From dfdfeff1b30e17a01926a05f455fbffac1e0ab9c Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Sun, 15 Sep 2024 23:20:03 +0800 Subject: [PATCH 01/32] Update ares_user_defconfig --- arch/arm64/configs/ares_user_defconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/configs/ares_user_defconfig b/arch/arm64/configs/ares_user_defconfig index 1ac66a59c4094..a16efe853d313 100644 --- a/arch/arm64/configs/ares_user_defconfig +++ b/arch/arm64/configs/ares_user_defconfig @@ -509,3 +509,8 @@ CONFIG_MTK_VOW_GVA_SUPPORT=n CONFIG_MTK_VOW_PCMCALLBACK_SUPPORT=n CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y CONFIG_MI_ESD_CHECK=y + +# KernelSU +CONFIG_KPROBES=y +CONFIG_HAVE_KPROBES=y +CONFIG_KPROBE_EVENTS=y From b227999f04645135a3958136efac4d08af065727 Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Sun, 15 Sep 2024 23:21:40 +0800 Subject: [PATCH 02/32] Update ares_user_defconfig --- arch/arm64/configs/ares_user_defconfig | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm64/configs/ares_user_defconfig b/arch/arm64/configs/ares_user_defconfig index a16efe853d313..686a4f1930be6 100644 --- a/arch/arm64/configs/ares_user_defconfig +++ b/arch/arm64/configs/ares_user_defconfig @@ -509,8 +509,12 @@ CONFIG_MTK_VOW_GVA_SUPPORT=n CONFIG_MTK_VOW_PCMCALLBACK_SUPPORT=n CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y CONFIG_MI_ESD_CHECK=y - -# KernelSU +# fixed CONFIG_KPROBES=y CONFIG_HAVE_KPROBES=y CONFIG_KPROBE_EVENTS=y +CONFIG_OVERLAY_FS=y +CONFIG_MODULES=y +CONFIG_MODULE_FORCE_LOAD=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y From 3675807f5ab80b148c937f96af33585f94bd2cba Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Sun, 15 Sep 2024 23:51:18 +0800 Subject: [PATCH 03/32] Add files via upload --- .../boot/dts/include/k6893v1_64/cust.dtsi | 577 ++++++++++++++++++ 1 file changed, 577 insertions(+) create mode 100644 arch/arm64/boot/dts/include/k6893v1_64/cust.dtsi diff --git a/arch/arm64/boot/dts/include/k6893v1_64/cust.dtsi b/arch/arm64/boot/dts/include/k6893v1_64/cust.dtsi new file mode 100644 index 0000000000000..28c20a0bdf903 --- /dev/null +++ b/arch/arm64/boot/dts/include/k6893v1_64/cust.dtsi @@ -0,0 +1,577 @@ +/* + * Generated by MTK SP DrvGen Version: 3.5.160809 for MT6893. + * 2021-10-15 06:06:19 + * Do Not Modify The File. + * Copyright Mediatek Inc. (c) 2016. +*/ + +/************************* + * ADC DTSI File +*************************/ + +&auxadc { + adc_channel@ { + compatible = "mediatek,adc_channel"; + mediatek,temperature0 = <0>; + mediatek,temperature1 = <1>; + mediatek,adc_fdd_rf_params_dynamic_custom_ch = <2>; + status = "okay"; + }; +}; +&md_auxadc { + io-channels = <&auxadc 2>; +}; + + +/************************* + * CLK_BUF DTSI File +*************************/ + +&pmic_clock_buffer_ctrl { + mediatek,clkbuf-quantity = <7>; + mediatek,clkbuf-config = <2 1 1 2 0 0 1>; + mediatek,clkbuf-output-impedance = <3 4 3 4 0 0 3>; + mediatek,clkbuf-controls-for-desense = <0 4 0 4 0 0 0>; + status = "okay"; +}; + + +/************************* + * I2C DTSI File +*************************/ + +&i2c0 { + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <400000>; + mediatek,use-open-drain; +}; + +&i2c1 { + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <400000>; + mediatek,use-open-drain; +}; + +&i2c2 { + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <400000>; + mediatek,use-push-pull; + camera_sub_two_mtk:camera_sub_two@7b { + compatible = "mediatek,camera_sub_two"; + reg = <0x7b>; + status = "okay"; + }; + + camera_main_mtk:camera_main@21 { + compatible = "mediatek,camera_main"; + reg = <0x21>; + status = "okay"; + }; + + camera_main_af_mtk:camera_main_af@19 { + compatible = "mediatek,camera_main_af"; + reg = <0x19>; + status = "okay"; + }; + +}; + +&i2c3 { + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <400000>; + mediatek,use-open-drain; +}; + +&i2c4 { + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <400000>; + mediatek,use-push-pull; + camera_main_two_mtk:camera_main_two@45 { + compatible = "mediatek,camera_main_two"; + reg = <0x45>; + status = "okay"; + }; + + camera_sub_mtk:camera_sub@21 { + compatible = "mediatek,camera_sub"; + reg = <0x21>; + status = "okay"; + }; + + camera_main_three_mtk:camera_main_three@10 { + compatible = "mediatek,camera_main_three"; + reg = <0x10>; + status = "okay"; + }; + +}; + +&i2c5 { + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <3400000>; + mediatek,use-push-pull; + subpmic_mtk:subpmic@34 { + compatible = "mediatek,subpmic"; + reg = <0x34>; + status = "okay"; + }; + + usb_type_c_mtk:usb_type_c@4e { + compatible = "mediatek,usb_type_c"; + reg = <0x4e>; + status = "okay"; + }; + + subpmic_pmic_mtk:subpmic_pmic@1a { + compatible = "mediatek,subpmic_pmic"; + reg = <0x1a>; + status = "okay"; + }; + + subpmic_ldo_mtk:subpmic_ldo@64 { + compatible = "mediatek,subpmic_ldo"; + reg = <0x64>; + status = "okay"; + }; + +}; + +&i2c6 { + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <400000>; + mediatek,use-push-pull; + i2c_lcd_bias_mtk:i2c_lcd_bias@3e { + compatible = "mediatek,i2c_lcd_bias"; + reg = <0x3e>; + status = "okay"; + }; + + dp_switch_mtk:dp_switch@50 { + compatible = "mediatek,dp_switch"; + reg = <0x50>; + status = "okay"; + }; + + ext_buck_vmddr_mtk:ext_buck_vmddr@61 { + compatible = "mediatek,ext_buck_vmddr"; + reg = <0x61>; + status = "okay"; + }; + +}; + +&i2c7 { + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <100000>; + mediatek,use-open-drain; +}; + +&i2c8 { + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <400000>; + mediatek,use-open-drain; +}; + +&i2c9 { + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <400000>; + mediatek,use-open-drain; + nfc_mtk:nfc@28 { + compatible = "mediatek,nfc"; + reg = <0x28>; + status = "okay"; + }; + +}; + + + +/************************* + * GPIO DTSI File +*************************/ + +&gpio_usage_mapping { + GPIO_SIM1_HOT_PLUG = <&pio 43 0>; + GPIO_SIM2_SCLK = <&pio 45 0>; + GPIO_SIM2_SRST = <&pio 46 0>; + GPIO_SIM2_SIO = <&pio 47 0>; + GPIO_SIM1_SIO = <&pio 48 0>; + GPIO_SIM1_SRST = <&pio 49 0>; + GPIO_SIM1_SCLK = <&pio 50 0>; + GPIO_FDD_BAND_SUPPORT_DETECT_1ST_PIN = <&pio 63 0>; + GPIO_FDD_BAND_SUPPORT_DETECT_2ND_PIN = <&pio 64 0>; + GPIO_FDD_BAND_SUPPORT_DETECT_3RD_PIN = <&pio 65 0>; + GPIO_FDD_BAND_SUPPORT_DETECT_4TH_PIN = <&pio 66 0>; +}; + +&gpio{ + gpio_init_default = <0 0 0 0 1 1 1>, + <1 0 0 0 1 0 1>, + <2 0 0 0 1 0 1>, + <3 0 0 0 1 0 1>, + <4 0 0 0 1 1 1>, + <5 0 0 0 0 0 1>, + <6 0 1 0 1 0 0>, + <7 0 0 0 0 0 1>, + <8 0 0 0 1 0 1>, + <9 0 0 0 1 0 1>, + <10 0 0 0 1 0 1>, + <11 0 0 0 1 0 0>, + <12 0 1 0 1 1 1>, + <13 0 1 0 1 1 1>, + <14 0 1 0 0 0 0>, + <15 0 0 0 0 0 0>, + <16 0 1 0 1 0 0>, + <17 1 0 0 1 0 0>, + <18 2 0 0 1 0 1>, + <19 0 1 0 1 0 1>, + <20 0 1 0 1 0 1>, + <21 0 0 0 1 1 1>, + <22 0 0 0 1 1 1>, + <23 0 0 0 1 1 1>, + <24 0 0 0 1 1 1>, + <25 0 0 0 1 1 1>, + <26 0 1 0 1 0 1>, + <27 0 1 1 1 0 1>, + <28 0 1 0 1 0 1>, + <29 0 1 0 1 0 1>, + <30 0 1 0 1 0 1>, + <31 0 0 0 1 1 1>, + <32 1 0 0 0 0 1>, + <33 1 0 0 0 0 1>, + <34 1 0 0 1 0 1>, + <35 1 0 0 0 0 1>, + <36 1 1 0 0 0 0>, + <37 1 1 0 0 0 0>, + <38 1 0 0 1 1 0>, + <39 1 1 0 1 0 0>, + <40 1 0 0 0 0 0>, + <41 1 0 0 1 0 0>, + <42 0 1 0 1 0 0>, + <43 1 0 0 1 1 1>, + <44 0 0 0 1 0 0>, + <45 1 0 0 0 0 1>, + <46 1 0 0 0 0 1>, + <47 1 0 0 1 1 1>, + <48 1 0 0 1 1 1>, + <49 1 0 0 0 0 1>, + <50 1 0 0 0 0 1>, + <51 0 1 0 1 0 1>, + <52 1 0 0 1 1 1>, + <53 1 0 0 1 1 1>, + <54 0 1 0 1 0 1>, + <55 1 0 0 1 0 1>, + <56 1 0 0 1 0 1>, + <57 1 0 0 1 0 0>, + <58 1 0 0 1 0 0>, + <59 1 0 0 1 0 1>, + <60 1 0 0 1 0 1>, + <61 1 0 0 1 0 0>, + <62 1 0 0 1 0 1>, + <63 0 0 0 1 0 0>, + <64 0 0 0 1 0 0>, + <65 0 0 0 1 0 0>, + <66 0 0 0 1 0 0>, + <67 1 0 0 1 0 0>, + <68 1 0 0 1 0 0>, + <69 1 0 0 1 0 0>, + <70 1 0 0 1 0 0>, + <71 1 0 0 1 0 0>, + <72 1 0 0 1 0 0>, + <73 1 0 0 1 0 0>, + <74 1 0 0 1 0 0>, + <75 1 0 0 1 0 0>, + <76 1 0 0 1 0 0>, + <77 1 0 0 1 0 0>, + <78 1 0 0 1 0 0>, + <79 1 0 0 1 0 0>, + <80 1 0 0 1 0 0>, + <81 1 0 0 1 0 0>, + <82 1 0 0 1 0 0>, + <83 1 0 0 1 0 0>, + <84 1 0 0 1 0 0>, + <85 1 0 0 1 0 0>, + <86 1 0 0 1 0 0>, + <87 1 0 0 1 0 0>, + <88 1 0 0 1 0 0>, + <89 1 0 0 0 0 1>, + <90 1 0 0 0 0 1>, + <92 1 0 0 1 1 0>, + <93 1 0 0 1 1 0>, + <94 0 0 0 0 0 0>, + <95 0 1 0 1 0 0>, + <96 7 0 0 1 0 0>, + <97 7 0 0 1 0 0>, + <98 7 0 0 1 0 0>, + <99 7 0 0 0 0 0>, + <100 7 0 0 1 0 0>, + <101 7 0 0 1 0 0>, + <102 7 0 0 1 0 0>, + <103 2 0 0 0 0 0>, + <104 2 0 0 1 0 0>, + <105 2 0 0 1 0 0>, + <106 2 0 0 1 0 0>, + <107 7 0 0 1 0 1>, + <108 7 0 0 1 0 0>, + <109 7 0 0 1 0 0>, + <110 0 1 0 1 0 0>, + <111 0 1 0 1 0 0>, + <112 0 1 0 1 0 0>, + <113 0 1 0 1 0 0>, + <114 2 0 0 1 0 0>, + <115 2 0 0 0 0 0>, + <116 2 0 0 0 0 0>, + <117 2 0 0 0 0 0>, + <118 2 0 0 1 1 1>, + <119 2 0 0 1 1 1>, + <120 1 0 0 1 1 1>, + <121 1 0 0 1 1 1>, + <122 1 0 0 1 1 1>, + <123 1 0 0 1 1 1>, + <124 1 0 0 1 1 1>, + <125 1 0 0 1 1 1>, + <126 5 0 0 1 1 1>, + <127 5 0 0 1 1 1>, + <128 0 1 0 1 0 1>, + <129 0 1 0 1 0 0>, + <130 0 1 0 1 0 0>, + <131 0 1 0 1 0 0>, + <132 1 0 0 1 0 0>, + <133 0 1 0 1 0 0>, + <134 0 1 0 1 0 0>, + <135 0 0 0 0 0 1>, + <136 1 0 0 0 0 0>, + <137 0 0 0 1 0 0>, + <138 0 1 0 1 0 0>, + <139 1 0 0 1 1 1>, + <140 1 0 0 1 1 1>, + <141 1 0 0 1 1 1>, + <142 1 0 0 1 1 1>, + <143 0 1 0 1 0 0>, + <144 0 1 0 1 0 0>, + <145 0 1 0 1 0 0>, + <146 0 1 0 1 0 0>, + <147 0 0 0 0 0 1>, + <148 0 1 0 1 0 0>, + <149 1 0 0 0 0 0>, + <150 1 0 0 0 0 0>, + <151 1 0 0 0 0 0>, + <152 0 0 0 1 0 0>, + <153 1 0 0 0 0 0>, + <154 1 0 0 1 1 0>, + <155 0 0 0 0 0 0>, + <156 1 1 0 0 0 0>, + <157 0 1 0 0 0 0>, + <158 1 0 0 1 0 0>, + <159 1 1 0 0 0 0>, + <160 1 0 0 1 1 1>, + <161 1 0 0 1 1 1>, + <162 0 1 0 1 0 1>, + <163 0 1 0 1 0 1>, + <164 0 0 0 1 0 1>, + <165 1 0 0 1 0 1>, + <166 1 0 0 1 0 1>, + <167 0 0 0 1 0 1>, + <168 6 0 0 1 1 1>, + <169 6 0 0 1 1 1>, + <170 6 0 0 1 1 1>, + <171 6 0 0 1 1 1>, + <172 0 0 0 1 0 0>, + <173 0 0 0 1 0 0>, + <174 0 0 0 1 0 0>, + <175 0 0 0 1 0 0>, + <176 0 0 0 1 0 0>, + <177 0 0 0 1 0 0>, + <178 0 0 0 1 0 0>, + <179 0 0 0 1 0 0>, + <180 0 0 0 1 0 0>, + <181 0 0 0 1 0 0>, + <182 0 0 0 1 0 0>, + <187 0 1 0 1 0 0>, + <189 0 1 0 1 0 1>, + <191 0 1 0 1 0 1>, + <192 0 1 0 1 0 1>, + <193 0 0 0 0 0 1>, + <195 1 0 0 0 0 0>, + <196 1 0 0 0 0 1>, + <197 1 0 0 0 0 1>, + <198 1 0 0 0 0 1>, + <199 1 0 0 1 0 1>, + <200 3 0 0 1 1 1>, + <201 3 0 0 1 1 1>, + <202 1 0 0 1 1 1>, + <203 1 0 0 1 1 1>, + <204 1 0 0 1 1 1>, + <205 1 0 0 1 1 1>, + <206 1 0 0 0 0 0>, + <207 1 0 0 0 0 0>, + <208 1 0 0 0 0 0>, + <209 1 0 0 1 0 0>, + <210 1 0 0 0 0 0>, + <211 1 0 0 0 0 0>, + <212 1 0 0 0 0 0>, + <213 1 0 0 1 0 0>, + <214 1 0 0 0 0 1>, + <215 1 0 0 0 0 1>, + <216 1 0 0 0 0 1>, + <217 1 0 0 0 0 1>, + <218 1 0 0 1 0 1>, + <219 1 0 0 1 0 1>, + <220 0 0 0 1 0 0>, + <221 0 0 0 1 0 0>, + <222 0 0 0 1 0 0>, + <223 0 0 0 1 0 0>, + <224 0 0 0 1 0 0>, + <225 0 0 0 1 0 0>, + <226 0 0 0 1 0 0>; +}; + + +/************************* + * EINT DTSI File +*************************/ + +#include +#include + +&mrdump_ext_rst { + interrupt-parent = <&pio>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW 0 0>; + deb-gpios = <&pio 0 0>; + debounce = <512000>; + status = "okay"; +}; + +&irq_nfc { + interrupt-parent = <&pio>; + interrupts = <7 IRQ_TYPE_LEVEL_HIGH 7 0>; + status = "okay"; +}; + +&touch { + interrupt-parent = <&pio>; + interrupts = <21 IRQ_TYPE_EDGE_FALLING 21 0>; + status = "okay"; +}; + +&swtp { + interrupt-parent = <&pio>; + interrupts = <22 IRQ_TYPE_LEVEL_HIGH 22 0>; + deb-gpios = <&pio 22 0>; + debounce = <512000>; + status = "okay"; +}; + +&subpmic_pmu_eint { + interrupt-parent = <&pio>; + interrupts = <24 IRQ_TYPE_EDGE_FALLING 24 0>; + status = "okay"; +}; + +&tcpc_pd { + interrupt-parent = <&pio>; + interrupts = <25 IRQ_TYPE_EDGE_FALLING 25 0>; + status = "okay"; +}; + +&smart_pa { + interrupt-parent = <&pio>; + interrupts = <31 IRQ_TYPE_LEVEL_LOW 31 0>; + status = "okay"; +}; + +&dsi_te { + interrupt-parent = <&pio>; + interrupts = <41 IRQ_TYPE_EDGE_RISING 41 1>; + status = "okay"; +}; + + + +/************************* + * MD1_EINT DTSI File +*************************/ + +&md1_sim1_hot_plug_eint { + compatible = "mediatek,md1_sim1_hot_plug_eint-eint"; + interrupts = <0 8>; + debounce = <0 10000>; + dedicated = <0 0>; + src_pin = <0 1>; + sockettype = <0 0>; + status = "okay"; +}; + + + +/************************* + * PMIC DTSI File +*************************/ + +&mt_pmic_vcamio_ldo_reg { + regulator-name = "vcamio"; + regulator-default-on = <1>; /* 0:skip, 1: off, 2:on */ + status = "okay"; +}; +&mt_pmic_vtp_ldo_reg { + regulator-name = "vtp"; + regulator-default-on = <1>; /* 0:skip, 1: off, 2:on */ + status = "okay"; +}; + +&kd_camera_hw1 { + vcamio-supply = <&mt_pmic_vcamio_ldo_reg>; + vcamio_sub-supply = <&mt_pmic_vcamio_ldo_reg>; + vcamio_main2-supply = <&mt_pmic_vcamio_ldo_reg>; + vcamaf-supply = <&mt_pmic_vcamio_ldo_reg>; + vcamaf_main2-supply = <&mt_pmic_vcamio_ldo_reg>; + status = "okay"; +}; + +&touch { + vtouch-supply = <&mt_pmic_vtp_ldo_reg>; + status = "okay"; +}; + + +/************************* + * POWER DTSI File +*************************/ + + + +/************************* + * KPD DTSI File +*************************/ + +&keypad { + mediatek,kpd-key-debounce = <1024>; + mediatek,kpd-sw-pwrkey = <116>; + mediatek,kpd-hw-pwrkey = <8>; + mediatek,kpd-sw-rstkey = <115>; + mediatek,kpd-hw-rstkey = <17>; + mediatek,kpd-use-extend-type = <0>; + /*HW Keycode [0~71] -> Linux Keycode*/ + mediatek,kpd-hw-map-num = <72>; + mediatek,kpd-hw-init-map = <114 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 >; + mediatek,kpd-pwrkey-eint-gpio = <0>; + mediatek,kpd-pwkey-gpio-din = <0>; + mediatek,kpd-hw-dl-key0 = <17>; + mediatek,kpd-hw-dl-key1 = <0>; + mediatek,kpd-hw-dl-key2 = <8>; + mediatek,kpd-hw-recovery-key = <17>; + mediatek,kpd-hw-factory-key = <0>; + status = "okay"; +}; + + From 613ca78530d3bb906b62da2f2a161bfd6ed9c326 Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Sun, 15 Sep 2024 23:55:51 +0800 Subject: [PATCH 04/32] Update Kconfig --- drivers/input/touchscreen/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 29752c3dde73b..172d7af2c0ab2 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -13,7 +13,6 @@ source "drivers/input/touchscreen/mediatek/Kconfig" if INPUT_TOUCHSCREEN -source "drivers/input/touchscreen/focaltech_spi/Kconfig" source "drivers/input/touchscreen/xiaomi/Kconfig" config TOUCHSCREEN_PROPERTIES def_tristate INPUT From c52cb5ad5cf5f11d3a5f716484b8430c38e7e2f9 Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Sun, 15 Sep 2024 23:57:32 +0800 Subject: [PATCH 05/32] Update Makefile --- drivers/input/touchscreen/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 65c430fb92a87..5a745514baaf0 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -105,7 +105,6 @@ obj-$(CONFIG_TOUCHSCREEN_ZET6223) += zet6223.o obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o -obj-$(CONFIG_TOUCHSCREEN_FOCALTECH) += focaltech_spi/ obj-$(CONFIG_TOUCHSCREEN_XIAOMI_TOUCHFEATURE) += xiaomi/ TOUCH_LISTS := $(subst ",,$(CONFIG_TOUCHSCREEN_MTK_TOUCH)) obj-n += $(foreach TOUCH,$(TOUCH_LISTS),$(TOUCH)/) From 0466081795b43bc863c1326a6db10a6b744582be Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 21:36:55 +0800 Subject: [PATCH 06/32] Add files via upload --- .../connectivity/bt/mt66xx/Android.mk | 11 + .../mediatek/connectivity/bt/mt66xx/README | 2 + .../connectivity/bt/mt66xx/connac2/Android.mk | 21 + .../bt/mt66xx/connac2/Android.mk_disable | 27 + .../connectivity/bt/mt66xx/connac2/Makefile | 107 + .../bt/mt66xx/connac2/Makefile.ce | 57 + .../bt/mt66xx/connac2/btmtk_btif.h | 522 ++ .../bt/mt66xx/connac2/btmtk_btif_main.c | 1471 ++++ .../bt/mt66xx/connac2/btmtk_char_dev.c | 595 ++ .../bt/mt66xx/connac2/btmtk_chip_if.h | 32 + .../bt/mt66xx/connac2/btmtk_config.h | 28 + .../bt/mt66xx/connac2/btmtk_dbg.c | 615 ++ .../bt/mt66xx/connac2/btmtk_define.h | 210 + .../bt/mt66xx/connac2/btmtk_drv.h | 235 + .../bt/mt66xx/connac2/btmtk_fw_log.c | 479 ++ .../bt/mt66xx/connac2/btmtk_irq.c | 381 + .../bt/mt66xx/connac2/btmtk_main.c | 879 ++ .../bt/mt66xx/connac2/btmtk_main.h | 120 + .../bt/mt66xx/connac2/btmtk_mt66xx.c | 1910 +++++ .../bt/mt66xx/connac2/btmtk_mt66xx_reg.h | 880 ++ .../bt/mt66xx/connac2/btmtk_mt76xx.c | 204 + .../bt/mt66xx/connac2/btmtk_queue.c | 478 ++ .../bt/mt66xx/connac2/btmtk_uart.h | 81 + .../bt/mt66xx/connac2/btmtk_uart_main.c | 344 + .../bt/mt66xx/connac2/init.bt_drv.rc | 4 + .../connectivity/bt/mt66xx/legacy/Android.mk | 21 + .../connectivity/bt/mt66xx/legacy/Makefile | 62 + .../connectivity/bt/mt66xx/legacy/bt.h | 138 + .../connectivity/bt/mt66xx/legacy/dbg_bt.c | 367 + .../connectivity/bt/mt66xx/legacy/fw_log_bt.c | 347 + .../bt/mt66xx/legacy/init.bt_drv.rc | 4 + .../bt/mt66xx/legacy/stp_chrdev_bt.c | 849 ++ .../connectivity/bt/mt76xx/sdio/Android.mk | 63 + .../connectivity/bt/mt76xx/sdio/Makefile | 20 + .../bt/mt76xx/sdio/btmtk_config.h | 71 + .../bt/mt76xx/sdio/btmtk_define.h | 190 + .../connectivity/bt/mt76xx/sdio/btmtk_drv.h | 218 + .../connectivity/bt/mt76xx/sdio/btmtk_main.c | 336 + .../connectivity/bt/mt76xx/sdio/btmtk_sdio.c | 7583 +++++++++++++++++ .../connectivity/bt/mt76xx/sdio/btmtk_sdio.h | 479 ++ .../bt/mt76xx/sdio/init.btmtksdio.rc | 3 + 41 files changed, 20444 insertions(+) create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/Android.mk create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/README create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/Android.mk create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/Android.mk_disable create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/Makefile create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/Makefile.ce create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_btif.h create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_btif_main.c create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_char_dev.c create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_chip_if.h create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_config.h create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_dbg.c create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_define.h create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_drv.h create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_fw_log.c create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_irq.c create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_main.c create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_main.h create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_mt66xx.c create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_mt66xx_reg.h create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_mt76xx.c create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_queue.c create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_uart.h create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_uart_main.c create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/init.bt_drv.rc create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/Android.mk create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/Makefile create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/bt.h create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/dbg_bt.c create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/fw_log_bt.c create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/init.bt_drv.rc create mode 100644 drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/stp_chrdev_bt.c create mode 100644 drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/Android.mk create mode 100644 drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/Makefile create mode 100644 drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/btmtk_config.h create mode 100644 drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/btmtk_define.h create mode 100644 drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/btmtk_drv.h create mode 100644 drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/btmtk_main.c create mode 100644 drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/btmtk_sdio.c create mode 100644 drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/btmtk_sdio.h create mode 100644 drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/init.btmtksdio.rc diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/Android.mk b/drivers/misc/mediatek/connectivity/bt/mt66xx/Android.mk new file mode 100644 index 0000000000000..0bc0966bf5754 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/Android.mk @@ -0,0 +1,11 @@ +ifeq ($(MTK_BT_SUPPORT), yes) +ifeq ($(filter MTK_MT76%, $(MTK_BT_CHIP)),) +$(info MTK_BT_CHIP=$(MTK_BT_CHIP)) + +ifeq ($(MTK_BT_CHIP), $(filter $(MTK_BT_CHIP), MTK_CONSYS_MT6885 MTK_CONSYS_MT6893)) + include $(call all-subdir-makefiles, connac2) +else + include $(call all-subdir-makefiles, legacy) +endif +endif +endif diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/README b/drivers/misc/mediatek/connectivity/bt/mt66xx/README new file mode 100644 index 0000000000000..cd9911263ec01 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/README @@ -0,0 +1,2 @@ +Bluetooth driver - kernel modules move out of kernel tree + diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/Android.mk b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/Android.mk new file mode 100644 index 0000000000000..d1f4c931e18f6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/Android.mk @@ -0,0 +1,21 @@ +LOCAL_PATH := $(call my-dir) + +ifneq (true,$(strip $(TARGET_NO_KERNEL))) +ifeq ($(MTK_BT_CHIP), $(filter $(MTK_BT_CHIP), MTK_CONSYS_MT6885 MTK_CONSYS_MT6893)) + +include $(CLEAR_VARS) +LOCAL_MODULE := bt_drv.ko +LOCAL_PROPRIETARY_MODULE := true +LOCAL_MODULE_OWNER := mtk + +LOCAL_INIT_RC := init.bt_drv.rc +LOCAL_SRC_FILES := $(patsubst $(LOCAL_PATH)/%,%,$(shell find $(LOCAL_PATH) -type f -name '*.[cho]')) Makefile +LOCAL_REQUIRED_MODULES := conninfra.ko + +include $(MTK_KERNEL_MODULE) + +BT_OPTS += _MTK_BT_CHIP=$(MTK_BT_CHIP) +BT_OPTS += _MTK_PLAT_MT6885_EMULATION=$(MTK_PLAT_MT6885_EMULATION) +$(linked_module): OPTS += $(BT_OPTS) +endif +endif diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/Android.mk_disable b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/Android.mk_disable new file mode 100644 index 0000000000000..7eed65afbe70a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/Android.mk_disable @@ -0,0 +1,27 @@ +LOCAL_PATH := $(call my-dir) + +ifneq (true,$(strip $(TARGET_NO_KERNEL))) + +include $(CLEAR_VARS) +LOCAL_MODULE := bt_drv.ko +LOCAL_PROPRIETARY_MODULE := true +LOCAL_MODULE_OWNER := mtk + +LOCAL_INIT_RC := init.bt_drv.rc +LOCAL_SRC_FILES := $(patsubst $(LOCAL_PATH)/%,%,$(shell find $(LOCAL_PATH) -type f -name '*.[cho]')) Makefile +LOCAL_REQUIRED_MODULES := conninfra.ko + +include $(MTK_KERNEL_MODULE) + +#### Copy Module.symvers from $(LOCAL_REQUIRED_MODULES) to this module ####### +#### For symbol link (when CONFIG_MODVERSIONS is defined) +CONN_INFRA_EXPORT_SYMBOL := $(subst $(LOCAL_MODULE),$(LOCAL_REQUIRED_MODULES),$(intermediates)/LINKED)/Module.symvers +$(CONN_INFRA_EXPORT_SYMBOL): $(subst $(LOCAL_MODULE),$(LOCAL_REQUIRED_MODULES),$(linked_module)) +BT_EXPORT_SYMBOL := $(intermediates)/LINKED/Module.symvers +$(BT_EXPORT_SYMBOL).in: $(intermediates)/LINKED/% : $(CONN_INFRA_EXPORT_SYMBOL) + $(copy-file-to-target) + cp $(CONN_INFRA_EXPORT_SYMBOL) $(BT_EXPORT_SYMBOL) + +$(linked_module): $(BT_EXPORT_SYMBOL).in + +endif diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/Makefile b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/Makefile new file mode 100644 index 0000000000000..4aed1179ec859 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/Makefile @@ -0,0 +1,107 @@ +MTK_PLATFORM := $(subst ",,$(CONFIG_MTK_PLATFORM)) +############################################################################### +# Bluetooth character device driver + +############################################################################### +# Necessary Check + +ifeq ($(AUTOCONF_H),) + $(error AUTOCONF_H is not defined) +endif + +$(warning connac20 bt driver: _MTK_BT_CHIP = $(_MTK_BT_CHIP)) +CONNAC20_CHIPID=$(subst MTK_CONSYS_MT,,$(_MTK_BT_CHIP)) +ccflags-y += -D CONNAC20_CHIPID=$(CONNAC20_CHIPID) +$(warning connac20 bt driver: CONNAC20_CHIPID = $(CONNAC20_CHIPID)) + +# only for sw-ready-go +ifeq ($(_MTK_BT_CHIP), MTK_CONSYS_MT6893) +ifneq ($(filter yes, $(_MTK_PLAT_MT6885_EMULATION)),) + $(warning connac20 bt driver: 6885 emulation is set!) + ccflags-y += -D CONNAC20_CHIPID=6885 +endif +endif + +ifndef TOP + TOP := $(srctree)/.. +endif + +USE_DEVICE_NODE := y +#CUSTOMER_FW_UPDATE := y + +ccflags-y += -imacros $(AUTOCONF_H) -DCHIP_IF_BTIF + +# Customized feature, load 1b fw bin +#ccflags-y += -D BT_CUS_FEATURE + +# Force build fail on modpost warning +KBUILD_MODPOST_FAIL_ON_WARNINGS := y +############################################################################### + +# --------------------------------------------------- +# Compile Options +# --------------------------------------------------- +ccflags-y += -D CREATE_NODE_DYNAMIC=1 + +ifeq ($(CUSTOMER_FW_UPDATE), y) +ccflags-y += -D CUSTOMER_FW_UPDATE=1 +else +ccflags-y += -D CUSTOMER_FW_UPDATE=0 +endif + +ifneq ($(CFG_BT_PM_QOS_CONTROL),) + $(warning set PM_QOS_CONTROL=1) + ccflags-y += -D PM_QOS_CONTROL=1 +else + ccflags-y += -D PM_QOS_CONTROL=0 +endif + +# --------------------------------------------------- +# Include Path +# --------------------------------------------------- +CONN_INFRA_SRC := $(TOP)/vendor/mediatek/kernel_modules/connectivity/conninfra +WMT_SRC := $(TOP)/vendor/mediatek/kernel_modules/connectivity/common +BTIF_SRC := $(srctree)/drivers/misc/mediatek/btif +ccflags-y += -I$(srctree)/drivers/misc/mediatek/connectivity/common +ccflags-y += -I$(CONN_INFRA_SRC)/include +ccflags-y += -I$(CONN_INFRA_SRC)/debug_utility/include +ccflags-y += -I$(CONN_INFRA_SRC)/debug_utility/ +ifneq ($(CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH),) +ccflags-y += -I$(WMT_SRC)/debug_utility +endif +ccflags-y += -I$(BTIF_SRC)/common/inc + +ccflags-y += -I$(src)/core/include +ccflags-y += -I$(src)/connsys/connac_2_0 + +ifeq ($(USE_DEVICE_NODE), y) +ccflags-y += -DUSE_DEVICE_NODE=1 +else +ccflags-y += -DUSE_DEVICE_NODE=0 +endif + +# --------------------------------------------------- +# Objects List +# --------------------------------------------------- +MODULE_NAME := bt_drv +obj-m += $(MODULE_NAME).o + +#PLAT_DIR := plat/$(MTK_PLATFORM) + +CORE_OBJS := btmtk_main.o btmtk_dbg.o btmtk_irq.o + +ifeq ($(USE_DEVICE_NODE), y) +CORE_OBJS += btmtk_char_dev.o btmtk_queue.o +endif + +CHIP_OBJS := btmtk_mt66xx.o +HIF_OBJS := btmtk_btif_main.o btmtk_fw_log.o + +#$(MODULE_NAME)-objs += bt_char_dev.o +#ifneq ($(CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH),) +#$(MODULE_NAME)-objs += fw_log_bt.o +#endif + +$(MODULE_NAME)-objs += $(CORE_OBJS) +$(MODULE_NAME)-objs += $(HIF_OBJS) +$(MODULE_NAME)-objs += $(CHIP_OBJS) diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/Makefile.ce b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/Makefile.ce new file mode 100644 index 0000000000000..55697b454615d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/Makefile.ce @@ -0,0 +1,57 @@ +CONFIG_MODULE_SIG=n +export KERNEL_SRC := /lib/modules/$(shell uname -r)/build + +#################### Configurations #################### +# For chip interface, driver supports "usb", "sdio", "uart" and "btif" +MTK_CHIP_IF := uart + +ifeq ($(MTK_CHIP_IF), sdio) + MOD_NAME = btmtksdio + CFILES := btmtk_sdio.c + ccflags-y += -DCHIP_IF_SDIO +else ifeq ($(MTK_CHIP_IF), usb) + MOD_NAME = btmtk_usb + CFILES := btmtkusb.c + ccflags-y += -DCHIP_IF_USB +else ifeq ($(MTK_CHIP_IF), uart) + MOD_NAME = btmtk_uart + CFILES := btmtk_uart_main.c btmtk_mt76xx.c + ccflags-y += -DCHIP_IF_UART +else + MOD_NAME = btmtkbtif + CFILES := btmtk_btif_main.c btmtk_mt66xx.c + ccflags-y += -DCHIP_IF_BTIF +endif + +CFILES += btmtk_main.c + +ccflags-y += -I$(src)/include/ -I$(src)/ + +$(MOD_NAME)-objs := $(CFILES:.c=.o) + +obj-m += $(MOD_NAME).o + + +#VPATH = /opt/toolchains/gcc-linaro-aarch64-linux-gnu-4.9-2014.09_linux +#UART_MOD_NAME = btmtk_uart +#UART_CFILES := \ +# btmtk_uart_main.c +#$(UART_MOD_NAME)-objs := $(UART_CFILES:.c=.o) +############################################################################### +# Common +############################################################################### +#obj-m := $(UART_MOD_NAME).o +all: + make -C $(KERNEL_SRC) M=$(PWD) modules +clean: + make -C $(KERNEL_SRC) M=$(PWD) clean +# Check coding style +# export IGNORE_CODING_STYLE_RULES := NEW_TYPEDEFS,LEADING_SPACE,CODE_INDENT,SUSPECT_CODE_INDENT +ccs: + ./util/checkpatch.pl --no-tree --show-types --max-line-length=120 --ignore $(IGNORE_CODING_STYLE_RULES) -f btmtk_main.c + ./util/checkpatch.pl --no-tree --show-types --max-line-length=120 --ignore $(IGNORE_CODING_STYLE_RULES) -f btmtk_sdio.c + ./util/checkpatch.pl --no-tree --show-types --max-line-length=120 --ignore $(IGNORE_CODING_STYLE_RULES) -f btmtk_sdio.h + ./util/checkpatch.pl --no-tree --show-types --max-line-length=120 --ignore $(IGNORE_CODING_STYLE_RULES) -f btmtk_config.h + ./util/checkpatch.pl --no-tree --show-types --max-line-length=120 --ignore $(IGNORE_CODING_STYLE_RULES) -f btmtk_define.h + ./util/checkpatch.pl --no-tree --show-types --max-line-length=120 --ignore $(IGNORE_CODING_STYLE_RULES) -f btmtk_drv.h + diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_btif.h b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_btif.h new file mode 100644 index 0000000000000..3b775027e19b9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_btif.h @@ -0,0 +1,522 @@ +/* + * Copyright (c) 2016,2017 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _BTMTK_BTIF_H_ +#define _BTMTK_BTIF_H_ + +#include +#include +#include +#include +#include +#include + +#include "conninfra.h" +#include "btmtk_define.h" + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* Preamble length for HCI Command: +** 2-bytes for opcode and 1 byte for length +*/ +#define HCI_CMD_PREAMBLE_SIZE 3 + +/* Preamble length for ACL Data: +** 2-byte for Handle and 2 byte for length +*/ +#define HCI_ACL_PREAMBLE_SIZE 4 + +/* Preamble length for SCO Data: +** 2-byte for Handle and 1 byte for length +*/ +#define HCI_SCO_PREAMBLE_SIZE 3 + +/* Preamble length for HCI Event: +** 1-byte for opcode and 1 byte for length +*/ +#define HCI_EVT_PREAMBLE_SIZE 2 + +#define HCI_CMD_HDR_LEN (HCI_CMD_PREAMBLE_SIZE + 1) +#define HCI_EVT_HDR_LEN (HCI_EVT_PREAMBLE_SIZE) + +/* WMT Event */ +#define WMT_EVT_OFFSET (HCI_EVT_HDR_LEN) +#define WMT_EVT_HDR_LEN (4) + +#define WAKE_LOCK_NAME_SIZE (16) + + +#define MT_BGF2AP_BTIF_WAKEUP_IRQ_ID 312 /* temp */ +#define MT_BGF2AP_SW_IRQ_ID 271 /* temp */ + +#define IRQ_NAME_SIZE (20) +#define MAX_STATE_MONITORS (2) +#define RING_BUFFER_SIZE (16384) + +#define MAX_DUMP_DATA_SIZE (20) +#define MAX_DUMP_QUEUE_SIZE (100) + +/* sleep parameter */ +#define USLEEP_1MS_L (1000) +#define USLEEP_1MS_H (1100) +#define USLEEP_5MS_L (5000) +#define USLEEP_5MS_H (5200) + +#undef SUPPORT_BT_THREAD +#define SUPPORT_BT_THREAD (1) +#define SUPPORT_COREDUMP (1) + +#define DRIVER_CMD_CHECK (1) + +typedef void (*BT_RX_EVENT_CB) (void); + +enum wmt_evt_result { + WMT_EVT_SUCCESS, + WMT_EVT_FAIL, + WMT_EVT_INVALID, + WMT_EVT_SKIP // normal packet, not for wmt cmd +}; + +typedef enum wmt_pkt_dir { + WMT_PKT_DIR_HOST_TO_CHIP = 1, /* command */ + WMT_PKT_DIR_CHIP_TO_HOST = 2 /* event */ +} WMT_PKT_DIR_T; + +typedef enum wmt_opcode { + WMT_OPCODE_FUNC_CTRL = 0x06, + WMT_OPCODE_RF_CAL = 0x14, + WMT_OPCODE_0XF0 = 0xF0, + WMT_OPCODE_MAX +} WMT_OPCODE_T; + +enum bt_irq_type { + BGF2AP_BTIF_WAKEUP_IRQ, + BGF2AP_SW_IRQ, + BGF2AP_IRQ_MAX +}; + +enum bt_state { + FUNC_OFF = 0, + TURNING_ON = 1, + PRE_ON_AFTER_CAL = 2, + FUNC_ON = 3, + RESET_START = 4, + RESET_END = 5 +}; + +struct bt_irq_ctrl { + uint32_t irq_num; + uint8_t name[IRQ_NAME_SIZE]; + u_int8_t active; + spinlock_t lock; + unsigned long flags; +}; + +struct btif_deepidle_ctrl { + struct semaphore sem; + struct workqueue_struct *task; + struct delayed_work work; + u_int8_t is_dpidle; +}; + +enum bt_reset_level { + RESET_LEVEL_NONE, + RESET_LEVEL_0_5, /* subsys reset */ + RESET_LEVEL_0, /* whole chip reset */ + RESET_LEVEL_MAX +}; + + +struct bt_wake_lock { + struct wakeup_source *ws; + uint8_t name[WAKE_LOCK_NAME_SIZE]; +#if (PM_QOS_CONTROL == 1) + struct pm_qos_request qos_req; +#endif +}; + +enum bt_psm_state { + PSM_ST_SLEEP, + PSM_ST_NORMAL_TR, + PSM_ST_MAX +}; + +struct bt_psm_ctrl { + enum bt_psm_state state; + u_int8_t sleep_flag; /* sleep notify */ + u_int8_t wakeup_flag; /* wakeup notify */ + struct completion comp; /* request completion */ + u_int8_t result; /* request result */ + struct bt_wake_lock wake_lock; + u_int8_t force_on; +}; + +enum bt_direction_type { + NONE, + TX, + RX +}; + +struct bt_dump_packet { + enum bt_direction_type direction_type; + u_int16_t data_length; + u_int8_t data[MAX_DUMP_DATA_SIZE]; + struct timespec kerneltime; + struct timeval time; +}; + +struct bt_dump_queue { + struct bt_dump_packet queue[MAX_DUMP_QUEUE_SIZE]; + int32_t index; + bool full; + spinlock_t lock; +}; + + +#define BT_BTIF_DUMP_OWN_CR 0x01 +#define BT_BTIF_DUMP_REG 0x02 +#define BT_BTIF_DUMP_LOG 0x04 +#define BT_BTIF_DUMP_DMA 0x08 +#define BT_BTIF_DUMP_ALL 0x0F + +struct sched_param { + int sched_priority; +}; + +struct bt_dbg_st { + bool rt_thd_enable; + bool trx_enable; + uint16_t trx_opcode; + struct completion trx_comp; + void(*trx_cb) (char *buf, int len); + uint8_t rx_buf_ctrl; +}; + +typedef void (*BT_STATE_CHANGE_CB) (enum bt_state state); + +struct wmt_pkt_param { + /* Extensible union */ + union { + struct { + uint8_t subsys; /* subsys type: + 00 - BT + 01 - FM (obsolete) + 02 - GPS (obsolete) + 03 - WIFI (obsolete) */ + uint8_t on; /* 00 - off, 01 - on */ + } func_ctrl_cmd; + + struct { + uint8_t status; + } func_ctrl_evt; + + struct { + uint8_t subop; /* sub operation: + 01 - calibration start (obsolete) + 02 - restore indication (obsolete) + 03 - backup */ + } rf_cal_cmd; + + struct { + uint8_t status; + uint8_t subop; + uint8_t start_addr[4]; /* start address of cal data, little endian */ + uint8_t data_len[2]; /* cal data length, little endian */ + uint8_t ready_addr[4]; /* ready bit address, little endian */ + } rf_cal_evt; + + uint8_t evt_buf[16]; + } u; +}; + +struct bt_rf_cal_data_backup { + uint32_t start_addr; /* calibration data start address on sysram */ + uint32_t ready_addr; /* ready bit address on sysram to mark calibration data is ready */ + uint8_t *p_cache_buf; /* buffer to cache the calibration data */ + uint16_t cache_len; /* cached data length */ +}; + +struct bt_ring_buffer_mgmt { + uint8_t buf[RING_BUFFER_SIZE]; + uint32_t write_idx; + uint32_t read_idx; + spinlock_t lock; +}; + +/* + * WMT Packet Format + * + * NOTICE: + * It is recommanded to define each field in bytes, otherwise we should consider the + * memory alignment by compiler and use __attribute__((__packed__)) if needed. + */ +struct wmt_pkt_hdr { + uint8_t dir; + uint8_t opcode; + uint8_t param_len[2]; /* 2 bytes length, little endian */ +}; + + +struct wmt_pkt { + struct wmt_pkt_hdr hdr; + struct wmt_pkt_param params; +}; + +struct bt_internal_cmd { + uint8_t waiting_event; + uint16_t pending_cmd_opcode; + uint8_t wmt_opcode; + struct completion comp; /* command completion */ + u_int8_t result; /* command result */ + struct wmt_pkt_param wmt_event_params; +}; + +#if (DRIVER_CMD_CHECK == 1) +struct bt_cmd_node { + uint16_t opcode; + struct bt_cmd_node *next; +}; + +struct bt_cmd_queue { + uint8_t size; + struct bt_cmd_node *head, *tail; + spinlock_t lock; +}; +#endif + +struct btmtk_dev { + struct hci_dev *hdev; + unsigned long hdev_flags; + + /* BT state machine */ + enum bt_state bt_state; + + /* Power state */ + struct bt_psm_ctrl psm; + + /* Reset relative */ + int32_t subsys_reset; + struct completion rst_comp; + enum bt_reset_level rst_level; + u_int8_t rst_count; + + u_int8_t do_recal; + enum bt_state bt_precal_state; + struct bt_rf_cal_data_backup cal_data; + + unsigned long tx_state; +#ifdef SUPPORT_BT_THREAD + /* thread */ + struct task_struct *tx_thread; + wait_queue_head_t tx_waitq; + + /* Tx quque */ + struct sk_buff_head tx_queue; +#endif + /* For rx queue */ + struct sk_buff *rx_skb; +#if (USE_DEVICE_NODE == 1) + struct bt_ring_buffer_mgmt rx_buffer; +#endif + u_int8_t rx_ind; /* RX indication from Firmware */ + u_int8_t bgf2ap_ind; /* FW log / reset indication */ + + /* context for current pending command */ + struct bt_internal_cmd internal_cmd; + /* For internal command (generated in driver) handling */ + u_int8_t event_intercept; + + /* event queue */ + struct sk_buff *evt_skb; + wait_queue_head_t p_wait_event_q; +#if (DRIVER_CMD_CHECK == 1) + /* command response queue */ + struct bt_cmd_queue cmd_queue; + uint8_t cmd_timeout_count; + bool cmd_timeout_check; +#endif + /* driver dump queue*/ + struct bt_dump_queue dump_queue; + /* cif info */ + struct platform_device *pdev; + + /* coredump handle */ + void *coredump_handle; + + /* state change callback */ + BT_STATE_CHANGE_CB state_change_cb[MAX_STATE_MONITORS]; + + /* call back to notify upper layer RX data is available */ + BT_RX_EVENT_CB rx_event_cb; + + /* sempaphore to control close */ + struct semaphore halt_sem; + struct semaphore internal_cmd_sem; + + /* blank status */ + int32_t blank_state; + + /* btif deep idle ctrl */ + struct btif_deepidle_ctrl btif_dpidle_ctrl; +}; + +#define BTMTK_GET_DEV(bdev) (&bdev->pdev->dev) + +/* IRQ APIs */ +int bt_request_irq(enum bt_irq_type irq_type); +void bt_enable_irq(enum bt_irq_type irq_type); +void bt_disable_irq(enum bt_irq_type irq_type); +void bt_free_irq(enum bt_irq_type irq_type); +void bt_trigger_reset(void); +int bt_chip_reset_flow(enum bt_reset_level rst_level, + enum consys_drv_type drv, + char *reason); + + +void bt_bgf2ap_irq_handler(void); +int32_t bgfsys_check_conninfra_ready(void); + + +/* external functions */ +int32_t btmtk_btif_open(void); +int32_t btmtk_btif_close(void); +int32_t btmtk_tx_thread(void * arg); +int32_t btmtk_cif_dispatch_event(struct hci_dev *hdev, struct sk_buff *skb); +void btmtk_cif_dump_fw_no_rsp(unsigned int flag); +void btmtk_cif_dump_rxd_backtrace(void); +void btmtk_reset_init(void); + +static void inline bt_notify_state(struct btmtk_dev *bdev) +{ + int32_t i = 0; + for(i = 0; i < MAX_STATE_MONITORS; i++) + if (bdev->state_change_cb[i]) + bdev->state_change_cb[i](bdev->bt_state); +} + +static inline void bt_wake_lock_init(struct bt_wake_lock *plock) +{ + if (plock) { + plock->ws = wakeup_source_register(NULL, plock->name); + if (!plock->ws) + BTMTK_ERR("ERROR NO MEM\n"); +#if (PM_QOS_CONTROL == 1) + else + pm_qos_add_request(&plock->qos_req, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE); +#endif + } +} + +static inline void bt_wake_lock_deinit(struct bt_wake_lock *plock) +{ + if (plock && plock->ws) { + wakeup_source_unregister(plock->ws); +#if (PM_QOS_CONTROL == 1) + pm_qos_remove_request(&plock->qos_req); +#endif + } +} + +static inline void bt_hold_wake_lock(struct bt_wake_lock *plock) +{ + if (plock && plock->ws) { + __pm_stay_awake(plock->ws); +#if (PM_QOS_CONTROL == 1) + pm_qos_update_request(&plock->qos_req, 1000); +#endif + } +} + +static inline void bt_hold_wake_lock_timeout(struct bt_wake_lock *plock, uint32_t ms) +{ + if (plock && plock->ws) { + __pm_wakeup_event(plock->ws, ms); +#if (PM_QOS_CONTROL == 1) + //pm_qos_update_request_timeout(&plock->qos_req, 1000, ms * 1000); +#endif + } +} + +static inline void bt_release_wake_lock(struct bt_wake_lock *plock) +{ + if (plock && plock->ws) { + __pm_relax(plock->ws); +#if (PM_QOS_CONTROL == 1) + pm_qos_update_request(&plock->qos_req, PM_QOS_DEFAULT_VALUE); +#endif + } +} + +static inline void bt_psm_init(struct bt_psm_ctrl *psm) +{ + init_completion(&psm->comp); + strncpy(psm->wake_lock.name, "bt_psm", 6); + psm->wake_lock.name[6] = '\0'; + bt_wake_lock_init(&psm->wake_lock); +} + +static inline void bt_psm_deinit(struct bt_psm_ctrl *psm) +{ + bt_wake_lock_deinit(&psm->wake_lock); +} + +/** + * Send cmd dispatch evt + */ +#define RETRY_TIMES 10 +#define HCI_EV_VENDOR 0xff + + +int btmtk_cif_send_calibration(struct hci_dev *hdev); + +int btmtk_cif_send_cmd(struct hci_dev *hdev, const uint8_t *cmd, + const int32_t cmd_len, int32_t retry, int32_t endpoint, uint64_t tx_state); + + +/** + * FW log init/deinit APIs + */ +int fw_log_bt_init(struct hci_dev *hdev); +void fw_log_bt_exit(void); + + +#if (USE_DEVICE_NODE == 1) +void rx_queue_initialize(void); +void rx_queue_destroy(void); + +uint8_t is_rx_queue_empty(void); +int32_t rx_skb_enqueue(struct sk_buff *skb); +void rx_dequeue(uint8_t *buffer, uint32_t size, uint32_t *plen); +void rx_queue_flush(void); +#endif + +#if (DRIVER_CMD_CHECK == 1) +void cmd_list_initialize(void); +bool cmd_list_check(uint16_t opcode); +bool cmd_list_remove(uint16_t opcode); +bool cmd_list_append (uint16_t opcode); +void cmd_list_destory(void); +bool cmd_list_isempty(void); + +bool cmd_workqueue_init(void); +void cmd_workqueue_exit(void); +void update_command_response_workqueue(void); +#endif + +void dump_queue_initialize(void); +void add_dump_packet(const uint8_t *buffer, const uint32_t length, enum bt_direction_type type); +void show_all_dump_packet(void); + +#endif diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_btif_main.c b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_btif_main.c new file mode 100644 index 0000000000000..8b99af3ad1e26 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_btif_main.c @@ -0,0 +1,1471 @@ +/* + * Copyright (c) 2016,2017 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "conninfra.h" +#include "mtk_btif_exp.h" +#include "connectivity_build_in_adapter.h" +#include "btmtk_config.h" +#include "btmtk_define.h" +#include "btmtk_main.h" +#include "btmtk_btif.h" +#include "btmtk_mt66xx_reg.h" + +#if SUPPORT_COREDUMP +#include "connsys_debug_utility.h" +#endif + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define LOG TRUE +#define MTKBT_BTIF_NAME "mtkbt_btif" +#define BTIF_OWNER_NAME "CONSYS_BT" + +#define LPCR_POLLING_RTY_LMT 4096 /* 16*n */ +#define LPCR_MASS_DUMP_LMT 4000 +#define BTIF_IDLE_WAIT_TIME 32 /* ms */ + +#define MAX_RESET_COUNT (3) +/******************************************************************************* +* 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 +******************************************************************************** +*/ +uint8_t *p_conn_infra_base_addr; +uint8_t *p_bgfsys_base_addr; +struct btmtk_dev *g_bdev; +static unsigned long g_btif_id; /* The user identifier to operate btif */ +struct task_struct *g_btif_rxd_thread; + +static struct platform_driver mtkbt_btif_driver = { + .driver = { + .name = MTKBT_BTIF_NAME, + .owner = THIS_MODULE, + }, + .probe = NULL, + .remove = NULL, +}; + +#if (USE_DEVICE_NODE == 0) +static struct platform_device *mtkbt_btif_device; +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/* bt_reg_init + * + * Remapping control registers + * + * Arguments: + * N/A + * + * Return Value: + * 0 if success, otherwise error code + * + */ +static int32_t bt_reg_init(void) +{ + int32_t ret = -1; + struct device_node *node = NULL; + struct consys_reg_base_addr *base_addr = NULL; + struct resource res; + int32_t flag, i = 0; + + node = of_find_compatible_node(NULL, NULL, "mediatek,bt"); + if (node) { + for (i = 0; i < CONSYS_BASE_ADDR_MAX; i++) { + base_addr = &bt_reg.reg_base_addr[i]; + + ret = of_address_to_resource(node, i, &res); + if (ret) { + BTMTK_ERR("Get Reg Index(%d) failed", i); + return -1; + } + + base_addr->phy_addr = res.start; + base_addr->vir_addr = + (unsigned long) of_iomap(node, i); + of_get_address(node, i, &(base_addr->size), &flag); + + BTMTK_DBG("Get Index(%d) phy(0x%zx) baseAddr=(0x%zx) size=(0x%zx)", + i, base_addr->phy_addr, base_addr->vir_addr, + base_addr->size); + } + + } else { + BTMTK_ERR("[%s] can't find CONSYS compatible node\n", __func__); + return -1; + } + return 0; +} + +/* bt_reg_deinit + * + * Release the memory of remapping address + * + * Arguments: + * N/A + * + * Return Value: + * N/A + * + */ +int32_t bt_reg_deinit(void) +{ + int i = 0; + + for (i = 0; i < CONSYS_BASE_ADDR_MAX; i++) { + if (bt_reg.reg_base_addr[i].vir_addr) { + iounmap((void __iomem*)bt_reg.reg_base_addr[i].vir_addr); + bt_reg.reg_base_addr[i].vir_addr = 0; + } + } + return 0; +} + +static struct notifier_block bt_fb_notifier; +static int btmtk_fb_notifier_callback(struct notifier_block + *self, unsigned long event, void *data) +{ + struct fb_event *evdata = data; + int32_t blank = 0; + int32_t val = 0; + + if ((event != FB_EVENT_BLANK)) + return 0; + + blank = *(int32_t *)evdata->data; + switch (blank) { + case FB_BLANK_UNBLANK: + case FB_BLANK_POWERDOWN: + if(g_bdev->bt_state == FUNC_ON) { + if (conninfra_reg_readable()) { + val = REG_READL(CON_REG_SPM_BASE_ADDR + 0x26C); + BTMTK_INFO("%s: HOST_MAILBOX_BT_ADDR[0x1806026C] read[0x%08x]", __func__, val); + } + + BTMTK_INFO("%s: blank state [%ld]->[%ld], and send cmd", __func__, g_bdev->blank_state, blank); + g_bdev->blank_state = blank; + btmtk_send_blank_status_cmd(g_bdev->hdev, blank); + } else { + BTMTK_INFO("%s: blank state [%ld]->[%ld]", __func__, g_bdev->blank_state, blank); + g_bdev->blank_state = blank; + } + break; + default: + break; + } + + return 0; +} + +static int btmtk_fb_notify_register(void) +{ + int32_t ret; + + bt_fb_notifier.notifier_call = btmtk_fb_notifier_callback; + + ret = fb_register_client(&bt_fb_notifier); + if (ret) + BTMTK_ERR("Register wlan_fb_notifier failed:%d\n", ret); + else + BTMTK_DBG("Register wlan_fb_notifier succeed\n"); + + return ret; +} + +static void btmtk_fb_notify_unregister(void) +{ + fb_unregister_client(&bt_fb_notifier); +} + +/* btmtk_cif_dump_fw_no_rsp + * + * Dump fw/driver own cr and btif cr if + * fw response timeout + * + * Arguments: + * + * + * Return Value: + * N/A + * + */ +void btmtk_cif_dump_fw_no_rsp(unsigned int flag) +{ + BTMTK_WARN("%s! [%u]", __func__, flag); + if (!g_btif_id) { + BTMTK_ERR("NULL BTIF ID reference!"); + } else { + if (flag & BT_BTIF_DUMP_OWN_CR) + bt_dump_cif_own_cr(); + + if (flag & BT_BTIF_DUMP_REG) + mtk_wcn_btif_dbg_ctrl(g_btif_id, BTIF_DUMP_BTIF_REG); + + if (flag & BT_BTIF_DUMP_LOG) + mtk_wcn_btif_dbg_ctrl(g_btif_id, BTIF_DUMP_LOG); + + if (flag & BT_BTIF_DUMP_DMA) + mtk_wcn_btif_dbg_ctrl(g_btif_id, BTIF_DUMP_DMA_VFIFO); + + } +} + + +void btmtk_cif_dump_rxd_backtrace(void) +{ + if (!g_btif_rxd_thread) + BTMTK_ERR("g_btif_rxd_thread == NULL"); + else + KERNEL_show_stack(g_btif_rxd_thread, NULL); +} + + +/* btmtk_cif_dump_btif_tx_no_rsp + * + * Dump btif cr if fw no response yet + * + * Arguments: + * N/A + * + * Return Value: + * N/A + * + */ +void btmtk_cif_dump_btif_tx_no_rsp(void) +{ + BTMTK_INFO("%s", __func__); + if (!g_btif_id) { + BTMTK_ERR("NULL BTIF ID reference!"); + } else { + mtk_wcn_btif_dbg_ctrl(g_btif_id, BTIF_DUMP_BTIF_IRQ); + } +} + +/* btmtk_cif_fw_own_clr() + * + * Ask FW to wakeup from sleep state, driver should invoke this function + * before communitcate with FW/HW + * + * Arguments: + * N/A + * + * Return Value: + * 0 if success, otherwise error code + */ +static int32_t btmtk_cif_fw_own_clr(void) +{ + uint32_t lpctl_cr; + int32_t retry = LPCR_POLLING_RTY_LMT; + + do { + /* assume wait interval 0.5ms each time, + * wait maximum total 7ms to query status + */ + if ((retry & 0xF) == 0) { /* retry % 16 == 0 */ + if (((retry < LPCR_POLLING_RTY_LMT && retry >= LPCR_MASS_DUMP_LMT) || (retry == 2048) || (retry == 32)) && + ((retry & 0x1F) == 0)) { + BTMTK_WARN("FW own clear failed in %d ms, retry[%d]", (LPCR_POLLING_RTY_LMT - retry) / 2, retry); + bt_dump_cif_own_cr(); + REG_WRITEL(BGF_LPCTL, BGF_HOST_CLR_FW_OWN_B); + BTMTK_WARN("FW own clear dump after write:"); + bt_dump_cif_own_cr(); + } else + REG_WRITEL(BGF_LPCTL, BGF_HOST_CLR_FW_OWN_B); + } + + lpctl_cr = REG_READL(BGF_LPCTL); + if (!(lpctl_cr & BGF_OWNER_STATE_SYNC_B)) { + REG_WRITEL(BGF_IRQ_STAT, BGF_IRQ_FW_OWN_CLR_B); + break; + } + + usleep_range(500, 550); + retry --; + } while (retry > 0); + + if (retry == 0) { + BTMTK_ERR("FW own clear (Wakeup) failed!"); + bt_dump_cif_own_cr(); + + /* dump cpupcr, 10 times with 1ms interval */ + bt_dump_cpupcr(10 , 5); + return -1; + } + + BTMTK_DBG("FW own clear (Wakeup) succeed"); + return 0; +} + +/* btmtk_cif_fw_own_set() + * + * Ask FW to sleep for power saving + * + * Arguments: + * N/A + * + * Return Value: + * 0 if success, otherwise error code + * + */ +static int32_t btmtk_cif_fw_own_set(void) +{ + uint32_t irqstat_cr; + int32_t retry = LPCR_POLLING_RTY_LMT; + + do { + if ((retry & 0xF) == 0) { /* retry % 16 == 0 */ + if (((retry < LPCR_POLLING_RTY_LMT && retry >= LPCR_MASS_DUMP_LMT) || (retry == 2048) || (retry == 32)) && + ((retry & 0x1F) == 0)) { + BTMTK_WARN("FW own set failed in %d ms, retry[%d]", (LPCR_POLLING_RTY_LMT - retry) / 2, retry); + bt_dump_cif_own_cr(); + REG_WRITEL(BGF_LPCTL, BGF_HOST_SET_FW_OWN_B); + BTMTK_WARN("FW own set dump after write:"); + bt_dump_cif_own_cr(); + } else + REG_WRITEL(BGF_LPCTL, BGF_HOST_SET_FW_OWN_B); + } + + /* + * As current H/W design, BGF_LPCTL.OWNER_STATE_SYNC bit will be automatically + * asserted by H/W once driver set FW own, not waiting for F/W's ack, + * which means F/W may still transmit data to host at that time. + * So we cannot check this bit for FW own done identity, use BGF_IRQ_FW_OWN_SET + * bit for instead, even on polling mode and the interrupt is masked. + * + * This is a work-around, H/W will change design on ECO. + */ + irqstat_cr = REG_READL(BGF_IRQ_STAT2); + if (irqstat_cr & BGF_IRQ_FW_OWN_SET_B) { + /* Write 1 to clear IRQ */ + REG_WRITEL(BGF_IRQ_STAT2, BGF_IRQ_FW_OWN_SET_B); + break; + } + + usleep_range(500, 550); + retry --; + } while (retry > 0); + + if (retry == 0) { + BTMTK_ERR("FW own set (Sleep) failed!"); + bt_dump_cif_own_cr(); + + /* dump cpupcr, 10 times with 1ms interval */ + bt_dump_cpupcr(10 , 5); + return -1; + } + + BTMTK_DBG("FW own set (Sleep) succeed"); + return 0; +} + +int bt_chip_reset_flow(enum bt_reset_level rst_level, + enum consys_drv_type drv, + char *reason) +{ + u_int8_t is_1st_reset = (g_bdev->rst_count == 0) ? TRUE : FALSE; + uint8_t retry = 15; + int32_t dump_property = 0; /* default = 0 */ + int32_t ret = 0; + + /* dump debug message */ + show_all_dump_packet(); + btmtk_cif_dump_fw_no_rsp(BT_BTIF_DUMP_ALL); + + g_bdev->rst_count++; + while (g_bdev->rst_level != RESET_LEVEL_NONE && retry > 0) { + msleep(200); + retry--; + } + + if (retry == 0) { + BTMTK_ERR("Unable to trigger pre_chip_rst due to unfinish previous reset"); + return -1; + } + + g_bdev->rst_level = rst_level; + + if (is_1st_reset) { + /* + * 1. Trigger BT PAD_EINT to force FW coredump, + * trigger coredump only if the first time reset + * (compare with the case of subsys reset fail) + */ + CLR_BIT(BGF_PAD_EINT, BIT(9)); + bt_enable_irq(BGF2AP_SW_IRQ); + + /* 2. Wait for IRQ */ + if (!wait_for_completion_timeout(&g_bdev->rst_comp, msecs_to_jiffies(2000))) { +#if SUPPORT_COREDUMP + dump_property = CONNSYS_DUMP_PROPERTY_NO_WAIT; +#endif + BTMTK_ERR("uanble to get reset IRQ in 2000ms"); + } + + /* 3. Reset PAD_INT CR */ + SET_BIT(BGF_PAD_EINT, BIT(9)); +#if SUPPORT_COREDUMP + /* 4. Do coredump, only do this while BT is on */ + down(&g_bdev->halt_sem); + if (g_bdev->bt_state == FUNC_ON) { + bt_dump_bgfsys_debug_cr(); + connsys_coredump_start(g_bdev->coredump_handle, dump_property, drv, reason); + } else + BTMTK_WARN("BT is not at on state, skip coredump: [%d]", + g_bdev->bt_state); + up(&g_bdev->halt_sem); +#endif + } + + /* Dump assert reason, only for subsys reset */ + if (rst_level == RESET_LEVEL_0_5) { + phys_addr_t emi_ap_phy_base; + uint8_t *dump_msg_addr; + uint8_t msg[256] = {0}; + + conninfra_get_phy_addr((uint32_t*)&emi_ap_phy_base, NULL); + emi_ap_phy_base &= 0xFFFFFFFF; + + dump_msg_addr = ioremap_nocache(emi_ap_phy_base + 0x3B000, 0x100); + if (dump_msg_addr) { + memcpy(msg, dump_msg_addr, 0xFF); + iounmap(dump_msg_addr); + msg[0xFF] = 0; + BTMTK_INFO("FW Coredump Msg: [%s]", msg); + } else { + BTMTK_ERR("uanble to remap dump msg addr"); + } + } + + /* directly return if following cases + * 1. BT is already off + * 2. another reset is already done whole procdure and back to normal + */ + if (g_bdev->bt_state == FUNC_OFF || g_bdev->rst_level == RESET_LEVEL_NONE) { + BTMTK_INFO("BT is already off or reset success, skip power off [%d, %d]", + g_bdev->bt_state, g_bdev->rst_level); + return 0; + } + + g_bdev->bt_state = RESET_START; + bt_notify_state(g_bdev); + + /* 5. Turn off BT */ + ret = g_bdev->hdev->close(g_bdev->hdev); +#if (USE_DEVICE_NODE == 0) + bt_report_hw_error(); +#endif + return ret; +} + + +/******************************************************************************* +* C A L L B A C K F U N C T I O N S +******************************************************************************** +*/ +/* bt_pre_chip_rst_handler() + * + * Pre-action of chip reset (before HW power off), driver should ask + * conninfra to do coredump and then turn off bt driver + * + * Arguments: + * N/A + * + * Return Value: + * 0 if success, otherwise error code + * + */ +static int bt_pre_chip_rst_handler(enum consys_drv_type drv, char *reason) +{ + // skip reset flow if bt is not on + if (g_bdev->bt_state == FUNC_OFF) + return 0; + else + return bt_chip_reset_flow(RESET_LEVEL_0, drv, reason); +} + +/* bt_post_chip_rst_handler() + * + * Post-action of chip reset (after HW power on), turn on BT + * + * Arguments: + * N/A + * + * Return Value: + * 0 if success, otherwise error code + * + */ +static int bt_post_chip_rst_handler(void) +{ + bt_notify_state(g_bdev); + return 0; +} + +/* bt_do_pre_power_on() + * + * Only set the flag to pre-calibration mode here + * + * Arguments: + * N/A + * + * Return Value: + * 0 always (for success) + * + */ +static int bt_do_pre_power_on(void) +{ + return btmtk_set_power_on(g_bdev->hdev, TRUE); +} + +/* bt_do_calibration() + * + * calibration flow is control by conninfra driver, driver should implement + * the function of calibration callback, here what driver do is send cmd to + * FW to get calibration data (BT calibration is done in BT func on) and + * backup the calibration data + * + * Arguments: + * N/A + * + * Return Value: + * 0 if success, otherwise error code + * + */ +static int32_t bt_do_calibration(void) +{ + int32_t ret = 0; + + if(g_bdev->bt_state != FUNC_ON) { + BTMTK_ERR("%s: bt is not on, skip calibration", __func__); + return CONNINFRA_CB_RET_CAL_FAIL_POWER_OFF; + } + + ret = btmtk_calibration_flow(g_bdev->hdev); + /* return -1 means driver unable to recv calibration event and reseting + * In such case, we don't have to turn off bt, it will be handled by + * reset thread */ + if (ret != -1 && g_bdev->bt_precal_state == FUNC_OFF) + btmtk_set_power_off(g_bdev->hdev, TRUE); + + if (ret == -1) { + BTMTK_ERR("%s: error return in recving calibration event, reset", __func__); + return CONNINFRA_CB_RET_CAL_FAIL_POWER_ON; + } else if (ret) { + BTMTK_ERR("%s: error return in sent calibration cmd", __func__); + return (g_bdev->bt_precal_state) ? CONNINFRA_CB_RET_CAL_FAIL_POWER_ON : + CONNINFRA_CB_RET_CAL_FAIL_POWER_OFF; + } else + return (g_bdev->bt_precal_state) ? CONNINFRA_CB_RET_CAL_PASS_POWER_ON : + CONNINFRA_CB_RET_CAL_PASS_POWER_OFF; + +} + +/* btmtk_send_thermal_query_cmd + * + * Send query thermal (a-die) command to FW + * + * Arguments: + * [IN] hdev - hci_device as control structure during BT life cycle + * + * Return Value: + * Thermal value + * + */ +static int32_t bt_query_thermal(void) +{ + uint8_t cmd[] = { 0x01, 0x91, 0xFD, 0x00 }; + struct bt_internal_cmd *p_inter_cmd = &g_bdev->internal_cmd; + struct wmt_pkt_param *evt = &p_inter_cmd->wmt_event_params; + uint8_t *evtbuf = NULL; + int32_t ret = 0; + int32_t thermal = 0; + /* To-Do, for event check */ + /* u8 event[] = { 0x04, 0x0E, 0x08, 0x01, 0x91, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00 }; */ + + BTMTK_INFO("[InternalCmd] %s", __func__); + down(&g_bdev->internal_cmd_sem); + g_bdev->event_intercept = TRUE; + + p_inter_cmd->waiting_event = 0xE4; + p_inter_cmd->pending_cmd_opcode = 0xFD91; + p_inter_cmd->wmt_opcode = WMT_OPCODE_RF_CAL; + p_inter_cmd->result = WMT_EVT_INVALID; + + ret = btmtk_main_send_cmd(g_bdev->hdev, cmd, sizeof(cmd), + BTMTKUART_TX_WAIT_VND_EVT); + + if (ret <= 0) { + BTMTK_ERR("Unable to send thermal cmd"); + return -1; + } + + if (p_inter_cmd->result == WMT_EVT_SUCCESS) { + evtbuf = &evt->u.evt_buf[6]; + thermal = evtbuf[3] << 24 | + evtbuf[2] << 16 | + evtbuf[1] << 8 | + evtbuf[0]; + } + + g_bdev->event_intercept = FALSE; + up(&g_bdev->internal_cmd_sem); + BTMTK_INFO("[InternalCmd] %s done, result = %s, thermal = %d", + __func__, _internal_evt_result(p_inter_cmd->result), thermal); + return thermal; +} + +/* sub_drv_ops_cb + * + * All callbacks needs by conninfra driver, 3 types of callback functions + * 1. Chip reset functions + * 2. Calibration functions + * 3. Thermal query functions (todo) + * + */ +static struct sub_drv_ops_cb bt_drv_cbs = +{ + .rst_cb.pre_whole_chip_rst = bt_pre_chip_rst_handler, + .rst_cb.post_whole_chip_rst = bt_post_chip_rst_handler, + .pre_cal_cb.pwr_on_cb = bt_do_pre_power_on, + .pre_cal_cb.do_cal_cb = bt_do_calibration, + .thermal_qry = bt_query_thermal, +}; + +/* bt_receive_data_cb + * + * Callback function register to BTIF while BTIF receiving data from FW + * + * Arguments: + * [IN] buf pointer to incoming data buffer + * [IN] count length of incoming data + * + * Return Value: + * 0 if success, otherwise error code + * + */ +static int32_t bt_receive_data_cb(uint8_t *buf, uint32_t count) +{ + BTMTK_DBG_RAW(buf, count, "%s, len = %d rx data: ", __func__, count); + add_dump_packet(buf, count, RX); + g_bdev->psm.sleep_flag = FALSE; + return btmtk_recv(g_bdev->hdev, buf, count); +} + +#if SUPPORT_COREDUMP +/* bt_coredump_cb + * + * coredump API to check bt cr status + * Access bgf bus won't hang, so checking conninfra bus + * + */ +static struct coredump_event_cb bt_coredump_cb = +{ + .reg_readable = conninfra_reg_readable, + .poll_cpupcr = bt_dump_cpupcr, +}; +#endif + + +/******************************************************************************* +* B T I F F U N C T I O N S +******************************************************************************** +*/ +#if SUPPORT_BT_THREAD +static void btmtk_btif_enter_deep_idle(struct work_struct *pwork) +{ + int32_t ret = 0; + struct btif_deepidle_ctrl *idle_ctrl = &g_bdev->btif_dpidle_ctrl; + + down(&idle_ctrl->sem); + BTMTK_DBG("%s idle = [%d]", __func__, idle_ctrl->is_dpidle); + if (idle_ctrl->is_dpidle) { + ret = mtk_wcn_btif_dpidle_ctrl(g_btif_id, BTIF_DPIDLE_ENABLE); + bt_release_wake_lock(&g_bdev->psm.wake_lock); + idle_ctrl->is_dpidle = (ret) ? FALSE : TRUE; + + if (ret) + BTMTK_ERR("BTIF enter dpidle failed(%d)", ret); + else + BTMTK_DBG("BTIF enter dpidle succeed"); + } else + BTMTK_DBG("Deep idle is set to false, skip this time"); + up(&idle_ctrl->sem); +} +#endif + +/* btmtk_btif_open + + * + * Called when line discipline changed to HCI_UART. + * + * Arguments: + * tty pointer to tty info structure + * Return Value: + * 0 if success, otherwise error code + */ +int32_t btmtk_btif_open(void) +{ + int32_t ret = 0; + struct btif_deepidle_ctrl *idle_ctrl = &g_bdev->btif_dpidle_ctrl; + + /* 1. Open BTIF */ + ret = mtk_wcn_btif_open(BTIF_OWNER_NAME, &g_btif_id); + if (ret) { + BTMTK_ERR("BT open BTIF failed(%d)", ret); + return -1; + } + +#if SUPPORT_BT_THREAD + idle_ctrl->is_dpidle = FALSE; + idle_ctrl->task = create_singlethread_workqueue("dpidle_task"); + if (!idle_ctrl->task){ + BTMTK_ERR("fail to idle_ctrl->task "); + return -1; + } + INIT_DELAYED_WORK(&idle_ctrl->work, btmtk_btif_enter_deep_idle); +#endif + + /* 2. Register rx callback */ + ret = mtk_wcn_btif_rx_cb_register(g_btif_id, (MTK_WCN_BTIF_RX_CB)bt_receive_data_cb); + if (ret) { + BTMTK_ERR("Register rx cb to BTIF failed(%d)", ret); + mtk_wcn_btif_close(g_btif_id); + return -1; + } + + g_btif_rxd_thread = mtk_btif_exp_rx_thread_get(g_btif_id); + +#if SUPPORT_BT_THREAD + /* 3. Enter deeple idle */ + ret = mtk_wcn_btif_dpidle_ctrl(g_btif_id, TRUE); + if (ret) { + BTMTK_ERR("BTIF enter dpidle failed(%d)", ret); + mtk_wcn_btif_close(g_btif_id); + return -1; + } +#endif + + BTMTK_DBG("BT open BTIF OK"); + return 0; +} + +/* btmtk_btif_close() + * + * Close btif + * + * Arguments: + * N/A + * + * Return Value: + * 0 if success, otherwise error code + */ +int32_t btmtk_btif_close() +{ + int32_t ret = 0; + + if (!g_btif_id) { + BTMTK_ERR("NULL BTIF ID reference!"); + return 0; + } + +#if SUPPORT_BT_THREAD + if(&g_bdev->btif_dpidle_ctrl.task != NULL) { + cancel_delayed_work(&g_bdev->btif_dpidle_ctrl.work); + flush_workqueue(g_bdev->btif_dpidle_ctrl.task); + down(&g_bdev->btif_dpidle_ctrl.sem); + destroy_workqueue(g_bdev->btif_dpidle_ctrl.task); + up(&g_bdev->btif_dpidle_ctrl.sem); + g_bdev->btif_dpidle_ctrl.task = NULL; + } +#endif + + ret = mtk_wcn_btif_close(g_btif_id); + g_btif_id = 0; + bt_release_wake_lock(&g_bdev->psm.wake_lock); + + if (ret) { + BTMTK_ERR("BT close BTIF failed(%d)", ret); + return -1; + } + BTMTK_DBG("BT close BTIF OK"); + return 0; + +} + +#if SUPPORT_BT_THREAD +/* btmtk_btif_dpidle_ctrl + * + * + * Ask btif to wakeup / sleep + * + * Arguments: + * enable 0 to wakeup BTIF, sleep otherwise + * + * Return Value: + * 0 if success, otherwise error code + */ +static int32_t btmtk_btif_dpidle_ctrl(u_int8_t enable) +{ + int32_t ret = 0; + struct btif_deepidle_ctrl *idle_ctrl = &g_bdev->btif_dpidle_ctrl; + down(&idle_ctrl->sem); + + if (!g_btif_id) { + BTMTK_ERR("NULL BTIF ID reference!"); + return -1; + } + + if(idle_ctrl->task != NULL) { + BTMTK_DBG("%s enable = %d", __func__, enable); + /* 1. Remove active timer, and remove a unschedule timer does no harm */ + cancel_delayed_work(&idle_ctrl->work); + + /* 2. Check enable or disable */ + if (!enable) { + /* disable deep idle, call BTIF api directly */ + bt_hold_wake_lock(&g_bdev->psm.wake_lock); + ret = mtk_wcn_btif_dpidle_ctrl(g_btif_id, BTIF_DPIDLE_DISABLE); + idle_ctrl->is_dpidle = (ret) ? TRUE : FALSE; + + if (ret) + BTMTK_ERR("BTIF exit dpidle failed(%d)", ret); + else + BTMTK_DBG("BTIF exit dpidle succeed"); + } else { + BTMTK_DBG("create timer for enable deep idle"); + idle_ctrl->is_dpidle = TRUE; + /* enable deep idle, schedule a timer */ + queue_delayed_work(idle_ctrl->task, &idle_ctrl->work, + (BTIF_IDLE_WAIT_TIME * HZ) >> 10); + } + } else { + BTMTK_INFO("idle_ctrl->task already cancelled!"); + } + + up(&idle_ctrl->sem); + return ret; +} +#endif + +/* btmtk_btif_probe + * + * Probe function of BT driver with BTIF HAL, initialize variable after + * driver installed + * + * Arguments: + * [IN] pdev platform device pointer after driver installed + * + * Return Value: + * 0 if success, otherwise error code + */ +static int btmtk_btif_probe(struct platform_device *pdev) +{ + /* 1. allocate global context data */ + if (g_bdev == NULL) { + g_bdev = kzalloc(sizeof(struct btmtk_dev), GFP_KERNEL); + if (!g_bdev) { + BTMTK_ERR("%s: alloc memory fail (g_data)", __func__); + return -1; + } + } + + g_bdev->pdev = pdev; + + if (bt_reg_init()) { + BTMTK_ERR("%s: Error allocating memory remap"); + return -1; + } + + /* 2. Init HCI device */ + btmtk_allocate_hci_device(g_bdev, HCI_UART); + + /* 3. Init power manager */ + bt_psm_init(&g_bdev->psm); + + /* 4. Init reset completion */ + init_completion(&g_bdev->rst_comp); + + /* 5. Init fw log */ + fw_log_bt_init(g_bdev->hdev); + + /* 6. Init semaphore */ + sema_init(&g_bdev->halt_sem, 1); + sema_init(&g_bdev->internal_cmd_sem, 1); + sema_init(&g_bdev->btif_dpidle_ctrl.sem, 1); + +#if SUPPORT_COREDUMP + /* 7. Init coredump */ + g_bdev->coredump_handle = connsys_coredump_init(CONN_DEBUG_TYPE_BT, &bt_coredump_cb); +#endif + + /* 8. Register screen on/off notify callback */ + g_bdev->blank_state = FB_BLANK_UNBLANK; + btmtk_fb_notify_register(); + + /* Finally register callbacks to conninfra driver */ + conninfra_sub_drv_ops_register(CONNDRV_TYPE_BT, &bt_drv_cbs); + + BTMTK_INFO("%s: Done", __func__); + return 0; +} + +/* btmtk_btif_remove + * + * Remove function of BT driver with BTIF HAL, de-initialize variable after + * driver being removed + * + * Arguments: + * [IN] pdev platform device pointer + * + * Return Value: + * 0 if success, otherwise error code + */ +static int btmtk_btif_remove(struct platform_device *pdev) +{ + conninfra_sub_drv_ops_unregister(CONNDRV_TYPE_BT); + + btmtk_fb_notify_unregister(); + + fw_log_bt_exit(); + + bt_psm_deinit(&g_bdev->psm); +#if (USE_DEVICE_NODE == 0) + btmtk_free_hci_device(g_bdev, HCI_UART); +#endif +#if SUPPORT_COREDUMP + if (!g_bdev->coredump_handle) + connsys_coredump_deinit(g_bdev->coredump_handle); +#endif + + bt_reg_deinit(); + kfree(g_bdev); + return 0; +} + +/* btmtk_cif_register + * + * BT driver with BTIF hal has its own device, this API should be invoked + * by BT main driver when installed + * + * Arguments: + * N/A + * + * Return Value: + * 0 if success, otherwise error code + */ +int btmtk_cif_register(void) +{ + int ret = -1; + + mtkbt_btif_driver.probe = btmtk_btif_probe; + mtkbt_btif_driver.remove = btmtk_btif_remove; + +#if (USE_DEVICE_NODE == 1) + ret = btmtk_btif_probe(NULL); + rx_queue_initialize(); +#else + ret = platform_driver_register(&mtkbt_btif_driver); + BTMTK_INFO("platform_driver_register ret = %d", ret); + + mtkbt_btif_device = platform_device_alloc(MTKBT_BTIF_NAME, 0); + if (mtkbt_btif_device == NULL) { + platform_driver_unregister(&mtkbt_btif_driver); + BTMTK_ERR("platform_device_alloc device fail"); + return -1; + } + ret = platform_device_add(mtkbt_btif_device); + if (ret) { + platform_driver_unregister(&mtkbt_btif_driver); + BTMTK_ERR("platform_device_add fail"); + + return -1; + } +#endif + BTMTK_INFO("%s: Done", __func__); + return 0; +} + +/* btmtk_cif_register + * + * BT driver with BTIF hal has its own device, this API should be invoked + * by BT main driver when removed + * + * Arguments: + * N/A + * + * Return Value: + * 0 + */ +int btmtk_cif_deregister(void) +{ + btmtk_btif_close(); +#if (USE_DEVICE_NODE == 1) + rx_queue_destroy(); +#else + platform_driver_unregister(&mtkbt_btif_driver); + platform_device_unregister(mtkbt_btif_device); +#endif + + return 0; +} + +/* btmtk_cif_send_cmd + * + * Public API of BT TX + * + * Arguments: + * [IN] hdev - hci_device as control structure during BT life cycle + * [IN] cmd - sending data buffer + * [IN] cmd_len - data length + * [IN] retry_limit - retry count + * [IN] endpoint - NOT USE in BTIF driver (ignore) + * [IN] tx_state - NOT USE in BTIF driver (ignore) + * + * Return Value: + * write length of TX + */ +int32_t btmtk_cif_send_cmd(struct hci_dev *hdev, const uint8_t *cmd, + const int32_t cmd_len, int32_t retry_limit, int32_t endpoint, uint64_t tx_state) +{ + int32_t ret = -1; + uint32_t wr_count = 0; + int32_t tx_len = cmd_len; + int32_t retry = 0; + struct btmtk_dev *bdev = hci_get_drvdata(hdev); + + BTMTK_DBG_RAW(cmd, cmd_len, "%s, len = %d, send cmd: ", __func__, cmd_len); + + if (!g_btif_id) { + BTMTK_ERR("NULL BTIF ID reference!"); + return -1; + } + + add_dump_packet(cmd, cmd_len, TX); + +#if (DRIVER_CMD_CHECK == 1) + // To do: need to check if list_append will affect throughput + if (cmd[0] == 0x01) { + if ((cmd[1] == 0x5D && cmd[2] == 0xFC) || + (cmd[1] == 0x6F && cmd[2] == 0xFC) || + bdev->cmd_timeout_check == FALSE ) { + /* Skip these cmd: + fw will not return response, or response with other format */ + } else { + u16 cmd_opcode = (cmd[1] << 8) | cmd[2]; + BTMTK_DBG("%s add opcode %4X in cmd queue", __func__,cmd_opcode); + cmd_list_append(cmd_opcode); + update_command_response_workqueue(); + } + } +#endif + + while (tx_len > 0 && retry < retry_limit) { + if (retry++ > 0) + usleep_range(USLEEP_5MS_L, USLEEP_5MS_H); + + ret = mtk_wcn_btif_write(g_btif_id, cmd, tx_len); + if (ret < 0) { + BTMTK_ERR("BTIF write failed(%d) on retry(%d)", ret, retry-1); + return -1; + } + + tx_len -= ret; + wr_count += ret; + cmd += ret; + } + return ret; +} + +/* _check_wmt_evt_over_hci + * + * Check incoming event (RX data) if it's a WMT(vendor) event + * (won't send to stack) + * + * Arguments: + * [IN] buffer - event buffer + * [IN] len - event length + * [IN] expected_op - OPCODE that driver is waiting for (calle assigned) + * [IN] p_evt_params - event parameter + * + * Return Value: + * return check + * WMT_EVT_SUCCESS - get expected event + * WMT_EVT_FAIL - otherwise + */ +static int32_t _check_wmt_evt_over_hci( + uint8_t *buffer, + uint16_t len, + uint8_t expected_op, + struct wmt_pkt_param *p_evt_params) +{ + struct wmt_pkt *p_wmt_evt; + uint8_t opcode, sub_opcode; + uint8_t status = 0xFF; /* reserved value for check error */ + uint16_t param_len = 0; + + /* Sanity check */ + if (len < (HCI_EVT_HDR_LEN + WMT_EVT_HDR_LEN)) { + BTMTK_ERR("Incomplete packet len %d for WMT event!", len); + goto check_error; + } + + p_wmt_evt = (struct wmt_pkt *)&buffer[WMT_EVT_OFFSET]; + if (p_wmt_evt->hdr.dir != WMT_PKT_DIR_CHIP_TO_HOST) { + BTMTK_ERR("WMT direction %x error!", p_wmt_evt->hdr.dir); + goto check_error; + } + + opcode = p_wmt_evt->hdr.opcode; + if (opcode != expected_op) { + BTMTK_ERR("WMT OpCode is unexpected! opcode[0x%02X], expect[0x%02X]", opcode, expected_op); + goto check_error; + } + + param_len = (p_wmt_evt->hdr.param_len[1] << 8) | (p_wmt_evt->hdr.param_len[0]); + /* Sanity check */ + if (len < (HCI_EVT_HDR_LEN + WMT_EVT_HDR_LEN + param_len)) { + BTMTK_ERR("Incomplete packet len %d for WMT event!", len); + goto check_error; + } + + switch (opcode) { + case WMT_OPCODE_FUNC_CTRL: + if (param_len != sizeof(p_wmt_evt->params.u.func_ctrl_evt)) { + BTMTK_ERR("Unexpected event param len %d for WMT OpCode 0x%x!", + param_len, opcode); + break; + } + status = p_wmt_evt->params.u.func_ctrl_evt.status; + break; + + case WMT_OPCODE_RF_CAL: + sub_opcode = p_wmt_evt->params.u.rf_cal_evt.subop; + + if (sub_opcode != 0x03) { + BTMTK_ERR("Unexpected subop 0x%x for WMT OpCode 0x%x!", + sub_opcode, opcode); + break; + } + + if (param_len != sizeof(p_wmt_evt->params.u.rf_cal_evt)) { + BTMTK_ERR("Unexpected event param len %d for WMT OpCode 0x%x!", + param_len, opcode); + break; + } + status = p_wmt_evt->params.u.rf_cal_evt.status; + break; + case WMT_OPCODE_0XF0: + status = 0x00; // todo: need more check? + break; + default: + BTMTK_ERR("Unknown WMT OpCode 0x%x!", opcode); + break; + } + + if (status != 0xFF) { + memcpy(p_evt_params, &p_wmt_evt->params, param_len); + return (status == 0) ? WMT_EVT_SUCCESS : WMT_EVT_FAIL; + } + +check_error: + BTMTK_DBG_RAW(buffer, len, "Dump data: "); + return WMT_EVT_INVALID; +} + +/* btmtk_cif_dispatch_event + * + * Handler of vendor event + * + * Arguments: + * [IN] hdev - hci_device as control structure during BT life cycle + * [IN] skb - packet that carries vendor event + * + * Return Value: + * return check - 0 for checking success, -1 otherwise + * + */ +int32_t btmtk_cif_dispatch_event(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct btmtk_dev *bdev = hci_get_drvdata(hdev); + struct bt_internal_cmd *p_inter_cmd = &bdev->internal_cmd; + uint8_t event_code = skb->data[0]; + + /* WMT event */ + BTMTK_DBG("%s: event code=[0x%02x], length = %d", __func__, event_code, skb->len); + if (event_code == 0xE4) { + p_inter_cmd->result = _check_wmt_evt_over_hci(skb->data, + skb->len, + p_inter_cmd->wmt_opcode, + &p_inter_cmd->wmt_event_params); + + //p_inter_cmd->result = (ret == WMT_EVT_SUCCESS) ? 1: 0; + } else if(event_code == 0x0E && skb->len == 10 && + skb->data[3] == 0x91 && skb->data[4] == 0xFD) { + /* Sepcial case for thermal event, currently FW thermal event + * is not a typical WMT event, we have to do it separately + */ + memcpy((void*)&p_inter_cmd->wmt_event_params.u, skb->data, skb->len); + p_inter_cmd->result = WMT_EVT_SUCCESS; + } else { + /* Not WMT event */ + p_inter_cmd->result = WMT_EVT_SKIP; + } + + //return (p_inter_cmd->result == 1) ? 0 : -1; + return p_inter_cmd->result; +} + +#if SUPPORT_BT_THREAD +/* bt_tx_wait_for_msg + * + * Check needing action of current bt status to wake up bt thread + * + * Arguments: + * [IN] bdev - bt driver control strcuture + * + * Return Value: + * return check - 1 for waking up bt thread, 0 otherwise + * + */ +static u_int8_t bt_tx_wait_for_msg(struct btmtk_dev *bdev) +{ + /* Ignore other cases for reset situation, and wait for close */ + if (bdev->bt_state == RESET_START) + return kthread_should_stop(); + else { + BTMTK_DBG("skb [%d], rx_ind [%d], bgf2ap_ind [%d], sleep_flag [%d], wakeup_flag [%d], force_on [%d]", + skb_queue_empty(&bdev->tx_queue), bdev->rx_ind, + bdev->bgf2ap_ind, bdev->psm.sleep_flag, + bdev->psm.wakeup_flag, + bdev->psm.force_on); + return (!skb_queue_empty(&bdev->tx_queue) + || bdev->rx_ind + || bdev->bgf2ap_ind + || (!bdev->psm.force_on && bdev->psm.sleep_flag) // only check sleep_flag if force_on is FALSE + || bdev->psm.wakeup_flag + || kthread_should_stop()); + } +} + +/* btmtk_tx_thread + * + * Internal bt thread handles driver's TX / wakeup / sleep flow + * + * Arguments: + * [IN] arg + * + * Return Value: + * N/A + * + */ +int32_t btmtk_tx_thread(void * arg) +{ + struct btmtk_dev *bdev = (struct btmtk_dev *)arg; + struct bt_psm_ctrl *psm = &bdev->psm; + int32_t sleep_ret = 0, wakeup_ret = 0, ret, ii; + struct sk_buff *skb; + int skb_len, btif_pending_data; + char state_tag[20] = ""; + + BTMTK_INFO("btmtk_tx_thread start running..."); + do { + BTMTK_DBG("entering wait_event_interruptible"); + wait_event_interruptible(bdev->tx_waitq, bt_tx_wait_for_msg(bdev)); + BTMTK_DBG("btmtk_tx_thread wakeup"); + if (kthread_should_stop()) { + BTMTK_INFO("btmtk_tx_thread should stop now..."); + if (psm->state == PSM_ST_NORMAL_TR) + bt_release_wake_lock(&psm->wake_lock); + break; + } + + /* handling SW IRQ */ + if(bdev->bgf2ap_ind) { + bt_bgf2ap_irq_handler(); + /* reset bgf2ap_ind flag move into bt_bgf2ap_irq_handler */ + continue; + } + + switch (psm->state) { + case PSM_ST_SLEEP: + if (psm->sleep_flag) { + psm->sleep_flag = FALSE; + complete(&psm->comp); + psm->result = sleep_ret; + continue; + } + /* + * TX queue has pending data to send, + * or F/W pull interrupt to indicate there's data to host, + * or there's a explicit wakeup request. + * + * All need to execute the Wakeup procedure. + */ + btmtk_btif_dpidle_ctrl(FALSE); + + bt_disable_irq(BGF2AP_BTIF_WAKEUP_IRQ); + wakeup_ret = btmtk_cif_fw_own_clr(); + if (wakeup_ret) { + /* + * Special case handling: + * if FW is asserted, FW OWN clr must fail, + * so we can assume that FW is asserted from driver view + * and trigger reset directly + */ + bt_enable_irq(BGF2AP_BTIF_WAKEUP_IRQ); + btmtk_btif_dpidle_ctrl(TRUE); + /* check current bt_state to prevent from conflict + * resetting b/w subsys reset & whole chip reset + */ + if (bdev->bt_state == FUNC_ON) { + BTMTK_ERR("(PSM_ST_SLEEP) FATAL: btmtk_cif_fw_own_clr error!! going to reset"); + bt_trigger_reset(); + } else + BTMTK_WARN("(PSM_ST_SLEEP) bt_state [%d] is not FUNC_ON, skip reset", bdev->bt_state); + break; + } else { + /* BGFSYS is awake and ready for data transmission */ + psm->state = PSM_ST_NORMAL_TR; + } + break; + + case PSM_ST_NORMAL_TR: + if (psm->wakeup_flag) { + psm->wakeup_flag = FALSE; + complete(&psm->comp); + psm->result = wakeup_ret; + } + + if (bdev->rx_ind) { + BTMTK_DBG("wakeup by BTIF_WAKEUP_IRQ"); + /* Just reset the flag, F/W will send data to host after FW own clear */ + bdev->rx_ind = FALSE; + } + + /* + * Dequeue and send TX pending packets to bus + */ + while(!skb_queue_empty(&bdev->tx_queue)) { + skb = skb_dequeue(&bdev->tx_queue); + if(skb == NULL) + continue; + + /* + * make a copy of skb->len ot prevent skb being + * free after sending and recv event from FW + */ + skb_len = skb->len; + // dump cr if it is fw_assert cmd + if (skb_len >= 4 && skb->data[0] == 0x01 && skb->data[1] == 0x5B && + skb->data[2] == 0xFD && skb->data[3] == 0x00) { + kfree_skb(skb); + skb_queue_purge(&bdev->tx_queue); + bt_trigger_reset(); + break; + } +#if (DRIVER_CMD_CHECK == 1) + // enable driver check command timeout mechanism + if (skb_len >= 3 && skb->data[0] == 0x01 && skb->data[1] == 0x1B && + skb->data[2] == 0xFD ) { + kfree_skb(skb); + BTMTK_INFO("enable check command timeout"); + bdev->cmd_timeout_check = TRUE; + continue; + } +#endif + ret = btmtk_cif_send_cmd(bdev->hdev, skb->data, skb->len, 5, 0, 0); + kfree_skb(skb); + if ((ret < 0) || (ret != skb_len)) { + BTMTK_ERR("FATAL: TX packet error!! (%u/%d)", skb_len, ret); + break; + } + + if (psm->sleep_flag) { + BTMTK_DBG("more data to send and wait for event, ignore sleep"); + psm->sleep_flag = FALSE; + } + } + + /* + * If Quick PS mode is enabled, + * or there's a explicit sleep request. + * + * We need to excecute the Sleep procedure. + * + * For performance consideration, donot try to enter sleep during BT func on. + * + * [20191108] + * - do not sleep if there's pending cmd waiting for event + * [20191119] + * - add check if btif has pending data + */ + if (bdev->bt_state == FUNC_ON && cmd_list_isempty() && + psm->sleep_flag && !psm->force_on) { + // wait if btif tx is not finish yet + for (ii = 0; ii < 5; ii++) { + if (mtk_btif_is_tx_complete(g_btif_id) > 0) + break; + else + usleep_range(USLEEP_1MS_L, USLEEP_1MS_H); + if (ii == 4) + BTMTK_INFO("%s mtk_btif_is_tx_complete run 5 times", state_tag); + } + + sleep_ret = btmtk_cif_fw_own_set(); + if (sleep_ret) { + if (bdev->bt_state == FUNC_ON) { + BTMTK_ERR("(PSM_ST_NORMAL_TR) FATAL: btmtk_cif_fw_own_set error!! going to reset"); + bt_trigger_reset(); + } else + BTMTK_WARN("(PSM_ST_NORMAL_TR) bt_state [%d] is not FUNC_ON, skip reset", bdev->bt_state); + break; + } else { + bt_enable_irq(BGF2AP_BTIF_WAKEUP_IRQ); + btmtk_btif_dpidle_ctrl(TRUE); + psm->state = PSM_ST_SLEEP; + } + } + break; + + default: + BTMTK_ERR("FATAL: Unknown state %d!!", psm->state); + break; + } + } while(1); + + return 0; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_char_dev.c b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_char_dev.c new file mode 100644 index 0000000000000..2e30527930b84 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_char_dev.c @@ -0,0 +1,595 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#include "btmtk_main.h" + +MODULE_LICENSE("Dual BSD/GPL"); + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define BT_DRIVER_NAME "mtk_bt_chrdev" +#define BT_DRIVER_NODE_NAME "stpbt" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define BT_BUFFER_SIZE (2048) +#define FTRACE_STR_LOG_SIZE (256) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +enum chip_reset_state { + CHIP_RESET_NONE, + CHIP_RESET_START, + CHIP_RESET_END, + CHIP_RESET_NOTIFIED +}; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static int32_t BT_devs = 1; +static int32_t BT_major = 192; +module_param(BT_major, uint, 0); +static struct cdev BT_cdev; +#if CREATE_NODE_DYNAMIC +static struct class *BT_class; +static struct device *BT_dev; +#endif + +static uint8_t i_buf[BT_BUFFER_SIZE]; /* Input buffer for read */ +static uint8_t o_buf[BT_BUFFER_SIZE]; /* Output buffer for write */ + +extern struct btmtk_dev *g_bdev; +static struct semaphore wr_mtx, rd_mtx; +static struct bt_wake_lock bt_wakelock; +/* Wait queue for poll and read */ +static wait_queue_head_t inq; +static DECLARE_WAIT_QUEUE_HEAD(BT_wq); +static int32_t flag; +static int32_t bt_ftrace_flag; +/* + * Reset flag for whole chip reset scenario, to indicate reset status: + * 0 - normal, no whole chip reset occurs + * 1 - reset start + * 2 - reset end, have not sent Hardware Error event yet + * 3 - reset end, already sent Hardware Error event + */ +static uint32_t rstflag = CHIP_RESET_NONE; +static uint8_t HCI_EVT_HW_ERROR[] = {0x04, 0x10, 0x01, 0x00}; +static loff_t rd_offset; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +extern int bt_dev_dbg_init(void); +extern int bt_dev_dbg_deinit(void); +extern int bt_dev_dbg_set_state(bool turn_on); + +static int32_t ftrace_print(const uint8_t *str, ...) +{ +#ifdef CONFIG_TRACING + va_list args; + uint8_t temp_string[FTRACE_STR_LOG_SIZE]; + + if (bt_ftrace_flag) { + va_start(args, str); + if (vsnprintf(temp_string, FTRACE_STR_LOG_SIZE, str, args) < 0) + BTMTK_INFO("%s: vsnprintf error", __func__); + va_end(args); + trace_printk("%s\n", temp_string); + } +#endif + return 0; +} + +static size_t bt_report_hw_error(uint8_t *buf, size_t count, loff_t *f_pos) +{ + size_t bytes_rest, bytes_read; + + if (*f_pos == 0) + BTMTK_INFO("Send Hardware Error event to stack to restart Bluetooth"); + + bytes_rest = sizeof(HCI_EVT_HW_ERROR) - *f_pos; + bytes_read = count < bytes_rest ? count : bytes_rest; + memcpy(buf, HCI_EVT_HW_ERROR + *f_pos, bytes_read); + *f_pos += bytes_read; + + return bytes_read; +} + +static void bt_state_cb(enum bt_state state) +{ + switch (state) { + + case FUNC_ON: + rstflag = CHIP_RESET_NONE; + break; + case RESET_START: + rstflag = CHIP_RESET_START; + break; + case FUNC_OFF: + if (rstflag != CHIP_RESET_START) { + rstflag = CHIP_RESET_NONE; + break; + } + case RESET_END: + rstflag = CHIP_RESET_END; + rd_offset = 0; + flag = 1; + wake_up_interruptible(&inq); + wake_up(&BT_wq); + break; + default: + break; + } + return; +} + +#if 1 +static void BT_event_cb(void) +{ + ftrace_print("%s get called", __func__); + + /* + * Hold wakelock for 100ms to avoid system enter suspend in such case: + * FW has sent data to host, STP driver received the data and put it + * into BT rx queue, then send sleep command and release wakelock as + * quick sleep mechanism for low power, BT driver will wake up stack + * hci thread stuck in poll or read. + * But before hci thread comes to read data, system enter suspend, + * hci command timeout timer keeps counting during suspend period till + * expires, then the RTC interrupt wakes up system, command timeout + * handler is executed and meanwhile the event is received. + * This will false trigger FW assert and should never happen. + */ + bt_hold_wake_lock_timeout(&bt_wakelock, 100); + + /* + * Finally, wake up any reader blocked in poll or read + */ + flag = 1; + wake_up_interruptible(&inq); + wake_up(&BT_wq); + ftrace_print("%s wake_up triggered", __func__); +} +#endif + +static unsigned int BT_poll(struct file *filp, poll_table *wait) +{ + uint32_t mask = 0; + + if ((!btmtk_rx_data_valid() && rstflag == CHIP_RESET_NONE) || + (rstflag == CHIP_RESET_START) || (rstflag == CHIP_RESET_NOTIFIED)) { + /* + * BT RX queue is empty, or whole chip reset start, or already sent Hardware Error event + * for whole chip reset end, add to wait queue. + */ + poll_wait(filp, &inq, wait); + /* + * Check if condition changes before poll_wait return, in case of + * wake_up_interruptible is called before add_wait_queue, otherwise, + * do_poll will get into sleep and never be waken up until timeout. + */ + if (!((!btmtk_rx_data_valid() && rstflag == CHIP_RESET_NONE) || + (rstflag == CHIP_RESET_START) || (rstflag == CHIP_RESET_NOTIFIED))) + mask |= POLLIN | POLLRDNORM; /* Readable */ + } else { + /* BT RX queue has valid data, or whole chip reset end, have not sent Hardware Error event yet */ + mask |= POLLIN | POLLRDNORM; /* Readable */ + } + + /* Do we need condition here? */ + mask |= POLLOUT | POLLWRNORM; /* Writable */ + ftrace_print("%s: return mask = 0x%04x", __func__, mask); + + return mask; +} + +static ssize_t __bt_write(uint8_t *buf, size_t count, uint32_t flags) +{ + int32_t retval = 0; + + retval = btmtk_send_data(g_bdev->hdev, buf, count); + + if (retval < 0) + BTMTK_ERR("bt_core_send_data failed, retval %d", retval); + else if (retval == 0) { + /* + * TX queue cannot be digested in time and no space is available for write. + * + * If nonblocking mode, return -EAGAIN to let user retry, + * native program should not call write with no delay. + */ + if (flags & O_NONBLOCK) { + BTMTK_WARN("Non-blocking write, no space is available!"); + retval = -EAGAIN; + } else { + /*TODO: blocking write case */ + } + } else + BTMTK_DBG("Write bytes %d/%zd", retval, count); + + return retval; +} + +static ssize_t BT_write_iter(struct kiocb *iocb, struct iov_iter *from) +{ + ssize_t retval = 0; + size_t count = iov_iter_count(from); + + ftrace_print("%s get called, count %zd", __func__, count); + down(&wr_mtx); + + BTMTK_DBG("count %zd", count); + + if (rstflag != CHIP_RESET_NONE) { + BTMTK_ERR("whole chip reset occurs! rstflag=%d", rstflag); + retval = -EIO; + goto OUT; + } + + if (count > 0) { + if (count > BT_BUFFER_SIZE) { + BTMTK_WARN("Shorten write count from %zd to %d", count, BT_BUFFER_SIZE); + count = BT_BUFFER_SIZE; + } + + if (copy_from_iter(o_buf, count, from) != count) { + retval = -EFAULT; + goto OUT; + } + + retval = __bt_write(o_buf, count, iocb->ki_filp->f_flags); + } + +OUT: + up(&wr_mtx); + return retval; +} + +static ssize_t BT_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) +{ + ssize_t retval = 0; + + ftrace_print("%s get called, count %zd", __func__, count); + down(&wr_mtx); + + BTMTK_DBG("count %zd pos %lld", count, *f_pos); + + if (rstflag != CHIP_RESET_NONE) { + BTMTK_ERR("whole chip reset occurs! rstflag=%d", rstflag); + retval = -EIO; + goto OUT; + } + + if (count > 0) { + if (count > BT_BUFFER_SIZE) { + BTMTK_WARN("Shorten write count from %zd to %d", count, BT_BUFFER_SIZE); + count = BT_BUFFER_SIZE; + } + + if (copy_from_user(o_buf, buf, count)) { + retval = -EFAULT; + goto OUT; + } + + retval = __bt_write(o_buf, count, filp->f_flags); + } + +OUT: + up(&wr_mtx); + return retval; +} + +static ssize_t BT_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + ssize_t retval = 0; + + ftrace_print("%s get called, count %zd", __func__, count); + down(&rd_mtx); + + BTMTK_DBG("%s: count %zd pos %lld", __func__, count, *f_pos); + + if (rstflag != CHIP_RESET_NONE) { + while (rstflag != CHIP_RESET_END && rstflag != CHIP_RESET_NONE) { + /* + * If nonblocking mode, return -EIO directly. + * O_NONBLOCK is specified during open(). + */ + if (filp->f_flags & O_NONBLOCK) { + BTMTK_ERR("Non-blocking read, whole chip reset occurs! rstflag=%d", rstflag); + retval = -EIO; + goto OUT; + } + + wait_event(BT_wq, flag != 0); + flag = 0; + } + /* + * Reset end, send Hardware Error event to stack only once. + * To avoid high frequency read from stack before process is killed, set rstflag to 3 + * to block poll and read after Hardware Error event is sent. + */ + retval = bt_report_hw_error(i_buf, count, &rd_offset); + if (rd_offset == sizeof(HCI_EVT_HW_ERROR)) { + rd_offset = 0; + rstflag = CHIP_RESET_NOTIFIED; + } + + if (copy_to_user(buf, i_buf, retval)) { + retval = -EFAULT; + if (rstflag == CHIP_RESET_NOTIFIED) + rstflag = CHIP_RESET_END; + } + + goto OUT; + } + + if (count > BT_BUFFER_SIZE) { + BTMTK_WARN("Shorten read count from %zd to %d", count, BT_BUFFER_SIZE); + count = BT_BUFFER_SIZE; + } + + do { + retval = btmtk_receive_data(g_bdev->hdev, i_buf, count); + if (retval < 0) { + BTMTK_ERR("bt_core_receive_data failed, retval %d", retval); + goto OUT; + } else if (retval == 0) { /* Got nothing, wait for RX queue's signal */ + /* + * If nonblocking mode, return -EAGAIN to let user retry. + * O_NONBLOCK is specified during open(). + */ + if (filp->f_flags & O_NONBLOCK) { + BTMTK_ERR("Non-blocking read, no data is available!"); + retval = -EAGAIN; + goto OUT; + } + + wait_event(BT_wq, flag != 0); + flag = 0; + } else { /* Got something from RX queue */ + break; + } + } while (btmtk_rx_data_valid() && rstflag == CHIP_RESET_NONE); + + if (retval == 0) { + if (rstflag != CHIP_RESET_END) { /* Should never happen */ + WARN(1, "Blocking read is waken up in unexpected case, rstflag=%d", rstflag); + retval = -EIO; + goto OUT; + } else { /* Reset end, send Hardware Error event only once */ + retval = bt_report_hw_error(i_buf, count, &rd_offset); + if (rd_offset == sizeof(HCI_EVT_HW_ERROR)) { + rd_offset = 0; + rstflag = CHIP_RESET_NOTIFIED; + } + } + } + + if (copy_to_user(buf, i_buf, retval)) { + retval = -EFAULT; + if (rstflag == CHIP_RESET_NOTIFIED) + rstflag = CHIP_RESET_END; + } + +OUT: + up(&rd_mtx); + return retval; +} + +static long BT_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + int32_t retval = 0; + + BTMTK_DBG("cmd: 0x%08x", cmd); + return retval; +} + +static long BT_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + return BT_unlocked_ioctl(filp, cmd, arg); +} + +static int BT_open(struct inode *inode, struct file *file) +{ + int32_t ret; + + bt_hold_wake_lock(&bt_wakelock); + BTMTK_INFO("major %d minor %d (pid %d)", imajor(inode), iminor(inode), current->pid); + + /* Turn on BT */ + ret = g_bdev->hdev->open(g_bdev->hdev); + if (ret) { + BTMTK_ERR("BT turn on fail!"); + bt_release_wake_lock(&bt_wakelock); + return ret; + } + + BTMTK_INFO("BT turn on OK!"); + + btmtk_register_rx_event_cb(g_bdev, BT_event_cb); + + bt_ftrace_flag = 1; + bt_dev_dbg_set_state(TRUE); + bt_release_wake_lock(&bt_wakelock); + return 0; +} + +static int BT_close(struct inode *inode, struct file *file) +{ + int32_t ret; + + bt_hold_wake_lock(&bt_wakelock); + BTMTK_INFO("major %d minor %d (pid %d)", imajor(inode), iminor(inode), current->pid); + bt_dev_dbg_set_state(FALSE); + bt_ftrace_flag = 0; + //bt_core_unregister_rx_event_cb(); + + ret = g_bdev->hdev->close(g_bdev->hdev); + if (ret) { + BTMTK_ERR("BT turn off fail!"); + bt_release_wake_lock(&bt_wakelock); + return ret; + } + + BTMTK_INFO("BT turn off OK!"); + + bt_release_wake_lock(&bt_wakelock); + return 0; +} + +const struct file_operations BT_fops = { + .open = BT_open, + .release = BT_close, + .read = BT_read, + .write = BT_write, + .write_iter = BT_write_iter, + /* .ioctl = BT_ioctl, */ + .unlocked_ioctl = BT_unlocked_ioctl, + .compat_ioctl = BT_compat_ioctl, + .poll = BT_poll +}; + +static int BT_init(void) +{ + int32_t alloc_err = 0; + int32_t cdv_err = 0; + dev_t dev = MKDEV(BT_major, 0); + + sema_init(&wr_mtx, 1); + sema_init(&rd_mtx, 1); + init_waitqueue_head(&inq); + + /* Initialize wake lock for I/O operation */ + strncpy(bt_wakelock.name, "bt_drv_io", 9); + bt_wakelock.name[9] = 0; + bt_wake_lock_init(&bt_wakelock); + + main_driver_init(); + + g_bdev->state_change_cb[1] = bt_state_cb; +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH +#if 0 + fw_log_bt_init(); +#endif +#endif + + /* Allocate char device */ + alloc_err = register_chrdev_region(dev, BT_devs, BT_DRIVER_NAME); + if (alloc_err) { + BTMTK_ERR("Failed to register device numbers"); + goto alloc_error; + } + + cdev_init(&BT_cdev, &BT_fops); + BT_cdev.owner = THIS_MODULE; + + cdv_err = cdev_add(&BT_cdev, dev, BT_devs); + if (cdv_err) + goto cdv_error; + +#if CREATE_NODE_DYNAMIC /* mknod replace */ + BT_class = class_create(THIS_MODULE, BT_DRIVER_NODE_NAME); + if (IS_ERR(BT_class)) + goto create_node_error; + BT_dev = device_create(BT_class, NULL, dev, NULL, BT_DRIVER_NODE_NAME); + if (IS_ERR(BT_dev)) + goto create_node_error; +#endif + + bt_dev_dbg_init(); + BTMTK_INFO("%s driver(major %d) installed", BT_DRIVER_NAME, BT_major); + return 0; + +#if CREATE_NODE_DYNAMIC +create_node_error: + if (BT_class && !IS_ERR(BT_class)) { + class_destroy(BT_class); + BT_class = NULL; + } + + cdev_del(&BT_cdev); +#endif + +cdv_error: + unregister_chrdev_region(dev, BT_devs); + +alloc_error: +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH +#if 0 + fw_log_bt_exit(); +#endif +#endif + main_driver_exit(); + return -1; +} + +static void BT_exit(void) +{ + dev_t dev = MKDEV(BT_major, 0); + bt_dev_dbg_deinit(); + +#if CREATE_NODE_DYNAMIC + if (BT_dev && !IS_ERR(BT_dev)) { + device_destroy(BT_class, dev); + BT_dev = NULL; + } + if (BT_class && !IS_ERR(BT_class)) { + class_destroy(BT_class); + BT_class = NULL; + } +#endif + + cdev_del(&BT_cdev); + unregister_chrdev_region(dev, BT_devs); + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH +#if 0 + fw_log_bt_exit(); +#endif +#endif + g_bdev->state_change_cb[1] = NULL; + main_driver_exit(); + + /* Destroy wake lock */ + bt_wake_lock_deinit(&bt_wakelock); + + BTMTK_INFO("%s driver removed", BT_DRIVER_NAME); +} + +#ifdef MTK_WCN_REMOVE_KERNEL_MODULE + +int mtk_wcn_stpbt_drv_init(void) +{ + return BT_init(); +} +EXPORT_SYMBOL(mtk_wcn_stpbt_drv_init); + +void mtk_wcn_stpbt_drv_exit(void) +{ + return BT_exit(); +} +EXPORT_SYMBOL(mtk_wcn_stpbt_drv_exit); + +#else + +module_init(BT_init); +module_exit(BT_exit); + +#endif diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_chip_if.h b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_chip_if.h new file mode 100644 index 0000000000000..ceadb77a43187 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_chip_if.h @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2018 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef __BTMTK_CHIP_IF_H__ +#define __BTMTK_CHIP_IF_H__ + +/* default not support */ +#define SUPPORT_BT_THREAD (0) + +#ifdef CHIP_IF_USB +#include "btmtk_usb.h" +#elif defined(CHIP_IF_SDIO) +#include "btmtk_sdio.h" +#elif defined(CHIP_IF_UART) +#include "btmtk_uart.h" +#elif defined(CHIP_IF_BTIF) +#include "btmtk_btif.h" +#endif + +int btmtk_cif_register(void); +int btmtk_cif_deregister(void); + +#endif /* __BTMTK_CHIP_IF_H__ */ diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_config.h b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_config.h new file mode 100644 index 0000000000000..428e3014c2f61 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_config.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2016,2017 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef __BTMTK_CONFIG_H__ +#define __BTMTK_CONFIG_H__ + +/** + * GPIO PIN configureation + */ +#ifndef BT_DONGLE_RESET_GPIO_PIN + #define BT_DONGLE_RESET_GPIO_PIN 220 +#endif /* BT_DONGLE_RESET_GPIO_PIN */ + + +/** + * WoBLE by BLE RC + */ +#endif /* __BTMTK_CONFIG_H__ */ diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_dbg.c b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_dbg.c new file mode 100644 index 0000000000000..fd6f2a23d7b87 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_dbg.c @@ -0,0 +1,615 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#include +#include +#include +#include +#include "btmtk_define.h" +#include "btmtk_mt66xx_reg.h" +#include "btmtk_chip_if.h" +#include "conninfra.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define BT_DBG_PROCNAME "driver/bt_dbg" +#define BUF_LEN_MAX 384 +#define BT_DBG_DUMP_BUF_SIZE 1024 +#define BT_DBG_PASSWD "4w2T8M65K5?2af+a " +#define BT_DBG_USER_TRX_PREFIX "[user-trx] " + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef int(*BT_DEV_DBG_FUNC) (int par1, int par2, int par3); +typedef struct { + BT_DEV_DBG_FUNC func; + bool turn_off_availavle; // function can be work when bt off +} tBT_DEV_DBG_STRUCT; + +/******************************************************************************* +* P U B L I C 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 ssize_t bt_dbg_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos); +static ssize_t bt_dbg_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos); +static int bt_dbg_hwver_get(int par1, int par2, int par3); +static int bt_dbg_chip_rst(int par1, int par2, int par3); +static int bt_dbg_read_chipid(int par1, int par2, int par3); +static int bt_dbg_force_bt_wakeup(int par1, int par2, int par3); +static int bt_dbg_get_fwp_datetime(int par1, int par2, int par3); +static int bt_dbg_get_bt_patch_path(int par1, int par2, int par3); +extern int fwp_if_get_datetime(char *buf, int max_len); +extern int fwp_if_get_bt_patch_path(char *buf, int max_len); +#if (CUSTOMER_FW_UPDATE == 1) +static int bt_dbg_set_fwp_update_enable(int par1, int par2, int par3); +static int bt_dbg_get_fwp_update_info(int par1, int par2, int par3); +extern void fwp_if_set_update_enable(int par); +extern int fwp_if_get_update_info(char *buf, int max_len); +#endif +static int bt_dbg_reg_read(int par1, int par2, int par3); +static int bt_dbg_reg_write(int par1, int par2, int par3); +static int bt_dbg_ap_reg_read(int par1, int par2, int par3); +static int bt_dbg_ap_reg_write(int par1, int par2, int par3); +static int bt_dbg_setlog_level(int par1, int par2, int par3); +static int bt_dbg_set_rt_thread(int par1, int par2, int par3); +static int bt_dbg_get_bt_state(int par1, int par2, int par3); +static int bt_dbg_rx_buf_control(int par1, int par2, int par3); +static int bt_dbg_set_rt_thread_runtime(int par1, int par2, int par3); +static void bt_dbg_user_trx_proc(char *cmd_raw); +static void bt_dbg_user_trx_cb(char *buf, int len); + +extern int32_t btmtk_send_data(struct hci_dev *hdev, uint8_t *buf, uint32_t count); +extern int32_t btmtk_set_wakeup(struct hci_dev *hdev); +extern int32_t btmtk_set_sleep(struct hci_dev *hdev, u_int8_t need_wait); +extern void bt_trigger_reset(void); + + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +extern struct btmtk_dev *g_bdev; +extern struct bt_dbg_st g_bt_dbg_st; +static struct proc_dir_entry *g_bt_dbg_entry; +static struct mutex g_bt_lock; +static char g_bt_dump_buf[BT_DBG_DUMP_BUF_SIZE]; +static char *g_bt_dump_buf_ptr; +static int g_bt_dump_buf_len; +static bool g_bt_turn_on = FALSE; +static bool g_bt_dbg_enable = FALSE; + +static const tBT_DEV_DBG_STRUCT bt_dev_dbg_struct[] = { + [0x0] = {bt_dbg_hwver_get, FALSE}, + [0x1] = {bt_dbg_chip_rst, FALSE}, + [0x2] = {bt_dbg_read_chipid, FALSE}, + [0x3] = {bt_dbg_force_bt_wakeup, FALSE}, + [0x4] = {bt_dbg_reg_read, FALSE}, + [0x5] = {bt_dbg_reg_write, FALSE}, + [0x6] = {bt_dbg_get_fwp_datetime, TRUE}, +#if (CUSTOMER_FW_UPDATE == 1) + [0x7] = {bt_dbg_set_fwp_update_enable, TRUE}, + [0x8] = {bt_dbg_get_fwp_update_info, FALSE}, +#endif + [0x9] = {bt_dbg_ap_reg_read, FALSE}, + [0xa] = {bt_dbg_ap_reg_write, TRUE}, + [0xb] = {bt_dbg_setlog_level, TRUE}, + [0xc] = {bt_dbg_get_bt_patch_path, TRUE}, + [0xd] = {bt_dbg_set_rt_thread, TRUE}, + [0xe] = {bt_dbg_get_bt_state, TRUE}, + [0xf] = {bt_dbg_rx_buf_control, TRUE}, + [0x10] = {bt_dbg_set_rt_thread_runtime, FALSE}, +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + + + +void _bt_dbg_reset_dump_buf(void) +{ + memset(g_bt_dump_buf, '\0', BT_DBG_DUMP_BUF_SIZE); + g_bt_dump_buf_ptr = g_bt_dump_buf; + g_bt_dump_buf_len = 0; +} + +int bt_dbg_hwver_get(int par1, int par2, int par3) +{ + BTMTK_INFO("query chip version"); + /* TODO: */ + return 0; +} + +int bt_dbg_chip_rst(int par1, int par2, int par3) +{ + if(par2 == 0) + bt_trigger_reset(); + else + conninfra_trigger_whole_chip_rst(CONNDRV_TYPE_BT, "bt_dbg"); + return 0; +} + + +int bt_dbg_read_chipid(int par1, int par2, int par3) +{ + return 0; +} + +int bt_dbg_reg_read(int par1, int par2, int par3) +{ + uint32_t *dynamic_remap_addr = NULL; + uint32_t *dynamic_remap_value = NULL; + + /* TODO: */ + dynamic_remap_addr = ioremap_nocache(0x18001104, 4); + if (dynamic_remap_addr) { + *dynamic_remap_addr = par2; + BTMTK_DBG("read address = [0x%08x]", par2); + } else { + BTMTK_ERR("ioremap 0x18001104 fail"); + return -1; + } + iounmap(dynamic_remap_addr); + + dynamic_remap_value = ioremap_nocache(0x18900000, 4); + if (dynamic_remap_value) + BTMTK_INFO("%s: 0x%08x value = [0x%08x]", __func__, par2, + *dynamic_remap_value); + else { + BTMTK_ERR("ioremap 0x18900000 fail"); + return -1; + } + iounmap(dynamic_remap_value); + return 0; +} + +int bt_dbg_reg_write(int par1, int par2, int par3) +{ + uint32_t *dynamic_remap_addr = NULL; + uint32_t *dynamic_remap_value = NULL; + + /* TODO: */ + dynamic_remap_addr = ioremap_nocache(0x18001104, 4); + if (dynamic_remap_addr) { + *dynamic_remap_addr = par2; + BTMTK_DBG("write address = [0x%08x]", par2); + } else { + BTMTK_ERR("ioremap 0x18001104 fail"); + return -1; + } + iounmap(dynamic_remap_addr); + + dynamic_remap_value = ioremap_nocache(0x18900000, 4); + if (dynamic_remap_value) + *dynamic_remap_value = par3; + else { + BTMTK_ERR("ioremap 0x18900000 fail"); + return -1; + } + iounmap(dynamic_remap_value); + return 0; + +} + +int bt_dbg_ap_reg_read(int par1, int par2, int par3) +{ + uint32_t *remap_addr = NULL; + + /* TODO: */ + remap_addr = ioremap_nocache(par2, 4); + if (!remap_addr) { + BTMTK_ERR("ioremap [0x%08x] fail", par2); + return -1; + } + + BTMTK_INFO("%s: 0x%08x value = [0x%08x]", __func__, par2, *remap_addr); + iounmap(remap_addr); + return 0; +} + +int bt_dbg_ap_reg_write(int par1, int par2, int par3) +{ + uint32_t *remap_addr = NULL; + + /* TODO: */ + remap_addr = ioremap_nocache(par2, 4); + if (!remap_addr) { + BTMTK_ERR("ioremap [0x%08x] fail", par2); + return -1; + } + + *remap_addr = par3; + iounmap(remap_addr); + return 0; +} + +int bt_dbg_setlog_level(int par1, int par2, int par3) +{ + if (par2 < BTMTK_LOG_LVL_ERR || par2 > BTMTK_LOG_LVL_DBG) { + btmtk_log_lvl = BTMTK_LOG_LVL_INFO; + } else { + btmtk_log_lvl = par2; + } + return 0; +} + +int bt_dbg_set_rt_thread(int par1, int par2, int par3) +{ + g_bt_dbg_st.rt_thd_enable = par2; + return 0; +} + +int bt_dbg_set_rt_thread_runtime(int par1, int par2, int par3) +{ + struct sched_param params; + int policy = 0; + int ret = 0; + + /* reference parameter: + - normal: 0x10 0x01(SCHED_FIFO) 0x01 + - normal: 0x10 0x01(SCHED_FIFO) 0x50(MAX_RT_PRIO - 20) + */ + if (par2 > SCHED_DEADLINE || par3 > MAX_RT_PRIO) { + BTMTK_INFO("%s: parameter not allow!", __func__); + return 0; + } + policy = par2; + params.sched_priority = par3; + ret = sched_setscheduler(g_bdev->tx_thread, policy, ¶ms); + BTMTK_INFO("%s: ret[%d], policy[%d], sched_priority[%d]", __func__, ret, policy, params.sched_priority); + + return 0; +} + +int bt_dbg_get_bt_state(int par1, int par2, int par3) +{ + // 0x01: bt on, 0x00: bt off + BTMTK_INFO("%s: g_bt_turn_on[%d]", __func__, g_bt_turn_on); + _bt_dbg_reset_dump_buf(); + g_bt_dump_buf[0] = g_bt_turn_on; + g_bt_dump_buf[1] = '\0'; + g_bt_dump_buf_len = 2; + return 0; +} + +int bt_dbg_force_bt_wakeup(int par1, int par2, int par3) +{ + int ret; + + BTMTK_INFO("%s", __func__); + + switch(par2) { + case 0: + g_bdev->psm.force_on = FALSE; + ret = btmtk_set_sleep(g_bdev->hdev, TRUE); + break; + + case 1: + g_bdev->psm.force_on = TRUE; + ret = btmtk_set_wakeup(g_bdev->hdev); + break; + default: + BTMTK_ERR("Not support"); + return -1; + } + + BTMTK_INFO("bt %s %s", (par2 == 1) ? "wakeup" : "sleep", + (ret) ? "fail" : "success"); + + return 0; +} + +int bt_dbg_get_fwp_datetime(int par1, int par2, int par3) +{ + _bt_dbg_reset_dump_buf(); + g_bt_dump_buf_len = fwp_if_get_datetime(g_bt_dump_buf, BT_DBG_DUMP_BUF_SIZE); + return 0; +} + +int bt_dbg_get_bt_patch_path(int par1, int par2, int par3) +{ + _bt_dbg_reset_dump_buf(); + g_bt_dump_buf_len = fwp_if_get_bt_patch_path(g_bt_dump_buf, BT_DBG_DUMP_BUF_SIZE); + return 0; +} + +#if (CUSTOMER_FW_UPDATE == 1) +int bt_dbg_set_fwp_update_enable(int par1, int par2, int par3) +{ + fwp_if_set_update_enable(par2); + return 0; +} + + +int bt_dbg_get_fwp_update_info(int par1, int par2, int par3) +{ + _bt_dbg_reset_dump_buf(); + g_bt_dump_buf_len = fwp_if_get_update_info(g_bt_dump_buf, BT_DBG_DUMP_BUF_SIZE); + return 0; +} +#endif + +int bt_dbg_rx_buf_control(int par1, int par2, int par3) +{ + /* + 0x00: disable + 0x01: wait rx buffer available for max 200ms + */ + BTMTK_INFO("%s: rx_buf_ctrl[%d] set to [%d]", __func__, g_bt_dbg_st.rx_buf_ctrl, par2); + g_bt_dbg_st.rx_buf_ctrl = par2; + return 0; +} + +ssize_t bt_dbg_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + int ret = 0; + int dump_len; + + ret = mutex_lock_killable(&g_bt_lock); + if (ret) { + BTMTK_ERR("%s: dump_lock fail!!", __func__); + return ret; + } + + if (g_bt_dump_buf_len == 0) + goto exit; + + if (*f_pos == 0) + g_bt_dump_buf_ptr = g_bt_dump_buf; + + dump_len = g_bt_dump_buf_len >= count ? count : g_bt_dump_buf_len; + ret = copy_to_user(buf, g_bt_dump_buf_ptr, dump_len); + if (ret) { + BTMTK_ERR("%s: copy to dump info buffer failed, ret:%d", __func__, ret); + ret = -EFAULT; + goto exit; + } + + *f_pos += dump_len; + g_bt_dump_buf_len -= dump_len; + g_bt_dump_buf_ptr += dump_len; + BTMTK_INFO("%s: after read, wmt for dump info buffer len(%d)", __func__, g_bt_dump_buf_len); + + ret = dump_len; +exit: + + mutex_unlock(&g_bt_lock); + return ret; +} + +int osal_strtol(const char *str, unsigned int adecimal, long *res) +{ + if (sizeof(long) == 4) + return kstrtou32(str, adecimal, (unsigned int *) res); + else + return kstrtol(str, adecimal, res); +} + +void bt_dbg_user_trx_cb(char *buf, int len) +{ + unsigned char *ptr = buf; + int i = 0; + + // if this event is not the desire one, skip and reset buffer + if((buf[3] + (buf[4] << 8)) != g_bt_dbg_st.trx_opcode) + return; + + // desire rx event is received, write to read buffer as string + BTMTK_INFO_RAW(buf, len, "%s: len[%d], RxEvt: ", __func__, len); + if((len + 1)*5 + 2 > BT_DBG_DUMP_BUF_SIZE) + return; + + _bt_dbg_reset_dump_buf(); + // write event packet type + if (snprintf(g_bt_dump_buf, 6, "0x04 ") < 0) { + BTMTK_INFO("%s: snprintf error", __func__); + goto end; + + } + for (i = 0; i < len; i++) { + if (snprintf(g_bt_dump_buf + 5*(i+1), 6, "0x%02X ", ptr[i]) < 0) { + BTMTK_INFO("%s: snprintf error", __func__); + goto end; + } + } + len++; + g_bt_dump_buf[5*len] = '\n'; + g_bt_dump_buf[5*len + 1] = '\0'; + g_bt_dump_buf_len = 5*len + 1; + +end: + // complete trx process + complete(&g_bt_dbg_st.trx_comp); +} + +void bt_dbg_user_trx_proc(char *cmd_raw) +{ +#define LEN_64 64 + unsigned char hci_cmd[LEN_64]; + int len = 0; + long tmp = 0; + char *ptr = NULL, *pRaw = NULL; + + // Parse command raw data + memset(hci_cmd, 0, sizeof(hci_cmd)); + pRaw = cmd_raw; + ptr = cmd_raw; + while(*ptr != '\0' && pRaw != NULL) { + if (len > LEN_64 - 1) { + BTMTK_INFO("%s: skip since cmd length exceed!", __func__); + return; + } + ptr = strsep(&pRaw, " "); + if (ptr != NULL) { + osal_strtol(ptr, 16, &tmp); + hci_cmd[len++] = (unsigned char)tmp; + } + } + BTMTK_INFO_RAW(hci_cmd, len, "%s: len[%d], TxCmd: ", __func__, len); + + // Send command and wait for command_complete event + g_bt_dbg_st.trx_opcode = hci_cmd[1] + (hci_cmd[2] << 8); + g_bt_dbg_st.trx_enable = TRUE; + btmtk_send_data(g_bdev->hdev, hci_cmd, len); + if (!wait_for_completion_timeout(&g_bt_dbg_st.trx_comp, msecs_to_jiffies(2000))) + BTMTK_ERR("%s: wait event timeout!", __func__); + g_bt_dbg_st.trx_enable = FALSE; +} + +ssize_t bt_dbg_write(struct file *filp, const char __user *buffer, size_t count, loff_t *f_pos) +{ + bool is_passwd = FALSE, is_turn_on = FALSE; + size_t len = count; + char buf[256], *pBuf; + int x = 0, y = 0, z = 0; + long res = 0; + char* pToken = NULL; + char* pDelimiter = " \t"; + + if (len <= 0 || len >= sizeof(buf)) { + BTMTK_ERR("%s: input handling fail!", __func__); + len = sizeof(buf) - 1; + return -1; + } + + memset(buf, 0, sizeof(buf)); + if (copy_from_user(buf, buffer, len)) + return -EFAULT; + buf[len] = '\0'; + BTMTK_INFO("%s: g_bt_turn_on[%d], dbg_enable[%d], len[%d], data = %s", + __func__, g_bt_turn_on, g_bt_dbg_enable, (int)len, buf); + + /* Check debug function is enabled or not + * - not enable yet: user should enable it + * - already enabled: user can disable it + */ + if (len > strlen(BT_DBG_PASSWD) && + 0 == memcmp(buf, BT_DBG_PASSWD, strlen(BT_DBG_PASSWD))) { + is_passwd = TRUE; + if (0 == memcmp(buf + strlen(BT_DBG_PASSWD), "ON", strlen("ON"))) + is_turn_on = TRUE; + } + if(!g_bt_dbg_enable) { + if(is_passwd && is_turn_on) + g_bt_dbg_enable = TRUE; + return len; + } else { + if(is_passwd && !is_turn_on) { + g_bt_dbg_enable = FALSE; + return len; + } + } + + /* Mode 1: User trx flow: send command, get response */ + if (0 == memcmp(buf, BT_DBG_USER_TRX_PREFIX, strlen(BT_DBG_USER_TRX_PREFIX))) { + if(!g_bt_turn_on) // only work when bt on + return len; + buf[len - 1] = '\0'; + bt_dbg_user_trx_proc(buf + strlen(BT_DBG_USER_TRX_PREFIX)); + return len; + } + + /* Mode 2: Debug cmd flow, parse three parameters */ + pBuf = buf; + pToken = strsep(&pBuf, pDelimiter); + if (pToken != NULL) { + osal_strtol(pToken, 16, &res); + x = (int)res; + } else { + x = 0; + } + + pToken = strsep(&pBuf, "\t\n "); + if (pToken != NULL) { + osal_strtol(pToken, 16, &res); + y = (int)res; + BTMTK_INFO("%s: y = 0x%08x\n\r", __func__, y); + } else { + y = 3000; + /*efuse, register read write default value */ + if (0x5 == x || 0x6 == x) + y = 0x80000000; + } + + pToken = strsep(&pBuf, "\t\n "); + if (pToken != NULL) { + osal_strtol(pToken, 16, &res); + z = (int)res; + } else { + z = 10; + /*efuse, register read write default value */ + if (0x5 == x || 0x6 == x) + z = 0xffffffff; + } + + BTMTK_INFO("%s: x(0x%08x), y(0x%08x), z(0x%08x)", __func__, x, y, z); + if (ARRAY_SIZE(bt_dev_dbg_struct) > x && NULL != bt_dev_dbg_struct[x].func) { + if(!g_bt_turn_on && !bt_dev_dbg_struct[x].turn_off_availavle) { + BTMTK_WARN("%s: command id(0x%08x) only work when bt on!", __func__, x); + } else { + (*bt_dev_dbg_struct[x].func) (x, y, z); + } + } else { + BTMTK_WARN("%s: command id(0x%08x) no handler defined!", __func__, x); + } + + return len; +} + +int bt_dev_dbg_init(void) +{ + int i_ret = 0; + static const struct file_operations bt_dbg_fops = { + .owner = THIS_MODULE, + .read = bt_dbg_read, + .write = bt_dbg_write, + }; + + // initialize debug function struct + g_bt_dbg_st.rt_thd_enable = FALSE; + g_bt_dbg_st.trx_enable = FALSE; + g_bt_dbg_st.trx_cb = bt_dbg_user_trx_cb; + g_bt_dbg_st.rx_buf_ctrl = TRUE; + init_completion(&g_bt_dbg_st.trx_comp); + + g_bt_dbg_entry = proc_create(BT_DBG_PROCNAME, 0664, NULL, &bt_dbg_fops); + if (g_bt_dbg_entry == NULL) { + BTMTK_ERR("Unable to create [%s] bt proc entry", BT_DBG_PROCNAME); + i_ret = -1; + } + + mutex_init(&g_bt_lock); + + return i_ret; +} + +int bt_dev_dbg_deinit(void) +{ + mutex_destroy(&g_bt_lock); + + if (g_bt_dbg_entry != NULL) { + proc_remove(g_bt_dbg_entry); + g_bt_dbg_entry = NULL; + } + + return 0; +} + + +int bt_dev_dbg_set_state(bool turn_on) +{ + g_bt_turn_on = turn_on; + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_define.h b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_define.h new file mode 100644 index 0000000000000..cb8662a4e5c29 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_define.h @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2016,2017 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef __BTMTK_DEFINE_H__ +#define __BTMTK_DEFINE_H__ + + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +/* Define for proce node */ +#include +#include + +#include "btmtk_config.h" + + +/** Driver version */ +#define VERSION "7.0.18081001" +#define SUBVER ":turnkey" + + +#define ENABLESTP FALSE +#define BLUEDROID TRUE +#define BTMTKUART_TX_STATE_ACTIVE 1 +#define BTMTKUART_TX_STATE_WAKEUP 2 +#define BTMTKUART_TX_WAIT_VND_EVT 3 +#define BTMTKUART_REQUIRED_WAKEUP 4 +#define BTMTKUART_REQUIRED_DOWNLOAD 5 +#define BTMTKUART_TX_SKIP_VENDOR_EVT 6 + +#define BTMTKUART_RX_STATE_ACTIVE 1 +#define BTMTKUART_RX_STATE_WAKEUP 2 +#define BTMTKUART_RX_STATE_RESET 3 + + + +/** + * Type definition + */ +#ifndef TRUE + #define TRUE 1 +#endif +#ifndef FALSE + #define FALSE 0 +#endif + +#ifndef UNUSED + #define UNUSED(x) (void)(x) +#endif + +#ifndef ALIGN_4 +#define ALIGN_4(_value) (((_value) + 3) & ~3u) +#endif /* ALIGN_4 */ + +#ifndef ALIGN_8 +#define ALIGN_8(_value) (((_value) + 7) & ~7u) +#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 */ + +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + +#undef container_of +#define container_of(ptr, type, member) ({ \ + const typeof(((type *)0)->member) *__mptr = (ptr); \ + (type *)((char *)__mptr - offsetof(type, member)); \ +}) + + +/** + * Log and level definition + */ +#define BTMTK_LOG_LVL_ERR 1 +#define BTMTK_LOG_LVL_WARN 2 +#define BTMTK_LOG_LVL_INFO 3 +#define BTMTK_LOG_LVL_DBG 4 +#define BTMTK_LOG_LVL_MAX BTMTK_LOG_LVL_DBG +#define BTMTK_LOG_LVL_DEF BTMTK_LOG_LVL_INFO /* default setting */ +#define RAW_MAX_BYTES 30 + +static uint8_t raw_buf[RAW_MAX_BYTES * 5 + 10]; +extern uint8_t btmtk_log_lvl; + +#define BTMTK_ERR(fmt, ...) \ + do { if (btmtk_log_lvl >= BTMTK_LOG_LVL_ERR) pr_info("[btmtk_err] ***"fmt"***\n", ##__VA_ARGS__); } while (0) +#define BTMTK_WARN(fmt, ...) \ + do { if (btmtk_log_lvl >= BTMTK_LOG_LVL_WARN) pr_info("[btmtk_warn] "fmt"\n", ##__VA_ARGS__); } while (0) +#define BTMTK_INFO(fmt, ...) \ + do { if (btmtk_log_lvl >= BTMTK_LOG_LVL_INFO) pr_info("[btmtk_info] "fmt"\n", ##__VA_ARGS__); } while (0) +#define BTMTK_DBG(fmt, ...) \ + do { if (btmtk_log_lvl >= BTMTK_LOG_LVL_DBG) pr_info("[btmtk_dbg] "fmt"\n", ##__VA_ARGS__); } while (0) + +#define BTMTK_INFO_RAW(p, l, fmt, ...) \ + do { \ + if (btmtk_log_lvl >= BTMTK_LOG_LVL_INFO) { \ + int cnt_ = 0; \ + int len_ = (l <= RAW_MAX_BYTES ? l : RAW_MAX_BYTES); \ + const unsigned char *ptr = p; \ + for (cnt_ = 0; cnt_ < len_; ++cnt_) { \ + if (snprintf(raw_buf+5*cnt_, 6, "0x%02X ", ptr[cnt_]) < 0) { \ + pr_info("snprintf error\n"); \ + break; \ + } \ + } \ + raw_buf[5*cnt_] = '\0'; \ + if (l <= RAW_MAX_BYTES) { \ + pr_cont("[btmtk_info] "fmt"%s\n", ##__VA_ARGS__, raw_buf); \ + } else { \ + pr_cont("[btmtk_info] "fmt"%s (prtail)\n", ##__VA_ARGS__, raw_buf); \ + } \ + } \ + } while (0) + +#define BTMTK_DBG_RAW(p, l, fmt, ...) \ + do { \ + if (btmtk_log_lvl >= BTMTK_LOG_LVL_DBG) { \ + int cnt_ = 0; \ + int len_ = (l <= RAW_MAX_BYTES ? l : RAW_MAX_BYTES); \ + const unsigned char *ptr = p; \ + for (cnt_ = 0; cnt_ < len_; ++cnt_) { \ + if (snprintf(raw_buf+5*cnt_, 6, "0x%02X ", ptr[cnt_]) < 0) { \ + pr_info("snprintf error\n"); \ + break; \ + } \ + } \ + raw_buf[5*cnt_] = '\0'; \ + if (l <= RAW_MAX_BYTES) { \ + pr_cont("[btmtk_debug] "fmt"%s\n", ##__VA_ARGS__, raw_buf); \ + } else { \ + pr_cont("[btmtk_debug] "fmt"%s (prtail)\n", ##__VA_ARGS__, raw_buf); \ + } \ + } \ + } while (0) + +#define FN_ENTER(fmt, ...) \ + pr_cont("[btmtk_info] %s Enter: "fmt"\n", __func__, ##__VA_ARGS__); +#define FN_END(fmt, ...) \ + pr_cont("[btmtk_info] %s End: "fmt"\n", __func__, ##__VA_ARGS__); + + +/** + * + * HCI packet type + */ +#define MTK_HCI_COMMAND_PKT 0x01 +#define MTK_HCI_ACLDATA_PKT 0x02 +#define MTK_HCI_SCODATA_PKT 0x03 +#define MTK_HCI_EVENT_PKT 0x04 + +/** + * ROM patch related + */ +#define PATCH_HCI_HEADER_SIZE 4 +#define PATCH_WMT_HEADER_SIZE 5 +/* + * Enable STP + * HCI+WMT+STP = 4 + 5 + 1(phase) +(4=STP_HEADER + 2=CRC) +#define PATCH_HEADER_SIZE 16 + */ +/*#ifdef ENABLESTP +#define PATCH_HEADER_SIZE (PATCH_HCI_HEADER_SIZE + PATCH_WMT_HEADER_SIZE + 1 + 6) +#define UPLOAD_PATCH_UNIT 916 +#define PATCH_INFO_SIZE 30 +#else*/ +#define PATCH_HEADER_SIZE (PATCH_HCI_HEADER_SIZE + PATCH_WMT_HEADER_SIZE + 1) +#define UPLOAD_PATCH_UNIT 910 +#define PATCH_INFO_SIZE 30 +//#endif +#define PATCH_PHASE1 1 +#define PATCH_PHASE2 2 +#define PATCH_PHASE3 3 + + +#define USB_IO_BUF_SIZE (HCI_MAX_EVENT_SIZE > 256 ? HCI_MAX_EVENT_SIZE : 256) +#define HCI_SNOOP_ENTRY_NUM 30 +#define HCI_SNOOP_BUF_SIZE 32 + +#endif /* __BTMTK_DEFINE_H__ */ diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_drv.h b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_drv.h new file mode 100644 index 0000000000000..e8feb8e024746 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_drv.h @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2016,2017 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef _BTMTK_DRV_H_ +#define _BTMTK_DRV_H_ + +#include +#include +#include +#include + +#define SAVE_FW_DUMP_IN_KERNEL 1 + +#define SUPPORT_FW_DUMP 1 +#define BTM_HEADER_LEN 5 +#define BTM_UPLD_SIZE 2312 + +#define MTK_TXDATA_SIZE 2000 +#define MTK_RXDATA_SIZE 2000 + +/* Time to wait until Host Sleep state change in millisecond */ +#define WAIT_UNTIL_HS_STATE_CHANGED msecs_to_jiffies(5000) +/* Time to wait for command response in millisecond */ +#define WAIT_UNTIL_CMD_RESP msecs_to_jiffies(5000) + +#define BTMTK_BIN_FILE_MODE 1 +#if BTMTK_BIN_FILE_MODE +/** For 7668 please storage cfg/bin file in ${firmware} */ +#define E2P_ACCESS_MODE_SWITCHER "wifi.cfg" +#define E2P_BIN_FILE "EEPROM_MT%X.bin" + +#define E2P_MODE "EfuseBufferModeCal" +#define BIN_FILE_MODE '1' +#endif + +enum rdwr_status { + RDWR_STATUS_SUCCESS = 0, + RDWR_STATUS_FAILURE = 1, + RDWR_STATUS_DONE = 2 +}; + +#define FW_DUMP_MAX_NAME_LEN 8 +#define FW_DUMP_HOST_READY 0xEE +#define FW_DUMP_DONE 0xFF +#define FW_DUMP_READ_DONE 0xFE + +struct memory_type_mapping { + u8 mem_name[FW_DUMP_MAX_NAME_LEN]; + u8 *mem_ptr; + u32 mem_size; + u8 done_flag; +}; + +struct btmtk_thread { + struct task_struct *task; + wait_queue_head_t wait_q; + void *priv; +}; + +struct btmtk_device { + void *card; + /* struct hci_dev *hcidev; */ + + u8 dev_type; + + u8 tx_dnld_rdy; + + u8 psmode; + u8 pscmd; + u8 hsmode; + u8 hscmd; + + /* Low byte is gap, high byte is GPIO */ + u16 gpio_gap; + + u8 hscfgcmd; + u8 sendcmdflag; +}; + +struct btmtk_adapter { + void *hw_regs_buf; + u8 *hw_regs; + u32 int_count; + struct sk_buff_head tx_queue; + struct sk_buff_head fops_queue; + struct sk_buff_head fwlog_fops_queue; + struct sk_buff_head fwlog_tx_queue; + u8 fops_mode; + u8 psmode; + u8 ps_state; + u8 hs_state; + u8 wakeup_tries; + wait_queue_head_t cmd_wait_q; + wait_queue_head_t event_hs_wait_q; + u8 cmd_complete; + bool is_suspended; +}; + +struct btmtk_private { + struct btmtk_device btmtk_dev; + struct btmtk_adapter *adapter; + struct btmtk_thread main_thread; + int (*hw_host_to_card)(struct btmtk_private *priv, + u8 *payload, u16 nb); + + int (*hw_set_own_back)(int owntype); + int (*hw_process_int_status)(struct btmtk_private *priv); + void (*firmware_dump)(struct btmtk_private *priv); + spinlock_t driver_lock; /* spinlock used by driver */ +#ifdef CONFIG_DEBUG_FS + void *debugfs_data; +#endif + bool surprise_removed; +#if SUPPORT_FW_DUMP + struct semaphore fw_dump_semaphore; + struct task_struct *fw_dump_tsk; + struct task_struct *fw_dump_end_check_tsk; +#endif +}; + +#define MTK_VENDOR_PKT 0xFE + +/* Vendor specific Bluetooth commands */ +#define BT_CMD_PSCAN_WIN_REPORT_ENABLE 0xFC03 +#define BT_CMD_ROUTE_SCO_TO_HOST 0xFC1D +#define BT_CMD_SET_BDADDR 0xFC22 +#define BT_CMD_AUTO_SLEEP_MODE 0xFC23 +#define BT_CMD_HOST_SLEEP_CONFIG 0xFC59 +#define BT_CMD_HOST_SLEEP_ENABLE 0xFC5A +#define BT_CMD_MODULE_CFG_REQ 0xFC5B +#define BT_CMD_LOAD_CONFIG_DATA 0xFC61 + +/* Sub-commands: Module Bringup/Shutdown Request/Response */ +#define MODULE_BRINGUP_REQ 0xF1 +#define MODULE_BROUGHT_UP 0x00 +#define MODULE_ALREADY_UP 0x0C + +#define MODULE_SHUTDOWN_REQ 0xF2 + +/* Vendor specific Bluetooth events */ +#define BT_EVENT_AUTO_SLEEP_MODE 0x23 +#define BT_EVENT_HOST_SLEEP_CONFIG 0x59 +#define BT_EVENT_HOST_SLEEP_ENABLE 0x5A +#define BT_EVENT_MODULE_CFG_REQ 0x5B +#define BT_EVENT_POWER_STATE 0x20 + +/* Bluetooth Power States */ +#define BT_PS_ENABLE 0x02 +#define BT_PS_DISABLE 0x03 +#define BT_PS_SLEEP 0x01 + +/* Host Sleep states */ +#define HS_ACTIVATED 0x01 +#define HS_DEACTIVATED 0x00 + +/* Power Save modes */ +#define PS_SLEEP 0x01 +#define PS_AWAKE 0x00 + +#define BT_CAL_HDR_LEN 4 +#define BT_CAL_DATA_SIZE 28 + +#define FW_DUMP_BUF_SIZE (1024*512) + +#define FW_DUMP_FILE_NAME_SIZE 64 + +#define EVENT_COMPARE_SIZE 64 + + +/* #define SAVE_FW_DUMP_IN_KERNEL 1 */ + +/* stpbt device node */ +#define BT_NODE "stpbt" +#define BT_DRIVER_NAME "BT_chrdev" + +struct btmtk_event { + u8 ec; /* event counter */ + u8 length; + u8 data[4]; +} __packed; + +/* Prototype of global function */ + +struct btmtk_private *btmtk_add_card(void *card); +int btmtk_remove_card(struct btmtk_private *priv); + +void btmtk_interrupt(struct btmtk_private *priv); + +bool btmtk_check_evtpkt(struct btmtk_private *priv, struct sk_buff *skb); +int btmtk_process_event(struct btmtk_private *priv, struct sk_buff *skb); + +int btmtk_send_module_cfg_cmd(struct btmtk_private *priv, u8 subcmd); +int btmtk_pscan_window_reporting(struct btmtk_private *priv, u8 subcmd); +int btmtk_send_hscfg_cmd(struct btmtk_private *priv); +int btmtk_enable_ps(struct btmtk_private *priv); +int btmtk_prepare_command(struct btmtk_private *priv); +int btmtk_enable_hs(struct btmtk_private *priv); +void btmtk_firmware_dump(struct btmtk_private *priv); + +#define META_BUFFER_SIZE (1024*50) + +struct _OSAL_UNSLEEPABLE_LOCK_ { + spinlock_t lock; + unsigned long flag; +}; + +struct ring_buffer { + struct _OSAL_UNSLEEPABLE_LOCK_ spin_lock; + u8 buffer[META_BUFFER_SIZE]; /* MTKSTP_BUFFER_SIZE:1024 */ + u32 read_p; /* indicate the current read index */ + u32 write_p; /* indicate the current write index */ +}; + +#ifdef CONFIG_DEBUG_FS + +#define FIXED_STPBT_MAJOR_DEV_ID 111 + + + +#define FW_DUMP_END_EVENT "coredump end" + +#endif + +#endif + diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_fw_log.c b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_fw_log.c new file mode 100644 index 0000000000000..e9530b76638f9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_fw_log.c @@ -0,0 +1,479 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH +#define PFX "[BTFWLOG]" +#include "btmtk_chip_if.h" +#include "btmtk_main.h" +#include "connsys_debug_utility.h" + + +MODULE_LICENSE("Dual BSD/GPL"); + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define BT_LOG_NODE_NAME "fw_log_bt" + +#define BT_FW_LOG_IOC_MAGIC (0xfc) +#define BT_FW_LOG_IOCTL_ON_OFF _IOW(BT_FW_LOG_IOC_MAGIC, 0, int) +#define BT_FW_LOG_IOCTL_SET_LEVEL _IOW(BT_FW_LOG_IOC_MAGIC, 1, int) +#define BT_FW_LOG_IOCTL_GET_LEVEL _IOW(BT_FW_LOG_IOC_MAGIC, 2, int) + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* + * Flags to mark for BT state and log state. + */ +#define OFF 0x00 +#define ON 0xFF + +/* + * BT Logger Tool will turn on/off Firmware Picus log, and set 3 log levels (Low, SQC and Debug) + * For extention capability, driver does not check the value range. + * + * Combine log state and log level to below settings: + * - 0x00: OFF + * - 0x01: Low Power + * - 0x02: SQC + * - 0x03: Debug + */ +#define DEFAULT_LEVEL 0x02 + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +static struct btmtk_dev *g_bdev; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static struct cdev log_cdev; +#if CREATE_NODE_DYNAMIC +static struct class *log_class; +static struct device *log_dev; +#endif +static dev_t devno; + +static wait_queue_head_t BT_log_wq; + +static struct semaphore ioctl_mtx; + +/* Global variables to save BT function and log status */ +static uint8_t g_bt_on = OFF; +static uint8_t g_log_on = OFF; +static uint8_t g_log_level = DEFAULT_LEVEL; +static uint8_t g_log_current = OFF; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +static int32_t ascii_to_hex(uint8_t ascii, uint8_t *hex) +{ + int32_t ret = 0; + + if('0' <= ascii && ascii <= '9') + *hex = ascii - '0'; + else if ('a' <= ascii && ascii <= 'f') + *hex = ascii - 'a' + 10; + else if ('A' <= ascii && ascii <= 'F') + *hex = ascii - 'A' + 10; + else + ret = -1; + + return ret; +} + +/* btmtk_send_utc_sync_cmd + * + * Send time sync command to FW to synchronize time + * + * Arguments: + * [IN] hdev - hci_device as control structure during BT life cycle + * + * Return Value: + * N/A + * + */ +int32_t btmtk_send_utc_sync_cmd(void) +{ + struct bt_internal_cmd *p_inter_cmd = &g_bdev->internal_cmd; + uint8_t cmd[] = {0x01, 0x6F, 0xFC, 0x01, 0x0C, + 0xF0, 0x09, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, /* UTC time second unit */ + 0x00, 0x00, 0x00, 0x00}; /* UTC time microsecond unit*/ + uint32_t sec, usec; + /* uint8_t evt[] = {0x04, 0xE4, 0x06, 0x02, 0xF0, 0x02, 0x00, 0x02, 0x00}; */ + + BTMTK_INFO("[InternalCmd] %s", __func__); + down(&g_bdev->internal_cmd_sem); + g_bdev->event_intercept = TRUE; + + connsys_log_get_utc_time(&sec, &usec); + memcpy(cmd + 9, &sec, sizeof(uint32_t)); + memcpy(cmd + 9 + sizeof(uint32_t), &usec, sizeof(uint32_t)); + + p_inter_cmd->waiting_event = 0xE4; + p_inter_cmd->pending_cmd_opcode = 0xFC6F; + p_inter_cmd->wmt_opcode = WMT_OPCODE_0XF0; + p_inter_cmd->result = WMT_EVT_INVALID; + + btmtk_main_send_cmd(g_bdev->hdev, cmd, sizeof(cmd), + BTMTKUART_TX_WAIT_VND_EVT); + + g_bdev->event_intercept = FALSE; + up(&g_bdev->internal_cmd_sem); + BTMTK_INFO("[InternalCmd] %s done, result = %s", __func__, _internal_evt_result(p_inter_cmd->result)); + return 0; +} + +/** + * \brief: set_fw_log + * + * \details + * Send an MTK vendor specific command to configure Firmware Picus log: + * - enable, disable, or set it to a particular level. + * + * The command format is conventional as below: + * + * 5D FC = TCI_MTK_DEBUG_VERSION_INFO + * 04 = Command Length + * 01 00 01 XX = Refer to table + * XX = Log Level + * + * If configured to return a vendor specific event, the event format is as below: + * + * FF = HCI_MTK_TRACE_EVENT + * 08 = Event Length + * FE = TCI_HOST_DRIVER_LOG_EVENT + * 5D FC = TCI_MTK_DEBUG_VERSION_INFO + * 00 = Success + * 01 00 01 XX = Refer to table + * + * +----------------------------+-----------------------+--------------+--------------------+ + * | Return Type | Op Code | Log Type | Log Level | + * +----------------------------+-----------------------+--------------+--------------------+ + * | 1 byte | 1 byte | 1 byte | 1 byte | + * +----------------------------+-----------------------+--------------+--------------------+ + * | 0x00 Command Complete | 0x00 Config Picus Log | 0x00 Via HCI | 0x00 Disable | + * | 0x01 Vendor Specific Event | | 0x01 Via EMI | 0x01 Low Power | + * | 0x02 No Event | | | 0x02 SQC (Default) | + * | | | | 0x03 Debug (Full) | + * +----------------------------+-----------------------+--------------+--------------------+ + * + * \param + * @flag: F/W log level + * + * \return + * 0: success; nagtive: fail + */ +static int32_t set_fw_log(uint8_t flag) +{ + int32_t ret; + uint8_t HCI_CMD_FW_LOG_DEBUG[] = {0x01, 0x5d, 0xfc, 0x04, 0x02, 0x00, 0x01, 0xff}; + + if (g_bdev->rst_level != RESET_LEVEL_NONE) { + BTMTK_WARN("Resetting, skip set_fw_log [%d]", flag); + return -1; + } + + HCI_CMD_FW_LOG_DEBUG[7] = flag; + BTMTK_DBG("hci_cmd: %02x %02x %02x %02x %02x %02x %02x %02x\n", + HCI_CMD_FW_LOG_DEBUG[0], HCI_CMD_FW_LOG_DEBUG[1], + HCI_CMD_FW_LOG_DEBUG[2], HCI_CMD_FW_LOG_DEBUG[3], + HCI_CMD_FW_LOG_DEBUG[4], HCI_CMD_FW_LOG_DEBUG[5], + HCI_CMD_FW_LOG_DEBUG[6], HCI_CMD_FW_LOG_DEBUG[7]); + + down(&g_bdev->internal_cmd_sem); + ret = btmtk_main_send_cmd(g_bdev->hdev, HCI_CMD_FW_LOG_DEBUG, + sizeof(HCI_CMD_FW_LOG_DEBUG), + BTMTKUART_TX_SKIP_VENDOR_EVT); + up(&g_bdev->internal_cmd_sem); + + if (ret < 0) { + BTMTK_ERR("Send F/W log cmd failed!\n"); + return ret; + } + return 0; +} + +static void fw_log_bt_state_cb(enum bt_state state) +{ + uint8_t on_off; + + on_off = (state == FUNC_ON) ? ON : OFF; + BTMTK_DBG("bt_on(0x%x) state(%d) on_off(0x%x)\n", g_bt_on, state, on_off); + + if (g_bt_on != on_off) { + // changed + if (on_off == OFF) { // should turn off + g_bt_on = OFF; + BTMTK_INFO("BT func off, no need to send hci cmd\n"); + } else { + g_bt_on = ON; + if(g_log_current) { + set_fw_log(g_log_current); + btmtk_send_utc_sync_cmd(); + } + } + } +} + +static long fw_log_bt_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + long retval = 0; + uint8_t log_tmp = OFF; + + down(&ioctl_mtx); + switch (cmd) { + case BT_FW_LOG_IOCTL_ON_OFF: + /* Connsyslogger daemon dynamically enable/disable Picus log */ + BTMTK_INFO("[ON_OFF]arg(%lu) bt_on(0x%x) log_on(0x%x) level(0x%x) log_cur(0x%x)\n", + arg, g_bt_on, g_log_on, g_log_level, g_log_current); + log_tmp = (arg == 0) ? OFF : ON; + if (log_tmp == g_log_on) // no change + break; + else { // changed + g_log_on = log_tmp; + g_log_current = g_log_on & g_log_level; + if (g_bt_on) { + retval = set_fw_log(g_log_current); + btmtk_send_utc_sync_cmd(); + } + } + break; + case BT_FW_LOG_IOCTL_SET_LEVEL: + /* Connsyslogger daemon dynamically set Picus log level */ + BTMTK_INFO("[SET_LEVEL]arg(%lu) bt_on(0x%x) log_on(0x%x) level(0x%x) log_cur(0x%x)\n", + arg, g_bt_on, g_log_on, g_log_level, g_log_current); + log_tmp = (uint8_t)arg; + if(log_tmp == g_log_level) // no change + break; + else { + g_log_level = log_tmp; + g_log_current = g_log_on & g_log_level; + if (g_bt_on & g_log_on) { + // driver on and log on + retval = set_fw_log(g_log_current); + btmtk_send_utc_sync_cmd(); + } + } + break; + case BT_FW_LOG_IOCTL_GET_LEVEL: + retval = g_log_level; + BTMTK_INFO("[GET_LEVEL]return %ld\n", retval); + break; + default: + BTMTK_ERR("Unknown cmd: 0x%08x\n", cmd); + retval = -EOPNOTSUPP; + break; + } + + up(&ioctl_mtx); + return retval; +} + +static long fw_log_bt_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + return fw_log_bt_unlocked_ioctl(filp, cmd, arg); +} + +static void fw_log_bt_event_cb(void) +{ + BTMTK_DBG("fw_log_bt_event_cb"); + wake_up_interruptible(&BT_log_wq); +} + +static unsigned int fw_log_bt_poll(struct file *file, poll_table *wait) +{ + uint32_t mask = 0; + + poll_wait(file, &BT_log_wq, wait); + if (connsys_log_get_buf_size(CONN_DEBUG_TYPE_BT) > 0) { + mask = (POLLIN | POLLRDNORM); + } + return mask; +} + +static ssize_t fw_log_bt_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) +{ +#define BT_LOG_BUFFER_SIZE 512 + + ssize_t retval; + static uint8_t tmp_buf[BT_LOG_BUFFER_SIZE]; + uint8_t hci_cmd[1024] = {0}; + uint8_t tmp = 0, tmp_h = 0; + uint32_t i = 0, j = 0, k = 0; + + if(count >= BT_LOG_BUFFER_SIZE) { + BTMTK_ERR("write count %zd exceeds max buffer size %d", count, BT_LOG_BUFFER_SIZE); + retval = -EINVAL; + goto OUT; + } + + if (copy_from_user(tmp_buf, buf, count)) { + BTMTK_ERR("copy_from_user failed!\n"); + retval = -EFAULT; + } else { + BTMTK_INFO("adb input: %s, len %zd\n", tmp_buf, strlen(tmp_buf)); + if (0 == memcmp(tmp_buf, "raw-hex,", strlen("raw-hex,"))) { + /* Skip prefix */ + for(i = strlen("raw-hex,"); i < strlen(tmp_buf); i++) { + if(tmp_buf[i] == ' ') // get space + continue; + else if(tmp_buf[i] == '\r' || tmp_buf[i] =='\n') // get 0x0a('\n') or 0x0d('\r') + break; + /* Two input char should turn into one byte */ + if (ascii_to_hex(tmp_buf[i], &tmp) == 0) { + if (j%2 == 0) + tmp_h = tmp; + else { + hci_cmd[k] = tmp_h * 16 + tmp; + BTMTK_DBG("hci_cmd[%u] = 0x%02x\n", k, hci_cmd[k]); + k++; + } + } else { + BTMTK_ERR("get unexpected char %c\n", tmp_buf[i]); + retval = -EINVAL; + goto OUT; + } + j++; + } + } + /* Only send F/W log cmd when BT func on */ + if (g_bt_on) { + retval = btmtk_main_send_cmd(g_bdev->hdev, hci_cmd, k, BTMTKUART_TX_SKIP_VENDOR_EVT); + } + else { + BTMTK_ERR("BT func off, skip to send F/W log cmd\n"); + retval = -EIO; + } + } + +OUT: + return (retval < 0) ? retval : count; +} + +static ssize_t fw_log_bt_read(struct file *filp, char __user *buf, size_t len, loff_t *f_pos) +{ + size_t retval = 0; + + retval = connsys_log_read_to_user(CONN_DEBUG_TYPE_BT, buf, len); + BTMTK_DBG("BT F/W log from Connsys, len %zd\n", retval); + return retval; +} + +static int fw_log_bt_open(struct inode *inode, struct file *file) +{ + BTMTK_INFO("major %d minor %d (pid %d)\n", imajor(inode), iminor(inode), current->pid); + return 0; +} + +static int fw_log_bt_close(struct inode *inode, struct file *file) +{ + BTMTK_INFO("major %d minor %d (pid %d)\n", imajor(inode), iminor(inode), current->pid); + return 0; +} + +struct file_operations log_fops = { + .open = fw_log_bt_open, + .release = fw_log_bt_close, + .read = fw_log_bt_read, + .write = fw_log_bt_write, + .unlocked_ioctl = fw_log_bt_unlocked_ioctl, + .compat_ioctl = fw_log_bt_compat_ioctl, + .poll = fw_log_bt_poll +}; + +int fw_log_bt_init(struct hci_dev *hdev) +{ + int32_t alloc_err = 0; + int32_t cdv_err = 0; + + BTMTK_INFO("%s", __func__); + g_bdev = hci_get_drvdata(hdev); + connsys_log_init(CONN_DEBUG_TYPE_BT); + connsys_log_register_event_cb(CONN_DEBUG_TYPE_BT, fw_log_bt_event_cb); + + init_waitqueue_head(&BT_log_wq); + sema_init(&ioctl_mtx, 1); + + /* Allocate char device */ + alloc_err = alloc_chrdev_region(&devno, 0, 1, BT_LOG_NODE_NAME); + if (alloc_err) { + BTMTK_ERR("Failed to register device numbers\n"); + goto alloc_error; + } + + cdev_init(&log_cdev, &log_fops); + log_cdev.owner = THIS_MODULE; + + cdv_err = cdev_add(&log_cdev, devno, 1); + if (cdv_err) + goto cdv_error; + +#if CREATE_NODE_DYNAMIC /* mknod replace */ + log_class = class_create(THIS_MODULE, BT_LOG_NODE_NAME); + if (IS_ERR(log_class)) + goto create_node_error; + + log_dev = device_create(log_class, NULL, devno, NULL, BT_LOG_NODE_NAME); + if (IS_ERR(log_dev)) + goto create_node_error; +#endif + + g_bdev->state_change_cb[0] = fw_log_bt_state_cb; + BTMTK_INFO("%s driver(major %d, minor %d) installed\n", + BT_LOG_NODE_NAME, MAJOR(devno), MINOR(devno)); + + return 0; + +#if CREATE_NODE_DYNAMIC +create_node_error: + if (log_class && !IS_ERR(log_class)) { + class_destroy(log_class); + log_class = NULL; + } + + cdev_del(&log_cdev); +#endif + +cdv_error: + unregister_chrdev_region(devno, 1); + +alloc_error: + connsys_log_deinit(CONN_DEBUG_TYPE_BT); + return -1; +} + +void fw_log_bt_exit(void) +{ +#if CREATE_NODE_DYNAMIC + if (log_dev && !IS_ERR(log_dev)) { + device_destroy(log_class, devno); + log_dev = NULL; + } + if (log_class && !IS_ERR(log_class)) { + class_destroy(log_class); + log_class = NULL; + } +#endif + + cdev_del(&log_cdev); + unregister_chrdev_region(devno, 1); + + g_bdev->state_change_cb[0] = NULL; + connsys_log_deinit(CONN_DEBUG_TYPE_BT); + + BTMTK_INFO("%s driver removed\n", BT_LOG_NODE_NAME); +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_irq.c b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_irq.c new file mode 100644 index 0000000000000..310bd69850395 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_irq.c @@ -0,0 +1,381 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#include +#include + +#include +#include +#include + +#include "btmtk_chip_if.h" +#include "btmtk_mt66xx_reg.h" +#include "conninfra.h" +#include "connsys_debug_utility.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 +******************************************************************************** +*/ +extern struct btmtk_dev *g_bdev; +static struct bt_irq_ctrl bgf2ap_btif_wakeup_irq = {.name = "BTIF_WAKEUP_IRQ"}; +static struct bt_irq_ctrl bgf2ap_sw_irq = {.name = "BGF_SW_IRQ"}; +static struct bt_irq_ctrl *bt_irq_table[BGF2AP_IRQ_MAX]; +static struct work_struct rst_trigger_work; + + +/******************************************************************************* +* 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 (USE_DEVICE_NODE == 0) +/* bt_report_hw_error() + * + * Insert an event to stack to report error while recovering from chip reset + * + * Arguments: + * N/A + * + * Return Value: + * 0 if success, otherwise error code + * + */ +void bt_report_hw_error() +{ + const uint8_t HCI_EVT_HW_ERROR[] = {0x04, 0x10, 0x01, 0x00}; + btmtk_recv(g_bdev->hdev, HCI_EVT_HW_ERROR, sizeof(HCI_EVT_HW_ERROR)); +} +#endif + +/* bt_reset_work + * + * A work thread that handles BT subsys reset request + * + * Arguments: + * [IN] work + * + * Return Value: + * N/A + * + */ +static void bt_reset_work(struct work_struct *work) +{ + BTMTK_INFO("Trigger subsys reset"); + bt_chip_reset_flow(RESET_LEVEL_0_5, CONNDRV_TYPE_BT, "Subsys reset"); +} + +/* bt_trigger_reset + * + * Trigger reset (could be subsys or whole chip reset) + * + * Arguments: + * N/A + * + * Return Value: + * N/A + * + */ +void bt_trigger_reset(void) +{ + int32_t ret = conninfra_is_bus_hang(); + + BTMTK_INFO("%s: conninfra_is_bus_hang ret = %d", __func__, ret); + + if (ret > 0) + conninfra_trigger_whole_chip_rst(CONNDRV_TYPE_BT, "bus hang"); + else if (ret == CONNINFRA_ERR_RST_ONGOING) + BTMTK_INFO("whole chip reset is onging, skip subsys reset"); + else + schedule_work(&rst_trigger_work); +} + +/* bt_bgf2ap_irq_handler + * + * Handling BGF2AP_SW_IRQ, include FW log & chip reset + * Please be noticed this handler is running in bt thread + * not interrupt thread + * + * Arguments: + * N/A + * + * Return Value: + * N/A + * + */ +void bt_bgf2ap_irq_handler(void) +{ + int32_t ret, mailbox_status = 0, bgf_status = 0; + + g_bdev->bgf2ap_ind = FALSE; + /* 1. Check conninfra bus before accessing BGF's CR */ + if (!conninfra_reg_readable()) { + ret = conninfra_is_bus_hang(); + if (ret > 0) { + BTMTK_ERR("conninfra bus is hang, needs reset"); + conninfra_trigger_whole_chip_rst(CONNDRV_TYPE_BT, "bus hang"); + return; + } + BTMTK_ERR("conninfra not readable, but not bus hang ret = %d", ret); + } + + /* 2. Check bgf bus status */ + if (bt_is_bgf_bus_timeout()) { + bt_dump_bgfsys_all(); + return; + } + + /* 3. Read IRQ status CR to identify what happens */ + bgf_status = REG_READL(BGF_SW_IRQ_STATUS); + if (!(bgf_status & BGF_FW_LOG_NOTIFY)) { + BTMTK_INFO("bgf_status = 0x%08x", bgf_status); + } + + if (bgf_status == 0xDEADFEED) { + bt_dump_bgfsys_all(); + bt_enable_irq(BGF2AP_SW_IRQ); + } else if (bgf_status & BGF_SUBSYS_CHIP_RESET) { + SET_BIT(BGF_SW_IRQ_RESET_ADDR, BGF_SUBSYS_CHIP_RESET); + if (g_bdev->rst_level != RESET_LEVEL_NONE) + complete(&g_bdev->rst_comp); + else + schedule_work(&rst_trigger_work); + } else if (bgf_status & BGF_FW_LOG_NOTIFY) { + /* FW notify host to get FW log */ + SET_BIT(BGF_SW_IRQ_RESET_ADDR, BGF_FW_LOG_NOTIFY); + connsys_log_irq_handler(CONN_DEBUG_TYPE_BT); + bt_enable_irq(BGF2AP_SW_IRQ); + } else if (bgf_status & BGF_WHOLE_CHIP_RESET) { + conninfra_trigger_whole_chip_rst(CONNDRV_TYPE_BT, "FW trigger"); + } else { + BTMTK_WARN("uknown case"); + bt_enable_irq(BGF2AP_SW_IRQ); + } +} + + +/* btmtk_reset_init() + * + * Inint work thread for subsys chip reset + * + * Arguments: + * N/A + * + * Return Value: + * N/A + * + */ +void btmtk_reset_init(void) +{ + INIT_WORK(&rst_trigger_work, bt_reset_work); +} + +/* btmtk_irq_handler() + * + * IRQ handler, process following types IRQ + * BGF2AP_BTIF_WAKEUP_IRQ - this IRQ indicates that FW has data to transmit + * BGF2AP_SW_IRQ - this indicates that fw assert / fw log + * + * Arguments: + * [IN] irq - IRQ number + * [IN] arg - + * + * Return Value: + * returns IRQ_HANDLED for handled IRQ, IRQ_NONE otherwise + * + */ +static irqreturn_t btmtk_irq_handler(int irq, void * arg) +{ + if (irq == bgf2ap_btif_wakeup_irq.irq_num) { + if (g_bdev->rst_level == RESET_LEVEL_NONE) { + bt_disable_irq(BGF2AP_BTIF_WAKEUP_IRQ); + g_bdev->rx_ind = TRUE; + g_bdev->psm.sleep_flag = FALSE; + wake_up_interruptible(&g_bdev->tx_waitq); + } + return IRQ_HANDLED; + } else if (irq == bgf2ap_sw_irq.irq_num) { + bt_disable_irq(BGF2AP_SW_IRQ); + g_bdev->bgf2ap_ind = TRUE; + wake_up_interruptible(&g_bdev->tx_waitq); + return IRQ_HANDLED; + } + return IRQ_NONE; +} + +/* bt_request_irq() + * + * Request IRQ + * + * Arguments: + * [IN] irq_type - IRQ type + * + * Return Value: + * returns 0 for success, fail otherwise + * + */ +int32_t bt_request_irq(enum bt_irq_type irq_type) +{ + uint32_t irq_num = 0; + int32_t ret = 0; + unsigned long irq_flags = 0; + struct bt_irq_ctrl *pirq = NULL; + struct device_node *node = NULL; + + switch (irq_type) { + case BGF2AP_BTIF_WAKEUP_IRQ: + node = of_find_compatible_node(NULL, NULL, "mediatek,bt"); + if (node) { + irq_num = irq_of_parse_and_map(node, 0); + BTMTK_INFO("irqNum of BGF2AP_BTIF_WAKEUP_IRQ = %d", irq_num); + } + else + BTMTK_ERR("WIFI-OF: get bt device node fail"); + + irq_flags = IRQF_TRIGGER_HIGH | IRQF_SHARED; + pirq = &bgf2ap_btif_wakeup_irq; + break; + case BGF2AP_SW_IRQ: + node = of_find_compatible_node(NULL, NULL, "mediatek,bt"); + if (node) { + irq_num = irq_of_parse_and_map(node, 1); + BTMTK_INFO("irqNum of BGF2AP_SW_IRQ = %d", irq_num); + } + else + BTMTK_ERR("WIFI-OF: get bt device node fail"); + irq_flags = IRQF_TRIGGER_HIGH | IRQF_SHARED; + pirq = &bgf2ap_sw_irq; + break; + default: + BTMTK_ERR("Invalid irq_type %d!", irq_type); + return -EINVAL; + } + + BTMTK_INFO("pirq = %p, flag = 0x%08x", pirq, irq_flags); + ret = request_irq(irq_num, btmtk_irq_handler, irq_flags, + pirq->name, pirq); + if (ret) { + BTMTK_ERR("Request %s (%u) failed! ret(%d)", pirq->name, irq_num, ret); + return ret; + } + + BTMTK_INFO("Request %s (%u) succeed", pirq->name, irq_num); + bt_irq_table[irq_type] = pirq; + pirq->irq_num = irq_num; + pirq->active = TRUE; + spin_lock_init(&pirq->lock); + return 0; +} + +/* bt_enable_irq() + * + * Enable IRQ + * + * Arguments: + * [IN] irq_type - IRQ type + * + * Return Value: + * N/A + * + */ +void bt_enable_irq(enum bt_irq_type irq_type) +{ + struct bt_irq_ctrl *pirq; + + if (irq_type >= BGF2AP_IRQ_MAX) { + BTMTK_ERR("Invalid irq_type %d!", irq_type); + return; + } + + pirq = bt_irq_table[irq_type]; + if (pirq) { + spin_lock_irqsave(&pirq->lock, pirq->flags); + if (!pirq->active) { + enable_irq(pirq->irq_num); + pirq->active = TRUE; + } + spin_unlock_irqrestore(&pirq->lock, pirq->flags); + } +} + +/* bt_disable_irq() + * + * Disable IRQ + * + * Arguments: + * [IN] irq_type - IRQ type + * + * Return Value: + * N/A + * + */ +void bt_disable_irq(enum bt_irq_type irq_type) +{ + struct bt_irq_ctrl *pirq; + + if (irq_type >= BGF2AP_IRQ_MAX) { + BTMTK_ERR("Invalid irq_type %d!", irq_type); + return; + } + + pirq = bt_irq_table[irq_type]; + if (pirq) { + spin_lock_irqsave(&pirq->lock, pirq->flags); + if (pirq->active) { + disable_irq_nosync(pirq->irq_num); + pirq->active = FALSE; + } + spin_unlock_irqrestore(&pirq->lock, pirq->flags); + } +} + + +/* bt_disable_irq() + * + * Release IRQ and de-register IRQ + * + * Arguments: + * [IN] irq_type - IRQ type + * + * Return Value: + * N/A + * + */ +void bt_free_irq(enum bt_irq_type irq_type) +{ + struct bt_irq_ctrl *pirq; + + if (irq_type >= BGF2AP_IRQ_MAX) { + BTMTK_ERR("Invalid irq_type %d!", irq_type); + return; + } + + pirq = bt_irq_table[irq_type]; + if (pirq) { + free_irq(pirq->irq_num, pirq); + pirq->active = FALSE; + bt_irq_table[irq_type] = NULL; + } +} diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_main.c b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_main.c new file mode 100644 index 0000000000000..c13910c233208 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_main.c @@ -0,0 +1,879 @@ +/** + * Copyright (c) 2018 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include "btmtk_define.h" +#include "btmtk_main.h" +#include "btmtk_drv.h" +#include "btmtk_chip_if.h" + +#define MTKBT_UNSLEEPABLE_LOCK(x, y) spin_lock_irqsave(x, y) +#define MTKBT_UNSLEEPABLE_UNLOCK(x, y) spin_unlock_irqsave(x, y) +#define HCI_COMMAND_COMPLETE_EVT 0x0E +#define HCI_COMMAND_STATUS_EVT 0x0F + +/** + * Global parameters(mtkbt_) + */ +uint8_t btmtk_log_lvl = BTMTK_LOG_LVL_DEF; +struct bt_dbg_st g_bt_dbg_st; + +static int main_init(void) +{ + return 0; +} + +static int main_exit(void) +{ + return 0; +} + +/* HCI receive mechnism */ + + +static inline struct sk_buff *h4_recv_buf(struct hci_dev *hdev, + struct sk_buff *skb, + const unsigned char *buffer, + int count, + const struct h4_recv_pkt *pkts, + int pkts_count) +{ + /* Check for error from previous call */ + if (IS_ERR(skb)) + skb = NULL; + + while (count) { + int i, len; + + if (!skb) { + for (i = 0; i < pkts_count; i++) { + if (buffer[0] != (&pkts[i])->type) + continue; + + skb = bt_skb_alloc((&pkts[i])->maxlen, + GFP_ATOMIC); + if (!skb) + return ERR_PTR(-ENOMEM); + + hci_skb_pkt_type(skb) = (&pkts[i])->type; + hci_skb_expect(skb) = (&pkts[i])->hlen; + break; + } + + /* Check for invalid packet type */ + if (!skb) { + BTMTK_ERR("skb is NULL"); + btmtk_set_sleep(hdev, FALSE); + return ERR_PTR(-EILSEQ); + } + + count -= 1; + buffer += 1; + } + + len = min_t(uint, hci_skb_expect(skb) - skb->len, count); + memcpy(skb_put(skb, len), buffer, len); + /* + If kernel version > 4.x + skb_put_data(skb, buffer, len); + */ + + count -= len; + buffer += len; + + /* Check for partial packet */ + if (skb->len < hci_skb_expect(skb)) + continue; + + for (i = 0; i < pkts_count; i++) { + if (hci_skb_pkt_type(skb) == (&pkts[i])->type) + break; + } + + if (i >= pkts_count) { + BTMTK_ERR("i (%d) >= pkts_count (%d)", i, pkts_count); + kfree_skb(skb); + btmtk_set_sleep(hdev, FALSE); + return ERR_PTR(-EILSEQ); + } + + if (skb->len == (&pkts[i])->hlen) { + u16 dlen; + + switch ((&pkts[i])->lsize) { + case 0: + /* No variable data length */ + dlen = 0; + break; + case 1: + /* Single octet variable length */ + dlen = skb->data[(&pkts[i])->loff]; + hci_skb_expect(skb) += dlen; + + if (skb_tailroom(skb) < dlen) { + BTMTK_ERR("1. skb_tailroom(skb) < dlen (%d)", dlen); + kfree_skb(skb); + btmtk_set_sleep(hdev, FALSE); + return ERR_PTR(-EMSGSIZE); + } + break; + case 2: + /* Double octet variable length */ + dlen = get_unaligned_le16(skb->data + + (&pkts[i])->loff); + /* parse ISO packet len*/ + if ((&pkts[i])->type == HCI_ISODATA_PKT) { + unsigned char *cp = (unsigned char *)&dlen + 1; + *cp = *cp & 0x3F; + } + hci_skb_expect(skb) += dlen; + + if (skb_tailroom(skb) < dlen) { + BTMTK_ERR("2. skb_tailroom(skb) < dlen (%d)", dlen); + kfree_skb(skb); + btmtk_set_sleep(hdev, FALSE); + return ERR_PTR(-EMSGSIZE); + } + break; + default: + /* Unsupported variable length */ + BTMTK_ERR("Unsupported variable length"); + kfree_skb(skb); + btmtk_set_sleep(hdev, FALSE); + return ERR_PTR(-EILSEQ); + } + + if (!dlen) { + /* No more data, complete frame */ + (&pkts[i])->recv(hdev, skb); + btmtk_set_sleep(hdev, FALSE); + if (skb) + kfree_skb(skb); + skb = NULL; + } + } else { + /* Complete frame */ + (&pkts[i])->recv(hdev, skb); + btmtk_set_sleep(hdev, FALSE); + if (skb) + kfree_skb(skb); + skb = NULL; + } + } + + return skb; +} + +static const struct h4_recv_pkt mtk_recv_pkts[] = { + { H4_RECV_ACL, .recv = btmtk_recv_acl }, + { H4_RECV_SCO, .recv = hci_recv_frame }, + { H4_RECV_EVENT, .recv = btmtk_recv_event }, + { H4_RECV_ISO, .recv = btmtk_recv_iso }, +}; +#if ENABLESTP +static inline struct sk_buff *mtk_add_stp(struct btmtk_dev *bdev, struct sk_buff *skb) +{ + struct mtk_stp_hdr *shdr; + int dlen, err = 0, type = 0; + u8 stp_crc[] = {0x00, 0x00}; + + if (unlikely(skb_headroom(skb) < sizeof(*shdr)) || + (skb_tailroom(skb) < MTK_STP_TLR_SIZE)) { + BTMTK_DBG("%s, add pskb_expand_head, headroom = %d, tailroom = %d", + __func__, skb_headroom(skb), skb_tailroom(skb)); + + err = pskb_expand_head(skb, sizeof(*shdr), MTK_STP_TLR_SIZE, + GFP_ATOMIC); + } + dlen = skb->len; + shdr = (void *) skb_push(skb, sizeof(*shdr)); + shdr->prefix = 0x80; + shdr->dlen = cpu_to_be16((dlen & 0x0fff) | (type << 12)); + shdr->cs = 0; + // Add the STP trailer + // kernel version > 4.20 + // skb_put_zero(skb, MTK_STP_TLR_SIZE); + // kernel version < 4.20 + skb_put(skb, sizeof(stp_crc)); + + return skb; +} + +static const unsigned char * +mtk_stp_split(struct btmtk_dev *bdev, const unsigned char *data, int count, + int *sz_h4) +{ + struct mtk_stp_hdr *shdr; + + /* The cursor is reset when all the data of STP is consumed out */ + if (!bdev->stp_dlen && bdev->stp_cursor >= 6) { + bdev->stp_cursor = 0; + BTMTK_ERR("reset cursor = %d\n", bdev->stp_cursor); + } + + /* Filling pad until all STP info is obtained */ + while (bdev->stp_cursor < 6 && count > 0) { + bdev->stp_pad[bdev->stp_cursor] = *data; + BTMTK_ERR("fill stp format (%02x, %d, %d)\n", + bdev->stp_pad[bdev->stp_cursor], bdev->stp_cursor, count); + bdev->stp_cursor++; + data++; + count--; + } + + /* Retrieve STP info and have a sanity check */ + if (!bdev->stp_dlen && bdev->stp_cursor >= 6) { + shdr = (struct mtk_stp_hdr *)&bdev->stp_pad[2]; + bdev->stp_dlen = be16_to_cpu(shdr->dlen) & 0x0fff; + BTMTK_ERR("stp format (%02x, %02x)", + shdr->prefix, bdev->stp_dlen); + + /* Resync STP when unexpected data is being read */ + if (shdr->prefix != 0x80 || bdev->stp_dlen > 2048) { + BTMTK_ERR("stp format unexpect (%02x, %02x)", + shdr->prefix, bdev->stp_dlen); + BTMTK_ERR("reset cursor = %d\n", bdev->stp_cursor); + bdev->stp_cursor = 2; + bdev->stp_dlen = 0; + } + } + + /* Directly quit when there's no data found for H4 can process */ + if (count <= 0) + return NULL; + + /* Tranlate to how much the size of data H4 can handle so far */ + *sz_h4 = min_t(int, count, bdev->stp_dlen); + + /* Update the remaining size of STP packet */ + bdev->stp_dlen -= *sz_h4; + + /* Data points to STP payload which can be handled by H4 */ + return data; +} +#endif + +#if (USE_DEVICE_NODE == 1) +void btmtk_rx_flush(void) +{ + rx_queue_flush(); +} + +uint8_t btmtk_rx_data_valid(void) +{ + return !is_rx_queue_empty(); +} + +int32_t btmtk_send_data(struct hci_dev *hdev, uint8_t *buf, uint32_t count) +{ + struct sk_buff *skb = NULL; + struct btmtk_dev *bdev = hci_get_drvdata(hdev); + + skb = alloc_skb(count + BT_SKB_RESERVE, GFP_KERNEL); + if (skb == NULL) { + BTMTK_ERR("%s allocate skb failed!!", __func__); + return -1; + } + + /* Reserv for core and drivers use */ + skb_reserve(skb , BT_SKB_RESERVE); + bt_cb(skb)->pkt_type = buf[0]; + memcpy(skb->data, buf, count); + skb->len = count; + + skb_queue_tail(&bdev->tx_queue, skb); + wake_up_interruptible(&bdev->tx_waitq); + + return count; +} + +void btmtk_register_rx_event_cb(struct btmtk_dev *bdev, BT_RX_EVENT_CB cb) +{ + bdev->rx_event_cb = cb; + btmtk_rx_flush(); +} + +int32_t btmtk_receive_data(struct hci_dev *hdev, uint8_t *buf, uint32_t count) +{ + uint32_t read_bytes; + + rx_dequeue(buf, count, &read_bytes); + /* TODO: disable quick PS mode by traffic density */ + return read_bytes; +} +#endif + +int btmtk_recv(struct hci_dev *hdev, const u8 *data, size_t count) +{ + struct btmtk_dev *bdev = hci_get_drvdata(hdev); + int err; +#if ENABLESTP + const unsigned char *p_left = data, *p_h4 = NULL; + int sz_left = count, sz_h4 = 0, adv = 0; + + while (sz_left > 0) { + /* The serial data received from MT7622 BT controller is + * at all time padded around with the STP header and tailer. + * + * A full STP packet is looking like + * ----------------------------------- + * | STP header | H:4 | STP tailer | + * ----------------------------------- + * but it doesn't guarantee to contain a full H:4 packet which + * means that it's possible for multiple STP packets forms a + * full H:4 packet that means extra STP header + length doesn't + * indicate a full H:4 frame, things can fragment. Whose length + * recorded in STP header just shows up the most length the + * H:4 engine can handle currently. + */ + p_h4 = mtk_stp_split(bdev, p_left, sz_left, &sz_h4); + if (!p_h4) + break; + + adv = p_h4 - p_left; + sz_left -= adv; + p_left += adv; + bdev->rx_skb = h4_recv_buf(bdev->hdev, bdev->rx_skb, p_h4, + sz_h4, mtk_recv_pkts, + ARRAY_SIZE(mtk_recv_pkts)); + + if (IS_ERR(bdev->rx_skb)) { + err = PTR_ERR(bdev->rx_skb); + BTMTK_ERR("Frame reassembly failed (%d)", err); + bdev->rx_skb = NULL; + return err; + } + + sz_left -= sz_h4; + p_left += sz_h4; + } +#else + bdev->rx_skb = h4_recv_buf(hdev, bdev->rx_skb, data, + count, mtk_recv_pkts, + ARRAY_SIZE(mtk_recv_pkts)); + + if (IS_ERR(bdev->rx_skb)) { + err = PTR_ERR(bdev->rx_skb); + BTMTK_ERR("Frame reassembly failed (%d)", err); + bdev->rx_skb = NULL; + return err; + } +#endif + + return 0; +} +int btmtk_dispatch_acl(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct btmtk_dev *bdev = hci_get_drvdata(hdev); + + if (skb->data[0]== 0x6f && skb->data[1]== 0xfc && skb->len > 12) { + /* coredump data done + * For Example : TotalTimeForDump=0xxxxxxx, (xx secs) + */ + if (skb->data[4]== 0x54 && skb->data[5] == 0x6F && + skb->data[6]== 0x74 && skb->data[7] == 0x61 && + skb->data[8]== 0x6C && skb->data[9] == 0x54 && + skb->data[10]== 0x69 && skb->data[11] == 0x6D && + skb->data[12]== 0x65) { + /* coredump end, do reset */ + BTMTK_INFO("%s coredump done", __func__); + msleep(3000); + bdev->subsys_reset= 1; + } + return 1; + } else if (skb->data[0]== 0xff && skb->data[1] == 0x05) { + BTMTK_DBG("%s correct picus log by ACL", __func__); + } + return 0; +} + +int btmtk_dispatch_event(struct hci_dev *hdev, struct sk_buff *skb) +{ + + /* For Picus */ + if (skb->data[0]== 0xff && skb->data[2] == 0x50) { + BTMTK_DBG("%s correct picus log format by EVT", __func__); + } + return btmtk_cif_dispatch_event(hdev, skb); +} + +int btmtk_recv_acl(struct hci_dev *hdev, struct sk_buff *skb) +{ + int err = 0, skip_pkt = 0; + + skip_pkt = btmtk_dispatch_acl(hdev, skb); + if(skip_pkt == 0) +#if (USE_DEVICE_NODE == 0) + err = hci_recv_frame(hdev, skb); +#else + err = rx_skb_enqueue(skb); +#endif + + return err; +} +#if (DRIVER_CMD_CHECK == 1) + +void btmtk_check_event(struct sk_buff *skb) +{ + u8 event_code = skb->data[0]; + u16 cmd_opcode; + + if(event_code == HCI_COMMAND_COMPLETE_EVT) { + cmd_opcode = (skb->data[3] << 8) | skb->data[4]; + + if(cmd_list_check(cmd_opcode) == FALSE) { + BTMTK_ERR("%s No match command %4X", __func__,cmd_opcode); + } else { + cmd_list_remove(cmd_opcode); + update_command_response_workqueue(); + } + } else if(event_code == HCI_COMMAND_STATUS_EVT) { + cmd_opcode = (skb->data[4] << 8) | skb->data[5]; + + if(cmd_list_check(cmd_opcode) == FALSE) { + BTMTK_ERR("%s No match command %4X", __func__,cmd_opcode); + } else { + cmd_list_remove(cmd_opcode); + update_command_response_workqueue(); + } + } +} +#endif + +int btmtk_recv_event(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct btmtk_dev *bdev = hci_get_drvdata(hdev); + int err = 0; + +#if (DRIVER_CMD_CHECK == 1) + if (bdev->cmd_timeout_check == TRUE) { + btmtk_check_event(skb); + } +#endif + +#if 0 + /* Fix up the vendor event id with 0xff for vendor specific instead + * of 0xe4 so that event send via monitoring socket can be parsed + * properly. + */ + if (hdr->evt == 0xe4) { + BTMTK_DBG("%s: hdr->evt is %02x", __func__, hdr->evt); + hdr->evt = HCI_EV_VENDOR; + } +#endif + + /* When someone waits for the WMT event, the skb is being cloned + * and being processed the events from there then. + */ + if (test_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state)) { + /* check is corresponding wmt event */ + if (btmtk_dispatch_event(hdev, skb) != WMT_EVT_SKIP) { + bdev->evt_skb = skb_copy(skb, GFP_KERNEL); + if (!bdev->evt_skb) { + err = -ENOMEM; + BTMTK_ERR("%s: WMT event copy to evt_skb failed, err = %d", __func__, err); + goto out; + } + + if (test_and_clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state)) { + BTMTK_DBG("%s: clear bit BTMTKUART_TX_WAIT_VND_EVT", __func__); + wake_up(&bdev->p_wait_event_q); + BTMTK_DBG("%s: wake_up p_wait_event_q", __func__); + } else { + BTMTK_ERR("%s: test_and_clear_bit(BTMTKUART_TX_WAIT_VND_EVT) fail", __func__); + if (bdev->evt_skb) + kfree_skb(bdev->evt_skb); + bdev->evt_skb = NULL; + } + goto out; + } else { + // may be normal packet, continue put skb to rx queue + BTMTK_INFO("%s: may be normal packet!", __func__); + } + } + + /* User trx debug function, put rx event to callbacl */ + if (g_bt_dbg_st.trx_enable) { + g_bt_dbg_st.trx_cb(skb->data, (int)skb->len); + } + +#if (USE_DEVICE_NODE == 0) + err = hci_recv_frame(hdev, skb); +#else + err = rx_skb_enqueue(skb); +#endif + + if (err < 0) { + BTMTK_ERR("%s: hci_recv_failed, err = %d", __func__, err); + } + return 0; + +out: + return err; +} + +int btmtk_recv_iso(struct hci_dev *hdev, struct sk_buff *skb) +{ + int err = 0; + +#if (USE_DEVICE_NODE == 0) + err = hci_recv_frame(hdev, skb); +#else + err = rx_skb_enqueue(skb); +#endif + return err; +} + + +int btmtk_main_send_cmd(struct hci_dev *hdev, const uint8_t *cmd, const int cmd_len, const int tx_state) +{ + struct sk_buff *skb = NULL; + struct btmtk_dev *bdev = hci_get_drvdata(hdev); + int ret = 0; + + skb = alloc_skb(cmd_len + BT_SKB_RESERVE, GFP_ATOMIC); + if (skb == NULL) { + BTMTK_ERR("%s allocate skb failed!!", __func__); + goto err_free_skb; + } + /* Reserv for core and drivers use */ + skb_reserve(skb , 7); + bt_cb(skb)->pkt_type = HCI_COMMAND_PKT; + memcpy(skb->data, cmd, cmd_len); + skb->len = cmd_len; + +#if ENABLESTP + skb = mtk_add_stp(bdev, skb); +#endif + + BTMTK_DBG_RAW(skb->data, skb->len, "%s, len = %d, send cmd: ", __func__, skb->len); + + set_bit(tx_state, &bdev->tx_state); +#if SUPPORT_BT_THREAD + skb_queue_tail(&bdev->tx_queue, skb); + wake_up_interruptible(&bdev->tx_waitq); +#else + btmtk_cif_send_cmd(hdev, skb->data, skb->len, 5, 0, 0); +#endif + ret = wait_event_timeout(bdev->p_wait_event_q, + bdev->evt_skb != NULL || tx_state == BTMTKUART_TX_SKIP_VENDOR_EVT, 2*HZ); + BTMTK_INFO("%s, ret = %d", __func__, ret); + +err_free_skb: +#if (SUPPORT_BT_THREAD == 0) + if (skb) + kfree_skb(skb); +#endif + if (tx_state == BTMTKUART_TX_WAIT_VND_EVT) { + if (bdev->evt_skb) + kfree_skb(bdev->evt_skb); + bdev->evt_skb = NULL; + } + + return ret; +} + +uint8_t *_internal_evt_result(u_int8_t wmt_evt_result) +{ + + if (wmt_evt_result == WMT_EVT_SUCCESS) + return "WMT_EVT_SUCCESS"; + else if (wmt_evt_result == WMT_EVT_FAIL) + return "WMT_EVT_FAIL"; + else if (wmt_evt_result == WMT_EVT_INVALID) + return "WMT_EVT_INVALID"; + else + return "WMT_EVT_SKIP"; +} + +int btmtk_load_code_from_bin(u8 **image, char *bin_name, + struct device *dev, u32 *code_len, u8 retry) +{ + const struct firmware *fw_entry = NULL; + int err = 0; + + do { + err = request_firmware(&fw_entry, bin_name, dev); + if (err == 0) { + break; + } else if (retry <= 0) { + *image = NULL; + BTMTK_ERR("%s: request_firmware %d times fail!!! err = %d", __func__, 10, err); + return -1; + } + BTMTK_ERR("%s: request_firmware fail!!! err = %d, retry = %d", __func__, err, retry); + msleep(100); + } while (retry-- > 0); + + *image = vmalloc(ALIGN_4(fw_entry->size)); + if (*image == NULL) { + *code_len = 0; + BTMTK_ERR("%s: vmalloc failed!! error code = %d", __func__, err); + return -1; + } + + memcpy(*image, fw_entry->data, fw_entry->size); + *code_len = fw_entry->size; + + release_firmware(fw_entry); + return 0; +} + +int btmtk_calibration_flow(struct hci_dev *hdev) +{ + int ret = 0; + ret = btmtk_send_calibration_cmd(hdev); + BTMTK_INFO("%s done", __func__); + return ret; +} + +#if ENABLESTP +static int btmtk_send_set_stp_cmd(struct hci_dev *hdev) +{ + u8 cmd[] = { 0x01, 0x6F, 0xFC, 0x09, 0x01, 0x04, 0x05, 0x00, 0x03, 0x11, 0x0E, 0x00, 0x00}; + /* To-Do, for event check */ + /* u8 event[] = { 0x04, 0xE4, 0x06, 0x02, 0x04, 0x02, 0x00, 0x00, 0x03}; */ + struct btmtk_dev *bdev = hci_get_drvdata(hdev); + + btmtk_main_send_cmd(hdev, cmd, sizeof(cmd), BTMTKUART_TX_WAIT_VND_EVT); + + BTMTK_INFO("%s done", __func__); + return 0; +} + +static int btmtk_send_set_stp1_cmd(struct hci_dev *hdev) +{ + u8 cmd[] = {0x01, 0x6F, 0xFC, 0x0C, 0x01, 0x08, 0x08, 0x00, 0x02, 0x01, 0x00, 0x01, 0x08, 0x00, 0x00, 0x80}; + /* To-Do, for event check */ + /* u8 event[] = {0x04, 0xE4, 0x10, 0x02, 0x08, + 0x0C, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x80, 0x63, 0x76, 0x00, 0x00}; */ + //struct btmtk_dev *bdev = hci_get_drvdata(hdev); + + btmtk_main_send_cmd(hdev, cmd, sizeof(cmd), BTMTKUART_TX_WAIT_VND_EVT); + + BTMTK_INFO("%s done", __func__); + return 0; +} +#endif + +/** + * Kernel HCI Interface Registeration + */ +static int bt_flush(struct hci_dev *hdev) +{ +#if SUPPORT_BT_THREAD + struct btmtk_dev *bdev = hci_get_drvdata(hdev); + + skb_queue_purge(&bdev->tx_queue); +#endif + return 0; +} + +int bt_close(struct hci_dev *hdev) +{ + BTMTK_INFO("%s", __func__); + + /* Power off */ + btmtk_set_power_off(hdev, FALSE); + clear_bit(HCI_RUNNING, &hdev->flags); + + return 0; +} + +static int bt_setup(struct hci_dev *hdev) +{ + int ret = 0; + struct btmtk_dev *bdev = hci_get_drvdata(hdev); + + BTMTK_INFO("%s", __func__); + + /* 1. Power on */ + ret = btmtk_set_power_on(hdev, FALSE); + if (ret) { + BTMTK_ERR("btmtk_set_power_on fail"); + return ret; + } +#if ENABLESTP + btmtk_send_set_stp_cmd(hdev); + btmtk_send_set_stp1_cmd(hdev); +#endif + + /* 3. Do calibration */ +#if 0 /* skip temporary for bring up state */ + ret = btmtk_calibration_flow(hdev); + if (ret) { + BTMTK_ERR("btmtk_calibration_flow fail"); + goto func_on_fail; + } +#endif + + /* Set bt to sleep mode */ + btmtk_set_sleep(hdev, TRUE); + + return 0; +} + +static int bt_open(struct hci_dev *hdev) +{ + int ret = 0; + BTMTK_INFO("%s", __func__); + + if (test_bit(HCI_RUNNING, &hdev->flags)) { + BTMTK_WARN("BT already on!\n"); + return -EIO; + } + +#if BLUEDROID + ret = bt_setup(hdev); +#endif + + if (!ret) + set_bit(HCI_RUNNING, &hdev->flags); + + BTMTK_INFO("HCI running bit = %d", test_bit(HCI_RUNNING, &hdev->flags)); + return ret; +} + +static int bt_send_frame(struct hci_dev *hdev, struct sk_buff *skb) +{ +#if SUPPORT_BT_THREAD + struct btmtk_dev *bdev = hci_get_drvdata(hdev); +#endif + + BTMTK_INFO("%s\n", __func__); + memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); +#if ENABLESTP + skb = mtk_add_stp(bdev, skb); +#endif + +#if SUPPORT_BT_THREAD + skb_queue_tail(&bdev->tx_queue, skb); + wake_up_interruptible(&bdev->tx_waitq); +#else + btmtk_cif_send_cmd(hdev, skb->data, skb->len, 5, 0, 0); +#endif + + return 0; +} + +int btmtk_allocate_hci_device(struct btmtk_dev *bdev, int hci_bus_type) +{ + struct hci_dev *hdev; +#if (USE_DEVICE_NODE == 0) + int err = 0; +#endif + + /* Add hci device */ + hdev = hci_alloc_dev(); + if (!hdev) + return -ENOMEM; + hdev->bus = hci_bus_type; + + bdev->hdev = hdev; + hci_set_drvdata(hdev, bdev); + + /* register hci callback */ + hdev->open = bt_open; + hdev->close = bt_close; + hdev->flush = bt_flush; + hdev->send = bt_send_frame; + hdev->setup = bt_setup; + + init_waitqueue_head(&bdev->p_wait_event_q); +#if SUPPORT_BT_THREAD + skb_queue_head_init(&bdev->tx_queue); +#endif +#if (USE_DEVICE_NODE == 0) + SET_HCIDEV_DEV(hdev, BTMTK_GET_DEV(bdev)); + + err = hci_register_dev(hdev); + /* After hci_register_dev completed + * It will set dev_flags to HCI_SETUP + * That cause vendor_lib create socket failed + */ + if (err < 0) { + BTMTK_INFO("%s can't register", __func__); + hci_free_dev(hdev); + return err; + } + + /*set_bit(HCI_RUNNING, &hdev->flags); + set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);*/ +#if BLUEDROID +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,4,0)) + clear_bit(HCI_SETUP, &hdev->dev_flags); +#else + hci_dev_clear_flag(hdev, HCI_SETUP); +#endif +#endif // BLUEDROID +#endif // USE_DEVICE_NODE == 0 + set_bit(BTMTKUART_REQUIRED_DOWNLOAD, &bdev->tx_state); + + BTMTK_INFO("%s done", __func__); + return 0; +} + +int32_t btmtk_free_hci_device(struct btmtk_dev *bdev, int hci_bus_type) +{ + hci_unregister_dev(bdev->hdev); + hci_free_dev(bdev->hdev); + + bdev->hdev = NULL; + return 0; +} + +#if (USE_DEVICE_NODE == 1) +#undef __init +#undef __exit +#define __init +#define __exit +#endif + +/** + * Kernel Module init/exit Functions + */ +int __init main_driver_init(void) +{ + int ret = -1; + + BTMTK_INFO("%s", __func__); + ret = main_init(); + if (ret < 0) + return ret; + + ret = btmtk_cif_register(); + if (ret < 0) { + BTMTK_ERR("*** USB registration failed(%d)! ***", ret); + return ret; + } + BTMTK_INFO("%s: Done", __func__); + return 0; +} + +void __exit main_driver_exit(void) +{ + BTMTK_INFO("%s", __func__); + btmtk_cif_deregister(); + main_exit(); +} + +#if (USE_DEVICE_NODE == 0) +module_init(main_driver_init); +module_exit(main_driver_exit); +#endif + +/** + * Module Common Information + */ +MODULE_DESCRIPTION("Mediatek Bluetooth Driver"); +MODULE_VERSION(VERSION SUBVER); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_main.h b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_main.h new file mode 100644 index 0000000000000..cb9b7f48bed2e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_main.h @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2018 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef __BTMTK_MAIN_H__ +#define __BTMTK_MAIN_H__ +#include "btmtk_define.h" +#include "btmtk_chip_if.h" + + +int btmtk_allocate_hci_device(struct btmtk_dev *bdev, int hci_bus_type); +int btmtk_free_hci_device(struct btmtk_dev *bdev, int hci_bus_type); +int btmtk_recv(struct hci_dev *hdev, const u8 *data, size_t count); +int btmtk_recv_event(struct hci_dev *hdev, struct sk_buff *skb); +int btmtk_recv_acl(struct hci_dev *hdev, struct sk_buff *skb); +int btmtk_recv_iso(struct hci_dev *hdev, struct sk_buff *skb); +int btmtk_dispatch_event(struct hci_dev *hdev, struct sk_buff *skb); +int btmtk_dispatch_acl(struct hci_dev *hdev, struct sk_buff *skb); +int btmtk_send_init_cmds(struct hci_dev *hdev); +int btmtk_send_deinit_cmds(struct hci_dev *hdev); +int btmtk_main_send_cmd(struct hci_dev *hdev, const uint8_t *cmd, const int cmd_len, const int tx_state); +uint8_t *_internal_evt_result(u_int8_t wmt_evt_result); +int btmtk_load_code_from_bin(u8 **image, char *bin_name, + struct device *dev, u32 *code_len, u8 retry); +int btmtk_calibration_flow(struct hci_dev *hdev); + + +/** + * HW Common commands + */ +int32_t btmtk_set_sleep(struct hci_dev*, u_int8_t need_wait); +int32_t btmtk_set_power_on(struct hci_dev*, u_int8_t for_precal); +int32_t btmtk_set_power_off(struct hci_dev*, u_int8_t for_precal); +int32_t btmtk_send_wmt_reset(struct hci_dev *hdev); +int32_t btmtk_send_wmt_power_on_cmd(struct hci_dev *hdev); +int32_t btmtk_send_wmt_power_off_cmd(struct hci_dev *hdev); +int32_t btmtk_send_calibration_cmd(struct hci_dev *hdev); +int32_t btmtk_send_blank_status_cmd(struct hci_dev *hdev, int32_t blank); +int32_t btmtk_send_utc_sync_cmd(void); + +#if (USE_DEVICE_NODE == 1) +uint8_t btmtk_rx_data_valid(void); +int32_t btmtk_send_data(struct hci_dev *hdev, uint8_t *buf, uint32_t count); +int32_t btmtk_receive_data(struct hci_dev * hdev,uint8_t * buf,uint32_t count); +void btmtk_rx_flush(void); +void btmtk_register_rx_event_cb(struct btmtk_dev *bdev, BT_RX_EVENT_CB cb); +int main_driver_init(void); +void main_driver_exit(void); +#endif + +//static inline struct sk_buff *mtk_add_stp(struct btmtk_dev *bdev, struct sk_buff *skb); + +#define hci_dev_clear_flag(hdev, nr) clear_bit((nr), (hdev)->dev_flags) + +/* h4_recv */ +#define hci_skb_pkt_type(skb) bt_cb((skb))->pkt_type +#define hci_skb_expect(skb) bt_cb((skb))->expect +#define hci_skb_opcode(skb) bt_cb((skb))->hci.opcode + +/* HCI bus types */ +#define HCI_VIRTUAL 0 +#define HCI_USB 1 +#define HCI_PCCARD 2 +#define HCI_UART 3 +#define HCI_RS232 4 +#define HCI_PCI 5 +#define HCI_SDIO 6 +#define HCI_SPI 7 +#define HCI_I2C 8 +#define HCI_SMD 9 + +struct h4_recv_pkt { + u8 type; /* Packet type */ + u8 hlen; /* Header length */ + u8 loff; /* Data length offset in header */ + u8 lsize; /* Data length field size */ + u16 maxlen; /* Max overall packet length */ + int (*recv)(struct hci_dev *hdev, struct sk_buff *skb); +}; + +#define H4_RECV_ACL \ + .type = HCI_ACLDATA_PKT, \ + .hlen = HCI_ACL_HDR_SIZE, \ + .loff = 2, \ + .lsize = 2, \ + .maxlen = HCI_MAX_FRAME_SIZE \ + +#define H4_RECV_SCO \ + .type = HCI_SCODATA_PKT, \ + .hlen = HCI_SCO_HDR_SIZE, \ + .loff = 2, \ + .lsize = 1, \ + .maxlen = HCI_MAX_SCO_SIZE + +#define H4_RECV_EVENT \ + .type = HCI_EVENT_PKT, \ + .hlen = HCI_EVENT_HDR_SIZE, \ + .loff = 1, \ + .lsize = 1, \ + .maxlen = HCI_MAX_EVENT_SIZE + +// TODO: replace by kernel constant if kernel support new spec +#define HCI_ISODATA_PKT 0x05 +#define HCI_ISO_HDR_SIZE 4 +#define H4_RECV_ISO \ + .type = HCI_ISODATA_PKT, \ + .hlen = HCI_ISO_HDR_SIZE, \ + .loff = 2, \ + .lsize = 2, \ + .maxlen = HCI_MAX_FRAME_SIZE + +#endif /* __BTMTK_MAIN_H__ */ diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_mt66xx.c b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_mt66xx.c new file mode 100644 index 0000000000000..9a85cfd973bf6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_mt66xx.c @@ -0,0 +1,1910 @@ +/* + * Copyright (c) 2016,2017 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include +#include +#include +#include +#include +#include "btmtk_chip_if.h" +#include "btmtk_mt66xx_reg.h" +#include "btmtk_define.h" +#include "btmtk_main.h" + +#include "conninfra.h" +#include "connsys_debug_utility.h" + + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define PATCH_FILE_NUM 2 +#define WMT_CMD_HDR_LEN (4) + +#define EMI_BGFSYS_MCU_START 0 +#define EMI_BGFSYS_MCU_SIZE 0x100000 /* 1024*1024 */ +#define EMI_BT_START (EMI_BGFSYS_MCU_START + EMI_BGFSYS_MCU_SIZE) +#define EMI_BT_SIZE 0x129400 /* 1189*1024 */ +#define EMI_DATETIME_LEN 16 // 14 bytes(ex: "20190821054545") + end of string +#define EMI_COREDUMP_MCU_DATE_OFFSET 0xE0 +#define EMI_COREDUMP_BT_DATE_OFFSET 0xF0 + +#define POS_POLLING_RTY_LMT 100 +#define IDLE_LOOP_RTY_LMT 100 +#define CAL_READY_BIT_PATTERN 0x5AD02EA5 +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +struct fw_patch_emi_hdr { + uint8_t date_time[EMI_DATETIME_LEN]; + uint8_t plat[4]; + uint16_t hw_ver; + uint16_t sw_ver; + uint8_t emi_addr[4]; + uint32_t subsys_id; + uint8_t reserved[14]; + uint16_t crc; +}; + +#if (CUSTOMER_FW_UPDATE == 1) +struct fwp_info { + bool result; + uint8_t status; + uint8_t datetime[PATCH_FILE_NUM][EMI_DATETIME_LEN]; + uint8_t update_time[EMI_DATETIME_LEN]; +}; +#else +struct fwp_info{ + bool result; + uint8_t datetime[PATCH_FILE_NUM][EMI_DATETIME_LEN]; +}; +#endif + +enum FWP_LOAD_FROM { + FWP_DIR_DEFAULT, + FWP_DIR_UPDATE, +}; + +enum FWP_CHECK_STATUS { + FWP_CHECK_SUCCESS, + FWP_NO_PATCH, + FWP_CRC_ERROR, + FWP_ERROR, + FWP_OLDER_DATETIME, + FWP_FUNCTION_DISABLE, +}; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +static const uint8_t WMT_OVER_HCI_CMD_HDR[] = { 0x01, 0x6F, 0xFC, 0x00 }; + +#if (CUSTOMER_FW_UPDATE == 1) +static bool g_fwp_update_enable = FALSE; +static uint8_t *g_fwp_names[PATCH_FILE_NUM][2] = { + {BIN_NAME_MCU, BIN_NAME_MCU_U}, + {BIN_NAME_BT, BIN_NAME_BT_U}, +}; +#else +static uint8_t *g_fwp_names[PATCH_FILE_NUM][1] = { + {BIN_NAME_MCU}, + {BIN_NAME_BT}, +}; +#endif +static struct fwp_info g_fwp_info; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +extern struct btmtk_dev *g_bdev; +extern struct bt_dbg_st g_bt_dbg_st; +struct bt_base_addr bt_reg; +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +#if (CUSTOMER_FW_UPDATE == 1) +static uint16_t fwp_checksume16(uint8_t *pData, uint64_t len) { + int32_t sum = 0; + + while (len > 1) { + sum += *((uint16_t*)pData); + pData = pData + 2; + + if (sum & 0x80000000) { + sum = (sum & 0xFFFF) + (sum >> 16); + } + + len -= 2; + } + + if (len) { + sum += *((uint8_t*)pData); + } + + while (sum >> 16) { + sum = (sum & 0xFFFF) + (sum >> 16); + } + return ~sum; +} + +static enum FWP_CHECK_STATUS fwp_check_patch ( + uint8_t *patch_name, + uint8_t *patch_datetime) +{ + uint8_t *p_buf = NULL; + struct fw_patch_emi_hdr *p_patch_hdr = NULL; + uint32_t patch_size; + uint8_t header_szie = sizeof(struct fw_patch_emi_hdr); + uint16_t crc; + int32_t ret = FWP_CHECK_SUCCESS; + + /* Read Firmware patch content */ + if(btmtk_load_code_from_bin(&p_buf, patch_name, NULL, &patch_size, 2) == -1) { + ret = FWP_NO_PATCH; + goto done; + } else if(patch_size < header_szie) { + BTMTK_ERR("%s: patch size %u error", __func__, patch_size); + ret = FWP_ERROR; + goto done; + } + + /* Check patch header information */ + p_patch_hdr = (struct fw_patch_emi_hdr *)p_buf; + strncpy(patch_datetime, p_patch_hdr->date_time, EMI_DATETIME_LEN); + patch_datetime[EMI_DATETIME_LEN - 2] = '\0'; // 14 bytes actually + + /* Caculate crc from body patch */ + crc = fwp_checksume16(p_buf + header_szie, patch_size - header_szie); + if(crc != p_patch_hdr->crc) { + ret = FWP_CRC_ERROR; + } +done: + BTMTK_INFO("%s: patch_name[%s], ret[%d]", __func__, patch_name, ret); + if (p_buf) + vfree(p_buf); + return ret; +} + +static enum FWP_LOAD_FROM fwp_preload_patch(struct fwp_info *info) +{ + uint8_t i = 0; + bool result = FWP_DIR_UPDATE; + uint8_t status = FWP_CHECK_SUCCESS; + uint8_t time_d[EMI_DATETIME_LEN], time_u[EMI_DATETIME_LEN]; + + if(g_fwp_update_enable) { + for(i = 0; i < PATCH_FILE_NUM; i++) { + fwp_check_patch(g_fwp_names[i][FWP_DIR_DEFAULT], time_d); + status = fwp_check_patch(g_fwp_names[i][FWP_DIR_UPDATE], time_u); + if(status != FWP_CHECK_SUCCESS) { + // if there is any error on update patch + result = FWP_DIR_DEFAULT; + goto done; + } else { + BTMTK_INFO("%s: %s, datetime[%s]", __func__, g_fwp_names[i][FWP_DIR_DEFAULT], time_d); + BTMTK_INFO("%s: %s: datetime[%s]", __func__, g_fwp_names[i][FWP_DIR_UPDATE], time_u); + if(strcmp(time_u, time_d) < 0) { + // if any update patch datetime is older + status = FWP_OLDER_DATETIME; + result = FWP_DIR_DEFAULT; + goto done; + } + } + } + } else { + result = FWP_DIR_DEFAULT; + status = FWP_FUNCTION_DISABLE; + } +done: + info->result = result; + info->status = status; + return result; +} + +static void fwp_update_info(struct fwp_info *info) { + struct timeval time; + struct rtc_time tm; + unsigned long local_time; + int i; + + do_gettimeofday(&time); + local_time = (uint32_t)(time.tv_sec - (sys_tz.tz_minuteswest * 60)); + rtc_time_to_tm(local_time, &tm); + if (snprintf(info->update_time, EMI_DATETIME_LEN, "%04d%02d%02d%02d%02d%02d", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec) < 0) { + BTMTK_INFO("%s: snprintf error", __func__); + return; + } + info->update_time[EMI_DATETIME_LEN - 2] = '\0'; // 14 bytes actually + + BTMTK_INFO("%s: result=%s, status=%d, datetime=%s, update_time=%s", __func__, + info->result == FWP_DIR_DEFAULT ? "FWP_DIR_DEFAULT" : "FWP_DIR_UPDATE", + info->status, info->datetime[0], info->update_time); +} + +void fwp_if_set_update_enable(int par) +{ + /* 0: disable, 1: enable*/ + g_fwp_update_enable = (par == 0) ? FALSE : TRUE; + BTMTK_INFO("%s: set fw patch update function = %s", __func__, (par == 0) ? "DISABLE" : "ENABLE"); +} + +int fwp_if_get_update_info(char *buf, int max_len) +{ + // mapping to FWP_CHECK_STATUS + char* status_info[] ={ + "none", "no new patch", "crc error", "error", "older version", "function disable" + }; + + /* return update information */ + if (snprintf(buf, max_len - 1, "result=%s\nstatus=%s\nversion=%s\nupdate_time=%s", + g_fwp_info.result == FWP_DIR_DEFAULT ? "FAIL" : "PASS", + status_info[g_fwp_info.status], + g_fwp_info.datetime[0], + g_fwp_info.update_time) < 0) { + BTMTK_INFO("%s: snprintf error", __func__); + return 0; + } + buf[strlen(buf)] = '\0'; + BTMTK_INFO("%s: %s, %d", __func__, buf, strlen(buf)); + return strlen(buf) + 1; +} +#endif + +int fwp_if_get_datetime(char *buf, int max_len) +{ + #define VER_STR_LEN 60 + int i = 0, ret_len = 0; + bool fwp_from = g_fwp_info.result; + char *tmp = buf; + + if (PATCH_FILE_NUM * VER_STR_LEN > max_len) + return 0; + /* write datetime information of each patch */ + for (i = 0; i < PATCH_FILE_NUM; i++) { + if (snprintf(tmp, VER_STR_LEN, "%s: %s\n", g_fwp_names[i][fwp_from], g_fwp_info.datetime[i]) < 0) { + BTMTK_INFO("%s: snprintf error", __func__); + return 0; + } + ret_len += strlen(tmp); + tmp = tmp + strlen(tmp); + } + buf[ret_len] = '\0'; + BTMTK_INFO("%s: %s, %d", __func__, buf, strlen(buf)); + return ret_len + 1; +} + +int fwp_if_get_bt_patch_path(char *buf, int max_len) +{ + #undef VER_STR_LEN + #define VER_STR_LEN 100 + bool fwp_from = g_fwp_info.result; + int ret = 0; + + if (VER_STR_LEN > max_len) + return 0; + if (fwp_from == FWP_DIR_DEFAULT) { + ret = snprintf(buf, VER_STR_LEN, "/vendor/firmware/%s", g_fwp_names[1][fwp_from]); + } else { +#if (CUSTOMER_FW_UPDATE == 1) + ret = snprintf(buf, VER_STR_LEN, "/data/vendor/firmware/update/%s", g_fwp_names[1][fwp_from]); +#else + ret = snprintf(buf, VER_STR_LEN, ""); +#endif + } + + if (ret < 0) { + BTMTK_INFO("%s: snprintf error", __func__); + return 0; + } + BTMTK_INFO("%s: %s, %d", __func__, buf, strlen(buf)); + return strlen(buf) + 1; +} + +/* bgfsys_ccif_on + * + * MD coex indication, BT driver should set relative control register to info + * MD that BT is on + * + * Arguments: + * N/A + * + * Return Value: + * N/A + * + * Todo: + * Use pre-mapped memory, don't know why it doesn't work + */ +void bgfsys_ccif_on(void) +{ + uint8_t *ccif_base = ioremap_nocache(0x10003300, 0x100); + + if (ccif_base == NULL) { + BTMTK_ERR("%s: remapping ccif_base fail", __func__); + return; + } + + /* CONSYS_BGF_PWR_ON, 0x10003318[0] = 1'b1 */ + SET_BIT(ccif_base + 0x18, BIT(0)); + /* CONSYS_BGF_READY, 0x10003318[1] = 1'b0 */ + CLR_BIT(ccif_base + 0x18, BIT(1)); + iounmap(ccif_base); +} + +/* bgfsys_ccif_off + * + * MD coex indication, BT driver should set relative control register to info + * MD that BT is off + * + * Arguments: + * N/A + * + * Return Value: + * N/A + * + * Todo: + * Use pre-mapped memory, don't know why it doesn't work + */ +void bgfsys_ccif_off(void) +{ + uint8_t *ccif_base = NULL, *bgf2md_base = NULL; + + ccif_base = ioremap_nocache(0x10003300, 0x100); + if (ccif_base == NULL) { + BTMTK_ERR("%s: remapping ccif_base fail", __func__); + return; + } + + /* CONSYS_BGF_PWR_ON, 0x10003318[0] = 1'b0 */ + CLR_BIT(ccif_base + 0x18, BIT(0)); + /* CONSYS_BGF_READY, 0x10003318[1] = 1'b0 */ + CLR_BIT(ccif_base + 0x18, BIT(1)); + iounmap(ccif_base); + + + bgf2md_base = ioremap_nocache(0x1025C000, 0x100); + if (bgf2md_base == NULL) { + BTMTK_ERR("%s: remapping bgf2md_base fail", __func__); + return; + } + + /* set PCCIF5 RX ACK, 0x1025C014[0:7] = 8'b1 */ + REG_WRITEL(bgf2md_base + 0x14, 0xFF); + iounmap(bgf2md_base); +} + +/* bgfsys_cal_data_backup + * + * Backup BT calibration data + * + * Arguments: + * [IN] start_addr - offset to the SYSRAM + * [IN] cal_data - data buffer to backup calibration data + * [IN] data_len - data length + * + * Return Value: + * N/A + * + */ +static void bgfsys_cal_data_backup( + uint32_t start_addr, + uint8_t *cal_data, + uint16_t data_len) +{ + uint32_t start_offset; + + /* + * The calibration data start address and ready bit address returned in WMT RF cal event + * should be 0x7C05XXXX from F/W's point of view (locate at ConnInfra sysram region), + * treat the low 3 bytes as offset to our remapped virtual base. + */ + start_offset = start_addr & 0x0000FFFF; + if (start_offset > 0x1000) { + BTMTK_ERR("Error sysram offset address start=[0x%08x]", + start_addr); + return; + } + + if (!conninfra_reg_readable()) { + int32_t ret = conninfra_is_bus_hang(); + if (ret > 0) + BTMTK_ERR("%s: conninfra bus is hang, needs reset", __func__); + else + BTMTK_ERR("%s: conninfra not readable, but not bus hang ret = %d", __func__, ret); + return; + } + + memcpy_fromio(cal_data, (const volatile void *)(CON_REG_INFRA_SYS_ADDR + start_offset), data_len); +} + +/* bgfsys_cal_data_restore + * + * Restore BT calibration data to SYSRAM, after restore success, + * driver needs to write a special pattern '0x5AD02EA5' to ready address to + * info FW not to do calibration this time + * + * Arguments: + * [IN] start_addr - offset to the SYSRAM + * [IN] ready_addr - readya_address to write 0x5AD02EA5 + * [IN] cal_data - data buffer of calibration data + * [IN] data_len - data length + * + * Return Value: + * N/A + * + */ +static void bgfsys_cal_data_restore(uint32_t start_addr, + uint32_t ready_addr, + uint8_t *cal_data, + uint16_t data_len) +{ + uint32_t start_offset, ready_offset; + uint32_t ready_status = 0; + + start_offset = start_addr & 0x0000FFFF; + ready_offset = ready_addr & 0x0000FFFF; + + if (start_offset > 0x1000 || ready_offset > 0x1000) { + BTMTK_ERR("Error sysram offset address start=[0x%08x], ready=[0x%08x]", + start_addr, ready_addr); + return; + } + + if (!conninfra_reg_readable()) { + int32_t ret = conninfra_is_bus_hang(); + if (ret > 0) + BTMTK_ERR("%s: conninfra bus is hang, needs reset", __func__); + else + BTMTK_ERR("%s: conninfra not readable, but not bus hang ret = %d", __func__, ret); + return; + } + + memcpy_toio((volatile void *)(CON_REG_INFRA_SYS_ADDR + start_offset), cal_data, data_len); + /* Firmware will not do calibration again when BT func on */ + REG_WRITEL(CON_REG_INFRA_SYS_ADDR + ready_offset, CAL_READY_BIT_PATTERN); + ready_status = REG_READL(CON_REG_INFRA_SYS_ADDR + ready_offset); + BTMTK_DBG("Ready pattern after restore cal=[0x%08x]", ready_status); +} + +/* bgfsys_check_conninfra_ready + * + * wakeup conninfra and check its ready status + * + * Arguments: + * N/A + * + * Return Value: + * 0 if success, otherwise error code + * + */ +int32_t bgfsys_check_conninfra_ready(void) +{ + int32_t retry = POS_POLLING_RTY_LMT; + uint32_t value = 0; + + /* wake up conn_infra off */ + SET_BIT(CONN_INFRA_WAKEUP_BT, BIT(0)); + + /* check ap2conn slpprot_rdy */ + retry = POS_POLLING_RTY_LMT; + do { + value = CONN_INFRA_ON2OFF_SLP_PROT_ACK & + REG_READL(CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL); + BTMTK_DBG("ap2conn slpprot_rdy = 0x%08x", value); + usleep_range(1000, 1100); + retry--; + } while (value != 0 && retry > 0); + + if (retry == 0) + return -1; + + if (conninfra_reg_readable()) { + /* check conn_infra off ID */ + value = REG_READL(CONN_INFRA_CFG_VERSION); + BTMTK_DBG("connifra cfg version = 0x%08x", value); + if (value != CONN_INFRA_CFG_ID) + return -1; + } else { + BTMTK_ERR("Conninfra is not readable"); + return -1; + } + + return 0; +} + +static void bgfsys_dump_uart_pta_pready_status(void) +{ + uint8_t *base = NULL; + + if (!conninfra_reg_readable()) { + BTMTK_ERR("%s: conninfra bus is not readable, discard", __func__); + return; + } + + REG_WRITEL(CON_REG_SPM_BASE_ADDR + 0x128, 0x00020002); + BTMTK_INFO("0x18060128 = [0x%08x]", + REG_READL(CON_REG_SPM_BASE_ADDR + 0x128)); + + BTMTK_INFO("0x18001A00 = [0x%08x]", + REG_READL(CON_REG_INFRA_CFG_ADDR + 0xA00)); + + base = ioremap_nocache(0x1800C00C, 4); + if (base == NULL) { + BTMTK_ERR("%s: remapping 0x18001A00 fail", __func__); + return; + } + BTMTK_INFO("0x1800C00C = [0x%08x]", *base); + iounmap(base); +} + +/* bgfsys_power_on + * + * BGF MCU power on sequence + * + * Arguments: + * N/A + * + * Return Value: + * 0 if success, otherwise error code + * + */ +static int32_t bgfsys_power_on(void) +{ + uint32_t value; + int32_t retry = POS_POLLING_RTY_LMT; + uint32_t delay_ms = 5; + uint32_t mcu_idle, mcu_pc; + uint32_t remap_addr; + + remap_addr = REG_READL(CONN_REMAP_ADDR); + BTMTK_INFO("remap addr = 0x%08X", remap_addr); + + bgfsys_dump_uart_pta_pready_status(); + + /* reset n10 cpu core */ + CLR_BIT(CONN_INFRA_RGU_BGFSYS_CPU_SW_RST, BGF_CPU_SW_RST_B); + + /* bus clock ctrl */ + conninfra_bus_clock_ctrl(CONNDRV_TYPE_BT, CONNINFRA_BUS_CLOCK_WPLL | CONNINFRA_BUS_CLOCK_BPLL, 1); + + /* enable bt function en */ + SET_BIT(CONN_INFRA_CFG_BT_PWRCTLCR0, BT_FUNC_EN_B); + + if (!conninfra_reg_readable()) { + if (conninfra_is_bus_hang() > 0) { + BTMTK_ERR("%s: check conninfra status fail after set CONN_INFRA_CFG_BT_PWRCTLCR0!", __func__); + goto error; + } + } + + /* polling bgfsys top on power ack bits until they are asserted */ + do { + value = BGF_ON_PWR_ACK_B & + REG_READL(CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_ACK_ST); + BTMTK_INFO("bgfsys on power ack = 0x%08x", value); + usleep_range(500, 550); + retry--; + } while (value != BGF_ON_PWR_ACK_B && retry > 0); + + if (0 == retry) + goto error; + + /* polling bgfsys top off power ack bits until they are asserted */ + retry = POS_POLLING_RTY_LMT; + do { + value = BGF_OFF_PWR_ACK_B & + REG_READL(CONN_INFRA_RGU_BGFSYS_OFF_TOP_PWR_ACK_ST); + BTMTK_INFO("bgfsys off top power ack_b = 0x%08x", value); + usleep_range(500, 550); + retry--; + } while (value != BGF_OFF_PWR_ACK_B && retry > 0); + + if (0 == retry) + goto error; + + retry = POS_POLLING_RTY_LMT; + do { + value = BGF_OFF_PWR_ACK_S & + REG_READL(CONN_INFRA_RGU_BGFSYS_OFF_TOP_PWR_ACK_ST); + BTMTK_INFO("bgfsys off top power ack_s = 0x%08x", value); + usleep_range(500, 550); + retry--; + } while (value != BGF_OFF_PWR_ACK_S && retry > 0); + + if (0 == retry) + goto error; + + /* disable conn2bt slp_prot rx en */ + CLR_BIT(CONN_INFRA_CONN2BT_GALS_SLP_CTL, CONN2BT_SLP_PROT_RX_EN_B); + + /* polling conn2bt slp_prot rx ack until it is cleared */ + retry = POS_POLLING_RTY_LMT; + do { + value = CONN2BT_SLP_PROT_RX_ACK_B & + REG_READL(CONN_INFRA_CONN2BT_GALS_SLP_CTL); + BTMTK_INFO("conn2bt slp_prot rx ack = 0x%08x", value); + usleep_range(500, 550); + retry--; + } while (value != 0 && retry > 0); + + if (0 == retry) + goto error; + + /* disable conn2bt slp_prot tx en */ + CLR_BIT(CONN_INFRA_CONN2BT_GALS_SLP_CTL, CONN2BT_SLP_PROT_TX_EN_B); + /* polling conn2bt slp_prot tx ack until it is cleared */ + retry = POS_POLLING_RTY_LMT; + do { + value = CONN2BT_SLP_PROT_TX_ACK_B & + REG_READL(CONN_INFRA_CONN2BT_GALS_SLP_CTL); + BTMTK_INFO("conn2bt slp_prot tx ack = 0x%08x", value); + usleep_range(500, 550); + retry--; + } while (value != 0 && retry > 0); + + if (0 == retry) + goto error; + + /* disable bt2conn slp_prot rx en */ + CLR_BIT(CONN_INFRA_BT2CONN_GALS_SLP_CTL, BT2CONN_SLP_PROT_RX_EN_B); + /* polling bt2conn slp_prot rx ack until it is cleared */ + retry = POS_POLLING_RTY_LMT; + do { + value = BT2CONN_SLP_PROT_RX_ACK_B & + REG_READL(CONN_INFRA_BT2CONN_GALS_SLP_CTL); + BTMTK_INFO("bt2conn slp_prot rx ack = 0x%08x", value); + usleep_range(500, 550); + retry--; + } while (value != 0 && retry > 0); + + if (0 == retry) + goto error; + + /* disable bt2conn slp_prot tx en */ + CLR_BIT(CONN_INFRA_BT2CONN_GALS_SLP_CTL, BT2CONN_SLP_PROT_TX_EN_B); + /* polling bt2conn slp_prot tx ack until it is cleared */ + retry = POS_POLLING_RTY_LMT; + do { + value = BT2CONN_SLP_PROT_TX_ACK_B & + REG_READL(CONN_INFRA_BT2CONN_GALS_SLP_CTL); + BTMTK_INFO("bt2conn slp_prot tx ack = 0x%08x", value); + usleep_range(500, 550); + retry--; + } while (value != 0 && retry > 0); + + if (0 == retry) + goto error; + + usleep_range(400, 440); + + /* read bgfsys hw_version */ + retry = 10; + do { + value = REG_READL(BGF_HW_VERSION); + BTMTK_INFO("bgfsys hw version id = 0x%08x", value); + usleep_range(500, 550); + retry--; + } while (value != BGF_HW_VER_ID && retry > 0); + + if (0 == retry) + goto error; + + /* read bgfsys fw_version */ + value = REG_READL(BGF_FW_VERSION); + BTMTK_INFO("bgfsys fw version id = 0x%08x", value); + if (value != BGF_FW_VER_ID) + goto error; + + /* read bgfsys hw_code */ + value = REG_READL(BGF_HW_CODE); + BTMTK_INFO("bgfsys hw code = 0x%08x", value); + if (value != BGF_HW_CODE_ID) + goto error; + + /* read and check bgfsys version id */ + value = REG_READL(BGF_IP_VERSION); + BTMTK_INFO("bgfsys version id = 0x%08x", value); + if (value != BGF_IP_VER_ID) + goto error; + + /* clear con_cr_ahb_auto_dis */ + CLR_BIT(BGF_MCCR, BGF_CON_CR_AHB_AUTO_DIS); + + /* set con_cr_ahb_stop */ + REG_WRITEL(BGF_MCCR_SET, BGF_CON_CR_AHB_STOP); + + /* reset bfgsys semaphore */ + CLR_BIT(CONN_INFRA_RGU_BGFSYS_SW_RST_B, BGF_SW_RST_B); + + /* release n10 cpu core */ + SET_BIT(CONN_INFRA_RGU_BGFSYS_CPU_SW_RST, BGF_CPU_SW_RST_B); + + /* trun off BPLL & WPLL (use common API) */ + conninfra_bus_clock_ctrl(CONNDRV_TYPE_BT, CONNINFRA_BUS_CLOCK_WPLL | CONNINFRA_BUS_CLOCK_BPLL, 0); + + /* + * enable conn_infra bus hang detect function & + * bus timeout value(use common API) + */ + conninfra_config_setup(); + + bgfsys_dump_uart_pta_pready_status(); + + /* release conn_infra force on */ + CLR_BIT(CONN_INFRA_WAKEUP_BT, BIT(0)); + + /* + * polling BGFSYS MCU sw_dbg_ctl cr to wait it becomes 0x1D1E, + * which indicates that the power-on part of ROM is completed. + */ + retry = IDLE_LOOP_RTY_LMT; + do { + if (conninfra_reg_readable()) { + mcu_pc = REG_READL(CONN_MCU_PC); + mcu_idle = REG_READL(BGF_MCU_CFG_SW_DBG_CTL); + BTMTK_INFO("MCU sw_dbg_ctl = 0x%08x", mcu_idle); + BTMTK_INFO("MCU pc = 0x%08x", mcu_pc); + if (0x1D1E == mcu_idle) + break; + } else { + bgfsys_power_on_dump_cr(); + return -1; + } + + msleep(delay_ms); + retry--; + } while (retry > 0); + + if (retry == 0) { + bt_dump_cif_own_cr(); + return -1; + } + + return 0; + +error: + /* turn off clock ctrl */ + conninfra_bus_clock_ctrl(CONNDRV_TYPE_BT, CONNINFRA_BUS_CLOCK_WPLL | CONNINFRA_BUS_CLOCK_BPLL, 0); + + bgfsys_power_on_dump_cr(); + + /* release conn_infra force on */ + CLR_BIT(CONN_INFRA_WAKEUP_BT, BIT(0)); + + return -1; + +} + +/* bgfsys_power_off + * + * BGF MCU power off sequence + * + * Arguments: + * N/A + * + * Return Value: + * 0 if success, otherwise error code + * + */ +static int32_t bgfsys_power_off(void) +{ + uint32_t value = 0; + int32_t retry = POS_POLLING_RTY_LMT; + int32_t ret = 0; + + ret = bgfsys_check_conninfra_ready(); + if (ret) + return ret; + + bgfsys_dump_uart_pta_pready_status(); + + /* enable bt2conn slp_prot tx en */ + SET_BIT(CONN_INFRA_BT2CONN_GALS_SLP_CTL, BT2CONN_SLP_PROT_TX_EN_B); + /* polling bt2conn slp_prot tx ack until it is asserted */ + retry = POS_POLLING_RTY_LMT; + do { + value = BT2CONN_SLP_PROT_TX_ACK_B & + REG_READL(CONN_INFRA_BT2CONN_GALS_SLP_CTL); + BTMTK_DBG("bt2conn slp_prot tx ack = 0x%08x", value); + usleep_range(500, 550); + retry--; + } while (value == 0 && retry > 0); + + if (retry == 0) + ret = -1; + + /* enable bt2conn slp_prot rx en */ + SET_BIT(CONN_INFRA_BT2CONN_GALS_SLP_CTL, BT2CONN_SLP_PROT_RX_EN_B); + /* polling bt2conn slp_prot rx ack until it is asserted */ + retry = POS_POLLING_RTY_LMT; + do { + value = BT2CONN_SLP_PROT_RX_ACK_B & + REG_READL(CONN_INFRA_BT2CONN_GALS_SLP_CTL); + BTMTK_DBG("bt2conn slp_prot rx ack = 0x%08x", value); + usleep_range(500, 550); + retry --; + } while (value == 0 && retry > 0); + + if (retry == 0) + ret = -2; + + /* enable conn2bt slp_prot tx en */ + SET_BIT(CONN_INFRA_CONN2BT_GALS_SLP_CTL, CONN2BT_SLP_PROT_TX_EN_B); + /* polling conn2bt slp_prot tx ack until it is asserted */ + retry = POS_POLLING_RTY_LMT; + do { + value = CONN2BT_SLP_PROT_TX_ACK_B & + REG_READL(CONN_INFRA_CONN2BT_GALS_SLP_CTL); + BTMTK_DBG("conn2bt slp_prot tx ack = 0x%08x", value); + usleep_range(500, 550); + retry --; + } while (value == 0 && retry > 0); + + if (retry == 0) + ret = -2; + + /* enable conn2bt slp_prot rx en */ + SET_BIT(CONN_INFRA_CONN2BT_GALS_SLP_CTL, CONN2BT_SLP_PROT_RX_EN_B); + /* polling conn2bt slp_prot rx ack until it is asserted */ + retry = POS_POLLING_RTY_LMT; + do { + value = CONN2BT_SLP_PROT_RX_ACK_B & + REG_READL(CONN_INFRA_CONN2BT_GALS_SLP_CTL); + BTMTK_DBG("conn2bt slp_prot rx ack = 0x%08x", value); + usleep_range(500, 550); + retry --; + } while (value == 0 && retry > 0); + + if (retry == 0) + ret = -1; + + if (ret == -2) + conninfra_trigger_whole_chip_rst(CONNDRV_TYPE_BT, "Power off fail"); + + /* trun off BPLL & WPLL (use common API) */ + conninfra_bus_clock_ctrl(CONNDRV_TYPE_BT, CONNINFRA_BUS_CLOCK_WPLL | CONNINFRA_BUS_CLOCK_BPLL, 0); + + /* disable bt function en */ + CLR_BIT(CONN_INFRA_CFG_BT_PWRCTLCR0, BT_FUNC_EN_B); + + /* reset n10 cpu core */ + CLR_BIT(CONN_INFRA_RGU_BGFSYS_CPU_SW_RST, BGF_CPU_SW_RST_B); + + /* Disable A-die top_ck_en (use common API) */ + conninfra_adie_top_ck_en_off(CONNSYS_ADIE_CTL_FW_BT); + + /* reset bfgsys semaphore */ + CLR_BIT(CONN_INFRA_RGU_BGFSYS_SW_RST_B, BGF_SW_RST_B); + + /* clear bt_emi_req */ + SET_BIT(CONN_INFRA_CFG_EMI_CTL_BT_EMI_REQ_BT, BT_EMI_CTRL_BIT); + CLR_BIT(CONN_INFRA_CFG_EMI_CTL_BT_EMI_REQ_BT, BT_EMI_CTRL_BIT); + CLR_BIT(CONN_INFRA_CFG_EMI_CTL_BT_EMI_REQ_BT, BT_EMI_CTRL_BIT1); + + if (ret) + bgfsys_power_on_dump_cr(); + + bgfsys_dump_uart_pta_pready_status(); + + /* release conn_infra force on */ + CLR_BIT(CONN_INFRA_WAKEUP_BT, BIT(0)); + + return ret; +} + +/* __download_patch_to_emi + * + * Download(copy) FW to EMI + * + * Arguments: + * [IN] patch_name - FW bin filename + * [IN] emi_start - offset to EMI address for BT / MCU + * [IN] emi_size - EMI region + * + * Return Value: + * 0 if success, otherwise error code + * + */ +static int32_t __download_patch_to_emi( + uint8_t *patch_name, + uint32_t emi_start, + uint32_t emi_size, +#if SUPPORT_COREDUMP + phys_addr_t fwdate_offset, +#endif + uint8_t *datetime) +{ + int32_t ret = 0; + struct fw_patch_emi_hdr *p_patch_hdr = NULL; + uint8_t *p_buf = NULL, *p_img = NULL; + uint32_t patch_size; + uint16_t hw_ver = 0; + uint16_t sw_ver = 0; + uint32_t subsys_id = 0; + uint32_t patch_emi_offset = 0; + phys_addr_t emi_ap_phy_base; + uint8_t *remap_addr; + + BTMTK_INFO("%s: load binary [%s]", __func__, patch_name); + /* Read Firmware patch content */ + btmtk_load_code_from_bin(&p_img, patch_name, NULL, &patch_size, 10); + if (p_img == NULL || patch_size < sizeof(struct fw_patch_emi_hdr)) { + BTMTK_ERR("patch size %u error", patch_size); + ret = -EINVAL; + goto done; + } + + /* Patch binary format: + * |<-EMI header: 48 Bytes->|<-BT/MCU header: 48 Bytes ->||<-patch body: X Bytes ----->| + */ + /* Check patch header information */ + p_buf = p_img; + p_patch_hdr = (struct fw_patch_emi_hdr *)p_buf; + + + hw_ver = p_patch_hdr->hw_ver; + sw_ver = p_patch_hdr->sw_ver; + subsys_id = p_patch_hdr->subsys_id; + strncpy(datetime, p_patch_hdr->date_time, sizeof(p_patch_hdr->date_time)); + datetime[sizeof(p_patch_hdr->date_time) - 2] = '\0'; // 14 bytes actually + BTMTK_INFO( + "[Patch]BTime=%s,HVer=0x%04x,SVer=0x%04x,Plat=%c%c%c%c,Addr=0x%02x%02x%02x%02x,Type=%x", + datetime, + ((hw_ver & 0x00ff) << 8) | ((hw_ver & 0xff00) >> 8), + ((sw_ver & 0x00ff) << 8) | ((sw_ver & 0xff00) >> 8), + p_patch_hdr->plat[0], p_patch_hdr->plat[1], + p_patch_hdr->plat[2], p_patch_hdr->plat[3], + p_patch_hdr->emi_addr[3], p_patch_hdr->emi_addr[2], + p_patch_hdr->emi_addr[1], p_patch_hdr->emi_addr[0], + subsys_id); + + /* Remove EMI header: + * |<-BT/MCU header: 48 Bytes ->||<-patch body: X Bytes ----->| + */ + patch_size -= sizeof(struct fw_patch_emi_hdr); + p_buf += sizeof(struct fw_patch_emi_hdr); + + /* + * The EMI entry address given in patch header should be 0xFXXXXXXX + * from F/W's point of view, treat the middle 2 bytes as offset, + * the actual phy base should be dynamically allocated and provided + * by conninfra driver. + * + */ + patch_emi_offset = (p_patch_hdr->emi_addr[2] << 16) | + (p_patch_hdr->emi_addr[1] << 8); + + conninfra_get_phy_addr((uint32_t*)&emi_ap_phy_base, NULL); + emi_ap_phy_base &= 0xFFFFFFFF; + + if ((patch_emi_offset >= emi_start) && + (patch_emi_offset + patch_size < emi_start + emi_size)) { + remap_addr = ioremap_nocache(emi_ap_phy_base + patch_emi_offset, patch_size); + if (remap_addr) { + memcpy_toio(remap_addr, p_buf, patch_size); + iounmap(remap_addr); + } else { + BTMTK_ERR("ioremap_nocache fail!"); + ret = -EFAULT; + } + } else { + BTMTK_ERR("emi_start =0x%x size=0x%x", emi_start, emi_size); + BTMTK_ERR("Patch overflow on EMI, offset=0x%x size=0x%x", + patch_emi_offset, patch_size); + ret = -EINVAL; + } + +#if SUPPORT_COREDUMP + remap_addr = ioremap_nocache(emi_ap_phy_base + fwdate_offset, sizeof(p_patch_hdr->date_time)); + if (remap_addr) { + memcpy_toio(remap_addr, p_patch_hdr->date_time, sizeof(p_patch_hdr->date_time)); + iounmap(remap_addr); + } else + BTMTK_ERR("ioremap_nocache coredump data field fail"); +#endif + +done: + if (p_img) + vfree(p_img); + return ret; +} + +/* bgfsys_mcu_rom_patch_dl + * + * Download BGF MCU rom patch + * + * Arguments: + * N/A + * + * Return Value: + * 0 if success, otherwise error code + * + */ +static int32_t bgfsys_mcu_rom_patch_dl(enum FWP_LOAD_FROM fwp_from, struct fwp_info *info) +{ + int32_t ret = 0; +#if SUPPORT_COREDUMP + phys_addr_t fwdate_offset = connsys_coredump_get_start_offset(CONN_DEBUG_TYPE_BT) + + EMI_COREDUMP_MCU_DATE_OFFSET; +#endif + + ret = bgfsys_check_conninfra_ready(); + if (ret) + return ret; + + return __download_patch_to_emi(g_fwp_names[0][fwp_from], + EMI_BGFSYS_MCU_START, + EMI_BGFSYS_MCU_SIZE, +#if SUPPORT_COREDUMP + fwdate_offset, +#endif + info->datetime[0]); +} + +/* bgfsys_mcu_rom_patch_dl + * + * Download BT ram patch + * + * Arguments: + * N/A + * + * Return Value: + * 0 if success, otherwise error code + * + */ +static int32_t bgfsys_bt_ram_code_dl(enum FWP_LOAD_FROM fwp_from, struct fwp_info *info) +{ +#if SUPPORT_COREDUMP + phys_addr_t fwdate_offset = connsys_coredump_get_start_offset(CONN_DEBUG_TYPE_BT) + + EMI_COREDUMP_BT_DATE_OFFSET; +#endif + + return __download_patch_to_emi(g_fwp_names[1][fwp_from], + EMI_BT_START, + EMI_BT_SIZE, +#if SUPPORT_COREDUMP + fwdate_offset, +#endif + info->datetime[1]); +} + +/* bt_hw_and_mcu_on + * + * BT HW / MCU / HAL poweron/init flow + * + * Arguments: + * N/A + * + * Return Value: + * 0 if success, otherwise error code + * + */ +static int32_t bt_hw_and_mcu_on(void) +{ + int ret = -1; + enum FWP_LOAD_FROM fwp_from = FWP_DIR_DEFAULT; + + memset(&g_fwp_info, '\0', sizeof(struct fwp_info)); +#if (CUSTOMER_FW_UPDATE == 1) + fwp_from = fwp_preload_patch(&g_fwp_info); +#else + g_fwp_info.result = fwp_from; +#endif + + /* + * Firmware patch download (ROM patch, RAM code...) + * start MCU to enter idle loop after patch ready + */ + ret = bgfsys_mcu_rom_patch_dl(fwp_from, &g_fwp_info); + if (ret) + goto power_on_error; + + ret = bgfsys_bt_ram_code_dl(fwp_from, &g_fwp_info); + if (ret) + goto power_on_error; + +#if (CUSTOMER_FW_UPDATE == 1) + fwp_update_info(&g_fwp_info); +#endif + + /* BGFSYS hardware power on */ + if (bgfsys_power_on()) { + BTMTK_ERR("BGFSYS power on failed!"); + ret = -EIO; + goto power_on_error; + } + + /* Register all needed IRQs by MCU */ + ret = bt_request_irq(BGF2AP_BTIF_WAKEUP_IRQ); + if (ret) + goto request_irq_error; + + bt_disable_irq(BGF2AP_BTIF_WAKEUP_IRQ); + + ret = bt_request_irq(BGF2AP_SW_IRQ); + if (ret) + goto request_irq_error2; + + bt_disable_irq(BGF2AP_SW_IRQ); + + btmtk_reset_init(); + + if (btmtk_btif_open()) { + ret = -EIO; + goto bus_operate_error; + } + return 0; + + +bus_operate_error: + bt_free_irq(BGF2AP_SW_IRQ); + +request_irq_error2: + bt_free_irq(BGF2AP_BTIF_WAKEUP_IRQ); + +request_irq_error: +power_on_error: + bgfsys_power_off(); + return ret; +} + +/* bt_hw_and_mcu_off + * + * BT HW / MCU / HAL poweron/deinit flow + * + * Arguments: + * N/A + * + * Return Value: + * N/A + * + */ +static void bt_hw_and_mcu_off(void) +{ + BTMTK_INFO("%s", __func__); + /* Close hardware bus interface */ + btmtk_btif_close(); + + /* Free all registered IRQs */ + bt_free_irq(BGF2AP_SW_IRQ); + bt_free_irq(BGF2AP_BTIF_WAKEUP_IRQ); + + /* BGFSYS hardware power off */ + bgfsys_power_off(); +} + +/* btmtk_send_wmt_reset_cmd + * + * Send BT reset command (for testing) + * + * Arguments: + * [IN] hdev - hci_device as control structure during BT life cycle + * + * Return Value: + * N/A + * + */ +int32_t btmtk_send_wmt_reset_cmd(struct hci_dev *hdev) +{ + /* Support MT66xx*/ + uint8_t cmd[] = {0x01, 0x5B, 0xFD, 0x00}; + + btmtk_main_send_cmd(hdev, cmd, sizeof(cmd), BTMTKUART_TX_SKIP_VENDOR_EVT); + + BTMTK_INFO("%s done", __func__); + return 0; +} + +#if 0 +static int btmtk_send_gating_disable_cmd(struct hci_dev *hdev) +{ + u8 cmd[] = { 0x01, 0x6F, 0xFC, 0x05, 0x01, 0x03, 0x01, 0x00, 0x04 }; + /* To-Do, for event check */ + /* u8 event[] = { 0x04, 0xE4, 0x06, 0x02, 0x03, 0x02, 0x00, 0x00, 0x04 }; */ + btmtk_main_send_cmd(hdev, cmd, sizeof(cmd), BTMTKUART_TX_WAIT_VND_EVT); + + BTMTK_INFO("%s done", __func__); + return 0; +} + +static int btmtk_send_read_conn_cmd(struct hci_dev *hdev) +{ + u8 cmd[] = { 0x01, 0x6F, 0xFC, 0x05, 0x01, 0x04, 0x01, 0x00, 0x07 }; + /* To-Do, for event check */ + /* u8 event[] = { 0x04, 0xE4, 0x0A, 0x02, 0x04, 0x06, 0x00, 0x00, 0x07, 0x00, 0x8a, 0x00, 0x00 }; */ + btmtk_main_send_cmd(hdev, cmd, sizeof(cmd), BTMTKUART_TX_WAIT_VND_EVT); + + BTMTK_INFO("%s done", __func__); + return 0; +} +#endif + +/* btmtk_send_blank_status_cmd + * + * Send blank status to FW + * + * Arguments: + * [IN] hdev - hci_device as control structure during BT life cycle + * + * Return Value: + * N/A + * + */ +int32_t btmtk_send_blank_status_cmd(struct hci_dev *hdev, int32_t blank) +{ + struct btmtk_dev *bdev = hci_get_drvdata(hdev); + struct bt_internal_cmd *p_inter_cmd = &bdev->internal_cmd; + uint8_t cmd[] = { 0x01, 0x6F, 0xFC, 0x06, 0x01, 0xF0, 0x02, 0x00, 0x03, 0x00 }; + /* uint8_t evt[] = {0x04, 0xE4, 0x06, 0x02, 0xF0, 0x02, 0x00, 0x03, 0x00}; */ + + BTMTK_INFO("[InternalCmd] %s", __func__); + down(&bdev->internal_cmd_sem); + bdev->event_intercept = TRUE; + + // fb event: 0(screen on, FB_BLANK_UNBLANK) / 4(screen off, FB_BLANK_POWERDOWN) + // wmt parameter: 0(screen off) / 1(screen on) + cmd[9] = (blank == 0) ? 1 : 0; + bdev->event_intercept = TRUE; + p_inter_cmd->waiting_event = 0xE4; + p_inter_cmd->pending_cmd_opcode = 0xFC6F; + p_inter_cmd->wmt_opcode = WMT_OPCODE_0XF0; + p_inter_cmd->result = WMT_EVT_INVALID; + + btmtk_main_send_cmd(hdev, cmd, sizeof(cmd), BTMTKUART_TX_WAIT_VND_EVT); + + bdev->event_intercept = FALSE; + up(&bdev->internal_cmd_sem); + BTMTK_INFO("[InternalCmd] %s done, result = %s", __func__, _internal_evt_result(p_inter_cmd->result)); + return 0; +} + +/* _send_wmt_power_cmd + * + * Send BT func on/off command to FW + * + * Arguments: + * [IN] hdev - hci_device as control structure during BT life cycle + * [IN] is_on - indicate current action is On (TRUE) or Off (FALSE) + * + * Return Value: + * 0 if success, otherwise -EIO + * + */ +static int32_t _send_wmt_power_cmd(struct hci_dev *hdev, u_int8_t is_on) +{ + struct btmtk_dev *bdev = hci_get_drvdata(hdev); + struct wmt_pkt wmt_cmd; + uint8_t buffer[HCI_MAX_FRAME_SIZE]; + uint16_t param_len, pkt_len; + struct bt_internal_cmd *p_inter_cmd = &bdev->internal_cmd; + int ret; + + BTMTK_INFO("[InternalCmd] %s", __func__); + down(&bdev->internal_cmd_sem); + bdev->event_intercept = TRUE; + + wmt_cmd.hdr.dir = WMT_PKT_DIR_HOST_TO_CHIP; + + /* Support Connac 2.0 */ + wmt_cmd.hdr.opcode = WMT_OPCODE_FUNC_CTRL; + wmt_cmd.params.u.func_ctrl_cmd.subsys = 0; + wmt_cmd.params.u.func_ctrl_cmd.on = is_on ? 1 : 0; + param_len = sizeof(wmt_cmd.params.u.func_ctrl_cmd); + + wmt_cmd.hdr.param_len[0] = (uint8_t)(param_len & 0xFF); + wmt_cmd.hdr.param_len[1] = (uint8_t)((param_len >> 8) & 0xFF); + + pkt_len = HCI_CMD_HDR_LEN + WMT_CMD_HDR_LEN + param_len; + memcpy(buffer, WMT_OVER_HCI_CMD_HDR, HCI_CMD_HDR_LEN); + buffer[3] = WMT_CMD_HDR_LEN + param_len; + memcpy(buffer + HCI_CMD_HDR_LEN, &wmt_cmd, WMT_CMD_HDR_LEN + param_len); + + p_inter_cmd->waiting_event = 0xE4; + p_inter_cmd->pending_cmd_opcode = 0xFC6F; + p_inter_cmd->wmt_opcode = WMT_OPCODE_FUNC_CTRL; + p_inter_cmd->result = WMT_EVT_INVALID; + + btmtk_main_send_cmd(hdev, buffer, pkt_len, BTMTKUART_TX_WAIT_VND_EVT); + + ret = (p_inter_cmd->result == WMT_EVT_SUCCESS) ? 0 : -EIO; + bdev->event_intercept = FALSE; + up(&bdev->internal_cmd_sem); + BTMTK_INFO("[InternalCmd] %s done, result = %s", __func__, _internal_evt_result(p_inter_cmd->result)); + return ret; +} + +/* btmtk_send_wmt_power_on_cmd + * + * Send BT func on + * + * Arguments: + * [IN] hdev - hci_device as control structure during BT life cycle + * + * Return Value: + * 0 if success, otherwise -EIO + * + */ +int32_t btmtk_send_wmt_power_on_cmd(struct hci_dev *hdev) +{ + struct btmtk_dev *bdev = hci_get_drvdata(hdev); + int ret = 0; + + ret = _send_wmt_power_cmd(hdev, TRUE); + if (!ret) { + bdev->bt_state = FUNC_ON; + bt_notify_state(bdev); + } else { + if (++bdev->rst_count > 3) + conninfra_trigger_whole_chip_rst(CONNDRV_TYPE_BT, + "power on fail more than 3 times"); + + bt_dump_cpupcr(10, 5); + bt_dump_bgfsys_debug_cr(); + } + + return ret; +} + +/* btmtk_send_wmt_power_off_cmd + * + * Send BT func off (cmd won't send during reset flow) + * + * Arguments: + * [IN] hdev - hci_device as control structure during BT life cycle + * + * Return Value: + * 0 if success, otherwise -EIO + * + */ +int32_t btmtk_send_wmt_power_off_cmd(struct hci_dev *hdev) +{ + struct btmtk_dev *bdev = hci_get_drvdata(hdev); + int32_t ret = 0; + + /* Do not send CMD to connsys while connsys is resetting */ + if (bdev->bt_state == FUNC_OFF) { + BTMTK_INFO("already at off state, skip command"); + return 0; + } else if (bdev->bt_state != RESET_START) + ret = _send_wmt_power_cmd(hdev, FALSE); + + BTMTK_INFO("%s: Done", __func__); + return ret; +} + +/* btmtk_get_cal_data_ref + * + * Send query calibration data command to FW and wait for response (event) + * to get calibration data (for backup calibration data purpose) + * + * + * Arguments: + * [IN] hdev - hci_device as control structure during BT life cycle + * [OUT] p_start_addr - start offset to SYSRAM that stores calibration data + * [OUT] p_ready_addr - ready address for indicating restore calibration data + * successfully + * [OUT] p_data_len - length of calibration data + * + * Return Value: + * 0 if success, otherwise -EIO + * + */ +static int32_t btmtk_get_cal_data_ref( + struct hci_dev *hdev, + uint32_t *p_start_addr, + uint32_t *p_ready_addr, + uint16_t *p_data_len +) +{ + struct btmtk_dev *bdev = hci_get_drvdata(hdev); + struct wmt_pkt wmt_cmd; + uint8_t buffer[HCI_MAX_FRAME_SIZE]; + uint16_t param_len, pkt_len; + struct bt_internal_cmd *p_inter_cmd = &bdev->internal_cmd; + int ret; + + BTMTK_INFO("[InternalCmd] %s", __func__); + down(&bdev->internal_cmd_sem); + bdev->event_intercept = TRUE; + + wmt_cmd.hdr.dir = WMT_PKT_DIR_HOST_TO_CHIP; + wmt_cmd.hdr.opcode = WMT_OPCODE_RF_CAL; + wmt_cmd.params.u.rf_cal_cmd.subop = 0x03; + param_len = sizeof(wmt_cmd.params.u.rf_cal_cmd); + + + wmt_cmd.hdr.param_len[0] = (uint8_t)(param_len & 0xFF); + wmt_cmd.hdr.param_len[1] = (uint8_t)((param_len >> 8) & 0xFF); + + pkt_len = HCI_CMD_HDR_LEN + WMT_CMD_HDR_LEN + param_len; + memcpy(buffer, WMT_OVER_HCI_CMD_HDR, HCI_CMD_HDR_LEN); + buffer[3] = WMT_CMD_HDR_LEN + param_len; + memcpy(buffer + HCI_CMD_HDR_LEN, &wmt_cmd, WMT_CMD_HDR_LEN + param_len); + + /* Save the necessary information to internal_cmd struct */ + p_inter_cmd->waiting_event = 0xE4; + p_inter_cmd->pending_cmd_opcode = 0xFC6F; + p_inter_cmd->wmt_opcode = WMT_OPCODE_RF_CAL; + p_inter_cmd->result = WMT_EVT_INVALID; + + ret = btmtk_main_send_cmd(hdev, buffer, pkt_len, BTMTKUART_TX_WAIT_VND_EVT); + + if (ret <= 0) { + BTMTK_ERR("Unable to get calibration event in time, start dump and reset!"); + // TODO: FW request dump & reset, need apply to all internal cmdÃ¥ + bt_trigger_reset(); + return -1; + } + + *p_start_addr = (p_inter_cmd->wmt_event_params.u.rf_cal_evt.start_addr[3] << 24) | + (p_inter_cmd->wmt_event_params.u.rf_cal_evt.start_addr[2] << 16) | + (p_inter_cmd->wmt_event_params.u.rf_cal_evt.start_addr[1] << 8) | + (p_inter_cmd->wmt_event_params.u.rf_cal_evt.start_addr[0]); + *p_ready_addr = (p_inter_cmd->wmt_event_params.u.rf_cal_evt.ready_addr[3] << 24) | + (p_inter_cmd->wmt_event_params.u.rf_cal_evt.ready_addr[2] << 16) | + (p_inter_cmd->wmt_event_params.u.rf_cal_evt.ready_addr[1] << 8) | + (p_inter_cmd->wmt_event_params.u.rf_cal_evt.ready_addr[0]); + *p_data_len = (p_inter_cmd->wmt_event_params.u.rf_cal_evt.data_len[1] << 8) | + (p_inter_cmd->wmt_event_params.u.rf_cal_evt.data_len[0]); + + if (p_inter_cmd->result == WMT_EVT_SUCCESS) + ret = 0; + else { + uint32_t offset = *p_start_addr & 0x0000FFFF; + uint8_t *data = NULL; + + if(offset > 0x1000) + BTMTK_ERR("Error calibration offset (%d)", offset); + else { + data = (uint8_t *)(CON_REG_INFRA_SYS_ADDR + offset); + + BTMTK_ERR("Calibration fail, dump calibration data"); + if(*p_data_len < BT_CR_DUMP_BUF_SIZE) + bt_dump_memory8(data, *p_data_len); + else + BTMTK_ERR("get wrong calibration length [%d]", *p_data_len); + } + ret = -EIO; + } + + /* Whether succeed or not, no one is waiting, reset the flag here */ + bdev->event_intercept = FALSE; + up(&bdev->internal_cmd_sem); + BTMTK_INFO("[InternalCmd] %s done, result = %s", __func__, _internal_evt_result(p_inter_cmd->result)); + return ret; +} + +/* btmtk_send_calibration_cmd + * + * Check calibration cache and send query calibration data command if + * cache is not available + * + * + * Arguments: + * [IN] hdev - hci_device as control structure during BT life cycle + * + * Return Value: + * N/A + * + */ +int32_t btmtk_send_calibration_cmd(struct hci_dev *hdev) +{ + struct btmtk_dev *bdev = hci_get_drvdata(hdev); + uint32_t cal_data_start_addr = 0; + uint32_t cal_data_ready_addr = 0; + uint16_t cal_data_len = 0; + uint8_t *p_cal_data = NULL; + int ret = 0; + + if (bdev->cal_data.p_cache_buf) { + BTMTK_DBG("calibration cache has data, no need to recal"); + return 0; + } + + /* + * In case that we did not have a successful pre-calibration and no + * cached data to restore, the first BT func on will trigger calibration, + * but it is most likely to be failed due to Wi-Fi is off. + * + * If BT func on return success and we get here, anyway try to backup + * the calibration data, any failure during backup should be ignored. + */ + + /* Get calibration data reference for backup */ + ret = btmtk_get_cal_data_ref(hdev, &cal_data_start_addr, + &cal_data_ready_addr, + &cal_data_len); + if (ret) + BTMTK_ERR("Get cal data ref failed!"); + else { + BTMTK_DBG( + "Get cal data ref: saddr(0x%08x) raddr(0x%08x) len(%d)", + cal_data_start_addr, cal_data_ready_addr, cal_data_len); + + /* Allocate a cache buffer to backup the calibration data in driver */ + if (cal_data_len) { + p_cal_data = kmalloc(cal_data_len, GFP_KERNEL); + if (p_cal_data) { + bgfsys_cal_data_backup(cal_data_start_addr, p_cal_data, cal_data_len); + bdev->cal_data.p_cache_buf = p_cal_data; + bdev->cal_data.cache_len = cal_data_len; + bdev->cal_data.start_addr = cal_data_start_addr; + bdev->cal_data.ready_addr = cal_data_ready_addr; + } else + BTMTK_ERR("Failed to allocate cache buffer for backup!"); + } else + BTMTK_ERR( + "Abnormal cal data length! something error with F/W!"); + } + return ret; +} + + +/* btmtk_set_power_on + * + * BT On flow including all steps exclude BT func on commaond + * + * + * Arguments: + * [IN] hdev - hci_device as control structure during BT life cycle + * [IN] for_precal - power on in pre-calibation flow, and don't + * call coninfra_pwr_on if the value is TRUE + * + * Return Value: + * 0 if success, otherwise error code + * + */ +int32_t btmtk_set_power_on(struct hci_dev *hdev, u_int8_t for_precal) +{ + int ret; + int sch_ret = -1; + struct sched_param sch_param; +#if SUPPORT_BT_THREAD + struct btmtk_dev *bdev = hci_get_drvdata(hdev); +#endif + + /* + * 1. ConnInfra hardware power on (Must be the first step) + * + * We will block in this step if conninfra driver find that the pre-calibration + * has not been performed, conninfra driver should guarantee to trigger + * pre-calibration procedure first: + * - call BT/Wi-Fi registered pwr_on_cb and do_cal_cb + * then return from this API after 2.4G calibration done. + */ + if (!for_precal) + { + if (conninfra_pwr_on(CONNDRV_TYPE_BT)) { + BTMTK_ERR("ConnInfra power on failed!"); + ret = -EIO; + goto conninfra_error; + } + } + + BTMTK_DBG("%s: wait halt_sem...", __func__); + down(&bdev->halt_sem); + BTMTK_DBG("%s: wait halt_sem finish...", __func__); + + /* record current bt state for restoring orginal state after pre-cal */ + bdev->bt_precal_state = g_bdev->bt_state; + + /* state check before power on */ + if (bdev->bt_state == FUNC_ON) { + BTMTK_INFO("BT is already on, skip"); + up(&bdev->halt_sem); + return 0; + } else if (bdev->bt_state != FUNC_OFF) { + BTMTK_ERR("BT is not at off state, uanble to on [%d]!", + bdev->bt_state); + up(&bdev->halt_sem); + return -EIO; + } + BTMTK_INFO("%s: CONNAC20_CHIPID[%d], bdev[0x%p], bt_state[%d]!", + __func__, CONNAC20_CHIPID, bdev, bdev->bt_state); + + bdev->bt_state = TURNING_ON; + + /* 2. MD coex ccif on */ + bgfsys_ccif_on(); + + /* 3. clear coredump */ +#if SUPPORT_COREDUMP + if (!bdev->coredump_handle) + BTMTK_ERR("Coredump handle is NULL\n"); + else + connsys_coredump_clean(bdev->coredump_handle); +#endif + + /* 4. BGFSYS hardware and MCU bring up, BT RAM code ready */ + ret = bt_hw_and_mcu_on(); + if (ret) { + BTMTK_ERR("BT hardware and MCU on failed!"); + goto mcu_error; + } + + + /* 5. initialize bdev variables */ + if (bdev->evt_skb) + kfree_skb(bdev->evt_skb); + bdev->evt_skb = NULL; + + bdev->event_intercept = FALSE; + bdev->internal_cmd.waiting_event = 0x00; + bdev->internal_cmd.pending_cmd_opcode = 0x0000; + bdev->internal_cmd.wmt_opcode = 0x00; + bdev->internal_cmd.result = WMT_EVT_INVALID; + + bdev->rx_ind = FALSE; + bdev->psm.state = PSM_ST_SLEEP; + bdev->psm.sleep_flag = FALSE; + bdev->psm.wakeup_flag = FALSE; + bdev->psm.result = 0; + bdev->psm.force_on = FALSE; + +#if (USE_DEVICE_NODE == 1) + btmtk_rx_flush(); +#endif + +#if SUPPORT_BT_THREAD + /* 6. Create TX thread with PS state machine */ + skb_queue_purge(&bdev->tx_queue); + init_waitqueue_head(&bdev->tx_waitq); + bdev->tx_thread = kthread_create(btmtk_tx_thread, bdev, "bt_tx_ps"); + if (IS_ERR(bdev->tx_thread)) { + BTMTK_DBG("btmtk_tx_thread failed to start!"); + ret = PTR_ERR(bdev->tx_thread); + goto thread_create_error; + } + + if(g_bt_dbg_st.rt_thd_enable) { + sch_param.sched_priority = MAX_RT_PRIO - 20; + sch_ret = sched_setscheduler(bdev->tx_thread, SCHED_FIFO, &sch_param); + BTMTK_INFO("sch_ret = %d", sch_ret); + if (sch_ret != 0) + BTMTK_INFO("set RT to workqueue failed"); + else + BTMTK_INFO("set RT to workqueue succeed"); + } + wake_up_process(bdev->tx_thread); +#endif + + /* + * 7. Calibration data restore + * If we have a cache of calibration data, restore it to Firmware sysram, + * otherwise, BT func on will trigger calibration again. + */ + if (bdev->cal_data.p_cache_buf) + bgfsys_cal_data_restore(bdev->cal_data.start_addr, + bdev->cal_data.ready_addr, + bdev->cal_data.p_cache_buf, + bdev->cal_data.cache_len); + +#if SUPPORT_COREDUMP + if (!bdev->coredump_handle) + BTMTK_ERR("Coredump handle is NULL\n"); + else + connsys_coredump_setup_dump_region(bdev->coredump_handle); +#endif + + bt_enable_irq(BGF2AP_SW_IRQ); + + /* 8. init cmd queue and workqueue */ +#if (DRIVER_CMD_CHECK == 1) + cmd_list_initialize(); + cmd_workqueue_init(); + bdev->cmd_timeout_check = FALSE; +#endif + dump_queue_initialize(); + + /* 9. send WMT cmd to set BT on */ + ret = btmtk_send_wmt_power_on_cmd(hdev); + if (ret) { + BTMTK_ERR("btmtk_send_wmt_power_on_cmd fail"); + goto wmt_power_on_error; + } + + /* Set utc_sync & blank_state cmd */ + btmtk_send_utc_sync_cmd(); + btmtk_send_blank_status_cmd(hdev, bdev->blank_state); + + /* clear reset count if power on success */ + bdev->rst_level = RESET_LEVEL_NONE; + bdev->rst_count = 0; + + up(&bdev->halt_sem); + + return 0; + +wmt_power_on_error: + wake_up_interruptible(&bdev->tx_waitq); + kthread_stop(bdev->tx_thread); + bdev->tx_thread = NULL; +#if (DRIVER_CMD_CHECK == 1) + cmd_workqueue_exit(); + cmd_list_destory(); + bdev->cmd_timeout_check = FALSE; +#endif + +thread_create_error: + bt_hw_and_mcu_off(); + +mcu_error: + bgfsys_ccif_off(); + if (!for_precal) + conninfra_pwr_off(CONNDRV_TYPE_BT); + up(&bdev->halt_sem); + +conninfra_error: + bdev->bt_state = FUNC_OFF; + return ret; +} + +/* btmtk_set_power_off + * + * BT off flow + * + * + * Arguments: + * [IN] hdev - hci_device as control structure during BT life cycle + * [IN] for_precal - power on in pre-calibation flow, and don't + * call coninfra_pwr_off if the value is TRUE + * + * Return Value: + * N/A + * + */ +int32_t btmtk_set_power_off(struct hci_dev *hdev, u_int8_t for_precal) +{ + struct btmtk_dev *bdev = hci_get_drvdata(hdev); + + BTMTK_INFO("%s", __func__); + + down(&bdev->halt_sem); + + if (bdev->bt_state == FUNC_OFF) { + BTMTK_WARN("Alread in off state, skip"); + up(&bdev->halt_sem); + return 0; + /* Do not power off while chip reset thread is doing coredump */ + } else if ((bdev->bt_state == FUNC_ON || bdev->bt_state == TURNING_ON) + && bdev->rst_level != RESET_LEVEL_NONE) { + BTMTK_WARN("BT is coredump, ignore stack power off"); + up(&bdev->halt_sem); + return 0; + } + + /* 1. Send WMT cmd to set BT off */ + btmtk_send_wmt_power_off_cmd(hdev); + + /* 2. Stop TX thread */ +#if SUPPORT_BT_THREAD + if (bdev->tx_thread) { + wake_up_interruptible(&bdev->tx_waitq); + kthread_stop(bdev->tx_thread); + } + bdev->tx_thread = NULL; + skb_queue_purge(&bdev->tx_queue); +#endif + + /* 3. BGFSYS hardware and MCU shut down */ + bt_hw_and_mcu_off(); + BTMTK_DBG("BT hardware and MCU off!"); + + /* 4. MD Coex ccif */ + bgfsys_ccif_off(); + + /* 5. close cmd queue and workqueue */ +#if (DRIVER_CMD_CHECK == 1) + cmd_workqueue_exit(); + cmd_list_destory(); + bdev->cmd_timeout_check = FALSE; +#endif + + bdev->bt_state = FUNC_OFF; + + up(&bdev->halt_sem); + /* 6. ConnInfra hardware power off */ + if (!for_precal) + conninfra_pwr_off(CONNDRV_TYPE_BT); + + /* Delay sending HW error to stack if it's whole chip reset, + * we have to wait conninfra power on then send message or + * stack triggers BT on will fail bcz conninfra is not power on + */ + if (bdev->rst_level != RESET_LEVEL_0) + bt_notify_state(bdev); + + BTMTK_INFO("ConnInfra power off!"); + + return 0; +} + +/* btmtk_set_sleep + * + * Request driver to enter sleep mode (FW own), and restore the state from + * btmtk_set_wakeup (this api makes driver stay at wakeup all the time) + * + * + * Arguments: + * [IN] hdev - hci_device as control structure during BT life cycle + * + * Return Value: + * N/A + * + */ +int32_t btmtk_set_sleep(struct hci_dev *hdev, uint8_t need_wait) +{ + struct btmtk_dev *bdev = hci_get_drvdata(hdev); + +#if SUPPORT_BT_THREAD + bdev->psm.sleep_flag = TRUE; + wake_up_interruptible(&bdev->tx_waitq); + + if (!need_wait) + return 0; + + if (!wait_for_completion_timeout(&bdev->psm.comp, msecs_to_jiffies(1000))) { + BTMTK_ERR("[PSM]Timeout for BGFSYS to enter sleep!"); + bdev->psm.sleep_flag = FALSE; + return -1; + } + + BTMTK_DBG("[PSM]sleep return %s, sleep(%d), wakeup(%d)", + (bdev->psm.result == 0) ? "success" : "failure", + bdev->psm.sleep_flag, bdev->psm.wakeup_flag); + + return 0; +#else + BTMTK_ERR("%s: [PSM] Doesn't support non-thread mode !", __func__); + return -1; +#endif + + +} + +/* btmtk_set_wakeup + * + * Force BT driver/FW awake all the time + * + * + * Arguments: + * [IN] hdev - hci_device as control structure during BT life cycle + * + * Return Value: + * N/A + * + */ +int32_t btmtk_set_wakeup(struct hci_dev *hdev) +{ + struct btmtk_dev *bdev = hci_get_drvdata(hdev); + +#if SUPPORT_BT_THREAD + wake_up_interruptible(&bdev->tx_waitq); +#else + BTMTK_ERR("%s: [PSM] Doesn't support non-thread mode !", __func__); + return -1; +#endif + + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_mt66xx_reg.h b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_mt66xx_reg.h new file mode 100644 index 0000000000000..9c08f8d0627b4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_mt66xx_reg.h @@ -0,0 +1,880 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _BT_REG_H +#define _BT_REG_H + +//#include "typedef.h" +#include "conninfra.h" +#include "connsys_debug_utility.h" + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifndef BIT +#define BIT(n) (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) ((unsigned long)&(((_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. + * _addr_of_field - address of a field within the structure, + * _type - structure name, + * _field - field name of the structure + */ +#ifndef ENTRY_OF +#define ENTRY_OF(_addr_of_field, _type, _field) \ + ((_type *)((unsigned char *)(_addr_of_field) - (unsigned char *)OFFSET_OF(_type, _field))) +#endif /* ENTRY_OF */ + +#define BT_CR_DUMP_BUF_SIZE (1024) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +struct consys_reg_base_addr { + unsigned long vir_addr; + unsigned long phy_addr; + unsigned long long size; +}; + +enum bt_base_addr_index { + CONN_INFRA_RGU_BASE_INDEX = 0, + CONN_INFRA_CFG_BASE_INDEX = 1, + CONN_INFRA_SYS_BASE_INDEX = 2, + SPM_BASE_INDEX = 3, + + BGFSYS_BASE_INDEX = 4, + BGFSYS_INFO_BASE_INDEX = 5, + + INFRACFG_AO_BASE_INDEX = 6, +#if 0 + CONN_INFRA_CFG_CCIF_BASE = 7, + BGF2MD_BASE_INDEX = 8, +#endif + + CONSYS_BASE_ADDR_MAX +}; + +struct bt_base_addr { + struct consys_reg_base_addr reg_base_addr[CONSYS_BASE_ADDR_MAX]; +}; + +extern struct bt_base_addr bt_reg; +extern int32_t bgfsys_check_conninfra_ready(void); + +#define CON_REG_INFRA_RGU_ADDR bt_reg.reg_base_addr[CONN_INFRA_RGU_BASE_INDEX].vir_addr /* 0x18000000 0x1000 */ +#define CON_REG_INFRA_CFG_ADDR bt_reg.reg_base_addr[CONN_INFRA_CFG_BASE_INDEX].vir_addr /* 0x18001000 0x1000 */ +#define CON_REG_INFRA_SYS_ADDR bt_reg.reg_base_addr[CONN_INFRA_SYS_BASE_INDEX].vir_addr /* 0x18050000 0x1000 */ +#define CON_REG_SPM_BASE_ADDR bt_reg.reg_base_addr[SPM_BASE_INDEX].vir_addr /* 0x18060000 0x1000 */ +#define BGF_REG_BASE_ADDR bt_reg.reg_base_addr[BGFSYS_BASE_INDEX].vir_addr /* 0x18800000 0x1000 */ +#define BGF_REG_INFO_BASE_ADDR bt_reg.reg_base_addr[BGFSYS_INFO_BASE_INDEX].vir_addr /* 0x18812000 0x1000 */ +#define CON_REG_INFRACFG_AO_ADDR bt_reg.reg_base_addr[INFRACFG_AO_BASE_INDEX].vir_addr /* 0x10001000 0x1000 */ +#if 0 +#define CON_REG_INFRA_CCIF_ADDR bt_reg.reg_base_addr[CONN_INFRA_CFG_CCIF_BASE].vir_addr +#define BGF2MD_BASE_ADDR bt_reg.reg_base_addr[BGF2MD_BASE_INDEX].vir_addr +#endif + +static uint8_t g_dump_cr_buffer[BT_CR_DUMP_BUF_SIZE]; + +/********************************************************************* +* +* Connsys Control Register Definition +* +********************************************************************** +*/ +#define SET_BIT(addr, bit) \ + (*((volatile uint32_t *)(addr))) |= ((uint32_t)bit) +#define CLR_BIT(addr, bit) \ + (*((volatile uint32_t *)(addr))) &= ~((uint32_t)bit) +#define REG_READL(addr) \ + readl((volatile uint32_t *)(addr)) +#define REG_WRITEL(addr, val) \ + writel(val, (volatile uint32_t *)(addr)) + +/* + * EMI region + */ +#define BT_EMI_BASE_OFFSET 0x000000000 + +/* + * ConnInfra Control Register Region: + * (CONN_INFRA_BASE) ~ (CONN_INFRA_BASE + CONN_INFRA_LENGTH) + */ +#define CONN_INFRA_BASE 0x18000000 /* variable */ + +/* + * Conninfra CFG AO + * + */ +#define CONN_INFRA_CFG_AO_BASE CON_REG_INFRACFG_AO_ADDR +#define BGF_PAD_EINT (CONN_INFRA_CFG_AO_BASE + 0xF00) + +#if 0 +/* + * CCIF Base + * + */ +#define CONN_INFRA_CFG_CCIF_BASE CON_REG_INFRA_CCIF_ADDR +#define CCIF_CONSYS_BGF_ADDR (CONN_INFRA_CFG_CCIF_BASE + 0x318) + +/* + * BGF2MD Base + * + */ +#define CONN_BGF2MD_BASE BGF2MD_BASE_ADDR +#define CONN_PCCIF5_RX_ACK (BGF2MD_BASE_ADDR + 0x14) +#endif + +/* + * ConnInfra RGU Region + */ +#define CONN_INFRA_RGU_START CON_REG_INFRA_RGU_ADDR + +#define CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_CTL (CONN_INFRA_RGU_START + 0x0008) +#define BGF_PWR_CTL_B BIT(7) + +#define CONN_INFRA_RGU_BGFSYS_CPU_SW_RST (CONN_INFRA_RGU_START + 0x0014) +#define BGF_CPU_SW_RST_B BIT(0) + +#define CONN_INFRA_RGU_BGFSYS_SW_RST_B (CONN_INFRA_RGU_START + 0x001C) +#define BGF_SW_RST_B BIT(0) + +#define CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_ACK_ST (CONN_INFRA_RGU_START + 0x0114) +#define BGF_ON_PWR_ACK_B BITS(24, 25) + +#define CONN_INFRA_RGU_BGFSYS_OFF_TOP_PWR_ACK_ST (CONN_INFRA_RGU_START + 0x0124) +#define BGF_OFF_PWR_ACK_B BIT(24) +#define BGF_OFF_PWR_ACK_S BITS(0, 1) + + + + + +/* + * ConnInfra CFG Region + */ +#define CONN_INFRA_CFG_START CON_REG_INFRA_CFG_ADDR + +#define CONN_INFRA_CFG_VERSION (CONN_INFRA_CFG_START) + +#define CONN_INFRA_CONN2BT_GALS_SLP_CTL (CONN_INFRA_CFG_START + 0x0610) +#define CONN2BT_SLP_PROT_TX_EN_B BIT(0) +#define CONN2BT_SLP_PROT_TX_ACK_B BIT(3) +#define CONN2BT_SLP_PROT_RX_EN_B BIT(4) +#define CONN2BT_SLP_PROT_RX_ACK_B BIT(7) + +#define CONN_INFRA_BT2CONN_GALS_SLP_CTL (CONN_INFRA_CFG_START + 0x0614) +#define BT2CONN_SLP_PROT_TX_EN_B BIT(0) +#define BT2CONN_SLP_PROT_TX_ACK_B BIT(3) +#define BT2CONN_SLP_PROT_RX_EN_B BIT(4) +#define BT2CONN_SLP_PROT_RX_ACK_B BIT(7) + +#define CONN_INFRA_CFG_BT_PWRCTLCR0 (CONN_INFRA_CFG_START + 0x0874) +#define BT_FUNC_EN_B BIT(0) + +#define CONN_INFRA_CFG_EMI_CTL_BT_EMI_REQ_BT (CONN_INFRA_CFG_START + 0x0C18) +#define BT_EMI_CTRL_BIT BIT(0) +#define BT_EMI_CTRL_BIT1 BIT(1) + +/* + * Connsys Host CSR Top Region + */ +#define CONN_HOST_CSR_TOP_START CON_REG_SPM_BASE_ADDR + +#define CONN_INFRA_WAKEUP_BT (CONN_HOST_CSR_TOP_START + 0x01A8) +#define CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL (CONN_HOST_CSR_TOP_START + 0x0184) + +#define CONN_REMAP_ADDR (CONN_HOST_CSR_TOP_START + 0x01C4) + +#define CONN_INFRA_ON2OFF_SLP_PROT_ACK BIT(5) + +#define CONN_MCU_PC (CONN_HOST_CSR_TOP_START + 0x22C) + +#define BGF_LPCTL (CONN_HOST_CSR_TOP_START + 0x0030) +#define BGF_HOST_SET_FW_OWN_B BIT(0) +#define BGF_HOST_CLR_FW_OWN_B BIT(1) +#define BGF_OWNER_STATE_SYNC_B BIT(2) + +#define BGF_IRQ_STAT (CONN_HOST_CSR_TOP_START + 0x0034) +#define BGF_IRQ_FW_OWN_CLR_B BIT(0) + +#define BGF_IRQ_EN (CONN_HOST_CSR_TOP_START + 0x0038) +#define BGF_IRQ_DRV_OWN_EN_B BIT(0) +#define BGF_IRQ_FW_OWN_EN_B BIT(1) + +#define BGF_IRQ_STAT2 (CONN_HOST_CSR_TOP_START + 0x003C) +#define BGF_IRQ_FW_OWN_SET_B BIT(0) + +/* + * BGFSYS Control Register Region: + * (BGFSYS_BASE) ~ (BGFSYS_BASE + BGFSYS_LENGTH) + */ +#define BGFSYS_BASE 0x18800000 + +#define BGF_MCCR (BGF_REG_BASE_ADDR + 0x0100) +#define BGF_CON_CR_AHB_AUTO_DIS BIT(31) + +#define BGF_MCCR_SET (BGF_REG_BASE_ADDR + 0x0104) +#define BGF_CON_CR_AHB_STOP BIT(2) + +#define BGF_SW_IRQ_RESET_ADDR (BGF_REG_BASE_ADDR + 0x014C) +#define BGF_SW_IRQ_STATUS (BGF_REG_BASE_ADDR + 0x0150) +#define BGF_WHOLE_CHIP_RESET BIT(26) +#define BGF_SUBSYS_CHIP_RESET BIT(25) +#define BGF_FW_LOG_NOTIFY BIT(24) + +#define BGF_MCU_CFG_SW_DBG_CTL (BGF_REG_BASE_ADDR + 0x016C) + +#define BGF_HW_VERSION BGF_REG_INFO_BASE_ADDR +#define BGF_HW_VER_ID 0x00008A00 + +#define BGF_FW_VERSION (BGF_REG_INFO_BASE_ADDR + 0x04) +#define BGF_FW_VER_ID 0x00008A00 + +#define BGF_HW_CODE (BGF_REG_INFO_BASE_ADDR + 0x08) +#define BGF_HW_CODE_ID 0x00000000 + +#define BGF_IP_VERSION (BGF_REG_INFO_BASE_ADDR + 0x10) +#define BGF_IP_VER_ID 0x20010000 + + +#define CAN_DUMP_HOST_CSR(reason) \ + (reason != CONNINFRA_INFRA_BUS_HANG && \ + reason != CONNINFRA_AP2CONN_RX_SLP_PROT_ERR && \ + reason != CONNINFRA_AP2CONN_TX_SLP_PROT_ERR && \ + reason != CONNINFRA_AP2CONN_CLK_ERR) + +/********************************************************************* +* +* CR/Constant value for specific project +* +********************************************************************** +*/ +#define _BIN_NAME_POSTFIX ".bin" +#define _BIN_NAME_UPDATE_POSTFIX "-u.bin" + +#if (CONNAC20_CHIPID == 6885) +#ifdef BT_CUS_FEATURE + #define _BIN_NAME_MCU "soc3_0_ram_mcu_1b_1_hdr" + #define _BIN_NAME_BT "soc3_0_ram_bt_1b_1_hdr" +#else + #define _BIN_NAME_MCU "soc3_0_ram_mcu_1_1_hdr" + #define _BIN_NAME_BT "soc3_0_ram_bt_1_1_hdr" +#endif + #define CONN_INFRA_CFG_ID (0x20010000) +#elif (CONNAC20_CHIPID == 6893) + #define _BIN_NAME_MCU "soc3_0_ram_mcu_1a_1_hdr" + #define _BIN_NAME_BT "soc3_0_ram_bt_1a_1_hdr" + #define CONN_INFRA_CFG_ID (0x20010101) +#endif + +#define BIN_NAME_MCU (_BIN_NAME_MCU _BIN_NAME_POSTFIX) +#define BIN_NAME_BT (_BIN_NAME_BT _BIN_NAME_POSTFIX) +#define BIN_NAME_MCU_U (_BIN_NAME_MCU _BIN_NAME_UPDATE_POSTFIX) +#define BIN_NAME_BT_U (_BIN_NAME_BT _BIN_NAME_UPDATE_POSTFIX) + +/* bt_dump_cpucpr + * + * Dump cpu counter for a period of time + * + * Arguments: + * [IN] times how many times to dump CR + * [IN] sleep_ms sleep interval b/w each dump + * + * Return Value: + * N/A + * + */ +static void inline bt_dump_cpupcr(uint32_t times, uint32_t sleep_ms) +{ + uint32_t i = 0; + uint32_t value = 0; + + for(i = 0; i < times; i++) { + value = REG_READL(CONN_MCU_PC); + BTMTK_DBG("%s: bt pc=0x%08x", __func__, value); + if (sleep_ms > 0) + msleep(sleep_ms); + } +} + +static uint32_t inline bt_read_cr(uint32_t addr) +{ + uint32_t value = 0; + uint8_t *base = ioremap_nocache(addr, 0x10); + + if (base == NULL) { + BTMTK_ERR("%s: remapping 0x%08x fail", addr); + } else { + value = REG_READL(base); + iounmap(base); + } + return value; +} + +static void inline bt_write_cr(uint32_t addr, uint32_t value) +{ + uint32_t *base = ioremap_nocache(addr, 0x10); + + if (base == NULL) { + BTMTK_ERR("%s: remapping 0x%08x fail", addr); + } else { + *base = value; + iounmap(base); + } +} + +static void inline bt_dump_memory8(uint8_t *buf, uint32_t len) +{ + uint32_t i = 0; + uint8_t *pos = NULL, *end = NULL; + int32_t ret = 0; + + memset(g_dump_cr_buffer, 0, BT_CR_DUMP_BUF_SIZE); + pos = &g_dump_cr_buffer[0]; + end = pos + BT_CR_DUMP_BUF_SIZE - 1; + + BTMTK_INFO("%s: length = (%d)", __func__, len); + for (i = 0; i <= len; i++) { + ret = snprintf(pos, (end - pos + 1), "%02x ", buf[i]); + if (ret < 0 || ret >= (end - pos + 1)) + break; + pos += ret; + + if ((i & 0xF) == 0xF || i == len - 1) { + BTMTK_INFO("%s", g_dump_cr_buffer); + memset(g_dump_cr_buffer, 0, BT_CR_DUMP_BUF_SIZE); + pos = &g_dump_cr_buffer[0]; + end = pos + BT_CR_DUMP_BUF_SIZE - 1; + } + } + +} + +static inline u_int8_t bt_is_bgf_bus_timeout(void) +{ + int32_t mailbox_status = 0; + + /* + * Conn-infra bus timeout : 160ms + * Bgf bus timeout : 80ms + * + * There's still a case that we pass conninfra check but still get + * bus hang, so we have to check mail box for sure + */ + mailbox_status = REG_READL(CON_REG_SPM_BASE_ADDR + 0x268); + if (mailbox_status != 0 && + (mailbox_status & 0xFF000000) != 0x87000000) { + BTMTK_INFO("mailbox_status = 0x%08x", mailbox_status); + return TRUE; + } + + return FALSE; +} + +static void inline bt_dump_bgfsys_host_csr(void) +{ + uint32_t value = 0; + uint32_t i = 0; + uint8_t *pos = NULL, *end = NULL; + int32_t ret = 0; + + memset(g_dump_cr_buffer, 0, BT_CR_DUMP_BUF_SIZE); + pos = &g_dump_cr_buffer[0]; + end = pos + BT_CR_DUMP_BUF_SIZE - 1; + + BTMTK_INFO("[BGF host csr] Count = 11"); + for (i = 0x22C; i <= 0x244; i+=4) { + value = REG_READL(CON_REG_SPM_BASE_ADDR + i); + ret = snprintf(pos, (end - pos + 1), "%08x ", value); + if (ret < 0 || ret >= (end - pos + 1)) + break; + pos += ret; + } + + for (i = 0x264; i <= 0x270; i+=4) { + value = REG_READL(CON_REG_SPM_BASE_ADDR + i); + ret = snprintf(pos, (end - pos + 1), "%08x ", value); + if (ret < 0 || ret >= (end - pos + 1)) + break; + pos += ret; + } + + BTMTK_INFO("%s", g_dump_cr_buffer); +} + +/* please make sure check bus hang before calling this dump */ +static void inline bt_dump_bgfsys_mcusys_flag(void) +{ + uint32_t value = 0; + uint32_t i = 0, count = 1, cr_count = 56; + uint8_t *pos = NULL, *end = NULL; + int32_t ret = 0; + uint16_t switch_flag = 0x2A; + + memset(g_dump_cr_buffer, 0, BT_CR_DUMP_BUF_SIZE); + pos = &g_dump_cr_buffer[0]; + end = pos + BT_CR_DUMP_BUF_SIZE - 1; + value = REG_READL(CON_REG_SPM_BASE_ADDR + 0xA0); + value &= 0xFFFFFF03; /* ignore [7:2] */ + value |= (switch_flag << 2); + REG_WRITEL(CON_REG_SPM_BASE_ADDR + 0xA0, value); + + BTMTK_INFO("[BGF MCUSYS debug flag] Count = (%d)", cr_count); + for (i = 0x00020101; i <= 0x00706F01; i+= 0x20200, count++) { + REG_WRITEL(CON_REG_SPM_BASE_ADDR + 0xA8, i); + value = REG_READL(CON_REG_SPM_BASE_ADDR + 0x22C); + ret = snprintf(pos, (end - pos + 1), "%08x ", value); + if (ret < 0 || ret >= (end - pos + 1)) + break; + pos += ret; + + if ((count & 0xF) == 0 || count == cr_count) { + BTMTK_INFO("%s", g_dump_cr_buffer); + memset(g_dump_cr_buffer, 0, BT_CR_DUMP_BUF_SIZE); + pos = &g_dump_cr_buffer[0]; + end = pos + BT_CR_DUMP_BUF_SIZE - 1; + } + } +} + +/* please make sure check bus hang before calling this dump */ +static void inline bt_dump_bgfsys_bus_flag(void) +{ + uint32_t value = 0; + uint32_t i = 0, j = 0, count = 1, cr_count = 20; + uint8_t *pos = NULL, *end = NULL; + int32_t ret = 0; + uint16_t switch_flag = 0x2A; + + + memset(g_dump_cr_buffer, 0, BT_CR_DUMP_BUF_SIZE); + pos = &g_dump_cr_buffer[0]; + end = pos + BT_CR_DUMP_BUF_SIZE - 1; + value = REG_READL(CON_REG_SPM_BASE_ADDR + 0xA0); + value &= 0xFFFFFF03; /* ignore [7:2] */ + value |= (switch_flag << 2); + REG_WRITEL(CON_REG_SPM_BASE_ADDR + 0xA0, value); + + if (conninfra_reg_readable() && !bt_is_bgf_bus_timeout()) { + value = bt_read_cr(0x1881E000); + value &= 0xFFFFFFEF; + value |= (1 << 4); + bt_write_cr(0x1881E000, value); + } else + BTMTK_ERR("conninfra is not readable"); + + BTMTK_INFO("[BGF BUS debug flag] Count = (%d)", cr_count); + for (i = 0x104A4901; i <= 0xA04A4901; i += 0x10000000) { + for (j = i; j <= i + 0x20200; j += 0x20200) { + REG_WRITEL(CON_REG_SPM_BASE_ADDR + 0xA8, j); + value = REG_READL(CON_REG_SPM_BASE_ADDR + 0x22C); + ret = snprintf(pos, (end - pos + 1), "%08x ", value); + if (ret < 0 || ret >= (end - pos + 1)) + break; + pos += ret; + count++; + + if ((count & 0xF) == 0 || count == cr_count) { + BTMTK_INFO("%s", g_dump_cr_buffer); + memset(g_dump_cr_buffer, 0, BT_CR_DUMP_BUF_SIZE); + pos = &g_dump_cr_buffer[0]; + end = pos + BT_CR_DUMP_BUF_SIZE - 1; + } + } + } +} + +static void inline bt_dump_bgfsys_top_common_flag(void) +{ + uint32_t value = 0; + uint32_t i = 0, count = 1, cr_count = 20; + uint8_t *pos = NULL, *end = NULL; + int32_t ret = 0; + + memset(g_dump_cr_buffer, 0, BT_CR_DUMP_BUF_SIZE); + pos = &g_dump_cr_buffer[0]; + end = pos + BT_CR_DUMP_BUF_SIZE - 1; + + BTMTK_INFO("[BGF TOP common/bt part debug flag] Count = (%d)", cr_count); + for (i = 0x80; i <= 0x93; i++, count++) { + REG_WRITEL(CON_REG_SPM_BASE_ADDR + 0xAC, i); + value = REG_READL(CON_REG_SPM_BASE_ADDR + 0x23C); + ret = snprintf(pos, (end - pos + 1), "%08x ", value); + if (ret < 0 || ret >= (end - pos + 1)) + break; + pos += ret; + + if ((count & 0xF) == 0 || count == cr_count) { + BTMTK_INFO("%s", g_dump_cr_buffer); + memset(g_dump_cr_buffer, 0, BT_CR_DUMP_BUF_SIZE); + pos = &g_dump_cr_buffer[0]; + end = pos + BT_CR_DUMP_BUF_SIZE - 1; + } + } +} + +/* please make sure check bus hang before calling this dump */ +static void inline bt_dump_bgfsys_mcu_core_flag(void) +{ + uint32_t value = 0; + uint32_t i = 0, count = 1, cr_count = 38; + uint8_t *pos = NULL, *end = NULL; + int32_t ret = 0; + uint16_t switch_flag = 0x2B; + + memset(g_dump_cr_buffer, 0, BT_CR_DUMP_BUF_SIZE); + pos = &g_dump_cr_buffer[0]; + end = pos + BT_CR_DUMP_BUF_SIZE - 1; + value = REG_READL(CON_REG_SPM_BASE_ADDR + 0xA0); + value &= 0xFFFFFF03; /* ignore [7:2] */ + value |= (switch_flag << 2); + REG_WRITEL(CON_REG_SPM_BASE_ADDR + 0xA0, value); + + BTMTK_INFO("[BGF MCU core debug flag] Count = (%d)", cr_count); + + /* gpr0 ~ ipc */ + for (i = 0x3; i <= 0x25000003; i+= 0x1000000, count++) { + REG_WRITEL(CON_REG_SPM_BASE_ADDR + 0xA8, i); + value = REG_READL(CON_REG_SPM_BASE_ADDR + 0x22C); + ret = snprintf(pos, (end - pos + 1), "%08x ", value); + if (ret < 0 || ret >= (end - pos + 1)) + break; + pos += ret; + + if ((count & 0xF) == 0 || count == cr_count) { + BTMTK_INFO("%s", g_dump_cr_buffer); + memset(g_dump_cr_buffer, 0, BT_CR_DUMP_BUF_SIZE); + pos = &g_dump_cr_buffer[0]; + end = pos + BT_CR_DUMP_BUF_SIZE - 1; + } + } +} + +static inline void bt_dump_bgfsys_mcu_pc_log(void) +{ + uint32_t value = 0; + uint32_t i = 0, count = 1, cr_count = 45; + uint8_t *pos = NULL, *end = NULL; + int32_t ret = 0; + + + memset(g_dump_cr_buffer, 0, BT_CR_DUMP_BUF_SIZE); + pos = &g_dump_cr_buffer[0]; + end = pos + BT_CR_DUMP_BUF_SIZE - 1; + + BTMTK_INFO("[BGF MCU PC log] Count = (%d)", cr_count); + for (i = 0x00; i <= 0x2C; i++, count++) { + value = REG_READL(CON_REG_SPM_BASE_ADDR + 0xA0); + value &= 0xFFFFFF03; /* ignore [7:2] */ + value |= (i << 2); + REG_WRITEL(CON_REG_SPM_BASE_ADDR + 0xA0, value); + + value = REG_READL(CON_REG_SPM_BASE_ADDR + 0x22C); + ret = snprintf(pos, (end - pos + 1), "%08x ", value); + if (ret < 0 || ret >= (end - pos + 1)) + break; + pos += ret; + + if ((count & 0xF) == 0 || count == cr_count) { + BTMTK_INFO("%s", g_dump_cr_buffer); + memset(g_dump_cr_buffer, 0, BT_CR_DUMP_BUF_SIZE); + pos = &g_dump_cr_buffer[0]; + end = pos + BT_CR_DUMP_BUF_SIZE - 1; + } + } +} + +static void bt_dump_bgfsys_all(void) +{ + /* these dump all belongs to host_csr */ + bt_dump_cpupcr(10, 0); + bt_dump_bgfsys_host_csr(); + bt_dump_bgfsys_mcu_pc_log(); + bt_dump_bgfsys_mcu_core_flag(); + bt_dump_bgfsys_mcusys_flag(); + bt_dump_bgfsys_bus_flag(); + bt_dump_bgfsys_top_common_flag(); +} + +/* bt_dump_bgfsys_debug_cr() + * + * Dump all bgfsys debug cr for debuging bus hang + * + * Arguments: + * N/A + * + * Return Value: + * N/A + * + */ +static inline void bt_dump_bgfsys_debug_cr(void) +{ + uint32_t offset = 0x410, value = 0, i = 0; + uint8_t *pos = NULL, *end = NULL; + int32_t ret = 0; + + ret = conninfra_is_bus_hang(); + BTMTK_INFO("%s: conninfra_is_bus_hang ret = %d", __func__, ret); + + if (!CAN_DUMP_HOST_CSR(ret)) { + BTMTK_ERR("%s; host csr is not readable", __func__); + return; + } + + if(bgfsys_check_conninfra_ready()) + goto host_csr_only; + + BTMTK_INFO("%s: M0 - M3 semaphore status:", __func__); + for (i = 0x18070400; i <= 0x18073400; i += 0x1000) { + value = bt_read_cr(i); + BTMTK_INFO("[0x%08x] = [0x%08x]", i, value); + } + + if (conninfra_reg_readable() && !bt_is_bgf_bus_timeout()) { + BTMTK_INFO("[BGF Bus hang debug CR (18800410~18000444)] Count = (14)"); + + memset(g_dump_cr_buffer, 0, BT_CR_DUMP_BUF_SIZE); + pos = &g_dump_cr_buffer[0]; + end = pos + BT_CR_DUMP_BUF_SIZE - 1; + for (offset = 0x410; offset <= 0x0444; offset += 4) { + ret = snprintf(pos, (end - pos + 1), "%08x ", + REG_READL(BGF_REG_BASE_ADDR + offset)); + if (ret < 0 || ret >= (end - pos + 1)) + break; + pos += ret; + } + BTMTK_INFO("%s", g_dump_cr_buffer); + } else + BTMTK_INFO("conninfra is not readable, skip [BGF Bus hang debug CR]"); + +host_csr_only: + bt_dump_bgfsys_all(); + /* release conn_infra force on */ + CLR_BIT(CONN_INFRA_WAKEUP_BT, BIT(0)); +} + +/* bt_cif_dump_own_cr + * + * Dump fw/driver own relative cr (plus cpucpr) if + * driver own or fw own fail + * + * Arguments: + * N/A + * + * Return Value: + * N/A + * + */ +static inline void bt_dump_cif_own_cr(void) +{ + uint32_t value = 0, i = 0; + int32_t ret = 0; + + ret = conninfra_is_bus_hang(); + BTMTK_INFO("%s: conninfra_is_bus_hang ret = %d", __func__, ret); + + if (!CAN_DUMP_HOST_CSR(ret)) { + BTMTK_ERR("%s; host csr is not readable", __func__); + return; + } + + if(bgfsys_check_conninfra_ready()) + goto host_csr_only; + + /* following CR only accessible while bus is not hang */ + if (!ret ) { + value = REG_READL(CON_REG_INFRA_CFG_ADDR + 0x400); + BTMTK_INFO("0x18001400 = [0x%08x]", value); + + value = REG_READL(CON_REG_INFRA_CFG_ADDR + 0x41C); + BTMTK_INFO("0x1800141C = [0x%08x]", value); + + value = REG_READL(CON_REG_INFRA_CFG_ADDR + 0x420); + BTMTK_INFO("0x18001420 = [0x%08x]", value); + + value = 0x87654321; + REG_WRITEL(CON_REG_INFRA_CFG_ADDR + 0x10, value); + value = REG_READL(CON_REG_INFRA_CFG_ADDR + 0x10); + BTMTK_INFO("0x18001010 = [0x%08x]", value); + + value = REG_READL(CON_REG_INFRA_CFG_ADDR + 0x160); + BTMTK_INFO("0x18001160 = [0x%08x]", value); + + value = REG_READL(CONN_INFRA_CFG_START + 0x0168); + BTMTK_INFO("0x18001168 = [0x%08x]", value); + + value = REG_READL(CONN_INFRA_CFG_START + 0x0170); + BTMTK_INFO("0x18001170 = [0x%08x]", value); + + value = REG_READL(CONN_INFRA_CFG_BT_PWRCTLCR0); + BTMTK_INFO("0x18001874 = [0x%08x]", value); + + value = REG_READL(CONN_INFRA_CFG_START + 0x0C00); + BTMTK_INFO("0x18001C00 = [0x%08x]", value); + + value = REG_READL(CONN_INFRA_CFG_START + 0x0C04); + BTMTK_INFO("0x18001C04 = [0x%08x]", value); + + BTMTK_INFO("%s: M0 - M3 semaphore status:", __func__); + for (i = 0x18070400; i <= 0x18073400; i += 0x1000) { + value = bt_read_cr(i); + BTMTK_INFO("[0x%08x] = [0x%08x]", i, value); + } + + value = bt_read_cr(0x18071400); + BTMTK_INFO("0x18070400 = [0x%08x]", value); + + value = bt_read_cr(0x18070400); + BTMTK_INFO("0x18070400 = [0x%08x]", value); + + value = bt_read_cr(0x18070400); + BTMTK_INFO("0x18070400 = [0x%08x]", value); + } + +host_csr_only: + value = REG_READL(BGF_LPCTL); + BTMTK_INFO("0x18060030 = [0x%08x]", value); + + value = REG_READL(BGF_IRQ_STAT2); + BTMTK_INFO("0x1806003C = [0x%08x]", value); + + value = 0x12345678; + REG_WRITEL(CON_REG_SPM_BASE_ADDR + 0x188, value); + value = REG_READL(CON_REG_SPM_BASE_ADDR + 0x188); + BTMTK_INFO("0x18060188 = [0x%08x]", value); + + REG_WRITEL(CON_REG_SPM_BASE_ADDR + 0xA8, 0x194C4BA7); + BTMTK_INFO("Write [0x180600A8] = [0x194C4BA7]"); + + bt_dump_bgfsys_all(); + /* release conn_infra force on */ + CLR_BIT(CONN_INFRA_WAKEUP_BT, BIT(0)); +} + +/* bgfsys_power_on_dump_cr + * + * Dump CR for debug if power on sequence fail + * + * Arguments: + * N/A + * + * Return Value: + * N/A + * + */ +static inline void bgfsys_power_on_dump_cr(void) +{ + uint32_t i; + uint32_t val_w, val_r; + int32_t is_bus_hang = 0; + + is_bus_hang = conninfra_is_bus_hang(); + BTMTK_INFO("%s: conninfra_is_bus_hang ret = %d", __func__, is_bus_hang); + + if (!CAN_DUMP_HOST_CSR(is_bus_hang)) { + BTMTK_ERR("%s; host csr is not readable", __func__); + return; + } + + if(bgfsys_check_conninfra_ready()) + goto host_csr_only; + + BTMTK_INFO("%s: M0 - M3 semaphore status:", __func__); + for (i = 0x18070400; i <= 0x18073400; i += 0x1000) { + val_r = bt_read_cr(i); + BTMTK_INFO("[0x%08x] = [0x%08x]", i, val_r); + } + + BTMTK_INFO("%s: conninfra part:", __func__); + val_r = REG_READL(CONN_HOST_CSR_TOP_START + 0x02CC); + BTMTK_INFO("%s: REG[0x180602CC] read[0x%08x]", __func__, val_r); + + if (!is_bus_hang) { + val_r = REG_READL(CONN_INFRA_CFG_START + 0x0610); + BTMTK_INFO("%s: REG[0x18001610] read[0x%08x]", __func__, val_r); + val_r = REG_READL(CONN_INFRA_CFG_START + 0x0614); + BTMTK_INFO("%s: REG[0x18001614] read[0x%08x]", __func__, val_r); + val_r = REG_READL(CONN_INFRA_CFG_START + 0x0150); + BTMTK_INFO("%s: REG[0x18001150] read[0x%08x]", __func__, val_r); + val_r = REG_READL(CONN_INFRA_CFG_START + 0x0170); + BTMTK_INFO("%s: REG[0x18001170] read[0x%08x]", __func__, val_r); + + //REG_WRITEL(CONN_INFRA_CFG_START + 0x0610, BIT(1)); + //val_r = REG_READL(CONN_INFRA_CFG_START + 0x0610); + //BTMTK_INFO("%s: REG[0x18001610] write[0x%08x], REG[0x18001610] read[0x%08x]", __func__, BIT(1), val_r); + bt_write_cr(0x1800F000, 0x32C8001C); + } + +host_csr_only: + for(i = 0x0F; i >= 0x01; i--) { + val_w = (i << 16) + 0x0001; + REG_WRITEL(CONN_HOST_CSR_TOP_START + 0x0128, val_w); + val_r = REG_READL(CONN_HOST_CSR_TOP_START + 0x0148); + BTMTK_INFO("%s: REG[0x18060128] write[0x%08x], REG[0x18060148] read[0x%08x]", __func__, val_w, val_r); + } + for(i = 0x03; i >= 0x01; i--) { + val_w = (i << 16) + 0x0002; + REG_WRITEL(CONN_HOST_CSR_TOP_START + 0x0128, val_w); + val_r = REG_READL(CONN_HOST_CSR_TOP_START + 0x0148); + BTMTK_INFO("%s: REG[0x18060128] write[0x%08x], REG[0x18060148] read[0x%08x]", __func__, val_w, val_r); + } + for(i = 0x04; i >= 0x01; i--) { + val_w = (i << 16) + 0x0003; + REG_WRITEL(CONN_HOST_CSR_TOP_START + 0x0128, val_w); + val_r = REG_READL(CONN_HOST_CSR_TOP_START + 0x0148); + BTMTK_INFO("%s: REG[0x18060128] write[0x%08x], REG[0x18060148] read[0x%08x]", __func__, val_w, val_r); + } + + BTMTK_INFO("%s: bgf part:", __func__); + val_r = REG_READL(CONN_HOST_CSR_TOP_START + 0x022C); + BTMTK_INFO("%s: REG[0x1806022C] read[0x%08x]", __func__, val_r); + val_r = REG_READL(CONN_HOST_CSR_TOP_START + 0x0230); + BTMTK_INFO("%s: REG[0x18060230] read[0x%08x]", __func__, val_r); + val_r = REG_READL(CONN_HOST_CSR_TOP_START + 0x0234); + BTMTK_INFO("%s: REG[0x18060234] read[0x%08x]", __func__, val_r); + val_r = REG_READL(CONN_HOST_CSR_TOP_START + 0x0238); + BTMTK_INFO("%s: REG[0x18060238] read[0x%08x]", __func__, val_r); + val_r = REG_READL(CON_REG_SPM_BASE_ADDR + 0x268); + BTMTK_INFO("%s: REG[0x18060268] read[0x%08x]", __func__, val_r); + val_r = REG_READL(CON_REG_SPM_BASE_ADDR + 0x26C); + BTMTK_INFO("%s: REG[0x1806026C] read[0x%08x]", __func__, val_r); + + bt_dump_bgfsys_all(); + /* release conn_infra force on */ + CLR_BIT(CONN_INFRA_WAKEUP_BT, BIT(0)); +} +#endif diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_mt76xx.c b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_mt76xx.c new file mode 100644 index 0000000000000..52ee572a6c05c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_mt76xx.c @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2016,2017 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include "btmtk_define.h" +#include "btmtk_main.h" +#include "btmtk_chip_if.h" + + +int32_t btmtk_load_rom_patch_766x(struct hci_dev *hdev) +{ + char *tmp_str; + s32 sent_len; + u32 patch_len = 0; + u32 cur_len = 0; + int first_block = 1; + u8 phase; + u32 written = 0; + int ret = 0; + + u8 *pos; + struct btmtk_dev *bdev = hci_get_drvdata(hdev); + /* To-Do, for event check */ + /* u8 event[] = {0x04, 0xE4, 0x05, 0x02, 0x01, 0x01, 0x00, 0x00}; */ + + unsigned char *rom_patch; + unsigned char *rom_patch_bin_file_name; + unsigned int rom_patch_len = 0; + + struct sk_buff *skb = NULL; + + rom_patch_bin_file_name = kzalloc(MAX_BIN_FILE_NAME_LEN, GFP_KERNEL); + + /* To-Do + * Read CHIP ID for bin_file_name + */ + memcpy(rom_patch_bin_file_name, "mt7915_patch_e1_hdr.bin", 23); + //memcpy(rom_patch_bin_file_name, "mt7663_patch_e2_hdr.bin", 23); + + btmtk_load_code_from_bin(&rom_patch, + rom_patch_bin_file_name, NULL, + &rom_patch_len, 10); + + tmp_str = rom_patch; + + tmp_str = rom_patch + 16; + BTMTK_INFO("%s: platform = %c%c%c%c\n", __func__, tmp_str[0], tmp_str[1], tmp_str[2], tmp_str[3]); + + tmp_str = rom_patch + 20; + BTMTK_INFO("%s: HW/SW version = %c%c%c%c\n", __func__, tmp_str[0], tmp_str[1], tmp_str[2], tmp_str[3]); + + tmp_str = rom_patch + 24; + BTMTK_INFO("loading rom patch...\n"); + + cur_len = 0x00; + patch_len = rom_patch_len - PATCH_INFO_SIZE; + + BTMTK_INFO("%s: patch_len = %d\n", __func__, patch_len); + + BTMTK_INFO("%s: loading rom patch...\n", __func__); + + + pos = kmalloc(UPLOAD_PATCH_UNIT, GFP_ATOMIC); + + /* loading rom patch */ + while (1) { + s32 sent_len_max = UPLOAD_PATCH_UNIT - PATCH_HEADER_SIZE; + + sent_len = (patch_len - cur_len) >= sent_len_max ? sent_len_max : (patch_len - cur_len); + + if (sent_len > 0) { + if (first_block == 1) { + if (sent_len < sent_len_max) + phase = PATCH_PHASE3; + else + phase = PATCH_PHASE1; + first_block = 0; + } else if (sent_len == sent_len_max) { + if (patch_len - cur_len == sent_len_max) + phase = PATCH_PHASE3; + else + phase = PATCH_PHASE2; + } else { + phase = PATCH_PHASE3; + } + + + /* prepare HCI header */ + pos[0] = 0x02; + pos[1] = 0x6F; + pos[2] = 0xFC; + pos[3] = (sent_len + 5) & 0xFF; + pos[4] = ((sent_len + 5) >> 8) & 0xFF; + + /* prepare WMT header */ + pos[5] = 0x01; + pos[6] = 0x01; + pos[7] = (sent_len + 1) & 0xFF; + pos[8] = ((sent_len + 1) >> 8) & 0xFF; + + pos[9] = phase; + memcpy(&pos[10], rom_patch + PATCH_INFO_SIZE + cur_len, + sent_len); + ret = btmtk_main_send_cmd(hdev, pos, sent_len + PATCH_HEADER_SIZE, BTMTKUART_TX_WAIT_VND_EVT); + if (ret == 0) { + BTMTK_INFO("%s: send patch failed, terminate", __func__); + goto err; + } + cur_len = cur_len + sent_len; + BTMTK_INFO("%s: sent_len = %d, cur_len = %d, phase = %d, written = %d", __func__, sent_len, cur_len, phase, written); + + /*if (btmtk_usb_get_rom_patch_result() < 0) + goto error2;*/ + + } else { + btmtk_send_wmt_reset(hdev); + BTMTK_INFO("%s: loading rom patch... Done", __func__); + if (bdev->subsys_reset == 1) { + skb = alloc_skb(BT_SKB_RESERVE, GFP_ATOMIC); + if (skb == NULL) { + BTMTK_ERR("%s allocate skb failed!!", __func__); + } else { + BTMTK_INFO("%s: send hw_err!!", __func__); + hci_skb_pkt_type(skb) = HCI_EVENT_PKT; + skb->data[0] = 0x10; + skb->data[1] = 0x01; + skb->data[2] = 0x01; + hci_recv_frame(hdev, skb); + } + bdev->subsys_reset = 0; + } + clear_bit(BTMTKUART_REQUIRED_DOWNLOAD, &bdev->tx_state); + break; + } + } +err: + return ret; +} + +static inline int btmtk_send_wmt_power_on_cmd_766x(struct hci_dev *hdev) +{ + /* Support 7668 and 7663 */ + u8 cmd[] = { 0x01, 0x6F, 0xFC, 0x06, 0x01, 0x06, 0x02, 0x00, 0x00, 0x01 }; + /* To-Do, for event check */ + /* u8 event[] = { 0x04, 0xE4, 0x05, 0x02, 0x06, 0x01, 0x00 }; */ + + btmtk_main_send_cmd(hdev, cmd, sizeof(cmd), BTMTKUART_TX_WAIT_VND_EVT); + + BTMTK_INFO("%s done", __func__); + return 0; +} + +static inline int btmtk_76xx_send_wmt_reset(struct hci_dev *hdev) +{ + /* Support 7668 and 7663 */ + u8 cmd[] = { 0x01, 0x6F, 0xFC, 0x05, 0x01, 0x07, 0x01, 0x00, 0x04 }; + /* To-Do, for event check */ + /* u8 event[] = { 0x04, 0xE4, 0x05, 0x02, 0x07, 0x01, 0x00, 0x00 }; */ + + btmtk_main_send_cmd(hdev, cmd, sizeof(cmd), BTMTKUART_TX_WAIT_VND_EVT); + + BTMTK_INFO("%s done", __func__); + return 0; +} + +static int btmtk_send_hci_tci_set_sleep_cmd_766x(struct hci_dev *hdev) +{ + u8 cmd[] = { 0x01, 0x7A, 0xFC, 0x07, 0x05, 0x40, 0x06, 0x40, 0x06, 0x00, 0x00 }; + /* To-Do, for event check */ + /* u8 event[] = { 0x04, 0x0E, 0x04, 0x01, 0x7A, 0xFC, 0x00 }; */ + + //struct btmtk_dev *bdev = hci_get_drvdata(hdev); + + btmtk_main_send_cmd(hdev, cmd, sizeof(cmd), BTMTKUART_TX_WAIT_VND_EVT); + + BTMTK_INFO("%s done", __func__); + + return 0; +} + +int32_t btmtk_send_wmt_power_on_cmd(struct hci_dev *hdev) +{ + return btmtk_send_wmt_power_on_cmd_766x(hdev); +} + + +int32_t btmtk_set_power_on(struct hci_dev *hdev) +{ + return 0; +} + +int32_t btmtk_set_sleep(struct hci_dev *hdev, u_int8_t need_wait) +{ + return btmtk_send_hci_tci_set_sleep_cmd_766x(hdev); +} diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_queue.c b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_queue.c new file mode 100644 index 0000000000000..b82721591b2bf --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_queue.c @@ -0,0 +1,478 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + + #include "btmtk_btif.h" + #include + + /******************************************************************************* + * D A T A T Y P E S + ******************************************************************************** + */ + + /******************************************************************************* + * P U B L I C D A T A + ******************************************************************************** + */ +struct workqueue_struct *workqueue_task; +struct delayed_work work; + + /******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************** + */ +extern struct btmtk_dev *g_bdev; +extern struct bt_dbg_st g_bt_dbg_st; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +#if (USE_DEVICE_NODE == 1) +uint8_t is_rx_queue_empty(void) +{ + struct bt_ring_buffer_mgmt *p_ring = &g_bdev->rx_buffer; + + spin_lock(&p_ring->lock); + if (p_ring->read_idx == p_ring->write_idx) { + spin_unlock(&p_ring->lock); + return TRUE; + } else { + spin_unlock(&p_ring->lock); + return FALSE; + } +} + +static uint8_t is_rx_queue_res_available(uint32_t length) +{ + uint32_t room_left; + struct bt_ring_buffer_mgmt *p_ring = &g_bdev->rx_buffer; + + /* + * Get available space of RX Queue + */ + spin_lock(&p_ring->lock); + if (p_ring->read_idx <= p_ring->write_idx) + room_left = RING_BUFFER_SIZE - p_ring->write_idx + p_ring->read_idx - 1; + else + room_left = p_ring->read_idx - p_ring->write_idx - 1; + spin_unlock(&p_ring->lock); + + if (room_left < length) { + BTMTK_WARN("RX queue room left (%u) < required (%u)", room_left, length); + return FALSE; + } + return TRUE; +} + +static int32_t rx_pkt_enqueue(uint8_t *buffer, uint32_t length) +{ + uint32_t tail_len; + struct bt_ring_buffer_mgmt *p_ring = &g_bdev->rx_buffer; + + if (length > HCI_MAX_FRAME_SIZE) { + BTMTK_ERR("Abnormal packet length %u, not enqueue!", length); + return -EINVAL; + } + + spin_lock(&p_ring->lock); + if (p_ring->write_idx + length < RING_BUFFER_SIZE) { + memcpy(p_ring->buf + p_ring->write_idx, buffer, length); + p_ring->write_idx += length; + } else { + tail_len = RING_BUFFER_SIZE - p_ring->write_idx; + memcpy(p_ring->buf + p_ring->write_idx, buffer, tail_len); + memcpy(p_ring->buf, buffer + tail_len, length - tail_len); + p_ring->write_idx = length - tail_len; + } + spin_unlock(&p_ring->lock); + + return 0; + +} + +int32_t rx_skb_enqueue(struct sk_buff *skb) +{ + #define WAIT_TIMES 40 + int8_t i = 0; + int32_t ret = 0; + + if (skb->len == 0) { + BTMTK_WARN("Inavlid data event, skip, length = %d", skb->len); + return -1; + } + + /* FW will block the data if it's buffer is full, + driver can wait a interval for native process to read out */ + if(g_bt_dbg_st.rx_buf_ctrl == TRUE) { + for(i = 0; i < WAIT_TIMES; i++) { + if (!is_rx_queue_res_available(skb->len + 1)) { + usleep_range(USLEEP_5MS_L, USLEEP_5MS_H); + } else + break; + } + } + if (!is_rx_queue_res_available(skb->len + 1)) { + BTMTK_WARN("rx packet drop!!!"); + return -1; + } + + memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); + ret = rx_pkt_enqueue(skb->data, skb->len); + + if (!is_rx_queue_empty()) + g_bdev->rx_event_cb(); + + return ret; +} + +void rx_dequeue(uint8_t *buffer, uint32_t size, uint32_t *plen) +{ + uint32_t copy_len = 0, tail_len; + struct bt_ring_buffer_mgmt *p_ring = &g_bdev->rx_buffer; + + spin_lock(&p_ring->lock); + if (p_ring->read_idx != p_ring->write_idx) { + /* + * RX Queue not empty, + * fill out the retrieving buffer untill it is full, or we have no data. + */ + if (p_ring->read_idx < p_ring->write_idx) { + copy_len = p_ring->write_idx - p_ring->read_idx; + if (copy_len > size) + copy_len = size; + memcpy(buffer, p_ring->buf + p_ring->read_idx, copy_len); + p_ring->read_idx += copy_len; + } else { /* read_idx > write_idx */ + tail_len = RING_BUFFER_SIZE - p_ring->read_idx; + if (tail_len > size) { /* exclude equal case to skip wrap check */ + copy_len = size; + memcpy(buffer, p_ring->buf + p_ring->read_idx, copy_len); + p_ring->read_idx += copy_len; + } else { + /* 1. copy tail */ + memcpy(buffer, p_ring->buf + p_ring->read_idx, tail_len); + /* 2. check if head length is enough */ + copy_len = (p_ring->write_idx < (size - tail_len)) + ? p_ring->write_idx : (size - tail_len); + /* 3. copy header */ + memcpy(buffer + tail_len, p_ring->buf, copy_len); + p_ring->read_idx = copy_len; + /* 4. update copy length: head + tail */ + copy_len += tail_len; + } + } + } + spin_unlock(&p_ring->lock); + + *plen = copy_len; + return; +} + +void rx_queue_flush(void) +{ + struct bt_ring_buffer_mgmt *p_ring = &g_bdev->rx_buffer; + p_ring->read_idx = p_ring->write_idx = 0; +} + +void rx_queue_initialize(void) +{ + struct bt_ring_buffer_mgmt *p_ring = &g_bdev->rx_buffer; + + p_ring->read_idx = p_ring->write_idx = 0; + spin_lock_init(&p_ring->lock); +} + +void rx_queue_destroy(void) +{ + rx_queue_flush(); +} +#endif // (USE_DEVICE_NODE == 1) + +#if (DRIVER_CMD_CHECK == 1) + +void cmd_list_initialize(void) +{ + struct bt_cmd_queue *p_queue = &g_bdev->cmd_queue; + BTMTK_DBG("%s", __func__); + + p_queue->head = NULL; + p_queue->tail = NULL; + p_queue->size = 0; + spin_lock_init(&p_queue->lock); +} + +struct bt_cmd_node* cmd_free_node(struct bt_cmd_node* node) +{ + struct bt_cmd_queue *p_queue = &g_bdev->cmd_queue; + + struct bt_cmd_node* next = node->next; + kfree(node); + p_queue->size--; + + return next; +} + +bool cmd_list_isempty(void) +{ + struct bt_cmd_queue *p_queue = &g_bdev->cmd_queue; + + spin_lock(&p_queue->lock); + if(p_queue->size == 0) { + spin_unlock(&p_queue->lock); + return TRUE; + } else { + spin_unlock(&p_queue->lock); + return FALSE; + } +} + +bool cmd_list_append (uint16_t opcode) +{ + struct bt_cmd_queue *p_queue = &g_bdev->cmd_queue; + struct bt_cmd_node *node = kzalloc(sizeof(struct bt_cmd_node),GFP_KERNEL); + + if (!node) { + BTMTK_ERR("%s create node fail",__func__); + return FALSE; + } + spin_lock(&p_queue->lock); + node->next = NULL; + node->opcode = opcode; + + if(p_queue->tail == NULL){ + p_queue->head = node; + p_queue->tail = node; + } else { + p_queue->tail->next = node; + p_queue->tail = node; + } + p_queue->size ++; + + spin_unlock(&p_queue->lock); + + return TRUE; +} + +bool cmd_list_check(uint16_t opcode) +{ + struct bt_cmd_queue *p_queue = &g_bdev->cmd_queue; + struct bt_cmd_node* curr = NULL; + + if (cmd_list_isempty() == TRUE) return FALSE; + spin_lock(&p_queue->lock); + + curr = p_queue->head; + + while(curr){ + if(curr->opcode == opcode){ + spin_unlock(&p_queue->lock); + return TRUE; + } + curr=curr->next; + } + spin_unlock(&p_queue->lock); + + return FALSE; +} + +bool cmd_list_remove(uint16_t opcode) +{ + struct bt_cmd_queue *p_queue = &g_bdev->cmd_queue; + struct bt_cmd_node* prev = NULL; + struct bt_cmd_node* curr = NULL; + + if (cmd_list_isempty() == TRUE) return FALSE; + + spin_lock(&p_queue->lock); + + if(p_queue->head->opcode == opcode) { + struct bt_cmd_node* next = cmd_free_node(p_queue->head); + if (p_queue->head == p_queue->tail) p_queue->tail = NULL; + p_queue->head = next; + spin_unlock(&p_queue->lock); + return TRUE; + } + + prev = p_queue->head; + curr = p_queue->head->next; + + while(curr){ + if(curr->opcode == opcode) { + prev->next = cmd_free_node(curr); + if(p_queue->tail == curr) p_queue->tail = prev; + spin_unlock(&p_queue->lock); + return TRUE; + } + prev = curr; + curr = curr->next; + } + BTMTK_ERR("%s No match opcode: %4X", __func__,opcode); + spin_unlock(&p_queue->lock); + return FALSE; +} + +void cmd_list_destory(void) +{ + struct bt_cmd_queue *p_queue = &g_bdev->cmd_queue; + struct bt_cmd_node* curr = p_queue->head; + BTMTK_DBG("%s",__func__); + + while(curr){ + curr = cmd_free_node(curr); + } + p_queue->head = NULL; + p_queue->tail = NULL; + p_queue->size = 0; +} + +void command_response_timeout(struct work_struct *pwork) +{ + struct bt_cmd_queue *p_queue = &g_bdev->cmd_queue; + + if (p_queue->size != 0) { + g_bdev->cmd_timeout_count++; + + BTMTK_INFO("[%s] timeout [%d] sleep [%d] force_on [%d]", __func__, + g_bdev->cmd_timeout_count, + g_bdev->psm.sleep_flag, + g_bdev->psm.force_on); + btmtk_cif_dump_rxd_backtrace(); + btmtk_cif_dump_fw_no_rsp(BT_BTIF_DUMP_REG); + if (g_bdev->cmd_timeout_count == 4) { + BTMTK_ERR("%s, !!!! Command Timeout !!!! opcode 0x%4X", __func__, p_queue->head->opcode); + // To-do : Need to consider if it has any condition to check + g_bdev->cmd_timeout_count = 0; + bt_trigger_reset(); + } else + queue_delayed_work(workqueue_task, &work, HZ>>1); + } +} + +bool cmd_workqueue_init(void) +{ + BTMTK_INFO("init workqueue"); + workqueue_task = create_singlethread_workqueue("workqueue_task"); + if(!workqueue_task){ + BTMTK_ERR("fail to init workqueue"); + return FALSE; + } + INIT_DELAYED_WORK(&work, command_response_timeout); + g_bdev->cmd_timeout_count = 0; + return TRUE; +} + +void update_command_response_workqueue(void) { + struct bt_cmd_queue *p_queue = &g_bdev->cmd_queue; + if (p_queue->size == 0){ + BTMTK_DBG("command queue size = 0"); + cancel_delayed_work(&work); + } else { + BTMTK_DBG("update new command queue : %4X" , p_queue->head->opcode); + g_bdev->cmd_timeout_count = 0; + cancel_delayed_work(&work); + queue_delayed_work(workqueue_task, &work, HZ>>1); + } +} + +void cmd_workqueue_exit(void) +{ + BTMTK_INFO("exit workqueue"); + if(workqueue_task == NULL) + return; + cancel_delayed_work(&work); + flush_workqueue(workqueue_task); + destroy_workqueue(workqueue_task); + workqueue_task = NULL; +} + +#endif // (DRIVER_CMD_CHECK == 1) + + +const char* direction_tostring (enum bt_direction_type direction_type) { + char *type[] = {"NONE", "TX", "RX"}; + return type[direction_type]; +} + +void dump_queue_initialize(void) +{ + struct bt_dump_queue *d_queue = &g_bdev->dump_queue; + BTMTK_INFO("init dumpqueue"); + + d_queue->index = 0; + d_queue->full = 0; + spin_lock_init(&d_queue->lock); + memset(d_queue->queue, 0, MAX_DUMP_QUEUE_SIZE * sizeof(struct bt_dump_packet)); +} + + +void add_dump_packet(const uint8_t *buffer,const uint32_t length, enum bt_direction_type type){ + struct bt_dump_queue *d_queue = &g_bdev->dump_queue; + uint32_t index = d_queue->index; + struct bt_dump_packet *p_packet = &d_queue->queue[index]; + uint32_t copysize; + + spin_lock(&d_queue->lock); + if (length > MAX_DUMP_DATA_SIZE) + copysize = MAX_DUMP_DATA_SIZE; + else + copysize = length; + + do_gettimeofday(&p_packet->time); + ktime_get_ts(&p_packet->kerneltime); + memcpy(p_packet->data,buffer,copysize); + p_packet->data_length = length; + p_packet->direction_type = type; + + d_queue->index = (d_queue->index+1) % MAX_DUMP_QUEUE_SIZE; + BTMTK_DBG("index: %d", d_queue->index); + if (d_queue->full == FALSE && d_queue->index == 0) + d_queue->full = TRUE; + spin_unlock(&d_queue->lock); +} + +void print_dump_packet(struct bt_dump_packet *p_packet){ + int32_t copysize; + uint32_t sec, usec, ksec, knsec; + struct rtc_time tm; + + sec = p_packet->time.tv_sec; + usec = p_packet->time.tv_usec; + + ksec = p_packet->kerneltime.tv_sec; + knsec = p_packet->kerneltime.tv_nsec; + + rtc_time_to_tm(sec, &tm); + + if (p_packet->data_length > MAX_DUMP_DATA_SIZE) + copysize = MAX_DUMP_DATA_SIZE; + else + copysize = p_packet->data_length; + + BTMTK_INFO_RAW(p_packet->data, copysize, "Dump: Time:%02d:%02d:%02d.%06u, Kernel Time:%6d.%09u, %s, Size = %3d, Data: " + , tm.tm_hour+8, tm.tm_min, tm.tm_sec, usec, ksec, knsec + , direction_tostring(p_packet->direction_type), p_packet->data_length); +} + +void show_all_dump_packet(void) { + struct bt_dump_queue *d_queue = &g_bdev->dump_queue; + int32_t i, j, showsize; + struct bt_dump_packet *p_packet; + + spin_lock(&d_queue->lock); + if (d_queue->full == TRUE) { + showsize = MAX_DUMP_QUEUE_SIZE; + for(i = 0,j = d_queue->index; i < showsize; i++,j++) { + p_packet = &d_queue->queue[j % MAX_DUMP_QUEUE_SIZE]; + print_dump_packet(p_packet); + } + } else { + showsize = d_queue->index; + for(i = 0; i < showsize; i++) { + p_packet = &d_queue->queue[i]; + print_dump_packet(p_packet); + } + } + spin_unlock(&d_queue->lock); +} diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_uart.h b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_uart.h new file mode 100644 index 0000000000000..5cd35e9b53174 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_uart.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016,2017 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef _BTMTK_UART_H_ +#define _BTMTK_UART_H_ +#include "btmtk_define.h" + + +#include +#include +#include + +#define HCI_HEADER_LEN 4 + +struct mtk_stp_hdr { + u8 prefix; + __be16 dlen; + u8 cs; +} __packed; +#define MTK_STP_TLR_SIZE 2 +#define STP_HEADER_LEN 4 +#define STP_HEADER_CRC_LEN 2 + + +struct btmtk_dev { + struct hci_dev *hdev; + struct tty_struct *tty; + unsigned long hdev_flags; + + /* For tx queue */ + struct sk_buff *tx_skb; + unsigned long tx_state; + + /* For rx queue */ + struct sk_buff *rx_skb; + unsigned long rx_state; + + struct sk_buff *evt_skb; + wait_queue_head_t p_wait_event_q; + + unsigned int subsys_reset; + + u8 stp_pad[6]; + u8 stp_cursor; + u16 stp_dlen; +}; + + +/** + * Maximum rom patch file name length + */ +#define MAX_BIN_FILE_NAME_LEN 32 + +#define N_MTK (15+1) +/** + * Send cmd dispatch evt + */ +#define RETRY_TIMES 10 +#define HCI_EV_VENDOR 0xff + +#define N_MTK (15+1) + +/* Platform device */ +#define BTMTK_GET_DEV(bdev) (bdev->tty->dev) + +int btmtk_cif_send_cmd(struct hci_dev *hdev, const uint8_t *cmd, + const int cmd_len, int retry, int endpoint, unsigned long tx_state); +int btmtk_cif_send_calibration(struct hci_dev *hdev); +int btmtk_cif_dispatch_event(struct hci_dev *hdev, struct sk_buff *skb); +#endif + diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_uart_main.c b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_uart_main.c new file mode 100644 index 0000000000000..c0a71b8e9093b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/btmtk_uart_main.c @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2016,2017 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include "btmtk_config.h" +#include "btmtk_define.h" +#include "btmtk_uart.h" +#include "btmtk_main.h" + +#define LOG TRUE + +/*============================================================================*/ +/* Global Variable */ +/*============================================================================*/ +static struct btmtk_dev *g_bdev; + +/*============================================================================*/ +/* Function Prototype */ +/*============================================================================*/ +static int btmtk_uart_allocate_memory(void); +extern int btmtk_load_rom_patch_766x(struct hci_dev *); + +unsigned long flagss = 0; + +/* Allocate Uart-Related memory */ +static int btmtk_uart_allocate_memory(void) +{ + if (g_bdev == NULL) { + g_bdev = kzalloc(sizeof(*g_bdev), GFP_KERNEL); + if (!g_bdev) { + BTMTK_ERR("%s: alloc memory fail (g_data)", __func__); + return -1; + } + } + return 0; +} + +int btmtk_cif_send_calibration(struct hci_dev *hdev) +{ + + return 0; +} + +int btmtk_cif_dispatch_event(struct hci_dev *hdev, struct sk_buff *skb) +{ + return 0; +} + +/* Send cmd and Receive evt */ +int btmtk_cif_send_cmd(struct hci_dev *hdev, const uint8_t *cmd, + const int cmd_len, int retry, int endpoint, unsigned long tx_state) +{ + int ret = -1, len = 0; + struct btmtk_dev *bdev = hci_get_drvdata(hdev); + + BTMTK_DBG_RAW(cmd, cmd_len, "%s, len = %d, send cmd: ", __func__, cmd_len); + //BTMTK_INFO("%s: tty %p\n", __func__, bdev->tty); + while(len != cmd_len) { + ret = bdev->tty->ops->write(bdev->tty, cmd, cmd_len); + len += ret; + BTMTK_DBG("%s, len = %d", __func__, len); + } + + return ret; +} + +static int btmtk_uart_send_query_uart_cmd(struct hci_dev *hdev) { + u8 cmd[] = { 0x01, 0x6F, 0xFC, 0x05, 0x01, 0x04, 0x01, 0x00, 0x02}; + /* To-Do, for event check */ + /* u8 event[] = { 0x04, 0xE4, 0x0a, 0x02, 0x04, 0x06, 0x00, 0x00, 0x02}; */ + + btmtk_main_send_cmd(hdev, cmd, sizeof(cmd), BTMTKUART_TX_WAIT_VND_EVT); + BTMTK_INFO("%s done", __func__); + return 0; +} + + +/* ------ LDISC part ------ */ + +/* btmtk_uart_tty_open + + */ + + +/* btmtk_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 btmtk_uart_tty_open(struct tty_struct *tty) +{ + BTMTK_INFO("%s: tty %p\n", __func__, tty); + + /* Init tty-related operation */ + tty->receive_room = 65536; + tty->port->low_latency = 1; + + btmtk_uart_allocate_memory(); + + tty->disc_data = g_bdev; + g_bdev->tty = tty; + + /* 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 */ + + btmtk_allocate_hci_device(g_bdev, HCI_UART); + g_bdev->stp_cursor = 2; + g_bdev->stp_dlen = 0; + + /* definition changed!! */ + if (tty->ldisc->ops->flush_buffer) + tty->ldisc->ops->flush_buffer(tty); + + tty_driver_flush_buffer(tty); + + BTMTK_INFO("%s: tty done %p\n", __func__, tty); + + return 0; +} + +/* btmtk_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 btmtk_uart_tty_close(struct tty_struct *tty) +{ + btmtk_free_hci_device(g_bdev, HCI_UART); + BTMTK_INFO("%s: tty %p", __func__, tty); + return; +} + +/* + * We don't provide read/write/poll interface for user space. + */ +static ssize_t btmtk_uart_tty_read(struct tty_struct *tty, struct file *file, + unsigned char *buf, size_t count) +{ + BTMTK_INFO("%s: tty %p", __func__, tty); + return 0; +} + +static ssize_t btmtk_uart_tty_write(struct tty_struct *tty, struct file *file, + const unsigned char *data, size_t count) +{ + BTMTK_INFO("%s: tty %p", __func__, tty); + return 0; +} + +static unsigned int btmtk_uart_tty_poll(struct tty_struct *tty, struct file *filp, poll_table *wait) +{ + unsigned int mask = 0; + if (g_bdev->subsys_reset== 1) { + mask |= POLLIN | POLLRDNORM; /* readable */ + BTMTK_INFO("%s: tty %p", __func__, tty); + } + return mask; +} + +int btmtk_uart_send_wakeup_cmd(struct hci_dev *hdev) +{ + u8 cmd[] = { 0xFF }; + /* To-Do, for event check */ + /*u8 event[] = { 0x80, 0x00};*/ + + btmtk_main_send_cmd(hdev, cmd, sizeof(cmd), BTMTKUART_TX_SKIP_VENDOR_EVT); + return 0; +} + + +int btmtk_uart_send_set_uart_cmd(struct hci_dev *hdev) +{ + u8 cmd[] = { 0x01, 0x6F, 0xFC, 0x09, 0x01, 0x04, 0x05, 0x00, 0x01, 0x00, 0x10, 0x0E, 0x00}; + /* To-Do, for event check */ + /* u8 event[] = {0x04, 0xE4, 0x06, 0x02, 0x04, 0x02, 0x00, 0x00, 0x01}; */ + btmtk_main_send_cmd(hdev, cmd, sizeof(cmd), BTMTKUART_TX_WAIT_VND_EVT); + + return 0; +} + +/* btmtk_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 btmtk_uart_tty_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + u32 err = 0; + BTMTK_INFO("%s: tty %p", __func__, tty); + + switch (cmd) { + case HCIUARTSETPROTO: + pr_info(" Set low_latency to TRUE \n"); + tty->port->low_latency = 1; + break; + case HCIUARTSETBAUD: + pr_info(" Set BAUDRATE \n"); + btmtk_uart_send_set_uart_cmd(g_bdev->hdev); + btmtk_uart_send_wakeup_cmd(g_bdev->hdev); + msleep(100); + return 1; + case HCIUARTGETBAUD: + pr_info(" Get BAUDRATE \n"); + btmtk_uart_send_query_uart_cmd(g_bdev->hdev); + return 1; + case HCIUARTSETSTP: + pr_info(" Set STP mandatory command \n"); + return 1; + case HCIUARTLOADPATCH: + pr_info(" Set HCIUARTLOADPATCH command \n"); + btmtk_load_rom_patch_766x(g_bdev->hdev); + return 1; + default: + //pr_info(" n_tty_ioctl_helper \n"); + err = n_tty_ioctl_helper(tty, file, cmd, arg); + break; + }; + + return err; +} + +static void btmtk_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count) +{ + int ret = -1; + struct btmtk_dev *bdev = tty->disc_data; + + BTMTK_DBG_RAW(data, count, "Receive"); + + /* add hci device part */ + ret = btmtk_recv(bdev->hdev, data, count); + if (test_and_clear_bit(BTMTKUART_TX_SKIP_VENDOR_EVT, &bdev->tx_state)) { + BTMTK_DBG("%s clear bit BTMTKUART_TX_SKIP_VENDOR_EVT", __func__); + wake_up(&bdev->p_wait_event_q); + BTMTK_DBG("%s wake_up p_wait_event_q", __func__); + } else if (ret < 0) { + BTMTK_ERR("%s, ret = %d", __func__, ret); + } +} + +/* btmtk_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 btmtk_uart_tty_wakeup(struct tty_struct *tty) +{ + BTMTK_INFO("%s: tty %p", __func__, tty); +} + +static int uart_register(void) +{ + static struct tty_ldisc_ops btmtk_uart_ldisc; + u32 err = 0; + BTMTK_INFO("%s", __func__); + + /* Register the tty discipline */ + memset(&btmtk_uart_ldisc, 0, sizeof(btmtk_uart_ldisc)); + btmtk_uart_ldisc.magic = TTY_LDISC_MAGIC; + btmtk_uart_ldisc.name = "n_mtk"; + btmtk_uart_ldisc.open = btmtk_uart_tty_open; + btmtk_uart_ldisc.close = btmtk_uart_tty_close; + btmtk_uart_ldisc.read = btmtk_uart_tty_read; + btmtk_uart_ldisc.write = btmtk_uart_tty_write; + btmtk_uart_ldisc.ioctl = btmtk_uart_tty_ioctl; + btmtk_uart_ldisc.poll = btmtk_uart_tty_poll; + btmtk_uart_ldisc.receive_buf = btmtk_uart_tty_receive; + btmtk_uart_ldisc.write_wakeup = btmtk_uart_tty_wakeup; + btmtk_uart_ldisc.owner = THIS_MODULE; + + err = tty_register_ldisc(N_MTK, &btmtk_uart_ldisc); + if (err) { + BTMTK_ERR("MTK line discipline registration failed. (%d)", err); + return err; + } + + BTMTK_INFO("%s done", __func__); + return err; +} +static int uart_deregister(void) +{ + u32 err = 0; + err = tty_unregister_ldisc(N_MTK); + if (err) { + BTMTK_ERR("line discipline registration failed. (%d)", err); + return err; + } + return 0; +} + +int btmtk_cif_register(void) +{ + int ret = -1; + + BTMTK_INFO("%s", __func__); + ret = uart_register(); + if (ret < 0) { + BTMTK_ERR("*** UART registration fail(%d)! ***", ret); + return ret; + } + BTMTK_INFO("%s: Done", __func__); + return 0; +} + +int btmtk_cif_deregister(void) +{ + int ret = -1; + + BTMTK_INFO("%s", __func__); + ret = uart_deregister(); + if (ret < 0) { + BTMTK_ERR("*** UART deregistration fail(%d)! ***", ret); + return ret; + } + BTMTK_INFO("%s: Done", __func__); + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/init.bt_drv.rc b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/init.bt_drv.rc new file mode 100644 index 0000000000000..8001eac897240 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/init.bt_drv.rc @@ -0,0 +1,4 @@ +# load bt_drv +on property:vendor.connsys.driver.ready=yes + insmod /vendor/lib/modules/bt_drv.ko + chown bluetooth bluetooth /proc/driver/bt_dbg diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/Android.mk b/drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/Android.mk new file mode 100644 index 0000000000000..4e31139f266dc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/Android.mk @@ -0,0 +1,21 @@ +LOCAL_PATH := $(call my-dir) + +ifeq ($(MTK_BT_SUPPORT),yes) +ifneq ($(MTK_BT_CHIP), $(filter $(MTK_BT_CHIP), MTK_CONSYS_MT6885 MTK_CONSYS_MT6893)) + +include $(CLEAR_VARS) +LOCAL_MODULE := bt_drv.ko +LOCAL_PROPRIETARY_MODULE := true +LOCAL_MODULE_OWNER := mtk +LOCAL_INIT_RC := init.bt_drv.rc +LOCAL_REQUIRED_MODULES := wmt_drv.ko + +include $(MTK_KERNEL_MODULE) + +ifeq ($(MTK_BT_CHIP), $(filter $(MTK_BT_CHIP), MTK_CONSYS_MT6873 MTK_CONSYS_MT6853 MTK_CONSYS_MT6833)) + BT_OPTS += CFG_BT_PM_QOS_CONTROL=y +endif +$(linked_module): OPTS += $(BT_OPTS) + +endif +endif diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/Makefile b/drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/Makefile new file mode 100644 index 0000000000000..99e1e9eb4d004 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/Makefile @@ -0,0 +1,62 @@ +MTK_PLATFORM := $(subst ",,$(CONFIG_MTK_PLATFORM)) +############################################################################### +# Bluetooth character device driver + +############################################################################### +# Necessary Check + +ifeq ($(AUTOCONF_H),) + $(error AUTOCONF_H is not defined) +endif + +ifndef TOP + TOP := $(srctree)/.. +endif + +ifneq ($(CFG_BT_PM_QOS_CONTROL),) + $(warning set PM_QOS_CONTROL=1) + ccflags-y += -D PM_QOS_CONTROL=1 +else + ccflags-y += -D PM_QOS_CONTROL=0 +endif + +ccflags-y += -imacros $(AUTOCONF_H) + +# Force build fail on modpost warning +KBUILD_MODPOST_FAIL_ON_WARNINGS := y +############################################################################### +# To add WMT dependent Macro and header file, will be removed later + +ccflags-y += -D MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include + +ifeq ($(CONFIG_MTK_CONN_LTE_IDC_SUPPORT),y) + ccflags-y += -D WMT_IDC_SUPPORT=1 +else + ccflags-y += -D WMT_IDC_SUPPORT=0 +endif + +############################################################################### +# To include BT driver dependent header file + +WMT_SRC_FOLDER := $(TOP)/vendor/mediatek/kernel_modules/connectivity/common +ccflags-y += -I$(WMT_SRC_FOLDER)/common_main/include +ccflags-y += -I$(WMT_SRC_FOLDER)/common_main/linux/include +ifneq ($(CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH),) +ccflags-y += -I$(WMT_SRC_FOLDER)/debug_utility +endif + +############################################################################### + +MODULE_NAME := bt_drv +obj-m += $(MODULE_NAME).o + +ccflags-y += -D CREATE_NODE_DYNAMIC=1 + +$(MODULE_NAME)-objs += stp_chrdev_bt.o +$(MODULE_NAME)-objs += dbg_bt.o +ifneq ($(CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH),) +$(MODULE_NAME)-objs += fw_log_bt.o +endif diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/bt.h b/drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/bt.h new file mode 100644 index 0000000000000..febe31c2dba44 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/bt.h @@ -0,0 +1,138 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _BT_EXP_H_ +#define _BT_EXP_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wmt_exp.h" +#include "stp_exp.h" + + +#define TRUE 1 +#define FALSE 0 + +/* Flags to control BT FW log flow */ +#define OFF 0x00 +#define ON 0xff + +#define PFX "[MTK-BT]" +#define BT_LOG_DBG 4 +#define BT_LOG_INFO 3 +#define BT_LOG_WARN 2 +#define BT_LOG_ERR 1 +#define RAW_MAX_BYTES 30 + +static uint8_t raw_buf[RAW_MAX_BYTES * 5 + 10]; +extern UINT32 gBtDbgLevel; + +#define BT_LOG_PRT_DBG(fmt, arg...) \ + do { if (gBtDbgLevel >= BT_LOG_DBG) pr_info(PFX "%s: " fmt, __func__, ##arg); } while (0) +#define BT_LOG_PRT_INFO(fmt, arg...) \ + do { if (gBtDbgLevel >= BT_LOG_INFO) pr_info(PFX "%s: " fmt, __func__, ##arg); } while (0) +#define BT_LOG_PRT_WARN(fmt, arg...) \ + do { if (gBtDbgLevel >= BT_LOG_WARN) pr_info(PFX "%s: " fmt, __func__, ##arg); } while (0) +#define BT_LOG_PRT_ERR(fmt, arg...) \ + do { if (gBtDbgLevel >= BT_LOG_ERR) pr_info(PFX "%s: " fmt, __func__, ##arg); } while (0) +#define BT_LOG_PRT_INFO_RATELIMITED(fmt, arg...) \ + do { if (gBtDbgLevel >= BT_LOG_ERR) pr_info_ratelimited(PFX "%s: " fmt, __func__, ##arg); } while (0) + +#define BT_LOG_PRT_DBG_RAW(p, l, fmt, ...) \ + do { \ + if (gBtDbgLevel >= BT_LOG_DBG) { \ + int cnt_ = 0; \ + int len_ = (l <= RAW_MAX_BYTES ? l : RAW_MAX_BYTES); \ + const unsigned char *ptr = p; \ + for (cnt_ = 0; cnt_ < len_; ++cnt_) { \ + if (snprintf(raw_buf+5*cnt_, 6, "0x%02X ", ptr[cnt_]) < 0) { \ + pr_info("snprintf error\n"); \ + break; \ + } \ + } \ + raw_buf[5*cnt_] = '\0'; \ + if (l <= RAW_MAX_BYTES) { \ + pr_info(PFX" "fmt"%s\n", ##__VA_ARGS__, raw_buf); \ + } else { \ + pr_info(PFX" "fmt"%s (prtail)\n", ##__VA_ARGS__, raw_buf); \ + } \ + } \ + } while (0) + +#define BT_LOG_PRT_INFO_RAW(p, l, fmt, ...) \ + do { \ + if (gBtDbgLevel >= BT_LOG_INFO) { \ + int cnt_ = 0; \ + int len_ = (l <= RAW_MAX_BYTES ? l : RAW_MAX_BYTES); \ + const unsigned char *ptr = p; \ + for (cnt_ = 0; cnt_ < len_; ++cnt_) { \ + if (snprintf(raw_buf+5*cnt_, 6, "0x%02X ", ptr[cnt_]) < 0) { \ + pr_info("snprintf error\n"); \ + break; \ + } \ + } \ + raw_buf[5*cnt_] = '\0'; \ + if (l <= RAW_MAX_BYTES) { \ + pr_info(PFX" "fmt"%s\n", ##__VA_ARGS__, raw_buf); \ + } else { \ + pr_info(PFX" "fmt"%s (prtail)\n", ##__VA_ARGS__, raw_buf); \ + } \ + } \ + } while (0) + +struct bt_dbg_st { + bool trx_enable; + uint16_t trx_opcode; + struct completion trx_comp; + void(*trx_cb) (char *buf, int len); + int rx_len; + char rx_buf[64]; +}; + +struct pm_qos_ctrl { + struct semaphore sem; + struct workqueue_struct *task; + struct delayed_work work; + u_int8_t is_hold; +}; + +/* ***************************************************************************************** + * BT Logger Tool will send 3 levels(Low, SQC and Debug) + * Driver will not check its range so we can provide capability of extention. + ******************************************************************************************/ +#define DEFAULT_LEVEL 0x02 /* 0x00:OFF, 0x01: LOW POWER, 0x02: SQC, 0x03: DEBUG */ + +extern int fw_log_bt_init(void); +extern void fw_log_bt_exit(void); +extern void bt_state_notify(UINT32 on_off); +extern ssize_t send_hci_frame(const PUINT8 buf, size_t count); + +#endif + diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/dbg_bt.c b/drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/dbg_bt.c new file mode 100644 index 0000000000000..313ffe747bc30 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/dbg_bt.c @@ -0,0 +1,367 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#include +#include +#include +#include "bt.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define BT_DBG_PROCNAME "driver/bt_dbg" +#define BUF_LEN_MAX 384 +#define BT_DBG_DUMP_BUF_SIZE 1024 +#define BT_DBG_PASSWD "4w2T8M65K5?2af+a " +#define BT_DBG_USER_TRX_PREFIX "[user-trx] " + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef int(*BT_DEV_DBG_FUNC) (int par1, int par2, int par3); +typedef struct { + BT_DEV_DBG_FUNC func; + bool turn_off_availavle; // function can be work when bt off +} tBT_DEV_DBG_STRUCT; + +/******************************************************************************* +* P U B L I C 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 int bt_dbg_get_bt_state(int par1, int par2, int par3); +static int bt_dbg_setlog_level(int par1, int par2, int par3); + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +extern struct bt_dbg_st g_bt_dbg_st; +extern UINT32 gBtDbgLevel; +static struct proc_dir_entry *g_bt_dbg_entry; +static struct mutex g_bt_lock; +static char g_bt_dump_buf[BT_DBG_DUMP_BUF_SIZE]; +static char *g_bt_dump_buf_ptr; +static int g_bt_dump_buf_len; +static bool g_bt_turn_on = FALSE; +static bool g_bt_dbg_enable = FALSE; + +static const tBT_DEV_DBG_STRUCT bt_dev_dbg_struct[] = { + [0xb] = {bt_dbg_setlog_level, TRUE}, + [0xe] = {bt_dbg_get_bt_state, TRUE}, +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +void _bt_dbg_reset_dump_buf(void) +{ + memset(g_bt_dump_buf, '\0', BT_DBG_DUMP_BUF_SIZE); + g_bt_dump_buf_ptr = g_bt_dump_buf; + g_bt_dump_buf_len = 0; +} + +int bt_dbg_get_bt_state(int par1, int par2, int par3) +{ + // 0x01: bt on, 0x00: bt off + BT_LOG_PRT_INFO("g_bt_turn_on[%d]\n", g_bt_turn_on); + _bt_dbg_reset_dump_buf(); + g_bt_dump_buf[0] = g_bt_turn_on; + g_bt_dump_buf[1] = '\0'; + g_bt_dump_buf_len = 2; + return 0; +} + +int bt_dbg_setlog_level(int par1, int par2, int par3) +{ + if (par2 < BT_LOG_ERR || par2 > BT_LOG_DBG) { + gBtDbgLevel = BT_LOG_INFO; + } else { + gBtDbgLevel = par2; + } + BT_LOG_PRT_INFO("gBtDbgLevel = %d\n", gBtDbgLevel); + return 0; +} + +ssize_t bt_dbg_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + int ret = 0; + int dump_len; + + ret = mutex_lock_killable(&g_bt_lock); + if (ret) { + BT_LOG_PRT_ERR("dump_lock fail!!\n"); + return ret; + } + + if (g_bt_dump_buf_len == 0) + goto exit; + + if (*f_pos == 0) + g_bt_dump_buf_ptr = g_bt_dump_buf; + + dump_len = g_bt_dump_buf_len >= count ? count : g_bt_dump_buf_len; + ret = copy_to_user(buf, g_bt_dump_buf_ptr, dump_len); + if (ret) { + BT_LOG_PRT_ERR("copy to dump info buffer failed, ret:%d\n", ret); + ret = -EFAULT; + goto exit; + } + + *f_pos += dump_len; + g_bt_dump_buf_len -= dump_len; + g_bt_dump_buf_ptr += dump_len; + BT_LOG_PRT_INFO("after read, wmt for dump info buffer len(%d)\n", g_bt_dump_buf_len); + + ret = dump_len; +exit: + + mutex_unlock(&g_bt_lock); + return ret; +} + +int _osal_strtol(const char *str, unsigned int adecimal, long *res) +{ + if (sizeof(long) == 4) + return kstrtou32(str, adecimal, (unsigned int *) res); + else + return kstrtol(str, adecimal, res); +} + +void bt_dbg_user_trx_cb(char *buf, int len) +{ + unsigned char *ptr = g_bt_dbg_st.rx_buf; + unsigned int i = 0, evt_len = 0; + int ret = 0; + + /* 1. bluedroid use partial read, this callback will enter several times + 2. this function read and parse the command_complete event */ + memcpy(&g_bt_dbg_st.rx_buf[g_bt_dbg_st.rx_len], buf, len); + g_bt_dbg_st.rx_len += len; + + // check the complete packet is read out by bluedroid + if(g_bt_dbg_st.rx_len != (g_bt_dbg_st.rx_buf[2] + 3)) + return; + + // if this event is not the desire one, skip and reset buffer + if((g_bt_dbg_st.rx_buf[4] + (g_bt_dbg_st.rx_buf[5] << 8)) != g_bt_dbg_st.trx_opcode) { + g_bt_dbg_st.rx_len = 0; + memset(g_bt_dbg_st.rx_buf, 0, sizeof(g_bt_dbg_st.rx_buf)); + return; + } + + // desire rx event is received, write to read buffer as string + evt_len = g_bt_dbg_st.rx_len; + BT_LOG_PRT_INFO_RAW(g_bt_dbg_st.rx_buf, evt_len, "%s: len[%ud], RxEvt: ", __func__, evt_len); + if(evt_len * 5 + 2 > BT_DBG_DUMP_BUF_SIZE) + return; + + _bt_dbg_reset_dump_buf(); + for (i = 0; i < evt_len; i++) { + ret = snprintf(g_bt_dump_buf + 5*i, 6, "0x%02X ", ptr[i]); + if (ret < 0) { + BT_LOG_PRT_ERR("error snprintf return value = [%d]\n", ret); + return; + } + } + + g_bt_dump_buf[5*evt_len] = '\n'; + g_bt_dump_buf[5*evt_len + 1] = '\0'; + g_bt_dump_buf_len = 5*evt_len + 1; + + // complete trx process + complete(&g_bt_dbg_st.trx_comp); +} + +void bt_dbg_user_trx_proc(char *cmd_raw) +{ +#define LEN_64 64 + unsigned char hci_cmd[LEN_64]; + unsigned int len = 0; + long tmp = 0; + char *ptr = NULL, *pRaw = NULL; + + // Parse command raw data + memset(hci_cmd, 0, sizeof(hci_cmd)); + pRaw = cmd_raw; + ptr = cmd_raw; + while(*ptr != '\0' && pRaw != NULL) { + if (len > LEN_64 - 1) { + BT_LOG_PRT_INFO("%s: skip since cmd length exceed!", __func__); + return; + } + ptr = strsep(&pRaw, " "); + if (ptr != NULL) { + _osal_strtol(ptr, 16, &tmp); + hci_cmd[len++] = (unsigned char)tmp; + } + } + + // Initialize rx variables + g_bt_dbg_st.rx_len = 0; + g_bt_dbg_st.trx_opcode = hci_cmd[1] + (hci_cmd[2] << 8); + memset(g_bt_dbg_st.rx_buf, 0, sizeof(g_bt_dbg_st.rx_buf)); + BT_LOG_PRT_INFO_RAW(hci_cmd, len, "%s: len[%ud], TxCmd: ", __func__, len); + + // Send command and wait for command_complete event + g_bt_dbg_st.trx_enable = TRUE; + send_hci_frame(hci_cmd, len); + if (!wait_for_completion_timeout(&g_bt_dbg_st.trx_comp, msecs_to_jiffies(2000))) + BT_LOG_PRT_ERR("%s: wait event timeout!", __func__); + g_bt_dbg_st.trx_enable = FALSE; +} + +ssize_t bt_dbg_write(struct file *filp, const char __user *buffer, size_t count, loff_t *f_pos) +{ + bool is_passwd = FALSE, is_turn_on = FALSE; + size_t len = count; + char buf[256], *pBuf; + int x = 0, y = 0, z = 0; + long res = 0; + char* pToken = NULL; + char* pDelimiter = " \t"; + + if (len <= 0 || len >= sizeof(buf)) { + BT_LOG_PRT_ERR("input handling fail!\n"); + len = sizeof(buf) - 1; + return -1; + } + + memset(buf, 0, sizeof(buf)); + if (copy_from_user(buf, buffer, len)) + return -EFAULT; + buf[len] = '\0'; + BT_LOG_PRT_INFO("g_bt_turn_on[%d], dbg_enable[%d], len[%d], data = %s\n", + g_bt_turn_on, g_bt_dbg_enable, (int)len, buf); + + /* Check debug function is enabled or not + * - not enable yet: user should enable it + * - already enabled: user can disable it + */ + if (len > strlen(BT_DBG_PASSWD) && + 0 == memcmp(buf, BT_DBG_PASSWD, strlen(BT_DBG_PASSWD))) { + is_passwd = TRUE; + if (0 == memcmp(buf + strlen(BT_DBG_PASSWD), "ON", strlen("ON"))) + is_turn_on = TRUE; + } + if(!g_bt_dbg_enable) { + if(is_passwd && is_turn_on) + g_bt_dbg_enable = TRUE; + return len; + } else { + if(is_passwd && !is_turn_on) { + g_bt_dbg_enable = FALSE; + return len; + } + } + + /* Mode 1: User trx flow: send command, get response */ + if (0 == memcmp(buf, BT_DBG_USER_TRX_PREFIX, strlen(BT_DBG_USER_TRX_PREFIX))) { + if(!g_bt_turn_on) // only work when bt on + return len; + buf[len - 1] = '\0'; + bt_dbg_user_trx_proc(buf + strlen(BT_DBG_USER_TRX_PREFIX)); + return len; + } + + /* Mode 2: Debug cmd flow, parse three parameters */ + pBuf = buf; + pToken = strsep(&pBuf, pDelimiter); + if (pToken != NULL) { + _osal_strtol(pToken, 16, &res); + x = (int)res; + } else { + x = 0; + } + + pToken = strsep(&pBuf, "\t\n "); + if (pToken != NULL) { + _osal_strtol(pToken, 16, &res); + y = (int)res; + BT_LOG_PRT_INFO("y = 0x%08x\n", y); + } else { + y = 3000; + /*efuse, register read write default value */ + if (0x5 == x || 0x6 == x) + y = 0x80000000; + } + + pToken = strsep(&pBuf, "\t\n "); + if (pToken != NULL) { + _osal_strtol(pToken, 16, &res); + z = (int)res; + } else { + z = 10; + /*efuse, register read write default value */ + if (0x5 == x || 0x6 == x) + z = 0xffffffff; + } + + BT_LOG_PRT_INFO("x(0x%08x), y(0x%08x), z(0x%08x)\n", x, y, z); + if (ARRAY_SIZE(bt_dev_dbg_struct) > x && NULL != bt_dev_dbg_struct[x].func) { + if(!g_bt_turn_on && !bt_dev_dbg_struct[x].turn_off_availavle) { + BT_LOG_PRT_WARN("command id(0x%08x) only work when bt on!\n", x); + } else { + (*bt_dev_dbg_struct[x].func) (x, y, z); + } + } else { + BT_LOG_PRT_WARN("command id(0x%08x) no handler defined!\n", x); + } + + return len; +} + +int bt_dev_dbg_init(void) +{ + int i_ret = 0; + static const struct file_operations bt_dbg_fops = { + .owner = THIS_MODULE, + .read = bt_dbg_read, + .write = bt_dbg_write, + }; + + // initialize debug function struct + g_bt_dbg_st.trx_enable = FALSE; + g_bt_dbg_st.trx_opcode = 0; + g_bt_dbg_st.trx_cb = bt_dbg_user_trx_cb; + init_completion(&g_bt_dbg_st.trx_comp); + + g_bt_dbg_entry = proc_create(BT_DBG_PROCNAME, 0664, NULL, &bt_dbg_fops); + if (g_bt_dbg_entry == NULL) { + BT_LOG_PRT_ERR("Unable to create [%s] bt proc entry\n", BT_DBG_PROCNAME); + i_ret = -1; + } + + mutex_init(&g_bt_lock); + + BT_LOG_PRT_INFO("create [%s] done\n", BT_DBG_PROCNAME); + return i_ret; +} + +int bt_dev_dbg_deinit(void) +{ + mutex_destroy(&g_bt_lock); + + if (g_bt_dbg_entry != NULL) { + proc_remove(g_bt_dbg_entry); + g_bt_dbg_entry = NULL; + } + + return 0; +} + + +int bt_dev_dbg_set_state(bool turn_on) +{ + g_bt_turn_on = turn_on; + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/fw_log_bt.c b/drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/fw_log_bt.c new file mode 100644 index 0000000000000..de10bf7c6f146 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/fw_log_bt.c @@ -0,0 +1,347 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH +#include "bt.h" +#include "connsys_debug_utility.h" + +MODULE_LICENSE("Dual BSD/GPL"); + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define BT_LOG_NODE_NAME "fw_log_bt" + +#define BT_FW_LOG_IOC_MAGIC (0xfc) +#define BT_FW_LOG_IOCTL_ON_OFF _IOW(BT_FW_LOG_IOC_MAGIC, 0, int) +#define BT_FW_LOG_IOCTL_SET_LEVEL _IOW(BT_FW_LOG_IOC_MAGIC, 1, int) +#define BT_FW_LOG_IOCTL_GET_LEVEL _IOW(BT_FW_LOG_IOC_MAGIC, 2, int) + +static unsigned char g_bt_on = OFF; +static unsigned char g_log_on = OFF; +static unsigned char g_log_level = DEFAULT_LEVEL; +static unsigned char g_log_current = OFF; + +#define BT_LOG_BUFFER_SIZE 512 + +static struct cdev log_cdev; +#if CREATE_NODE_DYNAMIC +static struct class *log_class; +static struct device *log_dev; +#endif +static dev_t devno; + +wait_queue_head_t BT_log_wq; + +static struct semaphore ioctl_mtx; + +static int ascii_to_hex(unsigned char ascii, unsigned char *hex) +{ + int ret = 0; + + if('0' <= ascii && ascii <= '9') + *hex = ascii - '0'; + else if ('a' <= ascii && ascii <= 'f') + *hex = ascii - 'a' + 10; + else if ('A' <= ascii && ascii <= 'F') + *hex = ascii - 'A' + 10; + else + ret = -1; + + return ret; +} + +static int set_fw_log(unsigned char flag) +{ + ssize_t retval = 0; + + /* Opcode 0xfc5d TCI_MTK_DEBUG_VERSION_INFO */ + unsigned char HCI_CMD_FW_LOG_DEBUG[] = {0x01, 0x5d, 0xfc, 0x04, 0x02, 0x00, 0x01, 0xff}; // Via EMI + + HCI_CMD_FW_LOG_DEBUG[7] = flag; + BT_LOG_PRT_INFO("hci_cmd: %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x\n", + HCI_CMD_FW_LOG_DEBUG[0], HCI_CMD_FW_LOG_DEBUG[1], + HCI_CMD_FW_LOG_DEBUG[2], HCI_CMD_FW_LOG_DEBUG[3], + HCI_CMD_FW_LOG_DEBUG[4], HCI_CMD_FW_LOG_DEBUG[5], + HCI_CMD_FW_LOG_DEBUG[6], HCI_CMD_FW_LOG_DEBUG[7]); + + retval = send_hci_frame(HCI_CMD_FW_LOG_DEBUG, sizeof(HCI_CMD_FW_LOG_DEBUG)); + + if (likely(retval == sizeof(HCI_CMD_FW_LOG_DEBUG))) + return 0; + else if (retval < 0) + return retval; + else { + BT_LOG_PRT_ERR("Only partial sent %zu bytes, but hci cmd has %zu bytes", retval, sizeof(HCI_CMD_FW_LOG_DEBUG)); + return -EFAULT; + } +} + +void bt_state_notify(UINT32 on_off) +{ + BT_LOG_PRT_INFO("g_bt_on %d, on_off %d\n", g_bt_on, on_off); + + if (g_bt_on == on_off) { + // no change. + } else { + // changed. + if (on_off == OFF) { // should turn off. + g_bt_on = OFF; + BT_LOG_PRT_INFO("BT func off, no need to send hci cmd\n"); + } else { + g_bt_on = ON; + if(g_log_current) + set_fw_log(g_log_current); + } + } +} + +long fw_log_bt_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + long retval = 0; + unsigned char log_tmp = OFF; + + down(&ioctl_mtx); + switch (cmd) { + case BT_FW_LOG_IOCTL_ON_OFF: + /* connsyslogger daemon dynamically enable/disable Picus log */ + BT_LOG_PRT_INFO("BT_FW_LOG_IOCTL_ON_OFF: arg(%lu), g_bt_on(0x%02x), g_log_on(0x%02x), g_log_level(0x%02x), g_log_current(0x%02x)\n", + arg, g_bt_on, g_log_on, g_log_level, g_log_current); + log_tmp = (arg == 0 ? OFF: ON); + if (log_tmp == g_log_on) // no change + break; + else { // changed + g_log_on = log_tmp; + g_log_current = g_log_on & g_log_level; + if (g_bt_on) + retval = set_fw_log(g_log_current); + } + break; + case BT_FW_LOG_IOCTL_SET_LEVEL: + /* connsyslogger daemon dynamically set Picus log level */ + BT_LOG_PRT_INFO("BT_FW_LOG_IOCTL_SET_LEVEL: arg(%lu), g_bt_on(0x%02x), g_log_on(0x%02x), g_log_level(0x%02x), g_log_current(0x%02x)\n", + arg, g_bt_on, g_log_on, g_log_level, g_log_current); + log_tmp = (unsigned char)arg; + if(log_tmp == g_log_level) // no change + break; + else { + g_log_level = log_tmp; + g_log_current = g_log_on & g_log_level; + if (g_bt_on & g_log_on) // driver on and log on + retval = set_fw_log(g_log_current); + } + break; + case BT_FW_LOG_IOCTL_GET_LEVEL: + retval = g_log_level; + BT_LOG_PRT_INFO("BT_FW_LOG_IOCTL_GET_LEVEL: %ld\n", retval); + break; + default: + BT_LOG_PRT_ERR("Unknown cmd: 0x%08x\n", cmd); + retval = -EOPNOTSUPP; + break; + } + + up(&ioctl_mtx); + return retval; +} + +long fw_log_bt_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + return fw_log_bt_unlocked_ioctl(filp, cmd, arg); +} + +static void fw_log_bt_event_cb(void) +{ + BT_LOG_PRT_DBG("fw_log_bt_event_cb"); + wake_up_interruptible(&BT_log_wq); +} + +static unsigned int fw_log_bt_poll(struct file *file, poll_table *wait) +{ + unsigned int mask = 0; + + poll_wait(file, &BT_log_wq, wait); + if (connsys_log_get_buf_size(CONNLOG_TYPE_BT) > 0) { + mask = (POLLIN | POLLRDNORM); + } + return mask; +} + +static ssize_t fw_log_bt_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) +{ + ssize_t retval = 0; + UINT8 tmp_buf[BT_LOG_BUFFER_SIZE] = {0}; + UINT8 hci_cmd[BT_LOG_BUFFER_SIZE] = {0}; + UINT8 tmp = 0, tmp_h = 0; + size_t i = 0, j = 0, k = 0; + + if(count >= BT_LOG_BUFFER_SIZE) { + BT_LOG_PRT_ERR("write count %zd exceeds max buffer size %d", count, BT_LOG_BUFFER_SIZE); + retval = -EINVAL; + goto OUT; + } + + if (copy_from_user(tmp_buf, buf, count)) { + BT_LOG_PRT_ERR("copy_from_user failed!\n"); + retval = -EFAULT; + } else { + BT_LOG_PRT_INFO("adb input: %s, len %zd\n", tmp_buf, strlen(tmp_buf)); + if (0 == memcmp(tmp_buf, "raw-hex,", strlen("raw-hex,"))) { + // Skip prefix + for(i = strlen("raw-hex,"); i < strlen(tmp_buf); i++) { + if(tmp_buf[i] == ' ') // get space + continue; + else if(tmp_buf[i] == '\r' || tmp_buf[i] =='\n') // get 0x0a('\n') or 0x0d('\r') + break; + // Two input char should turn to one byte + if (ascii_to_hex(tmp_buf[i], &tmp) == 0) { + if (j%2 == 0) + tmp_h = tmp; + else { + hci_cmd[k] = tmp_h * 16 + tmp; + BT_LOG_PRT_DBG("hci_cmd[%zd] = 0x%02x\n", k, hci_cmd[k]); + k++; + } + } else { + BT_LOG_PRT_ERR("get unexpected char %c\n", tmp_buf[i]); + retval = -EINVAL; + goto OUT; + } + j++; + } + } + // ONLY send hci cmd when BT func on + if (!g_bt_on) { + retval = -EIO; + BT_LOG_PRT_ERR("BT func off, skip to send hci cmd\n"); + } else + retval = send_hci_frame(hci_cmd, k); + + } +OUT: + + return retval; +} + +static ssize_t fw_log_bt_read(struct file *filp, char __user *buf, size_t len, loff_t *f_pos) +{ + size_t ret = 0; + + ret = connsys_log_read_to_user(CONNLOG_TYPE_BT, buf, len); + BT_LOG_PRT_DBG("BT F/W log from connsys len %zd\n", ret); + return ret; +} + +static int fw_log_bt_open(struct inode *inode, struct file *file) +{ + BT_LOG_PRT_INFO("major %d minor %d (pid %d)\n", imajor(inode), iminor(inode), current->pid); + return 0; +} + +static int fw_log_bt_close(struct inode *inode, struct file *file) +{ + BT_LOG_PRT_INFO("major %d minor %d (pid %d)\n", imajor(inode), iminor(inode), current->pid); + return 0; +} + +struct file_operations log_fops = { + .open = fw_log_bt_open, + .release = fw_log_bt_close, + .read = fw_log_bt_read, + .write = fw_log_bt_write, + .unlocked_ioctl = fw_log_bt_unlocked_ioctl, + .compat_ioctl = fw_log_bt_compat_ioctl, + .poll = fw_log_bt_poll +}; + +int fw_log_bt_init(void) +{ + INT32 alloc_ret = 0; + INT32 cdv_err = 0; + + connsys_log_init(CONNLOG_TYPE_BT); + + init_waitqueue_head(&BT_log_wq); + connsys_log_register_event_cb(CONNLOG_TYPE_BT, fw_log_bt_event_cb); + sema_init(&ioctl_mtx, 1); + + /* Allocate char device */ + alloc_ret = alloc_chrdev_region(&devno, 0, 1, BT_LOG_NODE_NAME); + if (alloc_ret) { + BT_LOG_PRT_ERR("Failed to register device numbers\n"); + return alloc_ret; + } + + cdev_init(&log_cdev, &log_fops); + log_cdev.owner = THIS_MODULE; + + cdv_err = cdev_add(&log_cdev, devno, 1); + if (cdv_err) + goto error; + +#if CREATE_NODE_DYNAMIC /* mknod replace */ + log_class = class_create(THIS_MODULE, BT_LOG_NODE_NAME); + if (IS_ERR(log_class)) + goto error; + + log_dev = device_create(log_class, NULL, devno, NULL, BT_LOG_NODE_NAME); + if (IS_ERR(log_dev)) + goto error; +#endif + + BT_LOG_PRT_INFO("%s driver(major %d, minor %d) installed\n", BT_LOG_NODE_NAME, MAJOR(devno), MINOR(devno)); + return 0; + +error: + +#if CREATE_NODE_DYNAMIC + if (log_dev && !IS_ERR(log_dev)) { + device_destroy(log_class, devno); + log_dev = NULL; + } + if (log_class && !IS_ERR(log_class)) { + class_destroy(log_class); + log_class = NULL; + } +#endif + if (cdv_err == 0) + cdev_del(&log_cdev); + + if (alloc_ret == 0) + unregister_chrdev_region(devno, 1); + + return -1; +} + +void fw_log_bt_exit(void) +{ + connsys_log_deinit(CONNLOG_TYPE_BT); + + cdev_del(&log_cdev); + unregister_chrdev_region(devno, 1); + +#if CREATE_NODE_DYNAMIC + if (log_dev && !IS_ERR(log_dev)) { + device_destroy(log_class, devno); + log_dev = NULL; + } + if (log_class && !IS_ERR(log_class)) { + class_destroy(log_class); + log_class = NULL; + } +#endif + BT_LOG_PRT_INFO("%s driver removed\n", BT_LOG_NODE_NAME); +} +#endif diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/init.bt_drv.rc b/drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/init.bt_drv.rc new file mode 100644 index 0000000000000..b857ffba811c5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/init.bt_drv.rc @@ -0,0 +1,4 @@ +# load bt_drv +on property:vendor.connsys.driver.ready=yes + insmod /vendor/lib/modules/bt_drv.ko + chown bluetooth bluetooth /proc/driver/bt_dbg \ No newline at end of file diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/stp_chrdev_bt.c b/drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/stp_chrdev_bt.c new file mode 100644 index 0000000000000..1ad5ea7fa330c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/stp_chrdev_bt.c @@ -0,0 +1,849 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#include "bt.h" +#include +#include +#include +#include +#include + +MODULE_LICENSE("Dual BSD/GPL"); + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define BT_DRIVER_NAME "mtk_stp_bt_chrdev" +#define BT_DEV_MAJOR 192 + +#define VERSION "2.0" + +#define COMBO_IOC_MAGIC 0xb0 +#define COMBO_IOCTL_FW_ASSERT _IOW(COMBO_IOC_MAGIC, 0, int) +#define COMBO_IOCTL_BT_SET_PSM _IOW(COMBO_IOC_MAGIC, 1, bool) +#define COMBO_IOCTL_BT_IC_HW_VER _IOR(COMBO_IOC_MAGIC, 2, void*) +#define COMBO_IOCTL_BT_IC_FW_VER _IOR(COMBO_IOC_MAGIC, 3, void*) + +#define BT_BUFFER_SIZE 2048 +#define FTRACE_STR_LOG_SIZE 256 +#define REG_READL(addr) readl((volatile uint32_t *)(addr)) + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static INT32 BT_devs = 1; +static INT32 BT_major = BT_DEV_MAJOR; +module_param(BT_major, uint, 0); +static struct cdev BT_cdev; +#if CREATE_NODE_DYNAMIC +static struct class *stpbt_class; +static struct device *stpbt_dev; +#endif + +static UINT8 i_buf[BT_BUFFER_SIZE]; /* Input buffer for read */ +static UINT8 o_buf[BT_BUFFER_SIZE]; /* Output buffer for write */ + +static struct semaphore wr_mtx, rd_mtx; +static struct wakeup_source *bt_wakelock; +/* Wait queue for poll and read */ +static wait_queue_head_t inq; +static DECLARE_WAIT_QUEUE_HEAD(BT_wq); +static INT32 flag; +static INT32 bt_ftrace_flag; +static bool btonflag = 0; +UINT32 gBtDbgLevel = BT_LOG_INFO; +struct bt_dbg_st g_bt_dbg_st; +#if (PM_QOS_CONTROL == 1) +static struct pm_qos_request qos_req; +static struct pm_qos_ctrl qos_ctrl; +#endif + +/* + * Reset flag for whole chip reset scenario, to indicate reset status: + * 0 - normal, no whole chip reset occurs + * 1 - reset start + * 2 - reset end, have not sent Hardware Error event yet + * 3 - reset end, already sent Hardware Error event + */ +static UINT32 rstflag; +static UINT8 HCI_EVT_HW_ERROR[] = {0x04, 0x10, 0x01, 0x00}; +static loff_t rd_offset; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +extern int bt_dev_dbg_init(void); +extern int bt_dev_dbg_deinit(void); +extern int bt_dev_dbg_set_state(bool turn_on); + +static INT32 ftrace_print(const PINT8 str, ...) +{ +#ifdef CONFIG_TRACING + va_list args; + int ret = 0; + INT8 temp_string[FTRACE_STR_LOG_SIZE]; + + if (bt_ftrace_flag) { + va_start(args, str); + ret = vsnprintf(temp_string, FTRACE_STR_LOG_SIZE, str, args); + va_end(args); + if (ret < 0) { + BT_LOG_PRT_ERR("error return value in vsnprintf ret = [%d]\n", ret); + return 0; + } + trace_printk("%s\n", temp_string); + } +#endif + return 0; +} + +static size_t bt_report_hw_error(char *buf, size_t count, loff_t *f_pos) +{ + size_t bytes_rest, bytes_read; + + if (*f_pos == 0) + BT_LOG_PRT_INFO("Send Hardware Error event to stack to restart Bluetooth\n"); + + bytes_rest = sizeof(HCI_EVT_HW_ERROR) - *f_pos; + bytes_read = count < bytes_rest ? count : bytes_rest; + memcpy(buf, HCI_EVT_HW_ERROR + *f_pos, bytes_read); + *f_pos += bytes_read; + + return bytes_read; +} + +static uint32_t inline bt_read_cr(unsigned char *cr_name, uint32_t addr) +{ + uint32_t value = 0; + uint8_t *base = ioremap_nocache(addr, 0x10); + + if (base == NULL) { + BT_LOG_PRT_WARN("remapping 0x%08x fail\n", addr); + } else { + value = REG_READL(base); + iounmap(base); + BT_LOG_PRT_INFO("%s[0x%08x], read[0x%08x]\n", cr_name, addr, value); + } + return value; +} + +static struct notifier_block bt_fb_notifier; +static int bt_fb_notifier_callback(struct notifier_block + *self, unsigned long event, void *data) +{ + struct fb_event *evdata = data; + int32_t blank = 0; + + if ((event != FB_EVENT_BLANK)) + return 0; + + blank = *(int32_t *)evdata->data; + switch (blank) { + case FB_BLANK_UNBLANK: + case FB_BLANK_POWERDOWN: + if(btonflag == 1 && rstflag == 0) { + BT_LOG_PRT_INFO("blank state [%ld]", blank); + bt_read_cr("HOST_MAILBOX_BT_ADDR", 0x18007124); + } + break; + default: + break; + } + + return 0; +} + +static int bt_fb_notify_register(void) +{ + int32_t ret; + + bt_fb_notifier.notifier_call = bt_fb_notifier_callback; + + ret = fb_register_client(&bt_fb_notifier); + if (ret) + BT_LOG_PRT_WARN("Register bt_fb_notifier failed:%d\n", ret); + else + BT_LOG_PRT_DBG("Register bt_fb_notifier succeed\n"); + + return ret; +} + +static void bt_fb_notify_unregister(void) +{ + fb_unregister_client(&bt_fb_notifier); +} + +/******************************************************************* +* WHOLE CHIP RESET message handler +******************************************************************** +*/ +static VOID bt_cdev_rst_cb(ENUM_WMTDRV_TYPE_T src, + ENUM_WMTDRV_TYPE_T dst, ENUM_WMTMSG_TYPE_T type, PVOID buf, UINT32 sz) +{ + ENUM_WMTRSTMSG_TYPE_T rst_msg; + + if (sz > sizeof(ENUM_WMTRSTMSG_TYPE_T)) { + BT_LOG_PRT_WARN("Invalid message format!\n"); + return; + } + + memcpy((PINT8)&rst_msg, (PINT8)buf, sz); + BT_LOG_PRT_DBG("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)) { + switch (rst_msg) { + case WMTRSTMSG_RESET_START: +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + bt_state_notify(OFF); +#endif + BT_LOG_PRT_INFO("Whole chip reset start!\n"); + rstflag = 1; + break; + + case WMTRSTMSG_RESET_END: + case WMTRSTMSG_RESET_END_FAIL: + if (rst_msg == WMTRSTMSG_RESET_END) + BT_LOG_PRT_INFO("Whole chip reset end!\n"); + else + BT_LOG_PRT_INFO("Whole chip reset fail!\n"); + rd_offset = 0; + rstflag = 2; + flag = 1; + wake_up_interruptible(&inq); + wake_up(&BT_wq); + break; + + default: + break; + } + } +} + +static VOID BT_event_cb(VOID) +{ + BT_LOG_PRT_DBG("BT_event_cb\n"); + ftrace_print("%s get called", __func__); + + /* + * Hold wakelock for 100ms to avoid system enter suspend in such case: + * FW has sent data to host, STP driver received the data and put it + * into BT rx queue, then send sleep command and release wakelock as + * quick sleep mechanism for low power, BT driver will wake up stack + * hci thread stuck in poll or read. + * But before hci thread comes to read data, system enter suspend, + * hci command timeout timer keeps counting during suspend period till + * expires, then the RTC interrupt wakes up system, command timeout + * handler is executed and meanwhile the event is received. + * This will false trigger FW assert and should never happen. + */ + __pm_wakeup_event(bt_wakelock, 100); + +#if (PM_QOS_CONTROL == 1) + /* pm qos control: + * Set pm_qos to higher level for mass data transfer. + * When rx packet reveived, schedule a work to restore pm_qos setting after 500ms. + * If next packet is receiving before 500ms, this work will be cancel & re-schedule. + * (500ms: better power performance after experiment) + */ + down(&qos_ctrl.sem); + if(qos_ctrl.task != NULL ) { + cancel_delayed_work(&qos_ctrl.work); + if(qos_ctrl.is_hold == FALSE) { + pm_qos_update_request(&qos_req, 1000); + qos_ctrl.is_hold = TRUE; + BT_LOG_PRT_INFO("[qos] is_hold[%d]\n", qos_ctrl.is_hold); + } + queue_delayed_work(qos_ctrl.task, &qos_ctrl.work, (500 * HZ) >> 10); + } + up(&qos_ctrl.sem); +#endif + + /* + * Finally, wake up any reader blocked in poll or read + */ + flag = 1; + wake_up_interruptible(&inq); + wake_up(&BT_wq); + ftrace_print("%s wake_up triggered", __func__); +} + +unsigned int BT_poll(struct file *filp, poll_table *wait) +{ + UINT32 mask = 0; + + if ((mtk_wcn_stp_is_rxqueue_empty(BT_TASK_INDX) && rstflag == 0) || + (rstflag == 1) || (rstflag == 3)) { + /* + * BT rx queue is empty, or whole chip reset start, or already sent Hardware Error event + * for whole chip reset end, add to wait queue. + */ + poll_wait(filp, &inq, wait); + /* + * Check if condition changes before poll_wait return, in case of + * wake_up_interruptible is called before add_wait_queue, otherwise, + * do_poll will get into sleep and never be waken up until timeout. + */ + if (!((mtk_wcn_stp_is_rxqueue_empty(BT_TASK_INDX) && rstflag == 0) || + (rstflag == 1) || (rstflag == 3))) + mask |= POLLIN | POLLRDNORM; /* Readable */ + } else { + /* BT rx queue has valid data, or whole chip reset end, have not sent Hardware Error event yet */ + mask |= POLLIN | POLLRDNORM; /* Readable */ + } + + /* Do we need condition here? */ + mask |= POLLOUT | POLLWRNORM; /* Writable */ + ftrace_print("%s: return mask = 0x%04x", __func__, mask); + + return mask; +} + +static ssize_t __bt_write(const PUINT8 buffer, size_t count) +{ + INT32 retval = 0; + + retval = mtk_wcn_stp_send_data(buffer, count, BT_TASK_INDX); + + if (retval < 0) + BT_LOG_PRT_ERR("mtk_wcn_stp_send_data fail, retval %d\n", retval); + else if (retval == 0) { + /* Device cannot process data in time, STP queue is full and no space is available for write, + * native program should not call writev with no delay. + */ + BT_LOG_PRT_INFO_RATELIMITED("write count %zd, sent bytes %d, no space is available!\n", count, retval); + retval = -EAGAIN; + } else + BT_LOG_PRT_DBG("write count %zd, sent bytes %d\n", count, retval); + + return retval; +} + +ssize_t send_hci_frame(const PUINT8 buff, size_t count) +{ + ssize_t retval = 0; + int retry = 0; + + down(&wr_mtx); + + do { + if (retry > 0) { + msleep(30); + BT_LOG_PRT_ERR("Send hci cmd failed, retry %d time(s)\n", retry); + } + retval = __bt_write(buff, count); + retry++; + } while (retval == -EAGAIN && retry < 3); + + up(&wr_mtx); + + return retval; +} + +ssize_t BT_write_iter(struct kiocb *iocb, struct iov_iter *from) +{ + INT32 retval = 0; + size_t count = iov_iter_count(from); + + ftrace_print("%s get called, count %zu", __func__, count); + down(&wr_mtx); + + BT_LOG_PRT_DBG("count %zd\n", count); + + if (rstflag) { + BT_LOG_PRT_ERR("whole chip reset occurs! rstflag=%d\n", rstflag); + retval = -EIO; + goto OUT; + } + + if (count > 0) { + if (count > BT_BUFFER_SIZE) { + BT_LOG_PRT_ERR("write count %zd exceeds max buffer size %d", count, BT_BUFFER_SIZE); + retval = -EINVAL; + goto OUT; + } + + if (copy_from_iter(o_buf, count, from) != count) { + retval = -EFAULT; + goto OUT; + } + + BT_LOG_PRT_DBG_RAW(o_buf, count, "%s: len[%d], TX: ", __func__, count); + retval = __bt_write(o_buf, count); + } + +OUT: + up(&wr_mtx); + return retval; +} + +ssize_t BT_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) +{ + INT32 retval = 0; + + ftrace_print("%s get called, count %zu", __func__, count); + down(&wr_mtx); + + BT_LOG_PRT_DBG("count %zd pos %lld\n", count, *f_pos); + + if (rstflag) { + BT_LOG_PRT_ERR("whole chip reset occurs! rstflag=%d\n", rstflag); + retval = -EIO; + goto OUT; + } + + if (count > 0) { + if (count > BT_BUFFER_SIZE) { + BT_LOG_PRT_ERR("write count %zd exceeds max buffer size %d", count, BT_BUFFER_SIZE); + retval = -EINVAL; + goto OUT; + } + + if (copy_from_user(o_buf, buf, count)) { + retval = -EFAULT; + goto OUT; + } + + BT_LOG_PRT_DBG_RAW(o_buf, count, "%s: len[%d], TX: ", __func__, count); + retval = __bt_write(o_buf, count); + } + +OUT: + up(&wr_mtx); + return retval; +} + +ssize_t BT_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + INT32 retval = 0; + + ftrace_print("%s get called, count %zu", __func__, count); + down(&rd_mtx); + + BT_LOG_PRT_DBG("count %zd pos %lld\n", count, *f_pos); + + if (rstflag) { + while (rstflag != 2) { + /* + * If nonblocking mode, return directly. + * O_NONBLOCK is specified during open() + */ + if (filp->f_flags & O_NONBLOCK) { + BT_LOG_PRT_ERR("Non-blocking read, whole chip reset occurs! rstflag=%d\n", rstflag); + retval = -EIO; + goto OUT; + } + + wait_event(BT_wq, flag != 0); + flag = 0; + } + /* + * Reset end, send Hardware Error event to stack only once. + * To avoid high frequency read from stack before process is killed, set rstflag to 3 + * to block poll and read after Hardware Error event is sent. + */ + retval = bt_report_hw_error(i_buf, count, &rd_offset); + if (rd_offset == sizeof(HCI_EVT_HW_ERROR)) { + rd_offset = 0; + rstflag = 3; + } + + if (copy_to_user(buf, i_buf, retval)) { + retval = -EFAULT; + if (rstflag == 3) + rstflag = 2; + } + + goto OUT; + } + + if (count > BT_BUFFER_SIZE) { + count = BT_BUFFER_SIZE; + BT_LOG_PRT_WARN("Shorten read count from %zd to %d\n", count, BT_BUFFER_SIZE); + } + + do { + retval = mtk_wcn_stp_receive_data(i_buf, count, BT_TASK_INDX); + if (retval < 0) { + BT_LOG_PRT_ERR("mtk_wcn_stp_receive_data fail, retval %d\n", retval); + goto OUT; + } else if (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_LOG_PRT_ERR("Non-blocking read, no data is available!\n"); + retval = -EAGAIN; + goto OUT; + } + + wait_event(BT_wq, flag != 0); + flag = 0; + } else { /* Got something from STP driver */ + // for bt_dbg user trx function + if (g_bt_dbg_st.trx_enable) { + g_bt_dbg_st.trx_cb(i_buf, retval); + } + //BT_LOG_PRT_DBG("Read bytes %d\n", retval); + BT_LOG_PRT_DBG_RAW(i_buf, retval, "%s: len[%d], RX: ", __func__, retval); + break; + } + } while (!mtk_wcn_stp_is_rxqueue_empty(BT_TASK_INDX) && rstflag == 0); + + if (retval == 0) { + if (rstflag != 2) { /* Should never happen */ + WARN(1, "Blocking read is waken up with no data but rstflag=%d\n", rstflag); + retval = -EIO; + goto OUT; + } else { /* Reset end, send Hardware Error event only once */ + retval = bt_report_hw_error(i_buf, count, &rd_offset); + if (rd_offset == sizeof(HCI_EVT_HW_ERROR)) { + rd_offset = 0; + rstflag = 3; + } + } + } + + if (copy_to_user(buf, i_buf, retval)) { + retval = -EFAULT; + if (rstflag == 3) + rstflag = 2; + } + +OUT: + up(&rd_mtx); + return retval; +} + +/* int BT_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) */ +long BT_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + INT32 retval = 0; + UINT32 reason; + UINT32 ver = 0; + + BT_LOG_PRT_DBG("cmd: 0x%08x\n", cmd); + + switch (cmd) { + case COMBO_IOCTL_FW_ASSERT: + /* Trigger FW assert for debug */ + reason = (UINT32)arg & 0xFFFF; + BT_LOG_PRT_INFO("Host trigger FW assert......, reason:%d\n", reason); + if (reason == 31) /* HCI command timeout */ + BT_LOG_PRT_INFO("HCI command timeout OpCode 0x%04x\n", ((UINT32)arg >> 16) & 0xFFFF); + + if (mtk_wcn_wmt_assert(WMTDRV_TYPE_BT, reason) == MTK_WCN_BOOL_TRUE) { + BT_LOG_PRT_INFO("Host trigger FW assert succeed\n"); + retval = 0; + } else { + BT_LOG_PRT_ERR("Host trigger FW assert failed\n"); + retval = -EBUSY; + } + break; + case COMBO_IOCTL_BT_SET_PSM: + /* BT stack may need to dynamically enable/disable Power Saving Mode + * in some scenarios for performance, e.g. A2DP chopping. + */ + BT_LOG_PRT_INFO("BT stack change PSM setting: %lu\n", arg); + retval = mtk_wcn_wmt_psm_ctrl((MTK_WCN_BOOL)arg); + break; + case COMBO_IOCTL_BT_IC_HW_VER: + ver = mtk_wcn_wmt_ic_info_get(WMTCHIN_HWVER); + BT_LOG_PRT_INFO("HW ver: 0x%x\n", ver); + if (copy_to_user((UINT32 __user *)arg, &ver, sizeof(ver))) + retval = -EFAULT; + break; + case COMBO_IOCTL_BT_IC_FW_VER: + ver = mtk_wcn_wmt_ic_info_get(WMTCHIN_FWVER); + BT_LOG_PRT_INFO("FW ver: 0x%x\n", ver); + if (copy_to_user((UINT32 __user *)arg, &ver, sizeof(ver))) + retval = -EFAULT; + break; + default: + BT_LOG_PRT_ERR("Unknown cmd: 0x%08x\n", cmd); + retval = -EOPNOTSUPP; + break; + } + + return retval; +} + +long BT_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + return BT_unlocked_ioctl(filp, cmd, arg); +} + +#if (PM_QOS_CONTROL == 1) +static void pm_qos_release(struct work_struct *pwork) +{ + pm_qos_update_request(&qos_req, PM_QOS_DEFAULT_VALUE); + qos_ctrl.is_hold = FALSE; + BT_LOG_PRT_INFO("[qos] is_hold[%d]\n", qos_ctrl.is_hold); +} +#endif + +static int BT_open(struct inode *inode, struct file *file) +{ + if(btonflag) { + BT_LOG_PRT_WARN("BT already on!\n"); + return -EIO; + } + BT_LOG_PRT_INFO("major %d minor %d (pid %d)\n", imajor(inode), iminor(inode), current->pid); + + /* Turn on BT */ + if (mtk_wcn_wmt_func_on(WMTDRV_TYPE_BT) == MTK_WCN_BOOL_FALSE) { + BT_LOG_PRT_WARN("WMT turn on BT fail!\n"); + return -EIO; + } + + BT_LOG_PRT_INFO("WMT turn on BT OK!\n"); + + if (mtk_wcn_stp_is_ready() == MTK_WCN_BOOL_FALSE) { + + BT_LOG_PRT_ERR("STP is not ready!\n"); + mtk_wcn_wmt_func_off(WMTDRV_TYPE_BT); + return -EIO; + } + + mtk_wcn_stp_set_bluez(0); + + BT_LOG_PRT_INFO("Now it's in MTK Bluetooth Mode\n"); + BT_LOG_PRT_INFO("STP is ready!\n"); + + BT_LOG_PRT_DBG("Register BT event callback!\n"); + mtk_wcn_stp_register_event_cb(BT_TASK_INDX, BT_event_cb); + + BT_LOG_PRT_DBG("Register BT reset callback!\n"); + mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_BT, bt_cdev_rst_cb); + + rstflag = 0; + bt_ftrace_flag = 1; + btonflag = 1; + + sema_init(&wr_mtx, 1); + sema_init(&rd_mtx, 1); + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + bt_state_notify(ON); +#endif + bt_dev_dbg_set_state(TRUE); + +#if (PM_QOS_CONTROL == 1) + down(&qos_ctrl.sem); + pm_qos_update_request(&qos_req, PM_QOS_DEFAULT_VALUE); + qos_ctrl.is_hold = FALSE; + qos_ctrl.task = create_singlethread_workqueue("pm_qos_task"); + if (!qos_ctrl.task){ + BT_LOG_PRT_ERR("fail to create pm_qos_task"); + return -EIO; + } + INIT_DELAYED_WORK(&qos_ctrl.work, pm_qos_release); + up(&qos_ctrl.sem); +#endif + bt_fb_notify_register(); + + return 0; +} + +static int BT_close(struct inode *inode, struct file *file) +{ + BT_LOG_PRT_INFO("major %d minor %d (pid %d)\n", imajor(inode), iminor(inode), current->pid); + + bt_fb_notify_unregister(); + bt_dev_dbg_set_state(FALSE); +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + bt_state_notify(OFF); +#endif + + rstflag = 0; + bt_ftrace_flag = 0; + btonflag = 0; + + mtk_wcn_wmt_msgcb_unreg(WMTDRV_TYPE_BT); + mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL); + +#if (PM_QOS_CONTROL == 1) + down(&qos_ctrl.sem); + if(qos_ctrl.task != NULL) { + BT_LOG_PRT_INFO("[qos] cancel delayed work\n"); + cancel_delayed_work(&qos_ctrl.work); + flush_workqueue(qos_ctrl.task); + destroy_workqueue(qos_ctrl.task); + qos_ctrl.task = NULL; + } + pm_qos_update_request(&qos_req, PM_QOS_DEFAULT_VALUE); + qos_ctrl.is_hold = FALSE; + up(&qos_ctrl.sem); +#endif + + if (mtk_wcn_wmt_func_off(WMTDRV_TYPE_BT) == MTK_WCN_BOOL_FALSE) { + BT_LOG_PRT_ERR("WMT turn off BT fail!\n"); + return -EIO; /* Mostly, native program will not check this return value. */ + } + + BT_LOG_PRT_INFO("WMT turn off BT OK!\n"); + return 0; +} + +const struct file_operations BT_fops = { + .open = BT_open, + .release = BT_close, + .read = BT_read, + .write = BT_write, + .write_iter = BT_write_iter, + /* .ioctl = BT_ioctl, */ + .unlocked_ioctl = BT_unlocked_ioctl, + .compat_ioctl = BT_compat_ioctl, + .poll = BT_poll +}; + +static int BT_init(void) +{ + dev_t dev; + INT32 alloc_ret = 0; + INT32 cdv_err = 0; + dev = MKDEV(BT_major, 0); + + /* Initialize wait queue */ + init_waitqueue_head(&(inq)); + /* Initialize wake lock */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 149) + BT_LOG_PRT_INFO("wakeup_source_register() with kernel-4.14.149\n"); + bt_wakelock = wakeup_source_register(NULL, "bt_drv"); +#else + bt_wakelock = wakeup_source_register("bt_drv"); +#endif + if(!bt_wakelock) { + BT_LOG_PRT_ERR("%s: init bt_wakelock failed!\n", __func__); + } + + /* Allocate char device */ + alloc_ret = register_chrdev_region(dev, BT_devs, BT_DRIVER_NAME); + if (alloc_ret) { + BT_LOG_PRT_ERR("Failed to register device numbers\n"); + return alloc_ret; + } + + cdev_init(&BT_cdev, &BT_fops); + BT_cdev.owner = THIS_MODULE; + + cdv_err = cdev_add(&BT_cdev, dev, BT_devs); + if (cdv_err) + goto error; + +#if CREATE_NODE_DYNAMIC /* mknod replace */ + stpbt_class = class_create(THIS_MODULE, "stpbt"); + if (IS_ERR(stpbt_class)) + goto error; + stpbt_dev = device_create(stpbt_class, NULL, dev, NULL, "stpbt"); + if (IS_ERR(stpbt_dev)) + goto error; +#endif + + BT_LOG_PRT_INFO("%s driver(major %d) installed\n", BT_DRIVER_NAME, BT_major); + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + fw_log_bt_init(); +#endif + bt_dev_dbg_init(); + +#if (PM_QOS_CONTROL == 1) + pm_qos_add_request(&qos_req, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE); + sema_init(&qos_ctrl.sem, 1); +#endif + + return 0; + +error: +#if CREATE_NODE_DYNAMIC + if (stpbt_dev && !IS_ERR(stpbt_dev)) { + device_destroy(stpbt_class, dev); + stpbt_dev = NULL; + } + if (stpbt_class && !IS_ERR(stpbt_class)) { + class_destroy(stpbt_class); + stpbt_class = NULL; + } +#endif + if (cdv_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; + +#if (PM_QOS_CONTROL == 1) + pm_qos_remove_request(&qos_req); +#endif + + bt_dev_dbg_deinit(); +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + fw_log_bt_exit(); +#endif + + dev = MKDEV(BT_major, 0); + /* Destroy wake lock*/ + wakeup_source_unregister(bt_wakelock); + +#if CREATE_NODE_DYNAMIC + if (stpbt_dev && !IS_ERR(stpbt_dev)) { + device_destroy(stpbt_class, dev); + stpbt_dev = NULL; + } + if (stpbt_class && !IS_ERR(stpbt_class)) { + class_destroy(stpbt_class); + stpbt_class = NULL; + } +#endif + + cdev_del(&BT_cdev); + unregister_chrdev_region(dev, BT_devs); + + BT_LOG_PRT_INFO("%s driver removed\n", BT_DRIVER_NAME); +} + +#ifdef MTK_WCN_REMOVE_KERNEL_MODULE + +int mtk_wcn_stpbt_drv_init(void) +{ + return BT_init(); +} +EXPORT_SYMBOL(mtk_wcn_stpbt_drv_init); + +void mtk_wcn_stpbt_drv_exit(void) +{ + return BT_exit(); +} +EXPORT_SYMBOL(mtk_wcn_stpbt_drv_exit); + +#else + +module_init(BT_init); +module_exit(BT_exit); + +#endif diff --git a/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/Android.mk b/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/Android.mk new file mode 100644 index 0000000000000..8842ce7b70b33 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/Android.mk @@ -0,0 +1,63 @@ +############################################################################### +# Copyright (c) 2016,2017 MediaTek Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See http://www.gnu.org/licenses/gpl-2.0.html for more details. +# +############################################################################### + +############################################################################### +# Generally Android.mk can not get KConfig setting +# we can use this way to get +# include the final KConfig +# but there is no $(AUTO_CONF) at the first time (no out folder) when make +# +#ifneq (,$(wildcard $(AUTO_CONF))) +#include $(AUTO_CONF) +#include $(CLEAR_VARS) +#endif + +############################################################################### +############################################################################### +# Generally Android.mk can not get KConfig setting # +# # +# do not have any KConfig checking in Android.mk # +# do not have any KConfig checking in Android.mk # +# do not have any KConfig checking in Android.mk # +# # +# e.g. ifeq ($(CONFIG_MTK_COMBO_WIFI), m) # +# xxxx # +# endif # +# # +# e.g. ifneq ($(filter "MT6632",$(CONFIG_MTK_COMBO_CHIP)),) # +# xxxx # +# endif # +# # +# All the KConfig checking should move to Makefile for each module # +# All the KConfig checking should move to Makefile for each module # +# All the KConfig checking should move to Makefile for each module # +# # +############################################################################### +############################################################################### + +LOCAL_PATH := $(call my-dir) + +ifeq ($(MTK_BT_SUPPORT),yes) +ifneq ($(filter MTK_MT76%, $(MTK_BT_CHIP)),) + +include $(CLEAR_VARS) +LOCAL_MODULE := btmtksdio.ko +LOCAL_PROPRIETARY_MODULE := true +LOCAL_MODULE_OWNER := mtk +LOCAL_INIT_RC := init.btmtksdio.rc + +include $(MTK_KERNEL_MODULE) + +endif +endif diff --git a/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/Makefile b/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/Makefile new file mode 100644 index 0000000000000..ff1e1e65492ea --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/Makefile @@ -0,0 +1,20 @@ +############################################################################### +# Bluetooth character device driver + +############################################################################### +# Necessary Check + +ifeq ($(AUTOCONF_H),) + $(error AUTOCONF_H is not defined) +endif + +ccflags-y += -imacros $(AUTOCONF_H) +ccflags-y += -DCONFIG_MP_WAKEUP_SOURCE_SYSFS_STAT + +MODULE_NAME := btmtksdio +obj-m += $(MODULE_NAME).o + +#ccflags-y += -D CREATE_NODE_DYNAMIC=1 + +$(MODULE_NAME)-objs += btmtk_sdio.o \ + btmtk_main.o diff --git a/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/btmtk_config.h b/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/btmtk_config.h new file mode 100644 index 0000000000000..dd24cc04a7ff2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/btmtk_config.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef __BTMTK_CONFIG_H__ +#define __BTMTK_CONFIG_H__ + +#include + +/* It's for reset procedure */ +#include +#include + +/** + * Kernel configuration check + */ +#ifndef CONFIG_PM + #error "ERROR : CONFIG_PM should be turn on." +#endif + +/** + * Support IC configuration + */ +#define SUPPORT_MT7662 1 +#define SUPPORT_MT7668 1 +#define SUPPORT_MT7663 1 + +/** + * BTMTK LOG location, last char must be '/' + */ +/* #define BTMTK_LOG_PATH "/data/misc/bluedroid/" */ + + + +/** + * Fixed STPBT Major Device Id + */ +#define FIXED_STPBT_MAJOR_DEV_ID 111 + +/** + * WoBLE by BLE RC + */ + /*Linux build fail due to wake_lock, please set SUPPORT_ANDROID 0 for Linux*/ +/*#define SUPPORT_ANDROID 0 */ +#define BT_RC_VENDOR_DEFAULT 1 +#define BT_RC_VENDOR_S0 0 + +#define WAIT_POWERKEY_TIMEOUT 5000 + +/** + * Support toggle GPIO + */ +#define MT76x8_PMU_EN_PIN_NAME "mt76x8_pmu_en_gpio" +#define MT76x8_PMU_EN_DELAY_NAME "mt76x8_pmu_en_delay" +#define MT76x8_PMU_EN_DEFAULT_DELAY (5) /* Default delay 5ms */ + +/** + * L0 reset + */ +#define L0_RESET_TAG "[SER][L0] " + +#endif /* __BTMTK_CONFIG_H__ */ diff --git a/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/btmtk_define.h b/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/btmtk_define.h new file mode 100644 index 0000000000000..82b97d81f1beb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/btmtk_define.h @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef __BTMTK_DEFINE_H__ +#define __BTMTK_DEFINE_H__ + +#include "btmtk_config.h" + +/** + * Type definition + */ +#ifndef TRUE + #define TRUE 1 +#endif +#ifndef FALSE + #define FALSE 0 +#endif + +#ifndef UNUSED + #define UNUSED(x) (void)(x) +#endif + +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + +/** + * Log level definition + */ +#define BTMTK_LOG_LEVEL_ERROR 1 +#define BTMTK_LOG_LEVEL_WARNING 2 +#define BTMTK_LOG_LEVEL_INFO 3 +#define BTMTK_LOG_LEVEL_DEBUG 4 +#define BTMTK_LOG_LEVEL_MAX BTMTK_LOG_LEVEL_DEBUG +#define BTMTK_LOG_LEVEL_DEFAULT BTMTK_LOG_LEVEL_INFO /* default setting */ +extern u8 btmtk_log_lvl; + +#define BTMTK_ERR(fmt, ...) \ + do {if (btmtk_log_lvl >= BTMTK_LOG_LEVEL_ERROR) \ + pr_info("[btmtk_err] %s: "fmt"\n", __func__, ##__VA_ARGS__); } while (0) +#define BTMTK_WARN(fmt, ...) \ + do {if (btmtk_log_lvl >= BTMTK_LOG_LEVEL_WARNING) \ + pr_info("[btmtk_warn] %s: "fmt"\n", __func__, ##__VA_ARGS__); } while (0) +#define BTMTK_INFO(fmt, ...) \ + do {if (btmtk_log_lvl >= BTMTK_LOG_LEVEL_INFO) \ + pr_info("[btmtk_info] %s: "fmt"\n", __func__, ##__VA_ARGS__); } while (0) +#define BTMTK_DBG(fmt, ...) \ + do {if (btmtk_log_lvl >= BTMTK_LOG_LEVEL_DEBUG) \ + pr_info("[btmtk_debug] %s: "fmt"\n", __func__, ##__VA_ARGS__); } while (0) + +#define BTMTK_MAX_LOG_LEN 64 /* default length setting */ + +#define BTSDIO_INFO_RAW(p, l, fmt, ...) \ +do { \ + if (btmtk_log_lvl >= BTMTK_LOG_LEVEL_INFO) { \ + int raw_count = 0; \ + char str[BTMTK_MAX_LOG_LEN * 3 + 1]; \ + char *p_str = str; \ + const unsigned char *ptr = p; \ + for (raw_count = 0; raw_count < MIN(l, BTMTK_MAX_LOG_LEN); ++raw_count) \ + p_str += sprintf(p_str, " %02X", ptr[raw_count]); \ + *p_str = '\0'; \ + pr_info("[btmtk_info]"fmt"\n", ##__VA_ARGS__); \ + pr_info(" %s:%d - Length(%d): %s\n", __func__, __LINE__, l, str); \ + } \ +} while (0) + +#define BTSDIO_DEBUG_RAW(p, l, fmt, ...) \ +do { \ + if (btmtk_log_lvl >= BTMTK_LOG_LEVEL_DEBUG) { \ + int raw_count = 0; \ + char str[BTMTK_MAX_LOG_LEN * 3 + 1]; \ + char *p_str = str; \ + const unsigned char *ptr = p; \ + for (raw_count = 0; raw_count < MIN(l, BTMTK_MAX_LOG_LEN); ++raw_count) \ + p_str += sprintf(p_str, " %02X", ptr[raw_count]); \ + *p_str = '\0'; \ + pr_info("[btmtk_debug]"fmt"\n", ##__VA_ARGS__); \ + pr_info(" %s:%d - Length(%d): %s\n", __func__, __LINE__, l, str); \ + } \ +} while (0) + +#define MTK_HCI_WRITE_CR_PKT 0x07 +#define MTK_HCI_READ_CR_PKT 0x08 + +#define MTK_HCI_READ_CR_PKT_LENGTH 0x05 +#define MTK_HCI_WRITE_CR_PKT_LENGTH 0x09 + +#define MTK_HCI_CMD_HEADER_LEN (4) +#define MTK_HCI_ACL_HEADER_LEN (5) +#define MTK_HCI_SCO_HEADER_LEN (4) + +#define PRINT_DUMP_COUNT 20 + +/** + * SYS control + */ +#define SYSCTL 0x400000 + +/** + * WLAN + */ +#define WLAN 0x410000 + +/** + * MCUCTL + */ +#define CLOCK_CTL 0x0708 +#define INT_LEVEL 0x0718 +#define COM_REG0 0x0730 +#define SEMAPHORE_00 0x07B0 +#define SEMAPHORE_01 0x07B4 +#define SEMAPHORE_02 0x07B8 +#define SEMAPHORE_03 0x07BC + +/** + * Timeout setting, mescs + */ +#define USB_CTRL_IO_TIMO 100 +#define USB_INTR_MSG_TIMO 2000 + + +/** + * USB request type definition + */ +#define DEVICE_VENDOR_REQUEST_OUT 0x40 +#define DEVICE_VENDOR_REQUEST_IN 0xc0 +#define DEVICE_CLASS_REQUEST_OUT 0x20 +#define DEVICE_CLASS_REQUEST_IN 0xa0 + +#define BTUSB_MAX_ISOC_FRAMES 10 +#define BTUSB_INTR_RUNNING 0 +#define BTUSB_BULK_RUNNING 1 +#define BTUSB_ISOC_RUNNING 2 +#define BTUSB_SUSPENDING 3 +#define BTUSB_DID_ISO_RESUME 4 + +/** + * ROM patch related + */ +#define PATCH_HCI_HEADER_SIZE 4 +#define PATCH_WMT_HEADER_SIZE 5 +#define PATCH_HEADER_SIZE (PATCH_HCI_HEADER_SIZE + PATCH_WMT_HEADER_SIZE) +#define UPLOAD_PATCH_UNIT 2048 +#define PATCH_INFO_SIZE 30 +#define PATCH_PHASE1 1 +#define PATCH_PHASE2 2 +#define PATCH_PHASE3 3 +#define PATCH_LEN_ILM (192 * 1024) + + +#define USB_IO_BUF_SIZE (HCI_MAX_EVENT_SIZE > 256 ? HCI_MAX_EVENT_SIZE : 256) +#define HCI_SNOOP_ENTRY_NUM 30 +#define HCI_SNOOP_BUF_SIZE 32 +#define FW_LOG_PKT 0xFF + +/** + * stpbt device node + */ +#define BUFFER_SIZE (1024 * 4) /* Size of RX Queue */ + +/** + * fw log queue count + */ +#define FWLOG_QUEUE_COUNT 200 +#define FWLOG_ASSERT_QUEUE_COUNT 10000 +#define FWLOG_BLUETOOTH_KPI_QUEUE_COUNT 200 + +/** + * Maximum rom patch file name length + */ +#define MAX_BIN_FILE_NAME_LEN 32 + + +/** + * Firmware version size + */ +#define FW_VERSION_BUF_SIZE 32 /* 14 bytes for firmware version + 1 bytes for '0' */ +#define FW_VERSION_SIZE 15 /* 14 bytes for firmware version + 1 bytes for '0' */ + +#endif /* __BTMTK_DEFINE_H__ */ diff --git a/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/btmtk_drv.h b/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/btmtk_drv.h new file mode 100644 index 0000000000000..6edc467bde095 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/btmtk_drv.h @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef _BTMTK_DRV_H_ +#define _BTMTK_DRV_H_ + +#include +#include +#include +#include + +#define SUPPORT_FW_DUMP 1 +#define BTM_HEADER_LEN 5 +#define BTM_UPLD_SIZE 2312 + +#ifndef SUPPORT_CR_WR +#define SUPPORT_CR_WR 0 +#endif + +#define MTK_TXDATA_SIZE 2000 +#define MTK_RXDATA_SIZE 2000 + +/* Time to wait until Host Sleep state change in millisecond */ +#define WAIT_UNTIL_HS_STATE_CHANGED msecs_to_jiffies(5000) +/* Time to wait for command response in millisecond */ +#define WAIT_UNTIL_CMD_RESP msecs_to_jiffies(5000) + +/** For 7668 please storage cfg/bin file in ${firmware} */ +#define E2P_ACCESS_MODE_SWITCHER "wifi.cfg" +#define E2P_BIN_FILE "EEPROM_MT%X.bin" + +#define E2P_MODE "EfuseBufferModeCal" +#define E2P_ACCESS_EPA "BtUseExternalPA" +#define E2P_ACCESS_DUPLEX "BtDuplexMode" +#define TX_PWR_LIMIT "BtTxPwrLimit.bin" +#define KEEP_FULL_PWR "KeepFullPwr" +#define PWR_KEEP_NO_FW_OWN '1' +#define PWR_SWITCH_DRIVER_FW_OWN '0' +#define EFUSE_MODE 0 +#define EFUSE_BIN_FILE_MODE 1 +#define EFUSE_AUTO_MODE 2 + + +enum rdwr_status { + RDWR_STATUS_SUCCESS = 0, + RDWR_STATUS_FAILURE = 1, + RDWR_STATUS_DONE = 2 +}; + +#define FW_DUMP_MAX_NAME_LEN 8 +#define FW_DUMP_HOST_READY 0xEE +#define FW_DUMP_DONE 0xFF +#define FW_DUMP_READ_DONE 0xFE + +struct memory_type_mapping { + u8 mem_name[FW_DUMP_MAX_NAME_LEN]; + u8 *mem_ptr; + u32 mem_size; + u8 done_flag; +}; + +struct btmtk_thread { + struct task_struct *task; + wait_queue_head_t wait_q; + void *priv; + u8 thread_status; +}; + +struct btmtk_device { + void *card; + /* struct hci_dev *hcidev; */ + + u8 reset_progress; + u8 reset_dongle; + u8 tx_dnld_rdy; +}; + +struct btmtk_adapter { + void *hw_regs_buf; + u8 *hw_regs; + u32 int_count; +}; + +struct btmtk_private { + struct btmtk_device btmtk_dev; + struct btmtk_adapter *adapter; + struct btmtk_thread main_thread; + int (*hw_host_to_card)(struct btmtk_private *priv, + u8 *payload, u16 nb); + + void (*start_reset_dongle_progress)(void); + int (*hw_sdio_reset_dongle)(void); + int (*hw_set_own_back)(int owntype); + int (*hw_process_int_status)(struct btmtk_private *priv); + void (*hci_snoop_save)(u8 type, u8 *buf, u32 len); + void (*firmware_dump)(struct btmtk_private *priv); + spinlock_t driver_lock; /* spinlock used by driver */ +#ifdef CONFIG_DEBUG_FS + void *debugfs_data; +#endif + bool surprise_removed; +#if SUPPORT_FW_DUMP + struct semaphore fw_dump_semaphore; + struct task_struct *fw_dump_tsk; + struct task_struct *fw_dump_end_check_tsk; +#endif + struct semaphore wr_mtx; + struct semaphore rd_mtx; + struct semaphore wr_fwlog_mtx; + bool no_fw_own; +}; + +#define MTK_VENDOR_PKT 0xFE + +/* Vendor specific Bluetooth commands */ +#define BT_CMD_PSCAN_WIN_REPORT_ENABLE 0xFC03 +#define BT_CMD_ROUTE_SCO_TO_HOST 0xFC1D +#define BT_CMD_SET_BDADDR 0xFC22 +#define BT_CMD_AUTO_SLEEP_MODE 0xFC23 +#define BT_CMD_HOST_SLEEP_CONFIG 0xFC59 +#define BT_CMD_HOST_SLEEP_ENABLE 0xFC5A +#define BT_CMD_MODULE_CFG_REQ 0xFC5B +#define BT_CMD_LOAD_CONFIG_DATA 0xFC61 + +/* Sub-commands: Module Bringup/Shutdown Request/Response */ +#define MODULE_BRINGUP_REQ 0xF1 +#define MODULE_BROUGHT_UP 0x00 +#define MODULE_ALREADY_UP 0x0C + +#define MODULE_SHUTDOWN_REQ 0xF2 + +/* Vendor specific Bluetooth events */ +#define BT_EVENT_AUTO_SLEEP_MODE 0x23 +#define BT_EVENT_HOST_SLEEP_CONFIG 0x59 +#define BT_EVENT_HOST_SLEEP_ENABLE 0x5A +#define BT_EVENT_MODULE_CFG_REQ 0x5B +#define BT_EVENT_POWER_STATE 0x20 + +/* Bluetooth Power States */ +#define BT_PS_ENABLE 0x02 +#define BT_PS_DISABLE 0x03 +#define BT_PS_SLEEP 0x01 + +/* Host Sleep states */ +#define HS_ACTIVATED 0x01 +#define HS_DEACTIVATED 0x00 + +/* Power Save modes */ +#define PS_SLEEP 0x01 +#define PS_AWAKE 0x00 + +#define BT_CAL_HDR_LEN 4 +#define BT_CAL_DATA_SIZE 28 + +#define FW_DUMP_BUF_SIZE (1024*512) + +#define FW_DUMP_FILE_NAME_SIZE 64 + +#define EVENT_COMPARE_SIZE 64 + + +/* stpbt device node */ +#define BT_NODE "stpbt" +#define BT_DRIVER_NAME "BT_chrdev" + +struct btmtk_event { + u8 ec; /* event counter */ + u8 length; + u8 data[4]; +} __packed; + +/* Prototype of global function */ + +struct btmtk_private *btmtk_add_card(void *card); +int btmtk_remove_card(struct btmtk_private *priv); + +void btmtk_interrupt(struct btmtk_private *priv); + +bool btmtk_check_evtpkt(struct btmtk_private *priv, struct sk_buff *skb); +int btmtk_process_event(struct btmtk_private *priv, struct sk_buff *skb); + +int btmtk_send_module_cfg_cmd(struct btmtk_private *priv, u8 subcmd); +int btmtk_pscan_window_reporting(struct btmtk_private *priv, u8 subcmd); +int btmtk_send_hscfg_cmd(struct btmtk_private *priv); +int btmtk_enable_ps(struct btmtk_private *priv); +int btmtk_prepare_command(struct btmtk_private *priv); +void btmtk_firmware_dump(struct btmtk_private *priv); + +#define META_BUFFER_SIZE (1024*50) + +struct _OSAL_UNSLEEPABLE_LOCK_ { + spinlock_t lock; + unsigned long flag; +}; + +struct ring_buffer { + struct _OSAL_UNSLEEPABLE_LOCK_ spin_lock; + u8 buffer[META_BUFFER_SIZE]; /* MTKSTP_BUFFER_SIZE:1024 */ + u32 read_p; /* indicate the current read index */ + u32 write_p; /* indicate the current write index */ +}; + +#define FIXED_STPBT_MAJOR_DEV_ID 111 + +#define FW_DUMP_END_EVENT "coredump end" + +#endif + diff --git a/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/btmtk_main.c b/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/btmtk_main.c new file mode 100644 index 0000000000000..5fde1dc479421 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/btmtk_main.c @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include +#include +#include +#include +#include +#if (KERNEL_VERSION(4, 14, 0) > LINUX_VERSION_CODE) +#include +#else +#include +#endif + +#include "btmtk_define.h" +#include "btmtk_drv.h" +#include "btmtk_sdio.h" + +/* + * This function is called by interface specific interrupt handler. + * It updates Power Save & Host Sleep states, and wakes up the main + * thread. + */ +void btmtk_interrupt(struct btmtk_private *priv) +{ + priv->adapter->int_count++; + + wake_up_interruptible(&priv->main_thread.wait_q); +} +EXPORT_SYMBOL_GPL(btmtk_interrupt); + +static int btmtk_tx_pkt(struct btmtk_private *priv, struct sk_buff *skb) +{ + int ret = 0; + u32 sdio_header_len = 0; + + if (!skb) { + BTMTK_WARN("skb is NULL return -EINVAL"); + return -EINVAL; + } + + BTMTK_DBG("skb->len %d", skb->len); + + if (!skb->data) { + BTMTK_WARN("skb->data is NULL return -EINVAL"); + return -EINVAL; + } + + if (!skb->len || ((skb->len + BTM_HEADER_LEN) > MTK_TXDATA_SIZE)) { + BTMTK_WARN("Tx Error: Bad skb length %d : %d", + skb->len, MTK_TXDATA_SIZE); + return -EINVAL; + } + + if (priv->hci_snoop_save) + priv->hci_snoop_save(bt_cb(skb)->pkt_type, skb->data, skb->len); + + sdio_header_len = skb->len + BTM_HEADER_LEN; + memset(txbuf, 0, MTK_TXDATA_SIZE); + txbuf[0] = (sdio_header_len & 0x0000ff); + txbuf[1] = (sdio_header_len & 0x00ff00) >> 8; + txbuf[2] = 0; + txbuf[3] = 0; + txbuf[4] = bt_cb(skb)->pkt_type; + memcpy(&txbuf[5], &skb->data[0], skb->len); + if (priv->hw_host_to_card) + ret = priv->hw_host_to_card(priv, txbuf, sdio_header_len); + + BTMTK_DBG("end"); + return ret; +} + +static void btmtk_init_adapter(struct btmtk_private *priv) +{ + int buf_size; + + buf_size = ALIGN_SZ(SDIO_BLOCK_SIZE, BTSDIO_DMA_ALIGN); + priv->adapter->hw_regs_buf = kzalloc(buf_size, GFP_KERNEL); + if (!priv->adapter->hw_regs_buf) { + priv->adapter->hw_regs = NULL; + BTMTK_ERR("Unable to allocate buffer for hw_regs."); + } else { + priv->adapter->hw_regs = + (u8 *)ALIGN_ADDR(priv->adapter->hw_regs_buf, + BTSDIO_DMA_ALIGN); + BTMTK_DBG("hw_regs_buf=%p hw_regs=%p", + priv->adapter->hw_regs_buf, priv->adapter->hw_regs); + } +} + +static void btmtk_free_adapter(struct btmtk_private *priv) +{ + kfree(priv->adapter->hw_regs_buf); +} + +/* + * This function handles the event generated by firmware, rx data + * received from firmware, and tx data sent from kernel. + */ + +static int btmtk_service_main_thread(void *data) +{ + struct btmtk_thread *thread = data; + struct btmtk_private *priv = thread->priv; + struct btmtk_adapter *adapter = NULL; + struct btmtk_sdio_card *card = NULL; +#if (KERNEL_VERSION(4, 14, 0) > LINUX_VERSION_CODE) + wait_queue_t wait; +#else + struct wait_queue_entry wait; +#endif + struct sk_buff *skb; + int ret = 0; + int i = 0; + ulong flags; + struct sched_param param = { .sched_priority = 90 };/*RR 90 is the same as audio*/ + int reset_flag = 0; + + sched_setscheduler(current, SCHED_RR, ¶m); + + BTMTK_INFO("main_thread begin 50"); + /* mdelay(50); */ + + for (i = 0; i <= 1000; i++) { + if (kthread_should_stop()) { + BTMTK_INFO("main_thread: break from main thread for probe_ready"); + break; + } + + if (probe_ready) + break; + + BTMTK_INFO("probe_ready %d delay 10ms~15ms", probe_ready); + usleep_range(10*1000, 15*1000); + + if (i == 1000) { + BTMTK_WARN("probe_ready %d i = %d try too many times return", + probe_ready, i); + return 0; + } + } + + if (priv->adapter) + adapter = priv->adapter; + else { + BTMTK_ERR("priv->adapter is NULL return"); + return 0; + } + + if (priv->btmtk_dev.card) + card = priv->btmtk_dev.card; + else { + BTMTK_ERR("priv->btmtk_dev.card is NULL return"); + return 0; + } + + thread->thread_status = 1; + init_waitqueue_entry(&wait, current); + for (;;) { + add_wait_queue(&thread->wait_q, &wait); + set_current_state(TASK_INTERRUPTIBLE); + if (kthread_should_stop()) { + BTMTK_WARN("main_thread: break from main thread"); + break; + } + + if ((((!adapter->int_count) && + (!priv->btmtk_dev.tx_dnld_rdy || + skb_queue_empty(&card->tx_queue)))) && + (!priv->btmtk_dev.reset_dongle)) { + BTMTK_DBG("main_thread is sleeping..."); + schedule(); + } + + set_current_state(TASK_RUNNING); + + remove_wait_queue(&thread->wait_q, &wait); + + if (kthread_should_stop()) { + BTMTK_WARN("break after wake up"); + break; + } + + if (priv->btmtk_dev.reset_dongle) { + ret = priv->hw_sdio_reset_dongle(); + if (is_mt7663(card)) { + if (ret) { + BTMTK_ERR(L0_RESET_TAG "hw reset dongle error <%d>", ret); + } else { + BTMTK_INFO(L0_RESET_TAG "hw reset dongle done"); + reset_flag = 1; + break; + } + } else { + if (ret) { + BTMTK_ERR("btmtk_sdio_reset_dongle return %d, error", ret); + break; + } else { + BTMTK_INFO("hw reset dongle done"); + break; + } + } + } + + if (priv->btmtk_dev.reset_progress) + continue; + + ret = priv->hw_set_own_back(DRIVER_OWN); + if (ret) { + BTMTK_ERR("set driver own return fail"); + priv->start_reset_dongle_progress(); + continue; + } + + spin_lock_irqsave(&priv->driver_lock, flags); + if (adapter->int_count) { + BTMTK_DBG("go int"); + adapter->int_count = 0; + spin_unlock_irqrestore(&priv->driver_lock, flags); + if (priv->hw_process_int_status(priv)) { + priv->start_reset_dongle_progress(); + continue; + } + } else { + BTMTK_DBG("go tx"); + spin_unlock_irqrestore(&priv->driver_lock, flags); + } + + if (!priv->btmtk_dev.tx_dnld_rdy) { + BTMTK_DBG("tx_dnld_rdy == 0, continue"); + continue; + } + + spin_lock_irqsave(&priv->driver_lock, flags); + skb = skb_dequeue(&card->tx_queue); + spin_unlock_irqrestore(&priv->driver_lock, flags); + + if (skb) { + if (skb->len < 16) + btmtk_print_buffer_conent(skb->data, skb->len); + else + btmtk_print_buffer_conent(skb->data, 16); + + ret = btmtk_tx_pkt(priv, skb); + if (ret && (ret != (-EINVAL))) { + BTMTK_ERR("tx pkt return fail %d", ret); + priv->start_reset_dongle_progress(); + continue; + } + + BTMTK_DBG("after btmtk_tx_pkt kfree_skb"); + kfree_skb(skb); + } + + if (skb_queue_empty(&card->tx_queue)) { + ret = priv->hw_set_own_back(FW_OWN); + if (ret) { + BTMTK_ERR("set fw own return fail"); + priv->start_reset_dongle_progress(); + continue; + } + } + } + BTMTK_WARN("end"); + thread->thread_status = 0; + + if (is_mt7663(card) && reset_flag == 1) + btmtk_remove_card(priv); + + return 0; +} + +struct btmtk_private *btmtk_add_card(void *data) +{ + struct btmtk_sdio_card *card = (struct btmtk_sdio_card *)data; + struct btmtk_private *priv; + + BTMTK_INFO("begin"); + + priv = card->priv; + + btmtk_init_adapter(priv); + + BTMTK_INFO("Starting kthread..."); + priv->main_thread.priv = priv; + spin_lock_init(&priv->driver_lock); + + init_waitqueue_head(&priv->main_thread.wait_q); + priv->main_thread.task = kthread_run(btmtk_service_main_thread, + &priv->main_thread, "btmtk_main_service"); + if (IS_ERR(priv->main_thread.task)) + goto err_thread; + + priv->btmtk_dev.card = card; + priv->btmtk_dev.tx_dnld_rdy = true; + + return priv; + +err_thread: + return NULL; +} +EXPORT_SYMBOL_GPL(btmtk_add_card); + +int btmtk_remove_card(struct btmtk_private *priv) +{ + BTMTK_INFO("begin, stop main_thread"); + if (!IS_ERR(priv->main_thread.task) && (priv->main_thread.thread_status)) { + kthread_stop(priv->main_thread.task); + wake_up_interruptible(&priv->main_thread.wait_q); + BTMTK_INFO("wake_up_interruptible main_thread done"); + } + BTMTK_INFO("stop main_thread done"); +#ifdef CONFIG_DEBUG_FS + /*btmtk_debugfs_remove(hdev);*/ +#endif + + btmtk_free_adapter(priv); + + return 0; +} +EXPORT_SYMBOL_GPL(btmtk_remove_card); + +MODULE_AUTHOR("Mediatek Ltd."); +MODULE_DESCRIPTION("Mediatek Bluetooth driver ver " VERSION); +MODULE_VERSION(VERSION); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/btmtk_sdio.c b/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/btmtk_sdio.c new file mode 100644 index 0000000000000..8f4b85a409666 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/btmtk_sdio.c @@ -0,0 +1,7583 @@ +/* + * Copyright (c) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include "btmtk_config.h" +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Define for proce node */ +#include +#include + +#include "btmtk_define.h" +#include "btmtk_drv.h" +#include "btmtk_sdio.h" + +/* Used for WoBLE on EINT */ +#include +#include +#include +#include + +#include +#include + +typedef int (*sdio_card_probe)(struct sdio_func *func, + const struct sdio_device_id *id); + +static struct bt_stereo_clk stereo_clk; +static u64 sys_clk_tmp; +static unsigned int stereo_irq; +struct _OSAL_UNSLEEPABLE_LOCK_ stereo_spin_lock; + +static dev_t g_devIDfwlog; +static struct class *pBTClass; +static struct device *pBTDev; +struct device *pBTDevfwlog; +static wait_queue_head_t inq; +static wait_queue_head_t fw_log_inq; +static struct fasync_struct *fasync; +/*static int btmtk_woble_state = BTMTK_WOBLE_STATE_UNKNOWN;*/ + +static int need_reset_stack; +static int get_hci_reset; +static int need_reopen; +static int wlan_remove_done; + +static u8 user_rmmod; +static int need_retry_load_woble; + +struct completion g_done; +unsigned char probe_counter; +struct btmtk_private *g_priv; +#define STR_COREDUMP_END "coredump end\n\n" +const u8 READ_ADDRESS_EVENT[] = { 0x0e, 0x0a, 0x01, 0x09, 0x10, 0x00 }; + +static struct ring_buffer metabuffer; +static struct ring_buffer fwlog_metabuffer; + +u8 probe_ready; +/* record firmware version */ +static char fw_version_str[FW_VERSION_BUF_SIZE]; +static struct proc_dir_entry *g_proc_dir; + +static int btmtk_fops_state = BTMTK_FOPS_STATE_UNKNOWN; +static DEFINE_MUTEX(btmtk_fops_state_mutex); +#define FOPS_MUTEX_LOCK() mutex_lock(&btmtk_fops_state_mutex) +#define FOPS_MUTEX_UNLOCK() mutex_unlock(&btmtk_fops_state_mutex) + +/** read_write for proc */ +static int btmtk_proc_show(struct seq_file *m, void *v); +static int btmtk_proc_open(struct inode *inode, struct file *file); +static void btmtk_proc_create_new_entry(void); +static int btmtk_sdio_trigger_fw_assert(void); + +static int btmtk_sdio_RegisterBTIrq(struct btmtk_sdio_card *data); +static int btmtk_sdio_woble_input_init(struct btmtk_sdio_card *data); +static void btmtk_sdio_woble_input_deinit(struct btmtk_sdio_card *data); +/* bluetooth KPI feautre, bperf */ +u8 btmtk_bluetooth_kpi; +u8 btmtk_log_lvl = BTMTK_LOG_LEVEL_DEFAULT; + +static char event_need_compare[EVENT_COMPARE_SIZE] = {0}; +static char event_need_compare_len; +static char event_compare_status; +/*add special header in the beginning of even, stack won't recognize these event*/ + +/* timer for coredump end */ +struct task_struct *wait_dump_complete_tsk; +struct task_struct *wait_wlan_remove_tsk; +int wlan_status = WLAN_STATUS_DEFAULT; + +static int dump_data_counter; +static int dump_data_length; +static struct file *fw_dump_file; + +const struct file_operations BT_proc_fops = { + .open = btmtk_proc_open, + .read = seq_read, + .release = single_release, +}; + +static const struct btmtk_sdio_card_reg btmtk_reg_6630 = { + .cfg = 0x03, + .host_int_mask = 0x04, + .host_intstatus = 0x05, + .card_status = 0x20, + .sq_read_base_addr_a0 = 0x10, + .sq_read_base_addr_a1 = 0x11, + .card_fw_status0 = 0x40, + .card_fw_status1 = 0x41, + .card_rx_len = 0x42, + .card_rx_unit = 0x43, + .io_port_0 = 0x00, + .io_port_1 = 0x01, + .io_port_2 = 0x02, + .int_read_to_clear = false, + .func_num = 2, + .chip_id = 0x6630, +}; + +static const struct btmtk_sdio_card_reg btmtk_reg_6632 = { + .cfg = 0x03, + .host_int_mask = 0x04, + .host_intstatus = 0x05, + .card_status = 0x20, + .sq_read_base_addr_a0 = 0x10, + .sq_read_base_addr_a1 = 0x11, + .card_fw_status0 = 0x40, + .card_fw_status1 = 0x41, + .card_rx_len = 0x42, + .card_rx_unit = 0x43, + .io_port_0 = 0x00, + .io_port_1 = 0x01, + .io_port_2 = 0x02, + .int_read_to_clear = false, + .func_num = 2, + .chip_id = 0x6632, +}; + +static const struct btmtk_sdio_card_reg btmtk_reg_7668 = { + .cfg = 0x03, + .host_int_mask = 0x04, + .host_intstatus = 0x05, + .card_status = 0x20, + .sq_read_base_addr_a0 = 0x10, + .sq_read_base_addr_a1 = 0x11, + .card_fw_status0 = 0x40, + .card_fw_status1 = 0x41, + .card_rx_len = 0x42, + .card_rx_unit = 0x43, + .io_port_0 = 0x00, + .io_port_1 = 0x01, + .io_port_2 = 0x02, + .int_read_to_clear = false, + .func_num = 2, + .chip_id = 0x7668, +}; + +static const struct btmtk_sdio_card_reg btmtk_reg_7663 = { + .cfg = 0x03, + .host_int_mask = 0x04, + .host_intstatus = 0x05, + .card_status = 0x20, + .sq_read_base_addr_a0 = 0x10, + .sq_read_base_addr_a1 = 0x11, + .card_fw_status0 = 0x40, + .card_fw_status1 = 0x41, + .card_rx_len = 0x42, + .card_rx_unit = 0x43, + .io_port_0 = 0x00, + .io_port_1 = 0x01, + .io_port_2 = 0x02, + .int_read_to_clear = false, + .func_num = 2, + .chip_id = 0x7663, +}; + +static const struct btmtk_sdio_card_reg btmtk_reg_7666 = { + .cfg = 0x03, + .host_int_mask = 0x04, + .host_intstatus = 0x05, + .card_status = 0x20, + .sq_read_base_addr_a0 = 0x10, + .sq_read_base_addr_a1 = 0x11, + .card_fw_status0 = 0x40, + .card_fw_status1 = 0x41, + .card_rx_len = 0x42, + .card_rx_unit = 0x43, + .io_port_0 = 0x00, + .io_port_1 = 0x01, + .io_port_2 = 0x02, + .int_read_to_clear = false, + .func_num = 2, + .chip_id = 0x7666, +}; + +static const struct btmtk_sdio_device btmtk_sdio_6630 = { + .helper = "mtmk/sd8688_helper.bin", + .reg = &btmtk_reg_6630, + .support_pscan_win_report = false, + .sd_blksz_fw_dl = 64, + .supports_fw_dump = false, +}; + +static const struct btmtk_sdio_device btmtk_sdio_6632 = { + .helper = "mtmk/sd8688_helper.bin", + .reg = &btmtk_reg_6632, + .support_pscan_win_report = false, + .sd_blksz_fw_dl = 64, + .supports_fw_dump = false, +}; + +static const struct btmtk_sdio_device btmtk_sdio_7668 = { + .helper = "mtmk/sd8688_helper.bin", + .reg = &btmtk_reg_7668, + .support_pscan_win_report = false, + .sd_blksz_fw_dl = 64, + .supports_fw_dump = false, +}; + +static const struct btmtk_sdio_device btmtk_sdio_7663 = { + .helper = "mtmk/sd8688_helper.bin", + .reg = &btmtk_reg_7663, + .support_pscan_win_report = false, + .sd_blksz_fw_dl = 64, + .supports_fw_dump = false, +}; + +static const struct btmtk_sdio_device btmtk_sdio_7666 = { + .helper = "mtmk/sd8688_helper.bin", + .reg = &btmtk_reg_7666, + .support_pscan_win_report = false, + .sd_blksz_fw_dl = 64, + .supports_fw_dump = false, +}; + +typedef int (*sdio_reset_func) (struct mmc_card *card); +static sdio_reset_func pf_sdio_reset; + +static u8 hci_cmd_snoop_buf[HCI_SNOOP_ENTRY_NUM][HCI_SNOOP_BUF_SIZE]; +static u8 hci_cmd_snoop_len[HCI_SNOOP_ENTRY_NUM]; +static unsigned int hci_cmd_snoop_timestamp[HCI_SNOOP_ENTRY_NUM]; + +static u8 hci_event_snoop_buf[HCI_SNOOP_ENTRY_NUM][HCI_SNOOP_BUF_SIZE]; +static u8 hci_event_snoop_len[HCI_SNOOP_ENTRY_NUM]; +static unsigned int hci_event_snoop_timestamp[HCI_SNOOP_ENTRY_NUM]; + +static u8 hci_acl_snoop_buf[HCI_SNOOP_ENTRY_NUM][HCI_SNOOP_BUF_SIZE]; +static u8 hci_acl_snoop_len[HCI_SNOOP_ENTRY_NUM]; +static unsigned int hci_acl_snoop_timestamp[HCI_SNOOP_ENTRY_NUM]; + +static u8 fw_log_snoop_buf[HCI_SNOOP_ENTRY_NUM][HCI_SNOOP_BUF_SIZE]; +static u8 fw_log_snoop_len[HCI_SNOOP_ENTRY_NUM]; +static unsigned int fw_log_snoop_timestamp[HCI_SNOOP_ENTRY_NUM]; + +static int hci_cmd_snoop_index; +static int hci_event_snoop_index; +static int hci_acl_snoop_index; +static int fw_log_snoop_index; + +unsigned char *txbuf; +static unsigned char *rxbuf; +static unsigned char *userbuf; +static unsigned char *userbuf_fwlog; +static u32 rx_length; +static struct btmtk_sdio_card *g_card; + +static u32 reg_CHISR; /* Add for debug, need remove later */ + +#define SDIO_VENDOR_ID_MEDIATEK 0x037A + +static const struct sdio_device_id btmtk_sdio_ids[] = { + /* Mediatek SD8688 Bluetooth device */ + { SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, 0x6630), + .driver_data = (unsigned long) &btmtk_sdio_6630 }, + + { SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, 0x6632), + .driver_data = (unsigned long) &btmtk_sdio_6632 }, + + { SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, 0x7668), + .driver_data = (unsigned long) &btmtk_sdio_7668 }, + + { SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, 0x7663), + .driver_data = (unsigned long) &btmtk_sdio_7663 }, + + { SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, 0x7666), + .driver_data = (unsigned long) &btmtk_sdio_7666 }, + + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(sdio, btmtk_sdio_ids); + +static int btmtk_clean_queue(void); +static void btmtk_sdio_do_reset_or_wait_wlan_remove_done(void); +static int btmtk_sdio_download_partial_rom_patch(u8 *fwbuf, int firmwarelen); +static int btmtk_sdio_probe(struct sdio_func *func, + const struct sdio_device_id *id); +static void btmtk_sdio_L0_hook_new_probe(sdio_card_probe pFn_Probe); +static int btmtk_sdio_set_sleep(void); +static int btmtk_sdio_set_audio(void); +static int btmtk_sdio_send_hci_cmd(u8 cmd_type, u8 *cmd, int cmd_len, + const u8 *event, const int event_len, + int total_timeout); + +static int timestamp_threshold[BTMTK_SDIO_RX_CHECKPOINT_NUM]; +static unsigned int timestamp[BTMTK_SDIO_RX_CHECKPOINT_NUM][BTMTK_SDIO_TIMESTAMP_NUM]; + +static inline unsigned long btmtk_kallsyms_lookup_name(const char *name) +{ + unsigned long ret = 0; + + ret = kallsyms_lookup_name(name); + if (ret) { +#ifdef CONFIG_ARM +#ifdef CONFIG_THUMB2_KERNEL + /* set bit 0 in address for thumb mode */ + ret |= 1; +#endif +#endif + } + return ret; +} + +static unsigned int btmtk_sdio_get_microseconds(void) +{ + struct timeval now; + + do_gettimeofday(&now); + return now.tv_sec * 1000000 + now.tv_usec; +} + +void btmtk_sdio_timestamp(enum BTMTK_SDIO_RX_CHECKPOINT type) +{ + static int now; + static unsigned int ms_intr_now, ms_intr_last; + unsigned int ms_now; + unsigned int sum, max, min, avg; + int total, checkpoint_index, timestamp_index; + int threshold_zero[BTMTK_SDIO_RX_CHECKPOINT_NUM]; + + memset(threshold_zero, 0, sizeof(threshold_zero)); + if (memcmp(timestamp_threshold, threshold_zero, sizeof(timestamp_threshold)) == 0) + return; + + if (type == BTMTK_SDIO_RX_CHECKPOINT_INTR) + now++; + if (now == BTMTK_SDIO_TIMESTAMP_NUM) + now = 0; + + ms_now = btmtk_sdio_get_microseconds(); + + if (type == BTMTK_SDIO_RX_CHECKPOINT_INTR) { + if (ms_intr_last == 0) + timestamp[type][now] = 0; + else + timestamp[type][now] = ms_now - ms_intr_last; + ms_intr_last = ms_now; + ms_intr_now = ms_now; + } else { + timestamp[type][now] = ms_now - ms_intr_now; + } + + /* show statistics */ + if (timestamp_threshold[type] != 0 && timestamp[type][now] > timestamp_threshold[type]) { + BTMTK_INFO("---------------------START---------------------"); + BTMTK_INFO("Type(%d), Cur = %u", type, timestamp[type][now]); + for (checkpoint_index = 0; checkpoint_index < BTMTK_SDIO_RX_CHECKPOINT_NUM; checkpoint_index++) { + sum = 0; + total = 0; + max = 0; + min = 0xFFFFFFFF; + avg = 0; + for (timestamp_index = 0; timestamp_index < BTMTK_SDIO_TIMESTAMP_NUM; timestamp_index++) { + if (timestamp[checkpoint_index][timestamp_index] != 0) { + sum += timestamp[checkpoint_index][timestamp_index]; + total++; + if (timestamp[checkpoint_index][timestamp_index] > max) + max = timestamp[checkpoint_index][timestamp_index]; + if (timestamp[checkpoint_index][timestamp_index] < min) + min = timestamp[checkpoint_index][timestamp_index]; + } + } + avg = sum/total; + BTMTK_INFO("Type(%d), Max = %u, Min = %u, Avg = %u", + checkpoint_index, max, min, avg); + } + BTMTK_INFO("----------------------END----------------------"); + } +} + +static int btmtk_fops_get_state(void) +{ + return btmtk_fops_state; +} + +static void btmtk_fops_set_state(int new_state) +{ + static const char * const fstate_msg[BTMTK_FOPS_STATE_MAX] = {"UNKNOWN", "INIT", "OPENING", "OPENED", "CLOSING", "CLOSED"}; + + BTMTK_INFO("%s: FOPS_%s(%d) -> FOPS_%s(%d)", __func__, fstate_msg[btmtk_fops_state], + btmtk_fops_state, fstate_msg[new_state], new_state); + btmtk_fops_state = new_state; +} + +void btmtk_sdio_stop_wait_wlan_remove_tsk(void) +{ + if (wait_wlan_remove_tsk == NULL) + BTMTK_INFO("wait_wlan_remove_tsk is NULL"); + else if (IS_ERR(wait_wlan_remove_tsk)) + BTMTK_INFO("wait_wlan_remove_tsk is error"); + else { + BTMTK_INFO("call kthread_stop wait_wlan_remove_tsk"); + kthread_stop(wait_wlan_remove_tsk); + wait_wlan_remove_tsk = NULL; + } +} + +int btmtk_sdio_notify_wlan_remove_start(void) +{ + /* notify_wlan_remove_start */ + int ret = 0; + typedef void (*pnotify_wlan_remove_start) (int reserved); + char *notify_wlan_remove_start_func_name; + pnotify_wlan_remove_start pnotify_wlan_remove_start_func; + + BTMTK_INFO("wlan_status %d", wlan_status); + if (wlan_status == WLAN_STATUS_CALL_REMOVE_START) { + /* do notify before, just return */ + return ret; + } + + if (is_mt7663(g_card)) + notify_wlan_remove_start_func_name = + "BT_rst_L0_notify_WF_step1"; + else + notify_wlan_remove_start_func_name = + "notify_wlan_remove_start"; + + pnotify_wlan_remove_start_func = + (pnotify_wlan_remove_start)btmtk_kallsyms_lookup_name + (notify_wlan_remove_start_func_name); + + BTMTK_INFO(L0_RESET_TAG); + /* void notify_wlan_remove_start(void) */ + if (pnotify_wlan_remove_start_func) { + BTMTK_INFO("do notify %s", notify_wlan_remove_start_func_name); + wlan_remove_done = 0; + if (is_mt7663(g_card)) + pnotify_wlan_remove_start_func(0); + else + pnotify_wlan_remove_start_func(1); + wlan_status = WLAN_STATUS_CALL_REMOVE_START; + } else { + ret = -1; + BTMTK_ERR("do not get %s", notify_wlan_remove_start_func_name); + wlan_status = WLAN_STATUS_IS_NOT_LOAD; + wlan_remove_done = 1; + } + return ret; +} + +/*============================================================================*/ +/* Interface Functions : timer for coredump inform wifi */ +/*============================================================================*/ +static void btmtk_sdio_wakeup_mainthread_do_reset(void) +{ + if (g_priv) { + g_priv->btmtk_dev.reset_dongle = 1; + BTMTK_INFO("set reset_dongle %d", g_priv->btmtk_dev.reset_dongle); + wake_up_interruptible(&g_priv->main_thread.wait_q); + } else + BTMTK_ERR("g_priv is NULL"); +} + +static int btmtk_sdio_wait_wlan_remove_thread(void *ptr) +{ + int i = 0; + + BTMTK_INFO("begin"); + if (g_priv == NULL) { + BTMTK_ERR("g_priv is NULL, return"); + return 0; + } + + g_priv->btmtk_dev.reset_progress = 1; + for (i = 0; i < 30; i++) { + if ((wait_wlan_remove_tsk && kthread_should_stop()) || wlan_remove_done) { + BTMTK_WARN("break wlan_remove_done %d", wlan_remove_done); + break; + } + msleep(500); + } + + btmtk_sdio_wakeup_mainthread_do_reset(); + + while (!kthread_should_stop()) { + BTMTK_INFO("no one call stop"); + msleep(500); + } + + BTMTK_INFO("end"); + return 0; +} + +static void btmtk_sdio_start_reset_dongle_progress(void) +{ + if (!g_card->bt_cfg.support_dongle_reset) { + BTMTK_WARN("debug mode do not do reset"); + } else { + BTMTK_WARN("user mode do reset"); + btmtk_sdio_notify_wlan_remove_start(); + btmtk_sdio_do_reset_or_wait_wlan_remove_done(); + } +} + +/*============================================================================*/ +/* Interface Functions : timer for uncomplete coredump */ +/*============================================================================*/ +static void btmtk_sdio_do_reset_or_wait_wlan_remove_done(void) +{ + BTMTK_INFO("wlan_remove_done %d", wlan_remove_done); + if (wlan_remove_done || (wlan_status == WLAN_STATUS_IS_NOT_LOAD)) + /* wifi inform bt already, reset chip */ + btmtk_sdio_wakeup_mainthread_do_reset(); + else { + /* makesure wait thread is stopped */ + btmtk_sdio_stop_wait_wlan_remove_tsk(); + /* create thread wait wifi inform bt */ + BTMTK_INFO("create btmtk_sdio_wait_wlan_remove_thread"); + wait_wlan_remove_tsk = kthread_run( + btmtk_sdio_wait_wlan_remove_thread, NULL, + "btmtk_sdio_wait_wlan_remove_thread"); + if (wait_wlan_remove_tsk == NULL) + BTMTK_ERR("btmtk_sdio_wait_wlan_remove_thread create fail"); + } +} + +static int btmtk_sdio_wait_dump_complete_thread(void *ptr) +{ + int i = 0; + + BTMTK_INFO("begin"); + for (i = 0; i < 60; i++) { + if (wait_dump_complete_tsk && kthread_should_stop()) { + BTMTK_WARN("thread is stopped, break"); + break; + } + msleep(500); + } + + if (!g_card->bt_cfg.support_dongle_reset) { + BTMTK_INFO("debug mode don't do reset"); + } else { + BTMTK_INFO("user mode call do reset"); + btmtk_sdio_do_reset_or_wait_wlan_remove_done(); + } + + if (i >= 60) + BTMTK_WARN("wait dump complete timeout"); + wait_dump_complete_tsk = NULL; + + BTMTK_INFO("end"); + return 0; +} + +static void btmtk_sdio_free_fw_cfg_struct(struct fw_cfg_struct *fw_cfg, int count) +{ + int i = 0; + + for (i = 0; i < count; i++) { + if (fw_cfg[i].content) { + BTMTK_INFO("kfree %d", i); + kfree(fw_cfg[i].content); + fw_cfg[i].content = NULL; + fw_cfg[i].length = 0; + } else + fw_cfg[i].length = 0; + } +} + +static void btmtk_sdio_free_bt_cfg(void) +{ + BTMTK_INFO("begin"); + if (g_card == NULL) { + BTMTK_ERR("g_card == NULL"); + return; + } + + btmtk_sdio_free_fw_cfg_struct(&g_card->bt_cfg.picus_filter, 1); + btmtk_sdio_free_fw_cfg_struct(g_card->bt_cfg.wmt_cmd, WMT_CMD_COUNT); + btmtk_sdio_free_fw_cfg_struct(g_card->bt_cfg.vendor_cmd, VENDOR_CMD_COUNT); + + kfree(g_card->bt_cfg.sys_log_file_name); + g_card->bt_cfg.sys_log_file_name = NULL; + + kfree(g_card->bt_cfg.fw_dump_file_name); + g_card->bt_cfg.fw_dump_file_name = NULL; + + kfree(g_card->bt_cfg_file_name); + g_card->bt_cfg_file_name = NULL; + + memset(&g_card->bt_cfg, 0, sizeof(g_card->bt_cfg)); + + BTMTK_INFO("end"); +} + +static void btmtk_sdio_woble_free_setting(void) +{ + BTMTK_INFO("begin"); + if (g_card == NULL) { + BTMTK_ERR("g_card == NULL"); + return; + } + + btmtk_sdio_free_fw_cfg_struct(g_card->woble_setting_apcf, WOBLE_SETTING_COUNT); + btmtk_sdio_free_fw_cfg_struct(g_card->woble_setting_apcf_fill_mac, WOBLE_SETTING_COUNT); + btmtk_sdio_free_fw_cfg_struct(g_card->woble_setting_apcf_fill_mac_location, WOBLE_SETTING_COUNT); + btmtk_sdio_free_fw_cfg_struct(g_card->woble_setting_radio_off, WOBLE_SETTING_COUNT); + btmtk_sdio_free_fw_cfg_struct(g_card->woble_setting_radio_off_status_event, WOBLE_SETTING_COUNT); + btmtk_sdio_free_fw_cfg_struct(g_card->woble_setting_radio_off_comp_event, WOBLE_SETTING_COUNT); + btmtk_sdio_free_fw_cfg_struct(g_card->woble_setting_radio_on, WOBLE_SETTING_COUNT); + btmtk_sdio_free_fw_cfg_struct(g_card->woble_setting_radio_on_status_event, WOBLE_SETTING_COUNT); + btmtk_sdio_free_fw_cfg_struct(g_card->woble_setting_radio_on_comp_event, WOBLE_SETTING_COUNT); + btmtk_sdio_free_fw_cfg_struct(g_card->woble_setting_apcf_resume, WOBLE_SETTING_COUNT); + btmtk_sdio_free_fw_cfg_struct(g_card->woble_setting_apcf_resume_event, WOBLE_SETTING_COUNT); + + kfree(g_card->woble_setting_file_name); + g_card->woble_setting_file_name = NULL; + + if (g_card->bt_cfg.support_woble_by_eint) { + if (g_card->wobt_irq != 0 && atomic_read(&(g_card->irq_enable_count)) == 1) { + BTMTK_INFO("disable BT IRQ:%d", g_card->wobt_irq); + atomic_dec(&(g_card->irq_enable_count)); + disable_irq_nosync(g_card->wobt_irq); + } else + BTMTK_INFO("irq_enable count:%d", atomic_read(&(g_card->irq_enable_count))); + free_irq(g_card->wobt_irq, g_card); + } + + BTMTK_INFO("end"); +} + +static void btmtk_sdio_initialize_cfg_items(void) +{ + BTMTK_INFO("begin"); + if (g_card == NULL) { + BTMTK_ERR("g_card == NULL"); + return; + } + + g_card->bt_cfg.dongle_reset_gpio_pin = 0; + g_card->bt_cfg.save_fw_dump_in_kernel = 0; + g_card->bt_cfg.support_dongle_reset = 0; + g_card->bt_cfg.support_full_fw_dump = 1; + g_card->bt_cfg.support_legacy_woble = 0; + g_card->bt_cfg.support_unify_woble = 0; + g_card->bt_cfg.support_woble_by_eint = 0; + g_card->bt_cfg.support_woble_for_bt_disable = 0; + g_card->bt_cfg.support_woble_wakelock = 0; + g_card->bt_cfg.reset_stack_after_woble = 0; + g_card->bt_cfg.sys_log_file_name = NULL; + g_card->bt_cfg.fw_dump_file_name = NULL; + g_card->bt_cfg.support_auto_picus = 0; + btmtk_sdio_free_fw_cfg_struct(&g_card->bt_cfg.picus_filter, 1); + btmtk_sdio_free_fw_cfg_struct(g_card->bt_cfg.wmt_cmd, WMT_CMD_COUNT); + btmtk_sdio_free_fw_cfg_struct(g_card->bt_cfg.vendor_cmd, VENDOR_CMD_COUNT); + + BTMTK_INFO("end"); +} + +static bool btmtk_sdio_parse_bt_cfg_file(char *item_name, char *text, + char *searchcontent) +{ + bool ret = true; + int temp_len = 0; + char search[32]; + char *ptr = NULL, *p = NULL; + char *temp = text; + + if (text == NULL) { + BTMTK_ERR("text param is invalid!"); + ret = false; + goto out; + } + + memset(search, 0, sizeof(search)); + snprintf(search, sizeof(search), "%s", item_name); /* EX: SUPPORT_UNIFY_WOBLE */ + p = ptr = strstr(searchcontent, search); + + if (!ptr) { + BTMTK_ERR("Can't find %s", item_name); + ret = false; + goto out; + } + + if (p > searchcontent) { + p--; + while ((*p == ' ') && (p != searchcontent)) + p--; + if (*p == '#') { + BTMTK_ERR("It's invalid bt cfg item"); + ret = false; + goto out; + } + } + + p = ptr + strlen(item_name) + 1; + ptr = p; + + for (;;) { + switch (*p) { + case '\n': + goto textdone; + default: + *temp++ = *p++; + break; + } + } + +textdone: + temp_len = p - ptr; + *temp = '\0'; + +out: + return ret; +} + +static void btmtk_sdio_bt_cfg_item_value_to_bool(char *item_value, bool *value) +{ + unsigned long text_value = 0; + + if (item_value == NULL) { + BTMTK_ERR("item_value is NULL!"); + return; + } + + if (kstrtoul(item_value, 10, &text_value) == 0) { + if (text_value == 1) + *value = true; + else + *value = false; + } else { + BTMTK_WARN("kstrtoul failed!"); + } +} + +static int btmtk_sdio_load_fw_cfg_setting(char *block_name, struct fw_cfg_struct *save_content, + int save_content_count, u8 *searchconetnt, enum fw_cfg_index_len index_length) +{ + int ret = 0; + int i = 0; + long parsing_result = 0; + u8 *search_result = NULL; + u8 *search_end = NULL; + u8 search[32]; + u8 temp[260]; /* save for total hex number */ + u8 *next_number = NULL; + u8 *next_block = NULL; + u8 number[8]; + int temp_len; + + memset(search, 0, sizeof(search)); + memset(temp, 0, sizeof(temp)); + memset(number, 0, sizeof(number)); + + /* search block name */ + for (i = 0; i < save_content_count; i++) { + temp_len = 0; + if (index_length == FW_CFG_INX_LEN_2) /* EX: APCF01 */ + snprintf(search, sizeof(search), "%s%02d:", block_name, i); + else if (index_length == FW_CFG_INX_LEN_3) /* EX: APCF001 */ + snprintf(search, sizeof(search), "%s%03d:", block_name, i); + else + snprintf(search, sizeof(search), "%s:", block_name); + search_result = strstr(searchconetnt, search); + if (search_result) { + memset(temp, 0, sizeof(temp)); + temp_len = 0; + search_result += strlen(search); /* move to first number */ + + do { + next_number = NULL; + search_end = strstr(search_result, ","); + if ((search_end - search_result) <= 0) { + BTMTK_INFO("can not find search end, break"); + break; + } + + if ((search_end - search_result) > sizeof(number)) + break; + + memset(number, 0, sizeof(number)); + memcpy(number, search_result, search_end - search_result); + + if (number[0] == 0x20) /* space */ + ret = kstrtol(number + 1, 0, &parsing_result); + else + ret = kstrtol(number, 0, &parsing_result); + + if (ret == 0) { + if (temp_len >= sizeof(temp)) { + BTMTK_ERR("%s data over %zu", search, sizeof(temp)); + break; + } + temp[temp_len] = parsing_result; + temp_len++; + /* find next number */ + next_number = strstr(search_end, "0x"); + + /* find next block */ + next_block = strstr(search_end, ":"); + } else { + BTMTK_DBG("kstrtol ret = %d, search %s", ret, search); + break; + } + + if (next_number == NULL) { + BTMTK_DBG("not find next apcf number temp_len %d, break, search %s", + temp_len, search); + break; + } + + if ((next_number > next_block) && (next_block != 0)) { + BTMTK_DBG("find next apcf number is over to next block "); + BTMTK_DBG("temp_len %d, break, search %s", + temp_len, search); + break; + } + + search_result = search_end + 1; + } while (1); + } else + BTMTK_DBG("%s is not found", search); + + if (temp_len) { + BTMTK_INFO("%s found", search); + BTMTK_DBG("kzalloc i=%d temp_len=%d", i, temp_len); + save_content[i].content = kzalloc(temp_len, GFP_KERNEL); + memcpy(save_content[i].content, temp, temp_len); + save_content[i].length = temp_len; + BTMTK_DBG("x save_content[%d].length %d temp_len=%d", + i, save_content[i].length, temp_len); + } + + } + return ret; +} + +static bool btmtk_sdio_load_bt_cfg_item(struct bt_cfg_struct *bt_cfg_content, + char *searchcontent) +{ + bool ret = true; + char text[128]; /* save for search text */ + unsigned long text_value = 0; + + memset(text, 0, sizeof(text)); + ret = btmtk_sdio_parse_bt_cfg_file(BT_UNIFY_WOBLE, text, searchcontent); + if (ret) { + btmtk_sdio_bt_cfg_item_value_to_bool(text, &bt_cfg_content->support_unify_woble); + BTMTK_INFO("bt_cfg_content->support_unify_woble = %d", + bt_cfg_content->support_unify_woble); + } else { + BTMTK_WARN("search item %s is invalid!", BT_UNIFY_WOBLE); + } + + ret = btmtk_sdio_parse_bt_cfg_file(BT_LEGACY_WOBLE, text, searchcontent); + if (ret) { + btmtk_sdio_bt_cfg_item_value_to_bool(text, &bt_cfg_content->support_legacy_woble); + BTMTK_INFO("bt_cfg_content->support_legacy_woble = %d", + bt_cfg_content->support_legacy_woble); + } else { + BTMTK_WARN("search item %s is invalid!", BT_LEGACY_WOBLE); + } + + ret = btmtk_sdio_parse_bt_cfg_file(BT_WOBLE_BY_EINT, text, searchcontent); + if (ret) { + btmtk_sdio_bt_cfg_item_value_to_bool(text, &bt_cfg_content->support_woble_by_eint); + BTMTK_INFO("bt_cfg_content->support_woble_by_eint = %d", + bt_cfg_content->support_woble_by_eint); + } else { + BTMTK_WARN("search item %s is invalid!", BT_WOBLE_BY_EINT); + } + + ret = btmtk_sdio_parse_bt_cfg_file(BT_DONGLE_RESET_PIN, text, searchcontent); + if (ret) { + if (kstrtoul(text, 10, &text_value) == 0) + bt_cfg_content->dongle_reset_gpio_pin = text_value; + else + BTMTK_WARN("kstrtoul failed %s!", BT_DONGLE_RESET_PIN); + } else { + BTMTK_WARN("search item %s is invalid!", BT_DONGLE_RESET_PIN); + } + + BTMTK_INFO("bt_cfg_content->dongle_reset_gpio_pin = %d", + bt_cfg_content->dongle_reset_gpio_pin); + + ret = btmtk_sdio_parse_bt_cfg_file(BT_SAVE_FW_DUMP_IN_KERNEL, text, searchcontent); + if (ret) { + btmtk_sdio_bt_cfg_item_value_to_bool(text, &bt_cfg_content->save_fw_dump_in_kernel); + BTMTK_INFO("bt_cfg_content->save_fw_dump_in_kernel = %d", + bt_cfg_content->save_fw_dump_in_kernel); + } else { + BTMTK_WARN("search item %s is invalid!", BT_SAVE_FW_DUMP_IN_KERNEL); + } + + ret = btmtk_sdio_parse_bt_cfg_file(BT_RESET_DONGLE, text, searchcontent); + if (ret) { + btmtk_sdio_bt_cfg_item_value_to_bool(text, &bt_cfg_content->support_dongle_reset); + BTMTK_INFO("bt_cfg_content->support_dongle_reset = %d", + bt_cfg_content->support_dongle_reset); + } else { + BTMTK_WARN("search item %s is invalid!", BT_RESET_DONGLE); + } + + ret = btmtk_sdio_parse_bt_cfg_file(BT_FULL_FW_DUMP, text, searchcontent); + if (ret) { + btmtk_sdio_bt_cfg_item_value_to_bool(text, &bt_cfg_content->support_full_fw_dump); + BTMTK_INFO("bt_cfg_content->support_full_fw_dump = %d", + bt_cfg_content->support_full_fw_dump); + } else { + BTMTK_WARN("search item %s is invalid!", BT_FULL_FW_DUMP); + } + + ret = btmtk_sdio_parse_bt_cfg_file(BT_WOBLE_WAKELOCK, text, searchcontent); + if (ret) { + btmtk_sdio_bt_cfg_item_value_to_bool(text, &bt_cfg_content->support_woble_wakelock); + BTMTK_INFO("bt_cfg_content->support_woble_wakelock = %d", + bt_cfg_content->support_woble_wakelock); + } else { + BTMTK_WARN("search item %s is invalid!", BT_WOBLE_WAKELOCK); + } + + ret = btmtk_sdio_parse_bt_cfg_file(BT_WOBLE_FOR_BT_DISABLE, text, searchcontent); + if (ret) { + btmtk_sdio_bt_cfg_item_value_to_bool(text, &bt_cfg_content->support_woble_for_bt_disable); + BTMTK_INFO("bt_cfg_content->support_woble_for_bt_disable = %d", + bt_cfg_content->support_woble_for_bt_disable); + } else { + BTMTK_WARN("search item %s is invalid!", BT_WOBLE_FOR_BT_DISABLE); + } + + ret = btmtk_sdio_parse_bt_cfg_file(BT_RESET_STACK_AFTER_WOBLE, text, searchcontent); + if (ret) { + btmtk_sdio_bt_cfg_item_value_to_bool(text, &bt_cfg_content->reset_stack_after_woble); + BTMTK_INFO("%s: bt_cfg_content->reset_stack_after_woble = %d", __func__, + bt_cfg_content->reset_stack_after_woble); + } else { + BTMTK_WARN("%s: search item %s is invalid!", __func__, BT_RESET_STACK_AFTER_WOBLE); + } + + ret = btmtk_sdio_parse_bt_cfg_file(BT_SYS_LOG_FILE, text, searchcontent); + if (ret) { + if (bt_cfg_content->sys_log_file_name != NULL) { + kfree(bt_cfg_content->sys_log_file_name); + bt_cfg_content->sys_log_file_name = NULL; + } + bt_cfg_content->sys_log_file_name = kzalloc(strlen(text) + 1, GFP_KERNEL); + if (bt_cfg_content->sys_log_file_name == NULL) { + ret = false; + return ret; + } + memcpy(bt_cfg_content->sys_log_file_name, text, strlen(text)); + bt_cfg_content->sys_log_file_name[strlen(text)] = '\0'; + BTMTK_INFO("bt_cfg_content->sys_log_file_name = %s", + bt_cfg_content->sys_log_file_name); + } else { + BTMTK_WARN("search item %s is invalid!", BT_SYS_LOG_FILE); + } + + ret = btmtk_sdio_parse_bt_cfg_file(BT_FW_DUMP_FILE, text, searchcontent); + if (ret) { + if (bt_cfg_content->fw_dump_file_name != NULL) { + kfree(bt_cfg_content->fw_dump_file_name); + bt_cfg_content->fw_dump_file_name = NULL; + } + bt_cfg_content->fw_dump_file_name = kzalloc(strlen(text) + 1, GFP_KERNEL); + if (bt_cfg_content->fw_dump_file_name == NULL) { + ret = false; + return ret; + } + memcpy(bt_cfg_content->fw_dump_file_name, text, strlen(text)); + bt_cfg_content->fw_dump_file_name[strlen(text)] = '\0'; + BTMTK_INFO("bt_cfg_content->fw_dump_file_name = %s", + bt_cfg_content->fw_dump_file_name); + } else { + BTMTK_WARN("search item %s is invalid!", BT_FW_DUMP_FILE); + } + + ret = btmtk_sdio_parse_bt_cfg_file(BT_AUTO_PICUS, text, searchcontent); + if (ret) { + btmtk_sdio_bt_cfg_item_value_to_bool(text, &bt_cfg_content->support_auto_picus); + BTMTK_INFO("bt_cfg_content->support_auto_picus = %d", + bt_cfg_content->support_auto_picus); + if (bt_cfg_content->support_auto_picus == true) { + ret = btmtk_sdio_load_fw_cfg_setting(BT_AUTO_PICUS_FILTER, + &bt_cfg_content->picus_filter, 1, searchcontent, FW_CFG_INX_LEN_NONE); + if (ret) + BTMTK_WARN("search item %s is invalid!", BT_AUTO_PICUS_FILTER); + } + } else { + BTMTK_WARN("search item %s is invalid!", BT_AUTO_PICUS); + } + + ret = btmtk_sdio_load_fw_cfg_setting(BT_WMT_CMD, bt_cfg_content->wmt_cmd, + WMT_CMD_COUNT, searchcontent, FW_CFG_INX_LEN_3); + if (ret) + BTMTK_WARN("search item %s is invalid!", BT_WMT_CMD); + + ret = btmtk_sdio_load_fw_cfg_setting(BT_VENDOR_CMD, bt_cfg_content->vendor_cmd, + VENDOR_CMD_COUNT, searchcontent, FW_CFG_INX_LEN_3); + if (ret) + BTMTK_WARN("search item %s is invalid!", BT_VENDOR_CMD); + + /* release setting file memory */ + if (g_card) { + kfree(g_card->setting_file); + g_card->setting_file = NULL; + } + return ret; +} + +static void btmtk_sdio_load_woble_setting_callback(const struct firmware *fw_data, void *context) +{ + struct btmtk_sdio_card *card = (struct btmtk_sdio_card *)context; + int err = 0; + unsigned char *image = NULL; + + if (!fw_data) { + BTMTK_ERR("fw_data is NULL callback request_firmware fail or can't find file!!"); + + /* Request original woble_setting.bin */ + memcpy(g_card->woble_setting_file_name, + WOBLE_SETTING_FILE_NAME, + sizeof(WOBLE_SETTING_FILE_NAME)); + BTMTK_INFO("begin load orignial woble_setting_file_name = %s", + g_card->woble_setting_file_name); + if (need_retry_load_woble < BTMTK_LOAD_WOBLE_RETRY_COUNT) { + need_retry_load_woble++; + err = request_firmware_nowait(THIS_MODULE, true, g_card->woble_setting_file_name, + &g_card->func->dev, GFP_KERNEL, g_card, btmtk_sdio_load_woble_setting_callback); + if (err < 0) { + BTMTK_ERR("request %s file fail(%d)", + g_card->woble_setting_file_name, err); + } + } else { + BTMTK_ERR("request %s file fail(%d), need_load_origin_woble = %d", + g_card->woble_setting_file_name, err, need_retry_load_woble); + } + return; + } + + BTMTK_INFO("woble_setting callback request_firmware size %zu success", fw_data->size); + image = kzalloc(fw_data->size + 1, GFP_KERNEL); + if (image == NULL) { + BTMTK_ERR("kzalloc size %zu failed!!", fw_data->size); + goto LOAD_END; + } + + memcpy(image, fw_data->data, fw_data->size); + image[fw_data->size] = '\0'; + + err = btmtk_sdio_load_fw_cfg_setting("APCF", + card->woble_setting_apcf, WOBLE_SETTING_COUNT, image, FW_CFG_INX_LEN_2); + if (err) + goto LOAD_END; + + err = btmtk_sdio_load_fw_cfg_setting("APCF_ADD_MAC", + card->woble_setting_apcf_fill_mac, WOBLE_SETTING_COUNT, image, FW_CFG_INX_LEN_2); + if (err) + goto LOAD_END; + + err = btmtk_sdio_load_fw_cfg_setting("APCF_ADD_MAC_LOCATION", + card->woble_setting_apcf_fill_mac_location, WOBLE_SETTING_COUNT, image, FW_CFG_INX_LEN_2); + if (err) + goto LOAD_END; + + err = btmtk_sdio_load_fw_cfg_setting("RADIOOFF", + card->woble_setting_radio_off, WOBLE_SETTING_COUNT, image, FW_CFG_INX_LEN_2); + if (err) + goto LOAD_END; + + err = btmtk_sdio_load_fw_cfg_setting("RADIOOFF_STATUS_EVENT", + card->woble_setting_radio_off_status_event, WOBLE_SETTING_COUNT, image, FW_CFG_INX_LEN_2); + if (err) + goto LOAD_END; + + err = btmtk_sdio_load_fw_cfg_setting("RADIOOFF_COMPLETE_EVENT", + card->woble_setting_radio_off_comp_event, WOBLE_SETTING_COUNT, image, FW_CFG_INX_LEN_2); + if (err) + goto LOAD_END; + + err = btmtk_sdio_load_fw_cfg_setting("RADIOON", + card->woble_setting_radio_on, WOBLE_SETTING_COUNT, image, FW_CFG_INX_LEN_2); + if (err) + goto LOAD_END; + + err = btmtk_sdio_load_fw_cfg_setting("RADIOON_STATUS_EVENT", + card->woble_setting_radio_on_status_event, WOBLE_SETTING_COUNT, image, FW_CFG_INX_LEN_2); + if (err) + goto LOAD_END; + + err = btmtk_sdio_load_fw_cfg_setting("RADIOON_COMPLETE_EVENT", + card->woble_setting_radio_on_comp_event, WOBLE_SETTING_COUNT, image, FW_CFG_INX_LEN_2); + if (err) + goto LOAD_END; + + err = btmtk_sdio_load_fw_cfg_setting("APCF_RESMUE", + card->woble_setting_apcf_resume, WOBLE_SETTING_COUNT, image, FW_CFG_INX_LEN_2); + if (err) + goto LOAD_END; + + err = btmtk_sdio_load_fw_cfg_setting("APCF_COMPLETE_EVENT", + card->woble_setting_apcf_resume_event, WOBLE_SETTING_COUNT, image, FW_CFG_INX_LEN_2); + +LOAD_END: + if (image) { + kfree(image); + image = NULL; + } + release_firmware(fw_data); + if (err) + BTMTK_WARN("result fail"); + else + BTMTK_INFO("result success"); +} + +static int btmtk_sdio_load_code_from_setting_files(char *setting_file_name, + struct btmtk_sdio_card *data, u32 *code_len) +{ + int err = 0; + const struct firmware *fw_entry = NULL; + *code_len = 0; + + if (data == NULL || setting_file_name == NULL) { + BTMTK_ERR("invalid parameter!!"); + err = -1; + return err; + } + + err = request_firmware(&fw_entry, setting_file_name, &data->func->dev); + if (err != 0) { + BTMTK_ERR("request %s file fail(%d)", setting_file_name, err); + return err; + } + + if (data->setting_file != NULL) { + kfree(data->setting_file); + data->setting_file = NULL; + } + + if (fw_entry) { + /* alloc setting file memory */ + data->setting_file = kzalloc(fw_entry->size + 1, GFP_KERNEL); + BTMTK_INFO("setting file request_firmware size %zu success", fw_entry->size); + } else { + BTMTK_ERR("fw_entry is NULL request_firmware may fail!! error code = %d", err); + return err; + } + + if (data->setting_file == NULL) { + BTMTK_ERR("kzalloc size %zu failed!!", fw_entry->size); + release_firmware(fw_entry); + err = -1; + return err; + } + + memcpy(data->setting_file, fw_entry->data, fw_entry->size); + data->setting_file[fw_entry->size] = '\0'; + + *code_len = fw_entry->size; + release_firmware(fw_entry); + + BTMTK_INFO("cfg_file len (%d) assign done", *code_len); + return err; +} + +static int btmtk_sdio_load_setting_files(char *bin_name, struct device *dev, + struct btmtk_sdio_card *data) +{ + int err = 0; + char *ptr_name = NULL; + u32 code_len = 0; + + BTMTK_INFO("begin setting_file_name = %s", bin_name); + ptr_name = strstr(bin_name, "woble_setting"); + if (ptr_name) { + err = request_firmware_nowait(THIS_MODULE, true, bin_name, + &data->func->dev, GFP_KERNEL, data, btmtk_sdio_load_woble_setting_callback); + + if (err < 0) + BTMTK_ERR("request %s file fail(%d)", bin_name, err); + else + BTMTK_INFO("request %s file success(%d)", bin_name, err); + } else if (strcmp(bin_name, BT_CFG_NAME) == 0) { + err = btmtk_sdio_load_code_from_setting_files(bin_name, data, &code_len); + if (err != 0) { + BTMTK_ERR("btmtk_sdio_load_code_from_cfg_files failed!!"); + return err; + } + + if (btmtk_sdio_load_bt_cfg_item(&data->bt_cfg, data->setting_file)) { + BTMTK_ERR("btmtk_sdio_load_bt_cfg_item error!!"); + err = -1; + return err; + } + } else + BTMTK_WARN("bin_name is not defined"); + + return err; +} + +static inline void btmtk_sdio_woble_wake_lock(struct btmtk_sdio_card *data) +{ + if (!data->woble_ws) + return; + + if (data->bt_cfg.support_unify_woble && data->bt_cfg.support_woble_wakelock) { + BTMTK_INFO("wake lock"); + __pm_stay_awake(data->woble_ws); + } +} + +static inline void btmtk_sdio_woble_wake_unlock(struct btmtk_sdio_card *data) +{ + if (!data->woble_ws) + return; + + if (data->bt_cfg.support_unify_woble && data->bt_cfg.support_woble_wakelock) { + BTMTK_INFO("wake unlock"); + __pm_relax(data->woble_ws); + } +} + +u32 LOCK_UNSLEEPABLE_LOCK(struct _OSAL_UNSLEEPABLE_LOCK_ *pUSL) +{ + spin_lock_irqsave(&(pUSL->lock), pUSL->flag); + return 0; +} + +u32 UNLOCK_UNSLEEPABLE_LOCK(struct _OSAL_UNSLEEPABLE_LOCK_ *pUSL) +{ + spin_unlock_irqrestore(&(pUSL->lock), pUSL->flag); + return 0; +} + +static int btmtk_sdio_writesb(u32 offset, u8 *val, int len) +{ + u32 ret = 0; + u32 retry_count = 0; + + if (g_card->func == NULL) { + BTMTK_ERR("g_card->func is NULL"); + return -EIO; + } + + do { + sdio_claim_host(g_card->func); + ret = sdio_writesb(g_card->func, offset, val, len); + sdio_release_host(g_card->func); + retry_count++; + if (retry_count > BTMTK_SDIO_RETRY_COUNT) { + BTMTK_ERR("ret:%d", ret); + break; + } + } while (ret); + + return ret; +} + + +static int btmtk_sdio_readsb(u32 offset, u8 *val, int len) +{ + u32 ret = 0; + u32 retry_count = 0; + + if (g_card->func == NULL) { + BTMTK_ERR("g_card->func is NULL"); + return -EIO; + } + + do { + sdio_claim_host(g_card->func); + ret = sdio_readsb(g_card->func, val, offset, len); + sdio_release_host(g_card->func); + retry_count++; + if (retry_count > BTMTK_SDIO_RETRY_COUNT) { + BTMTK_ERR("ret:%d", ret); + break; + } + } while (ret); + + return ret; +} + +static int btmtk_sdio_writeb(u32 offset, u8 val) +{ + u32 ret = 0; + u32 retry_count = 0; + + if (g_card->func == NULL) { + BTMTK_ERR("g_card->func is NULL"); + return -EIO; + } + + do { + sdio_claim_host(g_card->func); + sdio_writeb(g_card->func, val, offset, &ret); + sdio_release_host(g_card->func); + retry_count++; + if (retry_count > BTMTK_SDIO_RETRY_COUNT) { + BTMTK_ERR("ret:%d", ret); + break; + } + } while (ret); + + return ret; +} + +static int btmtk_sdio_readb(u32 offset, u8 *val) +{ + u32 ret = 0; + u32 retry_count = 0; + + if (g_card->func == NULL) { + BTMTK_ERR("g_card->func is NULL"); + return -EIO; + } + + do { + sdio_claim_host(g_card->func); + *val = sdio_readb(g_card->func, offset, &ret); + sdio_release_host(g_card->func); + retry_count++; + if (retry_count > BTMTK_SDIO_RETRY_COUNT) { + BTMTK_ERR("ret:%d", ret); + break; + } + } while (ret); + + return ret; +} + +static int btmtk_sdio_writel(u32 offset, u32 val) +{ + u32 ret = 0; + u32 retry_count = 0; + + if (g_card->func == NULL) { + BTMTK_ERR("g_card->func is NULL"); + return -EIO; + } + + do { + sdio_claim_host(g_card->func); + sdio_writel(g_card->func, val, offset, &ret); + sdio_release_host(g_card->func); + retry_count++; + if (retry_count > BTMTK_SDIO_RETRY_COUNT) { + BTMTK_ERR("ret:%d", ret); + break; + } + } while (ret); + + return ret; +} + +static int btmtk_sdio_readl(u32 offset, u32 *val) +{ + u32 ret = 0; + u32 retry_count = 0; + + if (g_card->func == NULL) { + BTMTK_ERR("g_card->func is NULL"); + return -EIO; + } + + do { + sdio_claim_host(g_card->func); + *val = sdio_readl(g_card->func, offset, &ret); + sdio_release_host(g_card->func); + retry_count++; + if (retry_count > BTMTK_SDIO_RETRY_COUNT) { + BTMTK_ERR("ret:%d", ret); + break; + } + } while (ret); + + return ret; +} + +static void btmtk_sdio_print_debug_sr(void) +{ + u32 ret = 0; + u32 CCIR_Value = 0; + u32 CHLPCR_Value = 0; + u32 CSDIOCSR_Value = 0; + u32 CHISR_Value = 0; + u32 CHIER_Value = 0; + u32 CTFSR_Value = 0; + u32 CRPLR_Value = 0; + u32 SWPCDBGR_Value = 0; + unsigned char X0_Value = 0; + unsigned char F8_Value = 0; + unsigned char F9_Value = 0; + unsigned char FA_Value = 0; + unsigned char FB_Value = 0; + unsigned char FC_Value = 0; + unsigned char FD_Value = 0; + unsigned char FE_Value = 0; + unsigned char FF_Value = 0; + + ret = btmtk_sdio_readl(CCIR, &CCIR_Value); + ret = btmtk_sdio_readl(CHLPCR, &CHLPCR_Value); + ret = btmtk_sdio_readl(CSDIOCSR, &CSDIOCSR_Value); + ret = btmtk_sdio_readl(CHISR, &CHISR_Value); + ret = btmtk_sdio_readl(CHIER, &CHIER_Value); + ret = btmtk_sdio_readl(CTFSR, &CTFSR_Value); + ret = btmtk_sdio_readl(CRPLR, &CRPLR_Value); + ret = btmtk_sdio_readl(SWPCDBGR, &SWPCDBGR_Value); + sdio_claim_host(g_card->func); + X0_Value = sdio_f0_readb(g_card->func, 0x00, &ret); + F8_Value = sdio_f0_readb(g_card->func, 0xF8, &ret); + F9_Value = sdio_f0_readb(g_card->func, 0xF9, &ret); + FA_Value = sdio_f0_readb(g_card->func, 0xFA, &ret); + FB_Value = sdio_f0_readb(g_card->func, 0xFB, &ret); + FC_Value = sdio_f0_readb(g_card->func, 0xFC, &ret); + FD_Value = sdio_f0_readb(g_card->func, 0xFD, &ret); + FE_Value = sdio_f0_readb(g_card->func, 0xFE, &ret); + FF_Value = sdio_f0_readb(g_card->func, 0xFF, &ret); + sdio_release_host(g_card->func); + BTMTK_INFO("CCIR: 0x%x, CHLPCR: 0x%x, CSDIOCSR: 0x%x, CHISR: 0x%x", + CCIR_Value, CHLPCR_Value, CSDIOCSR_Value, CHISR_Value); + BTMTK_INFO("CHIER: 0x%x, CTFSR: 0x%x, CRPLR: 0x%x, SWPCDBGR: 0x%x", + CHIER_Value, CTFSR_Value, CRPLR_Value, SWPCDBGR_Value); + BTMTK_INFO("CCCR 00: 0x%x, F8: 0x%x, F9: 0x%x, FA: 0x%x, FB: 0x%x", + X0_Value, F8_Value, F9_Value, FA_Value, FB_Value); + BTMTK_INFO("FC: 0x%x, FD: 0x%x, FE: 0x%x, FE: 0x%x", + FC_Value, FD_Value, FE_Value, FF_Value); +} + + +static void btmtk_sdio_hci_snoop_save(u8 type, u8 *buf, u32 len) +{ + u32 copy_len = HCI_SNOOP_BUF_SIZE; + + if (buf == NULL || len == 0) + return; + + if (len < HCI_SNOOP_BUF_SIZE) + copy_len = len; + + switch (type) { + case HCI_COMMAND_PKT: + hci_cmd_snoop_len[hci_cmd_snoop_index] = copy_len & 0xff; + memset(hci_cmd_snoop_buf[hci_cmd_snoop_index], 0, HCI_SNOOP_BUF_SIZE); + memcpy(hci_cmd_snoop_buf[hci_cmd_snoop_index], buf, copy_len & 0xff); + hci_cmd_snoop_timestamp[hci_cmd_snoop_index] = btmtk_sdio_get_microseconds(); + + hci_cmd_snoop_index--; + if (hci_cmd_snoop_index < 0) + hci_cmd_snoop_index = HCI_SNOOP_ENTRY_NUM - 1; + break; + case HCI_ACLDATA_PKT: + hci_acl_snoop_len[hci_acl_snoop_index] = copy_len & 0xff; + memset(hci_acl_snoop_buf[hci_acl_snoop_index], 0, HCI_SNOOP_BUF_SIZE); + memcpy(hci_acl_snoop_buf[hci_acl_snoop_index], buf, copy_len & 0xff); + hci_acl_snoop_timestamp[hci_acl_snoop_index] = btmtk_sdio_get_microseconds(); + + hci_acl_snoop_index--; + if (hci_acl_snoop_index < 0) + hci_acl_snoop_index = HCI_SNOOP_ENTRY_NUM - 1; + break; + case HCI_EVENT_PKT: + if (buf[0] == 0x3E) /* Not save BLE Event */ + break; + hci_event_snoop_len[hci_event_snoop_index] = copy_len; + memset(hci_event_snoop_buf[hci_event_snoop_index], 0, + HCI_SNOOP_BUF_SIZE); + memcpy(hci_event_snoop_buf[hci_event_snoop_index], buf, copy_len); + hci_event_snoop_timestamp[hci_event_snoop_index] = btmtk_sdio_get_microseconds(); + + hci_event_snoop_index--; + if (hci_event_snoop_index < 0) + hci_event_snoop_index = HCI_SNOOP_ENTRY_NUM - 1; + break; + case FW_LOG_PKT: + fw_log_snoop_len[fw_log_snoop_index] = copy_len; + memset(fw_log_snoop_buf[fw_log_snoop_index], 0, + HCI_SNOOP_BUF_SIZE); + memcpy(fw_log_snoop_buf[fw_log_snoop_index], buf, copy_len); + fw_log_snoop_timestamp[fw_log_snoop_index] = btmtk_sdio_get_microseconds(); + + fw_log_snoop_index--; + if (fw_log_snoop_index < 0) + fw_log_snoop_index = HCI_SNOOP_ENTRY_NUM - 1; + break; + default: + BTSDIO_INFO_RAW(buf, len, + "type(%d):", type); + } +} + +static void btmtk_sdio_hci_snoop_print(void) +{ + int counter, index; + + BTMTK_INFO("HCI Command Dump"); + index = hci_cmd_snoop_index + 1; + if (index >= HCI_SNOOP_ENTRY_NUM) + index = 0; + for (counter = 0; counter < HCI_SNOOP_ENTRY_NUM; counter++) { + if (hci_cmd_snoop_len[index] != 0) + BTSDIO_INFO_RAW(hci_cmd_snoop_buf[index], hci_cmd_snoop_len[index], + " time(%u):", hci_cmd_snoop_timestamp[index]); + index++; + if (index >= HCI_SNOOP_ENTRY_NUM) + index = 0; + } + + BTMTK_INFO("HCI Event Dump"); + index = hci_event_snoop_index + 1; + if (index >= HCI_SNOOP_ENTRY_NUM) + index = 0; + for (counter = 0; counter < HCI_SNOOP_ENTRY_NUM; counter++) { + if (hci_event_snoop_len[index] != 0) + BTSDIO_INFO_RAW(hci_event_snoop_buf[index], hci_event_snoop_len[index], + " time(%u):", hci_event_snoop_timestamp[index]); + index++; + if (index >= HCI_SNOOP_ENTRY_NUM) + index = 0; + } + + BTMTK_INFO("HCI ACL Dump"); + index = hci_acl_snoop_index + 1; + if (index >= HCI_SNOOP_ENTRY_NUM) + index = 0; + for (counter = 0; counter < HCI_SNOOP_ENTRY_NUM; counter++) { + if (hci_acl_snoop_len[index] != 0) + BTSDIO_INFO_RAW(hci_acl_snoop_buf[index], hci_acl_snoop_len[index], + " time(%u):", hci_acl_snoop_timestamp[index]); + index++; + if (index >= HCI_SNOOP_ENTRY_NUM) + index = 0; + } + + BTMTK_INFO("FW LOG Dump"); + index = fw_log_snoop_index + 1; + if (index >= HCI_SNOOP_ENTRY_NUM) + index = 0; + for (counter = 0; counter < HCI_SNOOP_ENTRY_NUM; counter++) { + if (fw_log_snoop_len[index] != 0) + BTSDIO_INFO_RAW(fw_log_snoop_buf[index], fw_log_snoop_len[index], + " time(%u):", fw_log_snoop_timestamp[index]); + index++; + if (index >= HCI_SNOOP_ENTRY_NUM) + index = 0; + } +} + +static void btmtk_sdio_hci_snoop_init(void) +{ + hci_cmd_snoop_index = HCI_SNOOP_ENTRY_NUM - 1; + hci_event_snoop_index = HCI_SNOOP_ENTRY_NUM - 1; + hci_acl_snoop_index = HCI_SNOOP_ENTRY_NUM - 1; + fw_log_snoop_index = HCI_SNOOP_ENTRY_NUM - 1; + + memset(hci_cmd_snoop_buf, 0, HCI_SNOOP_ENTRY_NUM * HCI_SNOOP_BUF_SIZE * sizeof(u8)); + memset(hci_cmd_snoop_len, 0, HCI_SNOOP_ENTRY_NUM * sizeof(u8)); + memset(hci_cmd_snoop_timestamp, 0, HCI_SNOOP_ENTRY_NUM * sizeof(unsigned int)); + + memset(hci_event_snoop_buf, 0, HCI_SNOOP_ENTRY_NUM * HCI_SNOOP_BUF_SIZE * sizeof(u8)); + memset(hci_event_snoop_len, 0, HCI_SNOOP_ENTRY_NUM * sizeof(u8)); + memset(hci_event_snoop_timestamp, 0, HCI_SNOOP_ENTRY_NUM * sizeof(unsigned int)); + + memset(hci_acl_snoop_buf, 0, HCI_SNOOP_ENTRY_NUM * HCI_SNOOP_BUF_SIZE * sizeof(u8)); + memset(hci_acl_snoop_len, 0, HCI_SNOOP_ENTRY_NUM * sizeof(u8)); + memset(hci_acl_snoop_timestamp, 0, HCI_SNOOP_ENTRY_NUM * sizeof(unsigned int)); + + memset(fw_log_snoop_buf, 0, HCI_SNOOP_ENTRY_NUM * HCI_SNOOP_BUF_SIZE * sizeof(u8)); + memset(fw_log_snoop_len, 0, HCI_SNOOP_ENTRY_NUM * sizeof(u8)); + memset(fw_log_snoop_timestamp, 0, HCI_SNOOP_ENTRY_NUM * sizeof(unsigned int)); +} + +struct sk_buff *btmtk_create_send_data(struct sk_buff *skb) +{ + struct sk_buff *queue_skb = NULL; + u32 sdio_header_len = skb->len + BTM_HEADER_LEN; + + if (skb_headroom(skb) < (BTM_HEADER_LEN)) { + queue_skb = bt_skb_alloc(sdio_header_len, GFP_ATOMIC); + if (queue_skb == NULL) { + BTMTK_ERR("bt_skb_alloc fail return"); + return 0; + } + + queue_skb->data[0] = (sdio_header_len & 0x0000ff); + queue_skb->data[1] = (sdio_header_len & 0x00ff00) >> 8; + queue_skb->data[2] = 0; + queue_skb->data[3] = 0; + queue_skb->data[4] = bt_cb(skb)->pkt_type; + queue_skb->len = sdio_header_len; + memcpy(&queue_skb->data[5], &skb->data[0], skb->len); + kfree_skb(skb); + } else { + queue_skb = skb; + skb_push(queue_skb, BTM_HEADER_LEN); + queue_skb->data[0] = (sdio_header_len & 0x0000ff); + queue_skb->data[1] = (sdio_header_len & 0x00ff00) >> 8; + queue_skb->data[2] = 0; + queue_skb->data[3] = 0; + queue_skb->data[4] = bt_cb(skb)->pkt_type; + } + + BTMTK_INFO("end"); + return queue_skb; +} + +static void btmtk_sdio_set_no_fw_own(struct btmtk_private *priv, bool no_fw_own) +{ + if (priv) { + priv->no_fw_own = no_fw_own; + BTMTK_DBG("set no_fw_own %d", priv->no_fw_own); + } else + BTMTK_DBG("priv is NULL"); +} + +static int btmtk_sdio_set_own_back(int owntype) +{ + /*Set driver own*/ + int ret = 0, retry_ret = 0; + u32 u32LoopCount = 0; + u32 u32ReadCRValue = 0; + u32 ownValue = 0; + u32 set_checkretry = 30; + int i = 0; + + BTMTK_DBG("owntype %d", owntype); + + if (user_rmmod) + set_checkretry = 1; + + + if (owntype == FW_OWN && (g_priv)) { + if (g_priv->no_fw_own) { + ret = btmtk_sdio_readl(SWPCDBGR, &u32ReadCRValue); + BTMTK_DBG("no_fw_own is on, just return, u32ReadCRValue = 0x%08X, ret = %d", + u32ReadCRValue, ret); + return ret; + } + } + + ret = btmtk_sdio_readl(CHLPCR, &u32ReadCRValue); + + BTMTK_DBG("btmtk_sdio_readl CHLPCR done"); + if (owntype == DRIVER_OWN) { + if ((u32ReadCRValue&0x100) == 0x100) { + BTMTK_DBG("already driver own 0x%0x, return", u32ReadCRValue); + goto set_own_end; + } + } else if (owntype == FW_OWN) { + if ((u32ReadCRValue&0x100) == 0) { + BTMTK_DBG("already FW own 0x%0x, return", u32ReadCRValue); + goto set_own_end; + } + } + +setretry: + + if (owntype == DRIVER_OWN) + ownValue = 0x00000200; + else + ownValue = 0x00000100; + + BTMTK_DBG("write CHLPCR 0x%x", ownValue); + ret = btmtk_sdio_writel(CHLPCR, ownValue); + if (ret) { + ret = -EINVAL; + goto done; + } + BTMTK_DBG("write CHLPCR 0x%x done", ownValue); + + u32LoopCount = 1000; + + if (owntype == DRIVER_OWN) { + do { + usleep_range(100, 200); + ret = btmtk_sdio_readl(CHLPCR, &u32ReadCRValue); + u32LoopCount--; + BTMTK_DBG("DRIVER_OWN btmtk_sdio_readl CHLPCR 0x%x", u32ReadCRValue); + } while ((u32LoopCount > 0) && + ((u32ReadCRValue&0x100) != 0x100)); + + if ((u32LoopCount == 0) && (0x100 != (u32ReadCRValue&0x100)) + && (set_checkretry > 0)) { + BTMTK_WARN("retry set_check driver own, CHLPCR 0x%x", u32ReadCRValue); + for (i = 0; i < 3; i++) { + ret = btmtk_sdio_readl(SWPCDBGR, &u32ReadCRValue); + BTMTK_WARN("ret %d,SWPCDBGR 0x%x, and not sleep!", ret, u32ReadCRValue); + } + btmtk_sdio_print_debug_sr(); + + set_checkretry--; + mdelay(20); + goto setretry; + } + } else { + do { + usleep_range(100, 200); + ret = btmtk_sdio_readl(CHLPCR, &u32ReadCRValue); + u32LoopCount--; + BTMTK_DBG("FW_OWN btmtk_sdio_readl CHLPCR 0x%x", u32ReadCRValue); + } while ((u32LoopCount > 0) && ((u32ReadCRValue&0x100) != 0)); + + if ((u32LoopCount == 0) && + ((u32ReadCRValue&0x100) != 0) && + (set_checkretry > 0)) { + BTMTK_WARN("retry set_check FW own, CHLPCR 0x%x", u32ReadCRValue); + set_checkretry--; + goto setretry; + } + } + + BTMTK_DBG("CHLPCR(0x%x), is 0x%x", CHLPCR, u32ReadCRValue); + + if (owntype == DRIVER_OWN) { + if ((u32ReadCRValue&0x100) == 0x100) + BTMTK_DBG("check %04x, is 0x100 driver own success", CHLPCR); + else { + BTMTK_DBG("check %04x, is %x shuld be 0x100", CHLPCR, u32ReadCRValue); + ret = -EINVAL; + goto done; + } + } else { + if (0x0 == (u32ReadCRValue&0x100)) + BTMTK_DBG("check %04x, bit 8 is 0 FW own success", CHLPCR); + else{ + BTMTK_DBG("bit 8 should be 0, %04x bit 8 is %04x", u32ReadCRValue, + (u32ReadCRValue&0x100)); + ret = -EINVAL; + goto done; + } + } + +done: + if (owntype == DRIVER_OWN) { + if (ret) { + BTMTK_ERR("set driver own fail"); + for (i = 0; i < 8; i++) { + retry_ret = btmtk_sdio_readl(SWPCDBGR, &u32ReadCRValue); + BTMTK_ERR("ret %d,SWPCDBGR 0x%x, then sleep 200ms", retry_ret, u32ReadCRValue); + msleep(200); + } + } else + BTMTK_DBG("set driver own success"); + } else if (owntype == FW_OWN) { + if (ret) + BTMTK_ERR("set FW own fail"); + else + BTMTK_DBG("set FW own success"); + } else + BTMTK_ERR("unknown type %d", owntype); + +set_own_end: + if (ret) + btmtk_sdio_print_debug_sr(); + + return ret; +} + +static int btmtk_sdio_enable_interrupt(int enable) +{ + u32 ret = 0; + u32 cr_value = 0; + + if (enable) + cr_value |= C_FW_INT_EN_SET; + else + cr_value |= C_FW_INT_EN_CLEAR; + + ret = btmtk_sdio_writel(CHLPCR, cr_value); + BTMTK_DBG("enable %d write CHLPCR 0x%08x", enable, cr_value); + + return ret; +} + +static int btmtk_sdio_get_rx_unit(struct btmtk_sdio_card *card) +{ + u8 reg; + int ret; + + ret = btmtk_sdio_readb(card->reg->card_rx_unit, ®); + if (!ret) + card->rx_unit = reg; + + return ret; +} + +static int btmtk_sdio_enable_host_int_mask( + struct btmtk_sdio_card *card, + u8 mask) +{ + int ret; + + ret = btmtk_sdio_writeb(card->reg->host_int_mask, mask); + if (ret) { + BTMTK_ERR("Unable to enable the host interrupt!"); + ret = -EIO; + } + + return ret; +} + +static int btmtk_sdio_disable_host_int_mask( + struct btmtk_sdio_card *card, + u8 mask) +{ + u8 host_int_mask; + int ret; + + ret = btmtk_sdio_readb(card->reg->host_int_mask, &host_int_mask); + if (ret) + return -EIO; + + host_int_mask &= ~mask; + + ret = btmtk_sdio_writeb(card->reg->host_int_mask, host_int_mask); + if (ret < 0) { + BTMTK_ERR("Unable to disable the host interrupt!"); + return -EIO; + } + + return 0; +} + +/*for debug*/ +int btmtk_print_buffer_conent(u8 *buf, u32 Datalen) +{ + int i = 0; + int print_finish = 0; + /*Print out txbuf data for debug*/ + for (i = 0; i <= (Datalen-1); i += 16) { + if ((i+16) <= Datalen) { + BTMTK_DBG("%02X%02X%02X%02X%02X %02X%02X%02X%02X%02X %02X%02X%02X%02X%02X %02X", + buf[i], buf[i+1], buf[i+2], buf[i+3], + buf[i+4], buf[i+5], buf[i+6], buf[i+7], + buf[i+8], buf[i+9], buf[i+10], buf[i+11], + buf[i+12], buf[i+13], buf[i+14], buf[i+15]); + } else { + for (; i < (Datalen); i++) + BTMTK_DBG("%02X", buf[i]); + + print_finish = 1; + } + + if (print_finish) + break; + } + return 0; +} + +static int btmtk_sdio_send_tx_data(u8 *buffer, int tx_data_len) +{ + int ret = 0; + u8 MultiBluckCount = 0; + u8 redundant = 0; + + MultiBluckCount = tx_data_len/SDIO_BLOCK_SIZE; + redundant = tx_data_len % SDIO_BLOCK_SIZE; + + if (redundant) + tx_data_len = (MultiBluckCount+1)*SDIO_BLOCK_SIZE; + + ret = btmtk_sdio_writesb(CTDR, buffer, tx_data_len); + return ret; +} + +static int btmtk_sdio_recv_rx_data(void) +{ + int ret = 0; + u32 u32ReadCRValue = 0; + int retry_count = 500; + u32 sdio_header_length = 0; + + memset(rxbuf, 0, MTK_RXDATA_SIZE); + + do { + ret = btmtk_sdio_readl(CHISR, &u32ReadCRValue); + BTMTK_DBG("loop Get CHISR 0x%08X", u32ReadCRValue); + reg_CHISR = u32ReadCRValue; + rx_length = (u32ReadCRValue & RX_PKT_LEN) >> 16; + if (rx_length == 0xFFFF) { + BTMTK_WARN("0xFFFF==rx_length, error return -EIO"); + ret = -EIO; + break; + } + + if ((RX_DONE&u32ReadCRValue) && rx_length) { + if (rx_length > MTK_RXDATA_SIZE) { + BTMTK_ERR("rx_length %d is bigger than MTK_RXDATA_SIZE %d", + rx_length, MTK_RXDATA_SIZE); + ret = -EIO; + break; + } + + BTMTK_DBG("u32ReadCRValue = %08X", u32ReadCRValue); + u32ReadCRValue &= 0xFFFB; + ret = btmtk_sdio_writel(CHISR, u32ReadCRValue); + BTMTK_DBG("write = %08X", u32ReadCRValue); + + + ret = btmtk_sdio_readsb(CRDR, rxbuf, rx_length); + sdio_header_length = (rxbuf[1] << 8); + sdio_header_length |= rxbuf[0]; + + if (sdio_header_length != rx_length) { + BTMTK_ERR("sdio header length %d, rx_length %d mismatch", + sdio_header_length, rx_length); + break; + } + + if (sdio_header_length == 0) { + BTMTK_WARN("get sdio_header_length = %d", sdio_header_length); + continue; + } + + break; + } + + retry_count--; + if (retry_count <= 0) { + BTMTK_WARN("retry_count = %d,timeout", retry_count); + btmtk_sdio_print_debug_sr(); + ret = -EIO; + break; + } + + /* msleep(1); */ + mdelay(3); + BTMTK_DBG("retry_count = %d,wait", retry_count); + + if (ret) + break; + } while (1); + + if (ret) + return -EIO; + + return ret; +} + +static int btmtk_sdio_send_wmt_cmd(u8 *cmd, int cmd_len, + const u8 *event, const int event_len) +{ + int ret = 0; + u8 mtksdio_packet_header[MTK_SDIO_PACKET_HEADER_SIZE] = {0}; + + BTMTK_INFO("begin"); + mtksdio_packet_header[0] = sizeof(mtksdio_packet_header) + cmd_len + 1; + + memcpy(txbuf, mtksdio_packet_header, MTK_SDIO_PACKET_HEADER_SIZE); + memcpy(txbuf + MTK_SDIO_PACKET_HEADER_SIZE + 1, cmd, cmd_len); + txbuf[MTK_SDIO_PACKET_HEADER_SIZE] = 0x1; + + btmtk_sdio_send_tx_data(txbuf, MTK_SDIO_PACKET_HEADER_SIZE + cmd_len + 1); + btmtk_sdio_recv_rx_data(); + + if (event && event_len) { + /*compare rx data is wmt reset correct response or not*/ + if (memcmp(event, rxbuf + MTK_SDIO_PACKET_HEADER_SIZE + 1, event_len) != 0) { + ret = -EIO; + BTMTK_WARN("fail"); + } + } else { + BTSDIO_INFO_RAW(cmd, cmd_len, "%s: CMD:", __func__); + BTSDIO_INFO_RAW(rxbuf + MTK_SDIO_PACKET_HEADER_SIZE + 1, + rx_length - MTK_SDIO_PACKET_HEADER_SIZE - 1, + "EVT:"); + } + + return ret; +} + +static int btmtk_sdio_send_wmt_cfg(void) +{ + int ret = 0; + int index = 0; + + BTMTK_INFO("begin"); + + for (index = 0; index < WMT_CMD_COUNT; index++) { + if (g_card->bt_cfg.wmt_cmd[index].content && g_card->bt_cfg.wmt_cmd[index].length) { + ret = btmtk_sdio_send_wmt_cmd(g_card->bt_cfg.wmt_cmd[index].content, + g_card->bt_cfg.wmt_cmd[index].length, + NULL, 0); + if (ret) { + BTMTK_ERR("Send wmt cmd failed(%d)! Index: %d", ret, index); + return ret; + } + } + } + + return ret; +} + +static int btmtk_sdio_send_wmt_reset(void) +{ + int ret = 0; + u8 wmt_event[8] = {4, 0xE4, 5, 2, 7, 1, 0, 0}; + u8 mtksdio_packet_header[MTK_SDIO_PACKET_HEADER_SIZE] = {0}; + u8 mtksdio_wmt_reset[9] = {1, 0x6F, 0xFC, 5, 1, 7, 1, 0, 4}; + + BTMTK_INFO("begin"); + mtksdio_packet_header[0] = sizeof(mtksdio_packet_header) + + sizeof(mtksdio_wmt_reset); + + memcpy(txbuf, mtksdio_packet_header, MTK_SDIO_PACKET_HEADER_SIZE); + memcpy(txbuf+MTK_SDIO_PACKET_HEADER_SIZE, mtksdio_wmt_reset, + sizeof(mtksdio_wmt_reset)); + + btmtk_sdio_send_tx_data(txbuf, + MTK_SDIO_PACKET_HEADER_SIZE+sizeof(mtksdio_wmt_reset)); + btmtk_sdio_recv_rx_data(); + + /*compare rx data is wmt reset correct response or not*/ + if (memcmp(wmt_event, rxbuf+MTK_SDIO_PACKET_HEADER_SIZE, + sizeof(wmt_event)) != 0) { + ret = -EIO; + BTMTK_WARN("fail"); + } + + return ret; +} + +static u32 btmtk_sdio_bt_memRegister_read(u32 cr) +{ + int retrytime = 3; + u32 result = 0; + u8 wmt_event[15] = {0x04, 0xE4, 0x10, 0x02, + 0x08, 0x0C/*0x1C*/, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x80}; + /* msleep(1000); */ + u8 mtksdio_packet_header[MTK_SDIO_PACKET_HEADER_SIZE] = {0}; + u8 mtksdio_wmt_cmd[16] = {0x1, 0x6F, 0xFC, 0x0C, + 0x01, 0x08, 0x08, 0x00, + 0x02, 0x01, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00}; + mtksdio_packet_header[0] = sizeof(mtksdio_packet_header) + + sizeof(mtksdio_wmt_cmd); + BTMTK_INFO("read cr %x", cr); + + memcpy(&mtksdio_wmt_cmd[12], &cr, sizeof(cr)); + + memcpy(txbuf, mtksdio_packet_header, MTK_SDIO_PACKET_HEADER_SIZE); + memcpy(txbuf + MTK_SDIO_PACKET_HEADER_SIZE, mtksdio_wmt_cmd, + sizeof(mtksdio_wmt_cmd)); + + btmtk_sdio_send_tx_data(txbuf, + MTK_SDIO_PACKET_HEADER_SIZE + sizeof(mtksdio_wmt_cmd)); + btmtk_print_buffer_conent(txbuf, + MTK_SDIO_PACKET_HEADER_SIZE + sizeof(mtksdio_wmt_cmd)); + + do { + usleep_range(10*1000, 15*1000); + btmtk_sdio_recv_rx_data(); + retrytime--; + if (retrytime <= 0) + break; + + BTMTK_INFO("retrytime %d", retrytime); + } while (!rxbuf[0]); + + btmtk_print_buffer_conent(rxbuf, rx_length); + /* compare rx data is wmt reset correct response or not */ +#if 0 + if (memcmp(wmt_event, + rxbuf+MTK_SDIO_PACKET_HEADER_SIZE, + sizeof(wmt_event)) != 0) { + ret = -EIO; + BTMTK_INFO("fail"); + } +#endif + memcpy(&result, rxbuf+MTK_SDIO_PACKET_HEADER_SIZE + sizeof(wmt_event), + sizeof(result)); + BTMTK_INFO("ger cr 0x%x value 0x%x", cr, result); + return result; +} + +static int btmtk_sdio_send_hci_reset(bool is_closed) +{ + int ret = 0; + u8 event[] = {0x0e, 0x04, 0x01, 0x03, 0x0c, 0x00}; + u8 cmd[] = {0x03, 0x0c, 0x00}; + + BTMTK_INFO("begin\n"); + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, + cmd, sizeof(cmd), + event, sizeof(event), COMP_EVENT_TIMO); + if (ret != 0) + BTMTK_ERR("ret = %d\n", ret); + + if (is_closed == true) + get_hci_reset = 0; + return ret; +} + +/* 1:on , 0:off */ +static int btmtk_sdio_bt_set_power(u8 onoff) +{ + int ret = 0; + int count = 0; + u8 event[] = {0xE4, 0x05, 0x02, 0x06, 0x01, 0x00, 0x00}; + u8 cmd[] = {0x6F, 0xFC, 0x06, 0x01, 0x06, 0x02, 0x00, 0x00, 0x01}; + + BTMTK_INFO("onoff %d", onoff); + cmd[8] = onoff; + + do { + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, cmd, sizeof(cmd), + event, sizeof(event), COMP_EVENT_TIMO); + if (ret) + g_card->dongle_state = BT_SDIO_DONGLE_STATE_ERROR; + else + g_card->dongle_state = + onoff ? BT_SDIO_DONGLE_STATE_POWER_ON : BT_SDIO_DONGLE_STATE_POWER_OFF; + } while (++count < SET_POWER_NUM && ret); + + return ret; +} + +static int btmtk_sdio_send_vendor_cfg(void) +{ + int ret = 0; + int index = 0; + + BTMTK_INFO("begin"); + + for (index = 0; index < VENDOR_CMD_COUNT; index++) { + if (g_card->bt_cfg.vendor_cmd[index].content && g_card->bt_cfg.vendor_cmd[index].length) { + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, + g_card->bt_cfg.vendor_cmd[index].content, + g_card->bt_cfg.vendor_cmd[index].length, + NULL, 0, COMP_EVENT_TIMO); + if (ret) { + BTMTK_ERR("Send vendor cmd failed(%d)! Index: %d", ret, index); + return ret; + } + } + } + + return ret; +} + +static int btmtk_sdio_setup_picus_param(struct fw_cfg_struct *picus_setting) +{ + u8 dft_cmd[] = {0x5F, 0xFC, 0x2E, 0x50, 0x01, 0x0A, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0xE0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00}; + u8 *cmd = NULL; + int len = 0; + u8 event[] = { 0x0E, 0x04, 0x01, 0x5F, 0xFC, 0x00 }; + int ret = -1; /* if successful, 0 */ + + if (picus_setting->content && picus_setting->length) { + cmd = picus_setting->content; + len = picus_setting->length; + } else { + cmd = dft_cmd; + len = sizeof(dft_cmd); + } + + BTSDIO_INFO_RAW(cmd, len, "%s: Filter CMD:", __func__); + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, + cmd, len, + event, sizeof(event), COMP_EVENT_TIMO); + if (ret) { + BTMTK_ERR("Send picus filter cmd failed(%d)!", ret); + return ret; + } + + return ret; +} + +static int btmtk_sdio_picus_operation(bool enable) +{ + + u8 cmd[] = {0xBE, 0xFC, 0x01, 0x15}; + u8 event[] = {0x0E, 0x04, 0x01, 0xBE, 0xFC, 0x00}; + int ret = -1; /* if successful, 0 */ + + if (enable == false) + cmd[3] = 0x00; + + BTSDIO_INFO_RAW(cmd, (int)sizeof(cmd), "%s: Enable CMD:", __func__); + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, + cmd, sizeof(cmd), + event, sizeof(event), COMP_EVENT_TIMO); + if (ret) { + BTMTK_ERR("Send picus enable cmd failed(%d)!", ret); + return ret; + } + + return ret; +} + +/*get 1 byte only*/ +static int btmtk_efuse_read(u16 addr, u8 *value) +{ + uint8_t efuse_r[] = {0x6F, 0xFC, 0x0E, + 0x01, 0x0D, 0x0A, 0x00, 0x02, 0x04, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00};/*4 sub block number(sub block 0~3)*/ + + uint8_t efuse_r_event[] = {0xE4, 0x1E, 0x02, 0x0D, 0x1A, 0x00, 02, 04}; + /*check event + *04 E4 LEN(1B) 02 0D LEN(2Byte) 02 04 ADDR(2Byte) VALUE(4B) ADDR(2Byte) VALUE(4Byte) + *ADDR(2Byte) VALUE(4B) ADDR(2Byte) VALUE(4Byte) + */ + int ret = 0; + uint8_t sub_block_addr_in_event = 0; + uint16_t sub_block = (addr / 16) * 4; + uint8_t temp = 0; + + efuse_r[9] = sub_block & 0xFF; + efuse_r[10] = (sub_block & 0xFF00) >> 8; + efuse_r[11] = (sub_block + 1) & 0xFF; + efuse_r[12] = ((sub_block + 1) & 0xFF00) >> 8; + efuse_r[13] = (sub_block + 2) & 0xFF; + efuse_r[14] = ((sub_block + 2) & 0xFF00) >> 8; + efuse_r[15] = (sub_block + 3) & 0xFF; + efuse_r[16] = ((sub_block + 3) & 0xFF00) >> 8; + + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, + efuse_r, sizeof(efuse_r), + efuse_r_event, sizeof(efuse_r_event), COMP_EVENT_TIMO); + if (ret) { + BTMTK_WARN("btmtk_sdio_send_hci_cmd error"); + BTMTK_WARN("rx_length %d", rx_length); + return ret; + } + + if (memcmp(rxbuf + MTK_SDIO_PACKET_HEADER_SIZE + 1, efuse_r_event, sizeof(efuse_r_event)) == 0) { + /*compare rxbuf format ok, compare addr*/ + BTMTK_DBG("compare rxbuf format ok"); + if (efuse_r[9] == rxbuf[9 + MTK_SDIO_PACKET_HEADER_SIZE] && + efuse_r[10] == rxbuf[10 + MTK_SDIO_PACKET_HEADER_SIZE] && + efuse_r[11] == rxbuf[15 + MTK_SDIO_PACKET_HEADER_SIZE] && + efuse_r[12] == rxbuf[16 + MTK_SDIO_PACKET_HEADER_SIZE] && + efuse_r[13] == rxbuf[21 + MTK_SDIO_PACKET_HEADER_SIZE] && + efuse_r[14] == rxbuf[22 + MTK_SDIO_PACKET_HEADER_SIZE] && + efuse_r[15] == rxbuf[27 + MTK_SDIO_PACKET_HEADER_SIZE] && + efuse_r[16] == rxbuf[28 + MTK_SDIO_PACKET_HEADER_SIZE]) { + + BTMTK_DBG("address compare ok"); + /*Get value*/ + sub_block_addr_in_event = ((addr / 16) / 4);/*cal block num*/ + temp = addr % 16; + BTMTK_DBG("address in block %d", temp); + switch (temp) { + case 0: + case 1: + case 2: + case 3: + *value = rxbuf[11 + temp + MTK_SDIO_PACKET_HEADER_SIZE]; + break; + case 4: + case 5: + case 6: + case 7: + *value = rxbuf[17 + temp + MTK_SDIO_PACKET_HEADER_SIZE]; + break; + case 8: + case 9: + case 10: + case 11: + *value = rxbuf[22 + temp + MTK_SDIO_PACKET_HEADER_SIZE]; + break; + + case 12: + case 13: + case 14: + case 15: + *value = rxbuf[34 + temp + MTK_SDIO_PACKET_HEADER_SIZE]; + break; + } + + + } else { + BTMTK_WARN("address compare fail"); + ret = -1; + } + + + } else { + BTMTK_WARN("compare rxbuf format fail"); + ret = -1; + } + + return ret; +} + +static int btmtk_check_auto_mode(struct btmtk_sdio_card *card) +{ + u16 addr = 1; + u8 value = 0; + + if (card->efuse_mode != EFUSE_AUTO_MODE) + return 0; + + if (btmtk_efuse_read(addr, &value)) { + BTMTK_WARN("read fail"); + BTMTK_WARN("Use EEPROM Bin file mode"); + card->efuse_mode = EFUSE_BIN_FILE_MODE; + return -EIO; + } + + if (value == 0x76) { + BTMTK_WARN("get efuse[1]: 0x%02x", value); + BTMTK_WARN("use efuse mode"); + card->efuse_mode = EFUSE_MODE; + } else { + BTMTK_WARN("get efuse[1]: 0x%02x", value); + BTMTK_WARN("Use EEPROM Bin file mode"); + card->efuse_mode = EFUSE_BIN_FILE_MODE; + } + + return 0; +} + +static int btmtk_sdio_send_init_cmds(struct btmtk_sdio_card *card) +{ + if (btmtk_sdio_bt_set_power(1)) { + BTMTK_ERR("power on failed"); + return -EIO; + } + + if (btmtk_check_auto_mode(card)) { + BTMTK_ERR("check auto mode failed"); + return -EIO; + } + + if (btmtk_sdio_set_sleep()) { + BTMTK_ERR("set sleep failed"); + return -EIO; + } + + if (btmtk_sdio_set_audio()) { + BTMTK_ERR("set audio failed"); + return -EIO; + } + + if (btmtk_sdio_send_vendor_cfg()) { + BTMTK_ERR("send vendor cmd failed"); + return -EIO; + } + + if (g_card->bt_cfg.support_auto_picus == true) { + if (btmtk_sdio_setup_picus_param(&g_card->bt_cfg.picus_filter)) { + BTMTK_ERR("send setup_picus_param cmd failed"); + return -EIO; + } + } + + return 0; +} + +static int btmtk_sdio_send_deinit_cmds(void) +{ + if (btmtk_sdio_bt_set_power(0)) { + BTMTK_ERR("power off failed"); + return -EIO; + } + return 0; +} + +static void btmtk_parse_efuse_mode(uint8_t *buf, size_t buf_size, struct btmtk_sdio_card *card) +{ + char *p_buf = NULL; + char *ptr = NULL, *p = NULL; + + card->efuse_mode = EFUSE_MODE; + if (!buf) { + BTMTK_WARN("buf is null"); + return; + } else if (buf_size < (strlen(E2P_MODE) + 2)) { + BTMTK_WARN("incorrect buf size(%d)", (int)buf_size); + return; + } + + p_buf = kmalloc(buf_size + 1, GFP_KERNEL); + if (!p_buf) + return; + memcpy(p_buf, buf, buf_size); + p_buf[buf_size] = '\0'; + + /* find string */ + p = ptr = strstr(p_buf, E2P_MODE); + if (!ptr) { + BTMTK_ERR("Can't find %s", E2P_MODE); + goto out; + } + + if (p > p_buf) { + p--; + while ((*p == ' ') && (p != p_buf)) + p--; + if (*p == '#') { + BTMTK_ERR("It's not EEPROM - Bin file mode"); + goto out; + } + } + + /* check access mode */ + ptr += (strlen(E2P_MODE) + 1); + BTMTK_WARN("It's EEPROM bin mode: %c", *ptr); + card->efuse_mode = *ptr - '0'; + if (card->efuse_mode > EFUSE_AUTO_MODE) + card->efuse_mode = EFUSE_MODE; +out: + kfree(p_buf); + return; +} + +static void btmtk_set_eeprom2ctrler(uint8_t *buf, + size_t buf_size, + int device) +{ + int ret = -1; + uint8_t set_bdaddr[] = {0x1A, 0xFC, 0x06, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t set_bdaddr_e[] = {0x0E, 0x04, 0x01, + 0x1A, 0xFC, 0x00}; + uint8_t set_radio[] = {0x79, 0xFC, 0x08, + 0x07, 0x80, 0x00, 0x06, 0x07, 0x07, 0x00, 0x00}; + uint8_t set_radio_e[] = {0x0E, 0x04, 0x01, + 0x79, 0xFC, 0x00}; + uint8_t set_pwr_offset[] = {0x93, 0xFC, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t set_pwr_offset_e[] = {0x0E, 0x04, 0x01, + 0x93, 0xFC, 0x00}; + uint8_t set_xtal[] = {0x0E, 0xFC, 0x02, 0x00, 0x00}; + uint8_t set_xtal_e[] = {0x0E, 0x04, 0x01, + 0x0E, 0xFC, 0x00}; + uint16_t offset = 0; + + BTMTK_INFO("start, device: 0x%x", device); + + if (!buf) { + BTMTK_WARN("buf is null"); + return; + } else if (device == 0x7668 && buf_size < 0x389) { + BTMTK_WARN("incorrect buf size(%d)", (int)buf_size); + return; + } else if (device == 0x7663 && buf_size < 0x389) { + BTMTK_WARN("incorrect buf size(%d)", (int)buf_size); + return; + } + + /* set BD address */ + if (device == 0x7668) + offset = 0x384; + else if (device == 0x7663) + offset = 0x131; + else + offset = 0x1A; + + set_bdaddr[3] = *(buf + offset); + set_bdaddr[4] = *(buf + offset + 1); + set_bdaddr[5] = *(buf + offset + 2); + set_bdaddr[6] = *(buf + offset + 3); + set_bdaddr[7] = *(buf + offset + 4); + set_bdaddr[8] = *(buf + offset + 5); + if (0x0 == set_bdaddr[3] && 0x0 == set_bdaddr[4] + && 0x0 == set_bdaddr[5] && 0x0 == set_bdaddr[6] + && 0x0 == set_bdaddr[7] && 0x0 == set_bdaddr[8]) { + BTMTK_WARN("BDAddr is Zero, not set"); + } else { + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, set_bdaddr, + set_bdaddr[2] + 3, + set_bdaddr_e, sizeof(set_bdaddr_e), COMP_EVENT_TIMO); + BTMTK_WARN("set BDAddress(%02X-%02X-%02X-%02X-%02X-%02X) %s", + set_bdaddr[8], set_bdaddr[7], set_bdaddr[6], + set_bdaddr[5], set_bdaddr[4], set_bdaddr[3], + ret < 0 ? "fail" : "OK"); + } + /* radio setting - BT power */ + if (device == 0x7668) { + offset = 0x382; + /* BT default power */ + set_radio[3] = (*(buf + offset) & 0x07); + /* BLE default power */ + set_radio[7] = (*(buf + offset + 1) & 0x07); + /* TX MAX power */ + set_radio[8] = (*(buf + offset) & 0x70) >> 4; + /* TX power sub level */ + set_radio[9] = (*(buf + offset + 1) & 0x30) >> 4; + /* BR/EDR power diff mode */ + set_radio[10] = (*(buf + offset + 1) & 0xc0) >> 6; + } else if (device == 0x7663) { + offset = 0x137; + /* BT default power */ + set_radio[3] = (*(buf + offset) & 0x07); + /* BLE default power */ + set_radio[7] = (*(buf + offset + 1) & 0x07); + /* TX MAX power */ + set_radio[8] = (*(buf + offset) & 0x70) >> 4; + /* TX power sub level */ + set_radio[9] = (*(buf + offset + 1) & 0x30) >> 4; + /* BR/EDR power diff mode */ + set_radio[10] = (*(buf + offset + 1) & 0xc0) >> 6; + } else { + offset = 0x132; + /* BT default power */ + set_radio[3] = *(buf + offset); + /* BLE default power(no this for 7662 in table) */ + set_radio[7] = *(buf + offset); + /* TX MAX power */ + set_radio[8] = *(buf + offset + 1); + } + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, set_radio, + set_radio[2] + 3, + set_radio_e, sizeof(set_radio_e), COMP_EVENT_TIMO); + BTMTK_WARN("set radio(BT/BLE default power: %d/%d MAX power: %d) %s", + set_radio[3], set_radio[7], set_radio[8], + ret < 0 ? "fail" : "OK"); + + /* + * BT TX power compensation for low, middle and high + * channel + */ + if (device == 0x7668) { + offset = 0x36D; + /* length */ + set_pwr_offset[2] = 6; + /* Group 0 CH 0 ~ CH14 */ + set_pwr_offset[3] = *(buf + offset); + /* Group 1 CH15 ~ CH27 */ + set_pwr_offset[4] = *(buf + offset + 1); + /* Group 2 CH28 ~ CH40 */ + set_pwr_offset[5] = *(buf + offset + 2); + /* Group 3 CH41 ~ CH53 */ + set_pwr_offset[6] = *(buf + offset + 3); + /* Group 4 CH54 ~ CH66 */ + set_pwr_offset[7] = *(buf + offset + 4); + /* Group 5 CH67 ~ CH84 */ + set_pwr_offset[8] = *(buf + offset + 5); + } else if (device == 0x7663) { + offset = 0x180; + /* length */ + set_pwr_offset[2] = 16; + /* Group 0 CH 0 ~ CH6 */ + set_pwr_offset[3] = *(buf + offset); + /* Group 1 CH7 ~ CH11 */ + set_pwr_offset[4] = *(buf + offset + 1); + /* Group 2 CH12 ~ CH16 */ + set_pwr_offset[5] = *(buf + offset + 2); + /* Group 3 CH17 ~ CH21 */ + set_pwr_offset[6] = *(buf + offset + 3); + /* Group 4 CH22 ~ CH26 */ + set_pwr_offset[7] = *(buf + offset + 4); + /* Group 5 CH27 ~ CH31 */ + set_pwr_offset[8] = *(buf + offset + 5); + /* Group 6 CH32 ~ CH36 */ + set_pwr_offset[9] = *(buf + offset + 6); + /* Group 7 CH37 ~ CH41 */ + set_pwr_offset[10] = *(buf + offset + 7); + /* Group 8 CH42 ~ CH46 */ + set_pwr_offset[11] = *(buf + offset + 8); + /* Group 9 CH47 ~ CH51 */ + set_pwr_offset[12] = *(buf + offset + 9); + /* Group 10 CH52 ~ CH56 */ + set_pwr_offset[13] = *(buf + offset + 10); + /* Group 11 CH57 ~ CH61 */ + set_pwr_offset[14] = *(buf + offset + 11); + /* Group 12 CH62 ~ CH66 */ + set_pwr_offset[15] = *(buf + offset + 12); + /* Group 13 CH67 ~ CH71 */ + set_pwr_offset[16] = *(buf + offset + 13); + /* Group 14 CH72 ~ CH76 */ + set_pwr_offset[17] = *(buf + offset + 14); + /* Group 15 CH77 ~ CH78 */ + set_pwr_offset[18] = *(buf + offset + 15); + } else { + offset = 0x139; + /* length */ + set_pwr_offset[2] = 3; + /* low channel */ + set_pwr_offset[3] = *(buf + offset); + /* middle channel */ + set_pwr_offset[4] = *(buf + offset + 1); + /* high channel */ + set_pwr_offset[5] = *(buf + offset + 2); + } + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, set_pwr_offset, + set_pwr_offset[2] + 3, + set_pwr_offset_e, sizeof(set_pwr_offset_e), COMP_EVENT_TIMO); + BTMTK_WARN("set power offset(%02X %02X %02X %02X %02X %02X) %s", + set_pwr_offset[3], set_pwr_offset[4], + set_pwr_offset[5], set_pwr_offset[6], + set_pwr_offset[7], set_pwr_offset[8], + ret < 0 ? "fail" : "OK"); + + /* XTAL setting */ + if (device == 0x7668) { + offset = 0xF4; + /* BT default power */ + set_xtal[3] = *(buf + offset); + set_xtal[4] = *(buf + offset + 1); + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, set_xtal, + set_xtal[2] + 3, + set_xtal_e, sizeof(set_xtal_e), COMP_EVENT_TIMO); + BTMTK_WARN("set XTAL(0x%02X %02X) %s", + set_xtal[3], set_xtal[4], + ret < 0 ? "fail" : "OK"); + } + BTMTK_INFO("end"); +} + +static void btmtk_set_pa(uint8_t pa) +{ + int ret = -1; + uint8_t epa[] = {0x70, 0xFD, 0x09, + 0x00, + 0x07, 0x00, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00}; + uint8_t epa_e[] = {0x0E, 0x04, 0x01, + 0x70, 0xFD, 0x00}; + + epa[3] = pa; + if (pa > 1 || pa < 0) { + BTMTK_WARN("Incorrect format"); + return; + } + if (pa == 1) { + BTMTK_WARN("ePA mode, change power level to level 9."); + epa[4] = 0x09; + epa[8] = 0x09; + epa[9] = 0x09; + } + + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, epa, sizeof(epa), + epa_e, sizeof(epa_e), COMP_EVENT_TIMO); + BTMTK_WARN("set PA(%d) %s", + pa, ret < 0 ? "fail" : "OK"); +} + +static void btmtk_set_duplex(uint8_t duplex) +{ + int ret = -1; + uint8_t ant[] = {0x71, 0xFD, 0x01, 0x00}; + uint8_t ant_e[] = {0x0E, 0x04, 0x01, + 0x71, 0xFD, 0x00}; + + ant[3] = duplex; + if (duplex > 1 || duplex < 0) { + BTMTK_WARN("Incorrect format"); + return; + } + + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, ant, sizeof(ant), + ant_e, sizeof(ant_e), COMP_EVENT_TIMO); + BTMTK_WARN("set Duplex(%d) %s", + duplex, ret < 0 ? "fail" : "OK"); +} + +static void btmtk_set_pa_and_duplex(uint8_t *buf, size_t buf_size) +{ + char *p_buf = NULL; + char *ptr = NULL, *p = NULL; + + if (!buf) { + BTMTK_WARN("buf is null"); + return; + } else if (buf_size < (strlen(E2P_MODE) + 2)) { + BTMTK_WARN("incorrect buf size(%d)", (int)buf_size); + return; + } + p_buf = kmalloc(buf_size + 1, GFP_KERNEL); + if (!p_buf) + return; + + memcpy(p_buf, buf, buf_size); + p_buf[buf_size] = '\0'; + /* find string */ + p = ptr = strstr(p_buf, E2P_ACCESS_EPA); + if (!ptr) { + BTMTK_WARN("Can't find %s", E2P_ACCESS_EPA); + g_card->pa_setting = -1; + g_card->duplex_setting = -1; + goto out; + } + if (p > p_buf) { + p--; + while ((*p == ' ') && (p != p_buf)) + p--; + if (*p == '#') { + BTMTK_WARN("It's no pa setting"); + g_card->pa_setting = -1; + g_card->duplex_setting = -1; + goto out; + } + } + /* check access mode */ + ptr += (strlen(E2P_ACCESS_EPA) + 1); + if (*ptr != '0') { + BTMTK_WARN("ePA mode: %c", *ptr); + g_card->pa_setting = 1; + } else { + BTMTK_WARN("iPA mode: %c", *ptr); + g_card->pa_setting = 0; + } + + p = ptr = strstr(p_buf, E2P_ACCESS_DUPLEX); + if (!ptr) { + BTMTK_WARN("Can't find %s", E2P_ACCESS_DUPLEX); + g_card->duplex_setting = -1; + goto out; + } + if (p > p_buf) { + p--; + while ((*p == ' ') && (p != p_buf)) + p--; + if (*p == '#') { + BTMTK_WARN("It's no duplex setting"); + g_card->duplex_setting = -1; + goto out; + } + } + /* check access mode */ + ptr += (strlen(E2P_ACCESS_DUPLEX) + 1); + if (*ptr != '0') { + BTMTK_WARN("TDD mode: %c", *ptr); + g_card->duplex_setting = 1; + } else { + BTMTK_WARN("FDD mode: %c", *ptr); + g_card->duplex_setting = 0; + } + +out: + kfree(p_buf); +} + +void btmtk_set_keep_full_pwr(uint8_t *buf, size_t buf_size) +{ + char *p_buf = NULL; + char *ptr = NULL; + + g_card->is_KeepFullPwr = false; + + if (!buf) { + BTMTK_ERR("buf is null"); + return; + } else if (buf_size < (strlen(KEEP_FULL_PWR) + 2)) { + BTMTK_ERR("incorrect buf size(%d)", (int)buf_size); + return; + } + + p_buf = kmalloc(buf_size + 1, GFP_KERNEL); + if (!p_buf) + return; + + memcpy(p_buf, buf, buf_size); + p_buf[buf_size] = '\0'; + + /* find string */ + ptr = strstr(p_buf, KEEP_FULL_PWR); + if (!ptr) { + BTMTK_ERR("Can't find %s", KEEP_FULL_PWR); + goto out; + } + + /* check always driver own */ + ptr += (strlen(KEEP_FULL_PWR) + 1); + + if (*ptr == PWR_KEEP_NO_FW_OWN) { + /* always driver own is set*/ + BTMTK_INFO("Read KeepFullPwr on: %c", *ptr); + g_card->is_KeepFullPwr = true; + } else if (*ptr == PWR_SWITCH_DRIVER_FW_OWN) { + /* always driver own is not set */ + BTMTK_INFO("Read KeepFullPwr off: %c", *ptr); + } else { + BTMTK_WARN("It's not the correct own setting: %c", *ptr); + } + +out: + kfree(p_buf); +} + +static void btmtk_set_power_limit(uint8_t *buf, + size_t buf_size, + bool is7668) +{ + int ret = -1; + uint8_t set_radio[] = {0x79, 0xFC, 0x08, + 0x07, 0x80, 0x00, 0x06, 0x07, 0x07, 0x00, 0x00}; + uint8_t set_radio_e[] = {0x0E, 0x04, 0x01, + 0x79, 0xFC, 0x00}; + uint16_t offset = 0; + + if (!buf) { + BTMTK_WARN("buf is null"); + return; + } else if (is7668 == false) { + BTMTK_WARN("only support mt7668 right now"); + return; + } + + /* radio setting - BT power */ + if (is7668) { + /* BT default power */ + set_radio[3] = (*(buf + offset)); + /* BLE default power */ + set_radio[7] = (*(buf + offset + 1)); + /* TX MAX power */ + set_radio[8] = (*(buf + offset + 2)); + /* TX power sub level */ + set_radio[9] = 0; + /* BR/EDR power diff mode */ + set_radio[10] = (*(buf + offset + 3)); + } + + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, set_radio, sizeof(set_radio), + set_radio_e, sizeof(set_radio_e), COMP_EVENT_TIMO); + BTMTK_WARN("set radio(BT/BLE default power: %d/%d MAX power: %d) %s", + set_radio[3], set_radio[7], set_radio[8], + ret < 0 ? "fail" : "OK"); + +} + +static void btmtk_requset_power_limit_callback(const struct firmware *pwr_fw, void *context) +{ + struct btmtk_sdio_card *card = (struct btmtk_sdio_card *)context; + + BTMTK_INFO("begin"); + if (pwr_fw != NULL) { + /* set parameters to controller */ + btmtk_set_power_limit((uint8_t *)pwr_fw->data, + pwr_fw->size, + (card->func->device == 0x7668 ? true : false)); + release_firmware(pwr_fw); + } else { + BTMTK_INFO("pwr_fw is NULL"); + } +} + +static void btmtk_eeprom_bin_file(struct btmtk_sdio_card *card) +{ + char *cfg_file = NULL; + char bin_file[32]; + + const struct firmware *cfg_fw = NULL; + const struct firmware *bin_fw = NULL; + + int ret = -1; + int chipid = card->func->device; + + BTMTK_INFO("%X series", chipid); + cfg_file = E2P_ACCESS_MODE_SWITCHER; + sprintf(bin_file, E2P_BIN_FILE, chipid); + + usleep_range(10*1000, 15*1000); + + /* request configure file */ + ret = request_firmware(&cfg_fw, cfg_file, &card->func->dev); + if (ret < 0) { + if (ret == -EAGAIN) { + cfg_fw = NULL; + BTMTK_WARN("try to load configure file again"); + ret = request_firmware(&cfg_fw, cfg_file, &card->func->dev); + if (ret < 0) { + BTMTK_WARN("load configure file again but still fail(%d)", ret); + goto exit; + } + BTMTK_WARN("load configure file again and success(%d)", ret); + } else { + if (ret == -ENOENT) + BTMTK_WARN("Configure file not found, ignore EEPROM bin file"); + else + BTMTK_WARN("request configure file fail(%d)", ret); + goto exit; + } + } + + if (cfg_fw) { + btmtk_set_pa_and_duplex((uint8_t *)cfg_fw->data, cfg_fw->size); + btmtk_set_keep_full_pwr((uint8_t *)cfg_fw->data, cfg_fw->size); + } else { + BTMTK_ERR("cfg_fw is null"); + card->efuse_mode = EFUSE_MODE; + goto exit; + } + + btmtk_parse_efuse_mode((uint8_t *)cfg_fw->data, cfg_fw->size, card); + if (card->efuse_mode == EFUSE_MODE) { + if (card->bin_file_buffer != NULL) { + kfree(card->bin_file_buffer); + card->bin_file_buffer = NULL; + card->bin_file_size = 0; + } + goto exit; + } + + usleep_range(10*1000, 15*1000); + + /* open bin file for EEPROM */ + ret = request_firmware(&bin_fw, bin_file, &card->func->dev); + if (ret < 0) { + BTMTK_WARN("request bin file fail(%d)", ret); + goto exit; + } + + card->bin_file_buffer = kmalloc(bin_fw->size, GFP_KERNEL); + if (card->bin_file_buffer == NULL) { + goto exit; + } + memcpy(card->bin_file_buffer, bin_fw->data, bin_fw->size); + card->bin_file_size = bin_fw->size; + +exit: + /* open power limit */ + ret = request_firmware_nowait(THIS_MODULE, true, TX_PWR_LIMIT, + &card->func->dev, GFP_KERNEL, g_card, btmtk_requset_power_limit_callback); + if (ret < 0) + BTMTK_WARN("request power limit file fail(%d)", ret); + + if (cfg_fw) + release_firmware(cfg_fw); + if (bin_fw) + release_firmware(bin_fw); +} + +/* 1:on , 0:off */ +static int btmtk_sdio_set_sleep(void) +{ + int ret = 0; + u8 event[] = {0x0E, 0x04, 0x01, 0x7A, 0xFC, 0x00}; + u8 cmd[] = {0x7A, 0xFC, 0x07, + /*3:sdio, 5:usb*/0x03, + /*host non sleep duration*/0x80, 0x02, + /*host non sleep duration*/0x80, 0x02, 0x00, 0x00}; + BTMTK_INFO("begin"); + + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, cmd, sizeof(cmd), + event, sizeof(event), COMP_EVENT_TIMO); + + return ret; +} + +static int btmtk_sdio_skb_enq_fwlog(void *src, u32 len, u8 type, struct sk_buff_head *queue) +{ + struct sk_buff *skb_tmp = NULL; + int retry = 10; + + do { + /* If we need hci type, len + 1 */ + skb_tmp = alloc_skb(type ? len + 1 : len, GFP_ATOMIC); + if (skb_tmp != NULL) + break; + else if (retry <= 0) { + BTMTK_ERR("alloc_skb return 0, error"); + return -ENOMEM; + } + BTMTK_ERR("alloc_skb return 0, error, retry = %d", retry); + } while (retry-- > 0); + + if (type) { + memcpy(&skb_tmp->data[0], &type, 1); + memcpy(&skb_tmp->data[1], src, len); + skb_tmp->len = len + 1; + } else { + memcpy(skb_tmp->data, src, len); + skb_tmp->len = len; + } + + LOCK_UNSLEEPABLE_LOCK(&(fwlog_metabuffer.spin_lock)); + skb_queue_tail(queue, skb_tmp); + UNLOCK_UNSLEEPABLE_LOCK(&(fwlog_metabuffer.spin_lock)); + return 0; +} + +static int btmtk_sdio_dispatch_fwlog(u8 *buf, int len) +{ + static u8 fwlog_picus_blocking_warn; + static u8 fwlog_fwdump_blocking_warn; + int ret = 0; + + if ((buf[0] == 0xFF && buf[2] == 0x50) || + (buf[0] == 0xFF && buf[1] == 0x05)) { + if (skb_queue_len(&g_card->fwlog_fops_queue) < FWLOG_QUEUE_COUNT) { + BTMTK_DBG("This is picus data"); + if (btmtk_sdio_skb_enq_fwlog(buf, len, 0, &g_card->fwlog_fops_queue) == 0) + wake_up_interruptible(&fw_log_inq); + + fwlog_picus_blocking_warn = 0; + } else { + if (fwlog_picus_blocking_warn == 0) { + fwlog_picus_blocking_warn = 1; + BTMTK_WARN("fwlog queue size is full(picus)"); + } + } + } else if (buf[0] == 0x6f && buf[1] == 0xfc) { + /* Coredump */ + if (skb_queue_len(&g_card->fwlog_fops_queue) < FWLOG_ASSERT_QUEUE_COUNT) { + BTMTK_DBG("Receive coredump, move data to fwlogqueue for picus"); + if (btmtk_sdio_skb_enq_fwlog(buf, len, 0, &g_card->fwlog_fops_queue) == 0) + wake_up_interruptible(&fw_log_inq); + fwlog_fwdump_blocking_warn = 0; + } else { + if (fwlog_fwdump_blocking_warn == 0) { + fwlog_fwdump_blocking_warn = 1; + BTMTK_WARN("fwlog queue size is full(coredump)"); + } + } + } + return ret; +} + +static int btmtk_sdio_dispatch_data_bluetooth_kpi(u8 *buf, int len, u8 type) +{ + static u8 fwlog_blocking_warn; + int ret = 0; + + if (!btmtk_bluetooth_kpi) + return ret; + + if (skb_queue_len(&g_card->fwlog_fops_queue) < FWLOG_BLUETOOTH_KPI_QUEUE_COUNT) { + /* sent event to queue, picus tool will log it for bluetooth KPI feature */ + if (btmtk_sdio_skb_enq_fwlog(buf, len, type, &g_card->fwlog_fops_queue) == 0) { + wake_up_interruptible(&fw_log_inq); + fwlog_blocking_warn = 0; + } + } else { + if (fwlog_blocking_warn == 0) { + fwlog_blocking_warn = 1; + BTMTK_WARN("fwlog queue size is full(bluetooth_kpi)"); + } + } + return ret; +} + +static int btmtk_sdio_host_to_card(struct btmtk_private *priv, + u8 *payload, u16 nb) +{ + struct btmtk_sdio_card *card = priv->btmtk_dev.card; + int ret = 0; + int i = 0; + u8 MultiBluckCount = 0; + u8 redundant = 0; + int len = 0; + + if (payload != txbuf) { + memset(txbuf, 0, MTK_TXDATA_SIZE); + memcpy(txbuf, payload, nb); + } + + if (!card || !card->func) { + BTMTK_ERR("card or function is NULL!"); + return -EINVAL; + } + + len = nb - MTK_SDIO_PACKET_HEADER_SIZE; + + btmtk_sdio_dispatch_data_bluetooth_kpi(&txbuf[MTK_SDIO_PACKET_HEADER_SIZE], len, 0); + + MultiBluckCount = nb/SDIO_BLOCK_SIZE; + redundant = nb % SDIO_BLOCK_SIZE; + + if (redundant) + nb = (MultiBluckCount+1)*SDIO_BLOCK_SIZE; + + if (nb < 16) + btmtk_print_buffer_conent(txbuf, nb); + else + btmtk_print_buffer_conent(txbuf, 16); + + do { + /* Transfer data to card */ + ret = btmtk_sdio_writesb(CTDR, txbuf, nb); + if (ret < 0) { + i++; + BTMTK_ERR("i=%d writesb failed: %d", i, ret); + ret = -EIO; + if (i > MAX_WRITE_IOMEM_RETRY) + goto exit; + } + } while (ret); + + priv->btmtk_dev.tx_dnld_rdy = false; + +exit: + + return ret; +} + +static int btmtk_sdio_set_audio_slave(void) +{ + int ret = 0; + u8 *cmd = NULL; + u8 event[] = { 0x0E, 0x04, 0x01, 0x72, 0xFC, 0x00 }; +#ifdef MTK_CHIP_PCM /* For PCM setting */ + u8 cmd_pcm[] = { 0x72, 0xFC, 0x04, 0x03, 0x10, 0x00, 0x4A }; +#if SUPPORT_MT7668 + u8 cmd_7668[] = { 0x72, 0xFC, 0x04, 0x03, 0x10, 0x00, 0x4A }; +#endif +#if SUPPORT_MT7663 + u8 cmd_7663[] = { 0x72, 0xFC, 0x04, 0x49, 0x00, 0x80, 0x00 }; +#endif +#else /* For I2S setting */ +#if SUPPORT_MT7668 + u8 cmd_7668[] = { 0x72, 0xFC, 0x04, 0x03, 0x10, 0x00, 0x02 }; +#endif +#if SUPPORT_MT7663 + u8 cmd_7663[] = { 0x72, 0xFC, 0x04, 0x49, 0x00, 0x80, 0x00 }; +#endif +#endif + u8 mode = 0; + + BTMTK_INFO(); +#if SUPPORT_MT7668 + if (is_mt7668(g_card)) { + cmd = cmd_7668; + mode = 0x08; + } +#endif +#if SUPPORT_MT7663 + if (is_mt7663(g_card)) { + cmd = cmd_7663; + mode = 0x03; + } +#endif +#ifdef MTK_CHIP_PCM + if (!cmd) { + BTMTK_ERR("cmd == null, set default PCM setting"); + cmd = cmd_pcm; + mode |= 0x20; + } else + mode |= 0x10; +#endif + + BTMTK_INFO("set mode = 0x%x", mode); + + if (cmd) { + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, cmd, cmd[2] + 3, + event, sizeof(event), COMP_EVENT_TIMO); + } else + BTMTK_ERR("No any audio cmd applied!!"); + + return ret; +} + +static int btmtk_sdio_read_pin_mux_setting(u32 *value) +{ + int ret = 0; + u8 cmd[] = { 0xD1, 0xFC, 0x04, 0x54, 0x30, 0x02, 0x81 }; + u8 event[] = { 0x0E, 0x08, 0x01, 0xD1, 0xFC }; + + BTMTK_INFO(); + + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, cmd, sizeof(cmd), + event, sizeof(event), COMP_EVENT_TIMO); + + if (ret) + return ret; + + *value = (rxbuf[14] << 24) + (rxbuf[13] << 16) + (rxbuf[12] << 8) + rxbuf[11]; + BTMTK_DBG("value=%08x", *value); + return ret; +} + +static int btmtk_sdio_write_pin_mux_setting(u32 value) +{ + int ret = 0; + u8 *cmd = NULL; + u8 event[] = {0x0E, 0x04, 0x01, 0xD0, 0xFC, 0x00}; + u8 cmd_7668[] = {0xD0, 0xFC, 0x08, + 0x54, 0x30, 0x02, 0x81, 0x00, 0x00, 0x00, 0x00}; + u8 cmd_7663[] = {0xD0, 0xFC, 0x08, + 0x54, 0x50, 0x00, 0x78, 0x00, 0x10, 0x11, 0x01}; + +#if SUPPORT_MT7668 + if (is_mt7668(g_card)) + cmd = cmd_7668; +#endif +#if SUPPORT_MT7663 + if (is_mt7663(g_card)) + cmd = cmd_7663; +#endif + if (!cmd) { + BTMTK_INFO("not supported"); + return 0; + } + + BTMTK_INFO("begin, value = 0x%08x", value); + + cmd[7] = (value & 0x000000FF); + cmd[8] = ((value & 0x0000FF00) >> 8); + cmd[9] = ((value & 0x00FF0000) >> 16); + cmd[10] = ((value & 0xFF000000) >> 24); + + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, cmd, cmd[2] + 3, + event, sizeof(event), COMP_EVENT_TIMO); + + return ret; +} + +static int btmtk_sdio_set_audio_pin_mux(void) +{ + int ret = 0; + u32 pinmux = 0; + + ret = btmtk_sdio_read_pin_mux_setting(&pinmux); + if (ret) { + BTMTK_ERR("btmtk_sdio_read_pin_mux_setting error(%d)", ret); + return ret; + } + +#if SUPPORT_MT7668 + if (is_mt7668(g_card)) { + pinmux &= 0x0000FFFF; + pinmux |= 0x22220000; + } +#endif +#if SUPPORT_MT7663 + if (is_mt7663(g_card)) { + pinmux &= 0xF0000FFF; + pinmux |= 0x01111000; + } +#endif + ret = btmtk_sdio_write_pin_mux_setting(pinmux); + + if (ret) { + BTMTK_ERR("btmtk_sdio_write_pin_mux_setting error(%d)", ret); + return ret; + } + + pinmux = 0; + ret = btmtk_sdio_read_pin_mux_setting(&pinmux); + if (ret) { + BTMTK_ERR("btmtk_sdio_read_pin_mux_setting error(%d)", ret); + return ret; + } + BTMTK_INFO("confirm pinmux %04x", pinmux); + + return ret; +} + +static int btmtk_send_rom_patch(u8 *fwbuf, u32 fwlen, int mode) +{ + int ret = 0; + u8 mtksdio_packet_header[MTK_SDIO_PACKET_HEADER_SIZE] = {0}; + int stp_len = 0; + u8 mtkdata_header[MTKDATA_HEADER_SIZE] = {0}; + + int copy_len = 0; + int Datalen = fwlen; + u32 u32ReadCRValue = 0; + + + BTMTK_DBG("fwlen %d, mode = %d", fwlen, mode); + if (fwlen < Datalen) { + BTMTK_ERR("file size = %d,is not corect", fwlen); + return -ENOENT; + } + + stp_len = Datalen + MTKDATA_HEADER_SIZE; + + + mtkdata_header[0] = 0x2;/*ACL data*/ + mtkdata_header[1] = 0x6F; + mtkdata_header[2] = 0xFC; + + mtkdata_header[3] = ((Datalen+4+1)&0x00FF); + mtkdata_header[4] = ((Datalen+4+1)&0xFF00)>>8; + + mtkdata_header[5] = 0x1; + mtkdata_header[6] = 0x1; + + mtkdata_header[7] = ((Datalen+1)&0x00FF); + mtkdata_header[8] = ((Datalen+1)&0xFF00)>>8; + + mtkdata_header[9] = mode; + +/* 0 and 1 is packet length, include MTKSTP_HEADER_SIZE */ + mtksdio_packet_header[0] = + (Datalen+4+MTKSTP_HEADER_SIZE+6)&0xFF; + mtksdio_packet_header[1] = + ((Datalen+4+MTKSTP_HEADER_SIZE+6)&0xFF00)>>8; + mtksdio_packet_header[2] = 0; + mtksdio_packet_header[3] = 0; + +/* + * mtksdio_packet_header[2] and mtksdio_packet_header[3] + * are reserved + */ + BTMTK_DBG("result %02x %02x", + ((Datalen+4+MTKSTP_HEADER_SIZE+6)&0xFF00)>>8, + (Datalen+4+MTKSTP_HEADER_SIZE+6)); + + memcpy(txbuf+copy_len, mtksdio_packet_header, + MTK_SDIO_PACKET_HEADER_SIZE); + copy_len += MTK_SDIO_PACKET_HEADER_SIZE; + + memcpy(txbuf+copy_len, mtkdata_header, MTKDATA_HEADER_SIZE); + copy_len += MTKDATA_HEADER_SIZE; + + memcpy(txbuf+copy_len, fwbuf, Datalen); + copy_len += Datalen; + + BTMTK_DBG("txbuf %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + txbuf[0], txbuf[1], txbuf[2], txbuf[3], txbuf[4], + txbuf[5], txbuf[6], txbuf[7], txbuf[8], txbuf[9]); + + + ret = btmtk_sdio_readl(CHIER, &u32ReadCRValue); + BTMTK_DBG("CHIER u32ReadCRValue %x, ret %d", u32ReadCRValue, ret); + + ret = btmtk_sdio_readl(CHLPCR, &u32ReadCRValue); + BTMTK_DBG("CHLPCR u32ReadCRValue %x, ret %d", u32ReadCRValue, ret); + + ret = btmtk_sdio_readl(CHISR, &u32ReadCRValue); + BTMTK_DBG("0CHISR u32ReadCRValue %x, ret %d", u32ReadCRValue, ret); + ret = btmtk_sdio_readl(CHISR, &u32ReadCRValue); + BTMTK_DBG("00CHISR u32ReadCRValue %x, ret %d", u32ReadCRValue, ret); + + btmtk_sdio_send_tx_data(txbuf, copy_len); + + ret = btmtk_sdio_recv_rx_data(); + + return ret; +} + +/* + * type: cmd:1, ACL:2 + * ------------------------------------------------- + * mtksdio hedaer 4 byte| wmt header | + * + * + * data len should less than 512-4-4 + */ +static int btmtk_sdio_send_wohci(u8 type, u32 len, u8 *data) +{ + u32 ret = 0; + u32 push_in_data_len = 0; + u32 MultiBluckCount = 0; + u32 redundant = 0; + u8 mtk_wmt_header[MTKWMT_HEADER_SIZE] = {0}; + u8 mtksdio_packet_header[MTK_SDIO_PACKET_HEADER_SIZE] = {0}; + u8 mtk_tx_data[512] = {0}; + + mtk_wmt_header[0] = type; + mtk_wmt_header[1] = 0x6F; + mtk_wmt_header[2] = 0xFC; + mtk_wmt_header[3] = len; + + mtksdio_packet_header[0] = + (len+MTKWMT_HEADER_SIZE+MTK_SDIO_PACKET_HEADER_SIZE)&0xFF; + mtksdio_packet_header[1] = + ((len+MTKWMT_HEADER_SIZE+MTK_SDIO_PACKET_HEADER_SIZE)&0xFF00) + >>8; + mtksdio_packet_header[2] = 0; + mtksdio_packet_header[3] = 0; +/* + * mtksdio_packet_header[2] and mtksdio_packet_header[3] + * are reserved + */ + + memcpy(mtk_tx_data, mtksdio_packet_header, + sizeof(mtksdio_packet_header)); + push_in_data_len += sizeof(mtksdio_packet_header); + + memcpy(mtk_tx_data+push_in_data_len, mtk_wmt_header, + sizeof(mtk_wmt_header)); + push_in_data_len += sizeof(mtk_wmt_header); + + memcpy(mtk_tx_data+push_in_data_len, data, len); + push_in_data_len += len; + memcpy(txbuf, mtk_tx_data, push_in_data_len); + + MultiBluckCount = push_in_data_len/4; + redundant = push_in_data_len % 4; + if (redundant) + push_in_data_len = (MultiBluckCount+1)*4; + + ret = btmtk_sdio_writesb(CTDR, txbuf, push_in_data_len); + BTMTK_INFO("return 0x%0x", ret); + return ret; +} + +/* + * data event: + * return + * 0: + * patch download is not complete/get patch semaphore fail + * 1: + * patch download is complete by others + * 2 + * patch download is not coplete + * 3:(for debug) + * release patch semaphore success + */ +static int btmtk_sdio_need_load_rom_patch(void) +{ + u32 ret = -1; + u8 cmd[] = {0x1, 0x17, 0x1, 0x0, 0x1}; + u8 event[] = {0x2, 0x17, 0x1, 0x0}; + + do { + ret = btmtk_sdio_send_wohci(HCI_COMMAND_PKT, sizeof(cmd), cmd); + + if (ret) { + BTMTK_ERR("btmtk_sdio_send_wohci return fail ret %d", ret); + break; + } + + ret = btmtk_sdio_recv_rx_data(); + if (ret) + break; + + if (rx_length == 12) { + if (memcmp(rxbuf+7, event, sizeof(event)) == 0) + return rxbuf[11]; + + BTMTK_ERR("receive event content is not correct, print receive data"); + btmtk_print_buffer_conent(rxbuf, rx_length); + } + } while (0); + BTMTK_ERR("return ret %d", ret); + return ret; +} + +static int btmtk_sdio_set_write_clear(void) +{ + u32 u32ReadCRValue = 0; + u32 ret = 0; + + ret = btmtk_sdio_readl(CHCR, &u32ReadCRValue); + if (ret) { + BTMTK_ERR("read CHCR error"); + ret = EINVAL; + return ret; + } + + u32ReadCRValue |= 0x00000002; + btmtk_sdio_writel(CHCR, u32ReadCRValue); + BTMTK_INFO("write CHCR 0x%08X", u32ReadCRValue); + ret = btmtk_sdio_readl(CHCR, &u32ReadCRValue); + BTMTK_INFO("read CHCR 0x%08X", u32ReadCRValue); + if (u32ReadCRValue&0x00000002) + BTMTK_INFO("write clear"); + else + BTMTK_INFO("read clear"); + + return ret; +} + +static int btmtk_sdio_set_audio(void) +{ + int ret = 0; + + ret = btmtk_sdio_set_audio_slave(); + if (ret) { + BTMTK_ERR("btmtk_sdio_set_audio_slave error(%d)", ret); + return ret; + } + + ret = btmtk_sdio_set_audio_pin_mux(); + if (ret) { + BTMTK_ERR("btmtk_sdio_set_audio_pin_mux error(%d)", ret); + return ret; + } + + return ret; +} + +static int btmtk_sdio_send_audio_slave(void) +{ + int ret = 0; + + ret = btmtk_sdio_set_audio_slave(); + if (ret) { + BTMTK_ERR("btmtk_sdio_set_audio_slave error(%d)", ret); + return ret; + } + + if (is_mt7663(g_card)) { + ret = btmtk_sdio_set_audio_pin_mux(); + if (ret) { + BTMTK_ERR("btmtk_sdio_set_audio_pin_mux error(%d)", ret); + return ret; + } + } + + return ret; +} + +static int btmtk_sdio_download_rom_patch(struct btmtk_sdio_card *card) +{ + const struct firmware *fw_firmware = NULL; + int firmwarelen, ret = 0; + u8 *fwbuf; + struct _PATCH_HEADER *patchHdr; + u16 u2HwVer = 0; + u16 u2SwVer = 0; + u32 u4PatchVer = 0; + u32 u4FwVersion = 0; + u32 u4ChipId = 0; + u32 u32ReadCRValue = 0; + u8 patch_status = 0; + char strDateTime[17]; + bool load_sysram3 = false; + int retry = 20; + + ret = btmtk_sdio_set_own_back(DRIVER_OWN); + if (ret) + goto done; + + u4FwVersion = btmtk_sdio_bt_memRegister_read(FW_VERSION); + BTMTK_INFO("Fw Version 0x%x", u4FwVersion); + u4ChipId = btmtk_sdio_bt_memRegister_read(CHIP_ID); + BTMTK_INFO("Chip Id 0x%x", u4ChipId); + + if ((u4FwVersion & 0xff) == 0xff) { + BTMTK_ERR("failed ! wrong fw version : 0x%x", u4FwVersion); + ret = -ENODEV; + goto done; + + } else { + u8 uFirmwareName[MAX_BIN_FILE_NAME_LEN] = {0}; + + /* Bin filename format : "mt$$$$_patch_e%.bin" */ + /* $$$$ : chip id */ + /* % : fw version + 1 (in HEX) */ + snprintf(uFirmwareName, MAX_BIN_FILE_NAME_LEN, "mt%04x_patch_e%x_hdr.bin", + u4ChipId & 0xffff, (u4FwVersion & 0x0ff) + 1); + BTMTK_INFO("request_firmware(firmware name %s)", uFirmwareName); + ret = request_firmware(&fw_firmware, uFirmwareName, + &card->func->dev); + + if ((ret < 0) || !fw_firmware) { + BTMTK_ERR("request_firmware(firmware name %s) failed, error code = %d", + uFirmwareName, + ret); + ret = -ENOENT; + goto done; + } + } + memset(fw_version_str, 0, FW_VERSION_BUF_SIZE); + if ((fw_firmware->data[8] >= '0') && (fw_firmware->data[8] <= '9')) + memcpy(fw_version_str, fw_firmware->data, FW_VERSION_SIZE - 1); + else + sprintf(fw_version_str, "%.4s-%.2s-%.2s.%.1s.%.2s.%.1s.%.1s.%.2s", + fw_firmware->data, fw_firmware->data + 4, fw_firmware->data + 6, + fw_firmware->data + 8, fw_firmware->data + 9, + fw_firmware->data + 11, fw_firmware->data + 12, + fw_firmware->data + 13); + +#if SUPPORT_MT7668 + if (is_mt7668(g_card)) + load_sysram3 = + (fw_firmware->size > (PATCH_INFO_SIZE + PATCH_LEN_ILM)) + ? true : false; +#endif + + do { + patch_status = btmtk_sdio_need_load_rom_patch(); + BTMTK_DBG("patch_status %d", patch_status); + + if (patch_status > PATCH_NEED_DOWNLOAD || patch_status < 0) { + BTMTK_ERR("patch_status error"); + ret = -ENODEV; + goto done; + } else if (patch_status == PATCH_READY) { + BTMTK_INFO("patch is ready no need load patch again"); + if (!load_sysram3) + goto patch_end; + else + goto sysram3; + } else if (patch_status == PATCH_IS_DOWNLOAD_BY_OTHER) { + msleep(100); + retry--; + } else if (patch_status == PATCH_NEED_DOWNLOAD) { + if (is_mt7663(g_card)) { + if (btmtk_sdio_send_wmt_cfg()) + BTMTK_ERR("send wmt cfg failed!"); + } + break; /* Download ROM patch directly */ + } + } while (retry > 0); + + if (patch_status == PATCH_IS_DOWNLOAD_BY_OTHER) { + BTMTK_WARN("Hold by another fun more than 2 seconds"); + ret = -ENODEV; + goto done; + } + + fwbuf = (u8 *)fw_firmware->data; + + /*Display rom patch info*/ + patchHdr = (struct _PATCH_HEADER *)fwbuf; + memcpy(strDateTime, patchHdr->ucDateTime, sizeof(patchHdr->ucDateTime)); + strDateTime[16] = '\0'; + u2HwVer = patchHdr->u2HwVer; + u2SwVer = patchHdr->u2SwVer; + u4PatchVer = patchHdr->u4PatchVer; + + BTMTK_INFO("[btmtk] =============== Patch Info =============="); + BTMTK_INFO("[btmtk] Built Time = %s", strDateTime); + BTMTK_INFO("[btmtk] Hw Ver = 0x%x", + ((u2HwVer & 0x00ff) << 8) | ((u2HwVer & 0xff00) >> 8)); + BTMTK_INFO("[btmtk] Sw Ver = 0x%x", + ((u2SwVer & 0x00ff) << 8) | ((u2SwVer & 0xff00) >> 8)); + BTMTK_INFO("[btmtk] Patch Ver = 0x%04x", + ((u4PatchVer & 0xff000000) >> 24) | + ((u4PatchVer & 0x00ff0000) >> 16)); + + BTMTK_INFO("[btmtk] Platform = %c%c%c%c", + patchHdr->ucPlatform[0], + patchHdr->ucPlatform[1], + patchHdr->ucPlatform[2], + patchHdr->ucPlatform[3]); + BTMTK_INFO("[btmtk] Patch start addr = %02x", patchHdr->u2PatchStartAddr); + BTMTK_INFO("[btmtk] ========================================="); + + firmwarelen = load_sysram3 ? + PATCH_LEN_ILM : (fw_firmware->size - PATCH_INFO_SIZE); + + BTMTK_INFO("loading ILM rom patch..."); + ret = btmtk_sdio_download_partial_rom_patch(fwbuf, firmwarelen); + BTMTK_INFO("loading ILM rom patch... Done"); + + if (btmtk_sdio_need_load_rom_patch() == PATCH_READY) { + BTMTK_INFO("patchdownload is done by BT"); + } else { + /* TODO: Need error handling here*/ + BTMTK_WARN("patchdownload download by BT, not ready"); + } + + /* CHIP_RESET, ROM patch would be reactivated. + * Currently, wmt reset is only for ILM rom patch, and there are also + * some preparations need to be done in FW for loading sysram3 patch... + */ + ret = btmtk_sdio_send_wmt_reset(); + if (ret) + goto done; + +sysram3: + if (load_sysram3) { + firmwarelen = fw_firmware->size - PATCH_INFO_SIZE + - PATCH_LEN_ILM - PATCH_INFO_SIZE; + fwbuf = (u8 *)fw_firmware->data + PATCH_INFO_SIZE + + PATCH_LEN_ILM; + BTMTK_INFO("loading sysram3 rom patch..."); + ret = btmtk_sdio_download_partial_rom_patch(fwbuf, firmwarelen); + BTMTK_INFO("loading sysram3 rom patch... Done"); + } + +patch_end: + ret = btmtk_sdio_readl(0, &u32ReadCRValue); + BTMTK_INFO("read chipid = %x", u32ReadCRValue); + + /*Set interrupt output*/ + ret = btmtk_sdio_writel(CHIER, FIRMWARE_INT|TX_FIFO_OVERFLOW | + FW_INT_IND_INDICATOR | TX_COMPLETE_COUNT | + TX_UNDER_THOLD | TX_EMPTY | RX_DONE); + if (ret) { + BTMTK_ERR("Set interrupt output fail(%d)", ret); + ret = -EIO; + goto done; + } + + /*enable interrupt output*/ + ret = btmtk_sdio_writel(CHLPCR, C_FW_INT_EN_SET); + if (ret) { + BTMTK_ERR("enable interrupt output fail(%d)", ret); + ret = -EIO; + goto done; + } + + btmtk_sdio_set_write_clear(); + +done: + btmtk_sdio_set_own_back(FW_OWN); + + if (fw_firmware) + release_firmware(fw_firmware); + + if (!ret) + BTMTK_INFO("success"); + else + BTMTK_INFO("fail"); + + return ret; +} + +static int btmtk_sdio_download_partial_rom_patch(u8 *fwbuf, int firmwarelen) +{ + int ret = 0; + int RedundantSize = 0; + u32 bufferOffset = 0; + + BTMTK_INFO("Downloading FW image (%d bytes)", firmwarelen); + + fwbuf += PATCH_INFO_SIZE; + BTMTK_DBG("PATCH_HEADER size %d", PATCH_INFO_SIZE); + + RedundantSize = firmwarelen; + BTMTK_DBG("firmwarelen %d", firmwarelen); + + do { + bufferOffset = firmwarelen - RedundantSize; + + if (RedundantSize == firmwarelen && + RedundantSize >= PATCH_DOWNLOAD_SIZE) + ret = btmtk_send_rom_patch(fwbuf + bufferOffset, + PATCH_DOWNLOAD_SIZE, + SDIO_PATCH_DOWNLOAD_FIRST); + else if (RedundantSize == firmwarelen) + ret = btmtk_send_rom_patch(fwbuf + bufferOffset, + RedundantSize, + SDIO_PATCH_DOWNLOAD_FIRST); + else if (RedundantSize < PATCH_DOWNLOAD_SIZE) { + ret = btmtk_send_rom_patch(fwbuf + bufferOffset, + RedundantSize, + SDIO_PATCH_DOWNLOAD_END); + BTMTK_DBG("patch downoad last patch part"); + } else + ret = btmtk_send_rom_patch(fwbuf + bufferOffset, + PATCH_DOWNLOAD_SIZE, + SDIO_PATCH_DOWNLOAD_CON); + + RedundantSize -= PATCH_DOWNLOAD_SIZE; + + if (ret) { + BTMTK_ERR("btmtk_send_rom_patch fail"); + return ret; + } + BTMTK_DBG("RedundantSize %d", RedundantSize); + if (RedundantSize <= 0) { + BTMTK_DBG("patch downoad finish"); + break; + } + } while (1); + + return ret; +} + +static void btmtk_sdio_close_coredump_file(void) +{ + BTMTK_DBG("vfs_fsync"); + + if (g_card->bt_cfg.save_fw_dump_in_kernel && fw_dump_file) + vfs_fsync(fw_dump_file, 0); + + if (fw_dump_file) { + BTMTK_INFO("close file %s", g_card->bt_cfg.fw_dump_file_name); + if (g_card->bt_cfg.save_fw_dump_in_kernel) + filp_close(fw_dump_file, NULL); + fw_dump_file = NULL; + } else { + BTMTK_WARN("fw_dump_file is NULL can't close file %s", g_card->bt_cfg.fw_dump_file_name); + } +} + +static void btmtk_sdio_stop_wait_dump_complete_thread(void) +{ + if (IS_ERR(wait_dump_complete_tsk) || wait_dump_complete_tsk == NULL) + BTMTK_ERR("wait_dump_complete_tsk is error"); + else { + kthread_stop(wait_dump_complete_tsk); + wait_dump_complete_tsk = NULL; + } +} + +static int btmtk_sdio_card_to_host(struct btmtk_private *priv, const u8 *event, const int event_len, + int add_spec_header) +/*event: check event which want to compare*/ +/*return value: -x fail, 0 success*/ +{ + u16 buf_len = 0; + int ret = 0; + struct sk_buff *skb = NULL; + struct sk_buff *fops_skb = NULL; + u32 type; + u32 fourbalignment_len = 0; + u32 dump_len = 0; + char *core_dump_end = NULL; + int i = 0; + u16 retry = 0; + u32 u32ReadCRValue = 0; + u8 is_fwdump = 0, tail_len = 0; + int fops_state = 0; + static u8 picus_blocking_warn; + static u8 fwdump_blocking_warn; + + if (rx_length > (MTK_SDIO_PACKET_HEADER_SIZE + 1)) { + buf_len = rx_length - (MTK_SDIO_PACKET_HEADER_SIZE + 1); + } else { + BTMTK_ERR("rx_length error(%d)", rx_length); + return -EINVAL; + } + + /* Core dump packet format: + * A0 00 00 00 80 AA BB CC 02 6F FC YY ZZ XX ... XX 00 00 00 00 + * A0 00 00 00: SDIO Header + * 80 AA BB CC: STP Header + * 02 6F FC: Core dump header + * YY ZZ: Coredump length + * 00 00 00 00: STP CRC and aligment to multiple of 4 by SDIO + */ + if (rx_length > (COREDUMP_PACKET_HEADER_LEN) && + rxbuf[SDIO_HEADER_LEN] == 0x80 && + rxbuf[SDIO_HEADER_LEN + STP_HEADER_LEN + 1] == 0x6F && + rxbuf[SDIO_HEADER_LEN + STP_HEADER_LEN + 2] == 0xFC) { + + dump_len = rxbuf[SDIO_HEADER_LEN + STP_HEADER_LEN + 3] + + (rxbuf[SDIO_HEADER_LEN + STP_HEADER_LEN + 4] << 8); + BTMTK_DBG("get dump len %d", dump_len); + + dump_data_counter++; + /* Total dump length to fw_dump_files */ + dump_data_length += dump_len; + is_fwdump = 1; + + if (dump_data_counter % 1000 == 0) + BTMTK_WARN("coredump on-going, total_packet = %d, total_length = %d", + dump_data_counter, dump_data_length); + + if (dump_data_counter < PRINT_DUMP_COUNT) { + BTMTK_WARN("dump %d %s", + dump_data_counter, + &rxbuf[COREDUMP_PACKET_HEADER_LEN]); + /* release mode do reset dongle if print dump finish */ + } else if (!g_card->bt_cfg.support_full_fw_dump && + dump_data_counter == PRINT_DUMP_COUNT) { + /* create dump file fail and is user mode */ + BTMTK_INFO("user mode, do reset after print dump done %d", dump_data_counter); + picus_blocking_warn = 0; + fwdump_blocking_warn = 0; + btmtk_sdio_close_coredump_file(); + btmtk_sdio_stop_wait_dump_complete_thread(); + goto exit; + } + + if (dump_data_counter == 1) { + g_card->dongle_state = BT_SDIO_DONGLE_STATE_FW_DUMP; + btmtk_sdio_hci_snoop_print(); + BTMTK_INFO("create btmtk_sdio_wait_dump_complete_thread"); + wait_dump_complete_tsk = kthread_run(btmtk_sdio_wait_dump_complete_thread, + NULL, "btmtk_sdio_wait_dump_complete_thread"); + + msleep(100); + if (!wait_dump_complete_tsk) + BTMTK_ERR("wait_dump_complete_tsk is NULL"); + + btmtk_sdio_notify_wlan_remove_start(); + btmtk_sdio_set_no_fw_own(g_priv, TRUE); + + if (g_card->bt_cfg.save_fw_dump_in_kernel) { + BTMTK_WARN("open file %s", + g_card->bt_cfg.fw_dump_file_name); + fw_dump_file = filp_open(g_card->bt_cfg.fw_dump_file_name, O_RDWR | O_CREAT, 0644); + + if (!(IS_ERR(fw_dump_file))) { + BTMTK_WARN("open file %s success", + g_card->bt_cfg.fw_dump_file_name); + } else { + BTMTK_WARN("open file %s fail", + g_card->bt_cfg.fw_dump_file_name); + fw_dump_file = NULL; + } + + if (fw_dump_file && fw_dump_file->f_op == NULL) { + BTMTK_WARN("%s fw_dump_file->f_op is NULL, close", + g_card->bt_cfg.fw_dump_file_name); + filp_close(fw_dump_file, NULL); + fw_dump_file = NULL; + } + + if (fw_dump_file && fw_dump_file->f_op->write == NULL) { + BTMTK_WARN("%s fw_dump_file->f_op->write is NULL, close", + g_card->bt_cfg.fw_dump_file_name); + filp_close(fw_dump_file, NULL); + fw_dump_file = NULL; + } + } + } + + if (g_card->bt_cfg.save_fw_dump_in_kernel && (dump_len > 0) + && fw_dump_file && fw_dump_file->f_op && fw_dump_file->f_op->write) + fw_dump_file->f_op->write(fw_dump_file, &rxbuf[COREDUMP_PACKET_HEADER_LEN], + dump_len, &fw_dump_file->f_pos); + + if (skb_queue_len(&g_card->fwlog_fops_queue) < FWLOG_ASSERT_QUEUE_COUNT) { + /* This is coredump data, save coredump data to picus_queue */ + BTMTK_DBG("Receive coredump data, move data to fwlog queue for picus"); + /* Save coredump data to picus_queue from 6F FC, minus ACL header */ + btmtk_sdio_dispatch_fwlog(&rxbuf[SDIO_HEADER_LEN + STP_HEADER_LEN + 1], + dump_len + COREDUMP_HEADER_LEN - HCI_TYPE_LEN); + fwdump_blocking_warn = 0; + } else if (fwdump_blocking_warn == 0) { + fwdump_blocking_warn = 1; + BTMTK_WARN("btmtk_sdio FW dump queue size is full"); + } + + /* Modify header to ACL format, handle is 0xFFF0 + * Core dump header: + * 80 AA BB CC DD 6F FC XX XX XX ...... + * 80 AA BB CC -> STP header, droped, 4 bytes extra at tailed for CRC + * DD -> 02 (ACL TYPE) + * 6F FC -> FF F0 + */ + rxbuf[SDIO_HEADER_LEN + 4] = HCI_ACLDATA_PKT; + rxbuf[SDIO_HEADER_LEN + 5] = 0xFF; + rxbuf[SDIO_HEADER_LEN + 6] = 0xF0; + + if (dump_len >= strlen(FW_DUMP_END_EVENT)) { + core_dump_end = strstr(&rxbuf[SDIO_HEADER_LEN + 10], + FW_DUMP_END_EVENT); + + if (core_dump_end) { + BTMTK_WARN("core_dump_end %s, total_packet = %d, total_length = %d", + core_dump_end, dump_data_counter, dump_data_length); + BTMTK_WARN("rxbuf = %02x %02x %02x", + rxbuf[4], rxbuf[5], rxbuf[6]); + sdio_claim_host(g_card->func); + sdio_release_irq(g_card->func); + sdio_release_host(g_card->func); + dump_data_counter = 0; + dump_data_length = 0; + picus_blocking_warn = 0; + fwdump_blocking_warn = 0; + btmtk_sdio_close_coredump_file(); + btmtk_sdio_stop_wait_dump_complete_thread(); + } + } + } else if (rx_length > (SDIO_HEADER_LEN + 4) && + ((rxbuf[SDIO_HEADER_LEN] == 0x04 && + rxbuf[SDIO_HEADER_LEN + 1] == 0xFF && + rxbuf[SDIO_HEADER_LEN + 3] == 0x50) || + (rxbuf[SDIO_HEADER_LEN] == 0x02 && + rxbuf[SDIO_HEADER_LEN + 1] == 0xFF && + rxbuf[SDIO_HEADER_LEN + 2] == 0x05))) { + /*receive picus data to fwlog_queue*/ + if (rxbuf[SDIO_HEADER_LEN] == 0x04) { + dump_len = rxbuf[SDIO_HEADER_LEN + 2] - 1; + buf_len = dump_len + 3; + } else { + dump_len = ((rxbuf[SDIO_HEADER_LEN + 4] & 0x0F) << 8) + rxbuf[SDIO_HEADER_LEN + 3]; + buf_len = dump_len + 4; + } + BTMTK_DBG("This is debug log data, length = %d", dump_len); + if (rx_length < (buf_len + MTK_SDIO_PACKET_HEADER_SIZE + 1)) + goto data_err; + btmtk_sdio_dispatch_fwlog(&rxbuf[MTK_SDIO_PACKET_HEADER_SIZE + 1], buf_len); + btmtk_sdio_hci_snoop_save(FW_LOG_PKT, &rxbuf[MTK_SDIO_PACKET_HEADER_SIZE + 1], buf_len); + goto exit; + } else if (rxbuf[SDIO_HEADER_LEN] == 0x04 + && rxbuf[SDIO_HEADER_LEN + 1] == 0x0E + && rxbuf[SDIO_HEADER_LEN + 2] == 0x04 + && rxbuf[SDIO_HEADER_LEN + 3] == 0x01 + && rxbuf[SDIO_HEADER_LEN + 4] == 0x02 + && rxbuf[SDIO_HEADER_LEN + 5] == 0xFD) { + BTMTK_ERR("This is btclk event, status:%02x", rxbuf[SDIO_HEADER_LEN + 6]); + buf_len = rx_length - (MTK_SDIO_PACKET_HEADER_SIZE + 1); + goto exit; + } else if (rx_length >= (SDIO_HEADER_LEN + 13) + && rxbuf[SDIO_HEADER_LEN] == 0x04 + && rxbuf[SDIO_HEADER_LEN + 1] == 0xFF + && rxbuf[SDIO_HEADER_LEN + 3] == 0x41) { + /* receive BT clock data */ + BTMTK_DBG("This is btclk data - %d", rx_length); + BTMTK_DBG("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + rxbuf[SDIO_HEADER_LEN + 0], rxbuf[SDIO_HEADER_LEN + 1], rxbuf[SDIO_HEADER_LEN + 2], + rxbuf[SDIO_HEADER_LEN + 3], rxbuf[SDIO_HEADER_LEN + 4], rxbuf[SDIO_HEADER_LEN + 5], + rxbuf[SDIO_HEADER_LEN + 6], rxbuf[SDIO_HEADER_LEN + 7], rxbuf[SDIO_HEADER_LEN + 8], + rxbuf[SDIO_HEADER_LEN + 9], rxbuf[SDIO_HEADER_LEN + 10], rxbuf[SDIO_HEADER_LEN + 11], + rxbuf[SDIO_HEADER_LEN + 12], rxbuf[SDIO_HEADER_LEN + 13], rxbuf[SDIO_HEADER_LEN + 14], + rxbuf[SDIO_HEADER_LEN + 15], rxbuf[SDIO_HEADER_LEN + 16], rxbuf[SDIO_HEADER_LEN + 17]); + + if (rxbuf[SDIO_HEADER_LEN + 12] == 0x0) { + u32 intra_clk = 0, clk = 0; + + memcpy(&intra_clk, &rxbuf[SDIO_HEADER_LEN + 6], 2); + memcpy(&clk, &rxbuf[SDIO_HEADER_LEN + 8], 4); + + LOCK_UNSLEEPABLE_LOCK(&stereo_spin_lock); + stereo_clk.fw_clk = (u64)(intra_clk + (clk & 0x0FFFFFFC) * 3125 / 10); + stereo_clk.sys_clk = sys_clk_tmp; + UNLOCK_UNSLEEPABLE_LOCK(&stereo_spin_lock); + BTMTK_DBG("btclk intra:%x, clk:%x, fw_clk:%llu, sysclk: %llu", + intra_clk, clk, stereo_clk.fw_clk, stereo_clk.sys_clk); + } else { + BTMTK_WARN("No ACL CONNECTION(%d), disable event and interrupt", + rxbuf[SDIO_HEADER_LEN + 12]); + } + + buf_len = rx_length - (MTK_SDIO_PACKET_HEADER_SIZE + 1); + goto exit; + } else if (rxbuf[SDIO_HEADER_LEN] == HCI_EVENT_PKT && + rxbuf[SDIO_HEADER_LEN + 1] == 0x0E && + rxbuf[SDIO_HEADER_LEN + 4] == 0x03 && + rxbuf[SDIO_HEADER_LEN + 5] == 0x0C && + rxbuf[SDIO_HEADER_LEN + 6] == 0x00) { + BTMTK_INFO("get hci reset"); + get_hci_reset = 1; + } + + btmtk_print_buffer_conent(rxbuf, rx_length); + + /* Read the length of data to be transferred , not include pkt type*/ + buf_len = rx_length - (MTK_SDIO_PACKET_HEADER_SIZE + 1); + + BTMTK_DBG("buf_len : %d", buf_len); + if (rx_length <= SDIO_HEADER_LEN) { + BTMTK_WARN("invalid packet length: %d", buf_len); + ret = -EINVAL; + goto exit; + } + + /* Allocate buffer */ + /* rx_length = num_blocks * blksz + BTSDIO_DMA_ALIGN*/ + skb = bt_skb_alloc(rx_length, GFP_ATOMIC); + if (skb == NULL) { + BTMTK_WARN("No free skb"); + ret = -ENOMEM; + goto exit; + } + + BTMTK_DBG("rx_length %d,buf_len %d", rx_length, buf_len); + + if (is_fwdump == 0) { + memcpy(skb->data, &rxbuf[MTK_SDIO_PACKET_HEADER_SIZE + 1], buf_len); + type = rxbuf[MTK_SDIO_PACKET_HEADER_SIZE]; + } else { + memcpy(skb->data, &rxbuf[MTK_SDIO_PACKET_HEADER_SIZE + 5], buf_len - 4); + type = rxbuf[MTK_SDIO_PACKET_HEADER_SIZE + 4]; + } + + switch (type) { + case HCI_ACLDATA_PKT: + BTMTK_DBG("data[2] 0x%02x, data[3] 0x%02x" + , skb->data[2], skb->data[3]); + buf_len = skb->data[2] + skb->data[3] * 256 + 4; + BTMTK_DBG("acl buf_len %d", buf_len); + break; + case HCI_SCODATA_PKT: + buf_len = skb->data[2] + 3; + break; + case HCI_EVENT_PKT: + buf_len = skb->data[1] + 2; + break; + default: + BTSDIO_INFO_RAW(skb->data, buf_len, "CHISR(0x%08X) skb->data(type %d):", reg_CHISR, type); + + for (retry = 0; retry < 5; retry++) { + ret = btmtk_sdio_readl(SWPCDBGR, &u32ReadCRValue); + BTMTK_INFO("ret %d, SWPCDBGR 0x%x, and not sleep!", ret, u32ReadCRValue); + } + btmtk_sdio_print_debug_sr(); + + /* trigger fw core dump */ + FOPS_MUTEX_LOCK(); + fops_state = btmtk_fops_get_state(); + FOPS_MUTEX_UNLOCK(); + if (fops_state == BTMTK_FOPS_STATE_OPENED) + btmtk_sdio_trigger_fw_assert(); + ret = -EINVAL; + goto exit; + } + + if (buf_len > MTK_RXDATA_SIZE) { + BTMTK_ERR("buf_len %d is invalid, more than %d", buf_len, MTK_RXDATA_SIZE); + ret = -EINVAL; + goto exit; + } + + if ((buf_len >= sizeof(READ_ADDRESS_EVENT)) + && (event_compare_status == BTMTK_SDIO_EVENT_COMPARE_STATE_NEED_COMPARE)) { + if ((memcmp(skb->data, READ_ADDRESS_EVENT, sizeof(READ_ADDRESS_EVENT)) == 0) && (buf_len == 12)) { + for (i = 0; i < BD_ADDRESS_SIZE; i++) + g_card->bdaddr[i] = skb->data[6 + i]; + + BTMTK_DBG("GET TV BDADDR = %02X:%02X:%02X:%02X:%02X:%02X", + g_card->bdaddr[0], g_card->bdaddr[1], g_card->bdaddr[2], + g_card->bdaddr[3], g_card->bdaddr[4], g_card->bdaddr[5]); + + /* + * event_compare_status = + * BTMTK_SDIO_EVENT_COMPARE_STATE_COMPARE_SUCCESS; + */ + } else + BTMTK_DBG("READ_ADDRESS_EVENT compare fail buf_len %d", buf_len); + } + + if (event_compare_status == BTMTK_SDIO_EVENT_COMPARE_STATE_NEED_COMPARE) { + if (buf_len >= event_need_compare_len) { + if (memcmp(skb->data, event_need_compare, event_need_compare_len) == 0) { + event_compare_status = BTMTK_SDIO_EVENT_COMPARE_STATE_COMPARE_SUCCESS; + BTMTK_DBG("compare success"); + /* Drop by driver, don't send to stack */ + goto exit; + + } else { + BTMTK_DBG("%s compare fail", __func__); + BTSDIO_INFO_RAW(event_need_compare, event_need_compare_len, + "%s: event_need_compare:", __func__); + BTSDIO_INFO_RAW(skb->data, buf_len, + "%s: skb->data:", __func__); + } + } + } + + if (is_fwdump == 0) { + btmtk_sdio_hci_snoop_save(type, skb->data, buf_len); + btmtk_sdio_dispatch_data_bluetooth_kpi(&rxbuf[MTK_SDIO_PACKET_HEADER_SIZE], buf_len + 1, 0); + } + +#if 0 + /* to drop picus related event after save event, don't send picus event to host, + * because host will trace this event as other host cmd's event, + * it will cause command timeout + */ + if ((skb->data[3] == 0x5F || skb->data[3] == 0xBE) && skb->data[4] == 0xFC) { + BTSDIO_INFO_RAW(skb->data, buf_len, "%s: discard picus related event:", __func__); + goto exit; + } +#endif + + fops_skb = bt_skb_alloc(buf_len, GFP_ATOMIC); + if (fops_skb == NULL) { + BTMTK_WARN("No free fops_skb"); + ret = -ENOMEM; + goto exit; + } + + bt_cb(fops_skb)->pkt_type = type; + memcpy(fops_skb->data, skb->data, buf_len); + + fops_skb->len = buf_len; + LOCK_UNSLEEPABLE_LOCK(&(metabuffer.spin_lock)); + skb_queue_tail(&g_card->fops_queue, fops_skb); + if (skb_queue_empty(&g_card->fops_queue)) + BTMTK_INFO("fops_queue is empty"); + UNLOCK_UNSLEEPABLE_LOCK(&(metabuffer.spin_lock)); + + wake_up_interruptible(&inq); + +exit: + if (skb) { + BTMTK_DBG("fail free skb"); + kfree_skb(skb); + } + + if (is_fwdump == 1) { + /* + * This is a fw issue + * Fw will send some bytes extra 0x00 at tail of coredump packet + * It will cause alignment failed + * Workaround is that use buf_len with bytes extra 0x00 added + * bytes extra 0x00 = Total length - buf_len - header length + * 9 = 4(SDIO header) + 4(STP header) + 1(type) + */ + tail_len = rx_length - buf_len - 9; + buf_len += (4 + tail_len); + } + buf_len += 1; + if (buf_len % 4) + fourbalignment_len = buf_len + 4 - (buf_len % 4); + else + fourbalignment_len = buf_len; + + if (rx_length < fourbalignment_len) + goto data_err; + + rx_length -= fourbalignment_len; + + if (rx_length > (MTK_SDIO_PACKET_HEADER_SIZE)) { + memcpy(&rxbuf[MTK_SDIO_PACKET_HEADER_SIZE], + &rxbuf[MTK_SDIO_PACKET_HEADER_SIZE + fourbalignment_len], + rx_length - MTK_SDIO_PACKET_HEADER_SIZE); + } + + BTMTK_DBG("ret %d, rx_length, %d,fourbalignment_len %d <--", + ret, rx_length, fourbalignment_len); + + return ret; + +data_err: + BTMTK_ERR("data error!!! discard rxbuf:"); + BTSDIO_INFO_RAW(rxbuf, rx_length, "rxbuf"); + rx_length = MTK_SDIO_PACKET_HEADER_SIZE; + return -EINVAL; +} + +static int btmtk_sdio_process_int_status( + struct btmtk_private *priv) +{ + int ret = 0; + u32 u32rxdatacount = 0; + u32 u32ReadCRValue = 0; + btmtk_sdio_timestamp(BTMTK_SDIO_RX_CHECKPOINT_RX_START); + + ret = btmtk_sdio_readl(CHISR, &u32ReadCRValue); + BTMTK_DBG("CHISR 0x%08x", u32ReadCRValue); + if (u32ReadCRValue & FIRMWARE_INT_BIT15) { + btmtk_sdio_set_no_fw_own(g_priv, TRUE); + btmtk_sdio_writel(CHISR, FIRMWARE_INT_BIT15); + BTMTK_DBG("CHISR 0x%08x", u32ReadCRValue); + } + + BTMTK_DBG("check TX_EMPTY CHISR 0x%08x", u32ReadCRValue); + if (TX_EMPTY&u32ReadCRValue) { + ret = btmtk_sdio_writel(CHISR, (TX_EMPTY | TX_COMPLETE_COUNT)); + priv->btmtk_dev.tx_dnld_rdy = true; + BTMTK_DBG("set tx_dnld_rdy 1"); + } + + if (RX_DONE&u32ReadCRValue) + ret = btmtk_sdio_recv_rx_data(); + + if (ret == 0) { + btmtk_sdio_timestamp(BTMTK_SDIO_RX_CHECKPOINT_RX_DONE); + while (rx_length > (MTK_SDIO_PACKET_HEADER_SIZE)) { + btmtk_sdio_card_to_host(priv, NULL, -1, 0); + u32rxdatacount++; + BTMTK_DBG("u32rxdatacount %d, rx_length %d", + u32rxdatacount, rx_length); + } + } + + btmtk_sdio_timestamp(BTMTK_SDIO_RX_CHECKPOINT_ENABLE_INTR); + ret = btmtk_sdio_enable_interrupt(1); + + return ret; +} + +static void btmtk_sdio_interrupt(struct sdio_func *func) +{ + struct btmtk_private *priv; + struct btmtk_sdio_card *card; + + card = sdio_get_drvdata(func); + + if (!card) + return; + + + if (!card->priv) + return; + + btmtk_sdio_timestamp(BTMTK_SDIO_RX_CHECKPOINT_INTR); + priv = card->priv; + btmtk_sdio_enable_interrupt(0); + + btmtk_interrupt(priv); +} + +static int btmtk_sdio_register_dev(struct btmtk_sdio_card *card) +{ + struct sdio_func *func; + u8 u8ReadCRValue = 0; + u8 reg; + int ret = 0; + + if (!card || !card->func) { + BTMTK_ERR("Error: card or function is NULL!"); + ret = -EINVAL; + goto failed; + } + + func = card->func; + + sdio_claim_host(func); + + ret = sdio_enable_func(func); + sdio_release_host(g_card->func); + if (ret) { + BTMTK_ERR("sdio_enable_func() failed: ret=%d", ret); + ret = -EIO; + goto failed; + } + + btmtk_sdio_readb(SDIO_CCCR_IENx, &u8ReadCRValue); + BTMTK_INFO("before claim irq read SDIO_CCCR_IENx %x, func num %d", + u8ReadCRValue, func->num); + + sdio_claim_host(g_card->func); + ret = sdio_claim_irq(func, btmtk_sdio_interrupt); + sdio_release_host(g_card->func); + if (ret) { + BTMTK_ERR("sdio_claim_irq failed: ret=%d", ret); + ret = -EIO; + goto disable_func; + } + BTMTK_INFO("sdio_claim_irq success: ret=%d", ret); + + btmtk_sdio_readb(SDIO_CCCR_IENx, &u8ReadCRValue); + BTMTK_INFO("after claim irq read SDIO_CCCR_IENx %x", u8ReadCRValue); + + sdio_claim_host(g_card->func); + ret = sdio_set_block_size(card->func, SDIO_BLOCK_SIZE); + sdio_release_host(g_card->func); + if (ret) { + BTMTK_ERR("cannot set SDIO block size"); + ret = -EIO; + goto release_irq; + } + + ret = btmtk_sdio_readb(card->reg->io_port_0, ®); + if (ret < 0) { + ret = -EIO; + goto release_irq; + } + card->ioport = reg; + + ret = btmtk_sdio_readb(card->reg->io_port_1, ®); + if (ret < 0) { + ret = -EIO; + goto release_irq; + } + card->ioport |= (reg << 8); + + ret = btmtk_sdio_readb(card->reg->io_port_2, ®); + if (ret < 0) { + ret = -EIO; + goto release_irq; + } + + card->ioport |= (reg << 16); + + BTMTK_INFO("SDIO FUNC%d IO port: 0x%x", func->num, card->ioport); + + if (card->reg->int_read_to_clear) { + ret = btmtk_sdio_readb(card->reg->host_int_rsr, ®); + if (ret < 0) { + ret = -EIO; + goto release_irq; + } + ret = btmtk_sdio_writeb(card->reg->host_int_rsr, reg | 0x3f); + if (ret < 0) { + ret = -EIO; + goto release_irq; + } + + ret = btmtk_sdio_readb(card->reg->card_misc_cfg, ®); + if (ret < 0) { + ret = -EIO; + goto release_irq; + } + ret = btmtk_sdio_writeb(card->reg->card_misc_cfg, reg | 0x10); + if (ret < 0) { + ret = -EIO; + goto release_irq; + } + } + + sdio_set_drvdata(func, card); + + return 0; + +release_irq: + sdio_release_irq(func); + +disable_func: + sdio_disable_func(func); + +failed: + BTMTK_INFO("fail"); + return ret; +} + +static int btmtk_sdio_unregister_dev(struct btmtk_sdio_card *card) +{ + if (card && card->func) { + sdio_claim_host(card->func); + sdio_release_irq(card->func); + sdio_disable_func(card->func); + sdio_release_host(card->func); + sdio_set_drvdata(card->func, NULL); + } + + return 0; +} + +static int btmtk_sdio_enable_host_int(struct btmtk_sdio_card *card) +{ + int ret; + u32 read_data = 0; + + if (!card || !card->func) + return -EINVAL; + + ret = btmtk_sdio_enable_host_int_mask(card, HIM_ENABLE); + + btmtk_sdio_get_rx_unit(card); + + if (0) { + typedef int (*fp_sdio_hook)(struct mmc_host *host, + unsigned int width); + fp_sdio_hook func_sdio_hook = + (fp_sdio_hook)btmtk_kallsyms_lookup_name("mmc_set_bus_width"); + unsigned char data = 0; + + sdio_claim_host(g_card->func); + data = sdio_f0_readb(card->func, SDIO_CCCR_IF, &ret); + if (ret) + BTMTK_INFO("sdio_f0_readb ret %d", ret); + + BTMTK_INFO("sdio_f0_readb data 0x%X!", data); + + data &= ~SDIO_BUS_WIDTH_MASK; + data |= SDIO_BUS_ASYNC_INT; + card->func->card->quirks |= MMC_QUIRK_LENIENT_FN0; + + sdio_f0_writeb(card->func, data, SDIO_CCCR_IF, &ret); + if (ret) + BTMTK_INFO("sdio_f0_writeb ret %d", ret); + + BTMTK_INFO("func_sdio_hook at 0x%p!", func_sdio_hook); + if (func_sdio_hook) + func_sdio_hook(card->func->card->host, MMC_BUS_WIDTH_1); + + data = sdio_f0_readb(card->func, SDIO_CCCR_IF, &ret); + if (ret) + BTMTK_INFO("sdio_f0_readb 2 ret %d", ret); + sdio_release_host(g_card->func); + + BTMTK_INFO("sdio_f0_readb2 data 0x%X", data); + } + +/* workaround for some platform no host clock sometimes */ + + btmtk_sdio_readl(CSDIOCSR, &read_data); + BTMTK_INFO("read CSDIOCSR is 0x%X", read_data); + read_data |= 0x4; + btmtk_sdio_writel(CSDIOCSR, read_data); + BTMTK_INFO("write CSDIOCSR is 0x%X", read_data); + + return ret; +} + +static int btmtk_sdio_disable_host_int(struct btmtk_sdio_card *card) +{ + int ret; + + if (!card || !card->func) + return -EINVAL; + + ret = btmtk_sdio_disable_host_int_mask(card, HIM_DISABLE); + + return ret; +} + +static int btmtk_sdio_download_fw(struct btmtk_sdio_card *card) +{ + int ret = 0; + + BTMTK_INFO("begin"); + if (!card || !card->func) { + BTMTK_ERR("card or function is NULL!"); + return -EINVAL; + } + + sdio_claim_host(card->func); + + if (btmtk_sdio_download_rom_patch(card)) { + BTMTK_ERR("Failed to download firmware!"); + ret = -EIO; + } + sdio_release_host(card->func); + + return ret; +} + +static int btmtk_sdio_push_data_to_metabuffer( + struct ring_buffer *metabuffer, + char *data, + int len, + u8 type, + bool use_type) +{ + int remainLen = 0; + + if (metabuffer->write_p >= metabuffer->read_p) + remainLen = metabuffer->write_p - metabuffer->read_p; + else + remainLen = META_BUFFER_SIZE - + (metabuffer->read_p - metabuffer->write_p); + + if ((remainLen + 1 + len) >= META_BUFFER_SIZE) { + BTMTK_WARN("copy copyLen %d > META_BUFFER_SIZE(%d), push back to queue", + (remainLen + 1 + len), + META_BUFFER_SIZE); + return -1; + } + + if (use_type) { + metabuffer->buffer[metabuffer->write_p] = type; + metabuffer->write_p++; + } + if (metabuffer->write_p >= META_BUFFER_SIZE) + metabuffer->write_p = 0; + + if (metabuffer->write_p + len <= META_BUFFER_SIZE) + memcpy(&metabuffer->buffer[metabuffer->write_p], + data, + len); + else { + memcpy(&metabuffer->buffer[metabuffer->write_p], + data, + META_BUFFER_SIZE - metabuffer->write_p); + memcpy(metabuffer->buffer, + &data[META_BUFFER_SIZE - metabuffer->write_p], + len - (META_BUFFER_SIZE - metabuffer->write_p)); + } + + metabuffer->write_p += len; + if (metabuffer->write_p >= META_BUFFER_SIZE) + metabuffer->write_p -= META_BUFFER_SIZE; + + remainLen += (1 + len); + return 0; +} + +static int btmtk_sdio_pull_data_from_metabuffer( + struct ring_buffer *metabuffer, + char __user *buf, + size_t count) +{ + int copyLen = 0; + unsigned long ret = 0; + + if (metabuffer->write_p >= metabuffer->read_p) + copyLen = metabuffer->write_p - metabuffer->read_p; + else + copyLen = META_BUFFER_SIZE - + (metabuffer->read_p - metabuffer->write_p); + + if (copyLen > count) + copyLen = count; + + if (metabuffer->read_p + copyLen <= META_BUFFER_SIZE) + ret = copy_to_user(buf, + &metabuffer->buffer[metabuffer->read_p], + copyLen); + else { + ret = copy_to_user(buf, + &metabuffer->buffer[metabuffer->read_p], + META_BUFFER_SIZE - metabuffer->read_p); + if (!ret) + ret = copy_to_user( + &buf[META_BUFFER_SIZE - metabuffer->read_p], + metabuffer->buffer, + copyLen - (META_BUFFER_SIZE-metabuffer->read_p)); + } + + if (ret) + BTMTK_WARN("copy to user fail, ret %d", (int)ret); + + metabuffer->read_p += (copyLen - ret); + if (metabuffer->read_p >= META_BUFFER_SIZE) + metabuffer->read_p -= META_BUFFER_SIZE; + + return (copyLen - ret); +} + +static int btmtk_sdio_reset_dev(struct btmtk_sdio_card *card) +{ + struct sdio_func *func = NULL; + u8 reg = 0; + int ret = 0; + + if (!card || !card->func) { + BTMTK_ERR("Error: card or function is NULL!"); + return -1; + } + + func = card->func; + + sdio_claim_host(func); + + ret = sdio_enable_func(func); + if (ret) { + BTMTK_ERR("sdio_enable_func() failed: ret=%d", ret); + goto reset_dev_end; + } + + reg = sdio_f0_readb(func, SDIO_CCCR_IENx, &ret); + if (ret) { + BTMTK_ERR("read SDIO_CCCR_IENx %x, func num %d, ret %d", reg, func->num, ret); + goto reset_dev_end; + } + + /*return negative value due to inturrept function is register before*/ + ret = sdio_claim_irq(func, btmtk_sdio_interrupt); + BTMTK_INFO("sdio_claim_irq return %d", ret); + + reg |= 1 << func->num; + reg |= 1; + + /* for bt driver can write SDIO_CCCR_IENx */ + func->card->quirks |= MMC_QUIRK_LENIENT_FN0; + ret = 0; + sdio_f0_writeb(func, reg, SDIO_CCCR_IENx, &ret); + if (ret) { + BTMTK_ERR("f0_writeb SDIO_CCCR_IENx %x, func num %d, ret %d error", reg, func->num, ret); + goto reset_dev_end; + } + + reg = sdio_f0_readb(func, SDIO_CCCR_IENx, &ret); + if (ret) { + BTMTK_ERR("f0_readb SDIO_CCCR_IENx %x, func num %d, ret %d error", reg, func->num, ret); + goto reset_dev_end; + } + + ret = sdio_set_block_size(card->func, SDIO_BLOCK_SIZE); + if (ret) { + BTMTK_ERR("cannot set SDIO block size"); + goto reset_dev_end; + } + + reg = sdio_readb(func, card->reg->io_port_0, &ret); + if (ret < 0) { + BTMTK_ERR("read io port0 fail"); + goto reset_dev_end; + } + + card->ioport = reg; + + reg = sdio_readb(func, card->reg->io_port_1, &ret); + if (ret < 0) { + BTMTK_ERR("read io port1 fail"); + goto reset_dev_end; + } + + card->ioport |= (reg << 8); + + reg = sdio_readb(func, card->reg->io_port_2, &ret); + if (ret < 0) { + BTMTK_ERR("read io port2 fail"); + goto reset_dev_end; + } + + card->ioport |= (reg << 16); + + BTMTK_INFO("SDIO FUNC%d IO port: 0x%x", + func->num, card->ioport); + + if (card->reg->int_read_to_clear) { + reg = sdio_readb(func, card->reg->host_int_rsr, &ret); + if (ret < 0) { + BTMTK_ERR("read init rsr fail"); + goto reset_dev_end; + } + sdio_writeb(func, reg | 0x3f, card->reg->host_int_rsr, &ret); + if (ret < 0) { + BTMTK_ERR("write init rsr fail"); + goto reset_dev_end; + } + + reg = sdio_readb(func, card->reg->card_misc_cfg, &ret); + if (ret < 0) { + BTMTK_ERR("read misc cfg fail"); + goto reset_dev_end; + } + sdio_writeb(func, reg | 0x10, card->reg->card_misc_cfg, &ret); + if (ret < 0) + BTMTK_ERR("write misc cfg fail"); + } + + sdio_set_drvdata(func, card); +reset_dev_end: + sdio_release_host(func); + + return ret; +} + +static int btmtk_sdio_reset_fw(struct btmtk_sdio_card *card) +{ + int ret = 0; + + BTMTK_INFO("Mediatek Bluetooth driver Version=%s", VERSION); + + if (card->bt_cfg.support_woble_by_eint) { + btmtk_sdio_RegisterBTIrq(card); + btmtk_sdio_woble_input_init(card); + } + + BTMTK_DBG("func device %X, call btmtk_sdio_register_dev", card->func->device); + ret = btmtk_sdio_reset_dev(card); + if (ret) { + BTMTK_ERR("btmtk_sdio_reset_dev failed!"); + return ret; + } + + BTMTK_DBG("btmtk_sdio_register_dev success"); + btmtk_sdio_enable_host_int(card); + if (btmtk_sdio_download_fw(card)) { + BTMTK_ERR("Downloading firmware failed!"); + ret = -ENODEV; + } + + return ret; +} + +static int btmtk_sdio_set_card_clkpd(int on) +{ + int ret = -1; + /* call sdio_set_card_clkpd in sdio host driver */ + typedef void (*psdio_set_card_clkpd) (int on, struct sdio_func *func); + char *sdio_set_card_clkpd_func_name = "sdio_set_card_clkpd"; + psdio_set_card_clkpd psdio_set_card_clkpd_func = + (psdio_set_card_clkpd)btmtk_kallsyms_lookup_name + (sdio_set_card_clkpd_func_name); + + if (psdio_set_card_clkpd_func) { + BTMTK_INFO("get %s", + sdio_set_card_clkpd_func_name); + psdio_set_card_clkpd_func(on, g_card->func); + ret = 0; + } else + BTMTK_ERR("do not get %s", + sdio_set_card_clkpd_func_name); + return ret; +} + +/*toggle PMU enable*/ +static int btmtk_sdio_toggle_rst_pin(void) +{ + uint32_t pmu_en_delay = MT76x8_PMU_EN_DEFAULT_DELAY; + int pmu_en; + struct device *prDev; + + if (g_card == NULL) { + BTMTK_ERR("g_card is NULL return"); + return -1; + } + sdio_claim_host(g_card->func); + btmtk_sdio_set_card_clkpd(0); + sdio_release_host(g_card->func); + prDev = mmc_dev(g_card->func->card->host); + if (!prDev) { + BTMTK_ERR("unable to get struct dev for BT"); + return -1; + } + pmu_en = of_get_named_gpio(prDev->of_node, MT76x8_PMU_EN_PIN_NAME, 0); + BTMTK_INFO("pmu_en %d", pmu_en); + if (gpio_is_valid(pmu_en)) { + gpio_direction_output(pmu_en, 0); + mdelay(pmu_en_delay); + gpio_direction_output(pmu_en, 1); + BTMTK_INFO("%s pull low/high done", + MT76x8_PMU_EN_PIN_NAME); + } else { + BTMTK_ERR("*** Invalid GPIO %s ***", + MT76x8_PMU_EN_PIN_NAME); + return -1; + } + return 0; +} + +int btmtk_sdio_notify_wlan_remove_end(void) +{ + BTMTK_INFO("begin"); + wlan_remove_done = 1; + btmtk_sdio_stop_wait_wlan_remove_tsk(); + + BTMTK_INFO("done"); + return 0; +} +EXPORT_SYMBOL(btmtk_sdio_notify_wlan_remove_end); + +int btmtk_sdio_bt_trigger_core_dump(int trigger_dump) +{ + struct sk_buff *skb = NULL; + u8 coredump_cmd[] = {0x6F, 0xFC, 0x05, + 0x00, 0x01, 0x02, 0x01, 0x00, 0x08}; + + if (g_priv == NULL) { + BTMTK_ERR("g_priv is NULL return"); + return 0; + } + + if (wait_dump_complete_tsk) { + BTMTK_WARN("wait_dump_complete_tsk is working, return"); + return 0; + } + + if (wait_wlan_remove_tsk) { + BTMTK_WARN("wait_wlan_remove_tsk is working, return"); + return 0; + } + + if (g_priv->btmtk_dev.reset_dongle) { + BTMTK_WARN("reset_dongle is true, return"); + return 0; + } + + if (!probe_ready) { + BTMTK_INFO("probe_ready %d, return -1", + probe_ready); + return -1;/*BT driver is not ready, ask wifi do coredump*/ + } + + BTMTK_INFO("trigger_dump %d", trigger_dump); + if (trigger_dump) { + if (is_mt7663(g_card)) + wlan_status = WLAN_STATUS_CALL_REMOVE_START; + skb = bt_skb_alloc(sizeof(coredump_cmd), GFP_ATOMIC); + bt_cb(skb)->pkt_type = HCI_COMMAND_PKT; + memcpy(&skb->data[0], &coredump_cmd[0], sizeof(coredump_cmd)); + skb->len = sizeof(coredump_cmd); + skb_queue_tail(&g_card->tx_queue, skb); + wake_up_interruptible(&g_priv->main_thread.wait_q); + } else { + if (g_card->bt_cfg.support_dongle_reset == 1) { + /* makesure wait thread is stopped */ + btmtk_sdio_stop_wait_wlan_remove_tsk(); + wait_wlan_remove_tsk = + kthread_run(btmtk_sdio_wait_wlan_remove_thread, + NULL, + "btmtk_sdio_wait_wlan_remove_thread"); + + msleep(100); + btmtk_sdio_notify_wlan_remove_start(); + } else { + BTMTK_ERR("not support chip reset!"); + } + } + + return 0; +} +EXPORT_SYMBOL(btmtk_sdio_bt_trigger_core_dump); + +void btmtk_sdio_notify_wlan_toggle_rst_end(void) +{ + typedef void (*pnotify_wlan_toggle_rst_end) (int reserved); + char *notify_wlan_toggle_rst_end_func_name = + "notify_wlan_toggle_rst_end"; + /*void notify_wlan_toggle_rst_end(void)*/ + pnotify_wlan_toggle_rst_end pnotify_wlan_toggle_rst_end_func = + (pnotify_wlan_toggle_rst_end) btmtk_kallsyms_lookup_name + (notify_wlan_toggle_rst_end_func_name); + + BTMTK_INFO(L0_RESET_TAG); + if (pnotify_wlan_toggle_rst_end_func) { + BTMTK_INFO("do notify %s", + notify_wlan_toggle_rst_end_func_name); + pnotify_wlan_toggle_rst_end_func(1); + } else + BTMTK_ERR("do not get %s", + notify_wlan_toggle_rst_end_func_name); +} + +int btmtk_sdio_driver_reset_dongle(void) +{ + int ret = 0; + int retry = 3; + + BTMTK_INFO("begin"); + if (g_priv == NULL) { + BTMTK_INFO("g_priv = NULL, return"); + return -1; + } + + need_reset_stack = 1; + wlan_remove_done = 0; + +retry_reset: + retry--; + if (retry < 0) { + BTMTK_ERR("retry overtime fail"); + goto rst_dongle_err; + } + BTMTK_INFO("run %d", retry); + ret = 0; + if (btmtk_sdio_toggle_rst_pin()) { + ret = -1; + goto rst_dongle_err; + } + + btmtk_sdio_set_no_fw_own(g_priv, FALSE); + msleep(100); + sdio_claim_host(g_card->func); + if (pf_sdio_reset) + ret = pf_sdio_reset(g_card->func->card); + sdio_release_host(g_card->func); + if (ret) { + BTMTK_WARN("sdio_reset_comm error %d", ret); + goto retry_reset; + } + BTMTK_WARN("sdio_reset_comm done"); + msleep(100); + ret = btmtk_sdio_reset_fw(g_card); + if (ret) { + BTMTK_INFO("reset fw fail"); + goto retry_reset; + } else + BTMTK_INFO("reset fw done"); + +rst_dongle_err: + btmtk_sdio_notify_wlan_toggle_rst_end(); + + g_priv->btmtk_dev.tx_dnld_rdy = 1; + g_priv->btmtk_dev.reset_dongle = 0; + + wlan_status = WLAN_STATUS_DEFAULT; + btmtk_clean_queue(); + g_priv->btmtk_dev.reset_progress = 0; + dump_data_counter = 0; + BTMTK_INFO("return ret = %d", ret); + return ret; +} + +int WF_rst_L0_notify_BT_step2(void) +{ + int ret = -1; + + if (is_mt7663(g_card)) { + BTMTK_INFO(L0_RESET_TAG "begin"); + btmtk_sdio_notify_wlan_remove_end(); + BTMTK_INFO(L0_RESET_TAG "done"); + ret = 0; + } else { + BTMTK_ERR(L0_RESET_TAG "is not MT7663"); + } + return ret; +} +EXPORT_SYMBOL(WF_rst_L0_notify_BT_step2); + +int WF_rst_L0_notify_BT_step1(int reserved) +{ + int ret = -1; + + if (is_mt7663(g_card)) { + BTMTK_INFO(L0_RESET_TAG "begin"); + btmtk_sdio_bt_trigger_core_dump(true); + BTMTK_INFO(L0_RESET_TAG "done"); + ret = 0; + } else { + BTMTK_ERR(L0_RESET_TAG "is not MT7663"); + } + return ret; +} +EXPORT_SYMBOL(WF_rst_L0_notify_BT_step1); + +#ifdef MTK_KERNEL_DEBUG +static int btmtk_sdio_L0_hang_thread(void *data) +{ + do { + BTMTK_INFO(L0_RESET_TAG "Whole Chip Reset was triggered"); + msleep(3000); + } while (1); + return 0; +} + +static int btmtk_sdio_L0_debug_probe(struct sdio_func *func, + const struct sdio_device_id *id) +{ + int ret = 0; + struct task_struct *task = NULL; + struct btmtk_sdio_device *data = (void *) id->driver_data; + u32 u32ReadCRValue = 0; + u8 fw_download_fail = 0; + + BTMTK_INFO(L0_RESET_TAG "flow end"); + probe_counter++; + BTMTK_INFO(L0_RESET_TAG "Mediatek Bluetooth driver Version=%s", VERSION); + BTMTK_INFO(L0_RESET_TAG "vendor=0x%x, device=0x%x, class=%d, fn=%d, support func_num %d", + id->vendor, id->device, id->class, + func->num, data->reg->func_num); + + if (func->num != data->reg->func_num) { + BTMTK_ERR(L0_RESET_TAG "func num is not match"); + return -ENODEV; + } + + g_card->func = func; + + if (id->driver_data) { + g_card->helper = data->helper; + g_card->reg = data->reg; + g_card->sd_blksz_fw_dl = data->sd_blksz_fw_dl; + g_card->support_pscan_win_report = data->support_pscan_win_report; + g_card->supports_fw_dump = data->supports_fw_dump; + g_card->chip_id = data->reg->chip_id; + g_card->suspend_count = 0; + BTMTK_INFO(L0_RESET_TAG "chip_id %x", data->reg->chip_id); + } + + if (btmtk_sdio_register_dev(g_card) < 0) { + BTMTK_ERR(L0_RESET_TAG "Failed to register BT device!"); + return -ENODEV; + } + BTMTK_INFO("btmtk_sdio_register_dev success"); + + /* Disable the interrupts on the card */ + btmtk_sdio_enable_host_int(g_card); + BTMTK_DBG(L0_RESET_TAG "call btmtk_sdio_enable_host_int done"); + if (btmtk_sdio_download_fw(g_card)) { + BTMTK_ERR(L0_RESET_TAG "Downloading firmware failed!"); + fw_download_fail = 1; + } + + task = kthread_run(btmtk_sdio_L0_hang_thread, + NULL, "btmtk_sdio_L0_hang_thread"); + if (IS_ERR(task)) { + BTMTK_INFO(L0_RESET_TAG "create thread fail"); + goto unreg_dev; + } + + ret = btmtk_sdio_readl(CHLPCR, &u32ReadCRValue); + BTMTK_DBG(L0_RESET_TAG "chipid (0x%X)", g_card->chip_id); + + BTMTK_INFO(L0_RESET_TAG "PASS!!"); + + if (fw_download_fail) + btmtk_sdio_start_reset_dongle_progress(); + + return 0; + +unreg_dev: + btmtk_sdio_unregister_dev(g_card); + + BTMTK_ERR(L0_RESET_TAG "fail end"); + return ret; +} +#else +static int btmtk_sdio_L0_probe(struct sdio_func *func, + const struct sdio_device_id *id) +{ + int ret = 0; + /* Set flags/functions here to leave HW reset mark before probe. */ + + /* Now, ready to branch onto true sdio card probe. */ + ret = btmtk_sdio_probe(func, id); + + need_reset_stack = 1; + BTMTK_INFO("need_reset_stack %d probe_ret %d", need_reset_stack, ret); + wake_up_interruptible(&inq); + return ret; +} +#endif + +static int btmtk_sdio_L0_reset_host_config(struct mmc_host *host) +{ + + if (host == NULL) { + BTMTK_ERR(L0_RESET_TAG "mmc host is NULL"); + return -1; + } + + if (host->rescan_entered != 0) { + host->rescan_entered = 0; + BTMTK_INFO(L0_RESET_TAG "set mmc_host rescan to 0"); + } + + BTMTK_DBG(L0_RESET_TAG "done"); + return 0; +} + +static int btmtk_sdio_L0_reset(struct mmc_card *card) +{ + int ret = -1; + struct mmc_host *host = NULL; + + if ((card == NULL) || (card->host == NULL)) { + BTMTK_ERR(L0_RESET_TAG "mmc structs are NULL"); + return ret; + } + + host = card->host; + ret = btmtk_sdio_L0_reset_host_config(host); + if (ret != 0) { + BTMTK_ERR(L0_RESET_TAG "set SDIO host failed"); + return ret; + } + + BTMTK_INFO(L0_RESET_TAG "mmc_remove_host"); + mmc_remove_host(host); + + /* Replace hooked SDIO driver probe to new API; + * 1. It will be new kthread(state) after mmc_add_host; + * 2. Extend flexibility to notify us that HW reset was triggered, + * more flexiable on reviving in exchanging old/new kthread(state). + */ +#ifdef MTK_KERNEL_DEBUG + /* For DBG purpose only, replace to customized probe. + * Will only re-probe SDIO card function then hang for warning. + */ + btmtk_sdio_L0_hook_new_probe(btmtk_sdio_L0_debug_probe); +#else + btmtk_sdio_L0_hook_new_probe(btmtk_sdio_L0_probe); +#endif + + BTMTK_INFO(L0_RESET_TAG "mmc_add_host"); + ret = mmc_add_host(host); + + BTMTK_INFO(L0_RESET_TAG "mmc_add_host return %d", ret); + return ret; +} + +int btmtk_sdio_host_reset_dongle(void) +{ + int ret = -1; + + BTMTK_INFO("begin"); + if (g_priv == NULL) { + BTMTK_ERR("g_priv = NULL, return"); + return ret; + } + if ((!g_card) || (!g_card->func) || (!g_card->func->card)) { + BTMTK_ERR(L0_RESET_TAG "data corrupted"); + goto rst_dongle_done; + } + + wlan_remove_done = 0; + + ret = btmtk_sdio_L0_reset(g_card->func->card); + BTMTK_INFO(L0_RESET_TAG "HW Reset status <%d>.", ret); + +rst_dongle_done: + btmtk_sdio_notify_wlan_toggle_rst_end(); + + g_priv->btmtk_dev.tx_dnld_rdy = 1; + g_priv->btmtk_dev.reset_dongle = 0; + + wlan_status = WLAN_STATUS_DEFAULT; + btmtk_clean_queue(); + g_priv->btmtk_dev.reset_progress = 0; + dump_data_counter = 0; + dump_data_length = 0; + return ret; +} + +int btmtk_sdio_reset_dongle(void) +{ + if (is_mt7663(g_card)) + return btmtk_sdio_host_reset_dongle(); + else + return btmtk_sdio_driver_reset_dongle(); +} + +static irqreturn_t btmtk_sdio_woble_isr(int irq, void *dev) +{ + struct btmtk_sdio_card *data = (struct btmtk_sdio_card *)dev; + + BTMTK_INFO("begin"); + disable_irq_nosync(data->wobt_irq); + atomic_dec(&(data->irq_enable_count)); + BTMTK_INFO("disable BT IRQ, call wake lock"); + __pm_wakeup_event(data->eint_ws, WAIT_POWERKEY_TIMEOUT); + + input_report_key(data->WoBLEInputDev, KEY_WAKEUP, 1); + input_sync(data->WoBLEInputDev); + input_report_key(data->WoBLEInputDev, KEY_WAKEUP, 0); + input_sync(data->WoBLEInputDev); + BTMTK_INFO("end"); + return IRQ_HANDLED; +} + +static int btmtk_sdio_RegisterBTIrq(struct btmtk_sdio_card *data) +{ + struct device_node *eint_node = NULL; + int interrupts[2]; + + eint_node = of_find_compatible_node(NULL, NULL, "mediatek,mt7668_bt_ctrl"); + BTMTK_INFO("begin"); + if (eint_node) { + BTMTK_INFO("Get mt76xx_bt_ctrl compatible node"); + data->wobt_irq = irq_of_parse_and_map(eint_node, 0); + BTMTK_INFO("wobt_irq number:%d", data->wobt_irq); + if (data->wobt_irq) { + of_property_read_u32_array(eint_node, "interrupts", + interrupts, ARRAY_SIZE(interrupts)); + data->wobt_irqlevel = interrupts[1]; + if (request_irq(data->wobt_irq, btmtk_sdio_woble_isr, + data->wobt_irqlevel, "mt7668_bt_ctrl-eint", data)) + BTMTK_INFO("WOBTIRQ LINE NOT AVAILABLE!!"); + else { + BTMTK_INFO("disable BT IRQ"); + disable_irq_nosync(data->wobt_irq); + } + + } else + BTMTK_INFO("can't find mt76xx_bt_ctrl irq"); + + } else { + data->wobt_irq = 0; + BTMTK_INFO("can't find mt76xx_bt_ctrl compatible node"); + } + + + BTMTK_INFO("end"); + return 0; +} + +static int btmtk_sdio_woble_input_init(struct btmtk_sdio_card *data) +{ + int ret = 0; + + data->WoBLEInputDev = input_allocate_device(); + if (IS_ERR(data->WoBLEInputDev)) { + BTMTK_ERR("input_allocate_device error"); + return -ENOMEM; + } + + data->WoBLEInputDev->name = "WOBLE_INPUT_DEVICE"; + data->WoBLEInputDev->id.bustype = BUS_HOST; + data->WoBLEInputDev->id.vendor = 0x0002; + data->WoBLEInputDev->id.product = 0x0002; + data->WoBLEInputDev->id.version = 0x0002; + + __set_bit(EV_KEY, data->WoBLEInputDev->evbit); + __set_bit(KEY_WAKEUP, data->WoBLEInputDev->keybit); + + ret = input_register_device(data->WoBLEInputDev); + if (ret < 0) { + input_free_device(data->WoBLEInputDev); + data->WoBLEInputDev = NULL; + BTMTK_ERR("input_register_device %d", ret); + return ret; + } + + return ret; +} + +static void btmtk_sdio_woble_input_deinit(struct btmtk_sdio_card *data) +{ + if (data->WoBLEInputDev) { + input_unregister_device(data->WoBLEInputDev); + input_free_device(data->WoBLEInputDev); + data->WoBLEInputDev = NULL; + } +} + +static int btmtk_stereo_irq_handler(int irq, void *dev) +{ + /* Get sys clk */ + struct timeval tv; + + do_gettimeofday(&tv); + sys_clk_tmp = (u64)tv.tv_sec * 1000000L + tv.tv_usec; + BTMTK_DBG("tv_sec %d, tv_usec %d, sys_clk %llu", + (int)tv.tv_sec, (int)tv.tv_usec, sys_clk_tmp); + return 0; +} + +static int btmtk_stereo_reg_irq(void) +{ + int ret = 0; + struct device_node *node; + int stereo_gpio; + + BTMTK_INFO("start"); + node = of_find_compatible_node(NULL, NULL, "mediatek,connectivity-combo"); + if (node) { + stereo_gpio = of_get_named_gpio(node, "gpio_bt_stereo_pin", 0); + BTMTK_INFO("pmu_en %d", stereo_gpio); + if (gpio_is_valid(stereo_gpio)) + gpio_direction_input(stereo_gpio); + else + BTMTK_ERR("invalid stereo gpio"); + + stereo_irq = irq_of_parse_and_map(node, 0); + ret = request_irq(stereo_irq, (irq_handler_t)btmtk_stereo_irq_handler, + IRQF_TRIGGER_RISING, "BTSTEREO_ISR_Handler", NULL); + if (ret) { + BTMTK_ERR("fail(%d)!!! irq_number=%d", ret, stereo_irq); + stereo_irq = -1; + } + } else { + BTMTK_INFO("of_find_compatible_node fail!!!"); + ret = -1; + stereo_irq = -1; + } + return ret; +} + +static void btmtk_stereo_unreg_irq(void) +{ + BTMTK_INFO("enter"); + if (stereo_irq != -1) + free_irq(stereo_irq, NULL); + stereo_irq = -1; + BTMTK_INFO("exit"); +} + +static int btmtk_sdio_probe(struct sdio_func *func, + const struct sdio_device_id *id) +{ + int ret = 0; + struct btmtk_private *priv = NULL; + struct btmtk_sdio_device *data = (void *) id->driver_data; + u32 u32ReadCRValue = 0; + u8 fw_download_fail = 0; + + probe_counter++; + BTMTK_INFO("Mediatek Bluetooth driver Version=%s", VERSION); + BTMTK_INFO("vendor=0x%x, device=0x%x, class=%d, fn=%d, support func_num %d", + id->vendor, id->device, id->class, + func->num, data->reg->func_num); + + if (func->num != data->reg->func_num) { + BTMTK_INFO("func num is not match"); + return -ENODEV; + } + + g_card->func = func; + g_card->bin_file_buffer = NULL; + + if (id->driver_data) { + g_card->helper = data->helper; + g_card->reg = data->reg; + g_card->sd_blksz_fw_dl = data->sd_blksz_fw_dl; + g_card->support_pscan_win_report = data->support_pscan_win_report; + g_card->supports_fw_dump = data->supports_fw_dump; + g_card->chip_id = data->reg->chip_id; + g_card->suspend_count = 0; + BTMTK_INFO("chip_id is %x", data->reg->chip_id); + /*allocate memory for woble_setting_file*/ + g_card->woble_setting_file_name = kzalloc(MAX_BIN_FILE_NAME_LEN, GFP_KERNEL); + if (!g_card->woble_setting_file_name) + return -1; + need_retry_load_woble = 0; +#if SUPPORT_MT7663 + if (is_mt7668(g_card)) { + memcpy(g_card->woble_setting_file_name, + WOBLE_SETTING_FILE_NAME_7668, + sizeof(WOBLE_SETTING_FILE_NAME_7668)); + } +#endif + +#if SUPPORT_MT7668 + if (is_mt7663(g_card)) { + memcpy(g_card->woble_setting_file_name, + WOBLE_SETTING_FILE_NAME_7663, + sizeof(WOBLE_SETTING_FILE_NAME_7663)); + } +#endif + + /*allocate memory for bt_cfg_file_name*/ + g_card->bt_cfg_file_name = kzalloc(MAX_BIN_FILE_NAME_LEN, GFP_KERNEL); + if (!g_card->bt_cfg_file_name) + return -1; + + memcpy(g_card->bt_cfg_file_name, BT_CFG_NAME, sizeof(BT_CFG_NAME)); + } + + btmtk_sdio_initialize_cfg_items(); + btmtk_sdio_load_setting_files(g_card->bt_cfg_file_name, &g_card->func->dev, g_card); + + BTMTK_DBG("func device %X, call btmtk_sdio_register_dev", g_card->func->device); + if (btmtk_sdio_register_dev(g_card) < 0) { + BTMTK_ERR("Failed to register BT device!"); + return -ENODEV; + } + + BTMTK_DBG("btmtk_sdio_register_dev success"); + + /* Disable the interrupts on the card */ + btmtk_sdio_enable_host_int(g_card); + BTMTK_DBG("call btmtk_sdio_enable_host_int done"); + + if (btmtk_sdio_download_fw(g_card)) { + BTMTK_ERR("Downloading firmware failed!"); + fw_download_fail = 1; + } + + /* check buffer mode */ + btmtk_eeprom_bin_file(g_card); + + /* Move from btmtk_fops_open() */ + spin_lock_init(&(metabuffer.spin_lock.lock)); + spin_lock_init(&(fwlog_metabuffer.spin_lock.lock)); + + spin_lock_init(&(stereo_spin_lock.lock)); + + BTMTK_DBG("spin_lock_init end"); + + priv = btmtk_add_card(g_card); + if (!priv) { + BTMTK_ERR("Initializing card failed!"); + ret = -ENODEV; + goto unreg_dev; + } + BTMTK_DBG("btmtk_add_card success"); + BTMTK_DBG("assign priv done"); + /* Initialize the interface specific function pointers */ + pf_sdio_reset = (sdio_reset_func) btmtk_kallsyms_lookup_name("sdio_reset_comm"); + if (!pf_sdio_reset && is_mt7668(g_card)) { + BTMTK_WARN("no sdio_reset_comm() api, can't support chip reset!"); + g_card->bt_cfg.support_dongle_reset = 0; + } + g_priv->hw_host_to_card = btmtk_sdio_host_to_card; + g_priv->hw_process_int_status = btmtk_sdio_process_int_status; + g_priv->hw_set_own_back = btmtk_sdio_set_own_back; + g_priv->hw_sdio_reset_dongle = btmtk_sdio_reset_dongle; + g_priv->start_reset_dongle_progress = btmtk_sdio_start_reset_dongle_progress; + g_priv->hci_snoop_save = btmtk_sdio_hci_snoop_save; + btmtk_sdio_set_no_fw_own(g_priv, g_card->is_KeepFullPwr); + + memset(&metabuffer.buffer, 0, META_BUFFER_SIZE); + + fw_dump_file = NULL; + + ret = btmtk_sdio_readl(CHLPCR, &u32ReadCRValue); + BTMTK_DBG("read CHLPCR (0x%08X), chipid is (0x%X)", + u32ReadCRValue, g_card->chip_id); + if (is_support_unify_woble(g_card)) { + memset(g_card->bdaddr, 0, BD_ADDRESS_SIZE); + btmtk_sdio_load_setting_files(g_card->woble_setting_file_name, + &g_card->func->dev, + g_card); + } + + if (g_card->bt_cfg.support_unify_woble && g_card->bt_cfg.support_woble_wakelock) { +#ifdef CONFIG_MP_WAKEUP_SOURCE_SYSFS_STAT + g_card->woble_ws = wakeup_source_register(NULL, "btevent_woble"); +#else + g_card->woble_ws = wakeup_source_register("btevent_woble"); +#endif + if (!g_card->woble_ws) { + BTMTK_WARN("woble_ws register fail!"); + goto unreg_dev; + } + } + + if (g_card->bt_cfg.support_woble_by_eint) { +#ifdef CONFIG_MP_WAKEUP_SOURCE_SYSFS_STAT + g_card->eint_ws = wakeup_source_register(NULL, "btevent_eint"); +#else + g_card->eint_ws = wakeup_source_register("btevent_eint"); +#endif + if (!g_card->eint_ws) { + wakeup_source_unregister(g_card->woble_ws); + BTMTK_WARN("eint_ws register fail!"); + goto unreg_dev; + } + + btmtk_sdio_RegisterBTIrq(g_card); + btmtk_sdio_woble_input_init(g_card); + } + + sema_init(&g_priv->wr_mtx, 1); + sema_init(&g_priv->rd_mtx, 1); + + BTMTK_INFO("normal end"); + probe_ready = true; + if (fw_download_fail) + btmtk_sdio_start_reset_dongle_progress(); + + return 0; + +unreg_dev: + btmtk_sdio_unregister_dev(g_card); + + BTMTK_ERR("fail end"); + return ret; +} + +static void btmtk_sdio_remove(struct sdio_func *func) +{ + struct btmtk_sdio_card *card; + + BTMTK_INFO("begin user_rmmod %d", user_rmmod); + probe_ready = false; + + btmtk_sdio_set_no_fw_own(g_priv, FALSE); + if (func) { + card = sdio_get_drvdata(func); + if (card) { + BTMTK_INFO(L0_RESET_TAG "begin reset_dongle <%d>", + card->priv->btmtk_dev.reset_dongle); + /* Send SHUTDOWN command & disable interrupt + * if user removes the module. + */ + if (user_rmmod) { + BTMTK_INFO("begin user_rmmod %d in user mode", user_rmmod); + btmtk_sdio_enable_interrupt(0); + btmtk_sdio_disable_host_int(card); + } + + if (card->bt_cfg.support_unify_woble && card->bt_cfg.support_woble_wakelock) + wakeup_source_unregister(card->woble_ws); + + if (card->bt_cfg.support_woble_by_eint) { + wakeup_source_unregister(card->eint_ws); + btmtk_sdio_woble_input_deinit(g_card); + } + + btmtk_sdio_woble_free_setting(); + btmtk_sdio_free_bt_cfg(); + BTMTK_DBG("unregister dev"); + card->priv->surprise_removed = true; + if (!card->priv->btmtk_dev.reset_dongle) + btmtk_remove_card(card->priv); + btmtk_sdio_unregister_dev(card); + if (card->bin_file_buffer != NULL) { + kfree(card->bin_file_buffer); + card->bin_file_buffer = NULL; + } + need_reset_stack = 1; + } + } + BTMTK_INFO("end"); +} + +/* + * cmd_type: + * #define HCI_COMMAND_PKT 0x01 + * #define HCI_ACLDATA_PKT 0x02 + * #define HCI_SCODATA_PKT 0x03 + * #define HCI_EVENT_PKT 0x04 + * #define HCI_VENDOR_PKT 0xff + */ +static int btmtk_sdio_send_hci_cmd(u8 cmd_type, + u8 *cmd, int cmd_len, + const u8 *event, const int event_len, + int total_timeout) + /* cmd: if cmd is null, don't compare event, just return 0 if send cmd success */ + /* total_timeout: -1 */ + /* add_spec_header:0 hci event, 1 use vend specic event header*/ + /* return 0 if compare successfully and no need to compare */ + /* return < 0 if error*/ + /* return value: 0 or positive success, -x fail */ +{ + int ret = -1; + unsigned long comp_event_timo = 0, start_time = 0; + struct sk_buff *skb = NULL; + + if (cmd_len == 0) { + BTMTK_ERR("cmd_len (%d) error return", cmd_len); + return -EINVAL; + } + + + skb = bt_skb_alloc(cmd_len, GFP_ATOMIC); + if (skb == NULL) { + BTMTK_WARN("skb is null"); + return -ENOMEM; + } + bt_cb(skb)->pkt_type = cmd_type; + memcpy(&skb->data[0], cmd, cmd_len); + skb->len = cmd_len; + if (event) { + event_compare_status = BTMTK_SDIO_EVENT_COMPARE_STATE_NEED_COMPARE; + memcpy(event_need_compare, event, event_len); + event_need_compare_len = event_len; + } + skb_queue_tail(&g_card->tx_queue, skb); + wake_up_interruptible(&g_priv->main_thread.wait_q); + + + if (event == NULL) + return 0; + + if (event_len > EVENT_COMPARE_SIZE) { + BTMTK_ERR("event_len (%d) > EVENT_COMPARE_SIZE(%d), error", event_len, EVENT_COMPARE_SIZE); + return -1; + } + + start_time = jiffies; + /* check HCI event */ + comp_event_timo = jiffies + msecs_to_jiffies(total_timeout); + ret = -1; + BTMTK_DBG("event_need_compare_len %d, event_compare_status %d", + event_need_compare_len, event_compare_status); + do { + /* check if event_compare_success */ + if (event_compare_status == BTMTK_SDIO_EVENT_COMPARE_STATE_COMPARE_SUCCESS) { + BTMTK_DBG("compare success"); + ret = 0; + break; + } + + msleep(100); + } while (time_before(jiffies, comp_event_timo)); + event_compare_status = BTMTK_SDIO_EVENT_COMPARE_STATE_NOTHING_NEED_COMPARE; + BTMTK_DBG("ret %d", ret); + return ret; +} + +static int btmtk_sdio_trigger_fw_assert(void) +{ + int ret = 0; + /* + * fw dump has 2 types + * 1. Assert: trigger by hci cmd "5b fd 00" defined by bluedroid, + * 2. Exception: trigger by wmt cmd "6F FC 05 01 02 01 00 08" + */ + u8 cmd[] = { 0x5b, 0xfd, 0x00 }; + + BTMTK_INFO("begin"); + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, cmd, + sizeof(cmd), + NULL, 0, WOBLE_COMP_EVENT_TIMO); + if (ret != 0) + BTMTK_INFO("ret = %d", ret); + return ret; +} + +static int btmtk_sdio_send_get_vendor_cap(void) +{ + int ret = -1; + u8 get_vendor_cap_cmd[] = { 0x53, 0xFD, 0x00 }; + u8 get_vendor_cap_event[] = { 0x0e, 0x12, 0x01, 0x53, 0xFD, 0x00}; + + BTMTK_DBG("begin"); + BTSDIO_DEBUG_RAW(get_vendor_cap_cmd, (unsigned int)sizeof(get_vendor_cap_cmd), + "%s: send vendor_cap_cmd is:", __func__); + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, + get_vendor_cap_cmd, sizeof(get_vendor_cap_cmd), + get_vendor_cap_event, sizeof(get_vendor_cap_event), + WOBLE_COMP_EVENT_TIMO); + + BTMTK_DBG("ret %d", ret); + return ret; +} + +static int btmtk_sdio_send_read_BDADDR_cmd(void) +{ + u8 cmd[] = { 0x09, 0x10, 0x00 }; + int ret = -1; + unsigned char zero[BD_ADDRESS_SIZE]; + + BTMTK_DBG("begin"); + if (g_card == NULL) { + BTMTK_ERR("g_card == NULL!"); + return -1; + } + + memset(zero, 0, sizeof(zero)); + if (memcmp(g_card->bdaddr, zero, BD_ADDRESS_SIZE) != 0) { + BTMTK_DBG("already got bdaddr %02x%02x%02x%02x%02x%02x, return 0", + g_card->bdaddr[0], g_card->bdaddr[1], g_card->bdaddr[2], + g_card->bdaddr[3], g_card->bdaddr[4], g_card->bdaddr[5]); + return 0; + } + BTSDIO_DEBUG_RAW(cmd, (unsigned int)sizeof(cmd), "%s: send read bd address cmd is:", __func__); + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, cmd, sizeof(cmd), + READ_ADDRESS_EVENT, sizeof(READ_ADDRESS_EVENT), WOBLE_COMP_EVENT_TIMO); + /*BD address will get in btmtk_sdio_host_to_card*/ + BTMTK_DBG("ret = %d", ret); + + return ret; +} + +static int btmtk_sdio_set_Woble_APCF_filter_parameter(void) +{ + int ret = -1; + u8 cmd[] = { 0x57, 0xfd, 0x0a, 0x01, 0x00, 0x5a, 0x20, 0x00, 0x20, 0x00, 0x01, 0x80, 0x00 }; + u8 event[] = { 0x0e, 0x07, 0x01, 0x57, 0xfd, 0x00, 0x01/*, 00, 63*/ }; + + BTMTK_DBG("begin"); + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, cmd, sizeof(cmd), + event, sizeof(event), + WOBLE_COMP_EVENT_TIMO); + if (ret < 0) + BTMTK_ERR("end ret %d", ret); + else + ret = 0; + + BTMTK_INFO("end ret=%d", ret); + return ret; +} + + +/** + * Set APCF manufacturer data and filter parameter + */ +static int btmtk_sdio_set_Woble_APCF(void) +{ + int ret = -1; + int i = 0; + u8 manufactur_data[] = { 0x57, 0xfd, 0x27, 0x06, 0x00, 0x5a, + 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x43, 0x52, 0x4B, 0x54, 0x4D, + 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + u8 event_complete[] = { 0x0e, 0x07, 0x01, 0x57, 0xfd}; + + BTMTK_DBG("begin"); + if (!g_card) { + BTMTK_INFO("g_card is NULL, return -1"); + return -1; + } + + BTMTK_DBG("g_card->woble_setting_apcf[0].length %d", + g_card->woble_setting_apcf[0].length); + + /* start to send apcf cmd from woble setting file */ + if (g_card->woble_setting_apcf[0].length) { + for (i = 0; i < WOBLE_SETTING_COUNT; i++) { + if (!g_card->woble_setting_apcf[i].length) + continue; + + BTMTK_INFO("g_card->woble_setting_apcf_fill_mac[%d].content[0] = 0x%02x", + i, g_card->woble_setting_apcf_fill_mac[i].content[0]); + BTMTK_INFO("g_card->woble_setting_apcf_fill_mac_location[%d].length = %d", + i, g_card->woble_setting_apcf_fill_mac_location[i].length); + + if ((g_card->woble_setting_apcf_fill_mac[i].content[0] == 1) && + g_card->woble_setting_apcf_fill_mac_location[i].length) { + /* need add BD addr to apcf cmd */ + memcpy(g_card->woble_setting_apcf[i].content + + (*g_card->woble_setting_apcf_fill_mac_location[i].content), + g_card->bdaddr, BD_ADDRESS_SIZE); + BTMTK_INFO("apcf %d ,add mac to location %d", + i, (*g_card->woble_setting_apcf_fill_mac_location[i].content)); + } + + BTMTK_INFO("send APCF %d", i); + BTSDIO_INFO_RAW(g_card->woble_setting_apcf[i].content, g_card->woble_setting_apcf[i].length, + "woble_setting_apcf"); + + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, g_card->woble_setting_apcf[i].content, + g_card->woble_setting_apcf[i].length, + event_complete, sizeof(event_complete), WOBLE_COMP_EVENT_TIMO); + + if (ret < 0) { + BTMTK_ERR("apcf %d error ret %d", i, ret); + return ret; + } + + } + } else { /* use default */ + BTMTK_INFO("use default manufactur data"); + memcpy(manufactur_data + 9, g_card->bdaddr, BD_ADDRESS_SIZE); + BTSDIO_DEBUG_RAW(manufactur_data, (unsigned int)sizeof(manufactur_data), + "send manufactur_data "); + + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, manufactur_data, + sizeof(manufactur_data), + event_complete, sizeof(event_complete), WOBLE_COMP_EVENT_TIMO); + if (ret < 0) { + BTMTK_ERR("manufactur_data error ret %d", ret); + return ret; + } + + ret = btmtk_sdio_set_Woble_APCF_filter_parameter(); + } + + BTMTK_INFO("end ret=%d", ret); + return ret; +} + + + +static int btmtk_sdio_send_woble_settings(struct fw_cfg_struct *settings_cmd, + struct fw_cfg_struct *settings_event, char *message) +{ + int ret = -1; + int i = 0; + + BTMTK_INFO("%s length %d", message, settings_cmd->length); + if (g_card->woble_setting_radio_on[0].length) { + for (i = 0; i < WOBLE_SETTING_COUNT; i++) { + if (settings_cmd[i].length) { + BTMTK_INFO("send %s %d", message, i); + BTSDIO_INFO_RAW(settings_cmd[i].content, + settings_cmd[i].length, "Raw"); + + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, + settings_cmd[i].content, + settings_cmd[i].length, + settings_event[i].content, + settings_event[i].length, + WOBLE_COMP_EVENT_TIMO); + + if (ret) { + BTMTK_ERR("%s %d return error", message, i); + return ret; + } + } + } + } + return ret; +} + +static int btmtk_sdio_send_unify_woble_suspend_default_cmd(void) +{ + int ret = 0; /* if successful, 0 */ + /* Turn off WOBLE, FW go into low power mode only */ + u8 cmd[] = { 0xC9, 0xFC, 0x14, 0x01, 0x20, 0x02, 0x00, 0x00, + 0x02, 0x01, 0x00, 0x05, 0x10, 0x01, 0x00, 0x40, 0x06, + 0x02, 0x40, 0x5A, 0x02, 0x41, 0x0F }; + /*u8 status[] = { 0x0F, 0x04, 0x00, 0x01, 0xC9, 0xFC };*/ + u8 event[] = { 0xE6, 0x02, 0x08, 0x00 }; + + BTMTK_DBG("begin"); + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, cmd, sizeof(cmd), + event, sizeof(event), WOBLE_COMP_EVENT_TIMO); + if (ret) + BTMTK_ERR("comp_event return error(%d)", ret); + + return ret; +} + +/** + * Set APCF manufacturer data and filter parameter + * + * WoBLE test command(TCI_TRIGGER_GPIO, 0xFD77) define: + * b3 GPIO pin (1 or 9) + * b4 active mode (0: low active, 1: high active) + * b5 duration (slots) + * + */ +static int btmtk_sdio_set_Woble_radio_off(u8 is_suspend) +{ + int ret = -1; + u8 cmd[] = { 0x77, 0xFD, 0x03, 0x01, 0x00, 0xA0 }; + + if (is_suspend) { + BTMTK_DBG("g_card->woble_setting_radio_off[0].length %d", + g_card->woble_setting_radio_off[0].length); + BTMTK_DBG("g_card->woble_setting_radio_off_comp_event[0].length %d", + g_card->woble_setting_radio_off_comp_event[0].length); + + if (g_card->woble_setting_radio_off[0].length) { + if (g_card->woble_setting_radio_off_comp_event[0].length && + is_support_unify_woble(g_card)) { + ret = btmtk_sdio_send_woble_settings(g_card->woble_setting_radio_off, + g_card->woble_setting_radio_off_comp_event, + "radio off"); + if (ret) { + BTMTK_ERR("radio off error"); + return ret; + } + } else + BTMTK_INFO("woble_setting_radio_off length is %d", + g_card->woble_setting_radio_off[0].length); + } else {/* use default */ + BTMTK_INFO("use default radio off cmd"); + ret = btmtk_sdio_send_unify_woble_suspend_default_cmd(); + } + } else { + BTMTK_INFO("begin"); + + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, cmd, sizeof(cmd), + NULL, 0, WOBLE_COMP_EVENT_TIMO); + if (ret) + BTMTK_ERR("comp_event return error(%d)", ret); + } + BTMTK_INFO("end ret=%d", ret); + return ret; +} + +static int btmtk_sdio_handle_entering_WoBLE_state(u8 is_suspend) +{ + int ret = 0; + u8 radio_off_cmd[] = { 0xC9, 0xFC, 0x05, 0x01, 0x20, 0x02, 0x00, 0x00 }; + u8 radio_off_evt[] = { 0xE6, 0x02, 0x08, 0x00 }; + int fops_state = 0; + + BTMTK_DBG("begin"); + + FOPS_MUTEX_LOCK(); + fops_state = btmtk_fops_get_state(); + FOPS_MUTEX_UNLOCK(); + + if (!is_support_unify_woble(g_card)) { + if (fops_state == BTMTK_FOPS_STATE_OPENED) { + BTMTK_ERR("not support, send radio off"); + + BTSDIO_DEBUG_RAW(radio_off_cmd, (unsigned int)sizeof(radio_off_cmd), + "%s: send radio_off_cmd is:", __func__); + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, + radio_off_cmd, sizeof(radio_off_cmd), + radio_off_evt, sizeof(radio_off_evt), + WOBLE_COMP_EVENT_TIMO); + + BTMTK_DBG("ret %d", ret); + } else + BTMTK_WARN("when not support woble, in bt off state, do nothing!"); + } else { + if (g_card->dongle_state != BT_SDIO_DONGLE_STATE_POWER_ON) { + if (!g_card->bt_cfg.support_woble_for_bt_disable) { + BTMTK_INFO("BT is off, not support WoBLE"); + goto Finish; + } + + if (btmtk_sdio_bt_set_power(1)) { + BTMTK_ERR("power on failed"); + ret = -EIO; + goto Finish; + } + g_card->dongle_state = BT_SDIO_DONGLE_STATE_POWER_ON_FOR_WOBLE; + } else { + g_card->dongle_state = BT_SDIO_DONGLE_STATE_WOBLE; + } + + if (is_suspend) { + ret = btmtk_sdio_send_get_vendor_cap(); + if (ret < 0) { + BTMTK_ERR("btmtk_sdio_send_get_vendor_cap fail ret = %d", ret); + goto Finish; + } + + ret = btmtk_sdio_send_read_BDADDR_cmd(); + if (ret < 0) { + BTMTK_ERR("btmtk_sdio_send_read_BDADDR_cmd fail ret = %d", ret); + goto Finish; + } + + ret = btmtk_sdio_set_Woble_APCF(); + if (ret < 0) { + BTMTK_ERR("btmtk_sdio_set_Woble_APCF fail %d", ret); + goto Finish; + } + } + ret = btmtk_sdio_set_Woble_radio_off(is_suspend); + if (ret < 0) { + BTMTK_ERR("btmtk_sdio_set_Woble_radio_off return fail %d", ret); + goto Finish; + } + } +Finish: + if (ret) + btmtk_sdio_woble_wake_lock(g_card); + + BTMTK_INFO("end"); + return ret; +} + +static int btmtk_sdio_send_leave_woble_suspend_cmd(void) +{ + int ret = 0; /* if successful, 0 */ + u8 cmd[] = { 0xC9, 0xFC, 0x05, 0x01, 0x21, 0x02, 0x00, 0x00 }; + u8 event[] = { 0xe6, 0x02, 0x08, 0x01 }; + + BTSDIO_DEBUG_RAW(cmd, (unsigned int)sizeof(cmd), "cmd "); + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, cmd, sizeof(cmd), + event, sizeof(event), WOBLE_COMP_EVENT_TIMO); + + if (ret < 0) { + BTMTK_ERR("failed(%d)", ret); + } else { + BTMTK_INFO("OK"); + ret = 0; + } + return ret; +} + +static int btmtk_sdio_del_Woble_APCF_inde(void) +{ + int ret = -1; + u8 cmd[] = { 0x57, 0xfd, 0x03, 0x01, 0x01, 0x5a }; + u8 event[] = { 0x0e, 0x07, 0x01, 0x57, 0xfd, 0x00, 0x01, /* 00, 63 */ }; + + BTMTK_DBG("begin"); + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, cmd, sizeof(cmd), + event, sizeof(event), WOBLE_COMP_EVENT_TIMO); + + if (ret < 0) + BTMTK_ERR("Got error %d", ret); + + BTMTK_INFO("end ret = %d", ret); + return ret; +} + +static void btmtk_sdio_check_wobx_debug_log(void) +{ + /* 0xFF, 0xFF, 0xFF, 0xFF is log level */ + u8 cmd[] = { 0xCE, 0xFC, 0x04, 0xFF, 0xFF, 0xFF, 0xFF }; + u8 event[] = { 0xE8 }; + u8 *p = NULL, *pend = NULL; + int ret = -1; + u8 recv_len = 0; + + BTMTK_INFO("%s: begin", __func__); + if (g_card == NULL) { + BTMTK_ERR("%s: Incorrect g_card", __func__); + return; + } + + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, cmd, sizeof(cmd), event, sizeof(event), WOBLE_COMP_EVENT_TIMO); + if (ret != 0) { + BTMTK_ERR("%s: failed(%d)", __func__, ret); + return; + } + + recv_len = SDIO_HEADER_LEN + HCI_TYPE_LEN + HCI_EVENT_CODE_LEN; + recv_len += rxbuf[recv_len]; + BTSDIO_INFO_RAW(rxbuf, recv_len, "%s: ", __func__); + + /* parse WoBX debug log */ + p = &rxbuf[SDIO_HEADER_LEN + HCI_TYPE_LEN + HCI_EVENT_CODE_LEN]; + pend = p + rxbuf[SDIO_HEADER_LEN + HCI_TYPE_LEN + HCI_EVENT_CODE_LEN]; + while (p < pend) { + u8 attr_len = *(p + 1); + u8 attr_type = *(p + 2); + + BTMTK_INFO("attr_len = 0x%x, attr_type = 0x%x", attr_len, attr_type); + switch (attr_type) { + case WOBX_TRIGGER_INFO_ADDR_TYPE: + break; + case WOBX_TRIGGER_INFO_ADV_DATA_TYPE: + break; + case WOBX_TRIGGER_INFO_TRACE_LOG_TYPE: + break; + case WOBX_TRIGGER_INFO_SCAN_LOG_TYPE: + break; + case WOBX_TRIGGER_INFO_TRIGGER_CNT_TYPE: + BTMTK_INFO("wakeup times(via BT) = %02X%02X%02X%02X", + *(p + 6), *(p + 5), *(p + 4), *(p + 3)); + break; + default: + BTMTK_ERR("%s: unexpected attribute type(0x%x)", __func__, attr_type); + return; + } + p += 1 + attr_len; // 1: len + } +} + +static int btmtk_sdio_handle_leaving_WoBLE_state(void) +{ + int ret = 0; + u8 radio_on_cmd[] = { 0xC9, 0xFC, 0x05, 0x01, 0x21, 0x02, 0x00, 0x00 }; + u8 radio_on_evt[] = { 0xE6, 0x02, 0x08, 0x01 }; + int fops_state = 0; + + BTMTK_DBG("begin"); + + if (g_card == NULL) { + BTMTK_ERR("g_card is NULL return"); + goto exit; + } + + FOPS_MUTEX_LOCK(); + fops_state = btmtk_fops_get_state(); + FOPS_MUTEX_UNLOCK(); + + if (!is_support_unify_woble(g_card)) { + if (fops_state == BTMTK_FOPS_STATE_OPENED) { + BTMTK_ERR("not support, send radio on"); + BTSDIO_DEBUG_RAW(radio_on_cmd, (unsigned int)sizeof(radio_on_cmd), + "%s: send radio_on_cmd is:", __func__); + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, + radio_on_cmd, sizeof(radio_on_cmd), + radio_on_evt, sizeof(radio_on_evt), + WOBLE_COMP_EVENT_TIMO); + BTMTK_DBG("ret %d", ret); + goto exit; + } else { + BTMTK_WARN("when not support woble, in bt off state, do nothing!"); + goto exit; + } + } + + if ((g_card->dongle_state != BT_SDIO_DONGLE_STATE_POWER_ON_FOR_WOBLE) + && (g_card->dongle_state != BT_SDIO_DONGLE_STATE_WOBLE)) { + BTMTK_ERR("Not in woble mode"); + goto exit; + } + + if (g_card->woble_setting_radio_on[0].length && + g_card->woble_setting_radio_on_comp_event[0].length && + g_card->woble_setting_apcf_resume[0].length) { + /* start to send radio on cmd from woble setting file */ + ret = btmtk_sdio_send_woble_settings(g_card->woble_setting_radio_on, + g_card->woble_setting_radio_on_comp_event, "radio on"); + if (ret) { + BTMTK_ERR("woble radio on error"); + goto finish; + } + + ret = btmtk_sdio_send_woble_settings(g_card->woble_setting_apcf_resume, + g_card->woble_setting_apcf_resume_event, "apcf resume"); + if (ret) { + BTMTK_ERR("apcf resume error"); + goto finish; + } + + } else { /* use default */ + ret = btmtk_sdio_send_leave_woble_suspend_cmd(); + if (ret) { + BTMTK_ERR("radio on error"); + goto finish; + } + + ret = btmtk_sdio_del_Woble_APCF_inde(); + if (ret) { + BTMTK_ERR("del apcf index error"); + goto finish; + } + } + +finish: + btmtk_sdio_check_wobx_debug_log(); + + if (g_card->dongle_state == BT_SDIO_DONGLE_STATE_POWER_ON_FOR_WOBLE) { + if (btmtk_sdio_bt_set_power(0)) { + BTMTK_ERR("power off failed"); + return -EIO; + } + } else { + g_card->dongle_state = BT_SDIO_DONGLE_STATE_POWER_ON; + } + +exit: + BTMTK_INFO("end"); + return ret; +} + +static int btmtk_sdio_send_apcf_reserved(void) +{ + int ret = -1; + /* 76x8 APCF Cmd formate: [Header(0xFC5C), Len, Groups of APCF (Max. reserved 10)] + * 76x3 APCF Cmd Formate: [Header(0xFC85), Len, Groups of APCF (Max. reserved 2)] + */ + u8 reserve_apcf_cmd_7668[] = { 0x5C, 0xFC, 0x01, 0x0A }; + u8 reserve_apcf_event_7668[] = { 0x0e, 0x06, 0x01, 0x5C, 0xFC, 0x00 }; + + /* change apcf cmd and event according to mt7663 fw requirement in mp1.4*/ + u8 reserve_apcf_cmd_7663[] = { 0x85, 0xFC, 0x01, 0x02 }; + u8 reserve_apcf_event_7663[] = { 0x0e, 0x06, 0x01, 0x85, 0xFC, 0x00 }; + + if (g_card->func->device == 0x7668) + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, + reserve_apcf_cmd_7668, sizeof(reserve_apcf_cmd_7668), + reserve_apcf_event_7668, sizeof(reserve_apcf_event_7668), + WOBLE_COMP_EVENT_TIMO); + else if (g_card->func->device == 0x7663) + ret = btmtk_sdio_send_hci_cmd(HCI_COMMAND_PKT, + reserve_apcf_cmd_7663, sizeof(reserve_apcf_cmd_7663), + reserve_apcf_event_7663, sizeof(reserve_apcf_event_7663), + WOBLE_COMP_EVENT_TIMO); + else + BTMTK_WARN("not support for 0x%x", g_card->func->device); + + BTMTK_INFO("ret %d", ret); + return ret; +} + +static int btmtk_sdio_suspend(struct device *dev) +{ + struct sdio_func *func = dev_to_sdio_func(dev); + int fops_state = 0; + int ret = 0; + mmc_pm_flag_t pm_flags; + + BTMTK_INFO("begin"); + + if (g_card == NULL) { + BTMTK_ERR("g_card is NULL return"); + return 0; + } + + if (g_card->suspend_count++) { + BTMTK_WARN("Has suspended. suspend_count: %d, end", g_card->suspend_count); + return 0; + } + + FOPS_MUTEX_LOCK(); + fops_state = btmtk_fops_get_state(); + FOPS_MUTEX_UNLOCK(); + if ((fops_state == BTMTK_FOPS_STATE_OPENING) || (fops_state == BTMTK_FOPS_STATE_CLOSING)) { + BTMTK_WARN("fops state is %d, suspend abort", fops_state); + return -ENOSYS; + } + + btmtk_sdio_handle_entering_WoBLE_state(1); + + if (g_card->bt_cfg.support_unify_woble && g_card->bt_cfg.support_woble_by_eint) { + if (g_card->wobt_irq != 0 && atomic_read(&(g_card->irq_enable_count)) == 0) { + BTMTK_INFO("enable BT IRQ:%d", g_card->wobt_irq); + irq_set_irq_wake(g_card->wobt_irq, 1); + enable_irq(g_card->wobt_irq); + atomic_inc(&(g_card->irq_enable_count)); + } else + BTMTK_INFO("irq_enable count:%d", atomic_read(&(g_card->irq_enable_count))); + } + + if (func) { + pm_flags = sdio_get_host_pm_caps(func); + if (!(pm_flags & MMC_PM_KEEP_POWER)) { + BTMTK_ERR("%s cannot remain alive while suspended(0x%x)", + sdio_func_id(func), pm_flags); + } + + pm_flags = MMC_PM_KEEP_POWER; + ret = sdio_set_host_pm_flags(func, pm_flags); + if (ret) { + BTMTK_ERR("set flag 0x%x err %d", pm_flags, (int)ret); + return -ENOSYS; + } + } else { + BTMTK_ERR("sdio_func is not specified"); + return 0; + } + + return 0; +} + +static int btmtk_sdio_resume(struct device *dev) +{ + u8 ret = 0; + int fops_state = 0; + + if (g_card == NULL) { + BTMTK_ERR("g_card is NULL return"); + return 0; + } + + g_card->suspend_count--; + if (g_card->suspend_count) { + BTMTK_INFO("data->suspend_count %d, return 0", g_card->suspend_count); + return 0; + } + + if (g_card->bt_cfg.support_unify_woble && g_card->bt_cfg.support_woble_by_eint) { + if (g_card->wobt_irq != 0 && atomic_read(&(g_card->irq_enable_count)) == 1) { + BTMTK_INFO("disable BT IRQ:%d", g_card->wobt_irq); + atomic_dec(&(g_card->irq_enable_count)); + disable_irq_nosync(g_card->wobt_irq); + } else + BTMTK_INFO("irq_enable count:%d", atomic_read(&(g_card->irq_enable_count))); + } + + ret = btmtk_sdio_handle_leaving_WoBLE_state(); + if (ret) + BTMTK_ERR("btmtk_sdio_handle_leaving_WoBLE_state return fail %d", ret); + + FOPS_MUTEX_LOCK(); + fops_state = btmtk_fops_get_state(); + FOPS_MUTEX_UNLOCK(); + if (g_card->bt_cfg.reset_stack_after_woble + && need_reset_stack == 0 + && fops_state == BTMTK_FOPS_STATE_OPENED) + need_reset_stack = 1; + + BTMTK_INFO("end"); + return 0; +} + +static const struct dev_pm_ops btmtk_sdio_pm_ops = { + .suspend = btmtk_sdio_suspend, + .resume = btmtk_sdio_resume, +}; + +static struct sdio_driver bt_mtk_sdio = { + .name = "btmtk_sdio", + .id_table = btmtk_sdio_ids, + .probe = btmtk_sdio_probe, + .remove = btmtk_sdio_remove, + .drv = { + .owner = THIS_MODULE, + .pm = &btmtk_sdio_pm_ops, + } +}; + +static void btmtk_sdio_L0_hook_new_probe(sdio_card_probe pFn_Probe) +{ + if (pFn_Probe == NULL) { + BTMTK_ERR(L0_RESET_TAG "new probe is NULL"); + return; + } + bt_mtk_sdio.probe = pFn_Probe; +} + +static int btmtk_clean_queue(void) +{ + BTMTK_INFO("enter"); + LOCK_UNSLEEPABLE_LOCK(&(metabuffer.spin_lock)); + skb_queue_purge(&g_card->tx_queue); + skb_queue_purge(&g_card->fops_queue); + UNLOCK_UNSLEEPABLE_LOCK(&(metabuffer.spin_lock)); + BTMTK_INFO("end"); + return 0; +} + +static int btmtk_fops_open(struct inode *inode, struct file *file) +{ + int fops_state = 0; + + BTMTK_INFO("begin"); + + BTMTK_INFO("Mediatek Bluetooth SDIO driver ver %s", VERSION); + BTMTK_INFO("major %d minor %d (pid %d), probe counter: %d", + imajor(inode), iminor(inode), current->pid, probe_counter); + + if (!probe_ready) { + BTMTK_ERR("probe_ready is %d return", probe_ready); + return -EFAULT; + } + + if (g_priv == NULL) { + BTMTK_ERR("g_priv is NULL"); + return -ENOENT; + } + + if (g_priv->adapter == NULL) { + BTMTK_ERR("g_priv->adapter is NULL"); + return -ENOENT; + } + + FOPS_MUTEX_LOCK(); + fops_state = btmtk_fops_get_state(); + FOPS_MUTEX_UNLOCK(); + if (fops_state == BTMTK_FOPS_STATE_CLOSING) { + BTMTK_ERR("mode is %d", fops_state); + return -EAGAIN; + } + + if (fops_state == BTMTK_FOPS_STATE_OPENING || fops_state == BTMTK_FOPS_STATE_OPENED) { + BTMTK_ERR("mode is %d", fops_state); + return -ENOENT; + } + + FOPS_MUTEX_LOCK(); + btmtk_fops_set_state(BTMTK_FOPS_STATE_OPENING); + FOPS_MUTEX_UNLOCK(); + + metabuffer.read_p = 0; + metabuffer.write_p = 0; + + btmtk_sdio_hci_snoop_init(); + + if (btmtk_sdio_send_init_cmds(g_card)) { + BTMTK_ERR("send init failed"); + return -EIO; + } + + if (is_support_unify_woble(g_card)) { + if (btmtk_sdio_send_apcf_reserved()) { + BTMTK_ERR("send apcf failed"); + return -EIO; + } + } + + btmtk_clean_queue(); + + FOPS_MUTEX_LOCK(); + btmtk_fops_set_state(BTMTK_FOPS_STATE_OPENED); + FOPS_MUTEX_UNLOCK(); + + need_reset_stack = 0; + need_reopen = 0; + stereo_irq = -1; + BTMTK_INFO("end"); + return 0; +} + +static int btmtk_fops_close(struct inode *inode, struct file *file) +{ + int fops_state = 0; + + BTMTK_INFO("begin"); + + BTMTK_INFO("Mediatek Bluetooth SDIO driver ver %s", VERSION); + BTMTK_INFO("major %d minor %d (pid %d), probe counter: %d", + imajor(inode), iminor(inode), current->pid, probe_counter); + + if (!probe_ready) { + BTMTK_ERR("probe_ready is %d return", probe_ready); + return -EFAULT; + } + + if (g_priv == NULL) { + pr_info("%s g_priv is NULL\n", __func__); + return -ENOENT; + } + + if (g_priv->adapter == NULL) { + pr_info("%s g_priv->adapter is NULL\n", __func__); + return -ENOENT; + } + + if (g_card->dongle_state != BT_SDIO_DONGLE_STATE_POWER_ON) { + BTMTK_ERR("dongle_state is %d", g_card->dongle_state); + goto exit; + } + + FOPS_MUTEX_LOCK(); + fops_state = btmtk_fops_get_state(); + FOPS_MUTEX_UNLOCK(); + if (fops_state != BTMTK_FOPS_STATE_OPENED) { + BTMTK_ERR("mode is %d", fops_state); + goto exit; + } + + FOPS_MUTEX_LOCK(); + btmtk_fops_set_state(BTMTK_FOPS_STATE_CLOSING); + FOPS_MUTEX_UNLOCK(); + + if (g_card->bt_cfg.support_auto_picus == true) + btmtk_sdio_picus_operation(false); + + btmtk_sdio_send_hci_reset(true); + btmtk_sdio_send_deinit_cmds(); + +exit: + btmtk_stereo_unreg_irq(); + btmtk_clean_queue(); + need_reopen = 0; + + FOPS_MUTEX_LOCK(); + btmtk_fops_set_state(BTMTK_FOPS_STATE_CLOSED); + FOPS_MUTEX_UNLOCK(); + + if (g_priv && g_priv->adapter) + BTMTK_INFO("end"); + else + BTMTK_INFO("end g_priv or adapter is null"); + return 0; +} + +ssize_t btmtk_fops_write(struct file *filp, const char __user *buf, + size_t count, loff_t *f_pos) +{ + int retval = 0; + struct sk_buff *skb = NULL; + static u8 waiting_for_hci_without_packet_type; /* INITIALISED_STATIC: do not initialise statics to 0 */ + static u8 hci_packet_type = 0xff; + u32 copy_size = 0; + unsigned long c_result = 0; + u8 pkt_type = 0xff; + u32 pkt_len = 0; + unsigned char *pkt_data = NULL; + int fops_state = 0; +#if SUPPORT_CR_WR + u32 crAddr = 0, crValue = 0, crMask = 0; +#endif + + if (!probe_ready) { + BTMTK_ERR("probe_ready is %d return", probe_ready); + return -EFAULT; + } + + if (g_priv == NULL) { + BTMTK_ERR("g_priv is NULL"); + return -EFAULT; + } + + FOPS_MUTEX_LOCK(); + fops_state = btmtk_fops_get_state(); + FOPS_MUTEX_UNLOCK(); + if (fops_state != BTMTK_FOPS_STATE_OPENED) { + BTMTK_ERR("fops_state is %d", fops_state); + return -EFAULT; + } + + if (g_card->dongle_state != BT_SDIO_DONGLE_STATE_POWER_ON) { + BTMTK_ERR("dongle_state is %d return", g_card->dongle_state); + return 0; + } + + if (need_reopen) { + BTMTK_ERR("need_reopen (%d)!", need_reopen); + return -EFAULT; + } + + if (g_card->suspend_count) { + BTMTK_ERR("suspend_count is %d", g_card->suspend_count); + return -EAGAIN; + } + + down(&g_priv->wr_mtx); + + if (count > 0 && count < MTK_TXDATA_SIZE) { + memset(userbuf, 0, MTK_TXDATA_SIZE); + c_result = copy_from_user(userbuf, buf, count); + } else { + BTMTK_ERR("target packet length:%zu is not allowed", count); + retval = -EFAULT; + goto OUT; + } + + if (c_result != 0) { + BTMTK_ERR("copy_from_user failed!"); + retval = -EFAULT; + goto OUT; + } + +#if SUPPORT_CR_WR + if (userbuf[0] == 0x7 && waiting_for_hci_without_packet_type == 0) { + /* write CR */ + if (count < 15) { + BTMTK_ERR("count=%zd less than 15, error", count); + retval = -EFAULT; + goto OUT; + } + + crAddr = (userbuf[3] & 0xff) + ((userbuf[4] & 0xff) << 8) + + ((userbuf[5] & 0xff) << 16) + ((userbuf[6] & 0xff) << 24); + crValue = (userbuf[7] & 0xff) + ((userbuf[8] & 0xff) << 8) + + ((userbuf[9] & 0xff) << 16) + ((userbuf[10] & 0xff) << 24); + crMask = (userbuf[11] & 0xff) + ((userbuf[12] & 0xff) << 8) + + ((userbuf[13] & 0xff) << 16) + ((userbuf[14] & 0xff) << 24); + + BTMTK_INFO("crAddr=0x%08x crValue=0x%08x crMask=0x%08x", crAddr, crValue, crMask); + crValue &= crMask; + + BTMTK_INFO("write crAddr=0x%08x crValue=0x%08x", + crAddr, crValue); + btmtk_sdio_writel(crAddr, crValue); + retval = count; + goto OUT; + } else if (userbuf[0] == 0x8 && waiting_for_hci_without_packet_type == 0) { + /* read CR */ + if (count < 16) { + BTMTK_ERR("count=%zd less than 15, error", count); + retval = -EFAULT; + goto OUT; + } + + crAddr = (userbuf[3] & 0xff) + ((userbuf[4] & 0xff) << 8) + + ((userbuf[5] & 0xff) << 16) + ((userbuf[6] & 0xff) << 24); + crMask = (userbuf[11] & 0xff) + ((userbuf[12] & 0xff)<<8) + + ((userbuf[13] & 0xff) << 16) + ((userbuf[14] & 0xff) << 24); + + btmtk_sdio_readl(crAddr, &crValue); + BTMTK_INFO("read crAddr=0x%08x crValue=0x%08x crMask=0x%08x", + crAddr, crValue, crMask); + retval = count; + goto OUT; + } +#endif + if (count == 1) { + if (waiting_for_hci_without_packet_type == 1) { + BTMTK_WARN("Waiting for hci_without_packet_type, but receive data count is 1!"); + BTMTK_WARN("Treat this packet as packet_type(0x%02X)", userbuf[0]); + } + memcpy(&hci_packet_type, &userbuf[0], 1); + waiting_for_hci_without_packet_type = 1; + retval = 1; + goto OUT; + } + + if (waiting_for_hci_without_packet_type) { + copy_size = count + 1; + pkt_type = hci_packet_type; + pkt_data = &userbuf[0]; + } else { + copy_size = count; + pkt_type = userbuf[0]; + pkt_data = &userbuf[1]; + } + + /* Check input length which must follow the BT spec.*/ + switch (pkt_type) { + case HCI_COMMAND_PKT: + /* HCI command : Type(8b) OpCode(16b) length(8b) + * Header length = 1 + 2 + 1 + */ + pkt_len = pkt_data[2] + MTK_HCI_CMD_HEADER_LEN; + break; + case HCI_ACLDATA_PKT: + /* ACL data : Type(8b) handle+flag(16b) length(16b) + * Header length = 1 + 2 + 2 + */ + pkt_len = (pkt_data[2] | (pkt_data[3] << 8)) + MTK_HCI_ACL_HEADER_LEN; + break; + case HCI_SCODATA_PKT: + /* SCO data : Type(8b) handle+flag(16b) length(8b) + * Header length = 1 + 2 + 1 + */ + pkt_len = pkt_data[2] + MTK_HCI_SCO_HEADER_LEN; + break; + default: + BTMTK_ERR("type is 0x%x", pkt_type); + retval = -EFAULT; + goto OUT; + } + + /* check frame length is valid */ + if (pkt_len != copy_size) { + BTMTK_ERR("input len(%d) error (expect %d)", copy_size, pkt_type); + retval = -EFAULT; + goto OUT; + } + + + skb = bt_skb_alloc(copy_size - 1, GFP_ATOMIC); + if (skb == NULL) { + BTMTK_ERR(" No meory for skb"); + retval = -EFAULT; + goto OUT; + } + bt_cb(skb)->pkt_type = pkt_type; + memcpy(&skb->data[0], pkt_data, copy_size - 1); + + skb->len = copy_size - 1; + skb_queue_tail(&g_card->tx_queue, skb); + + if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) { + u8 fw_assert_cmd[] = { 0x6F, 0xFC, 0x05, 0x01, 0x02, 0x01, 0x00, 0x08 }; + u8 reset_cmd[] = { 0x03, 0x0C, 0x00 }; + u8 read_ver_cmd[] = { 0x01, 0x10, 0x00 }; + + if (skb->len == sizeof(fw_assert_cmd) && + !memcmp(&skb->data[0], fw_assert_cmd, sizeof(fw_assert_cmd))) + BTMTK_INFO("Donge FW Assert Triggered by upper layer"); + else if (skb->len == sizeof(reset_cmd) && + !memcmp(&skb->data[0], reset_cmd, sizeof(reset_cmd))) + BTMTK_INFO("got command: 0x03 0C 00 (HCI_RESET)"); + else if (skb->len == sizeof(read_ver_cmd) && + !memcmp(&skb->data[0], read_ver_cmd, sizeof(read_ver_cmd))) + BTMTK_INFO("got command: 0x01 10 00 (READ_LOCAL_VERSION)"); + } + + wake_up_interruptible(&g_priv->main_thread.wait_q); + + retval = copy_size; + + if (waiting_for_hci_without_packet_type) { + hci_packet_type = 0xff; + waiting_for_hci_without_packet_type = 0; + if (retval > 0) + retval -= 1; + } + +OUT: + BTMTK_DBG("end"); + up(&g_priv->wr_mtx); + return retval; +} + +ssize_t btmtk_fops_read(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + struct sk_buff *skb = NULL; + int copyLen = 0; + u8 hwerr_event[] = { 0x04, 0x10, 0x01, 0xff }; + static int send_hw_err_event_count; + int fops_state = 0; + + if (!probe_ready) { + BTMTK_ERR("probe_ready is %d return", probe_ready); + return -EFAULT; + } + + if (g_priv == NULL) { + BTMTK_ERR("g_priv is NULL"); + return -EFAULT; + } + + FOPS_MUTEX_LOCK(); + fops_state = btmtk_fops_get_state(); + FOPS_MUTEX_UNLOCK(); + if ((fops_state != BTMTK_FOPS_STATE_OPENED) && (need_reset_stack == 0)) { + BTMTK_ERR("fops_state is %d", fops_state); + return -EFAULT; + } + + if (g_card->suspend_count) { + BTMTK_ERR("suspend_count is %d", g_card->suspend_count); + return -EAGAIN; + } + + down(&g_priv->rd_mtx); + + if (need_reset_stack == 1) { + BTMTK_WARN("Reset BT stack, go if send_hw_err_event_count %d", send_hw_err_event_count); + if (send_hw_err_event_count < sizeof(hwerr_event)) { + if (count < (sizeof(hwerr_event) - send_hw_err_event_count)) { + copyLen = count; + BTMTK_INFO("call wake_up_interruptible"); + wake_up_interruptible(&inq); + } else + copyLen = (sizeof(hwerr_event) - send_hw_err_event_count); + BTMTK_WARN("in if copyLen = %d", copyLen); + if (copy_to_user(buf, hwerr_event + send_hw_err_event_count, copyLen)) { + BTMTK_ERR("send_hw_err_event_count %d copy to user fail, count = %d, go out", + send_hw_err_event_count, copyLen); + copyLen = -EFAULT; + goto OUT; + } + send_hw_err_event_count += copyLen; + BTMTK_WARN("in if send_hw_err_event_count = %d", send_hw_err_event_count); + if (send_hw_err_event_count >= sizeof(hwerr_event)) { + send_hw_err_event_count = 0; + BTMTK_WARN("set need_reset_stack=0"); + need_reset_stack = 0; + need_reopen = 1; + kill_fasync(&fasync, SIGIO, POLL_IN); + } + BTMTK_WARN("set call up"); + goto OUT; + } else { + BTMTK_ERR("xx set copyLen = -EFAULT"); + copyLen = -EFAULT; + goto OUT; + } + } + + if (get_hci_reset == 1) { + BTMTK_INFO("get reset complete and set audio!"); + btmtk_sdio_send_audio_slave(); + if (g_card->pa_setting != -1) + btmtk_set_pa(g_card->pa_setting); + if (g_card->duplex_setting != -1) + btmtk_set_duplex(g_card->duplex_setting); + if (g_card->efuse_mode == EFUSE_BIN_FILE_MODE) + btmtk_set_eeprom2ctrler((uint8_t *)g_card->bin_file_buffer, + g_card->bin_file_size, + g_card->func->device); + if (g_card->bt_cfg.support_auto_picus == true) + btmtk_sdio_picus_operation(true); + + get_hci_reset = 0; + } + + LOCK_UNSLEEPABLE_LOCK(&(metabuffer.spin_lock)); + if (skb_queue_empty(&g_card->fops_queue)) { + /* if (filp->f_flags & O_NONBLOCK) { */ + if (metabuffer.write_p == metabuffer.read_p) { + UNLOCK_UNSLEEPABLE_LOCK(&(metabuffer.spin_lock)); + up(&g_priv->rd_mtx); + return 0; + } + } + + if (need_reset_stack == 1) { + kill_fasync(&fasync, SIGIO, POLL_IN); + need_reset_stack = 0; + BTMTK_ERR("Call kill_fasync and set reset_stack 0"); + UNLOCK_UNSLEEPABLE_LOCK(&(metabuffer.spin_lock)); + up(&g_priv->rd_mtx); + return -ENODEV; + } + + do { + skb = skb_dequeue(&g_card->fops_queue); + if (skb == NULL) { + BTMTK_DBG("skb=NULL break"); + break; + } + + btmtk_print_buffer_conent(skb->data, skb->len); + + if (btmtk_sdio_push_data_to_metabuffer(&metabuffer, skb->data, + skb->len, bt_cb(skb)->pkt_type, true) < 0) { + skb_queue_head(&g_card->fops_queue, skb); + break; + } + kfree_skb(skb); + } while (!skb_queue_empty(&g_card->fops_queue)); + UNLOCK_UNSLEEPABLE_LOCK(&(metabuffer.spin_lock)); + + up(&g_priv->rd_mtx); + return btmtk_sdio_pull_data_from_metabuffer(&metabuffer, buf, count); + +OUT: + up(&g_priv->rd_mtx); + return copyLen; +} + +static int btmtk_fops_fasync(int fd, struct file *file, int on) +{ + BTMTK_INFO("fd = 0x%X, flag = 0x%X", fd, on); + return fasync_helper(fd, file, on, &fasync); +} + +unsigned int btmtk_fops_poll(struct file *filp, poll_table *wait) +{ + unsigned int mask = 0; + + if (!probe_ready) { + BTMTK_ERR("%s probe_ready is %d return\n", __func__, probe_ready); + return 0; + } + + if (g_priv == NULL) { + BTMTK_ERR("g_priv is NULL"); + return 0; + } + + poll_wait(filp, &inq, wait); + + if (metabuffer.write_p != metabuffer.read_p || need_reset_stack) + mask |= (POLLIN | POLLRDNORM); + + if (!skb_queue_empty(&g_card->fops_queue)) { + if (skb_queue_len(&g_card->fops_queue)) + mask |= (POLLIN | POLLRDNORM); + /* BTMTK_INFO("poll done"); */ + } + + mask |= (POLLOUT | POLLWRNORM); + + /* BTMTK_INFO("poll mask 0x%x",mask); */ + return mask; +} + +static long btmtk_fops_unlocked_ioctl(struct file *filp, + unsigned int cmd, unsigned long arg) +{ + u32 ret = 0; + struct bt_stereo_para stereo_para; + struct sk_buff *skb = NULL; + u8 set_btclk[] = {0x01, 0x02, 0xFD, 0x0B, + 0x00, 0x00, /* Handle */ + 0x00, /* Method */ + /* bit0~3 = 0x0:CVSD remove, 0x1:GPIO, 0x2:In-band with transport*/ + /* bit4~7 = 0x0:Shared memory, 0x1:auto event */ + 0x00, 0x00, 0x00, 0x00, /* Period = value * 0.625ms */ + 0x09, /* GPIO num - 0x01:BGF_INT_B, 0x09:GPIO0 */ + 0x01, /* trigger mode - 0x00:Low, 0x01:High */ + 0x00, 0x00}; /* active slots = value * 0.625ms */ + + + switch (cmd) { + case BTMTK_IOCTL_STEREO_GET_CLK: + BTMTK_DBG("BTMTK_IOCTL_STEREO_GET_CLK cmd"); + + LOCK_UNSLEEPABLE_LOCK(&stereo_spin_lock); + if (copy_to_user((struct bt_stereo_clk __user *)arg, &stereo_clk, sizeof(struct bt_stereo_clk))) + ret = -ENOMEM; + UNLOCK_UNSLEEPABLE_LOCK(&stereo_spin_lock); + break; + case BTMTK_IOCTL_STEREO_SET_PARA: + BTMTK_DBG("BTMTK_IOCTL_STEREO_SET_PARA cmd"); + if (copy_from_user(&stereo_para, (struct bt_stereo_para __user *)arg, + sizeof(struct bt_stereo_para))) + return -ENOMEM; + + if (stereo_para.period != 0) + btmtk_stereo_reg_irq(); + + /* Send and check HCI cmd */ + memcpy(&set_btclk[4], &stereo_para.handle, sizeof(stereo_para.handle)); + memcpy(&set_btclk[6], &stereo_para.method, sizeof(stereo_para.method)); + memcpy(&set_btclk[7], &stereo_para.period, sizeof(stereo_para.period)); + memcpy(&set_btclk[13], &stereo_para.active_slots, sizeof(stereo_para.active_slots)); +#if SUPPORT_MT7668 + if (is_mt7668(g_card)) + set_btclk[11] = 0x09; +#endif +#if SUPPORT_MT7663 + if (is_mt7663(g_card)) + set_btclk[11] = 0x0B; +#endif + + skb = bt_skb_alloc(sizeof(set_btclk) - 1, GFP_ATOMIC); + bt_cb(skb)->pkt_type = set_btclk[0]; + memcpy(&skb->data[0], &set_btclk[1], sizeof(set_btclk) - 1); + + skb->len = sizeof(set_btclk) - 1; + skb_queue_tail(&g_card->tx_queue, skb); + wake_up_interruptible(&g_priv->main_thread.wait_q); + + if (stereo_para.period == 0) + btmtk_stereo_unreg_irq(); + break; + default: + return -EINVAL; + } + return ret; +} + +static int btmtk_fops_openfwlog(struct inode *inode, + struct file *file) +{ + if (g_priv == NULL) { + BTMTK_ERR("ERROR, g_priv is NULL!"); + return -ENODEV; + } + + sema_init(&g_priv->wr_fwlog_mtx, 1); + BTMTK_INFO("OK"); + return 0; +} + +static int btmtk_fops_closefwlog(struct inode *inode, + struct file *file) +{ + if (g_priv == NULL) { + BTMTK_ERR("ERROR, g_priv is NULL!"); + return -ENODEV; + } + + BTMTK_INFO("OK"); + return 0; +} + +static ssize_t btmtk_fops_readfwlog(struct file *filp, + char __user *buf, + size_t count, + loff_t *f_pos) +{ + struct sk_buff *skb = NULL; + int copyLen = 0; + + if (g_priv == NULL || g_priv->adapter == NULL) { + BTMTK_ERR("g_priv is NULL"); + return -EFAULT; + } + + if (g_card->suspend_count) { + BTMTK_ERR("suspend_count is %d", g_card->suspend_count); + return -EAGAIN; + } + + /* picus read a queue, it may occur performace issue */ + LOCK_UNSLEEPABLE_LOCK(&(fwlog_metabuffer.spin_lock)); + if (skb_queue_len(&g_card->fwlog_fops_queue)) + skb = skb_dequeue(&g_card->fwlog_fops_queue); + UNLOCK_UNSLEEPABLE_LOCK(&(fwlog_metabuffer.spin_lock)); + + if (skb == NULL) + return 0; + + if (skb->len <= count) { + if (copy_to_user(buf, skb->data, skb->len)) { + BTMTK_ERR("copy_to_user failed!"); + /* copy_to_user failed, add skb to fwlog_fops_queue */ + skb_queue_head(&g_card->fwlog_fops_queue, skb); + copyLen = -EFAULT; + goto OUT; + } + copyLen = skb->len; + } else { + BTMTK_ERR("socket buffer length error(count: %d, skb.len: %d)", (int)count, skb->len); + } + kfree_skb(skb); +OUT: + return copyLen; +} + +static ssize_t btmtk_fops_writefwlog( + struct file *filp, const char __user *buf, + size_t count, loff_t *f_pos) +{ + struct sk_buff *skb = NULL; + int i = 0, len = 0, val = 0, ret = -1; + /*+1 is for i_fwlog_buf[count] = 0, end string byte*/ + int i_fwlog_buf_size = HCI_MAX_COMMAND_BUF_SIZE + 1; + u8 *i_fwlog_buf = NULL; + u8 *o_fwlog_buf = NULL; + int fops_state = 0; + u32 crAddr = 0, crValue = 0; + + if (g_priv == NULL || g_priv->adapter == NULL) { + BTMTK_ERR("g_priv is NULL"); + goto exit; + } + + down(&g_priv->wr_fwlog_mtx); + + FOPS_MUTEX_LOCK(); + fops_state = btmtk_fops_get_state(); + FOPS_MUTEX_UNLOCK(); + if (fops_state != BTMTK_FOPS_STATE_OPENED) { + BTMTK_ERR("fops_state is %d", fops_state); + count = -EFAULT; + goto exit; + } + + if (g_card->suspend_count) { + BTMTK_ERR("suspend_count is %d", g_card->suspend_count); + count = -EAGAIN; + goto exit; + } + + i_fwlog_buf = kmalloc(i_fwlog_buf_size, GFP_KERNEL); + o_fwlog_buf = kmalloc(HCI_MAX_COMMAND_SIZE, GFP_KERNEL); + + if (i_fwlog_buf == NULL || o_fwlog_buf == NULL) { + BTMTK_ERR("buf alloc fail"); + count = -ENOMEM; + goto exit; + } + + memset(i_fwlog_buf, 0, i_fwlog_buf_size); + memset(o_fwlog_buf, 0, HCI_MAX_COMMAND_SIZE); + + if (count > HCI_MAX_COMMAND_BUF_SIZE) { + BTMTK_ERR("your command is larger than maximum length, count = %zd", count); + count = -EFAULT; + goto exit; + } + + if (copy_from_user(i_fwlog_buf, buf, count) != 0) { + BTMTK_ERR("copy_from_user failed!"); + count = -EFAULT; + goto exit; + } + + i_fwlog_buf[count] = 0; + + if (strstr(i_fwlog_buf, FW_OWN_OFF)) { + BTMTK_WARN("set FW_OWN_OFF"); + btmtk_sdio_set_no_fw_own(g_priv, true); + len = count; + wake_up_interruptible(&g_priv->main_thread.wait_q); + goto exit; + } + + if (strstr(i_fwlog_buf, FW_OWN_ON)) { + BTMTK_WARN("set FW_OWN_ON"); + btmtk_sdio_set_no_fw_own(g_priv, false); + len = count; + wake_up_interruptible(&g_priv->main_thread.wait_q); + goto exit; + } + + if (strstr(i_fwlog_buf, WOBLE_ON)) { + BTMTK_INFO("set WOBLE_ON"); + btmtk_sdio_handle_entering_WoBLE_state(0); + len = count; + if (g_card->bt_cfg.support_woble_by_eint) { + if (g_card->wobt_irq != 0 && + atomic_read(&(g_card->irq_enable_count)) == 0) { + BTMTK_INFO("enable BT IRQ:%d", g_card->wobt_irq); + irq_set_irq_wake(g_card->wobt_irq, 1); + enable_irq(g_card->wobt_irq); + atomic_inc(&(g_card->irq_enable_count)); + } else + BTMTK_INFO("irq_enable count:%d", + atomic_read(&(g_card->irq_enable_count))); + } + goto exit; + } + + if (strstr(i_fwlog_buf, WOBLE_OFF)) { + BTMTK_INFO("set WOBLE_OFF"); + if (g_card->bt_cfg.support_woble_by_eint) { + if (g_card->wobt_irq != 0 && + atomic_read(&(g_card->irq_enable_count)) == 1) { + BTMTK_INFO("disable BT IRQ:%d", g_card->wobt_irq); + atomic_dec(&(g_card->irq_enable_count)); + disable_irq_nosync(g_card->wobt_irq); + } else + BTMTK_INFO(":irq_enable count:%d", + atomic_read(&(g_card->irq_enable_count))); + } + btmtk_sdio_send_leave_woble_suspend_cmd(); + len = count; + goto exit; + } + + if (strstr(i_fwlog_buf, RX_CHECK_ON)) { + /* echo rx check on 0=100000 */ + int type, i; + + if (strstr(i_fwlog_buf, "=")) { + type = i_fwlog_buf[strlen(RX_CHECK_ON) + 1] - '0'; + if (type >= BTMTK_SDIO_RX_CHECKPOINT_NUM) { + BTMTK_WARN("set RX_CHECK_ON failed. type=%d", type); + goto exit; + } + timestamp_threshold[type] = 0; + for (i = strlen("rx check on 0="); (i_fwlog_buf[i] >= '0' && i_fwlog_buf[i] <= '9'); i++) { + timestamp_threshold[type] = timestamp_threshold[type] * 10; + timestamp_threshold[type] += i_fwlog_buf[i] - '0'; + } + } else { + type = 0; + timestamp_threshold[BTMTK_SDIO_RX_CHECKPOINT_INTR] = 50000; + } + BTMTK_WARN("set RX_CHECK_ON %d=%d", type, timestamp_threshold[type]); + goto exit; + } + + if (strstr(i_fwlog_buf, RX_CHECK_OFF)) { + BTMTK_WARN("set RX_CHECK_OFF"); + memset(timestamp_threshold, 0, sizeof(timestamp_threshold)); + goto exit; + } + + if (strstr(i_fwlog_buf, RELOAD_SETTING)) { + BTMTK_INFO("set RELOAD_SETTING"); + btmtk_eeprom_bin_file(g_card); + len = count; + goto exit; + } + + /* For log_lvl, EX: echo log_lvl=4 > /dev/stpbtfwlog */ + if (strcmp(i_fwlog_buf, "log_lvl=") > 0) { + val = *(i_fwlog_buf + strlen("log_lvl=")) - 48; + + if (val > BTMTK_LOG_LEVEL_MAX || val <= 0) { + BTMTK_ERR("Got incorrect value for log level(%d)", val); + count = -EINVAL; + goto exit; + } + btmtk_log_lvl = val; + BTMTK_INFO("btmtk_log_lvl = %d", btmtk_log_lvl); + goto exit; + } + + /* For btmtk_bluetooth_kpi, EX: echo bperf=1 > /dev/stpbtfwlog */ + if (strcmp(i_fwlog_buf, "bperf=") >= 0) { + u8 val = *(i_fwlog_buf + strlen("bperf=")) - 48; + + btmtk_bluetooth_kpi = val; + BTMTK_INFO("set bluetooth KPI feature(bperf) to %d", btmtk_bluetooth_kpi); + goto exit; + } + + /* hci input command format : echo 01 be fc 01 05 > /dev/stpbtfwlog */ + /* We take the data from index three to end. */ + for (i = 0; i < count; i++) { + char *pos = i_fwlog_buf + i; + char temp_str[3] = {'\0'}; + long res = 0; + + if (*pos == ' ' || *pos == '\t' || *pos == '\r' || *pos == '\n') { + continue; + } else if (*pos == '0' && (*(pos + 1) == 'x' || *(pos + 1) == 'X')) { + i++; + continue; + } else if (!(*pos >= '0' && *pos <= '9') && !(*pos >= 'A' && *pos <= 'F') + && !(*pos >= 'a' && *pos <= 'f')) { + BTMTK_ERR("There is an invalid input(%c)", *pos); + count = -EINVAL; + goto exit; + } + temp_str[0] = *pos; + temp_str[1] = *(pos + 1); + i++; + ret = kstrtol(temp_str, 16, &res); + if (ret == 0) { + o_fwlog_buf[len++] = (u8)res; + if (len >= (HCI_MAX_COMMAND_SIZE - 1) && ((i + 1) < len)) { + BTMTK_WARN("buf is full, input format may error"); + goto exit; + } + } + else + BTMTK_ERR("Convert %s failed(%d)", temp_str, ret); + } + + /* + * Receive command from stpbtfwlog, then Sent hci command + * to controller + */ + BTMTK_DBG("hci buff is %02x%02x%02x%02x%02x, length %d", + o_fwlog_buf[0], o_fwlog_buf[1], + o_fwlog_buf[2], o_fwlog_buf[3], o_fwlog_buf[4], len); + + /* check HCI command length */ + if (len > HCI_MAX_COMMAND_SIZE) { + BTMTK_ERR("your command is larger than maximum length, length = %d", len); + goto exit; + } + + if (len <= 1) { + BTMTK_ERR("length = %d, command format may error", len); + goto exit; + } + + BTMTK_DBG("hci buff is %02x%02x%02x%02x%02x", + o_fwlog_buf[0], o_fwlog_buf[1], + o_fwlog_buf[2], o_fwlog_buf[3], o_fwlog_buf[4]); + + switch (o_fwlog_buf[0]) { + case MTK_HCI_READ_CR_PKT: + if (len == MTK_HCI_READ_CR_PKT_LENGTH) { + crAddr = (o_fwlog_buf[1] << 24) + (o_fwlog_buf[2] << 16) + + (o_fwlog_buf[3] << 8) + (o_fwlog_buf[4]); + btmtk_sdio_readl(crAddr, &crValue); + BTMTK_INFO("read crAddr=0x%08x crValue=0x%08x", crAddr, crValue); + } else + BTMTK_INFO("read length=%d is incorrect, should be %d", + len, MTK_HCI_READ_CR_PKT_LENGTH); + break; + + case MTK_HCI_WRITE_CR_PKT: + if (len == MTK_HCI_WRITE_CR_PKT_LENGTH) { + crAddr = (o_fwlog_buf[1] << 24) + (o_fwlog_buf[2] << 16) + + (o_fwlog_buf[3] << 8) + (o_fwlog_buf[4]); + crValue = (o_fwlog_buf[5] << 24) + (o_fwlog_buf[6] << 16) + + (o_fwlog_buf[7] << 8) + (o_fwlog_buf[8]); + BTMTK_INFO("write crAddr=0x%08x crValue=0x%08x", + crAddr, crValue); + btmtk_sdio_writel(crAddr, crValue); + } else + BTMTK_INFO("write length=%d is incorrect, should be %d", + len, MTK_HCI_WRITE_CR_PKT_LENGTH); + break; + + default: + /* + * Receive command from stpbtfwlog, then Sent hci command + * to Stack + */ + skb = bt_skb_alloc(len - 1, GFP_ATOMIC); + if (skb == NULL) { + BTMTK_WARN("skb is null"); + count = -ENOMEM; + goto exit; + } + bt_cb(skb)->pkt_type = o_fwlog_buf[0]; + memcpy(&skb->data[0], &o_fwlog_buf[1], len - 1); + skb->len = len - 1; + skb_queue_tail(&g_card->tx_queue, skb); + wake_up_interruptible(&g_priv->main_thread.wait_q); + break; + } + + + + BTMTK_INFO("write end"); +exit: + BTMTK_INFO("exit, length = %d", len); + if (i_fwlog_buf) + kfree(i_fwlog_buf); + if (o_fwlog_buf) + kfree(o_fwlog_buf); + if (g_priv) + up(&g_priv->wr_fwlog_mtx); + return count; +} + +static unsigned int btmtk_fops_pollfwlog( + struct file *file, poll_table *wait) +{ + unsigned int mask = 0; + + if (g_priv == NULL) { + BTMTK_ERR("g_priv is NULL"); + return 0; + } + + poll_wait(file, &fw_log_inq, wait); + + if (!skb_queue_empty(&g_card->fwlog_fops_queue)) { + if (skb_queue_len(&g_card->fwlog_fops_queue)) + mask |= (POLLIN | POLLRDNORM); + /* BTMTK_INFO("poll done"); */ + } + + mask |= (POLLOUT | POLLWRNORM); + + /* BTMTK_INFO("poll mask 0x%x",mask); */ + return mask; +} + +static long btmtk_fops_unlocked_ioctlfwlog( + struct file *filp, unsigned int cmd, + unsigned long arg) +{ + int retval = 0; + + BTMTK_INFO("->"); + if (g_priv == NULL) { + BTMTK_ERR("ERROR, g_priv is NULL!"); + return -ENODEV; + } + + return retval; +} + +/*============================================================================*/ +/* Interface Functions : Proc */ +/*============================================================================*/ +#define __________________________________________Interface_Function_for_Proc +static int btmtk_proc_show(struct seq_file *m, void *v) +{ + seq_printf(m, "patch version:%s driver version:%s", fw_version_str, VERSION); + return 0; +} + +static int btmtk_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, btmtk_proc_show, NULL); +} + +void btmtk_proc_create_new_entry(void) +{ + struct proc_dir_entry *proc_show_entry; + + BTMTK_INFO("proc initialized"); + + g_proc_dir = proc_mkdir("stpbt", 0); + if (g_proc_dir == 0) { + BTMTK_ERR("Unable to creat dir"); + return; + } + proc_show_entry = proc_create("bt_fw_version", 0644, g_proc_dir, &BT_proc_fops); +} + +static int BTMTK_major; +static int BT_majorfwlog; +static struct cdev BTMTK_cdev; +static struct cdev BT_cdevfwlog; +static int BTMTK_devs = 1; + +static wait_queue_head_t inq; +const struct file_operations BTMTK_fops = { + .open = btmtk_fops_open, + .release = btmtk_fops_close, + .read = btmtk_fops_read, + .write = btmtk_fops_write, + .poll = btmtk_fops_poll, + .unlocked_ioctl = btmtk_fops_unlocked_ioctl, + .fasync = btmtk_fops_fasync +}; + +const struct file_operations BT_fopsfwlog = { + .open = btmtk_fops_openfwlog, + .release = btmtk_fops_closefwlog, + .read = btmtk_fops_readfwlog, + .write = btmtk_fops_writefwlog, + .poll = btmtk_fops_pollfwlog, + .unlocked_ioctl = btmtk_fops_unlocked_ioctlfwlog + +}; + +static int BTMTK_init(void) +{ + dev_t devID = MKDEV(BTMTK_major, 0); + dev_t devIDfwlog = MKDEV(BT_majorfwlog, 1); + int ret = 0; + int cdevErr = 0; + int major = 0; + int majorfwlog = 0; + + BTMTK_INFO("begin"); + + g_card = NULL; + txbuf = NULL; + rxbuf = NULL; + userbuf = NULL; + rx_length = 0; + fw_dump_file = NULL; + g_priv = NULL; + probe_counter = 0; + + btmtk_proc_create_new_entry(); + + ret = alloc_chrdev_region(&devID, 0, 1, "BT_chrdev"); + if (ret) { + BTMTK_ERR("fail to allocate chrdev"); + return ret; + } + + ret = alloc_chrdev_region(&devIDfwlog, 0, 1, "BT_chrdevfwlog"); + if (ret) { + BTMTK_ERR("fail to allocate chrdev"); + return ret; + } + + BTMTK_major = major = MAJOR(devID); + BTMTK_INFO("major number:%d", BTMTK_major); + BT_majorfwlog = majorfwlog = MAJOR(devIDfwlog); + BTMTK_INFO("BT_majorfwlog number: %d", BT_majorfwlog); + + cdev_init(&BTMTK_cdev, &BTMTK_fops); + BTMTK_cdev.owner = THIS_MODULE; + + cdev_init(&BT_cdevfwlog, &BT_fopsfwlog); + BT_cdevfwlog.owner = THIS_MODULE; + + cdevErr = cdev_add(&BTMTK_cdev, devID, BTMTK_devs); + if (cdevErr) + goto error; + + cdevErr = cdev_add(&BT_cdevfwlog, devIDfwlog, 1); + if (cdevErr) + goto error; + + BTMTK_INFO("%s driver(major %d) installed.", + "BT_chrdev", BTMTK_major); + BTMTK_INFO("%s driver(major %d) installed.", + "BT_chrdevfwlog", BT_majorfwlog); + + pBTClass = class_create(THIS_MODULE, "BT_chrdev"); + if (IS_ERR(pBTClass)) { + BTMTK_ERR("class create fail, error code(%ld)", + PTR_ERR(pBTClass)); + goto error; + } + + pBTDev = device_create(pBTClass, NULL, devID, NULL, BT_NODE); + if (IS_ERR(pBTDev)) { + BTMTK_ERR("device create fail, error code(%ld)", + PTR_ERR(pBTDev)); + goto err2; + } + + pBTDevfwlog = device_create(pBTClass, NULL, + devIDfwlog, NULL, "stpbtfwlog"); + if (IS_ERR(pBTDevfwlog)) { + BTMTK_ERR("device(stpbtfwlog) create fail, error code(%ld)", + PTR_ERR(pBTDevfwlog)); + goto err2; + } + + BTMTK_INFO("BT_major %d, BT_majorfwlog %d", BTMTK_major, BT_majorfwlog); + BTMTK_INFO("devID %d, devIDfwlog %d", devID, devIDfwlog); + + FOPS_MUTEX_LOCK(); + btmtk_fops_set_state(BTMTK_FOPS_STATE_INIT); + FOPS_MUTEX_UNLOCK(); + + /* init wait queue */ + g_devIDfwlog = devIDfwlog; + init_waitqueue_head(&(fw_log_inq)); + init_waitqueue_head(&(inq)); + + return 0; + + err2: + if (pBTClass) { + class_destroy(pBTClass); + pBTClass = NULL; + } + + error: + if (cdevErr == 0) + cdev_del(&BTMTK_cdev); + + if (ret == 0) + unregister_chrdev_region(devID, BTMTK_devs); + + return -1; +} + +static void BTMTK_exit(void) +{ + dev_t dev = MKDEV(BTMTK_major, 0); + dev_t devIDfwlog = g_devIDfwlog; + + BTMTK_INFO("begin"); + + if (g_proc_dir != NULL) { + remove_proc_entry("bt_fw_version", g_proc_dir); + remove_proc_entry("stpbt", NULL); + g_proc_dir = NULL; + BTMTK_INFO("proc device node and folder removed!!"); + } + + if (pBTDevfwlog) { + BTMTK_INFO("6"); + device_destroy(pBTClass, devIDfwlog); + pBTDevfwlog = NULL; + } + + if (pBTDev) { + device_destroy(pBTClass, dev); + pBTDev = NULL; + } + + if (pBTClass) { + class_destroy(pBTClass); + pBTClass = NULL; + } + cdev_del(&BTMTK_cdev); + unregister_chrdev_region(dev, 1); + + cdev_del(&BT_cdevfwlog); + unregister_chrdev_region(devIDfwlog, 1); + BTMTK_INFO("%s driver removed.", BT_DRIVER_NAME); +} + +static int btmtk_sdio_allocate_memory(void) +{ + txbuf = kmalloc(MTK_TXDATA_SIZE, GFP_ATOMIC); + memset(txbuf, 0, MTK_TXDATA_SIZE); + + rxbuf = kmalloc(MTK_RXDATA_SIZE, GFP_ATOMIC); + memset(rxbuf, 0, MTK_RXDATA_SIZE); + + userbuf = kmalloc(MTK_TXDATA_SIZE, GFP_ATOMIC); + memset(userbuf, 0, MTK_TXDATA_SIZE); + + userbuf_fwlog = kmalloc(MTK_TXDATA_SIZE, GFP_ATOMIC); + memset(userbuf_fwlog, 0, MTK_TXDATA_SIZE); + + g_card = kzalloc(sizeof(*g_card), GFP_KERNEL); + memset(g_card, 0, sizeof(*g_card)); + + g_priv = kzalloc(sizeof(*g_priv), GFP_KERNEL); + memset(g_priv, 0, sizeof(*g_priv)); + + g_priv->adapter = kzalloc(sizeof(*g_priv->adapter), GFP_KERNEL); + memset(g_priv->adapter, 0, sizeof(*g_priv->adapter)); + + g_card->priv = g_priv; + + skb_queue_head_init(&g_card->tx_queue); + skb_queue_head_init(&g_card->fops_queue); + skb_queue_head_init(&g_card->fwlog_fops_queue); + + return 0; +} + +static int btmtk_sdio_free_memory(void) +{ + skb_queue_purge(&g_card->tx_queue); + skb_queue_purge(&g_card->fops_queue); + skb_queue_purge(&g_card->fwlog_fops_queue); + + kfree(txbuf); + txbuf = NULL; + + kfree(rxbuf); + rxbuf = NULL; + + kfree(userbuf); + userbuf = NULL; + + kfree(userbuf_fwlog); + userbuf_fwlog = NULL; + + kfree(g_card->priv->adapter); + g_card->priv->adapter = NULL; + + kfree(g_card->priv); + g_card->priv = NULL; + g_priv = NULL; + + kfree(g_card); + g_card = NULL; + + return 0; +} + +static int __init btmtk_sdio_init_module(void) +{ + int ret = 0; + + ret = BTMTK_init(); + if (ret) { + BTMTK_ERR("BTMTK_init failed!"); + return ret; + } + + if (btmtk_sdio_allocate_memory() < 0) { + BTMTK_ERR("allocate memory failed!"); + return -ENOMEM; + } + + if (sdio_register_driver(&bt_mtk_sdio) != 0) { + BTMTK_ERR("SDIO Driver Registration Failed"); + return -ENODEV; + } + + BTMTK_INFO("SDIO Driver Registration Success"); + + /* Clear the flag in case user removes the card. */ + user_rmmod = 0; + + return 0; +} + +static void __exit btmtk_sdio_exit_module(void) +{ + /* Set the flag as user is removing this module. */ + user_rmmod = 1; + BTMTK_exit(); + sdio_unregister_driver(&bt_mtk_sdio); + btmtk_sdio_free_memory(); +} + +module_init(btmtk_sdio_init_module); +module_exit(btmtk_sdio_exit_module); diff --git a/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/btmtk_sdio.h b/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/btmtk_sdio.h new file mode 100644 index 0000000000000..f48ddbcbb8270 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/btmtk_sdio.h @@ -0,0 +1,479 @@ +/* + * Copyright (c) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef _BTMTK_SDIO_H_ +#define _BTMTK_SDIO_H_ +#include "btmtk_config.h" +#include + +#define VERSION "v0.0.1.13_2020101001" + +#define SDIO_HEADER_LEN 4 +#define STP_HEADER_LEN 4 +#define COREDUMP_HEADER_LEN 5 +#define HCI_TYPE_LEN 1 +#define HCI_EVENT_CODE_LEN 1 +#define COREDUMP_PACKET_HEADER_LEN 13 + +#define BD_ADDRESS_SIZE 6 + +#define SET_POWER_NUM 3 + +#define DUMP_HCI_LOG_FILE_NAME "/sys/hcilog" +/* SD block size can not bigger than 64 due to buf size limit in firmware */ +/* define SD block size for data Tx/Rx */ +#define SDIO_BLOCK_SIZE 256 + +#define SDIO_PATCH_DOWNLOAD_FIRST 1/*first packet*/ +#define SDIO_PATCH_DOWNLOAD_CON 2/*continue*/ +#define SDIO_PATCH_DOWNLOAD_END 3/*end*/ + +/* Number of blocks for firmware transfer */ +#define FIRMWARE_TRANSFER_NBLOCK 2 + +/* This is for firmware specific length */ +#define FW_EXTRA_LEN 36 + +#define MRVDRV_SIZE_OF_CMD_BUFFER (2 * 1024) + +#define MRVDRV_BT_RX_PACKET_BUFFER_SIZE \ + (HCI_MAX_FRAME_SIZE + FW_EXTRA_LEN) + +#define ALLOC_BUF_SIZE (((max_t (int, MRVDRV_BT_RX_PACKET_BUFFER_SIZE, \ + MRVDRV_SIZE_OF_CMD_BUFFER) + SDIO_HEADER_LEN \ + + SDIO_BLOCK_SIZE - 1) / SDIO_BLOCK_SIZE) \ + * SDIO_BLOCK_SIZE) + +/* The number of times to try when polling for status */ +#define MAX_POLL_TRIES 100 + +/* Max retry number of CMD53 write */ +#define MAX_WRITE_IOMEM_RETRY 2 + +/* register bitmasks */ +#define HOST_POWER_UP BIT(1) +#define HOST_CMD53_FIN BIT(2) + +#define HIM_DISABLE 0xff +#define HIM_ENABLE (BIT(0) | BIT(1)) + +#define UP_LD_HOST_INT_STATUS BIT(0) +#define DN_LD_HOST_INT_STATUS BIT(1) + +#define DN_LD_CARD_RDY BIT(0) +#define CARD_IO_READY BIT(3) + +#define FIRMWARE_READY 0xfedc + +enum { + BTMTK_FOPS_STATE_UNKNOWN, /* deinit in stpbt destroy */ + BTMTK_FOPS_STATE_INIT, /* init in stpbt created */ + BTMTK_FOPS_STATE_OPENING, /* during opening */ + BTMTK_FOPS_STATE_OPENED, /* opened */ + BTMTK_FOPS_STATE_CLOSING, /* during closing */ + BTMTK_FOPS_STATE_CLOSED, /* closed */ + BTMTK_FOPS_STATE_MAX +}; + +struct btmtk_sdio_card_reg { + u8 cfg; + u8 host_int_mask; + u8 host_intstatus; + u8 card_status; + u8 sq_read_base_addr_a0; + u8 sq_read_base_addr_a1; + u8 card_revision; + u8 card_fw_status0; + u8 card_fw_status1; + u8 card_rx_len; + u8 card_rx_unit; + u8 io_port_0; + u8 io_port_1; + u8 io_port_2; + bool int_read_to_clear; + u8 host_int_rsr; + u8 card_misc_cfg; + u8 fw_dump_ctrl; + u8 fw_dump_start; + u8 fw_dump_end; + u8 func_num; + u32 chip_id; +}; +#if SUPPORT_MT7668 +#define WOBLE_SETTING_FILE_NAME_7668 "woble_setting_7668.bin" +#endif + +#if SUPPORT_MT7663 +#define WOBLE_SETTING_FILE_NAME_7663 "woble_setting_7663.bin" +#endif + +/* Backward compatibility */ +#define WOBLE_SETTING_FILE_NAME "woble_setting.bin" +#define BT_CFG_NAME "bt.cfg" +#define BT_UNIFY_WOBLE "SUPPORT_UNIFY_WOBLE" +#define BT_LEGACY_WOBLE "SUPPORT_LEGACY_WOBLE" +#define BT_WOBLE_BY_EINT "SUPPORT_WOBLE_BY_EINT" +#define BT_DONGLE_RESET_PIN "BT_DONGLE_RESET_GPIO_PIN" +#define BT_SAVE_FW_DUMP_IN_KERNEL "SAVE_FW_DUMP_IN_KERNEL" +#define BT_SYS_LOG_FILE "SYS_LOG_FILE_NAME" +#define BT_FW_DUMP_FILE "FW_DUMP_FILE_NAME" +#define BT_RESET_DONGLE "SUPPORT_DONGLE_RESET" +#define BT_FULL_FW_DUMP "SUPPORT_FULL_FW_DUMP" +#define BT_WOBLE_WAKELOCK "SUPPORT_WOBLE_WAKELOCK" +#define BT_WOBLE_FOR_BT_DISABLE "SUPPORT_WOBLE_FOR_BT_DISABLE" +#define BT_RESET_STACK_AFTER_WOBLE "RESET_STACK_AFTER_WOBLE" +#define BT_AUTO_PICUS "SUPPORT_AUTO_PICUS" +#define BT_AUTO_PICUS_FILTER "PICUS_FILTER_CMD" +#define BT_WMT_CMD "WMT_CMD" +#define BT_VENDOR_CMD "VENDOR_CMD" + +#define WMT_CMD_COUNT 255 +#define VENDOR_CMD_COUNT 255 + +#define WOBLE_SETTING_COUNT 10 + +#define WOBLE_FAIL -10 + +enum bt_sdio_dongle_state { + BT_SDIO_DONGLE_STATE_UNKNOWN, + BT_SDIO_DONGLE_STATE_POWER_ON, + BT_SDIO_DONGLE_STATE_POWER_ON_FOR_WOBLE, + BT_SDIO_DONGLE_STATE_POWER_OFF, + BT_SDIO_DONGLE_STATE_WOBLE, + BT_SDIO_DONGLE_STATE_FW_DUMP, + BT_SDIO_DONGLE_STATE_ERROR +}; + +enum fw_cfg_index_len { + FW_CFG_INX_LEN_NONE = 0, + FW_CFG_INX_LEN_2 = 2, + FW_CFG_INX_LEN_3 = 3, +}; + +struct fw_cfg_struct { + char *content; /* APCF conecnt or radio off content */ + int length; /* APCF conecnt or radio off content of length */ +}; + +struct bt_cfg_struct { + bool support_unify_woble; /* support unify woble or not */ + bool support_legacy_woble; /* support legacy woble or not */ + bool support_woble_by_eint; /* support woble by eint or not */ + bool save_fw_dump_in_kernel; /* save fw dump in kernel or not */ + bool support_dongle_reset; /* support chip reset or not */ + bool support_full_fw_dump; /* dump full fw coredump or not */ + bool support_woble_wakelock; /* support when woble error, do wakelock or not */ + bool support_woble_for_bt_disable; /* when bt disable, support enter susend or not */ + bool reset_stack_after_woble; /* support reset stack to re-connect IOT after resume */ + bool support_auto_picus; /* support enable PICUS automatically */ + struct fw_cfg_struct picus_filter; /* support on PICUS filter command customization */ + int dongle_reset_gpio_pin; /* BT_DONGLE_RESET_GPIO_PIN number */ + char *sys_log_file_name; + char *fw_dump_file_name; + struct fw_cfg_struct wmt_cmd[WMT_CMD_COUNT]; + struct fw_cfg_struct vendor_cmd[VENDOR_CMD_COUNT]; +}; + +struct btmtk_sdio_card { + struct sdio_func *func; + u32 ioport; + const char *helper; + const struct btmtk_sdio_card_reg *reg; + bool support_pscan_win_report; + bool supports_fw_dump; + u16 sd_blksz_fw_dl; + u8 rx_unit; + bool is_KeepFullPwr; + struct btmtk_private *priv; + + unsigned char *woble_setting_file_name; + + unsigned int chip_id; + struct fw_cfg_struct woble_setting_apcf[WOBLE_SETTING_COUNT]; + struct fw_cfg_struct woble_setting_apcf_fill_mac[WOBLE_SETTING_COUNT]; + struct fw_cfg_struct woble_setting_apcf_fill_mac_location[WOBLE_SETTING_COUNT]; + + struct fw_cfg_struct woble_setting_radio_off[WOBLE_SETTING_COUNT]; + struct fw_cfg_struct woble_setting_radio_off_status_event[WOBLE_SETTING_COUNT]; + /* complete event */ + struct fw_cfg_struct woble_setting_radio_off_comp_event[WOBLE_SETTING_COUNT]; + + struct fw_cfg_struct woble_setting_radio_on[WOBLE_SETTING_COUNT]; + struct fw_cfg_struct woble_setting_radio_on_status_event[WOBLE_SETTING_COUNT]; + struct fw_cfg_struct woble_setting_radio_on_comp_event[WOBLE_SETTING_COUNT]; + + int suspend_count; + /* set apcf after resume(radio on) */ + struct fw_cfg_struct woble_setting_apcf_resume[WOBLE_SETTING_COUNT]; + struct fw_cfg_struct woble_setting_apcf_resume_event[WOBLE_SETTING_COUNT]; + unsigned char bdaddr[BD_ADDRESS_SIZE]; + unsigned int woble_need_trigger_coredump; + unsigned char *bt_cfg_file_name; + unsigned char *setting_file; + struct bt_cfg_struct bt_cfg; + struct wakeup_source *woble_ws; + struct wakeup_source *eint_ws; + + /* WoBLE */ + unsigned int wobt_irq; + int wobt_irqlevel; + atomic_t irq_enable_count; + struct input_dev *WoBLEInputDev; + + int pa_setting; + int duplex_setting; + u8 *bin_file_buffer; + size_t bin_file_size; + u8 efuse_mode; + + struct sk_buff_head tx_queue; + struct sk_buff_head fops_queue; + struct sk_buff_head fwlog_fops_queue; + + enum bt_sdio_dongle_state dongle_state; +}; + +struct btmtk_sdio_device { + const char *helper; + const struct btmtk_sdio_card_reg *reg; + const bool support_pscan_win_report; + u16 sd_blksz_fw_dl; + bool supports_fw_dump; +}; +#pragma pack(1) +struct _PATCH_HEADER { + u8 ucDateTime[16]; + u8 ucPlatform[4]; + u16 u2HwVer; + u16 u2SwVer; + u32 u4PatchVer; + u16 u2PatchStartAddr;/*Patch ram start address*/ +}; +#pragma pack() + +struct bt_stereo_clk { + u64 sys_clk; + u64 fw_clk; +}; + +struct bt_stereo_para { + u16 handle; + u8 method; + u32 period; + u16 active_slots; +}; + +#define HW_VERSION 0x80000000 +#define FW_VERSION 0x80000004 +#define CHIP_ID 0x80000008 + +/*common 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 +#define SWPCDBGR 0x0154 +/*CHLPCR*/ +#define C_FW_INT_EN_SET 0x00000001 +#define C_FW_INT_EN_CLEAR 0x00000002 +/*CHISR*/ +#define RX_PKT_LEN 0xFFFF0000 +#define FIRMWARE_INT 0x0000FE00 +#define FIRMWARE_INT_BIT15 0x00008000/*FW inform driver don't change to fw own for dore dump*/ +#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 + + +#define MTKSTP_HEADER_SIZE 0x0004 + +#define MTK_SDIO_PACKET_HEADER_SIZE 4 +#define MTKDATA_HEADER_SIZE 10 +#define MTKWMT_HEADER_SIZE 4 + +#define PATCH_DOWNLOAD_SIZE 1970 + +#define DRIVER_OWN 0 +#define FW_OWN 1 + +#define MTK_WMT_HEADER_LEN 4 + +#define DEFAULE_PATCH_FRAG_SIZE 1000 + +#define PATCH_IS_DOWNLOAD_BY_OTHER 0 +#define PATCH_READY 1 +#define PATCH_NEED_DOWNLOAD 2 + +#define BTMTK_SDIO_RETRY_COUNT 500 + +#define BTMTK_LOAD_WOBLE_RETRY_COUNT 1 + +/** + * stpbtfwlog device node + */ +#define HCI_MAX_COMMAND_SIZE 255 +/* Write a char to buffer. + * ex : echo 01 be > /dev/stpbtfwlog + * "01 " need three bytes. + */ +#define HCI_MAX_COMMAND_BUF_SIZE (HCI_MAX_COMMAND_SIZE * 3) + +/* + * data event: + * return + * 0: + * patch download is not complete/get patch semaphore fail + * 1: + * patch download is complete by others + * 2 + * patch download is not coplete + * 3:(for debug) + * release patch semaphore success + */ + +/* Platform specific DMA alignment */ +#define BTSDIO_DMA_ALIGN 8 + +/* Macros for Data Alignment : size */ +#define ALIGN_SZ(p, a) \ + (((p) + ((a) - 1)) & ~((a) - 1)) + +/* Macros for Data Alignment : address */ +#define ALIGN_ADDR(p, a) \ + ((((unsigned long)(p)) + (((unsigned long)(a)) - 1)) & \ + ~(((unsigned long)(a)) - 1)) +struct sk_buff *btmtk_create_send_data(struct sk_buff *skb); +int btmtk_print_buffer_conent(u8 *buf, u32 Datalen); +u32 lock_unsleepable_lock(struct _OSAL_UNSLEEPABLE_LOCK_ *pUSL); +u32 unlock_unsleepable_lock(struct _OSAL_UNSLEEPABLE_LOCK_ *pUSL); + +extern unsigned char probe_counter; +extern unsigned char *txbuf; +extern u8 probe_ready; + +enum { + BTMTK_WOBLE_STATE_UNKNOWN, + BTMTK_WOBLE_STATE_SUSPEND, + BTMTK_WOBLE_STATE_RESUME, + BTMTK_WOBLE_STATE_DUMPING, + BTMTK_WOBLE_STATE_DUMPEND, + BTMTK_WOBLE_STATE_NEEDRESET_STACK, +}; + +enum { + BTMTK_SDIO_EVENT_COMPARE_STATE_UNKNOWN, + BTMTK_SDIO_EVENT_COMPARE_STATE_NOTHING_NEED_COMPARE, + BTMTK_SDIO_EVENT_COMPARE_STATE_NEED_COMPARE, + BTMTK_SDIO_EVENT_COMPARE_STATE_COMPARE_SUCCESS, +}; + + +/** + * Maximum rom patch file name length + */ +#define MAX_BIN_FILE_NAME_LEN 32 + + +#define COMPARE_FAIL -1 +#define COMPARE_SUCCESS 1 +#define COMP_EVENT_TIMO 2000 +#define WOBLE_COMP_EVENT_TIMO 5000 +#define WLAN_STATUS_IS_NOT_LOAD -1 +#define WLAN_STATUS_DEFAULT 0 +#define WLAN_STATUS_CALL_REMOVE_START 1 /* WIFI driver is inserted */ + +/** + * BTMTK ioctl + */ +#define BTMTK_IOCTL_MAGIC 'k' + +#define BTMTK_IOCTL_STEREO_GET_CLK _IOR(BTMTK_IOCTL_MAGIC, 1, void *) +#define BTMTK_IOCTL_STEREO_SET_PARA _IOW(BTMTK_IOCTL_MAGIC, 2, void *) + +/** + * Inline functions + */ +static inline int is_support_unify_woble(struct btmtk_sdio_card *data) +{ + if (data->bt_cfg.support_unify_woble) { + if (((data->chip_id & 0xffff) == 0x7668) || + ((data->chip_id & 0xffff) == 0x7663)) + return 1; + else + return 0; + } else { + return 0; + } +} + +static inline int is_mt7668(struct btmtk_sdio_card *data) +{ +#if SUPPORT_MT7668 + return ((data->chip_id & 0xffff) == 0x7668); +#else + return 0; +#endif +} + +static inline int is_mt7663(struct btmtk_sdio_card *data) +{ +#if SUPPORT_MT7663 + return ((data->chip_id & 0xffff) == 0x7663); +#else + return 0; +#endif +} + +#define FW_OWN_OFF "fw own off" +#define FW_OWN_ON "fw own on" + +#define WOBLE_OFF "woble off" +#define WOBLE_ON "woble on" + +#define RX_CHECK_OFF "rx check off" +#define RX_CHECK_ON "rx check on" + +#define RELOAD_SETTING "reload_setting" + +enum BTMTK_SDIO_RX_CHECKPOINT { + BTMTK_SDIO_RX_CHECKPOINT_INTR, + BTMTK_SDIO_RX_CHECKPOINT_RX_START, + BTMTK_SDIO_RX_CHECKPOINT_RX_DONE, + BTMTK_SDIO_RX_CHECKPOINT_ENABLE_INTR, + + BTMTK_SDIO_RX_CHECKPOINT_NUM +}; + +#define BTMTK_SDIO_TIMESTAMP_NUM 50 + +int btmtk_sdio_reset_dongle(void); + +/* WOBX attribute type */ +#define WOBX_TRIGGER_INFO_ADDR_TYPE 1 +#define WOBX_TRIGGER_INFO_ADV_DATA_TYPE 2 +#define WOBX_TRIGGER_INFO_TRACE_LOG_TYPE 3 +#define WOBX_TRIGGER_INFO_SCAN_LOG_TYPE 4 +#define WOBX_TRIGGER_INFO_TRIGGER_CNT_TYPE 5 + +#endif + diff --git a/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/init.btmtksdio.rc b/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/init.btmtksdio.rc new file mode 100644 index 0000000000000..6fc686bbba772 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/bt/mt76xx/sdio/init.btmtksdio.rc @@ -0,0 +1,3 @@ +# load btmtksdio +on boot + insmod /vendor/lib/modules/btmtksdio.ko From 37e928d9f74117331588566e25d58678e27583b6 Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 21:40:26 +0800 Subject: [PATCH 07/32] Add files via upload --- .../misc/mediatek/connectivity/gps/Android.mk | 25 + .../misc/mediatek/connectivity/gps/Makefile | 226 +++ drivers/misc/mediatek/connectivity/gps/README | 2 + .../gps/data_link/gps_dl_context.c | 252 +++ .../gps/data_link/gps_each_link.c | 1714 +++++++++++++++++ .../gps/data_link/hal/gps_dl_conn_infra.c | 109 ++ .../gps/data_link/hal/gps_dl_dma.c | 209 ++ .../gps/data_link/hal/gps_dl_hal.c | 461 +++++ .../gps/data_link/hal/gps_dl_hal_util.c | 15 + .../gps/data_link/hal/gps_dl_isr.c | 335 ++++ .../gps/data_link/hal/gps_dl_mcub.c | 182 ++ .../gps/data_link/hal/gps_dl_power_ctrl.c | 654 +++++++ .../gps/data_link/hal/gps_dl_zbus.c | 12 + .../gps/data_link/hal/gps_dsp_fsm.c | 289 +++ .../gps/data_link/hal/inc/gps_dl_hal.h | 111 ++ .../gps/data_link/hal/inc/gps_dl_hal_api.h | 104 + .../gps/data_link/hal/inc/gps_dl_hal_type.h | 22 + .../gps/data_link/hal/inc/gps_dl_hal_util.h | 34 + .../gps/data_link/hal/inc/gps_dl_isr.h | 139 ++ .../gps/data_link/hal/inc/gps_dsp_fsm.h | 90 + .../gps/data_link/hal/inc/hal_common.h | 17 + .../gps/data_link/hw/gps_dl_hw_bgf.c | 39 + .../gps/data_link/hw/gps_dl_hw_conn_infra.c | 680 +++++++ .../gps/data_link/hw/gps_dl_hw_gps.c | 500 +++++ .../gps/data_link/hw/gps_dl_hw_power_ctrl.c | 695 +++++++ .../gps/data_link/hw/gps_dl_hw_priv_util.h | 221 +++ .../gps/data_link/hw/gps_dl_hw_usrt_apb.c | 450 +++++ .../gps/data_link/hw/gps_dl_hw_util.c | 223 +++ .../coda_gen/conn_infra/conn_host_csr_top.h | 52 + .../coda_gen/conn_infra/conn_infra_cfg.h | 86 + .../coda_gen/conn_infra/conn_infra_rgu.h | 27 + .../connac2_0/coda_gen/conn_infra/conn_pta6.h | 72 + .../coda_gen/conn_infra/conn_rf_spi_mst_reg.h | 32 + .../coda_gen/conn_infra/conn_semaphore.h | 33 + .../coda_gen/conn_infra/conn_uart_pta.h | 65 + .../inc/connac2_0/coda_gen/gps/bgf_gps_cfg.h | 23 + .../inc/connac2_0/coda_gen/gps/bgf_gps_dma.h | 195 ++ .../inc/connac2_0/coda_gen/gps/gps_aon_top.h | 24 + .../inc/connac2_0/coda_gen/gps/gps_cfg_on.h | 28 + .../coda_gen/gps/gps_l5_sys_adrdec.h | 14 + .../connac2_0/coda_gen/gps/gps_l5_usrt_apb.h | 60 + .../inc/connac2_0/coda_gen/gps/gps_rgu_on.h | 109 ++ .../connac2_0/coda_gen/gps/gps_sys_adrdec.h | 14 + .../inc/connac2_0/coda_gen/gps/gps_usrt_apb.h | 99 + .../hw/inc/connac2_0/gps_dl_hw_dep_api.h | 97 + .../gps/data_link/hw/inc/gps_dl_hw_api.h | 179 ++ .../gps/data_link/hw/inc/gps_dl_hw_type.h | 31 + .../gps/data_link/hw/inc/gps_dl_hw_ver.h | 16 + .../gps/data_link/inc/gps_dl_config.h | 64 + .../gps/data_link/inc/gps_dl_context.h | 76 + .../gps/data_link/inc/gps_dl_log.h | 255 +++ .../gps/data_link/inc/gps_each_link.h | 264 +++ .../gps/data_link/lib/gps_dl_dma_buf.c | 722 +++++++ .../gps/data_link/lib/gps_dl_hist_rec.c | 159 ++ .../gps/data_link/lib/gps_dl_lib_misc.c | 146 ++ .../gps/data_link/lib/gps_dl_name_list.c | 201 ++ .../gps/data_link/lib/gps_dl_time_tick.c | 53 + .../gps/data_link/lib/inc/gps_dl_base.h | 38 + .../gps/data_link/lib/inc/gps_dl_dma_buf.h | 157 ++ .../gps/data_link/lib/inc/gps_dl_hist_rec.h | 23 + .../gps/data_link/lib/inc/gps_dl_lib_misc.h | 29 + .../gps/data_link/lib/inc/gps_dl_name_list.h | 33 + .../gps/data_link/lib/inc/gps_dl_time_tick.h | 23 + .../gps/data_link/link/gps_dl_subsys_reset.c | 401 ++++ .../data_link/link/inc/gps_dl_subsys_reset.h | 53 + .../data_link/linux/gps_data_link_devices.c | 343 ++++ .../gps/data_link/linux/gps_dl_ctrld.c | 372 ++++ .../gps/data_link/linux/gps_dl_emi.c | 228 +++ .../gps/data_link/linux/gps_dl_linux.c | 148 ++ .../data_link/linux/gps_dl_linux_plat_drv.c | 555 ++++++ .../linux/gps_dl_linux_reserved_mem.c | 204 ++ .../gps/data_link/linux/gps_dl_osal.c | 326 ++++ .../gps/data_link/linux/gps_dl_procfs.c | 239 +++ .../gps/data_link/linux/gps_each_device.c | 469 +++++ .../linux/inc/gps_data_link_devices.h | 22 + .../gps/data_link/linux/inc/gps_dl_ctrld.h | 44 + .../gps/data_link/linux/inc/gps_dl_emi.h | 17 + .../gps/data_link/linux/inc/gps_dl_linux.h | 43 + .../linux/inc/gps_dl_linux_plat_drv.h | 41 + .../linux/inc/gps_dl_linux_reserved_mem.h | 29 + .../gps/data_link/linux/inc/gps_dl_osal.h | 203 ++ .../gps/data_link/linux/inc/gps_dl_procfs.h | 22 + .../gps/data_link/linux/inc/gps_each_device.h | 72 + .../mediatek/connectivity/gps/fw_log_gps.c | 259 +++ drivers/misc/mediatek/connectivity/gps/gps.h | 101 + .../mediatek/connectivity/gps/gps_dl_module.c | 59 + .../misc/mediatek/connectivity/gps/gps_emi.c | 507 +++++ .../mediatek/connectivity/gps/gps_mt3337.c | 101 + .../mediatek/connectivity/gps/init.gps_drv.rc | 4 + .../gps/lna_ctrl/inc/gps_lna_drv.h | 19 + .../gps/lna_ctrl/src/gps_lna_drv.c | 294 +++ .../connectivity/gps/stp_chrdev_gps.c | 1369 +++++++++++++ .../connectivity/gps/stp_chrdev_gps2.c | 844 ++++++++ 93 files changed, 18697 insertions(+) create mode 100644 drivers/misc/mediatek/connectivity/gps/Android.mk create mode 100644 drivers/misc/mediatek/connectivity/gps/Makefile create mode 100644 drivers/misc/mediatek/connectivity/gps/README create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/gps_dl_context.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/gps_each_link.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_conn_infra.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_dma.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_hal.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_hal_util.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_isr.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_mcub.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_power_ctrl.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_zbus.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dsp_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/gps_dl_hal.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/gps_dl_hal_api.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/gps_dl_hal_type.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/gps_dl_hal_util.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/gps_dl_isr.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/gps_dsp_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/hal_common.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_bgf.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_conn_infra.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_gps.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_power_ctrl.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_priv_util.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_usrt_apb.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_util.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_host_csr_top.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_infra_cfg.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_infra_rgu.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_pta6.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_rf_spi_mst_reg.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_semaphore.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_uart_pta.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/bgf_gps_cfg.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/bgf_gps_dma.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_aon_top.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_cfg_on.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_l5_sys_adrdec.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_l5_usrt_apb.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_rgu_on.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_sys_adrdec.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_usrt_apb.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/gps_dl_hw_dep_api.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/gps_dl_hw_api.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/gps_dl_hw_type.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/gps_dl_hw_ver.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/inc/gps_dl_config.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/inc/gps_dl_context.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/inc/gps_dl_log.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/inc/gps_each_link.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/lib/gps_dl_dma_buf.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/lib/gps_dl_hist_rec.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/lib/gps_dl_lib_misc.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/lib/gps_dl_name_list.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/lib/gps_dl_time_tick.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/lib/inc/gps_dl_base.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/lib/inc/gps_dl_dma_buf.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/lib/inc/gps_dl_hist_rec.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/lib/inc/gps_dl_lib_misc.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/lib/inc/gps_dl_name_list.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/lib/inc/gps_dl_time_tick.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/link/gps_dl_subsys_reset.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/link/inc/gps_dl_subsys_reset.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_data_link_devices.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_ctrld.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_emi.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_linux.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_linux_plat_drv.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_linux_reserved_mem.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_osal.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_procfs.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_each_device.c create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_data_link_devices.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_ctrld.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_emi.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_linux.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_linux_plat_drv.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_linux_reserved_mem.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_osal.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_procfs.h create mode 100644 drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_each_device.h create mode 100644 drivers/misc/mediatek/connectivity/gps/fw_log_gps.c create mode 100644 drivers/misc/mediatek/connectivity/gps/gps.h create mode 100644 drivers/misc/mediatek/connectivity/gps/gps_dl_module.c create mode 100644 drivers/misc/mediatek/connectivity/gps/gps_emi.c create mode 100644 drivers/misc/mediatek/connectivity/gps/gps_mt3337.c create mode 100644 drivers/misc/mediatek/connectivity/gps/init.gps_drv.rc create mode 100644 drivers/misc/mediatek/connectivity/gps/lna_ctrl/inc/gps_lna_drv.h create mode 100644 drivers/misc/mediatek/connectivity/gps/lna_ctrl/src/gps_lna_drv.c create mode 100644 drivers/misc/mediatek/connectivity/gps/stp_chrdev_gps.c create mode 100644 drivers/misc/mediatek/connectivity/gps/stp_chrdev_gps2.c diff --git a/drivers/misc/mediatek/connectivity/gps/Android.mk b/drivers/misc/mediatek/connectivity/gps/Android.mk new file mode 100644 index 0000000000000..fe503b64db0c7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/Android.mk @@ -0,0 +1,25 @@ +LOCAL_PATH := $(call my-dir) + +ifeq ($(MTK_GPS_SUPPORT), yes) + +include $(CLEAR_VARS) +LOCAL_MODULE := gps_drv.ko +LOCAL_PROPRIETARY_MODULE := true +LOCAL_MODULE_OWNER := mtk +LOCAL_INIT_RC := init.gps_drv.rc + +ifneq (,$(filter MT6885 MT6893,$(MTK_PLATFORM))) +#Only set dependency to conninfra.ko when CONSYS_CHIP in list. +ifneq (,$(filter CONSYS_6885 CONSYS_6893,$(MTK_COMBO_CHIP))) +LOCAL_REQUIRED_MODULES := conninfra.ko +else +$(warning MTK_PLATFORM=$(MTK_PLATFORM), MTK_COMBO_CHIP=$(MTK_COMBO_CHIP)) +$(warning gps_drv.ko does not claim the requirement for conninfra.ko) +endif +else +LOCAL_REQUIRED_MODULES := wmt_drv.ko +endif + +include $(MTK_KERNEL_MODULE) + +endif diff --git a/drivers/misc/mediatek/connectivity/gps/Makefile b/drivers/misc/mediatek/connectivity/gps/Makefile new file mode 100644 index 0000000000000..2afaca3babb77 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/Makefile @@ -0,0 +1,226 @@ +MTK_PLATFORM := $(subst ",,$(CONFIG_MTK_PLATFORM)) +# drivers/barcelona/gps/Makefile +# +# Makefile for the Barcelona GPS driver. +# +# Copyright (C) 2004,2005 TomTom BV +# Author: Dimitry Andric +# +# 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. + +############################################################################### +# Necessary Check +MTK_PLATFORM := $(subst ",,$(CONFIG_MTK_PLATFORM)) +ifeq ($(CONFIG_MTK_GPS_SUPPORT), y) + +ifeq ($(AUTOCONF_H),) + $(error AUTOCONF_H is not defined) +endif + +ccflags-y += -imacros $(AUTOCONF_H) +ifndef TOP + TOP := $(srctree)/.. +endif +ifeq ($(TARGET_BUILD_VARIANT),$(filter $(TARGET_BUILD_VARIANT),userdebug user)) + ldflags-y += -s +endif + +# Force build fail on modpost warning +KBUILD_MODPOST_FAIL_ON_WARNINGS := y +############################################################################### + +# only WMT align this design flow, but gps use this also. +#ccflags-y += -D MTK_WCN_REMOVE_KERNEL_MODULE + +ifeq ($(CONFIG_ARM64), y) + ccflags-y += -D CONFIG_MTK_WCN_ARM64 +endif + +ifeq ($(CONFIG_MTK_CONN_LTE_IDC_SUPPORT),y) + ccflags-y += -D WMT_IDC_SUPPORT=1 +else + ccflags-y += -D WMT_IDC_SUPPORT=0 +endif +ccflags-y += -D MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include/mach +ccflags-y += -I$(srctree)/drivers/misc/mediatek/freqhopping +ccflags-y += -I$(srctree)/drivers/misc/mediatek/freqhopping/$(MTK_PLATFORM) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/emi/submodule +ccflags-y += -I$(srctree)/drivers/misc/mediatek/emi/$(MTK_PLATFORM) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/connectivity/common +ccflags-y += -I$(srctree)/drivers/misc/mediatek/mach/$(MTK_PLATFORM)/include/mach +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/$(MTK_PLATFORM) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include/clkbuf_v1 +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include/clkbuf_v1/$(MTK_PLATFORM) +ccflags-y += -I$(srctree)/drivers/devfreq +############################################################################### + +MODULE_NAME := gps_drv +obj-m += $(MODULE_NAME).o + +GPS_DRV_CONTROL_LNA := n +SELECT_GPS_DL_DRV := n +GPS_DL_HAS_MOCK := n +GPS_DL_HAS_CONNINFRA_DRV := n +GPS_SRC_FOLDER := $(TOP)/vendor/mediatek/kernel_modules/connectivity/gps + +ifeq ($(CONFIG_ARCH_MTK_PROJECT),"k6833v1_64_swrgo") +ccflags-y += -DCONFIG_GPSL5_SUPPORT +ccflags-y += -DCONFIG_GPS_CTRL_LNA_SUPPORT +GPS_DRV_CONTROL_LNA := y +endif + +ifeq ($(CONFIG_MACH_MT6833),y) +ccflags-y += -DCONFIG_GPSL5_SUPPORT +ccflags-y += -DCONFIG_GPS_CTRL_LNA_SUPPORT +GPS_DRV_CONTROL_LNA := y +endif + +ifeq ($(CONFIG_MACH_MT6885),y) +SELECT_GPS_DL_DRV := y +ccflags-y += -I$(GPS_SRC_FOLDER)/data_link/hw/inc/connac2_0 +ccflags-y += -I$(GPS_SRC_FOLDER)/data_link/hw/inc/connac2_0/coda_gen +ifeq ($(CONFIG_MTK_COMBO_CHIP_CONSYS_6885),y) +GPS_DL_HAS_CONNINFRA_DRV := y +endif +ifeq ($(CONFIG_MTK_COMBO_CHIP_CONSYS_6893),y) +GPS_DL_HAS_CONNINFRA_DRV := y +endif +endif + +ifeq ($(CONFIG_MACH_MT6893),y) +SELECT_GPS_DL_DRV := y +# For MT6893, the CODA is same as connac2_0 +ccflags-y += -I$(GPS_SRC_FOLDER)/data_link/hw/inc/connac2_0 +ccflags-y += -I$(GPS_SRC_FOLDER)/data_link/hw/inc/connac2_0/coda_gen +ifeq ($(CONFIG_MTK_COMBO_CHIP_CONSYS_6885),y) +GPS_DL_HAS_CONNINFRA_DRV := y +endif +ifeq ($(CONFIG_MTK_COMBO_CHIP_CONSYS_6893),y) +GPS_DL_HAS_CONNINFRA_DRV := y +endif +endif + +ifeq ($(SELECT_GPS_DL_DRV),y) # New GPS driver with L1+L5 support +ifeq ($(GPS_DL_HAS_CONNINFRA_DRV),y) +CONNINFRA_SRC_FOLDER := $(TOP)/vendor/mediatek/kernel_modules/connectivity/conninfra +ccflags-y += -I$(CONNINFRA_SRC_FOLDER)/include +ccflags-y += -DGPS_DL_HAS_CONNINFRA_DRV=1 +endif + +ccflags-y += -I$(GPS_SRC_FOLDER)/data_link/inc +ccflags-y += -I$(GPS_SRC_FOLDER)/data_link/linux/inc +ccflags-y += -I$(GPS_SRC_FOLDER)/data_link/link/inc +ccflags-y += -I$(GPS_SRC_FOLDER)/data_link/lib/inc +ccflags-y += -I$(GPS_SRC_FOLDER)/data_link/hal/inc +ccflags-y += -I$(GPS_SRC_FOLDER)/data_link/hw/inc +ccflags-y += -I$(GPS_SRC_FOLDER)/data_link_mock/mock/inc + +$(MODULE_NAME)-objs += gps_dl_module.o +$(MODULE_NAME)-objs += data_link/gps_dl_context.o + +$(MODULE_NAME)-objs += data_link/lib/gps_dl_dma_buf.o +$(MODULE_NAME)-objs += data_link/lib/gps_dl_lib_misc.o +$(MODULE_NAME)-objs += data_link/lib/gps_dl_hist_rec.o +$(MODULE_NAME)-objs += data_link/lib/gps_dl_time_tick.o +$(MODULE_NAME)-objs += data_link/lib/gps_dl_name_list.o + +$(MODULE_NAME)-objs += data_link/hw/gps_dl_hw_conn_infra.o +$(MODULE_NAME)-objs += data_link/hw/gps_dl_hw_bgf.o +$(MODULE_NAME)-objs += data_link/hw/gps_dl_hw_gps.o +$(MODULE_NAME)-objs += data_link/hw/gps_dl_hw_power_ctrl.o +$(MODULE_NAME)-objs += data_link/hw/gps_dl_hw_usrt_apb.o +$(MODULE_NAME)-objs += data_link/hw/gps_dl_hw_util.o + +$(MODULE_NAME)-objs += data_link/hal/gps_dl_hal.o +$(MODULE_NAME)-objs += data_link/hal/gps_dl_hal_util.o +$(MODULE_NAME)-objs += data_link/hal/gps_dsp_fsm.o +$(MODULE_NAME)-objs += data_link/hal/gps_dl_power_ctrl.o +$(MODULE_NAME)-objs += data_link/hal/gps_dl_isr.o +$(MODULE_NAME)-objs += data_link/hal/gps_dl_dma.o +$(MODULE_NAME)-objs += data_link/hal/gps_dl_mcub.o +$(MODULE_NAME)-objs += data_link/hal/gps_dl_zbus.o +$(MODULE_NAME)-objs += data_link/hal/gps_dl_conn_infra.o + +$(MODULE_NAME)-objs += data_link/link/gps_dl_subsys_reset.o +$(MODULE_NAME)-objs += data_link/gps_each_link.o + +$(MODULE_NAME)-objs += data_link/linux/gps_data_link_devices.o +$(MODULE_NAME)-objs += data_link/linux/gps_each_device.o +$(MODULE_NAME)-objs += data_link/linux/gps_dl_linux.o +$(MODULE_NAME)-objs += data_link/linux/gps_dl_linux_plat_drv.o +$(MODULE_NAME)-objs += data_link/linux/gps_dl_linux_reserved_mem.o +$(MODULE_NAME)-objs += data_link/linux/gps_dl_emi.o +$(MODULE_NAME)-objs += data_link/linux/gps_dl_ctrld.o +$(MODULE_NAME)-objs += data_link/linux/gps_dl_procfs.o +$(MODULE_NAME)-objs += data_link/linux/gps_dl_osal.o + +ifeq ($(GPS_DL_HAS_MOCK),y) +$(MODULE_NAME)-objs += data_link_mock/mock/gps_mock_mvcd.o +$(MODULE_NAME)-objs += data_link_mock/mock/gps_mock_hal.o +ccflags-y += -DGPS_DL_HAS_MOCK=1 +endif + +else #Legacy drivers +WMT_SRC_FOLDER := $(TOP)/vendor/mediatek/kernel_modules/connectivity/common + +ifeq ($(CONFIG_MTK_COMBO_CHIP),) + $(error CONFIG_MTK_COMBO_CHIP not defined) +endif + +ifneq ($(filter "CONSYS_%",$(CONFIG_MTK_COMBO_CHIP)),) + ccflags-y += -DSOC_CO_CLOCK_FLAG=1 + ccflags-y += -DWMT_CREATE_NODE_DYNAMIC=1 + ccflags-y += -DREMOVE_MK_NODE=0 + +ccflags-y += -I$(WMT_SRC_FOLDER)/common_main/$(MTK_PLATFORM)/include + +else + ccflags-y += -DSOC_CO_CLOCK_FLAG=0 + ccflags-y += -DWMT_CREATE_NODE_DYNAMIC=0 + ccflags-y += -DREMOVE_MK_NODE=1 +endif + +ccflags-y += -I$(WMT_SRC_FOLDER)/common_main/include +ccflags-y += -I$(WMT_SRC_FOLDER)/common_main/linux/include +ccflags-y += -I$(WMT_SRC_FOLDER)/common_main/core/include +ccflags-y += -I$(WMT_SRC_FOLDER)/common_main/platform/include +ifneq ($(CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH),) +ccflags-y += -I$(WMT_SRC_FOLDER)/debug_utility +endif +ifeq ($(GPS_DRV_CONTROL_LNA),y) +ccflags-y += -I$(GPS_SRC_FOLDER)/lna_ctrl/inc +endif + +ifeq ($(CONFIG_MTK_CONN_MT3337_CHIP_SUPPORT),y) + $(MODULE_NAME)-objs += gps_mt3337.o +else + $(MODULE_NAME)-objs += stp_chrdev_gps.o +ifeq ($(CONFIG_ARCH_MTK_PROJECT),"k6833v1_64_swrgo") + $(MODULE_NAME)-objs += stp_chrdev_gps2.o +endif +ifeq ($(CONFIG_MACH_MT6833),y) + $(MODULE_NAME)-objs += stp_chrdev_gps2.o +endif +ifeq ($(GPS_DRV_CONTROL_LNA),y) + $(MODULE_NAME)-objs += lna_ctrl/src/gps_lna_drv.o +endif +endif +ifneq ($(CONFIG_MTK_GPS_EMI),) +$(MODULE_NAME)-objs += gps_emi.o +endif +ifneq ($(CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH),) +$(MODULE_NAME)-objs += fw_log_gps.o +endif + +endif + +endif #ifeq ($(CONFIG_MTK_GPS_SUPPORT), y) +# EOF diff --git a/drivers/misc/mediatek/connectivity/gps/README b/drivers/misc/mediatek/connectivity/gps/README new file mode 100644 index 0000000000000..9046e3ac61ef2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/README @@ -0,0 +1,2 @@ +GPS driver - kernel modules move out of kernel tree + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/gps_dl_context.c b/drivers/misc/mediatek/connectivity/gps/data_link/gps_dl_context.c new file mode 100644 index 0000000000000..9f4a6f311aa68 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/gps_dl_context.c @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "gps_dl_config.h" +#include "gps_dl_context.h" +#include "gps_dl_hw_api.h" + +#if GPS_DL_ON_LINUX +#define GPS_DL_ISR_DATA0 gps_dl_linux_irq_dispatcher +#define GPS_DL_ISR_NODATA0 gps_dl_linux_irq_dispatcher +#define GPS_DL_ISR_MCUB0 gps_dl_linux_irq_dispatcher +#define GPS_DL_ISR_DATA1 gps_dl_linux_irq_dispatcher +#define GPS_DL_ISR_NODATA1 gps_dl_linux_irq_dispatcher +#define GPS_DL_ISR_MCUB1 gps_dl_linux_irq_dispatcher +#define GPS_DL_ISR_DMA gps_dl_linux_irq_dispatcher +#elif GPS_DL_ON_CTP +#define GPS_DL_ISR_DATA0 gps_dl_isr_dl0_has_data +#define GPS_DL_ISR_NODATA0 gps_dl_isr_dl0_has_nodata +#define GPS_DL_ISR_MCUB0 gps_dl_isr_dl0_mcub +#define GPS_DL_ISR_DATA1 gps_dl_isr_dl1_has_data +#define GPS_DL_ISR_NODATA1 gps_dl_isr_dl1_has_nodata +#define GPS_DL_ISR_MCUB1 gps_dl_isr_dl1_mcub +#define GPS_DL_ISR_DMA gps_dl_isr_dma_done +#endif + +static struct gps_dl_ctx s_gps_dl_ctx = { + .links = { + /* for /dev/gpsdl0 */ + {.cfg = {.tx_buf_size = GPS_DL_TX_BUF_SIZE, .rx_buf_size = GPS_DL_RX_BUF_SIZE} }, + + /* for /dev/gpsdl1 */ + {.cfg = {.tx_buf_size = GPS_DL_TX_BUF_SIZE, .rx_buf_size = GPS_DL_RX_BUF_SIZE} }, + }, + .irqs = { + {.cfg = {.index = GPS_DL_IRQ_LINK0_DATA, .name = "gps_da0", + .trig_type = GPS_DL_IRQ_TRIG_LEVEL_HIGH, + .isr = (void *)GPS_DL_ISR_DATA0} }, + {.cfg = {.index = GPS_DL_IRQ_LINK0_NODATA, .name = "gps_nd0", + .trig_type = GPS_DL_IRQ_TRIG_LEVEL_HIGH, + .isr = (void *)GPS_DL_ISR_NODATA0} }, + {.cfg = {.index = GPS_DL_IRQ_LINK0_MCUB, .name = "gps_mb0", + .trig_type = GPS_DL_IRQ_TRIG_LEVEL_HIGH, + .isr = (void *)GPS_DL_ISR_MCUB0} }, + {.cfg = {.index = GPS_DL_IRQ_LINK1_DATA, .name = "gps_da1", + .trig_type = GPS_DL_IRQ_TRIG_LEVEL_HIGH, + .isr = (void *)GPS_DL_ISR_DATA1} }, + {.cfg = {.index = GPS_DL_IRQ_LINK1_NODATA, .name = "gps_nd1", + .trig_type = GPS_DL_IRQ_TRIG_LEVEL_HIGH, + .isr = (void *)GPS_DL_ISR_NODATA1} }, + {.cfg = {.index = GPS_DL_IRQ_LINK1_MCUB, .name = "gps_mb1", + .trig_type = GPS_DL_IRQ_TRIG_LEVEL_HIGH, + .isr = (void *)GPS_DL_ISR_MCUB1} }, + {.cfg = {.index = GPS_DL_IRQ_DMA, .name = "gps_dma", + .trig_type = GPS_DL_IRQ_TRIG_LEVEL_HIGH, + .isr = (void *)GPS_DL_ISR_DMA} }, + }, +#if GPS_DL_ON_LINUX + .devices = { + /* for /dev/gpsdl0 */ + {.cfg = {.dev_name = "gpsdl0", .index = 0} }, + + /* for /dev/gpsdl1 */ + {.cfg = {.dev_name = "gpsdl1", .index = 1} }, + }, +#endif /* GPS_DL_ON_LINUX */ +}; + +static struct gps_dl_runtime_cfg s_gps_rt_cfg = { + .dma_is_1byte_mode = false, + .dma_is_enabled = true, + .show_reg_rw_log = false, + .show_reg_wait_log = true, + .only_show_wait_done_log = true, + .log_level = GPS_DL_LOG_DEF_SETTING_LEVEL, + .log_mod_bitmask = GPS_DL_LOG_DEF_SETTING_MODULES, + .log_reg_rw_bitmask = GPS_DL_LOG_REG_RW_BITMASK, +}; + +struct gps_each_link *gps_dl_link_get(enum gps_dl_link_id_enum link_id) +{ + if (link_id >= 0 && link_id < GPS_DATA_LINK_NUM) + return &s_gps_dl_ctx.links[link_id]; + + return NULL; +} + +struct gps_each_irq *gps_dl_irq_get(enum gps_dl_irq_index_enum irq_idx) +{ + if (irq_idx >= 0 && irq_idx < GPS_DL_IRQ_NUM) + return &s_gps_dl_ctx.irqs[irq_idx]; + + return NULL; +} + +#if GPS_DL_ON_LINUX +struct gps_each_device *gps_dl_device_get(enum gps_dl_link_id_enum link_id) +{ + if (link_id >= 0 && link_id < GPS_DATA_LINK_NUM) + return &s_gps_dl_ctx.devices[link_id]; + + return NULL; +} +#endif + +struct gps_dl_remap_ctx *gps_dl_remap_ctx_get(void) +{ + return &s_gps_dl_ctx.remap_ctx; +} + +bool gps_dl_is_1byte_mode(void) +{ + return s_gps_rt_cfg.dma_is_1byte_mode; +} + +bool gps_dl_set_1byte_mode(bool is_1byte_mode) +{ + bool old = s_gps_rt_cfg.dma_is_1byte_mode; + + s_gps_rt_cfg.dma_is_1byte_mode = is_1byte_mode; + return old; +} + +bool gps_dl_is_dma_enabled(void) +{ + return s_gps_rt_cfg.dma_is_enabled; +} + +bool gps_dl_set_dma_enabled(bool to_enable) +{ + bool old = s_gps_rt_cfg.dma_is_enabled; + + s_gps_rt_cfg.dma_is_enabled = to_enable; + return old; +} + +bool gps_dl_show_reg_rw_log(void) +{ + return s_gps_rt_cfg.show_reg_rw_log; +} + +bool gps_dl_show_reg_wait_log(void) +{ + return s_gps_rt_cfg.show_reg_wait_log; +} + +bool gps_dl_only_show_wait_done_log(void) +{ + return s_gps_rt_cfg.only_show_wait_done_log; +} + +bool gps_dl_set_show_reg_rw_log(bool on) +{ + bool last_on = s_gps_rt_cfg.show_reg_rw_log; + + s_gps_rt_cfg.show_reg_rw_log = on; + return last_on; +} + +void gps_dl_set_show_reg_wait_log(bool on) +{ + s_gps_rt_cfg.show_reg_wait_log = on; +} + +int gps_dl_set_rx_transfer_max(enum gps_dl_link_id_enum link_id, int max) +{ + struct gps_each_link *p_link; + int old_max = 0; + + p_link = gps_dl_link_get(link_id); + + if (p_link) { + old_max = p_link->rx_dma_buf.transfer_max; + p_link->rx_dma_buf.transfer_max = max; + GDL_LOGXD(link_id, "old_max = %d, new_max = %d", old_max, max); + } + + return old_max; +} + +int gps_dl_set_tx_transfer_max(enum gps_dl_link_id_enum link_id, int max) +{ + struct gps_each_link *p_link; + int old_max = 0; + + p_link = gps_dl_link_get(link_id); + + if (p_link) { + old_max = p_link->tx_dma_buf.transfer_max; + p_link->tx_dma_buf.transfer_max = max; + GDL_LOGXD(link_id, "old_max = %d, new_max = %d", old_max, max); + } + + return old_max; +} + +enum gps_dl_log_level_enum gps_dl_log_level_get(void) +{ + return s_gps_rt_cfg.log_level; +} + +void gps_dl_log_level_set(enum gps_dl_log_level_enum level) +{ + s_gps_rt_cfg.log_level = level; +} + +bool gps_dl_log_mod_is_on(enum gps_dl_log_module_enum mod) +{ + return (bool)(s_gps_rt_cfg.log_mod_bitmask & (1UL << mod)); +} + +void gps_dl_log_mod_on(enum gps_dl_log_module_enum mod) +{ + s_gps_rt_cfg.log_mod_bitmask |= (1UL << mod); +} + +void gps_dl_log_mod_off(enum gps_dl_log_module_enum mod) +{ + s_gps_rt_cfg.log_mod_bitmask &= ~(1UL << mod); +} + +void gps_dl_log_mod_bitmask_set(unsigned int bitmask) +{ + s_gps_rt_cfg.log_mod_bitmask = bitmask; +} + +unsigned int gps_dl_log_mod_bitmask_get(void) +{ + return s_gps_rt_cfg.log_mod_bitmask; +} + +bool gps_dl_log_reg_rw_is_on(enum gps_dl_log_reg_rw_ctrl_enum log_reg_rw) +{ + return (bool)(s_gps_rt_cfg.log_reg_rw_bitmask & (1UL << log_reg_rw)); +} + +void gps_dl_log_info_show(void) +{ + bool show_reg_rw_log = gps_dl_show_reg_rw_log(); + + GDL_LOGE("level = %d, bitmask = 0x%08x, rrw = %d", + s_gps_rt_cfg.log_level, s_gps_rt_cfg.log_mod_bitmask, show_reg_rw_log); +} + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/gps_each_link.c b/drivers/misc/mediatek/connectivity/gps/data_link/gps_each_link.c new file mode 100644 index 0000000000000..109d8e41308f7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/gps_each_link.c @@ -0,0 +1,1714 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "gps_dl_config.h" +#include "gps_dl_time_tick.h" + +#include "gps_each_link.h" +#include "gps_dl_hal.h" +#include "gps_dl_hal_api.h" +#include "gps_dl_hal_util.h" +#include "gps_dl_hw_api.h" +#include "gps_dl_isr.h" +#include "gps_dl_lib_misc.h" +#include "gps_dsp_fsm.h" +#include "gps_dl_osal.h" +#include "gps_dl_name_list.h" +#include "gps_dl_context.h" +#include "gps_dl_subsys_reset.h" + +#include "linux/jiffies.h" + +#include "linux/errno.h" +#if GPS_DL_HAS_PLAT_DRV +#include "gps_dl_linux_plat_drv.h" +#endif + +void gps_each_link_set_bool_flag(enum gps_dl_link_id_enum link_id, + enum gps_each_link_bool_state name, bool value) +{ + struct gps_each_link *p = gps_dl_link_get(link_id); + + if (!p) + return; + + gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + switch (name) { + case LINK_TO_BE_CLOSED: + p->sub_states.to_be_closed = value; + break; + case LINK_USER_OPEN: + p->sub_states.user_open = value; + break; + case LINK_OPEN_RESULT_OKAY: + p->sub_states.open_result_okay = value; + break; + case LINK_NEED_A2Z_DUMP: + p->sub_states.need_a2z_dump = value; + break; + case LINK_SUSPEND_TO_CLK_EXT: + p->sub_states.suspend_to_clk_ext = value; + break; + default: + break; /* do nothing */ + } + gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); +} + +bool gps_each_link_get_bool_flag(enum gps_dl_link_id_enum link_id, + enum gps_each_link_bool_state name) +{ + struct gps_each_link *p = gps_dl_link_get(link_id); + bool value = false; + + if (!p) + return false; + + gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + switch (name) { + case LINK_TO_BE_CLOSED: + value = p->sub_states.to_be_closed; + break; + case LINK_USER_OPEN: + value = p->sub_states.user_open; + break; + case LINK_OPEN_RESULT_OKAY: + value = p->sub_states.open_result_okay; + break; + case LINK_NEED_A2Z_DUMP: + value = p->sub_states.need_a2z_dump; + break; + case LINK_SUSPEND_TO_CLK_EXT: + value = p->sub_states.suspend_to_clk_ext; + break; + default: + break; /* TODO: warning it */ + } + gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + + return value; +} + +void gps_dl_link_set_ready_to_write(enum gps_dl_link_id_enum link_id, bool is_ready) +{ + struct gps_each_link *p = gps_dl_link_get(link_id); + + gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + if (p) + p->sub_states.is_ready_to_write = is_ready; + gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); +} + +bool gps_dl_link_is_ready_to_write(enum gps_dl_link_id_enum link_id) +{ + struct gps_each_link *p = gps_dl_link_get(link_id); + bool ready; + + gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + if (p) + ready = p->sub_states.is_ready_to_write; + else + ready = false; + gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + + return ready; +} + +void gps_each_link_set_active(enum gps_dl_link_id_enum link_id, bool is_active) +{ + struct gps_each_link *p = gps_dl_link_get(link_id); + + gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + if (p) + p->sub_states.is_active = is_active; + gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); +} + +bool gps_each_link_is_active(enum gps_dl_link_id_enum link_id) +{ + struct gps_each_link *p = gps_dl_link_get(link_id); + bool ready; + + gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + if (p) + ready = p->sub_states.is_active; + else + ready = false; + gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + + return ready; +} + +void gps_each_link_inc_session_id(enum gps_dl_link_id_enum link_id) +{ + struct gps_each_link *p = gps_dl_link_get(link_id); + int sid; + + gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + if (p->session_id >= GPS_EACH_LINK_SID_MAX) + p->session_id = 1; + else + p->session_id++; + sid = p->session_id; + gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + + GDL_LOGXD(link_id, "new sid = %d, 1byte_mode = %d", sid, gps_dl_is_1byte_mode()); +} + +int gps_each_link_get_session_id(enum gps_dl_link_id_enum link_id) +{ + struct gps_each_link *p = gps_dl_link_get(link_id); + int sid; + + gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + sid = p->session_id; + gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + + return sid; +} + +void gps_dl_link_open_wait(enum gps_dl_link_id_enum link_id, long *p_sigval) +{ + struct gps_each_link *p = gps_dl_link_get(link_id); + enum GDL_RET_STATUS gdl_ret; + long sigval; + + gdl_ret = gps_dl_link_wait_on(&p->waitables[GPS_DL_WAIT_OPEN_CLOSE], &sigval); + if (gdl_ret == GDL_FAIL_SIGNALED) { + if (p_sigval != NULL) { + *p_sigval = sigval; + return; + } + } else if (gdl_ret == GDL_FAIL_NOT_SUPPORT) + ; /* show warnning */ +} + +void gps_dl_link_open_ack(enum gps_dl_link_id_enum link_id, bool okay, bool hw_resume) +{ +#if 0 + enum GDL_RET_STATUS gdl_ret; + struct gdl_dma_buf_entry dma_buf_entry; +#endif + struct gps_each_link *p = gps_dl_link_get(link_id); + bool send_msg = false; + + GDL_LOGXD_ONF(link_id, "hw_resume = %d", hw_resume); + + /* TODO: open fail case */ + gps_each_link_set_bool_flag(link_id, LINK_OPEN_RESULT_OKAY, okay); + gps_dl_link_wake_up(&p->waitables[GPS_DL_WAIT_OPEN_CLOSE]); + + gps_each_link_take_big_lock(link_id, GDL_LOCK_FOR_OPEN_DONE); + if (gps_each_link_get_bool_flag(link_id, LINK_USER_OPEN) && okay) { + GDL_LOGXW_ONF(link_id, + "user still online, try to change to opened"); + + /* Note: if pre_status not OPENING, it might be RESETTING, not handle it here */ + if (hw_resume) + gps_each_link_change_state_from(link_id, LINK_RESUMING, LINK_OPENED); + else + gps_each_link_change_state_from(link_id, LINK_OPENING, LINK_OPENED); + + /* TODO: ack on DSP reset done */ +#if 0 + /* if has pending data, can send it now */ + gdl_ret = gdl_dma_buf_get_data_entry(&p->tx_dma_buf, &dma_buf_entry); + if (gdl_ret == GDL_OKAY) + gps_dl_hal_a2d_tx_dma_start(link_id, &dma_buf_entry); +#endif + } else { + GDL_LOGXW_ONF(link_id, + "okay = %d or user already offline, try to change to closing", okay); + + /* Note: if pre_status not OPENING, it might be RESETTING, not handle it here */ + if (gps_each_link_change_state_from(link_id, LINK_OPENING, LINK_CLOSING)) + send_msg = true; + } + gps_each_link_give_big_lock(link_id); + + if (send_msg) { + gps_dl_link_event_send(GPS_DL_EVT_LINK_CLOSE, link_id); + gps_each_link_set_bool_flag(link_id, LINK_TO_BE_CLOSED, true); + } +} + +void gps_each_link_init(enum gps_dl_link_id_enum link_id) +{ + struct gps_each_link *p = gps_dl_link_get(link_id); + + p->session_id = 0; + gps_each_link_mutexes_init(p); + gps_each_link_spin_locks_init(p); + gps_each_link_set_active(link_id, false); + gps_dl_link_set_ready_to_write(link_id, false); + gps_each_link_context_init(link_id); + gps_each_link_set_state(link_id, LINK_CLOSED); +} + +void gps_each_link_deinit(enum gps_dl_link_id_enum link_id) +{ + struct gps_each_link *p = gps_dl_link_get(link_id); + + gps_each_link_set_state(link_id, LINK_UNINIT); + gps_each_link_mutexes_deinit(p); + gps_each_link_spin_locks_deinit(p); +} + +void gps_each_link_context_init(enum gps_dl_link_id_enum link_id) +{ + enum gps_each_link_waitable_type j; + + for (j = 0; j < GPS_DL_WAIT_NUM; j++) + gps_dl_link_waitable_reset(link_id, j); +} + +void gps_each_link_context_clear(enum gps_dl_link_id_enum link_id) +{ + gps_dl_link_waitable_reset(link_id, GPS_DL_WAIT_WRITE); + gps_dl_link_waitable_reset(link_id, GPS_DL_WAIT_READ); +} + +int gps_each_link_open(enum gps_dl_link_id_enum link_id) +{ + enum gps_each_link_state_enum state, state2; + enum GDL_RET_STATUS gdl_ret; + long sigval = 0; + bool okay; + int retval; +#if GPS_DL_ON_CTP + /* Todo: is it need on LINUX? */ + struct gps_each_link *p_link = gps_dl_link_get(link_id); + + gps_dma_buf_align_as_byte_mode(&p_link->tx_dma_buf); + gps_dma_buf_align_as_byte_mode(&p_link->rx_dma_buf); +#endif + +#if 0 +#if (GPS_DL_ON_LINUX && !GPS_DL_NO_USE_IRQ && !GPS_DL_HW_IS_MOCK) + if (!p_link->sub_states.irq_is_init_done) { + gps_dl_irq_init(); + p_link->sub_states.irq_is_init_done = true; + } +#endif +#endif + + state = gps_each_link_get_state(link_id); + + switch (state) { + case LINK_RESUMING: + case LINK_SUSPENDED: + case LINK_SUSPENDING: + retval = -EAGAIN; + break; + + case LINK_CLOSING: + case LINK_RESETTING: + case LINK_DISABLED: + retval = -EAGAIN; + break; + + case LINK_RESET_DONE: + /* RESET_DONE stands for user space not close me */ + retval = -EBUSY; /* twice open not allowed */ + break; + + case LINK_OPENED: + case LINK_OPENING: + retval = -EBUSY;; /* twice open not allowed */ + break; + + case LINK_CLOSED: + okay = gps_each_link_change_state_from(link_id, LINK_CLOSED, LINK_OPENING); + if (!okay) { + retval = -EBUSY; + break; + } + + /* TODO: simplify the flags */ + gps_each_link_set_bool_flag(link_id, LINK_TO_BE_CLOSED, false); + gps_each_link_set_bool_flag(link_id, LINK_USER_OPEN, true); + + gps_dl_link_waitable_reset(link_id, GPS_DL_WAIT_OPEN_CLOSE); + gps_dl_link_event_send(GPS_DL_EVT_LINK_OPEN, link_id); + gps_dl_link_open_wait(link_id, &sigval); + + /* TODO: Check this mutex can be removed? + * the possible purpose is make it's atomic from LINK_USER_OPEN and LINK_OPEN_RESULT_OKAY. + */ + gps_each_link_take_big_lock(link_id, GDL_LOCK_FOR_OPEN); + if (sigval != 0) { + gps_each_link_set_bool_flag(link_id, LINK_USER_OPEN, false); + + gdl_ret = gps_dl_link_try_wait_on(link_id, GPS_DL_WAIT_OPEN_CLOSE); + if (gdl_ret == GDL_OKAY) { + okay = gps_each_link_change_state_from(link_id, LINK_OPENED, LINK_CLOSING); + + /* Change okay, need to send event to trigger close */ + if (okay) { + gps_each_link_give_big_lock(link_id); + gps_dl_link_event_send(GPS_DL_EVT_LINK_CLOSE, link_id); + GDL_LOGXW_ONF(link_id, + "sigval = %ld, corner case 1: close it", sigval); + retval = -EBUSY; + break; + } + + /* Not change okay, state maybe RESETTING or RESET_DONE */ + state2 = gps_each_link_get_state(link_id); + if (state2 == LINK_RESET_DONE) + gps_each_link_set_state(link_id, LINK_CLOSED); + + gps_each_link_give_big_lock(link_id); + GDL_LOGXW_ONF(link_id, "sigval = %ld, corner case 2: %s", + sigval, gps_dl_link_state_name(state2)); + retval = -EBUSY; + break; + } + + gps_each_link_give_big_lock(link_id); + GDL_LOGXW_ONF(link_id, "sigval = %ld, normal case", sigval); + retval = -EINVAL; + break; + } + + okay = gps_each_link_get_bool_flag(link_id, LINK_OPEN_RESULT_OKAY); + gps_each_link_give_big_lock(link_id); + + if (okay) + retval = 0; + else { + gps_each_link_set_bool_flag(link_id, LINK_USER_OPEN, false); + retval = -EBUSY; + } + break; + + default: + retval = -EINVAL; + break; + } + + if (retval == 0) { + GDL_LOGXD_ONF(link_id, "prev_state = %s, retval = %d", + gps_dl_link_state_name(state), retval); + } else { + GDL_LOGXW_ONF(link_id, "prev_state = %s, retval = %d", + gps_dl_link_state_name(state), retval); + } + + return retval; +} + +int gps_each_link_reset(enum gps_dl_link_id_enum link_id) +{ + /* + * - set each link resetting flag + */ + enum gps_each_link_state_enum state, state2; + bool okay; + int retval; + + state = gps_each_link_get_state(link_id); + + switch (state) { + case LINK_OPENING: + case LINK_CLOSING: + case LINK_CLOSED: + case LINK_DISABLED: + retval = -EBUSY; + break; + + case LINK_RESETTING: + case LINK_RESET_DONE: + retval = 0; + break; + + case LINK_RESUMING: + case LINK_SUSPENDING: + case LINK_SUSPENDED: + case LINK_OPENED: +_try_change_to_reset_again: + okay = gps_each_link_change_state_from(link_id, state, LINK_RESETTING); + if (!okay) { + state2 = gps_each_link_get_state(link_id); + + /* Already reset or close, not trigger reseeting again */ + GDL_LOGXW_ONF(link_id, "state flip to %s - corner case", + gps_dl_link_state_name(state2)); + + /* -ing state may become -ed state, try change to reset again */ + if ((state == LINK_SUSPENDING && state2 == LINK_SUSPENDED) || + (state == LINK_RESUMING && state2 == LINK_OPENED)) { + state = state2; + goto _try_change_to_reset_again; + } + + if (state2 == LINK_RESETTING || state2 == LINK_RESET_DONE) + retval = 0; + else + retval = -EBUSY; + break; + } + + gps_each_link_set_bool_flag(link_id, LINK_IS_RESETTING, true); + + /* no need to wait reset ack + * TODO: make sure message send okay + */ + gps_dl_link_waitable_reset(link_id, GPS_DL_WAIT_RESET); + gps_dl_link_event_send(GPS_DL_EVT_LINK_RESET_DSP, link_id); + retval = 0; + break; + + default: + retval = -EINVAL; + break; + } + + /* wait until cttld thread ack the status */ + if (retval == 0) { + GDL_LOGXD_ONF(link_id, "prev_state = %s, retval = %d", + gps_dl_link_state_name(state), retval); + } else { + GDL_LOGXW_ONF(link_id, "prev_state = %s, retval = %d", + gps_dl_link_state_name(state), retval); + } + + return retval; +} + +void gps_dl_ctrld_set_resest_status(void) +{ + gps_each_link_set_active(GPS_DATA_LINK_ID0, false); + gps_each_link_set_active(GPS_DATA_LINK_ID1, false); +} + +void gps_dl_link_reset_ack_inner(enum gps_dl_link_id_enum link_id, bool post_conn_reset) +{ + struct gps_each_link *p = gps_dl_link_get(link_id); + enum gps_each_link_state_enum old_state, new_state; + enum gps_each_link_reset_level old_level, new_level; + bool user_still_open; + bool both_clear_done = false; + bool try_conn_infra_off = false; + + gps_each_link_take_big_lock(link_id, GDL_LOCK_FOR_RESET_DONE); + gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + old_state = p->state_for_user; + old_level = p->reset_level; + user_still_open = p->sub_states.user_open; + + switch (old_level) { + case GPS_DL_RESET_LEVEL_GPS_SINGLE_LINK: + p->reset_level = GPS_DL_RESET_LEVEL_NONE; + if (p->sub_states.user_open) + p->state_for_user = LINK_RESET_DONE; + else + p->state_for_user = LINK_CLOSED; + break; + + case GPS_DL_RESET_LEVEL_CONNSYS: + if (!post_conn_reset) + break; + p->reset_level = GPS_DL_RESET_LEVEL_NONE; + both_clear_done = gps_dl_link_try_to_clear_both_resetting_status(); + try_conn_infra_off = true; + break; + + case GPS_DL_RESET_LEVEL_GPS_SUBSYS: + p->reset_level = GPS_DL_RESET_LEVEL_NONE; + both_clear_done = gps_dl_link_try_to_clear_both_resetting_status(); + break; + + default: + break; + } + + new_state = p->state_for_user; + new_level = p->reset_level; + gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + + if (try_conn_infra_off) { + /* During connsys resetting, conninfra_pwr_off may fail, + * it need to be called again when connsys reset done. + */ + gps_dl_hal_conn_infra_driver_off(); + } + + /* TODO: if both clear, show another link's log */ + GDL_LOGXE_STA(link_id, + "state change: %s -> %s, level: %d -> %d, user = %d, post_reset = %d, both_clear = %d", + gps_dl_link_state_name(old_state), gps_dl_link_state_name(new_state), + old_level, new_level, + user_still_open, post_conn_reset, both_clear_done); + + gps_each_link_give_big_lock(link_id); + + /* Note: for CONNSYS or GPS_SUBSYS RESET, here might be still RESETTING, + * if any other link not reset done (see both_clear_done print). + */ + gps_dl_link_wake_up(&p->waitables[GPS_DL_WAIT_RESET]); +} + +bool gps_dl_link_try_to_clear_both_resetting_status(void) +{ + enum gps_dl_link_id_enum link_id; + struct gps_each_link *p; + + for (link_id = 0; link_id < GPS_DATA_LINK_NUM; link_id++) { + p = gps_dl_link_get(link_id); + if (p->reset_level != GPS_DL_RESET_LEVEL_NONE) + return false; + } + + for (link_id = 0; link_id < GPS_DATA_LINK_NUM; link_id++) { + p = gps_dl_link_get(link_id); + + if (p->sub_states.user_open) + p->state_for_user = LINK_RESET_DONE; + else + p->state_for_user = LINK_CLOSED; + } + + return true; +} + +void gps_dl_link_reset_ack(enum gps_dl_link_id_enum link_id) +{ + gps_dl_link_reset_ack_inner(link_id, false); +} + +void gps_dl_link_on_post_conn_reset(enum gps_dl_link_id_enum link_id) +{ + gps_dl_link_reset_ack_inner(link_id, true); +} + +void gps_dl_link_close_wait(enum gps_dl_link_id_enum link_id, long *p_sigval) +{ + struct gps_each_link *p = gps_dl_link_get(link_id); + enum GDL_RET_STATUS gdl_ret; + long sigval; + + gdl_ret = gps_dl_link_wait_on(&p->waitables[GPS_DL_WAIT_OPEN_CLOSE], &sigval); + if (gdl_ret == GDL_FAIL_SIGNALED) { + if (p_sigval != NULL) { + *p_sigval = sigval; + return; + } + } else if (gdl_ret == GDL_FAIL_NOT_SUPPORT) + ; /* show warnning */ +} + +void gps_dl_link_close_ack(enum gps_dl_link_id_enum link_id, bool hw_suspend) +{ + struct gps_each_link *p = gps_dl_link_get(link_id); + + GDL_LOGXD_ONF(link_id, "hw_suspend = %d", hw_suspend); + gps_dl_link_wake_up(&p->waitables[GPS_DL_WAIT_OPEN_CLOSE]); + + gps_each_link_take_big_lock(link_id, GDL_LOCK_FOR_CLOSE_DONE); + + /* gps_each_link_set_state(link_id, LINK_CLOSED); */ + /* For case of reset_done */ + if (hw_suspend) { + gps_each_link_change_state_from(link_id, LINK_SUSPENDING, LINK_SUSPENDED); + /* TODO */ + } else + gps_each_link_change_state_from(link_id, LINK_CLOSING, LINK_CLOSED); + + gps_each_link_give_big_lock(link_id); +} + +int gps_each_link_close_or_suspend_inner(enum gps_dl_link_id_enum link_id, + enum gps_each_link_state_enum state, + enum gps_each_link_close_or_suspend_op close_or_suspend_op) +{ + enum gps_each_link_state_enum state2; + bool okay; + int retval = 0; + bool hw_suspend; + + hw_suspend = !!(close_or_suspend_op == GDL_DPSTOP || close_or_suspend_op == GDL_CLKEXT); + gps_each_link_take_big_lock(link_id, GDL_LOCK_FOR_CLOSE); + do { + if (hw_suspend) { + okay = gps_each_link_change_state_from(link_id, LINK_OPENED, LINK_SUSPENDING); + if (!okay) { + state2 = gps_each_link_get_state(link_id); + gps_each_link_give_big_lock(link_id); + GDL_LOGXW_ONF(link_id, "state check: %s, return hw suspend fail", + gps_dl_link_state_name(state2)); + retval = -EINVAL; + break; + } + + gps_each_link_set_bool_flag(link_id, + LINK_SUSPEND_TO_CLK_EXT, close_or_suspend_op == GDL_CLKEXT); + } else { + if (state == LINK_SUSPENDED) { + okay = gps_each_link_change_state_from( + link_id, LINK_SUSPENDED, LINK_CLOSING); + } else { + okay = gps_each_link_change_state_from( + link_id, LINK_OPENED, LINK_CLOSING); + } + gps_each_link_set_bool_flag(link_id, LINK_USER_OPEN, false); + if (!okay) { + state2 = gps_each_link_get_state(link_id); + if (state2 == LINK_RESET_DONE) + gps_each_link_set_state(link_id, LINK_CLOSED); + else { + GDL_LOGXW_ONF(link_id, "state check: %s, return close ok", + gps_dl_link_state_name(state2)); + } + gps_each_link_give_big_lock(link_id); + retval = 0; + break; + } + } + gps_each_link_give_big_lock(link_id); + } while (0); + return retval; +} + +int gps_each_link_close_or_suspend(enum gps_dl_link_id_enum link_id, + enum gps_each_link_close_or_suspend_op close_or_suspend_op) +{ + enum gps_each_link_state_enum state; + long sigval = 0; + int retval; + bool hw_suspend; + + state = gps_each_link_get_state(link_id); + hw_suspend = !!(close_or_suspend_op == GDL_DPSTOP || close_or_suspend_op == GDL_CLKEXT); + + switch (state) { + case LINK_OPENING: + case LINK_CLOSING: + case LINK_CLOSED: + case LINK_DISABLED: + /* twice close */ + /* TODO: show user open flag */ + retval = -EINVAL; + break; + + case LINK_SUSPENDING: + case LINK_RESUMING: + case LINK_RESETTING: + if (hw_suspend) { + if (state == LINK_SUSPENDING) + retval = 0; + else if (state == LINK_RESUMING) + retval = -EBUSY; + else + retval = -EINVAL; + break; + } + + /* close on xxx-ing states: just recording user is not online + * ctrld will handle it on the end of xxx-ing handling + */ + gps_each_link_set_bool_flag(link_id, LINK_USER_OPEN, false); + GDL_LOGXE_ONF(link_id, "state check: %s, return close ok", gps_dl_link_state_name(state)); + /* return okay to avoid twice close */ + retval = 0; + break; + + case LINK_RESET_DONE: + if (hw_suspend) { + retval = -EINVAL; + break; + } + gps_each_link_set_bool_flag(link_id, LINK_USER_OPEN, false); + gps_each_link_set_state(link_id, LINK_CLOSED); + retval = 0; + break; + + case LINK_SUSPENDED: + case LINK_OPENED: + retval = gps_each_link_close_or_suspend_inner(link_id, state, close_or_suspend_op); + if (retval != 0) + break; + + /* clean the done(fired) flag before send and wait */ + gps_dl_link_waitable_reset(link_id, GPS_DL_WAIT_OPEN_CLOSE); + if (hw_suspend) + gps_dl_link_event_send(GPS_DL_EVT_LINK_ENTER_DPSTOP, link_id); + else + gps_dl_link_event_send(GPS_DL_EVT_LINK_CLOSE, link_id); + + /* set this status, hal proc will by pass the message from the link + * it can make LINK_CLOSE be processed faster + */ + gps_each_link_set_bool_flag(link_id, LINK_TO_BE_CLOSED, true); + gps_dl_link_close_wait(link_id, &sigval); + + if (sigval) { + retval = -EINVAL; + break; + } + + retval = 0; + break; + default: + retval = -EINVAL; + break; + } + + if (retval == 0) { + GDL_LOGXD_ONF(link_id, "prev_state = %s, retval = %d, op = %d", + gps_dl_link_state_name(state), retval, close_or_suspend_op); + } else { + GDL_LOGXW_ONF(link_id, "prev_state = %s, retval = %d, op = %d", + gps_dl_link_state_name(state), retval, close_or_suspend_op); + } + + return retval; +} + +int gps_each_link_close(enum gps_dl_link_id_enum link_id) +{ + return gps_each_link_close_or_suspend(link_id, GDL_CLOSE); +} +int gps_each_link_check(enum gps_dl_link_id_enum link_id, int reason) +{ + enum gps_each_link_state_enum state; + enum gps_dl_link_event_id event; + int retval = 0; + + state = gps_each_link_get_state(link_id); + + switch (state) { + case LINK_OPENING: + case LINK_CLOSING: + case LINK_CLOSED: + case LINK_DISABLED: + break; + + case LINK_RESETTING: +#if 0 + if (rstflag == 1) { + /* chip resetting */ + retval = -888; + } else if (rstflag == 2) { + /* chip reset end */ + retval = -889; + } else { + /* normal */ + retval = 0; + } +#endif + retval = -888; + break; + + case LINK_RESET_DONE: + retval = 889; + break; + + case LINK_RESUMING: + case LINK_SUSPENDING: + case LINK_SUSPENDED: + case LINK_OPENED: + if (reason == 2) + event = GPS_DL_EVT_LINK_PRINT_HW_STATUS; + else if (reason == 4) + event = GPS_DL_EVT_LINK_PRINT_DATA_STATUS; + else + break; + + /* if L1 trigger it, also print L5 status + * for this case, dump L5 firstly. + */ + if (link_id == GPS_DATA_LINK_ID0) + gps_dl_link_event_send(event, GPS_DATA_LINK_ID1); + + gps_dl_link_event_send(event, link_id); + break; + + default: + break; + } + + GDL_LOGXW_ONF(link_id, "prev_state = %s, reason = %d, retval = %d", + gps_dl_link_state_name(state), reason, retval); + + return retval; +} + +int gps_each_link_enter_dsleep(enum gps_dl_link_id_enum link_id) +{ + struct gps_each_link *p_link = gps_dl_link_get(link_id); + + gps_dl_link_event_send(GPS_DL_EVT_LINK_ENTER_DPSLEEP, link_id); + gps_dma_buf_reset(&p_link->tx_dma_buf); + gps_dma_buf_reset(&p_link->rx_dma_buf); + return 0; +} + +int gps_each_link_leave_dsleep(enum gps_dl_link_id_enum link_id) +{ +#if GPS_DL_ON_CTP + struct gps_each_link *p_link = gps_dl_link_get(link_id); + + gps_dma_buf_align_as_byte_mode(&p_link->tx_dma_buf); + gps_dma_buf_align_as_byte_mode(&p_link->rx_dma_buf); +#endif + gps_dl_link_event_send(GPS_DL_EVT_LINK_LEAVE_DPSLEEP, link_id); + return 0; +} + + +int gps_each_link_hw_suspend(enum gps_dl_link_id_enum link_id, bool need_clk_ext) +{ + enum gps_each_link_close_or_suspend_op op; + + if (need_clk_ext) + op = GDL_CLKEXT; + else + op = GDL_DPSTOP; + return gps_each_link_close_or_suspend(link_id, op); +} + +int gps_each_link_hw_resume(enum gps_dl_link_id_enum link_id) +{ + enum gps_each_link_state_enum state; + long sigval = 0; + bool okay; + int retval; +#if GPS_DL_ON_CTP + struct gps_each_link *p_link = gps_dl_link_get(link_id); +#endif + + state = gps_each_link_get_state(link_id); + do { + if (state != LINK_SUSPENDED) { + retval = -EINVAL; + break; + } + + okay = gps_each_link_change_state_from(link_id, LINK_SUSPENDED, LINK_RESUMING); + if (!okay) { + retval = -EBUSY; + break; + } + + gps_each_link_set_bool_flag(link_id, LINK_TO_BE_CLOSED, false); + gps_dl_link_waitable_reset(link_id, GPS_DL_WAIT_OPEN_CLOSE); +#if GPS_DL_ON_CTP + gps_dma_buf_align_as_byte_mode(&p_link->tx_dma_buf); + gps_dma_buf_align_as_byte_mode(&p_link->rx_dma_buf); +#endif + gps_dl_link_event_send(GPS_DL_EVT_LINK_LEAVE_DPSTOP, link_id); + gps_dl_link_open_wait(link_id, &sigval); + if (sigval != 0) { + GDL_LOGXW_ONF(link_id, "sigval = %ld", sigval); + retval = -EBUSY; + break; + } + + okay = gps_each_link_get_bool_flag(link_id, LINK_OPEN_RESULT_OKAY); + if (okay) + retval = 0; + else + retval = -EBUSY; + } while (0); + + if (retval == 0) { + GDL_LOGXD_ONF(link_id, "prev_state = %s, retval = %d", + gps_dl_link_state_name(state), retval); + } else { + GDL_LOGXW_ONF(link_id, "prev_state = %s, retval = %d", + gps_dl_link_state_name(state), retval); + } + return retval; +} + +void gps_dl_link_waitable_init(struct gps_each_link_waitable *p, + enum gps_each_link_waitable_type type) +{ + p->type = type; + p->fired = false; +#if GPS_DL_ON_LINUX + init_waitqueue_head(&p->wq); +#endif +} + +void gps_dl_link_waitable_reset(enum gps_dl_link_id_enum link_id, enum gps_each_link_waitable_type type) +{ + struct gps_each_link *p_link = gps_dl_link_get(link_id); + + /* TOOD: check NULL and boundary */ + p_link->waitables[type].fired = false; +} + +#define GDL_TEST_TRUE_AND_SET_FALSE(x, x_old) \ + do { \ + x_old = x; \ + if (x_old) { \ + x = false; \ + } } while (0) + +#define GDL_TEST_FALSE_AND_SET_TRUE(x, x_old) \ + do { \ + x_old = x; \ + if (!x_old) { \ + x = true; \ + } } while (0) + +enum GDL_RET_STATUS gps_dl_link_wait_on(struct gps_each_link_waitable *p, long *p_sigval) +{ +#if GPS_DL_ON_LINUX + long val; + bool is_fired; + + p->waiting = true; + /* TODO: check race conditions? */ + GDL_TEST_TRUE_AND_SET_FALSE(p->fired, is_fired); + if (is_fired) { + GDL_LOGD("waitable = %s, no wait return", gps_dl_waitable_type_name(p->type)); + p->waiting = false; + return GDL_OKAY; + } + + GDL_LOGD("waitable = %s, wait start", gps_dl_waitable_type_name(p->type)); + val = wait_event_interruptible(p->wq, p->fired); + p->waiting = false; + + if (val) { + GDL_LOGI("signaled by %ld", val); + if (p_sigval) + *p_sigval = val; + p->waiting = false; + return GDL_FAIL_SIGNALED; + } + + p->fired = false; + p->waiting = false; + GDL_LOGD("waitable = %s, wait done", gps_dl_waitable_type_name(p->type)); + return GDL_OKAY; +#else + return GDL_FAIL_NOT_SUPPORT; +#endif +} + +enum GDL_RET_STATUS gps_dl_link_try_wait_on(enum gps_dl_link_id_enum link_id, + enum gps_each_link_waitable_type type) +{ + struct gps_each_link *p_link; + struct gps_each_link_waitable *p; + bool is_fired; + + p_link = gps_dl_link_get(link_id); + p = &p_link->waitables[type]; + + GDL_TEST_TRUE_AND_SET_FALSE(p->fired, is_fired); + if (is_fired) { + GDL_LOGD("waitable = %s, okay", gps_dl_waitable_type_name(p->type)); + p->waiting = false; + return GDL_OKAY; + } + + return GDL_FAIL; +} + +void gps_dl_link_wake_up(struct gps_each_link_waitable *p) +{ + bool is_fired; + + ASSERT_NOT_NULL(p, GDL_VOIDF()); + + if (!p->waiting) { + if (p->type == GPS_DL_WAIT_WRITE || p->type == GPS_DL_WAIT_READ) { + /* normal case for read/write, not show warning */ + GDL_LOGD("waitable = %s, nobody waiting", + gps_dl_waitable_type_name(p->type)); + } else { + /* not return, just show warning */ + GDL_LOGW("waitable = %s, nobody waiting", + gps_dl_waitable_type_name(p->type)); + } + } + + GDL_TEST_FALSE_AND_SET_TRUE(p->fired, is_fired); + GDL_LOGD("waitable = %s, fired = %d", gps_dl_waitable_type_name(p->type), is_fired); + + if (!is_fired) { +#if GPS_DL_ON_LINUX + wake_up(&p->wq); +#else +#endif + } +} + +/* TODO: determine return value type */ +int gps_each_link_write(enum gps_dl_link_id_enum link_id, + unsigned char *buf, unsigned int len) +{ + return gps_each_link_write_with_opt(link_id, buf, len, true); +} + +#define GPS_DL_READ_SHOW_BUF_MAX_LEN (32) +int gps_each_link_write_with_opt(enum gps_dl_link_id_enum link_id, + unsigned char *buf, unsigned int len, bool wait_tx_done) +{ + struct gps_each_link *p = gps_dl_link_get(link_id); + enum GDL_RET_STATUS gdl_ret; + long sigval = 0; + + if (NULL == p) + return -1; + + if (len > p->tx_dma_buf.len) + return -1; + + if (gps_each_link_get_state(link_id) != LINK_OPENED) { + GDL_LOGXW_DRW(link_id, "not opened, drop the write data len = %d", len); + return -EBUSY; + } + + if (len <= GPS_DL_READ_SHOW_BUF_MAX_LEN) + gps_dl_hal_show_buf("wr_buf", buf, len); + else + GDL_LOGXD_DRW(link_id, "wr_buf, len = %d", len); + + while (1) { + gdl_ret = gdl_dma_buf_put(&p->tx_dma_buf, buf, len); + + if (gdl_ret == GDL_OKAY) { + gps_dl_link_event_send(GPS_DL_EVT_LINK_WRITE, link_id); +#if (GPS_DL_NO_USE_IRQ == 1) + if (wait_tx_done) { + do { + gps_dl_hal_a2d_tx_dma_wait_until_done_and_stop_it( + link_id, GPS_DL_RW_NO_TIMEOUT, false); + gps_dl_hal_event_send(GPS_DL_HAL_EVT_A2D_TX_DMA_DONE, link_id); + /* for case tx transfer_max > 0, GPS_DL_HAL_EVT_A2D_TX_DMA_DONE may */ + /* start anthor dma session again, need to loop again until all data done */ + } while (!gps_dma_buf_is_empty(&p->tx_dma_buf)); + } +#endif + return 0; + } else if (gdl_ret == GDL_FAIL_NOSPACE || gdl_ret == GDL_FAIL_BUSY || + gdl_ret == GDL_FAIL_NOENTRY) { + /* TODO: */ + /* 1. note: BUSY stands for others thread is do write, it should be impossible */ + /* - If wait on BUSY, should wake up the waitings or return eno_again? */ + /* 2. note: NOSPACE stands for need wait for tx dma working done */ + gps_dma_buf_show(&p->tx_dma_buf, false); + GDL_LOGXD(link_id, + "wait due to gdl_dma_buf_put ret = %s", gdl_ret_to_name(gdl_ret)); + gdl_ret = gps_dl_link_wait_on(&p->waitables[GPS_DL_WAIT_WRITE], &sigval); + if (gdl_ret == GDL_FAIL_SIGNALED) + break; + } else { + gps_dma_buf_show(&p->tx_dma_buf, true); + GDL_LOGXW(link_id, + "fail due to gdl_dma_buf_put ret = %s", gdl_ret_to_name(gdl_ret)); + break; + } + } + + return -1; +} + +int gps_each_link_read(enum gps_dl_link_id_enum link_id, + unsigned char *buf, unsigned int len) { + return gps_each_link_read_with_timeout(link_id, buf, len, GPS_DL_RW_NO_TIMEOUT, NULL); +} + +int gps_each_link_read_with_timeout(enum gps_dl_link_id_enum link_id, + unsigned char *buf, unsigned int len, int timeout_usec, bool *p_is_nodata) +{ + struct gps_each_link *p = gps_dl_link_get(link_id); + enum GDL_RET_STATUS gdl_ret; +#if (GPS_DL_NO_USE_IRQ == 0) + long sigval = 0; +#endif + unsigned int data_len; + + if (NULL == p) + return -1; + + while (1) { + gdl_ret = gdl_dma_buf_get(&p->rx_dma_buf, buf, len, &data_len, p_is_nodata); + + if (gdl_ret == GDL_OKAY) { + if (data_len <= GPS_DL_READ_SHOW_BUF_MAX_LEN) + gps_dl_hal_show_buf("rd_buf", buf, data_len); + else + GDL_LOGXD_DRW(link_id, "rd_buf, len = %d", data_len); + + gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_DMA_BUF); + if (p->rx_dma_buf.has_pending_rx) { + p->rx_dma_buf.has_pending_rx = false; + gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_DMA_BUF); + + GDL_LOGXI_DRW(link_id, "has pending rx, trigger again"); + gps_dl_hal_event_send(GPS_DL_HAL_EVT_D2A_RX_HAS_DATA, link_id); + } else + gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_DMA_BUF); + + return data_len; + } else if (gdl_ret == GDL_FAIL_NODATA) { + GDL_LOGXD_DRW(link_id, "gdl_dma_buf_get no data and wait"); +#if (GPS_DL_NO_USE_IRQ == 1) + gdl_ret = gps_dl_hal_wait_and_handle_until_usrt_has_data( + link_id, timeout_usec); + if (gdl_ret == GDL_FAIL_TIMEOUT) + return -1; + + gdl_ret = gps_dl_hal_wait_and_handle_until_usrt_has_nodata_or_rx_dma_done( + link_id, timeout_usec, true); + if (gdl_ret == GDL_FAIL_TIMEOUT) + return -1; + continue; +#else + gdl_ret = gps_dl_link_wait_on(&p->waitables[GPS_DL_WAIT_READ], &sigval); + if (gdl_ret == GDL_FAIL_SIGNALED || gdl_ret == GDL_FAIL_NOT_SUPPORT) + return -1; +#endif + } else { + GDL_LOGXW_DRW(link_id, "gdl_dma_buf_get fail %s", gdl_ret_to_name(gdl_ret)); + return -1; + } + } + + return 0; +} + +void gps_dl_link_event_send(enum gps_dl_link_event_id evt, + enum gps_dl_link_id_enum link_id) +{ +#if (GPS_DL_HAS_CTRLD == 0) + gps_dl_link_event_proc(evt, link_id); +#else + { + struct gps_dl_osal_lxop *pOp; + struct gps_dl_osal_signal *pSignal; + int iRet; + + pOp = gps_dl_get_free_op(); + if (!pOp) + return; + + pSignal = &pOp->signal; + pSignal->timeoutValue = 0;/* send data need to wait ?ms */ + if (link_id < GPS_DATA_LINK_NUM) { + pOp->op.opId = GPS_DL_OPID_LINK_EVENT_PROC; + pOp->op.au4OpData[0] = link_id; + pOp->op.au4OpData[1] = evt; + iRet = gps_dl_put_act_op(pOp); + } else { + gps_dl_put_op_to_free_queue(pOp); + /*printf error msg*/ + return; + } + } +#endif +} + +void gps_dl_link_irq_set(enum gps_dl_link_id_enum link_id, bool enable) +{ + struct gps_each_link *p_link = gps_dl_link_get(link_id); + bool dma_working, pending_rx; + bool bypass_unmask_irq; + + if (enable) { + gps_dl_irq_each_link_unmask(link_id, GPS_DL_IRQ_TYPE_HAS_DATA, GPS_DL_IRQ_CTRL_FROM_THREAD); + gps_dl_irq_each_link_unmask(link_id, GPS_DL_IRQ_TYPE_HAS_NODATA, GPS_DL_IRQ_CTRL_FROM_THREAD); + + /* check if MCUB ROM ready */ + if (gps_dl_test_mask_mcub_irq_on_open_get(link_id)) { + GDL_LOGXE(link_id, "test mask mcub irq, not unmask irq and wait reset"); + gps_dl_hal_set_mcub_irq_dis_flag(link_id, true); + gps_dl_test_mask_mcub_irq_on_open_set(link_id, false); + } else if (!gps_dl_hal_mcub_flag_handler(link_id)) { + GDL_LOGXE(link_id, "mcub_flag_handler not okay, not unmask irq and wait reset"); + gps_dl_hal_set_mcub_irq_dis_flag(link_id, true); + } else { + gps_dl_irq_each_link_unmask(link_id, + GPS_DL_IRQ_TYPE_MCUB, GPS_DL_IRQ_CTRL_FROM_THREAD); + } + } else { + if (gps_dl_hal_get_mcub_irq_dis_flag(link_id)) { + GDL_LOGXW(link_id, "mcub irq already disable, bypass mask irq"); + gps_dl_hal_set_mcub_irq_dis_flag(link_id, false); + } else { + gps_dl_irq_each_link_mask(link_id, + GPS_DL_IRQ_TYPE_MCUB, GPS_DL_IRQ_CTRL_FROM_THREAD); + } + + bypass_unmask_irq = false; + if (gps_dl_hal_get_irq_dis_flag(link_id, GPS_DL_IRQ_TYPE_HAS_DATA)) { + GDL_LOGXW(link_id, "hasdata irq already disable, bypass mask irq"); + gps_dl_hal_set_irq_dis_flag(link_id, GPS_DL_IRQ_TYPE_HAS_DATA, false); + bypass_unmask_irq = true; + } + + gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_DMA_BUF); + dma_working = p_link->rx_dma_buf.dma_working_entry.is_valid; + pending_rx = p_link->rx_dma_buf.has_pending_rx; + if (dma_working || pending_rx) { + p_link->rx_dma_buf.has_pending_rx = false; + gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_DMA_BUF); + + /* It means this irq has already masked, */ + /* DON'T mask again, otherwise twice unmask might be needed */ + GDL_LOGXW(link_id, + "has dma_working = %d, pending rx = %d, bypass mask irq", + dma_working, pending_rx); + } else { + gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_DMA_BUF); + if (!bypass_unmask_irq) { + gps_dl_irq_each_link_mask(link_id, + GPS_DL_IRQ_TYPE_HAS_DATA, GPS_DL_IRQ_CTRL_FROM_THREAD); + } + } + + /* TODO: avoid twice mask need to be handled if HAS_CTRLD */ + gps_dl_irq_each_link_mask(link_id, GPS_DL_IRQ_TYPE_HAS_NODATA, GPS_DL_IRQ_CTRL_FROM_THREAD); + } +} + +void gps_dl_link_pre_off_setting(enum gps_dl_link_id_enum link_id) +{ + /* + * The order is important: + * 1. disallow write, avoiding to start dma + * 2. stop tx/rx dma and mask dma irq if it is last link + * 3. mask link's irqs + * 4. set inactive after all irq mask done + * (at this time isr can check inactive and unmask irq safely due to step 3 already mask irqs) + */ + gps_dl_link_set_ready_to_write(link_id, false); + gps_dl_hal_link_confirm_dma_stop(link_id); + gps_dl_link_irq_set(link_id, false); + gps_each_link_set_active(link_id, false); +} + +void gps_dl_link_event_proc(enum gps_dl_link_event_id evt, + enum gps_dl_link_id_enum link_id) +{ + struct gps_each_link *p_link = gps_dl_link_get(link_id); + bool show_log = false; + bool show_log2 = false; + unsigned long j0, j1; + int ret; + enum gps_dsp_state_t dsp_state; + + j0 = jiffies; + GDL_LOGXD_EVT(link_id, "evt = %s", gps_dl_link_event_name(evt)); + + switch (evt) { + case GPS_DL_EVT_LINK_OPEN: + /* show_log = gps_dl_set_show_reg_rw_log(true); */ + gps_each_dsp_reg_gourp_read_init(link_id); + gps_each_link_inc_session_id(link_id); + gps_each_link_set_active(link_id, true); + gps_each_link_set_bool_flag(link_id, LINK_NEED_A2Z_DUMP, false); + + ret = gps_dl_hal_conn_power_ctrl(link_id, 1); + if (ret != 0) { + gps_dl_link_open_ack(link_id, false, false); + break; + } + + ret = gps_dl_hal_link_power_ctrl(link_id, GPS_DL_HAL_POWER_ON); + if (ret != 0) { + gps_dl_link_open_ack(link_id, false, false); + break; + } + + gps_dsp_fsm(GPS_DSP_EVT_FUNC_ON, link_id); + gps_dl_link_irq_set(link_id, true); +#if GPS_DL_NO_USE_IRQ + gps_dl_wait_us(1000); /* wait 1ms */ +#endif + /* set ready to write before open ack, otherwise need to check pending tx data + * gps_dl_link_set_ready_to_write(link_id, true); + * move it to DSP reset done handler + */ + gps_dl_link_open_ack(link_id, true, false); /* TODO: ack on DSP reset done */ + /* gps_dl_set_show_reg_rw_log(show_log); */ + break; + case GPS_DL_EVT_LINK_LEAVE_DPSTOP: + gps_each_dsp_reg_gourp_read_init(link_id); + gps_each_link_inc_session_id(link_id); + gps_each_link_set_active(link_id, true); + gps_each_link_set_bool_flag(link_id, LINK_NEED_A2Z_DUMP, false); + ret = gps_dl_hal_link_power_ctrl(link_id, GPS_DL_HAL_LEAVE_DPSTOP); + if (ret != 0) + gps_dl_link_open_ack(link_id, false, true); + else { + gps_dsp_fsm(GPS_DSP_EVT_HW_STOP_EXIT, link_id); + gps_dl_link_irq_set(link_id, true); + gps_dl_link_open_ack(link_id, true, true); + } + break; + case GPS_DL_EVT_LINK_LEAVE_DPSLEEP: + gps_dl_hal_link_power_ctrl(link_id, GPS_DL_HAL_LEAVE_DPSLEEP); + gps_dl_link_irq_set(link_id, true); + break; + case GPS_DL_EVT_LINK_ENTER_DPSLEEP: + gps_dl_link_pre_off_setting(link_id); + gps_dl_hal_link_power_ctrl(link_id, GPS_DL_HAL_ENTER_DPSLEEP); + break; + case GPS_DL_EVT_LINK_ENTER_DPSTOP: + dsp_state = gps_dsp_state_get(link_id); + if ((GPS_DSP_ST_WORKING != dsp_state) && (GPS_DSP_ST_RESET_DONE != dsp_state)) { + /* TODO: ever working check */ + GDL_LOGXE(link_id, "not enter dpstop due to dsp state = %s", + gps_dl_dsp_state_name(dsp_state)); + + /* TODO: ack fail */ + gps_dl_link_close_ack(link_id, true); + break; + } + + if (GPS_DSP_ST_WORKING == dsp_state) { + GDL_LOGXW(link_id, "enter dpstop with dsp state = %s", + gps_dl_dsp_state_name(dsp_state)); + } + + gps_dl_hal_set_need_clk_ext_flag(link_id, + gps_each_link_get_bool_flag(link_id, LINK_SUSPEND_TO_CLK_EXT)); + + gps_dl_link_pre_off_setting(link_id); + /* TODO: handle fail */ + gps_dl_hal_link_power_ctrl(link_id, GPS_DL_HAL_ENTER_DPSTOP); + gps_dsp_fsm(GPS_DSP_EVT_HW_STOP_REQ, link_id); + gps_each_link_context_clear(link_id); +#if GPS_DL_ON_LINUX + gps_dma_buf_reset(&p_link->tx_dma_buf); + gps_dma_buf_reset(&p_link->rx_dma_buf); +#endif + gps_dl_link_close_ack(link_id, true); + break; + case GPS_DL_EVT_LINK_DSP_ROM_READY_TIMEOUT: + /* check again mcub not ready triggered */ + if (false) + break; /* wait hal handle it */ + + /* true: */ + if (!gps_each_link_change_state_from(link_id, LINK_OPENED, LINK_RESETTING)) { + /* no handle it again */ + break; + } + /* TODO: go and do close */ + case GPS_DL_EVT_LINK_CLOSE: + case GPS_DL_EVT_LINK_RESET_DSP: + case GPS_DL_EVT_LINK_RESET_GPS: + case GPS_DL_EVT_LINK_PRE_CONN_RESET: + if (evt != GPS_DL_EVT_LINK_CLOSE) + show_log = gps_dl_set_show_reg_rw_log(true); + + /* handle open fail case */ + if (!gps_each_link_get_bool_flag(link_id, LINK_OPEN_RESULT_OKAY)) { + GDL_LOGXD(link_id, "not open okay, just power off for %s", + gps_dl_link_event_name(evt)); + + gps_each_link_set_active(link_id, false); + gps_dl_hal_link_power_ctrl(link_id, GPS_DL_HAL_POWER_OFF); + gps_dl_hal_conn_power_ctrl(link_id, 0); + goto _close_or_reset_ack; + } + + /* to avoid twice enter */ + if (GPS_DSP_ST_OFF == gps_dsp_state_get(link_id)) { + GDL_LOGXD(link_id, "dsp state is off, do nothing for %s", + gps_dl_link_event_name(evt)); + + if (evt != GPS_DL_EVT_LINK_CLOSE) + gps_dl_set_show_reg_rw_log(show_log); + + goto _close_or_reset_ack; + } else if (GPS_DSP_ST_HW_STOP_MODE == gps_dsp_state_get(link_id)) { + /* exit deep stop mode and turn off it + * before exit deep stop, need clear pwr stat to make sure dsp is in hold-on state + * after exit deep stop mode. + */ + gps_dl_hal_link_clear_hw_pwr_stat(link_id); + gps_dl_hal_link_power_ctrl(link_id, GPS_DL_HAL_LEAVE_DPSTOP); + } else { + /* make sure current link's DMAs are stopped and mask the IRQs */ + gps_dl_link_pre_off_setting(link_id); + } + gps_dl_hal_set_need_clk_ext_flag(link_id, false); + + if (evt != GPS_DL_EVT_LINK_CLOSE) { + /* try to dump host csr info if not normal close operation */ + if (gps_dl_conninfra_is_okay_or_handle_it(NULL, true)) + gps_dl_hw_dump_host_csr_gps_info(true); + } + + if (gps_each_link_get_bool_flag(link_id, LINK_NEED_A2Z_DUMP)) { + show_log2 = gps_dl_set_show_reg_rw_log(true); + gps_dl_hw_do_gps_a2z_dump(); + gps_dl_set_show_reg_rw_log(show_log2); + } + + gps_dl_hal_link_power_ctrl(link_id, GPS_DL_HAL_POWER_OFF); + gps_dl_hal_conn_power_ctrl(link_id, 0); + + gps_dsp_fsm(GPS_DSP_EVT_FUNC_OFF, link_id); + + gps_each_link_context_clear(link_id); +#if GPS_DL_ON_LINUX + gps_dma_buf_reset(&p_link->tx_dma_buf); + gps_dma_buf_reset(&p_link->rx_dma_buf); +#endif + +_close_or_reset_ack: + if (evt != GPS_DL_EVT_LINK_CLOSE) + gps_dl_set_show_reg_rw_log(show_log); + + if (GPS_DL_EVT_LINK_CLOSE == evt) + gps_dl_link_close_ack(link_id, false); /* TODO: check fired race */ + else + gps_dl_link_reset_ack(link_id); + break; + + case GPS_DL_EVT_LINK_POST_CONN_RESET: + gps_dl_link_on_post_conn_reset(link_id); + break; + + case GPS_DL_EVT_LINK_WRITE: + /* gps_dl_hw_print_usrt_status(link_id); */ + if (gps_dl_link_is_ready_to_write(link_id)) + gps_dl_link_start_tx_dma_if_has_data(link_id); + else + GDL_LOGXW(link_id, "too early writing"); + break; + + case GPS_DL_EVT_LINK_PRINT_HW_STATUS: + case GPS_DL_EVT_LINK_PRINT_DATA_STATUS: + if (!gps_each_link_is_active(link_id)) { + GDL_LOGXW(link_id, "inactive, do not dump hw status"); + break; + } + + gps_dma_buf_show(&p_link->rx_dma_buf, true); + gps_dma_buf_show(&p_link->tx_dma_buf, true); + if (!gps_dl_conninfra_is_okay_or_handle_it(NULL, true)) + break; + + show_log = gps_dl_set_show_reg_rw_log(true); + if (evt == GPS_DL_EVT_LINK_PRINT_HW_STATUS) { + gps_dl_hw_dump_host_csr_gps_info(true); + gps_dl_hw_print_hw_status(link_id, true); + gps_each_dsp_reg_gourp_read_start(link_id, true, 4); + } else { + gps_dl_hw_print_hw_status(link_id, false); + gps_each_dsp_reg_gourp_read_start(link_id, true, 2); + } + gps_dl_set_show_reg_rw_log(show_log); + break; + + case GPS_DL_EVT_LINK_DSP_FSM_TIMEOUT: + gps_dsp_fsm(GPS_DSP_EVT_CTRL_TIMER_EXPIRE, link_id); + break; +#if 0 + case GPS_DL_EVT_LINK_RESET_GPS: + /* turn off GPS power directly */ + break; + + case GPS_DL_EVT_LINK_PRE_CONN_RESET: + /* turn off Connsys power directly + * 1. no need to do anything, just make sure the message queue is empty + * 2. how to handle ctrld block issue + */ + /* gps_dl_link_open_ack(link_id); */ + break; +#endif + default: + break; + } + + j1 = jiffies; + GDL_LOGXI_EVT(link_id, "evt = %s, dj = %lu", gps_dl_link_event_name(evt), j1 - j0); +} + +void gps_each_link_mutexes_init(struct gps_each_link *p) +{ + enum gps_each_link_mutex i; + + for (i = 0; i < GPS_DL_MTX_NUM; i++) + gps_dl_osal_sleepable_lock_init(&p->mutexes[i]); +} + +void gps_each_link_mutexes_deinit(struct gps_each_link *p) +{ + enum gps_each_link_mutex i; + + for (i = 0; i < GPS_DL_MTX_NUM; i++) + gps_dl_osal_sleepable_lock_deinit(&p->mutexes[i]); +} + +void gps_each_link_spin_locks_init(struct gps_each_link *p) +{ + enum gps_each_link_spinlock i; + + for (i = 0; i < GPS_DL_SPINLOCK_NUM; i++) + gps_dl_osal_unsleepable_lock_init(&p->spin_locks[i]); +} + +void gps_each_link_spin_locks_deinit(struct gps_each_link *p) +{ +#if 0 + enum gps_each_link_spinlock i; + + for (i = 0; i < GPS_DL_SPINLOCK_NUM; i++) + osal_unsleepable_lock_deinit(&p->spin_locks[i]); +#endif +} + +void gps_each_link_mutex_take(enum gps_dl_link_id_enum link_id, enum gps_each_link_mutex mtx_id) +{ + /* TODO: check range */ + struct gps_each_link *p = gps_dl_link_get(link_id); + + /* TODO: handle killed */ + gps_dl_osal_lock_sleepable_lock(&p->mutexes[mtx_id]); +} + +void gps_each_link_mutex_give(enum gps_dl_link_id_enum link_id, enum gps_each_link_mutex mtx_id) +{ + /* TODO: check range */ + struct gps_each_link *p = gps_dl_link_get(link_id); + + gps_dl_osal_unlock_sleepable_lock(&p->mutexes[mtx_id]); +} + +void gps_each_link_spin_lock_take(enum gps_dl_link_id_enum link_id, enum gps_each_link_spinlock spin_lock_id) +{ + /* TODO: check range */ + struct gps_each_link *p = gps_dl_link_get(link_id); + + gps_dl_osal_lock_unsleepable_lock(&p->spin_locks[spin_lock_id]); +} + +void gps_each_link_spin_lock_give(enum gps_dl_link_id_enum link_id, enum gps_each_link_spinlock spin_lock_id) +{ + /* TODO: check range */ + struct gps_each_link *p = gps_dl_link_get(link_id); + + gps_dl_osal_unlock_unsleepable_lock(&p->spin_locks[spin_lock_id]); +} + +int gps_each_link_take_big_lock(enum gps_dl_link_id_enum link_id, + enum gps_each_link_lock_reason reason) +{ + gps_each_link_mutex_take(link_id, GPS_DL_MTX_BIG_LOCK); + return 0; +} + +int gps_each_link_give_big_lock(enum gps_dl_link_id_enum link_id) +{ + gps_each_link_mutex_give(link_id, GPS_DL_MTX_BIG_LOCK); + return 0; +} + +enum gps_each_link_state_enum gps_each_link_get_state(enum gps_dl_link_id_enum link_id) +{ + struct gps_each_link *p = gps_dl_link_get(link_id); + enum gps_each_link_state_enum state; + + gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + state = p->state_for_user; + gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + + return state; +} + +void gps_each_link_set_state(enum gps_dl_link_id_enum link_id, enum gps_each_link_state_enum state) +{ + struct gps_each_link *p = gps_dl_link_get(link_id); + enum gps_each_link_state_enum pre_state; + + + gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + pre_state = p->state_for_user; + p->state_for_user = state; + gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + + GDL_LOGXI_STA(link_id, "state change: %s -> %s", + gps_dl_link_state_name(pre_state), gps_dl_link_state_name(state)); +} + +bool gps_each_link_change_state_from(enum gps_dl_link_id_enum link_id, + enum gps_each_link_state_enum from, enum gps_each_link_state_enum to) +{ + bool is_okay = false; + struct gps_each_link *p = gps_dl_link_get(link_id); + enum gps_each_link_state_enum pre_state; + enum gps_each_link_reset_level old_level, new_level; + + gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + pre_state = p->state_for_user; + if (from == pre_state) { + p->state_for_user = to; + is_okay = true; + + if (to == LINK_RESETTING) { + old_level = p->reset_level; + if (old_level < GPS_DL_RESET_LEVEL_GPS_SINGLE_LINK) + p->reset_level = GPS_DL_RESET_LEVEL_GPS_SINGLE_LINK; + new_level = p->reset_level; + } + } + gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + + if (is_okay && (to == LINK_RESETTING)) { + GDL_LOGXI_STA(link_id, "state change: %s -> %s, okay, level: %d -> %d", + gps_dl_link_state_name(from), gps_dl_link_state_name(to), + old_level, new_level); + } else if (is_okay) { + GDL_LOGXI_STA(link_id, "state change: %s -> %s, okay", + gps_dl_link_state_name(from), gps_dl_link_state_name(to)); + } else { + GDL_LOGXW_STA(link_id, "state change: %s -> %s, fail on pre_state = %s", + gps_dl_link_state_name(from), gps_dl_link_state_name(to), + gps_dl_link_state_name(pre_state)); + } + + return is_okay; +} + +bool gps_dl_link_start_tx_dma_if_has_data(enum gps_dl_link_id_enum link_id) +{ + struct gps_each_link *p_link = gps_dl_link_get(link_id); + struct gdl_dma_buf_entry dma_buf_entry; + enum GDL_RET_STATUS gdl_ret; + bool tx_dma_started; + + gdl_ret = gdl_dma_buf_get_data_entry(&p_link->tx_dma_buf, &dma_buf_entry); + + if (gdl_ret == GDL_OKAY) { + /* wait until dsp recevie last data done or timeout(10ms) + * TODO: handle timeout case + */ + gps_dl_hw_poll_usrt_dsp_rx_empty(link_id); + gps_dl_hal_a2d_tx_dma_claim_emi_usage(link_id, true); + gps_dl_hal_a2d_tx_dma_start(link_id, &dma_buf_entry); + tx_dma_started = true; + } else { + GDL_LOGD("gdl_dma_buf_get_data_entry ret = %s", gdl_ret_to_name(gdl_ret)); + tx_dma_started = false; + } + + return tx_dma_started; +} + +int gps_dl_link_get_clock_flag(void) +{ + return gps_dl_hal_get_clock_flag(); +} + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_conn_infra.c b/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_conn_infra.c new file mode 100644 index 0000000000000..93caba4c4a093 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_conn_infra.c @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#include "gps_dl_config.h" + +#include "gps_dl_context.h" +#include "gps_dl_hw_ver.h" +#include "gps_dl_hw_api.h" +#include "gps_dl_hal_api.h" +#if GPS_DL_HAS_PLAT_DRV +#include "gps_dl_linux_reserved_mem.h" +#endif + +#define GPS_EMI_REMAP_BASE_MASK (0xFFFFF0000) /* start from 64KB boundary, get msb20 of 36bit */ +#define GPS_EMI_REMAP_LENGTH (64 * 1024 * 1024UL) +#define GPS_EMI_BUS_BASE (0x78000000) + +void gps_dl_emi_remap_set(unsigned int min_addr, unsigned int max_addr) +{ + unsigned int aligned_addr = 0; + unsigned int _20msb_of_36bit_phy_addr; + + /* TODO: addr may not use uint, due to addr might be 36bit and uint might be only 32bit */ + aligned_addr = (min_addr & GPS_EMI_REMAP_BASE_MASK); + + + if (max_addr - aligned_addr > GPS_EMI_REMAP_LENGTH) { + GDL_LOGE("min = 0x%09x, max = 0x%09x, base = 0x%09x, over range", + min_addr, max_addr, aligned_addr); + } else { + GDL_LOGD("min = 0x%09x, max = 0x%09x, base = 0x%09x", + min_addr, max_addr, aligned_addr); + } + + _20msb_of_36bit_phy_addr = aligned_addr >> 16; + GDL_LOGD("icap_buf: remap setting = 0x%08x", _20msb_of_36bit_phy_addr); + gps_dl_hw_set_gps_emi_remapping(_20msb_of_36bit_phy_addr); + gps_dl_remap_ctx_get()->gps_emi_phy_high20 = aligned_addr; +} + +enum GDL_RET_STATUS gps_dl_emi_remap_phy_to_bus_addr(unsigned int phy_addr, unsigned int *bus_addr) +{ + unsigned int remap_setting = gps_dl_remap_ctx_get()->gps_emi_phy_high20; + + if ((phy_addr >= remap_setting) && + (phy_addr < (remap_setting + GPS_EMI_REMAP_LENGTH))) { + *bus_addr = GPS_EMI_BUS_BASE + (phy_addr - remap_setting); + return GDL_OKAY; + } + + *bus_addr = 0; + return GDL_FAIL; +} + +void gps_dl_emi_remap_calc_and_set(void) +{ + enum gps_dl_link_id_enum i; + struct gps_each_link *p_link; + + unsigned int min_addr = 0xFFFFFFFF; + unsigned int max_addr = 0; + unsigned int tx_end; + unsigned int rx_end; + +#if GPS_DL_HAS_PLAT_DRV + if (gps_dl_reserved_mem_is_ready()) { + gps_dl_reserved_mem_show_info(); + gps_dl_reserved_mem_get_range(&min_addr, &max_addr); + gps_dl_emi_remap_set(min_addr, max_addr); + return; + } +#endif + + for (i = 0; i < GPS_DATA_LINK_NUM; i++) { + p_link = gps_dl_link_get(i); + + min_addr = (p_link->rx_dma_buf.phy_addr < min_addr) ? p_link->rx_dma_buf.phy_addr : min_addr; + min_addr = (p_link->tx_dma_buf.phy_addr < min_addr) ? p_link->tx_dma_buf.phy_addr : min_addr; + + rx_end = p_link->rx_dma_buf.phy_addr + p_link->rx_dma_buf.len; + tx_end = p_link->tx_dma_buf.phy_addr + p_link->tx_dma_buf.len; + + max_addr = (rx_end > min_addr) ? rx_end : max_addr; + max_addr = (tx_end > min_addr) ? tx_end : max_addr; + } + GDL_LOGD("cal from dma buffers: min = 0x%x, max = 0x%x", min_addr, max_addr); + gps_dl_emi_remap_set(min_addr, max_addr); +} + + +unsigned int g_gps_dl_hal_conn_infra_poll_ok_ver; + +void gps_dl_hal_set_conn_infra_ver(unsigned int ver) +{ + g_gps_dl_hal_conn_infra_poll_ok_ver = ver; +} + +unsigned int gps_dl_hal_get_conn_infra_ver(void) +{ + return g_gps_dl_hal_conn_infra_poll_ok_ver; +} + +bool gps_dl_hal_conn_infra_ver_is_mt6885(void) +{ + /* is_mt6885 valid after gps_dl_hw_gps_common_on */ + return (gps_dl_hal_get_conn_infra_ver() == GDL_HW_CONN_INFRA_VER_MT6885); +} + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_dma.c b/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_dma.c new file mode 100644 index 0000000000000..6a92b431ff4c2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_dma.c @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "gps_dl_config.h" +#include "gps_dl_context.h" + +#include "gps_dl_hal.h" +#include "gps_dl_hal_api.h" +#include "gps_dl_hal_util.h" +#include "gps_each_link.h" + +#if GPS_DL_MOCK_HAL +#include "gps_mock_hal.h" +#endif +#include "gps_dl_hw_api.h" + +void gps_dl_hal_dma_init(void) +{ +} + +void gps_dl_hal_dma_config(enum gps_dl_hal_dma_ch_index ch) +{ +} + + +void gps_dl_hal_a2d_tx_dma_start(enum gps_dl_link_id_enum link_id, + struct gdl_dma_buf_entry *p_entry) +{ + struct gps_each_link *p_link = gps_dl_link_get(link_id); + + p_link->tx_dma_buf.dma_working_entry = *p_entry; + + GDL_LOGXD(link_id, ""); + + if (link_id == GPS_DATA_LINK_ID0) + gps_dl_hal_dma_start(GPS_DL_DMA_LINK0_A2D, p_entry); + else if (link_id == GPS_DATA_LINK_ID1) + gps_dl_hal_dma_start(GPS_DL_DMA_LINK1_A2D, p_entry); +} + +void gps_dl_hal_a2d_tx_dma_stop(enum gps_dl_link_id_enum link_id) +{ + if (link_id == GPS_DATA_LINK_ID0) + gps_dl_hal_dma_stop(GPS_DL_DMA_LINK0_A2D); + else if (link_id == GPS_DATA_LINK_ID1) + gps_dl_hal_dma_stop(GPS_DL_DMA_LINK1_A2D); +} + +enum GDL_RET_STATUS gps_dl_hal_a2d_tx_dma_wait_until_done_and_stop_it( + enum gps_dl_link_id_enum link_id, int timeout_usec, bool return_if_not_start) +{ + GDL_LOGXD(link_id, ""); + if (link_id == GPS_DATA_LINK_ID0) { + return gps_dl_hw_wait_until_dma_complete_and_stop_it( + GPS_DL_DMA_LINK0_A2D, timeout_usec, return_if_not_start); + } else if (link_id == GPS_DATA_LINK_ID1) { + return gps_dl_hw_wait_until_dma_complete_and_stop_it( + GPS_DL_DMA_LINK1_A2D, timeout_usec, return_if_not_start); + } + + return GDL_FAIL; +} + +void gps_dl_hal_d2a_rx_dma_start(enum gps_dl_link_id_enum link_id, + struct gdl_dma_buf_entry *p_entry) +{ + struct gps_each_link *p_link = gps_dl_link_get(link_id); + + ASSERT_LINK_ID(link_id, GDL_VOIDF()); + ASSERT_NOT_NULL(p_entry, GDL_VOIDF()); + + p_link->rx_dma_buf.dma_working_entry = *p_entry; + + if (link_id == GPS_DATA_LINK_ID0) + gps_dl_hal_dma_start(GPS_DL_DMA_LINK0_D2A, p_entry); + else if (link_id == GPS_DATA_LINK_ID1) + gps_dl_hal_dma_start(GPS_DL_DMA_LINK1_D2A, p_entry); +} + +void gps_dl_hal_d2a_rx_dma_stop(enum gps_dl_link_id_enum link_id) +{ + if (link_id == GPS_DATA_LINK_ID0) + gps_dl_hal_dma_stop(GPS_DL_DMA_LINK0_D2A); + else if (link_id == GPS_DATA_LINK_ID1) + gps_dl_hal_dma_stop(GPS_DL_DMA_LINK1_D2A); +} + +enum GDL_RET_STATUS gps_dl_hal_d2a_rx_dma_wait_until_done( + enum gps_dl_link_id_enum link_id, int timeout_usec) +{ + if (link_id == GPS_DATA_LINK_ID0) { + return gps_dl_hw_wait_until_dma_complete_and_stop_it( + GPS_DL_DMA_LINK0_D2A, timeout_usec, false); + } else if (link_id == GPS_DATA_LINK_ID1) { + return gps_dl_hw_wait_until_dma_complete_and_stop_it( + GPS_DL_DMA_LINK1_D2A, timeout_usec, false); + } + + return GDL_FAIL; +} + +unsigned int gps_dl_hal_d2a_rx_dma_get_rx_len(enum gps_dl_link_id_enum link_id) +{ + return 0; +} + +enum GDL_RET_STATUS gps_dl_real_dma_get_rx_write_index( + enum gps_dl_link_id_enum link_id, unsigned int *p_write_index) +{ + enum GDL_RET_STATUS gdl_ret; + unsigned int left_len; + enum gps_dl_hal_dma_ch_index ch; + struct gps_each_link *p_link = gps_dl_link_get(link_id); + + ASSERT_LINK_ID(link_id, GDL_FAIL_ASSERT); + + if (link_id == GPS_DATA_LINK_ID0) + ch = GPS_DL_DMA_LINK0_D2A; + else + ch = GPS_DL_DMA_LINK1_D2A; + + left_len = gps_dl_hw_get_dma_left_len(ch); + if (!gps_dl_is_1byte_mode()) + left_len *= 4; + + gdl_ret = gdl_dma_buf_entry_transfer_left_to_write_index( + &p_link->rx_dma_buf.dma_working_entry, left_len, p_write_index); + + return gdl_ret; +} + +enum GDL_RET_STATUS gps_dl_hal_d2a_rx_dma_get_write_index( + enum gps_dl_link_id_enum link_id, unsigned int *p_write_index) +{ +#if GPS_DL_MOCK_HAL + unsigned int write_index_from_mock; + enum GDL_RET_STATUS gdl_from_mock; +#endif + enum GDL_RET_STATUS gdl_ret; + + ASSERT_NOT_NULL(p_write_index, GDL_FAIL_ASSERT); +#if GPS_DL_MOCK_HAL + gdl_from_mock = gps_dl_mock_dma_get_rx_write_index(link_id, &write_index_from_mock); + if (gdl_from_mock != GDL_OKAY) + return gdl_from_mock; +#endif + gdl_ret = gps_dl_real_dma_get_rx_write_index(link_id, p_write_index); + GDL_LOGD("real gdl_ret = %s", gdl_ret_to_name(gdl_ret)); + +#if GPS_DL_MOCK_HAL + *p_write_index = write_index_from_mock; + return gdl_from_mock; +#else + return gdl_ret; +#endif +} + +void gps_dl_real_dma_start(enum gps_dl_hal_dma_ch_index ch, + struct gdl_dma_buf_entry *p_entry) +{ + enum GDL_RET_STATUS gdl_ret; + enum gps_dl_link_id_enum link_id; + struct gdl_hw_dma_transfer dma_transfer; + + ASSERT_NOT_NULL(p_entry, GDL_VOIDF()); + + link_id = DMA_CH_TO_LINK_ID(ch); + ASSERT_LINK_ID(link_id, GDL_VOIDF()); + + GDL_LOGXD(link_id, "ch = %d, r = %u, w = %u, addr = 0x%p", + ch, p_entry->read_index, p_entry->write_index, + p_entry->vir_addr); + + if (DMA_CH_IS_TX(ch)) + gdl_ret = gdl_dma_buf_entry_to_transfer(p_entry, &dma_transfer, true); + else if (DMA_CH_IS_RX(ch)) + gdl_ret = gdl_dma_buf_entry_to_transfer(p_entry, &dma_transfer, false); + else + GDL_ASSERT(false, GDL_VOIDF(), ""); + GDL_ASSERT(gdl_ret == GDL_OKAY, GDL_VOIDF(), "gdl_ret = %d", gdl_ret); + gps_dl_hw_set_dma_start(ch, &dma_transfer); +} + +void gps_dl_hal_dma_start(enum gps_dl_hal_dma_ch_index ch, + struct gdl_dma_buf_entry *p_entry) +{ + gps_dl_real_dma_start(ch, p_entry); +#if GPS_DL_MOCK_HAL + gps_dl_mock_dma_start(ch, p_entry); +#endif +} + +void gps_dl_hal_dma_stop(enum gps_dl_hal_dma_ch_index ch) +{ +#if GPS_DL_MOCK_HAL + gps_dl_mock_dma_stop(ch); +#endif + gps_dl_hw_set_dma_stop(ch); +} + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_hal.c b/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_hal.c new file mode 100644 index 0000000000000..3d03e4bd91d57 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_hal.c @@ -0,0 +1,461 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "gps_dl_hal.h" +#include "gps_dl_hw_api.h" +#include "gps_dsp_fsm.h" +#include "gps_each_link.h" +#include "gps_dl_isr.h" +#include "gps_dl_context.h" +#include "gps_dl_name_list.h" +#include "gps_dl_subsys_reset.h" +#if GPS_DL_HAS_CONNINFRA_DRV +#include "conninfra.h" +#endif + +#include "linux/jiffies.h" + + +static bool s_gps_has_data_irq_masked[GPS_DATA_LINK_NUM]; + + +void gps_dl_hal_event_send(enum gps_dl_hal_event_id evt, + enum gps_dl_link_id_enum link_id) +{ +#if (GPS_DL_HAS_CTRLD == 0) + gps_dl_hal_event_proc(evt, link_id, gps_each_link_get_session_id(link_id)); +#else + { + struct gps_dl_osal_lxop *pOp; + struct gps_dl_osal_signal *pSignal; + int iRet; + + pOp = gps_dl_get_free_op(); + if (!pOp) + return; + + pSignal = &pOp->signal; + pSignal->timeoutValue = 0;/* send data need to wait ?ms */ + if (link_id < GPS_DATA_LINK_NUM) { + pOp->op.opId = GPS_DL_OPID_HAL_EVENT_PROC; + pOp->op.au4OpData[0] = link_id; + pOp->op.au4OpData[1] = evt; + pOp->op.au4OpData[2] = gps_each_link_get_session_id(link_id); + iRet = gps_dl_put_act_op(pOp); + } else { + gps_dl_put_op_to_free_queue(pOp); + /*printf error msg*/ + return; + } + } +#endif +} + +void gps_dl_hal_event_proc(enum gps_dl_hal_event_id evt, + enum gps_dl_link_id_enum link_id, int sid_on_evt) +{ + struct gps_each_link *p_link = gps_dl_link_get(link_id); + struct gdl_dma_buf_entry dma_buf_entry; + enum GDL_RET_STATUS gdl_ret; + unsigned int write_index; + int curr_sid; + bool last_session_msg = false; + unsigned long j0, j1; + bool show_log, reg_rw_log; + bool conninfra_okay, dma_irq_en; + + j0 = jiffies; + curr_sid = gps_each_link_get_session_id(link_id); + + if (!gps_dl_reset_level_is_none(link_id) || + gps_each_link_get_bool_flag(link_id, LINK_IS_RESETTING)) { + /* ack the reset status */ + last_session_msg = true; + } else if (sid_on_evt != curr_sid && sid_on_evt != GPS_EACH_LINK_SID_NO_CHECK) { + GDL_LOGXW_EVT(link_id, "curr_sid = %d, evt = %s, on_sid = %d, not matching", + curr_sid, gps_dl_hal_event_name(evt), sid_on_evt); + last_session_msg = true; + } else if (!gps_each_link_is_active(link_id) || + gps_each_link_get_bool_flag(link_id, LINK_TO_BE_CLOSED)) { + GDL_LOGXW_EVT(link_id, "curr_sid = %d, evt = %s, on_sid = %d, not active", + curr_sid, gps_dl_hal_event_name(evt), sid_on_evt); + last_session_msg = true; + } + + if (last_session_msg) { + /* unmask irq to make it balance */ + if (evt == GPS_DL_HAL_EVT_D2A_RX_HAS_NODATA) { + gps_dl_irq_each_link_unmask(link_id, + GPS_DL_IRQ_TYPE_HAS_NODATA, GPS_DL_IRQ_CTRL_FROM_HAL); + } else if (evt == GPS_DL_HAL_EVT_D2A_RX_HAS_DATA) { + gps_dl_irq_each_link_unmask(link_id, + GPS_DL_IRQ_TYPE_HAS_DATA, GPS_DL_IRQ_CTRL_FROM_HAL); + } else if (evt == GPS_DL_HAL_EVT_MCUB_HAS_IRQ) { + gps_dl_irq_each_link_unmask(link_id, + GPS_DL_IRQ_TYPE_MCUB, GPS_DL_IRQ_CTRL_FROM_HAL); + } else if (evt == GPS_DL_HAL_EVT_DMA_ISR_PENDING) { + /* + * do nothing if last_session_msg + */ + } + return; + } + + if (sid_on_evt == GPS_EACH_LINK_SID_NO_CHECK) { + GDL_LOGXW_EVT(link_id, "curr_sid = %d, evt = %s, on_sid = %d, no check", + curr_sid, gps_dl_hal_event_name(evt), sid_on_evt); + } else if (sid_on_evt <= 0 || sid_on_evt > GPS_EACH_LINK_SID_MAX) { + GDL_LOGXW_EVT(link_id, "curr_sid = %d, evt = %s, on_sid = %d, out of range", + curr_sid, gps_dl_hal_event_name(evt), sid_on_evt); + } else { + GDL_LOGXD_EVT(link_id, "curr_sid = %d, evt = %s, on_sid = %d", + curr_sid, gps_dl_hal_event_name(evt), sid_on_evt); + } + + GDL_LOGXD_EVT(link_id, "evt = %s", gps_dl_hal_event_name(evt)); + switch (evt) { + case GPS_DL_HAL_EVT_D2A_RX_HAS_DATA: + gdl_ret = gdl_dma_buf_get_free_entry( + &p_link->rx_dma_buf, &dma_buf_entry, true); + + s_gps_has_data_irq_masked[link_id] = true; + if (gdl_ret == GDL_OKAY) { + gps_dl_hal_d2a_rx_dma_claim_emi_usage(link_id, true); + gps_dl_hal_d2a_rx_dma_start(link_id, &dma_buf_entry); + } else { + + /* TODO: has pending rx: GDL_FAIL_NOSPACE_PENDING_RX */ + GDL_LOGXI_DRW(link_id, "rx dma not start due to %s", gdl_ret_to_name(gdl_ret)); + } + break; + + /* TODO: handle the case data_len is just equal to buf_len, */ + /* the rx_dma_done and usrt_has_nodata both happen. */ + case GPS_DL_HAL_EVT_D2A_RX_DMA_DONE: + /* TODO: to make mock work with it */ + + /* stop and clear int flag in isr */ + /* gps_dl_hal_d2a_rx_dma_stop(link_id); */ + p_link->rx_dma_buf.dma_working_entry.write_index = + p_link->rx_dma_buf.dma_working_entry.read_index; + + /* check whether no data also happen */ + if (gps_dl_hw_usrt_has_set_nodata_flag(link_id)) { + p_link->rx_dma_buf.dma_working_entry.is_nodata = true; + gps_dl_hw_usrt_clear_nodata_irq(link_id); + } else + p_link->rx_dma_buf.dma_working_entry.is_nodata = false; + + gdl_ret = gdl_dma_buf_set_free_entry(&p_link->rx_dma_buf, + &p_link->rx_dma_buf.dma_working_entry); + + if (gdl_ret == GDL_OKAY) { + p_link->rx_dma_buf.dma_working_entry.is_valid = false; + gps_dl_link_wake_up(&p_link->waitables[GPS_DL_WAIT_READ]); + } + + gps_dl_hal_d2a_rx_dma_claim_emi_usage(link_id, false); + /* mask data irq */ + if (s_gps_has_data_irq_masked[link_id] == true) { + gps_dl_irq_each_link_unmask(link_id, GPS_DL_IRQ_TYPE_HAS_DATA, GPS_DL_IRQ_CTRL_FROM_HAL); + s_gps_has_data_irq_masked[link_id] = false; + } else + GDL_LOGXW_DRW(link_id, "D2A_RX_DMA_DONE while s_gps_has_data_irq_masked is false"); + break; + + case GPS_DL_HAL_EVT_D2A_RX_HAS_NODATA: + /* get rx length */ + gdl_ret = gps_dl_hal_d2a_rx_dma_get_write_index(link_id, &write_index); + + /* 20181118 for mock, rx dma stop must after get write index */ + gps_dl_hal_d2a_rx_dma_stop(link_id); + + if (gdl_ret == GDL_OKAY) { + /* no need to mask data irq */ + p_link->rx_dma_buf.dma_working_entry.write_index = write_index; + p_link->rx_dma_buf.dma_working_entry.is_nodata = true; + + gdl_ret = gdl_dma_buf_set_free_entry(&p_link->rx_dma_buf, + &p_link->rx_dma_buf.dma_working_entry); + + if (gdl_ret != GDL_OKAY) + GDL_LOGD("gdl_dma_buf_set_free_entry ret = %s", gdl_ret_to_name(gdl_ret)); + + } else + GDL_LOGD("gps_dl_hal_d2a_rx_dma_get_write_index ret = %s", gdl_ret_to_name(gdl_ret)); + + if (gdl_ret == GDL_OKAY) { + p_link->rx_dma_buf.dma_working_entry.is_valid = false; + gps_dl_link_wake_up(&p_link->waitables[GPS_DL_WAIT_READ]); + } + + gps_dl_hal_d2a_rx_dma_claim_emi_usage(link_id, false); + gps_dl_hw_usrt_clear_nodata_irq(link_id); + gps_dl_irq_each_link_unmask(link_id, GPS_DL_IRQ_TYPE_HAS_NODATA, GPS_DL_IRQ_CTRL_FROM_HAL); + if (gps_dl_test_mask_hasdata_irq_get(link_id)) { + GDL_LOGXE(link_id, "test mask hasdata irq, not unmask irq and wait reset"); + gps_dl_test_mask_hasdata_irq_set(link_id, false); + gps_dl_hal_set_irq_dis_flag(link_id, GPS_DL_IRQ_TYPE_HAS_DATA, true); + } else { + if (s_gps_has_data_irq_masked[link_id] == true) { + gps_dl_irq_each_link_unmask(link_id, GPS_DL_IRQ_TYPE_HAS_DATA, + GPS_DL_IRQ_CTRL_FROM_HAL); + s_gps_has_data_irq_masked[link_id] = false; + } else + GDL_LOGXW_DRW(link_id, "D2A_RX_HAS_NODATA while s_gps_has_data_irq_masked is false"); + } + break; + + case GPS_DL_HAL_EVT_A2D_TX_DMA_DONE: + /* gps_dl_hw_print_usrt_status(link_id); */ + + /* data tx finished */ + gdl_ret = gdl_dma_buf_set_data_entry(&p_link->tx_dma_buf, + &p_link->tx_dma_buf.dma_working_entry); + + p_link->tx_dma_buf.dma_working_entry.is_valid = false; + + GDL_LOGD("gdl_dma_buf_set_data_entry ret = %s", gdl_ret_to_name(gdl_ret)); + + /* stop tx dma, should stop and clear int flag in isr */ + /* gps_dl_hal_a2d_tx_dma_stop(link_id); */ + + /* wakeup writer if it's pending on it */ + gps_dl_link_wake_up(&p_link->waitables[GPS_DL_WAIT_WRITE]); + gps_dl_hal_a2d_tx_dma_claim_emi_usage(link_id, false); + gps_dl_link_start_tx_dma_if_has_data(link_id); + break; + + case GPS_DL_HAL_EVT_DMA_ISR_PENDING: + conninfra_okay = gps_dl_conninfra_is_okay_or_handle_it(NULL, true); + dma_irq_en = gps_dl_hal_get_dma_irq_en_flag(); + + GDL_LOGXE(link_id, "conninfra_okay = %d, dma_irq_en = %d", conninfra_okay, dma_irq_en); + if (conninfra_okay && !dma_irq_en) { + gps_dl_irq_unmask_dma_intr(GPS_DL_IRQ_CTRL_FROM_HAL); + gps_dl_hal_set_dma_irq_en_flag(true); + } + break; + + case GPS_DL_HAL_EVT_MCUB_HAS_IRQ: + reg_rw_log = gps_dl_log_reg_rw_is_on(GPS_DL_REG_RW_MCUB_IRQ_HANDLER); + if (reg_rw_log) + show_log = gps_dl_set_show_reg_rw_log(true); + if (!gps_dl_hal_mcub_flag_handler(link_id)) { + GDL_LOGXE(link_id, "mcub_flag_handler not okay, not unmask irq and wait reset"); + gps_dl_hal_set_mcub_irq_dis_flag(link_id, true); + } else + gps_dl_irq_each_link_unmask(link_id, GPS_DL_IRQ_TYPE_MCUB, GPS_DL_IRQ_CTRL_FROM_HAL); + if (reg_rw_log) + gps_dl_set_show_reg_rw_log(show_log); + break; + +#if 0 + case GPS_DL_HAL_EVT_DSP_ROM_START: + gps_dsp_fsm(GPS_DSP_EVT_RESET_DONE, link_id); + + /* if has pending data, can send it now */ + gdl_ret = gdl_dma_buf_get_data_entry(&p_link->tx_dma_buf, &dma_buf_entry); + if (gdl_ret == GDL_OKAY) + gps_dl_hal_a2d_tx_dma_start(link_id, &dma_buf_entry); + break; + + case GPS_DL_HAL_EVT_DSP_RAM_START: + gps_dsp_fsm(GPS_DSP_EVT_RAM_CODE_READY, link_id); + + /* start reg polling */ + break; +#endif + + default: + break; + } + + j1 = jiffies; + GDL_LOGXI_EVT(link_id, "evt = %s, on_sid = %d, dj = %lu", + gps_dl_hal_event_name(evt), sid_on_evt, j1 - j0); +} + +bool gps_dl_hal_mcub_flag_handler(enum gps_dl_link_id_enum link_id) +{ + struct gps_dl_hal_mcub_info d2a; + bool conninfra_okay; + + /* Todo: while condition make sure DSP is on and session ID */ + while (1) { + conninfra_okay = gps_dl_conninfra_is_okay_or_handle_it(NULL, true); + if (!conninfra_okay) { + GDL_LOGXE(link_id, "conninfra_okay = %d", conninfra_okay); + return false; /* not okay */ + } + + gps_dl_hw_get_mcub_info(link_id, &d2a); + if (d2a.flag == 0) + break; + + if (d2a.flag == GPS_MCUB_D2AF_MASK_DSP_REG_READ_READY) { + /* do nothing + * + * only "reg read ready" in flag bits, print the information in + * gps_each_dsp_reg_read_ack, rather than here. + */ + } else { + GDL_LOGXI(link_id, "d2a: flag = 0x%04x, d0 = 0x%04x, d1 = 0x%04x", + d2a.flag, d2a.dat0, d2a.dat1); + } + + if (d2a.flag == 0xdeadfeed) { + gps_dl_hw_dump_host_csr_gps_info(true); + gps_dl_hw_dump_sleep_prot_status(); + + GDL_LOGXE(link_id, "deadfeed, trigger connsys reset"); + gps_dl_trigger_connsys_reset(); + return false; + } + + /* Todo: if (dsp is off) -> break */ + /* Note: clear flag before check and handle the flage event, + * avoiding race condtion when dsp do "too fast twice ack". + * EX: gps_each_dsp_reg_gourp_read_next + */ + gps_dl_hw_clear_mcub_d2a_flag(link_id, d2a.flag); + + if (d2a.flag & GPS_MCUB_D2AF_MASK_DSP_RESET_DONE) { + /* gps_dl_hal_event_send(GPS_DL_HAL_EVT_DSP_ROM_START, link_id); */ + gps_dsp_fsm(GPS_DSP_EVT_RESET_DONE, link_id); + } + + if (d2a.flag & GPS_MCUB_D2AF_MASK_DSP_RAMCODE_READY) { + if (d2a.dat1 == 0xDEAD || d2a.dat1 == 0xBEEF) { + GDL_LOGXW(link_id, + "d2a: flag = 0x%04x, d0 = 0x%04x, d1 = 0x%04x, do dump", + d2a.flag, d2a.dat0, d2a.dat1); + gps_dl_hw_dump_host_csr_gps_info(true); +#if GPS_DL_HAS_CONNINFRA_DRV + /* API to check and dump host csr */ + conninfra_is_bus_hang(); +#else + gps_dl_hw_dump_host_csr_conninfra_info(true); +#endif + gps_dl_hw_print_hw_status(link_id, true); + gps_dl_hw_dump_host_csr_gps_info(true); + continue; + } + + /* bypass gps_dsp_fsm if ariving here and the status is already working */ + if (GPS_DSP_ST_WORKING == gps_dsp_state_get(link_id)) + continue; + + /* gps_dl_hal_event_send(GPS_DL_HAL_EVT_DSP_RAM_START, link_id); */ + gps_dsp_fsm(GPS_DSP_EVT_RAM_CODE_READY, link_id); + + /* start reg polling */ + gps_each_dsp_reg_gourp_read_start(link_id, false, 1); + } + + if (d2a.flag & GPS_MCUB_D2AF_MASK_DSP_REG_READ_READY) + gps_each_dsp_reg_read_ack(link_id, &d2a); + + } + + return true; +} + + +unsigned int g_gps_dl_hal_emi_usage_bitmask; + +void gps_dl_hal_emi_usage_init(void) +{ + unsigned int old_mask; + + old_mask = g_gps_dl_hal_emi_usage_bitmask; + g_gps_dl_hal_emi_usage_bitmask = 0; + + if (old_mask) + GDL_LOGW("mask is 0x%x, force it to 0", old_mask); + else + GDL_LOGD("mask is 0"); + + /* Not claim/disclaim it for low power + * gps_dl_hal_emi_usage_claim(GPS_DL_EMI_USER_GPS_ON, true); + */ +} + +void gps_dl_hal_emi_usage_deinit(void) +{ + unsigned int old_mask; + + /* Not claim/disclaim it for low power + * gps_dl_hal_emi_usage_claim(GPS_DL_EMI_USER_GPS_ON, false); + */ + + old_mask = g_gps_dl_hal_emi_usage_bitmask; + + if (old_mask) + GDL_LOGW("mask is 0x%x, force to release emi usage", old_mask); + else + GDL_LOGD("mask is 0"); + + /* force to release it anyway */ + gps_dl_hw_gps_sw_request_emi_usage(false); +} + +void gps_dl_hal_emi_usage_claim(enum gps_dl_hal_emi_user user, bool use_emi) +{ + unsigned int old_mask, new_mask; + bool changed = false, usage = false; + + /* TODO: protect them using spin lock to make it more safe, + * currently only one thread call me, no racing. + */ + old_mask = g_gps_dl_hal_emi_usage_bitmask; + if (use_emi) + g_gps_dl_hal_emi_usage_bitmask = old_mask | (1UL << user); + else + g_gps_dl_hal_emi_usage_bitmask = old_mask & ~(1UL << user); + new_mask = g_gps_dl_hal_emi_usage_bitmask; + + if (old_mask == 0 && new_mask != 0) { + gps_dl_hw_gps_sw_request_emi_usage(true); + changed = true; + usage = true; + } else if (old_mask != 0 && new_mask == 0) { + gps_dl_hw_gps_sw_request_emi_usage(false); + changed = true; + usage = false; + } + + if (changed) { + GDL_LOGD("user = %d, use = %d, old_mask = 0x%x, new_mask = 0x%x, change = %d/%d", + user, use_emi, old_mask, new_mask, changed, usage); + } else { + GDL_LOGD("user = %d, use = %d, old_mask = 0x%x, new_mask = 0x%x, change = %d", + user, use_emi, old_mask, new_mask, changed); + } +} + +void gps_dl_hal_a2d_tx_dma_claim_emi_usage(enum gps_dl_link_id_enum link_id, bool use_emi) +{ + if (link_id == GPS_DATA_LINK_ID0) + gps_dl_hal_emi_usage_claim(GPS_DL_EMI_USER_TX_DMA0, use_emi); + else if (link_id == GPS_DATA_LINK_ID1) + gps_dl_hal_emi_usage_claim(GPS_DL_EMI_USER_TX_DMA1, use_emi); +} + +void gps_dl_hal_d2a_rx_dma_claim_emi_usage(enum gps_dl_link_id_enum link_id, bool use_emi) +{ + if (link_id == GPS_DATA_LINK_ID0) + gps_dl_hal_emi_usage_claim(GPS_DL_EMI_USER_RX_DMA0, use_emi); + else if (link_id == GPS_DATA_LINK_ID1) + gps_dl_hal_emi_usage_claim(GPS_DL_EMI_USER_RX_DMA1, use_emi); +} + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_hal_util.c b/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_hal_util.c new file mode 100644 index 0000000000000..a9bff23abac7f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_hal_util.c @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + + + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_isr.c b/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_isr.c new file mode 100644 index 0000000000000..87a1c852a14b9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_isr.c @@ -0,0 +1,335 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "gps_dl_config.h" +#include "gps_dl_isr.h" +#include "gps_dl_hal.h" +#include "gps_dl_hw_api.h" +#include "gps_dl_hal_util.h" +#include "gps_dsp_fsm.h" +#include "gps_each_link.h" +#include "gps/gps_usrt_apb.h" +#include "gps/gps_l5_usrt_apb.h" + +/* TODO: IRQ hwirq, irq_id, gdl_irq_index */ +/* On CTP: hwirq == irq_id */ +/* On Linux: hwirq != irq_id */ +#if GPS_DL_ON_CTP +/* x_define_irq.h 198 -> 415 */ +#define GPS_DL_IRQ_BASE_ID (GPS_L1_IRQ_BUS_BIT0_ID) +#else +#define GPS_DL_IRQ_BASE_ID (383) /* (415 - 32) */ +#endif + +#define GPS_IRQ_ID_DL0_HAS_DATA (GPS_DL_IRQ_BASE_ID + 0) +#define GPS_IRQ_ID_DL0_HAS_NODATA (GPS_DL_IRQ_BASE_ID + 1) +#define GPS_IRQ_ID_DL0_MCUB (GPS_DL_IRQ_BASE_ID + 2) +#define GPS_IRQ_ID_DL1_HAS_DATA (GPS_DL_IRQ_BASE_ID + 3) +#define GPS_IRQ_ID_DL1_HAS_NODATA (GPS_DL_IRQ_BASE_ID + 4) +#define GPS_IRQ_ID_DL1_MCUB (GPS_DL_IRQ_BASE_ID + 5) +#define GPS_IRQ_ID_DMA_DONE (GPS_DL_IRQ_BASE_ID + 6) + +#if GPS_DL_ON_LINUX +/* TODO: hwirq and linux irq id */ +int g_gps_irq_index_to_id_table[GPS_DL_IRQ_NUM]; +void gps_dl_irq_set_id(enum gps_dl_irq_index_enum irq_idx, int irq_id) +{ + g_gps_irq_index_to_id_table[irq_idx] = irq_id; +} +#else +int g_gps_irq_index_to_id_table[GPS_DL_IRQ_NUM] = { + [GPS_DL_IRQ_LINK0_DATA] = GPS_IRQ_ID_DL0_HAS_DATA, + [GPS_DL_IRQ_LINK0_NODATA] = GPS_IRQ_ID_DL0_HAS_NODATA, + [GPS_DL_IRQ_LINK0_MCUB] = GPS_IRQ_ID_DL0_MCUB, + [GPS_DL_IRQ_LINK1_DATA] = GPS_IRQ_ID_DL1_HAS_DATA, + [GPS_DL_IRQ_LINK1_NODATA] = GPS_IRQ_ID_DL1_HAS_NODATA, + [GPS_DL_IRQ_LINK1_MCUB] = GPS_IRQ_ID_DL1_MCUB, + [GPS_DL_IRQ_DMA] = GPS_IRQ_ID_DMA_DONE, +}; +#endif + +int gps_dl_irq_index_to_id(enum gps_dl_irq_index_enum irq_idx) +{ + ASSERT_IRQ_IDX(irq_idx, -1); + return g_gps_irq_index_to_id_table[irq_idx]; +} + +int g_gps_irq_type_to_hwirq_table[GPS_DATA_LINK_NUM][GPS_DL_IRQ_TYPE_NUM] = { + [GPS_DATA_LINK_ID0][GPS_DL_IRQ_TYPE_HAS_DATA] = + GPS_IRQ_ID_DL0_HAS_DATA, + [GPS_DATA_LINK_ID0][GPS_DL_IRQ_TYPE_HAS_NODATA] = + GPS_IRQ_ID_DL0_HAS_NODATA, + [GPS_DATA_LINK_ID0][GPS_DL_IRQ_TYPE_MCUB] = + GPS_IRQ_ID_DL0_MCUB, + + [GPS_DATA_LINK_ID1][GPS_DL_IRQ_TYPE_HAS_DATA] = + GPS_IRQ_ID_DL1_HAS_DATA, + [GPS_DATA_LINK_ID1][GPS_DL_IRQ_TYPE_HAS_NODATA] = + GPS_IRQ_ID_DL1_HAS_NODATA, + [GPS_DATA_LINK_ID1][GPS_DL_IRQ_TYPE_MCUB] = + GPS_IRQ_ID_DL1_MCUB, +}; + +int gps_dl_irq_type_to_hwirq(enum gps_dl_link_id_enum link_id, + enum gps_dl_each_link_irq_type irq_type) +{ + ASSERT_LINK_ID(link_id, -1); + ASSERT_IRQ_TYPE(irq_type, -1); + return g_gps_irq_type_to_hwirq_table[link_id][irq_type]; +} + +int g_gps_irq_type_to_index_table[GPS_DATA_LINK_NUM][GPS_DL_IRQ_TYPE_NUM] = { + [GPS_DATA_LINK_ID0][GPS_DL_IRQ_TYPE_HAS_DATA] = + GPS_DL_IRQ_LINK0_DATA, + [GPS_DATA_LINK_ID0][GPS_DL_IRQ_TYPE_HAS_NODATA] = + GPS_DL_IRQ_LINK0_NODATA, + [GPS_DATA_LINK_ID0][GPS_DL_IRQ_TYPE_MCUB] = + GPS_DL_IRQ_LINK0_MCUB, + + [GPS_DATA_LINK_ID1][GPS_DL_IRQ_TYPE_HAS_DATA] = + GPS_DL_IRQ_LINK1_DATA, + [GPS_DATA_LINK_ID1][GPS_DL_IRQ_TYPE_HAS_NODATA] = + GPS_DL_IRQ_LINK1_NODATA, + [GPS_DATA_LINK_ID1][GPS_DL_IRQ_TYPE_MCUB] = + GPS_DL_IRQ_LINK1_MCUB, + +}; + +int gps_dl_irq_type_to_id(enum gps_dl_link_id_enum link_id, + enum gps_dl_each_link_irq_type irq_type) +{ + int irq_index; + int irq_id; + + ASSERT_LINK_ID(link_id, -1); + ASSERT_IRQ_TYPE(irq_type, -1); + + irq_index = g_gps_irq_type_to_index_table[link_id][irq_type]; + irq_id = g_gps_irq_index_to_id_table[irq_index]; + + return irq_id; +} + +void gps_dl_irq_each_link_control(enum gps_dl_link_id_enum link_id, + enum gps_dl_each_link_irq_type irq_type, bool mask_it, + enum gps_dl_irq_ctrl_from from) +{ + int irq_id; + + ASSERT_LINK_ID(link_id, GDL_VOIDF()); + + irq_id = gps_dl_irq_type_to_id(link_id, irq_type); + + GDL_LOGXD(link_id, "irq ctrl: from = %d, mask = %d, type = %d, irq_id = %d", + from, mask_it, irq_type, irq_id); +#if !GPS_DL_HW_IS_MOCK + if (mask_it) + gps_dl_irq_mask(irq_id, from); + else + gps_dl_irq_unmask(irq_id, from); +#endif +} + +void gps_dl_irq_each_link_mask(enum gps_dl_link_id_enum link_id, + enum gps_dl_each_link_irq_type irq_type, enum gps_dl_irq_ctrl_from from) +{ +#if (GPS_DL_ON_CTP && !GPS_DL_NO_USE_IRQ) + if (irq_type == GPS_DL_IRQ_TYPE_HAS_DATA && + gps_dl_link_is_ready_to_write(link_id)) + /* Note: CTP isr main always unmask ARM IRQ when return. */ + /* we need irq not go for some cases, so musk it form GPS side. */ + gps_dl_hw_usrt_rx_irq_enable(link_id, false); +#endif + gps_dl_irq_each_link_control(link_id, irq_type, true, from); +} + +void gps_dl_irq_each_link_unmask(enum gps_dl_link_id_enum link_id, + enum gps_dl_each_link_irq_type irq_type, enum gps_dl_irq_ctrl_from from) +{ +#if (GPS_DL_ON_CTP && !GPS_DL_NO_USE_IRQ) + if (irq_type == GPS_DL_IRQ_TYPE_HAS_DATA && + gps_dl_link_is_ready_to_write(link_id)) + gps_dl_hw_usrt_rx_irq_enable(link_id, true); +#endif + gps_dl_irq_each_link_control(link_id, irq_type, false, from); +} + +void gps_dl_irq_mask_dma_intr(enum gps_dl_irq_ctrl_from from) +{ + GDL_LOGD("from = %d", from); +#if !GPS_DL_HW_IS_MOCK + gps_dl_irq_mask(gps_dl_irq_index_to_id(GPS_DL_IRQ_DMA), from); +#endif +} + +void gps_dl_irq_unmask_dma_intr(enum gps_dl_irq_ctrl_from from) +{ + GDL_LOGD("from = %d", from); +#if !GPS_DL_HW_IS_MOCK + gps_dl_irq_unmask(gps_dl_irq_index_to_id(GPS_DL_IRQ_DMA), from); +#endif +} + +void gps_dl_isr_usrt_has_data(enum gps_dl_link_id_enum link_id) +{ + GDL_LOGXD(link_id, "start"); + gps_dl_irq_each_link_mask(link_id, GPS_DL_IRQ_TYPE_HAS_DATA, GPS_DL_IRQ_CTRL_POSSIBLE_FROM_ISR); + + if (gps_each_link_is_active(link_id)) + gps_dl_hal_event_send(GPS_DL_HAL_EVT_D2A_RX_HAS_DATA, link_id); + else { + /* NOTE: ctrld has already unmask it, still unmask here to keep balance */ + gps_dl_irq_each_link_unmask(link_id, GPS_DL_IRQ_TYPE_HAS_DATA, + GPS_DL_IRQ_CTRL_POSSIBLE_FROM_ISR); + GDL_LOGXD(link_id, "bypass due to link not active"); + } +} + +void gps_dl_isr_usrt_has_nodata(enum gps_dl_link_id_enum link_id) +{ + GDL_LOGXD(link_id, "ch = %d", GET_RX_DMA_CH_OF(link_id)); + + gps_dl_irq_each_link_mask(link_id, GPS_DL_IRQ_TYPE_HAS_NODATA, GPS_DL_IRQ_CTRL_POSSIBLE_FROM_ISR); + + if (gps_each_link_is_active(link_id)) + gps_dl_hal_event_send(GPS_DL_HAL_EVT_D2A_RX_HAS_NODATA, link_id); + else { + gps_dl_irq_each_link_unmask(link_id, GPS_DL_IRQ_TYPE_HAS_NODATA, + GPS_DL_IRQ_CTRL_POSSIBLE_FROM_ISR); + GDL_LOGXD(link_id, "bypass due to link not active"); + } +} + +void gps_dl_isr_d2a_rx_dma_done(enum gps_dl_link_id_enum link_id) +{ + GDL_LOGXD(link_id, "ch = %d", GET_RX_DMA_CH_OF(link_id)); + + /* gps_dl_irq_each_link_mask(link_id, GPS_DL_IRQ_TYPE_MCUB); */ + gps_dl_hal_d2a_rx_dma_stop(link_id); + + gps_dl_hal_event_send(GPS_DL_HAL_EVT_D2A_RX_DMA_DONE, link_id); +} + +void gps_dl_isr_a2d_tx_dma_done(enum gps_dl_link_id_enum link_id) +{ + GDL_LOGXD(link_id, "ch = %d", GET_TX_DMA_CH_OF(link_id)); + + /* gps_dl_irq_mask_dma_intr(); */ + gps_dl_hal_a2d_tx_dma_stop(link_id); + + /* update dma buf write pointor */ + /* notify controller thread */ + gps_dl_hal_event_send(GPS_DL_HAL_EVT_A2D_TX_DMA_DONE, link_id); + + /* by ctrld thread determine whether start next dma session */ +} + +void gps_dl_isr_dma_done(void) +{ + enum gps_dl_hal_dma_ch_index i; + + gps_dl_irq_mask_dma_intr(GPS_DL_IRQ_CTRL_POSSIBLE_FROM_ISR); + + if (!gps_dl_conninfra_is_readable()) { + /* set it for gps_ctrld to check, avoiding twice mask */ + gps_dl_hal_set_dma_irq_en_flag(false); + gps_dl_hal_event_send(GPS_DL_HAL_EVT_DMA_ISR_PENDING, GPS_DATA_LINK_ID0); + gps_dl_hal_event_send(GPS_DL_HAL_EVT_DMA_ISR_PENDING, GPS_DATA_LINK_ID1); + GDL_LOGE("pending due to readable check fail"); + return; + } + + /* dma isr must copy the data and restore the intr flag + * no need to copy data, the data is copied in ctrld thread + */ + + /* TODO: not always starts on i = 0 to make it's fair for each DMA ch */ + for (i = 0; i < GPS_DL_DMA_CH_NUM; i++) { + /* TODO: is the dma ch is active */ + + if (gps_dl_hw_get_dma_int_status(i)) { +#if 0 + DMA_Stop((kal_uint8)(index)); + set_dma_acki(index); + while (DMA_CheckRunStat(index)) + ; + DMA_Clock_Disable(index); +#endif + switch (i) { + case GPS_DL_DMA_LINK0_A2D: + gps_dl_isr_a2d_tx_dma_done(GPS_DATA_LINK_ID0); + break; + case GPS_DL_DMA_LINK0_D2A: + gps_dl_isr_d2a_rx_dma_done(GPS_DATA_LINK_ID0); + break; + case GPS_DL_DMA_LINK1_A2D: + gps_dl_isr_a2d_tx_dma_done(GPS_DATA_LINK_ID1); + break; + case GPS_DL_DMA_LINK1_D2A: + gps_dl_isr_d2a_rx_dma_done(GPS_DATA_LINK_ID1); + break; + default: + break; + } + } + } + /* TODO: end for-loop until all DMA is stopped */ + + gps_dl_irq_unmask_dma_intr(GPS_DL_IRQ_CTRL_POSSIBLE_FROM_ISR); +} + +void gps_dl_isr_mcub(enum gps_dl_link_id_enum link_id) +{ + GDL_LOGXD(link_id, "start"); + gps_dl_irq_each_link_mask(link_id, GPS_DL_IRQ_TYPE_MCUB, GPS_DL_IRQ_CTRL_FROM_ISR); + + if (gps_each_link_is_active(link_id)) + gps_dl_hal_event_send(GPS_DL_HAL_EVT_MCUB_HAS_IRQ, link_id); + else { + gps_dl_irq_each_link_unmask(link_id, GPS_DL_IRQ_TYPE_MCUB, + GPS_DL_IRQ_CTRL_POSSIBLE_FROM_ISR); + GDL_LOGXD(link_id, "bypass due to link not active"); + } +} + +#if GPS_DL_ON_CTP +void gps_dl_isr_dl0_has_data(void) +{ + gps_dl_isr_usrt_has_data(GPS_DATA_LINK_ID0); +} + +void gps_dl_isr_dl0_has_nodata(void) +{ + gps_dl_isr_usrt_has_nodata(GPS_DATA_LINK_ID0); +} + +void gps_dl_isr_dl0_mcub(void) +{ + gps_dl_isr_mcub(GPS_DATA_LINK_ID0); +} + +void gps_dl_isr_dl1_has_data(void) +{ + gps_dl_isr_usrt_has_data(GPS_DATA_LINK_ID1); +} + +void gps_dl_isr_dl1_has_nodata(void) +{ + gps_dl_isr_usrt_has_nodata(GPS_DATA_LINK_ID1); +} + +void gps_dl_isr_dl1_mcub(void) +{ + gps_dl_isr_mcub(GPS_DATA_LINK_ID1); +} +#endif + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_mcub.c b/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_mcub.c new file mode 100644 index 0000000000000..f172562187336 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_mcub.c @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "gps_dl_config.h" +#include "gps_dl_log.h" +#include "gps_dl_hw_api.h" +#include "gps_dsp_fsm.h" + +#define GPS_DSP_REG_POLL_MAX (11) +const unsigned int c_gps_dsp_reg_list[GPS_DATA_LINK_NUM][GPS_DSP_REG_POLL_MAX] = { + /* 8: HW TICK H/L, BG tick H/L, TX_END/TX_RD, RX_END/RX_WR + * 3: PC, GALMAN CNT, WRHOST CNT + */ + { + 0x5028, 0x5029, 0x0100, 0x0101, 0x4882, 0x4883, 0x4886, 0x4887, + 0xEF00, 0xEF01, 0xEF02, + }, + { + 0x5014, 0x5015, 0x0100, 0x0101, 0x4882, 0x4883, 0x4886, 0x4887, + 0xEF00, 0xEF01, 0xEF02, + } +}; + +#define GPS_DSP_REG_DBG_POLL_MAX (20) +const unsigned int c_gps_dsp_reg_dbg_list[GPS_DATA_LINK_NUM][GPS_DSP_REG_DBG_POLL_MAX] = { + /* 9: PC, GALMAN CNT, WRHOST CNT, DBTT CNT, NEXT CNT, BG TICK H/L, HW TICK H/L + * 11: USRT CTL, STA, TX_END/RD/MAX, RX_MAX/END/WR, TX_CNT, RX_CNT, MISC + */ + { + 0xEF00, 0xEF01, 0xEF02, 0xEF03, 0xEF04, 0x0100, 0x0101, 0x5028, 0x5029, + 0x4880, 0x4881, 0x4882, 0x4883, 0x4884, 0x4885, 0x4886, 0x4887, 0x4888, 0x4889, 0x488a, + }, + { + 0xEF00, 0xEF01, 0xEF02, 0xEF03, 0xEF04, 0x0100, 0x0101, 0x5014, 0x5015, + 0x4880, 0x4881, 0x4882, 0x4883, 0x4884, 0x4885, 0x4886, 0x4887, 0x4888, 0x4889, 0x488a, + } +}; + + + +struct gps_each_dsp_reg_read_context { + bool poll_ongoing; + int poll_index; + unsigned int poll_addr; + + /* a "poll" means one register in c_gps_dsp_reg_list. + * a "round" means a round to poll all registers in c_gps_dsp_reg_list. + * sometimes for debug we need for several rounds + * to check the changing of the values of each register. + */ + unsigned int round_max; + unsigned int round_index; + const unsigned int *poll_list_ptr; + int poll_list_len; +}; + +struct gps_each_dsp_reg_read_context g_gps_each_dsp_reg_read_context[GPS_DATA_LINK_NUM]; + + +enum GDL_RET_STATUS gps_each_dsp_reg_read_request( + enum gps_dl_link_id_enum link_id, unsigned int reg_addr) +{ + enum GDL_RET_STATUS ret; + + ASSERT_LINK_ID(link_id, GDL_FAIL_INVAL); + ret = gps_dl_hw_mcub_dsp_read_request(link_id, reg_addr); + + if (ret == GDL_OKAY) { + g_gps_each_dsp_reg_read_context[link_id].poll_addr = reg_addr; + g_gps_each_dsp_reg_read_context[link_id].poll_ongoing = true; + } + + return ret; +} + +void gps_each_dsp_reg_gourp_read_next(enum gps_dl_link_id_enum link_id, bool restart) +{ + unsigned int reg_addr; + enum GDL_RET_STATUS ret; + struct gps_each_dsp_reg_read_context *p_read_context; + int i; + + ASSERT_LINK_ID(link_id, GDL_VOIDF()); + p_read_context = &g_gps_each_dsp_reg_read_context[link_id]; + if (restart) { + p_read_context->poll_index = 0; + p_read_context->round_index = 0; + } else { + p_read_context->poll_index++; + if (p_read_context->poll_index >= p_read_context->poll_list_len) { + p_read_context->round_index++; + if (p_read_context->round_index >= p_read_context->round_max) { + /* all polling end */ + return; + } + /* next round */ + p_read_context->poll_index = 0; + } + } + + i = p_read_context->poll_index; + reg_addr = p_read_context->poll_list_ptr[i]; + ret = gps_each_dsp_reg_read_request(link_id, reg_addr); + GDL_LOGXD(link_id, "i = %d/%d, addr = 0x%04x, status = %s", + i, p_read_context->poll_list_len, reg_addr, gdl_ret_to_name(ret)); +} + +void gps_each_dsp_reg_read_ack( + enum gps_dl_link_id_enum link_id, const struct gps_dl_hal_mcub_info *p_d2a) +{ + ASSERT_LINK_ID(link_id, GDL_VOIDF()); + + GDL_LOGXI(link_id, + "n = %d/%d, addr = 0x%04x, val = 0x%04x/0x%04x, round = %d/%d", + g_gps_each_dsp_reg_read_context[link_id].poll_index + 1, + g_gps_each_dsp_reg_read_context[link_id].poll_list_len, + g_gps_each_dsp_reg_read_context[link_id].poll_addr, + p_d2a->dat0, p_d2a->dat1, + g_gps_each_dsp_reg_read_context[link_id].round_index + 1, + g_gps_each_dsp_reg_read_context[link_id].round_max); + + g_gps_each_dsp_reg_read_context[link_id].poll_ongoing = false; + gps_each_dsp_reg_gourp_read_next(link_id, false); +} + +void gps_each_dsp_reg_gourp_read_start(enum gps_dl_link_id_enum link_id, + bool dbg, unsigned int round_max) +{ + unsigned int a2d_flag; + struct gps_dl_hal_mcub_info d2a; + + ASSERT_LINK_ID(link_id, GDL_VOIDF()); + + if (g_gps_each_dsp_reg_read_context[link_id].poll_ongoing) { + GDL_LOGXW(link_id, "n = %d/%d, addr = 0x%04x, seem busy, check it", + g_gps_each_dsp_reg_read_context[link_id].poll_index + 1, + g_gps_each_dsp_reg_read_context[link_id].poll_list_len, + g_gps_each_dsp_reg_read_context[link_id].poll_addr); + + /* TODO: show hw status */ + a2d_flag = gps_dl_hw_get_mcub_a2d_flag(link_id); + gps_dl_hw_get_mcub_info(link_id, &d2a); + GDL_LOGXW(link_id, "a2d_flag = %d, d2a_flag = %d, d0 = 0x%04x, d1 = 0x%04x", + a2d_flag, d2a.flag, d2a.dat0, d2a.dat1); + + if (a2d_flag & GPS_MCUB_A2DF_MASK_DSP_REG_READ_REQ || + d2a.flag & GPS_MCUB_D2AF_MASK_DSP_REG_READ_READY) { + /* real busy, bypass */ + return; + } + } + + if (dbg) { + g_gps_each_dsp_reg_read_context[link_id].poll_list_ptr = + &c_gps_dsp_reg_dbg_list[link_id][0]; + g_gps_each_dsp_reg_read_context[link_id].poll_list_len = GPS_DSP_REG_DBG_POLL_MAX; + } else { + g_gps_each_dsp_reg_read_context[link_id].poll_list_ptr = + &c_gps_dsp_reg_list[link_id][0]; + g_gps_each_dsp_reg_read_context[link_id].poll_list_len = GPS_DSP_REG_POLL_MAX; + } + g_gps_each_dsp_reg_read_context[link_id].round_max = round_max; + gps_each_dsp_reg_gourp_read_next(link_id, true); +} + +void gps_each_dsp_reg_gourp_read_init(enum gps_dl_link_id_enum link_id) +{ + ASSERT_LINK_ID(link_id, GDL_VOIDF()); + + memset(&g_gps_each_dsp_reg_read_context[link_id], 0, + sizeof(g_gps_each_dsp_reg_read_context[link_id])); +} + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_power_ctrl.c b/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_power_ctrl.c new file mode 100644 index 0000000000000..d2d1d01f0d526 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_power_ctrl.c @@ -0,0 +1,654 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "gps_dl_config.h" +#include "gps_dl_context.h" + +#include "gps_dl_hal.h" +#include "gps_dl_hw_api.h" +#include "gps_dl_hal.h" +#if GPS_DL_MOCK_HAL +#include "gps_mock_hal.h" +#endif +#if GPS_DL_HAS_CONNINFRA_DRV +#if GPS_DL_ON_LINUX +#include "conninfra.h" +#elif GPS_DL_ON_CTP +#include "conninfra_ext.h" +#endif +#endif + +#if GPS_DL_HAS_PLAT_DRV +#include "gps_dl_linux_plat_drv.h" +#endif +#if GPS_DL_ON_CTP +#include "gps_dl_ctp.h" +#endif + +/* TODO: move them into a single structure */ +bool g_gps_common_on; +bool g_gps_dsp_on_array[GPS_DATA_LINK_NUM]; +int g_gps_dsp_off_ret_array[GPS_DATA_LINK_NUM]; +bool g_gps_conninfa_on; +bool g_gps_pta_init_done; +bool g_gps_tia_on; +bool g_gps_dma_irq_en; +bool g_gps_irqs_dis[GPS_DATA_LINK_NUM][GPS_DL_IRQ_TYPE_NUM]; +bool g_gps_need_clk_ext[GPS_DATA_LINK_NUM]; +int g_gps_conn_clock_flag = GPSDL_CLOCK_FLAG_COTMS; +unsigned int g_conn_user; + +bool gps_dl_hal_get_dma_irq_en_flag(void) +{ + bool enable; + + /* spin lock protection between gps_dl_isr_dma_done and gps_kctrld + * both link 0 & 1 spin lock can be used, use 0's. + */ + gps_each_link_spin_lock_take(GPS_DATA_LINK_ID0, GPS_DL_SPINLOCK_FOR_LINK_STATE); + enable = g_gps_dma_irq_en; + gps_each_link_spin_lock_give(GPS_DATA_LINK_ID0, GPS_DL_SPINLOCK_FOR_LINK_STATE); + return enable; +} + +void gps_dl_hal_set_dma_irq_en_flag(bool enable) +{ + gps_each_link_spin_lock_take(GPS_DATA_LINK_ID0, GPS_DL_SPINLOCK_FOR_LINK_STATE); + g_gps_dma_irq_en = enable; + gps_each_link_spin_lock_give(GPS_DATA_LINK_ID0, GPS_DL_SPINLOCK_FOR_LINK_STATE); +} + +bool gps_dl_hal_get_mcub_irq_dis_flag(enum gps_dl_link_id_enum link_id) +{ + return gps_dl_hal_get_irq_dis_flag(link_id, GPS_DL_IRQ_TYPE_MCUB); +} + +void gps_dl_hal_set_mcub_irq_dis_flag(enum gps_dl_link_id_enum link_id, bool disable) +{ + gps_dl_hal_set_irq_dis_flag(link_id, GPS_DL_IRQ_TYPE_MCUB, disable); +} + +bool gps_dl_hal_get_irq_dis_flag(enum gps_dl_link_id_enum link_id, + enum gps_dl_each_link_irq_type type) +{ + bool disable; + + ASSERT_LINK_ID(link_id, false); + ASSERT_IRQ_TYPE(type, false); + gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + disable = g_gps_irqs_dis[link_id][type]; + gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + return disable; +} + +void gps_dl_hal_set_irq_dis_flag(enum gps_dl_link_id_enum link_id, + enum gps_dl_each_link_irq_type type, bool disable) +{ + ASSERT_LINK_ID(link_id, GDL_VOIDF()); + ASSERT_IRQ_TYPE(type, GDL_VOIDF()); + gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + g_gps_irqs_dis[link_id][type] = disable; + gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); +} + +bool gps_dl_hal_get_need_clk_ext_flag(enum gps_dl_link_id_enum link_id) +{ + bool need; + + ASSERT_LINK_ID(link_id, false); + gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + need = g_gps_need_clk_ext[link_id]; + gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + return need; +} + +void gps_dl_hal_set_need_clk_ext_flag(enum gps_dl_link_id_enum link_id, bool need) +{ + ASSERT_LINK_ID(link_id, GDL_VOIDF()); + gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + g_gps_need_clk_ext[link_id] = need; + gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); +} + +int gps_dl_hal_link_power_ctrl(enum gps_dl_link_id_enum link_id, + enum gps_dl_hal_power_ctrl_op_enum op) +{ + bool wakeup_okay; + bool conninfra_okay; + bool keep_conninfra_clk; + int hung_value = 0; + int ret = 0; + + wakeup_okay = gps_dl_hw_gps_force_wakeup_conninfra_top_off(true); + conninfra_okay = gps_dl_conninfra_is_okay_or_handle_it(&hung_value, true); + keep_conninfra_clk = !!( + op == GPS_DL_HAL_POWER_ON || + op == GPS_DL_HAL_LEAVE_DPSLEEP || + op == GPS_DL_HAL_LEAVE_DPSTOP); + GDL_LOGXW_ONF(link_id, + "op = %d, conn_okay = %d/%d/0x%x, gps_common = %d, L1 = %d, L5 = %d, cfg = %d/0x%x", + op, wakeup_okay, conninfra_okay, hung_value, g_gps_common_on, + g_gps_dsp_on_array[GPS_DATA_LINK_ID0], + g_gps_dsp_on_array[GPS_DATA_LINK_ID1], + keep_conninfra_clk, + gps_dl_hw_get_mcub_a2d1_cfg(link_id, gps_dl_is_1byte_mode())); + + if (!wakeup_okay && conninfra_okay) { +#if (GPS_DL_HAS_CONNINFRA_DRV) + int trigger_ret; + trigger_ret = conninfra_trigger_whole_chip_rst(CONNDRV_TYPE_GPS, "GPS conninfra wake fail"); + GDL_LOGXE(link_id, "conninfra wake fail, trigger reset ret = %d", trigger_ret); +#else + GDL_LOGXE(link_id, "conninfra wake fail, trigger reset not support"); +#endif + ret = -1; + } else if (!conninfra_okay && hung_value != 0) { + g_gps_common_on = false; + g_gps_dsp_on_array[GPS_DATA_LINK_ID0] = false; + g_gps_dsp_on_array[GPS_DATA_LINK_ID1] = false; + GDL_LOGXE(link_id, "reset flags due to conninfa not okay"); + ret = -1; + } else { +#if (GPS_DL_HAS_CONNINFRA_DRV) + /* Due to GPS on or GPS exit deep sleep/stop mode may change osc_en from 0 to 1, + * keeping conninfra_bus_clock will make it more safety. + */ + if (keep_conninfra_clk) { + conninfra_bus_clock_ctrl(CONNDRV_TYPE_GPS, + CONNINFRA_BUS_CLOCK_WPLL | CONNINFRA_BUS_CLOCK_BPLL, 1); + } + + ret = gps_dl_hal_link_power_ctrl_inner(link_id, op); + + if (keep_conninfra_clk) { + conninfra_bus_clock_ctrl(CONNDRV_TYPE_GPS, + CONNINFRA_BUS_CLOCK_WPLL | CONNINFRA_BUS_CLOCK_BPLL, 0); + } +#else + ret = gps_dl_hal_link_power_ctrl_inner(link_id, op); +#endif + } + gps_dl_hw_gps_force_wakeup_conninfra_top_off(false); + return ret; +} + +int gps_dl_hal_link_power_ctrl_inner(enum gps_dl_link_id_enum link_id, + enum gps_dl_hal_power_ctrl_op_enum op) +{ + int dsp_ctrl_ret; + + if (1 == op) { + /* GPS common */ + if (!g_gps_common_on) { + if (gps_dl_hw_gps_common_on() != 0) + return -1; + gps_dl_hal_md_blanking_ctrl(true); + g_gps_common_on = true; + } + + if (g_gps_dsp_on_array[link_id]) + return 0; + g_gps_dsp_on_array[link_id] = true; + +#if GPS_DL_HAS_PLAT_DRV + gps_dl_lna_pin_ctrl(link_id, true, false); +#endif +#if GPS_DL_MOCK_HAL + gps_dl_mock_open(link_id); +#endif + + if (GPS_DATA_LINK_ID0 == link_id) + dsp_ctrl_ret = gps_dl_hw_gps_dsp_ctrl(GPS_L1_DSP_ON); + else if (GPS_DATA_LINK_ID1 == link_id) + dsp_ctrl_ret = gps_dl_hw_gps_dsp_ctrl(GPS_L5_DSP_ON); + else + dsp_ctrl_ret = -1; + return dsp_ctrl_ret; + } else if (3 == op || 5 == op) { + gps_dl_lna_pin_ctrl(link_id, true, false); + if (GPS_DATA_LINK_ID0 == link_id) { + if (3 == op) + gps_dl_hw_gps_dsp_ctrl(GPS_L1_DSP_EXIT_DSLEEP); + else if (5 == op) + gps_dl_hw_gps_dsp_ctrl(GPS_L1_DSP_EXIT_DSTOP); + } else if (GPS_DATA_LINK_ID1 == link_id) { + if (3 == op) + gps_dl_hw_gps_dsp_ctrl(GPS_L5_DSP_EXIT_DSLEEP); + else if (5 == op) + gps_dl_hw_gps_dsp_ctrl(GPS_L5_DSP_EXIT_DSTOP); + } + return 0; + } else if (2 == op || 4 == op) { + if (GPS_DATA_LINK_ID0 == link_id) { + if (2 == op) + gps_dl_hw_gps_dsp_ctrl(GPS_L1_DSP_ENTER_DSLEEP); + else if (4 == op) + gps_dl_hw_gps_dsp_ctrl(GPS_L1_DSP_ENTER_DSTOP); + } else if (GPS_DATA_LINK_ID1 == link_id) { + if (2 == op) + gps_dl_hw_gps_dsp_ctrl(GPS_L5_DSP_ENTER_DSLEEP); + else if (4 == op) + gps_dl_hw_gps_dsp_ctrl(GPS_L5_DSP_ENTER_DSTOP); + } + gps_dl_lna_pin_ctrl(link_id, false, false); + return 0; + } else if (0 == op) { + if (g_gps_dsp_on_array[link_id]) { + g_gps_dsp_on_array[link_id] = false; + if (GPS_DATA_LINK_ID0 == link_id) { +#if 0 + if (g_gps_dsp_l5_on && + (0x1 == GDL_HW_GET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_CR_RGU_GPS_L5_ON))) + /* TODO: ASSERT SW status and HW status are same */ +#endif + g_gps_dsp_off_ret_array[link_id] = gps_dl_hw_gps_dsp_ctrl(GPS_L1_DSP_OFF); + } else if (GPS_DATA_LINK_ID1 == link_id) { +#if 0 + if (g_gps_dsp_l1_on && + (0x1 == GDL_HW_GET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_CR_RGU_GPS_L1_ON))) + /* TODO: ASSERT SW status and HW status are same */ +#endif + g_gps_dsp_off_ret_array[link_id] = gps_dl_hw_gps_dsp_ctrl(GPS_L5_DSP_OFF); + } + +#if GPS_DL_HAS_PLAT_DRV + gps_dl_lna_pin_ctrl(link_id, false, false); +#endif +#if GPS_DL_MOCK_HAL + gps_dl_mock_close(link_id); +#endif + } + + if (!g_gps_dsp_on_array[GPS_DATA_LINK_ID0] && !g_gps_dsp_on_array[GPS_DATA_LINK_ID1]) { + if ((g_gps_dsp_off_ret_array[GPS_DATA_LINK_ID0] != 0) || + (g_gps_dsp_off_ret_array[GPS_DATA_LINK_ID1] != 0)) { + GDL_LOGXE(link_id, "l1 ret = %d, l5 ret = %d, force adie off", + g_gps_dsp_off_ret_array[GPS_DATA_LINK_ID0], + g_gps_dsp_off_ret_array[GPS_DATA_LINK_ID1]); + gps_dl_hw_gps_adie_force_off(); + } + + if (g_gps_common_on) { + gps_dl_hal_md_blanking_ctrl(false); + g_gps_common_on = false; + g_gps_dsp_off_ret_array[GPS_DATA_LINK_ID0] = 0; + g_gps_dsp_off_ret_array[GPS_DATA_LINK_ID1] = 0; + if (gps_dl_hw_gps_common_off() != 0) { + /* already trigger connssy reset if arrive here, + * no need to call gps_dl_hw_gps_force_wakeup_conninfra_top_off. + */ + GDL_LOGE("gps_dl_hw_gps_common_off fail"); + return -1; + } + } + } + return 0; + } + return -1; +} + +void gps_dl_hal_link_clear_hw_pwr_stat(enum gps_dl_link_id_enum link_id) +{ + if (GPS_DATA_LINK_ID0 == link_id) + gps_dl_hw_gps_dsp_ctrl(GPS_L1_DSP_CLEAR_PWR_STAT); + else if (GPS_DATA_LINK_ID1 == link_id) + gps_dl_hw_gps_dsp_ctrl(GPS_L5_DSP_CLEAR_PWR_STAT); +} + +int gps_dl_hal_conn_power_ctrl(enum gps_dl_link_id_enum link_id, int op) +{ + bool dma_en_flag = gps_dl_hal_get_dma_irq_en_flag(); + + GDL_LOGXI_ONF(link_id, + "sid = %d, op = %d, conn_user = 0x%x,%d, tia_on = %d, dma_irq_en = %d, mcub_cfg = 0x%x", + gps_each_link_get_session_id(link_id), + op, g_conn_user, g_gps_conninfa_on, g_gps_tia_on, dma_en_flag, + gps_dl_hw_get_mcub_a2d1_cfg(link_id, gps_dl_is_1byte_mode())); + + if (1 == op) { + if (g_conn_user == 0) { + gps_dl_log_info_show(); + if (!gps_dl_hal_conn_infra_driver_on()) + return -1; + + gps_dl_hal_load_clock_flag(); + gps_dl_emi_remap_calc_and_set(); +#if GPS_DL_HAS_PLAT_DRV + gps_dl_wake_lock_hold(true); +#if GPS_DL_USE_TIA + gps_dl_tia_gps_ctrl(true); + g_gps_tia_on = true; +#endif +#endif + gps_dl_irq_unmask_dma_intr(GPS_DL_IRQ_CTRL_FROM_THREAD); + gps_dl_hal_set_dma_irq_en_flag(true); + } + g_conn_user |= (1UL << link_id); + } else if (0 == op) { + g_conn_user &= ~(1UL << link_id); + if (g_conn_user == 0) { + if (dma_en_flag) { + gps_dl_irq_mask_dma_intr(GPS_DL_IRQ_CTRL_FROM_THREAD); + gps_dl_hal_set_dma_irq_en_flag(false); + } +#if GPS_DL_HAS_PLAT_DRV +#if GPS_DL_USE_TIA + if (g_gps_tia_on) { + gps_dl_tia_gps_ctrl(false); + g_gps_tia_on = false; + } +#endif + gps_dl_wake_lock_hold(false); +#endif + gps_dl_hal_conn_infra_driver_off(); + } + } + + return 0; +} + +#define GPS_DL_WAIT_DMA_DONE_TIMEOUT_MS (5) +void gps_dl_hal_link_confirm_dma_stop(enum gps_dl_link_id_enum link_id) +{ + struct gps_each_link *p_link = gps_dl_link_get(link_id); + unsigned int conn_user; + bool tx_working, rx_working; + enum GDL_RET_STATUS stop_tx_status, stop_rx_status; + bool old_dma_en, do_dma_en_ctrl; + + /* make sure dma irq is mask done */ + old_dma_en = gps_dl_hal_get_dma_irq_en_flag(); + do_dma_en_ctrl = false; + if (old_dma_en) { + /* Note1: currently, twice mask should not happen here, + * due to ISR does mask/unmask pair operations, + * except one case, please see Note2 + */ + gps_dl_irq_mask_dma_intr(GPS_DL_IRQ_CTRL_FROM_THREAD); + + /* Note2: double-get to check race condition, if en_flag changed + * it must gps_dl_isr_dma_done change it, need to unmask to make balance + */ + if (!gps_dl_hal_get_dma_irq_en_flag()) + gps_dl_irq_unmask_dma_intr(GPS_DL_IRQ_CTRL_FROM_THREAD); + else { + gps_dl_hal_set_dma_irq_en_flag(false); + do_dma_en_ctrl = true; + } + } + + /* If DMA is working, must stop it when it at proper status -> + * polling until it done or timeout + */ + tx_working = p_link->tx_dma_buf.dma_working_entry.is_valid; + rx_working = p_link->rx_dma_buf.dma_working_entry.is_valid; + stop_tx_status = GDL_OKAY; + stop_rx_status = GDL_OKAY; + + if (tx_working) { + stop_tx_status = gps_dl_hal_a2d_tx_dma_wait_until_done_and_stop_it( + link_id, GPS_DL_WAIT_DMA_DONE_TIMEOUT_MS * 1000, true); + + if (stop_tx_status == GDL_FAIL_TIMEOUT) + gps_dl_hal_a2d_tx_dma_stop(link_id); + } + + if (rx_working && stop_tx_status != GDL_FAIL_CONN_NOT_OKAY) { + stop_rx_status = gps_dl_hal_wait_and_handle_until_usrt_has_nodata_or_rx_dma_done( + link_id, GPS_DL_WAIT_DMA_DONE_TIMEOUT_MS * 1000, false); + + if (stop_rx_status == GDL_FAIL_TIMEOUT) + gps_dl_hal_d2a_rx_dma_stop(link_id); + } + + /* enable the dma irq anyway, leave gps_dl_hal_conn_power_ctrl to disable it */ + if (do_dma_en_ctrl) { + gps_dl_hal_set_dma_irq_en_flag(true); + gps_dl_irq_unmask_dma_intr(GPS_DL_IRQ_CTRL_FROM_THREAD); + } + + /* check the active users */ + conn_user = g_conn_user; + GDL_LOGXW(link_id, "conn_user = 0x%x, old_dma_en = %d/%d, tx = %d/%s, rx = %d/%s", + conn_user, old_dma_en, do_dma_en_ctrl, + tx_working, gdl_ret_to_name(stop_tx_status), + rx_working, gdl_ret_to_name(stop_rx_status)); +} + +bool gps_dl_hal_conn_infra_driver_on(void) +{ +#if GPS_DL_HAS_CONNINFRA_DRV + int ret; + +#if GPS_DL_ON_LINUX + ret = conninfra_pwr_on(CONNDRV_TYPE_GPS); +#elif GPS_DL_ON_CTP + ret = conninfra_power_on(CONNDRV_TYPE_GPS); +#endif + if (ret != 0) { + GDL_LOGE("conninfra_pwr_on fail, ret = %d", ret); + return false; /* not okay */ + } + g_gps_conninfa_on = true; +#endif + return true; /* okay */ +} + +void gps_dl_hal_conn_infra_driver_off(void) +{ +#if GPS_DL_HAS_CONNINFRA_DRV + int ret; + + if (g_gps_conninfa_on) { +#if GPS_DL_ON_LINUX + ret = conninfra_pwr_off(CONNDRV_TYPE_GPS); +#elif GPS_DL_ON_CTP + ret = conninfra_power_off(CONNDRV_TYPE_GPS); +#endif + if (ret != 0) { + GDL_LOGE("conninfra_pwr_off fail, ret = %d", ret); + + /* TODO: trigger whole chip reset? */ + return; + } + + GDL_LOGW("conninfra_pwr_off okay"); + g_gps_conninfa_on = false; + } else + GDL_LOGW("conninfra_pwr_off already done"); +#endif +} + +#if GPS_DL_HAS_PTA +bool gps_dl_hal_md_blanking_init_pta_idc_mode(void) +{ + bool okay, done; + + /* do pta uart init firstly */ + done = gps_dl_hw_is_pta_uart_init_done(); + if (!done) { + okay = gps_dl_hw_init_pta_uart(); + if (!okay) { + GDL_LOGE("gps_dl_hw_init_pta_uart fail"); + return false; + } + } else + GDL_LOGW("pta uart already init done"); + + /* do pta init secondly */ + done = gps_dl_hw_is_pta_init_done(); + if (!done) + gps_dl_hw_init_pta(); + else + GDL_LOGW("pta already init done"); + + gps_dl_hw_claim_pta_used_by_gps(); + + /* use_direct_path = false */ + gps_dl_hw_set_pta_blanking_parameter(false); + return true; +} + +void gps_dl_hal_md_blanking_init_pta_direct_path(void) +{ + /* use_direct_path = true */ + gps_dl_hw_set_pta_blanking_parameter(true); +} + +bool gps_dl_hal_md_blanking_init_pta(void) +{ + bool okay, done; + bool is_mt6885; + bool clk_is_ready; + bool use_direct_path; + + is_mt6885 = gps_dl_hal_conn_infra_ver_is_mt6885(); + use_direct_path = true; + GDL_LOGW("is_mt6885 = %d, use_direct_path = %d", is_mt6885, use_direct_path); + + if (g_gps_pta_init_done) { + GDL_LOGW("already init done, do nothing return"); + return false; + } + + clk_is_ready = true; + if (!gps_dl_hw_is_pta_clk_cfg_ready()) { + GDL_LOGE("gps_dl_hw_is_pta_clk_cfg_ready fail"); + clk_is_ready = false; + } + + okay = gps_dl_hw_take_conn_coex_hw_sema(100); + if (!okay) { + GDL_LOGE("gps_dl_hw_take_conn_coex_hw_sema fail"); + return false; + } + + if (!clk_is_ready) { + gps_dl_hw_set_ptk_clk_cfg(); + if (!gps_dl_hw_is_pta_clk_cfg_ready()) { + GDL_LOGE("gps_dl_hw_is_pta_clk_cfg_ready 2nd fail"); + gps_dl_hw_give_conn_coex_hw_sema(); + return false; + } + } + + if (!use_direct_path) { + /* idc mode */ + okay = gps_dl_hal_md_blanking_init_pta_idc_mode(); + if (!okay) { + gps_dl_hw_give_conn_coex_hw_sema(); + return false; + } + } else { + /* direct path */ + gps_dl_hal_md_blanking_init_pta_direct_path(); + } + + gps_dl_hw_give_conn_coex_hw_sema(); + + /* okay, update flags */ +#if GPS_DL_HAS_PLAT_DRV + gps_dl_update_status_for_md_blanking(true); +#endif + g_gps_pta_init_done = true; + + return true; /* okay */ +} + +void gps_dl_hal_md_blanking_deinit_pta(void) +{ + bool okay; + + /* clear the flags anyway */ +#if GPS_DL_HAS_PLAT_DRV + gps_dl_update_status_for_md_blanking(false); +#endif + if (!g_gps_pta_init_done) { + GDL_LOGW("already deinit done, do nothing return"); + return; + } + g_gps_pta_init_done = false; + + /* Currently, deinit is no need. + * Just keep the bellow code for future usage. + */ + okay = gps_dl_hw_take_conn_coex_hw_sema(0); /* 0 stands for polling just one time */ + if (!okay) { + GDL_LOGE("gps_dl_hw_take_conn_coex_hw_sema fail"); + return; + } + + gps_dl_hw_disclaim_pta_used_by_gps(); + + if (gps_dl_hw_is_pta_init_done()) + gps_dl_hw_deinit_pta(); + else + GDL_LOGW("pta already deinit done"); + + if (gps_dl_hw_is_pta_uart_init_done()) + gps_dl_hw_deinit_pta_uart(); + else + GDL_LOGW("pta uart already deinit done"); + + gps_dl_hw_give_conn_coex_hw_sema(); +} +#endif /* GPS_DL_HAS_PTA */ + +void gps_dl_hal_md_blanking_ctrl(bool on) +{ +#if GPS_DL_HAS_PTA + if (on) + gps_dl_hal_md_blanking_init_pta(); + else + gps_dl_hal_md_blanking_deinit_pta(); +#else + /* For directly connection case, there is no PTA, just update status for md. */ +#if GPS_DL_HAS_PLAT_DRV + gps_dl_update_status_for_md_blanking(on); +#endif +#endif +} + +int gps_dl_hal_get_clock_flag(void) +{ + return g_gps_conn_clock_flag; +} + +void gps_dl_hal_load_clock_flag(void) +{ + int gps_clock_flag; +#if GPS_DL_HAS_CONNINFRA_DRV + enum connsys_clock_schematic clock_sch; + + clock_sch = (enum connsys_clock_schematic)conninfra_get_clock_schematic(); + switch (clock_sch) { + case CONNSYS_CLOCK_SCHEMATIC_26M_COTMS: + gps_clock_flag = GPSDL_CLOCK_FLAG_COTMS; + break; + case CONNSYS_CLOCK_SCHEMATIC_52M_COTMS: + gps_clock_flag = GPSDL_CLOCK_FLAG_52M_COTMS; + break; + case CONNSYS_CLOCK_SCHEMATIC_26M_EXTCXO: + gps_clock_flag = GPSDL_CLOCK_FLAG_TCXO; + break; + default: + gps_clock_flag = GPSDL_CLOCK_FLAG_COTMS; + break; + } + GDL_LOGW("clk: sch from conninfra = %d, mapping to flag = 0x%x", clock_sch, gps_clock_flag); +#else + gps_clock_flag = GPSDL_CLOCK_FLAG_COTMS; + GDL_LOGW("clk: no conninfra drv, default flag = 0x%x", gps_clock_flag); +#endif + g_gps_conn_clock_flag = gps_clock_flag; +} + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_zbus.c b/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_zbus.c new file mode 100644 index 0000000000000..3187861b569fe --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dl_zbus.c @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dsp_fsm.c b/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dsp_fsm.c new file mode 100644 index 0000000000000..70df18e5ba5a1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hal/gps_dsp_fsm.c @@ -0,0 +1,289 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/* #include "autoconf.h" */ + +#if 1 + +/* #ifdef CONFIG_GPS_SUPPORT */ +#if 0 +#include "gps_reroute.h" +#include "gps_reroute_emi.h" +#include "emi_symbol_hook.h" +#include "gps_util.h" +#include "wmt_task.h" +#include "cos_api.h" +#endif + +#include "gps_dsp_fsm.h" +#include "gps_dl_log.h" +#include "gps_each_link.h" +#include "gps_dl_name_list.h" +#include "gps_dl_hal.h" +#include "gps_dl_hw_api.h" + + +/* extern kal_uint32 g_mcu_real_clock_rate; */ +/* extern kal_uint32 g_max_mcu_clock_rate; */ +/* #define GPS_REQ_CLOCK_FREQ_MHZ_MVCD (g_max_mcu_clock_rate/ 1000000UL) */ +/* #define GPS_REQ_CLOCK_FREQ_MHZ_NORMAL (1) 1MHz */ + +enum gps_dsp_state_t g_gps_dsp_state[GPS_DATA_LINK_NUM]; + + +enum gps_dsp_state_t gps_dsp_state_get(enum gps_dl_link_id_enum link_id) +{ + return g_gps_dsp_state[link_id]; +} + +bool gps_dsp_state_is(enum gps_dsp_state_t state, enum gps_dl_link_id_enum link_id) +{ + ASSERT_LINK_ID(link_id, false); + return !!(g_gps_dsp_state[link_id] == state); +} + +void gps_dsp_state_change_to(enum gps_dsp_state_t next_state, enum gps_dl_link_id_enum link_id) +{ + ASSERT_LINK_ID(link_id, GDL_VOIDF()); + + if (next_state == GPS_DSP_ST_TURNED_ON) { + /* gps_clock_switch (GPS_REQ_CLOCK_FREQ_MHZ_MVCD); */ + /* gps_ctrl_timer_start(GPS_DSP_RESET_TIMEOUT_MS); */ + } + + if (next_state == GPS_DSP_ST_RESET_DONE) { + /* Note: here is just a candidate caller, if no problem, we call it */ + /* in GPS_Reroute_Ext_Power_Ctrl_Inner */ + /* GPS_Reroute_Set_DSP_Config_By_MCUB(); */ + + /* gps_clock_switch (GPS_REQ_CLOCK_FREQ_MHZ_MVCD); */ + /* gps_ctrl_timer_start(GPS_DSP_MVCD_TIMEOUT_MS); */ +#if 0 + if (!g_gps_bypass_dsp_turned_on_state) { + /* ready to do reroute */ + gps_data_reroute_set_pending(false); + GPS_Reroute_Buffer_to_GPS_port_real(); + } +#endif + gps_dl_link_set_ready_to_write(link_id, true); + gps_dl_link_start_tx_dma_if_has_data(link_id); + } + + if (next_state == GPS_DSP_ST_WAKEN_UP) { + /* gps_ctrl_timer_start(GPS_DSP_WAKEUP_TIMEOUT_MS); + */ + } + + if (next_state == GPS_DSP_ST_WORKING) { + /* gps_clock_switch (GPS_REQ_CLOCK_FREQ_MHZ_NORMAL); */ + gps_dl_hal_link_clear_hw_pwr_stat(link_id); + gps_dl_hal_set_need_clk_ext_flag(link_id, false); + } + + if (next_state == GPS_DSP_ST_OFF) { + /* gps_clock_switch (0); - already done before gps_dsp_fsm */ + /* gps_ctrl_timer_stop(); */ + } + + g_gps_dsp_state[link_id] = next_state; +} + +void gps_dsp_fsm(enum gps_dsp_event_t evt, enum gps_dl_link_id_enum link_id) +{ +#if 1 + bool abnormal_flag = true; + enum gps_dsp_state_t last_state = gps_dsp_state_get(link_id); + + if (GPS_DSP_EVT_FUNC_ON != evt && GPS_DSP_ST_OFF == last_state) { + /* bypass all event except gps func on when gps is off */ + abnormal_flag = true; + goto _last_check; + } + + if (GPS_DSP_EVT_FUNC_OFF == evt) { +#if 0 + if (GPS_DSP_ST_HW_SLEEP_MODE == last_state || + GPS_DSP_ST_HW_STOP_MODE == last_state) { + /* Special handing rather than GPS_Reroute_Ext_Power_Ctrl_Inner */ + if (GPS_DSP_ST_HW_SLEEP_MODE == last_state) + ; /* wmt_task_subsystem_power_ctrl_handler(COS_GPS_CTRL, 3); */ + else if (GPS_DSP_ST_HW_STOP_MODE == last_state) + ; /* wmt_task_subsystem_power_ctrl_handler(COS_GPS_CTRL, 5); */ + + /* wmt_task_subsystem_power_ctrl_handler(COS_GPS_CTRL, 0); */ + /* GPS_Reroute_Buffer_to_GPS_port_drop(); */ + /* GPS_Reroute_Cos_Sleep_Enable(); */ + } +#endif + if (GPS_DSP_ST_RESET_DONE == last_state || + GPS_DSP_ST_HW_STOP_MODE == last_state) + abnormal_flag = false; + gps_dsp_state_change_to(GPS_DSP_ST_OFF, link_id); + goto _last_check; + } + + if (GPS_DSP_EVT_CTRL_TIMER_EXPIRE == evt) { + /* if (!gps_ctrl_timer_check_valid()) */ + { + abnormal_flag = true; + goto _last_check; + } + + /* TODO: unmask it when timer ready */ +#if 0 + switch (last_state) { + case GPS_DSP_ST_TURNED_ON: + /* GPS_DSP_EVT_RESET_DONE timeout (180ms) */ + /* GPS_Reroute_Buffer_to_GPS_port_drop(); */ + /* gps_dsp_state_change_to(GPS_DSP_ST_RESET_DONE, link_id); */ + /* ERROR timeout - each DSP restart */ + + /* TODO: gps_each_link_reset(link_id); */ + break; + case GPS_DSP_ST_RESET_DONE: + /* GPS_DSP_EVT_RAM_CODE_READY timeout (1s) */ + gps_dsp_state_change_to(GPS_DSP_ST_WORKING, link_id); + break; +#if 0 + case GPS_DSP_ST_HW_SLEEP_MODE: + GPS_Reroute_Ext_Power_Ctrl_Inner(3); + /* cos_resource_enable(COS_SLEEP_MODE, g_gps_sleep_handle); */ + gps_dsp_state_change_to(GPS_DSP_ST_WAKEN_UP, link_id); + break; + case GPS_DSP_ST_WAKEN_UP: + gps_dsp_state_change_to(GPS_DSP_ST_WORKING, link_id); + break; +#endif + default: + abnormal_flag = true; + } + goto _last_check; +#endif + } + + switch (last_state) { + case GPS_DSP_ST_OFF: + if (GPS_DSP_EVT_FUNC_ON == evt) { +#if 0 + if (g_gps_bypass_dsp_turned_on_state) + gps_dsp_state_change_to(GPS_DSP_ST_RESET_DONE, link_id); + else + gps_dsp_state_change_to(GPS_DSP_ST_TURNED_ON, link_id); +#endif + gps_dsp_state_change_to(GPS_DSP_ST_TURNED_ON, link_id); + abnormal_flag = false; + } + break; + + case GPS_DSP_ST_TURNED_ON: + if (GPS_DSP_EVT_RESET_DONE == evt) { + gps_dsp_state_change_to(GPS_DSP_ST_RESET_DONE, link_id); + abnormal_flag = false; + } else + abnormal_flag = true; + break; + + case GPS_DSP_ST_RESET_DONE: + if (GPS_DSP_EVT_RAM_CODE_READY == evt) { + /* TODO */ + /* gps_ctrl_timer_stop(); */ + gps_dsp_state_change_to(GPS_DSP_ST_WORKING, link_id); + abnormal_flag = false; + } else if (GPS_DSP_EVT_HW_STOP_REQ == evt) { + /* already done outside + * GPS_Reroute_Ext_Power_Ctrl_Inner(4); + */ + gps_dsp_state_change_to(GPS_DSP_ST_HW_STOP_MODE, link_id); + abnormal_flag = false; + } else + abnormal_flag = true; + break; + + case GPS_DSP_ST_WORKING: + if (GPS_DSP_EVT_RESET_DONE == evt) { + /* PMTK101 like restart or to be powered off */ + gps_dsp_state_change_to(GPS_DSP_ST_RESET_DONE, link_id); + abnormal_flag = false; + } else if (GPS_DSP_EVT_HW_STOP_REQ == evt) { + /* already done outside + * GPS_Reroute_Ext_Power_Ctrl_Inner(4); + */ + gps_dsp_state_change_to(GPS_DSP_ST_HW_STOP_MODE, link_id); + abnormal_flag = true; /* just show warning */ + } else + abnormal_flag = true; +#if 0 + else if (GPS_DSP_EVT_HW_SLEEP_REQ == evt) { + GPS_Reroute_Ext_Power_Ctrl_Inner(2); + /* to_do_timer check!!! - dynamic change timer */ + /* gps_ctrl_timer_start(800); */ + gps_dsp_state_change_to(GPS_DSP_ST_HW_SLEEP_MODE, link_id); + } else + abnormal_flag = true; +#endif + break; + + case GPS_DSP_ST_HW_SLEEP_MODE: +#if 0 + if (GPS_DSP_EVT_HW_SLEEP_EXIT == evt) { + /* from host - only for test */ + GPS_Reroute_Ext_Power_Ctrl_Inner(3); + gps_dsp_state_change_to(GPS_DSP_ST_WAKEN_UP, link_id); + } else + abnormal_flag = true; +#endif + abnormal_flag = true; + break; + + case GPS_DSP_ST_HW_STOP_MODE: + if (GPS_DSP_EVT_HW_STOP_EXIT == evt) { + /* GPS_Reroute_Ext_Power_Ctrl_Inner(5); */ + gps_dsp_state_change_to(GPS_DSP_ST_WAKEN_UP, link_id); + abnormal_flag = false; + } else if (GPS_DSP_EVT_RESET_DONE == evt) { + gps_dsp_state_change_to(GPS_DSP_ST_RESET_DONE, link_id); + abnormal_flag = false; + } else + abnormal_flag = true; + break; + + case GPS_DSP_ST_WAKEN_UP: + if (GPS_DSP_EVT_RAM_CODE_READY == evt) { + /* gps_ctrl_timer_stop(); */ + gps_dl_link_set_ready_to_write(link_id, true); + gps_dl_link_start_tx_dma_if_has_data(link_id); + gps_dsp_state_change_to(GPS_DSP_ST_WORKING, link_id); + abnormal_flag = false; + } else + abnormal_flag = true; + break; + + default: + abnormal_flag = true; + } + +_last_check: + if (abnormal_flag) { + GDL_LOGXW_STA(link_id, "gps_dsp_fsm: old_st=%s, evt=%s, new_st=%s, is_err=%d", + gps_dl_dsp_state_name(last_state), gps_dl_dsp_event_name(evt), + gps_dl_dsp_state_name(gps_dsp_state_get(link_id)), abnormal_flag); + } else { + GDL_LOGXI_STA(link_id, "gps_dsp_fsm: old_st=%s, evt=%s, new_st=%s", + gps_dl_dsp_state_name(last_state), gps_dl_dsp_event_name(evt), + gps_dl_dsp_state_name(gps_dsp_state_get(link_id))); + } + return; +#endif +} + +#endif /* CONFIG_GPS_SUPPORT */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/gps_dl_hal.h b/drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/gps_dl_hal.h new file mode 100644 index 0000000000000..d1c5f9308c5bb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/gps_dl_hal.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _GPS_DL_HAL_H +#define _GPS_DL_HAL_H + +#include "gps_dl_config.h" +#include "gps_dl_dma_buf.h" +#include "gps_dl_hal_type.h" +#include "gps_dl_isr.h" + +/* for gps_each_device.c */ + + +/* for gps_each_link.c */ +enum gps_dl_hal_power_ctrl_op_enum { + GPS_DL_HAL_POWER_OFF = 0, + GPS_DL_HAL_POWER_ON = 1, + GPS_DL_HAL_ENTER_DPSLEEP = 2, + GPS_DL_HAL_LEAVE_DPSLEEP = 3, + GPS_DL_HAL_ENTER_DPSTOP = 4, + GPS_DL_HAL_LEAVE_DPSTOP = 5, + GPS_DL_HAL_POWER_OP_MAX +}; + +bool gps_dl_hal_conn_infra_driver_on(void); +void gps_dl_hal_conn_infra_driver_off(void); +void gps_dl_hal_link_confirm_dma_stop(enum gps_dl_link_id_enum link_id); +int gps_dl_hal_conn_power_ctrl(enum gps_dl_link_id_enum link_id, int op); +int gps_dl_hal_link_power_ctrl(enum gps_dl_link_id_enum link_id, + enum gps_dl_hal_power_ctrl_op_enum op); +int gps_dl_hal_link_power_ctrl_inner(enum gps_dl_link_id_enum link_id, + enum gps_dl_hal_power_ctrl_op_enum op); +void gps_dl_hal_link_clear_hw_pwr_stat(enum gps_dl_link_id_enum link_id); +#if GPS_DL_ON_LINUX +bool gps_dl_hal_md_blanking_init_pta(void); +void gps_dl_hal_md_blanking_deinit_pta(void); +#endif +void gps_dl_hal_md_blanking_ctrl(bool on); +void gps_dl_hal_a2d_tx_dma_start(enum gps_dl_link_id_enum link_id, + struct gdl_dma_buf_entry *p_entry); +void gps_dl_hal_d2a_rx_dma_start(enum gps_dl_link_id_enum link_id, + struct gdl_dma_buf_entry *p_entry); + +void gps_dl_hal_a2d_tx_dma_stop(enum gps_dl_link_id_enum link_id); +void gps_dl_hal_d2a_rx_dma_stop(enum gps_dl_link_id_enum link_id); + +unsigned int gps_dl_hal_d2a_rx_dma_get_rx_len(enum gps_dl_link_id_enum link_id); +enum GDL_RET_STATUS gps_dl_hal_d2a_rx_dma_get_write_index( + enum gps_dl_link_id_enum link_id, unsigned int *p_write_index); + +enum GDL_RET_STATUS gps_dl_hal_a2d_tx_dma_wait_until_done_and_stop_it( + enum gps_dl_link_id_enum link_id, int timeout_usec, bool return_if_not_start); +enum GDL_RET_STATUS gps_dl_hal_d2a_rx_dma_wait_until_done( + enum gps_dl_link_id_enum link_id, int timeout_usec); +enum GDL_RET_STATUS gps_dl_hal_wait_and_handle_until_usrt_has_data( + enum gps_dl_link_id_enum link_id, int timeout_usec); +enum GDL_RET_STATUS gps_dl_hal_wait_and_handle_until_usrt_has_nodata_or_rx_dma_done( + enum gps_dl_link_id_enum link_id, int timeout_usec, bool to_handle); + +enum GDL_RET_STATUS gps_dl_hal_poll_event( + unsigned int L1_evt_in, unsigned int L5_evt_in, + unsigned int *pL1_evt_out, unsigned int *pL5_evt_out, unsigned int timeout_usec); + +int gps_dl_hal_usrt_direct_write(enum gps_dl_link_id_enum link_id, + unsigned char *buf, unsigned int len); +int gps_dl_hal_usrt_direct_read(enum gps_dl_link_id_enum link_id, + unsigned char *buf, unsigned int len); + +void gps_each_dsp_reg_read_ack( + enum gps_dl_link_id_enum link_id, const struct gps_dl_hal_mcub_info *p_d2a); +void gps_each_dsp_reg_gourp_read_init(enum gps_dl_link_id_enum link_id); +void gps_each_dsp_reg_gourp_read_start(enum gps_dl_link_id_enum link_id, + bool dbg, unsigned int round_max); + +enum GDL_RET_STATUS gps_each_dsp_reg_read_request( + enum gps_dl_link_id_enum link_id, unsigned int reg_addr); +void gps_each_dsp_reg_gourp_read_next(enum gps_dl_link_id_enum link_id, bool restart); + +bool gps_dl_hal_get_dma_irq_en_flag(void); +void gps_dl_hal_set_dma_irq_en_flag(bool enable); +bool gps_dl_hal_get_mcub_irq_dis_flag(enum gps_dl_link_id_enum link_id); +void gps_dl_hal_set_mcub_irq_dis_flag(enum gps_dl_link_id_enum link_id, bool disable); +bool gps_dl_hal_get_irq_dis_flag(enum gps_dl_link_id_enum link_id, + enum gps_dl_each_link_irq_type type); +void gps_dl_hal_set_irq_dis_flag(enum gps_dl_link_id_enum link_id, + enum gps_dl_each_link_irq_type type, bool disable); +bool gps_dl_hal_get_need_clk_ext_flag(enum gps_dl_link_id_enum link_id); +void gps_dl_hal_set_need_clk_ext_flag(enum gps_dl_link_id_enum link_id, bool need); + +#define GPSDL_CLOCK_FLAG_TCXO (0x00) +#define GPSDL_CLOCK_FLAG_COTMS (0x21) +#define GPSDL_CLOCK_FLAG_52M_COTMS (0x51) +int gps_dl_hal_get_clock_flag(void); +void gps_dl_hal_load_clock_flag(void); + +void gps_dl_hal_set_conn_infra_ver(unsigned int ver); +unsigned int gps_dl_hal_get_conn_infra_ver(void); +bool gps_dl_hal_conn_infra_ver_is_mt6885(void); + +#endif /* _GPS_DL_HAL_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/gps_dl_hal_api.h b/drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/gps_dl_hal_api.h new file mode 100644 index 0000000000000..bc55ec04ebc9d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/gps_dl_hal_api.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _GPS_DL_HAL_API_H +#define _GPS_DL_HAL_API_H + +#include "gps_dl_config.h" +#include "gps_dl_dma_buf.h" + +/* provide function declaration for gps_dl_hal.c */ +/* the functions are implemented in hal/gps_dl*.c */ +enum gps_dl_hal_event_id { + GPS_DL_HAL_EVT_A2D_TX_DMA_DONE, + GPS_DL_HAL_EVT_D2A_RX_HAS_DATA, + GPS_DL_HAL_EVT_D2A_RX_DMA_DONE, + GPS_DL_HAL_EVT_D2A_RX_HAS_NODATA, + GPS_DL_HAL_EVT_MCUB_HAS_IRQ, + GPS_DL_HAL_EVT_DSP_ROM_START, + GPS_DL_HAL_EVT_DSP_RAM_START, + GPS_DL_HAL_EVT_A2D_TX_DMA_TIMEOUT, /* exception */ + GPS_DL_HAL_EVT_A2D_RX_DMA_TIMEOUT, + GPS_DL_HAL_EVT_DMA_ISR_PENDING, + GPD_DL_HAL_EVT_NUM +}; + +enum gps_dl_hal_poll_id { + GPS_DL_POLL_TX_DMA_DONE, + GPS_DL_POLL_RX_DMA_DONE, + GPS_DL_POLL_USRT_HAS_DATA, + GPS_DL_POLL_USRT_HAS_NODATA, + GPS_DL_POLL_MCUB_D2A_FLAG_SET, + GPS_DL_POLL_MAX +}; + +void gps_dl_hal_event_send(enum gps_dl_hal_event_id evt, + enum gps_dl_link_id_enum link_id); + +void gps_dl_hal_event_proc(enum gps_dl_hal_event_id evt, + enum gps_dl_link_id_enum link_id, int sid_on_evt); + +/* DMA operations */ +enum gps_dl_hal_dma_ch_index { + GPS_DL_DMA_LINK0_A2D, + GPS_DL_DMA_LINK0_D2A, + GPS_DL_DMA_LINK1_A2D, + GPS_DL_DMA_LINK1_D2A, + GPS_DL_DMA_CH_NUM, +}; + +enum gps_dl_hal_emi_user { + GPS_DL_EMI_USER_TX_DMA0 = GPS_DL_DMA_LINK0_A2D, + GPS_DL_EMI_USER_RX_DMA0 = GPS_DL_DMA_LINK0_D2A, + GPS_DL_EMI_USER_TX_DMA1 = GPS_DL_DMA_LINK1_A2D, + GPS_DL_EMI_USER_RX_DMA1 = GPS_DL_DMA_LINK1_D2A, + GPS_DL_EMI_USER_ICAP, /* reserved, driver not use it */ + GPS_DL_EMI_USER_GPS_ON, /* may remove this user later */ + GPS_DL_EMI_USER_NUM +}; + +#define DMA_CH_TO_LINK_ID(ch) (\ + ((ch) == GPS_DL_DMA_LINK0_A2D || (ch) == GPS_DL_DMA_LINK0_D2A) ? GPS_DATA_LINK_ID0 : (\ + ((ch) == GPS_DL_DMA_LINK1_A2D || (ch) == GPS_DL_DMA_LINK1_D2A) ? GPS_DATA_LINK_ID1 : (\ + 0xFF))) + +#define DMA_CH_IS_TX(ch) \ + ((ch) == GPS_DL_DMA_LINK0_A2D || (ch) == GPS_DL_DMA_LINK1_A2D) + +#define DMA_CH_IS_RX(ch) \ + ((ch) == GPS_DL_DMA_LINK0_D2A || (ch) == GPS_DL_DMA_LINK1_D2A) + +#define GET_TX_DMA_CH_OF(link_id) \ + CHOOSE_BY_LINK_ID(link_id, GPS_DL_DMA_LINK0_A2D, GPS_DL_DMA_LINK1_A2D, 0xFF) + +#define GET_RX_DMA_CH_OF(link_id) \ + CHOOSE_BY_LINK_ID(link_id, GPS_DL_DMA_LINK0_D2A, GPS_DL_DMA_LINK1_D2A, 0xFF) + +void gps_dl_hal_dma_init(void); + +void gps_dl_hal_dma_config(enum gps_dl_hal_dma_ch_index ch); +void gps_dl_hal_dma_start(enum gps_dl_hal_dma_ch_index ch, + struct gdl_dma_buf_entry *p_entry); +void gps_dl_hal_dma_stop(enum gps_dl_hal_dma_ch_index ch); + +void gps_dl_emi_remap_calc_and_set(void); +enum GDL_RET_STATUS gps_dl_emi_remap_phy_to_bus_addr(unsigned int phy_addr, unsigned int *bus_addr); + +void gps_dl_hal_emi_usage_init(void); +void gps_dl_hal_emi_usage_deinit(void); +void gps_dl_hal_emi_usage_claim(enum gps_dl_hal_emi_user user, bool use_emi); +void gps_dl_hal_a2d_tx_dma_claim_emi_usage(enum gps_dl_link_id_enum link_id, bool use_emi); +void gps_dl_hal_d2a_rx_dma_claim_emi_usage(enum gps_dl_link_id_enum link_id, bool use_emi); + + +#endif /* _GPS_DL_HAL_API_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/gps_dl_hal_type.h b/drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/gps_dl_hal_type.h new file mode 100644 index 0000000000000..20a4b3eca05fb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/gps_dl_hal_type.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _GPS_DL_HAL_TYPE_H +#define _GPS_DL_HAL_TYPE_H + +struct gps_dl_hal_mcub_info { + unsigned int flag; + unsigned int dat0; + unsigned int dat1; +}; + +#endif /* _GPS_DL_HAL_TYPE_H */ diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/gps_dl_hal_util.h b/drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/gps_dl_hal_util.h new file mode 100644 index 0000000000000..f32ef2c7b0175 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/gps_dl_hal_util.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _GPS_DL_HAL_UTIL_H +#define _GPS_DL_HAL_UTIL_H + + + +/* bool gps_dl_hal_get_dma_int_status(enum gps_dl_hal_dma_ch_index channel); */ + + +enum GPS_DL_HWCR_OWNER_ENUM { + GPS_DL_HWCR_OWNER_POS, /* for power on sequence */ + GPS_DL_HWCR_OWNER_DMA, /* for dma control */ + GPS_DL_HWCR_OWNER_NUM +}; + + +/* Must claim the owner before access hardware control registers */ +enum GDL_RET_STATUS gps_dl_hwcr_access_claim(enum GPS_DL_HWCR_OWNER_ENUM owner); +enum GDL_RET_STATUS gps_dl_hwcr_access_disclaim(enum GPS_DL_HWCR_OWNER_ENUM owner); + + +#endif /* _GPS_DL_HAL_UTIL_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/gps_dl_isr.h b/drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/gps_dl_isr.h new file mode 100644 index 0000000000000..a478d0e132bc1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/gps_dl_isr.h @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _GPS_DL_ISR_H +#define _GPS_DL_ISR_H + +#include "gps_dl_config.h" +#include "gps_each_link.h" + +enum gps_dl_irq_index_enum { + GPS_DL_IRQ_LINK0_DATA, + GPS_DL_IRQ_LINK0_NODATA, + GPS_DL_IRQ_LINK0_MCUB, + GPS_DL_IRQ_LINK1_DATA, + GPS_DL_IRQ_LINK1_NODATA, + GPS_DL_IRQ_LINK1_MCUB, + GPS_DL_IRQ_DMA, + GPS_DL_IRQ_NUM, +}; + +enum gps_dl_irq_trigger_type { + GPS_DL_IRQ_TRIG_LEVEL_HIGH, + GPS_DL_IRQ_TRIG_EDGE_RISING, + GPS_DL_IRQ_TRIG_NUM, +}; + +struct gps_each_irq_cfg { + int sens_type; + enum gps_dl_irq_index_enum index; + void *isr; + const char *name; + enum gps_dl_irq_trigger_type trig_type; +}; + +struct gps_each_irq { + struct gps_each_irq_cfg cfg; + bool register_done; + int reg_irq_id; +}; + +#define IRQ_IDX_IS_VALID(irq_idx) \ + (((irq_idx) >= 0) && ((irq_idx) < GPS_DL_IRQ_NUM)) + +#define ASSERT_IRQ_IDX(irq_idx, ret) \ + GDL_ASSERT(IRQ_IDX_IS_VALID(irq_idx), ret, "invalid irq index: %d", irq_idx) + +struct gps_each_irq *gps_dl_irq_get(enum gps_dl_irq_index_enum irq_idx); + + +enum gps_dl_each_link_irq_type { + GPS_DL_IRQ_TYPE_HAS_DATA, + GPS_DL_IRQ_TYPE_HAS_NODATA, + GPS_DL_IRQ_TYPE_MCUB, + GPS_DL_IRQ_TYPE_NUM, +}; +#define IRQ_TYPE_IS_VALID(irq_type) \ + (((irq_type) >= 0) && ((irq_type) < GPS_DL_IRQ_TYPE_NUM)) + +#define ASSERT_IRQ_TYPE(irq_type, ret) \ + GDL_ASSERT(IRQ_TYPE_IS_VALID(irq_type), ret, "invalid irq type: %d", irq_type) + + +enum gps_dl_irq_ctrl_from { + GPS_DL_IRQ_CTRL_FROM_ISR, + GPS_DL_IRQ_CTRL_FROM_THREAD, + GPS_DL_IRQ_CTRL_FROM_MAX, +}; + +#if GPS_DL_USE_THREADED_IRQ +/* + * #define GPS_DL_IRQ_CTRL_POSSIBLE_FROM_ISR GPS_DL_IRQ_CTRL_FROM_THREAD + * threaded_irq still can't call disable_irq + */ +#define GPS_DL_IRQ_CTRL_POSSIBLE_FROM_ISR GPS_DL_IRQ_CTRL_FROM_ISR +#else +#define GPS_DL_IRQ_CTRL_POSSIBLE_FROM_ISR GPS_DL_IRQ_CTRL_FROM_ISR +#endif + +#if GPS_DL_HAS_CTRLD +#define GPS_DL_IRQ_CTRL_FROM_HAL GPS_DL_IRQ_CTRL_FROM_THREAD +#else +#define GPS_DL_IRQ_CTRL_FROM_HAL GPS_DL_IRQ_CTRL_POSSIBLE_FROM_ISR +#endif + + +void gps_dl_irq_mask(int irq_id, enum gps_dl_irq_ctrl_from from); +void gps_dl_irq_unmask(int irq_id, enum gps_dl_irq_ctrl_from from); + +#if GPS_DL_ON_LINUX +void gps_dl_irq_set_id(enum gps_dl_irq_index_enum irq_idx, int irq_id); +#endif + +int gps_dl_irq_index_to_id(enum gps_dl_irq_index_enum irq_idx); +int gps_dl_irq_type_to_id(enum gps_dl_link_id_enum link_id, + enum gps_dl_each_link_irq_type irq_type); +int gps_dl_irq_type_to_hwirq(enum gps_dl_link_id_enum link_id, + enum gps_dl_each_link_irq_type irq_type); + +void gps_dl_irq_each_link_control(enum gps_dl_link_id_enum link_id, + enum gps_dl_each_link_irq_type irq_type, bool mask_it, enum gps_dl_irq_ctrl_from from); +void gps_dl_irq_each_link_mask(enum gps_dl_link_id_enum link_id, + enum gps_dl_each_link_irq_type irq_type, enum gps_dl_irq_ctrl_from from); +void gps_dl_irq_each_link_unmask(enum gps_dl_link_id_enum link_id, + enum gps_dl_each_link_irq_type irq_type, enum gps_dl_irq_ctrl_from from); + +int gps_dl_irq_init(void); +int gps_dl_irq_deinit(void); +void gps_dl_irq_mask_dma_intr(enum gps_dl_irq_ctrl_from from); +void gps_dl_irq_unmask_dma_intr(enum gps_dl_irq_ctrl_from from); + +void gps_dl_isr_usrt_has_data(enum gps_dl_link_id_enum link_id); +void gps_dl_isr_usrt_has_nodata(enum gps_dl_link_id_enum link_id); +void gps_dl_isr_a2d_tx_dma_done(enum gps_dl_link_id_enum link_id); +void gps_dl_isr_d2a_rx_dma_done(enum gps_dl_link_id_enum link_id); +void gps_dl_isr_mcub(enum gps_dl_link_id_enum link_id); +bool gps_dl_hal_mcub_flag_handler(enum gps_dl_link_id_enum link_id); + +#if GPS_DL_ON_CTP +void gps_dl_isr_dl0_has_data(void); +void gps_dl_isr_dl0_has_nodata(void); +void gps_dl_isr_dl0_mcub(void); +void gps_dl_isr_dl1_has_data(void); +void gps_dl_isr_dl1_has_nodata(void); +void gps_dl_isr_dl1_mcub(void); +#endif + +void gps_dl_isr_dma_done(void); + +#endif /* _GPS_DL_ISR_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/gps_dsp_fsm.h b/drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/gps_dsp_fsm.h new file mode 100644 index 0000000000000..f8ed928d69588 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/gps_dsp_fsm.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _GPS_DSP_FSM_H_ +#define _GPS_DSP_FSM_H_ + +#include "gps_dl_config.h" + +enum gps_dsp_state_t { + /* GPS and DSP are function off */ + GPS_DSP_ST_OFF, /* 0 */ + + /* MCU turned DSP on and just released the reset flag */ + GPS_DSP_ST_TURNED_ON, /* 1 */ + + /* DSP notified MCU about it's reset flow done */ + /* It will also stand for DSP finished Mbist flow if DSP has this flow */ + /* MCU should suspend the data reoute until change to this state */ + /* When change to this state, MVCD flow should start immediately */ + GPS_DSP_ST_RESET_DONE, /* 2 */ + + /* DSP raw code download finish/DSP wakeup and raw code start working */ + GPS_DSP_ST_WORKING, /* 3 */ + + /* DSP in HW sleep mode for GLP duty cycle mode */ + GPS_DSP_ST_HW_SLEEP_MODE, /* 4 */ + + /* DSP in HW stop mode. MVCD flow can be skipped after wakeup */ + GPS_DSP_ST_HW_STOP_MODE, /* 5 */ + + /* Wakeup from sleep/stop mode */ + /* No MVCD procedure, should directly goto GPS_DSP_ST_WORKING */ + GPS_DSP_ST_WAKEN_UP, /* 6 */ + + GPS_DSP_ST_MAX +}; + + +/* DSP to MCU MCUB flag bit usage definition */ +#define GPS_MCUB_D2AF_MASK_DSP_RAMCODE_READY 0x1 /* bit0 */ +#define GPS_MCUB_D2AF_MASK_DSP_REG_READ_READY 0x2 /* bit1 */ +#define GPS_MCUB_D2AF_MASK_DSP_REQUEST_MCU_ACTION 0x4 /* bit2 */ +/* To be renamed to GPS_MCUB_D2AF_MASK_DSP_RESET_DONE */ +/* #define GPS_MCUB_D2AF_MASK_DSP_MBIST_READY 0b1000 */ +#define GPS_MCUB_D2AF_MASK_DSP_RESET_DONE 0x8 /* bit3 */ + + +/* MCU to DSP MCUB flag bit usage definition */ +#define GPS_MCUB_A2DF_MASK_DSP_DCLK_79MHZ_REQ 0x1 /* bit0 */ +#define GPS_MCUB_A2DF_MASK_DSP_DCLK_88MHZ_REQ 0x2 /* bit1 */ +#define GPS_MCUB_A2DF_MASK_DSP_REG_READ_REQ 0x4 /* bit2 */ +/* Will be available on MT6779. The previous chips don't use it */ +#define GPS_MCUB_A2DF_MASK_DSP_SET_CFG_REQ 0x8 /* bit3 */ + + +enum gps_dsp_event_t { + GPS_DSP_EVT_FUNC_OFF, /* 0 From host */ + GPS_DSP_EVT_FUNC_ON, /* 1 From host */ + GPS_DSP_EVT_RESET_DONE, /* 2 From DSP D2AF[3] */ + GPS_DSP_EVT_RAM_CODE_READY, /* 3 From DSP D2AF[0] */ + GPS_DSP_EVT_CTRL_TIMER_EXPIRE, /* 4 From timer */ + GPS_DSP_EVT_HW_SLEEP_REQ, /* 5 From DSP D2AF[2] - DSP request it; from host for test */ + GPS_DSP_EVT_HW_SLEEP_EXIT, /* 6 From host - just for test */ + GPS_DSP_EVT_HW_STOP_REQ, /* 7 From host */ + GPS_DSP_EVT_HW_STOP_EXIT, /* 8 From host */ + GPS_DSP_EVT_MAX +}; + +#define GPS_DSP_RESET_TIMEOUT_MS (180) +#define GPS_DSP_MVCD_TIMEOUT_MS (1000) +#define GPS_DSP_WAKEUP_TIMEOUT_MS (180) + + +enum gps_dsp_state_t gps_dsp_state_get(enum gps_dl_link_id_enum link_id); +void gps_dsp_state_change_to(enum gps_dsp_state_t state, enum gps_dl_link_id_enum link_id); +bool gps_dsp_state_is(enum gps_dsp_state_t state, enum gps_dl_link_id_enum link_id); + +void gps_dsp_fsm(enum gps_dsp_event_t evt, enum gps_dl_link_id_enum link_id); + +#endif /* _GPS_DSP_FSM_H_ */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/hal_common.h b/drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/hal_common.h new file mode 100644 index 0000000000000..ca22ff30bf1dc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hal/inc/hal_common.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef ___HAL_COMMON_H__ +#define ___HAL_COMMON_H__ + + +#endif /* ___HAL_COMMON_H__ */ diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_bgf.c b/drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_bgf.c new file mode 100644 index 0000000000000..8faa31121fab5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_bgf.c @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "gps_dl_config.h" +#include "gps_dl_hw_priv_util.h" +/* #include "bgf/bgf_cfg.h" */ +/* #include "bgf/bgf_cfg_on.h" */ + +#define BGF_ADDR_ENTRY_NUM (1) +static const struct gps_dl_addr_map_entry g_bfg_addr_table[BGF_ADDR_ENTRY_NUM] = { + {0, 0, 0} + /* {0x18812000, BGF_CFG_BASE, 0x1000}, */ + /* {0x18813000, BGF_CFG_ON_BASE, 0x1000}, */ +}; + +unsigned int bgf_bus_to_host(unsigned int bgf_addr) +{ + unsigned int i; + const struct gps_dl_addr_map_entry *p; + + for (i = 0; i < BGF_ADDR_ENTRY_NUM; i++) { + p = &g_bfg_addr_table[i]; + if (bgf_addr >= p->bus_addr && + bgf_addr < (p->bus_addr + p->length)) + return ((bgf_addr - p->bus_addr) + p->host_addr); + } + + return 0; +} + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_conn_infra.c b/drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_conn_infra.c new file mode 100644 index 0000000000000..1ef54eb63e08e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_conn_infra.c @@ -0,0 +1,680 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "gps_dl_config.h" + +#include "gps_dl_context.h" +#include "gps_dl_hw_api.h" +#include "gps_dl_hw_dep_api.h" +#include "gps_dl_hw_priv_util.h" + +#include "conn_infra/conn_host_csr_top.h" +#include "conn_infra/conn_infra_cfg.h" +#if GPS_DL_HAS_PTA +#include "conn_infra/conn_uart_pta.h" +#include "conn_infra/conn_pta6.h" +#endif +#include "conn_infra/conn_semaphore.h" +#include "conn_infra/conn_rf_spi_mst_reg.h" + +void gps_dl_hw_set_gps_emi_remapping(unsigned int _20msb_of_36bit_phy_addr) +{ + GDL_HW_SET_CONN_INFRA_ENTRY( + CONN_HOST_CSR_TOP_CONN2AP_REMAP_GPS_EMI_BASE_ADDR_CONN2AP_REMAP_GPS_EMI_BASE_ADDR, + _20msb_of_36bit_phy_addr); +} + +unsigned int gps_dl_hw_get_gps_emi_remapping(void) +{ + return GDL_HW_GET_CONN_INFRA_ENTRY( + CONN_HOST_CSR_TOP_CONN2AP_REMAP_GPS_EMI_BASE_ADDR_CONN2AP_REMAP_GPS_EMI_BASE_ADDR); +} + +void gps_dl_hw_print_hw_status(enum gps_dl_link_id_enum link_id, bool dump_rf_cr) +{ + struct gps_dl_hw_dma_status_struct a2d_dma_status, d2a_dma_status; + struct gps_dl_hw_usrt_status_struct usrt_status; + enum gps_dl_hal_dma_ch_index a2d_dma_ch, d2a_dma_ch; + + if (gps_dl_show_reg_wait_log()) + GDL_LOGXD(link_id, ""); + + if (link_id == GPS_DATA_LINK_ID0) { + a2d_dma_ch = GPS_DL_DMA_LINK0_A2D; + d2a_dma_ch = GPS_DL_DMA_LINK0_D2A; + } else if (link_id == GPS_DATA_LINK_ID1) { + a2d_dma_ch = GPS_DL_DMA_LINK1_A2D; + d2a_dma_ch = GPS_DL_DMA_LINK1_D2A; + } else + return; + + gps_dl_hw_save_usrt_status_struct(link_id, &usrt_status); + gps_dl_hw_print_usrt_status_struct(link_id, &usrt_status); + + gps_dl_hw_save_dma_status_struct(a2d_dma_ch, &a2d_dma_status); + gps_dl_hw_print_dma_status_struct(a2d_dma_ch, &a2d_dma_status); + + gps_dl_hw_save_dma_status_struct(d2a_dma_ch, &d2a_dma_status); + gps_dl_hw_print_dma_status_struct(d2a_dma_ch, &d2a_dma_status); + + GDL_HW_RD_GPS_REG(0x80073160); /* DL0 */ + GDL_HW_RD_GPS_REG(0x80073134); /* DL1 */ + + GDL_HW_RD_CONN_INFRA_REG(CONN_RF_SPI_MST_ADDR_SPI_STA_ADDR); + GDL_HW_RD_CONN_INFRA_REG(CONN_RF_SPI_MST_ADDR_SPI_GPS_GPS_ADDR_ADDR); + GDL_HW_RD_CONN_INFRA_REG(CONN_RF_SPI_MST_ADDR_SPI_GPS_GPS_WDAT_ADDR); + GDL_HW_RD_CONN_INFRA_REG(CONN_RF_SPI_MST_ADDR_SPI_GPS_GPS_RDAT_ADDR); + GDL_HW_RD_CONN_INFRA_REG(CONN_RF_SPI_MST_ADDR_SPI_STA_ADDR); + + if (dump_rf_cr) { + gps_dl_hw_gps_dump_top_rf_cr(); + gps_dl_hw_gps_dump_gps_rf_cr(); + } + + /* only need for L1 */ + gps_each_link_set_bool_flag(GPS_DATA_LINK_ID0, LINK_NEED_A2Z_DUMP, true); +} + +void gps_dl_hw_do_gps_a2z_dump(void) +{ + GDL_HW_WR_GPS_REG(0x80073120, 1); /* enable A2Z */ + GDL_HW_RD_GPS_REG(0x800706C0); + GDL_HW_RD_GPS_REG(0x80070450); + GDL_HW_RD_GPS_REG(0x80080450); +} + +void gps_dl_hw_dump_sleep_prot_status(void) +{ + bool show_log = true; + + show_log = gps_dl_set_show_reg_rw_log(true); + GDL_HW_DUMP_SLP_RPOT_STATUS(); + gps_dl_set_show_reg_rw_log(show_log); +} + +void gps_dl_hw_dump_host_csr_gps_info(bool force_show_log) +{ + int i; + bool show_log = true; + + if (force_show_log) + show_log = gps_dl_set_show_reg_rw_log(true); + +#if 0 + GDL_HW_GET_CONN_INFRA_ENTRY(CONN_HOST_CSR_TOP_HOST2GPS_DEGUG_SEL_HOST2GPS_DEGUG_SEL); + GDL_HW_GET_CONN_INFRA_ENTRY(CONN_HOST_CSR_TOP_GPS_CFG2HOST_DEBUG_GPS_CFG2HOST_DEBUG); +#else + gps_dl_bus_rd_opt(GPS_DL_CONN_INFRA_BUS, + CONN_HOST_CSR_TOP_HOST2GPS_DEGUG_SEL_ADDR, + BMASK_RW_FORCE_PRINT); + gps_dl_bus_rd_opt(GPS_DL_CONN_INFRA_BUS, + CONN_HOST_CSR_TOP_GPS_CFG2HOST_DEBUG_ADDR, + BMASK_RW_FORCE_PRINT); +#endif + + for (i = 0xA2; i <= 0xB7; i++) { +#if 0 + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_HOST_CSR_TOP_HOST2GPS_DEGUG_SEL_HOST2GPS_DEGUG_SEL, i); + GDL_HW_GET_CONN_INFRA_ENTRY(CONN_HOST_CSR_TOP_GPS_CFG2HOST_DEBUG_GPS_CFG2HOST_DEBUG); +#else + gps_dl_bus_wr_opt(GPS_DL_CONN_INFRA_BUS, + CONN_HOST_CSR_TOP_HOST2GPS_DEGUG_SEL_ADDR, i, + BMASK_RW_FORCE_PRINT); + gps_dl_bus_rd_opt(GPS_DL_CONN_INFRA_BUS, + CONN_HOST_CSR_TOP_GPS_CFG2HOST_DEBUG_ADDR, + BMASK_RW_FORCE_PRINT); +#endif + } + + if (force_show_log) + gps_dl_set_show_reg_rw_log(show_log); +} + +void gps_dl_bus_check_and_print(unsigned int host_addr) +{ + /* not do rw check because here is the checking */ + GDL_LOGI("for addr = 0x%08x", host_addr); + gps_dl_bus_wr_opt(GPS_DL_CONN_INFRA_BUS, + CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_AO_DEBUGSYS_ADDR, 0x000D0001, + BMASK_RW_FORCE_PRINT); + + gps_dl_bus_rd_opt(GPS_DL_CONN_INFRA_BUS, + CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT_ADDR, + BMASK_RW_FORCE_PRINT); + + gps_dl_bus_wr_opt(GPS_DL_CONN_INFRA_BUS, + CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_AO_DEBUGSYS_ADDR, 0x000B0001, + BMASK_RW_FORCE_PRINT); + + gps_dl_bus_rd_opt(GPS_DL_CONN_INFRA_BUS, + CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT_ADDR, + BMASK_RW_FORCE_PRINT); + + gps_dl_bus_wr_opt(GPS_DL_CONN_INFRA_BUS, + CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_AO_DEBUGSYS_ADDR, 0x000A0001, + BMASK_RW_FORCE_PRINT); + + gps_dl_bus_rd_opt(GPS_DL_CONN_INFRA_BUS, + CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT_ADDR, + BMASK_RW_FORCE_PRINT); +} + +void gps_dl_hw_dump_host_csr_conninfra_info_inner(unsigned int selection, int n) +{ + int i; + + for (i = 0; i < n; i++) { +#if 0 + GDL_HW_SET_CONN_INFRA_ENTRY( + CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_AO_DEBUGSYS_CONN_INFRA_DEBUG_CTRL_AO_DEBUGSYS_CTRL, + selection); + GDL_HW_GET_CONN_INFRA_ENTRY( + CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT); +#else + /* Due to RW_DO_CHECK might be enabled, not use + * GDL_HW_SET_CONN_INFRA_ENTRY and GDL_HW_GET_CONN_INFRA_ENTRY to avoid redundant print. + */ + gps_dl_bus_wr_opt(GPS_DL_CONN_INFRA_BUS, + CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_AO_DEBUGSYS_ADDR, selection, + BMASK_RW_FORCE_PRINT); + + gps_dl_bus_rd_opt(GPS_DL_CONN_INFRA_BUS, + CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT_ADDR, + BMASK_RW_FORCE_PRINT); +#endif + selection -= 0x10000; + } +} + +void gps_dl_hw_dump_host_csr_conninfra_info(bool force_show_log) +{ + bool show_log = true; + + if (force_show_log) + show_log = gps_dl_set_show_reg_rw_log(true); + + gps_dl_hw_dump_host_csr_conninfra_info_inner(0x000F0001, 15); + gps_dl_hw_dump_host_csr_conninfra_info_inner(0x00030002, 3); + gps_dl_hw_dump_host_csr_conninfra_info_inner(0x00040003, 4); + + if (force_show_log) + gps_dl_set_show_reg_rw_log(show_log); +} + +#if GPS_DL_HAS_PTA +/* CONN_INFRA_CFG_CKGEN_BUS_ADDR[5:2] */ +#define CONN_INFRA_CFG_PTA_CLK_ADDR CONN_INFRA_CFG_CKGEN_BUS_ADDR +#define CONN_INFRA_CFG_PTA_CLK_MASK (\ + CONN_INFRA_CFG_CKGEN_BUS_CONN_CO_EXT_UART_PTA_OSC_CKEN_MASK | \ + CONN_INFRA_CFG_CKGEN_BUS_CONN_CO_EXT_UART_PTA_HCLK_CKEN_MASK | \ + CONN_INFRA_CFG_CKGEN_BUS_CONN_CO_EXT_UART_PTA5_OSC_CKEN_MASK | \ + CONN_INFRA_CFG_CKGEN_BUS_CONN_CO_EXT_UART_PTA5_HCLK_CKEN_MASK) +#define CONN_INFRA_CFG_PTA_CLK_SHFT \ + CONN_INFRA_CFG_CKGEN_BUS_CONN_CO_EXT_UART_PTA5_HCLK_CKEN_SHFT + +bool gps_dl_hw_is_pta_clk_cfg_ready(void) +{ + unsigned int pta_clk_cfg; + bool okay = true; + + pta_clk_cfg = GDL_HW_GET_CONN_INFRA_ENTRY(CONN_INFRA_CFG_PTA_CLK); + if (pta_clk_cfg != 0xF) { + /* clock cfg is default ready, no need to set it + * if not as excepted, skip pta and pta_uart init + */ + okay = false; + } + + if (!okay) + GDL_LOGE("pta_clk_cfg = 0x%x", pta_clk_cfg); + return okay; +} + +void gps_dl_hw_set_ptk_clk_cfg(void) +{ + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_INFRA_CFG_PTA_CLK, 0xF); +} + +bool gps_dl_hw_is_pta_uart_init_done(void) +{ + bool done; + unsigned int pta_uart_en; + + pta_uart_en = GDL_HW_GET_CONN_INFRA_ENTRY(CONN_PTA6_RO_PTA_CTRL_ro_uart_apb_hw_en); + done = (pta_uart_en == 1); + GDL_LOGD("done = %d, pta_uart_en = %d", done, pta_uart_en); + + return done; +} + +/* Only check bit7, so not use CONN_UART_PTA_FCR_RFTL */ +#define CONN_UART_PTA_FCR_RFTL_HIGH_BIT_ADDR CONN_UART_PTA_FCR_ADDR +#define CONN_UART_PTA_FCR_RFTL_HIGH_BIT_MASK 0x00000080 +#define CONN_UART_PTA_FCR_RFTL_HIGH_BIT_SHFT 7 + +bool gps_dl_hw_init_pta_uart(void) +{ +#if 0 + unsigned int pta_uart_en; +#endif + bool show_log; + bool poll_okay; + bool reg_rw_log = gps_dl_log_reg_rw_is_on(GPS_DL_REG_RW_HOST_CSR_PTA_INIT); + + /* 20191008 after DE checking, bellow steps are no need */ +#if 0 + /* Set pta uart to MCU mode before init it. + * Note: both wfset and btset = 0, then pta_uart_en should become 0, + * set one of them = 1, then pta_uart_en should become 1. + */ + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_WFSET_PTA_CTRL_r_wfset_uart_apb_hw_en, 0); + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_BTSET_PTA_CTRL_r_btset_uart_apb_hw_en, 0); + pta_uart_en = GDL_HW_GET_CONN_INFRA_ENTRY(CONN_PTA6_RO_PTA_CTRL_ro_uart_apb_hw_en); + + if (pta_uart_en != 0) { + GDL_LOGE("ro_uart_apb_hw_en not become 0, fail"); + return false; + } +#endif + + if (reg_rw_log) { + gps_dl_hw_dump_host_csr_conninfra_info(true); + show_log = gps_dl_set_show_reg_rw_log(true); + } + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_UART_PTA_HIGHSPEED_SPEED, 3); + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_UART_PTA_SAMPLE_COUNT_SAMPLE_COUNT, 5); + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_UART_PTA_SAMPLE_POINT_SAMPLE_POINT, 2); + + /* UART_PTA_BASE + 0x3C = 0x12, this step is no-need now + * GDL_HW_SET_CONN_INFRA_ENTRY(CONN_UART_PTA_GUARD_GUARD_CNT, 2); + * GDL_HW_SET_CONN_INFRA_ENTRY(CONN_UART_PTA_GUARD_GUARD_EN, 1); + */ + + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_UART_PTA_VFIFO_EN_RX_TIME_EN, 1); /* bit7 */ + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_UART_PTA_VFIFO_EN_PTA_RX_FE_EN, 1); /* bit3 */ + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_UART_PTA_VFIFO_EN_PTA_RX_MODE, 1); /* bit2 */ + + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_UART_PTA_FRACDIV_L_FRACDIV_L, 0x55); + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_UART_PTA_FRACDIV_M_FRACDIV_M, 2); + + /* UART_PTA_BASE + 0x3C[4] = 0, this step is no-need now + * GDL_HW_SET_CONN_INFRA_ENTRY(CONN_UART_PTA_GUARD_GUARD_EN, 0); + */ + + GDL_HW_WR_CONN_INFRA_REG(CONN_UART_PTA_LCR_ADDR, 0xBF); + GDL_HW_WR_CONN_INFRA_REG(CONN_UART_PTA_DLL_ADDR, 1); + GDL_HW_WR_CONN_INFRA_REG(CONN_UART_PTA_DLM_ADDR, 0); + GDL_HW_WR_CONN_INFRA_REG(CONN_UART_PTA_LCR_ADDR, 3); + + /* 20191008 after DE checking, add CONN_UART_PTA_FCR_ADDR read-back checking */ + + /* dump value before setting */ + GDL_HW_RD_CONN_INFRA_REG(CONN_UART_PTA_FCR_ADDR); + GDL_HW_WR_CONN_INFRA_REG(CONN_UART_PTA_FCR_ADDR, 0x37); + /* dump value after setting and poll until bit7 become 1 or timeout */ + GDL_HW_POLL_CONN_INFRA_ENTRY(CONN_UART_PTA_FCR_RFTL_HIGH_BIT, 1, POLL_DEFAULT, &poll_okay); + if (!poll_okay) { + if (reg_rw_log) + gps_dl_set_show_reg_rw_log(show_log); + GDL_LOGE("CONN_UART_PTA_FCR bit7 not become 1, fail"); + return false; + } + + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_WFSET_PTA_CTRL_r_wfset_uart_apb_hw_en, 1); + + /* 20191008 after DE checking, add this step */ + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_BTSET_PTA_CTRL_r_btset_uart_apb_hw_en, 1); + + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_WFSET_PTA_CTRL_r_wfset_lte_pta_en, 1); + + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_TMR_CTRL_1_r_idc_2nd_byte_tmout, 4); /* us */ + + if (reg_rw_log) + gps_dl_set_show_reg_rw_log(show_log); + + return true; +} + +void gps_dl_hw_deinit_pta_uart(void) +{ + /* Currently no need to do pta uart deinit */ +} + + +#define PTA_1M_CNT_VALUE 26 /* mobile platform uses 26M */ + +bool gps_dl_hw_is_pta_init_done(void) +{ + bool done; + unsigned int pta_en; + unsigned int pta_arb_en; + unsigned int pta_1m_cnt; + + pta_en = GDL_HW_GET_CONN_INFRA_ENTRY(CONN_PTA6_RO_PTA_CTRL_ro_pta_en); + pta_arb_en = GDL_HW_GET_CONN_INFRA_ENTRY(CONN_PTA6_RO_PTA_CTRL_ro_en_pta_arb); + pta_1m_cnt = GDL_HW_GET_CONN_INFRA_ENTRY(CONN_PTA6_PTA_CLK_CFG_r_pta_1m_cnt); + + done = ((pta_en == 1) && (pta_arb_en == 1) && (pta_1m_cnt == PTA_1M_CNT_VALUE)); + GDL_LOGD("done = %d, pta_en = %d, pta_arb_en = %d, pta_1m_cnt = 0x%x", + done, pta_en, pta_arb_en, pta_1m_cnt); + + return done; +} + +void gps_dl_hw_init_pta(void) +{ + unsigned int pta_en; + unsigned int pta_arb_en; + + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_PTA_CLK_CFG_r_pta_1m_cnt, PTA_1M_CNT_VALUE); + + /* Note: GPS use WFSET */ + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_WFSET_PTA_CTRL_r_wfset_en_pta_arb, 1); + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_WFSET_PTA_CTRL_r_wfset_pta_en, 1); + + /* just confirm status change properly */ + pta_en = GDL_HW_GET_CONN_INFRA_ENTRY(CONN_PTA6_RO_PTA_CTRL_ro_pta_en); + pta_arb_en = GDL_HW_GET_CONN_INFRA_ENTRY(CONN_PTA6_RO_PTA_CTRL_ro_en_pta_arb); + + if (!((pta_en == 1) && (pta_arb_en == 1))) { + /* should not happen, do nothing but just show log */ + GDL_LOGE("pta_en = %d, pta_arb_en = %d, fail", pta_en, pta_arb_en); + } else + GDL_LOGI("pta_en = %d, pta_arb_en = %d, okay", pta_en, pta_arb_en); +} + +void gps_dl_hw_deinit_pta(void) +{ + /* Currently no need to do pta deinit */ +} + + +void gps_dl_hw_claim_pta_used_by_gps(void) +{ + /* Currently it's empty */ +} + +void gps_dl_hw_disclaim_pta_used_by_gps(void) +{ + /* Currently it's empty */ +} + +void gps_dl_hw_set_pta_blanking_parameter(bool use_direct_path) +{ + if (use_direct_path) { + /* Use direct path - just cfg src, no other parameter */ + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_GPS_BLANK_CFG_r_gps_blank_src, 1); + return; + } + + /* Set timeout threashold: ms */ + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_TMR_CTRL_3_r_gps_l5_blank_tmr_thld, 3); + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_TMR_CTRL_3_r_gps_l1_blank_tmr_thld, 3); + + /* Set blanking source: both LTE and NR */ + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_GPS_BLANK_CFG_r_idc_gps_l1_blank_src, 2); + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_GPS_BLANK_CFG_r_idc_gps_l5_blank_src, 2); + + /* Use IDC mode */ + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_GPS_BLANK_CFG_r_gps_blank_src, 0); +} + +/* + * COS_SEMA_COEX_INDEX = 5(see conninfra/platform/include/consys_hw.h) + * GPS use M3 + */ +#define COS_SEMA_COEX_STA_ENTRY_FOR_GPS \ + CONN_SEMAPHORE_CONN_SEMA05_M3_OWN_STA_CONN_SEMA05_M3_OWN_STA + +#define COS_SEMA_COEX_REL_ENTRY_FOR_GPS \ + CONN_SEMAPHORE_CONN_SEMA05_M3_OWN_REL_CONN_SEMA05_M3_OWN_REL + +bool gps_dl_hw_take_conn_coex_hw_sema(unsigned int try_timeout_ms) +{ + bool okay; + bool show_log; + unsigned int poll_us, poll_max_us; + unsigned int val; + + show_log = gps_dl_set_show_reg_rw_log(true); + /* poll until value is expected or timeout */ + poll_us = 0; + poll_max_us = POLL_US * 1000 * try_timeout_ms; + okay = false; + while (!okay) { + val = GDL_HW_GET_CONN_INFRA_ENTRY(COS_SEMA_COEX_STA_ENTRY_FOR_GPS); + /* 2bit value: + * 0 -> need waiting + * 1,3 -> okay; 2 -> already taken + */ + if (val != 0) { + okay = true; + break; + } + if (poll_us >= poll_max_us) { + okay = false; + break; + } + gps_dl_wait_us(POLL_INTERVAL_US); + poll_us += POLL_INTERVAL_US; + } + gps_dl_set_show_reg_rw_log(show_log); + + if (!okay) + GDL_LOGW("okay = %d", okay); + else + GDL_LOGD("okay = %d", okay); + return okay; +} + +void gps_dl_hw_give_conn_coex_hw_sema(void) +{ + bool show_log; + + show_log = gps_dl_set_show_reg_rw_log(true); + GDL_HW_SET_CONN_INFRA_ENTRY(COS_SEMA_COEX_REL_ENTRY_FOR_GPS, 1); + gps_dl_set_show_reg_rw_log(show_log); + + GDL_LOGD(""); +} +#endif /* GPS_DL_HAS_PTA */ + +/* + * COS_SEMA_RFSPI_INDEX = 11(see conninfra/platform/include/consys_hw.h) + * GPS use M3 + */ +#define COS_SEMA_RFSPI_STA_ENTRY_FOR_GPS \ + CONN_SEMAPHORE_CONN_SEMA11_M3_OWN_STA_CONN_SEMA11_M3_OWN_STA + +#define COS_SEMA_RFSPI_REL_ENTRY_FOR_GPS \ + CONN_SEMAPHORE_CONN_SEMA11_M3_OWN_REL_CONN_SEMA11_M3_OWN_REL + +bool gps_dl_hw_take_conn_rfspi_hw_sema(unsigned int try_timeout_ms) +{ + bool okay; + bool show_log; + unsigned int poll_us, poll_max_us; + unsigned int val; + + show_log = gps_dl_set_show_reg_rw_log(true); + /* poll until value is expected or timeout */ + poll_us = 0; + poll_max_us = POLL_US * 1000 * try_timeout_ms; + okay = false; + while (!okay) { + val = GDL_HW_GET_CONN_INFRA_ENTRY(COS_SEMA_RFSPI_STA_ENTRY_FOR_GPS); + /* 2bit value: + * 0 -> need waiting + * 1,3 -> okay; 2 -> already taken + */ + if (val != 0) { + okay = true; + break; + } + if (poll_us >= poll_max_us) { + okay = false; + break; + } + gps_dl_wait_us(POLL_INTERVAL_US); + poll_us += POLL_INTERVAL_US; + } + gps_dl_set_show_reg_rw_log(show_log); + + GDL_LOGI("okay = %d", okay); + + return okay; +} + +void gps_dl_hw_give_conn_rfspi_hw_sema(void) +{ + bool show_log; + + show_log = gps_dl_set_show_reg_rw_log(true); + GDL_HW_SET_CONN_INFRA_ENTRY(COS_SEMA_RFSPI_REL_ENTRY_FOR_GPS, 1); + gps_dl_set_show_reg_rw_log(show_log); + + GDL_LOGI(""); +} + + +#define GPS_DL_RFSPI_BUSY_POLL_MAX (10*1000*POLL_US) /* 10ms */ + +/* note: must be protect by gps_dl_hw_take_conn_rfspi_hw_sema */ +static bool gps_dl_hw_gps_fmspi_state_backup(unsigned int *p_rd_ext_en_bk, unsigned int *p_rd_ext_cnt_bk) +{ + bool okay = true; + bool poll_okay; + + if (p_rd_ext_en_bk == NULL || p_rd_ext_cnt_bk == NULL) + return false; + + GDL_HW_POLL_CONN_INFRA_ENTRY(CONN_RF_SPI_MST_REG_SPI_STA_FM_BUSY, 0, + GPS_DL_RFSPI_BUSY_POLL_MAX, &poll_okay); + if (!poll_okay) + return false; + + *p_rd_ext_en_bk = GDL_HW_GET_CONN_INFRA_ENTRY(CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_EN); + *p_rd_ext_cnt_bk = GDL_HW_GET_CONN_INFRA_ENTRY(CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_CNT); + return okay; +} + +/* note: must be protect by gps_dl_hw_take_conn_rfspi_hw_sema */ +static void gps_dl_hw_gps_fmspi_state_restore(unsigned int rd_ext_en_bk, unsigned int rd_ext_cnt_bk) +{ + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_EN, rd_ext_en_bk); + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_CNT, rd_ext_cnt_bk); +} + +/* note: must be protect by gps_dl_hw_take_conn_rfspi_hw_sema */ +static bool gps_dl_hw_gps_fmspi_read_rfcr(unsigned int addr, unsigned int *p_val) +{ + unsigned int val; + bool okay; + bool poll_okay; + unsigned int tmp; + + if (p_val == NULL) + return false; + + GDL_HW_POLL_CONN_INFRA_ENTRY(CONN_RF_SPI_MST_REG_SPI_STA_FM_BUSY, 0, + GPS_DL_RFSPI_BUSY_POLL_MAX, &poll_okay); + if (!poll_okay) + return false; + + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_EN, 0); + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_CNT, 0); + + tmp = ((addr & 0xFFF) | (1 << 12UL) | (4 << 13UL) | (0 << 16UL)); + GDL_HW_WR_CONN_INFRA_REG(CONN_RF_SPI_MST_ADDR_SPI_FM_ADDR_ADDR, tmp); + GDL_HW_WR_CONN_INFRA_REG(CONN_RF_SPI_MST_ADDR_SPI_FM_WDAT_ADDR, 0); + + GDL_HW_POLL_CONN_INFRA_ENTRY(CONN_RF_SPI_MST_REG_SPI_STA_FM_BUSY, 0, + GPS_DL_RFSPI_BUSY_POLL_MAX, &poll_okay); + if (!poll_okay) { + GDL_HW_RD_CONN_INFRA_REG(CONN_RF_SPI_MST_ADDR_SPI_FM_RDAT_ADDR); + return false; + } + + val = GDL_HW_RD_CONN_INFRA_REG(CONN_RF_SPI_MST_ADDR_SPI_FM_RDAT_ADDR); + *p_val = val; + okay = true; + return okay; +} + +static bool gps_dl_hw_gps_fmspi_write_rfcr(unsigned int addr, unsigned int val) +{ + bool okay; + bool poll_okay; + unsigned int tmp; + + GDL_HW_POLL_CONN_INFRA_ENTRY(CONN_RF_SPI_MST_REG_SPI_STA_FM_BUSY, 0, + GPS_DL_RFSPI_BUSY_POLL_MAX, &poll_okay); + if (!poll_okay) + return false; + + tmp = ((addr & 0xFFF) | (0 << 12UL) | (4 << 13UL) | (0 << 16UL)); + GDL_HW_WR_CONN_INFRA_REG(CONN_RF_SPI_MST_ADDR_SPI_FM_ADDR_ADDR, tmp); + GDL_HW_WR_CONN_INFRA_REG(CONN_RF_SPI_MST_ADDR_SPI_FM_WDAT_ADDR, val); + + GDL_HW_POLL_CONN_INFRA_ENTRY(CONN_RF_SPI_MST_REG_SPI_STA_FM_BUSY, 0, + GPS_DL_RFSPI_BUSY_POLL_MAX, &poll_okay); + if (!poll_okay) { + GDL_HW_RD_CONN_INFRA_REG(CONN_RF_SPI_MST_ADDR_SPI_FM_RDAT_ADDR); + return false; + } + + okay = true; + return okay; +} + +void gps_dl_hw_gps_dump_gps_rf_cr(void) +{ + bool show_log, backup_okay; + unsigned int addr, val; + unsigned int rd_ext_en_bk, rd_ext_cnt_bk; + + gps_dl_hw_take_conn_rfspi_hw_sema(100); + show_log = gps_dl_set_show_reg_rw_log(true); + backup_okay = gps_dl_hw_gps_fmspi_state_backup(&rd_ext_en_bk, &rd_ext_cnt_bk); + + /* read: 0x500 ~ 0x51b */ + for (addr = 0x500; addr <= 0x51B; addr++) { + if (gps_dl_hw_gps_fmspi_read_rfcr(addr, &val)) + GDL_LOGW("rd: addr = 0x%x, val = 0x%x", addr, val); + else + GDL_LOGW("rd: addr = 0x%x, fail", addr); + } + + /* write: 0x51a = 1 */ + addr = 0x51A; + val = 1; + if (gps_dl_hw_gps_fmspi_write_rfcr(addr, val)) + GDL_LOGW("wr: addr = 0x%x, val = 0x%x, okay", addr, val); + else + GDL_LOGW("wr: addr = 0x%x, val = 0x%x, fail", addr, val); + + /* read: 0x51a & 0x51b */ + for (addr = 0x51A; addr <= 0x51B; addr++) { + if (gps_dl_hw_gps_fmspi_read_rfcr(addr, &val)) + GDL_LOGW("rd: addr = 0x%x, val = 0x%x", addr, val); + else + GDL_LOGW("rd: addr = 0x%x, fail", addr); + } + + if (backup_okay) + gps_dl_hw_gps_fmspi_state_restore(rd_ext_en_bk, rd_ext_cnt_bk); + else + GDL_LOGW("not do gps_dl_hw_gps_fmspi_state_restore due to backup failed!"); + gps_dl_set_show_reg_rw_log(show_log); + gps_dl_hw_give_conn_rfspi_hw_sema(); +} + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_gps.c b/drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_gps.c new file mode 100644 index 0000000000000..a6f3236561dbd --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_gps.c @@ -0,0 +1,500 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "gps_dl_config.h" + +#include "gps_dl_context.h" +#include "gps_dl_time_tick.h" +#include "gps_dsp_fsm.h" +#include "gps_dl_hw_api.h" +#include "gps_dl_hw_priv_util.h" +#include "gps/bgf_gps_dma.h" +#include "gps/gps_aon_top.h" +#include "gps/gps_usrt_apb.h" +#include "gps/gps_l5_usrt_apb.h" + +#define GPS_ADDR_ENTRY_NUM (1) +static const struct gps_dl_addr_map_entry g_gps_addr_table[GPS_ADDR_ENTRY_NUM] = { + /* Put base list here: */ + /* BGF_GPS_CFG_BASE */ + {0x18C00000, 0x80000000, 0x90000}, +}; + +unsigned int gps_bus_to_host(unsigned int gps_addr) +{ + unsigned int i; + const struct gps_dl_addr_map_entry *p; + + for (i = 0; i < GPS_ADDR_ENTRY_NUM; i++) { + p = &g_gps_addr_table[i]; + if (gps_addr >= p->bus_addr && + gps_addr < (p->bus_addr + p->length)) + return ((gps_addr - p->bus_addr) + p->host_addr); + } + + return 0; +} + + +void gps_dl_hw_set_dma_start(enum gps_dl_hal_dma_ch_index channel, + struct gdl_hw_dma_transfer *p_transfer) +{ + unsigned int bus_addr_of_data_start; + unsigned int bus_addr_of_buf_start; + unsigned int gdl_ret; + + gdl_ret = gps_dl_emi_remap_phy_to_bus_addr(p_transfer->transfer_start_addr, &bus_addr_of_data_start); + gdl_ret = gps_dl_emi_remap_phy_to_bus_addr(p_transfer->buf_start_addr, &bus_addr_of_buf_start); + + switch (channel) { + case GPS_DL_DMA_LINK0_A2D: + if (gps_dl_is_1byte_mode()) + GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA1_CON_ADDR, 0x00128014); + else + GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA1_CON_ADDR, 0x00128016); + + GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA1_PGMADDR_PGMADDR_ADDR, + bus_addr_of_data_start); + GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA1_WPTO_WPTO_ADDR, + bus_addr_of_buf_start); + GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA1_WPPT_WPPT, p_transfer->len_to_wrap); + GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA1_COUNT_LEN, p_transfer->transfer_max_len); + GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA1_START_STR, 1); + break; + case GPS_DL_DMA_LINK0_D2A: + if (gps_dl_is_1byte_mode()) + GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA2_CON_ADDR, 0x00078018); + else + GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA2_CON_ADDR, 0x0007801A); + + GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA2_PGMADDR_PGMADDR_ADDR, + bus_addr_of_data_start); + GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA2_WPTO_WPTO_ADDR, + bus_addr_of_buf_start); + GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA2_WPPT_WPPT, p_transfer->len_to_wrap); + GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA2_COUNT_LEN, p_transfer->transfer_max_len); + GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA2_START_STR, 1); + break; + case GPS_DL_DMA_LINK1_A2D: + if (gps_dl_is_1byte_mode()) + GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA3_CON_ADDR, 0x00328014); + else + GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA3_CON_ADDR, 0x00328016); + + GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA3_PGMADDR_PGMADDR_ADDR, + bus_addr_of_data_start); + GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA3_WPTO_WPTO_ADDR, + bus_addr_of_buf_start); + GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA3_WPPT_WPPT, p_transfer->len_to_wrap); + GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA3_COUNT_LEN, p_transfer->transfer_max_len); + GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA3_START_STR, 1); + break; + case GPS_DL_DMA_LINK1_D2A: + if (gps_dl_is_1byte_mode()) + GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA4_CON_ADDR, 0x00278018); + else + GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA4_CON_ADDR, 0x0027801A); + + GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA4_PGMADDR_PGMADDR_ADDR, + bus_addr_of_data_start); + GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA4_WPTO_WPTO_ADDR, + bus_addr_of_buf_start); + GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA4_WPPT_WPPT, p_transfer->len_to_wrap); + GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA4_COUNT_LEN, p_transfer->transfer_max_len); + GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA4_START_STR, 1); + break; + default: + return; + } +} + +void gps_dl_hw_set_dma_stop(enum gps_dl_hal_dma_ch_index channel) +{ + /* Poll until DMA IDLE */ + switch (channel) { + case GPS_DL_DMA_LINK0_A2D: + GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA1_START_STR, 0); + GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA1_ACKINT_ACK, 1); + break; + case GPS_DL_DMA_LINK0_D2A: + GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA2_START_STR, 0); + GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA2_ACKINT_ACK, 1); + break; + case GPS_DL_DMA_LINK1_A2D: + GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA3_START_STR, 0); + GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA3_ACKINT_ACK, 1); + break; + case GPS_DL_DMA_LINK1_D2A: + GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA4_START_STR, 0); + GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA4_ACKINT_ACK, 1); + break; + default: + return; + } +} + +bool gps_dl_hw_get_dma_int_status(enum gps_dl_hal_dma_ch_index channel) +{ + /* ASSERT(channel >= 0 && channel <= GPS_DL_DMA_CH_NUM); */ + switch (channel) { + case GPS_DL_DMA_LINK0_A2D: + return (bool)GDL_HW_GET_GPS_ENTRY(BGF_GPS_DMA_DMA1_INTSTA_INT); + case GPS_DL_DMA_LINK0_D2A: + return (bool)GDL_HW_GET_GPS_ENTRY(BGF_GPS_DMA_DMA2_INTSTA_INT); + case GPS_DL_DMA_LINK1_A2D: + return (bool)GDL_HW_GET_GPS_ENTRY(BGF_GPS_DMA_DMA3_INTSTA_INT); + case GPS_DL_DMA_LINK1_D2A: + return (bool)GDL_HW_GET_GPS_ENTRY(BGF_GPS_DMA_DMA4_INTSTA_INT); + default: + return false; + } +} + +void gps_dl_hw_save_dma_status_struct( + enum gps_dl_hal_dma_ch_index ch, struct gps_dl_hw_dma_status_struct *p) +{ + unsigned int offset = + (BGF_GPS_DMA_DMA2_WPPT_ADDR - BGF_GPS_DMA_DMA1_WPPT_ADDR) * ch; + + p->wrap_count = GDL_HW_RD_GPS_REG(BGF_GPS_DMA_DMA1_WPPT_ADDR + offset); + p->wrap_to_addr = GDL_HW_RD_GPS_REG(BGF_GPS_DMA_DMA1_WPTO_ADDR + offset); + p->total_count = GDL_HW_RD_GPS_REG(BGF_GPS_DMA_DMA1_COUNT_ADDR + offset); + p->config = GDL_HW_RD_GPS_REG(BGF_GPS_DMA_DMA1_CON_ADDR + offset); + p->start_flag = GDL_HW_RD_GPS_REG(BGF_GPS_DMA_DMA1_START_ADDR + offset); + p->intr_flag = GDL_HW_RD_GPS_REG(BGF_GPS_DMA_DMA1_INTSTA_ADDR + offset); + p->left_count = GDL_HW_RD_GPS_REG(BGF_GPS_DMA_DMA1_RLCT_ADDR + offset); + p->curr_addr = GDL_HW_RD_GPS_REG(BGF_GPS_DMA_DMA1_PGMADDR_ADDR + offset); + p->state = GDL_HW_RD_GPS_REG(BGF_GPS_DMA_DMA1_STATE_ADDR + offset); +} + +void gps_dl_hw_print_dma_status_struct( + enum gps_dl_hal_dma_ch_index ch, struct gps_dl_hw_dma_status_struct *p) +{ + if (!gps_dl_show_reg_wait_log()) + return; + + GDL_LOGW("dma ch %d, wrap = 0x%08x; tra = 0x%08x, count l/w/t = %d/%d/%d, str/int/sta = %d/%d/%d", + ch, p->wrap_to_addr, + p->curr_addr, p->left_count, p->wrap_count, p->total_count, + GDL_HW_EXTRACT_ENTRY(BGF_GPS_DMA_DMA1_START_STR, p->start_flag), + GDL_HW_EXTRACT_ENTRY(BGF_GPS_DMA_DMA1_INTSTA_INT, p->intr_flag), + GDL_HW_EXTRACT_ENTRY(BGF_GPS_DMA_DMA1_STATE_STATE, p->state)); + + GDL_LOGW("dma ch %d, conf = 0x%08x, master = %d, b2w = %d, w2b = %d, size = %d", + ch, p->config, + GDL_HW_EXTRACT_ENTRY(BGF_GPS_DMA_DMA1_CON_MAS, p->config), + GDL_HW_EXTRACT_ENTRY(BGF_GPS_DMA_DMA1_CON_B2W, p->config), + GDL_HW_EXTRACT_ENTRY(BGF_GPS_DMA_DMA1_CON_W2B, p->config), + GDL_HW_EXTRACT_ENTRY(BGF_GPS_DMA_DMA1_CON_SIZE, p->config)); +} + +enum GDL_RET_STATUS gps_dl_hw_wait_until_dma_complete_and_stop_it( + enum gps_dl_hal_dma_ch_index ch, int timeout_usec, bool return_if_not_start) +{ + struct gps_dl_hw_dma_status_struct dma_status; + struct gps_dl_hw_usrt_status_struct usrt_status; + enum gps_dl_link_id_enum link_id = DMA_CH_TO_LINK_ID(ch); + bool last_rw_log_on; + unsigned long tick0, tick1; + bool conninfra_okay; + bool do_stop = true; + enum GDL_RET_STATUS ret = GDL_OKAY; + int loop_cnt; + + tick0 = gps_dl_tick_get(); + loop_cnt = 0; + while (1) { + gps_dl_hw_save_dma_status_struct(ch, &dma_status); + if (gps_dl_only_show_wait_done_log()) + last_rw_log_on = gps_dl_set_show_reg_rw_log(false); + else + gps_dl_hw_print_dma_status_struct(ch, &dma_status); + + if (GDL_HW_EXTRACT_ENTRY(BGF_GPS_DMA_DMA1_START_STR, dma_status.start_flag)) { + if (gps_dl_only_show_wait_done_log()) { + gps_dl_set_show_reg_rw_log(last_rw_log_on); + gps_dl_hw_print_dma_status_struct(ch, &dma_status); + gps_dl_hw_save_dma_status_struct(ch, &dma_status); + } + break; /* to next while-loop */ + } else if (return_if_not_start) { + ret = GDL_OKAY; + do_stop = false; + goto _end; + } + + tick1 = gps_dl_tick_get(); + if (timeout_usec > GPS_DL_RW_NO_TIMEOUT && ( + gps_dl_tick_delta_to_usec(tick0, tick1) >= timeout_usec || + loop_cnt * GDL_HW_STATUS_POLL_INTERVAL_USEC >= timeout_usec)) { + ret = GDL_FAIL_TIMEOUT; + do_stop = false; + goto _end; + } + + gps_dl_wait_us(GDL_HW_STATUS_POLL_INTERVAL_USEC); + loop_cnt++; + } + + while (1) { + conninfra_okay = gps_dl_conninfra_is_okay_or_handle_it(NULL, true); + if (!conninfra_okay) { + ret = GDL_FAIL_CONN_NOT_OKAY; + do_stop = false; + break; + } + + gps_dl_hw_save_dma_status_struct(ch, &dma_status); + gps_dl_hw_save_usrt_status_struct(link_id, &usrt_status); + if (gps_dl_only_show_wait_done_log()) + last_rw_log_on = gps_dl_set_show_reg_rw_log(false); + else { + gps_dl_hw_print_dma_status_struct(ch, &dma_status); + gps_dl_hw_print_usrt_status_struct(link_id, &usrt_status); + } + + if (GDL_HW_EXTRACT_ENTRY(BGF_GPS_DMA_DMA1_INTSTA_INT, dma_status.intr_flag) && + GDL_HW_EXTRACT_ENTRY(BGF_GPS_DMA_DMA1_STATE_STATE, dma_status.state) == 0x01) { + if (gps_dl_only_show_wait_done_log()) { + gps_dl_set_show_reg_rw_log(last_rw_log_on); + gps_dl_hw_print_dma_status_struct(ch, &dma_status); + gps_dl_hw_save_dma_status_struct(ch, &dma_status); + } + + /* DMA ready to stop */ + gps_dl_hw_set_dma_stop(ch); + gps_dl_hw_save_dma_status_struct(ch, &dma_status); + gps_dl_hw_print_dma_status_struct(ch, &dma_status); + ret = GDL_OKAY; + do_stop = true; + break; + } + + tick1 = gps_dl_tick_get(); + if (timeout_usec > GPS_DL_RW_NO_TIMEOUT && ( + gps_dl_tick_delta_to_usec(tick0, tick1) >= timeout_usec || + loop_cnt * GDL_HW_STATUS_POLL_INTERVAL_USEC >= timeout_usec)) { + ret = GDL_FAIL_TIMEOUT; + do_stop = false; + break; + } + + gps_dl_wait_us(GDL_HW_STATUS_POLL_INTERVAL_USEC); + loop_cnt++; + } + +_end: + tick1 = gps_dl_tick_get(); + GDL_LOGW("ch = %d, d_us = %d, do_stop = %d, ret = %s", + ch, gps_dl_tick_delta_to_usec(tick0, tick1), do_stop, gdl_ret_to_name(ret)); + return ret; +} + +unsigned int gps_dl_hw_get_dma_left_len(enum gps_dl_hal_dma_ch_index channel) +{ + /* ASSERT(channel >= 0 && channel <= GPS_DL_DMA_CH_NUM); */ + switch (channel) { + case GPS_DL_DMA_LINK0_A2D: + return GDL_HW_GET_GPS_ENTRY(BGF_GPS_DMA_DMA1_RLCT_RLCT); + case GPS_DL_DMA_LINK0_D2A: + return GDL_HW_GET_GPS_ENTRY(BGF_GPS_DMA_DMA2_RLCT_RLCT); + case GPS_DL_DMA_LINK1_A2D: + return GDL_HW_GET_GPS_ENTRY(BGF_GPS_DMA_DMA3_RLCT_RLCT); + case GPS_DL_DMA_LINK1_D2A: + return GDL_HW_GET_GPS_ENTRY(BGF_GPS_DMA_DMA4_RLCT_RLCT); + default: + return 0; + } +} + +void gps_dl_hw_get_link_status( + enum gps_dl_link_id_enum link_id, struct gps_dl_hw_link_status_struct *p) +{ + unsigned int reg_val; + unsigned int offset = + (GPS_L5_USRT_APB_APB_CTRL_ADDR - GPS_USRT_APB_APB_CTRL_ADDR) * link_id; + + /* todo: link_id error handling */ + + if (link_id == GPS_DATA_LINK_ID0) { + p->tx_dma_done = gps_dl_hw_get_dma_int_status(GPS_DL_DMA_LINK0_A2D); + p->rx_dma_done = gps_dl_hw_get_dma_int_status(GPS_DL_DMA_LINK0_D2A); + } else if (link_id == GPS_DATA_LINK_ID1) { + p->tx_dma_done = gps_dl_hw_get_dma_int_status(GPS_DL_DMA_LINK1_A2D); + p->rx_dma_done = gps_dl_hw_get_dma_int_status(GPS_DL_DMA_LINK1_D2A); + } else { + p->tx_dma_done = false; + p->rx_dma_done = false; + } + + reg_val = GDL_HW_RD_GPS_REG(GPS_USRT_APB_APB_STA_ADDR + offset); + p->usrt_has_data = GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_TX_IND, reg_val); + p->usrt_has_nodata = GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_NODAINTB, reg_val); +} + +void gps_dl_hw_save_usrt_status_struct( + enum gps_dl_link_id_enum link_id, struct gps_dl_hw_usrt_status_struct *p) +{ + unsigned int offset = + (GPS_L5_USRT_APB_APB_CTRL_ADDR - GPS_USRT_APB_APB_CTRL_ADDR) * link_id; + + p->ctrl_setting = GDL_HW_RD_GPS_REG(GPS_USRT_APB_APB_CTRL_ADDR + offset); + p->intr_enable = GDL_HW_RD_GPS_REG(GPS_USRT_APB_APB_INTEN_ADDR + offset); + p->state = GDL_HW_RD_GPS_REG(GPS_USRT_APB_APB_STA_ADDR + offset); + + p->mcub_a2d_flag = GDL_HW_RD_GPS_REG(GPS_USRT_APB_MCUB_A2DF_ADDR + offset); + p->mcub_d2a_flag = GDL_HW_RD_GPS_REG(GPS_USRT_APB_MCUB_D2AF_ADDR + offset); + + p->mcub_a2d_d0 = GDL_HW_RD_GPS_REG(GPS_USRT_APB_MCU_A2D0_ADDR + offset); + p->mcub_a2d_d1 = GDL_HW_RD_GPS_REG(GPS_USRT_APB_MCU_A2D1_ADDR + offset); + p->mcub_d2a_d0 = GDL_HW_RD_GPS_REG(GPS_USRT_APB_MCU_D2A0_ADDR + offset); + p->mcub_d2a_d1 = GDL_HW_RD_GPS_REG(GPS_USRT_APB_MCU_D2A1_ADDR + offset); +} + +void gps_dl_hw_print_usrt_status_struct( + enum gps_dl_link_id_enum link_id, struct gps_dl_hw_usrt_status_struct *p) +{ + if (!gps_dl_show_reg_wait_log()) + return; + + GDL_LOGXW(link_id, "usrt ctrl = 0x%08x[DMA_EN RX=%d,TX=%d; 1BYTE=%d], intr_en = 0x%08x", + p->ctrl_setting, + GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_CTRL_RX_EN, p->ctrl_setting), + GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_CTRL_TX_EN, p->ctrl_setting), + GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_CTRL_BYTEN, p->ctrl_setting), + p->intr_enable); + + GDL_LOGXW(link_id, "usrt state = 0x%08x, [UOEFS]RX=%d%d%d%d(%d),TX=%d%d%d%d(%d)", + p->state, + GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_RX_UNDR, p->state), + GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_RX_OVF, p->state), + GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_RX_EMP, p->state), + GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_RX_FULL, p->state), + GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_RX_ST, p->state), + GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_TX_UNDR, p->state), + GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_TX_OVF, p->state), + GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_TX_EMP, p->state), + GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_TX_FULL, p->state), + GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_TX_ST, p->state)); + + GDL_LOGXW(link_id, "usrt TxReg_em=%d, TX_IND=%d, TX_IND=%d, U_em=%d, NOD_INT=%d", + GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_REGE, p->state), + GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_TX_IND, p->state), + GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_TXINTB, p->state), + GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_URAME, p->state), + GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_NODAINTB, p->state)); + + GDL_LOGXW(link_id, "mcub d2a flag=0x%08x, d0=0x%08x, d1=0x%08x", + p->mcub_d2a_flag, p->mcub_d2a_d0, p->mcub_d2a_d1); + + GDL_LOGXW(link_id, "mcub a2d flag=0x%08x, d0=0x%08x, d1=0x%08x", + p->mcub_a2d_flag, p->mcub_a2d_d0, p->mcub_a2d_d1); +} + +void gps_dl_hw_switch_dsp_jtag(void) +{ + unsigned int value, value_new; + + value = GDL_HW_RD_GPS_REG(0x80073160); + value_new = value & 0xFFFFFFFE; + value_new = value_new | ((~(value & 0x00000001)) & 0x00000001); + GDL_HW_WR_GPS_REG(0x80073160, value_new); +} + +enum GDL_HW_RET gps_dl_hw_get_mcub_info(enum gps_dl_link_id_enum link_id, struct gps_dl_hal_mcub_info *p) +{ + if (p == NULL) + return E_INV_PARAMS; + + if (link_id == GPS_DATA_LINK_ID0) { + p->flag = GDL_HW_RD_GPS_REG(GPS_USRT_APB_MCUB_D2AF_ADDR); + p->dat0 = GDL_HW_RD_GPS_REG(GPS_USRT_APB_MCU_D2A0_ADDR); + p->dat1 = GDL_HW_RD_GPS_REG(GPS_USRT_APB_MCU_D2A1_ADDR); + return HW_OKAY; + } else if (link_id == GPS_DATA_LINK_ID1) { + p->flag = GDL_HW_RD_GPS_REG(GPS_L5_USRT_APB_MCUB_D2AF_ADDR); + p->dat0 = GDL_HW_RD_GPS_REG(GPS_L5_USRT_APB_MCU_D2A0_ADDR); + p->dat1 = GDL_HW_RD_GPS_REG(GPS_L5_USRT_APB_MCU_D2A1_ADDR); + return HW_OKAY; + } else + return E_INV_PARAMS; +} + +void gps_dl_hw_clear_mcub_d2a_flag(enum gps_dl_link_id_enum link_id, unsigned int d2a_flag) +{ + if (link_id == GPS_DATA_LINK_ID0) + GDL_HW_WR_GPS_REG(GPS_USRT_APB_MCUB_D2AF_ADDR, d2a_flag); + else if (link_id == GPS_DATA_LINK_ID1) + GDL_HW_WR_GPS_REG(GPS_L5_USRT_APB_MCUB_D2AF_ADDR, d2a_flag); +} + +unsigned int gps_dl_hw_get_mcub_a2d_flag(enum gps_dl_link_id_enum link_id) +{ + unsigned int val = 0; + + if (link_id == GPS_DATA_LINK_ID0) + val = GDL_HW_RD_GPS_REG(GPS_USRT_APB_MCUB_A2DF_ADDR); + else if (link_id == GPS_DATA_LINK_ID1) + val = GDL_HW_RD_GPS_REG(GPS_L5_USRT_APB_MCUB_A2DF_ADDR); + + return val; +} + +enum GDL_RET_STATUS gps_dl_hw_mcub_dsp_read_request(enum gps_dl_link_id_enum link_id, u16 dsp_addr) +{ + unsigned int a2d_flag = 0; + + /* Fill addr to A2D0 and trigger A2DF bit2 + * (0x04, GPS_MCUB_A2DF_MASK_DSP_REG_READ_REQ), + * the result will be put into D2A0 after D2AF bit1 + * (0x02, GPS_MCUB_D2AF_MASK_DSP_REG_READ_READY) set. + */ + + if (link_id == GPS_DATA_LINK_ID0) + a2d_flag = GDL_HW_RD_GPS_REG(GPS_USRT_APB_MCUB_A2DF_ADDR); + else if (link_id == GPS_DATA_LINK_ID1) + a2d_flag = GDL_HW_RD_GPS_REG(GPS_L5_USRT_APB_MCUB_A2DF_ADDR); + else + return GDL_FAIL_INVAL; + + /* A2DF bit2 must be cleared, otherwise dsp is busy */ + if ((a2d_flag & GPS_MCUB_A2DF_MASK_DSP_REG_READ_REQ) != 0) { + GDL_LOGXD(link_id, "a2d_flag = 0x%x, mask = 0x%x, busy", + a2d_flag, GPS_MCUB_A2DF_MASK_DSP_REG_READ_REQ); + return GDL_FAIL_BUSY; + } + + if (link_id == GPS_DATA_LINK_ID0) { + GDL_HW_WR_GPS_REG(GPS_USRT_APB_MCU_A2D0_ADDR, (dsp_addr & 0xFFFF)); + GDL_HW_WR_GPS_REG(GPS_USRT_APB_MCUB_A2DF_ADDR, + GPS_MCUB_A2DF_MASK_DSP_REG_READ_REQ); + } else if (link_id == GPS_DATA_LINK_ID1) { + GDL_HW_WR_GPS_REG(GPS_L5_USRT_APB_MCU_A2D0_ADDR, (dsp_addr & 0xFFFF)); + GDL_HW_WR_GPS_REG(GPS_L5_USRT_APB_MCUB_A2DF_ADDR, + GPS_MCUB_A2DF_MASK_DSP_REG_READ_REQ); + } + + return GDL_OKAY; +} + +void gps_dl_hw_print_ms_counter_status(void) +{ + bool show_log; + + show_log = gps_dl_set_show_reg_rw_log(true); + gps_dl_bus_rd_opt(GPS_DL_GPS_BUS, GPS_AON_TOP_DSLEEP_CTL_ADDR, BMASK_RW_FORCE_PRINT); + gps_dl_bus_rd_opt(GPS_DL_GPS_BUS, GPS_AON_TOP_WAKEUP_CTL_ADDR, BMASK_RW_FORCE_PRINT); + gps_dl_bus_rd_opt(GPS_DL_GPS_BUS, GPS_AON_TOP_TCXO_MS_H_ADDR, BMASK_RW_FORCE_PRINT); + gps_dl_bus_rd_opt(GPS_DL_GPS_BUS, GPS_AON_TOP_TCXO_MS_L_ADDR, BMASK_RW_FORCE_PRINT); + gps_dl_set_show_reg_rw_log(show_log); +} + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_power_ctrl.c b/drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_power_ctrl.c new file mode 100644 index 0000000000000..fcb98bac25815 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_power_ctrl.c @@ -0,0 +1,695 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "gps_dl_config.h" +#include "gps_dl_context.h" + +#include "gps_dl_hal.h" +#if GPS_DL_MOCK_HAL +#include "gps_mock_hal.h" +#endif +#if GPS_DL_HAS_CONNINFRA_DRV +#if GPS_DL_ON_LINUX +#include "conninfra.h" +#elif GPS_DL_ON_CTP +#include "conninfra_ext.h" +#endif +#endif + +#include "gps_dl_hw_api.h" +#include "gps_dl_hw_dep_api.h" +#include "gps_dl_hw_priv_util.h" +#include "gps_dl_hal_util.h" +#include "gps_dsp_fsm.h" +#include "gps_dl_subsys_reset.h" + +#include "conn_infra/conn_infra_rgu.h" +#include "conn_infra/conn_infra_cfg.h" +#include "conn_infra/conn_host_csr_top.h" + +#include "gps/gps_rgu_on.h" +#include "gps/gps_cfg_on.h" +#include "gps/gps_aon_top.h" +#include "gps/bgf_gps_cfg.h" + +static int gps_dl_hw_gps_sleep_prot_ctrl(int op) +{ + bool poll_okay; + + if (1 == op) { + /* disable when on */ + GDL_HW_SET_CONN2GPS_SLP_PROT_RX_VAL(0); + GDL_HW_POLL_CONN2GPS_SLP_PROT_RX_UNTIL_VAL(0, POLL_DEFAULT, &poll_okay); + if (!poll_okay) { + GDL_LOGE("_fail_disable_gps_slp_prot - conn2gps rx"); + goto _fail_disable_gps_slp_prot; + } + + GDL_HW_SET_CONN2GPS_SLP_PROT_TX_VAL(0); + GDL_HW_POLL_CONN2GPS_SLP_PROT_TX_UNTIL_VAL(0, POLL_DEFAULT, &poll_okay); + if (!poll_okay) { + GDL_LOGE("_fail_disable_gps_slp_prot - conn2gps tx"); + goto _fail_disable_gps_slp_prot; + } + + GDL_HW_SET_GPS2CONN_SLP_PROT_RX_VAL(0); + GDL_HW_POLL_GPS2CONN_SLP_PROT_RX_UNTIL_VAL(0, POLL_DEFAULT, &poll_okay); + if (!poll_okay) { + GDL_LOGE("_fail_disable_gps_slp_prot - gps2conn rx"); + goto _fail_disable_gps_slp_prot; + } + + GDL_HW_SET_GPS2CONN_SLP_PROT_TX_VAL(0); + GDL_HW_POLL_GPS2CONN_SLP_PROT_TX_UNTIL_VAL(0, POLL_DEFAULT, &poll_okay); + if (!poll_okay) { + GDL_LOGE("_fail_disable_gps_slp_prot - gps2conn tx"); + goto _fail_disable_gps_slp_prot; + } + return 0; + +_fail_disable_gps_slp_prot: +#if 0 + GDL_HW_WR_CONN_INFRA_REG(CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_ADDR, + CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL_R_CONN2GPS_SLP_PROT_RX_EN_MASK | + CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL_R_CONN2GPS_SLP_PROT_TX_EN_MASK | + CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_R_GPS2CONN_SLP_PROT_RX_EN_MASK | + CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_R_GPS2CONN_SLP_PROT_TX_EN_MASK); +#endif + return -1; + } else if (0 == op) { + /* enable when off */ + GDL_HW_SET_CONN2GPS_SLP_PROT_TX_VAL(1); + GDL_HW_POLL_CONN2GPS_SLP_PROT_TX_UNTIL_VAL(1, POLL_DEFAULT, &poll_okay); + if (!poll_okay) { + /* From DE: need to trigger connsys reset */ + GDL_LOGE("_fail_enable_gps_slp_prot - conn2gps tx"); + goto _fail_enable_gps_slp_prot; + } + + GDL_HW_SET_CONN2GPS_SLP_PROT_RX_VAL(1); + GDL_HW_POLL_CONN2GPS_SLP_PROT_RX_UNTIL_VAL(1, POLL_DEFAULT, &poll_okay); + if (!poll_okay) { + /* not handle it, just show warning */ + GDL_LOGE("_fail_enable_gps_slp_prot - conn2gps rx"); + } + + GDL_HW_SET_GPS2CONN_SLP_PROT_TX_VAL(1); + GDL_HW_POLL_GPS2CONN_SLP_PROT_TX_UNTIL_VAL(1, POLL_DEFAULT, &poll_okay); + if (!poll_okay) { + /* not handle it, just show warning */ + GDL_LOGE("_fail_enable_gps_slp_prot - gps2conn tx"); + } + + GDL_HW_SET_GPS2CONN_SLP_PROT_RX_VAL(1); + GDL_HW_POLL_GPS2CONN_SLP_PROT_RX_UNTIL_VAL(1, POLL_DEFAULT, &poll_okay); + if (!poll_okay) { + /* From DE: need to trigger connsys reset */ + GDL_LOGE("_fail_enable_gps_slp_prot - gps2conn rx"); + goto _fail_enable_gps_slp_prot; + } + + return 0; + +_fail_enable_gps_slp_prot: + /* trigger reset on outer function */ +#if 0 + gps_dl_trigger_connsys_reset(); +#endif + return -1; + } + + return 0; +} + +bool gps_dl_hw_gps_force_wakeup_conninfra_top_off(bool enable) +{ + bool poll_okay; + + if (enable) { + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_GPS_CONN_INFRA_WAKEPU_GPS, 1); + GDL_HW_MAY_WAIT_CONN_INFRA_SLP_PROT_DISABLE_ACK(&poll_okay); + if (!poll_okay) { + GDL_LOGE("_fail_conn_slp_prot_not_okay"); + return false; /* not okay */ + } + } else + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_GPS_CONN_INFRA_WAKEPU_GPS, 0); + + return true; +} + +void gps_dl_hw_gps_sw_request_emi_usage(bool request) +{ + bool show_log; + bool reg_rw_log = gps_dl_log_reg_rw_is_on(GPS_DL_REG_RW_EMI_SW_REQ_CTRL); + + if (reg_rw_log) { + show_log = gps_dl_set_show_reg_rw_log(true); + GDL_HW_RD_CONN_INFRA_REG(CONN_INFRA_CFG_EMI_CTL_TOP_ADDR); + GDL_HW_RD_CONN_INFRA_REG(CONN_INFRA_CFG_EMI_CTL_WF_ADDR); + GDL_HW_RD_CONN_INFRA_REG(CONN_INFRA_CFG_EMI_CTL_BT_ADDR); + GDL_HW_RD_CONN_INFRA_REG(CONN_INFRA_CFG_EMI_CTL_GPS_ADDR); + } +#if (GPS_DL_USE_TIA) + /* If use TIA, CONN_INFRA_CFG_EMI_CTL_GPS used by DSP, driver use TOP's. */ + if (request) + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_INFRA_CFG_EMI_CTL_TOP_EMI_REQ_TOP, 1); + else + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_INFRA_CFG_EMI_CTL_TOP_EMI_REQ_TOP, 0); +#else + if (request) + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_INFRA_CFG_EMI_CTL_GPS_EMI_REQ_GPS, 1); + else + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_INFRA_CFG_EMI_CTL_GPS_EMI_REQ_GPS, 0); +#endif + if (reg_rw_log) + gps_dl_set_show_reg_rw_log(show_log); +} + +int gps_dl_hw_gps_common_on(void) +{ + bool poll_okay; + unsigned int poll_ver; + int i; + + /* Enable Conninfra BGF */ + GDL_HW_SET_CONN_INFRA_BGF_EN(1); + + /* Poll conninfra hw version */ + GDL_HW_CHECK_CONN_INFRA_VER(&poll_okay, &poll_ver); + if (!poll_okay) { + GDL_LOGE("_fail_conn_hw_ver_not_okay, poll_ver = 0x%08x", poll_ver); + goto _fail_conn_hw_ver_not_okay; + } + + /* GDL_HW_CHECK_CONN_INFRA_VER may check a list and return ok if poll_ver is in the list, + * record the poll_ver here and we can know which one it is, + * and it may help for debug purpose. + */ + gps_dl_hal_set_conn_infra_ver(poll_ver); + GDL_LOGW("%s: poll_ver = 0x%08x is ok", GDL_HW_SUPPORT_LIST, poll_ver); + + /* GPS SW EMI request + * gps_dl_hw_gps_sw_request_emi_usage(true); + */ + gps_dl_hal_emi_usage_init(); + + /* Enable GPS function */ + GDL_HW_SET_GPS_FUNC_EN(1); + + /* bit24: BGFSYS_ON_TOP primary power ack */ + GDL_HW_POLL_CONN_INFRA_ENTRY(CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_ACK_ST_BGFSYS_ON_TOP_PWR_ACK, 1, + POLL_DEFAULT, &poll_okay); + if (!poll_okay) { + GDL_LOGE("_fail_bgf_top_1st_pwr_ack_not_okay"); + goto _fail_bgf_top_1st_pwr_ack_not_okay; + } + + /* bit25: BGFSYS_ON_TOP secondary power ack */ + GDL_HW_POLL_CONN_INFRA_ENTRY(CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_ACK_ST_AN_BGFSYS_ON_TOP_PWR_ACK_S, 1, + POLL_DEFAULT, &poll_okay); + if (!poll_okay) { + GDL_LOGE("_fail_bgf_top_2nd_pwr_ack_not_okay"); + goto _fail_bgf_top_2nd_pwr_ack_not_okay; + } + + GDL_WAIT_US(200); + + /* sleep prot */ + if (gps_dl_hw_gps_sleep_prot_ctrl(1) != 0) { + GDL_LOGE("_fail_disable_gps_slp_prot_not_okay"); + goto _fail_disable_gps_slp_prot_not_okay; + } + + /* polling status and version */ + /* Todo: set GPS host csr flag selection */ + /* 0x18060240[3:0] == 4h'2 gps_top_off is GPS_ACTIVE state */ + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_HOST_CSR_TOP_HOST2GPS_DEGUG_SEL_HOST2GPS_DEGUG_SEL, 0x80); + for (i = 0; i < 3; i++) { + GDL_HW_POLL_CONN_INFRA_ENTRY(CONN_HOST_CSR_TOP_GPS_CFG2HOST_DEBUG_GPS_CFG2HOST_DEBUG, 2, + POLL_DEFAULT, &poll_okay); + if (poll_okay) + break; + /* + * TODO: + * if (!gps_dl_reset_level_is_none()) break; + */ + if (i > 0) + GDL_LOGW("_poll_gps_top_off_active, cnt = %d", i + 1); + } + if (!poll_okay) { + GDL_LOGE("_fail_gps_top_off_active_not_okay"); + goto _fail_gps_top_off_active_not_okay; + } + + /* 0x18c21010[31:0] bgf ip version */ + GDL_HW_POLL_GPS_ENTRY(BGF_GPS_CFG_BGF_IP_VERSION_BGFSYS_VERSION, + GDL_HW_BGF_VER, POLL_DEFAULT, &poll_okay); + if (!poll_okay) { + GDL_LOGE("_fail_bgf_ip_ver_not_okay"); + goto _fail_bgf_ip_ver_not_okay; + } + + /* 0x18c21014[7:0] bgf ip cfg */ + GDL_HW_POLL_GPS_ENTRY(BGF_GPS_CFG_BGF_IP_CONFIG_BGFSYS_CONFIG, 0, + POLL_DEFAULT, &poll_okay); + if (!poll_okay) { + GDL_LOGE("_fail_bgf_ip_cfg_not_okay"); + goto _fail_bgf_ip_cfg_not_okay; + } + +#if (GPS_DL_HAS_CONNINFRA_DRV) + /* conninfra driver add an API to do bellow step */ + conninfra_config_setup(); +#else + /* Enable conninfra bus hung detection */ + GDL_HW_WR_CONN_INFRA_REG(0x1800F000, 0xF000001C); +#endif + + /* host csr gps bus debug mode enable 0x18c60000 = 0x10 */ + GDL_HW_WR_GPS_REG(0x80060000, 0x10); + + /* Power on A-die top clock */ +#if (GPS_DL_HAS_CONNINFRA_DRV) + conninfra_adie_top_ck_en_on(CONNSYS_ADIE_CTL_HOST_GPS); +#endif + + /* Enable PLL driver */ + GDL_HW_SET_GPS_ENTRY(GPS_CFG_ON_GPS_CLKGEN1_CTL_CR_GPS_DIGCK_DIV_EN, 1); + + return 0; + +_fail_bgf_ip_cfg_not_okay: +_fail_bgf_ip_ver_not_okay: +_fail_gps_top_off_active_not_okay: +_fail_disable_gps_slp_prot_not_okay: +_fail_bgf_top_2nd_pwr_ack_not_okay: +_fail_bgf_top_1st_pwr_ack_not_okay: + GDL_HW_SET_GPS_FUNC_EN(0); + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_INFRA_CFG_EMI_CTL_GPS_EMI_REQ_GPS, 0); + +_fail_conn_hw_ver_not_okay: + return -1; +} + +int gps_dl_hw_gps_common_off(void) +{ + /* Power off A-die top clock */ +#if (GPS_DL_HAS_CONNINFRA_DRV) + conninfra_adie_top_ck_en_off(CONNSYS_ADIE_CTL_HOST_GPS); +#endif + + if (gps_dl_hw_gps_sleep_prot_ctrl(0) != 0) { + GDL_LOGE("enable sleep prot fail, trigger connsys reset"); + gps_dl_trigger_connsys_reset(); + return -1; + } + + /* GPS SW EMI request + * gps_dl_hw_gps_sw_request_emi_usage(false); + */ + gps_dl_hal_emi_usage_deinit(); + + if (gps_dl_log_reg_rw_is_on(GPS_DL_REG_RW_HOST_CSR_GPS_OFF)) + gps_dl_hw_dump_host_csr_conninfra_info(true); + + /* Disable GPS function */ + GDL_HW_SET_GPS_FUNC_EN(0); + + /* Disable Conninfra BGF */ + GDL_HW_SET_CONN_INFRA_BGF_EN(0); + + return 0; +} + +/* L1 and L5 share same pwr stat and current we can support the bellow case: + * 1. Both L1 and L5 on / off + * 2. Both L1 and L5 enter deep stop mode and wakeup + * 3. L5 stays off, L1 do on / off + * 4. L5 stays off, L1 enter deep stop mode and wakeup + */ +unsigned int g_gps_pwr_stat; +int gps_dl_hw_gps_pwr_stat_ctrl(enum dsp_ctrl_enum ctrl) +{ + bool clk_ext = gps_dl_hal_get_need_clk_ext_flag(GPS_DATA_LINK_ID0); + + switch (ctrl) { + case GPS_L1_DSP_ON: + case GPS_L5_DSP_ON: + case GPS_L1_DSP_OFF: + case GPS_L5_DSP_OFF: + GDL_HW_SET_GPS_ENTRY(GPS_AON_TOP_DSLEEP_CTL_GPS_PWR_STAT, 0); + GDL_HW_SET_GPS_ENTRY(GPS_AON_TOP_DSLEEP_CTL_FORCE_OSC_EN_ON, 0); + g_gps_pwr_stat = 0; + break; + + case GPS_L1_DSP_CLEAR_PWR_STAT: + case GPS_L5_DSP_CLEAR_PWR_STAT: + gps_dl_hw_print_ms_counter_status(); + GDL_HW_SET_GPS_ENTRY(GPS_AON_TOP_DSLEEP_CTL_GPS_PWR_STAT, 0); + GDL_HW_SET_GPS_ENTRY(GPS_AON_TOP_DSLEEP_CTL_FORCE_OSC_EN_ON, 0); + g_gps_pwr_stat = 0; + break; + + case GPS_L1_DSP_ENTER_DSTOP: + case GPS_L5_DSP_ENTER_DSTOP: + GDL_HW_SET_GPS_ENTRY(GPS_AON_TOP_DSLEEP_CTL_GPS_PWR_STAT, 1); + GDL_HW_SET_GPS_ENTRY(GPS_AON_TOP_DSLEEP_CTL_FORCE_OSC_EN_ON, clk_ext); + gps_dl_hw_print_ms_counter_status(); + g_gps_pwr_stat = 1; + break; + + case GPS_L1_DSP_EXIT_DSTOP: + case GPS_L5_DSP_EXIT_DSTOP: + /* do nothing */ + gps_dl_hw_print_ms_counter_status(); + break; + + case GPS_L1_DSP_ENTER_DSLEEP: + case GPS_L5_DSP_ENTER_DSLEEP: + GDL_HW_SET_GPS_ENTRY(GPS_AON_TOP_DSLEEP_CTL_GPS_PWR_STAT, 3); + GDL_HW_SET_GPS_ENTRY(GPS_AON_TOP_DSLEEP_CTL_FORCE_OSC_EN_ON, clk_ext); + g_gps_pwr_stat = 3; + break; + + case GPS_L1_DSP_EXIT_DSLEEP: + case GPS_L5_DSP_EXIT_DSLEEP: + /* do nothong */ + break; + + default: + break; + } + + return 0; +} + +int gps_dl_hw_gps_dsp_ctrl(enum dsp_ctrl_enum ctrl) +{ + bool poll_okay; + bool dsp_off_done; + + switch (ctrl) { + case GPS_L1_DSP_ON: + case GPS_L1_DSP_EXIT_DSTOP: + case GPS_L1_DSP_EXIT_DSLEEP: + gps_dl_hw_gps_pwr_stat_ctrl(ctrl); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_CR_RGU_GPS_L1_ON, 1); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_CR_RGU_GPS_L1_SOFT_RST_B, 1); + GDL_HW_POLL_GPS_ENTRY(GPS_CFG_ON_GPS_L1_SLP_PWR_CTL_GPS_L1_SLP_PWR_CTL_CS, 3, + POLL_DEFAULT, &poll_okay); + if (!poll_okay) { + GDL_LOGE("ctrl = %d fail", ctrl); + return -1; + } + + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_MEM_DLY_CTL_RGU_GPSSYS_L1_MEM_ADJ_DLY_EN, 1); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DLY_CHAIN_CTL_RGU_GPS_L1_MEM_PDN_DELAY_DUMMY_NUM, 5); + gps_dl_wait_us(100); /* 3 x 32k clk ~= 100us */ + gps_dl_hw_usrt_ctrl(GPS_DATA_LINK_ID0, + true, gps_dl_is_dma_enabled(), gps_dl_is_1byte_mode()); + break; + + case GPS_L1_DSP_CLEAR_PWR_STAT: + gps_dl_hw_gps_pwr_stat_ctrl(ctrl); + return 0; + + case GPS_L1_DSP_OFF: + case GPS_L1_DSP_ENTER_DSTOP: + case GPS_L1_DSP_ENTER_DSLEEP: + gps_dl_hw_usrt_ctrl(GPS_DATA_LINK_ID0, + false, gps_dl_is_dma_enabled(), gps_dl_is_1byte_mode()); + + /* poll */ + dsp_off_done = gps_dl_hw_gps_dsp_is_off_done(GPS_DATA_LINK_ID0); + + gps_dl_hw_gps_pwr_stat_ctrl(ctrl); + if (ctrl == GPS_L1_DSP_ENTER_DSLEEP) { + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPPRAM_PDN_EN_RGU_GPS_L1_PRAM_HWCTL_PDN, 0); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPPRAM_SLP_EN_RGU_GPS_L1_PRAM_HWCTL_SLP, 0x1FF); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPXRAM_PDN_EN_RGU_GPS_L1_XRAM_HWCTL_PDN, 0); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPXRAM_SLP_EN_RGU_GPS_L1_XRAM_HWCTL_SLP, 0xF); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPYRAM_PDN_EN_RGU_GPS_L1_YRAM_HWCTL_PDN, 0); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPYRAM_SLP_EN_RGU_GPS_L1_YRAM_HWCTL_SLP, 0x1FF); + } else if (ctrl == GPS_L1_DSP_ENTER_DSTOP) { + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPPRAM_PDN_EN_RGU_GPS_L1_PRAM_HWCTL_PDN, 0); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPPRAM_SLP_EN_RGU_GPS_L1_PRAM_HWCTL_SLP, 0x1FF); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPXRAM_PDN_EN_RGU_GPS_L1_XRAM_HWCTL_PDN, 0); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPXRAM_SLP_EN_RGU_GPS_L1_XRAM_HWCTL_SLP, 0xF); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPYRAM_PDN_EN_RGU_GPS_L1_YRAM_HWCTL_PDN, 0x1FF); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPYRAM_SLP_EN_RGU_GPS_L1_YRAM_HWCTL_SLP, 0); + } else { + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPPRAM_PDN_EN_RGU_GPS_L1_PRAM_HWCTL_PDN, 0x1FF); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPPRAM_SLP_EN_RGU_GPS_L1_PRAM_HWCTL_SLP, 0); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPXRAM_PDN_EN_RGU_GPS_L1_XRAM_HWCTL_PDN, 0xF); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPXRAM_SLP_EN_RGU_GPS_L1_XRAM_HWCTL_SLP, 0); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPYRAM_PDN_EN_RGU_GPS_L1_YRAM_HWCTL_PDN, 0x1FF); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPYRAM_SLP_EN_RGU_GPS_L1_YRAM_HWCTL_SLP, 0); + } + + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_CR_RGU_GPS_L1_SOFT_RST_B, 0); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_CR_RGU_GPS_L1_ON, 0); + + if (dsp_off_done) + return 0; + else + return -1; + + case GPS_L5_DSP_ON: + case GPS_L5_DSP_EXIT_DSTOP: + case GPS_L5_DSP_EXIT_DSLEEP: + gps_dl_hw_gps_pwr_stat_ctrl(ctrl); + + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_CR_RGU_GPS_L5_ON, 1); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_CR_RGU_GPS_L5_SOFT_RST_B, 1); + GDL_HW_POLL_GPS_ENTRY(GPS_CFG_ON_GPS_L5_SLP_PWR_CTL_GPS_L5_SLP_PWR_CTL_CS, 3, + POLL_DEFAULT, &poll_okay); + if (!poll_okay) { + GDL_LOGE("ctrl = %d fail", ctrl); + return -1; + } + + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_MEM_DLY_CTL_RGU_GPSSYS_L5_MEM_ADJ_DLY_EN, 1); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DLY_CHAIN_CTL_RGU_GPS_L5_MEM_PDN_DELAY_DUMMY_NUM, 9); + gps_dl_wait_us(100); /* 3 x 32k clk ~= 1ms */ + gps_dl_hw_usrt_ctrl(GPS_DATA_LINK_ID1, + true, gps_dl_is_dma_enabled(), gps_dl_is_1byte_mode()); + break; + + case GPS_L5_DSP_CLEAR_PWR_STAT: + gps_dl_hw_gps_pwr_stat_ctrl(ctrl); + return 0; + + case GPS_L5_DSP_OFF: + case GPS_L5_DSP_ENTER_DSTOP: + case GPS_L5_DSP_ENTER_DSLEEP: + gps_dl_hw_usrt_ctrl(GPS_DATA_LINK_ID1, + false, gps_dl_is_dma_enabled(), gps_dl_is_1byte_mode()); + + /* poll */ + dsp_off_done = gps_dl_hw_gps_dsp_is_off_done(GPS_DATA_LINK_ID1); + + gps_dl_hw_gps_pwr_stat_ctrl(ctrl); + if (ctrl == GPS_L5_DSP_ENTER_DSLEEP) { + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPPRAM_PDN_EN_RGU_GPS_L5_PRAM_HWCTL_PDN, 0); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPPRAM_SLP_EN_RGU_GPS_L5_PRAM_HWCTL_SLP, 0x3FF); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPXRAM_PDN_EN_RGU_GPS_L5_XRAM_HWCTL_PDN, 0); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPXRAM_SLP_EN_RGU_GPS_L5_XRAM_HWCTL_SLP, 0xF); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPYRAM_PDN_EN_RGU_GPS_L5_YRAM_HWCTL_PDN, 0); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPYRAM_SLP_EN_RGU_GPS_L5_YRAM_HWCTL_SLP, 0x3FF); + } else if (ctrl == GPS_L5_DSP_ENTER_DSTOP) { + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPPRAM_PDN_EN_RGU_GPS_L5_PRAM_HWCTL_PDN, 0); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPPRAM_SLP_EN_RGU_GPS_L5_PRAM_HWCTL_SLP, 0x3FF); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPXRAM_PDN_EN_RGU_GPS_L5_XRAM_HWCTL_PDN, 0); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPXRAM_SLP_EN_RGU_GPS_L5_XRAM_HWCTL_SLP, 0xF); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPYRAM_PDN_EN_RGU_GPS_L5_YRAM_HWCTL_PDN, 0x3FF); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPYRAM_SLP_EN_RGU_GPS_L5_YRAM_HWCTL_SLP, 0); + } else { + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPPRAM_PDN_EN_RGU_GPS_L5_PRAM_HWCTL_PDN, 0x3FF); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPPRAM_SLP_EN_RGU_GPS_L5_PRAM_HWCTL_SLP, 0); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPXRAM_PDN_EN_RGU_GPS_L5_XRAM_HWCTL_PDN, 0xF); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPXRAM_SLP_EN_RGU_GPS_L5_XRAM_HWCTL_SLP, 0); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPYRAM_PDN_EN_RGU_GPS_L5_YRAM_HWCTL_PDN, 0x3FF); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPYRAM_SLP_EN_RGU_GPS_L5_YRAM_HWCTL_SLP, 0); + } + + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_CR_RGU_GPS_L5_SOFT_RST_B, 0); + GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_CR_RGU_GPS_L5_ON, 0); + + if (dsp_off_done) + return 0; + else + return -1; + + default: + return -1; + } + + return 0; +} + +bool gps_dl_hw_gps_dsp_is_off_done(enum gps_dl_link_id_enum link_id) +{ + int i; + bool done; + bool show_log; + + /* TODO: move it to proper place */ + if (GPS_DSP_ST_HW_STOP_MODE == gps_dsp_state_get(link_id)) { + /* expect it change to RESET_DONE after this call */ + if (!gps_dl_hal_mcub_flag_handler(link_id)) { + GDL_LOGXW(link_id, "pre-check fail"); + return false; + } + } + + if (GPS_DSP_ST_RESET_DONE == gps_dsp_state_get(link_id)) { + GDL_LOGXD(link_id, "1st return, done = 1"); + return true; + } + + i = 0; + + show_log = gps_dl_set_show_reg_rw_log(true); + do { + /* MCUB IRQ already mask at this time */ + if (!gps_dl_hal_mcub_flag_handler(link_id)) { + done = false; + break; + } + + done = true; + while (GPS_DSP_ST_RESET_DONE != gps_dsp_state_get(link_id)) { + /* poll 10ms */ + if (i > 10) { + done = false; + break; + } + gps_dl_wait_us(1000); + + /* read dummy cr confirm dsp state for debug */ + if (GPS_DATA_LINK_ID0 == link_id) + GDL_HW_RD_GPS_REG(0x80073160); + else if (GPS_DATA_LINK_ID1 == link_id) + GDL_HW_RD_GPS_REG(0x80073134); + + if (!gps_dl_hal_mcub_flag_handler(link_id)) { + done = false; + break; + } + i++; + } + } while (0); + gps_dl_set_show_reg_rw_log(show_log); + GDL_LOGXW(link_id, "2nd return, done = %d, i = %d", done, i); + return done; +} + +void gps_dl_hw_gps_adie_force_off(void) +{ +#if GPS_DL_HAS_CONNINFRA_DRV + unsigned int spi_data; + int rd_status; + int wr_status; + + /* TOP: 0xFC[1:0] = 2'b11 */ + spi_data = 0; + rd_status = conninfra_spi_read(SYS_SPI_TOP, 0xFC, &spi_data); + ASSERT_ZERO(rd_status, GDL_VOIDF()); + GDL_LOGW("spi_data = 0x%x", spi_data); + wr_status = conninfra_spi_write(SYS_SPI_TOP, 0xFC, spi_data | 3UL); + ASSERT_ZERO(wr_status, GDL_VOIDF()); + + /* TOP: 0xA0C[31:0] = 0xFFFFFFFF; 0xAFC[31:0] = 0xFFFFFFFF */ + wr_status = conninfra_spi_write(SYS_SPI_TOP, 0xA0C, 0xFFFFFFFF); + ASSERT_ZERO(wr_status, GDL_VOIDF()); + wr_status = conninfra_spi_write(SYS_SPI_TOP, 0xAFC, 0xFFFFFFFF); + ASSERT_ZERO(wr_status, GDL_VOIDF()); + + /* TOP: 0xF8[0] = 1'b0 */ + spi_data = 0; + rd_status = conninfra_spi_read(SYS_SPI_TOP, 0xF8, &spi_data); + ASSERT_ZERO(rd_status, GDL_VOIDF()); + GDL_LOGW("spi_data = 0x%x", spi_data); + wr_status = conninfra_spi_write(SYS_SPI_TOP, 0xF8, spi_data & (~1UL)); + ASSERT_ZERO(wr_status, GDL_VOIDF()); + + /* GPS: 0x0[15] = 1'b1 */ + spi_data = 0; + rd_status = conninfra_spi_read(SYS_SPI_GPS, 0x0, &spi_data); + ASSERT_ZERO(rd_status, GDL_VOIDF()); + GDL_LOGW("spi_data = 0x%x", spi_data); + wr_status = conninfra_spi_write(SYS_SPI_GPS, 0x0, spi_data & (1UL << 15)); + ASSERT_ZERO(wr_status, GDL_VOIDF()); + + /* TOP: 0xF8[0] = 1'b1 */ + spi_data = 0; + rd_status = conninfra_spi_read(SYS_SPI_TOP, 0xF8, &spi_data); + ASSERT_ZERO(rd_status, GDL_VOIDF()); + GDL_LOGW("spi_data = 0x%x", spi_data); + wr_status = conninfra_spi_write(SYS_SPI_TOP, 0xF8, spi_data | 1UL); + ASSERT_ZERO(wr_status, GDL_VOIDF()); + + /* GPS: 0x0[15] = 1'b1 */ + spi_data = 0; + rd_status = conninfra_spi_read(SYS_SPI_GPS, 0x0, &spi_data); + ASSERT_ZERO(rd_status, GDL_VOIDF()); + GDL_LOGW("spi_data = 0x%x", spi_data); + wr_status = conninfra_spi_write(SYS_SPI_GPS, 0x0, spi_data & (1UL << 15)); + ASSERT_ZERO(wr_status, GDL_VOIDF()); + + /* TOP: 0xF8[0] = 1'b0 */ + spi_data = 0; + rd_status = conninfra_spi_read(SYS_SPI_TOP, 0xF8, &spi_data); + ASSERT_ZERO(rd_status, GDL_VOIDF()); + GDL_LOGW("spi_data = 0x%x", spi_data); + wr_status = conninfra_spi_write(SYS_SPI_TOP, 0xF8, spi_data & (~1UL)); + ASSERT_ZERO(wr_status, GDL_VOIDF()); + + /* TOP: 0xA0C[31:0] = 0; 0xAFC[31:0] = 0 */ + wr_status = conninfra_spi_write(SYS_SPI_TOP, 0xA0C, 0); + ASSERT_ZERO(wr_status, GDL_VOIDF()); + wr_status = conninfra_spi_write(SYS_SPI_TOP, 0xAFC, 0); + ASSERT_ZERO(wr_status, GDL_VOIDF()); + + /* TOP: 0xFC[1:0] = 2'b00 */ + rd_status = conninfra_spi_read(SYS_SPI_TOP, 0xFC, &spi_data); + ASSERT_ZERO(rd_status, GDL_VOIDF()); + GDL_LOGW("spi_data = 0x%x", spi_data); + wr_status = conninfra_spi_write(SYS_SPI_TOP, 0xFC, spi_data & (~3UL)); + ASSERT_ZERO(wr_status, GDL_VOIDF()); +#else + GDL_LOGE("no conninfra driver"); +#endif +} + +void gps_dl_hw_gps_dump_top_rf_cr(void) +{ +#if GPS_DL_HAS_CONNINFRA_DRV + unsigned int spi_data; + int rd_status; + int i; + const int rd_addr_list[] = {0x03C, 0xA18, 0xA1C, 0x0C8, 0xA00, 0x0B4, 0x34C}; + int rd_addr; + + for (i = 0; i < ARRAY_SIZE(rd_addr_list); i++) { + rd_addr = rd_addr_list[i]; + spi_data = 0; + rd_status = conninfra_spi_read(SYS_SPI_TOP, rd_addr, &spi_data); + GDL_LOGW("rd: addr = 0x%x, val = 0x%x, rd_status = %d", + rd_addr, spi_data, rd_status); + } +#else + GDL_LOGE("no conninfra driver"); +#endif +} + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_priv_util.h b/drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_priv_util.h new file mode 100644 index 0000000000000..46c9276800550 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_priv_util.h @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _GPS_DL_HW_UTIL_H +#define _GPS_DL_HW_UTIL_H + +#include "gps_dl_config.h" +#include "gps_dl_hw_type.h" +#include "gps_dl_time_tick.h" + +enum GPS_DL_BUS_ENUM { + GPS_DL_GPS_BUS, + GPS_DL_BGF_BUS, + GPS_DL_CONN_INFRA_BUS, + GPS_DL_BUS_NUM +}; + +enum gps_dl_bus_rw_opt_enum { + WR_NO_READ_BACK, + RW_DO_CHECK, + RW_FORCE_PRINT, + RW_FULL_PRINT, + RW_OPT_MAX = 32 +}; +#define BMASK_WR_NO_READ_BACK (1UL << WR_NO_READ_BACK) +#define BMASK_RW_DO_CHECK (1UL << RW_DO_CHECK) +#define BMASK_RW_FORCE_PRINT (1UL << RW_FORCE_PRINT) +#define BMASK_RW_FULL_PRINT (1UL << RW_FULL_PRINT) + +void gps_dl_bus_wr_opt(enum GPS_DL_BUS_ENUM bus_id, unsigned int bus_addr, unsigned int val, + unsigned int opt_bitmask); +unsigned int gps_dl_bus_rd_opt(enum GPS_DL_BUS_ENUM bus_id, unsigned int bus_addr, + unsigned int opt_bitmask); + + +/* the function will convert bus addr to host-view addr by remaping */ +#if 0 +void gps_dl_bus_wr32(u32 bus_addr, u32 val); +u32 gps_dl_bus_rd32(u32 bus_addr); +#endif +void gps_dl_bus_write(enum GPS_DL_BUS_ENUM bus_id, unsigned int bus_addr, unsigned int val); +void gps_dl_bus_write_no_rb(enum GPS_DL_BUS_ENUM bus_id, unsigned int bus_addr, unsigned int val); +unsigned int gps_dl_bus_read(enum GPS_DL_BUS_ENUM bus_id, unsigned int bus_addr); +void gps_dl_bus_check_and_print(unsigned int host_addr); + + +/* provide function/macro declaration for c files under hal folder */ + +/* todo: writel, mb */ +#define ADDR(Field) (Field##_ADDR) +#define MASK(Field) (Field##_MASK) +#define SHFT(Field) (Field##_SHFT) + +/* TODO: using volatile in kernel is almost an error */ +#if 0 +#define DL_SET_ENTRY(Field, Value) \ + { conn_reg * addr = ADDR(Field); \ + *addr = ((((conn_reg)(Value) << SHFT(Field)) \ + & MASK(Field)) | (*addr & ~MASK(Field))) ; } + +#define DL_GET_ENTRY(Field) \ + ((*ADDR(Field) & (MASK(Field))) >> SHFT(Field)) +#endif + +/* todo + * 1. iomap the region to access or just writel can work? + * 2. using volatile in kernel is almost an error. Replace it with accessor functions + */ +#if GPS_DL_ON_CTP +#define GPS_DL_HOST_REG_WR(host_addr, val) ((*(conn_reg *)host_addr) = (val)) +#define GPS_DL_HOST_REG_RD(host_addr) (*(conn_reg *)host_addr) +#else +#define GPS_DL_HOST_REG_WR(host_addr, val) do {} while (0) +#define GPS_DL_HOST_REG_RD(host_addr) (0) +#endif + +#define GDL_HW_WR_CONN_INFRA_REG(Addr, Value) gps_dl_bus_write(GPS_DL_CONN_INFRA_BUS, Addr, Value) +#define GDL_HW_RD_CONN_INFRA_REG(Addr) gps_dl_bus_read(GPS_DL_CONN_INFRA_BUS, Addr) + +#define GDL_HW_WR_BGF_REG(Addr, Value) gps_dl_bus_write(GPS_DL_BGF_BUS, Addr, Value) +#define GDL_HW_RD_BGF_REG(Addr) gps_dl_bus_read(GPS_DL_BGF_BUS, Addr) + +#define GDL_HW_WR_GPS_REG(Addr, Value) gps_dl_bus_write(GPS_DL_GPS_BUS, Addr, Value) +#define GDL_HW_RD_GPS_REG(Addr) gps_dl_bus_read(GPS_DL_GPS_BUS, Addr) + + +#define GDL_HW_SET_ENTRY(Bus_ID, Field, Value) do { \ + conn_reg val; \ + val = gps_dl_bus_read(Bus_ID, ADDR(Field)); \ + val &= (~MASK(Field)); \ + val |= ((Value << SHFT(Field)) & MASK(Field)); \ + gps_dl_bus_write(Bus_ID, ADDR(Field), val); \ + } while (0) + +#define GDL_HW_GET_ENTRY(Bus_ID, Field) \ + ((gps_dl_bus_read(Bus_ID, ADDR(Field)) & (MASK(Field))) >> SHFT(Field)) + +#define GDL_HW_EXTRACT_ENTRY(Field, Val) \ + ((Val & (MASK(Field))) >> SHFT(Field)) + +#define POLL_INTERVAL_US (100) +#define POLL_US (1) +#define POLL_1_TIME (0) +#define POLL_FOREVER (-1) +#define POLL_DEFAULT (1000 * POLL_US) +#if (GPS_DL_ON_CTP || GPS_DL_ON_LINUX) +#define GDL_HW_POLL_ENTRY_VERBOSE(Bus_ID, Field, pIsOkay, pLastValue, TimeoutUsec, condExpected) \ + do { \ + if (pIsOkay != NULL) { \ + *pIsOkay = false; \ + } \ + if (POLL_1_TIME == TimeoutUsec) { \ + if (pLastValue != NULL) { \ + *pLastValue = GDL_HW_GET_ENTRY(Bus_ID, Field); \ + } \ + if ((condExpected)) { \ + if (pIsOkay != NULL) { \ + *pIsOkay = true; \ + } \ + } \ + } else if (TimeoutUsec > 0) { \ + unsigned int poll_wait_cnt = 0; \ + while (true) { \ + if (pLastValue != NULL) { \ + *pLastValue = GDL_HW_GET_ENTRY(Bus_ID, Field); \ + } \ + if ((condExpected)) { \ + if (pIsOkay != NULL) { \ + *pIsOkay = true; \ + } \ + break; \ + } \ + if (poll_wait_cnt >= TimeoutUsec) { \ + break; \ + } \ + gps_dl_wait_us(POLL_INTERVAL_US); \ + poll_wait_cnt += POLL_INTERVAL_US; \ + } \ + } else if (TimeoutUsec <= POLL_FOREVER) { \ + while (true) { \ + if (pLastValue != NULL) { \ + *pLastValue = GDL_HW_GET_ENTRY(Bus_ID, Field); \ + } \ + if ((condExpected)) { \ + if (pIsOkay != NULL) { \ + *pIsOkay = true; \ + } \ + break; \ + } \ + gps_dl_wait_us(POLL_INTERVAL_US); \ + } \ + } \ + } while (0) + +#define GDL_HW_POLL_ENTRY(Bus_ID, Field, ValueExpected, TimeoutUsec, pIsOkay) \ + do { \ + unsigned int gdl_hw_poll_value; \ + GDL_HW_POLL_ENTRY_VERBOSE(Bus_ID, Field, \ + pIsOkay, &gdl_hw_poll_value, \ + TimeoutUsec, (gdl_hw_poll_value == ValueExpected)); \ + } while (0) +#else +#define GDL_HW_POLL_ENTRY(Bus_ID, Field, ValueExpected, TimeoutUsec, pIsOkay) \ + do { \ + if (ValueExpected == GDL_HW_GET_ENTRY(Bus_ID, Field)) { \ + ; \ + } \ + } while (0) +#endif + + + +#define GDL_HW_SET_CONN_INFRA_ENTRY(Field, Value) GDL_HW_SET_ENTRY(GPS_DL_CONN_INFRA_BUS, Field, Value) +#define GDL_HW_GET_CONN_INFRA_ENTRY(Field) GDL_HW_GET_ENTRY(GPS_DL_CONN_INFRA_BUS, Field) +#define GDL_HW_POLL_CONN_INFRA_ENTRY(Field, ValueExpected, TimeoutUsec, pIsOkay) \ + GDL_HW_POLL_ENTRY(GPS_DL_CONN_INFRA_BUS, Field, ValueExpected, TimeoutUsec, pIsOkay) + +#define GDL_HW_SET_BGF_ENTRY(Field, Value) GDL_HW_SET_ENTRY(GPS_DL_BGF_BUS, Field, Value) +#define GDL_HW_GET_BGF_ENTRY(Field) GDL_HW_GET_ENTRY(GPS_DL_BGF_BUS, Field) +#define GDL_HW_POLL_BGF_ENTRY(Field, ValueExpected, TimeoutUsec, pIsOkay) \ + GDL_HW_POLL_ENTRY(GPS_DL_BGF_BUS, Field, ValueExpected, TimeoutUsec, pIsOkay) + +#define GDL_HW_SET_GPS_ENTRY(Field, Value) GDL_HW_SET_ENTRY(GPS_DL_GPS_BUS, Field, Value) +#define GDL_HW_SET_GPS_ENTRY2(LinkID, Value, Field1, Field2) do { \ + if (GPS_DATA_LINK_ID0 == LinkID) \ + GDL_HW_SET_GPS_ENTRY(Field1, Value); \ + else if (GPS_DATA_LINK_ID1 == LinkID) \ + GDL_HW_SET_GPS_ENTRY(Field2, Value); \ + } while (0) + +#define GDL_HW_GET_GPS_ENTRY(Field) GDL_HW_GET_ENTRY(GPS_DL_GPS_BUS, Field) +#define GDL_HW_GET_GPS_ENTRY2(LinkID, Field1, Field2) ( \ + (GPS_DATA_LINK_ID0 == LinkID) ? \ + GDL_HW_GET_GPS_ENTRY(Field1) : \ + ((GPS_DATA_LINK_ID1 == LinkID) ? \ + GDL_HW_GET_GPS_ENTRY(Field2) : 0) \ + ) + +#define GDL_HW_POLL_GPS_ENTRY(Field, ValueExpected, TimeoutUsec, pIsOkay) \ + GDL_HW_POLL_ENTRY(GPS_DL_GPS_BUS, Field, ValueExpected, TimeoutUsec, pIsOkay) + +struct gps_dl_addr_map_entry { + unsigned int host_addr; + unsigned int bus_addr; + unsigned int length; +}; + +unsigned int bgf_bus_to_host(unsigned int bgf_addr); +unsigned int gps_bus_to_host(unsigned int gps_addr); + + +#endif /* _GPS_DL_HW_UTIL_H */ diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_usrt_apb.c b/drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_usrt_apb.c new file mode 100644 index 0000000000000..40a1921dd70bc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_usrt_apb.c @@ -0,0 +1,450 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "gps_dl_config.h" +#include "gps_dl_context.h" +#include "gps_dl_time_tick.h" + +#include "gps_dl_hal.h" +#if GPS_DL_MOCK_HAL +#include "gps_mock_hal.h" +#endif + +#include "gps_dl_hw_api.h" +#include "gps_dl_hw_priv_util.h" + +#include "gps/gps_usrt_apb.h" +#include "gps/gps_l5_usrt_apb.h" +#include "gps/bgf_gps_dma.h" +#include "conn_infra/conn_host_csr_top.h" + +void gps_dl_hw_usrt_rx_irq_enable(enum gps_dl_link_id_enum link_id, bool enable) +{ + if (enable) + GDL_HW_SET_GPS_ENTRY2(link_id, 1, GPS_USRT_APB_APB_INTEN_TXIEN, GPS_L5_USRT_APB_APB_INTEN_TXIEN); + else + GDL_HW_SET_GPS_ENTRY2(link_id, 0, GPS_USRT_APB_APB_INTEN_TXIEN, GPS_L5_USRT_APB_APB_INTEN_TXIEN); +} + +#define GPS_DSP_CFG_BITMASK_ADIE_IS_MT6631 (1UL << 0) +#define GPS_DSP_CFG_BITMASK_MVCD_SPEED_UP (1UL << 1) +#define GPS_DSP_CFG_BITMASK_ADIE_IS_MT6635_E2_OR_AFTER (1UL << 2) +#define GPS_DSP_CFG_BITMASK_USRT_4BYTE_MODE (1UL << 3) +#define GPS_DSP_CFG_BITMASK_COLOCK_USE_TIA (1UL << 6) +#define GPS_DSP_CFG_BITMASK_CLOCK_EXTENSION_WAKEUP (1UL << 7) + +unsigned int gps_dl_hw_get_mcub_a2d1_cfg(enum gps_dl_link_id_enum link_id, bool is_1byte_mode) +{ + unsigned int cfg = 0; + + cfg |= GPS_DSP_CFG_BITMASK_MVCD_SPEED_UP; + cfg |= GPS_DSP_CFG_BITMASK_ADIE_IS_MT6635_E2_OR_AFTER; + if (!is_1byte_mode) + cfg |= GPS_DSP_CFG_BITMASK_USRT_4BYTE_MODE; +#if GPS_DL_USE_TIA + cfg |= GPS_DSP_CFG_BITMASK_COLOCK_USE_TIA; +#endif + if (gps_dl_hal_get_need_clk_ext_flag(link_id)) + cfg |= GPS_DSP_CFG_BITMASK_CLOCK_EXTENSION_WAKEUP; + return cfg; +} + +void gps_dl_hw_usrt_ctrl(enum gps_dl_link_id_enum link_id, + bool is_on, bool is_dma_mode, bool is_1byte_mode) +{ + bool poll_okay; + + if (is_1byte_mode) + GDL_HW_SET_GPS_ENTRY2(link_id, 1, GPS_USRT_APB_APB_CTRL_BYTEN, GPS_L5_USRT_APB_APB_CTRL_BYTEN); + else + GDL_HW_SET_GPS_ENTRY2(link_id, 0, GPS_USRT_APB_APB_CTRL_BYTEN, GPS_L5_USRT_APB_APB_CTRL_BYTEN); + + if (!is_on) { + GDL_HW_SET_GPS_ENTRY2(link_id, 0, GPS_USRT_APB_APB_CTRL_TX_EN, GPS_L5_USRT_APB_APB_CTRL_TX_EN); + GDL_HW_SET_GPS_ENTRY2(link_id, 0, GPS_USRT_APB_APB_CTRL_RX_EN, GPS_L5_USRT_APB_APB_CTRL_RX_EN); + GDL_HW_SET_GPS_ENTRY2(link_id, 0, GPS_USRT_APB_APB_INTEN_TXIEN, GPS_L5_USRT_APB_APB_INTEN_TXIEN); + GDL_HW_SET_GPS_ENTRY2(link_id, 0, GPS_USRT_APB_APB_INTEN_NODAIEN, GPS_L5_USRT_APB_APB_INTEN_NODAIEN); + } else if (is_dma_mode) { + GDL_HW_SET_GPS_ENTRY2(link_id, 1, GPS_USRT_APB_APB_CTRL_TX_EN, GPS_L5_USRT_APB_APB_CTRL_TX_EN); + GDL_HW_SET_GPS_ENTRY2(link_id, 1, GPS_USRT_APB_APB_CTRL_RX_EN, GPS_L5_USRT_APB_APB_CTRL_RX_EN); + GDL_HW_SET_GPS_ENTRY2(link_id, 1, GPS_USRT_APB_APB_INTEN_TXIEN, GPS_L5_USRT_APB_APB_INTEN_TXIEN); + GDL_HW_SET_GPS_ENTRY2(link_id, 1, GPS_USRT_APB_APB_INTEN_NODAIEN, GPS_L5_USRT_APB_APB_INTEN_NODAIEN); + } else { + GDL_HW_SET_GPS_ENTRY2(link_id, 0, GPS_USRT_APB_APB_CTRL_TX_EN, GPS_L5_USRT_APB_APB_CTRL_TX_EN); + GDL_HW_SET_GPS_ENTRY2(link_id, 0, GPS_USRT_APB_APB_CTRL_RX_EN, GPS_L5_USRT_APB_APB_CTRL_RX_EN); + GDL_HW_SET_GPS_ENTRY2(link_id, 1, GPS_USRT_APB_APB_INTEN_TXIEN, GPS_L5_USRT_APB_APB_INTEN_TXIEN); + GDL_HW_SET_GPS_ENTRY2(link_id, 0, GPS_USRT_APB_APB_INTEN_NODAIEN, GPS_L5_USRT_APB_APB_INTEN_NODAIEN); + } + + GDL_HW_SET_GPS_ENTRY2(link_id, gps_dl_hw_get_mcub_a2d1_cfg(link_id, is_1byte_mode), + GPS_USRT_APB_MCU_A2D1_A2D_1, GPS_L5_USRT_APB_MCU_A2D1_A2D_1); + + GDL_HW_SET_GPS_ENTRY2(link_id, 1, GPS_USRT_APB_MCUB_A2DF_A2DF3, GPS_L5_USRT_APB_MCUB_A2DF_A2DF3); + + /* wait ROM okay flag */ + if (link_id == GPS_DATA_LINK_ID0) + GDL_HW_POLL_GPS_ENTRY(GPS_USRT_APB_MCUB_D2AF_D2AF3, 1, POLL_DEFAULT, &poll_okay); + else + GDL_HW_POLL_GPS_ENTRY(GPS_L5_USRT_APB_MCUB_D2AF_D2AF3, 1, POLL_DEFAULT, &poll_okay); +} + +bool gps_dl_hw_usrt_has_set_nodata_flag(enum gps_dl_link_id_enum link_id) +{ + return (bool)GDL_HW_GET_GPS_ENTRY2(link_id, + GPS_USRT_APB_APB_STA_NODAINTB, GPS_L5_USRT_APB_APB_STA_NODAINTB); +} + +void gps_dl_hw_usrt_clear_nodata_irq(enum gps_dl_link_id_enum link_id) +{ + GDL_HW_SET_GPS_ENTRY2(link_id, 1, GPS_USRT_APB_APB_STA_NODAINTB, GPS_L5_USRT_APB_APB_STA_NODAINTB); +} + +void gps_dl_hw_print_usrt_status(enum gps_dl_link_id_enum link_id) +{ + bool show_log; + unsigned int value; + + show_log = gps_dl_set_show_reg_rw_log(true); + if (link_id == GPS_DATA_LINK_ID0) { + value = GDL_HW_RD_GPS_REG(GPS_USRT_APB_APB_STA_ADDR); + value = GDL_HW_RD_GPS_REG(GPS_USRT_APB_MONF_ADDR); + } else if (link_id == GPS_DATA_LINK_ID1) { + value = GDL_HW_RD_GPS_REG(GPS_L5_USRT_APB_APB_STA_ADDR); + value = GDL_HW_RD_GPS_REG(GPS_L5_USRT_APB_MONF_ADDR); + } + gps_dl_set_show_reg_rw_log(show_log); +} + +bool gps_dl_hw_poll_usrt_dsp_rx_empty(enum gps_dl_link_id_enum link_id) +{ + bool poll_okay = false; + + if (link_id == GPS_DATA_LINK_ID0) + GDL_HW_POLL_GPS_ENTRY(GPS_USRT_APB_APB_STA_RX_EMP, 1, 10000 * POLL_US, &poll_okay); + else if (link_id == GPS_DATA_LINK_ID1) + GDL_HW_POLL_GPS_ENTRY(GPS_L5_USRT_APB_APB_STA_RX_EMP, 1, 10000 * POLL_US, &poll_okay); + + if (!poll_okay) + GDL_LOGXE_DRW(link_id, "okay = %d", poll_okay); + + return poll_okay; +} + +enum GDL_RET_STATUS gps_dl_hal_wait_and_handle_until_usrt_has_data( + enum gps_dl_link_id_enum link_id, int timeout_usec) +{ + struct gps_dl_hw_usrt_status_struct usrt_status; + bool last_rw_log_on; + unsigned long tick0, tick1; + + tick0 = gps_dl_tick_get(); + + if (gps_dl_show_reg_wait_log()) + GDL_LOGXD(link_id, "timeout = %d", timeout_usec); + + while (1) { + gps_dl_hw_save_usrt_status_struct(link_id, &usrt_status); + + if (gps_dl_only_show_wait_done_log()) + last_rw_log_on = gps_dl_set_show_reg_rw_log(false); + else + gps_dl_hw_print_usrt_status_struct(link_id, &usrt_status); + + if (GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_TX_IND, usrt_status.state)) { + if (gps_dl_only_show_wait_done_log()) { + gps_dl_set_show_reg_rw_log(last_rw_log_on); + gps_dl_hw_print_usrt_status_struct(link_id, &usrt_status); + gps_dl_hw_save_usrt_status_struct(link_id, &usrt_status); + } + + gps_dl_hal_event_send(GPS_DL_HAL_EVT_D2A_RX_HAS_DATA, link_id); + break; + } + + tick1 = gps_dl_tick_get(); + if (timeout_usec > GPS_DL_RW_NO_TIMEOUT && + gps_dl_tick_delta_to_usec(tick0, tick1) >= timeout_usec) + return GDL_FAIL_TIMEOUT; + + gps_dl_wait_us(GDL_HW_STATUS_POLL_INTERVAL_USEC); + } + + return GDL_OKAY; +} + +enum GDL_RET_STATUS gps_dl_hal_wait_and_handle_until_usrt_has_nodata_or_rx_dma_done( + enum gps_dl_link_id_enum link_id, int timeout_usec, bool to_handle) +{ + struct gps_dl_hw_dma_status_struct dma_status; + struct gps_dl_hw_usrt_status_struct usrt_status; + enum gps_dl_hal_dma_ch_index dma_ch; + bool last_rw_log_on; + unsigned long tick0, tick1; + bool conninfra_okay; + bool do_stop = true; + enum GDL_RET_STATUS ret = GDL_OKAY; + int loop_cnt; + + if (link_id == GPS_DATA_LINK_ID0) + dma_ch = GPS_DL_DMA_LINK0_D2A; + else if (link_id == GPS_DATA_LINK_ID1) + dma_ch = GPS_DL_DMA_LINK1_D2A; + else + return GDL_FAIL; + + if (gps_dl_show_reg_wait_log()) + GDL_LOGXD(link_id, "timeout = %d", timeout_usec); + + tick0 = gps_dl_tick_get(); + loop_cnt = 0; + while (1) { + conninfra_okay = gps_dl_conninfra_is_okay_or_handle_it(NULL, true); + if (!conninfra_okay) { + ret = GDL_FAIL_CONN_NOT_OKAY; + do_stop = false; + break; + } + + gps_dl_hw_save_dma_status_struct(dma_ch, &dma_status); + if (gps_dl_only_show_wait_done_log()) + last_rw_log_on = gps_dl_set_show_reg_rw_log(false); + else + gps_dl_hw_print_dma_status_struct(dma_ch, &dma_status); + + if (GDL_HW_EXTRACT_ENTRY(BGF_GPS_DMA_DMA1_START_STR, dma_status.intr_flag) && + GDL_HW_EXTRACT_ENTRY(BGF_GPS_DMA_DMA1_STATE_STATE, dma_status.state) == 0x01) { + if (gps_dl_only_show_wait_done_log()) { + gps_dl_set_show_reg_rw_log(last_rw_log_on); + gps_dl_hw_print_dma_status_struct(dma_ch, &dma_status); + gps_dl_hw_save_dma_status_struct(dma_ch, &dma_status); + } + + /* DMA has stopped */ + gps_dl_hw_set_dma_stop(dma_ch); + gps_dl_hw_save_dma_status_struct(dma_ch, &dma_status); + gps_dl_hw_print_dma_status_struct(dma_ch, &dma_status); + if (to_handle) + gps_dl_hal_event_send(GPS_DL_HAL_EVT_D2A_RX_DMA_DONE, link_id); + ret = GDL_OKAY; + do_stop = true; + break; + } + + gps_dl_hw_save_usrt_status_struct(link_id, &usrt_status); + if (gps_dl_only_show_wait_done_log()) + last_rw_log_on = gps_dl_set_show_reg_rw_log(false); + else + gps_dl_hw_print_usrt_status_struct(link_id, &usrt_status); + + if (GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_REGE, usrt_status.state) || + GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_NODAINTB, usrt_status.state)) { + if (gps_dl_only_show_wait_done_log()) { + gps_dl_set_show_reg_rw_log(last_rw_log_on); + gps_dl_hw_print_usrt_status_struct(link_id, &usrt_status); + gps_dl_hw_save_usrt_status_struct(link_id, &usrt_status); + } + if (to_handle) + gps_dl_hal_event_send(GPS_DL_HAL_EVT_D2A_RX_HAS_NODATA, link_id); + else { + gps_dl_hw_set_dma_stop(dma_ch); + gps_dl_hw_save_dma_status_struct(dma_ch, &dma_status); + gps_dl_hw_print_dma_status_struct(dma_ch, &dma_status); + } + ret = GDL_OKAY; + do_stop = true; + break; + } + + tick1 = gps_dl_tick_get(); + if (timeout_usec > GPS_DL_RW_NO_TIMEOUT && ( + gps_dl_tick_delta_to_usec(tick0, tick1) >= timeout_usec || + loop_cnt * GDL_HW_STATUS_POLL_INTERVAL_USEC >= timeout_usec)) { + ret = GDL_FAIL_TIMEOUT; + do_stop = false; + break; + } + + gps_dl_wait_us(GDL_HW_STATUS_POLL_INTERVAL_USEC); + loop_cnt++; + } + + tick1 = gps_dl_tick_get(); + GDL_LOGXW(link_id, "d_us = %d, cnt = %d, do_stop = %d, ret = %s", + gps_dl_tick_delta_to_usec(tick0, tick1), loop_cnt, do_stop, gdl_ret_to_name(ret)); + return ret; +} + +void gps_dl_hal_poll_single_link(enum gps_dl_link_id_enum link_id, + unsigned int evt_in, unsigned int *p_evt_out) +{ + unsigned int evt_out = 0; + struct gps_dl_hw_link_status_struct hw_status; + + gps_dl_hw_get_link_status(link_id, &hw_status); + + if (evt_in & (1UL << GPS_DL_POLL_TX_DMA_DONE)) { + if (hw_status.tx_dma_done) { + evt_out |= (1UL << GPS_DL_POLL_TX_DMA_DONE); + gps_dl_isr_a2d_tx_dma_done(link_id); + } + } + + if (evt_in & (1UL << GPS_DL_POLL_RX_DMA_DONE)) { + if (hw_status.rx_dma_done) { + evt_out |= (1UL << GPS_DL_POLL_RX_DMA_DONE); + gps_dl_isr_d2a_rx_dma_done(link_id); + } + } + + if (evt_in & (1UL << GPS_DL_POLL_USRT_HAS_DATA)) { + if (hw_status.usrt_has_data) { + evt_out |= (1UL << GPS_DL_POLL_USRT_HAS_DATA); + gps_dl_isr_usrt_has_data(link_id); + } + } + + if (evt_in & (1UL << GPS_DL_POLL_USRT_HAS_NODATA)) { + if (hw_status.usrt_has_nodata) { + evt_out |= (1UL << GPS_DL_POLL_USRT_HAS_NODATA); + gps_dl_isr_usrt_has_nodata(link_id); + } + } + + *p_evt_out = evt_out; +} + +enum GDL_RET_STATUS gps_dl_hal_poll_event( + unsigned int L1_evt_in, unsigned int L5_evt_in, + unsigned int *pL1_evt_out, unsigned int *pL5_evt_out, unsigned int timeout_usec) +{ + unsigned int L1_evt_out = 0; + unsigned int L5_evt_out = 0; + enum GDL_RET_STATUS ret_val = GDL_OKAY; + unsigned long tick0, tick1; + int take_usec; + + if (L1_evt_in == 0 && L5_evt_in == 0) { + *pL1_evt_out = 0; + *pL5_evt_out = 0; + return GDL_OKAY; + } + + tick0 = gps_dl_tick_get(); + while (1) { + if (L1_evt_in) + gps_dl_hal_poll_single_link(GPS_DATA_LINK_ID0, L1_evt_in, &L1_evt_out); + + if (L5_evt_in) + gps_dl_hal_poll_single_link(GPS_DATA_LINK_ID1, L5_evt_in, &L5_evt_out); + + tick1 = gps_dl_tick_get(); + take_usec = gps_dl_tick_delta_to_usec(tick0, tick1); + + if (L1_evt_out || L5_evt_out) + break; + + GDL_LOGD("tick0 = %ld, tick1 = %ld, usec = %d/%d", + tick0, tick1, take_usec, timeout_usec); + + if (take_usec >= timeout_usec) { + ret_val = GDL_FAIL_TIMEOUT; + break; + } + + gps_dl_wait_us(GDL_HW_STATUS_POLL_INTERVAL_USEC); + } + + GDL_LOGD("ret = %d, L1 = 0x%x, L5 = 0x%x, usec = %d/%d", + ret_val, L1_evt_out, L5_evt_out, take_usec, timeout_usec); + + if (ret_val != GDL_OKAY) + return ret_val; + + /* TODO: read one more time? */ + *pL1_evt_out = L1_evt_out; + *pL5_evt_out = L5_evt_out; + return GDL_OKAY; +} + +int gps_dl_hal_usrt_direct_write(enum gps_dl_link_id_enum link_id, + unsigned char *buf, unsigned int len) +{ + unsigned int reg_val; + unsigned int reg_addr; + int i, j; + + if (link_id == GPS_DATA_LINK_ID0) + reg_addr = GPS_USRT_APB_GPS_APB_DATA_ADDR; + else if (link_id == GPS_DATA_LINK_ID1) + reg_addr = GPS_L5_USRT_APB_GPS_APB_DATA_ADDR; + else + return -1; + + if (gps_dl_is_1byte_mode()) { + for (i = 0; i < len; i++) + gps_dl_bus_write_no_rb(GPS_DL_GPS_BUS, reg_addr, buf[i]); + } else { + for (i = 0; i < len;) { + reg_val = (unsigned int) buf[i++]; + + for (j = 1; j < 4 && i < len; j++, i++) + reg_val |= (((unsigned int) buf[i]) << (j * 8)); + + gps_dl_bus_write_no_rb(GPS_DL_GPS_BUS, reg_addr, reg_val); + } + } + + return 0; +} + +int gps_dl_hal_usrt_direct_read(enum gps_dl_link_id_enum link_id, + unsigned char *buf, unsigned int len) +{ + unsigned int reg_val; + unsigned int reg_addr; + struct gps_dl_hw_link_status_struct hw_status; + int i; + + if (link_id == GPS_DATA_LINK_ID0) + reg_addr = GPS_USRT_APB_GPS_APB_DATA_ADDR; + else if (link_id == GPS_DATA_LINK_ID1) + reg_addr = GPS_L5_USRT_APB_GPS_APB_DATA_ADDR; + else + return -1; + + /* GPS_USRT_APB_APB_STA_TXINTB_SHFT */ + /* APB_STA[7:0]: 0x22000030 -> 0x20000009 -> 0x22000019 -> 0x22000030 */ + do { + gps_dl_hw_get_link_status(link_id, &hw_status); + } while (!hw_status.usrt_has_data); + + for (i = 0; i < len; ) { + reg_val = GDL_HW_RD_GPS_REG(reg_addr); + + if (gps_dl_is_1byte_mode()) + buf[i++] = (unsigned char)reg_val; + else { + buf[i++] = (unsigned char)(reg_val >> 0); + buf[i++] = (unsigned char)(reg_val >> 8); + buf[i++] = (unsigned char)(reg_val >> 16); + buf[i++] = (unsigned char)(reg_val >> 24); + } + + gps_dl_hw_get_link_status(link_id, &hw_status); + if (!hw_status.usrt_has_data) /* no need: hw_status.usrt_has_nodata */ + break; + } + + GDL_LOGXD(link_id, "read len = %d", i); + return i; +} + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_util.c b/drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_util.c new file mode 100644 index 0000000000000..7c7398e147580 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/gps_dl_hw_util.c @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "gps_dl_config.h" +#include "gps_dl_context.h" +#include "gps_dl_hw_priv_util.h" +#include "gps_dl_subsys_reset.h" + +#if GPS_DL_ON_LINUX +#include +#include +#include +#include "gps_dl_linux.h" +#if GPS_DL_HAS_PLAT_DRV +#include "gps_dl_linux_plat_drv.h" +#endif +#elif GPS_DL_ON_CTP +#include "kernel_to_ctp.h" +#endif + +unsigned int gps_dl_bus_to_host_addr(enum GPS_DL_BUS_ENUM bus_id, unsigned int bus_addr) +{ + unsigned int host_addr = 0; + + switch (bus_id) { + case GPS_DL_GPS_BUS: + host_addr = gps_bus_to_host(bus_addr); + break; + case GPS_DL_BGF_BUS: + host_addr = bgf_bus_to_host(bus_addr); + break; + case GPS_DL_CONN_INFRA_BUS: + host_addr = bus_addr; + break; + default: + host_addr = 0; + } + + return host_addr; +} + +void gps_dl_bus_wr_opt(enum GPS_DL_BUS_ENUM bus_id, unsigned int bus_addr, unsigned int val, + unsigned int opt_bitmask) +{ + bool no_read_back = !!(opt_bitmask & BMASK_WR_NO_READ_BACK); + bool do_check = !!(opt_bitmask & BMASK_RW_DO_CHECK); + bool force_print = !!(opt_bitmask & BMASK_RW_FORCE_PRINT); + bool full_print = !!(opt_bitmask & BMASK_RW_FULL_PRINT); + bool print_vir_addr = false; + + unsigned int read_back_val = 0; + unsigned int host_addr = gps_dl_bus_to_host_addr(bus_id, bus_addr); +#if GPS_DL_ON_LINUX +#if GPS_DL_HAS_PLAT_DRV + void __iomem *host_vir_addr = gps_dl_host_addr_to_virt(host_addr); +#else + void __iomem *host_vir_addr = phys_to_virt(host_addr); +#endif +#else + void *host_vir_addr = NULL; +#endif + + /* + * For linux preparation and checking + */ +#if GPS_DL_ON_LINUX + if (host_vir_addr == NULL) { + GDL_LOGW_RRW("bus_id = %d, addr = 0x%p/0x%08x/0x%08x, NULL!", + bus_id, host_vir_addr, host_addr, bus_addr); + return; + } + print_vir_addr = true; + + if (do_check) { + /* gps_dl_conninfra_not_readable_show_warning(host_addr); */ + gps_dl_bus_check_and_print(host_addr); + } +#endif /* GPS_DL_ON_LINUX */ + + /* + * Do writing + */ +#if GPS_DL_HW_IS_MOCK + /* do nothing if it's mock */ +#elif GPS_DL_ON_LINUX + gps_dl_linux_sync_writel(val, host_vir_addr); +#else + GPS_DL_HOST_REG_WR(host_addr, val); +#endif + + /* + * Do reading back + */ + if (!no_read_back) { +#if GPS_DL_HW_IS_MOCK + /* do nothing if it's mock */ +#elif GPS_DL_ON_LINUX + read_back_val = __raw_readl(host_vir_addr); +#else + read_back_val = GPS_DL_HOST_REG_RD(host_addr); +#endif + } + if (!(gps_dl_show_reg_rw_log() || force_print)) + return; + + /* + * Do printing if need + */ + if (no_read_back && (!full_print)) { + GDL_LOGI_RRW("bus_id = %d, addr = 0x%08x, w_val = 0x%08x", + bus_id, host_addr, val); + } else if (no_read_back && (full_print && !print_vir_addr)) { + GDL_LOGI_RRW("bus_id = %d, addr = 0x%08x/0x%08x, w_val = 0x%08x", + bus_id, host_addr, bus_addr, val); + } else if (no_read_back && (full_print && print_vir_addr)) { + GDL_LOGI_RRW("bus_id = %d, addr = 0x%p/0x%08x/0x%08x, w_val = 0x%08x", + bus_id, host_vir_addr, host_addr, bus_addr, val); + } else if (!no_read_back && (!full_print)) { + GDL_LOGI_RRW("bus_id = %d, addr = 0x%08x, w_val = 0x%08x, r_back = 0x%08x", + bus_id, host_addr, val, read_back_val); + } else if (!no_read_back && (full_print && !print_vir_addr)) { + GDL_LOGI_RRW("bus_id = %d, addr = 0x%08x/0x%08x, w_val = 0x%08x, r_back = 0x%08x", + bus_id, host_addr, bus_addr, val, read_back_val); + } else { + /* if (!no_read_back && (full_print && print_vir_addr)) */ + GDL_LOGI_RRW("bus_id = %d, addr = 0x%p/0x%08x/0x%08x, w_val = 0x%08x, r_back = 0x%08x", + bus_id, host_vir_addr, host_addr, bus_addr, val, read_back_val); + } +} + +void gps_dl_bus_write(enum GPS_DL_BUS_ENUM bus_id, unsigned int bus_addr, unsigned int val) +{ + /* gps_dl_bus_wr_opt(bus_id, bus_addr, val, BMASK_RW_DO_CHECK); */ + gps_dl_bus_wr_opt(bus_id, bus_addr, val, 0); +} + +void gps_dl_bus_write_no_rb(enum GPS_DL_BUS_ENUM bus_id, unsigned int bus_addr, unsigned int val) +{ + gps_dl_bus_wr_opt(bus_id, bus_addr, val, BMASK_WR_NO_READ_BACK); +} + +unsigned int gps_dl_bus_rd_opt(enum GPS_DL_BUS_ENUM bus_id, unsigned int bus_addr, + unsigned int opt_bitmask) +{ + bool do_check = !!(opt_bitmask & BMASK_RW_DO_CHECK); + bool force_print = !!(opt_bitmask & BMASK_RW_FORCE_PRINT); + bool full_print = !!(opt_bitmask & BMASK_RW_FULL_PRINT); + bool print_vir_addr = false; + + unsigned int val = 0; + unsigned int host_addr = gps_dl_bus_to_host_addr(bus_id, bus_addr); +#if GPS_DL_ON_LINUX +#if GPS_DL_HAS_PLAT_DRV + void __iomem *host_vir_addr = gps_dl_host_addr_to_virt(host_addr); +#else + void __iomem *host_vir_addr = phys_to_virt(host_addr); +#endif +#else + void *host_vir_addr = NULL; +#endif + + /* + * For linux preparation and checking + */ +#if GPS_DL_ON_LINUX + if (host_vir_addr == NULL) { + GDL_LOGW_RRW("bus_id = %d, addr = 0x%p/0x%08x/0x%08x, NULL!", + bus_id, host_vir_addr, host_addr, bus_addr); + return 0; + } + print_vir_addr = true; + + if (do_check) { + /* gps_dl_conninfra_not_readable_show_warning(host_addr); */ + gps_dl_bus_check_and_print(host_addr); + } +#endif /* GPS_DL_ON_LINUX */ + + /* + * Do reading + */ +#if GPS_DL_HW_IS_MOCK + /* do nothing if it's mock */ +#elif GPS_DL_ON_LINUX + val = __raw_readl(host_vir_addr); +#else + val = GPS_DL_HOST_REG_RD(host_addr); +#endif + if (!(gps_dl_show_reg_rw_log() || force_print)) + return val; + + /* + * Do printing if need + */ + if (!full_print) { + GDL_LOGI_RRW("bus_id = %d, addr = 0x%08x, r_val = 0x%08x", + bus_id, host_addr, val); + } else if (full_print && !print_vir_addr) { + GDL_LOGI_RRW("bus_id = %d, addr = 0x%08x/0x%08x, r_val = 0x%08x", + bus_id, host_addr, bus_addr, val); + } else { + /* if (full_print && print_vir_addr) */ + GDL_LOGI_RRW("bus_id = %d, addr = 0x%p/0x%08x/0x%08x, r_val = 0x%08x", + bus_id, host_vir_addr, host_addr, bus_addr, val); + } + return val; +} + +unsigned int gps_dl_bus_read(enum GPS_DL_BUS_ENUM bus_id, unsigned int bus_addr) +{ + /* return gps_dl_bus_rd_opt(bus_id, bus_addr, BMASK_RW_DO_CHECK); */ + return gps_dl_bus_rd_opt(bus_id, bus_addr, 0); +} + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_host_csr_top.h b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_host_csr_top.h new file mode 100644 index 0000000000000..3b7edcff8eb8c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_host_csr_top.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ +#ifndef __CONN_HOST_CSR_TOP_REGS_H__ +#define __CONN_HOST_CSR_TOP_REGS_H__ + +#define CONN_HOST_CSR_TOP_BASE 0x18060000 + +#define CONN_HOST_CSR_TOP_HOST2GPS_DEGUG_SEL_ADDR (CONN_HOST_CSR_TOP_BASE + 0x00B0) +#define CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_AO_DEBUGSYS_ADDR (CONN_HOST_CSR_TOP_BASE + 0x0128) +#define CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT_ADDR (CONN_HOST_CSR_TOP_BASE + 0x0148) +#define CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL_ADDR (CONN_HOST_CSR_TOP_BASE + 0x0184) +#define CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_GPS_ADDR (CONN_HOST_CSR_TOP_BASE + 0x01AC) +#define CONN_HOST_CSR_TOP_CONN2AP_REMAP_GPS_EMI_BASE_ADDR_ADDR (CONN_HOST_CSR_TOP_BASE + 0x01D0) +#define CONN_HOST_CSR_TOP_GPS_CFG2HOST_DEBUG_ADDR (CONN_HOST_CSR_TOP_BASE + 0x0240) + + +#define CONN_HOST_CSR_TOP_HOST2GPS_DEGUG_SEL_HOST2GPS_DEGUG_SEL_ADDR CONN_HOST_CSR_TOP_HOST2GPS_DEGUG_SEL_ADDR +#define CONN_HOST_CSR_TOP_HOST2GPS_DEGUG_SEL_HOST2GPS_DEGUG_SEL_MASK 0x000000FF +#define CONN_HOST_CSR_TOP_HOST2GPS_DEGUG_SEL_HOST2GPS_DEGUG_SEL_SHFT 0 + +#define CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_AO_DEBUGSYS_CONN_INFRA_DEBUG_CTRL_AO_DEBUGSYS_CTRL_ADDR \ + CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_AO_DEBUGSYS_ADDR +#define CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_AO_DEBUGSYS_CONN_INFRA_DEBUG_CTRL_AO_DEBUGSYS_CTRL_MASK 0xFFFFFFFF +#define CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_AO_DEBUGSYS_CONN_INFRA_DEBUG_CTRL_AO_DEBUGSYS_CTRL_SHFT 0 + +#define CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT_ADDR \ + CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT_ADDR +#define CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT_MASK 0xFFFFFFFF +#define CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT_SHFT 0 + +#define CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL_CONN_INFRA_ON2OFF_SLP_PROT_ACK_ADDR \ + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL_ADDR +#define CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL_CONN_INFRA_ON2OFF_SLP_PROT_ACK_MASK 0x00000020 +#define CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL_CONN_INFRA_ON2OFF_SLP_PROT_ACK_SHFT 5 + +#define CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_GPS_CONN_INFRA_WAKEPU_GPS_ADDR CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_GPS_ADDR +#define CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_GPS_CONN_INFRA_WAKEPU_GPS_MASK 0x00000001 +#define CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_GPS_CONN_INFRA_WAKEPU_GPS_SHFT 0 + +#define CONN_HOST_CSR_TOP_CONN2AP_REMAP_GPS_EMI_BASE_ADDR_CONN2AP_REMAP_GPS_EMI_BASE_ADDR_ADDR \ + CONN_HOST_CSR_TOP_CONN2AP_REMAP_GPS_EMI_BASE_ADDR_ADDR +#define CONN_HOST_CSR_TOP_CONN2AP_REMAP_GPS_EMI_BASE_ADDR_CONN2AP_REMAP_GPS_EMI_BASE_ADDR_MASK 0x000FFFFF +#define CONN_HOST_CSR_TOP_CONN2AP_REMAP_GPS_EMI_BASE_ADDR_CONN2AP_REMAP_GPS_EMI_BASE_ADDR_SHFT 0 + +#define CONN_HOST_CSR_TOP_GPS_CFG2HOST_DEBUG_GPS_CFG2HOST_DEBUG_ADDR CONN_HOST_CSR_TOP_GPS_CFG2HOST_DEBUG_ADDR +#define CONN_HOST_CSR_TOP_GPS_CFG2HOST_DEBUG_GPS_CFG2HOST_DEBUG_MASK 0x0000FFFF +#define CONN_HOST_CSR_TOP_GPS_CFG2HOST_DEBUG_GPS_CFG2HOST_DEBUG_SHFT 0 + +#endif /* __CONN_HOST_CSR_TOP_REGS_H__ */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_infra_cfg.h b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_infra_cfg.h new file mode 100644 index 0000000000000..425dbb171f82b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_infra_cfg.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ +#ifndef __CONN_INFRA_CFG_REGS_H__ +#define __CONN_INFRA_CFG_REGS_H__ + +#define CONN_INFRA_CFG_BASE 0x18001000 + +#define CONN_INFRA_CFG_CONN_HW_VER_ADDR (CONN_INFRA_CFG_BASE + 0x0000) +#define CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL_ADDR (CONN_INFRA_CFG_BASE + 0x0618) +#define CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_ADDR (CONN_INFRA_CFG_BASE + 0x061C) +#define CONN_INFRA_CFG_PLL_STATUS_ADDR (CONN_INFRA_CFG_BASE + 0x0810) +#define CONN_INFRA_CFG_GPS_PWRCTRL0_ADDR (CONN_INFRA_CFG_BASE + 0x0878) +#define CONN_INFRA_CFG_CKGEN_BUS_ADDR (CONN_INFRA_CFG_BASE + 0x0A00) +#define CONN_INFRA_CFG_EMI_CTL_TOP_ADDR (CONN_INFRA_CFG_BASE + 0x0C10) +#define CONN_INFRA_CFG_EMI_CTL_WF_ADDR (CONN_INFRA_CFG_BASE + 0x0C14) +#define CONN_INFRA_CFG_EMI_CTL_BT_ADDR (CONN_INFRA_CFG_BASE + 0x0C18) +#define CONN_INFRA_CFG_EMI_CTL_GPS_ADDR (CONN_INFRA_CFG_BASE + 0x0C1C) + + +#define CONN_INFRA_CFG_CONN_HW_VER_RO_CONN_HW_VERSION_ADDR CONN_INFRA_CFG_CONN_HW_VER_ADDR +#define CONN_INFRA_CFG_CONN_HW_VER_RO_CONN_HW_VERSION_MASK 0xFFFFFFFF +#define CONN_INFRA_CFG_CONN_HW_VER_RO_CONN_HW_VERSION_SHFT 0 + +#define CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL_R_CONN2GPS_SLP_PROT_TX_EN_ADDR CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL_ADDR +#define CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL_R_CONN2GPS_SLP_PROT_TX_EN_MASK 0x00000001 +#define CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL_R_CONN2GPS_SLP_PROT_TX_EN_SHFT 0 +#define CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL_R_CONN2GPS_SLP_PROT_TX_RDY_ADDR \ + CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL_ADDR +#define CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL_R_CONN2GPS_SLP_PROT_TX_RDY_MASK 0x00000008 +#define CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL_R_CONN2GPS_SLP_PROT_TX_RDY_SHFT 3 +#define CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL_R_CONN2GPS_SLP_PROT_RX_EN_ADDR CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL_ADDR +#define CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL_R_CONN2GPS_SLP_PROT_RX_EN_MASK 0x00000010 +#define CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL_R_CONN2GPS_SLP_PROT_RX_EN_SHFT 4 +#define CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL_R_CONN2GPS_SLP_PROT_RX_RDY_ADDR \ + CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL_ADDR +#define CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL_R_CONN2GPS_SLP_PROT_RX_RDY_MASK 0x00000080 +#define CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL_R_CONN2GPS_SLP_PROT_RX_RDY_SHFT 7 + +#define CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_R_GPS2CONN_SLP_PROT_TX_EN_ADDR CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_ADDR +#define CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_R_GPS2CONN_SLP_PROT_TX_EN_MASK 0x00000001 +#define CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_R_GPS2CONN_SLP_PROT_TX_EN_SHFT 0 +#define CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_R_GPS2CONN_SLP_PROT_TX_RDY_ADDR \ + CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_ADDR +#define CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_R_GPS2CONN_SLP_PROT_TX_RDY_MASK 0x00000008 +#define CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_R_GPS2CONN_SLP_PROT_TX_RDY_SHFT 3 +#define CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_R_GPS2CONN_SLP_PROT_RX_EN_ADDR CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_ADDR +#define CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_R_GPS2CONN_SLP_PROT_RX_EN_MASK 0x00000010 +#define CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_R_GPS2CONN_SLP_PROT_RX_EN_SHFT 4 +#define CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_R_GPS2CONN_SLP_PROT_RX_RDY_ADDR \ + CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_ADDR +#define CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_R_GPS2CONN_SLP_PROT_RX_RDY_MASK 0x00000080 +#define CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_R_GPS2CONN_SLP_PROT_RX_RDY_SHFT 7 + +#define CONN_INFRA_CFG_PLL_STATUS_BPLL_RDY_ADDR CONN_INFRA_CFG_PLL_STATUS_ADDR +#define CONN_INFRA_CFG_PLL_STATUS_BPLL_RDY_MASK 0x00000002 +#define CONN_INFRA_CFG_PLL_STATUS_BPLL_RDY_SHFT 1 + +#define CONN_INFRA_CFG_GPS_PWRCTRL0_GP_FUNCTION_EN_ADDR CONN_INFRA_CFG_GPS_PWRCTRL0_ADDR +#define CONN_INFRA_CFG_GPS_PWRCTRL0_GP_FUNCTION_EN_MASK 0x00000001 +#define CONN_INFRA_CFG_GPS_PWRCTRL0_GP_FUNCTION_EN_SHFT 0 + +#define CONN_INFRA_CFG_CKGEN_BUS_CONN_CO_EXT_UART_PTA_OSC_CKEN_ADDR CONN_INFRA_CFG_CKGEN_BUS_ADDR +#define CONN_INFRA_CFG_CKGEN_BUS_CONN_CO_EXT_UART_PTA_OSC_CKEN_MASK 0x00000020 +#define CONN_INFRA_CFG_CKGEN_BUS_CONN_CO_EXT_UART_PTA_OSC_CKEN_SHFT 5 +#define CONN_INFRA_CFG_CKGEN_BUS_CONN_CO_EXT_UART_PTA_HCLK_CKEN_ADDR CONN_INFRA_CFG_CKGEN_BUS_ADDR +#define CONN_INFRA_CFG_CKGEN_BUS_CONN_CO_EXT_UART_PTA_HCLK_CKEN_MASK 0x00000010 +#define CONN_INFRA_CFG_CKGEN_BUS_CONN_CO_EXT_UART_PTA_HCLK_CKEN_SHFT 4 +#define CONN_INFRA_CFG_CKGEN_BUS_CONN_CO_EXT_UART_PTA5_OSC_CKEN_ADDR CONN_INFRA_CFG_CKGEN_BUS_ADDR +#define CONN_INFRA_CFG_CKGEN_BUS_CONN_CO_EXT_UART_PTA5_OSC_CKEN_MASK 0x00000008 +#define CONN_INFRA_CFG_CKGEN_BUS_CONN_CO_EXT_UART_PTA5_OSC_CKEN_SHFT 3 +#define CONN_INFRA_CFG_CKGEN_BUS_CONN_CO_EXT_UART_PTA5_HCLK_CKEN_ADDR CONN_INFRA_CFG_CKGEN_BUS_ADDR +#define CONN_INFRA_CFG_CKGEN_BUS_CONN_CO_EXT_UART_PTA5_HCLK_CKEN_MASK 0x00000004 +#define CONN_INFRA_CFG_CKGEN_BUS_CONN_CO_EXT_UART_PTA5_HCLK_CKEN_SHFT 2 + +#define CONN_INFRA_CFG_EMI_CTL_TOP_EMI_REQ_TOP_ADDR CONN_INFRA_CFG_EMI_CTL_TOP_ADDR +#define CONN_INFRA_CFG_EMI_CTL_TOP_EMI_REQ_TOP_MASK 0x00000001 +#define CONN_INFRA_CFG_EMI_CTL_TOP_EMI_REQ_TOP_SHFT 0 + +#define CONN_INFRA_CFG_EMI_CTL_GPS_EMI_REQ_GPS_ADDR CONN_INFRA_CFG_EMI_CTL_GPS_ADDR +#define CONN_INFRA_CFG_EMI_CTL_GPS_EMI_REQ_GPS_MASK 0x00000001 +#define CONN_INFRA_CFG_EMI_CTL_GPS_EMI_REQ_GPS_SHFT 0 + +#endif /* __CONN_INFRA_CFG_REGS_H__ */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_infra_rgu.h b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_infra_rgu.h new file mode 100644 index 0000000000000..598da98008e87 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_infra_rgu.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ +#ifndef __CONN_INFRA_RGU_REGS_H__ +#define __CONN_INFRA_RGU_REGS_H__ + +#define CONN_INFRA_RGU_BASE 0x18000000 + +#define CONN_INFRA_RGU_BGFYS_ON_TOP_PWR_CTL_ADDR (CONN_INFRA_RGU_BASE + 0x0008) +#define CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_ACK_ST_ADDR (CONN_INFRA_RGU_BASE + 0x0114) + + +#define CONN_INFRA_RGU_BGFYS_ON_TOP_PWR_CTL_BGFSYS_ON_TOP_PWR_ON_ADDR CONN_INFRA_RGU_BGFYS_ON_TOP_PWR_CTL_ADDR +#define CONN_INFRA_RGU_BGFYS_ON_TOP_PWR_CTL_BGFSYS_ON_TOP_PWR_ON_MASK 0x00000080 +#define CONN_INFRA_RGU_BGFYS_ON_TOP_PWR_CTL_BGFSYS_ON_TOP_PWR_ON_SHFT 7 + +#define CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_ACK_ST_AN_BGFSYS_ON_TOP_PWR_ACK_S_ADDR \ + CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_ACK_ST_ADDR +#define CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_ACK_ST_AN_BGFSYS_ON_TOP_PWR_ACK_S_MASK 0x02000000 +#define CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_ACK_ST_AN_BGFSYS_ON_TOP_PWR_ACK_S_SHFT 25 +#define CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_ACK_ST_BGFSYS_ON_TOP_PWR_ACK_ADDR CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_ACK_ST_ADDR +#define CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_ACK_ST_BGFSYS_ON_TOP_PWR_ACK_MASK 0x01000000 +#define CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_ACK_ST_BGFSYS_ON_TOP_PWR_ACK_SHFT 24 + +#endif /* __CONN_INFRA_RGU_REGS_H__ */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_pta6.h b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_pta6.h new file mode 100644 index 0000000000000..9ebb76589c253 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_pta6.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ +#ifndef __CONN_PTA6_REGS_H__ +#define __CONN_PTA6_REGS_H__ + +#define CONN_PTA6_BASE 0x1800C000 + +#define CONN_PTA6_WFSET_PTA_CTRL_ADDR (CONN_PTA6_BASE + 0x0000) +#define CONN_PTA6_PTA_CLK_CFG_ADDR (CONN_PTA6_BASE + 0x0004) +#define CONN_PTA6_BTSET_PTA_CTRL_ADDR (CONN_PTA6_BASE + 0x0008) +#define CONN_PTA6_RO_PTA_CTRL_ADDR (CONN_PTA6_BASE + 0x000C) +#define CONN_PTA6_GPS_BLANK_CFG_ADDR (CONN_PTA6_BASE + 0x0240) +#define CONN_PTA6_TMR_CTRL_1_ADDR (CONN_PTA6_BASE + 0x02C4) +#define CONN_PTA6_TMR_CTRL_3_ADDR (CONN_PTA6_BASE + 0x02CC) + + +#define CONN_PTA6_WFSET_PTA_CTRL_r_wfset_uart_apb_hw_en_ADDR CONN_PTA6_WFSET_PTA_CTRL_ADDR +#define CONN_PTA6_WFSET_PTA_CTRL_r_wfset_uart_apb_hw_en_MASK 0x00010000 +#define CONN_PTA6_WFSET_PTA_CTRL_r_wfset_uart_apb_hw_en_SHFT 16 +#define CONN_PTA6_WFSET_PTA_CTRL_r_wfset_lte_pta_en_ADDR CONN_PTA6_WFSET_PTA_CTRL_ADDR +#define CONN_PTA6_WFSET_PTA_CTRL_r_wfset_lte_pta_en_MASK 0x000000FC +#define CONN_PTA6_WFSET_PTA_CTRL_r_wfset_lte_pta_en_SHFT 2 +#define CONN_PTA6_WFSET_PTA_CTRL_r_wfset_en_pta_arb_ADDR CONN_PTA6_WFSET_PTA_CTRL_ADDR +#define CONN_PTA6_WFSET_PTA_CTRL_r_wfset_en_pta_arb_MASK 0x00000002 +#define CONN_PTA6_WFSET_PTA_CTRL_r_wfset_en_pta_arb_SHFT 1 +#define CONN_PTA6_WFSET_PTA_CTRL_r_wfset_pta_en_ADDR CONN_PTA6_WFSET_PTA_CTRL_ADDR +#define CONN_PTA6_WFSET_PTA_CTRL_r_wfset_pta_en_MASK 0x00000001 +#define CONN_PTA6_WFSET_PTA_CTRL_r_wfset_pta_en_SHFT 0 + +#define CONN_PTA6_PTA_CLK_CFG_r_pta_1m_cnt_ADDR CONN_PTA6_PTA_CLK_CFG_ADDR +#define CONN_PTA6_PTA_CLK_CFG_r_pta_1m_cnt_MASK 0x000000FF +#define CONN_PTA6_PTA_CLK_CFG_r_pta_1m_cnt_SHFT 0 + +#define CONN_PTA6_BTSET_PTA_CTRL_r_btset_uart_apb_hw_en_ADDR CONN_PTA6_BTSET_PTA_CTRL_ADDR +#define CONN_PTA6_BTSET_PTA_CTRL_r_btset_uart_apb_hw_en_MASK 0x00010000 +#define CONN_PTA6_BTSET_PTA_CTRL_r_btset_uart_apb_hw_en_SHFT 16 + +#define CONN_PTA6_RO_PTA_CTRL_ro_uart_apb_hw_en_ADDR CONN_PTA6_RO_PTA_CTRL_ADDR +#define CONN_PTA6_RO_PTA_CTRL_ro_uart_apb_hw_en_MASK 0x00010000 +#define CONN_PTA6_RO_PTA_CTRL_ro_uart_apb_hw_en_SHFT 16 +#define CONN_PTA6_RO_PTA_CTRL_ro_en_pta_arb_ADDR CONN_PTA6_RO_PTA_CTRL_ADDR +#define CONN_PTA6_RO_PTA_CTRL_ro_en_pta_arb_MASK 0x00000002 +#define CONN_PTA6_RO_PTA_CTRL_ro_en_pta_arb_SHFT 1 +#define CONN_PTA6_RO_PTA_CTRL_ro_pta_en_ADDR CONN_PTA6_RO_PTA_CTRL_ADDR +#define CONN_PTA6_RO_PTA_CTRL_ro_pta_en_MASK 0x00000001 +#define CONN_PTA6_RO_PTA_CTRL_ro_pta_en_SHFT 0 + +#define CONN_PTA6_GPS_BLANK_CFG_r_idc_gps_l5_blank_src_ADDR CONN_PTA6_GPS_BLANK_CFG_ADDR +#define CONN_PTA6_GPS_BLANK_CFG_r_idc_gps_l5_blank_src_MASK 0x00000018 +#define CONN_PTA6_GPS_BLANK_CFG_r_idc_gps_l5_blank_src_SHFT 3 +#define CONN_PTA6_GPS_BLANK_CFG_r_idc_gps_l1_blank_src_ADDR CONN_PTA6_GPS_BLANK_CFG_ADDR +#define CONN_PTA6_GPS_BLANK_CFG_r_idc_gps_l1_blank_src_MASK 0x00000006 +#define CONN_PTA6_GPS_BLANK_CFG_r_idc_gps_l1_blank_src_SHFT 1 +#define CONN_PTA6_GPS_BLANK_CFG_r_gps_blank_src_ADDR CONN_PTA6_GPS_BLANK_CFG_ADDR +#define CONN_PTA6_GPS_BLANK_CFG_r_gps_blank_src_MASK 0x00000001 +#define CONN_PTA6_GPS_BLANK_CFG_r_gps_blank_src_SHFT 0 + +#define CONN_PTA6_TMR_CTRL_1_r_idc_2nd_byte_tmout_ADDR CONN_PTA6_TMR_CTRL_1_ADDR +#define CONN_PTA6_TMR_CTRL_1_r_idc_2nd_byte_tmout_MASK 0xFF000000 +#define CONN_PTA6_TMR_CTRL_1_r_idc_2nd_byte_tmout_SHFT 24 + +#define CONN_PTA6_TMR_CTRL_3_r_gps_l5_blank_tmr_thld_ADDR CONN_PTA6_TMR_CTRL_3_ADDR +#define CONN_PTA6_TMR_CTRL_3_r_gps_l5_blank_tmr_thld_MASK 0x0000FF00 +#define CONN_PTA6_TMR_CTRL_3_r_gps_l5_blank_tmr_thld_SHFT 8 +#define CONN_PTA6_TMR_CTRL_3_r_gps_l1_blank_tmr_thld_ADDR CONN_PTA6_TMR_CTRL_3_ADDR +#define CONN_PTA6_TMR_CTRL_3_r_gps_l1_blank_tmr_thld_MASK 0x000000FF +#define CONN_PTA6_TMR_CTRL_3_r_gps_l1_blank_tmr_thld_SHFT 0 + +#endif /* __CONN_PTA6_REGS_H__ */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_rf_spi_mst_reg.h b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_rf_spi_mst_reg.h new file mode 100644 index 0000000000000..849e60a923589 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_rf_spi_mst_reg.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ +#ifndef __CONN_RF_SPI_MST_REG_REGS_H__ +#define __CONN_RF_SPI_MST_REG_REGS_H__ + +#define CONN_RF_SPI_MST_REG_BASE 0x18004000 + +#define CONN_RF_SPI_MST_ADDR_SPI_STA_ADDR (CONN_RF_SPI_MST_REG_BASE + 0x0000) +#define CONN_RF_SPI_MST_ADDR_FM_CTRL_ADDR (CONN_RF_SPI_MST_REG_BASE + 0x000C) +#define CONN_RF_SPI_MST_ADDR_SPI_FM_ADDR_ADDR (CONN_RF_SPI_MST_REG_BASE + 0x0030) +#define CONN_RF_SPI_MST_ADDR_SPI_FM_WDAT_ADDR (CONN_RF_SPI_MST_REG_BASE + 0x0034) +#define CONN_RF_SPI_MST_ADDR_SPI_FM_RDAT_ADDR (CONN_RF_SPI_MST_REG_BASE + 0x0038) +#define CONN_RF_SPI_MST_ADDR_SPI_GPS_GPS_ADDR_ADDR (CONN_RF_SPI_MST_REG_BASE + 0x0210) +#define CONN_RF_SPI_MST_ADDR_SPI_GPS_GPS_WDAT_ADDR (CONN_RF_SPI_MST_REG_BASE + 0x0214) +#define CONN_RF_SPI_MST_ADDR_SPI_GPS_GPS_RDAT_ADDR (CONN_RF_SPI_MST_REG_BASE + 0x0218) + + +#define CONN_RF_SPI_MST_REG_SPI_STA_FM_BUSY_ADDR CONN_RF_SPI_MST_ADDR_SPI_STA_ADDR +#define CONN_RF_SPI_MST_REG_SPI_STA_FM_BUSY_MASK 0x00000008 +#define CONN_RF_SPI_MST_REG_SPI_STA_FM_BUSY_SHFT 3 + +#define CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_EN_ADDR CONN_RF_SPI_MST_ADDR_FM_CTRL_ADDR +#define CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_EN_MASK 0x00008000 +#define CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_EN_SHFT 15 +#define CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_CNT_ADDR CONN_RF_SPI_MST_ADDR_FM_CTRL_ADDR +#define CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_CNT_MASK 0x000000FF +#define CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_CNT_SHFT 0 + +#endif /* __CONN_RF_SPI_MST_REG_REGS_H__ */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_semaphore.h b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_semaphore.h new file mode 100644 index 0000000000000..7b807463e18a1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_semaphore.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ +#ifndef __CONN_SEMAPHORE_REGS_H__ +#define __CONN_SEMAPHORE_REGS_H__ + +#define CONN_SEMAPHORE_BASE 0x18070000 + +#define CONN_SEMAPHORE_CONN_SEMA05_M3_OWN_STA_ADDR (CONN_SEMAPHORE_BASE + 0x3014) +#define CONN_SEMAPHORE_CONN_SEMA11_M3_OWN_STA_ADDR (CONN_SEMAPHORE_BASE + 0x302C) +#define CONN_SEMAPHORE_CONN_SEMA05_M3_OWN_REL_ADDR (CONN_SEMAPHORE_BASE + 0x3214) +#define CONN_SEMAPHORE_CONN_SEMA11_M3_OWN_REL_ADDR (CONN_SEMAPHORE_BASE + 0x322C) + + +#define CONN_SEMAPHORE_CONN_SEMA05_M3_OWN_STA_CONN_SEMA05_M3_OWN_STA_ADDR CONN_SEMAPHORE_CONN_SEMA05_M3_OWN_STA_ADDR +#define CONN_SEMAPHORE_CONN_SEMA05_M3_OWN_STA_CONN_SEMA05_M3_OWN_STA_MASK 0x00000003 +#define CONN_SEMAPHORE_CONN_SEMA05_M3_OWN_STA_CONN_SEMA05_M3_OWN_STA_SHFT 0 + +#define CONN_SEMAPHORE_CONN_SEMA11_M3_OWN_STA_CONN_SEMA11_M3_OWN_STA_ADDR CONN_SEMAPHORE_CONN_SEMA11_M3_OWN_STA_ADDR +#define CONN_SEMAPHORE_CONN_SEMA11_M3_OWN_STA_CONN_SEMA11_M3_OWN_STA_MASK 0x00000003 +#define CONN_SEMAPHORE_CONN_SEMA11_M3_OWN_STA_CONN_SEMA11_M3_OWN_STA_SHFT 0 + +#define CONN_SEMAPHORE_CONN_SEMA05_M3_OWN_REL_CONN_SEMA05_M3_OWN_REL_ADDR CONN_SEMAPHORE_CONN_SEMA05_M3_OWN_REL_ADDR +#define CONN_SEMAPHORE_CONN_SEMA05_M3_OWN_REL_CONN_SEMA05_M3_OWN_REL_MASK 0x00000001 +#define CONN_SEMAPHORE_CONN_SEMA05_M3_OWN_REL_CONN_SEMA05_M3_OWN_REL_SHFT 0 + +#define CONN_SEMAPHORE_CONN_SEMA11_M3_OWN_REL_CONN_SEMA11_M3_OWN_REL_ADDR CONN_SEMAPHORE_CONN_SEMA11_M3_OWN_REL_ADDR +#define CONN_SEMAPHORE_CONN_SEMA11_M3_OWN_REL_CONN_SEMA11_M3_OWN_REL_MASK 0x00000001 +#define CONN_SEMAPHORE_CONN_SEMA11_M3_OWN_REL_CONN_SEMA11_M3_OWN_REL_SHFT 0 + +#endif /* __CONN_SEMAPHORE_REGS_H__ */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_uart_pta.h b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_uart_pta.h new file mode 100644 index 0000000000000..518fca56e74f7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/conn_infra/conn_uart_pta.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ +#ifndef __CONN_UART_PTA_REGS_H__ +#define __CONN_UART_PTA_REGS_H__ + +#define CONN_UART_PTA_BASE 0x1800D000 + +#define CONN_UART_PTA_FCR_ADDR (CONN_UART_PTA_BASE + 0x0008) +#define CONN_UART_PTA_LCR_ADDR (CONN_UART_PTA_BASE + 0x000C) +#define CONN_UART_PTA_DLL_ADDR (CONN_UART_PTA_BASE + 0x0000) +#define CONN_UART_PTA_DLM_ADDR (CONN_UART_PTA_BASE + 0x0004) +#define CONN_UART_PTA_HIGHSPEED_ADDR (CONN_UART_PTA_BASE + 0x0024) +#define CONN_UART_PTA_SAMPLE_COUNT_ADDR (CONN_UART_PTA_BASE + 0x0028) +#define CONN_UART_PTA_SAMPLE_POINT_ADDR (CONN_UART_PTA_BASE + 0x002C) +#define CONN_UART_PTA_GUARD_ADDR (CONN_UART_PTA_BASE + 0x003C) +#define CONN_UART_PTA_VFIFO_EN_ADDR (CONN_UART_PTA_BASE + 0x004C) +#define CONN_UART_PTA_FRACDIV_L_ADDR (CONN_UART_PTA_BASE + 0x0054) +#define CONN_UART_PTA_FRACDIV_M_ADDR (CONN_UART_PTA_BASE + 0x0058) + + +#define CONN_UART_PTA_FCR_RFTL_ADDR CONN_UART_PTA_FCR_ADDR +#define CONN_UART_PTA_FCR_RFTL_MASK 0x000000C0 +#define CONN_UART_PTA_FCR_RFTL_SHFT 6 + +#define CONN_UART_PTA_HIGHSPEED_SPEED_ADDR CONN_UART_PTA_HIGHSPEED_ADDR +#define CONN_UART_PTA_HIGHSPEED_SPEED_MASK 0x00000003 +#define CONN_UART_PTA_HIGHSPEED_SPEED_SHFT 0 + +#define CONN_UART_PTA_SAMPLE_COUNT_SAMPLE_COUNT_ADDR CONN_UART_PTA_SAMPLE_COUNT_ADDR +#define CONN_UART_PTA_SAMPLE_COUNT_SAMPLE_COUNT_MASK 0x000000FF +#define CONN_UART_PTA_SAMPLE_COUNT_SAMPLE_COUNT_SHFT 0 + +#define CONN_UART_PTA_SAMPLE_POINT_SAMPLE_POINT_ADDR CONN_UART_PTA_SAMPLE_POINT_ADDR +#define CONN_UART_PTA_SAMPLE_POINT_SAMPLE_POINT_MASK 0x000000FF +#define CONN_UART_PTA_SAMPLE_POINT_SAMPLE_POINT_SHFT 0 + +#define CONN_UART_PTA_GUARD_GUARD_EN_ADDR CONN_UART_PTA_GUARD_ADDR +#define CONN_UART_PTA_GUARD_GUARD_EN_MASK 0x00000010 +#define CONN_UART_PTA_GUARD_GUARD_EN_SHFT 4 +#define CONN_UART_PTA_GUARD_GUARD_CNT_ADDR CONN_UART_PTA_GUARD_ADDR +#define CONN_UART_PTA_GUARD_GUARD_CNT_MASK 0x0000000F +#define CONN_UART_PTA_GUARD_GUARD_CNT_SHFT 0 + +#define CONN_UART_PTA_VFIFO_EN_RX_TIME_EN_ADDR CONN_UART_PTA_VFIFO_EN_ADDR +#define CONN_UART_PTA_VFIFO_EN_RX_TIME_EN_MASK 0x00000080 +#define CONN_UART_PTA_VFIFO_EN_RX_TIME_EN_SHFT 7 +#define CONN_UART_PTA_VFIFO_EN_PTA_RX_FE_EN_ADDR CONN_UART_PTA_VFIFO_EN_ADDR +#define CONN_UART_PTA_VFIFO_EN_PTA_RX_FE_EN_MASK 0x00000008 +#define CONN_UART_PTA_VFIFO_EN_PTA_RX_FE_EN_SHFT 3 +#define CONN_UART_PTA_VFIFO_EN_PTA_RX_MODE_ADDR CONN_UART_PTA_VFIFO_EN_ADDR +#define CONN_UART_PTA_VFIFO_EN_PTA_RX_MODE_MASK 0x00000004 +#define CONN_UART_PTA_VFIFO_EN_PTA_RX_MODE_SHFT 2 + +#define CONN_UART_PTA_FRACDIV_L_FRACDIV_L_ADDR CONN_UART_PTA_FRACDIV_L_ADDR +#define CONN_UART_PTA_FRACDIV_L_FRACDIV_L_MASK 0x000000FF +#define CONN_UART_PTA_FRACDIV_L_FRACDIV_L_SHFT 0 + +#define CONN_UART_PTA_FRACDIV_M_FRACDIV_M_ADDR CONN_UART_PTA_FRACDIV_M_ADDR +#define CONN_UART_PTA_FRACDIV_M_FRACDIV_M_MASK 0x00000003 +#define CONN_UART_PTA_FRACDIV_M_FRACDIV_M_SHFT 0 + +#endif /* __CONN_UART_PTA_REGS_H__ */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/bgf_gps_cfg.h b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/bgf_gps_cfg.h new file mode 100644 index 0000000000000..3106378892b53 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/bgf_gps_cfg.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ +#ifndef __BGF_GPS_CFG_REGS_H__ +#define __BGF_GPS_CFG_REGS_H__ + +#define BGF_GPS_CFG_BASE 0x80021000 + +#define BGF_GPS_CFG_BGF_IP_VERSION_ADDR (BGF_GPS_CFG_BASE + 0x0010) +#define BGF_GPS_CFG_BGF_IP_CONFIG_ADDR (BGF_GPS_CFG_BASE + 0x0014) + + +#define BGF_GPS_CFG_BGF_IP_VERSION_BGFSYS_VERSION_ADDR BGF_GPS_CFG_BGF_IP_VERSION_ADDR +#define BGF_GPS_CFG_BGF_IP_VERSION_BGFSYS_VERSION_MASK 0xFFFFFFFF +#define BGF_GPS_CFG_BGF_IP_VERSION_BGFSYS_VERSION_SHFT 0 + +#define BGF_GPS_CFG_BGF_IP_CONFIG_BGFSYS_CONFIG_ADDR BGF_GPS_CFG_BGF_IP_CONFIG_ADDR +#define BGF_GPS_CFG_BGF_IP_CONFIG_BGFSYS_CONFIG_MASK 0x000000FF +#define BGF_GPS_CFG_BGF_IP_CONFIG_BGFSYS_CONFIG_SHFT 0 + +#endif /* __BGF_GPS_CFG_REGS_H__ */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/bgf_gps_dma.h b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/bgf_gps_dma.h new file mode 100644 index 0000000000000..681be8114d979 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/bgf_gps_dma.h @@ -0,0 +1,195 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ +#ifndef __BGF_GPS_DMA_REGS_H__ +#define __BGF_GPS_DMA_REGS_H__ + +#define BGF_GPS_DMA_BASE 0x80010000 + +#define BGF_GPS_DMA_DMA1_WPPT_ADDR (BGF_GPS_DMA_BASE + 0x0108) +#define BGF_GPS_DMA_DMA1_WPTO_ADDR (BGF_GPS_DMA_BASE + 0x010C) +#define BGF_GPS_DMA_DMA1_COUNT_ADDR (BGF_GPS_DMA_BASE + 0x0110) +#define BGF_GPS_DMA_DMA1_CON_ADDR (BGF_GPS_DMA_BASE + 0x0114) +#define BGF_GPS_DMA_DMA1_START_ADDR (BGF_GPS_DMA_BASE + 0x0118) +#define BGF_GPS_DMA_DMA1_INTSTA_ADDR (BGF_GPS_DMA_BASE + 0x011C) +#define BGF_GPS_DMA_DMA1_ACKINT_ADDR (BGF_GPS_DMA_BASE + 0x0120) +#define BGF_GPS_DMA_DMA1_RLCT_ADDR (BGF_GPS_DMA_BASE + 0x0124) +#define BGF_GPS_DMA_DMA1_PGMADDR_ADDR (BGF_GPS_DMA_BASE + 0x012C) +#define BGF_GPS_DMA_DMA1_STATE_ADDR (BGF_GPS_DMA_BASE + 0x0148) +#define BGF_GPS_DMA_DMA2_WPPT_ADDR (BGF_GPS_DMA_BASE + 0x0208) +#define BGF_GPS_DMA_DMA2_WPTO_ADDR (BGF_GPS_DMA_BASE + 0x020C) +#define BGF_GPS_DMA_DMA2_COUNT_ADDR (BGF_GPS_DMA_BASE + 0x0210) +#define BGF_GPS_DMA_DMA2_CON_ADDR (BGF_GPS_DMA_BASE + 0x0214) +#define BGF_GPS_DMA_DMA2_START_ADDR (BGF_GPS_DMA_BASE + 0x0218) +#define BGF_GPS_DMA_DMA2_INTSTA_ADDR (BGF_GPS_DMA_BASE + 0x021C) +#define BGF_GPS_DMA_DMA2_ACKINT_ADDR (BGF_GPS_DMA_BASE + 0x0220) +#define BGF_GPS_DMA_DMA2_RLCT_ADDR (BGF_GPS_DMA_BASE + 0x0224) +#define BGF_GPS_DMA_DMA2_PGMADDR_ADDR (BGF_GPS_DMA_BASE + 0x022C) +#define BGF_GPS_DMA_DMA3_WPPT_ADDR (BGF_GPS_DMA_BASE + 0x0308) +#define BGF_GPS_DMA_DMA3_WPTO_ADDR (BGF_GPS_DMA_BASE + 0x030C) +#define BGF_GPS_DMA_DMA3_COUNT_ADDR (BGF_GPS_DMA_BASE + 0x0310) +#define BGF_GPS_DMA_DMA3_CON_ADDR (BGF_GPS_DMA_BASE + 0x0314) +#define BGF_GPS_DMA_DMA3_START_ADDR (BGF_GPS_DMA_BASE + 0x0318) +#define BGF_GPS_DMA_DMA3_INTSTA_ADDR (BGF_GPS_DMA_BASE + 0x031C) +#define BGF_GPS_DMA_DMA3_ACKINT_ADDR (BGF_GPS_DMA_BASE + 0x0320) +#define BGF_GPS_DMA_DMA3_RLCT_ADDR (BGF_GPS_DMA_BASE + 0x0324) +#define BGF_GPS_DMA_DMA3_PGMADDR_ADDR (BGF_GPS_DMA_BASE + 0x032C) +#define BGF_GPS_DMA_DMA4_WPPT_ADDR (BGF_GPS_DMA_BASE + 0x0408) +#define BGF_GPS_DMA_DMA4_WPTO_ADDR (BGF_GPS_DMA_BASE + 0x040C) +#define BGF_GPS_DMA_DMA4_COUNT_ADDR (BGF_GPS_DMA_BASE + 0x0410) +#define BGF_GPS_DMA_DMA4_CON_ADDR (BGF_GPS_DMA_BASE + 0x0414) +#define BGF_GPS_DMA_DMA4_START_ADDR (BGF_GPS_DMA_BASE + 0x0418) +#define BGF_GPS_DMA_DMA4_INTSTA_ADDR (BGF_GPS_DMA_BASE + 0x041C) +#define BGF_GPS_DMA_DMA4_ACKINT_ADDR (BGF_GPS_DMA_BASE + 0x0420) +#define BGF_GPS_DMA_DMA4_RLCT_ADDR (BGF_GPS_DMA_BASE + 0x0424) +#define BGF_GPS_DMA_DMA4_PGMADDR_ADDR (BGF_GPS_DMA_BASE + 0x042C) + + +#define BGF_GPS_DMA_DMA1_WPPT_WPPT_ADDR BGF_GPS_DMA_DMA1_WPPT_ADDR +#define BGF_GPS_DMA_DMA1_WPPT_WPPT_MASK 0x0000FFFF +#define BGF_GPS_DMA_DMA1_WPPT_WPPT_SHFT 0 + +#define BGF_GPS_DMA_DMA1_WPTO_WPTO_ADDR BGF_GPS_DMA_DMA1_WPTO_ADDR +#define BGF_GPS_DMA_DMA1_WPTO_WPTO_MASK 0xFFFFFFFF +#define BGF_GPS_DMA_DMA1_WPTO_WPTO_SHFT 0 + +#define BGF_GPS_DMA_DMA1_COUNT_LEN_ADDR BGF_GPS_DMA_DMA1_COUNT_ADDR +#define BGF_GPS_DMA_DMA1_COUNT_LEN_MASK 0x0000FFFF +#define BGF_GPS_DMA_DMA1_COUNT_LEN_SHFT 0 + +#define BGF_GPS_DMA_DMA1_CON_MAS_ADDR BGF_GPS_DMA_DMA1_CON_ADDR +#define BGF_GPS_DMA_DMA1_CON_MAS_MASK 0x00300000 +#define BGF_GPS_DMA_DMA1_CON_MAS_SHFT 20 +#define BGF_GPS_DMA_DMA1_CON_W2B_ADDR BGF_GPS_DMA_DMA1_CON_ADDR +#define BGF_GPS_DMA_DMA1_CON_W2B_MASK 0x00000040 +#define BGF_GPS_DMA_DMA1_CON_W2B_SHFT 6 +#define BGF_GPS_DMA_DMA1_CON_B2W_ADDR BGF_GPS_DMA_DMA1_CON_ADDR +#define BGF_GPS_DMA_DMA1_CON_B2W_MASK 0x00000020 +#define BGF_GPS_DMA_DMA1_CON_B2W_SHFT 5 +#define BGF_GPS_DMA_DMA1_CON_SIZE_ADDR BGF_GPS_DMA_DMA1_CON_ADDR +#define BGF_GPS_DMA_DMA1_CON_SIZE_MASK 0x00000003 +#define BGF_GPS_DMA_DMA1_CON_SIZE_SHFT 0 + +#define BGF_GPS_DMA_DMA1_START_STR_ADDR BGF_GPS_DMA_DMA1_START_ADDR +#define BGF_GPS_DMA_DMA1_START_STR_MASK 0x00008000 +#define BGF_GPS_DMA_DMA1_START_STR_SHFT 15 + +#define BGF_GPS_DMA_DMA1_INTSTA_INT_ADDR BGF_GPS_DMA_DMA1_INTSTA_ADDR +#define BGF_GPS_DMA_DMA1_INTSTA_INT_MASK 0x00008000 +#define BGF_GPS_DMA_DMA1_INTSTA_INT_SHFT 15 + +#define BGF_GPS_DMA_DMA1_ACKINT_ACK_ADDR BGF_GPS_DMA_DMA1_ACKINT_ADDR +#define BGF_GPS_DMA_DMA1_ACKINT_ACK_MASK 0x00008000 +#define BGF_GPS_DMA_DMA1_ACKINT_ACK_SHFT 15 + +#define BGF_GPS_DMA_DMA1_RLCT_RLCT_ADDR BGF_GPS_DMA_DMA1_RLCT_ADDR +#define BGF_GPS_DMA_DMA1_RLCT_RLCT_MASK 0x0000FFFF +#define BGF_GPS_DMA_DMA1_RLCT_RLCT_SHFT 0 + +#define BGF_GPS_DMA_DMA1_PGMADDR_PGMADDR_ADDR BGF_GPS_DMA_DMA1_PGMADDR_ADDR +#define BGF_GPS_DMA_DMA1_PGMADDR_PGMADDR_MASK 0xFFFFFFFF +#define BGF_GPS_DMA_DMA1_PGMADDR_PGMADDR_SHFT 0 + +#define BGF_GPS_DMA_DMA1_STATE_STATE_ADDR BGF_GPS_DMA_DMA1_STATE_ADDR +#define BGF_GPS_DMA_DMA1_STATE_STATE_MASK 0x0000007F +#define BGF_GPS_DMA_DMA1_STATE_STATE_SHFT 0 + +#define BGF_GPS_DMA_DMA2_WPPT_WPPT_ADDR BGF_GPS_DMA_DMA2_WPPT_ADDR +#define BGF_GPS_DMA_DMA2_WPPT_WPPT_MASK 0x0000FFFF +#define BGF_GPS_DMA_DMA2_WPPT_WPPT_SHFT 0 + +#define BGF_GPS_DMA_DMA2_WPTO_WPTO_ADDR BGF_GPS_DMA_DMA2_WPTO_ADDR +#define BGF_GPS_DMA_DMA2_WPTO_WPTO_MASK 0xFFFFFFFF +#define BGF_GPS_DMA_DMA2_WPTO_WPTO_SHFT 0 + +#define BGF_GPS_DMA_DMA2_COUNT_LEN_ADDR BGF_GPS_DMA_DMA2_COUNT_ADDR +#define BGF_GPS_DMA_DMA2_COUNT_LEN_MASK 0x0000FFFF +#define BGF_GPS_DMA_DMA2_COUNT_LEN_SHFT 0 + +#define BGF_GPS_DMA_DMA2_START_STR_ADDR BGF_GPS_DMA_DMA2_START_ADDR +#define BGF_GPS_DMA_DMA2_START_STR_MASK 0x00008000 +#define BGF_GPS_DMA_DMA2_START_STR_SHFT 15 + +#define BGF_GPS_DMA_DMA2_INTSTA_INT_ADDR BGF_GPS_DMA_DMA2_INTSTA_ADDR +#define BGF_GPS_DMA_DMA2_INTSTA_INT_MASK 0x00008000 +#define BGF_GPS_DMA_DMA2_INTSTA_INT_SHFT 15 + +#define BGF_GPS_DMA_DMA2_ACKINT_ACK_ADDR BGF_GPS_DMA_DMA2_ACKINT_ADDR +#define BGF_GPS_DMA_DMA2_ACKINT_ACK_MASK 0x00008000 +#define BGF_GPS_DMA_DMA2_ACKINT_ACK_SHFT 15 + +#define BGF_GPS_DMA_DMA2_RLCT_RLCT_ADDR BGF_GPS_DMA_DMA2_RLCT_ADDR +#define BGF_GPS_DMA_DMA2_RLCT_RLCT_MASK 0x0000FFFF +#define BGF_GPS_DMA_DMA2_RLCT_RLCT_SHFT 0 + +#define BGF_GPS_DMA_DMA2_PGMADDR_PGMADDR_ADDR BGF_GPS_DMA_DMA2_PGMADDR_ADDR +#define BGF_GPS_DMA_DMA2_PGMADDR_PGMADDR_MASK 0xFFFFFFFF +#define BGF_GPS_DMA_DMA2_PGMADDR_PGMADDR_SHFT 0 + +#define BGF_GPS_DMA_DMA3_WPPT_WPPT_ADDR BGF_GPS_DMA_DMA3_WPPT_ADDR +#define BGF_GPS_DMA_DMA3_WPPT_WPPT_MASK 0x0000FFFF +#define BGF_GPS_DMA_DMA3_WPPT_WPPT_SHFT 0 + +#define BGF_GPS_DMA_DMA3_WPTO_WPTO_ADDR BGF_GPS_DMA_DMA3_WPTO_ADDR +#define BGF_GPS_DMA_DMA3_WPTO_WPTO_MASK 0xFFFFFFFF +#define BGF_GPS_DMA_DMA3_WPTO_WPTO_SHFT 0 + +#define BGF_GPS_DMA_DMA3_COUNT_LEN_ADDR BGF_GPS_DMA_DMA3_COUNT_ADDR +#define BGF_GPS_DMA_DMA3_COUNT_LEN_MASK 0x0000FFFF +#define BGF_GPS_DMA_DMA3_COUNT_LEN_SHFT 0 + +#define BGF_GPS_DMA_DMA3_START_STR_ADDR BGF_GPS_DMA_DMA3_START_ADDR +#define BGF_GPS_DMA_DMA3_START_STR_MASK 0x00008000 +#define BGF_GPS_DMA_DMA3_START_STR_SHFT 15 + +#define BGF_GPS_DMA_DMA3_INTSTA_INT_ADDR BGF_GPS_DMA_DMA3_INTSTA_ADDR +#define BGF_GPS_DMA_DMA3_INTSTA_INT_MASK 0x00008000 +#define BGF_GPS_DMA_DMA3_INTSTA_INT_SHFT 15 + +#define BGF_GPS_DMA_DMA3_ACKINT_ACK_ADDR BGF_GPS_DMA_DMA3_ACKINT_ADDR +#define BGF_GPS_DMA_DMA3_ACKINT_ACK_MASK 0x00008000 +#define BGF_GPS_DMA_DMA3_ACKINT_ACK_SHFT 15 + +#define BGF_GPS_DMA_DMA3_RLCT_RLCT_ADDR BGF_GPS_DMA_DMA3_RLCT_ADDR +#define BGF_GPS_DMA_DMA3_RLCT_RLCT_MASK 0x0000FFFF +#define BGF_GPS_DMA_DMA3_RLCT_RLCT_SHFT 0 + +#define BGF_GPS_DMA_DMA3_PGMADDR_PGMADDR_ADDR BGF_GPS_DMA_DMA3_PGMADDR_ADDR +#define BGF_GPS_DMA_DMA3_PGMADDR_PGMADDR_MASK 0xFFFFFFFF +#define BGF_GPS_DMA_DMA3_PGMADDR_PGMADDR_SHFT 0 + +#define BGF_GPS_DMA_DMA4_WPPT_WPPT_ADDR BGF_GPS_DMA_DMA4_WPPT_ADDR +#define BGF_GPS_DMA_DMA4_WPPT_WPPT_MASK 0x0000FFFF +#define BGF_GPS_DMA_DMA4_WPPT_WPPT_SHFT 0 + +#define BGF_GPS_DMA_DMA4_WPTO_WPTO_ADDR BGF_GPS_DMA_DMA4_WPTO_ADDR +#define BGF_GPS_DMA_DMA4_WPTO_WPTO_MASK 0xFFFFFFFF +#define BGF_GPS_DMA_DMA4_WPTO_WPTO_SHFT 0 + +#define BGF_GPS_DMA_DMA4_COUNT_LEN_ADDR BGF_GPS_DMA_DMA4_COUNT_ADDR +#define BGF_GPS_DMA_DMA4_COUNT_LEN_MASK 0x0000FFFF +#define BGF_GPS_DMA_DMA4_COUNT_LEN_SHFT 0 + +#define BGF_GPS_DMA_DMA4_START_STR_ADDR BGF_GPS_DMA_DMA4_START_ADDR +#define BGF_GPS_DMA_DMA4_START_STR_MASK 0x00008000 +#define BGF_GPS_DMA_DMA4_START_STR_SHFT 15 + +#define BGF_GPS_DMA_DMA4_INTSTA_INT_ADDR BGF_GPS_DMA_DMA4_INTSTA_ADDR +#define BGF_GPS_DMA_DMA4_INTSTA_INT_MASK 0x00008000 +#define BGF_GPS_DMA_DMA4_INTSTA_INT_SHFT 15 + +#define BGF_GPS_DMA_DMA4_ACKINT_ACK_ADDR BGF_GPS_DMA_DMA4_ACKINT_ADDR +#define BGF_GPS_DMA_DMA4_ACKINT_ACK_MASK 0x00008000 +#define BGF_GPS_DMA_DMA4_ACKINT_ACK_SHFT 15 + +#define BGF_GPS_DMA_DMA4_RLCT_RLCT_ADDR BGF_GPS_DMA_DMA4_RLCT_ADDR +#define BGF_GPS_DMA_DMA4_RLCT_RLCT_MASK 0x0000FFFF +#define BGF_GPS_DMA_DMA4_RLCT_RLCT_SHFT 0 + +#define BGF_GPS_DMA_DMA4_PGMADDR_PGMADDR_ADDR BGF_GPS_DMA_DMA4_PGMADDR_ADDR +#define BGF_GPS_DMA_DMA4_PGMADDR_PGMADDR_MASK 0xFFFFFFFF +#define BGF_GPS_DMA_DMA4_PGMADDR_PGMADDR_SHFT 0 + +#endif /* __BGF_GPS_DMA_REGS_H__ */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_aon_top.h b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_aon_top.h new file mode 100644 index 0000000000000..ce7b4cedfa45e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_aon_top.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ +#ifndef __GPS_AON_TOP_REGS_H__ +#define __GPS_AON_TOP_REGS_H__ + +#define GPS_AON_TOP_BASE 0x80073000 + +#define GPS_AON_TOP_DSLEEP_CTL_ADDR (GPS_AON_TOP_BASE + 0x0108) +#define GPS_AON_TOP_WAKEUP_CTL_ADDR (GPS_AON_TOP_BASE + 0x0110) +#define GPS_AON_TOP_TCXO_MS_H_ADDR (GPS_AON_TOP_BASE + 0x0114) +#define GPS_AON_TOP_TCXO_MS_L_ADDR (GPS_AON_TOP_BASE + 0x0118) + + +#define GPS_AON_TOP_DSLEEP_CTL_FORCE_OSC_EN_ON_ADDR GPS_AON_TOP_DSLEEP_CTL_ADDR +#define GPS_AON_TOP_DSLEEP_CTL_FORCE_OSC_EN_ON_MASK 0x00000008 +#define GPS_AON_TOP_DSLEEP_CTL_FORCE_OSC_EN_ON_SHFT 3 +#define GPS_AON_TOP_DSLEEP_CTL_GPS_PWR_STAT_ADDR GPS_AON_TOP_DSLEEP_CTL_ADDR +#define GPS_AON_TOP_DSLEEP_CTL_GPS_PWR_STAT_MASK 0x00000003 +#define GPS_AON_TOP_DSLEEP_CTL_GPS_PWR_STAT_SHFT 0 + +#endif /* __GPS_AON_TOP_REGS_H__ */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_cfg_on.h b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_cfg_on.h new file mode 100644 index 0000000000000..2dd8ce5ec6ecd --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_cfg_on.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ +#ifndef __GPS_CFG_ON_REGS_H__ +#define __GPS_CFG_ON_REGS_H__ + +#define GPS_CFG_ON_BASE 0x80001000 + +#define GPS_CFG_ON_GPS_L1_SLP_PWR_CTL_ADDR (GPS_CFG_ON_BASE + 0x0020) +#define GPS_CFG_ON_GPS_L5_SLP_PWR_CTL_ADDR (GPS_CFG_ON_BASE + 0x0024) +#define GPS_CFG_ON_GPS_CLKGEN1_CTL_ADDR (GPS_CFG_ON_BASE + 0x003C) + + +#define GPS_CFG_ON_GPS_L1_SLP_PWR_CTL_GPS_L1_SLP_PWR_CTL_CS_ADDR GPS_CFG_ON_GPS_L1_SLP_PWR_CTL_ADDR +#define GPS_CFG_ON_GPS_L1_SLP_PWR_CTL_GPS_L1_SLP_PWR_CTL_CS_MASK 0x0000000F +#define GPS_CFG_ON_GPS_L1_SLP_PWR_CTL_GPS_L1_SLP_PWR_CTL_CS_SHFT 0 + +#define GPS_CFG_ON_GPS_L5_SLP_PWR_CTL_GPS_L5_SLP_PWR_CTL_CS_ADDR GPS_CFG_ON_GPS_L5_SLP_PWR_CTL_ADDR +#define GPS_CFG_ON_GPS_L5_SLP_PWR_CTL_GPS_L5_SLP_PWR_CTL_CS_MASK 0x0000000F +#define GPS_CFG_ON_GPS_L5_SLP_PWR_CTL_GPS_L5_SLP_PWR_CTL_CS_SHFT 0 + +#define GPS_CFG_ON_GPS_CLKGEN1_CTL_CR_GPS_DIGCK_DIV_EN_ADDR GPS_CFG_ON_GPS_CLKGEN1_CTL_ADDR +#define GPS_CFG_ON_GPS_CLKGEN1_CTL_CR_GPS_DIGCK_DIV_EN_MASK 0x00000010 +#define GPS_CFG_ON_GPS_CLKGEN1_CTL_CR_GPS_DIGCK_DIV_EN_SHFT 4 + +#endif /* __GPS_CFG_ON_REGS_H__ */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_l5_sys_adrdec.h b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_l5_sys_adrdec.h new file mode 100644 index 0000000000000..ef074d699aac4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_l5_sys_adrdec.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ +#ifndef __GPS_L5_SYS_ADRDEC_REGS_H__ +#define __GPS_L5_SYS_ADRDEC_REGS_H__ + +#define GPS_L5_SYS_ADRDEC_BASE 0x80080400 + + + + +#endif /* __GPS_L5_SYS_ADRDEC_REGS_H__ */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_l5_usrt_apb.h b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_l5_usrt_apb.h new file mode 100644 index 0000000000000..2e0a17f80aab0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_l5_usrt_apb.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ +#ifndef __GPS_L5_USRT_APB_REGS_H__ +#define __GPS_L5_USRT_APB_REGS_H__ + +#define GPS_L5_USRT_APB_BASE 0x80083000 + +#define GPS_L5_USRT_APB_GPS_APB_DATA_ADDR (GPS_L5_USRT_APB_BASE + 0x0000) +#define GPS_L5_USRT_APB_APB_CTRL_ADDR (GPS_L5_USRT_APB_BASE + 0x0004) +#define GPS_L5_USRT_APB_APB_INTEN_ADDR (GPS_L5_USRT_APB_BASE + 0x0008) +#define GPS_L5_USRT_APB_APB_STA_ADDR (GPS_L5_USRT_APB_BASE + 0x000C) +#define GPS_L5_USRT_APB_MONF_ADDR (GPS_L5_USRT_APB_BASE + 0x0010) +#define GPS_L5_USRT_APB_MCUB_A2DF_ADDR (GPS_L5_USRT_APB_BASE + 0x0020) +#define GPS_L5_USRT_APB_MCUB_D2AF_ADDR (GPS_L5_USRT_APB_BASE + 0x0024) +#define GPS_L5_USRT_APB_MCU_A2D0_ADDR (GPS_L5_USRT_APB_BASE + 0x0030) +#define GPS_L5_USRT_APB_MCU_A2D1_ADDR (GPS_L5_USRT_APB_BASE + 0x0034) +#define GPS_L5_USRT_APB_MCU_D2A0_ADDR (GPS_L5_USRT_APB_BASE + 0x0050) +#define GPS_L5_USRT_APB_MCU_D2A1_ADDR (GPS_L5_USRT_APB_BASE + 0x0054) + + +#define GPS_L5_USRT_APB_APB_CTRL_BYTEN_ADDR GPS_L5_USRT_APB_APB_CTRL_ADDR +#define GPS_L5_USRT_APB_APB_CTRL_BYTEN_MASK 0x00000008 +#define GPS_L5_USRT_APB_APB_CTRL_BYTEN_SHFT 3 +#define GPS_L5_USRT_APB_APB_CTRL_TX_EN_ADDR GPS_L5_USRT_APB_APB_CTRL_ADDR +#define GPS_L5_USRT_APB_APB_CTRL_TX_EN_MASK 0x00000002 +#define GPS_L5_USRT_APB_APB_CTRL_TX_EN_SHFT 1 +#define GPS_L5_USRT_APB_APB_CTRL_RX_EN_ADDR GPS_L5_USRT_APB_APB_CTRL_ADDR +#define GPS_L5_USRT_APB_APB_CTRL_RX_EN_MASK 0x00000001 +#define GPS_L5_USRT_APB_APB_CTRL_RX_EN_SHFT 0 + +#define GPS_L5_USRT_APB_APB_INTEN_NODAIEN_ADDR GPS_L5_USRT_APB_APB_INTEN_ADDR +#define GPS_L5_USRT_APB_APB_INTEN_NODAIEN_MASK 0x00000002 +#define GPS_L5_USRT_APB_APB_INTEN_NODAIEN_SHFT 1 +#define GPS_L5_USRT_APB_APB_INTEN_TXIEN_ADDR GPS_L5_USRT_APB_APB_INTEN_ADDR +#define GPS_L5_USRT_APB_APB_INTEN_TXIEN_MASK 0x00000001 +#define GPS_L5_USRT_APB_APB_INTEN_TXIEN_SHFT 0 + +#define GPS_L5_USRT_APB_APB_STA_RX_EMP_ADDR GPS_L5_USRT_APB_APB_STA_ADDR +#define GPS_L5_USRT_APB_APB_STA_RX_EMP_MASK 0x20000000 +#define GPS_L5_USRT_APB_APB_STA_RX_EMP_SHFT 29 +#define GPS_L5_USRT_APB_APB_STA_NODAINTB_ADDR GPS_L5_USRT_APB_APB_STA_ADDR +#define GPS_L5_USRT_APB_APB_STA_NODAINTB_MASK 0x00000002 +#define GPS_L5_USRT_APB_APB_STA_NODAINTB_SHFT 1 + +#define GPS_L5_USRT_APB_MCUB_A2DF_A2DF3_ADDR GPS_L5_USRT_APB_MCUB_A2DF_ADDR +#define GPS_L5_USRT_APB_MCUB_A2DF_A2DF3_MASK 0x00000008 +#define GPS_L5_USRT_APB_MCUB_A2DF_A2DF3_SHFT 3 + +#define GPS_L5_USRT_APB_MCUB_D2AF_D2AF3_ADDR GPS_L5_USRT_APB_MCUB_D2AF_ADDR +#define GPS_L5_USRT_APB_MCUB_D2AF_D2AF3_MASK 0x00000008 +#define GPS_L5_USRT_APB_MCUB_D2AF_D2AF3_SHFT 3 + +#define GPS_L5_USRT_APB_MCU_A2D1_A2D_1_ADDR GPS_L5_USRT_APB_MCU_A2D1_ADDR +#define GPS_L5_USRT_APB_MCU_A2D1_A2D_1_MASK 0x0000FFFF +#define GPS_L5_USRT_APB_MCU_A2D1_A2D_1_SHFT 0 + +#endif /* __GPS_L5_USRT_APB_REGS_H__ */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_rgu_on.h b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_rgu_on.h new file mode 100644 index 0000000000000..835340b3993b0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_rgu_on.h @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ +#ifndef __GPS_RGU_ON_REGS_H__ +#define __GPS_RGU_ON_REGS_H__ + +#define GPS_RGU_ON_BASE 0x80000000 + +#define GPS_RGU_ON_GPS_L1_CR_ADDR (GPS_RGU_ON_BASE + 0x0014) +#define GPS_RGU_ON_GPS_L1_DSPPRAM_PDN_EN_ADDR (GPS_RGU_ON_BASE + 0x0048) +#define GPS_RGU_ON_GPS_L1_DSPPRAM_SLP_EN_ADDR (GPS_RGU_ON_BASE + 0x004C) +#define GPS_RGU_ON_GPS_L1_DSPXRAM_PDN_EN_ADDR (GPS_RGU_ON_BASE + 0x0050) +#define GPS_RGU_ON_GPS_L1_DSPXRAM_SLP_EN_ADDR (GPS_RGU_ON_BASE + 0x0054) +#define GPS_RGU_ON_GPS_L1_DSPYRAM_PDN_EN_ADDR (GPS_RGU_ON_BASE + 0x0058) +#define GPS_RGU_ON_GPS_L1_DSPYRAM_SLP_EN_ADDR (GPS_RGU_ON_BASE + 0x005C) +#define GPS_RGU_ON_GPS_L1_DLY_CHAIN_CTL_ADDR (GPS_RGU_ON_BASE + 0x0160) +#define GPS_RGU_ON_GPS_L1_MEM_DLY_CTL_ADDR (GPS_RGU_ON_BASE + 0x0164) +#define GPS_RGU_ON_GPS_L5_CR_ADDR (GPS_RGU_ON_BASE + 0x0214) +#define GPS_RGU_ON_GPS_L5_DSPPRAM_PDN_EN_ADDR (GPS_RGU_ON_BASE + 0x0248) +#define GPS_RGU_ON_GPS_L5_DSPPRAM_SLP_EN_ADDR (GPS_RGU_ON_BASE + 0x024C) +#define GPS_RGU_ON_GPS_L5_DSPXRAM_PDN_EN_ADDR (GPS_RGU_ON_BASE + 0x0250) +#define GPS_RGU_ON_GPS_L5_DSPXRAM_SLP_EN_ADDR (GPS_RGU_ON_BASE + 0x0254) +#define GPS_RGU_ON_GPS_L5_DSPYRAM_PDN_EN_ADDR (GPS_RGU_ON_BASE + 0x0258) +#define GPS_RGU_ON_GPS_L5_DSPYRAM_SLP_EN_ADDR (GPS_RGU_ON_BASE + 0x025C) +#define GPS_RGU_ON_GPS_L5_DLY_CHAIN_CTL_ADDR (GPS_RGU_ON_BASE + 0x0360) +#define GPS_RGU_ON_GPS_L5_MEM_DLY_CTL_ADDR (GPS_RGU_ON_BASE + 0x0364) + + +#define GPS_RGU_ON_GPS_L1_CR_RGU_GPS_L1_SOFT_RST_B_ADDR GPS_RGU_ON_GPS_L1_CR_ADDR +#define GPS_RGU_ON_GPS_L1_CR_RGU_GPS_L1_SOFT_RST_B_MASK 0x00000020 +#define GPS_RGU_ON_GPS_L1_CR_RGU_GPS_L1_SOFT_RST_B_SHFT 5 +#define GPS_RGU_ON_GPS_L1_CR_RGU_GPS_L1_ON_ADDR GPS_RGU_ON_GPS_L1_CR_ADDR +#define GPS_RGU_ON_GPS_L1_CR_RGU_GPS_L1_ON_MASK 0x00000001 +#define GPS_RGU_ON_GPS_L1_CR_RGU_GPS_L1_ON_SHFT 0 + +#define GPS_RGU_ON_GPS_L1_DSPPRAM_PDN_EN_RGU_GPS_L1_PRAM_HWCTL_PDN_ADDR GPS_RGU_ON_GPS_L1_DSPPRAM_PDN_EN_ADDR +#define GPS_RGU_ON_GPS_L1_DSPPRAM_PDN_EN_RGU_GPS_L1_PRAM_HWCTL_PDN_MASK 0x000001FF +#define GPS_RGU_ON_GPS_L1_DSPPRAM_PDN_EN_RGU_GPS_L1_PRAM_HWCTL_PDN_SHFT 0 + +#define GPS_RGU_ON_GPS_L1_DSPPRAM_SLP_EN_RGU_GPS_L1_PRAM_HWCTL_SLP_ADDR GPS_RGU_ON_GPS_L1_DSPPRAM_SLP_EN_ADDR +#define GPS_RGU_ON_GPS_L1_DSPPRAM_SLP_EN_RGU_GPS_L1_PRAM_HWCTL_SLP_MASK 0x000001FF +#define GPS_RGU_ON_GPS_L1_DSPPRAM_SLP_EN_RGU_GPS_L1_PRAM_HWCTL_SLP_SHFT 0 + +#define GPS_RGU_ON_GPS_L1_DSPXRAM_PDN_EN_RGU_GPS_L1_XRAM_HWCTL_PDN_ADDR GPS_RGU_ON_GPS_L1_DSPXRAM_PDN_EN_ADDR +#define GPS_RGU_ON_GPS_L1_DSPXRAM_PDN_EN_RGU_GPS_L1_XRAM_HWCTL_PDN_MASK 0x0000000F +#define GPS_RGU_ON_GPS_L1_DSPXRAM_PDN_EN_RGU_GPS_L1_XRAM_HWCTL_PDN_SHFT 0 + +#define GPS_RGU_ON_GPS_L1_DSPXRAM_SLP_EN_RGU_GPS_L1_XRAM_HWCTL_SLP_ADDR GPS_RGU_ON_GPS_L1_DSPXRAM_SLP_EN_ADDR +#define GPS_RGU_ON_GPS_L1_DSPXRAM_SLP_EN_RGU_GPS_L1_XRAM_HWCTL_SLP_MASK 0x0000000F +#define GPS_RGU_ON_GPS_L1_DSPXRAM_SLP_EN_RGU_GPS_L1_XRAM_HWCTL_SLP_SHFT 0 + +#define GPS_RGU_ON_GPS_L1_DSPYRAM_PDN_EN_RGU_GPS_L1_YRAM_HWCTL_PDN_ADDR GPS_RGU_ON_GPS_L1_DSPYRAM_PDN_EN_ADDR +#define GPS_RGU_ON_GPS_L1_DSPYRAM_PDN_EN_RGU_GPS_L1_YRAM_HWCTL_PDN_MASK 0x000001FF +#define GPS_RGU_ON_GPS_L1_DSPYRAM_PDN_EN_RGU_GPS_L1_YRAM_HWCTL_PDN_SHFT 0 + +#define GPS_RGU_ON_GPS_L1_DSPYRAM_SLP_EN_RGU_GPS_L1_YRAM_HWCTL_SLP_ADDR GPS_RGU_ON_GPS_L1_DSPYRAM_SLP_EN_ADDR +#define GPS_RGU_ON_GPS_L1_DSPYRAM_SLP_EN_RGU_GPS_L1_YRAM_HWCTL_SLP_MASK 0x000001FF +#define GPS_RGU_ON_GPS_L1_DSPYRAM_SLP_EN_RGU_GPS_L1_YRAM_HWCTL_SLP_SHFT 0 + +#define GPS_RGU_ON_GPS_L1_DLY_CHAIN_CTL_RGU_GPS_L1_MEM_PDN_DELAY_DUMMY_NUM_ADDR GPS_RGU_ON_GPS_L1_DLY_CHAIN_CTL_ADDR +#define GPS_RGU_ON_GPS_L1_DLY_CHAIN_CTL_RGU_GPS_L1_MEM_PDN_DELAY_DUMMY_NUM_MASK 0x000F0000 +#define GPS_RGU_ON_GPS_L1_DLY_CHAIN_CTL_RGU_GPS_L1_MEM_PDN_DELAY_DUMMY_NUM_SHFT 16 + +#define GPS_RGU_ON_GPS_L1_MEM_DLY_CTL_RGU_GPSSYS_L1_MEM_ADJ_DLY_EN_ADDR GPS_RGU_ON_GPS_L1_MEM_DLY_CTL_ADDR +#define GPS_RGU_ON_GPS_L1_MEM_DLY_CTL_RGU_GPSSYS_L1_MEM_ADJ_DLY_EN_MASK 0x80000000 +#define GPS_RGU_ON_GPS_L1_MEM_DLY_CTL_RGU_GPSSYS_L1_MEM_ADJ_DLY_EN_SHFT 31 + +#define GPS_RGU_ON_GPS_L5_CR_RGU_GPS_L5_SOFT_RST_B_ADDR GPS_RGU_ON_GPS_L5_CR_ADDR +#define GPS_RGU_ON_GPS_L5_CR_RGU_GPS_L5_SOFT_RST_B_MASK 0x00000020 +#define GPS_RGU_ON_GPS_L5_CR_RGU_GPS_L5_SOFT_RST_B_SHFT 5 +#define GPS_RGU_ON_GPS_L5_CR_RGU_GPS_L5_ON_ADDR GPS_RGU_ON_GPS_L5_CR_ADDR +#define GPS_RGU_ON_GPS_L5_CR_RGU_GPS_L5_ON_MASK 0x00000001 +#define GPS_RGU_ON_GPS_L5_CR_RGU_GPS_L5_ON_SHFT 0 + +#define GPS_RGU_ON_GPS_L5_DSPPRAM_PDN_EN_RGU_GPS_L5_PRAM_HWCTL_PDN_ADDR GPS_RGU_ON_GPS_L5_DSPPRAM_PDN_EN_ADDR +#define GPS_RGU_ON_GPS_L5_DSPPRAM_PDN_EN_RGU_GPS_L5_PRAM_HWCTL_PDN_MASK 0x000003FF +#define GPS_RGU_ON_GPS_L5_DSPPRAM_PDN_EN_RGU_GPS_L5_PRAM_HWCTL_PDN_SHFT 0 + +#define GPS_RGU_ON_GPS_L5_DSPPRAM_SLP_EN_RGU_GPS_L5_PRAM_HWCTL_SLP_ADDR GPS_RGU_ON_GPS_L5_DSPPRAM_SLP_EN_ADDR +#define GPS_RGU_ON_GPS_L5_DSPPRAM_SLP_EN_RGU_GPS_L5_PRAM_HWCTL_SLP_MASK 0x000003FF +#define GPS_RGU_ON_GPS_L5_DSPPRAM_SLP_EN_RGU_GPS_L5_PRAM_HWCTL_SLP_SHFT 0 + +#define GPS_RGU_ON_GPS_L5_DSPXRAM_PDN_EN_RGU_GPS_L5_XRAM_HWCTL_PDN_ADDR GPS_RGU_ON_GPS_L5_DSPXRAM_PDN_EN_ADDR +#define GPS_RGU_ON_GPS_L5_DSPXRAM_PDN_EN_RGU_GPS_L5_XRAM_HWCTL_PDN_MASK 0x0000000F +#define GPS_RGU_ON_GPS_L5_DSPXRAM_PDN_EN_RGU_GPS_L5_XRAM_HWCTL_PDN_SHFT 0 + +#define GPS_RGU_ON_GPS_L5_DSPXRAM_SLP_EN_RGU_GPS_L5_XRAM_HWCTL_SLP_ADDR GPS_RGU_ON_GPS_L5_DSPXRAM_SLP_EN_ADDR +#define GPS_RGU_ON_GPS_L5_DSPXRAM_SLP_EN_RGU_GPS_L5_XRAM_HWCTL_SLP_MASK 0x0000000F +#define GPS_RGU_ON_GPS_L5_DSPXRAM_SLP_EN_RGU_GPS_L5_XRAM_HWCTL_SLP_SHFT 0 + +#define GPS_RGU_ON_GPS_L5_DSPYRAM_PDN_EN_RGU_GPS_L5_YRAM_HWCTL_PDN_ADDR GPS_RGU_ON_GPS_L5_DSPYRAM_PDN_EN_ADDR +#define GPS_RGU_ON_GPS_L5_DSPYRAM_PDN_EN_RGU_GPS_L5_YRAM_HWCTL_PDN_MASK 0x000003FF +#define GPS_RGU_ON_GPS_L5_DSPYRAM_PDN_EN_RGU_GPS_L5_YRAM_HWCTL_PDN_SHFT 0 + +#define GPS_RGU_ON_GPS_L5_DSPYRAM_SLP_EN_RGU_GPS_L5_YRAM_HWCTL_SLP_ADDR GPS_RGU_ON_GPS_L5_DSPYRAM_SLP_EN_ADDR +#define GPS_RGU_ON_GPS_L5_DSPYRAM_SLP_EN_RGU_GPS_L5_YRAM_HWCTL_SLP_MASK 0x000003FF +#define GPS_RGU_ON_GPS_L5_DSPYRAM_SLP_EN_RGU_GPS_L5_YRAM_HWCTL_SLP_SHFT 0 + +#define GPS_RGU_ON_GPS_L5_DLY_CHAIN_CTL_RGU_GPS_L5_MEM_PDN_DELAY_DUMMY_NUM_ADDR GPS_RGU_ON_GPS_L5_DLY_CHAIN_CTL_ADDR +#define GPS_RGU_ON_GPS_L5_DLY_CHAIN_CTL_RGU_GPS_L5_MEM_PDN_DELAY_DUMMY_NUM_MASK 0x000F0000 +#define GPS_RGU_ON_GPS_L5_DLY_CHAIN_CTL_RGU_GPS_L5_MEM_PDN_DELAY_DUMMY_NUM_SHFT 16 + +#define GPS_RGU_ON_GPS_L5_MEM_DLY_CTL_RGU_GPSSYS_L5_MEM_ADJ_DLY_EN_ADDR GPS_RGU_ON_GPS_L5_MEM_DLY_CTL_ADDR +#define GPS_RGU_ON_GPS_L5_MEM_DLY_CTL_RGU_GPSSYS_L5_MEM_ADJ_DLY_EN_MASK 0x80000000 +#define GPS_RGU_ON_GPS_L5_MEM_DLY_CTL_RGU_GPSSYS_L5_MEM_ADJ_DLY_EN_SHFT 31 + +#endif /* __GPS_RGU_ON_REGS_H__ */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_sys_adrdec.h b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_sys_adrdec.h new file mode 100644 index 0000000000000..5a81b94aa3040 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_sys_adrdec.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ +#ifndef __GPS_SYS_ADRDEC_REGS_H__ +#define __GPS_SYS_ADRDEC_REGS_H__ + +#define GPS_SYS_ADRDEC_BASE 0x80070400 + + + + +#endif /* __GPS_SYS_ADRDEC_REGS_H__ */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_usrt_apb.h b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_usrt_apb.h new file mode 100644 index 0000000000000..99153d3608ec2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/coda_gen/gps/gps_usrt_apb.h @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ +#ifndef __GPS_USRT_APB_REGS_H__ +#define __GPS_USRT_APB_REGS_H__ + +#define GPS_USRT_APB_BASE 0x80073000 + +#define GPS_USRT_APB_GPS_APB_DATA_ADDR (GPS_USRT_APB_BASE + 0x0000) +#define GPS_USRT_APB_APB_CTRL_ADDR (GPS_USRT_APB_BASE + 0x0004) +#define GPS_USRT_APB_APB_INTEN_ADDR (GPS_USRT_APB_BASE + 0x0008) +#define GPS_USRT_APB_APB_STA_ADDR (GPS_USRT_APB_BASE + 0x000C) +#define GPS_USRT_APB_MONF_ADDR (GPS_USRT_APB_BASE + 0x0010) +#define GPS_USRT_APB_MCUB_A2DF_ADDR (GPS_USRT_APB_BASE + 0x0020) +#define GPS_USRT_APB_MCUB_D2AF_ADDR (GPS_USRT_APB_BASE + 0x0024) +#define GPS_USRT_APB_MCU_A2D0_ADDR (GPS_USRT_APB_BASE + 0x0030) +#define GPS_USRT_APB_MCU_A2D1_ADDR (GPS_USRT_APB_BASE + 0x0034) +#define GPS_USRT_APB_MCU_D2A0_ADDR (GPS_USRT_APB_BASE + 0x0050) +#define GPS_USRT_APB_MCU_D2A1_ADDR (GPS_USRT_APB_BASE + 0x0054) + + +#define GPS_USRT_APB_APB_CTRL_BYTEN_ADDR GPS_USRT_APB_APB_CTRL_ADDR +#define GPS_USRT_APB_APB_CTRL_BYTEN_MASK 0x00000008 +#define GPS_USRT_APB_APB_CTRL_BYTEN_SHFT 3 +#define GPS_USRT_APB_APB_CTRL_TX_EN_ADDR GPS_USRT_APB_APB_CTRL_ADDR +#define GPS_USRT_APB_APB_CTRL_TX_EN_MASK 0x00000002 +#define GPS_USRT_APB_APB_CTRL_TX_EN_SHFT 1 +#define GPS_USRT_APB_APB_CTRL_RX_EN_ADDR GPS_USRT_APB_APB_CTRL_ADDR +#define GPS_USRT_APB_APB_CTRL_RX_EN_MASK 0x00000001 +#define GPS_USRT_APB_APB_CTRL_RX_EN_SHFT 0 + +#define GPS_USRT_APB_APB_INTEN_NODAIEN_ADDR GPS_USRT_APB_APB_INTEN_ADDR +#define GPS_USRT_APB_APB_INTEN_NODAIEN_MASK 0x00000002 +#define GPS_USRT_APB_APB_INTEN_NODAIEN_SHFT 1 +#define GPS_USRT_APB_APB_INTEN_TXIEN_ADDR GPS_USRT_APB_APB_INTEN_ADDR +#define GPS_USRT_APB_APB_INTEN_TXIEN_MASK 0x00000001 +#define GPS_USRT_APB_APB_INTEN_TXIEN_SHFT 0 + +#define GPS_USRT_APB_APB_STA_RX_UNDR_ADDR GPS_USRT_APB_APB_STA_ADDR +#define GPS_USRT_APB_APB_STA_RX_UNDR_MASK 0x80000000 +#define GPS_USRT_APB_APB_STA_RX_UNDR_SHFT 31 +#define GPS_USRT_APB_APB_STA_RX_OVF_ADDR GPS_USRT_APB_APB_STA_ADDR +#define GPS_USRT_APB_APB_STA_RX_OVF_MASK 0x40000000 +#define GPS_USRT_APB_APB_STA_RX_OVF_SHFT 30 +#define GPS_USRT_APB_APB_STA_RX_EMP_ADDR GPS_USRT_APB_APB_STA_ADDR +#define GPS_USRT_APB_APB_STA_RX_EMP_MASK 0x20000000 +#define GPS_USRT_APB_APB_STA_RX_EMP_SHFT 29 +#define GPS_USRT_APB_APB_STA_RX_FULL_ADDR GPS_USRT_APB_APB_STA_ADDR +#define GPS_USRT_APB_APB_STA_RX_FULL_MASK 0x10000000 +#define GPS_USRT_APB_APB_STA_RX_FULL_SHFT 28 +#define GPS_USRT_APB_APB_STA_TX_UNDR_ADDR GPS_USRT_APB_APB_STA_ADDR +#define GPS_USRT_APB_APB_STA_TX_UNDR_MASK 0x08000000 +#define GPS_USRT_APB_APB_STA_TX_UNDR_SHFT 27 +#define GPS_USRT_APB_APB_STA_TX_OVF_ADDR GPS_USRT_APB_APB_STA_ADDR +#define GPS_USRT_APB_APB_STA_TX_OVF_MASK 0x04000000 +#define GPS_USRT_APB_APB_STA_TX_OVF_SHFT 26 +#define GPS_USRT_APB_APB_STA_TX_EMP_ADDR GPS_USRT_APB_APB_STA_ADDR +#define GPS_USRT_APB_APB_STA_TX_EMP_MASK 0x02000000 +#define GPS_USRT_APB_APB_STA_TX_EMP_SHFT 25 +#define GPS_USRT_APB_APB_STA_TX_FULL_ADDR GPS_USRT_APB_APB_STA_ADDR +#define GPS_USRT_APB_APB_STA_TX_FULL_MASK 0x01000000 +#define GPS_USRT_APB_APB_STA_TX_FULL_SHFT 24 +#define GPS_USRT_APB_APB_STA_TX_ST_ADDR GPS_USRT_APB_APB_STA_ADDR +#define GPS_USRT_APB_APB_STA_TX_ST_MASK 0x00700000 +#define GPS_USRT_APB_APB_STA_TX_ST_SHFT 20 +#define GPS_USRT_APB_APB_STA_RX_ST_ADDR GPS_USRT_APB_APB_STA_ADDR +#define GPS_USRT_APB_APB_STA_RX_ST_MASK 0x00070000 +#define GPS_USRT_APB_APB_STA_RX_ST_SHFT 16 +#define GPS_USRT_APB_APB_STA_REGE_ADDR GPS_USRT_APB_APB_STA_ADDR +#define GPS_USRT_APB_APB_STA_REGE_MASK 0x00000020 +#define GPS_USRT_APB_APB_STA_REGE_SHFT 5 +#define GPS_USRT_APB_APB_STA_URAME_ADDR GPS_USRT_APB_APB_STA_ADDR +#define GPS_USRT_APB_APB_STA_URAME_MASK 0x00000010 +#define GPS_USRT_APB_APB_STA_URAME_SHFT 4 +#define GPS_USRT_APB_APB_STA_TX_IND_ADDR GPS_USRT_APB_APB_STA_ADDR +#define GPS_USRT_APB_APB_STA_TX_IND_MASK 0x00000008 +#define GPS_USRT_APB_APB_STA_TX_IND_SHFT 3 +#define GPS_USRT_APB_APB_STA_NODAINTB_ADDR GPS_USRT_APB_APB_STA_ADDR +#define GPS_USRT_APB_APB_STA_NODAINTB_MASK 0x00000002 +#define GPS_USRT_APB_APB_STA_NODAINTB_SHFT 1 +#define GPS_USRT_APB_APB_STA_TXINTB_ADDR GPS_USRT_APB_APB_STA_ADDR +#define GPS_USRT_APB_APB_STA_TXINTB_MASK 0x00000001 +#define GPS_USRT_APB_APB_STA_TXINTB_SHFT 0 + +#define GPS_USRT_APB_MCUB_A2DF_A2DF3_ADDR GPS_USRT_APB_MCUB_A2DF_ADDR +#define GPS_USRT_APB_MCUB_A2DF_A2DF3_MASK 0x00000008 +#define GPS_USRT_APB_MCUB_A2DF_A2DF3_SHFT 3 + +#define GPS_USRT_APB_MCUB_D2AF_D2AF3_ADDR GPS_USRT_APB_MCUB_D2AF_ADDR +#define GPS_USRT_APB_MCUB_D2AF_D2AF3_MASK 0x00000008 +#define GPS_USRT_APB_MCUB_D2AF_D2AF3_SHFT 3 + +#define GPS_USRT_APB_MCU_A2D1_A2D_1_ADDR GPS_USRT_APB_MCU_A2D1_ADDR +#define GPS_USRT_APB_MCU_A2D1_A2D_1_MASK 0x0000FFFF +#define GPS_USRT_APB_MCU_A2D1_A2D_1_SHFT 0 + +#endif /* __GPS_USRT_APB_REGS_H__ */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/gps_dl_hw_dep_api.h b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/gps_dl_hw_dep_api.h new file mode 100644 index 0000000000000..43cdb537d4d88 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/connac2_0/gps_dl_hw_dep_api.h @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ +#ifndef _GPS_DL_HW_DEP_API_H +#define _GPS_DL_HW_DEP_API_H + +#include "gps_dl_hw_ver.h" +#include "conn_infra/conn_infra_cfg.h" +#include "conn_infra/conn_host_csr_top.h" + +#define GDL_HW_SUPPORT_LIST "SUPPORT:MT6885,MT6893" + +#define GDL_HW_CHECK_CONN_INFRA_VER(p_poll_okay, p_poll_ver) \ + GDL_HW_POLL_ENTRY_VERBOSE(GPS_DL_CONN_INFRA_BUS, \ + CONN_INFRA_CFG_CONN_HW_VER_RO_CONN_HW_VERSION, \ + p_poll_okay, p_poll_ver, POLL_DEFAULT, ( \ + (*p_poll_ver == GDL_HW_CONN_INFRA_VER_MT6885) || \ + (*p_poll_ver == GDL_HW_CONN_INFRA_VER_MT6893)) \ + ) + + +#define GDL_HW_SET_CONN2GPS_SLP_PROT_RX_VAL(val) \ + GDL_HW_SET_CONN_INFRA_ENTRY( \ + CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL_R_CONN2GPS_SLP_PROT_RX_EN, val) + +#define GDL_HW_POLL_CONN2GPS_SLP_PROT_RX_UNTIL_VAL(val, timeout, p_is_okay) \ + GDL_HW_POLL_CONN_INFRA_ENTRY( \ + CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL_R_CONN2GPS_SLP_PROT_RX_RDY, \ + val, timeout, p_is_okay) + + +#define GDL_HW_SET_CONN2GPS_SLP_PROT_TX_VAL(val) \ + GDL_HW_SET_CONN_INFRA_ENTRY( \ + CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL_R_CONN2GPS_SLP_PROT_TX_EN, val) + +#define GDL_HW_POLL_CONN2GPS_SLP_PROT_TX_UNTIL_VAL(val, timeout, p_is_okay) \ + GDL_HW_POLL_CONN_INFRA_ENTRY( \ + CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL_R_CONN2GPS_SLP_PROT_TX_RDY, \ + val, timeout, p_is_okay) + + +#define GDL_HW_SET_GPS2CONN_SLP_PROT_RX_VAL(val) \ + GDL_HW_SET_CONN_INFRA_ENTRY( \ + CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_R_GPS2CONN_SLP_PROT_RX_EN, val) + +#define GDL_HW_POLL_GPS2CONN_SLP_PROT_RX_UNTIL_VAL(val, timeout, p_is_okay) \ + GDL_HW_POLL_CONN_INFRA_ENTRY( \ + CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_R_GPS2CONN_SLP_PROT_RX_RDY, \ + val, timeout, p_is_okay) + + +#define GDL_HW_SET_GPS2CONN_SLP_PROT_TX_VAL(val) \ + GDL_HW_SET_CONN_INFRA_ENTRY( \ + CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_R_GPS2CONN_SLP_PROT_TX_EN, val) + +#define GDL_HW_POLL_GPS2CONN_SLP_PROT_TX_UNTIL_VAL(val, timeout, p_is_okay) \ + GDL_HW_POLL_CONN_INFRA_ENTRY( \ + CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_R_GPS2CONN_SLP_PROT_TX_RDY, \ + val, timeout, p_is_okay) + + +/* For Connac2.0, wait until sleep prot disable done, or after polling 10 x 1ms */ +#define GDL_HW_MAY_WAIT_CONN_INFRA_SLP_PROT_DISABLE_ACK(p_poll_okay) \ + GDL_HW_POLL_CONN_INFRA_ENTRY( \ + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL_CONN_INFRA_ON2OFF_SLP_PROT_ACK, \ + 0, 10 * 1000 * POLL_US, p_poll_okay) + + +/* The dump address list for Connac2.0 */ +#define GDL_HW_DUMP_SLP_RPOT_STATUS() do {\ + gps_dl_bus_rd_opt(GPS_DL_CONN_INFRA_BUS, \ + CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL_ADDR, \ + BMASK_RW_FORCE_PRINT); \ + gps_dl_bus_rd_opt(GPS_DL_CONN_INFRA_BUS, \ + CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_ADDR, \ + BMASK_RW_FORCE_PRINT); \ + } while (0) + + +#if (GPS_DL_HAS_CONNINFRA_DRV) +/* + * For MT6885 and MT6893, conninfra driver do it due to GPS/BT share same bit, + * so do nothing here if conninfra driver ready. + */ +#define GDL_HW_SET_CONN_INFRA_BGF_EN_MT6885_MT6893(val) +#else +#define GDL_HW_SET_CONN_INFRA_BGF_EN_MT6885_MT6893(val) \ + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_INFRA_RGU_BGFYS_ON_TOP_PWR_CTL_BGFSYS_ON_TOP_PWR_ON, val) +#endif +#define GDL_HW_SET_CONN_INFRA_BGF_EN(val) GDL_HW_SET_CONN_INFRA_BGF_EN_MT6885_MT6893(val) + +#define GDL_HW_SET_GPS_FUNC_EN(val) \ + GDL_HW_SET_CONN_INFRA_ENTRY(CONN_INFRA_CFG_GPS_PWRCTRL0_GP_FUNCTION_EN, val) + +#endif /* _GPS_DL_HW_DEP_API_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/gps_dl_hw_api.h b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/gps_dl_hw_api.h new file mode 100644 index 0000000000000..7a13a7bebfe8e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/gps_dl_hw_api.h @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _GPS_DL_HW_API_H +#define _GPS_DL_HW_API_H + +#include "gps_dl_config.h" +#include "gps_dl_dma_buf.h" +#include "gps_dl_hal_api.h" +#include "gps_dl_hal_type.h" + +enum GDL_HW_RET { + HW_OKAY, /* hw CRs access okay */ + E_INV_PARAMS, /* invalid parameters */ + E_RESETTING, /* whole chip reset is on-going */ + E_POLL_TIMEOUT, /* timeout when waiting CR change to excepted value */ + E_MAX +}; + +#if GPS_DL_ON_LINUX +#define GDL_HW_STATUS_POLL_INTERVAL_USEC (1) /* 1us */ +#else +#define GDL_HW_STATUS_POLL_INTERVAL_USEC (2*1000) /* 2ms */ +#endif + +enum dsp_ctrl_enum { + GPS_L1_DSP_ON, + GPS_L1_DSP_OFF, + GPS_L5_DSP_ON, + GPS_L5_DSP_OFF, + GPS_L1_DSP_ENTER_DSLEEP, + GPS_L1_DSP_EXIT_DSLEEP, + GPS_L1_DSP_ENTER_DSTOP, + GPS_L1_DSP_EXIT_DSTOP, + GPS_L5_DSP_ENTER_DSLEEP, + GPS_L5_DSP_EXIT_DSLEEP, + GPS_L5_DSP_ENTER_DSTOP, + GPS_L5_DSP_EXIT_DSTOP, + GPS_L1_DSP_CLEAR_PWR_STAT, + GPS_L5_DSP_CLEAR_PWR_STAT, + GPS_DSP_CTRL_MAX +}; +int gps_dl_hw_gps_dsp_ctrl(enum dsp_ctrl_enum ctrl); +bool gps_dl_hw_gps_dsp_is_off_done(enum gps_dl_link_id_enum link_id); +void gps_dl_hw_gps_adie_force_off(void); +void gps_dl_hw_gps_dump_top_rf_cr(void); + +int gps_dl_hw_gps_common_on(void); +int gps_dl_hw_gps_common_off(void); +bool gps_dl_hw_gps_force_wakeup_conninfra_top_off(bool enable); +void gps_dl_hw_gps_sw_request_emi_usage(bool request); + +enum GDL_HW_RET gps_dl_hw_get_mcub_info( + enum gps_dl_link_id_enum link_id, struct gps_dl_hal_mcub_info *p); + +void gps_dl_hw_clear_mcub_d2a_flag( + enum gps_dl_link_id_enum link_id, unsigned int d2a_flag); + +unsigned int gps_dl_hw_get_mcub_a2d_flag(enum gps_dl_link_id_enum link_id); + +enum GDL_RET_STATUS gps_dl_hw_mcub_dsp_read_request( + enum gps_dl_link_id_enum link_id, u16 dsp_addr); + +void gps_dl_hw_set_gps_emi_remapping(unsigned int _20msb_of_36bit_phy_addr); +unsigned int gps_dl_hw_get_gps_emi_remapping(void); + +void gps_dl_hw_set_dma_start(enum gps_dl_hal_dma_ch_index channel, + struct gdl_hw_dma_transfer *p_transfer); + +void gps_dl_hw_set_dma_stop(enum gps_dl_hal_dma_ch_index channel); + +bool gps_dl_hw_get_dma_int_status(enum gps_dl_hal_dma_ch_index channel); + +unsigned int gps_dl_hw_get_dma_left_len(enum gps_dl_hal_dma_ch_index channel); + +struct gps_dl_hw_dma_status_struct { + unsigned int wrap_count; + unsigned int wrap_to_addr; + unsigned int total_count; + unsigned int config; + unsigned int start_flag; + unsigned int intr_flag; + unsigned int left_count; + unsigned int curr_addr; + unsigned int state; +}; + +void gps_dl_hw_save_dma_status_struct( + enum gps_dl_hal_dma_ch_index ch, struct gps_dl_hw_dma_status_struct *p); + +void gps_dl_hw_print_dma_status_struct( + enum gps_dl_hal_dma_ch_index ch, struct gps_dl_hw_dma_status_struct *p); + +enum GDL_RET_STATUS gps_dl_hw_wait_until_dma_complete_and_stop_it( + enum gps_dl_hal_dma_ch_index ch, int timeout_usec, bool return_if_not_start); + + +struct gps_dl_hw_usrt_status_struct { + unsigned int ctrl_setting; + unsigned int intr_enable; + unsigned int state; + unsigned int mcub_d2a_flag; + unsigned int mcub_d2a_d0; + unsigned int mcub_d2a_d1; + unsigned int mcub_a2d_flag; + unsigned int mcub_a2d_d0; + unsigned int mcub_a2d_d1; +}; + +/* TODO: replace gps_dl_hw_usrt_status_struct */ +struct gps_dl_hw_link_status_struct { + bool usrt_has_data; + bool usrt_has_nodata; + bool rx_dma_done; + bool tx_dma_done; +}; + +void gps_dl_hw_get_link_status( + enum gps_dl_link_id_enum link_id, struct gps_dl_hw_link_status_struct *p); + +void gps_dl_hw_save_usrt_status_struct( + enum gps_dl_link_id_enum link_id, struct gps_dl_hw_usrt_status_struct *p); + +void gps_dl_hw_print_usrt_status_struct( + enum gps_dl_link_id_enum link_id, struct gps_dl_hw_usrt_status_struct *p); + +void gps_dl_hw_dump_sleep_prot_status(void); +void gps_dl_hw_dump_host_csr_gps_info(bool force_show_log); +void gps_dl_hw_dump_host_csr_conninfra_info(bool force_show_log); +void gps_dl_hw_print_hw_status(enum gps_dl_link_id_enum link_id, bool dump_rf_cr); +void gps_dl_hw_do_gps_a2z_dump(void); +void gps_dl_hw_print_usrt_status(enum gps_dl_link_id_enum link_id); +bool gps_dl_hw_poll_usrt_dsp_rx_empty(enum gps_dl_link_id_enum link_id); +void gps_dl_hw_gps_dump_gps_rf_cr(void); +void gps_dl_hw_print_ms_counter_status(void); + +void gps_dl_hw_switch_dsp_jtag(void); + +void gps_dl_hw_usrt_rx_irq_enable( + enum gps_dl_link_id_enum link_id, bool enable); +void gps_dl_hw_usrt_ctrl(enum gps_dl_link_id_enum link_id, + bool is_on, bool is_dma_mode, bool is_1byte_mode); +void gps_dl_hw_usrt_clear_nodata_irq(enum gps_dl_link_id_enum link_id); +bool gps_dl_hw_usrt_has_set_nodata_flag(enum gps_dl_link_id_enum link_id); + + +bool gps_dl_hw_is_pta_clk_cfg_ready(void); +void gps_dl_hw_set_ptk_clk_cfg(void); + +bool gps_dl_hw_is_pta_uart_init_done(void); +bool gps_dl_hw_init_pta_uart(void); +void gps_dl_hw_deinit_pta_uart(void); + +bool gps_dl_hw_is_pta_init_done(void); +void gps_dl_hw_init_pta(void); +void gps_dl_hw_deinit_pta(void); + +void gps_dl_hw_claim_pta_used_by_gps(void); +void gps_dl_hw_disclaim_pta_used_by_gps(void); +void gps_dl_hw_set_pta_blanking_parameter(bool use_direct_path); + +bool gps_dl_hw_take_conn_coex_hw_sema(unsigned int timeout_ms); +void gps_dl_hw_give_conn_coex_hw_sema(void); +bool gps_dl_hw_take_conn_rfspi_hw_sema(unsigned int timeout_ms); +void gps_dl_hw_give_conn_rfspi_hw_sema(void); + +unsigned int gps_dl_hw_get_mcub_a2d1_cfg(enum gps_dl_link_id_enum link_id, bool is_1byte_mode); + +#endif /* _GPS_DL_HW_API_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/gps_dl_hw_type.h b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/gps_dl_hw_type.h new file mode 100644 index 0000000000000..62f9b3517234d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/gps_dl_hw_type.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _GPS_DL_HW_TYPE_H +#define _GPS_DL_HW_TYPE_H + +#include "gps_dl_config.h" + +/* to import u32 series types */ +#if GPS_DL_ON_LINUX +#include +#elif GPS_DL_ON_CTP +#include "kernel_to_ctp.h" +#endif + +typedef u32 conn_reg; + + +#define GPS_DL_HW_INVALID_ADDR (0xFFFFFFFF) + +#endif /* _GPS_DL_HW_TYPE_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/gps_dl_hw_ver.h b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/gps_dl_hw_ver.h new file mode 100644 index 0000000000000..5119e104d3542 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/hw/inc/gps_dl_hw_ver.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ +#ifndef _GPS_DL_HW_VER_H +#define _GPS_DL_HW_VER_H + + +#define GDL_HW_CONN_INFRA_VER_MT6885 (0x20010000) +#define GDL_HW_CONN_INFRA_VER_MT6893 (0x20010101) + + +#define GDL_HW_BGF_VER (0x20010000) + + +#endif /* _GPS_DL_HW_VER_H */ diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/inc/gps_dl_config.h b/drivers/misc/mediatek/connectivity/gps/data_link/inc/gps_dl_config.h new file mode 100644 index 0000000000000..04febfa26eb1b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/inc/gps_dl_config.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _GPS_DL_CONFIG_H +#define _GPS_DL_CONFIG_H + +enum gps_dl_link_id_enum { + GPS_DATA_LINK_ID0 = 0, + GPS_DATA_LINK_ID1 = 1, + GPS_DATA_LINK_NUM = 2, +}; + +#define LINK_ID_IS_VALID(link_id) \ + (((link_id) >= 0) && ((link_id) < GPS_DATA_LINK_NUM)) + +#define CHOOSE_BY_LINK_ID(link_id, val_for_id0, val_for_id1, val_for_otherwise) \ + (!LINK_ID_IS_VALID((link_id)) ? (val_for_otherwise) : ( \ + (link_id == GPS_DATA_LINK_ID0) ? val_for_id0 : val_for_id1)) + +#ifdef GPS_DL_HAS_MOCK +#define GPS_DL_HW_IS_MOCK (1) +#define GPS_DL_MOCK_HAL (1) +#else +#define GPS_DL_HW_IS_MOCK (0) +#define GPS_DL_MOCK_HAL (0) +#endif + +#define GPS_DL_MOCK_RX_TIMEOUT (0) + +#define GPS_DL_ON_LINUX (1) +#define GPS_DL_ON_CTP (0) + +#define GPS_DL_HAS_CTRLD (1) +#define GPS_DL_NO_USE_IRQ (0) +#define GPS_DL_USE_THREADED_IRQ (1) + +#ifndef GPS_DL_HAS_CONNINFRA_DRV +#define GPS_DL_HAS_CONNINFRA_DRV (0) +#endif + +#define GPS_DL_HAS_PLAT_DRV (1) +#define GPS_DL_HAS_PTA (1) +#define GPS_DL_USE_TIA (0) + +#define GPS_DL_IS_MODULE (1) + +#define GPS_DL_USE_MTK_SYNC_WRITE (1) +#define GPS_DL_SET_EMI_MPU_CFG (1) +#define GPS_DL_GET_RSV_MEM_IN_MODULE (0) + + +#include "gps_dl_log.h" + +#endif /* _GPS_DL_CONFIG_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/inc/gps_dl_context.h b/drivers/misc/mediatek/connectivity/gps/data_link/inc/gps_dl_context.h new file mode 100644 index 0000000000000..402aa01877bb5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/inc/gps_dl_context.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _GPS_DL_CONTEXT_H +#define _GPS_DL_CONTEXT_H + +#include "gps_dl_config.h" +#include "gps_each_link.h" +#include "gps_dl_isr.h" + +#if GPS_DL_ON_LINUX +#include "gps_each_device.h" +#include "gps_dl_linux.h" +#include "gps_dl_ctrld.h" +#define GPS_DL_TX_BUF_SIZE (8 * 1024) +#define GPS_DL_RX_BUF_SIZE (8 * 1024) +#else +#define GPS_DL_TX_BUF_SIZE (4 * 1024) +#define GPS_DL_RX_BUF_SIZE (4 * 1024) +#endif + +struct gps_dl_remap_ctx { + unsigned int gps_emi_phy_high20; +}; + +struct gps_dl_ctx { + int major; + int minor; +#if GPS_DL_ON_LINUX + struct gps_each_device devices[GPS_DATA_LINK_NUM]; +#endif + struct gps_each_link links[GPS_DATA_LINK_NUM]; + struct gps_each_irq irqs[GPS_DL_IRQ_NUM]; + struct gps_dl_remap_ctx remap_ctx; +}; + +struct gps_dl_remap_ctx *gps_dl_remap_ctx_get(void); + +struct gps_dl_runtime_cfg { + bool dma_is_1byte_mode; + bool dma_is_enabled; + bool show_reg_rw_log; + bool show_reg_wait_log; + bool only_show_wait_done_log; + enum gps_dl_log_level_enum log_level; + unsigned int log_mod_bitmask; + unsigned int log_reg_rw_bitmask; +}; + +bool gps_dl_is_1byte_mode(void); +bool gps_dl_is_dma_enabled(void); + +bool gps_dl_show_reg_rw_log(void); +bool gps_dl_show_reg_wait_log(void); +bool gps_dl_only_show_wait_done_log(void); + +bool gps_dl_set_1byte_mode(bool is_1byte_mode); +bool gps_dl_set_dma_enabled(bool to_enable); + +bool gps_dl_set_show_reg_rw_log(bool on); +void gps_dl_set_show_reg_wait_log(bool on); + +int gps_dl_set_rx_transfer_max(enum gps_dl_link_id_enum link_id, int max); +int gps_dl_set_tx_transfer_max(enum gps_dl_link_id_enum link_id, int max); + +#endif /* _GPS_DL_CONTEXT_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/inc/gps_dl_log.h b/drivers/misc/mediatek/connectivity/gps/data_link/inc/gps_dl_log.h new file mode 100644 index 0000000000000..b82c94cf5a5a5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/inc/gps_dl_log.h @@ -0,0 +1,255 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _GPS_DL_LOG_H +#define _GPS_DL_LOG_H + +#include "gps_dl_config.h" +#if GPS_DL_ON_LINUX +#include +#elif GPS_DL_ON_CTP +#include "gps_dl_ctp_log.h" +#endif + +enum gps_dl_log_level_enum { + GPS_DL_LOG_LEVEL_DBG = 1, + GPS_DL_LOG_LEVEL_INFO = 3, + GPS_DL_LOG_LEVEL_WARN = 5, + GPS_DL_LOG_LEVEL_ERR = 7, +}; + +enum gps_dl_log_module_enum { + GPS_DL_LOG_MOD_DEFAULT = 0, + GPS_DL_LOG_MOD_OPEN_CLOSE = 1, + GPS_DL_LOG_MOD_READ_WRITE = 2, + GPS_DL_LOG_MOD_REG_RW = 3, + GPS_DL_LOG_MOD_STATUS = 4, + GPS_DL_LOG_MOD_EVENT = 5, + GPS_DL_LOG_MOD_INIT = 6, + + GPS_DL_LOG_MOD_MAX = 32 +}; + +enum gps_dl_log_reg_rw_ctrl_enum { + GPS_DL_REG_RW_HOST_CSR_PTA_INIT, + GPS_DL_REG_RW_HOST_CSR_GPS_OFF, + GPS_DL_REG_RW_EMI_SW_REQ_CTRL, + GPS_DL_REG_RW_MCUB_IRQ_HANDLER, + + GPS_DL_REG_RW_MAX = 32 +}; + +#define GPS_DL_LOG_DEF_SETTING_LEVEL GPS_DL_LOG_LEVEL_INFO +#define GPS_DL_LOG_DEF_SETTING_MODULES ( \ + (1UL << GPS_DL_LOG_MOD_DEFAULT) | \ + (1UL << GPS_DL_LOG_MOD_OPEN_CLOSE) | \ + (0UL << GPS_DL_LOG_MOD_READ_WRITE) | \ + (1UL << GPS_DL_LOG_MOD_REG_RW) | \ + (1UL << GPS_DL_LOG_MOD_STATUS) | \ + (0UL << GPS_DL_LOG_MOD_EVENT) | \ + (1UL << GPS_DL_LOG_MOD_INIT) | \ + 0) +#define GPS_DL_LOG_REG_RW_BITMASK ( \ + (0UL << GPS_DL_REG_RW_HOST_CSR_PTA_INIT) |\ + (0UL << GPS_DL_REG_RW_HOST_CSR_GPS_OFF) |\ + (0UL << GPS_DL_REG_RW_EMI_SW_REQ_CTRL) |\ + (0UL << GPS_DL_REG_RW_MCUB_IRQ_HANDLER) |\ + 0) + +enum gps_dl_log_level_enum gps_dl_log_level_get(void); +void gps_dl_log_level_set(enum gps_dl_log_level_enum level); + +unsigned int gps_dl_log_mod_bitmask_get(void); +void gps_dl_log_mod_bitmask_set(unsigned int bitmask); +bool gps_dl_log_mod_is_on(enum gps_dl_log_module_enum mod); +void gps_dl_log_mod_on(enum gps_dl_log_module_enum mod); +void gps_dl_log_mod_off(enum gps_dl_log_module_enum mod); + +bool gps_dl_log_reg_rw_is_on(enum gps_dl_log_reg_rw_ctrl_enum log_reg_rw); + +void gps_dl_log_info_show(void); + + +#if GPS_DL_ON_LINUX +#define __GDL_LOGE(mod, fmt, ...) pr_notice("GDL[E:%d] [%s:%d]: "fmt, \ + mod, __func__, __LINE__, ##__VA_ARGS__) +#define __GDL_LOGW(mod, fmt, ...) pr_notice("GDL[W:%d] [%s:%d]: "fmt, \ + mod, __func__, __LINE__, ##__VA_ARGS__) +#define __GDL_LOGI(mod, fmt, ...) pr_info("GDL[I:%d] [%s:%d]: "fmt, \ + mod, __func__, __LINE__, ##__VA_ARGS__) +#define __GDL_LOGD(mod, fmt, ...) pr_info("GDL[D:%d] [%s:%d]: "fmt, \ + mod, __func__, __LINE__, ##__VA_ARGS__) + +#define __GDL_LOGXE(mod, link_id, fmt, ...) pr_notice("GDL-%d[E:%d] [%s:%d]: "fmt, \ + link_id, mod, __func__, __LINE__, ##__VA_ARGS__) + +#define __GDL_LOGXW(mod, link_id, fmt, ...) pr_notice("GDL-%d[W:%d] [%s:%d]: "fmt, \ + link_id, mod, __func__, __LINE__, ##__VA_ARGS__) + +#define __GDL_LOGXI(mod, link_id, fmt, ...) pr_info("GDL-%d[I:%d] [%s:%d]: "fmt, \ + link_id, mod, __func__, __LINE__, ##__VA_ARGS__) + +#define __GDL_LOGXD(mod, link_id, fmt, ...) pr_info("GDL-%d[D:%d] [%s:%d]: "fmt, \ + link_id, mod, __func__, __LINE__, ##__VA_ARGS__) +#endif /* GPS_DL_ON_XX */ + + +#define _GDL_LOGE(...) \ + do { if (gps_dl_log_level_get() <= GPS_DL_LOG_LEVEL_ERR) __GDL_LOGE(__VA_ARGS__); } while (0) +#define _GDL_LOGW(...) \ + do { if (gps_dl_log_level_get() <= GPS_DL_LOG_LEVEL_WARN) __GDL_LOGW(__VA_ARGS__); } while (0) +#define _GDL_LOGI(...) \ + do { if (gps_dl_log_level_get() <= GPS_DL_LOG_LEVEL_INFO) __GDL_LOGI(__VA_ARGS__); } while (0) +#define _GDL_LOGD(...) \ + do { if (gps_dl_log_level_get() <= GPS_DL_LOG_LEVEL_DBG) __GDL_LOGD(__VA_ARGS__); } while (0) +#define _GDL_LOGXE(...) \ + do { if (gps_dl_log_level_get() <= GPS_DL_LOG_LEVEL_ERR) __GDL_LOGXE(__VA_ARGS__); } while (0) +#define _GDL_LOGXW(...) \ + do { if (gps_dl_log_level_get() <= GPS_DL_LOG_LEVEL_WARN) __GDL_LOGXW(__VA_ARGS__); } while (0) +#define _GDL_LOGXI(...) \ + do { if (gps_dl_log_level_get() <= GPS_DL_LOG_LEVEL_INFO) __GDL_LOGXI(__VA_ARGS__); } while (0) +#define _GDL_LOGXD(...) \ + do { if (gps_dl_log_level_get() <= GPS_DL_LOG_LEVEL_DBG) __GDL_LOGXD(__VA_ARGS__); } while (0) + + +#define GDL_LOGE2(mod, ...) \ + do { if (1) \ + _GDL_LOGE(mod, __VA_ARGS__); } while (0) +#define GDL_LOGW2(mod, ...) \ + do { if (1) \ + _GDL_LOGW(mod, __VA_ARGS__); } while (0) +#define GDL_LOGI2(mod, ...) \ + do { if (gps_dl_log_mod_is_on(mod)) \ + _GDL_LOGI(mod, __VA_ARGS__); } while (0) +#define GDL_LOGD2(mod, ...) \ + do { if (gps_dl_log_mod_is_on(mod)) \ + _GDL_LOGD(mod, __VA_ARGS__); } while (0) + +/* Usage: + * 1. Bellow macro can be used to output log: + * err level: GDL_LOGE, GDL_LOGE_YYY, GDL_LOGXE, GDL_LOGXE_YYY + * warn level: GDL_LOGW, GDL_LOGW_YYY, GDL_LOGXW, GDL_LOGXW_YYY + * info level: GDL_LOGI, GDL_LOGI_YYY, GDL_LOGXI, GDL_LOGXI_YYY + * dbg level: GDL_LOGD, GDL_LOGE_YYY, GDL_LOGXD, GDL_LOGXD_YYY + * + * 2. _YYY stands for log module(group), the list are: + * _ONF for device/link open or close flow + * _DRW for devcie/link read or write flow + * _RRW for hw register read or write flow + * _STA for state machine related flow + * _EVT for event processing related flow + * _INI for device initialization/deinitializaion flow + * if they are used, the log can be easily filtered by keywords like "[E:2]", "[I:5]" and so on + * if you don't know which to use, just use: GDL_LOG* or GDL_LOGX*, which have no _YYY subfix + * + * 3. Log of info and dbg level can be showed seeing log level and module setting meet: + * a) log level setting <= INFO or DBG and + * b) log module bitmask bit is 1 for the module + * + * 4. Log of warn and err level is showed only seeing log level: + * a) log level setting <= WARN or ERR + * + * 5. Difference between GDL_LOG* and GDL_LOGX*: + * GDL_LOG* can be used like: GDL_LOGD("a = %d", a) + * GDL_LOGX* can take a parameters of link_id, like: GDL_LOGXD(link_id, "a = %d", a) + */ +#define GDL_LOGE(...) GDL_LOGE2(GPS_DL_LOG_MOD_DEFAULT, __VA_ARGS__) +#define GDL_LOGW(...) GDL_LOGW2(GPS_DL_LOG_MOD_DEFAULT, __VA_ARGS__) +#define GDL_LOGI(...) GDL_LOGI2(GPS_DL_LOG_MOD_DEFAULT, __VA_ARGS__) +#define GDL_LOGD(...) GDL_LOGD2(GPS_DL_LOG_MOD_DEFAULT, __VA_ARGS__) + +#define GDL_LOGD_ONF(...) GDL_LOGD2(GPS_DL_LOG_MOD_OPEN_CLOSE, __VA_ARGS__) + +#define GDL_LOGI_DRW(...) GDL_LOGI2(GPS_DL_LOG_MOD_READ_WRITE, __VA_ARGS__) + +#define GDL_LOGW_RRW(...) GDL_LOGI2(GPS_DL_LOG_MOD_REG_RW, __VA_ARGS__) +#define GDL_LOGI_RRW(...) GDL_LOGI2(GPS_DL_LOG_MOD_REG_RW, __VA_ARGS__) + +#define GDL_LOGE_EVT(...) GDL_LOGE2(GPS_DL_LOG_MOD_EVENT, __VA_ARGS__) +#define GDL_LOGW_EVT(...) GDL_LOGW2(GPS_DL_LOG_MOD_EVENT, __VA_ARGS__) +#define GDL_LOGD_EVT(...) GDL_LOGD2(GPS_DL_LOG_MOD_EVENT, __VA_ARGS__) + +#define GDL_LOGE_INI(...) GDL_LOGE2(GPS_DL_LOG_MOD_INIT, __VA_ARGS__) +#define GDL_LOGW_INI(...) GDL_LOGW2(GPS_DL_LOG_MOD_INIT, __VA_ARGS__) +#define GDL_LOGI_INI(...) GDL_LOGI2(GPS_DL_LOG_MOD_INIT, __VA_ARGS__) +#define GDL_LOGD_INI(...) GDL_LOGD2(GPS_DL_LOG_MOD_INIT, __VA_ARGS__) + +#define GDL_LOGXE2(mod, ...) \ + do { if (1) \ + _GDL_LOGXE(mod, __VA_ARGS__); } while (0) +#define GDL_LOGXW2(mod, ...) \ + do { if (1) \ + _GDL_LOGXW(mod, __VA_ARGS__); } while (0) +#define GDL_LOGXI2(mod, ...) \ + do { if (gps_dl_log_mod_is_on(mod)) \ + _GDL_LOGXI(mod, __VA_ARGS__); } while (0) +#define GDL_LOGXD2(mod, ...) \ + do { if (gps_dl_log_mod_is_on(mod)) \ + _GDL_LOGXD(mod, __VA_ARGS__); } while (0) + +#define GDL_LOGXE(...) GDL_LOGXE2(GPS_DL_LOG_MOD_DEFAULT, __VA_ARGS__) +#define GDL_LOGXW(...) GDL_LOGXW2(GPS_DL_LOG_MOD_DEFAULT, __VA_ARGS__) +#define GDL_LOGXI(...) GDL_LOGXI2(GPS_DL_LOG_MOD_DEFAULT, __VA_ARGS__) +#define GDL_LOGXD(...) GDL_LOGXD2(GPS_DL_LOG_MOD_DEFAULT, __VA_ARGS__) + +#define GDL_LOGXE_ONF(...) GDL_LOGXE2(GPS_DL_LOG_MOD_OPEN_CLOSE, __VA_ARGS__) +#define GDL_LOGXW_ONF(...) GDL_LOGXW2(GPS_DL_LOG_MOD_OPEN_CLOSE, __VA_ARGS__) +#define GDL_LOGXI_ONF(...) GDL_LOGXI2(GPS_DL_LOG_MOD_OPEN_CLOSE, __VA_ARGS__) +#define GDL_LOGXD_ONF(...) GDL_LOGXD2(GPS_DL_LOG_MOD_OPEN_CLOSE, __VA_ARGS__) + +#define GDL_LOGXE_DRW(...) GDL_LOGXE2(GPS_DL_LOG_MOD_READ_WRITE, __VA_ARGS__) +#define GDL_LOGXW_DRW(...) GDL_LOGXW2(GPS_DL_LOG_MOD_READ_WRITE, __VA_ARGS__) +#define GDL_LOGXI_DRW(...) GDL_LOGXI2(GPS_DL_LOG_MOD_READ_WRITE, __VA_ARGS__) +#define GDL_LOGXD_DRW(...) GDL_LOGXD2(GPS_DL_LOG_MOD_READ_WRITE, __VA_ARGS__) + +#define GDL_LOGXE_STA(...) GDL_LOGXE2(GPS_DL_LOG_MOD_STATUS, __VA_ARGS__) +#define GDL_LOGXW_STA(...) GDL_LOGXW2(GPS_DL_LOG_MOD_STATUS, __VA_ARGS__) +#define GDL_LOGXI_STA(...) GDL_LOGXI2(GPS_DL_LOG_MOD_STATUS, __VA_ARGS__) + +#define GDL_LOGXW_EVT(...) GDL_LOGXW2(GPS_DL_LOG_MOD_EVENT, __VA_ARGS__) +#define GDL_LOGXI_EVT(...) GDL_LOGXI2(GPS_DL_LOG_MOD_EVENT, __VA_ARGS__) +#define GDL_LOGXD_EVT(...) GDL_LOGXD2(GPS_DL_LOG_MOD_EVENT, __VA_ARGS__) + +#define GDL_LOGXE_INI(...) GDL_LOGXE2(GPS_DL_LOG_MOD_INIT, __VA_ARGS__) +#define GDL_LOGXI_INI(...) GDL_LOGXI2(GPS_DL_LOG_MOD_INIT, __VA_ARGS__) +#define GDL_LOGXD_INI(...) GDL_LOGXD2(GPS_DL_LOG_MOD_INIT, __VA_ARGS__) + + +#define GDL_ASSERT(cond, ret, fmt, ...) \ + do { if (!(cond)) { \ + GDL_LOGE("{** GDL_ASSERT: [(%s) = %d] **}: "fmt, \ + #cond, (cond), ##__VA_ARGS__); \ + return ret; \ + } } while (0) + +void GDL_VOIDF(void); + +#define GDL_ASSERT_RET_OKAY(gdl_ret) \ + GDL_ASSERT((callee_ret) != GDL_OKAY, GDL_FAIL_ASSERT, "") + +#define GDL_ASSERT_RET_NOT_ASSERT(callee_ret, ret_to_caller) \ + GDL_ASSERT((callee_ret) == GDL_FAIL_ASSERT, ret_to_caller, "") + +#define ASSERT_NOT_ZERO(val, ret)\ + GDL_ASSERT(val != 0, ret, "%s should not be 0!", #val) + +#define ASSERT_ZERO(val, ret)\ + GDL_ASSERT(val == 0, ret, "%s should be 0!", #val) + +#define ASSERT_NOT_NULL(ptr, ret)\ + GDL_ASSERT(ptr != NULL, ret, "null ptr!") + +#define ASSERT_LINK_ID(link_id, ret) \ + GDL_ASSERT(LINK_ID_IS_VALID(link_id), ret, "invalid link_id: %d", link_id) + +#endif /* _GPS_DL_LOG_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/inc/gps_each_link.h b/drivers/misc/mediatek/connectivity/gps/data_link/inc/gps_each_link.h new file mode 100644 index 0000000000000..0876ada70de91 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/inc/gps_each_link.h @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _GPS_EACH_LINK_H +#define _GPS_EACH_LINK_H + +#include "gps_dl_config.h" + +#if GPS_DL_ON_LINUX +#include +#endif + +#if GPS_DL_ON_CTP +#include "gps_dl_ctp_osal.h" +#endif + +#if GPS_DL_HAS_CTRLD +#include "gps_dl_ctrld.h" +#endif + +#include "gps_dl_subsys_reset.h" +#include "gps_dl_dma_buf.h" + +struct gps_each_link_cfg { + int tx_buf_size; + int rx_buf_size; +}; + +enum gps_each_link_waitable_type { + GPS_DL_WAIT_OPEN_CLOSE, + GPS_DL_WAIT_WRITE, + GPS_DL_WAIT_READ, + GPS_DL_WAIT_RESET, + GPS_DL_WAIT_NUM +}; + +struct gps_each_link_state_list { + bool is_ready_to_write; + bool is_active; + bool to_be_closed; + bool is_resetting; + bool open_result_okay; + bool user_open; + bool need_a2z_dump; + bool suspend_to_clk_ext; +}; + +enum gps_each_link_bool_state { + LINK_WRITE_READY, + LINK_IS_ACTIVE, + LINK_TO_BE_CLOSED, + LINK_USER_OPEN, + LINK_WAIT_RESET_DONE, + LINK_IS_RESETTING, + LINK_OPEN_RESULT_OKAY, + LINK_NEED_A2Z_DUMP, + LINK_SUSPEND_TO_CLK_EXT, + BOOL_STATE_NUM +}; + +void gps_each_link_set_bool_flag(enum gps_dl_link_id_enum link_id, + enum gps_each_link_bool_state name, bool value); +bool gps_each_link_get_bool_flag(enum gps_dl_link_id_enum link_id, + enum gps_each_link_bool_state name); + +bool gps_dl_link_is_ready_to_write(enum gps_dl_link_id_enum link_id); +void gps_dl_link_set_ready_to_write(enum gps_dl_link_id_enum link_id, bool is_ready); + +bool gps_each_link_is_active(enum gps_dl_link_id_enum link_id); +void gps_each_link_set_active(enum gps_dl_link_id_enum link_id, bool is_active); + +enum gps_each_link_wait_status { + WAITING, + OKAY, + FAIL, + SIGNAL, +}; + +struct gps_each_link_waitable { +#if GPS_DL_ON_LINUX + /* TODO: use completion */ + wait_queue_head_t wq; +#endif + bool fired; + bool waiting; + enum gps_each_link_wait_status status; + enum gps_each_link_waitable_type type; +}; + +enum gps_each_link_mutex { + GPS_DL_MTX_BIG_LOCK, + GPS_DL_MTX_NUM +}; + +void gps_each_link_mutex_take(enum gps_dl_link_id_enum link_id, enum gps_each_link_mutex mtx_id); +void gps_each_link_mutex_give(enum gps_dl_link_id_enum link_id, enum gps_each_link_mutex mtx_id); + +enum gps_each_link_spinlock { + GPS_DL_SPINLOCK_FOR_LINK_STATE, + GPS_DL_SPINLOCK_FOR_DMA_BUF, + GPS_DL_SPINLOCK_NUM +}; + +void gps_each_link_spin_lock_take(enum gps_dl_link_id_enum link_id, enum gps_each_link_spinlock spin_lock_id); +void gps_each_link_spin_lock_give(enum gps_dl_link_id_enum link_id, enum gps_each_link_spinlock spin_lock_id); + + +enum gps_each_link_state_enum { + LINK_UNINIT, + LINK_CLOSED, + LINK_OPENING, + LINK_OPENED, + LINK_CLOSING, + LINK_RESETTING, /* Not distinguish EACH_LINK or WHOLE_GPS or WHOLE_CONNSYS */ + LINK_RESET_DONE, + LINK_DISABLED, + LINK_SUSPENDING, + LINK_SUSPENDED, + LINK_RESUMING, + LINK_STATE_NUM +}; + +#define GPS_EACH_LINK_SID_MAX (0x7FFFFFFE) +#define GPS_EACH_LINK_SID_NO_CHECK (0xFFFFFFFF) +struct gps_each_link { + struct gps_each_link_cfg cfg; + struct gps_each_device *p_device; + struct gps_dl_dma_buf tx_dma_buf; + struct gps_dl_dma_buf rx_dma_buf; + struct gps_each_link_waitable waitables[GPS_DL_WAIT_NUM]; + struct gps_dl_osal_sleepable_lock mutexes[GPS_DL_MTX_NUM]; + struct gps_dl_osal_unsleepable_lock spin_locks[GPS_DL_SPINLOCK_NUM]; + struct gps_each_link_state_list sub_states; + enum gps_each_link_state_enum state_for_user; + enum gps_each_link_reset_level reset_level; + int session_id; +}; + +void gps_each_link_mutexes_init(struct gps_each_link *p); +void gps_each_link_mutexes_deinit(struct gps_each_link *p); +void gps_each_link_spin_locks_init(struct gps_each_link *p); +void gps_each_link_spin_locks_deinit(struct gps_each_link *p); + + +struct gps_common_context { + struct gps_dl_osal_sleepable_lock big_lock; +}; + +/* only ctrld can change it */ +struct gps_dl_ctrl_context { + bool gps_reset; + bool connsys_reset; +}; + +struct gps_each_link *gps_dl_link_get(enum gps_dl_link_id_enum link_id); + +void gps_each_link_init(enum gps_dl_link_id_enum link_id); +void gps_each_link_deinit(enum gps_dl_link_id_enum link_id); +void gps_each_link_context_init(enum gps_dl_link_id_enum link_id); +void gps_each_link_context_clear(enum gps_dl_link_id_enum link_id); +void gps_each_link_inc_session_id(enum gps_dl_link_id_enum link_id); +int gps_each_link_get_session_id(enum gps_dl_link_id_enum link_id); + +int gps_each_link_open(enum gps_dl_link_id_enum link_id); +void gps_dl_link_open_ack(enum gps_dl_link_id_enum link_id, bool okay, bool hw_resume); + +enum gps_each_link_lock_reason { + GDL_LOCK_FOR_OPEN, + GDL_LOCK_FOR_OPEN_DONE, + GDL_LOCK_FOR_CLOSE, + GDL_LOCK_FOR_CLOSE_DONE, + GDL_LOCK_FOR_RESET, + GDL_LOCK_FOR_RESET_DONE, +}; + +enum gps_each_link_state_enum gps_each_link_get_state(enum gps_dl_link_id_enum link_id); +void gps_each_link_set_state(enum gps_dl_link_id_enum link_id, enum gps_each_link_state_enum state); +bool gps_each_link_change_state_from(enum gps_dl_link_id_enum link_id, + enum gps_each_link_state_enum from, enum gps_each_link_state_enum to); + + +int gps_each_link_take_big_lock(enum gps_dl_link_id_enum link_id, + enum gps_each_link_lock_reason reason); +int gps_each_link_give_big_lock(enum gps_dl_link_id_enum link_id); + +int gps_each_link_reset(enum gps_dl_link_id_enum link_id); +void gps_dl_link_reset_ack(enum gps_dl_link_id_enum link_id); +void gps_dl_link_on_post_conn_reset(enum gps_dl_link_id_enum link_id); +bool gps_dl_link_try_to_clear_both_resetting_status(void); +int gps_dl_link_get_clock_flag(void); + +enum gps_each_link_close_or_suspend_op { + GDL_CLOSE, + GDL_DPSTOP, + GDL_CLKEXT, +}; +int gps_each_link_enter_dsleep(enum gps_dl_link_id_enum link_id); +int gps_each_link_leave_dsleep(enum gps_dl_link_id_enum link_id); +int gps_each_link_hw_suspend(enum gps_dl_link_id_enum link_id, bool need_clk_ext); +int gps_each_link_hw_resume(enum gps_dl_link_id_enum link_id); +int gps_each_link_close(enum gps_dl_link_id_enum link_id); +int gps_each_link_check(enum gps_dl_link_id_enum link_id, int reason); + +int gps_each_link_write(enum gps_dl_link_id_enum link_id, + unsigned char *buf, unsigned int len); +int gps_each_link_write_with_opt(enum gps_dl_link_id_enum link_id, + unsigned char *buf, unsigned int len, bool wait_tx_done); +int gps_each_link_read(enum gps_dl_link_id_enum link_id, + unsigned char *buf, unsigned int len); +int gps_each_link_read_with_timeout(enum gps_dl_link_id_enum link_id, + unsigned char *buf, unsigned int len, int timeout_usec, bool *p_is_nodata); + +bool gps_dl_link_start_tx_dma_if_has_data(enum gps_dl_link_id_enum link_id); + +void gps_dl_link_waitable_init(struct gps_each_link_waitable *p, + enum gps_each_link_waitable_type type); + +void gps_dl_link_waitable_reset(enum gps_dl_link_id_enum link_id, enum gps_each_link_waitable_type type); + +enum GDL_RET_STATUS gps_dl_link_wait_on(struct gps_each_link_waitable *p, long *p_sigval); + +enum GDL_RET_STATUS gps_dl_link_try_wait_on(enum gps_dl_link_id_enum link_id, + enum gps_each_link_waitable_type type); + +void gps_dl_link_wake_up(struct gps_each_link_waitable *p); + +enum gps_dl_link_event_id { + GPS_DL_EVT_LINK_OPEN, + GPS_DL_EVT_LINK_CLOSE, + GPS_DL_EVT_LINK_WRITE, + GPS_DL_EVT_LINK_READ, + GPS_DL_EVT_LINK_DSP_ROM_READY_TIMEOUT, + GPS_DL_EVT_LINK_DSP_FSM_TIMEOUT, + GPS_DL_EVT_LINK_RESET_DSP, + GPS_DL_EVT_LINK_RESET_GPS, + GPS_DL_EVT_LINK_PRE_CONN_RESET, + GPS_DL_EVT_LINK_POST_CONN_RESET, + GPS_DL_EVT_LINK_PRINT_HW_STATUS, + GPS_DL_EVT_LINK_ENTER_DPSLEEP, + GPS_DL_EVT_LINK_LEAVE_DPSLEEP, + GPS_DL_EVT_LINK_ENTER_DPSTOP, + GPS_DL_EVT_LINK_LEAVE_DPSTOP, + GPS_DL_EVT_LINK_UPDATE_SETTING, + GPS_DL_EVT_LINK_PRINT_DATA_STATUS, + GPS_DL_LINK_EVT_NUM, +}; + +void gps_dl_link_event_send(enum gps_dl_link_event_id evt, + enum gps_dl_link_id_enum link_id); + +void gps_dl_link_event_proc(enum gps_dl_link_event_id evt, + enum gps_dl_link_id_enum link_id); + +#endif /* _GPS_EACH_LINK_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/lib/gps_dl_dma_buf.c b/drivers/misc/mediatek/connectivity/gps/data_link/lib/gps_dl_dma_buf.c new file mode 100644 index 0000000000000..8e2ff3a870687 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/lib/gps_dl_dma_buf.c @@ -0,0 +1,722 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "gps_dl_config.h" +#include "gps_dl_context.h" + +#include "gps_dl_dma_buf.h" +#if GPS_DL_ON_LINUX +#include "asm/barrier.h" +#endif + +#define GDL_COUNT_FREE(r, w, l)\ + ((w >= r) ? (l + r - w) : (r - w)) + +#define GDL_COUNT_DATA(r, w, l)\ + ((w >= r) ? (w - r) : (l + w - r)) + +void gps_dma_buf_reset(struct gps_dl_dma_buf *p_dma) +{ + gps_each_link_spin_lock_take(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF); + p_dma->read_index = 0; + p_dma->reader_working = 0; + p_dma->write_index = 0; + p_dma->writer_working = 0; + p_dma->dma_working_entry.is_valid = false; + p_dma->entry_r = 0; + p_dma->entry_w = 0; + memset(&p_dma->data_entries[0], 0, sizeof(p_dma->data_entries)); + gps_each_link_spin_lock_give(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF); + + GDL_LOGXD(p_dma->dev_index, "dir = %d", p_dma->dir); +} + +void gps_dma_buf_show(struct gps_dl_dma_buf *p_dma, bool is_warning) +{ + unsigned int ri, wi, fl, re, we, fe; + bool r_working, w_working; + + gps_each_link_spin_lock_take(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF); + ri = p_dma->read_index; + r_working = p_dma->reader_working; + wi = p_dma->write_index; + w_working = p_dma->writer_working; + fl = GDL_COUNT_FREE(p_dma->read_index, p_dma->writer_working, p_dma->len); + re = p_dma->entry_r; + we = p_dma->entry_w; + fe = GDL_COUNT_FREE(p_dma->entry_r, p_dma->entry_w, GPS_DL_DMA_BUF_ENTRY_MAX); + gps_each_link_spin_lock_give(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF); + + if (is_warning) { + GDL_LOGXW_DRW(p_dma->dev_index, + "dir = %d, l = %d, r = %d(%d), w = %d(%d), fl = %d, re = %d, we = %d, fe = %d", + p_dma->dir, p_dma->len, ri, r_working, wi, w_working, fl, re, we, fe); + } else { + GDL_LOGXD_DRW(p_dma->dev_index, + "dir = %d, l = %d, r = %d(%d), w = %d(%d), fl = %d, re = %d, we = %d, fe = %d", + p_dma->dir, p_dma->len, ri, r_working, wi, w_working, fl, re, we, fe); + } +} + +void gps_dma_buf_align_as_byte_mode(struct gps_dl_dma_buf *p_dma) +{ + unsigned int ri, wi; + unsigned int ri_new, wi_new; + + gps_each_link_spin_lock_take(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF); + ri = p_dma->read_index; + wi = p_dma->write_index; + + if (!gps_dl_is_1byte_mode()) { + p_dma->read_index = ((p_dma->read_index + 3) / 4) * 4; + if (p_dma->read_index >= p_dma->len) + p_dma->read_index -= p_dma->len; + p_dma->reader_working = 0; + + p_dma->write_index = ((p_dma->write_index + 3) / 4) * 4; + if (p_dma->write_index >= p_dma->len) + p_dma->write_index -= p_dma->len; + p_dma->writer_working = 0; + p_dma->dma_working_entry.is_valid = false; + } + + ri_new = p_dma->read_index; + wi_new = p_dma->write_index; + + /* clear it anyway */ + p_dma->read_index = p_dma->write_index; + gps_each_link_spin_lock_give(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF); + + GDL_LOGXD(p_dma->dev_index, "is_1byte = %d, ri: %u -> %u, wi: %u -> %u", + gps_dl_is_1byte_mode(), ri, ri_new, wi, wi_new); +} + +#if 0 +enum GDL_RET_STATUS gdl_dma_buf_init(struct gps_dl_dma_buf *p_dma_buf) +{ + return GDL_OKAY; +} + +enum GDL_RET_STATUS gdl_dma_buf_deinit(struct gps_dl_dma_buf *p_dma_buf) +{ + return GDL_OKAY; +} +#endif + +bool gps_dma_buf_is_empty(struct gps_dl_dma_buf *p_dma) +{ + bool is_empty; + + gps_each_link_spin_lock_take(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF); + is_empty = (p_dma->read_index == p_dma->write_index); + gps_each_link_spin_lock_give(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF); + + return is_empty; +} + +enum GDL_RET_STATUS gdl_dma_buf_put(struct gps_dl_dma_buf *p_dma, + const unsigned char *p_buf, unsigned int buf_len) +{ + struct gdl_dma_buf_entry entry; + struct gdl_dma_buf_entry *p_entry = &entry; + + /* unsigned int free_len; */ + /* unsigned int wrap_len; */ + enum GDL_RET_STATUS gdl_ret; + + ASSERT_NOT_NULL(p_dma, GDL_FAIL_ASSERT); + ASSERT_NOT_NULL(p_buf, GDL_FAIL_ASSERT); + + gdl_ret = gdl_dma_buf_get_free_entry(p_dma, p_entry, false); + + if (GDL_OKAY != gdl_ret) + return gdl_ret; + +#if 0 + free_len = GDL_COUNT_FREE(p_entry->read_index, + p_entry->write_index, p_entry->buf_length); + GDL_LOGD("r=%u, w=%u, l=%u, f=%u", p_entry->read_index, + p_entry->write_index, p_entry->buf_length, free_len); + + if (free_len < buf_len) { + gdl_dma_buf_set_free_entry(p_dma, NULL); + return GDL_FAIL_NOSPACE; + } + + wrap_len = p_entry->buf_length - p_entry->write_index; + if (wrap_len >= buf_len) { + memcpy(((unsigned char *)p_entry->vir_addr) + p_entry->write_index, + p_buf, buf_len); + + p_entry->write_index += buf_len; + if (p_entry->write_index >= p_entry->buf_length) + p_entry->write_index = 0; + } else { + memcpy(((unsigned char *)p_entry->vir_addr) + p_entry->write_index, + p_buf, wrap_len); + + memcpy(((unsigned char *)p_entry->vir_addr) + 0, + p_buf + wrap_len, buf_len - wrap_len); + + p_entry->write_index = buf_len - wrap_len; + } +#endif + gdl_ret = gdl_dma_buf_buf_to_entry(p_entry, p_buf, buf_len, + &p_entry->write_index); + + if (GDL_OKAY != gdl_ret) + return gdl_ret; + + /* TODO: make a data entry */ + + GDL_LOGD("new_w=%u", p_entry->write_index); + gdl_dma_buf_set_free_entry(p_dma, p_entry); + + return GDL_OKAY; +} + +enum GDL_RET_STATUS gdl_dma_buf_get(struct gps_dl_dma_buf *p_dma, + unsigned char *p_buf, unsigned int buf_len, unsigned int *p_data_len, + bool *p_is_nodata) +{ + struct gdl_dma_buf_entry entry; + struct gdl_dma_buf_entry *p_entry = &entry; + + /* unsigned int data_len; */ + /* unsigned int wrap_len; */ + enum GDL_RET_STATUS gdl_ret; + + ASSERT_NOT_NULL(p_entry, GDL_FAIL_ASSERT); + ASSERT_NOT_NULL(p_buf, GDL_FAIL_ASSERT); + ASSERT_NOT_ZERO(buf_len, GDL_FAIL_ASSERT); + ASSERT_NOT_NULL(p_data_len, GDL_FAIL_ASSERT); + + gdl_ret = gdl_dma_buf_get_data_entry(p_dma, p_entry); + + if (GDL_OKAY != gdl_ret) + return gdl_ret; + +#if 0 + data_len = GDL_COUNT_DATA(p_entry->read_index, + p_entry->write_index, p_entry->buf_length); + GDL_LOGD("r=%u, w=%u, l=%u, d=%u", p_entry->read_index, + p_entry->write_index, p_entry->buf_length, data_len); + + /* assert data_len > 0 */ + + if (data_len > buf_len) { + /* TODO: improve it */ + gdl_dma_buf_set_data_entry(p_dma, p_entry); + return GDL_FAIL_NOSPACE; + } + + if (p_entry->write_index > p_entry->read_index) { + memcpy(p_buf, ((unsigned char *)p_entry->vir_addr) + p_entry->read_index, + data_len); + } else { + wrap_len = p_entry->buf_length - p_entry->read_index; + + memcpy(p_buf, ((unsigned char *)p_entry->vir_addr) + p_entry->read_index, + wrap_len); + + memcpy(p_buf + wrap_len, ((unsigned char *)p_entry->vir_addr) + 0, + data_len - wrap_len); + } +#endif + gdl_ret = gdl_dma_buf_entry_to_buf(p_entry, p_buf, buf_len, p_data_len); + + if (GDL_OKAY != gdl_ret) + return gdl_ret; + + /* Todo: Case1: buf < data in entry */ + /* Note: we can limit the rx transfer max to 512, then case1 should not be happened */ + + /* Todo: Case2: buf > data in entry, need to combine multiple entry until no data entry? */ + + if (p_is_nodata) + *p_is_nodata = p_entry->is_nodata; + + /* *p_data_len = data_len; */ + p_entry->read_index = p_entry->write_index; + gdl_dma_buf_set_data_entry(p_dma, p_entry); + + return GDL_OKAY; +} + +static enum GDL_RET_STATUS gdl_dma_buf_get_data_entry_inner(struct gps_dl_dma_buf *p_dma, + struct gdl_dma_buf_entry *p_entry) +{ + struct gdl_dma_buf_entry *p_data_entry; + unsigned int data_len; + + if (p_dma->reader_working) + return GDL_FAIL_BUSY; + + p_dma->reader_working = true; + + if (p_dma->read_index == p_dma->write_index) { + p_dma->reader_working = false; + return GDL_FAIL_NODATA; + } + + if (p_dma->entry_r == p_dma->entry_w) { + /* impossible: has data but no data entry */ + p_dma->reader_working = false; + return GDL_FAIL_NOENTRY; + } + + p_data_entry = &p_dma->data_entries[p_dma->entry_r]; + p_entry->write_index = p_data_entry->write_index; + p_entry->is_nodata = p_data_entry->is_nodata; + if ((p_dma->transfer_max > 0) && (p_dma->dir == GDL_DMA_A2D)) { + data_len = GDL_COUNT_DATA(p_data_entry->read_index, + p_data_entry->write_index, p_data_entry->buf_length); + + if (data_len > p_dma->transfer_max) { + p_entry->write_index = p_data_entry->read_index + p_dma->transfer_max; + if (p_entry->write_index >= p_data_entry->buf_length) + p_entry->write_index -= p_data_entry->buf_length; + p_entry->is_nodata = false; + } + } + p_entry->read_index = p_data_entry->read_index; + p_entry->buf_length = p_data_entry->buf_length; + p_entry->phy_addr = p_data_entry->phy_addr; + p_entry->vir_addr = p_data_entry->vir_addr; + p_entry->is_valid = true; + return GDL_OKAY; +} +enum GDL_RET_STATUS gdl_dma_buf_get_data_entry(struct gps_dl_dma_buf *p_dma, + struct gdl_dma_buf_entry *p_entry) +{ + enum GDL_RET_STATUS ret; + + ASSERT_NOT_NULL(p_dma, GDL_FAIL_ASSERT); + ASSERT_NOT_NULL(p_entry, GDL_FAIL_ASSERT); + + gps_each_link_spin_lock_take(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF); + ret = gdl_dma_buf_get_data_entry_inner(p_dma, p_entry); + gps_each_link_spin_lock_give(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF); + + return ret; +} + + +static enum GDL_RET_STATUS gdl_dma_buf_set_data_entry_inner(struct gps_dl_dma_buf *p_dma, + struct gdl_dma_buf_entry *p_entry) +{ + struct gdl_dma_buf_entry *p_data_entry; + + if (!p_dma->reader_working) + return GDL_FAIL_STATE_MISMATCH; + + if (NULL == p_entry) { + p_dma->reader_working = false; + return GDL_OKAY; + } + + if (p_dma->entry_r == p_dma->entry_w) { + /* impossible due to get_data_entry already check it */ + p_dma->writer_working = false; + return GDL_FAIL_NOENTRY2; + } + + p_data_entry = &p_dma->data_entries[p_dma->entry_r]; + if (p_entry->write_index == p_data_entry->write_index) { + p_data_entry->is_valid = false; + p_dma->entry_r++; + if (p_dma->entry_r >= GPS_DL_DMA_BUF_ENTRY_MAX) + p_dma->entry_r = 0; + } else + p_data_entry->read_index = p_entry->write_index; + + p_dma->read_index = p_entry->write_index; + p_dma->reader_working = false; + return GDL_OKAY; +} + +enum GDL_RET_STATUS gdl_dma_buf_set_data_entry(struct gps_dl_dma_buf *p_dma, + struct gdl_dma_buf_entry *p_entry) +{ + enum GDL_RET_STATUS ret; + + ASSERT_NOT_NULL(p_dma, GDL_FAIL_ASSERT); + + gps_each_link_spin_lock_take(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF); + ret = gdl_dma_buf_set_data_entry_inner(p_dma, p_entry); + gps_each_link_spin_lock_give(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF); + + return ret; +} + + +static enum GDL_RET_STATUS gdl_dma_buf_get_free_entry_inner(struct gps_dl_dma_buf *p_dma, + struct gdl_dma_buf_entry *p_entry) +{ + unsigned int free_len; + + if (p_dma->writer_working) + return GDL_FAIL_BUSY; + + p_dma->writer_working = true; + + if (GDL_COUNT_FREE(p_dma->read_index, p_dma->write_index, p_dma->len) <= 1) { + /* dma buf is full */ + p_dma->writer_working = false; + return GDL_FAIL_NOSPACE; + } + + if (GDL_COUNT_FREE(p_dma->entry_r, p_dma->entry_w, GPS_DL_DMA_BUF_ENTRY_MAX) <= 1) { + /* entries is all used (not use the last one) */ + p_dma->writer_working = false; + return GDL_FAIL_NOENTRY; + } + + p_entry->read_index = p_dma->read_index; + if ((p_dma->transfer_max > 0) && (p_dma->dir == GDL_DMA_D2A)) { + /* the free space is between write_index to read_index, + * if transfer_max set and free_len > it, + * limit the free space from write_index to write_index + transfer_max + */ + free_len = GDL_COUNT_FREE(p_dma->read_index, p_dma->write_index, p_dma->len); + if (free_len > p_dma->transfer_max) { + p_entry->read_index = p_dma->write_index + p_dma->transfer_max; + if (p_entry->read_index >= p_dma->len) + p_entry->read_index -= p_dma->len; + } + } + p_entry->write_index = p_dma->write_index; + p_entry->buf_length = p_dma->len; + p_entry->phy_addr = p_dma->phy_addr; + p_entry->vir_addr = p_dma->vir_addr; + p_entry->is_valid = true; + + /* This field not used for free entry, just make static analysis tool happy. */ + p_entry->is_nodata = false; + return GDL_OKAY; +} + +enum GDL_RET_STATUS gdl_dma_buf_get_free_entry(struct gps_dl_dma_buf *p_dma, + struct gdl_dma_buf_entry *p_entry, bool nospace_set_pending_rx) +{ + enum GDL_RET_STATUS ret; + + ASSERT_NOT_NULL(p_dma, GDL_FAIL_ASSERT); + ASSERT_NOT_NULL(p_entry, GDL_FAIL_ASSERT); + + gps_each_link_spin_lock_take(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF); + ret = gdl_dma_buf_get_free_entry_inner(p_dma, p_entry); + if (nospace_set_pending_rx && + (ret == GDL_FAIL_NOSPACE || ret == GDL_FAIL_NOENTRY)) { + p_dma->has_pending_rx = true; + ret = GDL_FAIL_NOSPACE_PENDING_RX; + } + gps_each_link_spin_lock_give(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF); + + return ret; +} + +static enum GDL_RET_STATUS gdl_dma_buf_set_free_entry_inner(struct gps_dl_dma_buf *p_dma, + struct gdl_dma_buf_entry *p_entry) +{ + struct gdl_dma_buf_entry *p_data_entry; + + if (!p_dma->writer_working) + return GDL_FAIL_STATE_MISMATCH; + + if (GDL_COUNT_FREE(p_dma->entry_r, p_dma->entry_w, GPS_DL_DMA_BUF_ENTRY_MAX) <= 1) { + /* impossible due to get_free_entry already check it */ + p_dma->writer_working = false; + return GDL_FAIL_NOENTRY2; + } + + p_data_entry = &p_dma->data_entries[p_dma->entry_w]; + p_dma->entry_w++; + if (p_dma->entry_w >= GPS_DL_DMA_BUF_ENTRY_MAX) + p_dma->entry_w = 0; + + p_data_entry->read_index = p_dma->write_index; + p_data_entry->write_index = p_entry->write_index; + p_data_entry->buf_length = p_dma->len; + p_data_entry->phy_addr = p_dma->phy_addr; + p_data_entry->vir_addr = p_dma->vir_addr; + p_data_entry->is_valid = true; + p_data_entry->is_nodata = p_entry->is_nodata; + + p_dma->write_index = p_entry->write_index; + p_dma->writer_working = false; + + return GDL_OKAY; +} + +enum GDL_RET_STATUS gdl_dma_buf_set_free_entry(struct gps_dl_dma_buf *p_dma, + struct gdl_dma_buf_entry *p_entry) +{ + enum GDL_RET_STATUS ret; + + ASSERT_NOT_NULL(p_dma, GDL_FAIL_ASSERT); + ASSERT_NOT_NULL(p_entry, GDL_FAIL_ASSERT); + + gps_each_link_spin_lock_take(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF); + ret = gdl_dma_buf_set_free_entry_inner(p_dma, p_entry); + gps_each_link_spin_lock_give(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF); + + return ret; +} + + +void gps_dma_buf_memcpy_from_rx(void *p_dst, const void *p_src, unsigned int len) +{ + /* TODO: + * __dma_unmap_area((void *)p_dst, len, DMA_FROM_DEVICE); + * dma_sync_single_for_cpu(DMA_FROM_DEVICE); + */ +#if GPS_DL_ON_LINUX + memcpy_fromio(p_dst, p_src, len); +#elif GPS_DL_ON_CTP + /* gps_dl_ctp_memcpy((unsigned char *)p_dst, (const unsigned char *)p_src, len); */ + memcpy(p_dst, p_src, len); +#else + memcpy(p_dst, p_src, len); +#endif +} + +void gps_dma_buf_memcpy_to_tx(void *p_dst, const void *p_src, unsigned int len) +{ +#if GPS_DL_ON_LINUX + memcpy_toio(p_dst, p_src, len); +#elif GPS_DL_ON_CTP + /* gps_dl_ctp_memcpy((unsigned char *)p_dst, (const unsigned char *)p_src, len); */ + memcpy(p_dst, p_src, len); +#else + memcpy(p_dst, p_src, len); +#endif + /* Use mb to make sure memcpy is done by CPU, and then DMA can be started. */ + mb(); + /* TODO: + * __dma_flush_area((void *)p_dst, len); + * dma_sync_single_for_device(DMA_TO_DEVICE); + */ +} + +void gps_dma_buf_memset_io(void *p_dst, unsigned char val, unsigned int len) +{ +#if GPS_DL_ON_LINUX + memset_io(p_dst, val, len); +#elif GPS_DL_ON_CTP + gps_dl_ctp_memset((unsigned char *)p_dst, val, len); +#else + memset(p_dst, val, len); +#endif + /* Use mb to make sure memcpy is done by CPU, and then DMA can be started. */ + mb(); + /* TODO: + * __dma_flush_area((void *)p_dst, len); + * dma_sync_single_for_device(DMA_TO_DEVICE); + */ +} + +enum GDL_RET_STATUS gdl_dma_buf_entry_to_buf(const struct gdl_dma_buf_entry *p_entry, + unsigned char *p_buf, unsigned int buf_len, unsigned int *p_data_len) +{ + unsigned int data_len; + unsigned int wrap_len; + unsigned char *p_src; + + ASSERT_NOT_NULL(p_entry, GDL_FAIL_ASSERT); + ASSERT_NOT_NULL(p_buf, GDL_FAIL_ASSERT); + ASSERT_NOT_ZERO(buf_len, GDL_FAIL_ASSERT); + ASSERT_NOT_NULL(p_data_len, GDL_FAIL_ASSERT); + + data_len = GDL_COUNT_DATA(p_entry->read_index, + p_entry->write_index, p_entry->buf_length); + GDL_LOGD("r=%u, w=%u, l=%u, d=%u", p_entry->read_index, + p_entry->write_index, p_entry->buf_length, data_len); + + if (data_len > buf_len) { + *p_data_len = 0; + return GDL_FAIL_NOSPACE; + } + + if (p_entry->write_index > p_entry->read_index) { + p_src = ((unsigned char *)p_entry->vir_addr) + p_entry->read_index; + gps_dma_buf_memcpy_from_rx(p_buf, p_src, data_len); + } else { + wrap_len = p_entry->buf_length - p_entry->read_index; + + p_src = ((unsigned char *)p_entry->vir_addr) + p_entry->read_index; + gps_dma_buf_memcpy_from_rx(p_buf, p_src, wrap_len); + + p_src = ((unsigned char *)p_entry->vir_addr) + 0; + gps_dma_buf_memcpy_from_rx(p_buf + wrap_len, p_src, data_len - wrap_len); + } + + *p_data_len = data_len; + return GDL_OKAY; +} + +enum GDL_RET_STATUS gdl_dma_buf_buf_to_entry(const struct gdl_dma_buf_entry *p_entry, + const unsigned char *p_buf, unsigned int data_len, unsigned int *p_write_index) +{ + unsigned int free_len; + unsigned int wrap_len; + unsigned int write_index; + unsigned int alligned_data_len; + unsigned int fill_zero_len; + unsigned char *p_dst; + + if (gps_dl_is_1byte_mode()) { + alligned_data_len = data_len; + fill_zero_len = 0; + } else { + alligned_data_len = ((data_len + 3) / 4) * 4; + fill_zero_len = alligned_data_len - data_len; + GDL_LOGD("data_len = %u, alligned = %u", data_len, alligned_data_len); + } + + ASSERT_NOT_NULL(p_entry, GDL_FAIL_ASSERT); + ASSERT_NOT_NULL(p_buf, GDL_FAIL_ASSERT); + ASSERT_NOT_ZERO(data_len, GDL_FAIL_ASSERT); + ASSERT_NOT_NULL(p_write_index, GDL_FAIL_ASSERT); + + /* TODO: make dma done event */ + + free_len = GDL_COUNT_FREE(p_entry->read_index, + p_entry->write_index, p_entry->buf_length); + + GDL_LOGD("r=%u, w=%u, l=%u, f=%u", p_entry->read_index, + p_entry->write_index, p_entry->buf_length, free_len); + + if (free_len < alligned_data_len) + return GDL_FAIL_NOSPACE; + + wrap_len = p_entry->buf_length - p_entry->write_index; + if (wrap_len >= data_len) { + p_dst = ((unsigned char *)p_entry->vir_addr) + p_entry->write_index; + gps_dma_buf_memcpy_to_tx(p_dst, p_buf, data_len); + + write_index = p_entry->write_index + data_len; + if (write_index >= p_entry->buf_length) + write_index = 0; + } else { + p_dst = ((unsigned char *)p_entry->vir_addr) + p_entry->write_index; + gps_dma_buf_memcpy_to_tx(p_dst, p_buf, wrap_len); + + p_dst = ((unsigned char *)p_entry->vir_addr) + 0; + gps_dma_buf_memcpy_to_tx(p_dst, p_buf + wrap_len, data_len - wrap_len); + + write_index = data_len - wrap_len; + } + + /* fill it to allignment */ + if (fill_zero_len > 0) { + wrap_len = p_entry->buf_length - write_index; + if (wrap_len >= fill_zero_len) { + p_dst = ((unsigned char *)p_entry->vir_addr) + write_index; + gps_dma_buf_memset_io(p_dst, 0, fill_zero_len); + + write_index += fill_zero_len; + if (write_index >= p_entry->buf_length) + write_index = 0; + } else { + /* impossible case when buf_len is an integral multiple of 4byte */ + p_dst = ((unsigned char *)p_entry->vir_addr) + write_index; + gps_dma_buf_memset_io(p_dst, 0, wrap_len); + + p_dst = ((unsigned char *)p_entry->vir_addr) + 0; + gps_dma_buf_memset_io(p_dst, 0, fill_zero_len - wrap_len); + + write_index = fill_zero_len - wrap_len; + } + } + + GDL_LOGD("new_w=%u", write_index); + *p_write_index = write_index; + + return GDL_OKAY; +} + +enum GDL_RET_STATUS gdl_dma_buf_entry_to_transfer( + const struct gdl_dma_buf_entry *p_entry, + struct gdl_hw_dma_transfer *p_transfer, bool is_tx) +{ + ASSERT_NOT_NULL(p_entry, GDL_FAIL_ASSERT); + ASSERT_NOT_NULL(p_transfer, GDL_FAIL_ASSERT); + + p_transfer->buf_start_addr = (unsigned int)p_entry->phy_addr; + if (is_tx) { + p_transfer->transfer_start_addr = + (unsigned int)p_entry->phy_addr + p_entry->read_index; + p_transfer->len_to_wrap = p_entry->buf_length - p_entry->read_index; + p_transfer->transfer_max_len = GDL_COUNT_DATA( + p_entry->read_index, p_entry->write_index, p_entry->buf_length); + + if (!gps_dl_is_1byte_mode()) { + p_transfer->len_to_wrap /= 4; + p_transfer->transfer_max_len /= 4; + } + } else { + p_transfer->transfer_start_addr = + (unsigned int)p_entry->phy_addr + p_entry->write_index; + p_transfer->len_to_wrap = p_entry->buf_length - p_entry->write_index; + p_transfer->transfer_max_len = GDL_COUNT_FREE( + p_entry->read_index, p_entry->write_index, p_entry->buf_length); + + if (!gps_dl_is_1byte_mode()) { + p_transfer->len_to_wrap /= 4; + p_transfer->transfer_max_len /= 4; + } + } + + GDL_LOGD("r=%u, w=%u, l=%u, is_tx=%d, transfer: ba=0x%08x, ta=0x%08x, wl=%d, tl=%d", + p_entry->read_index, p_entry->write_index, p_entry->buf_length, is_tx, + p_transfer->buf_start_addr, p_transfer->buf_start_addr, + p_transfer->len_to_wrap, p_transfer->transfer_max_len); + + ASSERT_NOT_ZERO(p_transfer->buf_start_addr, GDL_FAIL_ASSERT); + ASSERT_NOT_ZERO(p_transfer->transfer_start_addr, GDL_FAIL_ASSERT); + ASSERT_NOT_ZERO(p_transfer->len_to_wrap, GDL_FAIL_ASSERT); + ASSERT_NOT_ZERO(p_transfer->transfer_max_len, GDL_FAIL_ASSERT); + + return GDL_OKAY; +} + +enum GDL_RET_STATUS gdl_dma_buf_entry_transfer_left_to_write_index( + const struct gdl_dma_buf_entry *p_entry, + unsigned int left_len, unsigned int *p_write_index) +{ + unsigned int free_len; + unsigned int new_write_index; + + ASSERT_NOT_NULL(p_entry, GDL_FAIL_ASSERT); + ASSERT_NOT_NULL(p_write_index, GDL_FAIL_ASSERT); + + free_len = GDL_COUNT_FREE(p_entry->read_index, + p_entry->write_index, p_entry->buf_length); + + GDL_ASSERT(free_len > left_len, GDL_FAIL_ASSERT, ""); + + new_write_index = p_entry->write_index + free_len - left_len; + if (new_write_index >= p_entry->buf_length) + new_write_index -= p_entry->buf_length; + + GDL_LOGD("r=%u, w=%u, l=%u, left=%d, new_w=%d", + p_entry->read_index, p_entry->write_index, p_entry->buf_length, + left_len, new_write_index); + GDL_ASSERT(new_write_index < p_entry->buf_length, GDL_FAIL_ASSERT, ""); + + *p_write_index = new_write_index; + + return GDL_OKAY; +} + + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/lib/gps_dl_hist_rec.c b/drivers/misc/mediatek/connectivity/gps/data_link/lib/gps_dl_hist_rec.c new file mode 100644 index 0000000000000..03068ac9954c5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/lib/gps_dl_hist_rec.c @@ -0,0 +1,159 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#include "gps_dl_config.h" + +#include "gps_each_link.h" +#include "gps_dl_osal.h" +#include "gps_dl_hist_rec.h" + +enum gps_dl_hist_rec_rw_type { + GPS_DL_HIST_REC_RW_READ, + GPS_DL_HIST_REC_RW_WRITE, + GPS_DL_HIST_REC_RW_TYPE_MAX +}; + +enum gps_dl_hist_rec_rw_dump_point { + GPS_DL_HIST_REC_RW_DUMP_ON_REC_FULL, + GPS_DL_HIST_REC_RW_DUMP_ON_INTERVAL, + GPS_DL_HIST_REC_RW_DUMP_ON_PID_CHANGED, + GPS_DL_HIST_REC_RW_DUMP_ON_FORCE_DUMP, + GPS_DL_HIST_REC_RW_DUMP_ON_ERROR_LEN, +}; + +struct gps_dl_hist_rec_rw_item { + int len; +}; + +#define GPS_DL_HIST_REC_RW_ITEM_MAX (8) +struct gps_dl_hist_rec_rw_list { + struct gps_dl_hist_rec_rw_item items[GPS_DL_HIST_REC_RW_ITEM_MAX]; + unsigned int n_item; + unsigned int rec_idx; + int pid; + enum gps_dl_hist_rec_rw_rec_point rec_point; + enum gps_dl_hist_rec_rw_type type; +}; + +struct gps_dl_hist_rec_rw_list g_gps_dl_hist_rec_rw_list[GPS_DATA_LINK_NUM][GPS_DL_HIST_REC_RW_TYPE_MAX]; + + +static void gps_dl_hist_rec_rw_do_dump(enum gps_dl_link_id_enum link_id, + struct gps_dl_hist_rec_rw_list *p_list, enum gps_dl_hist_rec_rw_dump_point dump_point) +{ + GDL_LOGXW_DRW(link_id, "%s: dp=%d, pid=%d, i=%d, n=%d(%d), l=%d %d %d %d; %d %d %d %d", + (p_list->type == GPS_DL_HIST_REC_RW_READ) ? "rd" : "wr", + dump_point, p_list->pid, p_list->rec_idx, p_list->n_item, p_list->rec_point, + p_list->items[0].len, p_list->items[1].len, p_list->items[2].len, p_list->items[3].len, + p_list->items[4].len, p_list->items[5].len, p_list->items[6].len, p_list->items[7].len); + p_list->rec_idx += p_list->n_item; + p_list->n_item = 0; + memset(&p_list->items, 0, sizeof(p_list->items)); +} + +static void gps_dl_hist_rec_rw_check_dump(enum gps_dl_link_id_enum link_id, + struct gps_dl_hist_rec_rw_list *p_list, enum gps_dl_hist_rec_rw_rec_point rec_point) +{ + if (p_list->n_item > GPS_DL_HIST_REC_RW_ITEM_MAX) { + GDL_LOGXE_DRW(link_id, "type=%d, n_rec=%d, rec_point=%d", + p_list->type, p_list->n_item, rec_point); + p_list->n_item = GPS_DL_HIST_REC_RW_ITEM_MAX; + } + + if (p_list->n_item == GPS_DL_HIST_REC_RW_ITEM_MAX) + gps_dl_hist_rec_rw_do_dump(link_id, p_list, GPS_DL_HIST_REC_RW_DUMP_ON_REC_FULL); +} + +static void gps_dl_hist_rec_rw_add_rec(enum gps_dl_link_id_enum link_id, + enum gps_dl_hist_rec_rw_type type, + enum gps_dl_hist_rec_rw_rec_point rec_point, + int pid, int len) +{ + struct gps_dl_hist_rec_rw_list *p_list; + struct gps_dl_hist_rec_rw_item *p_item; + enum gps_dl_hist_rec_rw_rec_point last_point; + + ASSERT_LINK_ID(link_id, GDL_VOIDF()); + /* TODO: check type & rec_point */ + + /* TODO: protect it by lock */ + p_list = &g_gps_dl_hist_rec_rw_list[link_id][type]; + if (p_list->pid == 0) + p_list->pid = pid; + else if (pid != p_list->pid && rec_point == DRW_RETURN) { + gps_dl_hist_rec_rw_do_dump(link_id, p_list, GPS_DL_HIST_REC_RW_DUMP_ON_PID_CHANGED); + p_list->pid = pid; + } + gps_dl_hist_rec_rw_check_dump(link_id, p_list, rec_point); + + p_item = &p_list->items[p_list->n_item]; + last_point = p_list->rec_point; + p_list->rec_point = rec_point; + + if (last_point == DRW_RETURN && rec_point == DRW_ENTER) { + /* TODO: record tiemstamp */ + p_item->len = len; + } else if (last_point == DRW_ENTER && rec_point == DRW_RETURN) { + p_item->len = len; + p_list->n_item++; + if (len <= 0) + gps_dl_hist_rec_rw_do_dump(link_id, p_list, GPS_DL_HIST_REC_RW_DUMP_ON_PID_CHANGED); + else + gps_dl_hist_rec_rw_check_dump(link_id, p_list, DRW_RETURN); + } else { + GDL_LOGXE_DRW(link_id, "type=%d, n_rec=%d, mismatch rec_point=%d/%d, len=%d, pid=%d", + p_list->type, p_list->n_item, last_point, rec_point, len, pid); + } +} + + +void gps_each_link_rec_read(enum gps_dl_link_id_enum link_id, int pid, int len, + enum gps_dl_hist_rec_rw_rec_point rec_point) +{ + ASSERT_LINK_ID(link_id, GDL_VOIDF()); + gps_each_link_mutex_take(link_id, GPS_DL_MTX_BIG_LOCK); + gps_dl_hist_rec_rw_add_rec(link_id, GPS_DL_HIST_REC_RW_READ, rec_point, pid, len); + gps_each_link_mutex_give(link_id, GPS_DL_MTX_BIG_LOCK); +} + +void gps_each_link_rec_write(enum gps_dl_link_id_enum link_id, int pid, int len, + enum gps_dl_hist_rec_rw_rec_point rec_point) +{ + ASSERT_LINK_ID(link_id, GDL_VOIDF()); + gps_each_link_mutex_take(link_id, GPS_DL_MTX_BIG_LOCK); + gps_dl_hist_rec_rw_add_rec(link_id, GPS_DL_HIST_REC_RW_WRITE, rec_point, pid, len); + gps_each_link_mutex_give(link_id, GPS_DL_MTX_BIG_LOCK); +} + +void gps_each_link_rec_reset(enum gps_dl_link_id_enum link_id) +{ + enum gps_dl_hist_rec_rw_type type; + struct gps_dl_hist_rec_rw_list *p_list; + + ASSERT_LINK_ID(link_id, GDL_VOIDF()); + gps_each_link_mutex_take(link_id, GPS_DL_MTX_BIG_LOCK); + for (type = 0; type < GPS_DL_HIST_REC_RW_TYPE_MAX; type++) { + p_list = &g_gps_dl_hist_rec_rw_list[link_id][type]; + memset(p_list, 0, sizeof(*p_list)); + p_list->type = type; + p_list->rec_point = DRW_RETURN; + } + gps_each_link_mutex_give(link_id, GPS_DL_MTX_BIG_LOCK); +} + +void gps_each_link_rec_force_dump(enum gps_dl_link_id_enum link_id) +{ + enum gps_dl_hist_rec_rw_type type; + struct gps_dl_hist_rec_rw_list *p_list; + + ASSERT_LINK_ID(link_id, GDL_VOIDF()); + gps_each_link_mutex_take(link_id, GPS_DL_MTX_BIG_LOCK); + for (type = 0; type < GPS_DL_HIST_REC_RW_TYPE_MAX; type++) { + p_list = &g_gps_dl_hist_rec_rw_list[link_id][type]; + gps_dl_hist_rec_rw_do_dump(link_id, p_list, GPS_DL_HIST_REC_RW_DUMP_ON_FORCE_DUMP); + } + gps_each_link_mutex_give(link_id, GPS_DL_MTX_BIG_LOCK); +} + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/lib/gps_dl_lib_misc.c b/drivers/misc/mediatek/connectivity/gps/data_link/lib/gps_dl_lib_misc.c new file mode 100644 index 0000000000000..7f1f00c154242 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/lib/gps_dl_lib_misc.c @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "gps_dl_lib_misc.h" +#include "gps_dl_log.h" + +bool gps_dl_hal_comp_buf_match(unsigned char *data_buf, unsigned int data_len, + unsigned char *golden_buf, unsigned int golden_len, unsigned int data_shift) { + bool is_match = true; + + int i; + + if (data_len < golden_len + data_shift) { + GDL_LOGD("not match len: %d, %d, %d", data_len, golden_len, data_shift); + is_match = false; + } + + if (is_match) { + for (i = 0; i < data_shift; i++) { + if (data_buf[i] != 0) { + GDL_LOGD("not fill 0 on start %d: %x", i, data_buf[i]); + is_match = false; + break; + } + } + } + + if (is_match) { + for (; i < data_shift + golden_len; i++) { + if (data_buf[i] != golden_buf[i - data_shift]) { + GDL_LOGD("not match on data[%d] -> %x, gold[%d] -> %x", + i, data_buf[i], i - data_shift, golden_buf[i - data_shift]); + is_match = false; + break; + } + } + } + + if (is_match) { + for (; i < data_len; i++) { + if (data_buf[i] != 0) { + GDL_LOGD("not fill 0 on end %d: %x", i, data_buf[i]); + is_match = false; + break; + } + } + } + + GDL_LOGD("match = %d, data_len = %d, golden_len = %d, data_shift = %d", + is_match, data_len, golden_len, data_shift); + + if (!is_match) { + gps_dl_hal_show_buf("data", data_buf, data_len); + gps_dl_hal_show_buf("golden", golden_buf, golden_len); + } + + return is_match; +} + +#define SHOW_BUF_MAX_LINE 2 +void gps_dl_hal_show_buf(unsigned char *tag, + unsigned char *buf, unsigned int len) +{ + int base = 0, line_idx = 0; + int line_len = 8; + int left_len = len; +#define SHOW_BUF_FMT0 "[%s] len = %u" +#define SHOW_BUF_FMT1 SHOW_BUF_FMT0", data = %02x" +#define SHOW_BUF_FMT2 SHOW_BUF_FMT1" %02x" +#define SHOW_BUF_FMT3 SHOW_BUF_FMT2" %02x" +#define SHOW_BUF_FMT4 SHOW_BUF_FMT3" %02x" +#define SHOW_BUF_FMT5 SHOW_BUF_FMT4", %02x" +#define SHOW_BUF_FMT6 SHOW_BUF_FMT5" %02x" +#define SHOW_BUF_FMT7 SHOW_BUF_FMT6" %02x" +#define SHOW_BUF_FMT8 SHOW_BUF_FMT7" %02x" + +#define SHOW_BUF_ARG0 do {GDL_LOGI_DRW(SHOW_BUF_FMT0, tag, len); } while (0) + +#define SHOW_BUF_ARG1 do {GDL_LOGI_DRW(SHOW_BUF_FMT1, tag, len, buf[base+0]); } while (0) + +#define SHOW_BUF_ARG2 do {GDL_LOGI_DRW(SHOW_BUF_FMT2, tag, len, buf[base+0], buf[base+1]); } while (0) + +#define SHOW_BUF_ARG3 do {GDL_LOGI_DRW(SHOW_BUF_FMT3, tag, len, buf[base+0], buf[base+1], buf[base+2]) \ + ; } while (0) + +#define SHOW_BUF_ARG4 do {GDL_LOGI_DRW(SHOW_BUF_FMT4, tag, len, buf[base+0], buf[base+1], buf[base+2], \ + buf[base+3]); } while (0) + +#define SHOW_BUF_ARG5 do {GDL_LOGI_DRW(SHOW_BUF_FMT5, tag, len, buf[base+0], buf[base+1], buf[base+2], \ + buf[base+3], buf[base+4]); } while (0) + +#define SHOW_BUF_ARG6 do {GDL_LOGI_DRW(SHOW_BUF_FMT6, tag, len, buf[base+0], buf[base+1], buf[base+2], \ + buf[base+3], buf[base+4], buf[base+5]); } while (0) + +#define SHOW_BUF_ARG7 do {GDL_LOGI_DRW(SHOW_BUF_FMT7, tag, len, buf[base+0], buf[base+1], buf[base+2], \ + buf[base+3], buf[base+4], buf[base+5], buf[base+6]); } while (0) + +#define SHOW_BUF_ARG8 do {GDL_LOGI_DRW(SHOW_BUF_FMT8, tag, len, buf[base+0], buf[base+1], buf[base+2], \ + buf[base+3], buf[base+4], buf[base+5], buf[base+6], buf[base+7]); } while (0) + + for (left_len = len, base = 0, line_idx = 0; + left_len > 0 && line_idx < SHOW_BUF_MAX_LINE; + left_len -= 8, base += 8, line_idx++) { + + if (left_len > 8) + line_len = 8; + else + line_len = left_len; + + switch (line_len) { +#if 0 + /* case 0 is impossible */ + case 0: + SHOW_BUF_ARG0; break; +#endif + case 1: + SHOW_BUF_ARG1; break; + case 2: + SHOW_BUF_ARG2; break; + case 3: + SHOW_BUF_ARG3; break; + case 4: + SHOW_BUF_ARG4; break; + case 5: + SHOW_BUF_ARG5; break; + case 6: + SHOW_BUF_ARG6; break; + case 7: + SHOW_BUF_ARG7; break; + default: + SHOW_BUF_ARG8; break; + } + } +} + +void GDL_VOIDF(void) {} + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/lib/gps_dl_name_list.c b/drivers/misc/mediatek/connectivity/gps/data_link/lib/gps_dl_name_list.c new file mode 100644 index 0000000000000..b22a25baa8491 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/lib/gps_dl_name_list.c @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "gps_dl_config.h" + +#include "gps_dl_base.h" +#include "gps_dl_name_list.h" + +#if GPS_DL_ON_LINUX +/* Make sure num for RETURN_NAME_IN_LIST is const to detect coding error such + * as swapping the position of num and index. + * MASK_BE_CONST can be empty if compiler not support the macros used. + */ +#define MUST_BE_CONST(num) BUILD_BUG_ON(!__builtin_constant_p(num)) +#else +#define MUST_BE_CONST(num) +#endif +#define NAME_ON_NULL "(NULL)" +#define RETURN_NAME_IN_LIST(list, num, index, retval) \ + do { \ + MUST_BE_CONST(num); \ + if (((index) >= 0) && ((index) < (num))) { \ + if ((list)[index]) \ + retval = (list)[index]; \ + else { \ + GDL_LOGW("name is null for index: %d", index); \ + retval = NAME_ON_NULL; \ + } \ + } else { \ + GDL_LOGW("name index: %d out of range", index); \ + retval = (list)[num]; \ + } \ + } while (0) + + +const char *const gps_dl_ret_name_list[GDL_RET_NUM + 1] = { + [GDL_OKAY] = "OKAY", + [GDL_FAIL] = "FAIL_GENERAL", + [GDL_FAIL_ASSERT] = "FAIL_ASSERT", + [GDL_FAIL_BUSY] = "FAIL_BUSY", + [GDL_FAIL_NOSPACE] = "FAIL_NOSPACE", + [GDL_FAIL_NOSPACE_PENDING_RX] = "FAIL_NOSPACE_PENDING_RX", + [GDL_FAIL_NODATA] = "FAIL_NODATA", + [GDL_FAIL_STATE_MISMATCH] = "FAIL_STATE_MISMATCH", + [GDL_FAIL_SIGNALED] = "FAIL_SIGNALED", + [GDL_FAIL_TIMEOUT] = "FAIL_TIMEOUT", + [GDL_FAIL_NOT_SUPPORT] = "FAIL_NOT_SUPPORT", + [GDL_FAIL_INVAL] = "FAIL_INVAL", + [GDL_FAIL_NOENTRY] = "FAIL_NOENTRY", + [GDL_FAIL_NOENTRY2] = "FAIL_NOENTRY2", + [GDL_FAIL_CONN_NOT_OKAY] = "FAIL_CONN_NOT_OKAY", + [GDL_RET_NUM] = "FAIL_UNKNOWN" +}; + +const char *gdl_ret_to_name(enum GDL_RET_STATUS gdl_ret) +{ + const char *retval; + + RETURN_NAME_IN_LIST(gps_dl_ret_name_list, GDL_RET_NUM, gdl_ret, retval); + return retval; +} + + +const char *const gps_dl_dsp_state_name_list[GPS_DSP_ST_MAX + 1] = { + [GPS_DSP_ST_OFF] = "OFF ", + [GPS_DSP_ST_TURNED_ON] = "ON ", + [GPS_DSP_ST_RESET_DONE] = "RST ", + [GPS_DSP_ST_WORKING] = "WORK", + [GPS_DSP_ST_HW_SLEEP_MODE] = "SLP ", + [GPS_DSP_ST_HW_STOP_MODE] = "STOP", + [GPS_DSP_ST_WAKEN_UP] = "WAKE", + [GPS_DSP_ST_MAX] = "UNKN" +}; + +const char *gps_dl_dsp_state_name(enum gps_dsp_state_t state) +{ + const char *retval; + + RETURN_NAME_IN_LIST(gps_dl_dsp_state_name_list, GPS_DSP_ST_MAX, state, retval); + return retval; +} + + +const char *const gps_dl_dsp_event_name_list[GPS_DSP_EVT_MAX + 1] = { + [GPS_DSP_EVT_FUNC_OFF] = "FUNC_OFF", + [GPS_DSP_EVT_FUNC_ON] = "FUNC_ON ", + [GPS_DSP_EVT_RESET_DONE] = "RST_DONE", + [GPS_DSP_EVT_RAM_CODE_READY] = "RAM_OKAY", + [GPS_DSP_EVT_CTRL_TIMER_EXPIRE] = "TIMEOUT ", + [GPS_DSP_EVT_HW_SLEEP_REQ] = "SLP_REQ ", + [GPS_DSP_EVT_HW_SLEEP_EXIT] = "SLP_WAK ", + [GPS_DSP_EVT_HW_STOP_REQ] = "STOP_REQ", + [GPS_DSP_EVT_HW_STOP_EXIT] = "STOP_WAK", + [GPS_DSP_EVT_MAX] = "UNKNOWN " +}; + +const char *gps_dl_dsp_event_name(enum gps_dsp_event_t event) +{ + const char *retval; + + RETURN_NAME_IN_LIST(gps_dl_dsp_event_name_list, GPS_DSP_EVT_MAX, event, retval); + return retval; +} + + +const char * const gps_dl_link_state_name_list[LINK_STATE_NUM + 1] = { + [LINK_UNINIT] = "UNINIT", + [LINK_CLOSED] = "CLOSED", + [LINK_OPENING] = "OPENING", + [LINK_OPENED] = "OPENED", + [LINK_CLOSING] = "CLOSING", + [LINK_RESETTING] = "RESETTING", + [LINK_RESET_DONE] = "RESET_DONE", + [LINK_DISABLED] = "DISABLED", + [LINK_SUSPENDING] = "SUSPNEDING", + [LINK_SUSPENDED] = "SUSPENDED", + [LINK_RESUMING] = "RESUMING", + /* [LNK_INIT_FAIL] = "INIT_FAIL", */ + [LINK_STATE_NUM] = "INVALID" +}; + +const char *gps_dl_link_state_name(enum gps_each_link_state_enum state) +{ + const char *retval; + + RETURN_NAME_IN_LIST(gps_dl_link_state_name_list, LINK_STATE_NUM, state, retval); + return retval; +} + + +const char *const gps_dl_link_event_name_list[GPS_DL_LINK_EVT_NUM + 1] = { + [GPS_DL_EVT_LINK_OPEN] = "LINK_OPEN", + [GPS_DL_EVT_LINK_CLOSE] = "LINK_CLOSE", + [GPS_DL_EVT_LINK_WRITE] = "LINK_WRITE", + [GPS_DL_EVT_LINK_READ] = "LINK_READ", + [GPS_DL_EVT_LINK_DSP_ROM_READY_TIMEOUT] = "ROM_READY_TIMEOUT", + [GPS_DL_EVT_LINK_DSP_FSM_TIMEOUT] = "DSP_FSM_TIMEOUT", + [GPS_DL_EVT_LINK_RESET_DSP] = "RESET_DSP", + [GPS_DL_EVT_LINK_RESET_GPS] = "RESET_GPS", + [GPS_DL_EVT_LINK_PRE_CONN_RESET] = "PRE_CONN_RESET", + [GPS_DL_EVT_LINK_POST_CONN_RESET] = "POST_CONN_RESET", + [GPS_DL_EVT_LINK_PRINT_HW_STATUS] = "PRINT_HW_STATUS", + [GPS_DL_EVT_LINK_ENTER_DPSLEEP] = "ENTER_DPSLEEP", + [GPS_DL_EVT_LINK_LEAVE_DPSLEEP] = "LEAVE_DPSLEEP", + [GPS_DL_EVT_LINK_ENTER_DPSTOP] = "ENTER_DPSTOP", + [GPS_DL_EVT_LINK_LEAVE_DPSTOP] = "LEAVE_DPSTOP", + [GPS_DL_EVT_LINK_PRINT_DATA_STATUS] = "PRINT_DATA_STATUS", + [GPS_DL_LINK_EVT_NUM] = "LINK_INVALID_EVT" +}; + +const char *gps_dl_link_event_name(enum gps_dl_link_event_id event) +{ + const char *retval; + + RETURN_NAME_IN_LIST(gps_dl_link_event_name_list, GPS_DL_LINK_EVT_NUM, event, retval); + return retval; +} + +const char *gps_dl_hal_event_name_list[GPD_DL_HAL_EVT_NUM + 1] = { + [GPS_DL_HAL_EVT_A2D_TX_DMA_DONE] = "HAL_TX_DMA_DONE", + [GPS_DL_HAL_EVT_D2A_RX_HAS_DATA] = "HAL_RX_HAS_DATA", + [GPS_DL_HAL_EVT_D2A_RX_HAS_NODATA] = "HAL_RX_HAS_NODATA", + [GPS_DL_HAL_EVT_D2A_RX_DMA_DONE] = "HAL_RX_DMA_DONE", + [GPS_DL_HAL_EVT_MCUB_HAS_IRQ] = "HAL_MCUB_HAS_FLAG", + [GPS_DL_HAL_EVT_DMA_ISR_PENDING] = "HAL_DMA_ISR_PENDING", + [GPD_DL_HAL_EVT_NUM] = "HAL_INVALID_EVT", +}; + +const char *gps_dl_hal_event_name(enum gps_dl_hal_event_id event) +{ + const char *retval; + + RETURN_NAME_IN_LIST(gps_dl_hal_event_name_list, GPD_DL_HAL_EVT_NUM, event, retval); + return retval; +} + +const char *const gps_dl_waitable_name_list[GPS_DL_WAIT_NUM + 1] = { + [GPS_DL_WAIT_OPEN_CLOSE] = "OPEN_OR_CLOSE", + [GPS_DL_WAIT_WRITE] = "WRITE", + [GPS_DL_WAIT_READ] = "READ", + [GPS_DL_WAIT_RESET] = "RESET", + [GPS_DL_WAIT_NUM] = "INVALID" +}; + +const char *gps_dl_waitable_type_name(enum gps_each_link_waitable_type type) +{ + const char *retval; + + RETURN_NAME_IN_LIST(gps_dl_waitable_name_list, GPS_DL_WAIT_NUM, type, retval); + return retval; +} + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/lib/gps_dl_time_tick.c b/drivers/misc/mediatek/connectivity/gps/data_link/lib/gps_dl_time_tick.c new file mode 100644 index 0000000000000..7b6a20d2c0bb9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/lib/gps_dl_time_tick.c @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "gps_dl_config.h" +#include "gps_dl_time_tick.h" + +#if GPS_DL_ON_LINUX +#include +#include +#elif GPS_DL_ON_CTP +#include "kernel_to_ctp.h" +#endif + +void gps_dl_wait_us(unsigned int us) +{ +#if GPS_DL_ON_LINUX + udelay(us); +#elif GPS_DL_ON_CTP + udelay(us); /* GPT_Delay_us(us); */ +#endif +} + +unsigned long gps_dl_tick_get(void) +{ +#if GPS_DL_ON_LINUX + return jiffies; +#elif GPS_DL_ON_CTP + return GPT_GetTickCount(0); +#else + return 0; +#endif +} + +int gps_dl_tick_delta_to_usec(unsigned int tick0, unsigned int tick1) +{ +#if GPS_DL_ON_LINUX + return (int)((tick1 - tick0) * 1000 * 1000 / HZ); +#elif GPS_DL_ON_CTP + return (int)((tick1 - tick0) / 13); +#else + return 0; +#endif +} + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/lib/inc/gps_dl_base.h b/drivers/misc/mediatek/connectivity/gps/data_link/lib/inc/gps_dl_base.h new file mode 100644 index 0000000000000..79e079d942af4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/lib/inc/gps_dl_base.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _GPS_DL_BASE_H +#define _GPS_DL_BASE_H + +enum GDL_RET_STATUS { + GDL_OKAY = 0, + GDL_FAIL, /* general fail */ + GDL_FAIL_ASSERT, + GDL_FAIL_BUSY, + GDL_FAIL_NOSPACE, + GDL_FAIL_NODATA, + GDL_FAIL_STATE_MISMATCH, + GDL_FAIL_SIGNALED, + GDL_FAIL_TIMEOUT, + GDL_FAIL_NOT_SUPPORT, + GDL_FAIL_INVAL, + GDL_FAIL_NOSPACE_PENDING_RX, + GDL_FAIL_NOENTRY, + GDL_FAIL_NOENTRY2, + GDL_FAIL_CONN_NOT_OKAY, + GDL_RET_NUM, +}; + +const char *gdl_ret_to_name(enum GDL_RET_STATUS gdl_ret); + +#endif /* _GPS_DL_BASE_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/lib/inc/gps_dl_dma_buf.h b/drivers/misc/mediatek/connectivity/gps/data_link/lib/inc/gps_dl_dma_buf.h new file mode 100644 index 0000000000000..b7f53de0309f7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/lib/inc/gps_dl_dma_buf.h @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _GPS_DL_DMA_BUF_H +#define _GPS_DL_DMA_BUF_H + +#include "gps_dl_config.h" + +#if GPS_DL_ON_LINUX +#include "linux/semaphore.h" +#include "linux/dma-mapping.h" +#elif GPS_DL_ON_CTP +#include "kernel_to_ctp.h" +#include "gps_dl_ctp_osal.h" +#endif + +#include "gps_dl_base.h" + +enum gps_dl_dma_dir { + GDL_DMA_A2D, + GDL_DMA_D2A, + GDL_DMA_DIR_NUM +}; + +/* for lock free structure */ +struct gdl_dma_buf_idx { + unsigned int rd_idx; + unsigned int wr_idx; +}; + +#if GPS_DL_ON_LINUX +struct gdl_dma_lock { + struct semaphore internal_lock; +}; + +enum GDL_RET_STATUS gdl_dma_lock_init(struct gdl_dma_lock *p_lock); +enum GDL_RET_STATUS gdl_dma_lock_take(struct gdl_dma_lock *p_lock); +enum GDL_RET_STATUS gdl_dma_lock_give(struct gdl_dma_lock *p_lock); +void gdl_dma_lock_deinit(struct gdl_dma_lock *p_lock); +#endif + +struct gdl_dma_buf_entry { + void *vir_addr; +#if GPS_DL_ON_LINUX + dma_addr_t phy_addr; +#else + unsigned int phy_addr; +#endif + unsigned int read_index; + unsigned int write_index; + unsigned int buf_length; + bool is_valid; + bool is_nodata; +}; + +#if GPS_DL_ON_LINUX +/* if set to 2, it likes not use multi entry */ +#define GPS_DL_DMA_BUF_ENTRY_MAX (2) +#else +#define GPS_DL_DMA_BUF_ENTRY_MAX (4) +#endif +struct gps_dl_dma_buf { + int dev_index; + enum gps_dl_dma_dir dir; + unsigned int len; + + void *vir_addr; +#if GPS_DL_ON_LINUX + dma_addr_t phy_addr; +#else + unsigned int phy_addr; +#endif + unsigned int read_index; + unsigned int write_index; + unsigned int transfer_max; + bool writer_working; + bool reader_working; + + /* TODO: better way is put it to LINK rather than dma_buf */ + bool has_pending_rx; + + struct gdl_dma_buf_entry dma_working_entry; + struct gdl_dma_buf_entry data_entries[GPS_DL_DMA_BUF_ENTRY_MAX]; + unsigned int entry_r; + unsigned int entry_w; + +#if 0 + struct gdl_dma_buf_idx reader; + struct gdl_dma_buf_idx writer; + struct gdl_dma_lock lock; +#endif +}; + + +struct gdl_hw_dma_transfer { + unsigned int buf_start_addr; + unsigned int transfer_start_addr; + unsigned int len_to_wrap; + unsigned int transfer_max_len; +}; + +int gps_dl_dma_buf_alloc(struct gps_dl_dma_buf *p_dma_buf, enum gps_dl_link_id_enum link_id, + enum gps_dl_dma_dir dir, unsigned int len); +void gps_dma_buf_reset(struct gps_dl_dma_buf *p_dma); +void gps_dma_buf_show(struct gps_dl_dma_buf *p_dma, bool is_warning); +void gps_dma_buf_align_as_byte_mode(struct gps_dl_dma_buf *p_dma); +bool gps_dma_buf_is_empty(struct gps_dl_dma_buf *p_dma); + +/* enum GDL_RET_STATUS gdl_dma_buf_init(struct gps_dl_dma_buf *p_dma); */ +/* enum GDL_RET_STATUS gdl_dma_buf_deinit(struct gps_dl_dma_buf *p_dma); */ + +enum GDL_RET_STATUS gdl_dma_buf_put(struct gps_dl_dma_buf *p_dma, + const unsigned char *p_buf, unsigned int buf_len); + +enum GDL_RET_STATUS gdl_dma_buf_get(struct gps_dl_dma_buf *p_dma, + unsigned char *p_buf, unsigned int buf_len, unsigned int *p_data_len, + bool *p_is_nodata); + + +enum GDL_RET_STATUS gdl_dma_buf_get_data_entry(struct gps_dl_dma_buf *p_dma, + struct gdl_dma_buf_entry *p_entry); + +enum GDL_RET_STATUS gdl_dma_buf_set_data_entry(struct gps_dl_dma_buf *p_dma, + struct gdl_dma_buf_entry *p_entry); + +enum GDL_RET_STATUS gdl_dma_buf_get_free_entry(struct gps_dl_dma_buf *p_dma, + struct gdl_dma_buf_entry *p_entry, bool nospace_set_pending_rx); + +enum GDL_RET_STATUS gdl_dma_buf_set_free_entry(struct gps_dl_dma_buf *p_dma, + struct gdl_dma_buf_entry *p_entry); + + +enum GDL_RET_STATUS gdl_dma_buf_entry_to_buf(const struct gdl_dma_buf_entry *p_entry, + unsigned char *p_buf, unsigned int buf_len, unsigned int *p_data_len); + +enum GDL_RET_STATUS gdl_dma_buf_buf_to_entry(const struct gdl_dma_buf_entry *p_entry, + const unsigned char *p_buf, unsigned int data_len, unsigned int *p_write_index); + +enum GDL_RET_STATUS gdl_dma_buf_entry_to_transfer( + const struct gdl_dma_buf_entry *p_entry, + struct gdl_hw_dma_transfer *p_transfer, bool is_tx); + +enum GDL_RET_STATUS gdl_dma_buf_entry_transfer_left_to_write_index( + const struct gdl_dma_buf_entry *p_entry, + unsigned int left_len, unsigned int *p_write_index); + +#endif /* _GPS_DL_DMA_BUF_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/lib/inc/gps_dl_hist_rec.h b/drivers/misc/mediatek/connectivity/gps/data_link/lib/inc/gps_dl_hist_rec.h new file mode 100644 index 0000000000000..8573f8785692b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/lib/inc/gps_dl_hist_rec.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#ifndef _GPS_DL_HIST_REC_H +#define _GPS_DL_HIST_REC_H + +#include "gps_dl_config.h" + +enum gps_dl_hist_rec_rw_rec_point { + DRW_ENTER, + DRW_RETURN +}; + +void gps_each_link_rec_read(enum gps_dl_link_id_enum link_id, int pid, int len, + enum gps_dl_hist_rec_rw_rec_point rec_point); +void gps_each_link_rec_write(enum gps_dl_link_id_enum link_id, int pid, int len, + enum gps_dl_hist_rec_rw_rec_point rec_point); +void gps_each_link_rec_reset(enum gps_dl_link_id_enum link_id); +void gps_each_link_rec_force_dump(enum gps_dl_link_id_enum link_id); + +#endif /* _GPS_DL_HIST_REC_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/lib/inc/gps_dl_lib_misc.h b/drivers/misc/mediatek/connectivity/gps/data_link/lib/inc/gps_dl_lib_misc.h new file mode 100644 index 0000000000000..2ee1830ab0214 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/lib/inc/gps_dl_lib_misc.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _GPS_DL_LIB_MISC_H +#define _GPS_DL_LIB_MISC_H + +#include "gps_dl_config.h" +#include "gps_dl_base.h" +#if GPS_DL_ON_LINUX +#include /* for bool */ +#endif + +void gps_dl_hal_show_buf(unsigned char *tag, + unsigned char *buf, unsigned int len); + +bool gps_dl_hal_comp_buf_match(unsigned char *data_buf, unsigned int data_len, + unsigned char *golden_buf, unsigned int golden_len, unsigned int data_shift); + +#endif /* _GPS_DL_LIB_MISC_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/lib/inc/gps_dl_name_list.h b/drivers/misc/mediatek/connectivity/gps/data_link/lib/inc/gps_dl_name_list.h new file mode 100644 index 0000000000000..6e8217f428cca --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/lib/inc/gps_dl_name_list.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _GPS_DL_NAME_LIST_H +#define _GPS_DL_NAME_LIST_H + +#include "gps_dl_config.h" + +#include "gps_each_link.h" +#include "gps_dl_hal_api.h" +#include "gps_dsp_fsm.h" +#include "gps_dl_base.h" + +const char *gps_dl_dsp_state_name(enum gps_dsp_state_t state); +const char *gps_dl_dsp_event_name(enum gps_dsp_event_t event); + +const char *gps_dl_link_state_name(enum gps_each_link_state_enum state); +const char *gps_dl_link_event_name(enum gps_dl_link_event_id event); +const char *gps_dl_hal_event_name(enum gps_dl_hal_event_id event); + +const char *gps_dl_waitable_type_name(enum gps_each_link_waitable_type type); + +#endif /* _GPS_DL_NAME_LIST_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/lib/inc/gps_dl_time_tick.h b/drivers/misc/mediatek/connectivity/gps/data_link/lib/inc/gps_dl_time_tick.h new file mode 100644 index 0000000000000..7ec941c301c97 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/lib/inc/gps_dl_time_tick.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _GPS_DL_TIME_TICK_H +#define _GPS_DL_TIME_TICK_H + +#define GPS_DL_RW_NO_TIMEOUT (-1) +void gps_dl_wait_us(unsigned int us); +#define GDL_WAIT_US(Usec) gps_dl_wait_us(Usec) +unsigned long gps_dl_tick_get(void); +int gps_dl_tick_delta_to_usec(unsigned int tick0, unsigned int tick1); + +#endif /* _GPS_DL_TIME_TICK_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/link/gps_dl_subsys_reset.c b/drivers/misc/mediatek/connectivity/gps/data_link/link/gps_dl_subsys_reset.c new file mode 100644 index 0000000000000..b46058ec06087 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/link/gps_dl_subsys_reset.c @@ -0,0 +1,401 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "gps_dl_config.h" + +#include "gps_dl_context.h" +#include "gps_dl_subsys_reset.h" +#include "gps_each_link.h" +#include "gps_dl_name_list.h" +#include "gps_dl_hw_api.h" + +#if GPS_DL_HAS_CONNINFRA_DRV +#include "conninfra.h" +#endif + +bool gps_dl_reset_level_is_none(enum gps_dl_link_id_enum link_id) +{ + struct gps_each_link *p = gps_dl_link_get(link_id); + enum gps_each_link_state_enum state; + enum gps_each_link_reset_level level; + bool is_none; + + gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + state = p->state_for_user; + level = p->reset_level; + is_none = (level == GPS_DL_RESET_LEVEL_NONE); + gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + + if (!is_none) + GDL_LOGW("state = %s, level = %d", gps_dl_link_state_name(state), level); + + return is_none; +} + +enum GDL_RET_STATUS gps_dl_reset_level_set_and_trigger( + enum gps_each_link_reset_level level, bool wait_reset_done) +{ + enum gps_dl_link_id_enum link_id; + struct gps_each_link *p; + enum gps_each_link_state_enum old_state, new_state; + enum gps_each_link_reset_level old_level, new_level; + bool need_wait[GPS_DATA_LINK_NUM] = {false}; + bool to_send_reset_event; + long sigval; + enum GDL_RET_STATUS wait_status; + + if (level != GPS_DL_RESET_LEVEL_GPS_SUBSYS && level != GPS_DL_RESET_LEVEL_CONNSYS) { + GDL_LOGW("level = %d, do nothing and return", level); + return GDL_FAIL_INVAL; + } + + if (wait_reset_done) + ; /* TODO: take mutex to allow pending more waiter */ + + for (link_id = 0; link_id < GPS_DATA_LINK_NUM; link_id++) { + p = gps_dl_link_get(link_id); + to_send_reset_event = false; + + gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + old_state = p->state_for_user; + old_level = p->reset_level; + + switch (old_state) { + case LINK_CLOSED: + need_wait[link_id] = false; + p->state_for_user = LINK_DISABLED; + p->reset_level = level; + + /* Send reset event to ctld: + * + * for GPS_DL_RESET_LEVEL_GPS_SUBSYS ctrld do nothing but + * just change state from DISABLED back to CLOSED + * + * for GPS_DL_RESET_LEVEL_CONNSYS ctrld do nothing but + * just change state from DISABLED state back to CLOSED + */ + to_send_reset_event = true; + break; + + case LINK_OPENING: + case LINK_OPENED: + case LINK_CLOSING: + case LINK_RESET_DONE: + case LINK_RESUMING: + case LINK_SUSPENDING: + case LINK_SUSPENDED: + need_wait[link_id] = true; + p->state_for_user = LINK_RESETTING; + p->reset_level = level; + to_send_reset_event = true; + break; + + case LINK_RESETTING: + need_wait[link_id] = true; + if (old_level < level) + p->reset_level = level; + break; + + case LINK_DISABLED: + case LINK_UNINIT: + need_wait[link_id] = false; + break; + + default: + need_wait[link_id] = false; + break; + } + + new_state = p->state_for_user; + new_level = p->reset_level; + gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + + if (to_send_reset_event) { + gps_dl_link_waitable_reset(link_id, GPS_DL_WAIT_RESET); + if (level == GPS_DL_RESET_LEVEL_CONNSYS) + gps_dl_link_event_send(GPS_DL_EVT_LINK_PRE_CONN_RESET, link_id); + else + gps_dl_link_event_send(GPS_DL_EVT_LINK_RESET_GPS, link_id); + } + + GDL_LOGXE_STA(link_id, + "state change: %s -> %s, level = %d (%d -> %d), is_sent = %d, to_wait = %d", + gps_dl_link_state_name(old_state), gps_dl_link_state_name(new_state), + level, old_level, new_level, + to_send_reset_event, need_wait[link_id]); + } + + if (!wait_reset_done) { + GDL_LOGE("force no wait"); + return GDL_OKAY; + } + + for (link_id = 0; link_id < GPS_DATA_LINK_NUM; link_id++) { + if (!need_wait[link_id]) + continue; + + sigval = 0; + p = gps_dl_link_get(link_id); + wait_status = gps_dl_link_wait_on(&p->waitables[GPS_DL_WAIT_RESET], &sigval); + if (wait_status == GDL_FAIL_SIGNALED) { + GDL_LOGXE(link_id, "sigval = %ld", sigval); + return GDL_FAIL_SIGNALED; + } + + GDL_LOGXE(link_id, "wait ret = %s", gdl_ret_to_name(wait_status)); + } + + if (wait_reset_done) + ; /* TODO: take mutex to allow pending more waiter */ + + return GDL_OKAY; +} + +int gps_dl_trigger_gps_subsys_reset(bool wait_reset_done) +{ + enum GDL_RET_STATUS ret_status; + + ret_status = gps_dl_reset_level_set_and_trigger(GPS_DL_RESET_LEVEL_GPS_SUBSYS, wait_reset_done); + if (ret_status != GDL_OKAY) { + GDL_LOGE("status %s is not okay, return -1", gdl_ret_to_name(ret_status)); + return -1; + } + return 0; +} + +void gps_dl_trigger_gps_print_hw_status(void) +{ + GDL_LOGE(""); + gps_dl_link_event_send(GPS_DL_EVT_LINK_PRINT_HW_STATUS, GPS_DATA_LINK_ID0); + gps_dl_link_event_send(GPS_DL_EVT_LINK_PRINT_HW_STATUS, GPS_DATA_LINK_ID1); +} + +void gps_dl_trigger_gps_print_data_status(void) +{ + GDL_LOGE(""); + gps_dl_link_event_send(GPS_DL_EVT_LINK_PRINT_DATA_STATUS, GPS_DATA_LINK_ID0); + gps_dl_link_event_send(GPS_DL_EVT_LINK_PRINT_DATA_STATUS, GPS_DATA_LINK_ID1); +} + +void gps_dl_handle_connsys_reset_done(void) +{ + enum gps_dl_link_id_enum link_id; + struct gps_each_link *p; + enum gps_each_link_state_enum state; + enum gps_each_link_reset_level level; + bool to_send_reset_event; + + for (link_id = 0; link_id < GPS_DATA_LINK_NUM; link_id++) { + p = gps_dl_link_get(link_id); + to_send_reset_event = false; + + gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + state = p->state_for_user; + level = p->reset_level; + + if (level == GPS_DL_RESET_LEVEL_CONNSYS) { + if (state == LINK_DISABLED || state == LINK_RESETTING) + to_send_reset_event = true; + } + gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE); + + if (to_send_reset_event) + gps_dl_link_event_send(GPS_DL_EVT_LINK_POST_CONN_RESET, link_id); + + GDL_LOGXE_STA(link_id, "state check: %s, level = %d, is_sent = %d", + gps_dl_link_state_name(state), level, to_send_reset_event); + } +} + +int gps_dl_trigger_connsys_reset(void) +{ +#if GPS_DL_HAS_CONNINFRA_DRV + int ret; + + GDL_LOGE(""); + ret = conninfra_trigger_whole_chip_rst(CONNDRV_TYPE_GPS, "GPS debug"); + GDL_LOGE("conninfra_trigger_whole_chip_rst return = %d", ret); +#else + GDL_LOGE("has no conninfra_drv"); +#endif + return 0; +} + +#if GPS_DL_HAS_CONNINFRA_DRV +static bool gps_dl_connsys_is_resetting; +int gps_dl_on_pre_connsys_reset(enum consys_drv_type drv, char *reason) +{ + enum GDL_RET_STATUS ret_status; + + GDL_LOGE("already in resetting = %d", gps_dl_connsys_is_resetting); + gps_dl_connsys_is_resetting = true; + + ret_status = gps_dl_reset_level_set_and_trigger(GPS_DL_RESET_LEVEL_CONNSYS, true); + + if (ret_status != GDL_OKAY) { + GDL_LOGE("status %s is not okay, return -1", gdl_ret_to_name(ret_status)); + return -1; + } + + return 0; +} + +int gps_dl_on_post_connsys_reset(void) +{ + GDL_LOGE("already in resetting = %d", gps_dl_connsys_is_resetting); + gps_dl_connsys_is_resetting = false; + + gps_dl_handle_connsys_reset_done(); + return 0; +} + +struct sub_drv_ops_cb gps_dl_conninfra_ops_cb; +#endif + +void gps_dl_register_conninfra_reset_cb(void) +{ +#if GPS_DL_HAS_CONNINFRA_DRV + memset(&gps_dl_conninfra_ops_cb, 0, sizeof(gps_dl_conninfra_ops_cb)); + gps_dl_conninfra_ops_cb.rst_cb.pre_whole_chip_rst = gps_dl_on_pre_connsys_reset; + gps_dl_conninfra_ops_cb.rst_cb.post_whole_chip_rst = gps_dl_on_post_connsys_reset; + + conninfra_sub_drv_ops_register(CONNDRV_TYPE_GPS, &gps_dl_conninfra_ops_cb); +#endif +} + +void gps_dl_unregister_conninfra_reset_cb(void) +{ +#if GPS_DL_HAS_CONNINFRA_DRV + conninfra_sub_drv_ops_unregister(CONNDRV_TYPE_GPS); +#endif +} + +bool gps_dl_conninfra_is_readable(void) +{ +#if GPS_DL_HAS_CONNINFRA_DRV + return (conninfra_reg_readable() != 0); +#else + return true; +#endif +} + +void gps_dl_conninfra_not_readable_show_warning(unsigned int host_addr) +{ +#if GPS_DL_HAS_CONNINFRA_DRV + int readable; + int hung_value = 0; + + readable = conninfra_reg_readable(); + if (readable) + return; + + hung_value = conninfra_is_bus_hang(); + GDL_LOGW("readable = %d, hung_value = %d, before access 0x%08x", + readable, hung_value, host_addr); +#endif +} + +bool gps_dl_conninfra_is_okay_or_handle_it(int *p_hung_value, bool dump_on_hung_value_zero) +{ +#if GPS_DL_HAS_CONNINFRA_DRV + int readable; + int hung_value = 0; + bool trigger = false; + int trigger_ret = 0; + bool check_again; + int check_cnt = 0; + + do { + check_again = false; + readable = conninfra_reg_readable(); + if (readable) { + GDL_LOGD("readable = %d, okay", readable); + return true; + } + + hung_value = conninfra_is_bus_hang(); + if (p_hung_value != NULL) + *p_hung_value = hung_value; + + /* hung_value > 0, need to trigger reset + * hung_value < 0, already in reset status + * hung_value = 0, connsys may not in proper status (such as conn_top_off is in sleep) + */ + if (hung_value > 0) { + /* it's safe to cump gps host csr even hang value > 0 */ + gps_dl_hw_dump_host_csr_gps_info(true); + + trigger = true; + trigger_ret = conninfra_trigger_whole_chip_rst( + CONNDRV_TYPE_GPS, "GPS detect hung - case1"); + } else if (hung_value == 0) { + if (dump_on_hung_value_zero) + gps_dl_hw_dump_host_csr_gps_info(true); + if (check_cnt < 1) { + /* readable = 0 and hung_value = 0 may not be a stable state, + * check again to double confirm + */ + check_again = true; + } else { + /* trigger connsys reset if same result of checking again */ + trigger = true; + trigger_ret = conninfra_trigger_whole_chip_rst( + CONNDRV_TYPE_GPS, "GPS detect hung - case2"); + } + } else { + /* alreay in connsys resetting + * do nothing + */ + } + + check_cnt++; + GDL_LOGE("cnt=%d, readable=%d, hung_value=0x%x, trigger_reset=%d(%d,%d)", + check_cnt, readable, hung_value, trigger, trigger_ret, dump_on_hung_value_zero); + } while (check_again); + return false; +#else + return true; +#endif +} + + +bool g_gps_dl_test_mask_mcub_irq_on_open_flag[GPS_DATA_LINK_NUM]; +bool g_gps_dl_test_mask_hasdata_irq_flag[GPS_DATA_LINK_NUM]; + +void gps_dl_test_mask_mcub_irq_on_open_set(enum gps_dl_link_id_enum link_id, bool mask) +{ + ASSERT_LINK_ID(link_id, GDL_VOIDF()); + + g_gps_dl_test_mask_mcub_irq_on_open_flag[link_id] = mask; +} + +bool gps_dl_test_mask_mcub_irq_on_open_get(enum gps_dl_link_id_enum link_id) +{ + ASSERT_LINK_ID(link_id, false); + + return g_gps_dl_test_mask_mcub_irq_on_open_flag[link_id]; +} + +void gps_dl_test_mask_hasdata_irq_set(enum gps_dl_link_id_enum link_id, bool mask) +{ + ASSERT_LINK_ID(link_id, GDL_VOIDF()); + + g_gps_dl_test_mask_hasdata_irq_flag[link_id] = mask; +} + +bool gps_dl_test_mask_hasdata_irq_get(enum gps_dl_link_id_enum link_id) +{ + ASSERT_LINK_ID(link_id, false); + + return g_gps_dl_test_mask_hasdata_irq_flag[link_id]; +} + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/link/inc/gps_dl_subsys_reset.h b/drivers/misc/mediatek/connectivity/gps/data_link/link/inc/gps_dl_subsys_reset.h new file mode 100644 index 0000000000000..1727444cb120c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/link/inc/gps_dl_subsys_reset.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _GPS_DL_SUBSYS_RESET_H +#define _GPS_DL_SUBSYS_RESET_H + +#include "gps_dl_base.h" + +enum gps_each_link_reset_level { + GPS_DL_RESET_LEVEL_NONE, + GPS_DL_RESET_LEVEL_GPS_SINGLE_LINK, + GPS_DL_RESET_LEVEL_GPS_SUBSYS, + GPS_DL_RESET_LEVEL_CONNSYS, + GPS_DL_RESET_LEVEL_NUM +}; + +enum GDL_RET_STATUS gps_dl_reset_level_set_and_trigger( + enum gps_each_link_reset_level level, bool wait_reset_done); + +bool gps_dl_reset_level_is_none(enum gps_dl_link_id_enum link_id); +bool gps_dl_reset_level_is_single(void); +bool gps_dl_reset_level_gt_single(void); + +void gps_dl_trigger_gps_print_hw_status(void); +void gps_dl_trigger_gps_print_data_status(void); +int gps_dl_trigger_gps_subsys_reset(bool wait_reset_done); +int gps_dl_trigger_connsys_reset(void); +void gps_dl_handle_connsys_reset_done(void); + +void gps_dl_register_conninfra_reset_cb(void); +void gps_dl_unregister_conninfra_reset_cb(void); + +bool gps_dl_conninfra_is_readable(void); +void gps_dl_conninfra_not_readable_show_warning(unsigned int host_addr); +bool gps_dl_conninfra_is_okay_or_handle_it(int *p_hung_value, bool dump_on_hung_value_zero); + +void gps_dl_test_mask_mcub_irq_on_open_set(enum gps_dl_link_id_enum link_id, bool mask); +bool gps_dl_test_mask_mcub_irq_on_open_get(enum gps_dl_link_id_enum link_id); + +void gps_dl_test_mask_hasdata_irq_set(enum gps_dl_link_id_enum link_id, bool mask); +bool gps_dl_test_mask_hasdata_irq_get(enum gps_dl_link_id_enum link_id); + +#endif /* _GPS_DL_SUBSYS_RESET_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_data_link_devices.c b/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_data_link_devices.c new file mode 100644 index 0000000000000..bcbbd0c1d5e3b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_data_link_devices.c @@ -0,0 +1,343 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include +#include + +#include +#include + +#include "gps_dl_config.h" +#include "gps_dl_context.h" +#include "gps_dl_hw_api.h" +#include "gps_dl_isr.h" +#include "gps_data_link_devices.h" +#include "gps_each_link.h" +#if GPS_DL_HAS_PLAT_DRV +#include "gps_dl_linux_plat_drv.h" +#include "gps_dl_linux_reserved_mem.h" +#endif +#if GPS_DL_MOCK_HAL +#include "gps_mock_hal.h" +#endif +#include "gps_dl_procfs.h" +#include "gps_dl_subsys_reset.h" + +#define GPS_DATA_LINK_DEV_NAME "gps_data_link_cdev" +int gps_dl_devno_major; +int gps_dl_devno_minor; + +void gps_dl_dma_buf_free(struct gps_dl_dma_buf *p_dma_buf, enum gps_dl_link_id_enum link_id) +{ + struct gps_each_device *p_dev; + + p_dev = gps_dl_device_get(link_id); + if (p_dev == NULL) { + GDL_LOGXE_INI(link_id, "gps_dl_device_get return null"); + return; + } + + if (p_dma_buf->vir_addr) + dma_free_coherent(p_dev->dev, + p_dma_buf->len, p_dma_buf->vir_addr, p_dma_buf->phy_addr); + + memset(p_dma_buf, 0, sizeof(*p_dma_buf)); +} + +int gps_dl_dma_buf_alloc(struct gps_dl_dma_buf *p_dma_buf, enum gps_dl_link_id_enum link_id, + enum gps_dl_dma_dir dir, unsigned int len) +{ + struct gps_each_device *p_dev; + struct device *p_linux_plat_dev; + + p_dev = gps_dl_device_get(link_id); + if (p_dev == NULL) { + GDL_LOGXE_INI(link_id, "gps_dl_device_get return null"); + return -1; + } + + p_linux_plat_dev = (struct device *)p_dev->private_data; + + memset(p_dma_buf, 0, sizeof(*p_dma_buf)); + p_dma_buf->dev_index = link_id; + p_dma_buf->dir = dir; + p_dma_buf->len = len; + + GDL_LOGI_INI("p_linux_plat_dev = 0x%p", p_linux_plat_dev); + if (p_linux_plat_dev == NULL) { + p_dma_buf->vir_addr = dma_zalloc_coherent( + p_dev->dev, len, &p_dma_buf->phy_addr, GFP_DMA | GFP_DMA32); + } else { + p_dma_buf->vir_addr = dma_zalloc_coherent( + p_linux_plat_dev, len, &p_dma_buf->phy_addr, GFP_DMA);/* | GFP_DMA32); */ + } + + GDL_LOGI_INI( +#if GPS_DL_ON_LINUX + "alloc gps dl dma buf(%d,%d), addr: vir=0x%p, phy=0x%pad, len=%u", +#else + "alloc gps dl dma buf(%d,%d), addr: vir=0x%p, phy=0x%08x, len=%u", +#endif + p_dma_buf->dev_index, p_dma_buf->dir, + p_dma_buf->vir_addr, p_dma_buf->phy_addr, p_dma_buf->len); + + if (NULL == p_dma_buf->vir_addr) { + GDL_LOGXE_INI(link_id, + "alloc gps dl dma buf(%d,%d)(len = %u) fail", link_id, dir, len); + /* force move forward even fail */ + /* return -ENOMEM; */ + } + + return 0; +} + +int gps_dl_dma_buf_alloc2(enum gps_dl_link_id_enum link_id) +{ + int retval; + struct gps_each_device *p_dev; + struct gps_each_link *p_link; + + p_dev = gps_dl_device_get(link_id); + p_link = gps_dl_link_get(link_id); + if (p_dev == NULL) { + GDL_LOGXE_INI(link_id, "gps_dl_device_get return null"); + return -1; + } + + of_dma_configure(p_dev->dev, p_dev->dev->of_node); + + if (!p_dev->dev->coherent_dma_mask) + p_dev->dev->coherent_dma_mask = DMA_BIT_MASK(32); + + if (!p_dev->dev->dma_mask) + p_dev->dev->dma_mask = &p_dev->dev->coherent_dma_mask; + + + retval = gps_dl_dma_buf_alloc( + &p_link->tx_dma_buf, link_id, GDL_DMA_A2D, p_link->cfg.tx_buf_size); + + if (retval) + return retval; + + retval = gps_dl_dma_buf_alloc( + &p_link->rx_dma_buf, link_id, GDL_DMA_D2A, p_link->cfg.rx_buf_size); + + if (retval) + return retval; + + return 0; +} + +void gps_dl_ctx_links_deinit(void) +{ + enum gps_dl_link_id_enum link_id; + + struct gps_each_device *p_dev; + struct gps_each_link *p_link; + + for (link_id = 0; link_id < GPS_DATA_LINK_NUM; link_id++) { + p_dev = gps_dl_device_get(link_id); + p_link = gps_dl_link_get(link_id); + + if (gps_dl_reserved_mem_is_ready()) { + gps_dl_reserved_mem_dma_buf_deinit(&p_link->tx_dma_buf); + gps_dl_reserved_mem_dma_buf_deinit(&p_link->rx_dma_buf); + + } else { + gps_dl_dma_buf_free(&p_link->tx_dma_buf, link_id); + gps_dl_dma_buf_free(&p_link->rx_dma_buf, link_id); + } + + /* un-binding each device and link */ + p_link->p_device = NULL; + p_dev->p_link = NULL; + gps_each_link_deinit(link_id); + } +} + +int gps_dl_ctx_links_init(void) +{ + int retval; + enum gps_dl_link_id_enum link_id; + struct gps_each_device *p_dev; + struct gps_each_link *p_link; + enum gps_each_link_waitable_type j; + + for (link_id = 0; link_id < GPS_DATA_LINK_NUM; link_id++) { + p_dev = gps_dl_device_get(link_id); + p_link = gps_dl_link_get(link_id); + + if (gps_dl_reserved_mem_is_ready()) { + gps_dl_reserved_mem_dma_buf_init(&p_link->tx_dma_buf, + link_id, GDL_DMA_A2D, p_link->cfg.tx_buf_size); + + gps_dl_reserved_mem_dma_buf_init(&p_link->rx_dma_buf, + link_id, GDL_DMA_D2A, p_link->cfg.rx_buf_size); + } else { + retval = gps_dl_dma_buf_alloc2(link_id); + if (retval) + return retval; + } + + for (j = 0; j < GPS_DL_WAIT_NUM; j++) + gps_dl_link_waitable_init(&p_link->waitables[j], j); + + /* binding each device and link */ + p_link->p_device = p_dev; + p_dev->p_link = p_link; + + /* Todo: MNL read buf is 512, here is work-around */ + /* the solution should be make on gdl_dma_buf_get */ + gps_dl_set_rx_transfer_max(link_id, GPS_LIBMNL_READ_MAX); + gps_each_link_init(link_id); + } + + return 0; +} + +static void gps_dl_devices_exit(void) +{ + enum gps_dl_link_id_enum link_id; + dev_t devno = MKDEV(gps_dl_devno_major, gps_dl_devno_minor); + struct gps_each_device *p_dev; + + gps_dl_device_context_deinit(); + +#if GPS_DL_HAS_PLAT_DRV + gps_dl_linux_plat_drv_unregister(); +#endif + + for (link_id = 0; link_id < GPS_DATA_LINK_NUM; link_id++) { + p_dev = gps_dl_device_get(link_id); + gps_dl_cdev_cleanup(p_dev, link_id); + } + + unregister_chrdev_region(devno, GPS_DATA_LINK_NUM); +} + +void gps_dl_device_context_deinit(void) +{ + gps_dl_procfs_remove(); + + gps_dl_unregister_conninfra_reset_cb(); + + gps_dl_irq_deinit(); + +#if GPS_DL_HAS_CTRLD + gps_dl_ctrld_deinit(); +#endif + +#if GPS_DL_MOCK_HAL + gps_dl_mock_deinit(); +#endif + + gps_dl_ctx_links_deinit(); + gps_dl_reserved_mem_deinit(); +} + +int gps_dl_irq_init(void) +{ +#if 0 + enum gps_dl_irq_index_enum irq_idx; + + for (irq_idx = 0; irq_idx < GPS_DL_IRQ_NUM; irq_idx++) + ; +#endif + + gps_dl_linux_irqs_register(gps_dl_irq_get(0), GPS_DL_IRQ_NUM); + + return 0; +} + +int gps_dl_irq_deinit(void) +{ + gps_dl_linux_irqs_unregister(gps_dl_irq_get(0), GPS_DL_IRQ_NUM); + return 0; +} + +static int gps_dl_devices_init(void) +{ + int result; + enum gps_dl_link_id_enum link_id; + dev_t devno = 0; + struct gps_each_device *p_dev; + + result = alloc_chrdev_region(&devno, gps_dl_devno_minor, + GPS_DATA_LINK_NUM, GPS_DATA_LINK_DEV_NAME); + + gps_dl_devno_major = MAJOR(devno); + + if (result < 0) { + GDL_LOGE_INI("fail to get major %d\n", gps_dl_devno_major); + return result; + } + + GDL_LOGW_INI("success to get major %d\n", gps_dl_devno_major); + + for (link_id = 0; link_id < GPS_DATA_LINK_NUM; link_id++) { + devno = MKDEV(gps_dl_devno_major, gps_dl_devno_minor + link_id); + p_dev = gps_dl_device_get(link_id); + p_dev->devno = devno; + result = gps_dl_cdev_setup(p_dev, link_id); + if (result) { + /* error happened */ + gps_dl_devices_exit(); + return result; + } + } + + +#if GPS_DL_HAS_PLAT_DRV + gps_dl_linux_plat_drv_register(); +#else + gps_dl_device_context_init(); +#endif + + return 0; +} + +void gps_dl_device_context_init(void) +{ + gps_dl_reserved_mem_init(); + gps_dl_ctx_links_init(); + +#if GPS_DL_MOCK_HAL + gps_dl_mock_init(); +#endif + +#if GPS_DL_HAS_CTRLD + gps_dl_ctrld_init(); +#endif + +#if (!(GPS_DL_NO_USE_IRQ || GPS_DL_HW_IS_MOCK)) + /* must after gps_dl_ctx_links_init */ + gps_dl_irq_init(); +#endif + gps_dl_register_conninfra_reset_cb(); + + gps_dl_procfs_setup(); +} + +void mtk_gps_data_link_devices_exit(void) +{ + GDL_LOGI_INI("mtk_gps_data_link_devices_exit"); + gps_dl_devices_exit(); +} + +int mtk_gps_data_link_devices_init(void) +{ + GDL_LOGI_INI("mtk_gps_data_link_devices_init"); + gps_dl_devices_init(); + /* GDL_ASSERT(false, 0, "test assert"); */ + return 0; +} + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_ctrld.c b/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_ctrld.c new file mode 100644 index 0000000000000..a5f18c88edc9c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_ctrld.c @@ -0,0 +1,372 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "gps_dl_ctrld.h" +#include "gps_each_device.h" +#if GPS_DL_MOCK_HAL +#include "gps_mock_mvcd.h" +#endif +#include "gps_data_link_devices.h" +#include "gps_dl_hal_api.h" + +struct gps_dl_ctrld_context gps_dl_ctrld; + +static int gps_dl_opfunc_link_event_proc(struct gps_dl_osal_op_dat *pOpDat); +static int gps_dl_opfunc_hal_event_proc(struct gps_dl_osal_op_dat *pOpDat); +static struct gps_dl_osal_lxop *gps_dl_get_op(struct gps_dl_osal_lxop_q *pOpQ); +static int gps_dl_put_op(struct gps_dl_osal_lxop_q *pOpQ, struct gps_dl_osal_lxop *pOp); + +static const GPS_DL_OPID_FUNC gps_dl_core_opfunc[] = { + [GPS_DL_OPID_LINK_EVENT_PROC] = gps_dl_opfunc_link_event_proc, + [GPS_DL_OPID_HAL_EVENT_PROC] = gps_dl_opfunc_hal_event_proc, +}; + +static int gps_dl_opfunc_link_event_proc(struct gps_dl_osal_op_dat *pOpDat) +{ + enum gps_dl_link_event_id evt; + enum gps_dl_link_id_enum link_id; + + link_id = (enum gps_dl_link_id_enum)pOpDat->au4OpData[0]; + evt = (enum gps_dl_link_event_id)pOpDat->au4OpData[1]; + gps_dl_link_event_proc(evt, link_id); + + return 0; +} + +static int gps_dl_opfunc_hal_event_proc(struct gps_dl_osal_op_dat *pOpDat) +{ + enum gps_dl_hal_event_id evt; + enum gps_dl_link_id_enum link_id; + int sid_on_evt; + + link_id = (enum gps_dl_link_id_enum)pOpDat->au4OpData[0]; + evt = (enum gps_dl_hal_event_id)pOpDat->au4OpData[1]; + sid_on_evt = (int)pOpDat->au4OpData[2]; + gps_dl_hal_event_proc(evt, link_id, sid_on_evt); + + return 0; +} + +unsigned int gps_dl_wait_event_checker(struct gps_dl_osal_thread *pThread) +{ + struct gps_dl_ctrld_context *pgps_dl_ctrld; + + if (pThread) { + pgps_dl_ctrld = (struct gps_dl_ctrld_context *) (pThread->pThreadData); + return !RB_EMPTY(&pgps_dl_ctrld->rOpQ); + } + GDL_LOGE_EVT("pThread null"); + return 0; +} + +static int gps_dl_core_opid(struct gps_dl_osal_op_dat *pOpDat) +{ + int ret; + + if (pOpDat == NULL) { + GDL_LOGE_EVT("null operation data"); + /*print some message with error info */ + return -1; + } + + if (pOpDat->opId >= GPS_DL_OPID_MAX) { + GDL_LOGE_EVT("Invalid OPID(%d)", pOpDat->opId); + return -2; + } + + if (gps_dl_core_opfunc[pOpDat->opId]) { + GDL_LOGD_EVT("GPS data link: operation id(%d)", pOpDat->opId); + ret = (*(gps_dl_core_opfunc[pOpDat->opId])) (pOpDat); + return ret; + } + + GDL_LOGE_EVT("GPS data link: null handler (%d)", pOpDat->opId); + + return -2; +} + +static int gps_dl_put_op(struct gps_dl_osal_lxop_q *pOpQ, struct gps_dl_osal_lxop *pOp) +{ + int iRet; + + if (!pOpQ || !pOp) { + GDL_LOGW_EVT("invalid input param: pOpQ(0x%p), pLxOp(0x%p)", pOpQ, pOp); + gps_dl_osal_assert(pOpQ); + gps_dl_osal_assert(pOp); + return -1; + } + + iRet = gps_dl_osal_lock_sleepable_lock(&pOpQ->sLock); + if (iRet) { + GDL_LOGW_EVT("gps_dl_osal_lock_sleepable_lock iRet(%d)", iRet); + return -1; + } + + /* acquire lock success */ + if (!RB_FULL(pOpQ)) + RB_PUT(pOpQ, pOp); + else { + GDL_LOGW("RB_FULL(%p -> %p)", pOp, pOpQ); + iRet = -1; + } + + gps_dl_osal_unlock_sleepable_lock(&pOpQ->sLock); + + if (iRet) + return -1; + return 0; +} + +int gps_dl_put_act_op(struct gps_dl_osal_lxop *pOp) +{ + struct gps_dl_ctrld_context *pgps_dl_ctrld = &gps_dl_ctrld; + struct gps_dl_osal_signal *pSignal = NULL; + int waitRet = -1; + int bRet = 0; + + gps_dl_osal_assert(pgps_dl_ctrld); + gps_dl_osal_assert(pOp); + + do { + if (!pgps_dl_ctrld || !pOp) { + GDL_LOGE("pgps_dl_ctx(0x%p), pOp(0x%p)", pgps_dl_ctrld, pOp); + break; + } + + /* Init ref_count to 1 indicating that current thread holds a ref to it */ + atomic_set(&pOp->ref_count, 1); + + pSignal = &pOp->signal; + if (pSignal->timeoutValue) { + pOp->result = -9; + gps_dl_osal_signal_init(pSignal); + } + + /* Increment ref_count by 1 as gps control thread will hold a reference also, + * this must be done here instead of on target thread, because + * target thread might not be scheduled until a much later time, + * allowing current thread to decrement ref_count at the end of function, + * putting op back to free queue before target thread has a chance to process. + */ + atomic_inc(&pOp->ref_count); + + /* put to active Q */ + bRet = gps_dl_put_op(&pgps_dl_ctrld->rOpQ, pOp); + if (bRet == -1) { + GDL_LOGE("put to active queue fail"); + atomic_dec(&pOp->ref_count); + break; + } + + /* wake up gps control thread */ + gps_dl_osal_trigger_event(&pgps_dl_ctrld->rgpsdlWq); + + if (pSignal->timeoutValue == 0) { + bRet = -1; + break; + } + + /* check result */ + waitRet = gps_dl_osal_wait_for_signal_timeout(pSignal, &pgps_dl_ctrld->thread); + + if (waitRet == 0) + GDL_LOGE("opId(%d) completion timeout", pOp->op.opId); + else if (pOp->result) + GDL_LOGW("opId(%d) result:%d", pOp->op.opId, pOp->result); + + /* op completes, check result */ + bRet = (pOp->result) ? -1 : 0; + } while (0); + + if (pOp && atomic_dec_and_test(&pOp->ref_count)) { + /* put Op back to freeQ */ + gps_dl_put_op(&pgps_dl_ctrld->rFreeOpQ, pOp); + } + + return bRet; +} + +struct gps_dl_osal_lxop *gps_dl_get_free_op(void) +{ + struct gps_dl_osal_lxop *pOp = NULL; + struct gps_dl_ctrld_context *pgps_dl_ctrld = &gps_dl_ctrld; + + gps_dl_osal_assert(pgps_dl_ctrld); + pOp = gps_dl_get_op(&pgps_dl_ctrld->rFreeOpQ); + if (pOp) + gps_dl_osal_memset(pOp, 0, sizeof(struct gps_dl_osal_lxop)); + return pOp; +} + +static struct gps_dl_osal_lxop *gps_dl_get_op(struct gps_dl_osal_lxop_q *pOpQ) +{ + struct gps_dl_osal_lxop *pOp; + int iRet; + + if (pOpQ == NULL) { + GDL_LOGE("pOpQ = NULL"); + gps_dl_osal_assert(pOpQ); + return NULL; + } + + iRet = gps_dl_osal_lock_sleepable_lock(&pOpQ->sLock); + if (iRet) { + GDL_LOGE("gps_dl_osal_lock_sleepable_lock iRet(%d)", iRet); + return NULL; + } + + /* acquire lock success */ + RB_GET(pOpQ, pOp); + gps_dl_osal_unlock_sleepable_lock(&pOpQ->sLock); + + if (pOp == NULL) { + GDL_LOGW("RB_GET(%p) return NULL", pOpQ); + gps_dl_osal_assert(pOp); + return NULL; + } + + return pOp; +} + +int gps_dl_put_op_to_free_queue(struct gps_dl_osal_lxop *pOp) +{ + struct gps_dl_ctrld_context *pgps_dl_ctrld = &gps_dl_ctrld; + + if (gps_dl_put_op(&pgps_dl_ctrld->rFreeOpQ, pOp) < 0) + return -1; + + return 0; +} + +static int gps_dl_ctrl_thread(void *pData) +{ + struct gps_dl_ctrld_context *pgps_dl_ctrld = (struct gps_dl_ctrld_context *) pData; + struct gps_dl_osal_event *pEvent = NULL; + struct gps_dl_osal_lxop *pOp; + int iResult; + + if (pgps_dl_ctrld == NULL) { + GDL_LOGE("pgps_dl_ctx is NULL"); + return -1; + } + + GDL_LOGI("gps control thread starts"); + + pEvent = &(pgps_dl_ctrld->rgpsdlWq); + + for (;;) { + pOp = NULL; + pEvent->timeoutValue = 0; + + gps_dl_osal_thread_wait_for_event(&pgps_dl_ctrld->thread, pEvent, gps_dl_wait_event_checker); + + if (gps_dl_osal_thread_should_stop(&pgps_dl_ctrld->thread)) { + GDL_LOGW(" thread should stop now..."); + /* TODO: clean up active opQ */ + break; + } + + /* get Op from Queue */ + pOp = gps_dl_get_op(&pgps_dl_ctrld->rOpQ); + if (!pOp) { + GDL_LOGW("get_lxop activeQ fail"); + continue; + } + + /*Execute operation*/ + iResult = gps_dl_core_opid(&pOp->op); + + if (atomic_dec_and_test(&pOp->ref_count)) + gps_dl_put_op(&pgps_dl_ctrld->rFreeOpQ, pOp); + else if (gps_dl_osal_op_is_wait_for_signal(pOp)) + gps_dl_osal_op_raise_signal(pOp, iResult); + + if (iResult) + GDL_LOGW("opid (0x%x) failed, iRet(%d)", pOp->op.opId, iResult); + + } + + GDL_LOGI("gps control thread exits succeed"); + + return 0; +} + +int gps_dl_ctrld_init(void) +{ + struct gps_dl_ctrld_context *pgps_dl_ctrld; + struct gps_dl_osal_thread *pThread; + int iRet; + int i; + + pgps_dl_ctrld = &gps_dl_ctrld; + gps_dl_osal_memset(&gps_dl_ctrld, 0, sizeof(gps_dl_ctrld)); + + /* Create gps data link control thread */ + pThread = &gps_dl_ctrld.thread; + gps_dl_osal_strncpy(pThread->threadName, "gps_kctrld", sizeof(pThread->threadName)); + pThread->pThreadData = (void *)pgps_dl_ctrld; + pThread->pThreadFunc = (void *)gps_dl_ctrl_thread; + + iRet = gps_dl_osal_thread_create(pThread); + if (iRet) { + GDL_LOGE("Create gps data link control thread fail:%d", iRet); + return -1; + } + + /* Initialize gps control Thread Information: Thread */ + gps_dl_osal_event_init(&pgps_dl_ctrld->rgpsdlWq); + gps_dl_osal_sleepable_lock_init(&pgps_dl_ctrld->rOpQ.sLock); + gps_dl_osal_sleepable_lock_init(&pgps_dl_ctrld->rFreeOpQ.sLock); + /* Initialize op queue */ + RB_INIT(&pgps_dl_ctrld->rOpQ, GPS_DL_OP_BUF_SIZE); + RB_INIT(&pgps_dl_ctrld->rFreeOpQ, GPS_DL_OP_BUF_SIZE); + + /* Put all to free Q */ + for (i = 0; i < GPS_DL_OP_BUF_SIZE; i++) { + gps_dl_osal_signal_init(&(pgps_dl_ctrld->arQue[i].signal)); + gps_dl_put_op(&pgps_dl_ctrld->rFreeOpQ, &(pgps_dl_ctrld->arQue[i])); + } + + iRet = gps_dl_osal_thread_run(pThread); + if (iRet) { + GDL_LOGE("gps data link ontrol thread run fail:%d", iRet); + return -1; + } + + return 0; +} + +int gps_dl_ctrld_deinit(void) +{ + struct gps_dl_osal_thread *pThread; + int iRet; + + pThread = &gps_dl_ctrld.thread; + + iRet = gps_dl_osal_thread_stop(pThread); + if (iRet) + GDL_LOGE("gps data link ontrol thread stop fail:%d", iRet); + else + GDL_LOGI("gps data link ontrol thread stop okay:%d", iRet); + + gps_dl_osal_event_deinit(&gps_dl_ctrld.rgpsdlWq); + + iRet = gps_dl_osal_thread_destroy(pThread); + if (iRet) { + GDL_LOGE("gps data link ontrol thread destroy fail:%d", iRet); + return -1; + } + GDL_LOGI("gps data link ontrol thread destroy okay:%d\n", iRet); + + return 0; +} + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_emi.c b/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_emi.c new file mode 100644 index 0000000000000..ddef332173804 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_emi.c @@ -0,0 +1,228 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#include "gps_dl_config.h" + +#if GPS_DL_HAS_PLAT_DRV +/******************************************************************************* +* Dependency +*******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gps_dl_log.h" +#include "gps_dl_linux_reserved_mem.h" +#include "gps_dl_emi.h" + +/****************************************************************************** + * Definition +******************************************************************************/ +/* device name and major number */ +#define GPS_DL_EMI_DEVNAME "gps_emi" +#define IOCTL_EMI_MEMORY_INIT 1 +#define IOCTL_MNL_NVRAM_FILE_TO_MEM 2 +#define IOCTL_MNL_NVRAM_MEM_TO_FILE 3 +#define IOCTL_ADC_CAPTURE_ADDR_GET 4 + + +/******************************************************************************* +* structure & enumeration +*******************************************************************************/ +/*---------------------------------------------------------------------------*/ +struct gps_icap_dev { + struct class *cls; + struct device *dev; + dev_t devno; + struct cdev chdev; +}; + +struct gps_icap_dev *gps_icap_dev_ptr; + +char gps_icap_local_buf[GPS_ICAP_BUF_SIZE]; + + +/*---------------------------------------------------------------------------*/ +long gps_icap_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int retval = 0; +#if 0 + unsigned int *tmp; +#endif + + GDL_LOGI("cmd (%d),arg(%ld)\n", cmd, arg); + + switch (cmd) { + case IOCTL_EMI_MEMORY_INIT: + GDL_LOGW("IOCTL_EMI_MEMORY_INIT"); + break; + + case IOCTL_MNL_NVRAM_FILE_TO_MEM: + GDL_LOGW("IOCTL_MNL_NVRAM_FILE_TO_MEM"); + break; + + case IOCTL_MNL_NVRAM_MEM_TO_FILE: + GDL_LOGW("IOCTL_MNL_NVRAM_MEM_TO_FILE"); + break; + + case IOCTL_ADC_CAPTURE_ADDR_GET: +#if 0 + tmp = (unsigned int *)&gGpsIcapPhyBase; + GPS_DBG("gps_emi:gGpsIcapPhyBase (%x)\n", &gGpsIcapPhyBase); + GPS_DBG("gps_emi:tmp (%x)\n", tmp); + if (copy_to_user((unsigned int __user *)arg, tmp, sizeof(unsigned int))) + retval = -1; +#endif + GDL_LOGW("IOCTL_ADC_CAPTURE_ADDR_GET,(%d)", retval); + break; + + default: + GDL_LOGW("unknown cmd (%d)", cmd); + retval = 0; + break; + } + return retval; + +} + +/******************************************************************************/ +long gps_icap_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + return gps_icap_unlocked_ioctl(filp, cmd, arg); +} + +/*****************************************************************************/ +static int gps_icap_open(struct inode *inode, struct file *file) +{ + return nonseekable_open(inode, file); +} + +/*****************************************************************************/ + + +/*****************************************************************************/ +static int gps_icap_release(struct inode *inode, struct file *file) +{ + return 0; +} + +/******************************************************************************/ +static ssize_t gps_icap_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) +{ + void *p_src; + + GDL_LOGI("begin"); + + if (count > GPS_ICAP_BUF_SIZE) + count = GPS_ICAP_BUF_SIZE; + + p_src = gps_dl_reserved_mem_icap_buf_get_vir_addr(); + + if (p_src == NULL) { + GDL_LOGW("src is null, return"); + return 0; + } + + memcpy_fromio(&gps_icap_local_buf[0], p_src, GPS_ICAP_BUF_SIZE); + + if (copy_to_user(buf, (char *)&gps_icap_local_buf[0], count)) { + GDL_LOGW("copy to user fail, return"); + return 0; + } + + GDL_LOGI("finish, count = %ld", count); + return count; +} + +/******************************************************************************/ +static ssize_t gps_icap_write(struct file *file, const char __user *buf, size_t count, + loff_t *ppos) +{ + ssize_t ret = 0; + + GDL_LOGW("count = %ld", count); + + return ret; +} + +/*****************************************************************************/ +/* Kernel interface */ +static const struct file_operations gps_icap_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = gps_icap_unlocked_ioctl, + .compat_ioctl = gps_icap_compat_ioctl, + .open = gps_icap_open, + .read = gps_icap_read, + .write = gps_icap_write, + .release = gps_icap_release, +}; + +/*****************************************************************************/ +void gps_icap_probe(void) +{ + int ret = 0, err = 0; + + GDL_LOGI("start"); + + gps_icap_dev_ptr = kzalloc(sizeof(*gps_icap_dev_ptr), GFP_KERNEL); + if (gps_icap_dev_ptr == NULL) { + err = -ENOMEM; + ret = -ENOMEM; + goto err_out; + } + + GDL_LOGD("registering chardev"); + ret = alloc_chrdev_region(&gps_icap_dev_ptr->devno, 0, 1, GPS_DL_EMI_DEVNAME); + if (ret) { + GDL_LOGE("alloc_chrdev_region fail: %d", ret); + err = -ENOMEM; + goto err_out; + } else + GDL_LOGI("major: %d, minor: %d", + MAJOR(gps_icap_dev_ptr->devno), MINOR(gps_icap_dev_ptr->devno)); + + cdev_init(&gps_icap_dev_ptr->chdev, &gps_icap_fops); + gps_icap_dev_ptr->chdev.owner = THIS_MODULE; + err = cdev_add(&gps_icap_dev_ptr->chdev, gps_icap_dev_ptr->devno, 1); + if (err) { + GDL_LOGE("cdev_add fail: %d", err); + goto err_out; + } + + gps_icap_dev_ptr->cls = class_create(THIS_MODULE, "gpsemi"); + if (IS_ERR(gps_icap_dev_ptr->cls)) { + GDL_LOGE("unable to create class, err = %d\n", (int)PTR_ERR(gps_icap_dev_ptr->cls)); + goto err_out; + } + gps_icap_dev_ptr->dev = device_create(gps_icap_dev_ptr->cls, + NULL, gps_icap_dev_ptr->devno, gps_icap_dev_ptr, "gps_emi"); + + GDL_LOGI("done"); + return; + +err_out: + if (gps_icap_dev_ptr != NULL) { + if (err == 0) + cdev_del(&gps_icap_dev_ptr->chdev); + if (ret == 0) + unregister_chrdev_region(gps_icap_dev_ptr->devno, 1); + + kfree(gps_icap_dev_ptr); + gps_icap_dev_ptr = NULL; + } +} + +#endif /* GPS_DL_HAS_PLAT_DRV */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_linux.c b/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_linux.c new file mode 100644 index 0000000000000..183decbdad7b6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_linux.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "gps_dl_linux.h" +#include "gps_dl_hal.h" +#include "gps_dl_log.h" + +void gps_dl_irq_mask(int irq_id, enum gps_dl_irq_ctrl_from from) +{ + /* TODO: */ + /* threaded_irq thread_fn still need to call disable_irq_nosync, + * otherwise it might be hung. + */ + if (from == GPS_DL_IRQ_CTRL_FROM_ISR) + disable_irq_nosync(irq_id); + else + /* It returns until irq done */ + disable_irq(irq_id); +} + +void gps_dl_irq_unmask(int irq_id, enum gps_dl_irq_ctrl_from from) +{ + /* TODO: */ + enable_irq(irq_id); +} + +static int gps_dl_linux_irq_index_to_id(enum gps_dl_irq_index_enum index) +{ + /* TODO: fill the real number or the value from dts */ + return gps_dl_irq_index_to_id(index); +} + +/* TODO: call it when module init */ +int gps_dl_linux_irqs_register(struct gps_each_irq *p_irqs, int irq_num) +{ + int irq_id, i_ret, i; + unsigned long sys_irq_flags; + + for (i = 0; i < irq_num; i++) { + irq_id = gps_dl_linux_irq_index_to_id(p_irqs[i].cfg.index); + + if (irq_id == 0) { + GDL_LOGE_INI("i = %d, irq_id = %d, name = %s, bypass", + i, irq_id, p_irqs[i].cfg.name); + continue; + } + + if (p_irqs[i].cfg.trig_type == GPS_DL_IRQ_TRIG_LEVEL_HIGH) + sys_irq_flags = IRQF_TRIGGER_HIGH; + else if (p_irqs[i].cfg.trig_type == GPS_DL_IRQ_TRIG_EDGE_RISING) + sys_irq_flags = IRQF_TRIGGER_RISING; + else + return -1; + + /* TODO: Use the dts to auto request the irqs */ +#if GPS_DL_USE_THREADED_IRQ + /* IRQF_ONESHOT is required for threaded irq */ + sys_irq_flags |= IRQF_ONESHOT; + i_ret = request_threaded_irq(irq_id, NULL, + (irq_handler_t)p_irqs[i].cfg.isr, + sys_irq_flags, p_irqs[i].cfg.name, &p_irqs[i]); +#else + i_ret = request_irq(irq_id, + (irq_handler_t)p_irqs[i].cfg.isr, /* gps_dl_linux_irq_dispatcher */ + sys_irq_flags, p_irqs[i].cfg.name, &p_irqs[i]); +#endif + GDL_LOGW_INI("i = %d, irq_id = %d, name = %s, flags = 0x%lx, ret = %d", + i, irq_id, p_irqs[i].cfg.name, sys_irq_flags, i_ret); + if (i_ret) { + /* show error log */ + /* return i_ret; */ + continue; /* not stop even fail */ + } + + /* The init status is unmask, mask them here */ + gps_dl_irq_mask(irq_id, GPS_DL_IRQ_CTRL_FROM_THREAD); + p_irqs[i].register_done = true; + p_irqs[i].reg_irq_id = irq_id; + } + + return 0; +} + +int gps_dl_linux_irqs_unregister(struct gps_each_irq *p_irqs, int irq_num) +{ + int irq_id, i; + + for (i = 0; i < irq_num; i++) { + if (p_irqs[i].register_done) { + irq_id = gps_dl_linux_irq_index_to_id(p_irqs[i].cfg.index); + /* assert irq_id = p_irqs[i].reg_irq_id */ + free_irq(irq_id, &p_irqs[i]); + + p_irqs[i].register_done = false; + p_irqs[i].reg_irq_id = 0; + } + } + + return 0; +} + +irqreturn_t gps_dl_linux_irq_dispatcher(int irq, void *data) +{ + struct gps_each_irq *p_irq; + + p_irq = (struct gps_each_irq *)data; + + switch (p_irq->cfg.index) { + case GPS_DL_IRQ_LINK0_DATA: + gps_dl_isr_usrt_has_data(GPS_DATA_LINK_ID0); + break; + case GPS_DL_IRQ_LINK0_NODATA: + gps_dl_isr_usrt_has_nodata(GPS_DATA_LINK_ID0); + break; + case GPS_DL_IRQ_LINK0_MCUB: + gps_dl_isr_mcub(GPS_DATA_LINK_ID0); + break; + + case GPS_DL_IRQ_LINK1_DATA: + gps_dl_isr_usrt_has_data(GPS_DATA_LINK_ID1); + break; + case GPS_DL_IRQ_LINK1_NODATA: + gps_dl_isr_usrt_has_nodata(GPS_DATA_LINK_ID1); + break; + case GPS_DL_IRQ_LINK1_MCUB: + gps_dl_isr_mcub(GPS_DATA_LINK_ID1); + break; + + case GPS_DL_IRQ_DMA: + gps_dl_isr_dma_done(); + break; + + default: + break; + } + + return IRQ_HANDLED; +} + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_linux_plat_drv.c b/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_linux_plat_drv.c new file mode 100644 index 0000000000000..0410a0b3937ed --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_linux_plat_drv.c @@ -0,0 +1,555 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "gps_dl_config.h" + +#if GPS_DL_HAS_PLAT_DRV +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gps_dl_linux.h" +#include "gps_dl_linux_plat_drv.h" +#include "gps_dl_linux_reserved_mem.h" +#include "gps_dl_isr.h" +#include "gps_each_device.h" + +/* #ifdef CONFIG_OF */ +const struct of_device_id gps_dl_of_ids[] = { + { .compatible = "mediatek,mt6885-gps", }, + {} +}; +/* #endif */ +#define GPS_DL_IOMEM_NUM 2 + +struct gps_dl_iomem_addr_map_entry g_gps_dl_iomem_arrary[GPS_DL_IOMEM_NUM]; +struct gps_dl_iomem_addr_map_entry g_gps_dl_status_dummy_cr; +struct gps_dl_iomem_addr_map_entry g_gps_dl_tia1_gps; +struct gps_dl_iomem_addr_map_entry g_gps_dl_tia2_gps_on; +struct gps_dl_iomem_addr_map_entry g_gps_dl_tia2_gps_rc_sel; + + +void __iomem *gps_dl_host_addr_to_virt(unsigned int host_addr) +{ + int i; + int offset; + struct gps_dl_iomem_addr_map_entry *p; + + for (i = 0; i < GPS_DL_IOMEM_NUM; i++) { + p = &g_gps_dl_iomem_arrary[i]; + + if (p->length == 0) + continue; + + offset = host_addr - p->host_phys_addr; + if (offset >= 0 && offset < p->length) + return p->host_virt_addr + offset; + } + + return (void __iomem *)0; +} + +void gps_dl_update_status_for_md_blanking(bool gps_is_on) +{ + void __iomem *p = g_gps_dl_status_dummy_cr.host_virt_addr; + unsigned int val = (gps_is_on ? 1 : 0); + unsigned int val_old, val_new; + + if (p != NULL) { + val_old = __raw_readl(p); + gps_dl_linux_sync_writel(val, p); + val_new = __raw_readl(p); + GDL_LOGI_INI("dummy cr updated: %d -> %d, due to on = %d", + val_old, val_new, gps_is_on); + } else + GDL_LOGW_INI("dummy cr addr is invalid, can not update (on = %d)", gps_is_on); +} + +void gps_dl_tia1_gps_ctrl(bool gps_is_on) +{ + void __iomem *p = g_gps_dl_tia1_gps.host_virt_addr; + unsigned int tia_gps_on, tia_gps_ctrl, tia_temp; + unsigned int tia_gps_on1, tia_gps_ctrl1, tia_temp1; + + if (p == NULL) { + GDL_LOGW_INI("on = %d, tia_gps addr is null", gps_is_on); + return; + } + + tia_gps_on = __raw_readl(p); + tia_gps_ctrl = __raw_readl(p + 4); + tia_temp = __raw_readl(p + 8); + + if (gps_is_on) { + /* 0x1001C018[0] = 1 (GPS on) */ + gps_dl_linux_sync_writel(tia_gps_on | 1UL, p); + + /* 0x1001C01C[11:0] = 100 (~3ms update period, 1/32k = 0.03125ms) + * 0x1001C01C[12] = 1 (enable TSX) + * 0x1001C01C[13] = 1 (enable DCXO) + */ + /* 20190923 period changed to 196 (0xC4, 6ms) */ + gps_dl_linux_sync_writel((196UL | (1UL << 12) | (1UL << 13)), p + 4); + } else { + /* 0x1001C018[0] = 0 (GPS off) */ + gps_dl_linux_sync_writel(tia_gps_on & ~1UL, p); + } + + tia_gps_on1 = __raw_readl(p); + tia_gps_ctrl1 = __raw_readl(p + 4); + tia_temp1 = __raw_readl(p + 8); + + GDL_LOGI_INI( + "on = %d, tia_gps_on = 0x%08x/0x%08x, ctrl = 0x%08x/0x%08x, temp = 0x%08x/0x%08x", + gps_is_on, tia_gps_on, tia_gps_on1, + tia_gps_ctrl, tia_gps_ctrl1, + tia_temp, tia_temp1); +} + +void gps_dl_tia2_gps_ctrl(bool gps_is_on) +{ + void __iomem *p_gps_on = g_gps_dl_tia2_gps_on.host_virt_addr; + void __iomem *p_gps_rc_sel = g_gps_dl_tia2_gps_rc_sel.host_virt_addr; + unsigned int tia2_gps_on_old = 0, tia2_gps_rc_sel_old = 0; + unsigned int tia2_gps_on_new = 0, tia2_gps_rc_sel_new = 0; + + if (p_gps_on == NULL) { + GDL_LOGW_INI("on = %d, tia2_gps_on addr is null", gps_is_on); + return; + } + + tia2_gps_on_old = __raw_readl(p_gps_on); + if (gps_is_on) { + /* 0x1001C000[5] = 1 (GPS on) */ + gps_dl_linux_sync_writel(tia2_gps_on_old | (1UL << 5), p_gps_on); + + if (p_gps_rc_sel == NULL) + GDL_LOGW_INI("on = %d, p_gps_rc_sel addr is null", gps_is_on); + else { + /* 0x1001C030[ 1: 0] = 0 + * 0x1001C030[ 5: 4] = 0 + * 0x1001C030[ 9: 8] = 0 + * 0x1001C030[13:12] = 0 + * 0x1001C030[17:16] = 0 + */ + tia2_gps_rc_sel_old = __raw_readl(p_gps_rc_sel); + gps_dl_linux_sync_writel(tia2_gps_rc_sel_old & ~(0x00033333), p_gps_rc_sel); + tia2_gps_rc_sel_new = __raw_readl(p_gps_rc_sel); + } + } else { + tia2_gps_rc_sel_old = __raw_readl(p_gps_rc_sel); + + /* 0x1001C000[5] = 0 (GPS off) */ + gps_dl_linux_sync_writel(tia2_gps_on_old & ~(1UL << 5), p_gps_on); + } + tia2_gps_on_new = __raw_readl(p_gps_on); + GDL_LOGI_INI( + "on = %d, tia2_gps_on = 0x%08x/0x%08x, rc_sel = 0x%08x/0x%08x", + gps_is_on, + tia2_gps_on_old, tia2_gps_on_new, + tia2_gps_rc_sel_old, tia2_gps_rc_sel_new); +} + +void gps_dl_tia_gps_ctrl(bool gps_is_on) +{ + if (g_gps_dl_tia2_gps_on.host_virt_addr != NULL) + gps_dl_tia2_gps_ctrl(gps_is_on); + else if (g_gps_dl_tia1_gps.host_virt_addr != NULL) + gps_dl_tia1_gps_ctrl(gps_is_on); + else + GDL_LOGE("tia reg not found, bypass!"); +} + +enum gps_dl_pinctrl_state_enum { + GPS_DL_L1_LNA_DISABLE, + GPS_DL_L1_LNA_DSP_CTRL, + GPS_DL_L1_LNA_ENABLE, + GPS_DL_L5_LNA_DISABLE, + GPS_DL_L5_LNA_DSP_CTRL, + GPS_DL_L5_LNA_ENABLE, + GPS_DL_PINCTRL_STATE_CNT +}; + +const char *const gps_dl_pinctrl_state_name_list[GPS_DL_PINCTRL_STATE_CNT] = { + "gps_l1_lna_disable", + "gps_l1_lna_dsp_ctrl", + "gps_l1_lna_enable", + "gps_l5_lna_disable", + "gps_l5_lna_dsp_ctrl", + "gps_l5_lna_enable", +}; + +struct pinctrl_state *g_gps_dl_pinctrl_state_struct_list[GPS_DL_PINCTRL_STATE_CNT]; +struct pinctrl *g_gps_dl_pinctrl_ptr; + +void gps_dl_pinctrl_show_info(void) +{ + enum gps_dl_pinctrl_state_enum state_id; + const char *p_name; + struct pinctrl_state *p_state; + + GDL_LOGD_INI("pinctrl_ptr = 0x%p", g_gps_dl_pinctrl_ptr); + + for (state_id = 0; state_id < GPS_DL_PINCTRL_STATE_CNT; state_id++) { + p_name = gps_dl_pinctrl_state_name_list[state_id]; + p_state = g_gps_dl_pinctrl_state_struct_list[state_id]; + GDL_LOGD_INI("state id = %d, ptr = 0x%p, name = %s", + state_id, p_state, p_name); + } +} + +void gps_dl_pinctrl_context_init(void) +{ + enum gps_dl_pinctrl_state_enum state_id; + const char *p_name; + struct pinctrl_state *p_state; + + if (IS_ERR(g_gps_dl_pinctrl_ptr)) { + GDL_LOGE_INI("pinctrl is error"); + return; + } + + for (state_id = 0; state_id < GPS_DL_PINCTRL_STATE_CNT; state_id++) { + p_name = gps_dl_pinctrl_state_name_list[state_id]; + p_state = pinctrl_lookup_state(g_gps_dl_pinctrl_ptr, p_name); + + if (IS_ERR(p_state)) { + GDL_LOGE_INI("lookup fail: state id = %d, name = %s", state_id, p_name); + g_gps_dl_pinctrl_state_struct_list[state_id] = NULL; + continue; + } + + g_gps_dl_pinctrl_state_struct_list[state_id] = p_state; + GDL_LOGW_INI("lookup okay: state id = %d, name = %s", state_id, p_name); + } +} + +void gps_dl_lna_pin_ctrl(enum gps_dl_link_id_enum link_id, bool dsp_is_on, bool force_en) +{ + struct pinctrl_state *p_state = NULL; + int ret; + + ASSERT_LINK_ID(link_id, GDL_VOIDF()); + + if (GPS_DATA_LINK_ID0 == link_id) { + if (dsp_is_on && force_en) + p_state = g_gps_dl_pinctrl_state_struct_list[GPS_DL_L1_LNA_ENABLE]; + else if (dsp_is_on) + p_state = g_gps_dl_pinctrl_state_struct_list[GPS_DL_L1_LNA_DSP_CTRL]; + else + p_state = g_gps_dl_pinctrl_state_struct_list[GPS_DL_L1_LNA_DISABLE]; + } + + if (GPS_DATA_LINK_ID1 == link_id) { + if (dsp_is_on && force_en) + p_state = g_gps_dl_pinctrl_state_struct_list[GPS_DL_L5_LNA_ENABLE]; + else if (dsp_is_on) + p_state = g_gps_dl_pinctrl_state_struct_list[GPS_DL_L5_LNA_DSP_CTRL]; + else + p_state = g_gps_dl_pinctrl_state_struct_list[GPS_DL_L5_LNA_DISABLE]; + } + + if (p_state == NULL) { + GDL_LOGXW(link_id, "on = %d, force = %d, state is null", dsp_is_on, force_en); + return; + } + + ret = pinctrl_select_state(g_gps_dl_pinctrl_ptr, p_state); + if (ret != 0) + GDL_LOGXW(link_id, "on = %d, force = %d, select ret = %d", dsp_is_on, force_en, ret); + else + GDL_LOGXD(link_id, "on = %d, force = %d, select ret = %d", dsp_is_on, force_en, ret); +} + +bool gps_dl_get_iomem_by_name(struct platform_device *pdev, const char *p_name, + struct gps_dl_iomem_addr_map_entry *p_entry) +{ + struct resource *regs; + bool okay; + + regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, p_name); + if (regs != NULL) { + p_entry->length = resource_size(regs); + p_entry->host_phys_addr = regs->start; + p_entry->host_virt_addr = devm_ioremap(&pdev->dev, p_entry->host_phys_addr, p_entry->length); + okay = true; + } else { + p_entry->length = 0; + p_entry->host_phys_addr = 0; + p_entry->host_virt_addr = 0; + okay = false; + } + + GDL_LOGW_INI("phy_addr = 0x%08x, vir_addr = 0x%p, ok = %d, size = 0x%x, name = %s", + p_entry->host_phys_addr, p_entry->host_virt_addr, okay, p_entry->length, p_name); + + return okay; +} + +#if (GPS_DL_GET_RSV_MEM_IN_MODULE) +phys_addr_t gGpsRsvMemPhyBase; +unsigned long long gGpsRsvMemSize; +static int gps_dl_get_reserved_memory(struct device *dev) +{ + struct device_node *np; + struct reserved_mem *rmem; + + np = of_parse_phandle(dev->of_node, "memory-region", 0); + if (!np) { + GDL_LOGE_INI("no memory-region 1"); + return -EINVAL; + } + rmem = of_reserved_mem_lookup(np); + of_node_put(np); + if (!rmem) { + GDL_LOGE_INI("no memory-region 2"); + return -EINVAL; + } + GDL_LOGW_INI("resource base=%pa, size=%pa", &rmem->base, &rmem->size); + gGpsRsvMemPhyBase = (phys_addr_t)rmem->base; + gGpsRsvMemSize = (unsigned long long)rmem->size; + return 0; +} +#endif + +static int gps_dl_probe(struct platform_device *pdev) +{ + struct resource *irq; + struct gps_each_device *p_each_dev0 = gps_dl_device_get(GPS_DATA_LINK_ID0); + struct gps_each_device *p_each_dev1 = gps_dl_device_get(GPS_DATA_LINK_ID1); + int i; + bool okay; + +#if (GPS_DL_GET_RSV_MEM_IN_MODULE) + gps_dl_get_reserved_memory(&pdev->dev); +#endif + gps_dl_get_iomem_by_name(pdev, "conn_infra_base", &g_gps_dl_iomem_arrary[0]); + gps_dl_get_iomem_by_name(pdev, "conn_gps_base", &g_gps_dl_iomem_arrary[1]); + + okay = gps_dl_get_iomem_by_name(pdev, "status_dummy_cr", &g_gps_dl_status_dummy_cr); + if (okay) + gps_dl_update_status_for_md_blanking(false); + + /* TIA 1 */ + gps_dl_get_iomem_by_name(pdev, "tia_gps", &g_gps_dl_tia1_gps); + + /* TIA 2 */ + gps_dl_get_iomem_by_name(pdev, "tia2_gps_on", &g_gps_dl_tia2_gps_on); + gps_dl_get_iomem_by_name(pdev, "tia2_gps_rc_sel", &g_gps_dl_tia2_gps_rc_sel); + + for (i = 0; i < GPS_DL_IRQ_NUM; i++) { + irq = platform_get_resource(pdev, IORESOURCE_IRQ, i); + if (irq == NULL) { + GDL_LOGE_INI("irq idx = %d, ptr = NULL!", i); + continue; + } + + GDL_LOGW_INI("irq idx = %d, start = %lld, end = %lld, name = %s, flag = 0x%lx", + i, irq->start, irq->end, irq->name, irq->flags); + gps_dl_irq_set_id(i, irq->start); + } + + g_gps_dl_pinctrl_ptr = devm_pinctrl_get(&pdev->dev); + if (IS_ERR(g_gps_dl_pinctrl_ptr)) + GDL_LOGE_INI("devm_pinctrl_get fail"); + else { + gps_dl_pinctrl_context_init(); + gps_dl_pinctrl_show_info(); + } + + GDL_LOGW_INI("do gps_dl_probe"); + platform_set_drvdata(pdev, p_each_dev0); + p_each_dev0->private_data = (struct device *)&pdev->dev; + p_each_dev1->private_data = (struct device *)&pdev->dev; + + gps_dl_device_context_init(); + + return 0; +} + +static int gps_dl_remove(struct platform_device *pdev) +{ + struct gps_each_device *p_each_dev = gps_dl_device_get(GPS_DATA_LINK_ID0); + + GDL_LOGW_INI("do gps_dl_remove"); + platform_set_drvdata(pdev, NULL); + p_each_dev->private_data = NULL; + return 0; +} + +static int gps_dl_drv_suspend(struct device *dev) +{ +#if 0 + struct platform_device *pdev = to_platform_device(dev); + pm_message_t state = PMSG_SUSPEND; + + return mtk_btif_suspend(pdev, state); +#endif + return 0; +} + +static int gps_dl_drv_resume(struct device *dev) +{ +#if 0 + struct platform_device *pdev = to_platform_device(dev); + + return mtk_btif_resume(pdev); +#endif + return 0; +} + +static int gps_dl_plat_suspend(struct platform_device *pdev, pm_message_t state) +{ +#if 0 + int i_ret = 0; + struct _mtk_btif_ *p_btif = NULL; + + BTIF_DBG_FUNC("++\n"); + p_btif = platform_get_drvdata(pdev); + i_ret = _btif_suspend(p_btif); + BTIF_DBG_FUNC("--, i_ret:%d\n", i_ret); + return i_ret; +#endif + return 0; +} + +static int gps_dl_plat_resume(struct platform_device *pdev) +{ +#if 0 + int i_ret = 0; + struct _mtk_btif_ *p_btif = NULL; + + BTIF_DBG_FUNC("++\n"); + p_btif = platform_get_drvdata(pdev); + i_ret = _btif_resume(p_btif); + BTIF_DBG_FUNC("--, i_ret:%d\n", i_ret); + return i_ret; +#endif + return 0; +} + + +const struct dev_pm_ops gps_dl_drv_pm_ops = { + .suspend = gps_dl_drv_suspend, + .resume = gps_dl_drv_resume, +}; + +struct platform_driver gps_dl_dev_drv = { + .probe = gps_dl_probe, + .remove = gps_dl_remove, +/* #ifdef CONFIG_PM */ + .suspend = gps_dl_plat_suspend, + .resume = gps_dl_plat_resume, +/* #endif */ + .driver = { + .name = "gps", /* mediatek,gps */ + .owner = THIS_MODULE, +/* #ifdef CONFIG_PM */ + .pm = &gps_dl_drv_pm_ops, +/* #endif */ +/* #ifdef CONFIG_OF */ + .of_match_table = gps_dl_of_ids, +/* #endif */ + } +}; + +static ssize_t driver_flag_read(struct device_driver *drv, char *buf) +{ + return sprintf(buf, "gps dl driver debug level:%d\n", 1); +} + +static ssize_t driver_flag_set(struct device_driver *drv, + const char *buffer, size_t count) +{ + GDL_LOGW_INI("buffer = %s, count = %zd", buffer, count); + return count; +} + +#define DRIVER_ATTR(_name, _mode, _show, _store) \ + struct driver_attribute driver_attr_##_name = \ + __ATTR(_name, _mode, _show, _store) +static DRIVER_ATTR(flag, 0644, driver_flag_read, driver_flag_set); + + +int gps_dl_linux_plat_drv_register(void) +{ + int result; + gps_dl_wake_lock_init(); + + result = platform_driver_register(&gps_dl_dev_drv); + /* if (result) */ + GDL_LOGW_INI("platform_driver_register, ret(%d)\n", result); + + result = driver_create_file(&gps_dl_dev_drv.driver, &driver_attr_flag); + /* if (result) */ + GDL_LOGW_INI("driver_create_file, ret(%d)\n", result); + + return 0; +} + +int gps_dl_linux_plat_drv_unregister(void) +{ + driver_remove_file(&gps_dl_dev_drv.driver, &driver_attr_flag); + platform_driver_unregister(&gps_dl_dev_drv); + gps_dl_wake_lock_deinit(); + + return 0; +} + +static struct wakeup_source *g_gps_dl_wake_lock_ptr; +const char c_gps_dl_wake_lock_name[] = "gpsdl_wakelock"; +void gps_dl_wake_lock_init(void) +{ + GDL_LOGD_INI(""); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 149) + g_gps_dl_wake_lock_ptr = wakeup_source_register(NULL, c_gps_dl_wake_lock_name); +#else + g_gps_dl_wake_lock_ptr = wakeup_source_register(c_gps_dl_wake_lock_name); +#endif +} + +void gps_dl_wake_lock_deinit(void) +{ + GDL_LOGD_INI(""); + wakeup_source_unregister(g_gps_dl_wake_lock_ptr); +} + +void gps_dl_wake_lock_hold(bool hold) +{ + GDL_LOGD_ONF("hold = %d", hold); + if (hold) + __pm_stay_awake(g_gps_dl_wake_lock_ptr); + else + __pm_relax(g_gps_dl_wake_lock_ptr); +} + +#endif /* GPS_DL_HAS_PLAT_DRV */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_linux_reserved_mem.c b/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_linux_reserved_mem.c new file mode 100644 index 0000000000000..2207129e68ac1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_linux_reserved_mem.c @@ -0,0 +1,204 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#include "gps_dl_config.h" + +#if GPS_DL_HAS_PLAT_DRV +#include "gps_dl_context.h" +#include "gps_dl_linux_plat_drv.h" +#include "gps_dl_linux_reserved_mem.h" +#include "gps_dl_emi.h" + +#include + +#if (GPS_DL_SET_EMI_MPU_CFG) +#include +#if (defined(CONFIG_MACH_MT6885) || defined(CONFIG_MACH_MT6893)) +#define GPS_DL_EMI_MPU_DOMAIN_AP 0 +#define GPS_DL_EMI_MPU_DOMAIN_CONN 2 +#define GPS_DL_EMI_MPU_REGION_NUM 29 +#endif +#endif + +#define GPS_ICAP_MEM_SIZE (GPS_ICAP_BUF_SIZE) +#define GPS_RESERVED_MEM_PADDING_SIZE (4*1024) + +struct gps_dl_reserved_mem_layout { + unsigned char icap_buf[GPS_ICAP_MEM_SIZE]; + unsigned char padding1[GPS_RESERVED_MEM_PADDING_SIZE]; + unsigned char tx_dma_buf[GPS_DATA_LINK_NUM][GPS_DL_RX_BUF_SIZE + GPS_RESERVED_MEM_PADDING_SIZE]; + unsigned char rx_dma_buf[GPS_DATA_LINK_NUM][GPS_DL_RX_BUF_SIZE + GPS_RESERVED_MEM_PADDING_SIZE]; +}; + +struct gps_dl_iomem_addr_map_entry g_gps_dl_res_emi; + +void gps_dl_reserved_mem_init(void) +{ + void __iomem *host_virt_addr = NULL; +#if (GPS_DL_SET_EMI_MPU_CFG) + struct emimpu_region_t region; + int emimpu_ret1, emimpu_ret2, emimpu_ret3, emimpu_ret4, emimpu_ret5, emimpu_ret6; +#endif + unsigned int min_size = sizeof(struct gps_dl_reserved_mem_layout); + + if (gGpsRsvMemPhyBase == (phys_addr_t)NULL || gGpsRsvMemSize < min_size) { + GDL_LOGE_INI("res_mem: base = 0x%llx, size = 0x%llx, min_size = %d, not enough", + (unsigned long long)gGpsRsvMemPhyBase, + (unsigned long long)gGpsRsvMemSize, min_size); + return; + } + + host_virt_addr = ioremap_nocache(gGpsRsvMemPhyBase, gGpsRsvMemSize); + if (host_virt_addr == NULL) { + GDL_LOGE_INI("res_mem: base = 0x%llx, size = 0x%llx, ioremap fail", + (unsigned long long)gGpsRsvMemPhyBase, (unsigned long long)gGpsRsvMemSize); + return; + } + + /* Set EMI MPU permission */ +#if (GPS_DL_SET_EMI_MPU_CFG) + GDL_LOGI_INI("emi mpu cfg: region = %d, no protection domain = %d, %d", + GPS_DL_EMI_MPU_REGION_NUM, GPS_DL_EMI_MPU_DOMAIN_AP, GPS_DL_EMI_MPU_DOMAIN_CONN); + emimpu_ret1 = mtk_emimpu_init_region(®ion, GPS_DL_EMI_MPU_REGION_NUM); + emimpu_ret2 = mtk_emimpu_set_addr(®ion, gGpsRsvMemPhyBase, gGpsRsvMemPhyBase + gGpsRsvMemSize - 1); + emimpu_ret3 = mtk_emimpu_set_apc(®ion, GPS_DL_EMI_MPU_DOMAIN_AP, MTK_EMIMPU_NO_PROTECTION); + emimpu_ret4 = mtk_emimpu_set_apc(®ion, GPS_DL_EMI_MPU_DOMAIN_CONN, MTK_EMIMPU_NO_PROTECTION); + emimpu_ret5 = mtk_emimpu_set_protection(®ion); + emimpu_ret6 = mtk_emimpu_free_region(®ion); + GDL_LOGI_INI("emi mpu cfg: ret = %d, %d, %d, %d, %d, %d", + emimpu_ret1, emimpu_ret2, emimpu_ret3, emimpu_ret4, emimpu_ret5, emimpu_ret6); +#endif + + g_gps_dl_res_emi.host_phys_addr = gGpsRsvMemPhyBase; + g_gps_dl_res_emi.host_virt_addr = host_virt_addr; + g_gps_dl_res_emi.length = gGpsRsvMemSize; + + GDL_LOGI_INI("phy_addr = 0x%08x, vir_addr = 0x%p, size = 0x%x, min_size = 0x%x", + g_gps_dl_res_emi.host_phys_addr, + g_gps_dl_res_emi.host_virt_addr, + g_gps_dl_res_emi.length, min_size); + gps_dl_reserved_mem_show_info(); + gps_icap_probe(); +} + +void gps_dl_reserved_mem_deinit(void) +{ + GDL_LOGI_INI("phy_addr = 0x%08x, vir_addr = 0x%p, size = 0x%x", + g_gps_dl_res_emi.host_phys_addr, + g_gps_dl_res_emi.host_virt_addr, + g_gps_dl_res_emi.length); + + if (g_gps_dl_res_emi.host_virt_addr != NULL) + iounmap(g_gps_dl_res_emi.host_virt_addr); + else + GDL_LOGW_INI("host_virt_addr already null, not do iounmap"); + + g_gps_dl_res_emi.host_phys_addr = (dma_addr_t)NULL; + g_gps_dl_res_emi.host_virt_addr = (void *)NULL; + g_gps_dl_res_emi.length = 0; +} + +bool gps_dl_reserved_mem_is_ready(void) +{ + return (g_gps_dl_res_emi.host_virt_addr != NULL); +} + +void gps_dl_reserved_mem_get_range(unsigned int *p_min, unsigned int *p_max) +{ + *p_min = g_gps_dl_res_emi.host_phys_addr; + *p_max = g_gps_dl_res_emi.host_phys_addr + g_gps_dl_res_emi.length; +} + +void gps_dl_reserved_mem_show_info(void) +{ + unsigned int min_size = sizeof(struct gps_dl_reserved_mem_layout); + struct gps_dl_reserved_mem_layout *p_mem_vir; + unsigned int p_mem_phy; + unsigned int p_buf_phy, offset; + enum gps_dl_link_id_enum link_id; + + p_mem_phy = g_gps_dl_res_emi.host_phys_addr; + p_mem_vir = (struct gps_dl_reserved_mem_layout *)g_gps_dl_res_emi.host_virt_addr; + + GDL_LOGI_INI("phy_addr = 0x%08x, vir_addr = 0x%p, size = 0x%x, min_size = 0x%x", + g_gps_dl_res_emi.host_phys_addr, + g_gps_dl_res_emi.host_virt_addr, + g_gps_dl_res_emi.length, min_size); + + offset = (unsigned int)((void *)&p_mem_vir->icap_buf[0] - (void *)p_mem_vir); + GDL_LOGD_INI("icap_buf: phy_addr = 0x%08x, vir_addr = 0x%p, size = 0x%x", + p_mem_phy + offset, &p_mem_vir->icap_buf[0], GPS_ICAP_MEM_SIZE); + + for (link_id = 0; link_id < GPS_DATA_LINK_NUM; link_id++) { + offset = (unsigned int)((void *)&p_mem_vir->tx_dma_buf[link_id][0] - (void *)p_mem_vir); + p_buf_phy = p_mem_phy + offset; + GDL_LOGXD_INI(link_id, "tx_dma_buf: phy_addr = 0x%08x, vir_addr = 0x%p, size = 0x%x", + p_buf_phy, &p_mem_vir->tx_dma_buf[link_id][0], GPS_DL_TX_BUF_SIZE); + + offset = (unsigned int)((void *)&p_mem_vir->rx_dma_buf[link_id][0] - (void *)p_mem_vir); + p_buf_phy = p_mem_phy + offset; + GDL_LOGXD_INI(link_id, "rx_dma_buf: phy_addr = 0x%08x, vir_addr = 0x%p, size = 0x%x", + p_buf_phy, &p_mem_vir->rx_dma_buf[link_id][0], GPS_DL_RX_BUF_SIZE); + } +} + +void gps_dl_reserved_mem_dma_buf_init(struct gps_dl_dma_buf *p_dma_buf, + enum gps_dl_link_id_enum link_id, enum gps_dl_dma_dir dir, unsigned int len) +{ + struct gps_dl_reserved_mem_layout *p_mem_vir; + unsigned int p_mem_phy, offset; + + p_mem_vir = (struct gps_dl_reserved_mem_layout *)g_gps_dl_res_emi.host_virt_addr; + p_mem_phy = g_gps_dl_res_emi.host_phys_addr; + + memset(p_dma_buf, 0, sizeof(*p_dma_buf)); + p_dma_buf->dev_index = link_id; + p_dma_buf->dir = dir; + p_dma_buf->len = len; + + if (dir == GDL_DMA_A2D) { + p_dma_buf->vir_addr = (void *)&p_mem_vir->tx_dma_buf[link_id][0]; + } else if (dir == GDL_DMA_D2A) { + p_dma_buf->vir_addr = (void *)&p_mem_vir->rx_dma_buf[link_id][0]; + } else { + GDL_LOGXE(link_id, ""); + return; + } + + offset = (unsigned int)((void *)p_dma_buf->vir_addr - (void *)p_mem_vir); + p_dma_buf->phy_addr = p_mem_phy + offset; + + GDL_LOGI_INI("init gps dl dma buf(%d,%d) in arch64, addr: vir=0x%p, phy=0x%llx, len=%u\n", + p_dma_buf->dev_index, p_dma_buf->dir, + p_dma_buf->vir_addr, + p_dma_buf->phy_addr, p_dma_buf->len); +} + +void gps_dl_reserved_mem_dma_buf_deinit(struct gps_dl_dma_buf *p_dma_buf) +{ + memset(p_dma_buf, 0, sizeof(*p_dma_buf)); +} + +void *gps_dl_reserved_mem_icap_buf_get_vir_addr(void) +{ + struct gps_dl_reserved_mem_layout *p_mem_vir; + unsigned int p_mem_phy, offset; + + p_mem_phy = g_gps_dl_res_emi.host_phys_addr; + p_mem_vir = (struct gps_dl_reserved_mem_layout *)g_gps_dl_res_emi.host_virt_addr; + + if (p_mem_vir == NULL) { + GDL_LOGE("gps_icap_buf: null"); + return NULL; + } + + offset = (unsigned int)((void *)&p_mem_vir->icap_buf[0] - (void *)p_mem_vir); + GDL_LOGI("gps_icap_buf: phy_addr = 0x%08x, vir_addr = 0x%p, size = 0x%x", + p_mem_phy + offset, &p_mem_vir->icap_buf[0], GPS_ICAP_MEM_SIZE); + + return (void *)&p_mem_vir->icap_buf[0]; +} + +#endif /* GPS_DL_HAS_PLAT_DRV */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_osal.c b/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_osal.c new file mode 100644 index 0000000000000..2dc57d6a9450a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_osal.c @@ -0,0 +1,326 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "gps_dl_config.h" + +#include "gps_dl_osal.h" +#include "gps_dl_log.h" + + +char *gps_dl_osal_strncpy(char *dst, const char *src, unsigned int len) +{ + return strncpy(dst, src, len); +} + +char *gps_dl_osal_strsep(char **str, const char *c) +{ + return strsep(str, c); +} + +int gps_dl_osal_strtol(const char *str, unsigned int adecimal, long *res) +{ + if (sizeof(long) == 4) + return kstrtou32(str, adecimal, (unsigned int *) res); + else + return kstrtol(str, adecimal, res); +} + +void *gps_dl_osal_memset(void *buf, int i, unsigned int len) +{ + return memset(buf, i, len); +} + +int gps_dl_osal_thread_create(struct gps_dl_osal_thread *pThread) +{ + if (!pThread) + return -1; + + pThread->pThread = kthread_create(pThread->pThreadFunc, pThread->pThreadData, pThread->threadName); + if (pThread->pThread == NULL) + return -1; + + return 0; +} + +int gps_dl_osal_thread_run(struct gps_dl_osal_thread *pThread) +{ + if ((pThread) && (pThread->pThread)) { + wake_up_process(pThread->pThread); + return 0; + } else + return -1; +} + +int gps_dl_osal_thread_stop(struct gps_dl_osal_thread *pThread) +{ + int iRet; + + if ((pThread) && (pThread->pThread)) { + iRet = kthread_stop(pThread->pThread); + /* pThread->pThread = NULL; */ + return iRet; + } + return -1; +} + +int gps_dl_osal_thread_should_stop(struct gps_dl_osal_thread *pThread) +{ + if ((pThread) && (pThread->pThread)) + return kthread_should_stop(); + else + return 1; + +} + +int gps_dl_osal_thread_destroy(struct gps_dl_osal_thread *pThread) +{ + if (pThread && (pThread->pThread)) { + kthread_stop(pThread->pThread); + pThread->pThread = NULL; + } + return 0; +} + +int gps_dl_osal_thread_wait_for_event(struct gps_dl_osal_thread *pThread, + struct gps_dl_osal_event *pEvent, OSAL_EVENT_CHECKER pChecker) +{ + if ((pThread) && (pThread->pThread) && (pEvent) && (pChecker)) { + return wait_event_interruptible(pEvent->waitQueue, ( + gps_dl_osal_thread_should_stop(pThread) + || (*pChecker) (pThread))); + } + return -1; +} + +int gps_dl_osal_signal_init(struct gps_dl_osal_signal *pSignal) +{ + if (pSignal) { + init_completion(&pSignal->comp); + return 0; + } else + return -1; +} + +int gps_dl_osal_wait_for_signal(struct gps_dl_osal_signal *pSignal) +{ + if (pSignal) { + wait_for_completion_interruptible(&pSignal->comp); + return 0; + } else + return -1; +} + +/* + * gps_dl_osal_wait_for_signal_timeout + * + * Wait for a signal to be triggered by the corresponding thread, within the + * expected timeout specified by the signal's timeoutValue. + * When the pThread parameter is specified, the thread's scheduling ability is + * considered, the timeout will be extended when thread cannot acquire CPU + * resource, and will only extend for a number of times specified by the + * signal's timeoutExtension should the situation continues. + * + * Return value: + * 0 : timeout + * >0 : signal triggered + */ +int gps_dl_osal_wait_for_signal_timeout(struct gps_dl_osal_signal *pSignal, struct gps_dl_osal_thread *pThread) +{ + /* struct gps_dl_osal_thread_schedstats schedstats; */ + /* int waitRet; */ + + /* 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. + */ + if (!pThread || !pThread->pThread) + return wait_for_completion_timeout(&pSignal->comp, msecs_to_jiffies(pSignal->timeoutValue)); +#if 0 + do { + osal_thread_sched_mark(pThread, &schedstats); + waitRet = wait_for_completion_timeout(&pSignal->comp, msecs_to_jiffies(pSignal->timeoutValue)); + osal_thread_sched_unmark(pThread, &schedstats); + + if (waitRet > 0) + break; + + if (schedstats.runnable > schedstats.exec) { + gps_dl_osal_err_print( + "[E]%s:wait completion timeout, %s cannot get CPU, extension(%d), show backtrace:\n", + __func__, + pThread->threadName, + pSignal->timeoutExtension); + } else { + gps_dl_osal_err_print("[E]%s:wait completion timeout, show %s backtrace:\n", + __func__, + pThread->threadName); + pSignal->timeoutExtension = 0; + } + gps_dl_osal_err_print("[E]%s:\tduration:%llums, sched(x%llu/r%llu/i%llu)\n", + __func__, + schedstats.time, + schedstats.exec, + schedstats.runnable, + schedstats.iowait); + /* + * no need to disginguish combo or A/D die projects + * osal_dump_thread_state will just return if target thread does not exist + */ + osal_dump_thread_state("mtk_wmtd"); + osal_dump_thread_state("btif_rxd"); + osal_dump_thread_state("mtk_stp_psm"); + osal_dump_thread_state("mtk_stp_btm"); + osal_dump_thread_state("stp_sdio_tx_rx"); + } while (pSignal->timeoutExtension--); + return waitRet; +#endif + return 1; +} + +int gps_dl_osal_raise_signal(struct gps_dl_osal_signal *pSignal) +{ + if (pSignal) { + complete(&pSignal->comp); + return 0; + } else + return -1; +} + +int gps_dl_osal_signal_active_state(struct gps_dl_osal_signal *pSignal) +{ + if (pSignal) + return pSignal->timeoutValue; + else + return -1; +} + +int gps_dl_osal_op_is_wait_for_signal(struct gps_dl_osal_lxop *pOp) +{ + return (pOp && pOp->signal.timeoutValue) ? 1 : 0; +} + +void gps_dl_osal_op_raise_signal(struct gps_dl_osal_lxop *pOp, int result) +{ + if (pOp) { + pOp->result = result; + gps_dl_osal_raise_signal(&pOp->signal); + } +} + +int gps_dl_osal_signal_deinit(struct gps_dl_osal_signal *pSignal) +{ + if (pSignal) { + pSignal->timeoutValue = 0; + return 0; + } else + return -1; +} + +/* + *OSAL layer Event Opeartion related APIs + *initialization + *wait for signal + *wait for signal timerout + *raise signal + *destroy a signal + * +*/ + +int gps_dl_osal_event_init(struct gps_dl_osal_event *pEvent) +{ + if (pEvent) { + init_waitqueue_head(&pEvent->waitQueue); + return 0; + } + return -1; +} + +int gps_dl_osal_trigger_event(struct gps_dl_osal_event *pEvent) +{ + int ret = 0; + + if (pEvent) { + wake_up_interruptible(&pEvent->waitQueue); + return ret; + } + return -1; +} + +int gps_dl_osal_wait_for_event(struct gps_dl_osal_event *pEvent, int (*condition)(void *), void *cond_pa) +{ + if (pEvent) + return wait_event_interruptible(pEvent->waitQueue, condition(cond_pa)); + else + return -1; +} + +int gps_dl_osal_wait_for_event_timeout(struct gps_dl_osal_event *pEvent, int (*condition)(void *), void *cond_pa) +{ + if (pEvent) + return wait_event_interruptible_timeout(pEvent->waitQueue, + condition(cond_pa), + msecs_to_jiffies(pEvent->timeoutValue)); + return -1; +} + +int gps_dl_osal_event_deinit(struct gps_dl_osal_event *pEvent) +{ + return 0; +} + +int gps_dl_osal_sleepable_lock_init(struct gps_dl_osal_sleepable_lock *pSL) +{ + mutex_init(&pSL->lock); + return 0; +} + +int gps_dl_osal_lock_sleepable_lock(struct gps_dl_osal_sleepable_lock *pSL) +{ + return mutex_lock_killable(&pSL->lock); +} + +int gps_dl_osal_unlock_sleepable_lock(struct gps_dl_osal_sleepable_lock *pSL) +{ + mutex_unlock(&pSL->lock); + return 0; +} + +int gps_dl_osal_trylock_sleepable_lock(struct gps_dl_osal_sleepable_lock *pSL) +{ + return mutex_trylock(&pSL->lock); +} + +int gps_dl_osal_sleepable_lock_deinit(struct gps_dl_osal_sleepable_lock *pSL) +{ + mutex_destroy(&pSL->lock); + return 0; +} + +int gps_dl_osal_unsleepable_lock_init(struct gps_dl_osal_unsleepable_lock *pUSL) +{ + spin_lock_init(&(pUSL->lock)); + return 0; +} + +int gps_dl_osal_lock_unsleepable_lock(struct gps_dl_osal_unsleepable_lock *pUSL) +{ + spin_lock_irqsave(&(pUSL->lock), pUSL->flag); + return 0; +} + +int gps_dl_osal_unlock_unsleepable_lock(struct gps_dl_osal_unsleepable_lock *pUSL) +{ + spin_unlock_irqrestore(&(pUSL->lock), pUSL->flag); + return 0; +} + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_procfs.c b/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_procfs.c new file mode 100644 index 0000000000000..bb92ed55e55ff --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_dl_procfs.c @@ -0,0 +1,239 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "gps_dl_config.h" + +#include +#include +#include +#include "gps_dl_osal.h" +#include "gps_dl_procfs.h" +#include "gps_dl_context.h" +#include "gps_each_link.h" +#include "gps_dl_subsys_reset.h" + +int gps_dl_procfs_dummy_op(int y, int z) +{ + GDL_LOGW("do nothing: y = %d, z = %d", y, z); + return 0; +} + +int gps_dl_procfs_set_opt(int y, int z) +{ + if (y == 0) + gps_dl_log_info_show(); + else if (y == 1) { + enum gps_dl_log_level_enum level_old, level_new; + + level_old = gps_dl_log_level_get(); + gps_dl_log_level_set(z); + level_new = gps_dl_log_level_get(); + GDL_LOGW("log level change: %d to %d", level_old, level_new); + } else if (y == 2) { + unsigned int mod_old, mod_new; + + mod_old = gps_dl_log_mod_bitmask_get(); + gps_dl_log_mod_bitmask_set(z); + mod_new = gps_dl_log_level_get(); + GDL_LOGW("log modules change: 0x%x to 0x%x", mod_old, mod_new); + } else if (y == 3) { + unsigned int mod_old, mod_new; + + mod_old = gps_dl_log_mod_bitmask_get(); + gps_dl_log_mod_on(z); + mod_new = gps_dl_log_level_get(); + GDL_LOGW("log modules change: 0x%x to 0x%x", mod_old, mod_new); + } else if (y == 4) { + unsigned int mod_old, mod_new; + + mod_old = gps_dl_log_mod_bitmask_get(); + gps_dl_log_mod_off(z); + mod_new = gps_dl_log_level_get(); + GDL_LOGW("log modules change: 0x%x to 0x%x", mod_old, mod_new); + } else if (y == 5) { + bool rrw_old, rrw_new; + + rrw_old = gps_dl_show_reg_rw_log(); + if (z == 0) + gps_dl_set_show_reg_rw_log(false); + else if (z == 1) + gps_dl_set_show_reg_rw_log(true); + rrw_new = gps_dl_show_reg_rw_log(); + GDL_LOGW("log rrw change: %d to %d", rrw_old, rrw_new); + } + + return 0; +} + +int gps_dl_procfs_trigger_reset(int y, int z) +{ + if (y == 0) + gps_dl_trigger_connsys_reset(); + else if (y == 1) + gps_dl_trigger_gps_subsys_reset((bool)z); + else if (y == 2 && (z >= 0 && z <= GPS_DATA_LINK_NUM)) + gps_each_link_reset(z); + else if (y == 3) + gps_dl_trigger_gps_print_hw_status(); + else if (y == 4 && (z >= 0 && z <= GPS_DATA_LINK_NUM)) + gps_dl_test_mask_hasdata_irq_set(z, true); + else if (y == 6 && (z >= 0 && z <= GPS_DATA_LINK_NUM)) + gps_dl_test_mask_mcub_irq_on_open_set(z, true); + else if (y == 7) + gps_dl_trigger_gps_print_data_status(); + return 0; +} + +gps_dl_procfs_test_func_type g_gps_dl_proc_test_func_list[] = { + [0x00] = gps_dl_procfs_dummy_op, + /* [0x01] = TODO: reg read */ + /* [0x02] = TODO: reg write */ + [0x03] = gps_dl_procfs_set_opt, + [0x04] = gps_dl_procfs_trigger_reset, +}; + +#define UNLOCK_MAGIC 0xDB9DB9 +#define PROCFS_WR_BUF_SIZE 256 +ssize_t gps_dl_procfs_write(struct file *filp, const char __user *buffer, size_t count, loff_t *f_pos) +{ + size_t len = count, sub_len; + char buf[PROCFS_WR_BUF_SIZE]; + char *pBuf; + int x = 0, y = 0, z = 0; + char *pToken = NULL; + long res; + static bool gpsdl_dbg_enabled; + + GDL_LOGD("write parameter len = %d", (int)len); + if (len >= PROCFS_WR_BUF_SIZE) { + GDL_LOGE("input handling fail!"); + return -1; + } + + if (copy_from_user(buf, buffer, len)) + return -EFAULT; + + buf[len] = '\0'; + pBuf = buf; + do { + if (!pBuf) { + GDL_LOGW("x,y,z use default value - case0"); + break; + } + res = 0; + sub_len = strlen(pBuf); + GDL_LOGD("write parameter data = %s, len = %ld", pBuf, sub_len); + if (sub_len != 0) + pToken = gps_dl_osal_strsep(&pBuf, "\t\n\r "); + if (sub_len != 0 && pToken != NULL) { + gps_dl_osal_strtol(pToken, 16, &res); + x = (int)res; + } else { + GDL_LOGW("x use default value"); + break; + } + + if (!pBuf) { + GDL_LOGW("y use default value - case1"); + break; + } + res = 0; + sub_len = strlen(pBuf); + GDL_LOGD("write parameter data = %s, len = %ld", pBuf, sub_len); + if (sub_len != 0) + pToken = gps_dl_osal_strsep(&pBuf, "\t\n\r "); + if (sub_len != 0 && pToken != NULL) { + gps_dl_osal_strtol(pToken, 16, &res); + y = (int)res; + } else { + GDL_LOGW("y use default value - case2"); + break; + } + + if (!pBuf) { + GDL_LOGW("z use default value - case1"); + break; + } + res = 0; + sub_len = strlen(pBuf); + GDL_LOGD("write parameter data = %s, len = %ld", pBuf, sub_len); + if (sub_len != 0) + pToken = gps_dl_osal_strsep(&pBuf, "\t\n\r "); + if (sub_len != 0 && pToken != NULL) { + gps_dl_osal_strtol(pToken, 16, &res); + z = (int)res; + } else { + GDL_LOGW("z use default value - case2"); + break; + } + } while (0); + GDL_LOGW("x = 0x%08x, y = 0x%08x, z = 0x%08x", x, y, z); + + /* For eng and userdebug load, have to enable gpsdl_dbg by + * writing 0xDB9DB9 to * "/proc/driver/gpsdl_dbg" to avoid + * some malicious use + */ + if (x == UNLOCK_MAGIC) { + gpsdl_dbg_enabled = true; + return len; + } + + if (!gpsdl_dbg_enabled) { + GDL_LOGW("please enable gpsdl_dbg firstly"); + return len; + } + + if (ARRAY_SIZE(g_gps_dl_proc_test_func_list) > x && NULL != g_gps_dl_proc_test_func_list[x]) + (*g_gps_dl_proc_test_func_list[x])(y, z); + else + GDL_LOGW("no handler defined for command id, x = 0x%08x", x); + + return len; +} + +ssize_t gps_dl_procfs_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + return 0; +} + +static const struct file_operations gps_dl_procfs_fops = { + .owner = THIS_MODULE, + .read = gps_dl_procfs_read, + .write = gps_dl_procfs_write, +}; + +static struct proc_dir_entry *g_gps_dl_procfs_entry; +#define GPS_DL_PROCFS_NAME "driver/gpsdl_dbg" + +int gps_dl_procfs_setup(void) +{ + + int i_ret = 0; + + g_gps_dl_procfs_entry = proc_create(GPS_DL_PROCFS_NAME, + 0664, NULL, &gps_dl_procfs_fops); + + if (g_gps_dl_procfs_entry == NULL) { + GDL_LOGE("Unable to create gps proc entry"); + i_ret = -1; + } + + return i_ret; +} + +int gps_dl_procfs_remove(void) +{ + if (g_gps_dl_procfs_entry != NULL) + proc_remove(g_gps_dl_procfs_entry); + return 0; +} + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_each_device.c b/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_each_device.c new file mode 100644 index 0000000000000..9285902997648 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/linux/gps_each_device.c @@ -0,0 +1,469 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "gps_each_device.h" +#include "gps_each_link.h" +#include "gps_dsp_fsm.h" +#if GPS_DL_MOCK_HAL +#include "gps_mock_mvcd.h" +#endif +#include "gps_dl_hal.h" +#include "gps_dl_ctrld.h" +#include "gps_data_link_devices.h" +#include "gps_dl_subsys_reset.h" +#include "gps_dl_hist_rec.h" + +static ssize_t gps_each_device_read(struct file *filp, + char __user *buf, size_t count, loff_t *f_pos) +{ + int retval; + int retlen; + int pid; + struct gps_each_device *dev; + enum gps_dl_link_id_enum link_id; + bool print_log = false; + + dev = (struct gps_each_device *)filp->private_data; + pid = current->pid; + link_id = (enum gps_dl_link_id_enum)dev->index; + + /* show read log after ram code downloading to avoid print too much */ + if (gps_dsp_state_get(link_id) != GPS_DSP_ST_RESET_DONE) { + GDL_LOGXI_DRW(link_id, "buf_len = %ld, pid = %d", count, pid); + print_log = true; + } else { + GDL_LOGXD_DRW(link_id, "buf_len = %ld, pid = %d", count, pid); + } + gps_each_link_rec_read(link_id, pid, count, DRW_ENTER); + + retlen = gps_each_link_read(link_id, &dev->i_buf[0], count); + if (retlen > 0) { + retval = copy_to_user(buf, &dev->i_buf[0], retlen); + if (retval != 0) { + GDL_LOGXW_DRW(link_id, "copy to user len = %d, retval = %d", + retlen, retval); + retlen = -EFAULT; + } + } + if (print_log) + GDL_LOGXI_DRW(link_id, "ret_len = %d", retlen); + else + GDL_LOGXD_DRW(link_id, "ret_len = %d", retlen); + gps_each_link_rec_read(link_id, pid, retlen, DRW_RETURN); + return retlen; +} + +static ssize_t gps_each_device_write(struct file *filp, + const char __user *buf, size_t count, loff_t *f_pos) +{ + int retval; + int retlen = 0; + int copy_size; + int pid; + struct gps_each_device *dev; + enum gps_dl_link_id_enum link_id; + bool print_log = false; + + dev = (struct gps_each_device *)filp->private_data; + pid = current->pid; + link_id = (enum gps_dl_link_id_enum)dev->index; + + /* show write log after ram code downloading to avoid print too much */ + if (gps_dsp_state_get(link_id) != GPS_DSP_ST_RESET_DONE) { + GDL_LOGXI_DRW(link_id, "len = %ld, pid = %d", count, pid); + print_log = true; + } else { + GDL_LOGXD_DRW(link_id, "len = %ld, pid = %d", count, pid); + } + gps_each_link_rec_write(link_id, pid, count, DRW_ENTER); + + if (count > 0) { + if (count > GPS_DATA_PATH_BUF_MAX) { + GDL_LOGXW_DRW(link_id, "len = %ld is too long", count); + copy_size = GPS_DATA_PATH_BUF_MAX; + } else + copy_size = count; + + retval = copy_from_user(&dev->o_buf[0], &buf[0], copy_size); + if (retval != 0) { + GDL_LOGXW_DRW(link_id, "copy from user len = %d, retval = %d", + copy_size, retval); + retlen = -EFAULT; + } else { + retval = gps_each_link_write(link_id, &dev->o_buf[0], copy_size); + if (retval == 0) + retlen = copy_size; + else + retlen = 0; + } + } + + if (print_log) + GDL_LOGXI_DRW(link_id, "ret_len = %d", retlen); + else + GDL_LOGXD_DRW(link_id, "ret_len = %d", retlen); + gps_each_link_rec_write(link_id, pid, retlen, DRW_RETURN); + return retlen; +} + +#if 0 +void gps_each_device_data_submit(unsigned char *buf, unsigned int len, int index) +{ + struct gps_each_device *dev; + + dev = gps_dl_device_get(index); + + GDL_LOGI("gps_each_device_data_submit len = %d, index = %d, dev = %p", + len, index, dev); + + if (!dev) + return; + + if (!dev->is_open) + return; + +#if GPS_DL_CTRLD_MOCK_LINK_LAYER + /* TODO: using mutex, len check */ + memcpy(&dev->i_buf[0], buf, len); + dev->i_len = len; + wake_up(&dev->r_wq); +#else + gps_dl_add_to_rx_queue(buf, len, index); + /* wake_up(&dev->r_wq); */ +#endif + + GDL_LOGI("gps_each_device_data_submit copy and wakeup done"); +} +#endif + +static int gps_each_device_open(struct inode *inode, struct file *filp) +{ + struct gps_each_device *dev; /* device information */ + int retval; + + dev = container_of(inode->i_cdev, struct gps_each_device, cdev); + filp->private_data = dev; /* for other methods */ + + GDL_LOGXW(dev->index, "major = %d, minor = %d, pid = %d", + imajor(inode), iminor(inode), current->pid); + + if (!dev->is_open) { + retval = gps_each_link_open((enum gps_dl_link_id_enum)dev->index); + + if (0 == retval) { + dev->is_open = true; + gps_each_link_rec_reset(dev->index); + } else + return retval; + } + + return 0; +} + +static int gps_each_device_hw_resume(enum gps_dl_link_id_enum link_id) +{ + int pid; + int retval; + + pid = current->pid; + GDL_LOGXW(link_id, "pid = %d", pid); + + retval = gps_each_link_hw_resume(link_id); + + /* device read may arrive before resume, not reset the recording here + * gps_each_link_rec_reset(link_id); + */ + + return retval; +} + +static int gps_each_device_release(struct inode *inode, struct file *filp) +{ + struct gps_each_device *dev; + + dev = (struct gps_each_device *)filp->private_data; + dev->is_open = false; + + GDL_LOGXW(dev->index, "major = %d, minor = %d, pid = %d", + imajor(inode), iminor(inode), current->pid); + + gps_each_link_close((enum gps_dl_link_id_enum)dev->index); + gps_each_link_rec_force_dump(dev->index); + + return 0; +} + +static int gps_each_device_hw_suspend(enum gps_dl_link_id_enum link_id, bool need_clk_ext) +{ + int pid; + int retval; + + pid = current->pid; + GDL_LOGXW(link_id, "pid = %d, clk_ext = %d", pid, need_clk_ext); + + retval = gps_each_link_hw_suspend(link_id, need_clk_ext); + gps_each_link_rec_force_dump(link_id); + + return retval; +} + +#define GPSDL_IOC_GPS_HWVER 6 +#define GPSDL_IOC_GPS_IC_HW_VERSION 7 +#define GPSDL_IOC_GPS_IC_FW_VERSION 8 +#define GPSDL_IOC_D1_EFUSE_GET 9 +#define GPSDL_IOC_RTC_FLAG 10 +#define GPSDL_IOC_CO_CLOCK_FLAG 11 +#define GPSDL_IOC_TRIGGER_ASSERT 12 +#define GPSDL_IOC_QUERY_STATUS 13 +#define GPSDL_IOC_TAKE_GPS_WAKELOCK 14 +#define GPSDL_IOC_GIVE_GPS_WAKELOCK 15 +#define GPSDL_IOC_GET_GPS_LNA_PIN 16 +#define GPSDL_IOC_GPS_FWCTL 17 +#define GPSDL_IOC_GPS_HW_SUSPEND 18 +#define GPSDL_IOC_GPS_HW_RESUME 19 +#define GPSDL_IOC_GPS_LISTEN_RST_EVT 20 + +static int gps_each_device_ioctl_inner(struct file *filp, unsigned int cmd, unsigned long arg, bool is_compat) +{ + struct gps_each_device *dev; /* device information */ + int retval; + +#if 0 + dev = container_of(inode->i_cdev, struct gps_each_device, cdev); + filp->private_data = dev; /* for other methods */ +#endif + dev = (struct gps_each_device *)(filp->private_data); + + GDL_LOGXD(dev->index, "cmd = %d, is_compat = %d", cmd, is_compat); +#if 0 + int retval = 0; + ENUM_WMTHWVER_TYPE_T hw_ver_sym = WMTHWVER_INVALID; + UINT32 hw_version = 0; + UINT32 fw_version = 0; + UINT32 gps_lna_pin = 0; +#endif + switch (cmd) { + case GPSDL_IOC_TRIGGER_ASSERT: + /* Trigger FW assert for debug */ + GDL_LOGXW_DRW(dev->index, "GPSDL_IOC_TRIGGER_ASSERT, reason = %ld", arg); + + /* TODO: assert dev->is_open */ + if (dev->index == GPS_DATA_LINK_ID0) + retval = gps_dl_trigger_gps_subsys_reset(false); + else + retval = gps_each_link_reset(dev->index); + break; + case GPSDL_IOC_QUERY_STATUS: + retval = gps_each_link_check(dev->index, arg); + gps_each_link_rec_force_dump(dev->index); + GDL_LOGXW_DRW(dev->index, "GPSDL_IOC_QUERY_STATUS, reason = %ld, ret = %d", arg, retval); + break; + case GPSDL_IOC_CO_CLOCK_FLAG: + retval = gps_dl_link_get_clock_flag(); + GDL_LOGXD_ONF(dev->index, "gps clock flag = 0x%x", retval); + break; +#if 0 + case GPSDL_IOC_GPS_HWVER: + /*get combo hw version */ + /* hw_ver_sym = mtk_wcn_wmt_hwver_get(); */ + + GPS_DBG_FUNC("GPS_ioctl(): get hw version = %d, sizeof(hw_ver_sym) = %zd\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 GPSDL_IOC_GPS_IC_HW_VERSION: + /*get combo hw version from ic, without wmt mapping */ + hw_version = mtk_wcn_wmt_ic_info_get(WMTCHIN_HWVER); + + GPS_DBG_FUNC("GPS_ioctl(): get hw version = 0x%x\n", hw_version); + if (copy_to_user((int __user *)arg, &hw_version, sizeof(hw_version))) + retval = -EFAULT; + + break; + + case GPSDL_IOC_GPS_IC_FW_VERSION: + /*get combo fw version from ic, without wmt mapping */ + fw_version = mtk_wcn_wmt_ic_info_get(WMTCHIN_FWVER); + + GPS_DBG_FUNC("GPS_ioctl(): get fw version = 0x%x\n", fw_version); + if (copy_to_user((int __user *)arg, &fw_version, sizeof(fw_version))) + retval = -EFAULT; + + break; + case GPSDL_IOC_RTC_FLAG: + + retval = rtc_GPS_low_power_detected(); + + GPS_DBG_FUNC("low power flag (%d)\n", retval); + break; + case GPSDL_IOC_CO_CLOCK_FLAG: +#if SOC_CO_CLOCK_FLAG + retval = mtk_wcn_wmt_co_clock_flag_get(); +#endif + GPS_DBG_FUNC("GPS co_clock_flag (%d)\n", retval); + break; + case GPSDL_IOC_D1_EFUSE_GET: +#if defined(CONFIG_MACH_MT6735) + do { + char *addr = ioremap(0x10206198, 0x4); + + retval = *(unsigned int *)addr; + GPS_DBG_FUNC("D1 efuse (0x%x)\n", retval); + iounmap(addr); + } while (0); +#elif defined(CONFIG_MACH_MT6763) + do { + char *addr = ioremap(0x11f10048, 0x4); + + retval = *(unsigned int *)addr; + GPS_DBG_FUNC("MT6763 efuse (0x%x)\n", retval); + iounmap(addr); + } while (0); +#else + GPS_ERR_FUNC("Read Efuse not supported in this platform\n"); +#endif + break; + + case GPSDL_IOC_TAKE_GPS_WAKELOCK: + GPS_INFO_FUNC("Ioctl to take gps wakelock\n"); + gps_hold_wake_lock(1); + if (wake_lock_acquired == 1) + retval = 0; + else + retval = -EAGAIN; + break; + case GPSDL_IOC_GIVE_GPS_WAKELOCK: + GPS_INFO_FUNC("Ioctl to give gps wakelock\n"); + gps_hold_wake_lock(0); + if (wake_lock_acquired == 0) + retval = 0; + else + retval = -EAGAIN; + break; +#ifdef GPS_FWCTL_SUPPORT + case GPSDL_IOC_GPS_FWCTL: + GPS_INFO_FUNC("GPSDL_IOC_GPS_FWCTL\n"); + retval = GPS_fwctl((struct gps_fwctl_data *)arg); + break; +#endif + case GPSDL_IOC_GET_GPS_LNA_PIN: + gps_lna_pin = mtk_wmt_get_gps_lna_pin_num(); + GPS_DBG_FUNC("GPS_ioctl(): get gps lna pin = %d\n", gps_lna_pin); + if (copy_to_user((int __user *)arg, &gps_lna_pin, sizeof(gps_lna_pin))) + retval = -EFAULT; + break; +#endif + case GPSDL_IOC_GPS_HW_SUSPEND: + /* arg == 1 stand for need clk extension, otherwise is normal deep sotp mode */ + retval = gps_each_device_hw_suspend(dev->index, (arg == 1)); + GDL_LOGXI_ONF(dev->index, + "GPSDL_IOC_GPS_HW_SUSPEND: arg = %ld, ret = %d", arg, retval); + break; + case GPSDL_IOC_GPS_HW_RESUME: + retval = gps_each_device_hw_resume(dev->index); + GDL_LOGXI_ONF(dev->index, + "GPSDL_IOC_GPS_HW_RESUME: arg = %ld, ret = %d", arg, retval); + break; + case GPSDL_IOC_GPS_LISTEN_RST_EVT: + retval = -EINVAL; + GDL_LOGXI_ONF(dev->index, + "GPSDL_IOC_GPS_LISTEN_RST_EVT retval = %d", retval); + break; + case 21505: + case 21506: + case 21515: + /* known unsupported cmd */ + retval = -EFAULT; + GDL_LOGXD_DRW(dev->index, "cmd = %d, not support", cmd); + break; + default: + retval = -EFAULT; + GDL_LOGXI_DRW(dev->index, "cmd = %d, not support", cmd); + break; + } + + return retval; +} + + +static long gps_each_device_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + return gps_each_device_ioctl_inner(filp, cmd, arg, false); +} + +static long gps_each_device_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + return gps_each_device_ioctl_inner(filp, cmd, arg, true); +} + +static const struct file_operations gps_each_device_fops = { + .owner = THIS_MODULE, + .open = gps_each_device_open, + .read = gps_each_device_read, + .write = gps_each_device_write, + .release = gps_each_device_release, + .unlocked_ioctl = gps_each_device_unlocked_ioctl, + .compat_ioctl = gps_each_device_compat_ioctl, +}; + +int gps_dl_cdev_setup(struct gps_each_device *dev, int index) +{ + int result; + + init_waitqueue_head(&dev->r_wq); + dev->i_len = 0; + + dev->index = index; + /* assert dev->index == dev->cfg.index */ + + cdev_init(&dev->cdev, &gps_each_device_fops); + dev->cdev.owner = THIS_MODULE; + dev->cdev.ops = &gps_each_device_fops; + + result = cdev_add(&dev->cdev, dev->devno, 1); + if (result) { + GDL_LOGE("cdev_add error %d on index %d", result, index); + return result; + } + + dev->cls = class_create(THIS_MODULE, dev->cfg.dev_name); + if (IS_ERR(dev->cls)) { + GDL_LOGE("class_create fail on %s", dev->cfg.dev_name); + return -1; + } + + dev->dev = device_create(dev->cls, NULL, dev->devno, NULL, dev->cfg.dev_name); + if (IS_ERR(dev->dev)) { + GDL_LOGE("device_create fail on %s", dev->cfg.dev_name); + return -1; + } + + return 0; +} + +void gps_dl_cdev_cleanup(struct gps_each_device *dev, int index) +{ + if (dev->dev) { + device_destroy(dev->cls, dev->devno); + dev->dev = NULL; + } + + if (dev->cls) { + class_destroy(dev->cls); + dev->cls = NULL; + } + + cdev_del(&dev->cdev); +} + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_data_link_devices.h b/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_data_link_devices.h new file mode 100644 index 0000000000000..d23e0ebc14f42 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_data_link_devices.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _GPS_DATA_LINK_DEVICES_H +#define _GPS_DATA_LINK_DEVICES_H + +#include "gps_dl_config.h" + +int mtk_gps_data_link_devices_init(void); +void mtk_gps_data_link_devices_exit(void); + +#endif /* _GPS_DATA_LINK_DEVICES_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_ctrld.h b/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_ctrld.h new file mode 100644 index 0000000000000..6f95e8ff8a375 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_ctrld.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _GPS_DL_CTRLD_H +#define _GPS_DL_CTRLD_H +#include "gps_dl_osal.h" +#include "gps_dl_config.h" + +#define GPS_DL_OP_BUF_SIZE (16) + +enum gps_dl_ctrld_opid { + GPS_DL_OPID_LINK_EVENT_PROC, + GPS_DL_OPID_HAL_EVENT_PROC, + GPS_DL_OPID_MAX +}; + +struct gps_dl_ctrld_context { + struct gps_dl_osal_event rgpsdlWq; /* rename */ + struct gps_dl_osal_lxop_q rOpQ; /* active op queue */ + struct gps_dl_osal_lxop_q rFreeOpQ; /* free op queue */ + struct gps_dl_osal_lxop arQue[GPS_DL_OP_BUF_SIZE]; /* real op instances */ + struct gps_dl_osal_thread thread; +}; + +typedef int(*GPS_DL_OPID_FUNC) (struct gps_dl_osal_op_dat *); + +unsigned int gps_dl_wait_event_checker(struct gps_dl_osal_thread *pThread); +int gps_dl_put_act_op(struct gps_dl_osal_lxop *pOp); +struct gps_dl_osal_lxop *gps_dl_get_free_op(void); +int gps_dl_put_op_to_free_queue(struct gps_dl_osal_lxop *pOp); +int gps_dl_ctrld_init(void); +int gps_dl_ctrld_deinit(void); + +#endif /* _GPS_DL_CTRLD_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_emi.h b/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_emi.h new file mode 100644 index 0000000000000..0ff6f65c07c0c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_emi.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#ifndef _GPS_GPS_DL_EMI_H +#define _GPS_GPS_DL_EMI_H + +#include "gps_dl_config.h" + +#if GPS_DL_HAS_PLAT_DRV +#define GPS_ICAP_BUF_SIZE 0x50000 /* 320KB */ + +void gps_icap_probe(void); +#endif + +#endif /* _GPS_GPS_DL_EMI_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_linux.h b/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_linux.h new file mode 100644 index 0000000000000..8a1948bf04e15 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_linux.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _GPS_DL_LINUX_H +#define _GPS_DL_LINUX_H + +#include "gps_dl_config.h" + +#include +#include + +#if (GPS_DL_USE_MTK_SYNC_WRITE) +#include +#define gps_dl_linux_sync_writel(v, a) mt_reg_sync_writel(v, a) +#else +/* Add mb after writel to make sure it takes effect before next operation */ +#define gps_dl_mb() mb() +#define gps_dl_linux_sync_writel(v, a) \ + do { \ + writel((v), (void __force __iomem *)((a))); \ + gps_dl_mb(); \ + } while (0) +#endif + +#include "gps_dl_isr.h" +#include "gps_each_link.h" + +/* put linux proprietary items here otherwise put into gps_dl_osal.h */ +irqreturn_t gps_dl_linux_irq_dispatcher(int irq, void *data); +int gps_dl_linux_irqs_register(struct gps_each_irq *p_irqs, int irq_num); +int gps_dl_linux_irqs_unregister(struct gps_each_irq *p_irqs, int irq_num); + +#endif /* _GPS_DL_LINUX_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_linux_plat_drv.h b/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_linux_plat_drv.h new file mode 100644 index 0000000000000..2b32e9ae71ece --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_linux_plat_drv.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _GPS_DL_LINUX_PLAT_DRV_H +#define _GPS_DL_LINUX_PLAT_DRV_H + +#include "gps_dl_config.h" + +#if GPS_DL_HAS_PLAT_DRV +#include +struct gps_dl_iomem_addr_map_entry { + void __iomem *host_virt_addr; + unsigned int host_phys_addr; + unsigned int length; +}; +#endif + +#if GPS_DL_HAS_PLAT_DRV +int gps_dl_linux_plat_drv_register(void); +int gps_dl_linux_plat_drv_unregister(void); +void __iomem *gps_dl_host_addr_to_virt(unsigned int host_addr); +void gps_dl_update_status_for_md_blanking(bool gps_is_on); +void gps_dl_tia_gps_ctrl(bool gps_is_on); +void gps_dl_lna_pin_ctrl(enum gps_dl_link_id_enum link_id, bool dsp_is_on, bool force_en); +void gps_dl_reserved_mem_show_info(void); +void gps_dl_wake_lock_init(void); +void gps_dl_wake_lock_deinit(void); +void gps_dl_wake_lock_hold(bool hold); +#endif + +#endif /* _GPS_DL_LINUX_PLAT_DRV_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_linux_reserved_mem.h b/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_linux_reserved_mem.h new file mode 100644 index 0000000000000..b1e6ec80e8578 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_linux_reserved_mem.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#ifndef _GPS_DL_LINUX_RESERVED_MEM_H +#define _GPS_DL_LINUX_RESERVED_MEM_H + +#include "gps_dl_config.h" + +#ifdef GPS_DL_HAS_PLAT_DRV +#include "gps_dl_dma_buf.h" + +extern phys_addr_t gGpsRsvMemPhyBase; +extern unsigned long long gGpsRsvMemSize; + +void gps_dl_reserved_mem_init(void); +void gps_dl_reserved_mem_deinit(void); +bool gps_dl_reserved_mem_is_ready(void); +void gps_dl_reserved_mem_get_range(unsigned int *p_min, unsigned int *p_max); +void gps_dl_reserved_mem_show_info(void); + +void gps_dl_reserved_mem_dma_buf_init(struct gps_dl_dma_buf *p_dma_buf, + enum gps_dl_link_id_enum link_id, enum gps_dl_dma_dir dir, unsigned int len); +void gps_dl_reserved_mem_dma_buf_deinit(struct gps_dl_dma_buf *p_dma_buf); +void *gps_dl_reserved_mem_icap_buf_get_vir_addr(void); +#endif + +#endif /* _GPS_DL_LINUX_RESERVED_MEM_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_osal.h b/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_osal.h new file mode 100644 index 0000000000000..72beb97b7194b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_osal.h @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _GPS_DL_OSAL_H +#define _GPS_DL_OSAL_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DBG_LOG_STR_SIZE 256 + +#define RB_LATEST(prb) ((prb)->write - 1) +#define RB_SIZE(prb) ((prb)->size) +#define RB_MASK(prb) (RB_SIZE(prb) - 1) +#define RB_COUNT(prb) ((prb)->write - (prb)->read) +#define RB_FULL(prb) (RB_COUNT(prb) >= RB_SIZE(prb)) +#define RB_EMPTY(prb) ((prb)->write == (prb)->read) + +#define RB_INIT(prb, qsize) \ +do { \ + (prb)->read = (prb)->write = 0; \ + (prb)->size = (qsize); \ +} while (0) + +#define RB_PUT(prb, value) \ +do { \ + if (!RB_FULL(prb)) { \ + (prb)->queue[(prb)->write & RB_MASK(prb)] = value; \ + ++((prb)->write); \ + } \ + else { \ + gps_dl_osal_assert(!RB_FULL(prb)); \ + } \ +} while (0) + +#define RB_GET(prb, value) \ +do { \ + if (!RB_EMPTY(prb)) { \ + value = (prb)->queue[(prb)->read & RB_MASK(prb)]; \ + ++((prb)->read); \ + if (RB_EMPTY(prb)) { \ + (prb)->read = (prb)->write = 0; \ + } \ + } \ + else { \ + value = NULL; \ + gps_dl_osal_assert(!RB_EMPTY(prb)); \ + } \ +} while (0) + +#define RB_GET_LATEST(prb, value) \ +do { \ + if (!RB_EMPTY(prb)) { \ + value = (prb)->queue[RB_LATEST(prb) & RB_MASK(prb)]; \ + if (RB_EMPTY(prb)) { \ + (prb)->read = (prb)->write = 0; \ + } \ + } \ + else { \ + value = NULL; \ + } \ +} while (0) + +#define MAX_THREAD_NAME_LEN 128 +#define OSAL_OP_DATA_SIZE 32 +#define OSAL_OP_BUF_SIZE 16 + +typedef void(*P_TIMEOUT_HANDLER) (unsigned long); +typedef int(*P_COND) (void *); + +struct gps_dl_osal_timer { + struct timer_list timer; + P_TIMEOUT_HANDLER timeoutHandler; + unsigned long timeroutHandlerData; +}; + +struct gps_dl_osal_unsleepable_lock { + spinlock_t lock; + unsigned long flag; +}; + +struct gps_dl_osal_sleepable_lock { + struct mutex lock; +}; + +struct gps_dl_osal_signal { + struct completion comp; + unsigned int timeoutValue; + unsigned int timeoutExtension; /* max number of timeout caused by thread not able to acquire CPU */ +}; + +struct gps_dl_osal_event { + wait_queue_head_t waitQueue; + unsigned int timeoutValue; + int waitFlag; +}; + +struct gps_dl_osal_op_dat { + unsigned int opId; /* Event ID */ + unsigned int u4InfoBit; /* Reserved */ + unsigned long au4OpData[OSAL_OP_DATA_SIZE]; /* OP Data */ +}; + +struct gps_dl_osal_lxop { + struct gps_dl_osal_op_dat op; + struct gps_dl_osal_signal signal; + int result; + atomic_t ref_count; +}; + +struct gps_dl_osal_lxop_q { + struct gps_dl_osal_sleepable_lock sLock; + unsigned int write; + unsigned int read; + unsigned int size; + struct gps_dl_osal_lxop *queue[OSAL_OP_BUF_SIZE]; +}; + +struct gps_dl_osal_thread { + struct task_struct *pThread; + void *pThreadFunc; + void *pThreadData; + char threadName[MAX_THREAD_NAME_LEN]; +}; + +typedef unsigned int(*OSAL_EVENT_CHECKER) (struct gps_dl_osal_thread *pThread); + +char *gps_dl_osal_strncpy(char *dst, const char *src, unsigned int len); +char *gps_dl_osal_strsep(char **str, const char *c); +int gps_dl_osal_strtol(const char *str, unsigned int adecimal, long *res); +void *gps_dl_osal_memset(void *buf, int i, unsigned int len); +int gps_dl_osal_thread_create(struct gps_dl_osal_thread *pThread); +int gps_dl_osal_thread_run(struct gps_dl_osal_thread *pThread); +int gps_dl_osal_thread_stop(struct gps_dl_osal_thread *pThread); +int gps_dl_osal_thread_should_stop(struct gps_dl_osal_thread *pThread); +int gps_dl_osal_thread_destroy(struct gps_dl_osal_thread *pThread); +int gps_dl_osal_thread_wait_for_event(struct gps_dl_osal_thread *pThread, + struct gps_dl_osal_event *pEvent, OSAL_EVENT_CHECKER pChecker); +int gps_dl_osal_signal_init(struct gps_dl_osal_signal *pSignal); +int gps_dl_osal_wait_for_signal(struct gps_dl_osal_signal *pSignal); +int gps_dl_osal_wait_for_signal_timeout(struct gps_dl_osal_signal *pSignal, struct gps_dl_osal_thread *pThread); +int gps_dl_osal_raise_signal(struct gps_dl_osal_signal *pSignal); +int gps_dl_osal_signal_active_state(struct gps_dl_osal_signal *pSignal); +int gps_dl_osal_op_is_wait_for_signal(struct gps_dl_osal_lxop *pOp); +void gps_dl_osal_op_raise_signal(struct gps_dl_osal_lxop *pOp, int result); +int gps_dl_osal_signal_deinit(struct gps_dl_osal_signal *pSignal); +int gps_dl_osal_event_init(struct gps_dl_osal_event *pEvent); +int gps_dl_osal_trigger_event(struct gps_dl_osal_event *pEvent); +int gps_dl_osal_wait_for_event(struct gps_dl_osal_event *pEvent, int (*condition)(void *), void *cond_pa); +int gps_dl_osal_wait_for_event_timeout(struct gps_dl_osal_event *pEvent, int (*condition)(void *), void *cond_pa); +int gps_dl_osal_event_deinit(struct gps_dl_osal_event *pEvent); +int gps_dl_osal_sleepable_lock_init(struct gps_dl_osal_sleepable_lock *pSL); +int gps_dl_osal_lock_sleepable_lock(struct gps_dl_osal_sleepable_lock *pSL); +int gps_dl_osal_unlock_sleepable_lock(struct gps_dl_osal_sleepable_lock *pSL); +int gps_dl_osal_trylock_sleepable_lock(struct gps_dl_osal_sleepable_lock *pSL); +int gps_dl_osal_sleepable_lock_deinit(struct gps_dl_osal_sleepable_lock *pSL); +int gps_dl_osal_unsleepable_lock_init(struct gps_dl_osal_unsleepable_lock *pUSL); +int gps_dl_osal_lock_unsleepable_lock(struct gps_dl_osal_unsleepable_lock *pUSL); +int gps_dl_osal_unlock_unsleepable_lock(struct gps_dl_osal_unsleepable_lock *pUSL); + +#define gps_dl_osal_assert(condition) \ +do { \ + if (!(condition)) { \ + GDL_LOGE("ASSERT: (%s)", #condition); \ + } \ +} while (0) + +#endif /* _GPS_DL_OSAL_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_procfs.h b/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_procfs.h new file mode 100644 index 0000000000000..ce604f4eec298 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_dl_procfs.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _GPS_DL_PROCFS_H +#define _GPS_DL_PROCFS_H + +int gps_dl_procfs_setup(void); +int gps_dl_procfs_remove(void); + +typedef int(*gps_dl_procfs_test_func_type)(int y, int z); + +#endif /* _GPS_DL_PROCFS_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_each_device.h b/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_each_device.h new file mode 100644 index 0000000000000..d6c60d4e4f792 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/data_link/linux/inc/gps_each_device.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _GPS_EACH_DEVICE_H +#define _GPS_EACH_DEVICE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gps_each_link.h" +#include "gps_dl_dma_buf.h" + +#define GPS_DATA_PATH_BUF_MAX 2048 + +/* Todo: should not use this const, currently it's a work-around */ +#define GPS_LIBMNL_READ_MAX 512 + +struct gps_each_device_cfg { + char *dev_name; + int index; +}; + +struct gps_each_device { + struct gps_each_device_cfg cfg; + struct gps_each_link *p_link; + int index; + dev_t devno; + struct class *cls; + struct device *dev; + struct cdev cdev; + bool is_open; + unsigned char i_buf[GPS_DATA_PATH_BUF_MAX]; + unsigned char o_buf[GPS_DATA_PATH_BUF_MAX]; + unsigned int i_len; + wait_queue_head_t r_wq; + void *private_data; +}; + +int gps_dl_cdev_setup(struct gps_each_device *dev, int index); +void gps_dl_cdev_cleanup(struct gps_each_device *dev, int index); +struct gps_each_device *gps_dl_device_get(enum gps_dl_link_id_enum link_id); + +void gps_each_device_data_submit(unsigned char *buf, unsigned int len, int index); + +void gps_dl_device_context_init(void); +void gps_dl_device_context_deinit(void); + +#endif /* _GPS_EACH_DEVICE_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/fw_log_gps.c b/drivers/misc/mediatek/connectivity/gps/fw_log_gps.c new file mode 100644 index 0000000000000..e5320fa9b7f13 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/fw_log_gps.c @@ -0,0 +1,259 @@ +/* + * Implementation of the GPS EMI driver. + * + * Copyright (C) 2014 Mediatek + * Authors: + * Heiping + * + * 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 +*******************************************************************************/ +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) +#include +#else +#include +#endif +#include +#include "gps.h" +#include "connsys_debug_utility.h" +#ifdef pr_fmt +#undef pr_fmt +#endif +#define pr_fmt(fmt) "["KBUILD_MODNAME"]" fmt + +/****************************************************************************** + * Definition +******************************************************************************/ +/* device name and major number */ +#define GPSFWLOG_DEVNAME "fw_log_gps" +#define GPS_FW_LOG_IOC_MAGIC (0xfc) +#define GPS_FW_LOG_IOCTL_ON_OFF _IOW(GPS_FW_LOG_IOC_MAGIC, 0, int) +#define GPS_FW_LOG_IOCTL_SET_LEVEL _IOW(GPS_FW_LOG_IOC_MAGIC, 1, int) +#define GPS_FW_LOG_IOCTL_GET_LEVEL _IOW(GPS_FW_LOG_IOC_MAGIC, 2, int) + +/******************************************************************************* +* structure & enumeration +*******************************************************************************/ +/*---------------------------------------------------------------------------*/ +struct gps_fw_log_dev { + struct class *cls; + struct device *dev; + dev_t devno; + struct cdev chdev; +}; +/* typedef unsigned char UINT8, *PUINT8, **PPUINT8; */ + +/****************************************************************************** + * local variables +******************************************************************************/ +/* static int flag; */ +struct gps_fw_log_dev *logdevobj; +static wait_queue_head_t GPS_log_wq; +bool fgGps_fw_log_ON; + +/*---------------------------------------------------------------------------*/ +static void log_event_cb(void); + +long fw_log_gps_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + long retval = 0; + + switch (cmd) { + case GPS_FW_LOG_IOCTL_ON_OFF: + pr_info("gps PS_FW_LOG_IOCTL_ON_OFF(%lu)\n", arg); + GPS_fwlog_ctrl((bool)arg); + break; + + case GPS_FW_LOG_IOCTL_SET_LEVEL: + pr_info("gps GPS_FW_LOG_IOCTL_SET_LEVEL\n"); + break; + case GPS_FW_LOG_IOCTL_GET_LEVEL: + pr_info("gps GPS_FW_LOG_IOCTL_GET_LEVEL\n"); + break; + + default: + pr_warn("gps unknown cmd (%d)\n", cmd); + break; + } + return retval; +} + +long fw_log_gps_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + return fw_log_gps_unlocked_ioctl(filp, cmd, arg); +} + +/******************************************************************************/ +/*****************************************************************************/ +static int fw_log_open(struct inode *inode, struct file *file) +{ + pr_info("%s: gps major %d minor %d (pid %d)\n", __func__, imajor(inode), iminor(inode), current->pid); + return 0; +} + +/*****************************************************************************/ + + +/*****************************************************************************/ +static int fw_log_close(struct inode *inode, struct file *file) +{ + pr_info("%s: gps major %d minor %d (pid %d)\n", __func__, imajor(inode), iminor(inode), current->pid); + return 0; +} + +/******************************************************************************/ +static ssize_t fw_log_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) +{ + int retval; + + #if 0 + pr_info("GPS fw_log_read,len=%d\n", count); + #endif + + retval = connsys_log_read_to_user(CONNLOG_TYPE_GPS, buf, count); + return retval; +} +/******************************************************************************/ +static unsigned int fw_log_poll(struct file *file, poll_table *wait) +{ + unsigned int mask = 0; + + poll_wait(file, &GPS_log_wq, wait); + if (connsys_log_get_buf_size(CONNLOG_TYPE_GPS) > 0) + mask = (POLLIN | POLLRDNORM); + + return mask; +} + +/*****************************************************************************/ +/* Kernel interface */ +static const struct file_operations gps_fw_log_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = fw_log_gps_unlocked_ioctl, + .compat_ioctl = fw_log_gps_compat_ioctl, + .open = fw_log_open, + .read = fw_log_read, + .release = fw_log_close, + .poll = fw_log_poll, +}; + +void log_event_cb(void) +{ + wake_up_interruptible(&GPS_log_wq); +} + +static int __init gps_fw_log_init(void) +{ + int ret = 0; + int err = 0; + + logdevobj = kzalloc(sizeof(*logdevobj), GFP_KERNEL); + if (logdevobj == NULL) { + err = -ENOMEM; + ret = -ENOMEM; + goto err_out; + } + + pr_info("Registering chardev\n"); + ret = alloc_chrdev_region(&logdevobj->devno, 0, 1, GPSFWLOG_DEVNAME); + if (ret) { + pr_err("alloc_chrdev_region fail: %d\n", ret); + err = -ENOMEM; + goto err_out; + } else { + pr_info("major: %d, minor: %d\n", MAJOR(logdevobj->devno), MINOR(logdevobj->devno)); + } + cdev_init(&logdevobj->chdev, &gps_fw_log_fops); + logdevobj->chdev.owner = THIS_MODULE; + err = cdev_add(&logdevobj->chdev, logdevobj->devno, 1); + if (err) { + pr_err("cdev_add fail: %d\n", err); + goto err_out; + } + logdevobj->cls = class_create(THIS_MODULE, "gpsfwlog"); + if (IS_ERR(logdevobj->cls)) { + pr_err("Unable to create class, err = %d\n", (int)PTR_ERR(logdevobj->cls)); + goto err_out; + } + logdevobj->dev = device_create(logdevobj->cls, NULL, logdevobj->devno, logdevobj, "fw_log_gps"); + + connsys_log_init(CONNLOG_TYPE_GPS); + init_waitqueue_head(&GPS_log_wq); + connsys_log_register_event_cb(CONNLOG_TYPE_GPS, log_event_cb); + + pr_info("GPS FW LOG device init Done\n"); + return 0; + +err_out: + if (logdevobj != NULL) { + if (err == 0) + cdev_del(&logdevobj->chdev); + if (ret == 0) + unregister_chrdev_region(logdevobj->devno, 1); + kfree(logdevobj); + logdevobj = NULL; + } + return -1; +} + +/*****************************************************************************/ +static void __exit gps_fw_log_exit(void) +{ + if (!logdevobj) { + pr_err("null pointer: %p\n", logdevobj); + return; + } + + pr_info("Unregistering chardev\n"); + connsys_log_deinit(CONNLOG_TYPE_GPS); + cdev_del(&logdevobj->chdev); + unregister_chrdev_region(logdevobj->devno, 1); + device_destroy(logdevobj->cls, logdevobj->devno); + class_destroy(logdevobj->cls); + kfree(logdevobj); + logdevobj = NULL; + pr_info("Done\n"); +} + +int mtk_gps_fw_log_init(void) +{ + pr_info("gps fw log init begin"); + return gps_fw_log_init(); +} + +void mtk_gps_fw_log_exit(void) +{ + pr_info("gps fw log exit begin"); + return gps_fw_log_exit(); +} + +/*****************************************************************************/ +#if 0 +module_init(gps_emi_mod_init); +module_exit(gps_emi_mod_exit); +#endif +/*****************************************************************************/ +MODULE_AUTHOR("Chaoran Zhang "); +MODULE_DESCRIPTION("GPS FW log driver"); +MODULE_LICENSE("GPL"); +#endif diff --git a/drivers/misc/mediatek/connectivity/gps/gps.h b/drivers/misc/mediatek/connectivity/gps/gps.h new file mode 100644 index 0000000000000..83300c8251bcc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/gps.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * brief Declaration of library functions + * Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. + */ + +#ifndef _GPS_H_ +#define _GPS_H_ + +#include "wmt_core.h" +#include "wmt_dev.h" +#include "osal.h" +#include "mtk_wcn_consys_hw.h" + +#if defined(CONFIG_MACH_MT6765) || defined(CONFIG_MACH_MT6761) || defined(CONFIG_MACH_MT6779) \ +|| defined(CONFIG_MACH_MT6768) || defined(CONFIG_MACH_MT6785) || defined(CONFIG_MACH_MT6873) \ +|| defined(CONFIG_MACH_MT6853) || defined(CONFIG_MACH_MT6833) +#define GPS_FWCTL_SUPPORT +#endif + +#ifdef GPS_FWCTL_SUPPORT +/* Disable: #define GPS_FWCTL_IOCTL_SUPPORT */ + +#define GPS_HW_SUSPEND_SUPPORT +#endif /* GPS_FWCTL_SUPPORT */ + +enum gps_ctrl_status_enum { + GPS_CLOSED, + GPS_OPENED, + GPS_SUSPENDED, + GPS_RESET_START, + GPS_RESET_DONE, + GPS_CTRL_STATUS_NUM +}; + +enum gps_reference_count_cmd { + FWLOG_CTRL_INNER = 0, + HANDLE_DESENSE, + FGGPS_FWCTL_EADY, +}; + +#ifdef GPS_FWCTL_SUPPORT +#define GPS_FWCTL_OPCODE_ENTER_SLEEP_MODE (2) +#define GPS_FWCTL_OPCODE_EXIT_SLEEP_MODE (3) +#define GPS_FWCTL_OPCODE_ENTER_STOP_MODE (4) +#define GPS_FWCTL_OPCODE_EXIT_STOP_MODE (5) +#define GPS_FWCTL_OPCODE_LOG_CFG (6) +#define GPS_FWCTL_OPCODE_LOOPBACK_TEST (7) +#define GPS2_FWCTL_OPCODE_ENTER_STOP_MODE (8) +#define GPS2_FWCTL_OPCODE_EXIT_STOP_MODE (9) + +#endif + +#define GPS_USER1 0 +#define GPS_USER2 1 + + +extern void GPS_reference_count(enum gps_reference_count_cmd cmd, bool flag, int user); + +extern phys_addr_t gConEmiPhyBase; + +extern int mtk_wcn_stpgps_drv_init(void); +extern void mtk_wcn_stpgps_drv_exit(void); +#ifdef CONFIG_MTK_GPS_EMI +extern int mtk_gps_emi_init(void); +extern void mtk_gps_emi_exit(void); +#endif +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH +extern int mtk_gps_fw_log_init(void); +extern void mtk_gps_fw_log_exit(void); +void GPS_fwlog_ctrl(bool on); +#endif + +#ifdef CONFIG_GPSL5_SUPPORT +/* stp_chrdev_gps2 */ +extern struct wakeup_source gps2_wake_lock; +extern struct semaphore wr_mtx2, rd_mtx2, status_mtx2; +extern const struct file_operations GPS2_fops; +#endif + +extern struct semaphore fwctl_mtx; + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH +extern bool fgGps_fwlog_on; +#endif + +#ifdef GPS_FWCTL_SUPPORT +extern bool fgGps_fwctl_ready; +#endif + +#endif diff --git a/drivers/misc/mediatek/connectivity/gps/gps_dl_module.c b/drivers/misc/mediatek/connectivity/gps/gps_dl_module.c new file mode 100644 index 0000000000000..df5152d9aca68 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/gps_dl_module.c @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include +#include + +#include "gps_dl_config.h" + +#if GPS_DL_IS_MODULE +#include "gps_data_link_devices.h" + +/*****************************************************************************/ +static int gps_dl_mod_init(void) +{ + int ret = 0; + + mtk_gps_data_link_devices_init(); + + return ret; +} + +/*****************************************************************************/ +static void gps_dl_mod_exit(void) +{ + mtk_gps_data_link_devices_exit(); +} + +#ifdef MTK_WCN_REMOVE_KERNEL_MODULE +int mtk_wcn_gpsdl_drv_init(void) +{ + return gps_dl_mod_init(); +} +EXPORT_SYMBOL(mtk_wcn_gpsdl_drv_init); + +void mtk_wcn_gpsdl_drv_exit(void) +{ + return gps_dl_mod_exit(); +} +EXPORT_SYMBOL(mtk_wcn_gpsdl_drv_exit); + +#else +module_init(gps_dl_mod_init); +module_exit(gps_dl_mod_exit); + +#endif + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Hua Fu"); +#endif + diff --git a/drivers/misc/mediatek/connectivity/gps/gps_emi.c b/drivers/misc/mediatek/connectivity/gps/gps_emi.c new file mode 100644 index 0000000000000..44923c30aa592 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/gps_emi.c @@ -0,0 +1,507 @@ +/* + * Implementation of the GPS EMI driver. + * + * Copyright (C) 2014 Mediatek + * Authors: + * Heiping + * + * 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 +*******************************************************************************/ +#ifdef CONFIG_MTK_GPS_EMI +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gps.h" + +#ifdef pr_fmt +#undef pr_fmt +#endif +#define pr_fmt(fmt) "["KBUILD_MODNAME"]" fmt + +/****************************************************************************** + * Definition +******************************************************************************/ +/* device name and major number */ +#define GPSEMI_DEVNAME "gps_emi" +#define IOCTL_EMI_MEMORY_INIT 1 +#define IOCTL_MNL_NVRAM_FILE_TO_MEM 2 +#define IOCTL_MNL_NVRAM_MEM_TO_FILE 3 +#define IOCTL_ADC_CAPTURE_ADDR_GET 4 + +#if defined(CONFIG_MACH_MT6765) || defined(CONFIG_MACH_MT6761) || defined(CONFIG_MACH_MT6768) +#define GPS_EMI_MPU_REGION 29 +#define GPS_EMI_BASE_ADDR_OFFSET (2*SZ_1M + SZ_1M/2 + 0x1000) +#define GPS_EMI_MPU_SIZE (SZ_1M + SZ_1M/2 - 0x2000) +#define EMI_MPU_PROTECTION_IS_READY 1 +#if EMI_MPU_PROTECTION_IS_READY +#include +#endif +#endif +#if defined(CONFIG_MACH_MT6779) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)) +#define GPS_EMI_MPU_REGION 29 +#define GPS_EMI_BASE_ADDR_OFFSET (3*SZ_1M + 0x10000) +#define GPS_EMI_MPU_SIZE (0xF0000) +#define EMI_MPU_PROTECTION_IS_READY 1 +#if EMI_MPU_PROTECTION_IS_READY +#include +#endif +#endif +#if defined(CONFIG_MACH_MT6771) || defined(CONFIG_MACH_MT6775) || defined(CONFIG_MACH_MT6758) +#define GPS_EMI_MPU_REGION 30 +#define GPS_EMI_BASE_ADDR_OFFSET (SZ_1M) +#define GPS_EMI_MPU_SIZE (SZ_1M) +#define EMI_MPU_PROTECTION_IS_READY 1 +#if EMI_MPU_PROTECTION_IS_READY +#include +#endif +#endif +#if defined(CONFIG_MACH_MT6873) || defined(CONFIG_MACH_MT6853) || defined(CONFIG_MACH_MT6893) +#define GPS_EMI_NEW_API +#define GPS_EMI_MPU_REGION 29 +#define GPS_EMI_BASE_ADDR_OFFSET (3*SZ_1M + 0x10000) +#define GPS_EMI_MPU_SIZE (0xF0000) +#define GPS_DL_EMI_MPU_DOMAIN_AP 0 +#define GPS_DL_EMI_MPU_DOMAIN_CONN 2 +#define EMI_MPU_PROTECTION_IS_READY 1 +#if EMI_MPU_PROTECTION_IS_READY +#include +#endif +#endif +#if defined(CONFIG_MACH_MT6833) +#define GPS_EMI_NEW_API +#define GPS_EMI_MPU_REGION 29 +#define GPS_EMI_BASE_ADDR_OFFSET (4*SZ_1M) +#define GPS_EMI_MPU_SIZE (0xFFFFF) +#define GPS_DL_EMI_MPU_DOMAIN_AP 0 +#define GPS_DL_EMI_MPU_DOMAIN_CONN 2 +#define EMI_MPU_PROTECTION_IS_READY 0 +#if EMI_MPU_PROTECTION_IS_READY +#include +#endif +#endif +#if defined(CONFIG_MACH_MT6779) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) +#define GPS_EMI_NEW_API +#define GPS_EMI_MPU_REGION 29 +#define GPS_EMI_BASE_ADDR_OFFSET (3*SZ_1M + 0x10000) +#define GPS_EMI_MPU_SIZE (0xF0000) +#define GPS_DL_EMI_MPU_DOMAIN_AP 0 +#define GPS_DL_EMI_MPU_DOMAIN_CONN 2 +#define EMI_MPU_PROTECTION_IS_READY 1 +#if EMI_MPU_PROTECTION_IS_READY +#include +#endif +#endif + +#define GPS_ADC_CAPTURE_BUFF_SIZE 0x50000 +/****************************************************************************** + * Debug configuration +******************************************************************************/ +#define GPS_DBG_NONE(fmt, arg...) do {} while (0) +#define GPS_DBG pr_err +#define GPS_TRC GPS_DBG_NONE +#define GPS_VER pr_err +#define GPS_ERR pr_err +/******************************************************************************* +* structure & enumeration +*******************************************************************************/ +/*---------------------------------------------------------------------------*/ +struct gps_emi_dev { + struct class *cls; + struct device *dev; + dev_t devno; + struct cdev chdev; +}; +/* typedef unsigned char UINT8, *PUINT8, **PPUINT8; */ + +/****************************************************************************** + * local variables +******************************************************************************/ +phys_addr_t gGpsEmiPhyBase; +void __iomem *pGpsEmibaseaddr; +struct gps_emi_dev *devobj; + +static struct semaphore fw_dl_mtx; + +void mtk_wcn_consys_gps_memory_reserve(void) +{ +#if 0 +#ifdef MTK_WCN_ARM64 + gGpsEmiPhyBase = arm64_memblock_steal(SZ_1M, SZ_1M); +#else + gGpsEmiPhyBase = arm_memblock_steal(SZ_1M, SZ_1M); +#endif +#else + #if EMI_MPU_PROTECTION_IS_READY + gGpsEmiPhyBase = gConEmiPhyBase + GPS_EMI_BASE_ADDR_OFFSET; + #endif +#endif + if (gGpsEmiPhyBase) + GPS_DBG("Con:0x%zx, Gps:0x%zx\n", (size_t)gConEmiPhyBase, (size_t)gGpsEmiPhyBase); + else + GPS_DBG("memblock fail\n"); +} + +INT32 gps_emi_mpu_set_region_protection(INT32 region) +{ +#if EMI_MPU_PROTECTION_IS_READY +#if defined(GPS_EMI_NEW_API) + struct emimpu_region_t region_info; + int emimpu_ret1, emimpu_ret2, emimpu_ret3, emimpu_ret4, emimpu_ret5, emimpu_ret6; + /* Set EMI MPU permission */ + GPS_DBG("emi mpu cfg: region = %d, no protection domain = %d, %d", + region, GPS_DL_EMI_MPU_DOMAIN_AP, GPS_DL_EMI_MPU_DOMAIN_CONN); + emimpu_ret1 = mtk_emimpu_init_region(®ion_info, region); + emimpu_ret2 = mtk_emimpu_set_addr(®ion_info, gGpsEmiPhyBase, gGpsEmiPhyBase + GPS_EMI_MPU_SIZE - 1); + emimpu_ret3 = mtk_emimpu_set_apc(®ion_info, GPS_DL_EMI_MPU_DOMAIN_AP, MTK_EMIMPU_NO_PROTECTION); + emimpu_ret4 = mtk_emimpu_set_apc(®ion_info, GPS_DL_EMI_MPU_DOMAIN_CONN, MTK_EMIMPU_NO_PROTECTION); + emimpu_ret5 = mtk_emimpu_set_protection(®ion_info); + emimpu_ret6 = mtk_emimpu_free_region(®ion_info); + GPS_DBG("emi mpu cfg: ret = %d, %d, %d, %d, %d, %d", + emimpu_ret1, emimpu_ret2, emimpu_ret3, emimpu_ret4, emimpu_ret5, emimpu_ret6); +#else + struct emi_region_info_t region_info; + /*set MPU for EMI share Memory */ + GPS_DBG("setting MPU for EMI share memory\n"); + region_info.start = gGpsEmiPhyBase; + region_info.end = gGpsEmiPhyBase + GPS_EMI_MPU_SIZE - 1; + region_info.region = region; + SET_ACCESS_PERMISSION(region_info.apc, LOCK, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + NO_PROTECTION, FORBIDDEN, NO_PROTECTION); + emi_mpu_set_protection(®ion_info); +#endif +#endif + return 0; +} + +INT32 gps_emi_patch_get(PUINT8 pPatchName, osal_firmware **ppPatch) +{ + INT32 iRet; + osal_firmware *fw; + + iRet = -1; + fw = NULL; + if (!ppPatch) { + GPS_DBG("invalid ppBufptr!\n"); + return -1; + } + *ppPatch = NULL; + iRet = request_firmware((const struct firmware **)&fw, pPatchName, NULL); + if (iRet != 0) { + GPS_DBG("failed to open or read!(%s)\n", pPatchName); + release_firmware(fw); + return -1; + } + GPS_DBG("loader firmware %s ok!!\n", pPatchName); + iRet = 0; + *ppPatch = fw; + + return iRet; +} + +INT32 mtk_wcn_consys_gps_emi_init(void) +{ + INT32 iRet; + + iRet = -1; + down(&fw_dl_mtx); + mtk_wcn_consys_gps_memory_reserve(); + if (gGpsEmiPhyBase) { + /*set MPU for EMI share Memory*/ + #if EMI_MPU_PROTECTION_IS_READY + GPS_DBG("setting MPU for EMI share memory\n"); + gps_emi_mpu_set_region_protection(GPS_EMI_MPU_REGION); + #endif + GPS_DBG("get consys start phy address(0x%zx)\n", (size_t)gGpsEmiPhyBase); + #if 0 + /*consys to ap emi remapping register:10001310, cal remapping address*/ + addrPhy = (gGpsEmiPhyBase & 0xFFF00000) >> 20; + + /*enable consys to ap emi remapping bit12*/ + addrPhy -= 0x400;/*Gavin ??*/ + addrPhy = addrPhy | 0x1000; + + CONSYS_REG_WRITE(conn_reg.topckgen_base + CONSYS_EMI_MAPPING_OFFSET, + CONSYS_REG_READ(conn_reg.topckgen_base + CONSYS_EMI_MAPPING_OFFSET) | addrPhy); + + GPS_DBG("GPS_EMI_MAPPING dump(0x%08x)\n", + CONSYS_REG_READ(conn_reg.topckgen_base + CONSYS_EMI_MAPPING_OFFSET)); + #endif + #if EMI_MPU_PROTECTION_IS_READY + pGpsEmibaseaddr = ioremap_nocache(gGpsEmiPhyBase, GPS_EMI_MPU_SIZE); + #endif + iRet = 1; + #if 0 + if (pGpsEmibaseaddr != NULL) { + unsigned char *pFullPatchName = "MNL.bin"; + osal_firmware *pPatch = NULL; + + GPS_DBG("EMI mapping OK(0x%p)\n", pGpsEmibaseaddr); + memset_io(pGpsEmibaseaddr, 0, GPS_EMI_MPU_SIZE); + if ((pFullPatchName != NULL) + && (gps_emi_patch_get(pFullPatchName, &pPatch) == 0)) { + if (pPatch != NULL) { + /*get full name patch success*/ + GPS_DBG("get full patch name(%s) buf(0x%p) size(%ld)\n", + pFullPatchName, (pPatch)->data, (pPatch)->size); + GPS_DBG("AF get patch, pPatch(0x%p)\n", pPatch); + } + } + if (pPatch != NULL) { + if ((pPatch)->size <= GPS_EMI_MPU_SIZE) { + GPS_DBG("Prepare to copy FW\n"); + memcpy(pGpsEmibaseaddr, (pPatch)->data, (pPatch)->size); + iRet = 1; + GPS_DBG("pGpsEmibaseaddr_1:0x%08x 0x%08x 0x%08x 0x%08x\n", + *(unsigned int *)pGpsEmibaseaddr, + *(((unsigned int *)pGpsEmibaseaddr)+1), + *(((unsigned int *)pGpsEmibaseaddr)+2), + *(((unsigned int *)pGpsEmibaseaddr)+3)); + GPS_DBG("pGpsEmibaseaddr_2:0x%08x 0x%08x 0x%08x 0x%08x\n", + *(((unsigned int *)pGpsEmibaseaddr)+4), + *(((unsigned int *)pGpsEmibaseaddr)+5), + *(((unsigned int *)pGpsEmibaseaddr)+6), + *(((unsigned int *)pGpsEmibaseaddr)+7)); + } + release_firmware(pPatch); + pPatch = NULL; + } + iounmap(pGpsEmibaseaddr); + } else { + GPS_DBG("EMI mapping fail\n"); + } + #endif + } else { + GPS_DBG("gps emi memory address gGpsEmiPhyBase invalid\n"); + } + up(&fw_dl_mtx); + return iRet; +} + +/*---------------------------------------------------------------------------*/ +long gps_emi_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int retval; + unsigned int *tmp; + + retval = 0; + GPS_DBG("gps_emi:cmd (%d),arg(%ld)\n", cmd, arg); + + switch (cmd) { + case IOCTL_EMI_MEMORY_INIT: + retval = mtk_wcn_consys_gps_emi_init(); + GPS_DBG("IOCTL_EMI_MEMORY_INIT\n"); + break; + + case IOCTL_MNL_NVRAM_FILE_TO_MEM: + GPS_DBG("IOCTL_MNL_NVRAM_FILE_TO_MEM\n"); + break; + + case IOCTL_MNL_NVRAM_MEM_TO_FILE: + GPS_DBG("IOCTL_MNL_NVRAM_MEM_TO_FILE\n"); + break; + + case IOCTL_ADC_CAPTURE_ADDR_GET: + tmp = (unsigned int *)&gGpsEmiPhyBase; + GPS_DBG("gps_emi:gGpsEmiPhyBase (%x)\n", &gGpsEmiPhyBase); + GPS_DBG("gps_emi:tmp (%x)\n", tmp); + if (copy_to_user((unsigned int __user *)arg, tmp, sizeof(unsigned int))) + retval = -1; + GPS_DBG("IOCTL_ADC_CAPTURE_ADDR_GET,(%d)\n", retval); + break; + + default: + GPS_DBG("unknown cmd (%d)\n", cmd); + retval = 0; + break; + } + return retval; + +} + +/******************************************************************************/ +long gps_emi_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + return gps_emi_unlocked_ioctl(filp, cmd, arg); +} + +/*****************************************************************************/ +static int gps_emi_open(struct inode *inode, struct file *file) +{ + GPS_TRC(); + return nonseekable_open(inode, file); +} + +/*****************************************************************************/ + + +/*****************************************************************************/ +static int gps_emi_release(struct inode *inode, struct file *file) +{ + GPS_TRC(); + + return 0; +} + +/******************************************************************************/ +static ssize_t gps_emi_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) +{ + ssize_t ret; + + ret = 0; + GPS_DBG("gps_emi_read begin\n"); + if (count > GPS_ADC_CAPTURE_BUFF_SIZE) + count = GPS_ADC_CAPTURE_BUFF_SIZE; + if (pGpsEmibaseaddr != NULL) { + if (copy_to_user(buf, (char *)pGpsEmibaseaddr, count)) + pr_err("Copy to user failed\n"); + } + GPS_DBG("gps_emi_read finish\n"); + return ret; +} +/******************************************************************************/ +static ssize_t gps_emi_write(struct file *file, const char __user *buf, size_t count, + loff_t *ppos) +{ + ssize_t ret = 0; + + GPS_TRC(); + + return ret; +} + + +/*****************************************************************************/ +/* Kernel interface */ +static const struct file_operations gps_emi_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = gps_emi_unlocked_ioctl, + .compat_ioctl = gps_emi_compat_ioctl, + .open = gps_emi_open, + .read = gps_emi_read, + .write = gps_emi_write, + .release = gps_emi_release, +}; + +/*****************************************************************************/ +#ifdef CONFIG_OF +static const struct of_device_id apgps_of_ids[] = { + { .compatible = "mediatek,gps_emi-v1", }, + {} +}; +#endif +/*****************************************************************************/ +static int __init gps_emi_mod_init(void) +{ + int ret = 0; + int err = 0; + + GPS_ERR("gps emi mod register begin"); + + sema_init(&fw_dl_mtx, 1); + + devobj = kzalloc(sizeof(*devobj), GFP_KERNEL); + if (devobj == NULL) { + err = -ENOMEM; + ret = -ENOMEM; + goto err_out; + } + + GPS_ERR("Registering chardev\n"); + ret = alloc_chrdev_region(&devobj->devno, 0, 1, GPSEMI_DEVNAME); + if (ret) { + GPS_ERR("alloc_chrdev_region fail: %d\n", ret); + err = -ENOMEM; + goto err_out; + } else { + GPS_ERR("major: %d, minor: %d\n", MAJOR(devobj->devno), MINOR(devobj->devno)); + } + cdev_init(&devobj->chdev, &gps_emi_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 err_out; + } + devobj->cls = class_create(THIS_MODULE, "gpsemi"); + if (IS_ERR(devobj->cls)) { + GPS_ERR("Unable to create class, err = %d\n", (int)PTR_ERR(devobj->cls)); + goto err_out; + } + devobj->dev = device_create(devobj->cls, NULL, devobj->devno, devobj, "gps_emi"); + + + GPS_ERR("GPS EMI Done\n"); + return 0; + +err_out: + if (devobj != NULL) { + if (err == 0) + cdev_del(&devobj->chdev); + if (ret == 0) + unregister_chrdev_region(devobj->devno, 1); + + kfree(devobj); + devobj = NULL; + } + return -1; +} + +/*****************************************************************************/ +static void __exit gps_emi_mod_exit(void) +{ + if (!devobj) { + GPS_ERR("null pointer: %p\n", devobj); + return; + } + + GPS_ERR("Unregistering chardev\n"); + cdev_del(&devobj->chdev); + unregister_chrdev_region(devobj->devno, 1); + device_destroy(devobj->cls, devobj->devno); + class_destroy(devobj->cls); + kfree(devobj); + GPS_ERR("Done\n"); +} + +int mtk_gps_emi_init(void) +{ + GPS_ERR("gps emi mod init begin"); + return gps_emi_mod_init(); +} + +void mtk_gps_emi_exit(void) +{ + GPS_ERR("gps emi mod exit begin"); + return gps_emi_mod_exit(); +} + +/*****************************************************************************/ +#if 0 +module_init(gps_emi_mod_init); +module_exit(gps_emi_mod_exit); +#endif +/*****************************************************************************/ +MODULE_AUTHOR("Heiping Lei "); +MODULE_DESCRIPTION("GPS EMI Driver"); +MODULE_LICENSE("GPL"); +#endif diff --git a/drivers/misc/mediatek/connectivity/gps/gps_mt3337.c b/drivers/misc/mediatek/connectivity/gps/gps_mt3337.c new file mode 100644 index 0000000000000..ef9e8de2e3805 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/gps_mt3337.c @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEVICE_NAME "mt3337_gpsonly" + +#ifdef pr_fmt +#undef pr_fmt +#endif +#define pr_fmt(fmt) "["KBUILD_MODNAME"]" fmt + +#define GPS_POWER_IOCTL _IOW('G', 0, int) + +static long gps_ioctrl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct miscdevice *dev; + struct regulator *reg; + int ret; + + switch (cmd) { + case GPS_POWER_IOCTL: + dev = (struct miscdevice *)filp->private_data; + reg = dev_get_drvdata(dev->this_device); + if (arg) + ret = regulator_enable(reg); + else + ret = regulator_disable(reg); + return ret; + default: + return -EINVAL; + } + return 0; +} + +static const struct file_operations gps_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = gps_ioctrl, + .compat_ioctl = gps_ioctrl, +}; + +static struct miscdevice mt3337_gps_driver = { + .minor = MISC_DYNAMIC_MINOR, + .name = DEVICE_NAME, + .fops = &gps_fops, +}; + +static int mt3337_gps_probe(struct platform_device *pdev) +{ + int ret; + struct regulator *regulator; + + regulator = devm_regulator_get(&pdev->dev, "power"); + if (IS_ERR(regulator)) + return PTR_ERR(regulator); + + ret = misc_register(&mt3337_gps_driver); + if (ret < 0) + return ret; + + dev_set_drvdata(mt3337_gps_driver.this_device, regulator); + + return 0; +} + +static const struct of_device_id mt3337_gps_of_match[] = { + { .compatible = "mediatek,mt3337" }, + {}, +}; + +static struct platform_driver mt3337_gps_pdriver = { + .probe = mt3337_gps_probe, + .driver = { + .name = DEVICE_NAME, + .of_match_table = of_match_ptr(mt3337_gps_of_match), + }, +}; + +module_platform_driver(mt3337_gps_pdriver); + +MODULE_AUTHOR("Hao Dong "); +MODULE_DESCRIPTION("MT3337 GPS Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mediatek/connectivity/gps/init.gps_drv.rc b/drivers/misc/mediatek/connectivity/gps/init.gps_drv.rc new file mode 100644 index 0000000000000..258aa6811002b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/init.gps_drv.rc @@ -0,0 +1,4 @@ + +# load gps_drv +on property:vendor.connsys.driver.ready=yes + insmod /vendor/lib/modules/gps_drv.ko diff --git a/drivers/misc/mediatek/connectivity/gps/lna_ctrl/inc/gps_lna_drv.h b/drivers/misc/mediatek/connectivity/gps/lna_ctrl/inc/gps_lna_drv.h new file mode 100644 index 0000000000000..310544f9ebd61 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/lna_ctrl/inc/gps_lna_drv.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ +#ifndef _GPS_LNA_DRV_H +#define _GPS_LNA_DRV_H +enum gps_lna_link_id_enum { + GPS_DATA_LINK_ID0 = 0, + GPS_DATA_LINK_ID1 = 1, + GPS_DATA_LINK_NUM = 2, +}; + +int gps_lna_linux_plat_drv_register(void); +int gps_lna_linux_plat_drv_unregister(void); +void gps_lna_pin_ctrl(enum gps_lna_link_id_enum link_id, bool dsp_is_on, bool force_en); +void gps_lna_update_status_for_md_blanking(bool gps_is_on); + +#endif /* _GPS_DL_LINUX_PLAT_DRV_H */ + diff --git a/drivers/misc/mediatek/connectivity/gps/lna_ctrl/src/gps_lna_drv.c b/drivers/misc/mediatek/connectivity/gps/lna_ctrl/src/gps_lna_drv.c new file mode 100644 index 0000000000000..77f7a74fa226d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/lna_ctrl/src/gps_lna_drv.c @@ -0,0 +1,294 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gps_lna_drv.h" + +#define PFX "[LNA_CTL] " +#define GPS_LOG_INFO 2 +static unsigned int gDbgLevel = GPS_LOG_INFO; + +#define GPS_INFO_FUNC(fmt, arg...) \ +do { if (gDbgLevel >= GPS_LOG_INFO) \ + pr_info(PFX "[I]%s: " fmt, __func__, ##arg); \ +} while (0) + + +/* #ifdef CONFIG_OF */ +const struct of_device_id gps_lna_of_ids[] = { + { .compatible = "mediatek,gps", }, + {} +}; +/* #endif */ + +enum gps_lna_pinctrl_state_enum { + GPS_DL_L1_LNA_DISABLE, + GPS_DL_L1_LNA_DSP_CTRL, + GPS_DL_L1_LNA_ENABLE, + GPS_DL_L5_LNA_DISABLE, + GPS_DL_L5_LNA_DSP_CTRL, + GPS_DL_L5_LNA_ENABLE, + GPS_DL_PINCTRL_STATE_CNT +}; + +const char *const gps_lna_pinctrl_state_name_list[GPS_DL_PINCTRL_STATE_CNT] = { + "gps_l1_lna_disable", + "gps_l1_lna_dsp_ctrl", + "gps_l1_lna_enable", + "gps_l5_lna_disable", + "gps_l5_lna_dsp_ctrl", + "gps_l5_lna_enable", +}; + +struct pinctrl_state *g_gps_lna_pinctrl_state_struct_list[GPS_DL_PINCTRL_STATE_CNT]; +struct pinctrl *g_gps_lna_pinctrl_ptr; + +void gps_lna_pinctrl_show_info(void) +{ + enum gps_lna_pinctrl_state_enum state_id; + const char *p_name; + struct pinctrl_state *p_state; + + GPS_INFO_FUNC("pinctrl_ptr = 0x%p", g_gps_lna_pinctrl_ptr); + + for (state_id = 0; state_id < GPS_DL_PINCTRL_STATE_CNT; state_id++) { + p_name = gps_lna_pinctrl_state_name_list[state_id]; + p_state = g_gps_lna_pinctrl_state_struct_list[state_id]; + GPS_INFO_FUNC("state id = %d, ptr = 0x%p, name = %s", state_id, p_state, p_name); + } +} + +void gps_lna_pinctrl_context_init(void) +{ + enum gps_lna_pinctrl_state_enum state_id; + const char *p_name; + struct pinctrl_state *p_state; + + if (IS_ERR(g_gps_lna_pinctrl_ptr)) { + GPS_INFO_FUNC("pinctrl is error"); + return; + } + + for (state_id = 0; state_id < GPS_DL_PINCTRL_STATE_CNT; state_id++) { + p_name = gps_lna_pinctrl_state_name_list[state_id]; + p_state = pinctrl_lookup_state(g_gps_lna_pinctrl_ptr, p_name); + + if (IS_ERR(p_state)) { + GPS_INFO_FUNC("lookup fail: state id = %d, name = %s", state_id, p_name); + g_gps_lna_pinctrl_state_struct_list[state_id] = NULL; + continue; + } + + g_gps_lna_pinctrl_state_struct_list[state_id] = p_state; + GPS_INFO_FUNC("lookup okay: state id = %d, name = %s", state_id, p_name); + } +} + +void gps_lna_pin_ctrl(enum gps_lna_link_id_enum link_id, bool dsp_is_on, bool force_en) +{ + struct pinctrl_state *p_state = NULL; + int ret; + + /*ASSERT_LINK_ID(link_id, GDL_VOIDF());*/ + + if (GPS_DATA_LINK_ID0 == link_id) { + if (dsp_is_on && force_en) + p_state = g_gps_lna_pinctrl_state_struct_list[GPS_DL_L1_LNA_ENABLE]; + else if (dsp_is_on) + p_state = g_gps_lna_pinctrl_state_struct_list[GPS_DL_L1_LNA_DSP_CTRL]; + else + p_state = g_gps_lna_pinctrl_state_struct_list[GPS_DL_L1_LNA_DISABLE]; + } + + if (GPS_DATA_LINK_ID1 == link_id) { + if (dsp_is_on && force_en) + p_state = g_gps_lna_pinctrl_state_struct_list[GPS_DL_L5_LNA_ENABLE]; + else if (dsp_is_on) + p_state = g_gps_lna_pinctrl_state_struct_list[GPS_DL_L5_LNA_DSP_CTRL]; + else + p_state = g_gps_lna_pinctrl_state_struct_list[GPS_DL_L5_LNA_DISABLE]; + } + + if (p_state == NULL) { + GPS_INFO_FUNC("link_id = %d, on = %d, force = %d, state is null", link_id, dsp_is_on, force_en); + return; + } + + if (g_gps_lna_pinctrl_ptr == NULL) { + GPS_INFO_FUNC("link_id = %d, on = %d, force = %d, g_gps_lna_pinctrl_ptr is null", + link_id, dsp_is_on, force_en); + return; + } + ret = pinctrl_select_state(g_gps_lna_pinctrl_ptr, p_state); + if (ret != 0) + GPS_INFO_FUNC("link_id = %d, on = %d, force = %d, select ret = %d", link_id, dsp_is_on, force_en, ret); + else + GPS_INFO_FUNC("link_id = %d, on = %d, force = %d, select ret = %d", link_id, dsp_is_on, force_en, ret); +} + +static int gps_lna_probe(struct platform_device *pdev) +{ + struct resource *irq; + int i; + bool okay; + + g_gps_lna_pinctrl_ptr = devm_pinctrl_get(&pdev->dev); + if (IS_ERR(g_gps_lna_pinctrl_ptr)) + GPS_INFO_FUNC("devm_pinctrl_get fail"); + if (!IS_ERR(g_gps_lna_pinctrl_ptr)) { + gps_lna_pinctrl_context_init(); + gps_lna_pinctrl_show_info(); + } + GPS_INFO_FUNC("do gps_lna_probe"); + + return 0; +} + +static int gps_lna_remove(struct platform_device *pdev) +{ + GPS_INFO_FUNC("do gps_lna_remove"); + platform_set_drvdata(pdev, NULL); + return 0; +} + +static int gps_lna_drv_suspend(struct device *dev) +{ +#if 0 + struct platform_device *pdev = to_platform_device(dev); + pm_message_t state = PMSG_SUSPEND; + + return mtk_btif_suspend(pdev, state); +#endif + return 0; +} + +static int gps_lna_drv_resume(struct device *dev) +{ +#if 0 + struct platform_device *pdev = to_platform_device(dev); + + return mtk_btif_resume(pdev); +#endif + return 0; +} + +static int gps_lna_plat_suspend(struct platform_device *pdev, pm_message_t state) +{ +#if 0 + int i_ret = 0; + struct _mtk_btif_ *p_btif = NULL; + + BTIF_DBG_FUNC("++\n"); + p_btif = platform_get_drvdata(pdev); + i_ret = _btif_suspend(p_btif); + BTIF_DBG_FUNC("--, i_ret:%d\n", i_ret); + return i_ret; +#endif + return 0; +} + +static int gps_lna_plat_resume(struct platform_device *pdev) +{ +#if 0 + int i_ret = 0; + struct _mtk_btif_ *p_btif = NULL; + + BTIF_DBG_FUNC("++\n"); + p_btif = platform_get_drvdata(pdev); + i_ret = _btif_resume(p_btif); + BTIF_DBG_FUNC("--, i_ret:%d\n", i_ret); + return i_ret; +#endif + return 0; +} + + +const struct dev_pm_ops gps_lna_drv_pm_ops = { + .suspend = gps_lna_drv_suspend, + .resume = gps_lna_drv_resume, +}; + +struct platform_driver gps_lna_dev_drv = { + .probe = gps_lna_probe, + .remove = gps_lna_remove, +/* #ifdef CONFIG_PM */ + .suspend = gps_lna_plat_suspend, + .resume = gps_lna_plat_resume, +/* #endif */ + .driver = { + .name = "gps", /* mediatek,gps */ + .owner = THIS_MODULE, +/* #ifdef CONFIG_PM */ + .pm = &gps_lna_drv_pm_ops, +/* #endif */ +/* #ifdef CONFIG_OF */ + .of_match_table = gps_lna_of_ids, +/* #endif */ + } +}; + +static ssize_t driver_flag_read(struct device_driver *drv, char *buf) +{ + return sprintf(buf, "gps lna driver debug level:%d\n", 1); +} + +static ssize_t driver_flag_set(struct device_driver *drv, + const char *buffer, size_t count) +{ + GPS_INFO_FUNC("buffer = %s, count = %zd", buffer, count); + return count; +} + +#define DRIVER_ATTR(_name, _mode, _show, _store) \ + struct driver_attribute driver_attr_##_name = \ + __ATTR(_name, _mode, _show, _store) +static DRIVER_ATTR(flag, 0644, driver_flag_read, driver_flag_set); + + +int gps_lna_linux_plat_drv_register(void) +{ + int result; + + result = platform_driver_register(&gps_lna_dev_drv); + /* if (result) */ + GPS_INFO_FUNC("platform_driver_register, ret(%d)\n", result); + + result = driver_create_file(&gps_lna_dev_drv.driver, &driver_attr_flag); + /* if (result) */ + GPS_INFO_FUNC("driver_create_file, ret(%d)\n", result); + + return 0; +} + +int gps_lna_linux_plat_drv_unregister(void) +{ + driver_remove_file(&gps_lna_dev_drv.driver, &driver_attr_flag); + platform_driver_unregister(&gps_lna_dev_drv); + + return 0; +} + diff --git a/drivers/misc/mediatek/connectivity/gps/stp_chrdev_gps.c b/drivers/misc/mediatek/connectivity/gps/stp_chrdev_gps.c new file mode 100644 index 0000000000000..b19e9ded9d262 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/stp_chrdev_gps.c @@ -0,0 +1,1369 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "osal_typedef.h" +#include "stp_exp.h" +#include "wmt_exp.h" +#include +#if defined(CONFIG_MACH_MT6580) +#include +#endif +#include "gps.h" +#if defined(CONFIG_MACH_MT6739) +#include +#include +#endif +#if defined(CONFIG_MACH_MT6765) || defined(CONFIG_MACH_MT6761) + +#include + +#endif +#include + +#ifdef CONFIG_GPS_CTRL_LNA_SUPPORT +#include "gps_lna_drv.h" +#endif +MODULE_LICENSE("GPL"); + +#define GPS_DRIVER_NAME "mtk_stp_GPS_chrdev" +#define GPS2_DRIVER_NAME "mtk_stp_GPS2_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 +#define COMBO_IOC_GPS_IC_HW_VERSION 7 +#define COMBO_IOC_GPS_IC_FW_VERSION 8 +#define COMBO_IOC_D1_EFUSE_GET 9 +#define COMBO_IOC_RTC_FLAG 10 +#define COMBO_IOC_CO_CLOCK_FLAG 11 +#define COMBO_IOC_TRIGGER_WMT_ASSERT 12 +#define COMBO_IOC_WMT_STATUS 13 +#define COMBO_IOC_TAKE_GPS_WAKELOCK 14 +#define COMBO_IOC_GIVE_GPS_WAKELOCK 15 +#define COMBO_IOC_GET_GPS_LNA_PIN 16 +#define COMBO_IOC_GPS_FWCTL 17 +#define COMBO_IOC_GPS_HW_SUSPEND 18 +#define COMBO_IOC_GPS_HW_RESUME 19 +#define COMBO_IOC_GPS_LISTEN_RST_EVT 20 + +static UINT32 gDbgLevel = GPS_LOG_DBG; + +#define GPS_DBG_FUNC(fmt, arg...) \ +do { if (gDbgLevel >= GPS_LOG_DBG) \ + pr_debug(PFX "[D]%s: " fmt, __func__, ##arg); \ +} while (0) +#define GPS_INFO_FUNC(fmt, arg...) \ +do { if (gDbgLevel >= GPS_LOG_INFO) \ + pr_info(PFX "[I]%s: " fmt, __func__, ##arg); \ +} while (0) +#define GPS_WARN_FUNC(fmt, arg...) \ +do { if (gDbgLevel >= GPS_LOG_WARN) \ + pr_warn(PFX "[W]%s: " fmt, __func__, ##arg); \ +} while (0) +#define GPS_ERR_FUNC(fmt, arg...) \ +do { if (gDbgLevel >= GPS_LOG_ERR) \ + pr_err(PFX "[E]%s: " fmt, __func__, ##arg); \ +} while (0) +#define GPS_TRC_FUNC(f) \ +do { if (gDbgLevel >= GPS_LOG_DBG) \ + pr_info(PFX "<%s> <%d>\n", __func__, __LINE__); \ +} while (0) + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH +bool fgGps_fwlog_on; +#endif + +#ifdef GPS_FWCTL_SUPPORT +bool fgGps_fwctl_ready; +#endif + +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; +#ifdef CONFIG_GPSL5_SUPPORT +static int GPS2_devs = 2; /* device count */ +static struct cdev GPS2_cdev; +#endif + +static struct wakeup_source *gps_wake_lock_ptr; +const char gps_wake_lock_name[] = "gpswakelock"; +static unsigned char wake_lock_acquired; /* default: 0 */ + +#if (defined(CONFIG_MTK_GMO_RAM_OPTIMIZE) && !defined(CONFIG_MTK_ENG_BUILD)) +#define STP_GPS_BUFFER_SIZE 2048 +#else +#define STP_GPS_BUFFER_SIZE MTKSTP_BUFFER_SIZE +#endif +static unsigned char i_buf[STP_GPS_BUFFER_SIZE]; /* input buffer of read() */ +static unsigned char o_buf[STP_GPS_BUFFER_SIZE]; /* output buffer of write() */ +static struct semaphore wr_mtx, rd_mtx, status_mtx; +struct semaphore fwctl_mtx; + +static DECLARE_WAIT_QUEUE_HEAD(GPS_wq); +static DECLARE_WAIT_QUEUE_HEAD(GPS_rst_wq); +static int flag; +static int rstflag; +static int rst_listening_flag; +static int rst_happened_or_gps_close_flag; + +static enum gps_ctrl_status_enum g_gps_ctrl_status; + +static void GPS_check_and_wakeup_rst_listener(enum gps_ctrl_status_enum to) +{ + if (to == GPS_RESET_START || to == GPS_RESET_DONE || to == GPS_CLOSED) { + rst_happened_or_gps_close_flag = 1; + if (rst_listening_flag) { + wake_up(&GPS_rst_wq); + GPS_WARN_FUNC("Set GPS rst_happened_or_gps_close_flag because to = %d", to); + } + } +} + +#ifdef GPS_HW_SUSPEND_SUPPORT +static void GPS_ctrl_status_change_from_to(enum gps_ctrl_status_enum from, enum gps_ctrl_status_enum to) +{ + bool okay = true; + enum gps_ctrl_status_enum status_backup; + + down(&status_mtx); + /* Due to checking status and setting status are not atomic, + * mutex is needed to make sure they are an atomic operation. + * Note: reading the status is no need to protect + */ + status_backup = g_gps_ctrl_status; + if (status_backup == from) + g_gps_ctrl_status = to; + else + okay = false; + up(&status_mtx); + + if (!okay) + GPS_WARN_FUNC("GPS unexpected status %d, not chagne from %d to %d", status_backup, from, to); + else + GPS_check_and_wakeup_rst_listener(to); +} +#endif + +static enum gps_ctrl_status_enum GPS_ctrl_status_change_to(enum gps_ctrl_status_enum to) +{ + enum gps_ctrl_status_enum status_backup; + + down(&status_mtx); + status_backup = g_gps_ctrl_status; + g_gps_ctrl_status = to; + up(&status_mtx); + + GPS_check_and_wakeup_rst_listener(to); + + return status_backup; +} + +static void GPS_event_cb(void); + +static void gps_hold_wake_lock(int hold) +{ + if (hold == 1) { + if (!wake_lock_acquired) { + GPS_DBG_FUNC("acquire gps wake_lock acquired = %d\n", wake_lock_acquired); + __pm_stay_awake(gps_wake_lock_ptr); + wake_lock_acquired = 1; + } else { + GPS_DBG_FUNC("acquire gps wake_lock acquired = %d (do nothing)\n", wake_lock_acquired); + } + } else if (hold == 0) { + if (wake_lock_acquired) { + GPS_DBG_FUNC("release gps wake_lock acquired = %d\n", wake_lock_acquired); + __pm_relax(gps_wake_lock_ptr); + wake_lock_acquired = 0; + } else { + GPS_DBG_FUNC("release gps wake_lock acquired = %d (do nothing)\n", wake_lock_acquired); + } + } +} + +bool rtc_GPS_low_power_detected(void) +{ + static bool first_query = true; + + if (first_query) { + first_query = false; + /*return rtc_low_power_detected();*/ + return 0; + } else { + return false; + } +} + +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(); */ + + /*pr_warn("%s: count %d pos %lld\n", __func__, count, *f_pos); */ + if (count > 0) { + int copy_size = (count < STP_GPS_BUFFER_SIZE) ? count : STP_GPS_BUFFER_SIZE; + + if (copy_from_user(&o_buf[0], &buf[0], copy_size)) { + retval = -EFAULT; + goto out; + } + /* pr_warn("%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; + + pr_warn("--[GPS-WRITE]--"); + for (k = 0; k < 10; k++) { + if (k % 16 == 0) + pr_warn("\n"); + pr_warn("0x%02x ", o_buf[k]); + } + pr_warn("\n"); + } +#endif + if (written == 0) { + 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:%zd, write success length:%d, retval = %d.\n", + count, written, retval); + } else { + retval = written; + } + } else { + retval = -EFAULT; + GPS_ERR_FUNC("target packet length:%zd 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); + + /* pr_debug("GPS_read(): count %d pos %lld\n", count, *f_pos); */ + if (rstflag == 1) { + if (filp->f_flags & O_NONBLOCK) { + /* GPS_DBG_FUNC("Non-blocking read, whole chip reset occurs! rstflag=%d\n", rstflag); */ + retval = -EIO; + goto OUT; + } + } + + if (count > STP_GPS_BUFFER_SIZE) + count = STP_GPS_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 */ + if (filp->f_flags & O_NONBLOCK) { + /* GPS_DBG_FUNC("Non-blocking read, no data is available!\n"); */ + retval = -EAGAIN; + goto OUT; + } + + 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_DBG_FUNC("signaled by -ERESTARTSYS(%ld)\n ", val); + else + GPS_DBG_FUNC("signaled by %ld\n ", val); + + break; + } + } + +#if GPS_DEBUG_DUMP + { + unsigned char *buf_ptr = &i_buf[0]; + int k = 0; + + pr_warn("--[GPS-READ]--"); + for (k = 0; k < 10; k++) { + if (k % 16 == 0) + pr_warn("\n"); + pr_warn("0x%02x ", i_buf[k]); + } + pr_warn("--\n"); + } +#endif + + if (retval > 0) { + /* 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); +/* pr_warn("GPS_read(): retval = %d\n", retval);*/ + return retval; +} + +#ifdef GPS_FWCTL_SUPPORT +#ifdef GPS_FWCTL_IOCTL_SUPPORT +struct gps_fwctl_data { + UINT32 size; + UINT32 tx_len; + UINT32 rx_max; + UINT32 pad; /* 128byte */ + UINT64 p_tx_buf; /* cast pointer to UINT64 to be compatible both 32/64bit */ + UINT64 p_rx_buf; /* 256byte */ + UINT64 p_rx_len; + UINT64 p_reserved; /* 384byte */ +}; + +#define GPS_FWCTL_BUF_MAX (128) +long GPS_fwctl(struct gps_fwctl_data *user_ptr) +{ + UINT8 tx_buf[GPS_FWCTL_BUF_MAX]; + UINT8 rx_buf[GPS_FWCTL_BUF_MAX]; + UINT8 tx0 = 0; + UINT8 rx0 = 0; + UINT8 rx1 = 0; + UINT32 rx_len = 0; + UINT32 rx_to_user_len; + struct gps_fwctl_data ctl_data; + INT32 status = 0; + UINT64 delta_time = 0; + bool fwctl_ready; + int retval = 0; + + if (copy_from_user(&ctl_data, user_ptr, sizeof(struct gps_fwctl_data))) { + pr_err("GPS_fwctl: copy_from_user error - ctl_data"); + return -EFAULT; + } + + if (ctl_data.size < sizeof(struct gps_fwctl_data)) { + /* user space data size not enough, risk to use it */ + pr_err("GPS_fwctl: struct size(%u) is too short than(%u)", + ctl_data.size, (UINT32)sizeof(struct gps_fwctl_data)); + return -EFAULT; + } + + if ((ctl_data.tx_len > GPS_FWCTL_BUF_MAX) || (ctl_data.tx_len == 0)) { + /* check tx data len */ + pr_err("GPS_fwctl: tx_len=%u too long (> %u) or too short", + ctl_data.tx_len, GPS_FWCTL_BUF_MAX); + return -EFAULT; + } + + if (copy_from_user(&tx_buf[0], (PUINT8)ctl_data.p_tx_buf, ctl_data.tx_len)) { + pr_err("GPS_fwctl: copy_from_user error - tx_buf"); + return -EFAULT; + } + + down(&fwctl_mtx); + if (fgGps_fwctl_ready) { + delta_time = local_clock(); + status = mtk_wmt_gps_mcu_ctrl( + &tx_buf[0], ctl_data.tx_len, &rx_buf[0], GPS_FWCTL_BUF_MAX, &rx_len); + delta_time = local_clock() - delta_time; + do_div(delta_time, 1e3); /* convert to us */ + fwctl_ready = true; + } else { + fwctl_ready = false; + } + up(&fwctl_mtx); + + tx0 = tx_buf[0]; + if (fwctl_ready && (status == 0) && (rx_len <= GPS_FWCTL_BUF_MAX) && (rx_len >= 2)) { + rx0 = rx_buf[0]; + rx1 = rx_buf[1]; + pr_info("GPS_fwctl: st=%d, tx_len=%u ([0]=%u), rx_len=%u ([0]=%u, [1]=%u), us=%u", + status, ctl_data.tx_len, tx0, rx_len, rx0, rx1, (UINT32)delta_time); + + if (ctl_data.rx_max < rx_len) + rx_to_user_len = ctl_data.rx_max; + else + rx_to_user_len = rx_len; + + if (copy_to_user((PUINT8)ctl_data.p_rx_buf, &rx_buf[0], rx_to_user_len)) { + pr_err("GPS_fwctl: copy_to_user error - rx_buf"); + retval = -EFAULT; + } + + if (copy_to_user((PUINT32)ctl_data.p_rx_len, &rx_len, sizeof(UINT32))) { + pr_err("GPS_fwctl: copy_to_user error - rx_len"); + retval = -EFAULT; + } + return retval; + } + + pr_info("GPS_fwctl: st=%d, tx_len=%u ([0]=%u), rx_len=%u, us=%u, ready=%u", + status, ctl_data.tx_len, tx0, rx_len, (UINT32)delta_time, (UINT32)fwctl_ready); + return -EFAULT; +} +#endif /* GPS_FWCTL_IOCTL_SUPPORT */ + +#define GPS_FWLOG_CTRL_BUF_MAX (20) + +#define GPS_NSEC_IN_MSEC (1000000) +UINT64 GPS_get_local_clock_ms(void) +{ + UINT64 tmp; + + /* tmp is ns */ + tmp = local_clock(); + + /* tmp is changed to ms after */ + do_div(tmp, GPS_NSEC_IN_MSEC); + + return tmp; +} + +void GPS_fwlog_ctrl_inner(bool on) +{ + UINT8 tx_buf[GPS_FWLOG_CTRL_BUF_MAX]; + UINT8 rx_buf[GPS_FWLOG_CTRL_BUF_MAX]; + UINT8 rx0 = 0; + UINT8 rx1 = 0; + UINT32 tx_len; + UINT32 rx_len = 0; + INT32 status; + UINT32 fw_tick = 0; + UINT32 local_ms0, local_ms1; + struct timeval tv; + + do_gettimeofday(&tv); + + /* 32bit ms overflow almost 4.9 days, it's enough here */ + local_ms0 = (UINT32)GPS_get_local_clock_ms(); + + tx_buf[0] = GPS_FWCTL_OPCODE_LOG_CFG; + tx_buf[1] = (UINT8)on; + tx_buf[2] = 0; + tx_buf[3] = 0; + tx_buf[4] = 0; /* bitmask, reserved now */ + tx_buf[5] = (UINT8)((local_ms0 >> 0) & 0xFF); + tx_buf[6] = (UINT8)((local_ms0 >> 8) & 0xFF); + tx_buf[7] = (UINT8)((local_ms0 >> 16) & 0xFF); + tx_buf[8] = (UINT8)((local_ms0 >> 24) & 0xFF); /* local time msecs */ + tx_buf[9] = (UINT8)((tv.tv_usec >> 0) & 0xFF); + tx_buf[10] = (UINT8)((tv.tv_usec >> 8) & 0xFF); + tx_buf[11] = (UINT8)((tv.tv_usec >> 16) & 0xFF); + tx_buf[12] = (UINT8)((tv.tv_usec >> 24) & 0xFF); /* utc usec */ + tx_buf[13] = (UINT8)((tv.tv_sec >> 0) & 0xFF); + tx_buf[14] = (UINT8)((tv.tv_sec >> 8) & 0xFF); + tx_buf[15] = (UINT8)((tv.tv_sec >> 16) & 0xFF); + tx_buf[16] = (UINT8)((tv.tv_sec >> 24) & 0xFF); /* utc sec */ + tx_len = 17; + + status = mtk_wmt_gps_mcu_ctrl(&tx_buf[0], tx_len, &rx_buf[0], GPS_FWLOG_CTRL_BUF_MAX, &rx_len); + + /* local_ms1 = jiffies_to_msecs(jiffies); */ + local_ms1 = (UINT32)GPS_get_local_clock_ms(); + + if (status == 0) { + if (rx_len >= 2) { + rx0 = rx_buf[0]; + rx1 = rx_buf[1]; + } + + if (rx_len >= 6) { + fw_tick |= (((UINT32)rx_buf[2]) << 0); + fw_tick |= (((UINT32)rx_buf[3]) << 8); + fw_tick |= (((UINT32)rx_buf[4]) << 16); + fw_tick |= (((UINT32)rx_buf[5]) << 24); + } + } + + pr_info("GPS_fwlog: st=%d, rx_len=%u ([0]=%u, [1]=%u), ms0=%u, ms1=%u, fw_tick=%u", + status, rx_len, rx0, rx1, local_ms0, local_ms1, fw_tick); +} + +#ifdef GPS_HW_SUSPEND_SUPPORT +#define HW_SUSPEND_CTRL_TX_LEN (3) +#define HW_SUSPEND_CTRL_RX_LEN (3) + +/* return 0 if okay, otherwise is fail */ +static int GPS_hw_suspend_ctrl(bool to_suspend, UINT8 mode) +{ + UINT8 tx_buf[HW_SUSPEND_CTRL_TX_LEN] = {0}; + UINT8 rx_buf[HW_SUSPEND_CTRL_RX_LEN] = {0}; + UINT8 rx0 = 0; + UINT8 rx1 = 0; + UINT32 tx_len; + UINT32 rx_len = 0; + INT32 wmt_status; + UINT32 local_ms0, local_ms1; + struct timeval tv; + + do_gettimeofday(&tv); + + /* 32bit ms overflow almost 4.9 days, it's enough here */ + local_ms0 = (UINT32)GPS_get_local_clock_ms(); + + tx_buf[0] = to_suspend ? GPS_FWCTL_OPCODE_ENTER_STOP_MODE : + GPS_FWCTL_OPCODE_EXIT_STOP_MODE; + tx_buf[1] = mode; /*mode value should be set in mnld, 0: HW suspend mode, 1: clock extension mode*/ + tx_len = 2; + + wmt_status = mtk_wmt_gps_mcu_ctrl(&tx_buf[0], tx_len, + &rx_buf[0], HW_SUSPEND_CTRL_RX_LEN, &rx_len); + + /* local_ms1 = jiffies_to_msecs(jiffies); */ + local_ms1 = (UINT32)GPS_get_local_clock_ms(); + + if (wmt_status == 0) { /* 0 is okay */ + if (rx_len >= 2) { + rx0 = rx_buf[0]; /* fw_status, 0 is okay */ + rx1 = rx_buf[1]; /* opcode */ + } + } + + if (wmt_status != 0 || rx0 != 0) { + /* Fail due to WMT fail or FW not support, + * bypass the following operations + */ + GPS_WARN_FUNC("GPS_hw_suspend_ctrl %d: st=%d, rx_len=%u ([0]=%u, [1]=%u), ms0=%u, ms1=%u, mode=%u", + to_suspend, wmt_status, rx_len, rx0, rx1, local_ms0, local_ms1, mode); + return -1; + } + + /* Okay */ + GPS_INFO_FUNC("GPS_hw_suspend_ctrl %d: st=%d, rx_len=%u ([0]=%u, [1]=%u), ms0=%u, ms1=%u, mode=%u", + to_suspend, wmt_status, rx_len, rx0, rx1, local_ms0, local_ms1, mode); + return 0; +} + +static int GPS_hw_suspend(UINT8 mode) +{ + MTK_WCN_BOOL wmt_okay; + enum gps_ctrl_status_enum gps_status; + + gps_status = g_gps_ctrl_status; + if (gps_status == GPS_OPENED) { + if (GPS_hw_suspend_ctrl(true, mode) != 0) + return -EINVAL; /* Stands for not support */ + +#ifdef CONFIG_GPSL5_SUPPORT + wmt_okay = mtk_wmt_gps_l1_suspend_ctrl(MTK_WCN_BOOL_TRUE); +#else + wmt_okay = mtk_wmt_gps_suspend_ctrl(MTK_WCN_BOOL_TRUE); +#endif + if (!wmt_okay) + GPS_WARN_FUNC("mtk_wmt_gps_l1_suspend_ctrl(1), is_ok = %d", wmt_okay); + + /* register event cb will clear GPS STP buffer */ + mtk_wcn_stp_register_event_cb(GPS_TASK_INDX, 0x0); + GPS_DBG_FUNC("mtk_wcn_stp_register_event_cb to null"); + + /* No need to clear the flag due to it just a flag and not stands for has data + * flag = 0; + * + * Keep msgcb due to GPS still need to recevice reset event under HW suspend mode + * mtk_wcn_wmt_msgcb_unreg(WMTDRV_TYPE_GPS); + */ + + GPS_reference_count(HANDLE_DESENSE, false, GPS_USER1); + gps_hold_wake_lock(0); + GPS_WARN_FUNC("gps_hold_wake_lock(0)\n"); + + GPS_ctrl_status_change_from_to(GPS_OPENED, GPS_SUSPENDED); + } else + GPS_WARN_FUNC("GPS_hw_suspend(): status %d not match\n", gps_status); + + return 0; +} + +static int GPS_hw_resume(UINT8 mode) +{ + MTK_WCN_BOOL wmt_okay; + enum gps_ctrl_status_enum gps_status; + + gps_status = g_gps_ctrl_status; + if (gps_status == GPS_SUSPENDED) { + GPS_reference_count(HANDLE_DESENSE, true, GPS_USER1); + gps_hold_wake_lock(1); + GPS_WARN_FUNC("gps_hold_wake_lock(1)\n"); + +#ifdef CONFIG_GPSL5_SUPPORT + wmt_okay = mtk_wmt_gps_l1_suspend_ctrl(MTK_WCN_BOOL_FALSE); +#else + wmt_okay = mtk_wmt_gps_suspend_ctrl(MTK_WCN_BOOL_FALSE); +#endif + if (!wmt_okay) + GPS_WARN_FUNC("mtk_wmt_gps_l1_suspend_ctrl(0), is_ok = %d", wmt_okay); + + /* should register it before real resuming to prepare for receiving data */ + mtk_wcn_stp_register_event_cb(GPS_TASK_INDX, GPS_event_cb); + if (GPS_hw_suspend_ctrl(false, mode) != 0) /*Ignore mode value for resume stage*/ + return -EINVAL; /* Stands for not support */ + + GPS_ctrl_status_change_from_to(GPS_SUSPENDED, GPS_OPENED); + } else + GPS_WARN_FUNC("GPS_hw_resume(): status %d not match\n", gps_status); + + return 0; +} +#endif /* GPS_HW_SUSPEND_SUPPORT */ + +#endif /* GPS_FWCTL_SUPPORT */ + +void GPS_fwlog_ctrl(bool on) +{ +#if (defined(GPS_FWCTL_SUPPORT) && defined(CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH)) + down(&fwctl_mtx); + if (fgGps_fwctl_ready) + GPS_reference_count(FWLOG_CTRL_INNER, on, GPS_USER1); + fgGps_fwlog_on = on; + up(&fwctl_mtx); +#endif +} + +/* block until wmt reset happen or GPS_close */ +static int GPS_listen_wmt_rst(void) +{ + long val = 0; + + rst_listening_flag = 1; + while (!rst_happened_or_gps_close_flag) { + val = wait_event_interruptible(GPS_rst_wq, rst_happened_or_gps_close_flag); + + GPS_WARN_FUNC("GPS_listen_wmt_rst(): val = %ld, cond = %d, rstflag = %d, status = %d\n", + val, rst_happened_or_gps_close_flag, rstflag, g_gps_ctrl_status); + + /* if we are signaled */ + if (val) { + rst_listening_flag = 0; + return val; + } + } + + rst_listening_flag = 0; + return 0; +} + +/* 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; + #if 0 + ENUM_WMTHWVER_TYPE_T hw_ver_sym = WMTHWVER_INVALID; + #endif + UINT32 hw_version = 0; + UINT32 fw_version = 0; + UINT32 gps_lna_pin = 0; + + pr_warn("GPS_ioctl(): cmd (%d)\n", cmd); + + switch (cmd) { + case 0: /* enable/disable STP */ + GPS_DBG_FUNC("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_DBG_FUNC("GPS_ioctl(): disable raw data from GPS dev\n"); + retval = -EINVAL; + break; + + #if 0 + case COMBO_IOC_GPS_HWVER: + /*get combo hw version */ + hw_ver_sym = mtk_wcn_wmt_hwver_get(); + + GPS_DBG_FUNC("GPS_ioctl(): get hw version = %d, sizeof(hw_ver_sym) = %zd\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; + #endif + case COMBO_IOC_GPS_IC_HW_VERSION: + /*get combo hw version from ic, without wmt mapping */ + hw_version = mtk_wcn_wmt_ic_info_get(WMTCHIN_HWVER); + + GPS_DBG_FUNC("GPS_ioctl(): get hw version = 0x%x\n", hw_version); + if (copy_to_user((int __user *)arg, &hw_version, sizeof(hw_version))) + retval = -EFAULT; + + break; + + case COMBO_IOC_GPS_IC_FW_VERSION: + /*get combo fw version from ic, without wmt mapping */ + fw_version = mtk_wcn_wmt_ic_info_get(WMTCHIN_FWVER); + + GPS_DBG_FUNC("GPS_ioctl(): get fw version = 0x%x\n", fw_version); + if (copy_to_user((int __user *)arg, &fw_version, sizeof(fw_version))) + retval = -EFAULT; + + break; + case COMBO_IOC_RTC_FLAG: + + retval = rtc_GPS_low_power_detected(); + + GPS_DBG_FUNC("low power flag (%d)\n", retval); + break; + case COMBO_IOC_CO_CLOCK_FLAG: +#if SOC_CO_CLOCK_FLAG + retval = mtk_wcn_wmt_co_clock_flag_get(); +#endif + GPS_DBG_FUNC("GPS co_clock_flag (%d)\n", retval); + break; + case COMBO_IOC_D1_EFUSE_GET: +#if defined(CONFIG_MACH_MT6735) + do { + char *addr = ioremap(0x10206198, 0x4); + + retval = *(volatile unsigned int *)addr; + GPS_DBG_FUNC("D1 efuse (0x%x)\n", retval); + iounmap(addr); + } while (0); +#elif defined(CONFIG_MACH_MT6763) + do { + char *addr = ioremap(0x11f10048, 0x4); + + retval = *(volatile unsigned int *)addr; + GPS_DBG_FUNC("bianco efuse (0x%x)\n", retval); + iounmap(addr); + } while (0); +#else + GPS_ERR_FUNC("Read Efuse not supported in this platform\n"); +#endif + break; + + case COMBO_IOC_TRIGGER_WMT_ASSERT: + /* Trigger FW assert for debug */ + GPS_INFO_FUNC("%s: Host trigger FW assert......, reason:%lu\n", __func__, arg); + retval = mtk_wcn_wmt_assert(WMTDRV_TYPE_GPS, arg); + if (retval == MTK_WCN_BOOL_TRUE) { + GPS_INFO_FUNC("Host trigger FW assert succeed\n"); + retval = 0; + } else { + GPS_ERR_FUNC("Host trigger FW assert Failed\n"); + retval = (-EBUSY); + } + break; + case COMBO_IOC_WMT_STATUS: + if (rstflag == 1) { + /* chip resetting */ + retval = -888; + } else if (rstflag == 2) { + /* chip reset end */ + retval = -889; + /* + * rstflag = 0 is cleared by GPS_open or GPS_close, + * no need to clear it here + */ + } else { + /* normal */ + retval = 0; + } + GPS_DBG_FUNC("rstflag(%d), retval(%d)\n", rstflag, retval); + break; + case COMBO_IOC_TAKE_GPS_WAKELOCK: + GPS_INFO_FUNC("Ioctl to take gps wakelock\n"); + gps_hold_wake_lock(1); + if (wake_lock_acquired == 1) + retval = 0; + else + retval = -EAGAIN; + break; + case COMBO_IOC_GIVE_GPS_WAKELOCK: + GPS_INFO_FUNC("Ioctl to give gps wakelock\n"); + gps_hold_wake_lock(0); + if (wake_lock_acquired == 0) + retval = 0; + else + retval = -EAGAIN; + break; +#ifdef GPS_FWCTL_IOCTL_SUPPORT + case COMBO_IOC_GPS_FWCTL: + GPS_INFO_FUNC("COMBO_IOC_GPS_FWCTL\n"); + retval = GPS_fwctl((struct gps_fwctl_data *)arg); + break; +#endif + +#ifdef GPS_HW_SUSPEND_SUPPORT + case COMBO_IOC_GPS_HW_SUSPEND: + GPS_INFO_FUNC("COMBO_IOC_GPS_HW_SUSPEND: mode %lu\n", arg); + retval = GPS_hw_suspend((UINT8)(arg&0xFF)); + break; + case COMBO_IOC_GPS_HW_RESUME: + GPS_INFO_FUNC("COMBO_IOC_GPS_HW_RESUME: mode %lu\n", arg); + retval = GPS_hw_resume((UINT8)(arg&0xFF)); + break; +#endif /* GPS_HW_SUSPEND_SUPPORT */ + + case COMBO_IOC_GPS_LISTEN_RST_EVT: + GPS_INFO_FUNC("COMBO_IOC_GPS_LISTEN_RST_EVT\n"); + retval = GPS_listen_wmt_rst(); + break; + + case COMBO_IOC_GET_GPS_LNA_PIN: + gps_lna_pin = mtk_wmt_get_gps_lna_pin_num(); + GPS_DBG_FUNC("GPS_ioctl(): get gps lna pin = %d\n", gps_lna_pin); + if (copy_to_user((int __user *)arg, &gps_lna_pin, sizeof(gps_lna_pin))) + retval = -EFAULT; + break; + default: + retval = -EFAULT; + GPS_DBG_FUNC("GPS_ioctl(): unknown cmd (%d)\n", cmd); + break; + } + +/*OUT:*/ + return retval; +} + +long GPS_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + long ret; + + pr_warn("%s: cmd (%d)\n", __func__, cmd); + ret = GPS_unlocked_ioctl(filp, cmd, arg); + pr_warn("%s: cmd (%d)\n", __func__, cmd); + return ret; +} + +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_DBG_FUNC("sizeof(ENUM_WMTRSTMSG_TYPE_T) = %zd\n", sizeof(ENUM_WMTRSTMSG_TYPE_T)); + if (sz <= sizeof(ENUM_WMTRSTMSG_TYPE_T)) { + memcpy((char *)&rst_msg, (char *)buf, sz); + GPS_DBG_FUNC("src = %d, dst = %d, type = %d, buf = 0x%x sz = %d, max = %d\n", src, + dst, type, rst_msg, sz, WMTRSTMSG_RESET_MAX); + + if ((src == WMTDRV_TYPE_WMT) && (dst == WMTDRV_TYPE_GPS) && (type == WMTMSG_TYPE_RESET)) { + switch (rst_msg) { + case WMTRSTMSG_RESET_START: + GPS_INFO_FUNC("Whole chip reset start!\n"); + rstflag = 1; +#ifdef GPS_FWCTL_SUPPORT + down(&fwctl_mtx); + GPS_reference_count(FGGPS_FWCTL_EADY, false, GPS_USER1); + up(&fwctl_mtx); +#endif + GPS_ctrl_status_change_to(GPS_RESET_START); + break; + case WMTRSTMSG_RESET_END: + case WMTRSTMSG_RESET_END_FAIL: + if (rst_msg == WMTRSTMSG_RESET_END) + GPS_INFO_FUNC("Whole chip reset end!\n"); + else + GPS_INFO_FUNC("Whole chip reset fail!\n"); + rstflag = 2; + + GPS_ctrl_status_change_to(GPS_RESET_DONE); + break; + default: + break; + } + } + } else { + /*message format invalid */ + GPS_WARN_FUNC("Invalid message format!\n"); + } +} + +static bool desense_handled_flag; +static void GPS_handle_desense(bool on) +{ + bool to_do = false, handled = false; + + down(&status_mtx); + handled = desense_handled_flag; + if ((on && !handled) || (!on && handled)) + to_do = true; + else + to_do = false; + + if (on) + desense_handled_flag = true; + else + desense_handled_flag = false; + up(&status_mtx); + + if (!to_do) { + GPS_WARN_FUNC("GPS_handle_desense(%d) not to go due to handled = %d", on, handled); + return; + } + + if (on) { +#if defined(CONFIG_MACH_MT6739) + if (freqhopping_config(FH_MEM_PLLID, 0, 1) == 0) + GPS_WARN_FUNC("Enable MEMPLL successfully\n"); + else + GPS_WARN_FUNC("Error to enable MEMPLL\n"); +#endif +#if defined(CONFIG_MACH_MT6580) + GPS_WARN_FUNC("export_clk_buf: %x\n", CLK_BUF_AUDIO); + KERNEL_clk_buf_ctrl(CLK_BUF_AUDIO, 1); +#endif +#if defined(CONFIG_MACH_MT6765) || defined(CONFIG_MACH_MT6761) + dvfsrc_enable_dvfs_freq_hopping(1); + GPS_WARN_FUNC("mt6765/61 GPS desense solution on\n"); +#endif + } else { +#if defined(CONFIG_MACH_MT6739) + if (freqhopping_config(FH_MEM_PLLID, 0, 0) == 0) + GPS_WARN_FUNC("disable MEMPLL successfully\n"); + else + GPS_WARN_FUNC("Error to disable MEMPLL\n"); +#endif +#if defined(CONFIG_MACH_MT6765) || defined(CONFIG_MACH_MT6761) + dvfsrc_enable_dvfs_freq_hopping(0); + GPS_WARN_FUNC("mt6765/61 GPS desense solution off\n"); +#endif +#if defined(CONFIG_MACH_MT6580) + GPS_WARN_FUNC("export_clk_buf: %x\n", CLK_BUF_AUDIO); + KERNEL_clk_buf_ctrl(CLK_BUF_AUDIO, 0); +#endif + } +} + +static int GPS_open(struct inode *inode, struct file *file) +{ + pr_warn("%s: major %d minor %d (pid %d)\n", __func__, imajor(inode), iminor(inode), current->pid); + if (current->pid == 1) + return 0; + if (rstflag == 1) { + GPS_WARN_FUNC("whole chip resetting...\n"); + return -EPERM; + } + +#if 1 /* GeorgeKuo: turn on function before check stp ready */ + /* turn on BT */ +#ifdef CONFIG_GPS_CTRL_LNA_SUPPORT + gps_lna_pin_ctrl(GPS_DATA_LINK_ID0, true, false); +#endif + if (mtk_wcn_wmt_func_on(WMTDRV_TYPE_GPS) == MTK_WCN_BOOL_FALSE) { + GPS_WARN_FUNC("WMT turn on GPS fail!\n"); + return -ENODEV; + } + + mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_GPS, gps_cdev_rst_cb); + GPS_WARN_FUNC("WMT turn on GPS OK!\n"); + rstflag = 0; + +#endif + + if (mtk_wcn_stp_is_ready()) { +#if 0 + if (mtk_wcn_wmt_func_on(WMTDRV_TYPE_GPS) == MTK_WCN_BOOL_FALSE) { + GPS_WARN_FUNC("WMT turn on GPS fail!\n"); + return -ENODEV; + } + GPS_DBG_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; + } + gps_hold_wake_lock(1); + GPS_WARN_FUNC("gps_hold_wake_lock(1)\n"); + + GPS_reference_count(HANDLE_DESENSE, true, GPS_USER1); + +#ifdef GPS_FWCTL_SUPPORT + down(&fwctl_mtx); + GPS_reference_count(FGGPS_FWCTL_EADY, true, GPS_USER1); +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + if (fgGps_fwlog_on) { + /* GPS fw clear log on flag when GPS on, no need to send it if log setting is off */ + GPS_reference_count(FWLOG_CTRL_INNER, fgGps_fwlog_on, GPS_USER1); + } +#endif + up(&fwctl_mtx); +#endif /* GPS_FWCTL_SUPPORT */ + + rst_happened_or_gps_close_flag = 0; + GPS_ctrl_status_change_to(GPS_OPENED); + return 0; +} + +static int GPS_close(struct inode *inode, struct file *file) +{ + int ret = 0; + pr_warn("%s: major %d minor %d (pid %d)\n", __func__, imajor(inode), iminor(inode), current->pid); + if (current->pid == 1) + return 0; + + if (rstflag == 1) { + GPS_WARN_FUNC("whole chip resetting...\n"); + ret = -EPERM; + goto _out; + } + +#ifdef GPS_FWCTL_SUPPORT + down(&fwctl_mtx); + GPS_reference_count(FGGPS_FWCTL_EADY, false, GPS_USER1); + up(&fwctl_mtx); +#endif +#ifdef CONFIG_GPS_CTRL_LNA_SUPPORT + gps_lna_pin_ctrl(GPS_DATA_LINK_ID0, false, false); +#endif + if (mtk_wcn_wmt_func_off(WMTDRV_TYPE_GPS) == MTK_WCN_BOOL_FALSE) { + GPS_WARN_FUNC("WMT turn off GPS fail!\n"); + ret = -EIO; /* mostly, native programer does not care this return vlaue, */ + /* but we still return error code. */ + goto _out; + } + GPS_WARN_FUNC("WMT turn off GPS OK!\n"); + rstflag = 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); + +_out: + gps_hold_wake_lock(0); + GPS_WARN_FUNC("gps_hold_wake_lock(0)\n"); + + GPS_reference_count(HANDLE_DESENSE, false, GPS_USER1); + + GPS_ctrl_status_change_to(GPS_CLOSED); + return ret; +} + +const 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, + .compat_ioctl = GPS_compat_ioctl, +}; + +void GPS_event_cb(void) +{ +/* pr_debug("GPS_event_cb()\n");*/ + + flag = 1; + wake_up(&GPS_wq); +} + +#if WMT_CREATE_NODE_DYNAMIC || REMOVE_MK_NODE +struct class *stpgps_class; +#ifdef CONFIG_GPSL5_SUPPORT +struct class *stpgps2_class; +#endif +#endif + +static int GPS_init(void) +{ + dev_t dev = MKDEV(GPS_major, 0); + int cdev_err = 0; +#if WMT_CREATE_NODE_DYNAMIC || REMOVE_MK_NODE + struct device *stpgps_dev = NULL; +#endif +#ifdef CONFIG_GPSL5_SUPPORT + dev_t dev2 = MKDEV(GPS_major, 1); + int cdev2_err = 0; +#if WMT_CREATE_NODE_DYNAMIC || REMOVE_MK_NODE + struct device *stpgps2_dev = NULL; +#endif +#endif + int alloc_ret = 0; + + + /*static allocate chrdev */ + alloc_ret = register_chrdev_region(dev, 1, GPS_DRIVER_NAME); + if (alloc_ret) { + pr_warn("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; +#if WMT_CREATE_NODE_DYNAMIC || REMOVE_MK_NODE + + stpgps_class = class_create(THIS_MODULE, "stpgps"); + if (IS_ERR(stpgps_class)) + goto error; + stpgps_dev = device_create(stpgps_class, NULL, dev, NULL, "stpgps"); + if (IS_ERR(stpgps_dev)) + goto error; +#endif + +#ifdef CONFIG_GPSL5_SUPPORT + /*static allocate chrdev */ + alloc_ret = register_chrdev_region(dev2, 1, GPS2_DRIVER_NAME); + if (alloc_ret) { + pr_info("fail to register chrdev\n"); + return alloc_ret; + } + + cdev_init(&GPS2_cdev, &GPS2_fops); + GPS2_cdev.owner = THIS_MODULE; + + cdev2_err = cdev_add(&GPS2_cdev, dev2, GPS2_devs); + if (cdev2_err) + goto error; +#if WMT_CREATE_NODE_DYNAMIC || REMOVE_MK_NODE + + stpgps2_class = class_create(THIS_MODULE, "stpgps2"); + if (IS_ERR(stpgps2_class)) + goto error; + stpgps2_dev = device_create(stpgps2_class, NULL, dev2, NULL, "stpgps2"); + if (IS_ERR(stpgps2_dev)) + goto error; +#endif +#endif + pr_warn("%s driver(major %d) installed.\n", GPS_DRIVER_NAME, GPS_major); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 149) + gps_wake_lock_ptr = wakeup_source_register(NULL, gps_wake_lock_name); +#else + gps_wake_lock_ptr = wakeup_source_register(gps_wake_lock_name); +#endif + if (!gps_wake_lock_ptr) { + pr_info("%s %d: init wakeup source fail!", __func__, __LINE__); + goto error; + } + + sema_init(&status_mtx, 1); + sema_init(&fwctl_mtx, 1); + /* init_MUTEX(&wr_mtx); */ + sema_init(&wr_mtx, 1); + /* init_MUTEX(&rd_mtx); */ + sema_init(&rd_mtx, 1); + +#ifdef CONFIG_GPSL5_SUPPORT + wakeup_source_init(&gps2_wake_lock, "gpswakelock"); + + sema_init(&status_mtx2, 1); + /* init_MUTEX(&wr_mtx); */ + sema_init(&wr_mtx2, 1); + /* init_MUTEX(&rd_mtx); */ + sema_init(&rd_mtx2, 1); +#endif +#ifdef CONFIG_GPS_CTRL_LNA_SUPPORT + gps_lna_linux_plat_drv_register(); +#endif + return 0; + +error: + +#if WMT_CREATE_NODE_DYNAMIC || REMOVE_MK_NODE + if (!IS_ERR(stpgps_dev)) + device_destroy(stpgps_class, dev); + if (!IS_ERR(stpgps_class)) { + class_destroy(stpgps_class); + stpgps_class = NULL; + } +#ifdef CONFIG_GPSL5_SUPPORT + if (!IS_ERR(stpgps2_dev)) + device_destroy(stpgps2_class, dev2); + if (!IS_ERR(stpgps2_class)) { + class_destroy(stpgps2_class); + stpgps2_class = NULL; + } +#endif +#endif + if (cdev_err == 0) + cdev_del(&GPS_cdev); +#ifdef CONFIG_GPSL5_SUPPORT + if (cdev2_err == 0) + cdev_del(&GPS2_cdev); +#endif + if (alloc_ret == 0) { + unregister_chrdev_region(dev, GPS_devs); +#ifdef CONFIG_GPSL5_SUPPORT + unregister_chrdev_region(dev2, GPS2_devs); +#endif + } + + return -1; +} + +static void GPS_exit(void) +{ + dev_t dev = MKDEV(GPS_major, 0); +#ifdef CONFIG_GPSL5_SUPPORT + dev_t dev2 = MKDEV(GPS_major, 1); +#endif +#if WMT_CREATE_NODE_DYNAMIC || REMOVE_MK_NODE + device_destroy(stpgps_class, dev); + class_destroy(stpgps_class); + stpgps_class = NULL; +#ifdef CONFIG_GPSL5_SUPPORT + device_destroy(stpgps2_class, dev2); + class_destroy(stpgps2_class); + stpgps2_class = NULL; +#endif +#endif + + cdev_del(&GPS_cdev); + unregister_chrdev_region(dev, GPS_devs); + pr_warn("%s driver removed.\n", GPS_DRIVER_NAME); + +#ifdef CONFIG_GPSL5_SUPPORT + cdev_del(&GPS2_cdev); + unregister_chrdev_region(dev2, GPS2_devs); + pr_info("%s driver removed.\n", GPS2_DRIVER_NAME); + +#endif +#ifdef CONFIG_GPS_CTRL_LNA_SUPPORT + gps_lna_linux_plat_drv_unregister(); +#endif + wakeup_source_unregister(gps_wake_lock_ptr); +} + +int mtk_wcn_stpgps_drv_init(void) +{ + return GPS_init(); +} +EXPORT_SYMBOL(mtk_wcn_stpgps_drv_init); + +void mtk_wcn_stpgps_drv_exit(void) +{ + return GPS_exit(); +} +EXPORT_SYMBOL(mtk_wcn_stpgps_drv_exit); + +/*****************************************************************************/ +static int __init gps_mod_init(void) +{ + int ret = 0; + + mtk_wcn_stpgps_drv_init(); + #ifdef CONFIG_MTK_GPS_EMI + mtk_gps_emi_init(); + #endif + #ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + mtk_gps_fw_log_init(); + #endif + return ret; +} + +/*****************************************************************************/ +static void __exit gps_mod_exit(void) +{ + mtk_wcn_stpgps_drv_exit(); + #ifdef CONFIG_MTK_GPS_EMI + mtk_gps_emi_exit(); + #endif + #ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + mtk_gps_fw_log_exit(); + #endif +} + +module_init(gps_mod_init); +module_exit(gps_mod_exit); + +int reference_count_bitmap[2] = {0}; +void GPS_reference_count(enum gps_reference_count_cmd cmd, bool flag, int user) +{ + bool old_state = false; + bool new_state = false; + + old_state = (reference_count_bitmap[0] & (0x01 << (int)cmd)) + || (reference_count_bitmap[1] & (0x01 << FWLOG_CTRL_INNER)); + if (flag == true) + reference_count_bitmap[user] |= (0x01 << (int)cmd); + else + reference_count_bitmap[user] &= ~(0x01 << (int)cmd); + new_state = (reference_count_bitmap[0] & (0x01 << (int)cmd)) + || (reference_count_bitmap[1] & (0x01 << FWLOG_CTRL_INNER)); + + switch (cmd) { + case FWLOG_CTRL_INNER: +#ifdef GPS_FWCTL_SUPPORT + if (old_state != new_state) + GPS_fwlog_ctrl_inner(new_state); +#endif + break; + case HANDLE_DESENSE: + if (old_state != new_state) + GPS_handle_desense(new_state); + break; + case FGGPS_FWCTL_EADY: +#ifdef GPS_FWCTL_SUPPORT + if (old_state != new_state) + fgGps_fwctl_ready = new_state; +#endif + break; + } +} + diff --git a/drivers/misc/mediatek/connectivity/gps/stp_chrdev_gps2.c b/drivers/misc/mediatek/connectivity/gps/stp_chrdev_gps2.c new file mode 100644 index 0000000000000..4415c1d461eac --- /dev/null +++ b/drivers/misc/mediatek/connectivity/gps/stp_chrdev_gps2.c @@ -0,0 +1,844 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "osal_typedef.h" +#include "stp_exp.h" +#include "wmt_exp.h" +#include +#if defined(CONFIG_MACH_MT6580) +#include +#endif +#include "gps.h" +#if defined(CONFIG_MACH_MT6739) +#include +#include +#endif +#if defined(CONFIG_MACH_MT6765) || defined(CONFIG_MACH_MT6761) +#include +#endif +#ifdef CONFIG_GPS_CTRL_LNA_SUPPORT +#include "gps_lna_drv.h" +#endif + +#define GPS2_DEBUG_TRACE_GPIO 0 +#define GPS2_DEBUG_DUMP 0 + +#define PFX2 "[GPS2] " +#define GPS2_LOG_DBG 3 +#define GPS2_LOG_INFO 2 +#define GPS2_LOG_WARN 1 +#define GPS2_LOG_ERR 0 + +#define COMBO_IOC_GPS2_HWVER 6 +#define COMBO_IOC_GPS2_IC_HW_VERSION 7 +#define COMBO_IOC_GPS2_IC_FW_VERSION 8 +#define COMBO_IOC_D1_EFUSE_GET2 9 +#define COMBO_IOC_RTC_FLAG2 10 +#define COMBO_IOC_CO_CLOCK_FLAG2 11 +#define COMBO_IOC_TRIGGER_WMT_ASSERT2 12 +#define COMBO_IOC_WMT_STATUS2 13 +#define COMBO_IOC_TAKE_GPS2_WAKELOCK 14 +#define COMBO_IOC_GIVE_GPS2_WAKELOCK 15 +#define COMBO_IOC_GET_GPS2_LNA_PIN 16 +#define COMBO_IOC_GPS2_FWCTL 17 +#define COMBO_IOC_GPS2_HW_SUSPEND 18 +#define COMBO_IOC_GPS2_HW_RESUME 19 +#define COMBO_IOC_GPS2_LISTEN_RST_EVT 20 + +static UINT32 g2DbgLevel = GPS2_LOG_DBG; + +#define GPS2_DBG_FUNC(fmt, arg...) \ +do { if (g2DbgLevel >= GPS2_LOG_DBG) \ + pr_debug(PFX2 "[D]%s: " fmt, __func__, ##arg); \ +} while (0) +#define GPS2_INFO_FUNC(fmt, arg...) \ +do { if (g2DbgLevel >= GPS2_LOG_INFO) \ + pr_info(PFX2 "[I]%s: " fmt, __func__, ##arg); \ +} while (0) +#define GPS2_WARN_FUNC(fmt, arg...) \ +do { if (g2DbgLevel >= GPS2_LOG_WARN) \ + pr_info(PFX2 "[W]%s: " fmt, __func__, ##arg); \ +} while (0) +#define GPS2_ERR_FUNC(fmt, arg...) \ +do { if (g2DbgLevel >= GPS2_LOG_ERR) \ + pr_info(PFX2 "[E]%s: " fmt, __func__, ##arg); \ +} while (0) +#define GPS2_TRC_FUNC(f) \ +do { if (g2DbgLevel >= GPS2_LOG_DBG) \ + pr_info(PFX2 "<%s> <%d>\n", __func__, __LINE__); \ +} while (0) + +struct wakeup_source gps2_wake_lock; +static unsigned char wake_lock_acquired2; /* default: 0 */ + +#if (defined(CONFIG_MTK_GMO_RAM_OPTIMIZE) && !defined(CONFIG_MTK_ENG_BUILD)) +#define STP_GPS_BUFFER_SIZE2 2048 +#else +#define STP_GPS_BUFFER_SIZE2 MTKSTP_BUFFER_SIZE +#endif +static unsigned char i_buf2[STP_GPS_BUFFER_SIZE2]; /* input buffer of read() */ +static unsigned char o_buf2[STP_GPS_BUFFER_SIZE2]; /* output buffer of write() */ +struct semaphore wr_mtx2, rd_mtx2, status_mtx2; +static DECLARE_WAIT_QUEUE_HEAD(GPS2_wq); +static DECLARE_WAIT_QUEUE_HEAD(GPS2_rst_wq); +static int flag2; +static int rstflag2; +static int rst_listening_flag2; +static int rst_happened_or_gps_close_flag2; + +static enum gps_ctrl_status_enum g_gps2_ctrl_status; + +static void GPS2_check_and_wakeup_rst_listener(enum gps_ctrl_status_enum to) +{ + if (to == GPS_RESET_START || to == GPS_RESET_DONE || to == GPS_CLOSED) { + rst_happened_or_gps_close_flag2 = 1; + if (rst_listening_flag2) { + wake_up(&GPS2_rst_wq); + GPS2_WARN_FUNC("Set GPS rst_happened_or_gps_close_flag2 because to = %d", to); + } + } +} + +#ifdef GPS_HW_SUSPEND_SUPPORT +static void GPS2_ctrl_status_change_from_to(enum gps_ctrl_status_enum from, enum gps_ctrl_status_enum to) +{ + bool okay = true; + enum gps_ctrl_status_enum status_backup; + + down(&status_mtx2); + /* Due to checking status and setting status are not atomic, + * mutex is needed to make sure they are an atomic operation. + * Note: reading the status is no need to protect + */ + status_backup = g_gps2_ctrl_status; + if (status_backup == from) + g_gps2_ctrl_status = to; + else + okay = false; + up(&status_mtx2); + + if (!okay) + GPS2_WARN_FUNC("GPS unexpected status %d, not chagne from %d to %d", status_backup, from, to); + else + GPS2_check_and_wakeup_rst_listener(to); +} +#endif + +static enum gps_ctrl_status_enum GPS2_ctrl_status_change_to(enum gps_ctrl_status_enum to) +{ + enum gps_ctrl_status_enum status_backup; + + down(&status_mtx2); + status_backup = g_gps2_ctrl_status; + g_gps2_ctrl_status = to; + up(&status_mtx2); + + GPS2_check_and_wakeup_rst_listener(to); + + return status_backup; +} + +static void GPS2_event_cb(void); + +static void gps2_hold_wake_lock(int hold) +{ + if (hold == 1) { + if (!wake_lock_acquired2) { + GPS2_DBG_FUNC("acquire gps2 wake_lock acquired = %d\n", wake_lock_acquired2); + __pm_stay_awake(&gps2_wake_lock); + wake_lock_acquired2 = 1; + } else { + GPS2_DBG_FUNC("acquire gps2 wake_lock acquired = %d (do nothing)\n", wake_lock_acquired2); + } + } else if (hold == 0) { + if (wake_lock_acquired2) { + GPS2_DBG_FUNC("release gps2 wake_lock acquired = %d\n", wake_lock_acquired2); + __pm_relax(&gps2_wake_lock); + wake_lock_acquired2 = 0; + } else { + GPS2_DBG_FUNC("release gps2 wake_lock acquired = %d (do nothing)\n", wake_lock_acquired2); + } + } +} + +bool rtc_GPS2_low_power_detected(void) +{ + static bool first_query = true; + + if (first_query) { + first_query = false; + /*return rtc_low_power_detected();*/ + return 0; + } else { + return false; + } +} + +ssize_t GPS2_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) +{ + int retval = 0; + int written = 0; + + down(&wr_mtx2); + + /* GPS2_TRC_FUNC(); */ + + /*pr_info("%s: count %d pos %lld\n", __func__, count, *f_pos); */ + if (count > 0) { + int copy_size = (count < STP_GPS_BUFFER_SIZE2) ? count : STP_GPS_BUFFER_SIZE2; + + if (copy_from_user(&o_buf2[0], &buf[0], copy_size)) { + retval = -EFAULT; + goto out; + } + /* pr_info("%02x ", val); */ +#if GPS2_DEBUG_TRACE_GPIO + mtk_wcn_stp_debug_gpio_assert(IDX_GPS_TX, DBG_TIE_LOW); +#endif + written = mtk_wcn_stp_send_data(&o_buf2[0], copy_size, GPSL5_TASK_INDX); +#if GPS2_DEBUG_TRACE_GPIO + mtk_wcn_stp_debug_gpio_assert(IDX_GPS_TX, DBG_TIE_HIGH); +#endif + +#if GPS2_DEBUG_DUMP + { + unsigned char *buf_ptr = &o_buf2[0]; + int k = 0; + + pr_info("--[GPS2-WRITE]--"); + for (k = 0; k < 10; k++) { + if (k % 16 == 0) + pr_info("\n"); + pr_info("0x%02x ", o_buf2[k]); + } + pr_info("\n"); + } +#endif + if (written == 0) { + retval = -ENOSPC; + /* no windowspace in STP is available, */ + /* native process should not call GPS2_write with no delay at all */ + GPS2_ERR_FUNC + ("target packet length:%zd, write success length:%d, retval = %d.\n", + count, written, retval); + } else { + retval = written; + } + } else { + retval = -EFAULT; + GPS2_ERR_FUNC("target packet length:%zd is not allowed, retval = %d.\n", count, retval); + } +out: + up(&wr_mtx2); + return retval; +} + +ssize_t GPS2_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + long val = 0; + int retval; + + down(&rd_mtx2); + + /* pr_debug("GPS2_read(): count %d pos %lld\n", count, *f_pos); */ + if (rstflag2 == 1) { + if (filp->f_flags & O_NONBLOCK) { + /* GPS2_DBG_FUNC("Non-blocking read, whole chip reset occurs! rstflag2=%d\n", rstflag2); */ + retval = -EIO; + goto OUT; + } + } + + if (count > STP_GPS_BUFFER_SIZE2) + count = STP_GPS_BUFFER_SIZE2; + +#if GPS2_DEBUG_TRACE_GPIO + mtk_wcn_stp_debug_gpio_assert(IDX_GPS_RX, DBG_TIE_LOW); +#endif + retval = mtk_wcn_stp_receive_data(i_buf2, count, GPSL5_TASK_INDX); +#if GPS2_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(GPS2_wq, flag2 != 0); *//* George: let signal wake up */ + if (filp->f_flags & O_NONBLOCK) { + /* GPS2_DBG_FUNC("Non-blocking read, no data is available!\n"); */ + retval = -EAGAIN; + goto OUT; + } + + val = wait_event_interruptible(GPS2_wq, flag2 != 0); + flag2 = 0; + +#if GPS2_DEBUG_TRACE_GPIO + mtk_wcn_stp_debug_gpio_assert(IDX_GPS_RX, DBG_TIE_LOW); +#endif + + retval = mtk_wcn_stp_receive_data(i_buf2, count, GPSL5_TASK_INDX); + +#if GPS2_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) + GPS2_DBG_FUNC("signaled by -ERESTARTSYS(%ld)\n ", val); + else + GPS2_DBG_FUNC("signaled by %ld\n ", val); + + break; + } + } + +#if GPS2_DEBUG_DUMP + { + unsigned char *buf_ptr = &i_buf2[0]; + int k = 0; + + pr_info("--[GPS2-READ]--"); + for (k = 0; k < 10; k++) { + if (k % 16 == 0) + pr_info("\n"); + pr_info("0x%02x ", i_buf2[k]); + } + pr_info("--\n"); + } +#endif + + if (retval > 0) { + /* we got something from STP driver */ + if (copy_to_user(buf, i_buf2, retval)) { + retval = -EFAULT; + goto OUT; + } else { + /* success */ + } + } else { + /* we got nothing from STP driver, being signaled */ + retval = val; + } + +OUT: + up(&rd_mtx2); +/* pr_info("GPS2_read(): retval = %d\n", retval);*/ + return retval; +} + +#ifdef GPS_FWCTL_SUPPORT +#ifdef GPS_HW_SUSPEND_SUPPORT +#define HW_SUSPEND_CTRL_TX_LEN2 (2) +#define HW_SUSPEND_CTRL_RX_LEN2 (3) + +/* return 0 if okay, otherwise is fail */ +static int GPS2_hw_suspend_ctrl(bool to_suspend) +{ + UINT8 tx_buf[HW_SUSPEND_CTRL_TX_LEN2]; + UINT8 rx_buf[HW_SUSPEND_CTRL_RX_LEN2]; + UINT8 rx0 = 0; + UINT8 rx1 = 0; + UINT32 tx_len; + UINT32 rx_len = 0; + INT32 wmt_status; + UINT32 local_ms0, local_ms1; + struct timeval tv; + UINT64 tmp; + + do_gettimeofday(&tv); + tmp = local_clock(); + do_div(tmp, 1e6); + local_ms0 = (UINT32)tmp; /* overflow almost 4.9 days */ + + tx_buf[0] = to_suspend ? GPS2_FWCTL_OPCODE_ENTER_STOP_MODE : + GPS2_FWCTL_OPCODE_EXIT_STOP_MODE; + tx_len = 1; + + wmt_status = mtk_wmt_gps_mcu_ctrl(&tx_buf[0], tx_len, + &rx_buf[0], HW_SUSPEND_CTRL_RX_LEN2, &rx_len); + + /* local_ms1 = jiffies_to_msecs(jiffies); */ + tmp = local_clock(); + do_div(tmp, 1e6); + local_ms1 = (UINT32)tmp; + + if (wmt_status == 0) { /* 0 is okay */ + if (rx_len >= 2) { + rx0 = rx_buf[0]; /* fw_status, 0 is okay */ + rx1 = rx_buf[1]; /* opcode */ + } + } + + if (wmt_status != 0 || rx0 != 0) { + /* Fail due to WMT fail or FW not support, + * bypass the following operations + */ + GPS2_WARN_FUNC("GPS2_hw_suspend_ctrl %d: st=%d, rx_len=%u ([0]=%u, [1]=%u), ms0=%u, ms1=%u", + to_suspend, wmt_status, rx_len, rx0, rx1, local_ms0, local_ms1); + return -1; + } + + /* Okay */ + GPS2_INFO_FUNC("GPS2_hw_suspend_ctrl %d: st=%d, rx_len=%u ([0]=%u, [1]=%u), ms0=%u, ms1=%u", + to_suspend, wmt_status, rx_len, rx0, rx1, local_ms0, local_ms1); + return 0; +} + +static int GPS2_hw_suspend(void) +{ + MTK_WCN_BOOL wmt_okay; + enum gps_ctrl_status_enum gps_status; + + gps_status = g_gps2_ctrl_status; + if (gps_status == GPS_OPENED) { + if (GPS2_hw_suspend_ctrl(true) != 0) + return -EINVAL; /* Stands for not support */ + + wmt_okay = mtk_wmt_gps_l5_suspend_ctrl(MTK_WCN_BOOL_TRUE); + if (!wmt_okay) + GPS2_WARN_FUNC("mtk_wmt_gps_l5_suspend_ctrl(1), is_ok = %d", wmt_okay); + + /* register event cb will clear GPS STP buffer */ + mtk_wcn_stp_register_event_cb(GPSL5_TASK_INDX, 0x0); + GPS2_DBG_FUNC("mtk_wcn_stp_register_event_cb to null"); + + /* No need to clear the flag2 due to it just a flag2 and not stands for has data + * flag2 = 0; + * + * Keep msgcb due to GPS still need to recevice reset event under HW suspend mode + * mtk_wcn_wmt_msgcb_unreg(WMTDRV_TYPE_GPSL5); + */ + + GPS_reference_count(HANDLE_DESENSE, false, GPS_USER2); + gps2_hold_wake_lock(0); + GPS2_WARN_FUNC("gps2_hold_wake_lock(0)\n"); + + GPS2_ctrl_status_change_from_to(GPS_OPENED, GPS_SUSPENDED); + } else + GPS2_WARN_FUNC("GPS2_hw_suspend(): status %d not match\n", gps_status); + + return 0; +} + +static int GPS2_hw_resume(void) +{ + MTK_WCN_BOOL wmt_okay; + enum gps_ctrl_status_enum gps_status; + + gps_status = g_gps2_ctrl_status; + if (gps_status == GPS_SUSPENDED) { + GPS_reference_count(HANDLE_DESENSE, true, GPS_USER2); + gps2_hold_wake_lock(1); + GPS2_WARN_FUNC("gps2_hold_wake_lock(1)\n"); + + wmt_okay = mtk_wmt_gps_l5_suspend_ctrl(MTK_WCN_BOOL_FALSE); + if (!wmt_okay) + GPS2_WARN_FUNC("mtk_wmt_gps_l5_suspend_ctrl(0), is_ok = %d", wmt_okay); + + if (GPS2_hw_suspend_ctrl(false) != 0) + return -EINVAL; /* Stands for not support */ + + mtk_wcn_stp_register_event_cb(GPSL5_TASK_INDX, GPS2_event_cb); + GPS2_ctrl_status_change_from_to(GPS_SUSPENDED, GPS_OPENED); + } else + GPS2_WARN_FUNC("GPS2_hw_resume(): status %d not match\n", gps_status); + + return 0; +} +#endif /* GPS_HW_SUSPEND_SUPPORT */ + +#endif /* GPS_FWCTL_SUPPORT */ + +/* block until wmt reset happen or GPS_close */ +static int GPS2_listen_wmt_rst(void) +{ + long val = 0; + + rst_listening_flag2 = 1; + while (!rst_happened_or_gps_close_flag2) { + val = wait_event_interruptible(GPS2_rst_wq, rst_happened_or_gps_close_flag2); + + GPS2_WARN_FUNC("GPS2_listen_wmt_rst(): val = %ld, cond = %d, rstflag2 = %d, status = %d\n", + val, rst_happened_or_gps_close_flag2, rstflag2, g_gps2_ctrl_status); + + /* if we are signaled */ + if (val) { + rst_listening_flag2 = 0; + return val; + } + } + + rst_listening_flag2 = 0; + return 0; +} + +/* int GPS_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) */ +long GPS2_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + int retval = 0; + #if 0 + ENUM_WMTHWVER_TYPE_T hw_ver_sym = WMTHWVER_INVALID; + #endif + UINT32 hw_version = 0; + UINT32 fw_version = 0; + UINT32 gps_lna_pin = 0; + + pr_info("GPS2_ioctl(): cmd (%d)\n", cmd); + + switch (cmd) { + case 0: /* enable/disable STP */ + GPS2_DBG_FUNC("GPS_ioctl(): disable STP control from GPS2 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 */ + GPS2_DBG_FUNC("GPS2_ioctl(): disable raw data from GPS2 dev\n"); + retval = -EINVAL; + break; + + #if 0 + case COMBO_IOC_GPS2_HWVER: + /*get combo hw version */ + hw_ver_sym = mtk_wcn_wmt_hwver_get(); + + GPS2_DBG_FUNC("GPS_ioctl(): get hw version = %d, sizeof(hw_ver_sym) = %zd\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; + #endif + case COMBO_IOC_GPS2_IC_HW_VERSION: + /*get combo hw version from ic, without wmt mapping */ + hw_version = mtk_wcn_wmt_ic_info_get(WMTCHIN_HWVER); + + GPS2_DBG_FUNC("GPS2_ioctl(): get hw version = 0x%x\n", hw_version); + if (copy_to_user((int __user *)arg, &hw_version, sizeof(hw_version))) + retval = -EFAULT; + + break; + + case COMBO_IOC_GPS2_IC_FW_VERSION: + /*get combo fw version from ic, without wmt mapping */ + fw_version = mtk_wcn_wmt_ic_info_get(WMTCHIN_FWVER); + + GPS2_DBG_FUNC("GPS2_ioctl(): get fw version = 0x%x\n", fw_version); + if (copy_to_user((int __user *)arg, &fw_version, sizeof(fw_version))) + retval = -EFAULT; + + break; + case COMBO_IOC_RTC_FLAG2: + + retval = rtc_GPS2_low_power_detected(); + + GPS2_DBG_FUNC("low power flag2 (%d)\n", retval); + break; + case COMBO_IOC_CO_CLOCK_FLAG2: +#if SOC_CO_CLOCK_FLAG + retval = mtk_wcn_wmt_co_clock_flag_get(); +#endif + GPS2_DBG_FUNC("GPS co_clock_flag (%d)\n", retval); + break; + case COMBO_IOC_D1_EFUSE_GET2: +#if defined(CONFIG_MACH_MT6735) + do { + char *addr = ioremap(0x10206198, 0x4); + + retval = *(unsigned int *)addr; + GPS2_DBG_FUNC("D1 efuse (0x%x)\n", retval); + iounmap(addr); + } while (0); +#elif defined(CONFIG_MACH_MT6763) + do { + char *addr = ioremap(0x11f10048, 0x4); + + retval = *(unsigned int *)addr; + GPS2_DBG_FUNC("6763 efuse (0x%x)\n", retval); + iounmap(addr); + } while (0); +#else + GPS2_ERR_FUNC("Read Efuse not supported in this platform\n"); +#endif + break; + + case COMBO_IOC_TRIGGER_WMT_ASSERT2: + /* Trigger FW assert for debug */ + GPS2_INFO_FUNC("%s: Host trigger FW assert......, reason:%lu\n", __func__, arg); + retval = mtk_wcn_wmt_assert(WMTDRV_TYPE_GPSL5, arg); + if (retval == MTK_WCN_BOOL_TRUE) { + GPS2_INFO_FUNC("Host trigger FW assert succeed\n"); + retval = 0; + } else { + GPS2_ERR_FUNC("Host trigger FW assert Failed\n"); + retval = (-EBUSY); + } + break; + case COMBO_IOC_WMT_STATUS2: + if (rstflag2 == 1) { + /* chip resetting */ + retval = -888; + } else if (rstflag2 == 2) { + /* chip reset end */ + retval = -889; + /* + * rstflag2 = 0 is cleared by GPS_open or GPS_close, + * no need to clear it here + */ + } else { + /* normal */ + retval = 0; + } + GPS2_DBG_FUNC("rstflag2(%d), retval(%d)\n", rstflag2, retval); + break; + case COMBO_IOC_TAKE_GPS2_WAKELOCK: + GPS2_INFO_FUNC("Ioctl to take gps2 wakelock\n"); + gps2_hold_wake_lock(1); + if (wake_lock_acquired2 == 1) + retval = 0; + else + retval = -EAGAIN; + break; + case COMBO_IOC_GIVE_GPS2_WAKELOCK: + GPS2_INFO_FUNC("Ioctl to give gps2 wakelock\n"); + gps2_hold_wake_lock(0); + if (wake_lock_acquired2 == 0) + retval = 0; + else + retval = -EAGAIN; + break; + +#ifdef GPS_HW_SUSPEND_SUPPORT + case COMBO_IOC_GPS2_HW_SUSPEND: + GPS2_INFO_FUNC("COMBO_IOC_GPS2_HW_SUSPEND\n"); + retval = GPS2_hw_suspend(); + break; + case COMBO_IOC_GPS2_HW_RESUME: + GPS2_INFO_FUNC("COMBO_IOC_GPS2_HW_RESUME\n"); + retval = GPS2_hw_resume(); + break; +#endif /* GPS_HW_SUSPEND_SUPPORT */ + + case COMBO_IOC_GPS2_LISTEN_RST_EVT: + GPS2_INFO_FUNC("COMBO_IOC_GPS2_LISTEN_RST_EVT\n"); + retval = GPS2_listen_wmt_rst(); + break; + + case COMBO_IOC_GET_GPS2_LNA_PIN: + gps_lna_pin = mtk_wmt_get_gps_lna_pin_num(); + GPS2_DBG_FUNC("GPS2_ioctl(): get gps lna pin = %d\n", gps_lna_pin); + if (copy_to_user((int __user *)arg, &gps_lna_pin, sizeof(gps_lna_pin))) + retval = -EFAULT; + break; + default: + retval = -EFAULT; + GPS2_DBG_FUNC("GPS2_ioctl(): unknown cmd (%d)\n", cmd); + break; + } + +/*OUT:*/ + return retval; +} + +long GPS2_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + long ret; + + pr_info("%s: cmd (%d)\n", __func__, cmd); + ret = GPS2_unlocked_ioctl(filp, cmd, arg); + pr_info("%s: cmd (%d)\n", __func__, cmd); + return ret; +} + +static void gps2_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; + + GPS2_DBG_FUNC("sizeof(ENUM_WMTRSTMSG_TYPE_T) = %zd\n", sizeof(ENUM_WMTRSTMSG_TYPE_T)); + if (sz <= sizeof(ENUM_WMTRSTMSG_TYPE_T)) { + memcpy((char *)&rst_msg, (char *)buf, sz); + GPS2_DBG_FUNC("src = %d, dst = %d, type = %d, buf = 0x%x sz = %d, max = %d\n", src, + dst, type, rst_msg, sz, WMTRSTMSG_RESET_MAX); + + if ((src == WMTDRV_TYPE_WMT) && (dst == WMTDRV_TYPE_GPSL5) && (type == WMTMSG_TYPE_RESET)) { + switch (rst_msg) { + case WMTRSTMSG_RESET_START: + GPS2_INFO_FUNC("Whole chip reset start!\n"); + rstflag2 = 1; +#ifdef GPS_FWCTL_SUPPORT + down(&fwctl_mtx); + GPS_reference_count(FGGPS_FWCTL_EADY, false, GPS_USER2); + up(&fwctl_mtx); +#endif + GPS2_ctrl_status_change_to(GPS_RESET_START); + break; + case WMTRSTMSG_RESET_END: + case WMTRSTMSG_RESET_END_FAIL: + if (rst_msg == WMTRSTMSG_RESET_END) + GPS2_INFO_FUNC("Whole chip reset end!\n"); + else + GPS2_INFO_FUNC("Whole chip reset fail!\n"); + rstflag2 = 2; + + GPS2_ctrl_status_change_to(GPS_RESET_DONE); + break; + default: + break; + } + } + } else { + /*message format invalid */ + GPS2_WARN_FUNC("Invalid message format!\n"); + } +} + +static int GPS2_open(struct inode *inode, struct file *file) +{ + pr_info("%s: major %d minor %d (pid %d)\n", __func__, imajor(inode), iminor(inode), current->pid); + if (current->pid == 1) + return 0; + if (rstflag2 == 1) { + GPS2_WARN_FUNC("whole chip resetting...\n"); + return -EPERM; + } + +#if 1 /* GeorgeKuo: turn on function before check stp ready */ + /* turn on BT */ +#ifdef CONFIG_GPS_CTRL_LNA_SUPPORT + gps_lna_pin_ctrl(GPS_DATA_LINK_ID1, true, false); +#endif + if (mtk_wcn_wmt_func_on(WMTDRV_TYPE_GPSL5) == MTK_WCN_BOOL_FALSE) { + GPS2_WARN_FUNC("WMT turn on GPS2 fail!\n"); + return -ENODEV; + } + + mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_GPSL5, gps2_cdev_rst_cb); + GPS2_WARN_FUNC("WMT turn on GPS2 OK!\n"); + rstflag2 = 0; + +#endif + + if (mtk_wcn_stp_is_ready()) { +#if 0 + if (mtk_wcn_wmt_func_on(WMTDRV_TYPE_GPSL5) == MTK_WCN_BOOL_FALSE) { + GPS2_WARN_FUNC("WMT turn on GPS fail!\n"); + return -ENODEV; + } + GPS2_DBG_FUNC("WMT turn on GPS2 OK!\n"); +#endif + mtk_wcn_stp_register_event_cb(GPSL5_TASK_INDX, GPS2_event_cb); + } else { + GPS2_ERR_FUNC("STP is not ready, Cannot open GPS2 Devices\n\r"); + + /*return error code */ + return -ENODEV; + } + gps2_hold_wake_lock(1); + GPS2_WARN_FUNC("gps2_hold_wake_lock(1)\n"); + + GPS_reference_count(HANDLE_DESENSE, true, GPS_USER2); + +#ifdef GPS_FWCTL_SUPPORT + down(&fwctl_mtx); + GPS_reference_count(FGGPS_FWCTL_EADY, true, GPS_USER2); +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + if (fgGps_fwlog_on) { + /* GPS fw clear log on flag2 when GPS on, no need to send it if log setting is off */ + GPS_reference_count(FWLOG_CTRL_INNER, fgGps_fwlog_on, GPS_USER2); + } +#endif + up(&fwctl_mtx); +#endif /* GPS_FWCTL_SUPPORT */ + + rst_happened_or_gps_close_flag2 = 0; + GPS2_ctrl_status_change_to(GPS_OPENED); + return 0; +} + +static int GPS2_close(struct inode *inode, struct file *file) +{ + int ret = 0; + + pr_info("%s: major %d minor %d (pid %d)\n", __func__, imajor(inode), iminor(inode), current->pid); + if (current->pid == 1) + return 0; + + if (rstflag2 == 1) { + GPS2_WARN_FUNC("whole chip resetting...\n"); + ret = -EPERM; + goto _out; + } + +#ifdef GPS_FWCTL_SUPPORT + down(&fwctl_mtx); + GPS_reference_count(FGGPS_FWCTL_EADY, false, GPS_USER2); + up(&fwctl_mtx); +#endif +#ifdef CONFIG_GPS_CTRL_LNA_SUPPORT + gps_lna_pin_ctrl(GPS_DATA_LINK_ID1, false, false); +#endif + if (mtk_wcn_wmt_func_off(WMTDRV_TYPE_GPSL5) == MTK_WCN_BOOL_FALSE) { + GPS2_WARN_FUNC("WMT turn off GPS2 fail!\n"); + ret = -EIO; + goto _out; + } + + GPS2_WARN_FUNC("WMT turn off GPS2 OK!\n"); + rstflag2 = 0; + /*Flush Rx Queue */ + mtk_wcn_stp_register_event_cb(GPSL5_TASK_INDX, 0x0); /* unregister event callback function */ + mtk_wcn_wmt_msgcb_unreg(WMTDRV_TYPE_GPSL5); + +_out: + gps2_hold_wake_lock(0); + GPS2_WARN_FUNC("gps2_hold_wake_lock(0)\n"); + + GPS_reference_count(HANDLE_DESENSE, false, GPS_USER2); + + GPS2_ctrl_status_change_to(GPS_CLOSED); + return ret; +} + +const struct file_operations GPS2_fops = { + .open = GPS2_open, + .release = GPS2_close, + .read = GPS2_read, + .write = GPS2_write, +/* .ioctl = GPS_ioctl */ + .unlocked_ioctl = GPS2_unlocked_ioctl, + .compat_ioctl = GPS2_compat_ioctl, +}; + +void GPS2_event_cb(void) +{ +/* pr_debug("GPS2_event_cb()\n");*/ + + flag2 = 1; + wake_up(&GPS2_wq); +} + From e473162e3c6e3e6962e1f4bff0896ba38a69212a Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 21:42:41 +0800 Subject: [PATCH 08/32] Add files via upload --- .../connectivity/conninfra/Android.mk | 27 + .../mediatek/connectivity/conninfra/Makefile | 186 ++ .../conninfra/base/include/msg_thread.h | 140 + .../conninfra/base/include/osal.h | 419 +++ .../conninfra/base/include/ring.h | 95 + .../connectivity/conninfra/base/msg_thread.c | 605 +++++ .../connectivity/conninfra/base/osal.c | 1644 ++++++++++++ .../connectivity/conninfra/base/ring.c | 151 ++ .../conninfra/conf/conninfra_conf.c | 635 +++++ .../conninfra/conf/include/conninfra_conf.h | 179 ++ .../conninfra/core/conninfra_core.c | 1806 +++++++++++++ .../conninfra/core/include/conninfra_core.h | 249 ++ .../conninfra/debug_utility/conninfra_dbg.c | 580 ++++ .../conninfra/debug_utility/conninfra_dbg.h | 14 + .../debug_utility/connsyslog/connsyslog.c | 1302 +++++++++ .../debug_utility/connsyslog/connsyslog.h | 60 + .../debug_utility/connsyslog/connsyslog_emi.h | 23 + .../debug_utility/connsyslog/log_ring.c | 141 + .../debug_utility/connsyslog/log_ring.h | 88 + .../platform/include/connsyslog_hw_config.h | 14 + .../connsyslog/platform/mt6885/mt6885.c | 35 + .../connsyslog/platform/mt6893/mt6893.c | 36 + .../debug_utility/connsyslog/ring_emi.c | 151 ++ .../debug_utility/connsyslog/ring_emi.h | 76 + .../debug_utility/coredump/conndump_netlink.c | 535 ++++ .../debug_utility/coredump/conndump_netlink.h | 35 + .../debug_utility/coredump/connsys_coredump.c | 1730 ++++++++++++ .../debug_utility/coredump/connsys_coredump.h | 63 + .../coredump/connsys_coredump_emi.h | 69 + .../include/connsys_coredump_hw_config.h | 24 + .../coredump/platform/mt6885/mt6885.c | 111 + .../coredump/platform/mt6893/mt6893.c | 111 + .../include/connsys_debug_utility.h | 36 + .../conninfra/drv_init/bluetooth_drv_init.c | 29 + .../conninfra/drv_init/conn_drv_init.c | 49 + .../conninfra/drv_init/fm_drv_init.c | 28 + .../conninfra/drv_init/gps_drv_init.c | 30 + .../drv_init/include/bluetooth_drv_init.h | 11 + .../drv_init/include/conn_drv_init.h | 9 + .../conninfra/drv_init/include/fm_drv_init.h | 11 + .../conninfra/drv_init/include/gps_drv_init.h | 10 + .../drv_init/include/wlan_drv_init.h | 16 + .../conninfra/drv_init/wlan_drv_init.c | 43 + .../conninfra/include/conninfra.h | 259 ++ .../connectivity/conninfra/init.conninfra.rc | 2 + .../conninfra/platform/clock_mng.c | 70 + .../conninfra/platform/consys_hw.c | 525 ++++ .../conninfra/platform/consys_reg_mng.c | 147 ++ .../connectivity/conninfra/platform/emi_mng.c | 147 ++ .../conninfra/platform/include/clock_mng.h | 71 + .../conninfra/platform/include/consys_hw.h | 244 ++ .../platform/include/consys_reg_base.h | 28 + .../platform/include/consys_reg_mng.h | 60 + .../platform/include/consys_reg_util.h | 137 + .../conninfra/platform/include/emi_mng.h | 98 + .../conninfra/platform/include/plat_def.h | 25 + .../conninfra/platform/include/pmic_mng.h | 107 + .../platform/mt6885/include/mt6885.h | 57 + .../mt6885/include/mt6885_consys_reg.h | 120 + .../mt6885/include/mt6885_consys_reg_offset.h | 318 +++ .../platform/mt6885/include/mt6885_emi.h | 76 + .../platform/mt6885/include/mt6885_pmic.h | 73 + .../platform/mt6885/include/mt6885_pos.h | 56 + .../conninfra/platform/mt6885/mt6885.c | 435 +++ .../platform/mt6885/mt6885_consys_reg.c | 799 ++++++ .../conninfra/platform/mt6885/mt6885_emi.c | 145 + .../conninfra/platform/mt6885/mt6885_pmic.c | 448 ++++ .../conninfra/platform/mt6885/mt6885_pos.c | 2352 +++++++++++++++++ .../platform/mt6893/include/mt6893.h | 45 + .../mt6893/include/mt6893_consys_reg.h | 107 + .../mt6893/include/mt6893_consys_reg_offset.h | 306 +++ .../platform/mt6893/include/mt6893_emi.h | 63 + .../platform/mt6893/include/mt6893_pmic.h | 59 + .../platform/mt6893/include/mt6893_pos.h | 43 + .../conninfra/platform/mt6893/mt6893.c | 445 ++++ .../platform/mt6893/mt6893_consys_reg.c | 783 ++++++ .../conninfra/platform/mt6893/mt6893_emi.c | 132 + .../conninfra/platform/mt6893/mt6893_pmic.c | 426 +++ .../conninfra/platform/mt6893/mt6893_pos.c | 2333 ++++++++++++++++ .../conninfra/platform/pmic_mng.c | 146 + .../connectivity/conninfra/src/conninfra.c | 316 +++ .../conninfra/src/conninfra_dev.c | 659 +++++ .../connectivity/conninfra/test/cal_test.c | 122 + .../conninfra/test/chip_rst_test.c | 144 + .../connectivity/conninfra/test/conf_test.c | 106 + .../conninfra/test/conninfra_core_test.c | 73 + .../conninfra/test/conninfra_test.c | 459 ++++ .../conninfra/test/connsyslog_test.c | 113 + .../connectivity/conninfra/test/dump_test.c | 290 ++ .../conninfra/test/include/cal_test.h | 74 + .../conninfra/test/include/chip_rst_test.h | 74 + .../conninfra/test/include/conf_test.h | 74 + .../test/include/conninfra_core_test.h | 76 + .../conninfra/test/include/conninfra_test.h | 78 + .../conninfra/test/include/connsyslog_test.h | 62 + .../conninfra/test/include/coredump_test.h | 61 + .../conninfra/test/include/mailbox_test.h | 71 + .../conninfra/test/include/msg_evt_test.h | 74 + .../conninfra/test/mailbox_test.c | 125 + .../conninfra/test/msg_evt_test.c | 152 ++ 100 files changed, 26496 insertions(+) create mode 100644 drivers/misc/mediatek/connectivity/conninfra/Android.mk create mode 100644 drivers/misc/mediatek/connectivity/conninfra/Makefile create mode 100644 drivers/misc/mediatek/connectivity/conninfra/base/include/msg_thread.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/base/include/osal.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/base/include/ring.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/base/msg_thread.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/base/osal.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/base/ring.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/conf/conninfra_conf.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/conf/include/conninfra_conf.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/core/conninfra_core.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/core/include/conninfra_core.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/debug_utility/conninfra_dbg.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/debug_utility/conninfra_dbg.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/connsyslog.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/connsyslog.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/connsyslog_emi.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/log_ring.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/log_ring.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/platform/include/connsyslog_hw_config.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/platform/mt6885/mt6885.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/platform/mt6893/mt6893.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/ring_emi.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/ring_emi.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/conndump_netlink.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/conndump_netlink.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/connsys_coredump.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/connsys_coredump.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/connsys_coredump_emi.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/platform/include/connsys_coredump_hw_config.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/platform/mt6885/mt6885.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/platform/mt6893/mt6893.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/debug_utility/include/connsys_debug_utility.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/drv_init/bluetooth_drv_init.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/drv_init/conn_drv_init.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/drv_init/fm_drv_init.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/drv_init/gps_drv_init.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/drv_init/include/bluetooth_drv_init.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/drv_init/include/conn_drv_init.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/drv_init/include/fm_drv_init.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/drv_init/include/gps_drv_init.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/drv_init/include/wlan_drv_init.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/drv_init/wlan_drv_init.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/include/conninfra.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/init.conninfra.rc create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/clock_mng.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/consys_hw.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/consys_reg_mng.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/emi_mng.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/include/clock_mng.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/include/consys_hw.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/include/consys_reg_base.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/include/consys_reg_mng.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/include/consys_reg_util.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/include/emi_mng.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/include/plat_def.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/include/pmic_mng.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/include/mt6885.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/include/mt6885_consys_reg.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/include/mt6885_consys_reg_offset.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/include/mt6885_emi.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/include/mt6885_pmic.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/include/mt6885_pos.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/mt6885.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/mt6885_consys_reg.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/mt6885_emi.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/mt6885_pmic.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/mt6885_pos.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/include/mt6893.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/include/mt6893_consys_reg.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/include/mt6893_consys_reg_offset.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/include/mt6893_emi.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/include/mt6893_pmic.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/include/mt6893_pos.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/mt6893.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/mt6893_consys_reg.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/mt6893_emi.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/mt6893_pmic.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/mt6893_pos.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/platform/pmic_mng.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/src/conninfra.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/src/conninfra_dev.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/test/cal_test.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/test/chip_rst_test.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/test/conf_test.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/test/conninfra_core_test.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/test/conninfra_test.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/test/connsyslog_test.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/test/dump_test.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/test/include/cal_test.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/test/include/chip_rst_test.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/test/include/conf_test.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/test/include/conninfra_core_test.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/test/include/conninfra_test.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/test/include/connsyslog_test.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/test/include/coredump_test.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/test/include/mailbox_test.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/test/include/msg_evt_test.h create mode 100644 drivers/misc/mediatek/connectivity/conninfra/test/mailbox_test.c create mode 100644 drivers/misc/mediatek/connectivity/conninfra/test/msg_evt_test.c diff --git a/drivers/misc/mediatek/connectivity/conninfra/Android.mk b/drivers/misc/mediatek/connectivity/conninfra/Android.mk new file mode 100644 index 0000000000000..0cfa79d9ac37b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/Android.mk @@ -0,0 +1,27 @@ +LOCAL_PATH := $(call my-dir) + +ifneq ($(filter yes,$(sort $(MTK_WLAN_SUPPORT) $(MTK_BT_SUPPORT) $(MTK_GPS_SUPPORT) $(MTK_FM_SUPPORT))),) + +ifneq (true,$(strip $(TARGET_NO_KERNEL))) +ifneq ($(filter yes,$(MTK_COMBO_SUPPORT)),) + +include $(CLEAR_VARS) +LOCAL_MODULE := conninfra.ko +LOCAL_PROPRIETARY_MODULE := true +LOCAL_MODULE_OWNER := mtk + +LOCAL_INIT_RC := init.conninfra.rc +LOCAL_SRC_FILES := $(patsubst $(LOCAL_PATH)/%,%,$(shell find $(LOCAL_PATH) -type f -name '*.[cho]')) Makefile +LOCAL_REQUIRED_MODULES := + +include $(MTK_KERNEL_MODULE) + +CONNINFRA_OPTS := TARGET_BOARD_PLATFORM_CONNINFRA=$(TARGET_BOARD_PLATFORM) +$(linked_module): OPTS += $(CONNINFRA_OPTS) + +else + $(warning wmt_drv-MTK_COMBO_SUPPORT: [$(MTK_COMBO_SUPPORT)]) +endif +endif + +endif diff --git a/drivers/misc/mediatek/connectivity/conninfra/Makefile b/drivers/misc/mediatek/connectivity/conninfra/Makefile new file mode 100644 index 0000000000000..07bfde909a442 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/Makefile @@ -0,0 +1,186 @@ +MTK_PLATFORM := $(subst ",,$(CONFIG_MTK_PLATFORM)) +############################################################################### +# Necessary Check + +ifneq ($(KERNEL_OUT),) + ccflags-y += -imacros $(KERNEL_OUT)/include/generated/autoconf.h +endif + +#ifeq ($(CONFIG_MTK_COMBO_CHIP),) +# $(error CONFIG_MTK_COMBO_CHIP not defined) +#endif + +#ifeq ($(TARGET_BUILD_VARIANT),$(filter $(TARGET_BUILD_VARIANT),userdebug user)) +# ldflags-y += -s +#endif + +# Force build fail on modpost warning +KBUILD_MODPOST_FAIL_ON_WARNINGS := y +############################################################################### + + +CONNSYS_PLATFORM := $(TARGET_BOARD_PLATFORM_CONNINFRA) + +ifeq ($(CONNSYS_PLATFORM),) +$(info $$CONFIG_MTK_COMBO_CHIP is [${CONFIG_MTK_COMBO_CHIP}]) +ifneq ($(CONFIG_MTK_COMBO_CHIP),) +# replace CONSYS_XXXX to mtXXXX +CONNINFRA_PLATFORM_ID := $(patsubst CONSYS_%,mt%,$(subst ",,$(CONFIG_MTK_COMBO_CHIP))) +$(info CONNINFRA_PLATFORM_ID is [${CONNINFRA_PLATFORM_ID}]) +CONNSYS_PLATFORM := $(CONNINFRA_PLATFORM_ID) +else +CONNSYS_PLATFORM := $(MTK_PLATFORM) +endif +endif +$(info $$CONNSYS_PLATFORM is [${CONNSYS_PLATFORM}]) + +#ccflags-y += -D MTK_WCN_REMOVE_KERNEL_MODULE +ifeq ($(CONFIG_ARM64), y) + ccflags-y += -D CONFIG_MTK_WCN_ARM64 +endif + +# Option for some ALPS specific feature, ex: AEE. +ccflags-y += -D CONNINFRA_PLAT_ALPS=1 + +ccflags-y += -D MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT +ccflags-y += -D MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE=1 + +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(CONNSYS_PLATFORM)/include +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(CONNSYS_PLATFORM)/include/mach +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/$(CONNSYS_PLATFORM) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include/clkbuf_v1 +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include/clkbuf_v1/$(CONNSYS_PLATFORM) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/eccci +ccflags-y += -I$(srctree)/drivers/misc/mediatek/eccci/$(CONNSYS_PLATFORM) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/eemcs +ccflags-y += -I$(srctree)/drivers/misc/mediatek/mach/$(CONNSYS_PLATFORM)/include/mach +ccflags-y += -I$(srctree)/drivers/misc/mediatek/emi/submodule +ccflags-y += -I$(srctree)/drivers/misc/mediatek/emi/$(CONNSYS_PLATFORM) +ccflags-y += -I$(srctree)/drivers/mmc/core +ccflags-y += -I$(srctree)/drivers/misc/mediatek/connectivity/common +ccflags-y += -I$(srctree)/drivers/misc/mediatek/pmic/include/ +############################################################################### + + +ccflags-y += -Werror +ccflags-y += -Wno-error=format +ccflags-y += -Wno-error=format-extra-args + +############################################################################### +MODULE_NAME := conninfra +ifeq ($(CONFIG_WLAN_DRV_BUILD_IN),y) +$(warning $(MODULE_NAME) build-in boot.img) +obj-y += $(MODULE_NAME).o +else +$(warning $(MODULE_NAME) is kernel module) +obj-m += $(MODULE_NAME).o +endif + +############################################################################### +# common_main +############################################################################### +ccflags-y += -I$(src)/include +ccflags-y += -I$(src)/base/include +ccflags-y += -I$(src)/core/include +ccflags-y += -I$(src)/conf/include +ccflags-y += -I$(src)/drv_init/include +ccflags-y += -I$(src)/platform/include +ccflags-y += -I$(src)/debug_utility +ccflags-y += -I$(src)/debug_utility/include +ccflags-y += -I$(src)/debug_utility/connsyslog +ccflags-y += -I$(src)/debug_utility/connsyslog/platform/include +ccflags-y += -I$(src)/debug_utility/coredump +ccflags-y += -I$(src)/debug_utility/coredump/platform/include + +# By Plaftfrom +ccflags-y += -I$(src)/platform/$(CONNSYS_PLATFORM)/include + +ifneq ($(TARGET_BUILD_VARIANT), user) + ccflags-y += -D CONNINFRA_DBG_SUPPORT=1 +else + ccflags-y += -D CONNINFRA_DBG_SUPPORT=0 +endif + +# Build mode option +ifeq ($(TARGET_BUILD_VARIANT),eng) + ccflags-y += -D CONNINFRA_PLAT_BUILD_MODE=1 +else ifeq ($(TARGET_BUILD_VARIANT),userdebug) + ccflags-y += -D CONNINFRA_PLAT_BUILD_MODE=2 +else ifeq ($(TARGET_BUILD_VARIANT),user) + ccflags-y += -D CONNINFRA_PLAT_BUILD_MODE=3 +else + $(info invalid $$TARGET_BUILD_VARIANT[${TARGET_BUILD_VARIANT}]) + ccflags-y += -D CONNINFRA_PLAT_BUILD_MODE=0 +endif + + +#ifeq ($(findstring evb, $(MTK_PROJECT)), evb) +#ccflags-y += -D CFG_WMT_EVB +#endif + +#ifneq ($(filter "CONSYS_%",$(CONFIG_MTK_COMBO_CHIP)),) +#$(MODULE_NAME)-objs += common_main/platform/$(CONNSYS_PLATFORM).o +#endif + +$(MODULE_NAME)-objs += base/ring.o +$(MODULE_NAME)-objs += base/osal.o +#$(MODULE_NAME)-objs += base/log.o +$(MODULE_NAME)-objs += base/msg_thread.o +$(MODULE_NAME)-objs += core/conninfra_core.o +$(MODULE_NAME)-objs += src/conninfra_dev.o +$(MODULE_NAME)-objs += src/conninfra.o +$(MODULE_NAME)-objs += conf/conninfra_conf.o +$(MODULE_NAME)-objs += platform/consys_hw.o +$(MODULE_NAME)-objs += platform/clock_mng.o +$(MODULE_NAME)-objs += platform/pmic_mng.o +$(MODULE_NAME)-objs += platform/emi_mng.o +$(MODULE_NAME)-objs += platform/consys_reg_mng.o + +$(MODULE_NAME)-objs += debug_utility/conninfra_dbg.o + +# By Plaftfrom +$(MODULE_NAME)-objs += platform/$(CONNSYS_PLATFORM)/$(CONNSYS_PLATFORM).o +$(MODULE_NAME)-objs += platform/$(CONNSYS_PLATFORM)/$(CONNSYS_PLATFORM)_pmic.o +$(MODULE_NAME)-objs += platform/$(CONNSYS_PLATFORM)/$(CONNSYS_PLATFORM)_emi.o +$(MODULE_NAME)-objs += platform/$(CONNSYS_PLATFORM)/$(CONNSYS_PLATFORM)_consys_reg.o +$(MODULE_NAME)-objs += platform/$(CONNSYS_PLATFORM)/$(CONNSYS_PLATFORM)_pos.o +#$(MODULE_NAME)-objs += platform/$(CONNSYS_PLATFORM)/$(CONNSYS_PLATFORM).o +#$(MODULE_NAME)-objs += platform/$(CONNSYS_PLATFORM)/$(CONNSYS_PLATFORM)_pmic.o +#$(MODULE_NAME)-objs += platform/$(CONNSYS_PLATFORM)/$(CONNSYS_PLATFORM)_clock.o + +# Debug utility +$(MODULE_NAME)-objs += debug_utility/connsyslog/ring_emi.o +$(MODULE_NAME)-objs += debug_utility/connsyslog/connsyslog.o +$(MODULE_NAME)-objs += debug_utility/connsyslog/platform/$(CONNSYS_PLATFORM)/$(CONNSYS_PLATFORM).o +$(MODULE_NAME)-objs += debug_utility/coredump/connsys_coredump.o +$(MODULE_NAME)-objs += debug_utility/coredump/conndump_netlink.o +$(MODULE_NAME)-objs += debug_utility/coredump/platform/$(CONNSYS_PLATFORM)/$(CONNSYS_PLATFORM).o + +# Drv init +$(MODULE_NAME)-objs += drv_init/bluetooth_drv_init.o +$(MODULE_NAME)-objs += drv_init/conn_drv_init.o +$(MODULE_NAME)-objs += drv_init/fm_drv_init.o +$(MODULE_NAME)-objs += drv_init/gps_drv_init.o +$(MODULE_NAME)-objs += drv_init/wlan_drv_init.o + +############################################################################### +# test +############################################################################### +ifneq ($(TARGET_BUILD_VARIANT), user) +ccflags-y += -D CFG_CONNINFRA_UT_SUPPORT + +ccflags-y += -I$(src)/test/include +$(MODULE_NAME)-objs += test/conninfra_core_test.o +$(MODULE_NAME)-objs += test/conf_test.o +$(MODULE_NAME)-objs += test/cal_test.o +$(MODULE_NAME)-objs += test/msg_evt_test.o +$(MODULE_NAME)-objs += test/chip_rst_test.o +$(MODULE_NAME)-objs += test/conninfra_test.o +$(MODULE_NAME)-objs += test/mailbox_test.o +$(MODULE_NAME)-objs += test/connsyslog_test.o +$(MODULE_NAME)-objs += test/dump_test.o +endif + diff --git a/drivers/misc/mediatek/connectivity/conninfra/base/include/msg_thread.h b/drivers/misc/mediatek/connectivity/conninfra/base/include/msg_thread.h new file mode 100644 index 0000000000000..127272436f0c1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/base/include/msg_thread.h @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _BASE_MSG_THREAD_H_ +#define _BASE_MSG_THREAD_H_ + +#include "osal.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + + +#define MSG_THREAD_OP_DATA_SIZE 8 +#define MSG_THREAD_OP_BUF_SIZE 64 + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + +struct msg_op_data { + unsigned int op_id; /* Event ID */ + unsigned int info_bit; /* Reserved */ + size_t op_data[MSG_THREAD_OP_DATA_SIZE]; /* OP Data */ +}; + +struct msg_op { + struct msg_op_data op; + OSAL_SIGNAL signal; + int result; + atomic_t ref_count; +}; + + +struct msg_op_q { + OSAL_SLEEPABLE_LOCK lock; + unsigned int write; + unsigned int read; + unsigned int size; + struct msg_op *queue[MSG_THREAD_OP_BUF_SIZE]; +}; + +typedef OSAL_OP_DAT msg_evt_op; +typedef int(*msg_opid_func) (struct msg_op_data *); + +struct msg_thread_ctx { + OSAL_THREAD thread; /* core thread */ + OSAL_EVENT evt; + + struct msg_op_q free_op_q; /* free op queue */ + struct msg_op_q active_op_q; /* active op queue */ + struct msg_op op_q_inst[MSG_THREAD_OP_BUF_SIZE]; /* real op instances */ + struct msg_op *cur_op; /* current op */ + + int op_func_size; + const msg_opid_func *op_func; + + struct osal_op_history op_history; +}; + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +#define MSG_OP_TIMEOUT 20000 + +int msg_thread_init(struct msg_thread_ctx *ctx, const char *name, + const msg_opid_func *func, int op_size); +int msg_thread_deinit(struct msg_thread_ctx *ctx); + +/* timeout: + * 0: default value (by MSG_OP_TIMEOUT define) + * >0: cutom timeout (ms) + */ +int msg_thread_send(struct msg_thread_ctx *ctx, int opid); +int msg_thread_send_1(struct msg_thread_ctx *ctx, int opid, + size_t param1); +int msg_thread_send_2(struct msg_thread_ctx *ctx, int opid, + size_t param1, size_t param2); + +int msg_thread_send_wait(struct msg_thread_ctx *ctx, int opid, + int timeout); +int msg_thread_send_wait_1(struct msg_thread_ctx *ctx, int opid, + int timeout, size_t param1); +int msg_thread_send_wait_2(struct msg_thread_ctx *ctx, int opid, + int timeout, size_t param1, size_t param2); +int msg_thread_send_wait_3(struct msg_thread_ctx *ctx, int opid, int timeout, size_t param1, + size_t param2,size_t param3); + + +/******************************************************************************* +* 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 /* _BASE_MSG_THREAD_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/base/include/osal.h b/drivers/misc/mediatek/connectivity/conninfra/base/include/osal.h new file mode 100644 index 0000000000000..3493dd6fb61ff --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/base/include/osal.h @@ -0,0 +1,419 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + + +/*! \file + * \brief Declaration of library functions + * Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. + */ + +#ifndef _OSAL_H_ +#define _OSAL_H_ + +#include +#include +#include +#include +#include "ring.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 + +#ifndef MTK_CONN_BOOL_TRUE +#define MTK_CONN_BOOL_FALSE ((MTK_CONN_BOOL) 0) +#define MTK_CONN_BOOL_TRUE ((MTK_CONN_BOOL) 1) +#endif + +#define _osal_inline_ inline + +#define MAX_THREAD_NAME_LEN 16 +#define MAX_HISTORY_NAME_LEN 16 +#define OSAL_OP_BUF_SIZE 64 + + +#if (defined(CONFIG_MTK_GMO_RAM_OPTIMIZE) && !defined(CONFIG_MTK_ENG_BUILD)) +#define OSAL_OP_DATA_SIZE 8 +#else +#define OSAL_OP_DATA_SIZE 32 +#endif + +#define DBG_LOG_STR_SIZE 256 + +#define osal_sizeof(x) sizeof(x) + +#define osal_array_size(x) ARRAY_SIZE(x) + +#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 GET_BIT_MASK(value, mask) ((value) & (mask)) +#define SET_BIT_MASK(pdest, value, mask) (*(pdest) = (GET_BIT_MASK(*(pdest), ~(mask)) | GET_BIT_MASK(value, mask))) +#define GET_BIT_RANGE(data, end, begin) ((data) & GENMASK(end, begin)) +#define SET_BIT_RANGE(pdest, data, end, begin) (SET_BIT_MASK(pdest, data, GENMASK(end, begin))) + +#define RB_LATEST(prb) ((prb)->write - 1) +#define RB_SIZE(prb) ((prb)->size) +#define RB_MASK(prb) (RB_SIZE(prb) - 1) +#define RB_COUNT(prb) ((prb)->write - (prb)->read) +#define RB_FULL(prb) (RB_COUNT(prb) >= RB_SIZE(prb)) +#define RB_EMPTY(prb) ((prb)->write == (prb)->read) + +#define RB_INIT(prb, qsize) \ +do { \ + (prb)->read = (prb)->write = 0; \ + (prb)->size = (qsize); \ +} while (0) + +#define RB_PUT(prb, value) \ +do { \ + if (!RB_FULL(prb)) { \ + (prb)->queue[(prb)->write & RB_MASK(prb)] = value; \ + ++((prb)->write); \ + } \ + else { \ + pr_warn("RB is full!"); \ + } \ +} while (0) + +#define RB_GET(prb, value) \ +do { \ + if (!RB_EMPTY(prb)) { \ + value = (prb)->queue[(prb)->read & RB_MASK(prb)]; \ + ++((prb)->read); \ + if (RB_EMPTY(prb)) { \ + (prb)->read = (prb)->write = 0; \ + } \ + } \ + else { \ + value = NULL; \ + pr_warn("RB is empty!"); \ + } \ +} while (0) + +#define RB_GET_LATEST(prb, value) \ +do { \ + if (!RB_EMPTY(prb)) { \ + value = (prb)->queue[RB_LATEST(prb) & RB_MASK(prb)]; \ + if (RB_EMPTY(prb)) { \ + (prb)->read = (prb)->write = 0; \ + } \ + } \ + else { \ + value = NULL; \ + } \ +} while (0) + + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef int MTK_CONN_BOOL; + +typedef void(*P_TIMEOUT_HANDLER) (unsigned long); +typedef int(*P_COND) (void *); + +typedef struct _OSAL_TIMER_ { + struct timer_list timer; + P_TIMEOUT_HANDLER timeoutHandler; + unsigned long timeroutHandlerData; +} OSAL_TIMER, *P_OSAL_TIMER; + +typedef struct _OSAL_UNSLEEPABLE_LOCK_ { + spinlock_t lock; + unsigned long flag; +} OSAL_UNSLEEPABLE_LOCK, *P_OSAL_UNSLEEPABLE_LOCK; + +typedef struct _OSAL_SLEEPABLE_LOCK_ { + struct mutex lock; +} OSAL_SLEEPABLE_LOCK, *P_OSAL_SLEEPABLE_LOCK; + +typedef struct _OSAL_SIGNAL_ { + struct completion comp; + unsigned int timeoutValue; + unsigned int timeoutExtension; /* max number of timeout caused by thread not able to acquire CPU */ +} OSAL_SIGNAL, *P_OSAL_SIGNAL; + +typedef struct _OSAL_EVENT_ { + wait_queue_head_t waitQueue; + unsigned int timeoutValue; + int waitFlag; + +} OSAL_EVENT, *P_OSAL_EVENT; + +/* Data collected from sched_entity and sched_statistics */ +typedef struct _OSAL_THREAD_SCHEDSTATS_ { + unsigned long long time; /* when marked: the profiling start time(ms), when unmarked: total duration(ms) */ + unsigned long long exec; /* time spent in exec (sum_exec_runtime) */ + unsigned long long runnable; /* time spent in run-queue while not being scheduled (wait_sum) */ + unsigned long long iowait; /* time spent waiting for I/O (iowait_sum) */ +} OSAL_THREAD_SCHEDSTATS, *P_OSAL_THREAD_SCHEDSTATS; + +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 */ + int (*FifoInit)(struct _OSAL_FIFO_ *pFifo, unsigned char *buf, unsigned int); + int (*FifoDeInit)(struct _OSAL_FIFO_ *pFifo); + int (*FifoReset)(struct _OSAL_FIFO_ *pFifo); + int (*FifoSz)(struct _OSAL_FIFO_ *pFifo); + int (*FifoAvailSz)(struct _OSAL_FIFO_ *pFifo); + int (*FifoLen)(struct _OSAL_FIFO_ *pFifo); + int (*FifoIsEmpty)(struct _OSAL_FIFO_ *pFifo); + int (*FifoIsFull)(struct _OSAL_FIFO_ *pFifo); + int (*FifoDataIn)(struct _OSAL_FIFO_ *pFifo, const void *buf, unsigned int len); + int (*FifoDataOut)(struct _OSAL_FIFO_ *pFifo, void *buf, unsigned int len); +} OSAL_FIFO, *P_OSAL_FIFO; + +typedef struct firmware osal_firmware; + +typedef struct _OSAL_OP_DAT { + unsigned int opId; /* Event ID */ + unsigned int u4InfoBit; /* Reserved */ + size_t au4OpData[OSAL_OP_DATA_SIZE]; /* OP Data */ +} OSAL_OP_DAT, *P_OSAL_OP_DAT; + +typedef struct _OSAL_LXOP_ { + OSAL_OP_DAT op; + OSAL_SIGNAL signal; + int result; + atomic_t ref_count; +} OSAL_OP, *P_OSAL_OP; + +typedef struct _OSAL_LXOP_Q { + OSAL_SLEEPABLE_LOCK sLock; + unsigned int write; + unsigned int read; + unsigned int size; + P_OSAL_OP queue[OSAL_OP_BUF_SIZE]; +} OSAL_OP_Q, *P_OSAL_OP_Q; + +typedef struct _OSAL_BIT_OP_VAR_ { + unsigned long data; + OSAL_UNSLEEPABLE_LOCK opLock; +} OSAL_BIT_OP_VAR, *P_OSAL_BIT_OP_VAR; + +typedef unsigned int (*P_OSAL_EVENT_CHECKER) (P_OSAL_THREAD pThread); + +struct osal_op_history_entry { + void *opbuf_address; + unsigned int op_id; + unsigned int opbuf_ref_count; + unsigned int op_info_bit; + size_t param_0; + size_t param_1; + size_t param_2; + size_t param_3; + unsigned long long ts; + unsigned long usec; +}; + +struct osal_op_history { + struct ring ring_buffer; + struct osal_op_history_entry *queue; + spinlock_t lock; + struct ring dump_ring_buffer; + struct work_struct dump_work; + unsigned char name[MAX_HISTORY_NAME_LEN]; +}; + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + +unsigned int osal_strlen(const char *str); +int osal_strcmp(const char *dst, const char *src); +int osal_strncmp(const char *dst, const char *src, unsigned int len); +char *osal_strcpy(char *dst, const char *src); +char *osal_strncpy(char *dst, const char *src, unsigned int len); +char *osal_strcat(char *dst, const char *src); +char *osal_strncat(char *dst, const char *src, unsigned int len); +char *osal_strchr(const char *str, unsigned char c); +char *osal_strsep(char **str, const char *c); +int osal_strtol(const char *str, unsigned int adecimal, long *res); +char *osal_strstr(char *str1, const char *str2); +char *osal_strnstr(char *str1, const char *str2, int n); + +void osal_bug_on(unsigned int val); + +int osal_snprintf(char *buf, unsigned int len, const char *fmt, ...); + +int osal_sprintf(char *str, const char *format, ...); +void *osal_malloc(unsigned int size); +void osal_free(const void *dst); +void *osal_memset(void *buf, int i, unsigned int len); +void *osal_memcpy(void *dst, const void *src, unsigned int len); +void osal_memcpy_fromio(void *dst, const void *src, unsigned int len); +void osal_memcpy_toio(void *dst, const void *src, unsigned int len); +int osal_memcmp(const void *buf1, const void *buf2, unsigned int len); + +unsigned short osal_crc16(const unsigned char *buffer, const unsigned int length); +void osal_thread_show_stack(P_OSAL_THREAD pThread); + +int osal_sleep_ms(unsigned int ms); +int osal_udelay(unsigned int us); +int osal_usleep_range(unsigned long min, unsigned long max); +int osal_timer_create(P_OSAL_TIMER); +int osal_timer_start(P_OSAL_TIMER, unsigned int); +int osal_timer_stop(P_OSAL_TIMER); +int osal_timer_stop_sync(P_OSAL_TIMER pTimer); +int osal_timer_modify(P_OSAL_TIMER, unsigned int); +int osal_timer_delete(P_OSAL_TIMER); + +int osal_fifo_init(P_OSAL_FIFO pFifo, unsigned char *buffer, unsigned int size); +void osal_fifo_deinit(P_OSAL_FIFO pFifo); +int osal_fifo_reset(P_OSAL_FIFO pFifo); +unsigned int osal_fifo_in(P_OSAL_FIFO pFifo, unsigned char *buffer, + unsigned int size); +unsigned int osal_fifo_out(P_OSAL_FIFO pFifo, unsigned char *buffer, + unsigned int size); +unsigned int osal_fifo_len(P_OSAL_FIFO pFifo); +unsigned int osal_fifo_sz(P_OSAL_FIFO pFifo); +unsigned int osal_fifo_avail(P_OSAL_FIFO pFifo); +unsigned int osal_fifo_is_empty(P_OSAL_FIFO pFifo); +unsigned int osal_fifo_is_full(P_OSAL_FIFO pFifo); + +#if defined(CONFIG_PROVE_LOCKING) +#define osal_unsleepable_lock_init(l) { spin_lock_init(&((l)->lock)); } +#else +int osal_unsleepable_lock_init(P_OSAL_UNSLEEPABLE_LOCK); +#endif +int osal_lock_unsleepable_lock(P_OSAL_UNSLEEPABLE_LOCK); +int osal_unlock_unsleepable_lock(P_OSAL_UNSLEEPABLE_LOCK); +int osal_unsleepable_lock_deinit(P_OSAL_UNSLEEPABLE_LOCK); + +#if defined(CONFIG_PROVE_LOCKING) +#define osal_sleepable_lock_init(l) { mutex_init(&((l)->lock)); } +#else +int osal_sleepable_lock_init(P_OSAL_SLEEPABLE_LOCK); +#endif +int osal_lock_sleepable_lock(P_OSAL_SLEEPABLE_LOCK); +int osal_unlock_sleepable_lock(P_OSAL_SLEEPABLE_LOCK); +int osal_trylock_sleepable_lock(P_OSAL_SLEEPABLE_LOCK); +int osal_sleepable_lock_deinit(P_OSAL_SLEEPABLE_LOCK); + +int osal_signal_init(P_OSAL_SIGNAL); +int osal_wait_for_signal(P_OSAL_SIGNAL); +int osal_wait_for_signal_timeout(P_OSAL_SIGNAL, P_OSAL_THREAD); +int osal_raise_signal(P_OSAL_SIGNAL); +int osal_signal_active_state(P_OSAL_SIGNAL pSignal); +int osal_signal_deinit(P_OSAL_SIGNAL); + +int osal_event_init(P_OSAL_EVENT); +int osal_wait_for_event(P_OSAL_EVENT, P_COND, void*); +int osal_wait_for_event_timeout(P_OSAL_EVENT, P_COND, void*); +extern int osal_trigger_event(P_OSAL_EVENT); + +int osal_event_deinit(P_OSAL_EVENT); +long osal_wait_for_event_bit_set(P_OSAL_EVENT pEvent, unsigned long *pState, unsigned int bitOffset); +long osal_wait_for_event_bit_clr(P_OSAL_EVENT pEvent, unsigned long *pState, unsigned int bitOffset); + +int osal_thread_create(P_OSAL_THREAD); +int osal_thread_run(P_OSAL_THREAD); +int osal_thread_should_stop(P_OSAL_THREAD); +int osal_thread_stop(P_OSAL_THREAD); +/*int osal_thread_wait_for_event(P_OSAL_THREAD, P_OSAL_EVENT);*/ +int osal_thread_wait_for_event(P_OSAL_THREAD, P_OSAL_EVENT, P_OSAL_EVENT_CHECKER); +/*check pOsalLxOp and OSAL_THREAD_SHOULD_STOP*/ +int osal_thread_destroy(P_OSAL_THREAD); +int osal_thread_sched_mark(P_OSAL_THREAD, P_OSAL_THREAD_SCHEDSTATS schedstats); +int osal_thread_sched_unmark(P_OSAL_THREAD pThread, P_OSAL_THREAD_SCHEDSTATS schedstats); + +int osal_clear_bit(unsigned int bitOffset, P_OSAL_BIT_OP_VAR pData); +int osal_set_bit(unsigned int bitOffset, P_OSAL_BIT_OP_VAR pData); +int osal_test_bit(unsigned int bitOffset, P_OSAL_BIT_OP_VAR pData); +int osal_test_and_clear_bit(unsigned int bitOffset, P_OSAL_BIT_OP_VAR pData); +int osal_test_and_set_bit(unsigned int bitOffset, P_OSAL_BIT_OP_VAR pData); + +int osal_gettimeofday(int *sec, int *usec); +//int osal_printtimeofday(const unsigned char *prefix); +void osal_get_local_time(unsigned long long *sec, unsigned long *nsec); +unsigned long long osal_elapsed_us(unsigned long long ts, unsigned long usec); + +void osal_buffer_dump(const unsigned char *buf, const unsigned char *title, unsigned int len, unsigned int limit); +void osal_buffer_dump_data(const unsigned int *buf, const unsigned char *title, const unsigned int len, const unsigned int limit, + const int flag); + +unsigned int osal_op_get_id(P_OSAL_OP pOp); +MTK_CONN_BOOL osal_op_is_wait_for_signal(P_OSAL_OP pOp); +void osal_op_raise_signal(P_OSAL_OP pOp, int result); +void osal_set_op_result(P_OSAL_OP pOp, int result); +void osal_opq_dump(const char *qName, P_OSAL_OP_Q pOpQ); +void osal_opq_dump_locked(const char *qName, P_OSAL_OP_Q pOpQ); +MTK_CONN_BOOL osal_opq_has_op(P_OSAL_OP_Q pOpQ, P_OSAL_OP pOp); + +int osal_ftrace_print(const char *str, ...); +int osal_ftrace_print_ctrl(int flag); + +void osal_dump_thread_state(const unsigned char *name); +void osal_op_history_init(struct osal_op_history *log_history, int queue_size); +void osal_op_history_save(struct osal_op_history *log_history, P_OSAL_OP pOp); +void osal_op_history_print(struct osal_op_history *log_history, char *name); + +void osal_systrace_major_b(const char *name, ...); +void osal_systrace_major_e(void); + +void osal_systrace_minor_b(const char *name, ...); +void osal_systrace_minor_e(void); +void osal_systrace_minor_c(int val, const char *name, ...); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _OSAL_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/base/include/ring.h b/drivers/misc/mediatek/connectivity/conninfra/base/include/ring.h new file mode 100644 index 0000000000000..81168ce866151 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/base/include/ring.h @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _RING_H_ +#define _RING_H_ + +struct ring { + /* addr where ring buffer starts */ + void *base; + /* addr storing the next writable pos, guaranteed to be >= read except when write overflow, but it's ok. */ + unsigned int write; + /* addr storing the next readable pos, except when read == write as buffer empty */ + unsigned int read; + /* must be power of 2 */ + unsigned int max_size; +}; + +struct ring_segment { + /* addr points into ring buffer for read/write */ + void *ring_pt; + /* size to read/write */ + unsigned int sz; + /* pos in external data buffer to read/write */ + unsigned int data_pos; + /* the size to be read/write after this segment completed */ + unsigned int remain; +}; + +void ring_init(void *base, unsigned int max_size, unsigned int read, + unsigned int write, struct ring *ring); +unsigned int ring_read_prepare(unsigned int sz, struct ring_segment *seg, struct ring *ring); +#define ring_read_all_prepare(seg, ring) ring_read_prepare((ring)->max_size, seg, ring) +unsigned int ring_write_prepare(unsigned int sz, struct ring_segment *seg, struct ring *ring); +unsigned int ring_overwrite_prepare(unsigned int sz, + struct ring_segment *seg, struct ring *ring); + +/* making sure max_size is power of 2 */ +#define RING_VALIDATE_SIZE(max_size) WARN_ON(!max_size || (max_size & (max_size - 1))) + +#define RING_EMPTY(ring) ((ring)->read == (ring)->write) +/* equation works even when write overflow */ +#define RING_SIZE(ring) ((ring)->write - (ring)->read) +#define RING_FULL(ring) (RING_SIZE(ring) == (ring)->max_size) +#define RING_WRITE_REMAIN_SIZE(ring) ((ring)->max_size - RING_SIZE(ring)) + +#define RING_READ_FOR_EACH(_sz, _seg, _ring) \ + for (ring_read_prepare(_sz, &(_seg), _ring), \ + _ring_segment_prepare((_ring)->read, &(_seg), (_ring)); \ + (_seg).sz > 0; \ + _ring_read_commit(&(_seg), (_ring)), _ring_segment_prepare((_ring)->read, \ + &(_seg), (_ring))) + +#define RING_READ_ALL_FOR_EACH(seg, ring) RING_READ_FOR_EACH((ring)->max_size, seg, ring) + +#define RING_READ_FOR_EACH_ITEM(_sz, _seg, _ring) \ + for (ring_read_prepare(_sz, &(_seg), _ring), \ + _ring_segment_prepare_item((_ring)->read, &(_seg), (_ring)); \ + (_seg).sz > 0; \ + _ring_read_commit(&(_seg), (_ring)), _ring_segment_prepare_item((_ring)->read, \ + &(_seg), (_ring))) + +#define RING_WRITE_FOR_EACH(_sz, _seg, _ring) \ + for (ring_write_prepare(_sz, &(_seg), _ring),\ + _ring_segment_prepare((_ring)->write, &(_seg), (_ring)); \ + (_seg).sz > 0; \ + _ring_write_commit(&(_seg), (_ring)), _ring_segment_prepare((_ring)->write, \ + &(_seg), (_ring))) + +#define RING_OVERWRITE_FOR_EACH(_sz, _seg, _ring) \ + for (ring_overwrite_prepare(_sz, &(_seg), _ring), \ + _ring_segment_prepare((_ring)->write, &(_seg), (_ring)); \ + (_seg).sz > 0; \ + _ring_write_commit(&(_seg), (_ring)), _ring_segment_prepare((_ring)->write, \ + &(_seg), (_ring))) + +void ring_dump(const char *title, struct ring *ring); +void ring_dump_segment(const char *title, struct ring_segment *seg); + + +/* ring Buffer Internal API */ +void _ring_segment_prepare(unsigned int from, struct ring_segment *seg, struct ring *ring); +void _ring_segment_prepare_item(unsigned int from, struct ring_segment *seg, struct ring *ring); +void _ring_read_commit(struct ring_segment *seg, struct ring *ring); +void _ring_write_commit(struct ring_segment *seg, struct ring *ring); + +#endif diff --git a/drivers/misc/mediatek/connectivity/conninfra/base/msg_thread.c b/drivers/misc/mediatek/connectivity/conninfra/base/msg_thread.c new file mode 100644 index 0000000000000..980dee6a8e5dc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/base/msg_thread.c @@ -0,0 +1,605 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#define pr_fmt(fmt) KBUILD_MODNAME "@(%s:%d) " fmt, __func__, __LINE__ +#include +#include "msg_thread.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 +******************************************************************************** +*/ + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#define MSG_OP_SIZE(prb) ((prb)->size) +#define MSG_OP_MASK(prb) (MSG_OP_SIZE(prb) - 1) +#define MSG_OP_COUNT(prb) ((prb)->write - (prb)->read) +#define MSG_OP_FULL(prb) (MSG_OP_COUNT(prb) >= MSG_OP_SIZE(prb)) +#define MSG_OP_EMPTY(prb) ((prb)->write == (prb)->read) + +#define MSG_OP_INIT(prb, qsize) \ +do { \ + (prb)->read = (prb)->write = 0; \ + (prb)->size = (qsize); \ +} while (0) + +#define MSG_OP_PUT(prb, value) \ +do { \ + if (!MSG_OP_FULL(prb)) { \ + (prb)->queue[(prb)->write & MSG_OP_MASK(prb)] = value; \ + ++((prb)->write); \ + } \ + else { \ + pr_warn("Message queue is full."); \ + } \ +} while (0) + +#define MSG_OP_GET(prb, value) \ +do { \ + if (!MSG_OP_EMPTY(prb)) { \ + value = (prb)->queue[(prb)->read & MSG_OP_MASK(prb)]; \ + ++((prb)->read); \ + if (MSG_OP_EMPTY(prb)) { \ + (prb)->read = (prb)->write = 0; \ + } \ + } \ + else { \ + value = NULL; \ + pr_warn("Message queue is empty."); \ + } \ +} while (0) + + + +#if defined(CONFIG_MTK_ENG_BUILD) || defined(CONFIG_MT_ENG_BUILD) +static bool msg_evt_opq_has_op(struct msg_op_q *op_q, struct msg_op *op) +{ + unsigned int rd; + unsigned int wt; + struct msg_op *tmp_op; + + rd = op_q->read; + wt = op_q->write; + + while (rd != wt) { + tmp_op = op_q->queue[rd & MSG_OP_MASK(op_q)]; + if (op == tmp_op) + return true; + rd++; + } + return false; +} +#endif + +/* + * Utility functions + */ +static int msg_evt_put_op_to_q(struct msg_op_q *op_q, struct msg_op *op) +{ + int ret; + + if (!op_q || !op) { + pr_err("invalid input param: pOpQ(0x%p), pLxOp(0x%p)\n", op_q, op); + return -1; + } + + ret = osal_lock_sleepable_lock(&op_q->lock); + if (ret) { + pr_warn("osal_lock_sleepable_lock iRet(%d)\n", ret); + return -2; + } + +#if defined(CONFIG_MTK_ENG_BUILD) || defined(CONFIG_MT_ENG_BUILD) + if (msg_evt_opq_has_op(op_q, op)) { + pr_err("Op(%p) already exists in queue(%p)\n", op, op_q); + ret = -3; + } +#endif + + /* acquire lock success */ + if (!MSG_OP_FULL(op_q)) + MSG_OP_PUT(op_q, op); + else { + pr_warn("MSG_OP_FULL(%p -> %p)\n", op, op_q); + ret = -4; + } + + osal_unlock_sleepable_lock(&op_q->lock); + + if (ret) { + //osal_opq_dump("FreeOpQ", &g_conninfra_ctx.rFreeOpQ); + //osal_opq_dump("ActiveOpQ", &g_conninfra_ctx.rActiveOpQ); + return ret; + } + return 0; +} + + +/* + * Utility functions + */ +static struct msg_op *msg_evt_get_op_from_q(struct msg_op_q *op_q) +{ + struct msg_op *op; + int ret; + + if (op_q == NULL) { + pr_err("pOpQ = NULL\n"); + return NULL; + } + + ret = osal_lock_sleepable_lock(&op_q->lock); + if (ret) { + pr_err("osal_lock_sleepable_lock iRet(%d)\n", ret); + return NULL; + } + + /* acquire lock success */ + MSG_OP_GET(op_q, op); + osal_unlock_sleepable_lock(&op_q->lock); + + if (op == NULL) { + pr_warn("MSG_OP_GET(%p) return NULL\n", op_q); + //osal_opq_dump("FreeOpQ", &g_conninfra_ctx.rFreeOpQ); + //osal_opq_dump("ActiveOpQ", &g_conninfra_ctx.rActiveOpQ); + } + + return op; +} + +/* + * msg_evt_thread API + */ + +int msg_evt_put_op_to_free_queue(struct msg_thread_ctx *ctx, struct msg_op *op) +{ + if (msg_evt_put_op_to_q(&ctx->free_op_q, op)) + return -1; + return 0; +} + + +struct msg_op *msg_evt_get_free_op(struct msg_thread_ctx *ctx) +{ + struct msg_op *op = NULL; + + if (ctx == NULL) { + pr_warn("ctx is null."); + return op; + } + op = msg_evt_get_op_from_q(&ctx->free_op_q); + if (op) + osal_memset(op, 0, osal_sizeof(struct msg_op)); + return op; +} + +int msg_evt_put_op_to_active(struct msg_thread_ctx *ctx, struct msg_op *op) +{ + P_OSAL_SIGNAL signal = NULL; + int wait_ret = -1; + int ret = 0; + + do { + if (!ctx || !op) { + pr_err("msg_thread_ctx(0x%p), op(0x%p)\n", ctx, op); + break; + } + + signal = &op->signal; + if (signal->timeoutValue) { + op->result = -9; + osal_signal_init(signal); + atomic_set(&op->ref_count, 1); + } else + atomic_set(&op->ref_count, 0); + + /* Increment ref_count by 1 as wmtd thread will hold a reference also, + * this must be done here instead of on target thread, because + * target thread might not be scheduled until a much later time, + * allowing current thread to decrement ref_count at the end of function, + * putting op back to free queue before target thread has a chance to process. + */ + atomic_inc(&op->ref_count); + + /* put to active Q */ + ret = msg_evt_put_op_to_q(&ctx->active_op_q, op); + if (ret) { + pr_warn("put to active queue fail\n"); + atomic_dec(&op->ref_count); + break; + } + + /* wake up conninfra_cored */ + osal_trigger_event(&ctx->evt); + + if (signal->timeoutValue == 0) { + //ret = -1; + /* Not set timeout, don't wait */ + /* pr_info("[%s] timeout is zero", __func__);*/ + break; + } + + /* check result */ + wait_ret = osal_wait_for_signal_timeout(signal, &ctx->thread); + /*pr_info("osal_wait_for_signal_timeout:%d result=[%d]\n", + wait_ret, op->result);*/ + + if (wait_ret == 0) + pr_warn("opId(%d) completion timeout\n", op->op.op_id); + else if (op->result) + pr_info("opId(%d) result:%d\n", + op->op.op_id, op->result); + + /* op completes, check result */ + ret = op->result; + } while (0); + + if (op != NULL && signal != NULL && signal->timeoutValue && + atomic_dec_and_test(&op->ref_count)) { + /* put Op back to freeQ */ + msg_evt_put_op_to_free_queue(ctx, op); + } + + return ret; +} + + +int msg_thread_send(struct msg_thread_ctx *ctx, int opid) +{ + return msg_thread_send_2(ctx, opid, 0, 0); +} + +int msg_thread_send_1(struct msg_thread_ctx *ctx, int opid, + size_t param1) +{ + return msg_thread_send_2(ctx, opid, param1, 0); +} + +int msg_thread_send_2(struct msg_thread_ctx *ctx, int opid, + size_t param1, size_t param2) +{ + struct msg_op *op = NULL; + P_OSAL_SIGNAL signal; + int ret; + + op = msg_evt_get_free_op(ctx); + if (!op) { + pr_err("[%s] can't get free op\n", __func__); + return -1; + } + op->op.op_id = opid; + op->op.op_data[0] = param1; + op->op.op_data[1] = param2; + + signal = &op->signal; + //signal->timeoutValue = timeout > 0 ? timeout : MSG_OP_TIMEOUT; + signal->timeoutValue = 0; + ret = msg_evt_put_op_to_active(ctx, op); + + return ret; +} + +int msg_thread_send_wait(struct msg_thread_ctx *ctx, int opid, + int timeout) +{ + return msg_thread_send_wait_3(ctx, opid, timeout, 0, 0, 0); +} + +int msg_thread_send_wait_1(struct msg_thread_ctx *ctx, + int opid, int timeout, + size_t param1) +{ + return msg_thread_send_wait_3(ctx, opid, timeout, param1, 0, 0); +} + + +int msg_thread_send_wait_2(struct msg_thread_ctx *ctx, + int opid, int timeout, + size_t param1, + size_t param2) +{ + return msg_thread_send_wait_3(ctx, opid, timeout, param1, param2, 0); +} + +int msg_thread_send_wait_3(struct msg_thread_ctx *ctx, + int opid, int timeout, + size_t param1, + size_t param2, + size_t param3) +{ + struct msg_op *op = NULL; + P_OSAL_SIGNAL signal; + int ret; + + op = msg_evt_get_free_op(ctx); + if (!op) { + pr_err("[%s] can't get free op\n", __func__); + return -1; + } + op->op.op_id = opid; + op->op.op_data[0] = param1; + op->op.op_data[1] = param2; + op->op.op_data[2] = param3; + + signal = &op->signal; + signal->timeoutValue = timeout > 0 ? timeout : MSG_OP_TIMEOUT; + ret = msg_evt_put_op_to_active(ctx, op); + return ret; + +} + +void msg_op_history_save(struct osal_op_history *log_history, struct msg_op *op) +{ + struct osal_op_history_entry *entry = NULL; + struct ring_segment seg; + int index; + unsigned long long sec = 0; + unsigned long usec = 0; + unsigned long flags; + + if (log_history->queue == NULL) + return; + + osal_get_local_time(&sec, &usec); + + spin_lock_irqsave(&(log_history->lock), flags); + RING_OVERWRITE_FOR_EACH(1, seg, &log_history->ring_buffer) { + index = seg.ring_pt - log_history->ring_buffer.base; + entry = &log_history->queue[index]; + } + + if (entry == NULL) { + pr_info("Entry is null, size %d\n", + RING_SIZE(&log_history->ring_buffer)); + spin_unlock_irqrestore(&(log_history->lock), flags); + return; + } + + entry->opbuf_address = op; + entry->op_id = op->op.op_id; + entry->opbuf_ref_count = atomic_read(&op->ref_count); + entry->op_info_bit = op->op.info_bit; + entry->param_0 = op->op.op_data[0]; + entry->param_1 = op->op.op_data[1]; + entry->param_2 = op->op.op_data[2]; + entry->param_3 = op->op.op_data[3]; + entry->ts = sec; + entry->usec = usec; + spin_unlock_irqrestore(&(log_history->lock), flags); +} + +unsigned int msg_evt_wait_event_checker(P_OSAL_THREAD thread) +{ + struct msg_thread_ctx *ctx = NULL; + + if (thread) { + ctx = (struct msg_thread_ctx *) (thread->pThreadData); + return !MSG_OP_EMPTY(&ctx->active_op_q); + } + return 0; +} + +int msg_evt_set_current_op(struct msg_thread_ctx *ctx, struct msg_op *op) +{ + ctx->cur_op = op; + return 0; +} + +int msg_evt_opid_handler(struct msg_thread_ctx *ctx, struct msg_op_data *op) +{ + int opid, ret; + + /*sanity check */ + if (op == NULL) { + pr_warn("null op\n"); + return -1; + } + if (ctx == NULL) { + pr_warn("null evt thread ctx\n"); + return -2; + } + + opid = op->op_id; + + if (opid >= ctx->op_func_size) { + pr_err("msg_evt_thread invalid OPID(%d)\n", opid); + return -3; + } + + if (ctx->op_func[opid] == NULL) { + pr_err("null handler (%d)\n", opid); + return -4; + } + ret = (*(ctx->op_func[opid])) (op); + return ret; +} + +static int msg_evt_thread(void *pvData) +{ + struct msg_thread_ctx *ctx = (struct msg_thread_ctx *)pvData; + P_OSAL_EVENT evt = NULL; + struct msg_op *op; + int ret; + + if (ctx == NULL) { + pr_err("msg_evt_thread (NULL)\n"); + return -1; + } + + evt = &(ctx->evt); + + for (;;) { + op = NULL; + evt->timeoutValue = 0; + + osal_thread_wait_for_event(&ctx->thread, evt, msg_evt_wait_event_checker); + + if (osal_thread_should_stop(&ctx->thread)) { + pr_info("msg_evt_thread thread should stop now...\n"); + /* TODO: clean up active opQ */ + break; + } + /* get Op from activeQ */ + op = msg_evt_get_op_from_q(&ctx->active_op_q); + if (!op) { + pr_warn("get op from activeQ fail\n"); + continue; + } + + /* TODO: save op history */ + msg_op_history_save(&ctx->op_history, op); + msg_evt_set_current_op(ctx, op); + ret = msg_evt_opid_handler(ctx, &op->op); + msg_evt_set_current_op(ctx, NULL); + + if (ret) + pr_warn("opid (0x%x) failed, ret(%d)\n", + op->op.op_id, ret); + + if (atomic_dec_and_test(&op->ref_count)) { + /* msg_evt_free_op(ctx) */ + msg_evt_put_op_to_free_queue(ctx, op); + } else if (op->signal.timeoutValue) { + op->result = ret; + osal_raise_signal(&op->signal); + } + } + + pr_debug("msg evt thread exists\n"); + return 0; +} + +int msg_thread_init(struct msg_thread_ctx *ctx, + const char *thread_name, const msg_opid_func *funcs, + int op_size) +{ + int r = 0, i; + P_OSAL_THREAD p_thread; + + osal_memset(ctx, 0, sizeof(struct msg_thread_ctx)); + + ctx->op_func = funcs; + ctx->op_func_size = op_size; + + /* init thread inst */ + p_thread = &ctx->thread; + + osal_strncpy(p_thread->threadName, thread_name, + sizeof(p_thread->threadName)); + + p_thread->pThreadData = (void *) ctx; + p_thread->pThreadFunc = (void *) msg_evt_thread; + r = osal_thread_create(p_thread); + + if (r) { + pr_err("osal_thread_create(0x%p) fail(%d)\n", p_thread, r); + return -1; + } + + osal_event_init(&ctx->evt); + osal_sleepable_lock_init(&ctx->active_op_q.lock); + osal_sleepable_lock_init(&ctx->free_op_q.lock); + + /* Initialize op queue */ + MSG_OP_INIT(&ctx->free_op_q, MSG_THREAD_OP_BUF_SIZE); + MSG_OP_INIT(&ctx->active_op_q, MSG_THREAD_OP_BUF_SIZE); + + /* Put all to free Q */ + for (i = 0; i < MSG_THREAD_OP_BUF_SIZE; i++) { + osal_signal_init(&(ctx->op_q_inst[i].signal)); + msg_evt_put_op_to_free_queue(ctx, &(ctx->op_q_inst[i])); + } + + osal_op_history_init(&ctx->op_history, 16); + + r = osal_thread_run(p_thread); + if (r) { + pr_err("osal_thread_run(evt_thread 0x%p) fail(%d)\n", + p_thread, r); + return -2; + } + return r; +} + +int msg_thread_deinit(struct msg_thread_ctx *ctx) +{ + int r, i; + P_OSAL_THREAD p_thraed = &ctx->thread; + + r = osal_thread_stop(p_thraed); + if (r) { + pr_err("osal_thread_stop(0x%p) fail(%d)\n", p_thraed, r); + return -1; + } + + for (i = 0; i < MSG_THREAD_OP_BUF_SIZE; i++) + osal_signal_deinit(&(ctx->op_q_inst[i].signal)); + + osal_sleepable_lock_deinit(&ctx->free_op_q.lock); + osal_sleepable_lock_deinit(&ctx->active_op_q.lock); + + r = osal_thread_destroy(p_thraed); + if (r) { + pr_err("osal_thread_stop(0x%p) fail(%d)\n", p_thraed, r); + return -2; + } + + osal_memset(ctx, 0, sizeof(struct msg_thread_ctx)); + + pr_debug("[%s] DONE\n", __func__); + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/conninfra/base/osal.c b/drivers/misc/mediatek/connectivity/conninfra/base/osal.c new file mode 100644 index 0000000000000..36b6e18df626c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/base/osal.c @@ -0,0 +1,1644 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/*! \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 +******************************************************************************** +*/ +#define pr_fmt(fmt) KBUILD_MODNAME "@(%s:%d) " fmt, __func__, __LINE__ +/******************************************************************************* +* 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include "connectivity_build_in_adapter.h" +#include "osal.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define GPIO_ASSERT 70 +/******************************************************************************* +* 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 unsigned short 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 +}; + +int ftrace_flag = 1; + +static unsigned long __read_mostly mark_addr; +static unsigned int g_pid; +/******************************************************************************* +* 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*/ +unsigned int osal_strlen(const char *str) +{ + return strlen(str); +} + +int osal_strcmp(const char *dst, const char *src) +{ + return strcmp(dst, src); +} + +int osal_strncmp(const char *dst, const char *src, unsigned int len) +{ + return strncmp(dst, src, len); +} + +char *osal_strcpy(char *dst, const char *src) +{ + return strncpy(dst, src, strlen(src)+1); +} + +char *osal_strncpy(char *dst, const char *src, unsigned int len) +{ + return strncpy(dst, src, len); +} + +char *osal_strcat(char *dst, const char *src) +{ + return strncat(dst, src, strlen(src)); +} + +char *osal_strncat(char *dst, const char *src, unsigned int len) +{ + return strncat(dst, src, len); +} + +char *osal_strchr(const char *str, unsigned char c) +{ + return strchr(str, c); +} + +char *osal_strsep(char **str, const char *c) +{ + return strsep(str, c); +} + +int osal_strtol(const char *str, unsigned int adecimal, long *res) +{ + if (sizeof(long) == 4) + return kstrtou32(str, adecimal, (unsigned int *) res); + else + return kstrtol(str, adecimal, res); +} + +char *osal_strstr(char *str1, const char *str2) +{ + return strstr(str1, str2); +} + +char *osal_strnstr(char *str1, const char *str2, int n) +{ + return strnstr(str1, str2, n); +} + +void osal_bug_on(unsigned int val) +{ + WARN_ON(val); +} + +int osal_snprintf(char *buf, unsigned int len, const char *fmt, ...) +{ + int iRet = 0; + va_list args; + + /*va_start(args, fmt); */ + va_start(args, fmt); + /*iRet = snprintf(buf, len, fmt, args); */ + iRet = vsnprintf(buf, len, fmt, args); + va_end(args); + + return iRet; +} + +int osal_sprintf(char *str, const char *format, ...) +{ + int iRet = 0; + va_list args; + + va_start(args, format); + iRet = vsnprintf(str, DBG_LOG_STR_SIZE, format, args); + va_end(args); + + return iRet; +} + +void *osal_malloc(unsigned int size) +{ + return vmalloc(size); +} + +void osal_free(const void *dst) +{ + vfree(dst); +} + +void *osal_memset(void *buf, int i, unsigned int len) +{ + return memset(buf, i, len); +} + +void *osal_memcpy(void *dst, const void *src, unsigned int len) +{ + return memcpy(dst, src, len); +} + +void osal_memcpy_fromio(void *dst, const void *src, unsigned int len) +{ + return memcpy_fromio(dst, src, len); +} + +void osal_memcpy_toio(void *dst, const void *src, unsigned int len) +{ + return memcpy_toio(dst, src, len); +} + +int osal_memcmp(const void *buf1, const void *buf2, unsigned int len) +{ + return memcmp(buf1, buf2, len); +} + +unsigned short osal_crc16(const unsigned char *buffer, + const unsigned int length) +{ + unsigned short crc = 0; + unsigned int i = 0; + const unsigned char *temp = buffer; + + /* FIXME: Add STP checksum feature */ + crc = 0; + for (i = 0; i < length; i++, temp++) + crc = (crc >> 8) ^ crc16_table[(crc ^ (*temp)) & 0xff]; + return crc; +} + +void osal_dump_thread_state(const unsigned char *name) +{ + //return connectivity_export_dump_thread_state(name); +} + +static inline bool __osal_is_valid_thread(P_OSAL_THREAD pThread) +{ + if ((pThread) && !IS_ERR_OR_NULL(pThread->pThread)) + return true; + else + return false; +} + +void osal_thread_show_stack(P_OSAL_THREAD pThread) +{ + if (__osal_is_valid_thread(pThread)) + KERNEL_show_stack(pThread->pThread, NULL); +} + +/* + * OSAL layer Thread Opeartion related APIs + * + */ +int osal_thread_create(P_OSAL_THREAD pThread) +{ + struct task_struct *task; + + if (!pThread) + return -1; + + task = kthread_create(pThread->pThreadFunc, + pThread->pThreadData, pThread->threadName); + if (IS_ERR(task)) { + pr_err("[%s] create %s thread fail", __func__, pThread->threadName); + return -1; + } + + pThread->pThread = task; + return 0; +} + +int osal_thread_run(P_OSAL_THREAD pThread) +{ + if (__osal_is_valid_thread(pThread)) { + wake_up_process(pThread->pThread); + return 0; + } else { + return -1; + } +} + +int osal_thread_stop(P_OSAL_THREAD pThread) +{ + int iRet; + + if (__osal_is_valid_thread(pThread)) { + iRet = kthread_stop(pThread->pThread); + pThread->pThread = NULL; + return iRet; + } + return -1; +} + +int osal_thread_should_stop(P_OSAL_THREAD pThread) +{ + if (__osal_is_valid_thread(pThread)) + return kthread_should_stop(); + else + return 1; + +} + +int osal_thread_wait_for_event(P_OSAL_THREAD pThread, + P_OSAL_EVENT pEvent, P_OSAL_EVENT_CHECKER pChecker) +{ + /* P_DEV_WMT pDevWmt;*/ + + if (__osal_is_valid_thread(pThread) && (pEvent) && (pChecker)) { + return wait_event_interruptible(pEvent->waitQueue, ( + osal_thread_should_stop(pThread) + || (*pChecker) (pThread))); + } + return -1; +} + +int osal_thread_destroy(P_OSAL_THREAD pThread) +{ + if (__osal_is_valid_thread(pThread)) { + kthread_stop(pThread->pThread); + pThread->pThread = NULL; + } + return 0; +} + +/* + * osal_thread_sched_retrieve + * Retrieve thread's current scheduling statistics and stored in output "sched". + * Return value: + * 0 : Schedstats successfully retrieved + * -1 : Kernel's schedstats feature not enabled + * -2 : pThread not yet initialized or sched is a NULL pointer + */ +static int osal_thread_sched_retrieve(P_OSAL_THREAD pThread, + P_OSAL_THREAD_SCHEDSTATS sched) +{ +#ifdef CONFIG_SCHEDSTATS + struct sched_entity se; + unsigned long long sec; + unsigned long usec; + + if (!sched) + return -2; + + /* always clear sched to simplify error handling at caller side */ + memset(sched, 0, sizeof(OSAL_THREAD_SCHEDSTATS)); + + if (!__osal_is_valid_thread(pThread)) + return -2; + + memcpy(&se, &pThread->pThread->se, sizeof(struct sched_entity)); + osal_get_local_time(&sec, &usec); + + sched->time = sec*1000 + usec/1000; + sched->exec = se.sum_exec_runtime; + sched->runnable = se.statistics.wait_sum; + sched->iowait = se.statistics.iowait_sum; + + return 0; +#else + /* always clear sched to simplify error handling at caller side */ + if (sched) + memset(sched, 0, sizeof(OSAL_THREAD_SCHEDSTATS)); + return -1; +#endif +} + +/* + * osal_thread_sched_mark + * Record the thread's current schedstats and stored + * in output "schedstats" parameter for profiling at + * later time. + * Return value: + * 0 : Schedstats successfully recorded + * -1 : Kernel's schedstats feature not enabled + * -2 : pThread not yet initialized or invalid parameters + */ +int osal_thread_sched_mark(P_OSAL_THREAD pThread, + P_OSAL_THREAD_SCHEDSTATS schedstats) +{ + return osal_thread_sched_retrieve(pThread, schedstats); +} + +/* + * osal_thread_sched_unmark + * Calculate scheduling statistics against the previously marked point. + * The result will be filled back into the schedstats output parameter. + * Return value: + * 0 : Schedstats successfully calculated + * -1 : Kernel's schedstats feature not enabled + * -2 : pThread not yet initialized or invalid parameters + */ +int osal_thread_sched_unmark(P_OSAL_THREAD pThread, + P_OSAL_THREAD_SCHEDSTATS schedstats) +{ + int ret; + OSAL_THREAD_SCHEDSTATS sched_now; + + if (unlikely(!schedstats)) { + ret = -2; + } else { + ret = osal_thread_sched_retrieve(pThread, &sched_now); + if (ret == 0) { + schedstats->time = sched_now.time - schedstats->time; + schedstats->exec = sched_now.exec - schedstats->exec; + schedstats->runnable = + sched_now.runnable - schedstats->runnable; + schedstats->iowait = + sched_now.iowait - schedstats->iowait; + } + } + return ret; +} + +/* + * OSAL layer Signal Opeartion related APIs + * initialization + * wait for signal + * wait for signal timerout + * raise signal + * destroy a signal + * + */ + +int osal_signal_init(P_OSAL_SIGNAL pSignal) +{ + if (pSignal) { + init_completion(&pSignal->comp); + return 0; + } else { + return -1; + } +} + +int osal_wait_for_signal(P_OSAL_SIGNAL pSignal) +{ + if (pSignal) { + wait_for_completion_interruptible(&pSignal->comp); + return 0; + } else { + return -1; + } +} + +/* + * osal_wait_for_signal_timeout + * + * Wait for a signal to be triggered by the corresponding thread, within the + * expected timeout specified by the signal's timeoutValue. + * When the pThread parameter is specified, the thread's scheduling ability is + * considered, the timeout will be extended when thread cannot acquire CPU + * resource, and will only extend for a number of times specified by the + * signal's timeoutExtension should the situation continues. + * + * Return value: + * 0 : timeout + * >0 : signal triggered + */ +int osal_wait_for_signal_timeout(P_OSAL_SIGNAL pSignal, P_OSAL_THREAD pThread) +{ + OSAL_THREAD_SCHEDSTATS schedstats; + int waitRet; + + /* [ChangeFeature][George] gps driver may be closed by -ERESTARTSYS. + * Avoid using *interruptible" version in order to complete our jobs, + * such as function off gracefully. + */ + if (!pThread || !pThread->pThread) + return wait_for_completion_timeout(&pSignal->comp, + msecs_to_jiffies(pSignal->timeoutValue)); + + do { + osal_thread_sched_mark(pThread, &schedstats); + waitRet = wait_for_completion_timeout(&pSignal->comp, + msecs_to_jiffies(pSignal->timeoutValue)); + osal_thread_sched_unmark(pThread, &schedstats); + + if (waitRet > 0) + break; + + if (schedstats.runnable > schedstats.exec) { + pr_err( + "[E]%s:wait completion timeout, %s cannot get CPU, extension(%d), show backtrace:\n", + __func__, + pThread->threadName, + pSignal->timeoutExtension); + } else { + pr_err( + "[E]%s:wait completion timeout, show %s backtrace:\n", + __func__, + pThread->threadName); + pSignal->timeoutExtension = 0; + } + pr_err( + "[E]%s:\tduration:%llums, sched(x%llu/r%llu/i%llu)\n", + __func__, + schedstats.time, + schedstats.exec, + schedstats.runnable, + schedstats.iowait); + /* + * no need to disginguish combo or A/D die projects + * osal_dump_thread_state will just return if target + * thread does not exist + */ + osal_dump_thread_state("mtk_wmtd"); + osal_dump_thread_state("mtk_wmtd_worker"); + osal_dump_thread_state("btif_rxd"); + osal_dump_thread_state("mtk_stp_psm"); + osal_dump_thread_state("mtk_stp_btm"); + osal_dump_thread_state("stp_sdio_tx_rx"); + } while (pSignal->timeoutExtension--); + return waitRet; +} + +int osal_raise_signal(P_OSAL_SIGNAL pSignal) +{ + if (pSignal) { + complete(&pSignal->comp); + return 0; + } else + return -1; +} + +int osal_signal_active_state(P_OSAL_SIGNAL pSignal) +{ + if (pSignal) + return pSignal->timeoutValue; + else + return -1; +} + +int osal_signal_deinit(P_OSAL_SIGNAL pSignal) +{ + if (pSignal) { + pSignal->timeoutValue = 0; + return 0; + } else + return -1; +} + +/* + * OSAL layer Event Opeartion related APIs + * initialization + * wait for signal + * wait for signal timerout + * raise signal + * destroy a signal + * + */ + +int osal_event_init(P_OSAL_EVENT pEvent) +{ + if (pEvent) { + init_waitqueue_head(&pEvent->waitQueue); + return 0; + } + return -1; +} + +int osal_trigger_event(P_OSAL_EVENT pEvent) +{ + int ret = 0; + + if (pEvent) { + wake_up_interruptible(&pEvent->waitQueue); + return ret; + } + return -1; +} + +int osal_wait_for_event(P_OSAL_EVENT pEvent, + int (*condition)(void *), void *cond_pa) +{ + if (pEvent) + return wait_event_interruptible(pEvent->waitQueue, + condition(cond_pa)); + else + return -1; +} + +int osal_wait_for_event_timeout(P_OSAL_EVENT pEvent, + int (*condition)(void *), void *cond_pa) +{ + if (pEvent) + return wait_event_interruptible_timeout(pEvent->waitQueue, + condition(cond_pa), + msecs_to_jiffies(pEvent->timeoutValue)); + return -1; +} + + +int osal_event_deinit(P_OSAL_EVENT pEvent) +{ + return 0; +} + +long osal_wait_for_event_bit_set(P_OSAL_EVENT pEvent, + unsigned long *pState, unsigned int bitOffset) +{ + unsigned int ms = 0; + + if (pEvent) { + 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)); + } else + return -1; + +} + +long osal_wait_for_event_bit_clr(P_OSAL_EVENT pEvent, + unsigned long *pState, unsigned int bitOffset) +{ + unsigned int ms = 0; + + if (pEvent) { + 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)); + } else + return -1; +} + +/* + * 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 + +int osal_bit_op_lock(P_OSAL_UNSLEEPABLE_LOCK pLock) +{ + + return 0; +} + +int osal_bit_op_unlock(P_OSAL_UNSLEEPABLE_LOCK pLock) +{ + + return 0; +} +#endif +int osal_clear_bit(unsigned int 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; +} + +int osal_set_bit(unsigned int 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; +} + +int osal_test_bit(unsigned int bitOffset, P_OSAL_BIT_OP_VAR pData) +{ + unsigned int iRet = 0; + + osal_bit_op_lock(&(pData->opLock)); + iRet = test_bit(bitOffset, &pData->data); + osal_bit_op_unlock(&(pData->opLock)); + return iRet; +} + +int osal_test_and_clear_bit(unsigned int bitOffset, P_OSAL_BIT_OP_VAR pData) +{ + unsigned int iRet = 0; + + osal_bit_op_lock(&(pData->opLock)); + iRet = test_and_clear_bit(bitOffset, &pData->data); + osal_bit_op_unlock(&(pData->opLock)); + return iRet; + +} + +int osal_test_and_set_bit(unsigned int bitOffset, P_OSAL_BIT_OP_VAR pData) +{ + unsigned int 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 + * + */ + +int osal_timer_create(P_OSAL_TIMER pTimer) +{ + struct timer_list *timer = &pTimer->timer; + + init_timer(timer); + timer->function = pTimer->timeoutHandler; + timer->data = (unsigned long)pTimer->timeroutHandlerData; + return 0; +} + +int osal_timer_start(P_OSAL_TIMER pTimer, unsigned int ms) +{ + + struct timer_list *timer = &pTimer->timer; + + timer->expires = jiffies + (ms / (1000 / HZ)); + add_timer(timer); + return 0; +} + +int osal_timer_stop(P_OSAL_TIMER pTimer) +{ + struct timer_list *timer = &pTimer->timer; + + del_timer(timer); + return 0; +} + +int osal_timer_stop_sync(P_OSAL_TIMER pTimer) +{ + struct timer_list *timer = &pTimer->timer; + + del_timer_sync(timer); + return 0; +} + +int osal_timer_modify(P_OSAL_TIMER pTimer, unsigned int ms) +{ + + mod_timer(&pTimer->timer, jiffies + (ms) / (1000 / HZ)); + return 0; +} + +int _osal_fifo_init(OSAL_FIFO *pFifo, unsigned char *buf, unsigned int size) +{ + struct kfifo *fifo = NULL; + int ret = -1; + + if (!pFifo) { + pr_err("pFifo must be !NULL\n"); + return -1; + } + if (pFifo->pFifoBody) { + pr_err("pFifo->pFifoBody must be NULL\n"); + pr_err("pFifo(0x%p), pFifo->pFifoBody(0x%p)\n", + pFifo, pFifo->pFifoBody); + return -1; + } + fifo = kzalloc(sizeof(struct kfifo), GFP_ATOMIC); + if (!buf) { + /*fifo's buffer is not ready, we allocate automatically */ + ret = kfifo_alloc(fifo, size, /*GFP_KERNEL */ GFP_ATOMIC); + } else { + if (is_power_of_2(size)) { + kfifo_init(fifo, buf, size); + ret = 0; + } else { + kfifo_free(fifo); + fifo = NULL; + ret = -1; + } + } + + pFifo->pFifoBody = fifo; + return (ret < 0) ? (-1) : (0); +} + +int _osal_fifo_deinit(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", + __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo) + kfifo_free(fifo); + + return 0; +} + +int _osal_fifo_size(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + int ret = 0; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", + __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo) + ret = kfifo_size(fifo); + + return ret; +} + +/*returns unused bytes in fifo*/ +int _osal_fifo_avail_size(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + int ret = 0; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", + __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo) + ret = kfifo_avail(fifo); + + return ret; +} + +/*returns used bytes in fifo*/ +int _osal_fifo_len(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + int ret = 0; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", + __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo) + ret = kfifo_len(fifo); + + return ret; +} + +int _osal_fifo_is_empty(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + int ret = 0; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", + __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo) + ret = kfifo_is_empty(fifo); + + return ret; +} + +int _osal_fifo_is_full(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + int ret = 0; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", + __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo) + ret = kfifo_is_full(fifo); + + return ret; +} + +int _osal_fifo_data_in(OSAL_FIFO *pFifo, const void *buf, unsigned int len) +{ + struct kfifo *fifo = NULL; + int ret = 0; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", + __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo && buf && (len <= _osal_fifo_avail_size(pFifo))) { + ret = kfifo_in(fifo, buf, len); + } else { + pr_err("%s: kfifo_in, error, len = %d, _osal_fifo_avail_size = %d, buf=%p\n", + __func__, len, _osal_fifo_avail_size(pFifo), buf); + + ret = 0; + } + + return ret; +} + +int _osal_fifo_data_out(OSAL_FIFO *pFifo, void *buf, unsigned int len) +{ + struct kfifo *fifo = NULL; + int ret = 0; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n" + , __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo && buf && (len <= _osal_fifo_len(pFifo))) { + ret = kfifo_out(fifo, buf, len); + } else { + pr_err("%s: kfifo_out, error, len = %d, osal_fifo_len = %d, buf=%p\n", + __func__, len, _osal_fifo_len(pFifo), buf); + + ret = 0; + } + + return ret; +} + +int _osal_fifo_reset(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", + __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo) + kfifo_reset(fifo); + + return 0; +} + +int osal_fifo_init(P_OSAL_FIFO pFifo, unsigned char *buffer, unsigned int size) +{ + if (!pFifo) { + pr_err("%s:pFifo = NULL, error\n", __func__); + return -1; + } + + pFifo->FifoInit = _osal_fifo_init; + pFifo->FifoDeInit = _osal_fifo_deinit; + pFifo->FifoSz = _osal_fifo_size; + pFifo->FifoAvailSz = _osal_fifo_avail_size; + pFifo->FifoLen = _osal_fifo_len; + pFifo->FifoIsEmpty = _osal_fifo_is_empty; + pFifo->FifoIsFull = _osal_fifo_is_full; + pFifo->FifoDataIn = _osal_fifo_data_in; + pFifo->FifoDataOut = _osal_fifo_data_out; + pFifo->FifoReset = _osal_fifo_reset; + + if (pFifo->pFifoBody != NULL) { + pr_err("%s:Because pFifo room is avialable, we clear the room and allocate them again.\n", __func__); + pFifo->FifoDeInit(pFifo->pFifoBody); + pFifo->pFifoBody = NULL; + } + + pFifo->FifoInit(pFifo, buffer, size); + + return 0; +} + +void osal_fifo_deinit(P_OSAL_FIFO pFifo) +{ + if (pFifo) + pFifo->FifoDeInit(pFifo); + else { + pr_err("%s:pFifo = NULL, error\n", __func__); + return; + } + kfree(pFifo->pFifoBody); +} + +int osal_fifo_reset(P_OSAL_FIFO pFifo) +{ + int ret = -1; + + if (pFifo) { + ret = pFifo->FifoReset(pFifo); + } else { + pr_err("%s:pFifo = NULL, error\n", __func__); + ret = -1; + } + return ret; +} + +unsigned int osal_fifo_in(P_OSAL_FIFO pFifo, + unsigned char *buffer, unsigned int size) +{ + unsigned int ret = 0; + + if (pFifo) { + ret = pFifo->FifoDataIn(pFifo, buffer, size); + } else { + pr_err("%s:pFifo = NULL, error\n", __func__); + ret = 0; + } + + return ret; +} + +unsigned int osal_fifo_out(P_OSAL_FIFO pFifo, + unsigned char *buffer, unsigned int size) +{ + unsigned int ret = 0; + + if (pFifo) { + ret = pFifo->FifoDataOut(pFifo, buffer, size); + } else { + pr_err("%s:pFifo = NULL, error\n", __func__); + ret = 0; + } + + return ret; +} + +unsigned int osal_fifo_len(P_OSAL_FIFO pFifo) +{ + unsigned int ret = 0; + + if (pFifo) { + ret = pFifo->FifoLen(pFifo); + } else { + pr_err("%s:pFifo = NULL, error\n", __func__); + ret = 0; + } + + return ret; +} + +unsigned int osal_fifo_sz(P_OSAL_FIFO pFifo) +{ + unsigned int ret = 0; + + if (pFifo) { + ret = pFifo->FifoSz(pFifo); + } else { + pr_err("%s:pFifo = NULL, error\n", __func__); + ret = 0; + } + + return ret; +} + +unsigned int osal_fifo_avail(P_OSAL_FIFO pFifo) +{ + unsigned int ret = 0; + + if (pFifo) { + ret = pFifo->FifoAvailSz(pFifo); + } else { + pr_err("%s:pFifo = NULL, error\n", __func__); + ret = 0; + } + + return ret; +} + +unsigned int osal_fifo_is_empty(P_OSAL_FIFO pFifo) +{ + unsigned int ret = 0; + + if (pFifo) { + ret = pFifo->FifoIsEmpty(pFifo); + } else { + pr_err("%s:pFifo = NULL, error\n", __func__); + ret = 0; + } + + return ret; +} + +unsigned int osal_fifo_is_full(P_OSAL_FIFO pFifo) +{ + unsigned int ret = 0; + + if (pFifo) { + ret = pFifo->FifoIsFull(pFifo); + } else { + pr_err("%s:pFifo = NULL, error\n", __func__); + ret = 0; + } + return ret; +} + +/* + * sleepable lock operations APIs + * init + * lock + * unlock + * destroy + * + */ +#if !defined(CONFIG_PROVE_LOCKING) +int osal_unsleepable_lock_init(P_OSAL_UNSLEEPABLE_LOCK pUSL) +{ + spin_lock_init(&(pUSL->lock)); + return 0; +} +#endif + +int osal_lock_unsleepable_lock(P_OSAL_UNSLEEPABLE_LOCK pUSL) +{ + spin_lock_irqsave(&(pUSL->lock), pUSL->flag); + return 0; +} + +int osal_unlock_unsleepable_lock(P_OSAL_UNSLEEPABLE_LOCK pUSL) +{ + spin_unlock_irqrestore(&(pUSL->lock), pUSL->flag); + return 0; +} + +int osal_unsleepable_lock_deinit(P_OSAL_UNSLEEPABLE_LOCK pUSL) +{ + return 0; +} + +/* + * unsleepable operations APIs + * init + * lock + * unlock + * destroy + * + */ + +#if !defined(CONFIG_PROVE_LOCKING) +int osal_sleepable_lock_init(P_OSAL_SLEEPABLE_LOCK pSL) +{ + mutex_init(&pSL->lock); + return 0; +} +#endif + +int osal_lock_sleepable_lock(P_OSAL_SLEEPABLE_LOCK pSL) +{ + return mutex_lock_killable(&pSL->lock); +} + +int osal_unlock_sleepable_lock(P_OSAL_SLEEPABLE_LOCK pSL) +{ + mutex_unlock(&pSL->lock); + return 0; +} + +int osal_trylock_sleepable_lock(P_OSAL_SLEEPABLE_LOCK pSL) +{ + return mutex_trylock(&pSL->lock); +} + +int osal_sleepable_lock_deinit(P_OSAL_SLEEPABLE_LOCK pSL) +{ + mutex_destroy(&pSL->lock); + return 0; +} + +int osal_sleep_ms(unsigned int ms) +{ + msleep(ms); + return 0; +} + +int osal_udelay(unsigned int us) +{ + udelay(us); + return 0; +} + +int osal_usleep_range(unsigned long min, unsigned long max) +{ + usleep_range(min, max); + return 0; +} + +int osal_gettimeofday(int *sec, int *usec) +{ + int 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; +} + +void osal_get_local_time(unsigned long long *sec, unsigned long *nsec) +{ + if (sec != NULL && nsec != NULL) { + *sec = local_clock(); + *nsec = do_div(*sec, 1000000000)/1000; + } else + pr_err("The input parameters error when get local time\n"); +} + +unsigned long long osal_elapsed_us(unsigned long long ts, unsigned long usec) +{ + unsigned long long current_ts = 0; + unsigned long current_usec = 0; + + osal_get_local_time(¤t_ts, ¤t_usec); + return (current_ts*1000000 + current_usec) - (ts*1000000 + usec); +} + +void osal_buffer_dump(const unsigned char *buf, + const unsigned char *title, const unsigned int len, + const unsigned int limit) +{ + int k; + unsigned int dump_len; + char str[DBG_LOG_STR_SIZE] = {""}; + int strlen = 0; + + pr_info("[%s] len=%d, limit=%d, start dump\n", title, len, limit); + + dump_len = ((limit != 0) && (len > limit)) ? limit : len; + for (k = 0; k < dump_len; k++) { + if ((k+1) % 16 != 0) { + strlen += osal_snprintf(str + strlen, DBG_LOG_STR_SIZE - strlen, + "%02x ", buf[k]); + } else { + strlen += osal_snprintf(str + strlen, DBG_LOG_STR_SIZE - strlen, + "%02x ", buf[k]); + + pr_info("%s", str); + strlen = 0; + } + } + if (k % 16 != 0) + pr_info("%s\n", str); + + pr_info("end of dump\n"); +} + +void osal_buffer_dump_data(const unsigned int *buf, + const unsigned char *title, const unsigned int len, + const unsigned int limit, + const int flag) +{ + int k; + unsigned int dump_len; + char str[DBG_LOG_STR_SIZE] = {""}; + int strlen = 0; + + dump_len = ((limit != 0) && (len > limit)) ? limit : len; + for (k = 0; k < dump_len; k++) { + if (((k+1) % 8 != 0) && (k < (dump_len - 1))) { + strlen += osal_snprintf(str + strlen, DBG_LOG_STR_SIZE - strlen, + "0x%08x,", buf[k]); + } else { + strlen += osal_snprintf(str + strlen, DBG_LOG_STR_SIZE - strlen, + "0x%08x,", buf[k]); + if (flag) + osal_ftrace_print("%s%s", title, str); + else + pr_info("%s%s", title, str); + strlen = 0; + } + } + if (k % 8 != 0) { + if (flag) + osal_ftrace_print("%s%s", title, str); + else + pr_info("%s%s", title, str); + } +} + +unsigned int osal_op_get_id(P_OSAL_OP pOp) +{ + return (pOp) ? pOp->op.opId : 0xFFFFFFFF; +} + +MTK_CONN_BOOL osal_op_is_wait_for_signal(P_OSAL_OP pOp) +{ + return (pOp && pOp->signal.timeoutValue) + ? MTK_CONN_BOOL_TRUE : MTK_CONN_BOOL_FALSE; +} + +void osal_op_raise_signal(P_OSAL_OP pOp, int result) +{ + if (pOp) { + pOp->result = result; + osal_raise_signal(&pOp->signal); + } +} + +int osal_ftrace_print(const char *str, ...) +{ +#ifdef CONFIG_TRACING + va_list args; + char tempString[DBG_LOG_STR_SIZE]; + + if (ftrace_flag) { + va_start(args, str); + vsnprintf(tempString, DBG_LOG_STR_SIZE, str, args); + va_end(args); + + trace_printk("%s\n", tempString); + } +#endif + return 0; +} + +int osal_ftrace_print_ctrl(int flag) +{ +#ifdef CONFIG_TRACING + if (flag) + ftrace_flag = 1; + else + ftrace_flag = 0; +#endif + return 0; +} + +void osal_set_op_result(P_OSAL_OP pOp, int result) +{ + if (pOp) + pOp->result = result; + +} + +MTK_CONN_BOOL osal_opq_has_op(P_OSAL_OP_Q pOpQ, P_OSAL_OP pOp) +{ + unsigned int rd; + unsigned int wt; + P_OSAL_OP op; + + rd = pOpQ->read; + wt = pOpQ->write; + + while (rd != wt) { + op = pOpQ->queue[rd & RB_MASK(pOpQ)]; + if (op == pOp) + return MTK_CONN_BOOL_TRUE; + rd++; + } + return MTK_CONN_BOOL_FALSE; +} + +static void osal_op_history_print_work(struct work_struct *work) +{ + struct osal_op_history *log_history + = container_of(work, struct osal_op_history, dump_work); + struct ring *ring_buffer = &log_history->dump_ring_buffer; + struct ring_segment seg; + struct osal_op_history_entry *queue = ring_buffer->base; + struct osal_op_history_entry *entry; + int index = 0; + + if (queue == NULL) { + pr_info("queue shouldn't be NULL, %s", log_history->name); + return; + } + + RING_READ_FOR_EACH_ITEM(RING_SIZE(ring_buffer), seg, ring_buffer) { + index = seg.ring_pt - ring_buffer->base; + entry = &queue[index]; + pr_info("(%llu.%06lu) %s: pOp(%p):%u(%d)-%x-%zx,%zx,%zx,%zx\n", + entry->ts, + entry->usec, + log_history->name, + entry->opbuf_address, + entry->op_id, + entry->opbuf_ref_count, + entry->op_info_bit, + entry->param_0, + entry->param_1, + entry->param_2, + entry->param_3); + } + kfree(queue); + ring_buffer->base = NULL; +} + +void osal_op_history_init(struct osal_op_history *log_history, int queue_size) +{ + int size = queue_size * sizeof(struct osal_op_history_entry); + + spin_lock_init(&(log_history->lock)); + + log_history->queue = kzalloc(size, GFP_ATOMIC); + if (log_history->queue == NULL) + return; + + /* queue_size must be power of 2 */ + ring_init( + &log_history->queue, + queue_size, + 0, + 0, + &log_history->ring_buffer); + + INIT_WORK(&log_history->dump_work, osal_op_history_print_work); +} + +void osal_op_history_print(struct osal_op_history *log_history, char *name) +{ + struct osal_op_history_entry *queue; + struct ring *ring_buffer, *dump_ring_buffer; + int queue_size; + unsigned long flags; + struct work_struct *work = &log_history->dump_work; + spinlock_t *lock = &(log_history->lock); + + if (log_history->queue == NULL) { + pr_info("Queue is NULL, name: %s\n", name); + return; + } + + ring_buffer = &log_history->ring_buffer; + queue_size = sizeof(struct osal_op_history_entry) + * RING_SIZE(ring_buffer); + + /* Allocate memory before getting lock to save time of holding lock */ + queue = kmalloc(queue_size, GFP_KERNEL); + if (queue == NULL) + return; + + dump_ring_buffer = &log_history->dump_ring_buffer; + + spin_lock_irqsave(lock, flags); + if (dump_ring_buffer->base != NULL) { + spin_unlock_irqrestore(lock, flags); + kfree(queue); + pr_info("print is ongoing: %s\n", name); + return; + } + + osal_snprintf(log_history->name, sizeof(log_history->name), "%s", name); + osal_memcpy(queue, log_history->queue, queue_size); + osal_memcpy(dump_ring_buffer, ring_buffer, sizeof(struct ring)); + /* assign value to base after memory copy */ + dump_ring_buffer->base = queue; + spin_unlock_irqrestore(lock, flags); + schedule_work(work); +} + +void osal_op_history_save(struct osal_op_history *log_history, P_OSAL_OP pOp) +{ + struct osal_op_history_entry *entry = NULL; + struct ring_segment seg; + int index; + unsigned long long sec = 0; + unsigned long usec = 0; + unsigned long flags; + + if (log_history->queue == NULL) + return; + + osal_get_local_time(&sec, &usec); + + spin_lock_irqsave(&(log_history->lock), flags); + RING_OVERWRITE_FOR_EACH(1, seg, &log_history->ring_buffer) { + index = seg.ring_pt - log_history->ring_buffer.base; + entry = &log_history->queue[index]; + } + + if (entry == NULL) { + pr_info("Entry is null, size %d\n", + RING_SIZE(&log_history->ring_buffer)); + spin_unlock_irqrestore(&(log_history->lock), flags); + return; + } + + entry->opbuf_address = pOp; + entry->op_id = pOp->op.opId; + entry->opbuf_ref_count = atomic_read(&pOp->ref_count); + entry->op_info_bit = pOp->op.u4InfoBit; + entry->param_0 = pOp->op.au4OpData[0]; + entry->param_1 = pOp->op.au4OpData[1]; + entry->param_2 = pOp->op.au4OpData[2]; + entry->param_3 = pOp->op.au4OpData[3]; + entry->ts = sec; + entry->usec = usec; + spin_unlock_irqrestore(&(log_history->lock), flags); +} + +static inline void osal_systrace_prepare(void) +{ + if (unlikely(mark_addr == 0)) + mark_addr = kallsyms_lookup_name("tracing_mark_write"); + if (unlikely(g_pid == 0)) + g_pid = task_pid_nr(current); +} + +static void osal_systrace_b(const char *log) +{ + osal_systrace_prepare(); + preempt_disable(); + KERNEL_event_trace_printk(mark_addr, "B|%d|%s\n", g_pid, log); + preempt_enable(); +} + + +static void osal_systrace_e(void) +{ + preempt_disable(); + KERNEL_event_trace_printk(mark_addr, "E\n"); + preempt_enable(); +} + +static void osal_systrace_c(int val, const char *log) +{ + osal_systrace_prepare(); + preempt_disable(); + KERNEL_event_trace_printk(mark_addr, "C|%d|%s|%d\n", g_pid, log, val); + preempt_enable(); +} + +void osal_systrace_major_b(const char *fmt, ...) +{ + char log[DBG_LOG_STR_SIZE]; + va_list args; + + memset(log, ' ', sizeof(log)); + va_start(args, fmt); + if (vsnprintf(log, sizeof(log), fmt, args) < 0) + pr_err("[%s:%d] vsnprintf error", __func__, __LINE__); + va_end(args); + osal_systrace_b(log); +} + +void osal_systrace_major_e(void) +{ + osal_systrace_e(); +} + +void osal_systrace_minor_b(const char *fmt, ...) +{ + char log[DBG_LOG_STR_SIZE]; + va_list args; + + if (!ftrace_flag) + return; + + memset(log, ' ', sizeof(log)); + va_start(args, fmt); + if (vsnprintf(log, sizeof(log), fmt, args) < 0) + pr_err("[%s:%d] vsnprintf error", __func__, __LINE__); + va_end(args); + osal_systrace_b(log); + +} + +void osal_systrace_minor_e(void) +{ + if (!ftrace_flag) + return; + osal_systrace_e(); +} + +void osal_systrace_minor_c(int val, const char *fmt, ...) +{ + char log[DBG_LOG_STR_SIZE]; + va_list args; + + if (!ftrace_flag) + return; + + memset(log, ' ', sizeof(log)); + va_start(args, fmt); + if (vsnprintf(log, sizeof(log), fmt, args) < 0) + pr_err("[%s:%d] vsnprintf error", __func__, __LINE__); + va_end(args); + osal_systrace_c(val, log); +} + diff --git a/drivers/misc/mediatek/connectivity/conninfra/base/ring.c b/drivers/misc/mediatek/connectivity/conninfra/base/ring.c new file mode 100644 index 0000000000000..e563760afecae --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/base/ring.c @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "ring.h" +#include +#include +#include + + + +void ring_init(void *base, unsigned int max_size, unsigned int read, + unsigned int write, struct ring *ring) +{ + WARN_ON(!base); + + /* making sure max_size is power of 2 */ + WARN_ON(!max_size || (max_size & (max_size - 1))); + + /* making sure write largger than read */ + WARN_ON(read > write); + + ring->base = base; + ring->read = read; + ring->write = write; + ring->max_size = max_size; +} + +void ring_dump(const char *title, struct ring *ring) +{ + pr_info("[%s] ring:{write=%d, read=%d, max_size=%d}\n", + title, ring->write, ring->read, ring->max_size); +} + +void ring_dump_segment(const char *title, struct ring_segment *seg) +{ + pr_info("[%s] seg:{ring_pt=0x%p, data_pos=%d, sz=%d, remain=%d}\n", + title, seg->ring_pt, seg->data_pos, + seg->sz, seg->remain); +} + +/* + * Function prepares the ring_segment and + * returns the number of valid bytes for read. + */ +unsigned int ring_read_prepare(unsigned int sz, + struct ring_segment *seg, + struct ring *ring) +{ + unsigned int wt = ring->write; + unsigned int rd = ring->read; + + memset(seg, 0, sizeof(struct ring_segment)); + if (sz > wt - rd) + sz = wt - rd; + seg->remain = sz; + /* ring_dump(__func__, ring); */ + /* ring_dump_segment(__func__, seg); */ + return seg->remain; +} + +/* + * Function prepares the ring_segment and + * returns the number of bytes available for write. + */ +unsigned int ring_write_prepare(unsigned int sz, + struct ring_segment *seg, + struct ring *ring) +{ + unsigned int wt = ring->write; + unsigned int rd = ring->read; + + memset(seg, 0, sizeof(struct ring_segment)); + if (sz > ring->max_size - (wt - rd)) + sz = ring->max_size - (wt - rd); + seg->remain = sz; + /* ring_dump(__func__, ring); */ + /* ring_dump_segment(__func__, seg); */ + return seg->remain; +} + +unsigned int ring_overwrite_prepare(unsigned int sz, struct ring_segment *seg, + struct ring *ring) +{ + unsigned int wt = ring->write; + unsigned int rd = ring->read; + + memset(seg, 0, sizeof(struct ring_segment)); + if (sz > ring->max_size - (wt - rd)) + ring->read += sz - (ring->max_size - (wt - rd)); + seg->remain = sz; + /* ring_dump(__func__, ring); */ + /* ring_dump_segment(__func__, seg); */ + return seg->remain; +} + +void __ring_segment_prepare(unsigned int from, unsigned int sz, + struct ring_segment *seg, + struct ring *ring) +{ + unsigned int ring_pos = from & (ring->max_size - 1); + + seg->ring_pt = ring->base + ring_pos; + seg->data_pos = (seg->sz ? seg->data_pos + seg->sz : 0); + if (ring_pos + sz <= ring->max_size) + seg->sz = sz; + else + seg->sz = ring->max_size - ring_pos; + seg->remain -= seg->sz; + /* ring_dump(__func__, ring); */ + /* ring_dump_segment(__func__, seg); */ +} + +void _ring_segment_prepare(unsigned int from, + struct ring_segment *seg, + struct ring *ring) +{ + __ring_segment_prepare(from, seg->remain, seg, ring); +} + +void _ring_segment_prepare_item(unsigned int from, + struct ring_segment *seg, + struct ring *ring) +{ + unsigned int size; + + size = (seg->remain ? 1 : 0); + __ring_segment_prepare(from, size, seg, ring); +} + +void _ring_read_commit(struct ring_segment *seg, struct ring *ring) +{ + ring->read += seg->sz; + /* ring_dump(__func__, ring); */ + /* ring_dump_segment(__func__, seg); */ +} +void _ring_write_commit(struct ring_segment *seg, struct ring *ring) +{ + ring->write += seg->sz; + /* ring_dump(__func__, ring); */ + /* ring_dump_segment(__func__, seg); */ +} + diff --git a/drivers/misc/mediatek/connectivity/conninfra/conf/conninfra_conf.c b/drivers/misc/mediatek/connectivity/conninfra/conf/conninfra_conf.c new file mode 100644 index 0000000000000..d330cb54fe8a3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/conf/conninfra_conf.c @@ -0,0 +1,635 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME "@(%s:%d) " fmt, __func__, __LINE__ + +#include +#include "conninfra_conf.h" + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +struct parse_data { + char *name; + int (*parser)(const struct parse_data *data, const char *value); + char *(*writer)(const struct parse_data *data); + void (*relase_mem)(const struct parse_data *data); + /*PCHAR param1, *param2, *param3; */ + /* TODO:[FixMe][George] CLARIFY WHAT SHOULD BE USED HERE!!! */ + char *param1; + char *param2; + char *param3; +}; + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +struct conninfra_conf g_conninfra_conf; + +/****************************************************************************** +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************* +*/ +static int conf_parse_char(const struct parse_data *data, const char *pos); + +static char *conf_write_char(const struct parse_data *data); + +static int conf_parse_short(const struct parse_data *data, const char *pos); + +static char *conf_write_short(const struct parse_data *data); + +static int conf_parse_int(const struct parse_data *data, const char *pos); + +static char *conf_write_int(const struct parse_data *data); + +static int conf_parse_byte_array(const struct parse_data *data, + const char *pos); + +static char *conf_write_byte_array(const struct parse_data *data); + +static void conf_release_byte_array(const struct parse_data *data); + +static int conf_parse_pair(const char *key, const char *pVal); + +static int conf_parse(const char *pInBuf, unsigned int size); + +//#define OFFSET(v) ((void *) &((struct conninfra_conf*) 0)->v) + +#define CHAR(f) {#f, conf_parse_char, conf_write_char, NULL, (char *)&g_conninfra_conf.f, NULL, NULL} + +#define SHORT(f) {#f, conf_parse_short, conf_write_short, NULL, (char *)&g_conninfra_conf.f, NULL, NULL} + +#define INT(f) {#f, conf_parse_int, conf_write_int, NULL, (char *)&g_conninfra_conf.f, NULL, NULL} + +#define BYTE_ARRAY(f) {#f, conf_parse_byte_array, conf_write_byte_array, conf_release_byte_array,\ + (char *)&g_conninfra_conf.f, NULL, NULL} + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +static const struct parse_data cfg_fields[] = { + CHAR(coex_wmt_ant_mode), + CHAR(coex_wmt_ant_mode_ex), + CHAR(coex_wmt_ext_component), + CHAR(coex_wmt_wifi_time_ctl), + CHAR(coex_wmt_ext_pta_dev_on), + CHAR(coex_wmt_filter_mode), + + CHAR(coex_bt_rssi_upper_limit), + CHAR(coex_bt_rssi_mid_limit), + CHAR(coex_bt_rssi_lower_limit), + CHAR(coex_bt_pwr_high), + CHAR(coex_bt_pwr_mid), + CHAR(coex_bt_pwr_low), + + CHAR(coex_wifi_rssi_upper_limit), + CHAR(coex_wifi_rssi_mid_limit), + CHAR(coex_wifi_rssi_lower_limit), + CHAR(coex_wifi_pwr_high), + CHAR(coex_wifi_pwr_mid), + CHAR(coex_wifi_pwr_low), + + CHAR(coex_ext_pta_hi_tx_tag), + CHAR(coex_ext_pta_hi_rx_tag), + CHAR(coex_ext_pta_lo_tx_tag), + CHAR(coex_ext_pta_lo_rx_tag), + SHORT(coex_ext_pta_sample_t1), + SHORT(coex_ext_pta_sample_t2), + CHAR(coex_ext_pta_wifi_bt_con_trx), + + INT(coex_misc_ext_pta_on), + INT(coex_misc_ext_feature_set), + + CHAR(wmt_gps_lna_pin), + CHAR(wmt_gps_lna_enable), + + CHAR(pwr_on_rtc_slot), + CHAR(pwr_on_ldo_slot), + CHAR(pwr_on_rst_slot), + CHAR(pwr_on_off_slot), + CHAR(pwr_on_on_slot), + CHAR(co_clock_flag), + + CHAR(disable_deep_sleep_cfg), + + INT(sdio_driving_cfg), + + SHORT(coex_wmt_wifi_path), + + CHAR(coex_wmt_ext_elna_gain_p1_support), + INT(coex_wmt_ext_elna_gain_p1_D0), + INT(coex_wmt_ext_elna_gain_p1_D1), + INT(coex_wmt_ext_elna_gain_p1_D2), + INT(coex_wmt_ext_elna_gain_p1_D3), + + BYTE_ARRAY(coex_wmt_epa_elna), + + CHAR(bt_tssi_from_wifi), + SHORT(bt_tssi_target), + + CHAR(coex_config_bt_ctrl), + CHAR(coex_config_bt_ctrl_mode), + CHAR(coex_config_bt_ctrl_rw), + + CHAR(coex_config_addjust_opp_time_ratio), + CHAR(coex_config_addjust_opp_time_ratio_bt_slot), + CHAR(coex_config_addjust_opp_time_ratio_wifi_slot), + + CHAR(coex_config_addjust_ble_scan_time_ratio), + CHAR(coex_config_addjust_ble_scan_time_ratio_bt_slot), + CHAR(coex_config_addjust_ble_scan_time_ratio_wifi_slot), + CHAR(tcxo_gpio), + CHAR(pre_cal_mode), +}; + +#define NUM_CFG_FIELDS (osal_sizeof(cfg_fields) / osal_sizeof(cfg_fields[0])) + +static int conf_parse_char(const struct parse_data *data, const char *pos) +{ + char *dst; + long res = 0; + + dst = (char *)(data->param1); + + if ((osal_strlen(pos) > 2) && ((*pos) == '0') && (*(pos + 1) == 'x')) { + osal_strtol(pos + 2, 16, &res); + *dst = (char)res; + pr_debug("cfg==> %s=0x%x\n", data->name, *dst); + } else { + osal_strtol(pos, 10, &res); + *dst = (char)res; + pr_debug("cfg==> %s=%d\n", data->name, *dst); + } + return 0; +} + +static char *conf_write_char(const struct parse_data *data) +{ + char *src; + int res; + char *value; + + src = data->param1; + + value = osal_malloc(20); + if (value == NULL) + return NULL; + res = osal_snprintf(value, 20, "0x%x", *src); + if (res < 0 || res >= 20) { + osal_free(value); + return NULL; + } + value[20 - 1] = '\0'; + return value; +} + +static int conf_parse_short(const struct parse_data *data, const char *pos) +{ + unsigned short *dst; + long res = 0; + + dst = (unsigned short *)data->param1; + + if ((osal_strlen(pos) > 2) && ((*pos) == '0') && (*(pos + 1) == 'x')) { + osal_strtol(pos + 2, 16, &res); + *dst = (unsigned short)res; + pr_debug("cfg==> %s=0x%x\n", data->name, *dst); + } else { + osal_strtol(pos, 10, &res); + *dst = (unsigned short)res; + pr_debug("cfg==> %s=%d\n", data->name, *dst); + } + + return 0; +} + +static char *conf_write_short(const struct parse_data *data) +{ + short *src; + int res; + char *value; + + /* TODO: [FixMe][George] FIX COMPILE WARNING HERE! */ + src = (short *)data->param1; + + value = osal_malloc(20); + if (value == NULL) + return NULL; + res = osal_snprintf(value, 20, "0x%x", *src); + if (res < 0 || res >= 20) { + osal_free(value); + return NULL; + } + value[20 - 1] = '\0'; + return value; +} + +static int conf_parse_int(const struct parse_data *data, const char *pos) +{ + int *dst; + long res = 0; + + dst = (int *)data->param1; + + if ((osal_strlen(pos) > 2) && ((*pos) == '0') && (*(pos + 1) == 'x')) { + osal_strtol(pos + 2, 16, &res); + *dst = (unsigned int)res; + pr_debug("cfg==> %s=0x%x\n", data->name, *dst); + } else { + osal_strtol(pos, 10, &res); + *dst = (unsigned int)res; + pr_debug("cfg==> %s=%d\n", data->name, *dst); + } + + return 0; +} + +static char *conf_write_int(const struct parse_data *data) +{ + int *src; + int res; + char *value; + + src = (unsigned int *) data->param1; + + value = osal_malloc(20); + if (value == NULL) + return NULL; + res = osal_snprintf(value, 20, "0x%x", *src); + if (res < 0 || res >= 20) { + osal_free(value); + return NULL; + } + value[20 - 1] = '\0'; + return value; +} + +static int conf_parse_byte_array(const struct parse_data *data, + const char *pos) +{ + unsigned char **dst; + struct conf_byte_ary *ba; + unsigned char *buffer; + int size = osal_strlen(pos) / 2; + unsigned char temp[3]; + int i; + long value; + + if (size <= 1) { + pr_err("cfg==> %s has no value assigned\n", + data->name); + return -1; + } else if (size & 0x1) { + pr_debug("cfg==> %s, length should be even\n", data->name); + return -1; + } + + ba = (struct conf_byte_ary *)osal_malloc(sizeof(struct conf_byte_ary)); + if (ba == NULL) { + pr_err("cfg==> %s malloc fail\n", data->name); + return -1; + } + + buffer = osal_malloc(size); + if (buffer == NULL) { + osal_free(ba); + pr_err("cfg==> %s malloc fail, size %d\n", data->name, size); + return -1; + } + + temp[2] = '\0'; + for (i = 0; i < size; i++) { + osal_memcpy(temp, &pos[i * 2], 2); + if (osal_strtol(temp, 16, &value) < 0) { + pr_err("cfg==> %s should be hexadecimal format\n", + data->name); + osal_free(ba); + osal_free(buffer); + return -1; + } + buffer[i] = (char)value; + } + ba->data = buffer; + ba->size = size; + + dst = (unsigned char **) data->param1; + *dst = (unsigned char *)ba; + + return 0; +} + +static char *conf_write_byte_array(const struct parse_data *data) +{ + unsigned char **src; + char *value; + struct conf_byte_ary *ba; + int i; + + src = (unsigned char **) data->param1; + if (*src == NULL) + return NULL; + + ba = (struct conf_byte_ary *)*src; + + value = osal_malloc(ba->size * 2 + 1); + if (value == NULL) + return NULL; + + for (i = 0; i < ba->size; i++) + osal_snprintf(&value[i * 2], 3, "%x", ba->data[i]); + + return value; +} + + +static void conf_release_byte_array(const struct parse_data *data) +{ + //unsigned char *buffer; + struct conf_byte_ary *ba; + unsigned char **src; + + if (data->param1 != NULL) { + src = (unsigned char **) data->param1; + ba = (struct conf_byte_ary *) *src; + if (ba->data != NULL) { + osal_free(ba->data); + ba->data = NULL; + } + osal_free(ba); + //data->param1 = NULL; + *src = NULL; + } +} + +static int conf_parse_pair(const char *pKey, const char *pVal) +{ + int i = 0; + int ret = 0; + + + for (i = 0; i < NUM_CFG_FIELDS; i++) { + const struct parse_data *field = &cfg_fields[i]; + + if (osal_strcmp(pKey, field->name) != 0) + continue; + if (field->parser(field, pVal)) { + pr_err("failed to parse %s '%s'.\n", pKey, pVal); + ret = -1; + } + break; + } + if (i == NUM_CFG_FIELDS) { + pr_err("unknown field '%s'.\n", pKey); + ret = -1; + } + + return ret; +} + +static int conf_parse(const char *pInBuf, unsigned int size) +{ + char *pch; + char *pBuf; + char *pLine; + char *pKey; + char *pVal; + char *pPos; + int ret = 0; + int i = 0; + char *pa = NULL; + + pBuf = osal_malloc(size+1); + if (!pBuf) + return -1; + + osal_memcpy(pBuf, pInBuf, size); + pBuf[size] = '\0'; + + pch = pBuf; + /* pch is to be updated by strsep(). Keep pBuf unchanged!! */ + + while ((pLine = osal_strsep(&pch, "\r\n")) != NULL) { + /* pch is updated to the end of pLine by + * strsep() and updated to '\0' + */ + /* parse each line */ + + if (!*pLine) + continue; + + pVal = osal_strchr(pLine, '='); + if (!pVal) { + pr_warn("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'; + + ret = conf_parse_pair(pKey, pVal); + pr_debug("parse (%s, %s, %d)\n", pKey, pVal, ret); + if (ret) + pr_debug("parse fail (%s, %s, %d)\n", pKey, pVal, ret); + } + + for (i = 0; i < NUM_CFG_FIELDS; i++) { + const struct parse_data *field = &cfg_fields[i]; + + pa = field->writer(field); + if (pa) { + pr_debug("#%d(%s)=>%s\n", i, field->name, pa); + osal_free(pa); + } else + pr_err("failed to parse '%s'.\n", field->name); + } + osal_free(pBuf); + return 0; +} + +static int platform_request_firmware(char *patch_name, osal_firmware **ppPatch) +{ + int ret; + osal_firmware *fw = NULL; + + if (!ppPatch) { + pr_err("invalid ppBufptr!\n"); + return -1; + } + + *ppPatch = NULL; + do { + ret = request_firmware((const struct firmware **)&fw, + patch_name, NULL); + if (ret == -EAGAIN) { + pr_err("failed to open or read!(%s), retry again!\n", + patch_name); + osal_sleep_ms(100); + } + } while (ret == -EAGAIN); + if (ret != 0) { + pr_err("failed to open or read!(%s)\n", patch_name); + release_firmware(fw); + return -1; + } + pr_debug("loader firmware %s ok!!\n", patch_name); + ret = 0; + *ppPatch = fw; + + return ret; +} + +static int platform_release_firmware(osal_firmware **ppPatch) +{ + if (*ppPatch != NULL) { + release_firmware((const struct firmware *)*ppPatch); + *ppPatch = NULL; + } + return 0; +} + +int conninfra_conf_init(void) +{ + int ret = -1; + const osal_firmware *conf_inst; + + osal_memset(&g_conninfra_conf, 0, osal_sizeof(struct conninfra_conf)); + osal_strcpy(&(g_conninfra_conf.conf_name[0]), "conninfra.cfg"); + + pr_debug("config file:%s\n", &(g_conninfra_conf.conf_name[0])); + if (0 == + platform_request_firmware(&g_conninfra_conf.conf_name[0], + (osal_firmware **) &conf_inst)) { + /*get full name patch success */ + pr_debug("get full file name(%s) buf(0x%p) size(%zu)\n", + &g_conninfra_conf.conf_name[0], conf_inst->data, + conf_inst->size); + if (0 == + conf_parse((const char *)conf_inst->data, + conf_inst->size)) { + /*config file exists */ + g_conninfra_conf.cfg_exist = 1; + ret = 0; + } else { + pr_err("conf parsing fail\n"); + ret = -1; + } + platform_release_firmware((osal_firmware **) &conf_inst); + return ret; + } + pr_err("read %s file fails\n", &(g_conninfra_conf.conf_name[0])); + g_conninfra_conf.cfg_exist = 0; + return ret; +} + +int conninfra_conf_set_cfg_file(const char *name) +{ + if (name == NULL) { + pr_err("name is NULL\n"); + return -1; + } + if (osal_strlen(name) >= osal_sizeof(g_conninfra_conf.conf_name)) { + pr_err("name is too long, length=%d, expect to < %zu\n", + osal_strlen(name), + osal_sizeof(g_conninfra_conf.conf_name)); + return -2; + } + osal_memset(&g_conninfra_conf.conf_name[0], 0, + osal_sizeof(g_conninfra_conf.conf_name)); + osal_strcpy(&(g_conninfra_conf.conf_name[0]), name); + pr_err("WMT config file is set to (%s)\n", + &(g_conninfra_conf.conf_name[0])); + + return 0; +} + +const struct conninfra_conf *conninfra_conf_get_cfg(void) +{ + if (g_conninfra_conf.cfg_exist == 0) + return NULL; + + return &g_conninfra_conf; +} + +int conninfra_conf_deinit(void) +{ + int i; + + if (g_conninfra_conf.cfg_exist == 0) + return -1; + + for (i = 0; i < NUM_CFG_FIELDS; i++) { + const struct parse_data *field = &cfg_fields[i]; + field->relase_mem(field); + } + g_conninfra_conf.cfg_exist = 0; + return 0; +} + diff --git a/drivers/misc/mediatek/connectivity/conninfra/conf/include/conninfra_conf.h b/drivers/misc/mediatek/connectivity/conninfra/conf/include/conninfra_conf.h new file mode 100644 index 0000000000000..8aa9169dd117f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/conf/include/conninfra_conf.h @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + +#ifndef _CONNINFRA_CONF_H_ +#define _CONNINFRA_CONF_H_ + +#include "osal.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define CUST_CFG_INFRA "WMT.cfg" +#define CUST_CFG_INFRA_SOC "WMT_SOC.cfg" + +/******************************************************************************* +* 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 +******************************************************************************** +*/ +struct conf_byte_ary { + unsigned int size; + char *data; +}; + +struct conninfra_conf { + + char conf_name[NAME_MAX + 1]; + //const osal_firmware *conf_inst; + unsigned char cfg_exist; + + unsigned char coex_wmt_ant_mode; + unsigned char coex_wmt_ant_mode_ex; + unsigned char coex_wmt_ext_component; + unsigned char coex_wmt_wifi_time_ctl; + unsigned char coex_wmt_ext_pta_dev_on; + /*combo chip and LTE coex filter mode setting */ + unsigned char coex_wmt_filter_mode; + + unsigned char coex_bt_rssi_upper_limit; + unsigned char coex_bt_rssi_mid_limit; + unsigned char coex_bt_rssi_lower_limit; + unsigned char coex_bt_pwr_high; + unsigned char coex_bt_pwr_mid; + unsigned char coex_bt_pwr_low; + + unsigned char coex_wifi_rssi_upper_limit; + unsigned char coex_wifi_rssi_mid_limit; + unsigned char coex_wifi_rssi_lower_limit; + unsigned char coex_wifi_pwr_high; + unsigned char coex_wifi_pwr_mid; + unsigned char coex_wifi_pwr_low; + + unsigned char coex_ext_pta_hi_tx_tag; + unsigned char coex_ext_pta_hi_rx_tag; + unsigned char coex_ext_pta_lo_tx_tag; + unsigned char coex_ext_pta_lo_rx_tag; + unsigned short coex_ext_pta_sample_t1; + unsigned short coex_ext_pta_sample_t2; + unsigned char coex_ext_pta_wifi_bt_con_trx; + + unsigned int coex_misc_ext_pta_on; + unsigned int coex_misc_ext_feature_set; + /*GPS LNA setting */ + unsigned char wmt_gps_lna_pin; + unsigned char wmt_gps_lna_enable; + /*Power on sequence */ + unsigned char pwr_on_rtc_slot; + unsigned char pwr_on_ldo_slot; + unsigned char pwr_on_rst_slot; + unsigned char pwr_on_off_slot; + unsigned char pwr_on_on_slot; + unsigned char co_clock_flag; + + /*deep sleep feature flag*/ + unsigned char disable_deep_sleep_cfg; + + /* Combo chip side SDIO driving setting */ + unsigned int sdio_driving_cfg; + + /* Combo chip WiFi path setting */ + unsigned short coex_wmt_wifi_path; + /* Combo chip WiFi eLAN gain setting */ + unsigned char coex_wmt_ext_elna_gain_p1_support; + unsigned int coex_wmt_ext_elna_gain_p1_D0; + unsigned int coex_wmt_ext_elna_gain_p1_D1; + unsigned int coex_wmt_ext_elna_gain_p1_D2; + unsigned int coex_wmt_ext_elna_gain_p1_D3; + + struct conf_byte_ary *coex_wmt_epa_elna; + + unsigned char bt_tssi_from_wifi; + unsigned short bt_tssi_target; + + unsigned char coex_config_bt_ctrl; + unsigned char coex_config_bt_ctrl_mode; + unsigned char coex_config_bt_ctrl_rw; + + unsigned char coex_config_addjust_opp_time_ratio; + unsigned char coex_config_addjust_opp_time_ratio_bt_slot; + unsigned char coex_config_addjust_opp_time_ratio_wifi_slot; + + unsigned char coex_config_addjust_ble_scan_time_ratio; + unsigned char coex_config_addjust_ble_scan_time_ratio_bt_slot; + unsigned char coex_config_addjust_ble_scan_time_ratio_wifi_slot; + + /* POS. If set, means using ext TCXO */ + unsigned char tcxo_gpio; + + unsigned char pre_cal_mode; +}; + + + +/******************************************************************************* +* 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 +******************************************************************************** +*/ +const struct conninfra_conf *conninfra_conf_get_cfg(void); +int conninfra_conf_set_cfg_file(const char *name); + +int conninfra_conf_init(void); +int conninfra_conf_deinit(void); + +#endif /* _CONNINFRA_CONF_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/core/conninfra_core.c b/drivers/misc/mediatek/connectivity/conninfra/core/conninfra_core.c new file mode 100644 index 0000000000000..b9c204f6acd79 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/core/conninfra_core.c @@ -0,0 +1,1806 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#define pr_fmt(fmt) KBUILD_MODNAME "@(%s:%d) " fmt, __func__, __LINE__ + +#include "consys_hw.h" +#include "conninfra_core.h" +#include "msg_thread.h" +#include "consys_reg_mng.h" +#include "conninfra_conf.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define CONNINFRA_EVENT_TIMEOUT 3000 +#define CONNINFRA_RESET_TIMEOUT 500 +#define CONNINFRA_PRE_CAL_TIMEOUT 500 + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static int opfunc_power_on(struct msg_op_data *op); +static int opfunc_power_off(struct msg_op_data *op); +static int opfunc_chip_rst(struct msg_op_data *op); +static int opfunc_pre_cal(struct msg_op_data *op); +static int opfunc_therm_ctrl(struct msg_op_data *op); +static int opfunc_rfspi_read(struct msg_op_data *op); +static int opfunc_rfspi_write(struct msg_op_data *op); +static int opfunc_adie_top_ck_en_on(struct msg_op_data *op); +static int opfunc_adie_top_ck_en_off(struct msg_op_data *op); +static int opfunc_spi_clock_switch(struct msg_op_data *op); +static int opfunc_clock_fail_dump(struct msg_op_data *op); +static int opfunc_pre_cal_prepare(struct msg_op_data *op); +static int opfunc_pre_cal_check(struct msg_op_data *op); + +static int opfunc_force_conninfra_wakeup(struct msg_op_data *op); +static int opfunc_force_conninfra_sleep(struct msg_op_data *op); + +static int opfunc_dump_power_state(struct msg_op_data *op); + +static int opfunc_subdrv_pre_reset(struct msg_op_data *op); +static int opfunc_subdrv_post_reset(struct msg_op_data *op); +static int opfunc_subdrv_cal_pwr_on(struct msg_op_data *op); +static int opfunc_subdrv_cal_do_cal(struct msg_op_data *op); +static int opfunc_subdrv_therm_ctrl(struct msg_op_data *op); + +static void _conninfra_core_update_rst_status(enum chip_rst_status status); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +struct conninfra_ctx g_conninfra_ctx; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static const msg_opid_func conninfra_core_opfunc[] = { + [CONNINFRA_OPID_PWR_ON] = opfunc_power_on, + [CONNINFRA_OPID_PWR_OFF] = opfunc_power_off, + [CONNINFRA_OPID_THERM_CTRL] = opfunc_therm_ctrl, + [CONNINFRA_OPID_RFSPI_READ] = opfunc_rfspi_read, + [CONNINFRA_OPID_RFSPI_WRITE] = opfunc_rfspi_write, + [CONNINFRA_OPID_ADIE_TOP_CK_EN_ON] = opfunc_adie_top_ck_en_on, + [CONNINFRA_OPID_ADIE_TOP_CK_EN_OFF] = opfunc_adie_top_ck_en_off, + [CONNINFRA_OPID_SPI_CLOCK_SWITCH] = opfunc_spi_clock_switch, + [CONNINFRA_OPID_CLOCK_FAIL_DUMP] = opfunc_clock_fail_dump, + [CONNINFRA_OPID_PRE_CAL_PREPARE] = opfunc_pre_cal_prepare, + [CONNINFRA_OPID_PRE_CAL_CHECK] = opfunc_pre_cal_check, + + [CONNINFRA_OPID_FORCE_CONNINFRA_WAKUP] = opfunc_force_conninfra_wakeup, + [CONNINFRA_OPID_FORCE_CONNINFRA_SLEEP] = opfunc_force_conninfra_sleep, + + [CONNINFRA_OPID_DUMP_POWER_STATE] = opfunc_dump_power_state, +}; + +static const msg_opid_func conninfra_core_cb_opfunc[] = { + [CONNINFRA_CB_OPID_CHIP_RST] = opfunc_chip_rst, + [CONNINFRA_CB_OPID_PRE_CAL] = opfunc_pre_cal, +}; + + +/* subsys ops */ +static char *drv_thread_name[] = { + [CONNDRV_TYPE_BT] = "sub_bt_thrd", + [CONNDRV_TYPE_FM] = "sub_fm_thrd", + [CONNDRV_TYPE_GPS] = "sub_gps_thrd", + [CONNDRV_TYPE_WIFI] = "sub_wifi_thrd", + [CONNDRV_TYPE_CONNINFRA] = "sub_conninfra_thrd", +}; + +static char *drv_name[] = { + [CONNDRV_TYPE_BT] = "BT", + [CONNDRV_TYPE_FM] = "FM", + [CONNDRV_TYPE_GPS] = "GPS", + [CONNDRV_TYPE_WIFI] = "WIFI", + [CONNDRV_TYPE_CONNINFRA] = "CONNINFRA", +}; + +typedef enum { + INFRA_SUBDRV_OPID_PRE_RESET = 0, + INFRA_SUBDRV_OPID_POST_RESET = 1, + INFRA_SUBDRV_OPID_CAL_PWR_ON = 2, + INFRA_SUBDRV_OPID_CAL_DO_CAL = 3, + INFRA_SUBDRV_OPID_THERM_CTRL = 4, + + INFRA_SUBDRV_OPID_MAX +} infra_subdrv_op; + + +static const msg_opid_func infra_subdrv_opfunc[] = { + [INFRA_SUBDRV_OPID_PRE_RESET] = opfunc_subdrv_pre_reset, + [INFRA_SUBDRV_OPID_POST_RESET] = opfunc_subdrv_post_reset, + [INFRA_SUBDRV_OPID_CAL_PWR_ON] = opfunc_subdrv_cal_pwr_on, + [INFRA_SUBDRV_OPID_CAL_DO_CAL] = opfunc_subdrv_cal_do_cal, + [INFRA_SUBDRV_OPID_THERM_CTRL] = opfunc_subdrv_therm_ctrl, +}; + +enum pre_cal_type { + PRE_CAL_ALL_ENABLED = 0, + PRE_CAL_ALL_DISABLED = 1, + PRE_CAL_PWR_ON_DISABLED = 2, + PRE_CAL_SCREEN_ON_DISABLED = 3 +}; + +static unsigned int g_pre_cal_mode = 0; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +static void reset_chip_rst_trg_data(void) +{ + g_conninfra_ctx.trg_drv = CONNDRV_TYPE_MAX; + memset(g_conninfra_ctx.trg_reason, '\0', CHIP_RST_REASON_MAX_LEN); +} + +static unsigned long timeval_to_ms(struct timeval *begin, struct timeval *end) +{ + unsigned long time_diff; + + time_diff = (end->tv_sec - begin->tv_sec) * 1000; + time_diff += (end->tv_usec - begin->tv_usec) / 1000; + + return time_diff; +} + +static unsigned int opfunc_get_current_status(void) +{ + unsigned int ret = 0; + unsigned int i; + + for (i = 0; i < CONNDRV_TYPE_MAX; i++) { + ret |= (g_conninfra_ctx.drv_inst[i].drv_status << i); + } + + return ret; +} + +static void opfunc_vcn_control_internal(unsigned int drv_type, bool on) +{ + /* VCNx enable */ + switch (drv_type) { + case CONNDRV_TYPE_BT: + consys_hw_bt_power_ctl(on); + break; + case CONNDRV_TYPE_FM: + consys_hw_fm_power_ctl(on); + break; + case CONNDRV_TYPE_GPS: + consys_hw_gps_power_ctl(on); + break; + case CONNDRV_TYPE_WIFI: + consys_hw_wifi_power_ctl(on); + break; + default: + pr_err("Wrong parameter: drv_type(%d)\n", drv_type); + break; + } +} + +static int opfunc_power_on_internal(unsigned int drv_type) +{ + int ret; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + + /* Check abnormal type */ + if (drv_type >= CONNDRV_TYPE_MAX) { + pr_err("abnormal Fun(%d)\n", drv_type); + return -EINVAL; + } + + /* Check abnormal state */ + if ((g_conninfra_ctx.drv_inst[drv_type].drv_status < DRV_STS_POWER_OFF) + || (g_conninfra_ctx.drv_inst[drv_type].drv_status >= DRV_STS_MAX)) { + pr_err("func(%d) status[0x%x] abnormal\n", drv_type, + g_conninfra_ctx.drv_inst[drv_type].drv_status); + return -EINVAL; + } + + ret = osal_lock_sleepable_lock(&infra_ctx->core_lock); + if (ret) { + pr_err("core_lock fail!!"); + return ret; + } + + /* check if func already on */ + if (g_conninfra_ctx.drv_inst[drv_type].drv_status == DRV_STS_POWER_ON) { + pr_warn("func(%d) already on\n", drv_type); + osal_unlock_sleepable_lock(&infra_ctx->core_lock); + return 0; + } + + ret = consys_hw_pwr_on(opfunc_get_current_status(), drv_type); + if (ret) { + pr_err("Conninfra power on fail. drv(%d) ret=(%d)\n", + drv_type, ret); + osal_unlock_sleepable_lock(&infra_ctx->core_lock); + return -3; + } + /* POWER ON SEQUENCE */ + g_conninfra_ctx.infra_drv_status = DRV_STS_POWER_ON; + + g_conninfra_ctx.drv_inst[drv_type].drv_status = DRV_STS_POWER_ON; + + /* VCNx enable */ + opfunc_vcn_control_internal(drv_type, true); + + pr_info("[Conninfra Pwr On] BT=[%d] FM=[%d] GPS=[%d] WF=[%d]", + infra_ctx->drv_inst[CONNDRV_TYPE_BT].drv_status, + infra_ctx->drv_inst[CONNDRV_TYPE_FM].drv_status, + infra_ctx->drv_inst[CONNDRV_TYPE_GPS].drv_status, + infra_ctx->drv_inst[CONNDRV_TYPE_WIFI].drv_status); + osal_unlock_sleepable_lock(&infra_ctx->core_lock); + + return 0; +} + +static int opfunc_power_on(struct msg_op_data *op) +{ + unsigned int drv_type = op->op_data[0]; + + return opfunc_power_on_internal(drv_type); +} + +static int opfunc_power_off_internal(unsigned int drv_type) +{ + int i, ret; + bool try_power_off = true; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + unsigned int curr_status = opfunc_get_current_status(); + + /* Check abnormal type */ + if (drv_type >= CONNDRV_TYPE_MAX) { + pr_err("abnormal Fun(%d)\n", drv_type); + return -EINVAL; + } + + ret = osal_lock_sleepable_lock(&infra_ctx->core_lock); + if (ret) { + pr_err("core_lock fail!!"); + return ret; + } + + /* Check abnormal state */ + if ((g_conninfra_ctx.drv_inst[drv_type].drv_status < DRV_STS_POWER_OFF) + || (g_conninfra_ctx.drv_inst[drv_type].drv_status >= DRV_STS_MAX)) { + pr_err("func(%d) status[0x%x] abnormal\n", drv_type, + g_conninfra_ctx.drv_inst[drv_type].drv_status); + osal_unlock_sleepable_lock(&infra_ctx->core_lock); + return -2; + } + + /* Special case for force power off */ + if (drv_type == CONNDRV_TYPE_CONNINFRA) { + if (g_conninfra_ctx.infra_drv_status == DRV_STS_POWER_OFF) { + pr_warn("Connsys already off, do nothing for force off\n"); + return 0; + } + /* Turn off subsys VCN and update record */ + for (i = 0; i < CONNDRV_TYPE_MAX; i++) { + if (g_conninfra_ctx.drv_inst[i].drv_status == DRV_STS_POWER_ON) { + opfunc_vcn_control_internal(i, false); + g_conninfra_ctx.drv_inst[i].drv_status = DRV_STS_POWER_OFF; + } + } + /* POWER OFF SEQUENCE */ + ret = consys_hw_pwr_off(0, drv_type); + /* For force power off operation, ignore err code */ + if (ret) + pr_err("Force power off fail. ret=%d\n", ret); + try_power_off = true; + } else { + /* check if func already off */ + if (g_conninfra_ctx.drv_inst[drv_type].drv_status + == DRV_STS_POWER_OFF) { + pr_warn("func(%d) already off\n", drv_type); + osal_unlock_sleepable_lock(&infra_ctx->core_lock); + return 0; + } + /* VCNx disable */ + opfunc_vcn_control_internal(drv_type, false); + g_conninfra_ctx.drv_inst[drv_type].drv_status = DRV_STS_POWER_OFF; + /* is there subsys on ? */ + for (i = 0; i < CONNDRV_TYPE_MAX; i++) + if (g_conninfra_ctx.drv_inst[i].drv_status == DRV_STS_POWER_ON) + try_power_off = false; + + /* POWER OFF SEQUENCE */ + ret = consys_hw_pwr_off(curr_status, drv_type); + if (ret) { + pr_err("Conninfra power on fail. drv(%d) ret=(%d)\n", + drv_type, ret); + osal_unlock_sleepable_lock(&infra_ctx->core_lock); + return -3; + } + } + + if (try_power_off) + g_conninfra_ctx.infra_drv_status = DRV_STS_POWER_OFF; + + pr_info("[Conninfra Pwr Off] Conninfra=[%d] BT=[%d] FM=[%d] GPS=[%d] WF=[%d]", + infra_ctx->infra_drv_status, + infra_ctx->drv_inst[CONNDRV_TYPE_BT].drv_status, + infra_ctx->drv_inst[CONNDRV_TYPE_FM].drv_status, + infra_ctx->drv_inst[CONNDRV_TYPE_GPS].drv_status, + infra_ctx->drv_inst[CONNDRV_TYPE_WIFI].drv_status); + + osal_unlock_sleepable_lock(&infra_ctx->core_lock); + return 0; +} + +static int opfunc_power_off(struct msg_op_data *op) +{ + unsigned int drv_type = op->op_data[0]; + + return opfunc_power_off_internal(drv_type); +} + +static int opfunc_chip_rst(struct msg_op_data *op) +{ + int i, ret, cur_rst_state; + struct subsys_drv_inst *drv_inst; + unsigned int drv_pwr_state[CONNDRV_TYPE_MAX]; + const unsigned int subdrv_all_done = (0x1 << CONNDRV_TYPE_MAX) - 1; + struct timeval pre_begin, pre_end, reset_end, done_end; + + if (g_conninfra_ctx.infra_drv_status == DRV_STS_POWER_OFF) { + pr_info("No subsys on, just return"); + _conninfra_core_update_rst_status(CHIP_RST_NONE); + return 0; + } + + do_gettimeofday(&pre_begin); + + atomic_set(&g_conninfra_ctx.rst_state, 0); + sema_init(&g_conninfra_ctx.rst_sema, 1); + + _conninfra_core_update_rst_status(CHIP_RST_PRE_CB); + + /* pre */ + for (i = 0; i < CONNDRV_TYPE_MAX; i++) { + drv_inst = &g_conninfra_ctx.drv_inst[i]; + drv_pwr_state[i] = drv_inst->drv_status; + pr_info("subsys %d is %d", i, drv_inst->drv_status); + ret = msg_thread_send_1(&drv_inst->msg_ctx, + INFRA_SUBDRV_OPID_PRE_RESET, i); + } + + pr_info("[chip_rst] pre vvvvvvvvvvvvv"); + while (atomic_read(&g_conninfra_ctx.rst_state) != subdrv_all_done) { + ret = down_timeout(&g_conninfra_ctx.rst_sema, msecs_to_jiffies(CONNINFRA_RESET_TIMEOUT)); + pr_info("sema ret=[%d]", ret); + if (ret == 0) + continue; + cur_rst_state = atomic_read(&g_conninfra_ctx.rst_state); + pr_info("cur_rst state =[%d]", cur_rst_state); + for (i = 0; i < CONNDRV_TYPE_MAX; i++) { + if ((cur_rst_state & (0x1 << i)) == 0) { + pr_info("[chip_rst] [%s] pre-callback is not back", drv_thread_name[i]); + drv_inst = &g_conninfra_ctx.drv_inst[i]; + osal_thread_show_stack(&drv_inst->msg_ctx.thread); + } + } + } + + _conninfra_core_update_rst_status(CHIP_RST_RESET); + + do_gettimeofday(&pre_end); + + pr_info("[chip_rst] reset ++++++++++++"); + /*******************************************************/ + /* reset */ + /* call consys_hw */ + /*******************************************************/ + /* Special power-off function, turn off connsys directly */ + ret = opfunc_power_off_internal(CONNDRV_TYPE_CONNINFRA); + pr_info("Force conninfra power off, ret=%d\n", ret); + pr_info("conninfra status should be power off. Status=%d", g_conninfra_ctx.infra_drv_status); + + /* Turn on subsys */ + for (i = 0; i < CONNDRV_TYPE_MAX; i++) { + if (drv_pwr_state[i]) { + ret = opfunc_power_on_internal(i); + pr_info("Call subsys(%d) power on ret=%d", i, ret); + } + } + pr_info("conninfra status should be power on. Status=%d", g_conninfra_ctx.infra_drv_status); + + pr_info("[chip_rst] reset --------------"); + + _conninfra_core_update_rst_status(CHIP_RST_POST_CB); + + do_gettimeofday(&reset_end); + + /* post */ + atomic_set(&g_conninfra_ctx.rst_state, 0); + sema_init(&g_conninfra_ctx.rst_sema, 1); + for (i = 0; i < CONNDRV_TYPE_MAX; i++) { + drv_inst = &g_conninfra_ctx.drv_inst[i]; + ret = msg_thread_send_1(&drv_inst->msg_ctx, + INFRA_SUBDRV_OPID_POST_RESET, i); + } + + while (atomic_read(&g_conninfra_ctx.rst_state) != subdrv_all_done) { + ret = down_timeout(&g_conninfra_ctx.rst_sema, msecs_to_jiffies(CONNINFRA_RESET_TIMEOUT)); + if (ret == 0) + continue; + cur_rst_state = atomic_read(&g_conninfra_ctx.rst_state); + for (i = 0; i < CONNDRV_TYPE_MAX; i++) { + if ((cur_rst_state & (0x1 << i)) == 0) { + pr_info("[chip_rst] [%s] post-callback is not back", drv_thread_name[i]); + drv_inst = &g_conninfra_ctx.drv_inst[i]; + osal_thread_show_stack(&drv_inst->msg_ctx.thread); + } + } + } + pr_info("[chip_rst] post ^^^^^^^^^^^^^^"); + + reset_chip_rst_trg_data(); + //_conninfra_core_update_rst_status(CHIP_RST_DONE); + _conninfra_core_update_rst_status(CHIP_RST_NONE); + do_gettimeofday(&done_end); + + pr_info("[chip_rst] summary pre=[%lu] reset=[%lu] post=[%lu]", + timeval_to_ms(&pre_begin, &pre_end), + timeval_to_ms(&pre_end, &reset_end), + timeval_to_ms(&reset_end, &done_end)); + + return 0; +} + +static int opfunc_pre_cal(struct msg_op_data *op) +{ +#define CAL_DRV_COUNT 2 + int cal_drvs[CAL_DRV_COUNT] = {CONNDRV_TYPE_BT, CONNDRV_TYPE_WIFI}; + int i, ret, cur_state; + int bt_cal_ret, wf_cal_ret; + struct subsys_drv_inst *drv_inst; + int pre_cal_done_state = (0x1 << CONNDRV_TYPE_BT) | (0x1 << CONNDRV_TYPE_WIFI); + struct timeval begin, bt_cal_begin, wf_cal_begin, end; + + /* Check BT/WIFI status again */ + ret = osal_lock_sleepable_lock(&g_conninfra_ctx.core_lock); + if (ret) { + pr_err("[%s] core_lock fail!!", __func__); + return ret; + } + /* check if func already on */ + for (i = 0; i < CAL_DRV_COUNT; i++) { + if (g_conninfra_ctx.drv_inst[cal_drvs[i]].drv_status == DRV_STS_POWER_ON) { + pr_warn("[%s] %s already on\n", __func__, drv_name[cal_drvs[i]]); + osal_unlock_sleepable_lock(&g_conninfra_ctx.core_lock); + return 0; + } + } + osal_unlock_sleepable_lock(&g_conninfra_ctx.core_lock); + + ret = conninfra_core_power_on(CONNDRV_TYPE_BT); + if (ret) { + pr_err("BT power on fail during pre_cal"); + return -1; + } + ret = conninfra_core_power_on(CONNDRV_TYPE_WIFI); + if (ret) { + pr_err("WIFI power on fail during pre_cal"); + conninfra_core_power_off(CONNDRV_TYPE_BT); + return -2; + } + + do_gettimeofday(&begin); + + /* power on subsys */ + atomic_set(&g_conninfra_ctx.pre_cal_state, 0); + sema_init(&g_conninfra_ctx.pre_cal_sema, 1); + + for (i = 0; i < CAL_DRV_COUNT; i++) { + drv_inst = &g_conninfra_ctx.drv_inst[cal_drvs[i]]; + ret = msg_thread_send_1(&drv_inst->msg_ctx, + INFRA_SUBDRV_OPID_CAL_PWR_ON, cal_drvs[i]); + if (ret) + pr_warn("driver [%d] power on fail\n", cal_drvs[i]); + } + + while (atomic_read(&g_conninfra_ctx.pre_cal_state) != pre_cal_done_state) { + ret = down_timeout(&g_conninfra_ctx.pre_cal_sema, msecs_to_jiffies(CONNINFRA_PRE_CAL_TIMEOUT)); + if (ret == 0) + continue; + cur_state = atomic_read(&g_conninfra_ctx.pre_cal_state); + pr_info("[pre_cal] cur state =[%d]", cur_state); + if ((cur_state & (0x1 << CONNDRV_TYPE_BT)) == 0) { + pr_info("[pre_cal] BT pwr_on callback is not back"); + drv_inst = &g_conninfra_ctx.drv_inst[CONNDRV_TYPE_BT]; + osal_thread_show_stack(&drv_inst->msg_ctx.thread); + } + if ((cur_state & (0x1 << CONNDRV_TYPE_WIFI)) == 0) { + pr_info("[pre_cal] WIFI pwr_on callback is not back"); + drv_inst = &g_conninfra_ctx.drv_inst[CONNDRV_TYPE_WIFI]; + osal_thread_show_stack(&drv_inst->msg_ctx.thread); + } + } + pr_info("[pre_cal] >>>>>>> power on DONE!!"); + + do_gettimeofday(&bt_cal_begin); + + /* Do Calibration */ + drv_inst = &g_conninfra_ctx.drv_inst[CONNDRV_TYPE_BT]; + bt_cal_ret = msg_thread_send_wait_1(&drv_inst->msg_ctx, + INFRA_SUBDRV_OPID_CAL_DO_CAL, 0, CONNDRV_TYPE_BT); + + pr_info("[pre_cal] driver [%s] calibration %s, ret=[%d]\n", drv_name[CONNDRV_TYPE_BT], + (bt_cal_ret == CONNINFRA_CB_RET_CAL_FAIL_POWER_OFF || + bt_cal_ret == CONNINFRA_CB_RET_CAL_FAIL_POWER_ON) ? "fail" : "success", + bt_cal_ret); + + if (bt_cal_ret == CONNINFRA_CB_RET_CAL_PASS_POWER_OFF || + bt_cal_ret == CONNINFRA_CB_RET_CAL_FAIL_POWER_OFF) + conninfra_core_power_off(CONNDRV_TYPE_BT); + + pr_info("[pre_cal] >>>>>>>> BT do cal done"); + + do_gettimeofday(&wf_cal_begin); + + drv_inst = &g_conninfra_ctx.drv_inst[CONNDRV_TYPE_WIFI]; + wf_cal_ret = msg_thread_send_wait_1(&drv_inst->msg_ctx, + INFRA_SUBDRV_OPID_CAL_DO_CAL, 0, CONNDRV_TYPE_WIFI); + + pr_info("[pre_cal] driver [%s] calibration %s, ret=[%d]\n", drv_name[CONNDRV_TYPE_WIFI], + (wf_cal_ret == CONNINFRA_CB_RET_CAL_FAIL_POWER_OFF || + wf_cal_ret == CONNINFRA_CB_RET_CAL_FAIL_POWER_ON) ? "fail" : "success", + wf_cal_ret); + + if (wf_cal_ret == CONNINFRA_CB_RET_CAL_PASS_POWER_OFF || + wf_cal_ret == CONNINFRA_CB_RET_CAL_FAIL_POWER_OFF) + conninfra_core_power_off(CONNDRV_TYPE_WIFI); + + pr_info(">>>>>>>> WF do cal done"); + + do_gettimeofday(&end); + + pr_info("[pre_cal] summary pwr=[%lu] bt_cal=[%d][%lu] wf_cal=[%d][%lu]", + timeval_to_ms(&begin, &bt_cal_begin), + bt_cal_ret, timeval_to_ms(&bt_cal_begin, &wf_cal_begin), + wf_cal_ret, timeval_to_ms(&wf_cal_begin, &end)); + + return 0; +} + + +static int opfunc_therm_ctrl(struct msg_op_data *op) +{ + int ret = -1; + int *data_ptr = (int*)op->op_data[0]; + + if (g_conninfra_ctx.infra_drv_status != DRV_STS_POWER_ON) { + *data_ptr = 0; + return 0; + } + + if (data_ptr) + ret = consys_hw_therm_query(data_ptr); + return ret; +} + + +static int opfunc_rfspi_read(struct msg_op_data *op) +{ + int ret = 0; + unsigned int data = 0; + unsigned int* data_pt = (unsigned int*)op->op_data[2]; + + ret = osal_lock_sleepable_lock(&g_conninfra_ctx.core_lock); + if (ret) { + pr_err("core_lock fail!!\n"); + return CONNINFRA_SPI_OP_FAIL; + } + + if (g_conninfra_ctx.infra_drv_status != DRV_STS_POWER_ON) { + pr_err("Connsys didn't power on\n"); + ret = CONNINFRA_SPI_OP_FAIL; + goto err; + } + if (consys_hw_reg_readable() == 0) { + pr_err("connsys reg not readable\n"); + ret = CONNINFRA_SPI_OP_FAIL; + goto err; + } + /* DO read spi */ + ret = consys_hw_spi_read(op->op_data[0], op->op_data[1], &data); + if (data_pt) + *(data_pt) = data; +err: + osal_unlock_sleepable_lock(&g_conninfra_ctx.core_lock); + return ret; +} + +static int opfunc_rfspi_write(struct msg_op_data *op) +{ + int ret = 0; + + ret = osal_lock_sleepable_lock(&g_conninfra_ctx.core_lock); + if (ret) { + pr_err("core_lock fail!!\n"); + return CONNINFRA_SPI_OP_FAIL; + } + + if (g_conninfra_ctx.infra_drv_status != DRV_STS_POWER_ON) { + pr_err("Connsys didn't power on\n"); + ret = CONNINFRA_SPI_OP_FAIL; + goto err; + } + if (consys_hw_reg_readable() == 0) { + pr_err("connsys reg not readable\n"); + ret = CONNINFRA_SPI_OP_FAIL; + goto err; + } + /* DO spi write */ + ret = consys_hw_spi_write(op->op_data[0], op->op_data[1], op->op_data[2]); +err: + osal_unlock_sleepable_lock(&g_conninfra_ctx.core_lock); + return ret; +} + +static int opfunc_adie_top_ck_en_on(struct msg_op_data *op) +{ + int ret = 0; + unsigned int type = op->op_data[0]; + + if (type >= CONNSYS_ADIE_CTL_MAX) { + pr_err("wrong parameter %d\n", type); + return -EINVAL; + } + + ret = osal_lock_sleepable_lock(&g_conninfra_ctx.core_lock); + if (ret) { + pr_err("core_lock fail!!\n"); + ret = -1; + goto err; + } + + if (g_conninfra_ctx.infra_drv_status != DRV_STS_POWER_ON) { + pr_err("Connsys didn't power on\n"); + ret = -2; + goto err; + } + + ret = consys_hw_adie_top_ck_en_on(type); + +err: + osal_unlock_sleepable_lock(&g_conninfra_ctx.core_lock); + return ret; +} + + +static int opfunc_adie_top_ck_en_off(struct msg_op_data *op) +{ + int ret = 0; + unsigned int type = op->op_data[0]; + + if (type >= CONNSYS_ADIE_CTL_MAX) { + pr_err("wrong parameter %d\n", type); + return -EINVAL; + } + + ret = osal_lock_sleepable_lock(&g_conninfra_ctx.core_lock); + if (ret) { + pr_err("core_lock fail!!\n"); + ret = -1; + goto err; + } + if (g_conninfra_ctx.infra_drv_status != DRV_STS_POWER_ON) { + pr_err("Connsys didn't power on\n"); + ret = -2; + goto err; + } + + ret = consys_hw_adie_top_ck_en_off(type); +err: + osal_unlock_sleepable_lock(&g_conninfra_ctx.core_lock); + return ret; +} + +static int opfunc_spi_clock_switch(struct msg_op_data *op) +{ + int ret = 0; + unsigned int type = op->op_data[0]; + + if (type >= CONNSYS_SPI_SPEED_MAX) { + pr_err("wrong parameter %d\n", type); + return -EINVAL; + } + + ret = osal_lock_sleepable_lock(&g_conninfra_ctx.core_lock); + if (ret) { + pr_err("core_lock fail!!\n"); + ret = -2; + goto err; + } + if (g_conninfra_ctx.infra_drv_status != DRV_STS_POWER_ON) { + pr_err("Connsys didn't power on\n"); + ret = -2; + goto err; + } + + ret = consys_hw_spi_clock_switch(type); +err: + osal_unlock_sleepable_lock(&g_conninfra_ctx.core_lock); + return ret; +} + + +static int opfunc_clock_fail_dump(struct msg_op_data *op) +{ + consys_hw_clock_fail_dump(); + return 0; +} + + +static int opfunc_pre_cal_prepare(struct msg_op_data *op) +{ + int ret, rst_status; + unsigned long flag; + struct pre_cal_info *cal_info = &g_conninfra_ctx.cal_info; + struct subsys_drv_inst *bt_drv = &g_conninfra_ctx.drv_inst[CONNDRV_TYPE_BT]; + struct subsys_drv_inst *wifi_drv = &g_conninfra_ctx.drv_inst[CONNDRV_TYPE_WIFI]; + enum pre_cal_status cur_status; + + spin_lock_irqsave(&g_conninfra_ctx.infra_lock, flag); + + if (bt_drv->ops_cb.pre_cal_cb.do_cal_cb == NULL || + wifi_drv->ops_cb.pre_cal_cb.do_cal_cb == NULL) { + pr_info("[%s] [pre_cal] [%p][%p]", __func__, + bt_drv->ops_cb.pre_cal_cb.do_cal_cb, + wifi_drv->ops_cb.pre_cal_cb.do_cal_cb); + spin_unlock_irqrestore(&g_conninfra_ctx.infra_lock, flag); + return 0; + } + spin_unlock_irqrestore(&g_conninfra_ctx.infra_lock, flag); + + spin_lock_irqsave(&g_conninfra_ctx.rst_lock, flag); + rst_status = g_conninfra_ctx.rst_status; + spin_unlock_irqrestore(&g_conninfra_ctx.rst_lock, flag); + + if (rst_status > CHIP_RST_NONE) { + pr_info("rst is ongoing, skip pre_cal"); + return 0; + } + + /* non-zero means lock got, zero means not */ + ret = osal_trylock_sleepable_lock(&cal_info->pre_cal_lock); + + if (ret) { + cur_status = cal_info->status; + + if ((cur_status == PRE_CAL_NOT_INIT || cur_status == PRE_CAL_NEED_RESCHEDULE) && + bt_drv->drv_status == DRV_STS_POWER_OFF && + wifi_drv->drv_status == DRV_STS_POWER_OFF) { + cal_info->status = PRE_CAL_SCHEDULED; + cal_info->caller = op->op_data[0]; + pr_info("[pre_cal] BT&WIFI is off, schedule pre-cal from status=[%d] to new status[%d]\n", + cur_status, cal_info->status); + schedule_work(&cal_info->pre_cal_work); + } else { + pr_info("[%s] [pre_cal] bt=[%d] wf=[%d] status=[%d]", __func__, + bt_drv->drv_status, wifi_drv->drv_status, cur_status); + } + osal_unlock_sleepable_lock(&cal_info->pre_cal_lock); + } + + return 0; +} + +static int opfunc_pre_cal_check(struct msg_op_data *op) +{ + int ret; + struct pre_cal_info *cal_info = &g_conninfra_ctx.cal_info; + struct subsys_drv_inst *bt_drv = &g_conninfra_ctx.drv_inst[CONNDRV_TYPE_BT]; + struct subsys_drv_inst *wifi_drv = &g_conninfra_ctx.drv_inst[CONNDRV_TYPE_WIFI]; + enum pre_cal_status cur_status; + + /* non-zero means lock got, zero means not */ + ret = osal_trylock_sleepable_lock(&cal_info->pre_cal_lock); + if (ret) { + cur_status = cal_info->status; + + pr_info("[%s] [pre_cal] bt=[%d] wf=[%d] status=[%d]", __func__, + bt_drv->drv_status, wifi_drv->drv_status, + cur_status); + if (cur_status == PRE_CAL_DONE && + bt_drv->drv_status == DRV_STS_POWER_OFF && + wifi_drv->drv_status == DRV_STS_POWER_OFF) { + pr_info("[pre_cal] reset pre-cal"); + cal_info->status = PRE_CAL_NEED_RESCHEDULE; + } + osal_unlock_sleepable_lock(&cal_info->pre_cal_lock); + } + return 0; +} + + +static int opfunc_force_conninfra_wakeup(struct msg_op_data *op) +{ + int ret; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + + ret = osal_lock_sleepable_lock(&infra_ctx->core_lock); + if (ret) { + pr_err("core_lock fail!!"); + return ret; + } + + /* check if conninfra already on */ + if (g_conninfra_ctx.infra_drv_status != DRV_STS_POWER_ON) { + ret = -1; + goto err; + } + + ret = consys_hw_force_conninfra_wakeup(); + if (ret) + pr_err("force conninfra wakeup fail"); + +err: + osal_unlock_sleepable_lock(&infra_ctx->core_lock); + return ret; +} + +static int opfunc_force_conninfra_sleep(struct msg_op_data *op) +{ + int ret; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + + ret = osal_lock_sleepable_lock(&infra_ctx->core_lock); + if (ret) { + pr_err("core_lock fail!!"); + return ret; + } + + /* check if conninfra already on */ + if (g_conninfra_ctx.infra_drv_status != DRV_STS_POWER_ON) { + ret = -1; + goto err; + } + + ret = consys_hw_force_conninfra_sleep(); + if (ret) + pr_err("force conninfra sleep fail"); + +err: + osal_unlock_sleepable_lock(&infra_ctx->core_lock); + return ret; +} + + +static int opfunc_dump_power_state(struct msg_op_data *op) +{ + int ret; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + + ret = osal_lock_sleepable_lock(&infra_ctx->core_lock); + if (ret) { + pr_err("core_lock fail!!"); + return ret; + } + + /* check if conninfra already on */ + if (g_conninfra_ctx.infra_drv_status != DRV_STS_POWER_ON) { + ret = -1; + goto err; + } + + ret = consys_hw_dump_power_state(); + if (ret) + pr_err("dump power state fail"); + +err: + osal_unlock_sleepable_lock(&infra_ctx->core_lock); + return ret; + +} + +static int opfunc_subdrv_pre_reset(struct msg_op_data *op) +{ + int ret, cur_rst_state; + unsigned int drv_type = op->op_data[0]; + struct subsys_drv_inst *drv_inst; + + + /* TODO: should be locked, to avoid cb was reset */ + drv_inst = &g_conninfra_ctx.drv_inst[drv_type]; + if (/*drv_inst->drv_status == DRV_ST_POWER_ON &&*/ + drv_inst->ops_cb.rst_cb.pre_whole_chip_rst) { + + ret = drv_inst->ops_cb.rst_cb.pre_whole_chip_rst(g_conninfra_ctx.trg_drv, + g_conninfra_ctx.trg_reason); + if (ret) + pr_err("[%s] fail [%d]", __func__, ret); + } + + atomic_add(0x1 << drv_type, &g_conninfra_ctx.rst_state); + cur_rst_state = atomic_read(&g_conninfra_ctx.rst_state); + + pr_info("[%s] rst_state=[%d]", drv_thread_name[drv_type], cur_rst_state); + + up(&g_conninfra_ctx.rst_sema); + return 0; +} + +static int opfunc_subdrv_post_reset(struct msg_op_data *op) +{ + int ret; + unsigned int drv_type = op->op_data[0]; + struct subsys_drv_inst *drv_inst; + + /* TODO: should be locked, to avoid cb was reset */ + drv_inst = &g_conninfra_ctx.drv_inst[drv_type]; + if (/*drv_inst->drv_status == DRV_ST_POWER_ON &&*/ + drv_inst->ops_cb.rst_cb.post_whole_chip_rst) { + ret = drv_inst->ops_cb.rst_cb.post_whole_chip_rst(); + if (ret) + pr_warn("[%s] fail [%d]", __func__, ret); + } + + atomic_add(0x1 << drv_type, &g_conninfra_ctx.rst_state); + up(&g_conninfra_ctx.rst_sema); + return 0; +} + +static int opfunc_subdrv_cal_pwr_on(struct msg_op_data *op) +{ + int ret; + unsigned int drv_type = op->op_data[0]; + struct subsys_drv_inst *drv_inst; + + pr_info("[%s] drv=[%s]", __func__, drv_thread_name[drv_type]); + + /* TODO: should be locked, to avoid cb was reset */ + drv_inst = &g_conninfra_ctx.drv_inst[drv_type]; + if (/*drv_inst->drv_status == DRV_ST_POWER_ON &&*/ + drv_inst->ops_cb.pre_cal_cb.pwr_on_cb) { + ret = drv_inst->ops_cb.pre_cal_cb.pwr_on_cb(); + if (ret) + pr_warn("[%s] fail [%d]", __func__, ret); + } + + atomic_add(0x1 << drv_type, &g_conninfra_ctx.pre_cal_state); + up(&g_conninfra_ctx.pre_cal_sema); + + pr_info("[pre_cal][%s] [%s] DONE", __func__, drv_thread_name[drv_type]); + return 0; +} + +static int opfunc_subdrv_cal_do_cal(struct msg_op_data *op) +{ + int ret = 0; + unsigned int drv_type = op->op_data[0]; + struct subsys_drv_inst *drv_inst; + + pr_info("[%s] drv=[%s]", __func__, drv_thread_name[drv_type]); + + drv_inst = &g_conninfra_ctx.drv_inst[drv_type]; + if (/*drv_inst->drv_status == DRV_ST_POWER_ON &&*/ + drv_inst->ops_cb.pre_cal_cb.do_cal_cb) { + ret = drv_inst->ops_cb.pre_cal_cb.do_cal_cb(); + if (ret) + pr_warn("[%s] fail [%d]", __func__, ret); + } + + pr_info("[pre_cal][%s] [%s] DONE", __func__, drv_thread_name[drv_type]); + return ret; +} + +static int opfunc_subdrv_therm_ctrl(struct msg_op_data *op) +{ + return 0; +} + + +/* + * CONNINFRA API + */ +int conninfra_core_power_on(enum consys_drv_type type) +{ + int ret = 0; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + + ret = msg_thread_send_wait_1(&infra_ctx->msg_ctx, + CONNINFRA_OPID_PWR_ON, 0, type); + if (ret) { + pr_err("[%s] fail, ret = %d\n", __func__, ret); + return -1; + } + return 0; +} + +int conninfra_core_power_off(enum consys_drv_type type) +{ + int ret = 0; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + + ret = msg_thread_send_wait_1(&infra_ctx->msg_ctx, + CONNINFRA_OPID_PWR_OFF, 0, type); + if (ret) { + pr_err("[%s] send msg fail, ret = %d\n", __func__, ret); + return -1; + } + return 0; +} + +int conninfra_core_pre_cal_start(void) +{ + int ret = 0; + bool skip = false; + enum pre_cal_caller caller; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + struct pre_cal_info *cal_info = &infra_ctx->cal_info; + + ret = osal_lock_sleepable_lock(&cal_info->pre_cal_lock); + if (ret) { + pr_err("[%s] get lock fail, ret = %d\n", + __func__, ret); + return -1; + } + + caller = cal_info->caller; + pr_info("[%s] [pre_cal] Caller = %u", __func__, caller); + + /* Handle different pre_cal_mode */ + switch (g_pre_cal_mode) { + case PRE_CAL_ALL_DISABLED: + pr_info("[%s] [pre_cal] Skip all pre-cal", __func__); + skip = true; + cal_info->status = PRE_CAL_DONE; + break; + case PRE_CAL_PWR_ON_DISABLED: + if (caller == PRE_CAL_BY_SUBDRV_REGISTER) { + pr_info("[%s] [pre_cal] Skip pre-cal triggered by subdrv register", __func__); + skip = true; + cal_info->status = PRE_CAL_NOT_INIT; + } + break; + case PRE_CAL_SCREEN_ON_DISABLED: + if (caller == PRE_CAL_BY_SCREEN_ON) { + pr_info("[%s] [pre_cal] Skip pre-cal triggered by screen on", __func__); + skip = true; + cal_info->status = PRE_CAL_DONE; + } + break; + default: + pr_info("[%s] [pre_cal] Begin pre-cal, g_pre_cal_mode: %u", + __func__, g_pre_cal_mode); + break; + } + + if (skip) { + pr_info("[%s] [pre_cal] Reset status to %d", __func__, cal_info->status); + osal_unlock_sleepable_lock(&cal_info->pre_cal_lock); + return -2; + } + + cal_info->status = PRE_CAL_EXECUTING; + ret = msg_thread_send_wait(&infra_ctx->cb_ctx, + CONNINFRA_CB_OPID_PRE_CAL, 0); + if (ret) { + pr_err("[%s] send msg fail, ret = %d\n", __func__, ret); + } + + cal_info->status = PRE_CAL_DONE; + osal_unlock_sleepable_lock(&cal_info->pre_cal_lock); + return 0; +} + +int conninfra_core_screen_on(void) +{ + int ret = 0, rst_status; + unsigned long flag; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + + spin_lock_irqsave(&infra_ctx->rst_lock, flag); + rst_status = g_conninfra_ctx.rst_status; + spin_unlock_irqrestore(&infra_ctx->rst_lock, flag); + + if (rst_status > CHIP_RST_NONE) { + pr_info("rst is ongoing, skip pre_cal"); + return 0; + } + + ret = msg_thread_send_1(&infra_ctx->msg_ctx, + CONNINFRA_OPID_PRE_CAL_PREPARE, PRE_CAL_BY_SCREEN_ON); + if (ret) { + pr_err("[%s] send msg fail, ret = %d\n", __func__, ret); + return -1; + } + return 0; +} + +int conninfra_core_screen_off(void) +{ + int ret = 0; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + + ret = msg_thread_send(&infra_ctx->msg_ctx, + CONNINFRA_OPID_PRE_CAL_CHECK); + if (ret) { + pr_err("[%s] send msg fail, ret = %d\n", __func__, ret); + return -1; + } + + return 0; +} + +int conninfra_core_reg_readable(void) +{ + int ret = 0, rst_status; + unsigned long flag; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + + + /* check if in reseting, can not read */ + spin_lock_irqsave(&g_conninfra_ctx.rst_lock, flag); + rst_status = g_conninfra_ctx.rst_status; + spin_unlock_irqrestore(&g_conninfra_ctx.rst_lock, flag); + + if (rst_status >= CHIP_RST_RESET && + rst_status < CHIP_RST_POST_CB) + return 0; + + ret = osal_lock_sleepable_lock(&infra_ctx->core_lock); + if (ret) { + pr_err("core_lock fail!!"); + return 0; + } + + if (infra_ctx->infra_drv_status == DRV_STS_POWER_ON) + ret = consys_hw_reg_readable(); + osal_unlock_sleepable_lock(&infra_ctx->core_lock); + + return ret; +} + +int conninfra_core_reg_readable_no_lock(void) +{ + int rst_status; + unsigned long flag; + + /* check if in reseting, can not read */ + spin_lock_irqsave(&g_conninfra_ctx.rst_lock, flag); + rst_status = g_conninfra_ctx.rst_status; + spin_unlock_irqrestore(&g_conninfra_ctx.rst_lock, flag); + + if (rst_status >= CHIP_RST_RESET && + rst_status < CHIP_RST_POST_CB) + return 0; + + return consys_hw_reg_readable(); +} + +int conninfra_core_is_bus_hang(void) +{ + int ret = 0; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + + ret = osal_lock_sleepable_lock(&infra_ctx->core_lock); + if (ret) { + pr_err("core_lock fail!!"); + return 0; + } + + if (infra_ctx->infra_drv_status == DRV_STS_POWER_ON) + ret = consys_hw_is_bus_hang(); + osal_unlock_sleepable_lock(&infra_ctx->core_lock); + + return ret; + +} + +int conninfra_core_is_consys_reg(phys_addr_t addr) +{ + return consys_hw_is_connsys_reg(addr); +} + +int conninfra_core_reg_read(unsigned long address, unsigned int *value, unsigned int mask) +{ + int ret = 0; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + + ret = osal_lock_sleepable_lock(&infra_ctx->core_lock); + if (ret) { + pr_err("core_lock fail!!"); + return 0; + } + + if (infra_ctx->infra_drv_status == DRV_STS_POWER_ON) { + if (consys_reg_mng_is_host_csr(address)) + ret = consys_reg_mng_reg_read(address, value, mask); + else if (consys_hw_reg_readable()) + ret = consys_reg_mng_reg_read(address, value, mask); + else + pr_info("CR (%lx) is not readable\n", address); + } else + pr_info("CR (%lx) cannot read. conninfra is off\n", address); + + osal_unlock_sleepable_lock(&infra_ctx->core_lock); + return ret; +} + +int conninfra_core_reg_write(unsigned long address, unsigned int value, unsigned int mask) +{ + int ret = 0; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + + ret = osal_lock_sleepable_lock(&infra_ctx->core_lock); + if (ret) { + pr_err("core_lock fail!!"); + return 0; + } + + if (infra_ctx->infra_drv_status == DRV_STS_POWER_ON) { + if (consys_reg_mng_is_host_csr(address)) + ret = consys_reg_mng_reg_write(address, value, mask); + else if (consys_hw_reg_readable()) + ret = consys_reg_mng_reg_write(address, value, mask); + else + pr_info("CR (%p) is not readable\n", (void*)address); + } else + pr_info("CR (%p) cannot read. conninfra is off\n", (void*)address); + + osal_unlock_sleepable_lock(&infra_ctx->core_lock); + return ret; + +} + +int conninfra_core_lock_rst(void) +{ + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + int ret = 0; + unsigned long flag; + + spin_lock_irqsave(&infra_ctx->rst_lock, flag); + + ret = infra_ctx->rst_status; + if (infra_ctx->rst_status > CHIP_RST_NONE && + infra_ctx->rst_status < CHIP_RST_DONE) { + /* do nothing */ + } else { + infra_ctx->rst_status = CHIP_RST_START; + } + spin_unlock_irqrestore(&infra_ctx->rst_lock, flag); + + pr_info("[%s] ret=[%d]", __func__, ret); + return ret; +} + +int conninfra_core_unlock_rst(void) +{ + unsigned long flag; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + + spin_lock_irqsave(&infra_ctx->rst_lock, flag); + infra_ctx->rst_status = CHIP_RST_NONE; + spin_unlock_irqrestore(&infra_ctx->rst_lock, flag); + return 0; +} + +int conninfra_core_trg_chip_rst(enum consys_drv_type drv, char *reason) +{ + int ret = 0; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + + infra_ctx->trg_drv = drv; + if (snprintf(infra_ctx->trg_reason, CHIP_RST_REASON_MAX_LEN, "%s", reason) < 0) + pr_warn("[%s::%d] snprintf error\n", __func__, __LINE__); + ret = msg_thread_send_1(&infra_ctx->cb_ctx, + CONNINFRA_CB_OPID_CHIP_RST, drv); + if (ret) { + pr_err("[%s] send msg fail, ret = %d", __func__, ret); + return -1; + } + pr_info("trg_reset DONE!"); + return 0; +} + +int conninfra_core_thermal_query(int *temp_val) +{ + int ret = 0; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + + ret = msg_thread_send_wait_1(&infra_ctx->msg_ctx, + CONNINFRA_OPID_THERM_CTRL, 0, + (size_t) temp_val); + if (ret) { + pr_err("send msg fail ret=%d\n", ret); + return ret; + } + pr_info("ret=[%d] temp=[%d]\n", ret, *temp_val); + return ret; +} + +void conninfra_core_clock_fail_dump_cb(void) +{ + int ret = 0; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + + ret = msg_thread_send(&infra_ctx->msg_ctx, + CONNINFRA_OPID_CLOCK_FAIL_DUMP); + if (ret) + pr_err("failed (ret = %d)", ret); +} + +static inline char* conninfra_core_spi_subsys_string(enum sys_spi_subsystem subsystem) +{ + static char* subsys_name[] = { + "SYS_SPI_WF1", + "SYS_SPI_WF", + "SYS_SPI_BT", + "SYS_SPI_FM", + "SYS_SPI_GPS", + "SYS_SPI_TOP", + "SYS_SPI_WF2", + "SYS_SPI_WF3", + "SYS_SPI_MAX" + }; + + if (subsystem < 0 || subsystem > SYS_SPI_MAX) + return "UNKNOWN"; + + return subsys_name[subsystem]; +} + +int conninfra_core_spi_read(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data) +{ + int ret = 0; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + size_t data_ptr = (size_t)data; + + ret = msg_thread_send_wait_3(&infra_ctx->msg_ctx, + CONNINFRA_OPID_RFSPI_READ, 0, + subsystem, addr, data_ptr); + if (ret) { + pr_err("[%s] failed (ret = %d). subsystem=%s addr=%x\n", + __func__, ret, conninfra_core_spi_subsys_string(subsystem), addr); + return CONNINFRA_SPI_OP_FAIL; + } + return 0; +} + +int conninfra_core_spi_write(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data) +{ + int ret; + ret = msg_thread_send_wait_3(&(g_conninfra_ctx.msg_ctx), CONNINFRA_OPID_RFSPI_WRITE, 0, + subsystem, addr, data); + if (ret) { + pr_err("[%s] failed (ret = %d). subsystem=%s addr=0x%x data=%d\n", + __func__, ret, conninfra_core_spi_subsys_string(subsystem), addr, data); + return CONNINFRA_SPI_OP_FAIL; + } + return 0; +} + +int conninfra_core_adie_top_ck_en_on(enum consys_adie_ctl_type type) +{ + int ret = 0; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + + ret = msg_thread_send_wait_1(&infra_ctx->msg_ctx, + CONNINFRA_OPID_ADIE_TOP_CK_EN_ON, 0, type); + if (ret) { + pr_err("[%s] fail, ret = %d\n", __func__, ret); + return -1; + } + return 0; +} + +int conninfra_core_adie_top_ck_en_off(enum consys_adie_ctl_type type) +{ + int ret = 0; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + + ret = msg_thread_send_wait_1(&infra_ctx->msg_ctx, + CONNINFRA_OPID_ADIE_TOP_CK_EN_OFF, 0, type); + if (ret) { + pr_err("[%s] fail, ret = %d\n", __func__, ret); + return -1; + } + return 0; +} + +int conninfra_core_force_conninfra_wakeup(void) +{ + int ret = 0; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + + /* if in conninfra_cored thread */ + if (current == infra_ctx->msg_ctx.thread.pThread) + return opfunc_force_conninfra_wakeup(NULL); + + ret = msg_thread_send_wait(&infra_ctx->msg_ctx, + CONNINFRA_OPID_FORCE_CONNINFRA_WAKUP, 0); + if (ret) { + pr_err("[%s] fail, ret = %d\n", __func__, ret); + return -1; + } + return 0; +} + +int conninfra_core_force_conninfra_sleep(void) +{ + int ret = 0; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + + /* if in conninfra_cored thread */ + if (current == infra_ctx->msg_ctx.thread.pThread) + return opfunc_force_conninfra_sleep(NULL); + + ret = msg_thread_send_wait(&infra_ctx->msg_ctx, + CONNINFRA_OPID_FORCE_CONNINFRA_SLEEP, 0); + if (ret) { + pr_err("[%s] fail, ret = %d\n", __func__, ret); + return -1; + } + return 0; +} + +int conninfra_core_spi_clock_switch(enum connsys_spi_speed_type type) +{ + int ret = 0; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + + ret = msg_thread_send_wait_1(&infra_ctx->msg_ctx, + CONNINFRA_OPID_SPI_CLOCK_SWITCH, 0, type); + if (ret) { + pr_err("[%s] fail, ret = %d\n", __func__, ret); + return -1; + } + return 0; +} + +int conninfra_core_subsys_ops_reg(enum consys_drv_type type, + struct sub_drv_ops_cb *cb) +{ + unsigned long flag; + struct subsys_drv_inst *drv_inst; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + int ret, trigger_pre_cal = 0; + + if (type < CONNDRV_TYPE_BT || type >= CONNDRV_TYPE_MAX) + return -1; + + spin_lock_irqsave(&g_conninfra_ctx.infra_lock, flag); + drv_inst = &g_conninfra_ctx.drv_inst[type]; + memcpy(&g_conninfra_ctx.drv_inst[type].ops_cb, cb, + sizeof(struct sub_drv_ops_cb)); + + pr_info("[%s] [pre_cal] type=[%s] cb rst=[%p][%p] pre_cal=[%p][%p], therm=[%p]", + __func__, drv_name[type], + cb->rst_cb.pre_whole_chip_rst, cb->rst_cb.post_whole_chip_rst, + cb->pre_cal_cb.pwr_on_cb, cb->pre_cal_cb.do_cal_cb, cb->thermal_qry); + + pr_info("[%s] [pre_cal] type=[%d] bt=[%p] wf=[%p]", __func__, type, + infra_ctx->drv_inst[CONNDRV_TYPE_BT].ops_cb.pre_cal_cb.pwr_on_cb, + infra_ctx->drv_inst[CONNDRV_TYPE_WIFI].ops_cb.pre_cal_cb.pwr_on_cb); + + /* trigger pre-cal if BT and WIFI are registered */ + if (infra_ctx->drv_inst[CONNDRV_TYPE_BT].ops_cb.pre_cal_cb.do_cal_cb != NULL && + infra_ctx->drv_inst[CONNDRV_TYPE_WIFI].ops_cb.pre_cal_cb.do_cal_cb != NULL) + trigger_pre_cal = 1; + + spin_unlock_irqrestore(&g_conninfra_ctx.infra_lock, flag); + + if (trigger_pre_cal) { + pr_info("[%s] [pre_cal] trigger pre-cal BT/WF are registered", __func__); + ret = msg_thread_send_1(&infra_ctx->msg_ctx, + CONNINFRA_OPID_PRE_CAL_PREPARE, PRE_CAL_BY_SUBDRV_REGISTER); + if (ret) + pr_err("send pre_cal_prepare msg fail, ret = %d\n", ret); + } + + return 0; +} + +int conninfra_core_subsys_ops_unreg(enum consys_drv_type type) +{ + unsigned long flag; + + if (type < CONNDRV_TYPE_BT || type >= CONNDRV_TYPE_MAX) + return -1; + spin_lock_irqsave(&g_conninfra_ctx.infra_lock, flag); + memset(&g_conninfra_ctx.drv_inst[type].ops_cb, 0, + sizeof(struct sub_drv_ops_cb)); + spin_unlock_irqrestore(&g_conninfra_ctx.infra_lock, flag); + + return 0; +} + +#if ENABLE_PRE_CAL_BLOCKING_CHECK +void conninfra_core_pre_cal_blocking(void) +{ +#define BLOCKING_CHECK_MONITOR_THREAD 100 + int ret; + struct pre_cal_info *cal_info = &g_conninfra_ctx.cal_info; + struct timeval start, end; + unsigned long diff; + static bool ever_pre_cal = false; + + do_gettimeofday(&start); + + /* non-zero means lock got, zero means not */ + while (true) { + // Handle PRE_CAL_PWR_ON_DISABLED case: + // 1. Do pre-cal "only once" after bootup if BT or WIFI is default on + // 2. Use ever_pre_cal to check if the "first" pre-cal is already + // triggered. If yes, skip pre-cal + if (g_pre_cal_mode == PRE_CAL_PWR_ON_DISABLED && !ever_pre_cal) { + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + + ret = msg_thread_send_1(&infra_ctx->msg_ctx, + CONNINFRA_OPID_PRE_CAL_PREPARE, PRE_CAL_BY_SUBDRV_PWR_ON); + ever_pre_cal = true; + pr_info("[%s] [pre_cal] Triggered by subdrv power on and set ever_pre_cal to true, result: %d", __func__, ret); + } + + ret = osal_trylock_sleepable_lock(&cal_info->pre_cal_lock); + if (ret) { + if (cal_info->status == PRE_CAL_NOT_INIT || + cal_info->status == PRE_CAL_SCHEDULED) { + pr_info("[%s] [pre_cal] ret=[%d] status=[%d]", __func__, ret, cal_info->status); + osal_unlock_sleepable_lock(&cal_info->pre_cal_lock); + osal_sleep_ms(100); + continue; + } + osal_unlock_sleepable_lock(&cal_info->pre_cal_lock); + break; + } else { + pr_info("[%s] [pre_cal] ret=[%d] status=[%d]", __func__, ret, cal_info->status); + osal_sleep_ms(100); + } + } + do_gettimeofday(&end); + + diff = timeval_to_ms(&start, &end); + if (diff > BLOCKING_CHECK_MONITOR_THREAD) + pr_info("blocking spent [%lu]", diff); +} +#endif + + +static void _conninfra_core_update_rst_status(enum chip_rst_status status) +{ + unsigned long flag; + + spin_lock_irqsave(&g_conninfra_ctx.rst_lock, flag); + g_conninfra_ctx.rst_status = status; + spin_unlock_irqrestore(&g_conninfra_ctx.rst_lock, flag); +} + + +int conninfra_core_is_rst_locking(void) +{ + unsigned long flag; + int ret = 0; + + spin_lock_irqsave(&g_conninfra_ctx.rst_lock, flag); + + if (g_conninfra_ctx.rst_status > CHIP_RST_NONE && + g_conninfra_ctx.rst_status < CHIP_RST_POST_CB) + ret = 1; + spin_unlock_irqrestore(&g_conninfra_ctx.rst_lock, flag); + return ret; +} + +static void conninfra_core_pre_cal_work_handler(struct work_struct *work) +{ + int ret; + + /* if fail, do we need re-try? */ + ret = conninfra_core_pre_cal_start(); + pr_info("[%s] [pre_cal][ret=%d] -----------", __func__, ret); +} + + +int conninfra_core_dump_power_state(void) +{ + int ret = 0; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + + ret = msg_thread_send(&infra_ctx->msg_ctx, + CONNINFRA_OPID_DUMP_POWER_STATE); + if (ret) { + pr_err("[%s] fail, ret = %d\n", __func__, ret); + return -1; + } + return 0; + +} + +void conninfra_core_config_setup(void) +{ + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + int ret; + + ret = osal_lock_sleepable_lock(&infra_ctx->core_lock); + if (ret) { + pr_err("[%s] core_lock fail!!\n", __func__); + return; + } + + if (infra_ctx->infra_drv_status == DRV_STS_POWER_ON) + consys_hw_config_setup(); + + osal_unlock_sleepable_lock(&infra_ctx->core_lock); +} + +int conninfra_core_pmic_event_cb(unsigned int id, unsigned int event) +{ + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + int ret; + + if (conninfra_core_is_rst_locking()) { + return 0; + } + + ret = osal_lock_sleepable_lock(&infra_ctx->core_lock); + if (ret) { + pr_err("[%s] core_lock fail!!\n", __func__); + return 0; + } + + if (infra_ctx->infra_drv_status == DRV_STS_POWER_ON) + consys_hw_pmic_event_cb(id, event); + + osal_unlock_sleepable_lock(&infra_ctx->core_lock); + + return 0; +} + +int conninfra_core_bus_clock_ctrl(enum consys_drv_type drv_type, unsigned int bus_clock, int status) +{ + int ret = -1, rst_status; + unsigned long flag; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + + /* check if in reseting, can not read */ + spin_lock_irqsave(&g_conninfra_ctx.rst_lock, flag); + rst_status = g_conninfra_ctx.rst_status; + spin_unlock_irqrestore(&g_conninfra_ctx.rst_lock, flag); + + if (rst_status >= CHIP_RST_RESET && + rst_status < CHIP_RST_POST_CB) + return -1; + + ret = osal_lock_sleepable_lock(&infra_ctx->core_lock); + if (ret) { + pr_err("[%s] core_lock fail!!", __func__); + return -1; + } + + if (infra_ctx->infra_drv_status == DRV_STS_POWER_ON) + ret = consys_hw_bus_clock_ctrl(drv_type, bus_clock, status); + osal_unlock_sleepable_lock(&infra_ctx->core_lock); + + return ret; +} + +int conninfra_core_init(void) +{ + int ret = 0, i; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + + // Get pre-cal mode + const struct conninfra_conf *conf = NULL; + conf = conninfra_conf_get_cfg(); + if (conf != NULL) { + g_pre_cal_mode = conf->pre_cal_mode; + } + pr_info("[%s] [pre_cal] Init g_pre_cal_mode = %u", __func__, g_pre_cal_mode); + + osal_memset(&g_conninfra_ctx, 0, sizeof(g_conninfra_ctx)); + + reset_chip_rst_trg_data(); + + spin_lock_init(&infra_ctx->infra_lock); + osal_sleepable_lock_init(&infra_ctx->core_lock); + spin_lock_init(&infra_ctx->rst_lock); + + + ret = msg_thread_init(&infra_ctx->msg_ctx, "conninfra_cored", + conninfra_core_opfunc, CONNINFRA_OPID_MAX); + if (ret) { + pr_err("msg_thread init fail(%d)\n", ret); + return -1; + } + + ret = msg_thread_init(&infra_ctx->cb_ctx, "conninfra_cb", + conninfra_core_cb_opfunc, CONNINFRA_CB_OPID_MAX); + if (ret) { + pr_err("callback msg thread init fail(%d)\n", ret); + return -1; + } + /* init subsys drv state */ + for (i = 0; i < CONNDRV_TYPE_MAX; i++) { + ret += msg_thread_init(&infra_ctx->drv_inst[i].msg_ctx, + drv_thread_name[i], infra_subdrv_opfunc, + INFRA_SUBDRV_OPID_MAX); + } + + if (ret) { + pr_err("subsys callback thread init fail.\n"); + return -1; + } + + INIT_WORK(&infra_ctx->cal_info.pre_cal_work, conninfra_core_pre_cal_work_handler); + osal_sleepable_lock_init(&infra_ctx->cal_info.pre_cal_lock); + + return ret; +} + + +int conninfra_core_deinit(void) +{ + int ret, i; + struct conninfra_ctx *infra_ctx = &g_conninfra_ctx; + + osal_sleepable_lock_deinit(&infra_ctx->cal_info.pre_cal_lock); + + for (i = 0; i < CONNDRV_TYPE_MAX; i++) { + ret = msg_thread_deinit(&infra_ctx->drv_inst[i].msg_ctx); + if (ret) + pr_warn("subdrv [%d] msg_thread deinit fail (%d)\n", + i, ret); + } + + ret = msg_thread_deinit(&infra_ctx->msg_ctx); + if (ret) { + pr_err("msg_thread_deinit fail(%d)\n", ret); + return -1; + } + + osal_sleepable_lock_deinit(&infra_ctx->core_lock); + //osal_sleepable_lock_deinit(&infra_ctx->rst_lock); + + return 0; +} + + + diff --git a/drivers/misc/mediatek/connectivity/conninfra/core/include/conninfra_core.h b/drivers/misc/mediatek/connectivity/conninfra/core/include/conninfra_core.h new file mode 100644 index 0000000000000..82dc62bb05b97 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/core/include/conninfra_core.h @@ -0,0 +1,249 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _CONNINFRA_CORE_H_ +#define _CONNINFRA_CORE_H_ + +#include +#include +#include +#include + +#include "osal.h" +#include "msg_thread.h" +#include "conninfra.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define ENABLE_PRE_CAL_BLOCKING_CHECK 1 +#define CHIP_RST_REASON_MAX_LEN 128 + +/******************************************************************************* +* 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_DRV_STS_ { + DRV_STS_POWER_OFF = 0, /* initial state */ + DRV_STS_POWER_ON = 1, /* powered on */ + DRV_STS_RESET = 2, + DRV_STS_MAX +} ENUM_DRV_STS, *P_ENUM_DRV_STS; + +enum pre_cal_status { + PRE_CAL_NOT_INIT = 0, + PRE_CAL_NEED_RESCHEDULE = 1, + PRE_CAL_SCHEDULED = 2, + PRE_CAL_EXECUTING = 3, + PRE_CAL_DONE = 4 +}; + +enum pre_cal_caller { + PRE_CAL_BY_NONE = 0, + PRE_CAL_BY_SUBDRV_REGISTER = 1, + PRE_CAL_BY_SUBDRV_PWR_ON = 2, + PRE_CAL_BY_SCREEN_ON = 3 +}; + +enum chip_rst_status { + CHIP_RST_NONE = 0, + CHIP_RST_START = 1, + CHIP_RST_PRE_CB = 2, + CHIP_RST_RESET = 3, + CHIP_RST_POST_CB = 4, + CHIP_RST_DONE = 5 +}; + +struct subsys_drv_inst { + ENUM_DRV_STS drv_status; /* Controlled driver status */ + unsigned int rst_state; + struct sub_drv_ops_cb ops_cb; + struct msg_thread_ctx msg_ctx; +}; + +struct pre_cal_info { + enum pre_cal_status status; + enum pre_cal_caller caller; + struct work_struct pre_cal_work; + OSAL_SLEEPABLE_LOCK pre_cal_lock; +}; + + +/* + * state of conninfra + * + */ +struct conninfra_ctx { + ENUM_DRV_STS infra_drv_status; + + struct subsys_drv_inst drv_inst[CONNDRV_TYPE_MAX]; + /*struct spinlock infra_lock;*/ + spinlock_t infra_lock; + + OSAL_SLEEPABLE_LOCK core_lock; + + /* chip reset */ + enum chip_rst_status rst_status; + spinlock_t rst_lock; + + struct semaphore rst_sema; + atomic_t rst_state; + enum consys_drv_type trg_drv; + char trg_reason[CHIP_RST_REASON_MAX_LEN]; + + /* pre_cal */ + struct semaphore pre_cal_sema; + atomic_t pre_cal_state; + + struct msg_thread_ctx msg_ctx; + struct msg_thread_ctx cb_ctx; + + unsigned int hw_ver; + unsigned int fw_ver; + unsigned int ip_ver; + + struct osal_op_history cored_op_history; + + struct pre_cal_info cal_info; + +}; + +//typedef enum _ENUM_CONNINFRA_CORE_OPID_T { +typedef enum { + CONNINFRA_OPID_PWR_ON = 0, + CONNINFRA_OPID_PWR_OFF = 1, + CONNINFRA_OPID_THERM_CTRL = 2, + CONNINFRA_OPID_RFSPI_READ = 5, + CONNINFRA_OPID_RFSPI_WRITE = 6, + CONNINFRA_OPID_ADIE_TOP_CK_EN_ON = 7, + CONNINFRA_OPID_ADIE_TOP_CK_EN_OFF = 8, + CONNINFRA_OPID_SPI_CLOCK_SWITCH = 9, + CONNINFRA_OPID_CLOCK_FAIL_DUMP = 10, + CONNINFRA_OPID_PRE_CAL_PREPARE = 11, + CONNINFRA_OPID_PRE_CAL_CHECK = 12, + CONNINFRA_OPID_FORCE_CONNINFRA_WAKUP = 13, + CONNINFRA_OPID_FORCE_CONNINFRA_SLEEP = 14, + CONNINFRA_OPID_DUMP_POWER_STATE = 15, + CONNINFRA_OPID_MAX +} conninfra_core_opid; + +/* For the operation which may callback subsys driver */ +typedef enum { + CONNINFRA_CB_OPID_CHIP_RST = 0, + CONNINFRA_CB_OPID_PRE_CAL = 1, + CONNINFRA_CB_OPID_MAX +} conninfra_core_cb_opid; + +/******************************************************************************* +* 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 conninfra_core_init(void); +extern int conninfra_core_deinit(void); + +int conninfra_core_power_on(enum consys_drv_type type); +int conninfra_core_power_off(enum consys_drv_type type); + +int conninfra_core_lock_rst(void); +int conninfra_core_unlock_rst(void); +int conninfra_core_trg_chip_rst(enum consys_drv_type drv, char *reason); + +int conninfra_core_subsys_ops_reg(enum consys_drv_type type, + struct sub_drv_ops_cb *cb); +int conninfra_core_subsys_ops_unreg(enum consys_drv_type type); + + +int conninfra_core_screen_on(void); +int conninfra_core_screen_off(void); + +/* pre_cal */ +int conninfra_core_pre_cal_start(void); +#if ENABLE_PRE_CAL_BLOCKING_CHECK +void conninfra_core_pre_cal_blocking(void); +#endif + +/* reg control */ +/* NOTE: NOT thread-safe + * return value + * 1 : Yes, 0: NO + */ +int conninfra_core_reg_readable(void); +int conninfra_core_reg_readable_no_lock(void); +int conninfra_core_is_bus_hang(void); + +int conninfra_core_is_consys_reg(phys_addr_t addr); +int conninfra_core_reg_read(unsigned long address, unsigned int *value, unsigned int mask); +int conninfra_core_reg_write(unsigned long address, unsigned int value, unsigned int mask); + +int conninfra_core_is_rst_locking(void); + +int conninfra_core_thermal_query(int *temp_val); +void conninfra_core_clock_fail_dump_cb(void); + +int conninfra_core_spi_read(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data); +int conninfra_core_spi_write(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data); + +int conninfra_core_adie_top_ck_en_on(enum consys_adie_ctl_type type); +int conninfra_core_adie_top_ck_en_off(enum consys_adie_ctl_type type); + +int conninfra_core_force_conninfra_wakeup(void); +int conninfra_core_force_conninfra_sleep(void); + +int conninfra_core_spi_clock_switch(enum connsys_spi_speed_type type); + +int conninfra_core_dump_power_state(void); +int conninfra_core_pmic_event_cb(unsigned int, unsigned int); + +void conninfra_core_config_setup(void); + +int conninfra_core_bus_clock_ctrl(enum consys_drv_type drv_type, unsigned int bus_clock, int status); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _CONNINFRA_CORE_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/debug_utility/conninfra_dbg.c b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/conninfra_dbg.c new file mode 100644 index 0000000000000..3d4245a836ff5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/conninfra_dbg.c @@ -0,0 +1,580 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#include +#include +#include +#include "osal.h" +#include "conninfra_dbg.h" +#include "conninfra.h" +#include "conninfra_core.h" +#include "emi_mng.h" +#include "connsys_debug_utility.h" + +#define CONNINFRA_DBG_PROCNAME "driver/conninfra_dbg" + +#define BUF_LEN_MAX 384 + +#if (defined(CONFIG_MTK_GMO_RAM_OPTIMIZE) && !defined(CONFIG_MTK_ENG_BUILD)) +#define WMT_EMI_DEBUG_BUF_SIZE (8*1024) +#else +#define WMT_EMI_DEBUG_BUF_SIZE (32*1024) +#endif + +static struct proc_dir_entry *g_conninfra_dbg_entry; + +#if CONNINFRA_DBG_SUPPORT +static ssize_t conninfra_dbg_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos); +static ssize_t conninfra_dbg_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos); + +static int conninfra_dbg_hwver_get(int par1, int par2, int par3); + +static int conninfra_dbg_chip_rst(int par1, int par2, int par3); + +static int conninfra_dbg_read_chipid(int par1, int par2, int par3); + +static int conninfra_dbg_force_conninfra_wakeup(int par1, int par2, int par3); +static int conninfra_dbg_force_conninfra_sleep(int par1, int par2, int par3); + +static int conninfra_dbg_reg_read(int par1, int par2, int par3); +static int conninfra_dbg_reg_write(int par1, int par2, int par3); + +static int conninfra_dbg_efuse_read(int par1, int par2, int par3); +static int conninfra_dbg_efuse_write(int par1, int par2, int par3); + +static int conninfra_dbg_ap_reg_read(int par1, int par2, int par3); +static int conninfra_dbg_ap_reg_write(int par1, int par2, int par3); + + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH +/* consys log, need this ?? */ +static int conninfra_dbg_set_fw_log_mode(int par1, int par2, int par3); +static int conninfra_dbg_fw_log_dump_emi(int par1, int offset, int size); +#endif + +static int conninfra_dbg_suspend_debug(int par1, int offset, int size); +static int conninfra_dbg_fw_log_ctrl(int par1, int onoff, int level); + +static int conninfra_dbg_thermal_query(int par1, int count, int interval); +static int conninfra_dbg_thermal_ctrl(int par1, int par2, int par3); + +static int conninfra_dbg_connsys_emi_dump(int par1, int par2, int par3); +#endif /* CONNINFRA_DBG_SUPPORT */ + +static int conninfra_dbg_connsys_coredump_ctrl(int par1, int par2, int par3); +static int conninfra_dbg_connsys_coredump_mode_query(int par1, int par2, int par3); + +static const CONNINFRA_DEV_DBG_FUNC conninfra_dev_dbg_func[] = { +#if CONNINFRA_DBG_SUPPORT + [0x0] = conninfra_dbg_hwver_get, + [0x1] = conninfra_dbg_chip_rst, + [0x2] = conninfra_dbg_read_chipid, + + [0x3] = conninfra_dbg_force_conninfra_wakeup, + [0x4] = conninfra_dbg_force_conninfra_sleep, + [0x5] = conninfra_dbg_reg_read, + [0x6] = conninfra_dbg_reg_write, + + [0x7] = conninfra_dbg_efuse_read, + [0x8] = conninfra_dbg_efuse_write, + [0x9] = conninfra_dbg_ap_reg_read, + [0xa] = conninfra_dbg_ap_reg_write, + + [0xb] = conninfra_dbg_fw_log_ctrl, + [0xc] = conninfra_dbg_thermal_query, + [0xd] = conninfra_dbg_thermal_ctrl, + + [0xf] = conninfra_dbg_suspend_debug, +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + [0x10] = conninfra_dbg_set_fw_log_mode, + [0x11] = conninfra_dbg_fw_log_dump_emi, +#endif + [0x12] = conninfra_dbg_connsys_emi_dump, +#endif /* CONNINFRA_DBG_SUPPORT */ + [0x13] = conninfra_dbg_connsys_coredump_ctrl, + [0x14] = conninfra_dbg_connsys_coredump_mode_query, +}; + +#define CONNINFRA_DBG_DUMP_BUF_SIZE 1024 +char g_dump_buf[CONNINFRA_DBG_DUMP_BUF_SIZE]; +char *g_dump_buf_ptr; +int g_dump_buf_len; +static OSAL_SLEEPABLE_LOCK g_dump_lock; + +#if CONNINFRA_DBG_SUPPORT +int conninfra_dbg_hwver_get(int par1, int par2, int par3) +{ + pr_info("query chip version\n"); + /* TODO: */ + return 0; +} + +int conninfra_dbg_chip_rst(int par1, int par2, int par3) +{ + /* TODO: */ + conninfra_trigger_whole_chip_rst(CONNDRV_TYPE_BT, "Conninfra_dbg"); + return 0; +} + + +int conninfra_dbg_read_chipid(int par1, int par2, int par3) +{ + //pr_info("chip id = %d\n", wmt_lib_get_icinfo(WMTCHIN_CHIPID)); + + return 0; +} + +int conninfra_dbg_reg_read(int par1, int par2, int par3) +{ + int ret = 0, sz; + char buf[CONNINFRA_DBG_DUMP_BUF_SIZE]; + + /* par2-->register address */ + /* par3-->register mask */ + unsigned int value = 0x0; + int iRet; + + iRet = conninfra_core_reg_read(par2, &value, par3); + ret = snprintf(buf, CONNINFRA_DBG_DUMP_BUF_SIZE, + "read chip register (0x%08x) with mask (0x%08x) %s, value = 0x%08x\n", + par2, par3, iRet != 0 ? "failed" : "succeed", iRet != 0 ? -1 : value); + if (ret < 0) { + pr_info("read chip register (0x%08x) with mask (0x%08x) error(%d)\n", + par2, par3, ret); + } else + pr_info("%s", buf); + + ret = osal_lock_sleepable_lock(&g_dump_lock); + if (ret) { + pr_err("dump_lock fail!!"); + return ret; + } + + if (g_dump_buf_len < CONNINFRA_DBG_DUMP_BUF_SIZE) { + sz = strlen(buf); + sz = (sz < CONNINFRA_DBG_DUMP_BUF_SIZE - g_dump_buf_len) ? + sz : CONNINFRA_DBG_DUMP_BUF_SIZE - g_dump_buf_len; + strncpy(g_dump_buf + g_dump_buf_len, buf, sz); + g_dump_buf_len += sz; + } + + osal_unlock_sleepable_lock(&g_dump_lock); + + return 0; +} + +int conninfra_dbg_reg_write(int par1, int par2, int par3) +{ + /* par2-->register address */ + /* par3-->value to set */ + int ret; + + ret = conninfra_core_reg_write(par2, par3, 0xffffffff); + pr_info("write chip register (0x%08x) with value (0x%08x) %s\n", + par2, par3, ret != 0 ? "failed" : "succeed"); + return 0; +} + + +int conninfra_dbg_force_conninfra_wakeup(int par1, int par2, int par3) +{ + int ret; + + ret = conninfra_core_force_conninfra_wakeup(); + if (ret) + pr_info("conninfra wakup fail\n"); + else + pr_info("conninfra wakup success\n"); + + return 0; +} + +int conninfra_dbg_force_conninfra_sleep(int par1, int par2, int par3) +{ + int ret; + + ret = conninfra_core_force_conninfra_sleep(); + if (ret) + pr_info("conninfra sleep fail\n"); + else + pr_info("conninfra sleep success\n"); + + return 0; +} + +int conninfra_dbg_efuse_read(int par1, int par2, int par3) +{ +#if 0 + /* par2-->efuse address */ + /* par3-->register mask */ + Uint value = 0x0; + Uint iRet = -1; + + iRet = wmt_lib_efuse_rw(0, par2, &value, par3); + pr_info("read combo chip efuse (0x%08x) with mask (0x%08x) %s, value = 0x%08x\n", + par2, par3, iRet != 0 ? "failed" : "succeed", iRet != 0 ? -1 : value); +#endif + return 0; +} + +int conninfra_dbg_efuse_write(int par1, int par2, int par3) +{ +#if 0 + /* par2-->efuse address */ + /* par3-->value to set */ + Uint iRet = -1; + + iRet = wmt_lib_efuse_rw(1, par2, &par3, 0xffffffff); + pr_info("write combo chip efuse (0x%08x) with value (0x%08x) %s\n", + par2, par3, iRet != 0 ? "failed" : "succeed"); +#endif + return 0; +} + + +static int conninfra_dbg_ap_reg_read(int par1, int par2, int par3) +{ + int value = 0x0; + unsigned char *ap_reg_base = NULL; + + pr_info("AP register read, reg address:0x%x\n", par2); + ap_reg_base = ioremap_nocache(par2, 0x4); + if (ap_reg_base) { + value = readl(ap_reg_base); + pr_info("AP register read, reg address:0x%x, value:0x%x\n", par2, value); + iounmap(ap_reg_base); + } else + pr_err("AP register ioremap fail!\n"); + + return 0; +} + +static int conninfra_dbg_ap_reg_write(int par1, int par2, int par3) +{ + int value = 0x0; + unsigned char *ap_reg_base = NULL; + + pr_info("AP register write, reg address:0x%x, value:0x%x\n", par2, par3); + + ap_reg_base = ioremap_nocache(par2, 0x4); + if (ap_reg_base) { + writel(par3, ap_reg_base); + value = readl(ap_reg_base); + pr_info("AP register write done, value after write:0x%x\n", value); + iounmap(ap_reg_base); + } else + pr_err("AP register ioremap fail!\n"); + + return 0; +} + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH +static int conninfra_dbg_set_fw_log_mode(int par1, int par2, int par3) +{ + connsys_dedicated_log_set_log_mode(par2); + return 0; +} + +static int conninfra_dbg_fw_log_dump_emi(int par1, int offset, int size) +{ + //connsys_dedicated_log_dump_emi(offset, size); + return 0; +} +#endif + +/********************************************************/ +/* par2: */ +/* 0: Off */ +/* others: alarm time (seconds) */ +/********************************************************/ +static int conninfra_dbg_suspend_debug(int par1, int par2, int par3) +{ +#if 0 + if (par2 > 0) + connsys_log_alarm_enable(par2); + else + connsys_log_alarm_disable(); +#endif + return 0; +} + + +static int conninfra_dbg_fw_log_ctrl(int par1, int onoff, int level) +{ + /* Parameter format + * onoff: + * - bit 24~31: unused + * - bit 16~23: subsys type + * - bit 8~15 : unused + * - bit 0~7 : on/off setting + * level: only lowest 8 bites will be used. + * - bit 8~31 : unused + * - bit 0~7 : log level setting + * Example: + * 1. To turn on MCU log + * onoff = 0x0001 + * 2. To turn on Subsys Z log + * onoff = 0x0z01 (z = subsys) + * 3. To turn off Subsys Z log + * onoff = 0x0z00 (z = subsys) + */ +#if 0 + UINT8 type = (unsigned char)(onoff >> 16); + + pr_info("Configuring firmware log: type:%d, on/off:%d, level:%d\n", + type, (unsigned char)onoff, (unsigned char)level); + //wmt_lib_fw_log_ctrl(type, (unsigned char)onoff, (unsigned char)level); +#endif + return 0; +} + +int conninfra_dbg_thermal_query(int par1, int count, int interval) +{ + int temp, ret; + + ret = conninfra_core_thermal_query(&temp); + + pr_info("[Conninfra_Thermal_Query] ret=[%d] temp=[%d]", ret, temp); + + return 0; +} + +int conninfra_dbg_thermal_ctrl(int par1, int par2, int par3) +{ +#if 0 + if (par2 == 0) { + if (par3 >= 99) { + pr_info("Can`t set temp threshold greater or queal 99\n"); + return -1; + } + wmt_dev_set_temp_threshold(par3); + } +#endif + return 0; +} + +static int conninfra_dbg_connsys_emi_dump(int par1, int par2, int par3) +{ + unsigned int start; + // make size 16-byte alignment + int size = (((par3 + 15) >> 4) << 4); + void __iomem *vir_addr = NULL; + char* buf = NULL; + struct consys_emi_addr_info* addr_info = emi_mng_get_phy_addr(); + int i; + + if (par2 & 0xf) { + pr_err("EMI dump fail: wrong offset(0x%x), should be 16-byte alignment\n", par2); + return -1; + } + + start = (unsigned int)(par2 + addr_info->emi_ap_phy_addr); + + buf = (char*)osal_malloc(sizeof(char)*size); + if (buf == NULL) { + pr_err("[%s] allocate buffer fail\n", __func__); + return -1; + } + + pr_info("EMI dump, offset=0x%x(physical addr=0x%x), size=0x%x\n", par2, start, size); + vir_addr = ioremap_nocache(start, size); + if (!vir_addr) { + pr_err("ioremap fail"); + osal_free(buf); + return -1; + } + memcpy_fromio(buf, vir_addr, size); + for (i = 0; i < size; i+= 16) { + pr_info( + "EMI[0x%x]: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", + par2 + i, + buf[i + 0], buf[i + 1], buf[i + 2], buf[i + 3], + buf[i + 4], buf[i + 5], buf[i + 6], buf[i + 7], + buf[i + 8], buf[i + 9], buf[i + 0xa], buf[i + 0xb], + buf[i + 0xc], buf[i + 0xd], buf[i + 0xe], buf[i + 0xf]); + } + + iounmap(vir_addr); + osal_free(buf); + return 0; +} +#endif /* CONNINFRA_DBG_SUPPORT */ + +static int conninfra_dbg_connsys_coredump_ctrl(int par1, int par2, int par3) +{ + unsigned int orig_mode = connsys_coredump_get_mode(); + + pr_info("Setup coredump mode from %d to %d\n", orig_mode, par2); + connsys_coredump_set_dump_mode(par2); + return 0; +} + +static int conninfra_dbg_connsys_coredump_mode_query(int par1, int par2, int par3) +{ + unsigned int orig_mode = connsys_coredump_get_mode(); + + pr_info("Connsys coredump mode is [%d]\n", orig_mode); + return orig_mode; +} + +ssize_t conninfra_dbg_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + int ret = 0; + int dump_len; + + ret = osal_lock_sleepable_lock(&g_dump_lock); + if (ret) { + pr_err("dump_lock fail!!"); + return ret; + } + + if (g_dump_buf_len == 0) + goto exit; + + if (*f_pos == 0) + g_dump_buf_ptr = g_dump_buf; + + dump_len = g_dump_buf_len >= count ? count : g_dump_buf_len; + ret = copy_to_user(buf, g_dump_buf_ptr, dump_len); + if (ret) { + pr_err("copy to dump info buffer failed, ret:%d\n", ret); + ret = -EFAULT; + goto exit; + } + + *f_pos += dump_len; + g_dump_buf_len -= dump_len; + g_dump_buf_ptr += dump_len; + pr_info("conninfra_dbg:after read,wmt for dump info buffer len(%d)\n", g_dump_buf_len); + + ret = dump_len; +exit: + + osal_unlock_sleepable_lock(&g_dump_lock); + return ret; +} + +ssize_t conninfra_dbg_write(struct file *filp, const char __user *buffer, size_t count, loff_t *f_pos) +{ + size_t len = count; + char buf[256]; + char* pBuf; + int x = 0, y = 0, z = 0; + char* pToken = NULL; + char* pDelimiter = " \t"; + long res = 0; + static char dbg_enabled; + + pr_info("write parameter len = %d\n\r", (int) len); + if (len >= osal_sizeof(buf)) { + pr_err("input handling fail!\n"); + len = osal_sizeof(buf) - 1; + return -1; + } + + if (copy_from_user(buf, buffer, len)) + return -EFAULT; + + buf[len] = '\0'; + pr_info("write parameter data = %s\n\r", buf); + + pBuf = buf; + pToken = osal_strsep(&pBuf, pDelimiter); + if (pToken != NULL) { + osal_strtol(pToken, 16, &res); + x = (int)res; + } else { + x = 0; + } + + pToken = osal_strsep(&pBuf, "\t\n "); + if (pToken != NULL) { + osal_strtol(pToken, 16, &res); + y = (int)res; + pr_info("y = 0x%08x\n\r", y); + } else { + y = 3000; + /*efuse, register read write default value */ + if (0x5 == x || 0x6 == x) + y = 0x80000000; + } + + pToken = osal_strsep(&pBuf, "\t\n "); + if (pToken != NULL) { + osal_strtol(pToken, 16, &res); + z = (int)res; + } else { + z = 10; + /*efuse, register read write default value */ + if (0x5 == x || 0x6 == x) + z = 0xffffffff; + } + + pr_info("x(0x%08x), y(0x%08x), z(0x%08x)\n\r", x, y, z); + + /* For eng and userdebug load, have to enable wmt_dbg by writing 0xDB9DB9 to + * "/proc/driver/wmt_dbg" to avoid some malicious use + */ +#if CONNINFRA_DBG_SUPPORT + if (0xDB9DB9 == x) { + dbg_enabled = 1; + return len; + } +#endif + /* For user load, only 0x13 is allowed to execute */ + /* allow command 0x2e to enable catch connsys log on userload */ + if (0 == dbg_enabled && (x != 0x13) && (x != 0x14)) { + pr_info("please enable conninfra debug first\n\r"); + return len; + } + + if (osal_array_size(conninfra_dev_dbg_func) > x && NULL != conninfra_dev_dbg_func[x]) + (*conninfra_dev_dbg_func[x]) (x, y, z); + else + pr_warn("no handler defined for command id(0x%08x)\n\r", x); + + return len; +} + +int conninfra_dev_dbg_init(void) +{ + static const struct file_operations conninfra_dbg_fops = { + .owner = THIS_MODULE, + .read = conninfra_dbg_read, + .write = conninfra_dbg_write, + }; + int i_ret = 0; + + g_conninfra_dbg_entry = proc_create(CONNINFRA_DBG_PROCNAME, 0664, NULL, &conninfra_dbg_fops); + if (g_conninfra_dbg_entry == NULL) { + pr_err("Unable to create / wmt_aee proc entry\n\r"); + i_ret = -1; + } + + osal_sleepable_lock_init(&g_dump_lock); + + return i_ret; +} + +int conninfra_dev_dbg_deinit(void) +{ + osal_sleepable_lock_deinit(&g_dump_lock); + + if (g_conninfra_dbg_entry != NULL) { + proc_remove(g_conninfra_dbg_entry); + g_conninfra_dbg_entry = NULL; + } + + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/conninfra/debug_utility/conninfra_dbg.h b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/conninfra_dbg.h new file mode 100644 index 0000000000000..c06b8c6092243 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/conninfra_dbg.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#ifndef _CONNINFRA_DBG_H_ +#define _CONNINFRA_DBG_H_ +#include "osal.h" + +typedef int(*CONNINFRA_DEV_DBG_FUNC) (int par1, int par2, int par3); +int conninfra_dev_dbg_init(void); +int conninfra_dev_dbg_deinit(void); + +#endif /* _CONNINFRA_DBG_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/connsyslog.c b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/connsyslog.c new file mode 100644 index 0000000000000..eac87ed21ac0f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/connsyslog.c @@ -0,0 +1,1302 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + */ +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#include +#include +#include +#include + +#include "connsyslog.h" +#include "connsyslog_emi.h" +#include "connsyslog_hw_config.h" +#include "ring.h" +#include "ring_emi.h" + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/* Close debug log */ +//#define DEBUG_RING 1 + +#define CONNLOG_ALARM_STATE_DISABLE 0x0 +#define CONNLOG_ALARM_STATE_ENABLE 0x01 +#define CONNLOG_ALARM_STATE_RUNNING 0x03 + +#define BYETES_PER_LINE 16 +#define LOG_LINE_SIZE (3*BYETES_PER_LINE + BYETES_PER_LINE + 1) +#define IS_VISIBLE_CHAR(c) ((c) >= 32 && (c) <= 126) + +#define LOG_MAX_LEN 1024 +#define LOG_HEAD_LENG 16 +#define TIMESYNC_LENG 40 + +static const char log_head[] = {0x55, 0x00, 0x00, 0x62}; +static const char timesync_head[] = {0x55, 0x00, 0x25, 0x62}; + +struct connlog_alarm { + struct alarm alarm_timer; + unsigned int alarm_state; + unsigned int blank_state; + unsigned int alarm_sec; + spinlock_t alarm_lock; + unsigned long flags; +}; + +struct connlog_offset { + unsigned int emi_base_offset; + unsigned int emi_size; + unsigned int emi_read; + unsigned int emi_write; + unsigned int emi_buf; + unsigned int emi_guard_pattern_offset; +}; + +struct connlog_buffer { + struct ring_emi ring_emi; + struct ring ring_cache; + void *cache_base; +}; + +struct connlog_event_cb { + CONNLOG_EVENT_CB log_data_handler; +}; + +struct connlog_dev { + int conn_type; + phys_addr_t phyAddrEmiBase; + unsigned int emi_size; + void __iomem *virAddrEmiLogBase; + struct connlog_offset log_offset; + struct connlog_buffer log_buffer; + bool eirqOn; + spinlock_t irq_lock; + unsigned long flags; + unsigned int irq_counter; + struct timer_list workTimer; + struct work_struct logDataWorker; + void *log_data; + char log_line[LOG_MAX_LEN]; + struct connlog_event_cb callback; +}; + +static char *type_to_title[CONN_DEBUG_TYPE_END] = { + "wifi_fw", "bt_fw" +}; + +static struct connlog_dev* gLogDev[CONN_DEBUG_TYPE_END]; + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH +static atomic_t g_log_mode = ATOMIC_INIT(LOG_TO_FILE); +#else +static atomic_t g_log_mode = ATOMIC_INIT(PRINT_TO_KERNEL_LOG); +#endif + +static phys_addr_t gPhyEmiBase; + +/* alarm timer for suspend */ +struct connlog_alarm gLogAlarm; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static void connlog_do_schedule_work(struct connlog_dev* handler, bool count); +static void work_timer_handler(unsigned long data); +static void connlog_event_set(struct connlog_dev* handler); +static struct connlog_dev* connlog_subsys_init( + int conn_type, + phys_addr_t emiaddr, + unsigned int emi_size); +static void connlog_subsys_deinit(struct connlog_dev* handler); +static ssize_t connlog_read_internal( + struct connlog_dev* handler, int conn_type, + char *buf, char __user *userbuf, size_t count, bool to_user); +static void connlog_dump_emi(struct connlog_dev* handler, int offset, int size); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +struct connlog_emi_config* __weak get_connsyslog_platform_config(int conn_type) +{ + pr_err("Miss platform ops !!\n"); + return NULL; +} + +void *connlog_cache_allocate(size_t size) +{ + void *pBuffer = NULL; + + if (size > (PAGE_SIZE << 1)) + pBuffer = vmalloc(size); + else + pBuffer = kmalloc(size, GFP_KERNEL); + + /* If there is fragment, kmalloc may not get memory when size > one page. + * For this case, use vmalloc instead. + */ + if (pBuffer == NULL && size > PAGE_SIZE) + pBuffer = vmalloc(size); + + return pBuffer; +} + +void connlog_cache_free(const void *dst) +{ + kvfree(dst); +} + +/***************************************************************************** + * FUNCTION + * connlog_event_set + * DESCRIPTION + * Trigger event call back to wakeup waitqueue + * PARAMETERS + * conn_type [IN] subsys type + * RETURNS + * void + *****************************************************************************/ +static void connlog_event_set(struct connlog_dev* handler) +{ + if (handler->callback.log_data_handler) + handler->callback.log_data_handler(); +} + + +/***************************************************************************** +* FUNCTION +* connlog_set_ring_ready +* DESCRIPTION +* set reserved bit be EMIFWLOG to indicate that init is ready. +* PARAMETERS +* void +* RETURNS +* void +*****************************************************************************/ +static void connlog_set_ring_ready(struct connlog_dev* handler) +{ + const char ready_str[] = "EMIFWLOG"; + + memcpy_toio(handler->virAddrEmiLogBase + CONNLOG_READY_PATTERN_BASE, + ready_str, CONNLOG_READY_PATTERN_BASE_SIZE); +} + +static unsigned int connlog_cal_log_size(unsigned int emi_size) +{ + int position; + int i; + + if (emi_size > 0) { + for (i = (emi_size >> 1), position = 0; i != 0; ++position) + i >>= 1; + } else { + return 0; + } + + return (1UL << position); +} + +static int connlog_emi_init(struct connlog_dev* handler, phys_addr_t emiaddr, unsigned int emi_size) +{ + int conn_type = handler->conn_type; + unsigned int cal_log_size = connlog_cal_log_size( + emi_size - CONNLOG_EMI_BASE_OFFSET - CONNLOG_EMI_END_PATTERN_SIZE); + + if (emiaddr == 0 || cal_log_size == 0) { + pr_err("[%s] consys emi memory address invalid emi_addr=%p emi_size=%d\n", + type_to_title[conn_type], emiaddr, emi_size); + return -1; + } + pr_info("input size = %d cal_size = %d\n", emi_size, cal_log_size); + + handler->phyAddrEmiBase = emiaddr; + handler->emi_size = emi_size; + handler->virAddrEmiLogBase = ioremap_nocache(handler->phyAddrEmiBase, emi_size); + handler->log_offset.emi_base_offset = CONNLOG_EMI_BASE_OFFSET; + handler->log_offset.emi_size = cal_log_size; + handler->log_offset.emi_read = CONNLOG_EMI_READ; + handler->log_offset.emi_write = CONNLOG_EMI_WRITE; + handler->log_offset.emi_buf = CONNLOG_EMI_BUF; + handler->log_offset.emi_guard_pattern_offset = handler->log_offset.emi_buf + handler->log_offset.emi_size; + + if (handler->virAddrEmiLogBase) { + pr_info("[%s] EMI mapping OK virtual(0x%p) physical(0x%x) size=%d\n", + type_to_title[conn_type], + handler->virAddrEmiLogBase, + (unsigned int)handler->phyAddrEmiBase, + handler->emi_size); + /* Clean it */ + memset_io(handler->virAddrEmiLogBase, 0xff, handler->emi_size); + /* Clean control block as 0 */ + memset_io(handler->virAddrEmiLogBase + CONNLOG_EMI_BASE_OFFSET, 0x0, CONNLOG_EMI_32_BYTE_ALIGNED); + /* Setup henader */ + EMI_WRITE32(handler->virAddrEmiLogBase + 0, handler->log_offset.emi_base_offset); + EMI_WRITE32(handler->virAddrEmiLogBase + 4, handler->log_offset.emi_size); + /* Setup end pattern */ + memcpy_toio( + handler->virAddrEmiLogBase + handler->log_offset.emi_guard_pattern_offset, + CONNLOG_EMI_END_PATTERN, CONNLOG_EMI_END_PATTERN_SIZE); + } else { + pr_err("[%s] EMI mapping fail\n", type_to_title[conn_type]); + return -1; + } + + return 0; +} + +/***************************************************************************** +* FUNCTION +* connlog_emi_deinit +* DESCRIPTION +* Do iounmap for log buffer on EMI +* PARAMETERS +* void +* RETURNS +* void +*****************************************************************************/ +static void connlog_emi_deinit(struct connlog_dev* handler) +{ + iounmap(handler->virAddrEmiLogBase); +} + +static int connlog_buffer_init(struct connlog_dev* handler) +{ + void *pBuffer = NULL; + + /* Init ring emi */ + ring_emi_init( + handler->virAddrEmiLogBase + handler->log_offset.emi_buf, + handler->log_offset.emi_size, + handler->virAddrEmiLogBase + handler->log_offset.emi_read, + handler->virAddrEmiLogBase + handler->log_offset.emi_write, + &handler->log_buffer.ring_emi); + + /* init ring cache */ + /* TODO: use emi size. Need confirm */ + pBuffer = connlog_cache_allocate(handler->emi_size); + if (pBuffer == NULL) { + pr_info("[%s] allocate cache fail.", __func__); + return -ENOMEM; + } + + handler->log_buffer.cache_base = pBuffer; + memset(handler->log_buffer.cache_base, 0, handler->emi_size); + ring_init( + handler->log_buffer.cache_base, + handler->log_offset.emi_size, + 0, + 0, + &handler->log_buffer.ring_cache); + + return 0; +} + +static int connlog_ring_buffer_init(struct connlog_dev* handler) +{ + void *pBuffer = NULL; + if (!handler->virAddrEmiLogBase) { + pr_err("[%s] consys emi memory address phyAddrEmiBase invalid\n", + type_to_title[handler->conn_type]); + return -1; + } + connlog_buffer_init(handler); + /* TODO: use emi size. Need confirm */ + pBuffer = connlog_cache_allocate(handler->emi_size); + if (pBuffer == NULL) { + pr_info("[%s] allocate ring buffer fail.", __func__); + return -ENOMEM; + } + handler->log_data = pBuffer; + connlog_set_ring_ready(handler); + return 0; +} + +/***************************************************************************** +* FUNCTION +* connlog_ring_buffer_deinit +* DESCRIPTION +* Initialize ring buffer setting for subsys +* PARAMETERS +* void +* RETURNS +* void +*****************************************************************************/ +static void connlog_ring_buffer_deinit(struct connlog_dev* handler) +{ + if (handler->log_buffer.cache_base) { + connlog_cache_free(handler->log_buffer.cache_base); + handler->log_buffer.cache_base = NULL; + } + + if (handler->log_data) { + connlog_cache_free(handler->log_data); + handler->log_data = NULL; + } +} + +/***************************************************************************** +* FUNCTION +* work_timer_handler +* DESCRIPTION +* IRQ is still on, do schedule_work again +* PARAMETERS +* data [IN] input data +* RETURNS +* void +*****************************************************************************/ +static void work_timer_handler(unsigned long data) +{ + struct connlog_dev* handler = (struct connlog_dev*)data; + connlog_do_schedule_work(handler, false); +} + +/***************************************************************************** +* FUNCTION +* connlog_dump_buf +* DESCRIPTION +* Dump EMI content. Output format: +* xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx ................ +* 3 digits hex * 16 + 16 single char + 1 NULL terminate = 64+1 bytes +* PARAMETERS +* +* RETURNS +* void +*****************************************************************************/ +void connsys_log_dump_buf(const char *title, const char *buf, ssize_t sz) +{ + int i; + char line[LOG_LINE_SIZE]; + + i = 0; + line[LOG_LINE_SIZE-1] = 0; + while (sz--) { + snprintf(line + i*3, 3, "%02x", *buf); + line[i*3 + 2] = ' '; + + if (IS_VISIBLE_CHAR(*buf)) + line[3*BYETES_PER_LINE + i] = *buf; + else + line[3*BYETES_PER_LINE + i] = '`'; + + i++; + buf++; + + if (i >= BYETES_PER_LINE || !sz) { + if (i < BYETES_PER_LINE) { + memset(line+i*3, ' ', (BYETES_PER_LINE-i)*3); + memset(line+3*BYETES_PER_LINE+i, '.', BYETES_PER_LINE-i); + } + pr_info("%s: %s\n", title, line); + i = 0; + } + } +} +EXPORT_SYMBOL(connsys_log_dump_buf); + +/***************************************************************************** +* FUNCTION +* connlog_dump_emi +* DESCRIPTION +* dump EMI buffer for debug. +* PARAMETERS +* offset [IN] buffer offset +* size [IN] dump buffer size +* RETURNS +* void +*****************************************************************************/ +void connlog_dump_emi(struct connlog_dev* handler, int offset, int size) +{ + char title[100]; + memset(title, 0, 100); + sprintf(title, "%s(%p)", "emi", handler->virAddrEmiLogBase + offset); + connsys_log_dump_buf(title, handler->virAddrEmiLogBase + offset, size); +} + +/***************************************************************************** +* FUNCTION +* connlog_ring_emi_check +* DESCRIPTION +* +* PARAMETERS +* +* RETURNS +* void +*****************************************************************************/ +static bool connlog_ring_emi_check(struct connlog_dev* handler) +{ + struct ring_emi *ring_emi = &handler->log_buffer.ring_emi; + char line[CONNLOG_EMI_END_PATTERN_SIZE + 1]; + + memcpy_fromio( + line, + handler->virAddrEmiLogBase + handler->log_offset.emi_guard_pattern_offset, + CONNLOG_EMI_END_PATTERN_SIZE); + line[CONNLOG_EMI_END_PATTERN_SIZE] = '\0'; + + /* Check ring_emi buffer memory. Dump EMI data if it is corruption. */ + if (EMI_READ32(ring_emi->read) > handler->log_offset.emi_size || + EMI_READ32(ring_emi->write) > handler->log_offset.emi_size || + strncmp(line, CONNLOG_EMI_END_PATTERN, CONNLOG_EMI_END_PATTERN_SIZE) != 0) { + pr_err("[connlog] %s out of bound or guard pattern overwrited. Read(pos=%p)=[0x%x] write(pos=%p)=[0x%x] size=[0x%x]\n", + type_to_title[handler->conn_type], + ring_emi->read, EMI_READ32(ring_emi->read), + ring_emi->write, EMI_READ32(ring_emi->write), + handler->log_offset.emi_size); + connlog_dump_emi(handler, 0x0, 0x60); + connlog_dump_emi(handler, CONNLOG_EMI_BASE_OFFSET, 0x20); + connlog_dump_emi( + handler, + handler->log_offset.emi_guard_pattern_offset, + CONNLOG_EMI_END_PATTERN_SIZE); + return false; + } + + return true; +} + +/***************************************************************************** +* FUNCTION +* connlog_ring_emi_to_cache +* DESCRIPTION +* +* PARAMETERS +* +* RETURNS +* void +*****************************************************************************/ +static void connlog_ring_emi_to_cache(struct connlog_dev* handler) +{ + struct ring_emi_segment ring_emi_seg; + struct ring_emi *ring_emi = &handler->log_buffer.ring_emi; + struct ring *ring_cache = &handler->log_buffer.ring_cache; + int total_size = 0; + int count = 0; + unsigned int cache_max_size = 0; +#ifndef DEBUG_LOG_ON + static DEFINE_RATELIMIT_STATE(_rs, 10 * HZ, 1); + static DEFINE_RATELIMIT_STATE(_rs2, HZ, 1); +#endif + + if (RING_FULL(ring_cache)) { + #ifndef DEBUG_LOG_ON + if (__ratelimit(&_rs)) + #endif + pr_warn("[connlog] %s cache is full.\n", type_to_title[handler->conn_type]); + return; + } + + cache_max_size = RING_WRITE_REMAIN_SIZE(ring_cache); + if (RING_EMI_EMPTY(ring_emi) || !ring_emi_read_prepare(cache_max_size, &ring_emi_seg, ring_emi)) { + #ifndef DEBUG_LOG_ON + if(__ratelimit(&_rs)) + #endif + pr_err("[connlog] %s no data.\n", type_to_title[handler->conn_type]); + return; + } + + /* Check ring_emi buffer memory. Dump EMI data if it is corruption. */ + if (connlog_ring_emi_check(handler) == false) { + pr_err("[connlog] %s emi check fail\n", type_to_title[handler->conn_type]); + /* TODO: trigger assert by callback? */ + return; + } + + RING_EMI_READ_ALL_FOR_EACH(ring_emi_seg, ring_emi) { + struct ring_segment ring_cache_seg; + unsigned int emi_buf_size = ring_emi_seg.sz; + unsigned int written = 0; + +#ifdef DEBUG_RING + ring_emi_dump(__func__, ring_emi); + ring_emi_dump_segment(__func__, &ring_emi_seg); +#endif + RING_WRITE_FOR_EACH(ring_emi_seg.sz, ring_cache_seg, &handler->log_buffer.ring_cache) { +#ifdef DEBUG_RING + ring_dump(__func__, &handler->log_buffer.ring_cache); + ring_dump_segment(__func__, &ring_cache_seg); +#endif + #ifndef DEBUG_LOG_ON + if (__ratelimit(&_rs2)) + #endif + pr_info("%s: ring_emi_seg.sz=%d, ring_cache_pt=%p, ring_cache_seg.sz=%d\n", + type_to_title[handler->conn_type], ring_emi_seg.sz, ring_cache_seg.ring_pt, + ring_cache_seg.sz); + memcpy_fromio(ring_cache_seg.ring_pt, ring_emi_seg.ring_emi_pt + ring_cache_seg.data_pos, + ring_cache_seg.sz); + emi_buf_size -= ring_cache_seg.sz; + written += ring_cache_seg.sz; + } + + total_size += ring_emi_seg.sz; + count++; + } +} + + +/***************************************************************************** + * FUNCTION + * connlog_fw_log_parser + * DESCRIPTION + * Parse fw log and print to kernel + * PARAMETERS + * conn_type [IN] log type + * buf [IN] buffer to prase + * sz [IN] buffer size + * RETURNS + * void + *****************************************************************************/ +static void connlog_fw_log_parser(struct connlog_dev* handler, ssize_t sz) +{ + unsigned int systime = 0; + unsigned int utc_s = 0; + unsigned int utc_us = 0; + unsigned int buf_len = 0; + unsigned int print_len = 0; + char* log_line = handler->log_line; + const char* buf = handler->log_data; + int conn_type = handler->conn_type; + + while (sz > LOG_HEAD_LENG) { + if (*buf == log_head[0]) { + if (!memcmp(buf, log_head, sizeof(log_head))) { + buf_len = buf[14] + (buf[15] << 8); + print_len = buf_len >= LOG_MAX_LEN ? LOG_MAX_LEN - 1 : buf_len; + memcpy(log_line, buf + LOG_HEAD_LENG, print_len); + log_line[print_len] = 0; + pr_info("%s: %s\n", type_to_title[conn_type], log_line); + sz -= (LOG_HEAD_LENG + buf_len); + buf += (LOG_HEAD_LENG + buf_len); + continue; + } else if (sz >= TIMESYNC_LENG && + !memcmp(buf, timesync_head, sizeof(timesync_head))) { + memcpy(&systime, buf + 28, sizeof(systime)); + memcpy(&utc_s, buf + 32, sizeof(utc_s)); + memcpy(&utc_us, buf + 36, sizeof(utc_us)); + pr_info("%s: timesync : (%u) %u.%06u\n", + type_to_title[conn_type], systime, utc_s, utc_us); + sz -= TIMESYNC_LENG; + buf += TIMESYNC_LENG; + continue; + } + } + sz--; + buf++; + } +} + +/***************************************************************************** + * FUNCTION + * connlog_ring_print + * DESCRIPTION + * print log data on kernel log + * PARAMETERS + * handler [IN] log handler + * RETURNS + * void + *****************************************************************************/ +static void connlog_ring_print(struct connlog_dev* handler) +{ + unsigned int written = 0; + unsigned int buf_size; + struct ring_emi_segment ring_emi_seg; + struct ring_emi *ring_emi = &handler->log_buffer.ring_emi; + int conn_type = handler->conn_type; + + if (RING_EMI_EMPTY(ring_emi) || !ring_emi_read_all_prepare(&ring_emi_seg, ring_emi)) { + pr_err("type(%s) no data, possibly taken by concurrent reader.\n", type_to_title[conn_type]); + return; + } + buf_size = ring_emi_seg.remain; + memset(handler->log_data, 0, handler->emi_size); + + /* Check ring_emi buffer memory. Dump EMI data if it is corruption. */ + if (connlog_ring_emi_check(handler) == false) { + pr_err("[connlog] %s emi check fail\n", type_to_title[handler->conn_type]); + /* TODO: trigger assert by callback? */ + return; + } + + RING_EMI_READ_ALL_FOR_EACH(ring_emi_seg, ring_emi) { + memcpy_fromio(handler->log_data + written, ring_emi_seg.ring_emi_pt, ring_emi_seg.sz); + buf_size -= ring_emi_seg.sz; + written += ring_emi_seg.sz; + } + + if (conn_type != CONN_DEBUG_TYPE_BT) + connlog_fw_log_parser(handler, written); +} + +/***************************************************************************** +* FUNCTION +* connlog_log_data_handler +* DESCRIPTION +* +* PARAMETERS +* +* RETURNS +* void +*****************************************************************************/ +static void connlog_log_data_handler(struct work_struct *work) +{ + struct connlog_dev* handler = + container_of(work, struct connlog_dev, logDataWorker); +#ifndef DEBUG_LOG_ON + static DEFINE_RATELIMIT_STATE(_rs, 10 * HZ, 1); + static DEFINE_RATELIMIT_STATE(_rs2, 2 * HZ, 1); +#endif + + if (!RING_EMI_EMPTY(&handler->log_buffer.ring_emi)) { + if (atomic_read(&g_log_mode) == LOG_TO_FILE) + connlog_ring_emi_to_cache(handler); + else + connlog_ring_print(handler); + connlog_event_set(handler); + } else { +#ifndef DEBUG_LOG_ON + if (__ratelimit(&_rs)) +#endif + pr_info("[connlog] %s emi ring is empty!\n", + type_to_title[handler->conn_type]); + } + +#ifndef DEBUG_LOG_ON + if (__ratelimit(&_rs2)) +#endif + pr_info("[connlog] %s irq counter = %d\n", + type_to_title[handler->conn_type], + EMI_READ32(handler->virAddrEmiLogBase + CONNLOG_IRQ_COUNTER_BASE)); + + spin_lock_irqsave(&handler->irq_lock, handler->flags); + if (handler->eirqOn) + mod_timer(&handler->workTimer, jiffies + 1); + spin_unlock_irqrestore(&handler->irq_lock, handler->flags); +} + +static void connlog_do_schedule_work(struct connlog_dev* handler, bool count) +{ + spin_lock_irqsave(&handler->irq_lock, handler->flags); + if (count) { + handler->irq_counter++; + EMI_WRITE32( + handler->virAddrEmiLogBase + CONNLOG_IRQ_COUNTER_BASE, + handler->irq_counter); + } + handler->eirqOn = !schedule_work(&handler->logDataWorker); + spin_unlock_irqrestore(&handler->irq_lock, handler->flags); +} + +/***************************************************************************** +* FUNCTION +* connsys_log_get_buf_size +* DESCRIPTION +* Get ring buffer unread size on EMI. +* PARAMETERS +* conn_type [IN] subsys type +* RETURNS +* unsigned int Ring buffer unread size +*****************************************************************************/ +unsigned int connsys_log_get_buf_size(int conn_type) +{ + struct connlog_dev* handler; + if (conn_type < CONN_DEBUG_TYPE_WIFI || conn_type >= CONN_DEBUG_TYPE_END) + return 0; + + handler = gLogDev[conn_type]; + if (handler == NULL) { + pr_err("[%s][%s] didn't init\n", __func__, type_to_title[conn_type]); + return 0; + } + + return RING_SIZE(&handler->log_buffer.ring_cache); +} +EXPORT_SYMBOL(connsys_log_get_buf_size); + +/***************************************************************************** + * FUNCTION + * connsys_log_read_internal + * DESCRIPTION + * Read log in ring_cache to buf + * PARAMETERS + * + * RETURNS + * + *****************************************************************************/ +static ssize_t connlog_read_internal( + struct connlog_dev* handler, int conn_type, + char *buf, char __user *userbuf, size_t count, bool to_user) +{ + unsigned int written = 0; + unsigned int cache_buf_size; + struct ring_segment ring_seg; + struct ring *ring = &handler->log_buffer.ring_cache; + unsigned int size = 0; + int retval; + static DEFINE_RATELIMIT_STATE(_rs, 10 * HZ, 1); + static DEFINE_RATELIMIT_STATE(_rs2, 1 * HZ, 1); + + size = count < RING_SIZE(ring) ? count : RING_SIZE(ring); + if (RING_EMPTY(ring) || !ring_read_prepare(size, &ring_seg, ring)) { + pr_err("type(%d) no data, possibly taken by concurrent reader.\n", conn_type); + goto done; + } + cache_buf_size = ring_seg.remain; + + RING_READ_FOR_EACH(size, ring_seg, ring) { + if (to_user) { + retval = copy_to_user(userbuf + written, ring_seg.ring_pt, ring_seg.sz); + if (retval) { + if (__ratelimit(&_rs)) + pr_err("copy to user buffer failed, ret:%d\n", retval); + goto done; + } + } else { + memcpy(buf + written, ring_seg.ring_pt, ring_seg.sz); + } + cache_buf_size -= ring_seg.sz; + written += ring_seg.sz; + if (__ratelimit(&_rs2)) + pr_info("[%s] copy %d to %s\n", + type_to_title[conn_type], + ring_seg.sz, + (to_user? "user space" : "buffer")); + } +done: + return written; +} + +/***************************************************************************** + * FUNCTION + * connsys_log_read_to_user + * DESCRIPTION + * Read log in ring_cache to user space buf + * PARAMETERS + * + * RETURNS + * + *****************************************************************************/ +ssize_t connsys_log_read_to_user(int conn_type, char __user *buf, size_t count) +{ + struct connlog_dev* handler; + unsigned int written = 0; + + if (conn_type < CONN_DEBUG_TYPE_WIFI || conn_type >= CONN_DEBUG_TYPE_END) + goto done; + if (atomic_read(&g_log_mode) != LOG_TO_FILE) + goto done; + + handler = gLogDev[conn_type]; + if (handler == NULL) { + pr_err("[%s][%s] not init\n", __func__, type_to_title[conn_type]); + goto done; + } + written = connlog_read_internal(handler, conn_type, NULL, buf, count, true); +done: + return written; +} +EXPORT_SYMBOL(connsys_log_read_to_user); + +/***************************************************************************** + * FUNCTION + * connsys_log_read + * DESCRIPTION + * Read log in ring_cache to buf + * PARAMETERS + * + * RETURNS + * + *****************************************************************************/ +ssize_t connsys_log_read(int conn_type, char *buf, size_t count) +{ + unsigned int ret = 0; + struct connlog_dev* handler; + + if (conn_type < CONN_DEBUG_TYPE_WIFI || conn_type >= CONN_DEBUG_TYPE_END) + goto done; + if (atomic_read(&g_log_mode) != LOG_TO_FILE) + goto done; + + handler = gLogDev[conn_type]; + ret = connlog_read_internal(handler, conn_type, buf, NULL, count, false); +done: + return ret; +} +EXPORT_SYMBOL(connsys_log_read); + + +/***************************************************************************** + * FUNCTION + * connsys_dedicated_log_set_log_mode + * DESCRIPTION + * set log mode. + * PARAMETERS + * mode [IN] log mode + * RETURNS + * void + *****************************************************************************/ +void connsys_dedicated_log_set_log_mode(int mode) +{ + atomic_set(&g_log_mode, (mode > 0 ? LOG_TO_FILE : PRINT_TO_KERNEL_LOG)); +} +EXPORT_SYMBOL(connsys_dedicated_log_set_log_mode); + +/***************************************************************************** +* FUNCTION +* connsys_dedicated_log_get_log_mode +* DESCRIPTION +* get log mode. +* PARAMETERS +* void +* RETURNS +* int log mode +*****************************************************************************/ +int connsys_dedicated_log_get_log_mode(void) +{ + return atomic_read(&g_log_mode); +} +EXPORT_SYMBOL(connsys_dedicated_log_get_log_mode); + +/***************************************************************************** +* FUNCTION +* connsys_log_irq_handler +* DESCRIPTION +* +* PARAMETERS +* void +* RETURNS +* int +*****************************************************************************/ +int connsys_log_irq_handler(int conn_type) +{ + struct connlog_dev* handler; + if (conn_type < CONN_DEBUG_TYPE_WIFI || conn_type >= CONN_DEBUG_TYPE_END) + return -1; + + handler = gLogDev[conn_type]; + if (handler == NULL) { + pr_err("[%s][%s] didn't init\n", __func__, type_to_title[conn_type]); + return -1; + } + + connlog_do_schedule_work(handler, true); + return 0; +} +EXPORT_SYMBOL(connsys_log_irq_handler); + +/***************************************************************************** +* FUNCTION +* connsys_log_register_event_cb +* DESCRIPTION +*· +* PARAMETERS +* void +* RETURNS +* +*****************************************************************************/ +int connsys_log_register_event_cb(int conn_type, CONNLOG_EVENT_CB func) +{ + struct connlog_dev* handler; + if (conn_type < CONN_DEBUG_TYPE_WIFI || conn_type >= CONN_DEBUG_TYPE_END) + return -1; + + handler = gLogDev[conn_type]; + if (handler == NULL) { + pr_err("[%s][%s] didn't init\n", __func__, type_to_title[conn_type]); + return -1; + } + + handler->callback.log_data_handler = func; + return 0; +} +EXPORT_SYMBOL(connsys_log_register_event_cb); + +/***************************************************************************** +* FUNCTION +* connlog_subsys_init +* DESCRIPTION +* +* PARAMETERS +* conn_type [IN] subsys type +* emi_addr [IN] physical emi +* emi_size [IN] emi size +* RETURNS +* struct connlog_dev* the handler +*****************************************************************************/ +static struct connlog_dev* connlog_subsys_init( + int conn_type, + phys_addr_t emi_addr, + unsigned int emi_size) +{ + struct connlog_dev* handler = 0; + + if (conn_type < CONN_DEBUG_TYPE_WIFI || conn_type >= CONN_DEBUG_TYPE_END) + return 0; + + handler = (struct connlog_dev*)kzalloc(sizeof(struct connlog_dev), GFP_KERNEL); + if (!handler) + return 0; + + handler->conn_type = conn_type; + if (connlog_emi_init(handler, emi_addr, emi_size)) { + pr_err("[%s] EMI init failed\n", type_to_title[conn_type]); + goto error_exit; + } + + if (connlog_ring_buffer_init(handler)) { + pr_err("[%s] Ring buffer init failed\n", type_to_title[conn_type]); + goto error_exit; + } + + init_timer(&handler->workTimer); + handler->workTimer.data = (unsigned long)handler; + handler->workTimer.function = work_timer_handler; + handler->irq_counter = 0; + spin_lock_init(&handler->irq_lock); + INIT_WORK(&handler->logDataWorker, connlog_log_data_handler); + + /* alarm timer */ + return handler; + +error_exit: + if (handler) + connlog_subsys_deinit(handler); + return 0; + +} + +/***************************************************************************** +* FUNCTION +* connsys_log_init +* DESCRIPTION +* +* PARAMETERS +* void +* RETURNS +* int +*****************************************************************************/ +int connsys_log_init(int conn_type) +{ + struct connlog_dev* handler; + phys_addr_t log_start_addr; + unsigned int log_size; + struct connlog_emi_config* emi_config; + + if (conn_type < CONN_DEBUG_TYPE_WIFI || conn_type >= CONN_DEBUG_TYPE_END) { + pr_err("[%s] invalid type:%d\n", __func__, conn_type); + return -1; + } + if (gLogDev[conn_type] != NULL) { + pr_err("[%s][%s] double init.\n", __func__, type_to_title[conn_type]); + return 0; + } + + emi_config = get_connsyslog_platform_config(conn_type); + if (!emi_config) { + pr_err("[%s] get emi config fail.\n", __func__); + return -1; + } + + log_start_addr = emi_config->log_offset + gPhyEmiBase; + log_size = emi_config->log_size; + pr_info("%s init. Base=%p size=%d\n", + type_to_title[conn_type], log_start_addr, log_size); + + handler = connlog_subsys_init(conn_type, log_start_addr, log_size); + if (handler == NULL) { + pr_err("[%s][%s] failed.\n", __func__, type_to_title[conn_type]); + return -1; + } + + gLogDev[conn_type] = handler; + return 0; +} +EXPORT_SYMBOL(connsys_log_init); + +/***************************************************************************** +* Function +* connlog_subsys_deinit +* DESCRIPTION +* +* PARAMETERS +* +* RETURNS +* +*****************************************************************************/ +static void connlog_subsys_deinit(struct connlog_dev* handler) +{ + if (handler == NULL) + return; + + connlog_emi_deinit(handler); + connlog_ring_buffer_deinit(handler); + kfree(handler); +} + +/***************************************************************************** +* Function +* connsys_log_deinit +* DESCRIPTION +* +* PARAMETERS +* +* RETURNS +* +*****************************************************************************/ +int connsys_log_deinit(int conn_type) +{ + struct connlog_dev* handler; + if (conn_type < CONN_DEBUG_TYPE_WIFI || conn_type >= CONN_DEBUG_TYPE_END) + return -1; + + handler = gLogDev[conn_type]; + if (handler == NULL) { + pr_err("[%s][%s] didn't init\n", __func__, type_to_title[conn_type]); + return -1; + } + + connlog_subsys_deinit(gLogDev[conn_type]); + gLogDev[conn_type] = NULL; + return 0; +} +EXPORT_SYMBOL(connsys_log_deinit); + +/***************************************************************************** +* FUNCTION +* connsys_log_get_utc_time +* DESCRIPTION +* Return UTC time +* PARAMETERS +* second [IN] UTC seconds +* usecond [IN] UTC usecons +* RETURNS +* void +*****************************************************************************/ +void connsys_log_get_utc_time( + unsigned int *second, unsigned int *usecond) +{ + struct timeval time; + + do_gettimeofday(&time); + *second = (unsigned int)time.tv_sec; /* UTC time second unit */ + *usecond = (unsigned int)time.tv_usec; /* UTC time microsecond unit */ +} +EXPORT_SYMBOL(connsys_log_get_utc_time); + +static inline bool connlog_is_alarm_enable(void) +{ + if ((gLogAlarm.alarm_state & CONNLOG_ALARM_STATE_ENABLE) > 0) + return true; + return false; +} + +static int connlog_set_alarm_timer(void) +{ + ktime_t kt; + + kt = ktime_set(gLogAlarm.alarm_sec, 0); + alarm_start_relative(&gLogAlarm.alarm_timer, kt); + + pr_info("[connsys_log_alarm] alarm timer enabled timeout=[%d]", gLogAlarm.alarm_sec); + return 0; +} + +static int connlog_cancel_alarm_timer(void) +{ + pr_info("[connsys_log_alarm] alarm timer cancel"); + return alarm_cancel(&gLogAlarm.alarm_timer); +} + + +static enum alarmtimer_restart connlog_alarm_timer_handler(struct alarm *alarm, + ktime_t now) +{ + ktime_t kt; + struct rtc_time tm; + unsigned int tsec, tusec; + int i; + + connsys_log_get_utc_time(&tsec, &tusec); + rtc_time_to_tm(tsec, &tm); + pr_info("[connsys_log_alarm] alarm_timer triggered [%d-%02d-%02d %02d:%02d:%02d.%09u]" + , tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday + , tm.tm_hour, tm.tm_min, tm.tm_sec, tusec); + + for (i = 0; i < CONN_DEBUG_TYPE_END; i++) { + if (gLogDev[i]) { + connlog_do_schedule_work(gLogDev[i], false); + } + } + + spin_lock_irqsave(&gLogAlarm.alarm_lock, gLogAlarm.flags); + kt = ktime_set(gLogAlarm.alarm_sec, 0); + alarm_start_relative(&gLogAlarm.alarm_timer, kt); + spin_unlock_irqrestore(&gLogAlarm.alarm_lock, gLogAlarm.flags); + + return ALARMTIMER_NORESTART; +} + +static int connlog_alarm_init(void) +{ + alarm_init(&gLogAlarm.alarm_timer, ALARM_REALTIME, connlog_alarm_timer_handler); + gLogAlarm.alarm_state = CONNLOG_ALARM_STATE_DISABLE; + spin_lock_init(&gLogAlarm.alarm_lock); + + return 0; +} + +/***************************************************************************** +* FUNCTION +* connsys_dedicated_log_path_alarm_enable +* DESCRIPTION +* Enable log timer. +* When log timer is enable, it starts every sec seconds to fetch log from EMI +* to file. +* Usually enable log timer for debug. +* PARAMETERS +* sec [IN] timer config +* RETURNS +* int +*****************************************************************************/ +int connsys_dedicated_log_path_alarm_enable(unsigned int sec) +{ + if (!gPhyEmiBase) + return -1; + + spin_lock_irqsave(&gLogAlarm.alarm_lock, gLogAlarm.flags); + + gLogAlarm.alarm_sec = sec; + if (!connlog_is_alarm_enable()) { + gLogAlarm.alarm_state = CONNLOG_ALARM_STATE_ENABLE; + pr_info("[connsys_log_alarm] alarm timer enabled timeout=[%d]", sec); + } + if (gLogAlarm.blank_state == 0) + connlog_set_alarm_timer(); + + spin_unlock_irqrestore(&gLogAlarm.alarm_lock, gLogAlarm.flags); + return 0; +} +EXPORT_SYMBOL(connsys_dedicated_log_path_alarm_enable); + +/***************************************************************************** +* FUNCTION +* connsys_dedicated_log_path_alarm_disable +* DESCRIPTION +* Disable log timer +* PARAMETERS +* +* RETURNS +* int +*****************************************************************************/ +int connsys_dedicated_log_path_alarm_disable(void) +{ + int ret; + + if (!gPhyEmiBase) + return -1; + + spin_lock_irqsave(&gLogAlarm.alarm_lock, gLogAlarm.flags); + + if (connlog_is_alarm_enable()) { + ret = connlog_cancel_alarm_timer(); + gLogAlarm.alarm_state = CONNLOG_ALARM_STATE_ENABLE; + pr_info("[connsys_log_alarm] alarm timer disable ret=%d", ret); + } + spin_unlock_irqrestore(&gLogAlarm.alarm_lock, gLogAlarm.flags); + return 0; +} +EXPORT_SYMBOL(connsys_dedicated_log_path_alarm_disable); + +/**************************************************************************** +* FUNCTION +* connsys_dedicated_log_path_blank_state_changed +* DESCRIPTION +* +* PARAMETERS +* +* RETURNS +* int +*****************************************************************************/ +int connsys_dedicated_log_path_blank_state_changed(int blank_state) +{ + int ret = 0; + + if (!gPhyEmiBase) + return -1; + spin_lock_irqsave(&gLogAlarm.alarm_lock, gLogAlarm.flags); + gLogAlarm.blank_state = blank_state; + if (connlog_is_alarm_enable()) { + if (blank_state == 0) + ret = connlog_set_alarm_timer(); + else + ret = connlog_cancel_alarm_timer(); + } + + spin_unlock_irqrestore(&gLogAlarm.alarm_lock, gLogAlarm.flags); + + return ret; +} +EXPORT_SYMBOL(connsys_dedicated_log_path_blank_state_changed); + +/***************************************************************************** +* FUNCTION +* connsys_dedicated_log_path_apsoc_init +* DESCRIPTION +* Initialize API for common driver to initialize connsys dedicated log +* for APSOC platform +* PARAMETERS +* emiaddr [IN] EMI physical base address +* RETURNS +* void +****************************************************************************/ +int connsys_dedicated_log_path_apsoc_init(phys_addr_t emiaddr) +{ + if (gPhyEmiBase != 0 || emiaddr == 0) { + pr_err("Connsys log double init or invalid parameter(emiaddr=%p)\n", emiaddr); + return -1; + } + + gPhyEmiBase = emiaddr; + + connlog_alarm_init(); + return 0; +} +EXPORT_SYMBOL(connsys_dedicated_log_path_apsoc_init); + +/***************************************************************************** +* FUNCTION +* connsys_dedicated_log_path_apsoc_deinit +* DESCRIPTION +* De-Initialize API for common driver to release cache, un-remap emi and free +* irq for APSOC platform +* PARAMETERS +* void +* RETURNS +* void +*****************************************************************************/ +int connsys_dedicated_log_path_apsoc_deinit(void) +{ + int i; + + /* Check subsys */ + for (i = 0; i < CONN_DEBUG_TYPE_END; i++) { + if (gLogDev[i] != NULL) { + pr_err("[%s] subsys %s should be deinit first.\n", + __func__, type_to_title[i]); + return -1; + } + } + + gPhyEmiBase = 0; + return 0; +} +EXPORT_SYMBOL(connsys_dedicated_log_path_apsoc_deinit); diff --git a/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/connsyslog.h b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/connsyslog.h new file mode 100644 index 0000000000000..6e410ec615b4e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/connsyslog.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#ifndef _CONNSYSLOG_H_ +#define _CONNSYSLOG_H_ + +#include +#include + +#include "connsys_debug_utility.h" + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/* Close debug log */ +//#define DEBUG_LOG_ON 1 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +enum FW_LOG_MODE { + PRINT_TO_KERNEL_LOG = 0, + LOG_TO_FILE = 1, +}; + +typedef void (*CONNLOG_EVENT_CB) (void); + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/* utility */ +void connsys_log_dump_buf(const char *title, const char *buf, ssize_t sz); +void connsys_log_get_utc_time( + unsigned int *second, unsigned int *usecond); + +/* Global config */ +int connsys_dedicated_log_path_apsoc_init(phys_addr_t emiaddr); +int connsys_dedicated_log_path_apsoc_deinit(void); +void connsys_dedicated_log_set_log_mode(int mode); +int connsys_dedicated_log_get_log_mode(void); +int connsys_dedicated_log_path_alarm_enable(unsigned int sec); +int connsys_dedicated_log_path_alarm_disable(void); +int connsys_dedicated_log_path_blank_state_changed(int blank_state); + +/* For subsys */ +int connsys_log_init(int conn_type); +int connsys_log_deinit(int conn_type); +unsigned int connsys_log_get_buf_size(int conn_type); +int connsys_log_register_event_cb(int conn_type, CONNLOG_EVENT_CB func); +ssize_t connsys_log_read_to_user(int conn_type, char __user *buf, size_t count); +ssize_t connsys_log_read(int conn_type, char *buf, size_t count); +int connsys_log_irq_handler(int conn_type); + +#endif /*_CONNSYSLOG_H_*/ diff --git a/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/connsyslog_emi.h b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/connsyslog_emi.h new file mode 100644 index 0000000000000..d2d823bd2d7d1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/connsyslog_emi.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#ifndef _CONNSYSLOG_EMI_H_ +#define _CONNSYSLOG_EMI_H_ + +#define CONNLOG_EMI_32_BYTE_ALIGNED 32 /* connsys EMI cache is 32-byte aligned */ +#define CONNLOG_CONTROL_RING_BUFFER_BASE_SIZE 64 /* Reserve for setup ring buffer base address */ +#define CONNLOG_CONTROL_RING_BUFFER_RESERVE_SIZE 32 +#define CONNLOG_IRQ_COUNTER_BASE 48 +#define CONNLOG_READY_PATTERN_BASE 56 +#define CONNLOG_READY_PATTERN_BASE_SIZE 8 +#define CONNLOG_EMI_END_PATTERN_SIZE CONNLOG_EMI_32_BYTE_ALIGNED +#define CONNLOG_EMI_END_PATTERN "FWLOGENDFWLOGENDFWLOGENDFWLOGEND" + +#define CONNLOG_EMI_BASE_OFFSET CONNLOG_CONTROL_RING_BUFFER_BASE_SIZE +#define CONNLOG_EMI_READ (CONNLOG_EMI_BASE_OFFSET + 0) +#define CONNLOG_EMI_WRITE (CONNLOG_EMI_BASE_OFFSET + 4) +#define CONNLOG_EMI_BUF (CONNLOG_EMI_BASE_OFFSET + \ + CONNLOG_EMI_32_BYTE_ALIGNED) + +#endif /* _CONNSYSLOG_EMI_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/log_ring.c b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/log_ring.c new file mode 100644 index 0000000000000..c1cfb3b2a6a2d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/log_ring.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#include "log_ring.h" +#include +#include +#include + + + +void log_ring_init(void *base, unsigned int max_size, unsigned int read, + unsigned int write, struct ring *ring) +{ + pr_info("base=0x%lx max_size=%x read=%x write=%x", base, max_size, read, write); + + WARN_ON(!base); + pr_info("xxxx-1"); + LOG_RING_VALIDATE_SIZE(max_size); + pr_info("xxx-2"); + /* making sure write largger than read */ + WARN_ON(read > write); + pr_info("xxx-3"); + ring->base = base; + ring->read = read; + ring->write = write; + ring->max_size = max_size; +} + +void log_ring_dump(const char *title, struct ring *ring) +{ + pr_info("[%s] ring:{write=%d, read=%d, max_size=%d}\n", + title, ring->write, ring->read, ring->max_size); +} + +void log_ring_dump_segment(const char *title, struct ring_segment *seg) +{ + pr_info("[%s] seg:{ring_pt=0x%p, data_pos=%d, sz=%d, remain=%d}\n", + title, seg->ring_pt, seg->data_pos, seg->sz, seg->remain); +} + +/* + * Function prepares the ring_segment and returns the number of valid bytes for read. + */ +unsigned int log_ring_read_prepare(unsigned int sz, struct ring_segment *seg, struct ring *ring) +{ + unsigned int wt = ring->write; + unsigned int rd = ring->read; + + memset(seg, 0, sizeof(struct ring_segment)); + if (sz > wt - rd) + sz = wt - rd; + seg->remain = sz; + /* log_ring_dump(__func__, ring); */ + /* log_ring_dump_segment(__func__, seg); */ + return seg->remain; +} + +/* + * Function prepares the ring_segment and returns the number of bytes available for write. + */ +unsigned int log_ring_write_prepare(unsigned int sz, struct ring_segment *seg, struct ring *ring) +{ + unsigned int wt = ring->write; + unsigned int rd = ring->read; + + memset(seg, 0, sizeof(struct ring_segment)); + if (sz > ring->max_size - (wt - rd)) + sz = ring->max_size - (wt - rd); + seg->remain = sz; + /* log_ring_dump(__func__, ring); */ + /* log_ring_dump_segment(__func__, seg); */ + return seg->remain; +} + +unsigned int log_ring_overwrite_prepare(unsigned int sz, struct ring_segment *seg, + struct ring *ring) +{ + unsigned int wt = ring->write; + unsigned int rd = ring->read; + + memset(seg, 0, sizeof(struct ring_segment)); + if (sz > ring->max_size - (wt - rd)) + ring->read += sz - (ring->max_size - (wt - rd)); + seg->remain = sz; + /* log_ring_dump(__func__, ring); */ + /* log_ring_dump_segment(__func__, seg); */ + return seg->remain; +} + +void __log_ring_segment_prepare(unsigned int from, unsigned int sz, struct ring_segment *seg, + struct ring *ring) +{ + unsigned int ring_pos = from; + + if (ring_pos >= ring->max_size) + ring_pos -= ring->max_size; + + seg->ring_pt = ring->base + ring_pos; + seg->data_pos = (seg->sz ? seg->data_pos + seg->sz : 0); + if (ring_pos + sz <= ring->max_size) + seg->sz = sz; + else + seg->sz = ring->max_size - ring_pos; + seg->remain -= seg->sz; + /* log_ring_dump(__func__, ring); */ + /* log_ring_dump_segment(__func__, seg); */ +} + +void _log_ring_segment_prepare(unsigned int from, struct ring_segment *seg, struct ring *ring) +{ + __log_ring_segment_prepare(from, seg->remain, seg, ring); +} + +void _log_ring_segment_prepare_item(unsigned int from, struct ring_segment *seg, struct ring *ring) +{ + unsigned int size; + + size = (seg->remain ? 1 : 0); + __log_ring_segment_prepare(from, size, seg, ring); +} + +void _log_ring_read_commit(struct ring_segment *seg, struct ring *ring) +{ + ring->read += seg->sz; + if (ring->read >= ring->max_size) + ring->read -= ring->max_size; + /* log_ring_dump(__func__, ring); */ + /* log_ring_dump_segment(__func__, seg); */ +} +void _log_ring_write_commit(struct ring_segment *seg, struct ring *ring) +{ + ring->write += seg->sz; + if (ring->write >= ring->max_size) + ring->write -= ring->max_size; + + /* log_ring_dump(__func__, ring); */ + /* log_ring_dump_segment(__func__, seg); */ +} + diff --git a/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/log_ring.h b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/log_ring.h new file mode 100644 index 0000000000000..49cc9f91fc229 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/log_ring.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#ifndef _LOG_RING_H_ +#define _LOG_RING_H_ + +struct ring { + /* addr where ring buffer starts */ + void *base; + /* addr storing the next writable pos, guaranteed to be >= read except when write overflow, but it's ok. */ + unsigned int write; + /* addr storing the next readable pos, except when read == write as buffer empty */ + unsigned int read; + /* must be power of 2 */ + unsigned int max_size; +}; + +struct ring_segment { + /* addr points into ring buffer for read/write */ + void *ring_pt; + /* size to read/write */ + unsigned int sz; + /* pos in external data buffer to read/write */ + unsigned int data_pos; + /* the size to be read/write after this segment completed */ + unsigned int remain; +}; + +void log_ring_init(void *base, unsigned int max_size, unsigned int read, + unsigned int write, struct ring *ring); +unsigned int log_ring_read_prepare(unsigned int sz, struct ring_segment *seg, struct ring *ring); +#define log_ring_read_all_prepare(seg, ring) log_ring_read_prepare((ring)->max_size, seg, ring) +unsigned int log_ring_write_prepare(unsigned int sz, struct ring_segment *seg, struct ring *ring); +unsigned int log_ring_overwrite_prepare(unsigned int sz, + struct ring_segment *seg, struct ring *ring); + +/* making sure max_size is power of 2 */ +#define LOG_RING_VALIDATE_SIZE(max_size) WARN_ON(!max_size) + +#define LOG_RING_EMPTY(ring) ((ring)->read == (ring)->write) +/* equation works even when write overflow */ +#define LOG_RING_SIZE(ring) ((ring)->write - (ring)->read) +#define LOG_RING_FULL(ring) (LOG_RING_SIZE(ring) == (ring)->max_size) +#define LOG_RING_WRITE_REMAIN_SIZE(ring) ((ring)->max_size - LOG_RING_SIZE(ring)) + +#define LOG_RING_READ_FOR_EACH(_sz, _seg, _ring) \ + for (log_ring_read_prepare(_sz, &(_seg), _ring), \ + _log_ring_segment_prepare((_ring)->read, &(_seg), (_ring)); \ + (_seg).sz > 0; \ + _log_ring_read_commit(&(_seg), (_ring)), _log_ring_segment_prepare((_ring)->read, \ + &(_seg), (_ring))) + +#define LOG_RING_READ_ALL_FOR_EACH(seg, ring) LOG_RING_READ_FOR_EACH((ring)->max_size, seg, ring) + +#define LOG_RING_READ_FOR_EACH_ITEM(_sz, _seg, _ring) \ + for (log_ring_read_prepare(_sz, &(_seg), _ring), \ + _log_ring_segment_prepare_item((_ring)->read, &(_seg), (_ring)); \ + (_seg).sz > 0; \ + _log_ring_read_commit(&(_seg), (_ring)), _log_ring_segment_prepare_item((_ring)->read, \ + &(_seg), (_ring))) + +#define LOG_RING_WRITE_FOR_EACH(_sz, _seg, _ring) \ + for (log_ring_write_prepare(_sz, &(_seg), _ring),\ + _log_ring_segment_prepare((_ring)->write, &(_seg), (_ring)); \ + (_seg).sz > 0; \ + _log_ring_write_commit(&(_seg), (_ring)), _log_ring_segment_prepare((_ring)->write, \ + &(_seg), (_ring))) + +#define LOG_RING_OVERWRITE_FOR_EACH(_sz, _seg, _ring) \ + for (log_ring_overwrite_prepare(_sz, &(_seg), _ring), \ + _log_ring_segment_prepare((_ring)->write, &(_seg), (_ring)); \ + (_seg).sz > 0; \ + _log_ring_write_commit(&(_seg), (_ring)), _log_ring_segment_prepare((_ring)->write, \ + &(_seg), (_ring))) + +void log_ring_dump(const char *title, struct ring *ring); +void log_ring_dump_segment(const char *title, struct ring_segment *seg); + + +/* ring Buffer Internal API */ +void _log_ring_segment_prepare(unsigned int from, struct ring_segment *seg, struct ring *ring); +void _log_ring_segment_prepare_item(unsigned int from, struct ring_segment *seg, struct ring *ring); +void _log_ring_read_commit(struct ring_segment *seg, struct ring *ring); +void _log_ring_write_commit(struct ring_segment *seg, struct ring *ring); + +#endif diff --git a/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/platform/include/connsyslog_hw_config.h b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/platform/include/connsyslog_hw_config.h new file mode 100644 index 0000000000000..df226ec93bc3c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/platform/include/connsyslog_hw_config.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#ifndef __CONNSYSLOG_HW_CONFIG_H__ +#define __CONNSYSLOG_HW_CONFIG_H__ + +struct connlog_emi_config { + phys_addr_t log_offset; + unsigned int log_size; +}; + +#endif /* __CONNSYSLOG_HW_CONFIG_H__ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/platform/mt6885/mt6885.c b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/platform/mt6885/mt6885.c new file mode 100644 index 0000000000000..e58b5b60efaa4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/platform/mt6885/mt6885.c @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#include + +#include "connsys_debug_utility.h" +#include "connsyslog_hw_config.h" + +#ifdef CONFIG_FPGA_EARLY_PORTING +#define CONNLOG_EMI_OFFSET_WIFI 0x0001F000 +#define CONNLOG_EMI_OFFSET_BT 0x0002F000 +#else +#define CONNLOG_EMI_OFFSET_WIFI 0x0024F000 +#define CONNLOG_EMI_OFFSET_BT 0x0004b000 +#endif + +#define CONNLOG_EMI_SIZE_WIFI (192*1024) +#define CONNLOG_EMI_SIZE_BT (64*1024) + +struct connlog_emi_config g_connsyslog_config[CONN_DEBUG_TYPE_END] = { + /* Wi-Fi config */ + {CONNLOG_EMI_OFFSET_WIFI, CONNLOG_EMI_SIZE_WIFI}, + {CONNLOG_EMI_OFFSET_BT, CONNLOG_EMI_SIZE_BT}, +}; + +struct connlog_emi_config* get_connsyslog_platform_config(int conn_type) +{ + if (conn_type < 0 || conn_type >= CONN_DEBUG_TYPE_END) { + pr_err("Incorrect type: %d\n", conn_type); + return NULL; + } + return &g_connsyslog_config[conn_type]; +} + diff --git a/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/platform/mt6893/mt6893.c b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/platform/mt6893/mt6893.c new file mode 100644 index 0000000000000..8b9632a63eb20 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/platform/mt6893/mt6893.c @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 MediaTek Inc. + */ + +#include + +#include "connsys_debug_utility.h" +#include "connsyslog_hw_config.h" + +#ifdef CONFIG_FPGA_EARLY_PORTING +#define CONNLOG_EMI_OFFSET_WIFI 0x0001F000 +#define CONNLOG_EMI_OFFSET_BT 0x0002F000 +#else +#define CONNLOG_EMI_OFFSET_WIFI 0x0024F000 +#define CONNLOG_EMI_OFFSET_BT 0x0004b000 +#endif + +#define CONNLOG_EMI_SIZE_WIFI (192*1024) +#define CONNLOG_EMI_SIZE_BT (64*1024) + +struct connlog_emi_config g_connsyslog_config[CONN_DEBUG_TYPE_END] = { + /* Wi-Fi config */ + {CONNLOG_EMI_OFFSET_WIFI, CONNLOG_EMI_SIZE_WIFI}, + {CONNLOG_EMI_OFFSET_BT, CONNLOG_EMI_SIZE_BT}, +}; + +struct connlog_emi_config* get_connsyslog_platform_config(int conn_type) +{ + if (conn_type < 0 || conn_type >= CONN_DEBUG_TYPE_END) { + pr_err("Incorrect type: %d\n", conn_type); + return NULL; + } + return &g_connsyslog_config[conn_type]; +} + diff --git a/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/ring_emi.c b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/ring_emi.c new file mode 100644 index 0000000000000..03115ad0f2613 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/ring_emi.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#include "ring_emi.h" +#include +#include +#include + +void ring_emi_init(void *base, unsigned int max_size, void *read, void *write, struct ring_emi *ring_emi) +{ + WARN_ON(!base || !read || !write); + + /* making sure max_size is power of 2 */ + WARN_ON(!max_size || (max_size & (max_size - 1))); + + /* making sure read & write pointers are 4 bytes aligned */ + WARN_ON(((long)read & 0x3) != 0 || ((long)write & 0x3) != 0); + + ring_emi->base = base; + ring_emi->read = read; + ring_emi->write = write; + EMI_WRITE32(ring_emi->write, 0); + EMI_WRITE32(ring_emi->read, 0); + ring_emi->max_size = max_size; + pr_info("write(%p) as 0, read(%p) as 0\n", ring_emi->write, ring_emi->read); + pr_info("base: %p, read: %p, write: %p, max_size: %d\n", base, read, write, max_size); +} + +void ring_emi_dump(const char *title, struct ring_emi *ring_emi) +{ + pr_info("[%s] ring_emi:{base=0x%p, write=%d, read=%d, max_size=%d}\n", + title, ring_emi->base, EMI_READ32(ring_emi->write), + EMI_READ32(ring_emi->read), ring_emi->max_size); +} + +void ring_emi_dump_segment(const char *title, struct ring_emi_segment *seg) +{ + pr_info("[%s] seg:{ring_emi_pt=0x%p, data_pos=%d, sz=%d, remain=%d}\n", + title, seg->ring_emi_pt, seg->data_pos, seg->sz, seg->remain); +} + +/* + * Function prepares the ring_emi_segment and returns the number of valid bytes for read. + */ +unsigned int ring_emi_read_prepare(unsigned int sz, struct ring_emi_segment *seg, struct ring_emi *ring_emi) +{ + unsigned int wt = EMI_READ32(ring_emi->write); + unsigned int rd = EMI_READ32(ring_emi->read); + + memset(seg, 0, sizeof(struct ring_emi_segment)); +#ifdef ROUND_REPEAT + if (wt >= rd) { + if (sz > wt - rd) + sz = wt - rd; + seg->remain = sz; + } else { + if (sz > ring_emi->max_size - (rd - wt)) + sz = ring_emi->max_size - (rd - wt); + seg->remain = sz; + } +#else + if (sz > wt - rd) + sz = wt - rd; + seg->remain = sz; +#endif + /* ring_emi_dump(__func__, ring_emi); */ + /* ring_emi_dump_segment(__func__, seg); */ + return seg->remain; +} + +/* + * Function prepares the ring_emi_segment and returns the number of bytes available for write. + */ +unsigned int ring_emi_write_prepare(unsigned int sz, struct ring_emi_segment *seg, struct ring_emi *ring_emi) +{ + unsigned int wt = EMI_READ32(ring_emi->write); + unsigned int rd = EMI_READ32(ring_emi->read); + + memset(seg, 0, sizeof(struct ring_emi_segment)); +#ifdef ROUND_REPEAT + if (wt >= rd) + seg->remain = ring_emi->max_size - (wt - rd + 1); + else + seg->remain = ring_emi->max_size - (rd - wt + 1); + + if (sz <= seg->remain) + seg->remain = sz; +#else + if (sz > ring_emi->max_size - (wt - rd)) + sz = ring_emi->max_size - (wt - rd); + seg->remain = sz; +#endif + /* ring_emi_dump(__func__, ring_emi); */ + /* ring_emi_dump_segment(__func__, seg); */ + return seg->remain; +} + +void _ring_emi_segment_prepare(unsigned int from, struct ring_emi_segment *seg, struct ring_emi *ring_emi) +{ +#ifndef ROUND_REPEAT + unsigned int ring_emi_pos = from & (ring_emi->max_size - 1); + + seg->ring_emi_pt = ring_emi->base + ring_emi_pos; +#else + seg->ring_emi_pt = ring_emi->base + from; +#endif + seg->data_pos = (seg->sz ? seg->data_pos + seg->sz : 0); + if (from + seg->remain <= ring_emi->max_size) + seg->sz = seg->remain; + else + seg->sz = ring_emi->max_size - from; + seg->remain -= seg->sz; + /* ring_emi_dump(__func__, ring_emi); */ + /* ring_emi_dump_segment(__func__, seg); */ +} + +void _ring_emi_read_commit(struct ring_emi_segment *seg, struct ring_emi *ring_emi) +{ +#ifdef ROUND_REPEAT +#ifdef DEBUG_LOG_ON + pr_info("[%s] write %p as %d\n", __func__, ring_emi->read, (EMI_READ32(ring_emi->read) + seg->sz) & (ring_emi->max_size - 1)); +#endif + EMI_WRITE32(ring_emi->read, (EMI_READ32(ring_emi->read) + seg->sz) & (ring_emi->max_size - 1)); +#else +#ifdef DEBUG_LOG_ON + pr_info("[%s] write %p as %d\n", __func__, ring_emi->read, EMI_READ32(ring_emi->read) + seg->sz); +#endif + EMI_WRITE32(ring_emi->read, EMI_READ32(ring_emi->read) + seg->sz); +#endif + /* *(ring_emi->read) += seg->sz; */ + /* ring_emi_dump(__func__, ring_emi); */ + /* ring_emi_dump_segment(__func__, seg); */ +} +void _ring_emi_write_commit(struct ring_emi_segment *seg, struct ring_emi *ring_emi) +{ +#ifdef ROUND_REPEAT +#ifdef DEBUG_LOG_ON + pr_info("[%s] write %p as %d\n", __func__, (EMI_READ32(ring_emi->write) + seg->sz) & (ring_emi->max_size - 1)); +#endif + EMI_WRITE32(ring_emi->write, (EMI_READ32(ring_emi->write) + seg->sz) & (ring_emi->max_size - 1)); +#else +#ifdef DEBUG_LOG_ON + pr_info("[%s] write %p as %d\n", __func__, ring_emi->write, EMI_READ32(ring_emi->write) + seg->sz); +#endif + EMI_WRITE32(ring_emi->write, EMI_READ32(ring_emi->write) + seg->sz); +#endif + /* ring_emi_dump(__func__, ring_emi); */ + /* ring_emi_dump_segment(__func__, seg); */ +} + diff --git a/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/ring_emi.h b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/ring_emi.h new file mode 100644 index 0000000000000..5969fd90f5bed --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/connsyslog/ring_emi.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#ifndef _RING_EMI_H_ +#define _RING_EMI_H_ + +#include +#define ROUND_REPEAT +#define EMI_READ32(addr) (readl(addr)) +#define EMI_WRITE32(addr, data) (writel(data, addr)) + +struct ring_emi { + /* addr where ring buffer starts */ + void *base; + /* addr storing the next writable pos, guaranteed to be >= read except when write overflow, but it's ok. */ + void *write; + /* addr storing the next readable pos, except when read == write as buffer empty */ + void *read; + /* must be power of 2 */ + unsigned int max_size; +}; + +struct ring_emi_segment { + /* addr points into ring buffer for read/write */ + void *ring_emi_pt; + /* size to read/write */ + unsigned int sz; + /* pos in external data buffer to read/write */ + unsigned int data_pos; + /* the size to be read/write after this segment completed */ + unsigned int remain; +}; + +void ring_emi_init(void *base, unsigned int max_size, void *read, void *write, struct ring_emi *ring_emi); +unsigned int ring_emi_read_prepare(unsigned int sz, struct ring_emi_segment *seg, struct ring_emi *ring_emi); +#define ring_emi_read_all_prepare(seg, ring_emi) ring_emi_read_prepare((ring_emi)->max_size, seg, ring_emi) +unsigned int ring_emi_write_prepare(unsigned int sz, struct ring_emi_segment *seg, struct ring_emi *ring_emi); + +/* making sure max_size is power of 2 */ +#define RING_EMI_VALIDATE_SIZE(max_size) WARN_ON(!max_size || (max_size & (max_size - 1))) + +#define RING_EMI_EMPTY(ring_emi) (EMI_READ32((ring_emi)->read) == EMI_READ32((ring_emi)->write)) +/* equation works even when write overflow */ +#define RING_EMI_SIZE(ring_emi) (EMI_READ32((ring_emi)->write) - EMI_READ32((ring_emi)->read)) +#ifdef ROUND_REPEAT +#define RING_EMI_FULL(ring_emi) (((EMI_READ32((ring_emi)->write) + 1) & ((ring_emi)->max_size - 1)) \ + == EMI_READ32((ring_emi)->read)) +#else +#define RING_EMI_FULL(ring_emi) (RING_EMI_SIZE(ring_emi) == (ring_emi)->max_size) +#endif + +#define RING_EMI_READ_FOR_EACH(_sz, _seg, _ring_emi) \ + for (_ring_emi_segment_prepare(EMI_READ32((_ring_emi)->read), &(_seg), (_ring_emi)); \ + (_seg).sz > 0; \ + _ring_emi_read_commit(&(_seg), (_ring_emi)), \ + _ring_emi_segment_prepare(EMI_READ32((_ring_emi)->read), &(_seg), (_ring_emi))) + +#define RING_EMI_READ_ALL_FOR_EACH(seg, ring_emi) RING_EMI_READ_FOR_EACH((ring_emi)->max_size, seg, ring_emi) + +#define RING_EMI_WRITE_FOR_EACH(_sz, _seg, _ring_emi) \ + for (_ring_emi_segment_prepare(EMI_READ32((_ring_emi)->write), &(_seg), (_ring_emi)); \ + (_seg).sz > 0; \ + _ring_emi_write_commit(&(_seg), (_ring_emi)), \ + _ring_emi_segment_prepare(EMI_READ32((_ring_emi)->write), &(_seg), (_ring_emi))) + +void ring_emi_dump(const char *title, struct ring_emi *ring_emi); +void ring_emi_dump_segment(const char *title, struct ring_emi_segment *seg); + + +/* Ring Buffer Internal API */ +void _ring_emi_segment_prepare(unsigned int from, struct ring_emi_segment *seg, struct ring_emi *ring_emi); +void _ring_emi_read_commit(struct ring_emi_segment *seg, struct ring_emi *ring_emi); +void _ring_emi_write_commit(struct ring_emi_segment *seg, struct ring_emi *ring_emi); + +#endif diff --git a/drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/conndump_netlink.c b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/conndump_netlink.c new file mode 100644 index 0000000000000..7c965643a92c2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/conndump_netlink.c @@ -0,0 +1,535 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "connsys_debug_utility.h" +#include "conndump_netlink.h" + + +/******************************************************************************* +* MACROS +******************************************************************************** +*/ +#define MAX_BIND_PROCESS (4) + +#define CONNSYS_DUMP_NETLINK_FAMILY_NAME_WIFI "CONNDUMP_WIFI" +#define CONNSYS_DUMP_NETLINK_FAMILY_NAME_BT "CONNDUMP_BT" + +#ifndef GENL_ID_GENERATE +#define GENL_ID_GENERATE 0 +#endif + +#define CONNSYS_DUMP_PKT_SIZE NLMSG_DEFAULT_SIZE + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +enum { + __CONNDUMP_ATTR_INVALID, + CONNDUMP_ATTR_MSG, + CONNDUMP_ATTR_PORT, + CONNDUMP_ATTR_HEADER, + CONNDUMP_ATTR_MSG_SIZE, + CONNDUMP_ATTR_LAST, + __CONNDUMP_ATTR_MAX, +}; +#define CONNDUMP_ATTR_MAX (__CONNDUMP_ATTR_MAX - 1) + +enum { + __CONNDUMP_COMMAND_INVALID, + CONNDUMP_COMMAND_BIND, + CONNDUMP_COMMAND_DUMP, + CONNDUMP_COMMAND_END, + CONNDUMP_COMMAND_RESET, + __CONNDUMP_COMMAND_MAX, +}; + +enum LINK_STATUS { + LINK_STATUS_INIT, + LINK_STATUS_INIT_DONE, + LINK_STATUS_MAX, +}; + +struct dump_netlink_ctx { + int conn_type; + pid_t bind_pid[MAX_BIND_PROCESS]; + unsigned int num_bind_process; + struct genl_family gnl_family; + unsigned int seqnum; + struct mutex nl_lock; + enum LINK_STATUS status; + void* coredump_ctx; + struct netlink_event_cb cb; +}; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static int conndump_nl_bind_wifi(struct sk_buff *skb, struct genl_info *info); +static int conndump_nl_dump_wifi(struct sk_buff *skb, struct genl_info *info); +static int conndump_nl_dump_end_wifi(struct sk_buff *skb, struct genl_info *info); +static int conndump_nl_reset_wifi(struct sk_buff *skb, struct genl_info *info); +static int conndump_nl_bind_bt(struct sk_buff *skb, struct genl_info *info); +static int conndump_nl_dump_bt(struct sk_buff *skb, struct genl_info *info); +static int conndump_nl_dump_end_bt(struct sk_buff *skb, struct genl_info *info); +static int conndump_nl_reset_bt(struct sk_buff *skb, struct genl_info *info); + +/******************************************************************************* +* G L O B A L V A R I A B L E +******************************************************************************** +*/ + +/* attribute policy */ +static struct nla_policy conndump_genl_policy[CONNDUMP_ATTR_MAX + 1] = { + [CONNDUMP_ATTR_MSG] = {.type = NLA_NUL_STRING}, + [CONNDUMP_ATTR_PORT] = {.type = NLA_U32}, + [CONNDUMP_ATTR_HEADER] = {.type = NLA_NUL_STRING}, + [CONNDUMP_ATTR_MSG_SIZE] = {.type = NLA_U32}, + [CONNDUMP_ATTR_LAST] = {.type = NLA_U32}, +}; + + +/* operation definition */ +static struct genl_ops conndump_gnl_ops_array_wifi[] = { + { + .cmd = CONNDUMP_COMMAND_BIND, + .flags = 0, + .policy = conndump_genl_policy, + .doit = conndump_nl_bind_wifi, + .dumpit = NULL, + }, + { + .cmd = CONNDUMP_COMMAND_DUMP, + .flags = 0, + .policy = conndump_genl_policy, + .doit = conndump_nl_dump_wifi, + .dumpit = NULL, + }, + { + .cmd = CONNDUMP_COMMAND_END, + .flags = 0, + .policy = conndump_genl_policy, + .doit = conndump_nl_dump_end_wifi, + .dumpit = NULL, + }, + { + .cmd = CONNDUMP_COMMAND_RESET, + .flags = 0, + .policy = conndump_genl_policy, + .doit = conndump_nl_reset_wifi, + .dumpit = NULL, + }, +}; + +static struct genl_ops conndump_gnl_ops_array_bt[] = { + { + .cmd = CONNDUMP_COMMAND_BIND, + .flags = 0, + .policy = conndump_genl_policy, + .doit = conndump_nl_bind_bt, + .dumpit = NULL, + }, + { + .cmd = CONNDUMP_COMMAND_DUMP, + .flags = 0, + .policy = conndump_genl_policy, + .doit = conndump_nl_dump_bt, + .dumpit = NULL, + }, + { + .cmd = CONNDUMP_COMMAND_END, + .flags = 0, + .policy = conndump_genl_policy, + .doit = conndump_nl_dump_end_bt, + .dumpit = NULL, + }, + { + .cmd = CONNDUMP_COMMAND_RESET, + .flags = 0, + .policy = conndump_genl_policy, + .doit = conndump_nl_reset_bt, + .dumpit = NULL, + }, +}; + +struct dump_netlink_ctx g_netlink_ctx[2] = { + /* WIFI */ + { + .conn_type = CONN_DEBUG_TYPE_WIFI, + .gnl_family = { + .id = GENL_ID_GENERATE, + .hdrsize = 0, + .name = CONNSYS_DUMP_NETLINK_FAMILY_NAME_WIFI, + .version = 1, + .maxattr = CONNDUMP_ATTR_MAX, + .ops = conndump_gnl_ops_array_wifi, + .n_ops = ARRAY_SIZE(conndump_gnl_ops_array_wifi), + }, + .status = LINK_STATUS_INIT, + .num_bind_process = 0, + .seqnum = 0, + }, + /* BT */ + { + .conn_type = CONN_DEBUG_TYPE_BT, + .gnl_family = { + .id = GENL_ID_GENERATE, + .hdrsize = 0, + .name = CONNSYS_DUMP_NETLINK_FAMILY_NAME_BT, + .version = 1, + .maxattr = CONNDUMP_ATTR_MAX, + .ops = conndump_gnl_ops_array_bt, + .n_ops = ARRAY_SIZE(conndump_gnl_ops_array_bt), + }, + .status = LINK_STATUS_INIT, + .num_bind_process = 0, + .seqnum = 0, + }, +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +static int conndump_nl_bind_internal(struct dump_netlink_ctx* ctx, struct sk_buff *skb, struct genl_info *info) +{ + int i; + struct nlattr *port_na; + unsigned int port; + + if (info == NULL) + goto out; + + if (mutex_lock_killable(&ctx->nl_lock)) + return -1; + + port_na = info->attrs[CONNDUMP_ATTR_PORT]; + if (port_na) { + port = (unsigned int)nla_get_u32(port_na); + } else { + pr_err("%s:-> no port_na found\n"); + return -1; + } + + for (i = 0; i < MAX_BIND_PROCESS; i ++) { + if (ctx->bind_pid[i] == 0) { + ctx->bind_pid[i] = port; + ctx->num_bind_process++; + pr_info("%s():-> pid = %d\n", __func__, port); + break; + } + } + if (i == MAX_BIND_PROCESS) { + pr_err("%s(): exceeding binding limit %d\n", __func__, MAX_BIND_PROCESS); + } + mutex_unlock(&ctx->nl_lock); + +out: + return 0; +} + +static int conndump_nl_dump_end_internal(struct dump_netlink_ctx* ctx, struct sk_buff *skb, struct genl_info *info) +{ + if (ctx && ctx->cb.coredump_end) { + pr_info("Get coredump end command, type=%d", ctx->conn_type); + ctx->cb.coredump_end(ctx->coredump_ctx); + } + return 0; +} + +static int conndump_nl_bind_wifi(struct sk_buff *skb, struct genl_info *info) +{ + int ret = 0; + + ret = conndump_nl_bind_internal(&g_netlink_ctx[CONN_DEBUG_TYPE_WIFI], skb, info); + return ret; +} + +static int conndump_nl_dump_wifi(struct sk_buff *skb, struct genl_info *info) +{ + pr_err("%s(): should not be invoked\n", __func__); + + return 0; +} + +static int conndump_nl_dump_end_wifi(struct sk_buff *skb, struct genl_info *info) +{ + int ret = 0; + + ret = conndump_nl_dump_end_internal(&g_netlink_ctx[CONN_DEBUG_TYPE_WIFI], skb, info); + + return ret; +} + +static int conndump_nl_reset_wifi(struct sk_buff *skb, struct genl_info *info) +{ + pr_err("%s(): should not be invoked\n", __func__); + + return 0; +} + +static int conndump_nl_bind_bt(struct sk_buff *skb, struct genl_info *info) +{ + int ret = 0; + + ret = conndump_nl_bind_internal(&g_netlink_ctx[CONN_DEBUG_TYPE_BT], skb, info); + return ret; +} + +static int conndump_nl_dump_bt(struct sk_buff *skb, struct genl_info *info) +{ + pr_err("%s(): should not be invoked\n", __func__); + + return 0; +} + +static int conndump_nl_dump_end_bt(struct sk_buff *skb, struct genl_info *info) +{ + int ret = 0; + + ret = conndump_nl_dump_end_internal(&g_netlink_ctx[CONN_DEBUG_TYPE_BT], skb, info); + + return ret; + +} + +static int conndump_nl_reset_bt(struct sk_buff *skb, struct genl_info *info) +{ + pr_err("%s(): should not be invoked\n", __func__); + + return 0; +} + +/***************************************************************************** + * FUNCTION + * conndump_netlink_init + * DESCRIPTION + * + * PARAMETERS + * + * RETURNS + * + *****************************************************************************/ +int conndump_netlink_init(int conn_type, void* dump_ctx, struct netlink_event_cb* cb) +{ + int ret = 0; + struct dump_netlink_ctx* ctx; + + if (conn_type < CONN_DEBUG_TYPE_WIFI || conn_type > CONN_DEBUG_TYPE_BT) { + pr_err("Incorrect type (%d)\n", conn_type); + return -1; + } + + ctx = &g_netlink_ctx[conn_type]; + mutex_init(&ctx->nl_lock); + ret = genl_register_family(&ctx->gnl_family); + if (ret != 0) { + pr_err("%s(): GE_NELINK family registration fail (ret=%d)\n", __func__, ret); + return -2; + } + ctx->status = LINK_STATUS_INIT_DONE; + memset(ctx->bind_pid, 0, sizeof(ctx->bind_pid)); + ctx->coredump_ctx = dump_ctx; + memcpy(&(ctx->cb), cb, sizeof(struct netlink_event_cb)); + + return ret; +} + +int conndump_netlink_msg_send(struct dump_netlink_ctx* ctx, char* tag, char* buf, unsigned int length, pid_t pid, unsigned int seq) +{ + struct sk_buff *skb; + void* msg_head = NULL; + int ret = 0; + int conn_type = ctx->conn_type; + + /* Allocating a Generic Netlink message buffer */ + skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + if (skb != NULL) { + /* Create message header */ + msg_head = genlmsg_put(skb, 0, seq, &ctx->gnl_family, 0, CONNDUMP_COMMAND_DUMP); + if (msg_head == NULL) { + pr_err("%s(): genlmsg_put fail(conn_type=%d).\n", __func__, conn_type); + nlmsg_free(skb); + return -EMSGSIZE; + } + /* Add message attribute and content */ + ret = nla_put_string(skb, CONNDUMP_ATTR_HEADER, tag); + if (ret != 0) { + pr_err("%s(): nla_put_string header fail(conn_type=%d): %d\n", __func__, conn_type, ret); + genlmsg_cancel(skb, msg_head); + nlmsg_free(skb); + return ret; + } + if (length) { + ret = nla_put(skb, CONNDUMP_ATTR_MSG, length, buf); + if (ret != 0) { + pr_err("%s(): nla_put fail(conn_type=%d): %d\n", __func__, conn_type, ret); + genlmsg_cancel(skb, msg_head); + nlmsg_free(skb); + return ret; + } + ret = nla_put_u32(skb, CONNDUMP_ATTR_MSG_SIZE, length); + if (ret != 0) { + pr_err("%s(): nal_put_u32 fail(conn_type=%d): %d\n", __func__, conn_type, ret); + genlmsg_cancel(skb, msg_head); + nlmsg_free(skb); + return ret; + } + } + /* finalize the message */ + genlmsg_end(skb, msg_head); + + /* sending message */ + ret = genlmsg_unicast(&init_net, skb, pid); + } else { + pr_err("Allocate message error\n"); + ret = -ENOMEM; + } + + return ret; +} + +/***************************************************************************** + * FUNCTION + * conndump_send_to_native + * DESCRIPTION + * Send dump content to native layer (AEE or dump service) + * PARAMETERS + * conn_type [IN] subsys type + * tag [IN] the tag for the content (null end string) + * [M] for coredump + * buf [IN] the content to dump (a buffer may not have end character) + * length [IN] dump length + * RETURNS + * + *****************************************************************************/ +int conndump_netlink_send_to_native_internal(struct dump_netlink_ctx* ctx, char* tag, char* buf, unsigned int length) +{ + int killed_num = 0; + int i, j, ret = 0; + unsigned int retry; + + for (i = 0; i < ctx->num_bind_process; i++) { + ret =conndump_netlink_msg_send(ctx, tag, buf, length, ctx->bind_pid[i], ctx->seqnum); + if (ret != 0) { + pr_err("%s(): genlmsg_unicast fail (ret=%d): pid = %d seq=%d tag=%s\n", + __func__, ret, ctx->bind_pid[i], ctx->seqnum, tag); + if (ret == -EAGAIN) { + retry = 0; + while (retry < 100 && ret == -EAGAIN) { + msleep(10); + ret =conndump_netlink_msg_send(ctx, tag, buf, length, ctx->bind_pid[i], ctx->seqnum); + retry ++; + pr_err("%s(): genlmsg_unicast retry (%d)...: ret = %d pid = %d seq=%d tag=%s\n", + __func__, retry, ret, ctx->bind_pid[i], ctx->seqnum, tag); + } + if (ret) { + pr_err("%s(): genlmsg_unicast fail (ret=%d) after retry %d times: pid = %d seq=%d tag=%s\n", + __func__, ret, retry, ctx->bind_pid[i], ctx->seqnum, tag); + } + } + if (ret == -ECONNREFUSED) { + ctx->bind_pid[i] = 0; + killed_num++; + } + } + } + + ctx->seqnum ++; + + /* Clean up invalid bind_pid */ + if (killed_num > 0) { + if (mutex_lock_killable(&ctx->nl_lock)) { + /* if fail to get lock, it is fine to update bind_pid[] later */ + return ret; + } + for (i = 0; i < ctx->num_bind_process - killed_num; i++) { + if (ctx->bind_pid[i] == 0) { + for (j = ctx->num_bind_process - 1; j > i; j--) { + if (ctx->bind_pid[j] > 0) { + ctx->bind_pid[i] = ctx->bind_pid[j]; + ctx->bind_pid[j] = 0; + } + } + } + } + ctx->num_bind_process -= killed_num; + mutex_unlock(&ctx->nl_lock); + } + + return ret; +} + + +/***************************************************************************** + * FUNCTION + * conndump_send_to_native + * DESCRIPTION + * Send dump content to native layer (AEE or dump service) + * PARAMETERS + * conn_type [IN] subsys type + * tag [IN] the tag for the content (null end string) + * [M] for coredump + * buf [IN] the content to dump (a buffer may not have end character) + * length [IN] dump length + * RETURNS + * + *****************************************************************************/ +int conndump_netlink_send_to_native(int conn_type, char* tag, char* buf, unsigned int length) +{ + struct dump_netlink_ctx* ctx; + int idx = 0; + unsigned int send_len; + unsigned int remain_len = length; + int ret; + + pr_info("[%s] conn_type=%d tag=%s buf=0x%x length=%d\n", + __func__, conn_type, tag, buf, length); + if ((conn_type < CONN_DEBUG_TYPE_WIFI || conn_type > CONN_DEBUG_TYPE_BT) || tag == NULL) { + pr_err("Incorrect type (%d), tag = %s\n", conn_type, tag); + return -1; + } + + ctx = &g_netlink_ctx[conn_type]; + if (ctx->status != LINK_STATUS_INIT_DONE) { + pr_err("%s(): netlink should be init (type=%d).\n", __func__, conn_type); + return -2; + } + + if (ctx->num_bind_process == 0) { + pr_err("No bind service\n"); + return -3; + } + + while (remain_len) { + send_len = (remain_len > CONNSYS_DUMP_PKT_SIZE? CONNSYS_DUMP_PKT_SIZE : remain_len); + ret = conndump_netlink_send_to_native_internal(ctx, tag, &buf[idx], send_len); + if (ret) { + pr_err("[%s] from %d with len=%d fail, ret=%d\n", __func__, idx, send_len, ret); + break; + } + remain_len -= send_len; + idx += send_len; + } + return idx; +} + diff --git a/drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/conndump_netlink.h b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/conndump_netlink.h new file mode 100644 index 0000000000000..70f351759318b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/conndump_netlink.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#ifndef _CONNDUMP_NETLINK_H_ +#define _CONNDUMP_NETLINK_H_ + +#include +#include + +#include "coredump/connsys_coredump.h" + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +struct netlink_event_cb { + void (*coredump_end)(void*); +}; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +int conndump_netlink_init(int conn_type, void* dump_ctx, struct netlink_event_cb* cb); +int conndump_netlink_send_to_native(int conn_type, char* tag, char* buf, unsigned int length); + + +#endif /*_CONNDUMP_NETLINK_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/connsys_coredump.c b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/connsys_coredump.c new file mode 100644 index 0000000000000..2aff7684f4e27 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/connsys_coredump.c @@ -0,0 +1,1730 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(CONNINFRA_PLAT_ALPS) && CONNINFRA_PLAT_ALPS +#include +#endif +#include "conninfra.h" +#include "connsys_debug_utility.h" +#include "connsys_coredump.h" +#include "connsys_coredump_emi.h" +#include "connsys_coredump_hw_config.h" +#include "conndump_netlink.h" + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +#define DEBUG_MODE 1 + +#define CONNSYS_DUMP_INFO_SIZE 180 +#define CONNSYS_ASSERT_INFO_SIZE 164 +#define CONNSYS_ASSERT_TYPE_SIZE 64 +#define CONNSYS_ASSERT_KEYWORD_SIZE 64 +#define CONNSYS_ASSERT_REASON_SIZE 128 +#define CONNSYS_AEE_INFO_SIZE 240 + +#define INFO_HEAD ";CONSYS FW CORE," +#define WDT_INFO_HEAD "Watch Dog Timeout" + +enum fw_coredump_status { + FW_DUMP_STATE_NOT_START = 0, + FW_DUMP_STATE_PUTTING = 1, + FW_DUMP_STATE_PUT_DONE = 2, + FW_DUMP_STATE_END, +}; + +enum core_dump_state { + CORE_DUMP_INIT = 0, + CORE_DUMP_START, + CORE_DUMP_DOING, + CORE_DUMP_TIMEOUT, /* Coredump timeout */ + CORE_DUMP_EMI_TIMEOUT, /* EMI dump timeout */ + CORE_DUMP_EMI, /* start for EMI dump */ + CORE_DUMP_DONE, + CORE_DUMP_INVALID, + CORE_DUMP_MAX, +}; + +enum connsys_issue_type { + CONNSYS_ISSUE_FW_ASSERT = 0, + CONNSYS_ISSUE_FW_EXCEPTION, + CONNSYS_ISSUE_DRIVER_ASSERT, + CONNSYS_ISSUE_MAX, +}; + +struct connsys_dump_info { + enum connsys_issue_type issue_type; + char dump_info[CONNSYS_DUMP_INFO_SIZE]; + char assert_info[CONNSYS_ASSERT_INFO_SIZE]; + unsigned int fw_task_id; + unsigned int fw_isr; + unsigned int fw_irq; + unsigned int exp_ipc; + unsigned int exp_eva; + char etype[CONNSYS_ASSERT_INFO_SIZE]; + char assert_type[CONNSYS_ASSERT_TYPE_SIZE]; + char exception_log[CONNSYS_AEE_INFO_SIZE]; + int drv_type; + char reason[CONNSYS_ASSERT_REASON_SIZE]; + char keyword[CONNSYS_ASSERT_KEYWORD_SIZE]; +}; + +struct connsys_dump_ctx { + int conn_type; + phys_addr_t emi_phy_addr_base; + void __iomem *emi_virt_addr_base; + unsigned int emi_size; + unsigned int mcif_emi_size; + struct coredump_event_cb callback; + struct timer_list dmp_timer; + struct completion emi_dump; + enum core_dump_state sm; + char* page_dump_buf; + struct dump_region* dump_regions; + int dump_regions_num; + unsigned int dynamic_map_cr; + struct coredump_hw_config hw_config; + struct connsys_dump_info info; + unsigned int full_emi_size; +}; + +#define DUMP_REGION_NAME_LENGTH 10 +/* TODO: Need check */ +#define DUMP_REGION_DEFAULT_NUM 50 + +enum dump_region_type { + DUMP_TYPE_CR = 0, + DUMP_TYPE_ROM, + DUMP_TYPE_ILM, + DUMP_TYPE_DLM, + DUMP_TYPE_SRAM, + DUMP_TYPE_SYS1, + DUMP_TYPE_SYS2, + DUMP_TYPE_MAX, +}; + +struct dump_region { + int dump_type; + char name[DUMP_REGION_NAME_LENGTH]; + unsigned int base; + unsigned int length; +}; + +static atomic_t g_dump_mode = ATOMIC_INIT(DUMP_MODE_DAEMON); + +static const char* g_type_name[] = { + "Wi-Fi", + "BT", +}; + +/******************************************************************************* +* MACROS +******************************************************************************** +*/ + +#if DEBUG_MODE +#if defined(CONFIG_FPGA_EARLY_PORTING) +/* For FPGA shorten the timer */ +#define CONNSYS_COREDUMP_TIMEOUT (1*10*1000) +#define CONNSYS_EMIDUMP_TIMEOUT (10*1000) +#else +#define CONNSYS_COREDUMP_TIMEOUT (1*10*1000) +#define CONNSYS_EMIDUMP_TIMEOUT (60*1000) +#endif +#else +#define CONNSYS_COREDUMP_TIMEOUT (10*1000) +#define CONNSYS_EMIDUMP_TIMEOUT (60*1000) +#endif + +#define CONNSYS_DUMP_BUFF_SIZE (32*1024*sizeof(char)) + +#define EMI_READ32(addr) (readl(addr)) +#define EMI_READ8(addr) (readb(addr)) +#define DUMP_LOG_BYTES_PER_LINE (128) +#define IS_VISIBLE_CHAR(c) ((c) >= 32 && (c) <= 126) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static void conndump_set_dump_state(struct connsys_dump_ctx* ctx, enum core_dump_state state); +static enum core_dump_state conndump_get_dump_state(struct connsys_dump_ctx* ctx); +static void conndump_timeout_handler(unsigned long data); +static inline int conndump_get_dmp_info(struct connsys_dump_ctx* ctx, unsigned int offset, bool log); +/* Dynamic remap relative function */ +static unsigned int conndump_setup_dynamic_remap(struct connsys_dump_ctx* ctx, unsigned int base, unsigned int length); +static void __iomem* conndump_remap(struct connsys_dump_ctx* ctx, unsigned int base, unsigned int length); +static void conndump_unmap(struct connsys_dump_ctx* ctx, void __iomem* vir_addr); +/* To dump different partition */ +static void conndump_dump_log(char* buf, int size); +static int conndump_dump_print_buff(struct connsys_dump_ctx* ctx); +static int conndump_dump_dump_buff(struct connsys_dump_ctx* ctx); +static int conndump_dump_cr_regions(struct connsys_dump_ctx* ctx); +static int conndump_dump_mem_regions(struct connsys_dump_ctx* ctx); +static int conndump_dump_emi(struct connsys_dump_ctx* ctx); +static int conndump_send_fake_coredump(struct connsys_dump_ctx* ctx); +/* Utility */ +static bool conndump_check_cr_readable(struct connsys_dump_ctx* ctx); +static int conndump_info_format( + struct connsys_dump_ctx* ctx, + char* buf, unsigned int max_len, + bool full_dump); +static void conndump_exception_show(struct connsys_dump_ctx* ctx, bool full_dump); +/* memory allocate/free */ +static void* conndump_malloc(unsigned int size); +static void conndump_free(const void* dst); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/* Platform relative function */ +/* ------------------------------------------------------------------------------*/ +struct coredump_hw_config* __weak get_coredump_platform_config(int conn_type) +{ + pr_err("[%s] Miss platform ops!\n", __func__); + return NULL; +} + +unsigned int __weak get_coredump_platform_chipid(void) +{ + pr_err("[%s] Miss platform ops!\n", __func__); + return 0; +} + +char* __weak get_task_string(int conn_type, int task_id) +{ + pr_err("[%s] Miss platform ops!\n", __func__); + return "ERROR"; +} + +char* __weak get_sys_name(int conn_type) +{ + pr_err("[%s] Miss platform ops!\n", __func__); + return "ERROR"; +} + +bool __weak is_host_view_cr(unsigned int addr, unsigned int* host_view) +{ + pr_err("[%s] Miss platform ops!\n", __func__); + return false; +} + +/*----------------------------------------------------------------------------*/ + + +static unsigned long timeval_to_ms(struct timeval *begin, struct timeval *end) +{ + unsigned long time_diff; + + time_diff = (end->tv_sec - begin->tv_sec) * 1000; + time_diff += (end->tv_usec - begin->tv_usec) / 1000; + + return time_diff; +} + +static void* conndump_malloc(unsigned int size) +{ + void* p = NULL; + + if (size > (PAGE_SIZE << 1)) + p = vmalloc(size); + else + p = kmalloc(size, GFP_KERNEL); + + /* If there is fragment, kmalloc may not get memory when size > one page. + * For this case, use vmalloc instead. + */ + if (p == NULL && size > PAGE_SIZE) + p = vmalloc(size); + return p; +} + +static void conndump_free(const void* dst) +{ + kvfree(dst); +} + + +static bool conndump_check_cr_readable(struct connsys_dump_ctx* ctx) +{ + int cb_ret = 0; + + /* Check reg readable */ + if (ctx->callback.reg_readable) { + cb_ret = ctx->callback.reg_readable(); + if (cb_ret == 1) { + return true; + } + pr_err("[%s] reg_readable callback ret = %d\n", + g_type_name[ctx->conn_type], cb_ret); + return false; + } + + pr_err("[%s] reg_readable callback is not implement! Return false\n", g_type_name[ctx->conn_type]); + return false; +} + +static void conndump_set_dump_state( + struct connsys_dump_ctx* ctx, enum core_dump_state state) +{ + if (ctx) + ctx->sm = state; +} + +static enum core_dump_state conndump_get_dump_state(struct connsys_dump_ctx* ctx) +{ + if (ctx) + return ctx->sm; + pr_err("%s ctx is null\n", __func__); + return CORE_DUMP_INVALID; +} + +static void conndump_timeout_handler(unsigned long data) +{ + struct connsys_dump_ctx* ctx = (struct connsys_dump_ctx*)data; + + pr_info("[%s] coredump timeout\n", ctx->conn_type); + conndump_set_dump_state(ctx, CORE_DUMP_TIMEOUT); +} + +static inline void conndump_get_dmp_char(struct connsys_dump_ctx* ctx, unsigned int offset, unsigned int byte_num, char* dest) +{ + int i; + char ret; + + if (!dest) + return; + + for (i = 0; i < byte_num; i++) { + ret = EMI_READ8(ctx->emi_virt_addr_base + offset + i); + dest[i] = ret; + } +} + +static inline int conndump_get_dmp_info(struct connsys_dump_ctx* ctx, unsigned int offset, bool log) +{ + int ret; + + ret = EMI_READ32(ctx->emi_virt_addr_base + offset); + if (log) + pr_info("EMI[0x%x] = 0x%08x\n", offset, ret); + + return ret; +} + +static void conndump_dump_log(char* buf, int size) +{ + int i = 0; + char line[DUMP_LOG_BYTES_PER_LINE + 1]; + + while (size--) { + if (IS_VISIBLE_CHAR(*buf)) + line[i] = *buf; + else + line[i] = '.'; + i++; + buf++; + + if (i >= DUMP_LOG_BYTES_PER_LINE || !size) { + line[i] = 0; + pr_info("page_trace: %s\n", line); + i = 0; + } + } +} + +static int conndump_info_format( + struct connsys_dump_ctx* ctx, + char* buf, + unsigned int max_len, + bool full_dump) +{ +#define FORMAT_STRING(buf, len, max_len, sec_len, fmt, arg...) \ +do { \ + sec_len = snprintf(buf + len, max_len, fmt, ##arg); \ + max_len -= sec_len; \ + len += sec_len; \ + if (max_len <= 0) \ + goto format_finish; \ +} while (0) + + int len = 0; + int ret; + int idx; + int sec_len; + char* drv_name[CONNDRV_TYPE_MAX] = { + "DRV_BT", + "DRV_FM", + "DRV_GPS", + "DRV_WIFI", + "DRV_CONNINFRA", + }; + /* Align with connac1.x and previous version */ + char* task_drv_name[CONNDRV_TYPE_MAX] = { + "Task_DrvBT", + "Task_DrvFM", + "Task_DrvGPS", + "Task_DrvWifi", + "Task_DrvConninfra", + }; + char* task_drv_name2[CONN_DEBUG_TYPE_END] = { + "Task_DrvWifi", + "Task_DrvBT", + }; + + if (!buf) { + pr_err("Invalid input, buf = %p", buf); + return 0; + } + + /* Init buffer */ + memset(buf, '\0', max_len); + FORMAT_STRING(buf, len, max_len, sec_len, "
\n"); + FORMAT_STRING(buf, len, max_len, sec_len, "\tMT%x\n", get_coredump_platform_chipid()); + + /* section */ + FORMAT_STRING(buf, len, max_len, sec_len, + "\t\n\t\t\n\t\t\t%s\n\t\t\n", + ctx->info.assert_info); + if (ctx->info.issue_type == CONNSYS_ISSUE_FW_EXCEPTION) { + FORMAT_STRING(buf, len, max_len, sec_len, + "\t\t\n\t\t\tFW Exception: %s\n\t\t\n", ctx->info.etype); + } else if (ctx->info.issue_type == CONNSYS_ISSUE_FW_ASSERT) { + FORMAT_STRING(buf, len, max_len, sec_len, + "\t\t\n\t\t\t%s\n\t\t\n", ctx->info.assert_type); + } else if (ctx->info.issue_type == CONNSYS_ISSUE_DRIVER_ASSERT) { + FORMAT_STRING(buf, len, max_len, sec_len, + "\t\t\n\t\t\t%s trigger assert\n\t\t\n", drv_name[ctx->info.drv_type]); + } else { + FORMAT_STRING(buf, len, max_len, sec_len, + "\t\t\n\t\t\tUnknown\n\t\t\n"); + } + /* section @{*/ + FORMAT_STRING(buf, len, max_len, sec_len, + "\t\n\t\n\t\t\n"); + + FORMAT_STRING(buf, len, max_len, sec_len, + "\t\t\t%s\n", ctx->hw_config.name); + if (ctx->info.issue_type == CONNSYS_ISSUE_DRIVER_ASSERT) { + /* Driver trigger assert */ + FORMAT_STRING(buf, len, max_len, sec_len, + "\t\t\t%s\n", + task_drv_name[ctx->info.drv_type]); + FORMAT_STRING(buf, len, max_len, sec_len, + "\t\t\tNULL\n"); + FORMAT_STRING(buf, len, max_len, sec_len, + "\t\t\tNULL\n"); + FORMAT_STRING(buf, len, max_len, sec_len, + "\t\t\t%s\n", + drv_name[ctx->info.drv_type]); + FORMAT_STRING(buf, len, max_len, sec_len, + "\t\t\t%s\n", + ctx->info.reason); + } else { + /* FW assert */ + if (full_dump) { + FORMAT_STRING(buf, len, max_len, sec_len, + "\t\t\t%s\n", + get_task_string(ctx->conn_type, ctx->info.fw_task_id)); + FORMAT_STRING(buf, len, max_len, sec_len, + "\t\t\tIRQ_0x%x_%s\n", + ctx->info.fw_irq, + get_sys_name(ctx->conn_type)); + FORMAT_STRING(buf, len, max_len, sec_len, + "\t\t\t0x%x\n", + ctx->info.fw_isr); + } else { + FORMAT_STRING(buf, len, max_len, sec_len, + "\t\t\t%s\n", + task_drv_name2[ctx->conn_type]); + FORMAT_STRING(buf, len, max_len, sec_len, + "\t\t\tNULL\n"); + FORMAT_STRING(buf, len, max_len, sec_len, + "\t\t\tNULL\n"); + } + FORMAT_STRING(buf, len, max_len, sec_len, + "\t\t\t%s\n", + "NULL"); + FORMAT_STRING(buf, len, max_len, sec_len, + "\t\t\t%s\n", + "NULL"); + } + if (strlen(ctx->info.keyword) != 0) { + FORMAT_STRING(buf, len, max_len, sec_len, + "\t\t\t%s\n", + ctx->info.keyword); + } else { + FORMAT_STRING(buf, len, max_len, sec_len, + "\t\t\tNULL\n"); + + } + FORMAT_STRING(buf, len, max_len, sec_len, + "\t\t\n\t\n"); + /* section @}*/ + /* section start @{ */ + FORMAT_STRING(buf, len, max_len, sec_len, "\t\n"); + for (idx = 0; idx < ctx->dump_regions_num; idx++) { + /* Non-empty name means memory regions */ + if (ctx->dump_regions[idx].name[0] != 0) { + FORMAT_STRING(buf, len, max_len, sec_len, + "\t\t<%s>\n\t\t\t0x%x\n\t\t\t0x%x\n\t\t\n", + ctx->dump_regions[idx].name, + ctx->dump_regions[idx].base, + ctx->dump_regions[idx].length, + ctx->dump_regions[idx].name); + } + } + FORMAT_STRING(buf, len, max_len, sec_len, "\t\n"); + /* section end @} */ + FORMAT_STRING(buf, len, max_len, sec_len, "
\n"); + +format_finish: + pr_info("== Issue info ==\n", buf); + pr_info("%s\n", buf); + pr_info("===== END =====\n"); + ret = conndump_netlink_send_to_native(ctx->conn_type, "INFO", buf, len); + if (ret < 0) + pr_err("Send issue info to native fail, ret=%d\n", ret); + return len; +} + +static void conndump_info_analysis( + struct connsys_dump_ctx* ctx, + unsigned int buf_len) +{ + const char* parser_sub_string[] = { + " ", + "id=", + "isr=", + "irq=", + "rc=", + }; + const char* exception_sub_string[] = { + " ", + "ipc=", + "eva=", + "etype:", + }; + char* pStr = ctx->page_dump_buf; + char* pDtr = NULL; + char* pTemp = NULL; + char* pTemp2 = NULL; + unsigned int len; + int remain_array_len = 0, sec_len = 0, idx = 0; + char tempBuf[CONNSYS_ASSERT_TYPE_SIZE] = { 0 }; + int ret, res; + char* type_str; + + /* Check */ + memset(&ctx->info.assert_info[0], '\0', CONNSYS_ASSERT_INFO_SIZE); + type_str = (char*)parser_sub_string[0]; + pDtr = strstr(pStr, type_str); + if (pDtr != NULL) { + if (ctx->info.issue_type != CONNSYS_ISSUE_DRIVER_ASSERT) + ctx->info.issue_type = CONNSYS_ISSUE_FW_ASSERT; + pDtr += strlen(type_str); + pTemp = strchr(pDtr, ' '); + + if (pTemp != NULL) { + idx = 0; + remain_array_len = CONNSYS_ASSERT_INFO_SIZE -1; + sec_len = strlen("assert@"); + memcpy(&ctx->info.assert_info[0], "assert@", sec_len); + idx += sec_len; + remain_array_len -= sec_len; + + len = pTemp - pDtr; + sec_len = (len < remain_array_len ? len : remain_array_len); + if (sec_len > remain_array_len) + goto check_task_id; + memcpy(&ctx->info.assert_info[idx], pDtr, sec_len); + remain_array_len -= sec_len; + idx += sec_len; + + sec_len = strlen("_"); + if (sec_len > remain_array_len) + goto check_task_id; + ctx->info.assert_info[idx] = '_'; + remain_array_len -= sec_len; + idx += sec_len; + + pTemp = strchr(pDtr, '#'); + if (pTemp != NULL) { + pTemp += 1; + pTemp2 = strchr(pTemp, ' '); + if (pTemp2 == NULL) { + pr_err("parser ' ' is not find\n"); + pTemp2 = pTemp + 1; + } + pr_info("(pTemp2 - pTemp)=%d\n", (pTemp2 - pTemp)); + if ((remain_array_len) > (pTemp2 - pTemp)) { + pr_info("Copy %d\n", pTemp2 - pTemp); + memcpy( + &ctx->info.assert_info[idx], + pTemp, + pTemp2 - pTemp); + } else { + pr_info("copy %d\n", (remain_array_len - 1)); + memcpy( + &ctx->info.assert_info[idx], + pTemp, + remain_array_len); + } + } + pr_info("assert info:%s\n", ctx->info.assert_info); + } + } else { + /* FW exception */ + type_str = (char*)exception_sub_string[0]; + pDtr = strstr(pStr, type_str); + if (pDtr == NULL) + goto check_task_id; + + if (ctx->info.issue_type != CONNSYS_ISSUE_DRIVER_ASSERT) + ctx->info.issue_type = CONNSYS_ISSUE_FW_EXCEPTION; + idx = 0; + remain_array_len = CONNSYS_ASSERT_INFO_SIZE; + sec_len = snprintf(&ctx->info.assert_info[idx], remain_array_len, + "%s", "Exception:"); + remain_array_len -= sec_len; + idx += sec_len; + + /* Check ipc */ + type_str = (char*)exception_sub_string[1]; + pDtr = strstr(pDtr, type_str); + if (pDtr == NULL) { + pr_err("Exception substring (%s) not found\n", type_str); + goto check_task_id; + } + pDtr += strlen(type_str); + pTemp = strchr(pDtr, ','); + if (pTemp != NULL) { + len = pTemp - pDtr; + len = (len >= CONNSYS_ASSERT_TYPE_SIZE) ? CONNSYS_ASSERT_TYPE_SIZE - 1 : len; + memcpy(&tempBuf[0], pDtr, len); + tempBuf[len] = '\0'; + ret = kstrtouint(tempBuf, 16, &res); + if (ret) { + pr_err("Convert to uint fail, ret=%d, buf=%s\n", + ret, tempBuf); + } else { + ctx->info.exp_ipc = res; + pr_info("exp_ipc=0x%x\n", ctx->info.exp_ipc); + } + if (remain_array_len > 0) { + sec_len = snprintf(&ctx->info.assert_info[idx], remain_array_len, + " ipc=0x%x", ctx->info.exp_ipc); + remain_array_len -= sec_len; + idx += sec_len; + } + } + + /* Check eva */ + type_str = (char*)exception_sub_string[2]; + pDtr = strstr(pDtr, type_str); + if (pDtr == NULL) { + pr_err("substring (%s) not found\n", type_str); + goto check_task_id; + } + pDtr += strlen(type_str); + pTemp = strchr(pDtr, ','); + if (pTemp != NULL) { + len = pTemp - pDtr; + len = (len >= CONNSYS_ASSERT_TYPE_SIZE) ? CONNSYS_ASSERT_TYPE_SIZE - 1 : len; + memcpy(&tempBuf[0], pDtr, len); + tempBuf[len] = '\0'; + ret = kstrtouint(tempBuf, 16, &res); + if (ret) { + pr_err("Convert to uint fail, ret=%d, buf=%s\n", + ret, tempBuf); + } else { + ctx->info.exp_eva = res; + pr_info("eva addr=0x%x\n", ctx->info.exp_eva); + } + if (remain_array_len > 0) { + sec_len = snprintf( + &ctx->info.assert_info[idx], remain_array_len, + " eva=0x%x", ctx->info.exp_eva); + remain_array_len -= sec_len; + idx += sec_len; + } + } + + /* Check etype */ + type_str = (char*)exception_sub_string[3]; + pDtr = strstr(pDtr, type_str); + if (pDtr == NULL) { + pr_err("Substring(%s) not found\n", type_str); + goto check_task_id; + } + pDtr += strlen(type_str); + pTemp = strchr(pDtr, ','); + if (pTemp != NULL) { + len = pTemp - pDtr; + len = (len >= CONNSYS_ASSERT_TYPE_SIZE) ? CONNSYS_ASSERT_TYPE_SIZE - 1 : len; + memcpy(ctx->info.etype, pDtr, len); + ctx->info.etype[len] = '\0'; + pr_info("etype=%s\n", ctx->info.etype); + if (remain_array_len > 0) { + sec_len = snprintf( + &ctx->info.assert_info[idx], remain_array_len, + " etype=%s", ctx->info.etype); + remain_array_len -= sec_len; + idx += sec_len; + } + } + } + +check_task_id: + /* Check id */ + ctx->info.fw_task_id = 0; + type_str = (char*)parser_sub_string[1]; + pDtr = strstr(pStr, type_str); + if (pDtr == NULL) { + pr_err("parser str is NULL,substring(%s)\n", type_str); + + } else { + pDtr += strlen(type_str); + pTemp = strchr(pDtr, ' '); + + if (pTemp == NULL) { + pr_err("delimiter( ) is not found,substring(%s)\n", + type_str); + } else { + len = pTemp - pDtr; + len = (len >= CONNSYS_ASSERT_TYPE_SIZE) ? CONNSYS_ASSERT_TYPE_SIZE - 1 : len; + memcpy(&tempBuf[0], pDtr, len); + tempBuf[len] = '\0'; + ret = kstrtouint(tempBuf, 16, &res); + if (ret) { + pr_err("Convert to uint fail, ret=%d\n, buf=%s\n", + ret, tempBuf); + } else { + ctx->info.fw_task_id = res; + pr_info("fw task id: %x\n", ctx->info.fw_task_id); + } + } + } + + /* Check ISR */ + ctx->info.fw_isr = 0; + type_str = (char*)parser_sub_string[2]; + pDtr = strstr(pStr, type_str); + if (pDtr == NULL) { + pr_err("parser str is NULL,substring(%s)\n", type_str); + } else { + pDtr += strlen(type_str); + pTemp = strchr(pDtr, ','); + + if (pTemp == NULL) { + pr_err("delimiter(,) is not found,substring(%s)\n", type_str); + } else { + len = pTemp - pDtr; + len = (len >= CONNSYS_ASSERT_TYPE_SIZE) ? CONNSYS_ASSERT_TYPE_SIZE - 1 : len; + memcpy(&tempBuf[0], pDtr, len); + tempBuf[len] = '\0'; + + ret = kstrtouint(tempBuf, 16, &res); + if (ret) { + pr_err("Get fw isr id fail, ret=%d, buf=%s\n", ret, tempBuf); + } else { + ctx->info.fw_isr = res; + pr_info("fw isr str:%x\n", ctx->info.fw_isr); + } + } + } + + /* Check IRQ */ + ctx->info.fw_irq = 0; + type_str = (char*)parser_sub_string[3]; + pDtr = strstr(pStr, type_str); + if (pDtr == NULL) { + pr_err("parser str is NULL,substring(%s)\n", type_str); + } else { + pDtr += strlen(type_str); + pTemp = strchr(pDtr, ','); + if (pTemp == NULL) { + pr_err("delimiter(,) is not found,substring(%s)\n", type_str); + } else { + len = pTemp - pDtr; + len = (len >= CONNSYS_ASSERT_TYPE_SIZE) ? CONNSYS_ASSERT_TYPE_SIZE - 1 : len; + memcpy(&tempBuf[0], pDtr, len); + tempBuf[len] = '\0'; + ret = kstrtouint(tempBuf, 16, &res); + if (ret) { + pr_err("get fw irq id fail ret=%d, buf=%s\n", ret, tempBuf); + } else { + ctx->info.fw_irq = res; + pr_info("fw irq value:%x\n", ctx->info.fw_irq); + } + } + } + + /* Check assert type */ + memset(&ctx->info.assert_type[0], '\0', CONNSYS_ASSERT_TYPE_SIZE); + type_str = (char*)parser_sub_string[4]; + pDtr = strstr(pStr, type_str); + if (pDtr == NULL) { + pr_err("parser str is NULL,substring(%s)\n", type_str); + } else { + pDtr += strlen(type_str); + pTemp = strchr(pDtr, ','); + + if (pTemp == NULL) { + pr_err("delimiter(,) is not found,substring(%s)\n", type_str); + } else { + len = pTemp - pDtr; + len = (len >= CONNSYS_ASSERT_TYPE_SIZE) ? CONNSYS_ASSERT_TYPE_SIZE - 1 : len; + memcpy(&tempBuf[0], pDtr, len); + tempBuf[len] = '\0'; + + if (memcmp(tempBuf, "*", strlen("*")) == 0) + memcpy( + &ctx->info.assert_type[0], + "general assert", + strlen("general assert")); + if (memcmp(tempBuf, WDT_INFO_HEAD, strlen(WDT_INFO_HEAD)) == 0) + memcpy( + &ctx->info.assert_type[0], "wdt", strlen("wdt")); + if (memcmp(tempBuf, "RB_FULL", strlen("RB_FULL")) == 0) { + memcpy(&ctx->info.assert_type[0], tempBuf, len); + pDtr = strstr(&ctx->info.assert_type[0], "RB_FULL("); + if (pDtr == NULL) { + pr_err("parser str is NULL,substring(RB_FULL()\n"); + } else { + pDtr += strlen("RB_FULL("); + pTemp = strchr(pDtr, ')'); + len = pTemp - pDtr; + len = (len >= CONNSYS_ASSERT_TYPE_SIZE) ? CONNSYS_ASSERT_TYPE_SIZE - 1 : len; + memcpy(&tempBuf[0], pDtr, len); + tempBuf[len] = '\0'; + ret = kstrtouint(tempBuf, 16, &res); + if (ret) { + pr_err("get fw task id fail(%d)\n", ret); + } else { + snprintf( + ctx->info.keyword, + CONNSYS_ASSERT_KEYWORD_SIZE, + "RB_FULL_%d_%s", res, + ctx->hw_config.name); + } + } + } + } + pr_info("fw asert type:%s\n", ctx->info.assert_type); + } + + /* Store first several characters */ + len = strlen(ctx->page_dump_buf); + len = (len >= CONNSYS_DUMP_INFO_SIZE) ? CONNSYS_DUMP_INFO_SIZE - 1 : len; + strncpy(ctx->info.dump_info, ctx->page_dump_buf, CONNSYS_DUMP_INFO_SIZE); + ctx->info.dump_info[len] = '\0'; +} + +/***************************************************************************** + * FUNCTION + * conndump_dump_print_buff + * DESCRIPTION + * + * PARAMETERS + * + * RETURNS + * + *****************************************************************************/ +static int conndump_dump_print_buff(struct connsys_dump_ctx* ctx) +{ + int ret = 0; + unsigned int buff_start, buff_len; + int section_len; + + buff_start = CONNSYS_DUMP_PRINT_BUFF_OFFSET; + buff_len = conndump_get_dmp_info(ctx, CONNSYS_DUMP_CTRL_BLOCK_OFFSET + EXP_CTRL_PRINT_BUFF_IDX, true); + + if (buff_len > CONNSYS_DUMP_PRINT_BUFF_SIZE) { + pr_err("Get print buff idx = %d, but the length is %d\n", buff_len, CONNSYS_DUMP_PRINT_BUFF_SIZE); + buff_len = CONNSYS_DUMP_PRINT_BUFF_SIZE; + } + + pr_info("-- paged trace ascii output start --\n"); + while (buff_len > 0) { + memset(ctx->page_dump_buf, '\0', CONNSYS_DUMP_BUFF_SIZE); + section_len = (buff_len > (CONNSYS_DUMP_BUFF_SIZE - 1)) ? (CONNSYS_DUMP_BUFF_SIZE - 1) : buff_len; + memcpy_fromio(ctx->page_dump_buf, ctx->emi_virt_addr_base + buff_start, section_len); + + pr_info("-- paged trace ascii output --\n"); + conndump_dump_log(ctx->page_dump_buf, section_len); + + buff_len -= section_len; + buff_start += section_len; + } + pr_info("-- paged trace ascii output end --\n"); + return ret; +} + +/***************************************************************************** + * FUNCTION + * conndump_dump_dump_buff + * DESCRIPTION + * + * PARAMETERS + * + * RETURNS + * + *****************************************************************************/ +static int conndump_dump_dump_buff(struct connsys_dump_ctx* ctx) +{ + int ret = 0; + unsigned int buff_start, buff_len; + int section_len; + bool first = true; + + buff_start = CONNSYS_DUMP_DUMP_BUFF_OFFSET; + buff_len = conndump_get_dmp_info(ctx, CONNSYS_DUMP_CTRL_BLOCK_OFFSET + EXP_CTRL_DUMP_BUFF_IDX, true); + + if (buff_len > CONNSYS_DUMP_DUMP_BUFF_SIZE) { + pr_err("Get dump buff idx = %d, but the size is %d\n", buff_len, CONNSYS_DUMP_DUMP_BUFF_SIZE); + buff_len = CONNSYS_DUMP_DUMP_BUFF_SIZE; + } + + if (buff_len == 0) { + ret = conndump_send_fake_coredump(ctx); + return ret; + } + + while (buff_len > 0) { + memset(ctx->page_dump_buf, '\0', CONNSYS_DUMP_BUFF_SIZE); + section_len = (buff_len > (CONNSYS_DUMP_BUFF_SIZE - 1)) ? (CONNSYS_DUMP_BUFF_SIZE - 1): buff_len; + memcpy_fromio(ctx->page_dump_buf, ctx->emi_virt_addr_base + buff_start, section_len); + + /* pack it */ + ret = conndump_netlink_send_to_native(ctx->conn_type, "[M]", ctx->page_dump_buf, section_len); + /* For 1st package, analysis it */ + if (first) { + conndump_info_analysis(ctx, section_len); + first = false; + } + + buff_len -= section_len; + buff_start += section_len; + } + return ret; +} + +/***************************************************************************** + * FUNCTION + * conndump_setup_dynamic_remap + * DESCRIPTION + * Setup dynamic remap region + * PARAMETERS + * + * RETURNS + * + *****************************************************************************/ +static unsigned int conndump_setup_dynamic_remap(struct connsys_dump_ctx* ctx, unsigned int base, unsigned int length) +{ + +#define DYNAMIC_MAP_MAX_SIZE 0x300000 + unsigned int map_len = (length > DYNAMIC_MAP_MAX_SIZE? DYNAMIC_MAP_MAX_SIZE : length); + void __iomem* vir_addr = 0; + + if (is_host_view_cr(base, NULL)) { + pr_info("Host view CR: 0x%x, skip dynamic remap\n", base); + return length; + } + + /* Expand to request size */ + vir_addr = ioremap_nocache(ctx->hw_config.seg1_cr, 4); + if (vir_addr) { + iowrite32(ctx->hw_config.seg1_phy_addr + map_len, vir_addr); + iounmap(vir_addr); + } else { + return 0; + } + /* Setup map base */ + vir_addr = ioremap_nocache(ctx->hw_config.seg1_start_addr, 4); + if (vir_addr) { + iowrite32(base, vir_addr); + iounmap(vir_addr); + } else { + return 0; + } + return map_len; +} + +/***************************************************************************** + * FUNCTION + * conndump_remap + * DESCRIPTION + * Map dynamic remap CR region to virtual address + * PARAMETERS + * + * RETURNS + * + *****************************************************************************/ +static void __iomem* conndump_remap(struct connsys_dump_ctx* ctx, unsigned int base, unsigned int length) +{ + void __iomem* vir_addr = 0; + unsigned int host_cr; + + if (is_host_view_cr(base, &host_cr)) { + pr_info("Map 0x%x to 0x%x\n", base, host_cr); + vir_addr = ioremap_nocache(host_cr, length); + } else { + vir_addr = ioremap_nocache(ctx->hw_config.seg1_phy_addr, length); + } + return vir_addr; +} + +/***************************************************************************** + * FUNCTION + * conndump_unmap + * DESCRIPTION + * Unmap virtual address + * PARAMETERS + * + * RETURNS + * + *****************************************************************************/ +static void conndump_unmap(struct connsys_dump_ctx* ctx, void __iomem* vir_addr) +{ + iounmap(vir_addr); +} + + +/***************************************************************************** + * FUNCTION + * conndump_dump_cr_regions + * DESCRIPTION + * + * PARAMETERS + * + * RETURNS + * + *****************************************************************************/ +static int conndump_dump_cr_regions(struct connsys_dump_ctx* ctx) +{ +#define CR_PER_LINE 11 + int ret = 0; + int idx; + unsigned int map_length; + void __iomem *map_base; + unsigned int buff_size = CONNSYS_DUMP_BUFF_SIZE; + /* format is [addr,valu] */ + char per_cr[CR_PER_LINE]; + int i; + int addr, value; + unsigned int buff_idx = 0; + + if (!conndump_check_cr_readable(ctx)) { + pr_err("CR not readable, skip cr dump\n"); + return -1; + } + + for (idx = 0; idx < ctx->dump_regions_num; idx++) { + /* empty name means cr regions */ + if (ctx->dump_regions[idx].name[0] == 0 && + (ctx->dump_regions[idx].base > 0) && + (ctx->dump_regions[idx].base & 0x3) == 0 && + (ctx->dump_regions[idx].length & 0x3) == 0) { + pr_info("[%s][Region %d] base=0x%x size=0x%x\n", __func__, idx, ctx->dump_regions[idx].base, ctx->dump_regions[idx].length); + map_length = conndump_setup_dynamic_remap( + ctx, ctx->dump_regions[idx].base, ctx->dump_regions[idx].length); + /* For CR region, we assume region size should < dynamic remap region. */ + if (map_length != ctx->dump_regions[idx].length) { + pr_err("Expect_size=0x%x map_length=0x%x\n", ctx->dump_regions[idx].length, map_length); + } else { + map_base = conndump_remap(ctx, ctx->dump_regions[idx].base, map_length); + if (!map_base) { + pr_err("[%s][Region %d] remap fail, break\n", __func__, idx); + break; + } + for (i = 0, addr = ctx->dump_regions[idx].base; i < map_length; i+=4, addr+=4) { + value = (*((volatile unsigned int *)(map_base + i))); + per_cr[0] = '['; + memcpy(&per_cr[1], &addr, 4); + per_cr[5] = ','; + memcpy(&per_cr[6], &value, 4); + per_cr[10] = ']'; + if (buff_size < CR_PER_LINE) { + pr_info("[%s] Dump buffer full (%d-th cr), flush to native space.\n", __func__, i); + /* pack it! */ + conndump_netlink_send_to_native(ctx->conn_type, "[M]", ctx->page_dump_buf, buff_idx); + + /* start from buffer start */ + buff_size = CONNSYS_DUMP_BUFF_SIZE; + buff_idx = 0; + memset(ctx->page_dump_buf, 0, CONNSYS_DUMP_BUFF_SIZE); + } + memcpy(&ctx->page_dump_buf[buff_idx], per_cr, CR_PER_LINE); + buff_size -= CR_PER_LINE; + buff_idx += CR_PER_LINE; + } + conndump_unmap(ctx, map_base); + } + } + } + + /* pack remaining item */ + if (buff_idx) { + pr_info("[%s] send remain %d bytes\n", __func__, buff_idx); + conndump_netlink_send_to_native(ctx->conn_type, "[M]", ctx->page_dump_buf, buff_idx); + } + + return ret; +} + +/***************************************************************************** + * FUNCTION + * conndump_nfra_get_phy_addr(&emi_addr, &emi_size); + * DESCRIPTION + * + * PARAMETERS + * + * RETURNS + * + *****************************************************************************/ +static int conndump_dump_mem_regions(struct connsys_dump_ctx* ctx) +{ +#define MEM_REGION_TAG_LENGTH 32 +#define MEM_REGION_MAX_COPY_LENGTH (CONNSYS_DUMP_BUFF_SIZE - MEM_REGION_TAG_LENGTH) + int ret = 0; + int idx; + unsigned int map_length; + void __iomem *map_base; + unsigned int* dump_buff = NULL; + + pr_info("[%s] dump_regions_num=%d\n", __func__, ctx->dump_regions_num); + /* Check reg readable */ + if (!conndump_check_cr_readable(ctx)) { + pr_err("CR not readable, skip memory region dump\n"); + return -1; + } + for (idx = 0; idx < ctx->dump_regions_num; idx++) { + /* Non-empty name means memory regions */ + if (ctx->dump_regions[idx].name[0] != 0 && + (ctx->dump_regions[idx].length > 0) && + (ctx->dump_regions[idx].length & 0x3) == 0 && + (ctx->dump_regions[idx].base & 0x3) == 0) { + pr_info("[%s][Region %d][%s] base=0x%x size=0x%x\n", + __func__, idx, ctx->dump_regions[idx].name, + ctx->dump_regions[idx].base, ctx->dump_regions[idx].length); + /* variable init */ + ret = 0; + dump_buff = (unsigned int*)conndump_malloc(ctx->dump_regions[idx].length); + if (!dump_buff) { + pr_err("Allocate buffer for %s fail.\n", + ctx->dump_regions[idx].name); + goto next_mem_region; + } + /* Change dynamic window */ + map_length = conndump_setup_dynamic_remap( + ctx, ctx->dump_regions[idx].base, ctx->dump_regions[idx].length); + if (map_length != ctx->dump_regions[idx].length) { + pr_err("Setup dynamic remap for %s fail. Expect 0x%x but 0x%x", + ctx->dump_regions[idx].name, + ctx->dump_regions[idx].length, + map_length); + goto next_mem_region; + } + map_base = conndump_remap(ctx, ctx->dump_regions[idx].base, map_length); + if (!map_base) { + pr_err("Remap %s fail.\n", ctx->dump_regions[idx].name); + goto next_mem_region; + } + memcpy_fromio(dump_buff, map_base, map_length); + conndump_unmap(ctx, map_base); + ret = conndump_netlink_send_to_native( + ctx->conn_type, + ctx->dump_regions[idx].name, + (char*)dump_buff, + ctx->dump_regions[idx].length); + if (ret != ctx->dump_regions[idx].length) { + pr_err("[%s][%s] Send fail, length = 0x%x but only 0x%x send\n", + __func__, ctx->dump_regions[idx].name, + ctx->dump_regions[idx].length, ret); + } + } +next_mem_region: + if (dump_buff) { + conndump_free((void*)dump_buff); + dump_buff = NULL; + } + } + return ret; +} + +/***************************************************************************** + * FUNCTION + * conndump_dump_emi + * DESCRIPTION + * + * PARAMETERS + * + * RETURNS + * + *****************************************************************************/ +static int conndump_dump_emi(struct connsys_dump_ctx* ctx) +{ +#define EMI_COMMAND_LENGTH 64 + int ret; + unsigned long comp_ret; + // format: emi_size=aaaaaaaa, mcif_emi_size=bbbbbbbb + char emi_dump_command[EMI_COMMAND_LENGTH]; + + snprintf(emi_dump_command, EMI_COMMAND_LENGTH, "emi_size=%d,mcif_emi_size=%d", ctx->full_emi_size, ctx->mcif_emi_size); + pr_info("[%s] dump command: %s\n", __func__, emi_dump_command); + conndump_set_dump_state(ctx, CORE_DUMP_EMI); + ret = conndump_netlink_send_to_native(ctx->conn_type, "[EMI]", emi_dump_command, strlen(emi_dump_command)); + + if (ret < 0) { + pr_err("Start EMI dump fail, ret = %d\n", ret); + return -1; + } + + comp_ret = wait_for_completion_timeout( + &ctx->emi_dump, + msecs_to_jiffies(CONNSYS_EMIDUMP_TIMEOUT)); + + if (comp_ret == 0) { + pr_err("EMI dump timeout\n"); + conndump_set_dump_state(ctx, CORE_DUMP_EMI_TIMEOUT); + } else { + pr_info("EMI dump end"); + conndump_set_dump_state(ctx, CORE_DUMP_DONE); + } + + return 0; +} + +static int connsys_coredump_init_dump_regions(struct connsys_dump_ctx* ctx, int num) +{ + int size = sizeof(struct dump_region)*num; + + ctx->dump_regions = (struct dump_region*)conndump_malloc(size); + if (!ctx->dump_regions) { + ctx->dump_regions_num = 0; + pr_err("ctx->dump_regions create fail!\n"); + return 0; + } + memset(ctx->dump_regions, 0, size); + ctx->dump_regions_num = num; + return num; +} + +static void connsys_coredump_deinit_dump_regions(struct connsys_dump_ctx* ctx) +{ + conndump_free(ctx->dump_regions); + ctx->dump_regions = 0; + ctx->dump_regions_num = 0; +} + +static void conndump_coredump_end(void* handler) +{ + struct connsys_dump_ctx* ctx = (struct connsys_dump_ctx*)handler; + + if (conndump_get_dump_state(ctx) == CORE_DUMP_EMI) { + pr_info("Wake up emi_dump\n"); + complete(&ctx->emi_dump); + } +} + +static int conndump_send_fake_coredump(struct connsys_dump_ctx* ctx) +{ + pr_info("Send fake coredump\n"); + return conndump_netlink_send_to_native(ctx->conn_type, "[M]", "FORCE_COREDUMP", 13); +} + +static void conndump_exception_show(struct connsys_dump_ctx* ctx, bool full_dump) +{ + if (full_dump) { + snprintf( + ctx->info.exception_log, CONNSYS_AEE_INFO_SIZE, + "%s %s %s %s", + INFO_HEAD, ctx->hw_config.name, + ctx->info.assert_type, ctx->info.dump_info); + } else { + snprintf( + ctx->info.exception_log, CONNSYS_AEE_INFO_SIZE, + "%s %s", + INFO_HEAD, ctx->hw_config.name); + } + +#if defined(CONNINFRA_PLAT_ALPS) && CONNINFRA_PLAT_ALPS + pr_info("par1: [%s] pars: [%s] par3: [%d]\n", + ctx->hw_config.exception_tag_name, + ctx->info.exception_log, + strlen(ctx->info.exception_log)); + /* Call AEE API */ + aed_common_exception_api( + ctx->hw_config.exception_tag_name, + NULL, 0, + (const int*)ctx->info.exception_log, strlen(ctx->info.exception_log), + ctx->info.exception_log, 0); +#endif +} + +/***************************************************************************** + * FUNCTION + * connsys_coredump_clean + * DESCRIPTION + * To clean coredump EMI region + * PARAMETERS + * + * RETURNS + * + *****************************************************************************/ +void connsys_coredump_clean(void* handler) +{ + struct connsys_dump_ctx* ctx = (struct connsys_dump_ctx*)handler; + + if (ctx == NULL) + return; + + pr_info("[%s] Clear %p size=%d as zero\n", __func__, ctx->emi_virt_addr_base, ctx->emi_size); + memset_io(ctx->emi_virt_addr_base, 0, ctx->emi_size); + + conndump_set_dump_state(ctx, CORE_DUMP_INIT); +} +EXPORT_SYMBOL(connsys_coredump_clean); + + +/***************************************************************************** + * FUNCTION + * connsys_coredump_setup_dump_region + * DESCRIPTION + * Parse dump region in EMI (including CR regions, IDLM, SYSRAM, ...) + * The number would be record in ctx->dump_regions_num + * The data would be stored in ctx->dump_regions + * PARAMETERS + * + * RETURNS + * + *****************************************************************************/ +int connsys_coredump_setup_dump_region(void* handler) +{ + int ret = 0; + int cr_regions_idx = 0; + int total_mem_region; + int total_count; + int i, idx = 0, offset; + struct connsys_dump_ctx* ctx = (struct connsys_dump_ctx*)handler; + struct dump_region* curr_region = 0; + const unsigned int BUF_SIZE = 1024; + const unsigned int MAX_IN_LINE = 10; + char buf[BUF_SIZE]; + int wsize = 0; + unsigned int accum_size = 0; + unsigned int cr_count = 1; + + total_mem_region = conndump_get_dmp_info( + ctx, CONNSYS_DUMP_CTRL_BLOCK_OFFSET + EXP_CTRL_TOTAL_MEM_REGION, false); + + /* Get idx first. The number is idx/8 */ + cr_regions_idx = conndump_get_dmp_info( + ctx, CONNSYS_DUMP_CTRL_BLOCK_OFFSET + EXP_CTRL_CR_REGION_IDX, false); + if (cr_regions_idx & 0x7) { + pr_err("cr_regions_idx should be multiple of 8. But it is %d.\n", cr_regions_idx); + } + cr_regions_idx = (cr_regions_idx >> 3); + total_count = total_mem_region + cr_regions_idx; + pr_info("CR region=%d. Memory region=%d total dump regions is %d.\n", + cr_regions_idx, total_mem_region, total_count); + + if (ctx->dump_regions) { + connsys_coredump_deinit_dump_regions(ctx); + } + if (total_count == 0) { + pr_info("Total dump regions is %d.\n", total_count); + return 0; + } + + ret = connsys_coredump_init_dump_regions(ctx, total_count); + if (ret != total_count) { + pr_err("[%s] allocate %d dump regions failed\n", __func__, total_count); + return 0; + } + + /* Setup memory region */ + offset = CONNSYS_DUMP_CTRL_BLOCK_OFFSET + EXP_CTRL_MEM_REGION_NAME_1; + for (i = 0, curr_region = ctx->dump_regions; i < total_mem_region && idx < total_count; i++, idx++, offset += 12, curr_region++) { + conndump_get_dmp_char(ctx, offset, 4, curr_region->name); + curr_region->base = conndump_get_dmp_info(ctx, offset + 4, false); + curr_region->length = conndump_get_dmp_info(ctx, offset + 8, false); + pr_info("[%d][Memory region] name: %s, base: %x, length: %x\n", + idx, + curr_region->name, + curr_region->base, + curr_region->length); + } + + memset(buf, '\0', sizeof(buf)); + wsize = snprintf(buf, BUF_SIZE, "[CR region](base,length): "); + + offset = CONNSYS_DUMP_CR_REGION_OFFSET; + for (i = 0; i < cr_regions_idx && idx < total_count; i++, idx++, offset+=8) { + ctx->dump_regions[idx].base = conndump_get_dmp_info(ctx, offset, false); + ctx->dump_regions[idx].length = conndump_get_dmp_info(ctx, offset + 4, false); + + if (wsize >= 0 && wsize < (BUF_SIZE - accum_size)) { + accum_size += wsize; + wsize = snprintf(buf + accum_size, (BUF_SIZE - accum_size), "[%d](0x%x, %d), ", idx, ctx->dump_regions[idx].base, ctx->dump_regions[idx].length); + } + + if (cr_count % MAX_IN_LINE == 0) { + pr_info("%s", buf); + memset(buf, '\0', sizeof(buf)); + wsize = snprintf(buf, BUF_SIZE, "[CR region](base,length): "); + accum_size = 0; + } + + cr_count++; + } + + if ((cr_count - 1) % MAX_IN_LINE != 0) { + pr_info("%s", buf); + } + + return ctx->dump_regions_num; +} +EXPORT_SYMBOL(connsys_coredump_setup_dump_region); + +/***************************************************************************** + * FUNCTION + * connsys_coredump_start + * DESCRIPTION + * + * PARAMETERS + * + * RETURNS + * + *****************************************************************************/ +int connsys_coredump_start( + void* handler, + unsigned int dump_property, + int drv, + char* reason) +{ + struct connsys_dump_ctx* ctx = (struct connsys_dump_ctx*)handler; + int ret = 0; + bool full_dump = false; + struct timeval begin, end, put_done; + struct timeval mem_start, mem_end, cr_start, cr_end, emi_dump_start, emi_dump_end; + + static DEFINE_RATELIMIT_STATE(_rs, HZ, 1); + + if (ctx == NULL) + return 0; + + /* TODO: Check coredump mode */ + if (connsys_coredump_get_mode() == DUMP_MODE_RESET_ONLY) { + pr_info("Chip reset only, skip coredump\n"); + return 0; + } + + pr_info("[COREDUMP] dump_property=[0x%x] drv=[%d] reason=[%s]\n", dump_property, drv, reason); + do_gettimeofday(&begin); + conndump_set_dump_state(ctx, CORE_DUMP_START); + /* Reset assert info */ + memset(&ctx->info, 0, sizeof(struct connsys_dump_info)); + if (drv >= CONNDRV_TYPE_BT && drv < CONNDRV_TYPE_MAX) { + ctx->info.issue_type = CONNSYS_ISSUE_DRIVER_ASSERT; + ctx->info.drv_type = drv; + snprintf(ctx->info.reason, CONNSYS_ASSERT_REASON_SIZE, "%s", reason); + } + + /* Start coredump timer */ + mod_timer(&ctx->dmp_timer, jiffies + (CONNSYS_COREDUMP_TIMEOUT) / (1000 / HZ)); + + /* Check coredump status */ + while (1) { + if (conndump_get_dmp_info(ctx, CONNSYS_DUMP_CTRL_BLOCK_OFFSET + EXP_CTRL_DUMP_STATE, false) == FW_DUMP_STATE_PUT_DONE) { + pr_info("coredump put done\n"); + del_timer(&ctx->dmp_timer); + full_dump = true; + break; + } else if (conndump_get_dump_state(ctx) == CORE_DUMP_TIMEOUT) { + pr_err("Coredump timeout\n"); + if (ctx->callback.poll_cpupcr) { + pr_info("Debug dump:\n"); + ctx->callback.poll_cpupcr(5, 1); + } + conndump_send_fake_coredump(ctx); + goto partial_dump; + } + if (__ratelimit(&_rs)) { + pr_info("Wait coredump state, EMI[0]=0x%x EMI[4]=0x%x\n", + conndump_get_dmp_info(ctx, 0, false), + conndump_get_dmp_info(ctx, 4, false)); + } + if (dump_property & CONNSYS_DUMP_PROPERTY_NO_WAIT) { + pr_info("Don't wait dump status, go to partial dump\n"); + if (ctx->callback.poll_cpupcr) { + pr_info("Debug dump:\n"); + ctx->callback.poll_cpupcr(5, 1); + } + conndump_send_fake_coredump(ctx); + goto partial_dump; + } + msleep(1); + } + do_gettimeofday(&put_done); + conndump_set_dump_state(ctx, CORE_DUMP_DOING); + + /* Get print_buff */ + conndump_dump_print_buff(ctx); + + /* Get dump_buff and send to pack it */ + conndump_dump_dump_buff(ctx); + +partial_dump: + /* TODO: move to init or other suitable place */ + ret = connsys_coredump_setup_dump_region(ctx); + if (!ret) + pr_err("No dump region found\n"); + + conndump_set_dump_state(ctx, CORE_DUMP_DOING); + /* Memory region and CR region should be setup when MCU init */ + /* Parse CR region and send to pack it */ + do_gettimeofday(&cr_start); + conndump_dump_cr_regions(ctx); + do_gettimeofday(&cr_end); + + /* Construct assert info and send to native */ + conndump_info_format(ctx, ctx->page_dump_buf, CONNSYS_DUMP_BUFF_SIZE, full_dump); + + /* Read memory region on ctrl block */ + do_gettimeofday(&mem_start); + conndump_dump_mem_regions(ctx); + do_gettimeofday(&mem_end); + + + /* Start EMI dump */ + do_gettimeofday(&emi_dump_start); + conndump_dump_emi(ctx); + do_gettimeofday(&emi_dump_end); + + /* All process finished, set to init status */ + conndump_set_dump_state(ctx, CORE_DUMP_INIT); + + conndump_exception_show(ctx, full_dump); + do_gettimeofday(&end); + pr_info("Coredump end\n"); + if (full_dump) { + pr_info("%s coredump summary: full dump total=[%lu] put_done=[%lu] cr=[%lu] mem=[%lu] emi=[%lu]\n", + g_type_name[ctx->conn_type], + timeval_to_ms(&begin, &end), + timeval_to_ms(&begin, &put_done), + timeval_to_ms(&cr_start, &cr_end), + timeval_to_ms(&mem_start, &mem_end), + timeval_to_ms(&emi_dump_start, &emi_dump_end)); + } else { + pr_info("%s coredump summary: partial dump total=[%lu] cr=[%lu] mem=[%lu] emi=[%lu]\n", + g_type_name[ctx->conn_type], + timeval_to_ms(&begin, &end), + timeval_to_ms(&cr_start, &cr_end), + timeval_to_ms(&mem_start, &mem_end), + timeval_to_ms(&emi_dump_start, &emi_dump_end)); + } + return 0; +} +EXPORT_SYMBOL(connsys_coredump_start); + +/***************************************************************************** + * FUNCTION + * connsys_coredump_get_start_offset + * DESCRIPTION + * + * PARAMETERS + * + * RETURNS + * + *****************************************************************************/ +phys_addr_t connsys_coredump_get_start_offset(int conn_type) +{ + struct coredump_hw_config *config = get_coredump_platform_config(conn_type); + + if (config) + return config->start_offset; + return 0; +} +EXPORT_SYMBOL(connsys_coredump_get_start_offset); + +/***************************************************************************** + * FUNCTION + * connsys_coredump_init + * DESCRIPTION + * + * PARAMETERS + * + * RETURNS + * + *****************************************************************************/ +void* connsys_coredump_init( + int conn_type, + struct coredump_event_cb* cb) +{ + struct connsys_dump_ctx* ctx = 0; + struct netlink_event_cb nl_cb; + struct coredump_hw_config *config = get_coredump_platform_config(conn_type); + phys_addr_t emi_base; + unsigned int emi_size, mcif_emi_size; + + /* Get EMI config */ + if (config == NULL) { + pr_err("Get coredump EMI config fail\n"); + goto error_exit; + } + + ctx = (struct connsys_dump_ctx*)conndump_malloc(sizeof(struct connsys_dump_ctx)); + if (!ctx) { + pr_err("Allocate connsys_dump_ctx fail"); + goto error_exit; + } + + /* clean it */ + memset(ctx, 0, sizeof(struct connsys_dump_ctx)); + memcpy(&ctx->hw_config, config, sizeof(struct coredump_hw_config)); + + ctx->page_dump_buf = (char*)conndump_malloc(CONNSYS_DUMP_BUFF_SIZE); + if (!ctx->page_dump_buf) { + pr_err("Create dump buffer fail.\n"); + goto error_exit; + } + + ctx->conn_type = conn_type; + if (cb) + memcpy(&ctx->callback, cb, sizeof(struct coredump_event_cb)); + else + pr_info("[%s][%d] callback is null\n", __func__, conn_type); + + /* EMI init */ + conninfra_get_emi_phy_addr(CONNSYS_EMI_FW, &emi_base, &emi_size); + conninfra_get_emi_phy_addr(CONNSYS_EMI_MCIF, NULL, &mcif_emi_size); + pr_info("Get emi_base=0x%x emi_size=%d\n", emi_base, emi_size); + ctx->full_emi_size = emi_size; + ctx->emi_phy_addr_base = config->start_offset + emi_base; + ctx->emi_size = config->size; + ctx->mcif_emi_size = mcif_emi_size; + + ctx->emi_virt_addr_base = + ioremap_nocache(ctx->emi_phy_addr_base, ctx->emi_size); + if (ctx->emi_virt_addr_base == 0) { + pr_err("Remap emi fail (0x%08x) size=%d", + ctx->emi_phy_addr_base, ctx->emi_size); + goto error_exit; + } + + pr_info("Clear %p size=%d as zero\n", ctx->emi_virt_addr_base, ctx->emi_size); + memset_io(ctx->emi_virt_addr_base, 0, ctx->emi_size); + + /* Setup timer */ + init_timer(&ctx->dmp_timer); + ctx->dmp_timer.function = conndump_timeout_handler; + ctx->dmp_timer.data = (unsigned long)ctx; + init_completion(&ctx->emi_dump); + + conndump_set_dump_state(ctx, CORE_DUMP_INIT); + + /* Init netlink */ + nl_cb.coredump_end = conndump_coredump_end; + conndump_netlink_init(ctx->conn_type, ctx, &nl_cb); + return ctx; + +error_exit: + if (ctx) + connsys_coredump_deinit(ctx); + + return 0; +} +EXPORT_SYMBOL(connsys_coredump_init); + +/***************************************************************************** + * FUNCTION + * connsys_coredump_deinit + * DESCRIPTION + * + * PARAMETERS + * + * RETURNS + * + *****************************************************************************/ +void connsys_coredump_deinit(void* handler) +{ + struct connsys_dump_ctx* ctx = (struct connsys_dump_ctx*)handler; + + if (handler == NULL) + return; + + if (ctx->emi_virt_addr_base) { + iounmap(ctx->emi_virt_addr_base); + ctx->emi_virt_addr_base = NULL; + } + + if (ctx->page_dump_buf) { + conndump_free(ctx->page_dump_buf); + ctx->page_dump_buf = NULL; + } + + if (ctx->dump_regions) { + connsys_coredump_deinit_dump_regions(ctx); + ctx->dump_regions = NULL; + } + + conndump_free(ctx); +} +EXPORT_SYMBOL(connsys_coredump_deinit); + + +/***************************************************************************** + * FUNCTION + * connsys_coredump_get_mode + * DESCRIPTION + * + * PARAMETERS + * + * RETURNS + * + *****************************************************************************/ +enum connsys_coredump_mode connsys_coredump_get_mode(void) +{ + return atomic_read(&g_dump_mode); +} +EXPORT_SYMBOL(connsys_coredump_get_mode); + +/***************************************************************************** + * FUNCTION + * connsys_coredump_set_dump_mode + * DESCRIPTION + * + * PARAMETERS + * + * RETURNS + * + *****************************************************************************/ +void connsys_coredump_set_dump_mode(enum connsys_coredump_mode mode) +{ + if (mode < DUMP_MODE_MAX) + atomic_set(&g_dump_mode, mode); +} +EXPORT_SYMBOL(connsys_coredump_set_dump_mode); + + diff --git a/drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/connsys_coredump.h b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/connsys_coredump.h new file mode 100644 index 0000000000000..609f60b7008d2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/connsys_coredump.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#ifndef _CONNSYS_COREDUMP_H_ +#define _CONNSYS_COREDUMP_H_ + +#include +#include + + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/* Coredump property */ +#define CONNSYS_DUMP_PROPERTY_NO_WAIT 0x1 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +enum connsys_coredump_mode { + DUMP_MODE_RESET_ONLY = 0, + DUMP_MODE_AEE = 1, + DUMP_MODE_DAEMON = 2, + DUMP_MODE_MAX, +}; + +struct coredump_event_cb { + int (*reg_readable)(void); + void (*poll_cpupcr)(unsigned int times, unsigned int sleep); +}; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/* subsys usage */ +void* connsys_coredump_init( + int conn_type, + struct coredump_event_cb* cb); +void connsys_coredump_deinit(void* handler); + +phys_addr_t connsys_coredump_get_start_offset(int conn_type); + +int connsys_coredump_setup_dump_region(void* handler); +int connsys_coredump_start( + void* handler, + unsigned int dump_property, + int drv, + char *reason); +void connsys_coredump_clean(void* handler); + + +/* config relative */ +enum connsys_coredump_mode connsys_coredump_get_mode(void); +void connsys_coredump_set_dump_mode(enum connsys_coredump_mode mode); + +#endif diff --git a/drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/connsys_coredump_emi.h b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/connsys_coredump_emi.h new file mode 100644 index 0000000000000..b52140429305e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/connsys_coredump_emi.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#ifndef _CONNSYS_COREDUMP_EMI_H_ +#define _CONNSYS_COREDUMP_EMI_H_ + +#include +#include + + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + + +/* Block and size definition */ +#define CONNSYS_DUMP_CTRL_BLOCK_SIZE 0x80 +#define CONNSYS_DUMP_DEBUG_BLOCK_SIZE 0x80 +#define CONNSYS_DUMP_PRINT_BUFF_SIZE 0x7f00 +#define CONNSYS_DUMP_DUMP_BUFF_SIZE 0x8000 +#define CONNSYS_DUMP_CR_REGION_SIZE 0x8000 + +#define CONNSYS_DUMP_CTRL_BLOCK_OFFSET 0x0 +#define CONNSYS_DUMP_DEBUG_BLOCK_OFFSET (CONNSYS_DUMP_CTRL_BLOCK_OFFSET + CONNSYS_DUMP_CTRL_BLOCK_SIZE) +#define CONNSYS_DUMP_PRINT_BUFF_OFFSET (CONNSYS_DUMP_DEBUG_BLOCK_OFFSET + CONNSYS_DUMP_DEBUG_BLOCK_SIZE) +#define CONNSYS_DUMP_DUMP_BUFF_OFFSET (CONNSYS_DUMP_PRINT_BUFF_OFFSET + CONNSYS_DUMP_PRINT_BUFF_SIZE) +#define CONNSYS_DUMP_CR_REGION_OFFSET (CONNSYS_DUMP_DUMP_BUFF_OFFSET + CONNSYS_DUMP_DUMP_BUFF_SIZE) + +/* Control block definition */ +enum connsys_dump_ctrl_block_offset { + EXP_CTRL_DUMP_STATE = 0x4, + EXP_CTRL_OUTBAND_ASSERT_W1 = 0x8, + EXP_CTRL_PRINT_BUFF_IDX = 0xC, + EXP_CTRL_DUMP_BUFF_IDX = 0x10, + EXP_CTRL_CR_REGION_IDX = 0x14, + EXP_CTRL_TOTAL_MEM_REGION = 0x18, + EXP_CTRL_MEM_REGION_NAME_1 = 0x1C, + EXP_CTRL_MEM_REGION_START_1 = 0x20, + EXP_CTRL_MEM_REGION_LEN_1 = 0x24, + EXP_CTRL_MEM_REGION_NAME_2 = 0x28, + EXP_CTRL_MEM_REGION_START_2 = 0x2c, + EXP_CTRL_MEM_REGION_LEN_2 = 0x30, + EXP_CTRL_MEM_REGION_NAME_3 = 0x34, + EXP_CTRL_MEM_REGION_START_3 = 0x38, + EXP_CTRL_MEM_REGION_LEN_3 = 0x3c, + EXP_CTRL_MEM_REGION_NAME_4 = 0x40, + EXP_CTRL_MEM_REGION_START_4 = 0x44, + EXP_CTRL_MEM_REGION_LEN_4 = 0x48, + EXP_CTRL_MEM_REGION_NAME_5 = 0x4C, + EXP_CTRL_MEM_REGION_START_5 = 0x50, + EXP_CTRL_MEM_REGION_LEN_5 = 0x54, +}; + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + + +#endif /*_CONNSYS_COREDUMP_EMI_H_*/ diff --git a/drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/platform/include/connsys_coredump_hw_config.h b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/platform/include/connsys_coredump_hw_config.h new file mode 100644 index 0000000000000..d150804e7d929 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/platform/include/connsys_coredump_hw_config.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#ifndef _CONNSYS_COREDUMP_HW_CONFIG_H_ +#define _CONNSYS_COREDUMP_HW_CONFIG_H_ + + +struct coredump_hw_config { + char* name; + phys_addr_t start_offset; + unsigned int size; + unsigned int seg1_cr; + unsigned int seg1_value_end; + unsigned int seg1_start_addr; + unsigned int seg1_phy_addr; + unsigned int task_table_size; + char** task_map_table; + char* exception_tag_name; +}; + +#endif + diff --git a/drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/platform/mt6885/mt6885.c b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/platform/mt6885/mt6885.c new file mode 100644 index 0000000000000..3ebcf97c432f1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/platform/mt6885/mt6885.c @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#include + +#include "connsys_debug_utility.h" +#include "connsys_coredump_hw_config.h" + +static char* wifi_task_str[] = { + "Task_WIFI", + "Task_TST_WFSYS", + "Task_Idle_WFSYS", +}; + +static char* bt_task_str[] = { + "Task_WMT", + "Task_BT", + "Task_TST_BTSYS", + "Task_BT2", + "Task_Idle_BTSYS", +}; + +struct coredump_hw_config g_coredump_config[CONN_DEBUG_TYPE_END] = { + /* Wi-Fi config */ + { + .name = "WFSYS", +#ifdef CONFIG_FPGA_EARLY_PORTING + .start_offset = 0x0004f000, +#else + .start_offset = 0x027f000, +#endif + .size = 0x18000, + .seg1_cr = 0x1800112c, + .seg1_value_end = 0x187fffff, + .seg1_start_addr = 0x18001120, + .seg1_phy_addr = 0x18500000, + .task_table_size = sizeof(wifi_task_str)/sizeof(char*), + .task_map_table = wifi_task_str, + .exception_tag_name = "combo_wifi", + }, + /* BT config */ + { + .name = "BTSYS", + .start_offset = 0x33000, + .size = 0x18000, + .seg1_cr = 0x18001110, + .seg1_value_end = 0x18bfffff, + .seg1_start_addr = 0x18001104, + .seg1_phy_addr = 0x18900000, + .task_table_size = sizeof(bt_task_str)/sizeof(char*), + .task_map_table = bt_task_str, + .exception_tag_name = "combo_bt", + }, +}; + +struct coredump_hw_config* get_coredump_platform_config(int conn_type) +{ + if (conn_type < 0 || conn_type >= CONN_DEBUG_TYPE_END) { + pr_err("Incorrect type: %d\n", conn_type); + return NULL; + } + return &g_coredump_config[conn_type]; +} + +unsigned int get_coredump_platform_chipid(void) +{ + return 0x6885; +} + +char* get_task_string(int conn_type, unsigned int task_id) +{ + if (conn_type < 0 || conn_type >= CONN_DEBUG_TYPE_END) { + pr_err("Incorrect type: %d\n", conn_type); + return NULL; + } + + if (task_id > g_coredump_config[conn_type].task_table_size) { + pr_err("[%s] Incorrect task: %d\n", + g_coredump_config[conn_type].name, task_id); + return NULL; + } + + return g_coredump_config[conn_type].task_map_table[task_id]; +} + +char* get_sys_name(int conn_type) +{ + if (conn_type < 0 || conn_type >= CONN_DEBUG_TYPE_END) { + pr_err("Incorrect type: %d\n", conn_type); + return NULL; + } + return g_coredump_config[conn_type].name; +} + +bool is_host_view_cr(unsigned int addr, unsigned int* host_view) +{ + if (addr >= 0x7C000000 && addr <= 0x7Cffffff) { + if (host_view) { + *host_view = ((addr - 0x7c000000) + 0x18000000); + } + return true; + } else if (addr >= 0x18000000 && addr <= 0x18ffffff) { + if (host_view) { + *host_view = addr; + } + return true; + } + return false; +} diff --git a/drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/platform/mt6893/mt6893.c b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/platform/mt6893/mt6893.c new file mode 100644 index 0000000000000..113695a5fa16b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/coredump/platform/mt6893/mt6893.c @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 MediaTek Inc. + */ + +#include + +#include "connsys_debug_utility.h" +#include "connsys_coredump_hw_config.h" + +static char* wifi_task_str[] = { + "Task_WIFI", + "Task_TST_WFSYS", + "Task_Idle_WFSYS", +}; + +static char* bt_task_str[] = { + "Task_WMT", + "Task_BT", + "Task_TST_BTSYS", + "Task_BT2", + "Task_Idle_BTSYS", +}; + +struct coredump_hw_config g_coredump_config[CONN_DEBUG_TYPE_END] = { + /* Wi-Fi config */ + { + .name = "WFSYS", +#ifdef CONFIG_FPGA_EARLY_PORTING + .start_offset = 0x0004f000, +#else + .start_offset = 0x027f000, +#endif + .size = 0x18000, + .seg1_cr = 0x1800112c, + .seg1_value_end = 0x187fffff, + .seg1_start_addr = 0x18001120, + .seg1_phy_addr = 0x18500000, + .task_table_size = sizeof(wifi_task_str)/sizeof(char*), + .task_map_table = wifi_task_str, + .exception_tag_name = "combo_wifi", + }, + /* BT config */ + { + .name = "BTSYS", + .start_offset = 0x33000, + .size = 0x18000, + .seg1_cr = 0x18001110, + .seg1_value_end = 0x18bfffff, + .seg1_start_addr = 0x18001104, + .seg1_phy_addr = 0x18900000, + .task_table_size = sizeof(bt_task_str)/sizeof(char*), + .task_map_table = bt_task_str, + .exception_tag_name = "combo_bt", + }, +}; + +struct coredump_hw_config* get_coredump_platform_config(int conn_type) +{ + if (conn_type < 0 || conn_type >= CONN_DEBUG_TYPE_END) { + pr_err("Incorrect type: %d\n", conn_type); + return NULL; + } + return &g_coredump_config[conn_type]; +} + +unsigned int get_coredump_platform_chipid(void) +{ + return 0x6893; +} + +char* get_task_string(int conn_type, unsigned int task_id) +{ + if (conn_type < 0 || conn_type >= CONN_DEBUG_TYPE_END) { + pr_err("Incorrect type: %d\n", conn_type); + return NULL; + } + + if (task_id > g_coredump_config[conn_type].task_table_size) { + pr_err("[%s] Incorrect task: %d\n", + g_coredump_config[conn_type].name, task_id); + return NULL; + } + + return g_coredump_config[conn_type].task_map_table[task_id]; +} + +char* get_sys_name(int conn_type) +{ + if (conn_type < 0 || conn_type >= CONN_DEBUG_TYPE_END) { + pr_err("Incorrect type: %d\n", conn_type); + return NULL; + } + return g_coredump_config[conn_type].name; +} + +bool is_host_view_cr(unsigned int addr, unsigned int* host_view) +{ + if (addr >= 0x7C000000 && addr <= 0x7Cffffff) { + if (host_view) { + *host_view = ((addr - 0x7c000000) + 0x18000000); + } + return true; + } else if (addr >= 0x18000000 && addr <= 0x18ffffff) { + if (host_view) { + *host_view = addr; + } + return true; + } + return false; +} diff --git a/drivers/misc/mediatek/connectivity/conninfra/debug_utility/include/connsys_debug_utility.h b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/include/connsys_debug_utility.h new file mode 100644 index 0000000000000..897bda5009825 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/debug_utility/include/connsys_debug_utility.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#ifndef _CONNSYS_DEBUG_UTILITY_H_ +#define _CONNSYS_DEBUG_UTILITY_H_ + +#include +#include + +#include "coredump/connsys_coredump.h" +#include "connsyslog/connsyslog.h" + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +enum CONN_DEBUG_TYPE { + CONN_DEBUG_TYPE_WIFI = 0, + CONN_DEBUG_TYPE_BT = 1, + CONN_DEBUG_TYPE_END, +}; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + + +#endif /*_CONNSYS_DEBUG_UTILITY_H_*/ diff --git a/drivers/misc/mediatek/connectivity/conninfra/drv_init/bluetooth_drv_init.c b/drivers/misc/mediatek/connectivity/conninfra/drv_init/bluetooth_drv_init.c new file mode 100644 index 0000000000000..ec4b05641c214 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/drv_init/bluetooth_drv_init.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#include +#include "bluetooth_drv_init.h" + +#ifdef CONFIG_MTK_COMBO_BT +int __attribute__((weak)) mtk_wcn_stpbt_drv_init() +{ + pr_info("Not implement mtk_wcn_stpbt_drv_init\n"); + return 0; +} +#endif + +int do_bluetooth_drv_init(int chip_id) +{ + int i_ret = -1; + +#ifdef CONFIG_MTK_COMBO_BT + pr_info("Start to do bluetooth driver init\n"); + i_ret = mtk_wcn_stpbt_drv_init(); + pr_info("Finish bluetooth driver init, i_ret:%d\n", i_ret); +#else + pr_info("CONFIG_MTK_COMBO_BT is not defined\n"); +#endif + return i_ret; +} diff --git a/drivers/misc/mediatek/connectivity/conninfra/drv_init/conn_drv_init.c b/drivers/misc/mediatek/connectivity/conninfra/drv_init/conn_drv_init.c new file mode 100644 index 0000000000000..06a0c3056d143 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/drv_init/conn_drv_init.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#include + +#include "conn_drv_init.h" +#include "fm_drv_init.h" +#include "wlan_drv_init.h" +#include "bluetooth_drv_init.h" +#include "gps_drv_init.h" + +#ifdef MTK_WCN_REMOVE_KERNEL_MODULE +int do_connectivity_driver_init(int chip_id) +{ + int i_ret = 0; + int tmp_ret = 0; + static int init_before = 0; + + /* To avoid invoking more than once.*/ + if (init_before) + return 0; + init_before = 1; + + tmp_ret = do_bluetooth_drv_init(chip_id); + i_ret += tmp_ret; + if (tmp_ret) + pr_err("Do BT driver init failed, ret:%d\n", tmp_ret); + + tmp_ret = do_gps_drv_init(chip_id); + i_ret += tmp_ret; + if (tmp_ret) + pr_err("Do GPS driver init failed, ret:%d\n", tmp_ret); + + tmp_ret = do_fm_drv_init(chip_id); + i_ret += tmp_ret; + if (tmp_ret) + pr_err("Do FM module init failed, ret:%d\n", tmp_ret); + + tmp_ret = do_wlan_drv_init(chip_id); + i_ret += tmp_ret; + if (tmp_ret) + pr_err("Do wlan module init failed, ret:%d\n", tmp_ret); + + return i_ret; +} +#endif + diff --git a/drivers/misc/mediatek/connectivity/conninfra/drv_init/fm_drv_init.c b/drivers/misc/mediatek/connectivity/conninfra/drv_init/fm_drv_init.c new file mode 100644 index 0000000000000..35d512408c435 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/drv_init/fm_drv_init.c @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#include + +#include "fm_drv_init.h" + +#ifdef CONFIG_MTK_FMRADIO +int __attribute__((weak)) mtk_wcn_fm_init() +{ + pr_err("no impl. mtk_wcn_fm_init\n"); + return 0; +} +#endif + +int do_fm_drv_init(int chip_id) +{ + pr_info("Start to do fm module init\n"); + +#ifdef CONFIG_MTK_FMRADIO + mtk_wcn_fm_init(); +#endif + + pr_info("Finish fm module init\n"); + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/conninfra/drv_init/gps_drv_init.c b/drivers/misc/mediatek/connectivity/conninfra/drv_init/gps_drv_init.c new file mode 100644 index 0000000000000..f3e7dc7169d38 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/drv_init/gps_drv_init.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#include + +#include "gps_drv_init.h" + +#ifdef CONFIG_MTK_GPS_SUPPORT +int __attribute__((weak)) mtk_wcn_gpsdl_drv_init() +{ + pr_info("No impl. %s\n", __func__); + return 0; +} +#endif + +int do_gps_drv_init(int chip_id) +{ + int i_ret = -1; +#ifdef CONFIG_MTK_GPS_SUPPORT + pr_info("Start to do gps driver init\n"); + i_ret = mtk_wcn_gpsdl_drv_init(); + pr_info("finish gps driver init, i_ret:%d\n", i_ret); +#else + pr_info("CONFIG_MTK_GPS_SUPPORT is not defined\n"); +#endif + return i_ret; + +} diff --git a/drivers/misc/mediatek/connectivity/conninfra/drv_init/include/bluetooth_drv_init.h b/drivers/misc/mediatek/connectivity/conninfra/drv_init/include/bluetooth_drv_init.h new file mode 100644 index 0000000000000..a47881f0baf2b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/drv_init/include/bluetooth_drv_init.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#ifndef _BLUETOOTH_DRIVER_INIT_H_ +#define _BLUETOOTH_DRIVER_INIT_H_ + +extern int do_bluetooth_drv_init(int chip_id); +extern int mtk_wcn_stpbt_drv_init(void); +#endif diff --git a/drivers/misc/mediatek/connectivity/conninfra/drv_init/include/conn_drv_init.h b/drivers/misc/mediatek/connectivity/conninfra/drv_init/include/conn_drv_init.h new file mode 100644 index 0000000000000..697b420ae1c7b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/drv_init/include/conn_drv_init.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#ifndef _CONNECTIVITY_DRV_INIT_H_ +#define _CONNECTIVITY_DRV_INIT_H_ +extern int do_connectivity_driver_init(int chip_id); +#endif diff --git a/drivers/misc/mediatek/connectivity/conninfra/drv_init/include/fm_drv_init.h b/drivers/misc/mediatek/connectivity/conninfra/drv_init/include/fm_drv_init.h new file mode 100644 index 0000000000000..e4d749297b23c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/drv_init/include/fm_drv_init.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#ifndef _FM_DRV_INIT_H_ +#define _FM_DRV_INIT_H_ +extern int do_fm_drv_init(int chip_id); +extern int mtk_wcn_fm_init(void); +extern void mtk_wcn_fm_exit(void); +#endif diff --git a/drivers/misc/mediatek/connectivity/conninfra/drv_init/include/gps_drv_init.h b/drivers/misc/mediatek/connectivity/conninfra/drv_init/include/gps_drv_init.h new file mode 100644 index 0000000000000..c274b3ad2cbe5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/drv_init/include/gps_drv_init.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#ifndef _GPS_DRIVER_INIT_H_ +#define _GPS_DRIVER_INIT_H_ +extern int do_gps_drv_init(int chip_id); +extern int mtk_wcn_stpgps_drv_init(void); +#endif diff --git a/drivers/misc/mediatek/connectivity/conninfra/drv_init/include/wlan_drv_init.h b/drivers/misc/mediatek/connectivity/conninfra/drv_init/include/wlan_drv_init.h new file mode 100644 index 0000000000000..12d74827afe44 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/drv_init/include/wlan_drv_init.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#ifndef _WLAN_DRV_INIT_H_ +#define _WLAN_DRV_INIT_H_ + + +extern int do_wlan_drv_init(int chip_id); + +extern int mtk_wcn_wmt_wifi_init(void); + +extern int mtk_wcn_wlan_gen4_init(void); + +#endif diff --git a/drivers/misc/mediatek/connectivity/conninfra/drv_init/wlan_drv_init.c b/drivers/misc/mediatek/connectivity/conninfra/drv_init/wlan_drv_init.c new file mode 100644 index 0000000000000..d62c7fc9be620 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/drv_init/wlan_drv_init.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#include + +#include "wlan_drv_init.h" + +int __attribute__((weak)) mtk_wcn_wlan_gen4_init() +{ + pr_info("no impl. mtk_wcn_wlan_gen4_init\n"); + return 0; +} + +int __attribute__((weak)) mtk_wcn_wmt_wifi_init() +{ + pr_info("no impl. mtk_wcn_wmt_wifi_init"); + return 0; +} + +int do_wlan_drv_init(int chip_id) +{ + int i_ret = 0; + int ret = 0; + + pr_info("Start to do wlan module init 0x%x\n", chip_id); + + /* WMT-WIFI char dev init */ + ret = mtk_wcn_wmt_wifi_init(); + pr_info("WMT-WIFI char dev init, ret:%d\n", ret); + i_ret += ret; + + /* WLAN driver init */ + ret = mtk_wcn_wlan_gen4_init(); + pr_info("WLAN-GEN4 driver init, ret:%d\n", ret); + + i_ret += ret; + + pr_info("Finish wlan module init\n"); + + return i_ret; +} diff --git a/drivers/misc/mediatek/connectivity/conninfra/include/conninfra.h b/drivers/misc/mediatek/connectivity/conninfra/include/conninfra.h new file mode 100644 index 0000000000000..9162e983f1ec0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/include/conninfra.h @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _CONNINFRA_H_ +#define _CONNINFRA_H_ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +enum consys_drv_type { + CONNDRV_TYPE_BT = 0, + CONNDRV_TYPE_FM = 1, + CONNDRV_TYPE_GPS = 2, + CONNDRV_TYPE_WIFI = 3, + CONNDRV_TYPE_CONNINFRA = 4, + CONNDRV_TYPE_MAX +}; + +enum consys_adie_ctl_type { + CONNSYS_ADIE_CTL_HOST_BT, + CONNSYS_ADIE_CTL_HOST_FM, + CONNSYS_ADIE_CTL_HOST_GPS, + CONNSYS_ADIE_CTL_HOST_WIFI, + CONNSYS_ADIE_CTL_HOST_CONNINFRA, + CONNSYS_ADIE_CTL_FW_BT, + CONNSYS_ADIE_CTL_FW_WIFI, + CONNSYS_ADIE_CTL_MAX +}; + +/* HW-specific, need sync with FW. DO NOT MODIFY */ +enum sys_spi_subsystem +{ + SYS_SPI_WF1 = 0x00, + SYS_SPI_WF = 0x01, + SYS_SPI_BT = 0x02, + SYS_SPI_FM = 0x03, + SYS_SPI_GPS = 0x04, + SYS_SPI_TOP = 0x05, + SYS_SPI_WF2 = 0x06, + SYS_SPI_WF3 = 0x07, + SYS_SPI_MAX +}; + +enum connsys_spi_speed_type { + CONNSYS_SPI_SPEED_26M, + CONNSYS_SPI_SPEED_64M, + CONNSYS_SPI_SPEED_MAX +}; + +enum connsys_clock_schematic +{ + CONNSYS_CLOCK_SCHEMATIC_26M_COTMS = 0, + CONNSYS_CLOCK_SCHEMATIC_52M_COTMS, + CONNSYS_CLOCK_SCHEMATIC_26M_EXTCXO, + + CONNSYS_CLOCK_SCHEMATIC_MAX, +}; + +/* Conninfra driver allocate EMI for FW + * (FW includes: BT, WIFI and their MCU) + * +-----------+ + * | | + * | FW | + * | | + * +-----------+ + * + * MCIF region is provided by MD + * +-----------+ + * | | + * | | + * | MCIF | + * | | + * +-----------+ + */ +enum connsys_emi_type +{ + CONNSYS_EMI_FW, + CONNSYS_EMI_MCIF, + + CONNSYS_EMI_MAX, +}; + +#define CONNINFRA_SPI_OP_FAIL 0x1 + +#define CONNINFRA_CB_RET_CAL_PASS_POWER_OFF 0x0 +#define CONNINFRA_CB_RET_CAL_PASS_POWER_ON 0x2 +#define CONNINFRA_CB_RET_CAL_FAIL_POWER_OFF 0x1 +#define CONNINFRA_CB_RET_CAL_FAIL_POWER_ON 0x3 + +#define CONNINFRA_BUS_CLOCK_WPLL 0x1 +#define CONNINFRA_BUS_CLOCK_BPLL 0x2 +#define CONNINFRA_BUS_CLOCK_ALL 0x3 + +/* bus hang error define */ +#define CONNINFRA_INFRA_BUS_HANG 0x1 +#define CONNINFRA_AP2CONN_RX_SLP_PROT_ERR 0x2 +#define CONNINFRA_AP2CONN_TX_SLP_PROT_ERR 0x4 +#define CONNINFRA_AP2CONN_CLK_ERR 0x8 +#define CONNINFRA_INFRA_BUS_HANG_IRQ 0x10 + +#define CONNINFRA_ERR_RST_ONGOING -0x7788 +#define CONNINFRA_ERR_WAKEUP_FAIL -0x5566 +/******************************************************************************* +* 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 +******************************************************************************** +*/ +/* Conninfra bus clock control */ +int conninfra_bus_clock_ctrl(enum consys_drv_type drv_type, unsigned int bus_clock, int status); +/* Clock schematic query */ +int conninfra_get_clock_schematic(void); + +/* SPI clock switch */ +int conninfra_spi_clock_switch(enum connsys_spi_speed_type type); + +/* A-die top_ck_en control */ +int conninfra_adie_top_ck_en_on(enum consys_adie_ctl_type type); +int conninfra_adie_top_ck_en_off(enum consys_adie_ctl_type type); + +/* RFSPI */ +int conninfra_spi_read(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data); +int conninfra_spi_write(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data); + +/* EMI */ +void conninfra_get_phy_addr(unsigned int *addr, unsigned int *size); +void conninfra_get_emi_phy_addr(enum connsys_emi_type type, phys_addr_t* base, unsigned int *size); + +/* power on/off */ +int conninfra_pwr_on(enum consys_drv_type drv_type); +int conninfra_pwr_off(enum consys_drv_type drv_type); + +/* To setup config relative data, ex: debug flag */ +void conninfra_config_setup(void); + +/* reg */ +/* + * 1 : can read + * 0 : can't read + */ +int conninfra_reg_readable(void); +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ +/* reg readable */ +/* THIS API SHOULD NOT USED IN NORMAL CASE */ +/* IF YOU NEED THIS, PLEASE DISCUSS WITH OWNER */ +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ +int conninfra_reg_readable_no_lock(void); +/* + * 0 : NO hang + * > 0 : HANG!! + * CONNINFRA_ERR_RST_ONGOING: whole chip reset is ongoing + */ +int conninfra_is_bus_hang(void); + +/* chip reset + * return: + * <0: error + * =0: triggered + * =1: ongoing + */ +int conninfra_trigger_whole_chip_rst(enum consys_drv_type drv, char *reason); + +/* whole chip reset callback + * return: + * =0: success + * !0: fail + */ +struct whole_chip_rst_cb { + int (*pre_whole_chip_rst)(enum consys_drv_type drv, char *reason); + int (*post_whole_chip_rst)(void); +}; + +/* driver state query */ + +/* VCN control */ + +/* Thermal */ + +/* Config */ + +/* semaphore */ + +/* calibration */ + + + +/* subsys callback register */ +struct pre_calibration_cb { + int (*pwr_on_cb)(void); + int (*do_cal_cb)(void); +}; + +struct sub_drv_ops_cb { + /* chip reset */ + struct whole_chip_rst_cb rst_cb; + + /* calibration */ + struct pre_calibration_cb pre_cal_cb; + + /* thermal query */ + int (*thermal_qry)(void); + +}; + +int conninfra_sub_drv_ops_register(enum consys_drv_type drv_type, struct sub_drv_ops_cb *cb); +int conninfra_sub_drv_ops_unregister(enum consys_drv_type drv_type); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _CONNINFRA_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/init.conninfra.rc b/drivers/misc/mediatek/connectivity/conninfra/init.conninfra.rc new file mode 100644 index 0000000000000..cca37bfcffcaf --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/init.conninfra.rc @@ -0,0 +1,2 @@ +on boot + insmod /vendor/lib/modules/conninfra.ko diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/clock_mng.c b/drivers/misc/mediatek/connectivity/conninfra/platform/clock_mng.c new file mode 100644 index 0000000000000..9c2fd55d28ad3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/clock_mng.c @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#include "osal.h" + +#include "clock_mng.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 +******************************************************************************** +*/ + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + + diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/consys_hw.c b/drivers/misc/mediatek/connectivity/conninfra/platform/consys_hw.c new file mode 100644 index 0000000000000..7e44816eba22b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/consys_hw.c @@ -0,0 +1,525 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ + +#include +#include +#include "osal.h" + +#include "consys_hw.h" +#include "emi_mng.h" +#include "pmic_mng.h" +#include "consys_reg_mng.h" +#include "connsys_debug_utility.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 +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static int mtk_conninfra_probe(struct platform_device *pdev); +static int mtk_conninfra_remove(struct platform_device *pdev); +static int mtk_conninfra_suspend(struct platform_device *pdev, pm_message_t state); +static int mtk_conninfra_resume(struct platform_device *pdev); + +static int _consys_hw_conninfra_wakeup(void); +static void _consys_hw_conninfra_sleep(void); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +#ifdef CONFIG_OF +const struct of_device_id apconninfra_of_ids[] = { + {.compatible = "mediatek,mt6885-consys",}, + {.compatible = "mediatek,mt6893-consys",}, + {} +}; +#endif + +static struct platform_driver mtk_conninfra_dev_drv = { + .probe = mtk_conninfra_probe, + .remove = mtk_conninfra_remove, + .suspend = mtk_conninfra_suspend, + .resume = mtk_conninfra_resume, + .driver = { + .name = "mtk_conninfra", + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = apconninfra_of_ids, +#endif + }, +}; + + +struct consys_hw_env conn_hw_env; + +struct consys_hw_ops_struct *consys_hw_ops; +struct platform_device *g_pdev; + +int g_conninfra_wakeup_ref_cnt; + +struct work_struct ap_resume_work; + +struct conninfra_dev_cb *g_conninfra_dev_cb; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +struct consys_hw_ops_struct* __weak get_consys_platform_ops(void) +{ + pr_err("Miss platform ops !!\n"); + return NULL; +} + + +struct platform_device *get_consys_device(void) +{ + return g_pdev; +} + +int consys_hw_get_clock_schematic(void) +{ + if (consys_hw_ops->consys_plt_co_clock_type) + return consys_hw_ops->consys_plt_co_clock_type(); + else + pr_err("consys_hw_ops->consys_co_clock_type not supported\n"); + + return -1; +} + +unsigned int consys_hw_chipid_get(void) +{ + if (consys_hw_ops->consys_plt_soc_chipid_get) + return consys_hw_ops->consys_plt_soc_chipid_get(); + else + pr_err("consys_plt_soc_chipid_get not supported\n"); + + return 0; +} + +unsigned int consys_hw_get_hw_ver(void) +{ + if (consys_hw_ops->consys_plt_get_hw_ver) + return consys_hw_ops->consys_plt_get_hw_ver(); + return 0; +} + + +int consys_hw_reg_readable(void) +{ + return consys_reg_mng_reg_readable(); +} + +int consys_hw_is_connsys_reg(phys_addr_t addr) +{ + return consys_reg_mng_is_connsys_reg(addr); +} + +int consys_hw_is_bus_hang(void) +{ + return consys_reg_mng_is_bus_hang(); +} + +int consys_hw_dump_bus_status(void) +{ + return consys_reg_mng_dump_bus_status(); +} + +int consys_hw_dump_cpupcr(enum conn_dump_cpupcr_type dump_type, int times, unsigned long interval_us) +{ + return consys_reg_mng_dump_cpupcr(dump_type, times, interval_us); +} + +int consys_hw_pwr_off(unsigned int curr_status, unsigned int off_radio) +{ + unsigned int next_status = curr_status & ~(0x1 << off_radio); + int ret = 0; + + if (next_status == 0) { + pr_info("Last pwoer off: %d\n", off_radio); + pr_info("Power off CONNSYS PART 1\n"); + if (consys_hw_ops->consys_plt_conninfra_on_power_ctrl) + consys_hw_ops->consys_plt_conninfra_on_power_ctrl(0); + pr_info("Power off CONNSYS PART 2\n"); + if (consys_hw_ops->consys_plt_set_if_pinmux) + consys_hw_ops->consys_plt_set_if_pinmux(0); + if (consys_hw_ops->consys_plt_clock_buffer_ctrl) + consys_hw_ops->consys_plt_clock_buffer_ctrl(0); + ret = pmic_mng_common_power_ctrl(0); + pr_info("Power off a-die power, ret=%d\n", ret); + } else { + pr_info("[%s] Part 0: only subsys (%d) off (curr_status=0x%x, next_status = 0x%x)\n", + __func__, off_radio, curr_status, next_status); + ret = _consys_hw_conninfra_wakeup(); + if (consys_hw_ops->consys_plt_subsys_status_update) + consys_hw_ops->consys_plt_subsys_status_update(false, off_radio); + if (consys_hw_ops->consys_plt_spi_master_cfg) + consys_hw_ops->consys_plt_spi_master_cfg(next_status); + if (consys_hw_ops->consys_plt_low_power_setting) + consys_hw_ops->consys_plt_low_power_setting(curr_status, next_status); + if (ret == 0) + _consys_hw_conninfra_sleep(); + } + + return 0; +} + +int consys_hw_pwr_on(unsigned int curr_status, unsigned int on_radio) +{ + int ret; + unsigned int next_status = (curr_status | (0x1 << on_radio)); + + /* first power on */ + if (curr_status == 0) { + /* POS PART 1: + * Set PMIC to turn on the power that AFE WBG circuit in D-die, + * OSC or crystal component, and A-die need. + */ + ret = pmic_mng_common_power_ctrl(1); + if (consys_hw_ops->consys_plt_clock_buffer_ctrl) + consys_hw_ops->consys_plt_clock_buffer_ctrl(1); + + /* POS PART 2: + * 1. Pinmux setting + * 2. Turn on MTCMOS + * 3. Enable AXI bus (AP2CONN slpprot) + */ + if (consys_hw_ops->consys_plt_set_if_pinmux) + consys_hw_ops->consys_plt_set_if_pinmux(1); + + if (consys_hw_ops->consys_plt_conninfra_on_power_ctrl) + consys_hw_ops->consys_plt_conninfra_on_power_ctrl(1); + + if (consys_hw_ops->consys_plt_polling_consys_chipid) + ret = consys_hw_ops->consys_plt_polling_consys_chipid(); + + /* POS PART 3: + * 1. Set connsys EMI mapping + * 2. d_die_cfg + * 3. spi_master_cfg + * 4. a_die_cfg + * 5. afe_wbg_cal + * 6. patch default value + * 7. CONN_INFRA low power setting (srcclken wait time, mtcmos HW ctl...) + */ + emi_mng_set_remapping_reg(); + if (consys_hw_ops->consys_plt_d_die_cfg) + consys_hw_ops->consys_plt_d_die_cfg(); + if (consys_hw_ops->consys_plt_spi_master_cfg) + consys_hw_ops->consys_plt_spi_master_cfg(next_status); + if (consys_hw_ops->consys_plt_a_die_cfg) + consys_hw_ops->consys_plt_a_die_cfg(); + if (consys_hw_ops->consys_plt_afe_wbg_cal) + consys_hw_ops->consys_plt_afe_wbg_cal(); + if (consys_hw_ops->consys_plt_subsys_pll_initial) + consys_hw_ops->consys_plt_subsys_pll_initial(); + /* Record SW status on shared sysram */ + if (consys_hw_ops->consys_plt_subsys_status_update) + consys_hw_ops->consys_plt_subsys_status_update(true, on_radio); + if (consys_hw_ops->consys_plt_low_power_setting) + consys_hw_ops->consys_plt_low_power_setting(curr_status, next_status); + } else { + ret = _consys_hw_conninfra_wakeup(); + /* Record SW status on shared sysram */ + if (consys_hw_ops->consys_plt_subsys_status_update) + consys_hw_ops->consys_plt_subsys_status_update(true, on_radio); + if (consys_hw_ops->consys_plt_spi_master_cfg) + consys_hw_ops->consys_plt_spi_master_cfg(next_status); + if (consys_hw_ops->consys_plt_low_power_setting) + consys_hw_ops->consys_plt_low_power_setting(curr_status, next_status); + + if (ret == 0) + _consys_hw_conninfra_sleep(); + } + return 0; +} + +int consys_hw_wifi_power_ctl(unsigned int enable) +{ + return pmic_mng_wifi_power_ctrl(enable); +} + +int consys_hw_bt_power_ctl(unsigned int enable) +{ + return pmic_mng_bt_power_ctrl(enable); +} + +int consys_hw_gps_power_ctl(unsigned int enable) +{ + return pmic_mng_gps_power_ctrl(enable); +} + +int consys_hw_fm_power_ctl(unsigned int enable) +{ + return pmic_mng_fm_power_ctrl(enable); +} + + +int consys_hw_therm_query(int *temp_ptr) +{ + int ret = 0; + + /* wake/sleep conninfra */ + if (consys_hw_ops && consys_hw_ops->consys_plt_thermal_query) { + ret = _consys_hw_conninfra_wakeup(); + if (ret) + return CONNINFRA_ERR_WAKEUP_FAIL; + *temp_ptr = consys_hw_ops->consys_plt_thermal_query(); + _consys_hw_conninfra_sleep(); + } else + ret = -1; + + return ret; +} + +void consys_hw_clock_fail_dump(void) +{ + if (consys_hw_ops && consys_hw_ops->consys_plt_clock_fail_dump) + consys_hw_ops->consys_plt_clock_fail_dump(); +} + + +int consys_hw_dump_power_state(void) +{ + if (consys_hw_ops && consys_hw_ops->consys_plt_power_state) + consys_hw_ops->consys_plt_power_state(); + return 0; +} + +int consys_hw_spi_read(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data) +{ + if (consys_hw_ops->consys_plt_spi_read) + return consys_hw_ops->consys_plt_spi_read(subsystem, addr, data); + return -1; +} + +int consys_hw_spi_write(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data) +{ + if (consys_hw_ops->consys_plt_spi_write) + return consys_hw_ops->consys_plt_spi_write(subsystem, addr, data); + return -1; +} + +int consys_hw_adie_top_ck_en_on(enum consys_adie_ctl_type type) +{ + if (consys_hw_ops->consys_plt_adie_top_ck_en_on) + return consys_hw_ops->consys_plt_adie_top_ck_en_on(type); + return -1; +} + +int consys_hw_adie_top_ck_en_off(enum consys_adie_ctl_type type) +{ + if (consys_hw_ops->consys_plt_adie_top_ck_en_off) + return consys_hw_ops->consys_plt_adie_top_ck_en_off(type); + return -1; +} + + +static int _consys_hw_conninfra_wakeup(void) +{ + int ref = g_conninfra_wakeup_ref_cnt; + bool wakeup = false, ret; + + if (consys_hw_ops->consys_plt_conninfra_wakeup) { + if (g_conninfra_wakeup_ref_cnt == 0) { + ret = consys_hw_ops->consys_plt_conninfra_wakeup(); + if (ret) { + pr_err("wakeup fail!! ret=[%d]", ret); + return ret; + } + wakeup = true; + } + g_conninfra_wakeup_ref_cnt++; + } + + pr_info("conninfra_wakeup refcnt=[%d]->[%d] %s", + ref, g_conninfra_wakeup_ref_cnt, (wakeup ? "wakeup!!" : "")); + return 0; +} + +static void _consys_hw_conninfra_sleep(void) +{ + int ref = g_conninfra_wakeup_ref_cnt; + bool sleep = false; + + if (consys_hw_ops->consys_plt_conninfra_sleep && + --g_conninfra_wakeup_ref_cnt == 0) { + sleep = true; + consys_hw_ops->consys_plt_conninfra_sleep(); + } + pr_info("conninfra_sleep refcnt=[%d]->[%d] %s", + ref, g_conninfra_wakeup_ref_cnt, (sleep ? "sleep!!" : "")); +} + +int consys_hw_force_conninfra_wakeup(void) +{ + return _consys_hw_conninfra_wakeup(); +} + +int consys_hw_force_conninfra_sleep(void) +{ + _consys_hw_conninfra_sleep(); + return 0; +} + +int consys_hw_spi_clock_switch(enum connsys_spi_speed_type type) +{ + if (consys_hw_ops->consys_plt_spi_clock_switch) + return consys_hw_ops->consys_plt_spi_clock_switch(type); + return -1; +} + +void consys_hw_config_setup(void) +{ + if (consys_hw_ops->consys_plt_config_setup) + consys_hw_ops->consys_plt_config_setup(); +} + +int consys_hw_pmic_event_cb(unsigned int id, unsigned int event) +{ + pmic_mng_event_cb(id, event); + return 0; +} + +int consys_hw_bus_clock_ctrl(enum consys_drv_type drv_type, unsigned int bus_clock, int status) +{ + if (consys_hw_ops->consys_plt_bus_clock_ctrl) + return consys_hw_ops->consys_plt_bus_clock_ctrl(drv_type, bus_clock, status); + else + return -1; +} + +int mtk_conninfra_probe(struct platform_device *pdev) +{ + int ret = -1; + struct consys_emi_addr_info* emi_info = NULL; + + /* Read device node */ + if (consys_reg_mng_init(pdev) != 0) { + pr_err("consys_plt_read_reg_from_dts fail"); + return -1; + } + + if (consys_hw_ops->consys_plt_clk_get_from_dts) + consys_hw_ops->consys_plt_clk_get_from_dts(pdev); + else { + pr_err("consys_plt_clk_get_from_dtsfail"); + return -2; + } + + /* emi mng init */ + ret = emi_mng_init(); + if (ret) { + pr_err("emi_mng init fail, %d\n", ret); + return -3; + } + + ret = pmic_mng_init(pdev, g_conninfra_dev_cb); + if (ret) { + pr_err("pmic_mng init fail, %d\n", ret); + return -4; + } + + /* Setup connsys log emi base */ + emi_info = emi_mng_get_phy_addr(); + if (emi_info) { + connsys_dedicated_log_path_apsoc_init((phys_addr_t)emi_info->emi_ap_phy_addr); + } else { + pr_err("Connsys log didn't init because EMI is invalid\n"); + } + + if (pdev) + g_pdev = pdev; + + return 0; +} + +int mtk_conninfra_remove(struct platform_device *pdev) +{ + if (g_pdev) + g_pdev = NULL; + + return 0; +} + +int mtk_conninfra_suspend(struct platform_device *pdev, pm_message_t state) +{ + /* suspend callback is in atomic context */ + return 0; +} + +int mtk_conninfra_resume(struct platform_device *pdev) +{ + /* suspend callback is in atomic context */ + schedule_work(&ap_resume_work); + return 0; +} + + +static void consys_hw_ap_resume_handler(struct work_struct *work) +{ + if (g_conninfra_dev_cb && g_conninfra_dev_cb->conninfra_resume_cb) + (*g_conninfra_dev_cb->conninfra_resume_cb)(); +} + + +int consys_hw_init(struct conninfra_dev_cb *dev_cb) +{ + int iRet = 0; + + if (consys_hw_ops == NULL) + consys_hw_ops = get_consys_platform_ops(); + + g_conninfra_dev_cb = dev_cb; + + iRet = platform_driver_register(&mtk_conninfra_dev_drv); + if (iRet) + pr_err("Conninfra platform driver registered failed(%d)\n", iRet); + + INIT_WORK(&ap_resume_work, consys_hw_ap_resume_handler); + pr_info("[consys_hw_init] result [%d]\n", iRet); + + return iRet; +} + +int consys_hw_deinit(void) +{ + platform_driver_unregister(&mtk_conninfra_dev_drv); + g_conninfra_dev_cb = NULL; + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/consys_reg_mng.c b/drivers/misc/mediatek/connectivity/conninfra/platform/consys_reg_mng.c new file mode 100644 index 0000000000000..a17ca4a001d64 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/consys_reg_mng.c @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#define pr_fmt(fmt) KBUILD_MODNAME "@(%s:%d) " fmt, __func__, __LINE__ + +#include "consys_reg_mng.h" +#include "consys_reg_util.h" + +struct consys_reg_mng_ops* g_consys_reg_ops = NULL; + +struct consys_reg_mng_ops* __weak get_consys_reg_mng_ops(void) +{ + pr_warn("No specify project\n"); + return NULL; +} + +int consys_reg_mng_reg_readable(void) +{ + if (g_consys_reg_ops && + g_consys_reg_ops->consys_reg_mng_check_reable) + return g_consys_reg_ops->consys_reg_mng_check_reable(); + pr_err("%s not implement", __func__); + return -1; +} + +int consys_reg_mng_is_connsys_reg(phys_addr_t addr) +{ + if (g_consys_reg_ops && + g_consys_reg_ops->consys_reg_mng_is_consys_reg) + return g_consys_reg_ops->consys_reg_mng_is_consys_reg(addr); + return -1; +} + + +int consys_reg_mng_is_bus_hang(void) +{ + if (g_consys_reg_ops && + g_consys_reg_ops->consys_reg_mng_is_bus_hang) + return g_consys_reg_ops->consys_reg_mng_is_bus_hang(); + return -1; +} + +int consys_reg_mng_dump_bus_status(void) +{ + if (g_consys_reg_ops && + g_consys_reg_ops->consys_reg_mng_dump_bus_status) + return g_consys_reg_ops->consys_reg_mng_dump_bus_status(); + return -1; +} + +int consys_reg_mng_dump_conninfra_status(void) +{ + if (g_consys_reg_ops && + g_consys_reg_ops->consys_reg_mng_dump_conninfra_status) + return g_consys_reg_ops->consys_reg_mng_dump_conninfra_status(); + return -1; +} + +int consys_reg_mng_dump_cpupcr(enum conn_dump_cpupcr_type dump_type, int times, unsigned long interval_us) +{ + if (g_consys_reg_ops && + g_consys_reg_ops->consys_reg_mng_dump_cpupcr) + return g_consys_reg_ops->consys_reg_mng_dump_cpupcr(dump_type, times, interval_us); + return -1; +} + +int consys_reg_mng_init(struct platform_device *pdev) +{ + int ret = 0; + if (g_consys_reg_ops == NULL) + g_consys_reg_ops = get_consys_reg_mng_ops(); + + if (g_consys_reg_ops && + g_consys_reg_ops->consys_reg_mng_init) + ret = g_consys_reg_ops->consys_reg_mng_init(pdev); + else + ret = EFAULT; + + return ret; +} + +int consys_reg_mng_deinit(void) +{ + if (g_consys_reg_ops&& + g_consys_reg_ops->consys_reg_mng_deinit) + g_consys_reg_ops->consys_reg_mng_deinit(); + + return 0; +} + +int consys_reg_mng_reg_read(unsigned long addr, unsigned int *value, unsigned int mask) +{ + void __iomem *vir_addr = NULL; + + vir_addr = ioremap_nocache(addr, 0x100); + if (!vir_addr) { + pr_err("ioremap fail"); + return -1; + } + + *value = (unsigned int)CONSYS_REG_READ(vir_addr) & mask; + + pr_info("[%x] mask=[%x]", *value, mask); + + iounmap(vir_addr); + return 0; +} + +int consys_reg_mng_reg_write(unsigned long addr, unsigned int value, unsigned int mask) +{ + void __iomem *vir_addr = NULL; + + vir_addr = ioremap_nocache(addr, 0x100); + if (!vir_addr) { + pr_err("ioremap fail"); + return -1; + } + + CONSYS_REG_WRITE_MASK(vir_addr, value, mask); + + iounmap(vir_addr); + return 0; +} + + +int consys_reg_mng_is_host_csr(unsigned long addr) +{ + if (g_consys_reg_ops && + g_consys_reg_ops->consys_reg_mng_is_host_csr) + return g_consys_reg_ops->consys_reg_mng_is_host_csr(addr); + return -1; +} diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/emi_mng.c b/drivers/misc/mediatek/connectivity/conninfra/platform/emi_mng.c new file mode 100644 index 0000000000000..ed953cc6de89f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/emi_mng.c @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#include +#include +#include +#include "osal.h" + +#include "emi_mng.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 +******************************************************************************** +*/ + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + + +extern unsigned long long gConEmiSize; +extern phys_addr_t gConEmiPhyBase; + +struct consys_platform_emi_ops* consys_platform_emi_ops = NULL; + +struct consys_emi_addr_info connsys_emi_addr_info = { + .emi_ap_phy_addr = 0, + .emi_size = 0, + .md_emi_phy_addr = 0, + .md_emi_size = 0, +}; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + + +int emi_mng_set_region_protection(void) +{ + if (consys_platform_emi_ops && + consys_platform_emi_ops->consys_ic_emi_mpu_set_region_protection) + return consys_platform_emi_ops->consys_ic_emi_mpu_set_region_protection(); + return -1; +} + +int emi_mng_set_remapping_reg(void) +{ + if (consys_platform_emi_ops && + consys_platform_emi_ops->consys_ic_emi_set_remapping_reg) + return consys_platform_emi_ops->consys_ic_emi_set_remapping_reg( + connsys_emi_addr_info.emi_ap_phy_addr, + connsys_emi_addr_info.md_emi_phy_addr); + return -1; +} + +struct consys_emi_addr_info* emi_mng_get_phy_addr(void) +{ + return &connsys_emi_addr_info; +} + + +struct consys_platform_emi_ops* __weak get_consys_platform_emi_ops(void) +{ + pr_warn("No specify project\n"); + return NULL; +} + +int emi_mng_init(void) +{ + if (consys_platform_emi_ops == NULL) + consys_platform_emi_ops = get_consys_platform_emi_ops(); + + pr_info("[emi_mng_init] gConEmiPhyBase = [0x%llx] size = [%llx] ops=[%p]", + gConEmiPhyBase, gConEmiSize, consys_platform_emi_ops); + + if (gConEmiPhyBase) { + connsys_emi_addr_info.emi_ap_phy_addr = gConEmiPhyBase; + connsys_emi_addr_info.emi_size = gConEmiSize; + } else { + pr_err("consys emi memory address gConEmiPhyBase invalid\n"); + } + + if (consys_platform_emi_ops && + consys_platform_emi_ops->consys_ic_emi_get_md_shared_emi) + consys_platform_emi_ops->consys_ic_emi_get_md_shared_emi( + &connsys_emi_addr_info.md_emi_phy_addr, + &connsys_emi_addr_info.md_emi_size); + + if (consys_platform_emi_ops && + consys_platform_emi_ops->consys_ic_emi_mpu_set_region_protection) + consys_platform_emi_ops->consys_ic_emi_mpu_set_region_protection(); + + return 0; +} + +int emi_mng_deinit(void) +{ + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/include/clock_mng.h b/drivers/misc/mediatek/connectivity/conninfra/platform/include/clock_mng.h new file mode 100644 index 0000000000000..ff628306c800b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/include/clock_mng.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _PLATFORM_CLOCK_MNG_H_ +#define _PLATFORM_CLOCK_MNG_H_ + +#include "osal.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 /* _PLATFORM_CLOCK_MNG_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/include/consys_hw.h b/drivers/misc/mediatek/connectivity/conninfra/platform/include/consys_hw.h new file mode 100644 index 0000000000000..bce4e91a64b66 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/include/consys_hw.h @@ -0,0 +1,244 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _PLATFORM_CONSYS_HW_H_ +#define _PLATFORM_CONSYS_HW_H_ + +#include + +#include "conninfra.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define CONN_SEMA_GET_SUCCESS 0 +#define CONN_SEMA_GET_FAIL 1 + +#define CONN_SEMA_TIMEOUT (1*1000) /* 1ms */ + +/******************************************************************************* +* 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 int(*CONSYS_PLT_CLK_GET_FROM_DTS) (struct platform_device *pdev); +typedef int(*CONSYS_PLT_READ_REG_FROM_DTS) (struct platform_device *pdev); + +typedef int(*CONSYS_PLT_CLOCK_BUFFER_CTRL) (unsigned int enable); +typedef int(*CONSYS_PLT_CONNINFRA_ON_POWER_CTRL) (unsigned int enable); +typedef void(*CONSYS_PLT_SET_IF_PINMUX) (unsigned int enable); + +typedef int(*CONSYS_PLT_POLLING_CONSYS_CHIPID) (void); +typedef int(*CONSYS_PLT_D_DIE_CFG) (void); +typedef int(*CONSYS_PLT_SPI_MASTER_CFG) (unsigned int next_status); +typedef int(*CONSYS_PLT_A_DIE_CFG) (void); +typedef int(*CONSYS_PLT_AFE_WBG_CAL) (void); +typedef int(*CONSYS_PLT_SUBSYS_PLL_INITIAL) (void); +typedef int(*CONSYS_PLT_LOW_POWER_SETTING) (unsigned int curr_status, unsigned int next_status); +typedef int(*CONSYS_PLT_CONNINFRA_WAKEUP) (void); +typedef int(*CONSYS_PLT_CONNINFRA_SLEEP) (void); + +typedef void(*CONSYS_PLT_AFE_REG_SETTING) (void); +typedef unsigned int(*CONSYS_PLT_SOC_CHIPID_GET) (void); + +typedef void(*CONSYS_PLT_FORCE_TRIGGER_ASSERT_DEBUG_PIN) (void); +typedef int(*CONSYS_PLT_CO_CLOCK_TYPE) (void); + +typedef int(*CONSYS_PLT_CHECK_REG_READABLE) (void); +typedef void(*CONSYS_PLT_CLOCK_FAIL_DUMP) (void); +typedef int(*CONSYS_PLT_IS_CONNSYS_REG) (unsigned int addr); + + +typedef int(*CONSYS_PLT_SPI_READ)(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data); +typedef int(*CONSYS_PLT_SPI_WRITE)(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data); + +typedef int(*CONSYS_PLT_ADIE_TOP_CK_EN_ON)(enum consys_adie_ctl_type type); +typedef int(*CONSYS_PLT_ADIE_TOP_CK_EN_OFF)(enum consys_adie_ctl_type type); + +typedef int(*CONSYS_PLT_SPI_CLOCK_SWITCH)(enum connsys_spi_speed_type type); + +typedef bool(*CONSYS_PLT_IS_RC_MODE_ENABLE)(void); +typedef int(*CONSYS_PLT_SUBSYS_STATUS_UPDATE)(bool on, int radio); + +typedef unsigned int(*CONSYS_PLT_GET_HW_VER)(void); +typedef int(*CONSYS_PLT_THERMAL_QUERY)(void); +typedef int(*CONSYS_PLT_POWER_STATE)(void); + +typedef void(*CONSYS_PLT_CONFIG_SETUP)(void); + +typedef int(*CONSYS_PLT_BUS_CLOCK_CTRL)(enum consys_drv_type drv_type, unsigned int, int); + +struct consys_hw_ops_struct { + /* load from dts */ + CONSYS_PLT_CLK_GET_FROM_DTS consys_plt_clk_get_from_dts; + + /* clock */ + CONSYS_PLT_CLOCK_BUFFER_CTRL consys_plt_clock_buffer_ctrl; + CONSYS_PLT_CO_CLOCK_TYPE consys_plt_co_clock_type; + + /* POS */ + CONSYS_PLT_CONNINFRA_ON_POWER_CTRL consys_plt_conninfra_on_power_ctrl; + CONSYS_PLT_SET_IF_PINMUX consys_plt_set_if_pinmux; + + CONSYS_PLT_POLLING_CONSYS_CHIPID consys_plt_polling_consys_chipid; + CONSYS_PLT_D_DIE_CFG consys_plt_d_die_cfg; + CONSYS_PLT_SPI_MASTER_CFG consys_plt_spi_master_cfg; + CONSYS_PLT_A_DIE_CFG consys_plt_a_die_cfg; + CONSYS_PLT_AFE_WBG_CAL consys_plt_afe_wbg_cal; + CONSYS_PLT_SUBSYS_PLL_INITIAL consys_plt_subsys_pll_initial; + CONSYS_PLT_LOW_POWER_SETTING consys_plt_low_power_setting; + + CONSYS_PLT_AFE_REG_SETTING consys_plt_afe_reg_setting; + + CONSYS_PLT_SOC_CHIPID_GET consys_plt_soc_chipid_get; + CONSYS_PLT_CONNINFRA_WAKEUP consys_plt_conninfra_wakeup; + CONSYS_PLT_CONNINFRA_SLEEP consys_plt_conninfra_sleep; + CONSYS_PLT_IS_RC_MODE_ENABLE consys_plt_is_rc_mode_enable; + + CONSYS_PLT_CHECK_REG_READABLE consys_plt_check_reg_readable; + /* debug */ + CONSYS_PLT_CLOCK_FAIL_DUMP consys_plt_clock_fail_dump; + CONSYS_PLT_GET_HW_VER consys_plt_get_hw_ver; + + /* For SPI operation */ + CONSYS_PLT_SPI_READ consys_plt_spi_read; + CONSYS_PLT_SPI_WRITE consys_plt_spi_write; + + /* For a-die top_ck_en control */ + CONSYS_PLT_ADIE_TOP_CK_EN_ON consys_plt_adie_top_ck_en_on; + CONSYS_PLT_ADIE_TOP_CK_EN_OFF consys_plt_adie_top_ck_en_off; + + /* For SPI clock switch */ + CONSYS_PLT_SPI_CLOCK_SWITCH consys_plt_spi_clock_switch; + CONSYS_PLT_SUBSYS_STATUS_UPDATE consys_plt_subsys_status_update; + + /* thermal */ + CONSYS_PLT_THERMAL_QUERY consys_plt_thermal_query; + + /* power state */ + CONSYS_PLT_POWER_STATE consys_plt_power_state; + + CONSYS_PLT_CONFIG_SETUP consys_plt_config_setup; + + CONSYS_PLT_BUS_CLOCK_CTRL consys_plt_bus_clock_ctrl; +}; + +struct conninfra_dev_cb { + int (*conninfra_suspend_cb) (void); + int (*conninfra_resume_cb) (void); + int (*conninfra_pmic_event_notifier) (unsigned int, unsigned int); +}; + +struct consys_hw_env { + unsigned int adie_hw_version; + int is_rc_mode; +}; + +extern struct consys_hw_env conn_hw_env; +extern struct consys_base_addr conn_reg; +/******************************************************************************* +* 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 +******************************************************************************** +*/ +int consys_hw_init(struct conninfra_dev_cb *dev_cb); +int consys_hw_deinit(void); + +int consys_hw_pwr_off(unsigned int curr_status, unsigned int off_radio); +int consys_hw_pwr_on(unsigned int curr_status, unsigned int on_radio); + +int consys_hw_wifi_power_ctl(unsigned int enable); +int consys_hw_bt_power_ctl(unsigned int enable); +int consys_hw_gps_power_ctl(unsigned int enable); +int consys_hw_fm_power_ctl(unsigned int enable); +int consys_hw_pmic_event_cb(unsigned int id, unsigned int event); + +unsigned int consys_hw_chipid_get(void); + +int consys_hw_get_clock_schematic(void); +unsigned int consys_hw_get_hw_ver(void); + +/* + * return + * 1 : can read + * 0 : can't read + * -1: not consys register + */ +int consys_hw_reg_readable(void); +int consys_hw_is_connsys_reg(phys_addr_t addr); +/* + * 0 means NO hang + * > 0 means hang!! + */ +int consys_hw_is_bus_hang(void); +int consys_hw_dump_bus_status(void); + +int consys_hw_spi_read(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data); +int consys_hw_spi_write(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data); + +int consys_hw_adie_top_ck_en_on(enum consys_adie_ctl_type type); +int consys_hw_adie_top_ck_en_off(enum consys_adie_ctl_type type); + +/* NOTE: debug only*/ +int consys_hw_force_conninfra_wakeup(void); +int consys_hw_force_conninfra_sleep(void); + +int consys_hw_spi_clock_switch(enum connsys_spi_speed_type type); + +struct platform_device *get_consys_device(void); +struct consys_base_addr *get_conn_reg_base_addr(void); + +int consys_hw_therm_query(int *temp_ptr); +void consys_hw_clock_fail_dump(void); + +int consys_hw_dump_power_state(void); +void consys_hw_config_setup(void); +int consys_hw_bus_clock_ctrl(enum consys_drv_type drv_type, unsigned int bus_clock, int status); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _PLATFORM_CONSYS_HW_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/include/consys_reg_base.h b/drivers/misc/mediatek/connectivity/conninfra/platform/include/consys_reg_base.h new file mode 100644 index 0000000000000..563fd198d0a60 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/include/consys_reg_base.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _PLATFORM_CONSYS_REG_BASE_H_ +#define _PLATFORM_CONSYS_REG_BASE_H_ + +struct consys_reg_base_addr { + unsigned long vir_addr; + unsigned long phy_addr; + unsigned long long size; +}; + +#endif /* _PLATFORM_CONSYS_REG_BASE_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/include/consys_reg_mng.h b/drivers/misc/mediatek/connectivity/conninfra/platform/include/consys_reg_mng.h new file mode 100644 index 0000000000000..81ddc27eb9e39 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/include/consys_reg_mng.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _PLATFORM_CONSYS_REG_MNG_H_ +#define _PLATFORM_CONSYS_REG_MNG_H_ + +#include + +enum conn_dump_cpupcr_type +{ + CONN_DUMP_CPUPCR_TYPE_BT = 1, + CONN_DUMP_CPUPCR_TYPE_WF = 2, + CONN_DUMP_CPUPCR_TYPE_ALL = 3, +}; + +struct consys_reg_mng_ops { + + int(*consys_reg_mng_init) (struct platform_device *pdev); + int(*consys_reg_mng_deinit) (void); + int(*consys_reg_mng_check_reable) (void); + int(*consys_reg_mng_is_consys_reg) (unsigned int addr); + + int(*consys_reg_mng_is_bus_hang) (void); + int(*consys_reg_mng_dump_bus_status) (void); + int(*consys_reg_mng_dump_conninfra_status) (void); + int(*consys_reg_mng_dump_cpupcr) (enum conn_dump_cpupcr_type, int times, unsigned long interval_us); + + int(*consys_reg_mng_is_host_csr) (unsigned long addr); +}; + +int consys_reg_mng_init(struct platform_device *pdev); +int consys_reg_mng_deinit(void); + +int consys_reg_mng_reg_readable(void); +int consys_reg_mng_is_connsys_reg(phys_addr_t addr); +int consys_reg_mng_reg_read(unsigned long addr, unsigned int *value, unsigned int mask); +int consys_reg_mng_reg_write(unsigned long addr, unsigned int value, unsigned int mask); +int consys_reg_mng_is_bus_hang(void); +int consys_reg_mng_dump_bus_status(void); +int consys_reg_mng_dump_conninfra_status(void); +int consys_reg_mng_dump_cpupcr(enum conn_dump_cpupcr_type dump_type, int times, unsigned long interval_us); + +int consys_reg_mng_is_host_csr(unsigned long addr); + +#endif /* _PLATFORM_CONSYS_REG_MNG_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/include/consys_reg_util.h b/drivers/misc/mediatek/connectivity/conninfra/platform/include/consys_reg_util.h new file mode 100644 index 0000000000000..e5d06ec4d76bf --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/include/consys_reg_util.h @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _PLATFORM_CONSYS_REG_UTIL_H_ +#define _PLATFORM_CONSYS_REG_UTIL_H_ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/* platform dependent */ +#include "plat_def.h" + +#define KBYTE (1024*sizeof(char)) + +#define GENMASK(h, l) \ + (((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h)))) + +#define GET_BIT_MASK(value, mask) ((value) & (mask)) +#define SET_BIT_MASK(pdest, value, mask) (*(pdest) = (GET_BIT_MASK(*(pdest), ~(mask)) | GET_BIT_MASK(value, mask))) +#define GET_BIT_RANGE(data, end, begin) ((data) & GENMASK(end, begin)) +#define SET_BIT_RANGE(pdest, data, end, begin) (SET_BIT_MASK(pdest, data, GENMASK(end, begin))) + +#define CONSYS_SET_BIT(REG, BITVAL) (*((volatile unsigned int *)(REG)) |= ((unsigned int)(BITVAL))) +#define CONSYS_CLR_BIT(REG, BITVAL) ((*(volatile unsigned int *)(REG)) &= ~((unsigned int)(BITVAL))) +#define CONSYS_CLR_BIT_WITH_KEY(REG, BITVAL, KEY) {\ + unsigned int val = (*(volatile unsigned int *)(REG)); \ + val &= ~((unsigned int)(BITVAL)); \ + val |= ((unsigned int)(KEY)); \ + (*(volatile unsigned int *)(REG)) = val;\ +} +#define CONSYS_REG_READ(addr) (*((volatile unsigned int *)(addr))) +#define CONSYS_REG_READ_BIT(addr, BITVAL) (*((volatile unsigned int *)(addr)) & ((unsigned int)(BITVAL))) +#define CONSYS_REG_WRITE(addr, data) mt_reg_sync_writel(data, addr) +#define CONSYS_REG_WRITE_RANGE(reg, data, end, begin) {\ + unsigned int val = CONSYS_REG_READ(reg); \ + SET_BIT_RANGE(&val, data, end, begin); \ + CONSYS_REG_WRITE(reg, val); \ +} +#define CONSYS_REG_WRITE_MASK(reg, data, mask) {\ + unsigned int val = CONSYS_REG_READ(reg); \ + SET_BIT_MASK(&val, data, mask); \ + CONSYS_REG_WRITE(reg, val); \ +} + +/* + * Write value with value_offset bits of right shift and size bits, + * to the reg_offset-th bit of address reg + * value -----------XXXXXXXXXXXX------------------- + * |<--size-->|<--value_offset-->| + * reg -------------OOOOOOOOOOOO----------------- + * |<--size-->|<--reg_offset-->| + * result -------------XXXXXXXXXXXX----------------- + */ +#define CONSYS_REG_WRITE_OFFSET_RANGE(reg, value, reg_offset, value_offset, size) ({\ + unsigned int data = (value) >> (value_offset); \ + data = GET_BIT_RANGE(data, size, 0); \ + data = data << (reg_offset); \ + CONSYS_REG_WRITE_RANGE(reg, data, ((reg_offset) + ((size) - 1)), reg_offset); \ +}) + +#define CONSYS_REG_WRITE_BIT(reg, offset, val) CONSYS_REG_WRITE_OFFSET_RANGE(reg, ((val) & 1), offset, 0, 1) + +#define CONSYS_REG_BIT_POLLING(addr, bit_index, exp_val, loop, delay, success) {\ + unsigned int polling_count = 0; \ + unsigned int reg_value = 0; \ + success = 0; \ + reg_value = (CONSYS_REG_READ_BIT(addr, (0x1 << bit_index)) >> bit_index); \ + while (reg_value != exp_val) { \ + if (polling_count > loop) { \ + success = -1; \ + break; \ + } \ + reg_value = (CONSYS_REG_READ_BIT(addr, (0x1 << bit_index)) >> bit_index); \ + udelay(delay); \ + polling_count++; \ + } \ +} + +/******************************************************************************* +* 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 /* _PLATFORM_CONSYS_REG_UTIL_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/include/emi_mng.h b/drivers/misc/mediatek/connectivity/conninfra/platform/include/emi_mng.h new file mode 100644 index 0000000000000..b017993877a92 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/include/emi_mng.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _PLATFORM_EMI_MNG_H_ +#define _PLATFORM_EMI_MNG_H_ + +#include +#include "osal.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 +******************************************************************************** +*/ + +struct consys_emi_addr_info { + /* This include BT/WF FW and WFDMA */ + phys_addr_t emi_ap_phy_addr; + unsigned int emi_size; + /* MCIF EMI get from MD */ + phys_addr_t md_emi_phy_addr; + unsigned int md_emi_size; +}; + +typedef int(*CONSYS_IC_EMI_MPU_SET_REGION_PROTECTION) (void); +typedef unsigned int(*CONSYS_IC_EMI_SET_REMAPPING_REG) (phys_addr_t, phys_addr_t); +typedef void(*CONSYS_IC_EMI_GET_MD_SHARED_EMI) (phys_addr_t* phy_addr, unsigned int *size); + +struct consys_platform_emi_ops { + CONSYS_IC_EMI_MPU_SET_REGION_PROTECTION consys_ic_emi_mpu_set_region_protection; + CONSYS_IC_EMI_SET_REMAPPING_REG consys_ic_emi_set_remapping_reg; + CONSYS_IC_EMI_GET_MD_SHARED_EMI consys_ic_emi_get_md_shared_emi; +}; + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + +int emi_mng_init(void); +int emi_mng_deinit(void); + +int emi_mng_set_region_protection(void); +int emi_mng_set_remapping_reg(void); +struct consys_emi_addr_info* emi_mng_get_phy_addr(void); + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _PLATFORM_EMI_MNG_H_ */ + diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/include/plat_def.h b/drivers/misc/mediatek/connectivity/conninfra/platform/include/plat_def.h new file mode 100644 index 0000000000000..0d3903bd99df9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/include/plat_def.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _PLATFORM_DEF_H_ +#define _PLATFORM_DEF_H_ + +#include +#include + +#endif /* _PLATFORM_DEF_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/include/pmic_mng.h b/drivers/misc/mediatek/connectivity/conninfra/platform/include/pmic_mng.h new file mode 100644 index 0000000000000..75d68ca59409e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/include/pmic_mng.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _PLATFORM_PMIC_MNG_H_ +#define _PLATFORM_PMIC_MNG_H_ + +#include + +#include "consys_hw.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 int(*CONSYS_PMIC_GET_FROM_DTS) ( + struct platform_device *pdev, + struct conninfra_dev_cb* dev_cb); + +typedef int(*CONSYS_PMIC_COMMON_POWER_CTRL) (unsigned int enable); + +typedef int(*CONSYS_PMIC_WIFI_POWER_CTRL) (unsigned int enable); +typedef int(*CONSYS_PMIC_BT_POWER_CTRL) (unsigned int enable); +typedef int(*CONSYS_PMIC_GPS_POWER_CTRL) (unsigned int enable); +typedef int(*CONSYS_PMIC_FM_POWER_CTRL) (unsigned int enable); +typedef int(*CONSYS_PMIC_EVENT_NOTIFIER) (unsigned int id, unsigned int event); + +typedef struct _CONSYS_PLATFORM_PMIC_OPS_ { + CONSYS_PMIC_GET_FROM_DTS consys_pmic_get_from_dts; + /* vcn 18 */ + CONSYS_PMIC_COMMON_POWER_CTRL consys_pmic_common_power_ctrl; + CONSYS_PMIC_WIFI_POWER_CTRL consys_pmic_wifi_power_ctrl; + CONSYS_PMIC_BT_POWER_CTRL consys_pmic_bt_power_ctrl; + CONSYS_PMIC_GPS_POWER_CTRL consys_pmic_gps_power_ctrl; + CONSYS_PMIC_FM_POWER_CTRL consys_pmic_fm_power_ctrl; + CONSYS_PMIC_EVENT_NOTIFIER consys_pmic_event_notifier; +} CONSYS_PLATFORM_PMIC_OPS, *P_CONSYS_PLATFORM_PMIC_OPS; + + + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + +int pmic_mng_init(struct platform_device *pdev, struct conninfra_dev_cb* dev_cb); +int pmic_mng_deinit(void); + +int pmic_mng_common_power_ctrl(unsigned int enable); +int pmic_mng_wifi_power_ctrl(unsigned int enable); +int pmic_mng_bt_power_ctrl(unsigned int enable); +int pmic_mng_gps_power_ctrl(unsigned int enable); +int pmic_mng_fm_power_ctrl(unsigned int enable); +int pmic_mng_event_cb(unsigned int id, unsigned int event); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _PLATFORM_PMIC_MNG_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/include/mt6885.h b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/include/mt6885.h new file mode 100644 index 0000000000000..6b067003c09e6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/include/mt6885.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _PLATFORM_MT6885_H_ +#define _PLATFORM_MT6885_H_ + +enum conn_semaphore_type +{ + CONN_SEMA_CHIP_POWER_ON_INDEX = 0, + CONN_SEMA_CALIBRATION_INDEX = 1, + CONN_SEMA_FW_DL_INDEX = 2, + CONN_SEMA_CLOCK_SWITCH_INDEX = 3, + CONN_SEMA_CCIF_INDEX = 4, + CONN_SEMA_COEX_INDEX = 5, + CONN_SEMA_USB_EP0_INDEX = 6, + CONN_SEMA_USB_SHARED_INFO_INDEX = 7, + CONN_SEMA_USB_SUSPEND_INDEX = 8, + CONN_SEMA_USB_RESUME_INDEX = 9, + CONN_SEMA_PCIE_INDEX = 10, + CONN_SEMA_RFSPI_INDEX = 11, + CONN_SEMA_EFUSE_INDEX = 12, + CONN_SEMA_THERMAL_INDEX = 13, + CONN_SEMA_FLASH_INDEX = 14, + CONN_SEMA_DEBUG_INDEX = 15, + CONN_SEMA_WIFI_LP_INDEX = 16, + CONN_SEMA_PATCH_DL_INDEX = 17, + CONN_SEMA_SHARED_VAR_INDEX = 18, + CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX = 19, + CONN_SEMA_NUM_MAX = 32 /* can't be omitted */ +}; + +int consys_platform_spm_conn_ctrl(unsigned int enable); +int consys_co_clock_type(void); + +struct consys_plat_thermal_data { + int thermal_b; + int slop_molecule; + int offset; +}; + +void update_thermal_data(struct consys_plat_thermal_data* input); +#endif /* _PLATFORM_MT6885_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/include/mt6885_consys_reg.h b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/include/mt6885_consys_reg.h new file mode 100644 index 0000000000000..70fc7cddd91fc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/include/mt6885_consys_reg.h @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _PLATFORM_MT6885_CONSYS_REG_H_ +#define _PLATFORM_MT6885_CONSYS_REG_H_ + +#include "consys_reg_base.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 +******************************************************************************** +*/ + +enum consys_base_addr_index { + CONN_INFRA_RGU_BASE_INDEX = 0, + CONN_INFRA_CFG_BASE_INDEX = 1, + CONN_HOST_CSR_TOP_BASE_INDEX = 2, + INFRACFG_AO_BASE_INDEX = 3, + TOPRGU_BASE_INDEX= 4, + SPM_BASE_INDEX = 5, + INFRACFG_BASE_INDEX = 6, + CONN_WT_SLP_CTL_REG_INDEX = 7, + CONN_AFE_CTL_INDEX = 8, + CONN_INFRA_SYSRAM_INDEX = 9, + GPIO_INDEX = 10, + CONN_RF_SPI_MST_REG_INDEX = 11, + CONN_SEMAPHORE_INDEX = 12, + CONN_TOP_THERM_CTL_INDEX = 13, + IOCFG_RT_INDEX = 14, /* Base: 0x11EA_0000 */ + CONN_DEBUG_CTRL = 15, /* Base: 0x1800_f000 */ + + CONSYS_BASE_ADDR_MAX +}; + + +struct consys_base_addr { + struct consys_reg_base_addr reg_base_addr[CONSYS_BASE_ADDR_MAX]; +}; + +extern struct consys_base_addr conn_reg; + +#define CON_REG_INFRA_RGU_ADDR conn_reg.reg_base_addr[CONN_INFRA_RGU_BASE_INDEX].vir_addr +#define CON_REG_INFRA_CFG_ADDR conn_reg.reg_base_addr[CONN_INFRA_CFG_BASE_INDEX].vir_addr +#define CON_REG_HOST_CSR_ADDR conn_reg.reg_base_addr[CONN_HOST_CSR_TOP_BASE_INDEX].vir_addr +#define CON_REG_INFRACFG_AO_ADDR conn_reg.reg_base_addr[INFRACFG_AO_BASE_INDEX].vir_addr + +#define CON_REG_TOP_RGU_ADDR conn_reg.reg_base_addr[TOPRGU_BASE_INDEX].vir_addr +#define CON_REG_SPM_BASE_ADDR conn_reg.reg_base_addr[SPM_BASE_INDEX].vir_addr +#define CON_REG_INFRACFG_BASE_ADDR conn_reg.reg_base_addr[INFRACFG_BASE_INDEX].vir_addr +#define CON_REG_WT_SPL_CTL_ADDR conn_reg.reg_base_addr[CONN_WT_SLP_CTL_REG_INDEX].vir_addr + +#define CONN_AFE_CTL_BASE_ADDR conn_reg.reg_base_addr[CONN_AFE_CTL_INDEX].vir_addr +#define CONN_INFRA_SYSRAM_BASE_ADDR conn_reg.reg_base_addr[CONN_INFRA_SYSRAM_INDEX].vir_addr +#define GPIO_BASE_ADDR conn_reg.reg_base_addr[GPIO_INDEX].vir_addr +#define CONN_REG_RFSPI_ADDR conn_reg.reg_base_addr[CONN_RF_SPI_MST_REG_INDEX].vir_addr + +#define CONN_REG_SEMAPHORE_ADDR conn_reg.reg_base_addr[CONN_SEMAPHORE_INDEX].vir_addr +#define CONN_TOP_THERM_CTL_ADDR conn_reg.reg_base_addr[CONN_TOP_THERM_CTL_INDEX].vir_addr +#define IOCFG_RT_ADDR conn_reg.reg_base_addr[IOCFG_RT_INDEX].vir_addr +#define CONN_DEBUG_CTRL_ADDR conn_reg.reg_base_addr[CONN_DEBUG_CTRL].vir_addr + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + +struct consys_base_addr* get_conn_reg_base_addr(void); + +#endif /* _PLATFORM_MT6885_CONSYS_REG_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/include/mt6885_consys_reg_offset.h b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/include/mt6885_consys_reg_offset.h new file mode 100644 index 0000000000000..50aa690570298 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/include/mt6885_consys_reg_offset.h @@ -0,0 +1,318 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _PLATFORM_MT6885_CONSYS_REG_OFFSET_H_ +#define _PLATFORM_MT6885_CONSYS_REG_OFFSET_H_ + + +/**********************************************************************/ +/* Base: infracfg_ao (0x1000_1000) */ +/**********************************************************************/ +#define INFRA_TOPAXI_PROTECTEN_STA1_OFFSET 0x0228 +#define INFRA_TOPAXI_PROTECTEN_SET_OFFSET 0x02a0 +#define INFRA_TOPAXI_PROTECTEN_CLR_OFFSET 0x02a4 +#define INFRA_TOPAXI_PROTECTEN2_CLR_OFFSET 0x0718 +#define INFRA_TOPAXI_PROTECTEN2_SET_OFFSET 0x0714 +#define INFRA_TOPAXI_PROTECTEN2_STA1_OFFSET 0x0724 + +/**********************************************************************/ +/* Base: GPIO (0x1000_5000) */ +/**********************************************************************/ +#define GPIO_DIR5_SET 0x0054 + +#define GPIO_DOUT5_SET 0x0154 + +#define GPIO_MODE19 0x0430 +#define GPIO_MODE21 0x0450 +#define GPIO_MODE22 0x0460 + +/**********************************************************************/ +/* Base: SPM (0x1000_6000) */ +/**********************************************************************/ +#define SPM_POWERON_CONFIG_EN 0x0000 +#define SPM_PCM_REG13_DATA 0x0110 +#define SPM_PCM_REG7_DATA 0x0100 +#define SPM_SRC_REQ_STA_0 0x0114 +#define SPM_BUS_PROTECT_RDY 0x0150 +#define SPM_BUS_PROTECT2_RDY 0x0158 +#define SPM_PWR_STATUS 0x016c +#define SPM_PWR_STATUS_2ND 0x0170 +#define SPM_CONN_PWR_CON 0x0304 +#define SPM_PLL_CON 0x044C +#define SPM_RC_CENTRAL_CFG1 0x0504 +#define SPM_PCM_WDT_LATCH_SPARE_0 0x084C + +#define SPM_RC_RC_M04_REQ_STA_0 0xE28 +#define SPM_RC_RC_M05_REQ_STA_0 0xE2C +#define SPM_RC_RC_M06_REQ_STA_0 0xE30 +#define SPM_RC_RC_M07_REQ_STA_0 0xE34 + +/**********************************************************************/ +/* Base: TOP RGU (0x1000_7000) */ +/**********************************************************************/ +#define TOP_RGU_WDT_SWSYSRST 0x0018 + + +/**********************************************************************/ +/* Base: INFRACFG (0x1020_e000) */ +/**********************************************************************/ +#define INFRA_AP2MD_GALS_CTL 0x0504 +#define INFRA_CONN2AP_GLAS_RC_ST 0x0804 + +/**********************************************************************/ +/* Base: IOCFG_RT (0x11EA_0000) */ +/**********************************************************************/ +#define IOCFG_RT_DRV_CFG0 0x0000 +#define IOCFG_RT_PD_CFG0_SET 0x0054 +#define IOCFG_RT_PD_CFG0_CLR 0x0058 +#define IOCFG_RT_PU_CFG0_SET 0x0074 +#define IOCFG_RT_PU_CFG0_CLR 0x0078 + +/**********************************************************************/ +/* Base: conn_infra_rgu (0x1800_0000) */ +/**********************************************************************/ +#define CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_CTL 0x0008 +#define CONN_INFRA_RGU_SYSRAM_HWCTL_PDN 0x0038 +#define CONN_INFRA_RGU_SYSRAM_HWCTL_SLP 0x003c +#define CONN_INFRA_RGU_CO_EXT_MEM_HWCTL_PDN 0x0050 +#define CONN_INFRA_RGU_CO_EXT_MEM_HWCTL_SLP 0x0054 +#define CONN_INFRA_RGU_DEBUG_SEL 0x0090 + +/**********************************************************************/ +/* Base: conn_infra_cfg (0x1800_1000) */ +/**********************************************************************/ +#define CONN_HW_VER_OFFSET 0x0000 +#define CONN_CFG_ID_OFFSET 0x0004 +#define CONN_INFRA_CFG_LIGHT_SECURITY_CTRL 0x00f0 + +#define CONN_INFRA_CFG_GALS_AP2CONN_GALS_DBG 0x0160 +#define CONN_INFRA_CFG_GALS_CONN2AP_TX_SLP_CTRL 0x0630 +#define CONN_INFRA_CFG_GALS_CONN2AP_RX_SLP_CTRL 0x0634 +#define CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL 0x061C +#define CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL 0x0618 +#define CONN_INFRA_CFG_GALS_BT2CONN_SLP_CTRL 0x0614 +#define CONN_INFRA_CFG_GALS_CONN2BT_SLP_CTRL 0x0610 + +#define CONN_INFRA_CFG_WF_SLP_CTRL 0x0620 +#define CONN_INFRA_CFG_ON_BUS_SLP_CTRL 0x0628 +#define CONN_INFRA_CFG_OFF_BUS_SLP_CTRL 0x062C + + +#define CONN_INFRA_CFG_OSC_CTL_0 0x0800 +#define CONN_INFRA_CFG_OSC_CTL_1 0x0804 +#define CONN_INFRA_CFG_OSC_STATUS 0x080C +#define CONN_INFRA_CFG_PLL_STATUS 0x0810 + +#define AP2CONN_EFUSE_DATA 0x0818 +#define CONN_INFRA_CFG_RC_CTL_0 0x0834 +#define CONN_INFRA_CFG_RC_CTL_0_GPS 0x0838 +#define CONN_INFRA_CFG_RC_CTL_1_GPS 0x083C +#define CONN_INFRA_CFG_RC_CTL_0_BT 0x0840 +#define CONN_INFRA_CFG_RC_CTL_1_BT 0x0844 +#define CONN_INFRA_CFG_RC_CTL_0_WF 0x0848 +#define CONN_INFRA_CFG_RC_CTL_1_WF 0x084c +#define CONN_INFRA_CFG_RC_CTL_1_TOP 0x0854 +#define CONN_INFRA_CFG_RC_CTL_0_TOP 0x0850 +#define CONN_INFRA_CFG_PWRCTRL0 0x0860 +#define CONN_INFRA_CFG_ADIE_CTL 0x0900 +#define CONN_INFRA_CFG_CKGEN_BUS 0x0a00 +#define CONN_INFRA_CFG_DBG_MUX_SEL 0x0b00 +#define CONN_INFRA_CFG_EMI_CTL_0 0x0c00 + +#define CONN_HW_VER 0x20010000 +#define CONN_CFG_ID 0x3 + +/**********************************************************************/ +/* Base: conn_top_therm_ctl (0x1800_2000) */ +/**********************************************************************/ +#define CONN_TOP_THERM_CTL_THERMCR1 0x0004 +#define CONN_TOP_THERM_CTL_THERM_AADDR 0x0018 +#define CONN_TOP_THERM_CTL_THERM_CAL_EN 0x0024 + +/**********************************************************************/ +/* Base: conn_afe_ctl(0x1800_3000) */ +/**********************************************************************/ +#define CONN_AFE_CTL_RG_DIG_EN_01 0x0000 +#define CONN_AFE_CTL_RG_DIG_EN_02 0x0004 +#define CONN_AFE_CTL_RG_DIG_EN_03 0x0008 +#define CONN_AFE_CTL_RG_WBG_AFE_01 0x0010 +#define CONN_AFE_CTL_RG_WBG_RCK_01 0x0018 +#define CONN_AFE_CTL_RG_WBG_GL1_01 0x0040 +#define CONN_AFE_CTL_RG_WBG_BT_TX_03 0x0058 +#define CONN_AFE_CTL_RG_WBG_WF0_TX_03 0x0078 +#define CONN_AFE_CTL_RG_WBG_WF1_TX_03 0x0094 +#define CONN_AFE_CTL_RG_PLL_STB_TIME 0x00f4 +#define CONN_AFE_CTL_RG_WBG_GL5_01 0x0100 + + +/**********************************************************************/ +/* Base: conn_rf_spi_mst_reg(0x1800_4000) */ +/**********************************************************************/ +#define CONN_RF_SPI_MST_REG_SPI_STA 0x0000 +#define CONN_RF_SPI_MST_REG_SPI_CRTL 0x0004 +#define CONN_RF_SPI_MST_REG_FM_CTRL 0x000c +#define CONN_RF_SPI_MST_REG_SPI_WF_ADDR 0x0010 +#define CONN_RF_SPI_MST_REG_SPI_WF_WDAT 0x0014 +#define CONN_RF_SPI_MST_REG_SPI_WF_RDAT 0x0018 +#define CONN_RF_SPI_MST_REG_SPI_BT_ADDR 0x0020 +#define CONN_RF_SPI_MST_REG_SPI_BT_WDAT 0x0024 +#define CONN_RF_SPI_MST_REG_SPI_BT_RDAT 0x0028 +#define CONN_RF_SPI_MST_REG_SPI_FM_ADDR 0x0030 +#define CONN_RF_SPI_MST_REG_SPI_FM_WDAT 0x0034 +#define CONN_RF_SPI_MST_REG_SPI_FM_RDAT 0x0038 +#define CONN_RF_SPI_MST_REG_SPI_TOP_ADDR 0x0050 +#define CONN_RF_SPI_MST_REG_SPI_TOP_WDAT 0x0054 +#define CONN_RF_SPI_MST_REG_SPI_TOP_RDAT 0x0058 +#define CONN_RF_SPI_MST_REG_SPI_GPS_GPS_ADDR 0x0210 +#define CONN_RF_SPI_MST_REG_SPI_GPS_GPS_WDAT 0x0214 +#define CONN_RF_SPI_MST_REG_SPI_GPS_GPS_RDAT 0x0218 + + +/**********************************************************************/ +/* Base: conn_wt_slp_ctl_reg(0x1800_5000) */ +/**********************************************************************/ +#define CONN_WTSLP_CTL_REG_WB_STA 0x0008 +#define CONN_WT_SLP_CTL_REG_WB_SLP_CTL 0x0004 +#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR1 0x0010 +#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR2 0x0014 +#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR3 0x0018 +#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR4 0x001c +#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR5 0x0020 +#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR6 0x0024 +#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR7 0x0028 +#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR8 0x002c +#define CONN_WT_SLP_CTL_REG_WB_BG_ON1 0x0030 +#define CONN_WT_SLP_CTL_REG_WB_BG_ON2 0x0034 +#define CONN_WT_SLP_CTL_REG_WB_BG_ON3 0x0038 +#define CONN_WT_SLP_CTL_REG_WB_BG_ON4 0x003c +#define CONN_WT_SLP_CTL_REG_WB_BG_ON5 0x0040 +#define CONN_WT_SLP_CTL_REG_WB_BG_ON6 0x0044 +#define CONN_WT_SLP_CTL_REG_WB_BG_ON7 0x0048 +#define CONN_WT_SLP_CTL_REG_WB_BG_ON8 0x004c +#define CONN_WT_SLP_CTL_REG_WB_BG_OFF1 0x0050 +#define CONN_WT_SLP_CTL_REG_WB_BG_OFF2 0x0054 +#define CONN_WT_SLP_CTL_REG_WB_BG_OFF3 0x0058 +#define CONN_WT_SLP_CTL_REG_WB_BG_OFF4 0x005c +#define CONN_WT_SLP_CTL_REG_WB_BG_OFF5 0x0060 +#define CONN_WT_SLP_CTL_REG_WB_BG_OFF6 0x0064 +#define CONN_WT_SLP_CTL_REG_WB_BG_OFF7 0x0068 +#define CONN_WT_SLP_CTL_REG_WB_BG_OFF8 0x006c +#define CONN_WT_SLP_CTL_REG_WB_WF_CK_ADDR 0x0070 +#define CONN_WT_SLP_CTL_REG_WB_WF_WAKE_ADDR 0x0074 +#define CONN_WT_SLP_CTL_REG_WB_WF_ZPS_ADDR 0x0078 +#define CONN_WT_SLP_CTL_REG_WB_BT_CK_ADDR 0x007c +#define CONN_WT_SLP_CTL_REG_WB_BT_WAKE_ADDR 0x0080 +#define CONN_WT_SLP_CTL_REG_WB_TOP_CK_ADDR 0x0084 +#define CONN_WT_SLP_CTL_REG_WB_GPS_CK_ADDR 0x0088 +#define CONN_WT_SLP_CTL_REG_WB_WF_B0_CMD_ADDR 0x008c +#define CONN_WT_SLP_CTL_REG_WB_WF_B1_CMD_ADDR 0x0090 +#define CONN_WT_SLP_CTL_REG_WB_GPS_RFBUF_ADDR 0x0094 +#define CONN_WT_SLP_CTL_REG_WB_GPS_L5_EN_ADDR 0x0098 + +/**********************************************************************/ +/* Base: GPT2 timer (0x1800_7000) */ +/**********************************************************************/ +#define CONN_GPT2_CTRL_BASE 0x18007000 +#define CONN_GPT2_CTRL_THERMAL_EN 0x38 + +/**********************************************************************/ +/* Base: debug_ctrl (0x1800_f000) */ +/**********************************************************************/ +#define CONN_DEBUG_CTRL_REG_OFFSET 0x0000 + + +/**********************************************************************/ +/* Base: conn_infra_sysram(0x1805_0000) */ +/**********************************************************************/ +#define CONN_INFRA_SYSRAM_SW_CR_A_DIE_CHIP_ID 0x2800 +#define CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_0 0x2804 +#define CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_1 0x2808 +#define CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_2 0x280C +#define CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_3 0x2810 + +#define CONN_INFRA_SYSRAM_SW_CR_D_DIE_EFUSE 0x2820 + +#define CONN_INFRA_SYSRAM_SW_CR_A_DIE_TOP_CK_EN_CTRL 0x2830 +#define CONN_INFRA_SYSRAM_SW_CR_RADIO_STATUS 0x2834 +#define CONN_INFRA_SYSRAM_SW_CR_BUILD_MODE 0x2838 + +#define CONN_INFRA_SYSRAM_SIZE (16 * 1024) + +/**********************************************************************/ +/* Base: conn_host_csr_top (0x1806_0000) */ +/**********************************************************************/ +#define CONN_HOST_CSR_TOP_CSR_DEADFEED_EN_CR 0x0124 +#define CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_AO_DEBUGSYS 0x0128 +#define CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT 0x0148 +#define CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL 0x0184 +#define CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP 0x01a0 +/* remap */ +#define CONN2AP_REMAP_MCU_EMI_BASE_ADDR_OFFSET 0x01c4 +#define CONN2AP_REMAP_MD_SHARE_EMI_BASE_ADDR_OFFSET 0x01cc +#define CONN2AP_REMAP_GPS_EMI_BASE_ADDR_OFFSET 0x01d0 +#define CONN2AP_REMAP_WF_PERI_BASE_ADDR_OFFSET 0x01d4 +#define CONN2AP_REMAP_BT_PERI_BASE_ADDR_OFFSET 0x01d8 +#define CONN2AP_REMAP_GPS_PERI_BASE_ADDR_OFFSET 0x01dc + +#define CONN_HOST_CSR_WM_MCU_PC_DBG 0x0204 +#define CONN_HOST_CSR_WM_MCU_GPR_DBG 0x0208 +#define CONN_HOST_CSR_BGF_MCU_PC_DBG 0x022C + +#define CONN_HOST_CSR_DBG_DUMMY_0 0x02C0 +#define CONN_HOST_CSR_DBG_DUMMY_2 0x02C8 +#define CONN_HOST_CSR_DBG_DUMMY_3 0x02CC +#define CONN_HOST_CSR_DBG_DUMMY_4 0x02D0 +#define CONN_HOST_CSR_TOP_BUS_TIMEOUT_IRQ 0x02d4 + +#define TOP_BUS_MUC_STAT_HCLK_FR_CK_DETECT_BIT (0x1 << 1) +#define TOP_BUS_MUC_STAT_OSC_CLK_DETECT_BIT (0x1 << 2) +#define TOP_SLP_PROT_CTRL_CONN_INFRA_ON2OFF_SLP_PROT_ACK_BIT (0x1 << 5) + +/**********************************************************************/ +/* Base: conn_semaphore(0x1807_0000) */ +/**********************************************************************/ +#define CONN_SEMA_OWN_BY_M0_STA_REP 0x0400 +#define CONN_SEMA_OWN_BY_M1_STA_REP 0x1400 +#define CONN_SEMAPHORE_M2_OWN_STA 0x2000 +#define CONN_SEMAPHORE_M2_OWN_REL 0x2200 +#define CONN_SEMA_OWN_BY_M2_STA_REP 0x2400 +#define CONN_SEMA_OWN_BY_M3_STA_REP 0x3400 + +/**********************************************************************/ +/* A-die CR */ +/**********************************************************************/ +#define ATOP_CHIP_ID 0x02c +#define ATOP_RG_TOP_THADC_BG 0x034 +#define ATOP_RG_TOP_THADC 0x038 +#define ATOP_WRI_CTR2 0x064 +#define ATOP_RG_ENCAL_WBTAC_IF_SW 0x070 +#define ATOP_SMCTK11 0x0BC +#define ATOP_EFUSE_CTRL 0x108 +#define ATOP_EFUSE_RDATA0 0x130 +#define ATOP_EFUSE_RDATA1 0x134 +#define ATOP_EFUSE_RDATA2 0x138 +#define ATOP_EFUSE_RDATA3 0x13c +#define ATOP_RG_WF0_TOP_01 0x380 +#define ATOP_RG_WF0_BG 0x384 +#define ATOP_RG_WF1_BG 0x394 +#define ATOP_RG_WF1_TOP_01 0x390 +#define ATOP_RG_TOP_XTAL_01 0xA18 +#define ATOP_RG_TOP_XTAL_02 0xA1C + + +#endif /* _PLATFORM_MT6885_CONSSY_REG_OFFSET_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/include/mt6885_emi.h b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/include/mt6885_emi.h new file mode 100644 index 0000000000000..f941a155a9c1f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/include/mt6885_emi.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _PLATFORM_MT6885_EMI_H_ +#define _PLATFORM_MT6885_EMI_H_ + +#include "osal.h" +#include "emi_mng.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 +******************************************************************************** +*/ + +struct consys_platform_emi_ops* get_consys_platform_emi_ops(void); + +struct consys_emi_addr_info* consys_emi_get_phy_addr(void); +int consys_emi_mpu_set_region_protection(void); +void consys_emi_get_md_shared_emi(phys_addr_t*, unsigned int*); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _PLATFORM_MT6885_EMI_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/include/mt6885_pmic.h b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/include/mt6885_pmic.h new file mode 100644 index 0000000000000..313fdeb4de6b3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/include/mt6885_pmic.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _PLATFORM_MT6885_PMIC_H_ +#define _PLATFORM_MT6885_PMIC_H_ + +#include "osal.h" +#include "pmic_mng.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 +******************************************************************************** +*/ + +P_CONSYS_PLATFORM_PMIC_OPS get_consys_platform_pmic_ops(void); +int consys_plt_pmic_ctrl_dump(const char* tag); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _PLATFORM_MT6885_PMIC_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/include/mt6885_pos.h b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/include/mt6885_pos.h new file mode 100644 index 0000000000000..8c1255a5bfb69 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/include/mt6885_pos.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _PLATFORM_MT6885_POS_H_ +#define _PLATFORM_MT6885_POS_H_ + + +unsigned int consys_emi_set_remapping_reg(phys_addr_t, phys_addr_t); + +int consys_conninfra_on_power_ctrl(unsigned int enable); +int consys_conninfra_wakeup(void); +int consys_conninfra_sleep(void); +void consys_set_if_pinmux(unsigned int enable); +int consys_polling_chipid(void); + +int connsys_d_die_cfg(void); +int connsys_spi_master_cfg(unsigned int); +int connsys_a_die_cfg(void); +int connsys_afe_wbg_cal(void); +int connsys_subsys_pll_initial(void); +int connsys_low_power_setting(unsigned int, unsigned int); + +int consys_sema_acquire_timeout(unsigned int index, unsigned int usec); +void consys_sema_release(unsigned int index); + +int consys_spi_read(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data); +int consys_spi_write(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data); +int consys_spi_write_offset_range( + enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int value, + unsigned int reg_offset, unsigned int value_offset, unsigned int size); + +int consys_adie_top_ck_en_on(enum consys_adie_ctl_type type); +int consys_adie_top_ck_en_off(enum consys_adie_ctl_type type); + +int consys_spi_clock_switch(enum connsys_spi_speed_type type); +int consys_subsys_status_update(bool, int); +bool consys_is_rc_mode_enable(void); + +void consys_config_setup(void); + +#endif /* _PLATFORM_MT6885_POS_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/mt6885.c b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/mt6885.c new file mode 100644 index 0000000000000..eeb5034d6afa5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/mt6885.c @@ -0,0 +1,435 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#define pr_fmt(fmt) KBUILD_MODNAME "@(%s:%d) " fmt, __func__, __LINE__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "osal.h" +#include "conninfra.h" +#include "conninfra_conf.h" +#include "consys_hw.h" +#include "consys_reg_mng.h" +#include "consys_reg_util.h" +#include "mt6885.h" +#include "emi_mng.h" +#include "mt6885_emi.h" +#include "mt6885_consys_reg.h" +#include "mt6885_consys_reg_offset.h" +#include "mt6885_pos.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define CONSYS_PWR_SPM_CTRL 1 +#define PLATFORM_SOC_CHIP 0x6885 + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static int consys_clk_get_from_dts(struct platform_device *pdev); +static int consys_clock_buffer_ctrl(unsigned int enable); +static unsigned int consys_soc_chipid_get(void); +static unsigned int consys_get_hw_ver(void); +static void consys_clock_fail_dump(void); +static int consys_thermal_query(void); +static int consys_power_state(void); +static int consys_bus_clock_ctrl(enum consys_drv_type, unsigned int, int); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +struct consys_hw_ops_struct g_consys_hw_ops = { + /* load from dts */ + /* TODO: mtcmos should move to a independent module */ + .consys_plt_clk_get_from_dts = consys_clk_get_from_dts, + + /* clock */ + .consys_plt_clock_buffer_ctrl = consys_clock_buffer_ctrl, + .consys_plt_co_clock_type = consys_co_clock_type, + + /* POS */ + .consys_plt_conninfra_on_power_ctrl = consys_conninfra_on_power_ctrl, + .consys_plt_set_if_pinmux = consys_set_if_pinmux, + + .consys_plt_polling_consys_chipid = consys_polling_chipid, + .consys_plt_d_die_cfg = connsys_d_die_cfg, + .consys_plt_spi_master_cfg = connsys_spi_master_cfg, + .consys_plt_a_die_cfg = connsys_a_die_cfg, + .consys_plt_afe_wbg_cal = connsys_afe_wbg_cal, + .consys_plt_subsys_pll_initial = connsys_subsys_pll_initial, + .consys_plt_low_power_setting = connsys_low_power_setting, + .consys_plt_soc_chipid_get = consys_soc_chipid_get, + .consys_plt_conninfra_wakeup = consys_conninfra_wakeup, + .consys_plt_conninfra_sleep = consys_conninfra_sleep, + .consys_plt_is_rc_mode_enable = consys_is_rc_mode_enable, + + /* debug */ + .consys_plt_clock_fail_dump = consys_clock_fail_dump, + .consys_plt_get_hw_ver = consys_get_hw_ver, + + .consys_plt_spi_read = consys_spi_read, + .consys_plt_spi_write = consys_spi_write, + .consys_plt_adie_top_ck_en_on = consys_adie_top_ck_en_on, + .consys_plt_adie_top_ck_en_off = consys_adie_top_ck_en_off, + .consys_plt_spi_clock_switch = consys_spi_clock_switch, + .consys_plt_subsys_status_update = consys_subsys_status_update, + + .consys_plt_thermal_query = consys_thermal_query, + .consys_plt_power_state = consys_power_state, + .consys_plt_config_setup = consys_config_setup, + .consys_plt_bus_clock_ctrl = consys_bus_clock_ctrl, +}; + + +struct clk *clk_scp_conn_main; /*ctrl conn_power_on/off */ +struct consys_plat_thermal_data g_consys_plat_therm_data; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +struct consys_hw_ops_struct* get_consys_platform_ops(void) +{ + return &g_consys_hw_ops; +} + +/* mtcmos contorl */ +int consys_clk_get_from_dts(struct platform_device *pdev) +{ + clk_scp_conn_main = devm_clk_get(&pdev->dev, "conn"); + if (IS_ERR(clk_scp_conn_main)) { + pr_err("[CCF]cannot get clk_scp_conn_main clock.\n"); + return PTR_ERR(clk_scp_conn_main); + } + pr_debug("[CCF]clk_scp_conn_main=%p\n", clk_scp_conn_main); + + return 0; +} + +int consys_platform_spm_conn_ctrl(unsigned int enable) +{ + int ret = 0; + + if (enable) { + ret = clk_prepare_enable(clk_scp_conn_main); + if (ret) { + pr_err("Turn on oonn_infra power fail. Ret=%d\n", ret); + return -1; + } + } else { + clk_disable_unprepare(clk_scp_conn_main); + + } + + return ret; +} + +int consys_clock_buffer_ctrl(unsigned int enable) +{ + /* This function call didn't work now. + * clock buffer is HW controlled, not SW controlled. + * Keep this function call to update status. + */ + if (enable) + KERNEL_clk_buf_ctrl(CLK_BUF_CONN, true); /*open XO_WCN*/ + else + KERNEL_clk_buf_ctrl(CLK_BUF_CONN, false); /*close XO_WCN*/ + return 0; +} + +int consys_co_clock_type(void) +{ + const struct conninfra_conf *conf; + + /* Default solution */ + conf = conninfra_conf_get_cfg(); + if (NULL == conf) { + pr_err("[%s] Get conf fail", __func__); + return -1; + } + /* TODO: for co-clock mode, there are two case: 26M and 52M. Need something to distinguish it. */ + if (conf->tcxo_gpio != 0) + return CONNSYS_CLOCK_SCHEMATIC_26M_EXTCXO; + else + return CONNSYS_CLOCK_SCHEMATIC_26M_COTMS; +} + +unsigned int consys_soc_chipid_get(void) +{ + return PLATFORM_SOC_CHIP; +} + +unsigned int consys_get_hw_ver(void) +{ + return CONN_HW_VER; +} + +void consys_clock_fail_dump(void) +{ + pr_info("[%s]", __func__); +} + + +void update_thermal_data(struct consys_plat_thermal_data* input) +{ + memcpy(&g_consys_plat_therm_data, input, sizeof(struct consys_plat_thermal_data)); + /* Special factor, not in POS */ + /* THERMCR1 [16:17]*/ + CONSYS_REG_WRITE(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERMCR1, + (CONSYS_REG_READ(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERMCR1) | + (0x3 << 16))); + +} + +int calculate_thermal_temperature(int y) +{ + struct consys_plat_thermal_data *data = &g_consys_plat_therm_data; + int t; + int const_offset = 25; + + /* + * MT6635 E1 : read 0x02C = 0x66358A00 + * MT6635 E2 : read 0x02C = 0x66358A10 + * MT6635 E3 : read 0x02C = 0x66358A11 + */ + if (conn_hw_env.adie_hw_version == 0x66358A10 || + conn_hw_env.adie_hw_version == 0x66358A11) + const_offset = 28; + + /* temperature = (y-b)*slope + (offset) */ + /* TODO: offset + 25 : this is only for E1, E2 is 28 */ + t = (y - (data->thermal_b == 0 ? 0x36 : data->thermal_b)) * + ((data->slop_molecule + 209) / 100) + (data->offset + const_offset); + + pr_info("y=[%d] b=[%d] constOffset=[%d] [%d] [%d] => t=[%d]\n", + y, data->thermal_b, const_offset, data->slop_molecule, data->offset, + t); + + return t; +} + +int consys_thermal_query(void) +{ +#define THERMAL_DUMP_NUM 11 +#define LOG_TMP_BUF_SZ 256 +#define TEMP_SIZE 13 + void __iomem *addr = NULL; + int cal_val, res = 0; + /* Base: 0x1800_2000, CONN_TOP_THERM_CTL */ + const unsigned int thermal_dump_crs[THERMAL_DUMP_NUM] = { + 0x00, 0x04, 0x08, 0x0c, + 0x10, 0x14, 0x18, 0x1c, + 0x20, 0x24, 0x28, + }; + char tmp[TEMP_SIZE] = {'\0'}; + char tmp_buf[LOG_TMP_BUF_SZ] = {'\0'}; + unsigned int i; + unsigned int efuse0, efuse1, efuse2, efuse3; + + addr = ioremap_nocache(CONN_GPT2_CTRL_BASE, 0x100); + if (addr == NULL) { + pr_err("GPT2_CTRL_BASE remap fail"); + return -1; + } + + consys_adie_top_ck_en_on(CONNSYS_ADIE_CTL_HOST_CONNINFRA); + + /* Hold Semaphore, TODO: may not need this, because + thermal cr seperate for different */ + if (consys_sema_acquire_timeout(CONN_SEMA_THERMAL_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) { + pr_err("[THERM QRY] Require semaphore fail\n"); + consys_adie_top_ck_en_off(CONNSYS_ADIE_CTL_HOST_CONNINFRA); + iounmap(addr); + return -1; + } + + /* therm cal en */ + CONSYS_REG_WRITE(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_CAL_EN, + (CONSYS_REG_READ(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_CAL_EN) | + (0x1 << 19))); + /* GPT2 En */ + CONSYS_REG_WRITE(addr + CONN_GPT2_CTRL_THERMAL_EN, + (CONSYS_REG_READ(addr + CONN_GPT2_CTRL_THERMAL_EN) | + 0x1)); + + /* thermal trigger */ + CONSYS_REG_WRITE(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_CAL_EN, + (CONSYS_REG_READ(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_CAL_EN) | + (0x1 << 18))); + udelay(500); + /* get thermal value */ + cal_val = CONSYS_REG_READ(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_CAL_EN); + cal_val = (cal_val >> 8) & 0x7f; + + /* thermal debug dump */ + efuse0 = CONSYS_REG_READ(CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_0); + efuse1 = CONSYS_REG_READ(CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_1); + efuse2 = CONSYS_REG_READ(CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_2); + efuse3 = CONSYS_REG_READ(CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_3); + for (i = 0; i < THERMAL_DUMP_NUM; i++) { + if (snprintf( + tmp, TEMP_SIZE, "[0x%08x]", + CONSYS_REG_READ(CONN_TOP_THERM_CTL_ADDR + thermal_dump_crs[i])) >= 0) + strncat(tmp_buf, tmp, strlen(tmp)); + } + pr_info("[%s] efuse:[0x%08x][0x%08x][0x%08x][0x%08x] thermal dump: %s", + __func__, efuse0, efuse1, efuse2, efuse3, tmp_buf); + + res = calculate_thermal_temperature(cal_val); + + /* GPT2 disable, no effect on 6885 */ + CONSYS_REG_WRITE(addr + CONN_GPT2_CTRL_THERMAL_EN, + (CONSYS_REG_READ(addr + CONN_GPT2_CTRL_THERMAL_EN) & + ~(0x1))); + + /* disable */ + CONSYS_REG_WRITE(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_CAL_EN, + (CONSYS_REG_READ(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_CAL_EN) & + ~(0x1 << 19))); + + consys_sema_release(CONN_SEMA_THERMAL_INDEX); + consys_adie_top_ck_en_off(CONNSYS_ADIE_CTL_HOST_CONNINFRA); + + iounmap(addr); + + return res; +} + + +int consys_power_state(void) +{ + const char* osc_str[] = { + "fm ", "gps ", "bgf ", "wf ", "ap2conn ", "conn_thm ", "conn_pta ", "conn_infra_bus " + }; + char buf[256] = {'\0'}; + unsigned int r = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_2); + unsigned int i, buf_len = 0, str_len; + + for (i = 0; i < 8; i++) { + str_len = strlen(osc_str[i]); + if ((r & (0x1 << (18 + i))) > 0 && (buf_len + str_len < 256)) { + strncat(buf, osc_str[i], str_len); + buf_len += str_len; + } + } + pr_info("[%s] [0x%x] %s", __func__, r, buf); + return 0; +} + +int consys_bus_clock_ctrl(enum consys_drv_type drv_type, unsigned int bus_clock, int status) +{ + static unsigned int conninfra_bus_clock_wpll_state = 0; + static unsigned int conninfra_bus_clock_bpll_state = 0; + unsigned int wpll_state = conninfra_bus_clock_wpll_state; + unsigned int bpll_state = conninfra_bus_clock_bpll_state; + bool wpll_switch = false, bpll_switch = false; + int check; + + if (status) { + /* Turn on */ + /* Enable BPLL */ + if (bus_clock & CONNINFRA_BUS_CLOCK_BPLL) { + + if (conninfra_bus_clock_bpll_state == 0) { + CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_03, (0x1 << 21)); + udelay(30); + bpll_switch = true; + } + conninfra_bus_clock_bpll_state |= (0x1 << drv_type); + } + /* Enable WPLL */ + if (bus_clock & CONNINFRA_BUS_CLOCK_WPLL) { + if (conninfra_bus_clock_wpll_state == 0) { + CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_03, (0x1 << 20)); + udelay(50); + wpll_switch = true; + } + conninfra_bus_clock_wpll_state |= (0x1 << drv_type); + } + pr_info("drv=[%d] conninfra_bus_clock_wpll=[%u]->[%u] %s conninfra_bus_clock_bpll=[%u]->[%u] %s", + drv_type, + wpll_state, conninfra_bus_clock_wpll_state, (wpll_switch ? "enable" : ""), + bpll_state, conninfra_bus_clock_bpll_state, (bpll_switch ? "enable" : "")); + } else { + /* Turn off */ + /* Turn off WPLL */ + if (bus_clock & CONNINFRA_BUS_CLOCK_WPLL) { + conninfra_bus_clock_wpll_state &= ~(0x1<[%u] %s conninfra_bus_clock_bpll=[%u]->[%u] %s", + drv_type, + wpll_state, conninfra_bus_clock_wpll_state, (wpll_switch ? "disable" : ""), + bpll_state, conninfra_bus_clock_bpll_state, (bpll_switch ? "disable" : "")); + if (consys_reg_mng_reg_readable() == 0) { + check = consys_reg_mng_is_bus_hang(); + pr_info("[%s] not readable, bus hang check=[%d]", __func__, check); + } + } + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/mt6885_consys_reg.c b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/mt6885_consys_reg.c new file mode 100644 index 0000000000000..573b9d6853cbf --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/mt6885_consys_reg.c @@ -0,0 +1,799 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#include +#include +#include +#include +#include +#include + +#include + +#include "consys_reg_mng.h" +#include "mt6885_consys_reg.h" +#include "mt6885_consys_reg_offset.h" +#include "consys_hw.h" +#include "consys_reg_util.h" + +#define LOG_TMP_BUF_SZ 256 +#define CONSYS_POWER_MODE_LEGACY "Legacy" +#define CONSYS_POWER_MODE_RC "RC" + +static int consys_reg_init(struct platform_device *pdev); +static int consys_reg_deinit(void); +static int consys_check_reg_readable(void); +static int consys_is_consys_reg(unsigned int addr); +static int consys_is_bus_hang(void); +static int consys_dump_bus_status(void); +static int consys_dump_conninfra_status(void); +static int consys_dump_cpupcr(enum conn_dump_cpupcr_type, int times, unsigned long interval_us); +static int consys_is_host_csr(unsigned long addr); + +struct consys_reg_mng_ops g_dev_consys_reg_ops = { + .consys_reg_mng_init = consys_reg_init, + .consys_reg_mng_deinit = consys_reg_deinit, + + .consys_reg_mng_check_reable = consys_check_reg_readable, + .consys_reg_mng_is_consys_reg = consys_is_consys_reg, + .consys_reg_mng_is_bus_hang = consys_is_bus_hang, + .consys_reg_mng_dump_bus_status = consys_dump_bus_status, + .consys_reg_mng_dump_conninfra_status = consys_dump_conninfra_status, + .consys_reg_mng_dump_cpupcr = consys_dump_cpupcr, + .consys_reg_mng_is_host_csr = consys_is_host_csr +}; + + +const char* consys_base_addr_index_to_str[CONSYS_BASE_ADDR_MAX] = { + "CONN_INFRA_RGU_BASE", + "CONN_INFRA_CFG_BASE", + "CONN_HOST_CSR_TOP_BASE", + "INFRACFG_AO_BASE", + "TOPRGU_BASE", + "SPM_BASE", + "INFRACFG_BASE", + "CONN_WT_SLP_CTL_REG", + "CONN_AFE_CTL_REG", + "CONN_INFRA_SYSRAM", + "GPIO", + "CONN_RF_SPI_MST_REG", + "CONN_SEMAPHORE", + "CONN_TOP_THERM_CTL", + "IOCFG_RT", +}; + +struct consys_base_addr conn_reg; + +struct consys_reg_mng_ops* get_consys_reg_mng_ops(void) +{ + return &g_dev_consys_reg_ops; +} + +struct consys_base_addr* get_conn_reg_base_addr() +{ + return &conn_reg; +} + +static void consys_bus_hang_dump_c(void) +{ + unsigned long debug_addr, out_addr; + unsigned long value; + int i; + unsigned long debug_setting[] = { + 0xf0001, 0xe0001, 0xd0001, 0xc0001, 0xb0001, 0xa0001, + 0x90001, 0x80001, 0x70001, 0x60001, 0x50001, 0x40001, + 0x30001, 0x20001, 0x10001, 0x30002, 0x20002, 0x10002, + 0x40003, 0x30003, 0x20003, 0x10003 + }; + + /* CONN2AP GALS RX status + * 0x1020_E804 + * + * CONNINFRA sleep protect + * 0x1000_6158[2] ap2conn gals rx slp prot + * 0x1000_6150[13] ap2conn gals tx slp prot + * + * conninfra on2off off2on slp prot + * 0x1806_0184[5] conn_infra on2off slp prot + * 0x1806_0184[3] conn_infra off2on slp prot + */ + pr_info("[CONN_BUS_C] [%x][%x][%x] [%x]", + CONSYS_REG_READ(CON_REG_INFRACFG_BASE_ADDR + INFRA_CONN2AP_GLAS_RC_ST), + CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_BUS_PROTECT2_RDY), + CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_BUS_PROTECT_RDY), + CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL) + ); + + debug_addr = CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_AO_DEBUGSYS; + out_addr = CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT; + + for (i = 0; i < ARRAY_SIZE(debug_setting); i++) { + CONSYS_REG_WRITE(debug_addr, debug_setting[i]); + value = CONSYS_REG_READ(out_addr); + pr_info("[CONN_BUS_C] addr=0x%x value=0x%08x", debug_setting[i], value); + } +} + +static void consys_bus_hang_dump_a_rc(void) +{ + unsigned int i; + char tmp[LOG_TMP_BUF_SZ] = {'\0'}; + char tmp_buf[LOG_TMP_BUF_SZ] = {'\0'}; + + for (i = 0xE50; i <= 0xE94; i += 4) { + if (snprintf(tmp, LOG_TMP_BUF_SZ, "[%x]", + CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + i)) >= 0) + strncat(tmp_buf, tmp, strlen(tmp)); + } + pr_info("[rc_trace] %s", tmp_buf); + + memset(tmp_buf, '\0', LOG_TMP_BUF_SZ); + for (i = 0xE98; i <= 0xED4; i += 4) { + if (snprintf(tmp, LOG_TMP_BUF_SZ, "[%x]", + CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + i)) >= 0) + strncat(tmp_buf, tmp, strlen(tmp)); + } + pr_info("[rc_timer] %s", tmp_buf); +} + +static void consys_bus_hang_dump_a(void) +{ + void __iomem *addr = NULL; + unsigned int r1, r2, r3, r4, r5, r6, r7 = 0, r8 = 0, r9 = 0, r10, r11; + char tmp_buf[LOG_TMP_BUF_SZ] = {'\0'}; + char rc_buf[LOG_TMP_BUF_SZ] = {'\0'}; + + /* + * r1 : 0x1000_6110 + * r2 : 0x1000_6114 + */ + if (snprintf(tmp_buf, LOG_TMP_BUF_SZ, "[%s] [0x%x][0x%x]", + (conn_hw_env.is_rc_mode ? CONSYS_POWER_MODE_RC : CONSYS_POWER_MODE_LEGACY), + CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_PCM_REG13_DATA), + CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_SRC_REQ_STA_0)) < 0) + pr_warn("[%s] sprintf error\n", __func__); + + /* RC REQ STA + * r3 : 0x1000_6E28 + * r4 : 0x1000_6E2C + * r5 : 0x1000_6E30 + * r6 : 0x1000_6E34 + */ + if (snprintf(rc_buf, LOG_TMP_BUF_SZ, "[%x][%x][%x][%x]", + CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_RC_RC_M04_REQ_STA_0), + CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_RC_RC_M05_REQ_STA_0), + CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_RC_RC_M06_REQ_STA_0), + CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_RC_RC_M07_REQ_STA_0)) < 0) + pr_warn("[%s] sprintf error\n", __func__); + + /* + * 0x1000684C [28] DEBUG_IDX_VTCXO_STATE + * 0x1000684C [29] DEBUG_IDX_INFRA_STATE + * 0x1000684C [30] DEBUG_IDX_VRF18_STATE + * 0x1000684C [31] DEBUG_IDX_APSRC_STATE + * r7: 0x1000684C + */ + r1 = CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_PCM_WDT_LATCH_SPARE_0); + + /* + * 0x10006100[0] sc_26m_ck_off 1'b0: 26M on; 1'b1 + * 0x10006100[3] sc_axi_ck_off 1'b0: bus ck on; 1'b1 bus ck off + * 0x10006100[5] sc_md26m_ck_off 1'b0: MD 26M on; 1'b1 MD 26M off + * 0x10006100[20] sc_cksq0_off 1'b0: clock square0 on; 1'b1 clock square off + * r8:0x10006100 + */ + r2 = CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_PCM_REG7_DATA); + + /* + * 0x1000_6304[2] : pwr_on + * 0x1000_616c[1] : pwr_ack + * 0x1000_6304[3] : pwr_on_s + * 0x1000_6170[1] : pwr_ack_s + * 0x1000_6304[1] : iso_en + * 0x1000_6304[0] : ap_sw_rst + * r9 : 0x1000_616C + * r10 : 0x1000_6170 + * r11 : 0x1000_6304 + */ + r3 = CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_PWR_STATUS); + r4 = CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_PWR_STATUS_2ND); + r5 = CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON); + + /* + * sc_md_32k_ck_off + * r12 : 0x1000_644C + */ + r6 = CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_PLL_CON); + + /* + * infra bus clock + * r13 : 0x1000_0000 pdn_conn_32k + * r14 : 0x1000_0010[2:0] + * 0: tck_26m_mx9_ck => 26M + * 1: mainpll_d4_d4 => 136.5M + * 2: mainpll_d7_d2 => 156M + * 3: mainpll_d4_d2 => 273M + * 4: mainpll_d5_d2 => 218.4M + * 5: mainpll_d6_d2 => 182M + * 6: osc_d4 => 65M + */ + addr = ioremap_nocache(0x10000000, 0x20); + if (addr != NULL) { + r7 = CONSYS_REG_READ(addr); + r8 = CONSYS_REG_READ(addr + 0x10); + iounmap(addr); + } + + /* + * r15 : 0x1000_0200 sc_md2_32k_off_en + */ + addr = ioremap_nocache(0x10000200, 0x20); + if (addr != NULL) { + r9 = CONSYS_REG_READ(addr); + iounmap(addr); + } + + /* ap2conn gals sleep protect status + * - 0x1000_1724 [2] / 0x1000_1228 [13] (infracfg_ao)(rx/tx) (sleep protect enable ready) + * r16 : 0x1000_1724 + * r17 : 0x1000_1228 + */ + r10 = CONSYS_REG_READ(CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN2_STA1_OFFSET); + r11 = CONSYS_REG_READ(CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1_OFFSET); + + pr_info("[CONN_BUS_A] %s %s [%x][%x][%x][%x][%x][%x] [%x][%x] [%x][%x][%x]", tmp_buf, + rc_buf, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11); + + consys_bus_hang_dump_a_rc(); +} + +static void consys_bus_hang_dump_b(void) +{ + char tmp_buf[LOG_TMP_BUF_SZ] = {'\0'}; + unsigned int r1, r2, r3, r4, r5, r6, r7; + + /* Legacy Mode */ + /* + * 0x180602c0 + * [4]: conn_srcclkena_ack + * [5]: conn_ap_bus_ack + * [6]: conn_apsrc_ack + * [7]: conn_ddr_en_ack + * cr1 : 0x1806_02c0 + */ + if (snprintf(tmp_buf, LOG_TMP_BUF_SZ, "[%s] [%x]", + (conn_hw_env.is_rc_mode ? CONSYS_POWER_MODE_RC : CONSYS_POWER_MODE_LEGACY), + CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_0)) < 0) + pr_warn("[%s] sprintf error\n", __func__); + + /* RC Mode */ + /* + * debug sel 0x18001B00[2:0] 3'b010 + * 0x1806_02C8 + * [12] conn_srcclkena_0_bblpm_ack + * [13] conn_srcclkena_0_fpm_ack + * [28] conn_srcclkena_1_bblpm_ack + * [29] conn_srcclkena_1_fpm_ack + * cr2 : 0x1806_02c8 + */ + r1 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_2); + + /* + * Consys status check + * debug sel 0x18001B00[2:0] 3'b010 + * 0x1806_02C8 + * [25] conninfra_bus_osc_en + * [24] conn_pta_osc_en + * [23] conn_thm_osc_en + * [22] ap2conn_osc_en + * [21] wfsys_osc_en + * [20] bgfsys_osc_en + * [19] gpssys_osc_en + * [18] fmsys_osc_en + */ + /*CONSYS_REG_WRITE_MASK(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_DBG_MUX_SEL, + 0x2, 0x7);*/ + /*r1 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_2);*/ + + /* Conninfra Off power state + * 0x1806_02CC + * [15] power_enable + * [14] power_on + * [13] pwer_ack + * [12] pwr_on_s + * [11] pwr_ack_s + * [10] iso_en + * [9] conn_infra_off_xreset_b + * [8] conn_infra_off_hreset_b + * + * cr3 : 0x1806_02CC + */ + r2 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_3); + + + /* conn_infra_on clock 0x1020E504[0] = 1’b1 + * + * cr4 : 0x1020_E504 + */ + r3 = CONSYS_REG_READ(CON_REG_INFRACFG_BASE_ADDR + + INFRA_AP2MD_GALS_CTL); + + /* Check conn_infra off bus clock + * - write 0x1 to 0x1806_0000[0], reset clock detect + * - 0x1806_0000[2] conn_infra off bus clock (should be 1'b1 if clock exist) + * - 0x1806_0000[1] osc clock (should be 1'b1 if clock exist) + * + * cr5 : 0x1806_0000 + */ + CONSYS_SET_BIT(CON_REG_HOST_CSR_ADDR, 0x1); + udelay(200); + r4 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR); + + /* conn_infra on2off sleep protect status + * - 0x1806_0184[5] (sleep protect enable ready), should be 1'b0 + * cr6 : 0x1806_0184 + */ + r5 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL); + + /* CONN_HOST_CSR_DBG_DUMMY_4 + * cr7 : 0x1806_02D0 + */ + r6 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_4); + + /* 0x1806_02D4: dump bus timeout irq status + * cr8 : 0x1806_02D4 + */ + r7 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_BUS_TIMEOUT_IRQ); + + pr_info("[CONN_BUS_B] infra_off %s [%x][%x] [%x][%x][%x] [%x] [%x]" + , tmp_buf, r1, r2, r3, r4, r5, r6, r7); + pr_info("[CONN_BUS_B] 0x1806_0294:[0x%08x] 0x1806_0220:[0x%08x]\n", + CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + 0x0294), + CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + 0x0220)); +} + +#if 0 +static void consys_bus_hang_dump_d(void) +{ + int r1; + + /* check if consys off on + * 0x1806_02cc[8] 1'b1 ==> pwr on, 1'b0 ==> pwr off + */ + r1 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_3); + if (((r1 >> 8) & 0x01) == 0) { + pr_info("[CONN_BUS_D] conninfra off is not on"); + return; + } + + /* PLL & OSC status + * 0x18001810[1] bpll_rdy + * 0x18001810[0] wpll_rdy + * + * OSC + * 0x1800_180C + * [3] : bus_bpll_sw_rdy, 1'b1 conninfra bus clock=166.4M + * [2] : bus_bpll_sw_rdy, 1'b1 conninfra bus clock=83.2M + * [1] : bus_bpll_sw_rdy, 1'b1 conninfra bus clock=32M + * [0] : bus_bpll_sw_rdy, 1'b1 conninfra bus clock=osc + * + * 0x1800_1160[22] ap2conn gals rx slp prot + * 0x1800_1630[3] conn2ap gals tx slp prot + * 0x1800_1634[3] conn2ap gals rx slp prot + * + * 0x1800_1628[3] conn_infra on2off slp pro + * 0x1800_162c[3] conn_infra off2on slp pro + * + * 0x1800_161C[3] gps2conn gals tx slp prot + * 0x1800_161C[7] gps2conn gals rx slp prot + * 0x1800_1618[7] conn2gps gals rx slp prot + * 0x1800_1618[3] conn2gps gals tx slp prot + * + * 0x1800_1614[3] bt2conn gals tx slp prot + * 0x1800_1614[7] bt2conn gals rx slp prot + * 0x1800_1610[3] conn2bt gals tx slp prot + * 0x1800_1610[7] conn2bt gals rx slp prot + * + * 0x1800_1620[3] wf2conn slp prot + */ + pr_info("[CONN_BUS_D] [%x][%x] [%x][%x][%x] [%x][%x] [%x][%x] [%x][%x] [%x]", + CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_PLL_STATUS), /* PLL */ + CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_OSC_STATUS), /* OSC */ + + CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_GALS_AP2CONN_GALS_DBG), + CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_GALS_CONN2AP_TX_SLP_CTRL), + CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_GALS_CONN2AP_RX_SLP_CTRL), + + CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_ON_BUS_SLP_CTRL), /* on2off */ + CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_OFF_BUS_SLP_CTRL),/* off2on */ + + CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL), /* gps2conn */ + CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL), /* conn2gps */ + + CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_GALS_BT2CONN_SLP_CTRL), /* bt2conn */ + CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_GALS_CONN2BT_SLP_CTRL), /* conn2bt */ + + CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_WF_SLP_CTRL) /* w2conn */ + ); +} +#endif + +static int consys_dump_bus_status(void) +{ + consys_bus_hang_dump_c(); + return 0; +} + +static int consys_dump_conninfra_status(void) +{ + consys_bus_hang_dump_a(); + consys_bus_hang_dump_b(); + return 0; +} + +int consys_dump_cpupcr(enum conn_dump_cpupcr_type type, int times, unsigned long interval_us) +{ + int i; + + for (i = 0; i < times; i++) { + pr_info("%s: wm pc=0x%x, wm lp=0x%x, bt pc=0x%x", + __func__, + CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_WM_MCU_PC_DBG), + CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_WM_MCU_GPR_DBG), + CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_BGF_MCU_PC_DBG)); + if (interval_us > 1000) + usleep_range(interval_us - 100, interval_us + 100); + else + udelay(interval_us); + } + + return 0; +} + +static int consys_is_bus_hang(void) +{ + int r; + + /* dump SPM register */ + consys_bus_hang_dump_a(); + + /* STEP - 1 */ + /* + * check kernel API lastbus_timeout_dump + * if return > 0 -> return 0x1 + */ + + /* 1. Check ap2conn gals sleep protect status + * - 0x1000_1724 [2] / 0x1000_1228 [13] (infracfg_ao)(rx/tx) (sleep protect enable ready) + * both of them should be 1'b0 (CR at ap side) + */ + r = CONSYS_REG_READ_BIT(CON_REG_INFRACFG_AO_ADDR + + INFRA_TOPAXI_PROTECTEN2_STA1_OFFSET, (0x1 << 2)); + if (r != 0) + return CONNINFRA_AP2CONN_RX_SLP_PROT_ERR; + + r = CONSYS_REG_READ_BIT(CON_REG_INFRACFG_AO_ADDR + + INFRA_TOPAXI_PROTECTEN_STA1_OFFSET, (0x1 << 13)); + if (r != 0) + return CONNINFRA_AP2CONN_TX_SLP_PROT_ERR; + + /* 2. Check conn_infra_on clock 0x1020E504[0] = 1’b1 */ + r = CONSYS_REG_READ_BIT(CON_REG_INFRACFG_BASE_ADDR + + INFRA_AP2MD_GALS_CTL, 0x1); + if (r != 1) + return CONNINFRA_AP2CONN_CLK_ERR; + + /* STEP - 2 */ + consys_bus_hang_dump_b(); + +#if 0 + /* 3. Check conn_infra off bus clock + * - write 0x1 to 0x1806_0000[0], reset clock detect + * - 0x1806_0000[2] conn_infra off bus clock (should be 1'b1 if clock exist) + * - 0x1806_0000[1] osc clock (should be 1'b1 if clock exist) + */ + CONSYS_SET_BIT(CON_REG_HOST_CSR_ADDR, 0x1); + udelay(500); + r = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR); + if ((r & TOP_BUS_MUC_STAT_HCLK_FR_CK_DETECT_BIT) == 0 || + (r & TOP_BUS_MUC_STAT_OSC_CLK_DETECT_BIT) == 0) + ret |= CONNINFRA_INFRA_BUS_CLK_ERR; +#endif + + /* 4. Check conn_infra off domain bus hang irq status + * - 0x1806_02d4[0], should be 1'b1, or means conn_infra off bus might hang + */ + r = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_BUS_TIMEOUT_IRQ); + + if ((r & 0x1) != 0x1) { + pr_err("conninfra off bus might hang cirq=[0x%08x]", r); + consys_bus_hang_dump_c(); + return CONNINFRA_INFRA_BUS_HANG_IRQ; + } + consys_bus_hang_dump_c(); + +#if 0 + /* 5. Check conn_infra on2off sleep protect status + * - 0x1806_0184[5] (sleep protect enable ready), should be 1'b0 + */ + r = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL); + if (r & TOP_SLP_PROT_CTRL_CONN_INFRA_ON2OFF_SLP_PROT_ACK_BIT) + ret |= CONNINFRA_ON2OFF_SLP_PROT_ERR; + if (ret) { + pr_info("[%s] ret=[%x]", __func__, ret); + consys_bus_hang_dump_c(); + return ret; + } +#endif + /*consys_bus_hang_dump_d();*/ + + return 0; + +} + +int consys_check_reg_readable(void) +{ + int r; + unsigned int rnd; + int delay_time = 1, spent = delay_time, max_wait = 16000; // 1.6 ms + int retry = max_wait / 10; + + /* STEP - 1 */ + /* + * check kernel API lastbus_timeout_dump + * if return > 0 -> return 0x1 + */ + + + /* 1. Check ap2conn gals sleep protect status + * - 0x1000_1724 [2] / 0x1000_1228 [13] (infracfg_ao)(rx/tx) (sleep protect enable ready) + * both of them should be 1'b0 (CR at ap side) + */ + r = CONSYS_REG_READ_BIT(CON_REG_INFRACFG_AO_ADDR + + INFRA_TOPAXI_PROTECTEN2_STA1_OFFSET, (0x1 << 2)); + if (r != 0) + return 0; + + r = CONSYS_REG_READ_BIT(CON_REG_INFRACFG_AO_ADDR + + INFRA_TOPAXI_PROTECTEN_STA1_OFFSET, (0x1 << 13)); + if (r != 0) + return 0; + + /* STEP - 2 */ + + /* 2. Check conn_infra_on clock 0x1020E504[0] = 1’b1 */ + r = CONSYS_REG_READ_BIT(CON_REG_INFRACFG_BASE_ADDR + + INFRA_AP2MD_GALS_CTL, 0x1); + if (r != 1) + return 0; + + /* 3. Check conn_infra off bus clock + * - write 0x1 to 0x1806_0000[0], reset clock detect + * - 0x1806_0000[1] conn_infra off bus clock (should be 1'b1 if clock exist) + * - 0x1806_0000[2] osc clock (should be 1'b1 if clock exist) + */ + + while (retry > 0 && spent < max_wait) { + CONSYS_SET_BIT(CON_REG_HOST_CSR_ADDR, 0x1); + udelay(delay_time); + r = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR); + if ((r & TOP_BUS_MUC_STAT_HCLK_FR_CK_DETECT_BIT) == 0 || + (r & TOP_BUS_MUC_STAT_OSC_CLK_DETECT_BIT) == 0) { + spent += delay_time; + retry--; + if (retry == 0) + pr_info("[%s] retry=0 r=[%x]", __func__, r); + else + delay_time = 10; + rnd = get_random_int() % 10; + spent += rnd; + udelay(rnd); + continue; + } + break; + } + if (retry == 0 || spent >= max_wait) { + pr_info("[%s] readable fail = bus clock retry=[%d] spent=[%d]", __func__, + retry, spent); + return 0; + } + + /* 4. Check conn_infra off domain bus hang irq status + * - 0x1806_02d4[0], should be 1'b1, or means conn_infra off bus might hang + */ + r = CONSYS_REG_READ_BIT(CON_REG_HOST_CSR_ADDR + + CONN_HOST_CSR_TOP_BUS_TIMEOUT_IRQ, 0x1); + if (r != 0x1) + return 0; + + /* 5. Check conn_infra on2off sleep protect status + * - 0x1806_0184[5] (sleep protect enable ready), should be 1'b0 + */ + r = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL); + if (r & TOP_SLP_PROT_CTRL_CONN_INFRA_ON2OFF_SLP_PROT_ACK_BIT) + return 0; + + return 1; +} + + +int consys_is_consys_reg(unsigned int addr) +{ + return 0; +} + + +static int consys_is_host_csr(unsigned long addr) +{ + struct consys_reg_base_addr *host_csr_addr = + &conn_reg.reg_base_addr[CONN_HOST_CSR_TOP_BASE_INDEX]; + + if (addr >= host_csr_addr->phy_addr && + addr < host_csr_addr->phy_addr + host_csr_addr->size) + return 1; + return 0; +} + +unsigned long consys_reg_validate_idx_n_offset(unsigned int idx, unsigned long offset) +{ + unsigned long res; + + if (idx < 0 || idx >= CONSYS_BASE_ADDR_MAX) { + pr_warn("ConsysReg failed: No support the base %d\n", idx); + return 0; + } + + res = conn_reg.reg_base_addr[idx].phy_addr; + + if (res == 0) { + pr_warn("ConsysReg failed: No support the base idx is 0 index=[%d]\n", idx); + return 0; + } + + if (offset >= conn_reg.reg_base_addr[idx].size) { + pr_warn("ConnReg failed: index(%d), offset(%d) over max size(%llu) %s\n", + idx, (int) offset, conn_reg.reg_base_addr[idx].size); + return 0; + } + return res; +} + +int consys_find_can_write_reg(unsigned int *idx, unsigned long *offset) +{ + int i; + size_t addr = 0, addr_offset; + int max, mask = 0x0000000F; + int before, after, ret; + + addr = conn_reg.reg_base_addr[CONN_INFRA_RGU_BASE_INDEX].vir_addr; + max = conn_reg.reg_base_addr[CONN_INFRA_RGU_BASE_INDEX].size; + + pr_info("[%s] addr=[%p]\n", __func__, addr); + + for (i = 0x0; i < max; i += 0x4) { + ret = 0; + addr_offset = addr + i; + before = CONSYS_REG_READ(addr_offset); + CONSYS_REG_WRITE_MASK(addr_offset, 0xFFFFFFFF, mask); + after = CONSYS_REG_READ(addr_offset); + if ((after & mask) != (0xFFFFFFFF & mask)) + ret = -1; + + CONSYS_REG_WRITE_MASK(addr_offset, 0x0, mask); + after = CONSYS_REG_READ(addr_offset); + if ((after & mask) != (0x0 & mask)) + ret = -1; + + CONSYS_REG_WRITE_MASK(addr_offset, before, mask); + + pr_info("[%s] addr=[%p] [%d]\n", __func__, addr_offset, ret); + if (ret == 0) { + *idx = CONN_INFRA_RGU_BASE_INDEX; + *offset = i; + return 0; + } + } + return -1; + +} + + +unsigned long consys_reg_get_phy_addr_by_idx(unsigned int idx) +{ + if (idx >= CONSYS_BASE_ADDR_MAX) + return 0; + return conn_reg.reg_base_addr[idx].phy_addr; +} + +unsigned long consys_reg_get_virt_addr_by_idx(unsigned int idx) +{ + if (idx >= CONSYS_BASE_ADDR_MAX) + return 0; + return conn_reg.reg_base_addr[idx].vir_addr; +} + + +int consys_reg_get_chip_id_idx_offset(unsigned int *idx, unsigned long *offset) +{ + *idx = CONN_INFRA_CFG_BASE_INDEX; + *offset = CONN_CFG_ID_OFFSET; + return 0; +} + +int consys_reg_get_reg_symbol_num(void) +{ + return CONSYS_BASE_ADDR_MAX; +} + + +int consys_reg_init(struct platform_device *pdev) +{ + int ret = -1; + struct device_node *node = NULL; + struct consys_reg_base_addr *base_addr = NULL; + struct resource res; + int flag, i = 0; + + node = pdev->dev.of_node; + pr_info("[%s] node=[%p]\n", __func__, node); + if (node) { + for (i = 0; i < CONSYS_BASE_ADDR_MAX; i++) { + base_addr = &conn_reg.reg_base_addr[i]; + + ret = of_address_to_resource(node, i, &res); + if (ret) { + pr_err("Get Reg Index(%d-%s) failed", + i, consys_base_addr_index_to_str[i]); + continue; + } + + base_addr->phy_addr = res.start; + base_addr->vir_addr = + (unsigned long) of_iomap(node, i); + of_get_address(node, i, &(base_addr->size), &flag); + + pr_info("Get Index(%d-%s) phy(0x%zx) baseAddr=(0x%zx) size=(0x%zx)", + i, consys_base_addr_index_to_str[i], base_addr->phy_addr, + base_addr->vir_addr, base_addr->size); + } + + } else { + pr_err("[%s] can't find CONSYS compatible node\n", __func__); + return ret; + } + return 0; + +} + +static int consys_reg_deinit(void) +{ + int i = 0; + + for (i = 0; i < CONSYS_BASE_ADDR_MAX; i++) { + if (conn_reg.reg_base_addr[i].vir_addr) { + pr_info("[%d] Unmap %s (0x%zx)", + i, consys_base_addr_index_to_str[i], + conn_reg.reg_base_addr[i].vir_addr); + iounmap((void __iomem*)conn_reg.reg_base_addr[i].vir_addr); + conn_reg.reg_base_addr[i].vir_addr = 0; + } + } + + return 0; +} + diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/mt6885_emi.c b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/mt6885_emi.c new file mode 100644 index 0000000000000..6673c75befe04 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/mt6885_emi.c @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#define pr_fmt(fmt) KBUILD_MODNAME "@(%s:%d) " fmt, __func__, __LINE__ + +#include +#include +#ifdef CONFIG_MTK_EMI +#include +#endif +#include + +#include +#include "mt6885_emi.h" +#include "mt6885.h" +#include "mt6885_consys_reg.h" +#include "consys_hw.h" +#include "consys_reg_util.h" +#include "mt6885_pos.h" + +/* For MCIF */ +#include + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define REGION_CONN 27 + +#define DOMAIN_AP 0 +#define DOMAIN_CONN 2 +#define DOMAIN_SCP 3 + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + +extern unsigned long long gConEmiSize; +extern phys_addr_t gConEmiPhyBase; + +struct consys_platform_emi_ops g_consys_platform_emi_ops = { + .consys_ic_emi_mpu_set_region_protection = consys_emi_mpu_set_region_protection, + .consys_ic_emi_set_remapping_reg = consys_emi_set_remapping_reg, + .consys_ic_emi_get_md_shared_emi = consys_emi_get_md_shared_emi, +}; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +struct consys_platform_emi_ops* get_consys_platform_emi_ops(void) +{ + return &g_consys_platform_emi_ops; +} + +int consys_emi_mpu_set_region_protection(void) +{ + struct emimpu_region_t region; + unsigned long long start = gConEmiPhyBase; + unsigned long long end = gConEmiPhyBase + gConEmiSize - 1; + + mtk_emimpu_init_region(®ion, REGION_CONN); + mtk_emimpu_set_addr(®ion, start, end); + mtk_emimpu_set_apc(®ion, DOMAIN_AP, MTK_EMIMPU_NO_PROTECTION); + mtk_emimpu_set_apc(®ion, DOMAIN_CONN, MTK_EMIMPU_NO_PROTECTION); + /* for scp */ + mtk_emimpu_set_apc(®ion, DOMAIN_SCP, MTK_EMIMPU_NO_PROTECTION); + mtk_emimpu_set_protection(®ion); + mtk_emimpu_free_region(®ion); + + pr_info("setting MPU for EMI share memory\n"); + return 0; +} + +void consys_emi_get_md_shared_emi(phys_addr_t* base, unsigned int* size) +{ + phys_addr_t mdPhy = 0; + int ret = 0; + +#ifdef CONFIG_MTK_ECCCI_DRIVER + mdPhy = get_smem_phy_start_addr(MD_SYS1, SMEM_USER_RAW_MD_CONSYS, &ret); +#else + pr_info("[%s] ECCCI Driver is not supported.\n", __func__); +#endif + if (ret && mdPhy) { + pr_info("MCIF base=0x%llx size=0x%x", mdPhy, ret); + if (base) + *base = mdPhy; + if (size) + *size = ret; + } else { + pr_info("MCIF is not supported"); + if (base) + *base = 0; + if (size) + *size = 0; + } +} + diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/mt6885_pmic.c b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/mt6885_pmic.c new file mode 100644 index 0000000000000..36e3e21ff17a5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/mt6885_pmic.c @@ -0,0 +1,448 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#define pr_fmt(fmt) KBUILD_MODNAME "@(%s:%d) " fmt, __func__, __LINE__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "consys_hw.h" +#include "consys_reg_util.h" +#include "osal.h" +#include "mt6885.h" +#include "mt6885_pmic.h" +#include "mt6885_pos.h" +#include "mt6885_consys_reg.h" +#include "mt6885_consys_reg_offset.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 +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static int consys_plt_pmic_get_from_dts(struct platform_device *pdev, struct conninfra_dev_cb* dev_cb); + +static int consys_plt_pmic_common_power_ctrl(unsigned int enable); +static int consys_plt_pmic_wifi_power_ctrl(unsigned int enable); +static int consys_plt_pmic_bt_power_ctrl(unsigned int enable); +static int consys_plt_pmic_gps_power_ctrl(unsigned int enable); +static int consys_plt_pmic_fm_power_ctrl(unsigned int enable); +/* VCN33_1 is enable when BT or Wi-Fi is on */ +static int consys_pmic_vcn33_1_power_ctl(bool enable, struct regulator* reg_VCN33_1); +/* VCN33_2 is enable when Wi-Fi is on */ +static int consys_pmic_vcn33_2_power_ctl(bool enable); + +static int consys_plt_pmic_event_notifier(unsigned int id, unsigned int event); + +static int consys_plt_pmic_exit_idle_power_ctrl(void); +static int consys_plt_pmic_enter_idle_power_ctrl(void); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +CONSYS_PLATFORM_PMIC_OPS g_consys_platform_pmic_ops = { + .consys_pmic_get_from_dts = consys_plt_pmic_get_from_dts, + /* vcn 18 */ + .consys_pmic_common_power_ctrl = consys_plt_pmic_common_power_ctrl, + .consys_pmic_wifi_power_ctrl = consys_plt_pmic_wifi_power_ctrl, + .consys_pmic_bt_power_ctrl = consys_plt_pmic_bt_power_ctrl, + .consys_pmic_gps_power_ctrl = consys_plt_pmic_gps_power_ctrl, + .consys_pmic_fm_power_ctrl = consys_plt_pmic_fm_power_ctrl, + .consys_pmic_event_notifier = consys_plt_pmic_event_notifier, +}; + +struct regulator *reg_VCN13; +struct regulator *reg_VCN18; +struct regulator *reg_VCN33_1_BT; +struct regulator *reg_VCN33_1_WIFI; +struct regulator *reg_VCN33_2_WIFI; +struct notifier_block vcn13_nb; + +static struct conninfra_dev_cb* g_dev_cb; +static int g_first_power_on = 0; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +P_CONSYS_PLATFORM_PMIC_OPS get_consys_platform_pmic_ops(void) +{ + return &g_consys_platform_pmic_ops; +} + + +static int consys_vcn13_oc_notify(struct notifier_block *nb, unsigned long event, + void *unused) +{ + if (event != REGULATOR_EVENT_OVER_CURRENT) + return NOTIFY_OK; + + if (g_dev_cb != NULL && g_dev_cb->conninfra_pmic_event_notifier != NULL) + g_dev_cb->conninfra_pmic_event_notifier(0, 0); + return NOTIFY_OK; +} + +static int consys_plt_pmic_event_notifier(unsigned int id, unsigned int event) +{ + static int oc_counter = 0; + + oc_counter++; + pr_info("[%s] VCN13 OC times: %d\n", __func__, oc_counter); + + consys_plt_pmic_ctrl_dump("VCN13 OC"); + return NOTIFY_OK; +} + +int consys_plt_pmic_ctrl_dump(const char* tag) +{ +#define ATOP_DUMP_NUM 10 +#define LOG_TMP_BUF_SZ 256 + int ret; + unsigned int adie_value = 0; + unsigned int value1 = 0, value2 = 0, value3 = 0; + const unsigned int adie_cr_list[ATOP_DUMP_NUM] = { + 0xa10, 0x90, 0x94, 0xa0, + 0xa18, 0xa1c, 0xc8, 0x3c, + 0x0b4, 0x34c + }; + int index; + char tmp[LOG_TMP_BUF_SZ] = {'\0'}; + char tmp_buf[LOG_TMP_BUF_SZ] = {'\0'}; + + consys_hw_is_bus_hang(); + ret = consys_hw_force_conninfra_wakeup(); + if (ret) { + pr_info("[%s] force conninfra wakeup fail\n", __func__); + return 0; + } + + value1 = CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_ADIE_CTL); + value2 = CONSYS_REG_READ(CON_REG_WT_SPL_CTL_ADDR + 0xa8); + if (consys_sema_acquire_timeout(CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_SUCCESS) { + value3 = CONSYS_REG_READ(CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_TOP_CK_EN_CTRL); + consys_sema_release(CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX); + pr_info("[%s] D-die: 0x1800_1900:0x%08x 0x1800_50A8:0x%08x 0x1805_2830:0x%08x\n", + (tag == NULL?__func__:tag), value1, value2, value3); + } else { + pr_info("[%s] D-die: 0x1800_1900:0x%08x 0x1800_50A8:0x%08x\n", + (tag == NULL?__func__:tag), value1, value2); + } + + for (index = 0; index < ATOP_DUMP_NUM; index++) { + consys_spi_read(SYS_SPI_TOP, adie_cr_list[index], &adie_value); + if (snprintf(tmp, LOG_TMP_BUF_SZ, " [0x%04x: 0x%08x]", adie_cr_list[index], adie_value) >= 0) + strncat(tmp_buf, tmp, strlen(tmp)); + } + pr_info("[%s] ATOP:%s\n", (tag == NULL?__func__:tag), tmp_buf); + consys_hw_force_conninfra_sleep(); + + return 0; +} + +int consys_plt_pmic_get_from_dts(struct platform_device *pdev, struct conninfra_dev_cb* dev_cb) +{ + int ret; + + g_dev_cb = dev_cb; +//#if CONSYS_PMIC_CTRL_ENABLE + reg_VCN13 = devm_regulator_get_optional(&pdev->dev, "vcn13"); + if (!reg_VCN13) + pr_err("Regulator_get VCN_13 fail\n"); + else { + vcn13_nb.notifier_call = consys_vcn13_oc_notify; + ret = devm_regulator_register_notifier(reg_VCN13, &vcn13_nb); + if (ret) { + pr_info("VCN13 regulator notifier request failed\n"); + } + /* Set VS2 to 1.4625V */ + KERNEL_pmic_set_register_value(PMIC_RG_BUCK_VS2_VOSEL, 0x35); + } + reg_VCN18 = regulator_get(&pdev->dev, "vcn18"); + if (!reg_VCN18) + pr_err("Regulator_get VCN_18 fail\n"); + reg_VCN33_1_BT = regulator_get(&pdev->dev, "vcn33_1_bt"); + if (!reg_VCN33_1_BT) + pr_err("Regulator_get VCN33_1_BT fail\n"); + reg_VCN33_1_WIFI = regulator_get(&pdev->dev, "vcn33_1_wifi"); + if (!reg_VCN33_1_WIFI) + pr_err("Regulator_get VCN33_1_WIFI fail\n"); + reg_VCN33_2_WIFI = regulator_get(&pdev->dev, "vcn33_2_wifi"); + if (!reg_VCN33_2_WIFI) + pr_err("Regulator_get VCN33_WIFI fail\n"); +//#endif + return 0; +} + +int consys_pmic_vcn33_1_power_ctl(bool enable, struct regulator *reg_VCN33_1) +{ + int ret; + if (enable) { + if (consys_is_rc_mode_enable()) { + /* PMRC_EN[6][5] HW_OP_EN = 1, HW_OP_CFG = 0 */ + KERNEL_pmic_ldo_vcn33_1_lp(SRCLKEN6, 0, 1, HW_OFF); + KERNEL_pmic_ldo_vcn33_1_lp(SRCLKEN5, 0, 1, HW_OFF); + /* SW_LP =0 */ + KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN33_1_LP, 0); + regulator_set_voltage(reg_VCN33_1, 3300000, 3300000); + /* SW_EN=0 */ + /* For RC mode, we don't have to control VCN33_1 & VCN33_2 */ + #if 0 + /* regulator_disable(reg_VCN33_1); */ + #endif + } else { + /* HW_OP_EN = 1, HW_OP_CFG = 0 */ + KERNEL_pmic_ldo_vcn33_1_lp(SRCLKEN0, 1, 1, HW_OFF); + /* SW_LP =0 */ + KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN33_1_LP, 0); + regulator_set_voltage(reg_VCN33_1, 3300000, 3300000); + /* SW_EN=1 */ + ret = regulator_enable(reg_VCN33_1); + if (ret) + pr_err("Enable VCN33_1 fail. ret=%d\n", ret); + } + } else { + if (consys_is_rc_mode_enable()) { + /* Do nothing */ + } else { + regulator_disable(reg_VCN33_1); + } + } + return 0; +} + +int consys_pmic_vcn33_2_power_ctl(bool enable) +{ + int ret; + + if (enable) { + if (consys_is_rc_mode_enable()) { + /* PMRC_EN[6] HW_OP_EN = 1, HW_OP_CFG = 0 */ + KERNEL_pmic_ldo_vcn33_2_lp(SRCLKEN6, 0, 1, HW_OFF); + /* SW_LP =0 */ + KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN33_2_LP, 0); + regulator_set_voltage(reg_VCN33_2_WIFI, 3300000, 3300000); + /* SW_EN=0 */ + /* For RC mode, we don't have to control VCN33_1 & VCN33_2 */ + #if 0 + regulator_disable(reg_VCN33_2_WIFI); + #endif + } else { + /* HW_OP_EN = 1, HW_OP_CFG = 0 */ + KERNEL_pmic_ldo_vcn33_2_lp(SRCLKEN0, 1, 1, HW_OFF); + /* SW_LP =0 */ + KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN33_2_LP, 0); + regulator_set_voltage(reg_VCN33_2_WIFI, 3300000, 3300000); + /* SW_EN=1 */ + ret = regulator_enable(reg_VCN33_2_WIFI); + if (ret) + pr_err("Enable VCN33_2 fail. ret=%d\n", ret); + } + } else { + if (consys_is_rc_mode_enable()) { + /* Do nothing */ + } else { + regulator_disable(reg_VCN33_2_WIFI); + } + } + return 0; +} + +int consys_plt_pmic_common_power_ctrl(unsigned int enable) +{ + int ret; + + if (enable) { + if (consys_is_rc_mode_enable()) { + /* RC mode */ + /* VCN18 */ + /* PMRC_EN[7][6][5][4] HW_OP_EN = 1, HW_OP_CFG = 0 */ + KERNEL_pmic_ldo_vcn18_lp(SRCLKEN7, 0, 1, HW_OFF); + KERNEL_pmic_ldo_vcn18_lp(SRCLKEN6, 0, 1, HW_OFF); + KERNEL_pmic_ldo_vcn18_lp(SRCLKEN5, 0, 1, HW_OFF); + KERNEL_pmic_ldo_vcn18_lp(SRCLKEN4, 0, 1, HW_OFF); + /* SW_LP =1 */ + KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN18_LP, 0); + regulator_set_voltage(reg_VCN18, 1800000, 1800000); + ret = regulator_enable(reg_VCN18); + if (ret) + pr_err("Enable VCN18 fail. ret=%d\n", ret); + + /* VCN13 */ + /* PMRC_EN[7][6][5][4] HW_OP_EN = 1, HW_OP_CFG = 0 */ + KERNEL_pmic_ldo_vcn13_lp(SRCLKEN7, 0, 1, HW_OFF); + KERNEL_pmic_ldo_vcn13_lp(SRCLKEN6, 0, 1, HW_OFF); + KERNEL_pmic_ldo_vcn13_lp(SRCLKEN5, 0, 1, HW_OFF); + KERNEL_pmic_ldo_vcn13_lp(SRCLKEN4, 0, 1, HW_OFF); + /* SW_LP =1 */ + KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN13_LP, 0); + regulator_set_voltage(reg_VCN13, 1300000, 1300000); + ret = regulator_enable(reg_VCN13); + if (ret) + pr_err("Enable VCN13 fail. ret=%d\n", ret); + + g_first_power_on = 1; + } else { + /* Legacy mode */ + /* HW_OP_EN = 1, HW_OP_CFG = 1 */ + KERNEL_pmic_ldo_vcn18_lp(SRCLKEN0, 1, 1, HW_LP); + /* SW_LP=0 */ + KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN18_LP, 0); + regulator_set_voltage(reg_VCN18, 1800000, 1800000); + /* SW_EN=1 */ + ret = regulator_enable(reg_VCN18); + if (ret) + pr_err("Enable VCN18 fail. ret=%d\n", ret); + + /* HW_OP_EN = 1, HW_OP_CFG = 1 */ + KERNEL_pmic_ldo_vcn13_lp(SRCLKEN0, 1, 1, HW_LP); + regulator_set_voltage(reg_VCN13, 1300000, 1300000); + /* SW_LP=0 */ + KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN13_LP, 0); + /* SW_EN=1 */ + ret = regulator_enable(reg_VCN13); + if (ret) + pr_err("Enable VCN13 fail. ret=%d\n", ret); + } + } else { + regulator_disable(reg_VCN13); + regulator_disable(reg_VCN18); + } + return 0; +} + +int consys_plt_pmic_wifi_power_ctrl(unsigned int enable) +{ + int ret; + + if (enable) + consys_plt_pmic_enter_idle_power_ctrl(); + + ret = consys_pmic_vcn33_1_power_ctl(enable, reg_VCN33_1_WIFI); + if (ret) + pr_err("%s VCN33_1 fail\n", (enable? "Enable" : "Disable")); + ret = consys_pmic_vcn33_2_power_ctl(enable); + if (ret) + pr_err("%s VCN33_2 fail\n", (enable? "Enable" : "Disable")); + return ret; +} + +int consys_plt_pmic_bt_power_ctrl(unsigned int enable) +{ + if (enable) { + consys_plt_pmic_exit_idle_power_ctrl(); + udelay(50); + + /* request VS2 to 1.4V by VS2 VOTER (use bit 4) */ + KERNEL_pmic_set_register_value(PMIC_RG_BUCK_VS2_VOTER_EN_SET, 0x10); + + /* Set VS2 sleep voltage to 1.375V */ + KERNEL_pmic_set_register_value(PMIC_RG_BUCK_VS2_VOSEL_SLEEP, 0x2E); + /* Set VCN13 to 1.37V */ + KERNEL_pmic_set_register_value(PMIC_RG_VCN13_VOCAL, 0x7); + udelay(50); + consys_plt_pmic_enter_idle_power_ctrl(); + } else { + consys_plt_pmic_exit_idle_power_ctrl(); + udelay(50); + /* restore VCN13 to 1.3V */ + KERNEL_pmic_set_register_value(PMIC_RG_VCN13_VOCAL, 0); + /* Restore VS2 sleep voltage to 1.35V */ + KERNEL_pmic_set_register_value(PMIC_RG_BUCK_VS2_VOSEL_SLEEP, 0x2C); + + /* clear bit 4 of VS2 VOTER then VS2 can restore to 1.35V */ + KERNEL_pmic_set_register_value(PMIC_RG_BUCK_VS2_VOTER_EN_CLR, 0x10); + udelay(50); + consys_plt_pmic_enter_idle_power_ctrl(); + } + return consys_pmic_vcn33_1_power_ctl(enable, reg_VCN33_1_BT); +} + +int consys_plt_pmic_gps_power_ctrl(unsigned int enable) +{ + if (enable) + consys_plt_pmic_enter_idle_power_ctrl(); + return 0; +} + +int consys_plt_pmic_fm_power_ctrl(unsigned int enable) +{ + if (enable) + consys_plt_pmic_enter_idle_power_ctrl(); + return 0; +} + +int consys_plt_pmic_exit_idle_power_ctrl(void) +{ + if (consys_is_rc_mode_enable() && g_first_power_on == 0) { + KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN18_LP, 0); + KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN13_LP, 0); + g_first_power_on = 1; + } + return 0; +} + +int consys_plt_pmic_enter_idle_power_ctrl(void) +{ + if (consys_is_rc_mode_enable() && g_first_power_on == 1) { + KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN18_LP, 1); + KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN13_LP, 1); + g_first_power_on = 0; + } + return 0; +} + diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/mt6885_pos.c b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/mt6885_pos.c new file mode 100644 index 0000000000000..79d0f02890054 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6885/mt6885_pos.c @@ -0,0 +1,2352 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#include "consys_hw.h" /* for semaphore index */ +/* platform dependent */ +#include "plat_def.h" +/* macro for read/write cr */ +#include "consys_reg_util.h" +#include "consys_reg_mng.h" +/* cr base address */ +#include "mt6885_consys_reg.h" +/* cr offset */ +#include "mt6885_consys_reg_offset.h" +/* For function declaration */ +#include "mt6885_pos.h" +#include "mt6885.h" +#include "mt6885_pmic.h" + +#include + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define CONN_INFRA_SYSRAM__A_DIE_DIG_TOP_CK_EN_MASK 0x7f + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +struct a_die_reg_config { + unsigned int reg; + unsigned int mask; + unsigned int config; +}; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +const static char* gAdieCtrlType[CONNSYS_ADIE_CTL_MAX] = +{ + "CONNSYS_ADIE_CTL_HOST_BT", + "CONNSYS_ADIE_CTL_HOST_FM", + "CONNSYS_ADIE_CTL_HOST_GPS", + "CONNSYS_ADIE_CTL_HOST_WIFI", + "CONNSYS_ADIE_CTL_HOST_CONNINFRA", + "CONNSYS_ADIE_CTL_FW_BT", + "CONNSYS_ADIE_CTL_FW_WIFI", +}; + +const static char* g_spi_system_name[SYS_SPI_MAX] = { + "SYS_SPI_WF1", + "SYS_SPI_WF", + "SYS_SPI_BT", + "SYS_SPI_FM", + "SYS_SPI_GPS", + "SYS_SPI_TOP", + "SYS_SPI_WF2", + "SYS_SPI_WF3", +}; + +const char* g_pos_unknown_str = "unknown"; + +#define ADIE_CONFIG_NUM 2 + +// E1 WF/GPS/FM on(default) +const static struct a_die_reg_config adie_e1_default[ADIE_CONFIG_NUM] = +{ + {ATOP_RG_TOP_XTAL_01, 0xc180, 0xc180}, + {ATOP_RG_TOP_XTAL_02, 0xf0ff0080, 0xd0550080}, +}; + +const static struct a_die_reg_config adie_e1_bt_only[ADIE_CONFIG_NUM] = +{ + {ATOP_RG_TOP_XTAL_01, 0xc180, 0x100}, + {ATOP_RG_TOP_XTAL_02, 0xf0ff0080, 0xf0ff0000}, +}; + +const static struct a_die_reg_config adie_e2_default[ADIE_CONFIG_NUM] = +{ + {ATOP_RG_TOP_XTAL_01, 0xc180, 0xc180}, + {ATOP_RG_TOP_XTAL_02, 0xf0ff0080, 0x50550080}, +}; + +const static struct a_die_reg_config adie_e2_bt_only[ADIE_CONFIG_NUM] = +{ + {ATOP_RG_TOP_XTAL_01, 0xc180, 0x100}, + {ATOP_RG_TOP_XTAL_02, 0xf0ff0080, 0x70ff0000}, +}; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static int consys_spi_read_nolock(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data); +static int consys_spi_write_nolock(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data); +static void consys_spi_write_offset_range_nolock( + enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int value, + unsigned int reg_offset, unsigned int value_offset, unsigned int size); +static int connsys_a_die_thermal_cal(int efuse_valid, unsigned int efuse); + +const char* get_adie_ctrl_type_str(enum consys_adie_ctl_type type) +{ + if (type >= CONNSYS_ADIE_CTL_HOST_BT && type < CONNSYS_ADIE_CTL_MAX) + return gAdieCtrlType[type]; + return g_pos_unknown_str; +} + +const char* get_spi_sys_name(enum sys_spi_subsystem subsystem) +{ + if (subsystem >= SYS_SPI_WF1 && subsystem < SYS_SPI_MAX) + return g_spi_system_name[subsystem]; + return g_pos_unknown_str; +} + + +unsigned int consys_emi_set_remapping_reg( + phys_addr_t con_emi_base_addr, + phys_addr_t md_shared_emi_base_addr) +{ + /* EMI Registers remapping */ + CONSYS_REG_WRITE_OFFSET_RANGE(CON_REG_HOST_CSR_ADDR + CONN2AP_REMAP_MCU_EMI_BASE_ADDR_OFFSET, + con_emi_base_addr, 0, 16, 20); + + CONSYS_REG_WRITE_MASK( + CON_REG_HOST_CSR_ADDR + CONN2AP_REMAP_WF_PERI_BASE_ADDR_OFFSET, + 0x01000, 0xFFFFF); + CONSYS_REG_WRITE_MASK( + CON_REG_HOST_CSR_ADDR + CONN2AP_REMAP_BT_PERI_BASE_ADDR_OFFSET, + 0x01000, 0xFFFFF); + CONSYS_REG_WRITE_MASK( + CON_REG_HOST_CSR_ADDR + CONN2AP_REMAP_GPS_PERI_BASE_ADDR_OFFSET, + 0x01000, 0xFFFFF); + + if (md_shared_emi_base_addr) { + CONSYS_REG_WRITE_OFFSET_RANGE( + CON_REG_HOST_CSR_ADDR + CONN2AP_REMAP_MD_SHARE_EMI_BASE_ADDR_OFFSET, + md_shared_emi_base_addr, 0, 16, 20); + } + pr_info("connsys_emi_base=[0x%llx] mcif_emi_base=[0x%llx] remap cr: connsys=[0x%08x] mcif=[0x%08x]\n", + con_emi_base_addr, md_shared_emi_base_addr, + CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN2AP_REMAP_MCU_EMI_BASE_ADDR_OFFSET), + CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN2AP_REMAP_MD_SHARE_EMI_BASE_ADDR_OFFSET)); + return 0; +} + +int consys_conninfra_on_power_ctrl(unsigned int enable) +{ + int check; + if (enable) { +#ifndef CONFIG_FPGA_EARLY_PORTING + /* Turn on SPM clock (apply this for SPM's CONNSYS power control related CR accessing) + * address: 0x1000_6000[0] + * 0x1000_6000[31:16] + * Data: [0]=1'b1 + * [31:16]=16'h0b16 (key) + * Action: write + */ + CONSYS_REG_WRITE_MASK( + CON_REG_SPM_BASE_ADDR + SPM_POWERON_CONFIG_EN, 0x0b160001, 0xffff0001); +#endif + + /* Turn on ap2conn host_ck CG (ECO) + * Address: INFRA_AP2MD_GALS_CTL[0] (0x1020E504[0]) + * Value: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CON_REG_INFRACFG_BASE_ADDR + INFRA_AP2MD_GALS_CTL, 0x1); + +#if MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE + check = consys_platform_spm_conn_ctrl(enable); + if (check) { + pr_err("Turn on conn_infra power fail\n"); + return -1; + } +#else + pr_info("Turn on conn_infra power by POS steps\n"); + /* Assert "conn_infra_on" primary part power on, set "connsys_on_domain_pwr_on"=1 + * Address: 0x1000_6304[2] + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x4); + +#ifndef CONFIG_FPGA_EARLY_PORTING + /* Check "conn_infra_on" primary part power status, check "connsys_on_domain_pwr_ack"=1 + * (polling "10 times" and each polling interval is "0.5ms") + * Address: 0x1000_616C[1] + * Data: 1'b1 + * Action: polling + */ + check = 0; + CONSYS_REG_BIT_POLLING(CON_REG_SPM_BASE_ADDR + SPM_PWR_STATUS, 1, 1, 10, 500, check); + if (check != 0) + pr_err("Check conn_infra_on primary power fail. 0x1000_616C is 0x%08x. Expect [1] as 1.\n", + CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_PWR_STATUS)); +#endif + + /* Assert "conn_infra_on" secondary part power on, set "connsys_on_domain_pwr_on_s"=1 + * Address: 0x1000_6304[3] + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x8); + +#ifndef CONFIG_FPGA_EARLY_PORTING + /* Check "conn_infra_on" secondary part power status, + * check "connsys_on_domain_pwr_ack_s"=1 + * (polling "10 times" and each polling interval is "0.5ms") + * Address: 0x1000_6170[1] + * Data: 1'b1 + * Action: polling + */ + check = 0; + CONSYS_REG_BIT_POLLING(CON_REG_SPM_BASE_ADDR + SPM_PWR_STATUS_2ND, 1, 1, 10, 500, check); + if (check != 0) + pr_err("Check conn_infra_on secondary power fail. 0x1000_6170 is 0x%08x. Expect [1] as 1.\n", + CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_PWR_STATUS_2ND)); +#endif + + /* Turn on AP-to-CONNSYS bus clock, set "conn_clk_dis"=0 + * (apply this for bus clock toggling) + * Address: 0x1000_6304[4] + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x10); + + /* Wait 1 us */ + udelay(1); + + /* De-assert "conn_infra_on" isolation, set "connsys_iso_en"=0 + * Address: 0x1000_6304[1] + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x2); + + /* De-assert CONNSYS S/W reset (TOP RGU CR), + * set "ap_sw_rst_b"=1 + * Address: WDT_SWSYSRST[9] (0x1000_7018[9]) + * WDT_SWSYSRST[31:24] (0x1000_7018[31:24]) + * Data: [9]=1'b0 + * [31:24]=8'h88 (key) + * Action: Write + */ + CONSYS_REG_WRITE_MASK( + CON_REG_TOP_RGU_ADDR + TOP_RGU_WDT_SWSYSRST,0x88000000, 0xff000200); + + /* De-assert CONNSYS S/W reset (SPM CR), set "ap_sw_rst_b"=1 + * Address: CONN_PWR_CON[0] (0x1000_6304[0]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x1); + + /* Wait 0.5ms */ + udelay(500); + + /* Disable AXI bus sleep protect */ + /* Turn off AXI RX bus sleep protect (AP2CONN AHB Bus protect) + * (apply this for INFRA AHB bus accessing when CONNSYS had been turned on) + * Address: 0x1000_1718[31:0] (INFRA_TOPAXI_PROTECTEN2_CLR) + * Data: 0x0000_0002 + * Action: write + */ + CONSYS_REG_WRITE( + CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN2_CLR_OFFSET, + 0x00000002); + +#ifndef CONFIG_FPGA_EARLY_PORTING + /* Check AHB RX bus sleep protect turn off + * (polling "100 times" and each polling interval is "0.5ms") + * Address: 0x1000_1724[2] (INFRA_TOPAXI_PROTECTEN2_STA1[2]) + * Data: 1'b0 + * Action: polling + */ + check = 0; + CONSYS_REG_BIT_POLLING( + CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN2_STA1_OFFSET, + 2, 0, 100, 500, check); + if (check != 0) + pr_err("Polling AHB RX bus sleep protect turn off fail. status=0x%08x\n", + CONSYS_REG_READ(CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN2_STA1_OFFSET)); +#endif + + /* Turn off AXI Rx bus sleep protect (CONN2AP AXI Rx Bus protect) + * (disable sleep protection when CONNSYS had been turned on) + * Note : Should turn off AHB Rx sleep protection first. + */ + CONSYS_REG_WRITE( + CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_CLR_OFFSET, + 0x00004000); +#if 0 /* POS update 20190819: Skip check */ +#ifndef CONFIG_FPGA_EARLY_PORTING + /* Check AXI Rx bus sleep protect turn off + * (polling "10 times" and each polling interval is "0.5ms") + * Address: 0x1000_1228[14] (INFRA_TOPAXI_PROTECTEN_STA1[14]) + * Data: 1'b0 + * Action: polling + */ + CONSYS_REG_BIT_POLLING( + CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1_OFFSET, + 14, 0, 10, 50, check); + if (check != 0) + pr_err("Polling AXI bus sleep protect turn off fail. Status=0x%08x\n", + CONSYS_REG_READ(CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1_OFFSET)); +#endif +#endif + /* Turn off AXI TX bus sleep protect (AP2CONN AXI Bus protect) + * (apply this for INFRA AXI bus accessing when CONNSYS had been turned on) + */ + CONSYS_REG_WRITE( + CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_CLR_OFFSET, + 0x00002000); + +#ifndef CONFIG_FPGA_EARLY_PORTING + /* Check AXI TX bus sleep protect turn off + * (polling "100 times" and each polling interval is "0.5ms") + * Address: 0x1000_1228[13] (INFRA_TOPAXI_PROTECTEN_STA1[13]) + * Data: 1'b0 + * Action: polling + */ + CONSYS_REG_BIT_POLLING( + CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1_OFFSET, + 13, 0, 100, 500, check); + if (check != 0) + pr_err("polling AHB TX bus sleep protect turn off fail. Status=0x%08x\n", + CONSYS_REG_READ(CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1_OFFSET)); +#endif +#endif /* MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE */ + /* Wait 6ms (apply this for CONNSYS XO clock ready) + * [NOTE] + * This setting could be changed at different design architecture + * and the characteristic of AFE WBG) + */ + mdelay(6); + } else { + consys_plt_pmic_ctrl_dump("CONN OFF"); + + /* Enable AXI bus sleep protect */ +#if MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE + pr_info("Turn off conn_infra power by SPM API\n"); + check = consys_platform_spm_conn_ctrl(enable); + if (check) { + pr_err("Turn off conn_infra power fail, ret=%d\n", check); + return -1; + } +#else + /* Turn on AXI TX bus sleep protect (AP2CONN AXI Bus protect) + * (apply this for INFRA AXI bus protection to prevent bus hang when + * CONNSYS had been turned off) + * Address: 0x1000_12a0[31:0] + * Data: 0x0000_2000 + * Action: write + */ + CONSYS_REG_WRITE( + CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_SET_OFFSET, + 0x00002000); + + /* check AHB TX bus sleep protect turn on (polling "100 times") + * Address: 0x1000_1228[13] + * Data: 1'b1 + * Action: polling + */ + CONSYS_REG_BIT_POLLING( + CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1_OFFSET, + 13, 1, 100, 500, check); + if (check) + pr_err("Polling AHB TX bus sleep protect turn on fail.\n"); + + /* Turn on AXI Rx bus sleep protect (CONN2AP AXI RX Bus protect) + * (apply this for INFRA AXI bus protection to prevent bus hang when + * CONNSYS had been turned off) + * Note: + * Should turn on AXI Rx sleep protection after + * AXI Tx sleep protection has been turn on. + * Address: 0x1000_12A0[31:0] + * Data: 0x0000_4000 + * Action: write + */ + CONSYS_REG_WRITE( + CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_SET_OFFSET, + 0x00004000); + + /* check AXI Rx bus sleep protect turn on + * (polling "100 times", polling interval is 1ms) + * Address: 0x1000_1228[14] + * Data: 1'b1 + * Action: polling + */ + CONSYS_REG_BIT_POLLING( + CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1_OFFSET, + 14, 1, 100, 1000, check); + if (check) + pr_err("Polling AXI Rx bus sleep protect turn on fail.\n"); + + /* Turn on AXI RX bus sleep protect (AP2CONN AXI Bus protect) + * (apply this for INFRA AXI bus protection to prevent bus hang when + * CONNSYS had been turned off) + * Address: 0x1000_1714[31:0] (INFRA_TOPAXI_PROTECTEN2_SET) + * Data: 0x0000_0002 + * Action: write + */ + CONSYS_REG_WRITE( + CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN2_SET_OFFSET, + 0x00000002); + /* check AHB RX bus sleep protect turn on (polling "10 times") + * Address: 0x1000_1724[2] (INFRA_TOPAXI_PROTECTEN2_STA1[2]) + * Value: 1'b1 + * Action: polling + */ + CONSYS_REG_BIT_POLLING( + CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN2_STA1_OFFSET, + 2, 1, 10, 1000, check); + if (check) + pr_err("Polling AHB RX bus sleep protect turn on fail.\n"); + + /* Assert "conn_infra_on" isolation, set "connsys_iso_en"=1 + * Address: CONN_PWR_CON[1] (0x1000_6304[1]) + * Value: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x2); + + /* Assert CONNSYS S/W reset (SPM CR), set "ap_sw_rst_b"=0 + * Address: CONN_PWR_CON[0] (0x1000_6304[0]) + * Value: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x1); + + /* Assert CONNSYS S/W reset(TOP RGU CR), set "ap_sw_rst_b"=0 + * Address: WDT_SWSYSRST[9] (0x1000_7018[9]) + * WDT_SWSYSRST[31:24] (0x1000_7018[31:24]) + * Value: [9]=1'b1 + * [31:24]=8'h88 (key) + * Action: write + * Note: this CR value for reset control is active high (0: not reset, 1: reset) + */ + CONSYS_REG_WRITE_MASK( + CON_REG_TOP_RGU_ADDR + TOP_RGU_WDT_SWSYSRST, + 0x88000200, + 0xff000200); + + /* Turn off AP-to-CONNSYS bus clock, set "conn_clk_dis"=1 + * (apply this for bus clock gating) + * Address: CONN_PWR_CON[4] (0x1000_6304[4]) + * Value: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x10); + + /* wait 1us (?) */ + udelay(1); + + /* De-assert "conn_infra_on" primary part power on, + * set "connsys_on_domain_pwr_on"=0 + * Address: CONN_PWR_CON[2] (0x1000_6304[2]) + * Value: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x4); + + /* De-assert "conn_infra_on" secondary part power on, + * set "connsys_on_domain_pwr_on_s"=0 + * Address: CONN_PWR_CON[3] (0x1000_6304[3]) + * Value: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x8); +#endif /* MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE */ + + /* Turn off ap2conn host_ck CG (ECO) + * Address: INFRA_AP2MD_GALS_CTL[0] (0x1020E504[0]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CON_REG_INFRACFG_BASE_ADDR + INFRA_AP2MD_GALS_CTL, 0x1); + } + return 0; +} + +int consys_conninfra_wakeup(void) +{ + int check, r1, r2; + unsigned int retry = 10; + unsigned int consys_hw_ver = 0; + int polling_fail_retry = 2; + unsigned long polling_fail_delay = 20000; /* 20ms */ + + /* Wake up conn_infra + * Address: CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP (0x180601a0) + * Data: 1'b1 + * Action: write + */ + CONSYS_REG_WRITE( + CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP, + 0x1); + + /* Check ap2conn slpprot_rdy + * (polling "10 times" for specific project code and each polling interval is "1ms") + * Address: CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL_CONN_INFRA_ON2OFF_SLP_PROT_ACK (0x1806_0184[5]) + * Data: 1'b0 + * Action: polling + */ + while (polling_fail_retry > 0) { + check = 0; + CONSYS_REG_BIT_POLLING( + CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL, 5, 0, 10, 1000, check); + + if (check) { + pr_err("[%s] Check ap2conn slpprot_rdy fail. value=0x%x WAKEUP_TOP=[0x%x]\n", + __func__, + CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL), + CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP)); + } + + if (consys_reg_mng_reg_readable() == 0) { + check = consys_reg_mng_is_bus_hang(); + r1 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_3); + r2 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP); + pr_info("[%s] check=[%d] r1=[0x%x] r2=[0x%x]", __func__, check, r1, r2); + consys_reg_mng_dump_cpupcr(CONN_DUMP_CPUPCR_TYPE_ALL, 10, 200); + if (check > 0) { + return -1; + } + check = -1; + } + + if (check == 0) + break; + + /* delay 20 ms */ + usleep_range(polling_fail_delay - 200, polling_fail_delay + 200); + polling_fail_retry--; + } + + if (check != 0) { + pr_err("[%s] wakeup fail retry %d", __func__, polling_fail_retry); + return -1; + } + + /* Check CONNSYS version ID + * (polling "10 times" for specific project code and each polling interval is "1ms") + * Address: CONN_HW_VER (0x1800_1000[31:0]) + * Data: 32'h2001_0000 + * Action: polling + */ + check = 0; + while (retry-- > 0) { + consys_hw_ver = CONSYS_REG_READ( + CON_REG_INFRA_CFG_ADDR + + CONN_HW_VER_OFFSET); + if (consys_hw_ver == CONN_HW_VER) { + check = 0; + pr_info("[%s] Polling chip id success (0x%x)\n", __func__, consys_hw_ver); + break; + } + check = -1; + } + if (check != 0) + pr_err("[%s] Polling chip id fail (0x%x)\n", __func__, consys_hw_ver); + + return check; +} + +int consys_conninfra_sleep(void) +{ + /* Release conn_infra force on + * Address: CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP (0x180601a0) + * Data: 1'b0 + * Action: write + */ + CONSYS_REG_WRITE( + CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP, + 0x0); + + return 0; +} + +void consys_set_if_pinmux(unsigned int enable) +{ +#ifndef CONFIG_FPGA_EARLY_PORTING + if (enable) { + /* Set pinmux for the interface between D-die and A-die + * (CONN_HRST_B / CONN_TOP_CLK / CONN_TOP_DATA / CONN_WB_PTA / + * CONN_BT_CLK / CONN_BT_DATA / CONN_WF_CTRL0 / CONN_WF_CTRL1 / + * CONN_WF_CTRL2 / CONN_WF_CTRL3 / CONN_WF_CTRL4) + */ + /* GPIO 172: 0x1000_5450[18:16] */ + /* GPIO 173: 0x1000_5450[22:20] */ + /* GPIO 174: 0x1000_5450[26:24] */ + /* GPIO 175: 0x1000_5450[30:28] */ + CONSYS_REG_WRITE_MASK(GPIO_BASE_ADDR + GPIO_MODE21, 0x11110000, 0xffff0000); + + /* GPIO 176: 0x1000_5460[2:0] */ + /* GPIO 177: 0x1000_5460[6:4] */ + /* GPIO 178: 0x1000_5460[10:8] */ + /* GPIO 179: 0x1000_5460[14:12] */ + /* GPIO 180: 0x1000_5460[18:16] */ + /* GPIO 181: 0x1000_5460[22:20] */ + /* GPIO 182: 0x1000_5460[26:24] */ + CONSYS_REG_WRITE_MASK(GPIO_BASE_ADDR + GPIO_MODE22, 0x01111111, 0x0fffffff); + + /* Set pinmux driving to 2mA + * Address: + * 0x11EA_0000[5:3]/0x11EA_0000[8:6]/0x11EA_0000[11:9] + * 0x11EA_0000[14:12]/0x11EA_0000[17:15] + * Data: 3'b000 + * Action: write + * Note: IOCFG_RT + */ + CONSYS_REG_WRITE_MASK(IOCFG_RT_ADDR + IOCFG_RT_DRV_CFG0, 0x0, 0x3fff8); + + /* Set CONN_TOP_CLK/CONN_TOP_DATA/CONN_BT_CLK/CONN_BT_DATA driving to 4mA + * (CONN_TOP_DATA driving config is the same position with + * CONN_WF_CTRL0/CONN_WF_CTRL1/CONN_WF_CTRL2/CONN_WF_CTRL3/CONN_WF_CTRL4) + * Address: + * CONN_TOP_CLK 0x11EA_0000[17:15] = 3b'001 + * CONN_TOP_DATA 0x11EA_0000[5:3] = 3b'001 + * CONN_BT_CLK 0x11EA_0000[8:6] = 3b'001 + * CONN_BT_DATA 0x11EA_0000[11:9] = 3b'001 + * Action: write + */ + CONSYS_REG_WRITE_MASK(IOCFG_RT_ADDR + IOCFG_RT_DRV_CFG0, 0x8248, 0x38ff8); + + /* Set pinmux PUPD setting + * Clear CONN_TOP_DATA/CONN_BT_DATA PD setting + * Address: 0x11EA_0058[14][11] + * Data: 2'b11 + * Action: write + * Note: IOCFG_RT + */ + CONSYS_REG_WRITE_MASK(IOCFG_RT_ADDR + IOCFG_RT_PD_CFG0_CLR, 0x4800, 0x4800); + + /* Set pinmux PUPD + * Setting CONN_TOP_DATA/CONN_BT_DATA as PU + * Address: 0x11EA_0074[14][11] + * Data: 2'b11 + * Action: write + * Note: IOCFG_RT + */ + CONSYS_REG_WRITE_MASK(IOCFG_RT_ADDR + IOCFG_RT_PU_CFG0_SET, 0x4800, 0x4800); + + /* If TCXO mode, set GPIO155 pinmux for TCXO mode (AUX4) + * (CONN_TCXOENA_REQ) + * Address: 0x1000_5430[14:12] + * Data: 3'b100 + * Action: write + */ + if (consys_co_clock_type() == CONNSYS_CLOCK_SCHEMATIC_26M_EXTCXO) { + /* TODO: need customization for TCXO GPIO */ + CONSYS_REG_WRITE_MASK(GPIO_BASE_ADDR + GPIO_MODE19, 0x4000, 0x7000); + } + } else { + /* Set pinmux for the interface between D-die and A-die (Aux0) + * Address: + * 0x1000_5450[26:24]/0x1000_5450[18:16]/0x1000_5450[22:20] + * 0x1000_5450[30:28]/0x1000_5460[2:0]/0x1000_5460[6:4] + * 0x1000_5460[10:8]/0x1000_5460[14:12]/0x1000_5460[18:16] + * 0x1000_5460[22:20]/0x1000_5460[26:24] + * Data: 3'b000 + * Action: write + */ + CONSYS_REG_WRITE_MASK(GPIO_BASE_ADDR + GPIO_MODE21, 0x0, 0xffff0000); + CONSYS_REG_WRITE_MASK(GPIO_BASE_ADDR + GPIO_MODE22, 0x0, 0x0fffffff); + + /* Set pinmux PUPD setting + * Clear CONN_TOP_DATA/CONN_BT_DATA PU setting + * Address: 0x11EA_0078[14][11] + * Data: 2'b11 + * Action: write + */ + CONSYS_REG_WRITE_MASK(IOCFG_RT_ADDR + IOCFG_RT_PU_CFG0_CLR, 0x4800, 0x4800); + + /* Set pinmux PUPD setting + * CONN_TOP_DATA/CONN_BT_DATA as PD + * Address: 0x11EA_0054[14][11] + * Data: 2'b11 + *Action: write + */ + CONSYS_REG_WRITE_MASK(IOCFG_RT_ADDR + IOCFG_RT_PD_CFG0_SET, 0x4800, 0x4800); + + /* If TCXO mode, set GPIO155 pinmux to GPIO mode + * Address: 0x1000_5430[14:12] + * Data: 3'b000 + * Action: write + */ + if (consys_co_clock_type() == CONNSYS_CLOCK_SCHEMATIC_26M_EXTCXO) { + CONSYS_REG_WRITE_MASK(GPIO_BASE_ADDR + GPIO_MODE19, 0x0, 0x7000); + } + } +#else + pr_info("[%s] not for FPGA\n", __func__); +#endif +} + +int consys_polling_chipid(void) +{ + unsigned int retry = 11; + unsigned int consys_hw_ver = 0; + unsigned int consys_configuration_id = 0; + int ret = -1; + int check; + + /* Check ap2conn slpprot_rdy + * (polling "10 times" for specific project code and each polling interval is "1ms") + * Address: + * CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL_CONN_INFRA_ON2OFF_SLP_PROT_ACK + * 0x1806_0184[5] + * Value: 1'b0 + * Action: polling + * Note: deadfeed CDC issue + */ + check = 0; + CONSYS_REG_BIT_POLLING( + CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL, 5, 0, 10, 1000, check); + if (check) { + pr_err("[%s] Check ap2conn slpprot_rdy fail. value=0x%x WAKEUP_TOP=[0x%x]\n", + __func__, + CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL), + CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP)); + } + + while (--retry > 0) { + consys_hw_ver = CONSYS_REG_READ( + CON_REG_INFRA_CFG_ADDR + + CONN_HW_VER_OFFSET); + if (consys_hw_ver == CONN_HW_VER) { + consys_configuration_id = CONSYS_REG_READ( + CON_REG_INFRA_CFG_ADDR + CONN_CFG_ID_OFFSET); + pr_info("Consys HW version id(0x%x) cfg_id=(0x%x)\n", + consys_hw_ver, consys_configuration_id); + ret = 0; + break; + } + msleep(20); + } + + if (retry == 0) { + pr_err("Read CONSYS version id fail. Expect 0x%x but get 0x%x\n", + CONN_HW_VER, consys_hw_ver); + return -1; + } + + /* Disable conn_infra deadfeed function(workaround) + * Address: CONN_HOST_CSR_TOP_CSR_DEADFEED_EN_CR_AP2CONN_DEADFEED_EN (0x1806_0124[0]) + * Data: 1'b0 + * Action: write + * Note: workaround for deadfeed CDC issue + */ + CONSYS_CLR_BIT(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CSR_DEADFEED_EN_CR, 0x1); + +#ifdef CONFIG_FPGA_EARLY_PORTING + /* For FPGA workaround */ + CONSYS_SET_BIT(CON_REG_INFRA_CFG_ADDR + 0x0c04, + ((0x1 << 1) | (0x1 << 9) | (0x1 << 17) | (0x1 << 25))); + pr_info("Workaround for FPGA: Check %x\n", CON_REG_INFRA_CFG_ADDR + 0x0c04); +#endif + + return ret; +} + +int connsys_d_die_cfg(void) +{ + /* Read D-die Efuse + * Address: AP2CONN_EFUSE_DATA (0x1800_1818) + * Data: + * Action: read + */ + CONSYS_REG_WRITE( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_D_DIE_EFUSE, + CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + AP2CONN_EFUSE_DATA)); + + /* Request from MCU, pass build type to FW + * 1: eng build + * 2: userdebug build + * 3: user build + */ +#if defined(CONNINFRA_PLAT_BUILD_MODE) + CONSYS_REG_WRITE( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_BUILD_MODE, + CONNINFRA_PLAT_BUILD_MODE); + pr_info("Write CONN_INFRA_SYSRAM_SW_CR_BUILD_MODE to 0x%08x\n", + CONSYS_REG_READ(CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_BUILD_MODE)); +#endif + + /* conn_infra sysram hw control setting -> disable hw power down + * Address: CONN_INFRA_RGU_SYSRAM_HWCTL_PDN_SYSRAM_HWCTL_PDN (0x1800_0038) + * Data: 32'h0 + * Action: write + */ + CONSYS_REG_WRITE(CON_REG_INFRA_RGU_ADDR + CONN_INFRA_RGU_SYSRAM_HWCTL_PDN, 0x0); + + /* conn_infra sysram hw control setting -> enable hw sleep + * Address: CONN_INFRA_RGU_SYSRAM_HWCTL_SLP_SYSRAM_HWCTL_SLP (0x1800_003C) + * Data: 32'h0000_00FF + * Action: write + */ + CONSYS_REG_WRITE(CON_REG_INFRA_RGU_ADDR + CONN_INFRA_RGU_SYSRAM_HWCTL_SLP, 0x000000ff); + + /* co-ext memory hw control setting -> disable hw power down + * Address: CONN_INFRA_RGU_CO_EXT_MEM_HWCTL_PDN_CO_EXT_MEM_HWCTL_PDN (0x1800_0050) + * Data: 32'h0 + * Action: write + */ + CONSYS_REG_WRITE(CON_REG_INFRA_RGU_ADDR + CONN_INFRA_RGU_CO_EXT_MEM_HWCTL_PDN, 0x0); + + /* co-ext memory hw control setting -> enable hw sleep + * Address: CONN_INFRA_RGU_CO_EXT_MEM_HWCTL_SLP_CO_EXT_MEM_HWCTL_SLP (0x1800_0054) + * Data: 32'h0000_0001 + * Action: write + */ + CONSYS_REG_WRITE(CON_REG_INFRA_RGU_ADDR + CONN_INFRA_RGU_CO_EXT_MEM_HWCTL_SLP, 0x1); + + return 0; +} + +int connsys_spi_master_cfg(unsigned int next_status) +{ + unsigned int bt_only = 0; + + if ((next_status & (~(0x1 << CONNDRV_TYPE_BT))) == 0) + bt_only = 1; + + /* CONN_WT_SLP_CTL_REG_WB_WF_CK_ADDR_ADDR(0x070) = 0x0AF40A04 + * CONN_WT_SLP_CTL_REG_WB_WF_WAKE_ADDR_ADDR(0x74) = 0x00A00090 + * CONN_WT_SLP_CTL_REG_WB_WF_ZPS_ADDR_ADDR(0x78) = 0x009c008c + * CONN_WT_SLP_CTL_REG_WB_BT_CK_ADDR_ADDR(0x7c[11:0]) = 0xa08 + * CONN_WT_SLP_CTL_REG_WB_BT_WAKE_ADDR_ADDR(0x80[11:0]) = 0x094 + * CONN_WT_SLP_CTL_REG_WB_TOP_CK_ADDR_ADDR(0x84[11:0]) = 0x02c + * CONN_WT_SLP_CTL_REG_WB_GPS_CK_ADDR_ADDR(0x88) = 0x0AFC0A0C + * CONN_WT_SLP_CTL_REG_WB_WF_B0_CMD_ADDR_ADDR(0x8c[11:0]) = 0x0F0 + * CONN_WT_SLP_CTL_REG_WB_WF_B1_CMD_ADDR_ADDR(0x90[11:0]) = 0x0F4 + * CONN_WT_SLP_CTL_REG_WB_GPS_RFBUF_ADDR(0x18005094[11:0]) = 0x0FC + * CONN_WT_SLP_CTL_REG_WB_GPS_L5_EN_ADDR(0x18005098[11:0]) = 0x0F8 + */ + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_WF_CK_ADDR, 0x0AF40A04); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_WF_WAKE_ADDR, 0x00A00090); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_WF_ZPS_ADDR, 0x009C008C); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BT_CK_ADDR, + 0xa08, 0xfff); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BT_WAKE_ADDR, + 0x094, 0xfff); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_TOP_CK_ADDR, + 0x02c, 0xfff); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_GPS_CK_ADDR, + 0x0AFC0A0C); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_WF_B0_CMD_ADDR, + 0x0f0, 0xfff); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_WF_B1_CMD_ADDR, + 0x0f4, 0xfff); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_GPS_RFBUF_ADDR, + 0x0FC, 0xfff); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_GPS_L5_EN_ADDR, + 0x0F8, 0xfff); + + /* CONN_WT_SLP_CTL_REG_WB_SLP_CTL_CMD_LENGTH(0x004[4:0]) = 0x8 + * CONN_WT_SLP_CTL_REG_WB_BG_ADDR1_WB_BG_ADDR1(0x10[15:0]) = 0xA03C + * CONN_WT_SLP_CTL_REG_WB_BG_ADDR2_WB_BG_ADDR2(0x14[15:0]) = 0xA03C + * CONN_WT_SLP_CTL_REG_WB_BG_ADDR3_WB_BG_ADDR3(0x18[15:0]) = 0xAA18 + * CONN_WT_SLP_CTL_REG_WB_BG_ADDR4_WB_BG_ADDR4(0x1c[15:0]) = 0xAA18 + * CONN_WT_SLP_CTL_REG_WB_BG_ADDR5_WB_BG_ADDR5(0x20[15:0]) = 0xA0C8 + * CONN_WT_SLP_CTL_REG_WB_BG_ADDR6_WB_BG_ADDR6(0x24[15:0]) = 0xAA00 + * CONN_WT_SLP_CTL_REG_WB_BG_ADDR7_WB_BG_ADDR7(0x28[15:0]) = 0xA0B4 + * CONN_WT_SLP_CTL_REG_WB_BG_ADDR8_WB_BG_ADDR8(0x2c[15:0]) = 0xA34C + * CONN_WT_SLP_CTL_REG_WB_BG_ON1_WB_BG_ON1(0x30) = 0x00000000 + * CONN_WT_SLP_CTL_REG_WB_BG_ON2_WB_BG_ON2(0x34) = 0x00000000 + * if (BT_only) { + * CONN_WT_SLP_CTL_REG_WB_BG_ON3_WB_BG_ON3(0x38) = 0x74E03F75 + * CONN_WT_SLP_CTL_REG_WB_BG_ON4_WB_BG_ON4(0x3c) = 0x76E83F75 + * } else { + * CONN_WT_SLP_CTL_REG_WB_BG_ON3_WB_BG_ON3(0x38) = 0x74E0FFF5 + * CONN_WT_SLP_CTL_REG_WB_BG_ON4_WB_BG_ON4(0x3c) = 0x76E8FFF5 + * } + * CONN_WT_SLP_CTL_REG_WB_BG_ON5_WB_BG_ON5(0x40) = 0x00000000 + * CONN_WT_SLP_CTL_REG_WB_BG_ON6_WB_BG_ON6(0x44) = 0xFFFFFFFF + * CONN_WT_SLP_CTL_REG_WB_BG_ON7_WB_BG_ON7(0x48) = 0x00000019 + * CONN_WT_SLP_CTL_REG_WB_BG_ON8_WB_BG_ON8(0x4c) = 0x00010400 + * CONN_WT_SLP_CTL_REG_WB_BG_OFF1_WB_BG_OFF1(0x50) = 0x57400000 + * CONN_WT_SLP_CTL_REG_WB_BG_OFF2_WB_BG_OFF2(0x54) = 0x57400000 + * if (BT only) { + * CONN_WT_SLP_CTL_REG_WB_BG_OFF3_WB_BG_OFF3(0x58) = 0x44E03F75 + * CONN_WT_SLP_CTL_REG_WB_BG_OFF4_WB_BG_OFF4(0x5c) = 0x44E03F75 + * } else { + * CONN_WT_SLP_CTL_REG_WB_BG_OFF3_WB_BG_OFF3(0x58) = 0x44E0FFF5 + * CONN_WT_SLP_CTL_REG_WB_BG_OFF4_WB_BG_OFF4(0x5c) = 0x44E0FFF5 + * } + * CONN_WT_SLP_CTL_REG_WB_BG_OFF5_WB_BG_OFF5(0x60) = 0x00000001 + * CONN_WT_SLP_CTL_REG_WB_BG_OFF6_WB_BG_OFF6(0x64) = 0x00000000 + * CONN_WT_SLP_CTL_REG_WB_RG_OFF7_WB_BG_OFF7(0x68) = 0x00040019 + * CONN_WT_SLP_CTL_REG_WB_RG_OFF8_WB_BG_OFF8(0x6c) = 0x00410440 + */ + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_SLP_CTL, + 0x8, 0x1f); + + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR1, + 0xa03c, 0xffff); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR2, + 0xa03c, 0xffff); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR3, + 0xaa18, 0xffff); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR4, + 0xaa18, 0xffff); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR5, + 0xa0c8, 0xffff); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR6, + 0xaa00, 0xffff); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR7, + 0xa0b4, 0xffff); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR8, + 0xa34c, 0xffff); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON1, 0x00000000); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON2, 0x00000000); + if (bt_only) { + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON3, 0x74E03F75); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON4, 0x76E83F75); + } else { + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON3, 0x74E0fff5); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON4, 0x76E8FFF5); + } + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON5, 0x00000000); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON6, 0xFFFFFFFF); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON7, 0x00000019); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON8, 0x00010400); + + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF1, 0x57400000); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF2, 0x57400000); + if (bt_only) { + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF3, 0x44E03F75); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF4, 0x44E03F75); + } else { + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF3, 0x44e0fff5); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF4, 0x44e0fff5); + } + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF5, 0x00000001); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF6, 0x00000000); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF7, 0x00040019); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF8, 0x00410440); + + return 0; +} + +//#ifndef CONFIG_FPGA_EARLY_PORTING +/***************************************************************************** +* FUNCTION +* connsys_a_die_efuse_read +* DESCRIPTION +* Read a-die efuse +* PARAMETERS +* efuse_addr: read address +* RETURNS +* int +* 0: fail, efuse is invalid +* 1: success, efuse is valid +*****************************************************************************/ +static int connsys_a_die_efuse_read(unsigned int efuse_addr) +{ + int ret = 0; + int retry = 0; + unsigned int efuse0 = 0, efuse1 = 0, efuse2 = 0, efuse3 = 0; + int ret0, ret1, ret2, ret3; + + /* Get semaphore before read */ + if (consys_sema_acquire_timeout(CONN_SEMA_RFSPI_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) { + pr_err("[EFUSE READ] Require semaphore fail\n"); + return 0; + } + + /* Efuse control clear, clear Status /trigger + * Address: ATOP EFUSE_CTRL_write_efsrom_kick_and_read_kick_busy_flag (0x108[30]) + * Data: 1'b0 + * Action: TOPSPI_WR + */ + consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, &ret); + ret &= ~(0x1 << 30); + consys_spi_write_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, ret); + + /* Efuse Read 1st 16byte + * Address: + * ATOP EFUSE_CTRL_efsrom_mode (0x108[7:6]) = 2'b00 + * ATOP EFUSE_CTRL_efsrom_ain (0x108[25:16]) = efuse_addr (0) + * ATOP EFUSE_CTRL_write_efsrom_kick_and_read_kick_busy_flag (0x108[30]) = 1'b1 + * Action: TOPSPI_WR + */ + consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, &ret); + ret &= ~(0x43ff00c0); + ret |= (0x1 << 30); + ret |= ((efuse_addr << 16) & 0x3ff0000); + consys_spi_write_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, ret); + + /* Polling EFUSE busy = low + * (each polling interval is "30us" and polling timeout is 2ms) + * Address: + * ATOP EFUSE_CTRL_write_efsrom_kick_and_read_kick_busy_flag (0x108[30]) = 1'b0 + * Action: TOPSPI_Polling + */ + consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, &ret); + while ((ret & (0x1 << 30)) != 0 && retry < 70) { + retry++; + udelay(30); + consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, &ret); + } + if ((ret & (0x1 << 30)) != 0) { + pr_info("[%s] EFUSE busy, retry failed(%d)\n", __func__, retry); + } + + /* Check efuse_valid & return + * Address: ATOP EFUSE_CTRL_csri_efsrom_dout_vld_sync_1_ (0x108[29]) + * Action: TOPSPI_RD + */ + /* if (efuse_valid == 1'b1) + * Read Efuse Data to global var + */ + consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, &ret); + if (((ret & (0x1 << 29)) >> 29) == 1) { + ret0 = consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_RDATA0, &efuse0); + + CONSYS_REG_WRITE( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_0, + efuse0); + + ret1 = consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_RDATA1, &efuse1); + CONSYS_REG_WRITE( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_1, + efuse1); + /* Sub-task: thermal cal */ + connsys_a_die_thermal_cal(1, efuse1); + + ret2 = consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_RDATA2, &efuse2); + CONSYS_REG_WRITE( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_2, + efuse2); + + ret3 = consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_RDATA3, &efuse3); + CONSYS_REG_WRITE( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_3, + efuse3); + + pr_info("efuse = [0x%08x, 0x%08x, 0x%08x, 0x%08x]", efuse0, efuse1, efuse2, efuse3); + if (ret0 || ret1 || ret2 || ret3) + pr_err("efuse read error: [%d, %d, %d, %d]", ret0, ret1, ret2, ret3); + ret = 1; + } else { + connsys_a_die_thermal_cal(0, 0); + pr_err("EFUSE is invalid\n"); + ret = 0; + } + + consys_sema_release(CONN_SEMA_RFSPI_INDEX); + return ret; +} + +static int connsys_a_die_thermal_cal(int efuse_valid, unsigned int efuse) +{ + struct consys_plat_thermal_data input; + memset(&input, 0, sizeof(struct consys_plat_thermal_data)); + + if (efuse_valid) { + if (efuse & (0x1 << 7)) { + consys_spi_write_offset_range_nolock( + SYS_SPI_TOP, ATOP_RG_TOP_THADC_BG, efuse, 12, 3, 4); + consys_spi_write_offset_range_nolock( + SYS_SPI_TOP, ATOP_RG_TOP_THADC, efuse, 23, 0, 3); + } + if(efuse & (0x1 << 15)) { + consys_spi_write_offset_range_nolock( + SYS_SPI_TOP, ATOP_RG_TOP_THADC, efuse, 26, 13, 2); + input.slop_molecule = (efuse & 0x1f00) >> 8; + pr_info("slop_molecule=[%d]", input.slop_molecule); + } + if (efuse & (0x1 << 23)) { + /* [22:16] */ + input.thermal_b = (efuse & 0x7f0000) >> 16; + pr_info("thermal_b =[%d]", input.thermal_b); + } + if (efuse & (0x1 << 31)) { + input.offset = (efuse & 0x7f000000) >> 24; + pr_info("offset=[%d]", input.offset); + } + } + update_thermal_data(&input); + return 0; +} +//#endif + +int connsys_a_die_cfg(void) +{ + int efuse_valid; + bool adie_26m = true; + unsigned int adie_id = 0; + + if (consys_co_clock_type() == CONNSYS_CLOCK_SCHEMATIC_52M_COTMS) { + pr_info("A-die clock 52M\n"); + adie_26m = false; + } + /* First time to setup conninfra sysram, clean it. */ + memset_io( + (volatile void*)CONN_INFRA_SYSRAM_BASE_ADDR, + 0x0, + CONN_INFRA_SYSRAM_SIZE); + + + /* if(A-die XTAL = 26MHz ) { + * CONN_WF_CTRL2 swtich to GPIO mode, GPIO output value + * before patch download swtich back to CONN mode. + * } + */ + /* Address: + * 0x1000_5054 = 32'h0010_0000 + * 0x1000_5154 = 32'h0010_0000 + * 0x1000_5460[18:16] = 3'b000 + * Actin: write + * Note: MT6635 strap pinmux, set CONN_WF_CTRL2 as GPIO + */ + if (adie_26m) { + CONSYS_REG_WRITE(GPIO_BASE_ADDR + GPIO_DIR5_SET, 0x00100000); + CONSYS_REG_WRITE(GPIO_BASE_ADDR + GPIO_DOUT5_SET, 0x00100000); + CONSYS_REG_WRITE_MASK(GPIO_BASE_ADDR + GPIO_MODE22, 0x0, 0x70000); + } + /* sub-task: a-die cfg */ + /* De-assert A-die reset + * Address: CONN_INFRA_CFG_ADIE_CTL_ADIE_RSTB (0x18001900[0]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_ADIE_CTL, 0x1); + + /* Read MT6635 ID + * Address: ATOP CHIP_ID + * 0x02C[31:16]: hw_code + * 0x02C[15:0]: hw_ver + * Data: + * MT6635 E1 : read 0x02C = 0x66358A00 + * MT6635 E2 : read 0x02C = 0x66358A10 + * MT6635 E3 : read 0x02C = 0x66358A11 + * Action: TOPSPI_RD + */ + consys_spi_read(SYS_SPI_TOP, ATOP_CHIP_ID, &adie_id); + conn_hw_env.adie_hw_version = adie_id; + conn_hw_env.is_rc_mode = consys_is_rc_mode_enable(); + pr_info("A-die CHIP_ID=0x%08x rc=%d\n", adie_id, conn_hw_env.is_rc_mode); + + CONSYS_REG_WRITE( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_CHIP_ID, + adie_id); + + /* Patch to FW from 7761(WF0_WRI_SX_CAL_MAP/WF1_WRI_SX_CAL_MAP) + * Address: ATOP WRI_CTR2 (0x064) + * Data: 32'h00007700 + * Action: TOPSPI_WR + */ + consys_spi_write(SYS_SPI_TOP, ATOP_WRI_CTR2, 0x00007700); + + /* Set WF low power cmd as DBDC mode & legacy interface + * Address: ATOP SMCTK11 (0x0BC) + * Data: 32'h00000021 + * Action: TOPSPI_WR + */ + consys_spi_write(SYS_SPI_TOP, ATOP_SMCTK11, 0x00000021); + + /* Update spi fm read extra bit setting + * Address: + * CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_EN (0x1800400C[15]) + * CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_CNT (0x1800400C[7:0]) + * Data: + * 0x1800400C[15] = 1'b0 + * 0x1800400C[7:0] = 8'h0 + * Action: write + */ + CONSYS_REG_WRITE_MASK( + CONN_REG_RFSPI_ADDR + CONN_RF_SPI_MST_REG_FM_CTRL, 0x0, 0x80ff); + + /* Update Thermal addr for 6635 + * Address: CONN_TOP_THERM_CTL_THERM_AADDR (0x18002018) + * Data: 32'h50305A00 + * Action: write + */ + CONSYS_REG_WRITE(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_AADDR, 0x50305A00); + + /* Sub-task: read a-die efuse */ + efuse_valid = connsys_a_die_efuse_read(0); + + /* Set WF_PAD to HighZ + * Address: ATOP RG_ENCAL_WBTAC_IF_SW (0x070) + * Data: 32'h80000000 + * Action: TOPSPI_WR + */ + consys_spi_write(SYS_SPI_TOP, ATOP_RG_ENCAL_WBTAC_IF_SW, 0x80000000); + + /* Disable CAL LDO + * Address: ATOP RG_WF0_TOP_01 (0x380) + * Data: 32'h000E8002 + * Action: TOPSPI_WR + * Note: AC mode + */ + consys_spi_write(SYS_SPI_TOP, ATOP_RG_WF0_TOP_01, 0x000e8002); + + /* Disable CAL LDO + * Address: ATOP RG_WF1_TOP_01 (0x390) + * Data: 32'h000E8002 + * Action: TOPSPI_WR + * Note: AC mode + */ + consys_spi_write(SYS_SPI_TOP, ATOP_RG_WF1_TOP_01, 0x000e8002); + + /* Increase XOBUF supply-V + * Address: ATOP RG_TOP_XTAL_01 (0xA18) + * Data: 32'hF6E8FFF5 + * Action: TOPSPI_WR + */ + consys_spi_write(SYS_SPI_TOP, ATOP_RG_TOP_XTAL_01, 0xF6E8FFF5); + + /* Increase XOBUF supply-R for MT6635 E1 + * Address: ATOP RG_TOP_XTAL_02 (0xA1C) + * Data: + * if(MT6635 E1) //rf_hw_ver = 0x8a00 + * 32'hD5555FFF + * else + * 32'h0x55555FFF + * Action: TOPSPI_WR + */ + if (adie_id == 0x66358a00) { + consys_spi_write(SYS_SPI_TOP, ATOP_RG_TOP_XTAL_02, 0xD5555FFF); + } else { + consys_spi_write(SYS_SPI_TOP, ATOP_RG_TOP_XTAL_02, 0x55555FFF); + } + + /* Initial IR value for WF0 THADC + * Address: ATOP RG_WF0_BG (0x384) + * Data: 0x00002008 + * Action: TOPSPI_WR + */ + consys_spi_write(SYS_SPI_TOP, ATOP_RG_WF0_BG, 0x2008); + + /* Initial IR value for WF1 THADC + * Address: ATOP RG_WF1_BG (0x394) + * Data: 0x00002008 + * Action: TOPSPI_WR + */ + consys_spi_write(SYS_SPI_TOP, ATOP_RG_WF1_BG, 0x2008); + + /* if(A-die XTAL = 26MHz ) { + * CONN_WF_CTRL2 swtich to CONN mode + * } + */ + /* Adress: 0x1000_5460[18:16] = 3'b001 + * Action: write + * Note: MT6635 strap pinmux, set CONN_WF_CTRL2 as conn mode + */ + if (adie_26m) { + CONSYS_REG_WRITE_MASK(GPIO_BASE_ADDR + GPIO_MODE22, 0x10000, 0x70000); + } + return 0; +} + +int connsys_afe_wbg_cal(void) +{ + /* Default value update; 1: AFE WBG CR (if needed) + * note that this CR must be backuped and restored by command batch engine + * Address: + * CONN_AFE_CTL_RG_WBG_AFE_01(0x18003010) = 32'h00000000 + * CONN_AFE_CTL_RG_WBG_RCK_01(0x18003018) = 32'h144B0160 + * CONN_AFE_CTL_RG_WBG_GL1_01(0x18003040) = 32'h10990C13 + * CONN_AFE_CTL_RG_WBG_GL5_01(0x18003100) = 32'h10990C13 + * CONN_AFE_CTL_RG_WBG_BT_TX_03 (0x18003058) = 32'hCD258051 + * CONN_AFE_CTL_RG_WBG_WF0_TX_03 (0x18003078) = 32'hC5258251 + * CONN_AFE_CTL_RG_WBG_WF1_TX_03 (0x18003094) = 32'hC5258251 + */ + CONSYS_REG_WRITE( + CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_WBG_AFE_01, + 0x0); + CONSYS_REG_WRITE( + CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_WBG_RCK_01, + 0x144B0160); + CONSYS_REG_WRITE( + CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_WBG_GL1_01, + 0x10990C13); + CONSYS_REG_WRITE( + CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_WBG_GL5_01, + 0x10990C13); + CONSYS_REG_WRITE( + CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_WBG_BT_TX_03, + 0xCD258051); + CONSYS_REG_WRITE( + CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_WBG_WF0_TX_03, + 0xC5258251); + CONSYS_REG_WRITE( + CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_WBG_WF1_TX_03, + 0xC5258251); + + /* AFE WBG CAL SEQ1 (RC calibration) */ + /* AFE WBG RC calibration, set "AFE RG_WBG_EN_RCK" = 1 + * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_RCK (0x18003000[0]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, 0x1); + udelay(60); + /* AFE WBG RC calibration */ + /* AFE WBG RC calibration, set "AFE RG_WBG_EN_RCK" = 0 + * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_RCK (0x18003000[0]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, 0x1); + + /* AFE WBG CAL SEQ2 (TX calibration) */ + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_BPLL_UP" = 1 + * Address: CONN_AFE_CTL_RG_DIG_EN_03_RG_WBG_EN_BPLL_UP (0x18003008[21]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_03, (0x1 << 21)); + udelay(30); + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_WPLL_UP" = 1 + * Address: CONN_AFE_CTL_RG_DIG_EN_03_RG_WBG_EN_WPLL_UP (0x18003008[20]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_03, (0x1 << 20)); + udelay(60); + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_BT" = 1 + * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_BT (0x18003000[21]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 21)); + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_WF0" = 1 + * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_WF0 (0x18003000[20]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 20)); + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_WF1" = 1 + * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_WF1 (0x18003000[19]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 19)); + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_WF2" = 1 + * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_WF2 (0x18003000[18]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 18)); + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_WF3" = 1 + * Addres: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_WF3 (0x18003000[17]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 17)); + udelay(800); + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_BT" = 0 + * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_BT (0x18003000[21]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 21)); + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_WF0" = 0 + * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_WF0 (0x18003000[20]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 20)); + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_WF1" = 0 + * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_WF1 (0x18003000[19]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 19)); + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_WF2" = 0 + * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_WF2 (0x18003000[18]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 18)); + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_WF3" = 0 + * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_WF3 (0x18003000[17]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 17)); + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_BPLL_UP" = 0 + * Address: CONN_AFE_CTL_RG_DIG_EN_03_RG_WBG_EN_BPLL_UP (0x18003008[21]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_03, (0x1 << 21)); + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_WPLL_UP" = 0 + * Address:i CONN_AFE_CTL_RG_DIG_EN_03_RG_WBG_EN_WPLL_UP (0x18003008[20]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_03, (0x1 << 20)); + + /* Initial BT path if WF is in cal(need set this CR after WBG cal) + * Address: ATOP RG_ENCAL_WBTAC_IF_SW (0x070) + * Data: 32'h00000005 + * Action: write + */ + consys_spi_write(SYS_SPI_TOP, ATOP_RG_ENCAL_WBTAC_IF_SW, 0x5); + return 0; +} + +int connsys_subsys_pll_initial(void) +{ + /* Check with DE, only 26M on mobile phone */ + /* Set BPLL stable time = 30us (value = 30 * 1000 *1.01 / 38.46ns) + * CONN_AFE_CTL_RG_PLL_STB_TIME_RG_WBG_BPLL_STB_TIME (0x180030F4[30:16]) = 0x314 + * Set WPLL stable time = 50us (value = 50 * 1000 *1.01 / 38.46ns) + * CONN_AFE_CTL_RG_PLL_STB_TIME_RG_WBG_WPLL_STB_TIME (0x180030F4[14:0]) = 0x521 + */ + CONSYS_REG_WRITE_MASK( + CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_PLL_STB_TIME, + 0x03140521, 0x7fff7fff); + + /* BT pll_en will turn on BPLL only (may change in different XTAL option) + * CONN_AFE_CTL_RG_DIG_EN_02_RG_WBG_EN_BT_PLL (0x18003004[7:6])=0x1 + * WF pll_en will turn on BPLL + WPLL only (may change in different XTAL option) + * CONN_AFE_CTL_RG_DIG_EN_02_RG_WBG_EN_WF_PLL (0x18003004[1:0])=0x3 + * MCU pll_en will turn on BPLL + WPLL (may change in different XTAL option) + * CONN_AFE_CTL_RG_DIG_EN_02_RG_WBG_EN_MCU_PLL (0x18003004[3:2])=0x3 + */ + CONSYS_REG_WRITE_MASK( + CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_02, + 0x4f, 0xcf); + + return 0; +} + +// Special setting for BT low power +static int connsys_bt_low_power_setting(bool bt_only) +{ + int hw_version; + const struct a_die_reg_config* config = NULL; + unsigned int ret, i; + + hw_version = CONSYS_REG_READ( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_CHIP_ID); + + if (bt_only) { + /* E1 */ + if (hw_version == 0x66358A00) { + config = adie_e1_bt_only; + } else if (hw_version == 0x66358A10 || hw_version == 0x66358A11) { + config = adie_e2_bt_only; + } else + pr_err("[%s] wrong adie version (0x%08x)\n", __func__, hw_version); + } else { + if (hw_version == 0x66358A00) { + config = adie_e1_default; + } else if (hw_version == 0x66358A10 || hw_version == 0x66358A11) { + config = adie_e2_default; + } else + pr_err("[%s] wrong adie version (0x%08x)\n", __func__, hw_version); + } + + if (config == NULL) + return -1; + + consys_adie_top_ck_en_on(CONNSYS_ADIE_CTL_HOST_CONNINFRA); + + /* Get semaphore before read */ + if (consys_sema_acquire_timeout(CONN_SEMA_RFSPI_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) { + pr_err("[EFUSE READ] Require semaphore fail\n"); + consys_adie_top_ck_en_off(CONNSYS_ADIE_CTL_HOST_CONNINFRA); + return -1; + } + + for (i = 0; i < ADIE_CONFIG_NUM; i++) { + consys_spi_read_nolock(SYS_SPI_TOP, config[i].reg, &ret); + ret &= (~config[i].mask); + ret |= config[i].config; + consys_spi_write_nolock(SYS_SPI_TOP, config[i].reg, ret); + } + + consys_sema_release(CONN_SEMA_RFSPI_INDEX); + + consys_adie_top_ck_en_off(CONNSYS_ADIE_CTL_HOST_CONNINFRA); + + return 0; +} + +void connsys_debug_select_config(void) +{ +#if 1 + /* select conn_infra_cfg debug_sel to low pwoer related + * Address: 0x18001B00[2:0] + * Data: 3'b000 + * Action: write + */ + CONSYS_REG_WRITE_MASK(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_DBG_MUX_SEL, + 0x0, 0x7); +#else + /* select conn_infra_cfg debug_sel to BPLL/WPLL status + * Address: 0x18001B00[2:0] + * Data: 3’b001 + * Action: write + */ + CONSYS_REG_WRITE_MASK(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_DBG_MUX_SEL, + 0x1, 0x7); + { + void __iomem *vir_addr = NULL; + vir_addr = ioremap_nocache(0x18006000, 0x1000); + if (vir_addr) { + /* wpll_rdy/bpll_rdy status dump + * 1.???Set 0x1800_604C = 0xFFFF_FFFF + * 2.???Set 0c1800_6058[1] = 0x1 + * 3.???Set 0x1800_603C = 0x0000_0100 + * 4.???Set 0x1800_601C = 0x0302_0100 + * 5.???Set 0x1800_6020 = 0x0706_0504 + * 6.???Set 0x1800_6024 = 0x0b0a_0908 + * 7.???Set 0x1800_6028 = 0x0f0e_0d0c + * 8.???Set 0x1800_602C = 0x1312_1110 + * 9.???Set 0x1800_6030 = 0x1716_1514 + * 10.??Set 0x1800_6034 = 0x1b1a_1918 + * 11.??Set 0x1800_6038 = 0x1f1e_1d1c + */ + CONSYS_REG_WRITE(vir_addr + 0x004c, 0xffffffff); + CONSYS_SET_BIT(vir_addr + 0x0058, 0x1); + CONSYS_REG_WRITE(vir_addr + 0x3c, 0x00000100); + CONSYS_REG_WRITE(vir_addr + 0x1c, 0x03020100); + CONSYS_REG_WRITE(vir_addr + 0x20, 0x07060504); + CONSYS_REG_WRITE(vir_addr + 0x24, 0x0b0a0908); + CONSYS_REG_WRITE(vir_addr + 0x28, 0x0f0e0d0c); + CONSYS_REG_WRITE(vir_addr + 0x2c, 0x13121110); + CONSYS_REG_WRITE(vir_addr + 0x30, 0x17161514); + CONSYS_REG_WRITE(vir_addr + 0x34, 0x1b1a1918); + CONSYS_REG_WRITE(vir_addr + 0x38, 0x1f1e1d1c); + iounmap(vir_addr); + } else { + pr_err("remap 0x1800_6000 fail\n"); + } + } +#endif + +} + + +int connsys_low_power_setting(unsigned int curr_status, unsigned int next_status) +{ + bool bt_only = false; + + if ((next_status & (~(0x1 << CONNDRV_TYPE_BT))) == 0) + bt_only = true; + + pr_info("[%s] current_status=%d bt_only = %d\n", __func__, curr_status, bt_only); + + /* First subsys on */ + if (curr_status == 0) { + /* Enable AP2CONN GALS Slave sleep protect en with conn_infra on2off/off2on & wfdma2conn + * sleep protect en + * Address: CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL_WFDMA2CONN_SLP_PROT_AP2CONN_EN_ENABLE + * CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL_CONN_INFRA_ON2OFF_SLP_PROT_AP2CONN_EN_ENABLE + * CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL_CONN_INFRA_OFF2ON_SLP_PROT_AP2CONN_EN_ENABLE (0x1806_0184[11:9]) + * Data: 3'b111 + * Action: write + */ + CONSYS_REG_WRITE_MASK( + CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL, + 0xe00, 0xe00); + + /* Unmask on2off/off2on slpprot_rdy enable checker @conn_infra off power off=> check slpprot_rdy = 1'b1 and go to sleep + * Address: CONN_INFRA_CFG_PWRCTRL0_CONN_INFRA_CFG_SLP_RDY_MASK (0x18001860[15:12]) + * Data: 4'h1 + * Action: write + */ + CONSYS_REG_WRITE_MASK( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_PWRCTRL0, + 0x1000, 0xf000); + + /* conn_infra low power setting */ + if (!consys_is_rc_mode_enable()) { + /* Default mode (non-RC) */ + /* Disable conn_top rc osc_ctrl_top + * Address: CONN_INFRA_CFG_RC_CTL_0_CONN_INFRA_OSC_RC_EN (0x18001834[7]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0, (0x1 << 7)); + /* Legacy OSC control stable time + * Address: + * CONN_INFRA_CFG_OSC_CTL_0_XO_VCORE_RDY_STABLE_TIME (0x18001800[7:0]) = 8'd6 + * CONN_INFRA_CFG_OSC_CTL_0_XO_INI_STABLE_TIME (0x18001800[15:8]) = 8'd7 + * CONN_INFRA_CFG_OSC_CTL_0_XO_BG_STABLE_TIME (0x18001800[23:16]) = 8'd8 + * Action: write + */ + CONSYS_REG_WRITE_MASK( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_OSC_CTL_0, 0x080706, 0xffffff); + /* Legacy OSC control unmask conn_srcclkena_ack + * Address: CONN_INFRA_CFG_OSC_CTL_1_ACK_FOR_XO_STATE_MASK (0x18001804[16]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_OSC_CTL_1, (0x1 << 16)); + } else { + /* RC mode */ + /* GPS RC OSC control stable time + * Address: + * CONN_INFRA_CFG_RC_CTL_1_GPS_XO_VCORE_RDY_STABLE_TIME_0 (0x1800183C[7:0]) = 8'd6 + * CONN_INFRA_CFG_RC_CTL_1_GPS_XO_INI_STABLE_TIME_0 (0x1800183C[15:8]) = 8'd7 + * CONN_INFRA_CFG_RC_CTL_1_GPS_XO_BG_STABLE_TIME_0 (0x1800183C[23:16]) = 8'd8 + * CONN_INFRA_CFG_RC_CTL_1_GPS_XO_VCORE_OFF_STABLE_TIME_0 (0x1800183C[31:24]) = 8'd2 + * Action: write + */ + CONSYS_REG_WRITE( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_1_GPS, + 0x02080706); + + /* GPS RC OSC control unmask conn_srcclkena_ack + * Address: CONN_INFRA_CFG_RC_CTL_0_GPS_ACK_FOR_XO_STATE_MASK_0 (0x18001838[15]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0_GPS, (0x1 << 15)); + + /* BT RC OSC control stable time + * Address: + * CONN_INFRA_CFG_RC_CTL_1_BT_XO_VCORE_RDY_STABLE_TIME_1 (0x18001844[7:0]) = 8'd6 + * CONN_INFRA_CFG_RC_CTL_1_BT_XO_INI_STABLE_TIME_1 (0x18001844[15:8]) = 8'd7 + * CONN_INFRA_CFG_RC_CTL_1_BT_XO_BG_STABLE_TIME_1 (0x18001844[23:16]) = 8'd8 + * CONN_INFRA_CFG_RC_CTL_1_BT_XO_VCORE_OFF_STABLE_TIME_1 (0x18001844[31:24]) = 8'd2 + * Action: write + */ + CONSYS_REG_WRITE( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_1_BT, + 0x02080706); + + /* BT RC OSC control unmask conn_srcclkena_ack + * Address: CONN_INFRA_CFG_RC_CTL_0_BT_ACK_FOR_XO_STATE_MASK_1 (0x18001840[15]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0_BT, (0x1 << 15)); + + /* WF RC OSC control stable time + * Address: + * CONN_INFRA_CFG_RC_CTL_1_WF_XO_VCORE_RDY_STABLE_TIME_2 (0x1800184C[7:0]) = 8'd6 + * CONN_INFRA_CFG_RC_CTL_1_WF_XO_INI_STABLE_TIME_2 (0x1800184C[15:8]) = 8'd7 + * CONN_INFRA_CFG_RC_CTL_1_WF_XO_BG_STABLE_TIME_2 (0x1800184C[23:16]) = 8'd8 + * CONN_INFRA_CFG_RC_CTL_1_WF_XO_VCORE_OFF_STABLE_TIME_2 (0x1800184C[31:24])= 8'd2 + * Action: write + */ + CONSYS_REG_WRITE( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_1_WF, + 0x02080706); + + /* WF RC OSC control unmask conn_srcclkena_ack + * Address: CONN_INFRA_CFG_RC_CTL_0_WF_ACK_FOR_XO_STATE_MASK_2 (0x18001848[15]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0_WF, (0x1 << 15)); + + /* TOP RC OSC control stable time + * Address: + * CONN_INFRA_CFG_RC_CTL_1_TOP_XO_VCORE_RDY_STABLE_TIME_3 (0x18001854[7:0]) = 8'd6 + * CONN_INFRA_CFG_RC_CTL_1_TOP_XO_INI_STABLE_TIME_3 (0x18001854[15:8]) = 8'd7 + * CONN_INFRA_CFG_RC_CTL_1_TOP_XO_BG_STABLE_TIME_3 (0x18001854[23:16]) = 8'd8 + * CONN_INFRA_CFG_RC_CTL_1_TOP_XO_VCORE_OFF_STABLE_TIME_3 (0x18001854[31:24]) = 8'd2 + * Action: write + */ + CONSYS_REG_WRITE( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_1_TOP, + 0x02080706); + + /* TOP RC OSC control unmask conn_srcclkena_ack + * Address: CONN_INFRA_CFG_RC_CTL_0_TOP_ACK_FOR_XO_STATE_MASK_3 (0x18001850[15]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0_TOP, + (0x1 << 15)); + + /* Enable conn_top rc osc_ctrl_gps + * Address: CONN_INFRA_CFG_RC_CTL_0_GPSSYS_OSC_RC_EN (0x18001834[4]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0, + (0x1 << 4)); + + /* Enable conn_top rc osc_ctrl_bt + * Address: CONN_INFRA_CFG_RC_CTL_0_BTSYS_OSC_RC_EN (0x18001834[5]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0, + (0x1 << 5)); + + /* Enable conn_top rc osc_ctrl_wf + * Address: CONN_INFRA_CFG_RC_CTL_0_WFSYS_OSC_RC_EN (0x18001834[6]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0, + (0x1 << 6)); + + /* set conn_srcclkena control by conn_infra_emi_ctl + * Address: CONN_INFRA_CFG_EMI_CTL_0_CONN_EMI_RC_EN (0x18001C00[0]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_EMI_CTL_0, 0x1); + + /* Disable legacy osc control + * Address: CONN_INFRA_CFG_RC_CTL_0_OSC_LEGACY_EN (0x18001834[0]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0, + 0x1); + } + /* conn2ap sleep protect release bypass ddr_en_ack check + * Address: CONN_INFRA_CFG_EMI_CTL_0_EMI_SLPPROT_BP_DDR_EN (0x18001C00[18]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_EMI_CTL_0, 0x40000); + + /* Enable ddr_en timeout, timeout value = 1023 T (Bus clock) + * Address: CONN_INFRA_CFG_EMI_CTL_0_DDR_CNT_LIMIT (0x18001C00[14:4]) + * Data: 11'd1023 + * Action: write + */ + CONSYS_REG_WRITE_MASK( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_EMI_CTL_0, + 0x3ff0, 0x7ff0); + + /* A-die clock buffer setting for BT only and others mode */ + connsys_bt_low_power_setting(bt_only); + + /* Enable conn_infra_clkgen BPLL source (hw workaround) + * Address: CONN_INFRA_CFG_CKGEN_BUS_RFSPI_DIV_EN (0x1800_1A00[28]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_CKGEN_BUS, (0x1 << 28)); + + /* Bus light security + * Address: + * CONN_INFRA_CFG_LIGHT_SECURITY_CTRL_R_CONN_INFRA_BT_PAIR1_EN + * CONN_INFRA_CFG_LIGHT_SECURITY_CTRL_R_CONN_INFRA_BT_PAIR0_EN + * CONN_INFRA_CFG_LIGHT_SECURITY_CTRL_R_CONN_INFRA_WF_PAIR1_EN + * CONN_INFRA_CFG_LIGHT_SECURITY_CTRL_R_CONN_INFRA_WF_PAIR0_EN + * 0x1800_10F0[4][3][1][0] = 6'h1B + * Action: write + */ + CONSYS_REG_WRITE_MASK( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_LIGHT_SECURITY_CTRL, + ((0x1 << 4) | (0x1 << 3) | (0x1 << 1) | 0x1), + ((0x1 << 4) | (0x1 << 3) | (0x1 << 1) | 0x1)); + + /* if(BT on or GPS on) + * Conn_infrapower on bgfsys on (woraround) + * Address: + * 0x18000008[31:16] = 16'h4254 (key) + * CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_CTL[7] (0x18000008[7]) = 1'b1 + * Action: write + */ + /* Check with DE, write 1 -> 1 is ok */ + if ((next_status & ((0x1 << CONNDRV_TYPE_BT) | (0x1 << CONNDRV_TYPE_GPS))) != 0) { + CONSYS_REG_WRITE_MASK( + CON_REG_INFRA_RGU_ADDR + CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_CTL, + ((0x42540000) | (0x1 << 7)), 0xffff0080); + } + + consys_config_setup(); + connsys_debug_select_config(); + /* + * set 0x1800_0090 = 4'h6 + */ + CONSYS_REG_WRITE(CON_REG_INFRA_RGU_ADDR + CONN_INFRA_RGU_DEBUG_SEL, 0x6); + + /******************************************************/ + /* power ctrl : 0x1800_1860[9] = 1'b1 */ + /******************************************************/ + CONSYS_SET_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_PWRCTRL0, 0x200); + + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + /* !!!!!!!!!!!!!!!!!!!!!! CANNOT add code after HERE!!!!!!!!!!!!!!!!!!!!!!!!!! */ + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + + /* Disable conn_infra bus clock sw control ==> conn_infra bus clock hw control + * Address: CONN_INFRA_CFG_CKGEN_BUS_HCLK_CKSEL_SWCTL (0x1800_1A00[23]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_CKGEN_BUS, (0x1 << 23)); + + /* Conn_infra HW_CONTROL => conn_infra enter dsleep mode + * Address: CONN_INFRA_CFG_PWRCTRL0_HW_CONTROL (0x1800_1860[0]) + * Data: 1'b1 + * Action: write + * Note: enable conn_infra off domain as HW control + */ + CONSYS_SET_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_PWRCTRL0, 0x1); + } else { + /* for subsys on/off, only update BT low power setting */ + connsys_bt_low_power_setting(bt_only); + + /* Workaround */ + if ((next_status & ((0x1 << CONNDRV_TYPE_BT) | (0x1 << CONNDRV_TYPE_GPS))) != 0) { + CONSYS_REG_WRITE_MASK( + CON_REG_INFRA_RGU_ADDR + CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_CTL, + ((0x42540000) | (0x1 << 7)), 0xffff0080); + } else { + CONSYS_REG_WRITE_MASK( + CON_REG_INFRA_RGU_ADDR + CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_CTL, + 0x42540000, 0xffff0080); + } + + consys_config_setup(); + connsys_debug_select_config(); + } + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + /* !!!!!!!!!!!!!!!!!!!!!!!!CANNOT add code HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + + return 0; +} + +static int consys_sema_acquire(unsigned int index) +{ + if (CONSYS_REG_READ_BIT( + CONN_REG_SEMAPHORE_ADDR + CONN_SEMAPHORE_M2_OWN_STA + index*4, 0x1) == 0x1) { + return CONN_SEMA_GET_SUCCESS; + } else { + return CONN_SEMA_GET_FAIL; + } +} + +int consys_sema_acquire_timeout(unsigned int index, unsigned int usec) +{ + int i, check, r1, r2; + + if (index >= CONN_SEMA_NUM_MAX) { + pr_err("[%s] wrong parameter: %d", __func__, index); + return CONN_SEMA_GET_FAIL; + } + + /* debug for bus hang */ + if (consys_reg_mng_reg_readable() == 0) { + check = consys_reg_mng_is_bus_hang(); + if (check > 0) { + r1 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_3); + r2 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP); + pr_info("[%s] check=[%d] r1=[0x%x] r2=[0x%x]", __func__, check, r1, r2); + consys_reg_mng_dump_bus_status(); + consys_reg_mng_dump_cpupcr(CONN_DUMP_CPUPCR_TYPE_ALL, 10, 200); + return CONN_SEMA_GET_FAIL; + } + } + + for (i = 0; i < usec; i++) { + if (consys_sema_acquire(index) == CONN_SEMA_GET_SUCCESS) { + return CONN_SEMA_GET_SUCCESS; + } + udelay(1); + } + + pr_err("Get semaphore 0x%x timeout, dump status:\n", index); + pr_err("M0:[0x%x] M1:[0x%x] M2:[0x%x] M3:[0x%x]\n", + CONSYS_REG_READ(CONN_REG_SEMAPHORE_ADDR + CONN_SEMA_OWN_BY_M0_STA_REP), + CONSYS_REG_READ(CONN_REG_SEMAPHORE_ADDR + CONN_SEMA_OWN_BY_M1_STA_REP), + CONSYS_REG_READ(CONN_REG_SEMAPHORE_ADDR + CONN_SEMA_OWN_BY_M2_STA_REP), + CONSYS_REG_READ(CONN_REG_SEMAPHORE_ADDR + CONN_SEMA_OWN_BY_M3_STA_REP)); + consys_reg_mng_dump_cpupcr(CONN_DUMP_CPUPCR_TYPE_ALL, 10, 200); + + return CONN_SEMA_GET_FAIL; +} + +void consys_sema_release(unsigned int index) +{ + if (index >= CONN_SEMA_NUM_MAX) + return; + CONSYS_REG_WRITE( + (CONN_REG_SEMAPHORE_ADDR + CONN_SEMAPHORE_M2_OWN_REL + index*4), 0x1); +} + +struct spi_op { + unsigned int busy_cr; + unsigned int polling_bit; + unsigned int addr_cr; + unsigned int read_addr_format; + unsigned int write_addr_format; + unsigned int write_data_cr; + unsigned int read_data_cr; + unsigned int read_data_mask; +}; + +static const struct spi_op spi_op_array[SYS_SPI_MAX] = { + /* SYS_SPI_WF1 */ + { + CONN_RF_SPI_MST_REG_SPI_STA, 1, + CONN_RF_SPI_MST_REG_SPI_WF_ADDR, 0x00001000, 0x00000000, + CONN_RF_SPI_MST_REG_SPI_WF_WDAT, + CONN_RF_SPI_MST_REG_SPI_WF_RDAT, 0xffffffff + }, + /* SYS_SPI_WF */ + { + CONN_RF_SPI_MST_REG_SPI_STA, 1, + CONN_RF_SPI_MST_REG_SPI_WF_ADDR, 0x00003000, 0x00002000, + CONN_RF_SPI_MST_REG_SPI_WF_WDAT, + CONN_RF_SPI_MST_REG_SPI_WF_RDAT, 0xffffffff + }, + /* SYS_SPI_BT */ + { + CONN_RF_SPI_MST_REG_SPI_STA, 2, + CONN_RF_SPI_MST_REG_SPI_BT_ADDR, 0x00005000, 0x00004000, + CONN_RF_SPI_MST_REG_SPI_BT_WDAT, + CONN_RF_SPI_MST_REG_SPI_BT_RDAT, 0x000000ff + }, + /* SYS_SPI_FM */ + { + CONN_RF_SPI_MST_REG_SPI_STA, 3, + CONN_RF_SPI_MST_REG_SPI_FM_ADDR, 0x00007000, 0x00006000, + CONN_RF_SPI_MST_REG_SPI_FM_WDAT, + CONN_RF_SPI_MST_REG_SPI_FM_RDAT, 0x0000ffff + }, + /* SYS_SPI_GPS */ + { + CONN_RF_SPI_MST_REG_SPI_STA, 4, + CONN_RF_SPI_MST_REG_SPI_GPS_GPS_ADDR, 0x00009000, 0x00008000, + CONN_RF_SPI_MST_REG_SPI_GPS_GPS_WDAT, + CONN_RF_SPI_MST_REG_SPI_GPS_GPS_RDAT, 0x0000ffff + }, + /* SYS_SPI_TOP */ + { + CONN_RF_SPI_MST_REG_SPI_STA, 5, + CONN_RF_SPI_MST_REG_SPI_TOP_ADDR, 0x0000b000, 0x0000a000, + CONN_RF_SPI_MST_REG_SPI_TOP_WDAT, + CONN_RF_SPI_MST_REG_SPI_TOP_RDAT, 0xffffffff + }, + /* SYS_SPI_WF2 */ + { + CONN_RF_SPI_MST_REG_SPI_STA, 1, + CONN_RF_SPI_MST_REG_SPI_WF_ADDR, 0x0000d000, 0x0000c000, + CONN_RF_SPI_MST_REG_SPI_WF_WDAT, + CONN_RF_SPI_MST_REG_SPI_WF_RDAT, 0xffffffff + }, + /* SYS_SPI_WF3 */ + { + CONN_RF_SPI_MST_REG_SPI_STA, 1, + CONN_RF_SPI_MST_REG_SPI_WF_ADDR, 0x0000f000, 0x0000e000, + CONN_RF_SPI_MST_REG_SPI_WF_WDAT, + CONN_RF_SPI_MST_REG_SPI_WF_RDAT, 0xffffffff + }, +}; + +static int consys_spi_read_nolock(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data) +{ + /* Read action: + * 1. Polling busy_cr[polling_bit] should be 0 + * 2. Write addr_cr with data being {read_addr_format | addr[11:0]} + * 3. Trigger SPI by writing write_data_cr as 0 + * 4. Polling busy_cr[polling_bit] as 0 + * 5. Read data_cr[data_mask] + */ + int check = 0; + const struct spi_op* op = &spi_op_array[subsystem]; + + if (!data) { + pr_err("[%s] invalid data ptr\n", __func__); + return CONNINFRA_SPI_OP_FAIL; + } + + CONSYS_REG_BIT_POLLING( + CONN_REG_RFSPI_ADDR + op->busy_cr, + op->polling_bit, 0, 100, 50, check); + if (check != 0) { + pr_err("[%s][%d][STEP1] polling 0x%08x bit %d fail. Value=0x%08x\n", + __func__, subsystem, CONN_REG_RFSPI_ADDR + op->busy_cr, + op->polling_bit, + CONSYS_REG_READ(CONN_REG_RFSPI_ADDR + op->busy_cr)); + return CONNINFRA_SPI_OP_FAIL; + } + + CONSYS_REG_WRITE( + CONN_REG_RFSPI_ADDR + op->addr_cr, + (op->read_addr_format | addr)); + + CONSYS_REG_WRITE(CONN_REG_RFSPI_ADDR + op->write_data_cr, 0); + + check = 0; + CONSYS_REG_BIT_POLLING( + CONN_REG_RFSPI_ADDR + op->busy_cr, + op->polling_bit, 0, 100, 50, check); + if (check != 0) { + pr_err("[%s][%d][STEP4] polling 0x%08x bit %d fail. Value=0x%08x\n", + __func__, subsystem, CONN_REG_RFSPI_ADDR + op->busy_cr, + op->polling_bit, + CONSYS_REG_READ(CONN_REG_RFSPI_ADDR + op->busy_cr)); + return CONNINFRA_SPI_OP_FAIL; + } + + check = CONSYS_REG_READ_BIT(CONN_REG_RFSPI_ADDR + op->read_data_cr, op->read_data_mask); + *data = check; + + return 0; +} + +int consys_spi_read(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data) +{ + int ret; + + /* Get semaphore before read */ + if (consys_sema_acquire_timeout(CONN_SEMA_RFSPI_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) { + pr_err("[SPI READ] Require semaphore fail\n"); + return CONNINFRA_SPI_OP_FAIL; + } + + ret = consys_spi_read_nolock(subsystem, addr, data); + + consys_sema_release(CONN_SEMA_RFSPI_INDEX); + + return ret; +} + +static int consys_spi_write_nolock(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data) +{ + int check = 0; + const struct spi_op* op = &spi_op_array[subsystem]; + + /* Write action: + * 1. Wait busy_cr[polling_bit] as 0 + * 2. Write addr_cr with data being {write_addr_format | addr[11:0] + * 3. Write write_data_cr ad data + * 4. Wait busy_cr[polling_bit] as 0 + */ + CONSYS_REG_BIT_POLLING( + CONN_REG_RFSPI_ADDR + op->busy_cr, + op->polling_bit, 0, 100, 50, check); + if (check != 0) { + pr_err("[%s][%d][STEP1] polling 0x%08x bit %d fail. Value=0x%08x\n", + __func__, subsystem, CONN_REG_RFSPI_ADDR + op->busy_cr, + op->polling_bit, + CONSYS_REG_READ(CONN_REG_RFSPI_ADDR + op->busy_cr)); + return CONNINFRA_SPI_OP_FAIL; + } + + CONSYS_REG_WRITE(CONN_REG_RFSPI_ADDR + op->addr_cr, (op->write_addr_format | addr)); + + CONSYS_REG_WRITE(CONN_REG_RFSPI_ADDR + op->write_data_cr, data); + + check = 0; + CONSYS_REG_BIT_POLLING( + CONN_REG_RFSPI_ADDR + op->busy_cr, + op->polling_bit, 0, 100, 50, check); + if (check != 0) { + pr_err("[%s][%d][STEP4] polling 0x%08x bit %d fail. Value=0x%08x\n", + __func__, subsystem, CONN_REG_RFSPI_ADDR + op->busy_cr, + op->polling_bit, + CONSYS_REG_READ(CONN_REG_RFSPI_ADDR + op->busy_cr)); + return CONNINFRA_SPI_OP_FAIL; + } + + return 0; +} + + +int consys_spi_write(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data) +{ + int ret; + + /* Get semaphore before read */ + if (consys_sema_acquire_timeout(CONN_SEMA_RFSPI_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) { + pr_err("[SPI WRITE] Require semaphore fail\n"); + return CONNINFRA_SPI_OP_FAIL; + } + + ret = consys_spi_write_nolock(subsystem, addr, data); + + consys_sema_release(CONN_SEMA_RFSPI_INDEX); + return ret; +} + +int consys_spi_write_offset_range( + enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int value, + unsigned int reg_offset, unsigned int value_offset, unsigned int size) +{ + if (consys_sema_acquire_timeout(CONN_SEMA_RFSPI_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) { + pr_err("[SPI READ] Require semaphore fail\n"); + return CONNINFRA_SPI_OP_FAIL; + } + consys_spi_write_offset_range_nolock( + subsystem, addr, value, reg_offset, value_offset, size); + + consys_sema_release(CONN_SEMA_RFSPI_INDEX); + return 0; +} + +static void consys_spi_write_offset_range_nolock( + enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int value, + unsigned int reg_offset, unsigned int value_offset, unsigned int size) +{ + unsigned int data = 0, data2; + unsigned int reg_mask; + int ret; + + pr_info("[%s][%s] addr=0x%04x value=0x%08x reg_offset=%d value_offset=%d size=%d", + __func__, get_spi_sys_name(subsystem), addr, value, reg_offset, value_offset, size); + value = (value >> value_offset); + value = GET_BIT_RANGE(value, size, 0); + value = (value << reg_offset); + ret = consys_spi_read_nolock(subsystem, addr, &data); + if (ret) { + pr_err("[%s][%s] Get 0x%08x error, ret=%d", + __func__, get_spi_sys_name(subsystem), addr, ret); + return; + } + reg_mask = GENMASK(reg_offset + size - 1, reg_offset); + data2 = data & (~reg_mask); + data2 = (data2 | value); + consys_spi_write_nolock(subsystem, addr, data2); + pr_info("[%s][%s] Write CR:0x%08x from 0x%08x to 0x%08x", + __func__, get_spi_sys_name(subsystem), + addr, data, data2); +} + + +static int consys_adie_top_ck_en_ctrl(bool on) +{ + int check = 0; + + if (on) + CONSYS_SET_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_ADIE_CTL, (0x1 << 1)); + else + CONSYS_CLR_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_ADIE_CTL, (0x1 << 1)); + + CONSYS_REG_BIT_POLLING( + CON_REG_WT_SPL_CTL_ADDR + CONN_WTSLP_CTL_REG_WB_STA, + 26, 0, 100, 5, check); + if (check == -1) { + pr_err("[%s] op=%d fail\n", __func__, on); + } + return check; + +} + +int consys_adie_top_ck_en_on(enum consys_adie_ctl_type type) +{ + unsigned int status; + int ret; + + if (type >= CONNSYS_ADIE_CTL_MAX) { + pr_err("[%s] invalid parameter(%d)\n", __func__, type); + return -1; + } + + if (consys_sema_acquire_timeout(CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) { + pr_err("[%s][%s] acquire semaphore (%d) timeout\n", + __func__, get_adie_ctrl_type_str(type), CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX); + return -1; + } + + status = CONSYS_REG_READ( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_TOP_CK_EN_CTRL); + if ((status & CONN_INFRA_SYSRAM__A_DIE_DIG_TOP_CK_EN_MASK) == 0) { + ret = consys_adie_top_ck_en_ctrl(true); + } + CONSYS_SET_BIT( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_TOP_CK_EN_CTRL, (0x1 << type)); + + consys_sema_release(CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX); + return 0; +} + +int consys_adie_top_ck_en_off(enum consys_adie_ctl_type type) +{ + unsigned int status; + int ret = 0; + + if (type >= CONNSYS_ADIE_CTL_MAX) { + pr_err("[%s] invalid parameter(%d)\n", __func__, type); + return -1; + } + + if (consys_sema_acquire_timeout(CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) { + pr_err("[%s][%s] acquire semaphoreaore (%d) timeout\n", + __func__, get_adie_ctrl_type_str(type), CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX); + return -1; + } + + status = CONSYS_REG_READ( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_TOP_CK_EN_CTRL); + if ((status & (0x1 << type)) == 0) { + pr_warn("[%s][%s] already off\n", __func__, get_adie_ctrl_type_str(type)); + } else { + CONSYS_CLR_BIT( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_TOP_CK_EN_CTRL, (0x1 << type)); + + status = CONSYS_REG_READ( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_TOP_CK_EN_CTRL); + if (0 == (status & CONN_INFRA_SYSRAM__A_DIE_DIG_TOP_CK_EN_MASK)) { + ret = consys_adie_top_ck_en_ctrl(false); + } + } + + consys_sema_release(CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX); + return ret; +} + +int consys_spi_clock_switch(enum connsys_spi_speed_type type) +{ +#define MAX_SPI_CLOCK_SWITCH_COUNT 100 + unsigned int status; + unsigned int counter = 0; + int ret = 0; + + /* Get semaphore before read */ + if (consys_sema_acquire_timeout(CONN_SEMA_RFSPI_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) { + pr_err("[SPI CLOCK SWITCH] Require semaphore fail\n"); + return -1; + } + + if (type == CONNSYS_SPI_SPEED_26M) { + CONSYS_REG_WRITE_MASK( + CONN_REG_RFSPI_ADDR + CONN_RF_SPI_MST_REG_SPI_CRTL, + 0x0, 0x5); + status = CONSYS_REG_READ(CONN_REG_RFSPI_ADDR + CONN_RF_SPI_MST_REG_SPI_CRTL) & 0x18; + while (status != 0x8 && counter < MAX_SPI_CLOCK_SWITCH_COUNT) { + udelay(10); + status = CONSYS_REG_READ(CONN_REG_RFSPI_ADDR + CONN_RF_SPI_MST_REG_SPI_CRTL) & 0x18; + counter++; + } + if (counter == MAX_SPI_CLOCK_SWITCH_COUNT) { + pr_err("[%s] switch to 26M fail\n", __func__); + ret = -1; + } + } else if (type == CONNSYS_SPI_SPEED_64M) { + CONSYS_REG_WRITE_MASK( + CONN_REG_RFSPI_ADDR + CONN_RF_SPI_MST_REG_SPI_CRTL, 0x5, 0x5); + status = CONSYS_REG_READ(CONN_REG_RFSPI_ADDR + CONN_RF_SPI_MST_REG_SPI_CRTL) & 0x18; + while (status != 0x10 && counter < MAX_SPI_CLOCK_SWITCH_COUNT) { + udelay(10); + status = CONSYS_REG_READ(CONN_REG_RFSPI_ADDR + CONN_RF_SPI_MST_REG_SPI_CRTL) & 0x18; + counter++; + } + if (counter == MAX_SPI_CLOCK_SWITCH_COUNT) { + pr_err("[%s] switch to 64M fail\n", __func__); + ret = -1; + } + } else { + ret = -1; + pr_err("[%s] wrong parameter %d\n", __func__, type); + } + + consys_sema_release(CONN_SEMA_RFSPI_INDEX); + + return ret; +} + +int consys_subsys_status_update(bool on, int radio) +{ + if (radio < CONNDRV_TYPE_BT || radio > CONNDRV_TYPE_WIFI) { + pr_err("[%s] wrong parameter: %d\n", __func__, radio); + return -1; + } + + if (consys_sema_acquire_timeout(CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) { + pr_err("[%s] acquire semaphore (%d) timeout\n", + __func__, CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX); + return -1; + } + + if (on) { + CONSYS_SET_BIT( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_RADIO_STATUS, + (0x1 << radio)); + } else { + CONSYS_CLR_BIT( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_RADIO_STATUS, + (0x1 << radio)); + } + + consys_sema_release(CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX); + return 0; +} + + +bool consys_is_rc_mode_enable(void) +{ + int ret; + + ret = CONSYS_REG_READ_BIT(CON_REG_SPM_BASE_ADDR + SPM_RC_CENTRAL_CFG1, 0x1); + + return ret; +} + +void consys_config_setup(void) +{ + /* To access CR in conninfra off domain, Conninfra should be on state */ + /* Enable conn_infra bus hang detect function + * Address: 0x1800_F000 + * Data: 32'h32C8_001C + * Action: write + */ + CONSYS_REG_WRITE(CONN_DEBUG_CTRL_ADDR + CONN_DEBUG_CTRL_REG_OFFSET, 0x32c8001c); +} diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/include/mt6893.h b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/include/mt6893.h new file mode 100644 index 0000000000000..3d2fe3632eb87 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/include/mt6893.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ + +#ifndef _PLATFORM_MT6893_H_ +#define _PLATFORM_MT6893_H_ + +enum conn_semaphore_type +{ + CONN_SEMA_CHIP_POWER_ON_INDEX = 0, + CONN_SEMA_CALIBRATION_INDEX = 1, + CONN_SEMA_FW_DL_INDEX = 2, + CONN_SEMA_CLOCK_SWITCH_INDEX = 3, + CONN_SEMA_CCIF_INDEX = 4, + CONN_SEMA_COEX_INDEX = 5, + CONN_SEMA_USB_EP0_INDEX = 6, + CONN_SEMA_USB_SHARED_INFO_INDEX = 7, + CONN_SEMA_USB_SUSPEND_INDEX = 8, + CONN_SEMA_USB_RESUME_INDEX = 9, + CONN_SEMA_PCIE_INDEX = 10, + CONN_SEMA_RFSPI_INDEX = 11, + CONN_SEMA_EFUSE_INDEX = 12, + CONN_SEMA_THERMAL_INDEX = 13, + CONN_SEMA_FLASH_INDEX = 14, + CONN_SEMA_DEBUG_INDEX = 15, + CONN_SEMA_WIFI_LP_INDEX = 16, + CONN_SEMA_PATCH_DL_INDEX = 17, + CONN_SEMA_SHARED_VAR_INDEX = 18, + CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX = 19, + CONN_SEMA_BUS_CONTROL = 20, + CONN_SEMA_NUM_MAX = 32 /* can't be omitted */ +}; + +int consys_platform_spm_conn_ctrl(unsigned int enable); +int consys_co_clock_type(void); + +struct consys_plat_thermal_data { + int thermal_b; + int slop_molecule; + int offset; +}; + +void update_thermal_data(struct consys_plat_thermal_data* input); +#endif /* _PLATFORM_MT6893_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/include/mt6893_consys_reg.h b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/include/mt6893_consys_reg.h new file mode 100644 index 0000000000000..f7ff6267a8b74 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/include/mt6893_consys_reg.h @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ + +#ifndef _PLATFORM_MT6893_CONSYS_REG_H_ +#define _PLATFORM_MT6893_CONSYS_REG_H_ + +#include "consys_reg_base.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 +******************************************************************************** +*/ + +enum consys_base_addr_index { + CONN_INFRA_RGU_BASE_INDEX = 0, + CONN_INFRA_CFG_BASE_INDEX = 1, + CONN_HOST_CSR_TOP_BASE_INDEX = 2, + INFRACFG_AO_BASE_INDEX = 3, + TOPRGU_BASE_INDEX= 4, + SPM_BASE_INDEX = 5, + INFRACFG_BASE_INDEX = 6, + CONN_WT_SLP_CTL_REG_INDEX = 7, + CONN_AFE_CTL_INDEX = 8, + CONN_INFRA_SYSRAM_INDEX = 9, + GPIO_INDEX = 10, + CONN_RF_SPI_MST_REG_INDEX = 11, + CONN_SEMAPHORE_INDEX = 12, + CONN_TOP_THERM_CTL_INDEX = 13, + IOCFG_RT_INDEX = 14, /* Base: 0x11EA_0000 */ + CONN_DEBUG_CTRL = 15, /* Base: 0x1800_f000 */ + + CONSYS_BASE_ADDR_MAX +}; + + +struct consys_base_addr { + struct consys_reg_base_addr reg_base_addr[CONSYS_BASE_ADDR_MAX]; +}; + +extern struct consys_base_addr conn_reg; + +#define CON_REG_INFRA_RGU_ADDR conn_reg.reg_base_addr[CONN_INFRA_RGU_BASE_INDEX].vir_addr +#define CON_REG_INFRA_CFG_ADDR conn_reg.reg_base_addr[CONN_INFRA_CFG_BASE_INDEX].vir_addr +#define CON_REG_HOST_CSR_ADDR conn_reg.reg_base_addr[CONN_HOST_CSR_TOP_BASE_INDEX].vir_addr +#define CON_REG_INFRACFG_AO_ADDR conn_reg.reg_base_addr[INFRACFG_AO_BASE_INDEX].vir_addr + +#define CON_REG_TOP_RGU_ADDR conn_reg.reg_base_addr[TOPRGU_BASE_INDEX].vir_addr +#define CON_REG_SPM_BASE_ADDR conn_reg.reg_base_addr[SPM_BASE_INDEX].vir_addr +#define CON_REG_INFRACFG_BASE_ADDR conn_reg.reg_base_addr[INFRACFG_BASE_INDEX].vir_addr +#define CON_REG_WT_SPL_CTL_ADDR conn_reg.reg_base_addr[CONN_WT_SLP_CTL_REG_INDEX].vir_addr + +#define CONN_AFE_CTL_BASE_ADDR conn_reg.reg_base_addr[CONN_AFE_CTL_INDEX].vir_addr +#define CONN_INFRA_SYSRAM_BASE_ADDR conn_reg.reg_base_addr[CONN_INFRA_SYSRAM_INDEX].vir_addr +#define GPIO_BASE_ADDR conn_reg.reg_base_addr[GPIO_INDEX].vir_addr +#define CONN_REG_RFSPI_ADDR conn_reg.reg_base_addr[CONN_RF_SPI_MST_REG_INDEX].vir_addr + +#define CONN_REG_SEMAPHORE_ADDR conn_reg.reg_base_addr[CONN_SEMAPHORE_INDEX].vir_addr +#define CONN_TOP_THERM_CTL_ADDR conn_reg.reg_base_addr[CONN_TOP_THERM_CTL_INDEX].vir_addr +#define IOCFG_RT_ADDR conn_reg.reg_base_addr[IOCFG_RT_INDEX].vir_addr +#define CONN_DEBUG_CTRL_ADDR conn_reg.reg_base_addr[CONN_DEBUG_CTRL].vir_addr + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + +struct consys_base_addr* get_conn_reg_base_addr(void); + +#endif /* _PLATFORM_MT6893_CONSYS_REG_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/include/mt6893_consys_reg_offset.h b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/include/mt6893_consys_reg_offset.h new file mode 100644 index 0000000000000..c44f5eb60370f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/include/mt6893_consys_reg_offset.h @@ -0,0 +1,306 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ + +#ifndef _PLATFORM_MT6893_CONSYS_REG_OFFSET_H_ +#define _PLATFORM_MT6893_CONSYS_REG_OFFSET_H_ + + +/**********************************************************************/ +/* Base: infracfg_ao (0x1000_1000) */ +/**********************************************************************/ +#define INFRA_TOPAXI_PROTECTEN_STA1_OFFSET 0x0228 +#define INFRA_TOPAXI_PROTECTEN_SET_OFFSET 0x02a0 +#define INFRA_TOPAXI_PROTECTEN_CLR_OFFSET 0x02a4 +#define INFRA_TOPAXI_PROTECTEN2_CLR_OFFSET 0x0718 +#define INFRA_TOPAXI_PROTECTEN2_SET_OFFSET 0x0714 +#define INFRA_TOPAXI_PROTECTEN2_STA1_OFFSET 0x0724 + +/**********************************************************************/ +/* Base: GPIO (0x1000_5000) */ +/**********************************************************************/ +#define GPIO_DIR5_SET 0x0054 + +#define GPIO_DOUT5_SET 0x0154 + +#define GPIO_MODE19 0x0430 +#define GPIO_MODE21 0x0450 +#define GPIO_MODE22 0x0460 + +/**********************************************************************/ +/* Base: SPM (0x1000_6000) */ +/**********************************************************************/ +#define SPM_POWERON_CONFIG_EN 0x0000 +#define SPM_PCM_REG13_DATA 0x0110 +#define SPM_PCM_REG7_DATA 0x0100 +#define SPM_SRC_REQ_STA_0 0x0114 +#define SPM_BUS_PROTECT_RDY 0x0150 +#define SPM_BUS_PROTECT2_RDY 0x0158 +#define SPM_PWR_STATUS 0x016c +#define SPM_PWR_STATUS_2ND 0x0170 +#define SPM_CONN_PWR_CON 0x0304 +#define SPM_PLL_CON 0x044C +#define SPM_RC_CENTRAL_CFG1 0x0504 +#define SPM_PCM_WDT_LATCH_SPARE_0 0x084C + +#define SPM_RC_RC_M04_REQ_STA_0 0xE28 +#define SPM_RC_RC_M05_REQ_STA_0 0xE2C +#define SPM_RC_RC_M06_REQ_STA_0 0xE30 +#define SPM_RC_RC_M07_REQ_STA_0 0xE34 + +/**********************************************************************/ +/* Base: TOP RGU (0x1000_7000) */ +/**********************************************************************/ +#define TOP_RGU_WDT_SWSYSRST 0x0018 + + +/**********************************************************************/ +/* Base: INFRACFG (0x1020_e000) */ +/**********************************************************************/ +#define INFRA_AP2MD_GALS_CTL 0x0504 +#define INFRA_CONN2AP_GLAS_RC_ST 0x0804 + +/**********************************************************************/ +/* Base: IOCFG_RT (0x11EA_0000) */ +/**********************************************************************/ +#define IOCFG_RT_DRV_CFG0 0x0000 +#define IOCFG_RT_PD_CFG0_SET 0x0054 +#define IOCFG_RT_PD_CFG0_CLR 0x0058 +#define IOCFG_RT_PU_CFG0_SET 0x0074 +#define IOCFG_RT_PU_CFG0_CLR 0x0078 + +/**********************************************************************/ +/* Base: conn_infra_rgu (0x1800_0000) */ +/**********************************************************************/ +#define CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_CTL 0x0008 +#define CONN_INFRA_RGU_SYSRAM_HWCTL_PDN 0x0038 +#define CONN_INFRA_RGU_SYSRAM_HWCTL_SLP 0x003c +#define CONN_INFRA_RGU_CO_EXT_MEM_HWCTL_PDN 0x0050 +#define CONN_INFRA_RGU_CO_EXT_MEM_HWCTL_SLP 0x0054 +#define CONN_INFRA_RGU_DEBUG_SEL 0x0090 + +/**********************************************************************/ +/* Base: conn_infra_cfg (0x1800_1000) */ +/**********************************************************************/ +#define CONN_HW_VER_OFFSET 0x0000 +#define CONN_CFG_ID_OFFSET 0x0004 +#define CONN_INFRA_CFG_LIGHT_SECURITY_CTRL 0x00f0 + +#define CONN_INFRA_CFG_GALS_AP2CONN_GALS_DBG 0x0160 +#define CONN_INFRA_CFG_GALS_CONN2AP_TX_SLP_CTRL 0x0630 +#define CONN_INFRA_CFG_GALS_CONN2AP_RX_SLP_CTRL 0x0634 +#define CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL 0x061C +#define CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL 0x0618 +#define CONN_INFRA_CFG_GALS_BT2CONN_SLP_CTRL 0x0614 +#define CONN_INFRA_CFG_GALS_CONN2BT_SLP_CTRL 0x0610 + +#define CONN_INFRA_CFG_WF_SLP_CTRL 0x0620 +#define CONN_INFRA_CFG_ON_BUS_SLP_CTRL 0x0628 +#define CONN_INFRA_CFG_OFF_BUS_SLP_CTRL 0x062C + + +#define CONN_INFRA_CFG_OSC_CTL_0 0x0800 +#define CONN_INFRA_CFG_OSC_CTL_1 0x0804 +#define CONN_INFRA_CFG_OSC_STATUS 0x080C +#define CONN_INFRA_CFG_PLL_STATUS 0x0810 + +#define AP2CONN_EFUSE_DATA 0x0818 +#define CONN_INFRA_CFG_RC_CTL_0 0x0834 +#define CONN_INFRA_CFG_RC_CTL_0_GPS 0x0838 +#define CONN_INFRA_CFG_RC_CTL_1_GPS 0x083C +#define CONN_INFRA_CFG_RC_CTL_0_BT 0x0840 +#define CONN_INFRA_CFG_RC_CTL_1_BT 0x0844 +#define CONN_INFRA_CFG_RC_CTL_0_WF 0x0848 +#define CONN_INFRA_CFG_RC_CTL_1_WF 0x084c +#define CONN_INFRA_CFG_RC_CTL_1_TOP 0x0854 +#define CONN_INFRA_CFG_RC_CTL_0_TOP 0x0850 +#define CONN_INFRA_CFG_PWRCTRL0 0x0860 +#define CONN_INFRA_CFG_ADIE_CTL 0x0900 +#define CONN_INFRA_CFG_CKGEN_BUS 0x0a00 +#define CONN_INFRA_CFG_DBG_MUX_SEL 0x0b00 +#define CONN_INFRA_CFG_EMI_CTL_0 0x0c00 + +#define CONN_HW_VER 0x20010101 +#define CONN_CFG_ID 0x3 + +/**********************************************************************/ +/* Base: conn_top_therm_ctl (0x1800_2000) */ +/**********************************************************************/ +#define CONN_TOP_THERM_CTL_THERMCR1 0x0004 +#define CONN_TOP_THERM_CTL_THERM_AADDR 0x0018 +#define CONN_TOP_THERM_CTL_THERM_CAL_EN 0x0024 + +/**********************************************************************/ +/* Base: conn_afe_ctl(0x1800_3000) */ +/**********************************************************************/ +#define CONN_AFE_CTL_RG_DIG_EN_01 0x0000 +#define CONN_AFE_CTL_RG_DIG_EN_02 0x0004 +#define CONN_AFE_CTL_RG_DIG_EN_03 0x0008 +#define CONN_AFE_CTL_RG_WBG_AFE_01 0x0010 +#define CONN_AFE_CTL_RG_WBG_RCK_01 0x0018 +#define CONN_AFE_CTL_RG_WBG_GL1_01 0x0040 +#define CONN_AFE_CTL_RG_WBG_BT_TX_03 0x0058 +#define CONN_AFE_CTL_RG_WBG_WF0_TX_03 0x0078 +#define CONN_AFE_CTL_RG_WBG_WF1_TX_03 0x0094 +#define CONN_AFE_CTL_RG_PLL_STB_TIME 0x00f4 +#define CONN_AFE_CTL_RG_WBG_GL5_01 0x0100 + + +/**********************************************************************/ +/* Base: conn_rf_spi_mst_reg(0x1800_4000) */ +/**********************************************************************/ +#define CONN_RF_SPI_MST_REG_SPI_STA 0x0000 +#define CONN_RF_SPI_MST_REG_SPI_CRTL 0x0004 +#define CONN_RF_SPI_MST_REG_FM_CTRL 0x000c +#define CONN_RF_SPI_MST_REG_SPI_WF_ADDR 0x0010 +#define CONN_RF_SPI_MST_REG_SPI_WF_WDAT 0x0014 +#define CONN_RF_SPI_MST_REG_SPI_WF_RDAT 0x0018 +#define CONN_RF_SPI_MST_REG_SPI_BT_ADDR 0x0020 +#define CONN_RF_SPI_MST_REG_SPI_BT_WDAT 0x0024 +#define CONN_RF_SPI_MST_REG_SPI_BT_RDAT 0x0028 +#define CONN_RF_SPI_MST_REG_SPI_FM_ADDR 0x0030 +#define CONN_RF_SPI_MST_REG_SPI_FM_WDAT 0x0034 +#define CONN_RF_SPI_MST_REG_SPI_FM_RDAT 0x0038 +#define CONN_RF_SPI_MST_REG_SPI_TOP_ADDR 0x0050 +#define CONN_RF_SPI_MST_REG_SPI_TOP_WDAT 0x0054 +#define CONN_RF_SPI_MST_REG_SPI_TOP_RDAT 0x0058 +#define CONN_RF_SPI_MST_REG_SPI_GPS_GPS_ADDR 0x0210 +#define CONN_RF_SPI_MST_REG_SPI_GPS_GPS_WDAT 0x0214 +#define CONN_RF_SPI_MST_REG_SPI_GPS_GPS_RDAT 0x0218 + + +/**********************************************************************/ +/* Base: conn_wt_slp_ctl_reg(0x1800_5000) */ +/**********************************************************************/ +#define CONN_WTSLP_CTL_REG_WB_STA 0x0008 +#define CONN_WT_SLP_CTL_REG_WB_SLP_CTL 0x0004 +#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR1 0x0010 +#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR2 0x0014 +#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR3 0x0018 +#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR4 0x001c +#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR5 0x0020 +#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR6 0x0024 +#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR7 0x0028 +#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR8 0x002c +#define CONN_WT_SLP_CTL_REG_WB_BG_ON1 0x0030 +#define CONN_WT_SLP_CTL_REG_WB_BG_ON2 0x0034 +#define CONN_WT_SLP_CTL_REG_WB_BG_ON3 0x0038 +#define CONN_WT_SLP_CTL_REG_WB_BG_ON4 0x003c +#define CONN_WT_SLP_CTL_REG_WB_BG_ON5 0x0040 +#define CONN_WT_SLP_CTL_REG_WB_BG_ON6 0x0044 +#define CONN_WT_SLP_CTL_REG_WB_BG_ON7 0x0048 +#define CONN_WT_SLP_CTL_REG_WB_BG_ON8 0x004c +#define CONN_WT_SLP_CTL_REG_WB_BG_OFF1 0x0050 +#define CONN_WT_SLP_CTL_REG_WB_BG_OFF2 0x0054 +#define CONN_WT_SLP_CTL_REG_WB_BG_OFF3 0x0058 +#define CONN_WT_SLP_CTL_REG_WB_BG_OFF4 0x005c +#define CONN_WT_SLP_CTL_REG_WB_BG_OFF5 0x0060 +#define CONN_WT_SLP_CTL_REG_WB_BG_OFF6 0x0064 +#define CONN_WT_SLP_CTL_REG_WB_BG_OFF7 0x0068 +#define CONN_WT_SLP_CTL_REG_WB_BG_OFF8 0x006c +#define CONN_WT_SLP_CTL_REG_WB_WF_CK_ADDR 0x0070 +#define CONN_WT_SLP_CTL_REG_WB_WF_WAKE_ADDR 0x0074 +#define CONN_WT_SLP_CTL_REG_WB_WF_ZPS_ADDR 0x0078 +#define CONN_WT_SLP_CTL_REG_WB_BT_CK_ADDR 0x007c +#define CONN_WT_SLP_CTL_REG_WB_BT_WAKE_ADDR 0x0080 +#define CONN_WT_SLP_CTL_REG_WB_TOP_CK_ADDR 0x0084 +#define CONN_WT_SLP_CTL_REG_WB_GPS_CK_ADDR 0x0088 +#define CONN_WT_SLP_CTL_REG_WB_WF_B0_CMD_ADDR 0x008c +#define CONN_WT_SLP_CTL_REG_WB_WF_B1_CMD_ADDR 0x0090 +#define CONN_WT_SLP_CTL_REG_WB_GPS_RFBUF_ADDR 0x0094 +#define CONN_WT_SLP_CTL_REG_WB_GPS_L5_EN_ADDR 0x0098 + +/**********************************************************************/ +/* Base: GPT2 timer (0x1800_7000) */ +/**********************************************************************/ +#define CONN_GPT2_CTRL_BASE 0x18007000 +#define CONN_GPT2_CTRL_THERMAL_EN 0x38 + +/**********************************************************************/ +/* Base: debug_ctrl (0x1800_f000) */ +/**********************************************************************/ +#define CONN_DEBUG_CTRL_REG_OFFSET 0x0000 + + +/**********************************************************************/ +/* Base: conn_infra_sysram(0x1805_0000) */ +/**********************************************************************/ +#define CONN_INFRA_SYSRAM_SW_CR_A_DIE_CHIP_ID 0x2800 +#define CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_0 0x2804 +#define CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_1 0x2808 +#define CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_2 0x280C +#define CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_3 0x2810 + +#define CONN_INFRA_SYSRAM_SW_CR_D_DIE_EFUSE 0x2820 + +#define CONN_INFRA_SYSRAM_SW_CR_A_DIE_TOP_CK_EN_CTRL 0x2830 +#define CONN_INFRA_SYSRAM_SW_CR_RADIO_STATUS 0x2834 +#define CONN_INFRA_SYSRAM_SW_CR_BUILD_MODE 0x2838 + +#define CONN_INFRA_SYSRAM_SIZE (16 * 1024) + + +/**********************************************************************/ +/* Base: conn_host_csr_top (0x1806_0000) */ +/**********************************************************************/ +#define CONN_HOST_CSR_TOP_CSR_DEADFEED_EN_CR 0x0124 +#define CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_AO_DEBUGSYS 0x0128 +#define CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT 0x0148 +#define CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL 0x0184 +#define CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP 0x01a0 +/* remap */ +#define CONN2AP_REMAP_MCU_EMI_BASE_ADDR_OFFSET 0x01c4 +#define CONN2AP_REMAP_MD_SHARE_EMI_BASE_ADDR_OFFSET 0x01cc +#define CONN2AP_REMAP_GPS_EMI_BASE_ADDR_OFFSET 0x01d0 +#define CONN2AP_REMAP_WF_PERI_BASE_ADDR_OFFSET 0x01d4 +#define CONN2AP_REMAP_BT_PERI_BASE_ADDR_OFFSET 0x01d8 +#define CONN2AP_REMAP_GPS_PERI_BASE_ADDR_OFFSET 0x01dc + +#define CONN_HOST_CSR_WM_MCU_PC_DBG 0x0204 +#define CONN_HOST_CSR_WM_MCU_GPR_DBG 0x0208 +#define CONN_HOST_CSR_BGF_MCU_PC_DBG 0x022C + +#define CONN_HOST_CSR_DBG_DUMMY_0 0x02C0 +#define CONN_HOST_CSR_DBG_DUMMY_2 0x02C8 +#define CONN_HOST_CSR_DBG_DUMMY_3 0x02CC +#define CONN_HOST_CSR_DBG_DUMMY_4 0x02D0 +#define CONN_HOST_CSR_TOP_BUS_TIMEOUT_IRQ 0x02d4 + +#define TOP_BUS_MUC_STAT_HCLK_FR_CK_DETECT_BIT (0x1 << 1) +#define TOP_BUS_MUC_STAT_OSC_CLK_DETECT_BIT (0x1 << 2) +#define TOP_SLP_PROT_CTRL_CONN_INFRA_ON2OFF_SLP_PROT_ACK_BIT (0x1 << 5) + +/**********************************************************************/ +/* Base: conn_semaphore(0x1807_0000) */ +/**********************************************************************/ +#define CONN_SEMA_OWN_BY_M0_STA_REP 0x0400 +#define CONN_SEMA_OWN_BY_M1_STA_REP 0x1400 +#define CONN_SEMAPHORE_M2_OWN_STA 0x2000 +#define CONN_SEMAPHORE_M2_OWN_REL 0x2200 +#define CONN_SEMA_OWN_BY_M2_STA_REP 0x2400 +#define CONN_SEMA_OWN_BY_M3_STA_REP 0x3400 + +/**********************************************************************/ +/* A-die CR */ +/**********************************************************************/ +#define ATOP_CHIP_ID 0x02c +#define ATOP_RG_TOP_THADC_BG 0x034 +#define ATOP_RG_TOP_THADC 0x038 +#define ATOP_WRI_CTR2 0x064 +#define ATOP_RG_ENCAL_WBTAC_IF_SW 0x070 +#define ATOP_SMCTK11 0x0BC +#define ATOP_EFUSE_CTRL 0x108 +#define ATOP_EFUSE_RDATA0 0x130 +#define ATOP_EFUSE_RDATA1 0x134 +#define ATOP_EFUSE_RDATA2 0x138 +#define ATOP_EFUSE_RDATA3 0x13c +#define ATOP_RG_WF0_TOP_01 0x380 +#define ATOP_RG_WF0_BG 0x384 +#define ATOP_RG_WF1_BG 0x394 +#define ATOP_RG_WF1_TOP_01 0x390 +#define ATOP_RG_TOP_XTAL_01 0xA18 +#define ATOP_RG_TOP_XTAL_02 0xA1C + + +#endif /* _PLATFORM_MT6893_CONSSY_REG_OFFSET_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/include/mt6893_emi.h b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/include/mt6893_emi.h new file mode 100644 index 0000000000000..4b20aaa541cd7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/include/mt6893_emi.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ + +#ifndef _PLATFORM_MT6893_EMI_H_ +#define _PLATFORM_MT6893_EMI_H_ + +#include "osal.h" +#include "emi_mng.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 +******************************************************************************** +*/ + +struct consys_platform_emi_ops* get_consys_platform_emi_ops(void); + +struct consys_emi_addr_info* consys_emi_get_phy_addr(void); +int consys_emi_mpu_set_region_protection(void); +void consys_emi_get_md_shared_emi(phys_addr_t*, unsigned int*); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _PLATFORM_MT6893_EMI_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/include/mt6893_pmic.h b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/include/mt6893_pmic.h new file mode 100644 index 0000000000000..f5b8ca8e8bc65 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/include/mt6893_pmic.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ + +#ifndef _PLATFORM_MT6893_PMIC_H_ +#define _PLATFORM_MT6893_PMIC_H_ + +#include "osal.h" +#include "pmic_mng.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 +******************************************************************************** +*/ + +P_CONSYS_PLATFORM_PMIC_OPS get_consys_platform_pmic_ops(void); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _PLATFORM_MT6893_PMIC_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/include/mt6893_pos.h b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/include/mt6893_pos.h new file mode 100644 index 0000000000000..f92ececc681c1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/include/mt6893_pos.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ + +#ifndef _PLATFORM_MT6893_POS_H_ +#define _PLATFORM_MT6893_POS_H_ + + +unsigned int consys_emi_set_remapping_reg(phys_addr_t, phys_addr_t); + +int consys_conninfra_on_power_ctrl(unsigned int enable); +int consys_conninfra_wakeup(void); +int consys_conninfra_sleep(void); +void consys_set_if_pinmux(unsigned int enable); +int consys_polling_chipid(void); + +int connsys_d_die_cfg(void); +int connsys_spi_master_cfg(unsigned int); +int connsys_a_die_cfg(void); +int connsys_afe_wbg_cal(void); +int connsys_subsys_pll_initial(void); +int connsys_low_power_setting(unsigned int, unsigned int); + +int consys_sema_acquire_timeout(unsigned int index, unsigned int usec); +void consys_sema_release(unsigned int index); + +int consys_spi_read(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data); +int consys_spi_write(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data); +int consys_spi_write_offset_range( + enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int value, + unsigned int reg_offset, unsigned int value_offset, unsigned int size); + +int consys_adie_top_ck_en_on(enum consys_adie_ctl_type type); +int consys_adie_top_ck_en_off(enum consys_adie_ctl_type type); + +int consys_spi_clock_switch(enum connsys_spi_speed_type type); +int consys_subsys_status_update(bool, int); +bool consys_is_rc_mode_enable(void); + +void consys_config_setup(void); + +#endif /* _PLATFORM_MT6893_POS_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/mt6893.c b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/mt6893.c new file mode 100644 index 0000000000000..9805786d129e7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/mt6893.c @@ -0,0 +1,445 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 MediaTek Inc. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME "@(%s:%d) " fmt, __func__, __LINE__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "osal.h" +#include "conninfra.h" +#include "conninfra_conf.h" +#include "consys_hw.h" +#include "consys_reg_mng.h" +#include "consys_reg_util.h" +#include "mt6893.h" +#include "emi_mng.h" +#include "mt6893_emi.h" +#include "mt6893_consys_reg.h" +#include "mt6893_consys_reg_offset.h" +#include "mt6893_pos.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define CONSYS_PWR_SPM_CTRL 1 +#define PLATFORM_SOC_CHIP 0x6893 + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static int consys_clk_get_from_dts(struct platform_device *pdev); +static int consys_clock_buffer_ctrl(unsigned int enable); +static unsigned int consys_soc_chipid_get(void); +static unsigned int consys_get_hw_ver(void); +static void consys_clock_fail_dump(void); +static int consys_thermal_query(void); +static int consys_power_state(void); +static int consys_bus_clock_ctrl(enum consys_drv_type, unsigned int, int); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +struct consys_hw_ops_struct g_consys_hw_ops = { + /* load from dts */ + /* TODO: mtcmos should move to a independent module */ + .consys_plt_clk_get_from_dts = consys_clk_get_from_dts, + + /* clock */ + .consys_plt_clock_buffer_ctrl = consys_clock_buffer_ctrl, + .consys_plt_co_clock_type = consys_co_clock_type, + + /* POS */ + .consys_plt_conninfra_on_power_ctrl = consys_conninfra_on_power_ctrl, + .consys_plt_set_if_pinmux = consys_set_if_pinmux, + + .consys_plt_polling_consys_chipid = consys_polling_chipid, + .consys_plt_d_die_cfg = connsys_d_die_cfg, + .consys_plt_spi_master_cfg = connsys_spi_master_cfg, + .consys_plt_a_die_cfg = connsys_a_die_cfg, + .consys_plt_afe_wbg_cal = connsys_afe_wbg_cal, + .consys_plt_subsys_pll_initial = connsys_subsys_pll_initial, + .consys_plt_low_power_setting = connsys_low_power_setting, + .consys_plt_soc_chipid_get = consys_soc_chipid_get, + .consys_plt_conninfra_wakeup = consys_conninfra_wakeup, + .consys_plt_conninfra_sleep = consys_conninfra_sleep, + .consys_plt_is_rc_mode_enable = consys_is_rc_mode_enable, + + /* debug */ + .consys_plt_clock_fail_dump = consys_clock_fail_dump, + .consys_plt_get_hw_ver = consys_get_hw_ver, + + .consys_plt_spi_read = consys_spi_read, + .consys_plt_spi_write = consys_spi_write, + .consys_plt_adie_top_ck_en_on = consys_adie_top_ck_en_on, + .consys_plt_adie_top_ck_en_off = consys_adie_top_ck_en_off, + .consys_plt_spi_clock_switch = consys_spi_clock_switch, + .consys_plt_subsys_status_update = consys_subsys_status_update, + + .consys_plt_thermal_query = consys_thermal_query, + .consys_plt_power_state = consys_power_state, + .consys_plt_config_setup = consys_config_setup, + .consys_plt_bus_clock_ctrl = consys_bus_clock_ctrl, +}; + + +struct clk *clk_scp_conn_main; /*ctrl conn_power_on/off */ +struct consys_plat_thermal_data g_consys_plat_therm_data; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +struct consys_hw_ops_struct* get_consys_platform_ops(void) +{ + return &g_consys_hw_ops; +} + +/* mtcmos contorl */ +int consys_clk_get_from_dts(struct platform_device *pdev) +{ + clk_scp_conn_main = devm_clk_get(&pdev->dev, "conn"); + if (IS_ERR(clk_scp_conn_main)) { + pr_err("[CCF]cannot get clk_scp_conn_main clock.\n"); + return PTR_ERR(clk_scp_conn_main); + } + pr_debug("[CCF]clk_scp_conn_main=%p\n", clk_scp_conn_main); + + return 0; +} + +int consys_platform_spm_conn_ctrl(unsigned int enable) +{ + int ret = 0; + + if (enable) { + ret = clk_prepare_enable(clk_scp_conn_main); + if (ret) { + pr_err("Turn on oonn_infra power fail. Ret=%d\n", ret); + return -1; + } + } else { + clk_disable_unprepare(clk_scp_conn_main); + + } + + return ret; +} + +int consys_clock_buffer_ctrl(unsigned int enable) +{ + /* This function call didn't work now. + * clock buffer is HW controlled, not SW controlled. + * Keep this function call to update status. + */ + if (enable) + KERNEL_clk_buf_ctrl(CLK_BUF_CONN, true); /*open XO_WCN*/ + else + KERNEL_clk_buf_ctrl(CLK_BUF_CONN, false); /*close XO_WCN*/ + return 0; +} + +int consys_co_clock_type(void) +{ + const struct conninfra_conf *conf; + + /* Default solution */ + conf = conninfra_conf_get_cfg(); + if (NULL == conf) { + pr_err("[%s] Get conf fail", __func__); + return -1; + } + /* TODO: for co-clock mode, there are two case: 26M and 52M. Need something to distinguish it. */ + if (conf->tcxo_gpio != 0) + return CONNSYS_CLOCK_SCHEMATIC_26M_EXTCXO; + else + return CONNSYS_CLOCK_SCHEMATIC_26M_COTMS; +} + +unsigned int consys_soc_chipid_get(void) +{ + return PLATFORM_SOC_CHIP; +} + +unsigned int consys_get_hw_ver(void) +{ + return CONN_HW_VER; +} + +void consys_clock_fail_dump(void) +{ + pr_info("[%s]", __func__); +} + + +void update_thermal_data(struct consys_plat_thermal_data* input) +{ + memcpy(&g_consys_plat_therm_data, input, sizeof(struct consys_plat_thermal_data)); + /* Special factor, not in POS */ + /* THERMCR1 [16:17]*/ + CONSYS_REG_WRITE(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERMCR1, + (CONSYS_REG_READ(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERMCR1) | + (0x3 << 16))); + +} + +int calculate_thermal_temperature(int y) +{ + struct consys_plat_thermal_data *data = &g_consys_plat_therm_data; + int t; + int const_offset = 25; + + /* + * MT6635 E1 : read 0x02C = 0x66358A00 + * MT6635 E2 : read 0x02C = 0x66358A10 + * MT6635 E3 : read 0x02C = 0x66358A11 + */ + if (conn_hw_env.adie_hw_version == 0x66358A10 || + conn_hw_env.adie_hw_version == 0x66358A11) + const_offset = 28; + + /* temperature = (y-b)*slope + (offset) */ + /* TODO: offset + 25 : this is only for E1, E2 is 28 */ + t = (y - (data->thermal_b == 0 ? 0x36 : data->thermal_b)) * + ((data->slop_molecule + 209) / 100) + (data->offset + const_offset); + + pr_info("y=[%d] b=[%d] constOffset=[%d] [%d] [%d] => t=[%d]\n", + y, data->thermal_b, const_offset, data->slop_molecule, data->offset, + t); + + return t; +} + +int consys_thermal_query(void) +{ +#define THERMAL_DUMP_NUM 11 +#define LOG_TMP_BUF_SZ 256 +#define TEMP_SIZE 13 + void __iomem *addr = NULL; + int cal_val, res = 0; + /* Base: 0x1800_2000, CONN_TOP_THERM_CTL */ + const unsigned int thermal_dump_crs[THERMAL_DUMP_NUM] = { + 0x00, 0x04, 0x08, 0x0c, + 0x10, 0x14, 0x18, 0x1c, + 0x20, 0x24, 0x28, + }; + char tmp[TEMP_SIZE] = {'\0'}; + char tmp_buf[LOG_TMP_BUF_SZ] = {'\0'}; + unsigned int i; + unsigned int efuse0, efuse1, efuse2, efuse3; + + addr = ioremap_nocache(CONN_GPT2_CTRL_BASE, 0x100); + if (addr == NULL) { + pr_err("GPT2_CTRL_BASE remap fail"); + return -1; + } + + consys_adie_top_ck_en_on(CONNSYS_ADIE_CTL_HOST_CONNINFRA); + + /* Hold Semaphore, TODO: may not need this, because + thermal cr seperate for different */ + if (consys_sema_acquire_timeout(CONN_SEMA_THERMAL_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) { + pr_err("[THERM QRY] Require semaphore fail\n"); + consys_adie_top_ck_en_off(CONNSYS_ADIE_CTL_HOST_CONNINFRA); + iounmap(addr); + return -1; + } + + /* therm cal en */ + CONSYS_REG_WRITE(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_CAL_EN, + (CONSYS_REG_READ(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_CAL_EN) | + (0x1 << 19))); + /* GPT2 En */ + CONSYS_REG_WRITE(addr + CONN_GPT2_CTRL_THERMAL_EN, + (CONSYS_REG_READ(addr + CONN_GPT2_CTRL_THERMAL_EN) | + 0x1)); + + /* thermal trigger */ + CONSYS_REG_WRITE(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_CAL_EN, + (CONSYS_REG_READ(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_CAL_EN) | + (0x1 << 18))); + udelay(500); + /* get thermal value */ + cal_val = CONSYS_REG_READ(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_CAL_EN); + cal_val = (cal_val >> 8) & 0x7f; + + /* thermal debug dump */ + efuse0 = CONSYS_REG_READ(CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_0); + efuse1 = CONSYS_REG_READ(CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_1); + efuse2 = CONSYS_REG_READ(CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_2); + efuse3 = CONSYS_REG_READ(CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_3); + for (i = 0; i < THERMAL_DUMP_NUM; i++) { + snprintf( + tmp, TEMP_SIZE, "[0x%08x]", + CONSYS_REG_READ(CONN_TOP_THERM_CTL_ADDR + thermal_dump_crs[i])); + strncat(tmp_buf, tmp, strlen(tmp)); + } + pr_info("[%s] efuse:[0x%08x][0x%08x][0x%08x][0x%08x] thermal dump: %s", + __func__, efuse0, efuse1, efuse2, efuse3, tmp_buf); + + res = calculate_thermal_temperature(cal_val); + + /* GPT2 disable, no effect on 6893 */ + CONSYS_REG_WRITE(addr + CONN_GPT2_CTRL_THERMAL_EN, + (CONSYS_REG_READ(addr + CONN_GPT2_CTRL_THERMAL_EN) & + ~(0x1))); + + /* disable */ + CONSYS_REG_WRITE(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_CAL_EN, + (CONSYS_REG_READ(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_CAL_EN) & + ~(0x1 << 19))); + + consys_sema_release(CONN_SEMA_THERMAL_INDEX); + consys_adie_top_ck_en_off(CONNSYS_ADIE_CTL_HOST_CONNINFRA); + + iounmap(addr); + + return res; +} + + +int consys_power_state(void) +{ + const char* osc_str[] = { + "fm ", "gps ", "bgf ", "wf ", "ap2conn ", "conn_thm ", "conn_pta ", "conn_infra_bus " + }; + char buf[256] = {'\0'}; + int r = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_2); + int i; + + for (i = 0; i < 8; i++) { + if ((r & (0x1 << (18 + i))) > 0) + strncat(buf, osc_str[i], strlen(osc_str[i])); + } + pr_info("[%s] [0x%x] %s", __func__, r, buf); + return 0; +} + +int consys_bus_clock_ctrl(enum consys_drv_type drv_type, unsigned int bus_clock, int status) +{ + static unsigned int conninfra_bus_clock_wpll_state = 0; + static unsigned int conninfra_bus_clock_bpll_state = 0; + unsigned int wpll_state = conninfra_bus_clock_wpll_state; + unsigned int bpll_state = conninfra_bus_clock_bpll_state; + bool wpll_switch = false, bpll_switch = false; + int check; + + if (status) { + /* Turn on */ + /* Enable BPLL */ + if (bus_clock & CONNINFRA_BUS_CLOCK_BPLL) { + + if (conninfra_bus_clock_bpll_state == 0) { + bpll_switch = true; + } + conninfra_bus_clock_bpll_state |= (0x1 << drv_type); + } + /* Enable WPLL */ + if (bus_clock & CONNINFRA_BUS_CLOCK_WPLL) { + if (conninfra_bus_clock_wpll_state == 0) { + wpll_switch = true; + } + conninfra_bus_clock_wpll_state |= (0x1 << drv_type); + } + + if (bpll_switch || wpll_switch) { + while (consys_sema_acquire_timeout(CONN_SEMA_BUS_CONTROL, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL); + + if (bpll_switch) { + CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_03, (0x1 << 21)); + udelay(30); + } + + if (wpll_switch) { + CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_03, (0x1 << 20)); + udelay(50); + } + + consys_sema_release(CONN_SEMA_BUS_CONTROL); + } + + pr_info("drv=[%d] conninfra_bus_clock_wpll=[%u]->[%u] %s conninfra_bus_clock_bpll=[%u]->[%u] %s", + drv_type, + wpll_state, conninfra_bus_clock_wpll_state, (wpll_switch ? "enable" : ""), + bpll_state, conninfra_bus_clock_bpll_state, (bpll_switch ? "enable" : "")); + } else { + /* Turn off */ + /* Turn off WPLL */ + if (bus_clock & CONNINFRA_BUS_CLOCK_WPLL) { + conninfra_bus_clock_wpll_state &= ~(0x1<[%u] %s conninfra_bus_clock_bpll=[%u]->[%u] %s", + drv_type, + wpll_state, conninfra_bus_clock_wpll_state, (wpll_switch ? "disable" : ""), + bpll_state, conninfra_bus_clock_bpll_state, (bpll_switch ? "disable" : "")); + if (consys_reg_mng_reg_readable() == 0) { + check = consys_reg_mng_is_bus_hang(); + pr_info("[%s] not readable, bus hang check=[%d]", __func__, check); + } + } + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/mt6893_consys_reg.c b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/mt6893_consys_reg.c new file mode 100644 index 0000000000000..e8187e4582321 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/mt6893_consys_reg.c @@ -0,0 +1,783 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 MediaTek Inc. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "consys_reg_mng.h" +#include "mt6893_consys_reg.h" +#include "mt6893_consys_reg_offset.h" +#include "consys_hw.h" +#include "consys_reg_util.h" + +#define LOG_TMP_BUF_SZ 256 +#define CONSYS_POWER_MODE_LEGACY "Legacy" +#define CONSYS_POWER_MODE_RC "RC" + +static int consys_reg_init(struct platform_device *pdev); +static int consys_reg_deinit(void); +static int consys_check_reg_readable(void); +static int consys_is_consys_reg(unsigned int addr); +static int consys_is_bus_hang(void); +static int consys_dump_bus_status(void); +static int consys_dump_conninfra_status(void); +static int consys_dump_cpupcr(enum conn_dump_cpupcr_type, int times, unsigned long interval_us); +static int consys_is_host_csr(unsigned long addr); + +struct consys_reg_mng_ops g_dev_consys_reg_ops = { + .consys_reg_mng_init = consys_reg_init, + .consys_reg_mng_deinit = consys_reg_deinit, + + .consys_reg_mng_check_reable = consys_check_reg_readable, + .consys_reg_mng_is_consys_reg = consys_is_consys_reg, + .consys_reg_mng_is_bus_hang = consys_is_bus_hang, + .consys_reg_mng_dump_bus_status = consys_dump_bus_status, + .consys_reg_mng_dump_conninfra_status = consys_dump_conninfra_status, + .consys_reg_mng_dump_cpupcr = consys_dump_cpupcr, + .consys_reg_mng_is_host_csr = consys_is_host_csr +}; + + +const char* consys_base_addr_index_to_str[CONSYS_BASE_ADDR_MAX] = { + "CONN_INFRA_RGU_BASE", + "CONN_INFRA_CFG_BASE", + "CONN_HOST_CSR_TOP_BASE", + "INFRACFG_AO_BASE", + "TOPRGU_BASE", + "SPM_BASE", + "INFRACFG_BASE", + "CONN_WT_SLP_CTL_REG", + "CONN_AFE_CTL_REG", + "CONN_INFRA_SYSRAM", + "GPIO", + "CONN_RF_SPI_MST_REG", + "CONN_SEMAPHORE", + "CONN_TOP_THERM_CTL", + "IOCFG_RT", +}; + +struct consys_base_addr conn_reg; + +struct consys_reg_mng_ops* get_consys_reg_mng_ops(void) +{ + return &g_dev_consys_reg_ops; +} + +struct consys_base_addr* get_conn_reg_base_addr() +{ + return &conn_reg; +} + +static void consys_bus_hang_dump_c(void) +{ + unsigned long debug_addr, out_addr; + unsigned long value; + int i; + unsigned long debug_setting[] = { + 0xf0001, 0xe0001, 0xd0001, 0xc0001, 0xb0001, 0xa0001, + 0x90001, 0x80001, 0x70001, 0x60001, 0x50001, 0x40001, + 0x30001, 0x20001, 0x10001, 0x30002, 0x20002, 0x10002, + 0x40003, 0x30003, 0x20003, 0x10003 + }; + + /* CONN2AP GALS RX status + * 0x1020_E804 + * + * CONNINFRA sleep protect + * 0x1000_6158[2] ap2conn gals rx slp prot + * 0x1000_6150[13] ap2conn gals tx slp prot + * + * conninfra on2off off2on slp prot + * 0x1806_0184[5] conn_infra on2off slp prot + * 0x1806_0184[3] conn_infra off2on slp prot + */ + pr_info("[CONN_BUS_C] [%x][%x][%x] [%x]", + CONSYS_REG_READ(CON_REG_INFRACFG_BASE_ADDR + INFRA_CONN2AP_GLAS_RC_ST), + CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_BUS_PROTECT2_RDY), + CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_BUS_PROTECT_RDY), + CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL) + ); + + debug_addr = CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_AO_DEBUGSYS; + out_addr = CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT; + + for (i = 0; i < ARRAY_SIZE(debug_setting); i++) { + CONSYS_REG_WRITE(debug_addr, debug_setting[i]); + value = CONSYS_REG_READ(out_addr); + pr_info("[CONN_BUS_C] addr=0x%x value=0x%08x", debug_setting[i], value); + } +} + +static void consys_bus_hang_dump_a_rc(void) +{ + unsigned int i; + char tmp[LOG_TMP_BUF_SZ] = {'\0'}; + char tmp_buf[LOG_TMP_BUF_SZ] = {'\0'}; + + for (i = 0xE50; i <= 0xE94; i += 4) { + snprintf(tmp, LOG_TMP_BUF_SZ, "[%x]", + CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + i)); + strncat(tmp_buf, tmp, strlen(tmp)); + } + pr_info("[rc_trace] %s", tmp_buf); + + memset(tmp_buf, '\0', LOG_TMP_BUF_SZ); + for (i = 0xE98; i <= 0xED4; i += 4) { + snprintf(tmp, LOG_TMP_BUF_SZ, "[%x]", + CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + i)); + strncat(tmp_buf, tmp, strlen(tmp)); + } + pr_info("[rc_timer] %s", tmp_buf); +} + +static void consys_bus_hang_dump_a(void) +{ + void __iomem *addr = NULL; + unsigned int r1, r2, r3, r4, r5, r6, r7 = 0, r8 = 0, r9 = 0, r10, r11; + char tmp_buf[LOG_TMP_BUF_SZ] = {'\0'}; + char rc_buf[LOG_TMP_BUF_SZ] = {'\0'}; + + /* + * r1 : 0x1000_6110 + * r2 : 0x1000_6114 + */ + snprintf(tmp_buf, LOG_TMP_BUF_SZ, "[%s] [0x%x][0x%x]", + (conn_hw_env.is_rc_mode ? CONSYS_POWER_MODE_RC : CONSYS_POWER_MODE_LEGACY), + CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_PCM_REG13_DATA), + CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_SRC_REQ_STA_0)); + + /* RC REQ STA + * r3 : 0x1000_6E28 + * r4 : 0x1000_6E2C + * r5 : 0x1000_6E30 + * r6 : 0x1000_6E34 + */ + snprintf(rc_buf, LOG_TMP_BUF_SZ, "[%x][%x][%x][%x]", + CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_RC_RC_M04_REQ_STA_0), + CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_RC_RC_M05_REQ_STA_0), + CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_RC_RC_M06_REQ_STA_0), + CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_RC_RC_M07_REQ_STA_0)); + + /* + * 0x1000684C [28] DEBUG_IDX_VTCXO_STATE + * 0x1000684C [29] DEBUG_IDX_INFRA_STATE + * 0x1000684C [30] DEBUG_IDX_VRF18_STATE + * 0x1000684C [31] DEBUG_IDX_APSRC_STATE + * r7: 0x1000684C + */ + r1 = CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_PCM_WDT_LATCH_SPARE_0); + + /* + * 0x10006100[0] sc_26m_ck_off 1'b0: 26M on; 1'b1 + * 0x10006100[3] sc_axi_ck_off 1'b0: bus ck on; 1'b1 bus ck off + * 0x10006100[5] sc_md26m_ck_off 1'b0: MD 26M on; 1'b1 MD 26M off + * 0x10006100[20] sc_cksq0_off 1'b0: clock square0 on; 1'b1 clock square off + * r8:0x10006100 + */ + r2 = CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_PCM_REG7_DATA); + + /* + * 0x1000_6304[2] : pwr_on + * 0x1000_616c[1] : pwr_ack + * 0x1000_6304[3] : pwr_on_s + * 0x1000_6170[1] : pwr_ack_s + * 0x1000_6304[1] : iso_en + * 0x1000_6304[0] : ap_sw_rst + * r9 : 0x1000_616C + * r10 : 0x1000_6170 + * r11 : 0x1000_6304 + */ + r3 = CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_PWR_STATUS); + r4 = CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_PWR_STATUS_2ND); + r5 = CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON); + + /* + * sc_md_32k_ck_off + * r12 : 0x1000_644C + */ + r6 = CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_PLL_CON); + + /* + * infra bus clock + * r13 : 0x1000_0000 pdn_conn_32k + * r14 : 0x1000_0010[2:0] + * 0: tck_26m_mx9_ck => 26M + * 1: mainpll_d4_d4 => 136.5M + * 2: mainpll_d7_d2 => 156M + * 3: mainpll_d4_d2 => 273M + * 4: mainpll_d5_d2 => 218.4M + * 5: mainpll_d6_d2 => 182M + * 6: osc_d4 => 65M + */ + addr = ioremap_nocache(0x10000000, 0x20); + if (addr != NULL) { + r7 = CONSYS_REG_READ(addr); + r8 = CONSYS_REG_READ(addr + 0x10); + iounmap(addr); + } + + /* + * r15 : 0x1000_0200 sc_md2_32k_off_en + */ + addr = ioremap_nocache(0x10000200, 0x20); + if (addr != NULL) { + r9 = CONSYS_REG_READ(addr); + iounmap(addr); + } + + /* ap2conn gals sleep protect status + * - 0x1000_1724 [2] / 0x1000_1228 [13] (infracfg_ao)(rx/tx) (sleep protect enable ready) + * r16 : 0x1000_1724 + * r17 : 0x1000_1228 + */ + r10 = CONSYS_REG_READ(CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN2_STA1_OFFSET); + r11 = CONSYS_REG_READ(CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1_OFFSET); + + pr_info("[CONN_BUS_A] %s %s [%x][%x][%x][%x][%x][%x] [%x][%x] [%x][%x][%x]", tmp_buf, + rc_buf, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11); + + consys_bus_hang_dump_a_rc(); +} + +static void consys_bus_hang_dump_b(void) +{ + char tmp_buf[LOG_TMP_BUF_SZ] = {'\0'}; + unsigned int r1, r2, r3, r4, r5, r6, r7; + + /* Legacy Mode */ + /* + * 0x180602c0 + * [4]: conn_srcclkena_ack + * [5]: conn_ap_bus_ack + * [6]: conn_apsrc_ack + * [7]: conn_ddr_en_ack + * cr1 : 0x1806_02c0 + */ + snprintf(tmp_buf, LOG_TMP_BUF_SZ, "[%s] [%x]", + (conn_hw_env.is_rc_mode ? CONSYS_POWER_MODE_RC : CONSYS_POWER_MODE_LEGACY), + CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_0)); + + /* RC Mode */ + /* + * debug sel 0x18001B00[2:0] 3'b010 + * 0x1806_02C8 + * [12] conn_srcclkena_0_bblpm_ack + * [13] conn_srcclkena_0_fpm_ack + * [28] conn_srcclkena_1_bblpm_ack + * [29] conn_srcclkena_1_fpm_ack + * cr2 : 0x1806_02c8 + */ + r1 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_2); + + /* + * Consys status check + * debug sel 0x18001B00[2:0] 3'b010 + * 0x1806_02C8 + * [25] conninfra_bus_osc_en + * [24] conn_pta_osc_en + * [23] conn_thm_osc_en + * [22] ap2conn_osc_en + * [21] wfsys_osc_en + * [20] bgfsys_osc_en + * [19] gpssys_osc_en + * [18] fmsys_osc_en + */ + /*CONSYS_REG_WRITE_MASK(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_DBG_MUX_SEL, + 0x2, 0x7);*/ + /*r1 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_2);*/ + + /* Conninfra Off power state + * 0x1806_02CC + * [15] power_enable + * [14] power_on + * [13] pwer_ack + * [12] pwr_on_s + * [11] pwr_ack_s + * [10] iso_en + * [9] conn_infra_off_xreset_b + * [8] conn_infra_off_hreset_b + * + * cr3 : 0x1806_02CC + */ + r2 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_3); + + + /* conn_infra_on clock 0x1020E504[0] = 1’b1 + * + * cr4 : 0x1020_E504 + */ + r3 = CONSYS_REG_READ(CON_REG_INFRACFG_BASE_ADDR + + INFRA_AP2MD_GALS_CTL); + + /* Check conn_infra off bus clock + * - write 0x1 to 0x1806_0000[0], reset clock detect + * - 0x1806_0000[2] conn_infra off bus clock (should be 1'b1 if clock exist) + * - 0x1806_0000[1] osc clock (should be 1'b1 if clock exist) + * + * cr5 : 0x1806_0000 + */ + CONSYS_SET_BIT(CON_REG_HOST_CSR_ADDR, 0x1); + udelay(200); + r4 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR); + + /* conn_infra on2off sleep protect status + * - 0x1806_0184[5] (sleep protect enable ready), should be 1'b0 + * cr6 : 0x1806_0184 + */ + r5 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL); + + /* CONN_HOST_CSR_DBG_DUMMY_4 + * cr7 : 0x1806_02D0 + */ + r6 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_4); + + /* 0x1806_02D4: dump bus timeout irq status + * cr8 : 0x1806_02D4 + */ + r7 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_BUS_TIMEOUT_IRQ); + + pr_info("[CONN_BUS_B] infra_off %s [%x][%x] [%x][%x][%x] [%x] [%x]" + , tmp_buf, r1, r2, r3, r4, r5, r6, r7); + pr_info("[CONN_BUS_B] 0x1806_0294:[0x%08x] 0x1806_0220:[0x%08x]\n", + CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + 0x0294), + CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + 0x0220)); +} + +#if 0 +static void consys_bus_hang_dump_d(void) +{ + int r1; + + /* check if consys off on + * 0x1806_02cc[8] 1'b1 ==> pwr on, 1'b0 ==> pwr off + */ + r1 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_3); + if (((r1 >> 8) & 0x01) == 0) { + pr_info("[CONN_BUS_D] conninfra off is not on"); + return; + } + + /* PLL & OSC status + * 0x18001810[1] bpll_rdy + * 0x18001810[0] wpll_rdy + * + * OSC + * 0x1800_180C + * [3] : bus_bpll_sw_rdy, 1'b1 conninfra bus clock=166.4M + * [2] : bus_bpll_sw_rdy, 1'b1 conninfra bus clock=83.2M + * [1] : bus_bpll_sw_rdy, 1'b1 conninfra bus clock=32M + * [0] : bus_bpll_sw_rdy, 1'b1 conninfra bus clock=osc + * + * 0x1800_1160[22] ap2conn gals rx slp prot + * 0x1800_1630[3] conn2ap gals tx slp prot + * 0x1800_1634[3] conn2ap gals rx slp prot + * + * 0x1800_1628[3] conn_infra on2off slp pro + * 0x1800_162c[3] conn_infra off2on slp pro + * + * 0x1800_161C[3] gps2conn gals tx slp prot + * 0x1800_161C[7] gps2conn gals rx slp prot + * 0x1800_1618[7] conn2gps gals rx slp prot + * 0x1800_1618[3] conn2gps gals tx slp prot + * + * 0x1800_1614[3] bt2conn gals tx slp prot + * 0x1800_1614[7] bt2conn gals rx slp prot + * 0x1800_1610[3] conn2bt gals tx slp prot + * 0x1800_1610[7] conn2bt gals rx slp prot + * + * 0x1800_1620[3] wf2conn slp prot + */ + pr_info("[CONN_BUS_D] [%x][%x] [%x][%x][%x] [%x][%x] [%x][%x] [%x][%x] [%x]", + CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_PLL_STATUS), /* PLL */ + CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_OSC_STATUS), /* OSC */ + + CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_GALS_AP2CONN_GALS_DBG), + CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_GALS_CONN2AP_TX_SLP_CTRL), + CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_GALS_CONN2AP_RX_SLP_CTRL), + + CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_ON_BUS_SLP_CTRL), /* on2off */ + CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_OFF_BUS_SLP_CTRL),/* off2on */ + + CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL), /* gps2conn */ + CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL), /* conn2gps */ + + CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_GALS_BT2CONN_SLP_CTRL), /* bt2conn */ + CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_GALS_CONN2BT_SLP_CTRL), /* conn2bt */ + + CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_WF_SLP_CTRL) /* w2conn */ + ); +} +#endif + +static int consys_dump_bus_status(void) +{ + consys_bus_hang_dump_c(); + return 0; +} + +static int consys_dump_conninfra_status(void) +{ + consys_bus_hang_dump_a(); + consys_bus_hang_dump_b(); + return 0; +} + +int consys_dump_cpupcr(enum conn_dump_cpupcr_type type, int times, unsigned long interval_us) +{ + int i; + + for (i = 0; i < times; i++) { + pr_info("%s: wm pc=0x%x, wm lp=0x%x, bt pc=0x%x", + __func__, + CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_WM_MCU_PC_DBG), + CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_WM_MCU_GPR_DBG), + CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_BGF_MCU_PC_DBG)); + if (interval_us > 1000) + usleep_range(interval_us - 100, interval_us + 100); + else + udelay(interval_us); + } + + return 0; +} + +static int consys_is_bus_hang(void) +{ + int r; + + /* dump SPM register */ + consys_bus_hang_dump_a(); + + /* STEP - 1 */ + /* + * check kernel API lastbus_timeout_dump + * if return > 0 -> return 0x1 + */ + + /* 1. Check ap2conn gals sleep protect status + * - 0x1000_1724 [2] / 0x1000_1228 [13] (infracfg_ao)(rx/tx) (sleep protect enable ready) + * both of them should be 1'b0 (CR at ap side) + */ + r = CONSYS_REG_READ_BIT(CON_REG_INFRACFG_AO_ADDR + + INFRA_TOPAXI_PROTECTEN2_STA1_OFFSET, (0x1 << 2)); + if (r != 0) + return CONNINFRA_AP2CONN_RX_SLP_PROT_ERR; + + r = CONSYS_REG_READ_BIT(CON_REG_INFRACFG_AO_ADDR + + INFRA_TOPAXI_PROTECTEN_STA1_OFFSET, (0x1 << 13)); + if (r != 0) + return CONNINFRA_AP2CONN_TX_SLP_PROT_ERR; + + /* 2. Check conn_infra_on clock 0x1020E504[0] = 1’b1 */ + r = CONSYS_REG_READ_BIT(CON_REG_INFRACFG_BASE_ADDR + + INFRA_AP2MD_GALS_CTL, 0x1); + if (r != 1) + return CONNINFRA_AP2CONN_CLK_ERR; + + /* STEP - 2 */ + consys_bus_hang_dump_b(); + +#if 0 + /* 3. Check conn_infra off bus clock + * - write 0x1 to 0x1806_0000[0], reset clock detect + * - 0x1806_0000[2] conn_infra off bus clock (should be 1'b1 if clock exist) + * - 0x1806_0000[1] osc clock (should be 1'b1 if clock exist) + */ + CONSYS_SET_BIT(CON_REG_HOST_CSR_ADDR, 0x1); + udelay(500); + r = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR); + if ((r & TOP_BUS_MUC_STAT_HCLK_FR_CK_DETECT_BIT) == 0 || + (r & TOP_BUS_MUC_STAT_OSC_CLK_DETECT_BIT) == 0) + ret |= CONNINFRA_INFRA_BUS_CLK_ERR; +#endif + + /* 4. Check conn_infra off domain bus hang irq status + * - 0x1806_02d4[0], should be 1'b1, or means conn_infra off bus might hang + */ + r = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_BUS_TIMEOUT_IRQ); + + if ((r & 0x1) != 0x1) { + pr_err("conninfra off bus might hang cirq=[0x%08x]", r); + consys_bus_hang_dump_c(); + return CONNINFRA_INFRA_BUS_HANG_IRQ; + } + consys_bus_hang_dump_c(); + +#if 0 + /* 5. Check conn_infra on2off sleep protect status + * - 0x1806_0184[5] (sleep protect enable ready), should be 1'b0 + */ + r = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL); + if (r & TOP_SLP_PROT_CTRL_CONN_INFRA_ON2OFF_SLP_PROT_ACK_BIT) + ret |= CONNINFRA_ON2OFF_SLP_PROT_ERR; + if (ret) { + pr_info("[%s] ret=[%x]", __func__, ret); + consys_bus_hang_dump_c(); + return ret; + } +#endif + /*consys_bus_hang_dump_d();*/ + + return 0; + +} + +int consys_check_reg_readable(void) +{ + int r; + unsigned int rnd; + int delay_time = 1, spent = delay_time, max_wait = 16000; // 1.6 ms + int retry = max_wait / 10; + + /* STEP - 1 */ + /* + * check kernel API lastbus_timeout_dump + * if return > 0 -> return 0x1 + */ + + + /* 1. Check ap2conn gals sleep protect status + * - 0x1000_1724 [2] / 0x1000_1228 [13] (infracfg_ao)(rx/tx) (sleep protect enable ready) + * both of them should be 1'b0 (CR at ap side) + */ + r = CONSYS_REG_READ_BIT(CON_REG_INFRACFG_AO_ADDR + + INFRA_TOPAXI_PROTECTEN2_STA1_OFFSET, (0x1 << 2)); + if (r != 0) + return 0; + + r = CONSYS_REG_READ_BIT(CON_REG_INFRACFG_AO_ADDR + + INFRA_TOPAXI_PROTECTEN_STA1_OFFSET, (0x1 << 13)); + if (r != 0) + return 0; + + /* STEP - 2 */ + + /* 2. Check conn_infra_on clock 0x1020E504[0] = 1’b1 */ + r = CONSYS_REG_READ_BIT(CON_REG_INFRACFG_BASE_ADDR + + INFRA_AP2MD_GALS_CTL, 0x1); + if (r != 1) + return 0; + + /* 3. Check conn_infra off bus clock + * - write 0x1 to 0x1806_0000[0], reset clock detect + * - 0x1806_0000[1] conn_infra off bus clock (should be 1'b1 if clock exist) + * - 0x1806_0000[2] osc clock (should be 1'b1 if clock exist) + */ + + while (retry > 0 && spent < max_wait) { + CONSYS_SET_BIT(CON_REG_HOST_CSR_ADDR, 0x1); + udelay(delay_time); + r = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR); + if ((r & TOP_BUS_MUC_STAT_HCLK_FR_CK_DETECT_BIT) == 0 || + (r & TOP_BUS_MUC_STAT_OSC_CLK_DETECT_BIT) == 0) { + spent += delay_time; + retry--; + if (retry == 0) + pr_info("[%s] retry=0 r=[%x]", __func__, r); + else + delay_time = 10; + rnd = get_random_int() % 10; + spent += rnd; + udelay(rnd); + continue; + } + break; + } + if (retry == 0 || spent >= max_wait) { + pr_info("[%s] readable fail = bus clock retry=[%d] spent=[%d]", __func__, + retry, spent); + return 0; + } + + /* 4. Check conn_infra off domain bus hang irq status + * - 0x1806_02d4[0], should be 1'b1, or means conn_infra off bus might hang + */ + r = CONSYS_REG_READ_BIT(CON_REG_HOST_CSR_ADDR + + CONN_HOST_CSR_TOP_BUS_TIMEOUT_IRQ, 0x1); + if (r != 0x1) + return 0; + + /* 5. Check conn_infra on2off sleep protect status + * - 0x1806_0184[5] (sleep protect enable ready), should be 1'b0 + */ + r = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL); + if (r & TOP_SLP_PROT_CTRL_CONN_INFRA_ON2OFF_SLP_PROT_ACK_BIT) + return 0; + + return 1; +} + + +int consys_is_consys_reg(unsigned int addr) +{ + return 0; +} + + +static int consys_is_host_csr(unsigned long addr) +{ + struct consys_reg_base_addr *host_csr_addr = + &conn_reg.reg_base_addr[CONN_HOST_CSR_TOP_BASE_INDEX]; + + if (addr >= host_csr_addr->phy_addr && + addr < host_csr_addr->phy_addr + host_csr_addr->size) + return 1; + return 0; +} + +unsigned long consys_reg_validate_idx_n_offset(unsigned int idx, unsigned long offset) +{ + unsigned long res; + + if (idx < 0 || idx >= CONSYS_BASE_ADDR_MAX) { + pr_warn("ConsysReg failed: No support the base %d\n", idx); + return 0; + } + + res = conn_reg.reg_base_addr[idx].phy_addr; + + if (res == 0) { + pr_warn("ConsysReg failed: No support the base idx is 0 index=[%d]\n", idx); + return 0; + } + + if (offset >= conn_reg.reg_base_addr[idx].size) { + pr_warn("ConnReg failed: index(%d), offset(%d) over max size(%llu) %s\n", + idx, (int) offset, conn_reg.reg_base_addr[idx].size); + return 0; + } + return res; +} + +int consys_find_can_write_reg(unsigned int *idx, unsigned long *offset) +{ + int i; + size_t addr = 0, addr_offset; + int max, mask = 0x0000000F; + int before, after, ret; + + addr = conn_reg.reg_base_addr[CONN_INFRA_RGU_BASE_INDEX].vir_addr; + max = conn_reg.reg_base_addr[CONN_INFRA_RGU_BASE_INDEX].size; + + pr_info("[%s] addr=[%p]\n", __func__, addr); + + for (i = 0x0; i < max; i += 0x4) { + ret = 0; + addr_offset = addr + i; + before = CONSYS_REG_READ(addr_offset); + CONSYS_REG_WRITE_MASK(addr_offset, 0xFFFFFFFF, mask); + after = CONSYS_REG_READ(addr_offset); + if ((after & mask) != (0xFFFFFFFF & mask)) + ret = -1; + + CONSYS_REG_WRITE_MASK(addr_offset, 0x0, mask); + after = CONSYS_REG_READ(addr_offset); + if ((after & mask) != (0x0 & mask)) + ret = -1; + + CONSYS_REG_WRITE_MASK(addr_offset, before, mask); + + pr_info("[%s] addr=[%p] [%d]\n", __func__, addr_offset, ret); + if (ret == 0) { + *idx = CONN_INFRA_RGU_BASE_INDEX; + *offset = i; + return 0; + } + } + return -1; + +} + + +unsigned long consys_reg_get_phy_addr_by_idx(unsigned int idx) +{ + if (idx >= CONSYS_BASE_ADDR_MAX) + return 0; + return conn_reg.reg_base_addr[idx].phy_addr; +} + +unsigned long consys_reg_get_virt_addr_by_idx(unsigned int idx) +{ + if (idx >= CONSYS_BASE_ADDR_MAX) + return 0; + return conn_reg.reg_base_addr[idx].vir_addr; +} + + +int consys_reg_get_chip_id_idx_offset(unsigned int *idx, unsigned long *offset) +{ + *idx = CONN_INFRA_CFG_BASE_INDEX; + *offset = CONN_CFG_ID_OFFSET; + return 0; +} + +int consys_reg_get_reg_symbol_num(void) +{ + return CONSYS_BASE_ADDR_MAX; +} + + +int consys_reg_init(struct platform_device *pdev) +{ + int ret = -1; + struct device_node *node = NULL; + struct consys_reg_base_addr *base_addr = NULL; + struct resource res; + int flag, i = 0; + + node = pdev->dev.of_node; + pr_info("[%s] node=[%p]\n", __func__, node); + if (node) { + for (i = 0; i < CONSYS_BASE_ADDR_MAX; i++) { + base_addr = &conn_reg.reg_base_addr[i]; + + ret = of_address_to_resource(node, i, &res); + if (ret) { + pr_err("Get Reg Index(%d-%s) failed", + i, consys_base_addr_index_to_str[i]); + continue; + } + + base_addr->phy_addr = res.start; + base_addr->vir_addr = + (unsigned long) of_iomap(node, i); + of_get_address(node, i, &(base_addr->size), &flag); + + pr_info("Get Index(%d-%s) phy(0x%zx) baseAddr=(0x%zx) size=(0x%zx)", + i, consys_base_addr_index_to_str[i], base_addr->phy_addr, + base_addr->vir_addr, base_addr->size); + } + + } else { + pr_err("[%s] can't find CONSYS compatible node\n", __func__); + return ret; + } + return 0; + +} + +static int consys_reg_deinit(void) +{ + int i = 0; + + for (i = 0; i < CONSYS_BASE_ADDR_MAX; i++) { + if (conn_reg.reg_base_addr[i].vir_addr) { + pr_info("[%d] Unmap %s (0x%zx)", + i, consys_base_addr_index_to_str[i], + conn_reg.reg_base_addr[i].vir_addr); + iounmap((void __iomem*)conn_reg.reg_base_addr[i].vir_addr); + conn_reg.reg_base_addr[i].vir_addr = 0; + } + } + + return 0; +} + diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/mt6893_emi.c b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/mt6893_emi.c new file mode 100644 index 0000000000000..0bdde11f47682 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/mt6893_emi.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 MediaTek Inc. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME "@(%s:%d) " fmt, __func__, __LINE__ + +#include +#include +#ifdef CONFIG_MTK_EMI +#include +#endif +#include + +#include +#include "mt6893_emi.h" +#include "mt6893.h" +#include "mt6893_consys_reg.h" +#include "consys_hw.h" +#include "consys_reg_util.h" +#include "mt6893_pos.h" + +/* For MCIF */ +#include + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define REGION_CONN 27 + +#define DOMAIN_AP 0 +#define DOMAIN_CONN 2 +#define DOMAIN_SCP 3 + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + +extern unsigned long long gConEmiSize; +extern phys_addr_t gConEmiPhyBase; + +struct consys_platform_emi_ops g_consys_platform_emi_ops = { + .consys_ic_emi_mpu_set_region_protection = consys_emi_mpu_set_region_protection, + .consys_ic_emi_set_remapping_reg = consys_emi_set_remapping_reg, + .consys_ic_emi_get_md_shared_emi = consys_emi_get_md_shared_emi, +}; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +struct consys_platform_emi_ops* get_consys_platform_emi_ops(void) +{ + return &g_consys_platform_emi_ops; +} + +int consys_emi_mpu_set_region_protection(void) +{ + struct emimpu_region_t region; + unsigned long long start = gConEmiPhyBase; + unsigned long long end = gConEmiPhyBase + gConEmiSize - 1; + + mtk_emimpu_init_region(®ion, REGION_CONN); + mtk_emimpu_set_addr(®ion, start, end); + mtk_emimpu_set_apc(®ion, DOMAIN_AP, MTK_EMIMPU_NO_PROTECTION); + mtk_emimpu_set_apc(®ion, DOMAIN_CONN, MTK_EMIMPU_NO_PROTECTION); + /* for scp */ + mtk_emimpu_set_apc(®ion, DOMAIN_SCP, MTK_EMIMPU_NO_PROTECTION); + mtk_emimpu_set_protection(®ion); + mtk_emimpu_free_region(®ion); + + pr_info("setting MPU for EMI share memory\n"); + return 0; +} + +void consys_emi_get_md_shared_emi(phys_addr_t* base, unsigned int* size) +{ + phys_addr_t mdPhy = 0; + int ret = 0; + +#ifdef CONFIG_MTK_ECCCI_DRIVER + mdPhy = get_smem_phy_start_addr(MD_SYS1, SMEM_USER_RAW_MD_CONSYS, &ret); + pr_info("MCIF base=0x%llx size=0x%x", mdPhy, ret); +#else + pr_info("[%s] ECCCI Driver is not supported.\n", __func__); +#endif + if (ret && mdPhy) { + if (base) + *base = mdPhy; + if (size) + *size = ret; + } else { + pr_info("MCIF is not supported"); + if (base) + *base = 0; + if (size) + *size = 0; + } +} + diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/mt6893_pmic.c b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/mt6893_pmic.c new file mode 100644 index 0000000000000..3e91b04192514 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/mt6893_pmic.c @@ -0,0 +1,426 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 MediaTek Inc. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME "@(%s:%d) " fmt, __func__, __LINE__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "consys_hw.h" +#include "consys_reg_util.h" +#include "osal.h" +#include "mt6893.h" +#include "mt6893_pmic.h" +#include "mt6893_pos.h" +#include "mt6893_consys_reg.h" +#include "mt6893_consys_reg_offset.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 +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static int consys_plt_pmic_get_from_dts(struct platform_device *pdev, struct conninfra_dev_cb* dev_cb); + +static int consys_plt_pmic_common_power_ctrl(unsigned int enable); +static int consys_plt_pmic_wifi_power_ctrl(unsigned int enable); +static int consys_plt_pmic_bt_power_ctrl(unsigned int enable); +static int consys_plt_pmic_gps_power_ctrl(unsigned int enable); +static int consys_plt_pmic_fm_power_ctrl(unsigned int enable); +/* VCN33_1 is enable when BT or Wi-Fi is on */ +static int consys_pmic_vcn33_1_power_ctl(bool enable, struct regulator* reg_VCN33_1); +/* VCN33_2 is enable when Wi-Fi is on */ +static int consys_pmic_vcn33_2_power_ctl(bool enable); + +static int consys_plt_pmic_event_notifier(unsigned int id, unsigned int event); + +static int consys_plt_pmic_exit_idle_power_ctrl(void); +static int consys_plt_pmic_enter_idle_power_ctrl(void); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +CONSYS_PLATFORM_PMIC_OPS g_consys_platform_pmic_ops = { + .consys_pmic_get_from_dts = consys_plt_pmic_get_from_dts, + /* vcn 18 */ + .consys_pmic_common_power_ctrl = consys_plt_pmic_common_power_ctrl, + .consys_pmic_wifi_power_ctrl = consys_plt_pmic_wifi_power_ctrl, + .consys_pmic_bt_power_ctrl = consys_plt_pmic_bt_power_ctrl, + .consys_pmic_gps_power_ctrl = consys_plt_pmic_gps_power_ctrl, + .consys_pmic_fm_power_ctrl = consys_plt_pmic_fm_power_ctrl, + .consys_pmic_event_notifier = consys_plt_pmic_event_notifier, +}; + +struct regulator *reg_VCN13; +struct regulator *reg_VCN18; +struct regulator *reg_VCN33_1_BT; +struct regulator *reg_VCN33_1_WIFI; +struct regulator *reg_VCN33_2_WIFI; +struct notifier_block vcn13_nb; + +static struct conninfra_dev_cb* g_dev_cb; +static int g_first_power_on = 0; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +P_CONSYS_PLATFORM_PMIC_OPS get_consys_platform_pmic_ops(void) +{ + return &g_consys_platform_pmic_ops; +} + + +static int consys_vcn13_oc_notify(struct notifier_block *nb, unsigned long event, + void *unused) +{ + if (event != REGULATOR_EVENT_OVER_CURRENT) + return NOTIFY_OK; + + if (g_dev_cb != NULL && g_dev_cb->conninfra_pmic_event_notifier != NULL) + g_dev_cb->conninfra_pmic_event_notifier(0, 0); + return NOTIFY_OK; +} + +static int consys_plt_pmic_event_notifier(unsigned int id, unsigned int event) +{ +#define ATOP_DUMP_NUM 10 +#define LOG_TMP_BUF_SZ 256 + static int oc_counter = 0; + int ret; + unsigned int adie_value = 0; + unsigned int value1 = 0, value2 = 0, value3 = 0; + const unsigned int adie_cr_list[ATOP_DUMP_NUM] = { + 0xa10, 0x90, 0x94, 0xa0, + 0xa18, 0xa1c, 0xc8, 0x3c, + 0x0b4, 0x34c + }; + int index; + char tmp[LOG_TMP_BUF_SZ] = {'\0'}; + char tmp_buf[LOG_TMP_BUF_SZ] = {'\0'}; + + oc_counter++; + pr_info("[%s] VCN13 OC times: %d\n", __func__, oc_counter); + + consys_hw_is_bus_hang(); + ret = consys_hw_force_conninfra_wakeup(); + if (ret) { + pr_err("[%s] force conninfra wakeup fail\n", __func__); + return NOTIFY_OK; + } + + value1 = CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_ADIE_CTL); + value2 = CONSYS_REG_READ(CON_REG_WT_SPL_CTL_ADDR + 0xa8); + if (consys_sema_acquire_timeout(CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_SUCCESS) { + value3 = CONSYS_REG_READ(CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_TOP_CK_EN_CTRL); + consys_sema_release(CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX); + pr_info("[VCN13 OC] D-die: 0x1800_1900:0x%08x 0x1800_50A8:0x%08x 0x1805_2830:0x%08x\n", value1, value2, value3); + } else { + pr_info("[VCN13 OC] D-die: 0x1800_1900:0x%08x 0x1800_50A8:0x%08x\n", value1, value2); + } + + for (index = 0; index < ATOP_DUMP_NUM; index++) { + consys_spi_read(SYS_SPI_TOP, adie_cr_list[index], &adie_value); + snprintf(tmp, LOG_TMP_BUF_SZ, " [0x%04x: 0x%08x]", adie_cr_list[index], adie_value); + strncat(tmp_buf, tmp, strlen(tmp)); + } + pr_info("[VCN13 OC] ATOP:%s\n", tmp_buf); + consys_hw_force_conninfra_sleep(); + + return NOTIFY_OK; +} + +int consys_plt_pmic_get_from_dts(struct platform_device *pdev, struct conninfra_dev_cb* dev_cb) +{ + int ret; + + g_dev_cb = dev_cb; +//#if CONSYS_PMIC_CTRL_ENABLE + reg_VCN13 = devm_regulator_get_optional(&pdev->dev, "vcn13"); + if (!reg_VCN13) + pr_err("Regulator_get VCN_13 fail\n"); + else { + vcn13_nb.notifier_call = consys_vcn13_oc_notify; + ret = devm_regulator_register_notifier(reg_VCN13, &vcn13_nb); + if (ret) { + pr_info("VCN13 regulator notifier request failed\n"); + } + /* Set VS2 to 1.4625V */ + KERNEL_pmic_set_register_value(PMIC_RG_BUCK_VS2_VOSEL, 0x35); + } + reg_VCN18 = regulator_get(&pdev->dev, "vcn18"); + if (!reg_VCN18) + pr_err("Regulator_get VCN_18 fail\n"); + reg_VCN33_1_BT = regulator_get(&pdev->dev, "vcn33_1_bt"); + if (!reg_VCN33_1_BT) + pr_err("Regulator_get VCN33_1_BT fail\n"); + reg_VCN33_1_WIFI = regulator_get(&pdev->dev, "vcn33_1_wifi"); + if (!reg_VCN33_1_WIFI) + pr_err("Regulator_get VCN33_1_WIFI fail\n"); + reg_VCN33_2_WIFI = regulator_get(&pdev->dev, "vcn33_2_wifi"); + if (!reg_VCN33_2_WIFI) + pr_err("Regulator_get VCN33_WIFI fail\n"); +//#endif + return 0; +} + +int consys_pmic_vcn33_1_power_ctl(bool enable, struct regulator *reg_VCN33_1) +{ + int ret; + if (enable) { + if (consys_is_rc_mode_enable()) { + /* PMRC_EN[6][5] HW_OP_EN = 1, HW_OP_CFG = 0 */ + KERNEL_pmic_ldo_vcn33_1_lp(SRCLKEN6, 0, 1, HW_OFF); + KERNEL_pmic_ldo_vcn33_1_lp(SRCLKEN5, 0, 1, HW_OFF); + /* SW_LP =0 */ + KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN33_1_LP, 0); + regulator_set_voltage(reg_VCN33_1, 3300000, 3300000); + /* SW_EN=0 */ + /* For RC mode, we don't have to control VCN33_1 & VCN33_2 */ + #if 0 + /* regulator_disable(reg_VCN33_1); */ + #endif + } else { + /* HW_OP_EN = 1, HW_OP_CFG = 0 */ + KERNEL_pmic_ldo_vcn33_1_lp(SRCLKEN0, 1, 1, HW_OFF); + /* SW_LP =0 */ + KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN33_1_LP, 0); + regulator_set_voltage(reg_VCN33_1, 3300000, 3300000); + /* SW_EN=1 */ + ret = regulator_enable(reg_VCN33_1); + if (ret) + pr_err("Enable VCN33_1 fail. ret=%d\n", ret); + } + } else { + if (consys_is_rc_mode_enable()) { + /* Do nothing */ + } else { + regulator_disable(reg_VCN33_1); + } + } + return 0; +} + +int consys_pmic_vcn33_2_power_ctl(bool enable) +{ + int ret; + + if (enable) { + if (consys_is_rc_mode_enable()) { + /* PMRC_EN[6] HW_OP_EN = 1, HW_OP_CFG = 0 */ + KERNEL_pmic_ldo_vcn33_2_lp(SRCLKEN6, 0, 1, HW_OFF); + /* SW_LP =0 */ + KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN33_2_LP, 0); + regulator_set_voltage(reg_VCN33_2_WIFI, 3300000, 3300000); + /* SW_EN=0 */ + /* For RC mode, we don't have to control VCN33_1 & VCN33_2 */ + #if 0 + regulator_disable(reg_VCN33_2_WIFI); + #endif + } else { + /* HW_OP_EN = 1, HW_OP_CFG = 0 */ + KERNEL_pmic_ldo_vcn33_2_lp(SRCLKEN0, 1, 1, HW_OFF); + /* SW_LP =0 */ + KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN33_2_LP, 0); + regulator_set_voltage(reg_VCN33_2_WIFI, 3300000, 3300000); + /* SW_EN=1 */ + ret = regulator_enable(reg_VCN33_2_WIFI); + if (ret) + pr_err("Enable VCN33_2 fail. ret=%d\n", ret); + } + } else { + if (consys_is_rc_mode_enable()) { + /* Do nothing */ + } else { + regulator_disable(reg_VCN33_2_WIFI); + } + } + return 0; +} + +int consys_plt_pmic_common_power_ctrl(unsigned int enable) +{ + int ret; + + if (enable) { + if (consys_is_rc_mode_enable()) { + /* RC mode */ + /* VCN18 */ + /* PMRC_EN[7][6][5][4] HW_OP_EN = 1, HW_OP_CFG = 0 */ + KERNEL_pmic_ldo_vcn18_lp(SRCLKEN7, 0, 1, HW_OFF); + KERNEL_pmic_ldo_vcn18_lp(SRCLKEN6, 0, 1, HW_OFF); + KERNEL_pmic_ldo_vcn18_lp(SRCLKEN5, 0, 1, HW_OFF); + KERNEL_pmic_ldo_vcn18_lp(SRCLKEN4, 0, 1, HW_OFF); + /* SW_LP =1 */ + KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN18_LP, 0); + regulator_set_voltage(reg_VCN18, 1800000, 1800000); + ret = regulator_enable(reg_VCN18); + if (ret) + pr_err("Enable VCN18 fail. ret=%d\n", ret); + + /* VCN13 */ + /* PMRC_EN[7][6][5][4] HW_OP_EN = 1, HW_OP_CFG = 0 */ + KERNEL_pmic_ldo_vcn13_lp(SRCLKEN7, 0, 1, HW_OFF); + KERNEL_pmic_ldo_vcn13_lp(SRCLKEN6, 0, 1, HW_OFF); + KERNEL_pmic_ldo_vcn13_lp(SRCLKEN5, 0, 1, HW_OFF); + KERNEL_pmic_ldo_vcn13_lp(SRCLKEN4, 0, 1, HW_OFF); + /* SW_LP =1 */ + KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN13_LP, 0); + regulator_set_voltage(reg_VCN13, 1300000, 1300000); + ret = regulator_enable(reg_VCN13); + if (ret) + pr_err("Enable VCN13 fail. ret=%d\n", ret); + + g_first_power_on = 1; + } else { + /* Legacy mode */ + /* HW_OP_EN = 1, HW_OP_CFG = 1 */ + KERNEL_pmic_ldo_vcn18_lp(SRCLKEN0, 1, 1, HW_LP); + /* SW_LP=0 */ + KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN18_LP, 0); + regulator_set_voltage(reg_VCN18, 1800000, 1800000); + /* SW_EN=1 */ + ret = regulator_enable(reg_VCN18); + if (ret) + pr_err("Enable VCN18 fail. ret=%d\n", ret); + + /* HW_OP_EN = 1, HW_OP_CFG = 1 */ + KERNEL_pmic_ldo_vcn13_lp(SRCLKEN0, 1, 1, HW_LP); + regulator_set_voltage(reg_VCN13, 1300000, 1300000); + /* SW_LP=0 */ + KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN13_LP, 0); + /* SW_EN=1 */ + ret = regulator_enable(reg_VCN13); + if (ret) + pr_err("Enable VCN13 fail. ret=%d\n", ret); + } + } else { + regulator_disable(reg_VCN13); + regulator_disable(reg_VCN18); + } + return 0; +} + +int consys_plt_pmic_wifi_power_ctrl(unsigned int enable) +{ + int ret; + + if (enable) + consys_plt_pmic_enter_idle_power_ctrl(); + + ret = consys_pmic_vcn33_1_power_ctl(enable, reg_VCN33_1_WIFI); + if (ret) + pr_err("%s VCN33_1 fail\n", (enable? "Enable" : "Disable")); + ret = consys_pmic_vcn33_2_power_ctl(enable); + if (ret) + pr_err("%s VCN33_2 fail\n", (enable? "Enable" : "Disable")); + return ret; +} + +int consys_plt_pmic_bt_power_ctrl(unsigned int enable) +{ + if (enable) { + consys_plt_pmic_exit_idle_power_ctrl(); + udelay(50); + + /* request VS2 to 1.4V by VS2 VOTER (use bit 4) */ + KERNEL_pmic_set_register_value(PMIC_RG_BUCK_VS2_VOTER_EN_SET, 0x10); + + /* Set VS2 sleep voltage to 1.375V */ + KERNEL_pmic_set_register_value(PMIC_RG_BUCK_VS2_VOSEL_SLEEP, 0x2E); + /* Set VCN13 to 1.37V */ + KERNEL_pmic_set_register_value(PMIC_RG_VCN13_VOCAL, 0x7); + udelay(50); + consys_plt_pmic_enter_idle_power_ctrl(); + } else { + consys_plt_pmic_exit_idle_power_ctrl(); + udelay(50); + /* restore VCN13 to 1.3V */ + KERNEL_pmic_set_register_value(PMIC_RG_VCN13_VOCAL, 0); + /* Restore VS2 sleep voltage to 1.35V */ + KERNEL_pmic_set_register_value(PMIC_RG_BUCK_VS2_VOSEL_SLEEP, 0x2C); + + /* clear bit 4 of VS2 VOTER then VS2 can restore to 1.35V */ + KERNEL_pmic_set_register_value(PMIC_RG_BUCK_VS2_VOTER_EN_CLR, 0x10); + udelay(50); + consys_plt_pmic_enter_idle_power_ctrl(); + } + return consys_pmic_vcn33_1_power_ctl(enable, reg_VCN33_1_BT); +} + +int consys_plt_pmic_gps_power_ctrl(unsigned int enable) +{ + if (enable) + consys_plt_pmic_enter_idle_power_ctrl(); + return 0; +} + +int consys_plt_pmic_fm_power_ctrl(unsigned int enable) +{ + if (enable) + consys_plt_pmic_enter_idle_power_ctrl(); + return 0; +} + +int consys_plt_pmic_exit_idle_power_ctrl(void) +{ + if (consys_is_rc_mode_enable() && g_first_power_on == 0) { + KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN18_LP, 0); + KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN13_LP, 0); + g_first_power_on = 1; + } + return 0; +} + +int consys_plt_pmic_enter_idle_power_ctrl(void) +{ + if (consys_is_rc_mode_enable() && g_first_power_on == 1) { + KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN18_LP, 1); + KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN13_LP, 1); + g_first_power_on = 0; + } + return 0; +} + diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/mt6893_pos.c b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/mt6893_pos.c new file mode 100644 index 0000000000000..358b6df286dce --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/mt6893/mt6893_pos.c @@ -0,0 +1,2333 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 MediaTek Inc. + */ + +#include "consys_hw.h" /* for semaphore index */ +/* platform dependent */ +#include "plat_def.h" +/* macro for read/write cr */ +#include "consys_reg_util.h" +#include "consys_reg_mng.h" +/* cr base address */ +#include "mt6893_consys_reg.h" +/* cr offset */ +#include "mt6893_consys_reg_offset.h" +/* For function declaration */ +#include "mt6893_pos.h" +#include "mt6893.h" + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define CONN_INFRA_SYSRAM__A_DIE_DIG_TOP_CK_EN_MASK 0x7f + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +struct a_die_reg_config { + unsigned int reg; + unsigned int mask; + unsigned int config; +}; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +const static char* gAdieCtrlType[CONNSYS_ADIE_CTL_MAX] = +{ + "CONNSYS_ADIE_CTL_HOST_BT", + "CONNSYS_ADIE_CTL_HOST_FM", + "CONNSYS_ADIE_CTL_HOST_GPS", + "CONNSYS_ADIE_CTL_HOST_WIFI", + "CONNSYS_ADIE_CTL_HOST_CONNINFRA", + "CONNSYS_ADIE_CTL_FW_BT", + "CONNSYS_ADIE_CTL_FW_WIFI", +}; + +const static char* g_spi_system_name[SYS_SPI_MAX] = { + "SYS_SPI_WF1", + "SYS_SPI_WF", + "SYS_SPI_BT", + "SYS_SPI_FM", + "SYS_SPI_GPS", + "SYS_SPI_TOP", + "SYS_SPI_WF2", + "SYS_SPI_WF3", +}; + +#define ADIE_CONFIG_NUM 2 + +// E1 WF/GPS/FM on(default) +const static struct a_die_reg_config adie_e1_default[ADIE_CONFIG_NUM] = +{ + {ATOP_RG_TOP_XTAL_01, 0xc180, 0xc180}, + {ATOP_RG_TOP_XTAL_02, 0xf0ff0080, 0xd0550080}, +}; + +const static struct a_die_reg_config adie_e1_bt_only[ADIE_CONFIG_NUM] = +{ + {ATOP_RG_TOP_XTAL_01, 0xc180, 0x100}, + {ATOP_RG_TOP_XTAL_02, 0xf0ff0080, 0xf0ff0000}, +}; + +const static struct a_die_reg_config adie_e2_default[ADIE_CONFIG_NUM] = +{ + {ATOP_RG_TOP_XTAL_01, 0xc180, 0xc180}, + {ATOP_RG_TOP_XTAL_02, 0xf0ff0080, 0x50550080}, +}; + +const static struct a_die_reg_config adie_e2_bt_only[ADIE_CONFIG_NUM] = +{ + {ATOP_RG_TOP_XTAL_01, 0xc180, 0x100}, + {ATOP_RG_TOP_XTAL_02, 0xf0ff0080, 0x70ff0000}, +}; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static int consys_spi_read_nolock(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data); +static int consys_spi_write_nolock(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data); +static void consys_spi_write_offset_range_nolock( + enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int value, + unsigned int reg_offset, unsigned int value_offset, unsigned int size); +static int connsys_a_die_thermal_cal(int efuse_valid, unsigned int efuse); + +unsigned int consys_emi_set_remapping_reg( + phys_addr_t con_emi_base_addr, + phys_addr_t md_shared_emi_base_addr) +{ + /* EMI Registers remapping */ + CONSYS_REG_WRITE_OFFSET_RANGE(CON_REG_HOST_CSR_ADDR + CONN2AP_REMAP_MCU_EMI_BASE_ADDR_OFFSET, + con_emi_base_addr, 0, 16, 20); + + CONSYS_REG_WRITE_MASK( + CON_REG_HOST_CSR_ADDR + CONN2AP_REMAP_WF_PERI_BASE_ADDR_OFFSET, + 0x01000, 0xFFFFF); + CONSYS_REG_WRITE_MASK( + CON_REG_HOST_CSR_ADDR + CONN2AP_REMAP_BT_PERI_BASE_ADDR_OFFSET, + 0x01000, 0xFFFFF); + CONSYS_REG_WRITE_MASK( + CON_REG_HOST_CSR_ADDR + CONN2AP_REMAP_GPS_PERI_BASE_ADDR_OFFSET, + 0x01000, 0xFFFFF); + + if (md_shared_emi_base_addr) { + CONSYS_REG_WRITE_OFFSET_RANGE( + CON_REG_HOST_CSR_ADDR + CONN2AP_REMAP_MD_SHARE_EMI_BASE_ADDR_OFFSET, + md_shared_emi_base_addr, 0, 16, 20); + } + pr_info("connsys_emi_base=[0x%llx] mcif_emi_base=[0x%llx] remap cr: connsys=[0x%08x] mcif=[0x%08x]\n", + con_emi_base_addr, md_shared_emi_base_addr, + CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN2AP_REMAP_MCU_EMI_BASE_ADDR_OFFSET), + CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN2AP_REMAP_MD_SHARE_EMI_BASE_ADDR_OFFSET)); + return 0; +} + +int consys_conninfra_on_power_ctrl(unsigned int enable) +{ + int check; + if (enable) { +#ifndef CONFIG_FPGA_EARLY_PORTING + /* Turn on SPM clock (apply this for SPM's CONNSYS power control related CR accessing) + * address: 0x1000_6000[0] + * 0x1000_6000[31:16] + * Data: [0]=1'b1 + * [31:16]=16'h0b16 (key) + * Action: write + */ + CONSYS_REG_WRITE_MASK( + CON_REG_SPM_BASE_ADDR + SPM_POWERON_CONFIG_EN, 0x0b160001, 0xffff0001); +#endif + + /* Turn on ap2conn host_ck CG (ECO) + * Address: INFRA_AP2MD_GALS_CTL[0] (0x1020E504[0]) + * Value: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CON_REG_INFRACFG_BASE_ADDR + INFRA_AP2MD_GALS_CTL, 0x1); + +#if MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE + check = consys_platform_spm_conn_ctrl(enable); + if (check) { + pr_err("Turn on conn_infra power fail\n"); + return -1; + } +#else + pr_info("Turn on conn_infra power by POS steps\n"); + /* Assert "conn_infra_on" primary part power on, set "connsys_on_domain_pwr_on"=1 + * Address: 0x1000_6304[2] + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x4); + +#ifndef CONFIG_FPGA_EARLY_PORTING + /* Check "conn_infra_on" primary part power status, check "connsys_on_domain_pwr_ack"=1 + * (polling "10 times" and each polling interval is "0.5ms") + * Address: 0x1000_616C[1] + * Data: 1'b1 + * Action: polling + */ + check = 0; + CONSYS_REG_BIT_POLLING(CON_REG_SPM_BASE_ADDR + SPM_PWR_STATUS, 1, 1, 10, 500, check); + if (check != 0) + pr_err("Check conn_infra_on primary power fail. 0x1000_616C is 0x%08x. Expect [1] as 1.\n", + CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_PWR_STATUS)); +#endif + + /* Assert "conn_infra_on" secondary part power on, set "connsys_on_domain_pwr_on_s"=1 + * Address: 0x1000_6304[3] + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x8); + +#ifndef CONFIG_FPGA_EARLY_PORTING + /* Check "conn_infra_on" secondary part power status, + * check "connsys_on_domain_pwr_ack_s"=1 + * (polling "10 times" and each polling interval is "0.5ms") + * Address: 0x1000_6170[1] + * Data: 1'b1 + * Action: polling + */ + check = 0; + CONSYS_REG_BIT_POLLING(CON_REG_SPM_BASE_ADDR + SPM_PWR_STATUS_2ND, 1, 1, 10, 500, check); + if (check != 0) + pr_err("Check conn_infra_on secondary power fail. 0x1000_6170 is 0x%08x. Expect [1] as 1.\n", + CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_PWR_STATUS_2ND)); +#endif + + /* Turn on AP-to-CONNSYS bus clock, set "conn_clk_dis"=0 + * (apply this for bus clock toggling) + * Address: 0x1000_6304[4] + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x10); + + /* Wait 1 us */ + udelay(1); + + /* De-assert "conn_infra_on" isolation, set "connsys_iso_en"=0 + * Address: 0x1000_6304[1] + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x2); + + /* De-assert CONNSYS S/W reset (TOP RGU CR), + * set "ap_sw_rst_b"=1 + * Address: WDT_SWSYSRST[9] (0x1000_7018[9]) + * WDT_SWSYSRST[31:24] (0x1000_7018[31:24]) + * Data: [9]=1'b0 + * [31:24]=8'h88 (key) + * Action: Write + */ + CONSYS_REG_WRITE_MASK( + CON_REG_TOP_RGU_ADDR + TOP_RGU_WDT_SWSYSRST,0x88000000, 0xff000200); + + /* De-assert CONNSYS S/W reset (SPM CR), set "ap_sw_rst_b"=1 + * Address: CONN_PWR_CON[0] (0x1000_6304[0]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x1); + + /* Wait 0.5ms */ + udelay(500); + + /* Disable AXI bus sleep protect */ + /* Turn off AXI RX bus sleep protect (AP2CONN AXI Bus protect) + * (apply this for INFRA AXI bus accessing when CONNSYS had been turned on) + * Address: 0x1000_1718[31:0] (INFRA_TOPAXI_PROTECTEN2_CLR) + * Data: 0x0000_0002 + * Action: write + */ + CONSYS_REG_WRITE( + CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN2_CLR_OFFSET, + 0x00000002); + +#ifndef CONFIG_FPGA_EARLY_PORTING + /* Check AXI RX bus sleep protect turn off + * (polling "100 times" and each polling interval is "0.5ms") + * Address: 0x1000_1724[2] (INFRA_TOPAXI_PROTECTEN2_STA1[2]) + * Data: 1'b0 + * Action: polling + */ + check = 0; + CONSYS_REG_BIT_POLLING( + CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN2_STA1_OFFSET, + 2, 0, 100, 500, check); + if (check != 0) + pr_err("Polling AXI RX bus sleep protect turn off fail. status=0x%08x\n", + CONSYS_REG_READ(CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN2_STA1_OFFSET)); +#endif + + /* Turn off AXI Rx bus sleep protect (CONN2AP AXI Rx Bus protect) + * (disable sleep protection when CONNSYS had been turned on) + * Note : Should turn off AXI Rx sleep protection first. + */ + CONSYS_REG_WRITE( + CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_CLR_OFFSET, + 0x00004000); +#if 0 /* POS update 20190819: Skip check */ +#ifndef CONFIG_FPGA_EARLY_PORTING + /* Check AXI Rx bus sleep protect turn off + * (polling "10 times" and each polling interval is "0.5ms") + * Address: 0x1000_1228[14] (INFRA_TOPAXI_PROTECTEN_STA1[14]) + * Data: 1'b0 + * Action: polling + */ + CONSYS_REG_BIT_POLLING( + CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1_OFFSET, + 14, 0, 10, 50, check); + if (check != 0) + pr_err("Polling AXI bus sleep protect turn off fail. Status=0x%08x\n", + CONSYS_REG_READ(CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1_OFFSET)); +#endif +#endif + /* Turn off AXI TX bus sleep protect (AP2CONN AXI Bus protect) + * (apply this for INFRA AXI bus accessing when CONNSYS had been turned on) + */ + CONSYS_REG_WRITE( + CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_CLR_OFFSET, + 0x00002000); + +#ifndef CONFIG_FPGA_EARLY_PORTING + /* Check AXI TX bus sleep protect turn off + * (polling "100 times" and each polling interval is "0.5ms") + * Address: 0x1000_1228[13] (INFRA_TOPAXI_PROTECTEN_STA1[13]) + * Data: 1'b0 + * Action: polling + */ + CONSYS_REG_BIT_POLLING( + CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1_OFFSET, + 13, 0, 100, 500, check); + if (check != 0) + pr_err("polling AXI TX bus sleep protect turn off fail. Status=0x%08x\n", + CONSYS_REG_READ(CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1_OFFSET)); +#endif +#endif /* MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE */ + /* Wait 6ms (apply this for CONNSYS XO clock ready) + * [NOTE] + * This setting could be changed at different design architecture + * and the characteristic of AFE WBG) + */ + mdelay(6); + } else { + + /* Enable AXI bus sleep protect */ +#if MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE + pr_info("Turn off conn_infra power by SPM API\n"); + check = consys_platform_spm_conn_ctrl(enable); + if (check) { + pr_err("Turn off conn_infra power fail, ret=%d\n", check); + return -1; + } +#else + /* Turn on AXI TX bus sleep protect (AP2CONN AXI Bus protect) + * (apply this for INFRA AXI bus protection to prevent bus hang when + * CONNSYS had been turned off) + * Address: 0x1000_12a0[31:0] + * Data: 0x0000_2000 + * Action: write + */ + CONSYS_REG_WRITE( + CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_SET_OFFSET, + 0x00002000); + + /* check AXI TX bus sleep protect turn on (polling "100 times") + * Address: 0x1000_1228[13] + * Data: 1'b1 + * Action: polling + */ + CONSYS_REG_BIT_POLLING( + CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1_OFFSET, + 13, 1, 100, 500, check); + if (check) + pr_err("Polling AXI TX bus sleep protect turn on fail.\n"); + + /* Turn on AXI Rx bus sleep protect (CONN2AP AXI RX Bus protect) + * (apply this for INFRA AXI bus protection to prevent bus hang when + * CONNSYS had been turned off) + * Note: + * Should turn on AXI Rx sleep protection after + * AXI Tx sleep protection has been turn on. + * Address: 0x1000_12A0[31:0] + * Data: 0x0000_4000 + * Action: write + */ + CONSYS_REG_WRITE( + CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_SET_OFFSET, + 0x00004000); + + /* check AXI Rx bus sleep protect turn on + * (polling "100 times", polling interval is 1ms) + * Address: 0x1000_1228[14] + * Data: 1'b1 + * Action: polling + */ + CONSYS_REG_BIT_POLLING( + CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1_OFFSET, + 14, 1, 100, 1000, check); + if (check) + pr_err("Polling AXI Rx bus sleep protect turn on fail.\n"); + + /* Turn on AXI RX bus sleep protect (AP2CONN AXI Bus protect) + * (apply this for INFRA AXI bus protection to prevent bus hang when + * CONNSYS had been turned off) + * Address: 0x1000_1714[31:0] (INFRA_TOPAXI_PROTECTEN2_SET) + * Data: 0x0000_0002 + * Action: write + */ + CONSYS_REG_WRITE( + CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN2_SET_OFFSET, + 0x00000002); + /* check AXI RX bus sleep protect turn on (polling "10 times") + * Address: 0x1000_1724[2] (INFRA_TOPAXI_PROTECTEN2_STA1[2]) + * Value: 1'b1 + * Action: polling + */ + CONSYS_REG_BIT_POLLING( + CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN2_STA1_OFFSET, + 2, 1, 10, 1000, check); + if (check) + pr_err("Polling AXI RX bus sleep protect turn on fail.\n"); + + /* Assert "conn_infra_on" isolation, set "connsys_iso_en"=1 + * Address: CONN_PWR_CON[1] (0x1000_6304[1]) + * Value: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x2); + + /* Assert CONNSYS S/W reset (SPM CR), set "ap_sw_rst_b"=0 + * Address: CONN_PWR_CON[0] (0x1000_6304[0]) + * Value: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x1); + + /* Assert CONNSYS S/W reset(TOP RGU CR), set "ap_sw_rst_b"=0 + * Address: WDT_SWSYSRST[9] (0x1000_7018[9]) + * WDT_SWSYSRST[31:24] (0x1000_7018[31:24]) + * Value: [9]=1'b1 + * [31:24]=8'h88 (key) + * Action: write + * Note: this CR value for reset control is active high (0: not reset, 1: reset) + */ + CONSYS_REG_WRITE_MASK( + CON_REG_TOP_RGU_ADDR + TOP_RGU_WDT_SWSYSRST, + 0x88000200, + 0xff000200); + + /* Turn off AP-to-CONNSYS bus clock, set "conn_clk_dis"=1 + * (apply this for bus clock gating) + * Address: CONN_PWR_CON[4] (0x1000_6304[4]) + * Value: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x10); + + /* wait 1us (?) */ + udelay(1); + + /* De-assert "conn_infra_on" primary part power on, + * set "connsys_on_domain_pwr_on"=0 + * Address: CONN_PWR_CON[2] (0x1000_6304[2]) + * Value: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x4); + + /* De-assert "conn_infra_on" secondary part power on, + * set "connsys_on_domain_pwr_on_s"=0 + * Address: CONN_PWR_CON[3] (0x1000_6304[3]) + * Value: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x8); +#endif /* MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE */ + + /* Turn off ap2conn host_ck CG (ECO) + * Address: INFRA_AP2MD_GALS_CTL[0] (0x1020E504[0]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CON_REG_INFRACFG_BASE_ADDR + INFRA_AP2MD_GALS_CTL, 0x1); + } + return 0; +} + +int consys_conninfra_wakeup(void) +{ + int check, r1, r2; + unsigned int retry = 10; + unsigned int consys_hw_ver = 0; + int polling_fail_retry = 2; + unsigned long polling_fail_delay = 20000; /* 20ms */ + + /* Wake up conn_infra + * Address: CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP (0x180601a0) + * Data: 1'b1 + * Action: write + */ + CONSYS_REG_WRITE( + CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP, + 0x1); + + /* Check ap2conn slpprot_rdy + * (polling "10 times" for specific project code and each polling interval is "1ms") + * Address: CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL_CONN_INFRA_ON2OFF_SLP_PROT_ACK (0x1806_0184[5]) + * Data: 1'b0 + * Action: polling + */ + while (polling_fail_retry > 0) { + check = 0; + CONSYS_REG_BIT_POLLING( + CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL, 5, 0, 10, 1000, check); + + if (check != 0) { + pr_err("[%s] Check ap2conn slpprot_rdy fail. value=0x%x WAKEUP_TOP=[0x%x]\n", + __func__, + CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL), + CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP)); + } + + if (consys_reg_mng_reg_readable() == 0) { + check = consys_reg_mng_is_bus_hang(); + r1 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_3); + r2 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP); + pr_info("[%s] check=[%d] r1=[0x%x] r2=[0x%x]", __func__, check, r1, r2); + consys_reg_mng_dump_cpupcr(CONN_DUMP_CPUPCR_TYPE_ALL, 10, 200); + if (check > 0) { + return -1; + } + check = -1; + } + + if (check == 0) + break; + + /* delay 20 ms */ + usleep_range(polling_fail_delay - 200, polling_fail_delay + 200); + polling_fail_retry--; + } + + if (check != 0) { + pr_err("[%s] wakeup fail retry %d", __func__, polling_fail_retry); + return -1; + } + + /* Check CONNSYS version ID + * (polling "10 times" for specific project code and each polling interval is "1ms") + * Address: CONN_HW_VER (0x1800_1000[31:0]) + * Data: 32'h2001_0101 + * Action: polling + */ + check = 0; + while (retry-- > 0) { + consys_hw_ver = CONSYS_REG_READ( + CON_REG_INFRA_CFG_ADDR + + CONN_HW_VER_OFFSET); + if (consys_hw_ver == CONN_HW_VER) { + check = 0; + pr_info("[%s] Polling chip id success (0x%x)\n", __func__, consys_hw_ver); + break; + } + check = -1; + } + if (check != 0) + pr_err("[%s] Polling chip id fail (0x%x)\n", __func__, consys_hw_ver); + + return check; +} + +int consys_conninfra_sleep(void) +{ + /* Release conn_infra force on + * Address: CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP (0x180601a0) + * Data: 1'b0 + * Action: write + */ + CONSYS_REG_WRITE( + CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP, + 0x0); + + return 0; +} + +void consys_set_if_pinmux(unsigned int enable) +{ +#ifndef CONFIG_FPGA_EARLY_PORTING + if (enable) { + /* Set pinmux for the interface between D-die and A-die + * (CONN_HRST_B / CONN_TOP_CLK / CONN_TOP_DATA / CONN_WB_PTA / + * CONN_BT_CLK / CONN_BT_DATA / CONN_WF_CTRL0 / CONN_WF_CTRL1 / + * CONN_WF_CTRL2 / CONN_WF_CTRL3 / CONN_WF_CTRL4) + */ + /* GPIO 172: 0x1000_5450[18:16] */ + /* GPIO 173: 0x1000_5450[22:20] */ + /* GPIO 174: 0x1000_5450[26:24] */ + /* GPIO 175: 0x1000_5450[30:28] */ + CONSYS_REG_WRITE_MASK(GPIO_BASE_ADDR + GPIO_MODE21, 0x11110000, 0xffff0000); + + /* GPIO 176: 0x1000_5460[2:0] */ + /* GPIO 177: 0x1000_5460[6:4] */ + /* GPIO 178: 0x1000_5460[10:8] */ + /* GPIO 179: 0x1000_5460[14:12] */ + /* GPIO 180: 0x1000_5460[18:16] */ + /* GPIO 181: 0x1000_5460[22:20] */ + /* GPIO 182: 0x1000_5460[26:24] */ + CONSYS_REG_WRITE_MASK(GPIO_BASE_ADDR + GPIO_MODE22, 0x01111111, 0x0fffffff); + + /* Set pinmux driving to 2mA + * Address: + * 0x11EA_0000[5:3]/0x11EA_0000[8:6]/0x11EA_0000[11:9] + * 0x11EA_0000[14:12]/0x11EA_0000[17:15] + * Data: 3'b000 + * Action: write + * Note: IOCFG_RT + */ + CONSYS_REG_WRITE_MASK(IOCFG_RT_ADDR + IOCFG_RT_DRV_CFG0, 0x0, 0x3fff8); + + /* Set CONN_TOP_CLK/CONN_TOP_DATA/CONN_BT_CLK/CONN_BT_DATA driving to 4mA + * (CONN_TOP_DATA driving config is the same position with + * CONN_WF_CTRL0/CONN_WF_CTRL1/CONN_WF_CTRL2/CONN_WF_CTRL3/CONN_WF_CTRL4) + * Address: + * CONN_TOP_CLK 0x11EA_0000[17:15] = 3b'001 + * CONN_TOP_DATA 0x11EA_0000[5:3] = 3b'001 + * CONN_BT_CLK 0x11EA_0000[8:6] = 3b'001 + * CONN_BT_DATA 0x11EA_0000[11:9] = 3b'001 + * Action: write + */ + CONSYS_REG_WRITE_MASK(IOCFG_RT_ADDR + IOCFG_RT_DRV_CFG0, 0x8248, 0x38ff8); + + /* Set pinmux PUPD setting + * Clear CONN_TOP_DATA/CONN_BT_DATA PD setting + * Address: 0x11EA_0058[14][11] + * Data: 2'b11 + * Action: write + * Note: IOCFG_RT + */ + CONSYS_REG_WRITE_MASK(IOCFG_RT_ADDR + IOCFG_RT_PD_CFG0_CLR, 0x4800, 0x4800); + + /* Set pinmux PUPD + * Setting CONN_TOP_DATA/CONN_BT_DATA as PU + * Address: 0x11EA_0074[14][11] + * Data: 2'b11 + * Action: write + * Note: IOCFG_RT + */ + CONSYS_REG_WRITE_MASK(IOCFG_RT_ADDR + IOCFG_RT_PU_CFG0_SET, 0x4800, 0x4800); + + /* If TCXO mode, set GPIO155 pinmux for TCXO mode (AUX4) + * (CONN_TCXOENA_REQ) + * Address: 0x1000_5430[14:12] + * Data: 3'b100 + * Action: write + */ + if (consys_co_clock_type() == CONNSYS_CLOCK_SCHEMATIC_26M_EXTCXO) { + /* TODO: need customization for TCXO GPIO */ + CONSYS_REG_WRITE_MASK(GPIO_BASE_ADDR + GPIO_MODE19, 0x4000, 0x7000); + } + } else { + /* Set pinmux for the interface between D-die and A-die (Aux0) + * Address: + * 0x1000_5450[26:24]/0x1000_5450[18:16]/0x1000_5450[22:20] + * 0x1000_5450[30:28]/0x1000_5460[2:0]/0x1000_5460[6:4] + * 0x1000_5460[10:8]/0x1000_5460[14:12]/0x1000_5460[18:16] + * 0x1000_5460[22:20]/0x1000_5460[26:24] + * Data: 3'b000 + * Action: write + */ + CONSYS_REG_WRITE_MASK(GPIO_BASE_ADDR + GPIO_MODE21, 0x0, 0xffff0000); + CONSYS_REG_WRITE_MASK(GPIO_BASE_ADDR + GPIO_MODE22, 0x0, 0x0fffffff); + + /* Set pinmux PUPD setting + * Clear CONN_TOP_DATA/CONN_BT_DATA PU setting + * Address: 0x11EA_0078[14][11] + * Data: 2'b11 + * Action: write + */ + CONSYS_REG_WRITE_MASK(IOCFG_RT_ADDR + IOCFG_RT_PU_CFG0_CLR, 0x4800, 0x4800); + + /* Set pinmux PUPD setting + * CONN_TOP_DATA/CONN_BT_DATA as PD + * Address: 0x11EA_0054[14][11] + * Data: 2'b11 + *Action: write + */ + CONSYS_REG_WRITE_MASK(IOCFG_RT_ADDR + IOCFG_RT_PD_CFG0_SET, 0x4800, 0x4800); + + /* If TCXO mode, set GPIO155 pinmux to GPIO mode + * Address: 0x1000_5430[14:12] + * Data: 3'b000 + * Action: write + */ + if (consys_co_clock_type() == CONNSYS_CLOCK_SCHEMATIC_26M_EXTCXO) { + CONSYS_REG_WRITE_MASK(GPIO_BASE_ADDR + GPIO_MODE19, 0x0, 0x7000); + } + } +#else + pr_info("[%s] not for FPGA\n", __func__); +#endif +} + +int consys_polling_chipid(void) +{ + unsigned int retry = 11; + unsigned int consys_hw_ver = 0; + unsigned int consys_configuration_id = 0; + int ret = -1; + int check; + + /* Check ap2conn slpprot_rdy + * (polling "10 times" for specific project code and each polling interval is "1ms") + * Address: + * CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL_CONN_INFRA_ON2OFF_SLP_PROT_ACK + * 0x1806_0184[5] + * Value: 1'b0 + * Action: polling + * Note: deadfeed CDC issue + */ + check = 0; + CONSYS_REG_BIT_POLLING( + CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL, 5, 0, 10, 1000, check); + if (check) { + pr_err("[%s] Check ap2conn slpprot_rdy fail. value=0x%x WAKEUP_TOP=[0x%x]\n", + __func__, + CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL), + CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP)); + } + + while (--retry > 0) { + consys_hw_ver = CONSYS_REG_READ( + CON_REG_INFRA_CFG_ADDR + + CONN_HW_VER_OFFSET); + if (consys_hw_ver == CONN_HW_VER) { + consys_configuration_id = CONSYS_REG_READ( + CON_REG_INFRA_CFG_ADDR + CONN_CFG_ID_OFFSET); + pr_info("Consys HW version id(0x%x) cfg_id=(0x%x)\n", + consys_hw_ver, consys_configuration_id); + ret = 0; + break; + } + msleep(20); + } + + if (retry == 0) { + check = consys_reg_mng_is_bus_hang(); + pr_err("Read CONSYS version id fail. Expect 0x%x but get 0x%x\n, bus hang check=[%d]", + CONN_HW_VER, consys_hw_ver, check); + return -1; + } + + /* Disable conn_infra deadfeed function(workaround) + * Address: CONN_HOST_CSR_TOP_CSR_DEADFEED_EN_CR_AP2CONN_DEADFEED_EN (0x1806_0124[0]) + * Data: 1'b0 + * Action: write + * Note: workaround for deadfeed CDC issue + */ + CONSYS_CLR_BIT(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CSR_DEADFEED_EN_CR, 0x1); + +#ifdef CONFIG_FPGA_EARLY_PORTING + /* For FPGA workaround */ + CONSYS_SET_BIT(CON_REG_INFRA_CFG_ADDR + 0x0c04, + ((0x1 << 1) | (0x1 << 9) | (0x1 << 17) | (0x1 << 25))); + pr_info("Workaround for FPGA: Check %x\n", CON_REG_INFRA_CFG_ADDR + 0x0c04); +#endif + + return ret; +} + +int connsys_d_die_cfg(void) +{ + /* Read D-die Efuse + * Address: AP2CONN_EFUSE_DATA (0x1800_1818) + * Data: + * Action: read + */ + CONSYS_REG_WRITE( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_D_DIE_EFUSE, + CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + AP2CONN_EFUSE_DATA)); + + /* Request from MCU, pass build type to FW + * 1: eng build + * 2: userdebug build + * 3: user build + */ +#if defined(CONNINFRA_PLAT_BUILD_MODE) + CONSYS_REG_WRITE( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_BUILD_MODE, + CONNINFRA_PLAT_BUILD_MODE); + pr_info("Write CONN_INFRA_SYSRAM_SW_CR_BUILD_MODE to 0x%08x\n", + CONSYS_REG_READ(CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_BUILD_MODE)); +#endif + + /* conn_infra sysram hw control setting -> disable hw power down + * Address: CONN_INFRA_RGU_SYSRAM_HWCTL_PDN_SYSRAM_HWCTL_PDN (0x1800_0038) + * Data: 32'h0 + * Action: write + */ + CONSYS_REG_WRITE(CON_REG_INFRA_RGU_ADDR + CONN_INFRA_RGU_SYSRAM_HWCTL_PDN, 0x0); + + /* conn_infra sysram hw control setting -> enable hw sleep + * Address: CONN_INFRA_RGU_SYSRAM_HWCTL_SLP_SYSRAM_HWCTL_SLP (0x1800_003C) + * Data: 32'h0000_00FF + * Action: write + */ + CONSYS_REG_WRITE(CON_REG_INFRA_RGU_ADDR + CONN_INFRA_RGU_SYSRAM_HWCTL_SLP, 0x000000ff); + + /* co-ext memory hw control setting -> disable hw power down + * Address: CONN_INFRA_RGU_CO_EXT_MEM_HWCTL_PDN_CO_EXT_MEM_HWCTL_PDN (0x1800_0050) + * Data: 32'h0 + * Action: write + */ + CONSYS_REG_WRITE(CON_REG_INFRA_RGU_ADDR + CONN_INFRA_RGU_CO_EXT_MEM_HWCTL_PDN, 0x0); + + /* co-ext memory hw control setting -> enable hw sleep + * Address: CONN_INFRA_RGU_CO_EXT_MEM_HWCTL_SLP_CO_EXT_MEM_HWCTL_SLP (0x1800_0054) + * Data: 32'h0000_0001 + * Action: write + */ + CONSYS_REG_WRITE(CON_REG_INFRA_RGU_ADDR + CONN_INFRA_RGU_CO_EXT_MEM_HWCTL_SLP, 0x1); + + return 0; +} + +int connsys_spi_master_cfg(unsigned int next_status) +{ + unsigned int bt_only = 0; + + if ((next_status & (~(0x1 << CONNDRV_TYPE_BT))) == 0) + bt_only = 1; + + /* CONN_WT_SLP_CTL_REG_WB_WF_CK_ADDR_ADDR(0x070) = 0x0AF40A04 + * CONN_WT_SLP_CTL_REG_WB_WF_WAKE_ADDR_ADDR(0x74) = 0x00A00090 + * CONN_WT_SLP_CTL_REG_WB_WF_ZPS_ADDR_ADDR(0x78) = 0x009c008c + * CONN_WT_SLP_CTL_REG_WB_BT_CK_ADDR_ADDR(0x7c[11:0]) = 0xa08 + * CONN_WT_SLP_CTL_REG_WB_BT_WAKE_ADDR_ADDR(0x80[11:0]) = 0x094 + * CONN_WT_SLP_CTL_REG_WB_TOP_CK_ADDR_ADDR(0x84[11:0]) = 0x02c + * CONN_WT_SLP_CTL_REG_WB_GPS_CK_ADDR_ADDR(0x88[11:0]) = 0x0AFC0A0C + * CONN_WT_SLP_CTL_REG_WB_WF_B0_CMD_ADDR_ADDR(0x8c[11:0]) = 0x0F0 + * CONN_WT_SLP_CTL_REG_WB_WF_B1_CMD_ADDR_ADDR(0x90[11:0]) = 0x0F4 + * CONN_WT_SLP_CTL_REG_WB_GPS_RFBUF_ADDR(0x18005094[11:0]) = 0x0FC + * CONN_WT_SLP_CTL_REG_WB_GPS_L5_EN_ADDR(0x18005098[11:0]) = 0x0F8 + */ + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_WF_CK_ADDR, 0x0AF40A04); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_WF_WAKE_ADDR, 0x00A00090); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_WF_ZPS_ADDR, 0x009C008C); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BT_CK_ADDR, + 0xa08, 0xfff); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BT_WAKE_ADDR, + 0x094, 0xfff); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_TOP_CK_ADDR, + 0x02c, 0xfff); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_GPS_CK_ADDR, + 0x0AFC0A0C); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_WF_B0_CMD_ADDR, + 0x0f0, 0xfff); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_WF_B1_CMD_ADDR, + 0x0f4, 0xfff); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_GPS_RFBUF_ADDR, + 0x0FC, 0xfff); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_GPS_L5_EN_ADDR, + 0x0F8, 0xfff); + + /* CONN_WT_SLP_CTL_REG_WB_SLP_CTL_CMD_LENGTH(0x004[4:0]) = 0x8 + * CONN_WT_SLP_CTL_REG_WB_BG_ADDR1_WB_BG_ADDR1(0x10[15:0]) = 0xA03C + * CONN_WT_SLP_CTL_REG_WB_BG_ADDR2_WB_BG_ADDR2(0x14[15:0]) = 0xA03C + * CONN_WT_SLP_CTL_REG_WB_BG_ADDR3_WB_BG_ADDR3(0x18[15:0]) = 0xAA18 + * CONN_WT_SLP_CTL_REG_WB_BG_ADDR4_WB_BG_ADDR4(0x1c[15:0]) = 0xAA18 + * CONN_WT_SLP_CTL_REG_WB_BG_ADDR5_WB_BG_ADDR5(0x20[15:0]) = 0xA0C8 + * CONN_WT_SLP_CTL_REG_WB_BG_ADDR6_WB_BG_ADDR6(0x24[15:0]) = 0xAA00 + * CONN_WT_SLP_CTL_REG_WB_BG_ADDR7_WB_BG_ADDR7(0x28[15:0]) = 0xA0B4 + * CONN_WT_SLP_CTL_REG_WB_BG_ADDR8_WB_BG_ADDR8(0x2c[15:0]) = 0xA34C + * CONN_WT_SLP_CTL_REG_WB_BG_ON1_WB_BG_ON1(0x30) = 0x00000000 + * CONN_WT_SLP_CTL_REG_WB_BG_ON2_WB_BG_ON2(0x34) = 0x00000000 + * if (BT_only) { + * CONN_WT_SLP_CTL_REG_WB_BG_ON3_WB_BG_ON3(0x38) = 0x74E03F75 + * CONN_WT_SLP_CTL_REG_WB_BG_ON4_WB_BG_ON4(0x3c) = 0x76E83F75 + * } else { + * CONN_WT_SLP_CTL_REG_WB_BG_ON3_WB_BG_ON3(0x38) = 0x74E0FFF5 + * CONN_WT_SLP_CTL_REG_WB_BG_ON4_WB_BG_ON4(0x3c) = 0x76E8FFF5 + * } + * CONN_WT_SLP_CTL_REG_WB_BG_ON5_WB_BG_ON5(0x40) = 0x00000000 + * CONN_WT_SLP_CTL_REG_WB_BG_ON6_WB_BG_ON6(0x44) = 0xFFFFFFFF + * CONN_WT_SLP_CTL_REG_WB_BG_ON7_WB_BG_ON7(0x48) = 0x00000019 + * CONN_WT_SLP_CTL_REG_WB_BG_ON8_WB_BG_ON8(0x4c) = 0x00010400 + * CONN_WT_SLP_CTL_REG_WB_BG_OFF1_WB_BG_OFF1(0x50) = 0x57400000 + * CONN_WT_SLP_CTL_REG_WB_BG_OFF2_WB_BG_OFF2(0x54) = 0x57400000 + * if (BT only) { + * CONN_WT_SLP_CTL_REG_WB_BG_OFF3_WB_BG_OFF3(0x58) = 0x44E03F75 + * CONN_WT_SLP_CTL_REG_WB_BG_OFF4_WB_BG_OFF4(0x5c) = 0x44E03F75 + * } else { + * CONN_WT_SLP_CTL_REG_WB_BG_OFF3_WB_BG_OFF3(0x58) = 0x44E0FFF5 + * CONN_WT_SLP_CTL_REG_WB_BG_OFF4_WB_BG_OFF4(0x5c) = 0x44E0FFF5 + * } + * CONN_WT_SLP_CTL_REG_WB_BG_OFF5_WB_BG_OFF5(0x60) = 0x00000001 + * CONN_WT_SLP_CTL_REG_WB_BG_OFF6_WB_BG_OFF6(0x64) = 0x00000000 + * CONN_WT_SLP_CTL_REG_WB_RG_OFF7_WB_BG_OFF7(0x68) = 0x00040019 + * CONN_WT_SLP_CTL_REG_WB_RG_OFF8_WB_BG_OFF8(0x6c) = 0x00410440 + */ + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_SLP_CTL, + 0x8, 0x1f); + + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR1, + 0xa03c, 0xffff); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR2, + 0xa03c, 0xffff); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR3, + 0xaa18, 0xffff); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR4, + 0xaa18, 0xffff); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR5, + 0xa0c8, 0xffff); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR6, + 0xaa00, 0xffff); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR7, + 0xa0b4, 0xffff); + CONSYS_REG_WRITE_MASK( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR8, + 0xa34c, 0xffff); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON1, 0x00000000); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON2, 0x00000000); + if (bt_only) { + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON3, 0x74E03F75); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON4, 0x76E83F75); + } else { + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON3, 0x74E0fff5); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON4, 0x76E8FFF5); + } + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON5, 0x00000000); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON6, 0xFFFFFFFF); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON7, 0x00000019); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON8, 0x00010400); + + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF1, 0x57400000); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF2, 0x57400000); + if (bt_only) { + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF3, 0x44E03F75); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF4, 0x44E03F75); + } else { + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF3, 0x44e0fff5); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF4, 0x44e0fff5); + } + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF5, 0x00000001); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF6, 0x00000000); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF7, 0x00040019); + CONSYS_REG_WRITE( + CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF8, 0x00410440); + + return 0; +} + +//#ifndef CONFIG_FPGA_EARLY_PORTING +/***************************************************************************** +* FUNCTION +* connsys_a_die_efuse_read +* DESCRIPTION +* Read a-die efuse +* PARAMETERS +* efuse_addr: read address +* RETURNS +* int +* 0: fail, efuse is invalid +* 1: success, efuse is valid +*****************************************************************************/ +static int connsys_a_die_efuse_read(unsigned int efuse_addr) +{ + int ret = 0; + int retry = 0; + unsigned int efuse0 = 0, efuse1 = 0, efuse2 = 0, efuse3 = 0; + int ret0, ret1, ret2, ret3; + + /* Get semaphore before read */ + if (consys_sema_acquire_timeout(CONN_SEMA_RFSPI_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) { + pr_err("[EFUSE READ] Require semaphore fail\n"); + return 0; + } + + /* Efuse control clear, clear Status /trigger + * Address: ATOP EFUSE_CTRL_write_efsrom_kick_and_read_kick_busy_flag (0x108[30]) + * Data: 1'b0 + * Action: TOPSPI_WR + */ + consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, &ret); + ret &= ~(0x1 << 30); + consys_spi_write_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, ret); + + /* Efuse Read 1st 16byte + * Address: + * ATOP EFUSE_CTRL_efsrom_mode (0x108[7:6]) = 2'b00 + * ATOP EFUSE_CTRL_efsrom_ain (0x108[25:16]) = efuse_addr (0) + * ATOP EFUSE_CTRL_write_efsrom_kick_and_read_kick_busy_flag (0x108[30]) = 1'b1 + * Action: TOPSPI_WR + */ + consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, &ret); + ret &= ~(0x43ff00c0); + ret |= (0x1 << 30); + ret |= ((efuse_addr << 16) & 0x3ff0000); + consys_spi_write_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, ret); + + /* Polling EFUSE busy = low + * (each polling interval is "30us" and polling timeout is 2ms) + * Address: + * ATOP EFUSE_CTRL_write_efsrom_kick_and_read_kick_busy_flag (0x108[30]) = 1'b0 + * Action: TOPSPI_Polling + */ + consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, &ret); + while ((ret & (0x1 << 30)) != 0 && retry < 70) { + retry++; + udelay(30); + consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, &ret); + } + if ((ret & (0x1 << 30)) != 0) { + pr_info("[%s] EFUSE busy, retry failed(%d)\n", __func__, retry); + } + + /* Check efuse_valid & return + * Address: ATOP EFUSE_CTRL_csri_efsrom_dout_vld_sync_1_ (0x108[29]) + * Action: TOPSPI_RD + */ + /* if (efuse_valid == 1'b1) + * Read Efuse Data to global var + */ + consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, &ret); + if (((ret & (0x1 << 29)) >> 29) == 1) { + ret0 = consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_RDATA0, &efuse0); + + CONSYS_REG_WRITE( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_0, + efuse0); + + ret1 = consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_RDATA1, &efuse1); + CONSYS_REG_WRITE( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_1, + efuse1); + /* Sub-task: thermal cal */ + connsys_a_die_thermal_cal(1, efuse1); + + ret2 = consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_RDATA2, &efuse2); + CONSYS_REG_WRITE( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_2, + efuse2); + + ret3 = consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_RDATA3, &efuse3); + CONSYS_REG_WRITE( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_3, + efuse3); + + pr_info("efuse = [0x%08x, 0x%08x, 0x%08x, 0x%08x]", efuse0, efuse1, efuse2, efuse3); + if (ret0 || ret1 || ret2 || ret3) + pr_err("efuse read error: [%d, %d, %d, %d]", ret0, ret1, ret2, ret3); + ret = 1; + } else { + connsys_a_die_thermal_cal(0, 0); + pr_err("EFUSE is invalid\n"); + ret = 0; + } + + consys_sema_release(CONN_SEMA_RFSPI_INDEX); + return ret; +} + +static int connsys_a_die_thermal_cal(int efuse_valid, unsigned int efuse) +{ + struct consys_plat_thermal_data input; + memset(&input, 0, sizeof(struct consys_plat_thermal_data)); + + if (efuse_valid) { + if (efuse & (0x1 << 7)) { + consys_spi_write_offset_range_nolock( + SYS_SPI_TOP, ATOP_RG_TOP_THADC_BG, efuse, 12, 3, 4); + consys_spi_write_offset_range_nolock( + SYS_SPI_TOP, ATOP_RG_TOP_THADC, efuse, 23, 0, 3); + } + if(efuse & (0x1 << 15)) { + consys_spi_write_offset_range_nolock( + SYS_SPI_TOP, ATOP_RG_TOP_THADC, efuse, 26, 13, 2); + input.slop_molecule = (efuse & 0x1f00) >> 8; + pr_info("slop_molecule=[%d]", input.slop_molecule); + } + if (efuse & (0x1 << 23)) { + /* [22:16] */ + input.thermal_b = (efuse & 0x7f0000) >> 16; + pr_info("thermal_b =[%d]", input.thermal_b); + } + if (efuse & (0x1 << 31)) { + input.offset = (efuse & 0x7f000000) >> 24; + pr_info("offset=[%d]", input.offset); + } + } + update_thermal_data(&input); + return 0; +} +//#endif + +int connsys_a_die_cfg(void) +{ + int efuse_valid; + bool adie_26m = true; + unsigned int adie_id = 0; + + if (consys_co_clock_type() == CONNSYS_CLOCK_SCHEMATIC_52M_COTMS) { + pr_info("A-die clock 52M\n"); + adie_26m = false; + } + /* First time to setup conninfra sysram, clean it. */ + memset_io( + (volatile void*)CONN_INFRA_SYSRAM_BASE_ADDR, + 0x0, + CONN_INFRA_SYSRAM_SIZE); + + + /* if(A-die XTAL = 26MHz ) { + * CONN_WF_CTRL2 swtich to GPIO mode, GPIO output value + * before patch download swtich back to CONN mode. + * } + */ + /* Address: + * 0x1000_5054 = 32'h0010_0000 + * 0x1000_5154 = 32'h0010_0000 + * 0x1000_5460[18:16] = 3'b000 + * Actin: write + * Note: MT6635 strap pinmux, set CONN_WF_CTRL2 as GPIO + */ + if (adie_26m) { + CONSYS_REG_WRITE(GPIO_BASE_ADDR + GPIO_DIR5_SET, 0x00100000); + CONSYS_REG_WRITE(GPIO_BASE_ADDR + GPIO_DOUT5_SET, 0x00100000); + CONSYS_REG_WRITE_MASK(GPIO_BASE_ADDR + GPIO_MODE22, 0x0, 0x70000); + } + /* sub-task: a-die cfg */ + /* De-assert A-die reset + * Address: CONN_INFRA_CFG_ADIE_CTL_ADIE_RSTB (0x18001900[0]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_ADIE_CTL, 0x1); + + /* Read MT6635 ID + * Address: ATOP CHIP_ID + * 0x02C[31:16]: hw_code + * 0x02C[15:0]: hw_ver + * Data: + * MT6635 E1 : read 0x02C = 0x66358A00 + * MT6635 E2 : read 0x02C = 0x66358A10 + * MT6635 E3 : read 0x02C = 0x66358A11 + * Action: TOPSPI_RD + */ + consys_spi_read(SYS_SPI_TOP, ATOP_CHIP_ID, &adie_id); + conn_hw_env.adie_hw_version = adie_id; + conn_hw_env.is_rc_mode = consys_is_rc_mode_enable(); + pr_info("A-die CHIP_ID=0x%08x rc=%d\n", adie_id, conn_hw_env.is_rc_mode); + + CONSYS_REG_WRITE( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_CHIP_ID, + adie_id); + + /* Patch to FW from 7761(WF0_WRI_SX_CAL_MAP/WF1_WRI_SX_CAL_MAP) + * Address: ATOP WRI_CTR2 (0x064) + * Data: 32'h00007700 + * Action: TOPSPI_WR + */ + consys_spi_write(SYS_SPI_TOP, ATOP_WRI_CTR2, 0x00007700); + + /* Set WF low power cmd as DBDC mode & legacy interface + * Address: ATOP SMCTK11 (0x0BC) + * Data: 32'h00000021 + * Action: TOPSPI_WR + */ + consys_spi_write(SYS_SPI_TOP, ATOP_SMCTK11, 0x00000021); + + /* Update spi fm read extra bit setting + * Address: + * CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_EN (0x1800400C[15]) + * CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_CNT (0x1800400C[7:0]) + * Data: + * 0x1800400C[15] = 1'b0 + * 0x1800400C[7:0] = 8'h0 + * Action: write + */ + CONSYS_REG_WRITE_MASK( + CONN_REG_RFSPI_ADDR + CONN_RF_SPI_MST_REG_FM_CTRL, 0x0, 0x80ff); + + /* Update Thermal addr for 6635 + * Address: CONN_TOP_THERM_CTL_THERM_AADDR (0x18002018) + * Data: 32'h50305A00 + * Action: write + */ + CONSYS_REG_WRITE(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_AADDR, 0x50305A00); + + /* Sub-task: read a-die efuse */ + efuse_valid = connsys_a_die_efuse_read(0); + + /* Set WF_PAD to HighZ + * Address: ATOP RG_ENCAL_WBTAC_IF_SW (0x070) + * Data: 32'h80000000 + * Action: TOPSPI_WR + */ + consys_spi_write(SYS_SPI_TOP, ATOP_RG_ENCAL_WBTAC_IF_SW, 0x80000000); + + /* Disable CAL LDO + * Address: ATOP RG_WF0_TOP_01 (0x380) + * Data: 32'h000E8002 + * Action: TOPSPI_WR + * Note: AC mode + */ + consys_spi_write(SYS_SPI_TOP, ATOP_RG_WF0_TOP_01, 0x000e8002); + + /* Disable CAL LDO + * Address: ATOP RG_WF1_TOP_01 (0x390) + * Data: 32'h000E8002 + * Action: TOPSPI_WR + * Note: AC mode + */ + consys_spi_write(SYS_SPI_TOP, ATOP_RG_WF1_TOP_01, 0x000e8002); + + /* Increase XOBUF supply-V + * Address: ATOP RG_TOP_XTAL_01 (0xA18) + * Data: 32'hF6E8FFF5 + * Action: TOPSPI_WR + */ + consys_spi_write(SYS_SPI_TOP, ATOP_RG_TOP_XTAL_01, 0xF6E8FFF5); + + /* Increase XOBUF supply-R for MT6635 E1 + * Address: ATOP RG_TOP_XTAL_02 (0xA1C) + * Data: + * if(MT6635 E1) //rf_hw_ver = 0x8a00 + * 32'hD5555FFF + * else + * 32'h0x55555FFF + * Action: TOPSPI_WR + */ + if (adie_id == 0x66358a00) { + consys_spi_write(SYS_SPI_TOP, ATOP_RG_TOP_XTAL_02, 0xD5555FFF); + } else { + consys_spi_write(SYS_SPI_TOP, ATOP_RG_TOP_XTAL_02, 0x55555FFF); + } + + /* Initial IR value for WF0 THADC + * Address: ATOP RG_WF0_BG (0x384) + * Data: 0x00002008 + * Action: TOPSPI_WR + */ + consys_spi_write(SYS_SPI_TOP, ATOP_RG_WF0_BG, 0x2008); + + /* Initial IR value for WF1 THADC + * Address: ATOP RG_WF1_BG (0x394) + * Data: 0x00002008 + * Action: TOPSPI_WR + */ + consys_spi_write(SYS_SPI_TOP, ATOP_RG_WF1_BG, 0x2008); + + /* if(A-die XTAL = 26MHz ) { + * CONN_WF_CTRL2 swtich to CONN mode + * } + */ + /* Adress: 0x1000_5460[18:16] = 3'b001 + * Action: write + * Note: MT6635 strap pinmux, set CONN_WF_CTRL2 as conn mode + */ + if (adie_26m) { + CONSYS_REG_WRITE_MASK(GPIO_BASE_ADDR + GPIO_MODE22, 0x10000, 0x70000); + } + return 0; +} + +int connsys_afe_wbg_cal(void) +{ + /* Default value update; 1: AFE WBG CR (if needed) + * note that this CR must be backuped and restored by command batch engine + * Address: + * CONN_AFE_CTL_RG_WBG_AFE_01(0x18003010) = 32'h00000000 + * CONN_AFE_CTL_RG_WBG_RCK_01(0x18003018) = 32'h144B0160 + * CONN_AFE_CTL_RG_WBG_GL1_01(0x18003040) = 32'h10990C13 + * CONN_AFE_CTL_RG_WBG_GL5_01(0x18003100) = 32'h10990C13 + * CONN_AFE_CTL_RG_WBG_BT_TX_03 (0x18003058) = 32'hCD258051 + * CONN_AFE_CTL_RG_WBG_WF0_TX_03 (0x18003078) = 32'hC5258251 + * CONN_AFE_CTL_RG_WBG_WF1_TX_03 (0x18003094) = 32'hC5258251 + */ + CONSYS_REG_WRITE( + CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_WBG_AFE_01, + 0x0); + CONSYS_REG_WRITE( + CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_WBG_RCK_01, + 0x144B0160); + CONSYS_REG_WRITE( + CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_WBG_GL1_01, + 0x10990C13); + CONSYS_REG_WRITE( + CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_WBG_GL5_01, + 0x10990C13); + CONSYS_REG_WRITE( + CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_WBG_BT_TX_03, + 0xCD258051); + CONSYS_REG_WRITE( + CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_WBG_WF0_TX_03, + 0xC5258251); + CONSYS_REG_WRITE( + CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_WBG_WF1_TX_03, + 0xC5258251); + + /* AFE WBG CAL SEQ1 (RC calibration) */ + /* AFE WBG RC calibration, set "AFE RG_WBG_EN_RCK" = 1 + * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_RCK (0x18003000[0]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, 0x1); + udelay(60); + /* AFE WBG RC calibration */ + /* AFE WBG RC calibration, set "AFE RG_WBG_EN_RCK" = 0 + * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_RCK (0x18003000[0]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, 0x1); + + /* AFE WBG CAL SEQ2 (TX calibration) */ + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_BPLL_UP" = 1 + * Address: CONN_AFE_CTL_RG_DIG_EN_03_RG_WBG_EN_BPLL_UP (0x18003008[21]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_03, (0x1 << 21)); + udelay(30); + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_WPLL_UP" = 1 + * Address: CONN_AFE_CTL_RG_DIG_EN_03_RG_WBG_EN_WPLL_UP (0x18003008[20]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_03, (0x1 << 20)); + udelay(60); + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_BT" = 1 + * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_BT (0x18003000[21]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 21)); + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_WF0" = 1 + * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_WF0 (0x18003000[20]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 20)); + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_WF1" = 1 + * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_WF1 (0x18003000[19]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 19)); + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_WF2" = 1 + * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_WF2 (0x18003000[18]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 18)); + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_WF3" = 1 + * Addres: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_WF3 (0x18003000[17]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 17)); + udelay(800); + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_BT" = 0 + * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_BT (0x18003000[21]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 21)); + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_WF0" = 0 + * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_WF0 (0x18003000[20]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 20)); + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_WF1" = 0 + * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_WF1 (0x18003000[19]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 19)); + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_WF2" = 0 + * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_WF2 (0x18003000[18]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 18)); + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_WF3" = 0 + * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_WF3 (0x18003000[17]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 17)); + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_BPLL_UP" = 0 + * Address: CONN_AFE_CTL_RG_DIG_EN_03_RG_WBG_EN_BPLL_UP (0x18003008[21]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_03, (0x1 << 21)); + /* AFE WBG TX calibration, set "AFE RG_WBG_EN_WPLL_UP" = 0 + * Address:i CONN_AFE_CTL_RG_DIG_EN_03_RG_WBG_EN_WPLL_UP (0x18003008[20]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_03, (0x1 << 20)); + + /* Initial BT path if WF is in cal(need set this CR after WBG cal) + * Address: ATOP RG_ENCAL_WBTAC_IF_SW (0x070) + * Data: 32'h00000005 + * Action: write + */ + consys_spi_write(SYS_SPI_TOP, ATOP_RG_ENCAL_WBTAC_IF_SW, 0x5); + return 0; +} + +int connsys_subsys_pll_initial(void) +{ + /* Check with DE, only 26M on mobile phone */ + /* Set BPLL stable time = 30us (value = 30 * 1000 *1.01 / 38.46ns) + * CONN_AFE_CTL_RG_PLL_STB_TIME_RG_WBG_BPLL_STB_TIME (0x180030F4[30:16]) = 0x314 + * Set WPLL stable time = 50us (value = 50 * 1000 *1.01 / 38.46ns) + * CONN_AFE_CTL_RG_PLL_STB_TIME_RG_WBG_WPLL_STB_TIME (0x180030F4[14:0]) = 0x521 + */ + CONSYS_REG_WRITE_MASK( + CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_PLL_STB_TIME, + 0x03140521, 0x7fff7fff); + + /* BT pll_en will turn on BPLL only (may change in different XTAL option) + * CONN_AFE_CTL_RG_DIG_EN_02_RG_WBG_EN_BT_PLL (0x18003004[7:6])=0x1 + * WF pll_en will turn on BPLL + WPLL only (may change in different XTAL option) + * CONN_AFE_CTL_RG_DIG_EN_02_RG_WBG_EN_WF_PLL (0x18003004[1:0])=0x3 + * MCU pll_en will turn on BPLL + WPLL (may change in different XTAL option) + * CONN_AFE_CTL_RG_DIG_EN_02_RG_WBG_EN_MCU_PLL (0x18003004[3:2])=0x3 + */ + CONSYS_REG_WRITE_MASK( + CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_02, + 0x4f, 0xcf); + + return 0; +} + +// Special setting for BT low power +static int connsys_bt_low_power_setting(bool bt_only) +{ + int hw_version; + const struct a_die_reg_config* config = NULL; + unsigned int ret, i; + + hw_version = CONSYS_REG_READ( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_CHIP_ID); + + if (bt_only) { + /* E1 */ + if (hw_version == 0x66358A00) { + config = adie_e1_bt_only; + } else if (hw_version == 0x66358A10 || hw_version == 0x66358A11) { + config = adie_e2_bt_only; + } else + pr_err("[%s] wrong adie version (0x%08x)\n", __func__, hw_version); + } else { + if (hw_version == 0x66358A00) { + config = adie_e1_default; + } else if (hw_version == 0x66358A10 || hw_version == 0x66358A11) { + config = adie_e2_default; + } else + pr_err("[%s] wrong adie version (0x%08x)\n", __func__, hw_version); + } + + if (config == NULL) + return -1; + + consys_adie_top_ck_en_on(CONNSYS_ADIE_CTL_HOST_CONNINFRA); + + /* Get semaphore before read */ + if (consys_sema_acquire_timeout(CONN_SEMA_RFSPI_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) { + pr_err("[EFUSE READ] Require semaphore fail\n"); + consys_adie_top_ck_en_off(CONNSYS_ADIE_CTL_HOST_CONNINFRA); + return -1; + } + + for (i = 0; i < ADIE_CONFIG_NUM; i++) { + consys_spi_read_nolock(SYS_SPI_TOP, config[i].reg, &ret); + ret &= (~config[i].mask); + ret |= config[i].config; + consys_spi_write_nolock(SYS_SPI_TOP, config[i].reg, ret); + } + + consys_sema_release(CONN_SEMA_RFSPI_INDEX); + + consys_adie_top_ck_en_off(CONNSYS_ADIE_CTL_HOST_CONNINFRA); + + return 0; +} + +void connsys_debug_select_config(void) +{ +#if 1 + /* select conn_infra_cfg debug_sel to low pwoer related + * Address: 0x18001B00[2:0] + * Data: 3'b000 + * Action: write + */ + CONSYS_REG_WRITE_MASK(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_DBG_MUX_SEL, + 0x0, 0x7); +#else + /* select conn_infra_cfg debug_sel to BPLL/WPLL status + * Address: 0x18001B00[2:0] + * Data: 3’b001 + * Action: write + */ + CONSYS_REG_WRITE_MASK(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_DBG_MUX_SEL, + 0x1, 0x7); + { + void __iomem *vir_addr = NULL; + vir_addr = ioremap_nocache(0x18006000, 0x1000); + if (vir_addr) { + /* wpll_rdy/bpll_rdy status dump + * 1.???Set 0x1800_604C = 0xFFFF_FFFF + * 2.???Set 0c1800_6058[1] = 0x1 + * 3.???Set 0x1800_603C = 0x0000_0100 + * 4.???Set 0x1800_601C = 0x0302_0100 + * 5.???Set 0x1800_6020 = 0x0706_0504 + * 6.???Set 0x1800_6024 = 0x0b0a_0908 + * 7.???Set 0x1800_6028 = 0x0f0e_0d0c + * 8.???Set 0x1800_602C = 0x1312_1110 + * 9.???Set 0x1800_6030 = 0x1716_1514 + * 10.??Set 0x1800_6034 = 0x1b1a_1918 + * 11.??Set 0x1800_6038 = 0x1f1e_1d1c + */ + CONSYS_REG_WRITE(vir_addr + 0x004c, 0xffffffff); + CONSYS_SET_BIT(vir_addr + 0x0058, 0x1); + CONSYS_REG_WRITE(vir_addr + 0x3c, 0x00000100); + CONSYS_REG_WRITE(vir_addr + 0x1c, 0x03020100); + CONSYS_REG_WRITE(vir_addr + 0x20, 0x07060504); + CONSYS_REG_WRITE(vir_addr + 0x24, 0x0b0a0908); + CONSYS_REG_WRITE(vir_addr + 0x28, 0x0f0e0d0c); + CONSYS_REG_WRITE(vir_addr + 0x2c, 0x13121110); + CONSYS_REG_WRITE(vir_addr + 0x30, 0x17161514); + CONSYS_REG_WRITE(vir_addr + 0x34, 0x1b1a1918); + CONSYS_REG_WRITE(vir_addr + 0x38, 0x1f1e1d1c); + iounmap(vir_addr); + } else { + pr_err("remap 0x1800_6000 fail\n"); + } + } +#endif + +} + + +int connsys_low_power_setting(unsigned int curr_status, unsigned int next_status) +{ + bool bt_only = false; + + if ((next_status & (~(0x1 << CONNDRV_TYPE_BT))) == 0) + bt_only = true; + + pr_info("[%s] current_status=%d bt_only = %d\n", __func__, curr_status, bt_only); + + /* First subsys on */ + if (curr_status == 0) { + /* Enable AP2CONN GALS Slave sleep protect en with conn_infra on2off/off2on & wfdma2conn + * sleep protect en + * Address: CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL_WFDMA2CONN_SLP_PROT_AP2CONN_EN_ENABLE + * CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL_CONN_INFRA_ON2OFF_SLP_PROT_AP2CONN_EN_ENABLE + * CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL_CONN_INFRA_OFF2ON_SLP_PROT_AP2CONN_EN_ENABLE (0x1806_0184[11:9]) + * Data: 3'b111 + * Action: write + */ + CONSYS_REG_WRITE_MASK( + CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL, + 0xe00, 0xe00); + + /* Unmask on2off/off2on slpprot_rdy enable checker @conn_infra off power off=> check slpprot_rdy = 1'b1 and go to sleep + * Address: CONN_INFRA_CFG_PWRCTRL0_CONN_INFRA_CFG_SLP_RDY_MASK (0x18001860[15:12]) + * Data: 4'h1 + * Action: write + */ + CONSYS_REG_WRITE_MASK( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_PWRCTRL0, + 0x1000, 0xf000); + + /* conn_infra low power setting */ + if (!consys_is_rc_mode_enable()) { + /* Default mode (non-RC) */ + /* Disable conn_top rc osc_ctrl_top + * Address: CONN_INFRA_CFG_RC_CTL_0_CONN_INFRA_OSC_RC_EN (0x18001834[7]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0, (0x1 << 7)); + /* Legacy OSC control stable time + * Address: + * CONN_INFRA_CFG_OSC_CTL_0_XO_VCORE_RDY_STABLE_TIME (0x18001800[7:0]) = 8'd6 + * CONN_INFRA_CFG_OSC_CTL_0_XO_INI_STABLE_TIME (0x18001800[15:8]) = 8'd7 + * CONN_INFRA_CFG_OSC_CTL_0_XO_BG_STABLE_TIME (0x18001800[23:16]) = 8'd8 + * Action: write + */ + CONSYS_REG_WRITE_MASK( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_OSC_CTL_0, 0x080706, 0xffffff); + /* Legacy OSC control unmask conn_srcclkena_ack + * Address: CONN_INFRA_CFG_OSC_CTL_1_ACK_FOR_XO_STATE_MASK (0x18001804[16]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_OSC_CTL_1, (0x1 << 16)); + } else { + /* RC mode */ + /* GPS RC OSC control stable time + * Address: + * CONN_INFRA_CFG_RC_CTL_1_GPS_XO_VCORE_RDY_STABLE_TIME_0 (0x1800183C[7:0]) = 8'd6 + * CONN_INFRA_CFG_RC_CTL_1_GPS_XO_INI_STABLE_TIME_0 (0x1800183C[15:8]) = 8'd7 + * CONN_INFRA_CFG_RC_CTL_1_GPS_XO_BG_STABLE_TIME_0 (0x1800183C[23:16]) = 8'd8 + * CONN_INFRA_CFG_RC_CTL_1_GPS_XO_VCORE_OFF_STABLE_TIME_0 (0x1800183C[31:24]) = 8'd2 + * Action: write + */ + CONSYS_REG_WRITE( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_1_GPS, + 0x02080706); + + /* GPS RC OSC control unmask conn_srcclkena_ack + * Address: CONN_INFRA_CFG_RC_CTL_0_GPS_ACK_FOR_XO_STATE_MASK_0 (0x18001838[15]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0_GPS, (0x1 << 15)); + + /* BT RC OSC control stable time + * Address: + * CONN_INFRA_CFG_RC_CTL_1_BT_XO_VCORE_RDY_STABLE_TIME_1 (0x18001844[7:0]) = 8'd6 + * CONN_INFRA_CFG_RC_CTL_1_BT_XO_INI_STABLE_TIME_1 (0x18001844[15:8]) = 8'd7 + * CONN_INFRA_CFG_RC_CTL_1_BT_XO_BG_STABLE_TIME_1 (0x18001844[23:16]) = 8'd8 + * CONN_INFRA_CFG_RC_CTL_1_BT_XO_VCORE_OFF_STABLE_TIME_1 (0x18001844[31:24]) = 8'd2 + * Action: write + */ + CONSYS_REG_WRITE( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_1_BT, + 0x02080706); + + /* BT RC OSC control unmask conn_srcclkena_ack + * Address: CONN_INFRA_CFG_RC_CTL_0_BT_ACK_FOR_XO_STATE_MASK_1 (0x18001840[15]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0_BT, (0x1 << 15)); + + /* WF RC OSC control stable time + * Address: + * CONN_INFRA_CFG_RC_CTL_1_WF_XO_VCORE_RDY_STABLE_TIME_2 (0x1800184C[7:0]) = 8'd6 + * CONN_INFRA_CFG_RC_CTL_1_WF_XO_INI_STABLE_TIME_2 (0x1800184C[15:8]) = 8'd7 + * CONN_INFRA_CFG_RC_CTL_1_WF_XO_BG_STABLE_TIME_2 (0x1800184C[23:16]) = 8'd8 + * CONN_INFRA_CFG_RC_CTL_1_WF_XO_VCORE_OFF_STABLE_TIME_2 (0x1800184C[31:24])= 8'd2 + * Action: write + */ + CONSYS_REG_WRITE( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_1_WF, + 0x02080706); + + /* WF RC OSC control unmask conn_srcclkena_ack + * Address: CONN_INFRA_CFG_RC_CTL_0_WF_ACK_FOR_XO_STATE_MASK_2 (0x18001848[15]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0_WF, (0x1 << 15)); + + /* TOP RC OSC control stable time + * Address: + * CONN_INFRA_CFG_RC_CTL_1_TOP_XO_VCORE_RDY_STABLE_TIME_3 (0x18001854[7:0]) = 8'd6 + * CONN_INFRA_CFG_RC_CTL_1_TOP_XO_INI_STABLE_TIME_3 (0x18001854[15:8]) = 8'd7 + * CONN_INFRA_CFG_RC_CTL_1_TOP_XO_BG_STABLE_TIME_3 (0x18001854[23:16]) = 8'd8 + * CONN_INFRA_CFG_RC_CTL_1_TOP_XO_VCORE_OFF_STABLE_TIME_3 (0x18001854[31:24]) = 8'd2 + * Action: write + */ + CONSYS_REG_WRITE( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_1_TOP, + 0x02080706); + + /* TOP RC OSC control unmask conn_srcclkena_ack + * Address: CONN_INFRA_CFG_RC_CTL_0_TOP_ACK_FOR_XO_STATE_MASK_3 (0x18001850[15]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0_TOP, + (0x1 << 15)); + + /* Enable conn_top rc osc_ctrl_gps + * Address: CONN_INFRA_CFG_RC_CTL_0_GPSSYS_OSC_RC_EN (0x18001834[4]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0, + (0x1 << 4)); + + /* Enable conn_top rc osc_ctrl_bt + * Address: CONN_INFRA_CFG_RC_CTL_0_BTSYS_OSC_RC_EN (0x18001834[5]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0, + (0x1 << 5)); + + /* Enable conn_top rc osc_ctrl_wf + * Address: CONN_INFRA_CFG_RC_CTL_0_WFSYS_OSC_RC_EN (0x18001834[6]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0, + (0x1 << 6)); + + /* set conn_srcclkena control by conn_infra_emi_ctl + * Address: CONN_INFRA_CFG_EMI_CTL_0_CONN_EMI_RC_EN (0x18001C00[0]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_EMI_CTL_0, 0x1); + + /* Disable legacy osc control + * Address: CONN_INFRA_CFG_RC_CTL_0_OSC_LEGACY_EN (0x18001834[0]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0, + 0x1); + } + /* conn2ap sleep protect release bypass ddr_en_ack check + * Address: CONN_INFRA_CFG_EMI_CTL_0_EMI_SLPPROT_BP_DDR_EN (0x18001C00[18]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_EMI_CTL_0, 0x40000); + + /* Enable ddr_en timeout, timeout value = 1023 T (Bus clock) + * Address: CONN_INFRA_CFG_EMI_CTL_0_DDR_CNT_LIMIT (0x18001C00[14:4]) + * Data: 11'd1023 + * Action: write + */ + CONSYS_REG_WRITE_MASK( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_EMI_CTL_0, + 0x3ff0, 0x7ff0); + + /* A-die clock buffer setting for BT only and others mode */ + connsys_bt_low_power_setting(bt_only); + + /* Enable conn_infra_clkgen BPLL source (hw workaround) + * Address: CONN_INFRA_CFG_CKGEN_BUS_RFSPI_DIV_EN (0x1800_1A00[28]) + * Data: 1'b1 + * Action: write + */ + CONSYS_SET_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_CKGEN_BUS, (0x1 << 28)); + + /* Bus light security + * Address: + * CONN_INFRA_CFG_LIGHT_SECURITY_CTRL_R_CONN_INFRA_BT_PAIR1_EN + * CONN_INFRA_CFG_LIGHT_SECURITY_CTRL_R_CONN_INFRA_BT_PAIR0_EN + * CONN_INFRA_CFG_LIGHT_SECURITY_CTRL_R_CONN_INFRA_WF_PAIR1_EN + * CONN_INFRA_CFG_LIGHT_SECURITY_CTRL_R_CONN_INFRA_WF_PAIR0_EN + * 0x1800_10F0[4][3][1][0] = 6'h1B + * Action: write + */ + CONSYS_REG_WRITE_MASK( + CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_LIGHT_SECURITY_CTRL, + ((0x1 << 4) | (0x1 << 3) | (0x1 << 1) | 0x1), + ((0x1 << 4) | (0x1 << 3) | (0x1 << 1) | 0x1)); + + /* if(BT on or GPS on) + * Conn_infrapower on bgfsys on (woraround) + * Address: + * 0x18000008[31:16] = 16'h4254 (key) + * CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_CTL[7] (0x18000008[7]) = 1'b1 + * Action: write + */ + /* Check with DE, write 1 -> 1 is ok */ + if ((next_status & ((0x1 << CONNDRV_TYPE_BT) | (0x1 << CONNDRV_TYPE_GPS))) != 0) { + CONSYS_REG_WRITE_MASK( + CON_REG_INFRA_RGU_ADDR + CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_CTL, + ((0x42540000) | (0x1 << 7)), 0xffff0080); + } + + consys_config_setup(); + connsys_debug_select_config(); + + /* + * set 0x1800_0090 = 4'h6 + */ + CONSYS_REG_WRITE(CON_REG_INFRA_RGU_ADDR + CONN_INFRA_RGU_DEBUG_SEL, 0x6); + + /******************************************************/ + /* power ctrl : 0x1800_1860[9] = 1'b1 */ + /******************************************************/ + CONSYS_SET_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_PWRCTRL0, 0x200); + + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + /* !!!!!!!!!!!!!!!!!!!!!! CANNOT add code after HERE!!!!!!!!!!!!!!!!!!!!!!!!!! */ + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + + /* Disable conn_infra bus clock sw control ==> conn_infra bus clock hw control + * Address: CONN_INFRA_CFG_CKGEN_BUS_HCLK_CKSEL_SWCTL (0x1800_1A00[23]) + * Data: 1'b0 + * Action: write + */ + CONSYS_CLR_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_CKGEN_BUS, (0x1 << 23)); + + /* Conn_infra HW_CONTROL => conn_infra enter dsleep mode + * Address: CONN_INFRA_CFG_PWRCTRL0_HW_CONTROL (0x1800_1860[0]) + * Data: 1'b1 + * Action: write + * Note: enable conn_infra off domain as HW control + */ + CONSYS_SET_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_PWRCTRL0, 0x1); + } else { + /* for subsys on/off, only update BT low power setting */ + connsys_bt_low_power_setting(bt_only); + + /* Workaround */ + if ((next_status & ((0x1 << CONNDRV_TYPE_BT) | (0x1 << CONNDRV_TYPE_GPS))) != 0) { + CONSYS_REG_WRITE_MASK( + CON_REG_INFRA_RGU_ADDR + CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_CTL, + ((0x42540000) | (0x1 << 7)), 0xffff0080); + } else { + CONSYS_REG_WRITE_MASK( + CON_REG_INFRA_RGU_ADDR + CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_CTL, + 0x42540000, 0xffff0080); + } + + consys_config_setup(); + connsys_debug_select_config(); + } + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + /* !!!!!!!!!!!!!!!!!!!!!!!!CANNOT add code HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + + return 0; +} + +static int consys_sema_acquire(unsigned int index) +{ + if (CONSYS_REG_READ_BIT( + CONN_REG_SEMAPHORE_ADDR + CONN_SEMAPHORE_M2_OWN_STA + index*4, 0x1) == 0x1) { + return CONN_SEMA_GET_SUCCESS; + } else { + return CONN_SEMA_GET_FAIL; + } +} + +int consys_sema_acquire_timeout(unsigned int index, unsigned int usec) +{ + int i, check, r1, r2; + + if (index >= CONN_SEMA_NUM_MAX) { + pr_err("[%s] wrong parameter: %d", __func__, index); + return CONN_SEMA_GET_FAIL; + } + + /* debug for bus hang */ + if (consys_reg_mng_reg_readable() == 0) { + check = consys_reg_mng_is_bus_hang(); + if (check > 0) { + r1 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_3); + r2 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP); + pr_info("[%s] check=[%d] r1=[0x%x] r2=[0x%x]", __func__, check, r1, r2); + consys_reg_mng_dump_bus_status(); + consys_reg_mng_dump_cpupcr(CONN_DUMP_CPUPCR_TYPE_ALL, 10, 200); + return CONN_SEMA_GET_FAIL; + } + } + + for (i = 0; i < usec; i++) { + if (consys_sema_acquire(index) == CONN_SEMA_GET_SUCCESS) { + return CONN_SEMA_GET_SUCCESS; + } + udelay(1); + } + + pr_err("Get semaphore 0x%x timeout, dump status:\n", index); + pr_err("M0:[0x%x] M1:[0x%x] M2:[0x%x] M3:[0x%x]\n", + CONSYS_REG_READ(CONN_REG_SEMAPHORE_ADDR + CONN_SEMA_OWN_BY_M0_STA_REP), + CONSYS_REG_READ(CONN_REG_SEMAPHORE_ADDR + CONN_SEMA_OWN_BY_M1_STA_REP), + CONSYS_REG_READ(CONN_REG_SEMAPHORE_ADDR + CONN_SEMA_OWN_BY_M2_STA_REP), + CONSYS_REG_READ(CONN_REG_SEMAPHORE_ADDR + CONN_SEMA_OWN_BY_M3_STA_REP)); + consys_reg_mng_dump_cpupcr(CONN_DUMP_CPUPCR_TYPE_ALL, 10, 200); + + return CONN_SEMA_GET_FAIL; +} + +void consys_sema_release(unsigned int index) +{ + if (index >= CONN_SEMA_NUM_MAX) + return; + CONSYS_REG_WRITE( + (CONN_REG_SEMAPHORE_ADDR + CONN_SEMAPHORE_M2_OWN_REL + index*4), 0x1); +} + +struct spi_op { + unsigned int busy_cr; + unsigned int polling_bit; + unsigned int addr_cr; + unsigned int read_addr_format; + unsigned int write_addr_format; + unsigned int write_data_cr; + unsigned int read_data_cr; + unsigned int read_data_mask; +}; + +static const struct spi_op spi_op_array[SYS_SPI_MAX] = { + /* SYS_SPI_WF1 */ + { + CONN_RF_SPI_MST_REG_SPI_STA, 1, + CONN_RF_SPI_MST_REG_SPI_WF_ADDR, 0x00001000, 0x00000000, + CONN_RF_SPI_MST_REG_SPI_WF_WDAT, + CONN_RF_SPI_MST_REG_SPI_WF_RDAT, 0xffffffff + }, + /* SYS_SPI_WF */ + { + CONN_RF_SPI_MST_REG_SPI_STA, 1, + CONN_RF_SPI_MST_REG_SPI_WF_ADDR, 0x00003000, 0x00002000, + CONN_RF_SPI_MST_REG_SPI_WF_WDAT, + CONN_RF_SPI_MST_REG_SPI_WF_RDAT, 0xffffffff + }, + /* SYS_SPI_BT */ + { + CONN_RF_SPI_MST_REG_SPI_STA, 2, + CONN_RF_SPI_MST_REG_SPI_BT_ADDR, 0x00005000, 0x00004000, + CONN_RF_SPI_MST_REG_SPI_BT_WDAT, + CONN_RF_SPI_MST_REG_SPI_BT_RDAT, 0x000000ff + }, + /* SYS_SPI_FM */ + { + CONN_RF_SPI_MST_REG_SPI_STA, 3, + CONN_RF_SPI_MST_REG_SPI_FM_ADDR, 0x00007000, 0x00006000, + CONN_RF_SPI_MST_REG_SPI_FM_WDAT, + CONN_RF_SPI_MST_REG_SPI_FM_RDAT, 0x0000ffff + }, + /* SYS_SPI_GPS */ + { + CONN_RF_SPI_MST_REG_SPI_STA, 4, + CONN_RF_SPI_MST_REG_SPI_GPS_GPS_ADDR, 0x00009000, 0x00008000, + CONN_RF_SPI_MST_REG_SPI_GPS_GPS_WDAT, + CONN_RF_SPI_MST_REG_SPI_GPS_GPS_RDAT, 0x0000ffff + }, + /* SYS_SPI_TOP */ + { + CONN_RF_SPI_MST_REG_SPI_STA, 5, + CONN_RF_SPI_MST_REG_SPI_TOP_ADDR, 0x0000b000, 0x0000a000, + CONN_RF_SPI_MST_REG_SPI_TOP_WDAT, + CONN_RF_SPI_MST_REG_SPI_TOP_RDAT, 0xffffffff + }, + /* SYS_SPI_WF2 */ + { + CONN_RF_SPI_MST_REG_SPI_STA, 1, + CONN_RF_SPI_MST_REG_SPI_WF_ADDR, 0x0000d000, 0x0000c000, + CONN_RF_SPI_MST_REG_SPI_WF_WDAT, + CONN_RF_SPI_MST_REG_SPI_WF_RDAT, 0xffffffff + }, + /* SYS_SPI_WF3 */ + { + CONN_RF_SPI_MST_REG_SPI_STA, 1, + CONN_RF_SPI_MST_REG_SPI_WF_ADDR, 0x0000f000, 0x0000e000, + CONN_RF_SPI_MST_REG_SPI_WF_WDAT, + CONN_RF_SPI_MST_REG_SPI_WF_RDAT, 0xffffffff + }, +}; + +static int consys_spi_read_nolock(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data) +{ + /* Read action: + * 1. Polling busy_cr[polling_bit] should be 0 + * 2. Write addr_cr with data being {read_addr_format | addr[11:0]} + * 3. Trigger SPI by writing write_data_cr as 0 + * 4. Polling busy_cr[polling_bit] as 0 + * 5. Read data_cr[data_mask] + */ + int check = 0; + const struct spi_op* op = &spi_op_array[subsystem]; + + if (!data) { + pr_err("[%s] invalid data ptr\n", __func__); + return CONNINFRA_SPI_OP_FAIL; + } + + CONSYS_REG_BIT_POLLING( + CONN_REG_RFSPI_ADDR + op->busy_cr, + op->polling_bit, 0, 100, 50, check); + if (check != 0) { + pr_err("[%s][%d][STEP1] polling 0x%08x bit %d fail. Value=0x%08x\n", + __func__, subsystem, CONN_REG_RFSPI_ADDR + op->busy_cr, + op->polling_bit, + CONSYS_REG_READ(CONN_REG_RFSPI_ADDR + op->busy_cr)); + return CONNINFRA_SPI_OP_FAIL; + } + + CONSYS_REG_WRITE( + CONN_REG_RFSPI_ADDR + op->addr_cr, + (op->read_addr_format | addr)); + + CONSYS_REG_WRITE(CONN_REG_RFSPI_ADDR + op->write_data_cr, 0); + + check = 0; + CONSYS_REG_BIT_POLLING( + CONN_REG_RFSPI_ADDR + op->busy_cr, + op->polling_bit, 0, 100, 50, check); + if (check != 0) { + pr_err("[%s][%d][STEP4] polling 0x%08x bit %d fail. Value=0x%08x\n", + __func__, subsystem, CONN_REG_RFSPI_ADDR + op->busy_cr, + op->polling_bit, + CONSYS_REG_READ(CONN_REG_RFSPI_ADDR + op->busy_cr)); + return CONNINFRA_SPI_OP_FAIL; + } + + check = CONSYS_REG_READ_BIT(CONN_REG_RFSPI_ADDR + op->read_data_cr, op->read_data_mask); + *data = check; + + return 0; +} + +int consys_spi_read(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data) +{ + int ret; + + /* Get semaphore before read */ + if (consys_sema_acquire_timeout(CONN_SEMA_RFSPI_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) { + pr_err("[SPI READ] Require semaphore fail\n"); + return CONNINFRA_SPI_OP_FAIL; + } + + ret = consys_spi_read_nolock(subsystem, addr, data); + + consys_sema_release(CONN_SEMA_RFSPI_INDEX); + + return ret; +} + +static int consys_spi_write_nolock(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data) +{ + int check = 0; + const struct spi_op* op = &spi_op_array[subsystem]; + + /* Write action: + * 1. Wait busy_cr[polling_bit] as 0 + * 2. Write addr_cr with data being {write_addr_format | addr[11:0] + * 3. Write write_data_cr ad data + * 4. Wait busy_cr[polling_bit] as 0 + */ + CONSYS_REG_BIT_POLLING( + CONN_REG_RFSPI_ADDR + op->busy_cr, + op->polling_bit, 0, 100, 50, check); + if (check != 0) { + pr_err("[%s][%d][STEP1] polling 0x%08x bit %d fail. Value=0x%08x\n", + __func__, subsystem, CONN_REG_RFSPI_ADDR + op->busy_cr, + op->polling_bit, + CONSYS_REG_READ(CONN_REG_RFSPI_ADDR + op->busy_cr)); + return CONNINFRA_SPI_OP_FAIL; + } + + CONSYS_REG_WRITE(CONN_REG_RFSPI_ADDR + op->addr_cr, (op->write_addr_format | addr)); + + CONSYS_REG_WRITE(CONN_REG_RFSPI_ADDR + op->write_data_cr, data); + + check = 0; + CONSYS_REG_BIT_POLLING( + CONN_REG_RFSPI_ADDR + op->busy_cr, + op->polling_bit, 0, 100, 50, check); + if (check != 0) { + pr_err("[%s][%d][STEP4] polling 0x%08x bit %d fail. Value=0x%08x\n", + __func__, subsystem, CONN_REG_RFSPI_ADDR + op->busy_cr, + op->polling_bit, + CONSYS_REG_READ(CONN_REG_RFSPI_ADDR + op->busy_cr)); + return CONNINFRA_SPI_OP_FAIL; + } + + return 0; +} + + +int consys_spi_write(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data) +{ + int ret; + + /* Get semaphore before read */ + if (consys_sema_acquire_timeout(CONN_SEMA_RFSPI_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) { + pr_err("[SPI WRITE] Require semaphore fail\n"); + return CONNINFRA_SPI_OP_FAIL; + } + + ret = consys_spi_write_nolock(subsystem, addr, data); + + consys_sema_release(CONN_SEMA_RFSPI_INDEX); + return ret; +} + +int consys_spi_write_offset_range( + enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int value, + unsigned int reg_offset, unsigned int value_offset, unsigned int size) +{ + if (consys_sema_acquire_timeout(CONN_SEMA_RFSPI_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) { + pr_err("[SPI READ] Require semaphore fail\n"); + return CONNINFRA_SPI_OP_FAIL; + } + consys_spi_write_offset_range_nolock( + subsystem, addr, value, reg_offset, value_offset, size); + + consys_sema_release(CONN_SEMA_RFSPI_INDEX); + return 0; +} + +static void consys_spi_write_offset_range_nolock( + enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int value, + unsigned int reg_offset, unsigned int value_offset, unsigned int size) +{ + unsigned int data = 0, data2; + unsigned int reg_mask; + int ret; + + pr_info("[%s][%s] addr=0x%04x value=0x%08x reg_offset=%d value_offset=%d size=%d", + __func__, g_spi_system_name[subsystem], addr, value, reg_offset, value_offset, size); + value = (value >> value_offset); + value = GET_BIT_RANGE(value, size, 0); + value = (value << reg_offset); + ret = consys_spi_read_nolock(subsystem, addr, &data); + if (ret) { + pr_err("[%s][%s] Get 0x%08x error, ret=%d", + __func__, g_spi_system_name[subsystem], addr, ret); + return; + } + reg_mask = GENMASK(reg_offset + size - 1, reg_offset); + data2 = data & (~reg_mask); + data2 = (data2 | value); + consys_spi_write_nolock(subsystem, addr, data2); + pr_info("[%s][%s] Write CR:0x%08x from 0x%08x to 0x%08x", + __func__, g_spi_system_name[subsystem], + addr, data, data2); +} + + +static int consys_adie_top_ck_en_ctrl(bool on) +{ + int check = 0; + + if (on) + CONSYS_SET_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_ADIE_CTL, (0x1 << 1)); + else + CONSYS_CLR_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_ADIE_CTL, (0x1 << 1)); + + CONSYS_REG_BIT_POLLING( + CON_REG_WT_SPL_CTL_ADDR + CONN_WTSLP_CTL_REG_WB_STA, + 26, 0, 100, 5, check); + if (check == -1) { + pr_err("[%s] op=%d fail\n", __func__, on); + } + return check; + +} + +int consys_adie_top_ck_en_on(enum consys_adie_ctl_type type) +{ + unsigned int status; + int ret; + + if (type >= CONNSYS_ADIE_CTL_MAX) { + pr_err("[%s] invalid parameter(%d)\n", __func__, type); + return -1; + } + + if (consys_sema_acquire_timeout(CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) { + pr_err("[%s][%s] acquire semaphore (%d) timeout\n", + __func__, gAdieCtrlType[type], CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX); + return -1; + } + + status = CONSYS_REG_READ( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_TOP_CK_EN_CTRL); + if ((status & CONN_INFRA_SYSRAM__A_DIE_DIG_TOP_CK_EN_MASK) == 0) { + ret = consys_adie_top_ck_en_ctrl(true); + } + CONSYS_SET_BIT( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_TOP_CK_EN_CTRL, (0x1 << type)); + + consys_sema_release(CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX); + return 0; +} + +int consys_adie_top_ck_en_off(enum consys_adie_ctl_type type) +{ + unsigned int status; + int ret = 0; + + if (type >= CONNSYS_ADIE_CTL_MAX) { + pr_err("[%s] invalid parameter(%d)\n", __func__, type); + return -1; + } + + if (consys_sema_acquire_timeout(CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) { + pr_err("[%s][%s] acquire semaphoreaore (%d) timeout\n", + __func__, gAdieCtrlType[type], CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX); + return -1; + } + + status = CONSYS_REG_READ( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_TOP_CK_EN_CTRL); + if ((status & (0x1 << type)) == 0) { + pr_warn("[%s][%s] already off\n", __func__, gAdieCtrlType[type]); + } else { + CONSYS_CLR_BIT( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_TOP_CK_EN_CTRL, (0x1 << type)); + + status = CONSYS_REG_READ( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_TOP_CK_EN_CTRL); + if (0 == (status & CONN_INFRA_SYSRAM__A_DIE_DIG_TOP_CK_EN_MASK)) { + ret = consys_adie_top_ck_en_ctrl(false); + } + } + + consys_sema_release(CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX); + return ret; +} + +int consys_spi_clock_switch(enum connsys_spi_speed_type type) +{ +#define MAX_SPI_CLOCK_SWITCH_COUNT 100 + unsigned int status; + unsigned int counter = 0; + int ret = 0; + + /* Get semaphore before read */ + if (consys_sema_acquire_timeout(CONN_SEMA_RFSPI_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) { + pr_err("[SPI CLOCK SWITCH] Require semaphore fail\n"); + return -1; + } + + if (type == CONNSYS_SPI_SPEED_26M) { + CONSYS_REG_WRITE_MASK( + CONN_REG_RFSPI_ADDR + CONN_RF_SPI_MST_REG_SPI_CRTL, + 0x0, 0x5); + status = CONSYS_REG_READ(CONN_REG_RFSPI_ADDR + CONN_RF_SPI_MST_REG_SPI_CRTL) & 0x18; + while (status != 0x8 && counter < MAX_SPI_CLOCK_SWITCH_COUNT) { + udelay(10); + status = CONSYS_REG_READ(CONN_REG_RFSPI_ADDR + CONN_RF_SPI_MST_REG_SPI_CRTL) & 0x18; + counter++; + } + if (counter == MAX_SPI_CLOCK_SWITCH_COUNT) { + pr_err("[%s] switch to 26M fail\n", __func__); + ret = -1; + } + } else if (type == CONNSYS_SPI_SPEED_64M) { + CONSYS_REG_WRITE_MASK( + CONN_REG_RFSPI_ADDR + CONN_RF_SPI_MST_REG_SPI_CRTL, 0x5, 0x5); + status = CONSYS_REG_READ(CONN_REG_RFSPI_ADDR + CONN_RF_SPI_MST_REG_SPI_CRTL) & 0x18; + while (status != 0x10 && counter < MAX_SPI_CLOCK_SWITCH_COUNT) { + udelay(10); + status = CONSYS_REG_READ(CONN_REG_RFSPI_ADDR + CONN_RF_SPI_MST_REG_SPI_CRTL) & 0x18; + counter++; + } + if (counter == MAX_SPI_CLOCK_SWITCH_COUNT) { + pr_err("[%s] switch to 64M fail\n", __func__); + ret = -1; + } + } else { + ret = -1; + pr_err("[%s] wrong parameter %d\n", __func__, type); + } + + consys_sema_release(CONN_SEMA_RFSPI_INDEX); + + return ret; +} + +int consys_subsys_status_update(bool on, int radio) +{ + if (radio < CONNDRV_TYPE_BT || radio > CONNDRV_TYPE_WIFI) { + pr_err("[%s] wrong parameter: %d\n", __func__, radio); + return -1; + } + + if (consys_sema_acquire_timeout(CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) { + pr_err("[%s] acquire semaphore (%d) timeout\n", + __func__, CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX); + return -1; + } + + if (on) { + CONSYS_SET_BIT( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_RADIO_STATUS, + (0x1 << radio)); + } else { + CONSYS_CLR_BIT( + CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_RADIO_STATUS, + (0x1 << radio)); + } + + consys_sema_release(CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX); + return 0; +} + + +bool consys_is_rc_mode_enable(void) +{ + int ret; + + ret = CONSYS_REG_READ_BIT(CON_REG_SPM_BASE_ADDR + SPM_RC_CENTRAL_CFG1, 0x1); + + return ret; +} + +void consys_config_setup(void) +{ + /* To access CR in conninfra off domain, Conninfra should be on state */ + /* Enable conn_infra bus hang detect function + * Address: 0x1800_F000 + * Data: 32'h32C8_001C + * Action: write + */ + CONSYS_REG_WRITE(CONN_DEBUG_CTRL_ADDR + CONN_DEBUG_CTRL_REG_OFFSET, 0x32c8001c); +} diff --git a/drivers/misc/mediatek/connectivity/conninfra/platform/pmic_mng.c b/drivers/misc/mediatek/connectivity/conninfra/platform/pmic_mng.c new file mode 100644 index 0000000000000..433f5b9995e95 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/platform/pmic_mng.c @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#include "pmic_mng.h" + +#include "osal.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 +******************************************************************************** +*/ + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + +P_CONSYS_PLATFORM_PMIC_OPS consys_platform_pmic_ops; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +P_CONSYS_PLATFORM_PMIC_OPS __weak get_consys_platform_pmic_ops(void) +{ + pr_err("No specify project\n"); + return NULL; +} + + +int pmic_mng_init(struct platform_device *pdev, struct conninfra_dev_cb* dev_cb) +{ + if (consys_platform_pmic_ops == NULL) + consys_platform_pmic_ops = get_consys_platform_pmic_ops(); + + if (consys_platform_pmic_ops && consys_platform_pmic_ops->consys_pmic_get_from_dts) + consys_platform_pmic_ops->consys_pmic_get_from_dts(pdev, dev_cb); + + return 0; +} + +int pmic_mng_deinit(void) +{ + return 0; +} + +int pmic_mng_common_power_ctrl(unsigned int enable) +{ + int ret = 0; + if (consys_platform_pmic_ops && + consys_platform_pmic_ops->consys_pmic_common_power_ctrl) + ret = consys_platform_pmic_ops->consys_pmic_common_power_ctrl(enable); + return ret; +} + +int pmic_mng_wifi_power_ctrl(unsigned int enable) +{ + int ret = 0; + if (consys_platform_pmic_ops && + consys_platform_pmic_ops->consys_pmic_wifi_power_ctrl) + ret = consys_platform_pmic_ops->consys_pmic_wifi_power_ctrl(enable); + return ret; + +} + +int pmic_mng_bt_power_ctrl(unsigned int enable) +{ + int ret = 0; + if (consys_platform_pmic_ops && + consys_platform_pmic_ops->consys_pmic_bt_power_ctrl) + ret = consys_platform_pmic_ops->consys_pmic_bt_power_ctrl(enable); + return ret; +} + +int pmic_mng_gps_power_ctrl(unsigned int enable) +{ + int ret = 0; + if (consys_platform_pmic_ops && + consys_platform_pmic_ops->consys_pmic_gps_power_ctrl) + ret = consys_platform_pmic_ops->consys_pmic_gps_power_ctrl(enable); + return ret; +} + +int pmic_mng_fm_power_ctrl(unsigned int enable) +{ + int ret = 0; + if (consys_platform_pmic_ops && + consys_platform_pmic_ops->consys_pmic_fm_power_ctrl) + ret = consys_platform_pmic_ops->consys_pmic_fm_power_ctrl(enable); + return ret; +} + + +int pmic_mng_event_cb(unsigned int id, unsigned int event) +{ + if (consys_platform_pmic_ops && + consys_platform_pmic_ops->consys_pmic_event_notifier) + consys_platform_pmic_ops->consys_pmic_event_notifier(id, event); + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/conninfra/src/conninfra.c b/drivers/misc/mediatek/connectivity/conninfra/src/conninfra.c new file mode 100644 index 0000000000000..ec09c08ec4923 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/src/conninfra.c @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#define pr_fmt(fmt) KBUILD_MODNAME "@(%s:%d) " fmt, __func__, __LINE__ + +#include +#include +#include +#include +#include +#include +#include "conninfra.h" +#include "emi_mng.h" +#include "conninfra_core.h" +#include "consys_hw.h" + +#include + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +#define CONNINFRA_RST_RATE_LIMIT 0 + +#if CONNINFRA_RST_RATE_LIMIT +DEFINE_RATELIMIT_STATE(g_rs, HZ, 1); + +#define DUMP_LOG() if (__ratelimit(&g_rs)) \ + pr_info("rst is ongoing") + +#else +#define DUMP_LOG() +#endif + +struct conninfra_rst_data { + struct work_struct rst_worker; + enum consys_drv_type drv; + char *reason; +}; + +struct conninfra_rst_data rst_data; + +int conninfra_get_clock_schematic(void) +{ + return consys_hw_get_clock_schematic(); +} +EXPORT_SYMBOL(conninfra_get_clock_schematic); + +void conninfra_get_phy_addr(unsigned int *addr, unsigned int *size) +{ + phys_addr_t base; + + conninfra_get_emi_phy_addr(CONNSYS_EMI_FW, &base, size); + if (addr) + *addr = (unsigned int)base; + return; +} +EXPORT_SYMBOL(conninfra_get_phy_addr); + +void conninfra_get_emi_phy_addr(enum connsys_emi_type type, phys_addr_t* base, unsigned int *size) +{ + struct consys_emi_addr_info* addr_info = emi_mng_get_phy_addr(); + + switch (type) { + case CONNSYS_EMI_FW: + if (base) + *base = addr_info->emi_ap_phy_addr; + if (size) + *size = addr_info->emi_size; + break; + case CONNSYS_EMI_MCIF: + if (base) + *base = addr_info->md_emi_phy_addr; + if (size) + *size = addr_info->md_emi_size; + break; + default: + pr_err("Wrong EMI type: %d\n", type); + if (base) + *base = 0x0; + if (size) + *size = 0; + } +} +EXPORT_SYMBOL(conninfra_get_emi_phy_addr); + +int conninfra_pwr_on(enum consys_drv_type drv_type) +{ + pr_info("[%s] drv=[%d]", __func__, drv_type); + if (conninfra_core_is_rst_locking()) { + DUMP_LOG(); + return CONNINFRA_ERR_RST_ONGOING; + } + +#if ENABLE_PRE_CAL_BLOCKING_CHECK + conninfra_core_pre_cal_blocking(); +#endif + + return conninfra_core_power_on(drv_type); +} +EXPORT_SYMBOL(conninfra_pwr_on); + +int conninfra_pwr_off(enum consys_drv_type drv_type) +{ + if (conninfra_core_is_rst_locking()) { + DUMP_LOG(); + return CONNINFRA_ERR_RST_ONGOING; + } + +#if ENABLE_PRE_CAL_BLOCKING_CHECK + conninfra_core_pre_cal_blocking(); +#endif + + return conninfra_core_power_off(drv_type); +} +EXPORT_SYMBOL(conninfra_pwr_off); + + +int conninfra_reg_readable(void) +{ + return conninfra_core_reg_readable(); +} +EXPORT_SYMBOL(conninfra_reg_readable); + + +int conninfra_reg_readable_no_lock(void) +{ + return conninfra_core_reg_readable_no_lock(); +} +EXPORT_SYMBOL(conninfra_reg_readable_no_lock); + +int conninfra_is_bus_hang(void) +{ + if (conninfra_core_is_rst_locking()) { + DUMP_LOG(); + return CONNINFRA_ERR_RST_ONGOING; + } + return conninfra_core_is_bus_hang(); +} +EXPORT_SYMBOL(conninfra_is_bus_hang); + +int conninfra_trigger_whole_chip_rst(enum consys_drv_type who, char *reason) +{ + /* use schedule worker to trigger ??? */ + /* so that function can be returned immediately */ + int r; + + r = conninfra_core_lock_rst(); + if (r >= CHIP_RST_START) { + /* reset is ongoing */ + pr_warn("[%s] r=[%d] chip rst is ongoing\n", __func__, r); + return 1; + } + pr_info("[%s] rst lock [%d] [%d] reason=%s", __func__, r, who, reason); + + conninfra_core_trg_chip_rst(who, reason); + + return 0; +} +EXPORT_SYMBOL(conninfra_trigger_whole_chip_rst); + +int conninfra_sub_drv_ops_register(enum consys_drv_type type, + struct sub_drv_ops_cb *cb) +{ + /* type validation */ + if (type < 0 || type >= CONNDRV_TYPE_MAX) { + pr_err("[%s] incorrect drv type [%d]", __func__, type); + return -EINVAL; + } + pr_info("[%s] ----", __func__); + conninfra_core_subsys_ops_reg(type, cb); + return 0; +} +EXPORT_SYMBOL(conninfra_sub_drv_ops_register); + +int conninfra_sub_drv_ops_unregister(enum consys_drv_type type) +{ + /* type validation */ + if (type < 0 || type >= CONNDRV_TYPE_MAX) { + pr_err("[%s] incorrect drv type [%d]", __func__, type); + return -EINVAL; + } + pr_info("[%s] ----", __func__); + conninfra_core_subsys_ops_unreg(type); + return 0; +} +EXPORT_SYMBOL(conninfra_sub_drv_ops_unregister); + + +int conninfra_spi_read(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data) +{ + if (conninfra_core_is_rst_locking()) { + DUMP_LOG(); + return CONNINFRA_ERR_RST_ONGOING; + } + if (subsystem >= SYS_SPI_MAX) { + pr_err("[%s] wrong subsys %d", __func__, subsystem); + return -EINVAL; + } + conninfra_core_spi_read(subsystem, addr, data); + return 0; +} +EXPORT_SYMBOL(conninfra_spi_read); + +int conninfra_spi_write(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data) +{ + if (conninfra_core_is_rst_locking()) { + DUMP_LOG(); + return CONNINFRA_ERR_RST_ONGOING; + } + + if (subsystem >= SYS_SPI_MAX) { + pr_err("[%s] wrong subsys %d", __func__, subsystem); + return -EINVAL; + } + conninfra_core_spi_write(subsystem, addr, data); + return 0; +} +EXPORT_SYMBOL(conninfra_spi_write); + +int conninfra_adie_top_ck_en_on(enum consys_adie_ctl_type type) +{ + if (conninfra_core_is_rst_locking()) { + DUMP_LOG(); + return CONNINFRA_ERR_RST_ONGOING; + } + + return conninfra_core_adie_top_ck_en_on(type); +} +EXPORT_SYMBOL(conninfra_adie_top_ck_en_on); + +int conninfra_adie_top_ck_en_off(enum consys_adie_ctl_type type) +{ + if (conninfra_core_is_rst_locking()) { + DUMP_LOG(); + return CONNINFRA_ERR_RST_ONGOING; + } + + return conninfra_core_adie_top_ck_en_off(type); +} +EXPORT_SYMBOL(conninfra_adie_top_ck_en_off); + +int conninfra_spi_clock_switch(enum connsys_spi_speed_type type) +{ + return conninfra_core_spi_clock_switch(type); +} +EXPORT_SYMBOL(conninfra_spi_clock_switch); + +void conninfra_config_setup(void) +{ + if (conninfra_core_is_rst_locking()) { + DUMP_LOG(); + return; + } + + conninfra_core_config_setup(); +} +EXPORT_SYMBOL(conninfra_config_setup); + +int conninfra_bus_clock_ctrl(enum consys_drv_type drv_type, unsigned int bus_clock, int status) +{ + return conninfra_core_bus_clock_ctrl(drv_type, bus_clock, status); +} +EXPORT_SYMBOL(conninfra_bus_clock_ctrl); diff --git a/drivers/misc/mediatek/connectivity/conninfra/src/conninfra_dev.c b/drivers/misc/mediatek/connectivity/conninfra/src/conninfra_dev.c new file mode 100644 index 0000000000000..b0279174eb7f6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/src/conninfra_dev.c @@ -0,0 +1,659 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#include +#include +#include +#include +#include +#include "conninfra.h" +#include "conninfra_conf.h" +#include "conninfra_core.h" +#include "conninfra_dbg.h" +#include "consys_hw.h" +#include "connsys_debug_utility.h" +#include "wmt_build_in_adapter.h" +#include "emi_mng.h" + +#ifdef MTK_WCN_REMOVE_KERNEL_MODULE +#include "conn_drv_init.h" +#endif +#ifdef CFG_CONNINFRA_UT_SUPPORT +#include "conninfra_test.h" +#endif + +#include + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define CONNINFRA_DEV_MAJOR 164 +//#define WMT_DETECT_MAJOR 154 +#define CONNINFRA_DEV_NUM 1 +#define CONNINFRA_DRVIER_NAME "conninfra_drv" +#define CONNINFRA_DEVICE_NAME "conninfra_dev" + +#define CONNINFRA_DEV_IOC_MAGIC 0xc2 +#define CONNINFRA_IOCTL_GET_CHIP_ID _IOR(CONNINFRA_DEV_IOC_MAGIC, 0, int) +#define CONNINFRA_IOCTL_SET_COREDUMP_MODE _IOW(CONNINFRA_DEV_IOC_MAGIC, 1, unsigned int) +#define CONNINFRA_IOCTL_DO_MODULE_INIT _IOR(CONNINFRA_DEV_IOC_MAGIC, 2, int) + +#define CONNINFRA_DEV_INIT_TO_MS (2 * 1000) + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +enum conninfra_init_status { + CONNINFRA_INIT_NOT_START, + CONNINFRA_INIT_START, + CONNINFRA_INIT_DONE, +}; +static int g_conninfra_init_status = CONNINFRA_INIT_NOT_START; +static wait_queue_head_t g_conninfra_init_wq; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +struct conninfra_pmic_work { + unsigned int id; + unsigned int event; + struct work_struct pmic_work; +}; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static int conninfra_dev_fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data); + +static int conninfra_dev_open(struct inode *inode, struct file *file); +static int conninfra_dev_close(struct inode *inode, struct file *file); +static ssize_t conninfra_dev_read(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos); +static ssize_t conninfra_dev_write(struct file *filp, + const char __user *buf, size_t count, + loff_t *f_pos); +static long conninfra_dev_unlocked_ioctl( + struct file *filp, unsigned int cmd, unsigned long arg); +#ifdef CONFIG_COMPAT +static long conninfra_dev_compat_ioctl( + struct file *filp, unsigned int cmd, unsigned long arg); +#endif +static int conninfra_mmap(struct file *pFile, struct vm_area_struct *pVma); +static int conninfra_thermal_query_cb(void); +static void conninfra_clock_fail_dump_cb(void); + +static int conninfra_conn_reg_readable(void); +static int conninfra_conn_is_bus_hang(void); + +static void conninfra_devapc_violation_cb(void); +static void conninfra_register_devapc_callback(void); + +static int conninfra_dev_suspend_cb(void); +static int conninfra_dev_resume_cb(void); +static int conninfra_dev_pmic_event_cb(unsigned int, unsigned int); + +static int conninfra_dev_do_drv_init(void); +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +struct class *pConninfraClass; +struct device *pConninfraDev; +static struct cdev gConninfraCdev; + +const struct file_operations gConninfraDevFops = { + .open = conninfra_dev_open, + .release = conninfra_dev_close, + .read = conninfra_dev_read, + .write = conninfra_dev_write, + .unlocked_ioctl = conninfra_dev_unlocked_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = conninfra_dev_compat_ioctl, +#endif + .mmap = conninfra_mmap, +}; + +struct wmt_platform_bridge g_plat_bridge = { + .thermal_query_cb = conninfra_thermal_query_cb, + .clock_fail_dump_cb = conninfra_clock_fail_dump_cb, + .conninfra_reg_readable_cb = conninfra_conn_reg_readable, + .conninfra_reg_is_bus_hang_cb = conninfra_conn_is_bus_hang +}; + + +static int gConnInfraMajor = CONNINFRA_DEV_MAJOR; + +/* screen on/off notification */ +static struct notifier_block conninfra_fb_notifier; +static struct work_struct gPwrOnOffWork; +static atomic_t g_es_lr_flag_for_blank = ATOMIC_INIT(0); /* for ctrl blank flag */ +static int last_thermal_value; +static int g_temp_thermal_value; +/* For DEVAPC callback */ +static struct work_struct g_conninfra_devapc_work; +static struct devapc_vio_callbacks conninfra_devapc_handle = { + .id = INFRA_SUBSYS_CONN, + .debug_dump = conninfra_devapc_violation_cb, +}; +/* For PMIC callback */ +static struct conninfra_pmic_work g_conninfra_pmic_work; + +static struct conninfra_dev_cb g_conninfra_dev_cb = { + .conninfra_suspend_cb = conninfra_dev_suspend_cb, + .conninfra_resume_cb = conninfra_dev_resume_cb, + .conninfra_pmic_event_notifier = conninfra_dev_pmic_event_cb, +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +int conninfra_dev_open(struct inode *inode, struct file *file) +{ +#ifdef MTK_WCN_REMOVE_KERNEL_MODULE + pr_info("[%s] built-in mode, allow to open", __func__); +#else + static DEFINE_RATELIMIT_STATE(_rs, HZ, 1); + + if (!wait_event_timeout( + g_conninfra_init_wq, + g_conninfra_init_status == CONNINFRA_INIT_DONE, + msecs_to_jiffies(CONNINFRA_DEV_INIT_TO_MS))) { + if (__ratelimit(&_rs)) { + pr_warn("wait_event_timeout (%d)ms,(%lu)jiffies,return -EIO\n", + CONNINFRA_DEV_INIT_TO_MS, msecs_to_jiffies(CONNINFRA_DEV_INIT_TO_MS)); + } + return -EIO; + } +#endif + pr_info("open major %d minor %d (pid %d)\n", + imajor(inode), iminor(inode), current->pid); + + return 0; +} + +int conninfra_dev_close(struct inode *inode, struct file *file) +{ + pr_info("close major %d minor %d (pid %d)\n", + imajor(inode), iminor(inode), current->pid); + + return 0; +} + +ssize_t conninfra_dev_read(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + return 0; +} + +ssize_t conninfra_dev_write(struct file *filp, + const char __user *buf, size_t count, loff_t *f_pos) +{ + return 0; +} + +static long conninfra_dev_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ +#ifdef MTK_WCN_REMOVE_KERNEL_MODULE + static DEFINE_RATELIMIT_STATE(_rs, HZ, 1); +#endif + int retval = 0; + + pr_info("[%s] cmd (%d),arg(%ld)\n", __func__, cmd, arg); + + /* Special process for module init command */ + if (cmd == CONNINFRA_IOCTL_DO_MODULE_INIT) { + #ifdef MTK_WCN_REMOVE_KERNEL_MODULE + retval = conninfra_dev_do_drv_init(); + return retval; + #else + pr_info("[%s] KO mode", __func__); + return 0; + #endif + } + +#ifdef MTK_WCN_REMOVE_KERNEL_MODULE + if (!wait_event_timeout( + g_conninfra_init_wq, + g_conninfra_init_status == CONNINFRA_INIT_DONE, + msecs_to_jiffies(CONNINFRA_DEV_INIT_TO_MS))) { + if (__ratelimit(&_rs)) { + pr_warn("wait_event_timeout (%d)ms,(%lu)jiffies,return -EIO\n", + CONNINFRA_DEV_INIT_TO_MS, msecs_to_jiffies(CONNINFRA_DEV_INIT_TO_MS)); + } + return -EIO; + } +#endif + + switch (cmd) { + case CONNINFRA_IOCTL_GET_CHIP_ID: + retval = consys_hw_chipid_get(); + break; + case CONNINFRA_IOCTL_SET_COREDUMP_MODE: + connsys_coredump_set_dump_mode(arg); + break; + } + + return retval; + +} + +#ifdef CONFIG_COMPAT +static long conninfra_dev_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + long ret; + + pr_info("[%s] cmd (%d)\n", __func__, cmd); + ret = conninfra_dev_unlocked_ioctl(filp, cmd, arg); + return ret; +} +#endif + +static int conninfra_mmap(struct file *pFile, struct vm_area_struct *pVma) +{ + unsigned long bufId = pVma->vm_pgoff; + struct consys_emi_addr_info* addr_info = emi_mng_get_phy_addr(); + + pr_info("conninfra_mmap start:%lu end:%lu size: %lu buffer id=%lu\n", + pVma->vm_start, pVma->vm_end, + pVma->vm_end - pVma->vm_start, bufId); + + if (bufId == 0) { + if (pVma->vm_end - pVma->vm_start > addr_info->emi_size) + return -EINVAL; + pr_info("conninfra_mmap size: %lu\n", pVma->vm_end - pVma->vm_start); + if (remap_pfn_range(pVma, pVma->vm_start, addr_info->emi_ap_phy_addr >> PAGE_SHIFT, + pVma->vm_end - pVma->vm_start, pVma->vm_page_prot)) + return -EAGAIN; + return 0; + } else if (bufId == 1) { + if (addr_info == NULL) + return -EINVAL; + if (addr_info->md_emi_size == 0 || + pVma->vm_end - pVma->vm_start > addr_info->md_emi_size) + return -EINVAL; + pr_info("MD direct path size=%u map size=%lu\n", + addr_info->md_emi_size, + pVma->vm_end - pVma->vm_start); + if (remap_pfn_range(pVma, pVma->vm_start, + addr_info->md_emi_phy_addr >> PAGE_SHIFT, + pVma->vm_end - pVma->vm_start, pVma->vm_page_prot)) + return -EAGAIN; + return 0; + } + /* Invalid bufId */ + return -EINVAL; +} + +static int conninfra_dev_get_blank_state(void) +{ + return atomic_read(&g_es_lr_flag_for_blank); +} + +int conninfra_dev_fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct fb_event *evdata = data; + int blank; + + pr_debug("conninfra_dev_fb_notifier_callback event=[%u]\n", event); + + /* If we aren't interested in this event, skip it immediately ... */ + if (event != FB_EARLY_EVENT_BLANK) + return 0; + + blank = *(int *)evdata->data; + + switch (blank) { + case FB_BLANK_UNBLANK: + atomic_set(&g_es_lr_flag_for_blank, 1); + pr_info("@@@@@@@@@@ Conninfra enter UNBLANK @@@@@@@@@@@@@@\n"); + schedule_work(&gPwrOnOffWork); + break; + case FB_BLANK_POWERDOWN: + atomic_set(&g_es_lr_flag_for_blank, 0); + pr_info("@@@@@@@@@@ Conninfra enter early POWERDOWN @@@@@@@@@@@@@@\n"); + schedule_work(&gPwrOnOffWork); + break; + default: + break; + } + return 0; +} + +static void conninfra_dev_pwr_on_off_handler(struct work_struct *work) +{ + pr_debug("conninfra_dev_pwr_on_off_handler start to run\n"); + + /* Update blank on status after wmt power on */ + if (conninfra_dev_get_blank_state() == 1) { + conninfra_core_screen_on(); + } else { + conninfra_core_screen_off(); + } +} + +static int conninfra_thermal_query_cb(void) +{ + int ret; + + /* if rst is ongoing, return thermal val got from last time */ + if (conninfra_core_is_rst_locking()) { + pr_info("[%s] rst is locking, return last temp ", __func__); + return last_thermal_value; + } + pr_info("[%s] query thermal", __func__); + ret = conninfra_core_thermal_query(&g_temp_thermal_value); + if (ret == 0) + last_thermal_value = g_temp_thermal_value; + else if (ret == CONNINFRA_ERR_WAKEUP_FAIL) + conninfra_trigger_whole_chip_rst(CONNDRV_TYPE_CONNINFRA, "Query thermal wakeup fail"); + + return last_thermal_value; +} + +static void conninfra_clock_fail_dump_cb(void) +{ + conninfra_core_clock_fail_dump_cb(); +} + + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ +/* THIS FUNCTION IS ONLY FOR AUDIO DRIVER */ +/* this function go through consys_hw, skip conninfra_core */ +/* there is no lock and skip consys power on check */ +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ +static int conninfra_conn_reg_readable(void) +{ + return consys_hw_reg_readable(); + /*return conninfra_core_reg_readable(); */ +} + +static int conninfra_conn_is_bus_hang(void) +{ + /* if rst is ongoing, don't dump */ + if (conninfra_core_is_rst_locking()) { + pr_info("[%s] rst is locking, skip dump", __func__); + return CONNINFRA_ERR_RST_ONGOING; + } + return conninfra_core_is_bus_hang(); +} + +static void conninfra_devapc_violation_cb(void) +{ + schedule_work(&g_conninfra_devapc_work); +} + +static void conninfra_devapc_handler(struct work_struct *work) +{ + conninfra_trigger_whole_chip_rst(CONNDRV_TYPE_CONNINFRA, "CONNSYS DEVAPC"); +} + +static void conninfra_register_devapc_callback(void) +{ + INIT_WORK(&g_conninfra_devapc_work, conninfra_devapc_handler); + register_devapc_vio_callback(&conninfra_devapc_handle); +} + +static int conninfra_dev_suspend_cb(void) +{ + return 0; +} + +static int conninfra_dev_resume_cb(void) +{ + conninfra_core_dump_power_state(); + return 0; +} + +static int conninfra_dev_pmic_event_cb(unsigned int id, unsigned int event) +{ + g_conninfra_pmic_work.id = id; + g_conninfra_pmic_work.event = event; + schedule_work(&g_conninfra_pmic_work.pmic_work); + + return 0; +} + +static void conninfra_dev_pmic_event_handler(struct work_struct *work) +{ + unsigned int id, event; + struct conninfra_pmic_work *pmic_work = + container_of(work, struct conninfra_pmic_work, pmic_work); + + if (pmic_work) { + id = pmic_work->id; + event = pmic_work->event; + conninfra_core_pmic_event_cb(id, event); + } else + pr_err("[%s] pmic_work is null (id, event)=(%d, %d)", __func__, id, event); + +} + +static void conninfra_register_pmic_callback(void) +{ + INIT_WORK(&g_conninfra_pmic_work.pmic_work, conninfra_dev_pmic_event_handler); +} + + +/************************************************************************/ +static int conninfra_dev_do_drv_init() +{ + static int init_done = 0; + int iret = 0; + + if (init_done) { + pr_info("%s already init, return.", __func__); + return 0; + } + init_done = 1; + + /* init power on off handler */ + INIT_WORK(&gPwrOnOffWork, conninfra_dev_pwr_on_off_handler); + conninfra_fb_notifier.notifier_call + = conninfra_dev_fb_notifier_callback; + iret = fb_register_client(&conninfra_fb_notifier); + if (iret) + pr_err("register fb_notifier fail"); + else + pr_info("register fb_notifier success"); + +#ifdef CFG_CONNINFRA_UT_SUPPORT + iret = conninfra_test_setup(); + if (iret) + pr_err("init conninfra_test fail, ret = %d\n", iret); +#endif + + iret = conninfra_conf_init(); + if (iret) + pr_warn("init conf fail\n"); + + iret = consys_hw_init(&g_conninfra_dev_cb); + if (iret) { + pr_err("init consys_hw fail, ret = %d\n", iret); + g_conninfra_init_status = CONNINFRA_INIT_NOT_START; + return -2; + } + + iret = conninfra_core_init(); + if (iret) { + pr_err("conninfra init fail"); + g_conninfra_init_status = CONNINFRA_INIT_NOT_START; + return -3; + } + + conninfra_dev_dbg_init(); + + wmt_export_platform_bridge_register(&g_plat_bridge); + + conninfra_register_devapc_callback(); + conninfra_register_pmic_callback(); + + pr_info("ConnInfra Dev: init (%d)\n", iret); + g_conninfra_init_status = CONNINFRA_INIT_DONE; + +#ifdef MTK_WCN_REMOVE_KERNEL_MODULE + iret = (int)consys_hw_chipid_get(); + iret = do_connectivity_driver_init(iret); + if (iret) + pr_err("Sub driver init fail, iret=%d", iret); +#endif + + return 0; + +} + + +static int conninfra_dev_init(void) +{ + dev_t devID = MKDEV(gConnInfraMajor, 0); + int cdevErr = -1; + int iret = 0; + + g_conninfra_init_status = CONNINFRA_INIT_START; + init_waitqueue_head((wait_queue_head_t *)&g_conninfra_init_wq); + + iret = register_chrdev_region(devID, CONNINFRA_DEV_NUM, + CONNINFRA_DRVIER_NAME); + if (iret) { + pr_err("fail to register chrdev\n"); + g_conninfra_init_status = CONNINFRA_INIT_NOT_START; + return -1; + } + + cdev_init(&gConninfraCdev, &gConninfraDevFops); + gConninfraCdev.owner = THIS_MODULE; + + cdevErr = cdev_add(&gConninfraCdev, devID, CONNINFRA_DEV_NUM); + if (cdevErr) { + pr_err("cdev_add() fails (%d)\n", cdevErr); + goto err1; + } + + pConninfraClass = class_create(THIS_MODULE, CONNINFRA_DEVICE_NAME); + if (IS_ERR(pConninfraClass)) { + pr_err("class create fail, error code(%ld)\n", + PTR_ERR(pConninfraClass)); + goto err1; + } + + pConninfraDev = device_create(pConninfraClass, NULL, devID, + NULL, CONNINFRA_DEVICE_NAME); + if (IS_ERR(pConninfraDev)) { + pr_err("device create fail, error code(%ld)\n", + PTR_ERR(pConninfraDev)); + goto err2; + } +#ifndef MTK_WCN_REMOVE_KERNEL_MODULE + iret = conninfra_dev_do_drv_init(); + if (iret) { + pr_err("conninfra_do_drv_init fail, iret = %d", iret); + return iret; + } +#endif + return 0; +err2: + + pr_err("[conninfra_dev_init] err2"); + if (pConninfraClass) { + class_destroy(pConninfraClass); + pConninfraClass = NULL; + } +err1: + pr_err("[conninfra_dev_init] err1"); + if (cdevErr == 0) + cdev_del(&gConninfraCdev); + + if (iret == 0) { + unregister_chrdev_region(devID, CONNINFRA_DEV_NUM); + gConnInfraMajor = -1; + } + + g_conninfra_init_status = CONNINFRA_INIT_NOT_START; + return -2; +} + +static void conninfra_dev_deinit(void) +{ + dev_t dev = MKDEV(gConnInfraMajor, 0); + int iret = 0; + + g_conninfra_init_status = CONNINFRA_INIT_NOT_START; + fb_unregister_client(&conninfra_fb_notifier); + + iret = conninfra_dev_dbg_deinit(); +#ifdef CFG_CONNINFRA_UT_SUPPORT + iret = conninfra_test_remove(); +#endif + + iret = conninfra_core_deinit(); + + iret = consys_hw_deinit(); + + iret = conninfra_conf_deinit(); + + if (pConninfraDev) { + device_destroy(pConninfraClass, dev); + pConninfraDev = NULL; + } + + if (pConninfraClass) { + class_destroy(pConninfraClass); + pConninfraClass = NULL; + } + + cdev_del(&gConninfraCdev); + unregister_chrdev_region(dev, CONNINFRA_DEV_NUM); + + pr_info("ConnInfra: ALPS platform init (%d)\n", iret); +} + +module_init(conninfra_dev_init); +module_exit(conninfra_dev_deinit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Willy.Yu @ CTD/SE5/CS5"); + +module_param(gConnInfraMajor, uint, 0644); + diff --git a/drivers/misc/mediatek/connectivity/conninfra/test/cal_test.c b/drivers/misc/mediatek/connectivity/conninfra/test/cal_test.c new file mode 100644 index 0000000000000..4ba3cc8806142 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/test/cal_test.c @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#include +#include +#include +#include "conninfra.h" +#include "conninfra_core.h" +#include "osal.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 +******************************************************************************** +*/ + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +int pre_cal_power_on_handler(void) +{ + pr_info("[%s] ===========", __func__); + osal_sleep_ms(100); + return 0; +} + +int pre_cal_do_cal_handler(void) +{ + pr_info("[%s] ===========", __func__); + return 0; +} + + +struct sub_drv_ops_cb g_cal_drv_ops_cb; + +int calibration_test(void) +{ + int ret; + + memset(&g_cal_drv_ops_cb, 0, sizeof(struct sub_drv_ops_cb)); + + g_cal_drv_ops_cb.pre_cal_cb.pwr_on_cb = pre_cal_power_on_handler; + g_cal_drv_ops_cb.pre_cal_cb.do_cal_cb = pre_cal_do_cal_handler; + + + pr_info("[%s] cb init [%p][%p]", __func__, + g_cal_drv_ops_cb.pre_cal_cb.pwr_on_cb, + g_cal_drv_ops_cb.pre_cal_cb.do_cal_cb); + + conninfra_sub_drv_ops_register(CONNDRV_TYPE_BT, &g_cal_drv_ops_cb); + conninfra_sub_drv_ops_register(CONNDRV_TYPE_WIFI, &g_cal_drv_ops_cb); + + ret = conninfra_core_pre_cal_start(); + if (ret) + pr_warn("[%s] fail [%d]", __func__, ret); + + osal_sleep_ms(1000); + + conninfra_core_screen_on(); + + conninfra_sub_drv_ops_unregister(CONNDRV_TYPE_BT); + conninfra_sub_drv_ops_unregister(CONNDRV_TYPE_WIFI); + pr_info("[%s] finish.", __func__); + return 0; +} + + diff --git a/drivers/misc/mediatek/connectivity/conninfra/test/chip_rst_test.c b/drivers/misc/mediatek/connectivity/conninfra/test/chip_rst_test.c new file mode 100644 index 0000000000000..bfd19b4fb5cb3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/test/chip_rst_test.c @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#include +#include +#include +#include "conninfra.h" +#include "osal.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 +******************************************************************************** +*/ + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +int pre_chip_rst_handler(enum consys_drv_type drv, char* reason) +{ + pr_info("[%s] ===========", __func__); + osal_sleep_ms(100); + return 0; +} + +int post_chip_rst_handler(void) +{ + pr_info("[%s] ===========", __func__); + return 0; +} + +int pre_chip_rst_timeout_handler(enum consys_drv_type drv, char* reason) +{ + pr_info("[%s] ++++++++++++", __func__); + osal_sleep_ms(800); + pr_info("[%s] ------------", __func__); + return 0; +} + +struct sub_drv_ops_cb g_drv_ops_cb; +struct sub_drv_ops_cb g_drv_timeout_ops_cb; + +int chip_rst_test(void) +{ + int ret; + + memset(&g_drv_ops_cb, 0, sizeof(struct sub_drv_ops_cb)); + memset(&g_drv_timeout_ops_cb, 0, sizeof(struct sub_drv_ops_cb)); + + g_drv_ops_cb.rst_cb.pre_whole_chip_rst = pre_chip_rst_handler; + g_drv_ops_cb.rst_cb.post_whole_chip_rst = post_chip_rst_handler; + + g_drv_timeout_ops_cb.rst_cb.pre_whole_chip_rst = pre_chip_rst_timeout_handler; + g_drv_timeout_ops_cb.rst_cb.post_whole_chip_rst = post_chip_rst_handler; + + pr_info("[%s] cb init [%p][%p]", __func__, + g_drv_ops_cb.rst_cb.pre_whole_chip_rst, + g_drv_ops_cb.rst_cb.post_whole_chip_rst); + + conninfra_sub_drv_ops_register(CONNDRV_TYPE_BT, &g_drv_ops_cb); + conninfra_sub_drv_ops_register(CONNDRV_TYPE_WIFI, &g_drv_ops_cb); + conninfra_sub_drv_ops_register(CONNDRV_TYPE_FM, &g_drv_timeout_ops_cb); + + pr_info("[%s] ++++++++++++++++++++++", __func__); + + ret = conninfra_trigger_whole_chip_rst(CONNDRV_TYPE_BT, "test reset"); + if (ret) + pr_warn("[%s] fail [%d]", __func__, ret); + else + pr_info("Trigger chip reset success. Test pass."); + osal_sleep_ms(10); + + pr_info("Try to trigger whole chip reset when reset is ongoing. It should be fail."); + ret = conninfra_trigger_whole_chip_rst(CONNDRV_TYPE_BT, "test reset"); + pr_info("Test %s. ret = %d.", ret == 1? "pass": "fail", ret); + + pr_info("Try to funcion on when reset is ongoing. It should be fail."); + ret = conninfra_pwr_on(CONNDRV_TYPE_WIFI); + pr_info("Test %s. ret = %d.", ret == CONNINFRA_ERR_RST_ONGOING ? "pass": "fail", ret); + + osal_sleep_ms(3000); + + conninfra_sub_drv_ops_unregister(CONNDRV_TYPE_BT); + conninfra_sub_drv_ops_unregister(CONNDRV_TYPE_WIFI); + pr_info("chip_rst_test finish"); + return 0; +} + + diff --git a/drivers/misc/mediatek/connectivity/conninfra/test/conf_test.c b/drivers/misc/mediatek/connectivity/conninfra/test/conf_test.c new file mode 100644 index 0000000000000..4f3936037decc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/test/conf_test.c @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#include "conninfra_conf.h" +#include "conf_test.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 +******************************************************************************** +*/ + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + + +int conninfra_conf_test(void) +{ + int ret; + const struct conninfra_conf *conf; + +#if 0 + ret = conninfra_conf_set_cfg_file("WMT_SOC.cfg"); + if (ret) { + pr_err("set cfg file fail [%d]", ret); + return -1; + } +#endif + + ret = conninfra_conf_init(); + if (ret) { + pr_err("int conf fail [%d]", ret); + return -1; + } + + conf = conninfra_conf_get_cfg(); + if (NULL == conf) { + pr_err("int conf fail [%d]", ret); + return -1; + } + if (conf->tcxo_gpio != 0) { + pr_err("test tcxo gpio fail [%d]. For most case, it should be 0.", + conf->tcxo_gpio); + return -1; + } + + pr_info("[%s] test PASS\n", __func__); + return 0; +} + + diff --git a/drivers/misc/mediatek/connectivity/conninfra/test/conninfra_core_test.c b/drivers/misc/mediatek/connectivity/conninfra/test/conninfra_core_test.c new file mode 100644 index 0000000000000..3f4e039cf79e8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/test/conninfra_core_test.c @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#include +#include +#include +#include "conninfra_core_test.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 +******************************************************************************** +*/ + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + + diff --git a/drivers/misc/mediatek/connectivity/conninfra/test/conninfra_test.c b/drivers/misc/mediatek/connectivity/conninfra/test/conninfra_test.c new file mode 100644 index 0000000000000..df5fd1376e139 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/test/conninfra_test.c @@ -0,0 +1,459 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#define pr_fmt(fmt) "conninfra_test@(%s:%d) " fmt, __func__, __LINE__ + +#include +#include +#include +#include "conninfra_test.h" +#include "osal.h" + +#include "conninfra.h" +#include "conninfra_core.h" +#include "consys_reg_mng.h" + +#include "connsyslog_test.h" +#include "conf_test.h" +#include "cal_test.h" +#include "msg_evt_test.h" +#include "chip_rst_test.h" +#include "mailbox_test.h" +#include "coredump_test.h" +#include "consys_hw.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define CONNINFRA_TEST_PROCNAME "driver/conninfra_test" + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static ssize_t conninfra_test_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos); +static ssize_t conninfra_test_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos); + +static int core_tc(int par1, int par2, int par3); +static int conf_tc(int par1, int par2, int par3); +static int cal_tc(int par1, int par2, int par3); +static int msg_evt_tc(int par1, int par2, int par3); +static int chip_rst_tc(int par1, int par2, int par3); +static int mailbox_tc(int par1, int par2, int par3); +static int emi_tc(int par1, int par2, int par3); +static int log_tc(int par1, int par2, int par3); +static int thermal_tc(int par1, int par2, int par3); +static int bus_hang_tc(int par1, int par2, int par3); +static int dump_tc(int par1, int par2, int par3); +static int is_bus_hang_tc(int par1, int par2, int par3); +static int ap_resume_tc(int par1, int par2, int par3); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +static struct proc_dir_entry *gConninfraTestEntry; + +static const CONNINFRA_TEST_FUNC conninfra_test_func[] = { + [0x01] = core_tc, + [0x02] = conf_tc, + [0x03] = msg_evt_tc, + [0x04] = chip_rst_tc, + [0x05] = cal_tc, + [0x06] = mailbox_tc, + [0x07] = emi_tc, + [0x08] = log_tc, + [0x09] = thermal_tc, + [0x0a] = bus_hang_tc, + [0x0b] = dump_tc, + [0x0c] = is_bus_hang_tc, + [0x0d] = ap_resume_tc, +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +int core_tc_pwr_on(void) +{ + int iret = 0; + + pr_info("Power on test start"); + iret = conninfra_core_power_on(CONNDRV_TYPE_BT); + pr_info("BT power on %s (result = %d)", iret? "fail" : "pass", iret); + osal_sleep_ms(100); + iret = conninfra_core_power_on(CONNDRV_TYPE_FM); + pr_info("FM power on %s (result = %d)", iret? "fail" : "pass", iret); + osal_sleep_ms(100); + iret = conninfra_core_power_on(CONNDRV_TYPE_GPS); + pr_info("GPS power on %s (result = %d)", iret? "fail" : "pass", iret); + osal_sleep_ms(100); + iret = conninfra_core_power_on(CONNDRV_TYPE_WIFI); + pr_info("Wi-Fi power on %s (result = %d)", iret? "fail" : "pass", iret); + osal_sleep_ms(200); + + return iret; +} + +int core_tc_pwr_off(void) +{ + int iret = 0; + + iret = conninfra_core_power_off(CONNDRV_TYPE_WIFI); + pr_info("Wi-Fi power off %s (result = %d)", iret? "fail" : "pass", iret); + osal_sleep_ms(100); + iret = conninfra_core_power_off(CONNDRV_TYPE_GPS); + pr_info("GPS power off %s (result = %d)", iret? "fail" : "pass", iret); + osal_sleep_ms(100); + iret = conninfra_core_power_off(CONNDRV_TYPE_BT); + pr_info("BT power off %s (result = %d)", iret? "fail" : "pass", iret); + osal_sleep_ms(100); + iret = conninfra_core_power_off(CONNDRV_TYPE_FM); + pr_info("FM power off %s (result = %d)", iret? "fail" : "pass", iret); + + return iret; +} + + +int core_tc(int par1, int par2, int par3) +{ + int iret = 0; + char* driver_name[CONNDRV_TYPE_MAX] = { + "BT", + "FM", + "GPS", + "Wi-Fi", + }; + + if (par2 == 0) { + iret = core_tc_pwr_on(); + iret = core_tc_pwr_off(); + } else if (par2 == 1) { + if (par3 == 15) { + iret = core_tc_pwr_on(); + } else if (par3 >= CONNDRV_TYPE_BT && par3 <= CONNDRV_TYPE_WIFI) { + pr_info("Power on %s test start\n", driver_name[par3]); + iret = conninfra_core_power_on(par3); + pr_info("Power on %s test, return = %d\n", driver_name[par3], iret); + } else { + pr_info("No support parameter\n"); + } + } else if (par2 == 2) { + if (par3 == 15) { + iret = core_tc_pwr_off(); + } else if (par3 >= CONNDRV_TYPE_BT && par3 <= CONNDRV_TYPE_WIFI) { + pr_info("Power off %s test start\n", driver_name[par3]); + iret = conninfra_core_power_off(par3); + pr_info("Power off %s test, return = %d\n", driver_name[par3], iret); + } else { + pr_info("No support parameter\n"); + } + } else if (par2 == 3) { + if (par3 == 1) { + iret = conninfra_core_adie_top_ck_en_on(CONNSYS_ADIE_CTL_FW_WIFI); + pr_info( + "Turn on adie top ck en (ret=%d), please check 0x1805_2830[6] should be 1\n", + iret); + } else if (par3 == 0) { + iret = conninfra_core_adie_top_ck_en_off(CONNSYS_ADIE_CTL_FW_WIFI); + pr_info( + "Turn off adie top ck en (ret=%d), please check 0x1805_2830[6] should be 1\n", + iret); + } + } + //pr_info("core_tc %s (result = %d)", iret? "fail" : "pass", iret); + return 0; +} + +static int conf_tc(int par1, int par2, int par3) +{ + return conninfra_conf_test(); +} + +static int msg_evt_tc(int par1, int par2, int par3) +{ + return msg_evt_test(); +} + +static int chip_rst_tc(int par1, int par2, int par3) +{ + pr_info("test start"); + return chip_rst_test(); +} + +static int cal_tc(int par1, int par2, int par3) +{ + pr_info("test start"); + return calibration_test(); +} + + +static int mailbox_tc(int par1, int par2, int par3) +{ + return mailbox_test(); +} + +static int emi_tc(int par1, int par2, int par3) +{ + unsigned int addr = 0; + unsigned int size = 0; + int ret = 0; + + pr_info("[%s] start", __func__); + conninfra_get_phy_addr(&addr, &size); + if (addr == 0 || size == 0) { + pr_err("[%s] fail! addr=[0x%x] size=[%u]", __func__, addr, size); + ret = -1; + } else + pr_info("[%s] pass. addr=[0x%x] size=[%u]", __func__, addr, size); + + pr_info("[%s] end", __func__); + + return ret; +} + +static int thermal_tc(int par1, int par2, int par3) +{ + int ret, temp; + + ret = core_tc_pwr_on(); + if (ret) { + pr_err("pwr on fail"); + return -1; + } + ret = conninfra_core_thermal_query(&temp); + pr_info("[%s] thermal res=[%d][%d]", __func__, ret, temp); + + return ret; +} + +static int log_tc(int par1, int par2, int par3) +{ + /* 0: initial state + * 1: log has been init. + */ + static int log_status = 0; + int ret = 0; + + if (par2 == 0) { + if (log_status != 0) { + pr_info("log has been init.\n"); + return 0; + } + /* init */ + ret = connlog_test_init(); + if (ret) + pr_err("FW log init fail! ret=%d\n", ret); + else { + log_status = 1; + pr_info("FW log init finish. Check result on EMI.\n"); + } + } else if (par2 == 1) { + /* add fake log */ + /* read log */ + connlog_test_read(); + } else if (par2 == 2) { + /* deinit */ + if (log_status == 0) { + pr_info("log didn't init\n"); + return 0; + } + ret = connlog_test_deinit(); + if (ret) + pr_err("FW log deinit fail! ret=%d\n", ret); + else + log_status = 0; + } + return ret; +} + + +static int bus_hang_tc(int par1, int par2, int par3) +{ + int r; + r = conninfra_core_is_bus_hang(); + + pr_info("[%s] r=[%d]\n", __func__, r); + return 0; +} + +static int dump_tc(int par1, int par2, int par3) +{ + return coredump_test(par1, par2, par3); +} + +static int is_bus_hang_tc(int par1, int par2, int par3) +{ + int r; + + r = consys_reg_mng_reg_readable(); + pr_info("[%s] r=[%d]", __func__, r); + r = consys_reg_mng_is_bus_hang(); + pr_info("[%s] r=[%d]", __func__, r); + return 0; +} + +static int ap_resume_tc(int par1, int par2, int par3) +{ + return 0; +} + +ssize_t conninfra_test_read(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + return 0; +} + +ssize_t conninfra_test_write(struct file *filp, const char __user *buffer, size_t count, loff_t *f_pos) +{ + size_t len = count; + char buf[256]; + char *pBuf; + char *pDelimiter = " \t"; + int x = 0, y = 0, z = 0; + char *pToken = NULL; + long res = 0; + static bool test_enabled = false; + + pr_info("write parameter len = %d\n\r", (int) len); + if (len >= osal_sizeof(buf)) { + pr_err("input handling fail!\n"); + len = osal_sizeof(buf) - 1; + return -1; + } + + if (copy_from_user(buf, buffer, len)) + return -EFAULT; + + buf[len] = '\0'; + pr_info("write parameter data = %s\n\r", buf); + + pBuf = buf; + pToken = osal_strsep(&pBuf, pDelimiter); + if (pToken != NULL) { + osal_strtol(pToken, 16, &res); + x = (int)res; + } else { + x = 0; + } + + pToken = osal_strsep(&pBuf, "\t\n "); + if (pToken != NULL) { + osal_strtol(pToken, 16, &res); + y = (int)res; + pr_info("y = 0x%08x\n\r", y); + } else { + y = 3000; + /*efuse, register read write default value */ + if (0x11 == x || 0x12 == x || 0x13 == x) + y = 0x80000000; + } + + pToken = osal_strsep(&pBuf, "\t\n "); + if (pToken != NULL) { + osal_strtol(pToken, 16, &res); + z = (int)res; + } else { + z = 10; + /*efuse, register read write default value */ + if (0x11 == x || 0x12 == x || 0x13 == x) + z = 0xffffffff; + } + + pr_info("x(0x%08x), y(0x%08x), z(0x%08x)\n\r", x, y, z); + + /* For eng and userdebug load, have to enable wmt_dbg by + * writing 0xDB9DB9 to * "/proc/driver/wmt_dbg" to avoid + * some malicious use + */ + if (x == 0xDB9DB9) { + test_enabled = true; + return len; + } + + if (!test_enabled) + return 0; + + if (osal_array_size(conninfra_test_func) > x && + NULL != conninfra_test_func[x]) + (*conninfra_test_func[x]) (x, y, z); + else + pr_warn("no handler defined for command id(0x%08x)\n\r", x); + + return len; + +} + + +int conninfra_test_setup(void) +{ + static const struct file_operations conninfra_test_fops = { + .owner = THIS_MODULE, + .read = conninfra_test_read, + .write = conninfra_test_write, + }; + int i_ret = 0; + + gConninfraTestEntry = proc_create(CONNINFRA_TEST_PROCNAME, + 0664, NULL, &conninfra_test_fops); + if (gConninfraTestEntry == NULL) { + pr_err("Unable to create / wmt_aee proc entry\n\r"); + i_ret = -1; + } + + return i_ret; +} + +int conninfra_test_remove(void) +{ + if (gConninfraTestEntry != NULL) + proc_remove(gConninfraTestEntry); + return 0; +} + diff --git a/drivers/misc/mediatek/connectivity/conninfra/test/connsyslog_test.c b/drivers/misc/mediatek/connectivity/conninfra/test/connsyslog_test.c new file mode 100644 index 0000000000000..eabcdc302b318 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/test/connsyslog_test.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + */ +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define pr_fmt(fmt) "connlog_test@(%s:%d) " fmt, __func__, __LINE__ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include + +#include "conninfra.h" +#include "connsys_debug_utility.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 connlog_test_event_handler(void); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +#define TEST_LOG_BUF_SIZE 1*2014 + +static char test_buf[TEST_LOG_BUF_SIZE]; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +static void connlog_test_event_handler(void) +{ + ssize_t read = 0; + pr_info("connlog_test_event_handler\n"); + + read = connsys_log_read(CONN_DEBUG_TYPE_WIFI, test_buf, TEST_LOG_BUF_SIZE); + pr_info("Read %u:\n", read); + connsys_log_dump_buf("log_test", test_buf, read); + pr_info("============================================\n"); +} + +int connlog_test_init(void) +{ + unsigned int emi_addr = 0; + unsigned int emi_size = 0; + int ret; + + conninfra_get_phy_addr(&emi_addr, &emi_size); + if (!emi_addr || !emi_size) { + pr_err("EMI init fail.\n"); + return 1; + } + + ret = connsys_dedicated_log_path_apsoc_init(emi_addr); + if (ret) { + pr_err("connsys_dedicated_log_path_apsoc_init should fail\n"); + return 2; + } else { + pr_info("connsys_dedicated_log_path_apsoc_init return fail as expection\n"); + } + + ret = connsys_log_init(CONN_DEBUG_TYPE_WIFI); + if (ret) { + pr_err("Init connsys log failed\n"); + return 3; + } + connsys_log_register_event_cb(CONN_DEBUG_TYPE_WIFI, connlog_test_event_handler); + return 0; +} + +int connlog_test_read(void) +{ + connsys_log_irq_handler(CONN_DEBUG_TYPE_WIFI); + return 0; +} + +int connlog_test_deinit(void) +{ + connsys_log_deinit(CONN_DEBUG_TYPE_WIFI); + return 0; +} + diff --git a/drivers/misc/mediatek/connectivity/conninfra/test/dump_test.c b/drivers/misc/mediatek/connectivity/conninfra/test/dump_test.c new file mode 100644 index 0000000000000..c1719f76d9c1f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/test/dump_test.c @@ -0,0 +1,290 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define pr_fmt(fmt) "dump_test@(%s:%d) " fmt, __func__, __LINE__ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include +#include + +#include "conninfra.h" +#include "connsys_debug_utility.h" + +#include "coredump_test.h" +#include "coredump/conndump_netlink.h" + +#include "msg_thread.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 int coredump_test_init(void); +static int coredump_test_start(void); +static int coredump_test_deinit(void); + +static int dump_test_reg_readable(void); +static void dump_test_poll_cpu_pcr(unsigned int times, unsigned int sleep); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static void* g_dumpCtx = 0; +static int nl_init = 0; +struct msg_thread_ctx g_msg_ctx; + +static int init = 0; + +typedef enum { + DUMP_TEST_OPID_1 = 0, + DUMP_TEST_OPID_2 = 1, + DUMP_TEST_OPID_MAX +} test_opid; + + +static int opfunc_test_1(struct msg_op_data *op); +static int opfunc_test_2(struct msg_op_data *op); + +static const msg_opid_func test_op_func[] = { + [DUMP_TEST_OPID_1] = opfunc_test_1, + [DUMP_TEST_OPID_2] = opfunc_test_2, +}; + +struct coredump_event_cb g_cb = { + .reg_readable = dump_test_reg_readable, + .poll_cpupcr = dump_test_poll_cpu_pcr, +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +static int dump_test_reg_readable(void) +{ + return 1; +} + +static void dump_test_poll_cpu_pcr(unsigned int times, unsigned int sleep) +{ + pr_info("[%s]\n", __func__); +} + +#define TEST_STRING "this is coredump test" + +static int coredump_test_start(void) +{ + + if (!g_dumpCtx) { + pr_err("coredump contxt is not init\n"); + return 1; + } +#if 0 + pr_info("[%s] tc[0] test case\n", __func__); + /* Trigger interrupt */ + connsys_coredump_setup_tc(g_dumpCtx, 0); + + /* Start to dump */ + connsys_coredump_start(g_dumpCtx, 0); + + pr_info("[%s] sleep\n", __func__); + msleep(5000); + + pr_info("[%s] tc[1] test case\n", __func__); + /* Trigger interrupt */ + connsys_coredump_setup_tc(g_dumpCtx, 1); + /* Start to dump */ + connsys_coredump_start(g_dumpCtx, 0); + + pr_info("[%s] tc[2] test case\n", __func__); + /* Trigger interrupt */ + connsys_coredump_setup_tc(g_dumpCtx, 2); + /* Start to dump */ + connsys_coredump_start(g_dumpCtx, 0); +#endif + + pr_info("[%s] end\n", __func__); + return 0; + +} + +static int coredump_nl_start(void) +{ + int ret; + + + ret = conndump_netlink_send_to_native(CONN_DEBUG_TYPE_WIFI, "[M]", TEST_STRING, osal_strlen(TEST_STRING)); + pr_info("send ret=%d", ret); + ret = conndump_netlink_send_to_native(CONN_DEBUG_TYPE_WIFI, "[EMI]", NULL, 0); + pr_info("send emi dump ret=%d", ret); + return 0; +} + +static int coredump_test_init(void) +{ + unsigned int emi_addr = 0; + unsigned int emi_size = 0; + + if (g_dumpCtx) { + pr_err("log handler has been init. Need to deinit.\n"); + return 1; + } + + conninfra_get_phy_addr(&emi_addr, &emi_size); + if (!emi_addr || !emi_size) { + pr_err("EMI init fail.\n"); + return 2; + } + + pr_info("emi_addr=0x%08x, size=%d", emi_addr, emi_size); + + g_dumpCtx = connsys_coredump_init( + CONN_DEBUG_TYPE_WIFI, &g_cb); + + if (!g_dumpCtx) { + pr_err("Coredump init fail.\n"); + return 3; + } + + return 0; + +} + +static void coredump_end_cb(void* ctx) { + pr_info("Get dump end"); +} + +static int coredump_nl_init(void) +{ + int ret; + struct netlink_event_cb nl_cb; + + if (!nl_init) { + nl_cb.coredump_end = coredump_end_cb; + ret = conndump_netlink_init(CONN_DEBUG_TYPE_WIFI, NULL, &nl_cb); + pr_info("init get %d", ret); + nl_init = 1; + } + return 0; +} + +static int coredump_test_deinit(void) +{ + if (!g_dumpCtx) { + pr_err("coredump contxt is not init\n"); + return 1; + } + + connsys_coredump_deinit(g_dumpCtx); + return 0; +} + +static int coredump_nl_deinit(void) +{ + nl_init = 0; + return 0; +} + +int opfunc_test_1(struct msg_op_data *op) +{ + int tc = op->op_data[0]; + int ret = 0; + + pr_info("[%s] param=[%d]", __func__, tc); + switch (tc) { + case 0: + ret = coredump_test_init(); + break; + case 1: + ret = coredump_test_start(); + break; + case 2: + ret = coredump_test_deinit(); + break; + } + pr_info("ret = %d", ret); + return 0; +} + +int opfunc_test_2(struct msg_op_data *op) +{ + int tc = op->op_data[0]; + int ret = 0; + + pr_info("[%s] param=[%d]", __func__, tc); + + switch (tc) { + case 0: + ret = coredump_nl_init(); + break; + case 1: + ret = coredump_nl_start(); + break; + case 2: + ret = coredump_nl_deinit(); + break; + } + pr_info("ret = %d", ret); + return 0; +} + +int coredump_test(int par1, int par2, int par3) +{ + pr_info("Disable coredump test in SQC\n"); + init = 1; + return 0; +#if 0 + int ret = 0; + + if (init == 0) { + ret = msg_thread_init( + &g_msg_ctx, "DumptestThread", test_op_func, DUMP_TEST_OPID_MAX); + init = 1; + } + if (par2 == 0xff && par3 == 0xff && init) { + pr_info("End test"); + msg_thread_deinit(&g_msg_ctx); + init = 0; + } + + msg_thread_send_1(&g_msg_ctx, par2, par3); + + return 0; +#endif +} + diff --git a/drivers/misc/mediatek/connectivity/conninfra/test/include/cal_test.h b/drivers/misc/mediatek/connectivity/conninfra/test/include/cal_test.h new file mode 100644 index 0000000000000..da917cae2e6db --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/test/include/cal_test.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _CAL_TEST_H_ +#define _CAL_TEST_H_ + +#include "osal.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 +******************************************************************************** +*/ + + +int calibration_test(void); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _CAL_TEST_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/test/include/chip_rst_test.h b/drivers/misc/mediatek/connectivity/conninfra/test/include/chip_rst_test.h new file mode 100644 index 0000000000000..b9b413a568b0c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/test/include/chip_rst_test.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _CHIP_RST_TEST_H_ +#define _CHIP_RST_TEST_H_ + +#include "osal.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 +******************************************************************************** +*/ + + +int chip_rst_test(void); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _CHIP_RST_TEST_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/test/include/conf_test.h b/drivers/misc/mediatek/connectivity/conninfra/test/include/conf_test.h new file mode 100644 index 0000000000000..a5aa7bd4a02ff --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/test/include/conf_test.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _CONF_TEST_H_ +#define _CONF_TEST_H_ + +#include "osal.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 +******************************************************************************** +*/ + + +int conninfra_conf_test(void); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _CONF_TEST_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/test/include/conninfra_core_test.h b/drivers/misc/mediatek/connectivity/conninfra/test/include/conninfra_core_test.h new file mode 100644 index 0000000000000..fcc964ad032b6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/test/include/conninfra_core_test.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _CONNINFRA_CORE_TEST_H_ +#define _CONNINFRA_CORE_TEST_H_ + +#include "osal.h" +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + + +#define WMT_FUNC_CTRL_ON (MTK_WCN_BOOL_TRUE) +#define WMT_FUNC_CTRL_OFF (MTK_WCN_BOOL_FALSE) + +#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 +******************************************************************************** +*/ + + +/******************************************************************************* +* 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 /* _CONNINFRA_CORE_TEST_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/test/include/conninfra_test.h b/drivers/misc/mediatek/connectivity/conninfra/test/include/conninfra_test.h new file mode 100644 index 0000000000000..4710e670b82d5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/test/include/conninfra_test.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _CONNINFRA_TEST_H_ +#define _CONNINFRA_TEST_H_ + +#include "osal.h" +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + + +#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 +******************************************************************************** +*/ + + +/******************************************************************************* +* 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 int(*CONNINFRA_TEST_FUNC) (int par1, int par2, int par3); + +int conninfra_test_setup(void); +int conninfra_test_remove(void); + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _CONNINFRA_CORE_TEST_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/test/include/connsyslog_test.h b/drivers/misc/mediatek/connectivity/conninfra/test/include/connsyslog_test.h new file mode 100644 index 0000000000000..f6e6988dd631e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/test/include/connsyslog_test.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#ifndef _CONNLOG_TEST_H_ +#define _CONNLOG_TEST_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 +******************************************************************************** +*/ + + +int connlog_test_init(void); +int connlog_test_read(void); +int connlog_test_deinit(void); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _CONNLOG_TEST_H_ */ + diff --git a/drivers/misc/mediatek/connectivity/conninfra/test/include/coredump_test.h b/drivers/misc/mediatek/connectivity/conninfra/test/include/coredump_test.h new file mode 100644 index 0000000000000..3934ca7726e46 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/test/include/coredump_test.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#ifndef _COREDUMP_TEST_H_ +#define _COREDUMP_TEST_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 +******************************************************************************** +*/ + +int coredump_test(int par1, int par2, int par3); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _COREDUMP_TEST_H_ */ + + diff --git a/drivers/misc/mediatek/connectivity/conninfra/test/include/mailbox_test.h b/drivers/misc/mediatek/connectivity/conninfra/test/include/mailbox_test.h new file mode 100644 index 0000000000000..99353524c7331 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/test/include/mailbox_test.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _MAILBOX_TEST_H_ +#define _MAILBOX_TEST_H_ + +#include "osal.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 +******************************************************************************** +*/ +int mailbox_test(void); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _MAILBOX_TEST_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/test/include/msg_evt_test.h b/drivers/misc/mediatek/connectivity/conninfra/test/include/msg_evt_test.h new file mode 100644 index 0000000000000..617c6579790f8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/test/include/msg_evt_test.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _MSG_EVT_TEST_H_ +#define _MSG_EVT_TEST_H_ + +#include "osal.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 +******************************************************************************** +*/ + + +int msg_evt_test(void); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _MSG_EVT_TEST_H_ */ diff --git a/drivers/misc/mediatek/connectivity/conninfra/test/mailbox_test.c b/drivers/misc/mediatek/connectivity/conninfra/test/mailbox_test.c new file mode 100644 index 0000000000000..49181bb12eef6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/test/mailbox_test.c @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#include +#include +#include +#include +#include +#include "consys_hw.h" +#include "conninfra_core_test.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 +******************************************************************************** +*/ + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +struct demo_client { + struct mbox_client cl; + struct mbox_chan *mbox; + struct completion c; + bool async; +}; + + +static void message_from_remote(struct mbox_client *cl, void *msg) +{ + struct demo_client *dc = container_of(cl, struct demo_client, cl); + if (dc->async) { + pr_info("AAAAsync"); + } else { + pr_info("SSSSSSSync"); + } +} + +static void sample_sent(struct mbox_client *cl, void *msg, int r) +{ + struct demo_client *dc = container_of(cl, struct demo_client, cl); + complete(&dc->c); +} + +int mailbox_test(void) +{ + struct demo_client *dc_sync; + struct platform_device *pdev = get_consys_device(); + + dc_sync = kzalloc(sizeof(*dc_sync), GFP_KERNEL); + dc_sync->cl.dev = &pdev->dev; + dc_sync->cl.rx_callback = message_from_remote; + dc_sync->cl.tx_done = sample_sent; + dc_sync->cl.tx_block = true; + dc_sync->cl.tx_tout = 500; + dc_sync->cl.knows_txdone = false; + dc_sync->async = false; + + dc_sync->mbox = mbox_request_channel(&dc_sync->cl, 0); + + if (IS_ERR(dc_sync->mbox)) { + pr_err("request channel fail [%d]", dc_sync->mbox); + return -1; + } + mbox_send_message(dc_sync->mbox, 0); + + wait_for_completion(&dc_sync->c); + + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/conninfra/test/msg_evt_test.c b/drivers/misc/mediatek/connectivity/conninfra/test/msg_evt_test.c new file mode 100644 index 0000000000000..6efd310a3362e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/test/msg_evt_test.c @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#define pr_fmt(fmt) "msg_evt_test@(%s:%d) " fmt, __func__, __LINE__ + +#include +#include +#include +#include "msg_thread.h" +#include "msg_evt_test.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 +******************************************************************************** +*/ + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +struct work_struct rst_worker; +struct msg_thread_ctx g_ctx; + +typedef enum { + INFRA_TEST_OPID_1 = 0, + INFRA_TEST_OPID_2 = 1, + INFRA_TEST_OPID_MAX +} test_opid; + + +static int opfunc_test_1(struct msg_op_data *op); +static int opfunc_test_2(struct msg_op_data *op); + +static const msg_opid_func test_op_func[] = { + [INFRA_TEST_OPID_1] = opfunc_test_1, + [INFRA_TEST_OPID_2] = opfunc_test_2, +}; + +int opfunc_test_1(struct msg_op_data *op) +{ + pr_info("[%s]", __func__); + return 0; +} + +int opfunc_test_2(struct msg_op_data *op) +{ + unsigned int drv_type = op->op_data[0]; + + pr_info("[%s] param=[%d]", __func__, drv_type); + return 0; +} + + +static void msg_thrd_handler(struct work_struct *work) +{ + msg_thread_send_1(&g_ctx, INFRA_TEST_OPID_2, 2011); + osal_sleep_ms(5); + msg_thread_send_wait_1(&g_ctx, INFRA_TEST_OPID_2, 0, 2022); + msg_thread_send_wait_1(&g_ctx, INFRA_TEST_OPID_2, 0, 2033); +} + +int msg_evt_test(void) +{ + int ret; + + INIT_WORK(&rst_worker, msg_thrd_handler); + + ret = msg_thread_init(&g_ctx, "TestThread", + test_op_func, INFRA_TEST_OPID_MAX); + if (ret) { + pr_err("inti msg_thread fail ret=[%d]\n", ret); + return -2; + } + + schedule_work(&rst_worker); + + msg_thread_send_wait_1(&g_ctx, INFRA_TEST_OPID_2, 0, 1011); + //osal_sleep_ms(10); + msg_thread_send_1(&g_ctx, INFRA_TEST_OPID_2, 1022); + osal_sleep_ms(10); + msg_thread_send_wait_1(&g_ctx, INFRA_TEST_OPID_2, 0, 1033); + + osal_sleep_ms(1000); + + pr_info("<<<<<>>>>>>> freeOpq=[%u][%u] ActiveQ=[%u][%u]", + g_ctx.free_op_q.write, g_ctx.free_op_q.read, + g_ctx.active_op_q.write, g_ctx.active_op_q.read); + osal_sleep_ms(500); + + ret = msg_thread_deinit(&g_ctx); + pr_info("[%s] msg_thread_deinit\n", __func__); + + pr_info("[%s] test PASS\n", __func__); + return 0; +} + + From 258eeb7f8cb80cba599270ee094f3c6ed038508c Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 21:43:47 +0800 Subject: [PATCH 09/32] Add files via upload --- .../mediatek/connectivity/conninfra/NOTICE | 202 ++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 drivers/misc/mediatek/connectivity/conninfra/NOTICE diff --git a/drivers/misc/mediatek/connectivity/conninfra/NOTICE b/drivers/misc/mediatek/connectivity/conninfra/NOTICE new file mode 100644 index 0000000000000..52c1cace2c1dd --- /dev/null +++ b/drivers/misc/mediatek/connectivity/conninfra/NOTICE @@ -0,0 +1,202 @@ +The GNU General Public License (GPL) + +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +Preamble + +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU +General Public License is intended to guarantee your freedom to share and change free software--to make sure the +software is free for all its users. This General Public License applies to most of the Free Software Foundation's +software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is +covered by the GNU Library General Public License instead.) You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make +sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you +receive source code or can get it if you want it, that you can change the software or use pieces of it in new free +programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to +surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the +software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all +the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them +these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty +for this free software. If the software is modified by someone else and passed on, we want its recipients to know that +what they have is not the original, so that any problems introduced by others will not reflect on the original authors' +reputations. + +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors +of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, +we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it +may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or +work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to +say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into +another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is +addressed as "you". + +Activities other than copying, distribution and modification are not covered by this License; they are outside its +scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents +constitute a work based on the Program (independent of having been made by running the Program). Whether that is true +depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided +that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of +warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other +recipients of the Program a copy of this License along with the Program. + +You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection +in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and +copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of +these conditions: + +a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any +change. + +b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the +Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this +License. + +c) If the modified program normally reads commands interactively when run, you must cause it, when started running for +such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright +notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may +redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if +the Program itself is interactive but does not normally print such an announcement, your work based on the Program is +not required to print an announcement.) + +These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the +Program, and can be reasonably considered independent and separate works in themselves, then this License, and its +terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same +sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part +regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; +rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the +Program. + +In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the +Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + +3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you also do one of the following: + +a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms +of Sections 1 and 2 above on a medium customarily used for software interchange; or, + +b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than +your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source +code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; +or, + +c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This +alternative is allowed only for noncommercial distribution and only if you received the program in object code or +executable form with such an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for making modifications to it. For an executable work, +complete source code means all the source code for all modules it contains, plus any associated interface definition +files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, +the source code distributed need not include anything that is normally distributed (in either source or binary form) +with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless +that component itself accompanies the executable. + +If distribution of executable or object code is made by offering access to copy from a designated place, then offering +equivalent access to copy the source code from the same place counts as distribution of the source code, even though +third parties are not compelled to copy the source along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your +rights under this License. However, parties who have received copies, or rights, from you under this License will not +have their licenses terminated so long as such parties remain in full compliance. + +5. You are not required to accept this License, since you have not signed it. However, nothing else grants you +permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do +not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you +indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or +modifying the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a +license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You +may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not +responsible for enforcing compliance by third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to +patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the +conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as +to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence +you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution +of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy +both it and this License would be to refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the +section is intended to apply and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest +validity of any such claims; this section has the sole purpose of protecting the integrity of the free software +distribution system, which is implemented by public license practices. Many people have made generous contributions to +the wide range of software distributed through that system in reliance on consistent application of that system; it is +up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee +cannot impose that choice. + +This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted +interfaces, the original copyright holder who places the Program under this License may add an explicit geographical +distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if written in the body of this License. + +9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. +Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or +concerns. + +Each version is given a distinguishing version number. If the Program specifies a version number of this License which +applies to it and "any later version", you have the option of following the terms and conditions either of that version +or of any later version published by the Free Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are +different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, +write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two +goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of +software generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM +"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR +CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY +WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, +SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT +LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF +THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY +OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS + + + + From a7a008fe2f652e9308c8db259048b96790819618 Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 21:45:52 +0800 Subject: [PATCH 10/32] Add files via upload --- .../mediatek/connectivity/fmradio/Android.mk | 28 + .../mediatek/connectivity/fmradio/Makefile | 165 + .../misc/mediatek/connectivity/fmradio/README | 2 + .../fmradio/chips/mt6627/inc/mt6627_drv_dsp.h | 27 + .../fmradio/chips/mt6627/inc/mt6627_fm_lib.h | 69 + .../fmradio/chips/mt6627/inc/mt6627_fm_reg.h | 58 + .../fmradio/chips/mt6627/pub/mt6627_fm_lib.c | 1841 +++++++++++ .../fmradio/chips/mt6627/pub/mt6627_fm_rds.c | 334 ++ .../fmradio/chips/mt6630/inc/mt6630_fm_lib.h | 69 + .../fmradio/chips/mt6630/inc/mt6630_fm_reg.h | 58 + .../fmradio/chips/mt6630/pub/mt6630_fm_lib.c | 2471 ++++++++++++++ .../fmradio/chips/mt6630/pub/mt6630_fm_rds.c | 368 +++ .../fmradio/chips/mt6631/inc/mt6631_fm_lib.h | 73 + .../fmradio/chips/mt6631/inc/mt6631_fm_reg.h | 57 + .../fmradio/chips/mt6631/pub/mt6631_fm_lib.c | 2293 +++++++++++++ .../fmradio/chips/mt6631/pub/mt6631_fm_rds.c | 335 ++ .../fmradio/chips/mt6632/inc/mt6632_fm_lib.h | 69 + .../fmradio/chips/mt6632/inc/mt6632_fm_reg.h | 58 + .../fmradio/chips/mt6632/pub/mt6632_fm_lib.c | 1793 +++++++++++ .../fmradio/chips/mt6632/pub/mt6632_fm_rds.c | 329 ++ .../fmradio/chips/mt6635/inc/mt6635_fm_lib.h | 73 + .../fmradio/chips/mt6635/inc/mt6635_fm_reg.h | 57 + .../chips/mt6635/pub/mt6635_2_fm_lib.c | 1966 +++++++++++ .../fmradio/chips/mt6635/pub/mt6635_fm_lib.c | 2109 ++++++++++++ .../fmradio/chips/mt6635/pub/mt6635_fm_rds.c | 335 ++ .../fmradio/chips/soc/inc/soc_drv_dsp.h | 27 + .../fmradio/chips/soc/inc/soc_fm_lib.h | 69 + .../fmradio/chips/soc/inc/soc_fm_reg.h | 63 + .../fmradio/chips/soc/pub/soc_fm_lib.c | 1841 +++++++++++ .../fmradio/chips/soc/pub/soc_fm_rds.c | 334 ++ .../connectivity/fmradio/core/fm_cmd.c | 842 +++++ .../connectivity/fmradio/core/fm_config.c | 625 ++++ .../connectivity/fmradio/core/fm_eint.c | 54 + .../connectivity/fmradio/core/fm_link.c | 570 ++++ .../connectivity/fmradio/core/fm_main.c | 2867 +++++++++++++++++ .../connectivity/fmradio/core/fm_module.c | 1607 +++++++++ .../connectivity/fmradio/core/fm_patch.c | 99 + .../connectivity/fmradio/core/fm_rds_parser.c | 2004 ++++++++++++ .../connectivity/fmradio/core/fm_reg_utils.c | 111 + .../connectivity/fmradio/core/fm_utils.c | 808 +++++ .../mediatek/connectivity/fmradio/dummy.c | 16 + .../connectivity/fmradio/inc/fm_cmd.h | 96 + .../connectivity/fmradio/inc/fm_config.h | 186 ++ .../connectivity/fmradio/inc/fm_dbg.h | 134 + .../connectivity/fmradio/inc/fm_eint.h | 30 + .../connectivity/fmradio/inc/fm_err.h | 36 + .../connectivity/fmradio/inc/fm_ext_api.h | 55 + .../connectivity/fmradio/inc/fm_interface.h | 287 ++ .../connectivity/fmradio/inc/fm_ioctl.h | 107 + .../connectivity/fmradio/inc/fm_link.h | 247 ++ .../connectivity/fmradio/inc/fm_main.h | 406 +++ .../connectivity/fmradio/inc/fm_patch.h | 47 + .../connectivity/fmradio/inc/fm_rds.h | 230 ++ .../connectivity/fmradio/inc/fm_reg_utils.h | 394 +++ .../connectivity/fmradio/inc/fm_stdlib.h | 74 + .../connectivity/fmradio/inc/fm_typedef.h | 18 + .../connectivity/fmradio/inc/fm_utils.h | 342 ++ .../connectivity/fmradio/init.fmradio_drv.rc | 5 + .../connectivity/fmradio/plat/conn_infra.c | 1505 +++++++++ .../connectivity/fmradio/plat/inc/plat.h | 96 + .../connectivity/fmradio/plat/legacy_wmt.c | 423 +++ 61 files changed, 31692 insertions(+) create mode 100644 drivers/misc/mediatek/connectivity/fmradio/Android.mk create mode 100644 drivers/misc/mediatek/connectivity/fmradio/Makefile create mode 100644 drivers/misc/mediatek/connectivity/fmradio/README create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/mt6627/inc/mt6627_drv_dsp.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/mt6627/inc/mt6627_fm_lib.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/mt6627/inc/mt6627_fm_reg.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/mt6627/pub/mt6627_fm_lib.c create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/mt6627/pub/mt6627_fm_rds.c create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/mt6630/inc/mt6630_fm_lib.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/mt6630/inc/mt6630_fm_reg.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/mt6630/pub/mt6630_fm_lib.c create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/mt6630/pub/mt6630_fm_rds.c create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/mt6631/inc/mt6631_fm_lib.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/mt6631/inc/mt6631_fm_reg.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/mt6631/pub/mt6631_fm_lib.c create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/mt6631/pub/mt6631_fm_rds.c create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/mt6632/inc/mt6632_fm_lib.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/mt6632/inc/mt6632_fm_reg.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/mt6632/pub/mt6632_fm_lib.c create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/mt6632/pub/mt6632_fm_rds.c create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/mt6635/inc/mt6635_fm_lib.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/mt6635/inc/mt6635_fm_reg.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/mt6635/pub/mt6635_2_fm_lib.c create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/mt6635/pub/mt6635_fm_lib.c create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/mt6635/pub/mt6635_fm_rds.c create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/soc/inc/soc_drv_dsp.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/soc/inc/soc_fm_lib.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/soc/inc/soc_fm_reg.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/soc/pub/soc_fm_lib.c create mode 100644 drivers/misc/mediatek/connectivity/fmradio/chips/soc/pub/soc_fm_rds.c create mode 100644 drivers/misc/mediatek/connectivity/fmradio/core/fm_cmd.c create mode 100644 drivers/misc/mediatek/connectivity/fmradio/core/fm_config.c create mode 100644 drivers/misc/mediatek/connectivity/fmradio/core/fm_eint.c create mode 100644 drivers/misc/mediatek/connectivity/fmradio/core/fm_link.c create mode 100644 drivers/misc/mediatek/connectivity/fmradio/core/fm_main.c create mode 100644 drivers/misc/mediatek/connectivity/fmradio/core/fm_module.c create mode 100644 drivers/misc/mediatek/connectivity/fmradio/core/fm_patch.c create mode 100644 drivers/misc/mediatek/connectivity/fmradio/core/fm_rds_parser.c create mode 100644 drivers/misc/mediatek/connectivity/fmradio/core/fm_reg_utils.c create mode 100644 drivers/misc/mediatek/connectivity/fmradio/core/fm_utils.c create mode 100644 drivers/misc/mediatek/connectivity/fmradio/dummy.c create mode 100644 drivers/misc/mediatek/connectivity/fmradio/inc/fm_cmd.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/inc/fm_config.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/inc/fm_dbg.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/inc/fm_eint.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/inc/fm_err.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/inc/fm_ext_api.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/inc/fm_interface.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/inc/fm_ioctl.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/inc/fm_link.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/inc/fm_main.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/inc/fm_patch.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/inc/fm_rds.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/inc/fm_reg_utils.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/inc/fm_stdlib.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/inc/fm_typedef.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/inc/fm_utils.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/init.fmradio_drv.rc create mode 100644 drivers/misc/mediatek/connectivity/fmradio/plat/conn_infra.c create mode 100644 drivers/misc/mediatek/connectivity/fmradio/plat/inc/plat.h create mode 100644 drivers/misc/mediatek/connectivity/fmradio/plat/legacy_wmt.c diff --git a/drivers/misc/mediatek/connectivity/fmradio/Android.mk b/drivers/misc/mediatek/connectivity/fmradio/Android.mk new file mode 100644 index 0000000000000..75ba06df12224 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/Android.mk @@ -0,0 +1,28 @@ +LOCAL_PATH := $(call my-dir) + +ifeq ($(MTK_FM_SUPPORT),yes) + +include $(CLEAR_VARS) +LOCAL_MODULE := fmradio_drv.ko +LOCAL_PROPRIETARY_MODULE := true +LOCAL_MODULE_OWNER := mtk +LOCAL_INIT_RC := init.fmradio_drv.rc +ifeq ($(BUILD_CONNAC2), true) +LOCAL_REQUIRED_MODULES := conninfra.ko +else +LOCAL_REQUIRED_MODULES := wmt_drv.ko +endif + +ifeq ($(TARGET_BUILD_VARIANT),user) +FM_OPTS := CONFIG_FM_USER_LOAD=1 +else +FM_OPTS := +endif + +FM_OPTS += CFG_BUILD_CONNAC2=$(BUILD_CONNAC2) CFG_FM_CHIP_ID=$(FM_CHIP_ID) CFG_FM_CHIP=$(FM_CHIP) + +include $(MTK_KERNEL_MODULE) + +$(linked_module): OPTS += $(FM_OPTS) + +endif diff --git a/drivers/misc/mediatek/connectivity/fmradio/Makefile b/drivers/misc/mediatek/connectivity/fmradio/Makefile new file mode 100644 index 0000000000000..af37a4e06e42a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/Makefile @@ -0,0 +1,165 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# + +############################################################################### +# Necessary Check + +ifneq ($(KERNEL_OUT),) + ccflags-y += -imacros $(KERNEL_OUT)/include/generated/autoconf.h +endif + +ifndef TOP + TOP := $(srctree)/.. +endif + +# Force build fail on modpost warning +KBUILD_MODPOST_FAIL_ON_WARNINGS := y +############################################################################### + +MTK_PLATFORM := $(subst ",,$(CONFIG_MTK_PLATFORM)) + +# only WMT align this design flow +#ccflags-y += -D MTK_WCN_REMOVE_KERNEL_MODULE + +ifeq ($(CONFIG_ARM64), y) + ccflags-y += -D CONFIG_MTK_WCN_ARM64 +endif + +ifeq ($(CONFIG_MTK_CONN_LTE_IDC_SUPPORT),y) + ccflags-y += -D WMT_IDC_SUPPORT=1 +else + ccflags-y += -D WMT_IDC_SUPPORT=0 +endif +ccflags-y += -D MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include + +ifeq ($(CONFIG_FM_USER_LOAD),1) + ccflags-y += -D CONFIG_MTK_USER_BUILD +endif + +# Makefile generated by Mediatek +# fm support + +ifneq ($(CONFIG_MTK_FMRADIO),) + +MODULE_NAME := fmradio_drv +obj-m += $(MODULE_NAME).o + +ifeq ($(CFG_FM_CHIP),) + FM_CHIP := mt6631_6635 + + ccflags-y += -I$(src)/chips/mt6631/inc -I$(src)/chips/mt6635/inc + + $(FM_CHIP)-objs += chips/mt6631/pub/mt6631_fm_rds.o + $(FM_CHIP)-objs += chips/mt6635/pub/mt6635_fm_rds.o + $(FM_CHIP)-objs += chips/mt6631/pub/mt6631_fm_lib.o + $(FM_CHIP)-objs += chips/mt6635/pub/mt6635_fm_lib.o + +else + +ifeq ($(CONFIG_MTK_FM_CHIP),) + $(error CONFIG_MTK_FM_CHIP not defined) +endif + +ifneq ($(CFG_FM_CHIP_ID),) + ccflags-y += -D CFG_FM_CHIP_ID=0x$(CFG_FM_CHIP_ID) +endif + + FM_CHIP_MACRO := $(subst ",,$(CONFIG_MTK_FM_CHIP)) + FM_CHIP := $(subst _FM,,$(subst MT,mt,$(subst ",,$(CONFIG_MTK_FM_CHIP)))) + +ifeq ($(FM_CHIP), mt6625) + FM_CHIP := mt6627 + ccflags-y += -DMT6625_FM +endif + +ifeq ($(FM_CHIP), mt6627) + FM_CHIP := mt6627 + ccflags-y += -DMT6627_FM +endif + +ifeq ($(FM_CHIP), mt6580) + FM_CHIP := soc + ccflags-y += -Dsoc +endif + +ifeq ($(FM_CHIP), mt0633) + FM_CHIP := soc + ccflags-y += -Dsoc +endif + +ifeq ($(FM_CHIP), mt6630) + ccflags-y += -DMT6630_FM +endif + +ifeq ($(FM_CHIP), mt6632) + ccflags-y += -DMT6632_FM +endif + +ifeq ($(FM_CHIP), mt6631) + ccflags-y += -DMT6631_FM +endif + +ifeq ($(FM_CHIP), mt6635) + ccflags-y += -DMT6635_FM +endif + + FM_CHIP_PATH := $(FM_CHIP)/pub/$(FM_CHIP) + ccflags-y += -I$(src)/chips/$(FM_CHIP)/inc + + $(FM_CHIP)-objs += chips/$(FM_CHIP_PATH)_fm_rds.o +ifneq ($(CFG_BUILD_CONNAC2), true) + $(FM_CHIP)-objs += chips/$(FM_CHIP_PATH)_fm_lib.o +endif +endif + + +ccflags-y += -I$(src)/inc \ + -I$(src)/plat/inc + +$(FM_CHIP)-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 \ + core/fm_cmd.o \ + core/fm_reg_utils.o + +ifeq ($(CFG_BUILD_CONNAC2), true) + CONNINFRA_SRC_FOLDER := $(TOP)/vendor/mediatek/kernel_modules/connectivity/conninfra + + ccflags-y += -I$(CONNINFRA_SRC_FOLDER)/include + ccflags-y += -DCFG_FM_CONNAC2=1 + $(FM_CHIP)-objs += chips/mt6635/pub/mt6635_2_fm_lib.o + $(FM_CHIP)-objs += plat/conn_infra.o +else + WMT_SRC_FOLDER := $(TOP)/vendor/mediatek/kernel_modules/connectivity/common + WMT_INCLUDE_PATH := common_main + + ccflags-y += -I$(WMT_SRC_FOLDER)/$(WMT_INCLUDE_PATH)/include \ + -I$(WMT_SRC_FOLDER)/$(WMT_INCLUDE_PATH)/linux/include + ccflags-y += -DCFG_FM_CONNAC2=0 + $(FM_CHIP)-objs += plat/legacy_wmt.o +endif + + $(MODULE_NAME)-objs += $($(FM_CHIP)-objs) + #obj-$(CONFIG_MTK_FMRADIO) += private/ +endif + +obj-y += dummy.o diff --git a/drivers/misc/mediatek/connectivity/fmradio/README b/drivers/misc/mediatek/connectivity/fmradio/README new file mode 100644 index 0000000000000..d8eef677c95ca --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/README @@ -0,0 +1,2 @@ +FM Radio driver - kernel modules move out of kernel tree + diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/mt6627/inc/mt6627_drv_dsp.h b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6627/inc/mt6627_drv_dsp.h new file mode 100644 index 0000000000000..957a869719bc3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6627/inc/mt6627_drv_dsp.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +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 +}; diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/mt6627/inc/mt6627_fm_lib.h b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6627/inc/mt6627_fm_lib.h new file mode 100644 index 0000000000000..f62c130f8b1a2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6627/inc/mt6627_fm_lib.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __MT6627_FM_LIB_H__ +#define __MT6627_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 { + mt6627_E1 = 0, + mt6627_E2 +}; + +struct mt6627_fm_cqi { + unsigned short ch; + unsigned short rssi; + unsigned short reserve; +}; + +struct adapt_fm_cqi { + signed int ch; + signed int rssi; + signed int reserve; +}; + +struct mt6627_full_cqi { + unsigned short ch; + unsigned short rssi; + unsigned short pamd; + unsigned short pr; + unsigned short fpamd; + unsigned short mr; + unsigned short atdc; + unsigned short prx; + unsigned short atdev; + unsigned short smg; /* soft-mute gain */ + unsigned short drssi; /* delta rssi */ +}; + +#endif diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/mt6627/inc/mt6627_fm_reg.h b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6627/inc/mt6627_fm_reg.h new file mode 100644 index 0000000000000..ba7a71d8565bf --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6627/inc/mt6627_fm_reg.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __MT6627_FM_REG_H__ +#define __MT6627_FM_REG_H__ + +/* 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, +}; + +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 /* __MT6627_FM_REG_H__ */ diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/mt6627/pub/mt6627_fm_lib.c b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6627/pub/mt6627_fm_lib.c new file mode 100644 index 0000000000000..b919fcfac956c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6627/pub/mt6627_fm_lib.c @@ -0,0 +1,1841 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#include "osal_typedef.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_cmd.h" + +#include "mt6627_fm_reg.h" +#include "mt6627_fm_lib.h" + +/* #include "mach/mt_gpio.h" */ + +/* #define MT6627_FM_PATCH_PATH "/etc/firmware/mt6627/mt6627_fm_patch.bin" */ +/* #define MT6627_FM_COEFF_PATH "/etc/firmware/mt6627/mt6627_fm_coeff.bin" */ +/* #define MT6627_FM_HWCOEFF_PATH "/etc/firmware/mt6627/mt6627_fm_hwcoeff.bin" */ +/* #define MT6627_FM_ROM_PATH "/etc/firmware/mt6627/mt6627_fm_rom.bin" */ + +static struct fm_patch_tbl mt6627_patch_tbl[5] = { + {FM_ROM_V1, "mt6627_fm_v1_patch.bin", "mt6627_fm_v1_coeff.bin", NULL, NULL}, + {FM_ROM_V2, "mt6627_fm_v2_patch.bin", "mt6627_fm_v2_coeff.bin", NULL, NULL}, + {FM_ROM_V3, "mt6627_fm_v3_patch.bin", "mt6627_fm_v3_coeff.bin", NULL, NULL}, + {FM_ROM_V4, "mt6627_fm_v4_patch.bin", "mt6627_fm_v4_coeff.bin", NULL, NULL}, + {FM_ROM_V5, "mt6627_fm_v5_patch.bin", "mt6627_fm_v5_coeff.bin", NULL, NULL} +}; + +static struct fm_hw_info mt6627_hw_info = { + .chip_id = 0x00006627, + .eco_ver = 0x00000000, + .rom_ver = 0x00000000, + .patch_ver = 0x00000000, + .reserve = 0x00000000, +}; + +static struct fm_callback *fm_cb_op; +/* static signed int Chip_Version = mt6627_E1; */ + +/* static bool rssi_th_set = false; */ + +#if 0 /* def CONFIG_MTK_FM_50KHZ_SUPPORT */ +static struct fm_fifo *cqi_fifo; +#endif +static signed int mt6627_is_dese_chan(unsigned short freq); +static bool mt6627_I2S_hopping_check(unsigned short freq); + +#if 0 +static signed int mt6627_mcu_dese(unsigned short freq, void *arg); +static signed int mt6627_gps_dese(unsigned short freq, void *arg); +static signed int mt6627_I2s_Setting(signed int onoff, signed int mode, signed int sample); +#endif +static unsigned short mt6627_chan_para_get(unsigned short freq); +static signed int mt6627_desense_check(unsigned short freq, signed int rssi); +static bool mt6627_TDD_chan_check(unsigned short freq); +static signed int mt6627_soft_mute_tune(unsigned short freq, signed int *rssi, signed int *valid); +static signed int mt6627_pwron(signed int data) +{ + if (mtk_wcn_wmt_func_on(WMTDRV_TYPE_FM) == MTK_WCN_BOOL_FALSE) { + WCN_DBG(FM_ERR | CHIP, "WMT turn on FM Fail!\n"); + return -FM_ELINK; + } + + WCN_DBG(FM_NTC | CHIP, "WMT turn on FM OK!\n"); + return 0; +} + +static signed int mt6627_pwroff(signed int data) +{ + if (mtk_wcn_wmt_func_off(WMTDRV_TYPE_FM) == MTK_WCN_BOOL_FALSE) { + WCN_DBG(FM_ERR | CHIP, "WMT turn off FM Fail!\n"); + return -FM_ELINK; + } + + WCN_DBG(FM_NTC | CHIP, "WMT turn off FM OK!\n"); + return 0; +} + +#if 0 +static signed int mt6627_top_set_bits(unsigned short addr, unsigned int bits, unsigned int mask) +{ + signed int ret = 0; + unsigned int val; + + ret = fm_top_reg_read(addr, &val); + + if (ret) + return ret; + + val = ((val & (mask)) | bits); + ret = fm_top_reg_write(addr, val); + + return ret; +} +#endif + +#if 0 +static signed int mt6627_DSP_write(unsigned short addr, unsigned short val) +{ + fm_reg_write(0xE2, addr); + fm_reg_write(0xE3, val); + fm_reg_write(0xE1, 0x0002); + return 0; +} +static signed int mt6627_DSP_read(unsigned short addr, unsigned short *val) +{ + signed int ret = -1; + + fm_reg_write(0xE2, addr); + fm_reg_write(0xE1, 0x0001); + ret = fm_reg_read(0xE4, val); + return ret; +} +#endif + +static unsigned short mt6627_get_chipid(void) +{ + return 0x6627; +} + +/* MT6627_SetAntennaType - set Antenna type + * @type - 1,Short Antenna; 0, Long Antenna + */ +static signed int mt6627_SetAntennaType(signed int type) +{ + unsigned short dataRead = 0; + + WCN_DBG(FM_DBG | CHIP, "set ana to %s\n", type ? "short" : "long"); + fm_reg_read(FM_MAIN_CG2_CTRL, &dataRead); + + if (type) + dataRead |= ANTENNA_TYPE; + else + dataRead &= (~ANTENNA_TYPE); + + fm_reg_write(FM_MAIN_CG2_CTRL, dataRead); + + return 0; +} + +static signed int mt6627_GetAntennaType(void) +{ + unsigned short dataRead = 0; + + fm_reg_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 signed int mt6627_Mute(bool mute) +{ + signed int ret = 0; + unsigned short dataRead = 0; + + WCN_DBG(FM_DBG | CHIP, "set %s\n", mute ? "mute" : "unmute"); + /* fm_reg_read(FM_MAIN_CTRL, &dataRead); */ + fm_reg_read(0x9C, &dataRead); + + /* fm_top_reg_write(0x0050,0x00000007); */ + if (mute == 1) + ret = fm_reg_write(0x9C, (dataRead & 0xFFFC) | 0x0003); + else + ret = fm_reg_write(0x9C, (dataRead & 0xFFFC)); + + /* fm_top_reg_write(0x0050,0x0000000F); */ + + return ret; +} + +#if 0 +static signed int mt6627_set_RSSITh(unsigned short TH_long, unsigned short TH_short) +{ + fm_reg_write(0xE2, 0x3072); + fm_reg_write(0xE3, TH_long); + fm_reg_write(0xE1, 0x0002); + + fm_delayms(1); + fm_reg_write(0xE2, 0x307A); + fm_reg_write(0xE3, TH_short); + fm_reg_write(0xE1, 0x0002); + + WCN_DBG(FM_DBG | CHIP, "RSSI TH, long:0x%04x, short:0x%04x", TH_long, TH_short); + return 0; +} + +static signed int mt6627_set_SMGTh(signed int ver, unsigned short TH_smg) +{ + if (mt6627_E1 == ver) { + fm_reg_write(0xE2, 0x321E); + fm_reg_write(0xE3, TH_smg); + fm_reg_write(0xE1, 0x0002); + } else { + fm_reg_write(0xE2, 0x3218); + fm_reg_write(0xE3, TH_smg); + fm_reg_write(0xE1, 0x0002); + } + + WCN_DBG(FM_DBG | CHIP, "Soft-mute gain TH %d\n", (int)TH_smg); + return 0; +} +#endif + +static signed int mt6627_pwrup_clock_on_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + unsigned short de_emphasis; + /* unsigned short osc_freq; */ + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + de_emphasis = fm_config.rx_cfg.deemphasis; + de_emphasis &= 0x0001; /* rang 0~1 */ + + /* 2,turn on top clock */ + pkt_size += fm_bop_top_write(0xA10, 0xFFFFFFFF, &buf[pkt_size], buf_size - pkt_size); /* wr a10 ffffffff */ + /* 3,enable MTCMOS */ + pkt_size += fm_bop_top_write(0x60, 0x00000030, &buf[pkt_size], buf_size - pkt_size); /* wr 60 30 */ + pkt_size += fm_bop_top_write(0x60, 0x00000035, &buf[pkt_size], buf_size - pkt_size); /* wr 60 35 */ + pkt_size += fm_bop_top_rd_until(0x60, 0x0000000A, 0xA, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_top_write(0x60, 0x00000015, &buf[pkt_size], buf_size - pkt_size); /* wr 60 15 */ + pkt_size += fm_bop_top_write(0x60, 0x00000005, &buf[pkt_size], buf_size - pkt_size); /* wr 60 5 */ + pkt_size += fm_bop_udelay(10, &buf[pkt_size], buf_size - pkt_size); /* delay 10us */ + pkt_size += fm_bop_top_write(0x60, 0x00000045, &buf[pkt_size], buf_size - pkt_size); /* wr 60 45 */ + /* 4,set CSPI fm slave dummy count */ + pkt_size += fm_bop_top_write(0x68, 0x0000003F, &buf[pkt_size], buf_size - pkt_size); /* wr 68 3F */ + + /* a1 enable digital OSC */ + pkt_size += fm_bop_top_write(0x50, 0x00000001, &buf[pkt_size], buf_size - pkt_size); /* wr 50 1 */ + pkt_size += fm_bop_udelay(3000, &buf[pkt_size], buf_size - pkt_size); /* delay 3ms */ + /* a3 set OSC clock output to fm */ + pkt_size += fm_bop_top_write(0x50, 0x00000003, &buf[pkt_size], buf_size - pkt_size); /* wr 50 3 */ + /* a4 release HW clock gating */ + pkt_size += fm_bop_top_write(0x50, 0x00000007, &buf[pkt_size], buf_size - pkt_size); /* wr 50 7 */ + /* set I2S current driving */ + pkt_size += fm_bop_top_write(0x000, 0x00000000, &buf[pkt_size], buf_size - pkt_size); /* wr 0 0 */ + /* a5 enable DSP auto clock gating */ + pkt_size += fm_bop_write(0x70, 0x0040, &buf[pkt_size], buf_size - pkt_size); /* wr 70 0040 */ + /* a7 deemphasis setting */ + 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); */ + + return pkt_size - 4; +} +/* + * mt6627_pwrup_clock_on - Wholechip FM Power Up: step 1, FM Digital Clock enable + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6627_pwrup_clock_on(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6627_pwrup_clock_on_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +static signed int mt6627_pwrup_digital_init_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* FM RF&ADPLL divider setting */ + /* D2.1 set cell mode */ + /* wr 30 D3:D2 00:FDD(default),01:both.10: TDD, 11 FDD */ + /* pkt_size += fm_bop_modify(0x30, 0xFFF3, 0x0000, &buf[pkt_size], buf_size - pkt_size); */ + /* D2.2 set ADPLL divider */ + pkt_size += fm_bop_write(0x21, 0xE000, &buf[pkt_size], buf_size - pkt_size); /* wr 21 E000 */ + /* D2.3 set SDM coeff0_H */ + pkt_size += fm_bop_write(0xD8, 0x03F0, &buf[pkt_size], buf_size - pkt_size); /* wr D8 0x03F0 */ + /* D2.4 set SDM coeff0_L */ + pkt_size += fm_bop_write(0xD9, 0x3F04, &buf[pkt_size], buf_size - pkt_size); /* wr D9 0x3F04 */ + /* D2.5 set SDM coeff1_H */ + pkt_size += fm_bop_write(0xDA, 0x0014, &buf[pkt_size], buf_size - pkt_size); /* wr DA 0x0014 */ + /* D2.6 set SDM coeff1_L */ + pkt_size += fm_bop_write(0xDB, 0x2A38, &buf[pkt_size], buf_size - pkt_size); /* wr DB 0x2A38 */ + /* D2.7 set 26M clock */ + pkt_size += fm_bop_write(0x23, 0x4000, &buf[pkt_size], buf_size - pkt_size); /* wr 23 4000 */ + + /* FM Digital Init: fm_rgf_maincon */ + /* E4 */ + pkt_size += fm_bop_write(0x6A, 0x0021, &buf[pkt_size], buf_size - pkt_size); /* wr 6A 0021 */ + pkt_size += fm_bop_write(0x6B, 0x0021, &buf[pkt_size], buf_size - pkt_size); /* wr 6B 0021 */ + /* E5 */ + pkt_size += fm_bop_top_write(0x50, 0x0000000F, &buf[pkt_size], buf_size - pkt_size); /* wr 50 f */ + /* E6 */ + pkt_size += fm_bop_modify(0x61, 0xFFFD, 0x0002, &buf[pkt_size], buf_size - pkt_size); /* wr 61 D1=1 */ + /* E7 */ + pkt_size += fm_bop_modify(0x61, 0xFFFE, 0x0000, &buf[pkt_size], buf_size - pkt_size); /* wr 61 D0=0 */ + /* E8 */ + pkt_size += fm_bop_udelay(100000, &buf[pkt_size], buf_size - pkt_size); /* delay 100ms */ + /* E9 */ + pkt_size += fm_bop_rd_until(0x64, 0x001F, 0x0002, &buf[pkt_size], buf_size - pkt_size); /* Poll 64[0~4] = 2 */ + + return pkt_size - 4; +} + +/* + * mt6627_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 + */ +static signed int mt6627_pwrup_digital_init(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6627_pwrup_digital_init_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +static signed int mt6627_pwrup_fine_tune_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* F1 set host control RF register */ + pkt_size += fm_bop_top_write(0x50, 0x00000007, &buf[pkt_size], buf_size - pkt_size); + /* F2 fine tune RF setting */ + pkt_size += fm_bop_write(0x01, 0xBEE8, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x03, 0xF6ED, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x15, 0x0D80, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x16, 0x0068, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x17, 0x092A, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x34, 0x807F, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x35, 0x311E, &buf[pkt_size], buf_size - pkt_size); + /* F1 set DSP control RF register */ + pkt_size += fm_bop_top_write(0x50, 0x0000000F, &buf[pkt_size], buf_size - pkt_size); + + return pkt_size - 4; +} + +/* + * mt6627_pwrup_fine_tune - Wholechip FM Power Up: step 5, FM RF fine tune setting + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6627_pwrup_fine_tune(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6627_pwrup_fine_tune_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +static signed int mt6627_pwrdown_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* A1:set audio output I2S Tx mode: */ + pkt_size += fm_bop_modify(0x9B, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size); + + /* B0:Disable HW clock control */ + pkt_size += fm_bop_top_write(0x50, 0x330F, &buf[pkt_size], buf_size - pkt_size); + /* B1:Reset ASIP */ + pkt_size += fm_bop_write(0x61, 0x0001, &buf[pkt_size], buf_size - pkt_size); + /* B2:digital core + digital rgf reset */ + pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size); + /* B3:Disable all clock */ + pkt_size += fm_bop_top_write(0x50, 0x0000, &buf[pkt_size], buf_size - pkt_size); + /* B4:Reset rgfrf */ + pkt_size += fm_bop_top_write(0x50, 0x4000, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_top_write(0x50, 0x0000, &buf[pkt_size], buf_size - pkt_size); + /* MTCMOS power off */ + /* C0:disable MTCMOS */ + pkt_size += fm_bop_top_write(0x60, 0x0005, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_top_write(0x60, 0x0015, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_top_write(0x60, 0x0035, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_top_write(0x60, 0x0030, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_top_rd_until(0x60, 0x0000000A, 0x0, &buf[pkt_size], buf_size - pkt_size); + + return pkt_size - 4; +} +/* + * mt6627_pwrdown - Wholechip FM Power down: Digital Modem Power Down + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6627_pwrdown(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6627_pwrdown_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +static signed int mt6627_tune_reg_op(unsigned char *buf, signed int buf_size, unsigned short freq, + unsigned short chan_para) +{ + signed int pkt_size = 4; + + WCN_DBG(FM_ALT | CHIP, "%s enter mt6627_tune function\n", __func__); + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* 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_MAIN_CTRL, 0xFFF8, TUNE, &buf[pkt_size], buf_size - pkt_size); + /* 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); + /* 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); +#endif + + WCN_DBG(FM_ALT | CHIP, "%s leave mt6627_tune function\n", __func__); + + return pkt_size - 4; +} + +/* + * mt6627_tune - execute tune action, + * @buf - target buf + * @buf_size - buffer size + * @freq - 760 ~ 1080, 100KHz unit + * return package size + */ +static signed int mt6627_tune(unsigned char *buf, signed int buf_size, unsigned short freq, + unsigned short chan_para) +{ + signed int pkt_size = 0; + + pkt_size = mt6627_tune_reg_op(buf, buf_size, freq, chan_para); + return fm_op_seq_combine_cmd(buf, FM_TUNE_OPCODE, pkt_size); +} + +static signed int mt6627_rampdown_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* Clear DSP state */ + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFF0, 0x0000, &buf[pkt_size], buf_size - pkt_size); + /* Set DSP ramp down state */ + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFFF, RAMP_DOWN, &buf[pkt_size], buf_size - pkt_size); + /* @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); + /* Clear DSP ramp down state */ + pkt_size += fm_bop_modify(FM_MAIN_CTRL, (~RAMP_DOWN), 0x0000, &buf[pkt_size], buf_size - pkt_size); + /* 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); + + return pkt_size - 4; +} +/* + * mt6627_rampdown - f/w will wait for STC_DONE interrupt + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6627_rampdown(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6627_rampdown_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_RAMPDOWN_OPCODE, pkt_size); +} + +static signed int mt6627_RampDown(void) +{ + signed int ret = 0; + unsigned short pkt_size; + /* unsigned short tmp; */ + + WCN_DBG(FM_DBG | CHIP, "ramp down\n"); + /* pwer up sequence 0425 */ + ret = fm_top_reg_write(0x0050, 0x00000007); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down wr top 0x50 failed\n"); + return ret; + } + + ret = fm_set_bits(0x0F, 0x0000, 0xF800); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down wr 0x0f failed\n"); + return ret; + } + + ret = fm_top_reg_write(0x0050, 0x0000000F); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down wr top 0x50 failed\n"); + return ret; + } + + /* fm_reg_read(FM_MAIN_INTRMASK, &tmp); */ + ret = fm_reg_write(FM_MAIN_INTRMASK, 0x0000); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down wr FM_MAIN_INTRMASK failed\n"); + return ret; + } + + ret = fm_reg_write(FM_MAIN_EXTINTRMASK, 0x0000); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down wr FM_MAIN_EXTINTRMASK failed\n"); + return ret; + } + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6627_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; + } + + ret = fm_reg_write(FM_MAIN_EXTINTRMASK, 0x0021); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down wr FM_MAIN_EXTINTRMASK failed\n"); + return ret; + } + + ret = fm_reg_write(FM_MAIN_INTRMASK, 0x0021); + if (ret) + WCN_DBG(FM_ERR | CHIP, "ramp down wr FM_MAIN_INTRMASK failed\n"); + + return ret; +} + +static signed int mt6627_get_rom_version(void) +{ + unsigned short tmp = 0; + signed int ret = 0; + + /* DSP rom code version request enable --- set 0x61 b15=1 */ + fm_set_bits(0x61, 0x8000, 0x7FFF); + + /* Release ASIP reset --- set 0x61 b1=1 */ + fm_set_bits(0x61, 0x0002, 0xFFFD); + + /* Enable ASIP power --- set 0x61 b0=0 */ + fm_set_bits(0x61, 0x0000, 0xFFFE); + + /* Wait DSP code version ready --- wait 1ms */ + do { + fm_delayus(1000); + ret = fm_reg_read(0x84, &tmp); + /* ret=-4 means signal got when control FM. usually get sig 9 to kill FM process. */ + /* now cancel FM power up sequence is recommended. */ + if (ret) + return ret; + + WCN_DBG(FM_DBG | CHIP, "0x84=%x\n", tmp); + } while (tmp != 0x0001); + + /* Get FM DSP code version --- rd 0x83[15:8] */ + fm_reg_read(0x83, &tmp); + tmp = (tmp >> 8); + + /* DSP rom code version request disable --- set 0x61 b15=0 */ + fm_set_bits(0x61, 0x0000, 0x7FFF); + + /* Reset ASIP --- set 0x61[1:0] = 1 */ + fm_set_bits(0x61, 0x0001, 0xFFFC); + + /* WCN_DBG(FM_NTC | CHIP, "ROM version: v%d\n", (signed int)tmp); */ + return (signed int) tmp; +} + +/* + * mt6627_pwrup_DSP_download - execute dsp/coeff patch dl action, + * @patch_tbl - current chip patch table + * return patch dl ok or not + */ +static signed int mt6627_pwrup_DSP_download(struct fm_patch_tbl *patch_tbl) +{ +#define PATCH_BUF_SIZE (4096*6) + signed int ret = 0; + signed int patch_len = 0; + unsigned char *dsp_buf = NULL; + unsigned short tmp_reg = 0; + + mt6627_hw_info.eco_ver = (signed int) mtk_wcn_wmt_ic_info_get(1); + WCN_DBG(FM_DBG | CHIP, "ECO version:0x%08x\n", mt6627_hw_info.eco_ver); + + /* get mt6627 DSP rom version */ + ret = mt6627_get_rom_version(); + if (ret >= 0) { + mt6627_hw_info.rom_ver = ret; + WCN_DBG(FM_DBG | CHIP, "ROM version: v%d\n", mt6627_hw_info.rom_ver); + } else { + WCN_DBG(FM_ERR | CHIP, "get ROM version failed\n"); + /* ret=-4 means signal got when control FM. usually get sig 9 to kill FM process. */ + /* now cancel FM power up sequence is recommended. */ + goto out; + } + + /* Wholechip FM Power Up: step 3, download patch */ + dsp_buf = fm_vmalloc(PATCH_BUF_SIZE); + if (!dsp_buf) { + WCN_DBG(FM_ALT | CHIP, "-ENOMEM\n"); + return -ENOMEM; + } + + patch_len = fm_get_patch_path(mt6627_hw_info.rom_ver, dsp_buf, PATCH_BUF_SIZE, patch_tbl); + if (patch_len <= 0) { + WCN_DBG(FM_ALT | CHIP, " fm_get_patch_path failed\n"); + ret = patch_len; + goto out; + } + + ret = fm_download_patch((const unsigned char *)dsp_buf, patch_len, IMG_PATCH); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " DL DSPpatch failed\n"); + goto out; + } + + patch_len = fm_get_coeff_path(mt6627_hw_info.rom_ver, dsp_buf, PATCH_BUF_SIZE, patch_tbl); + if (patch_len <= 0) { + WCN_DBG(FM_ALT | CHIP, " fm_get_coeff_path failed\n"); + ret = patch_len; + goto out; + } + + mt6627_hw_info.rom_ver += 1; + + tmp_reg = dsp_buf[38] | (dsp_buf[39] << 8); /* to be confirmed */ + mt6627_hw_info.patch_ver = (signed int) tmp_reg; + WCN_DBG(FM_NTC | CHIP, "Patch version: 0x%08x\n", mt6627_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; + } + + ret = fm_download_patch((const unsigned char *)dsp_buf, patch_len, IMG_COEFFICIENT); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " DL DSPcoeff failed\n"); + goto out; + } + fm_reg_write(0x92, 0x0000); /* ? */ + fm_reg_write(0x90, 0x0040); + fm_reg_write(0x90, 0x0000); + +out: + if (dsp_buf) { + fm_vfree(dsp_buf); + dsp_buf = NULL; + } + return ret; +} + +static signed int mt6627_PowerUp(unsigned short *chip_id, unsigned short *device_id) +{ + signed int ret = 0; + unsigned short pkt_size; + unsigned short tmp_reg = 0; +#if defined(MT6625_FM) + unsigned int host_reg = 0; +#endif + + if (chip_id == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (device_id == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + WCN_DBG(FM_DBG | CHIP, "pwr on seq......\n"); + + /* Wholechip FM Power Up: step 1, set common SPI parameter */ + ret = fm_host_reg_write(0x8013000C, 0x0000801F); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup set CSPI failed\n"); + return ret; + } +#if defined(MT6625_FM) + ret = fm_host_reg_read(0x80000224, &host_reg); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup read 0x80000224 failed\n"); + return ret; + } + ret = fm_host_reg_write(0x80000224, host_reg | (1 << 0)); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup conn_srcclkena enable failed\n"); + return ret; + } + + ret = fm_host_reg_read(0x80000224, &host_reg); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup read 0x80000224 failed\n"); + return ret; + } + ret = fm_host_reg_write(0x80000224, host_reg | (1 << 16)); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup conn_srcclkena switch failed\n"); + return ret; + } + + ret = fm_host_reg_read(0x80101030, &host_reg); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup read 0x80100030 failed\n"); + return ret; + } + ret = fm_host_reg_write(0x80101030, host_reg | (1 << 1)); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup enable top_ck_en_adie failed\n"); + return ret; + } + + /* enable bgldo */ + ret = fm_top_reg_read(0x00c0, &host_reg); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "power up read top 0xc0 failed\n"); + return ret; + } + ret = fm_top_reg_write(0x00c0, host_reg | (0x3 << 27)); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "power up write top 0xc0 failed\n"); + return ret; + } +#endif + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6627_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, "mt6627_pwrup_clock_on failed\n"); + return ret; + } +/* #ifdef FM_DIGITAL_INPUT */ + /* mt6627_I2s_Setting(MT6627_I2S_ON, MT6627_I2S_MASTER, MT6627_I2S_44K); */ + /* mt_combo_audio_ctrl(COMBO_AUDIO_STATE_2); */ + /* mtk_wcn_cmb_stub_audio_ctrl((CMB_STUB_AIF_X)CMB_STUB_AIF_2); */ +/* #endif */ + + /* Wholechip FM Power Up: step 2, read HW version */ + fm_reg_read(0x62, &tmp_reg); + /* *chip_id = tmp_reg; */ + if ((tmp_reg == 0x6625) || (tmp_reg == 0x6627)) + *chip_id = 0x6627; + *device_id = tmp_reg; + mt6627_hw_info.chip_id = (signed int) tmp_reg; + WCN_DBG(FM_DBG | CHIP, "chip_id:0x%04x\n", tmp_reg); + + if ((mt6627_hw_info.chip_id != 0x6627) && (mt6627_hw_info.chip_id != 0x6625)) { + WCN_DBG(FM_NTC | CHIP, "fm sys error, reset hw\n"); + return -FM_EFW; + } + + /* Wholechip FM Power Up: step 3, patch download */ + ret = mt6627_pwrup_DSP_download(mt6627_patch_tbl); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "mt6627_pwrup_DSP_download failed\n"); + return ret; + } + + /* Wholechip FM Power Up: step 4, FM Digital Init: fm_rgf_maincon */ + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6627_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, "mt6627_pwrup_digital_init failed\n"); + return ret; + } + /* Wholechip FM Power Up: step 5, FM RF fine tune setting */ + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6627_pwrup_fine_tune(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, "mt6627_pwrup_fine_tune failed\n"); + return ret; + } + /* enable connsys FM 2 wire RX */ + fm_reg_write(0x9B, 0xF9AB); + fm_host_reg_write(0x80101054, 0x00003f35); + + WCN_DBG(FM_DBG | CHIP, "pwr on seq ok\n"); + + return ret; +} + +static signed int mt6627_PowerDown(void) +{ + signed int ret = 0; + unsigned short pkt_size; + unsigned short dataRead = 0; + unsigned int tem = 0; +#if defined(MT6625_FM) + unsigned int host_reg = 0; + + WCN_DBG(FM_DBG | CHIP, "pwr down seq, but not clear top_clk_en_adie\n"); +#endif + + 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. + */ + fm_reg_read(FM_MAIN_INTR, &dataRead); + + if (dataRead & 0x1) + fm_reg_write(FM_MAIN_INTR, dataRead); /* clear status flag */ + + /* mt6627_RampDown(); */ + +/* #ifdef FM_DIGITAL_INPUT */ +/* mt6627_I2s_Setting(MT6627_I2S_OFF, MT6627_I2S_SLAVE, MT6627_I2S_44K); */ +/* #endif */ + /* pwer up sequence 0425 */ + /* A0:set audio output I2X Rx mode: */ + fm_host_reg_read(0x80101054, &tem); + tem = tem & 0xFFFF9FFF; + fm_host_reg_write(0x80101054, tem); + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6627_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, "mt6627_pwrdown failed\n"); + return ret; + } + /* FIX_ME, disable ext interrupt */ + fm_reg_write(FM_MAIN_EXTINTRMASK, 0x00); + +#if defined(MT6625_FM) + /* ret = fm_host_reg_read(0x80101030, &host_reg); + * if (ret) { + * WCN_DBG(FM_ALT | CHIP, " pwroff read 0x80100030 failed\n"); + * return ret; + * } + * WCN_DBG(FM_DBG | CHIP, "read host reg 0x80101030=%x\n", host_reg); + * ret = fm_host_reg_write(0x80101030, host_reg & (~(0x1 << 1))); + * if (ret) { + * WCN_DBG(FM_ALT | CHIP, " pwroff disable top_ck_en_adie failed\n"); + * return ret; + * } + */ + + ret = fm_host_reg_read(0x80000224, &host_reg); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwroff read 0x80000224 failed\n"); + return ret; + } + WCN_DBG(FM_DBG | CHIP, "read host reg 0x80000224=%x\n", host_reg); + ret = fm_host_reg_write(0x80000224, host_reg & (~(1 << 16))); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwroff conn_srcclkena switch failed\n"); + return ret; + } +#endif + +/* rssi_th_set = false; */ + return ret; +} + +/* just for dgb */ +#if 0 +static void mt6627_bt_write(unsigned int addr, unsigned int val) +{ + unsigned int tem, i = 0; + + fm_host_reg_write(0x80103020, addr); + fm_host_reg_write(0x80103024, val); + fm_host_reg_read(0x80103000, &tem); + while ((tem == 4) && (i < 1000)) { + i++; + fm_host_reg_read(0x80103000, &tem); + } +} +#endif +static bool mt6627_SetFreq(unsigned short freq) +{ + signed int ret = 0; + unsigned short pkt_size; + unsigned short chan_para = 0; + unsigned int reg_val = 0; + unsigned short freq_reg = 0; + + fm_cb_op->cur_freq_set(freq); + +#if 0 + /* MCU clock adjust if need */ + ret = mt6627_mcu_dese(freq, NULL); + if (ret < 0) + WCN_DBG(FM_ERR | MAIN, "mt6627_mcu_dese FAIL:%d\n", ret); + + WCN_DBG(FM_INF | MAIN, "MCU %d\n", ret); + + /* GPS clock adjust if need */ + ret = mt6627_gps_dese(freq, NULL); + if (ret < 0) + WCN_DBG(FM_ERR | MAIN, "mt6627_gps_dese FAIL:%d\n", ret); + + WCN_DBG(FM_INF | MAIN, "GPS %d\n", ret); +#endif + /* pwer up sequence 0425 */ + ret = fm_top_reg_write(0x0050, 0x00000007); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr top 0x50 failed\n"); + + ret = fm_set_bits(0x0F, 0x0455, 0xF800); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x0f failed\n"); + + if (mt6627_TDD_chan_check(freq)) { + ret = fm_set_bits(0x30, 0x0008, 0xFFF3); /* use TDD solution */ + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x30 failed\n"); + } else { + ret = fm_set_bits(0x30, 0x0000, 0xFFF3); /* default use FDD solution */ + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x30 failed\n"); + } + ret = fm_top_reg_write(0x0050, 0x0000000F); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr top 0x50 failed\n"); + +/* if (fm_cb_op->chan_para_get) { */ + chan_para = mt6627_chan_para_get(freq); + WCN_DBG(FM_DBG | CHIP, "%d chan para = %d\n", (signed int) freq, (signed int) chan_para); +/* } */ + + freq_reg = freq; + if (fm_get_channel_space(freq_reg) == 0) + freq_reg *= 10; + + freq_reg = (freq_reg - 6400) * 2 / 10; + ret = fm_set_bits(0x65, freq_reg, 0xFC00); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x65 failed\n"); + return false; + } + + ret = fm_set_bits(0x65, (chan_para << 12), 0x0FFF); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x65 failed\n"); + return false; + } + + /* enable connsys FM 2 wire RX */ + fm_reg_write(0x9B, 0xF9AB); + fm_host_reg_write(0x80101054, 0x00003f35); + + if ((mt6627_hw_info.chip_id == 0x6625) + && ((mtk_wcn_wmt_chipid_query() == 0x6592) || (mtk_wcn_wmt_chipid_query() == 0x6752) + || (mtk_wcn_wmt_chipid_query() == 0x6755) || (mtk_wcn_wmt_chipid_query() == 0x6757) + || (mtk_wcn_wmt_chipid_query() == 0x6763) || (mtk_wcn_wmt_chipid_query() == 0x6739))) { + if (mt6627_I2S_hopping_check(freq)) { + /* set i2s TX desense mode */ + ret = fm_set_bits(0x9C, 0x80, 0xFFFF); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x9C failed\n"); + + /* set i2s RX desense mode */ + ret = fm_host_reg_read(0x80101054, ®_val); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq rd 0x80101054 failed\n"); + + reg_val |= 0x8000; + ret = fm_host_reg_write(0x80101054, reg_val); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x80101054 failed\n"); + } else { + ret = fm_set_bits(0x9C, 0x0, 0xFF7F); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x9C failed\n"); + + ret = fm_host_reg_read(0x80101054, ®_val); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq rd 0x80101054 failed\n"); + + reg_val &= 0x7FFF; + ret = fm_host_reg_write(0x80101054, reg_val); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x80101054 failed\n"); + } + } + + if (FM_LOCK(cmd_buf_lock)) + return false; + pkt_size = mt6627_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, "mt6627_tune failed\n"); + return false; + } + + WCN_DBG(FM_DBG | CHIP, "set freq to %d ok\n", freq); +#if 0 + /* ADPLL setting for dbg */ + fm_top_reg_write(0x0050, 0x00000007); + fm_top_reg_write(0x0A08, 0xFFFFFFFF); + mt6627_bt_write(0x82, 0x11); + mt6627_bt_write(0x83, 0x11); + mt6627_bt_write(0x84, 0x11); + fm_top_reg_write(0x0040, 0x1C1C1C1C); + fm_top_reg_write(0x0044, 0x1C1C1C1C); + fm_reg_write(0x70, 0x0010); + /*0x0806 DCO clk + *0x0802 ref clk + *0x0804 feedback clk + */ + fm_reg_write(0xE0, 0x0806); +#endif + return true; +} + +#define FM_CQI_LOG_PATH "/mnt/sdcard/fmcqilog" + +static signed int mt6627_full_cqi_get(signed int min_freq, signed int max_freq, signed int space, signed int cnt) +{ + signed int ret = 0; + unsigned short pkt_size; + unsigned short freq, orig_freq; + signed int i, j, k; + signed int space_val, max, min, num; + struct mt6627_full_cqi *p_cqi; + unsigned char *cqi_log_title = "Freq, RSSI, PAMD, PR, FPAMD, MR, ATDC, PRX, ATDEV, SMGain, DltaRSSI\n"; + unsigned char cqi_log_buf[100] = { 0 }; + signed int pos; + unsigned char cqi_log_path[100] = { 0 }; + + /* for soft-mute tune, and get cqi */ + freq = fm_cb_op->cur_freq_get(); + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + /* get cqi */ + orig_freq = freq; + if (fm_get_channel_space(min_freq) == 0) + min = min_freq * 10; + else + min = min_freq; + + if (fm_get_channel_space(max_freq) == 0) + 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; (orig_freq == 10000) && (g_dbg_level == 0xffffffff) && (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)); + if (sprintf(&cqi_log_path[strlen(FM_CQI_LOG_PATH)], "%d.txt", k + 1) < 0) + WCN_DBG(FM_NTC | CHIP, "sprintf fail\n"); + 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 = fm_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, fm_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (!ret && fm_res) { + WCN_DBG(FM_NTC | CHIP, "smt cqi size %d\n", fm_res->cqi[0]); + p_cqi = (struct mt6627_full_cqi *)&fm_res->cqi[2]; + for (i = 0; i < fm_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 */ + if (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) < 0) + WCN_DBG(FM_NTC | CHIP, "sprintf fail\n"); + /* 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 */ + } + + return ret; +} + +/* + * mt6627_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 signed int mt6627_GetCurRSSI(signed int *pRSSI) +{ + unsigned short tmp_reg = 0; + + fm_reg_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 unsigned short mt6627_vol_tbl[16] = { 0x0000, 0x0519, 0x066A, 0x0814, + 0x0A2B, 0x0CCD, 0x101D, 0x1449, + 0x198A, 0x2027, 0x287A, 0x32F5, + 0x4027, 0x50C3, 0x65AD, 0x7FFF +}; + +static signed int mt6627_SetVol(unsigned char vol) +{ + signed int ret = 0; + + vol = (vol > 15) ? 15 : vol; + ret = fm_reg_write(0x7D, mt6627_vol_tbl[vol]); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "Set vol=%d Failed\n", vol); + return ret; + } + + 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 signed int mt6627_GetVol(unsigned char *pVol) +{ + int ret = 0; + unsigned short tmp = 0; + signed int i; + + if (pVol == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + ret = fm_reg_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 (mt6627_vol_tbl[i] == tmp) { + *pVol = i; + break; + } + } + + WCN_DBG(FM_DBG | CHIP, "Get vol=%d OK\n", *pVol); + return 0; +} + +static signed int mt6627_dump_reg(void) +{ + signed int i; + unsigned short TmpReg = 0; + + for (i = 0; i < 0xff; i++) { + fm_reg_read(i, &TmpReg); + WCN_DBG(FM_NTC | CHIP, "0x%02x=0x%04x\n", i, TmpReg); + } + return 0; +} + +/*0:mono, 1:stereo*/ +static bool mt6627_GetMonoStereo(unsigned short *pMonoStereo) +{ +#define FM_BF_STEREO 0x1000 + unsigned short TmpReg = 0; + + if (pMonoStereo) { + fm_reg_read(FM_RSSI_IND, &TmpReg); + *pMonoStereo = (TmpReg & FM_BF_STEREO) >> 12; + } else { + WCN_DBG(FM_ERR | CHIP, "MonoStero: para err\n"); + return false; + } + + WCN_DBG(FM_NTC | CHIP, "Get MonoStero:0x%04x\n", *pMonoStereo); + return true; +} + +static signed int mt6627_SetMonoStereo(signed int MonoStereo) +{ + signed int ret = 0; + + WCN_DBG(FM_NTC | CHIP, "set to %s\n", MonoStereo ? "mono" : "auto"); + fm_top_reg_write(0x50, 0x0007); + + if (MonoStereo) /*mono */ + ret = fm_set_bits(0x75, 0x0008, ~0x0008); + else + ret = fm_set_bits(0x75, 0x0000, ~0x0008); + + fm_top_reg_write(0x50, 0x000F); + return ret; +} + +static signed int mt6627_GetCapArray(signed int *ca) +{ + unsigned short dataRead = 0; + unsigned short tmp = 0; + + if (ca == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + fm_reg_read(0x60, &tmp); + fm_reg_write(0x60, tmp & 0xFFF7); /* 0x60 D3=0 */ + + fm_reg_read(0x26, &dataRead); + *ca = dataRead; + + fm_reg_write(0x60, tmp); /* 0x60 D3=1 */ + return 0; +} + +/* + * mt6627_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 bool mt6627_GetCurPamd(unsigned short *pPamdLevl) +{ + unsigned short tmp_reg = 0; + unsigned short dBvalue, valid_cnt = 0; + int i, total = 0; + + for (i = 0; i < 8; i++) { + if (fm_reg_read(FM_ADDR_PAMD, &tmp_reg)) { + *pPamdLevl = 0; + return 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); + } + fm_delayms(3); + } + if (valid_cnt != 0) + *pPamdLevl = total / valid_cnt; + else + *pPamdLevl = 0; + + WCN_DBG(FM_NTC | CHIP, "PAMD=%d\n", *pPamdLevl); + return true; +} + +static signed int mt6627_i2s_info_get(signed int *ponoff, signed int *pmode, signed int *psample) +{ + if (ponoff == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (pmode == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (psample == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + *ponoff = fm_config.aud_cfg.i2s_info.status; + *pmode = fm_config.aud_cfg.i2s_info.mode; + *psample = fm_config.aud_cfg.i2s_info.rate; + + return 0; +} + +static signed int mt6627fm_get_audio_info(struct fm_audio_info_t *data) +{ + memcpy(data, &fm_config.aud_cfg, sizeof(struct fm_audio_info_t)); + return 0; +} + +static signed int mt6627_hw_info_get(struct fm_hw_info *req) +{ + if (req == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + req->chip_id = mt6627_hw_info.chip_id; + req->eco_ver = mt6627_hw_info.eco_ver; + req->patch_ver = mt6627_hw_info.patch_ver; + req->rom_ver = mt6627_hw_info.rom_ver; + + return 0; +} + +static signed int mt6627_pre_search(void) +{ + mt6627_RampDown(); + /* disable audio output I2S Rx mode */ + fm_host_reg_write(0x80101054, 0x00000000); + /* disable audio output I2S Tx mode */ + fm_reg_write(0x9B, 0x0000); + + return 0; +} + +static signed int mt6627_restore_search(void) +{ + mt6627_RampDown(); + /* set audio output I2S Tx mode */ + fm_reg_write(0x9B, 0xF9AB); + /* set audio output I2S Rx mode */ + fm_host_reg_write(0x80101054, 0x00003f35); + return 0; +} + +static signed int mt6627_soft_mute_tune(unsigned short freq, signed int *rssi, signed int *valid) +{ + signed int ret = 0; + unsigned short pkt_size; + /* unsigned short freq;//, orig_freq; */ + struct mt6627_full_cqi *p_cqi; + signed int RSSI = 0, PAMD = 0, MR = 0, ATDC = 0; + unsigned int PRX = 0, ATDEV = 0; + unsigned short softmuteGainLvl = 0; + + ret = mt6627_chan_para_get(freq); + if (ret == 2) + ret = fm_set_bits(FM_CHANNEL_SET, 0x2000, 0x0FFF); /* mdf HiLo */ + else + ret = fm_set_bits(FM_CHANNEL_SET, 0x0000, 0x0FFF); /* clear FA/HL/ATJ */ + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = fm_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, fm_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (!ret && fm_res) { + p_cqi = (struct mt6627_full_cqi *)&fm_res->cqi[2]; + + 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 ((fm_config.rx_cfg.long_ana_rssi_th <= RSSI) + && (fm_config.rx_cfg.pamd_th >= PAMD) + && (fm_config.rx_cfg.atdc_th >= ATDC) + && (fm_config.rx_cfg.mr_th <= MR) + && (fm_config.rx_cfg.prx_th <= PRX) + && (ATDEV >= ATDC) /* sync scan algorithm */ + && (fm_config.rx_cfg.smg_th <= softmuteGainLvl)) { + *valid = true; + } else { + *valid = false; + } + WCN_DBG(FM_NTC | CHIP, + "valid=%d, freq %d, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x\n", + *valid, 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 = RSSI; + } else { + WCN_DBG(FM_ALT | CHIP, "smt get CQI failed\n"); + return false; + } + return true; +} + +static bool mt6627_em_test(unsigned short group_idx, unsigned short item_idx, unsigned int item_value) +{ + return true; +} + +/* +*parm: +* parm.th_type: 0, RSSI. 1,desense RSSI. 2,SMG. +* parm.th_val: threshold value +*/ +static signed int mt6627_set_search_th(signed int idx, signed int val, signed int reserve) +{ + switch (idx) { + case 0: { + fm_config.rx_cfg.long_ana_rssi_th = val; + WCN_DBG(FM_NTC | CHIP, "set rssi th =%d\n", val); + break; + } + case 1: { + fm_config.rx_cfg.desene_rssi_th = val; + WCN_DBG(FM_NTC | CHIP, "set desense rssi th =%d\n", val); + break; + } + case 2: { + fm_config.rx_cfg.smg_th = val; + WCN_DBG(FM_NTC | CHIP, "set smg th =%d\n", val); + break; + } + default: + break; + } + return 0; +} + +static signed int MT6627fm_low_power_wa_default(signed int fmon) +{ + return 0; +} + +signed int fm_low_ops_register(struct fm_callback *cb, struct fm_basic_interface *bi) +{ + signed int ret = 0; + /* Basic functions. */ + + if (bi == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,bi invalid pointer\n", __func__); + return -FM_EPARA; + } + if (cb->cur_freq_get == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,cb->cur_freq_get invalid pointer\n", __func__); + return -FM_EPARA; + } + if (cb->cur_freq_set == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,cb->cur_freq_set invalid pointer\n", __func__); + return -FM_EPARA; + } + fm_cb_op = cb; + + bi->pwron = mt6627_pwron; + bi->pwroff = mt6627_pwroff; + bi->chipid_get = mt6627_get_chipid; + bi->mute = mt6627_Mute; + bi->rampdown = mt6627_RampDown; + bi->pwrupseq = mt6627_PowerUp; + bi->pwrdownseq = mt6627_PowerDown; + bi->setfreq = mt6627_SetFreq; + bi->low_pwr_wa = MT6627fm_low_power_wa_default; + bi->get_aud_info = mt6627fm_get_audio_info; + bi->rssiget = mt6627_GetCurRSSI; + bi->volset = mt6627_SetVol; + bi->volget = mt6627_GetVol; + bi->dumpreg = mt6627_dump_reg; + bi->msget = mt6627_GetMonoStereo; + bi->msset = mt6627_SetMonoStereo; + bi->pamdget = mt6627_GetCurPamd; + bi->em = mt6627_em_test; + bi->anaswitch = mt6627_SetAntennaType; + bi->anaget = mt6627_GetAntennaType; + bi->caparray_get = mt6627_GetCapArray; + bi->hwinfo_get = mt6627_hw_info_get; + bi->i2s_get = mt6627_i2s_info_get; + bi->is_dese_chan = mt6627_is_dese_chan; + bi->softmute_tune = mt6627_soft_mute_tune; + bi->desense_check = mt6627_desense_check; + bi->cqi_log = mt6627_full_cqi_get; + bi->pre_search = mt6627_pre_search; + bi->restore_search = mt6627_restore_search; + bi->set_search_th = mt6627_set_search_th; + + cmd_buf_lock = fm_lock_create("27_cmd"); + ret = fm_lock_get(cmd_buf_lock); + + cmd_buf = fm_zalloc(TX_BUF_SIZE + 1); + + if (!cmd_buf) { + WCN_DBG(FM_ALT | CHIP, "6627 fm lib alloc tx buf failed\n"); + ret = -1; + } +#if 0 /* def CONFIG_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, "6627 fm lib create cqi fifo failed\n"); + ret = -1; + } +#endif + + return ret; +} + +signed int fm_low_ops_unregister(struct fm_basic_interface *bi) +{ + signed int ret = 0; + /* Basic functions. */ + if (bi == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + +#if 0 /* def CONFIG_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(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 unsigned short mt6627_mcu_dese_list[] = { + 7630, 7800, 7940, 8320, 9260, 9600, 9710, 9920, 10400, 10410 +}; + +static const unsigned short mt6627_gps_dese_list[] = { + 7850, 7860 +}; + +static const signed char mt6627_chan_para_map[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, /* 6500~6595 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6600~6695 */ + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, /* 6700~6795 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6800~6895 */ + 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6900~6995 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7000~7095 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, /* 7100~7195 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, /* 7200~7295 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7300~7395 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7400~7495 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7500~7595 */ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 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 */ + 8, 0, 2, 0, 2, 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, 1, 0, /* 7900~7995 */ + 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 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, 2, 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, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8300~8395 */ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 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, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8700~8795 */ + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 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, 2, 0, 0, 0, 0, 0, /* 9300~9395 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9400~9495 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9500~9595 */ + 0, 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, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 9900~9995 */ + 0, 0, 0, 0, 0, 0, 2, 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, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10400~10495 */ + 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, /* 10700~10795 */ + 0 /* 10800 */ +}; + +static const unsigned short mt6627_scan_dese_list[] = { + 6910, 7680, 7800, 9210, 9220, 9230, 9600, 9980, 9990, 10400, 10750, 10760 +}; + +static const unsigned short mt6627_I2S_hopping_list[] = { + 6550, 6760, 6960, 6970, 7170, 7370, 7580, 7780, 7990, 8810, 9210, 9220, 10240 +}; + +static const unsigned short mt6627_TDD_list[] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6500~6595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6600~6695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6700~6795 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6800~6895 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6900~6995 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7000~7095 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7100~7195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7200~7295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7300~7395 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7400~7495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7500~7595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7600~7695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7700~7795 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7800~7895 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7900~7995 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8000~8095 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8100~8195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8200~8295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8300~8395 */ + 0x0101, 0x0000, 0x0000, 0x0000, 0x0000, /* 8400~8495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8500~8595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8600~8695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8700~8795 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8800~8895 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8900~8995 */ + 0x0000, 0x0000, 0x0101, 0x0101, 0x0101, /* 9000~9095 */ + 0x0101, 0x0000, 0x0000, 0x0000, 0x0000, /* 9100~9195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9200~9295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9300~9395 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9400~9495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9500~9595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9600~9695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0100, /* 9700~9795 */ + 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, /* 9800~9895 */ + 0x0101, 0x0101, 0x0001, 0x0000, 0x0000, /* 9900~9995 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10000~10095 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10100~10195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10200~10295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10300~10395 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10400~10495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10500~10595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0100, /* 10600~10695 */ + 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, /* 10700~10795 */ + 0x0001 /* 10800 */ +}; + +static const unsigned short mt6627_TDD_Mask[] = { + 0x0001, 0x0010, 0x0100, 0x1000 +}; + +/* return value: 0, not a de-sense channel; 1, this is a de-sense channel; else error no */ +static signed int mt6627_is_dese_chan(unsigned short freq) +{ + signed int size; + + /* return 0;//HQA only :skip desense channel check. */ + size = ARRAY_SIZE(mt6627_scan_dese_list); + + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + while (size) { + if (mt6627_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 signed int mt6627_desense_check(unsigned short freq, signed int rssi) +{ + if (mt6627_is_dese_chan(freq)) { + if (rssi < fm_config.rx_cfg.desene_rssi_th) + return 1; + + WCN_DBG(FM_DBG | CHIP, "desen_rssi %d th:%d\n", rssi, fm_config.rx_cfg.desene_rssi_th); + } + return 0; +} + +static bool mt6627_TDD_chan_check(unsigned short freq) +{ + unsigned int i = 0; + unsigned short freq_tmp = freq; + signed int ret = 0; + + ret = fm_get_channel_space(freq_tmp); + if (ret == 0) + freq_tmp *= 10; + else if (ret == -1) + return false; + + i = (freq_tmp - 6500) / 5; + if ((i / 4) >= ARRAY_SIZE(mt6627_TDD_list)) { + WCN_DBG(FM_ERR | CHIP, "Freq index out of range(%d),max(%zd)\n", + i / 4, ARRAY_SIZE(mt6627_TDD_list)); + return false; + } + + if (mt6627_TDD_list[i / 4] & mt6627_TDD_Mask[i % 4]) { + WCN_DBG(FM_NTC | CHIP, "Freq %d use TDD solution\n", freq); + return true; + } else + return false; +} + +/* get channel parameter, HL side/ FA / ATJ */ +static unsigned short mt6627_chan_para_get(unsigned short freq) +{ + signed int pos, size; + + /* return 0;//for HQA only: skip FA/HL/ATJ */ + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + if (freq < 6500) + return 0; + + pos = (freq - 6500) / 5; + + size = ARRAY_SIZE(mt6627_chan_para_map); + + pos = (pos > (size - 1)) ? (size - 1) : pos; + + return mt6627_chan_para_map[pos]; +} + +static bool mt6627_I2S_hopping_check(unsigned short freq) +{ + signed int size; + + size = ARRAY_SIZE(mt6627_I2S_hopping_list); + + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + while (size) { + if (mt6627_I2S_hopping_list[size - 1] == freq) + return 1; + size--; + } + + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/mt6627/pub/mt6627_fm_rds.c b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6627/pub/mt6627_fm_rds.c new file mode 100644 index 0000000000000..20bad698b319b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6627/pub/mt6627_fm_rds.c @@ -0,0 +1,334 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_interface.h" +#include "fm_stdlib.h" +#include "fm_rds.h" +#include "mt6627_fm_reg.h" +#include "fm_cmd.h" + +static bool bRDS_FirstIn; /* false */ +static unsigned int gBLER_CHK_INTERVAL = 500; +static unsigned short GOOD_BLK_CNT = 0, BAD_BLK_CNT; +static unsigned char BAD_BLK_RATIO; + +static struct fm_basic_interface *fm_bi; + +static bool mt6627_RDS_support(void); +static signed int mt6627_RDS_enable(void); +static signed int mt6627_RDS_disable(void); +static unsigned short mt6627_RDS_Get_GoodBlock_Counter(void); +static unsigned short mt6627_RDS_Get_BadBlock_Counter(void); +static unsigned char mt6627_RDS_Get_BadBlock_Ratio(void); +static unsigned int mt6627_RDS_Get_BlerCheck_Interval(void); +/* static void mt6627_RDS_GetData(unsigned short *data, unsigned short datalen); */ +static void mt6627_RDS_Init_Data(struct rds_t *pstRDSData); + +static bool mt6627_RDS_support(void) +{ + return true; +} + +static signed int mt6627_RDS_enable(void) +{ + signed int ret = 0; + unsigned short dataRead = 0; + + WCN_DBG(FM_DBG | RDSC, "rds enable\n"); + ret = fm_reg_read(FM_RDS_CFG0, &dataRead); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds enable read 0x80 fail\n"); + return ret; + } + ret = fm_reg_write(FM_RDS_CFG0, 6); /* set buf_start_th */ + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds enable write 0x80 fail\n"); + return ret; + } + ret = fm_reg_read(FM_MAIN_CTRL, &dataRead); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds enable read 0x63 fail\n"); + return ret; + } + ret = fm_reg_write(FM_MAIN_CTRL, dataRead | (RDS_MASK)); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds enable write 0x63 fail\n"); + return ret; + } + + return ret; +} + +static signed int mt6627_RDS_disable(void) +{ + signed int ret = 0; + unsigned short dataRead = 0; + + WCN_DBG(FM_DBG | RDSC, "rds disable\n"); + ret = fm_reg_read(FM_MAIN_CTRL, &dataRead); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds disable read 0x63 fail\n"); + return ret; + } + ret = fm_reg_write(FM_MAIN_CTRL, dataRead & (~RDS_MASK)); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds disable write 0x63 fail\n"); + return ret; + } + + return ret; +} + +static unsigned short mt6627_RDS_Get_GoodBlock_Counter(void) +{ + unsigned short tmp_reg = 0; + + fm_reg_read(FM_RDS_GOODBK_CNT, &tmp_reg); + GOOD_BLK_CNT = tmp_reg; + WCN_DBG(FM_DBG | RDSC, "get good block cnt:%d\n", (signed int) tmp_reg); + + return tmp_reg; +} + +static unsigned short mt6627_RDS_Get_BadBlock_Counter(void) +{ + unsigned short tmp_reg = 0; + + fm_reg_read(FM_RDS_BADBK_CNT, &tmp_reg); + BAD_BLK_CNT = tmp_reg; + WCN_DBG(FM_DBG | RDSC, "get bad block cnt:%d\n", (signed int) tmp_reg); + + return tmp_reg; +} + +static unsigned char mt6627_RDS_Get_BadBlock_Ratio(void) +{ + unsigned short tmp_reg; + unsigned short gbc; + unsigned short bbc; + + gbc = mt6627_RDS_Get_GoodBlock_Counter(); + bbc = mt6627_RDS_Get_BadBlock_Counter(); + + if ((gbc + bbc) > 0) + tmp_reg = (unsigned char) (bbc * 100 / (gbc + bbc)); + else + tmp_reg = 0; + + BAD_BLK_RATIO = tmp_reg; + WCN_DBG(FM_DBG | RDSC, "get badblock ratio:%d\n", (signed int) tmp_reg); + + return tmp_reg; +} + +static signed int mt6627_RDS_BlockCounter_Reset(void) +{ + mt6627_RDS_disable(); + mt6627_RDS_enable(); + + return 0; +} + +static unsigned int mt6627_RDS_Get_BlerCheck_Interval(void) +{ + return gBLER_CHK_INTERVAL; +} + +static signed int mt6627_RDS_BlerCheck(struct rds_t *dst) +{ + return 0; +} + +#if 0 +static void RDS_Recovery_Handler(void) +{ + unsigned short tempData = 0; + + do { + fm_reg_read(FM_RDS_DATA_REG, &tempData); + fm_reg_read(FM_RDS_POINTER, &tempData); + } while (tempData & 0x3); +} +#endif + +#if 0 +static void mt6627_RDS_GetData(unsigned short *data, unsigned short 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 + + unsigned short CRC = 0, i = 0, RDS_adj = 0, RDSDataCount = 0, FM_WARorrCnt = 0; + unsigned short temp = 0, OutputPofm_s32 = 0; + + WCN_DBG(FM_DBG | RDSC, "get data\n"); + fm_reg_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_reg_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_reg_read(FM_RDS_DATA_REG, &data[0]); + + /* block B data and info handling */ + fm_reg_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_reg_read(FM_RDS_DATA_REG, &data[1]); + + /* block C data and info handling */ + fm_reg_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_reg_read(FM_RDS_DATA_REG, &data[2]); + + /* block D data and info handling */ + fm_reg_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_reg_read(FM_RDS_DATA_REG, &data[3]); + + data[4] = (CRC | RDS_adj | RDSDataCount); + data[5] = FM_WARorrCnt; + + fm_reg_read(FM_RDS_PWDI, &data[6]); + fm_reg_read(FM_RDS_PWDQ, &data[7]); + + fm_reg_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 mt6627_RDS_Init_Data(struct rds_t *pstRDSData) +{ + fm_memset(pstRDSData, 0, sizeof(struct rds_t)); + bRDS_FirstIn = true; + + pstRDSData->event_status = 0x0000; + 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)); +} + +bool mt6627_RDS_OnOff(struct rds_t *dst, bool bFlag) +{ + signed int ret = 0; + + if (mt6627_RDS_support() == false) { + WCN_DBG(FM_ALT | RDSC, "mt6627_RDS_OnOff failed, RDS not support\n"); + return false; + } + + if (bFlag) { + mt6627_RDS_Init_Data(dst); + ret = mt6627_RDS_enable(); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "mt6627_RDS_OnOff enable failed\n"); + return false; + } + } else { + mt6627_RDS_Init_Data(dst); + ret = mt6627_RDS_disable(); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "mt6627_RDS_OnOff disable failed\n"); + return false; + } + } + + return true; +} + +DEFINE_RDSLOG(mt6627_rds_log); + +/* mt6627_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 signed int mt6627_rds_parser(struct rds_t *rds_dst, struct rds_rx_t *rds_raw, + signed int rds_size, unsigned short(*getfreq) (void)) +{ + mt6627_rds_log.log_in(&mt6627_rds_log, rds_raw, rds_size); + return rds_parser(rds_dst, rds_raw, rds_size, getfreq); +} + +static signed int mt6627_rds_log_get(struct rds_rx_t *dst, signed int *dst_len) +{ + return mt6627_rds_log.log_out(&mt6627_rds_log, dst, dst_len); +} + +static signed int mt6627_rds_gc_get(struct rds_group_cnt_t *dst, struct rds_t *rdsp) +{ + return rds_grp_counter_get(dst, &rdsp->gc); +} + +static signed int mt6627_rds_gc_reset(struct rds_t *rdsp) +{ + return rds_grp_counter_reset(&rdsp->gc); +} + +signed int fm_rds_ops_register(struct fm_basic_interface *bi, struct fm_rds_interface *ri) +{ + signed int ret = 0; + + if (ri == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,ri invalid pointer\n", __func__); + return -FM_EPARA; + } + fm_bi = bi; + + ri->rds_blercheck = mt6627_RDS_BlerCheck; + ri->rds_onoff = mt6627_RDS_OnOff; + ri->rds_parser = mt6627_rds_parser; + ri->rds_gbc_get = mt6627_RDS_Get_GoodBlock_Counter; + ri->rds_bbc_get = mt6627_RDS_Get_BadBlock_Counter; + ri->rds_bbr_get = mt6627_RDS_Get_BadBlock_Ratio; + ri->rds_bc_reset = mt6627_RDS_BlockCounter_Reset; + ri->rds_bci_get = mt6627_RDS_Get_BlerCheck_Interval; + ri->rds_log_get = mt6627_rds_log_get; + ri->rds_gc_get = mt6627_rds_gc_get; + ri->rds_gc_reset = mt6627_rds_gc_reset; + return ret; +} + +signed int fm_rds_ops_unregister(struct fm_rds_interface *ri) +{ + signed int ret = 0; + + if (ri == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,ri invalid pointer\n", __func__); + return -FM_EPARA; + } + + fm_bi = NULL; + fm_memset(ri, 0, sizeof(struct fm_rds_interface)); + return ret; +} diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/mt6630/inc/mt6630_fm_lib.h b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6630/inc/mt6630_fm_lib.h new file mode 100644 index 0000000000000..55fd695b2031d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6630/inc/mt6630_fm_lib.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __MT6630_FM_LIB_H__ +#define __MT6630_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 { + mt6630_E1 = 0, + mt6630_E2 +}; + +struct mt6630_fm_cqi { + unsigned short ch; + unsigned short rssi; + unsigned short reserve; +}; + +struct adapt_fm_cqi { + signed int ch; + signed int rssi; + signed int reserve; +}; + +struct mt6630_full_cqi { + unsigned short ch; + unsigned short rssi; + unsigned short pamd; + unsigned short pr; + unsigned short fpamd; + unsigned short mr; + unsigned short atdc; + unsigned short prx; + unsigned short atdev; + unsigned short smg; /* soft-mute gain */ + unsigned short drssi; /* delta rssi */ +}; + +#endif diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/mt6630/inc/mt6630_fm_reg.h b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6630/inc/mt6630_fm_reg.h new file mode 100644 index 0000000000000..cab9c814e4ca3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6630/inc/mt6630_fm_reg.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __MT6630_FM_REG_H__ +#define __MT6630_FM_REG_H__ + +/* 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, +}; + +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 /* __MT6630_FM_REG_H__ */ diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/mt6630/pub/mt6630_fm_lib.c b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6630/pub/mt6630_fm_lib.c new file mode 100644 index 0000000000000..bbff7210ae252 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6630/pub/mt6630_fm_lib.c @@ -0,0 +1,2471 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#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_cmd.h" + +#include "mt6630_fm_reg.h" +#include "mt6630_fm_lib.h" + +static struct fm_patch_tbl mt6630_patch_tbl[5] = { + {FM_ROM_V1, "mt6630_fm_v1_patch.bin", "mt6630_fm_v1_coeff.bin", NULL, NULL}, + {FM_ROM_V2, "mt6630_fm_v2_patch.bin", "mt6630_fm_v2_coeff.bin", NULL, NULL}, + {FM_ROM_V3, "mt6630_fm_v3_patch.bin", "mt6630_fm_v3_coeff.bin", NULL, NULL}, + {FM_ROM_V4, "mt6630_fm_v4_patch.bin", "mt6630_fm_v4_coeff.bin", NULL, NULL}, + {FM_ROM_V5, "mt6630_fm_v5_patch.bin", "mt6630_fm_v5_coeff.bin", NULL, NULL}, +}; + +static struct fm_patch_tbl mt6630_patch_tbl_tx[5] = { + {FM_ROM_V1, "mt6630_fm_v1_patch_tx.bin", "mt6630_fm_v1_coeff_tx.bin", NULL, NULL}, + {FM_ROM_V2, "mt6630_fm_v2_patch_tx.bin", "mt6630_fm_v2_coeff_tx.bin", NULL, NULL}, + {FM_ROM_V3, "mt6630_fm_v3_patch_tx.bin", "mt6630_fm_v3_coeff_tx.bin", NULL, NULL}, + {FM_ROM_V4, "mt6630_fm_v4_patch_tx.bin", "mt6630_fm_v4_coeff_tx.bin", NULL, NULL}, + {FM_ROM_V5, "mt6630_fm_v5_patch_tx.bin", "mt6630_fm_v5_coeff_tx.bin", NULL, NULL}, +}; + +static struct fm_hw_info mt6630_hw_info = { + .chip_id = 0x00006630, + .eco_ver = 0x00000000, + .rom_ver = 0x00000000, + .patch_ver = 0x00000000, + .reserve = 0x00000000, +}; + +static struct fm_callback *fm_cb_op; +static unsigned char fm_packaging = 1; /*0:QFN,1:WLCSP */ +static unsigned int fm_sant_flag; /* 1,Short Antenna; 0, Long Antenna */ +static signed int mt6630_is_dese_chan(unsigned short freq); +#if 0 +static signed int mt6630_mcu_dese(unsigned short freq, void *arg); +#endif +static signed int mt6630_gps_dese(unsigned short freq, void *arg); + +static signed int mt6630_I2s_Setting(signed int onoff, signed int mode, signed int sample); +static unsigned short mt6630_chan_para_get(unsigned short freq); +static signed int mt6630_desense_check(unsigned short freq, signed int rssi); +static bool mt6630_TDD_chan_check(unsigned short freq); +static signed int mt6630_soft_mute_tune(unsigned short freq, signed int *rssi, signed int *valid); +static signed int mt6630_pwron(signed int data) +{ + if (mtk_wcn_wmt_func_on(WMTDRV_TYPE_FM) == MTK_WCN_BOOL_FALSE) { + WCN_DBG(FM_ERR | CHIP, "WMT turn on FM Fail!\n"); + return -FM_ELINK; + } + + WCN_DBG(FM_NTC | CHIP, "WMT turn on FM OK!\n"); + return 0; +} + +static signed int mt6630_pwroff(signed int data) +{ + if (mtk_wcn_wmt_func_off(WMTDRV_TYPE_FM) == MTK_WCN_BOOL_FALSE) { + WCN_DBG(FM_ERR | CHIP, "WMT turn off FM Fail!\n"); + return -FM_ELINK; + } + + WCN_DBG(FM_NTC | CHIP, "WMT turn off FM OK!\n"); + return 0; +} + +static unsigned short mt6630_get_chipid(void) +{ + return 0x6630; +} + +/* MT6630_SetAntennaType - set Antenna type + * @type - 1,Short Antenna; 0, Long Antenna + */ +static signed int mt6630_SetAntennaType(signed int type) +{ + unsigned short dataRead = 0; + + WCN_DBG(FM_NTC | CHIP, "set ana to %s\n", type ? "short" : "long"); + if (fm_packaging == 0) { + fm_sant_flag = type; + } else { + fm_reg_read(FM_MAIN_CG2_CTRL, &dataRead); + + if (type) + dataRead |= ANTENNA_TYPE; + else + dataRead &= (~ANTENNA_TYPE); + + fm_reg_write(FM_MAIN_CG2_CTRL, dataRead); + } + return 0; +} + +static signed int mt6630_GetAntennaType(void) +{ + unsigned short dataRead = 0; + + if (fm_packaging == 0) + return fm_sant_flag; + + fm_reg_read(FM_MAIN_CG2_CTRL, &dataRead); + WCN_DBG(FM_NTC | 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 signed int mt6630_Mute(bool mute) +{ + signed int ret = 0; + unsigned short dataRead = 0; + + WCN_DBG(FM_NTC | CHIP, "set %s\n", mute ? "mute" : "unmute"); + fm_reg_read(FM_MAIN_CTRL, &dataRead); + + if (mute == 1) + ret = fm_reg_write(FM_MAIN_CTRL, (dataRead & 0xFFDF) | 0x0020); + else + ret = fm_reg_write(FM_MAIN_CTRL, (dataRead & 0xFFDF)); + + return ret; +} + +signed int mt6630_rampdown_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* Clear DSP state */ + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFF0, 0x0000, &buf[pkt_size], buf_size - pkt_size); + /* Set DSP ramp down state */ + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFFF, RAMP_DOWN, &buf[pkt_size], buf_size - pkt_size); + /* @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); + /* Clear DSP ramp down state */ + pkt_size += fm_bop_modify(FM_MAIN_CTRL, (~RAMP_DOWN), 0x0000, &buf[pkt_size], buf_size - pkt_size); + /* 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); + + return pkt_size - 4; +} + + +/* + * mt6630_rampdown - f/w will wait for STC_DONE interrupt + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6630_rampdown(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6630_rampdown_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_RAMPDOWN_OPCODE, pkt_size); +} + +static signed int mt6630_RampDown(void) +{ + signed int ret = 0; + unsigned short pkt_size; + /* unsigned short tmp; */ + + WCN_DBG(FM_NTC | CHIP, "ramp down\n"); + + ret = fm_reg_write(FM_MAIN_EXTINTRMASK, 0x0000); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down write FM_MAIN_EXTINTRMASK failed\n"); + return ret; + } + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6630_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; + } + + ret = fm_reg_write(FM_MAIN_EXTINTRMASK, 0x0021); + if (ret) + WCN_DBG(FM_ERR | CHIP, "ramp down write FM_MAIN_EXTINTRMASK failed\n"); + + return ret; +} + +static signed int mt6630_pwrup_clock_on_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + unsigned short de_emphasis; + /* unsigned short osc_freq; */ + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + de_emphasis = fm_config.rx_cfg.deemphasis; + de_emphasis &= 0x0001; /* rang 0~1 */ + + /* B1.1 Enable digital OSC */ + pkt_size += fm_bop_write(0x60, 0x0003, &buf[pkt_size], buf_size - pkt_size); /* wr 60 3 */ + pkt_size += fm_bop_udelay(100, &buf[pkt_size], buf_size - pkt_size); /* delay 100us */ + /* B1.3 Release HW clock gating */ + pkt_size += fm_bop_write(0x60, 0x0007, &buf[pkt_size], buf_size - pkt_size); /* wr 60 7 */ + /* B1.4 Set FM long/short antenna:1: short_antenna 0: long antenna(default) */ + pkt_size += fm_bop_modify(0x61, 0xFFEF, 0x0000, &buf[pkt_size], buf_size - pkt_size); + /* B1.5 Set audio output mode (lineout/I2S) 0:lineout, 1:I2S */ + if (fm_config.aud_cfg.aud_path == FM_AUD_ANALOG) + pkt_size += fm_bop_modify(0x61, 0xFF7F, 0x0000, &buf[pkt_size], buf_size - pkt_size); + else + pkt_size += fm_bop_modify(0x61, 0xFF7F, 0x0080, &buf[pkt_size], buf_size - pkt_size); + + /* B1.6 Set deemphasis setting */ + 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); */ + + return pkt_size - 4; +} + +/* + * mt6630_pwrup_clock_on - Wholechip FM Power Up: step 1, FM Digital Clock enable + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6630_pwrup_clock_on(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6630_pwrup_clock_on_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +static signed int mt6630_pwrup_digital_init_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* update FM ADPLL fast tracking mode gain */ + pkt_size += fm_bop_modify(0xF, 0xF800, 0x0455, &buf[pkt_size], buf_size - pkt_size); + /* F1.4 Set appropriate interrupt mask behavior as desired(RX) */ + /* pkt_size += fm_bop_write(0x6A, 0x0021, &buf[pkt_size], buf_size - pkt_size);//wr 6A 0021 */ + pkt_size += fm_bop_write(0x6B, 0x0021, &buf[pkt_size], buf_size - pkt_size); /* wr 6B 0021 */ + /* F1.9 Enable HW auto control */ + pkt_size += fm_bop_write(0x60, 0x000F, &buf[pkt_size], buf_size - pkt_size); /* wr 60 f */ + /* F1.10 Release ASIP reset */ + pkt_size += fm_bop_modify(0x61, 0xFFFD, 0x0002, &buf[pkt_size], buf_size - pkt_size); /* wr 61 D1=1 */ + /* F1.11 Enable ASIP power */ + pkt_size += fm_bop_modify(0x61, 0xFFFE, 0x0000, &buf[pkt_size], buf_size - pkt_size); /* wr 61 D0=0 */ + pkt_size += fm_bop_udelay(100000, &buf[pkt_size], buf_size - pkt_size); /* delay 100ms */ + /* F1.13 Check HW intitial complete */ + pkt_size += fm_bop_rd_until(0x64, 0x001F, 0x0002, &buf[pkt_size], buf_size - pkt_size); /* Poll 64[0~4] = 2 */ + + return pkt_size - 4; +} + +/* + * mt6630_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 + */ +static signed int mt6630_pwrup_digital_init(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6630_pwrup_digital_init_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + + +signed int mt6630_pwrdown_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* Disable HW clock control */ + pkt_size += fm_bop_write(0x60, 0x0107, &buf[pkt_size], buf_size - pkt_size); /* wr 60 107 */ + /* 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 */ + + return pkt_size - 4; +} + +/* + * mt6630_pwrdown - Wholechip FM Power down: Digital Modem Power Down + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6630_pwrdown(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6630_pwrdown_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +signed int mt6630_tune_reg_op(unsigned char *buf, signed int buf_size, unsigned short freq, + unsigned short chan_para) +{ + signed int pkt_size = 4; + + WCN_DBG(FM_ALT | CHIP, "%s enter mt6630_tune function\n", __func__); + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + freq = (freq - 6400) * 2 / 10; + + /* 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); + /* 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); + /* 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); + /* 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); +#endif + + return pkt_size - 4; +} + +/* + * mt6630_tune - execute tune action, + * @buf - target buf + * @buf_size - buffer size + * @freq - 760 ~ 1080, 100KHz unit + * return package size + */ +static signed int mt6630_tune(unsigned char *buf, signed int buf_size, unsigned short freq, + unsigned short chan_para) +{ + signed int pkt_size = 0; + + pkt_size = mt6630_tune_reg_op(buf, buf_size, freq, chan_para); + return fm_op_seq_combine_cmd(buf, FM_TUNE_OPCODE, pkt_size); +} + +static signed int mt6630_get_rom_version(void) +{ + unsigned short tmp = 0; + signed int ret = 0; + + /* DSP rom code version request enable --- set 0x61 b15=1 */ + fm_set_bits(0x61, 0x8000, 0x7FFF); + + /* Release ASIP reset --- set 0x61 b1=1 */ + fm_set_bits(0x61, 0x0002, 0xFFFD); + + /* Enable ASIP power --- set 0x61 b0=0 */ + fm_set_bits(0x61, 0x0000, 0xFFFE); + + /* Wait DSP code version ready --- wait 1ms */ + do { + fm_delayus(1000); + ret = fm_reg_read(0x84, &tmp); + /* ret=-4 means signal got when control FM. usually get sig 9 to kill FM process. */ + /* now cancel FM power up sequence is recommended. */ + if (ret) + return ret; + + WCN_DBG(FM_DBG | CHIP, "0x84=%x\n", tmp); + } while (tmp != 0x0001); + + /* Get FM DSP code version --- rd 0x83[15:8] */ + fm_reg_read(0x83, &tmp); + WCN_DBG(FM_NTC | CHIP, "DSP ver=0x%x\n", tmp); + tmp = (tmp >> 8); + + /* DSP rom code version request disable --- set 0x61 b15=0 */ + fm_set_bits(0x61, 0x0000, 0x7FFF); + + /* Reset ASIP --- set 0x61[1:0] = 1 */ + fm_set_bits(0x61, 0x0001, 0xFFFC); + + return (signed int) tmp; +} + +static signed int mt6630_pwrup_top_setting(void) +{ + signed int ret = 0, value = 0; + /* A0.1 Turn on FM buffer */ + ret = fm_host_reg_read(0x8102123c, &value); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x8102123c rd failed\n"); + return ret; + } + ret = fm_host_reg_write(0x8102123c, value & 0xFFFFFFBF); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x8102123c wr failed\n"); + return ret; + } + /* A0.2 Set xtal no off when FM on */ + ret = fm_host_reg_read(0x81021134, &value); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81021134 rd failed\n"); + return ret; + } + ret = fm_host_reg_write(0x81021134, value | 0x80); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81021134 wr failed\n"); + return ret; + } + /* A0.3 Set top off always on when FM on */ + ret = fm_host_reg_read(0x81020010, &value); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81020010 rd failed\n"); + return ret; + } + ret = fm_host_reg_write(0x81020010, value & 0xFFFDFFFF); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81020010 wr failed\n"); + return ret; + } + /* A0.4 Always enable PALDO when FM on */ + ret = fm_host_reg_read(0x81021430, &value); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81021430 rd failed\n"); + return ret; + } + ret = fm_host_reg_write(0x81021430, value | 0x80000000); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81021430 wr failed\n"); + return ret; + } + /* A0.5 */ + fm_delayus(240); + + /* A0.6 MTCMOS Control */ + ret = fm_host_reg_read(0x81020008, &value); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81020008 rd failed\n"); + return ret; + } + ret = fm_host_reg_write(0x81020008, value | 0x00000030); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81020008 wr failed\n"); + return ret; + } + /* A0.7 */ + fm_delayus(20); + + /* A0.8 release power on reset */ + ret = fm_host_reg_read(0x81020008, &value); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81020008 rd failed\n"); + return ret; + } + ret = fm_host_reg_write(0x81020008, value | 0x00000001); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81020008 wr failed\n"); + return ret; + } + /* A0.9 enable fspi_mas_bclk_ck */ + ret = fm_host_reg_read(0x80000108, &value); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x80000108 rd failed\n"); + return ret; + } + ret = fm_host_reg_write(0x80000108, value | 0x00000100); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x80000108 wr failed\n"); + return ret; + } + return ret; +} + +static signed int mt6630_pwrdown_top_setting(void) +{ + signed int ret = 0, value = 0; + /* B0.1 disable fspi_mas_bclk_ck */ + ret = fm_host_reg_read(0x80000104, &value); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x80000104 rd failed\n"); + return ret; + } + ret = fm_host_reg_write(0x80000104, value | 0x00000100); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x80000104 wr failed\n"); + return ret; + } + /* B0.2 set power off reset */ + ret = fm_host_reg_read(0x81020008, &value); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81020008 rd failed\n"); + return ret; + } + ret = fm_host_reg_write(0x81020008, value & 0xFFFFFFFE); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81020008 wr failed\n"); + return ret; + } + /* B0.3 */ + fm_delayus(20); + + /* B0.4 disable MTCMOS & set Iso_en */ + ret = fm_host_reg_read(0x81020008, &value); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81020008 rd failed\n"); + return ret; + } + ret = fm_host_reg_write(0x81020008, value & 0xFFFFFFEF); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81020008 wr failed\n"); + return ret; + } + /* B0.5 Turn off FM buffer */ + ret = fm_host_reg_read(0x8102123c, &value); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x8102123c rd failed\n"); + return ret; + } + ret = fm_host_reg_write(0x8102123c, value | 0x40); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x8102123c wr failed\n"); + return ret; + } + /* B0.6 Clear xtal no off when FM off */ + ret = fm_host_reg_read(0x81021134, &value); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81021134 rd failed\n"); + return ret; + } + ret = fm_host_reg_write(0x81021134, value & 0xFFFFFF7F); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81021134 wr failed\n"); + return ret; + } + /* B0.7 Clear top off always on when FM off */ + ret = fm_host_reg_read(0x81020010, &value); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81020010 rd failed\n"); + return ret; + } + ret = fm_host_reg_write(0x81020010, value | 0x20000); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81020010 wr failed\n"); + return ret; + } + /* B0.9 Disable PALDO when FM off */ + ret = fm_host_reg_read(0x81021430, &value); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81021430 rd failed\n"); + return ret; + } + ret = fm_host_reg_write(0x81021430, value & 0x7FFFFFFF); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81021430 wr failed\n"); + return ret; + } + + return ret; +} + +static signed int mt6630_pwrup_DSP_download(struct fm_patch_tbl *patch_tbl) +{ +#define PATCH_BUF_SIZE (4096*6) + signed int ret = 0; + signed int patch_len = 0; + unsigned char *dsp_buf = NULL; + unsigned short tmp_reg = 0; + + mt6630_hw_info.eco_ver = (signed int) mtk_wcn_wmt_ic_info_get(1); + WCN_DBG(FM_NTC | CHIP, "ECO version:0x%08x\n", mt6630_hw_info.eco_ver); + + /* FM ROM code version request */ + ret = mt6630_get_rom_version(); + if (ret >= 0) { + mt6630_hw_info.rom_ver = ret; + WCN_DBG(FM_NTC | CHIP, "ROM version: v%d\n", mt6630_hw_info.rom_ver); + } else { + WCN_DBG(FM_ERR | CHIP, "get ROM version failed\n"); + /* ret=-4 means signal got when control FM. usually get sig 9 to kill FM process. */ + /* now cancel FM power up sequence is recommended. */ + return ret; + } + + /* Wholechip FM Power Up: step 3, download patch */ + dsp_buf = fm_vmalloc(PATCH_BUF_SIZE); + if (!dsp_buf) { + WCN_DBG(FM_ERR | CHIP, "-ENOMEM\n"); + return -ENOMEM; + } + + patch_len = fm_get_patch_path(mt6630_hw_info.rom_ver, dsp_buf, PATCH_BUF_SIZE, patch_tbl); + if (patch_len <= 0) { + WCN_DBG(FM_ALT | CHIP, " fm_get_patch_path failed\n"); + ret = patch_len; + goto out; + } + + ret = fm_download_patch((const unsigned char *)dsp_buf, patch_len, IMG_PATCH); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " DL DSPpatch failed\n"); + goto out; + } + + patch_len = fm_get_coeff_path(mt6630_hw_info.rom_ver, dsp_buf, PATCH_BUF_SIZE, patch_tbl); + if (patch_len <= 0) { + WCN_DBG(FM_ALT | CHIP, " fm_get_coeff_path failed\n"); + ret = patch_len; + goto out; + } + + mt6630_hw_info.rom_ver += 1; + + tmp_reg = dsp_buf[38] | (dsp_buf[39] << 8); /* to be confirmed */ + mt6630_hw_info.patch_ver = (signed int) tmp_reg; + WCN_DBG(FM_NTC | CHIP, "Patch version: 0x%08x\n", mt6630_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; + } + + ret = fm_download_patch((const unsigned char *)dsp_buf, patch_len, IMG_COEFFICIENT); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " DL DSPcoeff failed\n"); + goto out; + } + fm_reg_write(0x90, 0x0040); + fm_reg_write(0x90, 0x0000); +out: + if (dsp_buf) { + fm_vfree(dsp_buf); + dsp_buf = NULL; + } + return ret; +} + +static signed int mt6630_PowerUp(unsigned short *chip_id, unsigned short *device_id) +{ + signed int ret = 0, reg = 0; + unsigned short pkt_size; + unsigned short tmp_reg = 0; + + if (chip_id == NULL) { + WCN_DBG(CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (device_id == NULL) { + WCN_DBG(CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + WCN_DBG(FM_DBG | CHIP, "pwr on seq......\n"); + + ret = fm_host_reg_read(0x80021010, ®); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "packaging rd failed\n"); + } else { + fm_packaging = (reg & 0x00008000) >> 15; + WCN_DBG(FM_NTC | CHIP, "fm_packaging: %d\n", fm_packaging); + } + ret = mt6630_pwrup_top_setting(); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "mt6630_pwrup_top_setting failed\n"); + return ret; + } + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6630_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_ERR | CHIP, "mt6630_pwrup_clock_on failed\n"); + return ret; + } + /* read HW version */ + fm_reg_read(0x62, &tmp_reg); + *chip_id = tmp_reg; + *device_id = tmp_reg; + mt6630_hw_info.chip_id = (signed int) tmp_reg; + WCN_DBG(FM_NTC | CHIP, "chip_id:0x%04x\n", tmp_reg); + + if (mt6630_hw_info.chip_id != 0x6630) { + WCN_DBG(FM_NTC | CHIP, "fm sys error!\n"); + return -FM_EPARA; + } + ret = mt6630_pwrup_DSP_download(mt6630_patch_tbl); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "mt6630_pwrup_DSP_download failed\n"); + return ret; + } + + if ((fm_config.aud_cfg.aud_path == FM_AUD_MRGIF) + || (fm_config.aud_cfg.aud_path == FM_AUD_I2S)) { + mt6630_I2s_Setting(FM_I2S_ON, fm_config.aud_cfg.i2s_info.mode, + fm_config.aud_cfg.i2s_info.rate); + /* mt_combo_audio_ctrl(COMBO_AUDIO_STATE_2); */ + mtk_wcn_cmb_stub_audio_ctrl((enum CMB_STUB_AIF_X) CMB_STUB_AIF_2); + } + /* Wholechip FM Power Up: step 4, FM Digital Init: fm_rgf_maincon */ + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6630_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_ERR | CHIP, "mt6630_pwrup_digital_init failed\n"); + return ret; + } + + WCN_DBG(FM_NTC | CHIP, "pwr on seq ok\n"); + + return ret; +} + +static signed int mt6630_PowerDown(void) +{ + signed int ret = 0; + unsigned short pkt_size; + unsigned short dataRead = 0; + + 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. + */ + fm_reg_read(FM_MAIN_INTR, &dataRead); + + if (dataRead & 0x1) + fm_reg_write(FM_MAIN_INTR, dataRead); /* clear status flag */ + + /* mt6630_RampDown(); */ + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6630_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_ERR | CHIP, "mt6630_pwrdown failed\n"); + return ret; + } + + ret = mt6630_pwrdown_top_setting(); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "mt6630_pwrdown_top_setting failed\n"); + return ret; + } + + return ret; +} + +/* just for dgb */ +static bool mt6630_SetFreq(unsigned short freq) +{ + signed int ret = 0; + unsigned short pkt_size; + unsigned short chan_para = 0; + + fm_cb_op->cur_freq_set(freq); + +#if 0 + /* MCU clock adjust if need */ + ret = mt6630_mcu_dese(freq, NULL); + if (ret < 0) + WCN_DBG(FM_ERR | MAIN, "mt6630_mcu_dese FAIL:%d\n", ret); + + WCN_DBG(FM_INF | MAIN, "MCU %d\n", ret); +#endif + + /* GPS clock adjust if need */ + ret = mt6630_gps_dese(freq, NULL); + if (ret < 0) + WCN_DBG(FM_ERR | MAIN, "mt6630_gps_dese FAIL:%d\n", ret); + + WCN_DBG(FM_INF | MAIN, "GPS %d\n", ret); + + ret = fm_reg_write(0x60, 0x0007); + if (ret) + WCN_DBG(FM_ALT | MAIN, "set freq write 0x60 fail\n"); + + if (mt6630_TDD_chan_check(freq)) { + ret = fm_set_bits(0x30, 0x0004, 0xFFF9); /* use TDD solution */ + if (ret) + WCN_DBG(FM_ALT | MAIN, "set freq write 0x30 fail\n"); + } else { + ret = fm_set_bits(0x30, 0x0000, 0xFFF9); /* default use FDD solution */ + if (ret) + WCN_DBG(FM_ALT | MAIN, "set freq write 0x30 fail\n"); + } + ret = fm_reg_write(0x60, 0x000F); + if (ret) + WCN_DBG(FM_ALT | MAIN, "set freq write 0x60 fail\n"); + + chan_para = mt6630_chan_para_get(freq); + WCN_DBG(FM_DBG | CHIP, "%d chan para = %d\n", (signed int) freq, (signed int) chan_para); + + if (FM_LOCK(cmd_buf_lock)) + return false; + pkt_size = mt6630_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_ERR | CHIP, "mt6630_tune failed\n"); + return false; + } + + WCN_DBG(FM_DBG | CHIP, "set freq to %d ok\n", freq); + return true; +} + +#define FM_CQI_LOG_PATH "/mnt/sdcard/fmcqilog" + +static signed int mt6630_full_cqi_get(signed int min_freq, signed int max_freq, signed int space, signed int cnt) +{ + signed int ret = 0; + unsigned short pkt_size; + unsigned short freq, orig_freq; + signed int i, j, k; + signed int space_val, max, min, num; + struct mt6630_full_cqi *p_cqi; + unsigned char *cqi_log_title = "Freq, RSSI, PAMD, PR, FPAMD, MR, ATDC, PRX, ATDEV, SMGain, DltaRSSI\n"; + unsigned char cqi_log_buf[100] = { 0 }; + signed int pos; + unsigned char cqi_log_path[100] = { 0 }; + + WCN_DBG(FM_DBG | CHIP, "6630 cqi log start\n"); + /* for soft-mute tune, and get cqi */ + freq = fm_cb_op->cur_freq_get(); + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + /* get cqi */ + orig_freq = freq; + if (fm_get_channel_space(min_freq) == 0) + min = min_freq * 10; + else + min = min_freq; + + if (fm_get_channel_space(max_freq) == 0) + 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; (orig_freq == 10000) && (g_dbg_level == 0xffffffff) && (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)); + if (sprintf(&cqi_log_path[strlen(FM_CQI_LOG_PATH)], "%d.txt", k + 1) < 0) + WCN_DBG(FM_NTC | CHIP, "sprintf fail\n"); + 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 = fm_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, fm_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (!ret && fm_res) { + WCN_DBG(FM_NTC | CHIP, "smt cqi size %d\n", fm_res->cqi[0]); + p_cqi = (struct mt6630_full_cqi *)&fm_res->cqi[2]; + for (i = 0; i < fm_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 */ + if (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) < 0) + WCN_DBG(FM_NTC | CHIP, "sprintf fail\n"); + /* write back to log file */ + fm_file_write(cqi_log_path, cqi_log_buf, strlen(cqi_log_buf), &pos); + } + } else { + WCN_DBG(FM_ERR | 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_DBG | CHIP, "6630 cqi log done\n"); + + return ret; +} + +/* + * mt6630_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 signed int mt6630_GetCurRSSI(signed int *pRSSI) +{ + unsigned short tmp_reg = 0; + + /* TODO: check reg */ + fm_reg_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 unsigned short mt6630_vol_tbl[16] = { + 0x0000, 0x0519, 0x066A, 0x0814, + 0x0A2B, 0x0CCD, 0x101D, 0x1449, + 0x198A, 0x2027, 0x287A, 0x32F5, + 0x4027, 0x50C3, 0x65AD, 0x7FFF +}; + +static signed int mt6630_SetVol(unsigned char vol) +{ + signed int ret = 0; + + /* TODO: check reg */ + vol = (vol > 15) ? 15 : vol; + ret = fm_reg_write(0x7D, mt6630_vol_tbl[vol]); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "Set vol=%d Failed\n", vol); + return ret; + } + + 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 signed int mt6630_GetVol(unsigned char *pVol) +{ + int ret = 0; + unsigned short tmp = 0; + signed int i; + + if (pVol == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + /* TODO: check reg */ + ret = fm_reg_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 (mt6630_vol_tbl[i] == tmp) { + *pVol = i; + break; + } + } + + WCN_DBG(FM_DBG | CHIP, "Get vol=%d OK\n", *pVol); + return 0; +} + +static signed int mt6630_dump_reg(void) +{ + signed int i; + unsigned short TmpReg = 0; + + for (i = 0; i < 0xff; i++) { + fm_reg_read(i, &TmpReg); + WCN_DBG(FM_NTC | CHIP, "0x%02x=0x%04x\n", i, TmpReg); + } + return 0; +} + +static bool mt6630_GetMonoStereo(unsigned short *pMonoStereo) +{ +#define FM_BF_STEREO 0x1000 + unsigned short TmpReg = 0; + + /* TODO: check reg */ + if (pMonoStereo) { + fm_reg_read(FM_RSSI_IND, &TmpReg); + *pMonoStereo = (TmpReg & FM_BF_STEREO) >> 12; + } else { + WCN_DBG(FM_ERR | CHIP, "MonoStero: para err\n"); + return false; + } + + WCN_DBG(FM_DBG | CHIP, "MonoStero:0x%04x\n", *pMonoStereo); + return true; +} + +static signed int mt6630_SetMonoStereo(signed int MonoStereo) +{ + signed int ret = 0; +#define FM_FORCE_MS 0x0008 + + WCN_DBG(FM_DBG | CHIP, "set to %s\n", MonoStereo ? "mono" : "auto"); + /* TODO: check reg */ + + fm_reg_write(0x60, 0x3007); + + if (MonoStereo) + ret = fm_set_bits(0x75, FM_FORCE_MS, ~FM_FORCE_MS); + else + ret = fm_set_bits(0x75, 0x0000, ~FM_FORCE_MS); + + return ret; +} + +static signed int mt6630_GetCapArray(signed int *ca) +{ + unsigned short dataRead = 0; + unsigned short tmp = 0; + + /* TODO: check reg */ + if (ca == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + fm_reg_read(0x60, &tmp); + fm_reg_write(0x60, tmp & 0xFFF7); /* 0x60 D3=0 */ + + fm_reg_read(0x26, &dataRead); + *ca = dataRead; + + fm_reg_write(0x60, tmp); /* 0x60 D3=1 */ + return 0; +} + +/* + * mt6630_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 bool mt6630_GetCurPamd(unsigned short *pPamdLevl) +{ + unsigned short tmp_reg = 0; + unsigned short dBvalue, valid_cnt = 0; + int i, total = 0; + + for (i = 0; i < 8; i++) { + /* TODO: check reg */ + if (fm_reg_read(FM_ADDR_PAMD, &tmp_reg)) { + *pPamdLevl = 0; + return 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); + } + fm_delayms(3); + } + if (valid_cnt != 0) + *pPamdLevl = total / valid_cnt; + else + *pPamdLevl = 0; + + WCN_DBG(FM_NTC | CHIP, "PAMD=%d\n", *pPamdLevl); + return true; +} + +static signed int MT6630_FMOverBT(bool enable) +{ + signed int ret = 0; + + WCN_DBG(FM_NTC | CHIP, "+%s():\n", __func__); + + if (enable == true) { + /* change I2S to slave mode and 48K sample rate */ + if (mt6630_I2s_Setting(FM_I2S_ON, FM_I2S_SLAVE, FM_I2S_48K)) + goto out; + WCN_DBG(FM_NTC | CHIP, "set FM via BT controller\n"); + } else if (enable == false) { + /* change I2S to master mode and 44.1K sample rate */ + if (mt6630_I2s_Setting(FM_I2S_ON, FM_I2S_MASTER, FM_I2S_44K)) + 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; +} + +/* + * mt6630_I2s_Setting - set the I2S state on MT6630 + * @onoff - I2S on/off + * @mode - I2S mode: Master or Slave + * + * Return:0, if success; error code, if failed + */ +static signed int mt6630_I2s_Setting(signed int onoff, signed int mode, signed int sample) +{ + unsigned short tmp_state = 0; + unsigned short tmp_mode = 0; + unsigned short tmp_sample = 0; + signed int ret = 0; + + if (onoff == FM_I2S_ON) { + tmp_state = 0x0003; /* I2S enable and standard I2S mode, 0x9B D0,D1=1 */ + fm_config.aud_cfg.i2s_info.status = FM_I2S_ON; + } else if (onoff == FM_I2S_OFF) { + tmp_state = 0x0000; /* I2S off, 0x9B D0,D1=0 */ + fm_config.aud_cfg.i2s_info.status = FM_I2S_OFF; + } else { + WCN_DBG(FM_ERR | CHIP, "%s():[onoff=%d]\n", __func__, onoff); + ret = -FM_EPARA; + goto out; + } + + if (mode == FM_I2S_MASTER) { + tmp_mode = 0x0000; /* 6630 as I2S master, set 0x9B D3=0 */ + fm_config.aud_cfg.i2s_info.mode = FM_I2S_MASTER; + } else if (mode == FM_I2S_SLAVE) { + tmp_mode = 0x0008; /* 6630 as I2S slave, set 0x9B D3=1 */ + fm_config.aud_cfg.i2s_info.mode = FM_I2S_SLAVE; + } else { + WCN_DBG(FM_ERR | CHIP, "%s():[mode=%d]\n", __func__, mode); + ret = -FM_EPARA; + goto out; + } + + if (sample == FM_I2S_32K) { + tmp_sample = 0x0000; /* 6630 I2S 32KHz sample rate, 0x5F D11~12 */ + fm_config.aud_cfg.i2s_info.rate = FM_I2S_32K; + } else if (sample == FM_I2S_44K) { + tmp_sample = 0x0800; /* 6630 I2S 44.1KHz sample rate */ + fm_config.aud_cfg.i2s_info.rate = FM_I2S_44K; + } else if (sample == FM_I2S_48K) { + tmp_sample = 0x1000; /* 6630 I2S 48KHz sample rate */ + fm_config.aud_cfg.i2s_info.rate = FM_I2S_48K; + } else { + WCN_DBG(FM_ERR | CHIP, "%s():[sample=%d]\n", __func__, sample); + ret = -FM_EPARA; + goto out; + } + + ret = fm_reg_write(0x60, 0x7); + if (ret) + goto out; + + ret = fm_set_bits(0x5F, tmp_sample, 0xE7FF); + if (ret) + goto out; + + ret = fm_set_bits(0x9B, tmp_mode, 0xFFF7); + if (ret) + goto out; + + ret = fm_set_bits(0x9B, tmp_state, 0xFFFC); + if (ret) + goto out; + + /* F0.4 enable ft */ + ret = fm_set_bits(0x56, 0x1, 0xFFFE); + if (ret) + goto out; + + ret = fm_reg_write(0x60, 0xf); + if (ret) + goto out; + + WCN_DBG(FM_NTC | CHIP, "[onoff=%s][mode=%s][sample=%d](0)33KHz,(1)44.1KHz,(2)48KHz\n", + (onoff == FM_I2S_ON) ? "On" : "Off", (mode == FM_I2S_MASTER) ? "Master" : "Slave", sample); +out: + return ret; +} + +static signed int mt6630fm_get_audio_info(struct fm_audio_info_t *data) +{ + memcpy(data, &fm_config.aud_cfg, sizeof(struct fm_audio_info_t)); + return 0; +} + +static signed int mt6630_i2s_info_get(signed int *ponoff, signed int *pmode, signed int *psample) +{ + *ponoff = fm_config.aud_cfg.i2s_info.status; + *pmode = fm_config.aud_cfg.i2s_info.mode; + *psample = fm_config.aud_cfg.i2s_info.rate; + + return 0; +} + +static signed int mt6630_hw_info_get(struct fm_hw_info *req) +{ + if (req == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + req->chip_id = mt6630_hw_info.chip_id; + req->eco_ver = mt6630_hw_info.eco_ver; + req->patch_ver = mt6630_hw_info.patch_ver; + req->rom_ver = mt6630_hw_info.rom_ver; + + return 0; +} + +static signed int mt6630_pre_search(void) +{ + mt6630_RampDown(); + return 0; +} + +static signed int mt6630_restore_search(void) +{ + mt6630_RampDown(); + return 0; +} + +/* +*freq: 8750~10800 +*valid: true-valid channel,false-invalid channel +*return: true- smt success, false-smt fail +*/ +static signed int mt6630_soft_mute_tune(unsigned short freq, signed int *rssi, signed int *valid) +{ + signed int ret = 0; + unsigned short pkt_size; + /* unsigned short freq;//, orig_freq; */ + struct mt6630_full_cqi *p_cqi; + signed int RSSI = 0, PAMD = 0, MR = 0, ATDC = 0; + unsigned int PRX = 0, ATDEV = 0; + unsigned short softmuteGainLvl = 0; + + ret = mt6630_chan_para_get(freq); + if (ret == 2) + ret = fm_set_bits(FM_CHANNEL_SET, 0x2000, 0x0FFF); /* mdf HiLo */ + else + ret = fm_set_bits(FM_CHANNEL_SET, 0x0000, 0x0FFF); /* clear FA/HL/ATJ */ +#if 0 + fm_reg_write(0x60, 0x0007); + if (mt6630_TDD_chan_check(freq)) + fm_set_bits(0x30, 0x0004, 0xFFF9); /* use TDD solution */ + else + fm_set_bits(0x30, 0x0000, 0xFFF9); /* default use FDD solution */ + fm_reg_write(0x60, 0x000F); +#endif + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = fm_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, fm_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (!ret && fm_res) { + WCN_DBG(FM_DBG | CHIP, "smt cqi size %d\n", fm_res->cqi[0]); + p_cqi = (struct mt6630_full_cqi *)&fm_res->cqi[2]; + + 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 ((fm_config.rx_cfg.long_ana_rssi_th <= RSSI) + && (fm_config.rx_cfg.pamd_th >= PAMD) + && (fm_config.rx_cfg.atdc_th >= ATDC) + && (fm_config.rx_cfg.mr_th <= MR) + && (fm_config.rx_cfg.prx_th <= PRX) + && (ATDEV >= ATDC) /* sync scan algorithm */ + && (fm_config.rx_cfg.smg_th <= softmuteGainLvl)) { + *valid = true; + } else { + *valid = false; + } + + WCN_DBG(FM_NTC | CHIP, + "valid = %d, freq %d, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x\n", + *valid, 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 = RSSI; + } else { + WCN_DBG(FM_ERR | CHIP, "smt get CQI failed\n"); + return false; + } + return true; +} + +/* +*parm: +* parm.th_type: 0, RSSI. 1,desense RSSI. 2,SMG. +* parm.th_val: threshold value +*/ +static signed int mt6630_set_search_th(signed int idx, signed int val, signed int reserve) +{ + switch (idx) { + case 0: { + fm_config.rx_cfg.long_ana_rssi_th = val; + WCN_DBG(FM_NTC | CHIP, "set rssi th =%d\n", val); + break; + } + case 1: { + fm_config.rx_cfg.desene_rssi_th = val; + WCN_DBG(FM_NTC | CHIP, "set desense rssi th =%d\n", val); + break; + } + case 2: { + fm_config.rx_cfg.smg_th = val; + WCN_DBG(FM_NTC | CHIP, "set smg th =%d\n", val); + break; + } + default: + break; + } + return 0; +} + +#if 0 +static const unsigned short mt6630_mcu_dese_list[] = { + 0 /* 7630, 7800, 7940, 8320, 9260, 9600, 9710, 9920, 10400, 10410 */ +}; + +static const unsigned short mt6630_gps_dese_list[] = { + 0 /* 7850, 7860 */ +}; +#endif + +static const signed char mt6630_chan_para_map[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6500~6595 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6600~6695 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, /* 6700~6795 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6800~6895 */ + 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6900~6995 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7000~7095 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7100~7195 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7200~7295 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7300~7395 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7400~7495 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7500~7595 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 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 */ + 8, 0, 2, 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 */ + 0, 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, 2, 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, 2, 0, 0, 0, 0, 0, /* 8300~8395 */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 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, 2, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9400~9495 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9500~9595 */ + 1, 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, 0, 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, 1, 0, 1, 0, 0, 0, 0, 0, /* 10300~10395 */ + 8, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10400~10495 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 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 unsigned short mt6630_TDD_list[] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6500~6595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6600~6695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6700~6795 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6800~6895 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6900~6995 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7000~7095 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7100~7195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7200~7295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7300~7395 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7400~7495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7500~7595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7600~7695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7700~7795 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7800~7895 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7900~7995 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8000~8095 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8100~8195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8200~8295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8300~8395 */ + 0x0101, 0x0000, 0x0000, 0x0000, 0x0000, /* 8400~8495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8500~8595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8600~8695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8700~8795 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8800~8895 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8900~8995 */ + 0x0000, 0x0000, 0x0101, 0x0101, 0x0101, /* 9000~9095 */ + 0x0101, 0x0000, 0x0000, 0x0000, 0x0000, /* 9100~9195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9200~9295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9300~9395 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9400~9495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9500~9595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9600~9695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0100, /* 9700~9795 */ + 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, /* 9800~9895 */ + 0x0101, 0x0101, 0x0001, 0x0000, 0x0000, /* 9900~9995 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10000~10095 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10100~10195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10200~10295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10300~10395 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10400~10495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10500~10595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0100, /* 10600~10695 */ + 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, /* 10700~10795 */ + 0x0001 /* 10800 */ +}; + +static const unsigned short mt6630_TDD_Mask[] = { + 0x0001, 0x0010, 0x0100, 0x1000 +}; + +static const unsigned short mt6630_scan_dese_list[] = { + 7800, 9210, 9220, 9600, 9980, 10400, 10750, 10760 +}; + +/* return value: 0, not a de-sense channel; 1, this is a de-sense channel; else error no */ +static signed int mt6630_is_dese_chan(unsigned short freq) +{ + signed int size; + + /* return 0;//HQA only :skip desense channel check. */ + size = ARRAY_SIZE(mt6630_scan_dese_list); + + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + while (size) { + if (mt6630_scan_dese_list[size - 1] == freq) + return 1; + + size--; + } + + return 0; +} + +static bool mt6630_TDD_chan_check(unsigned short freq) +{ + unsigned int i = 0; + unsigned short freq_tmp = freq; + signed int ret = 0; + + ret = fm_get_channel_space(freq_tmp); + if (ret == 0) + freq_tmp *= 10; + else if (ret == -1) + return false; + + i = (freq_tmp - 6500) / 5; + if ((i / 4) >= ARRAY_SIZE(mt6630_TDD_list)) { + WCN_DBG(FM_ERR | CHIP, "Freq index out of range(%d),max(%zd)\n", + i / 4, ARRAY_SIZE(mt6630_TDD_list)); + return false; + } + + if (mt6630_TDD_list[i / 4] & mt6630_TDD_Mask[i % 4]) { + WCN_DBG(FM_DBG | CHIP, "Freq %d use TDD solution\n", freq); + return true; + } else + return false; +} + +/* 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 signed int mt6630_desense_check(unsigned short freq, signed int rssi) +{ + if (mt6630_is_dese_chan(freq)) { + if (rssi < fm_config.rx_cfg.desene_rssi_th) + return 1; + + WCN_DBG(FM_DBG | CHIP, "desen_rssi %d th:%d\n", rssi, fm_config.rx_cfg.desene_rssi_th); + } + return 0; +} + +/* get channel parameter, HL side/ FA / ATJ */ +static unsigned short mt6630_chan_para_get(unsigned short freq) +{ + signed int pos, size; + + /* return 0;//for HQA only: skip FA/HL/ATJ */ + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + if (freq < 6500) + return 0; + + pos = (freq - 6500) / 5; + + size = ARRAY_SIZE(mt6630_chan_para_map); + + pos = (pos > (size - 1)) ? (size - 1) : pos; + + return mt6630_chan_para_map[pos]; +} + +static signed int mt6630_gps_dese(unsigned short freq, void *arg) +{ + enum fm_gps_desense_t state = FM_GPS_DESE_DISABLE; + + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + WCN_DBG(FM_DBG | CHIP, "%s, [freq=%d]\n", __func__, (int)freq); + + if (state != FM_GPS_DESE_ENABLE) { + if ((freq >= 7800) && (freq <= 8000)) + state = FM_GPS_DESE_ENABLE; + } + /* request 6630 GPS change clk */ + if (state == FM_GPS_DESE_DISABLE) { + if (!mtk_wcn_wmt_dsns_ctrl(WMTDSNS_FM_GPS_DISABLE)) + return -1; + + return 0; + } + + if (!mtk_wcn_wmt_dsns_ctrl(WMTDSNS_FM_GPS_ENABLE)) + return -1; + + return 1; +} + +/******************************Tx function********************************************/ + +signed int mt6630_pwrup_clock_on_tx_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* B1.0 Enable digital OSC */ + pkt_size += fm_bop_write(0x60, 0x0003, &buf[pkt_size], buf_size - pkt_size); /* wr 60 3 */ + pkt_size += fm_bop_udelay(100, &buf[pkt_size], buf_size - pkt_size); /* delay 100us */ + /* B1.2 Release HW clock gating */ + pkt_size += fm_bop_write(0x60, 0x0007, &buf[pkt_size], buf_size - pkt_size); /* wr 60 7 */ + if (fm_config.aud_cfg.aud_path == FM_AUD_ANALOG) + pkt_size += fm_bop_modify(0x61, 0xFF7F, 0x0000, &buf[pkt_size], buf_size - pkt_size); + else + pkt_size += fm_bop_modify(0x61, 0xFF7F, 0x0080, &buf[pkt_size], buf_size - pkt_size); + + /* B1.4 set TX mode: 0909 sequence */ + pkt_size += fm_bop_write(0xC7, 0x8286, &buf[pkt_size], buf_size - pkt_size); /* wr C7 8286 */ + + return pkt_size - 4; +} + +/* + * mt6630_pwrup_clock_on_tx - FM tx Digital Clock enable + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6630_pwrup_clock_on_tx(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6630_pwrup_clock_on_tx_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +signed int mt6630_pwrup_tx_deviation_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* A1 switch to host control */ + pkt_size += fm_bop_write(0x60, 0x0007, &buf[pkt_size], buf_size - pkt_size); /* wr 60 0007 */ + /* set rgf_tx_beta_sum */ + pkt_size += fm_bop_write(0xCD, 0x72D2, &buf[pkt_size], buf_size - pkt_size); /* wr CD 72D2 */ + /* set rgf_tx_beta_diff */ + pkt_size += fm_bop_write(0xCF, 0x787B, &buf[pkt_size], buf_size - pkt_size); /* wr CF 787B */ + /* set rgf_tx_beta_rds */ + pkt_size += fm_bop_write(0xCE, 0x0785, &buf[pkt_size], buf_size - pkt_size); /* wr CE 785 */ + /* set rgf_tx_beta_pilot */ + pkt_size += fm_bop_write(0xCC, 0x0000, &buf[pkt_size], buf_size - pkt_size); /* wr CC 0 */ + /* set rgf_phase_gen_rsh */ + pkt_size += fm_bop_modify(0xAD, 0xFFE8, 0x0001, &buf[pkt_size], buf_size - pkt_size); /* wr AD D4 D2:D0=1 */ + /* set rgf_phase_gen_wb */ + pkt_size += fm_bop_modify(0xA8, 0xF000, 0x0F16, &buf[pkt_size], buf_size - pkt_size); /* wr A8 D11:D0=F16 */ + /* set agc */ + pkt_size += fm_bop_modify(0xAE, 0xFC00, 0x020B, &buf[pkt_size], buf_size - pkt_size); /* wr AE D9:D0=20B */ + /* set rgf_beta_fm */ + pkt_size += fm_bop_write(0xEE, 0x623D, &buf[pkt_size], buf_size - pkt_size); /* wr EE 623D */ + /* switch to DSP control */ + pkt_size += fm_bop_write(0x60, 0x000F, &buf[pkt_size], buf_size - pkt_size); /* wr 60 000F */ + + return pkt_size - 4; +} + +/* + * mt6630_pwrup_tx_deviation - default deviation (RDS off) + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +signed int mt6630_pwrup_tx_deviation(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6630_pwrup_tx_deviation_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +signed int mt6630_tx_rdson_deviation_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* A1 switch to host control */ + pkt_size += fm_bop_write(0x60, 0x0007, &buf[pkt_size], buf_size - pkt_size); /* wr 60 0007 */ + /* set rgf_tx_beta_sum */ + pkt_size += fm_bop_write(0xCD, 0x70E3, &buf[pkt_size], buf_size - pkt_size); /* wr CD 70E3 */ + /* set rgf_tx_beta_diff */ + pkt_size += fm_bop_write(0xCF, 0x7675, &buf[pkt_size], buf_size - pkt_size); /* wr CF 7675 */ + /* set rgf_tx_beta_rds:0909 sequence */ + pkt_size += fm_bop_write(0xCC, 0x0227, &buf[pkt_size], buf_size - pkt_size); /* wr CC 227 */ + /* set rgf_tx_beta_pilot :0909 sequence */ + pkt_size += fm_bop_write(0xCE, 0x0764, &buf[pkt_size], buf_size - pkt_size); /* wr CE 764 */ + /* set rgf_phase_gen_rsh */ + pkt_size += fm_bop_modify(0xAD, 0xFFEF, 0x0000, &buf[pkt_size], buf_size - pkt_size); /* wr AD D4 =0 */ + pkt_size += fm_bop_modify(0xAD, 0xFFF8, 0x0001, &buf[pkt_size], buf_size - pkt_size); /* wr AD D2:D0=1 */ + /* set rgf_phase_gen_wb */ + pkt_size += fm_bop_modify(0xA8, 0xF000, 0x0222, &buf[pkt_size], buf_size - pkt_size); /* wr A8 D11:D0=222 */ + /* set agc */ + pkt_size += fm_bop_modify(0xAE, 0xFC00, 0x0203, &buf[pkt_size], buf_size - pkt_size); /* wr AE D9:D0=203 */ + /* set rgf_beta_fm */ + pkt_size += fm_bop_write(0xEE, 0x63EB, &buf[pkt_size], buf_size - pkt_size); /* wr EE 63EB */ + /* switch to DSP control */ + pkt_size += fm_bop_write(0x60, 0x000F, &buf[pkt_size], buf_size - pkt_size); /* wr 60 000F */ + + return pkt_size - 4; +} +/* + * mt6630_tx_rdsoff_deviation - deviation (RDS on) + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6630_tx_rdson_deviation(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6630_tx_rdson_deviation_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, RDS_TX_OPCODE, pkt_size); +} + +signed int mt6630_tune_tx_reg_op(unsigned char *buf, signed int buf_size, unsigned short freq, + unsigned short chan_para) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + freq = (freq - 6400) * 2 / 10; + /* Set desired channel & channel parameter */ +#ifdef FM_TUNE_USE_POLL + pkt_size += fm_bop_write(0x6B, 0x0000, &buf[pkt_size], buf_size - pkt_size); +#endif + /* sequence 09/16:0x65 D12=1 for iq switch */ + pkt_size += fm_bop_modify(FM_CHANNEL_SET, 0xEC00, freq | 0x1000, &buf[pkt_size], buf_size - pkt_size); + /* set 0x65[9:0] = 0x029e, => ((97.5 - 64) * 20) */ + /* set iq switch, D12 */ + /* 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); + /* 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); + /* 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); +#endif + + return pkt_size - 4; +} + + +/* + * mt6630_tune_tx - execute tx tune action, + * @buf - target buf + * @buf_size - buffer size + * @freq - 760 ~ 1080, 100KHz unit + * return package size + */ +static signed int mt6630_tune_tx(unsigned char *buf, signed int buf_size, unsigned short freq, + unsigned short chan_para) +{ + signed int pkt_size = 0; + + pkt_size = mt6630_tune_tx_reg_op(buf, buf_size, freq, chan_para); + return fm_op_seq_combine_cmd(buf, FM_TUNE_OPCODE, pkt_size); +} + +signed int mt6630_rds_tx_reg_op(unsigned char *tx_buf, signed int tx_buf_size, unsigned short pi, + unsigned short *ps, unsigned short *other_rds, unsigned char other_rds_cnt) +{ + signed int pkt_size = 4; + signed int i = 0; + + if (tx_buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (tx_buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, tx_buf_size); + return -2; + } + + /* set repeat mode */ + pkt_size += fm_bop_modify(0x88, 0xFFFE, 0x0001, &tx_buf[pkt_size], TX_BUF_SIZE - pkt_size); + /* wr 88[0] = b'1, repeat mode */ + pkt_size += fm_bop_modify(0x88, 0xFFFB, 0x0004, &tx_buf[pkt_size], TX_BUF_SIZE - pkt_size); + /* wr 88[2] = b'1, PI_reg mode */ + pkt_size += fm_bop_write(0x8A, pi, &tx_buf[pkt_size], tx_buf_size - pkt_size); + /* write PI to PI_reg */ + + pkt_size += fm_bop_modify(0x88, 0xFFFD, 0x0002, &tx_buf[pkt_size], TX_BUF_SIZE - pkt_size); + /* wr 88[1] = b'1, addr from host */ + for (i = 0; i < 12; i++) { + pkt_size += fm_bop_write(0x8B, (0x0063 + i), &tx_buf[pkt_size], tx_buf_size - pkt_size); + /* 8B = mem_addr */ + pkt_size += fm_bop_write(0x8C, ps[i], &tx_buf[pkt_size], tx_buf_size - pkt_size); + /* 8C = RDS Tx data */ + } + pkt_size += fm_bop_modify(0x88, 0xFFFD, 0x0000, &tx_buf[pkt_size], TX_BUF_SIZE - pkt_size); + /* wr 88[1] = b'0, clear mem_addr */ + pkt_size += fm_bop_modify(0x88, 0xFFEF, 0x0010, &tx_buf[pkt_size], TX_BUF_SIZE - pkt_size); + /* wr 88[4] = b'1, switch to ps buf */ + /* work around: write at leat one group to normal buffer, otherwise ps buffer can be sent out. */ + pkt_size += fm_bop_write(0x8C, 0, &tx_buf[pkt_size], tx_buf_size - pkt_size); + pkt_size += fm_bop_write(0x8C, 0, &tx_buf[pkt_size], tx_buf_size - pkt_size); + pkt_size += fm_bop_write(0x8C, 0, &tx_buf[pkt_size], tx_buf_size - pkt_size); + pkt_size += fm_bop_write(0x8C, 0, &tx_buf[pkt_size], tx_buf_size - pkt_size); + pkt_size += fm_bop_modify(0x88, 0xFFDF, 0x0020, &tx_buf[pkt_size], TX_BUF_SIZE - pkt_size); + /* wr 88[5] = b'1,clear in_ptr */ + pkt_size += fm_bop_modify(0x88, 0xFFDF, 0x0000, &tx_buf[pkt_size], TX_BUF_SIZE - pkt_size); + /* wr 88[5] = b'0,clear in_ptr */ + + return pkt_size - 4; +} + +/* +*pi: pi code +*ps: block B,C,D +*other_rds: unused +*other_rds_cnt: unused +*/ +static signed int mt6630_rds_tx(unsigned char *tx_buf, signed int tx_buf_size, unsigned short pi, + unsigned short *ps, unsigned short *other_rds, unsigned char other_rds_cnt) +{ + signed int pkt_size = 0; + + pkt_size = mt6630_rds_tx_reg_op(tx_buf, tx_buf_size, pi, ps, other_rds, other_rds_cnt); + return fm_op_seq_combine_cmd(tx_buf, RDS_TX_OPCODE, pkt_size); +} + +static signed int mt6630_Tx_Support(signed int *sup) +{ + *sup = 1; + return 0; +} + +/* +*pi: pi code, +*ps: block B,C,D +*other_rds: NULL now +*other_rds_cnt:0 now +*/ +static signed int MT6630_lib_Rds_Tx_adapter(unsigned short pi, unsigned short *ps, unsigned short *other_rds, + unsigned char other_rds_cnt) +{ + signed int ret = 0; + unsigned short pkt_size = 0; + + WCN_DBG(FM_NTC | RDSC, + "+%s():PI=0x%04x, PS=0x%04x/0x%04x/0x%04x/0x%04x, other_rds_cnt=%d\n", __func__, + pi, ps[0], ps[1], ps[2], ps[3], other_rds_cnt); + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6630_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; +} + +/* +*freq: 8750~10800 +*valid: true-valid channel,false-invalid channel +*return: true- smt success, false-smt fail +*/ +static signed int mt6630_soft_mute_tune_Tx(unsigned short freq, signed int *rssi, bool *valid) +{ + signed int ret = 0; + unsigned short pkt_size; + struct mt6630_full_cqi *p_cqi; + signed int RSSI = 0, PAMD = 0, MR = 0, ATDC = 0; + unsigned int PRX = 0, ATDEV = 0; + unsigned short softmuteGainLvl = 0; + + ret = mt6630_chan_para_get(freq); + if (ret == 2) + ret = fm_set_bits(FM_CHANNEL_SET, 0x2000, 0x0FFF); /* mdf HiLo */ + else + ret = fm_set_bits(FM_CHANNEL_SET, 0x0000, 0x0FFF); /* clear FA/HL/ATJ */ + + fm_reg_write(0x60, 0x0007); + if (mt6630_TDD_chan_check(freq)) + fm_set_bits(0x30, 0x0004, 0xFFF9); /* use TDD solution */ + else + fm_set_bits(0x30, 0x0000, 0xFFF9); /* default use FDD solution */ + fm_reg_write(0x60, 0x000F); + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = fm_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, fm_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (!ret && fm_res) { + WCN_DBG(FM_NTC | CHIP, "smt cqi size %d\n", fm_res->cqi[0]); + p_cqi = (struct mt6630_full_cqi *)&fm_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 ((fm_config.tx_cfg.pamd_th < PAMD) + && (fm_config.tx_cfg.mr_th >= MR) + && (fm_config.tx_cfg.smg_th > softmuteGainLvl)) + *valid = true; + else + *valid = false; + + *rssi = RSSI; + } else { + WCN_DBG(FM_ERR | CHIP, "smt get CQI failed\n"); + return false; + } + WCN_DBG(FM_NTC | CHIP, "valid=%d\n", *valid); + return true; +} + +#define TX_ABANDON_BAND_LOW1 7320 +#define TX_ABANDON_BAND_HIGH1 7450 +#define TX_ABANDON_BAND_LOW2 9760 +#define TX_ABANDON_BAND_HIGH2 9940 +static signed int mt6630_TxScan(unsigned short min_freq, unsigned short max_freq, unsigned short *pFreq, + unsigned short *pScanTBL, unsigned short *ScanTBLsize, unsigned short scandir, + unsigned short space) +{ + signed int i = 0, ret = 0; + unsigned short freq = *pFreq; + unsigned short scan_cnt = *ScanTBLsize; + unsigned short cnt = 0; + signed int rssi = 0; + signed int step; + bool valid = false; + signed int total_no = 0; + + 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, "invalid scan table\n"); + ret = -FM_EPARA; + return 1; + } + if (fm_get_channel_space(freq) == 0) + *pFreq *= 10; + + if (fm_get_channel_space(max_freq) == 0) + max_freq *= 10; + + if (fm_get_channel_space(min_freq) == 0) + min_freq *= 10; + + 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 == FM_SPACE_200K) + step = 20; + else if (space == FM_SPACE_50K) + step = 5; + else + step = 10; + + total_no = (max_freq - min_freq) / step + 1; + if (scandir == FM_TX_SCAN_UP) { + for (i = ((*pFreq - min_freq) / step); i < total_no; i++) { + freq = min_freq + step * i; + + /* FM desense GPS */ + if ((freq >= TX_ABANDON_BAND_LOW1) && (freq <= TX_ABANDON_BAND_HIGH1)) { + freq = TX_ABANDON_BAND_HIGH1 + 10; + i = (freq - min_freq) / step; + } + + if ((freq >= TX_ABANDON_BAND_LOW2) && (freq <= TX_ABANDON_BAND_HIGH2)) { + freq = TX_ABANDON_BAND_HIGH2 + 10; + i = (freq - min_freq) / step; + } + + ret = mt6630_soft_mute_tune_Tx(freq, &rssi, &valid); + if (ret == false) { + WCN_DBG(FM_ERR | CHIP, "mt6630_soft_mute_tune_tx failed\n"); + return 1; + } + + if (valid == true) { + *(pScanTBL + cnt) = freq; /* strore the valid empty channel */ + cnt++; + WCN_DBG(FM_NTC | CHIP, "empty channel:[freq=%d] [cnt=%d]\n", freq, cnt); + } + if (cnt >= scan_cnt) + break; + } + + if (cnt < scan_cnt) { + for (i = 0; i < ((*pFreq - min_freq) / step); i++) { + freq = min_freq + step * i; + + /* FM desense GPS */ + if ((freq >= TX_ABANDON_BAND_LOW1) && (freq <= TX_ABANDON_BAND_HIGH1)) { + freq = TX_ABANDON_BAND_HIGH1 + 10; + i = (freq - min_freq) / step; + } + + if ((freq >= TX_ABANDON_BAND_LOW2) && (freq <= TX_ABANDON_BAND_HIGH2)) { + freq = TX_ABANDON_BAND_HIGH2 + 10; + i = (freq - min_freq) / step; + } + + if (i >= ((*pFreq - min_freq) / step)) + break; + + ret = mt6630_soft_mute_tune_Tx(freq, &rssi, &valid); + if (ret == false) { + WCN_DBG(FM_ERR | CHIP, "mt6630_soft_mute_tune failed\n"); + return 1; + } + + if (valid == true) { + *(pScanTBL + cnt) = freq; /* strore the valid empty channel */ + cnt++; + WCN_DBG(FM_NTC | CHIP, "empty channel:[freq=%d] [cnt=%d]\n", freq, cnt); + } + if (cnt >= scan_cnt) + break; + } + } + } else { + for (i = ((*pFreq - min_freq) / step - 1); i >= 0; i--) { + freq = min_freq + step * i; + + /* FM desense GPS */ + if ((freq >= TX_ABANDON_BAND_LOW1) && (freq <= TX_ABANDON_BAND_HIGH1)) { + freq = TX_ABANDON_BAND_LOW1 - 10; + i = (freq - min_freq) / step; + } + + if ((freq >= TX_ABANDON_BAND_LOW2) && (freq <= TX_ABANDON_BAND_HIGH2)) { + freq = TX_ABANDON_BAND_LOW2 - 10; + i = (freq - min_freq) / step; + } + + ret = mt6630_soft_mute_tune_Tx(freq, &rssi, &valid); + if (ret == false) { + WCN_DBG(FM_ERR | CHIP, "mt6630_soft_mute_tune failed\n"); + return 1; + } + + if (valid == true) { + *(pScanTBL + cnt) = freq; /* strore the valid empty channel */ + cnt++; + WCN_DBG(FM_NTC | CHIP, "empty channel:[freq=%d] [cnt=%d]\n", freq, cnt); + } + if (cnt >= scan_cnt) + break; + } + if (cnt < scan_cnt) { + for (i = (total_no - 1); i > ((*pFreq - min_freq) / step); i--) { + freq = min_freq + step * i; + + /* FM desense GPS */ + if ((freq >= TX_ABANDON_BAND_LOW1) && (freq <= TX_ABANDON_BAND_HIGH1)) { + freq = TX_ABANDON_BAND_LOW1 - 10; + i = (freq - min_freq) / step; + } + + if ((freq >= TX_ABANDON_BAND_LOW2) && (freq <= TX_ABANDON_BAND_HIGH2)) { + freq = TX_ABANDON_BAND_LOW2 - 10; + i = (freq - min_freq) / step; + } + + if (i <= ((*pFreq - min_freq) / step)) + break; + + ret = mt6630_soft_mute_tune_Tx(freq, &rssi, &valid); + if (ret == false) { + WCN_DBG(FM_ERR | CHIP, "mt6630_soft_mute_tune failed\n"); + return 1; + } + + if (valid == true) { + *(pScanTBL + cnt) = freq; /* strore the valid empty channel */ + cnt++; + WCN_DBG(FM_NTC | CHIP, "empty channel:[freq=%d] [cnt=%d]\n", freq, cnt); + } + if (cnt >= scan_cnt) + break; + } + } + } + + *ScanTBLsize = cnt; + WCN_DBG(FM_NTC | CHIP, "completed, [cnt=%d],[freq=%d]\n", cnt, freq); + /* return 875~1080 */ + for (i = 0; i < cnt; i++) { + if (fm_get_channel_space(*(pScanTBL + i)) == 1 && space != FM_SPACE_50K) + *(pScanTBL + i) = *(pScanTBL + i) / 10; + } + WCN_DBG(FM_NTC | CHIP, "-%s():[ret=%d]\n", __func__, ret); + return 0; +} + +static signed int mt6630_PowerUpTx(void) +{ + signed int ret = 0; + unsigned short pkt_size; + unsigned short dataRead = 0; + + WCN_DBG(FM_NTC | CHIP, "pwr on Tx seq......\n"); + + ret = mt6630_pwrup_top_setting(); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "mt6630_pwrup_top_setting failed\n"); + return ret; + } + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + + pkt_size = mt6630_pwrup_clock_on_tx(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, "mt6630_pwrup_clock_on_tx failed\n"); + return ret; + } + + fm_reg_read(0x62, &dataRead); + WCN_DBG(FM_NTC | CHIP, "Tx on chipid=%x\n", dataRead); + + ret = mt6630_pwrup_DSP_download(mt6630_patch_tbl_tx); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "mt6630_pwrup_DSP_download failed\n"); + return ret; + } + + if ((fm_config.aud_cfg.aud_path == FM_AUD_MRGIF) + || (fm_config.aud_cfg.aud_path == FM_AUD_I2S)) { + mt6630_I2s_Setting(FM_I2S_ON, fm_config.aud_cfg.i2s_info.mode, + fm_config.aud_cfg.i2s_info.rate); + /* mtk_wcn_cmb_stub_audio_ctrl((CMB_STUB_AIF_X)CMB_STUB_AIF_2);//no need to do? */ + WCN_DBG(FM_NTC | CHIP, "pwron set I2S on ok\n"); + } + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + + pkt_size = mt6630_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, "mt6630_dig_init failed\n"); + return ret; + } + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + + pkt_size = mt6630_tx_rdson_deviation(cmd_buf, TX_BUF_SIZE); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_RDS_TX, SW_RETRY_CNT, EN_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + if (ret) { + WCN_DBG(FM_ALT | CHIP, "mt6630_tx_rdson_deviation failed\n"); + return ret; + } + + WCN_DBG(FM_DBG | CHIP, "pwr on tx seq ok\n"); + return ret; +} + +static signed int mt6630_PowerDownTx(void) +{ + signed int ret = 0; + + ret = mt6630_PowerDown(); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "mt6630_PowerDownTx failed\n"); + return ret; + } + + return ret; +} + +static unsigned short mt6630_Hside_list_Tx[] = { 7720, 8045 }; + +static bool mt6630_HiSide_chan_check_Tx(unsigned short freq) +{ + /* signed int pos, size; */ + unsigned int i = 0, count = 0; + + /* return 0;//for HQA only: skip FA/HL/ATJ */ + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + if (freq < 6500) + return false; + + count = ARRAY_SIZE(mt6630_Hside_list_Tx); + for (i = 0; i < count; i++) { + if (freq == mt6630_Hside_list_Tx[i]) + return true; + } + + return false; +} + +static bool MT6630_SetFreq_Tx(unsigned short freq) +{ + signed int ret = 0; + unsigned short pkt_size; + unsigned short chan_para = 0; + unsigned short dataRead = 0; + + /* repeat tune due to audio noise workaround */ + fm_reg_read(0x63, &dataRead); + fm_reg_read(0x61, &dataRead); + fm_reg_write(0x63, 0x0); + fm_reg_write(0x61, 0x81); + fm_reg_write(0x61, 0x83); + fm_reg_write(0x61, 0x82); + /*fm_reg_write(0x69, 0x1);*/ + do { + fm_reg_read(0x64, &dataRead); + WCN_DBG(FM_DBG | CHIP, "dataRead = %d\n", dataRead); + } while (dataRead != 2); + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + + pkt_size = mt6630_tx_rdson_deviation(cmd_buf, TX_BUF_SIZE); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_RDS_TX, SW_RETRY_CNT, EN_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + if (ret) { + WCN_DBG(FM_ALT | CHIP, "mt6630_tx_rdson_deviation failed\n"); + return ret; + } + /* repeat tune due to audio noise workaround end */ + + ret = mt6630_RampDown(); + if (ret) { + WCN_DBG(FM_ALT | CHIP, "mt6630_RampDown failed\n"); + return ret; + } + + if (true == mt6630_HiSide_chan_check_Tx(freq)) { + WCN_DBG(FM_DBG | CHIP, "%d chan para = %d\n", (signed int) freq, (signed int) chan_para); + ret = fm_set_bits(FM_CHANNEL_SET, 0x2000, 0x0FFF); /* mdf HiLo */ + } else + ret = fm_set_bits(FM_CHANNEL_SET, 0x0000, 0xEFFF); /* clear HiLo */ + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "fm_set_bits failed\n"); + return ret; + } + /* fm_cb_op->cur_freq_set(freq); */ + /* start tune */ + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6630_tune_tx(cmd_buf, TX_BUF_SIZE, freq, 0); + 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, "mt6630_tune_tx failed\n"); + return ret; + } + + WCN_DBG(FM_DBG | CHIP, "mt6630_tune_tx to %d ok\n", freq); + + return true; +} + +signed int fm_low_ops_register(struct fm_callback *cb, struct fm_basic_interface *bi) +{ + signed int ret = 0; + /* Basic functions. */ + + if (bi == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,bi invalid pointer\n", __func__); + return -FM_EPARA; + } + if (cb->cur_freq_get == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,cb->cur_freq_get invalid pointer\n", __func__); + return -FM_EPARA; + } + if (cb->cur_freq_set == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,cb->cur_freq_set invalid pointer\n", __func__); + return -FM_EPARA; + } + fm_cb_op = cb; + + bi->pwron = mt6630_pwron; + bi->pwroff = mt6630_pwroff; + bi->chipid_get = mt6630_get_chipid; + bi->mute = mt6630_Mute; + bi->rampdown = mt6630_RampDown; + bi->pwrupseq = mt6630_PowerUp; + bi->pwrdownseq = mt6630_PowerDown; + bi->setfreq = mt6630_SetFreq; + /* bi->low_pwr_wa = MT6630fm_low_power_wa_default; */ + bi->i2s_set = mt6630_I2s_Setting; + bi->rssiget = mt6630_GetCurRSSI; + bi->volset = mt6630_SetVol; + bi->volget = mt6630_GetVol; + bi->dumpreg = mt6630_dump_reg; + bi->msget = mt6630_GetMonoStereo; + bi->msset = mt6630_SetMonoStereo; + bi->pamdget = mt6630_GetCurPamd; + /* bi->em = mt6630_em_test; */ + bi->anaswitch = mt6630_SetAntennaType; + bi->anaget = mt6630_GetAntennaType; + bi->caparray_get = mt6630_GetCapArray; + bi->hwinfo_get = mt6630_hw_info_get; + bi->fm_via_bt = MT6630_FMOverBT; + bi->i2s_get = mt6630_i2s_info_get; + bi->is_dese_chan = mt6630_is_dese_chan; + bi->softmute_tune = mt6630_soft_mute_tune; + bi->desense_check = mt6630_desense_check; + bi->cqi_log = mt6630_full_cqi_get; + bi->pre_search = mt6630_pre_search; + bi->restore_search = mt6630_restore_search; + bi->set_search_th = mt6630_set_search_th; + bi->get_aud_info = mt6630fm_get_audio_info; + /*****tx function****/ + bi->tx_support = mt6630_Tx_Support; + bi->pwrupseq_tx = mt6630_PowerUpTx; + bi->tune_tx = MT6630_SetFreq_Tx; + bi->pwrdownseq_tx = mt6630_PowerDownTx; + bi->tx_scan = mt6630_TxScan; + /* need call fm link/cmd */ + bi->rds_tx_adapter = MT6630_lib_Rds_Tx_adapter; + /* bi->tx_pwr_ctrl = MT6630_TX_PWR_CTRL; */ + /* bi->rtc_drift_ctrl = MT6630_RTC_Drift_CTRL; */ + /* bi->tx_desense_wifi = MT6630_TX_DESENSE; */ + + cmd_buf_lock = fm_lock_create("30_cmd"); + ret = fm_lock_get(cmd_buf_lock); + + cmd_buf = fm_zalloc(TX_BUF_SIZE + 1); + + if (!cmd_buf) { + WCN_DBG(FM_ERR | CHIP, "6630 fm lib alloc tx buf failed\n"); + ret = -1; + } + + return ret; +} + +signed int fm_low_ops_unregister(struct fm_basic_interface *bi) +{ + signed int ret = 0; + /* Basic functions. */ + if (bi == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + if (cmd_buf) { + fm_free(cmd_buf); + cmd_buf = NULL; + } + + ret = fm_lock_put(cmd_buf_lock); + fm_memset(bi, 0, sizeof(struct fm_basic_interface)); + return ret; +} diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/mt6630/pub/mt6630_fm_rds.c b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6630/pub/mt6630_fm_rds.c new file mode 100644 index 0000000000000..5f413c6a50de0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6630/pub/mt6630_fm_rds.c @@ -0,0 +1,368 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_interface.h" +#include "fm_stdlib.h" +#include "fm_rds.h" +#include "mt6630_fm_reg.h" +#include "fm_cmd.h" + +static bool bRDS_FirstIn; /* false */ +static unsigned int gBLER_CHK_INTERVAL = 500; +static unsigned short GOOD_BLK_CNT = 0, BAD_BLK_CNT; +static unsigned char BAD_BLK_RATIO; + +static struct fm_basic_interface *fm_bi; + +static bool mt6630_RDS_support(void); +static signed int mt6630_RDS_enable(void); +static signed int mt6630_RDS_disable(void); +static unsigned short mt6630_RDS_Get_GoodBlock_Counter(void); +static unsigned short mt6630_RDS_Get_BadBlock_Counter(void); +static unsigned char mt6630_RDS_Get_BadBlock_Ratio(void); +static unsigned int mt6630_RDS_Get_BlerCheck_Interval(void); +/* static void mt6630_RDS_GetData(unsigned short *data, unsigned short datalen); */ +static void mt6630_RDS_Init_Data(struct rds_t *pstRDSData); + +static bool mt6630_RDS_support(void) +{ + return true; +} + +static signed int mt6630_RDS_enable(void) +{ + signed int ret = 0; + unsigned short dataRead = 0; + + WCN_DBG(FM_DBG | RDSC, "rds enable\n"); + /* ret = fm_reg_read(FM_RDS_CFG0, &dataRead); */ + ret = fm_reg_write(FM_RDS_CFG0, 6); /* set buf_start_th */ + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds enable write 0x80 fail\n"); + return ret; + } + ret = fm_reg_read(FM_MAIN_CTRL, &dataRead); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds enable read 0x63 fail\n"); + return ret; + } + ret = fm_reg_write(FM_MAIN_CTRL, dataRead | (RDS_MASK)); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds enable write 0x63 fail\n"); + return ret; + } + + return ret; +} + +static signed int mt6630_RDS_disable(void) +{ + signed int ret = 0; + unsigned short dataRead = 0; + + WCN_DBG(FM_DBG | RDSC, "rds disable\n"); + ret = fm_reg_read(FM_MAIN_CTRL, &dataRead); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds disable read 0x63 fail\n"); + return ret; + } + ret = fm_reg_write(FM_MAIN_CTRL, dataRead & (~RDS_MASK)); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds disable write 0x63 fail\n"); + return ret; + } + + return ret; +} + +static unsigned short mt6630_RDS_Get_GoodBlock_Counter(void) +{ + unsigned short tmp_reg = 0; + + fm_reg_read(FM_RDS_GOODBK_CNT, &tmp_reg); + GOOD_BLK_CNT = tmp_reg; + WCN_DBG(FM_DBG | RDSC, "get good block cnt:%d\n", (signed int) tmp_reg); + + return tmp_reg; +} + +static unsigned short mt6630_RDS_Get_BadBlock_Counter(void) +{ + unsigned short tmp_reg = 0; + + fm_reg_read(FM_RDS_BADBK_CNT, &tmp_reg); + BAD_BLK_CNT = tmp_reg; + WCN_DBG(FM_DBG | RDSC, "get bad block cnt:%d\n", (signed int) tmp_reg); + + return tmp_reg; +} + +static unsigned char mt6630_RDS_Get_BadBlock_Ratio(void) +{ + unsigned short tmp_reg; + unsigned short gbc; + unsigned short bbc; + + gbc = mt6630_RDS_Get_GoodBlock_Counter(); + bbc = mt6630_RDS_Get_BadBlock_Counter(); + + if ((gbc + bbc) > 0) + tmp_reg = (unsigned char) (bbc * 100 / (gbc + bbc)); + else + tmp_reg = 0; + + BAD_BLK_RATIO = tmp_reg; + WCN_DBG(FM_DBG | RDSC, "get badblock ratio:%d\n", (signed int) tmp_reg); + + return tmp_reg; +} + +static signed int mt6630_RDS_BlockCounter_Reset(void) +{ + mt6630_RDS_disable(); + mt6630_RDS_enable(); + + return 0; +} + +static unsigned int mt6630_RDS_Get_BlerCheck_Interval(void) +{ + return gBLER_CHK_INTERVAL; +} + +static signed int mt6630_RDS_BlerCheck(struct rds_t *dst) +{ + return 0; +} + +#if 0 +static void RDS_Recovery_Handler(void) +{ + unsigned short tempData = 0; + + do { + fm_reg_read(FM_RDS_DATA_REG, &tempData); + fm_reg_read(FM_RDS_POINTER, &tempData); + } while (tempData & 0x3); +} +#endif + +#if 0 +static void mt6630_RDS_GetData(unsigned short *data, unsigned short 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 + + unsigned short CRC = 0, i = 0, RDS_adj = 0, RDSDataCount = 0, FM_WARorrCnt = 0; + unsigned short temp = 0, OutputPofm_s32 = 0; + + WCN_DBG(FM_DBG | RDSC, "get data\n"); + fm_reg_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_reg_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_reg_read(FM_RDS_DATA_REG, &data[0]); + + /* block B data and info handling */ + fm_reg_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_reg_read(FM_RDS_DATA_REG, &data[1]); + + /* block C data and info handling */ + fm_reg_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_reg_read(FM_RDS_DATA_REG, &data[2]); + + /* block D data and info handling */ + fm_reg_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_reg_read(FM_RDS_DATA_REG, &data[3]); + + data[4] = (CRC | RDS_adj | RDSDataCount); + data[5] = FM_WARorrCnt; + + fm_reg_read(FM_RDS_PWDI, &data[6]); + fm_reg_read(FM_RDS_PWDQ, &data[7]); + + fm_reg_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 signed int mt6630_rdsTx_Support(signed int *sup) +{ + *sup = 1; + return 0; +} + +static signed int mt6630_Rds_Tx_Enable(void) +{ + fm_set_bits(0xC7, 0x0800, 0xF7FF); + return 0; +} + +static signed int mt6630_Rds_Tx_Disable(void) +{ + fm_set_bits(0xC7, 0x0000, 0xF7FF); + return 0; +} + +/* +*pi: pi code, +*ps: block B,C,D +*other_rds: NULL now +*other_rds_cnt:0 now +*/ +static signed int mt6630_Rds_Tx(unsigned short pi, unsigned short *ps, unsigned short *other_rds, + unsigned char other_rds_cnt) +{ + return fm_bi->rds_tx_adapter(pi, ps, other_rds, other_rds_cnt); +} + +static void mt6630_RDS_Init_Data(struct rds_t *pstRDSData) +{ + fm_memset(pstRDSData, 0, sizeof(struct rds_t)); + bRDS_FirstIn = 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)); +} + +bool mt6630_RDS_OnOff(struct rds_t *dst, bool bFlag) +{ + signed int ret = 0; + + if (mt6630_RDS_support() == false) { + WCN_DBG(FM_ALT | RDSC, "mt6630_RDS_OnOff failed, RDS not support\n"); + return false; + } + + if (bFlag) { + mt6630_RDS_Init_Data(dst); + ret = mt6630_RDS_enable(); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "mt6630_RDS_OnOff enable failed\n"); + return false; + } + } else { + ret = mt6630_RDS_disable(); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "mt6630_RDS_OnOff disable failed\n"); + return false; + } + } + + return true; +} + +DEFINE_RDSLOG(mt6630_rds_log); + +/* mt6630_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 signed int mt6630_rds_parser(struct rds_t *rds_dst, struct rds_rx_t *rds_raw, + signed int rds_size, unsigned short(*getfreq) (void)) +{ + mt6630_rds_log.log_in(&mt6630_rds_log, rds_raw, rds_size); + return rds_parser(rds_dst, rds_raw, rds_size, getfreq); +} + +static signed int mt6630_rds_log_get(struct rds_rx_t *dst, signed int *dst_len) +{ + return mt6630_rds_log.log_out(&mt6630_rds_log, dst, dst_len); +} + +static signed int mt6630_rds_gc_get(struct rds_group_cnt_t *dst, struct rds_t *rdsp) +{ + return rds_grp_counter_get(dst, &rdsp->gc); +} + +static signed int mt6630_rds_gc_reset(struct rds_t *rdsp) +{ + return rds_grp_counter_reset(&rdsp->gc); +} + +signed int fm_rds_ops_register(struct fm_basic_interface *bi, struct fm_rds_interface *ri) +{ + signed int ret = 0; + + if (ri == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,ri invalid pointer\n", __func__); + return -FM_EPARA; + } + if (bi->rds_tx_adapter == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,bi->rds_tx_adapter invalid pointer\n", __func__); + return -FM_EPARA; + } + fm_bi = bi; + + ri->rds_blercheck = mt6630_RDS_BlerCheck; + ri->rds_onoff = mt6630_RDS_OnOff; + ri->rds_parser = mt6630_rds_parser; + ri->rds_gbc_get = mt6630_RDS_Get_GoodBlock_Counter; + ri->rds_bbc_get = mt6630_RDS_Get_BadBlock_Counter; + ri->rds_bbr_get = mt6630_RDS_Get_BadBlock_Ratio; + ri->rds_bc_reset = mt6630_RDS_BlockCounter_Reset; + ri->rds_bci_get = mt6630_RDS_Get_BlerCheck_Interval; + ri->rds_log_get = mt6630_rds_log_get; + ri->rds_gc_get = mt6630_rds_gc_get; + ri->rds_gc_reset = mt6630_rds_gc_reset; + ri->rdstx_support = mt6630_rdsTx_Support; + ri->rds_tx_enable = mt6630_Rds_Tx_Enable; + ri->rds_tx_disable = mt6630_Rds_Tx_Disable; + ri->rds_tx = mt6630_Rds_Tx; + + return ret; +} + +signed int fm_rds_ops_unregister(struct fm_rds_interface *ri) +{ + signed int ret = 0; + + if (ri == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,ri invalid pointer\n", __func__); + return -FM_EPARA; + } + + fm_bi = NULL; + fm_memset(ri, 0, sizeof(struct fm_rds_interface)); + return ret; +} + diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/mt6631/inc/mt6631_fm_lib.h b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6631/inc/mt6631_fm_lib.h new file mode 100644 index 0000000000000..57356b4cdd5bc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6631/inc/mt6631_fm_lib.h @@ -0,0 +1,73 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ +#ifndef __MT6631_FM_LIB_H__ +#define __MT6631_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 { + mt6631_E1 = 0, + mt6631_E2 +}; + +struct mt6631_fm_cqi { + unsigned short ch; + unsigned short rssi; + unsigned short reserve; +}; + +struct adapt_fm_cqi { + signed int ch; + signed int rssi; + signed int reserve; +}; + +struct mt6631_full_cqi { + unsigned short ch; + unsigned short rssi; + unsigned short pamd; + unsigned short pr; + unsigned short fpamd; + unsigned short mr; + unsigned short atdc; + unsigned short prx; + unsigned short atdev; + unsigned short smg; /* soft-mute gain */ + unsigned short drssi; /* delta rssi */ +}; + +signed int mt6631_fm_low_ops_register(struct fm_callback *cb, struct fm_basic_interface *bi); +signed int mt6631_fm_low_ops_unregister(struct fm_basic_interface *bi); +signed int mt6631_fm_rds_ops_register(struct fm_basic_interface *bi, struct fm_rds_interface *ri); +signed int mt6631_fm_rds_ops_unregister(struct fm_rds_interface *ri); + +#endif diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/mt6631/inc/mt6631_fm_reg.h b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6631/inc/mt6631_fm_reg.h new file mode 100644 index 0000000000000..d4ff954759f65 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6631/inc/mt6631_fm_reg.h @@ -0,0 +1,57 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ +#ifndef __MT6631_FM_REG_H__ +#define __MT6631_FM_REG_H__ + +/* 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, +}; + +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 /* __MT6631_FM_REG_H__ */ diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/mt6631/pub/mt6631_fm_lib.c b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6631/pub/mt6631_fm_lib.c new file mode 100644 index 0000000000000..ff0f1ff1e079f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6631/pub/mt6631_fm_lib.c @@ -0,0 +1,2293 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ +#include +#include + +#include "osal_typedef.h" +#include "stp_exp.h" +#include "wmt_exp.h" +#include "plat.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_cmd.h" + +#include "mt6631_fm_reg.h" +#include "mt6631_fm_lib.h" + +#define HQA_RETURN_ZERO_MAP 0 +#define HQA_ZERO_DESENSE_MAP 0 + +/* #include "mach/mt_gpio.h" */ + +/* #define MT6631_FM_PATCH_PATH "/etc/firmware/mt6631/mt6631_fm_patch.bin" */ +/* #define MT6631_FM_COEFF_PATH "/etc/firmware/mt6631/mt6631_fm_coeff.bin" */ +/* #define MT6631_FM_HWCOEFF_PATH "/etc/firmware/mt6631/mt6631_fm_hwcoeff.bin" */ +/* #define MT6631_FM_ROM_PATH "/etc/firmware/mt6631/mt6631_fm_rom.bin" */ + +static struct fm_patch_tbl mt6631_patch_tbl[5] = { + {FM_ROM_V1, "mt6631_fm_v1_patch.bin", "mt6631_fm_v1_coeff.bin", NULL, NULL}, + {FM_ROM_V2, "mt6631_fm_v2_patch.bin", "mt6631_fm_v2_coeff.bin", NULL, NULL}, + {FM_ROM_V3, "mt6631_fm_v3_patch.bin", "mt6631_fm_v3_coeff.bin", NULL, NULL}, + {FM_ROM_V4, "mt6631_fm_v4_patch.bin", "mt6631_fm_v4_coeff.bin", NULL, NULL}, + {FM_ROM_V5, "mt6631_fm_v5_patch.bin", "mt6631_fm_v5_coeff.bin", NULL, NULL} +}; + +static struct fm_hw_info mt6631_hw_info = { + .chip_id = 0x00006631, + .eco_ver = 0x00000000, + .rom_ver = 0x00000000, + .patch_ver = 0x00000000, + .reserve = 0x00000000, +}; + + +static struct fm_callback *fm_cb_op; + +/* static signed int Chip_Version = mt6631_E1; */ + +/* static bool rssi_th_set = false; */ + +#if 0 /* def CONFIG_MTK_FM_50KHZ_SUPPORT */ +static struct fm_fifo *cqi_fifo; +#endif +static signed int mt6631_is_dese_chan(unsigned short freq); + +#if 0 +static signed int mt6631_mcu_dese(unsigned short freq, void *arg); +static signed int mt6631_gps_dese(unsigned short freq, void *arg); +static signed int mt6631_I2s_Setting(signed int onoff, signed int mode, signed int sample); +#endif +static unsigned short mt6631_chan_para_get(unsigned short freq); +static signed int mt6631_desense_check(unsigned short freq, signed int rssi); +static bool mt6631_TDD_chan_check(unsigned short freq); +static bool mt6631_SPI_hopping_check(unsigned short freq); +static signed int mt6631_soft_mute_tune(unsigned short freq, signed int *rssi, signed int *valid); + +static bool mt6631_do_SPI_hopping_26M(void) +{ + struct fm_ext_interface *ei = &fm_wcn_ops.ei; + signed int hwid = ei->get_hw_version(); + signed int ret = 0; + unsigned int tem = 0, hw_ver_id = 0; + + /* switch SPI clock to 26MHz */ + if (ei->spi_clock_switch) + ret = ei->spi_clock_switch(FM_SPI_SPEED_26M); + else { + ret = -1; + WCN_DBG(FM_ERR | CHIP, "Clock switch cb is null\n"); + } + if (ret) + WCN_DBG(FM_ERR | CHIP, "Switch SPI clock to 26MHz failed\n"); + + ret = fm_host_reg_read(0x80021010, &hw_ver_id); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: read HW ver. failed\n", __func__); + hw_ver_id = hw_ver_id >> 16; + + /* unlock 64M */ + if (hwid >= FM_CONNAC_1_2) { + if (hw_ver_id == 0x1005 || hw_ver_id == 0x1002) { + ret = fm_host_reg_read(0x80023008, &tem); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: unlock 64M reg 0x880023008 failed\n", __func__); + ret = fm_host_reg_write(0x80023008, tem & (~(0x1 << 21))); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: unlock 64M failed\n", __func__); + } else { + ret = fm_host_reg_read(0x81021128, &tem); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: unlock 64M reg 0x81021128 failed\n", __func__); + ret = fm_host_reg_write(0x81021128, tem & ~0x1); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: unlock 64M failed\n", __func__); + ret = fm_host_reg_read(0x81024040, &tem); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: unlock 64M reg 0x81024040 failed\n", __func__); + ret = fm_host_reg_write(0x81024040, tem & ~0x3); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: unlock 64M failed\n", __func__); + } + } else { + ret = fm_host_reg_read(0x80026000, &tem); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: unlock 64M reg 0x80026000 failed\n", __func__); + ret = fm_host_reg_write(0x80026000, tem & (~(0x1 << 28))); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: unlock 64M failed\n", __func__); + } + + if (hwid <= FM_CONNAC_1_2) { + /* Rlease TOP2/64M sleep */ + fm_host_reg_read(0x81021138, &tem); /* Set 0x81021138[7] = 0x0 */ + tem = tem & 0xFFFFFF7F; + ret = fm_host_reg_write(0x81021138, tem); + if (ret) { + WCN_DBG(FM_ALT | CHIP, "Rlease TOP2/64M sleep failed\n"); + return ret; + } + WCN_DBG(FM_DBG | CHIP, "Rlease TOP2/64M sleep\n"); + } + + return ret == 0; +} + +static bool mt6631_do_SPI_hopping_64M(unsigned short freq) +{ + struct fm_ext_interface *ei = &fm_wcn_ops.ei; + signed int hwid = ei->get_hw_version(); + signed int ret = 0; + signed int i = 0; + unsigned int tem = 0, hw_ver_id = 0; + bool flag_spi_hopping = false; + + if (!mt6631_SPI_hopping_check(freq)) + return true; + + /* SPI hopping setting*/ + WCN_DBG(FM_NTC | CHIP, + "%s: freq:%d is SPI hopping channel,turn on 64M PLL\n", + __func__, freq); + + ret = fm_host_reg_read(0x80021010, &hw_ver_id); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: read HW ver. failed\n", __func__); + WCN_DBG(FM_NTC | CHIP, "%s: HW ver. ID = 0x%08x\n", __func__, hw_ver_id); + hw_ver_id = hw_ver_id >> 16; + + if (hwid <= FM_CONNAC_1_2) { + /*Disable TOP2/64M sleep*/ + ret = fm_host_reg_read(0x81021138, &tem); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: read 64M reg 0x81021138 failed\n", __func__); + tem |= 0x00000080; + ret = fm_host_reg_write(0x81021138, tem); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: disable 64M sleep failed\n", __func__); + } + /* lock 64M */ + if (hwid >= FM_CONNAC_1_2) { + if (hw_ver_id == 0x1005 || hw_ver_id == 0x1002) { + ret = fm_host_reg_read(0x80023008, &tem); + if (ret) + WCN_DBG(FM_ERR | CHIP, + "%s: lock 64M reg 0x80023008 failed\n", __func__); + ret = fm_host_reg_write(0x80023008, tem | (0x1 << 21)); + if (ret) + WCN_DBG(FM_ERR | CHIP, + "%s: lock 64M failed\n", __func__); + } else { + ret = fm_host_reg_read(0x81021128, &tem); + if (ret) + WCN_DBG(FM_ERR | CHIP, + "%s: read reg 0x81021128 failed\n", __func__); + ret = fm_host_reg_write(0x81021128, tem | 0x1); + if (ret) + WCN_DBG(FM_ERR | CHIP, + "%s: enable 'rf_spi_div_en' failed\n", __func__); + ret = fm_host_reg_read(0x81024040, &tem); + if (ret) + WCN_DBG(FM_ERR | CHIP, + "%s: lock 64M reg 0x81024040 failed\n", __func__); + ret = fm_host_reg_write(0x81024040, tem | 0x3); + if (ret) + WCN_DBG(FM_ERR | CHIP, + "%s: lock 64M failed\n", __func__); + } + } else { + ret = fm_host_reg_read(0x80026000, &tem); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: lock 64M reg 0x80026000 failed\n", __func__); + ret = fm_host_reg_write(0x80026000, tem | (0x1 << 28)); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: lock 64M failed\n", __func__); + } + + for (i = 0; i < 100; i++) { /*rd 0x8002110C until D27 ==1*/ + + if (hwid >= FM_CONNAC_1_2) + fm_host_reg_read(0x80021118, &tem); + else + fm_host_reg_read(0x8002110C, &tem); + + if (tem & 0x08000000) { + WCN_DBG(FM_NTC | CHIP, "%s: POLLING PLL_RDY success !\n", __func__); + if (ei->spi_clock_switch) + flag_spi_hopping = ei->spi_clock_switch(FM_SPI_SPEED_64M) == 0; + break; + } + fm_delayus(10); + } + if (false == flag_spi_hopping) + WCN_DBG(FM_ERR | CHIP, + "%s: Polling to read rd 0x8002110C[27] ==0x1 failed !\n", + __func__); + + return flag_spi_hopping; +} + +static signed int mt6631_pwron(signed int data) +{ + if (mtk_wcn_wmt_func_on(WMTDRV_TYPE_FM) == MTK_WCN_BOOL_FALSE) { + WCN_DBG(FM_ERR | CHIP, "WMT turn on FM Fail!\n"); + return -FM_ELINK; + } + + WCN_DBG(FM_NTC | CHIP, "WMT turn on FM OK!\n"); + return 0; +} + +static signed int mt6631_pwroff(signed int data) +{ + if (mtk_wcn_wmt_func_off(WMTDRV_TYPE_FM) == MTK_WCN_BOOL_FALSE) { + WCN_DBG(FM_ERR | CHIP, "WMT turn off FM Fail!\n"); + return -FM_ELINK; + } + + WCN_DBG(FM_NTC | CHIP, "WMT turn off FM OK!\n"); + return 0; +} + +static unsigned short mt6631_get_chipid(void) +{ + return 0x6631; +} + +/* MT6631_SetAntennaType - set Antenna type + * @type - 1, Short Antenna; 0, Long Antenna + */ +static signed int mt6631_SetAntennaType(signed int type) +{ + unsigned short dataRead = 0; + + WCN_DBG(FM_DBG | CHIP, "set ana to %s\n", type ? "short" : "long"); + fm_reg_read(FM_MAIN_CG2_CTRL, &dataRead); + + if (type) + dataRead |= ANTENNA_TYPE; + else + dataRead &= (~ANTENNA_TYPE); + + fm_reg_write(FM_MAIN_CG2_CTRL, dataRead); + + return 0; +} + +static signed int mt6631_GetAntennaType(void) +{ + unsigned short dataRead = 0; + + fm_reg_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 signed int mt6631_Mute(bool mute) +{ + signed int ret = 0; + unsigned short dataRead = 0; + + WCN_DBG(FM_DBG | CHIP, "set %s\n", mute ? "mute" : "unmute"); + /* fm_reg_read(FM_MAIN_CTRL, &dataRead); */ + fm_reg_read(0x9C, &dataRead); + + /* fm_top_reg_write(0x0050, 0x00000007); */ + if (mute == 1) + ret = fm_reg_write(0x9C, (dataRead & 0xFFFC) | 0x0003); + else + ret = fm_reg_write(0x9C, (dataRead & 0xFFFC)); + + /* fm_top_reg_write(0x0050, 0x0000000F); */ + + return ret; +} + +static signed int mt6631_rampdown_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* Clear DSP state */ + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFF0, 0x0000, &buf[pkt_size], buf_size - pkt_size); + /* Set DSP ramp down state */ + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFFF, RAMP_DOWN, &buf[pkt_size], buf_size - pkt_size); + /* @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); + /* Clear DSP ramp down state */ + pkt_size += fm_bop_modify(FM_MAIN_CTRL, (~RAMP_DOWN), 0x0000, &buf[pkt_size], buf_size - pkt_size); + /* 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); + + return pkt_size - 4; +} + +void mt8168_spi_hopping_clock_switch(bool clk_64M) +{ + signed int ret = 0; + unsigned int reg_val = 0; + bool flag_spi_hopping = false; + unsigned int i = 0; + + if (clk_64M == true) { + /*Disable TOP2/64M sleep*/ + ret = fm_host_reg_read(0x81021138, ®_val); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: read 64M reg 0x81021138 failed\n", __func__); + reg_val |= (0x1 << 7); + ret = fm_host_reg_write(0x81021138, reg_val); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: disable 64M sleep failed\n", __func__); + + /* lock 64M */ + ret = fm_host_reg_read(0x80023008, ®_val); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: lock 64M reg 0x80023008 failed\n", __func__); + ret = fm_host_reg_write(0x80023008, reg_val | (0x1 << 21)); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: lock 64M failed\n", __func__); + + for (i = 0; i < 100; i++) { /*rd 0x80021118 until D27 ==1*/ + + ret = fm_host_reg_read(0x80021118, ®_val); + + if (reg_val & 0x08000000) { + flag_spi_hopping = true; + WCN_DBG(FM_NTC | CHIP, "%s: POLLING PLL_RDY success !\n", __func__); + /* switch SPI clock to 64MHz */ + ret = fm_host_reg_read(0x81026004, ®_val); /* wr 0x81026004[0] 0x1 D0 */ + reg_val |= 0x00000001; + ret = fm_host_reg_write(0x81026004, reg_val); + break; + } + fm_delayus(10); + } + if (false == flag_spi_hopping) + WCN_DBG(FM_ERR | CHIP, "%s: Polling to read rd 0x80021118[27] == 0x1 failed !\n", __func__); + + flag_spi_hopping = false; + for (i = 0; i < 100; i++) { /*rd 0x8002110C until D27 ==1*/ + ret = fm_host_reg_read(0x81026004, ®_val); + if ((reg_val & 0x00000018) == 0x00000010) { + flag_spi_hopping = true; + WCN_DBG(FM_NTC | CHIP, "%s: POLLING switch command success !\n", __func__); + /* switch SPI clock to 64MHz */ + ret = fm_host_reg_read(0x81026004, ®_val); /* wr 0x81026004[0] 0x1 D0 */ + reg_val |= 0x00000004; + ret = fm_host_reg_write(0x81026004, reg_val); + break; + } + fm_delayus(10); + } + if (false == flag_spi_hopping) + WCN_DBG(FM_ERR | CHIP, "%s: Polling to read rd 0x80021118[4:3] == 0x2 failed !\n", __func__); + } else { + /*set next_cap_en*/ + ret = fm_host_reg_read(0x81026004, ®_val); /* wr 0x81026004[2] 0x0 D0 */ + reg_val &= 0xFFFFFFFB; + ret = fm_host_reg_write(0x81026004, reg_val); + + /*switch back to 26M*/ + ret = fm_host_reg_read(0x81026004, ®_val); /* wr 0x81026004[0] 0x0 D0 */ + reg_val &= 0xFFFFFFFE; + ret = fm_host_reg_write(0x81026004, reg_val); + + flag_spi_hopping = false; + for (i = 0; i < 100; i++) { + ret = fm_host_reg_read(0x81026004, ®_val); + if ((reg_val & 0x00000018) == 0x8) { + flag_spi_hopping = true; + WCN_DBG(FM_NTC | CHIP, "%s: POLLING switch command success !\n", __func__); + + /* turn off 64M PLL request */ + ret = fm_host_reg_read(0x80023008, ®_val); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: turn off 0x80023008 failed\n", __func__); + ret = fm_host_reg_write(0x80023008, reg_val & (~(0x1 << 21))); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: lock 64M failed\n", __func__); + break; + } + fm_delayus(10); + } + if (false == flag_spi_hopping) + WCN_DBG(FM_ERR | CHIP, "%s: Polling to read rd 0x80021118[4:3] == 0x2 failed !\n", __func__); + + ret = fm_host_reg_read(0x81021138, ®_val); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: read 64M reg 0x81021138 failed\n", __func__); + reg_val &= ~(0x1 << 7); + ret = fm_host_reg_write(0x81021138, reg_val); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: enable 64M sleep failed\n", __func__); + } +} + +/* + * mt6631_rampdown - f/w will wait for STC_DONE interrupt + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6631_rampdown(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6631_rampdown_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_RAMPDOWN_OPCODE, pkt_size); +} + +/* FMSYS Ramp Down Sequence*/ +static signed int mt6631_RampDown(void) +{ + signed int ret = 0; + unsigned short pkt_size; + signed int projectid = fm_cb_op->projectid_get(); + /* unsigned short tmp; */ + + WCN_DBG(FM_DBG | CHIP, "ramp down\n"); + + /* unlock 64M */ + if (projectid == 0x8168) + mt8168_spi_hopping_clock_switch(false); + else + mt6631_do_SPI_hopping_26M(); + + /* A0.0 Host control RF register */ + ret = fm_set_bits(0x60, 0x0007, 0xFFF0); /*Set 0x60 [D3:D0] = 0x7*/ + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down HOST control rf: Set 0x60 [D3:D0] = 0x7 failed\n"); + return ret; + } + + /* A0.1 Update FM ADPLL fast tracking mode gain */ + ret = fm_set_bits(0x0F, 0x0000, 0xF800); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down ADPLL gainA/B: Set 0xFH [D10:D0] = 0x000 failed\n"); + return ret; + } + + /* A0.2 Host control RF register */ + ret = fm_set_bits(0x60, 0x000F, 0xFFF0); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down Host control RF registerwr top 0x60 failed\n"); + return ret; + } + /*Clear dsp state*/ + ret = fm_set_bits(0x63, 0x0000, 0xFFF0); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down Host control RF registerwr top 0x63 failed\n"); + return ret; + } + /* Set DSP ramp down state*/ + ret = fm_set_bits(0x63, 0x0010, 0xFFEF); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down Host control RF registerwr top 0x63 failed\n"); + return ret; + } + + ret = fm_reg_write(FM_MAIN_INTRMASK, 0x0000); + if (ret) + WCN_DBG(FM_ERR | CHIP, "ramp down clean FM_MAIN_INTRMASK failed\n"); + + ret = fm_reg_write(FM_MAIN_EXTINTRMASK, 0x0000); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down clean FM_MAIN_EXTINTRMASK failed\n"); + return ret; + } + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6631_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; + } + + ret = fm_reg_write(FM_MAIN_EXTINTRMASK, 0x0021); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down wr FM_MAIN_EXTINTRMASK failed\n"); + return ret; + } + + ret = fm_reg_write(FM_MAIN_INTRMASK, 0x0021); + if (ret) + WCN_DBG(FM_ERR | CHIP, "ramp down wr FM_MAIN_INTRMASK failed\n"); + +#if 0 + fm_delayms(1); + WCN_DBG(FM_DBG | CHIP, "ramp down delay 1ms\n"); + + /* A1.1. Disable aon_osc_clk_cg */ + ret = fm_host_reg_write(0x81024064, 0x00000004); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " Disable aon_osc_clk_cg failed\n"); + return ret; + } + /* A1.1. Disable FMAUD trigger */ + ret = fm_host_reg_write(0x81024058, 0x88800000); + if (ret) { + WCN_DBG(FM_ALT | CHIP, "Disable FMAUD trigger failed\n"); + return ret; + } + + /* A1.1. issue fmsys memory powr down */ + ret = fm_host_reg_write(0x81024054, 0x00000180); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " Issue fmsys memory powr down failed\n"); + return ret; + } +#endif + + return ret; +} + +static signed int mt6631_get_rom_version(void) +{ + unsigned short flag_Romcode = 0; + unsigned short nRomVersion = 0; +#define ROM_CODE_READY 0x0001 + signed int ret = 0; + + /* A1.1 DSP rom code version request enable --- set 0x61 b15=1 */ + fm_set_bits(0x61, 0x8000, 0x7FFF); + + /* A1.2 Release ASIP reset --- set 0x61 b1=1 */ + fm_set_bits(0x61, 0x0002, 0xFFFD); + + /* A1.3 Enable ASIP power --- set 0x61 b0=0 */ + fm_set_bits(0x61, 0x0000, 0xFFFE); + + /* A1.4 Wait until DSP code version ready --- wait loop 1ms */ + do { + fm_delayus(1000); + ret = fm_reg_read(0x84, &flag_Romcode); + /* ret=-4 means signal got when control FM. usually get sig 9 to kill FM process. */ + /* now cancel FM power up sequence is recommended. */ + if (ret) + return ret; + + WCN_DBG(FM_DBG | CHIP, "ROM_CODE_READY flag 0x84=%x\n", flag_Romcode); + } while (flag_Romcode != ROM_CODE_READY); + + + /* A1.5 Read FM DSP code version --- rd 0x83[15:8] */ + fm_reg_read(0x83, &nRomVersion); + nRomVersion = (nRomVersion >> 8); + + /* A1.6 DSP rom code version request disable --- set 0x61 b15=0 */ + fm_set_bits(0x61, 0x0000, 0x7FFF); + + /* A1.7 Reset ASIP --- set 0x61[1:0] = 1 */ + fm_set_bits(0x61, 0x0001, 0xFFFC); + + return (signed int) nRomVersion; +} + +static signed int mt6631_pwrup_clock_on_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + unsigned short de_emphasis; + signed int hwid = fm_wcn_ops.ei.get_hw_version(); + /* unsigned short osc_freq; */ + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + de_emphasis = fm_config.rx_cfg.deemphasis; + de_emphasis &= 0x0001; /* rang 0~1 */ + /* 2,turn on top clock */ + pkt_size += fm_bop_top_write(0xA10, 0xFFFFFFFF, &buf[pkt_size], buf_size - pkt_size); + /* wr top cr a10 ffffffff */ + + /* 3,enable MTCMOS */ + pkt_size += fm_bop_top_write(0x60, 0x00000030, &buf[pkt_size], buf_size - pkt_size); + /* wr top 60 30 */ + + pkt_size += fm_bop_top_write(0x60, 0x00000035, &buf[pkt_size], buf_size - pkt_size); + /* wr top 60 35 */ + pkt_size += fm_bop_udelay(10, &buf[pkt_size], buf_size - pkt_size); + /* delay 10us */ + pkt_size += fm_bop_top_write(0x60, 0x00000015, &buf[pkt_size], buf_size - pkt_size); + /* wr top 60 15 */ + pkt_size += fm_bop_top_write(0x60, 0x00000005, &buf[pkt_size], buf_size - pkt_size); + /* wr top 60 5 */ + + pkt_size += fm_bop_udelay(10, &buf[pkt_size], buf_size - pkt_size); + /* delay 10us */ + pkt_size += fm_bop_top_write(0x60, 0x00000045, &buf[pkt_size], buf_size - pkt_size); + /* wr top 60 45 */ + + /* 4,set comspi fm slave dumy count */ + if (hwid >= FM_CONNAC_1_5) + pkt_size += fm_bop_write(0x7f, 0x801f, &buf[pkt_size], buf_size - pkt_size); /* wr 7f 801f */ + else + pkt_size += fm_bop_write(0x7f, 0x800f, &buf[pkt_size], buf_size - pkt_size); /* wr 7f 800f */ + + /* A. FM digital clock enable */ + /* A1. Enable digital OSC */ + if (hwid <= FM_CONNAC_1_2) + pkt_size += fm_bop_write(0x60, 0x00000001, &buf[pkt_size], buf_size - pkt_size); /* wr 60 1 */ + + /* A2. Wait 3ms */ + pkt_size += fm_bop_udelay(3000, &buf[pkt_size], buf_size - pkt_size); + + /* A3. Set OSC clock output to FM */ + if (hwid <= FM_CONNAC_1_2) + pkt_size += fm_bop_write(0x60, 0x00000003, &buf[pkt_size], buf_size - pkt_size); /* wr 60 3 */ + /* A4. Release HW clock gating*/ + pkt_size += fm_bop_write(0x60, 0x00000007, &buf[pkt_size], buf_size - pkt_size); /* wr 60 7 */ + /* Enable DSP auto clock gating */ + pkt_size += fm_bop_write(0x70, 0x0040, &buf[pkt_size], buf_size - pkt_size); /* wr 70 0040 */ + /* A7. Deemphasis setting: Set 0 for 50us, Set 1 for 75us */ + pkt_size += fm_bop_modify(0x61, ~DE_EMPHASIS, (de_emphasis << 12), &buf[pkt_size], buf_size - pkt_size); + + return pkt_size - 4; +} +/* + * mt6631_pwrup_clock_on - Wholechip FM Power Up: step 1, FM Digital Clock enable + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6631_pwrup_clock_on(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6631_pwrup_clock_on_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +static signed int mt6631_pwrup_digital_init_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* Part D FM RF&ADPLL divider setting */ + + /* D2.1 set cell mode */ + /* wr 30 D3:D2 00:FDD(default),01:both.10: TDD, 11 FDD */ + /* pkt_size += fm_bop_modify(0x30, 0xFFF3, 0x0000, &buf[pkt_size], buf_size - pkt_size); */ + + /* D2.2 set ADPLL divider */ + pkt_size += fm_bop_write(0x21, 0xE000, &buf[pkt_size], buf_size - pkt_size); /* wr 21 E000 */ + /* D2.3 set SDM coeff0_H */ + pkt_size += fm_bop_write(0xD8, 0x03F0, &buf[pkt_size], buf_size - pkt_size); /* wr D8 0x03F0 */ + /* D2.4 set SDM coeff0_L */ + pkt_size += fm_bop_write(0xD9, 0x3F04, &buf[pkt_size], buf_size - pkt_size); /* wr D9 0x3F04 */ + /* D2.5 set SDM coeff1_H */ + pkt_size += fm_bop_write(0xDA, 0x0014, &buf[pkt_size], buf_size - pkt_size); /* wr DA 0x0014 */ + /* D2.6 set SDM coeff1_L */ + pkt_size += fm_bop_write(0xDB, 0x2A38, &buf[pkt_size], buf_size - pkt_size); /* wr DB 0x2A38 */ + /* D2.7 set 26M clock */ + pkt_size += fm_bop_write(0x23, 0x4000, &buf[pkt_size], buf_size - pkt_size); /* wr 23 4000 */ + + /* Part E: FM Digital Init: fm_rgf_maincon */ + + /* E4. Set appropriate interrupt mask behavior as desired */ + /* Enable stc_done_mask, Enable rgf_rds_mask*/ + pkt_size += fm_bop_write(0x6A, 0x0021, &buf[pkt_size], buf_size - pkt_size); /* wr 6A 0021 */ + pkt_size += fm_bop_write(0x6B, 0x0021, &buf[pkt_size], buf_size - pkt_size); /* wr 6B 0021 */ + + /* E5. Enable hw auto control */ + pkt_size += fm_bop_write(0x60, 0x0000000F, &buf[pkt_size], buf_size - pkt_size); /* wr 60 f */ + + /* E6. Release ASIP reset */ + pkt_size += fm_bop_modify(0x61, 0xFFFD, 0x0002, &buf[pkt_size], buf_size - pkt_size); /* wr 61 D1=1 */ + /* E7. Enable ASIP power */ + pkt_size += fm_bop_modify(0x61, 0xFFFE, 0x0000, &buf[pkt_size], buf_size - pkt_size); /* wr 61 D0=0 */ + + /* E8 */ + pkt_size += fm_bop_udelay(100000, &buf[pkt_size], buf_size - pkt_size); /* delay 100ms */ + /* E9. Check HW initial complete */ + pkt_size += fm_bop_rd_until(0x64, 0x001F, 0x0002, &buf[pkt_size], buf_size - pkt_size); /* Poll 64[0~4] = 2 */ + + return pkt_size - 4; +} + +/* + * mt6631_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 + */ +static signed int mt6631_pwrup_digital_init(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6631_pwrup_digital_init_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +static signed int mt6631_pwrup_fine_tune_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* F1 set host control RF register */ + pkt_size += fm_bop_write(0x60, 0x00000007, &buf[pkt_size], buf_size - pkt_size); + /* F2 fine tune RF setting */ + pkt_size += fm_bop_write(0x01, 0xBEE8, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x03, 0xF6ED, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x15, 0x0D80, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x16, 0x0068, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x17, 0x092A, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x34, 0x807F, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x35, 0x311E, &buf[pkt_size], buf_size - pkt_size); + /* F3 set DSP control RF register */ + pkt_size += fm_bop_write(0x60, 0x0000000F, &buf[pkt_size], buf_size - pkt_size); + + return pkt_size - 4; +} + +/* + * mt6631_pwrup_fine_tune - Wholechip FM Power Up: step 5, FM RF fine tune setting + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6631_pwrup_fine_tune(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6631_pwrup_fine_tune_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +static signed int mt6631_pwrdown_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* A1:set audio output I2S Tx mode: */ + pkt_size += fm_bop_modify(0x9B, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size); + + /* B0:Disable HW clock control */ + pkt_size += fm_bop_write(0x60, 0x330F, &buf[pkt_size], buf_size - pkt_size); + /* B1:Reset ASIP : Set 0x61, [D1 = 0, D0=1] */ + pkt_size += fm_bop_modify(0x61, 0xFFFD, 0x0001, &buf[pkt_size], buf_size - pkt_size); + + /* B2:digital core + digital rgf reset */ + pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size); + + /* B3:Disable all clock */ + pkt_size += fm_bop_write(0x60, 0x0000, &buf[pkt_size], buf_size - pkt_size); + /* B4:Reset rgfrf */ + pkt_size += fm_bop_write(0x60, 0x4000, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x60, 0x0000, &buf[pkt_size], buf_size - pkt_size); + + /* MTCMOS power off */ + /* C0:disable MTCMOS */ + pkt_size += fm_bop_top_write(0x60, 0x0005, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_top_write(0x60, 0x0015, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_top_write(0x60, 0x0035, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_top_write(0x60, 0x0030, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_top_rd_until(0x60, 0x0000000A, 0x0, &buf[pkt_size], buf_size - pkt_size); + + return pkt_size - 4; +} +/* + * mt6631_pwrdown - Wholechip FM Power down: Digital Modem Power Down + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6631_pwrdown(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6631_pwrdown_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +static signed int mt6631_tune_reg_op(unsigned char *buf, signed int buf_size, unsigned short freq, + unsigned short chan_para) +{ + signed int pkt_size = 4; + + WCN_DBG(FM_ALT | CHIP, "%s enter mt6631_tune function\n", __func__); + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* A2 Enable hardware controlled tuning sequence */ + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFF8, TUNE, &buf[pkt_size], buf_size - pkt_size);/*Set 0x63 D0=1*/ + /* Wait for STC_DONE interrupt */ + +#ifdef FM_TUNE_USE_POLL + /* A3 Wait for STC_DONE interrupt */ + /* A4 Wait for STC_DONE interrupt status flag */ + pkt_size += fm_bop_rd_until(FM_MAIN_INTR, FM_INTR_STC_DONE, + FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size); + /* A6 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); +#endif + + pkt_size += fm_bop_udelay(100000, &buf[pkt_size], buf_size - pkt_size); + WCN_DBG(FM_ALT | CHIP, "mt6631_tune delay 100 ms wait 0x69 to change\n"); + + WCN_DBG(FM_ALT | CHIP, "%s leave mt6631_tune function\n", __func__); + + return pkt_size - 4; +} + +/* + * mt6631_tune - execute tune action, + * @buf - target buf + * @buf_size - buffer size + * @freq - 760 ~ 1080, 100KHz unit + * return package size + */ +static signed int mt6631_tune(unsigned char *buf, signed int buf_size, unsigned short freq, + unsigned short chan_para) +{ + signed int pkt_size = 0; + + pkt_size = mt6631_tune_reg_op(buf, buf_size, freq, chan_para); + return fm_op_seq_combine_cmd(buf, FM_TUNE_OPCODE, pkt_size); +} + +/* + * mt6631_pwrup_DSP_download - execute dsp/coeff patch dl action, + * @patch_tbl - current chip patch table + * return patch dl ok or not + */ +static signed int mt6631_pwrup_DSP_download(struct fm_patch_tbl *patch_tbl) +{ +#define PATCH_BUF_SIZE (4096*6) + signed int ret = 0; + signed int patch_len = 0; + unsigned char *dsp_buf = NULL; + unsigned short tmp_reg = 0; + + mt6631_hw_info.eco_ver = (signed int) mtk_wcn_wmt_ic_info_get(1); + WCN_DBG(FM_DBG | CHIP, "ECO version:0x%08x\n", mt6631_hw_info.eco_ver); + + /* Wholechip FM Power Up: step 3, get mt6631 DSP ROM version */ + ret = mt6631_get_rom_version(); + if (ret >= 0) { + mt6631_hw_info.rom_ver = ret; + WCN_DBG(FM_NTC | CHIP, "%s ROM version: v%d\n", __func__, mt6631_hw_info.rom_ver); + } else { + WCN_DBG(FM_ERR | CHIP, "get ROM version failed\n"); + if (ret == -4) + WCN_DBG(FM_ERR | CHIP, "signal got when control FM, usually get sig 9 to kill FM process.\n"); + /* now cancel FM power up sequence is recommended. */ + goto out; + } + + /* Wholechip FM Power Up: step 4 download patch */ + dsp_buf = fm_vmalloc(PATCH_BUF_SIZE); + if (!dsp_buf) { + WCN_DBG(FM_ALT | CHIP, "-ENOMEM\n"); + return -ENOMEM; + } + + patch_len = fm_get_patch_path(mt6631_hw_info.rom_ver, dsp_buf, PATCH_BUF_SIZE, patch_tbl); + if (patch_len <= 0) { + WCN_DBG(FM_ALT | CHIP, " fm_get_patch_path failed\n"); + ret = patch_len; + goto out; + } + + ret = fm_download_patch((const unsigned char *)dsp_buf, patch_len, IMG_PATCH); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " DL DSPpatch failed\n"); + goto out; + } + + patch_len = fm_get_coeff_path(mt6631_hw_info.rom_ver, dsp_buf, PATCH_BUF_SIZE, patch_tbl); + if (patch_len <= 0) { + WCN_DBG(FM_ALT | CHIP, " fm_get_coeff_path failed\n"); + ret = patch_len; + goto out; + } + + mt6631_hw_info.rom_ver += 1; + + tmp_reg = dsp_buf[38] | (dsp_buf[39] << 8); /* to be confirmed */ + mt6631_hw_info.patch_ver = (signed int) tmp_reg; + WCN_DBG(FM_NTC | CHIP, "Patch version: 0x%08x\n", mt6631_hw_info.patch_ver); + + ret = fm_download_patch((const unsigned char *)dsp_buf, patch_len, IMG_COEFFICIENT); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " Download DSP coefficient failed\n"); + goto out; + } + + /* Download HWACC coefficient */ + fm_reg_write(0x92, 0x0000); + fm_reg_write(0x90, 0x0040); /* Reset download control */ + fm_reg_write(0x90, 0x0000); /* Disable memory control from host*/ +out: + if (dsp_buf) + fm_vfree(dsp_buf); + return ret; +} +static void mt6631_show_reg(void) +{ + unsigned int host_reg[3] = {0}; + unsigned int debug_reg1[3] = {0}; + unsigned short debug_reg2[3] = {0}; + + fm_host_reg_read(0x81024030, &host_reg[0]); + fm_host_reg_read(0x81021234, &host_reg[1]); + fm_host_reg_read(0x81021138, &host_reg[2]); + WCN_DBG(FM_ALT | CHIP, + "host read 0x81024030 = 0x%08x, 0x81021234 = 0x%08x, 0x81021138 = 0x%08x\n", + host_reg[0], host_reg[1], host_reg[2]); + + fm_top_reg_read(0x00c0, &debug_reg1[0]); + fm_top_reg_read(0x00c8, &debug_reg1[1]); + fm_top_reg_read(0x0060, &debug_reg1[2]); + fm_reg_read(0x7f, &debug_reg2[0]); + fm_reg_read(0x62, &debug_reg2[1]); + fm_reg_read(0x60, &debug_reg2[2]); + WCN_DBG(FM_ALT | CHIP, + "top cr 0xc0 = 0x%08x, 0xc8 = 0x%08x, 0x60 = 0x%08x, fmreg 0x7f = 0x%08x, 0x62 = 0x%08x, 0x60 = 0x%08x\n", + debug_reg1[0], debug_reg1[1], debug_reg1[2], debug_reg2[0], debug_reg2[1], debug_reg2[2]); +} + +static signed int mt6631_PowerUp(unsigned short *chip_id, unsigned short *device_id) +{ + signed int ret = 0; + unsigned short pkt_size; + unsigned short tmp_reg = 0; + unsigned int tem = 0; + unsigned int host_reg = 0; + signed int hwid = fm_wcn_ops.ei.get_hw_version(); + + if (chip_id == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (device_id == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + WCN_DBG(FM_DBG | CHIP, "pwr on seq......\n"); + + /* Wholechip FM Power Up: step 1, set common SPI parameter */ + if (hwid >= FM_CONNAC_1_5) + ret = fm_host_reg_write(0x8102600C, 0x0000801F); + else + ret = fm_host_reg_write(0x8102600C, 0x0000800F); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup set CSPI failed\n"); + return ret; + } + + if (hwid >= FM_CONNAC_1_0) { + /* Set top_clk_en_adie to trigger sleep controller before FM power on */ + if (hwid >= FM_CONNAC_1_5) { + ret = fm_host_reg_write(0x81021500, 0x00000003); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup set top_clk_en_adie failed\n"); + return ret; + } + } else { + fm_host_reg_read(0x81021500, &tem); /* Set 0x81021500[1] = 0x1 */ + tem = tem | 0x00000002; + fm_host_reg_write(0x81021500, tem); + } + + /* Disable 26M crystal sleep */ + fm_host_reg_read(0x81021200, &tem); /* Set 0x81021200[23] = 0x1 */ + tem = tem | 0x00800000; + fm_host_reg_write(0x81021200, tem); + } else { + /* Set top_clk_en_adie to trigger sleep controller before FM power on */ + fm_host_reg_read(0x81024030, &tem); /* Set 0x81024030[1] = 0x1 */ + tem = tem | 0x00000002; + fm_host_reg_write(0x81024030, tem); + + /* Disable 26M crystal sleep */ + fm_host_reg_read(0x81021234, &tem); /* Set 0x81021234[7] = 0x1 */ + tem = tem | 0x00000080; + fm_host_reg_write(0x81021234, tem); + } + + /* turn on RG_TOP_BGLDO */ + ret = fm_top_reg_read(0x00c0, &host_reg); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "power up read top 0xc0 failed\n"); + return ret; + } + ret = fm_top_reg_write(0x00c0, host_reg | (0x3 << 27)); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "power up write top 0xc0 failed\n"); + return ret; + } + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + + pkt_size = mt6631_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, "mt6631_pwrup_clock_on failed\n"); + return ret; + } + + /* Wholechip FM Power Up: step 2, read HW version */ + mt6631_show_reg(); + fm_reg_read(0x62, &tmp_reg); + /* chip_id = tmp_reg; */ + if (tmp_reg == 0x6631) + *chip_id = 0x6631; + *device_id = tmp_reg; + mt6631_hw_info.chip_id = (signed int) tmp_reg; + WCN_DBG(FM_DBG | CHIP, "chip_id:0x%04x\n", tmp_reg); + + if ((mt6631_hw_info.chip_id != 0x6631)) { + mt6631_show_reg(); + WCN_DBG(FM_NTC | CHIP, "fm sys error, reset hw, chip_id = 0x%08x\n", mt6631_hw_info.chip_id); + return -FM_EFW; + + } + /* Wholechip FM Power Up: step 3, patch download */ + ret = mt6631_pwrup_DSP_download(mt6631_patch_tbl); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "mt6631_pwrup_DSP_download failed\n"); + return ret; + } + + /* Wholechip FM Power Up: step 4, FM Digital Init: fm_rgf_maincon */ + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6631_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, "mt6631_pwrup_digital_init failed\n"); + return ret; + } + + /* Wholechip FM Power Up: step 5, FM RF fine tune setting */ + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6631_pwrup_fine_tune(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, "mt6631_pwrup_fine_tune failed\n"); + return ret; + } + + /* Enable connsys FM 2 wire RX */ + fm_reg_write(0x9B, 0xF9AB); /* G2: Set audio output i2s TX mode */ + fm_host_reg_write(0x81024064, 0x00000014); /* G3: Enable aon_osc_clk_cg */ + /* G4: Enable FMAUD trigger, 20170119 */ + if (hwid >= FM_CONNAC_1_5) + fm_host_reg_write(0x81024058, 0x888100C3); + else + fm_host_reg_write(0x81024058, 0x888100F3); + fm_host_reg_write(0x81024054, 0x00000100); /* G5: Release fmsys memory power down*/ + + WCN_DBG(FM_NTC | CHIP, "pwr on seq ok\n"); + + return ret; +} + +static signed int mt6631_PowerDown(void) +{ + signed int ret = 0; + unsigned int tem = 0; + unsigned short pkt_size; + signed int hwid = fm_wcn_ops.ei.get_hw_version(); + /* unsigned int host_reg = 0; */ + + WCN_DBG(FM_DBG | CHIP, "pwr down seq\n"); + + /* A0.1. Disable aon_osc_clk_cg */ + ret = fm_host_reg_write(0x81024064, 0x00000004); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " Disable aon_osc_clk_cg failed\n"); + return ret; + } + /* A0.1. Disable FMAUD trigger */ + ret = fm_host_reg_write(0x81024058, 0x88800000); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " Disable FMAUD trigger failed\n"); + return ret; + } + + /* A0.1. issue fmsys memory powr down */ + ret = fm_host_reg_write(0x81024054, 0x00000180); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " Issue fmsys memory powr down failed\n"); + return ret; + } + + mt6631_do_SPI_hopping_26M(); + + /* Enable 26M crystal sleep */ + if (hwid >= FM_CONNAC_1_0 && hwid <= FM_CONNAC_1_2) { + WCN_DBG(FM_DBG | CHIP, "PowerDown: Enable 26M crystal sleep,Set 0x81021200[23] = 0x0\n"); + fm_host_reg_read(0x81021200, &tem); /* Set 0x81021200[23] = 0x0 */ + tem = tem & 0xFF7FFFFF; + fm_host_reg_write(0x81021200, tem); + } else { + WCN_DBG(FM_DBG | CHIP, "PowerDown: Enable 26M crystal sleep,Set 0x81021234[7] = 0x0\n"); + fm_host_reg_read(0x81021234, &tem); /* Set 0x81021234[7] = 0x0 */ + tem = tem & 0xFFFFFF7F; + fm_host_reg_write(0x81021234, tem); + } + + if (ret) + WCN_DBG(FM_ALT | CHIP, "PowerDown: Enable 26M crystal sleep,Set 0x81021234[7] = 0x0 failed\n"); + + /* A0:set audio output I2X Rx mode: */ + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6631_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, "mt6631_pwrdown failed\n"); + return ret; + } + /* FIX_ME, disable ext interrupt */ + /* fm_reg_write(FM_MAIN_EXTINTRMASK, 0x00); */ + + + /* D0. Clear top_clk_en_adie to indicate sleep controller after FM power off */ + /* ret = fm_host_reg_read(0x80101030, &host_reg); + * if (ret) { + * WCN_DBG(FM_ALT | CHIP, " pwroff read 0x80100030 failed\n"); + * return ret; + * } + * ret = fm_host_reg_write(0x80101030, host_reg & (~(0x1 << 1))); + * if (ret) { + * WCN_DBG(FM_ALT | CHIP, " pwroff disable top_ck_en_adie failed\n"); + * return ret; + * } + */ + return ret; +} + +/* just for dgb */ +#if 0 +static void mt6631_bt_write(unsigned int addr, unsigned int val) +{ + unsigned int tem, i = 0; + + fm_host_reg_write(0x80103020, addr); + fm_host_reg_write(0x80103024, val); + fm_host_reg_read(0x80103000, &tem); + while ((tem == 4) && (i < 1000)) { + i++; + fm_host_reg_read(0x80103000, &tem); + } +} +#endif + +static bool mt6631_SetFreq(unsigned short freq) +{ + signed int ret = 0; + unsigned short pkt_size; + unsigned short chan_para = 0; + unsigned short freq_reg = 0; + unsigned short tmp_reg[6] = {0}; + signed int projectid = fm_cb_op->projectid_get(); + + fm_cb_op->cur_freq_set(freq); + +#if 0 + /* MCU clock adjust if need */ + ret = mt6631_mcu_dese(freq, NULL); + if (ret < 0) + WCN_DBG(FM_ERR | MAIN, "mt6631_mcu_dese FAIL:%d\n", ret); + + WCN_DBG(FM_INF | MAIN, "MCU %d\n", ret); + + /* GPS clock adjust if need */ + ret = mt6631_gps_dese(freq, NULL); + if (ret < 0) + WCN_DBG(FM_ERR | MAIN, "mt6631_gps_dese FAIL:%d\n", ret); + + WCN_DBG(FM_INF | MAIN, "GPS %d\n", ret); +#endif + + /* A0. Host contrl RF register */ + ret = fm_set_bits(0x60, 0x0007, 0xFFF0); /* Set 0x60 [D3:D0] = 0x07*/ + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Host Control RF register 0x60 = 0x7 failed\n", __func__); + + /* A0.1 Update FM ADPLL fast tracking mode gain */ + ret = fm_set_bits(0x0F, 0x0455, 0xF800); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Set FM ADPLL gainA/B=0x455 failed\n", __func__); + + /* A0.2 Set FMSYS cell mode */ + if (mt6631_TDD_chan_check(freq)) { + ret = fm_set_bits(0x30, 0x0008, 0xFFF3); /* use TDD solution */ + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: freq[%d]: use TDD solution failed\n", __func__, freq); + } else { + ret = fm_set_bits(0x30, 0x0000, 0xFFF3); /* default use FDD solution */ + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: freq[%d]: default use FDD solution failed\n", __func__, freq); + } + + /* A0.3 Host control RF register */ + ret = fm_set_bits(0x60, 0x000F, 0xFFF0); /* Set 0x60 [D3:D0] = 0x0F*/ + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Set 0x60 [D3:D0] = 0x0F failed\n", __func__); + + /* A1 Get Channel parameter from map list*/ + + chan_para = mt6631_chan_para_get(freq); + WCN_DBG(FM_DBG | CHIP, "%s: %d chan para = %d\n", __func__, (signed int) freq, (signed int) chan_para); + + freq_reg = freq; + if (fm_get_channel_space(freq_reg) == 0) + freq_reg *= 10; + + freq_reg = (freq_reg - 6400) * 2 / 10; + + /*A1 Set rgfrf_chan = XXX*/ + ret = fm_set_bits(0x65, freq_reg, 0xFC00); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "%s: set rgfrf_chan = xxx = %d failed\n", __func__, freq_reg); + return false; + } + + ret = fm_set_bits(0x65, (chan_para << 12), 0x0FFF); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x65 failed\n"); + return false; + } + + /* SPI hoppint setting*/ + if (mt6631_SPI_hopping_check(freq)) { + + WCN_DBG(FM_NTC | CHIP, "%s: freq:%d is SPI hopping channel,turn on 64M PLL\n", __func__, freq); + + if (projectid == 0x8168) { + mt8168_spi_hopping_clock_switch(true); + } else { + if (!mt6631_do_SPI_hopping_64M(freq)) + WCN_DBG(FM_ERR | CHIP, "%s: spi hopping fail!\n", __func__); + } + } + + /* A0. Host contrl RF register */ + ret = fm_set_bits(0x60, 0x0007, 0xFFF0); /* Set 0x60 [D3:D0] = 0x07*/ + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Host Control RF register 0x60 = 0x7 failed\n", __func__); + + + fm_reg_read(0x62, &tmp_reg[0]); + fm_reg_read(0x64, &tmp_reg[1]); + fm_reg_read(0x69, &tmp_reg[2]); + fm_reg_read(0x6a, &tmp_reg[3]); + fm_reg_read(0x6b, &tmp_reg[4]); + fm_reg_read(0x9b, &tmp_reg[5]); + + WCN_DBG(FM_ALT | CHIP, "%s: Before tune--0x62 0x64 0x69 0x6a 0x6b 0x9b = %04x %04x %04x %04x %04x %04x\n", + __func__, + tmp_reg[0], + tmp_reg[1], + tmp_reg[2], + tmp_reg[3], + tmp_reg[4], + tmp_reg[5]); + + /* A0.3 Host control RF register */ + ret = fm_set_bits(0x60, 0x000F, 0xFF00); /* Set 0x60 [D3:D0] = 0x0F*/ + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Set 0x60 [D3:D0] = 0x0F failed\n", __func__); + + if (FM_LOCK(cmd_buf_lock)) + return false; + pkt_size = mt6631_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); + + + /* A0. Host contrl RF register */ + ret = fm_set_bits(0x60, 0x0007, 0xFFF0); /* Set 0x60 [D3:D0] = 0x07*/ + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Host Control RF register 0x60 = 0x7 failed\n", __func__); + + memset(tmp_reg, 0, sizeof(tmp_reg[0])*6); + + fm_reg_read(0x62, &tmp_reg[0]); + fm_reg_read(0x64, &tmp_reg[1]); + fm_reg_read(0x69, &tmp_reg[2]); + fm_reg_read(0x6a, &tmp_reg[3]); + fm_reg_read(0x6b, &tmp_reg[4]); + fm_reg_read(0x9b, &tmp_reg[5]); + + WCN_DBG(FM_ALT | CHIP, "%s: After tune--0x62 0x64 0x69 0x6a 0x6b 0x9b = %04x %04x %04x %04x %04x %04x\n", + __func__, + tmp_reg[0], + tmp_reg[1], + tmp_reg[2], + tmp_reg[3], + tmp_reg[4], + tmp_reg[5]); + + /* A0.3 Host control RF register */ + ret = fm_set_bits(0x60, 0x000F, 0xFF00); /* Set 0x60 [D3:D0] = 0x0F*/ + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Set 0x60 [D3:D0] = 0x0F failed\n", __func__); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "%s: mt6631_tune failed\n", __func__); + return false; + } + + WCN_DBG(FM_DBG | CHIP, "%s: set freq to %d ok\n", __func__, freq); +#if 0 + /* ADPLL setting for dbg */ + fm_top_reg_write(0x0050, 0x00000007); + fm_top_reg_write(0x0A08, 0xFFFFFFFF); + mt6631_bt_write(0x82, 0x11); + mt6631_bt_write(0x83, 0x11); + mt6631_bt_write(0x84, 0x11); + fm_top_reg_write(0x0040, 0x1C1C1C1C); + fm_top_reg_write(0x0044, 0x1C1C1C1C); + fm_reg_write(0x70, 0x0010); + /*0x0806 DCO clk + *0x0802 ref clk + *0x0804 feedback clk + */ + fm_reg_write(0xE0, 0x0806); +#endif + return true; +} + +#if 0 +/* +* mt6631_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 true:seek success; false:seek failed +*/ +static bool mt6631_Seek(unsigned short min_freq, unsigned short max_freq, unsigned short *pFreq, + unsigned short seekdir, unsigned short space) +{ + signed int ret = 0; + unsigned short pkt_size, temp; + + mt6631_RampDown(); + fm_reg_read(FM_MAIN_CTRL, &temp); + mt6631_Mute(true); + + if (FM_LOCK(cmd_buf_lock)) + return false; + pkt_size = mt6631_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, + fm_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (!ret && fm_res) { + *pFreq = fm_res->seek_result; + /* fm_cb_op->cur_freq_set(*pFreq); */ + } else { + WCN_DBG(FM_ALT | CHIP, "mt6631_seek failed\n"); + return ret; + } + + /* get the result freq */ + WCN_DBG(FM_NTC | CHIP, "seek, result freq:%d\n", *pFreq); + mt6631_RampDown(); + if ((temp & 0x0020) == 0) + mt6631_Mute(false); + + return true; +} +#endif +#define FM_CQI_LOG_PATH "/mnt/sdcard/fmcqilog" + +static signed int mt6631_full_cqi_get(signed int min_freq, signed int max_freq, signed int space, signed int cnt) +{ + signed int ret = 0; + unsigned short pkt_size; + unsigned short freq, orig_freq; + signed int i, j, k; + signed int space_val, max, min, num; + struct mt6631_full_cqi *p_cqi; + unsigned char *cqi_log_title = "Freq, RSSI, PAMD, PR, FPAMD, MR, ATDC, PRX, ATDEV, SMGain, DltaRSSI\n"; + unsigned char cqi_log_buf[100] = { 0 }; + signed int pos; + unsigned char cqi_log_path[100] = { 0 }; + + /* for soft-mute tune, and get cqi */ + freq = fm_cb_op->cur_freq_get(); + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + /* get cqi */ + orig_freq = freq; + if (fm_get_channel_space(min_freq) == 0) + min = min_freq * 10; + else + min = min_freq; + + if (fm_get_channel_space(max_freq) == 0) + 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; (orig_freq == 10000) && (g_dbg_level == 0xffffffff) && (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)); + if (sprintf(&cqi_log_path[strlen(FM_CQI_LOG_PATH)], "%d.txt", k + 1) < 0) + WCN_DBG(FM_NTC | CHIP, "sprintf fail\n"); + 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 = fm_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, fm_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (!ret && fm_res) { + WCN_DBG(FM_NTC | CHIP, "smt cqi size %d\n", fm_res->cqi[0]); + p_cqi = (struct mt6631_full_cqi *)&fm_res->cqi[2]; + for (i = 0; i < fm_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 */ + if (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) < 0) + WCN_DBG(FM_NTC | CHIP, "sprintf fail\n"); + /* 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 */ + } + + return ret; +} + +static unsigned short mt6631_read_dsp_reg(unsigned short addr) +{ + unsigned short regValue = 0; + + fm_reg_write(0x60, 0x07); + fm_reg_write(0xE2, addr); + fm_reg_write(0xE1, 0x01); + fm_reg_read(0xE4, ®Value); + fm_reg_write(0x60, 0x0F); + + return regValue; +} + +static bool mt6631_is_valid_freq(unsigned short freq) +{ + int i = 0; + bool valid = false; + signed int RSSI = 0, PAMD = 0, MR = 0; + unsigned int PRX = 0; + unsigned short softmuteGainLvl = 0; + unsigned short tmp_reg = 0; + + for (i = 0; i < 8; i++) { + fm_reg_read(0x6C, &tmp_reg); + RSSI += (((tmp_reg & 0x03FF) >= 512) ? ((tmp_reg & 0x03FF) - 1024) : (tmp_reg & 0x03FF)) >> 3; + fm_reg_read(0xB4, &tmp_reg); + PAMD += (((tmp_reg & 0x1FF) >= 256) ? ((tmp_reg & 0x01FF) - 512) : (tmp_reg & 0x01FF)) >> 3; + tmp_reg = mt6631_read_dsp_reg(0x4E1); + PRX += (tmp_reg & 0x00FF) >> 3; + fm_reg_read(0xBD, &tmp_reg); + MR += (((tmp_reg & 0x01FF) >= 256) ? ((tmp_reg & 0x01FF) - 512) : (tmp_reg & 0x01FF)) >> 3; + tmp_reg = mt6631_read_dsp_reg(0x2C4); + softmuteGainLvl += tmp_reg >> 3; + fm_delayus(2250); + } + + if ((fm_config.rx_cfg.long_ana_rssi_th <= RSSI) + && (fm_config.rx_cfg.pamd_th >= PAMD) + && (fm_config.rx_cfg.mr_th <= MR) + && (fm_config.rx_cfg.prx_th <= PRX) + && (fm_config.rx_cfg.smg_th <= softmuteGainLvl)) { + valid = true; + } + + WCN_DBG(FM_DBG | CHIP, + "freq %d valid=%d, %d, %d, 0x%04x, 0x%04x, 0x%04x\n", + freq, valid, RSSI, PAMD, PRX, MR, softmuteGainLvl); + + return valid; +} + +/* + * mt6631_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 signed int mt6631_GetCurRSSI(signed int *pRSSI) +{ + unsigned short tmp_reg = 0; + + fm_reg_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 unsigned short mt6631_vol_tbl[16] = { 0x0000, 0x0519, 0x066A, 0x0814, + 0x0A2B, 0x0CCD, 0x101D, 0x1449, + 0x198A, 0x2027, 0x287A, 0x32F5, + 0x4027, 0x50C3, 0x65AD, 0x7FFF +}; + +static signed int mt6631_SetVol(unsigned char vol) +{ + signed int ret = 0; + + vol = (vol > 15) ? 15 : vol; + ret = fm_reg_write(0x7D, mt6631_vol_tbl[vol]); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "Set vol=%d Failed\n", vol); + return ret; + } + 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 signed int mt6631_GetVol(unsigned char *pVol) +{ + int ret = 0; + unsigned short tmp = 0; + signed int i; + + if (pVol == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + ret = fm_reg_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 (mt6631_vol_tbl[i] == tmp) { + *pVol = i; + break; + } + } + + WCN_DBG(FM_DBG | CHIP, "Get vol=%d OK\n", *pVol); + return 0; +} + +static signed int mt6631_dump_reg(void) +{ + signed int i; + unsigned short TmpReg = 0; + + for (i = 0; i < 0xff; i++) { + fm_reg_read(i, &TmpReg); + WCN_DBG(FM_NTC | CHIP, "0x%02x=0x%04x\n", i, TmpReg); + } + return 0; +} + +/*0:mono, 1:stereo*/ +static bool mt6631_GetMonoStereo(unsigned short *pMonoStereo) +{ +#define FM_BF_STEREO 0x1000 + unsigned short TmpReg = 0; + + if (pMonoStereo) { + fm_reg_read(FM_RSSI_IND, &TmpReg); + *pMonoStereo = (TmpReg & FM_BF_STEREO) >> 12; + } else { + WCN_DBG(FM_ERR | CHIP, "MonoStero: para err\n"); + return false; + } + + WCN_DBG(FM_NTC | CHIP, "Get MonoStero:0x%04x\n", *pMonoStereo); + return true; +} + +static signed int mt6631_SetMonoStereo(signed int MonoStereo) +{ + signed int ret = 0; + + WCN_DBG(FM_NTC | CHIP, "set to %s\n", MonoStereo ? "mono" : "auto"); + fm_reg_write(0x60, 0x0007); + + if (MonoStereo) /*mono */ + ret = fm_set_bits(0x75, 0x0008, ~0x0008); + else + ret = fm_set_bits(0x75, 0x0000, ~0x0008); + + fm_reg_write(0x60, 0x000F); + return ret; +} + +static signed int mt6631_GetCapArray(signed int *ca) +{ + unsigned short dataRead = 0; + unsigned short tmp = 0; + + if (ca == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + fm_reg_read(0x60, &tmp); + fm_reg_write(0x60, tmp & 0xFFF7); /* 0x60 D3=0 */ + + fm_reg_read(0x26, &dataRead); + *ca = dataRead; + + fm_reg_write(0x60, tmp); /* 0x60 D3=1 */ + return 0; +} + +/* + * mt6631_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 bool mt6631_GetCurPamd(unsigned short *pPamdLevl) +{ + unsigned short tmp_reg = 0; + unsigned short dBvalue, valid_cnt = 0; + int i, total = 0; + + for (i = 0; i < 8; i++) { + if (fm_reg_read(FM_ADDR_PAMD, &tmp_reg)) { + *pPamdLevl = 0; + return 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); + } + fm_delayms(3); + } + if (valid_cnt != 0) + *pPamdLevl = total / valid_cnt; + else + *pPamdLevl = 0; + + WCN_DBG(FM_NTC | CHIP, "PAMD=%d\n", *pPamdLevl); + return true; +} + +static signed int mt6631_i2s_info_get(signed int *ponoff, signed int *pmode, signed int *psample) +{ + if (ponoff == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (pmode == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (psample == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + *ponoff = fm_config.aud_cfg.i2s_info.status; + *pmode = fm_config.aud_cfg.i2s_info.mode; + *psample = fm_config.aud_cfg.i2s_info.rate; + + return 0; +} + +static signed int mt6631_get_audio_info(struct fm_audio_info_t *data) +{ + memcpy(data, &fm_config.aud_cfg, sizeof(struct fm_audio_info_t)); + return 0; +} + +static signed int mt6631_hw_info_get(struct fm_hw_info *req) +{ + if (req == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + req->chip_id = mt6631_hw_info.chip_id; + req->eco_ver = mt6631_hw_info.eco_ver; + req->patch_ver = mt6631_hw_info.patch_ver; + req->rom_ver = mt6631_hw_info.rom_ver; + + return 0; +} + +static signed int mt6631_pre_search(void) +{ + mt6631_RampDown(); + /* disable audio output I2S Rx mode */ + fm_host_reg_write(0x80101054, 0x00000000); + /* disable audio output I2S Tx mode */ + fm_reg_write(0x9B, 0x0000); + + return 0; +} + +static signed int mt6631_restore_search(void) +{ + mt6631_RampDown(); + /* set audio output I2S Tx mode */ + fm_reg_write(0x9B, 0xF9AB); + /* set audio output I2S Rx mode */ + fm_host_reg_write(0x80101054, 0x00003f35); + return 0; +} + +static signed int mt6631_soft_mute_tune(unsigned short freq, signed int *rssi, signed int *valid) +{ + signed int ret = 0; + unsigned short pkt_size; + struct mt6631_full_cqi *p_cqi; + signed int RSSI = 0, PAMD = 0, MR = 0, ATDC = 0; + unsigned int PRX = 0, ATDEV = 0; + unsigned short softmuteGainLvl = 0; + signed int projectid = fm_cb_op->projectid_get(); + + ret = mt6631_chan_para_get(freq); + if (ret == 2) + ret = fm_set_bits(FM_CHANNEL_SET, 0x2000, 0x0FFF); /* mdf HiLo */ + else + ret = fm_set_bits(FM_CHANNEL_SET, 0x0000, 0x0FFF); /* clear FA/HL/ATJ */ + + /* SPI hoppint setting*/ + if (mt6631_SPI_hopping_check(freq)) { + WCN_DBG(FM_NTC | CHIP, "%s: freq:%d is SPI hopping channel,turn on 64M PLL\n", __func__, freq); + + if (projectid == 0x8168) { + mt8168_spi_hopping_clock_switch(true); + } else { + if (!mt6631_do_SPI_hopping_64M(freq)) + WCN_DBG(FM_ERR | CHIP, "%s: spi hopping fail!\n", __func__); + } + } + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = fm_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, fm_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (!ret && fm_res) { + p_cqi = (struct mt6631_full_cqi *)&fm_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 ((fm_config.rx_cfg.long_ana_rssi_th <= RSSI) + && (fm_config.rx_cfg.pamd_th >= PAMD) + && (fm_config.rx_cfg.atdc_th >= ATDC) + && (fm_config.rx_cfg.mr_th <= MR) + && (fm_config.rx_cfg.prx_th <= PRX) + && (ATDEV >= ATDC) /* sync scan algorithm */ + && (fm_config.rx_cfg.smg_th <= softmuteGainLvl)) { + *valid = true; + } else { + *valid = false; + } + *rssi = RSSI; + } else { + WCN_DBG(FM_ALT | CHIP, "smt get CQI failed\n"); + return false; + } + WCN_DBG(FM_NTC | CHIP, "valid=%d\n", *valid); + return true; +} + +static bool mt6631_em_test(unsigned short group_idx, unsigned short item_idx, unsigned int item_value) +{ + return true; +} + +/* +*parm: +* parm.th_type: 0, RSSI. 1, desense RSSI. 2, SMG. +* parm.th_val: threshold value +*/ +static signed int mt6631_set_search_th(signed int idx, signed int val, signed int reserve) +{ + switch (idx) { + case 0: { + fm_config.rx_cfg.long_ana_rssi_th = val; + WCN_DBG(FM_NTC | CHIP, "set rssi th =%d\n", val); + break; + } + case 1: { + fm_config.rx_cfg.desene_rssi_th = val; + WCN_DBG(FM_NTC | CHIP, "set desense rssi th =%d\n", val); + break; + } + case 2: { + fm_config.rx_cfg.smg_th = val; + WCN_DBG(FM_NTC | CHIP, "set smg th =%d\n", val); + break; + } + default: + break; + } + return 0; +} + +static signed int MT6631_low_power_wa_default(signed int fmon) +{ + return 0; +} + +signed int mt6631_fm_low_ops_register(struct fm_callback *cb, struct fm_basic_interface *bi) +{ + signed int ret = 0; + /* Basic functions. */ + + if (bi == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,bi invalid pointer\n", __func__); + return -FM_EPARA; + } + if (cb->cur_freq_get == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,cb->cur_freq_get invalid pointer\n", __func__); + return -FM_EPARA; + } + if (cb->cur_freq_set == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,cb->cur_freq_set invalid pointer\n", __func__); + return -FM_EPARA; + } + fm_cb_op = cb; + + bi->pwron = mt6631_pwron; + bi->pwroff = mt6631_pwroff; + bi->chipid_get = mt6631_get_chipid; + bi->mute = mt6631_Mute; + bi->rampdown = mt6631_RampDown; + bi->pwrupseq = mt6631_PowerUp; + bi->pwrdownseq = mt6631_PowerDown; + bi->setfreq = mt6631_SetFreq; + bi->low_pwr_wa = MT6631_low_power_wa_default; + bi->get_aud_info = mt6631_get_audio_info; + bi->rssiget = mt6631_GetCurRSSI; + bi->volset = mt6631_SetVol; + bi->volget = mt6631_GetVol; + bi->dumpreg = mt6631_dump_reg; + bi->msget = mt6631_GetMonoStereo; + bi->msset = mt6631_SetMonoStereo; + bi->pamdget = mt6631_GetCurPamd; + bi->em = mt6631_em_test; + bi->anaswitch = mt6631_SetAntennaType; + bi->anaget = mt6631_GetAntennaType; + bi->caparray_get = mt6631_GetCapArray; + bi->hwinfo_get = mt6631_hw_info_get; + bi->i2s_get = mt6631_i2s_info_get; + bi->is_dese_chan = mt6631_is_dese_chan; + bi->softmute_tune = mt6631_soft_mute_tune; + bi->desense_check = mt6631_desense_check; + bi->cqi_log = mt6631_full_cqi_get; + bi->pre_search = mt6631_pre_search; + bi->restore_search = mt6631_restore_search; + bi->set_search_th = mt6631_set_search_th; + bi->is_valid_freq = mt6631_is_valid_freq; + + cmd_buf_lock = fm_lock_create("31_cmd"); + ret = fm_lock_get(cmd_buf_lock); + + cmd_buf = fm_zalloc(TX_BUF_SIZE + 1); + + if (!cmd_buf) { + WCN_DBG(FM_ALT | CHIP, "6631 fm lib alloc tx buf failed\n"); + ret = -1; + } +#if 0 /* def CONFIG_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, "6631 fm lib create cqi fifo failed\n"); + ret = -1; + } +#endif + + return ret; +} + +signed int mt6631_fm_low_ops_unregister(struct fm_basic_interface *bi) +{ + signed int ret = 0; + /* Basic functions. */ + if (bi == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,bi invalid pointer\n", __func__); + return -FM_EPARA; + } + +#if 0 /* def CONFIG_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(bi, 0, sizeof(struct fm_basic_interface)); + + fm_cb_op = NULL; + + return ret; +} + +static const signed char mt6631_chan_para_map[] = { + /* 0, X, 1, X, 2, X, 3, X, 4, X, 5, X, 6, X, 7, X, 8, X, 9, X*/ + 0, 0, 2, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6500~6595 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6600~6695 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, /* 6700~6795 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6800~6895 */ + 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6900~6995 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7000~7095 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7100~7195 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, /* 7200~7295 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, /* 7300~7395 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 7400~7495 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7500~7595 */ + 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 */ + 8, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7800~7895 */ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7900~7995 */ + 0, 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, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8200~8295 */ + 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, /* 8300~8395 */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 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, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8700~8795 */ + 0, 0, 0, 0, 0, 0, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9400~9495 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9500~9595 */ + 3, 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, 8, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9800~9895 */ + 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 9900~9995 */ + 0, 0, 0, 0, 0, 0, 0, 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, 1, 0, 0, 0, 0, 0, /* 10300~10395 */ + 8, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10400~10495 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 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, 0, 0, 0, 0, 0, 0, /* 10700~10795 */ + 0 /* 10800 */ +}; +static const unsigned short mt6631_scan_dese_list[] = { + 6910, 6920, 7680, 7800, 8450, 9210, 9220, 9230, 9590, 9600, 9830, 9900, 9980, 9990, 10400, 10750, 10760 +}; + +static const unsigned short mt6631_SPI_hopping_list[] = { + 6510, 6520, 6530, 7780, 7790, 7800, 7810, 7820, 9090, 9100, 9110, 9120, 10380, 10390, 10400, 10410, 10420 +}; + +static const unsigned short mt6631_I2S_hopping_list[] = { + 6550, 6760, 6960, 6970, 7170, 7370, 7580, 7780, 7990, 8810, 9210, 9220, 10240 +}; + +static const unsigned short mt6631_TDD_list[] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6500~6595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6600~6695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6700~6795 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6800~6895 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6900~6995 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7000~7095 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7100~7195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7200~7295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7300~7395 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7400~7495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7500~7595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7600~7695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7700~7795 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7800~7895 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7900~7995 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8000~8095 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8100~8195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8200~8295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8300~8395 */ + 0x0101, 0x0000, 0x0000, 0x0000, 0x0000, /* 8400~8495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8500~8595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8600~8695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8700~8795 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8800~8895 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8900~8995 */ + 0x0000, 0x0000, 0x0101, 0x0101, 0x0101, /* 9000~9095 */ + 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, /* 9100~9195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9200~9295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9300~9395 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9400~9495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9500~9595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9600~9695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0100, /* 9700~9795 */ + 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, /* 9800~9895 */ + 0x0101, 0x0101, 0x0001, 0x0000, 0x0000, /* 9900~9995 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10000~10095 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10100~10195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10200~10295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10300~10395 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10400~10495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10500~10595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0100, /* 10600~10695 */ + 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, /* 10700~10795 */ + 0x0001 /* 10800 */ +}; + +static const unsigned short mt6631_TDD_Mask[] = { + 0x0001, 0x0010, 0x0100, 0x1000 +}; + +/* return value: 0, not a de-sense channel; 1, this is a de-sense channel; else error no */ +static signed int mt6631_is_dese_chan(unsigned short freq) +{ + signed int size; + + if (1 == HQA_ZERO_DESENSE_MAP) /*HQA only :skip desense channel check. */ + return 0; + + size = ARRAY_SIZE(mt6631_scan_dese_list); + + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + while (size) { + if (mt6631_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 signed int mt6631_desense_check(unsigned short freq, signed int rssi) +{ + if (mt6631_is_dese_chan(freq)) { + if (rssi < fm_config.rx_cfg.desene_rssi_th) + return 1; + + WCN_DBG(FM_DBG | CHIP, "desen_rssi %d th:%d\n", rssi, fm_config.rx_cfg.desene_rssi_th); + } + return 0; +} + +static bool mt6631_TDD_chan_check(unsigned short freq) +{ + unsigned int i = 0; + unsigned short freq_tmp = freq; + signed int ret = 0; + + ret = fm_get_channel_space(freq_tmp); + if (ret == 0) + freq_tmp *= 10; + else if (ret == -1) + return false; + + i = (freq_tmp - 6500) / 5; + if ((i / 4) >= ARRAY_SIZE(mt6631_TDD_list)) { + WCN_DBG(FM_ERR | CHIP, "Freq index out of range(%d),max(%zd)\n", + i / 4, ARRAY_SIZE(mt6631_TDD_list)); + return false; + } + + if (mt6631_TDD_list[i / 4] & mt6631_TDD_Mask[i % 4]) { + WCN_DBG(FM_DBG | CHIP, "Freq %d use TDD solution\n", freq); + return true; + } else + return false; +} + +/* get channel parameter, HL side/ FA / ATJ */ +static unsigned short mt6631_chan_para_get(unsigned short freq) +{ + signed int pos, size; + + if (1 == HQA_RETURN_ZERO_MAP) { + WCN_DBG(FM_NTC | CHIP, "HQA_RETURN_ZERO_CHAN mt6631_chan_para_map enabled!\n"); + return 0; + } + + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + if (freq < 6500) + return 0; + + pos = (freq - 6500) / 5; + + size = ARRAY_SIZE(mt6631_chan_para_map); + + pos = (pos > (size - 1)) ? (size - 1) : pos; + + return mt6631_chan_para_map[pos]; +} + + +static bool mt6631_SPI_hopping_check(unsigned short freq) +{ + signed int size; + + size = ARRAY_SIZE(mt6631_SPI_hopping_list); + + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + while (size) { + if (mt6631_SPI_hopping_list[size - 1] == freq) + return 1; + size--; + } + + return 0; +} + diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/mt6631/pub/mt6631_fm_rds.c b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6631/pub/mt6631_fm_rds.c new file mode 100644 index 0000000000000..7c48a23e5694a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6631/pub/mt6631_fm_rds.c @@ -0,0 +1,335 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ +#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 "mt6631_fm_reg.h" +#include "fm_cmd.h" + +static bool bRDS_FirstIn; /* false */ +static unsigned int gBLER_CHK_INTERVAL = 500; +static unsigned short GOOD_BLK_CNT = 0, BAD_BLK_CNT; +static unsigned char BAD_BLK_RATIO; + +static struct fm_basic_interface *fm_bi; + +static bool mt6631_RDS_support(void); +static signed int mt6631_RDS_enable(void); +static signed int mt6631_RDS_disable(void); +static unsigned short mt6631_RDS_Get_GoodBlock_Counter(void); +static unsigned short mt6631_RDS_Get_BadBlock_Counter(void); +static unsigned char mt6631_RDS_Get_BadBlock_Ratio(void); +static unsigned int mt6631_RDS_Get_BlerCheck_Interval(void); +/* static void mt6631_RDS_GetData(unsigned short *data, unsigned short datalen); */ +static void mt6631_RDS_Init_Data(struct rds_t *pstRDSData); + +static bool mt6631_RDS_support(void) +{ + return true; +} + +static signed int mt6631_RDS_enable(void) +{ + signed int ret = 0; + unsigned short dataRead = 0; + + WCN_DBG(FM_DBG | RDSC, "rds enable\n"); + ret = fm_reg_read(FM_RDS_CFG0, &dataRead); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds enable read 0x80 fail\n"); + return ret; + } + ret = fm_reg_write(FM_RDS_CFG0, 6); /* set buf_start_th */ + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds enable write 0x80 fail\n"); + return ret; + } + ret = fm_reg_read(FM_MAIN_CTRL, &dataRead); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds enable read 0x63 fail\n"); + return ret; + } + ret = fm_reg_write(FM_MAIN_CTRL, dataRead | (RDS_MASK)); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds enable write 0x63 fail\n"); + return ret; + } + + return ret; +} + +static signed int mt6631_RDS_disable(void) +{ + signed int ret = 0; + unsigned short dataRead = 0; + + WCN_DBG(FM_DBG | RDSC, "rds disable\n"); + ret = fm_reg_read(FM_MAIN_CTRL, &dataRead); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds disable read 0x63 fail\n"); + return ret; + } + ret = fm_reg_write(FM_MAIN_CTRL, dataRead & (~RDS_MASK)); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds disable write 0x63 fail\n"); + return ret; + } + + return ret; +} + +static unsigned short mt6631_RDS_Get_GoodBlock_Counter(void) +{ + unsigned short tmp_reg = 0; + + fm_reg_read(FM_RDS_GOODBK_CNT, &tmp_reg); + GOOD_BLK_CNT = tmp_reg; + WCN_DBG(FM_DBG | RDSC, "get good block cnt:%d\n", (signed int) tmp_reg); + + return tmp_reg; +} + +static unsigned short mt6631_RDS_Get_BadBlock_Counter(void) +{ + unsigned short tmp_reg = 0; + + fm_reg_read(FM_RDS_BADBK_CNT, &tmp_reg); + BAD_BLK_CNT = tmp_reg; + WCN_DBG(FM_DBG | RDSC, "get bad block cnt:%d\n", (signed int) tmp_reg); + + return tmp_reg; +} + +static unsigned char mt6631_RDS_Get_BadBlock_Ratio(void) +{ + unsigned short tmp_reg; + unsigned short gbc; + unsigned short bbc; + + gbc = mt6631_RDS_Get_GoodBlock_Counter(); + bbc = mt6631_RDS_Get_BadBlock_Counter(); + + if ((gbc + bbc) > 0) + tmp_reg = (unsigned char) (bbc * 100 / (gbc + bbc)); + else + tmp_reg = 0; + + BAD_BLK_RATIO = tmp_reg; + WCN_DBG(FM_DBG | RDSC, "get badblock ratio:%d\n", (signed int) tmp_reg); + + return tmp_reg; +} + +static signed int mt6631_RDS_BlockCounter_Reset(void) +{ + mt6631_RDS_disable(); + mt6631_RDS_enable(); + + return 0; +} + +static unsigned int mt6631_RDS_Get_BlerCheck_Interval(void) +{ + return gBLER_CHK_INTERVAL; +} + +static signed int mt6631_RDS_BlerCheck(struct rds_t *dst) +{ + return 0; +} + +#if 0 +static void RDS_Recovery_Handler(void) +{ + unsigned short tempData = 0; + + do { + fm_reg_read(FM_RDS_DATA_REG, &tempData); + fm_reg_read(FM_RDS_POINTER, &tempData); + } while (tempData & 0x3); +} +#endif + +#if 0 +static void mt6631_RDS_GetData(unsigned short *data, unsigned short 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 + + unsigned short CRC = 0, i = 0, RDS_adj = 0, RDSDataCount = 0, FM_WARorrCnt = 0; + unsigned short temp = 0, OutputPofm_s32 = 0; + + WCN_DBG(FM_DBG | RDSC, "get data\n"); + fm_reg_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_reg_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_reg_read(FM_RDS_DATA_REG, &data[0]); + + /* block B data and info handling */ + fm_reg_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_reg_read(FM_RDS_DATA_REG, &data[1]); + + /* block C data and info handling */ + fm_reg_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_reg_read(FM_RDS_DATA_REG, &data[2]); + + /* block D data and info handling */ + fm_reg_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_reg_read(FM_RDS_DATA_REG, &data[3]); + + data[4] = (CRC | RDS_adj | RDSDataCount); + data[5] = FM_WARorrCnt; + + fm_reg_read(FM_RDS_PWDI, &data[6]); + fm_reg_read(FM_RDS_PWDQ, &data[7]); + + fm_reg_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 mt6631_RDS_Init_Data(struct rds_t *pstRDSData) +{ + fm_memset(pstRDSData, 0, sizeof(struct rds_t)); + bRDS_FirstIn = true; + + pstRDSData->event_status = 0x0000; + 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)); +} + +bool mt6631_RDS_OnOff(struct rds_t *dst, bool bFlag) +{ + signed int ret = 0; + + if (mt6631_RDS_support() == false) { + WCN_DBG(FM_ALT | RDSC, "mt6631_RDS_OnOff failed, RDS not support\n"); + return false; + } + + if (bFlag) { + mt6631_RDS_Init_Data(dst); + ret = mt6631_RDS_enable(); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "mt6631_RDS_OnOff enable failed\n"); + return false; + } + } else { + mt6631_RDS_Init_Data(dst); + ret = mt6631_RDS_disable(); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "mt6631_RDS_OnOff disable failed\n"); + return false; + } + } + + return true; +} + +DEFINE_RDSLOG(mt6631_rds_log); + +/* mt6631_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 signed int mt6631_rds_parser(struct rds_t *rds_dst, struct rds_rx_t *rds_raw, + signed int rds_size, unsigned short(*getfreq) (void)) +{ + mt6631_rds_log.log_in(&mt6631_rds_log, rds_raw, rds_size); + return rds_parser(rds_dst, rds_raw, rds_size, getfreq); +} + +static signed int mt6631_rds_log_get(struct rds_rx_t *dst, signed int *dst_len) +{ + return mt6631_rds_log.log_out(&mt6631_rds_log, dst, dst_len); +} + +static signed int mt6631_rds_gc_get(struct rds_group_cnt_t *dst, struct rds_t *rdsp) +{ + return rds_grp_counter_get(dst, &rdsp->gc); +} + +static signed int mt6631_rds_gc_reset(struct rds_t *rdsp) +{ + return rds_grp_counter_reset(&rdsp->gc); +} + +signed int mt6631_fm_rds_ops_register(struct fm_basic_interface *bi, struct fm_rds_interface *ri) +{ + signed int ret = 0; + + if (ri == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,ri invalid pointer\n", __func__); + return -FM_EPARA; + } + + fm_bi = bi; + + ri->rds_blercheck = mt6631_RDS_BlerCheck; + ri->rds_onoff = mt6631_RDS_OnOff; + ri->rds_parser = mt6631_rds_parser; + ri->rds_gbc_get = mt6631_RDS_Get_GoodBlock_Counter; + ri->rds_bbc_get = mt6631_RDS_Get_BadBlock_Counter; + ri->rds_bbr_get = mt6631_RDS_Get_BadBlock_Ratio; + ri->rds_bc_reset = mt6631_RDS_BlockCounter_Reset; + ri->rds_bci_get = mt6631_RDS_Get_BlerCheck_Interval; + ri->rds_log_get = mt6631_rds_log_get; + ri->rds_gc_get = mt6631_rds_gc_get; + ri->rds_gc_reset = mt6631_rds_gc_reset; + + return ret; +} + +signed int mt6631_fm_rds_ops_unregister(struct fm_rds_interface *ri) +{ + signed int ret = 0; + + if (ri == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,ri invalid pointer\n", __func__); + return -FM_EPARA; + } + + fm_bi = NULL; + fm_memset(ri, 0, sizeof(struct fm_rds_interface)); + return ret; +} diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/mt6632/inc/mt6632_fm_lib.h b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6632/inc/mt6632_fm_lib.h new file mode 100644 index 0000000000000..1c1ae7ea5056e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6632/inc/mt6632_fm_lib.h @@ -0,0 +1,69 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef __MT6632_FM_LIB_H__ +#define __MT6632_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 { + mt6632_E1 = 0, + mt6632_E2 +}; + +struct mt6632_fm_cqi { + unsigned short ch; + unsigned short rssi; + unsigned short reserve; +}; + +struct adapt_fm_cqi { + signed int ch; + signed int rssi; + signed int reserve; +}; + +struct mt6632_full_cqi { + unsigned short ch; + unsigned short rssi; + unsigned short pamd; + unsigned short pr; + unsigned short fpamd; + unsigned short mr; + unsigned short atdc; + unsigned short prx; + unsigned short atdev; + unsigned short smg; /* soft-mute gain */ + unsigned short drssi; /* delta rssi */ +}; + +#endif diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/mt6632/inc/mt6632_fm_reg.h b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6632/inc/mt6632_fm_reg.h new file mode 100644 index 0000000000000..d1e0f62063aba --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6632/inc/mt6632_fm_reg.h @@ -0,0 +1,58 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef __MT6632_FM_REG_H__ +#define __MT6632_FM_REG_H__ + +/* 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, +}; + +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 /* __MT6632_FM_REG_H__ */ diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/mt6632/pub/mt6632_fm_lib.c b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6632/pub/mt6632_fm_lib.c new file mode 100644 index 0000000000000..0d17b1699df32 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6632/pub/mt6632_fm_lib.c @@ -0,0 +1,1793 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#include +#include + +#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_cmd.h" + +#include "mt6632_fm_reg.h" +#include "mt6632_fm_lib.h" + +static struct fm_patch_tbl mt6632_patch_tbl[5] = { + {FM_ROM_V1, "mt6632_fm_v1_patch.bin", "mt6632_fm_v1_coeff.bin", NULL, NULL}, + {FM_ROM_V2, "mt6632_fm_v2_patch.bin", "mt6632_fm_v2_coeff.bin", NULL, NULL}, + {FM_ROM_V3, "mt6632_fm_v3_patch.bin", "mt6632_fm_v3_coeff.bin", NULL, NULL}, + {FM_ROM_V4, "mt6632_fm_v4_patch.bin", "mt6632_fm_v4_coeff.bin", NULL, NULL}, + {FM_ROM_V5, "mt6632_fm_v5_patch.bin", "mt6632_fm_v5_coeff.bin", NULL, NULL}, +}; + + +static struct fm_hw_info mt6632_hw_info = { + .chip_id = 0x00006632, + .eco_ver = 0x00000000, + .rom_ver = 0x00000000, + .patch_ver = 0x00000000, + .reserve = 0x00000000, +}; + +static struct fm_callback *fm_cb_op; +static unsigned char fm_packaging = 1; /*0:QFN,1:WLCSP */ +static unsigned int fm_sant_flag; /* 1,Short Antenna; 0, Long Antenna */ +static signed int mt6632_is_dese_chan(unsigned short freq); +#if 0 +static signed int mt6632_mcu_dese(unsigned short freq, void *arg); +#endif +static signed int mt6632_gps_dese(unsigned short freq, void *arg); + +static signed int mt6632_I2s_Setting(signed int onoff, signed int mode, signed int sample); +static unsigned short mt6632_chan_para_get(unsigned short freq); +static signed int mt6632_desense_check(unsigned short freq, signed int rssi); +static bool mt6632_TDD_chan_check(unsigned short freq); +static signed int mt6632_soft_mute_tune(unsigned short freq, signed int *rssi, signed int *valid); +static signed int mt6632_pwron(signed int data) +{ + if (mtk_wcn_wmt_func_on(WMTDRV_TYPE_FM) == MTK_WCN_BOOL_FALSE) { + WCN_DBG(FM_ERR | CHIP, "WMT turn on FM Fail!\n"); + return -FM_ELINK; + } + + WCN_DBG(FM_NTC | CHIP, "WMT turn on FM OK!\n"); + return 0; +} + +static signed int mt6632_pwroff(signed int data) +{ + if (mtk_wcn_wmt_func_off(WMTDRV_TYPE_FM) == MTK_WCN_BOOL_FALSE) { + WCN_DBG(FM_ERR | CHIP, "WMT turn off FM Fail!\n"); + return -FM_ELINK; + } + + WCN_DBG(FM_NTC | CHIP, "WMT turn off FM OK!\n"); + return 0; +} + +static unsigned short mt6632_get_chipid(void) +{ + return 0x6632; +} + +/* MT6632_SetAntennaType - set Antenna type + * @type - 1,Short Antenna; 0, Long Antenna + */ +static signed int mt6632_SetAntennaType(signed int type) +{ + unsigned short dataRead = 0; + + WCN_DBG(FM_NTC | CHIP, "set ana to %s\n", type ? "short" : "long"); + if (fm_packaging == 0) { + fm_sant_flag = type; + } else { + fm_reg_read(FM_MAIN_CG2_CTRL, &dataRead); + + if (type) + dataRead |= ANTENNA_TYPE; + else + dataRead &= (~ANTENNA_TYPE); + + fm_reg_write(FM_MAIN_CG2_CTRL, dataRead); + } + return 0; +} + +static signed int mt6632_GetAntennaType(void) +{ + unsigned short dataRead = 0; + + if (fm_packaging == 0) + return fm_sant_flag; + + fm_reg_read(FM_MAIN_CG2_CTRL, &dataRead); + WCN_DBG(FM_NTC | 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 signed int mt6632_Mute(bool mute) +{ + signed int ret = 0; + unsigned short dataRead = 0; + + WCN_DBG(FM_NTC | CHIP, "set %s\n", mute ? "mute" : "unmute"); + fm_reg_read(FM_MAIN_CTRL, &dataRead); + + if (mute == 1) + ret = fm_reg_write(FM_MAIN_CTRL, (dataRead & 0xFFDF) | 0x0020); + else + ret = fm_reg_write(FM_MAIN_CTRL, (dataRead & 0xFFDF)); + + return ret; +} + +static signed int mt6632_rampdown_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* Clear DSP state */ + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFF0, 0x0000, &buf[pkt_size], buf_size - pkt_size); + /* Set DSP ramp down state */ + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFEFF, RAMP_DOWN, &buf[pkt_size], buf_size - pkt_size); + /* @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); + /* Clear DSP ramp down state */ + pkt_size += fm_bop_modify(FM_MAIN_CTRL, (~RAMP_DOWN), 0x0000, &buf[pkt_size], buf_size - pkt_size); + /* Write 1 clear the STC_DONE interrupt status flag */ + pkt_size += fm_bop_modify(FM_MAIN_INTR, 0xFFFE, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size); + + return pkt_size - 4; +} +/* + * mt6632_rampdown - f/w will wait for STC_DONE interrupt + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6632_rampdown(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6632_rampdown_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_RAMPDOWN_OPCODE, pkt_size); +} + +static signed int mt6632_RampDown(void) +{ + signed int ret = 0; + unsigned short pkt_size; + /* unsigned short tmp; */ + + WCN_DBG(FM_NTC | CHIP, "ramp down\n"); + + ret = fm_reg_write(FM_MAIN_EXTINTRMASK, 0x0000); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down write FM_MAIN_EXTINTRMASK failed\n"); + return ret; + } + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6632_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; + } + + ret = fm_reg_write(FM_MAIN_EXTINTRMASK, 0x0021); + if (ret) + WCN_DBG(FM_ERR | CHIP, "ramp down write FM_MAIN_EXTINTRMASK failed\n"); + + return ret; +} + +static signed int mt6632_get_rom_version(void) +{ + unsigned short tmp = 0; + signed int ret = 0; + + /* set download dsp coefficient mode */ + fm_reg_write(0x90, 0xe); + /* fill in coefficient data */ + fm_reg_write(0x92, 0x0); + /* reset download control */ + fm_reg_write(0x90, 0x40); + /* disable memory control from host */ + fm_reg_write(0x90, 0x0); + + /* DSP rom code version request enable --- set 0x61 b15=1 */ + fm_set_bits(0x61, 0x8000, 0x7FFF); + + /* Release ASIP reset --- set 0x61 b1=1 */ + fm_set_bits(0x61, 0x0002, 0xFFFD); + + /* Enable ASIP power --- set 0x61 b0=0 */ + fm_set_bits(0x61, 0x0000, 0xFFFE); + + /* Wait DSP code version ready --- wait 1ms */ + do { + fm_delayus(1000); + ret = fm_reg_read(0x84, &tmp); + /* ret=-4 means signal got when control FM. usually get sig 9 to kill FM process. */ + /* now cancel FM power up sequence is recommended. */ + if (ret) + return ret; + + WCN_DBG(FM_DBG | CHIP, "0x84=%x\n", tmp); + } while (tmp != 0x0001); + + /* Get FM DSP code version --- rd 0x83[15:8] */ + fm_reg_read(0x83, &tmp); + WCN_DBG(FM_NTC | CHIP, "DSP ver=0x%x\n", tmp); + tmp = (tmp >> 8); + + /* DSP rom code version request disable --- set 0x61 b15=0 */ + fm_set_bits(0x61, 0x0000, 0x7FFF); + + /* Reset ASIP --- set 0x61[1:0] = 1 */ + fm_set_bits(0x61, 0x0001, 0xFFFC); + + /* WCN_DBG(FM_NTC | CHIP, "ROM version: v%d\n", (signed int)tmp); */ + return (signed int) tmp; +} + +static signed int mt6632_pmic_read(unsigned char addr, unsigned int *val) +{ + signed int ret = 0; + unsigned char read_reslut = 0xff; + unsigned short pkt_size; + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = fm_pmic_get_reg(cmd_buf, TX_BUF_SIZE, addr); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_PMIC_READ, SW_RETRY_CNT, PMIC_CONTROL_TIMEOUT, fm_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (!ret && fm_res) { + fm_memcpy(val, &fm_res->pmic_result[0], sizeof(unsigned int)); + read_reslut = fm_res->pmic_result[4]; + } else { + WCN_DBG(FM_ERR | CHIP, "mt6632_pmic_read failed,ret(%d)\n", ret); + return -1; + } + + if (read_reslut) { + WCN_DBG(FM_ERR | CHIP, "mt6632_pmic_read failed(%02x)\n", read_reslut); + return -2; + } + return ret; +} + +static signed int mt6632_pmic_write(unsigned char addr, unsigned int val) +{ + signed int ret = 0; + unsigned char read_reslut = 0xff; + unsigned short pkt_size; + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = fm_pmic_set_reg(cmd_buf, TX_BUF_SIZE, addr, val); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_PMIC_MODIFY, SW_RETRY_CNT, + PMIC_CONTROL_TIMEOUT, fm_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (!ret && fm_res) + read_reslut = fm_res->pmic_result[0]; + else { + WCN_DBG(FM_ERR | CHIP, "mt6632_pmic_write failed,ret(%d)\n", ret); + return -1; + } + + if (read_reslut) { + WCN_DBG(FM_ERR | CHIP, "mt6632_pmic_write failed(%02x)\n", read_reslut); + return -2; + } + + return ret; +} + +static signed int mt6632_pmic_mod(unsigned char addr, unsigned int mask_and, unsigned int mask_or) +{ + signed int ret = 0; + unsigned char read_reslut = 0xff; + unsigned short pkt_size; + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = fm_pmic_mod_reg(cmd_buf, TX_BUF_SIZE, addr, mask_and, mask_or); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_PMIC_MODIFY, SW_RETRY_CNT, + PMIC_CONTROL_TIMEOUT, fm_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (!ret && fm_res) + read_reslut = fm_res->pmic_result[0]; + else { + WCN_DBG(FM_ERR | CHIP, "mt6632_pmic_mod failed,ret(%d)\n", ret); + return -1; + } + + if (read_reslut) { + WCN_DBG(FM_ERR | CHIP, "mt6632_pmic_mod failed(%02x)\n", read_reslut); + return -2; + } + return ret; +} + +static signed int mt6632_pmic_ctrl(void) +{ + signed int ret = 0; + unsigned int val = 0; + + ret = mt6632_pmic_mod(0xa8, 0xFFFFFFF7, 0x00000008); + if (!ret) { + mt6632_pmic_read(0xa8, &val); + WCN_DBG(FM_NTC | CHIP, "0xa8 = %08x\n", val); + } else { + WCN_DBG(FM_ERR | CHIP, "mt6632_pmic_ctrl 0xa8 failed(%d)\n", ret); + return ret; + } + + ret = mt6632_pmic_mod(0xc7, 0x7FFFFFCF, 0x00000000); + if (!ret) { + mt6632_pmic_read(0xc7, &val); + WCN_DBG(FM_NTC | CHIP, "0xc7 = %08x\n", val); + } else { + WCN_DBG(FM_ERR | CHIP, "mt6632_pmic_ctrl 0xc7 failed(%d)\n", ret); + return ret; + } + + return ret; +} + +static signed int mt6632_pwrup_top_setting(void) +{ + signed int ret = 0, value = 0; + /* A0.1 Turn on FM buffer */ + ret = fm_host_reg_read(0x81020008, &value); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81020008 rd failed\n"); + return ret; + } + ret = fm_host_reg_write(0x81020008, value | 0x30); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81020008 wr failed\n"); + return ret; + } + /* A0.2 Set xtal no off when FM on */ + fm_delayus(20); + /* A0.3 release power on reset */ + ret = fm_host_reg_read(0x81020008, &value); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81020008 rd failed\n"); + return ret; + } + ret = fm_host_reg_write(0x81020008, value | 0x1); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81020008 wr failed\n"); + return ret; + } + /* A0.4 enable fspi_mas_bclk_ck */ + ret = fm_host_reg_read(0x80000108, &value); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x80000108 rd failed\n"); + return ret; + } + ret = fm_host_reg_write(0x80000108, value | 0x00000100); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x80000108 wr failed\n"); + return ret; + } + return ret; +} + +static signed int mt6632_pwrdown_top_setting(void) +{ + signed int ret = 0, value = 0; + /* B0.1 disable fspi_mas_bclk_ck */ + ret = fm_host_reg_read(0x80000104, &value); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x80000104 rd failed\n"); + return ret; + } + ret = fm_host_reg_write(0x80000104, value | 0x00000100); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x80000104 wr failed\n"); + return ret; + } + /* B0.2 set power off reset */ + ret = fm_host_reg_read(0x81020008, &value); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81020008 rd failed\n"); + return ret; + } + ret = fm_host_reg_write(0x81020008, value & 0xFFFFFFFE); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81020008 wr failed\n"); + return ret; + } + /* B0.3 */ + fm_delayus(20); + + /* B0.4 disable MTCMOS & set Iso_en */ + ret = fm_host_reg_read(0x81020008, &value); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81020008 rd failed\n"); + return ret; + } + ret = fm_host_reg_write(0x81020008, value & 0xFFFFFFEF); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81020008 wr failed\n"); + return ret; + } +#if 0 + /* B0.5 Turn off FM buffer */ + ret = fm_host_reg_read(0x8102123c, &value); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x8102123c rd failed\n"); + return ret; + } + ret = fm_host_reg_write(0x8102123c, value | 0x40); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x8102123c wr failed\n"); + return ret; + } + /* B0.6 Clear xtal no off when FM off */ + ret = fm_host_reg_read(0x81021134, &value); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81021134 rd failed\n"); + return ret; + } + ret = fm_host_reg_write(0x81021134, value & 0xFFFFFF7F); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81021134 wr failed\n"); + return ret; + } + /* B0.7 Clear top off always on when FM off */ + ret = fm_host_reg_read(0x81020010, &value); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81020010 rd failed\n"); + return ret; + } + ret = fm_host_reg_write(0x81020010, value | 0x20000); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81020010 wr failed\n"); + return ret; + } + /* B0.9 Disable PALDO when FM off */ + ret = fm_host_reg_read(0x81021430, &value); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81021430 rd failed\n"); + return ret; + } + ret = fm_host_reg_write(0x81021430, value & 0x7FFFFFFF); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " 0x81021430 wr failed\n"); + return ret; + } +#endif + return ret; +} + +static signed int mt6632_pwrup_DSP_download(struct fm_patch_tbl *patch_tbl) +{ +#define PATCH_BUF_SIZE (4096*6) + signed int ret = 0; + signed int patch_len = 0; + unsigned char *dsp_buf = NULL; + unsigned short tmp_reg = 0; + + mt6632_hw_info.eco_ver = (signed int) mtk_wcn_wmt_ic_info_get(1); + WCN_DBG(FM_NTC | CHIP, "ECO version:0x%08x\n", mt6632_hw_info.eco_ver); + + /* FM ROM code version request */ + ret = mt6632_get_rom_version(); + if (ret >= 0) { + mt6632_hw_info.rom_ver = ret; + WCN_DBG(FM_NTC | CHIP, "ROM version: v%d\n", mt6632_hw_info.rom_ver); + } else { + WCN_DBG(FM_ERR | CHIP, "get ROM version failed\n"); + /* ret=-4 means signal got when control FM. usually get sig 9 to kill FM process. */ + /* now cancel FM power up sequence is recommended. */ + return ret; + } + + /* Wholechip FM Power Up: step 3, download patch */ + dsp_buf = fm_vmalloc(PATCH_BUF_SIZE); + if (!dsp_buf) { + WCN_DBG(FM_ERR | CHIP, "-ENOMEM\n"); + return -ENOMEM; + } + + patch_len = fm_get_patch_path(mt6632_hw_info.rom_ver, dsp_buf, PATCH_BUF_SIZE, patch_tbl); + if (patch_len <= 0) { + WCN_DBG(FM_ALT | CHIP, " fm_get_patch_path failed\n"); + ret = patch_len; + goto out; + } + + ret = fm_download_patch((const unsigned char *)dsp_buf, patch_len, IMG_PATCH); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " DL DSPpatch failed\n"); + goto out; + } + + patch_len = fm_get_coeff_path(mt6632_hw_info.rom_ver, dsp_buf, PATCH_BUF_SIZE, patch_tbl); + if (patch_len <= 0) { + WCN_DBG(FM_ALT | CHIP, " fm_get_coeff_path failed\n"); + ret = patch_len; + goto out; + } + + mt6632_hw_info.rom_ver += 1; + + tmp_reg = dsp_buf[38] | (dsp_buf[39] << 8); /* to be confirmed */ + mt6632_hw_info.patch_ver = (signed int) tmp_reg; + WCN_DBG(FM_NTC | CHIP, "Patch version: 0x%08x\n", mt6632_hw_info.patch_ver); + + ret = fm_download_patch((const unsigned char *)dsp_buf, patch_len, IMG_COEFFICIENT); + if (ret) { + WCN_DBG(FM_ERR | CHIP, " DL DSPcoeff failed\n"); + goto out; + } + fm_reg_write(0x90, 0x0040); + fm_reg_write(0x90, 0x0000); +out: + if (dsp_buf) { + fm_vfree(dsp_buf); + dsp_buf = NULL; + } + return ret; +} + +static signed int mt6632_pwrup_clock_on_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + unsigned short de_emphasis; + /* unsigned short osc_freq; */ + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + de_emphasis = fm_config.rx_cfg.deemphasis; + de_emphasis &= 0x0001; /* rang 0~1 */ + + /* B1.1 Enable digital OSC */ + pkt_size += fm_bop_write(0x60, 0x0003, &buf[pkt_size], buf_size - pkt_size); /* wr 60 3 */ + pkt_size += fm_bop_udelay(100, &buf[pkt_size], buf_size - pkt_size); /* delay 100us */ + /* B1.3 Release HW clock gating */ + pkt_size += fm_bop_write(0x60, 0x0007, &buf[pkt_size], buf_size - pkt_size); /* wr 60 7 */ + /* B1.4 Set FM long/short antenna:1: short_antenna 0: long antenna(default) */ + /* pkt_size += fm_bop_modify(0x61, 0xFFEF, 0x0000, &buf[pkt_size], buf_size - pkt_size); */ + /* B1.5 Set audio output mode (lineout/I2S) 0:lineout, 1:I2S */ + /* + *if (mt6632_fm_config.aud_cfg.aud_path == FM_AUD_ANALOG) + * pkt_size += fm_bop_modify(0x61, 0xFF7F, 0x0000, &buf[pkt_size], buf_size - pkt_size); + *else + * pkt_size += fm_bop_modify(0x61, 0xFF7F, 0x0080, &buf[pkt_size], buf_size - pkt_size); + */ + /* B1.6 Set deemphasis setting */ + 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); */ + + return pkt_size - 4; +} +/* + * mt6632_pwrup_clock_on - Wholechip FM Power Up: step 1, FM Digital Clock enable + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6632_pwrup_clock_on(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6632_pwrup_clock_on_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +static signed int mt6632_pwrup_digital_init_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* F1.4 Set appropriate interrupt mask behavior as desired(RX) */ + /* pkt_size += fm_bop_write(0x6A, 0x0021, &buf[pkt_size], buf_size - pkt_size);//wr 6A 0021 */ + pkt_size += fm_bop_write(0x6B, 0x0021, &buf[pkt_size], buf_size - pkt_size); /* wr 6B 0021 */ + /* F1.9 Enable HW auto control */ + pkt_size += fm_bop_write(0x60, 0x000F, &buf[pkt_size], buf_size - pkt_size); /* wr 60 f */ + /* F1.10 Release ASIP reset */ + pkt_size += fm_bop_modify(0x61, 0xFFFD, 0x0002, &buf[pkt_size], buf_size - pkt_size); /* wr 61 D1=1 */ + /* F1.11 Enable ASIP power */ + pkt_size += fm_bop_modify(0x61, 0xFFFE, 0x0000, &buf[pkt_size], buf_size - pkt_size); /* wr 61 D0=0 */ + pkt_size += fm_bop_udelay(100000, &buf[pkt_size], buf_size - pkt_size); /* delay 100ms */ + /* F1.13 Check HW intitial complete */ + pkt_size += fm_bop_rd_until(0x64, 0x001F, 0x0002, &buf[pkt_size], buf_size - pkt_size); /* Poll 64[0~4] = 2 */ + + return pkt_size - 4; +} + +/* + * mt6632_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 + */ +static signed int mt6632_pwrup_digital_init(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6632_pwrup_digital_init_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +static signed int mt6632_pwrdown_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* Disable HW clock control */ + pkt_size += fm_bop_write(0x60, 0x0107, &buf[pkt_size], buf_size - pkt_size); /* wr 60 107 */ + /* 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 */ + + return pkt_size - 4; +} +/* + * mt6632_pwrdown - Wholechip FM Power down: Digital Modem Power Down + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6632_pwrdown(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6632_pwrdown_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +static signed int mt6632_tune_reg_op(unsigned char *buf, signed int buf_size, unsigned short freq, + unsigned short chan_para) +{ + signed int pkt_size = 4; + + WCN_DBG(FM_ALT | CHIP, "%s enter mt6632_tune function\n", __func__); + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + freq = (freq - 6400) * 2 / 10; + + /* 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); + /* 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); + /* 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); + /* 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); +#endif + + WCN_DBG(FM_ALT | CHIP, "%s leave mt6632_tune function\n", __func__); + + return pkt_size - 4; +} + +/* + * mt6632_tune - execute tune action, + * @buf - target buf + * @buf_size - buffer size + * @freq - 760 ~ 1080, 100KHz unit + * return package size + */ +static signed int mt6632_tune(unsigned char *buf, signed int buf_size, unsigned short freq, + unsigned short chan_para) +{ + signed int pkt_size = 0; + + pkt_size = mt6632_tune_reg_op(buf, buf_size, freq, chan_para); + return fm_op_seq_combine_cmd(buf, FM_TUNE_OPCODE, pkt_size); +} + +static signed int mt6632_PowerUp(unsigned short *chip_id, unsigned short *device_id) +{ + signed int ret = 0; + unsigned short pkt_size; + unsigned short tmp_reg = 0; + + if (chip_id == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (device_id == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + WCN_DBG(FM_DBG | CHIP, "pwr on seq......\n"); + + ret = mt6632_pmic_ctrl(); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "mt6632_pmic_ctrl failed\n"); + return ret; + } + fm_delayus(240); + + ret = mt6632_pwrup_top_setting(); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "mt6632_pwrup_top_setting failed\n"); + return ret; + } + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6632_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_ERR | CHIP, "mt6632_pwrup_clock_on failed\n"); + return ret; + } + /* read HW version */ + fm_reg_read(0x62, &tmp_reg); + *chip_id = tmp_reg; + *device_id = tmp_reg; + mt6632_hw_info.chip_id = (signed int) tmp_reg; + WCN_DBG(FM_NTC | CHIP, "chip_id:0x%04x\n", tmp_reg); + + if (mt6632_hw_info.chip_id != 0x6632) { + WCN_DBG(FM_NTC | CHIP, "fm sys error!\n"); + return -FM_EPARA; + } + ret = mt6632_pwrup_DSP_download(mt6632_patch_tbl); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "mt6632_pwrup_DSP_download failed\n"); + return ret; + } + + if ((fm_config.aud_cfg.aud_path == FM_AUD_MRGIF) + || (fm_config.aud_cfg.aud_path == FM_AUD_I2S)) { + mt6632_I2s_Setting(FM_I2S_ON, fm_config.aud_cfg.i2s_info.mode, + fm_config.aud_cfg.i2s_info.rate); + /* mt_combo_audio_ctrl(COMBO_AUDIO_STATE_2); */ + mtk_wcn_cmb_stub_audio_ctrl((CMB_STUB_AIF_X) CMB_STUB_AIF_2); + } + /* Wholechip FM Power Up: step 4, FM Digital Init: fm_rgf_maincon */ + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6632_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_ERR | CHIP, "mt6632_pwrup_digital_init failed\n"); + return ret; + } + + /* FM RF fine tune setting */ + fm_reg_write(0x60, 0x7); + fm_reg_write(0x2d, 0x1fa); + fm_reg_write(0x60, 0xF); + + WCN_DBG(FM_NTC | CHIP, "pwr on seq ok\n"); + + return ret; +} + +static signed int mt6632_PowerDown(void) +{ + signed int ret = 0; + unsigned short pkt_size; + + WCN_DBG(FM_DBG | CHIP, "pwr down seq\n"); + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6632_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_ERR | CHIP, "mt6632_pwrdown failed\n"); + return ret; + } + + ret = mt6632_pwrdown_top_setting(); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "mt6632_pwrdown_top_setting failed\n"); + return ret; + } + + return ret; +} + +/* just for dgb */ +static bool mt6632_SetFreq(unsigned short freq) +{ + signed int ret = 0; + unsigned short pkt_size; + unsigned short chan_para = 0; + unsigned short tmp_reg[4]; + + fm_cb_op->cur_freq_set(freq); + +#if 0 + /* MCU clock adjust if need */ + ret = mt6632_mcu_dese(freq, NULL); + if (ret < 0) + WCN_DBG(FM_ERR | MAIN, "mt6632_mcu_dese FAIL:%d\n", ret); + + WCN_DBG(FM_INF | MAIN, "MCU %d\n", ret); +#endif + + /* GPS clock adjust if need */ + ret = mt6632_gps_dese(freq, NULL); + if (ret < 0) + WCN_DBG(FM_ERR | MAIN, "mt6632_gps_dese FAIL:%d\n", ret); + + WCN_DBG(FM_INF | MAIN, "GPS %d\n", ret); + + ret = fm_reg_write(0x60, 0x0007); + if (ret) + WCN_DBG(FM_ALT | MAIN, "set freq write 0x60 fail\n"); + + if (mt6632_TDD_chan_check(freq)) { + ret = fm_set_bits(0x30, 0x0004, 0xFFF9); /* use TDD solution */ + if (ret) + WCN_DBG(FM_ALT | MAIN, "set freq write 0x30 fail\n"); + } else { + ret = fm_set_bits(0x30, 0x0000, 0xFFF9); /* default use FDD solution */ + if (ret) + WCN_DBG(FM_ALT | MAIN, "set freq write 0x30 fail\n"); + } + ret = fm_reg_write(0x60, 0x000F); + if (ret) + WCN_DBG(FM_ALT | MAIN, "set freq write 0x60 fail\n"); + + chan_para = mt6632_chan_para_get(freq); + WCN_DBG(FM_DBG | CHIP, "%d chan para = %d\n", (signed int) freq, (signed int) chan_para); + + if (FM_LOCK(cmd_buf_lock)) + return false; + pkt_size = mt6632_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) { + fm_reg_read(0x64, &tmp_reg[0]); + fm_reg_read(0x69, &tmp_reg[1]); + fm_reg_read(0x6c, &tmp_reg[2]); + WCN_DBG(FM_ERR | CHIP, "mt6632_tune failed\n"); + WCN_DBG(FM_ERR | CHIP, "0x64[0x%04x],0x69[0x%04x],0x6c[0x%04x]\n", tmp_reg[0], tmp_reg[1], tmp_reg[2]); + return false; + } + + WCN_DBG(FM_DBG | CHIP, "set freq to %d ok\n", freq); + return true; +} + +#define FM_CQI_LOG_PATH "/mnt/sdcard/fmcqilog" + +static signed int mt6632_full_cqi_get(signed int min_freq, signed int max_freq, signed int space, signed int cnt) +{ + signed int ret = 0; + unsigned short pkt_size; + unsigned short freq, orig_freq; + signed int i, j, k; + signed int space_val, max, min, num; + struct mt6632_full_cqi *p_cqi; + unsigned char *cqi_log_title = "Freq, RSSI, PAMD, PR, FPAMD, MR, ATDC, PRX, ATDEV, SMGain, DltaRSSI\n"; + unsigned char cqi_log_buf[100] = { 0 }; + signed int pos; + unsigned char cqi_log_path[100] = { 0 }; + + WCN_DBG(FM_DBG | CHIP, "6632 cqi log start\n"); + /* for soft-mute tune, and get cqi */ + freq = fm_cb_op->cur_freq_get(); + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + /* get cqi */ + orig_freq = freq; + if (fm_get_channel_space(min_freq) == 0) + min = min_freq * 10; + else + min = min_freq; + + if (fm_get_channel_space(max_freq) == 0) + 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; (orig_freq == 10000) && (g_dbg_level == 0xffffffff) && (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)); + if (sprintf(&cqi_log_path[strlen(FM_CQI_LOG_PATH)], "%d.txt", k + 1) < 0) + WCN_DBG(FM_NTC | CHIP, "sprintf fail\n"); + 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 = fm_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, fm_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (!ret && fm_res) { + WCN_DBG(FM_NTC | CHIP, "smt cqi size %d\n", fm_res->cqi[0]); + p_cqi = (struct mt6632_full_cqi *)&fm_res->cqi[2]; + for (i = 0; i < fm_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 */ + if (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) < 0) + WCN_DBG(FM_NTC | CHIP, "sprintf fail\n"); + /* write back to log file */ + fm_file_write(cqi_log_path, cqi_log_buf, strlen(cqi_log_buf), &pos); + } + } else { + WCN_DBG(FM_ERR | 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_DBG | CHIP, "6632 cqi log done\n"); + + return ret; +} + +/* + * mt6632_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 signed int mt6632_GetCurRSSI(signed int *pRSSI) +{ + unsigned short tmp_reg = 0; + + /* TODO: check reg */ + fm_reg_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 unsigned short mt6632_vol_tbl[16] = { + 0x0000, 0x0519, 0x066A, 0x0814, + 0x0A2B, 0x0CCD, 0x101D, 0x1449, + 0x198A, 0x2027, 0x287A, 0x32F5, + 0x4027, 0x50C3, 0x65AD, 0x7FFF +}; + +static signed int mt6632_SetVol(unsigned char vol) +{ + signed int ret = 0; + + /* TODO: check reg */ + vol = (vol > 15) ? 15 : vol; + ret = fm_reg_write(0x7D, mt6632_vol_tbl[vol]); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "Set vol=%d Failed\n", vol); + return ret; + } + + 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 signed int mt6632_GetVol(unsigned char *pVol) +{ + int ret = 0; + unsigned short tmp = 0; + signed int i; + + if (pVol == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + /* TODO: check reg */ + ret = fm_reg_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 (mt6632_vol_tbl[i] == tmp) { + *pVol = i; + break; + } + } + + WCN_DBG(FM_DBG | CHIP, "Get vol=%d OK\n", *pVol); + return 0; +} + +static signed int mt6632_dump_reg(void) +{ + signed int i; + unsigned short TmpReg = 0; + + for (i = 0; i < 0xff; i++) { + fm_reg_read(i, &TmpReg); + WCN_DBG(FM_NTC | CHIP, "0x%02x=0x%04x\n", i, TmpReg); + } + return 0; +} + +static bool mt6632_GetMonoStereo(unsigned short *pMonoStereo) +{ +#define FM_BF_STEREO 0x1000 + unsigned short TmpReg = 0; + + /* TODO: check reg */ + if (pMonoStereo) { + fm_reg_read(FM_RSSI_IND, &TmpReg); + *pMonoStereo = (TmpReg & FM_BF_STEREO) >> 12; + } else { + WCN_DBG(FM_ERR | CHIP, "MonoStero: para err\n"); + return false; + } + + WCN_DBG(FM_DBG | CHIP, "MonoStero:0x%04x\n", *pMonoStereo); + return true; +} + +static signed int mt6632_SetMonoStereo(signed int MonoStereo) +{ + signed int ret = 0; +#define FM_FORCE_MS 0x0008 + + WCN_DBG(FM_DBG | CHIP, "set to %s\n", MonoStereo ? "mono" : "auto"); + /* TODO: check reg */ + + fm_reg_write(0x60, 0x3007); + + if (MonoStereo) + ret = fm_set_bits(0x75, FM_FORCE_MS, ~FM_FORCE_MS); + else + ret = fm_set_bits(0x75, 0x0000, ~FM_FORCE_MS); + + return ret; +} + +static signed int mt6632_GetCapArray(signed int *ca) +{ + unsigned short dataRead = 0; + unsigned short tmp = 0; + + /* TODO: check reg */ + if (ca == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + fm_reg_read(0x60, &tmp); + fm_reg_write(0x60, tmp & 0xFFF7); /* 0x60 D3=0 */ + + fm_reg_read(0x26, &dataRead); + *ca = dataRead; + + fm_reg_write(0x60, tmp); /* 0x60 D3=1 */ + return 0; +} + +/* + * mt6632_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 bool mt6632_GetCurPamd(unsigned short *pPamdLevl) +{ + unsigned short tmp_reg = 0; + unsigned short dBvalue, valid_cnt = 0; + int i, total = 0; + + for (i = 0; i < 8; i++) { + /* TODO: check reg */ + if (fm_reg_read(FM_ADDR_PAMD, &tmp_reg)) { + *pPamdLevl = 0; + return 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); + } + fm_delayms(3); + } + if (valid_cnt != 0) + *pPamdLevl = total / valid_cnt; + else + *pPamdLevl = 0; + + WCN_DBG(FM_NTC | CHIP, "PAMD=%d\n", *pPamdLevl); + return true; +} + +static signed int MT6632_FMOverBT(bool enable) +{ + signed int ret = 0; + + WCN_DBG(FM_NTC | CHIP, "+%s():\n", __func__); + + if (enable == true) { + /* change I2S to slave mode and 48K sample rate */ + if (mt6632_I2s_Setting(FM_I2S_ON, FM_I2S_SLAVE, FM_I2S_48K)) + goto out; + WCN_DBG(FM_NTC | CHIP, "set FM via BT controller\n"); + } else if (enable == false) { + /* change I2S to master mode and 44.1K sample rate */ + if (mt6632_I2s_Setting(FM_I2S_ON, FM_I2S_MASTER, FM_I2S_44K)) + 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; +} + +/* + * mt6632_I2s_Setting - set the I2S state on MT6632 + * @onoff - I2S on/off + * @mode - I2S mode: Master or Slave + * + * Return:0, if success; error code, if failed + */ +static signed int mt6632_I2s_Setting(signed int onoff, signed int mode, signed int sample) +{ + unsigned short tmp_state = 0; + unsigned short tmp_mode = 0; + unsigned short tmp_sample = 0; + signed int ret = 0; + + if (onoff == FM_I2S_ON) { + tmp_state = 0x0002; /* I2S enable and standard I2S mode, 0x9B D0,D1=1 */ + fm_config.aud_cfg.i2s_info.status = FM_I2S_ON; + } else if (onoff == FM_I2S_OFF) { + tmp_state = 0x0000; /* I2S off, 0x9B D0,D1=0 */ + fm_config.aud_cfg.i2s_info.status = FM_I2S_OFF; + } else { + WCN_DBG(FM_ERR | CHIP, "%s():[onoff=%d]\n", __func__, onoff); + ret = -FM_EPARA; + goto out; + } + + if (mode == FM_I2S_MASTER) { + tmp_mode = 0x0000; /* 6632 as I2S master, set 0x9B D3=0 */ + fm_config.aud_cfg.i2s_info.mode = FM_I2S_MASTER; + } else if (mode == FM_I2S_SLAVE) { + tmp_mode = 0x0008; /* 6632 as I2S slave, set 0x9B D3=1 */ + fm_config.aud_cfg.i2s_info.mode = FM_I2S_SLAVE; + } else { + WCN_DBG(FM_ERR | CHIP, "%s():[mode=%d]\n", __func__, mode); + ret = -FM_EPARA; + goto out; + } + + if (sample == FM_I2S_32K) { + tmp_sample = 0x0000; /* 6632 I2S 32KHz sample rate, 0x5F D11~12 */ + fm_config.aud_cfg.i2s_info.rate = FM_I2S_32K; + } else if (sample == FM_I2S_44K) { + tmp_sample = 0x0800; /* 6632 I2S 44.1KHz sample rate */ + fm_config.aud_cfg.i2s_info.rate = FM_I2S_44K; + } else if (sample == FM_I2S_48K) { + tmp_sample = 0x1000; /* 6632 I2S 48KHz sample rate */ + fm_config.aud_cfg.i2s_info.rate = FM_I2S_48K; + } else { + WCN_DBG(FM_ERR | CHIP, "%s():[sample=%d]\n", __func__, sample); + ret = -FM_EPARA; + goto out; + } + + ret = fm_reg_write(0x60, 0x0007); + if (ret) + goto out; + + ret = fm_set_bits(0x5F, tmp_sample, 0xE7FF); + if (ret) + goto out; + + ret = fm_set_bits(0x9B, tmp_mode, 0xFFF7); + if (ret) + goto out; + + ret = fm_set_bits(0x9B, tmp_state, 0xFFFD); + if (ret) + goto out; + + ret = fm_reg_write(0x60, 0x000F); + if (ret) + goto out; + WCN_DBG(FM_NTC | CHIP, "[onoff=%s][mode=%s][sample=%d](0)33KHz,(1)44.1KHz,(2)48KHz\n", + (onoff == FM_I2S_ON) ? "On" : "Off", (mode == FM_I2S_MASTER) ? "Master" : "Slave", sample); +out: + return ret; +} + +static signed int mt6632fm_get_audio_info(struct fm_audio_info_t *data) +{ + fm_memcpy(data, &fm_config.aud_cfg, sizeof(struct fm_audio_info_t)); + return 0; +} + +static signed int mt6632_i2s_info_get(signed int *ponoff, signed int *pmode, signed int *psample) +{ + *ponoff = fm_config.aud_cfg.i2s_info.status; + *pmode = fm_config.aud_cfg.i2s_info.mode; + *psample = fm_config.aud_cfg.i2s_info.rate; + + return 0; +} + +static signed int mt6632_hw_info_get(struct fm_hw_info *req) +{ + if (req == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + req->chip_id = mt6632_hw_info.chip_id; + req->eco_ver = mt6632_hw_info.eco_ver; + req->patch_ver = mt6632_hw_info.patch_ver; + req->rom_ver = mt6632_hw_info.rom_ver; + + return 0; +} + +static signed int mt6632_pre_search(void) +{ + mt6632_RampDown(); + return 0; +} + +static signed int mt6632_restore_search(void) +{ + mt6632_RampDown(); + return 0; +} + +/* +*freq: 8750~10800 +*valid: true-valid channel,false-invalid channel +*return: true- smt success, false-smt fail +*/ +static signed int mt6632_soft_mute_tune(unsigned short freq, signed int *rssi, signed int *valid) +{ + signed int ret = 0; + unsigned short pkt_size; + /* unsigned short freq;//, orig_freq; */ + struct mt6632_full_cqi *p_cqi; + signed int RSSI = 0, PAMD = 0, MR = 0, ATDC = 0; + unsigned int PRX = 0, ATDEV = 0; + unsigned short softmuteGainLvl = 0; + + ret = mt6632_chan_para_get(freq); + if (ret == 2) + ret = fm_set_bits(FM_CHANNEL_SET, 0x2000, 0x0FFF); /* mdf HiLo */ + else + ret = fm_set_bits(FM_CHANNEL_SET, 0x0000, 0x0FFF); /* clear FA/HL/ATJ */ +#if 0 + fm_reg_write(0x60, 0x0007); + if (mt6632_TDD_chan_check(freq)) + fm_set_bits(0x30, 0x0004, 0xFFF9); /* use TDD solution */ + else + fm_set_bits(0x30, 0x0000, 0xFFF9); /* default use FDD solution */ + fm_reg_write(0x60, 0x000F); +#endif + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = fm_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, fm_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (!ret && fm_res) { + WCN_DBG(FM_DBG | CHIP, "smt cqi size %d\n", fm_res->cqi[0]); + p_cqi = (struct mt6632_full_cqi *)&fm_res->cqi[2]; + + + 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 ((fm_config.rx_cfg.long_ana_rssi_th <= RSSI) + && (fm_config.rx_cfg.pamd_th >= PAMD) + && (fm_config.rx_cfg.atdc_th >= ATDC) + && (fm_config.rx_cfg.mr_th <= MR) + && (fm_config.rx_cfg.prx_th <= PRX) + && (ATDEV >= ATDC) /* sync scan algorithm */ + && (fm_config.rx_cfg.smg_th <= softmuteGainLvl)) { + *valid = true; + } else { + *valid = false; + } + WCN_DBG(FM_NTC | CHIP, + "valid=%d, freq %d, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x\n", + *valid, 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 = RSSI; + } else { + WCN_DBG(FM_ERR | CHIP, "smt get CQI failed\n"); + return false; + } + return true; +} + +/* +*parm: +* parm.th_type: 0, RSSI. 1,desense RSSI. 2,SMG. +* parm.th_val: threshold value +*/ +static signed int mt6632_set_search_th(signed int idx, signed int val, signed int reserve) +{ + switch (idx) { + case 0: { + fm_config.rx_cfg.long_ana_rssi_th = val; + WCN_DBG(FM_NTC | CHIP, "set rssi th =%d\n", val); + break; + } + case 1: { + fm_config.rx_cfg.desene_rssi_th = val; + WCN_DBG(FM_NTC | CHIP, "set desense rssi th =%d\n", val); + break; + } + case 2: { + fm_config.rx_cfg.smg_th = val; + WCN_DBG(FM_NTC | CHIP, "set smg th =%d\n", val); + break; + } + default: + break; + } + return 0; +} + +#if 0 +static const unsigned short mt6632_mcu_dese_list[] = { + 0 /* 7630, 7800, 7940, 8320, 9260, 9600, 9710, 9920, 10400, 10410 */ +}; + +static const unsigned short mt6632_gps_dese_list[] = { + 0 /* 7850, 7860 */ +}; +#endif + +static const signed char mt6632_chan_para_map[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6500~6595 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6600~6695 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6700~6795 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6800~6895 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6900~6995 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7000~7095 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7100~7195 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7200~7295 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7300~7395 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7400~7495 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7500~7595 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 */ + 8, 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 */ + 0, 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, 0, 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, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9400~9495 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9500~9595 */ + 0, 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, 0, 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, 0, 0, 0, 0, /* 9900~9995 */ + 0, 0, 0, 0, 0, 0, 0, 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, 0, 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 */ + 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10700~10795 */ + 0 /* 10800 */ +}; + +static const unsigned short mt6632_TDD_list[] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6500~6595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6600~6695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6700~6795 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6800~6895 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6900~6995 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7000~7095 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7100~7195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7200~7295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7300~7395 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7400~7495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7500~7595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7600~7695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7700~7795 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7800~7895 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7900~7995 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8000~8095 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8100~8195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8200~8295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8300~8395 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8400~8495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8500~8595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8600~8695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8700~8795 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8800~8895 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8900~8995 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9000~9095 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9100~9195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9200~9295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9300~9395 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9400~9495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9500~9595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9600~9695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9700~9795 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9800~9895 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9900~9995 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10000~10095 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10100~10195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10200~10295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10300~10395 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10400~10495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10500~10595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10600~10695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10700~10795 */ + 0x0000 /* 10800 */ +}; + +static const unsigned short mt6632_TDD_Mask[] = { + 0x0001, 0x0010, 0x0100, 0x1000 +}; + +static const unsigned short mt6632_scan_dese_list[] = { + 7800, 9210, 9220, 9600, 9980, 10400, 10750, 10760 +}; + + +/* return value: 0, not a de-sense channel; 1, this is a de-sense channel; else error no */ +static signed int mt6632_is_dese_chan(unsigned short freq) +{ + signed int size; + + /* return 0;//HQA only :skip desense channel check. */ + size = ARRAY_SIZE(mt6632_scan_dese_list); + + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + while (size) { + if (mt6632_scan_dese_list[size - 1] == freq) + return 1; + + size--; + } + + return 0; +} + +static bool mt6632_TDD_chan_check(unsigned short freq) +{ + unsigned int i = 0; + unsigned short freq_tmp = freq; + signed int ret = 0; + + ret = fm_get_channel_space(freq_tmp); + if (ret == 0) + freq_tmp *= 10; + else if (ret == -1) + return false; + + i = (freq_tmp - 6500) / 5; + if ((i / 4) >= ARRAY_SIZE(mt6632_TDD_list)) { + WCN_DBG(FM_ERR | CHIP, "Freq index out of range(%d),max(%zd)\n", + i / 4, ARRAY_SIZE(mt6632_TDD_list)); + return false; + } + + if (mt6632_TDD_list[i / 4] & mt6632_TDD_Mask[i % 4]) { + WCN_DBG(FM_DBG | CHIP, "Freq %d use TDD solution\n", freq); + return true; + } else + return false; +} + +/* 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 signed int mt6632_desense_check(unsigned short freq, signed int rssi) +{ + if (mt6632_is_dese_chan(freq)) { + if (rssi < fm_config.rx_cfg.desene_rssi_th) + return 1; + + WCN_DBG(FM_DBG | CHIP, "desen_rssi %d th:%d\n", rssi, fm_config.rx_cfg.desene_rssi_th); + } + return 0; +} + +/* get channel parameter, HL side/ FA / ATJ */ +static unsigned short mt6632_chan_para_get(unsigned short freq) +{ + signed int pos, size; + + /* return 0;//for HQA only: skip FA/HL/ATJ */ + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + if (freq < 6500) + return 0; + + pos = (freq - 6500) / 5; + size = ARRAY_SIZE(mt6632_chan_para_map); + + pos = (pos > (size - 1)) ? (size - 1) : pos; + + return mt6632_chan_para_map[pos]; +} + +static signed int mt6632_gps_dese(unsigned short freq, void *arg) +{ + /*enum fm_gps_desense_t state = FM_GPS_DESE_DISABLE;*/ + + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + WCN_DBG(FM_NTC | CHIP, "%s, [freq=%d]\n", __func__, (int)freq); + + /* request 6632 GPS change clk */ + if ((freq >= 7690) && (freq <= 8230)) { + WCN_DBG(FM_NTC | CHIP, "gps desense disable\n"); + if (!mtk_wcn_wmt_dsns_ctrl(WMTDSNS_FM_GPS_DISABLE)) + return -1; + } + + if ((freq >= 8460) && (freq <= 9120)) { + WCN_DBG(FM_NTC | CHIP, "gps desense enable\n"); + if (!mtk_wcn_wmt_dsns_ctrl(WMTDSNS_FM_GPS_ENABLE)) + return -1; + } + + return 1; +} + + +signed int fm_low_ops_register(struct fm_callback *cb, struct fm_basic_interface *bi) +{ + signed int ret = 0; + /* Basic functions. */ + + if (bi == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,bi invalid pointer\n", __func__); + return -FM_EPARA; + } + if (cb->cur_freq_get == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,cb->cur_freq_get invalid pointer\n", __func__); + return -FM_EPARA; + } + if (cb->cur_freq_set == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,cb->cur_freq_set invalid pointer\n", __func__); + return -FM_EPARA; + } + fm_cb_op = cb; + + bi->pwron = mt6632_pwron; + bi->pwroff = mt6632_pwroff; + bi->pmic_read = mt6632_pmic_read; + bi->pmic_write = mt6632_pmic_write; + bi->chipid_get = mt6632_get_chipid; + bi->mute = mt6632_Mute; + bi->rampdown = mt6632_RampDown; + bi->pwrupseq = mt6632_PowerUp; + bi->pwrdownseq = mt6632_PowerDown; + bi->setfreq = mt6632_SetFreq; + /* bi->low_pwr_wa = MT6632fm_low_power_wa_default; */ + bi->i2s_set = mt6632_I2s_Setting; + bi->rssiget = mt6632_GetCurRSSI; + bi->volset = mt6632_SetVol; + bi->volget = mt6632_GetVol; + bi->dumpreg = mt6632_dump_reg; + bi->msget = mt6632_GetMonoStereo; + bi->msset = mt6632_SetMonoStereo; + bi->pamdget = mt6632_GetCurPamd; + /* bi->em = mt6632_em_test; */ + bi->anaswitch = mt6632_SetAntennaType; + bi->anaget = mt6632_GetAntennaType; + bi->caparray_get = mt6632_GetCapArray; + bi->hwinfo_get = mt6632_hw_info_get; + bi->fm_via_bt = MT6632_FMOverBT; + bi->i2s_get = mt6632_i2s_info_get; + bi->is_dese_chan = mt6632_is_dese_chan; + bi->softmute_tune = mt6632_soft_mute_tune; + bi->desense_check = mt6632_desense_check; + bi->cqi_log = mt6632_full_cqi_get; + bi->pre_search = mt6632_pre_search; + bi->restore_search = mt6632_restore_search; + bi->set_search_th = mt6632_set_search_th; + bi->get_aud_info = mt6632fm_get_audio_info; + + cmd_buf_lock = fm_lock_create("32_cmd"); + ret = fm_lock_get(cmd_buf_lock); + + cmd_buf = fm_zalloc(TX_BUF_SIZE + 1); + + if (!cmd_buf) { + WCN_DBG(FM_ERR | CHIP, "6632 fm lib alloc tx buf failed\n"); + ret = -1; + } + + return ret; +} + +signed int fm_low_ops_unregister(struct fm_basic_interface *bi) +{ + signed int ret = 0; + /* Basic functions. */ + if (bi == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,bi invalid pointer\n", __func__); + return -FM_EPARA; + } + + if (cmd_buf) { + fm_free(cmd_buf); + cmd_buf = NULL; + } + + ret = fm_lock_put(cmd_buf_lock); + fm_memset(bi, 0, sizeof(struct fm_basic_interface)); + + fm_cb_op = NULL; + + return ret; +} + diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/mt6632/pub/mt6632_fm_rds.c b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6632/pub/mt6632_fm_rds.c new file mode 100644 index 0000000000000..f0160a48d0bf7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6632/pub/mt6632_fm_rds.c @@ -0,0 +1,329 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#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 "mt6632_fm_reg.h" +#include "fm_cmd.h" + +static bool bRDS_FirstIn; /* false */ +static unsigned int gBLER_CHK_INTERVAL = 500; +static unsigned short GOOD_BLK_CNT = 0, BAD_BLK_CNT; +static unsigned char BAD_BLK_RATIO; + +static struct fm_basic_interface *fm_bi; + +static bool mt6632_RDS_support(void); +static signed int mt6632_RDS_enable(void); +static signed int mt6632_RDS_disable(void); +static unsigned short mt6632_RDS_Get_GoodBlock_Counter(void); +static unsigned short mt6632_RDS_Get_BadBlock_Counter(void); +static unsigned char mt6632_RDS_Get_BadBlock_Ratio(void); +static unsigned int mt6632_RDS_Get_BlerCheck_Interval(void); +/* static void mt6632_RDS_GetData(unsigned short *data, unsigned short datalen); */ +static void mt6632_RDS_Init_Data(struct rds_t *pstRDSData); + +static bool mt6632_RDS_support(void) +{ + return true; +} + +static signed int mt6632_RDS_enable(void) +{ + signed int ret = 0; + unsigned short dataRead = 0; + + WCN_DBG(FM_DBG | RDSC, "rds enable\n"); + /* ret = fm_reg_read(FM_RDS_CFG0, &dataRead); */ + ret = fm_reg_write(FM_RDS_CFG0, 6); /* set buf_start_th */ + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds enable write 0x80 fail\n"); + return ret; + } + ret = fm_reg_read(FM_MAIN_CTRL, &dataRead); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds enable read 0x63 fail\n"); + return ret; + } + ret = fm_reg_write(FM_MAIN_CTRL, dataRead | (RDS_MASK)); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds enable write 0x63 fail\n"); + return ret; + } + + return ret; +} + +static signed int mt6632_RDS_disable(void) +{ + signed int ret = 0; + unsigned short dataRead = 0; + + WCN_DBG(FM_DBG | RDSC, "rds disable\n"); + ret = fm_reg_read(FM_MAIN_CTRL, &dataRead); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds disable read 0x63 fail\n"); + return ret; + } + ret = fm_reg_write(FM_MAIN_CTRL, dataRead & (~RDS_MASK)); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds disable write 0x63 fail\n"); + return ret; + } + + return ret; +} + +static unsigned short mt6632_RDS_Get_GoodBlock_Counter(void) +{ + unsigned short tmp_reg = 0; + + fm_reg_read(FM_RDS_GOODBK_CNT, &tmp_reg); + GOOD_BLK_CNT = tmp_reg; + WCN_DBG(FM_DBG | RDSC, "get good block cnt:%d\n", (signed int) tmp_reg); + + return tmp_reg; +} + +static unsigned short mt6632_RDS_Get_BadBlock_Counter(void) +{ + unsigned short tmp_reg = 0; + + fm_reg_read(FM_RDS_BADBK_CNT, &tmp_reg); + BAD_BLK_CNT = tmp_reg; + WCN_DBG(FM_DBG | RDSC, "get bad block cnt:%d\n", (signed int) tmp_reg); + + return tmp_reg; +} + +static unsigned char mt6632_RDS_Get_BadBlock_Ratio(void) +{ + unsigned short tmp_reg; + unsigned short gbc; + unsigned short bbc; + + gbc = mt6632_RDS_Get_GoodBlock_Counter(); + bbc = mt6632_RDS_Get_BadBlock_Counter(); + + if ((gbc + bbc) > 0) + tmp_reg = (unsigned char) (bbc * 100 / (gbc + bbc)); + else + tmp_reg = 0; + + BAD_BLK_RATIO = tmp_reg; + WCN_DBG(FM_DBG | RDSC, "get badblock ratio:%d\n", (signed int) tmp_reg); + + return tmp_reg; +} + +static signed int mt6632_RDS_BlockCounter_Reset(void) +{ + mt6632_RDS_disable(); + mt6632_RDS_enable(); + + return 0; +} + +static unsigned int mt6632_RDS_Get_BlerCheck_Interval(void) +{ + return gBLER_CHK_INTERVAL; +} + +static signed int mt6632_RDS_BlerCheck(struct rds_t *dst) +{ + return 0; +} + +#if 0 +static void RDS_Recovery_Handler(void) +{ + unsigned short tempData = 0; + + do { + fm_reg_read(FM_RDS_DATA_REG, &tempData); + fm_reg_read(FM_RDS_POINTER, &tempData); + } while (tempData & 0x3); +} +#endif + +#if 0 +static void mt6632_RDS_GetData(unsigned short *data, unsigned short 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 + + unsigned short CRC = 0, i = 0, RDS_adj = 0, RDSDataCount = 0, FM_WARorrCnt = 0; + unsigned short temp = 0, OutputPofm_s32 = 0; + + WCN_DBG(FM_DBG | RDSC, "get data\n"); + fm_reg_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_reg_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_reg_read(FM_RDS_DATA_REG, &data[0]); + + /* block B data and info handling */ + fm_reg_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_reg_read(FM_RDS_DATA_REG, &data[1]); + + /* block C data and info handling */ + fm_reg_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_reg_read(FM_RDS_DATA_REG, &data[2]); + + /* block D data and info handling */ + fm_reg_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_reg_read(FM_RDS_DATA_REG, &data[3]); + + data[4] = (CRC | RDS_adj | RDSDataCount); + data[5] = FM_WARorrCnt; + + fm_reg_read(FM_RDS_PWDI, &data[6]); + fm_reg_read(FM_RDS_PWDQ, &data[7]); + + fm_reg_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 mt6632_RDS_Init_Data(struct rds_t *pstRDSData) +{ + fm_memset(pstRDSData, 0, sizeof(struct rds_t)); + bRDS_FirstIn = 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)); +} + +bool mt6632_RDS_OnOff(struct rds_t *dst, bool bFlag) +{ + signed int ret = 0; + + if (mt6632_RDS_support() == false) { + WCN_DBG(FM_ALT | RDSC, "mt6632_RDS_OnOff failed, RDS not support\n"); + return false; + } + + if (bFlag) { + mt6632_RDS_Init_Data(dst); + ret = mt6632_RDS_enable(); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "mt6632_RDS_OnOff enable failed\n"); + return false; + } + } else { + ret = mt6632_RDS_disable(); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "mt6632_RDS_OnOff disable failed\n"); + return false; + } + } + + return true; +} + +DEFINE_RDSLOG(mt6632_rds_log); + +/* mt6632_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 signed int mt6632_rds_parser(struct rds_t *rds_dst, struct rds_rx_t *rds_raw, + signed int rds_size, unsigned short(*getfreq) (void)) +{ + mt6632_rds_log.log_in(&mt6632_rds_log, rds_raw, rds_size); + return rds_parser(rds_dst, rds_raw, rds_size, getfreq); +} + +static signed int mt6632_rds_log_get(struct rds_rx_t *dst, signed int *dst_len) +{ + return mt6632_rds_log.log_out(&mt6632_rds_log, dst, dst_len); +} + +static signed int mt6632_rds_gc_get(struct rds_group_cnt_t *dst, struct rds_t *rdsp) +{ + return rds_grp_counter_get(dst, &rdsp->gc); +} + +static signed int mt6632_rds_gc_reset(struct rds_t *rdsp) +{ + return rds_grp_counter_reset(&rdsp->gc); +} + +signed int fm_rds_ops_register(struct fm_basic_interface *bi, struct fm_rds_interface *ri) +{ + signed int ret = 0; + + if (ri == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,ri invalid pointer\n", __func__); + return -FM_EPARA; + } + fm_bi = bi; + + ri->rds_blercheck = mt6632_RDS_BlerCheck; + ri->rds_onoff = mt6632_RDS_OnOff; + ri->rds_parser = mt6632_rds_parser; + ri->rds_gbc_get = mt6632_RDS_Get_GoodBlock_Counter; + ri->rds_bbc_get = mt6632_RDS_Get_BadBlock_Counter; + ri->rds_bbr_get = mt6632_RDS_Get_BadBlock_Ratio; + ri->rds_bc_reset = mt6632_RDS_BlockCounter_Reset; + ri->rds_bci_get = mt6632_RDS_Get_BlerCheck_Interval; + ri->rds_log_get = mt6632_rds_log_get; + ri->rds_gc_get = mt6632_rds_gc_get; + ri->rds_gc_reset = mt6632_rds_gc_reset; + return ret; +} + +signed int fm_rds_ops_unregister(struct fm_rds_interface *ri) +{ + signed int ret = 0; + + if (ri == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,ri invalid pointer\n", __func__); + return -FM_EPARA; + } + + fm_bi = NULL; + fm_memset(ri, 0, sizeof(struct fm_rds_interface)); + return ret; +} + diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/mt6635/inc/mt6635_fm_lib.h b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6635/inc/mt6635_fm_lib.h new file mode 100644 index 0000000000000..339f10c41c5ae --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6635/inc/mt6635_fm_lib.h @@ -0,0 +1,73 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ +#ifndef __MT6635_FM_LIB_H__ +#define __MT6635_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 { + mt6635_E1 = 0, + mt6635_E2 +}; + +struct mt6635_fm_cqi { + unsigned short ch; + unsigned short rssi; + unsigned short reserve; +}; + +struct adapt_fm_cqi { + signed int ch; + signed int rssi; + signed int reserve; +}; + +struct mt6635_full_cqi { + unsigned short ch; + unsigned short rssi; + unsigned short pamd; + unsigned short pr; + unsigned short fpamd; + unsigned short mr; + unsigned short atdc; + unsigned short prx; + unsigned short atdev; + unsigned short smg; /* soft-mute gain */ + unsigned short drssi; /* delta rssi */ +}; + +signed int mt6635_fm_low_ops_register(struct fm_callback *cb, struct fm_basic_interface *bi); +signed int mt6635_fm_low_ops_unregister(struct fm_basic_interface *bi); +signed int mt6635_fm_rds_ops_register(struct fm_basic_interface *bi, struct fm_rds_interface *ri); +signed int mt6635_fm_rds_ops_unregister(struct fm_rds_interface *ri); + +#endif diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/mt6635/inc/mt6635_fm_reg.h b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6635/inc/mt6635_fm_reg.h new file mode 100644 index 0000000000000..9a2c77483fb3d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6635/inc/mt6635_fm_reg.h @@ -0,0 +1,57 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ +#ifndef __MT6635_FM_REG_H__ +#define __MT6635_FM_REG_H__ + +/* 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, +}; + +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 /* __MT6635_FM_REG_H__ */ diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/mt6635/pub/mt6635_2_fm_lib.c b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6635/pub/mt6635_2_fm_lib.c new file mode 100644 index 0000000000000..0cd0a24b95333 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6635/pub/mt6635_2_fm_lib.c @@ -0,0 +1,1966 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ +#include +#include + +#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_cmd.h" + +#include "mt6635_fm_reg.h" +#include "mt6635_fm_lib.h" + +#define HQA_RETURN_ZERO_MAP 0 +#define HQA_ZERO_DESENSE_MAP 0 + +/* #include "mach/mt_gpio.h" */ + +/* #define MT6635_FM_PATCH_PATH "/etc/firmware/mt6635/mt6635_fm_patch.bin" */ +/* #define MT6635_FM_COEFF_PATH "/etc/firmware/mt6635/mt6635_fm_coeff.bin" */ +/* #define MT6635_FM_HWCOEFF_PATH "/etc/firmware/mt6635/mt6635_fm_hwcoeff.bin" */ +/* #define MT6635_FM_ROM_PATH "/etc/firmware/mt6635/mt6635_fm_rom.bin" */ + +static struct fm_patch_tbl mt6635_patch_tbl[5] = { + {FM_ROM_V1, "mt6635_fm_v1_patch.bin", "mt6635_fm_v1_coeff.bin", NULL, NULL}, + {FM_ROM_V2, "mt6635_fm_v2_patch.bin", "mt6635_fm_v2_coeff.bin", NULL, NULL}, + {FM_ROM_V3, "mt6635_fm_v3_patch.bin", "mt6635_fm_v3_coeff.bin", NULL, NULL}, + {FM_ROM_V4, "mt6635_fm_v4_patch.bin", "mt6635_fm_v4_coeff.bin", NULL, NULL}, + {FM_ROM_V5, "mt6635_fm_v5_patch.bin", "mt6635_fm_v5_coeff.bin", NULL, NULL} +}; + +static struct fm_hw_info mt6635_hw_info = { + .chip_id = 0x00006635, + .eco_ver = 0x00000000, + .rom_ver = 0x00000000, + .patch_ver = 0x00000000, + .reserve = 0x00000000, +}; + +static struct fm_callback *fm_cb_op; + +/* static signed int Chip_Version = mt6635_E1; */ + +/* static bool rssi_th_set = false; */ + +#if 0 /* def CONFIG_MTK_FM_50KHZ_SUPPORT */ +static struct fm_fifo *cqi_fifo; +#endif +static signed int mt6635_is_dese_chan(unsigned short freq); + +static unsigned short mt6635_chan_para_get(unsigned short freq); +static signed int mt6635_desense_check(unsigned short freq, signed int rssi); +static bool mt6635_TDD_chan_check(unsigned short freq); +static bool mt6635_SPI_hopping_check(unsigned short freq); +static signed int mt6635_soft_mute_tune(unsigned short freq, signed int *rssi, signed int *valid); + +static signed int mt6635_pwron(signed int data) +{ + if (fm_wcn_ops.ei.wmt_func_on && !fm_wcn_ops.ei.wmt_func_on()) { + WCN_DBG(FM_ERR | CHIP, "WMT turn on FM Fail!\n"); + return -FM_ELINK; + } + + WCN_DBG(FM_NTC | CHIP, "WMT turn on FM OK!\n"); + return 0; +} + +static signed int mt6635_pwroff(signed int data) +{ + if (fm_wcn_ops.ei.wmt_func_off && !fm_wcn_ops.ei.wmt_func_off()) { + WCN_DBG(FM_ERR | CHIP, "WMT turn off FM Fail!\n"); + return -FM_ELINK; + } + + WCN_DBG(FM_NTC | CHIP, "WMT turn off FM OK!\n"); + return 0; +} + +static unsigned short mt6635_get_chipid(void) +{ + return 0x6635; +} + +/* MT6635_SetAntennaType - set Antenna type + * @type - 1, Short Antenna; 0, Long Antenna + */ +static signed int mt6635_SetAntennaType(signed int type) +{ + unsigned short dataRead = 0; + + WCN_DBG(FM_DBG | CHIP, "set ana to %s\n", type ? "short" : "long"); + fm_reg_read(FM_MAIN_CG2_CTRL, &dataRead); + + if (type) + dataRead |= ANTENNA_TYPE; + else + dataRead &= (~ANTENNA_TYPE); + + fm_reg_write(FM_MAIN_CG2_CTRL, dataRead); + + return 0; +} + +static signed int mt6635_GetAntennaType(void) +{ + unsigned short dataRead = 0; + + fm_reg_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 signed int mt6635_Mute(bool mute) +{ + signed int ret = 0; + unsigned short dataRead = 0; + + WCN_DBG(FM_DBG | CHIP, "set %s\n", mute ? "mute" : "unmute"); + /* fm_reg_read(FM_MAIN_CTRL, &dataRead); */ + fm_reg_read(0x9C, &dataRead); + + /* fm_top_reg_write(0x0050, 0x00000007); */ + if (mute == 1) + ret = fm_reg_write(0x9C, (dataRead & 0xFFFC) | 0x0003); + else + ret = fm_reg_write(0x9C, (dataRead & 0xFFFC)); + + /* fm_top_reg_write(0x0050, 0x0000000F); */ + + return ret; +} + +static signed int mt6635_rampdown_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + + /* A1. Clear DSP state */ + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFF0, 0x0000, &buf[pkt_size], buf_size - pkt_size); + /* A2. Set DSP ramp down state */ + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFFF, RAMP_DOWN, &buf[pkt_size], buf_size - pkt_size); + /* @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); + /* A6. Clear DSP ramp down state */ + pkt_size += fm_bop_modify(FM_MAIN_CTRL, (~RAMP_DOWN), 0x0000, &buf[pkt_size], buf_size - pkt_size); + /* A7. 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); + + return pkt_size - 4; +} +/* + * mt6635_rampdown - f/w will wait for STC_DONE interrupt + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6635_rampdown(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6635_rampdown_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_RAMPDOWN_OPCODE, pkt_size); +} + +/* FMSYS Ramp Down Sequence*/ +static signed int mt6635_RampDown(void) +{ + struct fm_ext_interface *ei = &fm_wcn_ops.ei; + signed int ret = 0; + unsigned int tem = 0; + unsigned short pkt_size; + /* unsigned short tmp; */ + + WCN_DBG(FM_DBG | CHIP, "ramp down\n"); + + /* switch SPI clock to 26MHz */ + if (ei->spi_clock_switch) + ret = ei->spi_clock_switch(FM_SPI_SPEED_26M); + else { + ret = -1; + WCN_DBG(FM_ERR | CHIP, "Clock switch cb is null\n"); + } + if (ret) + WCN_DBG(FM_ERR | CHIP, + "RampDown Switch SPI clock to 26MHz failed\n"); + + /* unlock 64M */ + ret = fm_host_reg_read(0x18003004, &tem); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: unlock 64M reg 0x18003004 failed\n", __func__); + ret = fm_host_reg_write(0x18003004, tem & (~(0x1 << 15))); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: unlock 64M failed\n", __func__); + + /* disable 'rf_spi_div_en' */ + ret = fm_host_reg_read(0x18001A00, &tem); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: disable rf_spi_div_en read failed\n", __func__); + ret = fm_host_reg_write(0x18001A00, tem | (0x1 << 28)); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: disable rf_spi_div_en write failed\n", __func__); + + /* A0.0 Host control RF register */ + ret = fm_set_bits(0x60, 0x0007, 0xFFF0); /*Set 0x60 [D3:D0] = 0x7*/ + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down HOST control rf: Set 0x60 [D3:D0] = 0x7 failed\n"); + return ret; + } + + /* A0.1 Update FM ADPLL fast tracking mode gain */ + ret = fm_set_bits(0x0F, 0x0000, 0xF800); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down ADPLL gainA/B: Set 0xFH [D10:D0] = 0x000 failed\n"); + return ret; + } + + /* A0.2 Host control RF register */ + ret = fm_set_bits(0x60, 0x000F, 0xFFF0); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down Host control RF registerwr top 0x60 failed\n"); + return ret; + } + /* A1. Clear dsp state*/ + ret = fm_set_bits(0x63, 0x0000, 0xFFF0); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down Host control RF registerwr top 0x63 failed\n"); + return ret; + } + /* A2. Set DSP ramp down state*/ + ret = fm_set_bits(0x63, 0x0010, 0xFFEF); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down Host control RF registerwr top 0x63 failed\n"); + return ret; + } + + /* A3. Clear STC_DONE interrupt */ + ret = fm_reg_write(FM_MAIN_INTRMASK, 0x0000); + if (ret) + WCN_DBG(FM_ERR | CHIP, "ramp down clean FM_MAIN_INTRMASK failed\n"); + + ret = fm_reg_write(FM_MAIN_EXTINTRMASK, 0x0000); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down clean FM_MAIN_EXTINTRMASK failed\n"); + return ret; + } + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6635_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; + } + + ret = fm_reg_write(FM_MAIN_EXTINTRMASK, 0x0021); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down wr FM_MAIN_EXTINTRMASK failed\n"); + return ret; + } + + ret = fm_reg_write(FM_MAIN_INTRMASK, 0x0021); + if (ret) + WCN_DBG(FM_ERR | CHIP, "ramp down wr FM_MAIN_INTRMASK failed\n"); + + return ret; +} + +static signed int mt6635_get_rom_version(void) +{ + unsigned short flag_Romcode = 0; + unsigned short nRomVersion = 0; +#define ROM_CODE_READY 0x0001 + signed int ret = 0; + + /* A1.1 DSP rom code version request enable --- set 0x61 b15=1 */ + fm_set_bits(0x61, 0x8000, 0x7FFF); + + /* A1.2 Release ASIP reset --- set 0x61 b1=1 */ + fm_set_bits(0x61, 0x0002, 0xFFFD); + + /* A1.3 Enable ASIP power --- set 0x61 b0=0 */ + fm_set_bits(0x61, 0x0000, 0xFFFE); + + /* A1.4 Wait until DSP code version ready --- wait loop 1ms */ + do { + fm_delayus(1000); + ret = fm_reg_read(0x84, &flag_Romcode); + /* ret=-4 means signal got when control FM. usually get sig 9 to kill FM process. */ + /* now cancel FM power up sequence is recommended. */ + if (ret) + return ret; + + WCN_DBG(FM_DBG | CHIP, "ROM_CODE_READY flag 0x84=%x\n", flag_Romcode); + } while (flag_Romcode != ROM_CODE_READY); + + + /* A1.5 Read FM DSP code version --- rd 0x83[15:8] */ + fm_reg_read(0x83, &nRomVersion); + nRomVersion = (nRomVersion >> 8); + + /* A1.6 DSP rom code version request disable --- set 0x61 b15=0 */ + fm_set_bits(0x61, 0x0000, 0x7FFF); + + /* A1.7 Reset ASIP --- set 0x61[1:0] = 1 */ + fm_set_bits(0x61, 0x0001, 0xFFFC); + + return (signed int) nRomVersion; +} + +static signed int mt6635_pwrup_clock_on_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + unsigned short de_emphasis; + /* unsigned short osc_freq; */ + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + de_emphasis = fm_config.rx_cfg.deemphasis; + de_emphasis &= 0x0001; /* rang 0~1 */ + /* 2,turn on top clock */ + pkt_size += fm_bop_top_write(0xA00, 0xFFFFFFFF, &buf[pkt_size], buf_size - pkt_size); + /* wr top cr a00 ffffffff */ + + /* 3,enable MTCMOS */ + pkt_size += fm_bop_top_write(0x160, 0x00000030, &buf[pkt_size], buf_size - pkt_size); + /* wr top 160 30 */ + + pkt_size += fm_bop_top_write(0x160, 0x00000035, &buf[pkt_size], buf_size - pkt_size); + /* wr top 160 35 */ + pkt_size += fm_bop_udelay(10, &buf[pkt_size], buf_size - pkt_size); + /* delay 10us */ + pkt_size += fm_bop_top_write(0x160, 0x00000015, &buf[pkt_size], buf_size - pkt_size); + /* wr top 160 15 */ + pkt_size += fm_bop_top_write(0x160, 0x00000005, &buf[pkt_size], buf_size - pkt_size); + /* wr top 160 5 */ + + pkt_size += fm_bop_udelay(10, &buf[pkt_size], buf_size - pkt_size); + /* delay 10us */ + pkt_size += fm_bop_top_write(0x160, 0x00000045, &buf[pkt_size], buf_size - pkt_size); + /* wr top 160 45 */ + + /* 4,set comspi fm slave dumy count */ + pkt_size += fm_bop_write(0x7f, 0x801f, &buf[pkt_size], buf_size - pkt_size); /* wr 7f 801f */ + + /* A. FM digital clock enable */ + /* A1. Wait 3ms */ + pkt_size += fm_bop_udelay(3000, &buf[pkt_size], buf_size - pkt_size); + + /* A2. Release HW clock gating*/ + pkt_size += fm_bop_write(0x60, 0x0007, &buf[pkt_size], buf_size - pkt_size); /* wr 60 7 */ + /* A3. Enable DSP auto clock gating */ + pkt_size += fm_bop_write(0x70, 0x0040, &buf[pkt_size], buf_size - pkt_size); /* wr 70 0040 */ + /* A4. Deemphasis setting: Set 0 for 50us, Set 1 for 75us */ + pkt_size += fm_bop_modify(0x61, ~DE_EMPHASIS, (de_emphasis << 12), &buf[pkt_size], buf_size - pkt_size); + + return pkt_size - 4; +} +/* + * mt6635_pwrup_clock_on - Wholechip FM Power Up: step 1, FM Digital Clock enable + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6635_pwrup_clock_on(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6635_pwrup_clock_on_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +static signed int mt6635_pwrup_digital_init_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* Part D FM RF&ADPLL divider setting */ + + /* D2.1 set cell mode */ + /* wr 30 D3:D2 00:FDD(default),01:both.10: TDD, 11 FDD */ + /* pkt_size += fm_bop_modify(0x30, 0xFFF3, 0x0000, &buf[pkt_size], buf_size - pkt_size); */ + + /* D2.2 set ADPLL divider */ + pkt_size += fm_bop_write(0x21, 0xE000, &buf[pkt_size], buf_size - pkt_size); /* wr 21 E000 */ + /* D2.3 set SDM coeff0_H */ + pkt_size += fm_bop_write(0xD8, 0x03F0, &buf[pkt_size], buf_size - pkt_size); /* wr D8 0x03F0 */ + /* D2.4 set SDM coeff0_L */ + pkt_size += fm_bop_write(0xD9, 0x3F04, &buf[pkt_size], buf_size - pkt_size); /* wr D9 0x3F04 */ + /* D2.5 set SDM coeff1_H */ + pkt_size += fm_bop_write(0xDA, 0x0014, &buf[pkt_size], buf_size - pkt_size); /* wr DA 0x0014 */ + /* D2.6 set SDM coeff1_L */ + pkt_size += fm_bop_write(0xDB, 0x2A38, &buf[pkt_size], buf_size - pkt_size); /* wr DB 0x2A38 */ + /* D2.7 set 26M clock */ + pkt_size += fm_bop_write(0x23, 0x4000, &buf[pkt_size], buf_size - pkt_size); /* wr 23 4000 */ + + /* Part E: FM Digital Init: fm_rgf_maincon */ + + /* E4. Set appropriate interrupt mask behavior as desired */ + /* Enable stc_done_mask, Enable rgf_rds_mask*/ + pkt_size += fm_bop_write(0x6A, 0x0021, &buf[pkt_size], buf_size - pkt_size); /* wr 6A 0021 */ + pkt_size += fm_bop_write(0x6B, 0x0021, &buf[pkt_size], buf_size - pkt_size); /* wr 6B 0021 */ + + /* E5. Enable hw auto control */ + pkt_size += fm_bop_write(0x60, 0x0000000F, &buf[pkt_size], buf_size - pkt_size); /* wr 60 f */ + + /* E6. Release ASIP reset */ + pkt_size += fm_bop_modify(0x61, 0xFFFD, 0x0002, &buf[pkt_size], buf_size - pkt_size); /* wr 61 D1=1 */ + /* E7. Enable ASIP power */ + pkt_size += fm_bop_modify(0x61, 0xFFFE, 0x0000, &buf[pkt_size], buf_size - pkt_size); /* wr 61 D0=0 */ + + /* E8 */ + pkt_size += fm_bop_udelay(100000, &buf[pkt_size], buf_size - pkt_size); /* delay 100ms */ + /* E9. Check HW initial complete */ + pkt_size += fm_bop_rd_until(0x64, 0x001F, 0x0002, &buf[pkt_size], buf_size - pkt_size); /* Poll 64[0~4] = 2 */ + + return pkt_size - 4; +} + +/* + * mt6635_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 + */ +static signed int mt6635_pwrup_digital_init(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6635_pwrup_digital_init_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +static signed int mt6635_pwrup_fine_tune_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* F1 set host control RF register */ + pkt_size += fm_bop_write(0x60, 0x00000007, &buf[pkt_size], buf_size - pkt_size); + + /* F2 fine tune RF setting */ + pkt_size += fm_bop_write(0x01, 0xBEE8, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x03, 0xF6ED, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x15, 0x0D80, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x16, 0x0068, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x17, 0x092A, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x34, 0x807F, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x35, 0x311E, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x40, 0x0100, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x03, 0xFAF5, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x05, 0x7A80, &buf[pkt_size], buf_size - pkt_size); + + /* F4 set DSP control RF register */ + pkt_size += fm_bop_write(0x60, 0x0000000F, &buf[pkt_size], buf_size - pkt_size); + + return pkt_size - 4; +} + +/* + * mt6635_pwrup_fine_tune - Wholechip FM Power Up: step 5, FM RF fine tune setting + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6635_pwrup_fine_tune(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6635_pwrup_fine_tune_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +static signed int mt6635_pwrdown_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* A1:set audio output I2S Tx mode: */ + pkt_size += fm_bop_modify(0x9B, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size); + + /* B0:Disable HW clock control */ + pkt_size += fm_bop_write(0x60, 0x330F, &buf[pkt_size], buf_size - pkt_size); + /* B1:Reset ASIP : Set 0x61, [D1 = 0, D0=1] */ + pkt_size += fm_bop_modify(0x61, 0xFFFD, 0x0001, &buf[pkt_size], buf_size - pkt_size); + + /* B2:digital core + digital rgf reset */ + pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size); + + /* B3:Disable all clock */ + pkt_size += fm_bop_write(0x60, 0x0000, &buf[pkt_size], buf_size - pkt_size); + /* B4:Reset rgfrf */ + pkt_size += fm_bop_write(0x60, 0x4000, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x60, 0x0000, &buf[pkt_size], buf_size - pkt_size); + + /* MTCMOS power off */ + /* C0:disable MTCMOS */ + pkt_size += fm_bop_top_write(0x160, 0x0005, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_top_write(0x160, 0x0015, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_top_write(0x160, 0x0035, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_top_write(0x160, 0x0030, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_top_rd_until(0x160, 0x0000000A, 0x0, &buf[pkt_size], buf_size - pkt_size); + + return pkt_size - 4; +} +/* + * mt6635_pwrdown - Wholechip FM Power down: Digital Modem Power Down + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6635_pwrdown(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6635_pwrdown_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +static signed int mt6635_tune_reg_op(unsigned char *buf, signed int buf_size, unsigned short freq, + unsigned short chan_para) +{ + signed int pkt_size = 4; + + WCN_DBG(FM_ALT | CHIP, "%s enter mt6635_tune function\n", __func__); + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* A2 Enable hardware controlled tuning sequence */ + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFF8, TUNE, &buf[pkt_size], buf_size - pkt_size);/*Set 0x63 D0=1*/ + /* Wait for STC_DONE interrupt */ + + +#ifdef FM_TUNE_USE_POLL + /* A3 Wait for STC_DONE interrupt */ + /* A4 Wait for STC_DONE interrupt status flag */ + pkt_size += fm_bop_rd_until(FM_MAIN_INTR, FM_INTR_STC_DONE, + FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size); + /* A6 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); +#endif + + pkt_size += fm_bop_udelay(100000, &buf[pkt_size], buf_size - pkt_size); + WCN_DBG(FM_ALT | CHIP, "mt6635_tune delay 100 ms wait 0x69 to change\n"); + + WCN_DBG(FM_ALT | CHIP, "%s leave mt6635_tune function\n", __func__); + + return pkt_size - 4; +} + +/* + * mt6635_tune - execute tune action, + * @buf - target buf + * @buf_size - buffer size + * @freq - 760 ~ 1080, 100KHz unit + * return package size + */ +static signed int mt6635_tune(unsigned char *buf, signed int buf_size, unsigned short freq, + unsigned short chan_para) +{ + signed int pkt_size = 0; + + pkt_size = mt6635_tune_reg_op(buf, buf_size, freq, chan_para); + return fm_op_seq_combine_cmd(buf, FM_TUNE_OPCODE, pkt_size); +} + +/* + * mt6635_pwrup_DSP_download - execute dsp/coeff patch dl action, + * @patch_tbl - current chip patch table + * return patch dl ok or not + */ +static signed int mt6635_pwrup_DSP_download(struct fm_patch_tbl *patch_tbl) +{ +#define PATCH_BUF_SIZE (4096*6) + signed int ret = 0; + signed int patch_len = 0; + unsigned char *dsp_buf = NULL; + unsigned short tmp_reg = 0; + + if (fm_wcn_ops.ei.wmt_ic_info_get) + mt6635_hw_info.eco_ver = fm_wcn_ops.ei.wmt_ic_info_get(); + WCN_DBG(FM_DBG | CHIP, "ECO version:0x%08x\n", mt6635_hw_info.eco_ver); + + /* Wholechip FM Power Up: step 3, get mt6635 DSP ROM version */ + ret = mt6635_get_rom_version(); + if (ret >= 0) { + mt6635_hw_info.rom_ver = ret; + WCN_DBG(FM_NTC | CHIP, "%s ROM version: v%d\n", __func__, mt6635_hw_info.rom_ver); + } else { + WCN_DBG(FM_ERR | CHIP, "get ROM version failed\n"); + if (ret == -4) + WCN_DBG(FM_ERR | CHIP, "signal got when control FM, usually get sig 9 to kill FM process.\n"); + /* now cancel FM power up sequence is recommended. */ + goto out; + } + + /* Wholechip FM Power Up: step 4 download patch */ + dsp_buf = fm_vmalloc(PATCH_BUF_SIZE); + if (!dsp_buf) { + WCN_DBG(FM_ALT | CHIP, "-ENOMEM\n"); + return -ENOMEM; + } + + patch_len = fm_get_patch_path(mt6635_hw_info.rom_ver, dsp_buf, PATCH_BUF_SIZE, patch_tbl); + if (patch_len <= 0) { + WCN_DBG(FM_ALT | CHIP, " fm_get_patch_path failed\n"); + ret = patch_len; + goto out; + } + + ret = fm_download_patch((const unsigned char *)dsp_buf, patch_len, IMG_PATCH); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " DL DSPpatch failed\n"); + goto out; + } + + patch_len = fm_get_coeff_path(mt6635_hw_info.rom_ver, dsp_buf, PATCH_BUF_SIZE, patch_tbl); + if (patch_len <= 0) { + WCN_DBG(FM_ALT | CHIP, " fm_get_coeff_path failed\n"); + ret = patch_len; + goto out; + } + + mt6635_hw_info.rom_ver += 1; + + tmp_reg = dsp_buf[38] | (dsp_buf[39] << 8); /* to be confirmed */ + mt6635_hw_info.patch_ver = (signed int) tmp_reg; + WCN_DBG(FM_NTC | CHIP, "Patch version: 0x%08x\n", mt6635_hw_info.patch_ver); + + ret = fm_download_patch((const unsigned char *)dsp_buf, patch_len, IMG_COEFFICIENT); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " Download DSP coefficient failed\n"); + goto out; + } + + /* Download HWACC coefficient */ + fm_reg_write(0x92, 0x0000); + fm_reg_write(0x90, 0x0040); /* Reset download control */ + fm_reg_write(0x90, 0x0000); /* Disable memory control from host*/ +out: + if (dsp_buf) + fm_vfree(dsp_buf); + return ret; +} +static void mt6635_show_reg(void) +{ + unsigned int host_reg[3] = {0}; + unsigned int debug_reg1[3] = {0}; + unsigned short debug_reg2[3] = {0}; + + fm_host_reg_read(0x1800400C, &host_reg[0]); + fm_host_reg_read(0x18001900, &host_reg[1]); + fm_host_reg_read(0x18008040, &host_reg[2]); + WCN_DBG(FM_ALT | CHIP, + "host read 0x1800400C = 0x%08x, 0x18001900 = 0x%08x, 0x18008040 = 0x%08x\n", + host_reg[0], host_reg[1], host_reg[2]); + + fm_top_reg_read(0x003c, &debug_reg1[0]); + fm_top_reg_read(0x0a18, &debug_reg1[1]); + fm_top_reg_read(0x0160, &debug_reg1[2]); + fm_reg_read(0x7f, &debug_reg2[0]); + fm_reg_read(0x62, &debug_reg2[1]); + fm_reg_read(0x60, &debug_reg2[2]); + WCN_DBG(FM_ALT | CHIP, + "top cr 0x3c = 0x%08x, 0xa18 = 0x%08x, 0x160 = 0x%08x, fmreg 0x7f = 0x%08x, 0x62 = 0x%08x, 0x60 = 0x%08x\n", + debug_reg1[0], debug_reg1[1], debug_reg1[2], debug_reg2[0], debug_reg2[1], debug_reg2[2]); +} + +static signed int mt6635_PowerUp(unsigned short *chip_id, unsigned short *device_id) +{ + signed int ret = 0, count = 0; + unsigned short pkt_size; + unsigned short tmp_reg = 0; + unsigned int tem = 0; + + if (chip_id == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (device_id == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + WCN_DBG(FM_DBG | CHIP, "pwr on seq......\n"); + + /* enable osc_en to conn_infra_cfg */ + ret = fm_host_reg_write(0x18008040, 0x00000001); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "Enable osc_en to conn_infra_cfg failed\n"); + return ret; + } + + /* polling 26M rdy, max 5 times */ + do { + fm_delayus(1000); + ret = fm_host_reg_read(0x18001830, &tem); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "read 0x18001830 failed\n"); + return ret; + } + count++; + } while ((tem & 0x80000) == 0 && count < 5); + + if (count >= 5) + WCN_DBG(FM_ERR | CHIP, "polling 26M rdy failed\n"); + + /* Wholechip FM Power Up: step 1, set common SPI parameter */ + ret = fm_host_reg_write(0x1800400C, 0x0000801F); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup set CSPI failed\n"); + return ret; + } + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + + pkt_size = mt6635_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, "mt6635_pwrup_clock_on failed\n"); + return ret; + } + + /* Wholechip FM Power Up: step 2, read HW version */ + mt6635_show_reg(); + fm_reg_read(0x62, &tmp_reg); + /* chip_id = tmp_reg; */ + if (tmp_reg == 0x6635) + *chip_id = 0x6635; + *device_id = tmp_reg; + mt6635_hw_info.chip_id = (signed int) tmp_reg; + WCN_DBG(FM_DBG | CHIP, "chip_id:0x%04x\n", tmp_reg); + + if ((mt6635_hw_info.chip_id != 0x6635)) { + mt6635_show_reg(); + WCN_DBG(FM_NTC | CHIP, "fm sys error, reset hw, chip_id = 0x%08x\n", mt6635_hw_info.chip_id); + return -FM_EFW; + + } + /* Wholechip FM Power Up: step 3, patch download */ + ret = mt6635_pwrup_DSP_download(mt6635_patch_tbl); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "mt6635_pwrup_DSP_download failed\n"); + return ret; + } + + /* Wholechip FM Power Up: step 4, FM Digital Init: fm_rgf_maincon */ + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6635_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, "mt6635_pwrup_digital_init failed\n"); + return ret; + } + + /* Wholechip FM Power Up: step 5, FM RF fine tune setting */ + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6635_pwrup_fine_tune(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, "mt6635_pwrup_fine_tune failed\n"); + return ret; + } + + /* Enable connsys FM 2 wire RX */ + fm_reg_write(0x9B, 0xF9AB); /* G2: Set audio output i2s TX mode */ + fm_host_reg_write(0x18008064, 0x00000014); /* G4: Enable aon_osc_clk_cg */ + fm_host_reg_write(0x18008058, 0x888100C3); /* G5: Enable FMAUD trigger, 20170119 */ + fm_host_reg_write(0x18000070, 0x00000000); /* G6: Release fmsys memory power down*/ + + WCN_DBG(FM_NTC | CHIP, "pwr on seq ok\n"); + + return ret; +} + +static signed int mt6635_PowerDown(void) +{ + struct fm_ext_interface *ei = &fm_wcn_ops.ei; + signed int ret = 0; + unsigned int tem = 0; + unsigned short pkt_size; + + WCN_DBG(FM_DBG | CHIP, "pwr down seq\n"); + + /* A0.1. Disable aon_osc_clk_cg */ + ret = fm_host_reg_write(0x18008064, 0x00000004); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " Disable aon_osc_clk_cg failed\n"); + return ret; + } + /* A0.1. Disable FMAUD trigger */ + ret = fm_host_reg_write(0x18008058, 0x88800000); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " Disable FMAUD trigger failed\n"); + return ret; + } + + /* A0.1. issue fmsys memory powr down */ + ret = fm_host_reg_write(0x18000070, 0x00000001); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " Issue fmsys memory powr down failed\n"); + return ret; + } + + /* switch SPI clock to 26M */ + WCN_DBG(FM_DBG | CHIP, "PowerDown: switch SPI clock to 26M\n"); + if (ei->spi_clock_switch) + ret = ei->spi_clock_switch(FM_SPI_SPEED_26M); + else { + ret = -1; + WCN_DBG(FM_ERR | CHIP, "Clock switch cb is null\n"); + } + if (ret) + WCN_DBG(FM_ERR | CHIP, + "PowerDown: Switch SPI clock to 26M failed\n"); + + /* unlock 64M */ + ret = fm_host_reg_read(0x18003004, &tem); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: unlock 64M reg 0x18003004 failed\n", __func__); + ret = fm_host_reg_write(0x18003004, tem & (~(0x1 << 15))); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: unlock 64M failed\n", __func__); + + /* disable 'rf_spi_div_en' */ + ret = fm_host_reg_read(0x18001A00, &tem); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: disable rf_spi_div_en read failed\n", __func__); + ret = fm_host_reg_write(0x18001A00, tem | (0x1 << 28)); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: disable rf_spi_div_en write failed\n", __func__); + + if (ret) + WCN_DBG(FM_ALT | CHIP, "PowerDown: Enable 26M crystal sleep failed\n"); + + /* A0:set audio output I2X Rx mode: */ + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6635_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, "mt6635_pwrdown failed\n"); + return ret; + } + + /* RF power off */ + + /* SLP_CTRL setting */ + + /* set common spi fm parameter */ + fm_host_reg_read(0x1800400C, &tem); + tem = tem & 0xFFFF0000; /* D15:D0 */ + ret = fm_host_reg_write(0x1800400C, tem); + if (ret) + WCN_DBG(FM_ALT | CHIP, "set common spi fm parameter failed\n"); + + /* clear 26M crystal sleep */ + WCN_DBG(FM_DBG | CHIP, "PowerDown: Enable 26M crystal sleep,Set 0x18008040[0] = 0x0\n"); + fm_host_reg_read(0x18008040, &tem); + tem = tem & 0xFFFFFFFE; + fm_host_reg_write(0x18008040, tem); + + return ret; +} + +static signed int mt6635_set_freq_fine_tune_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + /* disable DCOC IDAC auto-disable */ + pkt_size += fm_bop_modify(0x33, 0xFDFF, 0x0000, &buf[pkt_size], buf_size - pkt_size); + /* A1 Host control RF register */ + pkt_size += fm_bop_write(0x60, 0x0007, &buf[pkt_size], buf_size - pkt_size); + /* F3 DCOC @ LNA = 7 */ + pkt_size += fm_bop_write(0x40, 0x01AF, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x03, 0xFAF5, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x07, 0x0100, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x01, 0xEEE8, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x3F, 0x3221, &buf[pkt_size], buf_size - pkt_size); + /* wait 1ms */ + pkt_size += fm_bop_udelay(1000, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_rd_until(0x3F, 0x001F, 0x0001, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x3F, 0x0220, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x40, 0x0100, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x01, 0xAEE8, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x30, 0x0000, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x36, 0x017A, &buf[pkt_size], buf_size - pkt_size); + /* set threshold = 4 */ + pkt_size += fm_bop_modify(0x3F, 0x0FFF, 0x4000, &buf[pkt_size], buf_size - pkt_size); + /* enable DCOC IDAC auto-disable */ + pkt_size += fm_bop_modify(0x33, 0xFDFF, 0x0200, &buf[pkt_size], buf_size - pkt_size); + + /* F4 set DSP control RF register */ + pkt_size += fm_bop_write(0x60, 0x000F, &buf[pkt_size], buf_size - pkt_size); + + return pkt_size - 4; +} + +/* + * mt6635_set_freq_fine_tune - FM RF fine tune setting + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6635_set_freq_fine_tune(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6635_set_freq_fine_tune_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +static bool mt6635_do_SPI_hopping(unsigned short freq) +{ + struct fm_ext_interface *ei = &fm_wcn_ops.ei; + signed int ret = -1; + + if (!mt6635_SPI_hopping_check(freq)) + return true; + + /* SPI hopping setting*/ + WCN_DBG(FM_NTC | CHIP, + "%s: freq:%d is SPI hopping channel,turn on 64M PLL\n", + __func__, freq); + + /* switch SPI clock to 64MHz */ + if (ei->spi_hopping) + ret = ei->spi_hopping(); + + return ret == 0; +} + +static bool mt6635_SetFreq(unsigned short freq) +{ + signed int ret = 0; + unsigned short pkt_size; + unsigned short chan_para = 0; + unsigned short freq_reg = 0; + unsigned short tmp_reg[6] = {0}; + + fm_cb_op->cur_freq_set(freq); + + /* FM VCO Calibration */ + ret = fm_set_bits(0x60, 0x0007, 0xFFF0); /* Set 0x60 [D3:D0] = 0x07*/ + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Host Control RF register 0x60 = 0x7 failed\n", __func__); + + fm_delayus(5); + if (freq >= 750) { + fm_reg_write(0x37, 0xF68C); + fm_reg_write(0x38, 0x0B53); + ret = fm_set_bits(0x30, 0x0014 << 8, 0xC0FF); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Set 0x30 failed\n", __func__); + + } else { + fm_reg_write(0x37, 0x0675); + fm_reg_write(0x38, 0x0F54); + ret = fm_set_bits(0x30, 0x001C << 8, 0xC0FF); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Set 0x30 failed\n", __func__); + } + ret = fm_set_bits(0x30, 0x0001 << 14, 0xBFFF); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Set 0x30 failed\n", __func__); + + fm_reg_write(0x40, 0x010F); + fm_delayus(5); + fm_reg_write(0x36, 0x037A); + fm_reg_write(0x32, 0x8000); + fm_delayus(200); + ret = fm_set_bits(0x3D, 0x0001 << 2, 0xFFFB); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Set 0x3D failed\n", __func__); + + fm_reg_write(0x32, 0x0000); + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6635_set_freq_fine_tune(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, "mt6635_pwrup_fine_tune failed\n"); + return ret; + } + + /* A0. Host contrl RF register */ + ret = fm_set_bits(0x60, 0x0007, 0xFFF0); /* Set 0x60 [D3:D0] = 0x07*/ + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Host Control RF register 0x60 = 0x7 failed\n", __func__); + + /* A0.1 Update FM ADPLL fast tracking mode gain */ + ret = fm_set_bits(0x0F, 0x0455, 0xF800); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Set FM ADPLL gainA/B=0x455 failed\n", __func__); + + /* A0.2 Set FMSYS cell mode */ + if (mt6635_TDD_chan_check(freq)) { + ret = fm_set_bits(0x30, 0x0008, 0xFFF3); /* use TDD solution */ + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: freq[%d]: use TDD solution failed\n", __func__, freq); + } else { + ret = fm_set_bits(0x30, 0x0000, 0xFFF3); /* default use FDD solution */ + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: freq[%d]: default use FDD solution failed\n", __func__, freq); + } + + /* A0.3 Host control RF register */ + ret = fm_set_bits(0x60, 0x000F, 0xFFF0); /* Set 0x60 [D3:D0] = 0x0F*/ + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Set 0x60 [D3:D0] = 0x0F failed\n", __func__); + + /* A1 Get Channel parameter from map list*/ + + chan_para = mt6635_chan_para_get(freq); + WCN_DBG(FM_DBG | CHIP, "%s: %d chan para = %d\n", __func__, (signed int) freq, (signed int) chan_para); + + freq_reg = freq; + if (fm_get_channel_space(freq_reg) == 0) + freq_reg *= 10; + + freq_reg = (freq_reg - 6400) * 2 / 10; + + /*A1 Set rgfrf_chan = XXX*/ + ret = fm_set_bits(0x65, freq_reg, 0xFC00); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "%s: set rgfrf_chan = xxx = %d failed\n", __func__, freq_reg); + return false; + } + + ret = fm_set_bits(0x65, (chan_para << 12), 0x0FFF); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x65 failed\n"); + return false; + } + + if (!mt6635_do_SPI_hopping(freq)) + WCN_DBG(FM_ERR | CHIP, "%s: spi hopping fail!\n", __func__); + + /* A0. Host contrl RF register */ + ret = fm_set_bits(0x60, 0x0007, 0xFFF0); /* Set 0x60 [D3:D0] = 0x07*/ + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Host Control RF register 0x60 = 0x7 failed\n", __func__); + + + fm_reg_read(0x62, &tmp_reg[0]); + fm_reg_read(0x64, &tmp_reg[1]); + fm_reg_read(0x69, &tmp_reg[2]); + fm_reg_read(0x6a, &tmp_reg[3]); + fm_reg_read(0x6b, &tmp_reg[4]); + fm_reg_read(0x9b, &tmp_reg[5]); + + WCN_DBG(FM_ALT | CHIP, "%s: Before tune--0x62 0x64 0x69 0x6a 0x6b 0x9b = %04x %04x %04x %04x %04x %04x\n", + __func__, + tmp_reg[0], + tmp_reg[1], + tmp_reg[2], + tmp_reg[3], + tmp_reg[4], + tmp_reg[5]); + + /* A0.3 Host control RF register */ + ret = fm_set_bits(0x60, 0x000F, 0xFF00); /* Set 0x60 [D3:D0] = 0x0F*/ + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Set 0x60 [D3:D0] = 0x0F failed\n", __func__); + + if (FM_LOCK(cmd_buf_lock)) + return false; + pkt_size = mt6635_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); + + + /* A0. Host contrl RF register */ + ret = fm_set_bits(0x60, 0x0007, 0xFFF0); /* Set 0x60 [D3:D0] = 0x07*/ + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Host Control RF register 0x60 = 0x7 failed\n", __func__); + + memset(tmp_reg, 0, sizeof(tmp_reg[0])*6); + + fm_reg_read(0x62, &tmp_reg[0]); + fm_reg_read(0x64, &tmp_reg[1]); + fm_reg_read(0x69, &tmp_reg[2]); + fm_reg_read(0x6a, &tmp_reg[3]); + fm_reg_read(0x6b, &tmp_reg[4]); + fm_reg_read(0x9b, &tmp_reg[5]); + + WCN_DBG(FM_ALT | CHIP, "%s: After tune--0x62 0x64 0x69 0x6a 0x6b 0x9b = %04x %04x %04x %04x %04x %04x\n", + __func__, + tmp_reg[0], + tmp_reg[1], + tmp_reg[2], + tmp_reg[3], + tmp_reg[4], + tmp_reg[5]); + + /* A0.3 Host control RF register */ + ret = fm_set_bits(0x60, 0x000F, 0xFF00); /* Set 0x60 [D3:D0] = 0x0F*/ + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Set 0x60 [D3:D0] = 0x0F failed\n", __func__); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "%s: mt6635_tune failed\n", __func__); + return false; + } + + WCN_DBG(FM_DBG | CHIP, "%s: set freq to %d ok\n", __func__, freq); +#if 0 + /* ADPLL setting for dbg */ + fm_top_reg_write(0x0050, 0x00000007); + fm_top_reg_write(0x0A08, 0xFFFFFFFF); + mt6635_bt_write(0x82, 0x11); + mt6635_bt_write(0x83, 0x11); + mt6635_bt_write(0x84, 0x11); + fm_top_reg_write(0x0040, 0x1C1C1C1C); + fm_top_reg_write(0x0044, 0x1C1C1C1C); + fm_reg_write(0x70, 0x0010); + /*0x0806 DCO clk + *0x0802 ref clk + *0x0804 feedback clk + */ + fm_reg_write(0xE0, 0x0806); +#endif + return true; +} + +#define FM_CQI_LOG_PATH "/mnt/sdcard/fmcqilog" + +static signed int mt6635_full_cqi_get(signed int min_freq, signed int max_freq, signed int space, signed int cnt) +{ + signed int ret = 0; + unsigned short pkt_size; + unsigned short freq, orig_freq; + signed int i, j, k; + signed int space_val, max, min, num; + struct mt6635_full_cqi *p_cqi; + unsigned char *cqi_log_title = "Freq, RSSI, PAMD, PR, FPAMD, MR, ATDC, PRX, ATDEV, SMGain, DltaRSSI\n"; + unsigned char cqi_log_buf[100] = { 0 }; + signed int pos; + unsigned char cqi_log_path[100] = { 0 }; + + /* for soft-mute tune, and get cqi */ + freq = fm_cb_op->cur_freq_get(); + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + /* get cqi */ + orig_freq = freq; + if (fm_get_channel_space(min_freq) == 0) + min = min_freq * 10; + else + min = min_freq; + + if (fm_get_channel_space(max_freq) == 0) + 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; (orig_freq == 10000) && (g_dbg_level == 0xffffffff) && (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)); + if (sprintf(&cqi_log_path[strlen(FM_CQI_LOG_PATH)], "%d.txt", k + 1) < 0) + WCN_DBG(FM_NTC | CHIP, "sprintf fail\n"); + 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 = fm_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, fm_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (!ret && fm_res) { + WCN_DBG(FM_NTC | CHIP, "smt cqi size %d\n", fm_res->cqi[0]); + p_cqi = (struct mt6635_full_cqi *)&fm_res->cqi[2]; + for (i = 0; i < fm_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 */ + if (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) < 0) + WCN_DBG(FM_NTC | CHIP, "sprintf fail\n"); + /* 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 */ + } + + return ret; +} + +/* + * mt6635_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 signed int mt6635_GetCurRSSI(signed int *pRSSI) +{ + unsigned short tmp_reg = 0; + + fm_reg_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 unsigned short mt6635_vol_tbl[16] = { 0x0000, 0x0519, 0x066A, 0x0814, + 0x0A2B, 0x0CCD, 0x101D, 0x1449, + 0x198A, 0x2027, 0x287A, 0x32F5, + 0x4027, 0x50C3, 0x65AD, 0x7FFF +}; + +static signed int mt6635_SetVol(unsigned char vol) +{ + signed int ret = 0; + + vol = (vol > 15) ? 15 : vol; + ret = fm_reg_write(0x7D, mt6635_vol_tbl[vol]); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "Set vol=%d Failed\n", vol); + return ret; + } + 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 signed int mt6635_GetVol(unsigned char *pVol) +{ + int ret = 0; + unsigned short tmp = 0; + signed int i; + + if (pVol == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + ret = fm_reg_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 (mt6635_vol_tbl[i] == tmp) { + *pVol = i; + break; + } + } + + WCN_DBG(FM_DBG | CHIP, "Get vol=%d OK\n", *pVol); + return 0; +} + +static signed int mt6635_dump_reg(void) +{ + signed int i; + unsigned short TmpReg = 0; + + for (i = 0; i < 0xff; i++) { + fm_reg_read(i, &TmpReg); + WCN_DBG(FM_NTC | CHIP, "0x%02x=0x%04x\n", i, TmpReg); + } + return 0; +} + +/*0:mono, 1:stereo*/ +static bool mt6635_GetMonoStereo(unsigned short *pMonoStereo) +{ +#define FM_BF_STEREO 0x1000 + unsigned short TmpReg = 0; + + if (pMonoStereo) { + fm_reg_read(FM_RSSI_IND, &TmpReg); + *pMonoStereo = (TmpReg & FM_BF_STEREO) >> 12; + } else { + WCN_DBG(FM_ERR | CHIP, "MonoStero: para err\n"); + return false; + } + + WCN_DBG(FM_NTC | CHIP, "Get MonoStero:0x%04x\n", *pMonoStereo); + return true; +} + +static signed int mt6635_SetMonoStereo(signed int MonoStereo) +{ + signed int ret = 0; + + WCN_DBG(FM_NTC | CHIP, "set to %s\n", MonoStereo ? "mono" : "auto"); + fm_reg_write(0x60, 0x0007); + + if (MonoStereo) /*mono */ + ret = fm_set_bits(0x75, 0x0008, ~0x0008); + else + ret = fm_set_bits(0x75, 0x0000, ~0x0008); + + fm_reg_write(0x60, 0x000F); + return ret; +} + +static signed int mt6635_GetCapArray(signed int *ca) +{ + unsigned short dataRead = 0; + unsigned short tmp = 0; + + if (ca == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + fm_reg_read(0x60, &tmp); + fm_reg_write(0x60, tmp & 0xFFF7); /* 0x60 D3=0 */ + + fm_reg_read(0x26, &dataRead); + *ca = dataRead; + + fm_reg_write(0x60, tmp); /* 0x60 D3=1 */ + return 0; +} + +/* + * mt6635_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 bool mt6635_GetCurPamd(unsigned short *pPamdLevl) +{ + unsigned short tmp_reg = 0; + unsigned short dBvalue, valid_cnt = 0; + int i, total = 0; + + for (i = 0; i < 8; i++) { + if (fm_reg_read(FM_ADDR_PAMD, &tmp_reg)) { + *pPamdLevl = 0; + return 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); + } + fm_delayms(3); + } + if (valid_cnt != 0) + *pPamdLevl = total / valid_cnt; + else + *pPamdLevl = 0; + + WCN_DBG(FM_NTC | CHIP, "PAMD=%d\n", *pPamdLevl); + return true; +} + +static signed int mt6635_i2s_info_get(signed int *ponoff, signed int *pmode, signed int *psample) +{ + if (ponoff == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (pmode == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (psample == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + *ponoff = fm_config.aud_cfg.i2s_info.status; + *pmode = fm_config.aud_cfg.i2s_info.mode; + *psample = fm_config.aud_cfg.i2s_info.rate; + + return 0; +} + +static signed int mt6635_get_audio_info(struct fm_audio_info_t *data) +{ + memcpy(data, &fm_config.aud_cfg, sizeof(struct fm_audio_info_t)); + return 0; +} + +static signed int mt6635_hw_info_get(struct fm_hw_info *req) +{ + if (req == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + req->chip_id = mt6635_hw_info.chip_id; + req->eco_ver = mt6635_hw_info.eco_ver; + req->patch_ver = mt6635_hw_info.patch_ver; + req->rom_ver = mt6635_hw_info.rom_ver; + + return 0; +} + +static signed int mt6635_pre_search(void) +{ + mt6635_RampDown(); + /* disable audio output I2S Tx mode */ + fm_reg_write(0x9B, 0x0000); + + return 0; +} + +static signed int mt6635_restore_search(void) +{ + mt6635_RampDown(); + /* set audio output I2S Tx mode */ + fm_reg_write(0x9B, 0xF9AB); + return 0; +} + +static signed int mt6635_soft_mute_tune(unsigned short freq, signed int *rssi, signed int *valid) +{ + signed int ret = 0; + unsigned short pkt_size; + struct mt6635_full_cqi *p_cqi; + signed int RSSI = 0, PAMD = 0, MR = 0, ATDC = 0; + unsigned int PRX = 0, ATDEV = 0; + unsigned short softmuteGainLvl = 0; + + /* Set rgf_host2dsp_reserve[2] = 1 */ + + ret = mt6635_chan_para_get(freq); + if (ret == 2) + ret = fm_set_bits(FM_CHANNEL_SET, 0x2000, 0x0FFF); /* mdf HiLo */ + else + ret = fm_set_bits(FM_CHANNEL_SET, 0x0000, 0x0FFF); /* clear FA/HL/ATJ */ + + if (!mt6635_do_SPI_hopping(freq)) + WCN_DBG(FM_ERR | CHIP, "%s: spi hopping fail!\n", __func__); + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = fm_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, fm_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (!ret && fm_res) { + p_cqi = (struct mt6635_full_cqi *)&fm_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 ((fm_config.rx_cfg.long_ana_rssi_th <= RSSI) + && (fm_config.rx_cfg.pamd_th >= PAMD) + && (fm_config.rx_cfg.atdc_th >= ATDC) + && (fm_config.rx_cfg.mr_th <= MR) + && (fm_config.rx_cfg.prx_th <= PRX) + && (ATDEV >= ATDC) /* sync scan algorithm */ + && (fm_config.rx_cfg.smg_th <= softmuteGainLvl)) { + *valid = true; + } else { + *valid = false; + } + *rssi = RSSI; + } else { + WCN_DBG(FM_ALT | CHIP, "smt get CQI failed\n"); + return false; + } + WCN_DBG(FM_NTC | CHIP, "valid=%d\n", *valid); + return true; +} + +static bool mt6635_em_test(unsigned short group_idx, unsigned short item_idx, unsigned int item_value) +{ + return true; +} + +/* +*parm: +* parm.th_type: 0, RSSI. 1, desense RSSI. 2, SMG. +* parm.th_val: threshold value +*/ +static signed int mt6635_set_search_th(signed int idx, signed int val, signed int reserve) +{ + switch (idx) { + case 0: { + fm_config.rx_cfg.long_ana_rssi_th = val; + WCN_DBG(FM_NTC | CHIP, "set rssi th =%d\n", val); + break; + } + case 1: { + fm_config.rx_cfg.desene_rssi_th = val; + WCN_DBG(FM_NTC | CHIP, "set desense rssi th =%d\n", val); + break; + } + case 2: { + fm_config.rx_cfg.smg_th = val; + WCN_DBG(FM_NTC | CHIP, "set smg th =%d\n", val); + break; + } + default: + break; + } + return 0; +} + +static signed int MT6635_low_power_wa_default(signed int fmon) +{ + return 0; +} + +signed int mt6635_fm_low_ops_register(struct fm_callback *cb, struct fm_basic_interface *bi) +{ + signed int ret = 0; + /* Basic functions. */ + + if (bi == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,bi invalid pointer\n", __func__); + return -FM_EPARA; + } + if (cb->cur_freq_get == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,cb->cur_freq_get invalid pointer\n", __func__); + return -FM_EPARA; + } + if (cb->cur_freq_set == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,cb->cur_freq_set invalid pointer\n", __func__); + return -FM_EPARA; + } + fm_cb_op = cb; + + bi->pwron = mt6635_pwron; + bi->pwroff = mt6635_pwroff; + bi->chipid_get = mt6635_get_chipid; + bi->mute = mt6635_Mute; + bi->rampdown = mt6635_RampDown; + bi->pwrupseq = mt6635_PowerUp; + bi->pwrdownseq = mt6635_PowerDown; + bi->setfreq = mt6635_SetFreq; + bi->low_pwr_wa = MT6635_low_power_wa_default; + bi->get_aud_info = mt6635_get_audio_info; + bi->rssiget = mt6635_GetCurRSSI; + bi->volset = mt6635_SetVol; + bi->volget = mt6635_GetVol; + bi->dumpreg = mt6635_dump_reg; + bi->msget = mt6635_GetMonoStereo; + bi->msset = mt6635_SetMonoStereo; + bi->pamdget = mt6635_GetCurPamd; + bi->em = mt6635_em_test; + bi->anaswitch = mt6635_SetAntennaType; + bi->anaget = mt6635_GetAntennaType; + bi->caparray_get = mt6635_GetCapArray; + bi->hwinfo_get = mt6635_hw_info_get; + bi->i2s_get = mt6635_i2s_info_get; + bi->is_dese_chan = mt6635_is_dese_chan; + bi->softmute_tune = mt6635_soft_mute_tune; + bi->desense_check = mt6635_desense_check; + bi->cqi_log = mt6635_full_cqi_get; + bi->pre_search = mt6635_pre_search; + bi->restore_search = mt6635_restore_search; + bi->set_search_th = mt6635_set_search_th; + + cmd_buf_lock = fm_lock_create("31_cmd"); + ret = fm_lock_get(cmd_buf_lock); + + cmd_buf = fm_zalloc(TX_BUF_SIZE + 1); + + if (!cmd_buf) { + WCN_DBG(FM_ALT | CHIP, "6635 fm lib alloc tx buf failed\n"); + ret = -1; + } +#if 0 /* def CONFIG_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, "6635 fm lib create cqi fifo failed\n"); + ret = -1; + } +#endif + + return ret; +} + +signed int mt6635_fm_low_ops_unregister(struct fm_basic_interface *bi) +{ + signed int ret = 0; + /* Basic functions. */ + if (bi == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,bi invalid pointer\n", __func__); + return -FM_EPARA; + } + +#if 0 /* def CONFIG_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(bi, 0, sizeof(struct fm_basic_interface)); + + fm_cb_op = NULL; + + return ret; +} + +static const signed char mt6635_chan_para_map[] = { +/* 0, X, 1, X, 2, X, 3, X, 4, X, 5, X, 6, X, 7, X, 8, X, 9, X */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, /* 6500~6595 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6600~6695 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, /* 6700~6795 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6800~6895 */ + 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6900~6995 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7000~7095 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7100~7195 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, /* 7200~7295 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7300~7395 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 7400~7495 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7500~7595 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 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 */ + 8, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7800~7895 */ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7900~7995 */ + 0, 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, 2, 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, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, /* 8300~8395 */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 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, 2, 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, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9400~9495 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9500~9595 */ + 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, /* 9800~9895 */ + 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 9900~9995 */ + 0, 0, 0, 0, 0, 0, 0, 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, 0, 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 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 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 unsigned short mt6635_scan_dese_list[] = { + 6910, 6920, 7680, 7800, 8450, 9210, 9220, 9230, 9590, 9600, 9830, 9900, 9980, 9990, 10400, 10750, 10760 +}; + +static const unsigned short mt6635_SPI_hopping_list[] = { + 6510, 6520, 6530, 7780, 7790, 7800, 7810, 7820, 9090, 9100, 9110, 9120, 10380, 10390, 10400, 10410, 10420 +}; + +static const unsigned short mt6635_I2S_hopping_list[] = { + 6550, 6760, 6960, 6970, 7170, 7370, 7580, 7780, 7990, 8810, 9210, 9220, 10240 +}; + +static const unsigned short mt6635_TDD_list[] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6500~6595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6600~6695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6700~6795 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6800~6895 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6900~6995 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7000~7095 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7100~7195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7200~7295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7300~7395 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7400~7495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7500~7595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7600~7695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7700~7795 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7800~7895 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7900~7995 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8000~8095 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8100~8195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8200~8295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8300~8395 */ + 0x0101, 0x0000, 0x0000, 0x0000, 0x0000, /* 8400~8495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8500~8595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8600~8695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8700~8795 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8800~8895 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8900~8995 */ + 0x0000, 0x0000, 0x0101, 0x0101, 0x0101, /* 9000~9095 */ + 0x0101, 0x0000, 0x0000, 0x0000, 0x0000, /* 9100~9195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9200~9295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9300~9395 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9400~9495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9500~9595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9600~9695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0100, /* 9700~9795 */ + 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, /* 9800~9895 */ + 0x0101, 0x0101, 0x0001, 0x0000, 0x0000, /* 9900~9995 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10000~10095 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10100~10195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10200~10295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10300~10395 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10400~10495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10500~10595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0100, /* 10600~10695 */ + 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, /* 10700~10795 */ + 0x0001 /* 10800 */ +}; + +static const unsigned short mt6635_TDD_Mask[] = { + 0x0001, 0x0010, 0x0100, 0x1000 +}; + +/* return value: 0, not a de-sense channel; 1, this is a de-sense channel; else error no */ +static signed int mt6635_is_dese_chan(unsigned short freq) +{ + signed int size; + + if (1 == HQA_ZERO_DESENSE_MAP) /*HQA only :skip desense channel check. */ + return 0; + + size = ARRAY_SIZE(mt6635_scan_dese_list); + + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + while (size) { + if (mt6635_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 signed int mt6635_desense_check(unsigned short freq, signed int rssi) +{ + if (mt6635_is_dese_chan(freq)) { + if (rssi < fm_config.rx_cfg.desene_rssi_th) + return 1; + + WCN_DBG(FM_DBG | CHIP, "desen_rssi %d th:%d\n", rssi, fm_config.rx_cfg.desene_rssi_th); + } + return 0; +} + +static bool mt6635_TDD_chan_check(unsigned short freq) +{ + unsigned int i = 0; + unsigned short freq_tmp = freq; + signed int ret = 0; + + ret = fm_get_channel_space(freq_tmp); + if (ret == 0) + freq_tmp *= 10; + else if (ret == -1) + return false; + + i = (freq_tmp - 6500) / 5; + if ((i / 4) >= ARRAY_SIZE(mt6635_TDD_list)) { + WCN_DBG(FM_ERR | CHIP, "Freq index out of range(%d),max(%zd)\n", + i / 4, ARRAY_SIZE(mt6635_TDD_list)); + return false; + } + + if (mt6635_TDD_list[i / 4] & mt6635_TDD_Mask[i % 4]) { + WCN_DBG(FM_DBG | CHIP, "Freq %d use TDD solution\n", freq); + return true; + } else + return false; +} + +/* get channel parameter, HL side/ FA / ATJ */ +static unsigned short mt6635_chan_para_get(unsigned short freq) +{ + signed int pos, size; + + if (1 == HQA_RETURN_ZERO_MAP) { + WCN_DBG(FM_NTC | CHIP, "HQA_RETURN_ZERO_CHAN mt6635_chan_para_map enabled!\n"); + return 0; + } + + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + if (freq < 6500) + return 0; + + pos = (freq - 6500) / 5; + + size = ARRAY_SIZE(mt6635_chan_para_map); + + pos = (pos > (size - 1)) ? (size - 1) : pos; + + return mt6635_chan_para_map[pos]; +} + + +static bool mt6635_SPI_hopping_check(unsigned short freq) +{ + signed int size; + + size = ARRAY_SIZE(mt6635_SPI_hopping_list); + + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + while (size) { + if (mt6635_SPI_hopping_list[size - 1] == freq) + return 1; + size--; + } + + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/mt6635/pub/mt6635_fm_lib.c b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6635/pub/mt6635_fm_lib.c new file mode 100644 index 0000000000000..ab7126b34b991 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6635/pub/mt6635_fm_lib.c @@ -0,0 +1,2109 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ +#include +#include + +#include "osal_typedef.h" +#include "stp_exp.h" +#include "wmt_exp.h" +#include "plat.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_cmd.h" + +#include "mt6635_fm_reg.h" +#include "mt6635_fm_lib.h" + +#define HQA_RETURN_ZERO_MAP 0 +#define HQA_ZERO_DESENSE_MAP 0 + +/* #include "mach/mt_gpio.h" */ + +/* #define MT6635_FM_PATCH_PATH "/etc/firmware/mt6635/mt6635_fm_patch.bin" */ +/* #define MT6635_FM_COEFF_PATH "/etc/firmware/mt6635/mt6635_fm_coeff.bin" */ +/* #define MT6635_FM_HWCOEFF_PATH "/etc/firmware/mt6635/mt6635_fm_hwcoeff.bin" */ +/* #define MT6635_FM_ROM_PATH "/etc/firmware/mt6635/mt6635_fm_rom.bin" */ + +static struct fm_patch_tbl mt6635_patch_tbl[5] = { + {FM_ROM_V1, "mt6635_fm_v1_patch.bin", "mt6635_fm_v1_coeff.bin", NULL, NULL}, + {FM_ROM_V2, "mt6635_fm_v2_patch.bin", "mt6635_fm_v2_coeff.bin", NULL, NULL}, + {FM_ROM_V3, "mt6635_fm_v3_patch.bin", "mt6635_fm_v3_coeff.bin", NULL, NULL}, + {FM_ROM_V4, "mt6635_fm_v4_patch.bin", "mt6635_fm_v4_coeff.bin", NULL, NULL}, + {FM_ROM_V5, "mt6635_fm_v5_patch.bin", "mt6635_fm_v5_coeff.bin", NULL, NULL} +}; + +static struct fm_hw_info mt6635_hw_info = { + .chip_id = 0x00006635, + .eco_ver = 0x00000000, + .rom_ver = 0x00000000, + .patch_ver = 0x00000000, + .reserve = 0x00000000, +}; + +static struct fm_callback *fm_cb_op; + +/* static signed int Chip_Version = mt6635_E1; */ + +/* static bool rssi_th_set = false; */ + +#if 0 /* def CONFIG_MTK_FM_50KHZ_SUPPORT */ +static struct fm_fifo *cqi_fifo; +#endif +static signed int mt6635_is_dese_chan(unsigned short freq); + +static unsigned short mt6635_chan_para_get(unsigned short freq); +static signed int mt6635_desense_check(unsigned short freq, signed int rssi); +static bool mt6635_TDD_chan_check(unsigned short freq); +static bool mt6635_SPI_hopping_check(unsigned short freq); +static signed int mt6635_soft_mute_tune(unsigned short freq, signed int *rssi, signed int *valid); + +static bool mt6635_do_SPI_hopping_26M(void) +{ + struct fm_ext_interface *ei = &fm_wcn_ops.ei; + signed int ret = 0; + unsigned int tem = 0, hw_ver_id = 0; + + /* switch SPI clock to 26MHz */ + if (ei->spi_clock_switch) + ret = ei->spi_clock_switch(FM_SPI_SPEED_26M); + else { + ret = -1; + WCN_DBG(FM_ERR | CHIP, "Clock switch cb is null\n"); + } + if (ret) + WCN_DBG(FM_ERR | CHIP, "Switch SPI clock to 26MHz failed\n"); + + ret = fm_host_reg_read(0x80021010, &hw_ver_id); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: read HW ver. failed\n", __func__); + hw_ver_id = hw_ver_id >> 16; + + /* unlock 64M */ + if (hw_ver_id == 0x1005 || hw_ver_id == 0x1002) { + ret = fm_host_reg_read(0x80023008, &tem); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: unlock 64M reg 0x880023008 failed\n", __func__); + ret = fm_host_reg_write(0x80023008, tem & (~(0x1 << 21))); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: unlock 64M failed\n", __func__); + } else { + ret = fm_host_reg_read(0x81021128, &tem); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: unlock 64M reg 0x81021128 failed\n", __func__); + ret = fm_host_reg_write(0x81021128, tem & ~0x1); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: unlock 64M failed\n", __func__); + ret = fm_host_reg_read(0x81024040, &tem); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: unlock 64M reg 0x81024040 failed\n", __func__); + ret = fm_host_reg_write(0x81024040, tem & ~0x3); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: unlock 64M failed\n", __func__); + } + + return ret == 0; +} + +static bool mt6635_do_SPI_hopping_64M(unsigned short freq) +{ + struct fm_ext_interface *ei = &fm_wcn_ops.ei; + signed int ret = 0; + signed int i = 0; + unsigned int tem = 0, hw_ver_id = 0; + bool flag_spi_hopping = false; + + if (!mt6635_SPI_hopping_check(freq)) + return true; + + /* SPI hopping setting*/ + WCN_DBG(FM_NTC | CHIP, + "%s: freq:%d is SPI hopping channel,turn on 64M PLL\n", + __func__, freq); + + ret = fm_host_reg_read(0x80021010, &hw_ver_id); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: read HW ver. failed\n", __func__); + WCN_DBG(FM_NTC | CHIP, "%s: HW ver. ID = 0x%08x\n", __func__, hw_ver_id); + hw_ver_id = hw_ver_id >> 16; + + /* lock 64M */ + if (hw_ver_id == 0x1005 || hw_ver_id == 0x1002) { + ret = fm_host_reg_read(0x80023008, &tem); + if (ret) + WCN_DBG(FM_ERR | CHIP, + "%s: lock 64M reg 0x80023008 failed\n", __func__); + ret = fm_host_reg_write(0x80023008, tem | (0x1 << 21)); + if (ret) + WCN_DBG(FM_ERR | CHIP, + "%s: lock 64M failed\n", __func__); + } else { + ret = fm_host_reg_read(0x81021128, &tem); + if (ret) + WCN_DBG(FM_ERR | CHIP, + "%s: read reg 0x81021128 failed\n", __func__); + ret = fm_host_reg_write(0x81021128, tem | 0x1); + if (ret) + WCN_DBG(FM_ERR | CHIP, + "%s: enable 'rf_spi_div_en' failed\n", __func__); + ret = fm_host_reg_read(0x81024040, &tem); + if (ret) + WCN_DBG(FM_ERR | CHIP, + "%s: lock 64M reg 0x81024040 failed\n", __func__); + ret = fm_host_reg_write(0x81024040, tem | 0x3); + if (ret) + WCN_DBG(FM_ERR | CHIP, + "%s: lock 64M failed\n", __func__); + } + for (i = 0; i < 100; i++) { /*rd 0x80021118 until D27 ==1*/ + + fm_host_reg_read(0x80021118, &tem); + + if (tem & 0x08000000) { + WCN_DBG(FM_NTC | CHIP, + "%s: POLLING PLL_RDY success !\n", __func__); + if (ei->spi_clock_switch) + flag_spi_hopping = ei->spi_clock_switch(FM_SPI_SPEED_64M) == 0; + break; + } + fm_delayus(10); + } + if (false == flag_spi_hopping) + WCN_DBG(FM_ERR | CHIP, + "%s: Polling to read rd 0x80021118[27] ==0x1 failed!\n", + __func__); + + return flag_spi_hopping; +} + +static signed int mt6635_pwron(signed int data) +{ + if (fm_wcn_ops.ei.wmt_func_on && !fm_wcn_ops.ei.wmt_func_on()) { + WCN_DBG(FM_ERR | CHIP, "WMT turn on FM Fail!\n"); + return -FM_ELINK; + } + + WCN_DBG(FM_NTC | CHIP, "WMT turn on FM OK!\n"); + return 0; +} + +static signed int mt6635_pwroff(signed int data) +{ + if (fm_wcn_ops.ei.wmt_func_off && !fm_wcn_ops.ei.wmt_func_off()) { + WCN_DBG(FM_ERR | CHIP, "WMT turn off FM Fail!\n"); + return -FM_ELINK; + } + + WCN_DBG(FM_NTC | CHIP, "WMT turn off FM OK!\n"); + return 0; +} + +static unsigned short mt6635_get_chipid(void) +{ + return 0x6635; +} + +/* MT6635_SetAntennaType - set Antenna type + * @type - 1, Short Antenna; 0, Long Antenna + */ +static signed int mt6635_SetAntennaType(signed int type) +{ + unsigned short dataRead = 0; + + WCN_DBG(FM_DBG | CHIP, "set ana to %s\n", type ? "short" : "long"); + fm_reg_read(FM_MAIN_CG2_CTRL, &dataRead); + + if (type) + dataRead |= ANTENNA_TYPE; + else + dataRead &= (~ANTENNA_TYPE); + + fm_reg_write(FM_MAIN_CG2_CTRL, dataRead); + + return 0; +} + +static signed int mt6635_GetAntennaType(void) +{ + unsigned short dataRead = 0; + + fm_reg_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 signed int mt6635_Mute(bool mute) +{ + signed int ret = 0; + unsigned short dataRead = 0; + + WCN_DBG(FM_DBG | CHIP, "set %s\n", mute ? "mute" : "unmute"); + /* fm_reg_read(FM_MAIN_CTRL, &dataRead); */ + fm_reg_read(0x9C, &dataRead); + + /* fm_top_reg_write(0x0050, 0x00000007); */ + if (mute == 1) + ret = fm_reg_write(0x9C, (dataRead & 0xFFFC) | 0x0003); + else + ret = fm_reg_write(0x9C, (dataRead & 0xFFFC)); + + /* fm_top_reg_write(0x0050, 0x0000000F); */ + + return ret; +} + +static signed int mt6635_rampdown_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + + /* A1. Clear DSP state */ + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFF0, 0x0000, &buf[pkt_size], buf_size - pkt_size); + /* A2. Set DSP ramp down state */ + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFFF, RAMP_DOWN, &buf[pkt_size], buf_size - pkt_size); + /* @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); + /* A6. Clear DSP ramp down state */ + pkt_size += fm_bop_modify(FM_MAIN_CTRL, (~RAMP_DOWN), 0x0000, &buf[pkt_size], buf_size - pkt_size); + /* A7. 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); + + return pkt_size - 4; +} +/* + * mt6635_rampdown - f/w will wait for STC_DONE interrupt + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6635_rampdown(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6635_rampdown_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_RAMPDOWN_OPCODE, pkt_size); +} + +/* FMSYS Ramp Down Sequence*/ +static signed int mt6635_RampDown(void) +{ + signed int ret = 0; + unsigned short pkt_size; + /* unsigned short tmp; */ + + WCN_DBG(FM_DBG | CHIP, "ramp down\n"); + + mt6635_do_SPI_hopping_26M(); + + /* A0.0 Host control RF register */ + ret = fm_set_bits(0x60, 0x0007, 0xFFF0); /*Set 0x60 [D3:D0] = 0x7*/ + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down HOST control rf: Set 0x60 [D3:D0] = 0x7 failed\n"); + return ret; + } + + /* A0.1 Update FM ADPLL fast tracking mode gain */ + ret = fm_set_bits(0x0F, 0x0000, 0xF800); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down ADPLL gainA/B: Set 0xFH [D10:D0] = 0x000 failed\n"); + return ret; + } + + /* A0.2 Host control RF register */ + ret = fm_set_bits(0x60, 0x000F, 0xFFF0); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down Host control RF registerwr top 0x60 failed\n"); + return ret; + } + /* A1. Clear dsp state*/ + ret = fm_set_bits(0x63, 0x0000, 0xFFF0); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down Host control RF registerwr top 0x63 failed\n"); + return ret; + } + /* A2. Set DSP ramp down state*/ + ret = fm_set_bits(0x63, 0x0010, 0xFFEF); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down Host control RF registerwr top 0x63 failed\n"); + return ret; + } + + /* A3. Clear STC_DONE interrupt */ + ret = fm_reg_write(FM_MAIN_INTRMASK, 0x0000); + if (ret) + WCN_DBG(FM_ERR | CHIP, "ramp down clean FM_MAIN_INTRMASK failed\n"); + + ret = fm_reg_write(FM_MAIN_EXTINTRMASK, 0x0000); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down clean FM_MAIN_EXTINTRMASK failed\n"); + return ret; + } + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6635_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; + } + + ret = fm_reg_write(FM_MAIN_EXTINTRMASK, 0x0021); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down wr FM_MAIN_EXTINTRMASK failed\n"); + return ret; + } + + ret = fm_reg_write(FM_MAIN_INTRMASK, 0x0021); + if (ret) + WCN_DBG(FM_ERR | CHIP, "ramp down wr FM_MAIN_INTRMASK failed\n"); + + return ret; +} + +static signed int mt6635_get_rom_version(void) +{ + unsigned short flag_Romcode = 0; + unsigned short nRomVersion = 0; +#define ROM_CODE_READY 0x0001 + signed int ret = 0; + + /* A1.1 DSP rom code version request enable --- set 0x61 b15=1 */ + fm_set_bits(0x61, 0x8000, 0x7FFF); + + /* A1.2 Release ASIP reset --- set 0x61 b1=1 */ + fm_set_bits(0x61, 0x0002, 0xFFFD); + + /* A1.3 Enable ASIP power --- set 0x61 b0=0 */ + fm_set_bits(0x61, 0x0000, 0xFFFE); + + /* A1.4 Wait until DSP code version ready --- wait loop 1ms */ + do { + fm_delayus(1000); + ret = fm_reg_read(0x84, &flag_Romcode); + /* ret=-4 means signal got when control FM. usually get sig 9 to kill FM process. */ + /* now cancel FM power up sequence is recommended. */ + if (ret) + return ret; + + WCN_DBG(FM_DBG | CHIP, "ROM_CODE_READY flag 0x84=%x\n", flag_Romcode); + } while (flag_Romcode != ROM_CODE_READY); + + + /* A1.5 Read FM DSP code version --- rd 0x83[15:8] */ + fm_reg_read(0x83, &nRomVersion); + nRomVersion = (nRomVersion >> 8); + + /* A1.6 DSP rom code version request disable --- set 0x61 b15=0 */ + fm_set_bits(0x61, 0x0000, 0x7FFF); + + /* A1.7 Reset ASIP --- set 0x61[1:0] = 1 */ + fm_set_bits(0x61, 0x0001, 0xFFFC); + + return (signed int) nRomVersion; +} + +static signed int mt6635_pwrup_clock_on_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + unsigned short de_emphasis; + /* unsigned short osc_freq; */ + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + de_emphasis = fm_config.rx_cfg.deemphasis; + de_emphasis &= 0x0001; /* rang 0~1 */ + /* 2,turn on top clock */ + pkt_size += fm_bop_top_write(0xA00, 0xFFFFFFFF, &buf[pkt_size], buf_size - pkt_size); + /* wr top cr a00 ffffffff */ + + /* 3,enable MTCMOS */ + pkt_size += fm_bop_top_write(0x160, 0x00000030, &buf[pkt_size], buf_size - pkt_size); + /* wr top 160 30 */ + + pkt_size += fm_bop_top_write(0x160, 0x00000035, &buf[pkt_size], buf_size - pkt_size); + /* wr top 160 35 */ + pkt_size += fm_bop_udelay(10, &buf[pkt_size], buf_size - pkt_size); + /* delay 10us */ + pkt_size += fm_bop_top_write(0x160, 0x00000015, &buf[pkt_size], buf_size - pkt_size); + /* wr top 160 15 */ + pkt_size += fm_bop_top_write(0x160, 0x00000005, &buf[pkt_size], buf_size - pkt_size); + /* wr top 160 5 */ + + pkt_size += fm_bop_udelay(10, &buf[pkt_size], buf_size - pkt_size); + /* delay 10us */ + pkt_size += fm_bop_top_write(0x160, 0x00000045, &buf[pkt_size], buf_size - pkt_size); + /* wr top 160 45 */ + + /* 4,set comspi fm slave dumy count */ + pkt_size += fm_bop_write(0x7f, 0x801f, &buf[pkt_size], buf_size - pkt_size); /* wr 7f 801f */ + + /* A. FM digital clock enable */ + /* A1. Wait 3ms */ + pkt_size += fm_bop_udelay(3000, &buf[pkt_size], buf_size - pkt_size); + + /* A2. Release HW clock gating*/ + pkt_size += fm_bop_write(0x60, 0x0007, &buf[pkt_size], buf_size - pkt_size); /* wr 60 7 */ + /* A3. Enable DSP auto clock gating */ + pkt_size += fm_bop_write(0x70, 0x0040, &buf[pkt_size], buf_size - pkt_size); /* wr 70 0040 */ + /* A4. Deemphasis setting: Set 0 for 50us, Set 1 for 75us */ + pkt_size += fm_bop_modify(0x61, ~DE_EMPHASIS, (de_emphasis << 12), &buf[pkt_size], buf_size - pkt_size); + + return pkt_size - 4; +} +/* + * mt6635_pwrup_clock_on - Wholechip FM Power Up: step 1, FM Digital Clock enable + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6635_pwrup_clock_on(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6635_pwrup_clock_on_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +static signed int mt6635_pwrup_digital_init_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* Part D FM RF&ADPLL divider setting */ + + /* D2.1 set cell mode */ + /* wr 30 D3:D2 00:FDD(default),01:both.10: TDD, 11 FDD */ + /* pkt_size += fm_bop_modify(0x30, 0xFFF3, 0x0000, &buf[pkt_size], buf_size - pkt_size); */ + + /* D2.2 set ADPLL divider */ + pkt_size += fm_bop_write(0x21, 0xE000, &buf[pkt_size], buf_size - pkt_size); /* wr 21 E000 */ + /* D2.3 set SDM coeff0_H */ + pkt_size += fm_bop_write(0xD8, 0x03F0, &buf[pkt_size], buf_size - pkt_size); /* wr D8 0x03F0 */ + /* D2.4 set SDM coeff0_L */ + pkt_size += fm_bop_write(0xD9, 0x3F04, &buf[pkt_size], buf_size - pkt_size); /* wr D9 0x3F04 */ + /* D2.5 set SDM coeff1_H */ + pkt_size += fm_bop_write(0xDA, 0x0014, &buf[pkt_size], buf_size - pkt_size); /* wr DA 0x0014 */ + /* D2.6 set SDM coeff1_L */ + pkt_size += fm_bop_write(0xDB, 0x2A38, &buf[pkt_size], buf_size - pkt_size); /* wr DB 0x2A38 */ + /* D2.7 set 26M clock */ + pkt_size += fm_bop_write(0x23, 0x4000, &buf[pkt_size], buf_size - pkt_size); /* wr 23 4000 */ + + /* Part E: FM Digital Init: fm_rgf_maincon */ + + /* E4. Set appropriate interrupt mask behavior as desired */ + /* Enable stc_done_mask, Enable rgf_rds_mask*/ + pkt_size += fm_bop_write(0x6A, 0x0021, &buf[pkt_size], buf_size - pkt_size); /* wr 6A 0021 */ + pkt_size += fm_bop_write(0x6B, 0x0021, &buf[pkt_size], buf_size - pkt_size); /* wr 6B 0021 */ + + /* E5. Enable hw auto control */ + pkt_size += fm_bop_write(0x60, 0x0000000F, &buf[pkt_size], buf_size - pkt_size); /* wr 60 f */ + + /* E6. Release ASIP reset */ + pkt_size += fm_bop_modify(0x61, 0xFFFD, 0x0002, &buf[pkt_size], buf_size - pkt_size); /* wr 61 D1=1 */ + /* E7. Enable ASIP power */ + pkt_size += fm_bop_modify(0x61, 0xFFFE, 0x0000, &buf[pkt_size], buf_size - pkt_size); /* wr 61 D0=0 */ + + /* E8 */ + pkt_size += fm_bop_udelay(100000, &buf[pkt_size], buf_size - pkt_size); /* delay 100ms */ + /* E9. Check HW initial complete */ + pkt_size += fm_bop_rd_until(0x64, 0x001F, 0x0002, &buf[pkt_size], buf_size - pkt_size); /* Poll 64[0~4] = 2 */ + + return pkt_size - 4; +} + +/* + * mt6635_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 + */ +static signed int mt6635_pwrup_digital_init(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6635_pwrup_digital_init_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +static signed int mt6635_pwrup_fine_tune_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* F1 set host control RF register */ + pkt_size += fm_bop_write(0x60, 0x00000007, &buf[pkt_size], buf_size - pkt_size); + + /* F2 fine tune RF setting */ + pkt_size += fm_bop_write(0x01, 0xBEE8, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x03, 0xF6ED, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x15, 0x0D80, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x16, 0x0068, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x17, 0x092A, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x34, 0x807F, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x35, 0x311E, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x40, 0x0100, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x03, 0xFAF5, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x05, 0x7A80, &buf[pkt_size], buf_size - pkt_size); + + /* F4 set DSP control RF register */ + pkt_size += fm_bop_write(0x60, 0x0000000F, &buf[pkt_size], buf_size - pkt_size); + + return pkt_size - 4; +} + +/* + * mt6635_pwrup_fine_tune - Wholechip FM Power Up: step 5, FM RF fine tune setting + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6635_pwrup_fine_tune(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6635_pwrup_fine_tune_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +static signed int mt6635_pwrdown_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* A1:set audio output I2S Tx mode: */ + pkt_size += fm_bop_modify(0x9B, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size); + + /* B0:Disable HW clock control */ + pkt_size += fm_bop_write(0x60, 0x330F, &buf[pkt_size], buf_size - pkt_size); + /* B1:Reset ASIP : Set 0x61, [D1 = 0, D0=1] */ + pkt_size += fm_bop_modify(0x61, 0xFFFD, 0x0001, &buf[pkt_size], buf_size - pkt_size); + + /* B2:digital core + digital rgf reset */ + pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size); + + /* B3:Disable all clock */ + pkt_size += fm_bop_write(0x60, 0x0000, &buf[pkt_size], buf_size - pkt_size); + /* B4:Reset rgfrf */ + pkt_size += fm_bop_write(0x60, 0x4000, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x60, 0x0000, &buf[pkt_size], buf_size - pkt_size); + + /* MTCMOS power off */ + /* C0:disable MTCMOS */ + pkt_size += fm_bop_top_write(0x160, 0x0005, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_top_write(0x160, 0x0015, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_top_write(0x160, 0x0035, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_top_write(0x160, 0x0030, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_top_rd_until(0x160, 0x0000000A, 0x0, &buf[pkt_size], buf_size - pkt_size); + + return pkt_size - 4; +} +/* + * mt6635_pwrdown - Wholechip FM Power down: Digital Modem Power Down + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6635_pwrdown(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6635_pwrdown_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +static signed int mt6635_tune_reg_op(unsigned char *buf, signed int buf_size, unsigned short freq, + unsigned short chan_para) +{ + signed int pkt_size = 4; + + WCN_DBG(FM_ALT | CHIP, "%s enter mt6635_tune function\n", __func__); + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* A2 Enable hardware controlled tuning sequence */ + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFF8, TUNE, &buf[pkt_size], buf_size - pkt_size);/*Set 0x63 D0=1*/ + /* Wait for STC_DONE interrupt */ + + +#ifdef FM_TUNE_USE_POLL + /* A3 Wait for STC_DONE interrupt */ + /* A4 Wait for STC_DONE interrupt status flag */ + pkt_size += fm_bop_rd_until(FM_MAIN_INTR, FM_INTR_STC_DONE, + FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size); + /* A6 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); +#endif + + pkt_size += fm_bop_udelay(100000, &buf[pkt_size], buf_size - pkt_size); + WCN_DBG(FM_ALT | CHIP, "mt6635_tune delay 100 ms wait 0x69 to change\n"); + + WCN_DBG(FM_ALT | CHIP, "%s leave mt6635_tune function\n", __func__); + + return pkt_size - 4; +} + +/* + * mt6635_tune - execute tune action, + * @buf - target buf + * @buf_size - buffer size + * @freq - 760 ~ 1080, 100KHz unit + * return package size + */ +static signed int mt6635_tune(unsigned char *buf, signed int buf_size, unsigned short freq, + unsigned short chan_para) +{ + signed int pkt_size = 0; + + pkt_size = mt6635_tune_reg_op(buf, buf_size, freq, chan_para); + return fm_op_seq_combine_cmd(buf, FM_TUNE_OPCODE, pkt_size); +} + +/* + * mt6635_pwrup_DSP_download - execute dsp/coeff patch dl action, + * @patch_tbl - current chip patch table + * return patch dl ok or not + */ +static signed int mt6635_pwrup_DSP_download(struct fm_patch_tbl *patch_tbl) +{ +#define PATCH_BUF_SIZE (4096*6) + signed int ret = 0; + signed int patch_len = 0; + unsigned char *dsp_buf = NULL; + unsigned short tmp_reg = 0; + + if (fm_wcn_ops.ei.wmt_ic_info_get) + mt6635_hw_info.eco_ver = fm_wcn_ops.ei.wmt_ic_info_get(); + WCN_DBG(FM_DBG | CHIP, "ECO version:0x%08x\n", mt6635_hw_info.eco_ver); + + /* Wholechip FM Power Up: step 3, get mt6635 DSP ROM version */ + ret = mt6635_get_rom_version(); + if (ret >= 0) { + mt6635_hw_info.rom_ver = ret; + WCN_DBG(FM_NTC | CHIP, "%s ROM version: v%d\n", __func__, mt6635_hw_info.rom_ver); + } else { + WCN_DBG(FM_ERR | CHIP, "get ROM version failed\n"); + if (ret == -4) + WCN_DBG(FM_ERR | CHIP, "signal got when control FM, usually get sig 9 to kill FM process.\n"); + /* now cancel FM power up sequence is recommended. */ + goto out; + } + + /* Wholechip FM Power Up: step 4 download patch */ + dsp_buf = fm_vmalloc(PATCH_BUF_SIZE); + if (!dsp_buf) { + WCN_DBG(FM_ALT | CHIP, "-ENOMEM\n"); + return -ENOMEM; + } + + patch_len = fm_get_patch_path(mt6635_hw_info.rom_ver, dsp_buf, PATCH_BUF_SIZE, patch_tbl); + if (patch_len <= 0) { + WCN_DBG(FM_ALT | CHIP, " fm_get_patch_path failed\n"); + ret = patch_len; + goto out; + } + + ret = fm_download_patch((const unsigned char *)dsp_buf, patch_len, IMG_PATCH); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " DL DSPpatch failed\n"); + goto out; + } + + patch_len = fm_get_coeff_path(mt6635_hw_info.rom_ver, dsp_buf, PATCH_BUF_SIZE, patch_tbl); + if (patch_len <= 0) { + WCN_DBG(FM_ALT | CHIP, " fm_get_coeff_path failed\n"); + ret = patch_len; + goto out; + } + + mt6635_hw_info.rom_ver += 1; + + tmp_reg = dsp_buf[38] | (dsp_buf[39] << 8); /* to be confirmed */ + mt6635_hw_info.patch_ver = (signed int) tmp_reg; + WCN_DBG(FM_NTC | CHIP, "Patch version: 0x%08x\n", mt6635_hw_info.patch_ver); + + ret = fm_download_patch((const unsigned char *)dsp_buf, patch_len, IMG_COEFFICIENT); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " Download DSP coefficient failed\n"); + goto out; + } + + /* Download HWACC coefficient */ + fm_reg_write(0x92, 0x0000); + fm_reg_write(0x90, 0x0040); /* Reset download control */ + fm_reg_write(0x90, 0x0000); /* Disable memory control from host*/ +out: + if (dsp_buf) + fm_vfree(dsp_buf); + return ret; +} +static void mt6635_show_reg(void) +{ + unsigned int host_reg[3] = {0}; + unsigned int debug_reg1[3] = {0}; + unsigned short debug_reg2[3] = {0}; + + fm_host_reg_read(0x8102600C, &host_reg[0]); + fm_host_reg_read(0x81021500, &host_reg[1]); + fm_host_reg_read(0x81021200, &host_reg[2]); + WCN_DBG(FM_ALT | CHIP, + "host read 0x8102600C = 0x%08x, 0x81021500 = 0x%08x, 0x81021200 = 0x%08x\n", + host_reg[0], host_reg[1], host_reg[2]); + + fm_top_reg_read(0x003c, &debug_reg1[0]); + fm_top_reg_read(0x0a18, &debug_reg1[1]); + fm_top_reg_read(0x0160, &debug_reg1[2]); + fm_reg_read(0x7f, &debug_reg2[0]); + fm_reg_read(0x62, &debug_reg2[1]); + fm_reg_read(0x60, &debug_reg2[2]); + WCN_DBG(FM_ALT | CHIP, + "top cr 0x3c = 0x%08x, 0xa18 = 0x%08x, 0x160 = 0x%08x, fmreg 0x7f = 0x%08x, 0x62 = 0x%08x, 0x60 = 0x%08x\n", + debug_reg1[0], debug_reg1[1], debug_reg1[2], debug_reg2[0], debug_reg2[1], debug_reg2[2]); +} + +static signed int mt6635_PowerUp(unsigned short *chip_id, unsigned short *device_id) +{ + signed int ret = 0; + unsigned short pkt_size; + unsigned short tmp_reg = 0; + unsigned int tem = 0; + unsigned int host_reg = 0; + + if (chip_id == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (device_id == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + WCN_DBG(FM_DBG | CHIP, "pwr on seq......\n"); + + /* Wholechip FM Power Up: step 1, set common SPI parameter */ + ret = fm_host_reg_write(0x8102600C, 0x0000801F); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup set CSPI failed\n"); + return ret; + } + + + /* Set top_clk_en_adie to trigger sleep controller before FM power on */ + ret = fm_host_reg_write(0x81021500, 0x00000003); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup set top_clk_en_adie failed\n"); + return ret; + } + + /* Disable 26M crystal sleep */ + fm_host_reg_read(0x81021200, &tem); /* Set 0x81021200[23] = 0x1 */ + tem = tem | 0x00800000; + fm_host_reg_write(0x81021200, tem); + + /* Enable the power_RG_ready */ + ret = fm_top_reg_read(0x0a18, &host_reg); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "power up read top 0xa18 failed\n"); + return ret; + } + ret = fm_top_reg_write(0x0a18, host_reg | (0x3 << 26)); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "power up write top 0xa18 failed\n"); + return ret; + } + + /* Enable the buffer to top digital domain */ + ret = fm_top_reg_read(0x0a18, &host_reg); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "power up read top 0xa18 failed\n"); + return ret; + } + ret = fm_top_reg_write(0x0a18, host_reg | (0x1f << 25)); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "power up write top 0xa18 failed\n"); + return ret; + } + + /* Enable the buffer to FM RF domain */ + ret = fm_top_reg_read(0x0a18, &host_reg); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "power up read top 0xa18 failed\n"); + return ret; + } + ret = fm_top_reg_write(0x0a18, host_reg | (0x01 << 12)); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "power up write top 0xa18 failed\n"); + return ret; + } + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + + pkt_size = mt6635_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, "mt6635_pwrup_clock_on failed\n"); + return ret; + } + + /* Wholechip FM Power Up: step 2, read HW version */ + mt6635_show_reg(); + fm_reg_read(0x62, &tmp_reg); + /* chip_id = tmp_reg; */ + if (tmp_reg == 0x6635) + *chip_id = 0x6635; + *device_id = tmp_reg; + mt6635_hw_info.chip_id = (signed int) tmp_reg; + WCN_DBG(FM_DBG | CHIP, "chip_id:0x%04x\n", tmp_reg); + + if ((mt6635_hw_info.chip_id != 0x6635)) { + mt6635_show_reg(); + WCN_DBG(FM_NTC | CHIP, "fm sys error, reset hw, chip_id = 0x%08x\n", mt6635_hw_info.chip_id); + return -FM_EFW; + + } + /* Wholechip FM Power Up: step 3, patch download */ + ret = mt6635_pwrup_DSP_download(mt6635_patch_tbl); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "mt6635_pwrup_DSP_download failed\n"); + return ret; + } + + /* Wholechip FM Power Up: step 4, FM Digital Init: fm_rgf_maincon */ + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6635_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, "mt6635_pwrup_digital_init failed\n"); + return ret; + } + + /* Wholechip FM Power Up: step 5, FM RF fine tune setting */ + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6635_pwrup_fine_tune(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, "mt6635_pwrup_fine_tune failed\n"); + return ret; + } + + /* Enable connsys FM 2 wire RX */ + fm_reg_write(0x9B, 0xF9AB); /* G2: Set audio output i2s TX mode */ + fm_host_reg_write(0x81024064, 0x00000014); /* G3: Enable aon_osc_clk_cg */ + fm_host_reg_write(0x81024058, 0x888100C3); /* G4: Enable FMAUD trigger, 20170119 */ + fm_host_reg_write(0x81024054, 0x00000100); /* G5: Release fmsys memory power down*/ + + WCN_DBG(FM_NTC | CHIP, "pwr on seq ok\n"); + + return ret; +} + +static signed int mt6635_PowerDown(void) +{ + signed int ret = 0; + unsigned int tem = 0; + unsigned short pkt_size; + unsigned int host_reg = 0; + /* unsigned int host_reg = 0; */ + + WCN_DBG(FM_DBG | CHIP, "pwr down seq\n"); + + /* A0.1. Disable aon_osc_clk_cg */ + ret = fm_host_reg_write(0x81024064, 0x00000004); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " Disable aon_osc_clk_cg failed\n"); + return ret; + } + /* A0.1. Disable FMAUD trigger */ + ret = fm_host_reg_write(0x81024058, 0x88800000); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " Disable FMAUD trigger failed\n"); + return ret; + } + + /* A0.1. issue fmsys memory powr down */ + ret = fm_host_reg_write(0x81024054, 0x00000180); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " Issue fmsys memory powr down failed\n"); + return ret; + } + + mt6635_do_SPI_hopping_26M(); + + /* Enable 26M crystal sleep */ + WCN_DBG(FM_DBG | CHIP, "PowerDown: Enable 26M crystal sleep,Set 0x81021200[23] = 0x0\n"); + fm_host_reg_read(0x81021200, &tem); /* Set 0x81021200[23] = 0x0 */ + tem = tem & 0xFF7FFFFF; + ret = fm_host_reg_write(0x81021200, tem); + + if (ret) + WCN_DBG(FM_ALT | CHIP, "PowerDown: Enable 26M crystal sleep,Set 0x81021200[23] = 0x0 failed\n"); + + /* A0:set audio output I2X Rx mode: */ + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6635_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, "mt6635_pwrdown failed\n"); + return ret; + } + + /* RF power off */ + /* Disnable the buffer to fm rf domain */ + ret = fm_top_reg_read(0x0a18, &host_reg); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "power down read top 0xa18 failed\n"); + return ret; + } + ret = fm_top_reg_write(0x0a18, host_reg & (~(0x1 << 12))); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "power down write top 0xa18 failed\n"); + return ret; + } + + return ret; +} + +static signed int mt6635_set_freq_fine_tune_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* disable DCOC IDAC auto-disable */ + pkt_size += fm_bop_modify(0x33, 0xFDFF, 0x0000, &buf[pkt_size], buf_size - pkt_size); + /* A1 Host control RF register */ + pkt_size += fm_bop_write(0x60, 0x0007, &buf[pkt_size], buf_size - pkt_size); + /* F3 DCOC @ LNA = 7 */ + pkt_size += fm_bop_write(0x40, 0x01AF, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x03, 0xFAF5, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x07, 0x0100, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x01, 0xEEE8, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x3F, 0x3221, &buf[pkt_size], buf_size - pkt_size); + /* wait 1ms */ + pkt_size += fm_bop_udelay(1000, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_rd_until(0x3F, 0x001F, 0x0001, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x3F, 0x0220, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x40, 0x0100, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x01, 0xAEE8, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x30, 0x0000, &buf[pkt_size], buf_size - pkt_size); + pkt_size += fm_bop_write(0x36, 0x017A, &buf[pkt_size], buf_size - pkt_size); + /* set threshold = 4 */ + pkt_size += fm_bop_modify(0x3F, 0x0FFF, 0x4000, &buf[pkt_size], buf_size - pkt_size); + /* enable DCOC IDAC auto-disable */ + pkt_size += fm_bop_modify(0x33, 0xFDFF, 0x0200, &buf[pkt_size], buf_size - pkt_size); + + /* F4 set DSP control RF register */ + pkt_size += fm_bop_write(0x60, 0x000F, &buf[pkt_size], buf_size - pkt_size); + + return pkt_size - 4; +} + +/* + * mt6635_set_freq_fine_tune - FM RF fine tune setting + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6635_set_freq_fine_tune(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6635_set_freq_fine_tune_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +static bool mt6635_SetFreq(unsigned short freq) +{ + signed int ret = 0; + unsigned short pkt_size; + unsigned short chan_para = 0; + unsigned short freq_reg = 0; + unsigned short tmp_reg[6] = {0}; + + fm_cb_op->cur_freq_set(freq); + + /* FM VCO Calibration */ + ret = fm_set_bits(0x60, 0x0007, 0xFFF0); /* Set 0x60 [D3:D0] = 0x07*/ + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Host Control RF register 0x60 = 0x7 failed\n", __func__); + + fm_delayus(5); + if (freq >= 750) { + fm_reg_write(0x37, 0xF68C); + fm_reg_write(0x38, 0x0B53); + ret = fm_set_bits(0x30, 0x0014 << 8, 0xC0FF); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Set 0x30 failed\n", __func__); + + } else { + fm_reg_write(0x37, 0x0675); + fm_reg_write(0x38, 0x0F54); + ret = fm_set_bits(0x30, 0x001C << 8, 0xC0FF); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Set 0x30 failed\n", __func__); + } + ret = fm_set_bits(0x30, 0x0001 << 14, 0xBFFF); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Set 0x30 failed\n", __func__); + + fm_reg_write(0x40, 0x010F); + fm_delayus(5); + fm_reg_write(0x36, 0x037A); + fm_reg_write(0x32, 0x8000); + fm_delayus(200); + ret = fm_set_bits(0x3D, 0x0001 << 2, 0xFFFB); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Set 0x3D failed\n", __func__); + + fm_reg_write(0x32, 0x0000); + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6635_set_freq_fine_tune(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, "mt6635_pwrup_fine_tune failed\n"); + return ret; + } + + /* A0. Host contrl RF register */ + ret = fm_set_bits(0x60, 0x0007, 0xFFF0); /* Set 0x60 [D3:D0] = 0x07*/ + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Host Control RF register 0x60 = 0x7 failed\n", __func__); + + /* A0.1 Update FM ADPLL fast tracking mode gain */ + ret = fm_set_bits(0x0F, 0x0455, 0xF800); + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Set FM ADPLL gainA/B=0x455 failed\n", __func__); + + /* A0.2 Set FMSYS cell mode */ + if (mt6635_TDD_chan_check(freq)) { + ret = fm_set_bits(0x30, 0x0008, 0xFFF3); /* use TDD solution */ + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: freq[%d]: use TDD solution failed\n", __func__, freq); + } else { + ret = fm_set_bits(0x30, 0x0000, 0xFFF3); /* default use FDD solution */ + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: freq[%d]: default use FDD solution failed\n", __func__, freq); + } + + /* A0.3 Host control RF register */ + ret = fm_set_bits(0x60, 0x000F, 0xFFF0); /* Set 0x60 [D3:D0] = 0x0F*/ + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Set 0x60 [D3:D0] = 0x0F failed\n", __func__); + + /* A1 Get Channel parameter from map list*/ + + chan_para = mt6635_chan_para_get(freq); + WCN_DBG(FM_DBG | CHIP, "%s: %d chan para = %d\n", __func__, (signed int) freq, (signed int) chan_para); + + freq_reg = freq; + if (fm_get_channel_space(freq_reg) == 0) + freq_reg *= 10; + + freq_reg = (freq_reg - 6400) * 2 / 10; + + /*A1 Set rgfrf_chan = XXX*/ + ret = fm_set_bits(0x65, freq_reg, 0xFC00); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "%s: set rgfrf_chan = xxx = %d failed\n", __func__, freq_reg); + return false; + } + + ret = fm_set_bits(0x65, (chan_para << 12), 0x0FFF); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x65 failed\n"); + return false; + } + + if (!mt6635_do_SPI_hopping_64M(freq)) + WCN_DBG(FM_ERR | CHIP, "%s: spi hopping fail!\n", __func__); + + /* A0. Host contrl RF register */ + ret = fm_set_bits(0x60, 0x0007, 0xFFF0); /* Set 0x60 [D3:D0] = 0x07*/ + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Host Control RF register 0x60 = 0x7 failed\n", __func__); + + + fm_reg_read(0x62, &tmp_reg[0]); + fm_reg_read(0x64, &tmp_reg[1]); + fm_reg_read(0x69, &tmp_reg[2]); + fm_reg_read(0x6a, &tmp_reg[3]); + fm_reg_read(0x6b, &tmp_reg[4]); + fm_reg_read(0x9b, &tmp_reg[5]); + + WCN_DBG(FM_ALT | CHIP, "%s: Before tune--0x62 0x64 0x69 0x6a 0x6b 0x9b = %04x %04x %04x %04x %04x %04x\n", + __func__, + tmp_reg[0], + tmp_reg[1], + tmp_reg[2], + tmp_reg[3], + tmp_reg[4], + tmp_reg[5]); + + /* A0.3 Host control RF register */ + ret = fm_set_bits(0x60, 0x000F, 0xFF00); /* Set 0x60 [D3:D0] = 0x0F*/ + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Set 0x60 [D3:D0] = 0x0F failed\n", __func__); + + if (FM_LOCK(cmd_buf_lock)) + return false; + pkt_size = mt6635_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); + + + /* A0. Host contrl RF register */ + ret = fm_set_bits(0x60, 0x0007, 0xFFF0); /* Set 0x60 [D3:D0] = 0x07*/ + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Host Control RF register 0x60 = 0x7 failed\n", __func__); + + memset(tmp_reg, 0, sizeof(tmp_reg[0])*6); + + fm_reg_read(0x62, &tmp_reg[0]); + fm_reg_read(0x64, &tmp_reg[1]); + fm_reg_read(0x69, &tmp_reg[2]); + fm_reg_read(0x6a, &tmp_reg[3]); + fm_reg_read(0x6b, &tmp_reg[4]); + fm_reg_read(0x9b, &tmp_reg[5]); + + WCN_DBG(FM_ALT | CHIP, "%s: After tune--0x62 0x64 0x69 0x6a 0x6b 0x9b = %04x %04x %04x %04x %04x %04x\n", + __func__, + tmp_reg[0], + tmp_reg[1], + tmp_reg[2], + tmp_reg[3], + tmp_reg[4], + tmp_reg[5]); + + /* A0.3 Host control RF register */ + ret = fm_set_bits(0x60, 0x000F, 0xFF00); /* Set 0x60 [D3:D0] = 0x0F*/ + if (ret) + WCN_DBG(FM_ERR | CHIP, "%s: Set 0x60 [D3:D0] = 0x0F failed\n", __func__); + + if (ret) { + WCN_DBG(FM_ALT | CHIP, "%s: mt6635_tune failed\n", __func__); + return false; + } + + WCN_DBG(FM_DBG | CHIP, "%s: set freq to %d ok\n", __func__, freq); +#if 0 + /* ADPLL setting for dbg */ + fm_top_reg_write(0x0050, 0x00000007); + fm_top_reg_write(0x0A08, 0xFFFFFFFF); + mt6635_bt_write(0x82, 0x11); + mt6635_bt_write(0x83, 0x11); + mt6635_bt_write(0x84, 0x11); + fm_top_reg_write(0x0040, 0x1C1C1C1C); + fm_top_reg_write(0x0044, 0x1C1C1C1C); + fm_reg_write(0x70, 0x0010); + /*0x0806 DCO clk + *0x0802 ref clk + *0x0804 feedback clk + */ + fm_reg_write(0xE0, 0x0806); +#endif + return true; +} + +#define FM_CQI_LOG_PATH "/mnt/sdcard/fmcqilog" + +static signed int mt6635_full_cqi_get(signed int min_freq, signed int max_freq, signed int space, signed int cnt) +{ + signed int ret = 0; + unsigned short pkt_size; + unsigned short freq, orig_freq; + signed int i, j, k; + signed int space_val, max, min, num; + struct mt6635_full_cqi *p_cqi; + unsigned char *cqi_log_title = "Freq, RSSI, PAMD, PR, FPAMD, MR, ATDC, PRX, ATDEV, SMGain, DltaRSSI\n"; + unsigned char cqi_log_buf[100] = { 0 }; + signed int pos; + unsigned char cqi_log_path[100] = { 0 }; + + /* for soft-mute tune, and get cqi */ + freq = fm_cb_op->cur_freq_get(); + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + /* get cqi */ + orig_freq = freq; + if (fm_get_channel_space(min_freq) == 0) + min = min_freq * 10; + else + min = min_freq; + + if (fm_get_channel_space(max_freq) == 0) + 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; (orig_freq == 10000) && (g_dbg_level == 0xffffffff) && (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)); + if (sprintf(&cqi_log_path[strlen(FM_CQI_LOG_PATH)], "%d.txt", k + 1) < 0) + WCN_DBG(FM_NTC | CHIP, "sprintf fail\n"); + 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 = fm_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, fm_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (!ret && fm_res) { + WCN_DBG(FM_NTC | CHIP, "smt cqi size %d\n", fm_res->cqi[0]); + p_cqi = (struct mt6635_full_cqi *)&fm_res->cqi[2]; + for (i = 0; i < fm_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 */ + if (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) < 0) + WCN_DBG(FM_NTC | CHIP, "sprintf fail\n"); + /* 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 */ + } + + return ret; +} + +static unsigned short mt6635_read_dsp_reg(unsigned short addr) +{ + unsigned short regValue = 0; + + fm_reg_write(0x60, 0x07); + fm_reg_write(0xE2, addr); + fm_reg_write(0xE1, 0x01); + fm_reg_read(0xE4, ®Value); + fm_reg_write(0x60, 0x0F); + + return regValue; +} + +static bool mt6635_is_valid_freq(unsigned short freq) +{ + int i = 0; + bool valid = false; + signed int RSSI = 0, PAMD = 0, MR = 0; + unsigned int PRX = 0; + unsigned short softmuteGainLvl = 0; + unsigned short tmp_reg = 0; + + for (i = 0; i < 8; i++) { + fm_reg_read(0x6C, &tmp_reg); + RSSI += (((tmp_reg & 0x03FF) >= 512) ? + ((tmp_reg & 0x03FF) - 1024) : (tmp_reg & 0x03FF)) >> 3; + fm_reg_read(0xB4, &tmp_reg); + PAMD += (((tmp_reg & 0x1FF) >= 256) ? + ((tmp_reg & 0x01FF) - 512) : (tmp_reg & 0x01FF)) >> 3; + tmp_reg = mt6635_read_dsp_reg(0x4E1); + PRX += (tmp_reg & 0x00FF) >> 3; + fm_reg_read(0xBD, &tmp_reg); + MR += (((tmp_reg & 0x01FF) >= 256) ? + ((tmp_reg & 0x01FF) - 512) : (tmp_reg & 0x01FF)) >> 3; + tmp_reg = mt6635_read_dsp_reg(0x2C4); + softmuteGainLvl += tmp_reg >> 3; + fm_delayus(2250); + } + + if ((fm_config.rx_cfg.long_ana_rssi_th <= RSSI) + && (fm_config.rx_cfg.pamd_th >= PAMD) + && (fm_config.rx_cfg.mr_th <= MR) + && (fm_config.rx_cfg.prx_th <= PRX) + && (fm_config.rx_cfg.smg_th <= softmuteGainLvl)) { + valid = true; + } + + WCN_DBG(FM_DBG | CHIP, + "freq %d valid=%d, %d, %d, 0x%04x, 0x%04x, 0x%04x\n", + freq, valid, RSSI, PAMD, PRX, MR, softmuteGainLvl); + + return valid; +} + +/* + * mt6635_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 signed int mt6635_GetCurRSSI(signed int *pRSSI) +{ + unsigned short tmp_reg = 0; + + fm_reg_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 unsigned short mt6635_vol_tbl[16] = { 0x0000, 0x0519, 0x066A, 0x0814, + 0x0A2B, 0x0CCD, 0x101D, 0x1449, + 0x198A, 0x2027, 0x287A, 0x32F5, + 0x4027, 0x50C3, 0x65AD, 0x7FFF +}; + +static signed int mt6635_SetVol(unsigned char vol) +{ + signed int ret = 0; + + vol = (vol > 15) ? 15 : vol; + ret = fm_reg_write(0x7D, mt6635_vol_tbl[vol]); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "Set vol=%d Failed\n", vol); + return ret; + } + 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 signed int mt6635_GetVol(unsigned char *pVol) +{ + int ret = 0; + unsigned short tmp = 0; + signed int i; + + if (pVol == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + ret = fm_reg_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 (mt6635_vol_tbl[i] == tmp) { + *pVol = i; + break; + } + } + + WCN_DBG(FM_DBG | CHIP, "Get vol=%d OK\n", *pVol); + return 0; +} + +static signed int mt6635_dump_reg(void) +{ + signed int i; + unsigned short TmpReg = 0; + + for (i = 0; i < 0xff; i++) { + fm_reg_read(i, &TmpReg); + WCN_DBG(FM_NTC | CHIP, "0x%02x=0x%04x\n", i, TmpReg); + } + return 0; +} + +/*0:mono, 1:stereo*/ +static bool mt6635_GetMonoStereo(unsigned short *pMonoStereo) +{ +#define FM_BF_STEREO 0x1000 + unsigned short TmpReg = 0; + + if (pMonoStereo) { + fm_reg_read(FM_RSSI_IND, &TmpReg); + *pMonoStereo = (TmpReg & FM_BF_STEREO) >> 12; + } else { + WCN_DBG(FM_ERR | CHIP, "MonoStero: para err\n"); + return false; + } + + WCN_DBG(FM_NTC | CHIP, "Get MonoStero:0x%04x\n", *pMonoStereo); + return true; +} + +static signed int mt6635_SetMonoStereo(signed int MonoStereo) +{ + signed int ret = 0; + + WCN_DBG(FM_NTC | CHIP, "set to %s\n", MonoStereo ? "mono" : "auto"); + fm_reg_write(0x60, 0x0007); + + if (MonoStereo) /*mono */ + ret = fm_set_bits(0x75, 0x0008, ~0x0008); + else + ret = fm_set_bits(0x75, 0x0000, ~0x0008); + + fm_reg_write(0x60, 0x000F); + return ret; +} + +static signed int mt6635_GetCapArray(signed int *ca) +{ + unsigned short dataRead = 0; + unsigned short tmp = 0; + + if (ca == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + fm_reg_read(0x60, &tmp); + fm_reg_write(0x60, tmp & 0xFFF7); /* 0x60 D3=0 */ + + fm_reg_read(0x26, &dataRead); + *ca = dataRead; + + fm_reg_write(0x60, tmp); /* 0x60 D3=1 */ + return 0; +} + +/* + * mt6635_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 bool mt6635_GetCurPamd(unsigned short *pPamdLevl) +{ + unsigned short tmp_reg = 0; + unsigned short dBvalue, valid_cnt = 0; + int i, total = 0; + + for (i = 0; i < 8; i++) { + if (fm_reg_read(FM_ADDR_PAMD, &tmp_reg)) { + *pPamdLevl = 0; + return 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); + } + fm_delayms(3); + } + if (valid_cnt != 0) + *pPamdLevl = total / valid_cnt; + else + *pPamdLevl = 0; + + WCN_DBG(FM_NTC | CHIP, "PAMD=%d\n", *pPamdLevl); + return true; +} + +static signed int mt6635_i2s_info_get(signed int *ponoff, signed int *pmode, signed int *psample) +{ + if (ponoff == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (pmode == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (psample == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + *ponoff = fm_config.aud_cfg.i2s_info.status; + *pmode = fm_config.aud_cfg.i2s_info.mode; + *psample = fm_config.aud_cfg.i2s_info.rate; + + return 0; +} + +static signed int mt6635_get_audio_info(struct fm_audio_info_t *data) +{ + memcpy(data, &fm_config.aud_cfg, sizeof(struct fm_audio_info_t)); + return 0; +} + +static signed int mt6635_hw_info_get(struct fm_hw_info *req) +{ + if (req == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + req->chip_id = mt6635_hw_info.chip_id; + req->eco_ver = mt6635_hw_info.eco_ver; + req->patch_ver = mt6635_hw_info.patch_ver; + req->rom_ver = mt6635_hw_info.rom_ver; + + return 0; +} + +static signed int mt6635_pre_search(void) +{ + mt6635_RampDown(); + /* disable audio output I2S Rx mode */ + fm_host_reg_write(0x80101054, 0x00000000); + /* disable audio output I2S Tx mode */ + fm_reg_write(0x9B, 0x0000); + + return 0; +} + +static signed int mt6635_restore_search(void) +{ + mt6635_RampDown(); + /* set audio output I2S Tx mode */ + fm_reg_write(0x9B, 0xF9AB); + /* set audio output I2S Rx mode */ + fm_host_reg_write(0x80101054, 0x00003f35); + return 0; +} + +static signed int mt6635_soft_mute_tune(unsigned short freq, signed int *rssi, signed int *valid) +{ + signed int ret = 0; + unsigned short pkt_size; + struct mt6635_full_cqi *p_cqi; + signed int RSSI = 0, PAMD = 0, MR = 0, ATDC = 0; + unsigned int PRX = 0, ATDEV = 0; + unsigned short softmuteGainLvl = 0; + + /* Set rgf_host2dsp_reserve[2] = 1 */ + WCN_DBG(FM_NTC | CHIP, "start %s\n", __func__); + + ret = mt6635_chan_para_get(freq); + if (ret == 2) + ret = fm_set_bits(FM_CHANNEL_SET, 0x2000, 0x0FFF); /* mdf HiLo */ + else + ret = fm_set_bits(FM_CHANNEL_SET, 0x0000, 0x0FFF); /* clear FA/HL/ATJ */ + + if (!mt6635_do_SPI_hopping_64M(freq)) + WCN_DBG(FM_ERR | CHIP, "%s: spi hopping fail!\n", __func__); + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = fm_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, fm_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (!ret && fm_res) { + p_cqi = (struct mt6635_full_cqi *)&fm_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 ((fm_config.rx_cfg.long_ana_rssi_th <= RSSI) + && (fm_config.rx_cfg.pamd_th >= PAMD) + && (fm_config.rx_cfg.atdc_th >= ATDC) + && (fm_config.rx_cfg.mr_th <= MR) + && (fm_config.rx_cfg.prx_th <= PRX) + && (ATDEV >= ATDC) /* sync scan algorithm */ + && (fm_config.rx_cfg.smg_th <= softmuteGainLvl)) { + *valid = true; + } else { + *valid = false; + } + *rssi = RSSI; + } else { + WCN_DBG(FM_ALT | CHIP, "smt get CQI failed\n"); + return false; + } + WCN_DBG(FM_NTC | CHIP, "valid=%d\n", *valid); + return true; +} + +static bool mt6635_em_test(unsigned short group_idx, unsigned short item_idx, unsigned int item_value) +{ + return true; +} + +/* +*parm: +* parm.th_type: 0, RSSI. 1, desense RSSI. 2, SMG. +* parm.th_val: threshold value +*/ +static signed int mt6635_set_search_th(signed int idx, signed int val, signed int reserve) +{ + switch (idx) { + case 0: { + fm_config.rx_cfg.long_ana_rssi_th = val; + WCN_DBG(FM_NTC | CHIP, "set rssi th =%d\n", val); + break; + } + case 1: { + fm_config.rx_cfg.desene_rssi_th = val; + WCN_DBG(FM_NTC | CHIP, "set desense rssi th =%d\n", val); + break; + } + case 2: { + fm_config.rx_cfg.smg_th = val; + WCN_DBG(FM_NTC | CHIP, "set smg th =%d\n", val); + break; + } + default: + break; + } + return 0; +} + +static signed int MT6635_low_power_wa_default(signed int fmon) +{ + return 0; +} + +signed int mt6635_fm_low_ops_register(struct fm_callback *cb, struct fm_basic_interface *bi) +{ + signed int ret = 0; + /* Basic functions. */ + + if (bi == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,bi invalid pointer\n", __func__); + return -FM_EPARA; + } + if (cb->cur_freq_get == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,cb->cur_freq_get invalid pointer\n", __func__); + return -FM_EPARA; + } + if (cb->cur_freq_set == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,cb->cur_freq_set invalid pointer\n", __func__); + return -FM_EPARA; + } + fm_cb_op = cb; + + bi->pwron = mt6635_pwron; + bi->pwroff = mt6635_pwroff; + bi->chipid_get = mt6635_get_chipid; + bi->mute = mt6635_Mute; + bi->rampdown = mt6635_RampDown; + bi->pwrupseq = mt6635_PowerUp; + bi->pwrdownseq = mt6635_PowerDown; + bi->setfreq = mt6635_SetFreq; + bi->low_pwr_wa = MT6635_low_power_wa_default; + bi->get_aud_info = mt6635_get_audio_info; + bi->rssiget = mt6635_GetCurRSSI; + bi->volset = mt6635_SetVol; + bi->volget = mt6635_GetVol; + bi->dumpreg = mt6635_dump_reg; + bi->msget = mt6635_GetMonoStereo; + bi->msset = mt6635_SetMonoStereo; + bi->pamdget = mt6635_GetCurPamd; + bi->em = mt6635_em_test; + bi->anaswitch = mt6635_SetAntennaType; + bi->anaget = mt6635_GetAntennaType; + bi->caparray_get = mt6635_GetCapArray; + bi->hwinfo_get = mt6635_hw_info_get; + bi->i2s_get = mt6635_i2s_info_get; + bi->is_dese_chan = mt6635_is_dese_chan; + bi->softmute_tune = mt6635_soft_mute_tune; + bi->desense_check = mt6635_desense_check; + bi->cqi_log = mt6635_full_cqi_get; + bi->pre_search = mt6635_pre_search; + bi->restore_search = mt6635_restore_search; + bi->set_search_th = mt6635_set_search_th; + bi->is_valid_freq = mt6635_is_valid_freq; + + cmd_buf_lock = fm_lock_create("31_cmd"); + ret = fm_lock_get(cmd_buf_lock); + + cmd_buf = fm_zalloc(TX_BUF_SIZE + 1); + + if (!cmd_buf) { + WCN_DBG(FM_ALT | CHIP, "6635 fm lib alloc tx buf failed\n"); + ret = -1; + } +#if 0 /* def CONFIG_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, "6635 fm lib create cqi fifo failed\n"); + ret = -1; + } +#endif + + return ret; +} + +signed int mt6635_fm_low_ops_unregister(struct fm_basic_interface *bi) +{ + signed int ret = 0; + /* Basic functions. */ + if (bi == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,bi invalid pointer\n", __func__); + return -FM_EPARA; + } + +#if 0 /* def CONFIG_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(bi, 0, sizeof(struct fm_basic_interface)); + + fm_cb_op = NULL; + + return ret; +} + +static const signed char mt6635_chan_para_map[] = { +/* 0, X, 1, X, 2, X, 3, X, 4, X, 5, X, 6, X, 7, X, 8, X, 9, X */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, /* 6500~6595 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6600~6695 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, /* 6700~6795 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6800~6895 */ + 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6900~6995 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7000~7095 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7100~7195 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, /* 7200~7295 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7300~7395 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 7400~7495 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7500~7595 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 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 */ + 8, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7800~7895 */ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7900~7995 */ + 0, 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, 2, 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, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, /* 8300~8395 */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 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, 2, 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, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9400~9495 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9500~9595 */ + 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, /* 9800~9895 */ + 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 9900~9995 */ + 0, 0, 0, 0, 0, 0, 0, 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, 0, 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 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 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 unsigned short mt6635_scan_dese_list[] = { + 6910, 6920, 7680, 7800, 8450, 9210, 9220, 9230, 9590, 9600, 9830, 9900, 9980, 9990, 10400, 10750, 10760 +}; + +static const unsigned short mt6635_SPI_hopping_list[] = { + 6510, 6520, 6530, 7780, 7790, 7800, 7810, 7820, 9090, 9100, 9110, 9120, 10380, 10390, 10400, 10410, 10420 +}; + +static const unsigned short mt6635_I2S_hopping_list[] = { + 6550, 6760, 6960, 6970, 7170, 7370, 7580, 7780, 7990, 8810, 9210, 9220, 10240 +}; + +static const unsigned short mt6635_TDD_list[] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6500~6595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6600~6695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6700~6795 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6800~6895 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6900~6995 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7000~7095 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7100~7195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7200~7295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7300~7395 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7400~7495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7500~7595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7600~7695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7700~7795 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7800~7895 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7900~7995 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8000~8095 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8100~8195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8200~8295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8300~8395 */ + 0x0101, 0x0000, 0x0000, 0x0000, 0x0000, /* 8400~8495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8500~8595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8600~8695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8700~8795 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8800~8895 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8900~8995 */ + 0x0000, 0x0000, 0x0101, 0x0101, 0x0101, /* 9000~9095 */ + 0x0101, 0x0000, 0x0000, 0x0000, 0x0000, /* 9100~9195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9200~9295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9300~9395 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9400~9495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9500~9595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9600~9695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0100, /* 9700~9795 */ + 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, /* 9800~9895 */ + 0x0101, 0x0101, 0x0001, 0x0000, 0x0000, /* 9900~9995 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10000~10095 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10100~10195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10200~10295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10300~10395 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10400~10495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10500~10595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0100, /* 10600~10695 */ + 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, /* 10700~10795 */ + 0x0001 /* 10800 */ +}; + +static const unsigned short mt6635_TDD_Mask[] = { + 0x0001, 0x0010, 0x0100, 0x1000 +}; + +/* return value: 0, not a de-sense channel; 1, this is a de-sense channel; else error no */ +static signed int mt6635_is_dese_chan(unsigned short freq) +{ + signed int size; + + if (1 == HQA_ZERO_DESENSE_MAP) /*HQA only :skip desense channel check. */ + return 0; + + size = ARRAY_SIZE(mt6635_scan_dese_list); + + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + while (size) { + if (mt6635_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 signed int mt6635_desense_check(unsigned short freq, signed int rssi) +{ + if (mt6635_is_dese_chan(freq)) { + if (rssi < fm_config.rx_cfg.desene_rssi_th) + return 1; + + WCN_DBG(FM_DBG | CHIP, "desen_rssi %d th:%d\n", rssi, fm_config.rx_cfg.desene_rssi_th); + } + return 0; +} + +static bool mt6635_TDD_chan_check(unsigned short freq) +{ + unsigned int i = 0; + unsigned short freq_tmp = freq; + signed int ret = 0; + + ret = fm_get_channel_space(freq_tmp); + if (ret == 0) + freq_tmp *= 10; + else if (ret == -1) + return false; + + i = (freq_tmp - 6500) / 5; + if ((i / 4) >= ARRAY_SIZE(mt6635_TDD_list)) { + WCN_DBG(FM_ERR | CHIP, "Freq index out of range(%d),max(%zd)\n", + i / 4, ARRAY_SIZE(mt6635_TDD_list)); + return false; + } + + if (mt6635_TDD_list[i / 4] & mt6635_TDD_Mask[i % 4]) { + WCN_DBG(FM_DBG | CHIP, "Freq %d use TDD solution\n", freq); + return true; + } else + return false; +} + +/* get channel parameter, HL side/ FA / ATJ */ +static unsigned short mt6635_chan_para_get(unsigned short freq) +{ + signed int pos, size; + + if (1 == HQA_RETURN_ZERO_MAP) { + WCN_DBG(FM_NTC | CHIP, "HQA_RETURN_ZERO_CHAN mt6635_chan_para_map enabled!\n"); + return 0; + } + + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + if (freq < 6500) + return 0; + + pos = (freq - 6500) / 5; + + size = ARRAY_SIZE(mt6635_chan_para_map); + + pos = (pos > (size - 1)) ? (size - 1) : pos; + + return mt6635_chan_para_map[pos]; +} + + +static bool mt6635_SPI_hopping_check(unsigned short freq) +{ + signed int size; + + size = ARRAY_SIZE(mt6635_SPI_hopping_list); + + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + while (size) { + if (mt6635_SPI_hopping_list[size - 1] == freq) + return 1; + size--; + } + + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/mt6635/pub/mt6635_fm_rds.c b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6635/pub/mt6635_fm_rds.c new file mode 100644 index 0000000000000..5098adacb3246 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/mt6635/pub/mt6635_fm_rds.c @@ -0,0 +1,335 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ +#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 "mt6635_fm_reg.h" +#include "fm_cmd.h" + +static bool bRDS_FirstIn; /* false */ +static unsigned int gBLER_CHK_INTERVAL = 500; +static unsigned short GOOD_BLK_CNT = 0, BAD_BLK_CNT; +static unsigned char BAD_BLK_RATIO; + +static struct fm_basic_interface *fm_bi; + +static bool mt6635_RDS_support(void); +static signed int mt6635_RDS_enable(void); +static signed int mt6635_RDS_disable(void); +static unsigned short mt6635_RDS_Get_GoodBlock_Counter(void); +static unsigned short mt6635_RDS_Get_BadBlock_Counter(void); +static unsigned char mt6635_RDS_Get_BadBlock_Ratio(void); +static unsigned int mt6635_RDS_Get_BlerCheck_Interval(void); +/* static void mt6635_RDS_GetData(unsigned short *data, unsigned short datalen); */ +static void mt6635_RDS_Init_Data(struct rds_t *pstRDSData); + +static bool mt6635_RDS_support(void) +{ + return true; +} + +static signed int mt6635_RDS_enable(void) +{ + signed int ret = 0; + unsigned short dataRead = 0; + + WCN_DBG(FM_DBG | RDSC, "rds enable\n"); + ret = fm_reg_read(FM_RDS_CFG0, &dataRead); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds enable read 0x80 fail\n"); + return ret; + } + ret = fm_reg_write(FM_RDS_CFG0, 6); /* set buf_start_th */ + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds enable write 0x80 fail\n"); + return ret; + } + ret = fm_reg_read(FM_MAIN_CTRL, &dataRead); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds enable read 0x63 fail\n"); + return ret; + } + ret = fm_reg_write(FM_MAIN_CTRL, dataRead | (RDS_MASK)); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds enable write 0x63 fail\n"); + return ret; + } + + return ret; +} + +static signed int mt6635_RDS_disable(void) +{ + signed int ret = 0; + unsigned short dataRead = 0; + + WCN_DBG(FM_DBG | RDSC, "rds disable\n"); + ret = fm_reg_read(FM_MAIN_CTRL, &dataRead); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds disable read 0x63 fail\n"); + return ret; + } + ret = fm_reg_write(FM_MAIN_CTRL, dataRead & (~RDS_MASK)); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds disable write 0x63 fail\n"); + return ret; + } + + return ret; +} + +static unsigned short mt6635_RDS_Get_GoodBlock_Counter(void) +{ + unsigned short tmp_reg = 0; + + fm_reg_read(FM_RDS_GOODBK_CNT, &tmp_reg); + GOOD_BLK_CNT = tmp_reg; + WCN_DBG(FM_DBG | RDSC, "get good block cnt:%d\n", (signed int) tmp_reg); + + return tmp_reg; +} + +static unsigned short mt6635_RDS_Get_BadBlock_Counter(void) +{ + unsigned short tmp_reg = 0; + + fm_reg_read(FM_RDS_BADBK_CNT, &tmp_reg); + BAD_BLK_CNT = tmp_reg; + WCN_DBG(FM_DBG | RDSC, "get bad block cnt:%d\n", (signed int) tmp_reg); + + return tmp_reg; +} + +static unsigned char mt6635_RDS_Get_BadBlock_Ratio(void) +{ + unsigned short tmp_reg; + unsigned short gbc; + unsigned short bbc; + + gbc = mt6635_RDS_Get_GoodBlock_Counter(); + bbc = mt6635_RDS_Get_BadBlock_Counter(); + + if ((gbc + bbc) > 0) + tmp_reg = (unsigned char) (bbc * 100 / (gbc + bbc)); + else + tmp_reg = 0; + + BAD_BLK_RATIO = tmp_reg; + WCN_DBG(FM_DBG | RDSC, "get badblock ratio:%d\n", (signed int) tmp_reg); + + return tmp_reg; +} + +static signed int mt6635_RDS_BlockCounter_Reset(void) +{ + mt6635_RDS_disable(); + mt6635_RDS_enable(); + + return 0; +} + +static unsigned int mt6635_RDS_Get_BlerCheck_Interval(void) +{ + return gBLER_CHK_INTERVAL; +} + +static signed int mt6635_RDS_BlerCheck(struct rds_t *dst) +{ + return 0; +} + +#if 0 +static void RDS_Recovery_Handler(void) +{ + unsigned short tempData = 0; + + do { + fm_reg_read(FM_RDS_DATA_REG, &tempData); + fm_reg_read(FM_RDS_POINTER, &tempData); + } while (tempData & 0x3); +} +#endif + +#if 0 +static void mt6635_RDS_GetData(unsigned short *data, unsigned short 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 + + unsigned short CRC = 0, i = 0, RDS_adj = 0, RDSDataCount = 0, FM_WARorrCnt = 0; + unsigned short temp = 0, OutputPofm_s32 = 0; + + WCN_DBG(FM_DBG | RDSC, "get data\n"); + fm_reg_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_reg_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_reg_read(FM_RDS_DATA_REG, &data[0]); + + /* block B data and info handling */ + fm_reg_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_reg_read(FM_RDS_DATA_REG, &data[1]); + + /* block C data and info handling */ + fm_reg_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_reg_read(FM_RDS_DATA_REG, &data[2]); + + /* block D data and info handling */ + fm_reg_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_reg_read(FM_RDS_DATA_REG, &data[3]); + + data[4] = (CRC | RDS_adj | RDSDataCount); + data[5] = FM_WARorrCnt; + + fm_reg_read(FM_RDS_PWDI, &data[6]); + fm_reg_read(FM_RDS_PWDQ, &data[7]); + + fm_reg_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 mt6635_RDS_Init_Data(struct rds_t *pstRDSData) +{ + fm_memset(pstRDSData, 0, sizeof(struct rds_t)); + bRDS_FirstIn = true; + + pstRDSData->event_status = 0x0000; + 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)); +} + +bool mt6635_RDS_OnOff(struct rds_t *dst, bool bFlag) +{ + signed int ret = 0; + + if (mt6635_RDS_support() == false) { + WCN_DBG(FM_ALT | RDSC, "mt6635_RDS_OnOff failed, RDS not support\n"); + return false; + } + + if (bFlag) { + mt6635_RDS_Init_Data(dst); + ret = mt6635_RDS_enable(); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "mt6635_RDS_OnOff enable failed\n"); + return false; + } + } else { + mt6635_RDS_Init_Data(dst); + ret = mt6635_RDS_disable(); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "mt6635_RDS_OnOff disable failed\n"); + return false; + } + } + + return true; +} + +DEFINE_RDSLOG(mt6635_rds_log); + +/* mt6635_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 signed int mt6635_rds_parser(struct rds_t *rds_dst, struct rds_rx_t *rds_raw, + signed int rds_size, unsigned short(*getfreq) (void)) +{ + mt6635_rds_log.log_in(&mt6635_rds_log, rds_raw, rds_size); + return rds_parser(rds_dst, rds_raw, rds_size, getfreq); +} + +static signed int mt6635_rds_log_get(struct rds_rx_t *dst, signed int *dst_len) +{ + return mt6635_rds_log.log_out(&mt6635_rds_log, dst, dst_len); +} + +static signed int mt6635_rds_gc_get(struct rds_group_cnt_t *dst, struct rds_t *rdsp) +{ + return rds_grp_counter_get(dst, &rdsp->gc); +} + +static signed int mt6635_rds_gc_reset(struct rds_t *rdsp) +{ + return rds_grp_counter_reset(&rdsp->gc); +} + +signed int mt6635_fm_rds_ops_register(struct fm_basic_interface *bi, struct fm_rds_interface *ri) +{ + signed int ret = 0; + + if (ri == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,ri invalid pointer\n", __func__); + return -FM_EPARA; + } + + fm_bi = bi; + + ri->rds_blercheck = mt6635_RDS_BlerCheck; + ri->rds_onoff = mt6635_RDS_OnOff; + ri->rds_parser = mt6635_rds_parser; + ri->rds_gbc_get = mt6635_RDS_Get_GoodBlock_Counter; + ri->rds_bbc_get = mt6635_RDS_Get_BadBlock_Counter; + ri->rds_bbr_get = mt6635_RDS_Get_BadBlock_Ratio; + ri->rds_bc_reset = mt6635_RDS_BlockCounter_Reset; + ri->rds_bci_get = mt6635_RDS_Get_BlerCheck_Interval; + ri->rds_log_get = mt6635_rds_log_get; + ri->rds_gc_get = mt6635_rds_gc_get; + ri->rds_gc_reset = mt6635_rds_gc_reset; + + return ret; +} + +signed int mt6635_fm_rds_ops_unregister(struct fm_rds_interface *ri) +{ + signed int ret = 0; + + if (ri == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,ri invalid pointer\n", __func__); + return -FM_EPARA; + } + + fm_bi = NULL; + fm_memset(ri, 0, sizeof(struct fm_rds_interface)); + return ret; +} diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/soc/inc/soc_drv_dsp.h b/drivers/misc/mediatek/connectivity/fmradio/chips/soc/inc/soc_drv_dsp.h new file mode 100644 index 0000000000000..957a869719bc3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/soc/inc/soc_drv_dsp.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +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 +}; diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/soc/inc/soc_fm_lib.h b/drivers/misc/mediatek/connectivity/fmradio/chips/soc/inc/soc_fm_lib.h new file mode 100644 index 0000000000000..7e2f049f7010b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/soc/inc/soc_fm_lib.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __MT6580_FM_LIB_H__ +#define __MT6580_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 { + mt6580_E1 = 0, + mt6580_E2 +}; + +struct mt6580_fm_cqi { + unsigned short ch; + unsigned short rssi; + unsigned short reserve; +}; + +struct adapt_fm_cqi { + signed int ch; + signed int rssi; + signed int reserve; +}; + +struct mt6580_full_cqi { + unsigned short ch; + unsigned short rssi; + unsigned short pamd; + unsigned short pr; + unsigned short fpamd; + unsigned short mr; + unsigned short atdc; + unsigned short prx; + unsigned short atdev; + unsigned short smg; /* soft-mute gain */ + unsigned short drssi; /* delta rssi */ +}; + +#endif diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/soc/inc/soc_fm_reg.h b/drivers/misc/mediatek/connectivity/fmradio/chips/soc/inc/soc_fm_reg.h new file mode 100644 index 0000000000000..5a52de1464978 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/soc/inc/soc_fm_reg.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __MT6580_FM_REG_H__ +#define __MT6580_FM_REG_H__ + +enum MT6580_HOSTREG { + MCUPLL_CON1 = 0x80000224, + CONN_RF_CG = 0x80102090 +}; + +/* 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, +}; + +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 /* __MT6580_FM_REG_H__ */ diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/soc/pub/soc_fm_lib.c b/drivers/misc/mediatek/connectivity/fmradio/chips/soc/pub/soc_fm_lib.c new file mode 100644 index 0000000000000..c33263efbae6b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/soc/pub/soc_fm_lib.c @@ -0,0 +1,1841 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#include "osal_typedef.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_cmd.h" + +#include "soc_fm_reg.h" +#include "soc_fm_lib.h" + +/* #include "mach/mt_gpio.h" */ + +static struct fm_patch_tbl mt6580_patch_tbl[5] = { + {FM_ROM_V1, "soc_fm_v1_patch.bin", "soc_fm_v1_coeff.bin", NULL, NULL}, + {FM_ROM_V2, "soc_fm_v2_patch.bin", "soc_fm_v2_coeff.bin", NULL, NULL}, + {FM_ROM_V3, "soc_fm_v3_patch.bin", "soc_fm_v3_coeff.bin", NULL, NULL}, + {FM_ROM_V4, "soc_fm_v4_patch.bin", "soc_fm_v4_coeff.bin", NULL, NULL}, + {FM_ROM_V5, "soc_fm_v5_patch.bin", "soc_fm_v5_coeff.bin", NULL, NULL} +}; + +static struct fm_hw_info mt6580_hw_info = { + .chip_id = 0x00006580, + .eco_ver = 0x00000000, + .rom_ver = 0x00000000, + .patch_ver = 0x00000000, + .reserve = 0x00000000, +}; + +static struct fm_callback *fm_cb_op; +/* static signed int Chip_Version = mt6580_E1; */ + +/* static bool rssi_th_set = false; */ + +#if 0 /* def CONFIG_MTK_FM_50KHZ_SUPPORT */ +static struct fm_fifo *cqi_fifo; +#endif +static signed int mt6580_is_dese_chan(unsigned short freq); + +#if 0 +static signed int mt6580_mcu_dese(unsigned short freq, void *arg); +static signed int mt6580_gps_dese(unsigned short freq, void *arg); +static signed int mt6580_I2s_Setting(signed int onoff, signed int mode, signed int sample); +#endif +static unsigned short mt6580_chan_para_get(unsigned short freq); +static signed int mt6580_desense_check(unsigned short freq, signed int rssi); +/*static bool mt6580_TDD_chan_check(unsigned short freq);*/ +static signed int mt6580_soft_mute_tune(unsigned short freq, signed int *rssi, signed int *valid); +static signed int mt6580_pwron(signed int data) +{ + if (mtk_wcn_wmt_func_on(WMTDRV_TYPE_FM) == MTK_WCN_BOOL_FALSE) { + WCN_DBG(FM_ERR | CHIP, "WMT turn on FM Fail!\n"); + return -FM_ELINK; + } + + WCN_DBG(FM_NTC | CHIP, "WMT turn on FM OK!\n"); + return 0; +} + +static signed int mt6580_pwroff(signed int data) +{ + if (mtk_wcn_wmt_func_off(WMTDRV_TYPE_FM) == MTK_WCN_BOOL_FALSE) { + WCN_DBG(FM_ERR | CHIP, "WMT turn off FM Fail!\n"); + return -FM_ELINK; + } + + WCN_DBG(FM_NTC | CHIP, "WMT turn off FM OK!\n"); + return 0; +} + +#if 0 +static signed int mt6580_top_set_bits(unsigned short addr, unsigned int bits, unsigned int mask) +{ + signed int ret = 0; + unsigned int val; + + ret = fm_top_reg_read(addr, &val); + + if (ret) + return ret; + + val = ((val & (mask)) | bits); + ret = fm_top_reg_write(addr, val); + + return ret; +} +#endif + +#if 0 +static signed int mt6580_DSP_write(unsigned short addr, unsigned short val) +{ + fm_reg_write(0xE2, addr); + fm_reg_write(0xE3, val); + fm_reg_write(0xE1, 0x0002); + return 0; +} +static signed int mt6580_DSP_read(unsigned short addr, unsigned short *val) +{ + signed int ret = -1; + + fm_reg_write(0xE2, addr); + fm_reg_write(0xE1, 0x0001); + ret = fm_reg_read(0xE4, val); + return ret; +} +#endif + +static unsigned short mt6580_get_chipid(void) +{ + return 0x6580; +} + +/* MT6580_SetAntennaType - set Antenna type + * @type - 1,Short Antenna; 0, Long Antenna + */ +static signed int mt6580_SetAntennaType(signed int type) +{ + unsigned short dataRead = 0; + + WCN_DBG(FM_DBG | CHIP, "set ana to %s\n", type ? "short" : "long"); + fm_reg_read(FM_MAIN_CG2_CTRL, &dataRead); + + if (type) + dataRead |= ANTENNA_TYPE; + else + dataRead &= (~ANTENNA_TYPE); + + fm_reg_write(FM_MAIN_CG2_CTRL, dataRead); + + return 0; +} + +static signed int mt6580_GetAntennaType(void) +{ + unsigned short dataRead = 0; + + fm_reg_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 signed int mt6580_Mute(bool mute) +{ + signed int ret = 0; + unsigned short dataRead = 0; + + WCN_DBG(FM_DBG | CHIP, "set %s\n", mute ? "mute" : "unmute"); + /* fm_reg_read(FM_MAIN_CTRL, &dataRead); */ + fm_reg_read(0x9C, &dataRead); + + /* fm_top_reg_write(0x0050,0x00000007); */ + + if (mute == 1) + ret = fm_reg_write(0x9C, (dataRead & 0xFFFC) | 0x0003); + else + ret = fm_reg_write(0x9C, (dataRead & 0xFFFC)); + + /* fm_top_reg_write(0x0050,0x0000000F); */ + + return ret; +} + +#if 0 +static signed int mt6580_set_RSSITh(unsigned short TH_long, unsigned short TH_short) +{ + fm_reg_write(0xE2, 0x3072); + fm_reg_write(0xE3, TH_long); + fm_reg_write(0xE1, 0x0002); + fm_delayms(1); + fm_reg_write(0xE2, 0x307A); + fm_reg_write(0xE3, TH_short); + fm_reg_write(0xE1, 0x0002); + + WCN_DBG(FM_DBG | CHIP, "RSSI TH, long:0x%04x, short:0x%04x", TH_long, TH_short); + return 0; +} + +static signed int mt6580_set_SMGTh(signed int ver, unsigned short TH_smg) +{ + if (mt6580_E1 == ver) { + fm_reg_write(0xE2, 0x321E); + fm_reg_write(0xE3, TH_smg); + fm_reg_write(0xE1, 0x0002); + } else { + fm_reg_write(0xE2, 0x3218); + fm_reg_write(0xE3, TH_smg); + fm_reg_write(0xE1, 0x0002); + } + + WCN_DBG(FM_DBG | CHIP, "Soft-mute gain TH %d\n", (int)TH_smg); + return 0; +} +#endif + +static signed int mt6580_rampdown_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* Clear DSP state */ + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFF0, 0x0000, &buf[pkt_size], buf_size - pkt_size); + /* Set DSP ramp down state */ + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFFF, RAMP_DOWN, &buf[pkt_size], buf_size - pkt_size); + /* @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); + /* Clear DSP ramp down state */ + pkt_size += fm_bop_modify(FM_MAIN_CTRL, (~RAMP_DOWN), 0x0000, &buf[pkt_size], buf_size - pkt_size); + /* 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); + + return pkt_size - 4; +} +/* + * mt6580_rampdown - f/w will wait for STC_DONE interrupt + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6580_rampdown(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6580_rampdown_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_RAMPDOWN_OPCODE, pkt_size); +} + +static signed int mt6580_RampDown(void) +{ + signed int ret = 0; + unsigned short pkt_size; + + WCN_DBG(FM_DBG | CHIP, "ramp down\n"); + ret = fm_reg_write(0x60, 0x00000007); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down wr 0x60 failed\n"); + return ret; + } + ret = fm_reg_write(0x60, 0x0000000f); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "ramp down wr 0x60 failed\n"); + return ret; + } + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6580_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; + } + + return ret; +} + +static signed int mt6580_get_rom_version(void) +{ + unsigned short tmp; + signed int ret; + + fm_reg_write(0x90, 0xe); + fm_reg_write(0x92, 0x0); + fm_reg_write(0x90, 0x40); + fm_reg_write(0x90, 0x0); + + /* DSP rom code version request enable --- set 0x61 b15=1 */ + fm_set_bits(0x61, 0x8000, 0x7FFF); + + /* Release ASIP reset --- set 0x61 b1=1 */ + fm_set_bits(0x61, 0x0002, 0xFFFD); + + /* Enable ASIP power --- set 0x61 b0=0 */ + fm_set_bits(0x61, 0x0000, 0xFFFE); + + /* Wait DSP code version ready --- wait 1ms */ + do { + fm_delayus(1000); + ret = fm_reg_read(0x84, &tmp); + /* ret=-4 means signal got when control FM. usually get sig 9 to kill FM process. */ + /* now cancel FM power up sequence is recommended. */ + if (ret) + return ret; + + WCN_DBG(FM_NTC | CHIP, "0x84=%x\n", tmp); + } while (tmp != 0x0001); + + /* Get FM DSP code version --- rd 0x83[15:8] */ + fm_reg_read(0x83, &tmp); + tmp = (tmp >> 8); + + /* DSP rom code version request disable --- set 0x61 b15=0 */ + fm_set_bits(0x61, 0x0000, 0x7FFF); + + /* Reset ASIP --- set 0x61[1:0] = 1 */ + fm_set_bits(0x61, 0x0001, 0xFFFC); + + /* WCN_DBG(FM_NTC | CHIP, "ROM version: v%d\n", (signed int)tmp); */ + return (signed int) tmp; +} + +static signed int mt6580_enable_pmic_tldo(void) +{ + signed int ret = 0; + unsigned int hostreg = 0; + + /* set 26M clock mannual on */ + ret = fm_host_reg_read(MCUPLL_CON1, &hostreg); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup rd MCUPLL_CON1 failed\n"); + return ret; + } + ret = fm_host_reg_write(MCUPLL_CON1, hostreg | (0x1 << 0)); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup wr MCUPLL_CON1 failed\n"); + return ret; + } + + ret = fm_host_reg_read(MCUPLL_CON1, &hostreg); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup rd MCUPLL_CON1 failed\n"); + return ret; + } + ret = fm_host_reg_write(MCUPLL_CON1, hostreg | (0x1 << 6)); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup wr MCUPLL_CON1 failed\n"); + return ret; + } + + ret = fm_host_reg_read(MCUPLL_CON1, &hostreg); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup rd MCUPLL_CON1 failed\n"); + return ret; + } + ret = fm_host_reg_write(MCUPLL_CON1, hostreg | (0x1 << 16)); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup wr MCUPLL_CON1 failed\n"); + return ret; + } + + ret = fm_host_reg_read(MCUPLL_CON1, &hostreg); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup rd MCUPLL_CON1 failed\n"); + return ret; + } + ret = fm_host_reg_write(MCUPLL_CON1, hostreg | (0x1 << 22)); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup wr MCUPLL_CON1 failed\n"); + return ret; + } + + /* set RX_DET_OUT Gating off */ + ret = fm_host_reg_read(CONN_RF_CG, &hostreg); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup rd CONN_RF_CG failed\n"); + return ret; + } + ret = fm_host_reg_write(CONN_RF_CG, hostreg | (0x1 << 16)); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup wr CONN_RF_CG failed\n"); + return ret; + } + + /* set ADC_QD Gating off */ + ret = fm_host_reg_read(CONN_RF_CG, &hostreg); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup rd CONN_RF_CG failed\n"); + return ret; + } + ret = fm_host_reg_write(CONN_RF_CG, hostreg | (0x1 << 15)); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup wr CONN_RF_CG failed\n"); + return ret; + } + + /* set ADC_ID Gating off */ + ret = fm_host_reg_read(CONN_RF_CG, &hostreg); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup rd CONN_RF_CG failed\n"); + return ret; + } + ret = fm_host_reg_write(CONN_RF_CG, hostreg | (0x1 << 14)); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup wr CONN_RF_CG failed\n"); + return ret; + } + + /* set ADC_CK Gating off */ + ret = fm_host_reg_read(CONN_RF_CG, &hostreg); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup rd CONN_RF_CG failed\n"); + return ret; + } + ret = fm_host_reg_write(CONN_RF_CG, hostreg | (0x1 << 7)); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup wr CONN_RF_CG failed\n"); + return ret; + } + + /* set DIG_CK Gating off */ + ret = fm_host_reg_read(CONN_RF_CG, &hostreg); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup rd CONN_RF_CG failed\n"); + return ret; + } + ret = fm_host_reg_write(CONN_RF_CG, hostreg | (0x1 << 6)); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup wr CONN_RF_CG failed\n"); + return ret; + } + + return ret; +} + +static signed int mt6580_disable_pmic_tldo(void) +{ + signed int ret = 0; + unsigned int hostreg = 0; + + /* set 26M clock mannual on */ + ret = fm_host_reg_read(MCUPLL_CON1, &hostreg); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup rd MCUPLL_CON1 failed\n"); + return ret; + } + ret = fm_host_reg_write(MCUPLL_CON1, hostreg & (~(0x1 << 22))); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup wr MCUPLL_CON1 failed\n"); + return ret; + } + + ret = fm_host_reg_read(MCUPLL_CON1, &hostreg); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup rd MCUPLL_CON1 failed\n"); + return ret; + } + ret = fm_host_reg_write(MCUPLL_CON1, hostreg & (~(0x1 << 16))); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup wr MCUPLL_CON1 failed\n"); + return ret; + } + + ret = fm_host_reg_read(MCUPLL_CON1, &hostreg); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup rd MCUPLL_CON1 failed\n"); + return ret; + } + ret = fm_host_reg_write(MCUPLL_CON1, hostreg & (~(0x1 << 6))); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup wr MCUPLL_CON1 failed\n"); + return ret; + } + + ret = fm_host_reg_read(MCUPLL_CON1, &hostreg); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup rd MCUPLL_CON1 failed\n"); + return ret; + } + ret = fm_host_reg_write(MCUPLL_CON1, hostreg & (~(0x1 << 0))); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup wr MCUPLL_CON1 failed\n"); + return ret; + } + + /* set RX_DET_OUT Gating off */ + ret = fm_host_reg_read(CONN_RF_CG, &hostreg); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup rd CONN_RF_CG failed\n"); + return ret; + } + ret = fm_host_reg_write(CONN_RF_CG, hostreg & (~(0x1 << 16))); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup wr CONN_RF_CG failed\n"); + return ret; + } + + /* set ADC_QD Gating off */ + ret = fm_host_reg_read(CONN_RF_CG, &hostreg); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup rd CONN_RF_CG failed\n"); + return ret; + } + ret = fm_host_reg_write(CONN_RF_CG, hostreg & (~(0x1 << 15))); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup wr CONN_RF_CG failed\n"); + return ret; + } + + /* set ADC_ID Gating off */ + ret = fm_host_reg_read(CONN_RF_CG, &hostreg); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup rd CONN_RF_CG failed\n"); + return ret; + } + ret = fm_host_reg_write(CONN_RF_CG, hostreg & (~(0x1 << 14))); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup wr CONN_RF_CG failed\n"); + return ret; + } + + /* set ADC_CK Gating off */ + ret = fm_host_reg_read(CONN_RF_CG, &hostreg); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup rd CONN_RF_CG failed\n"); + return ret; + } + ret = fm_host_reg_write(CONN_RF_CG, hostreg & (~(0x1 << 7))); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup wr CONN_RF_CG failed\n"); + return ret; + } + + /* set DIG_CK Gating off */ + ret = fm_host_reg_read(CONN_RF_CG, &hostreg); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup rd CONN_RF_CG failed\n"); + return ret; + } + ret = fm_host_reg_write(CONN_RF_CG, hostreg & (~(0x1 << 6))); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " pwrup wr CONN_RF_CG failed\n"); + return ret; + } + + return ret; +} + +static signed int mt6580_pwrup_clock_on_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + unsigned short de_emphasis; + /* unsigned short osc_freq; */ + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + de_emphasis = fm_config.rx_cfg.deemphasis; /* fm_cust_config_fetch(FM_CFG_RX_DEEMPHASIS); */ + de_emphasis &= 0x0001; /* rang 0~1 */ + + /* turn on top clock */ + pkt_size += fm_bop_top_write(0xA10, 0xFFFFFFFF, &buf[pkt_size], buf_size - pkt_size); /* wr a10 ffffffff */ + /* enable MTCMOS */ + pkt_size += fm_bop_top_write(0x60, 0x00000030, &buf[pkt_size], buf_size - pkt_size); /* wr 60 30 */ + pkt_size += fm_bop_top_write(0x60, 0x00000005, &buf[pkt_size], buf_size - pkt_size); /* wr 60 5 */ + pkt_size += fm_bop_udelay(10, &buf[pkt_size], buf_size - pkt_size); /* delay 10us */ + pkt_size += fm_bop_top_write(0x60, 0x00000045, &buf[pkt_size], buf_size - pkt_size); /* wr 60 45 */ + + /* enable digital OSC */ + pkt_size += fm_bop_write(0x60, 0x00000001, &buf[pkt_size], buf_size - pkt_size); /* wr 60 1 */ + /* set OSC clock output to fm */ + pkt_size += fm_bop_write(0x60, 0x00000003, &buf[pkt_size], buf_size - pkt_size); /* wr 60 3 */ + /* release HW clock gating */ + pkt_size += fm_bop_write(0x60, 0x00000007, &buf[pkt_size], buf_size - pkt_size); /* wr 60 7 */ + /* enable DSP auto clock gating */ + pkt_size += fm_bop_write(0x70, 0x0040, &buf[pkt_size], buf_size - pkt_size); /* wr 70 0040 */ + /* deemphasis setting */ + pkt_size += fm_bop_modify(0x61, ~DE_EMPHASIS, (de_emphasis << 12), &buf[pkt_size], buf_size - pkt_size); + + return pkt_size - 4; +} +/* + * mt6580_pwrup_clock_on - Wholechip FM Power Up: step 1, FM Digital Clock enable + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6580_pwrup_clock_on(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6580_pwrup_clock_on_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +static signed int mt6580_pwrup_digital_init_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* FM Digital Init: fm_rgf_maincon */ + pkt_size += fm_bop_write(0x6A, 0x0021, &buf[pkt_size], buf_size - pkt_size); + /* wr 6A 0021, set 1 to enable interrupt */ + pkt_size += fm_bop_write(0x6B, 0x0021, &buf[pkt_size], buf_size - pkt_size); /* wr 6B 0021 */ + pkt_size += fm_bop_write(0x60, 0x0000000F, &buf[pkt_size], buf_size - pkt_size); /* wr 60 f */ + 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(100000, &buf[pkt_size], buf_size - pkt_size); /* delay 100ms */ + pkt_size += fm_bop_rd_until(0x64, 0x001F, 0x0002, &buf[pkt_size], buf_size - pkt_size); /* Poll 64[0~4] = 2 */ + pkt_size += fm_bop_write(0x60, 0x00000007, &buf[pkt_size], buf_size - pkt_size); /* wr 60 7 */ + pkt_size += fm_bop_write(0x2d, 0x000001fa, &buf[pkt_size], buf_size - pkt_size); /* wr 2d 1fa */ + pkt_size += fm_bop_write(0x60, 0x0000000F, &buf[pkt_size], buf_size - pkt_size); /* wr 60 f */ + + return pkt_size - 4; +} + +/* + * mt6580_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 + */ +static signed int mt6580_pwrup_digital_init(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6580_pwrup_digital_init_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +static signed int mt6580_pwrdown_reg_op(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 4; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* A1:set audio output I2S Tx mode: */ + pkt_size += fm_bop_modify(0x9B, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size); /* wr 9B[0~2] 0 */ + + /* B0:Disable HW clock control */ + pkt_size += fm_bop_write(0x60, 0x330F, &buf[pkt_size], buf_size - pkt_size); /* wr 60 330F */ + /* B1:Reset ASIP */ + pkt_size += fm_bop_write(0x61, 0x0001, &buf[pkt_size], buf_size - pkt_size); /* wr 61 0001 */ + /* B2: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 */ + /* B3:Disable all clock */ + pkt_size += fm_bop_write(0x60, 0x0000, &buf[pkt_size], buf_size - pkt_size); /* wr 60 0000 */ + /* B4: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 */ + /* MTCMOS power off */ + /* C0:disable MTCMOS */ + pkt_size += fm_bop_top_write(0x60, 0x0005, &buf[pkt_size], buf_size - pkt_size); /* wr top60 0005 */ + pkt_size += fm_bop_top_write(0x60, 0x0015, &buf[pkt_size], buf_size - pkt_size); /* wr top60 0015 */ + + return pkt_size - 4; +} +/* + * mt6580_pwrdown - Wholechip FM Power down: Digital Modem Power Down + * @buf - target buf + * @buf_size - buffer size + * return package size + */ +static signed int mt6580_pwrdown(unsigned char *buf, signed int buf_size) +{ + signed int pkt_size = 0; + + pkt_size = mt6580_pwrdown_reg_op(buf, buf_size); + return fm_op_seq_combine_cmd(buf, FM_ENABLE_OPCODE, pkt_size); +} + +static signed int mt6580_tune_reg_op(unsigned char *buf, signed int buf_size, unsigned short freq, + unsigned short chan_para) +{ + signed int pkt_size = 4; + + WCN_DBG(FM_ALT | CHIP, "%s enter mt6580_tune function\n", __func__); + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s invalid pointer\n", __func__); + return -1; + } + if (buf_size < TX_BUF_SIZE) { + WCN_DBG(FM_ERR | CHIP, "%s invalid buf size(%d)\n", __func__, buf_size); + return -2; + } + + /* 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 + /* Enable hardware controlled tuning sequence */ + pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFF8, TUNE, &buf[pkt_size], buf_size - pkt_size); + /* 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); + /* 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); +#endif + + WCN_DBG(FM_ALT | CHIP, "%s leave mt6580_tune function\n", __func__); + + return pkt_size - 4; +} + +/* + * mt6580_tune - execute tune action, + * @buf - target buf + * @buf_size - buffer size + * @freq - 760 ~ 1080, 100KHz unit + * return package size + */ +static signed int mt6580_tune(unsigned char *buf, signed int buf_size, unsigned short freq, + unsigned short chan_para) +{ + signed int pkt_size = 0; + + pkt_size = mt6580_tune_reg_op(buf, buf_size, freq, chan_para); + return fm_op_seq_combine_cmd(buf, FM_TUNE_OPCODE, pkt_size); +} + +/* + * mt6580_pwrup_DSP_download - execute dsp/coeff patch dl action, + * @patch_tbl - current chip patch table + * return patch dl ok or not + */ +static signed int mt6580_pwrup_DSP_download(struct fm_patch_tbl *patch_tbl) +{ +#define PATCH_BUF_SIZE (4096*6) + signed int ret = 0; + signed int patch_len = 0; + unsigned char *dsp_buf = NULL; + unsigned short tmp_reg = 0; + + mt6580_hw_info.eco_ver = (signed int) mtk_wcn_wmt_hwver_get(); + WCN_DBG(FM_NTC | CHIP, "ECO version:0x%08x\n", mt6580_hw_info.eco_ver); + mt6580_hw_info.eco_ver += 1; + + /* get mt6580 DSP rom version */ + ret = mt6580_get_rom_version(); + if (ret >= 0) { + mt6580_hw_info.rom_ver = ret; + WCN_DBG(FM_NTC | CHIP, "ROM version: v%d\n", mt6580_hw_info.rom_ver); + } else { + WCN_DBG(FM_ERR | CHIP, "get ROM version failed\n"); + /* ret=-4 means signal got when control FM. usually get sig 9 to kill FM process. */ + /* now cancel FM power up sequence is recommended. */ + goto out; + } + + dsp_buf = fm_vmalloc(PATCH_BUF_SIZE); + if (!dsp_buf) { + WCN_DBG(FM_ALT | CHIP, "-ENOMEM\n"); + return -ENOMEM; + } + + patch_len = fm_get_patch_path(mt6580_hw_info.rom_ver, dsp_buf, PATCH_BUF_SIZE, patch_tbl); + if (patch_len <= 0) { + WCN_DBG(FM_ALT | CHIP, " fm_get_patch_path failed\n"); + ret = patch_len; + goto out; + } + + ret = fm_download_patch((const unsigned char *)dsp_buf, patch_len, IMG_PATCH); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " DL DSPpatch failed\n"); + goto out; + } + + patch_len = fm_get_coeff_path(mt6580_hw_info.rom_ver, dsp_buf, PATCH_BUF_SIZE, patch_tbl); + if (patch_len <= 0) { + WCN_DBG(FM_ALT | CHIP, " fm_get_coeff_path failed\n"); + ret = patch_len; + goto out; + } + + mt6580_hw_info.rom_ver += 1; + + tmp_reg = dsp_buf[38] | (dsp_buf[39] << 8); /* to be confirmed */ + mt6580_hw_info.patch_ver = (signed int) tmp_reg; + WCN_DBG(FM_NTC | CHIP, "Patch version: 0x%08x\n", mt6580_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; + } + + ret = fm_download_patch((const unsigned char *)dsp_buf, patch_len, IMG_COEFFICIENT); + if (ret) { + WCN_DBG(FM_ALT | CHIP, " DL DSPcoeff failed\n"); + goto out; + } + fm_reg_write(0x92, 0x0000); + fm_reg_write(0x90, 0x0040); + fm_reg_write(0x90, 0x0000); +out: + if (dsp_buf) { + fm_vfree(dsp_buf); + dsp_buf = NULL; + } + return ret; +} + + +static signed int mt6580_PowerUp(unsigned short *chip_id, unsigned short *device_id) +{ + signed int ret = 0; + unsigned short pkt_size; + unsigned short tmp_reg = 0; + + if (chip_id == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (device_id == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + WCN_DBG(FM_DBG | CHIP, "pwr on seq......\n"); + + mt6580_enable_pmic_tldo(); + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6580_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, "mt6580_pwrup_clock_on failed\n"); + return ret; + } + + fm_reg_read(0x62, &tmp_reg); + /* *chip_id = tmp_reg; */ + if ((tmp_reg == 0x6580) || (tmp_reg == 0x0633)) + *chip_id = 0x6580; + *device_id = tmp_reg; + mt6580_hw_info.chip_id = (signed int) tmp_reg; + WCN_DBG(FM_NTC | CHIP, "chip_id:0x%04x\n", tmp_reg); + + if ((mt6580_hw_info.chip_id != 0x6580) && (mt6580_hw_info.chip_id != 0x0633)) { + WCN_DBG(FM_NTC | CHIP, "fm sys error, reset hw\n"); + return -FM_EFW; + } + + ret = mt6580_pwrup_DSP_download(mt6580_patch_tbl); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "mt6580_pwrup_DSP_download failed\n"); + return ret; + } + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6580_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, "mt6580_pwrup_digital_init failed\n"); + return ret; + } + + /* set audio output I2S TX mode */ + fm_reg_write(0x9B, 0x3); + + WCN_DBG(FM_NTC | CHIP, "pwr on seq ok\n"); + + return ret; +} + +static signed int mt6580_PowerDown(void) +{ + signed int ret = 0; + unsigned short pkt_size; + unsigned short dataRead = 0; + + 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. + */ + fm_reg_read(FM_MAIN_INTR, &dataRead); + + if (dataRead & 0x1) { + ret = fm_reg_write(FM_MAIN_INTR, dataRead); /* clear status flag */ + if (ret) + WCN_DBG(FM_ALT | CHIP, "mt6580_pwrdown wr FM_MAIN_INTR failed\n"); + } + /* mt6580_RampDown(); */ + + /* set audio output I2X Rx mode: */ + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = mt6580_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, "mt6580_pwrdown failed\n"); + return ret; + } + + mt6580_disable_pmic_tldo(); + + return ret; +} + +static bool mt6580_SetFreq(unsigned short freq) +{ + signed int ret = 0; + unsigned short pkt_size; + unsigned short chan_para = 0; + unsigned short freq_reg = 0; + + fm_cb_op->cur_freq_set(freq); + + chan_para = mt6580_chan_para_get(freq); + WCN_DBG(FM_DBG | CHIP, "%d chan para = %d\n", (signed int) freq, (signed int) chan_para); + freq_reg = freq; + if (fm_get_channel_space(freq_reg) == 0) + freq_reg *= 10; + WCN_DBG(FM_DBG | CHIP, "freq_reg = %d\n", freq_reg); + ret = fm_reg_write(0x60, 0x00000007); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x60 failed\n"); + /* add this paragragh to resolve FM sensitivity bad in low band issue */ +#if 0 + if (mt6580_TDD_chan_check(freq)) { + ret = fm_set_bits(0x39, 0x0008, 0xFFF3); /* use TDD solution */ + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x30 failed\n"); + } else { + ret = fm_set_bits(0x39, 0x0000, 0xFFF3); /* default use FDD solution */ + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x30 failed\n"); + } +#endif + if ((freq_reg >= 6500) && (freq_reg <= 7290)) { + ret = fm_reg_write(0x39, 0xd002); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x39 failed\n"); + } else if ((freq_reg >= 7295) && (freq_reg <= 8410)) { + ret = fm_reg_write(0x39, 0xce02); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x39 failed\n"); + } else if ((freq_reg >= 8415) && (freq_reg <= 9815)) { + ret = fm_reg_write(0x39, 0xcc02); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x39 failed\n"); + } else if ((freq_reg >= 9820) && (freq_reg <= 9830)) { + ret = fm_reg_write(0x39, 0xca02); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x39 failed\n"); + } else if ((freq_reg >= 9835) && (freq_reg <= 9940)) { + ret = fm_reg_write(0x39, 0xcc02); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x39 failed\n"); + } else if ((freq_reg >= 9845) && (freq_reg <= 10800)) { + ret = fm_reg_write(0x39, 0xca02); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x39 failed\n"); + } else { + ret = fm_reg_write(0x39, 0xca02); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x39 failed\n"); + } + + /* end */ + ret = fm_reg_write(0x6a, 0x00000021); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x6a failed\n"); + + ret = fm_reg_write(0x6b, 0x00000021); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x6b failed\n"); + + ret = fm_reg_write(0x60, 0x0000000F); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x60 failed\n"); + + + freq_reg = (freq_reg - 6400) * 2 / 10; + ret = fm_set_bits(0x65, freq_reg, 0xFC00); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x65 failed\n"); + return false; + } + ret = fm_set_bits(0x65, (chan_para << 12), 0x0FFF); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x65 failed\n"); + return false; + } + + if (FM_LOCK(cmd_buf_lock)) + return false; + pkt_size = mt6580_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, "mt6580_tune failed\n"); + return false; + } + + WCN_DBG(FM_DBG | CHIP, "set freq to %d ok\n", freq); + + return true; +} + +#define FM_CQI_LOG_PATH "/mnt/sdcard/fmcqilog" + +static signed int mt6580_full_cqi_get(signed int min_freq, signed int max_freq, signed int space, signed int cnt) +{ + signed int ret = 0; + unsigned short pkt_size; + unsigned short freq, orig_freq; + signed int i, j, k; + signed int space_val, max, min, num; + struct mt6580_full_cqi *p_cqi; + unsigned char *cqi_log_title = "Freq, RSSI, PAMD, PR, FPAMD, MR, ATDC, PRX, ATDEV, SMGain, DltaRSSI\n"; + unsigned char cqi_log_buf[100] = { 0 }; + signed int pos; + unsigned char cqi_log_path[100] = { 0 }; + + WCN_DBG(FM_DBG | CHIP, "6580 cqi log start\n"); + /* for soft-mute tune, and get cqi */ + freq = fm_cb_op->cur_freq_get(); + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + /* get cqi */ + orig_freq = freq; + if (fm_get_channel_space(min_freq) == 0) + min = min_freq * 10; + else + min = min_freq; + + if (fm_get_channel_space(max_freq) == 0) + 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; (orig_freq == 10000) && (g_dbg_level == 0xffffffff) && (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)); + if (sprintf(&cqi_log_path[strlen(FM_CQI_LOG_PATH)], "%d.txt", k + 1) < 0) + WCN_DBG(FM_NTC | CHIP, "sprintf fail\n"); + 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 = fm_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, fm_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (!ret && fm_res) { + WCN_DBG(FM_NTC | CHIP, "smt cqi size %d\n", fm_res->cqi[0]); + p_cqi = (struct mt6580_full_cqi *)&fm_res->cqi[2]; + for (i = 0; i < fm_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 */ + if (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) < 0) + WCN_DBG(FM_NTC | CHIP, "sprintf fail\n"); + /* 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_DBG | CHIP, "6580 cqi log done\n"); + + return ret; +} + +/* + * mt6580_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 signed int mt6580_GetCurRSSI(signed int *pRSSI) +{ + unsigned short tmp_reg = 0; + + fm_reg_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 unsigned short mt6580_vol_tbl[16] = { 0x0000, 0x0519, 0x066A, 0x0814, + 0x0A2B, 0x0CCD, 0x101D, 0x1449, + 0x198A, 0x2027, 0x287A, 0x32F5, + 0x4027, 0x50C3, 0x65AD, 0x7FFF +}; + +static signed int mt6580_SetVol(unsigned char vol) +{ + signed int ret = 0; + + vol = (vol > 15) ? 15 : vol; + ret = fm_reg_write(0x7D, mt6580_vol_tbl[vol]); + if (ret) { + WCN_DBG(FM_ERR | CHIP, "Set vol=%d Failed\n", vol); + return ret; + } + + 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 signed int mt6580_GetVol(unsigned char *pVol) +{ + int ret = 0; + unsigned short tmp = 0; + signed int i; + + if (pVol == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + ret = fm_reg_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 (mt6580_vol_tbl[i] == tmp) { + *pVol = i; + break; + } + } + + WCN_DBG(FM_DBG | CHIP, "Get vol=%d OK\n", *pVol); + return 0; +} + +static signed int mt6580_dump_reg(void) +{ + signed int i; + unsigned short TmpReg = 0; + + for (i = 0; i < 0xff; i++) { + fm_reg_read(i, &TmpReg); + WCN_DBG(FM_NTC | CHIP, "0x%02x=0x%04x\n", i, TmpReg); + } + return 0; +} + +/*0:mono, 1:stereo*/ +static bool mt6580_GetMonoStereo(unsigned short *pMonoStereo) +{ +#define FM_BF_STEREO 0x1000 + unsigned short TmpReg = 0; + + if (pMonoStereo) { + fm_reg_read(FM_RSSI_IND, &TmpReg); + *pMonoStereo = (TmpReg & FM_BF_STEREO) >> 12; + } else { + WCN_DBG(FM_ERR | CHIP, "MonoStero: para err\n"); + return false; + } + + WCN_DBG(FM_NTC | CHIP, "Get MonoStero:0x%04x\n", *pMonoStereo); + return true; +} + +static signed int mt6580_SetMonoStereo(signed int MonoStereo) +{ + signed int ret = 0; + + WCN_DBG(FM_NTC | CHIP, "set to %s\n", MonoStereo ? "mono" : "auto"); + fm_top_reg_write(0x50, 0x0007); + + if (MonoStereo) { /*mono */ + ret = fm_set_bits(0x75, 0x0008, ~0x0008); + } else { /*auto switch */ + + ret = fm_set_bits(0x75, 0x0000, ~0x0008); + } + + fm_top_reg_write(0x50, 0x000F); + return ret; +} + +static signed int mt6580_GetCapArray(signed int *ca) +{ + unsigned short dataRead = 0; + unsigned short tmp = 0; + + if (ca == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + fm_reg_read(0x60, &tmp); + fm_reg_write(0x60, tmp & 0xFFF7); /* 0x60 D3=0 */ + + fm_reg_read(0x26, &dataRead); + *ca = dataRead; + + fm_reg_write(0x60, tmp); /* 0x60 D3=1 */ + return 0; +} + +/* + * mt6580_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 bool mt6580_GetCurPamd(unsigned short *pPamdLevl) +{ + unsigned short tmp_reg = 0; + unsigned short dBvalue, valid_cnt = 0; + int i, total = 0; + + for (i = 0; i < 8; i++) { + if (fm_reg_read(FM_ADDR_PAMD, &tmp_reg)) { + *pPamdLevl = 0; + return 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); + } + fm_delayms(3); + } + if (valid_cnt != 0) + *pPamdLevl = total / valid_cnt; + else + *pPamdLevl = 0; + + WCN_DBG(FM_NTC | CHIP, "PAMD=%d\n", *pPamdLevl); + return true; +} + +static signed int mt6580_i2s_info_get(signed int *ponoff, signed int *pmode, signed int *psample) +{ + if (ponoff == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (pmode == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (psample == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + *ponoff = fm_config.aud_cfg.i2s_info.status; + *pmode = fm_config.aud_cfg.i2s_info.mode; + *psample = fm_config.aud_cfg.i2s_info.rate; + + return 0; +} + +static signed int mt6580fm_get_audio_info(struct fm_audio_info_t *data) +{ + memcpy(data, &fm_config.aud_cfg, sizeof(struct fm_audio_info_t)); + return 0; +} + +static signed int mt6580_hw_info_get(struct fm_hw_info *req) +{ + if (req == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + req->chip_id = mt6580_hw_info.chip_id; + req->eco_ver = mt6580_hw_info.eco_ver; + req->patch_ver = mt6580_hw_info.patch_ver; + req->rom_ver = mt6580_hw_info.rom_ver; + + return 0; +} + +static signed int mt6580_pre_search(void) +{ + mt6580_RampDown(); + /* disable audio output I2S Rx mode */ + fm_host_reg_write(0x80101054, 0x00000000); + /* disable audio output I2S Tx mode */ + fm_reg_write(0x9B, 0x0000); + + return 0; +} + +static signed int mt6580_restore_search(void) +{ + mt6580_RampDown(); + /* set audio output I2S Tx mode */ + fm_reg_write(0x9B, 0xF9AB); + /* set audio output I2S Rx mode */ + fm_host_reg_write(0x80101054, 0x00003f35); + return 0; +} + +static signed int mt6580_soft_mute_tune(unsigned short freq, signed int *rssi, signed int *valid) +{ + signed int ret = 0; + unsigned short pkt_size; + struct mt6580_full_cqi *p_cqi; + signed int RSSI = 0, PAMD = 0, MR = 0, ATDC = 0; + unsigned int PRX = 0, ATDEV = 0; + unsigned short softmuteGainLvl = 0; + unsigned short freq_reg = 0; + + /* add this paragragh to resolve FM sensitivity bad in low band issue */ +#if 0 + ret = mt6580_chan_para_get(freq); + if (ret == 2) + ret = fm_set_bits(FM_CHANNEL_SET, 0x2000, 0x0FFF); /* mdf HiLo */ + else + ret = fm_set_bits(FM_CHANNEL_SET, 0x0000, 0x0FFF); /* clear FA/HL/ATJ */ +#endif + freq_reg = freq; + if (fm_get_channel_space(freq_reg) == 0) + freq_reg *= 10; + + ret = fm_reg_write(0x60, 0x00000007); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x60 failed\n"); + + if ((freq_reg >= 6500) && (freq_reg <= 7290)) { + ret = fm_reg_write(0x39, 0xd002); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x39 failed\n"); + } else if ((freq_reg >= 7295) && (freq_reg <= 8410)) { + ret = fm_reg_write(0x39, 0xce02); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x39 failed\n"); + } else if ((freq_reg >= 8415) && (freq_reg <= 9815)) { + ret = fm_reg_write(0x39, 0xcc02); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x39 failed\n"); + } else if ((freq_reg >= 9820) && (freq_reg <= 9830)) { + ret = fm_reg_write(0x39, 0xca02); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x39 failed\n"); + } else if ((freq_reg >= 9835) && (freq_reg <= 9940)) { + ret = fm_reg_write(0x39, 0xcc02); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x39 failed\n"); + } else if ((freq_reg >= 9845) && (freq_reg <= 10800)) { + ret = fm_reg_write(0x39, 0xca02); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x39 failed\n"); + } else { + ret = fm_reg_write(0x39, 0xca02); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x39 failed\n"); + } + + ret = fm_reg_write(0x60, 0x0000000f); + if (ret) + WCN_DBG(FM_ERR | CHIP, "set freq wr 0x60 failed\n"); + /* end */ + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = fm_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, fm_get_read_result); + FM_UNLOCK(cmd_buf_lock); + + if (!ret && fm_res) { + WCN_DBG(FM_NTC | CHIP, "smt cqi size %d\n", fm_res->cqi[0]); + p_cqi = (struct mt6580_full_cqi *)&fm_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 ((fm_config.rx_cfg.long_ana_rssi_th <= RSSI) + && (fm_config.rx_cfg.pamd_th >= PAMD) + && (fm_config.rx_cfg.atdc_th >= ATDC) + && (fm_config.rx_cfg.mr_th <= MR) + && (fm_config.rx_cfg.prx_th <= PRX) + && (ATDEV >= ATDC) /* sync scan algorithm */ + && (fm_config.rx_cfg.smg_th <= softmuteGainLvl)) { + *valid = true; + } else { + *valid = 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 false; + } + WCN_DBG(FM_NTC | CHIP, "valid=%d\n", *valid); + return true; +} + +static bool mt6580_em_test(unsigned short group_idx, unsigned short item_idx, unsigned int item_value) +{ + return true; +} + +/* +*parm: +* parm.th_type: 0, RSSI. 1,desense RSSI. 2,SMG. +* parm.th_val: threshold value +*/ +static signed int mt6580_set_search_th(signed int idx, signed int val, signed int reserve) +{ + switch (idx) { + case 0: + { + fm_config.rx_cfg.long_ana_rssi_th = val; + WCN_DBG(FM_NTC | CHIP, "set rssi th =%d\n", val); + break; + } + case 1: + { + fm_config.rx_cfg.desene_rssi_th = val; + WCN_DBG(FM_NTC | CHIP, "set desense rssi th =%d\n", val); + break; + } + case 2: + { + fm_config.rx_cfg.smg_th = val; + WCN_DBG(FM_NTC | CHIP, "set smg th =%d\n", val); + break; + } + default: + break; + } + return 0; +} + +static signed int MT6580fm_low_power_wa_default(signed int fmon) +{ + return 0; +} + +signed int fm_low_ops_register(struct fm_callback *cb, struct fm_basic_interface *bi) +{ + signed int ret = 0; + /* Basic functions. */ + + if (bi == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,bi invalid pointer\n", __func__); + return -FM_EPARA; + } + if (cb->cur_freq_get == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,cb->cur_freq_get invalid pointer\n", __func__); + return -FM_EPARA; + } + if (cb->cur_freq_set == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,cb->cur_freq_set invalid pointer\n", __func__); + return -FM_EPARA; + } + fm_cb_op = cb; + + bi->pwron = mt6580_pwron; + bi->pwroff = mt6580_pwroff; + bi->chipid_get = mt6580_get_chipid; + bi->mute = mt6580_Mute; + bi->rampdown = mt6580_RampDown; + bi->pwrupseq = mt6580_PowerUp; + bi->pwrdownseq = mt6580_PowerDown; + bi->setfreq = mt6580_SetFreq; + bi->low_pwr_wa = MT6580fm_low_power_wa_default; + bi->get_aud_info = mt6580fm_get_audio_info; + bi->rssiget = mt6580_GetCurRSSI; + bi->volset = mt6580_SetVol; + bi->volget = mt6580_GetVol; + bi->dumpreg = mt6580_dump_reg; + bi->msget = mt6580_GetMonoStereo; + bi->msset = mt6580_SetMonoStereo; + bi->pamdget = mt6580_GetCurPamd; + bi->em = mt6580_em_test; + bi->anaswitch = mt6580_SetAntennaType; + bi->anaget = mt6580_GetAntennaType; + bi->caparray_get = mt6580_GetCapArray; + bi->hwinfo_get = mt6580_hw_info_get; + bi->i2s_get = mt6580_i2s_info_get; + bi->is_dese_chan = mt6580_is_dese_chan; + bi->softmute_tune = mt6580_soft_mute_tune; + bi->desense_check = mt6580_desense_check; + bi->cqi_log = mt6580_full_cqi_get; + bi->pre_search = mt6580_pre_search; + bi->restore_search = mt6580_restore_search; + bi->set_search_th = mt6580_set_search_th; + + cmd_buf_lock = fm_lock_create("80_cmd"); + ret = fm_lock_get(cmd_buf_lock); + + cmd_buf = fm_zalloc(TX_BUF_SIZE + 1); + + if (!cmd_buf) { + WCN_DBG(FM_ALT | CHIP, "6580 fm lib alloc tx buf failed\n"); + ret = -1; + } +#if 0 /* def CONFIG_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, "6627 fm lib create cqi fifo failed\n"); + ret = -1; + } +#endif + + return ret; +} + +signed int fm_low_ops_unregister(struct fm_basic_interface *bi) +{ + signed int ret = 0; + /* Basic functions. */ + if (bi == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + +#if 0 /* def CONFIG_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(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 unsigned short mt6580_mcu_dese_list[] = { + 0 +}; + +static const unsigned short mt6580_gps_dese_list[] = { + 7850, 7860 +}; + +static const signed char mt6580_chan_para_map[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6500~6595 */ + 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, /* 6600~6695 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6700~6795 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6800~6895 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, /* 6900~6995 */ + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7000~7095 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7100~7195 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, /* 7200~7295 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, /* 7300~7395 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7400~7495 */ + 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, /* 7500~7595 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7600~7695 */ + 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7700~7795 */ + 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, /* 7800~7895 */ + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7900~7995 */ + 0, 0, 0, 0, 0, 0, 0, 0, 2, 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, 2, 0, 0, /* 8100~8195 */ + 0, 0, 0, 0, 0, 0, 2, 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, 2, 0, 0, 0, 0, 0, /* 8300~8395 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, /* 8600~8695 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 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, 2, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, /* 9200~9295 */ + 0, 0, 0, 0, 0, 0, 2, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9400~9495 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9500~9595 */ + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9800~9895 */ + 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9900~9995 */ + 0, 0, 0, 0, 0, 0, 0, 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, 0, 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 */ + 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10700~10795 */ + 0 /* 10800 */ +}; + +static const unsigned short mt6580_scan_dese_list[] = { + 6700, 7800, 9210, 9220, 9300, 1040, 1041 +}; + +static const unsigned short mt6580_TDD_list[] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6500~6595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6600~6695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6700~6795 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6800~6895 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 6900~6995 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7000~7095 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7100~7195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7200~7295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7300~7395 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7400~7495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7500~7595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7600~7695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7700~7795 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7800~7895 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7900~7995 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8000~8095 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8100~8195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8200~8295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8300~8395 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8400~8495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8500~8595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8600~8695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8700~8795 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8800~8895 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8900~8995 */ + 0x0000, 0x0000, 0x0000, 0x0100, 0x0000, /* 9000~9095 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9100~9195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9200~9295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9300~9395 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9400~9495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9500~9595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9600~9695 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9700~9795 */ + 0x0000, 0x0101, 0x0000, 0x0000, 0x0000, /* 9800~9895 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9900~9995 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10000~10095 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10100~10195 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10200~10295 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10300~10395 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10400~10495 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10500~10595 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10600~10695 */ + 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, /* 10700~10795 */ + 0x0000 /* 10800 */ +}; + +static const unsigned short mt6580_TDD_Mask[] = { + 0x0001, 0x0010, 0x0100, 0x1000 +}; + +/* return value: 0, not a de-sense channel; 1, this is a de-sense channel; else error no */ +static signed int mt6580_is_dese_chan(unsigned short freq) +{ + signed int size; + + /* return 0;//HQA only :skip desense channel check. */ + size = ARRAY_SIZE(mt6580_scan_dese_list); + + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + while (size) { + if (mt6580_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 signed int mt6580_desense_check(unsigned short freq, signed int rssi) +{ + if (mt6580_is_dese_chan(freq)) { + if (rssi < fm_config.rx_cfg.desene_rssi_th) + return 1; + + WCN_DBG(FM_DBG | CHIP, "desen_rssi %d th:%d\n", rssi, fm_config.rx_cfg.desene_rssi_th); + } + return 0; +} +#if 0 +static bool mt6580_TDD_chan_check(unsigned short freq) +{ + unsigned int i = 0; + unsigned short freq_tmp = freq; + signed int ret = 0; + + ret = fm_get_channel_space(freq_tmp); + if (ret == 0) + freq_tmp *= 10; + else if (-1 == ret) + return false; + + i = (freq_tmp - 6500) / 5; + if ((i / 4) >= ARRAY_SIZE(mt6580_TDD_list)) { + WCN_DBG(FM_ERR | CHIP, "Freq index out of range(%d),max(%zd)\n", + i / 4, ARRAY_SIZE(mt6580_TDD_list)); + return false; + } + + WCN_DBG(FM_NTC | CHIP, "Freq %d is 0x%4x, mask is 0x%4x\n", freq, (mt6580_TDD_list[i / 4]), + mt6580_TDD_Mask[i % 4]); + if (mt6580_TDD_list[i / 4] & mt6580_TDD_Mask[i % 4]) { + WCN_DBG(FM_NTC | CHIP, "Freq %d use TDD solution\n", freq); + return true; + } else + return false; +} +#endif +/* get channel parameter, HL side/ FA / ATJ */ +static unsigned short mt6580_chan_para_get(unsigned short freq) +{ + signed int pos, size; + + /* return 0;//for HQA only: skip FA/HL/ATJ */ + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + if (freq < 6500) + return 0; + + pos = (freq - 6500) / 5; + + size = ARRAY_SIZE(mt6580_chan_para_map); + + pos = (pos > (size - 1)) ? (size - 1) : pos; + + return mt6580_chan_para_map[pos]; +} diff --git a/drivers/misc/mediatek/connectivity/fmradio/chips/soc/pub/soc_fm_rds.c b/drivers/misc/mediatek/connectivity/fmradio/chips/soc/pub/soc_fm_rds.c new file mode 100644 index 0000000000000..49d9ebef5803d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/chips/soc/pub/soc_fm_rds.c @@ -0,0 +1,334 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_interface.h" +#include "fm_stdlib.h" +#include "fm_rds.h" +#include "soc_fm_reg.h" +#include "fm_cmd.h" + +static bool bRDS_FirstIn; /* false */ +static unsigned int gBLER_CHK_INTERVAL = 500; +static unsigned short GOOD_BLK_CNT = 0, BAD_BLK_CNT; +static unsigned char BAD_BLK_RATIO; + +static struct fm_basic_interface *fm_bi; + +static bool mt6580_RDS_support(void); +static signed int mt6580_RDS_enable(void); +static signed int mt6580_RDS_disable(void); +static unsigned short mt6580_RDS_Get_GoodBlock_Counter(void); +static unsigned short mt6580_RDS_Get_BadBlock_Counter(void); +static unsigned char mt6580_RDS_Get_BadBlock_Ratio(void); +static unsigned int mt6580_RDS_Get_BlerCheck_Interval(void); +/* static void mt6580_RDS_GetData(unsigned short *data, unsigned short datalen); */ +static void mt6580_RDS_Init_Data(struct rds_t *pstRDSData); + +static bool mt6580_RDS_support(void) +{ + return true; +} + +static signed int mt6580_RDS_enable(void) +{ + signed int ret = 0; + unsigned short dataRead = 0; + + WCN_DBG(FM_DBG | RDSC, "rds enable\n"); + ret = fm_reg_read(FM_RDS_CFG0, &dataRead); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds enable read 0x80 fail\n"); + return ret; + } + ret = fm_reg_write(FM_RDS_CFG0, 6); /* set buf_start_th */ + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds enable write 0x80 fail\n"); + return ret; + } + ret = fm_reg_read(FM_MAIN_CTRL, &dataRead); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds enable read 0x63 fail\n"); + return ret; + } + ret = fm_reg_write(FM_MAIN_CTRL, dataRead | (RDS_MASK)); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds enable write 0x63 fail\n"); + return ret; + } + + return ret; +} + +static signed int mt6580_RDS_disable(void) +{ + signed int ret = 0; + unsigned short dataRead = 0; + + WCN_DBG(FM_DBG | RDSC, "rds disable\n"); + ret = fm_reg_read(FM_MAIN_CTRL, &dataRead); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds disable read 0x63 fail\n"); + return ret; + } + ret = fm_reg_write(FM_MAIN_CTRL, dataRead & (~RDS_MASK)); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "rds disable write 0x63 fail\n"); + return ret; + } + + return ret; +} + +static unsigned short mt6580_RDS_Get_GoodBlock_Counter(void) +{ + unsigned short tmp_reg = 0; + + fm_reg_read(FM_RDS_GOODBK_CNT, &tmp_reg); + GOOD_BLK_CNT = tmp_reg; + WCN_DBG(FM_DBG | RDSC, "get good block cnt:%d\n", (signed int) tmp_reg); + + return tmp_reg; +} + +static unsigned short mt6580_RDS_Get_BadBlock_Counter(void) +{ + unsigned short tmp_reg = 0; + + fm_reg_read(FM_RDS_BADBK_CNT, &tmp_reg); + BAD_BLK_CNT = tmp_reg; + WCN_DBG(FM_DBG | RDSC, "get bad block cnt:%d\n", (signed int) tmp_reg); + + return tmp_reg; +} + +static unsigned char mt6580_RDS_Get_BadBlock_Ratio(void) +{ + unsigned short tmp_reg; + unsigned short gbc; + unsigned short bbc; + + gbc = mt6580_RDS_Get_GoodBlock_Counter(); + bbc = mt6580_RDS_Get_BadBlock_Counter(); + + if ((gbc + bbc) > 0) + tmp_reg = (unsigned char) (bbc * 100 / (gbc + bbc)); + else + tmp_reg = 0; + + BAD_BLK_RATIO = tmp_reg; + WCN_DBG(FM_DBG | RDSC, "get badblock ratio:%d\n", (signed int) tmp_reg); + + return tmp_reg; +} + +static signed int mt6580_RDS_BlockCounter_Reset(void) +{ + mt6580_RDS_disable(); + mt6580_RDS_enable(); + + return 0; +} + +static unsigned int mt6580_RDS_Get_BlerCheck_Interval(void) +{ + return gBLER_CHK_INTERVAL; +} + +static signed int mt6580_RDS_BlerCheck(struct rds_t *dst) +{ + return 0; +} + +#if 0 +static void RDS_Recovery_Handler(void) +{ + unsigned short tempData = 0; + + do { + fm_reg_read(FM_RDS_DATA_REG, &tempData); + fm_reg_read(FM_RDS_POINTER, &tempData); + } while (tempData & 0x3); +} +#endif + +#if 0 +static void mt6580_RDS_GetData(unsigned short *data, unsigned short 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 + + unsigned short CRC = 0, i = 0, RDS_adj = 0, RDSDataCount = 0, FM_WARorrCnt = 0; + unsigned short temp = 0, OutputPofm_s32 = 0; + + WCN_DBG(FM_DBG | RDSC, "get data\n"); + fm_reg_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_reg_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_reg_read(FM_RDS_DATA_REG, &data[0]); + + /* block B data and info handling */ + fm_reg_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_reg_read(FM_RDS_DATA_REG, &data[1]); + + /* block C data and info handling */ + fm_reg_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_reg_read(FM_RDS_DATA_REG, &data[2]); + + /* block D data and info handling */ + fm_reg_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_reg_read(FM_RDS_DATA_REG, &data[3]); + + data[4] = (CRC | RDS_adj | RDSDataCount); + data[5] = FM_WARorrCnt; + + fm_reg_read(FM_RDS_PWDI, &data[6]); + fm_reg_read(FM_RDS_PWDQ, &data[7]); + + fm_reg_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 mt6580_RDS_Init_Data(struct rds_t *pstRDSData) +{ + fm_memset(pstRDSData, 0, sizeof(struct rds_t)); + bRDS_FirstIn = true; + + pstRDSData->event_status = 0x0000; + 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)); +} + +bool mt6580_RDS_OnOff(struct rds_t *dst, bool bFlag) +{ + signed int ret = 0; + + if (mt6580_RDS_support() == false) { + WCN_DBG(FM_ALT | RDSC, "mt6580_RDS_OnOff failed, RDS not support\n"); + return false; + } + + if (bFlag) { + mt6580_RDS_Init_Data(dst); + ret = mt6580_RDS_enable(); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "mt6580_RDS_OnOff enable failed\n"); + return false; + } + } else { + mt6580_RDS_Init_Data(dst); + ret = mt6580_RDS_disable(); + if (ret) { + WCN_DBG(FM_NTC | RDSC, "mt6580_RDS_OnOff disable failed\n"); + return false; + } + } + + return true; +} + +DEFINE_RDSLOG(mt6580_rds_log); + +/* mt6580_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 signed int mt6580_rds_parser(struct rds_t *rds_dst, struct rds_rx_t *rds_raw, + signed int rds_size, unsigned short(*getfreq) (void)) +{ + mt6580_rds_log.log_in(&mt6580_rds_log, rds_raw, rds_size); + return rds_parser(rds_dst, rds_raw, rds_size, getfreq); +} + +static signed int mt6580_rds_log_get(struct rds_rx_t *dst, signed int *dst_len) +{ + return mt6580_rds_log.log_out(&mt6580_rds_log, dst, dst_len); +} + +static signed int mt6580_rds_gc_get(struct rds_group_cnt_t *dst, struct rds_t *rdsp) +{ + return rds_grp_counter_get(dst, &rdsp->gc); +} + +static signed int mt6580_rds_gc_reset(struct rds_t *rdsp) +{ + return rds_grp_counter_reset(&rdsp->gc); +} + +signed int fm_rds_ops_register(struct fm_basic_interface *bi, struct fm_rds_interface *ri) +{ + signed int ret = 0; + + if (ri == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,ri invalid pointer\n", __func__); + return -FM_EPARA; + } + fm_bi = bi; + + ri->rds_blercheck = mt6580_RDS_BlerCheck; + ri->rds_onoff = mt6580_RDS_OnOff; + ri->rds_parser = mt6580_rds_parser; + ri->rds_gbc_get = mt6580_RDS_Get_GoodBlock_Counter; + ri->rds_bbc_get = mt6580_RDS_Get_BadBlock_Counter; + ri->rds_bbr_get = mt6580_RDS_Get_BadBlock_Ratio; + ri->rds_bc_reset = mt6580_RDS_BlockCounter_Reset; + ri->rds_bci_get = mt6580_RDS_Get_BlerCheck_Interval; + ri->rds_log_get = mt6580_rds_log_get; + ri->rds_gc_get = mt6580_rds_gc_get; + ri->rds_gc_reset = mt6580_rds_gc_reset; + return ret; +} + +signed int fm_rds_ops_unregister(struct fm_rds_interface *ri) +{ + signed int ret = 0; + + if (ri == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,ri invalid pointer\n", __func__); + return -FM_EPARA; + } + + fm_bi = NULL; + fm_memset(ri, 0, sizeof(struct fm_rds_interface)); + return ret; +} diff --git a/drivers/misc/mediatek/connectivity/fmradio/core/fm_cmd.c b/drivers/misc/mediatek/connectivity/fmradio/core/fm_cmd.c new file mode 100644 index 0000000000000..e79d41b5200d6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/core/fm_cmd.c @@ -0,0 +1,842 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#include +#include + +#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 "fm_cmd.h" + +signed int fm_bop_write(unsigned char addr, unsigned short value, unsigned char *buf, signed int size) +{ + if (size < (FM_WRITE_BASIC_OP_SIZE + 2)) { + WCN_DBG(FM_ERR | CHIP, "%s : left size(%d)/need size(%d)\n", + __func__, size, FM_WRITE_BASIC_OP_SIZE + 2); + return -1; + } + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s :buf invalid pointer\n", __func__); + return -2; + } + + buf[0] = FM_WRITE_BASIC_OP; + buf[1] = FM_WRITE_BASIC_OP_SIZE; + buf[2] = addr; + buf[3] = (unsigned char) ((value) & 0x00FF); + buf[4] = (unsigned char) ((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; +} + +signed int fm_bop_udelay(unsigned int value, unsigned char *buf, signed int size) +{ + if (size < (FM_UDELAY_BASIC_OP_SIZE + 2)) { + WCN_DBG(FM_ERR | CHIP, "%s : left size(%d)/need size(%d)\n", + __func__, size, FM_UDELAY_BASIC_OP_SIZE + 2); + return -1; + } + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s :buf invalid pointer\n", __func__); + return -2; + } + + buf[0] = FM_UDELAY_BASIC_OP; + buf[1] = FM_UDELAY_BASIC_OP_SIZE; + buf[2] = (unsigned char) ((value) & 0x000000FF); + buf[3] = (unsigned char) ((value >> 8) & 0x000000FF); + buf[4] = (unsigned char) ((value >> 16) & 0x000000FF); + buf[5] = (unsigned char) ((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; +} + +signed int fm_bop_rd_until(unsigned char addr, unsigned short mask, unsigned short value, + unsigned char *buf, signed int size) +{ + if (size < (FM_RD_UNTIL_BASIC_OP_SIZE + 2)) { + WCN_DBG(FM_ERR | CHIP, "%s : left size(%d)/need size(%d)\n", + __func__, size, FM_RD_UNTIL_BASIC_OP_SIZE + 2); + return -1; + } + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s :buf invalid pointer\n", __func__); + return -2; + } + + buf[0] = FM_RD_UNTIL_BASIC_OP; + buf[1] = FM_RD_UNTIL_BASIC_OP_SIZE; + buf[2] = addr; + buf[3] = (unsigned char) ((mask) & 0x00FF); + buf[4] = (unsigned char) ((mask >> 8) & 0x00FF); + buf[5] = (unsigned char) ((value) & 0x00FF); + buf[6] = (unsigned char) ((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; +} + +signed int fm_bop_modify(unsigned char addr, unsigned short mask_and, unsigned short mask_or, + unsigned char *buf, signed int size) +{ + if (size < (FM_MODIFY_BASIC_OP_SIZE + 2)) { + WCN_DBG(FM_ERR | CHIP, "%s : left size(%d)/need size(%d)\n", + __func__, size, FM_MODIFY_BASIC_OP_SIZE + 2); + return -1; + } + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s :buf invalid pointer\n", __func__); + return -2; + } + + buf[0] = FM_MODIFY_BASIC_OP; + buf[1] = FM_MODIFY_BASIC_OP_SIZE; + buf[2] = addr; + buf[3] = (unsigned char) ((mask_and) & 0x00FF); + buf[4] = (unsigned char) ((mask_and >> 8) & 0x00FF); + buf[5] = (unsigned char) ((mask_or) & 0x00FF); + buf[6] = (unsigned char) ((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; +} + +signed int fm_bop_top_write(unsigned short addr, unsigned int value, unsigned char *buf, signed int size) +{ + if (size < (FM_TOP_WRITE_BOP_SIZE + 2)) { + WCN_DBG(FM_ERR | CHIP, "%s : left size(%d)/need size(%d)\n", + __func__, size, FM_TOP_WRITE_BOP_SIZE + 2); + return -1; + } + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s :buf invalid pointer\n", __func__); + return -2; + } + + buf[0] = FM_WRITE_SPI_BASIC_OP; + buf[1] = FM_TOP_WRITE_BOP_SIZE; + buf[2] = top_index; + buf[3] = (unsigned char) ((addr) & 0x00FF); + buf[4] = (unsigned char) ((addr >> 8) & 0x00FF); + buf[5] = (unsigned char) ((value) & 0x00FF); + buf[6] = (unsigned char) ((value >> 8) & 0x00FF); + buf[7] = (unsigned char) ((value >> 16) & 0x00FF); + buf[8] = (unsigned char) ((value >> 24) & 0x00FF); + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x %02x %02x\n", buf[0], buf[1], + buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8]); + + return FM_TOP_WRITE_BOP_SIZE + 2; +} + +signed int fm_bop_top_rd_until(unsigned short addr, unsigned int mask, unsigned int value, + unsigned char *buf, signed int size) +{ + if (size < (FM_TOP_RD_UNTIL_BOP_SIZE + 2)) { + WCN_DBG(FM_ERR | CHIP, "%s : left size(%d)/need size(%d)\n", + __func__, size, FM_TOP_RD_UNTIL_BOP_SIZE + 2); + return -1; + } + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s :buf invalid pointer\n", __func__); + return -2; + } + + buf[0] = FM_RD_SPI_UNTIL_BASIC_OP; + buf[1] = FM_TOP_RD_UNTIL_BOP_SIZE; + buf[2] = top_index; + buf[3] = (unsigned char) ((addr) & 0x00FF); + buf[4] = (unsigned char) ((addr >> 8) & 0x00FF); + buf[5] = (unsigned char) ((mask) & 0x00FF); + buf[6] = (unsigned char) ((mask >> 8) & 0x00FF); + buf[7] = (unsigned char) ((mask >> 16) & 0x00FF); + buf[8] = (unsigned char) ((mask >> 24) & 0x00FF); + buf[9] = (unsigned char) ((value) & 0x00FF); + buf[10] = (unsigned char) ((value >> 8) & 0x00FF); + buf[11] = (unsigned char) ((value >> 16) & 0x00FF); + buf[12] = (unsigned char) ((value >> 24) & 0x00FF); + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], + buf[10], buf[11], buf[12]); + + return FM_TOP_RD_UNTIL_BOP_SIZE + 2; +} + +signed int fm_op_seq_combine_cmd(unsigned char *buf, unsigned char opcode, signed int pkt_size) +{ + signed int total_size = 0; + + if (buf == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s :buf invalid pointer\n", __func__); + return -1; + } + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = opcode; + buf[2] = (unsigned char) (pkt_size & 0x00FF); + buf[3] = (unsigned char) ((pkt_size >> 8) & 0x00FF); + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3]); + + total_size = pkt_size + 4; + + return total_size; +} + +/* + * fm_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 + */ +signed int fm_patch_download(unsigned char *buf, signed int buf_size, unsigned char seg_num, unsigned char seg_id, + const unsigned char *src, signed int seg_len) +{ + signed int pkt_size = 0; + unsigned char *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; + src++; + dst++; + } + + buf[2] = (unsigned char) ((pkt_size - 4) & 0x00FF); + buf[3] = (unsigned char) (((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; +} + +/* + * fm_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 + */ +signed int fm_coeff_download(unsigned char *buf, signed int buf_size, unsigned char seg_num, unsigned char seg_id, + const unsigned char *src, signed int seg_len) +{ + signed int pkt_size = 0; + unsigned char *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; + src++; + dst++; + } + + buf[2] = (unsigned char) ((pkt_size - 4) & 0x00FF); + buf[3] = (unsigned char) (((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; +} + +/* + * fm_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 + */ +signed int fm_full_cqi_req(unsigned char *buf, signed int buf_size, unsigned short *freq, + signed int cnt, signed int type) +{ + signed int 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] = (unsigned char) ((*freq) & 0x00FF); + pkt_size++; + buf[pkt_size] = (unsigned char) ((*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] = (unsigned short) type; + pkt_size++; + break; + } + + buf[2] = (unsigned char) ((pkt_size - 4) & 0x00FF); + buf[3] = (unsigned char) (((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + + +signed int fm_get_reg(unsigned char *buf, signed int buf_size, unsigned char 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; +} + +signed int fm_set_reg(unsigned char *buf, signed int buf_size, unsigned char addr, unsigned short 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] = (unsigned char) ((value) & 0x00FF); + buf[6] = (unsigned char) ((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; +} + +signed int fm_set_bits_reg(unsigned char *buf, signed int buf_size, unsigned char addr, + unsigned short bits, unsigned short mask) +{ + signed int pkt_size = 0; + + if (buf_size < TX_BUF_SIZE) + return -1; + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = 0x11; /* 0x11 this opcode won't be parsed as an opcode, so set here as spcial case. */ + pkt_size = 4; + pkt_size += fm_bop_modify(addr, mask, bits, &buf[pkt_size], buf_size - pkt_size); + + buf[2] = (unsigned char) ((pkt_size - 4) & 0x00FF); + buf[3] = (unsigned char) (((pkt_size - 4) >> 8) & 0x00FF); + + return pkt_size; +} + +/*top register read*/ +signed int fm_top_get_reg(unsigned char *buf, signed int buf_size, unsigned short addr) +{ + if (buf_size < TX_BUF_SIZE) + return -1; + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = CSPI_READ_OPCODE; + buf[2] = 0x03; + buf[3] = 0x00; + buf[4] = top_index; + buf[5] = (unsigned char) ((addr) & 0x00FF); + buf[6] = (unsigned char) ((addr >> 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; +} + +signed int fm_top_set_reg(unsigned char *buf, signed int buf_size, unsigned short addr, unsigned int value) +{ + if (buf_size < TX_BUF_SIZE) + return -1; + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = CSPI_WRITE_OPCODE; + buf[2] = 0x07; + buf[3] = 0x00; + buf[4] = top_index; + buf[5] = (unsigned char) ((addr) & 0x00FF); + buf[6] = (unsigned char) ((addr >> 8) & 0x00FF); + buf[7] = (unsigned char) ((value) & 0x00FF); + buf[8] = (unsigned char) ((value >> 8) & 0x00FF); + buf[9] = (unsigned char) ((value >> 16) & 0x00FF); + buf[10] = (unsigned char) ((value >> 24) & 0x00FF); + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", buf[0], + buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10]); + return 11; +} + +/*host register read*/ +signed int fm_host_get_reg(unsigned char *buf, signed int buf_size, unsigned int addr) +{ + if (buf_size < TX_BUF_SIZE) + return -1; + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_HOST_READ_OPCODE; + buf[2] = 0x04; + buf[3] = 0x00; + buf[4] = (unsigned char) ((addr) & 0x00FF); + buf[5] = (unsigned char) ((addr >> 8) & 0x00FF); + buf[6] = (unsigned char) ((addr >> 16) & 0x00FF); + buf[7] = (unsigned char) ((addr >> 24) & 0x00FF); + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x %02x\n", buf[0], buf[1], buf[2], + buf[3], buf[4], buf[5], buf[6], buf[7]); + return 8; +} + +signed int fm_host_set_reg(unsigned char *buf, signed int buf_size, unsigned int addr, unsigned int value) +{ + if (buf_size < TX_BUF_SIZE) + return -1; + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_HOST_WRITE_OPCODE; + buf[2] = 0x08; + buf[3] = 0x00; + buf[4] = (unsigned char) ((addr) & 0x00FF); + buf[5] = (unsigned char) ((addr >> 8) & 0x00FF); + buf[6] = (unsigned char) ((addr >> 16) & 0x00FF); + buf[7] = (unsigned char) ((addr >> 24) & 0x00FF); + buf[8] = (unsigned char) ((value) & 0x00FF); + buf[9] = (unsigned char) ((value >> 8) & 0x00FF); + buf[10] = (unsigned char) ((value >> 16) & 0x00FF); + buf[11] = (unsigned char) ((value >> 24) & 0x00FF); + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]); + return 12; +} + +signed int fm_pmic_get_reg(unsigned char *buf, signed int buf_size, unsigned char addr) +{ + if (buf_size < TX_BUF_SIZE) + return -1; + + if (buf == NULL) + return -2; + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_READ_PMIC_CR_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; +} + +signed int fm_pmic_set_reg(unsigned char *buf, signed int buf_size, unsigned char addr, unsigned int val) +{ + if (buf_size < TX_BUF_SIZE) + return -1; + + if (buf == NULL) + return -2; + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_WRITE_PMIC_CR_OPCODE; + buf[2] = 0x05; + buf[3] = 0x00; + buf[4] = addr; + buf[5] = (unsigned char) ((val) & 0x00FF); + buf[6] = (unsigned char) ((val >> 8) & 0x00FF); + buf[7] = (unsigned char) ((val >> 16) & 0x00FF); + buf[8] = (unsigned char) ((val >> 24) & 0x00FF); + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8]); + return 9; +} + +signed int fm_pmic_mod_reg(unsigned char *buf, signed int buf_size, unsigned char addr, + unsigned int mask_and, unsigned int mask_or) +{ + if (buf_size < TX_BUF_SIZE) + return -1; + + if (buf == NULL) + return -2; + + buf[0] = FM_TASK_COMMAND_PKT_TYPE; + buf[1] = FM_MODIFY_PMIC_CR_OPCODE; + buf[2] = 0x09; + buf[3] = 0x00; + buf[4] = addr; + buf[5] = (unsigned char) ((mask_and) & 0x00FF); + buf[6] = (unsigned char) ((mask_and >> 8) & 0x00FF); + buf[7] = (unsigned char) ((mask_and >> 16) & 0x00FF); + buf[8] = (unsigned char) ((mask_and >> 24) & 0x00FF); + buf[9] = (unsigned char) ((mask_or) & 0x00FF); + buf[10] = (unsigned char) ((mask_or >> 8) & 0x00FF); + buf[11] = (unsigned char) ((mask_or >> 16) & 0x00FF); + buf[12] = (unsigned char) ((mask_or >> 24) & 0x00FF); + + WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", buf[0], + buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12]); + + return 13; +} + +signed int fm_get_patch_path(signed int ver, unsigned char *buff, int buffsize, struct fm_patch_tbl *patch_tbl) +{ + signed int i; + signed int patch_len = 0; + signed int max = FM_ROM_MAX; + const signed char *ppath = NULL; + + /* check if the ROM version is defined or not */ + for (i = 0; i < max; i++) { + if (patch_tbl[i].idx == ver) { + ppath = patch_tbl[i].patch; + WCN_DBG(FM_NTC | CHIP, "Get ROM version OK\n"); + break; + } + } + + if (ppath == NULL) { + /* Load latest default patch */ + for (i = max; i > 0; i--) { + patch_len = fm_file_read(patch_tbl[i - 1].patch, buff, buffsize, 0); + if (patch_len >= 0) { + WCN_DBG(FM_NTC | CHIP, "undefined ROM version, load %s\n", patch_tbl[i - 1].patch); + return patch_len; + } + } + } else { + /* Load patch */ + patch_len = fm_file_read(ppath, buff, buffsize, 0); + if (patch_len >= 0) + return patch_len; + } + + /* get path failed */ + WCN_DBG(FM_ERR | CHIP, "No valid patch file\n"); + return -FM_EPATCH; +} + +signed int fm_get_coeff_path(signed int ver, unsigned char *buff, int buffsize, struct fm_patch_tbl *patch_tbl) +{ + signed int i; + signed int patch_len = 0; + const signed char *ppath = NULL; + signed int max = FM_ROM_MAX; + + /* check if the ROM version is defined or not */ + for (i = 0; i < max; i++) { + if (patch_tbl[i].idx == ver) { + ppath = patch_tbl[i].coeff; + WCN_DBG(FM_NTC | CHIP, "Get ROM version OK\n"); + break; + } + } + + if (ppath == NULL) { + /* Load default patch */ + for (i = max; i > 0; i--) { + patch_len = fm_file_read(patch_tbl[i - 1].coeff, buff, buffsize, 0); + if (patch_len >= 0) { + WCN_DBG(FM_NTC | CHIP, "undefined ROM version, load %s\n", patch_tbl[i - 1].coeff); + return patch_len; + } + } + } else { + /* Load patch by patch path*/ + patch_len = fm_file_read(ppath, buff, buffsize, 0); + if (patch_len >= 0) + return patch_len; + } + + /* get path failed */ + WCN_DBG(FM_ERR | CHIP, "No valid coeff file\n"); + return -FM_EPATCH; +} + +/* +* DspPatch - DSP download procedure +* @img - source dsp bin code +* @len - patch length in byte +* @type - rom/patch/coefficient/hw_coefficient +*/ +signed int fm_download_patch(const unsigned char *img, signed int len, enum IMG_TYPE type) +{ + unsigned char seg_num; + unsigned char seg_id = 0; + signed int seg_len; + signed int ret = 0; + unsigned short pkt_size; + + if (img == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + 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_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_INF | CHIP, "patch,[seg_id:%d], [seg_len:%d]\n", seg_id, seg_len); + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = + fm_patch_download(cmd_buf, TX_BUF_SIZE, seg_num, seg_id, + &img[seg_id * PATCH_SEG_LEN], seg_len); + WCN_DBG(FM_INF | CHIP, "pkt_size:%d\n", (signed int) 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_ERR | CHIP, "fm_patch_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_INF | CHIP, "coeff,[seg_id:%d], [seg_len:%d]\n", seg_id, seg_len); + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = + fm_coeff_download(cmd_buf, TX_BUF_SIZE, seg_num, seg_id, + &img[seg_id * PATCH_SEG_LEN], seg_len); + WCN_DBG(FM_INF | CHIP, "pkt_size:%d\n", (signed int) 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_ERR | CHIP, "fm_coeff_download failed\n"); + return ret; + } + } + + break; + default: + break; + } + + return 0; +} + +signed int fm_get_read_result(struct fm_res_ctx *result) +{ + if (result == NULL) { + WCN_DBG(FM_ERR | CHIP, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + fm_res = result; + + return 0; +} + +signed int fm_reg_read(unsigned char addr, unsigned short *val) +{ + signed int ret = 0; + unsigned short pkt_size; + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = fm_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, fm_get_read_result); + + if (!ret && fm_res) + *val = fm_res->fspi_rd; + + FM_UNLOCK(cmd_buf_lock); + + return ret; +} + +signed int fm_reg_write(unsigned char addr, unsigned short val) +{ + signed int ret = 0; + unsigned short pkt_size; + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = fm_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; +} + +signed int fm_set_bits(unsigned char addr, unsigned short bits, unsigned short mask) +{ + signed int ret = 0; + unsigned short pkt_size; + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = fm_set_bits_reg(cmd_buf, TX_BUF_SIZE, addr, bits, mask); + ret = fm_cmd_tx(cmd_buf, pkt_size, (1 << 0x11), SW_RETRY_CNT, FSPI_WR_TIMEOUT, NULL); + /* 0x11 this opcode won't be parsed as an opcode, so set here as spcial case. */ + FM_UNLOCK(cmd_buf_lock); + + return ret; +} + +signed int fm_top_reg_read(unsigned short addr, unsigned int *val) +{ + signed int ret = 0; + unsigned short pkt_size; + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = fm_top_get_reg(cmd_buf, TX_BUF_SIZE, addr); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_CSPI_READ, SW_RETRY_CNT, FSPI_RD_TIMEOUT, fm_get_read_result); + + if (!ret && fm_res) + *val = fm_res->cspi_rd; + + FM_UNLOCK(cmd_buf_lock); + + return ret; +} + +signed int fm_top_reg_write(unsigned short addr, unsigned int val) +{ + signed int ret = 0; + unsigned short pkt_size; + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = fm_top_set_reg(cmd_buf, TX_BUF_SIZE, addr, val); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_CSPI_WRITE, SW_RETRY_CNT, FSPI_WR_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + return ret; +} + +signed int fm_host_reg_read(unsigned int addr, unsigned int *val) +{ + signed int ret = 0; + unsigned short pkt_size; + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = fm_host_get_reg(cmd_buf, TX_BUF_SIZE, addr); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_HOST_READ, SW_RETRY_CNT, FSPI_RD_TIMEOUT, fm_get_read_result); + + if (!ret && fm_res) + *val = fm_res->cspi_rd; + + FM_UNLOCK(cmd_buf_lock); + + return ret; +} + +signed int fm_host_reg_write(unsigned int addr, unsigned int val) +{ + signed int ret = 0; + unsigned short pkt_size; + + if (FM_LOCK(cmd_buf_lock)) + return -FM_ELOCK; + pkt_size = fm_host_set_reg(cmd_buf, TX_BUF_SIZE, addr, val); + ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_HOST_WRITE, SW_RETRY_CNT, FSPI_WR_TIMEOUT, NULL); + FM_UNLOCK(cmd_buf_lock); + + return ret; +} diff --git a/drivers/misc/mediatek/connectivity/fmradio/core/fm_config.c b/drivers/misc/mediatek/connectivity/fmradio/core/fm_config.c new file mode 100644 index 0000000000000..deebbcb1eb9d3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/core/fm_config.c @@ -0,0 +1,625 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#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" + +struct fm_cust_cfg fm_config; +unsigned short g_fm_chipid; +enum fm_cfg_chip_type g_fm_chip_type = FM_CHIP_TYPE_MAX; + +#define FM_CUST_CFG_PATH "fm_cust.cfg" + +signed int to_upper_n(signed char *str, signed int len) +{ + signed int i = 0; + + for (i = 0; i < len; i++) { + if (('a' <= str[i]) && (str[i] <= 'z')) + str[i] = str[i] - ('a' - 'A'); + } + + return 0; +} + +signed int check_hex_str(signed char *str, signed int len) +{ + signed int 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; +} + +signed int check_dec_str(signed char *str, signed int len) +{ + signed int i = 0; + + for (i = 0; i < len; i++) { + if (('0' <= str[i]) && (str[i] <= '9')) + ; + else + return -1; + } + + return 0; +} + +signed int ascii_to_hex(signed char *in_ascii, unsigned short *out_hex) +{ + signed int len = (signed int) strlen(in_ascii); + int i = 0; + unsigned short 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; +} + +signed int ascii_to_dec(signed char *in_ascii, signed int *out_dec) +{ + signed int len = (signed int) 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; +} + +signed int trim_string(signed char **start) +{ + signed char *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; +} + +signed int trim_path(signed char **start) +{ + signed char *end = *start; + + while (*(*start) == ' ') + (*start)++; + + while (*end != '\0') + (end)++; + + do { + end--; + } while ((end >= *start) && ((*end == ' ') || (*end == '\n') || (*end == '\r'))); + + *(++end) = '\0'; + return end - *start; +} + +signed int check_path(signed char *str, signed int len) +{ + signed int 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')) || + ('/' == str[i]) || ('_' == str[i]) || + ('.' == str[i])) { + ; + } else { + return -1; + } + } + return 0; +} + +signed int cfg_parser(signed char *buffer, CFG_HANDLER handler, struct fm_cust_cfg *cfg) +{ + signed int ret = 0; + signed char *p = buffer; + signed char *group_start = NULL; + signed char *key_start = NULL; + signed char *value_start = NULL; + + enum fm_cfg_parser_state state = FM_CFG_STAT_NONE; + + if (p == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + 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; +} + +signed int cfg_item_match(signed char *src_key, signed char *src_val, signed char *dst_key, signed int *dst_val) +{ + signed int ret = 0; + unsigned short tmp_hex; + signed int 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; + } + /* WCN_DBG(FM_ERR | MAIN, "%s format error\n", dst_key); */ + return 1; + } + + 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; + } + /* 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 signed int cfg_item_handler(signed char *grp, signed char *key, signed char *val, struct fm_cust_cfg *cfg) +{ + signed int ret = 0; + struct fm_rx_cust_cfg *rx_cfg = &cfg->rx_cfg; + struct fm_tx_cust_cfg *tx_cfg = &cfg->tx_cfg; + + + ret = cfg_item_match(key, val, "FM_RX_RSSI_TH_LONG", &rx_cfg->long_ana_rssi_th); + if (ret >= 0) + return ret; + + ret = cfg_item_match(key, val, "FM_RX_RSSI_TH_SHORT", &rx_cfg->short_ana_rssi_th); + if (ret >= 0) + return ret; + + ret = cfg_item_match(key, val, "FM_RX_DESENSE_RSSI", &rx_cfg->desene_rssi_th); + if (ret >= 0) + return ret; + + ret = cfg_item_match(key, val, "FM_RX_SMG_TH", &rx_cfg->smg_th); + if (ret >= 0) + return ret; + + ret = cfg_item_match(key, val, "FM_RX_DEEMPHASIS", &rx_cfg->deemphasis); + if (ret >= 0) + return ret; + + ret = cfg_item_match(key, val, "FM_RX_OSC_FREQ", &rx_cfg->osc_freq); + if (ret >= 0) + return ret; + + ret = cfg_item_match(key, val, "FM_RX_PAMD_TH", &rx_cfg->pamd_th); + if (ret >= 0) + return ret; + + ret = cfg_item_match(key, val, "FM_RX_MR_TH", &rx_cfg->mr_th); + if (ret >= 0) + return ret; + + ret = cfg_item_match(key, val, "FM_RX_ATDC_TH", &rx_cfg->atdc_th); + if (ret >= 0) + return ret; + + ret = cfg_item_match(key, val, "FM_RX_PRX_TH", &rx_cfg->prx_th); + if (ret >= 0) + return ret; + + ret = cfg_item_match(key, val, "FM_TX_PAMD_TH", &tx_cfg->pamd_th); + if (ret >= 0) + return ret; + + ret = cfg_item_match(key, val, "FM_TX_MR_TH", &tx_cfg->mr_th); + if (ret >= 0) + return ret; + + ret = cfg_item_match(key, val, "FM_TX_SMG_TH", &tx_cfg->smg_th); + if (ret >= 0) + return ret; + + + WCN_DBG(FM_WAR | MAIN, "invalid key\n"); + return -1; +} + +static signed int fm_cust_config_default(struct fm_cust_cfg *cfg) +{ + if (cfg == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + /*RX Threshold config*/ + 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.desene_rssi_th = FM_RX_DESENSE_RSSI; + cfg->rx_cfg.pamd_th = FM_RX_PAMD_TH; + cfg->rx_cfg.mr_th = FM_RX_MR_TH; + cfg->rx_cfg.atdc_th = FM_RX_ATDC_TH; + cfg->rx_cfg.prx_th = FM_RX_PRX_TH; + cfg->rx_cfg.smg_th = FM_RX_SMG_TH; + cfg->rx_cfg.deemphasis = FM_RX_DEEMPHASIS; + cfg->rx_cfg.osc_freq = FM_RX_OSC_FREQ; + + /*TX Threshold config*/ + cfg->tx_cfg.pamd_th = FM_TX_PAMD_TH; + cfg->tx_cfg.mr_th = FM_TX_MR_TH; + cfg->tx_cfg.smg_th = FM_TX_SMG_TH; + + /*Audio path config*/ + if (g_fm_chip_type == FM_COMBO_CHIP) { + /* combo chip config MT6630,MT6632 */ +#ifdef CONFIG_MTK_MERGE_INTERFACE_SUPPORT + cfg->aud_cfg.aud_path = FM_AUD_MRGIF; + cfg->aud_cfg.i2s_info.status = FM_I2S_OFF; + cfg->aud_cfg.i2s_info.mode = FM_I2S_SLAVE; + if (g_fm_chipid == 0x6632) + cfg->aud_cfg.i2s_info.rate = FM_I2S_48K; + else + cfg->aud_cfg.i2s_info.rate = FM_I2S_44K; + cfg->aud_cfg.i2s_pad = FM_I2S_PAD_IO; +#elif defined FM_DIGITAL_INPUT + cfg->aud_cfg.aud_path = FM_AUD_I2S; + cfg->aud_cfg.i2s_info.status = FM_I2S_OFF; + cfg->aud_cfg.i2s_info.mode = FM_I2S_SLAVE; + if (g_fm_chipid == 0x6632) + cfg->aud_cfg.i2s_info.rate = FM_I2S_48K; + else + cfg->aud_cfg.i2s_info.rate = FM_I2S_44K; + cfg->aud_cfg.i2s_pad = FM_I2S_PAD_IO; +#elif defined FM_ANALOG_INPUT + cfg->aud_cfg.aud_path = FM_AUD_ANALOG; + cfg->aud_cfg.i2s_info.status = FM_I2S_STATE_ERR; + cfg->aud_cfg.i2s_info.mode = FM_I2S_MODE_ERR; + cfg->aud_cfg.i2s_info.rate = FM_I2S_SR_ERR; + cfg->aud_cfg.i2s_pad = FM_I2S_PAD_ERR; +#else + cfg->aud_cfg.aud_path = FM_AUD_ERR; + cfg->aud_cfg.i2s_info.status = FM_I2S_STATE_ERR; + cfg->aud_cfg.i2s_info.mode = FM_I2S_MODE_ERR; + cfg->aud_cfg.i2s_info.rate = FM_I2S_SR_ERR; + cfg->aud_cfg.i2s_pad = FM_I2S_PAD_ERR; +#endif + } else if ((g_fm_chip_type == FM_AD_DIE_CHIP) || (g_fm_chip_type == FM_SOC_CHIP)) { + /* MT6627 MT6580 MT6631 ?*/ + cfg->aud_cfg.aud_path = FM_AUD_I2S; + cfg->aud_cfg.i2s_info.status = FM_I2S_OFF; + cfg->aud_cfg.i2s_info.mode = FM_I2S_MASTER; + cfg->aud_cfg.i2s_info.rate = FM_I2S_32K; + cfg->aud_cfg.i2s_pad = FM_I2S_PAD_CONN; + } else { + WCN_DBG(FM_ALT | MAIN, "Invalid chip type %d\n", g_fm_chip_type); + cfg->aud_cfg.aud_path = FM_AUD_ERR; + cfg->aud_cfg.i2s_info.status = FM_I2S_STATE_ERR; + cfg->aud_cfg.i2s_info.mode = FM_I2S_MODE_ERR; + cfg->aud_cfg.i2s_info.rate = FM_I2S_SR_ERR; + cfg->aud_cfg.i2s_pad = FM_I2S_PAD_ERR; + } + return 0; +} + +static signed int fm_cust_config_file(const signed char *filename, struct fm_cust_cfg *cfg) +{ + signed int ret = 0; + signed char *buf = NULL; + signed int file_len = 0; + + buf = fm_zalloc(4096); + if (!buf) { + WCN_DBG(FM_ALT | MAIN, "-ENOMEM\n"); + return -ENOMEM; + } + + file_len = fm_file_read(filename, buf, 4096, 0); + + if (file_len <= 0) { + WCN_DBG(FM_ALT | MAIN, "fail to read config file = %s\n", filename); + ret = -1; + goto out; + } + + ret = cfg_parser(buf, cfg_item_handler, cfg); + +out: + if (buf) + fm_free(buf); + + return ret; +} + +static signed int fm_cust_config_print(struct fm_cust_cfg *cfg) +{ + WCN_DBG(FM_NTC | MAIN, "0x%x configs:\n", g_fm_chipid); + WCN_DBG(FM_NTC | MAIN, "RX->rssi_l:\t%d\n", cfg->rx_cfg.long_ana_rssi_th); + WCN_DBG(FM_NTC | MAIN, "RX->rssi_s:\t%d\n", cfg->rx_cfg.short_ana_rssi_th); + WCN_DBG(FM_NTC | MAIN, "RX->pamd_th:\t%d\n", cfg->rx_cfg.pamd_th); + WCN_DBG(FM_NTC | MAIN, "RX->mr_th:\t%d\n", cfg->rx_cfg.mr_th); + WCN_DBG(FM_NTC | MAIN, "RX->atdc_th:\t%d\n", cfg->rx_cfg.atdc_th); + WCN_DBG(FM_NTC | MAIN, "RX->prx_th:\t%d\n", cfg->rx_cfg.prx_th); + WCN_DBG(FM_NTC | MAIN, "RX->smg_th:\t%d\n", cfg->rx_cfg.smg_th); + WCN_DBG(FM_NTC | MAIN, "RX->de_emphasis:\t%d\n", cfg->rx_cfg.deemphasis); + WCN_DBG(FM_NTC | MAIN, "RX->osc_freq:\t%d\n", cfg->rx_cfg.osc_freq); + WCN_DBG(FM_NTC | MAIN, "RX->desense_rssi_th:\t%d\n", cfg->rx_cfg.desene_rssi_th); + + WCN_DBG(FM_NTC | MAIN, "TX->scan_hole_low:\t%d\n", cfg->tx_cfg.scan_hole_low); + WCN_DBG(FM_NTC | MAIN, "TX->scan_hole_high:\t%d\n", cfg->tx_cfg.scan_hole_high); + WCN_DBG(FM_NTC | MAIN, "TX->power_level:\t%d\n", cfg->tx_cfg.power_level); + + WCN_DBG(FM_NTC | MAIN, "aud path[%d]I2S state[%d]mode[%d]rate[%d]pad[%d]\n", + cfg->aud_cfg.aud_path, + cfg->aud_cfg.i2s_info.status, + cfg->aud_cfg.i2s_info.mode, + cfg->aud_cfg.i2s_info.rate, + cfg->aud_cfg.i2s_pad); + return 0; +} + +signed int fm_cust_config_setup(const signed char *filepath) +{ + signed int ret = 0; + signed char *filep = NULL; + signed char 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; + file_path[50] = '\0'; + trim_path(&filep); + } + + if (check_path(filep, strlen(filep)) != 0) { + WCN_DBG(FM_ALT | MAIN, + "Invalid config file: %s\n", filep); + return -FM_EPATCH; + } + + 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; +} + +unsigned short fm_cust_config_fetch(enum fm_cust_cfg_op op_code) +{ + unsigned short tmp = 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_DESENSE_RSSI_TH: + tmp = fm_config.rx_cfg.desene_rssi_th; + break; + case FM_CFG_RX_PAMD_TH: + tmp = fm_config.rx_cfg.pamd_th; + break; + case FM_CFG_RX_MR_TH: + tmp = fm_config.rx_cfg.mr_th; + break; + case FM_CFG_RX_ATDC_TH: + tmp = fm_config.rx_cfg.atdc_th; + break; + case FM_CFG_RX_PRX_TH: + tmp = fm_config.rx_cfg.prx_th; + break; + case FM_CFG_RX_ATDEV_TH: + tmp = fm_config.rx_cfg.atdev_th; + break; + case FM_CFG_RX_CQI_TH: + tmp = fm_config.rx_cfg.cqi_th; + break; + case FM_CFG_RX_SMG_TH: + tmp = fm_config.rx_cfg.smg_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; + + 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; + case FM_CFG_TX_PAMD_TH: + tmp = fm_config.tx_cfg.pamd_th; + break; + case FM_CFG_TX_DEEMPHASIS: + tmp = fm_config.tx_cfg.mr_th; + break; + case FM_CFG_TX_SMG_TH: + tmp = fm_config.tx_cfg.smg_th; + break; + default: + break; + } + + WCN_DBG(FM_DBG | MAIN, "cust cfg %d: 0x%04x\n", op_code, tmp); + return tmp; +} +unsigned short fm_cust_config_chip(unsigned short chipid, enum fm_cfg_chip_type type) +{ + g_fm_chipid = chipid; + g_fm_chip_type = type; + + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/fmradio/core/fm_eint.c b/drivers/misc/mediatek/connectivity/fmradio/core/fm_eint.c new file mode 100644 index 0000000000000..066ee1aae3f1a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/core/fm_eint.c @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_eint.h" +#include "fm_reg_utils.h" + +signed int fm_enable_eint(void) +{ + struct fm_ext_interface *ei = &fm_wcn_ops.ei; + + if (ei->enable_eint) + ei->enable_eint(); + + return 0; +} + +signed int fm_disable_eint(void) +{ + struct fm_ext_interface *ei = &fm_wcn_ops.ei; + + if (ei->disable_eint) + ei->disable_eint(); + + return 0; +} + +signed int fm_request_eint(void (*parser) (void)) +{ + struct fm_ext_interface *ei = &fm_wcn_ops.ei; + + if (ei->stp_register_event_cb) + ei->stp_register_event_cb(parser); + + return 0; +} + +signed int fm_eint_pin_cfg(signed int mode) +{ + return 0; +} + diff --git a/drivers/misc/mediatek/connectivity/fmradio/core/fm_link.c b/drivers/misc/mediatek/connectivity/fmradio/core/fm_link.c new file mode 100644 index 0000000000000..d91359ed37516 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/core/fm_link.c @@ -0,0 +1,570 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include + +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_stdlib.h" +#include "fm_link.h" +#include "fm_reg_utils.h" + +static struct fm_link_event *link_event; + +static struct fm_trace_fifo_t *cmd_fifo; + +static struct fm_trace_fifo_t *evt_fifo; + +signed int fm_link_setup(void *data) +{ + signed int ret = 0; + + link_event = fm_zalloc(sizeof(struct fm_link_event)); + if (!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; + } + + if (fm_wcn_ops.ei.wmt_msgcb_reg) + fm_wcn_ops.ei.wmt_msgcb_reg(data); + + return 0; + +failed: + fm_trace_fifo_release(evt_fifo); + fm_trace_fifo_release(cmd_fifo); + if (link_event) { + fm_flag_event_put(link_event->ln_event); + fm_free(link_event); + } + + return ret; +} + +signed int fm_link_release(void) +{ + + fm_trace_fifo_release(evt_fifo); + fm_trace_fifo_release(cmd_fifo); + if (link_event) { + fm_flag_event_put(link_event->ln_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 + */ +signed int fm_ctrl_rx(unsigned char addr, unsigned short *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 + */ +signed int fm_ctrl_tx(unsigned char addr, unsigned short 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 + */ +signed int fm_cmd_tx(unsigned char *buf, unsigned short len, signed int mask, signed int cnt, signed int timeout, + signed int (*callback)(struct fm_res_ctx *result)) +{ + signed int ret_time = 0; + struct task_struct *task = current; + struct fm_trace_t trace; + + if ((buf == NULL) || (len < 0) || (mask == 0) + || (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 = (signed int) 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 + + +#ifdef FM_TRACE_ENABLE + if (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 (fm_wcn_ops.ei.stp_send_data) + ret_time = fm_wcn_ops.ei.stp_send_data(buf, len); + if (ret_time <= 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 (cnt-- > 0) { + WCN_DBG(FM_WAR | LINK, "wait event timeout, [retry_cnt=%d], pid=%d\n", cnt, task->pid); + fm_print_cmd_fifo(); + fm_print_evt_fifo(); + } 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; +} + +signed int fm_event_parser(signed int(*rds_parser) (struct rds_rx_t *, signed int)) +{ + signed int len; + signed int i = 0; + unsigned char opcode = 0; + unsigned short length = 0; + unsigned char ch; + unsigned char rx_buf[RX_BUF_SIZE + 10] = { 0 }; /* the 10 bytes are protect gaps */ + unsigned int rx_len = 0; + + static enum fm_task_parser_state state = FM_TASK_RX_PARSER_PKT_TYPE; + struct fm_trace_t trace; + struct task_struct *task = current; + + if (fm_wcn_ops.ei.stp_recv_data) + len = fm_wcn_ops.ei.stp_recv_data(rx_buf, RX_BUF_SIZE); + WCN_DBG_LIMITED(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) { + if (i != 0) { + 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 |= (unsigned short) (ch << 0x8); + +#ifdef FM_TRACE_ENABLE + trace.type = FM_TASK_EVENT_PKT_TYPE; + trace.opcode = opcode; + trace.len = length; + trace.tid = (signed int) task->pid; + fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE); + rx_len = (length > FM_TRACE_PKT_SIZE) ? FM_TRACE_PKT_SIZE : length; + rx_len = (rx_len > (sizeof(rx_buf) - i)) ? sizeof(rx_buf) - i : rx_len; + fm_memcpy(trace.pkt, &rx_buf[i], rx_len); + + if (true == FM_TRACE_FULL(evt_fifo)) + FM_TRACE_OUT(evt_fifo, NULL); + + FM_TRACE_IN(evt_fifo, &trace); +#endif + if (length > 0) { + state = FM_TASK_RX_PARSER_PKT_PAYLOAD; + } else if (opcode == CSPI_WRITE_OPCODE) { + state = FM_TASK_RX_PARSER_PKT_TYPE; + FM_EVENT_SEND(link_event->ln_event, FLAG_CSPI_WRITE); + } 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); + + 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(unsigned short) * FM_SCANTBL_SIZE)) { + WCN_DBG(FM_ALT | LINK, + "FM_SCAN_OPCODE err, [tblsize=%d],[bufsize=%d]\n", + (unsigned int)(sizeof(unsigned short) * FM_SCANTBL_SIZE), + (unsigned int)(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(unsigned short) * 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 CSPI_READ_OPCODE: + { + if ((i + 1) < RX_BUF_SIZE) { + link_event->result.cspi_rd = + (rx_buf[i] + (rx_buf[i + 1] << 8) + + (rx_buf[i + 2] << 16) + (rx_buf[i + 3] << 24)); + } + + FM_EVENT_SEND(link_event->ln_event, FLAG_CSPI_READ); + break; + } + case FM_HOST_READ_OPCODE: + { + if ((i + 1) < RX_BUF_SIZE) { + link_event->result.cspi_rd = + (rx_buf[i] + (rx_buf[i + 1] << 8) + + (rx_buf[i + 2] << 16) + (rx_buf[i + 3] << 24)); + } + + FM_EVENT_SEND(link_event->ln_event, (1 << opcode)); + break; + } + case FM_WRITE_PMIC_CR_OPCODE: + case FM_MODIFY_PMIC_CR_OPCODE: + { + link_event->result.pmic_result[0] = rx_buf[i]; + + FM_EVENT_SEND(link_event->ln_event, FLAG_PMIC_MODIFY); + break; + } + case FM_READ_PMIC_CR_OPCODE: + { + fm_memcpy(&link_event->result.pmic_result[0], &rx_buf[i], length); + FM_EVENT_SEND(link_event->ln_event, FLAG_PMIC_READ); + 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", + (signed int) length, (RX_BUF_SIZE - i)); + FM_EVENT_SEND(link_event->ln_event, (1 << opcode)); + break; + } + + if (length > sizeof(struct rds_rx_t)) { + WCN_DBG(FM_ALT | LINK, + "RDS RX len out of range, [rxlen=%d],[needmaxlen=%zd]\n", + (signed int) length, (sizeof(struct rds_rx_t))); + 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; +} + +bool fm_wait_stc_done(unsigned int sec) +{ + return true; +} + +signed int fm_force_active_event(unsigned int mask) +{ + unsigned int 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 signed int fm_print_cmd_fifo(void) +{ +#ifdef FM_TRACE_ENABLE + struct fm_trace_t trace; + signed int i = 0; + + fm_memset(&trace, 0, sizeof(struct fm_trace_t)); + + while (false == FM_TRACE_EMPTY(cmd_fifo)) { + fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE); + FM_TRACE_OUT(cmd_fifo, &trace); + WCN_DBG_LIMITED(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_LIMITED(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_LIMITED(FM_ALT | LINK, "trace\n"); + } +#endif + + return 0; +} + +extern signed int fm_print_evt_fifo(void) +{ +#ifdef FM_TRACE_ENABLE + struct fm_trace_t trace; + signed int i = 0; + + fm_memset(&trace, 0, sizeof(struct fm_trace_t)); + + while (false == FM_TRACE_EMPTY(evt_fifo)) { + fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE); + FM_TRACE_OUT(evt_fifo, &trace); + WCN_DBG_LIMITED(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_LIMITED(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_LIMITED(FM_ALT | LINK, "%s\n", evt_fifo->name); + } +#endif + + return 0; +} + +signed int fm_trace_in(struct fm_trace_fifo_t *thiz, struct fm_trace_t *new_tra) +{ + if (new_tra == NULL) { + WCN_DBG(FM_ERR | LINK, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + 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 | LINK, "tra buf is full\n"); + return -FM_ENOMEM; + } + + return 0; +} + +signed int 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 | LINK, "del a tra[len=%d]\n", thiz->len); */ + } else { + WCN_DBG(FM_WAR | LINK, "tra buf is empty\n"); + } + + return 0; +} + +bool fm_trace_is_full(struct fm_trace_fifo_t *thiz) +{ + return (thiz->len == thiz->size) ? true : false; +} + +bool fm_trace_is_empty(struct fm_trace_fifo_t *thiz) +{ + return (thiz->len == 0) ? true : false; +} + +struct fm_trace_fifo_t *fm_trace_fifo_create(const signed char *name) +{ + struct fm_trace_fifo_t *tmp; + + tmp = fm_zalloc(sizeof(struct fm_trace_fifo_t)); + if (!tmp) { + WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_trace_fifo) -ENOMEM\n"); + return NULL; + } + + fm_memcpy(tmp->name, name, (strlen(name) + 1)); + 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; +} + +signed int 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/misc/mediatek/connectivity/fmradio/core/fm_main.c b/drivers/misc/mediatek/connectivity/fmradio/core/fm_main.c new file mode 100644 index 0000000000000..e1c5da759716f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/core/fm_main.c @@ -0,0 +1,2867 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include + +#include "fm_main.h" +#include "fm_err.h" +#include "fm_reg_utils.h" +/* #include "fm_cust_cfg.h" */ +#include "fm_cmd.h" +#include "fm_reg_utils.h" + +/* fm main data structure */ +static struct fm *g_fm_struct; +/* 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; + +/* 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; + +#if (FM_INVALID_CHAN_NOISE_REDUCING) +static struct fm_timer *fm_cqi_check_timer; +#endif + +static bool scan_stop_flag; /* false */ +static struct fm_gps_rtc_info gps_rtc_info; +static bool g_fm_stat[3] = { + false, /* RX power */ + false, /* TX power */ + false, /* TX scan */ +}; + +/* chipid porting table */ +static struct fm_chip_mapping fm_support_chip_array[] = { +{ 0x6572, 0x6627, FM_AD_DIE_CHIP }, +{ 0x6582, 0x6627, FM_AD_DIE_CHIP }, +{ 0x6592, 0x6627, FM_AD_DIE_CHIP }, +{ 0x8127, 0x6627, FM_AD_DIE_CHIP }, +{ 0x6571, 0x6627, FM_AD_DIE_CHIP }, +{ 0x6752, 0x6627, FM_AD_DIE_CHIP }, +{ 0x0321, 0x6627, FM_AD_DIE_CHIP }, +{ 0x0335, 0x6627, FM_AD_DIE_CHIP }, +{ 0x0337, 0x6627, FM_AD_DIE_CHIP }, +{ 0x6735, 0x6627, FM_AD_DIE_CHIP }, +{ 0x8163, 0x6627, FM_AD_DIE_CHIP }, +{ 0x6755, 0x6627, FM_AD_DIE_CHIP }, +{ 0x0326, 0x6627, FM_AD_DIE_CHIP }, +{ 0x6570, 0x0633, FM_SOC_CHIP }, +{ 0x6580, 0x6580, FM_SOC_CHIP }, +{ 0x6630, 0x6630, FM_COMBO_CHIP }, +{ 0x6797, 0x6631, FM_AD_DIE_CHIP }, +{ 0x6759, 0x6631, FM_AD_DIE_CHIP }, +{ 0x6758, 0x6631, FM_AD_DIE_CHIP }, +{ 0x6632, 0x6632, FM_COMBO_CHIP }, +{ 0x6757, 0x6627, FM_AD_DIE_CHIP }, +{ 0x6763, 0x6627, FM_AD_DIE_CHIP }, +{ 0x6765, 0x6631, FM_AD_DIE_CHIP }, +{ 0x6761, 0x6631, FM_AD_DIE_CHIP }, +{ 0x6739, 0x6627, FM_AD_DIE_CHIP }, +{ 0x3967, 0x6631, FM_AD_DIE_CHIP }, +{ 0x6771, 0x6631, FM_AD_DIE_CHIP }, +{ 0x6775, 0x6631, FM_AD_DIE_CHIP }, +{ 0x6768, 0x6631, FM_AD_DIE_CHIP }, +{ 0x6779, 0x6635, FM_AD_DIE_CHIP }, +}; + +unsigned char top_index; + +/* RDS reset related functions */ +static unsigned short fm_cur_freq_get(void); +static signed int fm_cur_freq_set(unsigned short 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); +#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE +static void fm_timer_func(struct timer_list *timer); +#else +static void fm_timer_func(unsigned long data); +#endif +static void fm_enable_rds_BlerCheck(struct fm *fm); +static void fm_disable_rds_BlerCheck(void); +static void fm_rds_reset_work_func(struct work_struct *work); +/* 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(struct work_struct *work); +static signed int pwrdown_flow(struct fm *fm); + +static unsigned short fm_cur_freq_get(void) +{ + return g_fm_struct ? g_fm_struct->cur_freq : 0; +} + +static signed int fm_cur_freq_set(unsigned short new_freq) +{ + if (g_fm_struct) + g_fm_struct->cur_freq = new_freq; + + return 0; +} + +static signed int fm_projectid_get(void) +{ + return g_fm_struct ? g_fm_struct->projectid : 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; + } + + WCN_DBG(FM_ERR | MAIN, "op state get para error\n"); + return FM_STA_UNKNOWN; +} + +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; + } + + WCN_DBG(FM_ERR | MAIN, "op state set para error, %d\n", sta); + return FM_STA_UNKNOWN; +} + +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; + } + + 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_DBG | MAIN, "pwr state set to %d\n", sta); + return fmp->pwr_sta; + } + + WCN_DBG(FM_ERR | MAIN, "pwr state set para error, %d\n", sta); + return FM_PWR_MAX; +} + +signed int fm_set_stat(struct fm *fmp, int which, bool stat) +{ + signed int ret = 0; + + if (fmp == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + if (which >= 0 && which < ARRAY_SIZE(g_fm_stat)) { + g_fm_stat[which] = stat; + WCN_DBG(FM_DBG | MAIN, "fm set stat object=%d, stat=%d\n", which, stat); + } else { + ret = -1; + WCN_DBG(FM_ERR | MAIN, "fm set stat error, object=%d, stat=%d\n", which, stat); + } + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +signed int fm_get_stat(struct fm *fmp, int which, bool *stat) +{ + signed int ret = 0; + + if (fmp == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (stat == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + if (which >= 0 && which < ARRAY_SIZE(g_fm_stat)) { + *stat = g_fm_stat[which]; + WCN_DBG(FM_DBG | MAIN, "fm get stat object=%d, stat=%d\n", which, *stat); + } else { + ret = -1; + WCN_DBG(FM_ERR | MAIN, "fm get stat error, object=%d\n", which); + } + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +static signed int subsys_rst_state = FM_SUBSYS_RST_OFF; + +signed int fm_sys_state_get(struct fm *fmp) +{ + return subsys_rst_state; +} + +signed int fm_sys_state_set(struct fm *fmp, signed int 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; +} + +signed int 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; + } + + if (fm == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + fm->timer_wkthd->add_work(fm->timer_wkthd, fm->rst_wk); + +out: + return 0; +} + +signed int fm_wholechip_rst_cb(signed int 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 if (sta == 2) { + if (fm_sys_state_get(fm) == FM_SUBSYS_RST_START) + fm_sys_state_set(fm, FM_SUBSYS_RST_OFF); + } else + fm->timer_wkthd->add_work(fm->timer_wkthd, fm->rst_wk); + + return 0; +} + +static signed int fm_which_chip(unsigned short chipid, enum fm_cfg_chip_type *type) +{ + signed short fm_chip = -1; + signed short i = 0; + + if (fm_wcn_ops.ei.get_get_adie) { + fm_chip = (signed short)fm_wcn_ops.ei.get_get_adie(); + if (fm_chip == 0x6631 || fm_chip == 0x6635) { + if (type) + *type = FM_AD_DIE_CHIP; + return fm_chip; + } + } + + for (i = 0; i < (sizeof(fm_support_chip_array)/sizeof(struct fm_chip_mapping)); i++) { + if (chipid == fm_support_chip_array[i].con_chip) { + fm_chip = fm_support_chip_array[i].fm_chip; + break; + } + } + + if (type) { + for (i = 0; i < (sizeof(fm_support_chip_array)/sizeof(struct fm_chip_mapping)); i++) { + if (chipid == fm_support_chip_array[i].fm_chip) { + *type = fm_support_chip_array[i].type; + break; + } + } + } + + return fm_chip; +} + +signed int fm_open(struct fm *fmp) +{ + signed int ret = 0; + signed int chipid = 0; + + if (fmp == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + if (fmp->chipon == false) { + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + if (fm_wcn_ops.ei.wmt_chipid_query) + chipid = fm_wcn_ops.ei.wmt_chipid_query(); + fmp->projectid = chipid; + WCN_DBG(FM_NTC | MAIN, "wmt chip id=0x%x\n", chipid); + + if (fm_wcn_ops.ei.get_top_index) + top_index = fm_wcn_ops.ei.get_top_index(); + else + top_index = 4; + WCN_DBG(FM_NTC | MAIN, "mcu top index = 0x%x\n", top_index); + /* what's the purpose of put chipid to fmp->chip_id ? */ + fmp->chip_id = fm_which_chip(chipid, NULL); + WCN_DBG(FM_NTC | MAIN, "fm chip id=0x%x\n", fmp->chip_id); + + fm_eint_pin_cfg(FM_EINT_PIN_EINT_MODE); + fm_request_eint(fm_eint_handler); + + FM_UNLOCK(fm_ops_lock); + } + return ret; +} + +signed int fm_close(struct fm *fmp) +{ + signed int ret = 0; + + if (fmp == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + fm_eint_pin_cfg(FM_EINT_PIN_GPIO_MODE); + + FM_UNLOCK(fm_ops_lock); + + return ret; +} + +signed int fm_rds_read(struct fm *fmp, signed char *dst, signed int len) +{ + signed int copy_len = 0, left = 0; + + copy_len = sizeof(struct rds_t); + + if (FM_EVENT_GET(fmp->rds_event) == FM_RDS_DATA_READY) { + if (FM_LOCK(fm_read_lock)) + return -FM_ELOCK; + + left = copy_to_user((void *)dst, fmp->pstRDSData, (unsigned long)copy_len); + if (left) + 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; + * } *//*event wait caused AP stop RDS thread and re-read RDS, which caused issue ALPS00595367 */ + + WCN_DBG(FM_DBG | MAIN, "fm_read no event now\n"); + return 0; + } + + return copy_len - left; +} + +signed int fm_powerup(struct fm *fm, struct fm_tune_parm *parm) +{ + signed int ret = 0; + unsigned char tmp_vol; + + if (fm_low_ops.bi.pwron == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (fm_low_ops.bi.pwrupseq == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + /* for normal case */ + if (fm_low_ops.bi.pwron == NULL) { + WCN_DBG(FM_NTC | MAIN, "get fm_low_ops fail\n"); + ret = -ENODEV; + goto out; + } + + if (fm->chipon == false) { + ret = fm_low_ops.bi.pwron(0); + if (ret) { + ret = -ENODEV; + goto out; + } + fm->chipon = true; + } + + if (fm_pwr_state_get(fm) == FM_PWR_RX_ON) { + WCN_DBG(FM_NTC | MAIN, "already pwron!\n"); + goto out; + } else if (fm_pwr_state_get(fm) == FM_PWR_TX_ON) { + /* if Tx is on, we need pwr down TX first */ + WCN_DBG(FM_NTC | MAIN, "power down TX first!\n"); + + 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) { + fm_pwr_state_set(fm, FM_PWR_OFF); + WCN_DBG(FM_ERR | MAIN, "powerup fail!!!\n"); + goto out; + } + + fm_cur_freq_set(parm->freq); + + parm->err = FM_SUCCESS; + if (fm_low_ops.bi.low_pwr_wa) + fm_low_ops.bi.low_pwr_wa(1); + + fm_low_ops.bi.volget(&tmp_vol); + WCN_DBG(FM_INF | MAIN, "vol=%d!!!\n", tmp_vol); + + /* fm_low_ops.bi.volset(0); */ + 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); + } else { + WCN_DBG(FM_NTC | MAIN, "start timer fail!!!\n"); + } + +out: + FM_UNLOCK(fm_ops_lock); + return ret; +} + +/* + * fm_powerup_tx + */ +signed int fm_powerup_tx(struct fm *fm, struct fm_tune_parm *parm) +{ + signed int ret = 0; + + if (fm_low_ops.bi.pwron == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (fm_low_ops.bi.pwrupseq_tx == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + if (fm_pwr_state_get(fm) == FM_PWR_TX_ON) { + WCN_DBG(FM_NTC | MAIN, "already pwron!\n"); + parm->err = FM_BADSTATUS; + goto out; + } else if (fm_pwr_state_get(fm) == FM_PWR_RX_ON) { + /* if Rx is on, we need pwr down first */ + ret = fm_powerdown(fm, 0); + 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 == false) { + fm_low_ops.bi.pwron(0); + fm->chipon = true; + } + + fm_pwr_state_set(fm, FM_PWR_TX_ON); + ret = fm_low_ops.bi.pwrupseq_tx(); + + if (ret) { + parm->err = FM_FAILED; + fm_pwr_state_set(fm, FM_PWR_OFF); + WCN_DBG(FM_ERR | MAIN, "FM pwr up Tx fail!\n"); + } else { + parm->err = FM_SUCCESS; + } + fm_cur_freq_set(parm->freq); + +out: + FM_UNLOCK(fm_ops_lock); + return ret; +} + +static signed int pwrdown_flow(struct fm *fm) +{ + signed int ret = 0; + + if (fm_low_ops.ri.rds_onoff == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (fm_low_ops.bi.pwrdownseq == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + if (fm_pwr_state_get(fm) == FM_PWR_OFF) { + WCN_DBG(FM_NTC | MAIN, "FMSYS already pwroff!\n"); + goto out; + } + + if (fm_pwr_state_get(fm) == FM_PWR_RX_ON) { + /* Disable all interrupt */ + fm_disable_rds_BlerCheck(); + fm_low_ops.ri.rds_onoff(fm->pstRDSData, false); + + fm_pwr_state_set(fm, FM_PWR_OFF); + + /* execute power down sequence */ + ret = fm_low_ops.bi.pwrdownseq(); + + if (fm_low_ops.bi.low_pwr_wa) + fm_low_ops.bi.low_pwr_wa(0); + + WCN_DBG(FM_ALT | MAIN, "pwrdown_flow exit\n"); + } +out: + return ret; +} + +signed int fm_powerdown(struct fm *fm, int type) +{ + signed int ret = 0; + +#if (FM_INVALID_CHAN_NOISE_REDUCING) + fm_cqi_check_timer->stop(fm_cqi_check_timer); +#endif + + if (type == 1) { /* 0: RX 1: TX */ + 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); + } + + if ((fm_pwr_state_get(fm) == FM_PWR_OFF) && (fm->chipon == true)) { + fm_low_ops.bi.pwroff(0); + fm->chipon = false; + } + + return ret; +} + +signed int fm_powerdowntx(struct fm *fm) +{ + signed int ret = 0; + + if (fm_low_ops.bi.pwrdownseq_tx == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (FM_LOCK(fm_rxtx_lock)) + return -FM_ELOCK; + + if (fm_pwr_state_get(fm) == FM_PWR_TX_ON) { + /* fm_low_ops.ri.rds_onoff(fm->pstRDSData, false); */ + /* execute power down sequence */ + ret = fm_low_ops.bi.pwrdownseq_tx(); + if (ret) + WCN_DBG(FM_ERR | MAIN, "pwrdown tx 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; +} + +/*********************************************************** +* Function: fm_tx_scan() +* +* Description: get the valid channels for fm tx function +* +* Para: fm--->fm driver global info +* parm--->input/output parameter +* +* Return: 0, if success; error code, if failed +***********************************************************/ +signed int fm_tx_scan(struct fm *fm, struct fm_tx_scan_parm *parm) +{ + signed int ret = 0; + unsigned short scandir = 0; + unsigned short space = parm->space; + + if (fm_low_ops.bi.tx_scan == NULL) { + pr_err("%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + if (fm->chipon != 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->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; + WCN_DBG(FM_ERR | MAIN, "%s parm->freq:%d fm->min_freq: %d fm->max_freq:%d\n", + __func__, parm->freq, fm->min_freq, fm->max_freq); + goto out; + } + + if (unlikely(parm->ScanTBLSize < TX_SCAN_MIN || parm->ScanTBLSize > TX_SCAN_MAX)) { + parm->err = FM_EPARM; + ret = -EPERM; + WCN_DBG(FM_ERR | MAIN, "%s parm->ScanTBLSize:%d TX_SCAN_MIN:%d TX_SCAN_MAX:%d\n", + __func__, parm->ScanTBLSize, TX_SCAN_MIN, TX_SCAN_MAX); + 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 */ + ret = fm_low_ops.bi.tx_scan(fm->min_freq, fm->max_freq, &(parm->freq), + parm->ScanTBL, &(parm->ScanTBLSize), scandir, space); + if (!ret) { + 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; +} + +signed int fm_cqi_get(struct fm *fm, signed int ch_num, signed char *buf, signed int buf_size) +{ + signed int ret = 0; + signed int idx = 0; + + if (fm_low_ops.bi.cqi_get == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + if (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. + */ +signed int fm_is_dese_chan(struct fm *pfm, unsigned short freq) +{ + signed int ret = 0; + + if (pfm == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + 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. + */ +signed int fm_desense_check(struct fm *pfm, unsigned short freq, signed int rssi) +{ + signed int ret = 0; + + if (pfm == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + 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; +} + +signed int fm_dump_reg(void) +{ + signed int 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. + */ +signed int fm_get_hw_info(struct fm *pfm, struct fm_hw_info *req) +{ + signed int ret = 0; + + if (req == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + /* 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; +} + +signed int fm_get_aud_info(struct fm_audio_info_t *data) +{ + if (fm_low_ops.bi.get_aud_info) + return fm_low_ops.bi.get_aud_info(data); + + data->aud_path = FM_AUD_ERR; + data->i2s_info.mode = FM_I2S_MODE_ERR; + data->i2s_info.status = FM_I2S_STATE_ERR; + data->i2s_info.rate = FM_I2S_SR_ERR; + data->i2s_pad = FM_I2S_PAD_ERR; + return 0; +} + +/* fm_get_i2s_info -- i2s info: on/off, master/slave, sample rate + * @pfm - fm driver global DS + * @req - target buffer + * return value: 0, success; else error NO. + */ +signed int fm_get_i2s_info(struct fm *pfm, struct fm_i2s_info *req) +{ + if (fm_low_ops.bi.i2s_get == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + return fm_low_ops.bi.i2s_get(&req->status, &req->mode, &req->rate); +} + +signed int fm_hwscan_stop(struct fm *fm) +{ + signed int ret = 0; + + if ((fm_op_state_get(fm) != FM_STA_SCAN) && (fm_op_state_get(fm) != FM_STA_SEEK)) { + WCN_DBG(FM_WAR | MAIN, "fm isn't on scan, no need stop\n"); + return ret; + } + + if (fm_low_ops.bi.scanstop == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + fm_low_ops.bi.scanstop(); + fm_low_ops.bi.seekstop(); + scan_stop_flag = 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 + */ +signed int fm_ana_switch(struct fm *fm, signed int antenna) +{ + signed int ret = 0; + + if (fm_low_ops.bi.anaswitch == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + 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; + + if ((fm_pwr_state_get(fm) == FM_PWR_RX_ON) || (fm_pwr_state_get(fm) == FM_PWR_TX_ON)) + 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] */ +signed int fm_setvol(struct fm *fm, unsigned int vol) +{ + unsigned char tmp_vol; + + if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) + return -EPERM; + + if (fm_low_ops.bi.volset == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + tmp_vol = (vol > 15) ? 15 : vol; + fm_low_ops.bi.volset(tmp_vol); + fm->vol = (signed int) tmp_vol; + + FM_UNLOCK(fm_ops_lock); + return 0; +} + +signed int fm_getvol(struct fm *fm, unsigned int *vol) +{ + unsigned char tmp_vol; + + if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) + return -EPERM; + + if (fm_low_ops.bi.volget == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + fm_low_ops.bi.volget(&tmp_vol); + *vol = (unsigned int) tmp_vol; + + FM_UNLOCK(fm_ops_lock); + return 0; +} + +signed int fm_mute(struct fm *fm, unsigned int bmute) +{ + signed int ret = 0; + + if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) { + ret = -EPERM; + return ret; + } + if (fm_low_ops.bi.mute == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + if (bmute) { + ret = fm_low_ops.bi.mute(true); + fm->mute = true; + } else { + ret = fm_low_ops.bi.mute(false); + fm->mute = false; + } + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +signed int fm_getrssi(struct fm *fm, signed int *rssi) +{ + signed int ret = 0; + + if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) { + ret = -EPERM; + return ret; + } + if (fm_low_ops.bi.rssiget == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + ret = fm_low_ops.bi.rssiget(rssi); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +signed int fm_read(struct fm *fm, unsigned char addr, unsigned short *val) +{ + signed int ret = 0; + + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + ret = fm_reg_read(addr, val); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +signed int fm_write(struct fm *fm, unsigned char addr, unsigned short val) +{ + signed int ret = 0; + + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + ret = fm_reg_write(addr, val); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +signed int fm_top_read(struct fm *fm, unsigned short addr, unsigned int *val) +{ + signed int ret = 0; + + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + ret = fm_top_reg_read(addr, val); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +signed int fm_top_write(struct fm *fm, unsigned short addr, unsigned int val) +{ + signed int ret = 0; + + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + ret = fm_top_reg_write(addr, val); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +signed int fm_host_read(struct fm *fm, unsigned int addr, unsigned int *val) +{ + signed int ret = 0; + + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + ret = fm_host_reg_read(addr, val); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +signed int fm_host_write(struct fm *fm, unsigned int addr, unsigned int val) +{ + signed int ret = 0; + + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + ret = fm_host_reg_write(addr, val); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +signed int fm_pmic_read(struct fm *fm, unsigned char addr, unsigned int *val) +{ + signed int ret = 0; + + if (fm_low_ops.bi.pmic_read == NULL) { + pr_err("%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + ret = fm_low_ops.bi.pmic_read(addr, val); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +signed int fm_pmic_write(struct fm *fm, unsigned char addr, unsigned int val) +{ + signed int ret = 0; + + if (fm_low_ops.bi.pmic_write == NULL) { + pr_err("%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + ret = fm_low_ops.bi.pmic_write(addr, val); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +signed int fm_chipid_get(struct fm *fm, unsigned short *chipid) +{ + if (chipid == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + *chipid = fm->chip_id; + + FM_UNLOCK(fm_ops_lock); + return 0; +} + +signed int fm_monostereo_get(struct fm *fm, unsigned short *ms) +{ + signed int ret = 0; + + if (fm_low_ops.bi.msget == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (ms == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + if (fm_low_ops.bi.msget(ms) == 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 + */ +signed int fm_monostereo_set(struct fm *fm, signed int ms) +{ + signed int ret = 0; + + if (fm_low_ops.bi.msset == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + ret = fm_low_ops.bi.msset(ms); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +signed int fm_pamd_get(struct fm *fm, unsigned short *pamd) +{ + signed int ret = 0; + + if (fm_low_ops.bi.pamdget == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (pamd == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + if (fm_low_ops.bi.pamdget(pamd) == false) + ret = -FM_EPARA; + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +signed int fm_caparray_get(struct fm *fm, signed int *ca) +{ + signed int ret = 0; + + if (fm_low_ops.bi.caparray_get == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (ca == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + ret = fm_low_ops.bi.caparray_get(ca); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +signed int fm_em_test(struct fm *fm, unsigned short group, unsigned short item, unsigned int val) +{ + signed int ret = 0; + + if (fm_low_ops.bi.em == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + if (false == fm_low_ops.bi.em(group, item, val)) + ret = -FM_EPARA; + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +signed int fm_set_search_th(struct fm *fm, struct fm_search_threshold_t parm) +{ + signed int ret = 0; + + if (fm_low_ops.bi.set_search_th == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + ret = fm_low_ops.bi.set_search_th(parm.th_type, parm.th_val, parm.reserve); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +signed int fm_rds_tx(struct fm *fm, struct fm_rds_tx_parm *parm) +{ + signed int ret = 0; + + if (fm_low_ops.ri.rds_tx == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + 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(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; +} + +signed int fm_rds_onoff(struct fm *fm, unsigned short rdson_off) +{ + signed int ret = 0; + + if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) { + ret = -EPERM; + goto out; + } + if (fm_low_ops.ri.rds_onoff == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + if (rdson_off) { + fm->rds_on = true; + if (fm_low_ops.ri.rds_onoff(fm->pstRDSData, true) == false) { + WCN_DBG(FM_ALT | MAIN, "FM_IOCTL_RDS_ONOFF on faield\n"); + ret = -EPERM; + goto out; + } + + fm_enable_rds_BlerCheck(fm); + } else { + fm->rds_on = false; + fm_disable_rds_BlerCheck(); + if (fm_low_ops.ri.rds_onoff(fm->pstRDSData, false) == false) { + WCN_DBG(FM_ALT | MAIN, "FM_IOCTL_RDS_ONOFF off faield\n"); + ret = -EPERM; + }; + } + +out: + FM_UNLOCK(fm_ops_lock); + return ret; +} + +signed int fm_rds_good_bc_get(struct fm *fm, unsigned short *gbc) +{ + signed int ret = 0; + + if (fm_low_ops.ri.rds_gbc_get == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (gbc == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + *gbc = fm_low_ops.ri.rds_gbc_get(); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +signed int fm_rds_bad_bc_get(struct fm *fm, unsigned short *bbc) +{ + signed int ret = 0; + + if (fm_low_ops.ri.rds_gbc_get == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (bbc == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + *bbc = fm_low_ops.ri.rds_bbc_get(); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +signed int fm_rds_bler_ratio_get(struct fm *fm, unsigned short *bbr) +{ + signed int ret = 0; + + if (fm_low_ops.ri.rds_bbr_get == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (bbr == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + *bbr = (unsigned short) fm_low_ops.ri.rds_bbr_get(); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +signed int fm_rds_group_cnt_get(struct fm *fm, struct rds_group_cnt_t *dst) +{ + signed int ret = 0; + + if (fm_low_ops.ri.rds_gc_get == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (dst == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + 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; +} + +signed int fm_rds_group_cnt_reset(struct fm *fm) +{ + signed int ret = 0; + + if (fm_low_ops.ri.rds_gc_reset == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + 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; +} + +signed int fm_rds_log_get(struct fm *fm, struct rds_rx_t *dst, signed int *dst_len) +{ + signed int ret = 0; + + if (fm_low_ops.ri.rds_log_get == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (dst == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (dst_len == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + 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; +} + +signed int fm_rds_block_cnt_reset(struct fm *fm) +{ + signed int ret = 0; + + if (fm_low_ops.ri.rds_bc_reset == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + ret = fm_low_ops.ri.rds_bc_reset(); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +signed int fm_i2s_set(struct fm *fm, signed int onoff, signed int mode, signed int sample) +{ + signed int ret = 0; + + if (fm_low_ops.bi.i2s_set == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if ((onoff != 0) && (onoff != 1)) + onoff = 0; /* default set i2s on in case user input illegal.*/ + + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + if ((fm_pwr_state_get(fm) == FM_PWR_RX_ON) || (fm_pwr_state_get(fm) == FM_PWR_TX_ON)) + ret = fm_low_ops.bi.i2s_set(onoff, mode, sample); + if (ret) + WCN_DBG(FM_ALT | MAIN, "i2s setting Failed\n"); + else + WCN_DBG(FM_INF | MAIN, "i2s setting OK!\n"); + + FM_UNLOCK(fm_ops_lock); + return ret; +} + +/* + * fm_tune_tx + */ +signed int fm_tune_tx(struct fm *fm, struct fm_tune_parm *parm) +{ + signed int ret = 0; + + if (fm_low_ops.bi.tune_tx == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + 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); + /* tune to desired channel */ + if (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 + */ +signed int fm_tune(struct fm *fm, struct fm_tune_parm *parm) +{ + signed int ret = 0; + signed int len = 0; + struct rds_raw_t rds_log; + +#if (FM_INVALID_CHAN_NOISE_REDUCING) + fm_cqi_check_timer->stop(fm_cqi_check_timer); +#endif + + if (fm_low_ops.bi.mute == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (fm_low_ops.bi.rampdown == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (fm_low_ops.bi.setfreq == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + WCN_DBG(FM_INF | MAIN, "%s\n", __func__); + + /* clean RDS first in case RDS event report before tune success */ + /* clean RDS data */ + fm_memset(fm->pstRDSData, 0, sizeof(struct rds_t)); + + /* clean RDS log buffer */ + do { + 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); + WCN_DBG(FM_ALT | MAIN, "clean rds log, rds_log.len =%d\n", rds_log.len); + if (ret < 0) + break; + } while (rds_log.len > 0); + + if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) { + parm->err = FM_BADSTATUS; + ret = -EPERM; + goto out; + } +/* fm_low_ops.bi.mute(true); */ + ret = fm_low_ops.bi.rampdown(); + if (ret) { + WCN_DBG(FM_ALT | MAIN, "FM ramp down failed\n"); + goto out; + } + + fm_op_state_set(fm, FM_STA_TUNE); + WCN_DBG(FM_ALT | MAIN, "tuning to %d\n", parm->freq); + + if (true != fm_low_ops.bi.setfreq(parm->freq)) { + parm->err = FM_TUNE_FAILED; + WCN_DBG(FM_ALT | MAIN, "FM tune failed\n"); + ret = -FM_EFW; + } + +#if (FM_INVALID_CHAN_NOISE_REDUCING) + if (fm_low_ops.bi.is_valid_freq) { + if (fm_low_ops.bi.is_valid_freq(parm->freq)) { + if (fm->vol != 15) { + fm_low_ops.bi.volset(15); + fm->vol = 15; + WCN_DBG(FM_NTC | MAIN, "Valid freq, volset: 15\n"); + } + WCN_DBG(FM_NTC | MAIN, "FM tune to a valid channel resume volume.\n"); + } else { + if (fm->vol != 5) { + fm_low_ops.bi.volset(5); + fm->vol = 5; + WCN_DBG(FM_NTC | MAIN, "Not a valid freq, volset: 5\n"); + } + WCN_DBG(FM_NTC | MAIN, "FM tune to an invalid channel.\n"); + fm_cqi_check_timer->start(fm_cqi_check_timer); + } + } +#endif + /* fm_low_ops.bi.mute(false);//open for dbg */ + fm_op_state_set(fm, FM_STA_PLAY); +out: + FM_UNLOCK(fm_ops_lock); + return ret; +} + +/* cqi log tool entry */ +signed int fm_cqi_log(void) +{ + signed int ret = 0; + unsigned short freq; + + if (fm_low_ops.bi.cqi_log == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + freq = fm_cur_freq_get(); + if (fm_get_channel_space(freq) == 0) + freq *= 10; + + if ((freq != 10000) && (g_dbg_level != 0xffffffff)) + 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; +} + +signed int fm_pre_search(struct fm *fm) +{ + signed int ret = 0; + + if (fm_low_ops.bi.pre_search == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) + return -FM_EPARA; + + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + WCN_DBG(FM_INF | MAIN, "%s\n", __func__); + + ret = fm_low_ops.bi.pre_search(); + FM_UNLOCK(fm_ops_lock); + return ret; +} + +signed int fm_restore_search(struct fm *fm) +{ + signed int ret = 0; + + if (fm_low_ops.bi.restore_search == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) + return -FM_EPARA; + + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + WCN_DBG(FM_INF | MAIN, "%s\n", __func__); + + ret = fm_low_ops.bi.restore_search(); + FM_UNLOCK(fm_ops_lock); + return ret; +} + +/*fm soft mute tune function*/ +signed int fm_soft_mute_tune(struct fm *fm, struct fm_softmute_tune_t *parm) +{ + signed int ret = 0; + +#if (FM_INVALID_CHAN_NOISE_REDUCING) + fm_cqi_check_timer->stop(fm_cqi_check_timer); +#endif + + if (fm_low_ops.bi.softmute_tune == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + + if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) { + parm->valid = false; + ret = -EPERM; + goto out; + } + /* fm_low_ops.bi.mute(true); */ + /* fm_op_state_set(fm, FM_STA_TUNE); */ + + if (false == fm_low_ops.bi.softmute_tune(parm->freq, &parm->rssi, &parm->valid)) { + parm->valid = false; + WCN_DBG(FM_ALT | MAIN, "sm tune failed\n"); + ret = -EPERM; + } +/* fm_low_ops.bi.mute(false); */ + WCN_DBG(FM_INF | MAIN, "%s, freq=%d, rssi=%d, valid=%d\n", __func__, parm->freq, parm->rssi, parm->valid); + +out: + FM_UNLOCK(fm_ops_lock); + + return ret; +} + +signed int fm_over_bt(struct fm *fm, signed int flag) +{ + signed int ret = 0; + + if (fm_low_ops.bi.fm_via_bt == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + 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; +} + +signed int fm_tx_support(struct fm *fm, signed int *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; +} + +signed int fm_rdstx_support(struct fm *fm, signed int *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; +} + +/*1:on,0:off*/ +signed int fm_rdstx_enable(struct fm *fm, signed int enable) +{ + signed int ret = -1; + + if (fm_low_ops.ri.rds_tx_enable == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (fm_low_ops.ri.rds_tx_disable == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + if (fm_pwr_state_get(fm) != FM_PWR_TX_ON) + return -FM_EPARA; + + if (FM_LOCK(fm_ops_lock)) + return -FM_ELOCK; + if (enable == 1) { + ret = fm_low_ops.ri.rds_tx_enable(); + if (ret) + WCN_DBG(FM_ERR | MAIN, "rds_tx_enable fail=[%d]!\n", ret); + + fm->rdstx_on = true; + } else { + ret = fm_low_ops.ri.rds_tx_disable(); + if (ret) + WCN_DBG(FM_ERR | MAIN, "rds_tx_disable fail=[%d]!\n", ret); + + fm->rdstx_on = false; + } + WCN_DBG(FM_NTC | MAIN, "rds tx enable=[%d]!\n", enable); + FM_UNLOCK(fm_ops_lock); + return 0; +} + +#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE +static void fm_timer_func(struct timer_list *timer) +#else +static void fm_timer_func(unsigned long data) +#endif +{ + 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 stopped before timeout */ + } + + if (fm != NULL) { + WCN_DBG(FM_DBG | MAIN, "timer:rds_wk\n"); + fm->timer_wkthd->add_work(fm->timer_wkthd, fm->rds_wk); + } + +out: + FM_UNLOCK(fm_timer_lock); +} + +#if (FM_INVALID_CHAN_NOISE_REDUCING) +#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE +static void fm_cqi_check_timer_func(struct timer_list *timer) +#else +static void fm_cqi_check_timer_func(unsigned long data) +#endif +{ + struct fm *fm = g_fm_struct; + + if (FM_LOCK(fm_timer_lock)) + return; + + if (fm_cqi_check_timer->update(fm_cqi_check_timer)) { + WCN_DBG(FM_NTC | MAIN, "timer skip\n"); + goto out; /* fm timer is stopped before timeout */ + } + + if (fm != NULL) { + WCN_DBG(FM_DBG | MAIN, "timer:ch_valid_check_wk\n"); + fm->timer_wkthd->add_work(fm->timer_wkthd, fm->ch_valid_check_wk); + } + +out: + FM_UNLOCK(fm_timer_lock); +} +#endif + +static void fm_tx_power_ctrl_worker_func(struct work_struct *work) +{ + signed int 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__); +} + +static void fm_tx_rtc_ctrl_worker_func(struct work_struct *work) +{ + signed int ret = 0; + signed int 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; + } + + 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); + + ret = fm_low_ops.bi.rtc_drift_ctrl(fm_cur_freq_get(), &ctrl); + if (ret) + goto out; + } +out: + WCN_DBG(FM_NTC | MAIN, "-%s()\n", __func__); +} + +static void fm_tx_desense_wifi_worker_func(struct work_struct *work) +{ + signed int ret = 0; + signed int 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__); +} + +/* +************************************************************************************ +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 +************************************************************************************ +*/ +signed int fm_get_gps_rtc_info(struct fm_gps_rtc_info *src) +{ + signed int ret = 0; +/* signed int retry_cnt = 0; */ + struct fm_gps_rtc_info *dst = &gps_rtc_info; + + if (src == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (dst == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + 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__, (signed int) 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); + + +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); + WCN_DBG(FM_INF | MAIN, "enable rds timer ok\n"); +} + +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); + WCN_DBG(FM_INF | MAIN, "stop rds timer ok\n"); +} + +void fm_rds_reset_work_func(struct work_struct *work) +{ + signed int 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); + + if (ret || g_fm_struct->pstRDSData->AF_Data.Addr_Cnt || g_fm_struct->pstRDSData->event_status) { + WCN_DBG(FM_NTC | MAIN, "ret=%d, Addr_Cnt=0x%02x, event_status=0x%04x\n", ret, + g_fm_struct->pstRDSData->AF_Data.Addr_Cnt, g_fm_struct->pstRDSData->event_status); + } + /* check af list get,can't use event==af_list because event will clear after read rds every time */ + if (g_fm_struct->pstRDSData->AF_Data.Addr_Cnt == 0xFF) + 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); + + FM_UNLOCK(fm_rds_cnt); + FM_UNLOCK(fm_rxtx_lock); +} + +#if (FM_INVALID_CHAN_NOISE_REDUCING) +void fm_cqi_check_work_func(struct work_struct *work) +{ + struct fm *fm = g_fm_struct; + + if (!fm) + return; + + if (FM_LOCK(fm_ops_lock)) + return; + + if (fm_low_ops.bi.is_valid_freq) { + if (fm_low_ops.bi.is_valid_freq(fm->cur_freq)) { + if (fm->vol != 15) { + fm_low_ops.bi.volset(15); + fm->vol = 15; + WCN_DBG(FM_NTC | MAIN, "Valid freq, volset: 15\n"); + } + } else { + if (fm->vol != 5) { + fm_low_ops.bi.volset(5); + fm->vol = 5; + WCN_DBG(FM_NTC | MAIN, "Not a valid freq, volset: 5\n"); + } + } + } + + FM_UNLOCK(fm_ops_lock); +} +#endif + +void fm_subsys_reset_work_func(struct work_struct *work) +{ + 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 == false) { + WCN_DBG(FM_ALT | MAIN, "chip off no need do recover\n"); + goto out; + } + + /* if whole chip reset, wmt will clear fm-on-flag, and firmware turn fm to off status, + * so no need turn fm off again + */ + if (g_fm_struct->wholechiprst == false) { + fm_low_ops.bi.pwrdownseq(); + /* subsystem power off */ + if (fm_low_ops.bi.pwroff(0)) { + WCN_DBG(FM_ALT | MAIN, "chip off fail\n"); + goto out; + } + } + + /* subsystem power on */ + if (fm_low_ops.bi.pwron(0)) { + WCN_DBG(FM_ALT | MAIN, "chip on fail\n"); + goto out; + } + /* recover context */ + if (g_fm_struct->chipon == false) { + fm_low_ops.bi.pwroff(0); + WCN_DBG(FM_ALT | MAIN, "no need do recover\n"); + goto out; + } + + if (fm_pwr_state_get(g_fm_struct) == FM_PWR_RX_ON) { + 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((unsigned char) g_fm_struct->vol); + + g_fm_struct->mute = 0; + fm_low_ops.bi.mute(g_fm_struct->mute); + + 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); + WCN_DBG(FM_NTC | MAIN, "initial timer ok\n"); + } else { + WCN_DBG(FM_NTC | MAIN, "initial timer fail!!!\n"); + } + +#if (FM_INVALID_CHAN_NOISE_REDUCING) + fm_cqi_check_timer->init(fm_cqi_check_timer, fm_cqi_check_timer_func, + (unsigned long)g_fm_struct, 1000, 0); +#endif + g_fm_struct->rds_on = 1; + 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); + g_fm_struct->wholechiprst = true; + + FM_UNLOCK(fm_ops_lock); + g_dbg_level = 0xfffffff5; +} + +void fm_pwroff_work_func(struct work_struct *work) +{ + fm_powerdown(g_fm_struct, 0); +} + +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); +} + +signed int fm_rds_parser(struct rds_rx_t *rds_raw, signed int rds_size) +{ + struct fm *fm = g_fm_struct; /* (struct fm *)work->data; */ + struct 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:0x%04x]\n", pstRDSData->event_status); + FM_EVENT_SEND(fm->rds_event, FM_RDS_DATA_READY); + } + + return 0; +} + +static void fm_eint_work_func(struct work_struct *work) +{ + if (fm_wcn_ops.ei.eint_handler) + fm_wcn_ops.ei.eint_handler(); + /* re-enable eint if need */ + fm_enable_eint(); +} + +static signed int fm_callback_register(struct fm_callback *cb) +{ + if (cb == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + cb->cur_freq_get = fm_cur_freq_get; + cb->cur_freq_set = fm_cur_freq_set; + cb->projectid_get = fm_projectid_get; + return 0; +} + +static signed int fm_ops_register(struct fm_lowlevel_ops *ops) +{ + signed int ret = 0; + + ret = fm_wcn_ops_register(); + if (ret) { + WCN_DBG(FM_ERR | MAIN, "fm_wcn_ops_register fail(%d)\n", ret); + return ret; + } + + ret = fm_callback_register(&ops->cb); + if (ret) { + WCN_DBG(FM_ERR | MAIN, "fm_callback_register fail(%d)\n", ret); + return ret; + } + + if (fm_wcn_ops.ei.low_ops_register) + ret = fm_wcn_ops.ei.low_ops_register(&ops->cb, &ops->bi); + else + ret = -1; + if (ret) { + WCN_DBG(FM_ERR | MAIN, "fm_low_ops_register fail(%d)\n", ret); + return ret; + } + + if (fm_wcn_ops.ei.rds_ops_register) + ret = fm_wcn_ops.ei.rds_ops_register(&ops->bi, &ops->ri); + else + ret = -1; + if (ret) { + WCN_DBG(FM_ERR | MAIN, "rds_ops_register fail(%d)\n", ret); + return ret; + } + + return ret; +} +static signed int fm_callback_unregister(struct fm_callback *cb) +{ + if (cb == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,cb invalid pointer\n", __func__); + return -FM_EPARA; + } + + fm_memset(cb, 0, sizeof(struct fm_callback)); + return 0; +} + +static signed int fm_ops_unregister(struct fm_lowlevel_ops *ops) +{ + signed int ret = 0; + + if (fm_wcn_ops.ei.rds_ops_unregister) + ret = fm_wcn_ops.ei.rds_ops_unregister(&ops->ri); + else + ret = -1; + if (ret) { + WCN_DBG(FM_ERR | MAIN, "fm_rds_ops_unregister fail(%d)\n", ret); + return ret; + } + + if (fm_wcn_ops.ei.low_ops_unregister) + ret = fm_wcn_ops.ei.low_ops_unregister(&ops->bi); + else + ret = -1; + if (ret) { + WCN_DBG(FM_ERR | MAIN, "fm_low_ops_unregister fail(%d)\n", ret); + return ret; + } + + ret = fm_callback_unregister(&ops->cb); + if (ret) { + WCN_DBG(FM_ERR | MAIN, "fm_callback_unregister fail(%d)\n", ret); + return ret; + } + + return ret; +} + +static signed short fm_cust_config_setting(void) +{ + unsigned short chipid = 0; + enum fm_cfg_chip_type type = FM_CHIP_TYPE_MAX; + + if (fm_low_ops.bi.chipid_get) + chipid = fm_low_ops.bi.chipid_get(); + fm_which_chip(chipid, &type); + WCN_DBG(FM_NTC | MAIN, "chipid:0x%x, chip type:%d\n", chipid, type); + + fm_cust_config_chip(chipid, type); + /* init customer config parameter */ + fm_cust_config_setup(NULL); + + return 0; +} + +struct fm *fm_dev_init(unsigned int arg) +{ + signed int ret = 0; + struct fm *fm = NULL; + +/* if (!fm_low_ops.ri.rds_bci_get) */ +/* return NULL; */ + + /* alloc fm main data structure */ + fm = fm_zalloc(sizeof(struct fm)); + if (!fm) { + WCN_DBG(FM_ALT | MAIN, "-ENOMEM\n"); + ret = -ENOMEM; + return NULL; + } + + fm->ref = 0; + fm->chipon = false; + fm_pwr_state_set(fm, FM_PWR_OFF); + /* 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; + fm->wholechiprst = true; + 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; + + fm->rds_event = fm_flag_event_create("fm_rds_event"); + if (!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 */ + fm->pstRDSData = fm_zalloc(sizeof(struct rds_t)); + if (!fm->pstRDSData) { + 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); + } + +#if (FM_INVALID_CHAN_NOISE_REDUCING) + fm->ch_valid_check_wk = fm_work_create("fm_ch_valid_check_work"); + if (!fm->ch_valid_check_wk) { + WCN_DBG(FM_ALT | MAIN, "-ENOMEM for ch_valid_check_wk\n"); + ret = -ENOMEM; + goto ERR_EXIT; + } else { + fm_work_get(fm->ch_valid_check_wk); + fm->ch_valid_check_wk->init(fm->ch_valid_check_wk, + fm_cqi_check_work_func, (unsigned long)fm); + } +#endif + + 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->pwroff_wk = fm_work_create("fm_pwroff_work"); + + if (!fm->pwroff_wk) { + WCN_DBG(FM_ALT | MAIN, "-ENOMEM for pwroff_wk\n"); + ret = -ENOMEM; + goto ERR_EXIT; + } else { + fm_work_get(fm->pwroff_wk); + fm->pwroff_wk->init(fm->pwroff_wk, fm_pwroff_work_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); */ + fm_cust_config_setting(); + + return g_fm_struct; + +ERR_EXIT: + + if (!fm) { + WCN_DBG(FM_NTC | MAIN, "fm is null\n"); + return NULL; + } + + 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->ch_valid_check_wk) { + ret = fm_work_put(fm->ch_valid_check_wk); + if (!ret) + fm->ch_valid_check_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->pwroff_wk) { + ret = fm_work_put(fm->pwroff_wk); + if (!ret) + fm->pwroff_wk = NULL; + } + + if (fm->pstRDSData) { + fm_free(fm->pstRDSData); + fm->pstRDSData = NULL; + } + + fm_free(fm); + g_fm_struct = NULL; + return NULL; +} + +signed int fm_dev_destroy(struct fm *fm) +{ + signed int ret = 0; + + WCN_DBG(FM_DBG | MAIN, "%s\n", __func__); + + fm_timer_sys->stop(fm_timer_sys); +#if (FM_INVALID_CHAN_NOISE_REDUCING) + fm_timer_sys->stop(fm_cqi_check_timer); +#endif + if (!fm) { + WCN_DBG(FM_NTC | MAIN, "fm is null\n"); + return -1; + } + + 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->ch_valid_check_wk) { + ret = fm_work_put(fm->ch_valid_check_wk); + if (!ret) + fm->ch_valid_check_wk = NULL; + } + + if (fm->rst_wk) { + ret = fm_work_put(fm->rst_wk); + if (!ret) + fm->rst_wk = NULL; + } + + if (fm->pwroff_wk) { + ret = fm_work_put(fm->pwroff_wk); + if (!ret) + fm->pwroff_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; +} + +signed int fm_env_setup(void) +{ + signed int ret = 0; + + WCN_DBG(FM_NTC | MAIN, "%s\n", __func__); + + ret = fm_ops_register(&fm_low_ops); + if (ret) + return ret; + + WCN_DBG(FM_NTC | MAIN, "fm ops registered\n"); + + + 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("rtc_lock"); + if (!fm_rxtx_lock) + return -1; + + fm_wcn_ops.tx_lock = fm_lock_create("tx_lock"); + if (!fm_wcn_ops.tx_lock) + return -1; + + fm_wcn_ops.own_lock = fm_lock_create("own_lock"); + if (!fm_wcn_ops.own_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); + fm_lock_get(fm_rtc_mutex); + fm_lock_get(fm_wcn_ops.tx_lock); + fm_lock_get(fm_wcn_ops.own_lock); + WCN_DBG(FM_NTC | MAIN, "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); + +#if (FM_INVALID_CHAN_NOISE_REDUCING) + fm_cqi_check_timer = fm_timer_create("fm_cqi_check_timer"); + if (!fm_cqi_check_timer) + return -1; + fm_timer_get(fm_cqi_check_timer); + fm_cqi_check_timer->init(fm_cqi_check_timer, fm_cqi_check_timer_func, (unsigned long)g_fm_struct, 500, 0); +#endif + + WCN_DBG(FM_NTC | MAIN, "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; +} + +signed int fm_env_destroy(void) +{ + signed int ret = 0; + + WCN_DBG(FM_NTC | MAIN, "%s\n", __func__); + + fm_link_release(); + + ret = fm_ops_unregister(&fm_low_ops); + if (ret) + return ret; + + WCN_DBG(FM_NTC | MAIN, "fm ops unregistered\n"); + + 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_lock_put(fm_rxtx_lock); + if (!ret) + fm_rxtx_lock = NULL; + + ret = fm_lock_put(fm_rtc_mutex); + if (!ret) + fm_rtc_mutex = NULL; + + ret = fm_timer_put(fm_timer_sys); + if (!ret) + fm_timer_sys = NULL; + +#if (FM_INVALID_CHAN_NOISE_REDUCING) + ret = fm_timer_put(fm_cqi_check_timer); + if (!ret) + fm_cqi_check_timer = NULL; +#endif + + ret = fm_lock_put(fm_wcn_ops.tx_lock); + if (!ret) + fm_wcn_ops.tx_lock = NULL; + ret = fm_lock_put(fm_wcn_ops.own_lock); + if (!ret) + fm_wcn_ops.own_lock = NULL; + + return ret; +} + +/* + * 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 + */ +signed int fm_get_channel_space(signed int freq) +{ + if ((freq >= 640) && (freq <= 1080)) + return 0; + else if ((freq >= 6400) && (freq <= 10800)) + return 1; + else + return -1; +} diff --git a/drivers/misc/mediatek/connectivity/fmradio/core/fm_module.c b/drivers/misc/mediatek/connectivity/fmradio/core/fm_module.c new file mode 100644 index 0000000000000..7690cec064fdb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/core/fm_module.c @@ -0,0 +1,1607 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* udelay() */ +#include + +#include "fm_config.h" +#include "fm_main.h" +#include "fm_ioctl.h" + +#define FM_PROC_FILE "fm" + +unsigned int g_dbg_level = 0xfffffff5; /* Debug level of FM */ + +/* fm main data structure */ +static struct fm *g_fm; +/* proc file entry */ +static struct proc_dir_entry *g_fm_proc; + +/* char device interface */ +static signed int fm_cdev_setup(struct fm *fm); +static signed int fm_cdev_destroy(struct fm *fm); + +static long fm_ops_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +#ifdef CONFIG_COMPAT +static long fm_ops_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +#endif +static loff_t fm_ops_lseek(struct file *filp, loff_t off, signed int whence); +static ssize_t fm_ops_read(struct file *filp, char *buf, size_t len, loff_t *off); +static signed int fm_ops_open(struct inode *inode, struct file *filp); +static signed int fm_ops_release(struct inode *inode, struct file *filp); +static signed int fm_ops_flush(struct file *filp, fl_owner_t Id); +static const struct file_operations fm_ops = { + .owner = THIS_MODULE, + .unlocked_ioctl = fm_ops_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = fm_ops_compat_ioctl, +#endif + .llseek = fm_ops_lseek, + .read = fm_ops_read, + .open = fm_ops_open, + .release = fm_ops_release, + .flush = fm_ops_flush, +}; + +/* static signed int fm_proc_read(char *page, char **start, off_t off, signed int count, + * signed int *eof, void *data); + */ +static ssize_t fm_proc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos); +static ssize_t fm_proc_write(struct file *file, const char *buffer, size_t count, loff_t *ppos); + +static const struct file_operations fm_proc_ops = { + .owner = THIS_MODULE, + .read = fm_proc_read, + .write = fm_proc_write, +}; + +#ifdef CONFIG_COMPAT +static long fm_ops_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + long ret; + + WCN_DBG(FM_NTC | MAIN, "COMPAT %s---pid(%d)---cmd(0x%08x)---arg(0x%08x)\n", current->comm, + current->pid, cmd, (unsigned int) arg); + + if (!filp->f_op || !filp->f_op->unlocked_ioctl) + return -ENOTTY; + switch (cmd) { + case COMPAT_FM_IOCTL_GET_AUDIO_INFO: { + ret = filp->f_op->unlocked_ioctl(filp, FM_IOCTL_GET_AUDIO_INFO, arg); + break; + } + default: + ret = filp->f_op->unlocked_ioctl(filp, ((cmd & 0xFF) | (FM_IOCTL_POWERUP & 0xFFFFFF00)), arg); + break; + } + return ret; +} +#endif + +static long fm_ops_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + signed int ret = 0; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + struct fm_platform *plat = container_of(filp->f_path.dentry->d_inode->i_cdev, struct fm_platform, cdev); +#else + struct fm_platform *plat = container_of(filp->f_dentry->d_inode->i_cdev, struct fm_platform, cdev); +#endif + struct fm *fm = container_of(plat, struct fm, platform); + + WCN_DBG(FM_INF | MAIN, "%s---pid(%d)---cmd(0x%08x)---arg(0x%08x)\n", current->comm, + current->pid, cmd, (unsigned int) 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; + } + + if (parm.freq <= 0 || parm.freq > FM_FREQ_MAX) { + struct fm_tune_parm_old *old_parm = + (struct fm_tune_parm_old *)&parm; + + if (old_parm->freq > 0 && old_parm->freq <= FM_FREQ_MAX) { + WCN_DBG(FM_WAR | MAIN, + "convert to old version fm_tune_parm [%u]->[%u]\n", + parm.freq, old_parm->freq); + parm.freq = old_parm->freq; + parm.deemphasis = 0; + } + } + + if (parm.deemphasis == 1) + fm_config.rx_cfg.deemphasis = 1; + else + fm_config.rx_cfg.deemphasis = 0; + + ret = fm_powerup(fm, &parm); + if (ret < 0) { + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_POWERUP:fail in fm_powerup, return\n"); + goto out; + } + ret = fm_tune(fm, &parm); + if (ret < 0) { + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_POWERUP:fail in fm_tune, return\n"); + 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:{ + int powerdwn_type = 0; + + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_POWERDOWN:0\n"); + + if (copy_from_user(&powerdwn_type, (void *)arg, sizeof(int))) { + ret = -EFAULT; + goto out; + } + + ret = fm_powerdown(fm, powerdwn_type); /* 0: RX 1: TX */ + 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; + } + + if (parm.freq <= 0 || parm.freq > FM_FREQ_MAX) { + struct fm_tune_parm_old *old_parm = + (struct fm_tune_parm_old *)&parm; + + if (old_parm->freq > 0 && old_parm->freq <= FM_FREQ_MAX) { + WCN_DBG(FM_WAR | MAIN, + "convert to old version fm_tune_parm [%u]->[%u]\n", + parm.freq, old_parm->freq); + parm.freq = old_parm->freq; + parm.deemphasis = 0; + } + } + + 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 */ + 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_PRE_SEARCH: + { + ret = fm_pre_search(fm); + break; + } + case FM_IOCTL_RESTORE_SEARCH: + { + ret = fm_restore_search(fm); + break; + } + case FM_IOCTL_CQI_GET:{ + struct fm_cqi_req cqi_req; + signed char *buf = NULL; + signed int tmp; + unsigned int cpy_size = 0; + + WCN_DBG(FM_INF | 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; + } + + cpy_size = cqi_req.ch_num * sizeof(struct fm_cqi); + if (cpy_size > tmp) + cpy_size = tmp; + if (copy_to_user((void *)cqi_req.cqi_buf, buf, cpy_size)) { + 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:{ + unsigned int vol; + + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_SETVOL start\n"); + if (copy_from_user(&vol, (void *)arg, sizeof(unsigned int))) { + 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:{ + unsigned int 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(unsigned int))) { + ret = -EFAULT; + goto out; + } + + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_GETVOL end=%d\n", vol); + break; + } + + case FM_IOCTL_MUTE:{ + unsigned int bmute; + + if (copy_from_user(&bmute, (void *)arg, sizeof(unsigned int))) { + ret = -EFAULT; + goto out; + } + + ret = fm_mute(fm, bmute); + WCN_DBG(FM_INF | MAIN, "FM_IOCTL_MUTE end-%d\n", bmute); + break; + } + + case FM_IOCTL_GETRSSI:{ + signed int rssi = 0; + + ret = fm_getrssi(fm, &rssi); + if (ret < 0) + goto out; + + if (copy_to_user((void *)arg, &rssi, sizeof(signed int))) { + 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_INF | MAIN, "FM_IOCTL_RW_REG\n"); + if (fm->chipon == false || fm_pwr_state_get(fm) == FM_PWR_OFF) { + WCN_DBG(FM_ERR | MAIN, "ERROR, FM chip is OFF\n"); + ret = -EFAULT; + goto out; + } + + if (copy_from_user(&parm_ctl, (void *)arg, sizeof(struct fm_ctl_parm))) { + WCN_DBG(FM_ALT | MAIN, "copy from user error\n"); + ret = -EFAULT; + goto out; + } + + if (parm_ctl.rw_flag == 0) + ret = fm_write(fm, parm_ctl.addr, parm_ctl.val); + else + ret = fm_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_TOP_RDWR: + { + struct fm_top_rw_parm parm_ctl; + + WCN_DBG(FM_INF | MAIN, "FM_IOCTL_TOP_RDWR\n"); + +#ifdef CONFIG_MTK_USER_BUILD + WCN_DBG(FM_ERR | MAIN, "Not support FM_IOCTL_TOP_RDWR\n"); + ret = -EFAULT; + goto out; +#endif + + if (g_dbg_level != 0xfffffff7) { + WCN_DBG(FM_ERR | MAIN, "Not support FM_IOCTL_TOP_RDWR\n"); + ret = -EFAULT; + goto out; + } + + if (fm->chipon == false || fm_pwr_state_get(fm) == FM_PWR_OFF) { + WCN_DBG(FM_ERR | MAIN, "ERROR, FM chip is OFF\n"); + ret = -EFAULT; + goto out; + } + + if (copy_from_user(&parm_ctl, (void *)arg, sizeof(struct fm_top_rw_parm))) { + WCN_DBG(FM_ALT | MAIN, "copy from user error\n"); + ret = -EFAULT; + goto out; + } + + if (parm_ctl.rw_flag == 0) + ret = fm_top_write(fm, parm_ctl.addr, parm_ctl.val); + else + ret = fm_top_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_top_rw_parm))) { + ret = -EFAULT; + goto out; + } + } + + break; + } + case FM_IOCTL_HOST_RDWR: + { + struct fm_host_rw_parm parm_ctl; + + WCN_DBG(FM_INF | MAIN, "FM_IOCTL_HOST_RDWR\n"); + +#ifdef CONFIG_MTK_USER_BUILD + WCN_DBG(FM_ERR | MAIN, "Not support FM_IOCTL_HOST_RDWR\n"); + ret = -EFAULT; + goto out; +#endif + + if (g_dbg_level != 0xfffffff7) { + WCN_DBG(FM_ERR | MAIN, "Not support FM_IOCTL_HOST_RDWR\n"); + ret = -EFAULT; + goto out; + } + + if (fm->chipon == false || fm_pwr_state_get(fm) == FM_PWR_OFF) { + WCN_DBG(FM_ERR | MAIN, "ERROR, FM chip is OFF\n"); + ret = -EFAULT; + goto out; + } + + if (copy_from_user(&parm_ctl, (void *)arg, sizeof(struct fm_host_rw_parm))) { + WCN_DBG(FM_ALT | MAIN, "copy from user error\n"); + ret = -EFAULT; + goto out; + } + + /* 4 bytes alignment and illegal address */ + if (parm_ctl.addr % 4 != 0 || parm_ctl.addr >= 0x90000000) { + ret = -FM_EPARA; + goto out; + } + WCN_DBG(FM_NTC | MAIN, "rw? (%d), addr: %x\n", parm_ctl.rw_flag, parm_ctl.addr); + if (parm_ctl.rw_flag == 0) + ret = fm_host_write(fm, parm_ctl.addr, parm_ctl.val); + else + ret = fm_host_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_host_rw_parm))) { + ret = -EFAULT; + goto out; + } + } + + break; + } + case FM_IOCTL_PMIC_RDWR: + { + struct fm_pmic_rw_parm parm_ctl; + + WCN_DBG(FM_INF | MAIN, "FM_IOCTL_PMIC_RDWR\n"); + if (fm->chipon == false || fm_pwr_state_get(fm) == FM_PWR_OFF) { + WCN_DBG(FM_ERR | MAIN, "ERROR, FM chip is OFF\n"); + ret = -EFAULT; + goto out; + } + + if (copy_from_user(&parm_ctl, (void *)arg, sizeof(struct fm_pmic_rw_parm))) { + WCN_DBG(FM_ALT | MAIN, "copy from user error\n"); + ret = -EFAULT; + goto out; + } + + if (parm_ctl.rw_flag == 0) + ret = fm_pmic_write(fm, parm_ctl.addr, parm_ctl.val); + else + ret = fm_pmic_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_pmic_rw_parm))) { + ret = -EFAULT; + goto out; + } + } + + break; + } + case FM_IOCTL_GETCHIPID:{ + unsigned short chipid = 0; + + ret = fm_chipid_get(fm, &chipid); + WCN_DBG(FM_INF | MAIN, "FM_IOCTL_GETCHIPID:%04x\n", chipid); + if (ret < 0) + goto out; + + if (copy_to_user((void *)arg, &chipid, sizeof(unsigned short))) { + ret = -EFAULT; + goto out; + } + break; + } + + case FM_IOCTL_GETMONOSTERO:{ + unsigned short usStereoMono = 0; + + ret = fm_monostereo_get(fm, &usStereoMono); + WCN_DBG(FM_INF | MAIN, "FM_IOCTL_GETMONOSTERO:%04x\n", usStereoMono); + if (ret < 0) + goto out; + + if (copy_to_user((void *)arg, &usStereoMono, sizeof(unsigned short))) { + ret = -EFAULT; + goto out; + } + break; + } + + case FM_IOCTL_SETMONOSTERO:{ + signed int monostero; + + WCN_DBG(FM_INF | MAIN, "FM_IOCTL_SETMONOSTERO\n"); + if (copy_from_user(&monostero, (void *)arg, sizeof(signed int))) { + WCN_DBG(FM_ALT | MAIN, "copy from user error\n"); + ret = -EFAULT; + goto out; + } + ret = fm_monostereo_set(fm, monostero); + break; + } + + case FM_IOCTL_GETCURPAMD:{ + unsigned short PamdLevl = 0; + + ret = fm_pamd_get(fm, &PamdLevl); + WCN_DBG(FM_INF | MAIN, "FM_IOCTL_GETCURPAMD:%d\n", PamdLevl); + if (ret < 0) + goto out; + + if (copy_to_user((void *)arg, &PamdLevl, sizeof(unsigned short))) + ret = -EFAULT; + goto out; + + break; + } + + case FM_IOCTL_GETCAPARRAY:{ + signed int ca = 0; + + ret = fm_caparray_get(fm, &ca); + WCN_DBG(FM_INF | MAIN, "FM_IOCTL_GETCAPARRAY:%d\n", ca); + if (ret < 0) + goto out; + + if (copy_to_user((void *)arg, &ca, sizeof(signed int))) { + 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:{ + signed int support = FM_RDS_ENABLE; + + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_RDS_SUPPORT\n"); + + if (copy_to_user((void *)arg, &support, sizeof(signed int))) { + ret = -EFAULT; + goto out; + } + break; + } + + case FM_IOCTL_IS_FM_POWERED_UP:{ + unsigned int 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(unsigned int))) { + ret = -EFAULT; + goto out; + } + break; + } + + case FM_IOCTL_FM_SET_STATUS:{ + struct fm_status_t fm_stat; + + WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_FM_SET_STATUS"); + + if (copy_from_user(&fm_stat, (void *)arg, sizeof(struct fm_status_t))) { + ret = -EFAULT; + goto out; + } + + fm_set_stat(fm, fm_stat.which, fm_stat.stat); + + break; + } + + case FM_IOCTL_FM_GET_STATUS:{ + struct fm_status_t fm_stat; + + WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_FM_GET_STATUS"); + + if (copy_from_user(&fm_stat, (void *)arg, sizeof(struct fm_status_t))) { + ret = -EFAULT; + goto out; + } + + fm_get_stat(fm, fm_stat.which, &fm_stat.stat); + + if (copy_to_user((void *)arg, &fm_stat, sizeof(struct fm_status_t))) { + ret = -EFAULT; + goto out; + } + + break; + } + + case FM_IOCTL_RDS_ONOFF:{ + unsigned short rdson_off = 0; + + WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_RDS_ONOFF start\n"); + + if (copy_from_user(&rdson_off, (void *)arg, sizeof(unsigned short))) { + 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:{ + unsigned short 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(unsigned short))) { + ret = -EFAULT; + goto out; + } + break; + } + + case FM_IOCTL_GETBADBNT:{ + unsigned short 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(unsigned short))) { + ret = -EFAULT; + goto out; + } + break; + } + + case FM_IOCTL_GETBLERRATIO:{ + unsigned short 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(unsigned short))) { + ret = -EFAULT; + goto out; + } + break; + } + + case FM_IOCTL_ANA_SWITCH:{ + signed int antenna = -1; + + WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_ANA_SWITCH\n"); + + if (copy_from_user(&antenna, (void *)arg, sizeof(signed int))) { + 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; + signed int len = 0; + + memset(rds_log.data, 0, sizeof(rds_log.data)); + 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(signed int))) { + 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_NTC | 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:{ + signed int tmp; + + WCN_DBG(FM_INF | MAIN, "FM_IOCTL_IS_DESE_CHAN\n"); + + if (copy_from_user(&tmp, (void *)arg, sizeof(signed int))) { + WCN_DBG(FM_ALT | MAIN, "is dese chan, copy_from_user err\n"); + ret = -EFAULT; + goto out; + } + + tmp = fm_is_dese_chan(fm, (unsigned short) tmp); + + if (copy_to_user((void *)arg, &tmp, sizeof(signed int))) { + WCN_DBG(FM_ALT | MAIN, "is dese chan, copy_to_user err\n"); + ret = -EFAULT; + goto out; + } + + break; + } + case FM_IOCTL_DESENSE_CHECK: + { + struct fm_desense_check_t tmp; + + WCN_DBG(FM_INF | MAIN, "FM_IOCTL_DESENSE_CHECK\n"); + + if (copy_from_user(&tmp, (void *)arg, sizeof(struct 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, (unsigned short) tmp.freq, tmp.rssi); + + /*if (copy_to_user((void*)arg, &tmp, sizeof(struct 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: + { + 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"); + if (g_dbg_level != 0xfffffff7) { + WCN_DBG(FM_ERR | MAIN, "Not support FM_IOCTL_HOST_RDWR\n"); + ret = -EFAULT; + goto out; + } + if (fm->chipon == false || fm_pwr_state_get(fm) == FM_PWR_OFF) { + WCN_DBG(FM_ERR | MAIN, "ERROR, FM chip is OFF\n"); + ret = -EFAULT; + goto out; + } + 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 (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: + { + signed int 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; + } + + case FM_IOCTL_SET_SEARCH_THRESHOLD: + { + struct fm_search_threshold_t parm; + + WCN_DBG(FM_NTC | MAIN, "......FM_IOCTL_SET_SEARCH_THRESHOLD......\n"); + + if (copy_from_user(&parm, (void *)arg, sizeof(struct fm_search_threshold_t))) { + WCN_DBG(FM_ALT | MAIN, "copy_from_user error\n"); + ret = -EFAULT; + goto out; + } + ret = fm_set_search_th(fm, parm); + if (ret < 0) + WCN_DBG(FM_ERR | MAIN, "FM_IOCTL_SET_SEARCH_THRESHOLD not supported\n"); + break; + } + case FM_IOCTL_GET_AUDIO_INFO: + { + struct fm_audio_info_t aud_data; + + ret = fm_get_aud_info(&aud_data); + if (ret) + WCN_DBG(FM_ERR | MAIN, "fm_get_aud_info err\n"); + + if (copy_to_user((void *)arg, &aud_data, sizeof(struct fm_audio_info_t))) { + WCN_DBG(FM_ERR | MAIN, "copy_to_user error\n"); + ret = -EFAULT; + goto out; + } + + WCN_DBG(FM_INF | MAIN, "fm_get_aud_info ret=%d\n", ret); + break; + } + /***************************FM Tx function************************************/ + case FM_IOCTL_TX_SUPPORT: + { + signed int 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(signed int))) { + 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: + { + signed int 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(signed int))) { + WCN_DBG(FM_ERR | MAIN, "copy_to_user error\n"); + ret = -EFAULT; + goto out; + } + break; + } + + case FM_IOCTL_RDSTX_ENABLE: + { + signed int onoff = -1; + + WCN_DBG(FM_NTC | MAIN, "......FM_IOCTL_RDSTX_ENABLE......\n"); + + if (copy_from_user(&onoff, (void *)arg, sizeof(signed int))) { + WCN_DBG(FM_ALT | MAIN, "FM_IOCTL_RDSTX_ENABLE, copy_from_user err\n"); + ret = -EFAULT; + goto out; + } + + ret = fm_rdstx_enable(fm, onoff); + if (ret) + WCN_DBG(FM_ERR | MAIN, "fm_rdstx_enable err\n"); + + 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) { + if (fm_sys_state_get(fm) == FM_SUBSYS_RST_OFF) { + fm->wholechiprst = false; + /* subsystem reset */ + WCN_DBG(FM_NTC | MAIN, "fm_subsys_reset START\n"); + fm_subsys_reset(fm); + WCN_DBG(FM_NTC | MAIN, "fm_subsys_reset END\n"); + } + } + + return ret; +} + +static loff_t fm_ops_lseek(struct file *filp, loff_t off, signed int 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; + signed int copy_len = 0; + + if (!fm) { + WCN_DBG(FM_ALT | MAIN, "fm_read invalid fm pointer\n"); + return 0; + } + + WCN_DBG(FM_DBG | MAIN, "rds buf len=%zu\n", len); + WCN_DBG(FM_DBG | MAIN, "sizeof(struct rds_t)=%zu\n", sizeof(struct rds_t)); + + if (!buf || len < sizeof(struct rds_t)) { + WCN_DBG(FM_NTC | MAIN, "fm_read invliad buf\n"); + return 0; + } + /* return if FM is resetting */ + if (fm_sys_state_get(fm) != FM_SUBSYS_RST_OFF) { + WCN_DBG(FM_ALT | MAIN, "fm subsys underring reset\n"); + return 0; + } + + copy_len = sizeof(struct rds_t); + + return fm_rds_read(fm, buf, copy_len); +} + +atomic_t g_counter = ATOMIC_INIT(0); +static signed int fm_ops_open(struct inode *inode, struct file *filp) +{ + signed int ret = 0; + struct fm_platform *plat = container_of(inode->i_cdev, struct fm_platform, cdev); + struct fm *fm = container_of(plat, struct fm, platform); + + 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; + atomic_inc(&g_counter); + + WCN_DBG(FM_NTC | MAIN, "fm_ops_open:%d [%d]\n", current->pid, atomic_read(&g_counter)); + return ret; +} + +static signed int fm_ops_release(struct inode *inode, struct file *filp) +{ +/* signed int ret = 0; */ +/* struct fm_platform *plat = container_of(inode->i_cdev, struct fm_platform, cdev); */ +/* struct fm *fm = container_of(plat, struct fm, platform); */ + struct fm *fm = filp->private_data; + + WCN_DBG(FM_NTC | MAIN, "fm_ops_release:%d [%d]\n", current->pid, atomic_read(&g_counter)); + + if (atomic_dec_and_test(&g_counter)) { + WCN_DBG(FM_ALT | MAIN, "FM power down... [%d]\n", atomic_read(&g_counter)); + if (-FM_ELOCK == fm_powerdown(fm, 0)) { + WCN_DBG(FM_ALT | MAIN, "FM power down fail. Do it later.\n"); + fm->timer_wkthd->add_work(fm->timer_wkthd, fm->pwroff_wk); + } + } + + filp->private_data = NULL; + return 0; +} + +static signed int fm_ops_flush(struct file *filp, fl_owner_t Id) +{ + signed int ret = 0; + struct fm *fm = filp->private_data; + + WCN_DBG(FM_NTC | MAIN, "fm_ops_flush:%d\n", current->pid); + fm_close(fm); + filp->private_data = fm; + return ret; +} + +static ssize_t fm_proc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) +{ + struct fm *fm = g_fm; + ssize_t length = 0; + char tmpbuf[3]; + unsigned long pos = *ppos; + + WCN_DBG(FM_NTC | MAIN, "Enter fm_proc_read.\n"); + /* WCN_DBG(FM_NTC | MAIN, "count = %d\n", count); */ + /* WCN_DBG(FM_NTC | MAIN, "ppos = %d\n", pos); */ + + if (pos != 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)) { + length = snprintf(tmpbuf, sizeof(tmpbuf), "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)) { + length = snprintf(tmpbuf, sizeof(tmpbuf), "2\n"); + WCN_DBG(FM_NTC | MAIN, " FM_PWR_TX_ON\n"); + } else { + length = snprintf(tmpbuf, sizeof(tmpbuf), "0\n"); + WCN_DBG(FM_NTC | MAIN, " FM POWER OFF\n"); + } + + if (copy_to_user(buf, tmpbuf, length)) { + WCN_DBG(FM_NTC | MAIN, " Read FM status fail!\n"); + return 0; + } + + pos += length; + *ppos = pos; + WCN_DBG(FM_NTC | MAIN, "Leave fm_proc_read. length = %zu\n", length); + + return length; +} + +static ssize_t fm_proc_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) +{ + struct fm *fm = g_fm; + signed char tmp_buf[51] = { 0 }; + unsigned int copysize; + + WCN_DBG(FM_NTC | MAIN, "fm_proc_write:0 count = %zu\n", count); + if (count <= 0 || buffer == NULL) { + WCN_DBG(FM_ERR | MAIN, "failed parameter not accept\n"); + return -EFAULT; + } + + copysize = (count < (sizeof(tmp_buf) - 1)) ? count : (sizeof(tmp_buf) - 1); + + memset(tmp_buf, 0, sizeof(tmp_buf)); + 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(fm); + return count; + } + + if (!fm->chipon || (fm_pwr_state_get(fm) != FM_PWR_RX_ON)) { + WCN_DBG(FM_ERR | MAIN, "FM is off.\n"); + return -EFAULT; + } + + if (kstrtouint(tmp_buf, 0, &g_dbg_level)) { + tmp_buf[50] = '\0'; + WCN_DBG(FM_ERR | MAIN, "Not a valid dbg_level: %s\n", tmp_buf); + if (!fm_cust_config_setup(tmp_buf)) { + WCN_DBG(FM_NTC | MAIN, "get config form %s ok\n", tmp_buf); + return count; + } + 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 signed int fm_cdev_setup(struct fm *fm) +{ + signed int 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 signed int fm_cdev_destroy(struct fm *fm) +{ + if (fm == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + 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 signed int fm_mod_init(unsigned int arg) +{ + signed int ret = 0; + struct fm *fm = NULL; + + fm = fm_dev_init(0); + + if (!fm) { + ret = -ENOMEM; + goto ERR_EXIT; + } + + ret = fm_cdev_setup(fm); + if (ret) + goto ERR_EXIT; + + /* fm proc file create "/proc/fm" */ + g_fm_proc = proc_create(FM_PROC_FILE, 0444, NULL, &fm_proc_ops); + + if (g_fm_proc == NULL) { + WCN_DBG(FM_ALT | MAIN, "create_proc_entry failed\n"); + ret = -ENOMEM; + goto ERR_EXIT; + } else { + 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 signed int fm_mod_destroy(struct fm *fm) +{ + signed int ret = 0; + + if (fm == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + 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 signed int mt_fm_probe(struct platform_device *pdev) +{ + signed int 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 signed int 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 *pr_fm_device; +/* +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 signed int mt_fm_init(void) +{ + signed int 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; + */ + + pr_fm_device = platform_device_alloc(FM_NAME, 0); + if (!pr_fm_device) { + WCN_DBG(FM_ERR | MAIN, "fm platform device alloc fail\n"); + return -ENOMEM; + } + + ret = platform_device_add(pr_fm_device); + if (ret) { + WCN_DBG(FM_ERR | MAIN, "fm platform device add failed(%d)\n", ret); + platform_device_put(pr_fm_device); + return ret; + } + + /* register fm driver to platform bus */ + ret = platform_driver_register(&mt_fm_dev_drv); + + if (ret) { + WCN_DBG(FM_ERR | MAIN, "fm platform driver register fail(%d)\n", ret); + platform_device_unregister(pr_fm_device); + return ret; + } + + fm_register_irq(&mt_fm_dev_drv); + + WCN_DBG(FM_NTC | MAIN, "6. fm platform driver registered\n"); + return ret; +} + +static void mt_fm_exit(void) +{ + WCN_DBG(FM_NTC | MAIN, "%s\n", __func__); + platform_driver_unregister(&mt_fm_dev_drv); + /* platform_device_unregister(&mt_fm_device); */ + platform_device_unregister(pr_fm_device); + fm_env_destroy(); +} + +#ifdef MTK_WCN_REMOVE_KERNEL_MODULE +int mtk_wcn_fm_init(void) +{ + return mt_fm_init(); +} +EXPORT_SYMBOL(mtk_wcn_fm_init); + +void mtk_wcn_fm_exit(void) +{ + mt_fm_exit(); +} +EXPORT_SYMBOL(mtk_wcn_fm_exit); +#else +module_init(mt_fm_init); +module_exit(mt_fm_exit); +#endif +EXPORT_SYMBOL(g_dbg_level); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("MediaTek FM Driver"); +MODULE_AUTHOR("Hongcheng "); diff --git a/drivers/misc/mediatek/connectivity/fmradio/core/fm_patch.c b/drivers/misc/mediatek/connectivity/fmradio/core/fm_patch.c new file mode 100644 index 0000000000000..cf42b79dd1697 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/core/fm_patch.c @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include + +#include "fm_patch.h" +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" + +static struct fm_file_read_data g_file_read_data; + +int file_read_thread(void *arg) +{ + struct fm_file_read_data *data = (struct fm_file_read_data *)arg; + const struct firmware *fw = NULL; + + if (!data) + return 0; + + data->ret = request_firmware(&fw, data->filename, NULL); + if (data->ret) { + WCN_DBG(FM_ERR | CHIP, "Failed to load firmware \"%s\"\n", + data->filename); + release_firmware(fw); + data->ret = -FM_EPATCH; + + complete(&data->comp); + return 0; + } + WCN_DBG(FM_NTC | CHIP, "load firmware \"%s\" ok\n", data->filename); + + if (data->len >= fw->size) { + memcpy(data->dst, fw->data, fw->size); + WCN_DBG(FM_NTC | CHIP, "Copy file data(%p) size(%zu)\n", + fw->data, fw->size); + data->ret = fw->size; + } else { + WCN_DBG(FM_NTC | CHIP, + "Copy file data failed fw->size(%zu) > bufsize(%d)\n", + fw->size, data->len); + data->ret = -FM_EPATCH; + } + release_firmware(fw); + + complete(&data->comp); + + return 0; +} + +/* + * 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 + */ +signed int fm_file_read(const signed char *filename, unsigned char *dst, signed int len, signed int position) +{ + struct fm_file_read_data *data = &g_file_read_data; + struct task_struct *k; + + init_completion(&data->comp); + + data->filename = filename; + data->dst = dst; + data->len = len; + data->position = position; + data->ret = 0; + + k = kthread_run(file_read_thread, (void *)data, "file_read_thread"); + if (IS_ERR(k)) { + WCN_DBG(FM_NTC | CHIP, "%s error ret:%d\n", __func__, PTR_ERR(k)); + data->ret = -FM_EPATCH; + } else + wait_for_completion(&data->comp); + return data->ret; +} + +signed int fm_file_write(const signed char *filename, unsigned char *dst, signed int len, signed int *ppos) +{ + signed int ret = 0; + return ret; +} diff --git a/drivers/misc/mediatek/connectivity/fmradio/core/fm_rds_parser.c b/drivers/misc/mediatek/connectivity/fmradio/core/fm_rds_parser.c new file mode 100644 index 0000000000000..dcb7aa43093a1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/core/fm_rds_parser.c @@ -0,0 +1,2004 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +#include "fm_typedef.h" +#include "fm_rds.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_stdlib.h" + +/* static enum rds_ps_state_machine_t ps_state_machine = RDS_PS_START; */ +/* static enum rds_rt_state_machine_t rt_state_machine = RDS_RT_START; */ +struct fm_state_machine { + signed int state; + signed int (*state_get)(struct fm_state_machine *thiz); + signed int (*state_set)(struct fm_state_machine *thiz, signed int new_state); +}; + +static signed int fm_state_get(struct fm_state_machine *thiz) +{ + return thiz->state; +} + +static signed int fm_state_set(struct fm_state_machine *thiz, signed int 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) \ +({ \ + signed int __ret = 0; \ + if ((a)->state_get) { \ + __ret = (a)->state_get((a)); \ + } \ + __ret; \ +}) + +static unsigned short (*rds_get_freq)(void); + +/* 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 signed int rds_cnt_get(struct rds_rx_t *rds_raw, signed int raw_size, signed int *cnt) +{ + signed int gap = sizeof(rds_raw->cos) + sizeof(rds_raw->sin); + + if (rds_raw == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (cnt == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + *cnt = (raw_size - gap) / sizeof(struct 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 signed int rds_grp_get(unsigned short *dst, struct rds_rx_t *raw, signed int idx) +{ + if (dst == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (raw == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + if (idx > (MAX_RDS_RX_GROUP_CNT - 1) || idx < 0) + 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=true, else *valid=false + * If success return 0, else return error code +*/ +static signed int rds_checksum_check(unsigned short crc, signed int mask, bool *valid) +{ + if (valid == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + if ((crc & mask) == mask) + *valid = true; + else + *valid = false; + + return 0; +} + +/* + * 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 signed int rds_event_set(unsigned short *events, signed int event_mask) +{ + if (events == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + WCN_DBG(FM_INF | RDSC, "rds set event[0x%04x->0x%04x]\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 signed int rds_flag_set(unsigned int *flags, signed int flag_mask) +{ + if (flags == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + WCN_DBG(FM_INF | RDSC, "rds set flag[0x%04x->0x%04x]\n", flag_mask, *flags); + *flags |= flag_mask; + + return 0; +} + +/* + * rds_grp_type_get + * To get rds group type form blockB + * If success return 0, else return error code +*/ +static signed int rds_grp_type_get(unsigned short crc, unsigned short blk, unsigned char *type, unsigned char *subtype) +{ + bool valid = false; + + if (type == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (subtype == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + /* to get the group type from block B */ + rds_checksum_check(crc, FM_RDS_GDBK_IND_B, &valid); + + if (valid == 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", (signed int) *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 signed int rds_grp_counter_add(unsigned char type, unsigned char subtype, struct rds_group_cnt_t *gc) +{ + if (gc == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + 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; + } + + gc->total++; + WCN_DBG(FM_INF | RDSC, "group counter:%d\n", (signed int) gc->total); + return 0; +} + +/* + * rds_grp_counter_get + * + * read group counter , g0a~g15b + * If success return 0, else return error code +*/ +extern signed int rds_grp_counter_get(struct rds_group_cnt_t *dst, struct rds_group_cnt_t *src) +{ + if (dst == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (src == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + fm_memcpy(dst, src, sizeof(struct rds_group_cnt_t)); + WCN_DBG(FM_DBG | RDSC, "rds gc get[total=%d]\n", (signed int) dst->total); + return 0; +} + +/* + * rds_grp_counter_reset + * + * clear group counter to 0, g0a~g15b + * If success return 0, else return error code +*/ +extern signed int rds_grp_counter_reset(struct rds_group_cnt_t *gc) +{ + if (gc == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + fm_memset(gc, 0, sizeof(struct rds_group_cnt_t)); + return 0; +} + +extern signed int rds_log_in(struct rds_log_t *thiz, struct rds_rx_t *new_log, signed int new_len) +{ + if (new_log == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + 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++; + thiz->len = (thiz->len >= thiz->size) ? thiz->size : thiz->len; + WCN_DBG(FM_DBG | RDSC, "add a new log[len=%d]\n", thiz->len); + + return 0; +} + +extern signed int rds_log_out(struct rds_log_t *thiz, struct rds_rx_t *dst, signed int *dst_len) +{ + if (dst == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (dst_len == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + 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 signed int rds_grp_pi_get(unsigned short crc, unsigned short blk, unsigned short *pi, bool *dirty) +{ + signed int ret = 0; + bool valid = false; + + if (pi == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (dirty == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + /* to get the group pi code from block A */ + ret = rds_checksum_check(crc, FM_RDS_GDBK_IND_A, &valid); + + if (valid == true) { + if (*pi != blk) { + /* PI=program Identication */ + *pi = blk; + *dirty = true; /* yes, we got new PI code */ + } else { + *dirty = 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 signed int rds_grp_pty_get(unsigned short crc, unsigned short blk, unsigned char *pty, bool *dirty) +{ + signed int ret = 0; +/* bool valid = false; */ + + if (pty == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (dirty == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + /* to get PTY code from block B */ +/* ret = rds_checksum_check(crc, FM_RDS_GDBK_IND_B, &valid); */ + +/* if (valid == 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 = true; /* yes, we got new PTY code */ + } else { + *dirty = false; /* PTY is the same as last one */ + } + + WCN_DBG(FM_INF | RDSC, "PTY=%d, %s\n", (signed int) *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 signed int rds_grp_tp_get(unsigned short crc, unsigned short blk, unsigned char *tp, bool *dirty) +{ + signed int ret = 0; +/* bool valid = false; */ + + if (tp == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (dirty == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + /* to get TP code from block B */ +/* ret = rds_checksum_check(crc, FM_RDS_GDBK_IND_B, &valid); */ + +/* if (valid == 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 = true; /* yes, we got new TP code */ + } else { + *dirty = false; /* TP is the same as last one */ + } + + /* WCN_DBG(FM_INF | RDSC, "TP=%d, %s\n", (signed int) *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 signed int rds_g0_ta_get(unsigned short blk, unsigned char *ta, bool *dirty) +{ + signed int ret = 0; + + if (ta == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (dirty == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + /* TA=Traffic Announcement code */ + if (*ta != ((blk & 0x0010) >> 4)) { + *ta = (blk & 0x0010) >> 4; + *dirty = true; /* yes, we got new TA code */ + } else { + *dirty = false; /* TA is the same as last one */ + } + + WCN_DBG(FM_INF | RDSC, "TA=%d, %s\n", (signed int) *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 signed int rds_g0_music_get(unsigned short blk, unsigned char *music, bool *dirty) +{ + signed int ret = 0; + + if (music == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (dirty == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + /* M/S=music speech switch code */ + if (*music != ((blk & 0x0008) >> 3)) { + *music = (blk & 0x0008) >> 3; + *dirty = true; /* yes, we got new music code */ + } else { + *dirty = false; /* music is the same as last one */ + } + + WCN_DBG(FM_INF | RDSC, "Music=%d, %s\n", (signed int) *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 signed int rds_g0_ps_addr_get(unsigned short blkB, unsigned char *addr) +{ + if (addr == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + *addr = (unsigned char) 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 signed int rds_g0_di_flag_get(unsigned short blkB, unsigned char *flag) +{ + if (flag == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + *flag = (unsigned char) ((blkB & 0x0004) >> 2); + + WCN_DBG(FM_INF | RDSC, "flag=0x%02x\n", *flag); + return 0; +} + +static signed int rds_g0_ps_get(unsigned short crc, unsigned short blkD, unsigned char addr, unsigned char *buf) +{ +/* bool valid = false; */ + signed int idx = 0; + + if (buf == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + /* ps segment addr rang 0~3 */ + if (addr > 0x03) { + WCN_DBG(FM_ERR | RDSC, "addr invalid(0x%02x)\n", addr); + return -FM_EPARA; + } + + 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 == 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_INF | 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 whether we got a full segment + * If success return 0, else return error code +*/ +static signed int rds_g0_ps_cmp(unsigned char addr, unsigned short cbc, unsigned char *fresh, + unsigned char *once, unsigned char *twice, /*bool *valid, */ unsigned char *bm) +{ + signed int ret = 0, indx; + /* signed int i = 0; */ + /* signed int j = 0; */ + /* signed int cnt = 0; */ + unsigned char AF_H, AF_L, PS_Num; + /* unsigned char corrBitCnt_BlkB, corrBitCnt_BlkD; */ + static signed char Pre_PS_Num = -1; + + if (fresh == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + if (once == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + if (twice == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + if (addr > 3) { /* ps limited in 8 chars */ + WCN_DBG(FM_NTC | RDSC, "PS Address error, addr=%x\n", addr); + return -1; + } + + /* 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 ((fresh[2 * PS_Num] == AF_H) && (fresh[2 * PS_Num + 1] == AF_L)) { + 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)) */ + /* ALPS00523685:6627 CBC sometime is unreliable */ +#ifdef RDS_CBC_DEPENDENCY + 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 +#endif + { + 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 = true; + } else { + once[j * addr] = fresh[j * addr]; + once[j * addr + 1] = fresh[j * addr + 1]; + *valid = 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 = true; + else + *valid = false; +#endif + /* WCN_DBG(FM_NTC | RDSC, "PS seg=%s\n", *valid == true ? "true" : "false"); */ + WCN_DBG(FM_INF | RDSC, "bitmap=%x\n", *bm); + WCN_DBG(FM_INF | RDSC, "PS[%02x][1][2]=%x %x|%x %x|%x %x|%x %x|%x %x|%x %x|%x %x|%x %x\n", + addr, once[0], twice[0], once[1], twice[1], once[2], twice[2], once[3], twice[3], + once[4], twice[4], once[5], twice[5], once[6], twice[6], once[7], twice[7]); + return ret; +} + +struct rds_bitmap { + unsigned short bm; + signed int cnt; + signed int max_addr; + unsigned short (*bm_get)(struct rds_bitmap *thiz); + signed int (*bm_cnt_get)(struct rds_bitmap *thiz); + signed int (*bm_get_pos)(struct rds_bitmap *thiz); + signed int (*bm_clr)(struct rds_bitmap *thiz); + signed int (*bm_cmp)(struct rds_bitmap *thiz, struct rds_bitmap *that); + signed int (*bm_set)(struct rds_bitmap *thiz, unsigned char addr); +}; + +static unsigned short rds_bm_get(struct rds_bitmap *thiz) +{ + return thiz->bm; +} + +static signed int rds_bm_cnt_get(struct rds_bitmap *thiz) +{ + return thiz->cnt; +} + +#define FM_RDS_USE_SOLUTION_B + +static signed int rds_bm_get_pos(struct rds_bitmap *thiz) +{ + signed int i = thiz->max_addr; + signed int j; + + j = 0; + + while ((i > -1) && !(thiz->bm & (1 << i))) + 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 signed int rds_bm_clr(struct rds_bitmap *thiz) +{ + thiz->bm = 0x0000; + thiz->cnt = 0; + return 0; +} + +static signed int rds_bm_cmp(struct rds_bitmap *bitmap1, struct rds_bitmap *bitmap2) +{ + return (signed int) (bitmap1->bm - bitmap2->bm); +} + +static signed int rds_bm_set(struct rds_bitmap *thiz, unsigned char 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 signed int rds_g2_rt_addr_get(unsigned short blkB, unsigned char *addr) +{ + signed int ret = 0; + + if (addr == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + *addr = (unsigned char) blkB & 0x0F; + + WCN_DBG(FM_INF | RDSC, "addr=0x%02x\n", *addr); + return ret; +} + +static signed int rds_g2_txtAB_get(unsigned short blk, unsigned char *txtAB, bool *dirty) +{ + signed int ret = 0; + static bool once_dirty; /* false */ + + if (txtAB == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (dirty == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + *dirty = false; + if (*txtAB != ((blk & 0x0010) >> 4)) { + if (once_dirty) { + *txtAB = (blk & 0x0010) >> 4; + *dirty = true; /* yes, we got new txtAB code */ + once_dirty = false; + WCN_DBG(FM_NTC | RDSC, "changed! txtAB=%d\n", *txtAB); + return ret; + } + once_dirty = true; + } else { + once_dirty = false; /* txtAB is the same as last one */ + } + + WCN_DBG(FM_INF | RDSC, "txtAB=%d, %s\n", *txtAB, *dirty ? "new" : "old"); + return ret; +} + +static signed int rds_g2_rt_get(unsigned short crc, unsigned char subtype, unsigned short blkC, unsigned short blkD, + unsigned char addr, unsigned char *buf) +{ + signed int ret = 0; + bool valid = false; + signed int idx = 0; + + if (buf == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + /* 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 == 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 == 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 signed int rds_g2_rt_get_len(unsigned char subtype, signed int pos, signed int *len) +{ + signed int ret = 0; + + if (len == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + 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 whether we got a full segment, for typeA if copyed 4bytes to twice buf, for typeB 2bytes copyed to twice buf + * 3.Check whether we got the end of RT, if we got 0x0D + * 4.If we got the end, then caculate the RT length + * If success return 0, else return error code +*/ +static signed int rds_g2_rt_cmp(unsigned char addr, unsigned short cbc, unsigned char subtype, unsigned char *fresh, + unsigned char *once, unsigned char *twice, bool *valid) +{ + signed int ret = 0; + signed int i = 0; + signed int j = 0; + signed int cnt = 0; + + if (fresh == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (once == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (twice == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (valid == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + 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) */ +#ifdef RDS_CBC_DEPENDENCY + if (cbc == 0) { +#endif + once[j * addr + 0] = fresh[j * addr + 0]; + once[j * addr + 1] = fresh[j * addr + 1]; + once[j * addr + 2] = fresh[j * addr + 2]; + once[j * addr + 3] = fresh[j * addr + 3]; +#ifdef RDS_CBC_DEPENDENCY + } +#endif + } else if (subtype == RDS_GRP_VER_B) { +#ifdef RDS_CBC_DEPENDENCY + if (cbc == 0) { +#endif + once[j * addr + 0] = fresh[j * addr + 0]; + once[j * addr + 1] = fresh[j * addr + 1]; +#ifdef RDS_CBC_DEPENDENCY + } +#endif + } +#ifdef RDS_CBC_DEPENDENCY + 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); */ + } + } +#else + for (i = 0; i < j; i++) { + if (twice[j * addr + i] == once[j * addr + i]) { + cnt++; + /* WCN_DBG(FM_NTC | RDSC, "twice=%d\n", j * addr + i); */ + } else { + twice[j * addr + i] = once[j * addr + i]; + /* WCN_DBG(FM_NTC | RDSC, "once=%d\n", j * addr + i); */ + } + } +#endif + + /* check if we got a valid segment 4bytes for typeA, 2bytes for typeB */ + if (cnt == j) + *valid = true; + else + *valid = false; + + WCN_DBG(FM_INF | RDSC, "RT seg=%s\n", *valid == true ? "true" : "false"); +/* WCN_DBG(FM_INF | RDSC, "RT end=%s\n", *end == true ? "true" : "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 length + * If success return 0, else return error code +*/ +static signed int rds_g2_rt_check_end(unsigned char addr, unsigned char subtype, unsigned char *twice, bool *end) +{ + signed int i = 0; + signed int j = 0; + + if (twice == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (end == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + j = (subtype == RDS_GRP_VER_A) ? 4 : 2; /* RT segment width */ + *end = false; + + for (i = 0; i < j; i++) { + /* if we got 0x0D twice, it means a RT end */ + if (twice[j * addr + i] == 0x0D) { + *end = true; + WCN_DBG(FM_NTC | RDSC, "get 0x0D\n"); + break; + } + } + + return 0; +} + +static signed int rds_retrieve_g0_af(unsigned short *block_data, unsigned char SubType, struct rds_t *pstRDSData) +{ + static signed short preAF_Num; + unsigned char indx, indx2, AF_H, AF_L, num; + signed short temp_H, temp_L; + signed int ret = 0; + bool valid = false; + bool dirty = false; + unsigned short *event = &pstRDSData->event_status; + unsigned int *flag = &pstRDSData->RDSFlag.flag_status; + +/* ret = rds_checksum_check(block_data[4], FM_RDS_GDBK_IND_D, &valid); */ + +/* if (valid == 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 == 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 == 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 B no AF information */ + goto out; + + /* Type A */ + + ret = rds_checksum_check(block_data[4], FM_RDS_GDBK_IND_C, &valid); + + if (valid == false) { + WCN_DBG(FM_WAR | RDSC, "Group0 BlockC crc err\n"); + return -FM_ECRC; + } + + 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_INF | 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 */ + pstRDSData->AF_Data.AF[0][0] *= 10; + 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 > 25) ? 25 : num; + num = num >> 1; + WCN_DBG(FM_INF | RDSC, "RetrieveGroup0 +num:%d\n", num); + + /* Put AF freq into 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] / 10 - 875)) + && (AF_L == (pstRDSData->AF_Data.AF[0][2 * indx] / 10 - 875))) { + WCN_DBG(FM_NTC | RDSC, + "RetrieveGroup0 +num:%d AF same as indx:%d\n", num, indx); + break; + } else if (!(pstRDSData->AF_Data.AF[0][2 * indx - 1])) { + /* null buffer */ + /* convert to 100KHz */ + pstRDSData->AF_Data.AF[0][2 * indx - 1] = AF_H + 875; + pstRDSData->AF_Data.AF[0][2 * indx] = AF_L + 875; + + pstRDSData->AF_Data.AF[0][2 * indx - 1] *= 10; + pstRDSData->AF_Data.AF[0][2 * indx] *= 10; + + WCN_DBG(FM_NTC | RDSC, + "RetrieveGroup0 +num:%d AF[0][%d]:%d, AF[0][%d]:%d\n", + num, 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; + num = (num > 25) ? 25 : num; + WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 ++num:%d\n", num); + + if (num <= 0) + goto out; + + if ((pstRDSData->AF_Data.AF[0][num - 1]) == 0) + goto out; + + 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++) { + temp_H = pstRDSData->AF_Data.AF[0][2 * indx - 1]; + temp_L = pstRDSData->AF_Data.AF[0][2 * indx]; + + if (temp_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] = temp_H; + pstRDSData->AF_Data.AF[0][2 * indx2] = temp_L; + } else if (temp_H == (pstRDSData->AF_Data.AF[0][2 * indx2 - 1])) { + if (temp_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] = temp_H; + pstRDSData->AF_Data.AF[0][2 * indx2] = temp_L; + } + } + } + } + + /* arrange frequency from low to high:end */ + /* compare AF buff0 and buff1 data:start */ + num = pstRDSData->AF_Data.AF_Num; + num = (num > 25) ? 25 : 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; + } + +out: return ret; +} + +static signed int rds_retrieve_g0_di(unsigned short *block_data, unsigned char SubType, struct rds_t *pstRDSData) +{ + unsigned char DI_Code, DI_Flag; + signed int ret = 0; +/* bool valid = false; */ + + unsigned short *event = &pstRDSData->event_status; + unsigned int *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 == 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 signed int rds_retrieve_g0_ps(unsigned short *block_data, unsigned char SubType, struct rds_t *pstRDSData) +{ + unsigned char ps_addr; + signed int ret = 0, i, num; + bool valid = false; +/* signed int 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 + unsigned short *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 == 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 == 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 */ + STATE_SET(&ps_sm, RDS_PS_GETLEN); + } else { + STATE_SET(&ps_sm, RDS_PS_FINISH); + } + + break; + case RDS_PS_GETLEN: + { + num = 0; + WCN_DBG(FM_INF | 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++) { + /* even ps=0x20 and bitmap=0xF, send event to host to cover last ps. */ + if (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); + WCN_DBG(FM_NTC | RDSC, "Yes, get an PS!\n"); + } else { + /* clear bitmap */ + pstRDSData->PS_Data.Addr_Cnt = 0; + } + } else { + /* if px3==ps2,clear bitmap */ + pstRDSData->PS_Data.Addr_Cnt = 0; + /* clear buf */ + fm_memset(pstRDSData->PS_Data.PS[0], 0x00, 8); + fm_memset(pstRDSData->PS_Data.PS[1], 0x00, 8); + fm_memset(pstRDSData->PS_Data.PS[2], 0x00, 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; + default: + break; + } + } + +out: + return ret; +} + +static signed int rds_retrieve_g0(unsigned short *block_data, unsigned char SubType, struct rds_t *pstRDSData) +{ + signed int 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 signed int rds_ecc_get(unsigned short blk, unsigned char *ecc, bool *dirty) +{ + signed int ret = 0; + + if (ecc == NULL) { + pr_err("%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (dirty == NULL) { + pr_err("%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + if (*ecc != (blk & 0xFF)) { + *ecc = (unsigned char)blk & 0xFF; + *dirty = true; /* yes, we got new ecc code */ + } else { + *dirty = false; /* ecc is the same as last one */ + } + + WCN_DBG(FM_NTC | RDSC, "ecc=%02x, %s\n", *ecc, *dirty ? "new" : "old"); + return ret; +} + +static signed int rds_retrieve_g1(unsigned short *block_data, unsigned char SubType, struct rds_t *pstRDSData) +{ + unsigned char variant_code = (block_data[2] & 0x7000) >> 12; + signed int ret = 0; + bool dirty = false; + + if (variant_code == 0) { + ret = rds_ecc_get(block_data[2], &pstRDSData->Extend_Country_Code, &dirty); + if (!ret) { + if (dirty == true) + rds_event_set(&pstRDSData->event_status, RDS_EVENT_ECC_CODE); + } else + WCN_DBG(FM_ERR | RDSC, "get ecc fail(%d)\n", ret); + 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 signed int rds_retrieve_g2(unsigned short *source, unsigned char subtype, struct rds_t *target) +{ + signed int ret = 0; + unsigned short crc, cbc; + unsigned short blkA, blkB, blkC, blkD; + unsigned char *fresh, *once, *twice, *display; + unsigned short *event; + unsigned int *flag; + unsigned short i = 0; + 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, + }; + unsigned char rt_addr = 0; + bool txtAB_change = false; /* text AB flag 0 --> 1 or 1-->0 meas new RT incoming */ + bool txt_end = false; /* 0x0D means text end */ + bool seg_ok = 0; + signed int pos = 0; + signed int rt_len = 0, indx = 0, invalid_cnt = 0; + signed int bufsize = 0; + + if (source == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (target == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + /* 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 == 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 == true) + STATE_SET(&rt_sm, RDS_RT_DECISION); + else +#endif + { + if (rds_g2_rt_get(crc, subtype, blkC, blkD, rt_addr, fresh) == 0) { + rds_g2_rt_cmp(rt_addr, cbc, subtype, fresh, once, twice, &seg_ok); + + if (seg_ok == true) + rt_bm.bm_set(&rt_bm, rt_addr); + else + 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 == 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); + + if (pos == -1) { + STATE_SET(&rt_sm, RDS_RT_FINISH); + } else { + if (rt_addr == pos) { + STATE_SET(&rt_sm, RDS_RT_GETLEN); + } else if (pos > rt_addr) { + rt_bm.bm &= ~(1 << (rt_addr + 1)); + STATE_SET(&rt_sm, RDS_RT_FINISH); + } else + STATE_SET(&rt_sm, RDS_RT_FINISH); + } + + if (txt_end == true) { + for (i = rt_addr + 1; i < rt_bm.max_addr; i++) + rt_bm.bm &= ~(1 << i); + } + } else { + STATE_SET(&rt_sm, RDS_RT_FINISH); + } + + break; + } + case RDS_RT_GETLEN: + if (rt_len > 0) { + 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 == true) { + txtAB_change = 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; + default: + break; + } + } + +out: + target->RT_Data.Addr_Cnt = rt_bm.bm; + return ret; +} + +static signed int rds_retrieve_g4(unsigned short *block_data, unsigned char SubType, struct rds_t *pstRDSData) +{ + unsigned short year, month, k = 0, D2, minute; + unsigned int MJD, D1; + signed int 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 = (unsigned int) (((block_data[1] & 0x0003) << 15) + ((block_data[2] & 0xFFFE) >> 1)); + year = (MJD * 100 - 1507820) / 36525; + + if (year > 1000) { + WCN_DBG(FM_DBG | RDSC, "Abnormal year: %d.\n", year); + return ret; + } + + month = (MJD * 10000 - 149561000 - 3652500 * year) / 306001; + + if ((month == 14) || (month == 15)) + k = 1; + + D1 = (unsigned int) ((36525 * year) / 100); + D2 = (unsigned short) ((306001 * month) / 10000); + pstRDSData->CT.Year = 1900 + year + k; + pstRDSData->CT.Month = month - 1 - k * 12; + pstRDSData->CT.Day = (unsigned short) (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 signed int rds_retrieve_g14(unsigned short *block_data, unsigned char SubType, struct rds_t *pstRDSData) +{ + static signed short preAFON_Num; + unsigned char TP_ON, TA_ON, PI_ON, AF_H, AF_L, indx, indx2, num; + unsigned short PS_Num = 0; + signed int 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; /* variant code */ + + if (PS_Num >= 0 && PS_Num < 4) { /* variant code = 0~3 represent PS */ + 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; + } + + goto out; + } else if (PS_Num < 0 || PS_Num > 4) /* variant code > 4 */ + goto out; + + /* variant code = 4 represent AF(ON) */ + + 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; + } + + goto out; + } + + if (!(pstRDSData->AFON_Data.isAFNum_Get) || ((pstRDSData->AFON_Data.Addr_Cnt) == 0xFF)) + goto out; + + /* AF Num correct */ + num = pstRDSData->AFON_Data.AF_Num; + num = (num > 25) ? 25 : num; + num = num >> 1; + + /* Put AF freq into 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; + num = (num > 25) ? 25 : num; + if (num <= 0) + goto out; + + if ((pstRDSData->AFON_Data.AF[0][num - 1]) == 0) + goto out; + + 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; + num = (num > 25) ? 25 : 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) { + signed int 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; + } + } + +out: 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 + */ +signed int rds_parser(struct rds_t *rds_dst, struct rds_rx_t *rds_raw, + signed int rds_size, unsigned short(*getfreq) (void)) +{ + signed int 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 */ + unsigned short block_data[6]; + unsigned char GroupType, SubType = 0; + signed int rds_cnt = 0; + signed int i = 0; + bool dirty = false; + /* target buf to fill the result in */ + unsigned short *event = &rds_dst->event_status; + unsigned int *flag = &rds_dst->RDSFlag.flag_status; + + if (getfreq == NULL) { + WCN_DBG(FM_ERR | RDSC, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + 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 == false) { + WCN_DBG(FM_INF | RDSC, "dirty = %d, update PI event\n", dirty); + ret = rds_event_set(event, RDS_EVENT_PI_CODE); /* yes, we got same PI, can be trust */ + } + + 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 == 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 == 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: + ret = rds_retrieve_g0(&block_data[0], SubType, rds_dst); + if (ret) + goto do_next; + + break; + case 1: + ret = rds_retrieve_g1(&block_data[0], SubType, rds_dst); + if (ret) + goto do_next; + + break; + case 2: + ret = rds_retrieve_g2(&block_data[0], SubType, rds_dst); + if (ret) + goto do_next; + + break; + case 4: + ret = rds_retrieve_g4(&block_data[0], SubType, rds_dst); + if (ret) + goto do_next; + + break; + case 14: + ret = rds_retrieve_g14(&block_data[0], SubType, rds_dst); + if (ret) + 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/misc/mediatek/connectivity/fmradio/core/fm_reg_utils.c b/drivers/misc/mediatek/connectivity/fmradio/core/fm_reg_utils.c new file mode 100644 index 0000000000000..24e4851d9e066 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/core/fm_reg_utils.c @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_stdlib.h" +#include "fm_link.h" +#include "fm_utils.h" +#include "fm_reg_utils.h" +#include "plat.h" + +struct fm_wcn_reg_ops fm_wcn_ops; +unsigned char *cmd_buf; +struct fm_lock *cmd_buf_lock; +struct fm_res_ctx *fm_res; + +void fw_spi_read(unsigned char addr, unsigned short *data) +{ + struct fm_spi_interface *si = &fm_wcn_ops.si; + int ret = 0; + unsigned int rdata; + + ret = si->sys_spi_read(si, SYS_SPI_FM, addr, &rdata); + if (ret) + WCN_DBG(FM_ERR | CHIP, "read error[%d].\n", ret); + *data = (unsigned short)rdata; +} + +void fw_spi_write(unsigned char addr, unsigned short data) +{ + struct fm_spi_interface *si = &fm_wcn_ops.si; + int ret = 0; + unsigned int wdata = (unsigned int)data; + + ret = si->sys_spi_write(si, SYS_SPI_FM, addr, wdata); + if (ret) + WCN_DBG(FM_ERR | CHIP, "write error[%d].\n", ret); +} + +void fw_bop_udelay(unsigned int usec) +{ + fm_delayus(usec); +} + +void fw_bop_rd_until(unsigned char addr, unsigned short mask, + unsigned short value) +{ + unsigned short data, count = 0; + + do { + fm_delayus(1000); + fw_spi_read(addr, &data); + count++; + } while (((data & mask) != value) && (count < 3000)); + + /* 3000ms should be big enough for polling bits */ + if (count == 3000) + WCN_DBG(FM_WAR | CHIP, "Value is never changed.\n"); +} + +void fw_bop_modify(unsigned char addr, unsigned short mask_and, + unsigned short mask_or) +{ + unsigned short data; + + fw_spi_read(addr, &data); + data &= mask_and; + data |= mask_or; + fw_spi_write(addr, data); +} + +void fw_bop_spi_rd_until(unsigned char subsys, unsigned short addr, + unsigned int mask, unsigned int value) +{ + struct fm_spi_interface *si = &fm_wcn_ops.si; + unsigned int data; + unsigned short count = 0; + + do { + fm_delayus(1000); + si->sys_spi_read(si, subsys, addr, &data); + count++; + } while (((data & mask) != value) && (count < 3000)); + + /* 3000ms should be big enough for polling bits */ + if (count == 3000) + WCN_DBG(FM_WAR | CHIP, "Value is never changed.\n"); +} + +void fw_bop_spi_modify(unsigned char subsys, unsigned short addr, + unsigned int mask_and, unsigned int mask_or) +{ + struct fm_spi_interface *si = &fm_wcn_ops.si; + unsigned int data; + + si->sys_spi_read(si, subsys, addr, &data); + data &= mask_and; + data |= mask_or; + si->sys_spi_write(si, subsys, addr, data); +} diff --git a/drivers/misc/mediatek/connectivity/fmradio/core/fm_utils.c b/drivers/misc/mediatek/connectivity/fmradio/core/fm_utils.c new file mode 100644 index 0000000000000..3de38f1ddddd5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/core/fm_utils.c @@ -0,0 +1,808 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_stdlib.h" +#include "fm_utils.h" + +signed int fm_delayms(unsigned int data) +{ + WCN_DBG(FM_DBG | CHIP, "delay %dms\n", data); + msleep(data); + return 0; +} + +signed int fm_delayus(unsigned int data) +{ + WCN_DBG(FM_DBG | CHIP, "delay %dus\n", data); + udelay(data); + return 0; +} + +static unsigned int fm_event_send(struct fm_flag_event *thiz, unsigned int 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 signed int fm_event_wait(struct fm_flag_event *thiz, unsigned int 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 unsigned int + * @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, unsigned int mask, long timeout) +{ + return wait_event_timeout(*((wait_queue_head_t *) (thiz->priv)), ((thiz->flag & mask) == mask), timeout * HZ); +} + +static unsigned int fm_event_clr(struct fm_flag_event *thiz, unsigned int mask) +{ + thiz->flag &= ~mask; + /* WCN_DBG(FM_DBG|MAIN, "%s clr 0x%08x\n", thiz->name, thiz->flag); */ + return thiz->flag; +} + +static unsigned int fm_event_get(struct fm_flag_event *thiz) +{ + return thiz->flag; + +} + +static unsigned int fm_event_rst(struct fm_flag_event *thiz) +{ + return thiz->flag = 0; +} + +struct fm_flag_event *fm_flag_event_create(const signed char *name) +{ + struct fm_flag_event *tmp; + wait_queue_head_t *wq; + + tmp = fm_zalloc(sizeof(struct fm_flag_event)); + if (!tmp) { + WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_event) -ENOMEM\n"); + return NULL; + } + + wq = fm_zalloc(sizeof(wait_queue_head_t)); + if (!wq) { + 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; +} + +signed int fm_flag_event_get(struct fm_flag_event *thiz) +{ + if (thiz == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + thiz->ref++; + return 0; +} + +signed int fm_flag_event_put(struct fm_flag_event *thiz) +{ + if (thiz == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + 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 signed int fm_lock_try(struct fm_lock *thiz, signed int retryCnt) +{ + signed int retry_cnt = 0; + struct semaphore *sem; + struct task_struct *task = current; + + if (thiz == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (thiz->priv == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + 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 signed int fm_lock_lock(struct fm_lock *thiz) +{ + struct semaphore *sem; + struct task_struct *task = current; + + if (thiz == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (thiz->priv == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + 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_DBG | MAIN, "%s --->lock, cnt=%d, pid=%d\n", + thiz->name, (int)sem->count, task->pid); + return 0; +} + +static signed int fm_lock_unlock(struct fm_lock *thiz) +{ + struct semaphore *sem; + struct task_struct *task = current; + + if (thiz == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (thiz->priv == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + sem = (struct semaphore *)thiz->priv; + WCN_DBG(FM_DBG | 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 signed char *name) +{ + struct fm_lock *tmp; + struct semaphore *mutex; + + tmp = fm_zalloc(sizeof(struct fm_lock)); + if (!tmp) { + WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_lock) -ENOMEM\n"); + return NULL; + } + + mutex = fm_zalloc(sizeof(struct semaphore)); + if (!mutex) { + 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; +} + +signed int fm_lock_get(struct fm_lock *thiz) +{ + if (thiz == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + thiz->ref++; + return 0; +} + +signed int fm_lock_put(struct fm_lock *thiz) +{ + if (thiz == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + 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 signed int fm_spin_lock_lock(struct fm_lock *thiz) +{ + struct task_struct *task = current; + + if (thiz == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (thiz->priv == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + spin_lock_bh((spinlock_t *) thiz->priv); + + WCN_DBG(FM_DBG | MAIN, "%s --->lock pid=%d\n", thiz->name, task->pid); + return 0; +} + +static signed int fm_spin_lock_unlock(struct fm_lock *thiz) +{ + struct task_struct *task = current; + + if (thiz == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (thiz->priv == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + WCN_DBG(FM_DBG | 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 signed char *name) +{ + struct fm_lock *tmp; + spinlock_t *spin_lock; + + tmp = fm_zalloc(sizeof(struct fm_lock)); + if (!tmp) { + WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_lock) -ENOMEM\n"); + return NULL; + } + + spin_lock = fm_zalloc(sizeof(spinlock_t)); + if (!spin_lock) { + 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; +} + +signed int fm_spin_lock_get(struct fm_lock *thiz) +{ + if (thiz == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + thiz->ref++; + return 0; +} + +signed int fm_spin_lock_put(struct fm_lock *thiz) +{ + if (thiz == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + 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 + * + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) +static signed int fm_timer_init(struct fm_timer *thiz, void (*timeout) (struct timer_list *timer), + unsigned long data, signed long time, signed int flag) +#else +static signed int fm_timer_init(struct fm_timer *thiz, void (*timeout) (unsigned long data), + unsigned long data, signed long time, signed int flag) +#endif +{ + 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; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) + timer_setup(timerlist, thiz->timeout_func, 0); +#else + init_timer(timerlist); + timerlist->function = thiz->timeout_func; + timerlist->data = (unsigned long)thiz->data; +#endif + timerlist->expires = jiffies + (thiz->timeout_ms) / (1000 / HZ); + + return 0; +} + +static signed int 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 signed int 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 signed int 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 signed int fm_timer_control(struct fm_timer *thiz, enum fm_timer_ctrl cmd, void *arg) +{ + + return 0; +} + +struct fm_timer *fm_timer_create(const signed char *name) +{ + struct fm_timer *tmp; + struct timer_list *timerlist; + + tmp = fm_zalloc(sizeof(struct fm_timer)); + if (!tmp) { + WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_timer) -ENOMEM\n"); + return NULL; + } + + timerlist = fm_zalloc(sizeof(struct timer_list)); + if (!timerlist) { + WCN_DBG(FM_ALT | MAIN, "fm_zalloc(struct timer_list) -ENOMEM\n"); + fm_free(tmp); + return NULL; + } + + 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; +} + +signed int fm_timer_get(struct fm_timer *thiz) +{ + if (thiz == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + thiz->ref++; + return 0; +} + +signed int fm_timer_put(struct fm_timer *thiz) +{ + if (thiz == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + 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 signed int fm_work_init(struct fm_work *thiz, work_func_t work_func, 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 signed char *name) +{ + struct fm_work *my_work; + struct work_struct *sys_work; + + my_work = fm_zalloc(sizeof(struct fm_work)); + if (!my_work) { + WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_work) -ENOMEM\n"); + return NULL; + } + + sys_work = fm_zalloc(sizeof(struct work_struct)); + if (!sys_work) { + 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; +} + +signed int fm_work_get(struct fm_work *thiz) +{ + if (thiz == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + thiz->ref++; + return 0; +} + +signed int fm_work_put(struct fm_work *thiz) +{ + if (thiz == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + 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 signed int fm_workthread_add_work(struct fm_workthread *thiz, struct fm_work *work) +{ + if (thiz == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + if (work == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + queue_work((struct workqueue_struct *)thiz->priv, (struct work_struct *)work->priv); + return 0; +} + +struct fm_workthread *fm_workthread_create(const signed char *name) +{ + struct fm_workthread *my_thread; + struct workqueue_struct *sys_thread; + + my_thread = fm_zalloc(sizeof(struct fm_workthread)); + if (!my_thread) { + 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; +} + +signed int fm_workthread_get(struct fm_workthread *thiz) +{ + if (thiz == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + thiz->ref++; + return 0; +} + +signed int fm_workthread_put(struct fm_workthread *thiz) +{ + if (thiz == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + 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; + } +} + +signed int fm_fifo_in(struct fm_fifo *thiz, void *item) +{ + if (item == NULL) { + WCN_DBG(FM_ERR | MAIN, "%s,invalid pointer\n", __func__); + return -FM_EPARA; + } + + 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; +} + +signed int 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; +} + +bool fm_fifo_is_full(struct fm_fifo *thiz) +{ + return (thiz->len == thiz->size) ? true : false; +} + +bool fm_fifo_is_empty(struct fm_fifo *thiz) +{ + return (thiz->len == 0) ? true : false; +} + +signed int fm_fifo_get_total_len(struct fm_fifo *thiz) +{ + return thiz->size; +} + +signed int fm_fifo_get_valid_len(struct fm_fifo *thiz) +{ + return thiz->len; +} + +signed int 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 signed char *name, signed int item_size, + signed int 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 signed char *name, signed int item_size, signed int item_num) +{ + struct fm_fifo *tmp; + void *buf; + + tmp = fm_zalloc(sizeof(struct fm_fifo)); + if (!tmp) { + WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_fifo) -ENOMEM\n"); + return NULL; + } + + buf = fm_zalloc(item_size * item_num); + if (!buf) { + 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; +} + +signed int 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; +} + +unsigned short fm_get_u16_from_auc(unsigned char *buf) +{ + return (unsigned short)((unsigned short)buf[0] + ((unsigned short) buf[1] << 8)); +} + +void fm_set_u16_to_auc(unsigned char *buf, unsigned short val) +{ + buf[0] = (unsigned char)(val & 0xFF); + buf[1] = (unsigned char)(val >> 8); +} + +unsigned int fm_get_u32_from_auc(unsigned char *buf) +{ + return ((unsigned int)(*buf) + ((unsigned int)(*(buf + 1)) << 8) + + ((unsigned int)(*(buf + 2)) << 16) + ((unsigned int)(*(buf + 3)) << 24)); +} + +void fm_set_u32_to_auc(unsigned char *buf, unsigned int val) +{ + buf[0] = (unsigned char)val; + buf[1] = (unsigned char)(val >> 8); + buf[2] = (unsigned char)(val >> 16); + buf[3] = (unsigned char)(val >> 24); +} diff --git a/drivers/misc/mediatek/connectivity/fmradio/dummy.c b/drivers/misc/mediatek/connectivity/fmradio/dummy.c new file mode 100644 index 0000000000000..872b38b4a31a0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/dummy.c @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* dummy.c + * This dummy file is just for meetting the build system's rule. + */ diff --git a/drivers/misc/mediatek/connectivity/fmradio/inc/fm_cmd.h b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_cmd.h new file mode 100644 index 0000000000000..7ec1a88165681 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_cmd.h @@ -0,0 +1,96 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef __FM_CMD_H__ +#define __FM_CMD_H__ + +#include +#include "fm_typedef.h" +#include "fm_patch.h" +#include "fm_link.h" +#include "fm_reg_utils.h" + +extern unsigned char *cmd_buf; +extern struct fm_lock *cmd_buf_lock; +extern struct fm_res_ctx *fm_res; +extern unsigned char top_index; + +#define PATCH_SEG_LEN 512 +enum IMG_TYPE { + IMG_WRONG = 0, + IMG_ROM, + IMG_PATCH, + IMG_COEFFICIENT, + IMG_HW_COEFFICIENT +}; + +/* FM BOP's size */ +#define FM_TOP_WRITE_BOP_SIZE (7) +#define FM_TOP_RD_UNTIL_BOP_SIZE (11) +#define FM_TOP_MODIFY_BOP_SIZE (11) + +#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) + +signed int fm_bop_write(unsigned char addr, unsigned short value, unsigned char *buf, signed int size); +signed int fm_bop_udelay(unsigned int value, unsigned char *buf, signed int size); +signed int fm_bop_rd_until(unsigned char addr, unsigned short mask, unsigned short value, unsigned char *buf, + signed int size); +signed int fm_bop_modify(unsigned char addr, unsigned short mask_and, unsigned short mask_or, unsigned char *buf, + signed int size); +signed int fm_bop_top_write(unsigned short addr, unsigned int value, unsigned char *buf, signed int size); +signed int fm_bop_top_rd_until(unsigned short addr, unsigned int mask, unsigned int value, unsigned char *buf, + signed int size); +signed int fm_op_seq_combine_cmd(unsigned char *buf, unsigned char opcode, signed int pkt_size); +signed int fm_get_reg(unsigned char *buf, signed int buf_size, unsigned char addr); +signed int fm_set_reg(unsigned char *buf, signed int buf_size, unsigned char addr, unsigned short value); +signed int fm_patch_download(unsigned char *buf, signed int buf_size, unsigned char seg_num, unsigned char seg_id, + const unsigned char *src, signed int seg_len); +signed int fm_coeff_download(unsigned char *buf, signed int buf_size, unsigned char seg_num, unsigned char seg_id, + const unsigned char *src, signed int seg_len); +signed int fm_full_cqi_req(unsigned char *buf, signed int buf_size, unsigned short *freq, signed int cnt, + signed int type); +signed int fm_top_get_reg(unsigned char *buf, signed int buf_size, unsigned short addr); +signed int fm_top_set_reg(unsigned char *buf, signed int buf_size, unsigned short addr, unsigned int value); +signed int fm_host_get_reg(unsigned char *buf, signed int buf_size, unsigned int addr); +signed int fm_host_set_reg(unsigned char *buf, signed int buf_size, unsigned int addr, unsigned int value); +signed int fm_set_bits_reg(unsigned char *buf, signed int buf_size, unsigned char addr, unsigned short bits, + unsigned short mask); +signed int fm_pmic_get_reg(unsigned char *buf, signed int buf_size, unsigned char addr); +signed int fm_pmic_set_reg(unsigned char *buf, signed int buf_size, unsigned char addr, unsigned int val); +signed int fm_pmic_mod_reg(unsigned char *buf, signed int buf_size, unsigned char addr, unsigned int mask_and, + unsigned int mask_or); +signed int fm_get_patch_path(signed int ver, unsigned char *buff, int buffsize, struct fm_patch_tbl *patch_tbl); +signed int fm_get_coeff_path(signed int ver, unsigned char *buff, int buffsize, struct fm_patch_tbl *patch_tbl); +signed int fm_download_patch(const unsigned char *img, signed int len, enum IMG_TYPE type); +signed int fm_get_read_result(struct fm_res_ctx *result); +signed int fm_reg_read(unsigned char addr, unsigned short *val); +signed int fm_reg_write(unsigned char addr, unsigned short val); +signed int fm_set_bits(unsigned char addr, unsigned short bits, unsigned short mask); +signed int fm_top_reg_read(unsigned short addr, unsigned int *val); +signed int fm_top_reg_write(unsigned short addr, unsigned int val); +signed int fm_host_reg_read(unsigned int addr, unsigned int *val); +signed int fm_host_reg_write(unsigned int addr, unsigned int val); + +/* + * 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 signed int fm_get_channel_space(int freq); + +#endif diff --git a/drivers/misc/mediatek/connectivity/fmradio/inc/fm_config.h b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_config.h new file mode 100644 index 0000000000000..ebd369db88114 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_config.h @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __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" +#include "fm_interface.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 + +#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 */ + +/* space */ +#define FM_SPACE_UNKNOWN 0 +#define FM_SPACE_100K 1 +#define FM_SPACE_200K 2 +#define FM_SPACE_50K 5 + +#define FM_INVALID_CHAN_NOISE_REDUCING 0 + +#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 + +/* ***************************************************************************************** */ +/* ***************************FM default config for customer: start************************* */ +/* ***************************************************************************************** */ + +/* RX */ +#define FM_RX_RSSI_TH_LONG -296 /* FM radio long antenna RSSI threshold(-4dBuV) */ +#define FM_RX_RSSI_TH_SHORT -296 /* FM radio short antenna RSSI threshold(-4dBuV) */ +#define FM_RX_DESENSE_RSSI -240 +#define FM_RX_PAMD_TH -12 +#define FM_RX_MR_TH -67 +#define FM_RX_ATDC_TH 3496 +#define FM_RX_PRX_TH 64 +#define FM_RX_SMG_TH 16421 /* FM soft-mute gain threshold */ +#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 */ +#define FM_AUTO_HILO_OFF 0 +#define FM_AUTO_HILO_ON 1 + +/* seek threshold */ +#define FM_SEEKTH_LEVEL_DEFAULT 4 + +/* TX threshold*/ +/* #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 */ +#define FM_TX_PAMD_TH -23 +#define FM_TX_MR_TH 60 +#define FM_TX_SMG_TH 8231 + +/* ***************************************************************************************** */ +/* ***************************FM default config for customer: end*************************** */ +/* ***************************************************************************************** */ + +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 +}; + +#define COMMENT_CHAR '#' +#define DELIMIT_CHAR '=' + +#define isspace(a) ((a) == 0x20) + +struct fm_rx_cust_cfg { + signed int desene_rssi_th; + signed int pamd_th; + signed int mr_th; + signed int atdc_th; + signed int prx_th; + signed int atdev_th; + signed int short_ana_rssi_th; + signed int long_ana_rssi_th; + signed int cqi_th; + signed int smg_th; + signed int deemphasis; + signed int osc_freq; +}; + +struct fm_tx_cust_cfg { + signed int scan_hole_low; + signed int scan_hole_high; + signed int power_level; + signed int pamd_th; + signed int mr_th; + signed int smg_th; +}; +struct fm_cust_cfg { + struct fm_rx_cust_cfg rx_cfg; + struct fm_tx_cust_cfg tx_cfg; + struct fm_audio_info_t aud_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_DEEMPHASIS, + FM_CFG_RX_OSC_FREQ, + FM_CFG_RX_DESENSE_RSSI_TH, + FM_CFG_RX_PAMD_TH, + FM_CFG_RX_ATDC_TH, + FM_CFG_RX_PRX_TH, + FM_CFG_RX_ATDEV_TH, + + FM_CFG_TX_SCAN_HOLE_LOW, + FM_CFG_TX_SCAN_HOLE_HIGH, + FM_CFG_TX_PWR_LEVEL, + FM_CFG_TX_PAMD_TH, + FM_CFG_TX_DEEMPHASIS, + FM_CFG_TX_SMG_TH, + + FM_CFG_MAX +}; + +enum fm_cfg_chip_type { + FM_COMBO_CHIP = 0, + FM_AD_DIE_CHIP, + FM_SOC_CHIP, + FM_CHIP_TYPE_MAX +}; + +typedef signed int(*CFG_HANDLER) (signed char *grp, signed char *key, signed char *val, struct fm_cust_cfg *cfg); +extern signed int to_upper_n(signed char *str, signed int len); +extern signed int check_hex_str(signed char *str, signed int len); +extern signed int check_dec_str(signed char *str, signed int len); +extern signed int ascii_to_hex(signed char *in_ascii, unsigned short *out_hex); +extern signed int ascii_to_dec(signed char *in_ascii, signed int *out_dec); +extern signed int trim_string(signed char **start); +extern signed int trim_path(signed char **start); +extern signed int cfg_parser(signed char *buffer, CFG_HANDLER handler, struct fm_cust_cfg *cfg); +extern signed int cfg_item_match(signed char *src_key, signed char *src_val, signed char *dst_key, signed int *dst_val); + +extern signed int fm_cust_config_setup(const signed char *filename); +extern unsigned short fm_cust_config_fetch(enum fm_cust_cfg_op op_code); +extern unsigned short fm_cust_config_chip(unsigned short chipid, enum fm_cfg_chip_type type); + +extern struct fm_cust_cfg fm_config; +extern unsigned short g_fm_chipid; +extern enum fm_cfg_chip_type g_fm_chip_type; +#endif /* __FM_CONFIG_H__ */ diff --git a/drivers/misc/mediatek/connectivity/fmradio/inc/fm_dbg.h b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_dbg.h new file mode 100644 index 0000000000000..d8da8421dbef1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_dbg.h @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __FM_DBG_H__ +#define __FM_DBG_H__ + +/* #include //for printk() */ +#include +#include + +/* 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 +#define FM_DEF(x) ((x)&0x0000000f) + +extern unsigned int g_dbg_level; + +#define WCN_DBG(flag, fmt, args...) \ + do { \ + if ((FM_DEF(flag) <= (g_dbg_level&0x0000000f)) && ((flag)&ALL) & g_dbg_level) { \ + pr_info("[" #flag "] %s: " fmt, __func__, ## args); \ + } \ + } while (0) + +#define WCN_DBG_LIMITED(flag, fmt, args...) \ + do { \ + if ((FM_DEF(flag) <= (g_dbg_level&0x0000000f)) && ((flag)&ALL) & g_dbg_level) { \ + pr_info_ratelimited("[" #flag "]" fmt, ## args); \ + } \ + } while (0) + +#define FM_LOG_DBG(flag, fmt, args...) \ + do { \ + if ((FM_DBG <= (g_dbg_level&0x0000000f)) && ((flag)&0xfffffff0) & g_dbg_level) { \ + pr_info("[" #flag "]" fmt, ## args); \ + } \ + } while (0) + +#define FM_LOG_INF(flag, fmt, args...) \ + do { \ + if ((FM_INF <= (g_dbg_level&0x0000000f)) && ((flag)&0xfffffff0) & g_dbg_level) { \ + pr_info("[" #flag "]" fmt, ## args); \ + } \ + } while (0) + +#define FM_LOG_NTC(flag, fmt, args...) \ + do { \ + if ((FM_NTC <= (g_dbg_level&0x0000000f)) && ((flag)&0xfffffff0) & g_dbg_level) { \ + pr_info("[" #flag "]" fmt, ## args); \ + } \ + } while (0) + +#define FM_LOG_WAR(flag, fmt, args...) \ + do { \ + if ((FM_WAR <= (g_dbg_level&0x0000000f)) && ((flag)&0xfffffff0) & g_dbg_level) { \ + pr_notice("[" #flag "]" fmt, ## args); \ + } \ + } while (0) + +#define FM_LOG_ERR(flag, fmt, args...) \ + do { \ + if ((FM_ERR <= (g_dbg_level&0x0000000f)) && ((flag)&0xfffffff0) & g_dbg_level) { \ + pr_notice("[" #flag "]" fmt, ## args); \ + } \ + } while (0) + +#define FM_LOG_CRT(flag, fmt, args...) \ + do { \ + if ((FM_CRT <= (g_dbg_level&0x0000000f)) && ((flag)&0xfffffff0) & g_dbg_level) { \ + pr_notice("[" #flag "]" fmt, ## args); \ + } \ + } while (0) + +#define FM_LOG_ALT(flag, fmt, args...) \ + do { \ + if ((FM_ALT <= (g_dbg_level&0x0000000f)) && ((flag)&0xfffffff0) & g_dbg_level) { \ + pr_notice("[" #flag "]" fmt, ## args); \ + } \ + } while (0) + +#define FM_LOG_EMG(flag, fmt, args...) \ + do { \ + if ((FM_EMG <= (g_dbg_level&0x0000000f)) && ((flag)&0xfffffff0) & g_dbg_level) { \ + pr_notice("[" #flag "]" fmt, ## args); \ + } \ + } while (0) + +#endif /* __FM_DBG_H__ */ diff --git a/drivers/misc/mediatek/connectivity/fmradio/inc/fm_eint.h b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_eint.h new file mode 100644 index 0000000000000..8b912e2379210 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_eint.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __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 signed int fm_enable_eint(void); +extern signed int fm_disable_eint(void); +extern signed int fm_request_eint(void (*parser) (void)); +extern signed int fm_eint_pin_cfg(signed int mode); + +#endif /* __FM_EINT_H__ */ diff --git a/drivers/misc/mediatek/connectivity/fmradio/inc/fm_err.h b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_err.h new file mode 100644 index 0000000000000..b118021420e0c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_err.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __FM_ERR_H__ +#define __FM_ERR_H__ + +#include /* for printk() */ + +#define FM_ERR_BASE 1000 +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 +}; + +#endif /* __FM_ERR_H__ */ diff --git a/drivers/misc/mediatek/connectivity/fmradio/inc/fm_ext_api.h b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_ext_api.h new file mode 100644 index 0000000000000..0f526a12194ee --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_ext_api.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef FM_EXT_API_H +#define FM_EXT_API_H + +#include + +#include "fm_interface.h" + +enum fm_spi_speed { + FM_SPI_SPEED_26M, + FM_SPI_SPEED_64M, + FM_SPI_SPEED_MAX +}; + +struct fm_ext_interface { + void (*eint_handler)(void); + void (*eint_cb)(void); + void (*enable_eint)(void); + void (*disable_eint)(void); + int (*stp_send_data)(unsigned char *buf, unsigned int len); + int (*stp_recv_data)(unsigned char *buf, unsigned int len); + int (*stp_register_event_cb)(void *cb); + int (*wmt_msgcb_reg)(void *data); + int (*wmt_func_on)(void); + int (*wmt_func_off)(void); + unsigned int (*wmt_ic_info_get)(void); + int (*wmt_chipid_query)(void); + int (*get_hw_version)(void); + unsigned char (*get_top_index)(void); + unsigned int (*get_get_adie)(void); + int (*spi_clock_switch)(enum fm_spi_speed speed); + bool (*is_bus_hang)(void); + int (*spi_hopping)(void); + signed int (*low_ops_register)(struct fm_callback *cb, struct fm_basic_interface *bi); + signed int (*low_ops_unregister)(struct fm_basic_interface *bi); + signed int (*rds_ops_register)(struct fm_basic_interface *bi, struct fm_rds_interface *ri); + signed int (*rds_ops_unregister)(struct fm_rds_interface *ri); + + struct platform_driver *drv; + unsigned int irq_id; +}; + +#endif /* FM_EXT_API_H */ diff --git a/drivers/misc/mediatek/connectivity/fmradio/inc/fm_interface.h b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_interface.h new file mode 100644 index 0000000000000..26575c6fb8f4a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_interface.h @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __FM_INTERFACE_H__ +#define __FM_INTERFACE_H__ + +#include +#include +#include + +#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_UNKNOWN = 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_antenna_type { + FM_ANA_LONG = 0, /* long antenna */ + FM_ANA_SHORT = 1, /* short antenna */ + FM_ANA_MAX +}; + +enum fm_gps_desense_t { + FM_GPS_DESE_ENABLE, + FM_GPS_DESE_DISABLE +}; + +struct fm_hw_info { + signed int chip_id; /* chip ID, eg. 6620 */ + signed int eco_ver; /* chip ECO version, eg. E3 */ + signed int rom_ver; /* FM DSP rom code version, eg. V2 */ + signed int patch_ver; /* FM DSP patch version, eg. 1.11 */ + signed int reserve; +}; + +struct fm_i2s_setting { + signed int onoff; + signed int mode; + signed int sample; +}; + +enum fm_i2s_state_e { + FM_I2S_ON = 0, + FM_I2S_OFF, + FM_I2S_STATE_ERR +}; + +enum fm_i2s_mode_e { + FM_I2S_MASTER = 0, + FM_I2S_SLAVE, + FM_I2S_MODE_ERR +}; + +enum fm_i2s_sample_e { + FM_I2S_32K = 0, + FM_I2S_44K, + FM_I2S_48K, + FM_I2S_SR_ERR +}; + +struct fm_i2s_info { + signed int status; /*0:FM_I2S_ON, 1:FM_I2S_OFF,2:error */ + signed int mode; /*0:FM_I2S_MASTER, 1:FM_I2S_SLAVE,2:error */ + signed int rate; /*0:FM_I2S_32K:32000,1:FM_I2S_44K:44100,2:FM_I2S_48K:48000,3:error */ +}; + +enum fm_audio_path_e { + FM_AUD_ANALOG = 0, + FM_AUD_I2S = 1, + FM_AUD_MRGIF = 2, + FM_AUD_ERR +}; + +enum fm_i2s_pad_sel_e { + FM_I2S_PAD_CONN = 0, /* sco fm chip: e.g.6627 */ + FM_I2S_PAD_IO = 1, /* combo fm chip: e.g.6628 */ + FM_I2S_PAD_ERR +}; + +struct fm_audio_info_t { + enum fm_audio_path_e aud_path; + struct fm_i2s_info i2s_info; + enum fm_i2s_pad_sel_e i2s_pad; +}; + +struct fm_platform { + struct cdev cdev; + dev_t dev_t; + struct class *cls; + struct device *dev; +}; + +struct fm { + /* chip info */ + signed int projectid; + unsigned short chip_id; /* chip id, such as 6616/6620/6626/6628 */ + unsigned short device_id; /* chip version */ + /* basic run time info */ + signed int ref; /* fm driver can be multi opened */ + 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 */ + signed int vol; /* current audio volume from chip side */ + bool mute; /* true: mute, false: playing */ + bool rds_on; /* true: on, false: off */ + enum fm_antenna_type ana_type; /* long/short antenna */ + bool via_bt; /* true: fm over bt controller; false: fm over host */ + unsigned short min_freq; /* for UE, 875KHz */ + unsigned short max_freq; /* for UE, 1080KHz */ + unsigned short cur_freq; /* current frequency */ + unsigned char band; /* UE/JAPAN/JPANWD */ + /*FM Tx */ + unsigned int vcoon; /* TX VCO tracking ON duiration(ms) */ + unsigned int vcooff; /* TX RTC VCO tracking interval(s) */ + unsigned int txpwrctl; /* TX power contrl interval(s) */ + unsigned int tx_pwr; + bool rdstx_on; /* false:rds tx off, true:rds tx on */ + bool wholechiprst; + /* 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 */ + struct fm_work *pwroff_wk; + struct fm_work *ch_valid_check_wk; + /* Tx */ + struct fm_work *fm_tx_desense_wifi_work; + struct fm_work *fm_tx_power_ctrl_work; + +}; + +struct fm_callback { + /* call backs */ + unsigned short (*cur_freq_get)(void); + signed int (*cur_freq_set)(unsigned short new_freq); + signed int (*projectid_get)(void); +/* unsigned short(*chan_para_get)(unsigned short freq); //get channel parameter, HL side/ FA / ATJ */ +}; + +struct fm_basic_interface { + /* mt66x6 lib interfaces */ + signed int (*low_pwr_wa)(signed int onoff); + signed int (*pwron)(signed int data); + signed int (*pwroff)(signed int data); + signed int (*pmic_read)(unsigned char addr, unsigned int *val); + signed int (*pmic_write)(unsigned char addr, unsigned int val); + unsigned short (*chipid_get)(void); + signed int (*mute)(bool mute); + signed int (*rampdown)(void); + signed int (*pwrupseq)(unsigned short *chip_id, unsigned short *device_id); + signed int (*pwrdownseq)(void); + bool (*setfreq)(unsigned short freq); + bool (*seek)(unsigned short min_freq, unsigned short max_freq, unsigned short *freq, unsigned short dir, + unsigned short space); + signed int (*seekstop)(void); + bool (*scan)(unsigned short min_freq, unsigned short max_freq, unsigned short *freq, unsigned short *tbl, + unsigned short *tblsize, unsigned short dir, unsigned short space); + bool (*jammer_scan)(unsigned short min_freq, unsigned short max_freq, unsigned short *freq, unsigned short *tbl, + unsigned short *tblsize, unsigned short dir, unsigned short space); + signed int (*cqi_get)(signed char *buf, signed int buf_len); + signed int (*scanstop)(void); + signed int (*rssiget)(signed int *rssi); + signed int (*volset)(unsigned char vol); + signed int (*volget)(unsigned char *vol); + signed int (*dumpreg)(void); + bool (*msget)(unsigned short *ms); /* mono/stereo indicator get */ + signed int (*msset)(signed int ms); /* mono/stereo force set */ + bool (*pamdget)(unsigned short *pamd); + bool (*em)(unsigned short group, unsigned short item, unsigned int val); + signed int (*anaswitch)(signed int ana); + signed int (*anaget)(void); + signed int (*caparray_get)(signed int *ca); + signed int (*i2s_set)(signed int onoff, signed int mode, signed int sample); + signed int (*i2s_get)(signed int *ponoff, signed int *pmode, signed int *psample); + signed int (*hwinfo_get)(struct fm_hw_info *req); + /* check if this is a de-sense channel */ + signed int (*is_dese_chan)(unsigned short freq); + signed int (*softmute_tune)(unsigned short freq, signed int *rssi, signed int *valid); + signed int (*pre_search)(void); + signed int (*restore_search)(void); + /* check if this is a valid channel */ + signed int (*desense_check)(unsigned short freq, signed int rssi); + signed int (*get_freq_cqi)(unsigned short freq, signed int *cqi); + /* cqi log tool */ + signed int (*cqi_log)(signed int min_freq, signed int max_freq, signed int space, signed int cnt); + signed int (*fm_via_bt)(bool flag); /* fm over BT:1:enable,0:disable */ + signed int (*set_search_th)(signed int idx, signed int val, signed int reserve); + signed int (*get_aud_info)(struct fm_audio_info_t *data); + /*tx function */ + signed int (*tx_support)(signed int *sup); + signed int (*rdstx_enable)(signed int *flag); + bool (*tune_tx)(unsigned short freq); + signed int (*pwrupseq_tx)(void); + signed int (*pwrdownseq_tx)(void); + signed int (*tx_pwr_ctrl)(unsigned short freq, signed int *ctr); + signed int (*rtc_drift_ctrl)(unsigned short freq, signed int *ctr); + signed int (*tx_desense_wifi)(unsigned short freq, signed int *ctr); + signed int (*tx_scan)(unsigned short min_freq, unsigned short max_freq, unsigned short *pFreq, + unsigned short *pScanTBL, unsigned short *ScanTBLsize, + unsigned short scandir, unsigned short space); + signed int (*rds_tx_adapter)(unsigned short pi, unsigned short *ps, unsigned short *other_rds, + unsigned char other_rds_cnt); + bool (*is_valid_freq)(unsigned short freq); + +}; + +struct fm_rds_interface { + /* rds lib interfaces */ + signed int (*rds_blercheck)(struct rds_t *dst); + bool (*rds_onoff)(struct rds_t *dst, bool onoff); + signed int (*rds_parser)(struct rds_t *rds_dst, struct rds_rx_t *rds_raw, + signed int rds_size, unsigned short(*getfreq) (void)); + unsigned short (*rds_gbc_get)(void); /* good block counter */ + unsigned short (*rds_bbc_get)(void); /* bad block counter */ + unsigned char (*rds_bbr_get)(void); /* bad block ratio */ + signed int (*rds_bc_reset)(void); /* reset block counter */ + unsigned int (*rds_bci_get)(void); /* bler check interval */ + signed int (*rds_log_get)(struct rds_rx_t *dst, signed int *dst_len); + signed int (*rds_gc_get)(struct rds_group_cnt_t *dst, struct rds_t *rdsp); + signed int (*rds_gc_reset)(struct rds_t *rdsp); + /*Tx */ + signed int (*rds_tx)(unsigned short pi, unsigned short *ps, unsigned short *other_rds, + unsigned char other_rds_cnt); + signed int (*rds_tx_enable)(void); + signed int (*rds_tx_disable)(void); + signed int (*rdstx_support)(signed int *sup); +}; + +struct fm_lowlevel_ops { + struct fm_callback cb; + struct fm_basic_interface bi; + struct fm_rds_interface ri; +}; + +extern signed int fm_low_ops_register(struct fm_callback *cb, struct fm_basic_interface *bi); +extern signed int fm_low_ops_unregister(struct fm_basic_interface *bi); +extern signed int fm_rds_ops_register(struct fm_basic_interface *bi, struct fm_rds_interface *ri); +extern signed int fm_rds_ops_unregister(struct fm_rds_interface *ri); +extern signed int fm_wcn_ops_register(void); +extern signed int fm_wcn_ops_unregister(void); +extern int fm_register_irq(struct platform_driver *drv); + +/* + * 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 signed int fm_get_channel_space(int freq); +#endif /* __FM_INTERFACE_H__ */ diff --git a/drivers/misc/mediatek/connectivity/fmradio/inc/fm_ioctl.h b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_ioctl.h new file mode 100644 index 0000000000000..ba120c637e675 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_ioctl.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __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) + +/* 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_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*) + +#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_TOP_RDWR _IOWR(FM_IOC_MAGIC, 43, struct fm_top_rw_parm*) +#define FM_IOCTL_HOST_RDWR _IOWR(FM_IOC_MAGIC, 44, struct fm_host_rw_parm*) + +#define FM_IOCTL_PRE_SEARCH _IOWR(FM_IOC_MAGIC, 45, int32_t) +#define FM_IOCTL_RESTORE_SEARCH _IOWR(FM_IOC_MAGIC, 46, int32_t) + +#define FM_IOCTL_SET_SEARCH_THRESHOLD _IOWR(FM_IOC_MAGIC, 47, struct fm_search_threshold_t*) + +#define FM_IOCTL_GET_AUDIO_INFO _IOWR(FM_IOC_MAGIC, 48, struct fm_audio_info_t*) +#define FM_IOCTL_FM_SET_STATUS _IOWR(FM_IOC_MAGIC, 49, struct fm_status_t) +#define FM_IOCTL_FM_GET_STATUS _IOWR(FM_IOC_MAGIC, 50, struct fm_status_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, struct fm_desense_check_t*) + +#define COMPAT_FM_IOCTL_GET_AUDIO_INFO _IOWR(FM_IOC_MAGIC, 48, struct fm_audio_info_t*) + +#define FM_IOCTL_PMIC_RDWR _IOWR(FM_IOC_MAGIC, 65, struct fm_pmic_rw_parm*) + +#define FM_IOCTL_DUMP_REG _IO(FM_IOC_MAGIC, 0xFF) +#endif /* __FM_IOCTL_H__ */ diff --git a/drivers/misc/mediatek/connectivity/fmradio/inc/fm_link.h b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_link.h new file mode 100644 index 0000000000000..75e6b2fee022b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_link.h @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __FM_LINK_H__ +#define __FM_LINK_H__ + +#include "fm_typedef.h" +#include "fm_rds.h" +#include "fm_utils.h" + +enum fm_task_parser_state { + 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 +}; + +enum { + FM_TASK_COMMAND_PKT_TYPE = 0x01, + FM_TASK_EVENT_PKT_TYPE = 0x04 +}; + +/* FM opcode */ +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, + FM_HOST_READ_OPCODE = 0x18, /* mcu register read */ + FM_HOST_WRITE_OPCODE = 0x19, + CSPI_WRITE_OPCODE = 0x20, + CSPI_READ_OPCODE = 0x21, /* common SPI read */ + FM_HOST_MODIFY_OPCODE = 0x22, + FM_READ_PMIC_CR_OPCODE = 0x23, + FM_WRITE_PMIC_CR_OPCODE = 0x24, + FM_MODIFY_PMIC_CR_OPCODE = 0x25, + FM_OPCODE_MAX +}; + +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_PMIC_READ = (1 << 8), + 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_PMIC_MODIFY = (1 << 15), + 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_CSPI_READ = (1 << 22), /* 22 */ + FLAG_SM_TUNE = (1 << FM_SOFT_MUTE_TUNE_OPCODE), /* 23 */ + FLAG_HOST_READ = (1 << FM_HOST_READ_OPCODE), /* 24 */ + FLAG_HOST_WRITE = (1 << FM_HOST_WRITE_OPCODE), /* 25 */ + FLAG_CSPI_WRITE = (1 << 26), /* 26 */ + 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 { + unsigned short fspi_rd; + unsigned short seek_result; + unsigned short scan_result[FM_SCANTBL_SIZE]; + signed char cqi[FM_CQI_BUF_SIZE]; + struct rds_rx_t rds_rx_result; + unsigned int cspi_rd; /* common spi read data */ + unsigned char pmic_result[8]; +}; + +#define FM_TRACE_ENABLE + +#define FM_TRACE_FIFO_SIZE 200 +#define FM_TRACE_PKT_SIZE 60 +struct fm_trace_t { + signed int type; + signed int opcode; + signed int len; + unsigned char pkt[FM_TRACE_PKT_SIZE]; /* full packet */ + unsigned long time; + signed int tid; +}; + +struct fm_trace_fifo_t { + signed char name[20 + 1]; + struct fm_trace_t trace[FM_TRACE_FIFO_SIZE]; + unsigned int size; + unsigned int in; + unsigned int out; + unsigned int len; + signed int (*trace_in)(struct fm_trace_fifo_t *thiz, struct fm_trace_t *new_tra); + signed int (*trace_out)(struct fm_trace_fifo_t *thiz, struct fm_trace_t *dst_tra); + + bool (*is_full)(struct fm_trace_fifo_t *thiz); + bool (*is_empty)(struct fm_trace_fifo_t *thiz); +}; + +#define FM_TRACE_IN(fifop, tracep) \ +({ \ + signed int __ret = (signed int)0; \ + if (fifop && (fifop)->trace_in) { \ + __ret = (fifop)->trace_in(fifop, tracep); \ + } \ + __ret; \ +}) + +#define FM_TRACE_OUT(fifop, tracep) \ +({ \ + signed int __ret = (signed int)0; \ + if (fifop && (fifop)->trace_out) { \ + __ret = (fifop)->trace_out(fifop, tracep); \ + } \ + __ret; \ +}) + +#define FM_TRACE_FULL(fifop) \ +({ \ + bool __ret = (bool)false; \ + if (fifop && (fifop)->is_full) { \ + __ret = (fifop)->is_full(fifop); \ + } \ + __ret; \ +}) + +#define FM_TRACE_EMPTY(fifop) \ +({ \ + bool __ret = (bool)false; \ + if (fifop && (fifop)->is_empty) { \ + __ret = (fifop)->is_empty(fifop); \ + } \ + __ret; \ +}) + +#define RX_BUF_SIZE 256 +#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) /* usually 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) +#define PMIC_CONTROL_TIMEOUT (3) + + +struct fm_link_event { + struct fm_flag_event *ln_event; + struct fm_res_ctx result; /* seek/scan/read/RDS */ +}; + +/* + * FM data and ctrl link APIs: platform related and bus related + */ +extern signed int fm_link_setup(void *data); + +extern signed int fm_link_release(void); + +extern signed int fm_cmd_tx(unsigned char *buf, unsigned short len, signed int mask, signed int cnt, signed int timeout, + signed int (*callback)(struct fm_res_ctx *result)); + +extern signed int fm_event_parser(signed int (*rds_parser)(struct rds_rx_t *, signed int)); + +extern signed int fm_ctrl_rx(unsigned char addr, unsigned short *val); + +extern signed int fm_ctrl_tx(unsigned char addr, unsigned short val); + +extern signed int fm_force_active_event(unsigned int mask); + +extern bool fm_wait_stc_done(unsigned int sec); + +extern struct fm_trace_fifo_t *fm_trace_fifo_create(const signed char *name); + +extern signed int fm_trace_fifo_release(struct fm_trace_fifo_t *fifo); + +extern signed int fm_print_cmd_fifo(void); + +extern signed int fm_print_evt_fifo(void); + +#endif /* __FM_LINK_H__ */ diff --git a/drivers/misc/mediatek/connectivity/fmradio/inc/fm_main.h b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_main.h new file mode 100644 index 0000000000000..4e726931087e1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_main.h @@ -0,0 +1,406 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __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_config.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 +}; + +enum fm_over_bt_enable_state { + FM_OVER_BT_DISABLE = 0, + FM_OVER_BT_ENABLE +}; + +#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 { + unsigned char err; + unsigned char band; + unsigned char space; + unsigned char hilo; + unsigned char deemphasis; + unsigned short freq; /* IN/OUT parameter */ +}; + +struct fm_tune_parm_old { + unsigned char err; + unsigned char band; + unsigned char space; + unsigned char hilo; + unsigned short freq; /* IN/OUT parameter */ +}; + +struct fm_seek_parm { + unsigned char err; + unsigned char band; + unsigned char space; + unsigned char hilo; + unsigned char seekdir; + unsigned char seekth; + unsigned short freq; /* IN/OUT parameter */ +}; + +struct fm_scan_parm { + unsigned char err; + unsigned char band; + unsigned char space; + unsigned char hilo; + unsigned short freq; /* OUT parameter */ + unsigned short ScanTBL[26]; /* need no less than the chip */ + unsigned short ScanTBLSize; /* IN/OUT parameter */ +}; + +struct fm_cqi { + signed int ch; + signed int rssi; + signed int reserve; +}; + +struct fm_cqi_req { + unsigned short ch_num; + signed int buf_size; + signed char *cqi_buf; +}; + +struct fm_ch_rssi { + unsigned short freq; + signed int 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; + signed int ret; /* 0, success; else error code */ + unsigned short lower; /* lower band, Eg, 7600 -> 76.0Mhz */ + unsigned short upper; /* upper band, Eg, 10800 -> 108.0Mhz */ + signed int space; /* 5: 50KHz, 10: 100Khz, 20: 200Khz */ + signed int num; /* valid channel number */ + void *priv; + signed int sr_size; /* scan result buffer size in bytes */ + union { + unsigned short *ch_buf; /* channel buffer */ + signed int *rssi_buf; /* rssi buffer */ + struct fm_ch_rssi *ch_rssi_buf; /* channel and RSSI buffer */ + } sr; +}; + +struct fm_seek_t { + signed int ret; /* 0, success; else error code */ + unsigned short freq; + unsigned short lower; /* lower band, Eg, 7600 -> 76.0Mhz */ + unsigned short upper; /* upper band, Eg, 10800 -> 108.0Mhz */ + signed int space; /* 5: 50KHz, 10: 100Khz, 20: 200Khz */ + signed int dir; /* 0: up; 1: down */ + signed int th; /* seek threshold in dbm(Eg, -95dbm) */ + void *priv; +}; + +struct fm_tune_t { + signed int ret; /* 0, success; else error code */ + unsigned short freq; + unsigned short lower; /* lower band, Eg, 7600 -> 76.0Mhz */ + unsigned short upper; /* upper band, Eg, 10800 -> 108.0Mhz */ + signed int space; /* 5: 50KHz, 10: 100Khz, 20: 200Khz */ + void *priv; +}; + +struct fm_rssi_req { + unsigned short num; + unsigned short read_cnt; + struct fm_ch_rssi cr[26 * 16]; +}; + +struct fm_rds_tx_parm { + unsigned char err; + unsigned short pi; + unsigned short ps[12]; /* 4 ps */ + unsigned short other_rds[87]; /* 0~29 other groups */ + unsigned char other_rds_cnt; /* # of other group */ +}; + +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 */ +}; + +#define TX_SCAN_MAX 10 +#define TX_SCAN_MIN 1 + +struct fm_tx_scan_parm { + unsigned char err; + unsigned char band; /* 87.6~108MHz */ + unsigned char space; + unsigned char hilo; + unsigned short freq; /* start freq, if less than band min freq, then will use band min freq */ + unsigned char scandir; + unsigned short ScanTBL[TX_SCAN_MAX]; /* need no less than the chip */ + unsigned short ScanTBLSize; /* IN: desired size, OUT: scan result size */ +}; + +struct fm_gps_rtc_info { + signed int err; /* error number, 0: success, other: err code */ + signed int retryCnt; /* GPS mnl can decide retry times */ + signed int ageThd; /* GPS 3D fix time diff threshold */ + signed int driftThd; /* GPS RTC drift threshold */ + struct timeval tvThd; /* time value diff threshold */ + signed int age; /* GPS 3D fix time diff */ + signed int drift; /* GPS RTC drift */ + union { + unsigned long stamp; /* time stamp in jiffies */ + struct timeval tv; /* time stamp value in RTC */ + }; + signed int flag; /* rw flag */ +}; + +struct fm_desense_check_t { + signed int freq; + signed int rssi; +}; + +struct fm_full_cqi_log_t { + uint16_t lower; /* lower band, Eg, 7600 -> 76.0Mhz */ + uint16_t upper; /* upper band, Eg, 10800 -> 108.0Mhz */ + int space; /* 0x1: 50KHz, 0x2: 100Khz, 0x4: 200Khz */ + int cycle; /* repeat times */ +}; + +enum { + FM_RX = 0, + FM_TX = 1 +}; + +struct fm_ctl_parm { + unsigned char err; + unsigned char addr; + unsigned short val; + unsigned short rw_flag; /* 0:write, 1:read */ +}; +struct fm_em_parm { + unsigned short group_idx; + unsigned short item_idx; + unsigned int item_value; +}; +struct fm_top_rw_parm { + unsigned char err; + unsigned char rw_flag; /* 0:write, 1:read */ + unsigned short addr; + unsigned int val; +}; +struct fm_host_rw_parm { + unsigned char err; + unsigned char rw_flag; /* 0:write, 1:read */ + unsigned int addr; + unsigned int val; +}; +struct fm_pmic_rw_parm { + unsigned char err; + unsigned char rw_flag; /* 0:write, 1:read */ + unsigned char addr; + unsigned int val; +}; +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 { + signed int rssi; /* RSSI of current channel */ + unsigned short freq; /* current frequency */ + signed int valid; /* current channel is valid(true) or not(false) */ +}; +struct fm_search_threshold_t { + signed int th_type; /* 0, RSSI. 1,desense RSSI. 2,SMG. */ + signed int th_val; /* threshold value */ + signed int reserve; +}; + +struct fm_status_t { + int which; + bool stat; +}; + +struct fm_chip_mapping { + unsigned short con_chip; + unsigned short fm_chip; + enum fm_cfg_chip_type type; +}; + +/* init and deinit APIs */ +extern signed int fm_env_setup(void); +extern signed int fm_env_destroy(void); +extern struct fm *fm_dev_init(unsigned int arg); +extern signed int 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 signed int fm_open(struct fm *fmp); +extern signed int fm_close(struct fm *fmp); +extern signed int fm_rds_read(struct fm *fmp, signed char *dst, signed int len); +extern signed int fm_powerup(struct fm *fm, struct fm_tune_parm *parm); +extern signed int fm_powerdown(struct fm *fm, int type); +extern signed int fm_cqi_get(struct fm *fm, signed int ch_num, signed char *buf, signed int buf_size); +extern signed int fm_get_hw_info(struct fm *pfm, struct fm_hw_info *req); +extern signed int fm_hwscan_stop(struct fm *fm); +extern signed int fm_ana_switch(struct fm *fm, signed int antenna); +extern signed int fm_setvol(struct fm *fm, unsigned int vol); +extern signed int fm_getvol(struct fm *fm, unsigned int *vol); +extern signed int fm_mute(struct fm *fm, unsigned int bmute); +extern signed int fm_getrssi(struct fm *fm, signed int *rssi); +extern signed int fm_read(struct fm *fm, unsigned char addr, unsigned short *val); +extern signed int fm_write(struct fm *fm, unsigned char addr, unsigned short val); +extern signed int fm_top_read(struct fm *fm, unsigned short addr, unsigned int *val); +extern signed int fm_top_write(struct fm *fm, unsigned short addr, unsigned int val); +extern signed int fm_host_read(struct fm *fm, unsigned int addr, unsigned int *val); +extern signed int fm_host_write(struct fm *fm, unsigned int addr, unsigned int val); +extern signed int fm_pmic_read(struct fm *fm, unsigned char addr, unsigned int *val); +extern signed int fm_pmic_write(struct fm *fm, unsigned char addr, unsigned int val); +extern signed int fm_chipid_get(struct fm *fm, unsigned short *chipid); +extern signed int fm_monostereo_get(struct fm *fm, unsigned short *ms); +extern signed int fm_monostereo_set(struct fm *fm, signed int ms); +extern signed int fm_pamd_get(struct fm *fm, unsigned short *pamd); +extern signed int fm_caparray_get(struct fm *fm, signed int *ca); +extern signed int fm_em_test(struct fm *fm, unsigned short group, unsigned short item, unsigned int val); +extern signed int fm_rds_onoff(struct fm *fm, unsigned short rdson_off); +extern signed int fm_rds_good_bc_get(struct fm *fm, unsigned short *gbc); +extern signed int fm_rds_bad_bc_get(struct fm *fm, unsigned short *bbc); +extern signed int fm_rds_bler_ratio_get(struct fm *fm, unsigned short *bbr); +extern signed int fm_rds_group_cnt_get(struct fm *fm, struct rds_group_cnt_t *dst); +extern signed int fm_rds_group_cnt_reset(struct fm *fm); +extern signed int fm_rds_log_get(struct fm *fm, struct rds_rx_t *dst, signed int *dst_len); +extern signed int fm_rds_block_cnt_reset(struct fm *fm); +extern signed int fm_i2s_set(struct fm *fm, signed int onoff, signed int mode, signed int sample); +extern signed int fm_get_i2s_info(struct fm *pfm, struct fm_i2s_info *req); +extern signed int fm_tune(struct fm *fm, struct fm_tune_parm *parm); +extern signed int fm_is_dese_chan(struct fm *pfm, unsigned short freq); +extern signed int fm_desense_check(struct fm *pfm, unsigned short freq, signed int rssi); +extern signed int fm_sys_state_get(struct fm *fmp); +extern signed int fm_sys_state_set(struct fm *fmp, signed int sta); +extern signed int fm_set_stat(struct fm *fmp, int which, bool stat); +extern signed int fm_get_stat(struct fm *fmp, int which, bool *stat); +extern signed int fm_subsys_reset(struct fm *fm); +extern signed int fm_cqi_log(void); +extern signed int fm_soft_mute_tune(struct fm *fm, struct fm_softmute_tune_t *parm); +extern signed int fm_pre_search(struct fm *fm); +extern signed int fm_restore_search(struct fm *fm); + +extern signed int fm_dump_reg(void); +extern signed int fm_get_gps_rtc_info(struct fm_gps_rtc_info *src); +extern signed int fm_over_bt(struct fm *fm, signed int flag); +extern signed int fm_set_search_th(struct fm *fm, struct fm_search_threshold_t parm); +extern signed int fm_get_aud_info(struct fm_audio_info_t *data); +/*tx function*/ +extern signed int fm_tx_support(struct fm *fm, signed int *support); + +extern signed int fm_powerup_tx(struct fm *fm, struct fm_tune_parm *parm); +extern signed int fm_tune_tx(struct fm *fm, struct fm_tune_parm *parm); +extern signed int fm_powerdowntx(struct fm *fm); +extern signed int fm_rds_tx(struct fm *fm, struct fm_rds_tx_parm *parm); +extern signed int fm_rdstx_support(struct fm *fm, signed int *support); +extern signed int fm_rdstx_enable(struct fm *fm, signed int enable); +extern signed int fm_tx_scan(struct fm *fm, struct fm_tx_scan_parm *parm); +signed int fm_full_cqi_logger(struct fm_full_cqi_log_t *setting); +signed int fm_rds_parser(struct rds_rx_t *rds_raw, signed int rds_size); + +#endif /* __FM_MAIN_H__ */ diff --git a/drivers/misc/mediatek/connectivity/fmradio/inc/fm_patch.h b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_patch.h new file mode 100644 index 0000000000000..10496381decab --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_patch.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#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 { + signed int idx; + signed char *patch; + signed char *coeff; + signed char *rom; + signed char *hwcoeff; +}; + +struct fm_file_read_data { + const signed char *filename; + unsigned char *dst; + signed int len; + signed int position; + signed int ret; + struct completion comp; +}; + +extern signed int fm_file_read(const signed char *filename, unsigned char *dst, signed int len, signed int position); + +extern signed int fm_file_write(const signed char *filename, unsigned char *dst, signed int len, signed int *ppos); + +#endif /* __FM_PATCH_H__ */ diff --git a/drivers/misc/mediatek/connectivity/fmradio/inc/fm_rds.h b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_rds.h new file mode 100644 index 0000000000000..c2d74e9b6acbc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_rds.h @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __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 80 /* 100 */ +/* #define RDS_CBC_DEPENDENCY */ + +struct rds_packet_t { + unsigned short blkA; + unsigned short blkB; + unsigned short blkC; + unsigned short blkD; + unsigned short cbc; /* correct bit cnt */ + unsigned short crc; /* crc checksum */ +}; + +struct rds_rx_t { + unsigned short sin; + unsigned short cos; + struct rds_packet_t data[MAX_RDS_RX_GROUP_CNT]; +}; + +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 +}; + +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 +}; + +enum { + RDS_GRP_VER_A = 0, /* group version A */ + RDS_GRP_VER_B +}; + +enum rds_blk_t { + RDS_BLK_A = 0, + RDS_BLK_B, + RDS_BLK_C, + RDS_BLK_D, + RDS_BLK_MAX +}; + +/* For RDS feature, these strcutures also be defined in "fm.h" */ +struct rds_flag_t { + unsigned char TP; + unsigned char TA; + unsigned char Music; + unsigned char Stereo; + unsigned char Artificial_Head; + unsigned char Compressed; + unsigned char Dynamic_PTY; + unsigned char Text_AB; + unsigned int flag_status; +}; + +struct rds_ct_t { + unsigned short Month; + unsigned short Day; + unsigned short Year; + unsigned short Hour; + unsigned short Minute; + unsigned char Local_Time_offset_signbit; + unsigned char Local_Time_offset_half_hour; +}; + +struct rds_af_t { + signed short AF_Num; + signed short AF[2][25]; /* 100KHz */ + unsigned char Addr_Cnt; + unsigned char isMethod_A; + unsigned char isAFNum_Get; +}; + +struct rds_ps_t { + unsigned char PS[4][8]; + unsigned char Addr_Cnt; +}; + +struct rds_rt_t { + unsigned char TextData[4][64]; + unsigned char GetLength; + unsigned char isRTDisplay; + unsigned char TextLength; + unsigned char isTypeA; + unsigned char BufCnt; + unsigned short Addr_Cnt; +}; + +struct rds_raw_t { + signed int dirty; /* indicate if the data changed or not */ + signed int len; /* the data len form chip */ + unsigned char data[148]; +}; + +struct rds_group_cnt_t { + unsigned int total; + unsigned int groupA[16]; /* RDS groupA counter */ + unsigned int groupB[16]; /* RDS groupB counter */ +}; + +enum rds_group_cnt_op_t { + RDS_GROUP_CNT_READ = 0, + RDS_GROUP_CNT_WRITE, + RDS_GROUP_CNT_RESET, + RDS_GROUP_CNT_MAX +}; + +struct rds_group_cnt_req_t { + signed int err; + enum rds_group_cnt_op_t op; + struct rds_group_cnt_t gc; +}; + +struct rds_t { + struct rds_ct_t CT; + struct rds_flag_t RDSFlag; + unsigned short PI; + unsigned char Switch_TP; + unsigned char PTY; + struct rds_af_t AF_Data; + struct rds_af_t AFON_Data; + unsigned char Radio_Page_Code; + unsigned short Program_Item_Number_Code; + unsigned char Extend_Country_Code; + unsigned short Language_Code; + struct rds_ps_t PS_Data; + unsigned char PS_ON[8]; + struct rds_rt_t RT_Data; + /* will use RDSFlag_Struct RDSFlag->flag_status to check which event, is that ok? */ + unsigned short event_status; + struct rds_group_cnt_t gc; +}; + +/* Need care the following definition. */ +/* valid Rds Flag for notify */ +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 */ +}; + +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_ECC_CODE = 0x1000, /* ECC code */ + 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 */ +}; + +#define RDS_LOG_SIZE 1 +struct rds_log_t { + struct rds_rx_t rds_log[RDS_LOG_SIZE]; + signed int log_len[RDS_LOG_SIZE]; + unsigned int size; + unsigned int in; + unsigned int out; + unsigned int len; + signed int (*log_in)(struct rds_log_t *thiz, struct rds_rx_t *new_log, signed int new_len); + signed int (*log_out)(struct rds_log_t *thiz, struct rds_rx_t *dst, signed int *dst_len); +}; + +extern signed int rds_parser(struct rds_t *rds_dst, struct rds_rx_t *rds_raw, + signed int rds_size, unsigned short(*getfreq) (void)); +extern signed int rds_grp_counter_get(struct rds_group_cnt_t *dst, struct rds_group_cnt_t *src); +extern signed int rds_grp_counter_reset(struct rds_group_cnt_t *gc); +extern signed int rds_log_in(struct rds_log_t *thiz, struct rds_rx_t *new_log, signed int new_len); +extern signed int rds_log_out(struct rds_log_t *thiz, struct rds_rx_t *dst, signed int *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/misc/mediatek/connectivity/fmradio/inc/fm_reg_utils.h b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_reg_utils.h new file mode 100644 index 0000000000000..1ff2c57f696cb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_reg_utils.h @@ -0,0 +1,394 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef FM_REG_UTILS_H +#define FM_REG_UTILS_H + +#include +#include +#include +#include +#include + +#include + +/* SPI register address */ +#if CFG_FM_CONNAC2 +#define SYS_SPI_BASE_ADDR (0x0000) +#else +#define SYS_SPI_BASE_ADDR (0x6000) +#endif +#define SYS_SPI_STA (0x00 + SYS_SPI_BASE_ADDR) +#define SYS_SPI_CRTL (0x04 + SYS_SPI_BASE_ADDR) +#define SYS_SPI_DIV (0x08 + SYS_SPI_BASE_ADDR) +#define SYS_SPI_FM_CTRL (0x0C + SYS_SPI_BASE_ADDR) + +/* control bit for SPI_STA */ +#define SYS_SPI_ADDR_CR_MASK (0x0FFF) +#define SYS_SPI_ADDR_CR_READ (0x01 << 12) +#define SYS_SPI_ADDR_CR_WRITE (0x00 << 12) + +#define SYS_SPI_ADDR_CR_WF1 (0x00 << 13) +#define SYS_SPI_ADDR_CR_WF (0x01 << 13) +#define SYS_SPI_ADDR_CR_BT (0x02 << 13) +#define SYS_SPI_ADDR_CR_FM (0x03 << 13) +#define SYS_SPI_ADDR_CR_GPS (0x04 << 13) +#define SYS_SPI_ADDR_CR_TOP (0x05 << 13) + +#define SYS_SPI_STA_WF_BUSY_ADDR SYS_SPI_STA +#define SYS_SPI_STA_WF_BUSY_MASK 0x0002 +#define SYS_SPI_STA_WF_BUSY_SHFT 1 + +#define SYS_SPI_STA_BT_BUSY_ADDR SYS_SPI_STA +#define SYS_SPI_STA_BT_BUSY_MASK 0x0004 +#define SYS_SPI_STA_BT_BUSY_SHFT 2 + +#define SYS_SPI_STA_FM_BUSY_ADDR SYS_SPI_STA +#define SYS_SPI_STA_FM_BUSY_MASK 0x0008 +#define SYS_SPI_STA_FM_BUSY_SHFT 3 + +#define SYS_SPI_STA_GPS_BUSY_ADDR SYS_SPI_STA +#define SYS_SPI_STA_GPS_BUSY_MASK 0x0010 +#define SYS_SPI_STA_GPS_BUSY_SHFT 4 + +#define SYS_SPI_STA_TOP_BUSY_ADDR SYS_SPI_STA +#define SYS_SPI_STA_TOP_BUSY_MASK 0x0020 +#define SYS_SPI_STA_TOP_BUSY_SHFT 5 + +/* control bit for SPI_STA */ +#define SYS_SPI_CRTL_MASTER_EN_ADDR SYS_SPI_CRTL +#define SYS_SPI_CRTL_MASTER_EN_MASK 0x8000 +#define SYS_SPI_CRTL_MASTER_EN_SHFT 15 + +/* control bit for SPI_DIV */ +#define SYS_SPI_DIV_DIV_CNT_ADDR SYS_SPI_DIV +#define SYS_SPI_DIV_DIV_CNT_MASK 0x00FF +#define SYS_SPI_DIV_DIV_CNT_SHFT 0 + +/* control bit for SPI_FM_CTRL */ +#define SYS_SPI_FM_CTRL_FM_RD_EXT_CNT_ADDR SYS_SPI_FM_CTRL +#define SYS_SPI_FM_CTRL_FM_RD_EXT_CNT_MASK 0x00FF +#define SYS_SPI_FM_CTRL_FM_RD_EXT_CNT_SHFT 0 + +#define SYS_SPI_FM_CTRL_FM_RD_EXT_EN_ADDR SYS_SPI_FM_CTRL +#define SYS_SPI_FM_CTRL_FM_RD_EXT_EN_MASK 0x8000 +#define SYS_SPI_FM_CTRL_FM_RD_EXT_EN_SHFT 15 + +/* WIFI data addr & mask */ +#define SYS_SPI_WF_ADDR_ADDR (0x10 + SYS_SPI_BASE_ADDR) +#define SYS_SPI_WF_ADDR_MASK 0xFFFF +#define SYS_SPI_WF_ADDR_SHFT 0 + +#define SYS_SPI_WF_WDAT_ADDR (0x14 + SYS_SPI_BASE_ADDR) +#define SYS_SPI_WF_WDAT_MASK 0xFFFFFFFF +#define SYS_SPI_WF_WDAT_SHFT 0 + +#define SYS_SPI_WF_RDAT_ADDR (0x18 + SYS_SPI_BASE_ADDR) +#define SYS_SPI_WF_RDAT_MASK 0xFFFFFFFF +#define SYS_SPI_WF_RDAT_SHFT 0 + +/* BT data addr & mask */ +#define SYS_SPI_BT_ADDR_ADDR (0x20 + SYS_SPI_BASE_ADDR) +#define SYS_SPI_BT_ADDR_MASK 0xFFFF +#define SYS_SPI_BT_ADDR_SHFT 0 + +#define SYS_SPI_BT_WDAT_ADDR (0x24 + SYS_SPI_BASE_ADDR) +#define SYS_SPI_BT_WDAT_MASK 0xFF +#define SYS_SPI_BT_WDAT_SHFT 0 + +#define SYS_SPI_BT_RDAT_ADDR (0x28 + SYS_SPI_BASE_ADDR) +#define SYS_SPI_BT_RDAT_MASK 0xFF +#define SYS_SPI_BT_RDAT_SHFT 0 + +/* FM data addr & mask */ +#define SYS_SPI_FM_ADDR_ADDR (0x30 + SYS_SPI_BASE_ADDR) +#define SYS_SPI_FM_ADDR_MASK 0xFFFF +#define SYS_SPI_FM_ADDR_SHFT 0 + +#define SYS_SPI_FM_WDAT_ADDR (0x34 + SYS_SPI_BASE_ADDR) +#define SYS_SPI_FM_WDAT_MASK 0xFFFF +#define SYS_SPI_FM_WDAT_SHFT 0 + +#define SYS_SPI_FM_RDAT_ADDR (0x38 + SYS_SPI_BASE_ADDR) +#define SYS_SPI_FM_RDAT_MASK 0xFFFF +#define SYS_SPI_FM_RDAT_SHFT 0 + +/* GPS data addr & mask */ +#define SYS_SPI_GPS_ADDR_ADDR (0x40 + SYS_SPI_BASE_ADDR) +#define SYS_SPI_GPS_ADDR_MASK 0xFFFF +#define SYS_SPI_GPS_ADDR_SHFT 0 + +#define SYS_SPI_GPS_WDAT_ADDR (0x44 + SYS_SPI_BASE_ADDR) +#define SYS_SPI_GPS_WDAT_MASK 0xFFFFFFFF +#define SYS_SPI_GPS_WDAT_SHFT 0 + +#define SYS_SPI_GPS_RDAT_ADDR (0x48 + SYS_SPI_BASE_ADDR) +#define SYS_SPI_GPS_RDAT_MASK 0xFFFFFFFF +#define SYS_SPI_GPS_RDAT_SHFT 0 + +/* TOP data addr & mask */ +#define SYS_SPI_TOP_ADDR_ADDR (0x50 + SYS_SPI_BASE_ADDR) +#define SYS_SPI_TOP_ADDR_MASK 0xFFFF +#define SYS_SPI_TOP_ADDR_SHFT 0 + +#define SYS_SPI_TOP_WDAT_ADDR (0x54 + SYS_SPI_BASE_ADDR) +#define SYS_SPI_TOP_WDAT_MASK 0xFFFFFFFF +#define SYS_SPI_TOP_WDAT_SHFT 0 + +#define SYS_SPI_TOP_RDAT_ADDR (0x58 + SYS_SPI_BASE_ADDR) +#define SYS_SPI_TOP_RDAT_MASK 0xFFFFFFFF +#define SYS_SPI_TOP_RDAT_SHFT 0 + +/* A-die TOP SPI registers */ +#define SYSCTL_HW_ID 0x24 +#define SYSCTL_ADIE_TOP_THADC 0xC4 +#define SYSCTL_CLK_STATUS 0xA00 +#define SYSCTL_WF_CLK_EN 0xA04 +#define SYSCTL_BT_CLK_EN 0xA08 +#define SYSCTL_GPS_CLK_EN 0xA0C +#define SYSCTL_TOP_CLK_EN 0xA10 + +#define SYSCTL_EFUSE_SIZE 32 +#define SYSCTL_Macro0_Efuse_D0 0x11C +#define SYSCTL_Macro1_Efuse_D0 0x124 + +/* 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_WRITE_SPI_BASIC_OP = (FM_BOP_BASE + 0x05), + FM_RD_SPI_UNTIL_BASIC_OP = (FM_BOP_BASE + 0x06), + FM_MODIFY_SPI_BASIC_OP = (FM_BOP_BASE + 0x07), + FM_MAX_BASIC_OP = (FM_BOP_BASE + 0x08) +}; + +/* FM SPI control registers */ +#define FSPI_MAS_BASE (0x80060000) +#define FSPI_MAS_CONTROL_REG (FSPI_MAS_BASE + 0x0000) +#define FSPI_MAS_ADDR_REG (FSPI_MAS_BASE + 0x0004) +#define FSPI_MAS_WRDATA_REG (FSPI_MAS_BASE + 0x0008) +#define FSPI_MAS_RDDATA_REG (FSPI_MAS_BASE + 0x000C) +#define FSPI_MAS_CFG1_REG (FSPI_MAS_BASE + 0x0010) +#define FSPI_MAS_CFG2_REG (FSPI_MAS_BASE + 0x0014) +#define FSPI_MAS_MODESEL_REG (FSPI_MAS_BASE + 0x0020) +#define FSPI_MAS_RESET_REG (FSPI_MAS_BASE + 0x0030) +#define FSPI_MAS_DEBUG1_REG (FSPI_MAS_BASE + 0x0034) +#define FSPI_MAS_DEBUG2_REG (FSPI_MAS_BASE + 0x0038) +#define FSPI_MAS_DEBUG3_REG (FSPI_MAS_BASE + 0x003C) +#define FSPI_MAS_DEBUG4_REG (FSPI_MAS_BASE + 0x0040) +#define FSPI_MAS_DEBUG5_REG (FSPI_MAS_BASE + 0x0048) + +/* FM Main Control Register */ +#define FM_MAIN_CTRL_TUNE (0x0001) +#define FM_MAIN_CTRL_SEEK (0x0002) +#define FM_MAIN_CTRL_SCAN (0x0004) +#define FM_MAIN_CTRL_DSP_INIT (0x0008) +#define FM_MAIN_CTRL_SCAN_CQI (0x0008) +#define FM_MAIN_CTRL_RDS (0x0010) +#define FM_MAIN_CTRL_DCOC (0x0020) +#define FM_MAIN_CTRL_MUTE (0x0040) +#define FM_MAIN_CTRL_IQCAL (0x0080) +#define FM_MAIN_CTRL_RAMPDOWN (0x0100) +#define FM_MAIN_CTRL_MEM_FLUSH (0x0200) +#define FM_MAIN_CTRL_MASK (0x0Fff) + +/* RDS control registers */ +#define FM_RDS_BASE (0x0) +#define RDS_INFO_REG (FM_RDS_BASE + 0x81) +#define RDS_CRC_CORR_CNT 0x001E +#define RDS_CRC_INFO 0x0001 +#define RDS_DATA_REG (FM_RDS_BASE + 0x82) +#define SCAN_BUFF_LEN 0xF +#define RDS_SIN_REG (FM_RDS_BASE + 0x85) +#define RDS_COS_REG (FM_RDS_BASE + 0x86) +#define RDS_FIFO_STATUS0 (FM_RDS_BASE + 0x87) +#define RDS_POINTER (FM_RDS_BASE + 0xF0) + +/* RDS Interrupt Status Register */ +#define RDS_INTR_THRE (0x0001) +#define RDS_INTR_TO (0x0002) +#define RDS_INTR_FULL (0x0004) +#define RDS_INTR_MASK (0x0007) +#define RDS_TX_INTR_MASK (0x0070) +#define RDS_TX_INTR_EMPTY (0x0010) +#define RDS_TX_INTR_LOW (0x0020) +#define RDS_TX_INTR_FULL (0x0040) +#define RDS_TX_INTR_EMPTY_MASK (0x0001) +#define RDS_TX_INTR_LOW_MASK (0x0002) +#define RDS_TX_INTR_FULL_MASK (0x0004) + +/* RDS Data CRC Offset Register */ +#define RDS_DCO_FIFO_OFST (0x007C) +#define RDS_DCO_FIFO_OFST_SHFT 2 + +/* Parameter for RDS */ +/* total 12 groups */ +#define RDS_RX_FIFO_CNT (12) +/* delay 1us between each register read */ +#define RDS_READ_DELAY (1) +#define RDS_GROUP_READ_DELAY (85) +#define FIFO_LEN (48) + +/* Parameter for DSP download */ +#define OFFSET_REG 0x91 +#define CONTROL_REG 0x90 +#define DATA_REG 0x92 + +#define FM_SOFTMUTE_TUNE_CQI_SIZE 0x16 + +#define FM_SPI_COUNT_LIMIT 100000 + +#define FM_BUFFER_SIZE (2048) +#define FM_HDR_SIZE (4) + +/* FM main registers */ +enum { + FM_MAIN_MCLKDESENSE = 0x38, + FM_MAIN_CG1_CTRL = 0x60, + FM_MAIN_CG2_CTRL = 0x61, + FM_MAIN_HWVER = 0x62, + FM_MAIN_CTRL = 0x63, + FM_MAIN_EN1 = 0x64, + FM_CHANNEL_SET = 0x65, + FM_MAIN_CFG1 = 0x66, + FM_MAIN_CFG2 = 0x67, + FM_MAIN_CFG3 = 0x68, + 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_MAIN_IQCOMP1 = 0x70, + FM_MAIN_IQCOMP2 = 0x71, + FM_MAIN_IQCOMP3 = 0x72, + FM_MAIN_IQCOMP4 = 0x73, + FM_MAIN_RXCALSTAT1 = 0x74, + FM_MAIN_RXCALSTAT2 = 0x75, + FM_MAIN_RXCALSTAT3 = 0x76, + FM_MAIN_MCLKDESENSE2 = 0x77, + FM_MAIN_MCLKDESENSE3 = 0x78, + FM_MAIN_CHNLSCAN_CTRL = 0x79, + FM_MAIN_CHNLSCAN_STAT = 0x7a, + FM_MAIN_CHNLSCAN_STAT2 = 0x7b, + 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_MAIN_PGSEL = 0x9f, + FM_ADDR_PAMD = 0xB4, + FM_RDS_BDGRP_ABD_CTRL_REG = 0xB6, + FM_RDS_POINTER = 0xF0, +}; + +/* FM Main Interrupt Register */ +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, + FM_INTR_CQI = 0x0021, + FM_INTR_MASK = 0x003f +}; + +enum { + DSP_ROM = 0, + DSP_PATCH, + DSP_COEFF, + DSP_HWCOEFF +}; + +struct fm_wcn_reg_info { + phys_addr_t spi_phy_addr; + void __iomem *spi_vir_addr; + unsigned int spi_size; + phys_addr_t top_phy_addr; + void __iomem *top_vir_addr; + unsigned int top_size; + phys_addr_t mcu_phy_addr; + void __iomem *mcu_vir_addr; + unsigned int mcu_size; +}; + +struct fm_spi_interface { + struct fm_wcn_reg_info info; + void (*spi_read)(struct fm_spi_interface *si, unsigned int addr, unsigned int *val); + void (*spi_write)(struct fm_spi_interface *si, unsigned int addr, unsigned int val); + void (*host_read)(struct fm_spi_interface *si, unsigned int addr, unsigned int *val); + void (*host_write)(struct fm_spi_interface *si, unsigned int addr, unsigned int val); + int (*sys_spi_read)(struct fm_spi_interface *si, unsigned int subsystem, + unsigned int addr, unsigned int *data); + int (*sys_spi_write)(struct fm_spi_interface *si, unsigned int subsystem, + unsigned int addr, unsigned int data); + bool (*set_own)(void); + bool (*clr_own)(void); +}; + +struct fm_wcn_reg_ops { + struct fm_ext_interface ei; + struct fm_spi_interface si; + unsigned char rx_buf[FM_BUFFER_SIZE]; + unsigned int rx_len; + struct fm_lock *tx_lock; + struct fm_lock *own_lock; +}; + +struct fm_full_cqi { + unsigned short ch; + unsigned short rssi; + unsigned short pamd; + unsigned short pr; + unsigned short fpamd; + unsigned short mr; + unsigned short atdc; + unsigned short prx; + unsigned short atdev; + unsigned short smg; /* soft-mute gain */ + unsigned short drssi; /* delta rssi */ +}; + +/* FM interface */ +void fw_spi_read(unsigned char addr, unsigned short *data); +void fw_spi_write(unsigned char addr, unsigned short data); +void fw_bop_udelay(unsigned int usec); +void fw_bop_rd_until(unsigned char addr, unsigned short mask, + unsigned short value); +void fw_bop_modify(unsigned char addr, unsigned short mask_and, + unsigned short mask_or); +void fw_bop_spi_rd_until(unsigned char subsys, unsigned short addr, + unsigned int mask, unsigned int value); +void fw_bop_spi_modify(unsigned char subsys, unsigned short addr, + unsigned int mask_and, unsigned int mask_or); + +extern struct fm_wcn_reg_ops fm_wcn_ops; +extern unsigned char *cmd_buf; +extern struct fm_lock *cmd_buf_lock; +extern struct fm_res_ctx *fm_res; + +#endif /* FM_REG_UTILS_H */ diff --git a/drivers/misc/mediatek/connectivity/fmradio/inc/fm_stdlib.h b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_stdlib.h new file mode 100644 index 0000000000000..4922e6f586412 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_stdlib.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __FM_STDLIB_H__ +#define __FM_STDLIB_H__ + +#include "fm_typedef.h" +#include +#include + +#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, signed char val, signed int len) +{ + return memset(buf, val, len); +} + +inline void *fm_memcpy(void *dst, const void *src, signed int len) +{ + return memcpy(dst, src, len); +} + +#endif + +#endif /* __FM_STDLIB_H__ */ diff --git a/drivers/misc/mediatek/connectivity/fmradio/inc/fm_typedef.h b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_typedef.h new file mode 100644 index 0000000000000..9d9039463a0d0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_typedef.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __FM_TYPEDEF_H__ +#define __FM_TYPEDEF_H__ + + +#endif /* __FM_TYPEDEF_H__ */ diff --git a/drivers/misc/mediatek/connectivity/fmradio/inc/fm_utils.h b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_utils.h new file mode 100644 index 0000000000000..7674cbaef8836 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/inc/fm_utils.h @@ -0,0 +1,342 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __FM_UTILS_H__ +#define __FM_UTILS_H__ + +#include + +#include "fm_typedef.h" + +/** +* Base structure of fm object +*/ +#define FM_NAME_MAX 20 +struct fm_object { + signed char name[FM_NAME_MAX + 1]; /* name of fm object */ + unsigned char type; /* type of fm object */ + unsigned char flag; /* flag of fm object */ + signed int ref; + void *priv; +}; + +/* + * FM FIFO + */ +struct fm_fifo { + struct fm_object obj; + signed int size; + signed int in; + signed int out; + signed int len; + signed int item_size; + signed int (*input)(struct fm_fifo *thiz, void *item); + signed int (*output)(struct fm_fifo *thiz, void *item); + bool (*is_full)(struct fm_fifo *thiz); + bool (*is_empty)(struct fm_fifo *thiz); + signed int (*get_total_len)(struct fm_fifo *thiz); + signed int (*get_valid_len)(struct fm_fifo *thiz); + signed int (*reset)(struct fm_fifo *thiz); +}; + +extern struct fm_fifo *fm_fifo_init(struct fm_fifo *fifo, void *buf, const signed char *name, + signed int item_size, signed int item_num); + +extern struct fm_fifo *fm_fifo_create(const signed char *name, signed int item_size, signed int item_num); + +extern signed int fm_fifo_release(struct fm_fifo *fifo); + +#define FM_FIFO_INPUT(fifop, item) \ +({ \ + signed int __ret = (signed int)0; \ + if (fifop && (fifop)->input) { \ + __ret = (fifop)->input(fifop, item); \ + } \ + __ret; \ +}) + +#define FM_FIFO_OUTPUT(fifop, item) \ +({ \ + signed int __ret = (signed int)0; \ + if (fifop && (fifop)->output) { \ + __ret = (fifop)->output(fifop, item); \ + } \ + __ret; \ +}) + +#define FM_FIFO_IS_FULL(fifop) \ +({ \ + bool __ret = false; \ + if (fifop && (fifop)->is_full) { \ + __ret = (fifop)->is_full(fifop); \ + } \ + __ret; \ +}) + +#define FM_FIFO_IS_EMPTY(fifop) \ +({ \ + bool __ret = false; \ + if (fifop && (fifop)->is_empty) { \ + __ret = (fifop)->is_empty(fifop); \ + } \ + __ret; \ +}) + +#define FM_FIFO_RESET(fifop) \ +({ \ + signed int __ret = (signed int)0; \ + if (fifop && (fifop)->reset) { \ + __ret = (fifop)->reset(fifop); \ + } \ + __ret; \ +}) + +#define FM_FIFO_GET_TOTAL_LEN(fifop) \ +({ \ + signed int __ret = (signed int)0; \ + if (fifop && (fifop)->get_total_len) { \ + __ret = (fifop)->get_total_len(fifop); \ + } \ + __ret; \ +}) + +#define FM_FIFO_GET_VALID_LEN(fifop) \ +({ \ + signed int __ret = (signed int)0; \ + if (fifop && (fifop)->get_valid_len) { \ + __ret = (fifop)->get_valid_len(fifop); \ + } \ + __ret; \ +}) + +/* + * FM asynchronous information mechanism + */ +struct fm_flag_event { + signed int ref; + signed char name[FM_NAME_MAX + 1]; + void *priv; + + unsigned int flag; + + /* flag methods */ + unsigned int (*send)(struct fm_flag_event *thiz, unsigned int mask); + signed int (*wait)(struct fm_flag_event *thiz, unsigned int mask); + long (*wait_timeout)(struct fm_flag_event *thiz, unsigned int mask, long timeout); + unsigned int (*clr)(struct fm_flag_event *thiz, unsigned int mask); + unsigned int (*get)(struct fm_flag_event *thiz); + unsigned int (*rst)(struct fm_flag_event *thiz); +}; + +extern struct fm_flag_event *fm_flag_event_create(const signed char *name); + +extern signed int fm_flag_event_get(struct fm_flag_event *thiz); + +extern signed int fm_flag_event_put(struct fm_flag_event *thiz); + +#define FM_EVENT_SEND(eventp, mask) \ +({ \ + unsigned int __ret = (unsigned int)0; \ + if (eventp && (eventp)->send) { \ + __ret = (eventp)->send(eventp, mask); \ + } \ + __ret; \ +}) + +#define FM_EVENT_WAIT(eventp, mask) \ +({ \ + signed int __ret = (signed int)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) \ +({ \ + unsigned int __ret = (unsigned int)0; \ + if (eventp && (eventp)->get) { \ + __ret = (eventp)->get(eventp); \ + } \ + __ret; \ +}) + +#define FM_EVENT_RESET(eventp) \ +({ \ + unsigned int __ret = (unsigned int)0; \ + if (eventp && (eventp)->rst) { \ + __ret = (eventp)->rst(eventp); \ + } \ + __ret; \ +}) + +#define FM_EVENT_CLR(eventp, mask) \ +({ \ + unsigned int __ret = (unsigned int)0; \ + if (eventp && (eventp)->clr) { \ + __ret = (eventp)->clr(eventp, mask); \ + } \ + __ret; \ +}) + +/* + * FM lock mechanism + */ +struct fm_lock { + signed char name[FM_NAME_MAX + 1]; + signed int ref; + void *priv; + + /* lock methods */ + signed int (*lock)(struct fm_lock *thiz); + signed int (*trylock)(struct fm_lock *thiz, signed int retryCnt); + signed int (*unlock)(struct fm_lock *thiz); +}; + +extern struct fm_lock *fm_lock_create(const signed char *name); + +extern signed int fm_lock_get(struct fm_lock *thiz); + +extern signed int fm_lock_put(struct fm_lock *thiz); + +extern struct fm_lock *fm_spin_lock_create(const signed char *name); + +extern signed int fm_spin_lock_get(struct fm_lock *thiz); + +extern signed int fm_spin_lock_put(struct fm_lock *thiz); + +#define FM_LOCK(a) \ + ({ \ + signed int __ret = (signed int)0; \ + if (!a) { \ + __ret = -1; \ + } else if ((a)->lock) { \ + __ret = (a)->lock(a); \ + } \ + __ret; \ + }) + +#define FM_UNLOCK(a) \ + { \ + if (a && (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 { + signed int ref; + signed char name[FM_NAME_MAX + 1]; + void *priv; /* platform detail impliment */ + + signed int flag; /* timer active/inactive */ +#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE + void (*timeout_func)(struct timer_list *timer); /* timeout function */ +#else + void (*timeout_func)(unsigned long data); /* timeout function */ +#endif + unsigned long data; /* timeout function's parameter */ + signed long timeout_ms; /* timeout tick */ + /* Tx parameters */ + unsigned int count; + unsigned char tx_pwr_ctrl_en; + unsigned char tx_rtc_ctrl_en; + unsigned char tx_desense_en; + + /* timer methods */ +#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE + signed int (*init)(struct fm_timer *thiz, void (*timeout) (struct timer_list *timer), + unsigned long data, signed long time, signed int flag); +#else + signed int (*init)(struct fm_timer *thiz, void (*timeout) (unsigned long data), + unsigned long data, signed long time, signed int flag); +#endif + signed int (*start)(struct fm_timer *thiz); + signed int (*update)(struct fm_timer *thiz); + signed int (*stop)(struct fm_timer *thiz); + signed int (*control)(struct fm_timer *thiz, enum fm_timer_ctrl cmd, void *arg); +}; + +extern struct fm_timer *fm_timer_create(const signed char *name); + +extern signed int fm_timer_get(struct fm_timer *thiz); + +extern signed int fm_timer_put(struct fm_timer *thiz); + +/* + * FM work thread mechanism + */ +struct fm_work { + signed int ref; + signed char name[FM_NAME_MAX + 1]; + void *priv; + + work_func_t work_func; + unsigned long data; + /* work methods */ + signed int (*init)(struct fm_work *thiz, work_func_t work_func, unsigned long data); +}; + +extern struct fm_work *fm_work_create(const signed char *name); + +extern signed int fm_work_get(struct fm_work *thiz); + +extern signed int fm_work_put(struct fm_work *thiz); + +struct fm_workthread { + signed int ref; + signed char name[FM_NAME_MAX + 1]; + void *priv; + + /* workthread methods */ + signed int (*add_work)(struct fm_workthread *thiz, struct fm_work *work); +}; + +extern struct fm_workthread *fm_workthread_create(const signed char *name); + +extern signed int fm_workthread_get(struct fm_workthread *thiz); + +extern signed int fm_workthread_put(struct fm_workthread *thiz); + +signed int fm_delayms(unsigned int data); + +signed int fm_delayus(unsigned int data); + +unsigned short fm_get_u16_from_auc(unsigned char *buf); + +void fm_set_u16_to_auc(unsigned char *buf, unsigned short val); + +unsigned int fm_get_u32_from_auc(unsigned char *buf); + +void fm_set_u32_to_auc(unsigned char *buf, unsigned int val); + +#endif /* __FM_UTILS_H__ */ diff --git a/drivers/misc/mediatek/connectivity/fmradio/init.fmradio_drv.rc b/drivers/misc/mediatek/connectivity/fmradio/init.fmradio_drv.rc new file mode 100644 index 0000000000000..d1111d0c41c48 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/init.fmradio_drv.rc @@ -0,0 +1,5 @@ + +# load fmradio_drv +on property:vendor.connsys.driver.ready=yes + insmod /vendor/lib/modules/fmradio_drv.ko + diff --git a/drivers/misc/mediatek/connectivity/fmradio/plat/conn_infra.c b/drivers/misc/mediatek/connectivity/fmradio/plat/conn_infra.c new file mode 100644 index 0000000000000..6d9c49d44ff0a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/plat/conn_infra.c @@ -0,0 +1,1505 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include "plat.h" + +/* CONNSYS register address */ +#if CFG_FM_CONNAC2 +#define AP_BASE_ADDRESS 0x18000000 +#define MCU_CFG_ADDR (AP_BASE_ADDRESS + 0x0) +#define MCU_CFG_CONSYS_BASE MCU_CFG_ADDR +#define MCU_CFG_SIZE 0x10000 +#define TOP_MISC_OFF_ADDR (AP_BASE_ADDRESS + 0x60000) +#define TOP_MISC_OFF_CONSYS_BASE TOP_MISC_OFF_ADDR +#define TOP_MISC_OFF_SIZE 0x1000 +#define TOP_RF_SPI_AON_ADDR (AP_BASE_ADDRESS + 0x4000) +#define TOP_RF_SPI_AON_CONSYS_BASE TOP_RF_SPI_AON_ADDR +#define TOP_RF_SPI_AON_SIZE 0x1000 +#else +#define AP_BASE_ADDRESS 0x18000000 +#define MCU_CFG_ADDR (AP_BASE_ADDRESS + 0x02000) +#define MCU_CFG_CONSYS_BASE 0x80000000 +#define MCU_CFG_SIZE 0x1000 +#define TOP_MISC_OFF_ADDR (AP_BASE_ADDRESS + 0xB0000) +#define TOP_MISC_OFF_CONSYS_BASE 0x80020000 +#define TOP_MISC_OFF_SIZE 0x10000 +#define TOP_RF_SPI_AON_ADDR (AP_BASE_ADDRESS + 0xC0000) +#define TOP_RF_SPI_AON_CONSYS_BASE 0x81020000 +#define TOP_RF_SPI_AON_SIZE 0x10000 +#endif /* CFG_FM_CONNAC2 */ + +#define FM_IRQ_NUMBER 0 +#define MAX_SET_OWN_COUNT 1000 + +#if CFG_FM_CONNAC2 +static int (*whole_chip_reset)(signed int sta); + +static int fm_pre_whole_chip_rst(enum consys_drv_type drv, char *reason) +{ + WCN_DBG(FM_WAR | LINK, "FM pre whole chip rst!\n"); + if (whole_chip_reset) + whole_chip_reset(1); + return 0; +} + +static int fm_post_whole_chip_rst(void) +{ + WCN_DBG(FM_WAR | LINK, "FM post whole chip rst!\n"); + if (whole_chip_reset) + whole_chip_reset(0); + return 0; +} + +static struct sub_drv_ops_cb fm_drv_cbs = { + .rst_cb.pre_whole_chip_rst = fm_pre_whole_chip_rst, + .rst_cb.post_whole_chip_rst = fm_post_whole_chip_rst, + .pre_cal_cb.pwr_on_cb = NULL, + .pre_cal_cb.do_cal_cb = NULL, +}; + +static int drv_sys_spi_read( + struct fm_spi_interface *si, unsigned int subsystem, + unsigned int addr, unsigned int *data) +{ + WCN_DBG(FM_DBG | CHIP, "[0x%08x]=[0x%08x]\n", addr, *data); + return conninfra_spi_read(subsystem, addr, data); +} + +static int drv_sys_spi_write( + struct fm_spi_interface *si, unsigned int subsystem, + unsigned int addr, unsigned int data) +{ + WCN_DBG(FM_DBG | CHIP, "[0x%08x]=[0x%08x]\n", addr, data); + return conninfra_spi_write(subsystem, addr, data); +} +#else /* CFG_FM_CONNAC2 */ +static int sys_spi_wait(unsigned int spi_busy) +{ + struct fm_spi_interface *si = &fm_wcn_ops.si; + unsigned int spi_count, rdata; + + /* It needs to prevent infinite loop */ + for (spi_count = 0; spi_count < FM_SPI_COUNT_LIMIT; spi_count++) { + si->spi_read(si, SYS_SPI_STA, &rdata); + if ((rdata & spi_busy) == 0) + break; + } + if (spi_count == FM_SPI_COUNT_LIMIT) { + WCN_DBG(FM_WAR | CHIP, + "SPI busy[0x%08x], retry count reached maximum.\n", + rdata); + return FM_SYS_SPI_BUSY; + } + return FM_SYS_SPI_OK; +} + +static int fm_sys_spi_read( + struct fm_spi_interface *si, unsigned int subsystem, + unsigned int addr, unsigned int *data) +{ + unsigned int spi_busy, spi_addr, spi_mask, spi_wdat, spi_rdat, rdata; + + if (!si->spi_read || !si->spi_write) { + WCN_DBG(FM_ERR | CHIP, "spi api is NULL.\n"); + return FM_SYS_SPI_ERR; + } + + switch (subsystem) { + case SYS_SPI_WF: + spi_busy = 1 << SYS_SPI_STA_WF_BUSY_SHFT; + spi_addr = SYS_SPI_WF_ADDR_ADDR; + spi_mask = SYS_SPI_WF_RDAT_MASK; + spi_wdat = SYS_SPI_WF_WDAT_ADDR; + spi_rdat = SYS_SPI_WF_RDAT_ADDR; + addr = SYS_SPI_ADDR_CR_READ | SYS_SPI_ADDR_CR_WF | (addr & SYS_SPI_ADDR_CR_MASK); + break; + case SYS_SPI_BT: + spi_busy = 1 << SYS_SPI_STA_BT_BUSY_SHFT; + spi_addr = SYS_SPI_BT_ADDR_ADDR; + spi_mask = SYS_SPI_BT_RDAT_MASK; + spi_wdat = SYS_SPI_BT_WDAT_ADDR; + spi_rdat = SYS_SPI_BT_RDAT_ADDR; + addr = SYS_SPI_ADDR_CR_READ | SYS_SPI_ADDR_CR_BT | (addr & SYS_SPI_ADDR_CR_MASK); + break; + case SYS_SPI_FM: + spi_busy = 1 << SYS_SPI_STA_FM_BUSY_SHFT; + spi_addr = SYS_SPI_FM_ADDR_ADDR; + spi_mask = SYS_SPI_FM_RDAT_MASK; + spi_wdat = SYS_SPI_FM_WDAT_ADDR; + spi_rdat = SYS_SPI_FM_RDAT_ADDR; + addr = SYS_SPI_ADDR_CR_READ | SYS_SPI_ADDR_CR_FM | (addr & SYS_SPI_ADDR_CR_MASK); + break; + case SYS_SPI_GPS: + spi_busy = 1 << SYS_SPI_STA_GPS_BUSY_SHFT; + spi_addr = SYS_SPI_GPS_ADDR_ADDR; + spi_mask = SYS_SPI_GPS_RDAT_MASK; + spi_wdat = SYS_SPI_GPS_WDAT_ADDR; + spi_rdat = SYS_SPI_GPS_RDAT_ADDR; + addr = SYS_SPI_ADDR_CR_READ | SYS_SPI_ADDR_CR_GPS | (addr & SYS_SPI_ADDR_CR_MASK); + break; + case SYS_SPI_TOP: + spi_busy = 1 << SYS_SPI_STA_TOP_BUSY_SHFT; + spi_addr = SYS_SPI_TOP_ADDR_ADDR; + spi_mask = SYS_SPI_TOP_RDAT_MASK; + spi_wdat = SYS_SPI_TOP_WDAT_ADDR; + spi_rdat = SYS_SPI_TOP_RDAT_ADDR; + addr = SYS_SPI_ADDR_CR_READ | SYS_SPI_ADDR_CR_TOP | (addr & SYS_SPI_ADDR_CR_MASK); + break; + case SYS_SPI_WF1: + spi_busy = 1 << SYS_SPI_STA_WF_BUSY_SHFT; + spi_addr = SYS_SPI_WF_ADDR_ADDR; + spi_mask = SYS_SPI_WF_RDAT_MASK; + spi_wdat = SYS_SPI_WF_WDAT_ADDR; + spi_rdat = SYS_SPI_WF_RDAT_ADDR; + addr = SYS_SPI_ADDR_CR_READ | SYS_SPI_ADDR_CR_WF1 | (addr & SYS_SPI_ADDR_CR_MASK); + break; + default: + return FM_SYS_SPI_ERR; + } + + if (sys_spi_wait(spi_busy) == FM_SYS_SPI_BUSY) + return FM_SYS_SPI_BUSY; + + si->spi_write(si, spi_addr, addr); + si->spi_write(si, spi_wdat, 0); + + sys_spi_wait(spi_busy); + + si->spi_read(si, spi_rdat, &rdata); + *data = rdata & spi_mask; + + WCN_DBG(FM_DBG | CHIP, "[0x%08x]=[0x%08x]\n", addr, *data); + + return FM_SYS_SPI_OK; +} + +static int fm_sys_spi_write( + struct fm_spi_interface *si, unsigned int subsystem, + unsigned int addr, unsigned int data) +{ + unsigned int spi_busy, spi_addr, spi_mask, spi_wdat; + + if (!si->spi_read || !si->spi_write) { + WCN_DBG(FM_ERR | CHIP, "spi api is NULL.\n"); + return FM_SYS_SPI_ERR; + } + + switch (subsystem) { + case SYS_SPI_WF: + spi_busy = 1 << SYS_SPI_STA_WF_BUSY_SHFT; + spi_addr = SYS_SPI_WF_ADDR_ADDR; + spi_mask = SYS_SPI_WF_WDAT_MASK; + spi_wdat = SYS_SPI_WF_WDAT_ADDR; + addr = SYS_SPI_ADDR_CR_WRITE | SYS_SPI_ADDR_CR_WF | (addr & SYS_SPI_ADDR_CR_MASK); + break; + case SYS_SPI_BT: + spi_busy = 1 << SYS_SPI_STA_BT_BUSY_SHFT; + spi_addr = SYS_SPI_BT_ADDR_ADDR; + spi_mask = SYS_SPI_BT_WDAT_MASK; + spi_wdat = SYS_SPI_BT_WDAT_ADDR; + addr = SYS_SPI_ADDR_CR_WRITE | SYS_SPI_ADDR_CR_BT | (addr & SYS_SPI_ADDR_CR_MASK); + break; + case SYS_SPI_FM: + spi_busy = 1 << SYS_SPI_STA_FM_BUSY_SHFT; + spi_addr = SYS_SPI_FM_ADDR_ADDR; + spi_mask = SYS_SPI_FM_WDAT_MASK; + spi_wdat = SYS_SPI_FM_WDAT_ADDR; + addr = SYS_SPI_ADDR_CR_WRITE | SYS_SPI_ADDR_CR_FM | (addr & SYS_SPI_ADDR_CR_MASK); + break; + case SYS_SPI_TOP: + spi_busy = 1 << SYS_SPI_STA_TOP_BUSY_SHFT; + spi_addr = SYS_SPI_TOP_ADDR_ADDR; + spi_mask = SYS_SPI_TOP_WDAT_MASK; + spi_wdat = SYS_SPI_TOP_WDAT_ADDR; + addr = SYS_SPI_ADDR_CR_WRITE | SYS_SPI_ADDR_CR_TOP | (addr & SYS_SPI_ADDR_CR_MASK); + break; + case SYS_SPI_WF1: + spi_busy = 1 << SYS_SPI_STA_WF_BUSY_SHFT; + spi_addr = SYS_SPI_WF_ADDR_ADDR; + spi_mask = SYS_SPI_WF_WDAT_MASK; + spi_wdat = SYS_SPI_WF_WDAT_ADDR; + addr = SYS_SPI_ADDR_CR_WRITE | SYS_SPI_ADDR_CR_WF1 | (addr & SYS_SPI_ADDR_CR_MASK); + break; + default: + return FM_SYS_SPI_ERR; + } + + if (sys_spi_wait(spi_busy) == FM_SYS_SPI_BUSY) + return FM_SYS_SPI_BUSY; + + si->spi_write(si, spi_addr, addr); + si->spi_write(si, spi_wdat, (data & spi_mask)); + + sys_spi_wait(spi_busy); + + WCN_DBG(FM_DBG | CHIP, "[0x%08x]=[0x%08x]\n", addr, data); + + return FM_SYS_SPI_OK; +} +#endif /* CFG_FM_CONNAC2 */ + +static void drv_spi_read( + struct fm_spi_interface *si, unsigned int addr, unsigned int *val) +{ + *val = readl(si->info.spi_vir_addr + addr); +} + +static void drv_spi_write( + struct fm_spi_interface *si, unsigned int addr, unsigned int val) +{ + writel(val, si->info.spi_vir_addr + addr); +} + +static void drv_top_read( + struct fm_spi_interface *si, unsigned int addr, unsigned int *val) +{ + *val = readl(si->info.top_vir_addr + addr); +} + +static void drv_top_write( + struct fm_spi_interface *si, unsigned int addr, unsigned int val) +{ + writel(val, si->info.top_vir_addr + addr); +} + +static void drv_mcu_read( + struct fm_spi_interface *si, unsigned int addr, unsigned int *val) +{ + *val = readl(si->info.mcu_vir_addr + addr); +} + +static void drv_mcu_write( + struct fm_spi_interface *si, unsigned int addr, unsigned int val) +{ + writel(val, si->info.mcu_vir_addr + addr); +} + +static void drv_host_read( + struct fm_spi_interface *si, unsigned int addr, unsigned int *data) +{ + unsigned new_addr = addr; + + if (addr >= TOP_RF_SPI_AON_CONSYS_BASE && + addr <= TOP_RF_SPI_AON_CONSYS_BASE + TOP_RF_SPI_AON_SIZE) { + new_addr = addr - TOP_RF_SPI_AON_CONSYS_BASE; + drv_spi_read(si, new_addr, data); + } else if (addr >= MCU_CFG_CONSYS_BASE && + addr <= MCU_CFG_CONSYS_BASE + MCU_CFG_SIZE) { + new_addr = addr - MCU_CFG_CONSYS_BASE; + drv_mcu_read(si, new_addr, data); + } else if (addr >= TOP_MISC_OFF_CONSYS_BASE && + addr <= TOP_MISC_OFF_CONSYS_BASE + TOP_MISC_OFF_SIZE) { + new_addr = addr - TOP_MISC_OFF_CONSYS_BASE; + drv_top_read(si, new_addr, data); + } else { + WCN_DBG(FM_WAR | CHIP, "not support addr[0x%08x].\n", addr); + return; + } + + WCN_DBG(FM_DBG | CHIP, "read [0x%08x]=[0x%08x]\n", + new_addr, addr, *data); +} + +static void drv_host_write( + struct fm_spi_interface *si, unsigned int addr, unsigned int data) +{ + unsigned new_addr = addr; + + if (addr >= TOP_RF_SPI_AON_CONSYS_BASE && + addr <= TOP_RF_SPI_AON_CONSYS_BASE + TOP_RF_SPI_AON_SIZE) { + new_addr = addr - TOP_RF_SPI_AON_CONSYS_BASE; + drv_spi_write(si, new_addr, data); + } else if (addr >= MCU_CFG_CONSYS_BASE && + addr <= MCU_CFG_CONSYS_BASE + MCU_CFG_SIZE) { + new_addr = addr - MCU_CFG_CONSYS_BASE; + drv_mcu_write(si, new_addr, data); + } else if (addr >= TOP_MISC_OFF_CONSYS_BASE && + addr <= TOP_MISC_OFF_CONSYS_BASE + TOP_MISC_OFF_SIZE) { + new_addr = addr - TOP_MISC_OFF_CONSYS_BASE; + drv_top_write(si, new_addr, data); + } else { + WCN_DBG(FM_WAR | CHIP, "not support addr[0x%08x].\n", addr); + return; + } + + WCN_DBG(FM_DBG | CHIP, "write [0x%08x/0x%08x]=[0x%08x]\n", + new_addr, addr, data); +} + +/** + * Send TX data via STP format + * + * @param None + * + * @return None + */ +static void fm_tx(unsigned char *buf, unsigned short length) +{ + if (FM_LOCK(fm_wcn_ops.tx_lock)) + return; + + if (length == 0xFFFF) { + length = (unsigned short)buf[2] + + (unsigned short)(buf[3] << 8) + FM_HDR_SIZE; + } + + memset(fm_wcn_ops.rx_buf, 0, RX_BUF_SIZE); + memcpy(fm_wcn_ops.rx_buf, buf, length); + fm_wcn_ops.rx_len = length; + fm_event_parser(fm_rds_parser); + + FM_UNLOCK(fm_wcn_ops.tx_lock); +} + +static void fm_stc_done_rechandler(void) +{ + unsigned short i, reg_value, freq, isr_value; + + fw_spi_read(FM_MAIN_CTRL, &isr_value); + + WCN_DBG(FM_NTC | CHIP, "isr_value[%04x]\n", isr_value); + + if (isr_value & FM_MAIN_CTRL_SEEK) { + unsigned char data[6]; + + fw_spi_read(FM_MAIN_CHANDETSTAT, ®_value); + + /* freq's unit is 10kHz */ + freq = ((((reg_value & 0x3ff0) >> 4) >> 1) + 640) * 10; + + data[0] = FM_TASK_EVENT_PKT_TYPE; + data[1] = FM_SEEK_OPCODE; + /* payload length */ + data[2] = 2; + data[3] = 0x00; + data[4] = (unsigned char)freq & 0xFF; + data[5] = (unsigned char)(freq >> 8); + + fm_tx(data, 0xFFFF); + } else if (isr_value & FM_MAIN_CTRL_SCAN) { + unsigned char data[36]; + + for (i = 0; i <= SCAN_BUFF_LEN; i++) { + fw_spi_read(RDS_DATA_REG, ®_value); + data[4 + (i * 2)] = reg_value & 0xff; + data[4 + (i * 2) + 1] = (reg_value & 0xff00) >> 8; + } + + data[0] = FM_TASK_EVENT_PKT_TYPE; + data[1] = FM_SCAN_OPCODE; + /* payload length */ + data[2] = 32; + data[3] = 0x00; + + fm_tx(data, 0xFFFF); + } else if (isr_value & FM_MAIN_CTRL_TUNE) { + unsigned char data[5]; + + data[0] = FM_TASK_EVENT_PKT_TYPE; + data[1] = FM_TUNE_OPCODE; + /* payload length */ + data[2] = 0x01; + data[3] = 0x00; + data[4] = 0x01; + fm_tx(data, 0x0005); + } +} + +static void fm_rds_rechandler(void) +{ + unsigned short fifo_cnt, reg_value, rds_data[6], reg_sin, reg_cos; + unsigned short crc = 0, corr_cnt = 0, rds_info; + unsigned short output_point, temp_data; + unsigned short i = 0; + unsigned char data[128]; + + do { + fw_spi_read(RDS_FIFO_STATUS0, &fifo_cnt); + fifo_cnt = (fifo_cnt & RDS_DCO_FIFO_OFST) >> + RDS_DCO_FIFO_OFST_SHFT; + + /* block A data and info handling */ + fw_spi_read(RDS_INFO_REG, &rds_info); + crc |= (rds_info & RDS_CRC_INFO) << 3; + corr_cnt |= ((rds_info & RDS_CRC_CORR_CNT) << 11); + fw_spi_read(RDS_DATA_REG, &(rds_data[0])); + + /* block B data and info handling */ + fw_spi_read(RDS_INFO_REG, &rds_info); + crc |= (rds_info & RDS_CRC_INFO) << 2; + corr_cnt |= ((rds_info & RDS_CRC_CORR_CNT) << 7); + fw_spi_read(RDS_DATA_REG, &(rds_data[1])); + + /* block C data and info handling */ + fw_spi_read(RDS_INFO_REG, &rds_info); + crc |= (rds_info & RDS_CRC_INFO) << 1; + corr_cnt |= ((rds_info & RDS_CRC_CORR_CNT) << 3); + fw_spi_read(RDS_DATA_REG, &(rds_data[2])); + + /* block D data and info handling */ + fw_spi_read(RDS_INFO_REG, &rds_info); + crc |= (rds_info & RDS_CRC_INFO); + corr_cnt |= ((rds_info & RDS_CRC_CORR_CNT) >> 1); + fw_spi_read(RDS_DATA_REG, &(rds_data[3])); + + + rds_data[4] = corr_cnt; + rds_data[5] = crc; + + /* -1 due to H/W behavior */ + if (fifo_cnt > 0) + fifo_cnt--; + + /* RDS recovery start */ + /* check if reading doesn't start at block A */ + fw_spi_read(RDS_POINTER, &output_point); + while (output_point & 0x3) { + fw_spi_read(RDS_DATA_REG, &temp_data); + fw_spi_read(RDS_POINTER, &output_point); + } + /* RDS recovery end */ + + fm_set_u16_to_auc(&(data[8 + 12 * i]), rds_data[0]); + fm_set_u16_to_auc(&(data[10 + 12 * i]), rds_data[1]); + fm_set_u16_to_auc(&(data[12 + 12 * i]), rds_data[2]); + fm_set_u16_to_auc(&(data[14 + 12 * i]), rds_data[3]); + fm_set_u16_to_auc(&(data[16 + 12 * i]), rds_data[4]); + fm_set_u16_to_auc(&(data[18 + 12 * i]), rds_data[5]); + + i++; + } while ((i < 10) && ((fifo_cnt & 0x1F) > 0)); + + if (i > 0) { + fw_spi_read(RDS_SIN_REG, ®_sin); + fw_spi_read(RDS_COS_REG, ®_cos); + + data[0] = FM_TASK_EVENT_PKT_TYPE; + data[1] = RDS_RX_DATA_OPCODE; + /* payload length */ + data[2] = (unsigned char)(12 * i + 4); + data[3] = 0x00; + fm_set_u16_to_auc(&(data[4]), reg_sin); + fm_set_u16_to_auc(&(data[6]), reg_cos); + fm_tx(data, 0xFFFF); + } + + fw_spi_read(FM_MAIN_EXTINTRMASK, ®_value); + reg_value |= (FM_INTR_RDS << 8); + fw_spi_write(FM_MAIN_EXTINTRMASK, reg_value); +} + +static void fm_fifo_rechandler(unsigned short intr) +{ + unsigned short reg_value; + + /* Handle channel info. data in FIFO if RDS interrupt + * and CQI interrupt arise simultaneously + */ + if ((intr & 0x0001) && (intr & 0x0020)) { + unsigned short i; + unsigned char data[100]; + + for (i = 0; i < FIFO_LEN; i++) { + fw_spi_read(RDS_DATA_REG, ®_value); + data[4 + (i * 2)] = reg_value & 0xff; + data[4 + (i * 2) + 1] = (reg_value & 0xff00) >> 8; + } + + data[0] = FM_TASK_EVENT_PKT_TYPE; + data[1] = FM_SCAN_OPCODE; + /* payload length */ + data[2] = (unsigned char)(FIFO_LEN<<1); + data[3] = 0x00; + + fm_tx(data, 0xFFFF); + } + /* Handle RDS data in FIFO, while only RDS interrupt issues */ + else if (intr & 0x0020) { + + fw_spi_read(FM_MAIN_EXTINTRMASK, ®_value); + reg_value &= ~(FM_INTR_RDS << 8); + fw_spi_write(FM_MAIN_EXTINTRMASK, reg_value); + + fm_rds_rechandler(); + } + +} + +static void fm_softmute_tune(unsigned short freq, unsigned char *pos) +{ + unsigned short rdata; + unsigned int i = 0, PRX = 0, ATEDV = 0, PR = 0; + int RSSI = 0, PAMD = 0, FPAMD = 0, MR = 0, ATDC = 0; + struct fm_full_cqi *p_cqi = (struct fm_full_cqi *)pos; + + p_cqi->ch = freq; + + /* soft mute tune */ + fw_bop_modify(FM_MAIN_CG2_CTRL, 0xBFFF, 0x4000); + /* disable interrupt */ + fw_spi_write(FM_MAIN_INTRMASK, 0x0000); + fw_spi_write(FM_MAIN_EXTINTRMASK, 0x0000); + /* ramp down */ + fw_bop_modify(FM_MAIN_CTRL, 0xFFF0, 0x0000); + /* Set DSP ramp down state */ + fw_bop_modify(FM_MAIN_CTRL, 0xFFFF, 0x0100); + + fw_bop_rd_until(FM_MAIN_INTR, 0x0001, 0x0001); + + fw_bop_modify(FM_MAIN_CTRL, 0xFEFF, 0x0000); + fw_bop_modify(FM_MAIN_INTR, 0xFFFF, 0x0001); + + /* tune */ + freq = freq / 5 - 1280; + fw_bop_modify(0x65, 0xFC00, freq); + fw_bop_modify(FM_MAIN_CTRL, 0xFFFF, 0x0001); + fw_bop_rd_until(FM_MAIN_INTR, 0x0001, 0x0001); + fw_bop_modify(FM_MAIN_INTR, 0xFFFF, 0x0001); + + /* get CQI */ + fw_bop_udelay(9000); + for (i = 0; i < 8; i++) { + /* RSSI */ + fw_spi_read(0x6C, &rdata); + RSSI += ((rdata & 0x3FF) >= 512) ? + ((rdata & 0x3FF) - 1024) : (rdata & 0x3FF); + + /* PAMD */ + fw_spi_read(0xB4, &rdata); + PAMD += ((rdata & 0x1FF) >= 256) ? + ((rdata & 0x1FF) - 512) : (rdata & 0x1FF); + + /* PR */ + fw_spi_read(0xB5, &rdata); + PR += (rdata & 0x3FF); + + /* FPAMD */ + fw_spi_read(0xBC, &rdata); + FPAMD += ((rdata & 0xFFF) >= 2048) ? + ((rdata & 0xFFF) - 4096) : (rdata & 0xFFF); + + /* MR */ + fw_spi_read(0xBD, &rdata); + MR += ((rdata & 0x1FF) >= 256) ? + ((rdata & 0x1FF) - 512) : (rdata & 0x1FF); + + /* ATDC */ + fw_spi_read(0x83, &rdata); + ATDC += (rdata >= 32768) ? (65536 - rdata) : rdata; + + /* PRX */ + fw_spi_read(0x84, &rdata); + PRX += rdata & 0xFF; + + /* ATDEV */ + fw_spi_read(0x85, &rdata); + ATEDV += rdata; + + fw_bop_udelay(2250); + } + + RSSI = (RSSI + 4) / 8; + p_cqi->rssi = RSSI & 0x03FF; + PAMD = (PAMD + 4) / 8; + p_cqi->pamd = PAMD & 0x01FF; + PR = (PR + 4) / 8; + p_cqi->pr = PR & 0x03FF; + FPAMD = (FPAMD + 4) / 8; + p_cqi->fpamd = FPAMD & 0x0FFF; + MR = (MR + 4) / 8; + p_cqi->mr = MR & 0x01FF; + ATDC = (ATDC + 4) / 8; + p_cqi->atdc = ATDC & 0xFFFF; + PRX = (PRX + 4) / 8; + p_cqi->prx = PRX & 0x00FF; + ATEDV = (ATEDV + 4) / 8; + p_cqi->atdev = ATEDV & 0xFFFF; + + /* Soft_mute Gain */ + fw_spi_read(0x86, &rdata); + p_cqi->smg = rdata; + + /* delta RSSI */ + fw_spi_read(0x88, &rdata); + p_cqi->drssi = rdata; + + /* clear soft mute tune */ + fw_bop_modify(FM_MAIN_CG2_CTRL, 0xBFFF, 0x0000); + + WCN_DBG(FM_DBG | 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); +} + +static void fm_dsp_download( + unsigned char target, unsigned short length, + unsigned char total_seg, unsigned char current_seg, + unsigned char *data) +{ + unsigned int control_code = 0; + unsigned short i; + + switch (target) { + case DSP_ROM: + case DSP_PATCH: + control_code = 0x10; + break; + case DSP_COEFF: + control_code = 0xe; + break; + case DSP_HWCOEFF: + control_code = 0xd; + break; + default: + break; + } + + if (current_seg == 0) { + fw_spi_write(CONTROL_REG, 0); + /* Start address */ + fw_spi_write(OFFSET_REG, data[1] << 8 | data[0]); + /* Reset download control */ + fw_spi_write(CONTROL_REG, 0x40); + /* Set download control */ + fw_spi_write(CONTROL_REG, control_code); + data += 4; + length -= 4; + } + + if (length > 0) { + for (i = 0; i < (length >> 1); i++) + fw_spi_write(DATA_REG, data[2 * i + 1] << 8 | data[2 * i]); + } else { + WCN_DBG(FM_ERR | CHIP, "incorrect length[%d].\n", length); + } +} + +static void fm_task_rx_basic_op( + unsigned char bop, unsigned char length, unsigned char *buf) +{ + struct fm_spi_interface *si = &fm_wcn_ops.si; + + switch (bop) { + case FM_WRITE_BASIC_OP: + fw_spi_write(buf[0], fm_get_u16_from_auc(&buf[1])); + break; + + case FM_UDELAY_BASIC_OP: + fw_bop_udelay(fm_get_u32_from_auc(&buf[0])); + break; + + case FM_RD_UNTIL_BASIC_OP: + fw_bop_rd_until(buf[0], fm_get_u16_from_auc(&buf[1]), + fm_get_u16_from_auc(&buf[3])); + break; + + case FM_MODIFY_BASIC_OP: + fw_bop_modify(buf[0], fm_get_u16_from_auc(&buf[1]), + fm_get_u16_from_auc(&buf[3])); + break; + + case FM_MSLEEP_BASIC_OP: + fm_delayms(fm_get_u32_from_auc(&buf[0])); + break; + + case FM_WRITE_SPI_BASIC_OP: + si->sys_spi_write(si, buf[0], fm_get_u16_from_auc(&buf[1]), + fm_get_u32_from_auc(&buf[3])); + break; + case FM_RD_SPI_UNTIL_BASIC_OP: + fw_bop_spi_rd_until(buf[0], fm_get_u16_from_auc(&buf[1]), + fm_get_u32_from_auc(&buf[3]), + fm_get_u32_from_auc(&buf[7])); + break; + case FM_MODIFY_SPI_BASIC_OP: + fw_bop_spi_modify(buf[0], fm_get_u16_from_auc(&buf[1]), + fm_get_u32_from_auc(&buf[3]), + fm_get_u32_from_auc(&buf[7])); + break; + + default: + break; + } +} + +/** + * FM task rx dispatcher default functions for basic operation processing + * + * @param opcode opcode for different packet type + * @param length the length of parameters + * @param buf the parameters for different packet type + * + * @return None + */ +static void fm_task_rx_dispatcher_default( + unsigned char opcode, unsigned short length, unsigned char *buf) +{ + int unused_op_size = length; + unsigned short used_op_size = 0; + + while (unused_op_size > 0) { + unsigned char basic_op = buf[used_op_size]; + unsigned char basic_op_length = buf[used_op_size + 1]; + unsigned char *basic_op_buf = &buf[used_op_size + 2]; + + fm_task_rx_basic_op(basic_op, basic_op_length, + basic_op_buf); + unused_op_size -= (int)(basic_op_length + 2); + used_op_size += (unsigned short)(basic_op_length + 2); + } +} + +/** + * FM task rx dispatcher functions for different packet type + * + * @param opcode opcode for different packet type + * @param length the length of parameters + * @param buf the parameters for different packet type + * + * @return None + */ +static void fm_task_rx_dispatcher( + unsigned char opcode, unsigned short length, unsigned char *buf) +{ + unsigned char event[28]; + + /* Prepare FM event packet, default no payload */ + event[0] = FM_TASK_EVENT_PKT_TYPE; + event[1] = opcode; + event[2] = 0x0; + event[3] = 0x0; + + switch (opcode) { + case FM_STP_TEST_OPCODE: + event[2] = 0x3; + event[3] = 0x0; + event[4] = 0x0; + event[5] = 0x1; + event[6] = 0x2; + break; + case FSPI_ENABLE_OPCODE: + break; + case FSPI_MUX_SEL_OPCODE: + break; + case FSPI_READ_OPCODE: + { + unsigned short data; + + fw_spi_read(buf[0], &data); + event[2] = 0x2; + event[3] = 0x0; + fm_set_u16_to_auc(&event[4], data); + break; + } + case FSPI_WRITE_OPCODE: + fw_spi_write(buf[0], fm_get_u16_from_auc(&buf[1])); + break; + + case FM_PATCH_DOWNLOAD_OPCODE: + fm_dsp_download(DSP_PATCH, length - 2, buf[0], buf[1], &buf[2]); + break; + + case FM_COEFF_DOWNLOAD_OPCODE: + fm_dsp_download(DSP_COEFF, length - 2, buf[0], buf[1], &buf[2]); + break; + + case FM_HWCOEFF_DOWNLOAD_OPCODE: + fm_dsp_download(DSP_HWCOEFF, length - 2, buf[0], buf[1], &buf[2]); + break; + + case FM_ROM_DOWNLOAD_OPCODE: + fm_dsp_download(DSP_ROM, length - 2, buf[0], buf[1], &buf[2]); + break; + case FM_SOFT_MUTE_TUNE_OPCODE: + { + switch (buf[0]) { + case 1: + { + unsigned short freq = 0; + + fm_set_u16_to_auc(&event[2], + (FM_SOFTMUTE_TUNE_CQI_SIZE + 2)); + event[4] = FM_SOFTMUTE_TUNE_CQI_SIZE; + event[5] = 0x01; + freq = fm_get_u16_from_auc(&buf[1]); + fm_softmute_tune(freq, &event[6]); + break; + } + case 2: + case 3: + case 4: + default: + { + event[2] = 0x00; + event[3] = 0x00; + memcpy(&event[2], buf, 3); + break; + } + } + break; + } + case FM_HOST_READ_OPCODE: + { + struct fm_spi_interface *si = &fm_wcn_ops.si; + unsigned int addr, data; + + addr = fm_get_u32_from_auc(&buf[0]); + si->host_read(si, addr, &data); + event[2] = 0x4; + event[3] = 0x0; + fm_set_u32_to_auc(&event[4], data); + } + break; + case FM_HOST_WRITE_OPCODE: + { + struct fm_spi_interface *si = &fm_wcn_ops.si; + unsigned int addr, data; + + addr = fm_get_u32_from_auc(&buf[0]); + data = fm_get_u32_from_auc(&buf[4]); + si->host_write(si, addr, data); + + break; + } + case CSPI_WRITE_OPCODE: + { + struct fm_spi_interface *si = &fm_wcn_ops.si; + + si->sys_spi_write(si, buf[0], fm_get_u16_from_auc(&buf[1]), + fm_get_u32_from_auc(&buf[3])); + break; + } + case CSPI_READ_OPCODE: + { + struct fm_spi_interface *si = &fm_wcn_ops.si; + unsigned int data; + unsigned short ret; + + ret = si->sys_spi_read( + si, buf[0], fm_get_u16_from_auc(&buf[1]), &data); + + if (ret != 0) + data = (unsigned short)ret; + + event[2] = 0x4; + event[3] = 0x0; + fm_set_u32_to_auc(&event[4], data); + break; + } + case FM_HOST_MODIFY_OPCODE: + { + struct fm_spi_interface *si = &fm_wcn_ops.si; + unsigned int addr, data; + + addr = fm_get_u32_from_auc(&buf[0]); + si->host_read(si, addr, &data); + data &= fm_get_u32_from_auc(&buf[4]); + data |= fm_get_u32_from_auc(&buf[8]); + si->host_write(si, addr, data); + break; + } + default: + fm_task_rx_dispatcher_default(opcode, length, buf); + break; + } + fm_tx(event, 0xFFFF); +} + +static bool drv_set_own(void) +{ + struct fm_spi_interface *si = &fm_wcn_ops.si; + struct fm_ext_interface *ei = &fm_wcn_ops.ei; + unsigned int val, tmp, i; + int ret = 0; + + ret = FM_LOCK(fm_wcn_ops.own_lock); + for (i = 0; ret && i < MAX_SET_OWN_COUNT; i++) { + fm_delayms(2); + ret = FM_LOCK(fm_wcn_ops.own_lock); + } + + /* get lock fail */ + if (i == MAX_SET_OWN_COUNT) { + WCN_DBG(FM_ERR | CHIP, "get own lock fail[%d]\n", ret); + return false; + } + + /* wakeup conninfra */ + drv_host_write(si, 0x180601B0, 0x1); + + /* polling chipid */ + drv_host_read(si, 0x18001000, &val); + for (i = 0; (val & 0xFFFF0000) != 0x20010000 && i < MAX_SET_OWN_COUNT; i++) { + fm_delayus(5000); + drv_host_read(si, 0x18001000, &val); + } + + /* polling fail */ + if (i == MAX_SET_OWN_COUNT) { + /* unlock if set own fail */ + drv_host_read(si, 0x180601B0, &val); + drv_host_read(si, 0x18001808, &tmp); + WCN_DBG(FM_ERR | CHIP, + "polling chip id fail [0x180601B0]=[0x%08x], [0x18001808]=[0x%08x]\n", + val, tmp); + FM_UNLOCK(fm_wcn_ops.own_lock); + return false; + } + + if (ei->is_bus_hang && ei->is_bus_hang()) { + FM_UNLOCK(fm_wcn_ops.own_lock); + return false; + } + + /* conn_infra bus debug function setting */ + conninfra_config_setup(); + + return true; +} + +static bool drv_clr_own(void) +{ + struct fm_spi_interface *si = &fm_wcn_ops.si; + + drv_host_write(si, 0x180601B0, 0x0); + + FM_UNLOCK(fm_wcn_ops.own_lock); + + return true; +} + +static int drv_stp_send_data(unsigned char *buf, unsigned int len) +{ + struct fm_spi_interface *si = &fm_wcn_ops.si; + + if (len < 4) { + WCN_DBG(FM_ERR | CHIP, "buf length error[%d].\n", len); + return -1; + } + + if (si->set_own && !si->set_own()) { + WCN_DBG(FM_ERR | CHIP, "set_own fail\n"); + return -1; + } + + fm_task_rx_dispatcher(buf[1], len - 4, buf + 4); + + if (si->clr_own) + si->clr_own(); + + WCN_DBG(FM_DBG | CHIP, "buffer: %02x %02x %02x %02x %02x %02x\n", + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); + + return 1; +} + +static int drv_stp_recv_data(unsigned char *buf, unsigned int len) +{ + unsigned int length = fm_wcn_ops.rx_len; + + if (length > len) + length = len; + + memcpy(buf, fm_wcn_ops.rx_buf, length); + + return length; +} + +static int drv_spi_hopping(void) +{ + struct fm_spi_interface *si = &fm_wcn_ops.si; + int ret = 0, i = 0; + unsigned int val = 0; + + if (si->set_own && !si->set_own()) { + WCN_DBG(FM_ERR | CHIP, "set_own fail\n"); + return -1; + } + + /* enable 'rf_spi_div_en' */ + drv_host_read(si, 0x18001A00, &val); + drv_host_write(si, 0x18001A00, val | (0x1 << 28)); + + /* lock 64M */ + drv_host_read(si, 0x18003004, &val); + drv_host_write(si, 0x18003004, val | (0x1 << 15)); + + /*rd 0x18001810 until D1 == 1*/ + for (i = 0; i < 100; i++) { + drv_host_read(si, 0x18001810, &val); + if (val & 0x00000002) { + WCN_DBG(FM_NTC | CHIP, + "%s: POLLING PLL_RDY success !\n", __func__); + /* switch SPI clock to 64MHz */ + if (conninfra_spi_clock_switch(CONNSYS_SPI_SPEED_64M) == -1) { + WCN_DBG(FM_ERR | CHIP, + "conninfra clock switch 64M fail.\n"); + ret = -1; + } + break; + } + fm_delayus(10); + } + + if (i == 100) { + ret = -1; + WCN_DBG(FM_ERR | CHIP, + "%s: Polling to read rd 0x18001810[1] ==0x1 failed !\n", + __func__); + } + + if (si->clr_own) + si->clr_own(); + + return ret; +} + +static void drv_enable_eint(void) +{ + struct fm_ext_interface *ei = &fm_wcn_ops.ei; + + enable_irq(ei->irq_id); +} + +static void drv_disable_eint(void) +{ + struct fm_ext_interface *ei = &fm_wcn_ops.ei; + + disable_irq_nosync(ei->irq_id); +} + +static void drv_eint_handler(void) +{ + struct fm_spi_interface *si = &fm_wcn_ops.si; + unsigned short main_isr; + + if (si->set_own && !si->set_own()) { + WCN_DBG(FM_ERR | CHIP, "set_own fail\n"); + return; + } + + fw_spi_read(FM_MAIN_INTR, &main_isr); + main_isr &= FM_INTR_MASK; + + WCN_DBG(FM_NTC | CHIP, "interrupt[%04x]\n", main_isr); + + if (main_isr & FM_INTR_STC_DONE) + fm_stc_done_rechandler(); + + if (main_isr & FM_INTR_RDS) + fm_fifo_rechandler(main_isr); + + fw_spi_write(FM_MAIN_INTR, main_isr); + + if (si->clr_own) + si->clr_own(); +} + +static int drv_interface_init(void) +{ + struct fm_spi_interface *interface = &fm_wcn_ops.si; + struct fm_wcn_reg_info *info = &interface->info; + + info->spi_phy_addr = TOP_RF_SPI_AON_ADDR; + info->spi_size = TOP_RF_SPI_AON_SIZE; + request_mem_region(info->spi_phy_addr, info->spi_size, "FM_SPI"); + info->spi_vir_addr = ioremap_nocache( + info->spi_phy_addr, info->spi_size); + if (info->spi_vir_addr == NULL) { + WCN_DBG(FM_ERR | CHIP, "Cannot remap address.\n"); + return -1; + } + + info->top_phy_addr = TOP_MISC_OFF_ADDR; + info->top_size = TOP_MISC_OFF_SIZE; + request_mem_region(info->top_phy_addr, info->top_size, "FM_TOP"); + info->top_vir_addr = ioremap_nocache( + info->top_phy_addr, info->top_size); + if (info->top_vir_addr == NULL) { + WCN_DBG(FM_ERR | CHIP, "Cannot remap address.\n"); + return -1; + } + + info->mcu_phy_addr = MCU_CFG_ADDR; + info->mcu_size = MCU_CFG_SIZE; + request_mem_region(info->mcu_phy_addr, info->mcu_size, "FM_MCU"); + info->mcu_vir_addr = ioremap_nocache( + info->mcu_phy_addr, info->mcu_size); + if (info->mcu_vir_addr == NULL) { + WCN_DBG(FM_ERR | CHIP, "Cannot remap address.\n"); + return -1; + } + + interface->spi_read = drv_spi_read; + interface->spi_write = drv_spi_write; + interface->host_read = drv_host_read; + interface->host_write = drv_host_write; +#if CFG_FM_CONNAC2 + interface->sys_spi_read = drv_sys_spi_read; + interface->sys_spi_write = drv_sys_spi_write; + interface->set_own = drv_set_own; + interface->clr_own = drv_clr_own; +#else + interface->sys_spi_read = fm_sys_spi_read; + interface->sys_spi_write = fm_sys_spi_write; + interface->set_own = NULL; + interface->clr_own = NULL; +#endif + + return 0; +} + +static int drv_interface_uninit(void) +{ + struct fm_spi_interface *interface = &fm_wcn_ops.si; + struct fm_wcn_reg_info *info = &interface->info; + + if (info->spi_vir_addr) { + iounmap(info->spi_vir_addr); + release_mem_region(info->spi_phy_addr, info->spi_size); + } + + if (info->top_vir_addr) { + iounmap(info->top_vir_addr); + release_mem_region(info->top_phy_addr, info->top_size); + } + + if (info->mcu_vir_addr) { + iounmap(info->mcu_vir_addr); + release_mem_region(info->mcu_phy_addr, info->mcu_size); + } + return 0; +} + +static int drv_get_hw_version(void) +{ + return FM_CONNAC_2_1; +} + +static unsigned char drv_get_top_index(void) +{ + return SYS_SPI_TOP; +} + +static unsigned int drv_get_get_adie(void) +{ + return 0x6635; +} + +#if CFG_FM_CONNAC2 + +static int fm_conninfra_stp_register_event_cb(void *cb) +{ + fm_wcn_ops.ei.eint_cb = (void (*)(void))cb; + return 0; +} + +static int fm_conninfra_msgcb_reg(void *data) +{ + /* get whole chip reset cb */ + whole_chip_reset = data; + return conninfra_sub_drv_ops_register( + CONNDRV_TYPE_FM, &fm_drv_cbs); +} + +static int fm_conninfra_func_on(void) +{ + struct fm_spi_interface *si = &fm_wcn_ops.si; + int ret = 0; + + ret = conninfra_pwr_on(CONNDRV_TYPE_FM); + if (ret == -1) { + WCN_DBG(FM_ERR | CHIP, "conninfra power on fail.\n"); + return 0; + } + + if (si->set_own && !si->set_own()) { + WCN_DBG(FM_ERR | CHIP, "set_own fail\n"); + return 0; + } + + ret = conninfra_adie_top_ck_en_on(CONNSYS_ADIE_CTL_HOST_FM); + + if (si->clr_own) + si->clr_own(); + + if (ret == -1) { + WCN_DBG(FM_ERR | CHIP, "top ck en fail.\n"); + return 0; + } + + return 1; +} + +static int fm_conninfra_func_off(void) +{ + struct fm_spi_interface *si = &fm_wcn_ops.si; + int ret = 0; + + if (si->set_own && !si->set_own()) { + WCN_DBG(FM_ERR | CHIP, "set_own fail\n"); + return 0; + } + + ret = conninfra_adie_top_ck_en_off(CONNSYS_ADIE_CTL_HOST_FM); + + if (si->clr_own) + si->clr_own(); + + if (ret == -1) { + WCN_DBG(FM_ERR | CHIP, "top ck en off fail.\n"); + return 0; + } + + ret = conninfra_pwr_off(CONNDRV_TYPE_FM); + if (ret == -1) { + WCN_DBG(FM_ERR | CHIP, "conninfra power off fail.\n"); + return 0; + } + + return 1; +} + +static int fm_conninfra_chipid_query(void) +{ +#ifdef CFG_FM_CHIP_ID + return CFG_FM_CHIP_ID; +#else + return 0; +#endif +} + +static int fm_conninfra_spi_clock_switch(enum fm_spi_speed speed) +{ + struct fm_spi_interface *si = &fm_wcn_ops.si; + enum connsys_spi_speed_type sp_type = CONNSYS_SPI_SPEED_26M; + int ret = 0; + + if (si->set_own && !si->set_own()) { + WCN_DBG(FM_ERR | CHIP, "set_own fail\n"); + return -2; + } + + switch (speed) { + case FM_SPI_SPEED_26M: + sp_type = CONNSYS_SPI_SPEED_26M; + break; + case FM_SPI_SPEED_64M: + sp_type = CONNSYS_SPI_SPEED_64M; + break; + default: + break; + } + + ret = conninfra_spi_clock_switch(sp_type); + + if (si->clr_own) + si->clr_own(); + + if (ret == -1) { + WCN_DBG(FM_ERR | CHIP, "conninfra clock switch fail.\n"); + return -1; + } + + return 0; +} + +static bool fm_conninfra_is_bus_hang(void) +{ + int ret = 0; + + if (conninfra_reg_readable()) + return false; + + /* Check conninfra bus before accessing BGF's CR */ + ret = conninfra_is_bus_hang(); + if (ret > 0) { + WCN_DBG(FM_ERR | CHIP, "conninfra bus is hang[0x%x]\n", ret); + conninfra_trigger_whole_chip_rst(CONNDRV_TYPE_FM, "bus hang"); + return true; + } + + WCN_DBG(FM_ERR | CHIP, + "conninfra not readable, but not bus hang ret = %d", ret); + + return false; +} + +#else /* CFG_FM_CONNAC2 */ + + +static int fm_stp_register_event_cb(void *cb) +{ + fm_wcn_ops.ei.eint_cb = (void (*)(void))cb; + return mtk_wcn_stp_register_event_cb(FM_TASK_INDX, cb); +} + +static int fm_wmt_msgcb_reg(void *data) +{ + /* get whole chip reset cb */ + return 0; +} + +static int fm_wmt_func_on(void) +{ + return mtk_wcn_wmt_func_on(WMTDRV_TYPE_FM) != MTK_WCN_BOOL_FALSE; +} + +static int fm_wmt_func_off(void) +{ + return mtk_wcn_wmt_func_off(WMTDRV_TYPE_FM) != MTK_WCN_BOOL_FALSE; +} + +static unsigned int fm_wmt_ic_info_get(void) +{ + return mtk_wcn_wmt_ic_info_get(1); +} + +static int fm_wmt_chipid_query(void) +{ + return mtk_wcn_wmt_chipid_query(); +} + +static int fm_wmt_spi_clock_switch(enum fm_spi_speed speed) +{ + struct fm_spi_interface *si = &fm_wcn_ops.si; + unsigned int reg_val = 0; + + switch (speed) { + case FM_SPI_SPEED_26M: + si->host_read(si, 0x18004004, ®_val); + reg_val &= 0xFFFFFFFE; + si->host_write(si, 0x18004004, reg_val); + break; + case FM_SPI_SPEED_64M: + si->host_read(si, 0x18004004, ®_val); + reg_val |= 0x00000001; + si->host_write(si, 0x18004004, reg_val); + break; + default: + break; + } + + return 0; +} +#endif /* CFG_FM_CONNAC2 */ + +static irqreturn_t fm_isr(int irq, void *dev) +{ + struct fm_ext_interface *ei = &fm_wcn_ops.ei; + + if (!ei->eint_cb) { + WCN_DBG(FM_WAR | CHIP, "fm eint cb is NULL\n"); + return IRQ_NONE; + } + + if (ei->disable_eint) + ei->disable_eint(); + + ei->eint_cb(); + + return IRQ_HANDLED; +} + +int fm_register_irq(struct platform_driver *drv) +{ +#ifdef CONFIG_OF + struct device_node *node = NULL; +#endif + struct fm_ext_interface *ei = &fm_wcn_ops.ei; + int ret = 0; + + ei->drv = drv; + ei->irq_id = FM_IRQ_NUMBER; +#ifdef CONFIG_OF + node = of_find_compatible_node(NULL, NULL, "mediatek,fm"); + if (node) + ei->irq_id = irq_of_parse_and_map(node, 0); + else + WCN_DBG(FM_ERR | CHIP, "get fm dts node fail\n"); +#endif + WCN_DBG(FM_NTC | CHIP, "request_irq num(%d)\n", ei->irq_id); + ret = request_irq(ei->irq_id, fm_isr, IRQF_SHARED, FM_NAME, drv); + if (ret != 0) + WCN_DBG(FM_ERR | CHIP, "request_irq ERROR(%d)\n", ret); + + return ret; +} + +static void register_drv_ops_init(void) +{ + struct fm_ext_interface *ei = &fm_wcn_ops.ei; + + drv_interface_init(); + ei->eint_handler = drv_eint_handler; + ei->stp_send_data = drv_stp_send_data; + ei->stp_recv_data = drv_stp_recv_data; + ei->get_hw_version = drv_get_hw_version; + ei->get_top_index = drv_get_top_index; + ei->get_get_adie = drv_get_get_adie; + +#if CFG_FM_CONNAC2 + ei->enable_eint = drv_enable_eint; + ei->disable_eint = drv_disable_eint; + ei->stp_register_event_cb = fm_conninfra_stp_register_event_cb; + ei->wmt_msgcb_reg = fm_conninfra_msgcb_reg; + ei->wmt_func_on = fm_conninfra_func_on; + ei->wmt_func_off = fm_conninfra_func_off; + ei->wmt_ic_info_get = NULL; + ei->wmt_chipid_query = fm_conninfra_chipid_query; + ei->spi_clock_switch = fm_conninfra_spi_clock_switch; + ei->is_bus_hang = fm_conninfra_is_bus_hang; + ei->spi_hopping = drv_spi_hopping; +#else + ei->enable_eint = NULL; + ei->disable_eint = NULL; + ei->stp_register_event_cb = fm_stp_register_event_cb; + ei->wmt_msgcb_reg = fm_wmt_msgcb_reg; + ei->wmt_func_on = fm_wmt_func_on; + ei->wmt_func_off = fm_wmt_func_off; + ei->wmt_ic_info_get = fm_wmt_ic_info_get; + ei->wmt_chipid_query = fm_wmt_chipid_query; + ei->spi_clock_switch = fm_wmt_spi_clock_switch; + ei->is_bus_hang = NULL; + ei->spi_hopping = NULL; +#endif + ei->low_ops_register = mt6635_fm_low_ops_register; + ei->rds_ops_unregister = mt6635_fm_rds_ops_unregister; + ei->rds_ops_register = mt6635_fm_rds_ops_register; + ei->rds_ops_unregister = mt6635_fm_rds_ops_unregister; +} + +static void register_drv_ops_uninit(void) +{ + struct fm_ext_interface *ei = &fm_wcn_ops.ei; + + if (ei->irq_id) + free_irq(ei->irq_id, ei->drv); + drv_interface_uninit(); + fm_memset(&fm_wcn_ops, 0, sizeof(struct fm_wcn_reg_ops)); +} + +int fm_wcn_ops_register(void) +{ + register_drv_ops_init(); + return 0; +} + +int fm_wcn_ops_unregister(void) +{ + register_drv_ops_uninit(); + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/fmradio/plat/inc/plat.h b/drivers/misc/mediatek/connectivity/fmradio/plat/inc/plat.h new file mode 100644 index 0000000000000..3e65ef7c4e612 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/plat/inc/plat.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef FM_PLAT_H +#define FM_PLAT_H + +#include +#include +#include +#include +#include +#include +#include + +#include "fm_typedef.h" +#include "fm_dbg.h" +#include "fm_err.h" +#include "fm_stdlib.h" +#include "fm_link.h" +#include "fm_utils.h" +#include "fm_rds.h" +#include "fm_ext_api.h" +#include "fm_reg_utils.h" +#include "fm_main.h" + +#if CFG_FM_CONNAC2 + +#include "conninfra.h" + +#else /* CFG_FM_CONNAC2 */ + +#include "osal_typedef.h" +#include "stp_exp.h" +#include "wmt_exp.h" + +enum { + SYS_SPI_WF1 = 0x00, + SYS_SPI_WF = 0x01, + SYS_SPI_BT = 0x02, + SYS_SPI_FM = 0x03, + SYS_SPI_GPS = 0x04, + SYS_SPI_TOP = 0x05, + SYS_SPI_WF2 = 0x06, + SYS_SPI_WF3 = 0x07, + SYS_SPI_MAX +}; + +#endif /* CFG_FM_CONNAC2 */ + +enum { + FM_SYS_SPI_OK = 0, + FM_SYS_SPI_BUSY, + FM_SYS_SPI_ERR +}; + +enum { + FM_CONNAC_LEGACY = 0, + FM_CONNAC_1_0, + FM_CONNAC_1_2, + FM_CONNAC_1_5, + FM_CONNAC_2_0, + FM_CONNAC_2_1, + FM_CONNAC_UNKNOWN +}; + +extern signed int fm_rds_parser( + struct rds_rx_t *rds_raw, signed int rds_size); + +extern signed int mt6631_fm_low_ops_register( + struct fm_callback *cb, struct fm_basic_interface *bi); +extern signed int mt6631_fm_low_ops_unregister( + struct fm_basic_interface *bi); +extern signed int mt6631_fm_rds_ops_register( + struct fm_basic_interface *bi, struct fm_rds_interface *ri); +extern signed int mt6631_fm_rds_ops_unregister( + struct fm_rds_interface *ri); +extern signed int mt6635_fm_low_ops_register( + struct fm_callback *cb, struct fm_basic_interface *bi); +extern signed int mt6635_fm_low_ops_unregister( + struct fm_basic_interface *bi); +extern signed int mt6635_fm_rds_ops_register( + struct fm_basic_interface *bi, struct fm_rds_interface *ri); +extern signed int mt6635_fm_rds_ops_unregister( + struct fm_rds_interface *ri); + +#endif /* FM_PLAT_H */ diff --git a/drivers/misc/mediatek/connectivity/fmradio/plat/legacy_wmt.c b/drivers/misc/mediatek/connectivity/fmradio/plat/legacy_wmt.c new file mode 100644 index 0000000000000..9a0a3cfb83c54 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/fmradio/plat/legacy_wmt.c @@ -0,0 +1,423 @@ +/* + * Copyright (C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include "plat.h" + +#include "fm_cmd.h" + +static int (*whole_chip_reset)(signed int sta); + +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)) { + /*message format invalid */ + WCN_DBG(FM_WAR | LINK, "message format invalid!\n"); + return; + } + + 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 (whole_chip_reset) + whole_chip_reset(1); + } else if (rst_msg == WMTRSTMSG_RESET_END_FAIL) { + WCN_DBG(FM_WAR | LINK, "FM restart end fail!\n"); + if (whole_chip_reset) + whole_chip_reset(2); + } else if (rst_msg == WMTRSTMSG_RESET_END) { + WCN_DBG(FM_WAR | LINK, "FM restart end!\n"); + if (whole_chip_reset) + whole_chip_reset(0); + } + } +} + +static void fw_eint_handler(void) +{ + fm_event_parser(fm_rds_parser); +} + +static int fm_stp_send_data(unsigned char *buf, unsigned int len) +{ + return mtk_wcn_stp_send_data(buf, len, FM_TASK_INDX); +} + +static int fm_stp_recv_data(unsigned char *buf, unsigned int len) +{ + return mtk_wcn_stp_receive_data(buf, len, FM_TASK_INDX); +} + +static int fm_stp_register_event_cb(void *cb) +{ + return mtk_wcn_stp_register_event_cb(FM_TASK_INDX, cb); +} + +static int fm_wmt_msgcb_reg(void *data) +{ + /* get whole chip reset cb */ + whole_chip_reset = data; + return mtk_wcn_wmt_msgcb_reg( + WMTDRV_TYPE_FM, WCNfm_wholechip_rst_cb); +} + +static int fm_wmt_func_on(void) +{ + int ret = 0; + + ret = mtk_wcn_wmt_func_on(WMTDRV_TYPE_FM) != MTK_WCN_BOOL_FALSE; + + return ret; +} + +static int fm_wmt_func_off(void) +{ + int ret = 0; + + ret = mtk_wcn_wmt_func_off(WMTDRV_TYPE_FM) != MTK_WCN_BOOL_FALSE; + + return ret; +} + +static unsigned int fm_wmt_ic_info_get(void) +{ + return mtk_wcn_wmt_ic_info_get(WMTCHIN_HWVER); +} + +static int fm_wmt_chipid_query(void) +{ + return mtk_wcn_wmt_chipid_query(); +} + +static signed int fm_drv_switch_clk_64m(void) +{ + unsigned int val = 0; + int i = 0, ret = 0; + + /* switch SPI clock to 64MHz */ + fm_host_reg_read(0x81026004, &val); + /* Set 0x81026004[0] = 0x1 */ + ret = fm_host_reg_write(0x81026004, val | 0x1); + if (ret) { + WCN_DBG(FM_ERR | CHIP, + "Switch SPI clock to 64MHz failed\n"); + return -1; + } + + for (i = 0; i < 100; i++) { + fm_host_reg_read(0x81026004, &val); + if ((val & 0x18) == 0x10) + break; + fm_delayus(10); + } + + if (i == 100) { + WCN_DBG(FM_ERR | CHIP, + "switch_SPI_clock_to_64MHz polling timeout\n"); + return -1; + } + + /* Capture next (with SPI Clock: 64MHz) */ + fm_host_reg_read(0x81026004, &val); + /* Set 0x81026004[2] = 0x1 */ + ret = fm_host_reg_write(0x81026004, val | 0x4); + if (ret) { + WCN_DBG(FM_ERR | CHIP, + "Switch SPI clock to 64MHz failed\n"); + return -1; + } + + return 0; +} + +static signed int fm_drv_switch_clk_26m(void) +{ + unsigned int val = 0; + int i = 0, ret = 0; + + /* Capture next (with SPI Clock: 26MHz) */ + fm_host_reg_read(0x81026004, &val); + /* Set 0x81026004[2] = 0x0 */ + ret = fm_host_reg_write(0x81026004, val & 0xFFFFFFFB); + if (ret) { + WCN_DBG(FM_ERR | CHIP, + "Switch SPI clock to 26MHz failed\n"); + return -1; + } + + /* switch SPI clock to 26MHz */ + fm_host_reg_read(0x81026004, &val); + /* Set 0x81026004[0] = 0x0 */ + ret = fm_host_reg_write(0x81026004, val & 0xFFFFFFFE); + if (ret) { + WCN_DBG(FM_ERR | CHIP, + "Switch SPI clock to 26MHz failed\n"); + return -1; + } + + for (i = 0; i < 100; i++) { + fm_host_reg_read(0x81026004, &val); + if ((val & 0x18) == 0x8) + break; + fm_delayus(10); + } + + if (i == 100) { + WCN_DBG(FM_ERR | CHIP, + "switch_SPI_clock_to_26MHz polling timeout\n"); + return -1; + } + + return 0; +} + +static int fm_drv_spi_clock_switch(enum fm_spi_speed speed) +{ + int ret = 0; + + switch (speed) { + case FM_SPI_SPEED_26M: + ret = fm_drv_switch_clk_26m(); + break; + case FM_SPI_SPEED_64M: + ret = fm_drv_switch_clk_64m(); + break; + default: + ret = -1; + break; + } + + return ret; +} + +static int drv_get_hw_version(void) +{ +#if defined(MT6625_FM) || defined(MT6627_FM) || defined(MT6630_FM) || defined(MT6632_FM) || defined(soc) + return FM_CONNAC_LEGACY; +#else + int id = fm_wmt_chipid_query(); + int ret = FM_CONNAC_UNKNOWN; + + switch (id) { + case 0x6758: + case 0x6759: + case 0x6771: + case 0x6775: + case 0x6797: + ret = FM_CONNAC_LEGACY; + break; + case 0x6765: + case 0x6761: + case 0x3967: + ret = FM_CONNAC_1_0; + break; + case 0x6768: + case 0x6785: + case 0x8168: + ret = FM_CONNAC_1_2; + break; + case 0x6779: + case 0x6873: + case 0x6853: + ret = FM_CONNAC_1_5; + break; + default: + ret = FM_CONNAC_UNKNOWN; + break; + } + + return ret; +#endif +} + +static unsigned char drv_get_top_index(void) +{ + if (drv_get_hw_version() < FM_CONNAC_1_5) + return 4; + return 5; +} + +static unsigned int drv_get_get_adie(void) +{ +#if defined(MT6625_FM) || defined(MT6627_FM) || defined(MT6630_FM) || defined(MT6632_FM) || defined(soc) + return 0; +#elif defined(MT6631_FM) + return 0x6631; +#elif defined(MT6635_FM) + return 0x6635; +#else + return mtk_wcn_wmt_ic_info_get(WMTCHIN_ADIE); +#endif +} + +signed int __weak fm_low_ops_register(struct fm_callback *cb, + struct fm_basic_interface *bi) +{ + WCN_DBG(FM_NTC | CHIP, "default %s\n", __func__); + return -1; +} + +signed int __weak fm_low_ops_unregister(struct fm_basic_interface *bi) +{ + WCN_DBG(FM_NTC | CHIP, "default %s\n", __func__); + return -1; +} + +signed int __weak fm_rds_ops_register(struct fm_basic_interface *bi, + struct fm_rds_interface *ri) +{ + WCN_DBG(FM_NTC | CHIP, "default %s\n", __func__); + return -1; +} + +signed int __weak fm_rds_ops_unregister(struct fm_rds_interface *ri) +{ + WCN_DBG(FM_NTC | CHIP, "default %s\n", __func__); + return -1; +} + +signed int __weak mt6631_fm_low_ops_register( + struct fm_callback *cb, struct fm_basic_interface *bi) +{ + WCN_DBG(FM_NTC | CHIP, "default %s\n", __func__); + return -1; +} + +signed int __weak mt6631_fm_low_ops_unregister(struct fm_basic_interface *bi) +{ + WCN_DBG(FM_NTC | CHIP, "default %s\n", __func__); + return -1; +} + +signed int __weak mt6631_fm_rds_ops_register( + struct fm_basic_interface *bi, struct fm_rds_interface *ri) +{ + WCN_DBG(FM_NTC | CHIP, "default %s\n", __func__); + return -1; +} + +signed int __weak mt6631_fm_rds_ops_unregister(struct fm_rds_interface *ri) +{ + WCN_DBG(FM_NTC | CHIP, "default %s\n", __func__); + return -1; +} +signed int __weak mt6635_fm_low_ops_register( + struct fm_callback *cb, struct fm_basic_interface *bi) +{ + WCN_DBG(FM_NTC | CHIP, "default %s\n", __func__); + return -1; +} + +signed int __weak mt6635_fm_low_ops_unregister(struct fm_basic_interface *bi) +{ + WCN_DBG(FM_NTC | CHIP, "default %s\n", __func__); + return -1; +} + +signed int __weak mt6635_fm_rds_ops_register( + struct fm_basic_interface *bi, struct fm_rds_interface *ri) +{ + WCN_DBG(FM_NTC | CHIP, "default %s\n", __func__); + return -1; +} + +signed int __weak mt6635_fm_rds_ops_unregister(struct fm_rds_interface *ri) +{ + WCN_DBG(FM_NTC | CHIP, "default %s\n", __func__); + return -1; +} + +void register_fw_ops_init(void) +{ + struct fm_ext_interface *ei = &fm_wcn_ops.ei; + unsigned int adie = drv_get_get_adie(); + + ei->eint_handler = fw_eint_handler; + ei->stp_send_data = fm_stp_send_data; + ei->stp_recv_data = fm_stp_recv_data; + ei->stp_register_event_cb = fm_stp_register_event_cb; + ei->wmt_msgcb_reg = fm_wmt_msgcb_reg; + ei->wmt_func_on = fm_wmt_func_on; + ei->wmt_func_off = fm_wmt_func_off; + ei->wmt_ic_info_get = fm_wmt_ic_info_get; + ei->wmt_chipid_query = fm_wmt_chipid_query; + ei->spi_clock_switch = fm_drv_spi_clock_switch; + ei->get_hw_version = drv_get_hw_version; + ei->get_top_index = drv_get_top_index; + ei->get_get_adie = drv_get_get_adie; + + WCN_DBG(FM_NTC | CHIP, "adie=0x%x\n", adie); + + if (adie == 0x6631) { + ei->low_ops_register = mt6631_fm_low_ops_register; + ei->low_ops_unregister = mt6631_fm_low_ops_unregister; + ei->rds_ops_register = mt6631_fm_rds_ops_register; + ei->rds_ops_unregister = mt6631_fm_rds_ops_unregister; + } else if (adie == 0x6635) { + ei->low_ops_register = mt6635_fm_low_ops_register; + ei->low_ops_unregister = mt6635_fm_low_ops_unregister; + ei->rds_ops_register = mt6635_fm_rds_ops_register; + ei->rds_ops_unregister = mt6635_fm_rds_ops_unregister; + } else { +#if defined(MT6631_FM) + ei->low_ops_register = mt6631_fm_low_ops_register; + ei->low_ops_unregister = mt6631_fm_low_ops_unregister; + ei->rds_ops_register = mt6631_fm_rds_ops_register; + ei->rds_ops_unregister = mt6631_fm_rds_ops_unregister; +#elif defined(MT6635_FM) + ei->low_ops_register = mt6635_fm_low_ops_register; + ei->low_ops_unregister = mt6635_fm_low_ops_unregister; + ei->rds_ops_register = mt6635_fm_rds_ops_register; + ei->rds_ops_unregister = mt6635_fm_rds_ops_unregister; +#else + ei->low_ops_register = fm_low_ops_register; + ei->low_ops_unregister = fm_low_ops_unregister; + ei->rds_ops_register = fm_rds_ops_register; + ei->rds_ops_unregister = fm_rds_ops_unregister; +#endif + } +} + +void register_fw_ops_uninit(void) +{ +} + +int fm_register_irq(struct platform_driver *drv) +{ + return 0; +} + +int fm_wcn_ops_register(void) +{ + register_fw_ops_init(); + + return 0; +} + +int fm_wcn_ops_unregister(void) +{ + register_fw_ops_uninit(); + + return 0; +} From 76c56eddb9413b1390b4e2cf6ed1c7a6520e354e Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 21:48:45 +0800 Subject: [PATCH 11/32] Add files via upload --- .../mediatek/connectivity/common/Android.mk | 37 + .../mediatek/connectivity/common/Makefile | 301 + .../misc/mediatek/connectivity/common/README | 2 + .../drv_init/bluetooth_drv_init.c | 43 + .../common_detect/drv_init/common_drv_init.c | 59 + .../common_detect/drv_init/conn_drv_init.c | 70 + .../common_detect/drv_init/fm_drv_init.c | 41 + .../common_detect/drv_init/gps_drv_init.c | 43 + .../drv_init/inc/bluetooth_drv_init.h | 20 + .../drv_init/inc/common_drv_init.h | 25 + .../drv_init/inc/conn_drv_init.h | 18 + .../common_detect/drv_init/inc/fm_drv_init.h | 20 + .../common_detect/drv_init/inc/gps_drv_init.h | 19 + .../drv_init/inc/wlan_drv_init.h | 29 + .../common_detect/drv_init/wlan_drv_init.c | 89 + .../common/common_detect/mtk_wcn_stub_alps.c | 621 +++ .../common/common_detect/sdio_detect.c | 249 + .../common/common_detect/sdio_detect.h | 36 + .../common/common_detect/wmt_detect.c | 407 ++ .../common/common_detect/wmt_detect.h | 120 + .../common/common_detect/wmt_detect_pwr.c | 259 + .../common/common_detect/wmt_detect_pwr.h | 29 + .../common/common_detect/wmt_gpio.c | 496 ++ .../common/common_detect/wmt_gpio.h | 127 + .../common/common_main/core/btm_core.c | 779 +++ .../common_main/core/include/btm_core.h | 154 + .../common_main/core/include/dbg_core.h | 75 + .../common_main/core/include/psm_core.h | 275 + .../common_main/core/include/stp_core.h | 699 +++ .../common/common_main/core/include/stp_wmt.h | 99 + .../common_main/core/include/wmt_conf.h | 85 + .../common_main/core/include/wmt_core.h | 585 ++ .../common_main/core/include/wmt_ctrl.h | 144 + .../common_main/core/include/wmt_func.h | 169 + .../common/common_main/core/include/wmt_ic.h | 127 + .../common/common_main/core/include/wmt_lib.h | 493 ++ .../common/common_main/core/psm_core.c | 2080 +++++++ .../common/common_main/core/stp_core.c | 3588 ++++++++++++ .../common/common_main/core/stp_exp.c | 374 ++ .../common/common_main/core/wmt_conf.c | 695 +++ .../common/common_main/core/wmt_core.c | 3797 +++++++++++++ .../common/common_main/core/wmt_ctrl.c | 1197 ++++ .../common/common_main/core/wmt_exp.c | 876 +++ .../common/common_main/core/wmt_func.c | 838 +++ .../common/common_main/core/wmt_ic_6620.c | 1909 +++++++ .../common/common_main/core/wmt_ic_6628.c | 1981 +++++++ .../common/common_main/core/wmt_ic_6630.c | 2043 +++++++ .../common/common_main/core/wmt_ic_6632.c | 1989 +++++++ .../common/common_main/core/wmt_ic_soc.c | 4062 ++++++++++++++ .../common/common_main/core/wmt_lib.c | 3382 +++++++++++ .../common_main/include/mtk_wcn_cmb_hw.h | 99 + .../common/common_main/include/stp_exp.h | 317 ++ .../common/common_main/include/wmt.h | 18 + .../common/common_main/include/wmt_exp.h | 450 ++ .../common/common_main/include/wmt_plat.h | 404 ++ .../common_main/include/wmt_plat_stub.h | 23 + .../common/common_main/linux/bgw_desense.c | 141 + .../common/common_main/linux/fw_log_wmt.c | 199 + .../common/common_main/linux/hif_sdio.c | 2924 ++++++++++ .../common_main/linux/include/bgw_desense.h | 73 + .../common_main/linux/include/fw_log_wmt.h | 23 + .../common_main/linux/include/hif_sdio.h | 371 ++ .../common/common_main/linux/include/osal.h | 443 ++ .../common_main/linux/include/osal_typedef.h | 81 + .../common_main/linux/include/stp_btif.h | 39 + .../common_main/linux/include/stp_dbg.h | 424 ++ .../common_main/linux/include/stp_dbg_combo.h | 23 + .../common_main/linux/include/stp_dbg_soc.h | 28 + .../common_main/linux/include/stp_sdio.h | 322 ++ .../common_main/linux/include/wmt_alarm.h | 15 + .../common_main/linux/include/wmt_dbg.h | 66 + .../common_main/linux/include/wmt_dev.h | 49 + .../common_main/linux/include/wmt_idc.h | 112 + .../common_main/linux/include/wmt_proc_dbg.h | 26 + .../common_main/linux/include/wmt_step.h | 373 ++ .../common_main/linux/include/wmt_user_proc.h | 14 + .../common/common_main/linux/osal.c | 1803 ++++++ .../common/common_main/linux/stp_btif.c | 304 + .../common/common_main/linux/stp_dbg.c | 2902 ++++++++++ .../common/common_main/linux/stp_dbg_combo.c | 196 + .../common/common_main/linux/stp_dbg_soc.c | 577 ++ .../common/common_main/linux/stp_sdio.c | 3584 ++++++++++++ .../common/common_main/linux/stp_uart.c | 843 +++ .../common/common_main/linux/wmt_alarm.c | 150 + .../common/common_main/linux/wmt_dbg.c | 1627 ++++++ .../common/common_main/linux/wmt_dev.c | 1779 ++++++ .../common/common_main/linux/wmt_idc.c | 318 ++ .../common/common_main/linux/wmt_proc_dbg.c | 299 + .../common/common_main/linux/wmt_step.c | 2433 ++++++++ .../common/common_main/linux/wmt_user_proc.c | 194 + .../platform/include/mtk_wcn_consys_hw.h | 418 ++ .../common_main/platform/mtk_wcn_cmb_hw.c | 340 ++ .../common_main/platform/mtk_wcn_consys_hw.c | 1237 ++++ .../common_main/platform/wmt_plat_alps.c | 1851 ++++++ .../common_main/platform/wmt_plat_stub.c | 120 + .../connectivity/common/init.wmt_drv.rc | 2 + .../common/test/include/wmt_step_test.h | 77 + .../connectivity/common/test/wmt_step_test.c | 4966 +++++++++++++++++ 98 files changed, 68732 insertions(+) create mode 100644 drivers/misc/mediatek/connectivity/common/Android.mk create mode 100644 drivers/misc/mediatek/connectivity/common/Makefile create mode 100644 drivers/misc/mediatek/connectivity/common/README create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/bluetooth_drv_init.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/common_drv_init.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/conn_drv_init.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/fm_drv_init.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/gps_drv_init.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/bluetooth_drv_init.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/common_drv_init.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/conn_drv_init.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/fm_drv_init.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/gps_drv_init.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/wlan_drv_init.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/wlan_drv_init.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/mtk_wcn_stub_alps.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/sdio_detect.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/sdio_detect.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect_pwr.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect_pwr.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/wmt_gpio.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/wmt_gpio.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/core/btm_core.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/core/include/btm_core.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/core/include/dbg_core.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/core/include/psm_core.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/core/include/stp_core.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/core/include/stp_wmt.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/core/include/wmt_conf.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/core/include/wmt_core.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/core/include/wmt_ctrl.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/core/include/wmt_func.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/core/include/wmt_ic.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/core/include/wmt_lib.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/core/psm_core.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/core/stp_core.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/core/stp_exp.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/core/wmt_conf.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/core/wmt_core.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/core/wmt_ctrl.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/core/wmt_exp.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/core/wmt_func.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/core/wmt_ic_6620.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/core/wmt_ic_6628.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/core/wmt_ic_6630.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/core/wmt_ic_6632.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/core/wmt_ic_soc.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/core/wmt_lib.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/include/mtk_wcn_cmb_hw.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/include/stp_exp.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/include/wmt.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/include/wmt_exp.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/include/wmt_plat.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/include/wmt_plat_stub.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/bgw_desense.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/fw_log_wmt.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/hif_sdio.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/include/bgw_desense.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/include/fw_log_wmt.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/include/hif_sdio.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/include/osal.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/include/osal_typedef.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/include/stp_btif.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/include/stp_dbg.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/include/stp_dbg_combo.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/include/stp_dbg_soc.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/include/stp_sdio.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_alarm.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_dbg.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_dev.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_idc.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_proc_dbg.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_step.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_user_proc.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/osal.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/stp_btif.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/stp_dbg.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/stp_dbg_combo.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/stp_dbg_soc.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/stp_sdio.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/stp_uart.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_alarm.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_dbg.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_dev.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_idc.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_proc_dbg.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_step.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_user_proc.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/platform/include/mtk_wcn_consys_hw.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/platform/mtk_wcn_cmb_hw.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/platform/mtk_wcn_consys_hw.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/platform/wmt_plat_alps.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_main/platform/wmt_plat_stub.c create mode 100644 drivers/misc/mediatek/connectivity/common/init.wmt_drv.rc create mode 100644 drivers/misc/mediatek/connectivity/common/test/include/wmt_step_test.h create mode 100644 drivers/misc/mediatek/connectivity/common/test/wmt_step_test.c diff --git a/drivers/misc/mediatek/connectivity/common/Android.mk b/drivers/misc/mediatek/connectivity/common/Android.mk new file mode 100644 index 0000000000000..2a74dafede554 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/Android.mk @@ -0,0 +1,37 @@ +LOCAL_PATH := $(call my-dir) + +ifneq ($(filter yes,$(sort $(MTK_WLAN_SUPPORT) $(MTK_BT_SUPPORT) $(MTK_GPS_SUPPORT) $(MTK_FM_SUPPORT))),) +WLAN_MT76XX_CHIPS := MT7668 MT7663 + +ifeq ($(filter $(WLAN_MT76XX_CHIPS), $(MTK_COMBO_CHIP)),) +ifneq (true,$(strip $(TARGET_NO_KERNEL))) +ifneq ($(filter yes,$(MTK_COMBO_SUPPORT)),) + +include $(CLEAR_VARS) +LOCAL_MODULE := wmt_drv.ko +LOCAL_PROPRIETARY_MODULE := true +LOCAL_MODULE_OWNER := mtk + +LOCAL_INIT_RC := init.wmt_drv.rc +LOCAL_SRC_FILES := $(patsubst $(LOCAL_PATH)/%,%,$(shell find $(LOCAL_PATH) -type f -name '*.[cho]')) Makefile +LOCAL_REQUIRED_MODULES := + +include $(MTK_KERNEL_MODULE) + +WMT_OPTS := MTK_CONSYS_ADIE=$(MTK_CONSYS_ADIE) +WMT_OPTS += MTK_PLATFORM_WMT=$(MTK_PLATFORM) +WMT_OPTS += TARGET_BOARD_PLATFORM_WMT=$(TARGET_BOARD_PLATFORM) + +$(linked_module): OPTS += $(WMT_OPTS) + +else + $(warning wmt_drv-MTK_COMBO_SUPPORT: [$(MTK_COMBO_SUPPORT)]) +endif +endif + +else +# MT76XX +$(warning skip wmt_drv) +$(warning wmt_drv-MTK_COMBO_CHIP: [$(MTK_COMBO_CHIP)]) +endif +endif diff --git a/drivers/misc/mediatek/connectivity/common/Makefile b/drivers/misc/mediatek/connectivity/common/Makefile new file mode 100644 index 0000000000000..84095c0b75dfa --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/Makefile @@ -0,0 +1,301 @@ +ifeq ($(MTK_PLATFORM),) +ifneq ($(MTK_PLATFORM_WMT),) +MTK_PLATFORM := $(shell echo $(MTK_PLATFORM_WMT) | tr A-Z a-z) +endif +endif + +ifeq ($(MTK_PLATFORM),) +ifneq ($(CONFIG_MTK_PLATFORM),) +MTK_PLATFORM := $(subst ",,$(CONFIG_MTK_PLATFORM)) +endif +endif + +CONNSYS_PLATFORM := $(TARGET_BOARD_PLATFORM_WMT) +PRIORITY_TABLE_MTK_PLATFORM := mt6735 + +ifeq ($(CONNSYS_PLATFORM),) +CONNSYS_PLATFORM := $(MTK_PLATFORM) +else +ifneq ($(filter $(PRIORITY_TABLE_MTK_PLATFORM), $(MTK_PLATFORM)),) +CONNSYS_PLATFORM := $(MTK_PLATFORM) +endif +endif + +############################################################################### +# Necessary Check + +ifneq ($(CONFIG_MTK_COMBO),) + +ifneq ($(KERNEL_OUT),) + ccflags-y += -imacros $(KERNEL_OUT)/include/generated/autoconf.h +endif + +ifeq ($(CONFIG_MTK_COMBO_CHIP),) + $(error CONFIG_MTK_COMBO_CHIP not defined) +endif + +ifeq ($(TARGET_BUILD_VARIANT),$(filter $(TARGET_BUILD_VARIANT),userdebug user)) + #ldflags-y += -s +endif + +# Force build fail on modpost warning +KBUILD_MODPOST_FAIL_ON_WARNINGS := y +############################################################################### + +#ccflags-y += -D MTK_WCN_REMOVE_KERNEL_MODULE +ifeq ($(CONFIG_ARM64), y) + ccflags-y += -D CONFIG_MTK_WCN_ARM64 +endif + +ifeq ($(CONFIG_MTK_CONN_LTE_IDC_SUPPORT),y) + ccflags-y += -D WMT_IDC_SUPPORT=1 +else + ccflags-y += -D WMT_IDC_SUPPORT=0 +endif +ccflags-y += -D MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include/mach +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/$(MTK_PLATFORM) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include/clkbuf_v1 +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include/clkbuf_v1/$(MTK_PLATFORM) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/btif/common/inc +ifeq ($(strip $(MTK_PLATFORM)), mt6735) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/eccci1 +ccflags-y += -I$(srctree)/drivers/misc/mediatek/eccci1/$(MTK_PLATFORM) +else +ccflags-y += -I$(srctree)/drivers/misc/mediatek/eccci +ccflags-y += -I$(srctree)/drivers/misc/mediatek/eccci/$(MTK_PLATFORM) +endif +ccflags-y += -I$(srctree)/drivers/misc/mediatek/eemcs +ccflags-y += -I$(srctree)/drivers/misc/mediatek/conn_md/include +ccflags-y += -I$(srctree)/drivers/misc/mediatek/mach/$(MTK_PLATFORM)/include/mach +ccflags-y += -I$(srctree)/drivers/misc/mediatek/emi/submodule +ccflags-y += -I$(srctree)/drivers/misc/mediatek/emi/$(MTK_PLATFORM) +ifeq ($(CONFIG_MTK_PMIC_CHIP_MT6359),y) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/pmic/include/mt6359 +endif +ifeq ($(CONFIG_MTK_PMIC_CHIP_MT6359P),y) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/pmic/include/mt6359p +endif +ccflags-y += -I$(srctree)/drivers/mmc/core +ccflags-y += -I$(srctree)/drivers/misc/mediatek/connectivity/common +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat +############################################################################### + + +ccflags-y += -Werror + +ifneq ($(filter "MT6628",$(CONFIG_MTK_COMBO_CHIP)),) + ccflags-y += -D MT6628 + ccflags-y += -D MERGE_INTERFACE_SUPPORT +endif +ifneq ($(filter "MT6630",$(CONFIG_MTK_COMBO_CHIP)),) + ccflags-y += -D MT6630 +ifneq ($(CONFIG_ARCH_MT2601),y) + ccflags-y += -D MERGE_INTERFACE_SUPPORT +endif +endif + +ifneq ($(filter "MT6632",$(CONFIG_MTK_COMBO_CHIP)),) + ccflags-y += -D MT6632 + ccflags-y += -D MERGE_INTERFACE_SUPPORT +endif + +#obj-y += common_main/ +#obj-y += common_detect/ + +ifneq ($(filter MT6631,$(MTK_CONSYS_ADIE)),) + ccflags-y += -D CONSYS_PMIC_CTRL_6635=0 +else + ccflags-y += -D CONSYS_PMIC_CTRL_6635=1 +endif + +############################################################################### +MODULE_NAME := wmt_drv +ifeq ($(CONFIG_WLAN_DRV_BUILD_IN),y) +$(warning $(MODULE_NAME) build-in boot.img) +obj-y += $(MODULE_NAME).o +else +$(warning $(MODULE_NAME) is kernel module) +obj-m += $(MODULE_NAME).o +endif + +############################################################################### +# common_detect +############################################################################### +ccflags-y += -I$(srctree)/arch/arm/mach-$(MTK_PLATFORM)/$(ARCH_MTK_PROJECT)/dct/dct +ccflags-y += -DWMT_PLAT_ALPS=1 + +COMBO_CHIP_SUPPORT := false +ifneq ($(filter "MT6620E3",$(CONFIG_MTK_COMBO_CHIP)),) + COMBO_CHIP_SUPPORT := true +endif +ifneq ($(filter "MT6628",$(CONFIG_MTK_COMBO_CHIP)),) + COMBO_CHIP_SUPPORT := true +endif +ifneq ($(filter "MT6630",$(CONFIG_MTK_COMBO_CHIP)),) + COMBO_CHIP_SUPPORT := true +endif +ifneq ($(filter "MT6632",$(CONFIG_MTK_COMBO_CHIP)),) + COMBO_CHIP_SUPPORT := true +endif +ifeq ($(COMBO_CHIP_SUPPORT), true) + ccflags-y += -D MTK_WCN_COMBO_CHIP_SUPPORT +endif + +ifneq ($(filter "CONSYS_%",$(CONFIG_MTK_COMBO_CHIP)),) + ccflags-y += -D MTK_WCN_SOC_CHIP_SUPPORT +endif + +ccflags-y += -I$(src)/common_main/linux/include +ccflags-y += -I$(src)/common_detect/drv_init/inc +ccflags-y += -I$(src)/common_detect +ccflags-y += -I$(src)/debug_utility + +$(MODULE_NAME)-objs += common_detect/wmt_detect_pwr.o +$(MODULE_NAME)-objs += common_detect/wmt_detect.o +$(MODULE_NAME)-objs += common_detect/sdio_detect.o +$(MODULE_NAME)-objs += common_detect/mtk_wcn_stub_alps.o +$(MODULE_NAME)-objs += common_detect/wmt_gpio.o + + +ifneq ($(filter "MT6630",$(CONFIG_MTK_COMBO_CHIP)),) + ccflags-y += -D MTK_WCN_WLAN_GEN3 +endif + +ifneq ($(filter "MT6632",$(CONFIG_MTK_COMBO_CHIP)),) + ccflags-y += -D MTK_WCN_WLAN_GEN4 +endif + +ifneq ($(filter "CONSYS_6797" "CONSYS_6759" "CONSYS_6758" "CONSYS_6771" "CONSYS_6775",$(CONFIG_MTK_COMBO_CHIP)),) + ccflags-y += -D MTK_WCN_WLAN_GEN3 +else ifneq ($(filter "CONSYS_%",$(CONFIG_MTK_COMBO_CHIP)),) + ccflags-y += -D MTK_WCN_WLAN_GEN2 +endif + +$(MODULE_NAME)-objs += common_detect/drv_init/fm_drv_init.o +$(MODULE_NAME)-objs += common_detect/drv_init/conn_drv_init.o +$(MODULE_NAME)-objs += common_detect/drv_init/bluetooth_drv_init.o +$(MODULE_NAME)-objs += common_detect/drv_init/wlan_drv_init.o +$(MODULE_NAME)-objs += common_detect/drv_init/common_drv_init.o +$(MODULE_NAME)-objs += common_detect/drv_init/gps_drv_init.o + + +############################################################################### +# common_main +############################################################################### +ccflags-y += -I$(src)/common_main/linux/include +ccflags-y += -I$(src)/common_main/linux/pri/include +ccflags-y += -I$(src)/common_main/platform/include +ccflags-y += -I$(src)/common_main/core/include +ccflags-y += -I$(src)/common_main/include + +ccflags-y += -D WMT_PLAT_ALPS=1 +ccflags-y += -D WMT_UART_RX_MODE_WORK=0 # 1. work thread 0. tasklet +ccflags-y += -D WMT_SDIO_MODE=1 +ccflags-y += -D WMT_CREATE_NODE_DYNAMIC=1 + +ifneq ($(TARGET_BUILD_VARIANT),eng) +ifeq ($(CONFIG_EXTREME_LOW_RAM), y) +ccflags-y += -DLOG_STP_DEBUG_DISABLE +endif +endif + +ifneq ($(TARGET_BUILD_VARIANT), user) + ccflags-y += -D WMT_DBG_SUPPORT=1 +else + ccflags-y += -D WMT_DBG_SUPPORT=0 +endif + +ifeq ($(CONFIG_MTK_DEVAPC),y) + ccflags-y += -D WMT_DEVAPC_DBG_SUPPORT=1 +else + ccflags-y += -D WMT_DEVAPC_DBG_SUPPORT=0 +endif + +ifeq ($(CONFIG_ARCH_MT6580), y) +ccflags-y += -D CFG_WMT_READ_EFUSE_VCN33 +endif + +# STEP: (Support Connac) +# MTK eng/userdebug/user load: Support +# Customer eng/userdebug load: Support +# Customer user load: Not support + +ifneq ($(TARGET_BUILD_VARIANT),user) + ccflags-y += -D CFG_WMT_STEP +endif + +ifeq ($(findstring evb, $(MTK_PROJECT)), evb) +ccflags-y += -D CFG_WMT_EVB +endif + +ifneq ($(filter "CONSYS_%",$(CONFIG_MTK_COMBO_CHIP)),) +$(MODULE_NAME)-objs += common_main/platform/$(CONNSYS_PLATFORM).o +endif + +#$(MODULE_NAME)-objs += common_main/platform/wmt_plat_stub.o +$(MODULE_NAME)-objs += common_main/platform/wmt_plat_alps.o +$(MODULE_NAME)-objs += common_main/platform/mtk_wcn_consys_hw.o +$(MODULE_NAME)-objs += common_main/platform/mtk_wcn_cmb_hw.o + +$(MODULE_NAME)-objs += common_main/core/wmt_ic_6628.o +$(MODULE_NAME)-objs += common_main/core/wmt_conf.o +$(MODULE_NAME)-objs += common_main/core/stp_core.o +$(MODULE_NAME)-objs += common_main/core/wmt_ctrl.o +$(MODULE_NAME)-objs += common_main/core/wmt_func.o +$(MODULE_NAME)-objs += common_main/core/wmt_core.o +$(MODULE_NAME)-objs += common_main/core/psm_core.o +$(MODULE_NAME)-objs += common_main/core/wmt_ic_soc.o +$(MODULE_NAME)-objs += common_main/core/wmt_lib.o +$(MODULE_NAME)-objs += common_main/core/wmt_ic_6620.o +$(MODULE_NAME)-objs += common_main/core/stp_exp.o +$(MODULE_NAME)-objs += common_main/core/wmt_ic_6632.o +$(MODULE_NAME)-objs += common_main/core/wmt_exp.o +$(MODULE_NAME)-objs += common_main/core/btm_core.o +$(MODULE_NAME)-objs += common_main/core/wmt_ic_6630.o + +$(MODULE_NAME)-objs += common_main/linux/hif_sdio.o +$(MODULE_NAME)-objs += common_main/linux/stp_dbg_soc.o +$(MODULE_NAME)-objs += common_main/linux/stp_dbg_combo.o +$(MODULE_NAME)-objs += common_main/linux/osal.o +$(MODULE_NAME)-objs += common_main/linux/wmt_dev.o +$(MODULE_NAME)-objs += common_main/linux/stp_sdio.o +$(MODULE_NAME)-objs += common_main/linux/bgw_desense.o +$(MODULE_NAME)-objs += common_main/linux/wmt_idc.o +$(MODULE_NAME)-objs += common_main/linux/stp_uart.o +$(MODULE_NAME)-objs += common_main/linux/wmt_dbg.o +$(MODULE_NAME)-objs += common_main/linux/stp_dbg.o +$(MODULE_NAME)-objs += common_main/linux/wmt_user_proc.o + +$(MODULE_NAME)-objs += common_main/linux/wmt_proc_dbg.o +$(MODULE_NAME)-objs += common_main/linux/wmt_alarm.o + +ifneq ($(CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH),) +$(MODULE_NAME)-objs += common_main/linux/fw_log_wmt.o +endif +$(MODULE_NAME)-objs += common_main/linux/wmt_step.o + +ifeq ($(CONFIG_MTK_BTIF),$(filter $(CONFIG_MTK_BTIF),y m)) +$(MODULE_NAME)-objs += common_main/linux/stp_btif.o +endif + +$(MODULE_NAME)-objs += debug_utility/ring.o +$(MODULE_NAME)-objs += debug_utility/ring_emi.o +$(MODULE_NAME)-objs += debug_utility/connsys_debug_utility.o +############################################################################### +# test +############################################################################### +ifeq ($(TARGET_BUILD_VARIANT),eng) +ccflags-y += -I$(src)/test/include +endif + +ifeq ($(TARGET_BUILD_VARIANT),eng) +$(MODULE_NAME)-objs += test/wmt_step_test.o +endif + +endif diff --git a/drivers/misc/mediatek/connectivity/common/README b/drivers/misc/mediatek/connectivity/common/README new file mode 100644 index 0000000000000..8b3fbca848d9d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/README @@ -0,0 +1,2 @@ +WMT driver - kernel modules move out of kernel tree + diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/bluetooth_drv_init.c b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/bluetooth_drv_init.c new file mode 100644 index 0000000000000..d89d5da4357b6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/bluetooth_drv_init.c @@ -0,0 +1,43 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[BT-MOD-INIT]" + +#include "wmt_detect.h" +#include "bluetooth_drv_init.h" + +#ifdef CONFIG_MTK_COMBO_BT +int __attribute__((weak)) mtk_wcn_stpbt_drv_init() +{ + WMT_DETECT_PR_INFO("Not implement mtk_wcn_stpbt_drv_init\n"); + return 0; +} +#endif + +int do_bluetooth_drv_init(int chip_id) +{ + int i_ret = -1; + +#ifdef CONFIG_MTK_COMBO_BT + WMT_DETECT_PR_INFO("start to do bluetooth driver init\n"); + i_ret = mtk_wcn_stpbt_drv_init(); + WMT_DETECT_PR_INFO("finish bluetooth driver init, i_ret:%d\n", i_ret); +#else + WMT_DETECT_PR_INFO("CONFIG_MTK_COMBO_BT is not defined\n"); +#endif + return i_ret; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/common_drv_init.c b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/common_drv_init.c new file mode 100644 index 0000000000000..e6c64529eaff7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/common_drv_init.c @@ -0,0 +1,59 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-MOD-INIT]" + +#include "wmt_detect.h" +#include "common_drv_init.h" + + +#if (MTK_WCN_REMOVE_KO) +int do_common_drv_init(int chip_id) +{ + int i_ret = 0; + int i_ret_tmp = 0; + + WMT_DETECT_PR_INFO("start to do common driver init, chipid:0x%08x\n", chip_id); + + wmt_detect_set_chip_type(chip_id); + + /* HIF-SDIO driver init */ + i_ret_tmp = mtk_wcn_hif_sdio_drv_init(); + i_ret += i_ret_tmp; + WMT_DETECT_PR_DBG("HIF-SDIO driver init, i_ret:%d\n", i_ret); + + /* WMT driver init */ + i_ret_tmp = mtk_wcn_common_drv_init(); + i_ret += i_ret_tmp; + WMT_DETECT_PR_DBG("COMBO COMMON driver init, i_ret:%d\n", i_ret); + + /* STP-UART driver init */ + i_ret_tmp = mtk_wcn_stp_uart_drv_init(); + i_ret += i_ret_tmp; + WMT_DETECT_PR_DBG("STP-UART driver init, i_ret:%d\n", i_ret); + + /* STP-SDIO driver init */ + i_ret_tmp = mtk_wcn_stp_sdio_drv_init(); + i_ret += i_ret_tmp; + WMT_DETECT_PR_DBG("STP-SDIO driver init, i_ret:%d\n", i_ret); + + WMT_DETECT_PR_INFO("common driver init finish:%d\n", i_ret); + return i_ret; + +} +#endif + diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/conn_drv_init.c b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/conn_drv_init.c new file mode 100644 index 0000000000000..ab03a5b14fe78 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/conn_drv_init.c @@ -0,0 +1,70 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WCN-MOD-INIT]" + +#include "wmt_detect.h" +#include "conn_drv_init.h" +#include "common_drv_init.h" +#include "fm_drv_init.h" +#include "wlan_drv_init.h" +#include "bluetooth_drv_init.h" +#include "gps_drv_init.h" + +#if (MTK_WCN_REMOVE_KO) +int do_connectivity_driver_init(int chip_id) +{ + int i_ret = 0; + int tmp_ret = 0; + static int init_before; + + /* To avoid invoking more than once.*/ + if (init_before) + return 0; + init_before = 1; + + tmp_ret = do_common_drv_init(chip_id); + i_ret += tmp_ret; + if (tmp_ret) { + WMT_DETECT_PR_ERR("do common driver not ready, ret:%d\n abort!\n", tmp_ret); + return i_ret; + } + + tmp_ret = do_bluetooth_drv_init(chip_id); + i_ret += tmp_ret; + if (tmp_ret) + WMT_DETECT_PR_ERR("do common driver init failed, ret:%d\n", tmp_ret); + + tmp_ret = do_gps_drv_init(chip_id); + i_ret += tmp_ret; + if (tmp_ret) + WMT_DETECT_PR_ERR("do common driver init failed, ret:%d\n", tmp_ret); + + tmp_ret = do_fm_drv_init(chip_id); + i_ret += tmp_ret; + if (tmp_ret) + WMT_DETECT_PR_ERR("do fm module init failed, ret:%d\n", tmp_ret); + + tmp_ret = do_wlan_drv_init(chip_id); + i_ret += tmp_ret; + if (tmp_ret) + WMT_DETECT_PR_ERR("do wlan module init failed, ret:%d\n", tmp_ret); + + return i_ret; +} +#endif + diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/fm_drv_init.c b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/fm_drv_init.c new file mode 100644 index 0000000000000..4ec149e77046a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/fm_drv_init.c @@ -0,0 +1,41 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[FM-MOD-INIT]" + +#include "wmt_detect.h" +#include "fm_drv_init.h" + +#ifdef CONFIG_MTK_FMRADIO +int __attribute__((weak)) mtk_wcn_fm_init() +{ + WMT_DETECT_PR_INFO("no impl. mtk_wcn_fm_init\n"); + return 0; +} +#endif + +int do_fm_drv_init(int chip_id) +{ + WMT_DETECT_PR_INFO("start to do fm module init\n"); + +#ifdef CONFIG_MTK_FMRADIO + mtk_wcn_fm_init(); +#endif + + WMT_DETECT_PR_INFO("finish fm module init\n"); + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/gps_drv_init.c b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/gps_drv_init.c new file mode 100644 index 0000000000000..ac48b231a3d0e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/gps_drv_init.c @@ -0,0 +1,43 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[GPS-MOD-INIT]" + +#include "wmt_detect.h" +#include "gps_drv_init.h" + +#ifdef CONFIG_MTK_COMBO_GPS +int __attribute__((weak)) mtk_wcn_stpgps_drv_init() +{ + WMT_DETECT_PR_INFO("no impl. mtk_wcn_stpgps_drv_init\n"); + return 0; +} +#endif + +int do_gps_drv_init(int chip_id) +{ + int i_ret = -1; +#ifdef CONFIG_MTK_COMBO_GPS + WMT_DETECT_PR_INFO("start to do gps driver init\n"); + i_ret = mtk_wcn_stpgps_drv_init(); + WMT_DETECT_PR_INFO("finish gps driver init, i_ret:%d\n", i_ret); +#else + WMT_DETECT_PR_INFO("CONFIG_MTK_COMBO_GPS is not defined\n"); +#endif + return i_ret; + +} diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/bluetooth_drv_init.h b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/bluetooth_drv_init.h new file mode 100644 index 0000000000000..8a847d361fc8c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/bluetooth_drv_init.h @@ -0,0 +1,20 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _BLUETOOTH_DRIVER_INIT_H_ +#define _BLUETOOTH_DRIVER_INIT_H_ + +extern int do_bluetooth_drv_init(int chip_id); +extern int mtk_wcn_stpbt_drv_init(void); +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/common_drv_init.h b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/common_drv_init.h new file mode 100644 index 0000000000000..dae155e1d4039 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/common_drv_init.h @@ -0,0 +1,25 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _COMMON_DRV_INIT_H_ +#define _COMMON_DRV_INIT_H_ +extern int do_common_drv_init(int chip_id); + +extern int mtk_wcn_common_drv_init(void); +extern int mtk_wcn_hif_sdio_drv_init(void); +extern int mtk_wcn_stp_uart_drv_init(void); +extern int mtk_wcn_stp_sdio_drv_init(void); + + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/conn_drv_init.h b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/conn_drv_init.h new file mode 100644 index 0000000000000..971193eade9e9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/conn_drv_init.h @@ -0,0 +1,18 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _CONNECTIVITY_DRV_INIT_H_ +#define _CONNECTIVITY_DRV_INIT_H_ +extern int do_connectivity_driver_init(int chip_id); +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/fm_drv_init.h b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/fm_drv_init.h new file mode 100644 index 0000000000000..f6ea30addc5da --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/fm_drv_init.h @@ -0,0 +1,20 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _FM_DRV_INIT_H_ +#define _FM_DRV_INIT_H_ +extern int do_fm_drv_init(int chip_id); +extern int mtk_wcn_fm_init(void); +extern void mtk_wcn_fm_exit(void); +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/gps_drv_init.h b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/gps_drv_init.h new file mode 100644 index 0000000000000..006ce072c53b6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/gps_drv_init.h @@ -0,0 +1,19 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _GPS_DRIVER_INIT_H_ +#define _GPS_DRIVER_INIT_H_ +extern int do_gps_drv_init(int chip_id); +extern int mtk_wcn_stpgps_drv_init(void); +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/wlan_drv_init.h b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/wlan_drv_init.h new file mode 100644 index 0000000000000..6ed7d4e458d1e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/wlan_drv_init.h @@ -0,0 +1,29 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _WLAN_DRV_INIT_H_ +#define _WLAN_DRV_INIT_H_ + + +extern int do_wlan_drv_init(int chip_id); + +extern int mtk_wcn_wmt_wifi_init(void); + +extern int mtk_wcn_wlan_gen2_init(void); + +extern int mtk_wcn_wlan_gen3_init(void); + +extern int mtk_wcn_wlan_gen4_init(void); + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/wlan_drv_init.c b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/wlan_drv_init.c new file mode 100644 index 0000000000000..7b28ad934f83f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/wlan_drv_init.c @@ -0,0 +1,89 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WLAN-MOD-INIT]" + +#include "wmt_detect.h" +#include "wlan_drv_init.h" + +int __attribute__((weak)) mtk_wcn_wlan_gen4_init() +{ + WMT_DETECT_PR_INFO("no impl. mtk_wcn_wlan_gen4_init\n"); + return 0; +} + +int __attribute__((weak)) mtk_wcn_wlan_gen3_init() +{ + WMT_DETECT_PR_INFO("no impl. mtk_wcn_wlan_gen3_init\n"); + return 0; +} + +int __attribute__((weak)) mtk_wcn_wlan_gen2_init() +{ + WMT_DETECT_PR_INFO("no impl. mtk_wcn_wlan_gen2_init\n"); + return 0; +} + +int __attribute__((weak)) mtk_wcn_wmt_wifi_init() +{ + WMT_DETECT_PR_INFO("no impl. mtk_wcn_wmt_wifi_init\n"); + return 0; +} + +int do_wlan_drv_init(int chip_id) +{ + int i_ret = 0; + int ret = 0; + + WMT_DETECT_PR_INFO("start to do wlan module init 0x%x\n", chip_id); + + /* WMT-WIFI char dev init */ + ret = mtk_wcn_wmt_wifi_init(); + WMT_DETECT_PR_INFO("WMT-WIFI char dev init, ret:%d\n", ret); + i_ret += ret; + + switch (chip_id) { + case 0x6580: + case 0x6739: + ret = mtk_wcn_wlan_gen2_init(); + WMT_DETECT_PR_INFO("WLAN-GEN2 driver init, ret:%d\n", ret); + break; + + case 0x6630: + case 0x6797: + case 0x6758: + case 0x6759: + case 0x6775: + case 0x6771: + /* WLAN driver init */ + ret = mtk_wcn_wlan_gen3_init(); + WMT_DETECT_PR_INFO("WLAN-GEN3 driver init, ret:%d\n", ret); + break; + + default: + /* WLAN driver init */ + ret = mtk_wcn_wlan_gen4_init(); + WMT_DETECT_PR_INFO("WLAN-GEN4 driver init, ret:%d\n", ret); + break; + } + + i_ret += ret; + + WMT_DETECT_PR_INFO("finish wlan module init\n"); + + return i_ret; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/mtk_wcn_stub_alps.c b/drivers/misc/mediatek/connectivity/common/common_detect/mtk_wcn_stub_alps.c new file mode 100644 index 0000000000000..cf281b416d858 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/mtk_wcn_stub_alps.c @@ -0,0 +1,621 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * ! \file + * \brief Declaration of library functions + * Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. + */ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + + +/* kernel wmt_build_in_adapter.c already has these, so always ignored */ +#ifdef MTK_WCN_REMOVE_KERNEL_MODULE +#undef MTK_WCN_REMOVE_KERNEL_MODULE +#endif + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define CMB_STUB_DBG_LOG 3 +#define CMB_STUB_INFO_LOG 2 +#define CMB_STUB_WARN_LOG 1 + +int gCmbStubLogLevel = CMB_STUB_INFO_LOG; + +#define CMB_STUB_LOG_PR_INFO(fmt, arg...) \ +do { \ + if (gCmbStubLogLevel >= CMB_STUB_INFO_LOG) \ + pr_info(fmt, ##arg); \ +} while (0) +#define CMB_STUB_LOG_PR_WARN(fmt, arg...) \ +do { \ + if (gCmbStubLogLevel >= CMB_STUB_WARN_LOG) \ + pr_warn(fmt, ##arg); \ +} while (0) +#define CMB_STUB_LOG_PR_DBG(fmt, arg...) \ +do { \ + if (gCmbStubLogLevel >= CMB_STUB_DBG_LOG) \ + pr_info(fmt, ##arg); \ +} while (0) + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "wmt_detect.h" + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +int gConnectivityChipId = -1; + +/* +* current used uart port name, default is "ttyMT2", +* will be changed when wmt driver init +*/ +char *wmt_uart_port_desc = "ttyMT2"; +EXPORT_SYMBOL(wmt_uart_port_desc); + +#ifdef MTK_WCN_REMOVE_KERNEL_MODULE +static void mtk_wcn_cmb_sdio_request_eirq(msdc_sdio_irq_handler_t irq_handler, void *data); +static void mtk_wcn_cmb_sdio_enable_eirq(void); +static void mtk_wcn_cmb_sdio_disable_eirq(void); +static void mtk_wcn_cmb_sdio_register_pm(pm_callback_t pm_cb, void *data); + +struct sdio_ops mt_sdio_ops[4] = { + {NULL, NULL, NULL, NULL}, + {NULL, NULL, NULL, NULL}, + {mtk_wcn_cmb_sdio_request_eirq, mtk_wcn_cmb_sdio_enable_eirq, + mtk_wcn_cmb_sdio_disable_eirq, mtk_wcn_cmb_sdio_register_pm}, + {mtk_wcn_cmb_sdio_request_eirq, mtk_wcn_cmb_sdio_enable_eirq, + mtk_wcn_cmb_sdio_disable_eirq, mtk_wcn_cmb_sdio_register_pm} +}; +#endif + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +static wmt_aif_ctrl_cb cmb_stub_aif_ctrl_cb; +static wmt_func_ctrl_cb cmb_stub_func_ctrl_cb; +static wmt_thermal_query_cb cmb_stub_thermal_ctrl_cb; +static wmt_trigger_assert_cb cmb_stub_trigger_assert_cb; +static enum CMB_STUB_AIF_X cmb_stub_aif_stat = CMB_STUB_AIF_0; +static wmt_deep_idle_ctrl_cb cmb_stub_deep_idle_ctrl_cb; +static wmt_func_do_reset cmb_stub_do_reset_cb; +static wmt_clock_fail_dump_cb cmb_stub_clock_fail_dump_cb; +/* A temp translation table between COMBO_AUDIO_STATE_X and CMB_STUB_AIF_X. + * This is used for ALPS backward compatible ONLY!!! Remove this table, related + * functions, and type definition after modifying other kernel built-in modules, + * such as AUDIO. [FixMe][GeorgeKuo] + */ +#if 0 +static enum CMB_STUB_AIF_X audio2aif[] = { + [COMBO_AUDIO_STATE_0] = CMB_STUB_AIF_0, + [COMBO_AUDIO_STATE_1] = CMB_STUB_AIF_1, + [COMBO_AUDIO_STATE_2] = CMB_STUB_AIF_2, + [COMBO_AUDIO_STATE_3] = CMB_STUB_AIF_3, +}; +#endif + +#ifdef MTK_WCN_REMOVE_KERNEL_MODULE +static msdc_sdio_irq_handler_t mtk_wcn_cmb_sdio_eirq_handler; +static atomic_t sdio_claim_irq_enable_flag; +static atomic_t irq_enable_flag; +static pm_callback_t mtk_wcn_cmb_sdio_pm_cb; +static void *mtk_wcn_cmb_sdio_pm_data; +static void *mtk_wcn_cmb_sdio_eirq_data; + +static u32 wifi_irq = 0xffffffff; +#endif +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#ifndef MTK_WCN_REMOVE_KERNEL_MODULE +static int _mtk_wcn_cmb_stub_query_ctrl(void); +static int _mtk_wcn_cmb_stub_trigger_assert(void); +static void _mtk_wcn_cmb_stub_clock_fail_dump(void); +#endif /* MTK_WCN_REMOVE_KERNEL_MODULE */ + +/******************************************************************************* +* 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(struct _CMB_STUB_CB_ *p_stub_cb) +{ +#ifndef MTK_WCN_REMOVE_KERNEL_MODULE + struct wmt_platform_bridge pbridge; + + memset(&pbridge, 0, sizeof(struct wmt_platform_bridge)); +#endif + + if ((!p_stub_cb) + || (p_stub_cb->size != sizeof(struct _CMB_STUB_CB_))) { + CMB_STUB_LOG_PR_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_PR_DBG("[cmb_stub] registered, p_stub_cb:0x%p size(%d)\n", + p_stub_cb, p_stub_cb->size); + + cmb_stub_aif_ctrl_cb = p_stub_cb->aif_ctrl_cb; + cmb_stub_func_ctrl_cb = p_stub_cb->func_ctrl_cb; + cmb_stub_thermal_ctrl_cb = p_stub_cb->thermal_query_cb; + cmb_stub_trigger_assert_cb = p_stub_cb->trigger_assert_cb; + cmb_stub_deep_idle_ctrl_cb = p_stub_cb->deep_idle_ctrl_cb; + cmb_stub_do_reset_cb = p_stub_cb->wmt_do_reset_cb; + cmb_stub_clock_fail_dump_cb = p_stub_cb->clock_fail_dump_cb; + +#ifndef MTK_WCN_REMOVE_KERNEL_MODULE + pbridge.thermal_query_cb = _mtk_wcn_cmb_stub_query_ctrl; + pbridge.trigger_assert_cb = _mtk_wcn_cmb_stub_trigger_assert; + pbridge.clock_fail_dump_cb = _mtk_wcn_cmb_stub_clock_fail_dump; + wmt_export_platform_bridge_register(&pbridge); +#endif + + return 0; +} +EXPORT_SYMBOL(mtk_wcn_cmb_stub_reg); +/*! + * \brief A unregistration function for WMT-PLAT to unregister from CMB-STUB. + * + * An MTK-WCN-CMB-STUB unregistration function provided to WMT-PLAT to + * unregister itself and clear callback function references. + * + * \retval 0 operation success + */ +int mtk_wcn_cmb_stub_unreg(void) +{ +#ifndef MTK_WCN_REMOVE_KERNEL_MODULE + wmt_export_platform_bridge_unregister(); +#endif + + cmb_stub_aif_ctrl_cb = NULL; + cmb_stub_func_ctrl_cb = NULL; + cmb_stub_thermal_ctrl_cb = NULL; + cmb_stub_deep_idle_ctrl_cb = NULL; + cmb_stub_do_reset_cb = NULL; + cmb_stub_clock_fail_dump_cb = NULL; + CMB_STUB_LOG_PR_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(enum CMB_STUB_AIF_X state, enum CMB_STUB_AIF_CTRL ctrl) +{ + int ret; + + if ((state >= CMB_STUB_AIF_MAX) + || (ctrl >= CMB_STUB_AIF_CTRL_MAX)) { + + CMB_STUB_LOG_PR_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_PR_INFO("aif state(%d->%d) ctrl(%d) ret(%d)\n", + cmb_stub_aif_stat, state, ctrl, ret); /* KERN_DEBUG */ + + cmb_stub_aif_stat = state; + } else { + CMB_STUB_LOG_PR_WARN("[cmb_stub] aif_ctrl_cb null\n"); + ret = -2; + } + return ret; +} +EXPORT_SYMBOL(mtk_wcn_cmb_stub_aif_ctrl); + +/* Use a temp translation table between COMBO_AUDIO_STATE_X and CMB_STUB_AIF_X + * for ALPS backward compatible ONLY!!! Remove this table, related functions, + * and type definition after modifying other kernel built-in modules, such as + * AUDIO. [FixMe][GeorgeKuo] + */ + +void mtk_wcn_cmb_stub_func_ctrl(unsigned int type, unsigned int on) +{ + if (cmb_stub_func_ctrl_cb) + (*cmb_stub_func_ctrl_cb) (type, on); + else + CMB_STUB_LOG_PR_WARN("[cmb_stub] func_ctrl_cb null\n"); +} +EXPORT_SYMBOL(mtk_wcn_cmb_stub_func_ctrl); + +#ifdef MTK_WCN_REMOVE_KERNEL_MODULE +int mtk_wcn_cmb_stub_query_ctrl(void) +#else +static int _mtk_wcn_cmb_stub_query_ctrl(void) +#endif +{ + signed long temp = 0; + + if (cmb_stub_thermal_ctrl_cb) + temp = (*cmb_stub_thermal_ctrl_cb) (); + else + CMB_STUB_LOG_PR_WARN("[cmb_stub] thermal_ctrl_cb null\n"); + + return temp; +} + +#ifdef MTK_WCN_REMOVE_KERNEL_MODULE +int mtk_wcn_cmb_stub_trigger_assert(void) +#else +static int _mtk_wcn_cmb_stub_trigger_assert(void) +#endif +{ + int ret = 0; + + if (cmb_stub_trigger_assert_cb) + ret = (*cmb_stub_trigger_assert_cb) (); + else + CMB_STUB_LOG_PR_WARN("[cmb_stub] trigger_assert_cb null\n"); + + return ret; +} + +#ifndef MTK_WCN_REMOVE_KERNEL_MODULE +void _mtk_wcn_cmb_stub_clock_fail_dump(void) +{ + if (cmb_stub_clock_fail_dump_cb) + (*cmb_stub_clock_fail_dump_cb) (); + else + CMB_STUB_LOG_PR_WARN("[cmb_stub] clock_fail_dump_cb null\n"); +} +#endif + +/*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(enum COMBO_IF src, int enter) +{ + int ret = -1; + +#if 0 + if (src != COMBO_IF_UART && src != COMBO_IF_MSDC && src != COMBO_IF_BTIF) { + CMB_STUB_LOG_PR_WARN("src = %d is error\n", src); + return ret; + } + if (src >= 0 && src < COMBO_IF_MAX) + CMB_STUB_LOG_PR_INFO("src = %s, to enter deep idle? %d\n", + combo_if_name[src], enter); +#endif + /* + * TODO: For Common SDIO configuration, we need to do some judgement between STP and WIFI + * to decide if the msdc will enter deep idle safely + */ + + switch (src) { + case COMBO_IF_UART: + if (enter == 0) { + /* clr_device_working_ability(MT65XX_PDN_PERI_UART3, DEEP_IDLE_STATE); */ + /* disable_dpidle_by_bit(MT65XX_PDN_PERI_UART2); */ +#ifdef MTK_WCN_COMBO_CHIP_SUPPORT +#if 0 + ret = mtk_uart_pdn_enable(wmt_uart_port_desc, 0); + if (ret < 0) + CMB_STUB_LOG_PR_WARN("%s exit deepidle failed", + wmt_uart_port_desc); +#endif +#endif + } else { + /* set_device_working_ability(MT65XX_PDN_PERI_UART3, DEEP_IDLE_STATE); */ + /* enable_dpidle_by_bit(MT65XX_PDN_PERI_UART2); */ +#ifdef MTK_WCN_COMBO_CHIP_SUPPORT +#if 0 + ret = mtk_uart_pdn_enable(wmt_uart_port_desc, 1); + if (ret < 0) + CMB_STUB_LOG_PR_WARN("%s enter deepidle failed", + wmt_uart_port_desc); +#endif +#endif + } + ret = 0; + break; + + case COMBO_IF_MSDC: + if (enter == 0) { + /* for common sdio hif */ + /* clr_device_working_ability(MT65XX_PDN_PERI_MSDC2, DEEP_IDLE_STATE); */ + } else { + /* for common sdio hif */ + /* set_device_working_ability(MT65XX_PDN_PERI_MSDC2, DEEP_IDLE_STATE); */ + } + ret = 0; + break; + + case COMBO_IF_BTIF: + if (cmb_stub_deep_idle_ctrl_cb) + ret = (*cmb_stub_deep_idle_ctrl_cb) (enter); + else + CMB_STUB_LOG_PR_WARN("NULL function pointer\n"); + + if (ret) + CMB_STUB_LOG_PR_WARN("%s deep idle fail(%d)\n", + enter == 1 ? "enter" : "exit", ret); + else + CMB_STUB_LOG_PR_DBG("%s deep idle ok(%d)\n", + enter == 1 ? "enter" : "exit", ret); + break; + default: + break; + } + + return ret; +} + +int mt_combo_plt_enter_deep_idle(enum 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(enum COMBO_IF src) +{ + /* return 0; */ + /* TODO: [FixMe][GeorgeKuo] handling this depends on common UART or common SDIO */ + return _mt_combo_plt_do_deep_idle(src, 0); +} +EXPORT_SYMBOL(mt_combo_plt_exit_deep_idle); + +int mtk_wcn_wmt_chipid_query(void) +{ + CMB_STUB_LOG_PR_INFO("query current consys chipid (0x%x)\n", + gConnectivityChipId); + return gConnectivityChipId; +} +EXPORT_SYMBOL(mtk_wcn_wmt_chipid_query); + +void mtk_wcn_wmt_set_chipid(int chipid) +{ + CMB_STUB_LOG_PR_INFO("set current consys chipid (0x%x)\n", chipid); + gConnectivityChipId = chipid; +} +EXPORT_SYMBOL(mtk_wcn_wmt_set_chipid); + +int mtk_wcn_cmb_stub_do_reset(unsigned int type) +{ + if (cmb_stub_do_reset_cb) + return (*cmb_stub_do_reset_cb) (type); + else + return -1; +} +EXPORT_SYMBOL(mtk_wcn_cmb_stub_do_reset); + +#ifdef MTK_WCN_REMOVE_KERNEL_MODULE +static void mtk_wcn_cmb_sdio_enable_eirq(void) +{ + if (atomic_read(&irq_enable_flag)) + CMB_STUB_LOG_PR_DBG("wifi eint has been enabled\n"); + else { + atomic_set(&irq_enable_flag, 1); + if (wifi_irq != 0xffffffff) { + enable_irq(wifi_irq); + CMB_STUB_LOG_PR_DBG(" enable WIFI EINT irq %d !!\n", + wifi_irq); + } + } +} + +static void mtk_wcn_cmb_sdio_disable_eirq(void) +{ + if (!atomic_read(&irq_enable_flag)) + CMB_STUB_LOG_PR_DBG("wifi eint has been disabled!\n"); + else { + if (wifi_irq != 0xffffffff) { + disable_irq_nosync(wifi_irq); + CMB_STUB_LOG_PR_DBG("disable WIFI EINT irq %d !!\n", + wifi_irq); + } + atomic_set(&irq_enable_flag, 0); + } +} + +irqreturn_t mtk_wcn_cmb_sdio_eirq_handler_stub(int irq, void *data) +{ + if ((mtk_wcn_cmb_sdio_eirq_handler != NULL) && (atomic_read(&sdio_claim_irq_enable_flag) != 0)) + mtk_wcn_cmb_sdio_eirq_handler(mtk_wcn_cmb_sdio_eirq_data); + return IRQ_HANDLED; +} + +static void mtk_wcn_cmb_sdio_request_eirq(msdc_sdio_irq_handler_t irq_handler, void *data) +{ + struct device_node *node; + int ret = -EINVAL; +#if 0 + unsigned int gpio_wifi_eint_pin; +#endif + + CMB_STUB_LOG_PR_INFO("enter %s\n", __func__); + mtk_wcn_sdio_irq_flag_set(0); + atomic_set(&irq_enable_flag, 1); + mtk_wcn_cmb_sdio_eirq_data = data; + mtk_wcn_cmb_sdio_eirq_handler = irq_handler; + + node = (struct device_node *)of_find_compatible_node(NULL, NULL, "mediatek,connectivity-combo"); + if (node) { +#if 0 + gpio_wifi_eint_pin = of_get_gpio(node, 5); + CMB_STUB_LOG_PR_INFO("WIFI EINT pin %d !!\n", + gpio_wifi_eint_pin); + wifi_irq = gpio_to_irq(gpio_wifi_eint_pin); +#else + wifi_irq = irq_of_parse_and_map(node, 0);/* get wifi eint num */ +#endif +#if 1 + ret = request_irq(wifi_irq, mtk_wcn_cmb_sdio_eirq_handler_stub, IRQF_TRIGGER_LOW, + "WIFI-eint", NULL); + CMB_STUB_LOG_PR_DBG("WIFI EINT irq %d !!\n", wifi_irq); +#endif + + if (ret) + CMB_STUB_LOG_PR_WARN("EINT IRQ LINE NOT AVAILABLE!!\n"); + else + mtk_wcn_cmb_sdio_disable_eirq();/*not ,chip state is power off*/ + } else + CMB_STUB_LOG_PR_WARN("[%s] can't find device node\n", __func__); + + CMB_STUB_LOG_PR_INFO("exit %s\n", __func__); +} + +static void mtk_wcn_cmb_sdio_register_pm(pm_callback_t pm_cb, void *data) +{ + CMB_STUB_LOG_PR_DBG("mtk_wcn_cmb_sdio_register_pm (0x%p, 0x%p)\n", + pm_cb, data); + /* register pm change callback */ + mtk_wcn_cmb_sdio_pm_cb = pm_cb; + mtk_wcn_cmb_sdio_pm_data = data; +} +#endif /* MTK_WCN_REMOVE_KERNEL_MODULE */ + +static void mtk_wcn_cmb_sdio_on(int sdio_port_num) +{ + pm_message_t state = {.event = PM_EVENT_USER_RESUME }; + + CMB_STUB_LOG_PR_INFO("mtk_wcn_cmb_sdio_on (%d)\n", sdio_port_num); + + /* 1. disable sdio eirq */ +#ifdef MTK_WCN_REMOVE_KERNEL_MODULE + mtk_wcn_cmb_sdio_disable_eirq(); +#else + wmt_export_mtk_wcn_cmb_sdio_disable_eirq(); +#endif + + /* 2. call sd callback */ + if (mtk_wcn_cmb_sdio_pm_cb) { + /* pr_warn("mtk_wcn_cmb_sdio_pm_cb(PM_EVENT_USER_RESUME, 0x%p, 0x%p)\n", + * mtk_wcn_cmb_sdio_pm_cb, mtk_wcn_cmb_sdio_pm_data); + */ + mtk_wcn_cmb_sdio_pm_cb(state, mtk_wcn_cmb_sdio_pm_data); + } else + CMB_STUB_LOG_PR_WARN("mtk_wcn_cmb_sdio_on no sd callback!!\n"); +} + +static void mtk_wcn_cmb_sdio_off(int sdio_port_num) +{ + pm_message_t state = {.event = PM_EVENT_USER_SUSPEND }; + + CMB_STUB_LOG_PR_INFO("mtk_wcn_cmb_sdio_off (%d)\n", sdio_port_num); + + /* 1. call sd callback */ + if (mtk_wcn_cmb_sdio_pm_cb) { + /* pr_warn("mtk_wcn_cmb_sdio_off(PM_EVENT_USER_SUSPEND, 0x%p, 0x%p)\n", + * mtk_wcn_cmb_sdio_pm_cb, mtk_wcn_cmb_sdio_pm_data); + */ + mtk_wcn_cmb_sdio_pm_cb(state, mtk_wcn_cmb_sdio_pm_data); + } else + CMB_STUB_LOG_PR_WARN("mtk_wcn_cmb_sdio_off no sd callback!!\n"); + + /* 2. disable sdio eirq */ +#ifdef MTK_WCN_REMOVE_KERNEL_MODULE + mtk_wcn_cmb_sdio_disable_eirq(); +#else + wmt_export_mtk_wcn_cmb_sdio_disable_eirq(); +#endif +} + +int board_sdio_ctrl(unsigned int sdio_port_num, unsigned int on) +{ + CMB_STUB_LOG_PR_DBG("mt_mtk_wcn_cmb_sdio_ctrl (%d, %d)\n", + sdio_port_num, on); + if (on) { +#if 1 + CMB_STUB_LOG_PR_DBG("board_sdio_ctrl force off before on\n"); + mtk_wcn_cmb_sdio_off(sdio_port_num); +#else + CMB_STUB_LOG_PR_WARN("skip sdio off before on\n"); +#endif + /* off -> on */ + mtk_wcn_cmb_sdio_on(sdio_port_num); + if (wifi_irq != 0xffffffff) + irq_set_irq_wake(wifi_irq, 1); + else + CMB_STUB_LOG_PR_WARN("wifi_irq is not available\n"); + } else { + if (wifi_irq != 0xffffffff) + irq_set_irq_wake(wifi_irq, 0); + else + CMB_STUB_LOG_PR_WARN("wifi_irq is not available\n"); + /* on -> off */ + mtk_wcn_cmb_sdio_off(sdio_port_num); + } + + return 0; +} +EXPORT_SYMBOL(board_sdio_ctrl); + +#ifdef MTK_WCN_REMOVE_KERNEL_MODULE +int mtk_wcn_sdio_irq_flag_set(int flag) +{ + if (flag != 0) + atomic_set(&sdio_claim_irq_enable_flag, 1); + else + atomic_set(&sdio_claim_irq_enable_flag, 0); + + CMB_STUB_LOG_PR_DBG("sdio_claim_irq_enable_flag:%d\n", + atomic_read(&sdio_claim_irq_enable_flag)); + + return atomic_read(&sdio_claim_irq_enable_flag); +} +EXPORT_SYMBOL(mtk_wcn_sdio_irq_flag_set); +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/sdio_detect.c b/drivers/misc/mediatek/connectivity/common/common_detect/sdio_detect.c new file mode 100644 index 0000000000000..42dbafecd265d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/sdio_detect.c @@ -0,0 +1,249 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[SDIO-DETECT]" + +#include "wmt_detect.h" + +unsigned int gComboChipId = -1; +struct sdio_func *g_func; +unsigned int gDrvRegistered; + +MTK_WCN_HIF_SDIO_CHIP_INFO gChipInfoArray[] = { + /* MT6620 *//* Not an SDIO standard class device */ + {{SDIO_DEVICE(0x037A, 0x020A)}, 0x6620}, /* SDIO1:FUNC1:WIFI */ + {{SDIO_DEVICE(0x037A, 0x020B)}, 0x6620}, /* SDIO2:FUNC1:BT+FM+GPS */ + {{SDIO_DEVICE(0x037A, 0x020C)}, 0x6620}, /* 2-function (SDIO2:FUNC1:BT+FM+GPS, FUNC2:WIFI) */ + + /* MT6628 *//* SDIO1: Wi-Fi, SDIO2: BGF */ + {{SDIO_DEVICE(0x037A, 0x6628)}, 0x6628}, + + /* MT6630 *//* SDIO1: Wi-Fi, SDIO2: BGF */ + {{SDIO_DEVICE(0x037A, 0x6630)}, 0x6630}, + + /* MT6632 *//* SDIO1: Wi-Fi */ + {{SDIO_DEVICE(0x037A, 0x6602)}, 0x6632}, + + /* MT6632 *//* SDIO2: BGF */ + {{SDIO_DEVICE(0x037A, 0x6632)}, 0x6632}, + +}; + +/* Supported SDIO device table */ +static const struct sdio_device_id mtk_sdio_id_tbl[] = { + /* MT6618 *//* Not an SDIO standard class device */ + {SDIO_DEVICE(0x037A, 0x018A)}, /* SDIO1:WIFI */ + {SDIO_DEVICE(0x037A, 0x018B)}, /* SDIO2:FUNC1:BT+FM */ + {SDIO_DEVICE(0x037A, 0x018C)}, /* 2-function (SDIO2:FUNC1:BT+FM, FUNC2:WIFI) */ + + /* MT6619 *//* Not an SDIO standard class device */ + {SDIO_DEVICE(0x037A, 0x6619)}, /* SDIO2:FUNC1:BT+FM+GPS */ + + /* MT6620 *//* Not an SDIO standard class device */ + {SDIO_DEVICE(0x037A, 0x020A)}, /* SDIO1:FUNC1:WIFI */ + {SDIO_DEVICE(0x037A, 0x020B)}, /* SDIO2:FUNC1:BT+FM+GPS */ + {SDIO_DEVICE(0x037A, 0x020C)}, /* 2-function (SDIO2:FUNC1:BT+FM+GPS, FUNC2:WIFI) */ + + /* MT5921 *//* Not an SDIO standard class device */ + {SDIO_DEVICE(0x037A, 0x5921)}, + + /* MT6628 *//* SDIO1: Wi-Fi, SDIO2: BGF */ + {SDIO_DEVICE(0x037A, 0x6628)}, + + /* MT6630 *//* SDIO1: Wi-Fi, SDIO2: BGF */ + {SDIO_DEVICE(0x037A, 0x6630)}, + + /* MT6632 *//* SDIO1: Wi-Fi */ + {SDIO_DEVICE(0x037A, 0x6602)}, + + /* MT6632 *//* SDIO2: BGF */ + {SDIO_DEVICE(0x037A, 0x6632)}, + { /* end: all zeroes */ }, +}; + +static int sdio_detect_probe(struct sdio_func *func, const struct sdio_device_id *id); + +static void sdio_detect_remove(struct sdio_func *func); + +static struct sdio_driver mtk_sdio_client_drv = { + .name = "mtk_sdio_client", /* MTK SDIO Client Driver */ + .id_table = mtk_sdio_id_tbl, /* all supported struct sdio_device_id table */ + .probe = sdio_detect_probe, + .remove = sdio_detect_remove, +}; + +static int hif_sdio_match_chipid_by_dev_id(const struct sdio_device_id *id); + +int hif_sdio_is_chipid_valid(int chipId) +{ + int index = -1; + + int left = 0; + int middle = 0; + int right = ARRAY_SIZE(gChipInfoArray) - 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 (index < 0) + WMT_DETECT_PR_ERR("no supported chipid found\n"); + else + WMT_DETECT_PR_INFO("index:%d, chipId:0x%x\n", index, gChipInfoArray[index].chipId); + + return index; +} + +int hif_sdio_match_chipid_by_dev_id(const struct sdio_device_id *id) +{ + int maxIndex = ARRAY_SIZE(gChipInfoArray); + int index = 0; + struct sdio_device_id *localId = NULL; + int chipId = -1; + + for (index = 0; index < maxIndex; index++) { + localId = &(gChipInfoArray[index].deviceId); + if ((localId->vendor == id->vendor) && (localId->device == id->device)) { + chipId = gChipInfoArray[index].chipId; + WMT_DETECT_PR_INFO + ("valid chipId found, index(%d), vendor id(0x%x), device id(0x%x), chip id(0x%x)\n", index, + localId->vendor, localId->device, chipId); + mtk_wcn_wmt_set_chipid(chipId); + gComboChipId = chipId; + break; + } + } + if (chipId < 0) { + WMT_DETECT_PR_ERR("No valid chipId found, vendor id(0x%x), device id(0x%x)\n", id->vendor, + id->device); + } + + return chipId; +} + +int sdio_detect_query_chipid(int waitFlag) +{ + unsigned int timeSlotMs = 200; + unsigned int maxTimeSlot = 30; + unsigned int counter = 0; + /* gComboChipId = 0x6628; */ + if (waitFlag == 0) + return gComboChipId; + if (hif_sdio_is_chipid_valid(gComboChipId) >= 0) + return gComboChipId; + + while (counter < maxTimeSlot) { + if (hif_sdio_is_chipid_valid(gComboChipId) >= 0) + break; + msleep(timeSlotMs); + counter++; + } + + return gComboChipId; +} + +int sdio_detect_do_autok(int chipId) +{ + int i_ret = 0; + + WMT_DETECT_PR_INFO("autok was move to sdio driver\n"); + return i_ret; +} + +/*! + * \brief hif_sdio probe function + * + * hif_sdio probe function called by mmc driver when any matched SDIO function + * is detected by it. + * + * \param func + * \param id + * + * \retval 0 register successfully + * \retval < 0 list error code here + */ +static int sdio_detect_probe(struct sdio_func *func, const struct sdio_device_id *id) +{ + int chipId = 0; + + WMT_DETECT_PR_INFO("vendor(0x%x) device(0x%x) num(0x%x)\n", func->vendor, func->device, func->num); + chipId = hif_sdio_match_chipid_by_dev_id(id); + + if ((chipId == 0x6630 || chipId == 0x6632) && (func->num == 1)) { + int ret = 0; + + g_func = func; + WMT_DETECT_PR_INFO("autok function detected, func:0x%p\n", g_func); + + sdio_claim_host(func); + ret = sdio_enable_func(func); + sdio_release_host(func); + if (ret) + WMT_DETECT_PR_ERR("sdio_enable_func failed!\n"); + } + + return 0; +} + +static void sdio_detect_remove(struct sdio_func *func) +{ + if (g_func == func) { + sdio_claim_host(func); + sdio_disable_func(func); + sdio_release_host(func); + g_func = NULL; + } + WMT_DETECT_PR_INFO("do sdio remove\n"); +} + +int sdio_detect_init(void) +{ + int ret = 0; + /* register to mmc driver */ + if (gDrvRegistered == 0) { + ret = sdio_register_driver(&mtk_sdio_client_drv); + if (ret == 0) + gDrvRegistered = 1; + } + WMT_DETECT_PR_INFO("sdio_register_driver() ret=%d\n", ret); + return ret; +} + +int sdio_detect_exit(void) +{ + g_func = NULL; + /* unregister to mmc driver */ + if (gDrvRegistered == 1) { + sdio_unregister_driver(&mtk_sdio_client_drv); + gDrvRegistered = 0; + } + WMT_DETECT_PR_INFO("sdio_unregister_driver\n"); + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/sdio_detect.h b/drivers/misc/mediatek/connectivity/common/common_detect/sdio_detect.h new file mode 100644 index 0000000000000..274261d6075d1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/sdio_detect.h @@ -0,0 +1,36 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _SDIO_DETECT_H_ +#define _SDIO_DETECT_H_ + +#include +#include +#include +#include +#include + +typedef struct _MTK_WCN_HIF_SDIO_CHIP_INFO_ { + struct sdio_device_id deviceId; + unsigned int chipId; +} MTK_WCN_HIF_SDIO_CHIP_INFO, *P_MTK_WCN_HIF_SDIO_CHIP_INFO; + +extern int sdio_detect_exit(void); +extern int sdio_detect_init(void); +extern int sdio_detect_query_chipid(int waitFlag); +extern int hif_sdio_is_chipid_valid(int chipId); + +extern int sdio_detect_do_autok(int chipId); + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect.c b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect.c new file mode 100644 index 0000000000000..ade16a12be1c8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect.c @@ -0,0 +1,407 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#include +#include + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-DETECT]" + +#include "wmt_detect.h" +#include "wmt_gpio.h" +#include "wmt_dev.h" + +#if MTK_WCN_REMOVE_KO +#include "conn_drv_init.h" +#endif +#ifdef CONFIG_COMPAT +#include +#endif + +#define WMT_DETECT_MAJOR 154 +#define WMT_DETECT_DEV_NUM 1 +#define WMT_DETECT_DRVIER_NAME "mtk_wcn_detect" +#define WMT_DETECT_DEVICE_NAME "wmtdetect" + +struct class *pDetectClass; +struct device *pDetectDev; +static int gWmtDetectMajor = WMT_DETECT_MAJOR; +static struct cdev gWmtDetectCdev; +int gWmtDetectDbgLvl = WMT_DETECT_LOG_INFO; +static ENUM_WMT_CHIP_TYPE g_chip_type = WMT_CHIP_TYPE_INVALID; + +static int wmt_detect_open(struct inode *inode, struct file *file) +{ + WMT_DETECT_PR_INFO("open major %d minor %d (pid %d)\n", imajor(inode), iminor(inode), current->pid); + + return 0; +} + +static int wmt_detect_close(struct inode *inode, struct file *file) +{ + WMT_DETECT_PR_INFO("close major %d minor %d (pid %d)\n", imajor(inode), iminor(inode), current->pid); + + return 0; +} + +static ssize_t wmt_detect_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + WMT_DETECT_PR_INFO(" ++\n"); + WMT_DETECT_PR_INFO(" --\n"); + + return 0; +} + +ssize_t wmt_detect_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) +{ + WMT_DETECT_PR_INFO(" ++\n"); + WMT_DETECT_PR_INFO(" --\n"); + + return 0; +} + +static long wmt_detect_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + int retval = 0; + + WMT_DETECT_PR_INFO("cmd (%d),arg(%ld)\n", cmd, arg); + + switch (cmd) { + case COMBO_IOCTL_GET_CHIP_ID: + /*just get chipid from sdio-detect module */ + /*check if external combo chip exists or not */ + /*if yes, just return combo chip id */ + /*if no, get soc chipid */ + retval = mtk_wcn_wmt_chipid_query(); + break; + + case COMBO_IOCTL_SET_CHIP_ID: + WMT_DETECT_PR_INFO("chipid(%ld)\n", arg); + mtk_wcn_wmt_set_chipid(arg); + wmt_detect_set_chip_type(arg); + break; + + case COMBO_IOCTL_EXT_CHIP_PWR_ON: + retval = wmt_detect_ext_chip_pwr_on(); + break; + + case COMBO_IOCTL_EXT_CHIP_DETECT: + retval = wmt_detect_ext_chip_detect(); + break; + + case COMBO_IOCTL_EXT_CHIP_PWR_OFF: + retval = wmt_detect_ext_chip_pwr_off(); + break; + + case COMBO_IOCTL_DO_SDIO_AUDOK: + retval = sdio_detect_do_autok(arg); + break; + + case COMBO_IOCTL_GET_SOC_CHIP_ID: + retval = wmt_plat_get_soc_chipid(); + /*get soc chipid by HAL interface */ + break; + + case COMBO_IOCTL_GET_ADIE_CHIP_ID: + retval = wmt_plat_get_adie_chipid(); + break; + + case COMBO_IOCTL_MODULE_CLEANUP: + retval = sdio_detect_exit(); + break; + + case COMBO_IOCTL_DO_MODULE_INIT: +#if (MTK_WCN_REMOVE_KO) + /*deinit SDIO-DETECT module */ + WMT_DETECT_PR_INFO("built-in mode\n"); + retval = do_connectivity_driver_init(arg); +#else + WMT_DETECT_PR_INFO("kernel object mode\n"); + retval = mtk_wcn_common_drv_init(); +#endif + break; + + default: + WMT_DETECT_PR_WARN("unknown cmd (%d)\n", cmd); + retval = 0; + break; + } + return retval; +} +#ifdef CONFIG_COMPAT +static long WMT_compat_detect_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + long ret; + + WMT_DETECT_PR_INFO("cmd (%d)\n", cmd); + ret = wmt_detect_unlocked_ioctl(filp, cmd, arg); + return ret; +} +#endif +const struct file_operations gWmtDetectFops = { + .open = wmt_detect_open, + .release = wmt_detect_close, + .read = wmt_detect_read, + .write = wmt_detect_write, + .unlocked_ioctl = wmt_detect_unlocked_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = WMT_compat_detect_ioctl, +#endif +}; + +int wmt_detect_ext_chip_pwr_on(void) +{ + /*pre power on external chip */ + /* wmt_plat_pwr_ctrl(FUNC_ON); */ +#ifdef MTK_WCN_COMBO_CHIP_SUPPORT + WMT_DETECT_PR_INFO("++\n"); + if (wmt_detect_chip_pwr_ctrl(1) != 0) + return -2; + if (wmt_detect_sdio_pwr_ctrl(1) != 0) + return -3; + return 0; +#else + WMT_DETECT_PR_INFO("combo chip is not supported\n"); + return -1; +#endif +} + +int wmt_detect_ext_chip_pwr_off(void) +{ + /*pre power off external chip */ + /* wmt_plat_pwr_ctrl(FUNC_OFF); */ +#ifdef MTK_WCN_COMBO_CHIP_SUPPORT + WMT_DETECT_PR_INFO("--\n"); + wmt_detect_sdio_pwr_ctrl(0); + return wmt_detect_chip_pwr_ctrl(0); +#else + WMT_DETECT_PR_INFO("combo chip is not supported\n"); + return 0; +#endif +} + +int wmt_detect_ext_chip_detect(void) +{ + int iRet = -1; +#ifdef MTK_WCN_COMBO_CHIP_SUPPORT + unsigned int chipId = -1; + /*if there is no external combo chip, return -1 */ + int bgfEintStatus = -1; + + WMT_DETECT_PR_INFO("++\n"); + /*wait for a stable time */ + msleep(20); + + /*read BGF_EINT_PIN status */ + bgfEintStatus = wmt_detect_read_ext_cmb_status(); + + if (bgfEintStatus == 0) { + /*external chip does not exist */ + WMT_DETECT_PR_INFO("external combo chip not detected\n"); + iRet = -2; + } else if (bgfEintStatus == 1) { + /*combo chip exists */ + WMT_DETECT_PR_INFO("external combo chip detected\n"); + + /*detect chipid by sdio_detect module */ + chipId = sdio_detect_query_chipid(1); + if (hif_sdio_is_chipid_valid(chipId) >= 0) + WMT_DETECT_PR_INFO("valid external combo chip id (0x%x)\n", chipId); + else + WMT_DETECT_PR_INFO("invalid external combo chip id (0x%x)\n", chipId); + iRet = 0; + } else { + /*Error exists */ + WMT_DETECT_PR_ERR("error happens when detecting combo chip\n"); + iRet = -3; + } + WMT_DETECT_PR_INFO("--\n"); + /*return 0 */ +#endif + return iRet; + /*todo: if there is external combo chip, power on chip return 0 */ +} + +#ifdef MTK_WCN_COMBO_CHIP_SUPPORT +static int wmt_detect_probe(struct platform_device *pdev) +{ + int ret = 0; + + WMT_DETECT_PR_INFO("platform name: %s\n", pdev->name); + ret = wmt_gpio_init(pdev); + if (-1 == ret) + WMT_DETECT_PR_ERR("gpio init fail ret:%d\n", ret); + return ret; +} + +static int wmt_detect_remove(struct platform_device *pdev) +{ + wmt_gpio_deinit(); + return 0; +} +#endif + +int wmt_detect_set_chip_type(int chip_id) +{ + switch (chip_id) { + case 0x6620: + case 0x6628: + case 0x6630: + case 0x6632: + g_chip_type = WMT_CHIP_TYPE_COMBO; + break; + case -1: + break; + default: + g_chip_type = WMT_CHIP_TYPE_SOC; + break; + } + return 0; +} +ENUM_WMT_CHIP_TYPE wmt_detect_get_chip_type(void) +{ + return g_chip_type; +} + + +#ifdef MTK_WCN_COMBO_CHIP_SUPPORT +static const struct of_device_id wmt_detect_match[] = { + { .compatible = "mediatek,connectivity-combo", }, + {} +}; +MODULE_DEVICE_TABLE(of, wmt_detect_match); + +static struct platform_driver wmt_detect_driver = { + .probe = wmt_detect_probe, + .remove = wmt_detect_remove, + .driver = { + .owner = THIS_MODULE, + .name = "mediatek,connectivity-combo", + .of_match_table = wmt_detect_match, + }, +}; +#endif + +/*module_platform_driver(wmt_detect_driver);*/ +static int wmt_detect_driver_init(void) +{ + dev_t devID = MKDEV(gWmtDetectMajor, 0); + int cdevErr = -1; + int ret = -1; + + /*init SDIO-DETECT module */ + sdio_detect_init(); + +#ifdef MTK_WCN_COMBO_CHIP_SUPPORT + ret = platform_driver_register(&wmt_detect_driver); + if (ret) + WMT_DETECT_PR_ERR("platform driver register fail ret:%d\n", ret); +#endif + + ret = register_chrdev_region(devID, WMT_DETECT_DEV_NUM, WMT_DETECT_DRVIER_NAME); + if (ret) { + WMT_DETECT_PR_ERR("fail to register chrdev\n"); + goto err0; + } + + cdev_init(&gWmtDetectCdev, &gWmtDetectFops); + gWmtDetectCdev.owner = THIS_MODULE; + + cdevErr = cdev_add(&gWmtDetectCdev, devID, WMT_DETECT_DEV_NUM); + if (cdevErr) { + WMT_DETECT_PR_ERR("cdev_add() fails (%d)\n", cdevErr); + goto err1; + } + + pDetectClass = class_create(THIS_MODULE, WMT_DETECT_DEVICE_NAME); + if (IS_ERR(pDetectClass)) { + WMT_DETECT_PR_ERR("class create fail, error code(%ld)\n", PTR_ERR(pDetectClass)); + goto err1; + } + + pDetectDev = device_create(pDetectClass, NULL, devID, NULL, WMT_DETECT_DEVICE_NAME); + if (IS_ERR(pDetectDev)) { + WMT_DETECT_PR_ERR("device create fail, error code(%ld)\n", PTR_ERR(pDetectDev)); + goto err2; + } + + WMT_DETECT_PR_INFO("driver(major %d) installed success\n", gWmtDetectMajor); + + return 0; + +err2: + + if (pDetectClass) { + class_destroy(pDetectClass); + pDetectClass = NULL; + } + +err1: + + if (cdevErr == 0) + cdev_del(&gWmtDetectCdev); + + if (ret == 0) { + unregister_chrdev_region(devID, WMT_DETECT_DEV_NUM); + gWmtDetectMajor = -1; + } + +err0: + sdio_detect_exit(); + +#ifdef MTK_WCN_COMBO_CHIP_SUPPORT + platform_driver_unregister(&wmt_detect_driver); +#endif + + return ret ? ret : -1; +} + +static void wmt_detect_driver_exit(void) +{ + dev_t dev = MKDEV(gWmtDetectMajor, 0); + + mtk_wcn_common_drv_exit(); + + if (pDetectDev) { + device_destroy(pDetectClass, dev); + pDetectDev = NULL; + } + + if (pDetectClass) { + class_destroy(pDetectClass); + pDetectClass = NULL; + } + + cdev_del(&gWmtDetectCdev); + unregister_chrdev_region(dev, WMT_DETECT_DEV_NUM); + + sdio_detect_exit(); + +#ifdef MTK_WCN_COMBO_CHIP_SUPPORT + if (wmt_detect_driver.driver.p) + platform_driver_unregister(&wmt_detect_driver); +#endif + + WMT_DETECT_PR_INFO("done\n"); +} + +module_init(wmt_detect_driver_init); +module_exit(wmt_detect_driver_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Zhiguo.Niu & Chaozhong.Liang @ MBJ/WCNSE/SS1"); + +module_param(gWmtDetectMajor, uint, 0); diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect.h b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect.h new file mode 100644 index 0000000000000..b6ca8857beab2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect.h @@ -0,0 +1,120 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _WMT_DETECT_H_ +#define _WMT_DETECT_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#ifdef MTK_WCN_REMOVE_KERNEL_MODULE +#define MTK_WCN_REMOVE_KO 1 +#else +#define MTK_WCN_REMOVE_KO 0 +#endif + +#include "sdio_detect.h" +#include "wmt_detect_pwr.h" +#include + +#define WMT_DETECT_LOG_LOUD 4 +#define WMT_DETECT_LOG_DBG 3 +#define WMT_DETECT_LOG_INFO 2 +#define WMT_DETECT_LOG_WARN 1 +#define WMT_DETECT_LOG_ERR 0 + +extern int gWmtDetectDbgLvl; + +#define WMT_DETECT_PR_LOUD(fmt, arg...) \ +do { \ + if (gWmtDetectDbgLvl >= WMT_DETECT_LOG_LOUD) \ + pr_info(DFT_TAG"[L]%s:" fmt, __func__, ##arg); \ +} while (0) +#define WMT_DETECT_PR_DBG(fmt, arg...) \ +do { \ + if (gWmtDetectDbgLvl >= WMT_DETECT_LOG_DBG) \ + pr_info(DFT_TAG"[D]%s:" fmt, __func__, ##arg); \ +} while (0) +#define WMT_DETECT_PR_INFO(fmt, arg...) \ +do { \ + if (gWmtDetectDbgLvl >= WMT_DETECT_LOG_INFO) \ + pr_info(DFT_TAG"[I]%s:" fmt, __func__, ##arg); \ +} while (0) +#define WMT_DETECT_PR_WARN(fmt, arg...) \ +do { \ + if (gWmtDetectDbgLvl >= WMT_DETECT_LOG_WARN) \ + pr_warn(DFT_TAG"[W]%s(%d):" fmt, __func__, __LINE__, ##arg); \ +} while (0) +#define WMT_DETECT_PR_ERR(fmt, arg...) \ +do { \ + if (gWmtDetectDbgLvl >= WMT_DETECT_LOG_ERR) \ + pr_err(DFT_TAG"[E]%s(%d):" fmt, __func__, __LINE__, ##arg); \ +} while (0) + +#define WMT_DETECT_IOC_MAGIC 'w' +#define COMBO_IOCTL_GET_CHIP_ID _IOR(WMT_DETECT_IOC_MAGIC, 0, int) +#define COMBO_IOCTL_SET_CHIP_ID _IOW(WMT_DETECT_IOC_MAGIC, 1, int) +#define COMBO_IOCTL_EXT_CHIP_DETECT _IOR(WMT_DETECT_IOC_MAGIC, 2, int) +#define COMBO_IOCTL_GET_SOC_CHIP_ID _IOR(WMT_DETECT_IOC_MAGIC, 3, int) +#define COMBO_IOCTL_DO_MODULE_INIT _IOR(WMT_DETECT_IOC_MAGIC, 4, int) +#define COMBO_IOCTL_MODULE_CLEANUP _IOR(WMT_DETECT_IOC_MAGIC, 5, int) +#define COMBO_IOCTL_EXT_CHIP_PWR_ON _IOR(WMT_DETECT_IOC_MAGIC, 6, int) +#define COMBO_IOCTL_EXT_CHIP_PWR_OFF _IOR(WMT_DETECT_IOC_MAGIC, 7, int) +#define COMBO_IOCTL_DO_SDIO_AUDOK _IOR(WMT_DETECT_IOC_MAGIC, 8, int) +#define COMBO_IOCTL_GET_ADIE_CHIP_ID _IOR(WMT_DETECT_IOC_MAGIC, 9, int) + +typedef enum _ENUM_WMT_CHIP_TYPE_T { + WMT_CHIP_TYPE_COMBO, + WMT_CHIP_TYPE_SOC, + WMT_CHIP_TYPE_INVALID +} ENUM_WMT_CHIP_TYPE; +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +********************************************************************************/ +extern int wmt_detect_ext_chip_detect(void); +extern int wmt_detect_ext_chip_pwr_on(void); +extern int wmt_detect_ext_chip_pwr_off(void); + +extern unsigned int wmt_plat_get_soc_chipid(void); +extern int wmt_plat_get_adie_chipid(void); + +#ifdef MTK_WCN_COMBO_CHIP_SUPPORT +/* mtk_uart_pdn_enable -- request uart port enter/exit deep idle mode, this API is defined in uart driver + * + * @ port - uart port name, Eg: "ttyMT0", "ttyMT1", "ttyMT2" + * @ enable - "1", enable deep idle; "0", disable deep idle + * + * Return 0 if success, else -1 + */ +extern unsigned int mtk_uart_pdn_enable(char *port, int enable); +#endif +extern int wmt_detect_set_chip_type(int chip_id); +extern ENUM_WMT_CHIP_TYPE wmt_detect_get_chip_type(void); +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect_pwr.c b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect_pwr.c new file mode 100644 index 0000000000000..7d26c2df4f210 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect_pwr.c @@ -0,0 +1,259 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* ALPS header files */ +#include + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)) +#ifndef CONFIG_RTC_DRV_MT6397 +#include +#else +#include +#endif +#endif + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-DETECT]" + +#include "wmt_detect.h" +#include "wmt_gpio.h" + +#define INVALID_PIN_ID (0xFFFFFFFF) + +/*copied form WMT module*/ +static int wmt_detect_dump_pin_conf(void) +{ + WMT_DETECT_PR_DBG("[WMT-DETECT]=>dump wmt pin configuration start<=\n"); + + WMT_DETECT_PR_INFO("LDO(GPIO%d), PMU(GPIO%d), PMUV28(GPIO%d)\n", + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_LDO_EN_PIN].gpio_num, + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num, + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMUV28_EN_PIN].gpio_num); + + WMT_DETECT_PR_INFO("RST(GPIO%d), BGF_EINT(GPIO%d), BGF_EINT_NUM(%d)\n", + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num, + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_BGF_EINT_PIN].gpio_num, + gpio_to_irq(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_BGF_EINT_PIN].gpio_num)); + + WMT_DETECT_PR_INFO("WIFI_EINT(GPIO%d), WIFI_EINT_NUM(%d)\n", + gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_num, + gpio_to_irq(gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_num)); + + WMT_DETECT_PR_DBG("[WMT-PLAT]=>dump wmt pin configuration ends<=\n"); + + return 0; +} + +int _wmt_detect_output_low(unsigned int id) +{ + if (gpio_ctrl_info.gpio_ctrl_state[id].gpio_num != INVALID_PIN_ID) { + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[id].gpio_num, 0); + WMT_DETECT_PR_INFO("WMT-DETECT: set GPIO%d to output %d\n", + gpio_ctrl_info.gpio_ctrl_state[id].gpio_num-280, + gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[id].gpio_num)); + } + + return 0; +} + +int _wmt_detect_output_high(unsigned int id) +{ + if (gpio_ctrl_info.gpio_ctrl_state[id].gpio_num != INVALID_PIN_ID) { + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[id].gpio_num, 1); + WMT_DETECT_PR_INFO("WMT-DETECT: set GPIO%d to output %d\n", + gpio_ctrl_info.gpio_ctrl_state[id].gpio_num-280, + gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[id].gpio_num)); + } + + return 0; +} + +int _wmt_detect_read_gpio_input(unsigned int id) +{ + int retval = 0; + + if (gpio_ctrl_info.gpio_ctrl_state[id].gpio_num != INVALID_PIN_ID) { + retval = gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[id].gpio_num); + WMT_DETECT_PR_DBG("WMT-DETECT: get GPIO%d val%d\n", + gpio_ctrl_info.gpio_ctrl_state[id].gpio_num, retval); + } else + WMT_DETECT_PR_ERR("WMT-DETECT: GPIO%d invalid\n", + gpio_ctrl_info.gpio_ctrl_state[id].gpio_num); + + return retval; +} + +/*This power on sequence must support all combo chip's basic power on sequence + * 1. LDO control is a must, if external LDO exist + * 2. PMU control is a must + * 3. RST control is a must + * 4. WIFI_EINT pin control is a must, used for GPIO mode for EINT status checkup + * 5. RTC32k clock control is a must + * + */ +static int wmt_detect_chip_pwr_on(void) +{ + int retval = -1; + + /*setting validiation check*/ + if ((gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num == INVALID_PIN_ID) || + (gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_num == INVALID_PIN_ID)) { + WMT_DETECT_PR_ERR("WMT-DETECT: either PMU(%d) or WIFI_EINT(%d) is not set\n", + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num, + gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_num); + + return retval; + } + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num == INVALID_PIN_ID) { + WMT_DETECT_PR_WARN("WMT-DETECT: RST(%d) is not set, if it`s not 6632 project, please check it\n", + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num); + + } + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_URXD_PIN].gpio_state[GPIO_PULL_DIS]) { + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_URXD_PIN]. + gpio_state[GPIO_PULL_DIS]); + } else + pr_err("wmt_gpio:set GPIO_COMBO_URXD_PIN to GPIO_PULL_DIS fail, is NULL!\n"); + + WMT_DETECT_PR_DBG("WMT-DETECT: GPIO_COMBO_URXD_PIN out 0\n"); + _wmt_detect_output_low(GPIO_COMBO_URXD_PIN); + + /*set LDO/PMU/RST to output 0, no pull*/ + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_LDO_EN_PIN].gpio_num != INVALID_PIN_ID) + _wmt_detect_output_low(GPIO_COMBO_LDO_EN_PIN); + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_state[GPIO_PULL_DIS]) { + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_state[GPIO_PULL_DIS]); + WMT_DETECT_PR_INFO("wmt_gpio:set GPIO_COMBO_PMU_EN_PIN to GPIO_PULL_DIS done!\n"); + } else + WMT_DETECT_PR_ERR("wmt_gpio:set GPIO_COMBO_PMU_EN_PIN to GPIO_PULL_DIS fail, is NULL!\n"); + _wmt_detect_output_low(GPIO_COMBO_PMU_EN_PIN); + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_state[GPIO_PULL_DIS]) { + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_state[GPIO_PULL_DIS]); + WMT_DETECT_PR_INFO("wmt_gpio:set GPIO_COMBO_RST_PIN to GPIO_PULL_DIS done!\n"); + } else + WMT_DETECT_PR_ERR("wmt_gpio:set GPIO_COMBO_RST_PIN to GPIO_PULL_DIS fail, is NULL!\n"); + _wmt_detect_output_low(GPIO_COMBO_RST_PIN); + +#if 0 + _wmt_detect_output_high(GPIO_WIFI_EINT_PIN); +#endif + + /*pull high LDO*/ + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_LDO_EN_PIN].gpio_num != INVALID_PIN_ID) + _wmt_detect_output_high(GPIO_COMBO_LDO_EN_PIN); + /*sleep for LDO stable time*/ + msleep(MAX_LDO_STABLE_TIME); + + /*export RTC clock, sleep for RTC stable time*/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)) + rtc_gpio_enable_32k(RTC_GPIO_USER_GPS); +#endif + msleep(MAX_RTC_STABLE_TIME); + /*PMU output low, RST output low, to make chip power off completely*/ + /*always done*/ + /*sleep for power off stable time*/ + msleep(MAX_OFF_STABLE_TIME); + /*PMU output high, and sleep for reset stable time*/ + _wmt_detect_output_high(GPIO_COMBO_PMU_EN_PIN); +#ifdef CONFIG_MTK_COMBO_COMM_NPWR + if ((gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_I2S_DAT_PIN].gpio_num != INVALID_PIN_ID) && + (gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAISYNC_PIN].gpio_num != INVALID_PIN_ID)) { + msleep(20); + _wmt_detect_output_high(GPIO_PCM_DAISYNC_PIN); + + msleep(20); + _wmt_detect_output_high(GPIO_COMBO_I2S_DAT_PIN); + + msleep(20); + _wmt_detect_output_low(GPIO_COMBO_I2S_DAT_PIN); + + msleep(20); + _wmt_detect_output_low(GPIO_PCM_DAISYNC_PIN); + + msleep(20); + } +#endif + msleep(MAX_RST_STABLE_TIME); + /*RST output high, and sleep for power on stable time */ + _wmt_detect_output_high(GPIO_COMBO_RST_PIN); + msleep(MAX_ON_STABLE_TIME); + retval = 0; + return retval; +} + +static int wmt_detect_chip_pwr_off(void) +{ + + /*set RST pin to input low status*/ + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_LDO_EN_PIN].gpio_num != INVALID_PIN_ID) + _wmt_detect_output_low(GPIO_COMBO_LDO_EN_PIN); + /*set RST pin to input low status*/ + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num != INVALID_PIN_ID) + _wmt_detect_output_low(GPIO_COMBO_RST_PIN); + /*set PMU pin to input low status*/ + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num != INVALID_PIN_ID) + _wmt_detect_output_low(GPIO_COMBO_PMU_EN_PIN); + return 0; +} + +int wmt_detect_read_ext_cmb_status(void) +{ + int retval = 0; + /*read WIFI_EINT pin status*/ + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_num == INVALID_PIN_ID) { + retval = 0; + WMT_DETECT_PR_ERR("WMT-DETECT: no WIFI_EINT pin set\n"); + } else { + retval = _wmt_detect_read_gpio_input(GPIO_WIFI_EINT_PIN); + WMT_DETECT_PR_INFO("WMT-DETECT: WIFI_EINT input status:%d\n", retval); + } + return retval; +} + +int wmt_detect_chip_pwr_ctrl(int on) +{ + int retval = -1; + + if (on == 0) { + /*power off combo chip */ + retval = wmt_detect_chip_pwr_off(); + } else { + wmt_detect_dump_pin_conf(); + /*power on combo chip */ + retval = wmt_detect_chip_pwr_on(); + } + return retval; +} + +int wmt_detect_sdio_pwr_ctrl(int on) +{ + int retval = -1; +#ifdef MTK_WCN_COMBO_CHIP_SUPPORT + if (on == 0) { + /*power off SDIO slot */ + retval = board_sdio_ctrl(1, 0); + } else { + /*power on SDIO slot */ + retval = board_sdio_ctrl(1, 1); + } +#else + WMT_DETECT_PR_WARN("WMT-DETECT: MTK_WCN_COMBO_CHIP_SUPPORT is not set\n"); +#endif + return retval; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect_pwr.h b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect_pwr.h new file mode 100644 index 0000000000000..32e661520fd0d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect_pwr.h @@ -0,0 +1,29 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef __WMT_DETECT_PWR_H_ +#define __WMT_DETECT_PWR_H_ + +#define MAX_RTC_STABLE_TIME 100 +#define MAX_LDO_STABLE_TIME 100 +#define MAX_RST_STABLE_TIME 30 +#define MAX_OFF_STABLE_TIME 10 +#define MAX_ON_STABLE_TIME 30 + +extern int board_sdio_ctrl(unsigned int sdio_port_num, unsigned int on); +extern int wmt_detect_chip_pwr_ctrl(int on); +extern int wmt_detect_sdio_pwr_ctrl(int on); +extern int wmt_detect_read_ext_cmb_status(void); + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/wmt_gpio.c b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_gpio.c new file mode 100644 index 0000000000000..55a483895f8fa --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_gpio.c @@ -0,0 +1,496 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#include "wmt_gpio.h" +#if (LINUX_VERSION_CODE >> 8) == 0x40E +#include +#endif + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +const PUINT8 gpio_state_name[GPIO_PIN_ID_MAX][GPIO_STATE_MAX] = {{"gpio_ldo_en_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "gpio_ldo_en_in_pulldown", + ""}, + {"gpio_pmuv28_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "gpio_pmuv28_in_pulldown", + ""}, + {"gpio_pmu_en_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "gpio_pmu_en_in_pulldown", + ""}, + {"gpio_rst_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "gpio_rst_in_pulldown", + ""}, + {"", + "", + "", + "", + "", + "", + "", + "gpio_bgf_eint_in_pull_dis", + "gpio_bgf_eint_in_pulldown", + "gpio_bgf_eint_in_pullup"}, + {"", + "", + "", + "", + "", + "", + "", + "gpio_wifi_eint_in_pull_dis", + "", + "gpio_wifi_eint_in_pullup"}, + {"", + "", + "", + "", + "", + "", + "", + "", + "gpio_all_eint_in_pulldown", + "gpio_all_eint_in_pullup"}, + {"gpio_urxd_uart_pull_dis", + "", + "", + "gpio_urxd_uart_out_low", + "", + "", + "", + "gpio_urxd_gpio_in_pull_dis", + "", + "gpio_urxd_gpio_in_pullup"}, + {"gpio_utxd_uart_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "", + ""}, + {"gpio_pcm_daiclk_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "", + ""}, + {"gpio_pcm_daipcmin_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "", + ""}, + {"gpio_pcm_daipcmout_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "", + ""}, + {"gpio_pcm_daisync_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "", + ""}, + {"gpio_i2s_ck_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "", + ""}, + {"gpio_i2s_ws_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "", + ""}, + {"gpio_i2s_dat_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "", + ""}, + {"gpio_gps_sync_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "", + ""}, + {"gpio_gps_lna_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "", + ""}, + {"", + "", + "", + "", + "", + "gpio_chip_deep_sleep_in_pull_dis", + "", + "", + "", + ""}, + {"", + "", + "gpio_chip_wake_up_pullup", + "", + "", + "", + "", + "", + "", + ""} +}; + +const PUINT8 gpio_pin_name[GPIO_PIN_ID_MAX] = {"gpio_combo_ldo_en_pin", + "gpio_combo_pmuv28_en_pin", + "gpio_combo_pmu_en_pin", + "gpio_combo_rst_pin", + "gpio_combo_bgf_eint_pin", + "gpio_wifi_eint_pin", + "gpio_all_eint_pin", + "gpio_combo_urxd_pin", + "gpio_combo_utxd_pin", + "gpio_pcm_daiclk_pin", + "gpio_pcm_daipcmin_pin", + "gpio_pcm_daipcmout_pin", + "gpio_pcm_daisync_pin", + "gpio_combo_i2s_ck_pin", + "gpio_combo_i2s_ws_pin", + "gpio_combo_i2s_dat_pin", + "gpio_gps_sync_pin", + "gpio_gps_lna_pin", + "gpio_chip_deep_sleep_pin", + "gpio_chip_wake_up_pin" + }; + +GPIO_CTRL_INFO gpio_ctrl_info; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +int __weak mt_get_gpio_mode_base(unsigned long pin) +{ + return 0; +} + +int __weak mt_get_gpio_pull_select_base(unsigned long pin) +{ + return 0; +} + +int __weak mt_get_gpio_in_base(unsigned long pin) +{ + return 0; +} + +int __weak mt_get_gpio_out_base(unsigned long pin) +{ + return 0; +} + +int __weak mt_get_gpio_pull_enable_base(unsigned long pin) +{ + return 0; +} + +int __weak mt_get_gpio_dir_base(unsigned long pin) +{ + return 0; +} + +int __weak mt_get_gpio_ies_base(unsigned long pin) +{ + return 0; +} + +INT32 wmt_gpio_init(struct platform_device *pdev) +{ + INT32 iret = 0; + UINT32 i, j; + struct device_node *node; + + node = of_find_compatible_node(NULL, NULL, "mediatek,connectivity-combo"); + if (!node) { + for (i = 0; i < GPIO_PIN_ID_MAX; i++) + gpio_ctrl_info.gpio_ctrl_state[i].gpio_num = DEFAULT_PIN_ID; + pr_err("wmt_gpio:can't find device tree node!\n"); + iret = -1; + goto err; + } + + gpio_ctrl_info.pinctrl_info = devm_pinctrl_get(&pdev->dev); + if (gpio_ctrl_info.pinctrl_info) { + for (i = 0; i < GPIO_PIN_ID_MAX; i++) { + gpio_ctrl_info.gpio_ctrl_state[i].gpio_num = of_get_named_gpio(node, + gpio_pin_name[i], 0); + if (gpio_ctrl_info.gpio_ctrl_state[i].gpio_num < 0) + gpio_ctrl_info.gpio_ctrl_state[i].gpio_num = DEFAULT_PIN_ID; + if (gpio_ctrl_info.gpio_ctrl_state[i].gpio_num != DEFAULT_PIN_ID) { + for (j = 0; j < GPIO_STATE_MAX; j++) { + if (strlen(gpio_state_name[i][j]) != 0) { + gpio_ctrl_info.gpio_ctrl_state[i].gpio_state[j] = + pinctrl_lookup_state(gpio_ctrl_info.pinctrl_info, + gpio_state_name[i][j]); + } else + gpio_ctrl_info.gpio_ctrl_state[i].gpio_state[j] = NULL; + } + } else { + for (j = 0; j < GPIO_STATE_MAX; j++) + gpio_ctrl_info.gpio_ctrl_state[i].gpio_state[j] = NULL; + } + } + + pr_info("wmt_gpio: gpio init start!\n"); + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_URXD_PIN].gpio_state[GPIO_PULL_DIS]) { + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_URXD_PIN]. + gpio_state[GPIO_PULL_DIS]); + } else + pr_err("wmt_gpio:set GPIO_COMBO_URXD_PIN to GPIO_PULL_DIS fail, is NULL!\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_UTXD_PIN].gpio_state[GPIO_PULL_DIS]) { + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_UTXD_PIN]. + gpio_state[GPIO_PULL_DIS]); + } else + pr_err("wmt_gpio:set GPIO_COMBO_UTXD_PIN to GPIO_PULL_DIS fail, is NULL!\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_state[GPIO_PULL_DIS]) { + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN]. + gpio_state[GPIO_PULL_DIS]); + } else + pr_err("wmt_gpio:set GPIO_COMBO_PMU_EN_PIN to GPIO_PULL_DIS fail, is NULL!\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num != DEFAULT_PIN_ID) { + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num, + 0); + pr_err("wmt_gpio:set GPIO_COMBO_PMU_EN_PIN out to 0: %d!\n", + gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num)); + } + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_state[GPIO_PULL_DIS]) { + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_state[GPIO_PULL_DIS]); + } else + pr_err("wmt_gpio:set GPIO_COMBO_RST_PIN to GPIO_PULL_DIS fail, is NULL!\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num != DEFAULT_PIN_ID) { + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num, + 0); + pr_err("wmt_gpio:set GPIO_COMBO_RST_PIN out to 0: %d!\n", + gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num)); + } + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_state[GPIO_IN_PULLUP]) { + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_state[GPIO_IN_PULLUP]); + } else + pr_err("wmt_gpio:set GPIO_WIFI_EINT_PIN to GPIO_IN_PULLUP fail, is NULL!\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAICLK_PIN].gpio_state[GPIO_PULL_DIS]) { + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAICLK_PIN].gpio_state[GPIO_PULL_DIS]); + } else + pr_err("wmt_gpio:set GPIO_PCM_DAICLK_PIN to GPIO_PULL_DIS fail, is NULL!\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAIPCMIN_PIN].gpio_state[GPIO_PULL_DIS]) { + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAIPCMIN_PIN]. + gpio_state[GPIO_PULL_DIS]); + } else + pr_err("wmt_gpio:set GPIO_PCM_DAIPCMIN_PIN to GPIO_PULL_DIS fail, is NULL!\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAIPCMOUT_PIN].gpio_state[GPIO_PULL_DIS]) { + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAIPCMOUT_PIN]. + gpio_state[GPIO_PULL_DIS]); + } else + pr_err("wmt_gpio:set GPIO_PCM_DAIPCMOUT_PIN to GPIO_PULL_DIS fail, is NULL!\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAISYNC_PIN].gpio_state[GPIO_PULL_DIS]) { + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAISYNC_PIN]. + gpio_state[GPIO_PULL_DIS]); + } else + pr_err("wmt_gpio:set GPIO_PCM_DAISYNC_PIN to GPIO_PULL_DIS fail, is NULL!\n"); + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_CHIP_DEEP_SLEEP_PIN].gpio_state[GPIO_IN_DIS]) { + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_CHIP_DEEP_SLEEP_PIN]. + gpio_state[GPIO_IN_DIS]); + } else + pr_warn("wmt_gpio:it may not be 6632 project, GPIO_CHIP_DEEP_SLEEP_PIN no need config!\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_CHIP_WAKE_UP_PIN].gpio_state[GPIO_PULL_UP]) { + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_CHIP_WAKE_UP_PIN]. + gpio_state[GPIO_PULL_UP]); + } else + pr_warn("wmt_gpio:it may not be 6632 project, GPIO_CHIP_WAKE_UP_PIN no need config!\n"); + + pr_info("wmt_gpio: gpio init done!\n"); + } else { + pr_err("wmt_gpio:can't find pinctrl dev!\n"); + iret = -1; + } + +#if (LINUX_VERSION_CODE >> 8) == 0x40E + KERNEL_mtk_wcn_cmb_sdio_request_eirq(); +#endif +err: + return iret; +} + +INT32 wmt_gpio_deinit(VOID) +{ + INT32 iret = 0; + UINT32 i; + UINT32 j; + + for (i = 0; i < GPIO_PIN_ID_MAX; i++) { + gpio_ctrl_info.gpio_ctrl_state[i].gpio_num = DEFAULT_PIN_ID; + if (gpio_ctrl_info.gpio_ctrl_state[i].gpio_num != DEFAULT_PIN_ID) { + for (j = 0; j < GPIO_STATE_MAX; j++) { + if (strlen(gpio_state_name[i][j]) != 0) + gpio_ctrl_info.gpio_ctrl_state[i].gpio_state[j] = NULL; + } + } + } + if (gpio_ctrl_info.pinctrl_info) { + devm_pinctrl_put(gpio_ctrl_info.pinctrl_info); + gpio_ctrl_info.pinctrl_info = NULL; + } + + return iret; +} + +VOID _wmt_dump_gpio_regs(INT32 idx) +{ + ULONG idxl = (ULONG)idx; + + pr_info("PIN: [MODE] [PULL_SEL] [DIN] [DOUT] [PULL EN] [DIR] [IES]\n"); + pr_info("idx = %3d: %d %d %d %d %d %d %d\n", + idx, mt_get_gpio_mode_base(idxl), + mt_get_gpio_pull_select_base(idxl), + mt_get_gpio_in_base(idxl), + mt_get_gpio_out_base(idxl), + mt_get_gpio_pull_enable_base(idxl), + mt_get_gpio_dir_base(idxl), + mt_get_gpio_ies_base(idxl)); +} + +VOID _wmt_gpio_pre_regs(INT32 num, WMT_GPIO_STATE_INFO *gpio_state) +{ + gpio_state->gpio_num = num; + gpio_state->mode = mt_get_gpio_mode_base(num); + gpio_state->pull_sel = mt_get_gpio_pull_select_base(num); + gpio_state->in = mt_get_gpio_in_base(num); + gpio_state->out = mt_get_gpio_out_base(num); + gpio_state->pull_en = mt_get_gpio_pull_enable_base(num); + gpio_state->dir = mt_get_gpio_dir_base(num); + gpio_state->ies = mt_get_gpio_ies_base(num); + +} + +VOID _wmt_dump_gpio_pre_regs(WMT_GPIO_STATE_INFO gpio_state) +{ + pr_info("PIN: [MODE] [PULL_SEL] [DIN] [DOUT] [PULL EN] [DIR] [IES]\n"); + pr_info("idx = %3d: %d %d %d %d %d %d %d\n", + gpio_state.gpio_num, gpio_state.mode, + gpio_state.pull_sel, gpio_state.in, + gpio_state.out, gpio_state.pull_en, + gpio_state.dir, gpio_state.ies); +} diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/wmt_gpio.h b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_gpio.h new file mode 100644 index 0000000000000..4e42dba212a15 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_gpio.h @@ -0,0 +1,127 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _WMT_GPIO_H_ +#define _WMT_GPIO_H_ + +#include +#include +#include +#include +#include +#include +#include "osal.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define DEFAULT_PIN_ID (0xffffffff) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_GPIO_PIN_ID { + GPIO_COMBO_LDO_EN_PIN = 0, + GPIO_COMBO_PMUV28_EN_PIN, + GPIO_COMBO_PMU_EN_PIN, + GPIO_COMBO_RST_PIN, + GPIO_COMBO_BGF_EINT_PIN, + GPIO_WIFI_EINT_PIN, + GPIO_COMBO_ALL_EINT_PIN, + GPIO_COMBO_URXD_PIN, + GPIO_COMBO_UTXD_PIN, + GPIO_PCM_DAICLK_PIN, + GPIO_PCM_DAIPCMIN_PIN, + GPIO_PCM_DAIPCMOUT_PIN, + GPIO_PCM_DAISYNC_PIN, + GPIO_COMBO_I2S_CK_PIN, + GPIO_COMBO_I2S_WS_PIN, + GPIO_COMBO_I2S_DAT_PIN, + GPIO_GPS_SYNC_PIN, + GPIO_GPS_LNA_PIN, + GPIO_CHIP_DEEP_SLEEP_PIN, + GPIO_CHIP_WAKE_UP_PIN, + GPIO_PIN_ID_MAX +} ENUM_GPIO_PIN_ID, *P_ENUM_GPIO_PIN_ID; + +typedef enum _ENUM_GPIO_STATE_ID { + GPIO_PULL_DIS = 0, + GPIO_PULL_DOWN, + GPIO_PULL_UP, + GPIO_OUT_LOW, + GPIO_OUT_HIGH, + GPIO_IN_DIS, + GPIO_IN_EN, + GPIO_IN_PULL_DIS, + GPIO_IN_PULLDOWN, + GPIO_IN_PULLUP, + GPIO_STATE_MAX, +} ENUM_GPIO_STATE_ID, *P_ENUM_GPIO_STATE_ID; + +typedef struct _GPIO_CTRL_STATE { + INT32 gpio_num; + struct pinctrl_state *gpio_state[GPIO_STATE_MAX]; +} GPIO_CTRL_STATE, *P_GPIO_CTRL_STATE; + +typedef struct _WMT_GPIO_STATE_INFO { + INT32 gpio_num; + INT32 mode; + INT32 pull_sel; + INT32 in; + INT32 out; + INT32 pull_en; + INT32 dir; + INT32 ies; +} WMT_GPIO_STATE_INFO; + +typedef struct _GPIO_CTRL_INFO { + struct pinctrl *pinctrl_info; + GPIO_CTRL_STATE gpio_ctrl_state[GPIO_PIN_ID_MAX]; +} GPIO_CTRL_INFO, *P_GPIO_CTRL_INFO; + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +extern const PUINT8 gpio_state_name[GPIO_PIN_ID_MAX][GPIO_STATE_MAX]; +extern const PUINT8 gpio_pin_name[GPIO_PIN_ID_MAX]; +extern GPIO_CTRL_INFO gpio_ctrl_info; + +extern int mt_get_gpio_mode_base(unsigned long pin); +extern int mt_get_gpio_pull_select_base(unsigned long pin); +extern int mt_get_gpio_in_base(unsigned long pin); +extern int mt_get_gpio_out_base(unsigned long pin); +extern int mt_get_gpio_pull_enable_base(unsigned long pin); +extern int mt_get_gpio_dir_base(unsigned long pin); +extern int mt_get_gpio_ies_base(unsigned long pin); + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +INT32 wmt_gpio_init(struct platform_device *pdev); +VOID _wmt_dump_gpio_regs(INT32 idx); +VOID _wmt_gpio_pre_regs(INT32 num, WMT_GPIO_STATE_INFO *gpio_state); +VOID _wmt_dump_gpio_pre_regs(WMT_GPIO_STATE_INFO gpio_state); +INT32 wmt_gpio_deinit(VOID); + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_main/core/btm_core.c b/drivers/misc/mediatek/connectivity/common/common_main/core/btm_core.c new file mode 100644 index 0000000000000..022e8c04d2726 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/core/btm_core.c @@ -0,0 +1,779 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#include +#include "osal_typedef.h" +#include "osal.h" +#include "stp_dbg.h" +#include "stp_core.h" +#include "btm_core.h" +#include "wmt_plat.h" +#include "wmt_step.h" +#include "wmt_detect.h" +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH +#include "connsys_debug_utility.h" +#endif +#include + +#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_PR_LOUD(fmt, arg...) \ +do { \ + if (gBtmDbgLevel >= STP_BTM_LOG_LOUD) \ + pr_info(PFX_BTM "%s: " fmt, __func__, ##arg); \ +} while (0) +#define STP_BTM_PR_DBG(fmt, arg...) \ +do { \ + if (gBtmDbgLevel >= STP_BTM_LOG_DBG) \ + pr_info(PFX_BTM "%s: " fmt, __func__, ##arg); \ +} while (0) +#define STP_BTM_PR_INFO(fmt, arg...) \ +do { \ + if (gBtmDbgLevel >= STP_BTM_LOG_INFO) \ + pr_info(PFX_BTM "[I]%s: " fmt, __func__, ##arg); \ +} while (0) +#define STP_BTM_PR_WARN(fmt, arg...) \ +do { \ + if (gBtmDbgLevel >= STP_BTM_LOG_WARN) \ + pr_warn(PFX_BTM "[W]%s: " fmt, __func__, ##arg); \ +} while (0) +#define STP_BTM_PR_ERR(fmt, arg...) \ +do { \ + if (gBtmDbgLevel >= STP_BTM_LOG_ERR) \ + pr_err(PFX_BTM "[E]%s(%d):ERROR! " fmt, __func__, __LINE__, ##arg); \ +} while (0) + +#define ASSERT(expr) + +MTKSTP_BTM_T stp_btm_i; +MTKSTP_BTM_T *stp_btm = &stp_btm_i; + +const PINT8 g_btm_op_name[] = { + "STP_OPID_BTM_RETRY", + "STP_OPID_BTM_RST", + "STP_OPID_BTM_DBG_DUMP", + "STP_OPID_BTM_DUMP_TIMEOUT", + "STP_OPID_BTM_POLL_CPUPCR", + "STP_OPID_BTM_PAGED_DUMP", + "STP_OPID_BTM_FULL_DUMP", + "STP_OPID_BTM_PAGED_TRACE", + "STP_OPID_BTM_FORCE_FW_ASSERT", +#if CFG_WMT_LTE_COEX_HANDLING + "STP_OPID_BTM_WMT_LTE_COEX", +#endif + "STP_OPID_BTM_ASSERT_TIMEOUT", + "STP_OPID_BTM_EMI_DUMP_END", + "STP_OPID_BTM_EXIT" +}; + +static VOID stp_btm_trigger_assert_timeout_handler(timer_handler_arg arg) +{ + ULONG data; + + GET_HANDLER_DATA(arg, data); + if (mtk_wcn_stp_coredump_start_get() == 0) + stp_btm_notify_assert_timeout_wq((MTKSTP_BTM_T *)data); +} + +static INT32 _stp_btm_handler(MTKSTP_BTM_T *stp_btm, P_STP_BTM_OP pStpOp) +{ + INT32 ret = -1; + /* core dump target, 0: aee; 1: netlink */ + INT32 dump_sink = mtk_wcn_stp_coredump_flag_get(); + + if (pStpOp == NULL) + 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: + if (mtk_wcn_stp_coredump_start_get() == 0) + stp_do_tx_timeout(); + ret = 0; + break; + + /*whole chip reset */ + case STP_OPID_BTM_RST: + STP_BTM_PR_INFO("whole chip reset start!\n"); + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC && + mtk_wcn_stp_coredump_flag_get() != 0 && chip_reset_only == 0) { +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + connsys_dedicated_log_flush_emi(); +#endif + stp_dbg_core_dump_flush(0, MTK_WCN_BOOL_FALSE); + } + STP_BTM_PR_INFO("....+\n"); + WMT_STEP_DO_ACTIONS_FUNC(STEP_TRIGGER_POINT_BEFORE_CHIP_RESET); + if (stp_btm->wmt_notify) { + stp_btm->wmt_notify(BTM_RST_OP); + ret = 0; + } else { + STP_BTM_PR_ERR("stp_btm->wmt_notify is NULL."); + ret = -1; + } + + STP_BTM_PR_INFO("whole chip reset end!\n"); + WMT_STEP_DO_ACTIONS_FUNC(STEP_TRIGGER_POINT_AFTER_CHIP_RESET); + break; + + case STP_OPID_BTM_DBG_DUMP: + /*Notify the wmt to get dump data */ + STP_BTM_PR_DBG("wmt dmp notification\n"); + set_user_nice(stp_btm->BTMd.pThread, -20); + ret = stp_dbg_core_dump(dump_sink); + set_user_nice(stp_btm->BTMd.pThread, 0); + break; + + case STP_OPID_BTM_DUMP_TIMEOUT: + /* append fake coredump end message */ + if (dump_sink == 2 && wmt_detect_get_chip_type() == WMT_CHIP_TYPE_COMBO) { + stp_dbg_set_coredump_timer_state(CORE_DUMP_DOING); + STP_BTM_PR_WARN("generate fake coredump message\n"); + stp_dbg_nl_send_data(FAKECOREDUMPEND, osal_sizeof(FAKECOREDUMPEND)); + } + stp_dbg_poll_cpupcr(5, 1, 1); + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_COMBO) { + /* Flush dump data, and reset compressor */ + STP_BTM_PR_INFO("Flush dump data\n"); + stp_dbg_core_dump_flush(0, MTK_WCN_BOOL_TRUE); + } + ret = mtk_wcn_stp_coredump_timeout_handle(); + break; +#if CFG_WMT_LTE_COEX_HANDLING + case STP_OPID_BTM_WMT_LTE_COEX: + ret = wmt_idc_msg_to_lte_handing(); + break; +#endif + case STP_OPID_BTM_ASSERT_TIMEOUT: + mtk_wcn_stp_assert_timeout_handle(); + ret = 0; + break; + case STP_OPID_BTM_EMI_DUMP_END: + STP_BTM_PR_INFO("emi dump end notification.\n"); + stp_dbg_stop_emi_dump(); + mtk_wcn_stp_ctx_restore(); + ret = 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_PR_WARN("!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_PR_DBG("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; + P_OSAL_OP pOp_latest = NULL; + P_OSAL_OP pOp_current = NULL; + INT32 flag_latest = 1; + INT32 flag_current = 1; + + if (!pOpQ || !pOp) { + STP_BTM_PR_WARN("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 (&stp_btm->rFreeOpQ == pOpQ) { + if (!RB_FULL(pOpQ)) + RB_PUT(pOpQ, pOp); + else + ret = -1; + } else if (pOp->op.opId == STP_OPID_BTM_RST || + pOp->op.opId == STP_OPID_BTM_ASSERT_TIMEOUT || + pOp->op.opId == STP_OPID_BTM_DUMP_TIMEOUT || + pOp->op.opId == STP_OPID_BTM_EMI_DUMP_END) { + if (!RB_FULL(pOpQ)) { + RB_PUT(pOpQ, pOp); + STP_BTM_PR_DBG("RB_PUT: 0x%x\n", pOp->op.opId); + } else + ret = -1; + } else { + pOp_current = stp_btm_get_current_op(stp_btm); + if (pOp_current) { + if (pOp_current->op.opId == STP_OPID_BTM_RST || + pOp_current->op.opId == STP_OPID_BTM_DUMP_TIMEOUT || + (pOp_current->op.opId == STP_OPID_BTM_ASSERT_TIMEOUT && + pOp->op.opId != STP_OPID_BTM_DBG_DUMP)) { + STP_BTM_PR_DBG("current: 0x%x\n", pOp_current->op.opId); + flag_current = 0; + } + } + + RB_GET_LATEST(pOpQ, pOp_latest); + if (pOp_latest) { + if (pOp_latest->op.opId == STP_OPID_BTM_RST || + pOp_latest->op.opId == STP_OPID_BTM_ASSERT_TIMEOUT || + pOp_latest->op.opId == STP_OPID_BTM_DUMP_TIMEOUT) { + STP_BTM_PR_DBG("latest: 0x%x\n", pOp_latest->op.opId); + flag_latest = 0; + } + if (pOp_latest->op.opId == pOp->op.opId +#if CFG_WMT_LTE_COEX_HANDLING + && pOp->op.opId != STP_OPID_BTM_WMT_LTE_COEX +#endif + ) { + flag_latest = 0; + STP_BTM_PR_DBG("With the latest a command repeat: latest 0x%x,current 0x%x\n", + pOp_latest->op.opId, pOp->op.opId); + } + } + if (flag_current && flag_latest) { + if (!RB_FULL(pOpQ)) { + RB_PUT(pOpQ, pOp); + STP_BTM_PR_DBG("RB_PUT: 0x%x\n", pOp->op.opId); + } else + ret = -1; + } else + ret = 0; + + } + + if (ret) { + STP_BTM_PR_DBG("RB_FULL(0x%p) %d ,rFreeOpQ = %p, rActiveOpQ = %p\n", + pOpQ, RB_COUNT(pOpQ), &stp_btm->rFreeOpQ, &stp_btm->rActiveOpQ); + osal_opq_dump_locked("FreeOpQ", &stp_btm->rFreeOpQ); + osal_opq_dump_locked("ActiveOpQ", &stp_btm->rActiveOpQ); + } + + osal_unlock_unsleepable_lock(&(stp_btm->wq_spinlock)); + return ret ? 0 : 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, 0, osal_sizeof(OSAL_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 wait_ret = -1; + + P_OSAL_SIGNAL pSignal = NULL; + + if (!stp_btm || !pOp) { + STP_BTM_PR_ERR("Input NULL pointer\n"); + return bRet; + } + do { + pSignal = &pOp->signal; + + if (pSignal->timeoutValue) { + pOp->result = -9; + osal_signal_init(&pOp->signal); + } + + /* Init ref_count to 2, as one is held by current thread, the second by btm thread */ + atomic_set(&pOp->ref_count, 2); + + /* put to active Q */ + bRet = _stp_btm_put_op(stp_btm, &stp_btm->rActiveOpQ, pOp); + if (bRet == 0) { + STP_BTM_PR_DBG("put active queue fail\n"); + atomic_dec(&pOp->ref_count); + break; + } + /* wake up wmtd */ + osal_trigger_event(&stp_btm->STPd_event); + + if (pSignal->timeoutValue == 0) { + bRet = 1; /* MTK_WCN_BOOL_TRUE; */ + break; + } + + /* check result */ + wait_ret = osal_wait_for_signal_timeout(&pOp->signal, &stp_btm->BTMd); + + STP_BTM_PR_DBG("wait completion:%d\n", wait_ret); + if (!wait_ret) { + STP_BTM_PR_ERR("wait completion timeout\n"); + /* TODO: how to handle it? retry? */ + } else { + if (pOp->result) + STP_BTM_PR_WARN("op(%d) result:%d\n", pOp->op.opId, pOp->result); + bRet = (pOp->result) ? 0 : 1; + } + } while (0); + + if (pOp && atomic_dec_and_test(&pOp->ref_count)) { + /* put Op back to freeQ */ + _stp_btm_put_op(stp_btm, &stp_btm->rFreeOpQ, pOp); + } + + return bRet; +} + +static INT32 _stp_btm_wait_for_msg(PVOID 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(PVOID pvData) +{ + MTKSTP_BTM_T *stp_btm = (MTKSTP_BTM_T *) pvData; + P_OSAL_OP pOp; + INT32 id; + INT32 result; + + if (!stp_btm) { + STP_BTM_PR_WARN("!stp_btm\n"); + return -1; + } + + for (;;) { + pOp = NULL; + + osal_wait_for_event(&stp_btm->STPd_event, _stp_btm_wait_for_msg, (PVOID) stp_btm); + + if (osal_thread_should_stop(&stp_btm->BTMd)) { + STP_BTM_PR_INFO("should stop now...\n"); + /* TODO: clean up active opQ */ + break; + } + + if (stp_btm->gDumplogflag) { + /* pr_warn("enter place1\n"); */ + stp_btm->gDumplogflag = 0; + continue; + } + + /* get Op from activeQ */ + pOp = _stp_btm_get_op(stp_btm, &stp_btm->rActiveOpQ); + + if (!pOp) { + STP_BTM_PR_WARN("get_lxop activeQ fail\n"); + continue; + } + osal_op_history_save(&stp_btm->op_history, pOp); + + id = osal_op_get_id(pOp); + + if ((id >= STP_OPID_BTM_NUM) || (id < 0)) { + STP_BTM_PR_WARN("abnormal opid id: 0x%x\n", id); + result = -1; + goto handler_done; + } + + STP_BTM_PR_DBG("======> lxop_get_opid = %d, %s, remaining count = *%d*\n", id, + g_btm_op_name[id], RB_COUNT(&stp_btm->rActiveOpQ)); + + osal_lock_unsleepable_lock(&(stp_btm->wq_spinlock)); + stp_btm_set_current_op(stp_btm, pOp); + osal_unlock_unsleepable_lock(&(stp_btm->wq_spinlock)); + result = _stp_btm_handler(stp_btm, &pOp->op); + osal_lock_unsleepable_lock(&(stp_btm->wq_spinlock)); + stp_btm_set_current_op(stp_btm, NULL); + osal_unlock_unsleepable_lock(&(stp_btm->wq_spinlock)); + + if (result) { + STP_BTM_PR_WARN("opid id(0x%x)(%s) error(%d)\n", id, + g_btm_op_name[id], result); + } + +handler_done: + + if (atomic_dec_and_test(&pOp->ref_count)) { + _stp_btm_put_op(stp_btm, &stp_btm->rFreeOpQ, pOp); + } else if (osal_op_is_wait_for_signal(pOp)) { + osal_op_raise_signal(pOp, result); + } + + if (id == STP_OPID_BTM_EXIT) { + break; + } else if (id == STP_OPID_BTM_RST) { + /* prevent multi reset case */ + stp_btm_reset_btm_wq(stp_btm); + } + } + + STP_BTM_PR_INFO("exits\n"); + + return 0; +} + +static inline INT32 _stp_btm_dump_type(MTKSTP_BTM_T *stp_btm, ENUM_STP_BTM_OPID_T opid) +{ + P_OSAL_OP pOp; + INT32 bRet; + INT32 retval; + + pOp = _stp_btm_get_free_op(stp_btm); + if (!pOp) { + STP_BTM_PR_WARN("get_free_lxop fail\n"); + return -1; /* break; */ + } + + pOp->op.opId = opid; + pOp->signal.timeoutValue = 0; + bRet = _stp_btm_put_act_op(stp_btm, pOp); + STP_BTM_PR_DBG("OPID(%d) type(%zd) bRet(%d)\n\n", pOp->op.opId, pOp->op.au4OpData[0], bRet); + retval = (bRet == 0) ? STP_BTM_OPERATION_FAIL : STP_BTM_OPERATION_SUCCESS; + + return retval; +} + +static inline INT32 _stp_btm_notify_wmt_rst_wq(MTKSTP_BTM_T *stp_btm) +{ + INT32 retval; + + if (stp_btm == NULL) + return STP_BTM_OPERATION_FAIL; + + retval = _stp_btm_dump_type(stp_btm, STP_OPID_BTM_RST); + return retval; +} + +static inline INT32 _stp_btm_notify_stp_retry_wq(MTKSTP_BTM_T *stp_btm) +{ + INT32 retval; + + if (stp_btm == NULL) + return STP_BTM_OPERATION_FAIL; + + retval = _stp_btm_dump_type(stp_btm, STP_OPID_BTM_RETRY); + return retval; +} + + +static inline INT32 _stp_btm_notify_coredump_timeout_wq(MTKSTP_BTM_T *stp_btm) +{ + INT32 retval; + + if (!stp_btm) + return STP_BTM_OPERATION_FAIL; + + stp_btm_reset_btm_wq(stp_btm); + retval = _stp_btm_dump_type(stp_btm, STP_OPID_BTM_DUMP_TIMEOUT); + return retval; +} + +static inline INT32 _stp_btm_notify_assert_timeout_wq(MTKSTP_BTM_T *stp_btm) +{ + INT32 retval; + + if (!stp_btm) + return STP_BTM_OPERATION_FAIL; + + retval = _stp_btm_dump_type(stp_btm, STP_OPID_BTM_ASSERT_TIMEOUT); + return retval; +} + +static inline INT32 _stp_btm_notify_wmt_dmp_wq(MTKSTP_BTM_T *stp_btm) +{ + + INT32 retval; + + if (stp_btm == NULL) + return STP_BTM_OPERATION_FAIL; + + /* Paged dump */ + retval = _stp_btm_dump_type(stp_btm, STP_OPID_BTM_DBG_DUMP); + + return retval; +} + +static inline INT32 _stp_btm_notify_emi_dump_end_wq(MTKSTP_BTM_T *stp_btm) +{ + INT32 retval; + + if (!stp_btm) + return STP_BTM_OPERATION_FAIL; + + retval = _stp_btm_dump_type(stp_btm, STP_OPID_BTM_EMI_DUMP_END); + 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_assert_timeout_wq(MTKSTP_BTM_T *stp_btm) +{ + return _stp_btm_notify_assert_timeout_wq(stp_btm); +} + +INT32 stp_btm_notify_wmt_dmp_wq(MTKSTP_BTM_T *stp_btm) +{ + return _stp_btm_notify_wmt_dmp_wq(stp_btm); +} + +INT32 stp_btm_notify_emi_dump_end(MTKSTP_BTM_T *stp_btm) +{ + return _stp_btm_notify_emi_dump_end_wq(stp_btm); +} + +INT32 stp_notify_btm_poll_cpupcr_ctrl(UINT32 en) +{ + return stp_dbg_poll_cpupcr_ctrl(en); +} + + +#if CFG_WMT_LTE_COEX_HANDLING + +static inline INT32 _stp_notify_btm_handle_wmt_lte_coex(MTKSTP_BTM_T *stp_btm) +{ + INT32 retval; + + if (stp_btm == NULL) + return STP_BTM_OPERATION_FAIL; + + retval = _stp_btm_dump_type(stp_btm, STP_OPID_BTM_WMT_LTE_COEX); + return retval; +} + +INT32 stp_notify_btm_handle_wmt_lte_coex(MTKSTP_BTM_T *stp_btm) +{ + return _stp_notify_btm_handle_wmt_lte_coex(stp_btm); +} + +#endif +MTKSTP_BTM_T *stp_btm_init(VOID) +{ + INT32 i = 0x0; + INT32 ret = -1; + + osal_unsleepable_lock_init(&stp_btm->wq_spinlock); + osal_event_init(&stp_btm->STPd_event); + stp_btm->wmt_notify = wmt_lib_btm_cb; + + RB_INIT(&stp_btm->rFreeOpQ, STP_BTM_OP_BUF_SIZE); + RB_INIT(&stp_btm->rActiveOpQ, STP_BTM_OP_BUF_SIZE); + + /* Put all to free Q */ + for (i = 0; i < STP_BTM_OP_BUF_SIZE; i++) { + osal_signal_init(&(stp_btm->arQue[i].signal)); + _stp_btm_put_op(stp_btm, &stp_btm->rFreeOpQ, &(stp_btm->arQue[i])); + } + + stp_btm_init_trigger_assert_timer(stp_btm); + osal_op_history_init(&stp_btm->op_history, 16); + + /*Generate PSM thread, to servie STP-CORE for packet retrying and core dump receiving */ + stp_btm->BTMd.pThreadData = (PVOID) stp_btm; + stp_btm->BTMd.pThreadFunc = (PVOID) _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_PR_ERR("osal_thread_create fail...\n"); + goto ERR_EXIT1; + } + + /* Start STPd thread */ + ret = osal_thread_run(&stp_btm->BTMd); + if (ret < 0) { + STP_BTM_PR_ERR("osal_thread_run FAILS\n"); + goto ERR_EXIT1; + } + + return stp_btm; + +ERR_EXIT1: + + return NULL; + +} + +INT32 stp_btm_deinit(MTKSTP_BTM_T *stp_btm) +{ + + INT32 ret = -1; + + STP_BTM_PR_INFO("btm deinit\n"); + + if (!stp_btm) + return STP_BTM_OPERATION_FAIL; + + ret = osal_thread_destroy(&stp_btm->BTMd); + if (ret < 0) { + STP_BTM_PR_ERR("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) +{ + /* pr_warn("%s:enter++\n",__func__); */ + if (stp_btm == NULL) { + osal_dbg_print("%s: NULL POINTER\n", __func__); + return -1; + } + stp_btm->gDumplogflag = 1; + osal_trigger_event(&stp_btm->STPd_event); + return 0; +} + +static inline INT32 _stp_btm_do_fw_assert(MTKSTP_BTM_T *stp_btm) +{ + INT32 status = -1; + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + + /* send assert command */ + STP_BTM_PR_INFO("trigger stp assert process\n"); + if (mtk_wcn_stp_is_sdio_mode()) { + bRet = stp_btm->wmt_notify(BTM_TRIGGER_STP_ASSERT_OP); + if (bRet == MTK_WCN_BOOL_FALSE) { + STP_BTM_PR_INFO("trigger stp assert failed\n"); + return status; + } + status = 0; + } else if (mtk_wcn_stp_is_btif_fullset_mode()) { +#if BTIF_RXD_BE_BLOCKED_DETECT + stp_dbg_is_btif_rxd_be_blocked(); +#endif + status = wmt_plat_force_trigger_assert(STP_FORCE_TRG_ASSERT_DEBUG_PIN); + } + + stp_btm_start_trigger_assert_timer(stp_btm); + + if (status == 0) + STP_BTM_PR_INFO("trigger stp assert succeed\n"); + + return status; +} + + +INT32 stp_notify_btm_do_fw_assert(MTKSTP_BTM_T *stp_btm) +{ + return _stp_btm_do_fw_assert(stp_btm); +} + +INT32 wmt_btm_trigger_reset(VOID) +{ + return stp_btm_notify_wmt_rst_wq(stp_btm); +} + +INT32 stp_btm_set_current_op(MTKSTP_BTM_T *stp_btm, P_OSAL_OP pOp) +{ + if (stp_btm) { + stp_btm->pCurOP = pOp; + STP_BTM_PR_DBG("pOp=0x%p\n", pOp); + return 0; + } + STP_BTM_PR_ERR("Invalid pointer\n"); + return -1; +} + +P_OSAL_OP stp_btm_get_current_op(MTKSTP_BTM_T *stp_btm) +{ + if (stp_btm) + return stp_btm->pCurOP; + STP_BTM_PR_ERR("Invalid pointer\n"); + return NULL; +} + +INT32 stp_btm_init_trigger_assert_timer(MTKSTP_BTM_T *stp_btm) +{ + stp_btm->trigger_assert_timer.timeoutHandler = stp_btm_trigger_assert_timeout_handler; + stp_btm->trigger_assert_timer.timeroutHandlerData = (ULONG)stp_btm; + stp_btm->timeout = 1000; + + return osal_timer_create(&stp_btm->trigger_assert_timer); +} + +INT32 stp_btm_start_trigger_assert_timer(MTKSTP_BTM_T *stp_btm) +{ + return osal_timer_start(&stp_btm->trigger_assert_timer, stp_btm->timeout); +} + +INT32 stp_btm_stop_trigger_assert_timer(MTKSTP_BTM_T *stp_btm) +{ + return osal_timer_stop(&stp_btm->trigger_assert_timer); +} + +VOID stp_btm_print_op_history(VOID) +{ + osal_op_history_print(&stp_btm->op_history, "_stp_btm_proc"); +} diff --git a/drivers/misc/mediatek/connectivity/common/common_main/core/include/btm_core.h b/drivers/misc/mediatek/connectivity/common/common_main/core/include/btm_core.h new file mode 100644 index 0000000000000..2b79f26948531 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/core/include/btm_core.h @@ -0,0 +1,154 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + + +#ifndef _BTM_CORE_H +#define _BTM_CORE_H + +#include "osal_typedef.h" +#include "osal.h" +#include "stp_wmt.h" +#include "wmt_plat.h" +#include "wmt_idc.h" +#include "osal.h" +#include "mtk_btif_exp.h" +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define STP_BTM_OPERATION_FAIL (-1) +#define STP_BTM_OPERATION_SUCCESS (0) + +#define STP_BTM_OP_BUF_SIZE (64) + +#define BTM_THREAD_NAME "mtk_stp_btm" +#define STP_PAGED_DUMP_TIME_LIMIT 3500 +#define STP_FULL_DUMP_TIME 3 +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_STP_BTM_OPID_T { + STP_OPID_BTM_RETRY = 0x0, + STP_OPID_BTM_RST = 0x1, + STP_OPID_BTM_DBG_DUMP = 0x2, + STP_OPID_BTM_DUMP_TIMEOUT = 0x3, + STP_OPID_BTM_POLL_CPUPCR = 0x4, + STP_OPID_BTM_PAGED_DUMP = 0x5, + STP_OPID_BTM_FULL_DUMP = 0x6, + STP_OPID_BTM_PAGED_TRACE = 0x7, + STP_OPID_BTM_FORCE_FW_ASSERT = 0x8, +#if CFG_WMT_LTE_COEX_HANDLING + STP_OPID_BTM_WMT_LTE_COEX = 0x9, +#endif + STP_OPID_BTM_ASSERT_TIMEOUT = 0xa, + STP_OPID_BTM_EMI_DUMP_END = 0xb, + 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 */ + P_OSAL_OP pCurOP; /* current op */ + INT32 gDumplogflag; + + /*wmt_notify */ + INT32 (*wmt_notify)(MTKSTP_BTM_WMT_OP_T); + + OSAL_TIMER trigger_assert_timer; + UINT32 timeout; + struct osal_op_history op_history; +} 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_assert_timeout_wq(MTKSTP_BTM_T *stp_btm); +INT32 stp_btm_notify_wmt_dmp_wq(MTKSTP_BTM_T *stp_btm); +INT32 stp_btm_notify_emi_dump_end(MTKSTP_BTM_T *stp_btm); +INT32 stp_btm_deinit(MTKSTP_BTM_T *stp_btm); +INT32 stp_btm_reset_btm_wq(MTKSTP_BTM_T *stp_btm); +INT32 stp_notify_btm_poll_cpupcr(MTKSTP_BTM_T *stp_btm, UINT32 times, UINT32 sleep); +INT32 stp_notify_btm_poll_cpupcr_ctrl(UINT32 en); +INT32 stp_btm_sort_btm_wq(MTKSTP_BTM_T *stp_btm); +INT32 stp_notify_btm_dump(MTKSTP_BTM_T *stp_btm); +INT32 stp_notify_btm_do_fw_assert(MTKSTP_BTM_T *stp_btm); +INT32 stp_notify_btm_handle_wmt_lte_coex(MTKSTP_BTM_T *stp_btm); +INT32 wcn_psm_flag_trigger_collect_ftrace(void); +#if BTIF_RXD_BE_BLOCKED_DETECT +INT32 wcn_btif_rxd_blocked_collect_ftrace(void); +MTK_WCN_BOOL is_btif_rxd_be_blocked(void); +#endif + +INT32 wmt_btm_trigger_reset(VOID); +INT32 stp_btm_init_trigger_assert_timer(MTKSTP_BTM_T *stp_btm); +INT32 stp_btm_start_trigger_assert_timer(MTKSTP_BTM_T *stp_btm); +INT32 stp_btm_stop_trigger_assert_timer(MTKSTP_BTM_T *stp_btm); +INT32 stp_btm_set_current_op(MTKSTP_BTM_T *stp_btm, P_OSAL_OP pOp); +P_OSAL_OP stp_btm_get_current_op(MTKSTP_BTM_T *stp_btm); + +MTKSTP_BTM_T *stp_btm_init(VOID); +extern unsigned int chip_reset_only; + +VOID stp_btm_print_op_history(VOID); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_main/core/include/dbg_core.h b/drivers/misc/mediatek/connectivity/common/common_main/core/include/dbg_core.h new file mode 100644 index 0000000000000..d57740edfeae6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/core/include/dbg_core.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + + +#ifndef _DBG_CORE_H +#define _DBG_CORE_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_main/core/include/psm_core.h b/drivers/misc/mediatek/connectivity/common/common_main/core/include/psm_core.h new file mode 100644 index 0000000000000..393d0f41227dd --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/core/include/psm_core.h @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \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 "stp_wmt.h" +#include "osal.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 || WMT_SDIO_MODE) +#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 30 /* temporary for stress testing */ +#define STP_PSM_IDLE_TIME_SLEEP_1000 1000 /* for high speed transmission e.g. BT OPP*/ +#define STP_PSM_SDIO_IDLE_TIME_SLEEP 100 /* temporary for SDIO stress testing */ +#define STP_PSM_WAIT_EVENT_TIMEOUT 18500 /* set same as MAX_FUNC_ON_TIME */ + +#if 0 +#define STP_PSM_WMT_EVENT_SLEEP_EN (0x1UL << 0) +#define STP_PSM_WMT_EVENT_WAKEUP_EN (0x1UL << 1) +#define STP_PSM_BLOCK_DATA_EN (0x1UL << 2) +#define STP_PSM_WMT_EVENT_DISABLE_MONITOR (0x1UL << 3) +#define STP_PSM_WMT_EVENT_ROLL_BACK_EN (0x1UL << 4) +#define STP_PSM_RESET_EN (0x1UL << 5) +#define STP_PSM_WMT_EVENT_HOST_WAKEUP_EN (0x1UL << 6) +#define STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY (0x1UL << 7) +#define STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY (0x1UL << 8) +#endif + +#define STP_PSM_WMT_EVENT_SLEEP_EN (0) +#define STP_PSM_WMT_EVENT_WAKEUP_EN (1) +#define STP_PSM_BLOCK_DATA_EN (2) +#define STP_PSM_WMT_EVENT_DISABLE_MONITOR (3) +#define STP_PSM_WMT_EVENT_ROLL_BACK_EN (4) +#define STP_PSM_RESET_EN (5) +#define STP_PSM_WMT_EVENT_HOST_WAKEUP_EN (6) +#define STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY (7) +#define STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY (8) + +#define STP_PSM_DBG_SIZE (48) + +/* 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 = 1, + INACT = 2, + INACT_ACT = 3, + STP_PSM_MAX_STATE = 4, +} 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) (PUINT8 buffer, UINT32 length, UINT8 type); + +typedef OSAL_OP_DAT STP_OP; +typedef P_OSAL_OP_DAT P_STP_OP; +#if 0 +#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 +#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 */ + OSAL_BIT_OP_VAR flag; + + /* in normal cases, sleep op is always enabled; but in error cases, we can't execute sleep cmd, + * Eg: FW assert, core dump + */ + INT32 sleep_en; + +/* OSAL_UNSLEEPABLE_LOCK flagSpinlock; */ + INT32 idle_time_to_sleep; + OSAL_WAKE_LOCK wake_lock; + OSAL_TIMER psm_timer; /*monitor if active */ + OSAL_EVENT wait_wmt_q; + OSAL_FIFO hold_fifo; + + /* PSM_FIFO_LOCK hold_fifo_lock; */ + OSAL_SLEEPABLE_LOCK hold_fifo_spinlock_global; + + 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)(PUINT8 buffer, UINT32 length, UINT8 type); + MTK_WCN_BOOL (*is_wmt_quick_ps_support)(VOID); + INT32 (*update_wmt_fw_patch_chip_rst)(VOID); + UINT8 out_buf[STP_PSM_TX_SIZE]; + struct osal_op_history op_history; +} MTKSTP_PSM_T; + +typedef struct { + UINT32 prev_flag; + UINT32 cur_flag; + UINT32 line_num; + UINT32 package_no; + UINT32 sec; + UINT32 usec; + UINT32 pid; + UINT64 l_sec; + ULONG l_nsec; +} STP_PSM_ENTRY_T; + +typedef struct stp_psm_record { + STP_PSM_ENTRY_T queue[STP_PSM_DBG_SIZE]; + UINT32 in; + UINT32 out; + UINT32 size; + OSAL_UNSLEEPABLE_LOCK lock; +} STP_PSM_RECORD_T; + +typedef struct stp_psm_opid_record { + STP_PSM_ENTRY_T queue[STP_PSM_DBG_SIZE]; + UINT32 in; + UINT32 out; + UINT32 size; + OSAL_UNSLEEPABLE_LOCK lock; +} STP_PSM_OPID_RECORD, *P_STP_PSM_OPID_RECORD; +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#define PSM_USE_COUNT_PACKAGE 0 + +#if PSM_USE_COUNT_PACKAGE +#define MTK_COMBO_PSM_RX_TH_DEFAULT (1600) +#define MTK_COMBO_PSM_TX_TH_DEFAULT (300) +INT32 stp_psm_disable_by_tx_rx_density(MTKSTP_PSM_T *stp_psm, INT32 dir); +#else +#define SAMPLE_DURATION 1 /*1 second */ +#define RTX_SPEED_THRESHOLD 50000 /*50KB/s */ +INT32 stp_psm_disable_by_tx_rx_density(MTKSTP_PSM_T *stp_psm, INT32 dir, INT32 length); +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*stp-psm external function*/ +INT32 stp_psm_notify_stp(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_ACTION_T action); +INT32 stp_psm_notify_wmt_wakeup(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_notify_wmt_sleep(MTKSTP_PSM_T *stp_psm); + +INT32 stp_psm_start_monitor(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_is_to_block_traffic(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_is_disable(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_has_pending_data(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_release_data(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_hold_data(MTKSTP_PSM_T *stp_psm, + const PUINT8 buffer, const UINT32 len, const UINT8 type); +INT32 stp_psm_do_wakeup(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_reset(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_disable(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_enable(MTKSTP_PSM_T *stp_psm, INT32 idle_time_to_sleep); +struct mtk_stp_psm *stp_psm_init(void); +INT32 stp_psm_deinit(MTKSTP_PSM_T *stp_psm); +MTK_WCN_BOOL mtk_wcn_stp_psm_dbg_level(INT32 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); + +VOID stp_psm_print_op_history(VOID); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_main/core/include/stp_core.h b/drivers/misc/mediatek/connectivity/common/common_main/core/include/stp_core.h new file mode 100644 index 0000000000000..2099131738bed --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/core/include/stp_core.h @@ -0,0 +1,699 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + +#ifndef _STP_CORE_H +#define _STP_CORE_H +#include "osal_typedef.h" +#include "osal.h" +#include "stp_exp.h" +#include "psm_core.h" +#include "btm_core.h" +#include "stp_btif.h" +#include "stp_wmt.h" +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#define WMT_LTE_COEX_FLAG (0x16) +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define CONFIG_POWER_SAVING_SUPPORT +#if (WMT_UART_RX_MODE_WORK || WMT_SDIO_MODE) +#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 INT32 gStpDbgLvl; + +#define STP_DBG_FUNC(fmt, arg...) do {\ + if (gStpDbgLvl >= STP_LOG_DBG)\ + osal_warn_print(PFX "%s: " fmt, __func__, ##arg);\ +} while (0) + +#define STP_INFO_FUNC(fmt, arg...) do {\ + if (gStpDbgLvl >= STP_LOG_INFO)\ + osal_warn_print(PFX "%s:[I] " fmt, __func__, ##arg);\ +} while (0) + +#define STP_WARN_RATELIMITED_FUNC(fmt, arg...) do {\ + static DEFINE_RATELIMIT_STATE(_rs, HZ, 5);\ + if (gStpDbgLvl >= STP_LOG_WARN && __ratelimit(&_rs))\ + osal_warn_print(PFX "%s:[W] " fmt, __func__, ##arg);\ +} while (0) + +#define STP_WARN_FUNC(fmt, arg...) do {\ + if (gStpDbgLvl >= STP_LOG_WARN)\ + osal_warn_print(PFX "%s:[W] " fmt, __func__, ##arg);\ +} while (0) + +#define STP_ERR_FUNC(fmt, arg...) do {\ + if (gStpDbgLvl >= STP_LOG_ERR)\ + osal_err_print(PFX "%s:[E] " fmt, __func__, ##arg);\ +} while (0) + +#define STP_TRC_FUNC(f) do {\ + if (gStpDbgLvl >= STP_LOG_DBG)\ + osal_warn_print(PFX "<%s> <%d>\n", __func__, __LINE__);\ +} while (0) + +#define STP_DUMP_PACKET_HEAD(a, b, c) do {\ + if (gStpDbgLvl >= STP_LOG_PKHEAD)\ + stp_dump_data(a, b, c);\ +} while (0) + +#define STP_TRACE_FUNC(fmt, arg...) do {\ + if (gStpDbgLvl >= STP_LOG_DBG)\ + osal_warn_print(PFX "%s: " fmt, __func__, ##arg);\ +} while (0) + +#define STP_MODE_BIT(x) (0x1UL << x) +#define MTKSTP_UART_FULL_MODE STP_MODE_BIT(0) +#define MTKSTP_UART_MAND_MODE STP_MODE_BIT(1) +#define MTKSTP_BTIF_FULL_MODE STP_MODE_BIT(2) +#define MTKSTP_BTIF_MAND_MODE STP_MODE_BIT(3) +#define MTKSTP_SDIO_MODE STP_MODE_BIT(4) + +#define MTKSTP_BUFFER_SIZE (16384) +#define PARSER_CORE_DUMP_NUM 200 +#define CORE_DUMP_NUM 100 +/*To check function driver's status by the the interface*/ +/*Operation definition*/ +#define OP_FUNCTION_ACTIVE 0 + +/*Driver's status*/ +#define STATUS_OP_INVALID 0 +#define STATUS_FUNCTION_INVALID 1 + +#define STATUS_FUNCTION_ACTIVE 31 +#define STATUS_FUNCTION_INACTIVE 32 + +#define MTKSTP_CRC_SIZE (2) +#define MTKSTP_HEADER_SIZE (4) +#define MTKSTP_SEQ_SIZE (8) + +/*#define MTKSTP_WINSIZE (4)*/ +#define MTKSTP_WINSIZE (7) +#define MTKSTP_TX_TIMEOUT (180) /*TODO: Baudrate to decide this */ +#define MTKSTP_RETRY_LIMIT (10) + +#define INDEX_INC(idx) \ +{ \ + idx++; \ + idx &= 0x7; \ +} + +#define INDEX_DEC(idx) \ +{ \ + idx--; \ + idx &= 0x7; \ +} + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef INT32(*IF_TX) (const PUINT8 data, const UINT32 size, PUINT32 written_size); +typedef INT32(*RX_HAS_PENDING_DATA) (VOID); +typedef INT32(*TX_HAS_PENDING_DATA) (VOID); +typedef P_OSAL_THREAD(*RX_THREAD_GET) (VOID); +/* event/signal */ +typedef INT32(*EVENT_SET) (UINT8 function_type); +typedef INT32(*EVENT_TX_RESUME) (UINT8 winspace); +typedef INT32(*FUNCTION_STATUS) (UINT8 type, UINT8 op); +typedef INT32(*WMT_NOTIFY_FUNC_T) (UINT32 action); +typedef INT32(*BTM_NOTIFY_WMT_FUNC_T) (INT32); + +#if CFG_STP_CORE_CTX_SPIN_LOCK +typedef OSAL_UNSLEEPABLE_LOCK STP_CTX_LOCK, *PSTP_CTX_LOCK; +#else +typedef OSAL_SLEEPABLE_LOCK STP_CTX_LOCK, *PSTP_CTX_LOCK; +#endif + +typedef struct { + /* common interface */ + IF_TX cb_if_tx; + RX_HAS_PENDING_DATA cb_rx_has_pending_data; + TX_HAS_PENDING_DATA cb_tx_has_pending_data; + RX_THREAD_GET cb_rx_thread_get; + /* 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; + UINT8 tx_timeout_loop; /* for extend tx timeout */ + UINT8 rx_resync; /* num of 7f7f7f7f before expected_rxseq pkt, indicates if recv series of resync pkt */ + UINT8 rx_resync_seq; /* last resync pkg's seq (0xFF if not set), only valid if rx_resync != 0 */ +} 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 assert_info_cnt; + 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; + UINT8 f_emidump; + /* Flag to identify Blueztooth is Bluez/or MTK Stack */ + MTK_WCN_BOOL f_bluez; + MTK_WCN_BOOL f_dbg_en; + MTK_WCN_BOOL f_autorst_en; + + + + /* Flag to identify STP by SDIO or UART */ + UINT32 f_mode; + + /* Flag to indicate the last WMT CLOSE */ + UINT32 f_wmt_last_close; + /* Flag to indicate evt err has triggered assert or not */ + UINT32 f_evt_err_assert; + /* Flag to indicate assert process is ongoing or not */ + UINT32 f_assert_in_progress; + + /* Flag to identify support GPSL5 */ + MTK_WCN_BOOL f_gpsl5_en; +} 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(PUINT8 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_is_enable +* DESCRIPTION +* get STP enable/disable status +* PARAMETERS +* none. +* RETURNS +* INT32 0 = disable, 1 = enable +*****************************************************************************/ +extern INT32 mtk_wcn_stp_is_enable(VOID); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_ready +* DESCRIPTION +* ready/non-ready STP +* PARAMETERS +* value [IN] 0 = non-ready, others = ready +* RETURNS +* INT32 0 = success, others = error +*****************************************************************************/ +extern INT32 mtk_wcn_stp_ready(INT32 value); + + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_coredump_start_ctrl +* DESCRIPTION +* set f/w assert flag in STP context +* PARAMETERS +* value [IN] 0=assert end, others=assert begins +* RETURNS +* INT32 0=success, others=error +*****************************************************************************/ +extern INT32 mtk_wcn_stp_coredump_start_ctrl(UINT32 value); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_coredump_start_get +* DESCRIPTION +* get f/w assert flag in STP context +* PARAMETERS +* VOID +* RETURNS +* INT32 0= f/w assert flag is not set, others=f/w assert flag is set +*****************************************************************************/ +extern INT32 mtk_wcn_stp_coredump_start_get(VOID); + + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_send_data_raw +* DESCRIPTION +* send raw data to common interface, bypass STP +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* type [IN] subfunction type +* RETURNS +* INT32 length transmitted +*****************************************************************************/ +extern INT32 mtk_wcn_stp_send_data_raw(const PUINT8 buffer, const UINT32 length, const UINT8 type); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_set_sdio_mode +* DESCRIPTION +* Set stp for SDIO mode +* PARAMETERS +* sdio_flag [IN] sdio mode flag (TRUE:SDIO mode, FALSE:UART mode) +* RETURNS +* void +*****************************************************************************/ +extern VOID mtk_wcn_stp_set_mode(UINT32 sdio_flag); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_uart_fullset_mode +* DESCRIPTION +* Is stp use UART Fullset mode? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:UART Fullset, FALSE:UART Fullset +*****************************************************************************/ +extern MTK_WCN_BOOL mtk_wcn_stp_is_uart_fullset_mode(VOID); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_uart_mand_mode +* DESCRIPTION +* Is stp use UART Mandatory mode? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:UART Mandatory, FALSE:UART Mandatory +*****************************************************************************/ +extern MTK_WCN_BOOL mtk_wcn_stp_is_uart_mand_mode(VOID); + +extern MTK_WCN_BOOL mtk_wcn_stp_is_uart_mand_mode(VOID); +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_btif_fullset_mode +* DESCRIPTION +* Is stp use BTIF Fullset mode? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:BTIF Fullset, FALSE:BTIF Fullset +*****************************************************************************/ +extern MTK_WCN_BOOL mtk_wcn_stp_is_btif_fullset_mode(VOID); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_btif_mand_mode +* DESCRIPTION +* Is stp use BTIF Mandatory mode? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:BTIF Mandatory, FALSE:BTIF Mandatory +*****************************************************************************/ +extern MTK_WCN_BOOL mtk_wcn_stp_is_btif_mand_mode(void); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_sdio_mode +* DESCRIPTION +* Is stp use SDIO mode? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:SDIO mode, FALSE:UART mode +*****************************************************************************/ +extern MTK_WCN_BOOL mtk_wcn_stp_is_sdio_mode(VOID); + + +/***************************************************************************** +* FUNCTION +* stp_send_inband_reset +* DESCRIPTION +* To sync to oringnal stp state with f/w stp +* PARAMETERS +* none. +* RETURNS +* none +*****************************************************************************/ +extern VOID mtk_wcn_stp_inband_reset(VOID); + +/***************************************************************************** +* FUNCTION +* stp_send_inband_reset +* DESCRIPTION +* To send testing command to chip +* PARAMETERS +* none. +* RETURNS +* none +*****************************************************************************/ +extern VOID mtk_wcn_stp_test_cmd(INT32 no); + +/***************************************************************************** +* FUNCTION +* stp_send_inband_reset +* DESCRIPTION +* To control STP debugging mechanism +* PARAMETERS +* func_no: function control, func_op: dumpping filer, func_param: dumpping parameter +* RETURNS +* none +*****************************************************************************/ +extern VOID mtk_wcn_stp_debug_ctrl(INT32 func_no, INT32 func_op, INT32 func_param); +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_flush +* DESCRIPTION +* flush all stp context +* PARAMETERS +* none. +* RETURNS +* none +*****************************************************************************/ +extern VOID mtk_wcn_stp_flush_context(VOID); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_rx_queue +* DESCRIPTION +* flush all stp rx queue +* PARAMETERS +* none. +* RETURNS +* none +*****************************************************************************/ +extern VOID mtk_wcn_stp_flush_rx_queue(UINT32 type); + +/***************************************************************************** +* FUNCTION +* set stp debugging mdoe +* DESCRIPTION +* set stp debugging mdoe +* PARAMETERS +* dbg_mode: switch to dbg mode ? +* RETURNS +* void +*****************************************************************************/ +extern VOID mtk_wcn_stp_set_dbg_mode(MTK_WCN_BOOL dbg_mode); + +/***************************************************************************** +* FUNCTION +* set stp auto reset mdoe +* DESCRIPTION +* set stp auto reset mdoe +* PARAMETERS +* auto_rst: switch to auto reset mode ? +* RETURNS +* void +*****************************************************************************/ +extern VOID mtk_wcn_stp_set_auto_rst(MTK_WCN_BOOL auto_rst); + +/*stp_psm support*/ + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_psm_notify_stp +* DESCRIPTION +* WMT notification to STP that power saving job is done or not +* PARAMETERS +* +* RETURNS +* 0: Sccuess Negative value: Fail +*****************************************************************************/ +extern INT32 mtk_wcn_stp_psm_notify_stp(const MTKSTP_PSM_ACTION_T action); + +extern INT32 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 INT32 mtk_wcn_stp_psm_enable(INT32 idle_time_to_sleep); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_psm_disable +* DESCRIPTION +* disable STP PSM +* PARAMETERS +* void +* RETURNS +* 0: Sccuess Negative value: Fail +*****************************************************************************/ +extern INT32 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 INT32 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 INT32 mtk_wcn_stp_btm_get_dmp(PINT8 buf, PINT32 len); + +extern INT32 mtk_wcn_stp_dbg_enable(VOID); + +extern INT32 mtk_wcn_stp_dbg_disable(VOID); + +extern VOID mtk_wcn_stp_set_if_tx_type(ENUM_STP_TX_IF_TYPE stp_if_type); + +extern INT32 mtk_wcn_sys_if_rx(PUINT8 data, INT32 size); + +extern MTK_WCN_BOOL mtk_wcn_stp_dbg_level(INT32 dbglevel); + +extern INT32 mtk_wcn_stp_dbg_dump_package(VOID); + +extern INT32 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_emi_dump_flag_ctrl(UINT32 on); +extern INT32 mtk_wcn_stp_emi_dump_flag_get(VOID); + +extern INT32 mtk_wcn_stp_set_wmt_last_close(UINT32 value); +extern INT32 mtk_wcn_stp_is_wmt_last_close(VOID); + +/*stp btif API declared*/ +extern INT32 mtk_wcn_stp_open_btif(VOID); +extern INT32 mtk_wcn_stp_close_btif(VOID); +extern INT32 mtk_wcn_stp_rxcb_register(MTK_WCN_BTIF_RX_CB rx_cb); +extern INT32 mtk_wcn_stp_tx(UINT8 *pBuf, UINT32 len, UINT32 *written_len); +extern INT32 mtk_wcn_stp_wakeup_consys(VOID); +extern INT32 mtk_wcn_stp_dpidle_ctrl(UINT32 en_flag); +extern INT32 mtk_wcn_stp_lpbk_ctrl(enum _ENUM_BTIF_LPBK_MODE_ mode); +extern INT32 mtk_wcn_stp_logger_ctrl(enum _ENUM_BTIF_DBG_ID_ flag); +extern VOID mtk_wcn_stp_ctx_save(VOID); +extern VOID mtk_wcn_stp_ctx_restore(VOID); + +extern INT32 mtk_wcn_stp_wmt_trg_assert(VOID); +extern UINT32 mtk_wcn_stp_get_wmt_trg_assert(VOID); +extern VOID mtk_wcn_stp_set_wmt_trg_assert(UINT32 value); +extern INT32 mtk_wcn_stp_assert_timeout_handle(VOID); +extern INT32 mtk_wcn_stp_coredump_timeout_handle(VOID); +extern VOID mtk_wcn_stp_dbg_pkt_log(INT32 type, INT32 dir); + +extern INT32 mtk_wcn_sys_if_rx(UINT8 *data, INT32 size); + +/* + * API to get/set assert process is ongoing. + * It includes assert, coredump and chip reset process. + */ +extern VOID mtk_wcn_stp_assert_flow_ctrl(UINT32 on); +extern UINT32 mtk_wcn_stp_assert_flow_get(VOID); + +extern VOID mtk_wcn_stp_set_support_gpsl5(MTK_WCN_BOOL support_gpsl5); +extern INT32 mtk_wcn_stp_is_support_gpsl5(VOID); + +VOID mtk_stp_sdio_retry_flag_ctrl(INT32 flag); +VOID mtk_stp_dbg_sdio_retry_flag_ctrl(INT32 flag); +INT32 mtk_stp_sdio_retry_flag_get(VOID); +VOID mtk_stp_dump_sdio_register(VOID); +VOID mtk_stp_notify_emi_dump_end(VOID); +INT32 mtk_stp_check_rx_has_pending_data(VOID); +INT32 mtk_stp_dbg_dmp_append(PUINT8 buf, INT32 max_len); +P_OSAL_THREAD mtk_stp_rx_thread_get(VOID); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _STP_CORE_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/core/include/stp_wmt.h b/drivers/misc/mediatek/connectivity/common/common_main/core/include/stp_wmt.h new file mode 100644 index 0000000000000..63d237a058b22 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/core/include/stp_wmt.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \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_TRIGGER_STP_ASSERT_OP = 3, + 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); + +extern INT32 wmt_lib_ps_set_idle_time(UINT32 psIdleTime); + +extern INT32 wmt_lib_update_fw_patch_chip_rst(VOID); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _STP_WMT_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/core/include/wmt_conf.h b/drivers/misc/mediatek/connectivity/common/common_main/core/include/wmt_conf.h new file mode 100644 index 0000000000000..99788d3d2c63a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/core/include/wmt_conf.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \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_SOC "WMT_SOC.cfg" + +/******************************************************************************* +* 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 PINT8 name); +INT32 wmt_conf_deinit(VOID); + +#endif /* _WMT_CONF_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/core/include/wmt_core.h b/drivers/misc/mediatek/connectivity/common/common_main/core/include/wmt_core.h new file mode 100644 index 0000000000000..7ac2b51cdb6b6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/core/include/wmt_core.h @@ -0,0 +1,585 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \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 "wmt_ctrl.h" +#include "wmt_exp.h" +#include "wmt_plat.h" +#include "osal.h" +/******************************************************************************* +* 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 + +#if defined(MT6630) +#define CFG_CORE_MT6630_SUPPORT 1 /* whether MT6630 is supported or not */ +#else +#define CFG_CORE_MT6630_SUPPORT 1 /* whether MT6630 is supported or not */ +#endif + +#if defined(MT6632) +#define CFG_CORE_MT6632_SUPPORT 1 /* whether MT6632 is supported or not */ +#else +#define CFG_CORE_MT6632_SUPPORT 1 /* whether MT6632 is supported or not */ +#endif + +#define CFG_CORE_SOC_SUPPORT 1 +/* TODO:[ChangeFeature][George] move this definition outside so that wmt_dev can remove wmt_core.h inclusion. */ +#define defaultPatchName "mt66xx_patch_hdr.bin" + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define BCNT_PATCH_BUF_HEADROOM (8) + +#define BCNT_PATCH_BUF_CHECKSUM (2) + +#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_BTIF = 2, + WMT_HIF_MAX +} ENUM_WMT_HIF_T, *P_ENUM_WMT_HIF_T; + +#if 0 /* [George] moved to wmt_exp.h for hif_sdio's use */ +typedef enum { + WMT_SDIO_SLOT_INVALID = 0, + WMT_SDIO_SLOT_SDIO1 = 1, /* Wi-Fi dedicated SDIO1 */ + WMT_SDIO_SLOT_SDIO2 = 2, + WMT_SDIO_SLOT_MAX +} WMT_SDIO_SLOT_NUM; + +typedef enum { + WMT_SDIO_FUNC_STP = 0, + WMT_SDIO_FUNC_WIFI = 1, + WMT_SDIO_FUNC_MAX +} WMT_SDIO_FUNC_TYPE; +#endif + +typedef enum _ENUM_WMT_OPID_T { + WMT_OPID_HIF_CONF = 0, + WMT_OPID_PWR_ON = 1, + WMT_OPID_PWR_OFF = 2, + WMT_OPID_FUNC_ON = 3, + WMT_OPID_FUNC_OFF = 4, + WMT_OPID_REG_RW = 5, /* TODO:[ChangeFeature][George] is this OP obsoleted? */ + WMT_OPID_EXIT = 6, + WMT_OPID_PWR_SV = 7, + WMT_OPID_DSNS = 8, + WMT_OPID_LPBK = 9, + WMT_OPID_CMD_TEST = 10, + WMT_OPID_HW_RST = 11, + WMT_OPID_SW_RST = 12, + WMT_OPID_BAUD_RST = 13, + WMT_OPID_STP_RST = 14, + WMT_OPID_THERM_CTRL = 15, + WMT_OPID_EFUSE_RW = 16, + WMT_OPID_GPIO_CTRL = 17, + WMT_OPID_SDIO_CTRL = 18, + WMT_OPID_FW_COREDMP = 19, + WMT_OPID_GPIO_STATE = 20, + WMT_OPID_BGW_DS = 21, + WMT_OPID_SET_MCU_CLK = 22, + WMT_OPID_ADIE_LPBK_TEST = 23, +#ifdef CONFIG_MTK_COMBO_ANT + WMT_OPID_ANT_RAM_DOWN = 24, + WMT_OPID_ANT_RAM_STA_GET = 25, +#endif +#if CFG_WMT_LTE_COEX_HANDLING + WMT_OPID_IDC_MSG_HANDLING = 26, +#endif + WMT_OPID_TRIGGER_STP_ASSERT = 27, + WMT_OPID_FLASH_PATCH_DOWN = 28, + WMT_OPID_FLASH_PATCH_VER_GET = 29, + WMT_OPID_UTC_TIME_SYNC = 30, + WMT_OPID_FW_LOG_CTRL = 31, + WMT_OPID_WLAN_PROBE = 32, + WMT_OPID_WLAN_REMOVE = 33, + WMT_OPID_GPS_MCU_CTRL = 34, + WMT_OPID_TRY_PWR_OFF = 35, + WMT_OPID_BLANK_STATUS_CTRL = 36, + WMT_OPID_MET_CTRL = 37, + WMT_OPID_GPS_SUSPEND = 38, + WMT_OPID_GET_CONSYS_STATE = 39, + 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); + +struct WMT_BYTE_ARRAY { + UINT32 size; + PUINT8 data; +}; + +typedef struct _WMT_GEN_CONF { + UINT8 cfgExist; + + UINT8 coex_wmt_ant_mode; + UINT8 coex_wmt_ant_mode_ex; + UINT8 coex_wmt_ext_component; + UINT8 coex_wmt_wifi_time_ctl; + UINT8 coex_wmt_ext_pta_dev_on; + /*combo chip and LTE coex filter mode setting */ + UINT8 coex_wmt_filter_mode; + + UINT8 coex_bt_rssi_upper_limit; + UINT8 coex_bt_rssi_mid_limit; + UINT8 coex_bt_rssi_lower_limit; + UINT8 coex_bt_pwr_high; + UINT8 coex_bt_pwr_mid; + UINT8 coex_bt_pwr_low; + + UINT8 coex_wifi_rssi_upper_limit; + UINT8 coex_wifi_rssi_mid_limit; + UINT8 coex_wifi_rssi_lower_limit; + UINT8 coex_wifi_pwr_high; + UINT8 coex_wifi_pwr_mid; + UINT8 coex_wifi_pwr_low; + + UINT8 coex_ext_pta_hi_tx_tag; + UINT8 coex_ext_pta_hi_rx_tag; + UINT8 coex_ext_pta_lo_tx_tag; + UINT8 coex_ext_pta_lo_rx_tag; + UINT16 coex_ext_pta_sample_t1; + UINT16 coex_ext_pta_sample_t2; + UINT8 coex_ext_pta_wifi_bt_con_trx; + + UINT32 coex_misc_ext_pta_on; + UINT32 coex_misc_ext_feature_set; + /*GPS LNA setting */ + UINT8 wmt_gps_lna_pin; + UINT8 wmt_gps_lna_enable; + /*GPS HW suspend setting */ + UINT8 wmt_gps_suspend_ctrl; + /*Power on sequence */ + UINT8 pwr_on_rtc_slot; + UINT8 pwr_on_ldo_slot; + UINT8 pwr_on_rst_slot; + UINT8 pwr_on_off_slot; + UINT8 pwr_on_on_slot; + UINT8 co_clock_flag; + + /*deep sleep feature flag*/ + UINT8 disable_deep_sleep_cfg; + + /* Combo chip side SDIO driving setting */ + UINT32 sdio_driving_cfg; + + /* Combo chip WiFi path setting */ + UINT16 coex_wmt_wifi_path; + /* Combo chip WiFi eLAN gain setting */ + UINT8 coex_wmt_ext_elna_gain_p1_support; + UINT32 coex_wmt_ext_elna_gain_p1_D0; + UINT32 coex_wmt_ext_elna_gain_p1_D1; + UINT32 coex_wmt_ext_elna_gain_p1_D2; + UINT32 coex_wmt_ext_elna_gain_p1_D3; + PINT8 coex_wmt_antsel_invert_support; + UINT8 coex_wmt_ext_epa_mode; + + struct WMT_BYTE_ARRAY *coex_wmt_epa_elna; + + UINT8 bt_tssi_from_wifi; + UINT16 bt_tssi_target; + + UINT8 coex_config_bt_ctrl; + UINT8 coex_config_bt_ctrl_mode; + UINT8 coex_config_bt_ctrl_rw; + + UINT8 coex_config_addjust_opp_time_ratio; + UINT8 coex_config_addjust_opp_time_ratio_bt_slot; + UINT8 coex_config_addjust_opp_time_ratio_wifi_slot; + + UINT8 coex_config_addjust_ble_scan_time_ratio; + UINT8 coex_config_addjust_ble_scan_time_ratio_bt_slot; + UINT8 coex_config_addjust_ble_scan_time_ratio_wifi_slot; + + /* wifi ant swap feature */ + UINT8 wifi_ant_swap_mode; + UINT8 wifi_main_ant_polarity; + UINT8 wifi_ant_swap_ant_sel_gpio; + + struct WMT_BYTE_ARRAY *wifi_config; +} WMT_GEN_CONF, *P_WMT_GEN_CONF; + +typedef enum _ENUM_DRV_STS_ { +#if 0 + DRV_STS_INVALID = 0, + DRV_STS_UNREG = 1, /* Initial State */ +#endif + DRV_STS_POWER_OFF = 0, /* initial state */ + DRV_STS_POWER_ON = 1, /* powered on, only WMT */ + DRV_STS_FUNC_ON = 2, /* FUNC ON */ + DRV_STS_MAX +} ENUM_DRV_STS, *P_ENUM_DRV_STS; + +typedef enum _WMT_IC_PIN_ID_ { + WMT_IC_PIN_AUDIO = 0, + WMT_IC_PIN_EEDI = 1, + WMT_IC_PIN_EEDO = 2, + WMT_IC_PIN_GSYNC = 3, + WMT_IC_PIN_MAX +} WMT_IC_PIN_ID, *P_WMT_IC_PIN_ID; + + +typedef enum _WMT_IC_PIN_STATE_ { + WMT_IC_PIN_EN = 0, + WMT_IC_PIN_DIS = 1, + WMT_IC_AIF_0 = 2, /* = CMB_STUB_AIF_0, */ + WMT_IC_AIF_1 = 3, /* = CMB_STUB_AIF_1, */ + WMT_IC_AIF_2 = 4, /* = CMB_STUB_AIF_2, */ + WMT_IC_AIF_3 = 5, /* = CMB_STUB_AIF_3, */ + WMT_IC_PIN_MUX = 6, + WMT_IC_PIN_GPIO = 7, + WMT_IC_PIN_GPIO_HIGH = 8, + WMT_IC_PIN_GPIO_LOW = 9, + WMT_IC_PIN_STATE_MAX +} WMT_IC_PIN_STATE, *P_WMT_IC_PIN_STATE; + +typedef enum _WMT_CO_CLOCK_ { + WMT_CO_CLOCK_DIS = 0, + WMT_CO_CLOCK_EN = 1, + WMT_CO_CLOCK_DCXO = 2, + 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 MTK_WCN_BOOL(*TRIGGER_STP_ASSERT) (VOID); +typedef MTK_WCN_BOOL(*DEEP_SLEEP_CONTROL) (INT32 value); + + +typedef struct _WMT_IC_OPS_ { + UINT32 icId; + UINT64 options; + 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; + TRIGGER_STP_ASSERT trigger_stp_assert; + DEEP_SLEEP_CONTROL deep_sleep_ctrl; +} 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; + UINT32 wmtBlankStatus; /* Controlled blank status */ +} 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; /* WMT_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_WMT_PKT_TYPE { + WMT_PKT_TYPE_INVALID = 0, + WMT_PKT_TYPE_CMD = 1, + WMT_PKT_TYPE_EVENT = 2, + WMT_PKT_TYPE_MAX +} ENUM_WMT_PKT_TYPE, *P_ENUM_WMT_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 { + PUINT8 cmd; + UINT32 cmdSz; + PUINT8 evt; + UINT32 evtSz; + PUINT8 str; +}; + +typedef struct _WMT_PATCH { + UINT8 ucDateTime[16]; + UINT8 ucPLat[4]; + UINT16 u2HwVer; + UINT16 u2SwVer; + UINT32 u4PatchVer; +} WMT_PATCH, *P_WMT_PATCH; + +struct wmt_rom_patch { + UINT8 ucDateTime[16]; + UINT8 ucPLat[4]; + UINT16 u2HwVer; + UINT16 u2SwVer; + UINT32 u4PatchAddr; + UINT32 u4PatchType; + UINT32 u4CRC[4]; +}; + + +#define WMT_CORE_DMP_CPUPCR_NUM 10 +enum wmt_consys_dump_status { + WMT_DUMP_STATE_NONE = 0, + WMT_DUMP_STATE_SCHEDULED = 1, + WMT_DUMP_STATE_ONGOING = 2 +}; + +typedef struct consys_state_dmp_info { + UINT32 cpu_pcr[WMT_CORE_DMP_CPUPCR_NUM]; + CONSYS_STATE state; +} CONSYS_STATE_DMP_INFO, *P_CONSYS_STATE_DMP_INFO; + +typedef struct consys_state_dmp_op { + enum wmt_consys_dump_status status; + OSAL_SLEEPABLE_LOCK lock; + UINT32 times; + UINT32 cpu_sleep_ms; + CONSYS_STATE_DMP_INFO dmp_info; + ULONG version; +} CONSYS_STATE_DMP_OP, *P_CONSYS_STATE_DMP_OP; + + +/******************************************************************************* +* 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, PULONG pPa1, PULONG 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_retry(struct init_script *script, INT32 count, INT32 retry, INT32 dump_err_log); + +extern INT32 wmt_core_init_script(struct init_script *script, INT32 count); + +extern INT32 wmt_core_rx(PUINT8 pBuf, UINT32 bufLen, PUINT32 readSize); + +extern INT32 +wmt_core_tx(const PUINT8 pData, UINT32 size, PUINT32 writtenSize, MTK_WCN_BOOL bRawFlag); +extern MTK_WCN_BOOL wmt_core_is_quick_ps_support(VOID); + +extern MTK_WCN_BOOL wmt_core_get_aee_dump_flag(VOID); +extern MTK_WCN_BOOL wmt_core_trigger_stp_assert(VOID); +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT +extern MTK_WCN_BOOL wmt_core_deep_sleep_ctrl(INT32 value); +#endif +extern VOID wmt_core_set_coredump_state(ENUM_DRV_STS state); + +#if CFG_CORE_INTERNAL_TXRX +extern INT32 wmt_core_lpbk_do_stp_init(void); +extern INT32 wmt_core_lpbk_do_stp_deinit(void); +#endif + +extern VOID wmt_core_set_coredump_state(ENUM_DRV_STS state); +extern ENUM_DRV_STS wmt_core_get_drv_status(ENUM_WMTDRV_TYPE_T type); +#if CFG_WMT_LTE_COEX_HANDLING +extern VOID wmt_core_set_flag_for_test(UINT32 enable); +extern UINT32 wmt_core_get_flag_for_test(VOID); +#endif + +#if CFG_CORE_MT6620_SUPPORT +extern WMT_IC_OPS wmt_ic_ops_mt6620; +#endif + +#if CFG_CORE_MT6628_SUPPORT +extern WMT_IC_OPS wmt_ic_ops_mt6628; +#endif + +#if CFG_CORE_MT6630_SUPPORT +extern WMT_IC_OPS wmt_ic_ops_mt6630; +#endif + +#if CFG_CORE_MT6632_SUPPORT +extern WMT_IC_OPS wmt_ic_ops_mt6632; +#endif + +#if CFG_CORE_SOC_SUPPORT +extern WMT_IC_OPS wmt_ic_ops_soc; +#endif + +extern P_WMT_GEN_CONF wmt_get_gen_conf_pointer(VOID); + +VOID wmt_core_set_blank_status(UINT32 on_off_flag); +extern UINT32 wmt_core_get_blank_status(VOID); + +INT32 wmt_blank_status_ctrl(UINT32 on_off_flag); + +/******************************************************************************* +* 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 ((p_ops->sw_init == NULL) + || (p_ops->sw_deinit == NULL) + || (p_ops->ic_ver_check == NULL) + || (p_ops->ic_pin_ctrl == NULL)) { + return MTK_WCN_BOOL_FALSE; + } + return MTK_WCN_BOOL_TRUE; +} + +#endif /* _WMT_CORE_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/core/include/wmt_ctrl.h b/drivers/misc/mediatek/connectivity/common/common_main/core/include/wmt_ctrl.h new file mode 100644 index 0000000000000..6bb71ba0e2fd3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/core/include/wmt_ctrl.h @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + +#ifndef _WMT_CTRL_H_ +#define _WMT_CTRL_H_ + +#include "osal.h" +#include "stp_exp.h" +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define DWCNT_CTRL_DATA (16) + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + + + + + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef struct _WMT_CTRL_DATA_ { + UINT32 ctrlId; + SIZE_T au4CtrlData[DWCNT_CTRL_DATA]; +} WMT_CTRL_DATA, *P_WMT_CTRL_DATA; + +typedef enum _ENUM_WMT_CTRL_T { + WMT_CTRL_HW_PWR_OFF = 0, /* whole chip power off */ + WMT_CTRL_HW_PWR_ON = 1, /* whole chip power on */ + WMT_CTRL_HW_RST = 2, /* whole chip reset */ + 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_SOC_PALDO_CTRL = 27, + WMT_CTRL_SOC_WAKEUP_CONSYS = 28, + WMT_CTRL_SET_STP_DBG_INFO = 29, + WMT_CTRL_BGW_DESENSE_CTRL = 30, + WMT_CTRL_TRG_ASSERT = 31, +#if CFG_WMT_LTE_COEX_HANDLING + WMT_CTRL_GET_TDM_REQ_ANTSEL = 32, +#endif + WMT_CTRL_EVT_PARSER = 33, + WMT_CTRL_GET_ROM_PATCH_INFO = 34, + WMT_CTRL_UPDATE_PATCH_VERSION = 35, + WMT_CTRL_MAX +} ENUM_WMT_CTRL_T, *P_ENUM_WMT_CTRL_T; + +typedef INT32(*WMT_CTRL_FUNC) (P_WMT_CTRL_DATA); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + + + + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +extern INT32 wmt_ctrl(P_WMT_CTRL_DATA pWmtCtrlData); + +extern INT32 +wmt_ctrl_tx_ex(const PUINT8 pData, + const UINT32 size, PUINT32 writtenSize, const MTK_WCN_BOOL bRawFlag); + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + + + +#endif /* _WMT_CTRL_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/core/include/wmt_func.h b/drivers/misc/mediatek/connectivity/common/common_main/core/include/wmt_func.h new file mode 100644 index 0000000000000..9145bb205ba8c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/core/include/wmt_func.h @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \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 "wmt_core.h" +#include "wmt_plat.h" +#include "osal.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 IS_ENABLED(CONFIG_MTK_FMRADIO) +#define CFG_FUNC_FM_SUPPORT 1 +#else +#define CFG_FUNC_FM_SUPPORT 0 +#endif + +#if IS_ENABLED(CONFIG_MTK_COMBO_GPS) +#define CFG_FUNC_GPS_SUPPORT 1 +#define CFG_FUNC_GPSL5_SUPPORT 1 +#else +#define CFG_FUNC_GPS_SUPPORT 0 +#define CFG_FUNC_GPSL5_SUPPORT 0 +#endif + +#if 1 /* IS_ENABLED(CONFIG_MTK_COMBO_WIFI) */ +#define CFG_FUNC_WIFI_SUPPORT 1 +#else +#define CFG_FUNC_WIFI_SUPPORT 0 +#endif + +#if 1 +#define CFG_FUNC_ANT_SUPPORT 1 +#else +#define CFG_FUNC_ANT_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 +******************************************************************************** +*/ + +#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_GPSL5_SUPPORT +extern WMT_FUNC_OPS wmt_func_gpsl5_ops; +#endif + +#if CFG_FUNC_WIFI_SUPPORT +extern WMT_FUNC_OPS wmt_func_wifi_ops; +#endif + +#if CFG_FUNC_ANT_SUPPORT +extern WMT_FUNC_OPS wmt_func_ant_ops; +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + + + + + + + +#endif /* _WMT_FUNC_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/core/include/wmt_ic.h b/drivers/misc/mediatek/connectivity/common/common_main/core/include/wmt_ic.h new file mode 100644 index 0000000000000..aa44dff600b48 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/core/include/wmt_ic.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + +#ifndef _WMT_IC_H_ +#define _WMT_IC_H_ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "wmt_core.h" +#include "wmt_exp.h" + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define WMT_IC_NAME_MT6620 "MT6620" +#define WMT_IC_NAME_MT6628 "MT6628" +#define WMT_IC_NAME_MT6630 "MT6630" +#define WMT_IC_NAME_MT6632 "MT6632" +#define WMT_IC_NAME_DEFAULT "SOC_CONSYS" + +#define WMT_IC_VER_E1 "E1" +#define WMT_IC_VER_E2 "E2" +#define WMT_IC_VER_E3 "E3" +#define WMT_IC_VER_E4 "E4" +#define WMT_IC_VER_E5 "E5" +#define WMT_IC_VER_E6 "E6" +#define WMT_IC_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; +} 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 +******************************************************************************** +*/ + +INT32 mtk_wcn_soc_rom_patch_dwn(UINT32 ip_ver, UINT32 fw_ver); +VOID mtk_wcn_soc_restore_wifi_cal_result(VOID); + +#endif /* _WMT_IC_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/core/include/wmt_lib.h b/drivers/misc/mediatek/connectivity/common/common_main/core/include/wmt_lib.h new file mode 100644 index 0000000000000..afec898f8d531 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/core/include/wmt_lib.h @@ -0,0 +1,493 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \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 "wmt_core.h" +#include "wmt_exp.h" +#include +#include "stp_wmt.h" +#include "wmt_plat.h" +#include "wmt_idc.h" +#include "osal.h" +#include "mtk_wcn_consys_hw.h" + + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#define USE_NEW_PROC_FS_FLAG 1 + + +/******************************************************************************* +* 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_RETRY = 0x3, + WMTRSTRET_MAX +} ENUM_WMTRSTRET_TYPE_T, *P_ENUM_WMTRSTRET_TYPE_T; + +#define MAX_ANT_RAM_CODE_DOWN_TIME 3000 +/* +*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) */ +/* Since GPS timeout is 6 seconds */ +#define WMT_LIB_RX_EXTEND_TIMEOUT 4000 +/* +*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 + MAX_ANT_RAM_CODE_DOWN_TIME) + +/*1000->WMT_LIB_RX_TIMEOUT + 1000, logical judgement */ +#define MAX_EACH_FUNC_OFF (WMT_LIB_RX_TIMEOUT + 1000) +#define MAX_FUNC_OFF_TIME (MAX_EACH_FUNC_OFF * 4) + +/*1000->WMT_LIB_RX_TIMEOUT + 1000, logical judgement */ +#define MAX_EACH_WMT_CMD (WMT_LIB_RX_TIMEOUT + 1000) + +/* For WMT OP who will have trouble if timeout really happens */ +#define MAX_WMT_OP_TIMEOUT (30000) + +#define MAX_GPIO_CTRL_TIME (2000) /* [FixMe][GeorgeKuo] a temp value */ + +#define UTC_SYNC_TIME (60 * 60 * 1000) + +#define WMT_IDC_MSG_BUFFER 2048 +#define WMT_IDC_MSG_MAX_SIZE (WMT_IDC_MSG_BUFFER - 7) /* Subtract STP payload cmd size */ + +#define MAX_PATCH_NUM (10) + +#define WMT_FIRMWARE_VERSION_LENGTH (14) +#define WMT_FIRMWARE_MAX_FILE_NAME_LENGTH (50) + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/* AIF FLAG definition */ +/* bit(0): share pin or not */ +#define WMT_LIB_AIF_FLAG_MASK (0x1UL) +#define WMT_LIB_AIF_FLAG_SHARE (0x1UL << 0) +#define WMT_LIB_AIF_FLAG_SEPARATE (0x0UL << 0) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/* bit field offset definition */ +typedef enum { + WMT_STAT_PWR = 0, /* is powered on */ + WMT_STAT_STP_REG = 1, /* is STP driver registered: */ + WMT_STAT_STP_OPEN = 2, /* is STP opened: default FALSE */ + WMT_STAT_STP_EN = 3, /* is STP enabled: default FALSE */ + WMT_STAT_STP_RDY = 4, /* is STP ready for client: default FALSE */ + WMT_STAT_RX = 5, /* is rx data available */ + WMT_STAT_CMD = 6, /* is cmd string to be read */ + WMT_STAT_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; + +enum wmt_fw_log_type { + WMT_FWLOG_MCU = 0, + WMT_FWLOG_MAX +}; + +typedef struct { + PF_WMT_CB fDrvRst[WMTDRV_TYPE_MAX]; +} WMT_FDRV_CB, *P_WMT_FDRV_CB; + + +typedef struct { + UINT32 dowloadSeq; + UINT8 addRess[4]; + UINT8 patchName[256]; +} WMT_PATCH_INFO, *P_WMT_PATCH_INFO; + +struct wmt_rom_patch_info { + UINT32 type; + UINT8 addRess[4]; + UINT8 patchName[256]; +}; + +struct wmt_vendor_patch { + union { + INT32 id; + INT32 type; + }; + UINT8 file_name[WMT_FIRMWARE_MAX_FILE_NAME_LENGTH + 1]; + UINT8 version[WMT_FIRMWARE_VERSION_LENGTH + 1]; +}; + +struct vendor_patch_table { + UINT32 capacity; + UINT32 num; + INT8 status; + INT8 need_update; + PUINT8 *active_version; + struct wmt_vendor_patch *patch; +}; + +enum wmt_patch_type { + WMT_PATCH_TYPE_ROM = 0, + WMT_PATCH_TYPE_RAM, + WMT_PATCH_TYPE_WIFI +}; + +enum wmt_cp_status { + WMT_CP_INIT = 0, + WMT_CP_READY_TO_CHECK, + WMT_CP_CHECK_DONE +}; + +#define WMT_LIB_DMP_SLOT 2 +struct consys_state_dmp_req { + struct consys_state_dmp_op consys_ops[WMT_LIB_DMP_SLOT]; + atomic_t version; +}; + +/* OS independent wrapper for WMT_OP */ +typedef struct _DEV_WMT_ { + + OSAL_SLEEPABLE_LOCK psm_lock; + OSAL_SLEEPABLE_LOCK idc_lock; + OSAL_SLEEPABLE_LOCK wlan_lock; + OSAL_SLEEPABLE_LOCK assert_lock; + OSAL_SLEEPABLE_LOCK mpu_lock; + OSAL_SLEEPABLE_LOCK power_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 */ + OSAL_THREAD worker_thread; + OSAL_EVENT rWmtdWorkerWq; + /* 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 */ + UINT8 cPatchName[NAME_MAX + 1]; + UINT8 cFullPatchName[NAME_MAX + 1]; + UINT32 patchNum; + + const osal_firmware *pPatch; + + UINT8 cWmtcfgName[NAME_MAX + 1]; + + const osal_firmware *pWmtCfg; + + const osal_firmware *pNvram; + + /* Current used UART port description */ + INT8 cUartName[NAME_MAX + 1]; + + OSAL_OP_Q rFreeOpQ; /* free op queue */ + OSAL_OP_Q rActiveOpQ; /* active op queue */ + OSAL_OP_Q rWorkerOpQ; + OSAL_OP arQue[WMT_OP_BUF_SIZE]; /* real op instances */ + P_OSAL_OP pCurOP; /* current op */ + P_OSAL_OP pWorkerOP; /* current op on worker thread */ + + /* cmd str buffer */ + UINT8 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; + UINT32 ip_ver; + + UINT32 ext_ldo_flag; + P_WMT_PATCH_INFO pWmtPatchInfo; + struct wmt_rom_patch_info *pWmtRomPatchInfo[WMTDRV_TYPE_ANT]; + /* MET thread information */ + OSAL_THREAD met_thread; + INT32 met_log_ctrl; + /* Timer to sync UTC time with connsys */ + OSAL_TIMER utc_sync_timer; + struct work_struct utcSyncWorker; + /* Timer for wmt_worker_thread */ + OSAL_TIMER worker_timer; + struct work_struct wmtd_worker_thread_work; + struct osal_op_history wmtd_op_history; + struct osal_op_history worker_op_history; + UINT8 msg_local_buffer[WMT_IDC_MSG_BUFFER]; + struct vendor_patch_table patch_table; + + struct consys_state_dmp_req state_dmp_req; + +} 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 DEV_WMT gDevWmt; +extern INT32 wmt_lib_init(VOID); +extern INT32 wmt_lib_deinit(VOID); +extern INT32 wmt_lib_tx(PUINT8 data, UINT32 size, PUINT32 writtenSize); +extern INT32 wmt_lib_tx_raw(PUINT8 data, UINT32 size, PUINT32 writtenSize); +extern INT32 wmt_lib_rx(PUINT8 buff, UINT32 buffLen, PUINT32 readSize); +extern VOID wmt_lib_flush_rx(VOID); +extern UINT32 wmt_lib_co_clock_flag_get(VOID); +extern INT32 wmt_lib_sdio_reg_rw(INT32 func_num, INT32 direction, UINT32 offset, UINT32 value); + + +#if WMT_PLAT_ALPS +extern PINT8 wmt_uart_port_desc; /* defined in mtk_wcn_cmb_stub_alps.cpp */ +#endif + +#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); +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT +extern VOID wmt_lib_sdio_deep_sleep_flag_set_cb_reg(PF_WMT_SDIO_DEEP_SLEEP flag_cb); +#endif +extern VOID wmt_lib_sdio_reg_rw_cb(PF_WMT_SDIO_DEBUG reg_rw_cb); +extern INT32 wmt_lib_register_thermal_ctrl_cb(thermal_query_ctrl_cb thermal_ctrl); +extern INT32 wmt_lib_register_trigger_assert_cb(trigger_assert_cb trigger_assert); + +/* 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 MTK_WCN_BOOL wmt_lib_put_worker_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(ENUM_WMTTHERM_TYPE_T eType); +extern MTK_WCN_BOOL wmt_lib_is_dsns_ctrl_support(VOID); +extern INT32 wmt_lib_trigger_cmd_signal(INT32 result); +extern PUINT8 wmt_lib_get_cmd(VOID); +extern P_OSAL_EVENT wmt_lib_get_cmd_event(VOID); +extern INT32 wmt_lib_set_patch_name(PUINT8 cPatchName); +extern INT32 wmt_lib_set_uart_name(PINT8 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(enum 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); +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT +extern INT32 wmt_lib_deep_sleep_ctrl(INT32 value); +extern MTK_WCN_BOOL wmt_lib_deep_sleep_flag_set(MTK_WCN_BOOL flag); +#endif +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); +INT32 wmt_lib_met_ctrl(INT32 met_ctrl, INT32 log_ctrl); +INT32 wmt_lib_gps_mcu_ctrl(PUINT8 p_tx_data_buf, UINT32 tx_data_len, PUINT8 p_rx_data_buf, + UINT32 rx_data_buf_len, PUINT32 p_rx_data_len); +VOID wmt_lib_set_ext_ldo(UINT32 flag); +UINT32 wmt_lib_get_ext_ldo(VOID); +INT32 wmt_lib_try_pwr_off(VOID); +P_WMT_PATCH_INFO wmt_lib_get_patch_info(VOID); +INT32 wmt_lib_met_cmd(UINT32 value); + +INT32 wmt_lib_blank_status_ctrl(UINT32 on_off_flag); +VOID wmt_lib_set_blank_status(UINT32 on_off_flag); +extern UINT32 wmt_lib_get_blank_status(VOID); + +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_psm_lock_trylock(VOID); +extern VOID wmt_lib_idc_lock_release(VOID); +extern INT32 wmt_lib_idc_lock_aquire(VOID); +extern VOID wmt_lib_wlan_lock_release(VOID); +extern INT32 wmt_lib_wlan_lock_trylock(VOID); +extern INT32 wmt_lib_wlan_lock_aquire(VOID); +extern VOID wmt_lib_assert_lock_release(VOID); +extern INT32 wmt_lib_assert_lock_trylock(VOID); +extern INT32 wmt_lib_assert_lock_aquire(VOID); +extern VOID wmt_lib_mpu_lock_release(VOID); +extern INT32 wmt_lib_mpu_lock_aquire(VOID); +extern VOID wmt_lib_power_lock_release(VOID); +extern INT32 wmt_lib_power_lock_trylock(VOID); +extern INT32 wmt_lib_power_lock_aquire(VOID); +extern INT32 wmt_lib_set_stp_wmt_last_close(UINT32 value); + +extern VOID wmt_lib_set_patch_num(UINT32 num); +extern VOID wmt_lib_set_patch_info(P_WMT_PATCH_INFO pPatchinfo); +extern VOID wmt_lib_set_rom_patch_info(struct wmt_rom_patch_info *PatchInfo, ENUM_WMTDRV_TYPE_T type); +extern MTK_WCN_BOOL wmt_lib_stp_is_btif_fullset_mode(VOID); + +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_set_worker_op(P_DEV_WMT pWmtDev, P_OSAL_OP pOp); +extern P_OSAL_OP wmt_lib_get_worker_op(P_DEV_WMT pWmtDev); +extern PUINT8 wmt_lib_get_fwinfor_from_emi(UINT8 section, UINT32 offset, PUINT8 buff, UINT32 len); +extern INT32 wmt_lib_merge_if_flag_ctrl(UINT32 enable); +extern INT32 wmt_lib_merge_if_flag_get(UINT32 enable); + +extern PUINT8 wmt_lib_get_cpupcr_xml_format(PUINT32 len); +extern PUINT8 wmt_lib_get_cpupcr_reg_info(PUINT32 len, PUINT32 consys_reg); +extern UINT32 wmt_lib_set_host_assert_info(UINT32 type, UINT32 reason, UINT32 en); +extern INT8 wmt_lib_co_clock_get(VOID); +extern UINT32 wmt_lib_soc_set_wifiver(UINT32 wifiver); +extern VOID wmt_lib_dump_wmtd_backtrace(VOID); + +#if CFG_WMT_LTE_COEX_HANDLING +extern MTK_WCN_BOOL wmt_lib_handle_idc_msg(conn_md_ipc_ilm_t *idc_infor); +#endif +extern UINT32 wmt_lib_get_drv_status(UINT32 type); +extern INT32 wmt_lib_tm_temp_query(VOID); +extern INT32 wmt_lib_trigger_reset(VOID); +extern INT32 wmt_lib_trigger_assert(ENUM_WMTDRV_TYPE_T type, UINT32 reason); +extern INT32 wmt_lib_trigger_assert_keyword(ENUM_WMTDRV_TYPE_T type, UINT32 reason, PUINT8 keyword); +extern VOID wmt_lib_trigger_assert_keyword_delay(ENUM_WMTDRV_TYPE_T type, UINT32 reason, PUINT8 keyword); +extern INT32 wmt_lib_wifi_fem_cfg_report(PVOID pvInfoBuf); +#if CFG_WMT_PS_SUPPORT +extern UINT32 wmt_lib_quick_sleep_ctrl(UINT32 en); +#endif +extern UINT32 wmt_lib_fw_patch_update_rst_ctrl(UINT32 en); +#if CONSYS_ENALBE_SET_JTAG +extern UINT32 wmt_lib_jtag_flag_set(UINT32 en); +#endif + +UINT32 wmt_lib_get_gps_lna_pin_num(VOID); +extern INT32 wmt_lib_fw_log_ctrl(enum wmt_fw_log_type type, UINT8 onoff, UINT8 level); +VOID wmt_lib_print_wmtd_op_history(VOID); +VOID wmt_lib_print_worker_op_history(VOID); +extern INT32 wmt_lib_get_vendor_patch_num(VOID); +extern INT32 wmt_lib_set_vendor_patch_version(struct wmt_vendor_patch *p); +extern INT32 wmt_lib_get_vendor_patch_version(struct wmt_vendor_patch *p); +extern INT32 wmt_lib_set_check_patch_status(INT32 status); +extern INT32 wmt_lib_get_check_patch_status(VOID); +extern INT32 wmt_lib_set_active_patch_version(struct wmt_vendor_patch *p); +extern INT32 wmt_lib_get_active_patch_version(struct wmt_vendor_patch *p); +extern INT32 wmt_lib_get_need_update_patch_version(VOID); +extern INT32 wmt_lib_set_need_update_patch_version(INT32 need); +extern VOID wmt_lib_set_bt_link_status(INT32 type, INT32 value); +VOID mtk_lib_set_mcif_mpu_protection(MTK_WCN_BOOL enable); +INT32 wmt_lib_dmp_consys_state(P_CONSYS_STATE_DMP_INFO dmp_info, + UINT32 cpupcr_times, UINT32 slp_ms); + +extern INT32 wmt_lib_reg_readable(VOID); +extern INT32 wmt_lib_reg_readable_by_addr(SIZE_T addr); +extern INT32 wmt_lib_utc_time_sync(VOID); +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _WMT_LIB_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/core/psm_core.c b/drivers/misc/mediatek/connectivity/common/common_main/core/psm_core.c new file mode 100644 index 0000000000000..5e7220c86fcbf --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/core/psm_core.c @@ -0,0 +1,2080 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include "osal_typedef.h" +#include "osal.h" +#include "psm_core.h" +#include "stp_core.h" +#include "stp_dbg.h" +#include "wmt_detect.h" +#include "wmt_exp.h" +#include +#include + +INT32 gPsmDbgLevel = STP_PSM_LOG_INFO; +MTKSTP_PSM_T stp_psm_i; +MTKSTP_PSM_T *stp_psm = &stp_psm_i; + +STP_PSM_RECORD_T *g_stp_psm_dbg; +static UINT32 g_record_num; + +P_STP_PSM_OPID_RECORD g_stp_psm_opid_dbg; +static UINT32 g_opid_record_num; + +static UINT32 stp_traffic_start; +static UINT32 stp_traffic_current; + +#define STP_PSM_PR_LOUD(fmt, arg...) \ +do { \ + if (gPsmDbgLevel >= STP_PSM_LOG_LOUD) \ + pr_info(PFX_PSM "%s: " fmt, __func__, ##arg); \ +} while (0) +#define STP_PSM_PR_DBG(fmt, arg...) \ +do { \ + if (gPsmDbgLevel >= STP_PSM_LOG_DBG) \ + pr_info(PFX_PSM "%s: " fmt, __func__, ##arg); \ +} while (0) +#define STP_PSM_PR_INFO(fmt, arg...) \ +do { \ + if (gPsmDbgLevel >= STP_PSM_LOG_INFO) \ + pr_info(PFX_PSM "[I]%s: " fmt, __func__, ##arg); \ +} while (0) +#define STP_PSM_PR_WARN(fmt, arg...) \ +do { \ + if (gPsmDbgLevel >= STP_PSM_LOG_WARN) \ + pr_warn(PFX_PSM "[W]%s: " fmt, __func__, ##arg); \ +} while (0) +#define STP_PSM_PR_ERR(fmt, arg...) \ +do { \ + if (gPsmDbgLevel >= STP_PSM_LOG_ERR) \ + pr_err(PFX_PSM "[E]%s(%d):ERROR! " fmt, __func__, __LINE__, ##arg); \ +} while (0) + + +static inline INT32 _stp_psm_notify_wmt(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_ACTION_T action); +static INT32 _stp_psm_thread_lock_aquire(MTKSTP_PSM_T *stp_psm); +static INT32 _stp_psm_thread_lock_release(MTKSTP_PSM_T *stp_psm); +static INT32 _stp_psm_dbg_dmp_in(STP_PSM_RECORD_T *stp_psm_dbg, UINT32 flag, UINT32 line_num); +static INT32 _stp_psm_dbg_out_printk(STP_PSM_RECORD_T *stp_psm_dbg); +static INT32 _stp_psm_opid_dbg_dmp_in(P_STP_PSM_OPID_RECORD p_opid_dbg, UINT32 opid, UINT32 line_num); +static INT32 _stp_psm_opid_dbg_out_printk(P_STP_PSM_OPID_RECORD p_opid_dbg); + + +static const PINT8 g_psm_state[STP_PSM_MAX_STATE] = { + "ACT", + "ACT_INACT", + "INACT", + "INACT_ACT" +}; + +static const PINT8 g_psm_action[STP_PSM_MAX_ACTION] = { + "SLEEP", + "HOST_AWAKE", + "WAKEUP", + "EIRQ", + "ROLL_BACK" +}; + +static const PINT8 g_psm_op_name[STP_OPID_PSM_NUM] = { + "STP_OPID_PSM_SLEEP", + "STP_OPID_PSM_WAKEUP", + "STP_OPID_PSM_HOST_AWAKE", + "STP_OPID_PSM_EXIT" +}; + +static 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); + +ENUM_STP_TX_IF_TYPE __weak wmt_plat_get_comm_if_type(VOID) +{ + return STP_MAX_IF_TX; +} + +MTK_WCN_BOOL mtk_wcn_stp_psm_dbg_level(INT32 dbglevel) +{ + if (dbglevel >= 0 && dbglevel <= 4) { + gPsmDbgLevel = dbglevel; + STP_PSM_PR_INFO("gPsmDbgLevel = %d\n", gPsmDbgLevel); + return true; + } + STP_PSM_PR_INFO("invalid psm debug level. gPsmDbgLevel = %d\n", gPsmDbgLevel); + return false; +} +#if 0 +/* 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 +} +#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_PR_ERR("--->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_PR_INFO("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_PR_ERR("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_PR_WARN("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) && (pOp != NULL)) { + /* stp_psm->current_active_op = pOp; */ + stp_psm->last_active_opId = pOp->op.opId; + } + osal_unlock_unsleepable_lock(&(stp_psm->wq_spinlock)); + + if ((pOpQ == &stp_psm->rActiveOpQ) && (pOp != NULL)) + STP_PSM_PR_DBG("last_active_opId(%d)\n", stp_psm->last_active_opId); + + if (!pOp) + STP_PSM_PR_WARN("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_PR_DBG("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_PR_DBG("%s\n", g_psm_op_name[opId]); + else + STP_PSM_PR_WARN("Unknown OP Id\n"); + ++read_idx; + } + STP_PSM_PR_DBG("Active op list:--\n"); + } else + STP_PSM_PR_DBG("%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_psm->last_active_opId != STP_OPID_PSM_INALID)) { + 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_PR_DBG("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_PR_DBG("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); + if (!pOp) { + STP_PSM_PR_DBG("RB_GET pOp == NULL\n"); + } else { + STP_PSM_PR_DBG("redundant opId(%d) found, remove it\n", + pOp->op.opId); + } + RB_PUT(pFreeOpQ, pOp); + } else + if ((prev_opId == STP_OPID_PSM_WAKEUP + && prev_prev_opId == STP_OPID_PSM_HOST_AWAKE) + || (prev_opId == STP_OPID_PSM_HOST_AWAKE + && prev_prev_opId == STP_OPID_PSM_WAKEUP)) { + STP_PSM_PR_WARN("prev_opId(%d), prev_prev_opId(%d)\n", prev_opId, + prev_prev_opId); + RB_GET(pOpQ, pOp); + RB_PUT(pFreeOpQ, pOp); + } else { + STP_PSM_PR_ERR + ("prev_opId(%d), prev_prev_opId(%d), this should never happen!!!\n", + prev_opId, prev_prev_opId); + break; + } + } + } + + 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_PR_WARN("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_PR_DBG("opId(%d) enqueue\n", pOp->op.opId); + } else { + STP_PSM_PR_INFO("************ 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); + + + if (ret) { + STP_PSM_PR_WARN("RB_FULL, RB_COUNT=%d , RB_SIZE=%d\n", RB_COUNT(pOpQ), + RB_SIZE(pOpQ)); + osal_opq_dump_locked("FreeOpQ", &stp_psm->rFreeOpQ); + osal_opq_dump_locked("ActiveOpQ", &stp_psm->rActiveOpQ); + } + + osal_unlock_unsleepable_lock(&(stp_psm->wq_spinlock)); + return ret ? 0 : 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, 0, osal_sizeof(OSAL_OP)); + } + return pOp; + } + 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 wait_ret = -1; + P_OSAL_SIGNAL pSignal = NULL; + INT32 ret = 0; + + do { + if (!stp_psm || !pOp) { + STP_PSM_PR_ERR("stp_psm = %p, pOp = %p\n", stp_psm, pOp); + break; + } + + pSignal = &pOp->signal; + + if (pSignal->timeoutValue) { + pOp->result = -9; + osal_signal_init(&pOp->signal); + } + + /* Init ref_count to 2, as one is held by current thread, the second by psm thread */ + atomic_set(&pOp->ref_count, 2); + + /* put to active Q */ + bRet = _stp_psm_put_op(stp_psm, &stp_psm->rActiveOpQ, pOp); + + if (bRet == 0) { + STP_PSM_PR_WARN("+++++++++++ Put op Active queue Fail\n"); + atomic_dec(&pOp->ref_count); + break; + } + _stp_psm_opid_dbg_dmp_in(g_stp_psm_opid_dbg, pOp->op.opId, __LINE__); + /* wake up wmtd */ + ret = osal_trigger_event(&stp_psm->STPd_event); + + if (pSignal->timeoutValue == 0) { + bRet = 1; /* MTK_WCN_BOOL_TRUE; */ + break; + } + + /* check result */ + wait_ret = osal_wait_for_signal_timeout(&pOp->signal, &stp_psm->PSMd); + STP_PSM_PR_DBG("wait completion:%d\n", wait_ret); + if (!wait_ret) { + STP_PSM_PR_ERR("wait completion timeout\n"); + /* TODO: how to handle it? retry? */ + } else { + if (pOp->result) + STP_PSM_PR_WARN("op(%d) result:%d\n", pOp->op.opId, pOp->result); + /* op completes, check result */ + bRet = (pOp->result) ? 0 : 1; + } + } while (0); + + if (pOp && atomic_dec_and_test(&pOp->ref_count)) { + /* put Op back to freeQ */ + bRet = _stp_psm_put_op(stp_psm, &stp_psm->rFreeOpQ, pOp); + if (bRet == 0) + STP_PSM_PR_WARN("+++++++++++ Put op active free fail, maybe disable/enable psm\n"); + } + + return bRet; +} + +static INT32 _stp_psm_wait_for_msg(PVOID pvData) +{ + MTKSTP_PSM_T *stp_psm = (MTKSTP_PSM_T *)pvData; + + STP_PSM_PR_DBG("%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(PVOID pvData) +{ + MTKSTP_PSM_T *stp_psm = (MTKSTP_PSM_T *) pvData; + P_OSAL_OP pOp; + UINT32 id; + INT32 result; + + if (!stp_psm) { + STP_PSM_PR_WARN("!stp_psm\n"); + return -1; + } +/* STP_PSM_PR_INFO("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, (PVOID) stp_psm); + + /* we set reset flag when calling stp_reset after cleanup all op. */ + if (osal_test_bit(STP_PSM_RESET_EN, &stp_psm->flag)) { + osal_clear_bit(STP_PSM_RESET_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + } + if (osal_thread_should_stop(&stp_psm->PSMd)) { + STP_PSM_PR_INFO("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_PR_WARN + ("+++++++++++ Get op from activeQ fail, maybe disable/enable psm\n"); + continue; + } + osal_op_history_save(&stp_psm->op_history, pOp); + + id = osal_op_get_id(pOp); + + if (id >= STP_OPID_PSM_NUM) { + STP_PSM_PR_WARN("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_PR_WARN("opid id(0x%x)(%s) error(%d)\n", id, + (id >= 4) ? ("???") : (g_psm_op_name[id]), result); + + if (atomic_dec_and_test(&pOp->ref_count)) { + /* put Op back to freeQ */ + if (_stp_psm_put_op(stp_psm, &stp_psm->rFreeOpQ, pOp) == 0) + STP_PSM_PR_WARN + ("+++++++++++ Put op to FreeOpQ fail, maybe disable/enable psm\n"); + } else if (osal_op_is_wait_for_signal(pOp)) { + osal_op_raise_signal(pOp, result); + } + + if (id == STP_OPID_PSM_EXIT) + break; + } + STP_PSM_PR_INFO("exits\n"); + + return 0; +}; + +static inline INT32 _stp_psm_get_time(VOID) +{ + if (gPsmDbgLevel >= STP_PSM_LOG_LOUD) + osal_printtimeofday(">>>"); + + return 0; +} + +static inline INT32 _stp_psm_get_state(MTKSTP_PSM_T *stp_psm) +{ + if (stp_psm == NULL) + return STP_PSM_OPERATION_FAIL; + if (stp_psm->work_state < STP_PSM_MAX_STATE) + return stp_psm->work_state; + STP_PSM_PR_ERR("work_state = %d, invalid\n", stp_psm->work_state); + return -STP_PSM_OPERATION_FAIL; +} + +static inline INT32 _stp_psm_set_state(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_STATE_T state) +{ + if (stp_psm == NULL) + return STP_PSM_OPERATION_FAIL; + if (stp_psm->work_state < STP_PSM_MAX_STATE) { + _stp_psm_get_time(); + /* STP_PSM_PR_INFO("work_state = %s --> %s\n", + * g_psm_state[stp_psm->work_state], g_psm_state[state]); + */ + stp_psm->work_state = state; + if (stp_psm->work_state != ACT) { + /* osal_lock_unsleepable_lock(&stp_psm->flagSpinlock); */ + osal_set_bit(STP_PSM_BLOCK_DATA_EN, &stp_psm->flag); + /* osal_unlock_unsleepable_lock(&stp_psm->flagSpinlock); */ + } + } else + STP_PSM_PR_ERR("work_state = %d, invalid\n", stp_psm->work_state); + + return STP_PSM_OPERATION_SUCCESS; +} + +static inline INT32 _stp_psm_start_monitor(MTKSTP_PSM_T *stp_psm) +{ + + if (!stp_psm) + return STP_PSM_OPERATION_FAIL; + + if (osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag)) { + STP_PSM_PR_DBG("STP-PSM DISABLE, DONT restart monitor!\n\r"); + return STP_PSM_OPERATION_SUCCESS; + } + + + STP_PSM_PR_LOUD("start monitor\n"); + stp_traffic_start = stp_traffic_current; + osal_timer_modify(&stp_psm->psm_timer, stp_psm->idle_time_to_sleep); + + return STP_PSM_OPERATION_SUCCESS; +} + +static inline INT32 _stp_psm_stop_monitor(MTKSTP_PSM_T *stp_psm) +{ + if (!stp_psm) + return STP_PSM_OPERATION_FAIL; + STP_PSM_PR_DBG("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 PUINT8 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; + /*psm_fifo_lock(stp_psm);*/ + osal_lock_sleepable_lock(&stp_psm->hold_fifo_spinlock_global); + available_space = STP_PSM_FIFO_SIZE - osal_fifo_len(&stp_psm->hold_fifo); + needed_space = len + sizeof(UINT8) + sizeof(UINT32) + 2; + /* STP_PSM_PR_INFO("*******FIFO Available(%d), Need(%d)\n", + * available_space, needed_space); + */ + if (available_space < needed_space) { + STP_PSM_PR_ERR("FIFO Available!! Reset FIFO\n"); + osal_fifo_reset(&stp_psm->hold_fifo); + } + /* type */ + osal_fifo_in(&stp_psm->hold_fifo, (PUINT8) &type, sizeof(UINT8)); + /* length */ + osal_fifo_in(&stp_psm->hold_fifo, (PUINT8) &len, sizeof(UINT32)); + /* buffer */ + osal_fifo_in(&stp_psm->hold_fifo, (PUINT8) buffer, len); + /* delimiter */ + osal_fifo_in(&stp_psm->hold_fifo, (PUINT8) delimiter, 2); + /*psm_fifo_unlock(stp_psm);*/ + osal_unlock_sleepable_lock(&stp_psm->hold_fifo_spinlock_global); + return len; +} + +INT32 _stp_psm_has_pending_data(MTKSTP_PSM_T *stp_psm) +{ + return osal_fifo_len(&stp_psm->hold_fifo); +} + +INT32 _stp_psm_release_data(MTKSTP_PSM_T *stp_psm) +{ + + INT32 i = 20; /*Max buffered packet number */ + INT32 ret = 0; + UINT8 type = 0; + UINT32 len = 0; + UINT8 delimiter[2] = {0}; + INT32 winspace_flag = 0; + + /* STP_PSM_PR_ERR("++++++++++release data++len=%d\n", osal_fifo_len(&stp_psm->hold_fifo)); */ + while ((osal_fifo_len(&stp_psm->hold_fifo) && i > 0) || winspace_flag > 0) { + /* acquire spinlock */ + /* psm_fifo_lock(stp_psm); */ + osal_lock_sleepable_lock(&stp_psm->hold_fifo_spinlock_global); + + if (winspace_flag == 0) { + ret = osal_fifo_out(&stp_psm->hold_fifo, (PUINT8)&type, sizeof(UINT8)); + ret = osal_fifo_out(&stp_psm->hold_fifo, (PUINT8)&len, sizeof(UINT32)); + + if (len > STP_PSM_PACKET_SIZE_MAX) { + STP_PSM_PR_ERR("***psm packet's length too Long!****\n"); + STP_PSM_PR_INFO("***reset psm's fifo***\n"); + } else { + osal_memset(stp_psm->out_buf, 0, STP_PSM_TX_SIZE); + ret = osal_fifo_out(&stp_psm->hold_fifo, (PUINT8) stp_psm->out_buf, len); + } + + ret = osal_fifo_out(&stp_psm->hold_fifo, (PUINT8)delimiter, 2); + } + + if (delimiter[0] == 0xbb && delimiter[1] == 0xbb) { + /* osal_buffer_dump(stp_psm->out_buf, "psm->out_buf", len, 32); */ + ret = stp_send_data_no_ps(stp_psm->out_buf, len, type); + if (ret == 0) + winspace_flag++; + else + winspace_flag = 0; + } else { + STP_PSM_PR_ERR("***psm packet fifo parsing fail****\n"); + STP_PSM_PR_INFO("***reset psm's fifo***\n"); + + osal_fifo_reset(&stp_psm->hold_fifo); + } + + if (winspace_flag == 0) + i--; + /* psm_fifo_unlock(stp_psm); */ + osal_unlock_sleepable_lock(&stp_psm->hold_fifo_spinlock_global); + + if (winspace_flag > 0 && winspace_flag < 10) + osal_sleep_ms(2); + else if (winspace_flag >= 10) { + STP_PSM_PR_ERR("***More than 20ms no winspace available***\n"); + break; + } + } + return STP_PSM_OPERATION_SUCCESS; +} + +static inline INT32 _stp_psm_notify_wmt_host_awake_wq(MTKSTP_PSM_T *stp_psm) +{ + + P_OSAL_OP pOp; + INT32 bRet; + INT32 retval; + + if (stp_psm == NULL) + return STP_PSM_OPERATION_FAIL; + pOp = _stp_psm_get_free_op(stp_psm); + if (!pOp) { + STP_PSM_PR_DBG("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_PR_DBG("OPID(%d) type(%zd) bRet(%d)\n\n", pOp->op.opId, pOp->op.au4OpData[0], bRet); + retval = (bRet == 0) ? (STP_PSM_OPERATION_FAIL) : 0; + return retval; +} + +static inline INT32 _stp_psm_notify_wmt_wakeup_wq(MTKSTP_PSM_T *stp_psm) +{ + P_OSAL_OP pOp; + INT32 bRet; + INT32 retval; + + if (stp_psm == NULL) + return STP_PSM_OPERATION_FAIL; + pOp = _stp_psm_get_free_op(stp_psm); + if (!pOp) { + STP_PSM_PR_DBG("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 (bRet == 0) { + STP_PSM_PR_WARN("OPID(%d) type(%zd) bRet(%s)\n\n", + pOp->op.opId, pOp->op.au4OpData[0], "fail"); + } + retval = (bRet == 0) ? (STP_PSM_OPERATION_FAIL) : (STP_PSM_OPERATION_SUCCESS); + return retval; +} + +static inline INT32 _stp_psm_notify_wmt_sleep_wq(MTKSTP_PSM_T *stp_psm) +{ + P_OSAL_OP pOp; + INT32 bRet; + INT32 retval; + + if (stp_psm == NULL) + return STP_PSM_OPERATION_FAIL; + if (osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY, &stp_psm->flag)) + return 0; +#if PSM_USE_COUNT_PACKAGE + if (osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY, &stp_psm->flag)) + return 0; +#endif + if (osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag)) + return 0; + pOp = _stp_psm_get_free_op(stp_psm); + if (!pOp) { + STP_PSM_PR_DBG("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_PR_DBG("OPID(%d) type(%zd) bRet(%d)\n\n", pOp->op.opId, pOp->op.au4OpData[0], bRet); + retval = (bRet == 0) ? (STP_PSM_OPERATION_FAIL) : 1; + return retval; +} + +/*internal function*/ + +static inline INT32 _stp_psm_reset(MTKSTP_PSM_T *stp_psm) +{ + INT32 i = 0; + P_OSAL_OP_Q pOpQ; + P_OSAL_OP pOp; + INT32 ret = 0; + + STP_PSM_PR_DBG("PSM MODE RESET=============================>\n\r"); + STP_PSM_PR_DBG("_stp_psm_reset\n"); + STP_PSM_PR_DBG("reset-wake_lock(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock)); + osal_wake_unlock(&stp_psm->wake_lock); + STP_PSM_PR_DBG("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_PR_ERR("--->lock stp_psm->user_lock failed, ret=%d\n", ret); + return ret; + } + /* --> disable psm <--// */ + stp_psm->flag.data = 0; + osal_set_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + _stp_psm_stop_monitor(stp_psm); + /* --> prepare the op list <--// */ + osal_lock_unsleepable_lock(&(stp_psm->wq_spinlock)); + RB_INIT(&stp_psm->rFreeOpQ, STP_OP_BUF_SIZE); + RB_INIT(&stp_psm->rActiveOpQ, STP_OP_BUF_SIZE); + /* stp_psm->current_active_op = NULL; */ + stp_psm->last_active_opId = STP_OPID_PSM_INALID; + pOpQ = &stp_psm->rFreeOpQ; + for (i = 0; i < STP_OP_BUF_SIZE; i++) { + if (!RB_FULL(pOpQ)) { + pOp = &stp_psm->arQue[i]; + RB_PUT(pOpQ, pOp); + } + } + osal_unlock_unsleepable_lock(&(stp_psm->wq_spinlock)); + /* --> clean up interal data structure<--// */ + _stp_psm_set_state(stp_psm, ACT); + /*psm_fifo_lock(stp_psm);*/ + osal_lock_sleepable_lock(&stp_psm->hold_fifo_spinlock_global); + osal_fifo_reset(&stp_psm->hold_fifo); + /*psm_fifo_unlock(stp_psm);*/ + osal_unlock_sleepable_lock(&stp_psm->hold_fifo_spinlock_global); + /* --> stop psm thread wait <--*/ + osal_set_bit(STP_PSM_RESET_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + osal_trigger_event(&stp_psm->wait_wmt_q); + osal_unlock_sleepable_lock(&stp_psm->user_lock); + STP_PSM_PR_DBG("PSM MODE RESET<============================\n\r"); + return STP_PSM_OPERATION_SUCCESS; +} + +static INT32 _stp_psm_wait_wmt_event(PVOID pvData) +{ + MTKSTP_PSM_T *stp_psm = (MTKSTP_PSM_T *) pvData; + + STP_PSM_PR_DBG("%s, stp_psm->flag= %ld\n", __func__, stp_psm->flag.data); + osal_ftrace_print("%s, stp_psm->flag= %ld\n", __func__, stp_psm->flag.data); + + return (osal_test_bit(STP_PSM_WMT_EVENT_SLEEP_EN, &stp_psm->flag)) || + (osal_test_bit(STP_PSM_WMT_EVENT_WAKEUP_EN, &stp_psm->flag)) || + (osal_test_bit(STP_PSM_WMT_EVENT_ROLL_BACK_EN, &stp_psm->flag)) || + (osal_test_bit(STP_PSM_RESET_EN, &stp_psm->flag)); + +} + + +static inline INT32 _stp_psm_wait_wmt_event_wq(MTKSTP_PSM_T *stp_psm) +{ + + INT32 retval = 0; + PUINT8 pbuf = NULL; + INT32 len = 0; + + if (stp_psm == NULL) + return STP_PSM_OPERATION_FAIL; + osal_wait_for_event_timeout(&stp_psm->wait_wmt_q, _stp_psm_wait_wmt_event, (PVOID) stp_psm); + + if (mtk_wcn_stp_get_wmt_trg_assert() == 1 || mtk_wcn_stp_coredump_start_get() == 1) { + STP_PSM_PR_INFO("Host/Fw already triggered assert. Skip psm operation.\n"); + return STP_PSM_OPERATION_FAIL; + } + + if (osal_test_bit(STP_PSM_WMT_EVENT_WAKEUP_EN, &stp_psm->flag)) { + osal_clear_bit(STP_PSM_WMT_EVENT_WAKEUP_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + /* osal_lock_unsleepable_lock(&stp_psm->flagSpinlock); */ + /* STP send data here: STP enqueue data to psm buffer. */ + _stp_psm_release_data(stp_psm); + /* STP send data here: STP enqueue data to psm buffer. We release packet by the next one. */ + osal_clear_bit(STP_PSM_BLOCK_DATA_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + /* STP send data here: STP sends data directly without PSM. */ + _stp_psm_set_state(stp_psm, ACT); + /* osal_unlock_unsleepable_lock(&stp_psm->flagSpinlock); */ + if (stp_psm_is_quick_ps_support()) + stp_psm_notify_wmt_sleep(stp_psm); + else + _stp_psm_start_monitor(stp_psm); + } else if (osal_test_bit(STP_PSM_WMT_EVENT_SLEEP_EN, &stp_psm->flag)) { + osal_clear_bit(STP_PSM_WMT_EVENT_SLEEP_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + _stp_psm_set_state(stp_psm, INACT); + STP_PSM_PR_DBG("mt_combo_plt_enter_deep_idle++\n"); + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) + mt_combo_plt_enter_deep_idle(COMBO_IF_BTIF); + else { + switch (wmt_plat_get_comm_if_type()) { + case STP_UART_IF_TX: + mt_combo_plt_enter_deep_idle(COMBO_IF_UART); + break; + case STP_SDIO_IF_TX: + mt_combo_plt_enter_deep_idle(COMBO_IF_MSDC); + break; + default: + break; + } + } + STP_PSM_PR_DBG("mt_combo_plt_enter_deep_idle--\n"); + STP_PSM_PR_DBG("sleep-wake_lock(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock)); + osal_wake_unlock(&stp_psm->wake_lock); + STP_PSM_PR_DBG("sleep-wake_lock#(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock)); + + if (osal_wake_lock_count(&stp_psm->wake_lock) == 0 && stp_psm->update_wmt_fw_patch_chip_rst != NULL) + stp_psm->update_wmt_fw_patch_chip_rst(); + } else if (osal_test_bit(STP_PSM_WMT_EVENT_ROLL_BACK_EN, &stp_psm->flag)) { + osal_clear_bit(STP_PSM_WMT_EVENT_ROLL_BACK_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + if (_stp_psm_get_state(stp_psm) == ACT_INACT) { + /* osal_lock_unsleepable_lock(&stp_psm->flagSpinlock); */ + _stp_psm_release_data(stp_psm); + osal_clear_bit(STP_PSM_BLOCK_DATA_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + _stp_psm_set_state(stp_psm, ACT); + /* osal_unlock_unsleepable_lock(&stp_psm->flagSpinlock); */ + } else if (_stp_psm_get_state(stp_psm) == INACT_ACT) { + _stp_psm_set_state(stp_psm, INACT); + STP_PSM_PR_INFO("[WARNING]PSM state rollback due too wakeup fail\n"); + } + } else if (osal_test_bit(STP_PSM_RESET_EN, &stp_psm->flag)) { + osal_clear_bit(STP_PSM_WMT_EVENT_ROLL_BACK_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + } else { + STP_PSM_PR_ERR("state = %d, flag = %ld<== Abnormal flag be set!!\n\r", + stp_psm->work_state, stp_psm->flag.data); + mtk_wcn_wmt_dump_wmtd_backtrace(); + /* wcn_psm_flag_trigger_collect_ftrace(); */ /* trigger collect SYS_FTRACE */ + pbuf = "Abnormal PSM flag be set, just collect SYS_FTRACE to DB"; + len = osal_strlen(pbuf); + stp_dbg_trigger_collect_ftrace(pbuf, len); + _stp_psm_dbg_out_printk(g_stp_psm_dbg); + } + retval = STP_PSM_OPERATION_SUCCESS; + return retval; +} + +static inline INT32 _stp_psm_notify_stp(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_ACTION_T action) +{ + + INT32 retval = STP_PSM_OPERATION_SUCCESS; + + if (action < 0 || action >= STP_PSM_MAX_ACTION) + return STP_PSM_OPERATION_FAIL; + + if (action == EIRQ) { + STP_PSM_PR_DBG("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_PR_DBG("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_PR_LOUD("Action = %s, ACT_INACT state, ready to INACT\n\r", + g_psm_action[action]); + osal_clear_bit(STP_PSM_WMT_EVENT_WAKEUP_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + osal_set_bit(STP_PSM_WMT_EVENT_SLEEP_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + /* wake_up(&stp_psm->wait_wmt_q); */ + osal_trigger_event(&stp_psm->wait_wmt_q); + } else if (action == ROLL_BACK) { + STP_PSM_PR_LOUD("Action = %s, ACT_INACT state, back to ACT\n\r", + g_psm_action[action]); + /* stp_psm->flag &= ~STP_PSM_WMT_EVENT_ROLL_BACK_EN; */ + osal_set_bit(STP_PSM_WMT_EVENT_ROLL_BACK_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + /* wake_up(&stp_psm->wait_wmt_q); */ + osal_trigger_event(&stp_psm->wait_wmt_q); + } else { + if (action < STP_PSM_MAX_ACTION) { + STP_PSM_PR_ERR("Action = %s, state = %d, flag = %ld, abnormal!\n", + g_psm_action[action], + stp_psm->work_state, stp_psm->flag.data); + } else { + STP_PSM_PR_ERR("Invalid Action!!\n\r"); + } + _stp_psm_dbg_out_printk(g_stp_psm_dbg); + + retval = STP_PSM_OPERATION_FAIL; + } + break; + /* stp trigger */ + case INACT_ACT: + if (action == WAKEUP) { + STP_PSM_PR_LOUD("Action = %s, INACT_ACT state, ready to ACT\n\r", + g_psm_action[action]); + osal_clear_bit(STP_PSM_WMT_EVENT_SLEEP_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + osal_set_bit(STP_PSM_WMT_EVENT_WAKEUP_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + /* wake_up(&stp_psm->wait_wmt_q); */ + osal_trigger_event(&stp_psm->wait_wmt_q); + } else if (action == HOST_AWAKE) { + STP_PSM_PR_LOUD("Action = %s, INACT_ACT state, ready to ACT\n\r", + g_psm_action[action]); + osal_clear_bit(STP_PSM_WMT_EVENT_SLEEP_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + osal_set_bit(STP_PSM_WMT_EVENT_WAKEUP_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + /* wake_up(&stp_psm->wait_wmt_q); */ + osal_trigger_event(&stp_psm->wait_wmt_q); + } else if (action == ROLL_BACK) { + STP_PSM_PR_LOUD("Action = %s, INACT_ACT state, back to INACT\n\r", + g_psm_action[action]); + /* stp_psm->flag &= ~STP_PSM_WMT_EVENT_ROLL_BACK_EN; */ + osal_set_bit(STP_PSM_WMT_EVENT_ROLL_BACK_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + /* wake_up(&stp_psm->wait_wmt_q); */ + osal_trigger_event(&stp_psm->wait_wmt_q); + } else { + if (action < STP_PSM_MAX_ACTION) { + STP_PSM_PR_ERR("Action = %s, state = %d, flag = %ld, abnormal!\n", + g_psm_action[action], + stp_psm->work_state, stp_psm->flag.data); + } else { + STP_PSM_PR_ERR("Invalid Action!!\n\r"); + } + _stp_psm_dbg_out_printk(g_stp_psm_dbg); + retval = STP_PSM_OPERATION_FAIL; + } + break; + case INACT: + if (action < STP_PSM_MAX_ACTION) { + STP_PSM_PR_ERR("Action = %s, state = %d, flag = %ld, abnormal!\n", + g_psm_action[action], + stp_psm->work_state, stp_psm->flag.data); + } else { + STP_PSM_PR_ERR("Invalid Action!!\n\r"); + } + _stp_psm_dbg_out_printk(g_stp_psm_dbg); + retval = -1; + break; + case ACT: + if (action < STP_PSM_MAX_ACTION) { + STP_PSM_PR_ERR("Action = %s, state = %d, flag = %ld, abnormal!\n", + g_psm_action[action], + stp_psm->work_state, stp_psm->flag.data); + } else { + STP_PSM_PR_ERR("Invalid Action!!\n\r"); + } + _stp_psm_dbg_out_printk(g_stp_psm_dbg); + + retval = STP_PSM_OPERATION_FAIL; + break; + default: + /*invalid */ + if (action < STP_PSM_MAX_ACTION) { + STP_PSM_PR_ERR("Action = %s, state = %d, flag = %ld, abnormal!\n", + g_psm_action[action], + stp_psm->work_state, stp_psm->flag.data); + } else { + STP_PSM_PR_ERR("Invalid Action!!\n\r"); + } + _stp_psm_dbg_out_printk(g_stp_psm_dbg); + + retval = STP_PSM_OPERATION_FAIL; + break; + } + return retval; +} + +static inline INT32 _stp_psm_notify_wmt(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_ACTION_T action) +{ + INT32 ret = STP_PSM_OPERATION_SUCCESS; + + if (stp_psm == NULL || action < 0 || action >= STP_PSM_MAX_ACTION) + return STP_PSM_OPERATION_FAIL; + + switch (_stp_psm_get_state(stp_psm)) { + case ACT: + + if (action == SLEEP) { + osal_lock_sleepable_lock(&stp_psm->user_lock); + if (osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag)) { + STP_PSM_PR_ERR("psm monitor disabled, can't do sleep op\n"); + osal_unlock_sleepable_lock(&stp_psm->user_lock); + return STP_PSM_OPERATION_FAIL; + } + + _stp_psm_set_state(stp_psm, ACT_INACT); + osal_unlock_sleepable_lock(&stp_psm->user_lock); + _stp_psm_release_data(stp_psm); + + if (stp_psm->wmt_notify) { + ret = stp_psm->wmt_notify(SLEEP); + if (!ret) + _stp_psm_wait_wmt_event_wq(stp_psm); + else + STP_PSM_PR_ERR("stp_psm->wmt_notify return fail\n"); + + } else { + STP_PSM_PR_ERR("stp_psm->wmt_notify = NULL\n"); + ret = STP_PSM_OPERATION_FAIL; + } + } else if (action == WAKEUP || action == HOST_AWAKE) { + STP_PSM_PR_DBG("In ACT state, dont do WAKEUP/HOST_AWAKE again\n"); + _stp_psm_release_data(stp_psm); + } else { + STP_PSM_PR_ERR("Action = %s, state = %d, flag = %ld, abnormal!\n", + g_psm_action[action], + stp_psm->work_state, stp_psm->flag.data); + _stp_psm_dbg_out_printk(g_stp_psm_dbg); + ret = STP_PSM_OPERATION_FAIL; + + } + + break; + + case INACT: + + if (action == WAKEUP) { + _stp_psm_set_state(stp_psm, INACT_ACT); + + if (stp_psm->wmt_notify) { + STP_PSM_PR_DBG("wakeup +wake_lock(%d)\n", + osal_wake_lock_count(&stp_psm->wake_lock)); + osal_wake_lock(&stp_psm->wake_lock); + STP_PSM_PR_DBG("wakeup +wake_lock(%d)#\n", + osal_wake_lock_count(&stp_psm->wake_lock)); + + STP_PSM_PR_DBG("mt_combo_plt_exit_deep_idle++\n"); + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) + mt_combo_plt_exit_deep_idle(COMBO_IF_BTIF); + else { + switch (wmt_plat_get_comm_if_type()) { + case STP_UART_IF_TX: + mt_combo_plt_exit_deep_idle(COMBO_IF_UART); + break; + case STP_SDIO_IF_TX: + mt_combo_plt_exit_deep_idle(COMBO_IF_MSDC); + break; + default: + break; + } + } + STP_PSM_PR_DBG("mt_combo_plt_exit_deep_idle--\n"); + + ret = stp_psm->wmt_notify(WAKEUP); + if (!ret) + _stp_psm_wait_wmt_event_wq(stp_psm); + else + STP_PSM_PR_ERR("stp_psm->wmt_notify return fail\n"); + } else { + STP_PSM_PR_ERR("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_PR_DBG("host awake +wake_lock(%d)\n", + osal_wake_lock_count(&stp_psm->wake_lock)); + osal_wake_lock(&stp_psm->wake_lock); + STP_PSM_PR_DBG("host awake +wake_lock(%d)#\n", + osal_wake_lock_count(&stp_psm->wake_lock)); + + STP_PSM_PR_DBG("mt_combo_plt_exit_deep_idle++\n"); + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) + mt_combo_plt_exit_deep_idle(COMBO_IF_BTIF); + else { + switch (wmt_plat_get_comm_if_type()) { + case STP_UART_IF_TX: + mt_combo_plt_exit_deep_idle(COMBO_IF_UART); + break; + case STP_SDIO_IF_TX: + mt_combo_plt_exit_deep_idle(COMBO_IF_MSDC); + break; + default: + break; + } + } + STP_PSM_PR_DBG("mt_combo_plt_exit_deep_idle--\n"); + + ret = stp_psm->wmt_notify(HOST_AWAKE); + if (!ret) + _stp_psm_wait_wmt_event_wq(stp_psm); + else + STP_PSM_PR_ERR("stp_psm->wmt_notify return fail\n"); + } else { + STP_PSM_PR_ERR("stp_psm->wmt_notify = NULL\n"); + ret = STP_PSM_OPERATION_FAIL; + } + } else if (action == SLEEP) { + STP_PSM_PR_INFO("In INACT state, dont do SLEEP again\n"); + } else { + STP_PSM_PR_ERR("Action = %s, state = %d, flag = %ld, abnormal!\n", + g_psm_action[action], + stp_psm->work_state, stp_psm->flag.data); + _stp_psm_dbg_out_printk(g_stp_psm_dbg); + ret = STP_PSM_OPERATION_FAIL; + } + + break; + + default: + + /*invalid */ + STP_PSM_PR_ERR("Action = %s, state = %d, flag = %ld, abnormal!\n", + g_psm_action[action], + stp_psm->work_state, stp_psm->flag.data); + _stp_psm_dbg_out_printk(g_stp_psm_dbg); + ret = STP_PSM_OPERATION_FAIL; + + break; + } + return ret; +} + +static inline VOID _stp_psm_stp_is_idle(timer_handler_arg arg) +{ + ULONG data; + MTKSTP_PSM_T *stp_psm; + + GET_HANDLER_DATA(arg, data); + stp_psm = (MTKSTP_PSM_T *) data; + osal_clear_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + osal_clear_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + + if (osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag)) { + STP_PSM_PR_DBG("STP-PSM DISABLE!\n"); + return; + } + + if (stp_traffic_start != stp_traffic_current) { + STP_PSM_PR_DBG("Timer extension due to ongoing traffic (%d, %d)\n", + stp_traffic_start, stp_traffic_current); + stp_psm_start_monitor(stp_psm); + return; + } + + STP_PSM_PR_DBG("**IDLE is over %d msec, go to sleep!!!**\n", stp_psm->idle_time_to_sleep); + osal_ftrace_print("**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_PR_DBG("init monitor\n"); + stp_psm->psm_timer.timeoutHandler = _stp_psm_stp_is_idle; + stp_psm->psm_timer.timeroutHandlerData = (ULONG)stp_psm; + osal_timer_create(&stp_psm->psm_timer); + return STP_PSM_OPERATION_SUCCESS; +} + +static inline INT32 _stp_psm_deinit_monitor(MTKSTP_PSM_T *stp_psm) +{ + if (!stp_psm) + return STP_PSM_OPERATION_FAIL; + STP_PSM_PR_INFO("deinit monitor\n"); + osal_timer_stop_sync(&stp_psm->psm_timer); + return 0; +} +static inline INT32 _stp_psm_is_to_block_traffic(MTKSTP_PSM_T *stp_psm) +{ + INT32 iRet = -1; + /* osal_lock_unsleepable_lock(&stp_psm->flagSpinlock); */ + if (osal_test_bit(STP_PSM_BLOCK_DATA_EN, &stp_psm->flag)) + iRet = 1; + else + iRet = 0; + /* osal_unlock_unsleepable_lock(&stp_psm->flagSpinlock); */ + return iRet; +} + +static inline INT32 _stp_psm_is_disable(MTKSTP_PSM_T *stp_psm) +{ + if (osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag)) + return 1; + 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; + UINT64 sec = 0; + ULONG usec = 0; + + if (state < 0 || state >= STP_PSM_MAX_STATE) + return STP_PSM_OPERATION_FAIL; + + osal_get_local_time(&sec, &usec); + while (_stp_psm_get_state(stp_psm) != state && i < limit && mtk_wcn_stp_is_enable()) { + i++; + if (i < 3) + STP_PSM_PR_INFO("STP is waiting state for %s, i=%d, state = %d\n", + g_psm_state[state], i, _stp_psm_get_state(stp_psm)); + osal_sleep_ms(POLL_WAIT); + if (i == 10) { + STP_PSM_PR_WARN("-Wait for %s takes %d msec\n", g_psm_state[state], i * POLL_WAIT); + _stp_psm_opid_dbg_out_printk(g_stp_psm_opid_dbg); + } + } + if (mtk_wcn_stp_is_enable() == 0) { + STP_PSM_PR_INFO("STP disable, maybe do chip reset"); + return STP_PSM_OPERATION_FAIL; + } + + if (i == limit) { + STP_PSM_PR_WARN("-Wait for %s takes %llu usec\n", g_psm_state[state], osal_elapsed_us(sec, usec)); + mtk_wcn_wmt_dump_wmtd_backtrace(); + _stp_psm_opid_dbg_out_printk(g_stp_psm_opid_dbg); + return STP_PSM_OPERATION_FAIL; + } + if (i > 0) + STP_PSM_PR_INFO("+Total waits for %s takes %llu usec\n", + g_psm_state[state], osal_elapsed_us(sec, usec)); + 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_PR_LOUD("*** 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 (pOp != NULL && !RB_FULL(pOpQ)) + RB_PUT(pOpQ, pOp); + else + STP_PSM_PR_ERR("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_PR_INFO("<< wait ret = %d, num of activeQ = %d\n", ret, + * RB_COUNT(&stp_psm->rActiveOpQ)); + */ + if (ret == STP_PSM_OPERATION_SUCCESS) + break; + } else + STP_PSM_PR_ERR("_stp_psm_notify_wmt_wakeup_wq fail, retry = %d !!\n", retry); + /* STP_PSM_PR_INFO("retry = %d\n", retry); */ + retry--; + if (retry == 0) + break; + } while (1); + if (retry == 0) + return STP_PSM_OPERATION_FAIL; + return STP_PSM_OPERATION_SUCCESS; +} + +static inline INT32 _stp_psm_disable(MTKSTP_PSM_T *stp_psm) +{ + INT32 ret = STP_PSM_OPERATION_FAIL; + P_OSAL_THREAD psm_thread; + + STP_PSM_PR_DBG("PSM Disable start\n\r"); + ret = osal_lock_sleepable_lock(&stp_psm->user_lock); + if (ret) { + STP_PSM_PR_ERR("--->lock stp_psm->user_lock failed, ret=%d\n", ret); + return ret; + } + osal_set_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + ret = _stp_psm_do_wakeup(stp_psm); + osal_unlock_sleepable_lock(&stp_psm->user_lock); + if (ret == STP_PSM_OPERATION_SUCCESS) + STP_PSM_PR_DBG("PSM Disable Success\n"); + else { + STP_PSM_PR_ERR("***PSM Disable Fail***\n"); + psm_thread = &stp_psm_i.PSMd; + osal_thread_show_stack(psm_thread); + } + 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_PR_LOUD("PSM Enable start\n\r"); + ret = osal_lock_sleepable_lock(&stp_psm->user_lock); + if (ret) { + STP_PSM_PR_ERR("--->lock stp_psm->user_lock failed, ret=%d\n", ret); + return ret; + } + osal_set_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + ret = _stp_psm_do_wakeup(stp_psm); + if (ret == STP_PSM_OPERATION_SUCCESS) { + osal_clear_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + stp_psm->idle_time_to_sleep = idle_time_to_sleep; + if (osal_wake_lock_count(&stp_psm->wake_lock) == 0) { + STP_PSM_PR_DBG("psm_en+wake_lock(%d)\n", + osal_wake_lock_count(&stp_psm->wake_lock)); + osal_wake_lock(&stp_psm->wake_lock); + STP_PSM_PR_DBG("psm_en+wake_lock(%d)#\n", + osal_wake_lock_count(&stp_psm->wake_lock)); + } + _stp_psm_start_monitor(stp_psm); + STP_PSM_PR_DBG("PSM Enable succeed\n\r"); + } else + STP_PSM_PR_ERR("***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_PR_DBG("stp_psm->is_wmt_quick_ps_support is NULL, return false\n\r"); + return MTK_WCN_BOOL_FALSE; +} + + +MTK_WCN_BOOL stp_psm_is_quick_ps_support(VOID) +{ + return _stp_psm_is_quick_ps_support(); +} + +#if PSM_USE_COUNT_PACKAGE +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; + static INT32 rx_cnt; + INT32 tx_cnt_th = MTK_COMBO_PSM_TX_TH_DEFAULT; + INT32 rx_cnt_th = MTK_COMBO_PSM_RX_TH_DEFAULT; + static INT32 is_tx_first = 1; + static INT32 is_rx_first = 1; + static ULONG tx_end_time; + static ULONG rx_end_time; + long res; + + /* */ + /* 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 defined(MTK_COMBO_PSM_RX_TH) +* osal_strtol(MTK_COMBO_PSM_RX_TH, 10, &res); +* rx_cnt_th = (INT32)res; +* #endif +* #if defined(MTK_COMBO_PSM_TX_TH) +* osal_strtol(MTK_COMBO_PSM_TX_TH, 10, &res); +* tx_cnt_th = (INT32)res; +* #endif +*/ + STP_PSM_PR_DBG("RX TH:%d; TX TH:%d\n\r", rx_cnt_th, tx_cnt_th); + stp_traffic_current++; + 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_PR_INFO("tx cnt = %d in the previous 3 sec,tx_th = %d\n", tx_cnt, + tx_cnt_th); + /* if(tx_cnt > 400)//for high traffic , not to do sleep. */ + if (tx_cnt > tx_cnt_th) { + osal_set_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY, + &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + stp_psm_start_monitor(stp_psm); + } else { + osal_clear_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY, + &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + } + tx_cnt = 0; + if (is_tx_first) + is_tx_first = 0; + } + } else { + rx_cnt++; + + if (((long)jiffies - (long)rx_end_time >= 0) || (is_rx_first)) { + rx_end_time = jiffies + (3 * HZ); + STP_PSM_PR_INFO("rx cnt = %d in the previous 3 sec, rx_th = %d\n", rx_cnt, + rx_cnt_th); + + /* if(rx_cnt > 2000)//for high traffic , not to do sleep. */ + if (rx_cnt > rx_cnt_th) { /* for high traffic , not to do sleep. */ + osal_set_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY, + &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + stp_psm_start_monitor(stp_psm); + } else { + osal_clear_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY, + &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + } + rx_cnt = 0; + if (is_rx_first) + is_rx_first = 0; + } + } + + return 0; +} +#else +static struct timeval tv_now, tv_end; +static INT32 sample_start; +static INT32 tx_sum_len; +static INT32 rx_sum_len; + +INT32 stp_psm_disable_by_tx_rx_density(MTKSTP_PSM_T *stp_psm, INT32 dir, INT32 length) +{ + stp_traffic_current++; + if (sample_start) { + if (dir) + rx_sum_len += length; + else + tx_sum_len += length; + + osal_do_gettimeofday(&tv_now); + /* STP_PSM_PR_INFO("tv_now:%d.%d tv_end:%d.%d\n", tv_now.tv_sec, tv_now.tv_usec, + * tv_end.tv_sec,tv_end.tv_usec); + */ + if (((tv_now.tv_sec == tv_end.tv_sec) && (tv_now.tv_usec > tv_end.tv_usec)) || + (tv_now.tv_sec > tv_end.tv_sec)) { + STP_PSM_PR_INFO("STP speed rx:%d tx:%d\n", rx_sum_len, tx_sum_len); + if ((rx_sum_len + tx_sum_len) > RTX_SPEED_THRESHOLD) { + STP_PSM_PR_INFO("High speed,Disable monitor\n"); + osal_set_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY, &stp_psm->flag); + stp_psm->idle_time_to_sleep = STP_PSM_IDLE_TIME_SLEEP_1000; + stp_psm_start_monitor(stp_psm); + } else { + STP_PSM_PR_INFO("Low speed,Enable monitor\n"); + stp_psm->idle_time_to_sleep = STP_PSM_IDLE_TIME_SLEEP; + osal_clear_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY, &stp_psm->flag); + } + wmt_lib_ps_set_idle_time(stp_psm->idle_time_to_sleep); + sample_start = 0; + rx_sum_len = 0; + tx_sum_len = 0; + } + } else { + sample_start = 1; + osal_do_gettimeofday(&tv_now); + tv_end = tv_now; + tv_end.tv_sec += SAMPLE_DURATION; + } + + return 0; +} +#endif + +/*external function for WMT module to do sleep/wakeup*/ +INT32 stp_psm_set_state(MTKSTP_PSM_T *stp_psm, MTKSTP_PSM_STATE_T state) +{ + return _stp_psm_set_state(stp_psm, state); +} + + +INT32 stp_psm_thread_lock_aquire(MTKSTP_PSM_T *stp_psm) +{ + return _stp_psm_thread_lock_aquire(stp_psm); +} + + +INT32 stp_psm_thread_lock_release(MTKSTP_PSM_T *stp_psm) +{ + return _stp_psm_thread_lock_release(stp_psm); +} + + + +INT32 stp_psm_do_wakeup(MTKSTP_PSM_T *stp_psm) +{ + return _stp_psm_do_wakeup(stp_psm); +} + +INT32 stp_psm_notify_stp(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_ACTION_T action) +{ + + return _stp_psm_notify_stp(stp_psm, action); +} + +INT32 stp_psm_notify_wmt_wakeup(MTKSTP_PSM_T *stp_psm) +{ + return _stp_psm_notify_wmt_wakeup_wq(stp_psm); +} + +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 PUINT8 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_PR_DBG("\n"); + ret = 0; + } else { + STP_PSM_PR_INFO("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_PR_DBG("\n"); + ret = 0; + } else { + STP_PSM_PR_INFO("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_PR_DBG("%s\n", ret ? "enabled" : "disabled"); + } else { + STP_PSM_PR_INFO("Null pointer\n"); + ret = -1; + } + + return ret; +} + +static INT32 _stp_psm_dbg_dmp_in(STP_PSM_RECORD_T *stp_psm_dbg, UINT32 flag, UINT32 line_num) +{ + INT32 index = 0; + struct timeval now; + + if (stp_psm_dbg) { + osal_lock_unsleepable_lock(&stp_psm_dbg->lock); + osal_do_gettimeofday(&now); + index = stp_psm_dbg->in - 1; + index = (index + STP_PSM_DBG_SIZE) % STP_PSM_DBG_SIZE; + STP_PSM_PR_DBG("index(%d)\n", index); + stp_psm_dbg->queue[stp_psm_dbg->in].prev_flag = stp_psm_dbg->queue[index].cur_flag; + stp_psm_dbg->queue[stp_psm_dbg->in].cur_flag = flag; + stp_psm_dbg->queue[stp_psm_dbg->in].line_num = line_num; + stp_psm_dbg->queue[stp_psm_dbg->in].package_no = g_record_num++; + stp_psm_dbg->queue[stp_psm_dbg->in].sec = now.tv_sec; + stp_psm_dbg->queue[stp_psm_dbg->in].usec = now.tv_usec; + stp_psm_dbg->size++; + STP_PSM_PR_DBG("pre_Flag = %d, cur_flag = %d\n", stp_psm_dbg->queue[stp_psm_dbg->in].prev_flag, + stp_psm_dbg->queue[stp_psm_dbg->in].cur_flag); + stp_psm_dbg->size = (stp_psm_dbg->size > STP_PSM_DBG_SIZE) ? STP_PSM_DBG_SIZE : stp_psm_dbg->size; + stp_psm_dbg->in = (stp_psm_dbg->in >= (STP_PSM_DBG_SIZE - 1)) ? (0) : (stp_psm_dbg->in + 1); + STP_PSM_PR_DBG("record size = %d, in = %d num = %d\n", stp_psm_dbg->size, stp_psm_dbg->in, line_num); + + osal_unlock_unsleepable_lock(&stp_psm_dbg->lock); + } + return 0; +} + +static INT32 _stp_psm_dbg_out_printk(STP_PSM_RECORD_T *stp_psm_dbg) +{ + + UINT32 dumpSize = 0; + UINT32 inIndex = 0; + UINT32 outIndex = 0; + + if (!stp_psm_dbg) { + STP_PSM_PR_ERR("NULL g_stp_psm_dbg reference\n"); + return -1; + } + osal_lock_unsleepable_lock(&stp_psm_dbg->lock); + + inIndex = stp_psm_dbg->in; + dumpSize = stp_psm_dbg->size; + if (dumpSize == STP_PSM_DBG_SIZE) + outIndex = inIndex; + else + outIndex = ((inIndex + STP_PSM_DBG_SIZE) - dumpSize) % STP_PSM_DBG_SIZE; + + STP_PSM_PR_INFO("loged record size = %d, in(%d), out(%d)\n", dumpSize, inIndex, outIndex); + while (dumpSize > 0) { + + pr_info("STP-PSM:%d.%ds, n(%d)pre_flag(%d)cur_flag(%d)line_no(%d)\n", + stp_psm_dbg->queue[outIndex].sec, + stp_psm_dbg->queue[outIndex].usec, + stp_psm_dbg->queue[outIndex].package_no, + stp_psm_dbg->queue[outIndex].prev_flag, + stp_psm_dbg->queue[outIndex].cur_flag, stp_psm_dbg->queue[outIndex].line_num); + + outIndex = (outIndex >= (STP_PSM_DBG_SIZE - 1)) ? (0) : (outIndex + 1); + dumpSize--; + + } + + osal_unlock_unsleepable_lock(&stp_psm_dbg->lock); + + return 0; +} + +static INT32 _stp_psm_opid_dbg_dmp_in(P_STP_PSM_OPID_RECORD p_opid_dbg, UINT32 opid, UINT32 line_num) +{ + INT32 index = 0; + struct timeval now; + UINT64 ts; + ULONG nsec; + + osal_get_local_time(&ts, &nsec); + if (p_opid_dbg) { + osal_lock_unsleepable_lock(&p_opid_dbg->lock); + osal_do_gettimeofday(&now); + index = p_opid_dbg->in - 1; + index = (index + STP_PSM_DBG_SIZE) % STP_PSM_DBG_SIZE; + STP_PSM_PR_DBG("index(%d)\n", index); + p_opid_dbg->queue[p_opid_dbg->in].prev_flag = p_opid_dbg->queue[index].cur_flag; + p_opid_dbg->queue[p_opid_dbg->in].cur_flag = opid; + p_opid_dbg->queue[p_opid_dbg->in].line_num = line_num; + p_opid_dbg->queue[p_opid_dbg->in].package_no = g_opid_record_num++; + p_opid_dbg->queue[p_opid_dbg->in].sec = now.tv_sec; + p_opid_dbg->queue[p_opid_dbg->in].usec = now.tv_usec; + p_opid_dbg->queue[p_opid_dbg->in].pid = current->pid; + p_opid_dbg->queue[p_opid_dbg->in].l_sec = ts; + p_opid_dbg->queue[p_opid_dbg->in].l_nsec = nsec; + p_opid_dbg->size++; + STP_PSM_PR_DBG("pre_opid = %d, cur_opid = %d\n", p_opid_dbg->queue[p_opid_dbg->in].prev_flag, + p_opid_dbg->queue[p_opid_dbg->in].cur_flag); + p_opid_dbg->size = (p_opid_dbg->size > STP_PSM_DBG_SIZE) ? STP_PSM_DBG_SIZE : p_opid_dbg->size; + p_opid_dbg->in = (p_opid_dbg->in >= (STP_PSM_DBG_SIZE - 1)) ? (0) : (p_opid_dbg->in + 1); + STP_PSM_PR_DBG("opid record size = %d, in = %d num = %d\n", p_opid_dbg->size, p_opid_dbg->in, + line_num); + + osal_unlock_unsleepable_lock(&p_opid_dbg->lock); + } + return 0; + +} + +static INT32 _stp_psm_opid_dbg_out_printk(P_STP_PSM_OPID_RECORD p_opid_dbg) +{ + UINT32 dumpSize = 0; + UINT32 inIndex = 0; + UINT32 outIndex = 0; + + if (!p_opid_dbg) { + STP_PSM_PR_ERR("NULL p_opid_dbg reference\n"); + return -1; + } + osal_lock_unsleepable_lock(&p_opid_dbg->lock); + + inIndex = p_opid_dbg->in; + dumpSize = p_opid_dbg->size; + if (dumpSize == STP_PSM_DBG_SIZE) + outIndex = inIndex; + else + outIndex = ((inIndex + STP_PSM_DBG_SIZE) - dumpSize) % STP_PSM_DBG_SIZE; + + STP_PSM_PR_INFO("loged record size = %d, in(%d), out(%d)\n", dumpSize, inIndex, outIndex); + while (dumpSize > 0) { + + pr_info("STP-PSM:%d.%ds, time[%llu.%06lu], n(%d)pre_flag(%d)cur_flag(%d)line_no(%d) pid(%d)\n", + p_opid_dbg->queue[outIndex].sec, + p_opid_dbg->queue[outIndex].usec, + p_opid_dbg->queue[outIndex].l_sec, + p_opid_dbg->queue[outIndex].l_nsec, + p_opid_dbg->queue[outIndex].package_no, + p_opid_dbg->queue[outIndex].prev_flag, + p_opid_dbg->queue[outIndex].cur_flag, + p_opid_dbg->queue[outIndex].line_num, p_opid_dbg->queue[outIndex].pid); + + outIndex = (outIndex >= (STP_PSM_DBG_SIZE - 1)) ? (0) : (outIndex + 1); + dumpSize--; + + } + + osal_unlock_unsleepable_lock(&p_opid_dbg->lock); + + return 0; + +} + +VOID stp_psm_print_op_history(VOID) +{ + osal_op_history_print(&stp_psm->op_history, "_stp_psm_proc"); +} + +MTKSTP_PSM_T *stp_psm_init(VOID) +{ + INT32 err = 0; + INT32 i = 0; + INT32 ret = -1; + + STP_PSM_PR_DBG("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->update_wmt_fw_patch_chip_rst = wmt_lib_update_fw_patch_chip_rst; + stp_psm->flag.data = 0; + stp_psm->stp_tx_cb = NULL; + stp_psm_set_sleep_enable(stp_psm); + + ret = osal_fifo_init(&stp_psm->hold_fifo, NULL, STP_PSM_FIFO_SIZE); + if (ret < 0) { + STP_PSM_PR_ERR("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_sleepable_lock_init(&stp_psm->hold_fifo_spinlock_global); + osal_unsleepable_lock_init(&stp_psm->wq_spinlock); + osal_sleepable_lock_init(&stp_psm->stp_psm_lock); + +/* osal_unsleepable_lock_init(&stp_psm->flagSpinlock); */ + + osal_memcpy(stp_psm->wake_lock.name, "MT662x", 6); + stp_psm->wake_lock.init_flag = 0; + 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; + osal_op_history_init(&stp_psm->op_history, 16); + /*Generate PSM thread, to servie STP-CORE and WMT-CORE for sleeping, waking up and host awake */ + stp_psm->PSMd.pThreadData = (PVOID) stp_psm; + stp_psm->PSMd.pThreadFunc = (PVOID) _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_PR_ERR("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_PR_ERR("__stp_psm_init ERROR\n"); + goto ERR_EXIT6; + } + /* Start STPd thread */ + ret = osal_thread_run(&stp_psm->PSMd); + if (ret < 0) { + STP_PSM_PR_ERR("osal_thread_run FAILS\n"); + goto ERR_EXIT6; + } + + g_stp_psm_dbg = (STP_PSM_RECORD_T *) osal_malloc(osal_sizeof(STP_PSM_RECORD_T)); + if (!g_stp_psm_dbg) { + STP_PSM_PR_ERR("stp psm dbg allocate memory fail!\n"); + return NULL; + } + osal_memset(g_stp_psm_dbg, 0, osal_sizeof(STP_PSM_RECORD_T)); + osal_unsleepable_lock_init(&g_stp_psm_dbg->lock); + + g_stp_psm_opid_dbg = (STP_PSM_OPID_RECORD *) osal_malloc(osal_sizeof(STP_PSM_OPID_RECORD)); + if (!g_stp_psm_opid_dbg) { + STP_PSM_PR_ERR("stp psm dbg allocate memory fail!\n"); + return NULL; + } + osal_memset(g_stp_psm_opid_dbg, 0, osal_sizeof(STP_PSM_OPID_RECORD)); + osal_unsleepable_lock_init(&g_stp_psm_opid_dbg->lock); + + return stp_psm; + +ERR_EXIT6: + + ret = osal_thread_destroy(&stp_psm->PSMd); + if (ret < 0) { + STP_PSM_PR_ERR("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_PR_INFO("psm deinit\n"); + if (g_stp_psm_dbg) { + osal_unsleepable_lock_deinit(&g_stp_psm_dbg->lock); + osal_free(g_stp_psm_dbg); + g_stp_psm_dbg = NULL; + } + + if (!stp_psm) + return STP_PSM_OPERATION_FAIL; + + ret = osal_thread_destroy(&stp_psm->PSMd); + if (ret < 0) + STP_PSM_PR_ERR("osal_thread_destroy FAILS\n"); + + ret = _stp_psm_deinit_monitor(stp_psm); + if (ret < 0) + STP_PSM_PR_ERR("_stp_psm_deinit_monitor ERROR\n"); + + osal_wake_lock_deinit(&stp_psm->wake_lock); + osal_fifo_deinit(&stp_psm->hold_fifo); + osal_sleepable_lock_deinit(&stp_psm->user_lock); + /*psm_fifo_lock_deinit(stp_psm);*/ + osal_sleepable_lock_deinit(&stp_psm->hold_fifo_spinlock_global); + osal_unsleepable_lock_deinit(&stp_psm->wq_spinlock); + osal_sleepable_lock_deinit(&stp_psm->stp_psm_lock); +/* osal_unsleepable_lock_deinit(&stp_psm->flagSpinlock); */ + + return STP_PSM_OPERATION_SUCCESS; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_main/core/stp_core.c b/drivers/misc/mediatek/connectivity/common/common_main/core/stp_core.c new file mode 100644 index 0000000000000..9c6eb85f1dfd1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/core/stp_core.c @@ -0,0 +1,3588 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include "osal_typedef.h" +#include "stp_core.h" +#include "psm_core.h" +#include "btm_core.h" +#include "stp_dbg.h" +#include "stp_sdio.h" +#include "stp_btif.h" +#include "wmt_lib.h" +#include "wmt_step.h" +#include "wmt_detect.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 */ +#define STP_MAX_TX_TIMEOUT_LOOP 3 + +INT32 gStpDbgLvl = STP_LOG_INFO; +unsigned int chip_reset_only; +INT32 wmt_dbg_sdio_retry_ctrl = 1; +INT32 gCrcErrorCount; + +#define STP_POLL_CPUPCR_NUM 5 +#define STP_POLL_CPUPCR_DELAY 1 + +/* global variables */ +static const UINT8 stp_delimiter[STP_DEL_SIZE] = { 0x55, 0x55 }; + +static INT32 fgEnableNak; /* 0=enable NAK; 1=disable NAK */ +static INT32 fgEnableDelimiter; /* 0=disable Delimiter; 1=enable Delimiter */ +/* common interface */ +static IF_TX sys_if_tx; +static RX_HAS_PENDING_DATA sys_rx_has_pending_data; +static TX_HAS_PENDING_DATA sys_tx_has_pending_data; +static RX_THREAD_GET sys_rx_thread_get; +/* event/signal */ +static EVENT_SET sys_event_set; +static EVENT_TX_RESUME sys_event_tx_resume; +static FUNCTION_STATUS sys_check_function_status; +/* kernel lib */ +/* 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_EMI_DUMP_FLAG(x) ((x).f_emidump) +#define STP_SET_EMI_DUMP_FLAG(x, v) ((x).f_emidump = (v)) + +#define STP_WMT_LAST_CLOSE(x) ((x).f_wmt_last_close) +#define STP_SET_WMT_LAST_CLOSE(x, v) ((x).f_wmt_last_close = (v)) + +#define STP_ASSERT(x) ((x).f_evt_err_assert) +#define STP_SET_ASSERT(x, v) ((x).f_evt_err_assert = (v)) + +#define STP_ASSERT_IN_PROGRESS(x) ((x).f_assert_in_progress) +#define STP_SET_ASSERT_IN_PROGRESS(x, v) ((x).f_assert_in_progress = (v)) + +#define STP_IS_SUPPORT_GPSL5(x) ((x).f_gpsl5_en != 0) +#define STP_NOT_SUPPORT_GPSL5(x) ((x).f_gpsl5_en == 0) +#define STP_SET_SUPPORT_GPSL5(x, v) ((x).f_gpsl5_en = (v)) + + +/*[PatchNeed]Need to calculate the timeout value*/ +static UINT32 mtkstp_tx_timeout = MTKSTP_TX_TIMEOUT; +static mtkstp_parser_state prev_state = -1; + + +#define CONFIG_DEBUG_STP_TRAFFIC_SUPPORT +#ifdef CONFIG_DEBUG_STP_TRAFFIC_SUPPORT +static MTKSTP_DBG_T *g_mtkstp_dbg; +#endif +static VOID stp_dbg_pkt_log(INT32 type, INT32 txAck, INT32 seq, INT32 crc, INT32 dir, + const PUINT8 pBuf, INT32 len); +static MTK_WCN_BOOL stp_check_crc(PUINT8 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(timer_handler_arg arg); +static VOID stp_dump_data(const PUINT8 buf, const PUINT8 title, const UINT32 len); +static VOID stp_dump_tx_queue(UINT32 txseq); +static INT32 stp_is_apply_powersaving(VOID); +#if 0 +static INT32 stp_is_privileges_cmd(const UINT8 *buffer, const UINT32 length, const UINT8 type); +#endif +static MTK_WCN_BOOL stp_is_tx_res_available(UINT32 length); +static VOID stp_add_to_tx_queue(const PUINT8 buffer, UINT32 length); +static INT32 stp_add_to_rx_queue(PUINT8 buffer, UINT32 length, UINT8 type); +static VOID stp_send_tx_queue(UINT32 txseq); +static VOID stp_send_ack(UINT8 txAck, UINT8 nak); +static INT32 stp_process_rxack(VOID); +static VOID stp_process_packet(VOID); +static VOID stp_process_header_only_packet(VOID); +static VOID stp_sdio_process_packet(VOID); +static VOID stp_trace32_dump(VOID); +static VOID stp_sdio_trace32_dump(VOID); +static LONG stp_parser_dmp_num(PUINT8 str); +static INT32 wmt_parser_data(PUINT8 buffer, UINT32 length, UINT8 type); +static MTK_WCN_BOOL mtk_wcn_stp_is_info_task(VOID); + +INT32 __weak mtk_wcn_consys_stp_btif_logger_ctrl(enum _ENUM_BTIF_DBG_ID_ flag) +{ + STP_INFO_FUNC("in combo flow, mtk_wcn_consys_stp_btif_logger_ctrl is not define!!\n"); + return 0; +} +INT32 __weak mtk_wcn_consys_stp_btif_open(VOID) +{ + STP_INFO_FUNC("in combo flow, mtk_wcn_consys_stp_btif_open is not define!!\n"); + + return 0; +} + +INT32 __weak mtk_wcn_consys_stp_btif_close(VOID) +{ + STP_INFO_FUNC("in combo flow, mtk_wcn_consys_stp_btif_close is not define!!\n"); + + return 0; +} + +INT32 __weak mtk_wcn_consys_stp_btif_rx_cb_register(MTK_WCN_BTIF_RX_CB rx_cb) +{ + STP_INFO_FUNC("in combo flow, mtk_wcn_consys_stp_btif_rx_cb_register is not define!!\n"); + return 0; +} + +INT32 __weak mtk_wcn_consys_stp_btif_tx(const PUINT8 pBuf, const UINT32 len, PUINT32 written_len) +{ + STP_INFO_FUNC("in combo flow, mtk_wcn_consys_stp_btif_tx is not define!!\n"); + + return 0; +} + +INT32 __weak mtk_wcn_consys_stp_btif_wakeup(VOID) +{ + STP_INFO_FUNC("in combo flow, mtk_wcn_consys_stp_btif_wakeup is not define!!\n"); + + return 0; +} + +INT32 __weak mtk_wcn_consys_stp_btif_lpbk_ctrl(enum _ENUM_BTIF_LPBK_MODE_ mode) +{ + STP_INFO_FUNC("in combo flow, mtk_wcn_consys_stp_btif_lpbk_ctrl is not define!!\n"); + + return 0; +} + +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(); */ + /* pr_debug("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(); */ + /* pr_debug("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(INT32 dbglevel) +{ + if (dbglevel >= 0 && dbglevel <= 4) { + gStpDbgLvl = dbglevel; + STP_INFO_FUNC("gStpDbgLvl = %d\n", gStpDbgLvl); + return MTK_WCN_BOOL_TRUE; + } + STP_INFO_FUNC("invalid stp debug level. gStpDbgLvl = %d\n", gStpDbgLvl); + return MTK_WCN_BOOL_FALSE; +} + +static VOID stp_sdio_process_packet(VOID) +{ + MTK_WCN_BOOL is_function_active = 0; + + 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)) { + if (stp_core_ctx.parser.type == WMT_TASK_INDX) + wmt_parser_data(stp_core_ctx.rx_buf, stp_core_ctx.rx_counter, + stp_core_ctx.parser.type); + else { + stp_add_to_rx_queue(stp_core_ctx.rx_buf, stp_core_ctx.rx_counter, + stp_core_ctx.parser.type); + + /*notify corresponding subfunction of incoming data */ + (*sys_event_set)(stp_core_ctx.parser.type); + } + } else { + if (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); + } + } + } +} + +static MTK_WCN_BOOL mtk_wcn_stp_is_info_task(VOID) +{ + if (STP_NOT_SUPPORT_GPSL5(stp_core_ctx) && (stp_core_ctx.parser.type == INFO_TASK_INDX)) + return MTK_WCN_BOOL_TRUE; + else + return MTK_WCN_BOOL_FALSE; +} + +static VOID stp_trace32_dump(VOID) +{ + if (STP_IS_ENABLE_DBG(stp_core_ctx) && (stp_core_ctx.parser.type == STP_TASK_INDX)) { + STP_INFO_FUNC("[len=%d][type=%d]%s\n", stp_core_ctx.rx_counter, + stp_core_ctx.parser.type, stp_core_ctx.rx_buf); + } + /*Runtime FW Log */ + else if (STP_IS_ENABLE_DBG(stp_core_ctx) && mtk_wcn_stp_is_info_task()) { + 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_dbg_dump_package(); + + osal_dbg_assert_aee(stp_core_ctx.rx_buf, stp_core_ctx.rx_buf); + /*Whole Chip Reset Procedure Invoke */ + if (STP_IS_ENABLE_RST(stp_core_ctx)) { + STP_SET_READY(stp_core_ctx, 0); + stp_btm_notify_wmt_rst_wq(STP_BTM_CORE(stp_core_ctx)); + } else + STP_INFO_FUNC("No to launch whole chip reset! for debugging purpose\n"); + } +} + +static LONG stp_parser_dmp_num(PUINT8 str) +{ + PUINT8 pParserDmpStr = "Dump="; + PUINT8 pStr = NULL; + PUINT8 pDtr = NULL; + PUINT8 pTemp = NULL; + INT32 ret = -1; + UINT32 len = 0; + UINT8 tempBuf[64] = {0}; + LONG res; + + + if (!str) { + STP_DBG_PR_ERR("NULL string source\n"); + return -1; + } + + pStr = str; + pDtr = osal_strstr(pStr, pParserDmpStr); + if (pDtr != NULL) { + pDtr += osal_strlen(pParserDmpStr); + pTemp = pDtr; + while (*pTemp >= '0' && *pTemp <= '9') + pTemp++; + } else { + STP_DBG_PR_WARN("parser string 'Dump=' is not found\n"); + return -2; + } + len = pTemp - pDtr; + osal_memcpy(&tempBuf[0], pDtr, len); + tempBuf[len] = '\0'; + ret = osal_strtol(tempBuf, 10, &res); + if (ret) { + STP_DBG_PR_ERR(" get 'Dump=' from firmware failed (%d)", ret); + return -4; + } + + return res; +} + +static VOID stp_sdio_trace32_dump(VOID) +{ + LONG dmp_num = 0; + int coredump_end_str_len = osal_strlen("coredump end"); + int len; + + if (STP_IS_ENABLE_DBG(stp_core_ctx) && (stp_core_ctx.parser.type == STP_TASK_INDX) && + (mtk_wcn_stp_coredump_flag_get() != 0)) { + if (stp_core_ctx.rx_counter != 0) { + STP_SET_READY(stp_core_ctx, 0); + mtk_wcn_stp_ctx_save(); + if (stp_core_ctx.assert_info_cnt == 0) { + dmp_num = stp_parser_dmp_num(stp_core_ctx.rx_buf); + if (dmp_num > 0 && dmp_num < PARSER_CORE_DUMP_NUM) { + STP_INFO_FUNC("parser dmp_num is %ld\n", dmp_num); + stp_dbg_dump_num(dmp_num); + } else if (dmp_num > PARSER_CORE_DUMP_NUM) { + STP_INFO_FUNC("parser dmp_num is out of range %ld\n", + dmp_num); + stp_dbg_dump_num(PARSER_CORE_DUMP_NUM); + } else { + STP_INFO_FUNC("parser dmp_num not found %ld\n", dmp_num); + stp_dbg_dump_num(CORE_DUMP_NUM); + } + } + /*STP_DBG_FW_ASSERT */ + stp_dbg_log_pkt(g_mtkstp_dbg, STP_DBG_FW_DMP, STP_TASK_INDX, 0, 0, 0, 0, + (stp_core_ctx.rx_counter + 1), stp_core_ctx.rx_buf); + } + stp_core_ctx.assert_info_cnt++; + if (stp_core_ctx.assert_info_cnt == 20) + STP_INFO_FUNC("only dump 20 packages from the beginning\n"); + else if (stp_core_ctx.assert_info_cnt < 20) + osal_err_print("[len=%d][type=%d]counter[%d]\n%s\n", stp_core_ctx.rx_counter, + stp_core_ctx.parser.type, stp_core_ctx.assert_info_cnt, stp_core_ctx.rx_buf); + + len = stp_core_ctx.rx_counter - coredump_end_str_len - 2; + if ((len >= 0) && + (stp_core_ctx.rx_counter < MTKSTP_BUFFER_SIZE) && + (osal_strncmp("coredump end", stp_core_ctx.rx_buf + + len, coredump_end_str_len) == 0)) { + STP_INFO_FUNC("%d coredump packets received\n", stp_core_ctx.assert_info_cnt); + STP_ERR_FUNC("coredump end\n"); + mtk_wcn_stp_ctx_restore(); + } + } + /*Runtime FW Log */ + else if (STP_IS_ENABLE_DBG(stp_core_ctx) && mtk_wcn_stp_is_info_task()) { + 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_dbg_dump_package(); + if (mtk_wcn_stp_coredump_flag_get() == 0) { + osal_err_print("[len=%d][type=%d]\n%s\n", stp_core_ctx.rx_counter, + stp_core_ctx.parser.type, stp_core_ctx.rx_buf); + STP_ERR_FUNC("fw error happened 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"); + } +} + +static VOID stp_process_header_only_packet(VOID) +{ + if (stp_core_ctx.parser.length == 0) { + INT32 fgTriggerResume = (-1); + /* osal_lock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ + stp_ctx_lock(&stp_core_ctx); + if (stp_core_ctx.inband_rst_set == 0) { + stp_dbg_pkt_log(STP_TASK_INDX, + stp_core_ctx.parser.ack, + stp_core_ctx.parser.seq, + 5, /* STP type id */ + PKT_DIR_RX, + NULL, + 0); + fgTriggerResume = stp_process_rxack(); + } else { + STP_WARN_FUNC + ("Now it's inband reset process and drop ACK packet.\n"); + } + if (fgTriggerResume == 0) { + /* notify adaptation layer for + * possible tx resume mechanism + */ + (*sys_event_tx_resume) (stp_core_ctx.sequence.winspace); + } + stp_ctx_unlock(&stp_core_ctx); + /* osal_unlock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ + stp_change_rx_state(MTKSTP_SYNC); + stp_core_ctx.rx_counter = 0; + } else { + stp_change_rx_state(MTKSTP_DATA); + stp_core_ctx.rx_counter = 0; + } +} + +#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 PUINT8 pBuf, + INT32 len) +{ + +#ifndef CONFIG_LOG_STP_INTERNAL + return; +#endif + + if (STP_IS_ENABLE_DBG(stp_core_ctx)) { + if (STP_IS_READY(stp_core_ctx) || + (!STP_IS_READY(stp_core_ctx) && (type > WIFI_TASK_INDX) + && (type != ANT_TASK_INDX) && (len != 0))) + 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 or not ready or len is 0\n"); + } +} + +/***************************************************************************** +* 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(PUINT8 buffer, UINT32 length, UINT16 crc) +{ + /*----------------------------------------------------------------*/ + /* Local Variables */ + /*----------------------------------------------------------------*/ + UINT16 checksum; + + /*----------------------------------------------------------------*/ + /* Code Body */ + /*----------------------------------------------------------------*/ + + /* FIXME: Add STP feature: check or skip crc */ + + checksum = osal_crc16(buffer, length); + if (checksum == crc) + return MTK_WCN_BOOL_TRUE; + STP_ERR_FUNC("CRC fail, length = %d, rx = %x, calc = %x \r\n", length, crc, checksum); + return MTK_WCN_BOOL_FALSE; +} + +/***************************************************************************** +* FUNCTION +* stp_update_tx_queue +* DESCRIPTION +* update packet's ACK field +* PARAMETERS +* txseq [IN] index of the tx packet which we want to update +* RETURNS +* void +*****************************************************************************/ +static void stp_update_tx_queue(UINT32 txseq) +{ + INT32 tx_read, i; + UINT8 checksum = 0; + + tx_read = stp_core_ctx.tx_start_addr[txseq]; + if (tx_read < 0) + return; + + stp_core_ctx.tx_buf[tx_read] &= 0xf8; + stp_core_ctx.tx_buf[tx_read] |= stp_core_ctx.sequence.txack; + + for (i = 0; i < 3; i++) { + checksum += stp_core_ctx.tx_buf[tx_read]; + tx_read++; + if (tx_read >= MTKSTP_BUFFER_SIZE) + tx_read -= MTKSTP_BUFFER_SIZE; + } + + stp_core_ctx.tx_buf[tx_read] = checksum; +} + +/***************************************************************************** +* FUNCTION +* stp_rest_ctx_state +* DESCRIPTION +* Reset stp context state variables only. Mutex and timer resources are not touched. +* +* PARAMETERS +* void +* RETURNS +* void +*****************************************************************************/ +static VOID stp_rest_ctx_state(VOID) +{ + INT32 i; + + 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.sequence.tx_timeout_loop = 0; + stp_core_ctx.sequence.rx_resync = 0; + stp_core_ctx.sequence.rx_resync_seq = 0xFF; + 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; +} + +/* static void stp_tx_timeout_handler(void){ */ +static void stp_tx_timeout_handler(timer_handler_arg arg) +{ + if (mtk_wcn_stp_coredump_start_get() == 1) { + STP_WARN_FUNC("Starting coredump, skip tx retry.\n"); + return; + } + STP_WARN_FUNC("call retry btm retry wq ...\n"); + /*shorten the softirq lattency */ + stp_btm_notify_stp_retry_wq(STP_BTM_CORE(stp_core_ctx)); +} + +VOID stp_do_tx_timeout(VOID) +{ + UINT32 seq; + UINT32 ret; + UINT8 resync[4]; + INT32 tx_pending_state; + INT32 rx_pending_state; + + STP_WARN_FUNC + ("==============================================================================\n"); + osal_dump_thread_state("btif_rxd"); + if (!mtk_wcn_stp_is_sdio_mode()) + mtk_wcn_consys_stp_btif_logger_ctrl(BTIF_DUMP_BTIF_IRQ); + + tx_pending_state = sys_tx_has_pending_data(); + /* Sys_rx_has_pending_data cannot be called after stp_ctx_lock(&stp_core_ctx), + * there will be a deadlock problem, because sys_rx_has_pending_data will take + * the mutex of btif_rxd, and btif_rxd may need to return TX ack during parsing + * data process. This will take stp_ctx_lock(&stp_core_ctx), causing deadlock + */ + rx_pending_state = sys_rx_has_pending_data(); + STP_INFO_FUNC("check tx/rx has pending data(%d/%d).\n", tx_pending_state, rx_pending_state); + stp_ctx_lock(&stp_core_ctx); + + if (stp_core_ctx.sequence.retry_times > (MTKSTP_RETRY_LIMIT)) { + STP_INFO_FUNC("STP retry times(%d) have reached retry limit,stop it\n", + stp_core_ctx.sequence.retry_times); + stp_ctx_unlock(&stp_core_ctx); + return; + } + + seq = stp_core_ctx.sequence.rxack; + INDEX_INC(seq); + + if (seq != stp_core_ctx.sequence.txseq) { + osal_memset(&resync[0], 0x7f, 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 { + /* rxack (=last rx ack), txack (=last rx seq), txseq (=next tx seq) */ + STP_WARN_FUNC("[stp.ctx]rxack/txack/txseq=%d/%d/%d(Resend from%d->%d)\n", + stp_core_ctx.sequence.rxack, + stp_core_ctx.sequence.txack, + stp_core_ctx.sequence.txseq, + 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) { + do { + int reason = 42; + + if (tx_pending_state > 0 || (tx_pending_state == 0 && rx_pending_state > 0)) { + if (stp_core_ctx.sequence.tx_timeout_loop < STP_MAX_TX_TIMEOUT_LOOP) { + stp_core_ctx.sequence.retry_times = 0; + stp_core_ctx.sequence.tx_timeout_loop++; + STP_INFO_FUNC("extend tx retry only.\n"); + break; + } + + STP_ERR_FUNC("there are still some data in tx/rx buffer.\n"); + /* Reason number 45 means that stp data path still has data, + * possibly a driver problem + */ + reason = 45; + } + + WMT_STEP_COMMAND_TIMEOUT_DO_ACTIONS_FUNC("STP TX no ack timeout"); + osal_timer_stop(&stp_core_ctx.tx_timer); + stp_ctx_unlock(&stp_core_ctx); + + STP_ERR_FUNC("mtkstp_tx_timeout_handler: wmt_stop_timer\n"); + + STP_ERR_FUNC("TX retry limit = %d\n", MTKSTP_RETRY_LIMIT); + osal_assert(0); + stp_notify_btm_dump(STP_BTM_CORE(stp_core_ctx)); + + /*Whole Chip Reset Procedure Invoke */ + stp_psm_disable(STP_PSM_CORE(stp_core_ctx)); + STP_INFO_FUNC("**STP NoAck trigger firmware assert**\n"); + wmt_lib_trigger_assert(WMTDRV_TYPE_WMT, 42); + return; + } while (0); + } + } + + stp_ctx_unlock(&stp_core_ctx); + /*polling cpupcr when no ack occurs at first retry */ + stp_dbg_poll_cpupcr(STP_POLL_CPUPCR_NUM, STP_POLL_CPUPCR_DELAY, 1); + STP_WARN_FUNC + ("==============================================================================#\n"); +} + +static VOID stp_dump_data(const PUINT8 buf, const PUINT8 title, const UINT32 len) +{ + osal_buffer_dump(buf, title, len, 32); +} + +/***************************************************************************** + * FUNCTION + * stp_tx_timeout_handler + * DESCRIPTION + * tx timeout handler, send resync & retransmitt + * PARAMETERS + * void + * RETURNS + * void + *****************************************************************************/ +static VOID stp_dump_tx_queue(UINT32 txseq) +{ + INT32 tx_read, tx_length, last_len; + + tx_read = stp_core_ctx.tx_start_addr[txseq]; + tx_length = stp_core_ctx.tx_length[txseq]; + + STP_ERR_FUNC("tx_seq=%d ..", txseq); + + if (tx_read + tx_length < MTKSTP_BUFFER_SIZE) + stp_dump_data(&stp_core_ctx.tx_buf[tx_read], "tx_q", (tx_length >= 8) ? (8) : (tx_length)); + else { + last_len = MTKSTP_BUFFER_SIZE - tx_read; + stp_dump_data(&stp_core_ctx.tx_buf[tx_read], "tx_q_0", (last_len >= 8) ? (8) : (last_len)); + stp_dump_data(&stp_core_ctx.tx_buf[0], "tx_q_0", + ((tx_length - last_len) ? (8) : (tx_length - last_len))); + } +} + +/***************************************************************************** +* FUNCTION +* stp_is_apply_powersaving +* DESCRIPTION +* Check if STP support power saving mode. +* PARAMETERS +* +* RETURNS +* True: support power saving False: not support power saving +*****************************************************************************/ +static INT32 stp_is_apply_powersaving(VOID) +{ + + if (STP_IS_READY(stp_core_ctx) && !stp_psm_is_disable(STP_PSM_CORE(stp_core_ctx))) { + /* osal_dbg_print("apply power saving\n"); */ + return MTK_WCN_BOOL_TRUE; + } + if (mtk_wcn_stp_is_sdio_mode()) + return MTK_WCN_BOOL_FALSE; + STP_DBG_FUNC("not apply power saving\n"); + return MTK_WCN_BOOL_FALSE; +} + +#if 0 +/***************************************************************************** +* FUNCTION +* stp_is_privileges_cmd +* DESCRIPTION +* Check if the data is privilege command +* PARAMETERS +* +* RETURNS +* True/False +*****************************************************************************/ + +static INT32 stp_is_privileges_cmd(const UINT8 *buffer, const UINT32 length, const UINT8 type) +{ + typedef struct privileges_cmd { + UINT32 length; + UINT8 type; + UINT8 buf[7]; /* MAX length of target command is only 5 currently */ + } p_cmd_t; + + p_cmd_t p_cmd_table[] = { + {0x05, WMT_TASK_INDX, {0x01, 0x03, 0x01, 0x00, 0x01} }, /* sleep command */ + {0x05, WMT_TASK_INDX, {0x01, 0x03, 0x01, 0x00, 0x02} }, /* host_awake command */ + }; + + UINT32 i; + UINT32 size = ARRAY_SIZE(p_cmd_table)); + + for (i = 0; i < size; i++) { + if (type != p_cmd_table[i].type) + continue; + + if (length != p_cmd_table[i].length) + continue; + + if (osal_memcmp(p_cmd_table[i].buf, buffer, length)) + continue; + /* matched entry is found */ + STP_DBG_FUNC("It's p_cmd_t\n"); + return MTK_WCN_BOOL_TRUE; + } + + return MTK_WCN_BOOL_FALSE; +} +#endif +/***************************************************************************** +* FUNCTION +* tx_queue_room_available +* DESCRIPTION +* check room if available, +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* RETURNS +* void +*****************************************************************************/ +static MTK_WCN_BOOL stp_is_tx_res_available(UINT32 length) +{ + UINT32 roomLeft; + + /* + * Get available space of TX Queue + */ + if (stp_core_ctx.tx_read <= stp_core_ctx.tx_write) + roomLeft = MTKSTP_BUFFER_SIZE - stp_core_ctx.tx_write + stp_core_ctx.tx_read - 1; + else + roomLeft = stp_core_ctx.tx_read - stp_core_ctx.tx_write - 1; + if (roomLeft < length) { + STP_ERR_FUNC("%s: tx queue room shortage\n", __func__); + return MTK_WCN_BOOL_FALSE; + } + 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 PUINT8 buffer, UINT32 length) +{ + UINT32 last_len; + + /* Get available space of TX Queue */ + if (length + stp_core_ctx.tx_write < MTKSTP_BUFFER_SIZE) { + osal_memcpy(stp_core_ctx.tx_buf + stp_core_ctx.tx_write, buffer, length); + stp_core_ctx.tx_write += length; + } else { + last_len = MTKSTP_BUFFER_SIZE - stp_core_ctx.tx_write; + osal_memcpy(stp_core_ctx.tx_buf + stp_core_ctx.tx_write, buffer, last_len); + osal_memcpy(stp_core_ctx.tx_buf, buffer + last_len, length - last_len); + stp_core_ctx.tx_write = length - last_len; + } +} + +/***************************************************************************** +* FUNCTION +* stp_add_to_rx_queue +* DESCRIPTION +* put data to corresponding task's rx queue and notify corresponding task +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* type [IN] corresponding task index +* RETURNS +* INT32 0=success, others=error +*****************************************************************************/ +static INT32 stp_add_to_rx_queue(UINT8 *buffer, UINT32 length, UINT8 type) +{ + UINT32 roomLeft, last_len; + + osal_lock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); + + if (stp_core_ctx.ring[type].read_p <= stp_core_ctx.ring[type].write_p) + roomLeft = MTKSTP_BUFFER_SIZE - stp_core_ctx.ring[type].write_p + stp_core_ctx.ring[type].read_p - 1; + else + roomLeft = stp_core_ctx.ring[type].read_p - stp_core_ctx.ring[type].write_p - 1; + + if (roomLeft < length) { + osal_unlock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); + STP_WARN_RATELIMITED_FUNC( + "Queue full, type(%d), remain buf(%d), len(%d), w_p(%d), r_p(%d)\n", + type, roomLeft, length, + stp_core_ctx.ring[type].write_p, + stp_core_ctx.ring[type].read_p); + osal_assert(0); + return -1; + } + + if (length + stp_core_ctx.ring[type].write_p < MTKSTP_BUFFER_SIZE) { + osal_memcpy(stp_core_ctx.ring[type].buffer + stp_core_ctx.ring[type].write_p, buffer, length); + stp_core_ctx.ring[type].write_p += length; + } else { + last_len = MTKSTP_BUFFER_SIZE - stp_core_ctx.ring[type].write_p; + osal_memcpy(stp_core_ctx.ring[type].buffer + stp_core_ctx.ring[type].write_p, buffer, last_len); + osal_memcpy(stp_core_ctx.ring[type].buffer, buffer + last_len, length - last_len); + stp_core_ctx.ring[type].write_p = length - last_len; + } + + osal_unlock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); + + return 0; +} + +/***************************************************************************** +* FUNCTION +* wmt_parser_data +* DESCRIPTION +* push data to wmt parser engine +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* type [IN] corresponding task index +* RETURNS +* INT32 0=success, others=error +*****************************************************************************/ +static INT32 wmt_parser_data(PUINT8 buffer, UINT32 length, UINT8 type) +{ + UINT8 wmtsubtype; + INT32 fgRxOk = -1; + UINT32 parser_length = 0; + UINT32 packet_length = 0; + + while (parser_length < length) { + wmtsubtype = buffer[parser_length + 1]; + packet_length = buffer[parser_length + 3] << 8; + packet_length += buffer[parser_length + 2]; + STP_DBG_FUNC("wmt sub type (%d)\n", wmtsubtype); + if (wmtsubtype == WMT_LTE_COEX_FLAG) { +#if CFG_WMT_LTE_COEX_HANDLING + fgRxOk = stp_add_to_rx_queue(buffer + parser_length, packet_length + 4, COEX_TASK_INDX); + if (fgRxOk == 0) { + STP_DBG_FUNC("wmt/lte coex package!\n"); + stp_notify_btm_handle_wmt_lte_coex(STP_BTM_CORE(stp_core_ctx)); + } else + osal_buffer_dump(buffer, "coex_packet_print", length, 128); +#else + STP_WARN_FUNC("BT/WIFI & LTE coex in non-LTE projects,drop it...\n"); +#endif + } else { + fgRxOk = stp_add_to_rx_queue(buffer + parser_length, packet_length + 4, type); + if (fgRxOk == 0) { + STP_DBG_FUNC("wmt package!\n"); + (*sys_event_set)(type); + } else + osal_buffer_dump(buffer, "wmt_packet_print", length, 128); + } + parser_length += packet_length + 4; + } + + return fgRxOk; +} + +/***************************************************************************** +* FUNCTION +* stp_send_tx_queue +* DESCRIPTION +* send data in tx buffer to common interface +* PARAMETERS +* txseq [IN] sequence number of outgoing packet in tx buffer +* RETURNS +* void +*****************************************************************************/ +static VOID stp_send_tx_queue(UINT32 txseq) +{ + UINT32 ret; + INT32 tx_read, tx_length, last_len; + + tx_read = stp_core_ctx.tx_start_addr[txseq]; + tx_length = stp_core_ctx.tx_length[txseq]; + + stp_update_tx_queue(txseq); + + if (tx_read + tx_length < MTKSTP_BUFFER_SIZE) { + + (*sys_if_tx) (&stp_core_ctx.tx_buf[tx_read], tx_length, &ret); + + if (ret != tx_length) { + STP_ERR_FUNC("stp_send_tx_queue, %d/%d\n", tx_length, ret); + osal_assert(0); + } + } else { + last_len = MTKSTP_BUFFER_SIZE - tx_read; + (*sys_if_tx) (&stp_core_ctx.tx_buf[tx_read], last_len, &ret); + + if (ret != last_len) { + STP_ERR_FUNC("stp_send_tx_queue, %d/%d\n", last_len, ret); + osal_assert(0); + } + + (*sys_if_tx) (&stp_core_ctx.tx_buf[0], tx_length - last_len, &ret); + + if (ret != tx_length - last_len) { + STP_ERR_FUNC("stp_send_tx_queue, %d/%d\n", tx_length - last_len, ret); + osal_assert(0); + } + } +} + + +/***************************************************************************** +* FUNCTION +* stp_send_ack +* DESCRIPTION +* send ack packet to the peer +* PARAMETERS +* txAck [IN] Ack number +* nak [IN] 0 = ack; !0 = NAK +* RETURNS +* void +*****************************************************************************/ +static VOID stp_send_ack(UINT8 txAck, UINT8 nak) +{ + UINT8 mtkstp_header[MTKSTP_HEADER_SIZE]; + UINT32 ret; + INT32 iStatus; + + mtkstp_header[0] = 0x80 + (0 << 3) + txAck; /* stp_core_ctx.sequence.txack; */ + + if (fgEnableNak == 0) + mtkstp_header[1] = 0x00; /* disable NAK */ + else + mtkstp_header[1] = ((nak == 0) ? 0x00 : 0x80); + + mtkstp_header[2] = 0; + mtkstp_header[3] = (mtkstp_header[0] + mtkstp_header[1] + mtkstp_header[2]) & 0xff; + + stp_dbg_pkt_log(STP_TASK_INDX, txAck, 0, 0, PKT_DIR_TX, NULL, 0); + + if (fgEnableDelimiter == 1) { + iStatus = (*sys_if_tx) ((const PUINT8)(&stp_delimiter[0]), STP_DEL_SIZE, &ret); + STP_DUMP_PACKET_HEAD((PUINT8)(&stp_delimiter[0]), "tx del", STP_DEL_SIZE); + if (ret != STP_DEL_SIZE) { + STP_ERR_FUNC("stp_send_ack, %d/%d status %d\n", STP_DEL_SIZE, ret, iStatus); + osal_assert(0); + } + } + + iStatus = (*sys_if_tx) (&mtkstp_header[0], MTKSTP_HEADER_SIZE, &ret); + + if (ret != MTKSTP_HEADER_SIZE) { + STP_ERR_FUNC("stp_send_ack, %d/%d status %d\n", MTKSTP_HEADER_SIZE, ret, iStatus); + osal_assert(0); + } +} + + + +INT32 stp_send_data_no_ps(PUINT8 buffer, UINT32 length, UINT8 type) +{ + UINT8 mtkstp_header[MTKSTP_HEADER_SIZE], temp[2]; + PUINT8 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); */ + } else if ((mtk_wcn_stp_is_sdio_mode() || mtk_wcn_stp_is_uart_mand_mode() || + mtk_wcn_stp_is_btif_mand_mode()) && STP_IS_ENABLE(stp_core_ctx)) { + /* STP over SDIO */ + /* 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]"); */ + } else if ((mtk_wcn_stp_is_uart_fullset_mode() || mtk_wcn_stp_is_btif_fullset_mode()) + && STP_IS_ENABLE(stp_core_ctx)) { + /* STP over UART OR BTIF*/ + 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((const PUINT8)(&stp_delimiter[0]), + STP_DEL_SIZE); + } + + stp_add_to_tx_queue(mtkstp_header, MTKSTP_HEADER_SIZE); + + /*Make Payload */ + stp_add_to_tx_queue(buffer, length); + + /*Make CRC */ + crc = osal_crc16(buffer, length); + temp[0] = crc & 0xff; + temp[1] = (crc & 0xff00) >> 8; + stp_add_to_tx_queue(temp, 2); + + stp_dbg_pkt_log(type, + stp_core_ctx.sequence.txack, + stp_core_ctx.sequence.txseq, + crc, PKT_DIR_TX, buffer, length); + + /*Kick to UART */ + stp_send_tx_queue(stp_core_ctx.sequence.txseq); + INDEX_INC(stp_core_ctx.sequence.txseq); + stp_core_ctx.sequence.winspace--; + + /*Setup the Retry Timer */ + osal_timer_stop(&stp_core_ctx.tx_timer); + if (stp_core_ctx.sequence.winspace != MTKSTP_WINSIZE) + osal_timer_start(&stp_core_ctx.tx_timer, mtkstp_tx_timeout); + else + STP_ERR_FUNC("mtk_wcn_stp_send_data: wmt_stop_timer\n"); + ret = (INT32) length; + } else { + /* No winspace to send. Let caller retry */ + STP_ERR_FUNC("%s: There is no winspace/txqueue to send !!!\n", + __func__); + ret = 0; + } + } + + stp_ctx_unlock(&stp_core_ctx); + + 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; + stp_core_ctx.sequence.tx_timeout_loop = 0; + + osal_timer_stop(&stp_core_ctx.tx_timer); + if (stp_core_ctx.sequence.winspace != MTKSTP_WINSIZE) + osal_timer_start(&stp_core_ctx.tx_timer, mtkstp_tx_timeout); + fgResult = 0; + } + } + + return fgResult; +} + +/***************************************************************************** +* FUNCTION +* stp_process_packet +* DESCRIPTION +* process STP packet +* PARAMETERS +* void +* RETURNS +* void +*****************************************************************************/ +static VOID stp_process_packet(VOID) +{ + INT32 fgTriggerResume = (-1); + UINT8 txAck = 0; + static INT32 fgRxOk; + MTK_WCN_BOOL b; + MTK_WCN_BOOL is_function_active = 0; + static INT32 stp_process_packet_fail_count; + + 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)) { + stp_core_ctx.sequence.rx_resync = 0; + + /*Indicate packet to hci_stp */ + STP_DBG_FUNC("Send Packet to BT_SUBFUCTION, len = %d\n", stp_core_ctx.rx_counter); + + b = mtk_wcn_sys_if_rx(stp_core_ctx.rx_buf, stp_core_ctx.rx_counter); + if (b) + STP_ERR_FUNC("mtk_wcn_sys_if_rx is NULL\n"); + + /* osal_lock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ + stp_ctx_lock(&stp_core_ctx); + /*Process rx ack */ + fgTriggerResume = stp_process_rxack(); + stp_core_ctx.sequence.txack = stp_core_ctx.parser.seq; + INDEX_INC(stp_core_ctx.sequence.expected_rxseq); + txAck = stp_core_ctx.sequence.txack; + + /*Send ack back */ + stp_send_ack(txAck, 0); + + /* osal_unlock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ + stp_ctx_unlock(&stp_core_ctx); + fgRxOk = 0; + } + /* sequence matches expected, enqueue packet */ + else if (stp_core_ctx.sequence.expected_rxseq == stp_core_ctx.parser.seq) { + stp_core_ctx.sequence.rx_resync = 0; + + 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)) { + + stp_ctx_lock(&stp_core_ctx); + + fgTriggerResume = stp_process_rxack(); + stp_core_ctx.sequence.txack = stp_core_ctx.parser.seq; + INDEX_INC(stp_core_ctx.sequence.expected_rxseq); + + /*Send tx ack */ + txAck = stp_core_ctx.sequence.txack; + stp_send_ack(txAck, 0); + + stp_ctx_unlock(&stp_core_ctx); + + if (stp_core_ctx.parser.type == WMT_TASK_INDX) + fgRxOk = + wmt_parser_data(stp_core_ctx.rx_buf, stp_core_ctx.rx_counter, + stp_core_ctx.parser.type); + else + 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 */ + } + stp_ctx_lock(&stp_core_ctx); + + fgTriggerResume = stp_process_rxack(); + stp_core_ctx.sequence.txack = stp_core_ctx.parser.seq; + INDEX_INC(stp_core_ctx.sequence.expected_rxseq); + + /*Send tx ack */ + txAck = stp_core_ctx.sequence.txack; + stp_send_ack(txAck, 0); + + stp_ctx_unlock(&stp_core_ctx); + } + + /* enqueue successfully */ + if (fgRxOk == 0) { + stp_process_packet_fail_count = 0; + /*notify corresponding subfunction of incoming data */ + if (stp_core_ctx.parser.type != WMT_TASK_INDX) + (*sys_event_set) (stp_core_ctx.parser.type); + } else { + /*Queue is full */ + switch (stp_core_ctx.parser.type) { + case GPS_TASK_INDX: + /*Clear Rx Queue if GPS */ + mtk_wcn_stp_flush_rx_queue(GPS_TASK_INDX); + break; + case BT_TASK_INDX: + /* just ignore this case */ + /*notify corresponding subfunction of incoming data */ + (*sys_event_set) (stp_core_ctx.parser.type); + break; + default: + stp_process_packet_fail_count++; + /*notify corresponding subfunction of incoming data */ + (*sys_event_set) (stp_core_ctx.parser.type); + break; + } + /*enqueue fail, don't send ack and wait for peer retry */ + STP_WARN_RATELIMITED_FUNC("%s %d queue is full\n", + "Enqueue to Rx queue fail, maybe function", + 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, rx_resync = %d\n", + stp_core_ctx.sequence.expected_rxseq, + stp_core_ctx.parser.seq, + stp_core_ctx.sequence.rx_resync); + + stp_ctx_lock(&stp_core_ctx); + /* osal_lock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ + txAck = stp_core_ctx.sequence.txack; + stp_send_ack(txAck, 1); + stp_ctx_unlock(&stp_core_ctx); + /* osal_unlock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ + + if (stp_core_ctx.sequence.rx_resync) { + STP_ERR_FUNC("resync'd packets, discard and send the previous (ack no =%d)\n", txAck); + if (stp_core_ctx.sequence.rx_resync_seq == 0xFF) + stp_core_ctx.sequence.rx_resync_seq = stp_core_ctx.parser.seq; + else { + INDEX_INC(stp_core_ctx.sequence.rx_resync_seq); + if (stp_core_ctx.sequence.rx_resync_seq != stp_core_ctx.parser.seq) { + STP_ERR_FUNC("resync'd packet seq not match, %d expected\n", + stp_core_ctx.sequence.rx_resync_seq); + stp_process_packet_fail_count++; + stp_core_ctx.sequence.rx_resync = 0; + } + } + } else { + stp_process_packet_fail_count++; + STP_ERR_FUNC + ("seq not match && previous packet enqueue success, send the previous (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 + ("seq not match && previous packet enqueue failed, make the other side timeout\n"); + } + + if (fgTriggerResume == 0) { + /*[PatchNeed]Just Notificaiton, not blocking call */ + /* notify adaptation layer for possible tx resume mechanism */ + (*sys_event_tx_resume) (stp_core_ctx.sequence.winspace); + } + + if (stp_process_packet_fail_count > MTKSTP_RETRY_LIMIT) { + stp_process_packet_fail_count = 0; + STP_ERR_FUNC("The process packet fail count > 10 lastly, host trigger assert\n"); + /*Whole Chip Reset Procedure Invoke */ + wmt_lib_trigger_assert(WMTDRV_TYPE_WMT, 43); + } +} + +/***************************************************************************** +* 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 check tx/rx has pending data*/ + sys_rx_has_pending_data = cb_func->cb_rx_has_pending_data; + sys_tx_has_pending_data = cb_func->cb_tx_has_pending_data; + + /* Used to get rx thread */ + sys_rx_thread_get = cb_func->cb_rx_thread_get; + + /* 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); + STP_SET_EMI_DUMP_FLAG(stp_core_ctx, 0); + STP_SET_ASSERT(stp_core_ctx, 0); + STP_SET_ASSERT_IN_PROGRESS(stp_core_ctx, 0); + STP_SET_SUPPORT_GPSL5(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); + + mtk_wcn_stp_dbg_enable(); + + 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) +{ + INT32 i = 0; + + sys_if_tx = NULL; + sys_event_set = NULL; + sys_event_tx_resume = NULL; + sys_check_function_status = NULL; + + stp_dbg_deinit(g_mtkstp_dbg); + stp_btm_deinit(STP_BTM_CORE(stp_core_ctx)); + stp_psm_deinit(STP_PSM_CORE(stp_core_ctx)); + + for (i = 0; i < MTKSTP_MAX_TASK_NUM; i++) + osal_unsleepable_lock_deinit(&stp_core_ctx.ring[i].mtx); + + stp_ctx_lock_deinit(&stp_core_ctx); + return 0; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_btm_get_dmp +* DESCRIPTION +* get stp dump related information +* PARAMETERS +* buffer: dump placement, len: dump size +* RETURNS +* 0: Success Negative Value: Fail +*****************************************************************************/ + +INT32 mtk_wcn_stp_btm_get_dmp(PINT8 buf, PINT32 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 (mtk_wcn_stp_is_ready() && mtk_wcn_stp_is_enable() && (mtk_wcn_stp_is_uart_fullset_mode() + || mtk_wcn_stp_is_sdio_mode() || mtk_wcn_stp_is_btif_fullset_mode())) + return stp_psm_enable(STP_PSM_CORE(stp_core_ctx), idle_time_to_sleep); + + STP_WARN_FUNC("STP Not Ready, Dont do Sleep/Wakeup\n"); + return -1; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_psm_disable +* DESCRIPTION +* disable STP sleep/wakeup support +* PARAMETERS +* void +* RETURNS +* 0: Sccuess Negative value: Fail +*****************************************************************************/ +INT32 mtk_wcn_stp_psm_disable(VOID) +{ + if (mtk_wcn_stp_is_ready() && mtk_wcn_stp_is_enable() && (mtk_wcn_stp_is_uart_fullset_mode() + || mtk_wcn_stp_is_sdio_mode() || mtk_wcn_stp_is_btif_fullset_mode())) + return stp_psm_disable(STP_PSM_CORE(stp_core_ctx)); + + STP_WARN_FUNC("STP Not Ready, Dont do Sleep/Wakeup\n"); + return 0; +} + +INT32 mtk_wcn_stp_psm_reset(VOID) +{ + return stp_psm_reset(STP_PSM_CORE(stp_core_ctx)); +} + +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; +} + +INT32 mtk_wcn_stp_dbg_enable(VOID) +{ + if (STP_NOT_ENABLE_DBG(stp_core_ctx)) { + STP_DBG_FUNC("STP dbg mode is turned on\n"); + STP_SET_ENABLE_DBG(stp_core_ctx, 1); + stp_dbg_enable(g_mtkstp_dbg); + } else + STP_WARN_FUNC("STP dbg mode has been turned on\n"); + + return 0; +} + +INT32 mtk_wcn_stp_dbg_log_ctrl(UINT32 on) +{ + stp_dbg_log_ctrl(on); + return 0; +} + +INT32 mtk_wcn_stp_coredump_flag_ctrl(UINT32 on) +{ + static INT32 pre_coredump_mode; + + STP_ENABLE_FW_COREDUMP(stp_core_ctx, on); + STP_INFO_FUNC("%s coredump function.\n", 0 == on ? "disable" : "enable"); + if (pre_coredump_mode != on) { + if (on == 1 || on == 2) + stp_dbg_nl_init(); + else + stp_dbg_nl_deinit(); + } + pre_coredump_mode = on; + return 0; +} + +INT32 mtk_wcn_stp_coredump_flag_get(VOID) +{ + return STP_ENABLE_FW_COREDUMP_FLAG(stp_core_ctx); +} + +INT32 mtk_wcn_stp_emi_dump_flag_ctrl(UINT32 on) +{ + STP_SET_EMI_DUMP_FLAG(stp_core_ctx, on); + return 0; +} + +INT32 mtk_wcn_stp_emi_dump_flag_get(VOID) +{ + return STP_EMI_DUMP_FLAG(stp_core_ctx); +} + +static INT32 stp_parser_data_in_mand_mode(UINT32 length, UINT8 *p_data) +{ + UINT8 padding_len = 0; + INT32 remain_length = 0; + INT32 i = 0; + INT32 i_ret = 0; + + i = length; + while (i > 0) { + switch (stp_core_ctx.parser.state) { + case MTKSTP_SYNC: /* b'10 */ + /* Must be 0x80 */ + if (*p_data == 0x80) { + stp_change_rx_state(MTKSTP_NAK); + stp_core_ctx.rx_counter++; + } else { + STP_WARN_FUNC("non-0x80 (0x%x) detected, discard %d bytes\n", + *p_data, i); + osal_buffer_dump(p_data, "mandatory mode abnormal data", i, 0); + i = 0; + /* Drop them and keep at MTKSTP_SYNC state */ + continue; + } + break; + + case MTKSTP_NAK: + 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("abnormal type (0x%x) detected, discard %d bytes\n", + stp_core_ctx.parser.type, i); + osal_buffer_dump(p_data, "mandatory mode abnormal data", i, 0); + + /* Drop them and back to MTKSTP_SYNC state */ + i = 0; + STP_WARN_FUNC("nak to sync\n"); + stp_change_rx_state(MTKSTP_SYNC); + continue; + } + break; + + case MTKSTP_LENGTH: + 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("abnormal length (0x%x) detected, discard %d bytes\n", + stp_core_ctx.parser.length, i); + osal_buffer_dump(p_data, "mandatory mode abnormal data", i, 0); + + /* Drop them and back to MTKSTP_SYNC state */ + i = 0; + stp_change_rx_state(MTKSTP_SYNC); + stp_core_ctx.rx_counter = 0; + continue; + } + break; + + case MTKSTP_CHECKSUM: + if ((stp_core_ctx.parser.type == STP_TASK_INDX) || mtk_wcn_stp_is_info_task()) { + 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_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); + stp_core_ctx.parser.crc = *p_data; + break; + + case MTKSTP_CRC2: + stp_core_ctx.parser.crc += (*p_data) << 8; + if (stp_core_ctx.parser.crc != 0x00) + STP_ERR_FUNC + ("CRC (0x%x) is not 0 under SDIO/MAND mode, maybe something is wrong.\n", + stp_core_ctx.parser.crc); + /*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) { + 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_pkt_log(stp_core_ctx.parser.type, + 0, + 0, + 0, + PKT_DIR_RX, + stp_core_ctx.rx_buf, stp_core_ctx.rx_counter); + stp_sdio_process_packet(); + + stp_core_ctx.rx_counter = 0; + stp_change_rx_state(MTKSTP_SYNC); + + break; + + case MTKSTP_FW_MSG: + i_ret = -2; + if (stp_core_ctx.parser.length == 0) { + STP_INFO_FUNC("FW Assert len = 0, ignore this pkg\n"); + /*discard CRC */ + if (i > 2) { + STP_DBG_FUNC("crc discard.. i = %d\n", i); + i -= 2; + p_data += 2; + } else if (i == 2) { + STP_DBG_FUNC("crc discard.. i = %d\n", i); + i -= 2; + } + /*STP packet 4-bytes alignment */ + /*Discard padding bytes , otherwise make parser state machine disorder */ + if (i == 0) { + /*STP_DBG_FUNC("\n[STP]FW_EVENT======= no padding byte =======\n"); */ + /*do nothing */ + } else if (i <= 4) { + STP_INFO_FUNC + ("\n[STP]FW_EVENT========= block padding %d bytes =========\n", i); + p_data += i; + i -= i; + } 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); + } + continue; + } + mtk_wcn_stp_assert_flow_ctrl(1); + mtk_wcn_stp_coredump_start_ctrl(1); + if (mtk_wcn_stp_get_wmt_trg_assert() == 1) + stp_btm_stop_trigger_assert_timer(STP_BTM_CORE(stp_core_ctx)); + if (STP_IS_READY(stp_core_ctx)) { + 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_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); */ + + /*Trace32 Dump */ + stp_sdio_trace32_dump(); + + /*discard CRC */ + if (i > 2) { + STP_DBG_FUNC("crc discard.. i = %d\n", i); + i -= 2; + p_data += 2; + } else if (i == 2) { + STP_DBG_FUNC("crc discard.. i = %d\n", i); + i -= 2; + } + /*STP packet 4-bytes alignment */ + /*Discard padding bytes , otherwise make parser state machine disorder */ + if (i == 0) + STP_DBG_FUNC + ("\n[STP]FW_EVENT========= no padding byte =========\n"); + else if (i <= 4) { + STP_DBG_FUNC + ("\n[STP]FW_EVENT========= block padding %d bytes =========\n", i); + p_data += i; + i -= i; + } else { + padding_len = (0x04 - ((stp_core_ctx.parser.length + 6) & 0x03)) & 0x03; + p_data += padding_len; + i -= padding_len; + STP_DBG_FUNC + ("\n[STP]FW_EVENT========= STP Agg padding %d bytes =========\n", + padding_len); + } + continue; + } else { /* only copy by data length */ + + /*fixed klocwork insight issue */ + if (i + stp_core_ctx.rx_counter >= MTKSTP_BUFFER_SIZE) { + STP_ERR_FUNC + ("Fail to handle Packet, maybe it doesn't follow STP protocol.\n"); + stp_change_rx_state(MTKSTP_RESYNC1); + stp_core_ctx.rx_counter = 0; + return -1; + } + osal_memcpy(stp_core_ctx.rx_buf + stp_core_ctx.rx_counter, p_data, i); + stp_core_ctx.rx_counter += i; /* all remain buffer are data */ + i = 0; + p_data += i; + continue; + } + break; + default: + break; + } + p_data++; + i--; + } + return 0; +} + +static INT32 stp_parser_data_in_full_mode(UINT32 length, UINT8 *p_data) +{ + INT32 remain_length; /* GeorgeKuo: sync from MAUI, change to unsigned */ + INT32 i = length; + static DEFINE_RATELIMIT_STATE(_rs, 2 * HZ, 1); + + 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); + if (stp_core_ctx.sequence.rx_resync < 0xFF) + stp_core_ctx.sequence.rx_resync++; + stp_core_ctx.sequence.rx_resync_seq = 0xFF; + } 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; + } 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 */ + 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); + 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, drop them */ + osal_assert(0); + if (__ratelimit(&_rs)) { + STP_WARN_FUNC("error header(0x%x) detected, discard %d bytes\n", + *p_data, i); + osal_buffer_dump(p_data, "full mode unexpected header", i, 0); + } + i = 0; + continue; + } + break; + + case MTKSTP_NAK: + 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; + if (stp_core_ctx.parser.nak) + STP_ERR_FUNC("MTKSTP_NAK TRUE: 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: + 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_WARN_FUNC("error length(0x%x) detected, discard %d bytes\n", + stp_core_ctx.parser.length, i); + osal_buffer_dump(p_data, "full mode unexpected length", i, 0); + i = 0; + continue; + } + stp_core_ctx.rx_buf[2] = *p_data; + break; + + case MTKSTP_CHECKSUM: + if (((stp_core_ctx.rx_buf[0] + + stp_core_ctx.rx_buf[1] + stp_core_ctx.rx_buf[2]) & 0xff) == *p_data) { + if ((stp_core_ctx.parser.type == STP_TASK_INDX) || mtk_wcn_stp_is_info_task()) { + stp_change_rx_state(MTKSTP_FW_MSG); + stp_core_ctx.rx_counter = 0; + i -= 1; + if (i != 0) + p_data += 1; + continue; + } + /* header only packet */ + stp_process_header_only_packet(); + } 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); + 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_send_ack(1); NAK mechanism is removed */ + osal_buffer_dump(p_data, "full mode unexpected checksum", i, 0); + i = 0; + continue; + } + 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) { + 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; + } + 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("inband reset state,drop the packet\n"); + } else { + STP_ERR_FUNC("[%d]CRC error, drop the packet\n", gCrcErrorCount++); + osal_buffer_dump(&stp_core_ctx.rx_buf[0], "CRC data", stp_core_ctx.rx_counter, 0); + stp_change_rx_state(MTKSTP_SYNC); + 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 (((length > 11) && (osal_strncmp(p_data, "{reset}", 7) == 0)) || + (stp_core_ctx.parser.length == 7)) { + STP_INFO_FUNC("MCU need chip reset only! len=%d,pkt_len=%d!\n", + length, stp_core_ctx.parser.length); + chip_reset_only = 1; + } +#if CFG_WMT_DUMP_INT_STATUS + if (wmt_plat_dump_BGF_irq_status() == MTK_WCN_BOOL_TRUE) + wmt_plat_BGF_irq_dump_status(); +#endif + + if (mtk_wcn_stp_get_wmt_trg_assert() == 1) + stp_btm_stop_trigger_assert_timer(STP_BTM_CORE(stp_core_ctx)); + if (STP_IS_READY(stp_core_ctx)) + mtk_wcn_stp_dbg_dump_package(); + + STP_SET_READY(stp_core_ctx, 0); + /*stp inband reset */ + if (stp_core_ctx.parser.type == STP_TASK_INDX && + stp_core_ctx.parser.seq == 0 && + stp_core_ctx.parser.ack == 0 && + stp_core_ctx.parser.length == 0 && stp_core_ctx.inband_rst_set == 1) { + STP_INFO_FUNC("Inband reset event get! Resync STP with firmware!\n\r"); + stp_rest_ctx_state(); + stp_change_rx_state(MTKSTP_RESYNC1); + stp_core_ctx.inband_rst_set = 0; + STP_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); + } + + mtk_wcn_stp_assert_flow_ctrl(1); + if (mtk_wcn_stp_coredump_start_get() == 0 && stp_core_ctx.rx_counter == 0 && + STP_IS_ENABLE_DBG(stp_core_ctx) && (stp_core_ctx.parser.type == STP_TASK_INDX)) { + mtk_wcn_stp_coredump_start_ctrl(1); + mtk_wcn_stp_ctx_save(); + STP_INFO_FUNC("++ start to read paged dump and paged trace ++\n"); + stp_btm_notify_wmt_dmp_wq(stp_core_ctx.btm); + STP_INFO_FUNC("++ start to read paged dump and paged trace --\n"); + /* Dump CRC error count for debug only */ + STP_INFO_FUNC("gCrcErrorCount = %d\n", gCrcErrorCount); + } + + 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'; + /*Trace32 Dump */ + stp_trace32_dump(); + /*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, it doesn't follow STP protocol.\n"); + stp_change_rx_state(MTKSTP_RESYNC1); + stp_core_ctx.rx_counter = 0; + return -1; + } + osal_memcpy(stp_core_ctx.rx_buf + stp_core_ctx.rx_counter, p_data, i); + stp_core_ctx.rx_counter += i; /* all remain buffer are data */ + i = 0; + p_data += i; + continue; + } + + break; + default: + break; + } + p_data++; + i--; + } + + return 0; +} + + + + + + + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_parser_data +* DESCRIPTION +* push data to serial transport protocol parser engine +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* RETURNS +* INT32 0 = success; -1 = crc/checksum error +*****************************************************************************/ +#if STP_EXP_HID_API_EXPORT +INT32 _mtk_wcn_stp_parser_data(PUINT8 buffer, UINT32 length) +#else +INT32 mtk_wcn_stp_parser_data(PUINT8 buffer, UINT32 length) +#endif +{ + /*----------------------------------------------------------------*/ + /* Local Variables */ + /*----------------------------------------------------------------*/ + INT32 i; + PUINT8 p_data; + INT32 ret = 0; +#ifdef DEBUG_DUMP_PACKET_HEAD + static UINT32 counter; + + STP_TRACE_FUNC("++, rx (cnt=%d,len=%d)\n", ++counter, length); +#endif + + i = length; + p_data = (PUINT8) buffer; + + /* 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)) { + stp_add_to_rx_queue(buffer, i, STP_PENDING_TYPE(stp_core_ctx)); + + /* mike: notify corresponding subfunction of incoming data */ + (*sys_event_set) (STP_PENDING_TYPE(stp_core_ctx)); + } + /* Mandatory or SDIO mode */ + else if ((mtk_wcn_stp_is_sdio_mode() || mtk_wcn_stp_is_uart_mand_mode() || + mtk_wcn_stp_is_btif_mand_mode()) && STP_IS_ENABLE(stp_core_ctx)) { + ret = stp_parser_data_in_mand_mode(i, p_data); + } + /* Full mode */ + else if ((mtk_wcn_stp_is_btif_fullset_mode() || mtk_wcn_stp_is_uart_fullset_mode()) + && STP_IS_ENABLE(stp_core_ctx)) { + ret = stp_parser_data_in_full_mode(i, p_data); + } + STP_TRACE_FUNC("--\n"); + return ret; +} +#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT +EXPORT_SYMBOL(mtk_wcn_stp_parser_data); +#endif + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_enable +* DESCRIPTION +* enable/disable STP +* PARAMETERS +* value [IN] 0=disable, others=enable +* RETURNS +* INT32 0=success, others=error +*****************************************************************************/ +INT32 mtk_wcn_stp_enable(INT32 value) +{ + STP_DBG_FUNC("%s: set the current enable = (%d)\n", __func__, value); + + stp_rest_ctx_state(); + STP_SET_ENABLE(stp_core_ctx, value); + if (!value) + mtk_wcn_stp_psm_reset(); + else { +/* g_block_tx = 0; */ + mtk_wcn_stp_coredump_start_ctrl(0); + mtk_wcn_stp_set_wmt_trg_assert(0); + } + return 0; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_enable +* DESCRIPTION +* get STP enable/disable status +* PARAMETERS +* none. +* RETURNS +* INT32 0 = disable, 1 = enable +*****************************************************************************/ +INT32 mtk_wcn_stp_is_enable(VOID) +{ + return STP_IS_ENABLE(stp_core_ctx); +} + +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"); + wmt_lib_print_wmtd_op_history(); + wmt_lib_print_worker_op_history(); + stp_psm_print_op_history(); + stp_btm_print_op_history(); + + if (mtk_wcn_stp_coredump_start_get() == 0 && + mtk_wcn_stp_get_wmt_trg_assert() == 0) { + if (mtk_wcn_stp_is_sdio_mode()) { + stp_dbg_dmp_print(g_mtkstp_dbg); + STP_INFO_FUNC("STP_SDIO TX data dump start\n"); + stp_sdio_txdbg_dump(); + } else { + mtk_wcn_consys_stp_btif_logger_ctrl(BTIF_DUMP_BTIF_REG); + mtk_wcn_consys_stp_btif_logger_ctrl(BTIF_DUMP_LOG); + stp_dbg_dmp_print(g_mtkstp_dbg); + } + } else + STP_INFO_FUNC("assert start flag is set, disable packet dump function\n"); + } + return 0; +} + + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_ready +* DESCRIPTION +* ready/un-ready STP +* PARAMETERS +* value [IN] 0=un-ready, others=ready +* RETURNS +* INT32 0=success, others=error +*****************************************************************************/ +INT32 mtk_wcn_stp_ready(INT32 value) +{ + STP_DBG_FUNC("set ready (%d)\n", value); + + STP_SET_READY(stp_core_ctx, value); + /*if whole chip reset, reset the debuggine mode */ +#ifndef CONFIG_LOG_STP_INTERNAL + /* mtk_wcn_stp_dbg_disable(); */ +#endif + + if (stp_is_apply_powersaving()) { + STP_INFO_FUNC("Restart the stp-psm monitor !!\n"); + stp_psm_disable(STP_PSM_CORE(stp_core_ctx)); + } + + return 0; +} + + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_coredump_start_ctrl +* DESCRIPTION +* set f/w assert flag in STP context +* PARAMETERS +* value [IN] 0=assert end, others=assert begins +* RETURNS +* INT32 0=success, others=error +*****************************************************************************/ +INT32 mtk_wcn_stp_coredump_start_ctrl(UINT32 value) +{ + if (value != STP_FW_COREDUMP_FLAG(stp_core_ctx)) { + 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 +*****************************************************************************/ +#if STP_EXP_HID_API_EXPORT +INT32 _mtk_wcn_stp_coredump_start_get(VOID) +#else +INT32 mtk_wcn_stp_coredump_start_get(VOID) +#endif +{ + return STP_FW_COREDUMP_FLAG(stp_core_ctx); +} +#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT +EXPORT_SYMBOL(mtk_wcn_stp_coredump_start_get); +#endif + +/* 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); + + /* test whether last_close can be removed safely */ + /* STP_SET_WMT_LAST_CLOSE(stp_core_ctx, value); */ + + return 0; +} + +INT32 mtk_wcn_stp_is_wmt_last_close(VOID) +{ + return STP_WMT_LAST_CLOSE(stp_core_ctx); +} + + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_send_data +* DESCRIPTION +* subfunction send data through STP +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* type [IN] subfunction type +* RETURNS +* INT32 > 0: length transmitted; = 0: error +*****************************************************************************/ +#if STP_EXP_HID_API_EXPORT +INT32 _mtk_wcn_stp_send_data(const PUINT8 buffer, const UINT32 length, const UINT8 type) +#else +INT32 mtk_wcn_stp_send_data(const PUINT8 buffer, const UINT32 length, const UINT8 type) +#endif +{ + UINT8 mtkstp_header[MTKSTP_HEADER_SIZE], temp[2]; + PUINT8 p_tx_buf = NULL; + UINT16 crc; + INT32 ret = 0; + + /* osal_buffer_dump(buffer,"tx", length, 32); */ + osal_ftrace_print("%s|S|T%d|L%d\n", __func__, type, length); + + if (STP_WMT_LAST_CLOSE(stp_core_ctx) != 0) { + STP_ERR_FUNC("WMT lats close,should not have tx request!\n"); + return length; + } + /* if(g_block_tx) */ + if (mtk_wcn_stp_coredump_start_get() != 0) { + STP_WARN_RATELIMITED_FUNC("STP fw coredump start flag set...\n"); + return length; + } +#ifdef CONFIG_POWER_SAVING_SUPPORT + if (type != WMT_TASK_INDX) { +#if PSM_USE_COUNT_PACKAGE + stp_psm_disable_by_tx_rx_density(STP_PSM_CORE(stp_core_ctx), 0); +#else + stp_psm_disable_by_tx_rx_density(STP_PSM_CORE(stp_core_ctx), 0, length); +#endif + } + + if (type == WMT_TASK_INDX) + goto DONT_MONITOR; + if ((type == BT_TASK_INDX) && (wmt_plat_get_comm_if_type() == STP_SDIO_IF_TX)) { + if (stp_psm_is_to_block_traffic(STP_PSM_CORE(stp_core_ctx))) + stp_psm_notify_wmt_wakeup(STP_PSM_CORE(stp_core_ctx)); + 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; + } +DONT_MONITOR: +#endif + + ret = stp_ctx_lock(&stp_core_ctx); + if (ret) { + STP_ERR_FUNC("stp context lock failed, ret=%d\n", ret); + ret = 0; + goto STP_LOCK_FAIL; + } + /*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); */ + } else if ((mtk_wcn_stp_is_sdio_mode() || mtk_wcn_stp_is_uart_mand_mode() || mtk_wcn_stp_is_btif_mand_mode()) + && STP_IS_ENABLE(stp_core_ctx)) { + + /*mtkstp_header[0] = 0x80;*/ + mtkstp_header[0] = 0x80 + (stp_core_ctx.sequence.txseq << 3); /* for debug purpose */ + 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; + } + else if ((mtk_wcn_stp_is_uart_fullset_mode() || mtk_wcn_stp_is_btif_fullset_mode()) + && STP_IS_ENABLE(stp_core_ctx)) { + + 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 */ + 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((const PUINT8)(&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 BUS */ + 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_RATELIMITED_FUNC + ("Now it's inband reset process and drop sent packet.\n"); + else + STP_WARN_RATELIMITED_FUNC("%s: There is no winspace/txqueue to send !!!\n", + __func__); + ret = 0; + } + } + stp_ctx_unlock(&stp_core_ctx); +STP_LOCK_FAIL: +#ifdef CONFIG_POWER_SAVING_SUPPORT + + if (stp_psm_is_quick_ps_support() == MTK_WCN_BOOL_TRUE) { + stp_psm_notify_wmt_sleep(STP_PSM_CORE(stp_core_ctx)); + } + /*-----------------------------STP_PSM_UnLock----------------------------------------*/ + if (type != WMT_TASK_INDX) { + if (!((type == BT_TASK_INDX) && (wmt_plat_get_comm_if_type() == STP_SDIO_IF_TX))) + stp_psm_thread_lock_release(STP_PSM_CORE(stp_core_ctx)); + } +#endif + + osal_ftrace_print("%s|E|T|%d|L|%d\n", __func__, type, length); + return ret; +} +#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT +EXPORT_SYMBOL(mtk_wcn_stp_send_data); +#endif + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_send_data_raw +* DESCRIPTION +* send raw data to common interface, bypass STP +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* type [IN] subfunction type +* RETURNS +* INT32 >= 0: length transmitted; < 0: error +*****************************************************************************/ +#if STP_EXP_HID_API_EXPORT +INT32 _mtk_wcn_stp_send_data_raw(const PUINT8 buffer, const UINT32 length, const UINT8 type) +#else +INT32 mtk_wcn_stp_send_data_raw(const PUINT8 buffer, const UINT32 length, const UINT8 type) +#endif +{ + UINT32 written = 0; + INT32 ret = 0; + + if (STP_WMT_LAST_CLOSE(stp_core_ctx) != 0) { + STP_ERR_FUNC("WMT lats close, should not have tx request!"); + return length; + } + + if (length >= 6) + 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]); + else if (length > 0) + STP_DBG_FUNC("mtk_wcn_stp_send_data_raw, type = %d data = %x", type, buffer[0]); + + /* remember tx type, forward following rx to this type */ + STP_SET_PENDING_TYPE(stp_core_ctx, type); + + stp_ctx_lock(&stp_core_ctx); + stp_dbg_pkt_log(type, 0, 0, 0, PKT_DIR_TX, buffer, length); + (*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; +} +#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT +EXPORT_SYMBOL(mtk_wcn_stp_send_data_raw); +#endif + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_receive_data +* DESCRIPTION +* receive data from serial protocol engine +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* type [IN] subfunction type +* RETURNS +* INT32 >= 0: size of data received; < 0: error +*****************************************************************************/ +#if STP_EXP_HID_API_EXPORT +INT32 _mtk_wcn_stp_receive_data(PUINT8 buffer, UINT32 length, UINT8 type) +#else +INT32 mtk_wcn_stp_receive_data(PUINT8 buffer, UINT32 length, UINT8 type) +#endif +{ + /* GeorgeKuo modify: reduce "if" branch */ + UINT16 copyLen = 0; + UINT16 tailLen = 0; + + osal_ftrace_print("%s|S|T|%d|L|%d\n", __func__, type, length); + osal_lock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); + while (stp_core_ctx.ring[type].read_p != stp_core_ctx.ring[type].write_p) { + /* GeorgeKuo modify: reduce if branch */ + if (stp_core_ctx.ring[type].write_p > stp_core_ctx.ring[type].read_p) { + copyLen = stp_core_ctx.ring[type].write_p - stp_core_ctx.ring[type].read_p; + if (copyLen > length) + copyLen = length; + osal_memcpy(buffer, + stp_core_ctx.ring[type].buffer + stp_core_ctx.ring[type].read_p, + copyLen); + stp_core_ctx.ring[type].read_p += copyLen; + break; + } + tailLen = MTKSTP_BUFFER_SIZE - stp_core_ctx.ring[type].read_p; + if (tailLen > length) { /* exclude equal case to skip wrap check */ + copyLen = length; + osal_memcpy(buffer, stp_core_ctx.ring[type].buffer + + stp_core_ctx.ring[type].read_p, copyLen); + stp_core_ctx.ring[type].read_p += copyLen; + } else { + /* part 1: copy tailLen */ + osal_memcpy(buffer, stp_core_ctx.ring[type].buffer + + stp_core_ctx.ring[type].read_p, tailLen); + buffer += tailLen; /* update buffer offset */ + /* part 2: check if head length is enough */ + copyLen = length - tailLen; + copyLen = (stp_core_ctx.ring[type].write_p < + copyLen) ? stp_core_ctx.ring[type].write_p : copyLen; + if (copyLen) + osal_memcpy(buffer, stp_core_ctx.ring[type].buffer + 0, copyLen); + /* Update read_p final position */ + stp_core_ctx.ring[type].read_p = copyLen; + /* update return length: head + tail */ + copyLen += tailLen; + } + break; + } + + osal_unlock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); + + if ((stp_psm_is_quick_ps_support() == MTK_WCN_BOOL_TRUE) && (type != WMT_TASK_INDX)) { +#if PSM_USE_COUNT_PACKAGE + stp_psm_disable_by_tx_rx_density(STP_PSM_CORE(stp_core_ctx), 1); +#else + stp_psm_disable_by_tx_rx_density(STP_PSM_CORE(stp_core_ctx), 1, copyLen); +#endif + } + + osal_ftrace_print("%s|E|T|%d|L|%d\n", __func__, type, copyLen); + return copyLen; +} +#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT +EXPORT_SYMBOL(mtk_wcn_stp_receive_data); +#endif + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_rxqueue_empty +* DESCRIPTION +* Is certain rx queue empty? +* PARAMETERS +* type [IN] subfunction type +* RETURNS +* INT32 0: queue is NOT empyt; !0: queue is empty +*****************************************************************************/ +#if STP_EXP_HID_API_EXPORT +INT32 _mtk_wcn_stp_is_rxqueue_empty(UINT8 type) +#else +INT32 mtk_wcn_stp_is_rxqueue_empty(UINT8 type) +#endif +{ + INT32 ret; + + osal_lock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); + + if (stp_core_ctx.ring[type].read_p == stp_core_ctx.ring[type].write_p) + ret = 1; /* queue is empty */ + else + ret = 0; /* queue is not empty */ + + osal_unlock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); + + return ret; +} +#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT +EXPORT_SYMBOL(mtk_wcn_stp_is_rxqueue_empty); +#endif + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_set_sdio_mode +* DESCRIPTION +* Set stp for SDIO mode +* PARAMETERS +* sdio_flag [IN] sdio mode flag (TRUE:SDIO mode, FALSE:UART mode) +* RETURNS +* void +*****************************************************************************/ + +void mtk_wcn_stp_set_mode(UINT32 mode) +{ + STP_SET_SUPPORT_PROTOCOL(stp_core_ctx, mode); + STP_DBG_FUNC("STP_SUPPORT_PROTOCOL = %08x\n", STP_SUPPORT_PROTOCOL(stp_core_ctx)); +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_uart_fullset_mode +* DESCRIPTION +* Is stp use UART fullset mode? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:Uart Fullset mode, FALSE:Not UART Fullset mode +*****************************************************************************/ +MTK_WCN_BOOL mtk_wcn_stp_is_uart_fullset_mode(VOID) +{ + /* + * bit 0: uart fullset mode + * bit 1: uart mandatory mode + * bit 2: sdio mode + */ + if (STP_SUPPORT_PROTOCOL(stp_core_ctx) & MTKSTP_UART_FULL_MODE) + return MTK_WCN_BOOL_TRUE; + else + return MTK_WCN_BOOL_FALSE; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_uart_mand_mode +* DESCRIPTION +* Is stp use UART mandatory mode? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:Uart Mandatory mode, FALSE:Not UART Mandotary mode +*****************************************************************************/ +MTK_WCN_BOOL mtk_wcn_stp_is_uart_mand_mode(VOID) +{ + /* + * bit 0: uart fullset mode + * bit 1: uart mandatory mode + * bit 2: sdio mode + */ + if (STP_SUPPORT_PROTOCOL(stp_core_ctx) & MTKSTP_UART_MAND_MODE) + return MTK_WCN_BOOL_TRUE; + else + return MTK_WCN_BOOL_FALSE; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_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 +* mtk_wcn_stp_is_btif_fullset_mode +* DESCRIPTION +* Is stp use BTIF fullset mode? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:BTIF Fullset mode, FALSE:Not BTIF Fullset mode +*****************************************************************************/ +MTK_WCN_BOOL mtk_wcn_stp_is_btif_fullset_mode(VOID) +{ + + if (STP_SUPPORT_PROTOCOL(stp_core_ctx) & MTKSTP_BTIF_FULL_MODE) + return MTK_WCN_BOOL_TRUE; + else + return MTK_WCN_BOOL_FALSE; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_btif_mand_mode +* DESCRIPTION +* Is stp use BTIF mandatory mode? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:BTIF Mandatory mode, FALSE:Not BTIF Mandotary mode +*****************************************************************************/ + +MTK_WCN_BOOL mtk_wcn_stp_is_btif_mand_mode(void) +{ + + if (STP_SUPPORT_PROTOCOL(stp_core_ctx) & MTKSTP_BTIF_MAND_MODE) + return MTK_WCN_BOOL_TRUE; + else + return MTK_WCN_BOOL_FALSE; +} + +/***************************************************************************** +* FUNCTION +* 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 = ARRAY_SIZE(reset_payload); + 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) +{ +} + +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 = ARRAY_SIZE(test_payload); + 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) +{ + INT32 ret = 0; + + if (type < MTKSTP_MAX_TASK_NUM) { + ret = osal_lock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); + if (ret != 0) { + STP_WARN_FUNC("stp context lock failed, ret=%d\n", ret); + return; + } + stp_core_ctx.ring[type].read_p = 0; + stp_core_ctx.ring[type].write_p = 0; + osal_unlock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); + } +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_enable +* DESCRIPTION +* STP is ready? +* PARAMETERS +* none. +* RETURNS +* none +*****************************************************************************/ +#if STP_EXP_HID_API_EXPORT +MTK_WCN_BOOL _mtk_wcn_stp_is_ready(VOID) +#else +MTK_WCN_BOOL mtk_wcn_stp_is_ready(VOID) +#endif +{ + return STP_IS_READY(stp_core_ctx); +} +#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT +EXPORT_SYMBOL(mtk_wcn_stp_is_ready); +#endif + +/***************************************************************************** +* FUNCTION +* set_bluetooth_rx_interface +* DESCRIPTION +* Set bluetooth rx interface +* PARAMETERS +* rx interface type +* RETURNS +* void +*****************************************************************************/ +#if STP_EXP_HID_API_EXPORT +VOID _mtk_wcn_stp_set_bluez(MTK_WCN_BOOL bluez_flag) +#else +VOID mtk_wcn_stp_set_bluez(MTK_WCN_BOOL bluez_flag) +#endif +{ + /* g_mtkstp_bluez_flag = bluez_flag; */ + STP_SET_BT_STK(stp_core_ctx, bluez_flag); +} +#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT +EXPORT_SYMBOL(mtk_wcn_stp_set_bluez); +#endif + +/***************************************************************************** +* FUNCTION +* set stp debugging mdoe +* DESCRIPTION +* set stp debugging mdoe +* PARAMETERS +* dbg_mode: switch to dbg mode ? +* RETURNS +* void +*****************************************************************************/ +VOID mtk_wcn_stp_set_dbg_mode(MTK_WCN_BOOL dbg_mode) +{ + STP_SET_ENABLE_DBG(stp_core_ctx, dbg_mode); +} + +/***************************************************************************** +* FUNCTION +* set stp auto reset mdoe +* DESCRIPTION +* set stp auto reset mdoe +* PARAMETERS +* auto_rst: switch to auto reset mode ? +* RETURNS +* void +*****************************************************************************/ +VOID mtk_wcn_stp_set_auto_rst(MTK_WCN_BOOL auto_rst) +{ + STP_SET_ENABLE_RST(stp_core_ctx, auto_rst); +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_open_btif +* DESCRIPTION +* init btif hw & sw by owner stp +* PARAMETERS +* VOID +* RETURNS +* INT32 0-success,other fail. +*****************************************************************************/ +INT32 mtk_wcn_stp_open_btif(VOID) +{ + return mtk_wcn_consys_stp_btif_open(); +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_open_close +* DESCRIPTION +* close btif hw & sw by owner stp +* PARAMETERS +* VOID +* RETURNS +* INT32 0-success,other fail. +*****************************************************************************/ +INT32 mtk_wcn_stp_close_btif(VOID) +{ + return mtk_wcn_consys_stp_btif_close(); +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_rx_cb_register +* DESCRIPTION +* register stp rx cb to btif +* PARAMETERS +* MTK_WCN_BTIF_RX_CB stp rx handle function +* RETURNS +* INT32 0-success,other fail. +*****************************************************************************/ +INT32 mtk_wcn_stp_rxcb_register(MTK_WCN_BTIF_RX_CB rx_cb) +{ + return mtk_wcn_consys_stp_btif_rx_cb_register(rx_cb); +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_tx +* DESCRIPTION +* send stp package by btif +* PARAMETERS +* pBuf:package buffer pointer,len:package length +* written_len:package written length +* RETURNS +* INT32 package length-success,other fail. +*****************************************************************************/ +INT32 mtk_wcn_stp_tx(UINT8 *pBuf, UINT32 len, UINT32 *written_len) +{ + INT32 iRet = -1; + + iRet = mtk_wcn_consys_stp_btif_tx(pBuf, len, written_len); + return iRet; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_wakeup_consys +* DESCRIPTION +* STP wakeup consys by btif +* PARAMETERS +* VOID +* RETURNS +* INT32 0-success,other fail. +*****************************************************************************/ +INT32 mtk_wcn_stp_wakeup_consys(VOID) +{ + /*log wakeup int for debug */ + stp_dbg_pkt_log(7, 0, 0, 0, PKT_DIR_TX, NULL, 0); + return mtk_wcn_consys_stp_btif_wakeup(); +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_dpidle_ctrl +* DESCRIPTION +* decide AP enter or exit deep idle +* PARAMETERS +* en_flag:1,enter,0,exit +* RETURNS +* always 0 +*****************************************************************************/ +INT32 mtk_wcn_stp_dpidle_ctrl(UINT32 en_flag) +{ + mtk_wcn_consys_stp_btif_dpidle_ctrl(en_flag); + + return 0; +} + +INT32 mtk_wcn_stp_notify_sleep_for_thermal(VOID) +{ + return stp_psm_sleep_for_thermal(STP_PSM_CORE(stp_core_ctx)); +} + +VOID mtk_wcn_stp_set_wmt_trg_assert(UINT32 value) +{ + STP_DBG_FUNC("set evt err tigger assert flag to %d\n", value); + STP_SET_ASSERT(stp_core_ctx, value); +} + +UINT32 mtk_wcn_stp_get_wmt_trg_assert(VOID) +{ + return STP_ASSERT(stp_core_ctx); +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_lpbk_ctrl +* DESCRIPTION +* enable stp internal lpbk test or not +* PARAMETERS +* mode:1,enable,0,disabel +* RETURNS +* INT32 0-success,other fail. +*****************************************************************************/ +INT32 mtk_wcn_stp_lpbk_ctrl(enum _ENUM_BTIF_LPBK_MODE_ mode) +{ + return mtk_wcn_consys_stp_btif_lpbk_ctrl(mode); +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_logger_ctrl +* DESCRIPTION +* dump btif buffer or register status when No ACK or assert occurs +* PARAMETERS +* flag:see enum value in enum _ENUM_BTIF_DBG_ID_ +* RETURNS +* INT32 0-success,other fail. +*****************************************************************************/ +INT32 mtk_wcn_stp_logger_ctrl(enum _ENUM_BTIF_DBG_ID_ flag) +{ + return mtk_wcn_consys_stp_btif_logger_ctrl(flag); +} + +VOID mtk_wcn_stp_ctx_save(void) +{ + STP_DBG_FUNC("start ++\n"); + stp_psm_set_sleep_disable(stp_core_ctx.psm); + STP_DBG_FUNC("exit --\n"); +} + +VOID mtk_wcn_stp_ctx_restore(void) +{ + stp_core_ctx.assert_info_cnt = 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"); +} + +INT32 mtk_wcn_stp_wmt_trg_assert(VOID) +{ + INT32 ret = -1; + + if (mtk_wcn_stp_coredump_start_get() != 0) { + STP_INFO_FUNC("firmware assert has been triggered\n"); + return 1; + } + ret = stp_notify_btm_do_fw_assert(STP_BTM_CORE(stp_core_ctx)); + + if (ret) { + STP_ERR_FUNC("trigger assert fail,do chip reset to recovery\n"); + if (STP_IS_ENABLE_RST(stp_core_ctx)) + stp_btm_notify_wmt_rst_wq(STP_BTM_CORE(stp_core_ctx)); + else + STP_INFO_FUNC("No to launch whole chip reset! for debugging purpose\n"); + } + + return ret; +} + +INT32 mtk_wcn_stp_assert_timeout_handle(VOID) +{ + INT32 ret = 0; + P_CONSYS_EMI_ADDR_INFO p_ecsi; + + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_COMBO) { + mtk_wcn_stp_ctx_restore(); + return ret; + } + + p_ecsi = wmt_plat_get_emi_phy_add(); + /* dump btif data */ + mtk_wcn_consys_stp_btif_logger_ctrl(BTIF_DUMP_BTIF_REG); + mtk_wcn_consys_stp_btif_logger_ctrl(BTIF_DUMP_LOG); + mtk_wcn_stp_coredump_start_ctrl(1); + if (p_ecsi != NULL && wmt_plat_get_dump_info(p_ecsi->p_ecso->emi_apmem_ctrl_assert_flag)) { + STP_INFO_FUNC("EMI assert flag was set. To do coredump.\n"); + mtk_wcn_stp_ctx_save(); + ret = stp_btm_notify_wmt_dmp_wq(STP_BTM_CORE(stp_core_ctx)); + } else { + /*host trigger assert timeout and no coredump packet. To dump EMI data*/ + STP_INFO_FUNC("host trigger fw assert timeout!\n"); + WMT_STEP_COMMAND_TIMEOUT_DO_ACTIONS_FUNC("Trigger assert timeout"); + if (mtk_wcn_stp_coredump_flag_get() != 0) + ret = stp_dbg_start_emi_dump(); + else + mtk_wcn_stp_ctx_restore(); + } + return ret; +} + +INT32 mtk_wcn_stp_coredump_timeout_handle(VOID) +{ + /* dump btif data */ + mtk_wcn_consys_stp_btif_logger_ctrl(BTIF_DUMP_BTIF_REG); + mtk_wcn_consys_stp_btif_logger_ctrl(BTIF_DUMP_LOG); + + WMT_STEP_COMMAND_TIMEOUT_DO_ACTIONS_FUNC("Coredump timeout"); + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_COMBO) + mtk_wcn_stp_ctx_restore(); + return 0; +} + +VOID mtk_wcn_stp_dbg_pkt_log(INT32 type, INT32 dir) +{ + stp_dbg_pkt_log(type, 0, 0, 0, dir, NULL, 0); +} + +VOID mtk_stp_sdio_retry_flag_ctrl(INT32 flag) +{ + if (flag) { + if (flag != wmt_dbg_sdio_retry_ctrl) + flag = wmt_dbg_sdio_retry_ctrl; + } + stp_sdio_retry_flag_ctrl(flag == 0 ? 0 : 1); +} + +VOID mtk_stp_dbg_sdio_retry_flag_ctrl(INT32 flag) +{ + wmt_dbg_sdio_retry_ctrl = flag == 0 ? 0 : 1; +} + +INT32 mtk_stp_sdio_retry_flag_get(VOID) +{ + return stp_sdio_retry_flag_get(); +} + +VOID mtk_stp_dump_sdio_register(VOID) +{ + stp_sdio_dump_register(); +} + +INT32 mtk_stp_dbg_dmp_append(PUINT8 buf, INT32 max_len) +{ + return stp_dbg_dmp_append(g_mtkstp_dbg, buf, max_len); +} + +VOID mtk_stp_notify_emi_dump_end(VOID) +{ + stp_btm_notify_emi_dump_end(STP_BTM_CORE(stp_core_ctx)); +} + +INT32 mtk_stp_check_rx_has_pending_data(VOID) +{ + return sys_rx_has_pending_data(); +} + +P_OSAL_THREAD mtk_stp_rx_thread_get(VOID) +{ + return sys_rx_thread_get(); +} + +VOID mtk_wcn_stp_assert_flow_ctrl(UINT32 on) +{ + STP_DBG_FUNC("Set assert progress flag to %d\n", on); + STP_SET_ASSERT_IN_PROGRESS(stp_core_ctx, on); +} + +UINT32 mtk_wcn_stp_assert_flow_get(VOID) +{ + return STP_ASSERT_IN_PROGRESS(stp_core_ctx); +} + +VOID mtk_wcn_stp_set_support_gpsl5(MTK_WCN_BOOL support_gpsl5) +{ + STP_SET_SUPPORT_GPSL5(stp_core_ctx, support_gpsl5); +} + +INT32 mtk_wcn_stp_is_support_gpsl5(VOID) +{ + return STP_IS_SUPPORT_GPSL5(stp_core_ctx); +} diff --git a/drivers/misc/mediatek/connectivity/common/common_main/core/stp_exp.c b/drivers/misc/mediatek/connectivity/common/common_main/core/stp_exp.c new file mode 100644 index 0000000000000..f695778f328f1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/core/stp_exp.c @@ -0,0 +1,374 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/******************************************************************************* +* 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include /* udelay() */ + +#include +#include +#endif +#include "osal_typedef.h" +#include "stp_core.h" +#include "stp_exp.h" +#include "hif_sdio.h" +#include "stp_sdio.h" +#include "stp_dbg.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static MTK_WCN_STP_IF_TX stp_uart_if_tx; +static MTK_WCN_STP_IF_TX stp_sdio_if_tx; +static MTK_WCN_STP_IF_TX stp_btif_if_tx; +static MTK_WCN_STP_RX_HAS_PENDING_DATA stp_btif_rx_has_pending_data; +static MTK_WCN_STP_TX_HAS_PENDING_DATA stp_btif_tx_has_pending_data; +static MTK_WCN_STP_RX_THREAD_GET stp_btif_rx_thread_get; +static ENUM_STP_TX_IF_TYPE g_stp_if_type = STP_MAX_IF_TX; +static MTK_WCN_STP_IF_RX stp_if_rx; +static MTK_WCN_STP_EVENT_CB event_callback_tbl[MTKSTP_MAX_TASK_NUM] = { 0x0 }; +static MTK_WCN_STP_EVENT_CB tx_event_callback_tbl[MTKSTP_MAX_TASK_NUM] = { 0x0 }; + +/****************************************************************************** +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************* +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +INT32 mtk_wcn_sys_if_rx(PUINT8 data, INT32 size) +{ + if (stp_if_rx == 0x0) + return -1; + (*stp_if_rx)(data, size); + return 0; +} + +static INT32 mtk_wcn_sys_if_tx(const PUINT8 data, const UINT32 size, PUINT32 written_size) +{ + if (g_stp_if_type == STP_UART_IF_TX) + return stp_uart_if_tx != NULL ? (*stp_uart_if_tx)(data, size, written_size) : -1; + else if (g_stp_if_type == STP_SDIO_IF_TX) + return stp_sdio_if_tx != NULL ? (*stp_sdio_if_tx)(data, size, written_size) : -1; + else if (g_stp_if_type == STP_BTIF_IF_TX) + return stp_btif_if_tx != NULL ? (*stp_btif_if_tx) (data, size, written_size) : -1; + /*if (g_stp_if_type >= STP_MAX_IF_TX) *//* George: remove ALWAYS TRUE condition */ + return -1; +} + +static INT32 mtk_wcn_sys_rx_has_pending_data(VOID) +{ + if (g_stp_if_type == STP_BTIF_IF_TX) + return stp_btif_rx_has_pending_data != NULL ? (*stp_btif_rx_has_pending_data) () : -1; + return -1; +} + +static INT32 mtk_wcn_sys_tx_has_pending_data(VOID) +{ + if (g_stp_if_type == STP_BTIF_IF_TX) + return stp_btif_tx_has_pending_data != NULL ? (*stp_btif_tx_has_pending_data) () : -1; + return -1; +} + +static P_OSAL_THREAD mtk_wcn_sys_rx_thread_get(VOID) +{ + if (g_stp_if_type == STP_BTIF_IF_TX) + return stp_btif_rx_thread_get != NULL ? (*stp_btif_rx_thread_get) () : NULL; + return NULL; +} + +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 >= MTKSTP_MAX_TASK_NUM) + return STATUS_FUNCTION_INVALID; + + if (op == OP_FUNCTION_ACTIVE) { + if (event_callback_tbl[type] != 0x0) + return STATUS_FUNCTION_ACTIVE; + return STATUS_FUNCTION_INACTIVE; + } + /*you can define more operation here ..., to queury function's status/information */ + + return STATUS_OP_INVALID; +} + +#if STP_EXP_HID_API_EXPORT +INT32 _mtk_wcn_stp_register_if_rx(MTK_WCN_STP_IF_RX func) +#else +INT32 mtk_wcn_stp_register_if_rx(MTK_WCN_STP_IF_RX func) +#endif +{ + stp_if_rx = func; + + return 0; +} +#if !STP_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_stp_register_if_rx); +#endif + +VOID mtk_wcn_stp_set_if_tx_type(ENUM_STP_TX_IF_TYPE stp_if_type) +{ + g_stp_if_type = stp_if_type; + osal_dbg_print("[%s] set STP_IF_TX to %s.\n", + __func__, + (STP_UART_IF_TX == + stp_if_type) ? "UART" : ((STP_SDIO_IF_TX == + stp_if_type) ? "SDIO" : "NULL")); +} + +#if STP_EXP_HID_API_EXPORT +INT32 _mtk_wcn_stp_register_if_tx(ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_IF_TX func) +#else +INT32 mtk_wcn_stp_register_if_tx(ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_IF_TX func) +#endif +{ + if (stp_if == STP_UART_IF_TX) + stp_uart_if_tx = func; + else if (stp_if == STP_SDIO_IF_TX) + stp_sdio_if_tx = func; + else if (stp_if == STP_BTIF_IF_TX) + stp_btif_if_tx = func; + else { + osal_dbg_print("[%s] STP_IF_TX(%d) out of boundary.\n", __func__, stp_if); + return -1; + } + + return 0; +} +#if !STP_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_stp_register_if_tx); +#endif + +#if STP_EXP_HID_API_EXPORT +INT32 _mtk_wcn_stp_register_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func) +#else +INT32 mtk_wcn_stp_register_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func) +#endif +{ + if ((type < MTKSTP_MAX_TASK_NUM) && (type >= BT_TASK_INDX)) { + event_callback_tbl[type] = func; + + /*clear rx queue */ + mtk_wcn_stp_flush_rx_queue(type); + } + + return 0; +} +#if !STP_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_stp_register_event_cb); +#endif + +#if STP_EXP_HID_API_EXPORT +INT32 _mtk_wcn_stp_register_tx_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func) +#else +INT32 mtk_wcn_stp_register_tx_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func) +#endif +{ + if ((type < MTKSTP_MAX_TASK_NUM) && (type >= BT_TASK_INDX)) + tx_event_callback_tbl[type] = func; + else + osal_bug_on(0); + + return 0; +} +#if !STP_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_stp_register_tx_event_cb); +#endif + +#if STP_EXP_HID_API_EXPORT +INT32 _mtk_wcn_stp_register_rx_has_pending_data(ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_RX_HAS_PENDING_DATA func) +#else +INT32 mtk_wcn_stp_register_rx_has_pending_data(ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_RX_HAS_PENDING_DATA func) +#endif +{ + if (stp_if == STP_BTIF_IF_TX) + stp_btif_rx_has_pending_data = func; + else { + osal_dbg_print("[%s] STP_IF_TX(%d) out of boundary.\n", __func__, stp_if); + return -1; + } + + return 0; +} +#if !STP_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_stp_register_rx_has_pending_data); +#endif + +#if STP_EXP_HID_API_EXPORT +INT32 _mtk_wcn_stp_register_tx_has_pending_data(ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_TX_HAS_PENDING_DATA func) +#else +INT32 mtk_wcn_stp_register_tx_has_pending_data(ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_TX_HAS_PENDING_DATA func) +#endif +{ + if (stp_if == STP_BTIF_IF_TX) + stp_btif_tx_has_pending_data = func; + else { + osal_dbg_print("[%s] STP_IF_TX(%d) out of boundary.\n", __func__, stp_if); + return -1; + } + + return 0; +} +#if !STP_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_stp_register_tx_has_pending_data); +#endif + +#if STP_EXP_HID_API_EXPORT +INT32 _mtk_wcn_stp_register_rx_thread_get(ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_RX_THREAD_GET func) +#else +INT32 mtk_wcn_stp_register_rx_thread_get(ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_RX_THREAD_GET func) +#endif +{ + if (stp_if == STP_BTIF_IF_TX) + stp_btif_rx_thread_get = func; + else { + osal_dbg_print("[%s] STP_IF_TX(%d) out of boundary.\n", __func__, stp_if); + return -1; + } + + return 0; +} +#if !STP_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_stp_register_rx_thread_get); +#endif + +INT32 stp_drv_init(VOID) +{ + INT32 ret = 0; + + mtkstp_callback cb = { + .cb_if_tx = mtk_wcn_sys_if_tx, + .cb_rx_has_pending_data = mtk_wcn_sys_rx_has_pending_data, + .cb_tx_has_pending_data = mtk_wcn_sys_tx_has_pending_data, + .cb_rx_thread_get = mtk_wcn_sys_rx_thread_get, + .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 + }; +#if 0 +#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + MTK_WCN_STP_EXP_CB_INFO stpExpCb = { + .stp_send_data_cb = _mtk_wcn_stp_send_data, + .stp_send_data_raw_cb = _mtk_wcn_stp_send_data_raw, + .stp_parser_data_cb = _mtk_wcn_stp_parser_data, + .stp_receive_data_cb = _mtk_wcn_stp_receive_data, + .stp_is_rxqueue_empty_cb = _mtk_wcn_stp_is_rxqueue_empty, + .stp_is_ready_cb = _mtk_wcn_stp_is_ready, + .stp_set_bluez_cb = _mtk_wcn_stp_set_bluez, + .stp_if_tx_cb = _mtk_wcn_stp_register_if_tx, + .stp_if_rx_cb = _mtk_wcn_stp_register_if_rx, + .stp_reg_event_cb = _mtk_wcn_stp_register_event_cb, + .stp_reg_tx_event_cb = _mtk_wcn_stp_register_tx_event_cb, + .stp_coredump_start_get_cb = _mtk_wcn_stp_coredump_start_get + }; + mtk_wcn_stp_exp_cb_reg(&stpExpCb); + +#endif +#endif + ret = mtk_wcn_stp_init(&cb); + + return ret; +} + +VOID stp_drv_exit(VOID) +{ + mtk_wcn_stp_deinit(); +#if 0 +#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + mtk_wcn_stp_exp_cb_unreg(); +#endif +#endif +} + +INT32 mtk_wcn_stp_sdio_wake_up_ctrl(MTK_WCN_HIF_SDIO_CLTCTX ctx) +{ + stp_sdio_wake_up_ctrl(ctx); + return 0; +} +EXPORT_SYMBOL(mtk_wcn_stp_sdio_wake_up_ctrl); + +INT32 mtk_stp_dbg_poll_cpupcr(UINT32 times, UINT32 sleep, UINT32 cmd) +{ + return stp_dbg_poll_cpupcr(times, sleep, cmd); +} +EXPORT_SYMBOL(mtk_stp_dbg_poll_cpupcr); diff --git a/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_conf.c b/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_conf.c new file mode 100644 index 0000000000000..5d1d387c7a8a7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_conf.c @@ -0,0 +1,695 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifdef 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" +#include "wmt_detect.h" + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +struct parse_data { + PINT8 name; + INT32 (*parser)(P_DEV_WMT pWmtDev, const struct parse_data *data, const PINT8 value); + PINT8 (*writer)(P_DEV_WMT pWmtDev, const struct parse_data *data); + /*PCHAR param1, *param2, *param3; */ + /* TODO:[FixMe][George] CLARIFY WHAT SHOULD BE USED HERE!!! */ + PINT8 param1; + PINT8 param2; + PINT8 param3; +}; + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + + +/****************************************************************************** +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************* +*/ +static INT32 wmt_conf_parse_char(P_DEV_WMT pWmtDev, const struct parse_data *data, const PINT8 pos); + +static PINT8 wmt_conf_write_char(P_DEV_WMT pWmtDev, const struct parse_data *data); + +static INT32 wmt_conf_parse_short(P_DEV_WMT pWmtDev, + const struct parse_data *data, const PINT8 pos); + +static PINT8 wmt_conf_write_short(P_DEV_WMT pWmtDev, const struct parse_data *data); + +static INT32 wmt_conf_parse_int(P_DEV_WMT pWmtDev, const struct parse_data *data, const PINT8 pos); + +static PINT8 wmt_conf_write_int(P_DEV_WMT pWmtDev, const struct parse_data *data); + +static INT32 wmt_conf_parse_byte_array(P_DEV_WMT pWmtDev, const struct parse_data *data, + const PINT8 pos); + +static PINT8 wmt_conf_write_byte_array(P_DEV_WMT pWmtDev, const struct parse_data *data); + +static INT32 wmt_conf_parse_string(P_DEV_WMT pWmtDev, const struct parse_data *data, const PINT8 pos); + +static PINT8 wmt_conf_write_string(P_DEV_WMT pWmtDev, const struct parse_data *data); + +static INT32 wmt_conf_parse_pair(P_DEV_WMT pWmtDev, const PINT8 pKey, const PINT8 pVal); + +static INT32 wmt_conf_parse(P_DEV_WMT pWmtDev, const PINT8 pInBuf, UINT32 size); + +#define OFFSET(v) ((void *) &((P_DEV_WMT) 0)->v) + +#define CHAR(f) {#f, wmt_conf_parse_char, wmt_conf_write_char, OFFSET(rWmtGenConf.f), NULL, NULL} + +#define SHORT(f) {#f, wmt_conf_parse_short, wmt_conf_write_short, OFFSET(rWmtGenConf.f), NULL, NULL} + +#define INT(f) {#f, wmt_conf_parse_int, wmt_conf_write_int, OFFSET(rWmtGenConf.f), NULL, NULL} + +#define BYTE_ARRAY(f) {#f, wmt_conf_parse_byte_array, wmt_conf_write_byte_array, \ + OFFSET(rWmtGenConf.f), NULL, NULL} + +#define STRING(f) {#f, wmt_conf_parse_string, wmt_conf_write_string, OFFSET(rWmtGenConf.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_ant_mode_ex), + CHAR(coex_wmt_ext_component), + CHAR(coex_wmt_wifi_time_ctl), + CHAR(coex_wmt_ext_pta_dev_on), + CHAR(coex_wmt_filter_mode), + + CHAR(coex_bt_rssi_upper_limit), + CHAR(coex_bt_rssi_mid_limit), + CHAR(coex_bt_rssi_lower_limit), + CHAR(coex_bt_pwr_high), + CHAR(coex_bt_pwr_mid), + CHAR(coex_bt_pwr_low), + + CHAR(coex_wifi_rssi_upper_limit), + CHAR(coex_wifi_rssi_mid_limit), + CHAR(coex_wifi_rssi_lower_limit), + CHAR(coex_wifi_pwr_high), + CHAR(coex_wifi_pwr_mid), + CHAR(coex_wifi_pwr_low), + + CHAR(coex_ext_pta_hi_tx_tag), + CHAR(coex_ext_pta_hi_rx_tag), + CHAR(coex_ext_pta_lo_tx_tag), + CHAR(coex_ext_pta_lo_rx_tag), + SHORT(coex_ext_pta_sample_t1), + SHORT(coex_ext_pta_sample_t2), + CHAR(coex_ext_pta_wifi_bt_con_trx), + + INT(coex_misc_ext_pta_on), + INT(coex_misc_ext_feature_set), + + CHAR(wmt_gps_lna_pin), + CHAR(wmt_gps_lna_enable), + + CHAR(pwr_on_rtc_slot), + CHAR(pwr_on_ldo_slot), + CHAR(pwr_on_rst_slot), + CHAR(pwr_on_off_slot), + CHAR(pwr_on_on_slot), + CHAR(co_clock_flag), + + CHAR(disable_deep_sleep_cfg), + + INT(sdio_driving_cfg), + + SHORT(coex_wmt_wifi_path), + + CHAR(coex_wmt_ext_elna_gain_p1_support), + INT(coex_wmt_ext_elna_gain_p1_D0), + INT(coex_wmt_ext_elna_gain_p1_D1), + INT(coex_wmt_ext_elna_gain_p1_D2), + INT(coex_wmt_ext_elna_gain_p1_D3), + STRING(coex_wmt_antsel_invert_support), + CHAR(coex_wmt_ext_epa_mode), + + BYTE_ARRAY(coex_wmt_epa_elna), + + CHAR(bt_tssi_from_wifi), + SHORT(bt_tssi_target), + + CHAR(coex_config_bt_ctrl), + CHAR(coex_config_bt_ctrl_mode), + CHAR(coex_config_bt_ctrl_rw), + + CHAR(coex_config_addjust_opp_time_ratio), + CHAR(coex_config_addjust_opp_time_ratio_bt_slot), + CHAR(coex_config_addjust_opp_time_ratio_wifi_slot), + + CHAR(coex_config_addjust_ble_scan_time_ratio), + CHAR(coex_config_addjust_ble_scan_time_ratio_bt_slot), + CHAR(coex_config_addjust_ble_scan_time_ratio_wifi_slot), + + CHAR(wifi_ant_swap_mode), + CHAR(wifi_main_ant_polarity), + CHAR(wifi_ant_swap_ant_sel_gpio), + + /* This is an open config whose actual purpose is decided by WIFI. */ + BYTE_ARRAY(wifi_config), +}; + +#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 PINT8 pos) +{ + PUINT8 dst; + long res = 0; + + dst = (PINT8)(((PUINT8) pWmtDev) + (long)data->param1); + + if ((osal_strlen(pos) > 2) && ((*pos) == '0') && (*(pos + 1) == 'x')) { + osal_strtol(pos + 2, 16, &res); + *dst = (UINT8)res; + WMT_DBG_FUNC("wmtcfg==> %s=0x%x\n", data->name, *dst); + } else { + osal_strtol(pos, 10, &res); + *dst = (UINT8)res; + WMT_DBG_FUNC("wmtcfg==> %s=%d\n", data->name, *dst); + } + return 0; +} + +static PINT8 wmt_conf_write_char(P_DEV_WMT pWmtDev, const struct parse_data *data) +{ + PINT8 src; + INT32 res; + PINT8 value; + + src = (PINT8) (((PUINT8) pWmtDev) + (long)data->param1); + + value = osal_malloc(20); + if (value == NULL) + return NULL; + res = osal_snprintf(value, 20, "0x%x", *src); + if (res < 0 || res >= 20) { + osal_free(value); + return NULL; + } + value[20 - 1] = '\0'; + return value; +} + +static INT32 wmt_conf_parse_short(P_DEV_WMT pWmtDev, const struct parse_data *data, const PINT8 pos) +{ + PUINT16 dst; + long res = 0; + + 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')) { + osal_strtol(pos + 2, 16, &res); + *dst = (UINT16)res; + WMT_DBG_FUNC("wmtcfg==> %s=0x%x\n", data->name, *dst); + } else { + osal_strtol(pos, 10, &res); + *dst = (UINT16)res; + WMT_DBG_FUNC("wmtcfg==> %s=%d\n", data->name, *dst); + } + + return 0; +} + +static PINT8 wmt_conf_write_short(P_DEV_WMT pWmtDev, const struct parse_data *data) +{ + PINT16 src; + INT32 res; + PINT8 value; + + /* TODO: [FixMe][George] FIX COMPILE WARNING HERE! */ + src = (PINT16) (((PUINT8) pWmtDev) + (long)data->param1); + + value = osal_malloc(20); + if (value == NULL) + return NULL; + res = osal_snprintf(value, 20, "0x%x", *src); + if (res < 0 || res >= 20) { + osal_free(value); + return NULL; + } + value[20 - 1] = '\0'; + return value; +} + +static INT32 wmt_conf_parse_int(P_DEV_WMT pWmtDev, const struct parse_data *data, const PINT8 pos) +{ + PUINT32 dst; + long res = 0; + + 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')) { + osal_strtol(pos + 2, 16, &res); + *dst = (UINT32)res; + WMT_DBG_FUNC("wmtcfg==> %s=0x%x\n", data->name, *dst); + } else { + osal_strtol(pos, 10, &res); + *dst = (UINT32)res; + WMT_DBG_FUNC("wmtcfg==> %s=%d\n", data->name, *dst); + } + + return 0; +} + +static PINT8 wmt_conf_write_int(P_DEV_WMT pWmtDev, const struct parse_data *data) +{ + PINT32 src; + INT32 res; + PINT8 value; + + src = (PUINT32) (((PUINT8) pWmtDev) + (long) data->param1); + + value = osal_malloc(20); + if (value == NULL) + return NULL; + res = osal_snprintf(value, 20, "0x%x", *src); + if (res < 0 || res >= 20) { + osal_free(value); + return NULL; + } + value[20 - 1] = '\0'; + return value; +} + +static INT32 wmt_conf_parse_string(P_DEV_WMT pWmtDev, const struct parse_data *data, const PINT8 pos) +{ + PUINT8 *dst = NULL; + PUINT8 buffer; + + buffer = osal_malloc(osal_strlen(pos)+1); + if (buffer == NULL) { + WMT_ERR_FUNC("wmtcfg==> %s malloc fail, size %d\n", data->name, osal_strlen(pos)+1); + return -1; + } + + osal_strcpy(buffer, pos); + dst = (PUINT8 *)(((PUINT8) pWmtDev) + (long)data->param1); + *dst = (PUINT8)buffer; + WMT_DBG_FUNC("wmtcfg==> %s=%s\n", data->name, *dst); + + return 0; +} + +static PINT8 wmt_conf_write_string(P_DEV_WMT pWmtDev, const struct parse_data *data) +{ + PUINT8 *src; + INT32 res; + PINT8 value; + UINT32 str_size; + + src = (PUINT8 *)(((PUINT8) pWmtDev) + (long)data->param1); + if (*src == NULL) + return NULL; + + str_size = osal_strlen(*src) + 1; + value = osal_malloc(str_size); + if (value == NULL) + return NULL; + + res = osal_snprintf(value, str_size, "%s", *src); + if (res < 0 || res >= str_size) { + osal_free(value); + return NULL; + } + + value[str_size - 1] = '\0'; + return value; +} + +static INT32 wmt_conf_parse_byte_array(P_DEV_WMT pWmtDev, + const struct parse_data *data, const PINT8 pos) +{ + PUINT8 *dst = NULL; + struct WMT_BYTE_ARRAY *ba = NULL; + PUINT8 buffer; + INT32 size = osal_strlen(pos) / 2; + UINT8 temp[3]; + INT32 i; + long value; + + if (size <= 1) { + WMT_ERR_FUNC("wmtcfg==> %s has no value assigned\n", + data->name); + return -1; + } else if (size & 0x1) { + WMT_ERR_FUNC("wmtcfg==> %s, length should be even\n", data->name); + return -1; + } + + ba = (struct WMT_BYTE_ARRAY *)osal_malloc(sizeof(struct WMT_BYTE_ARRAY)); + if (ba == NULL) { + WMT_ERR_FUNC("wmtcfg==> %s malloc fail\n", data->name); + return -1; + } + + buffer = osal_malloc(size); + if (buffer == NULL) { + osal_free(ba); + WMT_ERR_FUNC("wmtcfg==> %s malloc fail, size %d\n", data->name, size); + return -1; + } + + temp[2] = '\0'; + for (i = 0; i < size; i++) { + osal_memcpy(temp, &pos[i * 2], 2); + if (osal_strtol(temp, 16, &value) < 0) { + WMT_ERR_FUNC("wmtcfg==> %s should be hexadecimal format\n", data->name); + osal_free(ba); + osal_free(buffer); + return -1; + } + buffer[i] = (UINT8)value; + } + ba->data = buffer; + ba->size = size; + + dst = (PUINT8 *)(((PUINT8) pWmtDev) + (long)data->param1); + *dst = (PUINT8)ba; + + return 0; +} + +static PINT8 wmt_conf_write_byte_array(P_DEV_WMT pWmtDev, const struct parse_data *data) +{ + PUINT8 *src = NULL; + PINT8 value; + struct WMT_BYTE_ARRAY *ba = NULL; + INT32 i; + + src = (PUINT8 *) (((PUINT8) pWmtDev) + (long)data->param1); + if (*src == NULL) + return NULL; + + ba = (struct WMT_BYTE_ARRAY *)*src; + + value = osal_malloc(ba->size * 2 + 1); + if (value == NULL) + return NULL; + + for (i = 0; i < ba->size; i++) + osal_snprintf(&value[i * 2], 3, "%x", ba->data[i]); + + return value; +} + +static INT32 wmt_conf_parse_pair(P_DEV_WMT pWmtDev, const PINT8 pKey, const PINT8 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 PINT8 pInBuf, UINT32 size) +{ + PINT8 pch; + PINT8 pBuf; + PINT8 pLine; + PINT8 pKey; + PINT8 pVal; + PINT8 pPos; + INT32 ret = 0; + INT32 i = 0; + PINT8 pa = NULL; + + pBuf = osal_malloc(size+1); + if (!pBuf) + return -1; + + osal_memcpy(pBuf, pInBuf, size); + pBuf[size] = '\0'; + + pch = pBuf; + /* pch is to be updated by strsep(). Keep pBuf unchanged!! */ + +#if 0 + { + PINT8 buf_ptr = pBuf; + INT32 k = 0; + + WMT_INFO_FUNC("%s len=%d", "wmcfg.content:", size); + for (k = 0; k < size; k++) { + /* if(k%16 == 0) WMT_INFO_FUNC("\n"); */ + WMT_INFO_FUNC("%c", buf_ptr[k]); + } + WMT_INFO_FUNC("--end\n"); + } +#endif + + while ((pLine = osal_strsep(&pch, "\r\n")) != NULL) { + /* pch is updated to the end of pLine by strsep() and updated to '\0' */ + /*WMT_INFO_FUNC("strsep offset(%d), char(%d, '%c' )\n", pLine-pBuf, *pLine, *pLine); */ + /* parse each line */ + + /* WMT_INFO_FUNC("==> Line = (%s)\n", pLine); */ + + if (!*pLine) + continue; + + pVal = osal_strchr(pLine, '='); + if (!pVal) { + WMT_WARN_FUNC("mal-format cfg string(%s)\n", pLine); + continue; + } + + /* |<-pLine->|'='<-pVal->|'\n' ('\0')| */ + *pVal = '\0'; /* replace '=' with '\0' to get key */ + /* |<-pKey->|'\0'|<-pVal->|'\n' ('\0')| */ + pKey = pLine; + + if ((pVal - pBuf) < size) + pVal++; + + /*key handling */ + pPos = pKey; + /*skip space characeter */ + while (((*pPos) == ' ') || ((*pPos) == '\t') || ((*pPos) == '\n')) { + if ((pPos - pBuf) >= size) + break; + pPos++; + } + /*key head */ + pKey = pPos; + while (((*pPos) != ' ') && ((*pPos) != '\t') && ((*pPos) != '\0') + && ((*pPos) != '\n')) { + if ((pPos - pBuf) >= size) + break; + pPos++; + } + /*key tail */ + (*pPos) = '\0'; + + /*value handling */ + pPos = pVal; + /*skip space characeter */ + while (((*pPos) == ' ') || ((*pPos) == '\t') || ((*pPos) == '\n')) { + if ((pPos - pBuf) >= size) + break; + pPos++; + } + /*value head */ + pVal = pPos; + while (((*pPos) != ' ') && ((*pPos) != '\t') && ((*pPos) != '\0') + && ((*pPos) != '\n')) { + if ((pPos - pBuf) >= size) + break; + pPos++; + } + /*value tail */ + (*pPos) = '\0'; + + /* WMT_DBG_FUNC("parse (key: #%s#, value: #%s#)\n", pKey, pVal); */ + ret = wmt_conf_parse_pair(pWmtDev, pKey, pVal); + WMT_DBG_FUNC("parse (%s, %s, %d)\n", pKey, pVal, ret); + if (ret) + WMT_WARN_FUNC("parse fail (%s, %s, %d)\n", pKey, pVal, ret); + } + + for (i = 0; i < NUM_WMTCFG_FIELDS; i++) { + const struct parse_data *field = &wmtcfg_fields[i]; + + pa = field->writer(pWmtDev, field); + if (pa) { + WMT_DBG_FUNC("#%d(%s)=>%s\n", i, field->name, pa); + osal_free(pa); + } else + WMT_ERR_FUNC("failed to parse '%s'.\n", field->name); + } + osal_free(pBuf); + return 0; +} + + +INT32 wmt_conf_set_cfg_file(const PINT8 name) +{ + if (name == NULL) { + 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 < %zu\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; + ENUM_WMT_CHIP_TYPE chip_type; + + osal_memset(&gDevWmt.rWmtGenConf, 0, osal_sizeof(gDevWmt.rWmtGenConf)); + osal_memset(&gDevWmt.pWmtCfg, 0, osal_sizeof(gDevWmt.pWmtCfg)); + chip_type = wmt_detect_get_chip_type(); + if (chip_type == WMT_CHIP_TYPE_SOC) { + osal_memset(&gDevWmt.cWmtcfgName[0], 0, osal_sizeof(gDevWmt.cWmtcfgName)); + + osal_strncat(&(gDevWmt.cWmtcfgName[0]), CUST_CFG_WMT_SOC, osal_sizeof(CUST_CFG_WMT_SOC)); + } + + if (!osal_strlen(&(gDevWmt.cWmtcfgName[0]))) { + WMT_ERR_FUNC("empty Wmtcfg name\n"); + osal_assert(0); + return ret; + } + WMT_DBG_FUNC("WMT config file:%s\n", &(gDevWmt.cWmtcfgName[0])); + if (0 == + wmt_dev_patch_get(&gDevWmt.cWmtcfgName[0], (osal_firmware **) &gDevWmt.pWmtCfg)) { + /*get full name patch success */ + WMT_DBG_FUNC("get full file name(%s) buf(0x%p) size(%zu)\n", + &gDevWmt.cWmtcfgName[0], gDevWmt.pWmtCfg->data, + gDevWmt.pWmtCfg->size); + if (0 == + wmt_conf_parse(&gDevWmt, (const PINT8)gDevWmt.pWmtCfg->data, + gDevWmt.pWmtCfg->size)) { + /*config file exists */ + gDevWmt.rWmtGenConf.cfgExist = 1; + WMT_DBG_FUNC("&gDevWmt.rWmtGenConf=%p\n", &gDevWmt.rWmtGenConf); + ret = 0; + } else { + WMT_ERR_FUNC("wmt conf parsing fail\n"); + osal_assert(0); + ret = -1; + } + wmt_dev_patch_put((osal_firmware **) &gDevWmt.pWmtCfg); +/* +* if (gDevWmt.pWmtCfg) +* { +* if (gDevWmt.pWmtCfg->data) +* { +* osal_free(gDevWmt.pWmtCfg->data); +* } +* osal_free(gDevWmt.pWmtCfg); +* gDevWmt.pWmtCfg = 0; +* } +*/ + return ret; + } + WMT_ERR_FUNC("read %s file fails\n", &(gDevWmt.cWmtcfgName[0])); + osal_assert(0); + gDevWmt.rWmtGenConf.cfgExist = 0; + return ret; +} + +P_WMT_GEN_CONF wmt_conf_get_cfg(VOID) +{ + if (gDevWmt.rWmtGenConf.cfgExist == 0) + return NULL; + + return &gDevWmt.rWmtGenConf; +} + +INT32 wmt_conf_deinit(VOID) +{ + P_WMT_GEN_CONF pWmtGenConf = wmt_conf_get_cfg(); + + if (pWmtGenConf == NULL) + return -1; + + if (pWmtGenConf->coex_wmt_epa_elna != NULL) { + if (pWmtGenConf->coex_wmt_epa_elna->data != NULL) { + osal_free(pWmtGenConf->coex_wmt_epa_elna->data); + pWmtGenConf->coex_wmt_epa_elna->data = NULL; + } + osal_free(pWmtGenConf->coex_wmt_epa_elna); + pWmtGenConf->coex_wmt_epa_elna = NULL; + } + + if (pWmtGenConf->coex_wmt_antsel_invert_support != NULL) { + osal_free(pWmtGenConf->coex_wmt_antsel_invert_support); + pWmtGenConf->coex_wmt_antsel_invert_support = NULL; + } + + if (pWmtGenConf->wifi_config != NULL) { + if (pWmtGenConf->wifi_config->data != NULL) { + osal_free(pWmtGenConf->wifi_config->data); + pWmtGenConf->wifi_config->data = NULL; + } + osal_free(pWmtGenConf->wifi_config); + pWmtGenConf->wifi_config = NULL; + } + + return 0; +} + diff --git a/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_core.c b/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_core.c new file mode 100644 index 0000000000000..acd14326bd6ee --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_core.c @@ -0,0 +1,3797 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/******************************************************************************* +* 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 +#include "osal_typedef.h" +#include "connsys_debug_utility.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" +#include "wmt_exp.h" +#include "wmt_detect.h" +#include "wmt_plat.h" +#include "wmt_dev.h" + +P_WMT_FUNC_OPS gpWmtFuncOps[WMTDRV_TYPE_MAX] = { +#if CFG_FUNC_BT_SUPPORT + [WMTDRV_TYPE_BT] = &wmt_func_bt_ops, +#else + [WMTDRV_TYPE_BT] = NULL, +#endif + +#if CFG_FUNC_FM_SUPPORT + [WMTDRV_TYPE_FM] = &wmt_func_fm_ops, +#else + [WMTDRV_TYPE_FM] = NULL, +#endif + +#if CFG_FUNC_GPS_SUPPORT + [WMTDRV_TYPE_GPS] = &wmt_func_gps_ops, +#else + [WMTDRV_TYPE_GPS] = NULL, +#endif + +#if CFG_FUNC_GPSL5_SUPPORT + [WMTDRV_TYPE_GPSL5] = &wmt_func_gpsl5_ops, +#else + [WMTDRV_TYPE_GPSL5] = NULL, +#endif + +#if CFG_FUNC_WIFI_SUPPORT + [WMTDRV_TYPE_WIFI] = &wmt_func_wifi_ops, +#else + [WMTDRV_TYPE_WIFI] = NULL, +#endif + +#if CFG_FUNC_ANT_SUPPORT + [WMTDRV_TYPE_ANT] = &wmt_func_ant_ops, +#else + [WMTDRV_TYPE_ANT] = 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. */ +#define CFG_CHECK_WMT_RESULT (1) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +static WMT_CTX gMtkWmtCtx; +static UINT8 gLpbkBuf[WMT_LPBK_BUF_LEN] = { 0 }; +#ifdef CONFIG_MTK_COMBO_ANT +static UINT8 gAntBuf[1024] = { 0 }; +#endif +#if CFG_WMT_LTE_COEX_HANDLING +static UINT32 g_open_wmt_lte_flag; +#endif +static UINT8 gFlashBuf[1024] = { 0 }; +#if CFG_WMT_LTE_COEX_HANDLING +static UINT8 msg_local_buffer[WMT_IDC_MSG_BUFFER] = { 0 }; +#endif +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static INT32 opfunc_hif_conf(P_WMT_OP pWmtOp); +static INT32 opfunc_pwr_on(P_WMT_OP pWmtOp); +static INT32 opfunc_pwr_off(P_WMT_OP pWmtOp); +static INT32 opfunc_func_on(P_WMT_OP pWmtOp); +static INT32 opfunc_func_off(P_WMT_OP pWmtOp); +static INT32 opfunc_reg_rw(P_WMT_OP pWmtOp); +static INT32 opfunc_exit(P_WMT_OP pWmtOp); +static INT32 opfunc_pwr_sv(P_WMT_OP pWmtOp); +static INT32 opfunc_dsns(P_WMT_OP pWmtOp); +static INT32 opfunc_lpbk(P_WMT_OP pWmtOp); +static INT32 opfunc_cmd_test(P_WMT_OP pWmtOp); +static INT32 opfunc_hw_rst(P_WMT_OP pWmtOp); +static INT32 opfunc_sw_rst(P_WMT_OP pWmtOp); +static INT32 opfunc_stp_rst(P_WMT_OP pWmtOp); +static INT32 opfunc_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 INT32 opfunc_bgw_ds(P_WMT_OP pWmtOp); +static INT32 opfunc_set_mcu_clk(P_WMT_OP pWmtOp); +static INT32 opfunc_adie_lpbk_test(P_WMT_OP pWmtOp); +static INT32 wmt_core_gen2_set_mcu_clk(UINT32 kind); +static INT32 wmt_core_gen3_set_mcu_clk(UINT32 kind); +static INT32 wmt_core_set_mcu_clk(UINT32 kind); +static VOID wmt_core_dump_func_state(PINT8 pSource); +static INT32 wmt_core_stp_init(VOID); +static INT32 wmt_core_trigger_assert(VOID); +static INT32 wmt_core_stp_deinit(VOID); +static INT32 wmt_core_hw_check(VOID); +#ifdef CONFIG_MTK_COMBO_ANT +static INT32 opfunc_ant_ram_down(P_WMT_OP pWmtOp); +static INT32 opfunc_ant_ram_stat_get(P_WMT_OP pWmtOp); +#endif +#if CFG_WMT_LTE_COEX_HANDLING +static INT32 opfunc_idc_msg_handling(P_WMT_OP pWmtOp); +#endif +static INT32 opfunc_trigger_stp_assert(P_WMT_OP pWmtOp); +static INT32 opfunc_flash_patch_down(P_WMT_OP pWmtOp); +static INT32 opfunc_flash_patch_ver_get(P_WMT_OP pWmtOp); +static INT32 opfunc_utc_time_sync(P_WMT_OP pWmtOp); +static INT32 opfunc_fw_log_ctrl(P_WMT_OP pWmtOp); +static INT32 opfunc_wlan_probe(P_WMT_OP pWmtOp); +static INT32 opfunc_wlan_remove(P_WMT_OP pWmtOp); +static INT32 opfunc_try_pwr_off(P_WMT_OP pWmtOp); +static INT32 opfunc_gps_mcu_ctrl(P_WMT_OP pWmtOp); +static INT32 opfunc_blank_status_ctrl(P_WMT_OP pWmtOp); +static INT32 opfunc_met_ctrl(P_WMT_OP pWmtOp); +static INT32 opfunc_gps_suspend(P_WMT_OP pWmtOp); +static INT32 opfunc_get_consys_state(P_WMT_OP pWmtOp); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +static const UINT8 WMT_SLEEP_CMD[] = { 0x01, 0x03, 0x01, 0x00, 0x01 }; +static const UINT8 WMT_SLEEP_EVT[] = { 0x02, 0x03, 0x02, 0x00, 0x00, 0x01 }; + +static const UINT8 WMT_HOST_AWAKE_CMD[] = { 0x01, 0x03, 0x01, 0x00, 0x02 }; +static const UINT8 WMT_HOST_AWAKE_EVT[] = { 0x02, 0x03, 0x02, 0x00, 0x00, 0x02 }; + +static const UINT8 WMT_WAKEUP_CMD[] = { 0xFF }; +static const UINT8 WMT_WAKEUP_EVT[] = { 0x02, 0x03, 0x02, 0x00, 0x00, 0x03 }; + +static UINT8 WMT_THERM_CMD[] = { 0x01, 0x11, 0x01, 0x00, + 0x00 /*thermal sensor operation */ +}; +static UINT8 WMT_THERM_CTRL_EVT[] = { 0x02, 0x11, 0x01, 0x00, 0x00 }; +static UINT8 WMT_THERM_READ_EVT[] = { 0x02, 0x11, 0x02, 0x00, 0x00, 0x00 }; + +static UINT8 WMT_EFUSE_CMD[] = { 0x01, 0x0D, 0x08, 0x00, + 0x01, /*[4]operation, 0:init, 1:write 2:read */ + 0x01, /*[5]Number of register setting */ + 0xAA, 0xAA, /*[6-7]Address */ + 0xBB, 0xBB, 0xBB, 0xBB /*[8-11] Value */ +}; + +static UINT8 WMT_EFUSE_EVT[] = { 0x02, 0x0D, 0x08, 0x00, + 0xAA, /*[4]operation, 0:init, 1:write 2:read */ + 0xBB, /*[5]Number of register setting */ + 0xCC, 0xCC, /*[6-7]Address */ + 0xDD, 0xDD, 0xDD, 0xDD /*[8-11] Value */ +}; + +static UINT8 WMT_DSNS_CMD[] = { 0x01, 0x0E, 0x02, 0x00, 0x01, + 0x00 /*desnse type */ +}; +static UINT8 WMT_DSNS_EVT[] = { 0x02, 0x0E, 0x01, 0x00, 0x00 }; + +/* TODO:[NewFeature][GeorgeKuo] Update register group in ONE CMD/EVT */ +static UINT8 WMT_SET_REG_CMD[] = { 0x01, 0x08, 0x10, 0x00 /*length */ + , 0x00 /*op: w(1) & r(2) */ + , 0x01 /*type: reg */ + , 0x00 /*res */ + , 0x01 /*1 register */ + , 0x00, 0x00, 0x00, 0x00 /* addr */ + , 0x00, 0x00, 0x00, 0x00 /* value */ + , 0xFF, 0xFF, 0xFF, 0xFF /*mask */ +}; + +static UINT8 WMT_SET_REG_WR_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 register */ + /* , 0x00, 0x00, 0x00, 0x00 *//* addr */ + /* , 0x00, 0x00, 0x00, 0x00 *//* value */ +}; + +static UINT8 WMT_SET_REG_RD_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 register */ + , 0x00, 0x00, 0x00, 0x00 /* addr */ + , 0x00, 0x00, 0x00, 0x00 /* value */ +}; + +#ifdef CONFIG_MTK_COMBO_ANT +static UINT8 WMT_ANT_RAM_STA_GET_CMD[] = { 0x01, 0x06, 0x02, 0x00, 0x05, 0x02 +}; +static UINT8 WMT_ANT_RAM_STA_GET_EVT[] = { 0x02, 0x06, 0x03, 0x00 /*length */ + , 0x05, 0x02, 0x00 /*S: result */ +}; +static UINT8 WMT_ANT_RAM_DWN_CMD[] = { 0x01, 0x15, 0x00, 0x00, 0x01 +}; +static UINT8 WMT_ANT_RAM_DWN_EVT[] = { 0x02, 0x15, 0x01, 0x00 /*length */ + , 0x00 +}; +#endif + +static UINT8 WMT_FLASH_PATCH_VER_GET_CMD[] = { 0x01, 0x01, 0x05, 0x00 /*length*/ + , 0x06, 0x00, 0x00, 0x00, 0x00 /*flash patch type*/ +}; + +static UINT8 WMT_FLASH_PATCH_VER_GET_EVT[] = { 0x02, 0x01, 0x09, 0x00 /*length */ + , 0x06, 0x00, 0x00, 0x00, 0x00 /*flash patch type*/ + , 0x00, 0x00, 0x00, 0x00 /*flash patch version*/ +}; + +static UINT8 WMT_FLASH_PATCH_DWN_CMD[] = { 0x01, 0x01, 0x0d, 0x00, 0x05 +}; + +static UINT8 WMT_FLASH_PATCH_DWN_EVT[] = { 0x02, 0x01, 0x01, 0x00 /*length */ + , 0x00 +}; + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH +static UINT8 WMT_UTC_SYNC_CMD[] = { 0x01, 0xF0, 0x09, 0x00, 0x02 + , 0x00, 0x00, 0x00, 0x00 /*UTC time second unit*/ + , 0x00, 0x00, 0x00, 0x00 /*UTC time microsecond unit*/ +}; +static UINT8 WMT_UTC_SYNC_EVT[] = { 0x02, 0xF0, 0x02, 0x00, 0x02, 0x00 +}; + +static UINT8 WMT_BLANK_STATUS_CMD[] = { 0x01, 0xF0, 0x02, 0x00, 0x03, 0x00 }; +static UINT8 WMT_BLANK_STATUS_EVT[] = { 0x02, 0xF0, 0x02, 0x00, 0x03, 0x00 }; +#endif + +static UINT8 WMT_FW_LOG_CTRL_CMD[] = { 0x01, 0xF0, 0x04, 0x00, 0x01 + , 0x00 /* subsys type */ + , 0x00 /* on/off */ + , 0x00 /* level (subsys-specific) */ +}; +static UINT8 WMT_FW_LOG_CTRL_EVT[] = { 0x02, 0xF0, 0x02, 0x00, 0x01, 0x00 }; + +/* GeorgeKuo: Use designated initializers described in + * http://gcc.gnu.org/onlinedocs/gcc-4.0.4/gcc/Designated-Inits.html + */ + +static const WMT_OPID_FUNC wmt_core_opfunc[] = { + [WMT_OPID_HIF_CONF] = opfunc_hif_conf, + [WMT_OPID_PWR_ON] = opfunc_pwr_on, + [WMT_OPID_PWR_OFF] = opfunc_pwr_off, + [WMT_OPID_FUNC_ON] = opfunc_func_on, + [WMT_OPID_FUNC_OFF] = opfunc_func_off, + [WMT_OPID_REG_RW] = opfunc_reg_rw, /* TODO:[ChangeFeature][George] is this OP obsoleted? */ + [WMT_OPID_EXIT] = opfunc_exit, + [WMT_OPID_PWR_SV] = opfunc_pwr_sv, + [WMT_OPID_DSNS] = opfunc_dsns, + [WMT_OPID_LPBK] = opfunc_lpbk, + [WMT_OPID_CMD_TEST] = opfunc_cmd_test, + [WMT_OPID_HW_RST] = opfunc_hw_rst, + [WMT_OPID_SW_RST] = opfunc_sw_rst, + [WMT_OPID_STP_RST] = opfunc_stp_rst, + [WMT_OPID_THERM_CTRL] = opfunc_therm_ctrl, + [WMT_OPID_EFUSE_RW] = opfunc_efuse_rw, + [WMT_OPID_GPIO_CTRL] = opfunc_gpio_ctrl, + [WMT_OPID_SDIO_CTRL] = opfunc_sdio_ctrl, + [WMT_OPID_GPIO_STATE] = opfunc_pin_state, + [WMT_OPID_BGW_DS] = opfunc_bgw_ds, + [WMT_OPID_SET_MCU_CLK] = opfunc_set_mcu_clk, + [WMT_OPID_ADIE_LPBK_TEST] = opfunc_adie_lpbk_test, +#ifdef CONFIG_MTK_COMBO_ANT + [WMT_OPID_ANT_RAM_DOWN] = opfunc_ant_ram_down, + [WMT_OPID_ANT_RAM_STA_GET] = opfunc_ant_ram_stat_get, +#endif +#if CFG_WMT_LTE_COEX_HANDLING + [WMT_OPID_IDC_MSG_HANDLING] = opfunc_idc_msg_handling, +#endif + [WMT_OPID_TRIGGER_STP_ASSERT] = opfunc_trigger_stp_assert, + [WMT_OPID_FLASH_PATCH_DOWN] = opfunc_flash_patch_down, + [WMT_OPID_FLASH_PATCH_VER_GET] = opfunc_flash_patch_ver_get, + [WMT_OPID_UTC_TIME_SYNC] = opfunc_utc_time_sync, + [WMT_OPID_FW_LOG_CTRL] = opfunc_fw_log_ctrl, + [WMT_OPID_WLAN_PROBE] = opfunc_wlan_probe, + [WMT_OPID_WLAN_REMOVE] = opfunc_wlan_remove, + [WMT_OPID_GPS_MCU_CTRL] = opfunc_gps_mcu_ctrl, + [WMT_OPID_TRY_PWR_OFF] = opfunc_try_pwr_off, + [WMT_OPID_BLANK_STATUS_CTRL] = opfunc_blank_status_ctrl, + [WMT_OPID_MET_CTRL] = opfunc_met_ctrl, + [WMT_OPID_GPS_SUSPEND] = opfunc_gps_suspend, + [WMT_OPID_GET_CONSYS_STATE] = opfunc_get_consys_state, +}; + +atomic_t g_wifi_on_off_ready; + +/******************************************************************************* +* 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; + } + + atomic_set(&g_wifi_on_off_ready, 0); + + return 0; +} + +INT32 wmt_core_deinit(VOID) +{ + /* return to init state */ + osal_memset(&gMtkWmtCtx, 0, osal_sizeof(gMtkWmtCtx)); + /* gMtkWmtCtx.p_ops is cleared to NULL */ + return 0; +} + +/* TODO: [ChangeFeature][George] Is wmt_ctrl a good interface? maybe not...... */ +/* parameters shall be copied in/from ctrl buffer, which is also a size-wasting buffer. */ +INT32 +wmt_core_tx(const PUINT8 pData, const UINT32 size, PUINT32 writtenSize, const MTK_WCN_BOOL bRawFlag) +{ + INT32 iRet = 0; + INT32 retry_times = 0; + INT32 max_retry_times = 0; + INT32 retry_delay_ms = 0; + ENUM_WMT_CHIP_TYPE chip_type; + + chip_type = wmt_detect_get_chip_type(); + iRet = wmt_ctrl_tx_ex(pData, size, writtenSize, bRawFlag); + if (*writtenSize == 0 && (chip_type == WMT_CHIP_TYPE_SOC)) { + retry_times = 0; + max_retry_times = 3; + retry_delay_ms = 360; + WMT_WARN_FUNC("WMT-CORE: wmt_ctrl_tx_ex failed and written ret:%d, maybe no winspace in STP layer\n", + *writtenSize); + while ((*writtenSize == 0) && (retry_times < max_retry_times)) { + WMT_ERR_FUNC("WMT-CORE: retrying, wait for %d ms\n", retry_delay_ms); + osal_sleep_ms(retry_delay_ms); + + iRet = wmt_ctrl_tx_ex(pData, size, writtenSize, bRawFlag); + retry_times++; + } + } + return iRet; +} + +INT32 wmt_core_rx(PUINT8 pBuf, UINT32 bufLen, PUINT32 readSize) +{ + INT32 iRet; + WMT_CTRL_DATA ctrlData; + + ctrlData.ctrlId = WMT_CTRL_RX; + ctrlData.au4CtrlData[0] = (SIZE_T) pBuf; + ctrlData.au4CtrlData[1] = bufLen; + ctrlData.au4CtrlData[2] = (SIZE_T) readSize; + + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + /* ERROR */ + WMT_ERR_FUNC("WMT-CORE: wmt_core_ctrl failed: WMT_CTRL_RX, iRet:%d\n", iRet); + 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) WMT_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 firwmare no rx event, trigger f/w assert. sub-driver type:%d, state(%d)\n", + type, fgEn); + wmt_lib_trigger_assert(WMTDRV_TYPE_WMT, 32); + break; + } + + /* Error Checking */ + if (rWmtPktEvent.eType != WMT_PKT_TYPE_EVENT) { + WMT_ERR_FUNC + ("WMT-CORE: wmt_func_ctrl_cmd WMT_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 (rWmtPktEvent.aucParam[0] != 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 (fgFail == MTK_WCN_BOOL_FALSE) { + /* WMT_INFO_FUNC("WMT-CORE: wmt_func_ctrl_cmd OK!\n"); */ + return 0; + } + WMT_ERR_FUNC("WMT-CORE: wmt_func_ctrl_cmd 0x%x FAIL\n", rWmtPktCmd.aucParam[0]); + return -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; + } + WMT_ERR_FUNC("WMT-CORE: null handler (%d)\n", pWmtOp->opId); + return -2; +} + +INT32 wmt_core_opid(P_WMT_OP pWmtOp) +{ + + /*sanity check */ + if (pWmtOp == NULL) { + WMT_ERR_FUNC("null pWmtOP\n"); + /*print some message with error info */ + return -1; + } + + if (pWmtOp->opId >= WMT_OPID_MAX) { + 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, PULONG pPa1, PULONG pPa2) +{ + INT32 iRet = -1; + WMT_CTRL_DATA ctrlData; + SIZE_T val1 = (pPa1) ? *pPa1 : 0; + SIZE_T val2 = (pPa2) ? *pPa2 : 0; + + ctrlData.ctrlId = (SIZE_T) ctrId; + ctrlData.au4CtrlData[0] = val1; + ctrlData.au4CtrlData[1] = val2; + + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + /* ERROR */ + WMT_ERR_FUNC + ("WMT-CORE: wmt_core_ctrl failed: id(%d), type(%zu), value(%zu) 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, %zu)\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); + if (isWrite) + WMT_INFO_FUNC("buf:[%2X,%2X,%2X,%2X,%2X] evt:[%2X,%2X,%2X,%2X,%2X]\n", + evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], + WMT_SET_REG_WR_EVT[0], WMT_SET_REG_WR_EVT[1], + WMT_SET_REG_WR_EVT[2], WMT_SET_REG_WR_EVT[3], + WMT_SET_REG_WR_EVT[4]); + else + WMT_INFO_FUNC("buf:[%2X,%2X,%2X,%2X,%2X] evt:[%2X,%2X,%2X,%2X,%2X]\n", + evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], + WMT_SET_REG_RD_EVT[0], WMT_SET_REG_RD_EVT[1], + WMT_SET_REG_RD_EVT[2], WMT_SET_REG_RD_EVT[3], + WMT_SET_REG_RD_EVT[4]); + mtk_wcn_stp_dbg_dump_package(); + wmt_core_trigger_assert(); + return -3; + } + + if (!isWrite) { + UINT32 rxEvtAddr; + UINT32 txCmdAddr; + + osal_memcpy(&txCmdAddr, &WMT_SET_REG_CMD[8], 4); + osal_memcpy(&rxEvtAddr, &evtBuf[8], 4); + + /* check read result */ + if (txCmdAddr != rxEvtAddr) { + WMT_ERR_FUNC("Check read addr fail (0x%08x, 0x%08x)\n", rxEvtAddr, + txCmdAddr); + return -4; + } + WMT_DBG_FUNC("Check read addr(0x%08x) ok\n", rxEvtAddr); + osal_memcpy(pVal, &evtBuf[12], 4); + } + + /* no error here just return 0 */ + return 0; +} + +INT32 wmt_core_init_script_retry(struct init_script *script, INT32 count, INT32 retry, INT32 dump_err_log) +{ + UINT8 evtBuf[256]; + UINT32 u4Res; + INT32 i = 0; + INT32 iRet; + INT32 err = 0; + + do { + err = 0; + 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); + + err = -1; + 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); + if (dump_err_log == 1) + mtk_wcn_stp_dbg_dump_package(); + + err = -1; + break; + } + /* RESULT */ + if (evtBuf[1] != 0x14) { /*workaround RF calibration data EVT, do not care this EVT*/ + if (osal_memcmp(evtBuf, script[i].evt, script[i].evtSz) != 0) { + WMT_ERR_FUNC("WMT-CORE:compare %s result error\n", script[i].str); + WMT_ERR_FUNC + ("WMT-CORE:rx(%d):[%02X,%02X,%02X,%02X,%02X]\n", + u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4]); + WMT_ERR_FUNC + ("WMT-CORE:exp(%d):[%02X,%02X,%02X,%02X,%02X]\n", + script[i].evtSz, script[i].evt[0], script[i].evt[1], script[i].evt[2], + script[i].evt[3], script[i].evt[4]); + if (dump_err_log == 1) + mtk_wcn_stp_dbg_dump_package(); + + err = -1; + break; + } + } + WMT_DBG_FUNC("init_script operation %s ok\n", script[i].str); + } + retry--; + } while (retry >= 0 && err < 0); + + return (i == count) ? 0 : -1; +} + + +INT32 wmt_core_init_script(struct init_script *script, INT32 count) +{ + return wmt_core_init_script_retry(script, count, 0, 1); +} + +static INT32 wmt_core_trigger_assert(VOID) +{ + INT32 ret = 0; + UINT32 u4Res; + UINT32 tstCmdSz = 0; + UINT32 tstEvtSz = 0; + UINT8 tstCmd[64]; + UINT8 tstEvt[64]; + UINT8 WMT_ASSERT_CMD[] = { 0x01, 0x02, 0x01, 0x00, 0x08 }; + UINT8 WMT_ASSERT_EVT[] = { 0x02, 0x02, 0x00, 0x00, 0x00 }; + + 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); + + ret = wmt_core_tx((PUINT8) tstCmd, tstCmdSz, &u4Res, MTK_WCN_BOOL_FALSE); + if (ret || (u4Res != tstCmdSz)) { + WMT_ERR_FUNC("WMT-CORE: wmt_cmd_test iRet(%d) cmd len err(%d, %d)\n", ret, u4Res, + tstCmdSz); + ret = -1; + } + return ret; +} + +static INT32 wmt_core_stp_init(VOID) +{ + INT32 iRet = -1; + ULONG ctrlPa1; + ULONG ctrlPa2; + UINT8 co_clock_type; + P_WMT_CTX pctx = &gMtkWmtCtx; + P_WMT_GEN_CONF pWmtGenConf = NULL; + + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_COMBO) + wmt_conf_read_file(); + gDevWmt.rWmtGenConf.co_clock_flag = wmt_lib_co_clock_flag_get(); + + pWmtGenConf = wmt_conf_get_cfg(); + if (pWmtGenConf == NULL) + WMT_ERR_FUNC("WMT-CORE: wmt_conf_get_cfg return NULL!!\n"); + 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 (pctx->wmtHifConf.hifType == WMT_HIF_SDIO) { + 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 (pctx->wmtHifConf.hifType == WMT_HIF_UART) { + 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 (pctx->wmtHifConf.hifType == WMT_HIF_UART) { + ctrlPa1 = WMT_STP_CONF_MODE; + ctrlPa2 = MTKSTP_UART_MAND_MODE; + iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + } else if (pctx->wmtHifConf.hifType == WMT_HIF_SDIO) { + + ctrlPa1 = WMT_STP_CONF_MODE; + ctrlPa2 = MTKSTP_SDIO_MODE; + iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + if (iRet) + WMT_ERR_FUNC(" confif SDIO_MODE fail!!!!\n"); + } + if (pctx->wmtHifConf.hifType == WMT_HIF_BTIF) { + ctrlPa1 = WMT_STP_CONF_MODE; + ctrlPa2 = MTKSTP_BTIF_MAND_MODE; + iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + } + ctrlPa1 = WMT_STP_CONF_EN; + ctrlPa2 = 1; + iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: stp_init <1><2> fail:%d\n", iRet); + return -7; + } + /* TODO: [ChangeFeature][GeorgeKuo] can we apply raise UART baud rate firstly for ALL supported chips??? */ + +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT + WMT_DBG_FUNC("disable deep sleep featrue before the first command to firmware\n"); + wmt_lib_deep_sleep_flag_set(MTK_WCN_BOOL_FALSE); +#endif + + 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 ((pctx->p_ic_ops->co_clock_ctrl != NULL) && (pWmtGenConf != NULL)) { + co_clock_type = (pWmtGenConf->co_clock_flag & 0x0f); + (*(pctx->p_ic_ops->co_clock_ctrl)) (co_clock_type == 0 ? WMT_CO_CLOCK_DIS : WMT_CO_CLOCK_EN); + } else { + WMT_WARN_FUNC("pctx->p_ic_ops->co_clock_ctrl(%p), pWmtGenConf(%p)\n", pctx->p_ic_ops->co_clock_ctrl, + pWmtGenConf); + } + osal_assert(pctx->p_ic_ops->sw_init != NULL); + if (pctx->p_ic_ops->sw_init != NULL) { + 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; + } + + /* send UTC time sync command after connsys power on or chip reset */ + opfunc_utc_time_sync(NULL); + + /* 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; + ULONG ctrlPa1; + ULONG ctrlPa2; + + WMT_DBG_FUNC(" start\n"); + + if (gMtkWmtCtx.p_ic_ops == NULL) { + WMT_WARN_FUNC("gMtkWmtCtx.p_ic_ops is NULL\n"); + goto deinit_ic_ops_done; + } + if (gMtkWmtCtx.p_ic_ops->sw_deinit != NULL) { + 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 (gMtkWmtCtx.wmtHifConf.hifType == WMT_HIF_SDIO) { + 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_DBG_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_DBG_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(PINT8 pSource) +{ + WMT_INFO_FUNC + ("[%s]status(b:%d f:%d g:%d gl5:%d w:%d lpbk:%d coredump:%d wmt:%d ant:%d sd1:%d sd2:%d stp:%d)\n", + (pSource == NULL ? (PINT8) "CORE" : pSource), gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_BT], + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_FM], gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_GPS], + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_GPSL5], + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WIFI], gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_LPBK], + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_COREDUMP], gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT], + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_ANT], gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO1], + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO2], gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_STP] + ); + return; + +} + +ENUM_DRV_STS wmt_core_get_drv_status(ENUM_WMTDRV_TYPE_T type) +{ + if ((type < WMTDRV_TYPE_BT) || (type >= WMTDRV_TYPE_MAX)) + return DRV_STS_POWER_OFF; + return gMtkWmtCtx.eDrvStatus[type]; +} + +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%x) does not match patch version(0x%x)\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) { +#if defined(KERNEL_clk_buf_show_status_info) + KERNEL_clk_buf_show_status_info(); /* dump clock buffer */ +#endif + WMT_ERR_FUNC("get hwcode (chip id) fail (%d)\n", iret); + return -2; + } + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) { + if (wmt_lib_get_icinfo(WMTCHIN_IPVER)) + chipid = wmt_plat_get_soc_chipid(); + } + 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 + +#if CFG_CORE_MT6630_SUPPORT + case 0x6630: + p_ops = &wmt_ic_ops_mt6630; + break; +#endif + +#if CFG_CORE_MT6632_SUPPORT + case 0x6632: + p_ops = &wmt_ic_ops_mt6632; + break; +#endif +#if CFG_CORE_SOC_SUPPORT + case 0x0690: + case 0x6572: + case 0x6582: + case 0x6592: + case 0x8127: + case 0x6571: + case 0x6752: + case 0x0279: + case 0x0326: + case 0x0321: + case 0x0335: + case 0x0337: + case 0x8163: + case 0x6580: + case 0x0551: + case 0x8167: + case 0x0507: + case 0x0688: + case 0x0699: + case 0x0633: + case 0x0713: + case 0x0788: + case 0x6765: + case 0x6761: + case 0x6779: + case 0x6768: + case 0x6785: + case 0x6833: + case 0x6853: + case 0x6873: + case 0x8168: + p_ops = &wmt_ic_ops_soc; + break; +#endif + + default: + p_ops = (P_WMT_IC_OPS) NULL; +#if CFG_CORE_SOC_SUPPORT + if (chipid - 0x600 == 0x7f90) { + p_ops = &wmt_ic_ops_soc; + chipid -= 0xf6d; + } +#endif + break; + } + + if (p_ops == NULL) { + WMT_ERR_FUNC("unsupported chip id (hw_code): 0x%x\n", chipid); + return -3; + } else if (wmt_core_ic_ops_check(p_ops) == MTK_WCN_BOOL_FALSE) { + 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); + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) { + wmt_ic_ops_soc.icId = chipid; + wmt_ic_ops_soc.options = mtk_wcn_consys_get_options(); + WMT_INFO_FUNC("options = %llx", wmt_ic_ops_soc.options); + } + iret = p_ops->ic_ver_check(); + if (iret) { + WMT_ERR_FUNC("chip id(0x%x) ver_check error:%d\n", chipid, iret); + return -5; + } + + WMT_DBG_FUNC("chip id(0x%x) ver_check ok\n", chipid); + gMtkWmtCtx.p_ic_ops = p_ops; + return 0; +} + +static INT32 opfunc_hif_conf(P_WMT_OP pWmtOp) +{ + if (!(pWmtOp->u4InfoBit & WMT_OP_HIF_BIT)) { + WMT_ERR_FUNC("WMT-CORE: no HIF_BIT in WMT_OP!\n"); + return -1; + } + + if (gMtkWmtCtx.wmtInfoBit & WMT_OP_HIF_BIT) { + WMT_ERR_FUNC("WMT-CORE: WMT HIF already exist. Just return\n"); + return 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; + ULONG ctrlPa1; + ULONG ctrlPa2; + INT32 retry = WMT_PWRON_RTY_DFT; + + if (gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] != DRV_STS_POWER_OFF) { + WMT_ERR_FUNC("WMT-CORE: already powered on, WMT DRV_STS_[0x%x]\n", + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]); + osal_assert(0); + return -1; + } + +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 (retry-- == 0) { + WMT_INFO_FUNC("WMT-CORE: retry (%d)\n", retry); + goto pwr_on_rty; + } + return -2; + } + 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(); + if (iRet) + WMT_ERR_FUNC("WMT-CORE: wmt_core_stp_deinit() failed.\n"); + iRet = opfunc_pwr_off(pWmtOp); + if (iRet) + WMT_ERR_FUNC("WMT-CORE: opfunc_pwr_off fail during pwr_on retry\n"); + + if (retry-- > 0) { + WMT_INFO_FUNC("WMT-CORE: retry (%d)\n", retry); + goto pwr_on_rty; + } + return -3; + } + + WMT_DBG_FUNC("WMT-CORE: WMT [FUNC_ON]\n"); + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_FUNC_ON; + + /* update blank status when ConnSys power on */ + wmt_blank_status_ctrl(wmt_dev_get_blank_state()); + + mtk_wcn_consys_sleep_info_restore(); + + /* 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; + ULONG ctrlPa1; + ULONG ctrlPa2; + + if (gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] == DRV_STS_POWER_OFF) { + WMT_WARN_FUNC("WMT-CORE: WMT already off, WMT DRV_STS_[0x%x]\n", + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]); + osal_assert(0); + return -1; + } + if (g_pwr_off_flag == MTK_WCN_BOOL_FALSE) { + WMT_WARN_FUNC("CONNSYS power off be disabled, maybe need trigger core dump!\n"); + osal_assert(0); + return -2; + } + /* wmt and stp are initialized successfully */ + if (gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] == DRV_STS_FUNC_ON) { + 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 */ + } + } + + if (wmt_lib_power_lock_aquire() == 0) { + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_POWER_OFF; + wmt_lib_power_lock_release(); + } else { + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_POWER_OFF; + WMT_INFO_FUNC("wmt_lib_power_lock_aquire failed\n"); + } + + /* 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_DBG_FUNC("HW_PWR_OFF ok\n"); + + return iRet; + +} + +static INT32 opfunc_func_on(P_WMT_OP pWmtOp) +{ + INT32 iRet = -1; + UINT32 drvType = pWmtOp->au4OpData[0]; + + /* Check abnormal type */ + if (drvType >= WMTDRV_TYPE_MAX) { + WMT_ERR_FUNC("abnormal Fun(%d)\n", drvType); + osal_assert(0); + return -1; + } + + /* Check abnormal state */ + if ((gMtkWmtCtx.eDrvStatus[drvType] < DRV_STS_POWER_OFF) + || (gMtkWmtCtx.eDrvStatus[drvType] >= DRV_STS_MAX)) { + WMT_ERR_FUNC("func(%d) status[0x%x] abnormal\n", + drvType, gMtkWmtCtx.eDrvStatus[drvType]); + osal_assert(0); + return -2; + } + + if (WMTDRV_TYPE_GPSL5 == drvType) + mtk_wcn_stp_set_support_gpsl5(1); + + /* check if func already on */ + if (gMtkWmtCtx.eDrvStatus[drvType] == DRV_STS_FUNC_ON) { + WMT_WARN_FUNC("func(%d) already on\n", drvType); + return 0; + } + /*enable power off flag, if flag=0, power off connsys will not be executed */ + mtk_wcn_set_connsys_power_off_flag(MTK_WCN_BOOL_TRUE); + /* check if chip power on is needed */ + if (gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] != DRV_STS_FUNC_ON) { + 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 || WMTDRV_TYPE_ANT == drvType || WMTDRV_TYPE_GPSL5 == drvType) { + if (gpWmtFuncOps[drvType] && gpWmtFuncOps[drvType]->func_on) { + + /* special handling for Wi-Fi */ + if (drvType == WMTDRV_TYPE_WIFI) { + P_OSAL_OP pOp = wmt_lib_get_current_op(&gDevWmt); + atomic_set(&g_wifi_on_off_ready, 1); + + pOp->op.opId = WMT_OPID_WLAN_PROBE; + if (wmt_lib_put_worker_op(pOp) == MTK_WCN_BOOL_FALSE) { + WMT_WARN_FUNC("put to activeWorker queue fail\n"); + atomic_set(&g_wifi_on_off_ready, 0); + return -4; + } + return 0; + } + + iRet = (*(gpWmtFuncOps[drvType]->func_on)) (gMtkWmtCtx.p_ic_ops, wmt_conf_get_cfg()); + if (iRet != 0) + 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 (drvType == WMTDRV_TYPE_LPBK) + gMtkWmtCtx.eDrvStatus[drvType] = DRV_STS_FUNC_ON; + else if (drvType == WMTDRV_TYPE_COREDUMP) + 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); + opfunc_try_pwr_off(pWmtOp); + return iRet; + } + + /* send UTC time sync command after function on */ + opfunc_utc_time_sync(NULL); + wmt_core_dump_func_state("AF FUNC ON"); + + return 0; +} + +static INT32 opfunc_func_off(P_WMT_OP pWmtOp) +{ + INT32 iRet = -1; + UINT32 drvType = pWmtOp->au4OpData[0]; + + /* Check abnormal type */ + if (drvType >= WMTDRV_TYPE_MAX) { + WMT_ERR_FUNC("WMT-CORE: abnormal Fun(%d) in wmt_func_off\n", drvType); + osal_assert(0); + return -1; + } + + /* Check abnormal state */ + if (gMtkWmtCtx.eDrvStatus[drvType] >= DRV_STS_MAX) { + 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 (gMtkWmtCtx.eDrvStatus[drvType] != DRV_STS_FUNC_ON) { + 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 || WMTDRV_TYPE_ANT == drvType || WMTDRV_TYPE_GPSL5 == drvType) { + if (gpWmtFuncOps[drvType] && gpWmtFuncOps[drvType]->func_off) { + /* special handling for Wi-Fi */ + if (drvType == WMTDRV_TYPE_WIFI) { + P_OSAL_OP pOp = wmt_lib_get_current_op(&gDevWmt); + atomic_set(&g_wifi_on_off_ready, 1); + + pOp->op.opId = WMT_OPID_WLAN_REMOVE; + if (wmt_lib_put_worker_op(pOp) == MTK_WCN_BOOL_FALSE) { + WMT_WARN_FUNC("put to activeWorker queue fail\n"); + atomic_set(&g_wifi_on_off_ready, 0); + return -4; + } + return 0; + } + iRet = (*(gpWmtFuncOps[drvType]->func_off)) (gMtkWmtCtx.p_ic_ops, wmt_conf_get_cfg()); + } else { + WMT_WARN_FUNC("WMT-CORE: ops for type(%d) not found\n", drvType); + iRet = -3; + } + } else { + if (drvType == WMTDRV_TYPE_LPBK) + gMtkWmtCtx.eDrvStatus[drvType] = DRV_STS_POWER_OFF; + else if (drvType == WMTDRV_TYPE_COREDUMP) + gMtkWmtCtx.eDrvStatus[drvType] = DRV_STS_POWER_OFF; + iRet = 0; + } + + if (drvType != WMTDRV_TYPE_WMT) + 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 */ + opfunc_try_pwr_off(pWmtOp); + wmt_core_dump_func_state("AF FUNC OFF"); + return iRet; +} + +static INT32 opfunc_gps_suspend_by_type(ENUM_WMTDRV_TYPE_T type, P_WMT_OP pWmtOp) +{ + INT32 iRet = -1; + P_WMT_GEN_CONF pWmtGenConf = NULL; + MTK_WCN_BOOL suspend = (pWmtOp->au4OpData[0] != 0); + UINT32 suspend_flag = WMT_GPS_SUSPEND; + + if (WMTDRV_TYPE_GPS != type && WMTDRV_TYPE_GPSL5 != type) + return 0; + + if (WMTDRV_TYPE_GPSL5 == type) + suspend_flag = WMT_GPSL5_SUSPEND; + + pWmtGenConf = wmt_conf_get_cfg(); + + if (gMtkWmtCtx.eDrvStatus[type] != DRV_STS_FUNC_ON) { + WMT_WARN_FUNC("WMT-CORE: GPS(%d) driver non-FUN_ON in opfunc_gps_suspend\n", type); + return 0; + } + + if (MTK_WCN_BOOL_TRUE == suspend) { + if (osal_test_bit(suspend_flag, &gGpsFmState)) { + WMT_WARN_FUNC("WMT-CORE: GPS(%d) already suspend\n", type); + return 0; + } + } else { + if (!osal_test_bit(suspend_flag, &gGpsFmState)) { + WMT_WARN_FUNC("WMT-CORE: GPS(%d) already resume on\n", type); + return 0; + } + } + + if (MTK_WCN_BOOL_TRUE == suspend) { + if (gpWmtFuncOps[type] && gpWmtFuncOps[type]->func_off) { + if (pWmtGenConf != NULL) + pWmtGenConf->wmt_gps_suspend_ctrl = 1; + iRet = (*(gpWmtFuncOps[type]->func_off)) (gMtkWmtCtx.p_ic_ops, wmt_conf_get_cfg()); + if (pWmtGenConf != NULL) + pWmtGenConf->wmt_gps_suspend_ctrl = 0; + } else { + WMT_WARN_FUNC("WMT-CORE: GPS(%d) suspend ops not found\n", type); + iRet = -3; + } + } else { + /*enable power off flag, if flag=0, power off connsys will not be executed */ + mtk_wcn_set_connsys_power_off_flag(MTK_WCN_BOOL_TRUE); + /* check if chip power on is needed */ + if (gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] != DRV_STS_FUNC_ON) { + iRet = opfunc_pwr_on(pWmtOp); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: func(%d) hw resume fail(%d)\n", type, iRet); + osal_assert(0); + + /* check all sub-func and do power off */ + return -5; + } + } + + if (gpWmtFuncOps[type] && gpWmtFuncOps[type]->func_on) { + if (pWmtGenConf != NULL) + pWmtGenConf->wmt_gps_suspend_ctrl = 1; + iRet = (*(gpWmtFuncOps[type]->func_on)) (gMtkWmtCtx.p_ic_ops, wmt_conf_get_cfg()); + if (pWmtGenConf != NULL) + pWmtGenConf->wmt_gps_suspend_ctrl = 0; + } else { + WMT_WARN_FUNC("WMT-CORE: GPS(%d) resume ops not found\n", type); + iRet = -7; + } + } + + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: gps(%d) %s function failed, ret(%d)\n", + type, ((pWmtOp->au4OpData[0] != 0) ? "suspend" : "resume"), iRet); + osal_assert(0); + } + + if (MTK_WCN_BOOL_FALSE == suspend) + opfunc_utc_time_sync(NULL); + + return iRet; +} + +static INT32 opfunc_gps_suspend(P_WMT_OP pWmtOp) +{ + if (pWmtOp->au4OpData[1] == 1) + opfunc_gps_suspend_by_type(WMTDRV_TYPE_GPS, pWmtOp); + + if (pWmtOp->au4OpData[2] == 1) + opfunc_gps_suspend_by_type(WMTDRV_TYPE_GPSL5, pWmtOp); + + return 0; +} + +/* TODO:[ChangeFeature][George] is this OP obsoleted? */ +static INT32 opfunc_reg_rw(P_WMT_OP pWmtOp) +{ + INT32 iret; + + if (gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] != DRV_STS_FUNC_ON) { + WMT_ERR_FUNC("reg_rw when WMT is powered off\n"); + return -1; + } + iret = wmt_core_reg_rw_raw(pWmtOp->au4OpData[0], + pWmtOp->au4OpData[1], + (PUINT32) pWmtOp->au4OpData[2], pWmtOp->au4OpData[3]); + + return iret; +} + +static INT32 opfunc_exit(P_WMT_OP pWmtOp) +{ + /* TODO: [FixMe][George] is ok to leave this function empty??? */ + WMT_WARN_FUNC("EMPTY FUNCTION\n"); + return 0; +} + +static INT32 opfunc_pwr_sv(P_WMT_OP pWmtOp) +{ + INT32 ret = -1; + UINT32 u4_result = 0; + UINT32 evt_len; + UINT8 evt_buf[16] = { 0 }; + ULONG ctrlPa1 = 0; + ULONG ctrlPa2 = 0; + + typedef INT32(*STP_PSM_CB) (const MTKSTP_PSM_ACTION_T); + STP_PSM_CB psm_cb = NULL; + + if (pWmtOp->au4OpData[0] == SLEEP) { + 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((const PUINT8)(&WMT_SLEEP_CMD[0]), sizeof(WMT_SLEEP_CMD), + &u4_result, 0); + if (ret || (u4_result != sizeof(WMT_SLEEP_CMD))) { + WMT_ERR_FUNC("wmt_core: SLEEP_CMD ret(%d) cmd len err(%d, %zu) ", 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), host trigger firmware assert\n", + ret, u4_result, evt_len); + + wmt_lib_trigger_assert(WMTDRV_TYPE_WMT, 33); + goto pwr_sv_done; + } + + if (osal_memcmp(evt_buf, (const PVOID)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("rx(%d):[%2X,%2X,%2X,%2X,%2X,%2X] exp(%zu):[%2X,%2X,%2X,%2X,%2X,%2X]\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; + } + WMT_DBG_FUNC("Send sleep command OK!\n"); + } else if (pWmtOp->au4OpData[0] == WAKEUP) { + if (mtk_wcn_stp_is_btif_fullset_mode()) { + WMT_DBG_FUNC("wakeup connsys by btif"); + ret = wmt_core_ctrl(WMT_CTRL_SOC_WAKEUP_CONSYS, &ctrlPa1, &ctrlPa2); + if (ret) { + WMT_ERR_FUNC("wmt-core:WAKEUP_CONSYS by BTIF fail(%d)", ret); + goto pwr_sv_done; + } + } else if (mtk_wcn_stp_is_sdio_mode()) { + WMT_DBG_FUNC("**** Send wakeup command\n"); + ret = + wmt_core_tx((const PUINT8)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, %zu)\n", + 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), host grigger firmaware assert\n", + ret, u4_result, evt_len); + + wmt_lib_trigger_assert(WMTDRV_TYPE_WMT, 34); + goto pwr_sv_done; + } + + if (osal_memcmp(evt_buf, (const PVOID)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("rx(%d):[%2X,%2X,%2X,%2X,%2X,%2X] exp(%zu):[%2X,%2X,%2X,%2X,%2X,%2X]\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; + } + WMT_DBG_FUNC("Send wakeup command OK!\n"); + } else if (pWmtOp->au4OpData[0] == HOST_AWAKE) { + + WMT_DBG_FUNC("**** Send host awake command\n"); + + psm_cb = (STP_PSM_CB) pWmtOp->au4OpData[1]; + /* (*kal_stp_flush_rx)(WMT_TASK_INDX); */ + ret = + wmt_core_tx((const PUINT8)WMT_HOST_AWAKE_CMD, sizeof(WMT_HOST_AWAKE_CMD), + &u4_result, 0); + if (ret || (u4_result != sizeof(WMT_HOST_AWAKE_CMD))) { + WMT_ERR_FUNC("wmt_core: HOST_AWAKE_CMD ret(%d) cmd len err(%d, %zu) ", 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), host trigger f/w assert\n", + ret, u4_result, evt_len); + + wmt_lib_trigger_assert(WMTDRV_TYPE_WMT, 35); + goto pwr_sv_done; + } + + if (osal_memcmp + (evt_buf, (const PVOID)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("rx(%d):[%2X,%2X,%2X,%2X,%2X,%2X] exp(%zu):[%2X,%2X,%2X,%2X,%2X,%2X]\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_DBG_FUNC("Send host awake command OK!\n"); + } + } +pwr_sv_done: + + if (pWmtOp->au4OpData[0] < STP_PSM_MAX_ACTION) { + psm_cb = (STP_PSM_CB) pWmtOp->au4OpData[1]; + WMT_DBG_FUNC("Do STP-CB! %zu %p\n", pWmtOp->au4OpData[0], + (PVOID) pWmtOp->au4OpData[1]); + if (psm_cb != NULL) { + 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, %zu)\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(%zu):[%02X,%02X,%02X,%02X,%02X]\n", + u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], + osal_sizeof(WMT_DSNS_EVT), WMT_DSNS_EVT[0], WMT_DSNS_EVT[1], WMT_DSNS_EVT[2], + WMT_DSNS_EVT[3], WMT_DSNS_EVT[4]); + } else { + WMT_INFO_FUNC("Send WMT_DSNS_CMD command OK!\n"); + } + + return iRet; +} + +#if CFG_CORE_INTERNAL_TXRX +INT32 wmt_core_lpbk_do_stp_init(void) +{ + INT32 iRet = 0; + ULONG ctrlPa1 = 0; + ULONG ctrlPa2 = 0; + + ctrlPa1 = 0; + ctrlPa2 = 0; + iRet = wmt_core_ctrl(WMT_CTRL_STP_OPEN, &ctrlPa1, &ctrlPa2); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: wmt open stp\n"); + return -1; + } + + ctrlPa1 = WMT_STP_CONF_MODE; + ctrlPa2 = MTKSTP_BTIF_MAND_MODE; + iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + + ctrlPa1 = WMT_STP_CONF_EN; + ctrlPa2 = 1; + iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: stp_init <1><2> fail:%d\n", iRet); + return -2; + } +} + +INT32 wmt_core_lpbk_do_stp_deinit(void) +{ + INT32 iRet = 0; + ULONG ctrlPa1 = 0; + ULONG ctrlPa2 = 0; + + ctrlPa1 = 0; + ctrlPa2 = 0; + iRet = wmt_core_ctrl(WMT_CTRL_STP_CLOSE, &ctrlPa1, &ctrlPa2); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: wmt open stp\n"); + return -1; + } + + return 0; +} +#endif + + +static INT32 opfunc_lpbk(P_WMT_OP pWmtOp) +{ + + INT32 iRet; + UINT32 u4WrittenSize = 0; + UINT32 u4ReadSize = 0; + UINT32 buf_length = 0; + PUINT32 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 = (PUINT32) 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 (gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_LPBK] != DRV_STS_FUNC_ON + || 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, %zu)\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((PVOID) 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); */ + if (fgFail == MTK_WCN_BOOL_TRUE) { + WMT_ERR_FUNC("LPBK fail and trigger assert\n"); + wmt_lib_trigger_assert(WMTDRV_TYPE_WMT, 37); + } + 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; + + PUINT8 pRes = NULL; + UINT32 resBufRoom = 0; + /*test command list */ + /*1 */ + UINT8 WMT_ASSERT_CMD[] = { 0x01, 0x02, 0x01, 0x00, 0x08 }; + UINT8 WMT_ASSERT_EVT[] = { 0x02, 0x02, 0x00, 0x00, 0x00 }; + UINT8 WMT_NOACK_CMD[] = { 0x01, 0x02, 0x01, 0x00, 0x0A }; + UINT8 WMT_NOACK_EVT[] = { 0x02, 0x02, 0x00, 0x00, 0x00 }; + UINT8 WMT_WARNRST_CMD[] = { 0x01, 0x02, 0x01, 0x00, 0x0B }; + UINT8 WMT_WARNRST_EVT[] = { 0x02, 0x02, 0x00, 0x00, 0x00 }; + UINT8 WMT_FWLOGTST_CMD[] = { 0x01, 0x02, 0x01, 0x00, 0x0C }; + UINT8 WMT_FWLOGTST_EVT[] = { 0x02, 0x02, 0x00, 0x00, 0x00 }; + + UINT8 WMT_EXCEPTION_CMD[] = { 0x01, 0x02, 0x01, 0x00, 0x09 }; + UINT8 WMT_EXCEPTION_EVT[] = { 0x02, 0x02, 0x00, 0x00, 0x00 }; + /*2 */ + UINT8 WMT_COEXDBG_CMD[] = { 0x01, 0x10, 0x02, 0x00, + 0x08, + 0xAA /*Debugging Parameter */ + }; + UINT8 WMT_COEXDBG_1_EVT[] = { 0x02, 0x10, 0x05, 0x00, + 0x00, + 0xAA, 0xAA, 0xAA, 0xAA /*event content */ + }; + UINT8 WMT_COEXDBG_2_EVT[] = { 0x02, 0x10, 0x07, 0x00, + 0x00, + 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB /*event content */ + }; + UINT8 WMT_COEXDBG_3_EVT[] = { 0x02, 0x10, 0x0B, 0x00, + 0x00, + 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xBB, 0xBB /*event content */ + }; + /*test command list -end */ + + cmdNo = pWmtOp->au4OpData[0]; + + WMT_INFO_FUNC("Send Test command %d!\n", cmdNo); + if (cmdNo == 0) { + /*dead command */ + WMT_INFO_FUNC("Send Assert command !\n"); + tstCmdSz = osal_sizeof(WMT_ASSERT_CMD); + tstEvtSz = osal_sizeof(WMT_ASSERT_EVT); + osal_memcpy(tstCmd, WMT_ASSERT_CMD, tstCmdSz); + osal_memcpy(tstEvt, WMT_ASSERT_EVT, tstEvtSz); + } else if (cmdNo == 1) { + /*dead command */ + WMT_INFO_FUNC("Send Exception command !\n"); + tstCmdSz = osal_sizeof(WMT_EXCEPTION_CMD); + tstEvtSz = osal_sizeof(WMT_EXCEPTION_EVT); + osal_memcpy(tstCmd, WMT_EXCEPTION_CMD, tstCmdSz); + osal_memcpy(tstEvt, WMT_EXCEPTION_EVT, tstEvtSz); + } else if (cmdNo == 2) { + cmdNoPa = pWmtOp->au4OpData[1]; + pRes = (PUINT8) pWmtOp->au4OpData[2]; + resBufRoom = pWmtOp->au4OpData[3]; + if (cmdNoPa <= 0xf) { + WMT_INFO_FUNC("Send Coexistence Debug command [0x%x]!\n", cmdNoPa); + tstCmdSz = osal_sizeof(WMT_COEXDBG_CMD); + osal_memcpy(tstCmd, WMT_COEXDBG_CMD, tstCmdSz); + if (tstCmdSz > 5) + tstCmd[5] = cmdNoPa; + + /*setup the expected event length */ + if (cmdNoPa <= 0x4) { + tstEvtSz = osal_sizeof(WMT_COEXDBG_1_EVT); + osal_memcpy(tstEvt, WMT_COEXDBG_1_EVT, tstEvtSz); + } else if (cmdNoPa == 0x5) { + tstEvtSz = osal_sizeof(WMT_COEXDBG_2_EVT); + osal_memcpy(tstEvt, WMT_COEXDBG_2_EVT, tstEvtSz); + } else if (cmdNoPa >= 0x6 && cmdNoPa <= 0xf) { + tstEvtSz = osal_sizeof(WMT_COEXDBG_3_EVT); + osal_memcpy(tstEvt, WMT_COEXDBG_3_EVT, tstEvtSz); + } else { + + } + } else { + WMT_ERR_FUNC("cmdNoPa is wrong\n"); + return iRet; + } + } else if (cmdNo == 3) { + /*dead command */ + WMT_INFO_FUNC("Send No Ack command !\n"); + tstCmdSz = osal_sizeof(WMT_NOACK_CMD); + tstEvtSz = osal_sizeof(WMT_NOACK_EVT); + osal_memcpy(tstCmd, WMT_NOACK_CMD, tstCmdSz); + osal_memcpy(tstEvt, WMT_NOACK_EVT, tstEvtSz); + } else if (cmdNo == 4) { + /*dead command */ + WMT_INFO_FUNC("Send Warm reset command !\n"); + tstCmdSz = osal_sizeof(WMT_WARNRST_CMD); + tstEvtSz = osal_sizeof(WMT_WARNRST_EVT); + osal_memcpy(tstCmd, WMT_WARNRST_CMD, tstCmdSz); + osal_memcpy(tstEvt, WMT_WARNRST_EVT, tstEvtSz); + } else if (cmdNo == 5) { + /*dead command */ + WMT_INFO_FUNC("Send f/w log test command !\n"); + tstCmdSz = osal_sizeof(WMT_FWLOGTST_CMD); + tstEvtSz = osal_sizeof(WMT_FWLOGTST_EVT); + osal_memcpy(tstCmd, WMT_FWLOGTST_CMD, tstCmdSz); + osal_memcpy(tstEvt, WMT_FWLOGTST_EVT, tstEvtSz); + } + + /* send command */ + /* iRet = (*kal_stp_tx)(tstCmd, tstCmdSz, &u4Res); */ + iRet = wmt_core_tx((PUINT8) tstCmd, tstCmdSz, &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != tstCmdSz)) { + WMT_ERR_FUNC("WMT-CORE: wmt_cmd_test iRet(%d) cmd len err(%d, %d)\n", iRet, u4Res, + tstCmdSz); + return -1; + } + + if ((cmdNo == 0) || (cmdNo == 1) || cmdNo == 3) { + WMT_INFO_FUNC("WMT-CORE: not to rx event for assert command\n"); + return 0; + } + + iRet = wmt_core_rx(tstEvtTmp, tstEvtSz, &u4Res); + + /*Event Post Handling */ + if (cmdNo == 2) { + WMT_INFO_FUNC("#=========================================================#\n"); + WMT_INFO_FUNC("coext debugging id = %d", cmdNoPa); + if (tstEvtSz > 5) + wmt_core_dump_data(&tstEvtTmp[5], "coex debugging ", tstEvtSz - 5); + else + 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; + ULONG ctrlPa1 = 0; + ULONG ctrlPa2 = 0; + + 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_GPSL5] = 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; + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_ANT] = DRV_STS_POWER_OFF; + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_COREDUMP] = DRV_STS_POWER_OFF; + /*enable power off flag, if flag=0, power off connsys will not be executed */ + mtk_wcn_set_connsys_power_off_flag(MTK_WCN_BOOL_TRUE); + + /* if wmt is poweroff, we need poweron chip first */ + if (gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] == DRV_STS_POWER_OFF) { + 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; + } + + if (gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_BT] == DRV_STS_FUNC_ON) { + if (mtk_wcn_stp_is_btif_fullset_mode()) { + ctrlPa1 = BT_PALDO; + ctrlPa2 = PALDO_OFF; + iRet = wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + if (iRet) + WMT_ERR_FUNC("WMT-CORE: wmt_ctrl_soc_paldo_ctrl failed(%d)(%lu)(%lu)\n", + iRet, ctrlPa1, ctrlPa2); + } + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_BT] = DRV_STS_POWER_OFF; + } + + iRet = wmt_lib_wlan_lock_aquire(); + if (iRet) { + WMT_ERR_FUNC("--->lock wlan_lock failed, iRet=%d\n", iRet); + return iRet; + } + + /*--> reset SDIO function/slot additionally if wifi ON*/ + if (gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WIFI] == DRV_STS_FUNC_ON) { + if (mtk_wcn_stp_is_sdio_mode()) { + 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 */ + } else if (mtk_wcn_stp_is_btif_fullset_mode()) { + if (gpWmtFuncOps[WMTDRV_TYPE_WIFI] != NULL && + gpWmtFuncOps[WMTDRV_TYPE_WIFI]->func_off != NULL) { + iRet = gpWmtFuncOps[WMTDRV_TYPE_WIFI]->func_off(gMtkWmtCtx.p_ic_ops, + wmt_conf_get_cfg()); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: turn off WIFI func fail (%d)\n", iRet); + + /* check all sub-func and do power off */ + } else { + WMT_INFO_FUNC("wmt core: turn off WIFI func ok!!\n"); + } + } + } + /* Anyway, turn off Wi-Fi Function */ + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WIFI] = DRV_STS_POWER_OFF; + + if (gMtkWmtCtx.wmtHifConf.hifType == WMT_HIF_UART) { + 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; + } + wmt_lib_wlan_lock_release(); + + if (gMtkWmtCtx.wmtHifConf.hifType == WMT_HIF_SDIO) { + 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) +{ + INT32 iRet = -1; + + iRet = wmt_core_stp_init(); + if (iRet == 0) { + WMT_INFO_FUNC("WMT-CORE: SW Rst succeed\n"); + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_FUNC_ON; + } else { + WMT_ERR_FUNC("WMT-CORE: SW Rst failed\n"); + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_POWER_OFF; + } + + return iRet; +} + +static INT32 opfunc_stp_rst(P_WMT_OP pWmtOp) +{ + + return 0; +} + +static INT32 opfunc_therm_ctrl(P_WMT_OP pWmtOp) +{ + + INT32 iRet = -1; + UINT32 u4Res; + UINT32 evtLen; + UINT8 evtBuf[16] = { 0 }; + + WMT_THERM_CMD[4] = pWmtOp->au4OpData[0]; /*CMD type, refer to ENUM_WMTTHERM_TYPE_T */ + + /* send command */ + /* iRet = (*kal_stp_tx)(WMT_THERM_CMD, osal_sizeof(WMT_THERM_CMD), &u4Res); */ + iRet = + wmt_core_tx((PUINT8) WMT_THERM_CMD, osal_sizeof(WMT_THERM_CMD), &u4Res, + MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != osal_sizeof(WMT_THERM_CMD))) { + WMT_ERR_FUNC("WMT-CORE: THERM_CTRL_CMD iRet(%d) cmd len err(%d, %zu)\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)\n", iRet, u4Res); + wmt_lib_trigger_assert(WMTDRV_TYPE_WMT, 36); + 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(%zu):[%02X,%02X,%02X,%02X,%02X]\n", + u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], + osal_sizeof(WMT_THERM_CTRL_EVT), WMT_THERM_CTRL_EVT[0], + WMT_THERM_CTRL_EVT[1], WMT_THERM_CTRL_EVT[2], WMT_THERM_CTRL_EVT[3], + WMT_THERM_CTRL_EVT[4]); + pWmtOp->au4OpData[1] = MTK_WCN_BOOL_FALSE; /*will return to function driver */ + mtk_wcn_stp_dbg_dump_package(); + } else { + WMT_DBG_FUNC("Send WMT_THERM_CTRL_CMD command OK!\n"); + pWmtOp->au4OpData[1] = MTK_WCN_BOOL_TRUE; /*will return to function driver */ + } + } else { + /*no need to judge the real thermal value */ + if (osal_memcmp(evtBuf, WMT_THERM_READ_EVT, osal_sizeof(WMT_THERM_READ_EVT) - 1) != + 0) { + WMT_ERR_FUNC("WMT-CORE: compare WMT_THERM_READ_EVT error\n"); + WMT_ERR_FUNC + ("WMT-CORE: rx(%d):[%02X,%02X,%02X,%02X,%02X,%02X] exp(%zu):[%02X,%02X,%02X,%02X]\n", + u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], + evtBuf[5], osal_sizeof(WMT_THERM_READ_EVT), WMT_THERM_READ_EVT[0], + WMT_THERM_READ_EVT[1], WMT_THERM_READ_EVT[2], WMT_THERM_READ_EVT[3]); + pWmtOp->au4OpData[1] = 0xFF; /*will return to function driver */ + mtk_wcn_stp_dbg_dump_package(); + } else { + WMT_DBG_FUNC("Send WMT_THERM_READ_CMD command OK!\n"); + pWmtOp->au4OpData[1] = evtBuf[5]; /*will return to function driver */ + } + } + + return iRet; + +} + +static INT32 opfunc_efuse_rw(P_WMT_OP pWmtOp) +{ + + INT32 iRet = -1; + UINT32 u4Res; + UINT32 evtLen; + UINT8 evtBuf[16] = { 0 }; + + if (gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] != DRV_STS_FUNC_ON) { + 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, %zu)\n", iRet, u4Res, + osal_sizeof(WMT_EFUSE_CMD)); + return iRet; + } + + evtLen = 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_INFO_FUNC("buf:[%2X,%2X,%2X,%2X,%2X] evt:[%2X,%2X,%2X,%2X,%2X]\n", + evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], + WMT_EFUSE_EVT[0], WMT_EFUSE_EVT[1], WMT_EFUSE_EVT[2], + WMT_EFUSE_EVT[3], WMT_EFUSE_EVT[4]); + } + 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 (gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] != DRV_STS_FUNC_ON) { + 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) +{ + ULONG ctrlPa1 = 0; + ULONG 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] = + ctrlPa2 == 0 ? DRV_STS_POWER_OFF : DRV_STS_POWER_ON; + } + + return 0; + +} + +INT32 opfunc_trigger_stp_assert(P_WMT_OP pWmtOp) +{ + if (wmt_core_trigger_stp_assert() == MTK_WCN_BOOL_TRUE) { + WMT_INFO_FUNC("trigger STP assert succeed\n"); + return 0; + } + WMT_WARN_FUNC("trigger STP assert failed\n"); + return -1; +} + +MTK_WCN_BOOL wmt_core_is_quick_ps_support(VOID) +{ + P_WMT_CTX pctx = &gMtkWmtCtx; + + if ((pctx->p_ic_ops != NULL) && (pctx->p_ic_ops->is_quick_sleep != NULL)) + 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 ((pctx->p_ic_ops != NULL) && (pctx->p_ic_ops->is_aee_dump_support != NULL)) + bRet = (*(pctx->p_ic_ops->is_aee_dump_support))(); + else + bRet = MTK_WCN_BOOL_FALSE; + + return bRet; +} + +static INT32 opfunc_bgw_ds(P_WMT_OP pWmtOp) +{ + INT32 iRet = -1; + UINT32 u4WrittenSize = 0; + UINT32 u4ReadSize = 0; + UINT32 buf_len = 0; + UINT8 *buffer = NULL; + UINT8 evt_buffer[8] = { 0 }; + MTK_WCN_BOOL fgFail; + + UINT8 WMT_BGW_DESENSE_CMD[] = { + 0x01, 0x0e, 0x0f, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 + }; + UINT8 WMT_BGW_DESENSE_EVT[] = { 0x02, 0x0e, 0x01, 0x00, 0x00 }; + + buf_len = pWmtOp->au4OpData[0]; + buffer = (PUINT8) pWmtOp->au4OpData[1]; + + osal_memcpy(&WMT_BGW_DESENSE_CMD[5], buffer, buf_len); + + do { + fgFail = MTK_WCN_BOOL_TRUE; + + iRet = + wmt_core_tx(&WMT_BGW_DESENSE_CMD[0], osal_sizeof(WMT_BGW_DESENSE_CMD), &u4WrittenSize, + MTK_WCN_BOOL_FALSE); + if (iRet || (u4WrittenSize != osal_sizeof(WMT_BGW_DESENSE_CMD))) { + WMT_ERR_FUNC("bgw desense tx CMD fail(%d),size(%d)\n", iRet, u4WrittenSize); + break; + } + + iRet = wmt_core_rx(evt_buffer, osal_sizeof(WMT_BGW_DESENSE_EVT), &u4ReadSize); + if (iRet || (u4ReadSize != osal_sizeof(WMT_BGW_DESENSE_EVT))) { + WMT_ERR_FUNC("bgw desense rx EVT fail(%d),size(%d)\n", iRet, u4ReadSize); + break; + } + + if (osal_memcmp(evt_buffer, WMT_BGW_DESENSE_EVT, osal_sizeof(WMT_BGW_DESENSE_EVT)) != 0) { + WMT_ERR_FUNC + ("bgw desense WMT_BGW_DESENSE_EVT compare fail:0x%02x,0x%02x,0x%02x,0x%02x,0x%02x\n", + evt_buffer[0], evt_buffer[1], evt_buffer[2], evt_buffer[3], evt_buffer[4]); + break; + } + + fgFail = MTK_WCN_BOOL_FALSE; + + } while (0); + + return fgFail; +} + +static INT32 wmt_core_gen2_set_mcu_clk(UINT32 kind) +{ + INT32 iRet = -1; + UINT32 u4WrittenSize = 0; + UINT32 u4ReadSize = 0; + UINT8 evt_buffer[12] = { 0 }; + MTK_WCN_BOOL fgFail; + PUINT8 set_mcu_clk_str[] = { + "Enable GEN2 MCU PLL", + "SET GEN2 MCU CLK to 26M", + "SET GEN2 MCU CLK to 37M", + "SET GEN2 MCU CLK to 64M", + "SET GEN2 MCU CLK to 69M", + "SET GEN2 MCU CLK to 104M", + "SET GEN2 MCU CLK to 118.857M", + "SET GEN2 MCU CLK to 138.67M", + "Disable GEN2 MCU PLL" + }; + UINT8 WMT_SET_MCU_CLK_CMD[] = { + 0x01, 0x08, 0x10, 0x00, + 0x01, 0x01, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff + }; + UINT8 WMT_SET_MCU_CLK_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; + + UINT8 WMT_EN_MCU_CLK_CMD[] = { 0x34, 0x03, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00 }; /* enable pll clk */ + UINT8 WMT_26_MCU_CLK_CMD[] = { 0x0c, 0x01, 0x00, 0x80, 0x00, 0x4d, 0x84, 0x00 }; /* set 26M */ + UINT8 WMT_37_MCU_CLK_CMD[] = { 0x0c, 0x01, 0x00, 0x80, 0x1e, 0x4d, 0x84, 0x00 }; /* set 37.8M */ + UINT8 WMT_64_MCU_CLK_CMD[] = { 0x0c, 0x01, 0x00, 0x80, 0x1d, 0x4d, 0x84, 0x00 }; /* set 64M */ + UINT8 WMT_69_MCU_CLK_CMD[] = { 0x0c, 0x01, 0x00, 0x80, 0x1c, 0x4d, 0x84, 0x00 }; /* set 69M */ + UINT8 WMT_104_MCU_CLK_CMD[] = { 0x0c, 0x01, 0x00, 0x80, 0x5b, 0x4d, 0x84, 0x00 }; /* set 104M */ + UINT8 WMT_108_MCU_CLK_CMD[] = { 0x0c, 0x01, 0x00, 0x80, 0x5a, 0x4d, 0x84, 0x00 }; /* set 118.857M */ + UINT8 WMT_138_MCU_CLK_CMD[] = { 0x0c, 0x01, 0x00, 0x80, 0x59, 0x4d, 0x84, 0x00 }; /* set 138.67M */ + UINT8 WMT_DIS_MCU_CLK_CMD[] = { 0x34, 0x03, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00 }; /* disable pll clk */ + + WMT_INFO_FUNC("do %s\n", set_mcu_clk_str[kind]); + + switch (kind) { + case 0: + osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_EN_MCU_CLK_CMD[0], osal_sizeof(WMT_EN_MCU_CLK_CMD)); + break; + case 1: + osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_26_MCU_CLK_CMD[0], osal_sizeof(WMT_26_MCU_CLK_CMD)); + break; + case 2: + osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_37_MCU_CLK_CMD[0], osal_sizeof(WMT_37_MCU_CLK_CMD)); + break; + case 3: + osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_64_MCU_CLK_CMD[0], osal_sizeof(WMT_64_MCU_CLK_CMD)); + break; + case 4: + osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_69_MCU_CLK_CMD[0], osal_sizeof(WMT_69_MCU_CLK_CMD)); + break; + case 5: + osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_104_MCU_CLK_CMD[0], osal_sizeof(WMT_104_MCU_CLK_CMD)); + break; + case 6: + osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_108_MCU_CLK_CMD[0], osal_sizeof(WMT_108_MCU_CLK_CMD)); + break; + case 7: + osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_138_MCU_CLK_CMD[0], osal_sizeof(WMT_138_MCU_CLK_CMD)); + break; + case 8: + osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_DIS_MCU_CLK_CMD[0], osal_sizeof(WMT_DIS_MCU_CLK_CMD)); + break; + default: + WMT_ERR_FUNC("unknown kind\n"); + break; + } + + do { + fgFail = MTK_WCN_BOOL_TRUE; + + iRet = + wmt_core_tx(&WMT_SET_MCU_CLK_CMD[0], osal_sizeof(WMT_SET_MCU_CLK_CMD), &u4WrittenSize, + MTK_WCN_BOOL_FALSE); + if (iRet || (u4WrittenSize != osal_sizeof(WMT_SET_MCU_CLK_CMD))) { + WMT_ERR_FUNC("WMT_SET_MCU_CLK_CMD fail(%d),size(%d)\n", iRet, u4WrittenSize); + break; + } + + iRet = wmt_core_rx(evt_buffer, osal_sizeof(WMT_SET_MCU_CLK_EVT), &u4ReadSize); + if (iRet || (u4ReadSize != osal_sizeof(WMT_SET_MCU_CLK_EVT))) { + WMT_ERR_FUNC("WMT_SET_MCU_CLK_EVT fail(%d),size(%d)\n", iRet, u4ReadSize); + mtk_wcn_stp_dbg_dump_package(); + break; + } + + if (osal_memcmp(evt_buffer, WMT_SET_MCU_CLK_EVT, osal_sizeof(WMT_SET_MCU_CLK_EVT)) != 0) { + WMT_ERR_FUNC("WMT_SET_MCU_CLK_EVT compare fail, [0-3]:0x%02x,0x%02x,0x%02x,0x%02x\n", + evt_buffer[0], evt_buffer[1], evt_buffer[2], evt_buffer[3]); + WMT_ERR_FUNC("WMT_SET_MCU_CLK_EVT compare fail, [4-7]:0x%02x,0x%02x,0x%02x,0x%02x\n", + evt_buffer[4], evt_buffer[5], evt_buffer[6], evt_buffer[7]); + break; + } + + fgFail = MTK_WCN_BOOL_FALSE; + + } while (0); + + if (fgFail == MTK_WCN_BOOL_FALSE) + WMT_INFO_FUNC("wmt-core:%s: ok!\n", set_mcu_clk_str[kind]); + else + WMT_INFO_FUNC("wmt-core:%s: fail!\n", set_mcu_clk_str[kind]); + + return fgFail; +} + +static INT32 wmt_core_gen3_set_mcu_clk(UINT32 kind) +{ + INT32 iRet = -1; + UINT32 u4WrittenSize = 0; + UINT32 u4ReadSize = 0; + UINT8 evt_buffer[12] = { 0 }; + MTK_WCN_BOOL fgFail; + PUINT8 set_mcu_clk_str[] = { + "SET GEN3 MCU CLK to 26M", + "SET GEN3 MCU CLK to 46M", + "SET GEN3 MCU CLK to 97M", + "SET GEN3 MCU CLK to 104M", + "SET GEN3 MCU CLK to 184M", + "SET GEN3 MCU CLK to 208M", + }; + UINT8 set_mcu_clk_vel[] = { + 0x1a, /* set 26M*/ + 0x2e, /* set 46M*/ + 0x61, /* set 97M*/ + 0x68, /* set 104M */ + 0xb8, /* set 184M */ + 0xd0, /* set 208M */ + }; + UINT8 WMT_SET_MCU_CLK_CMD[] = { 0x01, 0x0a, 0x04, 0x00, 0x09, 0x03, 0x00, 0x00 }; + UINT8 WMT_SET_MCU_CLK_EVT[] = { 0x02, 0x0a, 0x01, 0x00, 0x00 }; + + + if (kind < osal_sizeof(set_mcu_clk_vel)) { + WMT_INFO_FUNC("do %s\n", set_mcu_clk_str[kind]); + WMT_SET_MCU_CLK_CMD[6] = set_mcu_clk_vel[kind]; + } else { + WMT_ERR_FUNC("unknown kind(%d)!\n", kind); + return MTK_WCN_BOOL_TRUE; + } + + do { + fgFail = MTK_WCN_BOOL_TRUE; + + iRet = wmt_core_tx(&WMT_SET_MCU_CLK_CMD[0], osal_sizeof(WMT_SET_MCU_CLK_CMD), &u4WrittenSize, + MTK_WCN_BOOL_FALSE); + if (iRet || (u4WrittenSize != osal_sizeof(WMT_SET_MCU_CLK_CMD))) { + WMT_ERR_FUNC("WMT_SET_MCU_CLK_CMD fail(%d),size(%d)\n", iRet, u4WrittenSize); + break; + } + + iRet = wmt_core_rx(evt_buffer, osal_sizeof(WMT_SET_MCU_CLK_EVT), &u4ReadSize); + if (iRet || (u4ReadSize != osal_sizeof(WMT_SET_MCU_CLK_EVT))) { + WMT_ERR_FUNC("WMT_SET_MCU_CLK_EVT fail(%d),size(%d)\n", iRet, u4ReadSize); + mtk_wcn_stp_dbg_dump_package(); + break; + } + + if (osal_memcmp(evt_buffer, WMT_SET_MCU_CLK_EVT, osal_sizeof(WMT_SET_MCU_CLK_EVT)) != 0) { + WMT_ERR_FUNC("WMT_SET_MCU_CLK_EVT compare fail, [0-3]:0x%02x,0x%02x,0x%02x,0x%02x\n", + evt_buffer[0], evt_buffer[1], evt_buffer[2], evt_buffer[3]); + WMT_ERR_FUNC("WMT_SET_MCU_CLK_EVT compare fail, [4-7]:0x%02x,0x%02x,0x%02x,0x%02x\n", + evt_buffer[4], evt_buffer[5], evt_buffer[6], evt_buffer[7]); + break; + } + + fgFail = MTK_WCN_BOOL_FALSE; + + } while (0); + + if (fgFail == MTK_WCN_BOOL_FALSE) + WMT_INFO_FUNC("wmt-core:%s: ok!\n", set_mcu_clk_str[kind]); + else + WMT_INFO_FUNC("wmt-core:%s: fail!\n", set_mcu_clk_str[kind]); + + return fgFail; +} + +static INT32 wmt_core_set_mcu_clk(UINT32 kind) +{ + INT32 iRet = -1; + UINT32 u4WrittenSize = 0; + UINT32 u4ReadSize = 0; + UINT8 evt_buffer[12] = { 0 }; + MTK_WCN_BOOL fgFail; + + UINT8 WMT_SET_MCU_CLK_CMD[] = { 0x01, 0x0a, 0x04, 0x00, 0x09, 0x01, 0x00, 0x00 }; + UINT8 WMT_SET_MCU_CLK_EVT[] = { 0x02, 0x0a, 0x01, 0x00, 0x00 }; + + + WMT_INFO_FUNC("clock frequency 0x%x\n", kind); + WMT_SET_MCU_CLK_CMD[6] = (kind & 0xff); + + do { + fgFail = MTK_WCN_BOOL_TRUE; + + iRet = wmt_core_tx(&WMT_SET_MCU_CLK_CMD[0], osal_sizeof(WMT_SET_MCU_CLK_CMD), &u4WrittenSize, + MTK_WCN_BOOL_FALSE); + if (iRet || (u4WrittenSize != osal_sizeof(WMT_SET_MCU_CLK_CMD))) { + WMT_ERR_FUNC("WMT_SET_MCU_CLK_CMD fail(%d),size(%d)\n", iRet, u4WrittenSize); + break; + } + + iRet = wmt_core_rx(evt_buffer, osal_sizeof(WMT_SET_MCU_CLK_EVT), &u4ReadSize); + if (iRet || (u4ReadSize != osal_sizeof(WMT_SET_MCU_CLK_EVT))) { + WMT_ERR_FUNC("WMT_SET_MCU_CLK_EVT fail(%d),size(%d)\n", iRet, u4ReadSize); + mtk_wcn_stp_dbg_dump_package(); + break; + } + + if (osal_memcmp(evt_buffer, WMT_SET_MCU_CLK_EVT, osal_sizeof(WMT_SET_MCU_CLK_EVT)) != 0) { + WMT_ERR_FUNC("WMT_SET_MCU_CLK_EVT compare fail, [0-3]:0x%02x,0x%02x,0x%02x,0x%02x\n", + evt_buffer[0], evt_buffer[1], evt_buffer[2], evt_buffer[3]); + WMT_ERR_FUNC("WMT_SET_MCU_CLK_EVT compare fail, [4-7]:0x%02x,0x%02x,0x%02x,0x%02x\n", + evt_buffer[4], evt_buffer[5], evt_buffer[6], evt_buffer[7]); + break; + } + + fgFail = MTK_WCN_BOOL_FALSE; + + } while (0); + + if (fgFail == MTK_WCN_BOOL_FALSE) + WMT_INFO_FUNC("wmt-core:set mcu clock ok!\n"); + else + WMT_INFO_FUNC("wmt-core:set mcu clock fail!\n"); + + return fgFail; +} + +static INT32 opfunc_set_mcu_clk(P_WMT_OP pWmtOp) +{ + UINT32 kind = 0; + UINT32 version = 0; + MTK_WCN_BOOL ret; + + kind = pWmtOp->au4OpData[0]; + version = pWmtOp->au4OpData[1]; + + switch (version) { + case 0: + ret = wmt_core_gen2_set_mcu_clk(kind); + break; + case 1: + ret = wmt_core_gen3_set_mcu_clk(kind); + break; + case 2: + ret = wmt_core_set_mcu_clk(kind); + break; + default: + WMT_ERR_FUNC("wmt-core: version(%d) is not support!\n", version); + ret = MTK_WCN_BOOL_TRUE; + } + + return ret; +} + +static INT32 opfunc_adie_lpbk_test(P_WMT_OP pWmtOp) +{ + UINT8 *buffer = NULL; + MTK_WCN_BOOL fgFail; + UINT32 u4Res; + UINT32 aDieChipid = 0; + UINT8 soc_adie_chipid_cmd[] = { 0x01, 0x13, 0x04, 0x00, 0x02, 0x04, 0x24, 0x00 }; + UINT8 soc_adie_chipid_evt[] = { 0x02, 0x13, 0x09, 0x00, 0x00, 0x02, 0x04, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00 }; + UINT8 evtbuf[20]; + INT32 iRet = -1; + + buffer = (PUINT8) pWmtOp->au4OpData[1]; + + do { + fgFail = MTK_WCN_BOOL_TRUE; + + /* read A die chipid by wmt cmd */ + iRet = + wmt_core_tx((PUINT8) &soc_adie_chipid_cmd[0], osal_sizeof(soc_adie_chipid_cmd), &u4Res, + MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != osal_sizeof(soc_adie_chipid_cmd))) { + WMT_ERR_FUNC("wmt_core:read A die chipid CMD fail(%d),size(%d)\n", iRet, u4Res); + break; + } + osal_memset(evtbuf, 0, osal_sizeof(evtbuf)); + iRet = wmt_core_rx(evtbuf, osal_sizeof(soc_adie_chipid_evt), &u4Res); + if (iRet || (u4Res != osal_sizeof(soc_adie_chipid_evt))) { + WMT_ERR_FUNC("wmt_core:read A die chipid EVT fail(%d),size(%d)\n", iRet, u4Res); + break; + } + osal_memcpy(&aDieChipid, &evtbuf[u4Res - 2], 2); + osal_memcpy(buffer, &evtbuf[u4Res - 2], 2); + pWmtOp->au4OpData[0] = 2; + WMT_INFO_FUNC("get SOC A die chipid(0x%x)\n", aDieChipid); + + fgFail = MTK_WCN_BOOL_FALSE; + + } while (0); + + return fgFail; +} + +MTK_WCN_BOOL wmt_core_trigger_stp_assert(VOID) +{ + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + P_WMT_CTX pctx = &gMtkWmtCtx; + + if (mtk_wcn_stp_coredump_flag_get() == 0) { + WMT_INFO_FUNC("coredump is disabled, omit trigger STP assert\n"); + wmt_lib_trigger_reset(); + return MTK_WCN_BOOL_FALSE; + } + + if ((pctx->p_ic_ops != NULL) && (pctx->p_ic_ops->trigger_stp_assert != NULL)) { + WMT_INFO_FUNC("trigger stp assert function is supported by 0x%X\n", + pctx->p_ic_ops->icId); + bRet = (*(pctx->p_ic_ops->trigger_stp_assert)) (); + } else { + if (pctx->p_ic_ops != NULL) + WMT_INFO_FUNC("trigger stp assert function is not supported by 0x%X\n", + pctx->p_ic_ops->icId); + bRet = MTK_WCN_BOOL_FALSE; + } + + return bRet; +} +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT +MTK_WCN_BOOL wmt_core_deep_sleep_ctrl(INT32 value) +{ + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + P_WMT_CTX pctx = &gMtkWmtCtx; + + if ((pctx->p_ic_ops != NULL) && (pctx->p_ic_ops->deep_sleep_ctrl != NULL)) { + bRet = (*(pctx->p_ic_ops->deep_sleep_ctrl)) (value); + } else { + if (pctx->p_ic_ops != NULL) + WMT_INFO_FUNC("deep sleep function is not supported by 0x%x\n", + pctx->p_ic_ops->icId); + bRet = MTK_WCN_BOOL_FALSE; + } + return bRet; +} +#endif +INT32 opfunc_pin_state(P_WMT_OP pWmtOp) +{ + ULONG ctrlPa1 = 0; + ULONG ctrlPa2 = 0; + INT32 iRet = 0; + + iRet = wmt_core_ctrl(WMT_CTRL_HW_STATE_DUMP, &ctrlPa1, &ctrlPa2); + return iRet; +} + +#ifdef CONFIG_MTK_COMBO_ANT +INT32 opfunc_ant_ram_down(P_WMT_OP pWmtOp) +{ + INT32 iRet = 0; + size_t ctrlPa1 = pWmtOp->au4OpData[0]; + UINT32 ctrlPa2 = pWmtOp->au4OpData[1]; + PUINT8 pbuf = (PUINT8) ctrlPa1; + UINT32 fragSeq = 0; + UINT16 fragSize = 0; + UINT16 wmtCmdLen; + UINT16 wmtPktLen; + UINT32 u4Res = 0; + UINT8 antEvtBuf[osal_sizeof(WMT_ANT_RAM_DWN_EVT)]; +#if 1 + UINT32 ctrlPa3 = pWmtOp->au4OpData[2]; + + do { + fragSize = ctrlPa2; + fragSeq = ctrlPa3; + gAntBuf[5] = fragSeq; + + + wmtPktLen = fragSize + sizeof(WMT_ANT_RAM_DWN_CMD) + 1; + + /*WMT command length cal */ + wmtCmdLen = wmtPktLen - 4; +#if 0 + WMT_ANT_RAM_DWN_CMD[2] = wmtCmdLen & 0xFF; + WMT_ANT_RAM_DWN_CMD[3] = (wmtCmdLen & 0xFF00) >> 16; +#else + osal_memcpy(&WMT_ANT_RAM_DWN_CMD[2], &wmtCmdLen, 2); +#endif + + + + WMT_ANT_RAM_DWN_CMD[4] = 1; /*RAM CODE download */ + + osal_memcpy(gAntBuf, WMT_ANT_RAM_DWN_CMD, sizeof(WMT_ANT_RAM_DWN_CMD)); + + /*copy ram code content to global buffer */ + osal_memcpy(&gAntBuf[osal_sizeof(WMT_ANT_RAM_DWN_CMD) + 1], pbuf, fragSize); + + iRet = wmt_core_tx(gAntBuf, wmtPktLen, &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != wmtPktLen)) { + WMT_ERR_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) fail(%d)\n", fragSeq, + wmtPktLen, u4Res, iRet); + iRet = -4; + break; + } + WMT_DBG_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) ok\n", + fragSeq, wmtPktLen, u4Res); + + osal_memset(antEvtBuf, 0, sizeof(antEvtBuf)); + + WMT_ANT_RAM_DWN_EVT[4] = 0; /*download result; 0 */ + + iRet = wmt_core_rx(antEvtBuf, sizeof(WMT_ANT_RAM_DWN_EVT), &u4Res); + if (iRet || (u4Res != sizeof(WMT_ANT_RAM_DWN_EVT))) { + WMT_ERR_FUNC("wmt_core: read WMT_ANT_RAM_DWN_EVT length(%zu, %d) fail(%d)\n", + sizeof(WMT_ANT_RAM_DWN_EVT), u4Res, iRet); + iRet = -5; + break; + } +#if CFG_CHECK_WMT_RESULT + if (osal_memcmp(antEvtBuf, WMT_ANT_RAM_DWN_EVT, sizeof(WMT_ANT_RAM_DWN_EVT)) != 0) { + WMT_ERR_FUNC("wmt_core: compare WMT_ANT_RAM_DWN_EVT result error\n"); + WMT_ERR_FUNC("rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%zu):[%02X,%02X,%02X,%02X,%02X]\n", + u4Res, antEvtBuf[0], antEvtBuf[1], antEvtBuf[2], antEvtBuf[3], + antEvtBuf[4], sizeof(WMT_ANT_RAM_DWN_EVT), WMT_ANT_RAM_DWN_EVT[0], + WMT_ANT_RAM_DWN_EVT[1], WMT_ANT_RAM_DWN_EVT[2], WMT_ANT_RAM_DWN_EVT[3], + WMT_ANT_RAM_DWN_EVT[4]); + iRet = -6; + break; + } +#endif + WMT_DBG_FUNC("wmt_core: read WMT_ANT_RAM_DWN_EVT length(%zu, %d) ok\n", + sizeof(WMT_ANT_RAM_DWN_EVT), u4Res); + + } while (0); +#else + UINT32 patchSize = ctrlPa2; + UINT32 patchSizePerFrag = 1000; + UINT32 offset; + UINT32 fragNum = 0; + /*cal patch fragNum */ + fragNum = (patchSize + patchSizePerFrag - 1) / patchSizePerFrag; + if (fragNum <= 2) { + WMT_WARN_FUNC("ANT ramcode size(%d) too short\n", patchSize); + return -1; + } + + while (fragSeq < fragNum) { + /*update fragNum */ + fragSeq++; + + if (fragSeq == 1) { + fragSize = patchSizePerFrag; + /*first package */ + gAntBuf[5] = 1; /*RAM CODE start */ + } else if (fragNum == fragSeq) { + /*last package */ + fragSize = patchSizePerFrag; + gAntBuf[5] = 3; /*RAM CODE end */ + } else { + /*middle package */ + fragSize = patchSize - ((fragNum - 1) * patchSizePerFrag); + gAntBuf[5] = 2; /*RAM CODE confinue */ + } + wmtPktLen = fragSize + sizeof(WMT_ANT_RAM_OP_CMD) + 1; + + /*WMT command length cal */ + wmtCmdLen = wmtPktLen - 4; + + WMT_ANT_RAM_OP_CMD[2] = wmtCmdLen & 0xFF; + WMT_ANT_RAM_OP_CMD[3] = (wmtCmdLen & 0xFF00) >> 16; + + WMT_ANT_RAM_OP_CMD[4] = 1; /*RAM CODE download */ + + osal_memcpy(gAntBuf, WMT_ANT_RAM_OP_CMD, sizeof(WMT_ANT_RAM_OP_CMD)); + + /*copy ram code content to global buffer */ + osal_memcpy(&gAntBuf[6], pbuf, fragSize); + + /*update offset */ + offset += fragSize; + pbuf += offset; + + iRet = wmt_core_tx(gAntBuf, wmtPktLen, &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != wmtPktLen)) { + WMT_ERR_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) fail(%d)\n", fragSeq, + wmtPktLen, u4Res, iRet); + iRet = -4; + break; + } + WMT_DBG_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) ok\n", + fragSeq, wmtPktLen, u4Res); + + osal_memset(antEvtBuf, 0, sizeof(antEvtBuf)); + + WMT_SET_RAM_OP_EVT[4] = 0; /*download result; 0 */ + + iRet = wmt_core_rx(antEvtBuf, sizeof(WMT_SET_RAM_OP_EVT), &u4Res); + if (iRet || (u4Res != sizeof(WMT_SET_RAM_OP_EVT))) { + WMT_ERR_FUNC("wmt_core: read WMT_SET_RAM_OP_EVT length(%d, %d) fail(%d)\n", + sizeof(WMT_SET_RAM_OP_EVT), u4Res, iRet); + iRet = -5; + break; + } +#if CFG_CHECK_WMT_RESULT + if (osal_memcmp(antEvtBuf, WMT_SET_RAM_OP_EVT, sizeof(WMT_SET_RAM_OP_EVT)) != 0) { + WMT_ERR_FUNC("wmt_core: compare WMT_SET_RAM_OP_EVT result error\n"); + WMT_ERR_FUNC("rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%d):[%02X,%02X,%02X,%02X,%02X]\n", + u4Res, antEvtBuf[0], antEvtBuf[1], antEvtBuf[2], antEvtBuf[3], + antEvtBuf[4], sizeof(WMT_SET_RAM_OP_EVT), WMT_SET_RAM_OP_EVT[0], + WMT_SET_RAM_OP_EVT[1], WMT_SET_RAM_OP_EVT[2], WMT_SET_RAM_OP_EVT[3], + WMT_SET_RAM_OP_EVT[4]); + iRet = -6; + break; + } +#endif + WMT_DBG_FUNC("wmt_core: read WMT_SET_RAM_OP_EVT length(%d, %d) ok\n", + sizeof(WMT_SET_RAM_OP_EVT), u4Res); + + + } + if (fragSeq != fragNum) + iRet = -7; +#endif + return iRet; +} + + +INT32 opfunc_ant_ram_stat_get(P_WMT_OP pWmtOp) +{ + INT32 iRet = 0; + UINT32 u4Res = 0; + UINT32 wmtPktLen = osal_sizeof(WMT_ANT_RAM_STA_GET_CMD); + UINT32 u4AntRamStatus = 0; + UINT8 antEvtBuf[osal_sizeof(WMT_ANT_RAM_STA_GET_EVT)]; + + + iRet = wmt_core_tx(WMT_ANT_RAM_STA_GET_CMD, wmtPktLen, &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != wmtPktLen)) { + WMT_ERR_FUNC + ("wmt_core: write wmt and ramcode status query command failed, (%d, %d), iRet(%d)\n", + wmtPktLen, u4Res, iRet); + iRet = -4; + return iRet; + } + + + iRet = wmt_core_rx(antEvtBuf, sizeof(WMT_ANT_RAM_STA_GET_EVT), &u4Res); + if (iRet || (u4Res != sizeof(WMT_ANT_RAM_STA_GET_EVT))) { + WMT_ERR_FUNC("wmt_core: read WMT_ANT_RAM_STA_GET_EVT length(%zu, %d) fail(%d)\n", + sizeof(WMT_ANT_RAM_STA_GET_EVT), u4Res, iRet); + iRet = -5; + return iRet; + } +#if CFG_CHECK_WMT_RESULT + if (osal_memcmp(antEvtBuf, WMT_ANT_RAM_STA_GET_EVT, sizeof(WMT_ANT_RAM_STA_GET_EVT) - 1) != + 0) { + WMT_ERR_FUNC("wmt_core: compare WMT_ANT_RAM_STA_GET_EVT result error\n"); + WMT_ERR_FUNC("rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%zu):[%02X,%02X,%02X,%02X,%02X]\n", + u4Res, antEvtBuf[0], antEvtBuf[1], antEvtBuf[2], antEvtBuf[3], antEvtBuf[4], + sizeof(WMT_ANT_RAM_STA_GET_EVT), WMT_ANT_RAM_STA_GET_EVT[0], + WMT_ANT_RAM_STA_GET_EVT[1], WMT_ANT_RAM_STA_GET_EVT[2], + WMT_ANT_RAM_STA_GET_EVT[3], WMT_ANT_RAM_STA_GET_EVT[4]); + iRet = -6; + return iRet; + } +#endif + if (iRet == 0) { + u4AntRamStatus = antEvtBuf[sizeof(WMT_ANT_RAM_STA_GET_EVT) - 1]; + pWmtOp->au4OpData[2] = u4AntRamStatus; + WMT_INFO_FUNC("ANT ram code %s\n", + u4AntRamStatus == 1 ? "exist already" : "not exist"); + } + return iRet; +} +#endif +VOID wmt_core_set_coredump_state(ENUM_DRV_STS state) +{ + WMT_INFO_FUNC("wmt-core: set coredump state(%d)\n", state); + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_COREDUMP] = state; +} + +INT32 opfunc_flash_patch_down(P_WMT_OP pWmtOp) +{ + INT32 iRet = 0; + PUINT8 u4pbuf = (PUINT8)pWmtOp->au4OpData[0]; + UINT16 u4PatchSize = pWmtOp->au4OpData[1]; + UINT32 u4PatchSeq = pWmtOp->au4OpData[2]; + UINT32 u4PatchType = pWmtOp->au4OpData[3]; + UINT32 u4PatchVersion = pWmtOp->au4OpData[4]; + UINT32 u4PatchChecksum = pWmtOp->au4OpData[5]; + UINT16 wmtCmdLen; + UINT16 wmtPktLen = 0; + UINT32 u4Res = 0; + UINT8 evtBuf[osal_sizeof(WMT_FLASH_PATCH_DWN_EVT)]; + UINT32 i = 0; + + do { + osal_memcpy(gFlashBuf, WMT_FLASH_PATCH_DWN_CMD, sizeof(WMT_FLASH_PATCH_DWN_CMD)); + + switch (u4PatchSeq) { + case WMT_FLASH_PATCH_HEAD_PKT: + /*WMT command length cal */ + wmtPktLen = sizeof(WMT_FLASH_PATCH_DWN_CMD) + WMT_FLASH_PATCH_DWN_CMD[2] - 1; + osal_memcpy(&gFlashBuf[5], &u4PatchType, sizeof(u4PatchType)); + osal_memcpy(&gFlashBuf[9], &u4PatchVersion, sizeof(u4PatchVersion)); + osal_memcpy(&gFlashBuf[13], &u4PatchChecksum, sizeof(u4PatchChecksum)); + break; + case WMT_FLASH_PATCH_START_PKT: + case WMT_FLASH_PATCH_CONTINUE_PKT: + case WMT_FLASH_PATCH_END_PKT: + gFlashBuf[4] = u4PatchSeq; + /*WMT command length cal */ + wmtCmdLen = u4PatchSize + 1; + wmtPktLen = u4PatchSize + sizeof(WMT_FLASH_PATCH_DWN_CMD); + gFlashBuf[2] = wmtCmdLen & 0xFF; + gFlashBuf[3] = (wmtCmdLen & 0xFF00) >> 8; + /*copy ram code content to global buffer */ + osal_memcpy(&gFlashBuf[osal_sizeof(WMT_FLASH_PATCH_DWN_CMD)], u4pbuf, u4PatchSize); + break; + default: + break; + } + + iRet = wmt_core_tx(gFlashBuf, wmtPktLen, &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != wmtPktLen)) { + WMT_ERR_FUNC("wmt_core: write PatchSeq(%d) size(%d, %d) fail(%d)\n", u4PatchSeq, + wmtPktLen, u4Res, iRet); + iRet = -4; + u4Res = -1; + break; + } + WMT_DBG_FUNC("wmt_core: write PatchSeq(%d) size(%d, %d) ok\n", + u4PatchSeq, wmtPktLen, u4Res); + + osal_memset(evtBuf, 0, sizeof(evtBuf)); + + /* flash patch download time longer than WMT command timeout */ + for (i = 0; i < 3; i++) { + iRet = wmt_core_rx(evtBuf, sizeof(WMT_FLASH_PATCH_DWN_EVT), &u4Res); + if (!iRet) + break; + } + if (iRet || (u4Res != sizeof(WMT_FLASH_PATCH_DWN_EVT))) { + WMT_ERR_FUNC("wmt_core: read WMT_FLASH_PATCH_DWN_EVT length(%zu, %d) fail(%d)\n", + sizeof(WMT_FLASH_PATCH_DWN_EVT), u4Res, iRet); + wmt_lib_trigger_assert(WMTDRV_TYPE_WMT, 39); + + iRet = -5; + u4Res = -2; + break; + } +#if CFG_CHECK_WMT_RESULT + if (osal_memcmp(evtBuf, WMT_FLASH_PATCH_DWN_EVT, sizeof(WMT_FLASH_PATCH_DWN_EVT)) != 0) { + WMT_ERR_FUNC("wmt_core: compare WMT_FLASH_PATCH_DWN_EVT result error\n"); + WMT_ERR_FUNC("rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%zu):[%02X,%02X,%02X,%02X,%02X]\n", + u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], + sizeof(WMT_FLASH_PATCH_DWN_EVT), WMT_FLASH_PATCH_DWN_EVT[0], + WMT_FLASH_PATCH_DWN_EVT[1], WMT_FLASH_PATCH_DWN_EVT[2], + WMT_FLASH_PATCH_DWN_EVT[3], WMT_FLASH_PATCH_DWN_EVT[4]); + iRet = -6; + u4Res = -3; + break; + } +#endif + u4Res = 0; + WMT_DBG_FUNC("wmt_core: read WMT_FLASH_PATCH_DWN_EVT length(%zu, %d) ok\n", + sizeof(WMT_FLASH_PATCH_DWN_EVT), u4Res); + + } while (0); + + pWmtOp->au4OpData[6] = u4Res; + return iRet; +} + +INT32 opfunc_flash_patch_ver_get(P_WMT_OP pWmtOp) +{ + INT32 iRet = 0; + UINT32 u4Res = 0; + UINT32 wmtPktLen = osal_sizeof(WMT_FLASH_PATCH_VER_GET_CMD); + UINT32 u4PatchType = pWmtOp->au4OpData[3]; + UINT32 u4PatchVer = 0; + UINT8 evtBuf[osal_sizeof(WMT_FLASH_PATCH_VER_GET_EVT)]; + + do { + osal_memcpy(&WMT_FLASH_PATCH_VER_GET_CMD[5], &u4PatchType, sizeof(u4PatchType)); + + iRet = wmt_core_tx(WMT_FLASH_PATCH_VER_GET_CMD, wmtPktLen, &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != wmtPktLen)) { + WMT_ERR_FUNC + ("wmt_core: write wmt and flash patch query command failed, (%d, %d), iRet(%d)\n", + wmtPktLen, u4Res, iRet); + iRet = -4; + u4Res = -1; + break; + } + + iRet = wmt_core_rx(evtBuf, sizeof(WMT_FLASH_PATCH_VER_GET_EVT), &u4Res); + if (iRet || (u4Res != sizeof(WMT_FLASH_PATCH_VER_GET_EVT))) { + WMT_ERR_FUNC("wmt_core: read WMT_FLASH_PATCH_VER_GET_EVT length(%zu, %d) fail(%d)\n", + sizeof(WMT_FLASH_PATCH_VER_GET_EVT), u4Res, iRet); + wmt_lib_trigger_assert(WMTDRV_TYPE_WMT, 38); + + iRet = -5; + u4Res = -2; + break; + } +#if CFG_CHECK_WMT_RESULT + if (osal_memcmp(evtBuf, WMT_FLASH_PATCH_VER_GET_EVT, + sizeof(WMT_FLASH_PATCH_VER_GET_EVT) - 8) != 0) { + WMT_ERR_FUNC("wmt_core: compare WMT_FLASH_PATCH_VER_GET_EVT result error\n"); + WMT_ERR_FUNC("rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%zu):[%02X,%02X,%02X,%02X,%02X]\n", + u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], + sizeof(WMT_FLASH_PATCH_VER_GET_EVT), WMT_FLASH_PATCH_VER_GET_EVT[0], + WMT_FLASH_PATCH_VER_GET_EVT[1], WMT_FLASH_PATCH_VER_GET_EVT[2], + WMT_FLASH_PATCH_VER_GET_EVT[3], WMT_FLASH_PATCH_VER_GET_EVT[4]); + iRet = -6; + u4Res = -3; + break; + } +#endif + if (iRet == 0) { + osal_memcpy(&u4PatchVer, &evtBuf[9], sizeof(u4PatchVer)); + pWmtOp->au4OpData[4] = u4PatchVer; + u4Res = 0; + WMT_INFO_FUNC("flash patch type: %x, flash patch version %x\n", + u4PatchType, u4PatchVer); + } + } while (0); + + pWmtOp->au4OpData[6] = u4Res; + return iRet; +} + +#if CFG_WMT_LTE_COEX_HANDLING +static INT32 opfunc_idc_msg_handling(P_WMT_OP pWmtOp) +{ + MTK_WCN_BOOL fgFail; + UINT32 u4Res; + UINT8 host_lte_btwf_coex_cmd[] = { 0x01, 0x10, 0x00, 0x00, 0x00 }; + UINT8 host_lte_btwf_coex_evt[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + UINT8 *pTxBuf = NULL; + UINT8 evtbuf[8] = { 0 }; + INT32 iRet = -1; + UINT16 msg_len = 0; + UINT32 total_len = 0; + UINT32 index = 0; + UINT32 evtLen; + + pTxBuf = (UINT8 *) pWmtOp->au4OpData[0]; + if (pTxBuf == NULL) { + WMT_ERR_FUNC("idc msg buffer is NULL\n"); + return -1; + } + iRet = wmt_lib_idc_lock_aquire(); + if (iRet) { + WMT_ERR_FUNC("--->lock idc_lock failed, ret=%d\n", iRet); + return iRet; + } + osal_memcpy(&msg_len, &pTxBuf[0], osal_sizeof(msg_len)); + if (msg_len > WMT_IDC_MSG_MAX_SIZE) { + wmt_lib_idc_lock_release(); + WMT_ERR_FUNC("abnormal idc msg len:%d\n", msg_len); + return -2; + } + msg_len += 1; /*flag byte */ + osal_memcpy(&host_lte_btwf_coex_cmd[2], &msg_len, 2); + host_lte_btwf_coex_cmd[4] = (pWmtOp->au4OpData[1] & 0x00ff); + osal_memcpy(&msg_local_buffer[0], &host_lte_btwf_coex_cmd[0], + osal_sizeof(host_lte_btwf_coex_cmd)); + osal_memcpy(&msg_local_buffer[osal_sizeof(host_lte_btwf_coex_cmd)], + &pTxBuf[osal_sizeof(msg_len)], msg_len - 1); + wmt_lib_idc_lock_release(); + total_len = osal_sizeof(host_lte_btwf_coex_cmd) + msg_len - 1; + WMT_DBG_FUNC("wmt_core:idc msg payload len form lte(%d),wmt msg total len(%d)\n", + msg_len - 1, total_len); + WMT_DBG_FUNC("wmt_core:idc msg payload:\n"); + for (index = 0; index < total_len; index++) + WMT_DBG_FUNC("0x%02x ", msg_local_buffer[index]); + do { + fgFail = MTK_WCN_BOOL_TRUE; + + /* read A die chipid by wmt cmd */ + iRet = + wmt_core_tx((PUINT8) &msg_local_buffer[0], total_len, &u4Res, + MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != total_len)) { + WMT_ERR_FUNC("wmt_core:send lte idc msg to connsys fail(%d),size(%d)\n", + iRet, u4Res); + break; + } + osal_memset(evtbuf, 0, osal_sizeof(evtbuf)); + evtLen = osal_sizeof(host_lte_btwf_coex_evt); + iRet = wmt_core_rx(evtbuf, evtLen, &u4Res); + if (iRet || (u4Res != evtLen)) { + WMT_ERR_FUNC("wmt_core:recv host_lte_btwf_coex_evt fail(%d) len(%d, %d)\n", + iRet, u4Res, evtLen); + wmt_lib_trigger_assert(WMTDRV_TYPE_WMT, 41); + break; + } + + fgFail = MTK_WCN_BOOL_FALSE; + + } while (0); + + return fgFail; +} + +/*TEST CODE*/ +VOID wmt_core_set_flag_for_test(UINT32 enable) +{ + WMT_INFO_FUNC("%s wmt_lte_flag\n", enable ? "enable" : "disable"); + g_open_wmt_lte_flag = enable; +} + +UINT32 wmt_core_get_flag_for_test(VOID) +{ + return g_open_wmt_lte_flag; +} + +#endif + +static INT32 opfunc_utc_time_sync(P_WMT_OP pWmtOp) +{ +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + INT32 iRet; + UINT32 u4Res; + UINT32 evtLen; + UINT8 evtBuf[16] = { 0 }; + UINT32 tsec; + UINT32 tusec; + + connsys_dedicated_log_get_utc_time(&tsec, &tusec); + /* UTC time second unit */ + osal_memcpy(&WMT_UTC_SYNC_CMD[5], &tsec, 4); + /* UTC time microsecond unit */ + osal_memcpy(&WMT_UTC_SYNC_CMD[9], &tusec, 4); + + /* send command */ + iRet = wmt_core_tx(WMT_UTC_SYNC_CMD, sizeof(WMT_UTC_SYNC_CMD), + &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet) { + WMT_ERR_FUNC("Tx WMT_UTC_SYNC_CMD fail!(%d) len (%d, %zu)\n", + iRet, u4Res, sizeof(WMT_UTC_SYNC_CMD)); + return -1; + } + + /* receive event */ + evtLen = osal_sizeof(WMT_UTC_SYNC_EVT); + iRet = wmt_core_rx(evtBuf, evtLen, &u4Res); + if (iRet || (u4Res != evtLen)) { + WMT_ERR_FUNC("WMT-CORE: read WMT_UTC_SYNC_EVT fail(%d) len(%d, %d)\n", + iRet, u4Res, evtLen); + osal_assert(0); + return iRet; + } + + if (osal_memcmp(evtBuf, WMT_UTC_SYNC_EVT, + osal_sizeof(WMT_UTC_SYNC_EVT)) != 0) { + WMT_ERR_FUNC("WMT-CORE: compare WMT_UTC_SYNC_EVT error\n"); + WMT_ERR_FUNC("WMT-CORE: rx(%d):[%02X,%02X,%02X,%02X,%02X,%02X]\n", + u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], evtBuf[5]); + WMT_ERR_FUNC("WMT-CORE: exp(%zu):[%02X,%02X,%02X,%02X,%02X,%02X]\n", + osal_sizeof(WMT_UTC_SYNC_EVT), WMT_UTC_SYNC_EVT[0], + WMT_UTC_SYNC_EVT[1], WMT_UTC_SYNC_EVT[2], WMT_UTC_SYNC_EVT[3], + WMT_UTC_SYNC_EVT[4], WMT_UTC_SYNC_EVT[5]); + } else { + WMT_INFO_FUNC("Send WMT_UTC_SYNC_CMD command OK!\n"); + } + return 0; +#else + return -1; +#endif +} + +static INT32 opfunc_fw_log_ctrl(P_WMT_OP pWmtOp) +{ + INT32 iRet; + UINT32 u4Res; + UINT32 evtLen; + UINT8 evtBuf[osal_sizeof(WMT_FW_LOG_CTRL_EVT)]; + + /* fill command parameters */ + WMT_FW_LOG_CTRL_CMD[5] = (UINT8)pWmtOp->au4OpData[0]; /* type */ + WMT_FW_LOG_CTRL_CMD[6] = (UINT8)pWmtOp->au4OpData[1]; /* on/off */ + WMT_FW_LOG_CTRL_CMD[7] = (UINT8)pWmtOp->au4OpData[2]; /* log level */ + + /* send command */ + iRet = wmt_core_tx(WMT_FW_LOG_CTRL_CMD, sizeof(WMT_FW_LOG_CTRL_CMD), &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet) { + WMT_ERR_FUNC("Tx WMT_FW_LOG_CTRL_CMD fail!(%d) len (%d, %zu)\n", iRet, u4Res, + sizeof(WMT_FW_LOG_CTRL_CMD)); + return -1; + } + + /* receive event */ + evtLen = osal_sizeof(WMT_FW_LOG_CTRL_EVT); + iRet = wmt_core_rx(evtBuf, evtLen, &u4Res); + if (iRet || (u4Res != evtLen)) { + WMT_ERR_FUNC("WMT-CORE: read WMT_FW_LOG_CTRL_EVT fail(%d) len(%d, %d)\n", iRet, u4Res, evtLen); + osal_assert(0); + return iRet; + } + + if (osal_memcmp(evtBuf, WMT_FW_LOG_CTRL_EVT, evtLen) != 0) { + WMT_ERR_FUNC("WMT-CORE: compare WMT_FW_LOG_CTRL_EVT error\n"); + WMT_ERR_FUNC("WMT-CORE: tx(%zu):[%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x]\n", + osal_sizeof(WMT_FW_LOG_CTRL_CMD), WMT_FW_LOG_CTRL_CMD[0], WMT_FW_LOG_CTRL_CMD[1], + WMT_FW_LOG_CTRL_CMD[2], WMT_FW_LOG_CTRL_CMD[3], WMT_FW_LOG_CTRL_CMD[4], + WMT_FW_LOG_CTRL_CMD[5], WMT_FW_LOG_CTRL_CMD[6], WMT_FW_LOG_CTRL_CMD[7]); + WMT_ERR_FUNC("WMT-CORE: rx(%u):[%02x,%02x,%02x,%02x,%02x]\n", + u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4]); + } else { + WMT_INFO_FUNC("Send WMT_FW_LOG_CTRL_EVT command OK!\n"); + } + return 0; +} + +static INT32 opfunc_wlan_probe(P_WMT_OP pWmtOp) +{ + ULONG ctrlPa1; + ULONG ctrlPa2; + INT32 iRet; + UINT32 drvType = pWmtOp->au4OpData[0]; + + + iRet = wmt_lib_wlan_lock_aquire(); + atomic_set(&g_wifi_on_off_ready, 0); + if (iRet) { + WMT_ERR_FUNC("--->lock wlan_lock failed, iRet=%d\n", iRet); + return iRet; + } + + if (gMtkWmtCtx.eDrvStatus[drvType] == DRV_STS_FUNC_ON) { + WMT_WARN_FUNC("func(%d) already on\n", drvType); + iRet = 0; + wmt_lib_wlan_lock_release(); + goto done; + } + + if (gMtkWmtCtx.wmtHifConf.hifType == WMT_HIF_UART) { + 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); + } else { + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO1] = + DRV_STS_FUNC_ON; + } + } else if (gMtkWmtCtx.wmtHifConf.hifType == WMT_HIF_SDIO) { + if (gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO2] == DRV_STS_FUNC_ON) { + 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("turn on Wi-Fi SDIO2 but SDIO in FUNC_OFF state(0x%x)\n", + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO2]); + osal_assert(0); + iRet = -4; + wmt_lib_wlan_lock_release(); + goto done; + } + } else { + WMT_ERR_FUNC("not implemented yet 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 (iRet != 0) { + if (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; + + /* wlan_lock must release before try_pwr_off */ + wmt_lib_wlan_lock_release(); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE:type(0x%x) function on failed, ret(%d)\n", drvType, iRet); + /* FIX-ME:[Chaozhong Liang], Error handling? check subsystem state and do pwr off if necessary? */ + /* check all sub-func and do power off */ + wmt_lib_try_pwr_off(); + } + +done: + wmt_core_dump_func_state("AF FUNC ON"); + return iRet; +} + +static INT32 opfunc_wlan_remove(P_WMT_OP pWmtOp) +{ + ULONG ctrlPa1; + ULONG ctrlPa2; + INT32 iRet; + UINT32 drvType = pWmtOp->au4OpData[0]; + + iRet = wmt_lib_wlan_lock_aquire(); + atomic_set(&g_wifi_on_off_ready, 0); + if (iRet) { + WMT_ERR_FUNC("--->lock wlan_lock failed, iRet=%d\n", iRet); + return iRet; + } + + if (gMtkWmtCtx.eDrvStatus[drvType] != DRV_STS_FUNC_ON) { + WMT_WARN_FUNC("WMT-CORE: Fun(%d) DRV_STS_[0x%x] already non-FUN_ON in wmt_func_off\n", + drvType, gMtkWmtCtx.eDrvStatus[drvType]); + iRet = 0; + wmt_lib_wlan_lock_release(); + goto done; + } + + iRet = (*(gpWmtFuncOps[drvType]->func_off)) (gMtkWmtCtx.p_ic_ops, wmt_conf_get_cfg()); + + if (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); + } + /* Anyway, turn SDIO1 state to POWER_OFF state */ + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO1] = DRV_STS_POWER_OFF; + } + + 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; + */ + } + + /* wlan_lock must release before try_pwr_off */ + wmt_lib_wlan_lock_release(); + /* check all sub-func and do power off */ + wmt_lib_try_pwr_off(); + +done: + wmt_core_dump_func_state("AF FUNC OFF"); + return iRet; +} + +static INT32 opfunc_try_pwr_off(P_WMT_OP pWmtOp) +{ + INT32 iRet = 0; + UINT32 drvType = pWmtOp->au4OpData[0]; + + if (atomic_read(&g_wifi_on_off_ready) == 1) { + WMT_INFO_FUNC("wlan on/off procedure will be started, do not power off now.\n"); + return iRet; + } + + /* Why it can use try lock? + * Because only wmtd_worker_thread get wlan lock for wifi on/off in current design. + * It means it can decide whether to do Connsys power off after Wifi function on/off complete. + */ + if (wmt_lib_wlan_lock_trylock() == 0) { + WMT_INFO_FUNC("Can't lock wlan mutex which might be held by wlan on/off procedure.\n"); + return iRet; + } + + if ((gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_BT] == DRV_STS_POWER_OFF) && + (gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_GPS] == DRV_STS_POWER_OFF) && + (gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_GPSL5] == 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_ANT] == DRV_STS_POWER_OFF) && + (gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_COREDUMP] == DRV_STS_POWER_OFF)) { + WMT_INFO_FUNC("WMT-CORE:Fun(%d) [POWER_OFF] and power down chip\n", drvType); + mtk_wcn_wmt_system_state_reset(); + 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_lib_wlan_lock_release(); + return iRet; +} + +static INT32 opfunc_gps_mcu_ctrl(P_WMT_OP pWmtOp) +{ + INT32 iRet = -1; + UINT32 u4WrittenSize = 0; + UINT32 u4ReadSize = 0; + INT32 fgFail = -1; + PUINT8 p_tx_data_buf; + UINT32 tx_data_len; + PUINT8 p_rx_data_buf; + UINT32 rx_data_buf_len; + PUINT32 p_rx_data_len; + UINT8 WMT_GPS_MCU_CTRL_CMD[] = {0x01, 0x32, 0x00, 0x00}; + PUINT8 p_tx_buf = NULL; + PUINT8 p_rx_buf = NULL; + + p_tx_data_buf = (PUINT8)pWmtOp->au4OpData[0]; + tx_data_len = pWmtOp->au4OpData[1]; + p_rx_data_buf = (PUINT8)pWmtOp->au4OpData[2]; + rx_data_buf_len = pWmtOp->au4OpData[3]; + p_rx_data_len = (PINT32)(pWmtOp->au4OpData[4]); + + if ((!p_tx_data_buf) || (tx_data_len == 0) || (!p_rx_data_buf) || (rx_data_buf_len == 0)) { + pWmtOp->au4OpData[5] = -1; + WMT_ERR_FUNC("Parameter error!\n"); + return fgFail; + } + + p_tx_buf = osal_malloc(tx_data_len + osal_sizeof(WMT_GPS_MCU_CTRL_CMD)); + if (!p_tx_buf) { + pWmtOp->au4OpData[5] = -2; + WMT_ERR_FUNC("p_tx_buf alloc fail!\n"); + return fgFail; + } + + p_rx_buf = osal_malloc(rx_data_buf_len + osal_sizeof(WMT_GPS_MCU_CTRL_CMD)); + if (!p_rx_buf) { + osal_free(p_tx_buf); + pWmtOp->au4OpData[5] = -3; + WMT_ERR_FUNC("p_rx_buf alloc fail!\n"); + return fgFail; + } + + WMT_GPS_MCU_CTRL_CMD[2] = (tx_data_len & 0x000000ff); + WMT_GPS_MCU_CTRL_CMD[3] = ((tx_data_len & 0x0000ff00) >> 8); + osal_memcpy(p_tx_buf, WMT_GPS_MCU_CTRL_CMD, osal_sizeof(WMT_GPS_MCU_CTRL_CMD)); + osal_memcpy(p_tx_buf + osal_sizeof(WMT_GPS_MCU_CTRL_CMD), p_tx_data_buf, tx_data_len); + + do { + + iRet = wmt_core_tx(p_tx_buf, tx_data_len + osal_sizeof(WMT_GPS_MCU_CTRL_CMD), &u4WrittenSize, + MTK_WCN_BOOL_FALSE); + if (iRet || (u4WrittenSize != (tx_data_len + osal_sizeof(WMT_GPS_MCU_CTRL_CMD)))) { + WMT_ERR_FUNC("gps mcu ctrl tx CMD fail(%d),size(%d)\n", iRet, u4WrittenSize); + break; + } + + iRet = wmt_core_rx(p_rx_buf, rx_data_buf_len + osal_sizeof(WMT_GPS_MCU_CTRL_CMD), + &u4ReadSize); + if (iRet || (p_rx_buf[1] != WMT_GPS_MCU_CTRL_CMD[1])) { + WMT_ERR_FUNC("gps mcu ctrl rx EVT fail(%d),size(%d)\n", iRet, u4ReadSize); + break; + } + *p_rx_data_len = (p_rx_buf[2] | (p_rx_buf[3] << 8)); + osal_memcpy(p_rx_data_buf, p_rx_buf + osal_sizeof(WMT_GPS_MCU_CTRL_CMD), + *p_rx_data_len > rx_data_buf_len ? rx_data_buf_len : *p_rx_data_len); + + fgFail = 0; + } while (0); + + osal_free(p_tx_buf); + osal_free(p_rx_buf); + + return fgFail; +} + +P_WMT_GEN_CONF wmt_get_gen_conf_pointer(VOID) +{ + P_WMT_GEN_CONF pWmtGenConf = NULL; + + pWmtGenConf = wmt_conf_get_cfg(); + return pWmtGenConf; +} + +VOID wmt_core_set_blank_status(UINT32 on_off_flag) +{ + gMtkWmtCtx.wmtBlankStatus = on_off_flag; +} + +UINT32 wmt_core_get_blank_status(VOID) +{ + return gMtkWmtCtx.wmtBlankStatus; +} + +INT32 wmt_blank_status_ctrl(UINT32 on_off_flag) +{ + INT32 iRet = 0; +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + UINT32 u4Res; + UINT32 evtLen; + UINT8 evtBuf[16] = { 0 }; + + WMT_BLANK_STATUS_CMD[5] = (on_off_flag) ? 0x1 : 0x0; + + /* send command */ + iRet = wmt_core_tx((PUINT8)WMT_BLANK_STATUS_CMD, osal_sizeof(WMT_BLANK_STATUS_CMD), &u4Res, + MTK_WCN_BOOL_FALSE); + + if (iRet || (u4Res != osal_sizeof(WMT_BLANK_STATUS_CMD))) { + WMT_ERR_FUNC("WMT-CORE: WMT_BLANK_STATUS_CMD iRet(%d) cmd len err(%d, %zu)\n", + (iRet == 0 ? -1 : iRet), u4Res, osal_sizeof(WMT_BLANK_STATUS_CMD)); + return iRet; + } + + evtLen = osal_sizeof(WMT_BLANK_STATUS_EVT); + iRet = wmt_core_rx(evtBuf, evtLen, &u4Res); + if (iRet || (u4Res != evtLen)) { + WMT_ERR_FUNC("WMT-CORE: read WMT_BLANK_STATUS_EVT fail(%d) len(%d, %d)\n", + iRet, u4Res, evtLen); + WMT_INFO_FUNC("buf:[%2X,%2X,%2X,%2X,%2X] evt:[%2X,%2X,%2X,%2X,%2X]\n", + evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], + WMT_BLANK_STATUS_EVT[0], WMT_BLANK_STATUS_EVT[1], + WMT_BLANK_STATUS_EVT[2], WMT_BLANK_STATUS_EVT[3], + WMT_BLANK_STATUS_EVT[4]); + } + else + wmt_lib_set_blank_status(WMT_BLANK_STATUS_CMD[5]); +#endif + return iRet; +} + +static INT32 opfunc_blank_status_ctrl(P_WMT_OP pWmtOp) +{ + return wmt_blank_status_ctrl(pWmtOp->au4OpData[0]); +} + +static INT32 opfunc_met_ctrl(P_WMT_OP pWmtOp) +{ + INT32 iRet; + UINT32 u4Res; + UINT32 evtLen; + UINT8 evtBuf[16] = { 0 }; + UINT32 value; + UINT8 WMT_MET_CTRL_CMD[] = { 0x01, 0x31, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00}; + UINT8 WMT_MET_CTRL_EVT[] = { 0x02, 0x31, 0x01, 0x00, 0x00 }; + + value = pWmtOp->au4OpData[0]; + WMT_MET_CTRL_CMD[5] = (value & 0x000000ff); + WMT_MET_CTRL_CMD[6] = (value & 0x0000ff00) >> 8; + WMT_MET_CTRL_CMD[7] = (value & 0x00ff0000) >> 16; + WMT_MET_CTRL_CMD[8] = (value & 0xff000000) >> 24; + + /* send command */ + iRet = wmt_core_tx(WMT_MET_CTRL_CMD, sizeof(WMT_MET_CTRL_CMD), &u4Res, MTK_WCN_BOOL_FALSE); + if ((iRet) || (u4Res != sizeof(WMT_MET_CTRL_CMD))) { + WMT_ERR_FUNC("Tx MET_CTRL_CMD fail!(%d) len (%d, %zu)\n", iRet, u4Res, + sizeof(WMT_MET_CTRL_CMD)); + return -2; + } + + /* receive event */ + evtLen = sizeof(WMT_MET_CTRL_EVT); + iRet = wmt_core_rx(evtBuf, evtLen, &u4Res); + if ((iRet) || (u4Res != evtLen)) { + WMT_ERR_FUNC("Rx MET_CTRL_EVT fail!(%d) len(%d, %d)\n", iRet, u4Res, evtLen); + mtk_wcn_stp_dbg_dump_package(); + wmt_core_trigger_assert(); + return -3; + } + + return 0; +} + +static INT32 opfunc_get_consys_state(P_WMT_OP pWmtOp) +{ + INT32 ret = 0, i; + INT32 times = 0, slp_ms; + P_CONSYS_STATE_DMP_OP dmp_op = (P_CONSYS_STATE_DMP_OP)pWmtOp->au4OpData[0]; + ULONG ver = (ULONG)pWmtOp->au4OpData[1]; + + osal_lock_sleepable_lock(&dmp_op->lock); + if (dmp_op->status == WMT_DUMP_STATE_NONE + || dmp_op->version != ver) { + ret = -1; + goto done; + } + + /* WMT should be ON */ + if (gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] != DRV_STS_FUNC_ON) { + WMT_INFO_FUNC("WMT is not on"); + ret = -1; + goto done; + } + + if (mtk_wcn_consys_sleep_info_read_all_ctrl(&dmp_op->dmp_info.state) != 0) + ret = -1; + + /* Consys register should be readable */ + if (mtk_consys_check_reg_readable() == 0) { + WMT_INFO_FUNC("cr cannot readable"); + ret = -1; + goto done; + } + + times = dmp_op->times; + slp_ms = dmp_op->cpu_sleep_ms; + + /* dmp cpu_pcr */ + for (i = 0; i < times; i++) { + dmp_op->dmp_info.cpu_pcr[i] = wmt_plat_read_cpupcr(); + if (slp_ms > 0) + osal_sleep_ms(slp_ms); + } + + ret = mtk_consys_dump_osc_state(&dmp_op->dmp_info.state); + if (ret != MTK_WCN_BOOL_TRUE) + ret = -2; + + ret = mtk_wcn_consys_dump_gating_state(&dmp_op->dmp_info.state); + if (ret != MTK_WCN_BOOL_TRUE) + ret = -3; + +done: + osal_unlock_sleepable_lock(&dmp_op->lock); + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_ctrl.c b/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_ctrl.c new file mode 100644 index 0000000000000..8f94dd002bd6c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_ctrl.c @@ -0,0 +1,1197 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/******************************************************************************* +* 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" +#include "stp_dbg.h" +#include "wmt_ic.h" +#include "wmt_step.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); +static INT32 wmt_ctrl_hw_state_show(P_WMT_CTRL_DATA pWmtCtrlData); +static INT32 wmt_ctrl_get_patch_num(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_get_patch_info(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_rx_flush(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_soc_paldo_ctrl(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_soc_wakeup_consys(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_set_stp_dbg_info(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_bgw_desense_ctrl(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_trg_assert(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_evt_parser(P_WMT_CTRL_DATA pWmtCtrlData); +#if CFG_WMT_LTE_COEX_HANDLING +static INT32 wmt_ctrl_get_tdm_req_antsel(P_WMT_CTRL_DATA); +#endif + +static INT32 wmt_ctrl_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); + +static INT32 wmt_ctrl_get_rom_patch_info(P_WMT_CTRL_DATA pWmtCtrlData); + +static INT32 wmt_ctrl_update_patch_version(P_WMT_CTRL_DATA); + +/* TODO: [FixMe][GeorgeKuo]: remove unused function */ +/*static INT32 wmt_ctrl_hwver_get(P_WMT_CTRL_DATA);*/ + + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/* GeorgeKuo: Use designated initializers described in + * http://gcc.gnu.org/onlinedocs/gcc-4.0.4/gcc/Designated-Inits.html + */ +static const WMT_CTRL_FUNC wmt_ctrl_func[] = { + [WMT_CTRL_HW_PWR_OFF] = wmt_ctrl_hw_pwr_off, + [WMT_CTRL_HW_PWR_ON] = wmt_ctrl_hw_pwr_on, + [WMT_CTRL_HW_RST] = wmt_ctrl_hw_rst, + [WMT_CTRL_STP_CLOSE] = wmt_ctrl_stp_close, + [WMT_CTRL_STP_OPEN] = wmt_ctrl_stp_open, + [WMT_CTRL_STP_CONF] = wmt_ctrl_stp_conf, + [WMT_CTRL_FREE_PATCH] = wmt_ctrl_free_patch, + [WMT_CTRL_GET_PATCH] = wmt_ctrl_get_patch, + [WMT_CTRL_GET_PATCH_NAME] = wmt_ctrl_get_patch_name, + [WMT_CTRL_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_SOC_PALDO_CTRL] = wmt_ctrl_soc_paldo_ctrl, + [WMT_CTRL_SOC_WAKEUP_CONSYS] = wmt_ctrl_soc_wakeup_consys, + [WMT_CTRL_SET_STP_DBG_INFO] = wmt_ctrl_set_stp_dbg_info, + [WMT_CTRL_BGW_DESENSE_CTRL] = wmt_ctrl_bgw_desense_ctrl, + [WMT_CTRL_TRG_ASSERT] = wmt_ctrl_trg_assert, + #if CFG_WMT_LTE_COEX_HANDLING + [WMT_CTRL_GET_TDM_REQ_ANTSEL] = wmt_ctrl_get_tdm_req_antsel, +#endif + [WMT_CTRL_EVT_PARSER] = wmt_ctrl_evt_parser, + [WMT_CTRL_GET_ROM_PATCH_INFO] = wmt_ctrl_get_rom_patch_info, + [WMT_CTRL_UPDATE_PATCH_VERSION] = wmt_ctrl_update_patch_version, + [WMT_CTRL_MAX] = wmt_ctrl_others, +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +INT32 __weak mtk_wcn_consys_stp_btif_parser_wmt_evt(const PUINT8 str, UINT32 len) +{ + return 0; +} + +INT32 wmt_ctrl(P_WMT_CTRL_DATA pWmtCtrlData) +{ + UINT32 ctrlId = 0; + + if (pWmtCtrlData == NULL) { + osal_assert(0); + return -1; + } + + ctrlId = pWmtCtrlData->ctrlId; + /*1sanity check, including wmtCtrlId */ + if ((pWmtCtrlData == NULL) + || (ctrlId >= WMT_CTRL_MAX)) + /* || (ctrlId < WMT_CTRL_HW_PWR_OFF) ) [FixMe][GeorgeKuo]: useless comparison */ + { + osal_assert(pWmtCtrlData != NULL); + osal_assert(ctrlId < WMT_CTRL_MAX); + /* osal_assert(ctrlId >= WMT_CTRL_HW_PWR_OFF); [FixMe][GeorgeKuo]: useless comparison */ + return -2; + } + /* TODO: [FixMe][GeorgeKuo] do sanity check to const function table when init and skip checking here */ + if (wmt_ctrl_func[ctrlId]) { + /*call servicd handling API */ + return (*(wmt_ctrl_func[ctrlId])) (pWmtCtrlData); /* serviceHandlerPack[ctrlId].serviceHandler */ + } + osal_assert(wmt_ctrl_func[ctrlId] != NULL); + return -3; +} + +INT32 wmt_ctrl_tx(P_WMT_CTRL_DATA pWmtCtrlData /*UINT8 *pData, UINT32 size, UINT32 *writtenSize */) +{ + PUINT8 pData = (PUINT8) pWmtCtrlData->au4CtrlData[0]; + UINT32 size = pWmtCtrlData->au4CtrlData[1]; + PUINT32 writtenSize = (PUINT32) pWmtCtrlData->au4CtrlData[2]; + MTK_WCN_BOOL bRawFlag = pWmtCtrlData->au4CtrlData[3]; + + return wmt_ctrl_tx_ex(pData, size, writtenSize, bRawFlag); +} + +static VOID wmt_ctrl_show_sched_stats_log(P_OSAL_THREAD pThread, P_OSAL_THREAD_SCHEDSTATS pSchedstats) +{ + if ((pThread) && (pThread->pThread) && (pSchedstats)) + WMT_ERR_FUNC("WMT rx_timeout, pid[%d/%s] stats duration:%llums, sched(x%llu/r%llu/i%llu)\n", + pThread->pThread->pid, + pThread->threadName, + pSchedstats->time, + pSchedstats->exec, + pSchedstats->runnable, + pSchedstats->iowait); +} + +INT32 wmt_ctrl_rx(P_WMT_CTRL_DATA pWmtCtrlData /*UINT8 *pBuff, UINT32 buffLen, UINT32 *readSize */) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + INT32 readLen; + INT32 waitRet = -1; + INT32 loopCnt = 1; + INT32 leftCnt; + PUINT8 pBuff = (PUINT8) pWmtCtrlData->au4CtrlData[0]; + UINT32 buffLen = pWmtCtrlData->au4CtrlData[1]; + PUINT32 readSize = (PUINT32) pWmtCtrlData->au4CtrlData[2]; + INT32 stpRxState; + INT32 extended = 0; + P_OSAL_THREAD p_rx_thread = NULL; + OSAL_THREAD_SCHEDSTATS schedstats; + + if (readSize) + *readSize = 0; + + /* sanity check */ + if (!buffLen) { + WMT_WARN_FUNC("buffLen = 0\n"); + osal_assert(buffLen); + return 0; + } + + if (!osal_test_bit(WMT_STAT_STP_OPEN, &pDev->state)) { + WMT_WARN_FUNC("state(0x%lx)\n", pDev->state.data); + osal_assert(osal_test_bit(WMT_STAT_STP_OPEN, &pDev->state)); + return -2; + } + if (wmt_lib_get_drv_status(WMTDRV_TYPE_WMT) == DRV_STS_FUNC_ON) + loopCnt = 4; + leftCnt = loopCnt; + + /* sanity ok, proceeding rx operation */ + readLen = mtk_wcn_stp_receive_data(pBuff, buffLen, WMT_TASK_INDX); + p_rx_thread = mtk_stp_rx_thread_get(); + osal_thread_sched_mark(p_rx_thread, &schedstats); + + while (readLen == 0 && leftCnt > 0) { /* got nothing, wait for STP's signal */ + /* if assert happen, do not wait for any signal again */ + if (mtk_wcn_stp_get_wmt_trg_assert() == 1 + && mtk_wcn_stp_is_wmt_last_close() == 0) + break; + pDev->rWmtRxWq.timeoutValue = WMT_LIB_RX_TIMEOUT/loopCnt; + waitRet = wmt_dev_rx_timeout(&pDev->rWmtRxWq); + if (waitRet == 0) { + leftCnt--; + /* dump btif_rxd's backtrace to check whether it is blocked or not */ + osal_dump_thread_state("btif_rxd"); + stp_dbg_poll_cpupcr(5, 1, 1); + if (!mtk_wcn_stp_is_sdio_mode()) + mtk_wcn_consys_stp_btif_logger_ctrl(BTIF_DUMP_BTIF_IRQ); + + if (leftCnt <= 0) { + if (extended == 0) { + stpRxState = mtk_stp_check_rx_has_pending_data(); + WMT_INFO_FUNC("check rx pending data(%d)\n", stpRxState); + readLen = mtk_wcn_stp_receive_data(pBuff, buffLen, WMT_TASK_INDX); + if (readLen > 0) { + WMT_INFO_FUNC("rx data received, rx done.\n"); + break; + } else if (stpRxState > 0) { + osal_thread_sched_unmark(p_rx_thread, &schedstats); + wmt_ctrl_show_sched_stats_log(p_rx_thread, &schedstats); + WMT_INFO_FUNC("stp has pending data, extend ~4 seconds\n"); + leftCnt = WMT_LIB_RX_EXTEND_TIMEOUT/pDev->rWmtRxWq.timeoutValue; + extended = 1; + osal_thread_sched_mark(p_rx_thread, &schedstats); + continue; + } + /* wmt is closed, device is shuting down */ + if (wmt_dev_is_close() || mtk_wcn_stp_is_wmt_last_close() == 1) { + leftCnt = 10; + continue; + } + } + + osal_thread_sched_unmark(p_rx_thread, &schedstats); + wmt_ctrl_show_sched_stats_log(p_rx_thread, &schedstats); + stp_dbg_poll_cpupcr(5, 1, 1); + WMT_ERR_FUNC("wmt_dev_rx_timeout: timeout,jiffies(%lu),timeoutvalue(%d)\n", + jiffies, pDev->rWmtRxWq.timeoutValue); + WMT_STEP_COMMAND_TIMEOUT_DO_ACTIONS_FUNC("STP RX timeout"); + + /* Reason number 44 means that stp data path still has data, + * possibly a driver problem + */ + if (stpRxState != 0) + wmt_lib_trigger_assert(WMTDRV_TYPE_WMT, 44); + return -1; + } + } else if (waitRet < 0) { + WMT_WARN_FUNC("wmt_dev_rx_timeout: interrupted by signal (%d)\n", waitRet); + WMT_STEP_COMMAND_TIMEOUT_DO_ACTIONS_FUNC("STP RX timeout"); + return waitRet; + } + readLen = mtk_wcn_stp_receive_data(pBuff, buffLen, WMT_TASK_INDX); + + if (readLen == 0) + WMT_DBG_FUNC("wmt_ctrl_rx be signaled, but no rx data(%d)\n", waitRet); + WMT_DBG_FUNC("stp_receive_data: readLen(%d)\n", readLen); + } + + if (readSize) + *readSize = readLen; + + return 0; +} + + +INT32 +wmt_ctrl_tx_ex(const PUINT8 pData, + const UINT32 size, PUINT32 writtenSize, const MTK_WCN_BOOL bRawFlag) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + INT32 iRet; + + if (writtenSize != NULL) + *writtenSize = 0; + + /* sanity check */ + if (size == 0) { + 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.data); + osal_assert(osal_test_bit(WMT_STAT_STP_EN, &pDev->state)); + osal_assert(osal_test_bit(WMT_STAT_STP_OPEN, &pDev->state)); + iRet = -2; + if (writtenSize) + *writtenSize = iRet; + return iRet; + } + + /* 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 PUINT8 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 = 6000; + 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, NULL); + WMT_LOUD_FUNC("wait signal iRet:%d\n", waitRet); + if (waitRet == 0) { + WMT_ERR_FUNC("wait signal timeout\n"); + return -2; + } + + WMT_DBG_FUNC("str(%s) result(%d)\n", pCmdStr, pWmtDev->cmdResult); + + return pWmtDev->cmdResult; +} + +INT32 wmt_ctrl_hw_rst(P_WMT_CTRL_DATA pWmtCtrlData) +{ + wmt_plat_pwr_ctrl(FUNC_RST); + return 0; +} + +INT32 wmt_ctrl_hw_state_show(P_WMT_CTRL_DATA pWmtCtrlData) +{ + wmt_plat_pwr_ctrl(FUNC_STAT); + return 0; +} + +INT32 wmt_ctrl_stp_close(P_WMT_CTRL_DATA pWmtCtrlData) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + INT32 iRet = 0; + UINT8 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 (pDev->rWmtHifConf.hifType == WMT_HIF_UART) { + + 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; + } + } + if (pDev->rWmtHifConf.hifType == WMT_HIF_BTIF) { + /*un-register rxcb to btif */ + iRet = mtk_wcn_stp_rxcb_register(NULL); + if (iRet) { + WMT_WARN_FUNC("mtk_wcn_stp_rxcb_unregister fail(%d)\n", iRet); + return -2; + } + + iRet = mtk_wcn_stp_close_btif(); + if (iRet) { + WMT_WARN_FUNC("mtk_wcn_stp_close_btif fail(%d)\n", iRet); + return -3; + } + } + + osal_clear_bit(WMT_STAT_STP_OPEN, &pDev->state); + + return 0; +} + +INT32 wmt_ctrl_stp_open(P_WMT_CTRL_DATA pWmtCtrlData) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + INT32 iRet; + UINT8 cmdStr[NAME_MAX + 1] = { 0 }; + + if (pDev->rWmtHifConf.hifType == WMT_HIF_UART) { + 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; + } + } + if (pDev->rWmtHifConf.hifType == WMT_HIF_BTIF) { + iRet = mtk_wcn_stp_open_btif(); + if (iRet) { + WMT_WARN_FUNC("mtk_wcn_stp_open_btif fail(%d)\n", iRet); + return -1; + } + + /*register stp rx call back to btif */ + iRet = mtk_wcn_stp_rxcb_register((MTK_WCN_BTIF_RX_CB)mtk_wcn_stp_parser_data); + if (iRet) { + WMT_WARN_FUNC("mtk_wcn_stp_rxcb_register fail(%d)\n", iRet); + return -2; + } + } + /* register to STP-core for rx */ + /* mtk_wcn_stp_register_event_cb */ + iRet = mtk_wcn_stp_register_event_cb(WMT_TASK_INDX, wmt_dev_rx_event_cb); + if (iRet) { + WMT_WARN_FUNC("stp_reg cb fail(%d)\n", iRet); + return -2; + } + + osal_set_bit(WMT_STAT_STP_OPEN, &pDev->state); +#if 0 + iRet = mtk_wcn_stp_lpbk_ctrl(1); +#endif + + return 0; +} + + +INT32 wmt_ctrl_patch_search(P_WMT_CTRL_DATA pWmtCtrlData) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + INT32 iRet; + UINT8 cmdStr[NAME_MAX + 1] = { 0 }; + + osal_snprintf(cmdStr, NAME_MAX, "srh_patch"); + iRet = wmt_ctrl_ul_cmd(pDev, cmdStr); + if (iRet) { + WMT_WARN_FUNC("wmt_ctrl_ul_cmd fail(%d)\n", iRet); + return -1; + } + return 0; +} + + +INT32 wmt_ctrl_get_patch_num(P_WMT_CTRL_DATA pWmtCtrlData) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + + pWmtCtrlData->au4CtrlData[0] = pDev->patchNum; + return 0; +} + + +INT32 wmt_ctrl_get_patch_info(P_WMT_CTRL_DATA pWmtCtrlData) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + UINT32 downLoadSeq = 0; + P_WMT_PATCH_INFO pPatchinfo = NULL; + PUINT8 pNbuf = NULL; + PUINT8 pAbuf = NULL; + + if (pDev->pWmtPatchInfo == NULL) { + WMT_ERR_FUNC("pWmtPatchInfo is NULL\n"); + return -1; + } + + downLoadSeq = pWmtCtrlData->au4CtrlData[0]; + WMT_DBG_FUNC("download seq is %d\n", downLoadSeq); + + pPatchinfo = pDev->pWmtPatchInfo + downLoadSeq - 1; + pNbuf = (PUINT8) pWmtCtrlData->au4CtrlData[1]; + pAbuf = (PUINT8) pWmtCtrlData->au4CtrlData[2]; + if (pPatchinfo) { + osal_memcpy(pNbuf, pPatchinfo->patchName, osal_sizeof(pPatchinfo->patchName)); + osal_memcpy(pAbuf, pPatchinfo->addRess, osal_sizeof(pPatchinfo->addRess)); + WMT_DBG_FUNC("get 4 address bytes is 0x%2x,0x%2x,0x%2x,0x%2x", pAbuf[0], pAbuf[1], + pAbuf[2], pAbuf[3]); + } else + WMT_ERR_FUNC("NULL patchinfo pointer\n"); + + return 0; +} + +INT32 wmt_ctrl_get_rom_patch_info(P_WMT_CTRL_DATA pWmtCtrlData) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + UINT32 type = 0; + struct wmt_rom_patch_info *pPatchinfo = NULL; + PUINT8 pNbuf = NULL; + PUINT8 pAbuf = NULL; + INT32 ret = 0; + UINT8 cmdStr[NAME_MAX + 1] = { 0 }; + + type = pWmtCtrlData->au4CtrlData[0]; + WMT_DBG_FUNC("rom patch type is %d\n", type); + pDev->ip_ver = pWmtCtrlData->au4CtrlData[3]; + pDev->fw_ver = pWmtCtrlData->au4CtrlData[4]; + WMT_DBG_FUNC("ip version is [%x] [%x]\n", pDev->ip_ver, pDev->fw_ver); + + if (!pDev->pWmtRomPatchInfo[WMTDRV_TYPE_WMT]) { + osal_snprintf(cmdStr, NAME_MAX, "srh_rom_patch"); + ret = wmt_ctrl_ul_cmd(pDev, cmdStr); + if (ret) { + WMT_WARN_FUNC("wmt_ctrl_ul_cmd fail(%d)\n", ret); + return -1; + } + } + + if (type < WMTDRV_TYPE_ANT) { + pPatchinfo = pDev->pWmtRomPatchInfo[type]; + pNbuf = (PUINT8) pWmtCtrlData->au4CtrlData[1]; + pAbuf = (PUINT8) pWmtCtrlData->au4CtrlData[2]; + if (pPatchinfo) { + osal_memcpy(pNbuf, pPatchinfo->patchName, osal_sizeof(pPatchinfo->patchName)); + osal_memcpy(pAbuf, pPatchinfo->addRess, osal_sizeof(pPatchinfo->addRess)); + WMT_DBG_FUNC("get 4 address bytes is 0x%2x,0x%2x,0x%2x,0x%2x", + pAbuf[0], pAbuf[1], pAbuf[2], pAbuf[3]); + } else { + WMT_ERR_FUNC("NULL patchinfo pointer\n"); + ret = 1; + } + } else { + WMT_ERR_FUNC("rom patch type %d is error!\n", type); + ret = -1; + } + + return ret; +} + +INT32 wmt_ctrl_update_patch_version(P_WMT_CTRL_DATA pWmtCtrlData) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + INT32 iRet; + UINT8 cmdStr[NAME_MAX + 1] = { 0 }; + + osal_snprintf(cmdStr, NAME_MAX, "update_patch_version"); + 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_soc_paldo_ctrl(P_WMT_CTRL_DATA pWmtCtrlData) +{ + INT32 iRet = 0; + ENUM_PALDO_TYPE ept = pWmtCtrlData->au4CtrlData[0]; + ENUM_PALDO_OP epo = pWmtCtrlData->au4CtrlData[1]; + + WMT_DBG_FUNC("ept(%d),epo(%d)\n", ept, epo); + iRet = wmt_plat_soc_paldo_ctrl(ept, epo); + if (iRet) { + if (ept == PMIC_CHIPID_PALDO) { + /* special handling for PMIC CHIPID */ + pWmtCtrlData->au4CtrlData[2] = iRet; + } else { + /* for other PA handling */ + WMT_ERR_FUNC("soc palod ctrl fail(%d)\n", iRet); + } + } + + return iRet; +} + +INT32 wmt_ctrl_soc_wakeup_consys(P_WMT_CTRL_DATA pWmtCtrlData) +{ + INT32 iRet = 0; + + iRet = mtk_wcn_stp_wakeup_consys(); + if (iRet) + WMT_ERR_FUNC("soc palod ctrl fail(%d)\n", iRet); + + return iRet; +} + +static INT32 wmt_ctrl_bgw_desense_ctrl(P_WMT_CTRL_DATA pWmtCtrlData) +{ + UINT32 cmd = pWmtCtrlData->au4CtrlData[0]; + + WMT_INFO_FUNC("wmt-ctrl:send native cmd(%d)\n", cmd); + wmt_dev_send_cmd_to_daemon(cmd); + + return 0; +} + +#if CFG_WMT_LTE_COEX_HANDLING +static INT32 wmt_ctrl_get_tdm_req_antsel(P_WMT_CTRL_DATA pWmtCtrlData) +{ + INT32 antsel_index = wmt_plat_get_tdm_antsel_index(); + + if (antsel_index >= 0) + pWmtCtrlData->au4CtrlData[0] = antsel_index; + else + pWmtCtrlData->au4CtrlData[0] = 0xff; + + WMT_INFO_FUNC("get tdm req antsel index is %d\n", antsel_index); + + return 0; +} +#endif + +static INT32 wmt_ctrl_evt_parser(P_WMT_CTRL_DATA pWmtCtrlData) +{ + INT32 ret = -1; + UINT32 evt_idx = (UINT32) pWmtCtrlData->au4CtrlData[0]; + UINT8 *p_buf = NULL; + + static UINT8 sleep_evt[] = { 0x02, 0x03, 0x02, 0x00, 0x00, 0x01 }; + static UINT8 wakeup_evt[] = { 0x02, 0x03, 0x02, 0x00, 0x00, 0x03 }; + static UINT8 hostawake_evt[] = { 0x02, 0x03, 0x02, 0x00, 0x00, 0x02 }; + static UINT8 *evt_array[] = { sleep_evt, wakeup_evt, hostawake_evt }; + + p_buf = evt_array[evt_idx - 1]; + + WMT_INFO_FUNC("evt index:%d,p_buf:%p\n", evt_idx, p_buf); + + ret = mtk_wcn_consys_stp_btif_parser_wmt_evt(p_buf, 6); + if (ret == 1) { + WMT_INFO_FUNC("parser wmt evt from BTIF buf is OK\n"); + return 0; + } + WMT_ERR_FUNC("parser wmt evt from BTIF buf fail(%d)\n", ret); + return -1; +} + +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 (type == WMT_STP_CONF_EN) { + 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"); + } + } + if (type == WMT_STP_CONF_RDY) { + if (value) { + osal_set_bit(WMT_STAT_STP_RDY, &pDev->state); + WMT_DBG_FUNC("STP ready\n"); + } else { + osal_clear_bit(WMT_STAT_STP_RDY, &pDev->state); + WMT_DBG_FUNC("STP not ready\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(%p)\n", gDevWmt.pPatch); + if (gDevWmt.pPatch != NULL) + wmt_dev_patch_put((osal_firmware **) &(gDevWmt.pPatch)); + WMT_DBG_FUNC("AF free patch, gDevWmt.pPatch(%p)\n", gDevWmt.pPatch); + if (patchSeq == gDevWmt.patchNum) + WMT_DBG_FUNC("the %d patch has been download\n", patchSeq); + return 0; +} + +INT32 wmt_ctrl_get_patch_name(P_WMT_CTRL_DATA pWmtCtrlData) +{ + PUINT8 pBuf = (PUINT8) pWmtCtrlData->au4CtrlData[0]; + + osal_memcpy(pBuf, gDevWmt.cPatchName, osal_sizeof(gDevWmt.cPatchName)); + return 0; +} + +INT32 wmt_ctrl_crystal_triming_put(P_WMT_CTRL_DATA pWmtCtrlData) +{ + WMT_DBG_FUNC("BF free patch, gDevWmt.pPatch(%p)\n", gDevWmt.pPatch); + if (gDevWmt.pNvram != NULL) + wmt_dev_patch_put((osal_firmware **) &(gDevWmt.pNvram)); + WMT_DBG_FUNC("AF free patch, gDevWmt.pNvram(%p)\n", gDevWmt.pNvram); + return 0; +} + + +INT32 wmt_ctrl_crystal_triming_get(P_WMT_CTRL_DATA pWmtCtrlData) +{ + INT32 iRet = 0x0; + PUINT8 pFileName = (PUINT8) pWmtCtrlData->au4CtrlData[0]; + PPUINT8 ppBuf = (PPUINT8) pWmtCtrlData->au4CtrlData[1]; + PUINT32 pSize = (PUINT32) pWmtCtrlData->au4CtrlData[2]; + osal_firmware *pNvram = NULL; + + if ((pFileName == NULL) || (pSize == NULL)) { + WMT_ERR_FUNC("parameter error, pFileName(%p), pSize(%p)\n", pFileName, pSize); + iRet = -1; + return iRet; + } + if (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) +{ + PUINT8 pFullPatchName = NULL; + PUINT8 pDefPatchName = NULL; + PPUINT8 ppBuf = (PPUINT8) pWmtCtrlData->au4CtrlData[2]; + PUINT32 pSize = (PUINT32) pWmtCtrlData->au4CtrlData[3]; + osal_firmware *pPatch = NULL; + + pFullPatchName = (PUINT8) pWmtCtrlData->au4CtrlData[1]; + WMT_DBG_FUNC("BF get patch, pPatch(%p)\n", pPatch); + if ((pFullPatchName != NULL) + && (wmt_dev_patch_get(pFullPatchName, &pPatch) == 0)) { + /*get full name patch success */ + WMT_DBG_FUNC("get full patch name(%s) buf(0x%p) size(%zu)\n", + pFullPatchName, (pPatch)->data, (pPatch)->size); + WMT_DBG_FUNC("AF get patch, pPatch(%p)\n", pPatch); + *ppBuf = (PUINT8)(pPatch)->data; + *pSize = (pPatch)->size; + gDevWmt.pPatch = pPatch; + return 0; + } + + pDefPatchName = (PUINT8) pWmtCtrlData->au4CtrlData[0]; + if ((pDefPatchName != NULL) + && (wmt_dev_patch_get(pDefPatchName, &pPatch) == 0)) { + WMT_DBG_FUNC("get def patch name(%s) buf(0x%p) size(%zu)\n", + pDefPatchName, (pPatch)->data, (pPatch)->size); + WMT_DBG_FUNC("AF get patch, pPatch(%p)\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; + INT8 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(%zu) 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 ((sdioSlotNum == WMT_SDIO_SLOT_INVALID) + || (sdioSlotNum >= WMT_SDIO_SLOT_MAX)) { + 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 (sdioSlotNum == WMT_SDIO_SLOT_SDIO2) + 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 (sdioFuncType >= WMT_SDIO_FUNC_MAX) { + WMT_ERR_FUNC("CTRL_SDIO_FUNC, invalid func type (%d)\n", sdioFuncType); + return -1; + } + + if (sdioFuncType == WMT_SDIO_FUNC_STP) + statBit = WMT_STAT_SDIO_STP_ON; + + if (u4On) { + if (osal_test_bit(statBit, &pDev->state)) { + WMT_WARN_FUNC("CTRL_SDIO_FUNC(%d) but already ON\n", sdioFuncType); + iRet = 0; + } else { + while (retry-- > 0 && iRet != 0) { + if (iRet) { + /* sleep 150ms before sdio slot ON ready */ + osal_sleep_ms(150); + } + iRet = + mtk_wcn_hif_sdio_wmt_control(sdioFuncType, MTK_WCN_BOOL_TRUE); + if (iRet == HIF_SDIO_ERR_NOT_PROBED) { + /* not probed case, retry */ + continue; + } else if (iRet == HIF_SDIO_ERR_CLT_NOT_REG) { + /* 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 (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; + + return 0; +} + +static INT32 wmt_ctrl_gps_sync_set(P_WMT_CTRL_DATA pData) +{ + INT32 iret; + + WMT_DBG_FUNC("ctrl GPS_SYNC(%d)\n", + (pData->au4CtrlData[0] == 0) ? PIN_STA_DEINIT : PIN_STA_MUX); + iret = + wmt_plat_gpio_ctrl(PIN_GPS_SYNC, + (pData->au4CtrlData[0] == 0) ? PIN_STA_DEINIT : PIN_STA_MUX); + + if (iret) + WMT_WARN_FUNC("ctrl GPS_SYNC(%d) fail!(%d) ignore it...\n", + (pData->au4CtrlData[0] == 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_DBG_FUNC("ctrl GPS_LNA(%d)\n", + (pData->au4CtrlData[0] == 0) ? PIN_STA_DEINIT : PIN_STA_OUT_H); + iret = + wmt_plat_gpio_ctrl(PIN_GPS_LNA, + (pData->au4CtrlData[0] == 0) ? PIN_STA_DEINIT : PIN_STA_OUT_H); + + if (iret) + WMT_WARN_FUNC("ctrl GPS_SYNC(%d) fail!(%d) ignore it...\n", + (pData->au4CtrlData[0] == 0) ? PIN_STA_DEINIT : PIN_STA_OUT_H, iret); + + return 0; +} + + +INT32 wmt_ctrl_stp_rst(P_WMT_CTRL_DATA pWmtCtrlData) +{ + return 0; +} + +INT32 wmt_ctrl_get_wmt_conf(P_WMT_CTRL_DATA pWmtCtrlData) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + + pWmtCtrlData->au4CtrlData[0] = (size_t) &pDev->rWmtGenConf; + + return 0; +} + +INT32 wmt_ctrl_others(P_WMT_CTRL_DATA pWmtCtrlData) +{ + WMT_ERR_FUNC("wmt_ctrl_others, invalid CTRL ID (%d)\n", pWmtCtrlData->ctrlId); + return -1; +} + + +INT32 wmt_ctrl_set_stp_dbg_info(P_WMT_CTRL_DATA pWmtCtrlData) +{ + PUINT8 pRomVer = NULL; + P_WMT_PATCH pPatch = NULL; + UINT32 chipID = 0; + + chipID = pWmtCtrlData->au4CtrlData[0]; + pRomVer = (PUINT8) (pWmtCtrlData->au4CtrlData[1]); + pPatch = (P_WMT_PATCH)(pWmtCtrlData->au4CtrlData[2]); + if (!pRomVer) { + WMT_ERR_FUNC("pRomVer null pointer\n"); + return -1; + } + + if (!pPatch) { + WMT_ERR_FUNC("pPatch null pointer\n"); + return -2; + } + WMT_DBG_FUNC("chipid(0x%x),rom(%s),patch date(%s),patch plat(%s)\n", chipID, pRomVer, + pPatch->ucDateTime, pPatch->ucPLat); + return stp_dbg_set_version_info(chipID, pRomVer, &(pPatch->ucDateTime[0]), + &(pPatch->ucPLat[0])); +} + +static INT32 wmt_ctrl_trg_assert(P_WMT_CTRL_DATA pWmtCtrlData) +{ + INT32 iRet = -1; + + ENUM_WMTDRV_TYPE_T drv_type; + UINT32 reason = 0; + PUINT8 keyword; + + drv_type = pWmtCtrlData->au4CtrlData[0]; + reason = pWmtCtrlData->au4CtrlData[1]; + keyword = (PUINT8) pWmtCtrlData->au4CtrlData[2]; + WMT_INFO_FUNC("wmt-ctrl:drv_type(%d),reason(%d),keyword(%s)\n", drv_type, reason, keyword); + + if (wmt_dev_is_close()) + WMT_INFO_FUNC("WMT is closing, don't trigger assert\n"); + else if (chip_reset_only == 1) + WMT_INFO_FUNC("Do chip reset only, don't trigger assert\n"); + else if (mtk_wcn_stp_get_wmt_trg_assert() == 0) { + mtk_wcn_stp_dbg_dump_package(); + mtk_wcn_stp_set_wmt_trg_assert(1); + mtk_wcn_stp_assert_flow_ctrl(1); + + iRet = mtk_wcn_stp_wmt_trg_assert(); + if (iRet == 0) { + wmt_lib_set_host_assert_info(drv_type, reason, 1); + stp_dbg_set_keyword(keyword); + } + } else + WMT_INFO_FUNC("do trigger assert & chip reset in stp noack\n"); + + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_exp.c b/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_exp.c new file mode 100644 index 0000000000000..0cc26da0c2cfd --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_exp.c @@ -0,0 +1,876 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + + +/******************************************************************************* +* 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_step.h" + +#include +#include +#include +#include +#include +#include +#include + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +wmt_wlan_probe_cb mtk_wcn_wlan_probe; +wmt_wlan_remove_cb mtk_wcn_wlan_remove; +wmt_wlan_bus_cnt_get_cb mtk_wcn_wlan_bus_tx_cnt; +wmt_wlan_bus_cnt_clr_cb mtk_wcn_wlan_bus_tx_cnt_clr; +wmt_wlan_emi_mpu_set_protection_cb mtk_wcn_wlan_emi_mpu_set_protection; +wmt_wlan_is_wifi_drv_own_cb mtk_wcn_wlan_is_wifi_drv_own; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +OSAL_BIT_OP_VAR gBtWifiGpsState; +OSAL_BIT_OP_VAR gGpsFmState; +UINT32 gWifiProbed; +INT32 gWmtDbgLvl = WMT_LOG_INFO; +MTK_WCN_BOOL g_pwr_off_flag = MTK_WCN_BOOL_TRUE; + +/******************************************************************************* +* 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_pwr_on(VOID); +static MTK_WCN_BOOL mtk_wcn_wmt_func_ctrl(ENUM_WMTDRV_TYPE_T type, ENUM_WMT_OPID_T opId); +static MTK_WCN_BOOL mtk_wmt_gps_suspend_ctrl_by_type(MTK_WCN_BOOL gps_l1, MTK_WCN_BOOL gps_l5, MTK_WCN_BOOL suspend); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +static MTK_WCN_BOOL mtk_wcn_wmt_pwr_on(VOID) +{ + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal; + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_DBG_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + pSignal = &pOp->signal; + + pOp->op.opId = WMT_OPID_PWR_ON; + pSignal->timeoutValue = MAX_FUNC_ON_TIME; + pOp->op.au4OpData[0] = WMTDRV_TYPE_WMT; + + wmt_lib_host_awake_get(); + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed,OPID(%d) type(%zu) abort\n", pOp->op.opId, pOp->op.au4OpData[0]); + wmt_lib_put_op_to_free_queue(pOp); + wmt_lib_host_awake_put(); + return MTK_WCN_BOOL_FALSE; + } + + bRet = wmt_lib_put_act_op(pOp); + + ENABLE_PSM_MONITOR(); + wmt_lib_host_awake_put(); + + if (bRet == MTK_WCN_BOOL_FALSE) + WMT_WARN_FUNC("OPID(%d) type(%zu) fail\n", pOp->op.opId, pOp->op.au4OpData[0]); + + return bRet; +} + +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; + MTK_WCN_BOOL bOffload; + MTK_WCN_BOOL bExplicitPwrOn; + + bOffload = (type == WMTDRV_TYPE_WIFI); + bExplicitPwrOn = (bOffload && opId == WMT_OPID_FUNC_ON && + wmt_lib_get_drv_status(WMTDRV_TYPE_WMT) != DRV_STS_FUNC_ON); + + /* WIFI on no need to disable psm and prevent WIFI on blocked by psm lock. */ + /* So we power on connsys separately from function on flow. */ + if (bExplicitPwrOn) + mtk_wcn_wmt_pwr_on(); + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_DBG_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + + pSignal = &pOp->signal; + + pOp->op.opId = opId; + pOp->op.au4OpData[0] = type; + if (type == WMTDRV_TYPE_WIFI) + pSignal->timeoutValue = 4000; + else + pSignal->timeoutValue = (pOp->op.opId == WMT_OPID_FUNC_ON) ? MAX_FUNC_ON_TIME : MAX_FUNC_OFF_TIME; + + WMT_INFO_FUNC("wmt-exp: OPID(%d) type(%zu) start\n", pOp->op.opId, pOp->op.au4OpData[0]); + WMT_STEP_FUNC_CTRL_DO_ACTIONS_FUNC(type, opId); + + /*do not check return value, we will do this either way */ + wmt_lib_host_awake_get(); + /* wake up chip first */ + if (!bOffload) { + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed,OPID(%d) type(%zu) abort\n", pOp->op.opId, pOp->op.au4OpData[0]); + wmt_lib_put_op_to_free_queue(pOp); + wmt_lib_host_awake_put(); + return MTK_WCN_BOOL_FALSE; + } + } + + bRet = wmt_lib_put_act_op(pOp); + if (!bOffload) + ENABLE_PSM_MONITOR(); + wmt_lib_host_awake_put(); + + if (bRet == MTK_WCN_BOOL_FALSE) + WMT_WARN_FUNC("OPID(%d) type(%zu) fail\n", pOp->op.opId, pOp->op.au4OpData[0]); + else + WMT_INFO_FUNC("OPID(%d) type(%zu) ok\n", pOp->op.opId, pOp->op.au4OpData[0]); + + return bRet; +} + +INT32 mtk_wcn_wmt_psm_ctrl(MTK_WCN_BOOL flag) +{ + return -EFAULT; +} +EXPORT_SYMBOL(mtk_wcn_wmt_psm_ctrl); + +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; +} +EXPORT_SYMBOL(mtk_wcn_wmt_func_off); + +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; +} +EXPORT_SYMBOL(mtk_wcn_wmt_func_on); + +/* +*return value: +*enable/disable thermal sensor function: true(1)/false(0) +*read thermal sensor function:thermal value +*/ +VOID mtk_wcn_wmt_func_ctrl_for_plat(UINT32 on, ENUM_WMTDRV_TYPE_T type) +{ + MTK_WCN_BOOL ret; + + if (on) + ret = mtk_wcn_wmt_func_on(type); + else + ret = mtk_wcn_wmt_func_off(type); + + WMT_INFO_FUNC("on=%d type=%d ret=%d\n", on, type, ret); +} + +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 (eType > WMTTHERM_MAX || eType < WMTTHERM_ENABLE) { + 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(eType); + if (bRet == MTK_WCN_BOOL_FALSE) { + WMT_DBG_FUNC("thermal ctrl function not supported\n"); + return MTK_WCN_BOOL_FALSE; + } + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_DBG_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_DBG_FUNC("OPID(%d) type(%zu) start\n", pOp->op.opId, pOp->op.au4OpData[0]); + WMT_STEP_DO_ACTIONS_FUNC(STEP_TRIGGER_POINT_BEFORE_READ_THERMAL); + + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed,OPID(%d) type(%zu) abort!\n", pOp->op.opId, pOp->op.au4OpData[0]); + wmt_lib_put_op_to_free_queue(pOp); + return -1; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + + if (bRet == MTK_WCN_BOOL_FALSE) { + WMT_WARN_FUNC("OPID(%d) type(%zu) fail\n\n", pOpData->opId, pOpData->au4OpData[0]); + /*0xFF means read error occurs */ + /*will return to function driver */ + pOpData->au4OpData[1] = (eType == WMTTHERM_READ) ? 0xFF : MTK_WCN_BOOL_FALSE; + } else + WMT_DBG_FUNC("OPID(%d) type(%zu) return(%zu) 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%08zx)\n", eType, pOpData->au4OpData[1]); + + return (INT8) pOpData->au4OpData[1]; +} +EXPORT_SYMBOL(mtk_wcn_wmt_therm_ctrl); + +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); +} +EXPORT_SYMBOL(mtk_wcn_wmt_hwver_get); + +UINT32 mtk_wcn_wmt_ic_info_get(ENUM_WMT_CHIPINFO_TYPE_T type) +{ + return wmt_lib_get_icinfo(type); +} +EXPORT_SYMBOL(mtk_wcn_wmt_ic_info_get); + +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 (eType >= WMTDSNS_MAX) { + 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 (bRet == MTK_WCN_BOOL_FALSE) { + WMT_ERR_FUNC("thermal ctrl function not supported\n"); + return MTK_WCN_BOOL_FALSE; + } + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_DBG_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 ((eType >= WMTDSNS_FM_DISABLE) && (eType <= WMTDSNS_FM_GPS_ENABLE)) { + pOpData->au4OpData[0] = WMTDRV_TYPE_FM; + pOpData->au4OpData[1] = eType; + } + + WMT_INFO_FUNC("OPID(%d) type(%zu) start\n", pOp->op.opId, pOp->op.au4OpData[0]); + + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed,OPID(%d) type(%zu) abort!\n", pOp->op.opId, pOp->op.au4OpData[0]); + wmt_lib_put_op_to_free_queue(pOp); + return MTK_WCN_BOOL_FALSE; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + + if (bRet == MTK_WCN_BOOL_FALSE) + WMT_WARN_FUNC("OPID(%d) type(%zu) fail\n\n", pOpData->opId, pOpData->au4OpData[0]); + else + WMT_INFO_FUNC("OPID(%d) type(%zu) ok\n\n", pOpData->opId, pOpData->au4OpData[0]); + + return bRet; +} +EXPORT_SYMBOL(mtk_wcn_wmt_dsns_ctrl); + +INT32 mtk_wcn_wmt_msgcb_reg(ENUM_WMTDRV_TYPE_T eType, PF_WMT_CB pCb) +{ + return (INT32) wmt_lib_msgcb_reg(eType, pCb); +} +EXPORT_SYMBOL(mtk_wcn_wmt_msgcb_reg); + +INT32 mtk_wcn_wmt_msgcb_unreg(ENUM_WMTDRV_TYPE_T eType) +{ + return (INT32) wmt_lib_msgcb_unreg(eType); +} +EXPORT_SYMBOL(mtk_wcn_wmt_msgcb_unreg); + +INT32 mtk_wcn_stp_wmt_sdio_op_reg(PF_WMT_SDIO_PSOP own_cb) +{ + wmt_lib_ps_set_sdio_psop(own_cb); + return 0; +} +EXPORT_SYMBOL(mtk_wcn_stp_wmt_sdio_op_reg); + +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT +INT32 mtk_wcn_wmt_sdio_deep_sleep_flag_cb_reg(PF_WMT_SDIO_DEEP_SLEEP flag_cb) +{ + wmt_lib_sdio_deep_sleep_flag_set_cb_reg(flag_cb); + return 0; +} +EXPORT_SYMBOL(mtk_wcn_wmt_sdio_deep_sleep_flag_cb_reg); +#endif + +INT32 mtk_wcn_wmt_sdio_rw_cb_reg(PF_WMT_SDIO_DEBUG reg_rw_cb) +{ + wmt_lib_sdio_reg_rw_cb(reg_rw_cb); + return 0; +} + +INT32 mtk_wcn_stp_wmt_sdio_host_awake(VOID) +{ + wmt_lib_ps_irq_cb(); + return 0; +} +EXPORT_SYMBOL(mtk_wcn_stp_wmt_sdio_host_awake); + +MTK_WCN_BOOL mtk_wcn_wmt_assert_timeout(ENUM_WMTDRV_TYPE_T type, UINT32 reason, INT32 timeout) +{ + MTK_WCN_BOOL bRet; + + bRet = wmt_lib_trigger_assert(type, reason); + + return bRet == 0 ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE; +} +EXPORT_SYMBOL(mtk_wcn_wmt_assert_timeout); + +MTK_WCN_BOOL mtk_wcn_wmt_assert(ENUM_WMTDRV_TYPE_T type, UINT32 reason) +{ + return mtk_wcn_wmt_assert_timeout(type, reason, MAX_EACH_WMT_CMD); +} +EXPORT_SYMBOL(mtk_wcn_wmt_assert); + +MTK_WCN_BOOL mtk_wcn_wmt_assert_keyword(ENUM_WMTDRV_TYPE_T type, PUINT8 keyword) +{ + MTK_WCN_BOOL bRet; + + bRet = wmt_lib_trigger_assert_keyword(type, 0, keyword); + + return bRet == 0 ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE; +} +EXPORT_SYMBOL(mtk_wcn_wmt_assert_keyword); + +/* +* ctrlId: get flash patch version opId or flash patch download opId +* pBuf: pointer to flash patch +* length: total length of flash patch +* type: flash patch type +* version: flash patch version +* checksum: flash patch checksum +*/ +ENUM_WMT_FLASH_PATCH_STATUS mtk_wcn_wmt_flash_patch_ctrl(ENUM_WMT_FLASH_PATCH_CTRL ctrlId, + PUINT8 pBuf, UINT32 length, ENUM_WMT_FLASH_PATCH_SEQ seq, ENUM_WMT_FLASH_PATCH_TYPE type, + PUINT32 version, UINT32 checksum) +{ + ENUM_WMT_FLASH_PATCH_STATUS eRet = 0; + P_OSAL_OP pOp = NULL; + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + P_OSAL_SIGNAL pSignal; + + /*1. parameter validation check */ + /*for WMT_FLASH_PATCH_VERSION_GET, ignore pBuf and length */ + /*for WMT_ANT_RAM_DOWNLOAD, + * pBuf must not be NULL, kernel space memory pointer + * length must be large than 0 + */ + switch (ctrlId) { + case WMT_FLASH_PATCH_VERSION_GET: + break; + case WMT_FLASH_PATCH_DOWNLOAD: + if ((pBuf == NULL) || (length <= 0) || (length > 1000)) { + WMT_ERR_FUNC("error parameter detected, ctrlId:%d, pBuf:%p,length(0x%x).\n", + ctrlId, pBuf, length); + eRet = WMT_FLASH_PATCH_PARA_ERR; + goto exit; + } else + break; + default: + WMT_ERR_FUNC("error ctrlId:%d detected.\n", ctrlId); + eRet = WMT_FLASH_PATCH_PARA_ERR; + goto exit; + } + + /*get WMT opId */ + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_DBG_FUNC("get_free_lxop fail\n"); + eRet = WMT_FLASH_PATCH_OP_ERR; + goto exit; + } + + pSignal = &pOp->signal; + pSignal->timeoutValue = + (ctrlId == WMT_FLASH_PATCH_DOWNLOAD) ? MAX_FUNC_ON_TIME : MAX_EACH_WMT_CMD; + + pOp->op.opId = (ctrlId == WMT_FLASH_PATCH_DOWNLOAD) ? + WMT_OPID_FLASH_PATCH_DOWN : WMT_OPID_FLASH_PATCH_VER_GET; + pOp->op.au4OpData[0] = (size_t) pBuf; + pOp->op.au4OpData[1] = length; + pOp->op.au4OpData[2] = seq; + pOp->op.au4OpData[3] = type; + pOp->op.au4OpData[4] = *version; + pOp->op.au4OpData[5] = checksum; + + /*disable PSM monitor */ + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + wmt_lib_put_op_to_free_queue(pOp); + eRet = WMT_FLASH_PATCH_OP_ERR; + goto exit; + } + /*wakeup wmtd thread */ + bRet = wmt_lib_put_act_op(pOp); + + /*enable PSM monitor */ + ENABLE_PSM_MONITOR(); + + WMT_INFO_FUNC("CMD_TEST, opid (%d), ret(%d),retVal(%zu) result(%s)\n", + pOp->op.opId, + bRet, + pOp->op.au4OpData[6], MTK_WCN_BOOL_FALSE == bRet ? "failed" : "succeed"); + + /*check return value and return result */ + if (bRet == MTK_WCN_BOOL_FALSE) { + eRet = WMT_FLASH_PATCH_OP_ERR; + } else { + switch (ctrlId) { + case WMT_FLASH_PATCH_VERSION_GET: + if (pOp->op.au4OpData[6] == 0) { + *version = pOp->op.au4OpData[4]; + eRet = WMT_FLASH_PATCH_VERSION_GET_OK; + } else + eRet = WMT_FLASH_PATCH_VERSION_GET_FAIL; + break; + case WMT_FLASH_PATCH_DOWNLOAD: + eRet = (pOp->op.au4OpData[6] == 0) ? + WMT_FLASH_PATCH_DOWNLOAD_OK : WMT_FLASH_PATCH_DOWNLOAD_FAIL; + break; + default: + WMT_ERR_FUNC("error ctrlId:%d detected.\n", ctrlId); + eRet = WMT_FLASH_PATCH_PARA_ERR; + break; + } + } + +exit: + return eRet; +} +EXPORT_SYMBOL(mtk_wcn_wmt_flash_patch_ctrl); + +#if !(DELETE_HIF_SDIO_CHRDEV) +extern INT32 mtk_wcn_wmt_chipid_query(VOID) +{ + return mtk_wcn_hif_sdio_query_chipid(0); +} +EXPORT_SYMBOL(mtk_wcn_wmt_chipid_query); +#endif + +INT8 mtk_wcn_wmt_co_clock_flag_get(void) +{ + return wmt_lib_co_clock_get(); +} +EXPORT_SYMBOL(mtk_wcn_wmt_co_clock_flag_get); + +INT32 mtk_wcn_wmt_system_state_reset(void) +{ + osal_memset(&gBtWifiGpsState, 0, osal_sizeof(gBtWifiGpsState)); + osal_memset(&gGpsFmState, 0, osal_sizeof(gGpsFmState)); + + return 0; +} + +INT32 mtk_wcn_wmt_wlan_reg(P_MTK_WCN_WMT_WLAN_CB_INFO pWmtWlanCbInfo) +{ + INT32 iRet = -1; + + if (!pWmtWlanCbInfo) { + WMT_ERR_FUNC("wlan cb info in null!\n"); + return -1; + } + + WMT_INFO_FUNC("wmt wlan cb register\n"); + mtk_wcn_wlan_probe = pWmtWlanCbInfo->wlan_probe_cb; + mtk_wcn_wlan_remove = pWmtWlanCbInfo->wlan_remove_cb; + mtk_wcn_wlan_bus_tx_cnt = pWmtWlanCbInfo->wlan_bus_cnt_get_cb; + mtk_wcn_wlan_bus_tx_cnt_clr = pWmtWlanCbInfo->wlan_bus_cnt_clr_cb; + mtk_wcn_wlan_emi_mpu_set_protection = pWmtWlanCbInfo->wlan_emi_mpu_set_protection_cb; + mtk_wcn_wlan_is_wifi_drv_own = pWmtWlanCbInfo->wlan_is_wifi_drv_own_cb; + + if (gWifiProbed) { + WMT_INFO_FUNC("wlan has been done power on,call probe directly\n"); + iRet = (*mtk_wcn_wlan_probe) (); + if (!iRet) { + WMT_INFO_FUNC("call wlan probe OK when do wlan register to wmt\n"); + gWifiProbed = 0; + } else { + WMT_ERR_FUNC("call wlan probe fail(%d) when do wlan register to wmt\n", iRet); + return -2; + } + } + return 0; +} +EXPORT_SYMBOL(mtk_wcn_wmt_wlan_reg); + +INT32 mtk_wcn_wmt_wlan_unreg(void) +{ + WMT_INFO_FUNC("wmt wlan cb unregister\n"); + mtk_wcn_wlan_probe = NULL; + mtk_wcn_wlan_remove = NULL; + mtk_wcn_wlan_bus_tx_cnt = NULL; + mtk_wcn_wlan_bus_tx_cnt_clr = NULL; + mtk_wcn_wlan_emi_mpu_set_protection = NULL; + mtk_wcn_wlan_is_wifi_drv_own = NULL; + + return 0; +} +EXPORT_SYMBOL(mtk_wcn_wmt_wlan_unreg); + +MTK_WCN_BOOL mtk_wcn_set_connsys_power_off_flag(MTK_WCN_BOOL value) +{ + g_pwr_off_flag = value; + if (g_pwr_off_flag) + WMT_DBG_FUNC("enable connsys power off flag\n"); + else + WMT_INFO_FUNC("disable connsys power off, maybe need trigger coredump!\n"); + return g_pwr_off_flag; +} +EXPORT_SYMBOL(mtk_wcn_set_connsys_power_off_flag); + +#ifdef CONFIG_MTK_COMBO_ANT +/* +* ctrlId: get ram code status opId or ram code download opId +* pBuf: pointer to ANT ram code +* length: total length of ANT ram code +*/ +ENUM_WMT_ANT_RAM_STATUS mtk_wcn_wmt_ant_ram_ctrl(ENUM_WMT_ANT_RAM_CTRL ctrlId, PUINT8 pBuf, + UINT32 length, ENUM_WMT_ANT_RAM_SEQ seq) +{ + ENUM_WMT_ANT_RAM_STATUS eRet = 0; + P_OSAL_OP pOp = NULL; + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + P_OSAL_SIGNAL pSignal; + + /*1. parameter validation check */ + /*for WMT_ANT_RAM_GET_STATUS, ignore pBuf and length */ + /*for WMT_ANT_RAM_DOWNLOAD, + * pBuf must not be NULL, kernel space memory pointer + * length must be large than 0 + */ + if ((ctrlId < WMT_ANT_RAM_GET_STATUS) || (ctrlId >= WMT_ANT_RAM_CTRL_MAX)) { + WMT_ERR_FUNC("error ctrlId:%d detected.\n", ctrlId); + eRet = WMT_ANT_RAM_PARA_ERR; + return eRet; + } + + if ((ctrlId == WMT_ANT_RAM_DOWNLOAD) && ((pBuf == NULL) || (length <= 0) || + (length > 1000) || (seq >= WMT_ANT_RAM_SEQ_MAX) || (seq < WMT_ANT_RAM_START_PKT))) { + eRet = WMT_ANT_RAM_PARA_ERR; + WMT_ERR_FUNC + ("error parameter detected, ctrlId:%d, pBuf:%p,length(0x%x),seq(%d) .\n", + ctrlId, pBuf, length, seq); + return eRet; + } + /*get WMT opId */ + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_DBG_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + + pSignal = &pOp->signal; + pSignal->timeoutValue = + (ctrlId == WMT_ANT_RAM_DOWNLOAD) ? MAX_FUNC_ON_TIME : MAX_EACH_WMT_CMD; + + pOp->op.opId = + (ctrlId == WMT_ANT_RAM_DOWNLOAD) ? WMT_OPID_ANT_RAM_DOWN : WMT_OPID_ANT_RAM_STA_GET; + pOp->op.au4OpData[0] = (size_t) pBuf; + pOp->op.au4OpData[1] = length; + pOp->op.au4OpData[2] = seq; + + + /*disable PSM monitor */ + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + wmt_lib_put_op_to_free_queue(pOp); + return MTK_WCN_BOOL_FALSE; + } + /*wakeup wmtd thread */ + bRet = wmt_lib_put_act_op(pOp); + + /*enable PSM monitor */ + ENABLE_PSM_MONITOR(); + + WMT_INFO_FUNC("CMD_TEST, opid (%d), ret(%d),retVal(%zu) result(%s)\n", + pOp->op.opId, + bRet, + pOp->op.au4OpData[2], MTK_WCN_BOOL_FALSE == bRet ? "failed" : "succeed"); + + /*check return value and return result */ + if (bRet == MTK_WCN_BOOL_FALSE) { + eRet = WMT_ANT_RAM_OP_ERR; + } else { + eRet = (ctrlId == WMT_ANT_RAM_DOWNLOAD) ? + WMT_ANT_RAM_DOWN_OK : + ((pOp->op.au4OpData[2] == 1) ? WMT_ANT_RAM_EXIST : WMT_ANT_RAM_NOT_EXIST); + } + + return eRet; + +} +EXPORT_SYMBOL(mtk_wcn_wmt_ant_ram_ctrl); +#endif +MTK_WCN_BOOL mtk_wcn_wmt_do_reset(ENUM_WMTDRV_TYPE_T type) +{ + INT32 iRet = -1; + UINT8 *drv_name[] = { + [0] = "DRV_TYPE_BT", + [1] = "DRV_TYPE_FM", + [2] = "DRV_TYPE_GPS", + [3] = "DRV_TYPE_WIFI", + [4] = "DRV_TYPE_WMT", + [5] = "DRV_TYPE_ANT", + [11] = "DRV_TYPE_GPSL5", + }; + + if ((type < WMTDRV_TYPE_BT) || (type > WMTDRV_TYPE_ANT)) { + WMT_INFO_FUNC("Wrong driver type: %d, do not trigger reset.\n", type); + return MTK_WCN_BOOL_FALSE; + } + + WMT_INFO_FUNC("Subsystem trigger whole chip reset, reset source: %s\n", drv_name[type]); + if (mtk_wcn_stp_get_wmt_trg_assert() == 0) + iRet = wmt_lib_trigger_reset(); + else { + WMT_INFO_FUNC("assert has been triggered that no chip reset is required\n"); + iRet = 0; + } + + return iRet == 0 ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE; +} +EXPORT_SYMBOL(mtk_wcn_wmt_do_reset); + +MTK_WCN_BOOL mtk_wcn_wmt_do_reset_only(ENUM_WMTDRV_TYPE_T type) +{ + INT32 iRet = -1; + + WMT_INFO_FUNC("Whole chip reset without trigger assert\n"); + if (mtk_wcn_stp_get_wmt_trg_assert() == 0) { + chip_reset_only = 1; + iRet = wmt_lib_trigger_reset(); + } else { + WMT_INFO_FUNC("assert has been triggered already\n"); + iRet = 0; + } + + return iRet == 0 ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE; +} +EXPORT_SYMBOL(mtk_wcn_wmt_do_reset_only); + +VOID mtk_wcn_wmt_set_wifi_ver(UINT32 Value) +{ + wmt_lib_soc_set_wifiver(Value); +} +EXPORT_SYMBOL(mtk_wcn_wmt_set_wifi_ver); + +INT32 mtk_wcn_wmt_wifi_fem_cfg_report(PVOID pvInfoBuf) +{ + INT32 iRet = -1; + + iRet = wmt_lib_wifi_fem_cfg_report(pvInfoBuf); + return iRet; +} +EXPORT_SYMBOL(mtk_wcn_wmt_wifi_fem_cfg_report); + +VOID mtk_wcn_wmt_dump_wmtd_backtrace(VOID) +{ + wmt_lib_dump_wmtd_backtrace(); +} +EXPORT_SYMBOL(mtk_wcn_wmt_dump_wmtd_backtrace); + +UINT32 mtk_wmt_get_gps_lna_pin_num(VOID) +{ + return wmt_lib_get_gps_lna_pin_num(); +} +EXPORT_SYMBOL(mtk_wmt_get_gps_lna_pin_num); + +VOID mtk_wmt_set_ext_ldo(UINT32 flag) +{ + wmt_lib_set_ext_ldo(flag); +} +EXPORT_SYMBOL(mtk_wmt_set_ext_ldo); + +INT32 mtk_wmt_gps_mcu_ctrl(PUINT8 p_tx_data_buf, UINT32 tx_data_len, PUINT8 p_rx_data_buf, + UINT32 rx_data_buf_len, PUINT32 p_rx_data_len) +{ + return wmt_lib_gps_mcu_ctrl(p_tx_data_buf, tx_data_len, p_rx_data_buf, rx_data_buf_len, + p_rx_data_len); +} +EXPORT_SYMBOL(mtk_wmt_gps_mcu_ctrl); + +VOID mtk_wcn_wmt_set_mcif_mpu_protection(MTK_WCN_BOOL enable) +{ + mtk_consys_set_mcif_mpu_protection(enable); +} +EXPORT_SYMBOL(mtk_wcn_wmt_set_mcif_mpu_protection); + +static MTK_WCN_BOOL mtk_wmt_gps_suspend_ctrl_by_type(MTK_WCN_BOOL gps_l1, MTK_WCN_BOOL gps_l5, MTK_WCN_BOOL suspend) +{ + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal; + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_DBG_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + + pSignal = &pOp->signal; + + pOp->op.opId = WMT_OPID_GPS_SUSPEND; + pOp->op.au4OpData[0] = (MTK_WCN_BOOL_FALSE == suspend ? 0 : 1); + pOp->op.au4OpData[1] = (MTK_WCN_BOOL_FALSE == gps_l1 ? 0 : 1); + pOp->op.au4OpData[2] = (MTK_WCN_BOOL_FALSE == gps_l5 ? 0 : 1); + pSignal->timeoutValue = (MTK_WCN_BOOL_FALSE == suspend) ? MAX_FUNC_ON_TIME : MAX_FUNC_OFF_TIME; + + WMT_INFO_FUNC("wmt-exp: OPID(%d) type(%zu) start\n", pOp->op.opId, pOp->op.au4OpData[0]); + + /*do not check return value, we will do this either way */ + wmt_lib_host_awake_get(); + /* wake up chip first */ + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed,OPID(%d) type(%zu) abort\n", pOp->op.opId, pOp->op.au4OpData[0]); + wmt_lib_put_op_to_free_queue(pOp); + wmt_lib_host_awake_put(); + return MTK_WCN_BOOL_FALSE; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + wmt_lib_host_awake_put(); + + if (bRet == MTK_WCN_BOOL_FALSE) + WMT_WARN_FUNC("OPID(%d) type(%zu) fail\n", pOp->op.opId, pOp->op.au4OpData[0]); + else + WMT_INFO_FUNC("OPID(%d) type(%zu) ok\n", pOp->op.opId, pOp->op.au4OpData[0]); + + return bRet; +} + +MTK_WCN_BOOL mtk_wmt_gps_suspend_ctrl(MTK_WCN_BOOL suspend) +{ + return mtk_wmt_gps_suspend_ctrl_by_type(MTK_WCN_BOOL_TRUE, MTK_WCN_BOOL_TRUE, suspend); +} +EXPORT_SYMBOL(mtk_wmt_gps_suspend_ctrl); + +MTK_WCN_BOOL mtk_wmt_gps_l1_suspend_ctrl(MTK_WCN_BOOL suspend) +{ + return mtk_wmt_gps_suspend_ctrl_by_type(MTK_WCN_BOOL_TRUE, MTK_WCN_BOOL_FALSE, suspend); +} +EXPORT_SYMBOL(mtk_wmt_gps_l1_suspend_ctrl); + +MTK_WCN_BOOL mtk_wmt_gps_l5_suspend_ctrl(MTK_WCN_BOOL suspend) +{ + return mtk_wmt_gps_suspend_ctrl_by_type(MTK_WCN_BOOL_FALSE, MTK_WCN_BOOL_TRUE, suspend); +} +EXPORT_SYMBOL(mtk_wmt_gps_l5_suspend_ctrl); + +INT32 mtk_wcn_wmt_mpu_lock_aquire(VOID) +{ + return wmt_lib_mpu_lock_aquire(); +} +EXPORT_SYMBOL(mtk_wcn_wmt_mpu_lock_aquire); + +VOID mtk_wcn_wmt_mpu_lock_release(VOID) +{ + wmt_lib_mpu_lock_release(); +} +EXPORT_SYMBOL(mtk_wcn_wmt_mpu_lock_release); + diff --git a/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_func.c b/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_func.c new file mode 100644 index 0000000000000..d0374a4727e6b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_func.c @@ -0,0 +1,838 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-FUNC]" + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "osal_typedef.h" + +#include "wmt_func.h" +#include "wmt_lib.h" +#include "wmt_core.h" +#include "wmt_exp.h" +#include "wmt_detect.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_GPSL5_SUPPORT + +static INT32 wmt_func_gpsl5_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); +static INT32 wmt_func_gpsl5_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); + +WMT_FUNC_OPS wmt_func_gpsl5_ops = { + /* GPS subsystem function on/off */ + .func_on = wmt_func_gpsl5_on, + .func_off = wmt_func_gpsl5_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 + + +#if CFG_FUNC_ANT_SUPPORT + +static INT32 wmt_func_ant_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); +static INT32 wmt_func_ant_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); + +WMT_FUNC_OPS wmt_func_ant_ops = { + /* BT subsystem function on/off */ + .func_on = wmt_func_ant_on, + .func_off = wmt_func_ant_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 = ~(0x1L << 5), + .regMask = 0x00000020L, + }, + { + /* pull up ctrl register */ + .regAddr = 0x80050000, + .regValue = 0x1L << 5, + .regMask = 0x00000020L, + }, + { + /* iomode ctrl register */ + .regAddr = 0x80050110, + .regValue = 0x1L << 0, + .regMask = 0x00000007L, + }, + { + /* output high/low ctrl register */ + .regAddr = 0x80050040, + .regValue = 0x1L << 5, + .regMask = 0x00000020L, + } + +}; + +CMB_PIN_CTRL_REG eediPinOlRegs[] = { + { + .regAddr = 0x80050020, + .regValue = 0x1L << 5, + .regMask = 0x00000020L, + }, + { + .regAddr = 0x80050000, + .regValue = ~(0x1L << 5), + .regMask = 0x00000020L, + }, + { + .regAddr = 0x80050110, + .regValue = 0x1L << 0, + .regMask = 0x00000007L, + }, + { + .regAddr = 0x80050040, + .regValue = ~(0x1L << 5), + .regMask = 0x00000020L, + } +}; + +CMB_PIN_CTRL_REG eedoPinOhRegs[] = { + { + .regAddr = 0x80050020, + .regValue = ~(0x1L << 7), + .regMask = 0x00000080L, + }, + { + .regAddr = 0x80050000, + .regValue = 0x1L << 7, + .regMask = 0x00000080L, + }, + { + .regAddr = 0x80050110, + .regValue = 0x1L << 12, + .regMask = 0x00007000L, + }, + { + .regAddr = 0x80050040, + .regValue = 0x1L << 7, + .regMask = 0x00000080L, + } +}; + + +CMB_PIN_CTRL_REG eedoPinOlRegs[] = { + { + .regAddr = 0x80050020, + .regValue = 0x1L << 7, + .regMask = 0x00000080L, + }, + { + .regAddr = 0x80050000, + .regValue = ~(0x1L << 7), + .regMask = 0x00000080L, + }, + { + .regAddr = 0x80050110, + .regValue = 0x1L << 12, + .regMask = 0x00007000L, + }, + { + .regAddr = 0x80050040, + .regValue = ~(0x1L << 7), + .regMask = 0x00000080L, + } + +}; + +CMB_PIN_CTRL_REG gsyncPinOnRegs[] = { + { + .regAddr = 0x80050110, + .regValue = 0x3L << 20, + .regMask = 0x7L << 20, + } + +}; + +CMB_PIN_CTRL_REG gsyncPinOffRegs[] = { + { + .regAddr = 0x80050110, + .regValue = 0x0L << 20, + .regMask = 0x7L << 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) +{ + INT32 iRet = -1; + ULONG ctrlPa1; + ULONG ctrlPa2; + + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_COMBO) + return wmt_core_func_ctrl_cmd(WMTDRV_TYPE_BT, MTK_WCN_BOOL_TRUE); + + ctrlPa1 = BT_PALDO; + ctrlPa2 = PALDO_ON; + iRet = wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + if (iRet) { + WMT_ERR_FUNC("wmt-func: wmt_ctrl_soc_paldo_ctrl failed(%d)(%lu)(%lu)\n", + iRet, ctrlPa1, ctrlPa2); + return -1; + } + iRet = wmt_core_func_ctrl_cmd(WMTDRV_TYPE_BT, MTK_WCN_BOOL_TRUE); + if (iRet) { + WMT_ERR_FUNC("wmt-func: wmt_core_func_ctrl_cmd(bt_on) failed(%d)\n", iRet); + ctrlPa1 = BT_PALDO; + ctrlPa2 = PALDO_OFF; + wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + + return -2; + } + osal_set_bit(WMT_BT_ON, &gBtWifiGpsState); + return 0; +} + +INT32 wmt_func_bt_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + INT32 iRet1 = -1; + INT32 iRet2 = -1; + ULONG ctrlPa1; + ULONG ctrlPa2; + + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_COMBO) + return wmt_core_func_ctrl_cmd(WMTDRV_TYPE_BT, MTK_WCN_BOOL_FALSE); + + iRet1 = wmt_core_func_ctrl_cmd(WMTDRV_TYPE_BT, MTK_WCN_BOOL_FALSE); + if (iRet1) + WMT_ERR_FUNC("wmt-func: wmt_core_func_ctrl_cmd(bt_off) failed(%d)\n", iRet1); + + ctrlPa1 = BT_PALDO; + ctrlPa2 = PALDO_OFF; + iRet2 = wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + if (iRet2) + WMT_ERR_FUNC("wmt-func: wmt_ctrl_soc_paldo_ctrl(bt_off) failed(%d)\n", iRet2); + + if (iRet1 + iRet2) + return -1; + + osal_clear_bit(WMT_BT_ON, &gBtWifiGpsState); + return 0; +} + +#endif +#if CFG_FUNC_ANT_SUPPORT + +INT32 _osal_inline_ wmt_func_ant_ctrl(ENUM_FUNC_STATE funcState) +{ + /*only need to send turn BT subsystem wmt command */ + return wmt_core_func_ctrl_cmd(WMTDRV_TYPE_ANT, + (FUNC_ON == + funcState) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE); +} + +INT32 wmt_func_ant_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + return wmt_core_func_ctrl_cmd(WMTDRV_TYPE_ANT, MTK_WCN_BOOL_TRUE); +} + +INT32 wmt_func_ant_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + return wmt_core_func_ctrl_cmd(WMTDRV_TYPE_ANT, 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 = &gCmbPinCtrl[CMB_PIN_GSYNC_ID]; + WMT_CTRL_DATA ctrlData; + WMT_IC_PIN_ID wmtIcPinId = WMT_IC_PIN_MAX; + /* sanity check */ + if (FUNC_ON != funcStatus && FUNC_OFF != funcStatus) { + WMT_ERR_FUNC("invalid funcStatus(%d)\n", funcStatus); + return -1; + } + /* turn on GPS sync function on both side */ + ctrlData.ctrlId = WMT_CTRL_GPS_SYNC_SET; + ctrlData.au4CtrlData[0] = (funcStatus == FUNC_ON) ? 1 : 0; + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + /*we suppose this would never print */ + WMT_ERR_FUNC("ctrl GPS_SYNC_SET(%d) fail, ret(%d)\n", funcStatus, iRet); + /* TODO:[FixMe][George] error handling? */ + return -2; + } + WMT_DBG_FUNC("ctrl GPS_SYNC_SET(%d) ok\n", funcStatus); + + if ((pOps->ic_pin_ctrl == NULL) || (pOps->ic_pin_ctrl(WMT_IC_PIN_GSYNC, FUNC_ON == + funcStatus ? WMT_IC_PIN_MUX : WMT_IC_PIN_GPIO, 1) < 0)) { + /*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, ®Value, regMask); + if (iRet) { + WMT_ERR_FUNC("set reg for GPS_SYNC function fail(%d)\n", iRet); + /* TODO:[FixMe][Chaozhong] error handling? */ + return -2; + } + + } + } else { + WMT_DBG_FUNC("set reg for GPS_SYNC function okay by chip ic_pin_ctrl\n"); + } + WMT_DBG_FUNC("ctrl combo chip gps sync function succeed\n"); + /* turn on GPS lna ctrl function */ + if (pConf != NULL) { + if (pConf->wmt_gps_lna_enable == 0) { + + 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] = funcStatus == FUNC_ON ? 1 : 0; + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + /*we suppose this would never print */ + WMT_ERR_FUNC("ctrl host GPS_LNA output high fail, ret(%d)\n", iRet); + /* TODO:[FixMe][Chaozhong] error handling? */ + return -3; + } + WMT_INFO_FUNC("GPS LNA pin number(%d)\n", mtk_wmt_get_gps_lna_pin_num()); + WMT_DBG_FUNC("ctrl host gps lna function succeed\n"); + } else { + WMT_INFO_FUNC("combo chip pin(%s) used for gps lna\n", + pConf->wmt_gps_lna_pin == 0 ? "EEDI" : "EEDO"); + wmtIcPinId = + pConf->wmt_gps_lna_pin == 0 ? WMT_IC_PIN_EEDI : WMT_IC_PIN_EEDO; + if ((pOps->ic_pin_ctrl == NULL) || (pOps->ic_pin_ctrl(wmtIcPinId, FUNC_ON == + funcStatus ? WMT_IC_PIN_GPIO_HIGH : WMT_IC_PIN_GPIO_LOW, 1) < 0)) { + /*WMT_IC_PIN_GSYNC */ + if (pConf->wmt_gps_lna_pin == 0) { + /* EEDI needed */ + pCmbPinCtrl = &gCmbPinCtrl[CMB_PIN_EEDI_ID]; + } else if (pConf->wmt_gps_lna_pin == 1) { + /* EEDO needed */ + pCmbPinCtrl = &gCmbPinCtrl[CMB_PIN_EEDO_ID]; + } + regNum = pCmbPinCtrl->regNum; + for (i = 0; i < regNum; i++) { + pReg = + funcStatus == FUNC_ON ? &pCmbPinCtrl->pFuncOnArray[i] : + &pCmbPinCtrl->pFuncOffArray[i]; + regAddr = pReg->regAddr; + regValue = pReg->regValue; + regMask = pReg->regMask; + + iRet = wmt_core_reg_rw_raw(1, regAddr, ®Value, regMask); + if (iRet) { + WMT_ERR_FUNC + ("set reg for GPS_LNA function fail(%d)\n", + iRet); + /* TODO:[FixMe][Chaozhong] error handling? */ + return -3; + } + } + WMT_INFO_FUNC("ctrl combo chip gps lna succeed\n"); + } else { + WMT_INFO_FUNC + ("set reg for GPS_LNA function okay by chip ic_pin_ctrl\n"); + } + } + } + return 0; + +} + +INT32 wmt_func_gps_pre_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + return wmt_func_gps_pre_ctrl(pOps, pConf, FUNC_ON); +} + +INT32 wmt_func_gps_pre_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + + return wmt_func_gps_pre_ctrl(pOps, pConf, FUNC_OFF); +} + + +INT32 wmt_func_gps_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + INT32 iRet = 0; + unsigned long ctrlPa1; + unsigned long ctrlPa2; + UINT8 co_clock_type = 0; + + if (!pConf) + return -1; + + co_clock_type = (pConf->co_clock_flag & 0x0f); + + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) { + if ((co_clock_type) && (pConf->wmt_gps_lna_enable == 0)) { /* use SOC external LNA */ + if (!osal_test_bit(WMT_FM_ON, &gGpsFmState) && !osal_test_bit(WMT_GPSL5_ON, &gGpsFmState)) { + ctrlPa1 = GPS_PALDO; + ctrlPa2 = PALDO_ON; + wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + } else { + WMT_INFO_FUNC("LDO VCN28 has been turn on by FM or GPSL5\n"); + } + } + } + if (!osal_test_bit(WMT_GPSL5_ON, &gGpsFmState)) + iRet = wmt_func_gps_pre_on(pOps, pConf); + else + WMT_INFO_FUNC("gps has been pre on by GPSL5\n"); + if (iRet == 0) { + if (!pConf || pConf->wmt_gps_suspend_ctrl == 0) + iRet = wmt_func_gps_ctrl(FUNC_ON); + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) { + if (!iRet) { + osal_set_bit(WMT_GPS_ON, &gBtWifiGpsState); + if ((co_clock_type) && (pConf->wmt_gps_lna_enable == 0)) /* use SOC external LNA */ + osal_set_bit(WMT_GPS_ON, &gGpsFmState); + osal_clear_bit(WMT_GPS_SUSPEND, &gGpsFmState); + } + } + } + return iRet; +} + +INT32 wmt_func_gps_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + INT32 iRet = 0; + unsigned long ctrlPa1 = 0; + unsigned long ctrlPa2 = 0; + UINT8 co_clock_type = 0; + + if (!pConf) + return -1; + + co_clock_type = (pConf->co_clock_flag & 0x0f); + + if (osal_test_bit(WMT_GPSL5_ON, &gGpsFmState)) + WMT_INFO_FUNC("GPSL5 is still on, do not pre off gps\n"); + else if (!osal_test_bit(WMT_GPS_SUSPEND, &gGpsFmState)) + iRet = wmt_func_gps_pre_off(pOps, pConf); + if (iRet == 0) { + if (!pConf || pConf->wmt_gps_suspend_ctrl == 0) + iRet = wmt_func_gps_ctrl(FUNC_OFF); + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) { + if (!iRet) + osal_clear_bit(WMT_GPS_ON, &gBtWifiGpsState); + } + } + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) { + if ((co_clock_type) && (pConf->wmt_gps_lna_enable == 0)) { /* use SOC external LNA */ + if (osal_test_bit(WMT_FM_ON, &gGpsFmState) || osal_test_bit(WMT_GPSL5_ON, &gGpsFmState)) + WMT_INFO_FUNC("FM or GPSL5 is still on, do not turn off LDO VCN28\n"); + else if (osal_test_bit(WMT_GPS_SUSPEND, &gGpsFmState)) + WMT_INFO_FUNC("It's GPS suspend mode, LDO VCN28 has been turned off\n"); + else { + ctrlPa1 = GPS_PALDO; + ctrlPa2 = PALDO_OFF; + wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + } + osal_clear_bit(WMT_GPS_ON, &gGpsFmState); + } + if (pConf->wmt_gps_suspend_ctrl == 1) + osal_set_bit(WMT_GPS_SUSPEND, &gGpsFmState); + } + return iRet; + +} +#endif + +#if CFG_FUNC_GPSL5_SUPPORT +INT32 _osal_inline_ wmt_func_gpsl5_ctrl(ENUM_FUNC_STATE funcState) +{ + /*send turn GPS subsystem wmt command */ + return wmt_core_func_ctrl_cmd(6, + (FUNC_ON == + funcState) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE); +} + +INT32 wmt_func_gpsl5_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + INT32 iRet = 0; + unsigned long ctrlPa1; + unsigned long ctrlPa2; + UINT8 co_clock_type = 0; + + if (!pConf) { + WMT_INFO_FUNC("pConf == NULL\n"); + return -1; + } + + co_clock_type = (pConf->co_clock_flag & 0x0f); + + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) { + if ((co_clock_type) && (pConf->wmt_gps_lna_enable == 0)) { /* use SOC external LNA */ + if (!osal_test_bit(WMT_FM_ON, &gGpsFmState) && + !osal_test_bit(WMT_GPS_ON, &gGpsFmState)) { + ctrlPa1 = GPS_PALDO; + ctrlPa2 = PALDO_ON; + wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + } else { + WMT_INFO_FUNC("LDO VCN28 has been turn on by FM or GPSL1\n"); + } + } + } + if (!osal_test_bit(WMT_GPS_ON, &gGpsFmState)) + iRet = wmt_func_gps_pre_on(pOps, pConf); + else + WMT_INFO_FUNC("gps has been pre on by GPSL1\n"); + if (iRet == 0) { + if (pConf->wmt_gps_suspend_ctrl == 0) + iRet = wmt_func_gpsl5_ctrl(FUNC_ON); + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) { + if (!iRet) { + osal_set_bit(WMT_GPSL5_ON, &gBtWifiGpsState); + if ((co_clock_type) && (pConf->wmt_gps_lna_enable == 0)) /* use SOC external LNA */ + osal_set_bit(WMT_GPSL5_ON, &gGpsFmState); + osal_clear_bit(WMT_GPSL5_SUSPEND, &gGpsFmState); + } + } + } + return iRet; +} + +INT32 wmt_func_gpsl5_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + INT32 iRet = 0; + unsigned long ctrlPa1 = 0; + unsigned long ctrlPa2 = 0; + UINT8 co_clock_type = 0; + + if (!pConf) { + WMT_INFO_FUNC("pConf == NULL\n"); + return -1; + } + + co_clock_type = (pConf->co_clock_flag & 0x0f); + + if (osal_test_bit(WMT_GPS_ON, &gGpsFmState)) + WMT_INFO_FUNC("GPSL1 is still on, do not pre off gps\n"); + else if (!osal_test_bit(WMT_GPSL5_SUSPEND, &gGpsFmState)) + iRet = wmt_func_gps_pre_off(pOps, pConf); + if (iRet == 0) { + if (pConf->wmt_gps_suspend_ctrl == 0) + iRet = wmt_func_gpsl5_ctrl(FUNC_OFF); + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) { + if (!iRet) + osal_clear_bit(WMT_GPSL5_ON, &gBtWifiGpsState); + } + } + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) { + if ((co_clock_type) && (pConf->wmt_gps_lna_enable == 0)) { /* use SOC external LNA */ + if (osal_test_bit(WMT_FM_ON, &gGpsFmState) || osal_test_bit(WMT_GPS_ON, &gGpsFmState)) + WMT_INFO_FUNC("FM or GPSL1 is still on, do not turn off LDO VCN28\n"); + else if (osal_test_bit(WMT_GPSL5_SUSPEND, &gGpsFmState)) + WMT_INFO_FUNC("It's GPS suspend mode, LDO VCN28 has been turned off\n"); + else { + ctrlPa1 = GPS_PALDO; + ctrlPa2 = PALDO_OFF; + wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + } + osal_clear_bit(WMT_GPSL5_ON, &gGpsFmState); + } + if (pConf->wmt_gps_suspend_ctrl == 1) + osal_set_bit(WMT_GPSL5_SUSPEND, &gGpsFmState); + } + return iRet; + +} +#endif + +#if CFG_FUNC_FM_SUPPORT + +INT32 _osal_inline_ wmt_func_fm_ctrl(ENUM_FUNC_STATE funcState) +{ + /*only need to send turn FM subsystem wmt command */ + return wmt_core_func_ctrl_cmd(WMTDRV_TYPE_FM, + (FUNC_ON == + funcState) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE); +} + + +INT32 wmt_func_fm_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + ULONG ctrlPa1 = 0; + ULONG ctrlPa2 = 0; + INT32 iRet = -1; + UINT8 co_clock_type = (pConf->co_clock_flag & 0x0f); + + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) { + if (co_clock_type) { + if (!osal_test_bit(WMT_GPS_ON, &gGpsFmState) && !osal_test_bit(WMT_GPSL5_ON, &gGpsFmState)) { + ctrlPa1 = FM_PALDO; + ctrlPa2 = PALDO_ON; + wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + } else { + WMT_INFO_FUNC("LDO VCN28 has been turn on by GPS\n"); + } + } else + WMT_ERR_FUNC("wmt-func: co_clock_type is not 1!\n"); + iRet = wmt_core_func_ctrl_cmd(WMTDRV_TYPE_FM, MTK_WCN_BOOL_TRUE); + if (!iRet) { + if (co_clock_type) + osal_set_bit(WMT_FM_ON, &gGpsFmState); + } + return iRet; + } + 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) +{ + ULONG ctrlPa1 = 0; + ULONG ctrlPa2 = 0; + INT32 iRet = -1; + UINT8 co_clock_type = (pConf->co_clock_flag & 0x0f); + + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) { + iRet = wmt_core_func_ctrl_cmd(WMTDRV_TYPE_FM, MTK_WCN_BOOL_FALSE); + if (co_clock_type) { + if (osal_test_bit(WMT_GPS_ON, &gGpsFmState) || osal_test_bit(WMT_GPSL5_ON, &gGpsFmState)) { + WMT_INFO_FUNC("GPS is still on, do not turn off LDO VCN28\n"); + } else { + ctrlPa1 = FM_PALDO; + ctrlPa2 = PALDO_OFF; + wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + } + osal_clear_bit(WMT_FM_ON, &gGpsFmState); + } + return iRet; + } + 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; + ULONG ctrlPa1 = WMT_SDIO_FUNC_WIFI; + ULONG ctrlPa2 = (funcState == FUNC_ON) ? 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) +{ + INT32 iRet = 0; + + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_COMBO) + return wmt_func_wifi_ctrl(FUNC_ON); + + if (mtk_wcn_wlan_probe != NULL) { + WMT_WARN_FUNC("WMT-FUNC: wmt wlan func on before wlan probe\n"); + iRet = (*mtk_wcn_wlan_probe) (); + if (iRet) { + WMT_ERR_FUNC("WMT-FUNC: wmt call wlan probe fail(%d)\n", iRet); + iRet = -1; + } else { + WMT_WARN_FUNC("WMT-FUNC: wmt call wlan probe ok\n"); + } + } else { + WMT_ERR_FUNC("WMT-FUNC: null pointer mtk_wcn_wlan_probe\n"); + gWifiProbed = 1; + iRet = -2; + } + if (!iRet) + osal_set_bit(WMT_WIFI_ON, &gBtWifiGpsState); + return iRet; +} + +INT32 wmt_func_wifi_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + INT32 iRet = 0; + + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_COMBO) + return wmt_func_wifi_ctrl(FUNC_OFF); + + if (mtk_wcn_wlan_remove != NULL) { + WMT_WARN_FUNC("WMT-FUNC: wmt wlan func on before wlan remove\n"); + iRet = (*mtk_wcn_wlan_remove) (); + if (iRet) { + WMT_ERR_FUNC("WMT-FUNC: wmt call wlan remove fail(%d)\n", iRet); + iRet = -1; + } else { + WMT_WARN_FUNC("WMT-FUNC: wmt call wlan remove ok\n"); + } + } else { + WMT_ERR_FUNC("WMT-FUNC: null pointer mtk_wcn_wlan_remove\n"); + iRet = -2; + } + if (!iRet) + osal_clear_bit(WMT_WIFI_ON, &gBtWifiGpsState); + return iRet; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_ic_6620.c b/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_ic_6620.c new file mode 100644 index 0000000000000..9b033ad92dd4c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_ic_6620.c @@ -0,0 +1,1909 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/******************************************************************************* +* 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 "osal.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) +/* BT Port 2 Feature. this command does not need after coex command is downconfirmed by LC, */ +#define CFG_WMT_BT_PORT2 (0) + +#define CFG_SET_OPT_REG (0) +#define CFG_WMT_I2S_DBGUART_SUPPORT (0) +#define CFG_SET_OPT_REG_SWLA (0) +#define CFG_SET_OPT_REG_MCUCLK (0) +#define CFG_SET_OPT_REG_MCUIRQ (0) + +#define CFG_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 UINT8 gDefPatchName[NAME_MAX + 1]; +#endif +static UINT8 gFullPatchName[NAME_MAX + 1]; +static const WMT_IC_INFO_S *gp_mt6620_info; +static WMT_PATCH gp_mt6620_patch_info; + +static UINT8 WMT_WAKEUP_DIS_GATE_CMD[] = { 0x1, 0x3, 0x01, 0x00, 0x04 }; +static UINT8 WMT_WAKEUP_DIS_GATE_EVT[] = { 0x2, 0x3, 0x02, 0x0, 0x0, 0x04 }; + +#if 0 +static UINT8 WMT_WAKEUP_EN_GATE_CMD[] = { 0x1, 0x3, 0x01, 0x00, 0x05 }; +static UINT8 WMT_WAKEUP_EN_GATE_EVT[] = { 0x2, 0x3, 0x02, 0x0, 0x0, 0x05 }; +#endif +static UINT8 WMT_QUERY_BAUD_CMD[] = { 0x01, 0x04, 0x01, 0x00, 0x02 }; +static UINT8 WMT_QUERY_BAUD_EVT_115200[] = { 0x02, 0x04, 0x06, 0x00, 0x00, 0x02, 0x00, 0xC2, 0x01, 0x00 }; +static UINT8 WMT_QUERY_BAUD_EVT_X[] = { 0x02, 0x04, 0x06, 0x00, 0x00, 0x02, 0xAA, 0xAA, 0xAA, 0xBB }; +static UINT8 WMT_QUERY_STP_CMD[] = { 0x01, 0x04, 0x01, 0x00, 0x04 }; +static UINT8 WMT_QUERY_STP_EVT_DEFAULT[] = { 0x02, 0x04, 0x06, 0x00, 0x00, 0x04, 0x11, 0x00, 0x00, 0x00 }; +static UINT8 WMT_QUERY_STP_EVT_UART[] = { 0x02, 0x04, 0x06, 0x00, 0x00, 0x04, 0xDF, 0x0E, 0x68, 0x01 }; +static UINT8 WMT_SET_BAUD_CMD_X[] = { 0x01, 0x04, 0x05, 0x00, 0x01, 0xAA, 0xAA, 0xAA, 0xBB }; +static UINT8 WMT_SET_BAUD_EVT[] = { 0x02, 0x04, 0x02, 0x00, 0x00, 0x01 }; +static UINT8 WMT_SET_WAKEUP_WAKE_CMD_RAW[] = { 0xFF }; +static UINT8 WMT_SET_WAKEUP_WAKE_EVT[] = { 0x02, 0x03, 0x02, 0x00, 0x00, 0x03 }; + +#if CFG_WMT_MULTI_PATCH +static UINT8 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 UINT8 WMT_PATCH_ADDRESS_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; + +static UINT8 WMT_PATCH_P_ADDRESS_CMD[] = { 0x01, 0x08, 0x10, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x38, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff +}; +static UINT8 WMT_PATCH_P_ADDRESS_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; +#endif + +static UINT8 WMT_PATCH_CMD[] = { 0x01, 0x01, 0x00, 0x00, 0x00 }; +static UINT8 WMT_PATCH_EVT[] = { 0x02, 0x01, 0x01, 0x00, 0x00 }; +static UINT8 WMT_RESET_CMD[] = { 0x01, 0x07, 0x01, 0x00, 0x04 }; +static UINT8 WMT_RESET_EVT[] = { 0x02, 0x07, 0x01, 0x00, 0x00 }; + +#if CFG_WMT_BT_PORT2 +static UINT8 WMT_BTP2_CMD[] = { 0x01, 0x10, 0x03, 0x00, 0x01, 0x03, 0x01 }; +static UINT8 WMT_BTP2_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; +#endif +/*coex cmd/evt++*/ +static UINT8 WMT_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x04, 0x00, 0x01, 0xAA, 0xBB, 0xCC }; +static UINT8 WMT_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_BT_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x0B, + 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, + 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xAA +}; +static UINT8 WMT_BT_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_WIFI_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x0C, + 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xAA +}; +static UINT8 WMT_WIFI_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_PTA_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x0A, + 0x00, 0x04, + 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xEE, 0xFF, 0xFF, 0xFE +}; +static UINT8 WMT_PTA_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_MISC_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x09, + 0x00, 0x05, + 0xAA, 0xAA, 0xAA, 0xAA, + 0xBB, 0xBB, 0xBB, 0xBB +}; +static UINT8 WMT_MISC_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +/*coex cmd/evt--*/ +static UINT8 WMT_SET_STP_CMD[] = { 0x01, 0x04, 0x05, 0x00, 0x03, 0xDF, 0x0E, 0x68, 0x01 }; +static UINT8 WMT_SET_STP_EVT[] = { 0x02, 0x04, 0x02, 0x00, 0x00, 0x03 }; +static UINT8 WMT_STRAP_CONF_CMD_FM_COMM[] = { 0x01, 0x05, 0x02, 0x00, 0x02, 0x02 }; +static UINT8 WMT_STRAP_CONF_EVT[] = { 0x02, 0x05, 0x02, 0x00, 0x00, 0x02 }; + +#if 0 +static UINT8 WMT_SET_OSC32K_BYPASS_CMD[] = { 0x01, 0x0A, 0x01, 0x00, 0x05 }; +static UINT8 WMT_SET_OSC32K_BYPASS_EVT[] = { 0x02, 0x0A, 0x01, 0x00, 0x00 }; +#endif + +static UINT8 WMT_CORE_DUMP_LEVEL_04_CMD[] = { 0x1, 0x0F, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static UINT8 WMT_CORE_DUMP_LEVEL_04_EVT[] = { 0x2, 0x0F, 0x01, 0x00, 0x00 }; + +/* enable all interrupt */ +static UINT8 WMT_SET_ALLINT_REG_CMD[] = { 0x01, 0x08, 0x10, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ + , 0x00, 0x03, 0x05, 0x80 /*addr:0x80050300 */ + , 0x00, 0xC4, 0x00, 0x00 /*value:0x0000C400 */ + , 0x00, 0xC4, 0x00, 0x00 /*mask:0x0000C400 */ +}; + +static UINT8 WMT_SET_ALLINT_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ +}; + +#if CFG_SET_OPT_REG_SWLA /* enable swla: eesk(7) eecs(8) oscen(19) sck0(24) scs0(25) */ +static UINT8 WMT_SET_SWLA_REG_CMD[] = { 0x01, 0x08, 0x1C, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x02 /*2 registers */ + , 0x10, 0x01, 0x05, 0x80 /*addr:0x80050110 */ + , 0x10, 0x10, 0x01, 0x00 /*value:0x00011010 */ + , 0xF0, 0xF0, 0x0F, 0x00 /*mask:0x000FF0F0 */ + , 0x40, 0x01, 0x05, 0x80 /*addr:0x80050140 */ + , 0x00, 0x10, 0x01, 0x00 /*value:0x00011000 */ + , 0x00, 0xF0, 0x0F, 0x00 /*mask:0x000FF000 */ +}; + +static UINT8 WMT_SET_SWLA_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x02 /*2 registers */ +}; +#endif + +#if CFG_SET_OPT_REG_MCUCLK /* enable mcu clk: antsel_4, eedi */ +static UINT8 WMT_SET_MCUCLK_REG_CMD[] = { 0x01, 0x08, (4 + 12 * 4), 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /* type: reg */ + , 0x00 /* rev */ + , 0x04 /* 4 registers */ + , 0x00, 0x04, 0x00, 0x80 /* addr:0x8000 0400 */ + , 0x00, 0x14, 0x00, 0x00 /* value:0x0000 1400(osc, hclk), 0x0000 1501(PLL, en) */ + , 0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000 FFFF */ + , 0x80, 0x01, 0x05, 0x80 /* addr:0x8005 0180 */ + , 0x12, 0x13, 0x00, 0x00 /* value:0x0000 1312(osc, hclk), 0x0000 1a19(PLL, en) */ + , 0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000 FFFF */ + , 0x00, 0x01, 0x05, 0x80 /* addr:0x8005 0100 */ + , 0x00, 0x00, 0x02, 0x00 /* value:0x0002 0000 */ + , 0x00, 0x00, 0x0F, 0x00 /* mask:0x000F 0000 */ + , 0x10, 0x01, 0x05, 0x80 /* addr:0x8005 0110 */ + , 0x02, 0x00, 0x00, 0x00 /* value:0x0000 0002 */ + , 0x0F, 0x00, 0x00, 0x00 /* mask:0x0000 000F */ +}; + +static UINT8 WMT_SET_MCUCLK_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /* S: 0 */ + , 0x00 /* type: reg */ + , 0x00 /* rev */ + , 0x04 /* 4 registers */ +}; +#endif + +#if CFG_WMT_I2S_DBGUART_SUPPORT /* register write for debug uart */ +static UINT8 WMT_SET_DBGUART_REG_CMD[] = { 0x01, 0x08, 0x1C, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x02 /*2 registers */ + , 0x30, 0x01, 0x05, 0x80 /*addr:0x80050130 */ + , 0x00, 0x00, 0x00, 0x00 /*value:0x00000000 */ + , 0xF0, 0x0F, 0x00, 0x00 /*mask:0x00000FF0 */ + , 0x40, 0x01, 0x05, 0x80 /*addr:0x80050140 */ + , 0x00, 0x01, 0x00, 0x00 /*value:0x00000100 */ + , 0x00, 0x01, 0x00, 0x00 /*mask:0x00000100 */ +}; + +static UINT8 WMT_SET_DBGUART_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x02 /*2 registers */ +}; +#endif + +#if CFG_SET_OPT_REG_MCUIRQ /* enable mcu irq: antsel_4, wlan_act */ +#if 1 /* Ray */ +static UINT8 WMT_SET_MCUIRQ_REG_CMD[] = { 0x01, 0x08, (4 + 12 * 4), 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /* type: reg */ + , 0x00 /* rev */ + , 0x04 /* 4 registers */ + , 0x00, 0x04, 0x00, 0x80 /* addr:0x8000_0400 */ + , 0x03, 0x14, 0x00, 0x00 /* value:0x0000_1403 check confg debug flag 3 low word */ + , 0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000_FFFF */ + /* cirq_int_n */ + , 0x10, 0x01, 0x05, 0x80 /* addr:0x8005_0110 */ + , 0x02, 0x00, 0x00, 0x00 /* value:0x0000_0002 set EEDI as cirq_int_n debug flag (monitor flag2) */ + , 0x07, 0x00, 0x00, 0x00 /* mask:0x0000_0007 */ + , 0x00, 0x01, 0x05, 0x80 /* addr:0x8005_0100 */ + , 0x00, 0x00, 0x02, 0x00 /* value:0x0002_0000 (ANTSEL4=>monitor flag 0, ahb_x2_gt_ck debug flag) */ + , 0x00, 0x00, 0x07, 0x00 /* mask:0x0007_0000 */ + /* 1. ARM irq_b, monitor flag 0 */ + , 0x80, 0x01, 0x05, 0x80 /* addr:0x8005_0180 */ + , 0x1F, 0x1E, 0x00, 0x00 /* value:0x0000_1E1F check mcusys debug flag */ + , 0x7F, 0x7F, 0x00, 0x00 /* mask:0x0000_7F7F */ +}; + +static UINT8 WMT_SET_MCUIRQ_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /* S: 0 */ + , 0x00 /* type: reg */ + , 0x00 /* rev */ + , 0x04 /* 5 registers */ +}; +#elif 0 /* KC */ +static UINT8 WMT_SET_MCUIRQ_REG_CMD[] = { 0x01, 0x08, (4 + 12 * 5), 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /* type: reg */ + , 0x00 /* rev */ + , 0x05 /* 5 registers */ + , 0x00, 0x04, 0x00, 0x80 /* addr:0x8000_0400 */ + , 0x00, 0x02, 0x00, 0x00 /* value:0x0000_0200 [15:8]=0x2 arm irq_b, 0xA irq_bus[5] bt_timcon_irq_b */ + , 0x00, 0xFF, 0x00, 0x00 /* mask:0x0000_FF00 */ + /* 1. ARM irq_b, monitor flag 0 */ + , 0x80, 0x01, 0x05, 0x80 /* addr:0x8005_0180 */ + , 0x18, 0x00, 0x00, 0x00 /* value:0x0000_0018 [6:0]=001_1000 (monitor flag 0 select, MCUSYS, SEL:8) */ + , 0x7F, 0x00, 0x00, 0x00 /* mask:0x0000_007F */ + , 0x00, 0x01, 0x05, 0x80 /* addr:0x8005_0100 */ + , 0x00, 0x00, 0x02, 0x00 /* value:0x0002_0000 (ANTSEL4=>monitor flag 0) */ + , 0x00, 0x00, 0x07, 0x00 /* mask:0x0007_0000 */ + /* 2. irq_bus[5] bt_timcon_irq_b monitor flag 15 */ + , 0xB0, 0x01, 0x05, 0x80 /* addr:0x8005_01B0 */ + , 0x00, 0x00, 0x00, 0x16 /* value:0x1600_0000 [30:24]=001_0110 (monitor flag 15 select, MCUSYS, SEL:6) */ + , 0x00, 0x00, 0x00, 0x7F /* mask:0x7F00_0000 */ + , 0x30, 0x01, 0x05, 0x80 /* addr:0x8005_0130 */ + , 0x00, 0x20, 0x00, 0x00 /* value:0x0000_2000 (WLAN_ACT=>monitor flag 15) */ + , 0x00, 0x70, 0x00, 0x00 /* mask:0x0000_7000 */ +}; + +static UINT8 WMT_SET_MCUIRQ_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /* S: 0 */ + , 0x00 /* type: reg */ + , 0x00 /* rev */ + , 0x05 /* 5 registers */ +}; +#endif +#endif + +/* 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, + .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, + .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, + .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, + .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, + .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, + .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, + .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); + +static MTK_WCN_BOOL mt6620_aee_dump_flag_get(VOID); + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/* MT6620 Operation Function Table */ +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 = mt6620_aee_dump_flag_get, + .trigger_stp_assert = NULL, + .deep_sleep_ctrl = 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; + UINT8 evtBuf[256]; + unsigned long ctrlPa1; + unsigned long ctrlPa2; + UINT32 hw_ver; + + WMT_DBG_FUNC(" start\n"); + + osal_assert(gp_mt6620_info != NULL); + if ((gp_mt6620_info == NULL) + || (pWmtHifConf == NULL) + ) { + 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 (pWmtHifConf->hifType == WMT_HIF_SDIO) { + /* 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 (pWmtHifConf->hifType == WMT_HIF_UART) { + /* 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] = (UINT8) 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] = (UINT8) 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; + } + 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; + } + 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 (pWmtHifConf->hifType == WMT_HIF_UART) { + /* 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_sleep_ms(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] = (UINT8) pWmtHifConf->au4StrapConf[0]; + WMT_STRAP_CONF_EVT[5] = (UINT8) pWmtHifConf->au4StrapConf[0]; + iRet = wmt_core_init_script(init_table_5_1, osal_array_size(init_table_5_1)); + if (iRet) { + WMT_ERR_FUNC("init_table_5_1 fm mode(%d) fail(%d)\n", + pWmtHifConf->au4StrapConf[0], iRet); + return -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(gp_mt6620_info != NULL); + if (gp_mt6620_info != NULL) { + if (gp_mt6620_info->bPsmSupport != MTK_WCN_BOOL_FALSE) + 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; + UINT8 evtBuf[256]; + ULONG ctrlPa1; + ULONG ctrlPa2; + UINT32 hw_ver; + UINT32 patch_num = 0; + UINT32 patch_index = 0; + WMT_CTRL_DATA ctrlData; + + WMT_DBG_FUNC(" start\n"); + + osal_assert(gp_mt6620_info != NULL); + if ((gp_mt6620_info == NULL) + || (pWmtHifConf == NULL) + ) { + 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 (pWmtHifConf->hifType == WMT_HIF_SDIO) { + /* 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 (pWmtHifConf->hifType == WMT_HIF_UART) { + + /* 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 (pWmtHifConf->uartFcCtrl == WMT_UART_MTK_SW_FC) { + WMT_INFO_FUNC("enable MTK SW Flow Control\n"); + WMT_SET_BAUD_CMD_X[8] = (UINT8) 0x80; /* MTK SW flow control */ + WMT_QUERY_BAUD_EVT_X[9] = (UINT8) 0x80; /* MTK SW flow control */ + } else if (pWmtHifConf->uartFcCtrl == WMT_UART_LUX_SW_FC) { + WMT_INFO_FUNC("enable Linux SW Flow Control\n"); + WMT_SET_BAUD_CMD_X[8] = (UINT8) 0x80; /* Linux SW flow control */ + WMT_QUERY_BAUD_EVT_X[9] = (UINT8) 0x80; /* Linux SW flow control */ + } else if (pWmtHifConf->uartFcCtrl == WMT_UART_HW_FC) { + WMT_INFO_FUNC("enable HW Flow Control\n"); + WMT_SET_BAUD_CMD_X[8] = (UINT8) 0xC0; /* HW flow control */ + WMT_QUERY_BAUD_EVT_X[9] = (UINT8) 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] = (UINT8) 0x00; /* no flow control */ + WMT_QUERY_BAUD_EVT_X[9] = (UINT8) 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 (pWmtHifConf->hifType == WMT_HIF_UART) { + /* 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_sleep_ms(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; + } + 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; + } + 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] = (UINT8) pWmtHifConf->au4StrapConf[0]; + WMT_STRAP_CONF_EVT[5] = (UINT8) pWmtHifConf->au4StrapConf[0]; + iRet = wmt_core_init_script(init_table_5_1, osal_array_size(init_table_5_1)); + if (iRet) { + WMT_ERR_FUNC("init_table_5_1 fm mode(%d) fail(%d)\n", + pWmtHifConf->au4StrapConf[0], iRet); + return -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 (mtk_wcn_stp_coredump_flag_get() != 0) { + 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; + } + WMT_INFO_FUNC("enable mt662x firmware coredump\n"); + } else + WMT_INFO_FUNC("disable mt662x firmware coredump\n"); + +#if 1 + ctrlData.ctrlId = WMT_CTRL_SET_STP_DBG_INFO; + ctrlData.au4CtrlData[0] = wmt_ic_ops_mt6620.icId; + ctrlData.au4CtrlData[1] = (size_t) gp_mt6620_info->cChipVersion; + ctrlData.au4CtrlData[2] = (size_t) &gp_mt6620_patch_info; + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + WMT_ERR_FUNC("set dump info fail(%d)\n", iRet); + return -16; + } +#endif + +#if CFG_WMT_PS_SUPPORT + osal_assert(gp_mt6620_info != NULL); + if (gp_mt6620_info != NULL) { + if (gp_mt6620_info->bPsmSupport != MTK_WCN_BOOL_FALSE) + 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(gp_mt6620_info != NULL); + if ((gp_mt6620_info != NULL) + && (gp_mt6620_info->bPsmSupport != MTK_WCN_BOOL_FALSE)) { + 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); + break; + 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 MTK_WCN_BOOL mt6620_aee_dump_flag_get(VOID) +{ + return MTK_WCN_BOOL_TRUE; +} + + +static INT32 mt6620_ver_check(VOID) +{ + UINT32 hw_ver = 0; + UINT32 fw_ver = 0; + INT32 iret; + const WMT_IC_INFO_S *p_info = NULL; + ULONG ctrlPa1; + ULONG 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 (p_info == NULL) { + WMT_ERR_FUNC("MT6620: hw_ver(0x%x) find wmt ic info fail\n", hw_ver); + return -3; + } + + WMT_INFO_FUNC("MT6620: wmt ic info: %s.%s (0x%x, patch_ext:%s)\n", + p_info->cChipName, p_info->cChipVersion, + p_info->u4HwVer, p_info->cPatchNameExt); + + /* hw id & version */ + ctrlPa1 = (0x00006620UL << 16) | (hw_ver & 0x0000FFFF); + /* translated fw rom version */ + ctrlPa2 = (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 ((index >= 0) + && (hw_ver != mt6620_info_table[index].u4HwVer) /* full match */ + ) { + --index; + } + if (index >= 0) { + 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 ((index >= 0) + && (MAJORNUM(hw_ver) != MAJORNUM(mt6620_info_table[index].u4HwVer)) + ) { + --index; + } + if (index >= 0) { + 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; + ULONG addr = 0; + WMT_GEN_CONF *pWmtGenConf = NULL; + +#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\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, ARRAY_SIZE(coex_table)); + + 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]; + UINT8 addressByte[4]; + PINT8 cDataTime = NULL; + /*PINT8 cPlat = NULL; */ + UINT16 u2HwVer = 0; + UINT16 u2SwVer = 0; + UINT32 u4PatchVer = 0; + UINT32 patchSizePerFrag = 0; + WMT_CTRL_DATA ctrlData; + + /*1.check hardware information */ + if (gp_mt6620_info == NULL) { + 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] = (size_t) &gFullPatchName; + ctrlData.au4CtrlData[2] = (size_t) &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] = (size_t) NULL; + ctrlData.au4CtrlData[1] = (size_t) &gFullPatchName; + + ctrlData.au4CtrlData[2] = (size_t) &pbuf; + ctrlData.au4CtrlData[3] = (size_t) &patchSize; + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + WMT_ERR_FUNC("wmt_core: WMT_CTRL_GET_PATCH fail:%d\n", iRet); + iRet -= 1; + goto done; + } + + /* |<-BCNT_PATCH_BUF_HEADROOM(8) bytes dummy allocated->|<-patch file->| */ + pbuf += BCNT_PATCH_BUF_HEADROOM; + /* patch file with header: + * |<-patch header: 28 Bytes->|<-patch body: X Bytes ----->| + */ + patchHdr = (P_WMT_PATCH) pbuf; + /* check patch file information */ + + cDataTime = patchHdr->ucDateTime; + u2HwVer = patchHdr->u2HwVer; + u2SwVer = patchHdr->u2SwVer; + u4PatchVer = patchHdr->u4PatchVer; + /*cPlat = &patchHdr->ucPLat[0]; */ + cDataTime[15] = '\0'; + + /* remove patch header: + * |<-patch body: X Bytes (X=patchSize)--->| + */ + if (patchSize < sizeof(WMT_PATCH)) { + WMT_ERR_FUNC("error patch size\n"); + iRet = -1; + goto done; + } + 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)----->| + */ + osal_memcpy(&gp_mt6620_patch_info, patchHdr, osal_sizeof(WMT_PATCH)); + pbuf -= sizeof(WMT_PATCH_CMD); + + fragNum = patchSize / patchSizePerFrag; + fragNum += ((fragNum * patchSizePerFrag) == patchSize) ? 0 : 1; + + WMT_DBG_FUNC("patch size(%d) fragNum(%d)\n", patchSize, fragNum); + + /*send wmt part patch address command */ + 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(%zu, %d) fail(%d)\n", fragSeq, + fragSize + sizeof(WMT_PATCH_CMD), u4Res, iRet); + iRet = -4; + break; + } + WMT_DBG_FUNC("wmt_core: write fragSeq(%d) size(%zu, %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(%zu, %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("rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%zu):[%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(%zu, %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 (gp_mt6620_info->bWorkWithoutPatch != MTK_WCN_BOOL_FALSE) + 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]; + PINT8 cDataTime = NULL; + /*PINT8 cPlat = NULL; */ + UINT16 u2HwVer = 0; + UINT16 u2SwVer = 0; + UINT32 u4PatchVer = 0; + UINT32 patchSizePerFrag = 0; + WMT_CTRL_DATA ctrlData; + + /*1.check hardware information */ + if (gp_mt6620_info == NULL) { + 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 (iRet == 0) { + /* patch with correct Hw Ver Major Num found */ + ctrlData.ctrlId = WMT_CTRL_GET_PATCH_NAME; + ctrlData.au4CtrlData[0] = (size_t) &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] = (size_t) NULL; + ctrlData.au4CtrlData[1] = (size_t) &gFullPatchName; + + } else { + iRet -= 1; + return iRet; + } + ctrlData.au4CtrlData[2] = (size_t) &pbuf; + ctrlData.au4CtrlData[3] = (size_t) &patchSize; + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + WMT_ERR_FUNC("wmt_core: WMT_CTRL_GET_PATCH fail:%d\n", iRet); + iRet -= 1; + goto done; + } +#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)--->| + */ + if (patchSize < sizeof(WMT_PATCH)) { + WMT_ERR_FUNC("error patch size\n"); + return -1; + } + 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)----->| + */ + osal_memcpy(&gp_mt6620_patch_info, patchHdr, osal_sizeof(WMT_PATCH)); + pbuf -= sizeof(WMT_PATCH_CMD); + + fragNum = patchSize / patchSizePerFrag; + fragNum += ((fragNum * patchSizePerFrag) == patchSize) ? 0 : 1; + + WMT_DBG_FUNC("patch size(%d) fragNum(%d)\n", patchSize, fragNum); + + + /* send 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("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 (gp_mt6620_info->bWorkWithoutPatch != MTK_WCN_BOOL_FALSE) + iRet = 0; + } + + return iRet; +} + +static INT32 mt6620_update_patch_name(VOID) +{ + INT32 len; + UINT8 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 (gp_mt6620_info == NULL) { + 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/misc/mediatek/connectivity/common/common_main/core/wmt_ic_6628.c b/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_ic_6628.c new file mode 100644 index 0000000000000..68b5336e30220 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_ic_6628.c @@ -0,0 +1,1981 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ +/*! \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) +/* BT Port 2 Feature. this command does not need after coex command is downconfirmed by LC, */ +#define CFG_WMT_BT_PORT2 (0) + +#define CFG_SET_OPT_REG (0) +#define CFG_WMT_I2S_DBGUART_SUPPORT (0) +#define CFG_SET_OPT_REG_SWLA (0) +#define CFG_SET_OPT_REG_MCUCLK (0) +#define CFG_SET_OPT_REG_MCUIRQ (0) + +#define CFG_SUBSYS_COEX_NEED 0 + +#define CFG_WMT_COREDUMP_ENABLE 0 + +#define CFG_WMT_MULTI_PATCH (1) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +static UINT8 gFullPatchName[NAME_MAX + 1]; +static const WMT_IC_INFO_S *gp_mt6628_info; +static WMT_PATCH gp_mt6628_patch_info; +static WMT_CO_CLOCK gCoClockEn = WMT_CO_CLOCK_DIS; +#if 0 +static UINT8 WMT_WAKEUP_DIS_GATE_CMD[] = { 0x1, 0x3, 0x01, 0x00, 0x04 }; +static UINT8 WMT_WAKEUP_DIS_GATE_EVT[] = { 0x2, 0x3, 0x02, 0x0, 0x0, 0x04 }; + +static UINT8 WMT_WAKEUP_EN_GATE_CMD[] = { 0x1, 0x3, 0x01, 0x00, 0x05 }; +static UINT8 WMT_WAKEUP_EN_GATE_EVT[] = { 0x2, 0x3, 0x02, 0x0, 0x0, 0x05 }; +#endif + +static UINT8 WMT_QUERY_BAUD_CMD[] = { 0x01, 0x04, 0x01, 0x00, 0x02 }; +static UINT8 WMT_QUERY_BAUD_EVT_115200[] = { 0x02, 0x04, 0x06, 0x00, 0x00, 0x02, 0x00, 0xC2, 0x01, 0x00 }; +static UINT8 WMT_QUERY_BAUD_EVT_X[] = { 0x02, 0x04, 0x06, 0x00, 0x00, 0x02, 0xAA, 0xAA, 0xAA, 0xBB }; +static UINT8 WMT_QUERY_STP_CMD[] = { 0x01, 0x04, 0x01, 0x00, 0x04 }; +static UINT8 WMT_QUERY_STP_EVT_DEFAULT[] = { 0x02, 0x04, 0x06, 0x00, 0x00, 0x04, 0x11, 0x00, 0x00, 0x00 }; +static UINT8 WMT_QUERY_STP_EVT_UART[] = { 0x02, 0x04, 0x06, 0x00, 0x00, 0x04, 0xDF, 0x0E, 0x68, 0x01 }; +static UINT8 WMT_SET_BAUD_CMD_X[] = { 0x01, 0x04, 0x05, 0x00, 0x01, 0xAA, 0xAA, 0xAA, 0xBB }; +static UINT8 WMT_SET_BAUD_EVT[] = { 0x02, 0x04, 0x02, 0x00, 0x00, 0x01 }; +static UINT8 WMT_SET_WAKEUP_WAKE_CMD_RAW[] = { 0xFF }; +static UINT8 WMT_SET_WAKEUP_WAKE_EVT[] = { 0x02, 0x03, 0x02, 0x00, 0x00, 0x03 }; +static UINT8 WMT_PATCH_CMD[] = { 0x01, 0x01, 0x00, 0x00, 0x00 }; +static UINT8 WMT_PATCH_EVT[] = { 0x02, 0x01, 0x01, 0x00, 0x00 }; +static UINT8 WMT_RESET_CMD[] = { 0x01, 0x07, 0x01, 0x00, 0x04 }; +static UINT8 WMT_RESET_EVT[] = { 0x02, 0x07, 0x01, 0x00, 0x00 }; + +#if CFG_WMT_BT_PORT2 +static UINT8 WMT_BTP2_CMD[] = { 0x01, 0x10, 0x03, 0x00, 0x01, 0x03, 0x01 }; +static UINT8 WMT_BTP2_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; +#endif + +#if CFG_WMT_MULTI_PATCH +static UINT8 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 UINT8 WMT_PATCH_ADDRESS_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; + +static UINT8 WMT_PATCH_P_ADDRESS_CMD[] = { 0x01, 0x08, 0x10, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x48, 0x03, 0x09, 0xF0, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff +}; +static UINT8 WMT_PATCH_P_ADDRESS_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; +#endif + +/*coex cmd/evt++*/ +static UINT8 WMT_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x02, 0x00, 0x01, 0x00 }; +static UINT8 WMT_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +#if CFG_SUBSYS_COEX_NEED +static UINT8 WMT_BT_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x0B, + 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, + 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xAA +}; +static UINT8 WMT_BT_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_WIFI_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x0C, + 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xAA +}; +static UINT8 WMT_WIFI_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_PTA_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x0A, + 0x00, 0x04, + 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xEE, 0xFF, 0xFF, 0xFE +}; +static UINT8 WMT_PTA_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_MISC_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x09, + 0x00, 0x05, + 0xAA, 0xAA, 0xAA, 0xAA, + 0xBB, 0xBB, 0xBB, 0xBB +}; +static UINT8 WMT_MISC_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; +#endif + +/*coex cmd/evt--*/ +static UINT8 WMT_SET_STP_CMD[] = { 0x01, 0x04, 0x05, 0x00, 0x03, 0xDF, 0x0E, 0x68, 0x01 }; +static UINT8 WMT_SET_STP_EVT[] = { 0x02, 0x04, 0x02, 0x00, 0x00, 0x03 }; +static UINT8 WMT_STRAP_CONF_CMD_FM_COMM[] = { 0x01, 0x05, 0x02, 0x00, 0x02, 0x02 }; +static UINT8 WMT_STRAP_CONF_EVT[] = { 0x02, 0x05, 0x02, 0x00, 0x00, 0x02 }; + +#if 0 +static UINT8 WMT_SET_OSC32K_BYPASS_CMD[] = { 0x01, 0x0A, 0x01, 0x00, 0x05 }; +static UINT8 WMT_SET_OSC32K_BYPASS_EVT[] = { 0x02, 0x0A, 0x01, 0x00, 0x00 }; +#endif + +#if 0 +/* to enable dump feature */ +static UINT8 WMT_CORE_DUMP_EN_CMD[] = { 0x01, 0x0F, 0x02, 0x00, 0x03, 0x01 }; +static UINT8 WMT_CORE_DUMP_EN_EVT[] = { 0x02, 0x0F, 0x01, 0x00, 0x00 }; + +/* to get system stack dump when f/w assert */ +static UINT8 WMT_CORE_DUMP_LEVEL_01_CMD[] = { 0x1, 0x0F, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static UINT8 WMT_CORE_DUMP_LEVEL_01_EVT[] = { 0x2, 0x0F, 0x01, 0x00, 0x00 }; + +/* to get task and system stack dump when f/w assert */ +static UINT8 WMT_CORE_DUMP_LEVEL_02_CMD[] = { 0x1, 0x0F, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static UINT8 WMT_CORE_DUMP_LEVEL_02_EVT[] = { 0x2, 0x0F, 0x01, 0x00, 0x00 }; + +/* to get bt related memory dump when f/w assert */ +static UINT8 WMT_CORE_DUMP_LEVEL_03_CMD[] = { 0x1, 0x0F, 0x07, 0x00, 0x03, 0x00, 0x00, 0x09, 0xF0, 0x00, 0x0A }; +static UINT8 WMT_CORE_DUMP_LEVEL_03_EVT[] = { 0x2, 0x0F, 0x01, 0x00, 0x00 }; +#endif +/* to get full dump when f/w assert */ +static UINT8 WMT_CORE_DUMP_LEVEL_04_CMD[] = { 0x1, 0x0F, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static UINT8 WMT_CORE_DUMP_LEVEL_04_EVT[] = { 0x2, 0x0F, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_CORE_CO_CLOCK_CMD[] = { 0x1, 0x0A, 0x02, 0x00, 0x08, 0x03 }; +static UINT8 WMT_CORE_CO_CLOCK_EVT[] = { 0x2, 0x0A, 0x01, 0x00, 0x00 }; + + +#if (MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT) +static UINT8 WMT_SET_I2S_SLAVE_REG_CMD[] = { 0x01, 0x08, 0x10, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ + , 0x78, 0x00, 0x05, 0x80 /*addr:0x80050078 */ + , 0x00, 0x00, 0x11, 0x01 /*value:0x11010000 */ + , 0x00, 0x00, 0x77, 0x07 /*mask:0x07770000 */ +}; + +static UINT8 WMT_SET_I2S_SLAVE_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ +}; + +static UINT8 WMT_SET_DAI_TO_PAD_REG_CMD[] = { 0x01, 0x08, 0x10, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ + , 0x74, 0x00, 0x05, 0x80 /*addr:0x80050074 */ + , 0x44, 0x44, 0x00, 0x00 /*value:0x11010000 */ + , 0x77, 0x77, 0x00, 0x00 /*mask:0x07770000 */ +}; + +static UINT8 WMT_SET_DAI_TO_PAD_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ +}; + +static UINT8 WMT_SET_DAI_REG_CMD[] = { 0x01, 0x08, 0x10, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ + , 0xA0, 0x00, 0x05, 0x80 /*addr:0x80050074 */ + , 0x04, 0x00, 0x00, 0x00 /*value:0x11010000 */ + , 0x04, 0x00, 0x00, 0x00 /*mask:0x07770000 */ +}; + +static UINT8 WMT_SET_DAI_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ +}; +#endif + + +#ifndef CFG_IC_MT6628 /* For MT6628 no need to set ALLEINT registers, done in f/w */ +/* enable all interrupt */ +static UINT8 WMT_SET_ALLINT_REG_CMD[] = { 0x01, 0x08, 0x10, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ + , 0x00, 0x03, 0x05, 0x80 /*addr:0x80050300 */ + , 0x00, 0xC4, 0x00, 0x00 /*value:0x0000C400 */ + , 0x00, 0xC4, 0x00, 0x00 /*mask:0x0000C400 */ +}; + +static UINT8 WMT_SET_ALLINT_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ +}; + +#endif + +#if CFG_SET_OPT_REG_SWLA /* enable swla: eesk(7) eecs(8) oscen(19) sck0(24) scs0(25) */ +static UINT8 WMT_SET_SWLA_REG_CMD[] = { 0x01, 0x08, 0x1C, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x02 /*2 registers */ + , 0x10, 0x01, 0x05, 0x80 /*addr:0x80050110 */ + , 0x10, 0x10, 0x01, 0x00 /*value:0x00011010 */ + , 0xF0, 0xF0, 0x0F, 0x00 /*mask:0x000FF0F0 */ + , 0x40, 0x01, 0x05, 0x80 /*addr:0x80050140 */ + , 0x00, 0x10, 0x01, 0x00 /*value:0x00011000 */ + , 0x00, 0xF0, 0x0F, 0x00 /*mask:0x000FF000 */ +}; + +static UINT8 WMT_SET_SWLA_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x02 /*2 registers */ +}; +#endif + +#if CFG_SET_OPT_REG_MCUCLK /* enable mcu clk: antsel_4, eedi */ +static UINT8 WMT_SET_MCUCLK_REG_CMD[] = { 0x01, 0x08, (4 + 12 * 4), 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /* type: reg */ + , 0x00 /* rev */ + , 0x04 /* 4 registers */ + , 0x00, 0x04, 0x00, 0x80 /* addr:0x8000 0400 */ + , 0x00, 0x14, 0x00, 0x00 /* value:0x0000 1400(osc, hclk), 0x0000 1501(PLL, en) */ + , 0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000 FFFF */ + , 0x80, 0x01, 0x05, 0x80 /* addr:0x8005 0180 */ + , 0x12, 0x13, 0x00, 0x00 /* value:0x0000 1312(osc, hclk), 0x0000 1a19(PLL, en) */ + , 0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000 FFFF */ + , 0x00, 0x01, 0x05, 0x80 /* addr:0x8005 0100 */ + , 0x00, 0x00, 0x02, 0x00 /* value:0x0002 0000 */ + , 0x00, 0x00, 0x0F, 0x00 /* mask:0x000F 0000 */ + , 0x10, 0x01, 0x05, 0x80 /* addr:0x8005 0110 */ + , 0x02, 0x00, 0x00, 0x00 /* value:0x0000 0002 */ + , 0x0F, 0x00, 0x00, 0x00 /* mask:0x0000 000F */ +}; + +static UINT8 WMT_SET_MCUCLK_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /* S: 0 */ + , 0x00 /* type: reg */ + , 0x00 /* rev */ + , 0x04 /* 4 registers */ +}; +#endif + +#if CFG_WMT_I2S_DBGUART_SUPPORT /* register write for debug uart */ +static UINT8 WMT_SET_DBGUART_REG_CMD[] = { 0x01, 0x08, 0x1C, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x02 /*2 registers */ + , 0x30, 0x01, 0x05, 0x80 /*addr:0x80050130 */ + , 0x00, 0x00, 0x00, 0x00 /*value:0x00000000 */ + , 0xF0, 0x0F, 0x00, 0x00 /*mask:0x00000FF0 */ + , 0x40, 0x01, 0x05, 0x80 /*addr:0x80050140 */ + , 0x00, 0x01, 0x00, 0x00 /*value:0x00000100 */ + , 0x00, 0x01, 0x00, 0x00 /*mask:0x00000100 */ +}; + +static UINT8 WMT_SET_DBGUART_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x02 /*2 registers */ +}; +#endif + +#if CFG_SET_OPT_REG_MCUIRQ /* enable mcu irq: antsel_4, wlan_act */ +#if 1 /* Ray */ +static UINT8 WMT_SET_MCUIRQ_REG_CMD[] = { 0x01, 0x08, (4 + 12 * 4), 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /* type: reg */ + , 0x00 /* rev */ + , 0x04 /* 4 registers */ + , 0x00, 0x04, 0x00, 0x80 /* addr:0x8000_0400 */ + , 0x03, 0x14, 0x00, 0x00 /* value:0x0000_1403 check confg debug flag 3 low word */ + , 0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000_FFFF */ + /* cirq_int_n */ + , 0x10, 0x01, 0x05, 0x80 /* addr:0x8005_0110 */ + , 0x02, 0x00, 0x00, 0x00 /* value:0x0000_0002 set EEDI as cirq_int_n debug flag (monitor flag2) */ + , 0x07, 0x00, 0x00, 0x00 /* mask:0x0000_0007 */ + , 0x00, 0x01, 0x05, 0x80 /* addr:0x8005_0100 */ + , 0x00, 0x00, 0x02, 0x00 /* value:0x0002_0000 (ANTSEL4=>monitor flag 0, ahb_x2_gt_ck debug flag) */ + , 0x00, 0x00, 0x07, 0x00 /* mask:0x0007_0000 */ + /* 1. ARM irq_b, monitor flag 0 */ + , 0x80, 0x01, 0x05, 0x80 /* addr:0x8005_0180 */ + , 0x1F, 0x1E, 0x00, 0x00 /* value:0x0000_1E1F check mcusys debug flag */ + , 0x7F, 0x7F, 0x00, 0x00 /* mask:0x0000_7F7F */ +}; + +static UINT8 WMT_SET_MCUIRQ_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /* S: 0 */ + , 0x00 /* type: reg */ + , 0x00 /* rev */ + , 0x04 /* 5 registers */ +}; +#elif 0 /* KC */ +static UINT8 WMT_SET_MCUIRQ_REG_CMD[] = { 0x01, 0x08, (4 + 12 * 5), 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /* type: reg */ + , 0x00 /* rev */ + , 0x05 /* 5 registers */ + , 0x00, 0x04, 0x00, 0x80 /* addr:0x8000_0400 */ + , 0x00, 0x02, 0x00, 0x00 /* value:0x0000_0200 [15:8]=0x2 arm irq_b, 0xA irq_bus[5] bt_timcon_irq_b */ + , 0x00, 0xFF, 0x00, 0x00 /* mask:0x0000_FF00 */ + /* 1. ARM irq_b, monitor flag 0 */ + , 0x80, 0x01, 0x05, 0x80 /* addr:0x8005_0180 */ + , 0x18, 0x00, 0x00, 0x00 /* value:0x0000_0018 [6:0]=001_1000 (monitor flag 0 select, MCUSYS, SEL:8) */ + , 0x7F, 0x00, 0x00, 0x00 /* mask:0x0000_007F */ + , 0x00, 0x01, 0x05, 0x80 /* addr:0x8005_0100 */ + , 0x00, 0x00, 0x02, 0x00 /* value:0x0002_0000 (ANTSEL4=>monitor flag 0) */ + , 0x00, 0x00, 0x07, 0x00 /* mask:0x0007_0000 */ + /* 2. irq_bus[5] bt_timcon_irq_b monitor flag 15 */ + , 0xB0, 0x01, 0x05, 0x80 /* addr:0x8005_01B0 */ + , 0x00, 0x00, 0x00, 0x16 /* value:0x1600_0000 [30:24]=001_0110 (monitor flag 15 select, MCUSYS, SEL:6) */ + , 0x00, 0x00, 0x00, 0x7F /* mask:0x7F00_0000 */ + , 0x30, 0x01, 0x05, 0x80 /* addr:0x8005_0130 */ + , 0x00, 0x20, 0x00, 0x00 /* value:0x0000_2000 (WLAN_ACT=>monitor flag 15) */ + , 0x00, 0x70, 0x00, 0x00 /* mask:0x0000_7000 */ +}; + +static UINT8 WMT_SET_MCUIRQ_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /* S: 0 */ + , 0x00 /* type: reg */ + , 0x00 /* rev */ + , 0x05 /* 5 registers */ +}; +#endif +#endif + +static UINT8 WMT_SET_CRYSTAL_TRIMING_CMD[] = { 0x01, 0x12, 0x02, 0x00, 0x01, 0x00 }; +static UINT8 WMT_SET_CRYSTAL_TRIMING_EVT[] = { 0x02, 0x12, 0x02, 0x00, 0x01, 0x00 }; + +static UINT8 WMT_GET_CRYSTAL_TRIMING_CMD[] = { 0x01, 0x12, 0x02, 0x00, 0x00, 0x00 }; +static UINT8 WMT_GET_CRYSTAL_TRIMING_EVT[] = { 0x02, 0x12, 0x02, 0x00, 0x00, 0x00 }; + +/* set sdio driving */ +static UINT8 WMT_SET_SDIO_DRV_REG_CMD[] = { 0x01, 0x08, 0x10, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ + , 0x50, 0x00, 0x05, 0x80 /*addr:0x80050050 */ + , 0x44, 0x44, 0x04, 0x00 /*value:0x00044444 */ + , 0x77, 0x77, 0x07, 0x00 /*mask:0x00077777 */ +}; + +static UINT8 WMT_SET_SDIO_DRV_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ +}; + + +#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, + .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, + .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, + .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, + .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, + .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 */ +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, + .trigger_stp_assert = NULL, + .deep_sleep_ctrl = NULL, +}; + +/******************************************************************************* +* 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; + UINT8 evtBuf[256]; + unsigned long ctrlPa1; + unsigned long ctrlPa2; + UINT32 hw_ver; +#if CFG_WMT_MULTI_PATCH + UINT32 patch_num = 0; + UINT32 patch_index = 0; +#endif + WMT_CTRL_DATA ctrlData; + + WMT_DBG_FUNC(" start\n"); + + osal_assert(gp_mt6628_info != NULL); + if ((gp_mt6628_info == NULL) + || (pWmtHifConf == NULL) + ) { + 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 (pWmtHifConf->hifType == WMT_HIF_SDIO) { + 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, 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 (pWmtHifConf->hifType == WMT_HIF_UART) { + /* 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] = (UINT8) 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] = (UINT8) 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, 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, 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, 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, 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; + } + WMT_INFO_FUNC("init_coex ok\n"); + + mt6628_crystal_triming_set(); + + mt6628_set_sdio_driving(); + + if (pWmtHifConf->hifType == WMT_HIF_UART) { + /* 11. Set chip STP options */ + iRet = wmt_core_init_script(init_table_4, 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_sleep_ms(10); + /* 14. Query chip STP options (TEST-ONLY) */ + /* 15. Query baud rate (stp, TEST-ONLY) */ + iRet = wmt_core_init_script(init_table_5, ARRAY_SIZE(init_table_5)); + if (iRet) { + WMT_ERR_FUNC("init_table_5 fail(%d)\n", iRet); + return -14; + } + } + + if (mt6628_co_clock_get() == WMT_CO_CLOCK_EN) { + WMT_INFO_FUNC("co-clock enabled.\n"); + + iRet = wmt_core_init_script(osc_type_table, 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, 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] = (UINT8) pWmtHifConf->au4StrapConf[0]; + WMT_STRAP_CONF_EVT[5] = (UINT8) pWmtHifConf->au4StrapConf[0]; + iRet = wmt_core_init_script(init_table_5_1, 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, 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 (mtk_wcn_stp_coredump_flag_get() != 0) { + iRet = wmt_core_init_script(init_table_6, ARRAY_SIZE(init_table_6)); + if (iRet) { + WMT_ERR_FUNC("init_table_6 core dump setting fail(%d)\n", iRet); + return -18; + } + WMT_INFO_FUNC("enable mt662x firmware coredump\n"); + } else + WMT_INFO_FUNC("disable mt662x firmware coredump. hifType: %d\n", + pWmtHifConf->hifType); + +#if 1 + ctrlData.ctrlId = WMT_CTRL_SET_STP_DBG_INFO; + ctrlData.au4CtrlData[0] = wmt_ic_ops_mt6628.icId; + ctrlData.au4CtrlData[1] = (size_t) gp_mt6628_info->cChipVersion; + ctrlData.au4CtrlData[2] = (size_t) &gp_mt6628_patch_info; + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + WMT_ERR_FUNC("set dump info fail(%d)\n", iRet); + return -16; + } +#endif + +#if CFG_WMT_PS_SUPPORT + if (pWmtHifConf->hifType == WMT_HIF_UART) { + osal_assert(gp_mt6628_info != NULL); + if (gp_mt6628_info != NULL) { + if (gp_mt6628_info->bPsmSupport != MTK_WCN_BOOL_FALSE) + wmt_lib_ps_enable(); + else + wmt_lib_ps_disable(); + } + } else if (pWmtHifConf->hifType == WMT_HIF_SDIO) { + /* COMMON SDIO is used different PS from UART, so disable current ps support + * Note: using wmt_lib_ps_ctrl() due to wmt_lib_ps_disable() cannot clear gPsEnable setting + */ + wmt_lib_ps_ctrl(0); + } +#endif + + return 0; +} + +static INT32 mt6628_sw_deinit(P_WMT_HIF_CONF pWmtHifConf) +{ + WMT_DBG_FUNC(" start\n"); + +#if CFG_WMT_PS_SUPPORT + if (pWmtHifConf->hifType == WMT_HIF_UART) { + osal_assert(gp_mt6628_info != NULL); + if ((gp_mt6628_info != NULL) + && (gp_mt6628_info->bPsmSupport != MTK_WCN_BOOL_FALSE)) { + 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); + + break; + default: + WMT_ERR_FUNC("unsupported state (%d)\n", state); + ret = -1; + break; + } +#else + switch (state) { + case WMT_IC_AIF_0: + /* BT_PCM_OFF & FM line in/out */ + ret = 0; + break; + case WMT_IC_AIF_1: + /* BT_PCM_ON & FM line in/out */ + ret = 0; + break; + + case WMT_IC_AIF_2: + /* BT_PCM_OFF & FM I2S */ + val = 0x01110000; + ret = wmt_core_reg_rw_raw(1, 0x80050078, &val, 0x0FFF0000); + + break; + case WMT_IC_AIF_3: + ret = 0; + break; + + default: + WMT_ERR_FUNC("unsupported state (%d)\n", state); + ret = -1; + break; + } +#endif + } + + if (!ret) + WMT_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 ret = -1; + UINT32 uVal = 0; + + if (state == WMT_IC_PIN_MUX) + uVal = 0x1 << 28; + else + uVal = 0x5 << 28; + ret = wmt_core_reg_rw_raw(1, 0x80050078, &uVal, 0x7 << 28); + if (ret != 0) + WMT_ERR_FUNC("gps_sync pin ctrl failed, ret(%d)\n", ret); + /* 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 ((on >= WMT_CO_CLOCK_DIS) && (on < WMT_CO_CLOCK_MAX)) + 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 = 0; + UINT32 fw_ver = 0; + INT32 iret; + const WMT_IC_INFO_S *p_info = NULL; + unsigned long ctrlPa1; + unsigned long 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 (p_info == NULL) { + WMT_ERR_FUNC("MT6628: hw_ver(0x%x) find wmt ic info fail\n", hw_ver); + return -3; + } + + WMT_INFO_FUNC("MT6628: wmt ic info: %s.%s (0x%x, patch_ext:%s)\n", + p_info->cChipName, p_info->cChipVersion, + p_info->u4HwVer, p_info->cPatchNameExt); + + /* hw id & version */ + ctrlPa1 = (0x00006628UL << 16) | (hw_ver & 0x0000FFFF); + /* translated fw rom version */ + ctrlPa2 = (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 = 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 ((index >= 0) + && (hw_ver != mt6628_info_table[index].u4HwVer) /* full match */ + ) { + --index; + } + if (index >= 0) { + 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 ((index >= 0) + && (MAJORNUM(hw_ver) != MAJORNUM(mt6628_info_table[index].u4HwVer)) + ) { + --index; + } + if (index >= 0) { + 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; + ULONG addr = 0; + WMT_GEN_CONF *pWmtGenConf = NULL; + +#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, ARRAY_SIZE(coex_table)); + + return iRet; +} + + +static INT32 mt6628_set_sdio_driving(VOID) +{ + INT32 ret = 0; + + ULONG addr = 0; + WMT_GEN_CONF *pWmtGenConf = NULL; + 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%8lx)\n", addr); + + pWmtGenConf = (P_WMT_GEN_CONF) addr; + + /*Check if WMT.cfg exists */ + if (pWmtGenConf->cfgExist == 0) { + WMT_INFO_FUNC("cfgExist == 0, skip config chip\n"); + /*if WMT.cfg not existed, still return success and adopt the default value */ + return 0; + } + + drv_val = pWmtGenConf->sdio_driving_cfg; + + /*Dump the sdio driving related info */ + WMT_INFO_FUNC("sdio driving:0x%x\n", drv_val); + + sdio_driving_table[0].cmd[12] = (UINT8) ((drv_val & 0x00000077UL) >> 0); /* DAT0 and DAT1 */ + sdio_driving_table[0].cmd[13] = (UINT8) ((drv_val & 0x00007700UL) >> 8); /* DAT2 and DAT3 */ + sdio_driving_table[0].cmd[14] = (UINT8) ((drv_val & 0x00070000UL) >> 16); /* CMD */ + + ret = wmt_core_init_script(sdio_driving_table, ARRAY_SIZE(sdio_driving_table)); + + 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; + INT8 cCrystalTimingOffset = 0x0; + UINT8 cCrystalTiming = 0x0; + INT32 iCrystalTiming = 0x0; + MTK_WCN_BOOL bIsCrysTrimEnabled = MTK_WCN_BOOL_FALSE; + UINT32 u4Res; + + bIsNvramExist = MTK_WCN_BOOL_FALSE; + ctrlData.ctrlId = WMT_CTRL_CRYSTAL_TRIMING_GET; + ctrlData.au4CtrlData[0] = (size_t) "/data/nvram/APCFG/APRDEB/WIFI"; + ctrlData.au4CtrlData[1] = (size_t) &pbuf; + ctrlData.au4CtrlData[2] = (size_t) &bufLen; + + iRet = wmt_ctrl(&ctrlData); + if (iRet != 0) { + 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(%p), 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 = (UINT8) cCrystalTimingOffset & 0x7f; + } + WMT_DBG_FUNC("cCrystalTimingOffset (%d), bIsCrysTrimEnabled(%d)\n", + cCrystalTimingOffset, bIsCrysTrimEnabled); + } + ctrlData.ctrlId = WMT_CTRL_CRYSTAL_TRIMING_PUT; + ctrlData.au4CtrlData[0] = (size_t) "/data/nvram/APCFG/APRDEB/WIFI"; + iRet = wmt_ctrl(&ctrlData); + if (iRet != 0) { + 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 ((bIsNvramExist == MTK_WCN_BOOL_TRUE) && (bIsCrysTrimEnabled == MTK_WCN_BOOL_TRUE)) { + /*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); + if (iCrystalTiming > 0x7f) + cCrystalTiming = 0x7f; + else if (iCrystalTiming < 0) + cCrystalTiming = 0; + else + cCrystalTiming = 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]; + UINT8 addressByte[4]; + PINT8 cDataTime = NULL; + /*PINT8 cPlat = NULL; */ + UINT16 u2HwVer = 0; + UINT16 u2SwVer = 0; + UINT32 u4PatchVer = 0; + UINT32 patchSizePerFrag = 0; + WMT_CTRL_DATA ctrlData; + + /*1.check hardware information */ + if (gp_mt6628_info == NULL) { + 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] = (size_t) &gFullPatchName; + ctrlData.au4CtrlData[2] = (size_t) &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] = (size_t) NULL; + ctrlData.au4CtrlData[1] = (size_t) &gFullPatchName; + ctrlData.au4CtrlData[2] = (size_t) &pbuf; + ctrlData.au4CtrlData[3] = (size_t) &patchSize; + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + WMT_ERR_FUNC("wmt_core: WMT_CTRL_GET_PATCH fail:%d\n", iRet); + iRet -= 1; + goto done; + } + + /* |<-BCNT_PATCH_BUF_HEADROOM(8) bytes dummy allocated->|<-patch file->| */ + pbuf += BCNT_PATCH_BUF_HEADROOM; + /* patch file with header: + * |<-patch header: 28 Bytes->|<-patch body: X Bytes ----->| + */ + patchHdr = (P_WMT_PATCH) pbuf; + /* check patch file information */ + + cDataTime = patchHdr->ucDateTime; + u2HwVer = patchHdr->u2HwVer; + u2SwVer = patchHdr->u2SwVer; + u4PatchVer = patchHdr->u4PatchVer; + /*cPlat = &patchHdr->ucPLat[0]; */ + + cDataTime[15] = '\0'; + if (index == 0) { + WMT_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)--->| + */ + if (patchSize < sizeof(WMT_PATCH)) { + WMT_ERR_FUNC("error patch size\n"); + iRet = -1; + goto done; + } + 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)----->| + */ + osal_memcpy(&gp_mt6628_patch_info, patchHdr, osal_sizeof(WMT_PATCH)); + pbuf -= sizeof(WMT_PATCH_CMD); + + fragNum = patchSize / patchSizePerFrag; + fragNum += ((fragNum * patchSizePerFrag) == patchSize) ? 0 : 1; + + WMT_DBG_FUNC("patch size(%d) fragNum(%d)\n", patchSize, fragNum); + + + /*send wmt part patch address command */ + 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(%zu, %d) fail(%d)\n", fragSeq, + fragSize + sizeof(WMT_PATCH_CMD), u4Res, iRet); + iRet -= 1; + break; + } + WMT_DBG_FUNC("wmt_core: write fragSeq(%d) size(%zu, %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(%zu, %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("rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%zu):[%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(%zu, %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]; + PINT8 cDataTime = NULL; + /*PINT8 cPlat = NULL; */ + UINT16 u2HwVer = 0; + UINT16 u2SwVer = 0; + UINT32 u4PatchVer = 0; + UINT32 patchSizePerFrag = 0; + WMT_CTRL_DATA ctrlData; + + /*1.check hardware information */ + if (gp_mt6628_info == NULL) { + 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 (iRet == 0) { + /* patch with correct Hw Ver Major Num found */ + ctrlData.ctrlId = WMT_CTRL_GET_PATCH_NAME; + ctrlData.au4CtrlData[0] = (size_t) &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] = (size_t) NULL; + ctrlData.au4CtrlData[1] = (size_t) &gFullPatchName; + + } else { + iRet -= 1; + return iRet; + } + ctrlData.au4CtrlData[2] = (size_t) &pbuf; + ctrlData.au4CtrlData[3] = (size_t) &patchSize; + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + WMT_ERR_FUNC("wmt_core: WMT_CTRL_GET_PATCH fail:%d\n", iRet); + iRet -= 1; + goto done; + } + + /* |<-BCNT_PATCH_BUF_HEADROOM(8) bytes dummy allocated->|<-patch file->| */ + pbuf += BCNT_PATCH_BUF_HEADROOM; + /* patch file with header: + * |<-patch header: 28 Bytes->|<-patch body: X Bytes ----->| + */ + patchHdr = (P_WMT_PATCH) pbuf; + /* check patch file information */ + + cDataTime = patchHdr->ucDateTime; + u2HwVer = patchHdr->u2HwVer; + u2SwVer = patchHdr->u2SwVer; + u4PatchVer = patchHdr->u4PatchVer; + /*cPlat = &patchHdr->ucPLat[0]; */ + + cDataTime[15] = '\0'; + 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)--->| + */ + if (patchSize < sizeof(WMT_PATCH)) { + WMT_ERR_FUNC("error patch size\n"); + return -1; + } + 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)----->| + */ + osal_memcpy(&gp_mt6628_patch_info, patchHdr, osal_sizeof(WMT_PATCH)); + pbuf -= sizeof(WMT_PATCH_CMD); + + fragNum = patchSize / patchSizePerFrag; + fragNum += ((fragNum * patchSizePerFrag) == patchSize) ? 0 : 1; + + WMT_DBG_FUNC("patch size(%d) fragNum(%d)\n", patchSize, fragNum); + + + /* send 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("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/misc/mediatek/connectivity/common/common_main/core/wmt_ic_6630.c b/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_ic_6630.c new file mode 100644 index 0000000000000..31974df9853fb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_ic_6630.c @@ -0,0 +1,2043 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/*! \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_MT6630 1 + +#define MT6630_BRINGUP 0 +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "osal_typedef.h" +#include "wmt_ic.h" +#include "wmt_core.h" +#include "wmt_lib.h" +#include "stp_core.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define DEFAULT_PATCH_FRAG_SIZE (1000) +#define WMT_PATCH_FRAG_1ST (0x1) +#define WMT_PATCH_FRAG_MID (0x2) +#define WMT_PATCH_FRAG_LAST (0x3) + +#define CFG_CHECK_WMT_RESULT (1) +/* BT Port 2 Feature. this command does not need after coex command is downconfirmed by LC, */ +#define CFG_WMT_BT_PORT2 (0) + +#define CFG_SET_OPT_REG (0) +#define CFG_WMT_I2S_DBGUART_SUPPORT (0) +#define CFG_SET_OPT_REG_SWLA (0) +#define CFG_SET_OPT_REG_MCUCLK (0) +#define CFG_SET_OPT_REG_MCUIRQ (0) + +#define CFG_SUBSYS_COEX_NEED 0 + +#define CFG_WMT_COREDUMP_ENABLE 0 + +#define CFG_WMT_MULTI_PATCH (1) + +#define CFG_WMT_CRYSTAL_TIMING_SET (0) + +#if CFG_WMT_LTE_COEX_HANDLING +#define CFG_WMT_FILTER_MODE_SETTING (1) +#else +#define CFG_WMT_FILTER_MODE_SETTING (0) +#endif +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +static UINT8 gFullPatchName[NAME_MAX + 1]; +static const WMT_IC_INFO_S *gp_mt6630_info; +static WMT_PATCH gp_mt6630_patch_info; +static WMT_CO_CLOCK gCoClockEn = WMT_CO_CLOCK_DIS; + +static UINT8 WMT_QUERY_BAUD_CMD[] = { 0x01, 0x04, 0x01, 0x00, 0x02 }; +static UINT8 WMT_QUERY_BAUD_EVT_115200[] = { + 0x02, 0x04, 0x06, 0x00, 0x00, 0x02, 0x00, 0xC2, 0x01, 0x00 }; +static UINT8 WMT_QUERY_BAUD_EVT_X[] = { + 0x02, 0x04, 0x06, 0x00, 0x00, 0x02, 0xAA, 0xAA, 0xAA, 0xBB }; +static UINT8 WMT_QUERY_STP_CMD[] = { 0x01, 0x04, 0x01, 0x00, 0x04 }; +static UINT8 WMT_QUERY_STP_EVT_DEFAULT[] = { + 0x02, 0x04, 0x06, 0x00, 0x00, 0x04, 0x11, 0x00, 0x00, 0x00 }; +static UINT8 WMT_QUERY_STP_EVT_UART[] = { + 0x02, 0x04, 0x06, 0x00, 0x00, 0x04, 0xDF, 0x0E, 0x68, 0x01 }; +static UINT8 WMT_SET_BAUD_CMD_X[] = { 0x01, 0x04, 0x05, 0x00, 0x01, 0xAA, 0xAA, 0xAA, 0xBB }; +static UINT8 WMT_SET_BAUD_EVT[] = { 0x02, 0x04, 0x02, 0x00, 0x00, 0x01 }; +static UINT8 WMT_SET_WAKEUP_WAKE_CMD_RAW[] = { 0xFF }; +static UINT8 WMT_SET_WAKEUP_WAKE_EVT[] = { 0x02, 0x03, 0x02, 0x00, 0x00, 0x03 }; +static UINT8 WMT_PATCH_CMD[] = { 0x01, 0x01, 0x00, 0x00, 0x00 }; +static UINT8 WMT_PATCH_EVT[] = { 0x02, 0x01, 0x01, 0x00, 0x00 }; +static UINT8 WMT_RESET_CMD[] = { 0x01, 0x07, 0x01, 0x00, 0x04 }; +static UINT8 WMT_RESET_EVT[] = { 0x02, 0x07, 0x01, 0x00, 0x00 }; + +#if CFG_WMT_BT_PORT2 +static UINT8 WMT_BTP2_CMD[] = { 0x01, 0x10, 0x03, 0x00, 0x01, 0x03, 0x01 }; +static UINT8 WMT_BTP2_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; +#endif + +#if CFG_WMT_MULTI_PATCH +static UINT8 WMT_PATCH_ADDRESS_CMD[] = { 0x01, 0x08, 0x10, 0x00, 0x01, 0x01, 0x00, 0x01, +0xD4, 0x03, 0x09, 0x02, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff }; + +static UINT8 WMT_PATCH_ADDRESS_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; + +static UINT8 WMT_PATCH_P_ADDRESS_CMD[] = { 0x01, 0x08, 0x10, 0x00, 0x01, 0x01, 0x00, 0x01, +0xfc, 0x08, 0x09, 0x02, 0x00, 0x00, 0x08, 0x00, 0xff, 0xff, 0xff, 0xff }; + +static UINT8 WMT_PATCH_P_ADDRESS_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; +#endif + +/*coex cmd/evt++*/ +static UINT8 WMT_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x02, 0x00, 0x01, 0x00 }; +static UINT8 WMT_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +#if CFG_SUBSYS_COEX_NEED +static UINT8 WMT_BT_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x0B, + 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, + 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xAA +}; +static UINT8 WMT_BT_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_WIFI_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x0C, + 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xAA +}; +static UINT8 WMT_WIFI_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_PTA_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x0A, + 0x00, 0x04, + 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xEE, 0xFF, 0xFF, 0xFE +}; +static UINT8 WMT_PTA_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +static UINt8 WMT_MISC_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x09, + 0x00, 0x05, + 0xAA, 0xAA, 0xAA, 0xAA, + 0xBB, 0xBB, 0xBB, 0xBB +}; +static UINT8 WMT_MISC_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; +#endif + +/*coex cmd/evt--*/ +static UINT8 WMT_SET_STP_CMD[] = { 0x01, 0x04, 0x05, 0x00, 0x03, 0xDF, 0x0E, 0x68, 0x01 }; +static UINT8 WMT_SET_STP_EVT[] = { 0x02, 0x04, 0x02, 0x00, 0x00, 0x03 }; +static UINT8 WMT_STRAP_CONF_CMD_FM_COMM[] = { 0x01, 0x05, 0x02, 0x00, 0x02, 0x02 }; +static UINT8 WMT_STRAP_CONF_EVT[] = { 0x02, 0x05, 0x02, 0x00, 0x00, 0x02 }; + +/* to get full dump when f/w assert */ +static UINT8 WMT_CORE_DUMP_LEVEL_04_CMD[] = { + 0x1, 0x0F, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static UINT8 WMT_CORE_DUMP_LEVEL_04_EVT[] = { 0x2, 0x0F, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_CORE_CO_CLOCK_CMD[] = { 0x1, 0x0A, 0x02, 0x00, 0x08, 0x03 }; +static UINT8 WMT_CORE_CO_CLOCK_EVT[] = { 0x2, 0x0A, 0x01, 0x00, 0x00 }; + + +#if (MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT) + + +static UINT8 WMT_SET_DAI_MODE_REG_CMD[] = { 0x01, 0x08, 0x28, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x03 /*2 registers */ + , 0x6c, 0x50, 0x02, 0x80 /*addr:0x8002506c */ + , 0x00, 0x00, 0x10, 0x11 /*value:0x11100000 */ + , 0x00, 0x00, 0xf0, 0xff /*mask:0xfff00000 */ + , 0x70, 0x50, 0x02, 0x80 /*addr:0x80025070 */ + , 0x01, 0x00, 0x00, 0x00 /*value:0x00000001 */ + , 0x0f, 0x00, 0x00, 0x00 /*mask:0x0000000f */ + , 0x00, 0x53, 0x02, 0x80 /*addr:0x80025300 */ + , 0x04, 0x00, 0x00, 0x00 /*value:0x00000004 */ + , 0x04, 0x00, 0x00, 0x00 /*mask:0x00000004 */ +}; + +static UINT8 WMT_SET_DAI_MODE_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x03 /*2 registers */ +}; + + +#endif + + +#if CFG_SET_OPT_REG_SWLA /* enable swla: eesk(7) eecs(8) oscen(19) sck0(24) scs0(25) */ +static UINT8 WMT_SET_SWLA_REG_CMD[] = { 0x01, 0x08, 0x1C, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x02 /*2 registers */ + , 0x10, 0x01, 0x05, 0x80 /*addr:0x80050110 */ + , 0x10, 0x10, 0x01, 0x00 /*value:0x00011010 */ + , 0xF0, 0xF0, 0x0F, 0x00 /*mask:0x000FF0F0 */ + , 0x40, 0x01, 0x05, 0x80 /*addr:0x80050140 */ + , 0x00, 0x10, 0x01, 0x00 /*value:0x00011000 */ + , 0x00, 0xF0, 0x0F, 0x00 /*mask:0x000FF000 */ +}; + +static UINT8 WMT_SET_SWLA_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x02 /*2 registers */ +}; +#endif + +#if CFG_SET_OPT_REG_MCUCLK /* enable mcu clk: antsel_4, eedi */ +static UINT8 WMT_SET_MCUCLK_REG_CMD[] = { 0x01, 0x08, (4 + 12 * 4), 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /* type: reg */ + , 0x00 /* rev */ + , 0x04 /* 4 registers */ + , 0x00, 0x04, 0x00, 0x80 /* addr:0x8000 0400 */ + , 0x00, 0x14, 0x00, 0x00 /* value:0x0000 1400(osc, hclk), 0x0000 1501(PLL, en) */ + , 0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000 FFFF */ + , 0x80, 0x01, 0x05, 0x80 /* addr:0x8005 0180 */ + , 0x12, 0x13, 0x00, 0x00 /* value:0x0000 1312(osc, hclk), 0x0000 1a19(PLL, en) */ + , 0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000 FFFF */ + , 0x00, 0x01, 0x05, 0x80 /* addr:0x8005 0100 */ + , 0x00, 0x00, 0x02, 0x00 /* value:0x0002 0000 */ + , 0x00, 0x00, 0x0F, 0x00 /* mask:0x000F 0000 */ + , 0x10, 0x01, 0x05, 0x80 /* addr:0x8005 0110 */ + , 0x02, 0x00, 0x00, 0x00 /* value:0x0000 0002 */ + , 0x0F, 0x00, 0x00, 0x00 /* mask:0x0000 000F */ +}; + +static UINT8 WMT_SET_MCUCLK_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /* S: 0 */ + , 0x00 /* type: reg */ + , 0x00 /* rev */ + , 0x04 /* 4 registers */ +}; +#endif + +#if CFG_WMT_I2S_DBGUART_SUPPORT /* register write for debug uart */ +static UINT8 WMT_SET_DBGUART_REG_CMD[] = { 0x01, 0x08, 0x1C, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x02 /*2 registers */ + , 0x30, 0x01, 0x05, 0x80 /*addr:0x80050130 */ + , 0x00, 0x00, 0x00, 0x00 /*value:0x00000000 */ + , 0xF0, 0x0F, 0x00, 0x00 /*mask:0x00000FF0 */ + , 0x40, 0x01, 0x05, 0x80 /*addr:0x80050140 */ + , 0x00, 0x01, 0x00, 0x00 /*value:0x00000100 */ + , 0x00, 0x01, 0x00, 0x00 /*mask:0x00000100 */ +}; + +static UINT8 WMT_SET_DBGUART_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x02 /*2 registers */ +}; +#endif + +#if CFG_SET_OPT_REG_MCUIRQ /* enable mcu irq: antsel_4, wlan_act */ +static UINT8 WMT_SET_MCUIRQ_REG_CMD[] = { 0x01, 0x08, (4 + 12 * 4), 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /* type: reg */ + , 0x00 /* rev */ + , 0x04 /* 4 registers */ + , 0x00, 0x04, 0x00, 0x80 /* addr:0x8000_0400 */ + , 0x03, 0x14, 0x00, 0x00 /* value:0x0000_1403 check confg debug flag 3 low word */ + , 0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000_FFFF */ + /* cirq_int_n */ + , 0x10, 0x01, 0x05, 0x80 /* addr:0x8005_0110 */ + , 0x02, 0x00, 0x00, 0x00 /* value:0x0000_0002 set EEDI as cirq_int_n debug flag (monitor flag2) */ + , 0x07, 0x00, 0x00, 0x00 /* mask:0x0000_0007 */ + , 0x00, 0x01, 0x05, 0x80 /* addr:0x8005_0100 */ + , 0x00, 0x00, 0x02, 0x00 /* value:0x0002_0000 (ANTSEL4=>monitor flag 0, ahb_x2_gt_ck debug flag) */ + , 0x00, 0x00, 0x07, 0x00 /* mask:0x0007_0000 */ + /* 1. ARM irq_b, monitor flag 0 */ + , 0x80, 0x01, 0x05, 0x80 /* addr:0x8005_0180 */ + , 0x1F, 0x1E, 0x00, 0x00 /* value:0x0000_1E1F check mcusys debug flag */ + , 0x7F, 0x7F, 0x00, 0x00 /* mask:0x0000_7F7F */ +}; + +static UINT8 WMT_SET_MCUIRQ_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /* S: 0 */ + , 0x00 /* type: reg */ + , 0x00 /* rev */ + , 0x04 /* 5 registers */ +}; +#endif + +static UINT8 WMT_SET_CRYSTAL_TRIMING_CMD[] = { 0x01, 0x12, 0x02, 0x00, 0x01, 0x00 }; +static UINT8 WMT_SET_CRYSTAL_TRIMING_EVT[] = { 0x02, 0x12, 0x02, 0x00, 0x01, 0x00 }; + +#if CFG_WMT_CRYSTAL_TIMING_SET +static UINT8 WMT_GET_CRYSTAL_TRIMING_CMD[] = { 0x01, 0x12, 0x02, 0x00, 0x00, 0x00 }; +static UINT8 WMT_GET_CRYSTAL_TRIMING_EVT[] = { 0x02, 0x12, 0x02, 0x00, 0x00, 0x00 }; +#endif + + +#if CFG_WMT_FILTER_MODE_SETTING +static UINT8 WMT_COEX_EXT_COMPONENT_CMD[] = { 0x01, 0x10, 0x03, 0x00, 0x0d, 0x00, 0x00 }; + +static UINT8 WMT_COEX_FILTER_SPEC_CMD_TEST[] = { 0x01, 0x10, 0x45, 0x00, 0x11, + 0x00, 0x00, 0x01, 0x00, 0x11, + 0x11, 0x16, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x63, 0x63, 0x63, + 0x00, 0x39, 0x43, 0x63, 0x63, + 0x02, 0x02, 0x03, 0x00, 0x01, + 0x01, 0x01, 0x01, 0x0e, 0x0e, + 0x0e, 0x00, 0x0a, 0x0c, 0x0e, + 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 +}; + +static UINT8 WMT_COEX_LTE_FREQ_IDX_TABLE_CMD[] = { 0x01, 0x10, 0x21, 0x00, 0x12, + 0xfc, 0x08, 0x15, 0x09, 0x2e, + 0x09, 0x47, 0x09, 0xc4, 0x09, + 0xd4, 0x09, 0xe3, 0x09, 0x5a, + 0x0a, 0x14, 0x09, 0x2d, 0x09, + 0x46, 0x09, 0x60, 0x09, 0xd3, + 0x09, 0xe2, 0x09, 0x59, 0x0a, + 0x8B, 0x0a +}; + +static UINT8 WMT_COEX_LTE_CHAN_UNSAFE_CMD[] = { 0x01, 0x10, 0x02, 0x00, 0x13, 0x00 }; + +#if CFG_WMT_LTE_ENABLE_MSGID_MAPPING +#else +static UINT8 WMT_COEX_IS_LTE_L_CMD[] = { 0x01, 0x10, 0x02, 0x00, 0x21, 0x01 }; +#endif + +static UINT8 WMT_COEX_IS_LTE_PROJ_CMD[] = { 0x01, 0x10, 0x02, 0x00, 0x15, 0x01 }; + +static UINT8 WMT_COEX_SPLIT_MODE_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; +#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"), +}; + +#if CFG_WMT_CRYSTAL_TIMING_SET +static struct init_script get_crystal_timing_script[] = { + INIT_CMD(WMT_GET_CRYSTAL_TRIMING_CMD, WMT_GET_CRYSTAL_TRIMING_EVT, + "get crystal trim value"), +}; +#endif + +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[] = { + 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"), + +#if CFG_SUBSYS_COEX_NEED +/* no need in MT6630 */ + 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_DAI_MODE_REG_CMD, WMT_SET_DAI_MODE_REG_EVT, "DAI_PAD"), +}; +#endif + +#if CFG_WMT_FILTER_MODE_SETTING +#if CFG_WMT_LTE_ENABLE_MSGID_MAPPING +static struct init_script set_wifi_lte_coex_table_0[] = { + INIT_CMD(WMT_COEX_EXT_COMPONENT_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi lte ext component"), + INIT_CMD(WMT_COEX_FILTER_SPEC_CMD_TEST, WMT_COEX_SPLIT_MODE_EVT, "wifi lte coex filter"), + INIT_CMD(WMT_COEX_LTE_FREQ_IDX_TABLE_CMD, WMT_COEX_SPLIT_MODE_EVT, + "wifi lte freq id table"), + INIT_CMD(WMT_COEX_LTE_CHAN_UNSAFE_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi lte unsafe channel"), + INIT_CMD(WMT_COEX_IS_LTE_PROJ_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi coex is lte project"), +}; +#else +static struct init_script set_wifi_lte_coex_table_0[] = { + INIT_CMD(WMT_COEX_EXT_COMPONENT_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi lte ext component"), + INIT_CMD(WMT_COEX_FILTER_SPEC_CMD_TEST, WMT_COEX_SPLIT_MODE_EVT, "wifi lte coex filter"), + INIT_CMD(WMT_COEX_LTE_FREQ_IDX_TABLE_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi lte freq id table"), + INIT_CMD(WMT_COEX_LTE_CHAN_UNSAFE_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi lte unsafe channel"), + INIT_CMD(WMT_COEX_IS_LTE_L_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi coex is L branch"), + INIT_CMD(WMT_COEX_IS_LTE_PROJ_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi coex is lte project"), +}; +#endif +#endif + +/* MT6630 Chip Version and Info Table */ +static const WMT_IC_INFO_S mt6630_info_table[] = { + { + .u4HwVer = 0x8A00, + .cChipName = WMT_IC_NAME_MT6630, + .cChipVersion = WMT_IC_VER_E1, + .cPatchNameExt = WMT_IC_PATCH_E1_EXT, + .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE, + .bPsmSupport = MTK_WCN_BOOL_TRUE, + }, + { + .u4HwVer = 0x8A10, + .cChipName = WMT_IC_NAME_MT6630, + .cChipVersion = WMT_IC_VER_E2, + .cPatchNameExt = WMT_IC_PATCH_E2_EXT, + .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE, + .bPsmSupport = MTK_WCN_BOOL_TRUE, + }, + { + .u4HwVer = 0x8A11, + .cChipName = WMT_IC_NAME_MT6630, + .cChipVersion = WMT_IC_VER_E3, + .cPatchNameExt = WMT_IC_PATCH_E2_EXT, + .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE, + .bPsmSupport = MTK_WCN_BOOL_TRUE, + }, + { + .u4HwVer = 0x8B11, + .cChipName = WMT_IC_NAME_MT6630, + .cChipVersion = WMT_IC_VER_E4, + .cPatchNameExt = WMT_IC_PATCH_E2_EXT, + .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 mt6630_sw_init(P_WMT_HIF_CONF pWmtHifConf); + +static INT32 mt6630_sw_deinit(P_WMT_HIF_CONF pWmtHifConf); + +static INT32 mt6630_pin_ctrl(WMT_IC_PIN_ID id, WMT_IC_PIN_STATE state, UINT32 flag); + +static INT32 mt6630_aif_ctrl(WMT_IC_PIN_STATE state, UINT32 flag); + +static INT32 mt6630_ver_check(VOID); + +static const WMT_IC_INFO_S *mt6630_find_wmt_ic_info(const UINT32 hw_ver); + +static INT32 wmt_stp_init_coex(VOID); + +#if CFG_WMT_MULTI_PATCH +static INT32 mt6630_patch_dwn(UINT32 index); +static INT32 mt6630_patch_info_prepare(VOID); +#else +static INT32 mt6630_patch_dwn(VOID); +#endif + +static INT32 mt6630_co_clock_ctrl(WMT_CO_CLOCK on); +static WMT_CO_CLOCK mt6630_co_clock_get(VOID); + +#if CFG_WMT_CRYSTAL_TIMING_SET +static INT32 mt6630_crystal_triming_set(VOID); +#endif + +static MTK_WCN_BOOL mt6630_quick_sleep_flag_get(VOID); + +static MTK_WCN_BOOL mt6630_aee_dump_flag_get(VOID); +#if 0 +/* set sdio driving */ +static UINT8 WMT_SET_SDIO_DRV_REG_CMD[] = { 0x01, 0x08, 0x10, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ + , 0x50, 0x00, 0x05, 0x80 /*addr:0x80050050 */ + , 0x44, 0x44, 0x04, 0x00 /*value:0x00044444 */ + , 0x77, 0x77, 0x07, 0x00 /*mask:0x00077777 */ +}; + +static UINT8 WMT_SET_SDIO_DRV_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ +}; + +static INT32 mt6630_set_sdio_driving(void); +static struct init_script sdio_driving_table[] = { + INIT_CMD(WMT_SET_SDIO_DRV_REG_CMD, WMT_SET_SDIO_DRV_REG_EVT, "sdio_driving"), +}; + +#endif +static MTK_WCN_BOOL mt6630_trigger_stp_assert(VOID); +#if CFG_WMT_FILTER_MODE_SETTING +static INT32 wmt_stp_wifi_lte_coex(VOID); +#endif + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/* MT6630 Operation Function Table */ +WMT_IC_OPS wmt_ic_ops_mt6630 = { + .icId = 0x6630, + .sw_init = mt6630_sw_init, + .sw_deinit = mt6630_sw_deinit, + .ic_pin_ctrl = mt6630_pin_ctrl, + .ic_ver_check = mt6630_ver_check, + .co_clock_ctrl = mt6630_co_clock_ctrl, + .is_quick_sleep = mt6630_quick_sleep_flag_get, + .is_aee_dump_support = mt6630_aee_dump_flag_get, + .trigger_stp_assert = mt6630_trigger_stp_assert, + .deep_sleep_ctrl = NULL, +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +static INT32 mt6630_sw_init(P_WMT_HIF_CONF pWmtHifConf) +{ + INT32 iRet = -1; + UINT32 u4Res = 0; + UINT8 evtBuf[256]; + ULONG ctrlPa1; + ULONG ctrlPa2; + UINT32 hw_ver; +#if CFG_WMT_MULTI_PATCH + UINT32 patch_num = 0; + UINT32 patch_index = 0; +#endif + WMT_CTRL_DATA ctrlData; + + WMT_DBG_FUNC(" start\n"); + + osal_assert(gp_mt6630_info != NULL); + + if ((gp_mt6630_info == NULL) + || (pWmtHifConf == NULL) + ) { + WMT_ERR_FUNC("null pointers: gp_mt6630_info(0x%p), pWmtHifConf(0x%p)\n", + gp_mt6630_info, pWmtHifConf); + return -1; + } + + hw_ver = gp_mt6630_info->u4HwVer; + + /* 4 <3.1> start init for sdio */ + + /* 4 <3.2> start init for uart */ + if (pWmtHifConf->hifType == WMT_HIF_UART) { + /* 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] = (UINT8) 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] = (UINT8) 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, 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_DBG_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); + mtk_wcn_stp_dbg_dump_package(); + 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 = mt6630_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 = mt6630_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, 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 = mt6630_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, 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; + } + WMT_DBG_FUNC("init_coex ok\n"); + +#if CFG_WMT_CRYSTAL_TIMING_SET + mt6630_crystal_triming_set(); +#endif + +#if MT6630_BRINGUP + WMT_INFO_FUNC("Bring up period, skip sdio driving settings\n"); +#else + WMT_DBG_FUNC("Temp solution, skip sdio driving settings\n"); + /* 6630_set_sdio_driving(); */ +#endif + if (pWmtHifConf->hifType == WMT_HIF_UART) { + /* 11. Set chip STP options */ + iRet = wmt_core_init_script(init_table_4, 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_sleep_ms(10); + /* 14. Query chip STP options (TEST-ONLY) */ + /* 15. Query baud rate (stp, TEST-ONLY) */ + iRet = wmt_core_init_script(init_table_5, ARRAY_SIZE(init_table_5)); + + if (iRet) { + WMT_ERR_FUNC("init_table_5 fail(%d)\n", iRet); + return -14; + } + } + + if (mt6630_co_clock_get() == WMT_CO_CLOCK_EN) { + WMT_INFO_FUNC("co-clock enabled.\n"); + + iRet = wmt_core_init_script(osc_type_table, ARRAY_SIZE(osc_type_table)); + + if (iRet) { + WMT_ERR_FUNC("osc_type_table fail(%d), goes on\n", iRet); + return -15; + } + } else if (mt6630_co_clock_get() == WMT_CO_CLOCK_DCXO) { + WMT_SET_CRYSTAL_TRIMING_CMD[4] = 0x2; + WMT_SET_CRYSTAL_TRIMING_CMD[5] = 0x2; + WMT_SET_CRYSTAL_TRIMING_EVT[4] = 0x2; + WMT_SET_CRYSTAL_TRIMING_EVT[5] = 0x0; + iRet = wmt_core_init_script(set_crystal_timing_script, ARRAY_SIZE(set_crystal_timing_script)); + if (iRet == 0) + WMT_INFO_FUNC("set to Xtal mode suceed\n"); + else + WMT_INFO_FUNC("set to Xtal mode failed, iRet:%d.\n", iRet); + + + } else + WMT_DBG_FUNC("co-clock disabled.\n"); +#if MT6630_BRINGUP + WMT_INFO_FUNC("Bring up period, skip merge interface settings\n"); +#else + +#if (MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT) + iRet = wmt_core_init_script(merge_pcm_table, ARRAY_SIZE(merge_pcm_table)); + + if (iRet) { + WMT_ERR_FUNC("merge_pcm_table fail(%d), goes on\n", iRet); + return -15; + } +#endif +#endif + /* 15. Set FM strap */ + WMT_STRAP_CONF_CMD_FM_COMM[5] = (UINT8) pWmtHifConf->au4StrapConf[0]; + WMT_STRAP_CONF_EVT[5] = (UINT8) pWmtHifConf->au4StrapConf[0]; + iRet = wmt_core_init_script(init_table_5_1, 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, 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 (mtk_wcn_stp_coredump_flag_get() != 0) { + iRet = wmt_core_init_script(init_table_6, ARRAY_SIZE(init_table_6)); + + if (iRet) { + WMT_ERR_FUNC("init_table_6 core dump setting fail(%d)\n", iRet); + return -18; + } + WMT_INFO_FUNC("enable mt662x firmware coredump\n"); + } else + WMT_INFO_FUNC("disable mt662x firmware coredump\n"); + + ctrlData.ctrlId = WMT_CTRL_SET_STP_DBG_INFO; + ctrlData.au4CtrlData[0] = wmt_ic_ops_mt6630.icId; + ctrlData.au4CtrlData[1] = (size_t) gp_mt6630_info->cChipVersion; + ctrlData.au4CtrlData[2] = (size_t) &gp_mt6630_patch_info; + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + WMT_ERR_FUNC("set dump info fail(%d)\n", iRet); + return -16; + } +#if CFG_WMT_FILTER_MODE_SETTING + wmt_stp_wifi_lte_coex(); +#endif + +#if CFG_WMT_PS_SUPPORT + osal_assert(gp_mt6630_info != NULL); + + if (gp_mt6630_info != NULL) { + if (gp_mt6630_info->bPsmSupport != MTK_WCN_BOOL_FALSE) + wmt_lib_ps_enable(); + else + wmt_lib_ps_disable(); + } +#endif + + return 0; +} + +static INT32 mt6630_sw_deinit(P_WMT_HIF_CONF pWmtHifConf) +{ + WMT_DBG_FUNC(" start\n"); + +#if CFG_WMT_PS_SUPPORT + osal_assert(gp_mt6630_info != NULL); + + if ((gp_mt6630_info != NULL) + && (gp_mt6630_info->bPsmSupport != MTK_WCN_BOOL_FALSE)) { + wmt_lib_ps_disable(); + } +#endif + + gp_mt6630_info = NULL; + + return 0; +} + +static INT32 mt6630_aif_ctrl(WMT_IC_PIN_STATE state, UINT32 flag) +{ + INT32 ret = -1; + +#if MT6630_BRINGUP + ret = 0; + WMT_INFO_FUNC("Bring up period, skip aif settings\n"); +#else + + if ((flag & WMT_LIB_AIF_FLAG_MASK) == WMT_LIB_AIF_FLAG_SHARE) { + WMT_INFO_FUNC("PCM & I2S PIN SHARE\n"); + + WMT_WARN_FUNC("TBD!!"); + ret = 0; + } 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 */ + 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 */ +#if 0 + val = 0x01110000; + ret = wmt_core_reg_rw_raw(1, 0x80050078, &val, 0x0FFF0000); +#else + ret = 0; + WMT_INFO_FUNC("Bring up period, skip WMT_IC_AIF_2 settings\n"); +#endif + break; + + case WMT_IC_AIF_3: + ret = 0; + break; + + 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); +#endif + return ret; +} + +static INT32 mt6630_gps_sync_ctrl(WMT_IC_PIN_STATE state, UINT32 flag) +{ +#if 0 + INT32 iRet = -1; + UINT32 uVal = 0; + + if (state == WMT_IC_PIN_MUX) + uVal = 0x1 << 4; + else + uVal = 0x0 << 4; + /*0x80025070[7:4]: 1-A-GPS_SYNC mode, 0-Jtag mode */ +#if MT6630_BRINGUP + iRet = 0; + WMT_INFO_FUNC("Bring up period, skip gps sync settings\n"); + +#else + iRet = wmt_core_reg_rw_raw(1, 0x80025070, &uVal, 0xf << 4); +#endif + if (iRet != 0) + WMT_ERR_FUNC("gps_sync pin ctrl failed, iRet(%d)\n", iRet); +#endif + /* anyway, we return 0 */ + return 0; +} + + +static INT32 mt6630_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 = mt6630_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 = mt6630_gps_sync_ctrl(state, flag); + break; + + default: + break; + } + + WMT_INFO_FUNC("ret = (%d)\n", ret); + + return ret; +} + +INT32 mt6630_co_clock_ctrl(WMT_CO_CLOCK on) +{ + INT32 iRet = 0; + + if ((on >= WMT_CO_CLOCK_DIS) && (on < WMT_CO_CLOCK_MAX)) { + gCoClockEn = on; + } else { + WMT_DBG_FUNC("MT6630: error parameter:%d\n", on); + iRet = -1; + } + + WMT_DBG_FUNC("MT6630: Co-clock type: %d\n", gCoClockEn); + + return iRet; +} + +static MTK_WCN_BOOL mt6630_quick_sleep_flag_get(VOID) +{ + return MTK_WCN_BOOL_TRUE; +} + + +static MTK_WCN_BOOL mt6630_aee_dump_flag_get(VOID) +{ + if (mtk_wcn_stp_coredump_flag_get() == 1) + return MTK_WCN_BOOL_TRUE; + else + return MTK_WCN_BOOL_FALSE; +} + +static MTK_WCN_BOOL mt6630_trigger_stp_assert(VOID) +{ + INT32 iRet = -1; + UINT32 u4Res = 0; + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + UINT8 STP_DO_ASSERT_CMD[] = { 0x80, 0x50, 0x0a, 0x00, 'd', 'o', 'c', 'o', 'r', 'e', 'd', 'u', 'm', 'p', 0x00, + 0x00 + }; + + iRet = + wmt_core_tx((PUINT8)&STP_DO_ASSERT_CMD[0], sizeof(STP_DO_ASSERT_CMD), &u4Res, + MTK_WCN_BOOL_TRUE); + if (iRet || (u4Res != sizeof(STP_DO_ASSERT_CMD))) { + WMT_ERR_FUNC("wmt_core:send STP ASSERT COMMAND fail(%d),size(%d)\n", iRet, u4Res); + bRet = MTK_WCN_BOOL_FALSE; + } else + bRet = MTK_WCN_BOOL_TRUE; + return bRet; +} + +WMT_CO_CLOCK mt6630_co_clock_get(VOID) +{ + return gCoClockEn; +} + + + +static INT32 mt6630_ver_check(VOID) +{ + UINT32 hw_ver = 0; + UINT32 fw_ver = 0; + INT32 iret; + const WMT_IC_INFO_S *p_info = NULL; + ULONG ctrlPa1; + ULONG ctrlPa2; + + /* 1. identify chip versions: HVR(HW_VER) and FVR(FW_VER) */ + WMT_LOUD_FUNC("MT6630: 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("MT6630: read hw_ver fail:%d\n", iret); + return -2; + } + + WMT_LOUD_FUNC("MT6630: before fw_ver (rom version)\n"); + wmt_core_reg_rw_raw(0, GEN_FVR, &fw_ver, GEN_VER_MASK); + + if (iret) { + WMT_ERR_FUNC("MT6630: read fw_ver fail:%d\n", iret); + return -2; + } + + WMT_INFO_FUNC("MT6630: read (hw version)(0x%x), (fw version version)(0x%x)\n", hw_ver, fw_ver); + + p_info = mt6630_find_wmt_ic_info(hw_ver); + + if (p_info == NULL) { + WMT_ERR_FUNC("MT6630: hw_ver(0x%x) find wmt ic info fail\n", hw_ver); + return -3; + } + + WMT_INFO_FUNC("MT6630: wmt ic info: %s.%s (0x%x, patch_ext:%s)\n", + p_info->cChipName, p_info->cChipVersion, + p_info->u4HwVer, p_info->cPatchNameExt); + + /* hw id & version */ + ctrlPa1 = (0x00006630UL << 16) | (hw_ver & 0x0000FFFF); + /* translated fw rom version */ + ctrlPa2 = (fw_ver & 0x0000FFFF); + + iret = wmt_core_ctrl(WMT_CTRL_HWIDVER_SET, &ctrlPa1, &ctrlPa2); + + if (iret) + WMT_WARN_FUNC("MT6630: WMT_CTRL_HWIDVER_SET fail(%d)\n", iret); + + gp_mt6630_info = p_info; + return 0; +} + +static const WMT_IC_INFO_S *mt6630_find_wmt_ic_info(const UINT32 hw_ver) +{ + /* match chipversion with u4HwVer item in mt6630_info_table */ + const UINT32 size = ARRAY_SIZE(mt6630_info_table); + INT32 index; + + /* Leave full match here is a workaround for GPS to distinguish E3/E4 ICs. */ + index = size - 1; + + /* full match */ + while ((index >= 0) + && (hw_ver != mt6630_info_table[index].u4HwVer) /* full match */ + ) { + --index; + } + + if (index >= 0) { + WMT_INFO_FUNC("found ic info(0x%x) by full match! index:%d\n", hw_ver, index); + return &mt6630_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 ((index >= 0) + && (MAJORNUM(hw_ver) != MAJORNUM(mt6630_info_table[index].u4HwVer)) + ) { + --index; + } + + if (index >= 0) { + WMT_INFO_FUNC("MT6630: found ic info for hw_ver(0x%x) by major num! index:%d\n", + hw_ver, index); + return &mt6630_info_table[index]; + } + + WMT_ERR_FUNC + ("MT6630: 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; + ULONG addr = 0; + WMT_GEN_CONF *pWmtGenConf = NULL; + +#define COEX_WMT 0 + +#if CFG_SUBSYS_COEX_NEED + /* no need for MT6630 */ +#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, ARRAY_SIZE(coex_table)); + + return iRet; +} + +#if 0 +static INT32 mt6630_set_sdio_driving(void) +{ + INT32 ret = 0; + + UINT32 addr = 0; + 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%x)\n", addr); + + pWmtGenConf = (P_WMT_GEN_CONF) addr; + + /*Check if WMT.cfg exists */ + if (pWmtGenConf->cfgExist == 0) { + WMT_INFO_FUNC("cfgExist == 0, skip config chip\n"); + /*if WMT.cfg not existed, still return success and adopt the default value */ + return 0; + } + + drv_val = pWmtGenConf->sdio_driving_cfg; + + /*Dump the sdio driving related info */ + WMT_INFO_FUNC("sdio driving:0x%x\n", drv_val); + + sdio_driving_table[0].cmd[12] = (UINT8) ((drv_val & 0x00000077UL) >> 0); /* DAT0 and DAT1 */ + sdio_driving_table[0].cmd[13] = (UINT8) ((drv_val & 0x00007700UL) >> 8); /* DAT2 and DAT3 */ + sdio_driving_table[0].cmd[14] = (UINT8) ((drv_val & 0x00070000UL) >> 16); /* CMD */ + + ret = wmt_core_init_script(sdio_driving_table, ARRAY_SIZE(sdio_driving_table)); + + return ret; +} +#endif + +#if CFG_WMT_CRYSTAL_TIMING_SET +static INT32 mt6630_crystal_triming_set(VOID) +{ + INT32 iRet = 0; + PUINT8 pbuf = NULL; + UINT32 bufLen = 0; + WMT_CTRL_DATA ctrlData; + UINT32 uCryTimOffset = 0x6D; + MTK_WCN_BOOL bIsNvramExist = MTK_WCN_BOOL_FALSE; + INT8 cCrystalTimingOffset = 0x0; + UINT8 cCrystalTiming = 0x0; + INT32 iCrystalTiming = 0x0; + MTK_WCN_BOOL bIsCrysTrimEnabled = MTK_WCN_BOOL_FALSE; + UINT32 u4Res; + + bIsNvramExist = MTK_WCN_BOOL_FALSE; + ctrlData.ctrlId = WMT_CTRL_CRYSTAL_TRIMING_GET; + ctrlData.au4CtrlData[0] = (size_t) "/data/nvram/APCFG/APRDEB/WIFI"; + ctrlData.au4CtrlData[1] = (size_t) &pbuf; + ctrlData.au4CtrlData[2] = (size_t) &bufLen; + + iRet = wmt_ctrl(&ctrlData); + + if (iRet != 0) { + WMT_ERR_FUNC("MT6630: 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("MT6630: nvram pBuf(%p), bufLen(%d)\n", pbuf, bufLen); + + if (bufLen < (uCryTimOffset + 1)) { + WMT_ERR_FUNC + ("MT6630: 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 = (UINT8) cCrystalTimingOffset & 0x7f; + } + + WMT_DBG_FUNC("cCrystalTimingOffset (%d), bIsCrysTrimEnabled(%d)\n", + cCrystalTimingOffset, bIsCrysTrimEnabled); + } + + ctrlData.ctrlId = WMT_CTRL_CRYSTAL_TRIMING_PUT; + ctrlData.au4CtrlData[0] = (size_t) "/data/nvram/APCFG/APRDEB/WIFI"; + iRet = wmt_ctrl(&ctrlData); + + if (iRet != 0) { + WMT_ERR_FUNC("MT6630: WMT_CTRL_CRYSTAL_TRIMING_PUT fail:%d\n", iRet); + iRet = -2; + } else { + WMT_DBG_FUNC("MT6630: WMT_CTRL_CRYSTAL_TRIMING_PUT succeed\n"); + } + } + + if ((bIsNvramExist == MTK_WCN_BOOL_TRUE) && (bIsCrysTrimEnabled == MTK_WCN_BOOL_TRUE)) { + /*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); + if (iCrystalTiming > 0x7f) + cCrystalTiming = 0x7f; + else if (iCrystalTiming < 0) + cCrystalTiming = 0; + else + cCrystalTiming = iCrystalTiming; + WMT_DBG_FUNC("cCrystalTiming (0x%x)\n", cCrystalTiming); + /* set_crystal_timing_script */ + /*set crystal trim value command*/ + WMT_SET_CRYSTAL_TRIMING_CMD[4] = 0x1; + WMT_SET_CRYSTAL_TRIMING_EVT[4] = 0x1; + + WMT_SET_CRYSTAL_TRIMING_CMD[5] = cCrystalTiming; + WMT_GET_CRYSTAL_TRIMING_EVT[5] = cCrystalTiming; + + iRet = + wmt_core_init_script(set_crystal_timing_script, + 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, + ARRAY_SIZE(get_crystal_timing_script)); + + if (iRet) { + WMT_ERR_FUNC("get_crystal_timing_script fail(%d)\n", iRet); + iRet = -6; + } else { + WMT_INFO_FUNC("succeed, updated crystal timing value (0x%x)\n", + WMT_GET_CRYSTAL_TRIMING_EVT[5]); + iRet = 0x0; + } + } + } + +done: + return iRet; +} +#endif + +#if CFG_WMT_MULTI_PATCH +static INT32 mt6630_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 mt6630_patch_dwn(UINT32 index) +{ + INT32 iRet = -1; + P_WMT_PATCH patchHdr = NULL; + PUINT8 pBuf = NULL; + PUINT8 pPatchBuf = NULL; + UINT32 patchSize; + UINT32 fragSeq; + UINT32 fragNum; + UINT16 fragSize = 0; + UINT16 cmdLen; + UINT32 offset; + UINT32 u4Res; + UINT8 evtBuf[8]; + UINT8 addressevtBuf[12]; + UINT8 addressByte[4]; + PINT8 cDataTime = NULL; + /*PINT8 cPlat = NULL; */ + UINT16 u2HwVer = 0; + UINT16 u2SwVer = 0; + UINT32 u4PatchVer = 0; + UINT32 patchSizePerFrag = 0; + WMT_CTRL_DATA ctrlData; + + /*1.check hardware information */ + if (gp_mt6630_info == NULL) { + WMT_ERR_FUNC("null gp_mt6630_info!\n"); + return -1; + } + + osal_memset(gFullPatchName, 0, osal_sizeof(gFullPatchName)); + + ctrlData.ctrlId = WMT_CTRL_GET_PATCH_INFO; + ctrlData.au4CtrlData[0] = index + 1; + ctrlData.au4CtrlData[1] = (size_t) &gFullPatchName; + ctrlData.au4CtrlData[2] = (size_t) &addressByte; + iRet = wmt_ctrl(&ctrlData); + WMT_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] = (size_t) NULL; + ctrlData.au4CtrlData[1] = (size_t) &gFullPatchName; + ctrlData.au4CtrlData[2] = (size_t) &pBuf; + ctrlData.au4CtrlData[3] = (size_t) &patchSize; + iRet = wmt_ctrl(&ctrlData); + + if (iRet) { + WMT_ERR_FUNC("wmt_core: WMT_CTRL_GET_PATCH fail:%d\n", iRet); + iRet -= 1; + goto done; + } + + /* |<-BCNT_PATCH_BUF_HEADROOM(8) bytes dummy allocated->|<-patch file->| */ + /* patch file with header: + * |<-patch header: 28 Bytes->|<-patch body: X Bytes ----->| + */ + pPatchBuf = osal_malloc(patchSize); + if (pPatchBuf == NULL) { + WMT_ERR_FUNC("vmalloc pPatchBuf for patch download fail\n"); + return -2; + } + osal_memcpy(pPatchBuf, pBuf, patchSize); + /* check patch file information */ + + patchHdr = (P_WMT_PATCH) pPatchBuf; + + cDataTime = patchHdr->ucDateTime; + u2HwVer = patchHdr->u2HwVer; + u2SwVer = patchHdr->u2SwVer; + u4PatchVer = patchHdr->u4PatchVer; + + osal_memcpy(&gp_mt6630_patch_info, patchHdr, osal_sizeof(WMT_PATCH)); + + /*cPlat = &patchHdr->ucPLat[0]; */ + + cDataTime[15] = '\0'; + + if (index == 0) { + WMT_INFO_FUNC("Combo Patch:Build Time(%s)Hw(0x%x) Sw(0x%x) Ph(0x%04x)Platform(%c%c%c%c)\n", + cDataTime, ((u2HwVer & 0x00ff) << 8) | ((u2HwVer & 0xff00) >> 8), + ((u2SwVer & 0x00ff) << 8) | ((u2SwVer & 0xff00) >> 8), + ((u4PatchVer & 0xff000000) >> 24) | ((u4PatchVer & 0x00ff0000) >> 16), + patchHdr->ucPLat[0], patchHdr->ucPLat[1], patchHdr->ucPLat[2], patchHdr->ucPLat[3]); + } + + /* remove patch header: + * |<-patch body: X Bytes (X=patchSize)--->| + */ + if (patchSize < sizeof(WMT_PATCH)) { + WMT_ERR_FUNC("error patch size\n"); + iRet = -1; + goto done; + } + patchSize -= sizeof(WMT_PATCH); + pPatchBuf += 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)----->| + */ + pPatchBuf -= 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); + mtk_wcn_stp_dbg_dump_package(); + 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); + mtk_wcn_stp_dbg_dump_package(); + 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(pPatchBuf + offset - sizeof(WMT_PATCH_CMD), WMT_PATCH_CMD, + sizeof(WMT_PATCH_CMD)); + + iRet = + wmt_core_tx(pPatchBuf + 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(%zu, %d) fail(%d)\n", fragSeq, + fragSize + sizeof(WMT_PATCH_CMD), u4Res, iRet); + iRet -= 1; + break; + } + + WMT_DBG_FUNC("wmt_core: write fragSeq(%d) size(%zu, %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(%zu, %d) fail(%d)\n", + sizeof(WMT_PATCH_EVT), u4Res, iRet); + mtk_wcn_stp_dbg_dump_package(); + iRet -= 1; + break; + } +#if CFG_CHECK_WMT_RESULT + + if (osal_memcmp(evtBuf, WMT_PATCH_EVT, sizeof(WMT_PATCH_EVT)) != 0) { + WMT_ERR_FUNC("rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%zu):[%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(%zu, %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: + if (patchHdr != NULL) { + osal_free(patchHdr); + pPatchBuf = NULL; + patchHdr = NULL; + } + /* 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 mt6630_patch_dwn(VOID) +{ + INT32 iRet = -1; + P_WMT_PATCH patchHdr; + PUINT8 pbuf; + UINT32 patchSize; + UINT32 fragSeq; + UINT32 fragNum; + UINT16 fragSize = 0; + UINT16 cmdLen; + UINT32 offset; + UINT32 u4Res; + UINT8 evtBuf[8]; + PINT8 cDataTime = NULL; + /*PINT8 cPlat = NULL; */ + UINT16 u2HwVer = 0; + UINT16 u2SwVer = 0; + UINT32 u4PatchVer = 0; + UINT32 patchSizePerFrag = 0; + WMT_CTRL_DATA ctrlData; + + /*1.check hardware information */ + if (gp_mt6630_info == NULL) { + WMT_ERR_FUNC("null gp_mt6630_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 (iRet == 0) { + /* patch with correct Hw Ver Major Num found */ + ctrlData.ctrlId = WMT_CTRL_GET_PATCH_NAME; + ctrlData.au4CtrlData[0] = (size_t) &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] = (size_t) NULL; + ctrlData.au4CtrlData[1] = (size_t) &gFullPatchName; + + } else { + iRet -= 1; + return iRet; + } + + ctrlData.au4CtrlData[2] = (size_t) &pbuf; + ctrlData.au4CtrlData[3] = (size_t) &patchSize; + iRet = wmt_ctrl(&ctrlData); + + if (iRet) { + WMT_ERR_FUNC("wmt_core: WMT_CTRL_GET_PATCH fail:%d\n", iRet); + iRet -= 1; + goto done; + } + + /* |<-BCNT_PATCH_BUF_HEADROOM(8) bytes dummy allocated->|<-patch file->| */ + pbuf += BCNT_PATCH_BUF_HEADROOM; + /* patch file with header: + * |<-patch header: 28 Bytes->|<-patch body: X Bytes ----->| + */ + patchHdr = (P_WMT_PATCH) pbuf; + /* check patch file information */ + + cDataTime = patchHdr->ucDateTime; + u2HwVer = patchHdr->u2HwVer; + u2SwVer = patchHdr->u2SwVer; + u4PatchVer = patchHdr->u4PatchVer; + + osal_memcpy(&gp_mt6630_patch_info, patchHdr, osal_sizeof(WMT_PATCH)); + /*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)--->| + */ + if (patchSize < sizeof(WMT_PATCH)) { + WMT_ERR_FUNC("error patch size\n"); + return -1; + } + 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); + mtk_wcn_stp_dbg_dump_package(); + iRet -= 1; + break; + } +#if CFG_CHECK_WMT_RESULT + + if (osal_memcmp(evtBuf, WMT_PATCH_EVT, sizeof(WMT_PATCH_EVT)) != 0) { + WMT_ERR_FUNC("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 + +#if CFG_WMT_FILTER_MODE_SETTING +static INT32 wmt_stp_wifi_lte_coex(VOID) +{ + INT32 iRet; + ULONG addr = 0; + WMT_GEN_CONF *pWmtGenConf = NULL; + + /*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; + } + + if (pWmtGenConf->coex_wmt_filter_mode == 0) { + /*add WMT_COXE_CONFIG_EXT_COMPONENT_OPCODE command for 2G4 xLNA demand*/ + if (pWmtGenConf->coex_wmt_ext_component) { + WMT_INFO_FUNC("coex_wmt_ext_component:0x%x\n", pWmtGenConf->coex_wmt_ext_component); + set_wifi_lte_coex_table_0[0].cmd[5] = pWmtGenConf->coex_wmt_ext_component; + } + iRet = + wmt_core_init_script(set_wifi_lte_coex_table_0, + ARRAY_SIZE(set_wifi_lte_coex_table_0)); + if (iRet) + WMT_ERR_FUNC("wmt_core:set_wifi_lte_coex_table_0 fail(%d)\n", iRet); + else + WMT_INFO_FUNC("wmt_core:set_wifi_lte_coex_table_0 ok\n"); + } + + return iRet; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_ic_6632.c b/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_ic_6632.c new file mode 100644 index 0000000000000..20847f00a4a15 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_ic_6632.c @@ -0,0 +1,1989 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/*! \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_MT6632 1 + +#define MT6632_BRINGUP 0 +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "osal_typedef.h" +#include "wmt_ic.h" +#include "wmt_core.h" +#include "wmt_lib.h" +#include "stp_core.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define DEFAULT_PATCH_FRAG_SIZE (1000) +#define WMT_PATCH_FRAG_1ST (0x1) +#define WMT_PATCH_FRAG_MID (0x2) +#define WMT_PATCH_FRAG_LAST (0x3) + +#define CFG_CHECK_WMT_RESULT (1) +/* BT Port 2 Feature. this command does not need after coex command is downconfirmed by LC, */ +#define CFG_WMT_BT_PORT2 (0) + +#define CFG_SET_OPT_REG (0) +#define CFG_WMT_I2S_DBGUART_SUPPORT (0) +#define CFG_SET_OPT_REG_SWLA (0) +#define CFG_SET_OPT_REG_MCUCLK (0) +#define CFG_SET_OPT_REG_MCUIRQ (0) + +#define CFG_SUBSYS_COEX_NEED 0 + +#define CFG_WMT_COREDUMP_ENABLE 0 + +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT +INT32 g_deep_sleep_flag = 1; +#else +INT32 g_deep_sleep_flag; +#endif + +#if CFG_WMT_LTE_COEX_HANDLING +#define CFG_WMT_FILTER_MODE_SETTING (1) +#else +#define CFG_WMT_FILTER_MODE_SETTING (0) +#endif +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +static UINT8 gFullPatchName[NAME_MAX + 1]; +static const WMT_IC_INFO_S *gp_mt6632_info; +static WMT_PATCH gp_mt6632_patch_info; +static WMT_CO_CLOCK gCoClockEn = WMT_CO_CLOCK_DIS; + +static UINT8 WMT_QUERY_BAUD_CMD[] = { 0x01, 0x04, 0x01, 0x00, 0x02 }; +static UINT8 WMT_QUERY_BAUD_EVT_115200[] = { + 0x02, 0x04, 0x06, 0x00, 0x00, 0x02, 0x00, 0xC2, 0x01, 0x00 }; +static UINT8 WMT_QUERY_BAUD_EVT_X[] = { + 0x02, 0x04, 0x06, 0x00, 0x00, 0x02, 0xAA, 0xAA, 0xAA, 0xBB }; +static UINT8 WMT_QUERY_STP_CMD[] = { 0x01, 0x04, 0x01, 0x00, 0x04 }; +static UINT8 WMT_QUERY_STP_EVT_DEFAULT[] = { + 0x02, 0x04, 0x06, 0x00, 0x00, 0x04, 0x11, 0x00, 0x00, 0x00 }; +static UINT8 WMT_QUERY_STP_EVT_UART[] = { + 0x02, 0x04, 0x06, 0x00, 0x00, 0x04, 0xDF, 0x0E, 0x68, 0x01 }; +static UINT8 WMT_SET_BAUD_CMD_X[] = { 0x01, 0x04, 0x05, 0x00, 0x01, 0xAA, 0xAA, 0xAA, 0xBB }; +static UINT8 WMT_SET_BAUD_EVT[] = { 0x02, 0x04, 0x02, 0x00, 0x00, 0x01 }; +static UINT8 WMT_SET_WAKEUP_WAKE_CMD_RAW[] = { 0xFF }; +static UINT8 WMT_SET_WAKEUP_WAKE_EVT[] = { 0x02, 0x03, 0x02, 0x00, 0x00, 0x03 }; +static UINT8 WMT_PATCH_CMD[] = { 0x01, 0x01, 0x00, 0x00, 0x00 }; +static UINT8 WMT_PATCH_EVT[] = { 0x02, 0x01, 0x01, 0x00, 0x00 }; + +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT +UINT8 WMT_DEEP_SLEEP_CMD[] = { 0x01, 0x02, 0x02, 0x00, 0x11, 0x00 }; +UINT8 WMT_DEEP_SLEEP_EVT[] = { 0x02, 0x02, 0x01, 0x00, 0x00 }; +#endif + +UINT8 WMT_CLOCK_RATE_CMD[] = {0x01, 0x0A, 0x04, 0x00, 0x09, 0x01, 0x00, 0x00}; +UINT8 WMT_CLOCK_RATE_EVT[] = {0x02, 0x0A, 0x01, 0x00, 0x00}; +UINT8 WMT_PATCH_DWN_USE_DMA_CMD[] = {0x01, 0x08, 0x10, 0x00, 0x01, 0x01, 0x00, + 0x01, 0xc0, 0x0a, 0x01, 0x02, 0x04, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}; +UINT8 WMT_PATCH_DWN_USE_DMA_EVT[] = {0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01}; + +static UINT8 WMT_RESET_CMD[] = { 0x01, 0x07, 0x01, 0x00, 0x04 }; +static UINT8 WMT_RESET_EVT[] = { 0x02, 0x07, 0x01, 0x00, 0x00 }; + +#if CFG_WMT_BT_PORT2 +static UINT8 WMT_BTP2_CMD[] = { 0x01, 0x10, 0x03, 0x00, 0x01, 0x03, 0x01 }; +static UINT8 WMT_BTP2_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; +#endif + +static UINT8 WMT_PATCH_ADDRESS_CMD[] = { 0x01, 0x01, 0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}; + +static UINT8 WMT_PATCH_ADDRESS_EVT[] = { 0x02, 0x01, 0x01, 0x00, 0x00}; + +/*coex cmd/evt++*/ +static UINT8 WMT_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x02, 0x00, 0x01, 0x00 }; +static UINT8 WMT_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +#if CFG_SUBSYS_COEX_NEED +static UINT8 WMT_BT_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x0B, + 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, + 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xAA +}; +static UINT8 WMT_BT_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_WIFI_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x0C, + 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xAA +}; +static UINT8 WMT_WIFI_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_PTA_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x0A, + 0x00, 0x04, + 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xEE, 0xFF, 0xFF, 0xFE +}; +static UINT8 WMT_PTA_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +static UINt8 WMT_MISC_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x09, + 0x00, 0x05, + 0xAA, 0xAA, 0xAA, 0xAA, + 0xBB, 0xBB, 0xBB, 0xBB +}; +static UINT8 WMT_MISC_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; +#else +static UINT8 WMT_COEX_WIFI_PATH_CMD[] = { 0x01, 0x10, 0x03, 0x00, 0x1A, 0x0F, 0x00 }; +static UINT8 WMT_COEX_WIFI_PATH_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_COEX_EXT_ELAN_GAIN_P1_CMD[] = { 0x01, 0x10, 0x12, 0x00, 0x1B, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static UINT8 WMT_COEX_EXT_ELAN_GAIN_P1_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; +#endif + +/*coex cmd/evt--*/ +static UINT8 WMT_SET_STP_CMD[] = { 0x01, 0x04, 0x05, 0x00, 0x03, 0xDF, 0x0E, 0x68, 0x01 }; +static UINT8 WMT_SET_STP_EVT[] = { 0x02, 0x04, 0x02, 0x00, 0x00, 0x03 }; + +static UINT8 WMT_SET_SDIO_RETRY_CMD[] = { 0x01, 0x02, 0x02, 0x00, 0x18, 0x01 }; +static UINT8 WMT_SET_SDIO_RETRY_EVT[] = { 0x02, 0x02, 0x01, 0x00, 0x01 }; + +/* to get full dump when f/w assert */ +static UINT8 WMT_CORE_DUMP_LEVEL_04_CMD[] = { + 0x1, 0x0F, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static UINT8 WMT_CORE_DUMP_LEVEL_04_EVT[] = { 0x2, 0x0F, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_CORE_CO_CLOCK_CMD[] = { 0x1, 0x0A, 0x02, 0x00, 0x08, 0x03 }; +static UINT8 WMT_CORE_CO_CLOCK_EVT[] = { 0x2, 0x0A, 0x01, 0x00, 0x00 }; + + +#if (MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT) + + +static UINT8 WMT_SET_DAI_MODE_REG_CMD[] = { 0x01, 0x08, 0x1c, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x02 /*2 registers */ + , 0x54, 0x30, 0x02, 0x81 /*addr:0x81023054 */ + , 0x00, 0x00, 0x33, 0x33 /*value:0x33330000 */ + , 0x00, 0x00, 0xff, 0xff /*mask:0xffff0000 */ + , 0x00, 0x53, 0x02, 0x80 /*addr:0x80025300 */ + , 0x04, 0x00, 0x00, 0x00 /*value:0x00000004 */ + , 0x04, 0x00, 0x00, 0x00 /*mask:0x00000004 */ +}; + +static UINT8 WMT_SET_DAI_MODE_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x02 /*2 registers */ +}; + + +#endif + + +#if CFG_SET_OPT_REG_SWLA /* enable swla: eesk(7) eecs(8) oscen(19) sck0(24) scs0(25) */ +static UINT8 WMT_SET_SWLA_REG_CMD[] = { 0x01, 0x08, 0x1C, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x02 /*2 registers */ + , 0x10, 0x01, 0x05, 0x80 /*addr:0x80050110 */ + , 0x10, 0x10, 0x01, 0x00 /*value:0x00011010 */ + , 0xF0, 0xF0, 0x0F, 0x00 /*mask:0x000FF0F0 */ + , 0x40, 0x01, 0x05, 0x80 /*addr:0x80050140 */ + , 0x00, 0x10, 0x01, 0x00 /*value:0x00011000 */ + , 0x00, 0xF0, 0x0F, 0x00 /*mask:0x000FF000 */ +}; + +static UINT8 WMT_SET_SWLA_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x02 /*2 registers */ +}; +#endif + +#if CFG_SET_OPT_REG_MCUCLK /* enable mcu clk: antsel_4, eedi */ +static UINT8 WMT_SET_MCUCLK_REG_CMD[] = { 0x01, 0x08, (4 + 12 * 4), 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /* type: reg */ + , 0x00 /* rev */ + , 0x04 /* 4 registers */ + , 0x00, 0x04, 0x00, 0x80 /* addr:0x8000 0400 */ + , 0x00, 0x14, 0x00, 0x00 /* value:0x0000 1400(osc, hclk), 0x0000 1501(PLL, en) */ + , 0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000 FFFF */ + , 0x80, 0x01, 0x05, 0x80 /* addr:0x8005 0180 */ + , 0x12, 0x13, 0x00, 0x00 /* value:0x0000 1312(osc, hclk), 0x0000 1a19(PLL, en) */ + , 0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000 FFFF */ + , 0x00, 0x01, 0x05, 0x80 /* addr:0x8005 0100 */ + , 0x00, 0x00, 0x02, 0x00 /* value:0x0002 0000 */ + , 0x00, 0x00, 0x0F, 0x00 /* mask:0x000F 0000 */ + , 0x10, 0x01, 0x05, 0x80 /* addr:0x8005 0110 */ + , 0x02, 0x00, 0x00, 0x00 /* value:0x0000 0002 */ + , 0x0F, 0x00, 0x00, 0x00 /* mask:0x0000 000F */ +}; + +static UINT8 WMT_SET_MCUCLK_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /* S: 0 */ + , 0x00 /* type: reg */ + , 0x00 /* rev */ + , 0x04 /* 4 registers */ +}; +#endif + +#if CFG_WMT_I2S_DBGUART_SUPPORT /* register write for debug uart */ +static UINT8 WMT_SET_DBGUART_REG_CMD[] = { 0x01, 0x08, 0x1C, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x02 /*2 registers */ + , 0x30, 0x01, 0x05, 0x80 /*addr:0x80050130 */ + , 0x00, 0x00, 0x00, 0x00 /*value:0x00000000 */ + , 0xF0, 0x0F, 0x00, 0x00 /*mask:0x00000FF0 */ + , 0x40, 0x01, 0x05, 0x80 /*addr:0x80050140 */ + , 0x00, 0x01, 0x00, 0x00 /*value:0x00000100 */ + , 0x00, 0x01, 0x00, 0x00 /*mask:0x00000100 */ +}; + +static UINT8 WMT_SET_DBGUART_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x02 /*2 registers */ +}; +#endif + +#if CFG_SET_OPT_REG_MCUIRQ /* enable mcu irq: antsel_4, wlan_act */ +static UINT8 WMT_SET_MCUIRQ_REG_CMD[] = { 0x01, 0x08, (4 + 12 * 4), 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /* type: reg */ + , 0x00 /* rev */ + , 0x04 /* 4 registers */ + , 0x00, 0x04, 0x00, 0x80 /* addr:0x8000_0400 */ + , 0x03, 0x14, 0x00, 0x00 /* value:0x0000_1403 check confg debug flag 3 low word */ + , 0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000_FFFF */ + /* cirq_int_n */ + , 0x10, 0x01, 0x05, 0x80 /* addr:0x8005_0110 */ + , 0x02, 0x00, 0x00, 0x00 /* value:0x0000_0002 set EEDI as cirq_int_n debug flag (monitor flag2) */ + , 0x07, 0x00, 0x00, 0x00 /* mask:0x0000_0007 */ + , 0x00, 0x01, 0x05, 0x80 /* addr:0x8005_0100 */ + , 0x00, 0x00, 0x02, 0x00 /* value:0x0002_0000 (ANTSEL4=>monitor flag 0, ahb_x2_gt_ck debug flag) */ + , 0x00, 0x00, 0x07, 0x00 /* mask:0x0007_0000 */ + /* 1. ARM irq_b, monitor flag 0 */ + , 0x80, 0x01, 0x05, 0x80 /* addr:0x8005_0180 */ + , 0x1F, 0x1E, 0x00, 0x00 /* value:0x0000_1E1F check mcusys debug flag */ + , 0x7F, 0x7F, 0x00, 0x00 /* mask:0x0000_7F7F */ +}; + +static UINT8 WMT_SET_MCUIRQ_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /* S: 0 */ + , 0x00 /* type: reg */ + , 0x00 /* rev */ + , 0x04 /* 5 registers */ +}; +#endif + +static UINT8 WMT_SET_CRYSTAL_TRIMING_CMD[] = { 0x01, 0x12, 0x02, 0x00, 0x01, 0x00 }; +static UINT8 WMT_SET_CRYSTAL_TRIMING_EVT[] = { 0x02, 0x12, 0x02, 0x00, 0x01, 0x00 }; + +/* +* static UINT8 WMT_GET_CRYSTAL_TRIMING_CMD[] = { 0x01, 0x12, 0x02, 0x00, 0x00, 0x00 }; +* static UINT8 WMT_GET_CRYSTAL_TRIMING_EVT[] = { 0x02, 0x12, 0x02, 0x00, 0x00, 0x00 }; +*/ + + +#if CFG_WMT_FILTER_MODE_SETTING +static UINT8 WMT_COEX_EXT_COMPONENT_CMD[] = { 0x01, 0x10, 0x03, 0x00, 0x0d, 0x00, 0x00 }; + +static UINT8 WMT_COEX_FILTER_SPEC_CMD_TEST[] = { 0x01, 0x10, 0x45, 0x00, 0x11, + 0x00, 0x00, 0x01, 0x00, 0x11, + 0x11, 0x16, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x63, 0x63, 0x63, + 0x00, 0x39, 0x43, 0x63, 0x63, + 0x02, 0x02, 0x03, 0x00, 0x01, + 0x01, 0x01, 0x01, 0x0e, 0x0e, + 0x0e, 0x00, 0x0a, 0x0c, 0x0e, + 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 +}; + +static UINT8 WMT_COEX_LTE_FREQ_IDX_TABLE_CMD[] = { 0x01, 0x10, 0x21, 0x00, 0x12, + 0xfc, 0x08, 0x15, 0x09, 0x2e, + 0x09, 0x47, 0x09, 0xc4, 0x09, + 0xd4, 0x09, 0xe3, 0x09, 0x5a, + 0x0a, 0x14, 0x09, 0x2d, 0x09, + 0x46, 0x09, 0x60, 0x09, 0xd3, + 0x09, 0xe2, 0x09, 0x59, 0x0a, + 0x8B, 0x0a +}; + +static UINT8 WMT_COEX_LTE_CHAN_UNSAFE_CMD[] = { 0x01, 0x10, 0x02, 0x00, 0x13, 0x00 }; + +#if CFG_WMT_LTE_ENABLE_MSGID_MAPPING +#else +static UINT8 WMT_COEX_IS_LTE_L_CMD[] = { 0x01, 0x10, 0x02, 0x00, 0x21, 0x01 }; +#endif + +static UINT8 WMT_COEX_IS_LTE_PROJ_CMD[] = { 0x01, 0x10, 0x02, 0x00, 0x15, 0x01 }; + +static UINT8 WMT_COEX_SPLIT_MODE_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; +#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 +}; + +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT +static struct init_script init_deep_sleep_script[] = { + INIT_CMD(WMT_DEEP_SLEEP_CMD, WMT_DEEP_SLEEP_EVT, "chip deep sleep"), +}; +#endif + +static struct init_script clock_rate_modify[] = { + INIT_CMD(WMT_CLOCK_RATE_CMD, WMT_CLOCK_RATE_EVT, "clock rate modify"), +}; + +/* WMT_CLOCK_RATE_CMD[6] = 0xD0, promote the XTAL(26MHz) rate to 208MHz */ +static struct init_script clock_rate_pro_and_use_dma[] = { + INIT_CMD(WMT_CLOCK_RATE_CMD, WMT_CLOCK_RATE_EVT, "clock rate modify"), + INIT_CMD(WMT_PATCH_DWN_USE_DMA_CMD, WMT_PATCH_DWN_USE_DMA_EVT, "patch dwn use DMA"), +}; + + +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"), +* }; +*/ + +static struct init_script init_table_4[] = { + INIT_CMD(WMT_SET_STP_CMD, WMT_SET_STP_EVT, "set stp"), +}; + +static struct init_script set_sdio_retry_script[] = { + INIT_CMD(WMT_SET_SDIO_RETRY_CMD, WMT_SET_SDIO_RETRY_EVT, "set sdio retry"), +}; + +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_6[] = { + 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"), + +#if CFG_SUBSYS_COEX_NEED +/* no need in MT6632 */ + 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"), +#else + INIT_CMD(WMT_COEX_WIFI_PATH_CMD, WMT_COEX_WIFI_PATH_EVT, "wifi path"), + INIT_CMD(WMT_COEX_EXT_ELAN_GAIN_P1_CMD, WMT_COEX_EXT_ELAN_GAIN_P1_EVT, "wifi elan gain p1"), +#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_DAI_MODE_REG_CMD, WMT_SET_DAI_MODE_REG_EVT, "DAI_PAD"), +}; +#endif + +#if CFG_WMT_FILTER_MODE_SETTING +#if CFG_WMT_LTE_ENABLE_MSGID_MAPPING +static struct init_script set_wifi_lte_coex_table_0[] = { + INIT_CMD(WMT_COEX_EXT_COMPONENT_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi lte ext component"), + INIT_CMD(WMT_COEX_FILTER_SPEC_CMD_TEST, WMT_COEX_SPLIT_MODE_EVT, "wifi lte coex filter"), + INIT_CMD(WMT_COEX_LTE_FREQ_IDX_TABLE_CMD, WMT_COEX_SPLIT_MODE_EVT, + "wifi lte freq id table"), + INIT_CMD(WMT_COEX_LTE_CHAN_UNSAFE_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi lte unsafe channel"), + INIT_CMD(WMT_COEX_IS_LTE_PROJ_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi coex is lte project"), +}; +#else +static struct init_script set_wifi_lte_coex_table_0[] = { + INIT_CMD(WMT_COEX_EXT_COMPONENT_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi lte ext component"), + INIT_CMD(WMT_COEX_FILTER_SPEC_CMD_TEST, WMT_COEX_SPLIT_MODE_EVT, "wifi lte coex filter"), + INIT_CMD(WMT_COEX_LTE_FREQ_IDX_TABLE_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi lte freq id table"), + INIT_CMD(WMT_COEX_LTE_CHAN_UNSAFE_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi lte unsafe channel"), + INIT_CMD(WMT_COEX_IS_LTE_L_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi coex is L branch"), + INIT_CMD(WMT_COEX_IS_LTE_PROJ_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi coex is lte project"), +}; +#endif +#endif + +/* MT6632 Chip Version and Info Table */ +static const WMT_IC_INFO_S mt6632_info_table[] = { + { + .u4HwVer = 0x8A00, + .cChipName = WMT_IC_NAME_MT6632, + .cChipVersion = WMT_IC_VER_E1, + .cPatchNameExt = WMT_IC_PATCH_E1_EXT, + .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE, + .bPsmSupport = MTK_WCN_BOOL_TRUE, + }, + { + .u4HwVer = 0x8A10, + .cChipName = WMT_IC_NAME_MT6632, + .cChipVersion = WMT_IC_VER_E2, + .cPatchNameExt = WMT_IC_PATCH_E2_EXT, + .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE, + .bPsmSupport = MTK_WCN_BOOL_TRUE, + }, + { + .u4HwVer = 0x8A11, + .cChipName = WMT_IC_NAME_MT6632, + .cChipVersion = WMT_IC_VER_E3, + .cPatchNameExt = WMT_IC_PATCH_E2_EXT, + .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE, + .bPsmSupport = MTK_WCN_BOOL_TRUE, + }, + { + .u4HwVer = 0x8B11, + .cChipName = WMT_IC_NAME_MT6632, + .cChipVersion = WMT_IC_VER_E4, + .cPatchNameExt = WMT_IC_PATCH_E2_EXT, + .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 mt6632_sw_init(P_WMT_HIF_CONF pWmtHifConf); + +static INT32 mt6632_sw_deinit(P_WMT_HIF_CONF pWmtHifConf); + +static INT32 mt6632_pin_ctrl(WMT_IC_PIN_ID id, WMT_IC_PIN_STATE state, UINT32 flag); + +static INT32 mt6632_aif_ctrl(WMT_IC_PIN_STATE state, UINT32 flag); + +static INT32 mt6632_ver_check(VOID); + +static const WMT_IC_INFO_S *mt6632_find_wmt_ic_info(const UINT32 hw_ver); + +static INT32 wmt_stp_init_coex(VOID); + +static INT32 mt6632_patch_dwn(UINT32 index); +static INT32 mt6632_patch_info_prepare(VOID); + +static INT32 mt6632_co_clock_ctrl(WMT_CO_CLOCK on); +static WMT_CO_CLOCK mt6632_co_clock_get(VOID); + +/*static INT32 mt6632_crystal_triming_set(VOID);*/ + + +static MTK_WCN_BOOL mt6632_quick_sleep_flag_get(VOID); + +static MTK_WCN_BOOL mt6632_aee_dump_flag_get(VOID); +#if 0 +/* set sdio driving */ +static UINT8 WMT_SET_SDIO_DRV_REG_CMD[] = { 0x01, 0x08, 0x10, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ + , 0x50, 0x00, 0x05, 0x80 /*addr:0x80050050 */ + , 0x44, 0x44, 0x04, 0x00 /*value:0x00044444 */ + , 0x77, 0x77, 0x07, 0x00 /*mask:0x00077777 */ +}; + +static UINT8 WMT_SET_SDIO_DRV_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ +}; + +static INT32 mt6632_set_sdio_driving(void); +static struct init_script sdio_driving_table[] = { + INIT_CMD(WMT_SET_SDIO_DRV_REG_CMD, WMT_SET_SDIO_DRV_REG_EVT, "sdio_driving"), +}; + +#endif +static MTK_WCN_BOOL mt6632_trigger_stp_assert(VOID); +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT +static MTK_WCN_BOOL mt6632_deep_sleep_ctrl(INT32 value); +static INT32 wmt_stp_get_deep_sleep_flag_from_cfg(VOID); +#endif + +#if CFG_WMT_FILTER_MODE_SETTING +static INT32 wmt_stp_wifi_lte_coex(VOID); +#endif + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/* MT6632 Operation Function Table */ +WMT_IC_OPS wmt_ic_ops_mt6632 = { + .icId = 0x6632, + .sw_init = mt6632_sw_init, + .sw_deinit = mt6632_sw_deinit, + .ic_pin_ctrl = mt6632_pin_ctrl, + .ic_ver_check = mt6632_ver_check, + .co_clock_ctrl = mt6632_co_clock_ctrl, + .is_quick_sleep = mt6632_quick_sleep_flag_get, + .is_aee_dump_support = mt6632_aee_dump_flag_get, + .trigger_stp_assert = mt6632_trigger_stp_assert, +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT + .deep_sleep_ctrl = mt6632_deep_sleep_ctrl, +#else + .deep_sleep_ctrl = NULL, +#endif + +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +static INT32 mt6632_sw_init(P_WMT_HIF_CONF pWmtHifConf) +{ + INT32 iRet = -1; + UINT32 u4Res = 0; + UINT8 evtBuf[256]; + ULONG ctrlPa1; + ULONG ctrlPa2; + UINT32 hw_ver; + UINT32 patch_num = 0; + UINT32 patch_index = 0; + WMT_CTRL_DATA ctrlData; +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT + INT32 deep_sleep_flag_from_cfg; +#endif + WMT_DBG_FUNC(" start\n"); + + osal_assert(gp_mt6632_info != NULL); + + if ((gp_mt6632_info == NULL) + || (pWmtHifConf == NULL) + ) { + WMT_ERR_FUNC("null pointers: gp_mt6632_info(0x%p), pWmtHifConf(0x%p)\n", + gp_mt6632_info, pWmtHifConf); + return -1; + } + + hw_ver = gp_mt6632_info->u4HwVer; + + /* 4 <3.1> start init for sdio */ + + /* 4 <3.2> start init for uart */ + if (pWmtHifConf->hifType == WMT_HIF_UART) { + /* 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] = (UINT8) 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] = (UINT8) 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, 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); + mtk_wcn_stp_dbg_dump_package(); + 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 */ + /* 9.1 Let launcher to search patch info */ + iRet = mt6632_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_DBG_FUNC("patch total num = [%d]\n", patch_num); + + /* improve patch down load speed */ + WMT_DBG_FUNC("improve patch dwn speed, clock rate promote, copy data use DMA at firmware side\n"); + WMT_CLOCK_RATE_CMD[6] = 0xD0; + /* If WMT_CLOCK_RATE_CMD[6] = 0xD0, promote the XTAL(26MHz) rate to 208MHz + * copy data use DMA at firmware side + */ + iRet = wmt_core_init_script(clock_rate_pro_and_use_dma, ARRAY_SIZE(clock_rate_pro_and_use_dma)); + if (iRet) { + WMT_ERR_FUNC("clock_rate_pro_and_use_dma fail(%d)\n", iRet); + return -30; + } + /* 9.3 Multi-patch Patch download */ + for (patch_index = 0; patch_index < patch_num; patch_index++) { + iRet = mt6632_patch_dwn(patch_index); + + if (iRet) { + WMT_ERR_FUNC("patch dwn fail (%d),patch_index(%d)\n", iRet, patch_index); + return -12; + } + + /* 10. WMT Reset command */ + iRet = wmt_core_init_script(init_table_3, ARRAY_SIZE(init_table_3)); + + if (iRet) { + WMT_ERR_FUNC("init_table_3 fail(%d)\n", iRet); + return -13; + } + } + /*close clock rate promote*/ + WMT_CLOCK_RATE_CMD[6] = 0x00; + WMT_DBG_FUNC("close clock rate promote, made XTAL to 26MHz\n"); + iRet = wmt_core_init_script(clock_rate_modify, ARRAY_SIZE(clock_rate_modify)); + if (iRet) { + WMT_ERR_FUNC("close clock rate promote fail(%d)\n", iRet); + return -31; + } + + /* SDIO data patch retry feature enable/disable */ + mtk_stp_sdio_retry_flag_ctrl(1); + if (mtk_stp_sdio_retry_flag_get()) { + iRet = wmt_core_init_script(set_sdio_retry_script, ARRAY_SIZE(set_sdio_retry_script)); + + if (iRet) { + WMT_ERR_FUNC("set_sdio_retry_script fail(%d)\n", iRet); + mtk_stp_sdio_retry_flag_ctrl(0); + } + } + +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT + if (g_deep_sleep_flag) { + /*get flag form mt6632_ant_m1.cfg*/ + deep_sleep_flag_from_cfg = wmt_stp_get_deep_sleep_flag_from_cfg(); + if (deep_sleep_flag_from_cfg == 1) { + WMT_DEEP_SLEEP_CMD[5] = 1; + iRet = wmt_core_init_script(init_deep_sleep_script, ARRAY_SIZE(init_deep_sleep_script)); + if (iRet) { + WMT_ERR_FUNC("enalbe deep sleep feature fail\n"); + return -20; + } + WMT_DBG_FUNC("chip deep sleep feature is enable\n"); + wmt_lib_deep_sleep_flag_set(MTK_WCN_BOOL_TRUE); + } else { + WMT_DEEP_SLEEP_CMD[5] = 0; + iRet = wmt_core_init_script(init_deep_sleep_script, ARRAY_SIZE(init_deep_sleep_script)); + if (iRet) { + WMT_ERR_FUNC("disable deep sleep feature fail\n"); + return -21; + } + WMT_INFO_FUNC("chip deep sleep feature is disable\n"); + wmt_lib_deep_sleep_flag_set(MTK_WCN_BOOL_FALSE); + } + } else { + WMT_DEEP_SLEEP_CMD[5] = 0; + iRet = wmt_core_init_script(init_deep_sleep_script, ARRAY_SIZE(init_deep_sleep_script)); + if (iRet) { + WMT_ERR_FUNC("disable deep sleep feature fail\n"); + return -22; + } + WMT_INFO_FUNC("chip deep sleep feature is disable\n"); + wmt_lib_deep_sleep_flag_set(MTK_WCN_BOOL_FALSE); + } +#endif + iRet = wmt_stp_init_coex(); + + if (iRet) { + WMT_ERR_FUNC("init_coex fail(%d)\n", iRet); + return -10; + } + WMT_DBG_FUNC("init_coex ok\n"); + /*If TCXO or co-clock is applied in mt6632, remove the triming patch*/ + /*mt6632_crystal_triming_set();*/ +#if MT6632_BRINGUP + WMT_DBG_FUNC("Bring up period, skip sdio driving settings\n"); +#else + WMT_DBG_FUNC("Temp solution, skip sdio driving settings\n"); + /* 6632_set_sdio_driving(); */ +#endif + if (pWmtHifConf->hifType == WMT_HIF_UART) { + /* 11. Set chip STP options */ + iRet = wmt_core_init_script(init_table_4, 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_sleep_ms(10); + /* 14. Query chip STP options (TEST-ONLY) */ + /* 15. Query baud rate (stp, TEST-ONLY) */ + iRet = wmt_core_init_script(init_table_5, ARRAY_SIZE(init_table_5)); + + if (iRet) { + WMT_ERR_FUNC("init_table_5 fail(%d)\n", iRet); + return -14; + } + } + + if (mt6632_co_clock_get() == WMT_CO_CLOCK_EN) { + WMT_INFO_FUNC("co-clock enabled.\n"); + + iRet = wmt_core_init_script(osc_type_table, ARRAY_SIZE(osc_type_table)); + + if (iRet) { + WMT_ERR_FUNC("osc_type_table fail(%d), goes on\n", iRet); + return -15; + } + } else if (mt6632_co_clock_get() == WMT_CO_CLOCK_DCXO) { + WMT_SET_CRYSTAL_TRIMING_CMD[4] = 0x2; + WMT_SET_CRYSTAL_TRIMING_CMD[5] = 0x2; + WMT_SET_CRYSTAL_TRIMING_EVT[4] = 0x2; + WMT_SET_CRYSTAL_TRIMING_EVT[5] = 0x0; + iRet = wmt_core_init_script(set_crystal_timing_script, ARRAY_SIZE(set_crystal_timing_script)); + if (iRet == 0) + WMT_INFO_FUNC("set to Xtal mode suceed\n"); + else + WMT_INFO_FUNC("set to Xtal mode failed, iRet:%d.\n", iRet); + + + } else + WMT_INFO_FUNC("co-clock disabled.\n"); +#if MT6632_BRINGUP + WMT_INFO_FUNC("Bring up period, skip merge interface settings\n"); +#else + +#if (MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT) + iRet = wmt_core_init_script(merge_pcm_table, ARRAY_SIZE(merge_pcm_table)); + + if (iRet) { + WMT_ERR_FUNC("merge_pcm_table fail(%d), goes on\n", iRet); + return -15; + } +#endif +#endif + +#if CFG_SET_OPT_REG /*set registers */ + iRet = wmt_core_init_script(set_registers, 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 (mtk_wcn_stp_coredump_flag_get() != 0) { + iRet = wmt_core_init_script(init_table_6, ARRAY_SIZE(init_table_6)); + + if (iRet) { + WMT_ERR_FUNC("init_table_6 core dump setting fail(%d)\n", iRet); + return -18; + } + WMT_INFO_FUNC("enable mt662x firmware coredump\n"); + } else + WMT_INFO_FUNC("disable mt662x firmware coredump\n"); + + ctrlData.ctrlId = WMT_CTRL_SET_STP_DBG_INFO; + ctrlData.au4CtrlData[0] = wmt_ic_ops_mt6632.icId; + ctrlData.au4CtrlData[1] = (size_t) gp_mt6632_info->cChipVersion; + ctrlData.au4CtrlData[2] = (size_t) &gp_mt6632_patch_info; + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + WMT_ERR_FUNC("set dump info fail(%d)\n", iRet); + return -16; + } +#if CFG_WMT_FILTER_MODE_SETTING + wmt_stp_wifi_lte_coex(); +#endif + +#if CFG_WMT_PS_SUPPORT + osal_assert(gp_mt6632_info != NULL); + + if (gp_mt6632_info != NULL) { + if (gp_mt6632_info->bPsmSupport != MTK_WCN_BOOL_FALSE) + wmt_lib_ps_enable(); + else + wmt_lib_ps_disable(); + } +#endif + + return 0; +} + +static INT32 mt6632_sw_deinit(P_WMT_HIF_CONF pWmtHifConf) +{ + WMT_DBG_FUNC(" start\n"); + +#if CFG_WMT_PS_SUPPORT + osal_assert(gp_mt6632_info != NULL); + + if ((gp_mt6632_info != NULL) + && (gp_mt6632_info->bPsmSupport != MTK_WCN_BOOL_FALSE)) { + wmt_lib_ps_disable(); + } +#endif + + gp_mt6632_info = NULL; + + return 0; +} + +static INT32 mt6632_aif_ctrl(WMT_IC_PIN_STATE state, UINT32 flag) +{ + INT32 ret = -1; + +#if MT6632_BRINGUP + ret = 0; + WMT_INFO_FUNC("Bring up period, skip aif settings\n"); +#else + + if ((flag & WMT_LIB_AIF_FLAG_MASK) == WMT_LIB_AIF_FLAG_SHARE) { + WMT_INFO_FUNC("PCM & I2S PIN SHARE\n"); + + WMT_WARN_FUNC("TBD!!"); + ret = 0; + } 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 */ + 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 */ +#if 0 + val = 0x01110000; + ret = wmt_core_reg_rw_raw(1, 0x80050078, &val, 0x0FFF0000); +#else + ret = 0; + WMT_INFO_FUNC("Bring up period, skip WMT_IC_AIF_2 settings\n"); +#endif + break; + + case WMT_IC_AIF_3: + ret = 0; + break; + + 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); +#endif + return ret; +} + +static INT32 mt6632_gps_sync_ctrl(WMT_IC_PIN_STATE state, UINT32 flag) +{ + WMT_DBG_FUNC("MT6632 do not need gps sync settings\n"); + + /* anyway, we return 0 */ + return 0; +} + + +static INT32 mt6632_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 = mt6632_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 = mt6632_gps_sync_ctrl(state, flag); + break; + + default: + break; + } + + WMT_DBG_FUNC("ret = (%d)\n", ret); + + return ret; +} + +INT32 mt6632_co_clock_ctrl(WMT_CO_CLOCK on) +{ + INT32 iRet = 0; + + if ((on >= WMT_CO_CLOCK_DIS) && (on < WMT_CO_CLOCK_MAX)) { + gCoClockEn = on; + } else { + WMT_DBG_FUNC("MT6632: error parameter:%d\n", on); + iRet = -1; + } + + WMT_DBG_FUNC("MT6632: Co-clock type: %d\n", gCoClockEn); + + return iRet; +} + +static MTK_WCN_BOOL mt6632_quick_sleep_flag_get(VOID) +{ + return MTK_WCN_BOOL_TRUE; +} + + +static MTK_WCN_BOOL mt6632_aee_dump_flag_get(VOID) +{ + if (mtk_wcn_stp_coredump_flag_get() == 1) + return MTK_WCN_BOOL_TRUE; + else + return MTK_WCN_BOOL_FALSE; +} + +static MTK_WCN_BOOL mt6632_trigger_stp_assert(VOID) +{ + INT32 iRet = -1; + UINT32 u4Res = 0; + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + UINT8 STP_DO_ASSERT_CMD[] = { 0x80, 0x50, 0x0a, 0x00, 'd', 'o', 'c', 'o', 'r', 'e', 'd', 'u', 'm', 'p', 0x00, + 0x00 + }; + + iRet = + wmt_core_tx((PUINT8)&STP_DO_ASSERT_CMD[0], sizeof(STP_DO_ASSERT_CMD), &u4Res, + MTK_WCN_BOOL_TRUE); + if (iRet || (u4Res != sizeof(STP_DO_ASSERT_CMD))) { + WMT_ERR_FUNC("wmt_core:send STP ASSERT COMMAND fail(%d),size(%d)\n", iRet, u4Res); + bRet = MTK_WCN_BOOL_FALSE; + } else + bRet = MTK_WCN_BOOL_TRUE; + return bRet; +} +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT +static MTK_WCN_BOOL mt6632_deep_sleep_ctrl(INT32 value) +{ + INT32 ret = 0; + + g_deep_sleep_flag = value; + if (value) { + WMT_DEEP_SLEEP_CMD[5] = 1; + WMT_INFO_FUNC("enable chip deep sleep feature from wmt_dbg command\n"); + } else { + WMT_DEEP_SLEEP_CMD[5] = 0; + WMT_INFO_FUNC("disable chip deep sleep feature from wmt_dbg command\n"); + } + ret = wmt_core_init_script(init_deep_sleep_script, ARRAY_SIZE(init_deep_sleep_script)); + if (ret == 0) + return MTK_WCN_BOOL_TRUE; + else + return MTK_WCN_BOOL_FALSE; +} + +static INT32 wmt_stp_get_deep_sleep_flag_from_cfg(VOID) +{ + WMT_GEN_CONF *pWmtGenConf = NULL; + ULONG addr; + INT32 ret; + + /*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 -2; + } + + WMT_DBG_FUNC("ctrl GET_WMT_CONF ok(0x%lx)\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 -1; + } + if (pWmtGenConf->disable_deep_sleep_cfg == 0) { + WMT_DBG_FUNC("disable_deep_sleep_cfg (%d) get form mt6632_ant_m1.cfg, enable deep sleep feature\n", + pWmtGenConf->disable_deep_sleep_cfg); + ret = 1; + } else { + WMT_DBG_FUNC("disable_deep_sleep_cfg (%d) get form mt6632_ant_m1.cfg, disable deep sleep feature\n", + pWmtGenConf->disable_deep_sleep_cfg); + ret = 0; + } + return ret; +} + +#endif + +WMT_CO_CLOCK mt6632_co_clock_get(VOID) +{ + return gCoClockEn; +} + + + +static INT32 mt6632_ver_check(VOID) +{ + UINT32 hw_ver = 0; + UINT32 fw_ver = 0; + INT32 iret; + const WMT_IC_INFO_S *p_info = NULL; + ULONG ctrlPa1; + ULONG ctrlPa2; + + + /* 1. identify chip versions: HVR(HW_VER) and FVR(FW_VER) */ + WMT_LOUD_FUNC("MT6632: 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("MT6632: read hw_ver fail:%d\n", iret); + return -2; + } + + WMT_LOUD_FUNC("MT6632: before fw_ver (rom version)\n"); + wmt_core_reg_rw_raw(0, GEN_FVR, &fw_ver, GEN_VER_MASK); + + if (iret) { + WMT_ERR_FUNC("MT6632: read fw_ver fail:%d\n", iret); + return -2; + } + WMT_INFO_FUNC("MT6632: read (hw version)(0x%x), (fw version version)(0x%x)\n", hw_ver, fw_ver); + + p_info = mt6632_find_wmt_ic_info(hw_ver); + + if (p_info == NULL) { + WMT_ERR_FUNC("MT6632: hw_ver(0x%x) find wmt ic info fail\n", hw_ver); + return -3; + } + + WMT_DBG_FUNC("MT6632: wmt ic info: %s.%s (0x%x, patch_ext:%s)\n", + p_info->cChipName, p_info->cChipVersion, + p_info->u4HwVer, p_info->cPatchNameExt); + + /* hw id & version */ + ctrlPa1 = (0x00006632UL << 16) | (hw_ver & 0x0000FFFF); + /* translated fw rom version */ + ctrlPa2 = (fw_ver & 0x0000FFFF); + + iret = wmt_core_ctrl(WMT_CTRL_HWIDVER_SET, &ctrlPa1, &ctrlPa2); + + if (iret) + WMT_WARN_FUNC("MT6632: WMT_CTRL_HWIDVER_SET fail(%d)\n", iret); + + gp_mt6632_info = p_info; + return 0; +} + +static const WMT_IC_INFO_S *mt6632_find_wmt_ic_info(const UINT32 hw_ver) +{ + /* match chipversion with u4HwVer item in mt6632_info_table */ + const UINT32 size = ARRAY_SIZE(mt6632_info_table); + INT32 index; + + /* Leave full match here is a workaround for GPS to distinguish E3/E4 ICs. */ + index = size - 1; + + /* full match */ + while ((index >= 0) + && (hw_ver != mt6632_info_table[index].u4HwVer) /* full match */ + ) { + --index; + } + + if (index >= 0) { + WMT_DBG_FUNC("found ic info(0x%x) by full match! index:%d\n", hw_ver, index); + return &mt6632_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 ((index >= 0) + && (MAJORNUM(hw_ver) != MAJORNUM(mt6632_info_table[index].u4HwVer)) + ) { + --index; + } + + if (index >= 0) { + WMT_INFO_FUNC("MT6632: found ic info for hw_ver(0x%x) by major num! index:%d\n", + hw_ver, index); + return &mt6632_info_table[index]; + } + + WMT_ERR_FUNC + ("MT6632: 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; + ULONG addr = 0; + WMT_GEN_CONF *pWmtGenConf = NULL; + +#define COEX_WMT 0 + +#if CFG_SUBSYS_COEX_NEED + /* no need for MT6632 */ +#define COEX_BT 1 +#define COEX_WIFI 2 +#define COEX_PTA 3 +#define COEX_MISC 4 +#else +#define COEX_WIFI_PATH 1 +#define COEX_EXT_ELAN_GAIN_P1 2 +#endif +#define WMT_COXE_CONFIG_ADJUST_ANTENNA_OPCODE 6 + + /*Get wmt config */ + iRet = wmt_core_ctrl(WMT_CTRL_GET_WMT_CONF, &addr, 0); + + if (iRet) { + WMT_ERR_FUNC("ctrl GET_WMT_CONF fail(%d)\n", iRet); + return -2; + } + + WMT_DBG_FUNC("ctrl GET_WMT_CONF ok(0x%lx)\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_ant_mode:0x%x, coex_wmt_wifi_path:0x%x\n", + pWmtGenConf->coex_wmt_ant_mode, pWmtGenConf->coex_wmt_wifi_path); +#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[4] = WMT_COXE_CONFIG_ADJUST_ANTENNA_OPCODE; + 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); +#else + coex_table[COEX_WIFI_PATH].cmd[5] = + (UINT8)((pWmtGenConf->coex_wmt_wifi_path & 0x00FF) >> 0); + coex_table[COEX_WIFI_PATH].cmd[6] = + (UINT8)((pWmtGenConf->coex_wmt_wifi_path & 0xFF00) >> 8); + + if (gWmtDbgLvl >= WMT_LOG_DBG) { + wmt_core_dump_data(&coex_table[COEX_WIFI_PATH].cmd[0], + coex_table[COEX_WIFI_PATH].str, coex_table[COEX_WIFI_PATH].cmdSz); + } + + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[5] = pWmtGenConf->coex_wmt_ext_elna_gain_p1_support; + /* wmt_ext_elna_gain_p1 D0*/ + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[6] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D0 & 0x000000FF) >> 0); + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[7] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D0 & 0x0000FF00) >> 8); + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[8] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D0 & 0x00FF0000) >> 16); + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[9] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D0 & 0xFF000000) >> 24); + /* wmt_ext_elna_gain_p1 D1*/ + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[10] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D1 & 0x000000FF) >> 0); + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[11] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D1 & 0x0000FF00) >> 8); + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[12] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D1 & 0x00FF0000) >> 16); + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[13] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D1 & 0xFF000000) >> 24); + /* wmt_ext_elna_gain_p1 D2*/ + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[14] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D2 & 0x000000FF) >> 0); + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[15] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D2 & 0x0000FF00) >> 8); + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[16] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D2 & 0x00FF0000) >> 16); + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[17] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D2 & 0xFF000000) >> 24); + /* wmt_ext_elna_gain_p1 D3*/ + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[18] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D3 & 0x000000FF) >> 0); + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[19] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D3 & 0x0000FF00) >> 8); + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[20] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D3 & 0x00FF0000) >> 16); + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[21] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D3 & 0xFF000000) >> 24); + + if (gWmtDbgLvl >= WMT_LOG_DBG) { + wmt_core_dump_data(&coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[0], + coex_table[COEX_EXT_ELAN_GAIN_P1].str, coex_table[COEX_EXT_ELAN_GAIN_P1].cmdSz); + } + +#endif + + iRet = wmt_core_init_script(coex_table, ARRAY_SIZE(coex_table)); + + return iRet; +} + +#if 0 +static INT32 mt6632_set_sdio_driving(void) +{ + INT32 ret = 0; + + UINT32 addr = 0; + 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%x)\n", addr); + + pWmtGenConf = (P_WMT_GEN_CONF) addr; + + /*Check if WMT.cfg exists */ + if (pWmtGenConf->cfgExist == 0) { + WMT_INFO_FUNC("cfgExist == 0, skip config chip\n"); + /*if WMT.cfg not existed, still return success and adopt the default value */ + return 0; + } + + drv_val = pWmtGenConf->sdio_driving_cfg; + + /*Dump the sdio driving related info */ + WMT_INFO_FUNC("sdio driving:0x%x\n", drv_val); + + sdio_driving_table[0].cmd[12] = (UINT8) ((drv_val & 0x00000077UL) >> 0); /* DAT0 and DAT1 */ + sdio_driving_table[0].cmd[13] = (UINT8) ((drv_val & 0x00007700UL) >> 8); /* DAT2 and DAT3 */ + sdio_driving_table[0].cmd[14] = (UINT8) ((drv_val & 0x00070000UL) >> 16); /* CMD */ + + ret = wmt_core_init_script(sdio_driving_table, ARRAY_SIZE(sdio_driving_table)); + + return ret; +} + +static INT32 mt6632_crystal_triming_set(VOID) +{ + INT32 iRet = 0; + PUINT8 pbuf = NULL; + UINT32 bufLen = 0; + WMT_CTRL_DATA ctrlData; + UINT32 uCryTimOffset = 0x6D; + MTK_WCN_BOOL bIsNvramExist = MTK_WCN_BOOL_FALSE; + INT8 cCrystalTimingOffset = 0x0; + UINT8 cCrystalTiming = 0x0; + INT32 iCrystalTiming = 0x0; + MTK_WCN_BOOL bIsCrysTrimEnabled = MTK_WCN_BOOL_FALSE; + UINT32 u4Res; + + bIsNvramExist = MTK_WCN_BOOL_FALSE; + ctrlData.ctrlId = WMT_CTRL_CRYSTAL_TRIMING_GET; + ctrlData.au4CtrlData[0] = (size_t) "/data/nvram/APCFG/APRDEB/WIFI"; + ctrlData.au4CtrlData[1] = (size_t) &pbuf; + ctrlData.au4CtrlData[2] = (size_t) &bufLen; + + iRet = wmt_ctrl(&ctrlData); + + if (iRet != 0) { + WMT_ERR_FUNC("MT6632: 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("MT6632: nvram pBuf(%p), bufLen(%d)\n", pbuf, bufLen); + + if (bufLen < (uCryTimOffset + 1)) { + WMT_ERR_FUNC + ("MT6632: 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 = (UINT8) cCrystalTimingOffset & 0x7f; + } + + WMT_DBG_FUNC("cCrystalTimingOffset (%d), bIsCrysTrimEnabled(%d)\n", + cCrystalTimingOffset, bIsCrysTrimEnabled); + } + + ctrlData.ctrlId = WMT_CTRL_CRYSTAL_TRIMING_PUT; + ctrlData.au4CtrlData[0] = (size_t) "/data/nvram/APCFG/APRDEB/WIFI"; + iRet = wmt_ctrl(&ctrlData); + + if (iRet != 0) { + WMT_ERR_FUNC("MT6632: WMT_CTRL_CRYSTAL_TRIMING_PUT fail:%d\n", iRet); + iRet = -2; + } else { + WMT_DBG_FUNC("MT6632: WMT_CTRL_CRYSTAL_TRIMING_PUT succeed\n"); + } + } + + if ((bIsNvramExist == MTK_WCN_BOOL_TRUE) && (bIsCrysTrimEnabled == MTK_WCN_BOOL_TRUE)) { + /*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); + if (iCrystalTiming > 0x7f) + cCrystalTiming = 0x7f; + else if (iCrystalTiming < 0) + cCrystalTiming = 0; + else + cCrystalTiming = iCrystalTiming; + WMT_DBG_FUNC("cCrystalTiming (0x%x)\n", cCrystalTiming); + /* set_crystal_timing_script */ + /*set crystal trim value command*/ + WMT_SET_CRYSTAL_TRIMING_CMD[4] = 0x1; + WMT_SET_CRYSTAL_TRIMING_EVT[4] = 0x1; + + WMT_SET_CRYSTAL_TRIMING_CMD[5] = cCrystalTiming; + WMT_GET_CRYSTAL_TRIMING_EVT[5] = cCrystalTiming; + + iRet = + wmt_core_init_script(set_crystal_timing_script, + 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, + ARRAY_SIZE(get_crystal_timing_script)); + + if (iRet) { + WMT_ERR_FUNC("get_crystal_timing_script fail(%d)\n", iRet); + iRet = -6; + } else { + WMT_INFO_FUNC("succeed, updated crystal timing value (0x%x)\n", + WMT_GET_CRYSTAL_TRIMING_EVT[5]); + iRet = 0x0; + } + } + } + +done: + return iRet; +} +#endif + +static INT32 mt6632_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 mt6632_patch_dwn(UINT32 index) +{ + INT32 iRet = -1; + P_WMT_PATCH patchHdr = NULL; + PUINT8 pBuf = NULL; + PUINT8 pPatchBuf = NULL; + UINT32 patchSize; + UINT32 fragSeq; + UINT32 fragNum; + UINT16 fragSize = 0; + UINT16 cmdLen; + UINT32 offset; + UINT32 u4Res; + UINT8 evtBuf[8]; + UINT8 addressevtBuf[12]; + UINT8 addressByte[4]; + PINT8 cDataTime = NULL; + /*PINT8 cPlat = NULL; */ + UINT16 u2HwVer = 0; + UINT16 u2SwVer = 0; + UINT32 u4PatchVer = 0; + UINT32 patchSizePerFrag = 0; + WMT_CTRL_DATA ctrlData; + + /*1.check hardware information */ + if (gp_mt6632_info == NULL) { + WMT_ERR_FUNC("null gp_mt6632_info!\n"); + return -1; + } + + osal_memset(gFullPatchName, 0, osal_sizeof(gFullPatchName)); + + ctrlData.ctrlId = WMT_CTRL_GET_PATCH_INFO; + ctrlData.au4CtrlData[0] = index + 1; + ctrlData.au4CtrlData[1] = (size_t) &gFullPatchName; + ctrlData.au4CtrlData[2] = (size_t) &addressByte; + iRet = wmt_ctrl(&ctrlData); + WMT_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] = (size_t) NULL; + ctrlData.au4CtrlData[1] = (size_t) &gFullPatchName; + ctrlData.au4CtrlData[2] = (size_t) &pBuf; + ctrlData.au4CtrlData[3] = (size_t) &patchSize; + iRet = wmt_ctrl(&ctrlData); + + if (iRet) { + WMT_ERR_FUNC("wmt_core: WMT_CTRL_GET_PATCH fail:%d\n", iRet); + iRet -= 1; + goto done; + } + + /* |<-BCNT_PATCH_BUF_HEADROOM(8) bytes dummy allocated->|<-patch file->| */ + /* patch file with header: + * |<-patch header: 28 Bytes->|<-patch body: X Bytes ----->| + */ + pPatchBuf = osal_malloc(patchSize); + if (pPatchBuf == NULL) { + WMT_ERR_FUNC("vmalloc pPatchBuf for patch download fail\n"); + return -2; + } + osal_memcpy(pPatchBuf, pBuf, patchSize); + patchHdr = (P_WMT_PATCH) pPatchBuf; + + /* check patch file information */ + + cDataTime = patchHdr->ucDateTime; + u2HwVer = patchHdr->u2HwVer; + u2SwVer = patchHdr->u2SwVer; + u4PatchVer = patchHdr->u4PatchVer; + + osal_memcpy(&gp_mt6632_patch_info, patchHdr, osal_sizeof(WMT_PATCH)); + + /*cPlat = &patchHdr->ucPLat[0]; */ + + cDataTime[15] = '\0'; + + if (index == 0) { + WMT_INFO_FUNC("Combo Patch:Build Time(%s)Hw(0x%x) Sw(0x%x) Ph(0x%04x)Platform(%c%c%c%c)\n", + cDataTime, ((u2HwVer & 0x00ff) << 8) | ((u2HwVer & 0xff00) >> 8), + ((u2SwVer & 0x00ff) << 8) | ((u2SwVer & 0xff00) >> 8), + ((u4PatchVer & 0xff000000) >> 24) | ((u4PatchVer & 0x00ff0000) >> 16), + patchHdr->ucPLat[0], patchHdr->ucPLat[1], patchHdr->ucPLat[2], patchHdr->ucPLat[3]); + } + + /* remove patch header: + * |<-patch body: X Bytes (X=patchSize)--->| + */ + if (patchSize < sizeof(WMT_PATCH)) { + WMT_ERR_FUNC("error patch size\n"); + iRet = -1; + goto done; + } + patchSize -= sizeof(WMT_PATCH); + pPatchBuf += sizeof(WMT_PATCH); + patchSizePerFrag = DEFAULT_PATCH_FRAG_SIZE; + + /* remove patch checksum, MT6632 no need: + * |<-patch checksum: 2Bytes->|<-patch body: X Bytes (X=patchSize)--->| + */ + pPatchBuf += BCNT_PATCH_BUF_CHECKSUM; + patchSize -= BCNT_PATCH_BUF_CHECKSUM; + + /* reserve 1st patch cmd space before patch body + * |<-WMT_CMD: 5Bytes->|<-patch body: X Bytes (X=patchSize)----->| + */ + pPatchBuf -= 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 patch address command */ + osal_memcpy(&WMT_PATCH_ADDRESS_CMD[5], addressByte, osal_sizeof(addressByte)); + WMT_INFO_FUNC("4 bytes address command:0x%02x,0x%02x,0x%02x,0x%02x", + WMT_PATCH_ADDRESS_CMD[5], WMT_PATCH_ADDRESS_CMD[6], + WMT_PATCH_ADDRESS_CMD[7], WMT_PATCH_ADDRESS_CMD[8]); + 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 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_ADDRESS_EVT), &u4Res); + + if (iRet || (u4Res != sizeof(WMT_PATCH_ADDRESS_EVT))) { + WMT_ERR_FUNC("wmt_core:wmt patch address EVT fail(%d),size(%d),index(%d)\n", iRet, + u4Res, index); + mtk_wcn_stp_dbg_dump_package(); + 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,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(pPatchBuf + offset - sizeof(WMT_PATCH_CMD), WMT_PATCH_CMD, + sizeof(WMT_PATCH_CMD)); + + iRet = + wmt_core_tx(pPatchBuf + 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(%zu, %d) fail(%d)\n", fragSeq, + fragSize + sizeof(WMT_PATCH_CMD), u4Res, iRet); + iRet -= 1; + break; + } + + WMT_DBG_FUNC("wmt_core: write fragSeq(%d) size(%zu, %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(%zu, %d) fail(%d)\n", + sizeof(WMT_PATCH_EVT), u4Res, iRet); + mtk_wcn_stp_dbg_dump_package(); + iRet -= 1; + break; + } +#if CFG_CHECK_WMT_RESULT + + if (osal_memcmp(evtBuf, WMT_PATCH_EVT, sizeof(WMT_PATCH_EVT)) != 0) { + WMT_ERR_FUNC("rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%zu):[%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(%zu, %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: + if (patchHdr != NULL) { + osal_free(patchHdr); + pPatchBuf = NULL; + patchHdr = NULL; + } + + /* 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; +} + +#if CFG_WMT_FILTER_MODE_SETTING +static INT32 wmt_stp_wifi_lte_coex(VOID) +{ + INT32 iRet; + ULONG addr = 0; + WMT_GEN_CONF *pWmtGenConf = NULL; + + /*Get wmt config */ + iRet = wmt_core_ctrl(WMT_CTRL_GET_WMT_CONF, &addr, 0); + if (iRet) { + WMT_ERR_FUNC("ctrl GET_WMT_CONF fail(%d)\n", iRet); + return -2; + } + WMT_DBG_FUNC("ctrl GET_WMT_CONF ok(0x%08lx)\n", addr); + + pWmtGenConf = (P_WMT_GEN_CONF) addr; + + /*Check if WMT.cfg exists */ + if (pWmtGenConf->cfgExist == 0) { + WMT_INFO_FUNC("cfgExist == 0, skip config chip\n"); + /*if WMT.cfg not existed, still return success and adopt the default value */ + return 0; + } + + if (pWmtGenConf->coex_wmt_filter_mode == 0) { + iRet = + wmt_core_init_script(set_wifi_lte_coex_table_0, + ARRAY_SIZE(set_wifi_lte_coex_table_0)); + if (iRet) + WMT_ERR_FUNC("wmt_core:set_wifi_lte_coex_table_0 fail(%d)\n", iRet); + else + WMT_DBG_FUNC("wmt_core:set_wifi_lte_coex_table_0 ok\n"); + } + + return iRet; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_ic_soc.c b/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_ic_soc.c new file mode 100644 index 0000000000000..922f69147a7f3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_ic_soc.c @@ -0,0 +1,4062 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-IC]" +#define CFG_IC_SOC 1 + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "osal_typedef.h" +#include "wmt_ic.h" +#include "wmt_core.h" +#include "wmt_lib.h" +#include "stp_core.h" +#include "mtk_wcn_consys_hw.h" +#include "wmt_step.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define DEFAULT_PATCH_FRAG_SIZE (1000) +#define WMT_PATCH_FRAG_1ST (0x1) +#define WMT_PATCH_FRAG_MID (0x2) +#define WMT_PATCH_FRAG_LAST (0x3) + +#define CFG_CHECK_WMT_RESULT (1) +/* BT Port 2 Feature. this command does not need + * after coex command is downconfirmed by LC, + */ +#define CFG_WMT_BT_PORT2 (0) + +#define CFG_SET_OPT_REG (0) +#define CFG_WMT_I2S_DBGUART_SUPPORT (0) +#define CFG_SET_OPT_REG_SWLA (0) +#define CFG_SET_OPT_REG_MCUCLK (0) +#define CFG_SET_OPT_REG_MCUIRQ (0) + +#define CFG_SUBSYS_COEX_NEED 0 + +#define CFG_WMT_COREDUMP_ENABLE 0 + +#define CFG_WMT_MULTI_PATCH (1) + +#define CFG_WMT_CRYSTAL_TIMING_SET (0) + +#define CFG_WMT_SDIO_DRIVING_SET (0) + +#define CFG_WMT_UART_HIF_USE (0) + +#define CFG_WMT_WIFI_5G_SUPPORT (1) + +#define CFG_WMT_PATCH_DL_OPTM (1) +#if CFG_WMT_LTE_COEX_HANDLING +#define CFG_WMT_FILTER_MODE_SETTING (1) +#else +#define CFG_WMT_FILTER_MODE_SETTING (0) +#endif +/* #define MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT (0) */ + +#define CFG_WMT_POWER_ON_DLM (1) + +/* Define local option for debug purpose */ +#define CFG_CALIBRATION_BACKUP_RESTORE (1) +#define CALIBRATION_BACKUP_RESTORE_BUFFER_SIZE (640) + +#define PATCH_BUILD_TIME_SIZE (16) +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +static UINT8 gFullPatchName[NAME_MAX + 1]; +static const WMT_IC_INFO_S *gp_soc_info; +static WMT_PATCH gp_soc_patch_info; +static WMT_CO_CLOCK gCoClockEn = WMT_CO_CLOCK_DIS; + +#if CFG_CALIBRATION_BACKUP_RESTORE +static PUINT8 gBTCalResult; +static UINT16 gBTCalResultSize; +static UINT32 gWiFiCalAddrOffset; +static UINT32 gWiFiCalSize; +static PUINT8 gWiFiCalResult; +#endif + +#if 0 +static UINT8 WMT_WAKEUP_DIS_GATE_CMD[] = { 0x1, 0x3, 0x01, 0x00, 0x04 }; +static UINT8 WMT_WAKEUP_DIS_GATE_EVT[] = { 0x2, 0x3, 0x02, 0x0, 0x0, 0x04 }; + +static UINT8 WMT_WAKEUP_EN_GATE_CMD[] = { 0x1, 0x3, 0x01, 0x00, 0x05 }; +static UINT8 WMT_WAKEUP_EN_GATE_EVT[] = { 0x2, 0x3, 0x02, 0x0, 0x0, 0x05 }; +#endif + +#if CFG_WMT_UART_HIF_USE +static UINT8 WMT_QUERY_BAUD_CMD[] = { 0x01, 0x04, 0x01, 0x00, 0x02 }; +static UINT8 WMT_QUERY_BAUD_EVT_115200[] = { 0x02, 0x04, 0x06, 0x00, 0x00, 0x02, 0x00, 0xC2, 0x01, 0x00 }; +static UINT8 WMT_QUERY_BAUD_EVT_X[] = { 0x02, 0x04, 0x06, 0x00, 0x00, 0x02, 0xAA, 0xAA, 0xAA, 0xBB }; +static UINT8 WMT_SET_BAUD_CMD_X[] = { 0x01, 0x04, 0x05, 0x00, 0x01, 0xAA, 0xAA, 0xAA, 0xBB }; +static UINT8 WMT_SET_BAUD_EVT[] = { 0x02, 0x04, 0x02, 0x00, 0x00, 0x01 }; +static UINT8 WMT_SET_WAKEUP_WAKE_CMD_RAW[] = { 0xFF }; +static UINT8 WMT_SET_WAKEUP_WAKE_EVT[] = { 0x02, 0x03, 0x02, 0x00, 0x00, 0x03 }; +#endif +static UINT8 WMT_QUERY_STP_CMD[] = { 0x01, 0x04, 0x01, 0x00, 0x04 }; +static UINT8 WMT_QUERY_STP_EVT_DEFAULT[] = { 0x02, 0x04, 0x06, 0x00, 0x00, 0x04, 0x11, 0x00, 0x00, 0x00 }; +static UINT8 WMT_QUERY_STP_EVT[] = { 0x02, 0x04, 0x06, 0x00, 0x00, 0x04, 0xDB, 0x0E, 0x68, 0x01 }; +static UINT8 WMT_PATCH_CMD[] = { 0x01, 0x01, 0x00, 0x00, 0x00 }; +static UINT8 WMT_PATCH_EVT[] = { 0x02, 0x01, 0x01, 0x00, 0x00 }; +static UINT8 WMT_RESET_CMD[] = { 0x01, 0x07, 0x01, 0x00, 0x04 }; +static UINT8 WMT_RESET_EVT[] = { 0x02, 0x07, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_SET_CHIP_ID_CMD[] = { 0x01, 0x02, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00 }; +static UINT8 WMT_SET_CHIP_ID_EVT[] = { 0x02, 0x02, 0x01, 0x00, 0x00}; + +#if CFG_WMT_BT_PORT2 +static UINT8 WMT_BTP2_CMD[] = { 0x01, 0x10, 0x03, 0x00, 0x01, 0x03, 0x01 }; +static UINT8 WMT_BTP2_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; +#endif + +static UINT8 WMT_QUERY_A_DIE_CMD[] = { 0x01, 0x02, 0x01, 0x00, 0x12 }; +static UINT8 WMT_QUERY_A_DIE_EVT[] = { 0x02, 0x02, 0x05, 0x00, 0x00 }; + +/*soc patial patch address cmd & evt need firmware owner provide*/ +#if CFG_WMT_MULTI_PATCH +static UINT8 WMT_PATCH_ADDRESS_CMD[] = { + 0x01, 0x08, 0x10, 0x00, + 0x01, 0x01, 0x00, 0x01, + 0x3c, 0x02, 0x09, 0x02, + 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff +}; +static UINT8 WMT_PATCH_ADDRESS_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; + +static UINT8 WMT_PATCH_P_ADDRESS_CMD[] = { + 0x01, 0x08, 0x10, 0x00, + 0x01, 0x01, 0x00, 0x01, + 0xc4, 0x04, 0x09, 0x02, + 0x00, 0x3f, 0x00, 0x01, + 0xff, 0xff, 0xff, 0xff +}; +static UINT8 WMT_PATCH_P_ADDRESS_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; + +static UINT8 WMT_PATCH_PDA_CFG_CMD[] = { + 0x01, 0x01, 0x11, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*Target address*/ + 0x00, 0x00, 0x00, 0x00, /*Download size*/ + 0x00, 0x00, 0x00, 0x00, /*Scramble key*/ + 0x2f, 0x02, 0x02, 0x00 /*Configuration*/ +}; +static UINT8 WMT_PATCH_PDA_CFG_EVT[] = { 0x02, 0x01, 0x01, 0x00, 0x00}; + +static UINT8 WMT_PATCH_ADDRESS_CMD_NEW[] = { 0x01, 0x01, 0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}; + +static UINT8 WMT_PATCH_ADDRESS_EVT_NEW[] = { 0x02, 0x01, 0x01, 0x00, 0x00}; +#endif + +/*coex cmd/evt++*/ +static UINT8 WMT_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x02, 0x00, 0x01, 0x00 }; +static UINT8 WMT_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +#if CFG_SUBSYS_COEX_NEED +static UINT8 WMT_BT_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x0B, + 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, + 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xAA +}; +static UINT8 WMT_BT_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_WIFI_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x0C, + 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xAA +}; +static UINT8 WMT_WIFI_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_PTA_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x0A, + 0x00, 0x04, + 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xEE, 0xFF, 0xFF, 0xFE +}; +static UINT8 WMT_PTA_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_MISC_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x09, + 0x00, 0x05, + 0xAA, 0xAA, 0xAA, 0xAA, + 0xBB, 0xBB, 0xBB, 0xBB +}; +static UINT8 WMT_MISC_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; +#else +static UINT8 WMT_COEX_WIFI_PATH_CMD[] = { 0x01, 0x10, 0x03, 0x00, 0x1A, 0x0F, 0x00 }; +static UINT8 WMT_COEX_WIFI_PATH_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_COEX_EXT_ELAN_GAIN_P1_CMD[] = { 0x01, 0x10, 0x12, 0x00, 0x1B, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static UINT8 WMT_COEX_EXT_ELAN_GAIN_P1_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_COEX_EXT_EPA_MODE_CMD[] = { 0x01, 0x10, 0x02, 0x00, 0x1D, 0x00 }; +static UINT8 WMT_COEX_EXT_EPA_MODE_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; +#endif + +static UINT8 WMT_EPA_SETTING_CONFIG_CMD[] = { 0x01, 0x02, 0x02, 0x00, 0x0E, 0x00 }; +static UINT8 WMT_EPA_SETTING_CONFIG_EVT[] = { 0x02, 0x02, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_EPA_ELNA_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +/*coex cmd/evt--*/ +static UINT8 WMT_SET_STP_CMD[] = { 0x01, 0x04, 0x05, 0x00, 0x03, 0xDB, 0x0E, 0x68, 0x01 }; +static UINT8 WMT_SET_STP_EVT[] = { 0x02, 0x04, 0x02, 0x00, 0x00, 0x03 }; +static UINT8 WMT_STRAP_CONF_CMD_FM_COMM[] = { 0x01, 0x05, 0x02, 0x00, 0x02, 0x02 }; +static UINT8 WMT_STRAP_CONF_EVT[] = { 0x02, 0x05, 0x02, 0x00, 0x00, 0x02 }; + +#if 0 +static UINT8 WMT_SET_OSC32K_BYPASS_CMD[] = { 0x01, 0x0A, 0x01, 0x00, 0x05 }; +static UINT8 WMT_SET_OSC32K_BYPASS_EVT[] = { 0x02, 0x0A, 0x01, 0x00, 0x00 }; +#endif + +#if 0 +/* to enable dump feature */ +static UINT8 WMT_CORE_DUMP_EN_CMD[] = { 0x01, 0x0F, 0x02, 0x00, 0x03, 0x01 }; +static UINT8 WMT_CORE_DUMP_EN_EVT[] = { 0x02, 0x0F, 0x01, 0x00, 0x00 }; + +/* to get system stack dump when f/w assert */ +static UINT8 WMT_CORE_DUMP_LEVEL_01_CMD[] = { 0x1, 0x0F, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static UINT8 WMT_CORE_DUMP_LEVEL_01_EVT[] = { 0x2, 0x0F, 0x01, 0x00, 0x00 }; + +/* to get task and system stack dump when f/w assert */ +static UINT8 WMT_CORE_DUMP_LEVEL_02_CMD[] = { 0x1, 0x0F, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static UINT8 WMT_CORE_DUMP_LEVEL_02_EVT[] = { 0x2, 0x0F, 0x01, 0x00, 0x00 }; + +/* to get bt related memory dump when f/w assert */ +static UINT8 WMT_CORE_DUMP_LEVEL_03_CMD[] = { 0x1, 0x0F, 0x07, 0x00, 0x03, 0x00, 0x00, 0x09, 0xF0, 0x00, 0x0A }; +static UINT8 WMT_CORE_DUMP_LEVEL_03_EVT[] = { 0x2, 0x0F, 0x01, 0x00, 0x00 }; +#endif +/* to get full dump when f/w assert */ +static UINT8 WMT_CORE_DUMP_LEVEL_04_CMD[] = { 0x1, 0x0F, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static UINT8 WMT_CORE_DUMP_LEVEL_04_EVT[] = { 0x2, 0x0F, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_CORE_CO_CLOCK_CMD[] = { 0x1, 0x0A, 0x02, 0x00, 0x08, 0x03 }; +static UINT8 WMT_CORE_CO_CLOCK_EVT[] = { 0x2, 0x0A, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_CORE_START_RF_CALIBRATION_CMD[] = { 0x1, 0x14, 0x1, 0x00, 0x01 }; +static UINT8 WMT_CORE_START_RF_CALIBRATION_EVT[] = { 0x2, 0x14, 0x02, 0x00, 0x00, 0x01 }; + +#if CFG_CALIBRATION_BACKUP_RESTORE +static UINT8 WMT_CORE_GET_RF_CALIBRATION_CMD[] = { 0x1, 0x14, 0x01, 0x00, 0x03 }; +/* byte[2] & byte[3] is left for length */ +static UINT8 WMT_CORE_SEND_RF_CALIBRATION_CMD[] = { 0x1, 0x14, 0x00, 0x00, 0x02, 0x00, 0x00 }; +static UINT8 WMT_CORE_SEND_RF_CALIBRATION_EVT_OK[] = { 0x2, 0x14, 0x02, 0x00, 0x00, 0x02 }; +static UINT8 WMT_CORE_SEND_RF_CALIBRATION_EVT_RECAL[] = { 0x2, 0x14, 0x02, 0x00, 0x01, 0x02 }; +#endif + +#if (MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT) +static UINT8 WMT_SET_I2S_SLAVE_REG_CMD[] = { 0x01, 0x08, 0x10, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ + , 0x78, 0x00, 0x05, 0x80 /*addr:0x80050078 */ + , 0x00, 0x00, 0x11, 0x01 /*value:0x11010000 */ + , 0x00, 0x00, 0x77, 0x07 /*mask:0x07770000 */ +}; + +static UINT8 WMT_SET_I2S_SLAVE_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ +}; + +static UINT8 WMT_SET_DAI_TO_PAD_REG_CMD[] = { 0x01, 0x08, 0x10, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ + , 0x74, 0x00, 0x05, 0x80 /*addr:0x80050074 */ + , 0x44, 0x44, 0x00, 0x00 /*value:0x11010000 */ + , 0x77, 0x77, 0x00, 0x00 /*mask:0x07770000 */ +}; + +static UINT8 WMT_SET_DAI_TO_PAD_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ +}; + +static UINT8 WMT_SET_DAI_REG_CMD[] = { 0x01, 0x08, 0x10, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ + , 0xA0, 0x00, 0x05, 0x80 /*addr:0x80050074 */ + , 0x04, 0x00, 0x00, 0x00 /*value:0x11010000 */ + , 0x04, 0x00, 0x00, 0x00 /*mask:0x07770000 */ +}; + +static UINT8 WMT_SET_DAI_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ +}; +#endif + +#if !(CFG_IC_SOC) /* For MT6628 no need to set ALLEINT registers, done in f/w */ +/* enable all interrupt */ +static UINT8 WMT_SET_ALLINT_REG_CMD[] = { 0x01, 0x08, 0x10, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ + , 0x00, 0x03, 0x05, 0x80 /*addr:0x80050300 */ + , 0x00, 0xC4, 0x00, 0x00 /*value:0x0000C400 */ + , 0x00, 0xC4, 0x00, 0x00 /*mask:0x0000C400 */ +}; + +static UINT8 WMT_SET_ALLINT_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ +}; + +#endif + +#if CFG_SET_OPT_REG_SWLA /* enable swla: eesk(7) eecs(8) oscen(19) sck0(24) scs0(25) */ +static UINT8 WMT_SET_SWLA_REG_CMD[] = { 0x01, 0x08, 0x1C, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x02 /*2 registers */ + , 0x10, 0x01, 0x05, 0x80 /*addr:0x80050110 */ + , 0x10, 0x10, 0x01, 0x00 /*value:0x00011010 */ + , 0xF0, 0xF0, 0x0F, 0x00 /*mask:0x000FF0F0 */ + , 0x40, 0x01, 0x05, 0x80 /*addr:0x80050140 */ + , 0x00, 0x10, 0x01, 0x00 /*value:0x00011000 */ + , 0x00, 0xF0, 0x0F, 0x00 /*mask:0x000FF000 */ +}; + +static UINT8 WMT_SET_SWLA_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x02 /*2 registers */ +}; +#endif + +#if CFG_SET_OPT_REG_MCUCLK /* enable mcu clk: antsel_4, eedi */ +static UINT8 WMT_SET_MCUCLK_REG_CMD[] = { 0x01, 0x08, (4 + 12 * 4), 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /* type: reg */ + , 0x00 /* rev */ + , 0x04 /* 4 registers */ + , 0x00, 0x04, 0x00, 0x80 /* addr:0x8000 0400 */ + , 0x00, 0x14, 0x00, 0x00 /* value:0x0000 1400(osc, hclk), 0x0000 1501(PLL, en) */ + , 0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000 FFFF */ + , 0x80, 0x01, 0x05, 0x80 /* addr:0x8005 0180 */ + , 0x12, 0x13, 0x00, 0x00 /* value:0x0000 1312(osc, hclk), 0x0000 1a19(PLL, en) */ + , 0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000 FFFF */ + , 0x00, 0x01, 0x05, 0x80 /* addr:0x8005 0100 */ + , 0x00, 0x00, 0x02, 0x00 /* value:0x0002 0000 */ + , 0x00, 0x00, 0x0F, 0x00 /* mask:0x000F 0000 */ + , 0x10, 0x01, 0x05, 0x80 /* addr:0x8005 0110 */ + , 0x02, 0x00, 0x00, 0x00 /* value:0x0000 0002 */ + , 0x0F, 0x00, 0x00, 0x00 /* mask:0x0000 000F */ +}; + +static UINT8 WMT_SET_MCUCLK_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /* S: 0 */ + , 0x00 /* type: reg */ + , 0x00 /* rev */ + , 0x04 /* 4 registers */ +}; +#endif + +#if CFG_WMT_I2S_DBGUART_SUPPORT /* register write for debug uart */ +static UINT8 WMT_SET_DBGUART_REG_CMD[] = { 0x01, 0x08, 0x1C, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x02 /*2 registers */ + , 0x30, 0x01, 0x05, 0x80 /*addr:0x80050130 */ + , 0x00, 0x00, 0x00, 0x00 /*value:0x00000000 */ + , 0xF0, 0x0F, 0x00, 0x00 /*mask:0x00000FF0 */ + , 0x40, 0x01, 0x05, 0x80 /*addr:0x80050140 */ + , 0x00, 0x01, 0x00, 0x00 /*value:0x00000100 */ + , 0x00, 0x01, 0x00, 0x00 /*mask:0x00000100 */ +}; + +static UINT8 WMT_SET_DBGUART_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x02 /*2 registers */ +}; +#endif + +#if CFG_SET_OPT_REG_MCUIRQ /* enable mcu irq: antsel_4, wlan_act */ +#if 1 /* Ray */ +static UINT8 WMT_SET_MCUIRQ_REG_CMD[] = { 0x01, 0x08, (4 + 12 * 4), 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /* type: reg */ + , 0x00 /* rev */ + , 0x04 /* 4 registers */ + , 0x00, 0x04, 0x00, 0x80 /* addr:0x8000_0400 */ + , 0x03, 0x14, 0x00, 0x00 /* value:0x0000_1403 check confg debug flag 3 low word */ + , 0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000_FFFF */ + /* cirq_int_n */ + , 0x10, 0x01, 0x05, 0x80 /* addr:0x8005_0110 */ + , 0x02, 0x00, 0x00, 0x00 /* value:0x0000_0002 set EEDI as cirq_int_n debug flag (monitor flag2) */ + , 0x07, 0x00, 0x00, 0x00 /* mask:0x0000_0007 */ + , 0x00, 0x01, 0x05, 0x80 /* addr:0x8005_0100 */ + , 0x00, 0x00, 0x02, 0x00 /* value:0x0002_0000 (ANTSEL4=>monitor flag 0, ahb_x2_gt_ck debug flag) */ + , 0x00, 0x00, 0x07, 0x00 /* mask:0x0007_0000 */ + /* 1. ARM irq_b, monitor flag 0 */ + , 0x80, 0x01, 0x05, 0x80 /* addr:0x8005_0180 */ + , 0x1F, 0x1E, 0x00, 0x00 /* value:0x0000_1E1F check mcusys debug flag */ + , 0x7F, 0x7F, 0x00, 0x00 /* mask:0x0000_7F7F */ +}; + +static UINT8 WMT_SET_MCUIRQ_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /* S: 0 */ + , 0x00 /* type: reg */ + , 0x00 /* rev */ + , 0x04 /* 5 registers */ +}; +#elif 0 /* KC */ +static UINT8 WMT_SET_MCUIRQ_REG_CMD[] = { 0x01, 0x08, (4 + 12 * 5), 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /* type: reg */ + , 0x00 /* rev */ + , 0x05 /* 5 registers */ + , 0x00, 0x04, 0x00, 0x80 /* addr:0x8000_0400 */ + , 0x00, 0x02, 0x00, 0x00 /* value:0x0000_0200 [15:8]=0x2 arm irq_b, 0xA irq_bus[5] bt_timcon_irq_b */ + , 0x00, 0xFF, 0x00, 0x00 /* mask:0x0000_FF00 */ + /* 1. ARM irq_b, monitor flag 0 */ + , 0x80, 0x01, 0x05, 0x80 /* addr:0x8005_0180 */ + , 0x18, 0x00, 0x00, 0x00 /* value:0x0000_0018 [6:0]=001_1000 (monitor flag 0 select, MCUSYS, SEL:8) */ + , 0x7F, 0x00, 0x00, 0x00 /* mask:0x0000_007F */ + , 0x00, 0x01, 0x05, 0x80 /* addr:0x8005_0100 */ + , 0x00, 0x00, 0x02, 0x00 /* value:0x0002_0000 (ANTSEL4=>monitor flag 0) */ + , 0x00, 0x00, 0x07, 0x00 /* mask:0x0007_0000 */ + /* 2. irq_bus[5] bt_timcon_irq_b monitor flag 15 */ + , 0xB0, 0x01, 0x05, 0x80 /* addr:0x8005_01B0 */ + , 0x00, 0x00, 0x00, 0x16 /* value:0x1600_0000 [30:24]=001_0110 (monitor flag 15 select, MCUSYS, SEL:6) */ + , 0x00, 0x00, 0x00, 0x7F /* mask:0x7F00_0000 */ + , 0x30, 0x01, 0x05, 0x80 /* addr:0x8005_0130 */ + , 0x00, 0x20, 0x00, 0x00 /* value:0x0000_2000 (WLAN_ACT=>monitor flag 15) */ + , 0x00, 0x70, 0x00, 0x00 /* mask:0x0000_7000 */ +}; + +static UINT8 WMT_SET_MCUIRQ_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /* S: 0 */ + , 0x00 /* type: reg */ + , 0x00 /* rev */ + , 0x05 /* 5 registers */ +}; +#endif +#endif + +#if CFG_WMT_CRYSTAL_TIMING_SET +static UINT8 WMT_SET_CRYSTAL_TRIMING_CMD[] = { 0x01, 0x12, 0x02, 0x00, 0x01, 0x00 }; +static UINT8 WMT_SET_CRYSTAL_TRIMING_EVT[] = { 0x02, 0x12, 0x02, 0x00, 0x01, 0x00 }; + +static UINT8 WMT_GET_CRYSTAL_TRIMING_CMD[] = { 0x01, 0x12, 0x02, 0x00, 0x00, 0x00 }; +static UINT8 WMT_GET_CRYSTAL_TRIMING_EVT[] = { 0x02, 0x12, 0x02, 0x00, 0x00, 0x00 }; +#endif + +#ifdef CFG_WMT_READ_EFUSE_VCN33 +static UINT8 WMT_GET_EFUSE_VCN33_CMD[] = { 0x01, 0x12, 0x02, 0x00, 0x04, 0x00 }; +static UINT8 WMT_GET_EFUSE_VCN33_EVT[] = { 0x02, 0x12, 0x02, 0x00, 0x04, 0x00 }; +#endif + +/* set sdio driving */ +#if CFG_WMT_SDIO_DRIVING_SET +static UINT8 WMT_SET_SDIO_DRV_REG_CMD[] = { 0x01, 0x08, 0x10, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ + , 0x50, 0x00, 0x05, 0x80 /*addr:0x80050050 */ + , 0x44, 0x44, 0x04, 0x00 /*value:0x00044444 */ + , 0x77, 0x77, 0x07, 0x00 /*mask:0x00077777 */ +}; + +static UINT8 WMT_SET_SDIO_DRV_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ +}; +#endif + +#if CFG_WMT_WIFI_5G_SUPPORT +static UINT8 WMT_GET_SOC_ADIE_CHIPID_CMD[] = { 0x01, 0x13, 0x04, 0x00, 0x02, 0x04, 0x24, 0x00 }; +static UINT8 WMT_GET_SOC_ADIE_CHIPID_EVT[] = { + 0x02, 0x13, 0x09, 0x00, 0x00, 0x02, 0x04, 0x24, + 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static UINT8 WMT_GET_SOC_6625_L_CMD[] = { 0x01, 0x13, 0x04, 0x00, 0x02, 0x04, 0x20, 0x01 }; +static UINT8 WMT_GET_SOC_6625_L_EVT[] = { + 0x02, 0x13, 0x09, 0x00, 0x00, 0x02, 0x04, 0x20, + 0x01, 0x00, 0x00, 0x00, 0x00 +}; +#endif + +#if CFG_WMT_PATCH_DL_OPTM +static UINT8 WMT_SET_MCU_CLK_EN_CMD[] = { + 0x01, 0x08, 0x10, 0x00, + 0x01, 0x01, 0x00, 0x01, + 0x34, 0x03, 0x00, 0x80, + 0x00, 0x00, 0x01, 0x00, + 0xff, 0xff, 0xff, 0xff +}; +static UINT8 WMT_SET_MCU_CLK_EN_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; + +static UINT8 WMT_SET_MCU_CLK_138_CMD[] = { + 0x01, 0x08, 0x10, 0x00, + 0x01, 0x01, 0x00, 0x01, + 0x0c, 0x01, 0x00, 0x80, + 0x59, 0x4d, 0x84, 0x00, + 0xff, 0xff, 0xff, 0xff +}; +static UINT8 WMT_SET_MCU_CLK_138_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; + +static UINT8 WMT_SET_MCU_CLK_26_CMD[] = { + 0x01, 0x08, 0x10, 0x00, + 0x01, 0x01, 0x00, 0x01, + 0x0c, 0x01, 0x00, 0x80, + 0x00, 0x4d, 0x84, 0x00, + 0xff, 0xff, 0xff, 0xff +}; +static UINT8 WMT_SET_MCU_CLK_26_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; + +static UINT8 WMT_SET_MCU_CLK_DIS_CMD[] = { + 0x01, 0x08, 0x10, 0x00, + 0x01, 0x01, 0x00, 0x01, + 0x34, 0x03, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff +}; +static UINT8 WMT_SET_MCU_CLK_DIS_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; + +/*only for 6797,enable high clock frequency*/ +/*CLK EN*/ +static UINT8 WMT_SET_MCU_CLK_EN_6797[] = { + 0x01, 0x08, 0x10, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x10, 0x11, 0x02, 0x81, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10 +}; +/*RATIO SET*/ +static UINT8 WMT_SET_MCU_RATIO_SET_6797[] = { + 0x01, 0x08, 0x10, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x0c, 0x01, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, + 0xc0, 0x00, 0x00, 0x00 +}; +/*DIV SET*/ +static UINT8 WMT_SET_MCU_DIV_SET_6797[] = { + 0x01, 0x08, 0x10, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x18, 0x11, 0x02, 0x80, 0x07, 0x00, 0x00, 0x00, + 0x3f, 0x00, 0x00, 0x00 +}; +/*HCLK SET*/ +static UINT8 WMT_SET_MCU_HCLK_SET_6797[] = { + 0x01, 0x08, 0x10, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x00, 0x11, 0x02, 0x81, 0x04, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00 +}; + +/*Change clock to 26MHz*/ +/*HCLK DIS*/ +static UINT8 WMT_SET_MCU_HCLK_DIS_6797[] = { + 0x01, 0x08, 0x10, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x00, 0x11, 0x02, 0x81, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00 +}; +/*RATIO DIS*/ +static UINT8 WMT_SET_MCU_RATIO_DIS_6797[] = { + 0x01, 0x08, 0x10, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x0c, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x00, 0x00, 0x00 +}; +/*CLK DIS*/ +static UINT8 WMT_SET_MCU_CLK_DIS_6797[] = { + 0x01, 0x08, 0x10, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x10, 0x11, 0x02, 0x81, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10 +}; + +static UINT8 WMT_SET_MCU_CLK_EVT_6797[] = { + 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 +}; + +#endif + + +static UINT8 WMT_COEX_CONFIG_BT_CTRL_CMD[] = { + 0x01, 0x10, 0x04, 0x00, 0x1A, 0x00, 0x00, 0x00 }; +static UINT8 WMT_COEX_CONFIG_ADDJUST_OPP_TIME_RATIO_CMD[] = { + 0x01, 0x10, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00 }; +static UINT8 WMT_COEX_CONFIG_ADDJUST_BLE_SCAN_TIME_RATIO_CMD[] = { + 0x01, 0x10, 0x04, 0x00, 0x1C, 0x00, 0x00, 0x00 }; + +static UINT8 WMT_COEX_SPLIT_MODE_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +#if CFG_WMT_FILTER_MODE_SETTING +static UINT8 WMT_COEX_TDM_REQ_ANTSEL_NUM_CMD[] = { 0x01, 0x10, 0x02, 0x00, 0x14, 0x00 }; +static UINT8 WMT_COEX_FILTER_SPEC_CMD_TEST[] = { + 0x01, 0x10, 0x45, 0x00, 0x11, 0x00, 0x00, 0x01, + 0x00, 0x11, 0x11, 0x16, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x63, 0x63, 0x63, 0x00, 0x39, 0x43, 0x63, + 0x63, 0x02, 0x02, 0x03, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x0e, 0x0e, 0x0e, 0x00, 0x0a, 0x0c, 0x0e, + 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static UINT8 WMT_COEX_LTE_FREQ_IDX_TABLE_CMD[] = { + 0x01, 0x10, 0x21, 0x00, 0x12, 0xfc, 0x08, 0x15, + 0x09, 0x2e, 0x09, 0x47, 0x09, 0xc4, 0x09, 0xd4, + 0x09, 0xe3, 0x09, 0x5a, 0x0a, 0x14, 0x09, 0x2d, + 0x09, 0x46, 0x09, 0x60, 0x09, 0xd3, 0x09, 0xe2, + 0x09, 0x59, 0x0a, 0x8B, 0x0a}; +static UINT8 WMT_COEX_LTE_CHAN_UNSAFE_CMD[] = { 0x01, 0x10, 0x02, 0x00, 0x13, 0x00 }; +static UINT8 WMT_COEX_IS_LTE_L_CMD[] = { 0x01, 0x10, 0x02, 0x00, 0x21, 0x01 }; + +#if 0 +static UINT8 WMT_COEX_SPLIT_FILTER_CMD_TEST[] = { + 0x01, 0x10, 0x19, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x00, 0x6c, 0x09, 0x8a, 0x09, 0x8a, 0x09, 0x9e, + 0x09, 0x01, 0x07, 0x07, 0x0b, 0x07, 0x07, 0x00, + 0x32, 0x27, 0x4e, 0x27, 0x32 +}; + +static UINT8 WMT_COEX_FILTER_SPEC_CMD_TEST[] = { + 0x01, 0x10, 0x45, 0x00, 0x11, 0x00, 0x00, 0x01, + 0x00, 0x07, 0x07, 0x07, 0x54, 0x54, 0x00, 0x00, + 0x00, 0x50, 0x50, 0x50, 0x54, 0x54, 0x39, 0x39, + 0x39, 0x02, 0x02, 0x02, 0x0e, 0x0e, 0x01, 0x01, + 0x01, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0a, 0x0a, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 +}; + +static UINT8 WMT_COEX_LTE_FREQ_IDX_TABLE_CMD_TEST[] = { + 0x01, 0x10, 0x21, 0x00, 0x12, 0xfc, 0x08, 0x15, + 0x09, 0x2e, 0x09, 0x47, 0x09, 0xc4, 0x09, 0xdd, + 0x09, 0xf6, 0x09, 0x0f, 0xaf, 0x14, 0x09, 0x2d, + 0x09, 0x46, 0x09, 0x5f, 0x09, 0xdd, 0x09, 0xf5, + 0x09, 0x0d, 0x0a, 0x27, 0x0a +}; +static UINT8 WMT_COEX_LTE_CHAN_UNSAFE_CMD_TEST[] = { 0x01, 0x10, 0x02, 0x00, 0x13, 0x00 }; +static UINT8 WMT_COEX_EXT_COMPONENT_CMD_TEST[] = { 0x01, 0x10, 0x03, 0x00, 0x0d, 0x7f, 0x03 }; +#endif + +static UINT8 WMT_COEX_FILTER_SPEC_CMD_0[] = { + 0x01, 0x10, 0x45, 0x00, 0x11, 0x00, 0x00, 0x01, + 0x00, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, + 0x00, 0x63, 0x63, 0x63, 0x63, 0x3c, 0x3c, 0x3c, + 0x3c, 0x04, 0x04, 0x04, 0x04, 0x01, 0x01, 0x01, + 0x01, 0x0e, 0x0e, 0x0e, 0x0e, 0x0b, 0x0b, 0x0b, + 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 +}; + +static UINT8 WMT_COEX_LTE_FREQ_IDX_TABLE_CMD_0[] = { + 0x01, 0x10, 0x21, 0x00, 0x12, 0xfc, 0x08, 0x15, + 0x09, 0x2e, 0x09, 0x47, 0x09, 0xc4, 0x09, 0xdd, + 0x09, 0xf6, 0x09, 0x0f, 0x0a, 0x14, 0x09, 0x2d, + 0x09, 0x46, 0x09, 0x5f, 0x09, 0xdd, 0x09, 0xf5, + 0x09, 0x0d, 0x0a, 0x27, 0x0a +}; +static UINT8 WMT_COEX_IS_LTE_PROJ_CMD[] = { 0x01, 0x10, 0x02, 0x00, 0x15, 0x01 }; + +static UINT8 WMT_COEX_FILTER_SPEC_CMD_6752[] = { + 0x01, 0x10, 0x45, 0x00, 0x11, 0x00, 0x00, 0x01, + 0x00, 0x11, 0x11, 0x16, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x63, 0x63, 0x63, 0x00, 0x39, 0x43, 0x63, + 0x63, 0x02, 0x02, 0x03, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x0E, 0x0E, 0x0E, 0x00, 0x0A, 0x0C, 0x0E, + 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 +}; + +static UINT8 WMT_COEX_LTE_FREQ_IDX_TABLE_CMD_6752[] = { + 0x01, 0x10, 0x21, 0x00, 0x12, 0xFC, 0x08, 0x15, + 0x09, 0x2E, 0x09, 0x47, 0x09, 0xC4, 0x09, 0xD4, + 0x09, 0xE3, 0x09, 0x5A, 0x0A, 0x14, 0x09, 0x2D, + 0x09, 0x46, 0x09, 0x60, 0x09, 0xD3, 0x09, 0xE2, + 0x09, 0x59, 0x0A, 0x8B, 0x0A +}; +#endif + +static UINT8 WMT_BT_TSSI_FROM_WIFI_CONFIG_CMD[] = { + 0x01, 0x02, 0x04, 0x00, 0x0D, 0x01, 0x1E, 0x00 +}; + +static UINT8 WMT_BT_TSSI_FROM_WIFI_EVENT[] = { + 0x02, 0x02, 0x01, 0x00, 0x00 +}; + +#if CFG_WMT_POWER_ON_DLM +static UINT8 WMT_POWER_CTRL_DLM_CMD1[] = { + 0x01, 0x08, 0x10, 0x00, + 0x01, 0x01, 0x00, 0x01, + 0x60, 0x00, 0x10, 0x80, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0x00, 0x00 +}; + +static UINT8 WMT_POWER_CTRL_DLM_CMD2[] = { + 0x01, 0x08, 0x10, 0x00, + 0x01, 0x01, 0x00, 0x01, + 0x60, 0x00, 0x10, 0x80, + 0x00, 0x00, 0x00, 0x00, + 0xf0, 0x00, 0x00, 0x00 +}; + +static UINT8 WMT_POWER_CTRL_DLM_CMD3[] = { + 0x01, 0x08, 0x10, 0x00, + 0x01, 0x01, 0x00, 0x01, + 0x60, 0x00, 0x10, 0x80, + 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00 +}; +static UINT8 WMT_POWER_CTRL_DLM_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; +#endif + +static UINT8 WMT_WIFI_ANT_SWAP_CMD[] = { 0x01, 0x14, 0x04, 0x00, 0x07, 0x02, 0x00, 0x00 }; +static UINT8 WMT_WIFI_ANT_SWAP_EVT[] = { 0x02, 0x14, 0x02, 0x00, 0x00, 0x07 }; + +static UINT8 WMT_WIFI_CONFIG_EVT[] = { 0x02, 0x02, 0x01, 0x00, 0x00 }; + +#if (!CFG_IC_SOC) + +/* stp sdio init scripts */ +static struct init_script init_table_1_1[] = { + /* table_1_1 is only applied to common SDIO interface */ + INIT_CMD(WMT_SET_ALLINT_REG_CMD, WMT_SET_ALLINT_REG_EVT, "enable all interrupt"), + /* applied to MT6628 ? */ + INIT_CMD(WMT_WAKEUP_DIS_GATE_CMD, WMT_WAKEUP_DIS_GATE_EVT, "disable gating"), +}; + +#endif + +static struct init_script init_table_1_2[] = { + INIT_CMD(WMT_QUERY_STP_CMD, WMT_QUERY_STP_EVT_DEFAULT, "query stp default"), +}; + +#if CFG_WMT_UART_HIF_USE +static struct init_script init_table_2[] = { + INIT_CMD(WMT_QUERY_BAUD_CMD, WMT_QUERY_BAUD_EVT_X, "query baud X"), +}; +#endif + +static struct init_script init_table_3[] = { + INIT_CMD(WMT_RESET_CMD, WMT_RESET_EVT, "wmt reset"), +#if CFG_WMT_BT_PORT2 + INIT_CMD(WMT_BTP2_CMD, WMT_BTP2_EVT, "set bt port2"), +#endif +}; + +static struct init_script set_chipid_script[] = { + INIT_CMD(WMT_SET_CHIP_ID_CMD, WMT_SET_CHIP_ID_EVT, "wmt set chipid"), +}; + +#if CFG_WMT_CRYSTAL_TIMING_SET +static struct init_script set_crystal_timing_script[] = { + INIT_CMD(WMT_SET_CRYSTAL_TRIMING_CMD, WMT_SET_CRYSTAL_TRIMING_EVT, "set crystal trim value"), +}; + +static struct init_script get_crystal_timing_script[] = { + INIT_CMD(WMT_GET_CRYSTAL_TRIMING_CMD, WMT_GET_CRYSTAL_TRIMING_EVT, "get crystal trim value"), +}; +#endif +#ifdef CFG_WMT_READ_EFUSE_VCN33 +static struct init_script get_efuse_vcn33_script[] = { + INIT_CMD(WMT_GET_EFUSE_VCN33_CMD, WMT_GET_EFUSE_VCN33_EVT, "get efuse vcn33 value"), +}; +#endif + +static struct init_script get_a_die_script[] = { + INIT_CMD(WMT_QUERY_A_DIE_CMD, WMT_QUERY_A_DIE_EVT, "query A-die"), +}; + +static struct init_script init_table_4[] = { + INIT_CMD(WMT_SET_STP_CMD, WMT_SET_STP_EVT, "set stp"), +}; + +static struct init_script init_table_5[] = { + INIT_CMD(WMT_QUERY_STP_CMD, WMT_QUERY_STP_EVT, "query stp"), +}; + +static struct init_script init_table_5_1[] = { + INIT_CMD(WMT_STRAP_CONF_CMD_FM_COMM, WMT_STRAP_CONF_EVT, "configure FM comm"), +}; + +static struct init_script init_table_6[] = { + INIT_CMD(WMT_CORE_DUMP_LEVEL_04_CMD, WMT_CORE_DUMP_LEVEL_04_EVT, "setup core dump level"), +}; + +static struct init_script calibration_table[] = { + INIT_CMD(WMT_CORE_START_RF_CALIBRATION_CMD, WMT_CORE_START_RF_CALIBRATION_EVT, "start RF calibration data"), +}; + +#if CFG_WMT_PATCH_DL_OPTM +static struct init_script set_mcuclk_table_1[] = { + INIT_CMD(WMT_SET_MCU_CLK_EN_CMD, WMT_SET_MCU_CLK_EN_EVT, "enable set mcu clk"), + INIT_CMD(WMT_SET_MCU_CLK_138_CMD, WMT_SET_MCU_CLK_138_EVT, "set mcu clk to 138.67MH"), +}; + +static struct init_script set_mcuclk_table_2[] = { + INIT_CMD(WMT_SET_MCU_CLK_26_CMD, WMT_SET_MCU_CLK_26_EVT, "set mcu clk to 26MH"), + INIT_CMD(WMT_SET_MCU_CLK_DIS_CMD, WMT_SET_MCU_CLK_DIS_EVT, "disable set mcu clk"), +}; + +static struct init_script set_mcuclk_table_3[] = { + INIT_CMD(WMT_SET_MCU_CLK_EN_6797, WMT_SET_MCU_CLK_EVT_6797, "enable set mcu clk"), + INIT_CMD(WMT_SET_MCU_RATIO_SET_6797, WMT_SET_MCU_CLK_EVT_6797, "mcu ratio set"), + INIT_CMD(WMT_SET_MCU_DIV_SET_6797, WMT_SET_MCU_CLK_EVT_6797, "mcu div set"), + INIT_CMD(WMT_SET_MCU_HCLK_SET_6797, WMT_SET_MCU_CLK_EVT_6797, "set mcu clk to hclk"), +}; +static struct init_script set_mcuclk_table_4[] = { + INIT_CMD(WMT_SET_MCU_HCLK_DIS_6797, WMT_SET_MCU_CLK_EVT_6797, "disable mcu hclk"), + INIT_CMD(WMT_SET_MCU_RATIO_DIS_6797, WMT_SET_MCU_CLK_EVT_6797, "disable mcu ratio set"), + INIT_CMD(WMT_SET_MCU_CLK_DIS_6797, WMT_SET_MCU_CLK_EVT_6797, "disable mcu clk set"), +}; + +#endif + +static UINT8 WMT_COEX_EXT_COMPONENT_CMD[] = {0x01, 0x10, 0x03, 0x00, 0x0d, 0x00, 0x00}; + +static struct init_script set_wifi_ext_component_table[] = { + INIT_CMD(WMT_COEX_EXT_COMPONENT_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi ext component"), +}; + +#if CFG_WMT_FILTER_MODE_SETTING +static struct init_script set_wifi_lte_coex_table_1[] = { + INIT_CMD(WMT_COEX_FILTER_SPEC_CMD_6752, WMT_COEX_SPLIT_MODE_EVT, "wifi lte coex filter spec"), + INIT_CMD(WMT_COEX_LTE_FREQ_IDX_TABLE_CMD_6752, WMT_COEX_SPLIT_MODE_EVT, "wifi lte freq idx"), + INIT_CMD(WMT_COEX_IS_LTE_PROJ_CMD, WMT_COEX_SPLIT_MODE_EVT, "set LTE project"), +}; + +static struct init_script set_wifi_lte_coex_table_2[] = { + INIT_CMD(WMT_COEX_FILTER_SPEC_CMD_TEST, WMT_COEX_SPLIT_MODE_EVT, "wifi lte coex filter"), + INIT_CMD(WMT_COEX_LTE_FREQ_IDX_TABLE_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi lte freq id table"), + INIT_CMD(WMT_COEX_LTE_CHAN_UNSAFE_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi lte unsafe channel"), + INIT_CMD(WMT_COEX_IS_LTE_L_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi coex is L branch"), +}; + +static struct init_script set_wifi_lte_coex_table_3[] = { + INIT_CMD(WMT_COEX_IS_LTE_PROJ_CMD, WMT_COEX_SPLIT_MODE_EVT, "set LTE project"), +}; + +static struct init_script set_wifi_lte_coex_table_0[] = { +#if 0 + INIT_CMD(WMT_COEX_SPLIT_FILTER_CMD_TEST, WMT_COEX_SPLIT_MODE_EVT, "wifi lte coex split filter"), + INIT_CMD(WMT_COEX_FILTER_SPEC_CMD_TEST, WMT_COEX_SPLIT_MODE_EVT, "wifi lte coex filter spec"), + INIT_CMD(WMT_COEX_LTE_FREQ_IDX_TABLE_CMD_TEST, WMT_COEX_SPLIT_MODE_EVT, "wifi lte freq idx"), + INIT_CMD(WMT_COEX_LTE_CHAN_UNSAFE_CMD_TEST, WMT_COEX_SPLIT_MODE_EVT, "wifi lte channel unsafe"), + INIT_CMD(WMT_COEX_EXT_COMPONENT_CMD_TEST, WMT_COEX_SPLIT_MODE_EVT, "wifi coex ext component"), +#endif + INIT_CMD(WMT_COEX_FILTER_SPEC_CMD_0, WMT_COEX_SPLIT_MODE_EVT, "def wifi lte coex filter spec"), + INIT_CMD(WMT_COEX_LTE_FREQ_IDX_TABLE_CMD_0, WMT_COEX_SPLIT_MODE_EVT, "def wifi lte freq idx"), +}; + +static struct init_script get_tdm_req_antsel_num_table[] = { + INIT_CMD(WMT_COEX_TDM_REQ_ANTSEL_NUM_CMD, WMT_COEX_SPLIT_MODE_EVT, "get tdm req antsel num"), +}; +#endif + +static struct init_script bt_tssi_from_wifi_table[] = { + INIT_CMD(WMT_BT_TSSI_FROM_WIFI_CONFIG_CMD, WMT_BT_TSSI_FROM_WIFI_EVENT, "get bt tssi value from wifi"), +}; + +static struct init_script coex_config_addjust_table[] = { + INIT_CMD(WMT_COEX_CONFIG_BT_CTRL_CMD, WMT_COEX_SPLIT_MODE_EVT, "coex config bt ctrl"), + INIT_CMD(WMT_COEX_CONFIG_ADDJUST_OPP_TIME_RATIO_CMD, WMT_COEX_SPLIT_MODE_EVT, "opp time ratio"), + INIT_CMD(WMT_COEX_CONFIG_ADDJUST_BLE_SCAN_TIME_RATIO_CMD, WMT_COEX_SPLIT_MODE_EVT, "ble scan time ratio"), + +}; + +#if CFG_SET_OPT_REG +static struct init_script set_registers[] = { + /* INIT_CMD(WMT_SET_GPS_REG_CMD, WMT_SET_GPS_REG_EVT, "set wmt registers"), */ + /* INIT_CMD(WMT_SET_SDIODRV_REG_CMD, WMT_SET_SDIODRV_REG_EVT, "set SDIO driving registers") */ +#if CFG_WMT_I2S_DBGUART_SUPPORT + INIT_CMD(WMT_SET_DBGUART_REG_CMD, WMT_SET_DBGUART_REG_EVT, "set debug uart registers"), +#endif +#if CFG_SET_OPT_REG_SWLA + INIT_CMD(WMT_SET_SWLA_REG_CMD, WMT_SET_SWLA_REG_EVT, "set swla registers"), +#endif +#if CFG_SET_OPT_REG_MCUCLK + INIT_CMD(WMT_SET_MCUCLK_REG_CMD, WMT_SET_MCUCLK_REG_EVT, "set mcuclk dbg registers"), +#endif +#if CFG_SET_OPT_REG_MCUIRQ + INIT_CMD(WMT_SET_MCUIRQ_REG_CMD, WMT_SET_MCUIRQ_REG_EVT, "set mcu irq dbg registers"), +#endif +}; +#endif + +static struct init_script coex_table[] = { + INIT_CMD(WMT_COEX_SETTING_CONFIG_CMD, WMT_COEX_SETTING_CONFIG_EVT, "coex_wmt"), + +#if CFG_SUBSYS_COEX_NEED +/* no need in MT6628 */ + INIT_CMD(WMT_BT_COEX_SETTING_CONFIG_CMD, WMT_BT_COEX_SETTING_CONFIG_EVT, "coex_bt"), + INIT_CMD(WMT_WIFI_COEX_SETTING_CONFIG_CMD, WMT_WIFI_COEX_SETTING_CONFIG_EVT, "coex_wifi"), + INIT_CMD(WMT_PTA_COEX_SETTING_CONFIG_CMD, WMT_PTA_COEX_SETTING_CONFIG_EVT, "coex_ext_pta"), + INIT_CMD(WMT_MISC_COEX_SETTING_CONFIG_CMD, WMT_MISC_COEX_SETTING_CONFIG_EVT, "coex_misc"), +#else + INIT_CMD(WMT_COEX_WIFI_PATH_CMD, WMT_COEX_WIFI_PATH_EVT, "wifi path"), + INIT_CMD(WMT_COEX_EXT_ELAN_GAIN_P1_CMD, WMT_COEX_EXT_ELAN_GAIN_P1_EVT, "wifi elan gain p1"), + INIT_CMD(WMT_COEX_EXT_EPA_MODE_CMD, WMT_COEX_EXT_EPA_MODE_EVT, "wifi ext epa mode"), +#endif +}; + +static struct init_script epa_table[] = { + INIT_CMD(WMT_EPA_SETTING_CONFIG_CMD, WMT_EPA_SETTING_CONFIG_EVT, "coex_wmt_epa"), +}; + +static struct init_script osc_type_table[] = { + INIT_CMD(WMT_CORE_CO_CLOCK_CMD, WMT_CORE_CO_CLOCK_EVT, "osc_type"), +}; + +#if (MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT) +static struct init_script merge_pcm_table[] = { + INIT_CMD(WMT_SET_I2S_SLAVE_REG_CMD, WMT_SET_I2S_SLAVE_REG_EVT, "I2S_Slave"), + INIT_CMD(WMT_SET_DAI_TO_PAD_REG_CMD, WMT_SET_DAI_TO_PAD_REG_EVT, "DAI_PAD"), + INIT_CMD(WMT_SET_DAI_REG_CMD, WMT_SET_DAI_REG_EVT, "DAI_EVT"), +}; +#endif + +#if CFG_WMT_SDIO_DRIVING_SET +static struct init_script sdio_driving_table[] = { + INIT_CMD(WMT_SET_SDIO_DRV_REG_CMD, WMT_SET_SDIO_DRV_REG_EVT, "sdio_driving"), +}; +#endif + +#if CFG_WMT_POWER_ON_DLM +static struct init_script wmt_power_on_dlm_table[] = { + INIT_CMD(WMT_POWER_CTRL_DLM_CMD1, WMT_POWER_CTRL_DLM_EVT, "power on dlm cmd1"), + INIT_CMD(WMT_POWER_CTRL_DLM_CMD2, WMT_POWER_CTRL_DLM_EVT, "power on dlm cmd2"), + INIT_CMD(WMT_POWER_CTRL_DLM_CMD3, WMT_POWER_CTRL_DLM_EVT, "power on dlm cmd3") +}; +#endif + + +static struct init_script wifi_ant_swap_table[] = { + INIT_CMD(WMT_WIFI_ANT_SWAP_CMD, WMT_WIFI_ANT_SWAP_EVT, "ant swap"), +}; + +/* SOC Chip Version and Info Table */ +static const WMT_IC_INFO_S mtk_wcn_soc_info_table[] = { + { + .u4HwVer = 0x8A00, + .cChipName = WMT_IC_NAME_DEFAULT, + .cChipVersion = WMT_IC_VER_E1, + .cPatchNameExt = WMT_IC_PATCH_E1_EXT, + .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE, + .bPsmSupport = MTK_WCN_BOOL_TRUE, + }, + { + .u4HwVer = 0x8A01, + .cChipName = WMT_IC_NAME_DEFAULT, + .cChipVersion = WMT_IC_VER_E2, + .cPatchNameExt = WMT_IC_PATCH_E1_EXT, + .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE, + .bPsmSupport = MTK_WCN_BOOL_TRUE, + }, + { + .u4HwVer = 0x8B00, + .cChipName = WMT_IC_NAME_DEFAULT, + .cChipVersion = WMT_IC_VER_E2, + .cPatchNameExt = WMT_IC_PATCH_E1_EXT, + .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE, + .bPsmSupport = MTK_WCN_BOOL_TRUE, + }, + { + .u4HwVer = 0x8B01, + .cChipName = WMT_IC_NAME_DEFAULT, + .cChipVersion = WMT_IC_VER_E3, + .cPatchNameExt = WMT_IC_PATCH_E1_EXT, + .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE, + .bPsmSupport = MTK_WCN_BOOL_TRUE, + }, + { + .u4HwVer = 0x8C00, + .cChipName = WMT_IC_NAME_DEFAULT, + .cChipVersion = WMT_IC_VER_E2, + .cPatchNameExt = WMT_IC_PATCH_E1_EXT, + .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 MTK_WCN_BOOL mtk_wcn_soc_trigger_assert(VOID); + +static INT32 mtk_wcn_soc_sw_init(P_WMT_HIF_CONF pWmtHifConf); + +static INT32 mtk_wcn_soc_sw_deinit(P_WMT_HIF_CONF pWmtHifConf); + +static INT32 mtk_wcn_soc_pin_ctrl(WMT_IC_PIN_ID id, WMT_IC_PIN_STATE state, UINT32 flag); + +static INT32 mtk_wcn_soc_aif_ctrl(WMT_IC_PIN_STATE state, UINT32 flag); + +static INT32 mtk_wcn_soc_ver_check(VOID); + +static const WMT_IC_INFO_S *mtk_wcn_soc_find_wmt_ic_info(const UINT32 hw_ver); + +static INT32 wmt_stp_init_coex(VOID); + +static INT32 wmt_stp_init_epa(VOID); + +static INT32 wmt_stp_init_epa_elna(VOID); + +static INT32 wmt_stp_init_epa_elna_invert_cr(VOID); + +static INT32 wmt_init_wifi_config(VOID); + +#if CFG_WMT_FILTER_MODE_SETTING +static INT32 wmt_stp_wifi_lte_coex(VOID); +#endif + +#if CFG_WMT_MULTI_PATCH +static INT32 mtk_wcn_soc_patch_dwn(UINT32 index); +static INT32 mtk_wcn_soc_patch_info_prepare(VOID); +static UINT32 mtk_wcn_soc_get_patch_num(VOID); +static INT32 mtk_wcn_soc_normal_patch_dwn(PUINT8 pPatchBuf, UINT32 patchSize, PUINT8 addressByte); +static INT32 mtk_wcn_soc_pda_patch_dwn(PUINT8 pPatchBuf, UINT32 patchSize, PUINT8 addressByte); +#else +static INT32 mtk_wcn_soc_patch_dwn(VOID); +#endif + +static INT32 mtk_wcn_soc_co_clock_ctrl(WMT_CO_CLOCK on); + +#if CFG_WMT_CRYSTAL_TIMING_SET +static INT32 mtk_wcn_soc_crystal_triming_set(VOID); +#endif + +static MTK_WCN_BOOL mtk_wcn_soc_quick_sleep_flag_get(VOID); + +static MTK_WCN_BOOL mtk_wcn_soc_aee_dump_flag_get(VOID); + +#if CFG_WMT_SDIO_DRIVING_SET +static INT32 mtk_wcn_soc_set_sdio_driving(void); +#endif +static UINT32 mtk_wcn_soc_update_patch_version(VOID); + +static INT32 mtk_wcn_soc_calibration(void); +static INT32 mtk_wcn_soc_do_calibration(void); +#if CFG_CALIBRATION_BACKUP_RESTORE +static INT32 mtk_wcn_soc_calibration_backup(void); +static INT32 mtk_wcn_soc_calibration_restore(void); +#endif + +static INT32 wmt_stp_init_wifi_ant_swap(VOID); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/* SOC Operation Function Table */ +WMT_IC_OPS wmt_ic_ops_soc = { + .icId = 0x0000, /* soc may have mt6572/82/71/83,but they have the same sw init flow */ + .options = 0, + .sw_init = mtk_wcn_soc_sw_init, + .sw_deinit = mtk_wcn_soc_sw_deinit, + .ic_pin_ctrl = mtk_wcn_soc_pin_ctrl, + .ic_ver_check = mtk_wcn_soc_ver_check, + .co_clock_ctrl = mtk_wcn_soc_co_clock_ctrl, + .is_quick_sleep = mtk_wcn_soc_quick_sleep_flag_get, + .is_aee_dump_support = mtk_wcn_soc_aee_dump_flag_get, + .trigger_stp_assert = mtk_wcn_soc_trigger_assert, + .deep_sleep_ctrl = NULL, +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +static INT32 _wmt_soc_mode_ctrl(UINT32 mode) +{ + INT32 iRet = -1; + unsigned long ctrlPa1; + unsigned long ctrlPa2; + + /* only consider full mode situation for the moment */ + if (mode != MTKSTP_BTIF_FULL_MODE) + return -1; + + /* 1. Query chip STP default options */ + iRet = wmt_core_init_script(init_table_1_2, osal_array_size(init_table_1_2)); + if (iRet) { + WMT_ERR_FUNC("init_table_1_2 fail(%d)\n", iRet); + osal_assert(0); + return -2; + } + + /* 2. Set chip STP options */ + iRet = wmt_core_init_script(init_table_4, osal_array_size(init_table_4)); + if (iRet) { + WMT_ERR_FUNC("init_table_4 fail(%d)\n", iRet); + return -3; + } + + /* 3. Enable host full mode */ + ctrlPa1 = WMT_STP_CONF_MODE; + ctrlPa2 = MTKSTP_BTIF_FULL_MODE; + iRet = wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + ctrlPa1 = WMT_STP_CONF_EN; + ctrlPa2 = 1; + iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + if (iRet) { + WMT_ERR_FUNC("enable host STP-BTIF-FULL mode fail(%d)\n", iRet); + return -4; + } + WMT_DBG_FUNC("enable host STP-BTIF-FULL mode\n"); + + /*4. wait for 10ms, enough for chip do mechanism switch.(at least 2ms is needed) */ + osal_sleep_ms(10); + + /* 5. Query chip STP options */ + iRet = wmt_core_init_script(init_table_5, osal_array_size(init_table_5)); + if (iRet) { + WMT_ERR_FUNC("init_table_5 fail(%d)\n", iRet); + return -5; + } + + return 0; +} + +static INT32 mtk_wcn_soc_sw_init(P_WMT_HIF_CONF pWmtHifConf) +{ + INT32 iRet = -1; + unsigned long ctrlPa1; + unsigned long ctrlPa2; + UINT32 hw_ver; + WMT_CTRL_DATA ctrlData; + UINT32 chipid = 0; +#ifdef CFG_WMT_READ_EFUSE_VCN33 + UINT32 efuse_d3_vcn33 = 2; /*default voltage is 3.5V*/ +#endif +#if CFG_WMT_MULTI_PATCH + UINT32 patch_num = 0; + UINT32 patch_index = 0; +#endif +#if CFG_WMT_WIFI_5G_SUPPORT + UINT32 dDieChipid = 0; + UINT32 aDieChipid = 0; + UINT8 evtbuf[20]; + UINT32 u4Res; + UINT32 pmicChipid = 0; +#endif + P_WMT_GEN_CONF pWmtGenConf = NULL; + P_CONSYS_EMI_ADDR_INFO emiInfo = NULL; + + WMT_DBG_FUNC(" start\n"); + + osal_assert(gp_soc_info != NULL); + if ((gp_soc_info == NULL) + || (pWmtHifConf == NULL) + ) { + WMT_ERR_FUNC("null pointers: gp_soc_info(0x%p), pWmtHifConf(0x%p)\n", gp_soc_info, pWmtHifConf); + return -1; + } + + hw_ver = gp_soc_info->u4HwVer; + + /* 4 <3.2> start init for BTIF */ + if (pWmtHifConf->hifType == WMT_HIF_BTIF) { + + emiInfo = mtk_wcn_consys_soc_get_emi_phy_add(); + if (!emiInfo) { + WMT_ERR_FUNC("get emi info fail!\n"); + return -1; + } + /* non-PDA mode, enable full mode before patch download */ + if (!emiInfo->pda_dl_patch_flag) { + iRet = _wmt_soc_mode_ctrl(MTKSTP_BTIF_FULL_MODE); + if (iRet) + return iRet; + } + } + + /* Check whether need to update property of patch version. + * If yes, notify stp_launcher to update. + */ + if (wmt_lib_get_need_update_patch_version()) { + wmt_lib_set_need_update_patch_version(0); + mtk_wcn_soc_update_patch_version(); + WMT_INFO_FUNC("wmt update patch version\n"); + } + +#if CFG_WMT_POWER_ON_DLM + if (wmt_ic_ops_soc.options & OPT_POWER_ON_DLM_TABLE) { + iRet = wmt_core_init_script(wmt_power_on_dlm_table, + osal_array_size(wmt_power_on_dlm_table)); + if (iRet) + WMT_ERR_FUNC("wmt_power_on_dlm_table fail(%d)\n", iRet); + WMT_DBG_FUNC("wmt_power_on_dlm_table ok\n"); + } +#endif + /* 6. download patch */ +#if CFG_WMT_MULTI_PATCH + /* 6.1 Let launcher to search patch info */ + /* 6.2 Read patch number */ + /* If patch number is 0, it's first time connys power on */ + if ((wmt_ic_ops_soc.options & OPT_DISABLE_ROM_PATCH_DWN) == 0) { + patch_num = mtk_wcn_soc_get_patch_num(); + if (patch_num == 0 || wmt_lib_get_patch_info() == NULL) { + iRet = mtk_wcn_soc_patch_info_prepare(); + if (iRet) { + WMT_ERR_FUNC("patch info perpare fail(%d)\n", iRet); + return -6; + } + patch_num = mtk_wcn_soc_get_patch_num(); + WMT_INFO_FUNC("patch total num = [%d]\n", patch_num); + } + } else { + patch_num = 0; + } +#if CFG_WMT_PATCH_DL_OPTM + if (patch_num != 0) { + if (wmt_ic_ops_soc.options & OPT_SET_MCUCLK_TABLE_1_2) { + iRet = wmt_core_init_script(set_mcuclk_table_1, osal_array_size(set_mcuclk_table_1)); + if (iRet) + WMT_ERR_FUNC("set_mcuclk_table_1 fail(%d)\n", iRet); + } else if (wmt_ic_ops_soc.options & OPT_SET_MCUCLK_TABLE_3_4) { + iRet = wmt_core_init_script(set_mcuclk_table_3, osal_array_size(set_mcuclk_table_3)); + if (iRet) + WMT_ERR_FUNC("set_mcuclk_table_3 fail(%d)\n", iRet); + } + } +#endif + /* 6.3 Multi-patch Patch download */ + WMT_STEP_DO_ACTIONS_FUNC(STEP_TRIGGER_POINT_POWER_ON_BEFORE_SEND_DOWNLOAD_PATCH); + for (patch_index = 0; patch_index < patch_num; patch_index++) { + iRet = mtk_wcn_soc_patch_dwn(patch_index); + if (iRet) { + WMT_ERR_FUNC("patch dwn fail (%d),patch_index(%d)\n", iRet, patch_index); + return -7; + } + if (patch_index == (patch_num - 1)) + WMT_STEP_DO_ACTIONS_FUNC(STEP_TRIGGER_POINT_POWER_ON_BEFORE_CONNSYS_RESET); + + iRet = wmt_core_init_script(init_table_3, osal_array_size(init_table_3)); + if (iRet) { + WMT_ERR_FUNC("init_table_3 fail(%d)\n", iRet); + return -8; + } + } + +#if CFG_WMT_PATCH_DL_OPTM + if (patch_num != 0) { + if (wmt_ic_ops_soc.options & OPT_SET_MCUCLK_TABLE_1_2) { + iRet = wmt_core_init_script(set_mcuclk_table_2, osal_array_size(set_mcuclk_table_2)); + if (iRet) + WMT_ERR_FUNC("set_mcuclk_table_2 fail(%d)\n", iRet); + } else if (wmt_ic_ops_soc.options & OPT_SET_MCUCLK_TABLE_3_4) { + iRet = wmt_core_init_script(set_mcuclk_table_4, osal_array_size(set_mcuclk_table_4)); + if (iRet) + WMT_ERR_FUNC("set_mcuclk_table_4 fail(%d)\n", iRet); + } + } +#endif + +#else + /* 6.3 Patch download */ + if ((wmt_ic_ops_soc.options & OPT_DISABLE_ROM_PATCH_DWN) == 0) { + WMT_STEP_DO_ACTIONS_FUNC(STEP_TRIGGER_POINT_POWER_ON_BEFORE_SEND_DOWNLOAD_PATCH); + iRet = mtk_wcn_soc_patch_dwn(); + /* If patch download fail, we just ignore this error and let chip init process goes on */ + if (iRet) + WMT_ERR_FUNC("patch dwn fail (%d), just omit\n", iRet); + + /* 6.4. WMT Reset command */ + WMT_STEP_DO_ACTIONS_FUNC(STEP_TRIGGER_POINT_POWER_ON_BEFORE_CONNSYS_RESET); + iRet = wmt_core_init_script(init_table_3, osal_array_size(init_table_3)); + if (iRet) { + WMT_ERR_FUNC("init_table_3 fail(%d)\n", iRet); + return -8; + } + } +#endif + + /* PDA mode, enable full mode after patch download */ + if (pWmtHifConf->hifType == WMT_HIF_BTIF && + emiInfo->pda_dl_patch_flag) { + iRet = _wmt_soc_mode_ctrl(MTKSTP_BTIF_FULL_MODE); + if (iRet) + return iRet; + } + + chipid = wmt_plat_get_soc_chipid(); + WMT_SET_CHIP_ID_CMD[5] = chipid & 0xff; + WMT_SET_CHIP_ID_CMD[6] = (chipid >> 8) & 0xff; + iRet = wmt_core_init_script(set_chipid_script, osal_array_size(set_chipid_script)); + if (iRet) + WMT_ERR_FUNC("wmt_core:set_chipid_script %s(%d)\n", iRet ? "fail" : "ok", iRet); + + if (wmt_ic_ops_soc.options & OPT_QUERY_ADIE) { + iRet = wmt_core_init_script_retry(get_a_die_script, osal_array_size(get_a_die_script), 1, 0); + if (iRet) { + WMT_ERR_FUNC("get_a_die_script fail(%d)\n", iRet); +#ifdef CFG_WMT_EVB + /* prevent printing too much log */ + osal_sleep_ms(1000); +#else + osal_dbg_assert_aee("Connsys A-die is not exist", "Please check Connsys A-die\0"); +#endif + return -21; + } + } + + iRet = wmt_init_wifi_config(); + if (iRet) { + WMT_ERR_FUNC("init_wifi_config fail(%d)\n", iRet); + return -22; + } + +#ifdef CFG_WMT_READ_EFUSE_VCN33 + /*get CrystalTiming value before set it */ + iRet = wmt_core_tx(get_efuse_vcn33_script[0].cmd, get_efuse_vcn33_script[0].cmdSz, &u4Res, + MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != get_efuse_vcn33_script[0].cmdSz)) { + WMT_ERR_FUNC("WMT-CORE: write (%s) iRet(%d) cmd len err(%d, %d)\n", + get_efuse_vcn33_script[0].str, iRet, u4Res, get_efuse_vcn33_script[0].cmdSz); + } + /* EVENT BUF */ + osal_memset(get_efuse_vcn33_script[0].evt, 0, get_efuse_vcn33_script[0].evtSz); + iRet = wmt_core_rx(get_efuse_vcn33_script[0].evt, get_efuse_vcn33_script[0].evtSz, &u4Res); + if (iRet || (u4Res != get_efuse_vcn33_script[0].evtSz)) { + WMT_ERR_FUNC("WMT-CORE: read (%s) iRet(%d) evt len err(rx:%d, exp:%d)\n", + get_efuse_vcn33_script[0].str, iRet, u4Res, get_efuse_vcn33_script[0].evtSz); + mtk_wcn_stp_dbg_dump_package(); + } + efuse_d3_vcn33 = WMT_GET_EFUSE_VCN33_EVT[5] & 0x03; + WMT_INFO_FUNC("Read efuse to set PMIC voltage:(%d)\n", efuse_d3_vcn33); + wmt_set_pmic_voltage(efuse_d3_vcn33); +#endif + pWmtGenConf = wmt_get_gen_conf_pointer(); + if (wmt_ic_ops_soc.options & OPT_SET_WIFI_EXT_COMPONENT) { + /* add WMT_COXE_CONFIG_EXT_COMPONENT_OPCODE command for 2G4 eLNA demand*/ + if (pWmtGenConf->coex_wmt_ext_component) { + WMT_INFO_FUNC("coex_wmt_ext_component:0x%x\n", pWmtGenConf->coex_wmt_ext_component); + set_wifi_ext_component_table[0].cmd[5] = pWmtGenConf->coex_wmt_ext_component; + } + iRet = wmt_core_init_script(set_wifi_ext_component_table, + osal_array_size(set_wifi_ext_component_table)); + if (iRet) + WMT_ERR_FUNC("wmt_core:set_wifi_ext_component_table %s(%d)\n", + iRet ? "fail" : "ok", iRet); + } + +#if CFG_WMT_FILTER_MODE_SETTING + if (wmt_ic_ops_soc.options & OPT_WIFI_LTE_COEX) { + wmt_stp_wifi_lte_coex(); + WMT_DBG_FUNC("wmt_stp_wifi_lte_coex done!\n"); + } + if (wmt_ic_ops_soc.options & OPT_COEX_TDM_REQ_ANTSEL_NUM) { + /*get gpio tdm req antsel number */ + ctrlPa1 = 0; + ctrlPa2 = 0; + wmt_core_ctrl(WMT_CTRL_GET_TDM_REQ_ANTSEL, &ctrlPa1, &ctrlPa2); + WMT_INFO_FUNC("get GPIO TDM REQ ANTSEL number(%lu)\n", ctrlPa1); + /*set gpio tdm req antsel number to firmware */ + WMT_COEX_TDM_REQ_ANTSEL_NUM_CMD[5] = ctrlPa1; + iRet = wmt_core_init_script(get_tdm_req_antsel_num_table, + osal_array_size(get_tdm_req_antsel_num_table)); + if (iRet) + WMT_ERR_FUNC("get_tdm_req_antsel_num_table fail(%d)\n", iRet); + } +#endif + WMT_INFO_FUNC("bt_tssi_from_wifi=%d, bt_tssi_target=%d\n", + pWmtGenConf->bt_tssi_from_wifi, pWmtGenConf->bt_tssi_target); + if (pWmtGenConf->bt_tssi_from_wifi) { + if (wmt_ic_ops_soc.options & OPT_BT_TSSI_FROM_WIFI_CONFIG_NEW_OPID) + WMT_BT_TSSI_FROM_WIFI_CONFIG_CMD[4] = 0x10; + + WMT_BT_TSSI_FROM_WIFI_CONFIG_CMD[5] = pWmtGenConf->bt_tssi_from_wifi; + WMT_BT_TSSI_FROM_WIFI_CONFIG_CMD[6] = (pWmtGenConf->bt_tssi_target & 0x00FF) >> 0; + WMT_BT_TSSI_FROM_WIFI_CONFIG_CMD[7] = (pWmtGenConf->bt_tssi_target & 0xFF00) >> 8; + iRet = wmt_core_init_script(bt_tssi_from_wifi_table, osal_array_size(bt_tssi_from_wifi_table)); + if (iRet) + WMT_ERR_FUNC("bt_tssi_from_wifi_table fail(%d)\n", iRet); + } + + /* init epa before start RF calibration */ + /* for chip 0x6739 */ + iRet = wmt_stp_init_epa(); + + if (iRet) { + WMT_ERR_FUNC("init_epa fail(%d)\n", iRet); + return -20; + } + + /* for chip 0x6779 */ + iRet = wmt_stp_init_epa_elna(); + + if (iRet) { + WMT_ERR_FUNC("init_epa_elna fail(%d)\n", iRet); + return -22; + } + + iRet = wmt_stp_init_epa_elna_invert_cr(); + if (iRet) { + WMT_ERR_FUNC("init_invert_cr fail(%d)\n", iRet); + return -23; + } + + /* init coex before start RF calibration */ + if (wmt_ic_ops_soc.options & OPT_INIT_COEX_BEFORE_RF_CALIBRATION) { + iRet = wmt_stp_init_coex(); + if (iRet) { + WMT_ERR_FUNC("init_coex fail(%d)\n", iRet); + return -10; + } + WMT_DBG_FUNC("init_coex ok\n"); + } + + iRet = wmt_stp_init_wifi_ant_swap(); + + if (iRet) { + WMT_ERR_FUNC("init_wifi_ant_swap fail(%d)\n", iRet); + WMT_INFO_FUNC("A-DIE chip id=0x%x", mtk_wcn_consys_get_adie_chipid()); + } + + /* 7. start RF calibration data */ + iRet = mtk_wcn_soc_calibration(); + if (iRet) { + WMT_ERR_FUNC("calibration failed\n"); + return -9; + } + + /* turn off VCN28 after reading efuse */ + ctrlPa1 = EFUSE_PALDO; + ctrlPa2 = PALDO_OFF; + iRet = wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + + if (wmt_ic_ops_soc.options & OPT_INIT_COEX_AFTER_RF_CALIBRATION) { + iRet = wmt_stp_init_coex(); + if (iRet) { + WMT_ERR_FUNC("init_coex fail(%d)\n", iRet); + return -10; + } + WMT_DBG_FUNC("init_coex ok\n"); + } + + if (wmt_ic_ops_soc.options & OPT_COEX_CONFIG_ADJUST) { + WMT_INFO_FUNC("coex_config_bt_ctrl:0x%x\n", pWmtGenConf->coex_config_bt_ctrl); + coex_config_addjust_table[0].cmd[5] = pWmtGenConf->coex_config_bt_ctrl; + WMT_INFO_FUNC("coex_config_bt_ctrl_mode:0x%x\n", pWmtGenConf->coex_config_bt_ctrl_mode); + coex_config_addjust_table[0].cmd[6] = pWmtGenConf->coex_config_bt_ctrl_mode; + WMT_INFO_FUNC("coex_config_bt_ctrl_rw:0x%x\n", pWmtGenConf->coex_config_bt_ctrl_rw); + coex_config_addjust_table[0].cmd[7] = pWmtGenConf->coex_config_bt_ctrl_rw; + + WMT_INFO_FUNC("coex_config_addjust_opp_time_ratio:0x%x\n", + pWmtGenConf->coex_config_addjust_opp_time_ratio); + coex_config_addjust_table[1].cmd[5] = pWmtGenConf->coex_config_addjust_opp_time_ratio; + WMT_INFO_FUNC("coex_config_addjust_opp_time_ratio_bt_slot:0x%x\n", + pWmtGenConf->coex_config_addjust_opp_time_ratio_bt_slot); + coex_config_addjust_table[1].cmd[6] = + pWmtGenConf->coex_config_addjust_opp_time_ratio_bt_slot; + WMT_INFO_FUNC("coex_config_addjust_opp_time_ratio_wifi_slot:0x%x\n", + pWmtGenConf->coex_config_addjust_opp_time_ratio_wifi_slot); + coex_config_addjust_table[1].cmd[7] = + pWmtGenConf->coex_config_addjust_opp_time_ratio_wifi_slot; + + WMT_INFO_FUNC("coex_config_addjust_ble_scan_time_ratio:0x%x\n", + pWmtGenConf->coex_config_addjust_ble_scan_time_ratio); + coex_config_addjust_table[2].cmd[5] = + pWmtGenConf->coex_config_addjust_ble_scan_time_ratio; + WMT_INFO_FUNC("coex_config_addjust_ble_scan_time_ratio_bt_slot:0x%x\n", + pWmtGenConf->coex_config_addjust_ble_scan_time_ratio_bt_slot); + coex_config_addjust_table[2].cmd[6] = + pWmtGenConf->coex_config_addjust_ble_scan_time_ratio_bt_slot; + WMT_INFO_FUNC("coex_config_addjust_ble_scan_time_ratio_wifi_slot:0x%x\n", + pWmtGenConf->coex_config_addjust_ble_scan_time_ratio_wifi_slot); + coex_config_addjust_table[2].cmd[7] = + pWmtGenConf->coex_config_addjust_ble_scan_time_ratio_wifi_slot; + + /* COEX flag is different in these project. */ + if (wmt_ic_ops_soc.options & OPT_COEX_CONFIG_ADJUST_NEW_FLAG) { + coex_config_addjust_table[0].cmd[4] = 0x1e; + coex_config_addjust_table[1].cmd[4] = 0x1f; + coex_config_addjust_table[2].cmd[4] = 0x20; + } + + iRet = wmt_core_init_script(coex_config_addjust_table, + osal_array_size(coex_config_addjust_table)); + if (iRet) + WMT_ERR_FUNC("wmt_core:coex_config_addjust_table %s(%d)\n", + iRet ? "fail" : "ok", iRet); + } + +#if CFG_WMT_CRYSTAL_TIMING_SET + mtk_wcn_soc_crystal_triming_set(); +#endif + +#if CFG_WMT_SDIO_DRIVING_SET + mtk_wcn_soc_set_sdio_driving(); +#endif + + if (wmt_ic_ops_soc.options & OPT_SET_OSC_TYPE) { + if (wmt_plat_soc_co_clock_flag_get() == WMT_CO_CLOCK_EN) { + WMT_INFO_FUNC("co-clock enabled.\n"); + + iRet = wmt_core_init_script(osc_type_table, osal_array_size(osc_type_table)); + if (iRet) { + WMT_ERR_FUNC("osc_type_table fail(%d), goes on\n", iRet); + return -11; + } + } else { + WMT_WARN_FUNC("co-clock disabled.\n"); + } + } +#if (MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT) + iRet = wmt_core_init_script(merge_pcm_table, osal_array_size(merge_pcm_table)); + if (iRet) { + WMT_ERR_FUNC("merge_pcm_table fail(%d), goes on\n", iRet); + return -12; + } +#endif + + /* 15. Set FM strap */ + WMT_STRAP_CONF_CMD_FM_COMM[5] = (UINT8) pWmtHifConf->au4StrapConf[0]; + WMT_STRAP_CONF_EVT[5] = (UINT8) pWmtHifConf->au4StrapConf[0]; + iRet = wmt_core_init_script(init_table_5_1, osal_array_size(init_table_5_1)); + if (iRet) { + WMT_ERR_FUNC("init_table_5_1 fm mode(%d) fail(%d)\n", pWmtHifConf->au4StrapConf[0], iRet); + return -13; + } + WMT_DBG_FUNC("set fm mode (%d) ok\n", pWmtHifConf->au4StrapConf[0]); + +#if CFG_SET_OPT_REG /*set registers */ + iRet = wmt_core_init_script(set_registers, osal_array_size(set_registers)); + if (iRet) { + WMT_ERR_FUNC("set_registers fail(%d)", iRet); + return -14; + } +#endif + +#if CFG_WMT_COREDUMP_ENABLE + /*Open Core Dump Function @QC begin */ + mtk_wcn_stp_coredump_flag_ctrl(1); +#endif + if (wmt_ic_ops_soc.options & OPT_SET_COREDUMP_LEVEL) { + if (mtk_wcn_stp_coredump_flag_get() != 0) { + iRet = wmt_core_init_script(init_table_6, osal_array_size(init_table_6)); + if (iRet) { + WMT_ERR_FUNC("init_table_6 core dump setting fail(%d)\n", iRet); + return -15; + } + WMT_DBG_FUNC("enable soc_consys firmware coredump\n"); + } else { + WMT_DBG_FUNC("disable soc_consys firmware coredump\n"); + } + } + +#if CFG_WMT_WIFI_5G_SUPPORT + dDieChipid = wmt_ic_ops_soc.icId; + WMT_DBG_FUNC("current SOC chipid is 0x%x\n", dDieChipid); + if (wmt_ic_ops_soc.options & OPT_WIFI_5G_PALDO) { + /* read A die chipid by wmt cmd */ + iRet = + wmt_core_tx((PUINT8) &WMT_GET_SOC_ADIE_CHIPID_CMD[0], sizeof(WMT_GET_SOC_ADIE_CHIPID_CMD), &u4Res, + MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != sizeof(WMT_GET_SOC_ADIE_CHIPID_CMD))) { + WMT_ERR_FUNC("wmt_core:read A die chipid CMD fail(%d),size(%d)\n", iRet, u4Res); + return -16; + } + osal_memset(evtbuf, 0, sizeof(evtbuf)); + iRet = wmt_core_rx(evtbuf, sizeof(WMT_GET_SOC_ADIE_CHIPID_EVT), &u4Res); + if (iRet || (u4Res != sizeof(WMT_GET_SOC_ADIE_CHIPID_EVT))) { + WMT_ERR_FUNC("wmt_core:read A die chipid EVT fail(%d),size(%d)\n", iRet, u4Res); + WMT_INFO_FUNC("buf:[%2X,%2X,%2X,%2X,%2X] evt:[%2X,%2X,%2X,%2X,%2X]\n", + evtbuf[0], evtbuf[1], evtbuf[2], evtbuf[3], evtbuf[4], + WMT_GET_SOC_ADIE_CHIPID_EVT[0], + WMT_GET_SOC_ADIE_CHIPID_EVT[1], + WMT_GET_SOC_ADIE_CHIPID_EVT[2], + WMT_GET_SOC_ADIE_CHIPID_EVT[3], + WMT_GET_SOC_ADIE_CHIPID_EVT[4]); + mtk_wcn_stp_dbg_dump_package(); + return -17; + } + + osal_memcpy(&aDieChipid, &evtbuf[u4Res - 2], 2); + WMT_INFO_FUNC("get SOC A die chipid(0x%x)\n", aDieChipid); + + if (aDieChipid == 0x6625) { + iRet = + wmt_core_tx((PUINT8) &WMT_GET_SOC_6625_L_CMD[0], sizeof(WMT_GET_SOC_6625_L_CMD), &u4Res, + MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != sizeof(WMT_GET_SOC_6625_L_CMD))) + WMT_ERR_FUNC("wmt_core:read A die efuse CMD fail(%d),size(%d)\n", iRet, u4Res); + osal_memset(evtbuf, 0, sizeof(evtbuf)); + iRet = wmt_core_rx(evtbuf, sizeof(WMT_GET_SOC_6625_L_EVT), &u4Res); + if (iRet || (u4Res != sizeof(WMT_GET_SOC_6625_L_EVT))) { + WMT_ERR_FUNC("wmt_core:read A die efuse EVT fail(%d),size(%d)\n", iRet, u4Res); + WMT_INFO_FUNC("buf:[%2X,%2X,%2X,%2X] evt:[%2X,%2X,%2X,%2X]\n", + evtbuf[0], evtbuf[1], evtbuf[2], evtbuf[3], + WMT_GET_SOC_6625_L_EVT[0], + WMT_GET_SOC_6625_L_EVT[1], + WMT_GET_SOC_6625_L_EVT[2], + WMT_GET_SOC_6625_L_EVT[3]); + mtk_wcn_stp_dbg_dump_package(); + } + WMT_INFO_FUNC("read SOC Adie Efuse(0x120) value:0x%2x,0x%2x,0x%2x,0x%2x -> %s\n", + evtbuf[u4Res - 4], evtbuf[u4Res - 3], evtbuf[u4Res - 2], evtbuf[u4Res - 1], + evtbuf[u4Res - 2] == 0x31 ? "MT6625L" : "MT6625"); + } + /* get PMIC chipid */ + + ctrlData.ctrlId = WMT_CTRL_SOC_PALDO_CTRL; + ctrlData.au4CtrlData[0] = PMIC_CHIPID_PALDO; + ctrlData.au4CtrlData[1] = 0; + iRet = wmt_ctrl(&ctrlData); + if (iRet < 0) { + WMT_ERR_FUNC("wmt_core: read PMIC chipid fail(%d)\n", iRet); + return -18; + } + pmicChipid = ctrlData.au4CtrlData[2]; + WMT_INFO_FUNC("current PMIC chipid(0x%x)\n", pmicChipid); + + /* MT6625 & MT6322, write 1 to 0x0414[12] */ + /* MT6625 & MT6323, assert */ + /* MT6627 & (MT6322 or MT6323),write 0 to 0x0414[12] */ + + switch (aDieChipid) { + case 0x6625: + if (pmicChipid == 0x6322 || pmicChipid == 0x6356) { + WMT_INFO_FUNC("wmt-core:enable wifi 5G support\n"); + ctrlPa1 = WIFI_5G_PALDO; + ctrlPa2 = PALDO_ON; + wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + } else if (pmicChipid == 0x6323) { + osal_assert(0); + } else { + WMT_WARN_FUNC("wmt-core: unknown PMIC chipid\n"); + } + break; + case 0x6627: + if ((pmicChipid == 0x6322) || (pmicChipid == 0x6323)) { + WMT_INFO_FUNC("wmt-core: disable wifi 5G support\n"); + ctrlPa1 = WIFI_5G_PALDO; + ctrlPa2 = PALDO_OFF; + wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + } else { + WMT_WARN_FUNC("wmt-core: unknown PMIC chipid\n"); + } + break; + default: + WMT_WARN_FUNC("wmt-core: unknown A die chipid(0x%x)\n", aDieChipid); + break; + } + } +#endif + +#if 1 + ctrlData.ctrlId = WMT_CTRL_SET_STP_DBG_INFO; + ctrlData.au4CtrlData[0] = wmt_ic_ops_soc.icId; + ctrlData.au4CtrlData[1] = (SIZE_T) gp_soc_info->cChipVersion; + ctrlData.au4CtrlData[2] = (SIZE_T) &gp_soc_patch_info; + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + WMT_ERR_FUNC("set dump info fail(%d)\n", iRet); + return -19; + } +#endif + +#if CFG_WMT_PS_SUPPORT + osal_assert(gp_soc_info != NULL); + if (gp_soc_info != NULL) { + if (gp_soc_info->bPsmSupport != MTK_WCN_BOOL_FALSE) + wmt_lib_ps_enable(); + else + wmt_lib_ps_disable(); + } +#endif + + WMT_STEP_DO_ACTIONS_FUNC(STEP_TRIGGER_POINT_POWER_ON_END); + + return 0; +} + +static INT32 mtk_wcn_soc_sw_deinit(P_WMT_HIF_CONF pWmtHifConf) +{ + WMT_DBG_FUNC(" start\n"); + +#if CFG_WMT_PS_SUPPORT + osal_assert(gp_soc_info != NULL); + if ((gp_soc_info != NULL) + && (gp_soc_info->bPsmSupport != MTK_WCN_BOOL_FALSE)) { + wmt_lib_ps_disable(); + } +#endif + + gp_soc_info = NULL; + + return 0; +} + +static INT32 mtk_wcn_soc_aif_ctrl(WMT_IC_PIN_STATE state, UINT32 flag) +{ + INT32 ret = -1; + UINT32 val; + + if ((flag & WMT_LIB_AIF_FLAG_MASK) == WMT_LIB_AIF_FLAG_SHARE) { + WMT_INFO_FUNC("PCM & I2S PIN SHARE\n"); +#if 0 + switch (state) { + case WMT_IC_AIF_0: + /* BT_PCM_OFF & FM line in/out */ + val = 0x00000770; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000000; + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + break; + + case WMT_IC_AIF_1: + /* BT_PCM_ON & FM line in/out */ + val = 0x00000700; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000000; + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + break; + + case WMT_IC_AIF_2: + /* BT_PCM_OFF & FM I2S */ + val = 0x00000710; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000800; /* 800:3-wire, 000: 4-wire */ + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + break; + default: + WMT_ERR_FUNC("unsupported state (%d)\n", state); + ret = -1; + break; + } +#else + WMT_WARN_FUNC("TBD!!"); + ret = 0; +#endif + } else { + /*PCM & I2S separate */ + WMT_INFO_FUNC("PCM & I2S PIN SEPARATE\n"); +#if 0 + switch (state) { + case WMT_IC_AIF_0: + /* BT_PCM_OFF & FM line in/out */ + val = 0x00000770; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000000; + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + break; + + case WMT_IC_AIF_1: + /* BT_PCM_ON & FM line in/out */ + val = 0x00000700; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000000; + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + break; + + case WMT_IC_AIF_2: + /* BT_PCM_OFF & FM I2S */ + val = 0x00000070; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000800; /* 800:3-wire, 000: 4-wire */ + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + + break; + case WMT_IC_AIF_3: + val = 0x00000000; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000800; /* 800:3-wire, 000: 4-wire */ + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + + break; + default: + WMT_ERR_FUNC("unsupported state (%d)\n", state); + ret = -1; + break; + } +#else + switch (state) { + case WMT_IC_AIF_0: + /* BT_PCM_OFF & FM line in/out */ + ret = 0; + break; + case WMT_IC_AIF_1: + /* BT_PCM_ON & FM line in/out */ + ret = 0; + break; + + case WMT_IC_AIF_2: + /* BT_PCM_OFF & FM I2S */ + val = 0x01110000; + ret = wmt_core_reg_rw_raw(1, 0x80050078, &val, 0x0FFF0000); + + break; + case WMT_IC_AIF_3: + ret = 0; + break; + + default: + WMT_ERR_FUNC("unsupported state (%d)\n", state); + ret = -1; + break; + } +#endif + } + + if (!ret) + WMT_WARN_FUNC("new state(%d) fail(%d)\n", state, ret); + WMT_INFO_FUNC("new state(%d) ok\n", state); + + return ret; +} + +static INT32 mtk_wcn_soc_gps_sync_ctrl(WMT_IC_PIN_STATE state, UINT32 flag) +{ + INT32 iRet = -1; + UINT32 uVal = 0; + + /* gen3(6631) CONSYS can not access reg:0x80050078 and no need to do GPS SYNC + * may cause bus hang + */ + if (wmt_ic_ops_soc.options & OPT_GPS_SYNC) { + if (state == WMT_IC_PIN_MUX) + uVal = 0x1 << 28; + else + uVal = 0x5 << 28; + iRet = wmt_core_reg_rw_raw(1, 0x80050078, &uVal, 0x7 << 28); + if (iRet) + WMT_ERR_FUNC("gps_sync pin ctrl failed, iRet(%d)\n", iRet); + } else + WMT_INFO_FUNC("This chip no need to sync GPS and MODEM!\n"); + + /* anyway, we return 0 */ + return 0; +} + +static INT32 mtk_wcn_soc_pin_ctrl(WMT_IC_PIN_ID id, WMT_IC_PIN_STATE state, UINT32 flag) +{ + INT32 ret; + + WMT_DBG_FUNC("ic pin id:%d, state:%d, flag:0x%x\n", id, state, flag); + + ret = -1; + switch (id) { + case WMT_IC_PIN_AUDIO: + ret = mtk_wcn_soc_aif_ctrl(state, flag); + break; + + case WMT_IC_PIN_EEDI: + WMT_WARN_FUNC("TBD!!"); + /* We just return 0 here, prevent from WMT-FUNC do other register read/write */ + ret = 0; + break; + + case WMT_IC_PIN_EEDO: + WMT_WARN_FUNC("TBD!!"); + /* We just return 0 here, prevent from WMT-FUNC do other register read/write */ + ret = 0; + break; + case WMT_IC_PIN_GSYNC: + ret = mtk_wcn_soc_gps_sync_ctrl(state, flag); + break; + default: + break; + } + WMT_INFO_FUNC("ret = (%d)\n", ret); + + return ret; +} + +INT32 mtk_wcn_soc_co_clock_ctrl(WMT_CO_CLOCK on) +{ + INT32 iRet = 0; + + if ((on >= WMT_CO_CLOCK_DIS) && (on < WMT_CO_CLOCK_MAX)) { + gCoClockEn = on; + } else { + WMT_DBG_FUNC("0x%x: error parameter:%d\n", wmt_ic_ops_soc.icId, on); + iRet = -1; + } + WMT_DBG_FUNC("0x%x: Co-clock %s\n", wmt_ic_ops_soc.icId, + (gCoClockEn == WMT_CO_CLOCK_DIS) ? "disabled" : "enabled"); + + return iRet; +} + +static MTK_WCN_BOOL mtk_wcn_soc_quick_sleep_flag_get(VOID) +{ + return MTK_WCN_BOOL_TRUE; +} + +static MTK_WCN_BOOL mtk_wcn_soc_aee_dump_flag_get(VOID) +{ + return MTK_WCN_BOOL_FALSE; +} +static MTK_WCN_BOOL mtk_wcn_soc_trigger_assert(VOID) +{ + INT32 ret = 0; + UINT32 u4Res; + UINT32 tstCmdSz = 0; + UINT32 tstEvtSz = 0; + UINT8 tstCmd[64]; + UINT8 tstEvt[64]; + UINT8 WMT_ASSERT_CMD[] = { 0x01, 0x02, 0x01, 0x00, 0x08 }; + UINT8 WMT_ASSERT_EVT[] = { 0x02, 0x02, 0x00, 0x00, 0x00 }; + + 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); + + ret = wmt_core_tx((PUINT8) tstCmd, tstCmdSz, &u4Res, MTK_WCN_BOOL_FALSE); + if (ret || (u4Res != tstCmdSz)) { + WMT_ERR_FUNC("WMT-CORE: wmt_cmd_test iRet(%d) cmd len err(%d, %d)\n", ret, u4Res, + tstCmdSz); + ret = -1; + } + return (ret == 0); +} + +static INT32 mtk_wcn_soc_ver_check(VOID) +{ + UINT32 hw_ver = 0; + UINT32 fw_ver = 0; + INT32 iret; + const WMT_IC_INFO_S *p_info = NULL; + unsigned long ctrlPa1; + unsigned long ctrlPa2; + + /* 1. identify chip versions: HVR(HW_VER) and FVR(FW_VER) */ + WMT_LOUD_FUNC("0x%x: before read hw_ver (hw version)\n", wmt_ic_ops_soc.icId); + iret = wmt_core_reg_rw_raw(0, GEN_HVR, &hw_ver, GEN_VER_MASK); + if (iret) { + WMT_ERR_FUNC("0x%x: read hw_ver fail:%d\n", wmt_ic_ops_soc.icId, iret); + return -2; + } + WMT_DBG_FUNC("0x%x: read hw_ver (hw version) (0x%x)\n", wmt_ic_ops_soc.icId, hw_ver); + + WMT_LOUD_FUNC("0x%x: before fw_ver (rom version)\n", wmt_ic_ops_soc.icId); + wmt_core_reg_rw_raw(0, GEN_FVR, &fw_ver, GEN_VER_MASK); + if (iret) { + WMT_ERR_FUNC("0x%x: read fw_ver fail:%d\n", wmt_ic_ops_soc.icId, iret); + return -2; + } + WMT_DBG_FUNC("0x%x: read fw_ver (rom version) (0x%x)\n", wmt_ic_ops_soc.icId, fw_ver); + + p_info = mtk_wcn_soc_find_wmt_ic_info(hw_ver); + if (p_info == NULL) { + WMT_ERR_FUNC("0x%x: hw_ver(0x%x) find wmt ic info fail\n", wmt_ic_ops_soc.icId, hw_ver); + return -3; + } + WMT_WARN_FUNC("0x%x: ic info: %s.%s (0x%x/0x%x, HWVER:0x%04x, patch_ext:%s)\n", + wmt_ic_ops_soc.icId, p_info->cChipName, p_info->cChipVersion, + hw_ver, fw_ver, p_info->u4HwVer, p_info->cPatchNameExt); + + /* hw id & version */ + ctrlPa1 = (wmt_ic_ops_soc.icId << 16) | (hw_ver & 0x0000FFFF); + /* translated fw rom version */ + ctrlPa2 = (fw_ver & 0x0000FFFF); + + iret = wmt_core_ctrl(WMT_CTRL_HWIDVER_SET, &ctrlPa1, &ctrlPa2); + if (iret) + WMT_WARN_FUNC("0x%x: WMT_CTRL_HWIDVER_SET fail(%d)\n", wmt_ic_ops_soc.icId, iret); + + gp_soc_info = p_info; + return 0; +} + +static const WMT_IC_INFO_S *mtk_wcn_soc_find_wmt_ic_info(const UINT32 hw_ver) +{ + /* match chipversion with u4HwVer item in mtk_wcn_soc_info_table */ + const UINT32 size = osal_array_size(mtk_wcn_soc_info_table); + INT32 index = 0; + + /* George: reverse the search order to favor newer version products + * TODO:[FixMe][GeorgeKuo] Remove full match once API wmt_lib_get_hwver() + * is changed correctly in the future!! + * Leave full match here is a workaround for GPS to distinguish E3/E4 ICs. + */ + index = size - 1; + /* full match */ + while ((index >= 0) && (hw_ver != mtk_wcn_soc_info_table[index].u4HwVer)) + --index; + if (index >= 0) { + WMT_DBG_FUNC("found ic info(0x%x) by full match! index:%d\n", hw_ver, index); + return &mtk_wcn_soc_info_table[index]; + } + + WMT_WARN_FUNC("find no ic info for (0x%x) by full match!try major num match!\n", hw_ver); + + /* George: The ONLY CORRECT method to find supported hw table. Match MAJOR + * NUM only can help us support future minor hw ECO, or fab switch, etc. + * FULL matching eliminate such flexibility and software package have to be + * updated EACH TIME even when minor hw ECO or fab switch!!! + */ + /* George: reverse the search order to favor newer version products */ + index = size - 1; + /* major num match */ + while ((index >= 0) && + (MAJORNUM(hw_ver) != MAJORNUM(mtk_wcn_soc_info_table[index].u4HwVer))) { + --index; + } + if (index >= 0) { + WMT_DBG_FUNC("0x%x: found ic info for hw_ver(0x%x) by major num! index:%d\n", + wmt_ic_ops_soc.icId, hw_ver, index); + return &mtk_wcn_soc_info_table[index]; + } + + WMT_ERR_FUNC("0x%x: find no ic info for hw_ver(0x%x) by full match nor major num match!\n", + wmt_ic_ops_soc.icId, hw_ver); + WMT_ERR_FUNC("Set default chip version: E1!\n"); + return &mtk_wcn_soc_info_table[0]; +} + +#if CFG_WMT_FILTER_MODE_SETTING +static INT32 wmt_stp_wifi_lte_coex(VOID) +{ + INT32 iRet; + unsigned long addr = 0; + WMT_GEN_CONF *pWmtGenConf = NULL; + + /*Get wmt config */ + iRet = wmt_core_ctrl(WMT_CTRL_GET_WMT_CONF, &addr, 0); + if (iRet) { + WMT_ERR_FUNC("ctrl GET_WMT_CONF fail(%d)\n", iRet); + return -2; + } + WMT_DBG_FUNC("ctrl GET_WMT_CONF ok(0x%08lx)\n", addr); + + pWmtGenConf = (P_WMT_GEN_CONF) addr; + + /*Check if WMT.cfg exists */ + if (pWmtGenConf->cfgExist == 0) { + WMT_INFO_FUNC("cfgExist == 0, skip config chip\n"); + /*if WMT.cfg not existed, still return success and adopt the default value */ + return 0; + } + + osal_sleep_ms(5); + + if (pWmtGenConf->coex_wmt_filter_mode == 0) { + WMT_STEP_DO_ACTIONS_FUNC(STEP_TRIGGER_POINT_POWER_ON_BEFORE_SET_WIFI_LTE_COEX); + if (wmt_ic_ops_soc.options & OPT_WIFI_LTE_COEX_TABLE_1) { + iRet = + wmt_core_init_script(set_wifi_lte_coex_table_1, osal_array_size(set_wifi_lte_coex_table_1)); + WMT_DBG_FUNC("wmt_core:set_wifi_lte_coex_table_1 %s(%d)\n", iRet ? "fail" : "ok", iRet); + } else if (wmt_ic_ops_soc.options & OPT_WIFI_LTE_COEX_TABLE_2) { + /* add WMT_COXE_CONFIG_EXT_COMPONENT_OPCODE command for 2G4 eLNA demand*/ + if (pWmtGenConf->coex_wmt_ext_component) { + WMT_INFO_FUNC("coex_wmt_ext_component:0x%x\n", pWmtGenConf->coex_wmt_ext_component); + set_wifi_lte_coex_table_2[0].cmd[5] = pWmtGenConf->coex_wmt_ext_component; + } + iRet = + wmt_core_init_script(set_wifi_lte_coex_table_2, osal_array_size(set_wifi_lte_coex_table_2)); + WMT_DBG_FUNC("wmt_core:set_wifi_lte_coex_table_2 %s(%d)\n", iRet ? "fail" : "ok", iRet); + } else if (wmt_ic_ops_soc.options & OPT_WIFI_LTE_COEX_TABLE_3) { + iRet = + wmt_core_init_script(set_wifi_lte_coex_table_3, + osal_array_size(set_wifi_lte_coex_table_3)); + WMT_DBG_FUNC("wmt_core:set_wifi_lte_coex_table_3 %s(%d)\n", + iRet ? "fail" : "ok", iRet); + } else { + iRet = + wmt_core_init_script(set_wifi_lte_coex_table_0, osal_array_size(set_wifi_lte_coex_table_0)); + WMT_DBG_FUNC("wmt_core:set_wifi_lte_coex_table_0 %s(%d)\n", iRet ? "fail" : "ok", iRet); + } + } + + return iRet; +} +#endif + +static INT32 wmt_stp_init_coex(VOID) +{ + INT32 iRet; + unsigned long addr = 0; + WMT_GEN_CONF *pWmtGenConf = NULL; + +#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 +#else +#define COEX_WIFI_PATH 1 +#define COEX_EXT_ELAN_GAIN_P1 2 +#define COEX_EXT_EPA_MODE 3 +#endif +#define WMT_COXE_CONFIG_ADJUST_ANTENNA_OPCODE 6 + + /*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; + } + + if (wmt_ic_ops_soc.options & OPT_COEX_EXT_ELNA_GAIN_P1_SUPPORT) { + WMT_INFO_FUNC("elna_gain_p1_support:0x%x\n", pWmtGenConf->coex_wmt_ext_elna_gain_p1_support); + if (pWmtGenConf->coex_wmt_ext_elna_gain_p1_support != 1) + return 0; + } + + /*Dump the coex-related info */ + WMT_DBG_FUNC("coex_wmt_ant_mode:0x%x, coex_wmt_wifi_path:0x%x\n", + pWmtGenConf->coex_wmt_ant_mode, pWmtGenConf->coex_wmt_wifi_path); +#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[4] = WMT_COXE_CONFIG_ADJUST_ANTENNA_OPCODE; + 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); +#else + coex_table[COEX_WIFI_PATH].cmd[5] = + (UINT8)((pWmtGenConf->coex_wmt_wifi_path & 0x00FF) >> 0); + coex_table[COEX_WIFI_PATH].cmd[6] = + (UINT8)((pWmtGenConf->coex_wmt_wifi_path & 0xFF00) >> 8); + + if (gWmtDbgLvl >= WMT_LOG_DBG) { + wmt_core_dump_data(&coex_table[COEX_WIFI_PATH].cmd[0], + coex_table[COEX_WIFI_PATH].str, coex_table[COEX_WIFI_PATH].cmdSz); + } + + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[5] = pWmtGenConf->coex_wmt_ext_elna_gain_p1_support; + /* wmt_ext_elna_gain_p1 D0*/ + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[6] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D0 & 0x000000FF) >> 0); + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[7] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D0 & 0x0000FF00) >> 8); + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[8] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D0 & 0x00FF0000) >> 16); + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[9] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D0 & 0xFF000000) >> 24); + /* wmt_ext_elna_gain_p1 D1*/ + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[10] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D1 & 0x000000FF) >> 0); + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[11] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D1 & 0x0000FF00) >> 8); + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[12] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D1 & 0x00FF0000) >> 16); + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[13] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D1 & 0xFF000000) >> 24); + /* wmt_ext_elna_gain_p1 D2*/ + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[14] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D2 & 0x000000FF) >> 0); + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[15] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D2 & 0x0000FF00) >> 8); + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[16] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D2 & 0x00FF0000) >> 16); + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[17] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D2 & 0xFF000000) >> 24); + /* wmt_ext_elna_gain_p1 D3*/ + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[18] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D3 & 0x000000FF) >> 0); + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[19] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D3 & 0x0000FF00) >> 8); + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[20] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D3 & 0x00FF0000) >> 16); + coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[21] = + (UINT8)((pWmtGenConf->coex_wmt_ext_elna_gain_p1_D3 & 0xFF000000) >> 24); + + if (gWmtDbgLvl >= WMT_LOG_DBG) { + wmt_core_dump_data(&coex_table[COEX_EXT_ELAN_GAIN_P1].cmd[0], + coex_table[COEX_EXT_ELAN_GAIN_P1].str, + coex_table[COEX_EXT_ELAN_GAIN_P1].cmdSz); + } + + coex_table[COEX_EXT_EPA_MODE].cmd[5] = pWmtGenConf->coex_wmt_ext_epa_mode; +#endif + + iRet = wmt_core_init_script(coex_table, ARRAY_SIZE(coex_table)); + + return iRet; +} + +static INT32 wmt_stp_init_epa(VOID) +{ + INT32 iRet; + unsigned long addr = 0; + WMT_GEN_CONF *pWmtGenConf = NULL; + + /*Get wmt config */ + iRet = wmt_core_ctrl(WMT_CTRL_GET_WMT_CONF, &addr, 0); + if (iRet) { + WMT_ERR_FUNC("ctrl GET_WMT_CONF fail(%d)\n", iRet); + return -2; + } + WMT_DBG_FUNC("ctrl GET_WMT_CONF ok(0x%08lx)\n", addr); + + pWmtGenConf = (P_WMT_GEN_CONF) addr; + + /*Check if WMT.cfg exists */ + if (pWmtGenConf->cfgExist == 0) { + WMT_DBG_FUNC("cfgExist == 0, skip config chip\n"); + /*if WMT.cfg not existed, still return success and adopt the default value */ + return 0; + } + + WMT_INFO_FUNC("epa_mode:0x%x\n", pWmtGenConf->coex_wmt_ant_mode_ex); + + if (pWmtGenConf->coex_wmt_ant_mode_ex != 1) + return 0; + + epa_table[0].cmd[5] = pWmtGenConf->coex_wmt_ant_mode_ex; + if (gWmtDbgLvl >= WMT_LOG_DBG) + wmt_core_dump_data(&epa_table[0].cmd[0], epa_table[0].str, epa_table[0].cmdSz); + iRet = wmt_core_init_script(epa_table, ARRAY_SIZE(epa_table)); + + return iRet; +} + +static INT32 wmt_stp_init_epa_elna(VOID) +{ + INT32 iRet; + unsigned long addr = 0; + WMT_GEN_CONF *pWmtGenConf = NULL; + struct init_script script[1]; + struct WMT_BYTE_ARRAY *ba = NULL; + INT32 cmd_size; + INT32 data_size; + PUINT8 cmd; + UINT16 index = 0; + + /*Get wmt config */ + iRet = wmt_core_ctrl(WMT_CTRL_GET_WMT_CONF, &addr, 0); + if (iRet) { + WMT_ERR_FUNC("ctrl GET_WMT_CONF fail(%d)\n", iRet); + return -2; + } + WMT_DBG_FUNC("ctrl GET_WMT_CONF ok(0x%08lx)\n", addr); + + pWmtGenConf = (P_WMT_GEN_CONF) addr; + + /*Check if WMT.cfg exists */ + if (pWmtGenConf->cfgExist == 0) { + WMT_DBG_FUNC("cfgExist == 0, skip config chip\n"); + /*if WMT.cfg not existed, still return success and adopt the default value */ + return 0; + } + + if (pWmtGenConf->coex_wmt_epa_elna == NULL) + return 0; + + ba = pWmtGenConf->coex_wmt_epa_elna; + + /* cmd_size = direction(1) + op(1) + length(2) + coex op(1) + data */ + cmd_size = ba->size + 5; + cmd = (PUINT8)osal_malloc(cmd_size); + + if (cmd == NULL) { + WMT_ERR_FUNC("failed to malloc when init epa elna\n"); + return -1; + } + + /* 0x1: direction, 0x10: op code */ + cmd[index++] = 0x1; + cmd[index++] = 0x10; + + /* add 1 for coex op id */ + data_size = ba->size + 1; + /* assign data length */ + cmd[index++] = (data_size & 0x00FF) >> 0; + cmd[index++] = (data_size & 0xFF00) >> 8; + /* assign coex op id: 0x1D */ + cmd[index++] = 0x1D; + + osal_memcpy(&cmd[index], ba->data, ba->size); + + script[0].cmd = cmd; + script[0].cmdSz = cmd_size; + script[0].evt = WMT_EPA_ELNA_SETTING_CONFIG_EVT; + script[0].evtSz = sizeof(WMT_EPA_ELNA_SETTING_CONFIG_EVT); + script[0].str = "coex_wmt_epa_elna"; + + if (gWmtDbgLvl >= WMT_LOG_DBG) + wmt_core_dump_data(&(script[0].cmd[0]), script[0].str, + script[0].cmdSz); + + iRet = wmt_core_init_script(script, ARRAY_SIZE(script)); + + osal_free(cmd); + return iRet; +} + +static INT32 wmt_stp_init_epa_elna_invert_cr(VOID) +{ + INT32 iRet; + UINT32 uVal = 0; + unsigned long addr = 0; + WMT_GEN_CONF *pWmtGenConf = NULL; + UINT32 default_invert_cr[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + UINT32 default_invert_bit[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + PINT8 pbuf; + long res = 0; + PINT8 tok1, tok2; + UINT32 item1, item2, item_index; + UINT32 invert_cr, invert_bit; + + mtk_wcn_consys_ic_get_ant_sel_cr_addr(default_invert_cr, default_invert_bit); + pWmtGenConf = (P_WMT_GEN_CONF) addr; + + /*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_DBG_FUNC("cfgExist == 0, skip config chip\n"); + /*if WMT.cfg not existed, still return success and adopt the default value */ + return 0; + } + + WMT_DBG_FUNC("pWmtGenConf->coex_wmt_antsel_invert_support=[%s]\n", + pWmtGenConf->coex_wmt_antsel_invert_support); + + if (pWmtGenConf->coex_wmt_antsel_invert_support == NULL || + osal_strlen(pWmtGenConf->coex_wmt_antsel_invert_support) <= 0) + return 0; + + pbuf = osal_malloc(osal_strlen(pWmtGenConf->coex_wmt_antsel_invert_support)+1); + if (pbuf == NULL) { + WMT_ERR_FUNC("init_invert_cr, malloc fail, size %d\n", + osal_strlen(pWmtGenConf->coex_wmt_antsel_invert_support)+1); + return -1; + } + + osal_strcpy(pbuf, pWmtGenConf->coex_wmt_antsel_invert_support); + + while ((tok1 = osal_strsep(&pbuf, " /\\")) != NULL) { + if (*tok1 == '\0') + continue; + if (!*tok1) + continue; + item1 = 0; + item2 = 0; + item_index = 0; + while ((tok2 = osal_strsep(&tok1, " ,")) != NULL) { + if (*tok2 == '\0') + continue; + if (!*tok2) + continue; + if ((osal_strlen(tok2) > 2) && ((*tok2) == '0') && (*(tok2 + 1) == 'x')) + osal_strtol(tok2 + 2, 16, &res); + else + osal_strtol(tok2, 10, &res); + if (item_index == 0) + item1 = res; + else if (item_index == 1) + item2 = res; + item_index++; + } + + if (item_index != 1 && item_index != 2) + continue; + if ((item_index == 1) && (item1 > 7 || item1 < 0)) + continue; + if ((item_index == 2) && (item2 > 31 || item2 < 0)) + continue; + + if (item_index == 1) { + invert_cr = default_invert_cr[item1]; + invert_bit = default_invert_bit[item1]; + } else if (item_index == 2) { + invert_cr = item1; + invert_bit = item2; + } + + if (invert_cr == 0) + continue; + + uVal = 0; + iRet = wmt_core_reg_rw_raw(0, invert_cr, &uVal, 0xFFFFFFFF); + if (iRet) { + WMT_ERR_FUNC("init_invert_cr, read 0x%x[%d](before write) fail(%d)\n", + invert_cr, invert_bit, iRet); + continue; + } + WMT_DBG_FUNC("init_invert_cr, 0x%x[%d](before write) = 0x%x\n", + invert_cr, invert_bit, uVal); + + uVal = 0x1 << invert_bit; + iRet = wmt_core_reg_rw_raw(1, invert_cr, &uVal, 0x1 << invert_bit); + if (iRet) { + WMT_ERR_FUNC("init_invert_cr, write 0x%x[%d]=1 fail(%d)\n", + invert_cr, invert_bit, iRet); + continue; + } + + uVal = 0; + iRet = wmt_core_reg_rw_raw(0, invert_cr, &uVal, 0xFFFFFFFF); + if (iRet) { + WMT_ERR_FUNC("init_invert_cr, read 0x%x[%d](after write) fail(%d)\n", + invert_cr, invert_bit, iRet); + continue; + } + WMT_DBG_FUNC("init_invert_cr, 0x%x[%d](after write) = 0x%x\n", + invert_cr, invert_bit, uVal); + } + + if (pbuf != NULL) { + osal_free(pbuf); + pbuf = NULL; + } + + return 0; +} + +static INT32 wmt_stp_init_wifi_ant_swap(VOID) +{ + INT32 iRet; + unsigned long addr = 0; + WMT_GEN_CONF *pWmtGenConf = NULL; + UINT8 ant_swap_mode, polarity, ant_sel; + + /*Get wmt config */ + iRet = wmt_core_ctrl(WMT_CTRL_GET_WMT_CONF, &addr, 0); + if (iRet) { + WMT_ERR_FUNC("ctrl GET_WMT_CONF fail(%d)\n", iRet); + return -2; + } + WMT_DBG_FUNC("ctrl GET_WMT_CONF ok(0x%08lx)\n", addr); + + pWmtGenConf = (P_WMT_GEN_CONF) addr; + + /*Check if WMT.cfg exists */ + if (pWmtGenConf->cfgExist == 0) { + WMT_DBG_FUNC("cfgExist == 0, skip config chip\n"); + /*if WMT.cfg not existed, still return success and adopt the default value */ + return 0; + } + + ant_swap_mode = pWmtGenConf->wifi_ant_swap_mode; + polarity = pWmtGenConf->wifi_main_ant_polarity; + ant_sel = pWmtGenConf->wifi_ant_swap_ant_sel_gpio; + + WMT_INFO_FUNC("ant swap mode = %d, main_polarity = %d, ant_sel = %d\n", + ant_swap_mode, polarity, ant_sel); + + if (ant_swap_mode <= 0 || ant_swap_mode > 2) + return 0; + + if (ant_swap_mode == 2 && + mtk_consys_is_ant_swap_enable_by_hwid() == 0) + return 0; + + wifi_ant_swap_table[0].cmd[6] = polarity; + + if (ant_sel > 0) + wifi_ant_swap_table[0].cmd[7] = ant_sel; + else { + /* backward compatible */ + wifi_ant_swap_table[0].cmdSz = sizeof(WMT_WIFI_ANT_SWAP_CMD) - 1; + wifi_ant_swap_table[0].cmd[2] = 3; /* length */ + wifi_ant_swap_table[0].cmd[4] = 6; /* op id */ + wifi_ant_swap_table[0].evt[5] = 6; /* op id */ + } + + iRet = wmt_core_init_script(wifi_ant_swap_table, ARRAY_SIZE(wifi_ant_swap_table)); + + return iRet; +} + +static INT32 wmt_init_wifi_config(VOID) +{ + INT32 iRet; + unsigned long addr = 0; + WMT_GEN_CONF *pWmtGenConf = NULL; + struct init_script script[1]; + struct WMT_BYTE_ARRAY *ba = NULL; + INT32 cmd_size; + INT32 data_size; + PUINT8 cmd; + UINT16 index = 0; + + /*Get wmt config */ + iRet = wmt_core_ctrl(WMT_CTRL_GET_WMT_CONF, &addr, 0); + if (iRet) { + WMT_ERR_FUNC("ctrl GET_WMT_CONF fail(%d)\n", iRet); + return -2; + } + WMT_DBG_FUNC("ctrl GET_WMT_CONF ok(0x%08lx)\n", addr); + + pWmtGenConf = (P_WMT_GEN_CONF) addr; + + /*Check if WMT.cfg exists */ + if (pWmtGenConf->cfgExist == 0) { + WMT_DBG_FUNC("cfgExist == 0, skip config chip\n"); + /*if WMT.cfg not existed, still return success and adopt the default value */ + return 0; + } + + if (pWmtGenConf->wifi_config == NULL) + return 0; + + ba = pWmtGenConf->wifi_config; + + /* cmd_size = direction(1) + op(1) + length(2) + sub op(1) + data_len(1) + data */ + cmd_size = ba->size + 6; + cmd = (PUINT8)osal_malloc(cmd_size); + + if (cmd == NULL) { + WMT_ERR_FUNC("failed to malloc when init wifi config\n"); + return -1; + } + + /* 0x1: direction, 0x2: op code */ + cmd[index++] = 0x1; + cmd[index++] = 0x2; + + /* add 2 for test op id and data length */ + data_size = ba->size + 2; + /* assign data length */ + cmd[index++] = (data_size & 0x00FF) >> 0; + cmd[index++] = (data_size & 0xFF00) >> 8; + /* assign op id: 0x14 */ + cmd[index++] = 0x14; + /* assign data length */ + /* A byte to store data length is because firmware test op handler cannot see data length*/ + cmd[index++] = (UINT8)ba->size; + + osal_memcpy(&cmd[index], ba->data, ba->size); + + script[0].cmd = cmd; + script[0].cmdSz = cmd_size; + script[0].evt = WMT_WIFI_CONFIG_EVT; + script[0].evtSz = sizeof(WMT_WIFI_CONFIG_EVT); + script[0].str = "wifi_config"; + + if (gWmtDbgLvl >= WMT_LOG_DBG) + wmt_core_dump_data(&(script[0].cmd[0]), script[0].str, + script[0].cmdSz); + + iRet = wmt_core_init_script(script, ARRAY_SIZE(script)); + + osal_free(cmd); + + return iRet; +} + +#if CFG_WMT_SDIO_DRIVING_SET +static INT32 mtk_wcn_soc_set_sdio_driving(void) +{ + INT32 ret = 0; + + unsigned long addr = 0; + WMT_GEN_CONF *pWmtGenConf = NULL; + UINT32 drv_val = 0; + + /*Get wmt config */ + ret = wmt_core_ctrl(WMT_CTRL_GET_WMT_CONF, &addr, 0); + if (ret) { + WMT_ERR_FUNC("ctrl GET_WMT_CONF fail(%d)\n", ret); + return -1; + } + WMT_INFO_FUNC("ctrl GET_WMT_CONF ok(0x%08lx)\n", addr); + + pWmtGenConf = (P_WMT_GEN_CONF) addr; + + /*Check if WMT.cfg exists */ + if (pWmtGenConf->cfgExist == 0) { + WMT_INFO_FUNC("cfgExist == 0, skip config chip\n"); + /*if WMT.cfg not existed, still return success and adopt the default value */ + return 0; + } + + drv_val = pWmtGenConf->sdio_driving_cfg; + + /*Dump the sdio driving related info */ + WMT_INFO_FUNC("sdio driving:0x%x\n", drv_val); + + sdio_driving_table[0].cmd[12] = (UINT8) ((drv_val & 0x00000077UL) >> 0); /* DAT0 and DAT1 */ + sdio_driving_table[0].cmd[13] = (UINT8) ((drv_val & 0x00007700UL) >> 8); /* DAT2 and DAT3 */ + sdio_driving_table[0].cmd[14] = (UINT8) ((drv_val & 0x00070000UL) >> 16); /* CMD */ + + ret = wmt_core_init_script(sdio_driving_table, ARRAY_SIZE(sdio_driving_table)); + + return ret; +} +#endif + +#if CFG_WMT_CRYSTAL_TIMING_SET +static INT32 mtk_wcn_soc_crystal_triming_set(VOID) +{ + INT32 iRet = 0; + PUINT8 pbuf = NULL; + UINT32 bufLen = 0; + WMT_CTRL_DATA ctrlData; + UINT32 uCryTimOffset = 0x6D; + MTK_WCN_BOOL bIsNvramExist = MTK_WCN_BOOL_FALSE; + INT8 cCrystalTimingOffset = 0x0; + UINT8 cCrystalTiming = 0x0; + INT32 iCrystalTiming = 0x0; + MTK_WCN_BOOL bIsCrysTrimEnabled = MTK_WCN_BOOL_FALSE; + UINT32 u4Res; + + bIsNvramExist = MTK_WCN_BOOL_FALSE; + /**/ ctrlData.ctrlId = WMT_CTRL_CRYSTAL_TRIMING_GET; + ctrlData.au4CtrlData[0] = (UINT32) "/data/nvram/APCFG/APRDEB/WIFI"; + ctrlData.au4CtrlData[1] = (UINT32) &pbuf; + ctrlData.au4CtrlData[2] = (UINT32) &bufLen; + + iRet = wmt_ctrl(&ctrlData); + if (iRet != 0) { + WMT_ERR_FUNC("0x%x: WMT_CTRL_CRYSTAL_TRIMING_GET fail:%d\n", wmt_ic_ops_soc.icId, iRet); + bIsNvramExist = MTK_WCN_BOOL_FALSE; + bIsCrysTrimEnabled = MTK_WCN_BOOL_FALSE; + cCrystalTimingOffset = 0x0; + cCrystalTiming = 0x0; + iRet = -1; + } else { + WMT_DBG_FUNC("0x%x: nvram pBuf(0x%08x), bufLen(%d)\n", wmt_ic_ops_soc.icId, pbuf, bufLen); + if (bufLen < (uCryTimOffset + 1)) { + WMT_ERR_FUNC("0x%x: nvram len(%d) too short, crystalTimging value offset(%d)\n", + wmt_ic_ops_soc.icId, bufLen, uCryTimOffset); + bIsNvramExist = MTK_WCN_BOOL_FALSE; + bIsCrysTrimEnabled = MTK_WCN_BOOL_FALSE; + cCrystalTimingOffset = 0x0; + cCrystalTiming = 0x0; + } else { + bIsNvramExist = MTK_WCN_BOOL_TRUE; + cCrystalTimingOffset = *(pbuf + uCryTimOffset); + if (cCrystalTimingOffset & 0x80) { + bIsCrysTrimEnabled = MTK_WCN_BOOL_TRUE; + cCrystalTimingOffset = (UINT8) cCrystalTimingOffset & 0x7f; + } + WMT_DBG_FUNC("cCrystalTimingOffset (%d), bIsCrysTrimEnabled(%d)\n", cCrystalTimingOffset, + bIsCrysTrimEnabled); + } + ctrlData.ctrlId = WMT_CTRL_CRYSTAL_TRIMING_PUT; + ctrlData.au4CtrlData[0] = (UINT32) "/data/nvram/APCFG/APRDEB/WIFI"; + iRet = wmt_ctrl(&ctrlData); + if (iRet != 0) { + WMT_ERR_FUNC("0x%x: WMT_CTRL_CRYSTAL_TRIMING_PUT fail:%d\n", wmt_ic_ops_soc.icId, iRet); + iRet = -2; + } else { + WMT_DBG_FUNC("0x%x: WMT_CTRL_CRYSTAL_TRIMING_PUT succeed\n", wmt_ic_ops_soc.icId); + } + } + if ((bIsNvramExist == MTK_WCN_BOOL_TRUE) && (bIsCrysTrimEnabled == MTK_WCN_BOOL_TRUE)) { + /*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); + if (iCrystalTiming > 0x7f) + cCrystalTiming = 0x7f; + else if (iCrystalTiming < 0) + cCrystalTiming = 0; + else + cCrystalTiming = iCrystalTiming; + WMT_DBG_FUNC("cCrystalTiming (0x%x)\n", cCrystalTiming); + /* set_crystal_timing_script */ + WMT_SET_CRYSTAL_TRIMING_CMD[5] = cCrystalTiming; + WMT_GET_CRYSTAL_TRIMING_EVT[5] = cCrystalTiming; + + iRet = wmt_core_init_script(set_crystal_timing_script, osal_array_size(set_crystal_timing_script)); + if (iRet) { + WMT_ERR_FUNC("set_crystal_timing_script fail(%d)\n", iRet); + iRet = -5; + } else { + WMT_DBG_FUNC("set crystal timing value (0x%x) succeed\n", WMT_SET_CRYSTAL_TRIMING_CMD[5]); + iRet = + wmt_core_init_script(get_crystal_timing_script, osal_array_size(get_crystal_timing_script)); + if (iRet) { + WMT_ERR_FUNC("get_crystal_timing_script fail(%d)\n", iRet); + iRet = -6; + } else { + WMT_INFO_FUNC("succeed, updated crystal timing value (0x%x)\n", + WMT_GET_CRYSTAL_TRIMING_EVT[5]); + iRet = 0x0; + } + } + } +done: + return iRet; +} +#endif + +#if CFG_WMT_MULTI_PATCH +static INT32 mtk_wcn_soc_patch_info_prepare(VOID) +{ + INT32 iRet = -1; + WMT_CTRL_DATA ctrlData; + + ctrlData.ctrlId = WMT_CTRL_PATCH_SEARCH; + iRet = wmt_ctrl(&ctrlData); + + return iRet; +} + +static UINT32 mtk_wcn_soc_get_patch_num(VOID) +{ + ULONG ctrlPa1 = 0; + ULONG ctrlPa2 = 0; + + wmt_core_ctrl(WMT_CTRL_GET_PATCH_NUM, &ctrlPa1, &ctrlPa2); + WMT_DBG_FUNC("patch total num = [%lu]\n", ctrlPa1); + return ctrlPa1; +} + +static UINT32 mtk_wcn_soc_update_patch_version(VOID) +{ + return wmt_core_ctrl(WMT_CTRL_UPDATE_PATCH_VERSION, NULL, NULL); +} + +static INT32 mtk_wcn_soc_normal_patch_dwn(PUINT8 pPatchBuf, UINT32 patchSize, PUINT8 addressByte) +{ + INT32 iRet = -1; + UINT32 patchSizePerFrag = 0; + UINT32 fragSeq; + UINT32 fragNum; + UINT16 fragSize = 0; + UINT16 cmdLen; + UINT32 offset; + UINT32 u4Res; + UINT8 evtBuf[8]; + UINT8 addressevtBuf[12]; + + patchSizePerFrag = DEFAULT_PATCH_FRAG_SIZE; + /* reserve 1st patch cmd space before patch body + * |<-WMT_CMD: 5Bytes->|<-patch body: X Bytes (X=patchSize)----->| + */ + pPatchBuf -= sizeof(WMT_PATCH_CMD); + + fragNum = patchSize / patchSizePerFrag; + fragNum += ((fragNum * patchSizePerFrag) == patchSize) ? 0 : 1; + + WMT_INFO_FUNC("normal patch download patch size(%d) fragNum(%d)\n", patchSize, fragNum); + + /*send wmt part patch address command */ + if (wmt_ic_ops_soc.options & OPT_NORMAL_PATCH_DWN_0) { + /* ROMv2 patch RAM base */ + WMT_PATCH_ADDRESS_CMD[8] = 0x40; + WMT_PATCH_P_ADDRESS_CMD[8] = 0xc8; + } + /*send wmt part patch address command */ + if (wmt_ic_ops_soc.options & OPT_NORMAL_PATCH_DWN_1) { + /* ROMv3 patch RAM base */ + WMT_PATCH_ADDRESS_CMD[8] = 0x08; + WMT_PATCH_ADDRESS_CMD[9] = 0x05; + WMT_PATCH_P_ADDRESS_CMD[8] = 0x2c; + WMT_PATCH_P_ADDRESS_CMD[9] = 0x0b; + } + + if (wmt_ic_ops_soc.options & OPT_NORMAL_PATCH_DWN_2) { + /* ROMv4 patch RAM base */ + WMT_PATCH_ADDRESS_CMD[8] = 0x18; + WMT_PATCH_ADDRESS_CMD[9] = 0x05; + WMT_PATCH_P_ADDRESS_CMD[8] = 0x7c; + WMT_PATCH_P_ADDRESS_CMD[9] = 0x0b; + } + + if (wmt_ic_ops_soc.options & OPT_NORMAL_PATCH_DWN_3) { + /*send part patch address command */ + WMT_PATCH_ADDRESS_CMD_NEW[5] = addressByte[0]; + WMT_PATCH_ADDRESS_CMD_NEW[6] = addressByte[1]; + WMT_PATCH_ADDRESS_CMD_NEW[7] = addressByte[2]; + WMT_PATCH_ADDRESS_CMD_NEW[8] = addressByte[3]; + WMT_DBG_FUNC("4 bytes address command:0x%02x,0x%02x,0x%02x,0x%02x", + WMT_PATCH_ADDRESS_CMD_NEW[5], + WMT_PATCH_ADDRESS_CMD_NEW[6], + WMT_PATCH_ADDRESS_CMD_NEW[7], + WMT_PATCH_ADDRESS_CMD_NEW[8]); + iRet = wmt_core_tx((PUINT8) &WMT_PATCH_ADDRESS_CMD_NEW[0], sizeof(WMT_PATCH_ADDRESS_CMD_NEW), + &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != sizeof(WMT_PATCH_ADDRESS_CMD_NEW))) { + WMT_ERR_FUNC("wmt_core:wmt part patch address CMD fail(%d),size(%d)\n", iRet, u4Res); + return -1; + } + osal_memset(addressevtBuf, 0, sizeof(addressevtBuf)); + iRet = wmt_core_rx(addressevtBuf, sizeof(WMT_PATCH_ADDRESS_EVT_NEW), &u4Res); + if (iRet || (u4Res != sizeof(WMT_PATCH_ADDRESS_EVT_NEW))) { + WMT_ERR_FUNC("wmt_core:wmt patch address EVT fail(%d),size(%d)\n", iRet, u4Res); + WMT_INFO_FUNC("buf:[%2X,%2X,%2X,%2X,%2X] evt:[%2X,%2X,%2X,%2X,%2X]\n", + addressevtBuf[0], addressevtBuf[1], addressevtBuf[2], + addressevtBuf[3], addressevtBuf[4], + WMT_PATCH_ADDRESS_EVT_NEW[0], WMT_PATCH_ADDRESS_EVT_NEW[1], + WMT_PATCH_ADDRESS_EVT_NEW[2], WMT_PATCH_ADDRESS_EVT_NEW[3], + WMT_PATCH_ADDRESS_EVT_NEW[4]); + mtk_wcn_stp_dbg_dump_package(); + return -1; + } + goto patch_download; + } + + /*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); + return -1; + } + 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); + mtk_wcn_stp_dbg_dump_package(); + return -1; + } +#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"); + return -1; + } +#endif + + /*send part patch address command */ + WMT_PATCH_P_ADDRESS_CMD[12] = addressByte[0]; + WMT_PATCH_P_ADDRESS_CMD[13] = addressByte[1]; + WMT_PATCH_P_ADDRESS_CMD[14] = addressByte[2]; + WMT_PATCH_P_ADDRESS_CMD[15] = addressByte[3]; + WMT_DBG_FUNC("4 bytes address command:0x%02x,0x%02x,0x%02x,0x%02x", + WMT_PATCH_P_ADDRESS_CMD[12], + WMT_PATCH_P_ADDRESS_CMD[13], WMT_PATCH_P_ADDRESS_CMD[14], WMT_PATCH_P_ADDRESS_CMD[15]); + iRet = + wmt_core_tx((PUINT8) &WMT_PATCH_P_ADDRESS_CMD[0], sizeof(WMT_PATCH_P_ADDRESS_CMD), &u4Res, + MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != sizeof(WMT_PATCH_P_ADDRESS_CMD))) { + WMT_ERR_FUNC("wmt_core:wmt part patch address CMD fail(%d),size(%d)\n", iRet, u4Res); + return -1; + } + 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)\n", iRet, u4Res); + mtk_wcn_stp_dbg_dump_package(); + return -1; + } +#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\n"); + return -1; + } +#endif + +patch_download: + /* 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(pPatchBuf + 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(pPatchBuf + 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(%lu, %d) fail(%d)\n", fragSeq, + fragSize + sizeof(WMT_PATCH_CMD), u4Res, iRet); + iRet = -1; + break; + } + WMT_DBG_FUNC("wmt_core: write fragSeq(%d) size(%lu, %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(%lu, %d) fail(%d)\n", sizeof(WMT_PATCH_EVT), + u4Res, iRet); + mtk_wcn_stp_dbg_dump_package(); + iRet = -1; + break; + } +#if CFG_CHECK_WMT_RESULT + if (osal_memcmp(evtBuf, WMT_PATCH_EVT, sizeof(WMT_PATCH_EVT)) != 0) { + WMT_ERR_FUNC("wmt_core: compare WMT_PATCH_EVT error rx(%d):[%02X,%02X,%02X,%02X,%02X]\n", + u4Res, + evtBuf[0], + evtBuf[1], + evtBuf[2], + evtBuf[3], + evtBuf[4]); + WMT_ERR_FUNC("wmt_core: exp(%lu):[%02X,%02X,%02X,%02X,%02X]\n", + sizeof(WMT_PATCH_EVT), + WMT_PATCH_EVT[0], + WMT_PATCH_EVT[1], + WMT_PATCH_EVT[2], + WMT_PATCH_EVT[3], + WMT_PATCH_EVT[4]); + iRet = -1; + break; + } +#endif + WMT_DBG_FUNC("wmt_core: read WMT_PATCH_EVT length(%lu, %d) ok\n", sizeof(WMT_PATCH_EVT), u4Res); + offset += patchSizePerFrag; + ++fragSeq; + } + + WMT_WARN_FUNC("wmt_core: patch dwn:%d frag(%d, %d) %s\n", + iRet, fragSeq, fragSize, (!iRet && (fragSeq == fragNum)) ? "ok" : "fail"); + + if (fragSeq != fragNum) + return -1; + + return 0; +} + +static INT32 mtk_wcn_soc_pda_patch_dwn(PUINT8 pPatchBuf, UINT32 patchSize, PUINT8 addressByte) +{ +#define PDAHDRLEN 12 + UINT32 u4Res; + UINT8 evtBuf[8]; + INT32 iRet = -1; + UINT32 fragSeq; + UINT32 fragNum; + UINT16 fragSize = 0; + UINT32 patchSizePerFrag = 0; + UINT32 offset; + UINT8 pdaHdr[PDAHDRLEN]; + + /* PDA download address, LSB */ + WMT_PATCH_PDA_CFG_CMD[5] = addressByte[0]; + WMT_PATCH_PDA_CFG_CMD[6] = addressByte[1]; + WMT_PATCH_PDA_CFG_CMD[7] = addressByte[2]; + WMT_PATCH_PDA_CFG_CMD[8] = addressByte[3]; + + /* PDA download size, LSB */ + WMT_PATCH_PDA_CFG_CMD[9] = (patchSize & 0x000000FF); + WMT_PATCH_PDA_CFG_CMD[10] = (patchSize & 0x0000FF00) >> 8; + WMT_PATCH_PDA_CFG_CMD[11] = (patchSize & 0x00FF0000) >> 16; + WMT_PATCH_PDA_CFG_CMD[12] = (patchSize & 0xFF000000) >> 24; + + iRet = wmt_core_tx((PUINT8) &WMT_PATCH_PDA_CFG_CMD[0], sizeof(WMT_PATCH_PDA_CFG_CMD), &u4Res, + MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != sizeof(WMT_PATCH_PDA_CFG_CMD))) { + WMT_ERR_FUNC("wmt_core:wmt part patch PDA config CMD fail(%d),size(%d)\n", + iRet, u4Res); + return -1; + } + osal_memset(evtBuf, 0, sizeof(evtBuf)); + iRet = wmt_core_rx(evtBuf, sizeof(WMT_PATCH_PDA_CFG_EVT), &u4Res); + if (iRet || (u4Res != sizeof(WMT_PATCH_PDA_CFG_EVT))) { + WMT_ERR_FUNC("wmt_core:wmt patch PDA config EVT fail(%d),size(%d)\n", + iRet, u4Res); + WMT_INFO_FUNC("buf:[%2X,%2X,%2X,%2X,%2X] evt:[%2X,%2X,%2X,%2X,%2X]\n", + evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], + WMT_PATCH_PDA_CFG_EVT[0], WMT_PATCH_PDA_CFG_EVT[1], + WMT_PATCH_PDA_CFG_EVT[2], WMT_PATCH_PDA_CFG_EVT[3], + WMT_PATCH_PDA_CFG_EVT[4]); + mtk_wcn_stp_dbg_dump_package(); + return -1; + } + + patchSizePerFrag = DEFAULT_PATCH_FRAG_SIZE; + fragNum = patchSize / patchSizePerFrag; + fragNum += ((fragNum * patchSizePerFrag) == patchSize) ? 0 : 1; + + osal_memset(pdaHdr, 0, PDAHDRLEN); + pdaHdr[0] = (patchSize + PDAHDRLEN) & 0x000000FF; + pdaHdr[1] = ((patchSize + PDAHDRLEN) & 0x0000FF00) >> 8; + pdaHdr[2] = ((patchSize + PDAHDRLEN) & 0x00FF0000) >> 16; + pdaHdr[3] = ((patchSize + PDAHDRLEN) & 0xFF000000) >> 24; + + iRet = wmt_core_tx(pdaHdr, PDAHDRLEN, &u4Res, MTK_WCN_BOOL_TRUE); + if (iRet || (u4Res != PDAHDRLEN)) { + WMT_ERR_FUNC("wmt_core: set length:%d fails, u4Res:%d\n", PDAHDRLEN, u4Res); + return -1; + } + + /* send all fragments */ + offset = 0; + fragSeq = 0; + while (fragSeq < fragNum) { + if (fragSeq == (fragNum - 1)) { + /* last fragment */ + fragSize = patchSize - fragSeq * patchSizePerFrag; + } else + fragSize = patchSizePerFrag; + + iRet = wmt_core_tx(pPatchBuf + offset, fragSize, &u4Res, MTK_WCN_BOOL_TRUE); + if (iRet || (u4Res != fragSize)) { + WMT_ERR_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) fail(%d)\n", + fragSeq, fragSize, u4Res, iRet); + iRet = -1; + break; + } + + WMT_DBG_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) ok\n", + fragSeq, fragSize, 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) + return -1; + + return 0; +} + +static INT32 mtk_wcn_soc_patch_dwn(UINT32 index) +{ + INT32 iRet = -1; + P_WMT_PATCH patchHdr = NULL; + PUINT8 pBuf = NULL; + PUINT8 pPatchBuf = NULL; + PUINT8 patchBuildTimeAddr; + UINT32 patchSize; + PINT8 cDataTime = NULL; + UINT16 u2HwVer = 0; + UINT16 u2SwVer = 0; + UINT32 u4PatchVer = 0; + WMT_CTRL_DATA ctrlData; + P_CONSYS_EMI_ADDR_INFO emiInfo; + UINT8 addressByte[4]; + + /*1.check hardware information */ + if (gp_soc_info == NULL) { + WMT_ERR_FUNC("null gp_soc_info!\n"); + return -1; + } + + osal_memset(gFullPatchName, 0, osal_sizeof(gFullPatchName)); + + ctrlData.ctrlId = WMT_CTRL_GET_PATCH_INFO; + ctrlData.au4CtrlData[0] = index + 1; + ctrlData.au4CtrlData[1] = (SIZE_T)&gFullPatchName; + ctrlData.au4CtrlData[2] = (SIZE_T)&addressByte; + iRet = wmt_ctrl(&ctrlData); + WMT_DBG_FUNC("the %d time valid patch found: (%s)\n", index + 1, gFullPatchName); + + if (iRet) { + WMT_ERR_FUNC("wmt_core: WMT_CTRL_GET_PATCH_INFO fail:%d\n", iRet); + goto done; + } + + /* <2.2> read patch content */ + ctrlData.ctrlId = WMT_CTRL_GET_PATCH; + ctrlData.au4CtrlData[0] = (SIZE_T)NULL; + ctrlData.au4CtrlData[1] = (SIZE_T)&gFullPatchName; + ctrlData.au4CtrlData[2] = (SIZE_T)&pBuf; + ctrlData.au4CtrlData[3] = (SIZE_T)&patchSize; + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + WMT_ERR_FUNC("wmt_core: WMT_CTRL_GET_PATCH fail:%d\n", iRet); + iRet -= 1; + goto done; + } + + /* |<-BCNT_PATCH_BUF_HEADROOM(8) bytes dummy allocated->|<-patch file->| */ + /* patch file with header: + * |<-patch header: 28 Bytes->|<-patch body: X Bytes ----->| + */ + pPatchBuf = osal_malloc(patchSize); + if (pPatchBuf == NULL) { + WMT_ERR_FUNC("vmalloc pPatchBuf for patch download fail\n"); + return -2; + } + osal_memcpy(pPatchBuf, pBuf, patchSize); + /* check patch file information */ + patchHdr = (P_WMT_PATCH) pPatchBuf; + + cDataTime = patchHdr->ucDateTime; + u2HwVer = patchHdr->u2HwVer; + u2SwVer = patchHdr->u2SwVer; + u4PatchVer = patchHdr->u4PatchVer; + + cDataTime[15] = '\0'; + if (index == 0) { + WMT_INFO_FUNC("[Patch]BuiltTime=%s,HVer=0x%x,SVer=0x%x,PhVer=0x%04x,Platform=%c%c%c%c\n", + cDataTime, ((u2HwVer & 0x00ff) << 8) | ((u2HwVer & 0xff00) >> 8), + ((u2SwVer & 0x00ff) << 8) | ((u2SwVer & 0xff00) >> 8), + ((u4PatchVer & 0xff000000) >> 24) | ((u4PatchVer & 0x00ff0000) >> 16), + patchHdr->ucPLat[0], patchHdr->ucPLat[1], + patchHdr->ucPLat[2], patchHdr->ucPLat[3]); + } + osal_memcpy(&gp_soc_patch_info, patchHdr, osal_sizeof(WMT_PATCH)); + + /* remove patch header: + * |<-patch body: X Bytes (X=patchSize)--->| + */ + if (patchSize < sizeof(WMT_PATCH)) { + WMT_ERR_FUNC("error patch size\n"); + iRet = -1; + goto done; + } + patchSize -= sizeof(WMT_PATCH); + pPatchBuf += sizeof(WMT_PATCH); + + if (wmt_ic_ops_soc.options & OPT_PATCH_CHECKSUM) { + /* remove patch checksum: + * |<-patch checksum: 2Bytes->|<-patch body: X Bytes (X=patchSize)--->| + */ + pPatchBuf += BCNT_PATCH_BUF_CHECKSUM; + patchSize -= BCNT_PATCH_BUF_CHECKSUM; + } + + emiInfo = mtk_wcn_consys_soc_get_emi_phy_add(); + if (!emiInfo) { + WMT_ERR_FUNC("get emi info fail!\n"); + iRet = -1; + goto done; + } + + if (emiInfo->pda_dl_patch_flag) + iRet = mtk_wcn_soc_pda_patch_dwn(pPatchBuf, patchSize, addressByte); + else + iRet = mtk_wcn_soc_normal_patch_dwn(pPatchBuf, patchSize, addressByte); + + /* Set FW patch buildtime into EMI for debugging */ + if (emiInfo->emi_ram_mcu_buildtime_offset) { + patchBuildTimeAddr = ioremap_nocache(emiInfo->emi_ap_phy_addr + + emiInfo->emi_patch_mcu_buildtime_offset, PATCH_BUILD_TIME_SIZE); + if (patchBuildTimeAddr) { + osal_memcpy_toio(patchBuildTimeAddr, cDataTime, PATCH_BUILD_TIME_SIZE); + iounmap(patchBuildTimeAddr); + } else + WMT_ERR_FUNC("ioremap_nocache fail\n"); + } +done: + if (patchHdr != NULL) { + osal_free(patchHdr); + pPatchBuf = NULL; + patchHdr = NULL; + } + + /* WMT_CTRL_FREE_PATCH always return 0 */ + ctrlData.ctrlId = WMT_CTRL_FREE_PATCH; + ctrlData.au4CtrlData[0] = index + 1; + wmt_ctrl(&ctrlData); + + return iRet; +} + +#else +static INT32 mtk_wcn_soc_patch_dwn(VOID) +{ + INT32 iRet = -1; + P_WMT_PATCH patchHdr; + PUINT8 pbuf; + UINT32 patchSize; + UINT32 fragSeq; + UINT32 fragNum; + UINT16 fragSize = 0; + UINT16 cmdLen; + UINT32 offset; + UINT32 u4Res; + UINT8 evtBuf[8]; + PINT8 cDataTime = NULL; + /*PINT8 cPlat = NULL; */ + UINT16 u2HwVer = 0; + UINT16 u2SwVer = 0; + UINT32 u4PatchVer = 0; + UINT32 patchSizePerFrag = 0; + WMT_CTRL_DATA ctrlData; + + /*1.check hardware information */ + if (gp_soc_info == NULL) { + WMT_ERR_FUNC("null gp_soc_info!\n"); + return -1; + } + /* <2> search patch and read patch content */ + /* <2.1> search patch */ + ctrlData.ctrlId = WMT_CTRL_PATCH_SEARCH; + iRet = wmt_ctrl(&ctrlData); + if (iRet == 0) { + /* patch with correct Hw Ver Major Num found */ + ctrlData.ctrlId = WMT_CTRL_GET_PATCH_NAME; + ctrlData.au4CtrlData[0] = (UINT32) &gFullPatchName; + iRet = wmt_ctrl(&ctrlData); + + WMT_INFO_FUNC("valid patch found: (%s)\n", gFullPatchName); + /* <2.2> read patch content */ + ctrlData.ctrlId = WMT_CTRL_GET_PATCH; + ctrlData.au4CtrlData[0] = (UINT32) NULL; + ctrlData.au4CtrlData[1] = (UINT32) &gFullPatchName; + + } else { + iRet -= 1; + return iRet; + } + ctrlData.au4CtrlData[2] = (UINT32) &pbuf; + ctrlData.au4CtrlData[3] = (UINT32) &patchSize; + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + WMT_ERR_FUNC("wmt_core: WMT_CTRL_GET_PATCH fail:%d\n", iRet); + iRet -= 1; + goto done; + } + + /* |<-BCNT_PATCH_BUF_HEADROOM(8) bytes dummy allocated->|<-patch file->| */ + pbuf += BCNT_PATCH_BUF_HEADROOM; + /* patch file with header: + * |<-patch header: 28 Bytes->|<-patch body: X Bytes ----->| + */ + patchHdr = (P_WMT_PATCH) pbuf; + /* check patch file information */ + + cDataTime = patchHdr->ucDateTime; + u2HwVer = patchHdr->u2HwVer; + u2SwVer = patchHdr->u2SwVer; + u4PatchVer = patchHdr->u4PatchVer; + /*cPlat = &patchHdr->ucPLat[0]; */ + + cDataTime[15] = '\0'; + WMT_DBG_FUNC("===========================================\n"); + WMT_INFO_FUNC("[ConsysPatch]BuiltTime = %s, HVer = 0x%x, SVer = 0x%x, PhVer = 0x%04x,Platform = %c%c%c%c\n", + cDataTime, ((u2HwVer & 0x00ff) << 8) | ((u2HwVer & 0xff00) >> 8), + ((u2SwVer & 0x00ff) << 8) | ((u2SwVer & 0xff00) >> 8), + ((u4PatchVer & 0xff000000) >> 24) | ((u4PatchVer & 0x00ff0000) >> 16), + patchHdr->ucPLat[0], patchHdr->ucPLat[1], patchHdr->ucPLat[2], patchHdr->ucPLat[3]); + WMT_DBG_FUNC("[Consys Patch] Hw Ver = 0x%x\n", ((u2HwVer & 0x00ff) << 8) | ((u2HwVer & 0xff00) >> 8)); + WMT_DBG_FUNC("[Consys Patch] Sw Ver = 0x%x\n", ((u2SwVer & 0x00ff) << 8) | ((u2SwVer & 0xff00) >> 8)); + WMT_DBG_FUNC("[Consys Patch] Ph Ver = 0x%04x\n", + ((u4PatchVer & 0xff000000) >> 24) | ((u4PatchVer & 0x00ff0000) >> 16)); + WMT_DBG_FUNC("[Consys Patch] Platform = %c%c%c%c\n", patchHdr->ucPLat[0], patchHdr->ucPLat[1], + patchHdr->ucPLat[2], patchHdr->ucPLat[3]); + WMT_DBG_FUNC("===========================================\n"); + + /* remove patch header: + * |<-patch body: X Bytes (X=patchSize)--->| + */ + if (patchSize < sizeof(WMT_PATCH)) { + WMT_ERR_FUNC("error patch size\n"); + return -1; + } + 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); + mtk_wcn_stp_dbg_dump_package(); + iRet -= 1; + break; + } +#if CFG_CHECK_WMT_RESULT + if (osal_memcmp(evtBuf, WMT_PATCH_EVT, sizeof(WMT_PATCH_EVT)) != 0) { + WMT_ERR_FUNC("wmt_core: compare WMT_PATCH_EVT error rx(%d):[%02X,%02X,%02X,%02X,%02X]\n", + u4Res, + evtBuf[0], + evtBuf[1], + evtBuf[2], + evtBuf[3], + evtBuf[4]); + WMT_ERR_FUNC("wmt_core: exp(%d):[%02X,%02X,%02X,%02X,%02X]\n", + sizeof(WMT_PATCH_EVT), + WMT_PATCH_EVT[0], + WMT_PATCH_EVT[1], + WMT_PATCH_EVT[2], + WMT_PATCH_EVT[3], + WMT_PATCH_EVT[4]); + iRet -= 1; + break; + } +#endif + WMT_DBG_FUNC("wmt_core: read WMT_PATCH_EVT length(%d, %d) ok\n", sizeof(WMT_PATCH_EVT), u4Res); + offset += patchSizePerFrag; + ++fragSeq; + } + + WMT_WARN_FUNC("wmt_core: patch dwn:%d frag(%d, %d) %s\n", + iRet, fragSeq, fragSize, (!iRet && (fragSeq == fragNum)) ? "ok" : "fail"); + + if (fragSeq != fragNum) + iRet -= 1; +done: + /* WMT_CTRL_FREE_PATCH always return 0 */ + wmt_core_ctrl(WMT_CTRL_FREE_PATCH, NULL, NULL); + + return iRet; +} + +#endif + +INT32 mtk_wcn_soc_rom_patch_dwn(UINT32 ip_ver, UINT32 fw_ver) +{ + INT32 iRet = -1; + struct wmt_rom_patch *patchHdr = NULL; + PUINT8 pBuf = NULL; + PUINT8 pPatchBuf = NULL; + UINT32 patchSize; + UINT8 addressByte[4]; + PINT8 cDataTime = NULL; + UINT16 u2HwVer = 0; + UINT16 u2SwVer = 0; + UINT32 u4PatchType = 0; + UINT32 type; + UINT32 patchEmiOffset; + PUINT8 patchAddr; + UINT32 patchBuildTimeOffset = 0; + PUINT8 patchBuildTimeAddr; + WMT_CTRL_DATA ctrlData; + P_CONSYS_EMI_ADDR_INFO emiInfo; + + for (type = WMTDRV_TYPE_BT; type < WMTDRV_TYPE_ANT; type++) { + osal_memset(gFullPatchName, 0, osal_sizeof(gFullPatchName)); + + ctrlData.ctrlId = WMT_CTRL_GET_ROM_PATCH_INFO; + ctrlData.au4CtrlData[0] = type; + ctrlData.au4CtrlData[1] = (SIZE_T)&gFullPatchName; + ctrlData.au4CtrlData[2] = (SIZE_T)&addressByte; + ctrlData.au4CtrlData[3] = ip_ver; + ctrlData.au4CtrlData[4] = fw_ver; + iRet = wmt_ctrl(&ctrlData); + if (iRet > 0) { + WMT_INFO_FUNC("There is no need to download (%d) type patch!\n", type); + continue; + } else if (iRet < 0) { + WMT_ERR_FUNC("failed to get patch (type: %d, ret: %d)\n", type, iRet); + goto done; + } + + /* <2.2> read patch content */ + ctrlData.ctrlId = WMT_CTRL_GET_PATCH; + ctrlData.au4CtrlData[0] = (SIZE_T)NULL; + ctrlData.au4CtrlData[1] = (SIZE_T)&gFullPatchName; + ctrlData.au4CtrlData[2] = (SIZE_T)&pBuf; + ctrlData.au4CtrlData[3] = (SIZE_T)&patchSize; + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + WMT_ERR_FUNC("wmt_core: WMT_CTRL_GET_PATCH fail:%d\n", iRet); + iRet = -1; + goto done; + } + + /* |<-BCNT_PATCH_BUF_HEADROOM(8) bytes dummy allocated->|<-patch file->| + * patch file with header: + * |<-patch header: 32 Bytes->|<-patch body: X Bytes ----->| + */ + pPatchBuf = osal_malloc(patchSize); + if (pPatchBuf == NULL) { + WMT_ERR_FUNC("vmalloc pPatchBuf for patch download fail\n"); + iRet = -2; + goto done; + } + osal_memcpy(pPatchBuf, pBuf, patchSize); + /* check patch file information */ + patchHdr = (struct wmt_rom_patch *) pPatchBuf; + + cDataTime = patchHdr->ucDateTime; + u2HwVer = patchHdr->u2HwVer; + u2SwVer = patchHdr->u2SwVer; + u4PatchType = patchHdr->u4PatchType; + + cDataTime[15] = '\0'; + WMT_INFO_FUNC("[RomPatch]BTime=%s,HVer=0x%x,SVer=0x%x,Platform=%c%c%c%c\n,Type=%x\n", + cDataTime, + ((u2HwVer & 0x00ff) << 8) | ((u2HwVer & 0xff00) >> 8), + ((u2SwVer & 0x00ff) << 8) | ((u2SwVer & 0xff00) >> 8), + patchHdr->ucPLat[0], patchHdr->ucPLat[1], + patchHdr->ucPLat[2], patchHdr->ucPLat[3], + u4PatchType); + + /* remove patch header: + * |<-patch body: X Bytes (X=patchSize)--->| + */ + if (patchSize < sizeof(struct wmt_rom_patch)) { + WMT_ERR_FUNC("error patch size\n"); + iRet = -3; + goto done; + } + patchSize -= sizeof(struct wmt_rom_patch); + pPatchBuf += sizeof(struct wmt_rom_patch); + + patchEmiOffset = (addressByte[2] << 16) | (addressByte[1] << 8) | addressByte[0]; + + emiInfo = mtk_wcn_consys_soc_get_emi_phy_add(); + if (!emiInfo) { + WMT_ERR_FUNC("get emi info fail!\n"); + iRet = -4; + goto done; + } + + if (patchEmiOffset + patchSize < emiInfo->emi_size) { + WMT_INFO_FUNC("[Rom Patch] emiInfo: emi_ap_phy_addr=0x%x emi_size=%d emi_phy_addr=0x%x\n", + emiInfo->emi_ap_phy_addr, emiInfo->emi_size, emiInfo->emi_phy_addr); + WMT_INFO_FUNC("[Rom Patch]Name=%s,EmiOffset=0x%x,Size=0x%x\n", + gFullPatchName, patchEmiOffset, patchSize); + + if (type == WMTDRV_TYPE_WIFI) { + wmt_lib_mpu_lock_aquire(); + if (mtk_wcn_wlan_emi_mpu_set_protection) + (*mtk_wcn_wlan_emi_mpu_set_protection)(false); + } + + patchAddr = ioremap_nocache(emiInfo->emi_ap_phy_addr + patchEmiOffset, patchSize); + WMT_INFO_FUNC("physAddr=0x%x, size=%d virAddr=0x%p\n", + emiInfo->emi_ap_phy_addr + patchEmiOffset, patchSize, patchAddr); + if (patchAddr) { + osal_memcpy_toio(patchAddr, pPatchBuf, patchSize); + iounmap(patchAddr); + } else + WMT_ERR_FUNC("ioremap_nocache fail\n"); + + if (type == WMTDRV_TYPE_BT) + patchBuildTimeOffset = emiInfo->emi_ram_bt_buildtime_offset; + else if (type == WMTDRV_TYPE_WIFI) + patchBuildTimeOffset = emiInfo->emi_ram_wifi_buildtime_offset; + else if (type == WMTDRV_TYPE_WMT) + patchBuildTimeOffset = emiInfo->emi_ram_mcu_buildtime_offset; + /* Set ROM patch buildtime into EMI for debugging */ + if (patchBuildTimeOffset) { + patchBuildTimeAddr = ioremap_nocache(emiInfo->emi_ap_phy_addr + + patchBuildTimeOffset, PATCH_BUILD_TIME_SIZE); + if (patchBuildTimeAddr) { + osal_memcpy_toio(patchBuildTimeAddr, cDataTime, + PATCH_BUILD_TIME_SIZE); + iounmap(patchBuildTimeAddr); + } else + WMT_ERR_FUNC("ioremap_nocache fail\n"); + } + + if (type == WMTDRV_TYPE_WIFI) { + if (mtk_wcn_wlan_emi_mpu_set_protection) + (*mtk_wcn_wlan_emi_mpu_set_protection)(true); + wmt_lib_mpu_lock_release(); + } + } else + WMT_ERR_FUNC("The rom patch is too big to overflow on EMI\n"); + +done: + if (patchHdr != NULL) { + osal_free(patchHdr); + pPatchBuf = NULL; + patchHdr = NULL; + } + + /* WMT_CTRL_FREE_PATCH always return 0 */ + ctrlData.ctrlId = WMT_CTRL_FREE_PATCH; + ctrlData.au4CtrlData[0] = type; + wmt_ctrl(&ctrlData); + if (iRet) + break; + } + + return iRet; +} + + +VOID mtk_wcn_soc_restore_wifi_cal_result(VOID) +{ +#if CFG_CALIBRATION_BACKUP_RESTORE + P_CONSYS_EMI_ADDR_INFO emiInfo = mtk_wcn_consys_soc_get_emi_phy_add(); + PUINT8 wifiCalAddr = NULL; + + if (!emiInfo) { + WMT_ERR_FUNC("Get EMI info failed.\n"); + return; + } + + if (mtk_consys_is_calibration_backup_restore_support() == 0 || + mtk_wcn_stp_assert_flow_get() == 0) { + WMT_INFO_FUNC( + "Skip restore, chip id=%x mtk_wcn_stp_assert_flow_get()=%d\n", + wmt_ic_ops_soc.icId, mtk_wcn_stp_assert_flow_get()); + return; + } + /* Disable Wi-Fi MPU to touch Wi-Fi calibration data */ + if (mtk_wcn_wlan_emi_mpu_set_protection) + (*mtk_wcn_wlan_emi_mpu_set_protection)(false); + WMT_STEP_DO_ACTIONS_FUNC(STEP_TRIGGER_POINT_BEFORE_RESTORE_CAL_RESULT); + /* Write Wi-Fi data to EMI */ + if (gWiFiCalAddrOffset + gWiFiCalSize < emiInfo->emi_size) { + wifiCalAddr = ioremap_nocache(emiInfo->emi_ap_phy_addr + gWiFiCalAddrOffset, + gWiFiCalSize); + if (wifiCalAddr) { + osal_memcpy_toio(wifiCalAddr, gWiFiCalResult, gWiFiCalSize); + iounmap(wifiCalAddr); + WMT_STEP_DO_ACTIONS_FUNC(STEP_TRIGGER_POINT_AFTER_RESTORE_CAL_RESULT); + } else { + WMT_ERR_FUNC("ioremap_nocache fail\n"); + } + } + if (mtk_wcn_wlan_emi_mpu_set_protection) + (*mtk_wcn_wlan_emi_mpu_set_protection)(true); +#else + WMT_INFO_FUNC("Skip restore because it is not supported.\n"); +#endif +} + +#if CFG_CALIBRATION_BACKUP_RESTORE +/* + * To restore calibration data + * For BT, send by STP command. + * For Wi-Fi write to EMI directly. + * + * Return value: + * 0: restore success + * 1: recalibration happened. Caller need to re-get calibration data + * < 0: fail. Caller need to re-send calibration command. + */ +static INT32 mtk_wcn_soc_calibration_restore(void) +{ + INT32 iRet = 0; + PUINT8 evtBuf = NULL; + UINT32 u4Res; + UINT16 len = 0; + + /* Allocate event buffer */ + evtBuf = osal_malloc(CALIBRATION_BACKUP_RESTORE_BUFFER_SIZE); + if (evtBuf == NULL) { + WMT_ERR_FUNC("allocate event buffer failed\n"); + return -1; + } + + if ((gBTCalResultSize != 0 && gBTCalResult != NULL && + (gBTCalResultSize + sizeof(WMT_CORE_SEND_RF_CALIBRATION_CMD)) < CALIBRATION_BACKUP_RESTORE_BUFFER_SIZE) && + (gWiFiCalResult != NULL && gWiFiCalSize != 0 && gWiFiCalAddrOffset != 0)) { + WMT_INFO_FUNC("Send calibration data size=%d\n", gBTCalResultSize); + WMT_INFO_FUNC("Send calibration data start\n"); + /* Construct send calibration cmd for BT + * Format: 0x01 0x14 [ X+3 (2 bytes)] 0x02 + * [BT data len (2 bytes)] [BT data (X bytes)] + */ + /* clear buffer */ + osal_memset(&evtBuf[0], 0, CALIBRATION_BACKUP_RESTORE_BUFFER_SIZE); + /* copy cmd template */ + osal_memcpy( + &evtBuf[0], + WMT_CORE_SEND_RF_CALIBRATION_CMD, + sizeof(WMT_CORE_SEND_RF_CALIBRATION_CMD)); + /* Setup length to byte 2&3 */ + len = gBTCalResultSize + 3; + osal_memcpy(&evtBuf[2], &len, 2); + osal_memcpy(&evtBuf[5], &gBTCalResultSize, 2); + osal_memcpy(&evtBuf[7], gBTCalResult, gBTCalResultSize); + len = sizeof(WMT_CORE_SEND_RF_CALIBRATION_CMD) + gBTCalResultSize; + iRet = wmt_core_tx(evtBuf, len, &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || u4Res != len) { + WMT_ERR_FUNC("Send calibration data TX failed (%d), %d bytes writes, expect %d\n", + iRet, u4Res, len); + iRet = -4; + goto restore_end; + } + /* RX: 02 14 02 00 XX 02 + * XX means status + * 0: OK + * 1: recalibration happened + */ + iRet = wmt_core_rx(evtBuf, CALIBRATION_BACKUP_RESTORE_BUFFER_SIZE, &u4Res); + WMT_INFO_FUNC("Send calibration data end\n"); + if (iRet || u4Res != sizeof(WMT_CORE_SEND_RF_CALIBRATION_EVT_OK)) { + WMT_ERR_FUNC("Send calibration data event failed(%d), %d bytes get, expect %lu\n", + iRet, u4Res, sizeof(WMT_CORE_SEND_RF_CALIBRATION_EVT_OK)); + iRet = -5; + goto restore_end; + } + /* Check return */ + if (osal_memcmp(&evtBuf[0], WMT_CORE_SEND_RF_CALIBRATION_EVT_OK, + sizeof(WMT_CORE_SEND_RF_CALIBRATION_EVT_OK)) == 0) { + WMT_INFO_FUNC("Send calibration data OK.\n"); + iRet = 0; + } else if (osal_memcmp(&evtBuf[0], WMT_CORE_SEND_RF_CALIBRATION_EVT_RECAL, + sizeof(WMT_CORE_SEND_RF_CALIBRATION_EVT_RECAL)) == 0) { + WMT_INFO_FUNC("Recalibration happened. Re-get calibration data\n"); + iRet = 1; + goto restore_end; + } else { + /* Do calibration */ + WMT_ERR_FUNC("Send calibration event error. 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x\n", + evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], evtBuf[5]); + iRet = -5; + goto restore_end; + } + } else { + WMT_ERR_FUNC("Did not restore calibration data. Buf=0x%p, size=%d\n", + gBTCalResult, gBTCalResultSize); + iRet = -6; + goto restore_end; + } + +restore_end: + if (mtk_wcn_wlan_emi_mpu_set_protection) + (*mtk_wcn_wlan_emi_mpu_set_protection)(false); + WMT_STEP_DO_ACTIONS_FUNC(STEP_TRIGGER_POINT_AFTER_RESTORE_CAL_CMD); + if (mtk_wcn_wlan_emi_mpu_set_protection) + (*mtk_wcn_wlan_emi_mpu_set_protection)(true); + osal_free(evtBuf); + return iRet; +} + +/* + * To backup calibration data + * For BT, get data by STP command. + * For Wi-Fi, get EMI offset and length from STP command and then + * backup data from EMI + * + * Return value: + * 0: backup success + * < 0: fail + */ +static INT32 mtk_wcn_soc_calibration_backup(void) +{ + INT32 iRet = 0; + PUINT8 evtBuf; + UINT32 u4Res; + UINT16 len = 0; + P_CONSYS_EMI_ADDR_INFO emiInfo = mtk_wcn_consys_soc_get_emi_phy_add(); + UINT32 wifiOffset = 0; + UINT32 wifiLen = 0; + void __iomem *virWiFiAddrBase; + + /* Allocate RX event buffer */ + evtBuf = osal_malloc(CALIBRATION_BACKUP_RESTORE_BUFFER_SIZE); + if (evtBuf == NULL) { + WMT_ERR_FUNC("Allocate event buffer failed\n"); + return -1; + } + /* Get calibration data TX */ + iRet = wmt_core_tx(WMT_CORE_GET_RF_CALIBRATION_CMD, + sizeof(WMT_CORE_GET_RF_CALIBRATION_CMD), + &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || u4Res != sizeof(WMT_CORE_GET_RF_CALIBRATION_CMD)) { + WMT_ERR_FUNC("Write get calibration cmd failed(%d), exp: %lu but write %d\n", + iRet, sizeof(WMT_CORE_GET_RF_CALIBRATION_CMD), u4Res); + goto get_calibration_fail; + } + osal_memset(&evtBuf[0], 0, CALIBRATION_BACKUP_RESTORE_BUFFER_SIZE); + iRet = wmt_core_rx(evtBuf, CALIBRATION_BACKUP_RESTORE_BUFFER_SIZE, &u4Res); + /* RX expected format: + * 02 14 [X+14 (2 bytes)] 00 03 + * [BT size = X (2 bytes)] [BT Cal. Data (X bytes)] + * [WiFi Size = 8 (2 bytes)] [WiFi Offset (4 bytes)] [WiFi len(4 bytes)] + */ + if (iRet || u4Res < 8) { + WMT_ERR_FUNC("Get calibration event failed(%d), get %d bytes\n", iRet, u4Res); + goto get_calibration_fail; + } + /* Check data validaness */ + if (evtBuf[0] != 0x02 || evtBuf[1] != 0x14 || + evtBuf[4] != 0x00 || evtBuf[5] != 0x03) { + WMT_ERR_FUNC("Get calibration event error. 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x\n", + evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], evtBuf[5]); + goto get_calibration_fail; + } + /* Get data success, backup it. + * Data size is not the same as previous, realloc memory + */ + osal_memcpy(&len, &evtBuf[6], 2); + if (len != gBTCalResultSize) { + gBTCalResultSize = len; + if (gBTCalResult != NULL) { + osal_free(gBTCalResult); + gBTCalResult = NULL; + } + } + if (gBTCalResult == NULL) + gBTCalResult = osal_malloc(gBTCalResultSize); + if (gBTCalResult == NULL) { + WMT_ERR_FUNC("Allocate BT calibration buffer failed.\n"); + goto get_calibration_fail; + } + osal_memcpy(gBTCalResult, &evtBuf[8], gBTCalResultSize); + /* Get Wi-Fi info */ + osal_memcpy(&wifiOffset, &evtBuf[10 + gBTCalResultSize], 4); + osal_memcpy(&wifiLen, &evtBuf[14 + gBTCalResultSize], 4); + if (wifiLen != gWiFiCalSize) { + gWiFiCalSize = wifiLen; + if (gWiFiCalResult != NULL) { + osal_free(gWiFiCalResult); + gWiFiCalResult = NULL; + } + } + if (gWiFiCalResult == NULL) + gWiFiCalResult = osal_malloc(gWiFiCalSize); + if (gWiFiCalResult == NULL) { + WMT_ERR_FUNC("Allocate Wi-Fi calibration buffer failed.\n"); + goto get_calibration_fail; + } + /* Start to backup Wi-Fi data */ + if (!emiInfo) { + WMT_ERR_FUNC("get emi info fail!\n"); + goto get_calibration_fail; + } + /* Before copy, disable Wi-Fi MPU to access EMI */ + if (mtk_wcn_wlan_emi_mpu_set_protection) + (*mtk_wcn_wlan_emi_mpu_set_protection)(false); + WMT_STEP_DO_ACTIONS_FUNC( + STEP_TRIGGER_POINT_POWER_ON_AFTER_BT_WIFI_CALIBRATION); + gWiFiCalAddrOffset = wifiOffset; + virWiFiAddrBase = ioremap_nocache( + emiInfo->emi_ap_phy_addr + gWiFiCalAddrOffset, + gWiFiCalSize); + if (virWiFiAddrBase) { + osal_memcpy_fromio(gWiFiCalResult, virWiFiAddrBase, gWiFiCalSize); + iounmap(virWiFiAddrBase); + } else { + WMT_ERR_FUNC("Remap Wi-Fi EMI fail: offset=%d size=%d\n", + gWiFiCalAddrOffset, gWiFiCalSize); + goto get_calibration_fail; + } + /* Enable Wi-Fi MPU after finished. */ + if (mtk_wcn_wlan_emi_mpu_set_protection) + (*mtk_wcn_wlan_emi_mpu_set_protection)(true); + WMT_INFO_FUNC("gBTCalResultSize=%d gWiFiCalResult=0x%p gWiFiCalSize=%d gWiFiCalAddrOffset=0x%x\n", + gBTCalResultSize, + gWiFiCalResult, + gWiFiCalSize, + gWiFiCalAddrOffset); + osal_free(evtBuf); + return 0; +get_calibration_fail: + WMT_ERR_FUNC("Get calibration failed.\n"); + if (emiInfo) { + WMT_ERR_FUNC("emiInfo: emi_ap_phy_addr=0x%x emi_size=%d emi_phy_addr=0x%x\n", + emiInfo->emi_ap_phy_addr, + emiInfo->emi_size, + emiInfo->emi_phy_addr); + } + WMT_ERR_FUNC("gBTCalResultSize=%d gWiFiCalResult=0x%p gWiFiCalSize=%d gWiFiCalAddrOffset=0x%x\n", + gBTCalResultSize, gWiFiCalResult, + gWiFiCalSize, gWiFiCalAddrOffset); + if (gBTCalResult != NULL) { + osal_free(gBTCalResult); + gBTCalResult = NULL; + } + gBTCalResultSize = 0; + if (gWiFiCalResult != NULL) { + osal_free(gWiFiCalResult); + gWiFiCalResult = NULL; + } + gWiFiCalSize = 0; + gWiFiCalAddrOffset = 0; + /* Enable Wi-Fi MPU after finished. */ + if (mtk_wcn_wlan_emi_mpu_set_protection) + (*mtk_wcn_wlan_emi_mpu_set_protection)(true); + osal_free(evtBuf); + return -1; +} +#endif + +static INT32 mtk_wcn_soc_do_calibration(void) +{ + INT32 iRet = 0; + +#if CFG_CALIBRATION_BACKUP_RESTORE + /* When chip reset is caused by assert, skip calibration. + * Restore old data. + */ + if (mtk_consys_is_calibration_backup_restore_support() == 0 || + mtk_wcn_stp_assert_flow_get() == 0) { + WMT_INFO_FUNC( + "Skip restore, chip id=%x mtk_wcn_stp_assert_flow_get()=%d\n", + wmt_ic_ops_soc.icId, mtk_wcn_stp_assert_flow_get()); + goto do_calibration; + } + + iRet = mtk_wcn_soc_calibration_restore(); + if (iRet == 0) { + WMT_INFO_FUNC("Restore success\n"); + return 0; + } else if (iRet == 1) { + WMT_INFO_FUNC("Recal happened. Re-get calibration data.\n"); + goto get_calibration; + } else + /* For all other case, re-cali. */ + WMT_ERR_FUNC("Re-cal because restore fail(%d)\n", iRet); + +do_calibration: +#endif /* CFG_CALIBRATION_BACKUP_RESTORE */ + /* Do calibration */ + WMT_INFO_FUNC("Calibration start\n"); + iRet = wmt_core_init_script( + calibration_table, + osal_array_size(calibration_table)); + WMT_INFO_FUNC("Calibration end\n"); + if (iRet) { + #if CFG_CALIBRATION_BACKUP_RESTORE + /* Calibration failed. Clear backup data. */ + if (gBTCalResult != NULL) { + osal_free(gBTCalResult); + gBTCalResult = NULL; + } + gBTCalResultSize = 0; + if (gWiFiCalResult != NULL) { + osal_free(gWiFiCalResult); + gWiFiCalResult = NULL; + } + gWiFiCalSize = 0; + gWiFiCalAddrOffset = 0; + #endif + WMT_ERR_FUNC("do calibration failed (%d)\n", iRet); + return -1; + } + +#if CFG_CALIBRATION_BACKUP_RESTORE + if (mtk_consys_is_calibration_backup_restore_support() == 0) + return 0; + +get_calibration: + iRet = mtk_wcn_soc_calibration_backup(); + /* Backup process should not influence power on sequence. + * Hence, even it return error, just record it and + * report calibration success. + */ + if (iRet == 0) + WMT_INFO_FUNC("Backup success\n"); + else + WMT_ERR_FUNC("Backup failed(%d)\n", iRet); +#endif + return 0; +} + +static INT32 mtk_wcn_soc_calibration(void) +{ + INT32 iRet = -1; + INT32 iCalRet = -1; + unsigned long ctrlPa1; + unsigned long ctrlPa2; + + /* Turn on BT/Wi-Fi */ + ctrlPa1 = BT_PALDO; + ctrlPa2 = PALDO_ON; + iRet = wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + ctrlPa1 = WIFI_PALDO; + ctrlPa2 = PALDO_ON; + iRet = wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + + WMT_INFO_FUNC("mtk_wcn_soc_do_calibration start\n"); + iCalRet = mtk_wcn_soc_do_calibration(); + WMT_INFO_FUNC("mtk_wcn_soc_do_calibration end\n"); + + /* Turn off BT/Wi-Fi */ + ctrlPa1 = BT_PALDO; + ctrlPa2 = PALDO_OFF; + iRet = wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + ctrlPa1 = WIFI_PALDO; + ctrlPa2 = PALDO_OFF; + iRet = wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + + if (iCalRet) { + /* pwrap_read(0x0210,&ctrlPa1); */ + /* pwrap_read(0x0212,&ctrlPa2); */ + /* WMT_ERR_FUNC("power status: 210:(%d),212:(%d)!\n", ctrlPa1, ctrlPa2); */ + WMT_ERR_FUNC("calibration_table fail(%d)\n", iCalRet); + return -1; + } + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_lib.c b/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_lib.c new file mode 100644 index 0000000000000..13ebe4c8ad096 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/core/wmt_lib.c @@ -0,0 +1,3382 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/******************************************************************************* +* 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 "wmt_detect.h" +#include "mtk_wcn_consys_hw.h" + +#include "stp_core.h" +#include "btm_core.h" +#include "psm_core.h" +#include "stp_sdio.h" +#include "stp_dbg.h" +#include "wmt_step.h" +#include +#include + +/******************************************************************************* +* 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: enum 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, + [CMB_STUB_AIF_4] = WMT_IC_PIN_STATE_MAX, +}; + +#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; +static PF_WMT_SDIO_DEBUG sdio_reg_rw; +#endif +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT +static PF_WMT_SDIO_DEEP_SLEEP sdio_deep_sleep_flag_set; +#endif + + +#define WMT_STP_CPUPCR_BUF_SIZE 73728 +static UINT8 g_cpupcr_buf[WMT_STP_CPUPCR_BUF_SIZE] = { 0 }; +static UINT32 g_quick_sleep_ctrl = 1; +static UINT32 g_fw_patch_update_rst; +static u64 fw_patch_rst_time; + +#define ASSERT_KEYWORD_LENGTH 20 +struct assert_work_st { + struct work_struct work; + ENUM_WMTDRV_TYPE_T type; + UINT32 reason; + UINT8 keyword[ASSERT_KEYWORD_LENGTH]; +}; + +static struct assert_work_st wmt_assert_work; + +static INT32 g_bt_no_acl_link = 1; +static INT32 g_bt_no_br_acl_link = 1; + +#define CONSYS_MET_WAIT (1000*10) /* ms */ +#define MET_DUMP_MAX_NUM (1) +#define MET_DUMP_SIZE (4*MET_DUMP_MAX_NUM) +#define EMI_MET_READ_OFFSET 0x0 +#define EMI_MET_WRITE_OFFSET 0x4 +#define EMI_MET_DATA_OFFSET 0x8 +#define FW_PATCH_UPDATE_RST_DURATION 180 /* 180 seconds */ + +#define WMT_LIB_DMP_CONSYS_MAX_TIMES 10 + +/******************************************************************************* +* 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 met_thread(PVOID pvData); +static INT32 wmtd_worker_thread(PVOID pvData); + +static INT32 wmt_lib_pin_ctrl(WMT_IC_PIN_ID id, WMT_IC_PIN_STATE stat, UINT32 flag); +static MTK_WCN_BOOL wmt_lib_hw_state_show(VOID); +static VOID wmt_lib_utc_sync_timeout_handler(timer_handler_arg arg); +static VOID wmt_lib_utc_sync_worker_handler(struct work_struct *work); +static VOID wmt_lib_wmtd_worker_thread_timeout_handler(timer_handler_arg); +static VOID wmt_lib_wmtd_worker_thread_work_handler(struct work_struct *work); + +static VOID wmt_lib_assert_work_cb(struct work_struct *work); +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +INT32 __weak mtk_wcn_consys_stp_btif_dpidle_ctrl(UINT32 en_flag) +{ + WMT_ERR_FUNC("mtk_wcn_consys_stp_btif_dpidle_ctrl is not define!!!\n"); + + return 0; +} + +INT32 wmt_lib_wlan_lock_aquire(VOID) +{ + return osal_lock_sleepable_lock(&gDevWmt.wlan_lock); +} + +VOID wmt_lib_wlan_lock_release(VOID) +{ + osal_unlock_sleepable_lock(&gDevWmt.wlan_lock); +} + +INT32 wmt_lib_wlan_lock_trylock(VOID) +{ + return osal_trylock_sleepable_lock(&gDevWmt.wlan_lock); +} + +INT32 wmt_lib_idc_lock_aquire(VOID) +{ + return osal_lock_sleepable_lock(&gDevWmt.idc_lock); +} + +VOID wmt_lib_idc_lock_release(VOID) +{ + osal_unlock_sleepable_lock(&gDevWmt.idc_lock); +} + +INT32 wmt_lib_psm_lock_aquire(VOID) +{ + return osal_lock_sleepable_lock(&gDevWmt.psm_lock); +} + +void wmt_lib_psm_lock_release(VOID) +{ + osal_unlock_sleepable_lock(&gDevWmt.psm_lock); +} + +INT32 wmt_lib_psm_lock_trylock(VOID) +{ + return osal_trylock_sleepable_lock(&gDevWmt.psm_lock); +} + +INT32 wmt_lib_assert_lock_aquire(VOID) +{ + return osal_lock_sleepable_lock(&gDevWmt.assert_lock); +} + +VOID wmt_lib_assert_lock_release(VOID) +{ + osal_unlock_sleepable_lock(&gDevWmt.assert_lock); +} + +INT32 wmt_lib_assert_lock_trylock(VOID) +{ + return osal_trylock_sleepable_lock(&gDevWmt.assert_lock); +} + +INT32 wmt_lib_mpu_lock_aquire(VOID) +{ + return osal_lock_sleepable_lock(&gDevWmt.mpu_lock); +} + +VOID wmt_lib_mpu_lock_release(VOID) +{ + osal_unlock_sleepable_lock(&gDevWmt.mpu_lock); +} + +INT32 wmt_lib_power_lock_aquire(VOID) +{ + return osal_lock_sleepable_lock(&gDevWmt.power_lock); +} + +VOID wmt_lib_power_lock_release(VOID) +{ + osal_unlock_sleepable_lock(&gDevWmt.power_lock); +} + +INT32 wmt_lib_power_lock_trylock(VOID) +{ + return osal_trylock_sleepable_lock(&gDevWmt.power_lock); +} + +INT32 DISABLE_PSM_MONITOR(VOID) +{ + INT32 ret = 0; + PUINT8 pbuf = NULL; + INT32 len = 0; + + /* osal_lock_sleepable_lock(&gDevWmt.psm_lock); */ + ret = wmt_lib_psm_lock_aquire(); + if (ret) { + WMT_ERR_FUNC("--->lock psm_lock failed, ret=%d\n", ret); + return ret; + } +#if CFG_WMT_PS_SUPPORT + ret = wmt_lib_ps_disable(); + if (ret) { + WMT_ERR_FUNC("wmt_lib_ps_disable fail, ret=%d\n", ret); + wmt_lib_psm_lock_release(); + if (mtk_wcn_stp_coredump_start_get() == 0 && + chip_reset_only == 0 && + mtk_wcn_stp_get_wmt_trg_assert() == 0) { + pbuf = "wmt_lib_ps_disable fail, just collect SYS_FTRACE to DB"; + len = osal_strlen(pbuf); + stp_dbg_trigger_collect_ftrace(pbuf, len); + wmt_lib_trigger_reset(); + } + } +#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 pThread; + P_OSAL_THREAD pWorkerThread; + ENUM_WMT_CHIP_TYPE chip_type; + + /* create->init->start */ + /* 1. create: static allocation with zero initialization */ + pDevWmt = &gDevWmt; + osal_memset(&gDevWmt, 0, sizeof(gDevWmt)); + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) { + iRet = wmt_conf_read_file(); + if (iRet) { + WMT_ERR_FUNC("read wmt config file fail(%d)\n", iRet); + return -1; + } + } + osal_op_history_init(&pDevWmt->wmtd_op_history, 16); + osal_op_history_init(&pDevWmt->worker_op_history, 8); + + pThread = &gDevWmt.thread; + + /* Create mtk_wmtd thread */ + osal_strncpy(pThread->threadName, "mtk_wmtd", sizeof(pThread->threadName)); + pThread->pThreadData = (PVOID) pDevWmt; + pThread->pThreadFunc = (PVOID) wmtd_thread; + iRet = osal_thread_create(pThread); + if (iRet) { + WMT_ERR_FUNC("osal_thread_create(0x%p) fail(%d)\n", pThread, iRet); + return -2; + } + + /* create worker timer */ + gDevWmt.worker_timer.timeoutHandler = wmt_lib_wmtd_worker_thread_timeout_handler; + gDevWmt.worker_timer.timeroutHandlerData = 0; + osal_timer_create(&gDevWmt.worker_timer); + pWorkerThread = &gDevWmt.worker_thread; + INIT_WORK(&pDevWmt->wmtd_worker_thread_work, wmt_lib_wmtd_worker_thread_work_handler); + + /* Create wmtd_worker thread */ + osal_strncpy(pWorkerThread->threadName, "mtk_wmtd_worker", sizeof(pWorkerThread->threadName)); + pWorkerThread->pThreadData = (PVOID) pDevWmt; + pWorkerThread->pThreadFunc = (PVOID) wmtd_worker_thread; + iRet = osal_thread_create(pWorkerThread); + if (iRet) { + WMT_ERR_FUNC("osal_thread_create(0x%p) fail(%d)\n", pWorkerThread, iRet); + return -2; + } + + /* init timer */ + pDevWmt->utc_sync_timer.timeoutHandler = wmt_lib_utc_sync_timeout_handler; + osal_timer_create(&pDevWmt->utc_sync_timer); + osal_timer_start(&pDevWmt->utc_sync_timer, UTC_SYNC_TIME); + INIT_WORK(&pDevWmt->utcSyncWorker, wmt_lib_utc_sync_worker_handler); + + /* 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_event_init(&pDevWmt->rWmtdWorkerWq); + osal_sleepable_lock_init(&pDevWmt->psm_lock); + osal_sleepable_lock_init(&pDevWmt->idc_lock); + osal_sleepable_lock_init(&pDevWmt->wlan_lock); + osal_sleepable_lock_init(&pDevWmt->assert_lock); + osal_sleepable_lock_init(&pDevWmt->mpu_lock); + osal_sleepable_lock_init(&pDevWmt->power_lock); + osal_sleepable_lock_init(&pDevWmt->rActiveOpQ.sLock); + osal_sleepable_lock_init(&pDevWmt->rWorkerOpQ.sLock); + osal_sleepable_lock_init(&pDevWmt->rFreeOpQ.sLock); + pDevWmt->state.data = 0; + + atomic_set(&pDevWmt->state_dmp_req.version, 0); + for (i = 0; i < WMT_LIB_DMP_SLOT; i++) + osal_sleepable_lock_init(&(pDevWmt->state_dmp_req.consys_ops[i].lock)); + + /* Initialize op queue */ + RB_INIT(&pDevWmt->rFreeOpQ, WMT_OP_BUF_SIZE); + RB_INIT(&pDevWmt->rActiveOpQ, WMT_OP_BUF_SIZE); + RB_INIT(&pDevWmt->rWorkerOpQ, WMT_OP_BUF_SIZE); + /* Put all to free Q */ + for (i = 0; i < WMT_OP_BUF_SIZE; i++) { + osal_signal_init(&(pDevWmt->arQue[i].signal)); + wmt_lib_put_op(&pDevWmt->rFreeOpQ, &(pDevWmt->arQue[i])); + } + + /* initialize stp resources */ + osal_event_init(&pDevWmt->rWmtRxWq); + + /*function driver callback */ + for (i = 0; i < WMTDRV_TYPE_WIFI; i++) + pDevWmt->rFdrvCb.fDrvRst[i] = NULL; + + pDevWmt->hw_ver = WMTHWVER_MAX; + WMT_DBG_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 (gDevWmt.rWmtGenConf.cfgExist != 0) { + 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, gDevWmt.rWmtGenConf.co_clock_flag & 0x0f); + } else { + WMT_ERR_FUNC("no pwr on seq and clk par found\n"); + iRet = wmt_plat_init(NULL, 0); + } + chip_type = wmt_detect_get_chip_type(); + if (chip_type == WMT_CHIP_TYPE_SOC) + gDevWmt.rWmtGenConf.co_clock_flag = wmt_plat_soc_co_clock_flag_get(); + + if (iRet) { + WMT_ERR_FUNC("wmt_plat_init() fail(%d)\n", iRet); + return -3; + } + +#if CFG_WMT_PS_SUPPORT + iRet = wmt_lib_ps_init(); + if (iRet) { + WMT_ERR_FUNC("wmt_lib_ps_init() fail(%d)\n", iRet); + return -4; + } +#endif + + /* 3. start: start running mtk_wmtd */ + iRet = osal_thread_run(pThread); + if (iRet) { + WMT_ERR_FUNC("osal_thread_run(wmtd 0x%p) fail(%d)\n", pThread, iRet); + return -5; + } + + iRet = osal_thread_run(pWorkerThread); + if (iRet) { + WMT_ERR_FUNC("osal_thread_run(worker 0x%p) fail(%d)\n", pWorkerThread, iRet); + return -5; + } + /*4. register irq callback to WMT-PLAT */ + wmt_plat_irq_cb_reg(wmt_lib_ps_irq_cb); + /*5. register audio if control callback to WMT-PLAT */ + wmt_plat_aif_cb_reg(wmt_lib_set_aif); + /*6. register function control callback to WMT-PLAT */ + wmt_plat_func_ctrl_cb_reg(mtk_wcn_wmt_func_ctrl_for_plat); + + wmt_plat_deep_idle_ctrl_cb_reg(mtk_wcn_consys_stp_btif_dpidle_ctrl); + /*7 reset gps/bt state */ + + mtk_wcn_wmt_system_state_reset(); + +#ifndef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + mtk_wcn_wmt_exp_init(); +#endif + +#if CFG_WMT_LTE_COEX_HANDLING + wmt_idc_init(); +#endif + + INIT_WORK(&(wmt_assert_work.work), wmt_lib_assert_work_cb); + + WMT_DBG_FUNC("init success\n"); + return 0; +} + + +INT32 wmt_lib_deinit(VOID) +{ + INT32 iRet; + P_DEV_WMT pDevWmt; + P_OSAL_THREAD pThread; + P_OSAL_THREAD pWorkerThread; + INT32 i; + INT32 iResult; + struct vendor_patch_table *table = &(gDevWmt.patch_table); + + pDevWmt = &gDevWmt; + pThread = &gDevWmt.thread; + pWorkerThread = &gDevWmt.worker_thread; + iResult = 0; + + /* stop->deinit->destroy */ + + /* 1. stop: stop running mtk_wmtd */ + iRet = osal_thread_stop(pThread); + if (iRet) { + WMT_ERR_FUNC("osal_thread_stop(0x%p) fail(%d)\n", pThread, iRet); + iResult += 1; + } + + iRet = osal_thread_stop(pWorkerThread); + if (iRet) { + WMT_ERR_FUNC("osal_thread_stop(0x%p) fail(%d)\n", pWorkerThread, 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->rWorkerOpQ.sLock); + osal_sleepable_lock_deinit(&pDevWmt->power_lock); + osal_sleepable_lock_deinit(&pDevWmt->mpu_lock); + osal_sleepable_lock_deinit(&pDevWmt->idc_lock); + osal_sleepable_lock_deinit(&pDevWmt->wlan_lock); + osal_sleepable_lock_deinit(&pDevWmt->assert_lock); + osal_sleepable_lock_deinit(&pDevWmt->psm_lock); + + for (i = 0; i < WMT_LIB_DMP_SLOT; i++) + osal_sleepable_lock_deinit(&(pDevWmt->state_dmp_req.consys_ops[i].lock)); + + osal_event_deinit(&pDevWmt->rWmtdWq); + osal_event_deinit(&pDevWmt->rWmtdWorkerWq); + + for (i = 0; i < WMTDRV_TYPE_ANT; i++) { + kfree(pDevWmt->pWmtRomPatchInfo[i]); + pDevWmt->pWmtRomPatchInfo[i] = NULL; + } + + iRet = wmt_core_deinit(); + if (iRet) { + WMT_ERR_FUNC("wmt_core_deinit fail(%d)\n", iRet); + iResult += 8; + } + + /* 3. destroy */ + iRet = osal_thread_destroy(pThread); + if (iRet) { + WMT_ERR_FUNC("osal_thread_stop(0x%p) fail(%d)\n", pThread, iRet); + iResult += 16; + } + + iRet = osal_thread_destroy(pWorkerThread); + if (iRet) { + WMT_ERR_FUNC("osal_thread_stop(0x%p) fail(%d)\n", pWorkerThread, iRet); + iResult += 32; + } + + iRet = wmt_conf_deinit(); + if (iRet) { + WMT_ERR_FUNC("wmt_conf_deinit fail(%d)\n", iRet); + iResult += 64; + } + + osal_memset(&gDevWmt, 0, sizeof(gDevWmt)); +#if 0 +#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + mtk_wcn_wmt_exp_deinit(); +#endif +#endif + +#if CFG_WMT_LTE_COEX_HANDLING + wmt_idc_deinit(); +#endif + + if (table->active_version != NULL) { + for (i = 0; i < table->num; i++) { + if (table->active_version[i]) + osal_free(table->active_version[i]); + } + osal_free(table->active_version); + table->active_version = NULL; + } + + WMT_STEP_DEINIT_FUNC(); + + return iResult; +} + +VOID wmt_lib_flush_rx(VOID) +{ + mtk_wcn_stp_flush_rx_queue(WMT_TASK_INDX); +} + +INT32 wmt_lib_trigger_cmd_signal(INT32 result) +{ + P_OSAL_SIGNAL pSignal = &gDevWmt.cmdResp; + + gDevWmt.cmdResult = result; + osal_raise_signal(pSignal); + WMT_DBG_FUNC("wakeup cmdResp\n"); + return 0; +} + +P_OSAL_EVENT wmt_lib_get_cmd_event(VOID) +{ + return &gDevWmt.cmdReq; +} + +INT32 wmt_lib_set_patch_name(PUINT8 cPatchName) +{ + osal_strncpy(gDevWmt.cPatchName, cPatchName, NAME_MAX); + return 0; +} + +INT32 wmt_lib_set_uart_name(PINT8 cUartName) +{ +#if WMT_PLAT_ALPS + + WMT_DBG_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_DBG_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; + switch (val) { + case STP_UART_FULL: + 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); + wmt_plat_set_comm_if_type(STP_UART_IF_TX); + break; + case STP_SDIO: + pHif->hifType = WMT_HIF_SDIO; + mtk_wcn_stp_set_if_tx_type(STP_SDIO_IF_TX); + wmt_plat_set_comm_if_type(STP_SDIO_IF_TX); + break; + case STP_BTIF_FULL: + pHif->hifType = WMT_HIF_BTIF; + mtk_wcn_stp_set_if_tx_type(STP_BTIF_IF_TX); + break; + default: + WMT_WARN_FUNC("invalid stp mode: %lu %u\n", hifconf, val); + return -1; + } + + val = (hifconf & 0xF0) >> 4; + if (val == WMT_FM_COMM) { + pHif->au4StrapConf[0] = WMT_FM_COMM; + } else if (val == WMT_FM_I2C) { + pHif->au4StrapConf[0] = WMT_FM_I2C; + } else { + WMT_WARN_FUNC("invalid fm mode: %u\n", val); + return -2; + } + + WMT_DBG_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; +} + +PUINT8 wmt_lib_get_cmd(VOID) +{ + if (osal_test_and_clear_bit(WMT_STAT_CMD, &gDevWmt.state)) + return gDevWmt.cCmd; + + return NULL; +} + +MTK_WCN_BOOL wmt_lib_get_cmd_status(VOID) +{ + return osal_test_bit(WMT_STAT_CMD, &gDevWmt.state) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE; +} + +MTK_WCN_BOOL wmt_lib_stp_is_btif_fullset_mode(VOID) +{ + return mtk_wcn_stp_is_btif_fullset_mode(); +} + +#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 (state == 0) { + wmt_lib_ps_disable(); + gPsEnable = 0; + } else { + gPsEnable = 1; + wmt_lib_ps_enable(); + } + return 0; +} + + +INT32 wmt_lib_ps_enable(VOID) +{ + if (gPsEnable) + mtk_wcn_stp_psm_enable(gPsIdleTime); + + return 0; +} + +INT32 wmt_lib_ps_disable(VOID) +{ + if (gPsEnable) + return mtk_wcn_stp_psm_disable(); + + return 0; +} + +INT32 wmt_lib_ps_init(VOID) +{ + /* mtk_wcn_stp_psm_register_wmt_cb(wmt_lib_ps_stp_cb); */ + return 0; +} + +INT32 wmt_lib_ps_deinit(VOID) +{ + /* mtk_wcn_stp_psm_unregister_wmt_cb(); */ + return 0; +} + +static MTK_WCN_BOOL wmt_lib_ps_action(MTKSTP_PSM_ACTION_T action) +{ + P_OSAL_OP lxop; + MTK_WCN_BOOL bRet; + UINT32 u4Wait; + P_OSAL_SIGNAL pSignal; + + lxop = wmt_lib_get_free_op(); + if (!lxop) { + WMT_DBG_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + + pSignal = &lxop->signal; + pSignal->timeoutValue = 0; + lxop->op.opId = WMT_OPID_PWR_SV; + lxop->op.au4OpData[0] = action; + lxop->op.au4OpData[1] = (SIZE_T) mtk_wcn_stp_psm_notify_stp; + u4Wait = 0; + bRet = wmt_lib_put_act_op(lxop); + return bRet; +} + +#if CFG_WMT_LTE_COEX_HANDLING +MTK_WCN_BOOL wmt_lib_handle_idc_msg(conn_md_ipc_ilm_t *idc_infor) +{ + P_OSAL_OP lxop; + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + P_OSAL_SIGNAL pSignal; + INT32 ret = 0; + UINT16 msg_len = 0; + +#if CFG_WMT_LTE_ENABLE_MSGID_MAPPING + MTK_WCN_BOOL unknown_msgid = MTK_WCN_BOOL_FALSE; +#endif + WMT_DBG_FUNC("idc_infor from conn_md is 0x%p\n", idc_infor); + + ret = wmt_lib_idc_lock_aquire(); + if (ret) { + WMT_ERR_FUNC("--->lock idc_lock failed, ret=%d\n", ret); + return MTK_WCN_BOOL_FALSE; + } + msg_len = idc_infor->local_para_ptr->msg_len - osal_sizeof(struct local_para); + if (msg_len > WMT_IDC_MSG_MAX_SIZE) { + wmt_lib_idc_lock_release(); + WMT_ERR_FUNC("abnormal idc msg len:%d\n", msg_len); + return -2; + } + osal_memcpy(&gDevWmt.msg_local_buffer[0], &msg_len, osal_sizeof(msg_len)); + osal_memcpy(&gDevWmt.msg_local_buffer[osal_sizeof(msg_len)], + &(idc_infor->local_para_ptr->data[0]), msg_len - 1); + wmt_lib_idc_lock_release(); + + lxop = wmt_lib_get_free_op(); + if (!lxop) { + WMT_DBG_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + pSignal = &lxop->signal; + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + lxop->op.opId = WMT_OPID_IDC_MSG_HANDLING; + lxop->op.au4OpData[0] = (size_t) gDevWmt.msg_local_buffer; + + /*msg opcode fill rule is still not clrear,need scott comment */ + /***********************************************************/ + WMT_DBG_FUNC("ilm msg id is (0x%08x)\n", idc_infor->msg_id); + +#if CFG_WMT_LTE_ENABLE_MSGID_MAPPING + switch (idc_infor->msg_id) { + case IPC_MSG_ID_EL1_LTE_DEFAULT_PARAM_IND: + lxop->op.au4OpData[1] = WMT_IDC_TX_OPCODE_LTE_PARA; + break; + case IPC_MSG_ID_EL1_LTE_OPER_FREQ_PARAM_IND: + lxop->op.au4OpData[1] = WMT_IDC_TX_OPCODE_LTE_FREQ; + break; + case IPC_MSG_ID_EL1_WIFI_MAX_PWR_IND: + lxop->op.au4OpData[1] = WMT_IDC_TX_OPCODE_WIFI_MAX_POWER; + break; + case IPC_MSG_ID_EL1_LTE_TX_IND: + lxop->op.au4OpData[1] = WMT_IDC_TX_OPCODE_LTE_INDICATION; + break; + case IPC_MSG_ID_EL1_LTE_CONNECTION_STATUS_IND: + lxop->op.au4OpData[1] = WMT_IDC_TX_OPCODE_LTE_CONNECTION_STAS; + break; + case IPC_MSG_ID_EL1_LTE_HW_INTERFACE_IND: + lxop->op.au4OpData[1] = WMT_IDC_TX_OPCODE_LTE_HW_IF_INDICATION; + break; + default: + unknown_msgid = MTK_WCN_BOOL_TRUE; + break; + } + if (unknown_msgid == MTK_WCN_BOOL_FALSE) { + /*wake up chip first */ + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + wmt_lib_put_op_to_free_queue(lxop); + return MTK_WCN_BOOL_FALSE; + } + + bRet = wmt_lib_put_act_op(lxop); + ENABLE_PSM_MONITOR(); + if (bRet == MTK_WCN_BOOL_FALSE) { + WMT_WARN_FUNC("WMT_OPID_IDC_MSG_HANDLING fail(%d)\n", bRet); + } else { + WMT_DBG_FUNC("OPID(%d) type(%zu) ok\n", + lxop->op.opId, lxop->op.au4OpData[1]); + } + } else { + bRet = MTK_WCN_BOOL_FALSE; + wmt_lib_put_op_to_free_queue(lxop); + WMT_ERR_FUNC("unknown msgid from LTE(%d)\n", idc_infor->msg_id); + } +#else + if ((idc_infor->msg_id >= IPC_EL1_MSG_ID_BEGIN) + && (idc_infor->msg_id <= IPC_EL1_MSG_ID_BEGIN + IPC_EL1_MSG_ID_RANGE)) { + lxop->op.au4OpData[1] = idc_infor->msg_id - IPC_EL1_MSG_ID_BEGIN + LTE_MSG_ID_OFFSET - 1; + + /*wake up chip first */ + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + wmt_lib_put_op_to_free_queue(lxop); + return MTK_WCN_BOOL_FALSE; + } + + bRet = wmt_lib_put_act_op(lxop); + ENABLE_PSM_MONITOR(); + if (bRet == MTK_WCN_BOOL_FALSE) { + WMT_WARN_FUNC("WMT_OPID_IDC_MSG_HANDLING fail(%d)\n", bRet); + } else { + WMT_DBG_FUNC("wmt_lib_handle_idc_msg OPID(%d) type(%zu) ok\n", + lxop->op.opId, lxop->op.au4OpData[1]); + } + } else { + wmt_lib_put_op_to_free_queue(lxop); + WMT_ERR_FUNC("msgid(%d) out of range,wmt drop it!\n", idc_infor->msg_id); + } + +#endif + return bRet; +} +#endif + +static MTK_WCN_BOOL wmt_lib_ps_do_sleep(VOID) +{ + return wmt_lib_ps_action(SLEEP); +} + +static MTK_WCN_BOOL wmt_lib_ps_do_wakeup(VOID) +{ + return wmt_lib_ps_action(WAKEUP); +} + +static MTK_WCN_BOOL wmt_lib_ps_do_host_awake(VOID) +{ + 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; + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + static DEFINE_RATELIMIT_STATE(_rs, 2 * HZ, 1); + + ret = 0; /* TODO:[FixMe][George] initial value or compile warning? */ + /* if(g_block_tx && (action == SLEEP)) */ + if ((mtk_wcn_stp_coredump_start_get() != 0) && (action == SLEEP)) { + ret = mtk_wcn_stp_psm_notify_stp(SLEEP); + return ret; + } + + /*MT662x Not Ready */ + if (!mtk_wcn_stp_is_ready()) { + if (!mtk_wcn_stp_is_sdio_mode()) { + WMT_DBG_FUNC("MT662x Not Ready, Dont Send Sleep/Wakeup Command\n"); + ret = mtk_wcn_stp_psm_notify_stp(ROLL_BACK); + } else { + WMT_DBG_FUNC("MT662x Not Ready, SDIO mode, skip EIRQ"); + } + return ret; + } + + if (action == SLEEP) { + WMT_DBG_FUNC("send op--------------------------------> sleep job\n"); + + if (!mtk_wcn_stp_is_sdio_mode()) { + bRet = wmt_lib_ps_do_sleep(); + ret = bRet ? 0 : -1; + WMT_DBG_FUNC("enable host eirq\n"); + wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_EN); +#if CFG_WMT_DUMP_INT_STATUS + if (wmt_plat_dump_BGF_irq_status() == MTK_WCN_BOOL_TRUE) + wmt_plat_BGF_irq_dump_status(); +#endif + } else { + /* ret = mtk_wcn_stp_sdio_do_own_set(); */ + if (sdio_own_ctrl) { + ret = (*sdio_own_ctrl) (OWN_SET); + mtk_wcn_stp_dbg_pkt_log(8, PKT_DIR_TX); + } 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 (action == WAKEUP) { + WMT_DBG_FUNC("send op --------------------------------> wake job\n"); + + if (!mtk_wcn_stp_is_sdio_mode()) { + WMT_DBG_FUNC("disable host eirq\n"); +#if CFG_WMT_DUMP_INT_STATUS + if (wmt_plat_dump_BGF_irq_status() == MTK_WCN_BOOL_TRUE) + wmt_plat_BGF_irq_dump_status(); +#endif + wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); + bRet = wmt_lib_ps_do_wakeup(); + ret = bRet ? 0 : -1; + } 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 (action == HOST_AWAKE) { + WMT_DBG_FUNC("send op --------------------------------> host awake job\n"); + + if (!mtk_wcn_stp_is_sdio_mode()) { + WMT_DBG_FUNC("disable host eirq\n"); + /* IRQ already disabled */ + /* wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); */ +#if 0 + if (wmt_plat_dump_BGF_irq_status() == MTK_WCN_BOOL_TRUE) + wmt_plat_BGF_irq_dump_status(); +#endif + bRet = wmt_lib_ps_do_host_awake(); + ret = bRet ? 0 : -1; + } 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; + } + + mtk_wcn_stp_psm_notify_stp(HOST_AWAKE); + } + + WMT_DBG_FUNC("send op<--------------------------------- host awake job\n"); + } else if (action == EIRQ) { + WMT_DBG_FUNC("send op --------------------------------> eirq job\n"); + + if (!mtk_wcn_stp_is_sdio_mode()) { + if (__ratelimit(&_rs)) + pr_info("conn2ap_btif0_wakeup_out_b EIRQ handler\n"); + 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_DBG_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 +} + +VOID wmt_lib_set_bt_link_status(INT32 type, INT32 value) +{ + WMT_INFO_FUNC("t = %d, v = %d, no_acl = %d, no_br = %d\n", + type, value, g_bt_no_acl_link, g_bt_no_br_acl_link); + + if (type == 0) + g_bt_no_acl_link = value; + else if (type == 1) + g_bt_no_br_acl_link = value; +} + +/* + * Allow BT to reset as long as one of the conditions is true. + * 1. no ACL link + * 2. no BR ACL link at 2 AM + */ +static INT32 wmt_lib_is_bt_able_to_reset(VOID) +{ + if (g_bt_no_acl_link) + return 1; + else if (g_bt_no_br_acl_link) { + struct timeval time; + ULONG local_time; + struct rtc_time tm; + + osal_do_gettimeofday(&time); + local_time = (ULONG)(time.tv_sec - (sys_tz.tz_minuteswest * 60)); + rtc_time_to_tm(local_time, &tm); + if (tm.tm_hour == 2) + return 1; + } + return 0; +} + +INT32 wmt_lib_update_fw_patch_chip_rst(VOID) +{ + MTK_WCN_BOOL wifiDrvOwn = MTK_WCN_BOOL_FALSE; + + if (g_fw_patch_update_rst == 0) + return 0; + + if (chip_reset_only == 1) + return 0; + + if (time_before_eq64(get_jiffies_64(), fw_patch_rst_time)) + return 0; + + if (wmt_lib_get_drv_status(WMTDRV_TYPE_WIFI) == DRV_STS_FUNC_ON) { + if (wmt_lib_wlan_lock_trylock() == 0) + return 0; + + if (mtk_wcn_wlan_is_wifi_drv_own != NULL) + wifiDrvOwn = ((*mtk_wcn_wlan_is_wifi_drv_own)() == 0) ? MTK_WCN_BOOL_FALSE : MTK_WCN_BOOL_TRUE; + + wmt_lib_wlan_lock_release(); + } + + if (wmt_lib_get_drv_status(WMTDRV_TYPE_BT) == DRV_STS_FUNC_ON && + wmt_lib_is_bt_able_to_reset() == 0) + return 0; + + if (wmt_dev_get_early_suspend_state() == MTK_WCN_BOOL_FALSE + || wmt_lib_get_drv_status(WMTDRV_TYPE_FM) == DRV_STS_FUNC_ON + || mtk_wcn_stp_is_ready() == MTK_WCN_BOOL_FALSE + || wifiDrvOwn == MTK_WCN_BOOL_TRUE) + return 0; + + if (wmt_lib_psm_lock_trylock() == 0) + return 0; + wmt_lib_psm_lock_release(); + + wmt_lib_fw_patch_update_rst_ctrl(0); + chip_reset_only = 1; + fw_patch_rst_time = get_jiffies_64() + (FW_PATCH_UPDATE_RST_DURATION * HZ); + WMT_INFO_FUNC("Invoke whole chip reset from fw patch update!!!\n"); + return wmt_lib_trigger_reset(); +} + +MTK_WCN_BOOL wmt_lib_is_quick_ps_support(VOID) +{ + if ((g_quick_sleep_ctrl) && (wmt_dev_get_early_suspend_state() == MTK_WCN_BOOL_TRUE)) + return wmt_core_is_quick_ps_support(); + else + return MTK_WCN_BOOL_FALSE; +} + +VOID wmt_lib_ps_irq_cb(VOID) +{ +#if CFG_WMT_PS_SUPPORT + wmt_lib_ps_handler(EIRQ); +#else + WMT_DBG_FUNC("CFG_WMT_PS_SUPPORT is not set\n"); + return; +#endif +} + +VOID wmt_lib_ps_set_sdio_psop(PF_WMT_SDIO_PSOP own_cb) +{ +#if CFG_WMT_PS_SUPPORT + sdio_own_ctrl = own_cb; +#endif +} + +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT +VOID wmt_lib_sdio_deep_sleep_flag_set_cb_reg(PF_WMT_SDIO_DEEP_SLEEP flag_cb) +{ + sdio_deep_sleep_flag_set = flag_cb; +} +#endif + +VOID wmt_lib_sdio_reg_rw_cb(PF_WMT_SDIO_DEBUG reg_rw_cb) +{ + sdio_reg_rw = reg_rw_cb; +} + +UINT32 wmt_lib_wait_event_checker(P_OSAL_THREAD pThread) +{ + P_DEV_WMT pDevWmt; + + if (pThread) { + pDevWmt = (P_DEV_WMT) (pThread->pThreadData); + return !RB_EMPTY(&pDevWmt->rActiveOpQ); + } + WMT_ERR_FUNC("pThread(NULL)\n"); + return 0; +} + +UINT32 wmt_lib_worker_wait_event_checker(P_OSAL_THREAD pThread) +{ + P_DEV_WMT pDevWmt; + + if (pThread) { + pDevWmt = (P_DEV_WMT) (pThread->pThreadData); + return !RB_EMPTY(&pDevWmt->rWorkerOpQ); + } + 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 (pWmtDev == NULL) { + 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; + } + + osal_op_history_save(&pWmtDev->wmtd_op_history, pOp); + +#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) + || (pOp->op.opId == WMT_OPID_GET_CONSYS_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 (iResult == 0 && + (pOp->op.opId == WMT_OPID_WLAN_PROBE || pOp->op.opId == WMT_OPID_WLAN_REMOVE)) + continue; + + if (atomic_dec_and_test(&pOp->ref_count)) { + wmt_lib_put_op(&pWmtDev->rFreeOpQ, pOp); + } else if (osal_op_is_wait_for_signal(pOp)) { + osal_op_raise_signal(pOp, iResult); + } + + if (pOp->op.opId == WMT_OPID_EXIT) { + WMT_INFO_FUNC("wmtd thread received exit signal\n"); + break; + } + } + + WMT_INFO_FUNC("wmtd thread exits succeed\n"); + + return 0; +}; + +static INT32 met_thread(void *pvData) +{ + P_DEV_WMT p_wmtdev = (P_DEV_WMT) pvData; + INT32 log_ctrl; + UINT32 read_ptr = 0; + UINT32 write_ptr = 0; + UINT32 emi_met_size = 0; + UINT32 emi_met_offset = 0; + P_CONSYS_EMI_ADDR_INFO emi_info; + PUINT8 emi_met_base = NULL; + PINT32 met_dump_buf = 0; + UINT32 met_buf_offset = 0; + UINT32 value = 0; + + if (p_wmtdev == NULL) { + WMT_ERR_FUNC("pWmtDev(NULL)\n"); + return -1; + } + + WMT_INFO_FUNC("met thread starts\n"); + + emi_info = mtk_wcn_consys_soc_get_emi_phy_add(); + if (!emi_info) { + WMT_ERR_FUNC("get EMI info failed.\n"); + return -1; + } + + emi_met_size = emi_info->emi_met_size; + if (!emi_met_size) { + WMT_ERR_FUNC("get met emi size fail\n"); + return -1; + } + + emi_met_offset = emi_info->emi_met_data_offset; + if (!emi_met_offset) { + WMT_ERR_FUNC("get met emi offset fail\n"); + return -1; + } + + met_dump_buf = osal_malloc(MET_DUMP_SIZE); + if (!met_dump_buf) { + WMT_ERR_FUNC("alloc dump buffer fail\n"); + return -1; + } + osal_memset(met_dump_buf, 0, MET_DUMP_SIZE); + + emi_met_base = ioremap_nocache(emi_info->emi_ap_phy_addr + emi_met_offset, emi_met_size); + if (!emi_met_base) { + osal_free(met_dump_buf); + WMT_ERR_FUNC("met emi ioremap fail\n"); + return -1; + } + + WMT_INFO_FUNC("emi phy base:%x, emi vir base:%p, met offset:%x, size:%x\n", + emi_info->emi_ap_phy_addr, + emi_met_base, + emi_met_offset, + emi_met_size); + + + log_ctrl = p_wmtdev->met_log_ctrl; + if (log_ctrl) + osal_ftrace_print_ctrl(1); + + for (;;) { + if (osal_thread_should_stop(&p_wmtdev->met_thread)) { + WMT_INFO_FUNC("met thread should stop now...\n"); + goto met_exit; + } + + read_ptr = CONSYS_REG_READ(emi_met_base + EMI_MET_READ_OFFSET); + write_ptr = CONSYS_REG_READ(emi_met_base + EMI_MET_WRITE_OFFSET); + + if (read_ptr == write_ptr) + WMT_DBG_FUNC("read_ptr(0x%x) == write_ptr(0x%x) no met data need dump!!!\n", + read_ptr, write_ptr); + else if (write_ptr > (emi_met_size - EMI_MET_DATA_OFFSET)) { + WMT_ERR_FUNC("write_ptr(0x%x) overflow!!!\n", write_ptr); + wmt_lib_trigger_assert(WMTDRV_TYPE_WMT, 42); + goto met_exit; + } else { + if (read_ptr > write_ptr) { + for (; read_ptr < emi_met_size; read_ptr += 0x4) { + value = CONSYS_REG_READ(emi_met_base + EMI_MET_DATA_OFFSET + read_ptr); + met_dump_buf[met_buf_offset] = value; + met_buf_offset++; + if (met_buf_offset >= MET_DUMP_MAX_NUM) { + met_buf_offset = 0; + osal_buffer_dump_data(met_dump_buf, "MCU_MET_DATA:", + MET_DUMP_MAX_NUM, MET_DUMP_MAX_NUM, + log_ctrl); + } + } + read_ptr = 0; + } + + for (; read_ptr < write_ptr; read_ptr += 0x4) { + value = CONSYS_REG_READ(emi_met_base + EMI_MET_DATA_OFFSET + read_ptr); + met_dump_buf[met_buf_offset] = value; + met_buf_offset++; + if (met_buf_offset >= MET_DUMP_MAX_NUM) { + met_buf_offset = 0; + osal_buffer_dump_data(met_dump_buf, "MCU_MET_DATA:", MET_DUMP_MAX_NUM, + MET_DUMP_MAX_NUM, + log_ctrl); + } + } + CONSYS_REG_WRITE(emi_met_base, read_ptr); + } + osal_usleep_range(CONSYS_MET_WAIT, CONSYS_MET_WAIT); + } + +met_exit: + osal_free(met_dump_buf); + iounmap(emi_met_base); + WMT_INFO_FUNC("met thread exits succeed\n"); + + return 0; +}; + +static VOID wmt_lib_wmtd_worker_thread_timeout_handler(timer_handler_arg arg) +{ + schedule_work(&gDevWmt.wmtd_worker_thread_work); +} + +static VOID wmt_lib_wmtd_worker_thread_work_handler(struct work_struct *work) +{ + PUINT8 pbuf = NULL; + INT32 len = 0; + P_OSAL_OP pOp; + + pOp = wmt_lib_get_worker_op(&gDevWmt); + if (pOp) { + switch (pOp->op.opId) { + case WMT_OPID_WLAN_PROBE: + pbuf = "DrvWMT turn on wifi fail, just collect SYS_FTRACE to DB"; + len = osal_strlen(pbuf); + break; + case WMT_OPID_WLAN_REMOVE: + pbuf = "DrvWMT turn off wifi fail, just collect SYS_FTRACE to DB"; + len = osal_strlen(pbuf); + break; + default: + pbuf = "DrvWMT unknown op fail, just collect SYS_FTRACE to DB"; + len = osal_strlen(pbuf); + break; + } + wmt_lib_trigger_assert_keyword(WMTDRV_TYPE_WIFI, 0, pbuf); + } +} + +static INT32 wmtd_worker_thread(void *pvData) +{ + P_DEV_WMT pWmtDev = (P_DEV_WMT) pvData; + P_OSAL_EVENT pEvent = NULL; + P_OSAL_OP pOp; + INT32 iResult = 0; + + pEvent = &(pWmtDev->rWmtdWorkerWq); + + for (;;) { + osal_thread_wait_for_event(&pWmtDev->worker_thread, pEvent, wmt_lib_worker_wait_event_checker); + + if (osal_thread_should_stop(&pWmtDev->worker_thread)) { + WMT_INFO_FUNC("wmtd worker thread should stop now...\n"); + /* TODO: clean up active opQ */ + break; + } + + /* get Op from activeWorkerQ */ + pOp = wmt_lib_get_op(&pWmtDev->rWorkerOpQ); + if (!pOp) { + WMT_WARN_FUNC("get activeWorkerQ fail\n"); + continue; + } + osal_op_history_save(&pWmtDev->worker_op_history, pOp); + + if (osal_test_bit(WMT_STAT_RST_ON, &pWmtDev->state)) { + iResult = -2; + WMT_WARN_FUNC("Whole chip resetting, opid (0x%x) failed, iRet(%d)\n", pOp->op.opId, iResult); + } else { + WMT_WARN_FUNC("opid: 0x%x", pOp->op.opId); + wmt_lib_set_worker_op(pWmtDev, pOp); + osal_timer_start(&gDevWmt.worker_timer, MAX_FUNC_ON_TIME); + iResult = wmt_core_opid(&pOp->op); + osal_timer_stop(&gDevWmt.worker_timer); + wmt_lib_set_worker_op(pWmtDev, NULL); + } + + if (iResult) + WMT_WARN_FUNC("opid (0x%x) failed, iRet(%d)\n", pOp->op.opId, iResult); + + if (atomic_dec_and_test(&pOp->ref_count)) + wmt_lib_put_op(&pWmtDev->rFreeOpQ, pOp); + else if (osal_op_is_wait_for_signal(pOp)) + osal_op_raise_signal(pOp, iResult); + } + + return 0; +} + +static MTK_WCN_BOOL wmt_lib_put_op(P_OSAL_OP_Q pOpQ, P_OSAL_OP pOp) +{ + INT32 iRet; + + if (!pOpQ || !pOp) { + WMT_WARN_FUNC("invalid input param: pOpQ(0x%p), pLxOp(0x%p)\n", pOpQ, pOp); + osal_assert(pOpQ); + osal_assert(pOp); + return MTK_WCN_BOOL_FALSE; + } + + iRet = osal_lock_sleepable_lock(&pOpQ->sLock); + if (iRet) { + WMT_WARN_FUNC("osal_lock_sleepable_lock iRet(%d)\n", iRet); + return MTK_WCN_BOOL_FALSE; + } + +#if defined(CONFIG_MTK_ENG_BUILD) || defined(CONFIG_MT_ENG_BUILD) + if (osal_opq_has_op(pOpQ, pOp)) { + WMT_ERR_FUNC("Op(%p) already exists in queue(%p)\n", pOp, pOpQ); + iRet = -2; + } +#endif + + /* acquire lock success */ + if (!RB_FULL(pOpQ)) + RB_PUT(pOpQ, pOp); + else { + WMT_WARN_FUNC("RB_FULL(%p -> %p)\n", pOp, pOpQ); + iRet = -1; + } + + osal_unlock_sleepable_lock(&pOpQ->sLock); + + if (iRet) { + osal_opq_dump("FreeOpQ", &gDevWmt.rFreeOpQ); + osal_opq_dump("ActiveOpQ", &gDevWmt.rActiveOpQ); + return MTK_WCN_BOOL_FALSE; + } + 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 (pOpQ == NULL) { + 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 (pOp == NULL) { + P_OSAL_OP pCurOp = wmt_lib_get_current_op(&gDevWmt); + + WMT_WARN_FUNC("RB_GET(%p) return NULL\n", pOpQ); + if (pCurOp != NULL) + WMT_WARN_FUNC("Current opId (%d)\n", pCurOp->op.opId); + + wmt_lib_print_wmtd_op_history(); + wmt_lib_print_worker_op_history(); + osal_opq_dump("FreeOpQ", &gDevWmt.rFreeOpQ); + osal_opq_dump("ActiveOpQ", &gDevWmt.rActiveOpQ); + osal_assert(pOp); + } + + return pOp; +} + + +INT32 wmt_lib_put_op_to_free_queue(P_OSAL_OP pOp) +{ + P_DEV_WMT pWmtDev = &gDevWmt; + + if (wmt_lib_put_op(&pWmtDev->rFreeOpQ, pOp) == MTK_WCN_BOOL_FALSE) + return -1; + + return 0; +} + + +P_OSAL_OP wmt_lib_get_free_op(VOID) +{ + P_OSAL_OP pOp = NULL; + P_DEV_WMT pDevWmt = &gDevWmt; + + osal_assert(pDevWmt); + pOp = wmt_lib_get_op(&pDevWmt->rFreeOpQ); + if (pOp) { + osal_memset(pOp, 0, osal_sizeof(OSAL_OP)); + } + return pOp; +} + +MTK_WCN_BOOL wmt_lib_put_act_op(P_OSAL_OP pOp) +{ + P_DEV_WMT pWmtDev = &gDevWmt; + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + P_OSAL_SIGNAL pSignal = NULL; + INT32 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; + } + + /* Init ref_count to 1 indicating that current thread holds a ref to it */ + atomic_set(&pOp->ref_count, 1); + + if ((mtk_wcn_stp_coredump_start_get() != 0) && + (pOp->op.opId != WMT_OPID_HW_RST) && + (pOp->op.opId != WMT_OPID_SW_RST) && (pOp->op.opId != WMT_OPID_GPIO_STATE)) { + 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); + } + + /* Increment ref_count by 1 as wmtd thread will hold a reference also, + * this must be done here instead of on target thread, because + * target thread might not be scheduled until a much later time, + * allowing current thread to decrement ref_count at the end of function, + * putting op back to free queue before target thread has a chance to process. + */ + atomic_inc(&pOp->ref_count); + + /* put to active Q */ + bRet = wmt_lib_put_op(&pWmtDev->rActiveOpQ, pOp); + if (bRet == MTK_WCN_BOOL_FALSE) { + WMT_WARN_FUNC("put to active queue fail\n"); + atomic_dec(&pOp->ref_count); + break; + } + + /* wake up wmtd */ + /* wake_up_interruptible(&pWmtDev->rWmtdWq); */ + osal_trigger_event(&pWmtDev->rWmtdWq); + + if (pSignal->timeoutValue == 0) { + bRet = MTK_WCN_BOOL_TRUE; + /* clean it in wmtd */ + break; + } + + /* 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)); */ + if (pOp->op.opId == WMT_OPID_FUNC_ON && + pOp->op.au4OpData[0] == WMTDRV_TYPE_WIFI) + waitRet = osal_wait_for_signal_timeout(pSignal, &pWmtDev->worker_thread); + else + waitRet = osal_wait_for_signal_timeout(pSignal, &pWmtDev->thread); + WMT_DBG_FUNC("osal_wait_for_signal_timeout:%d\n", waitRet); + + /* if (unlikely(!wait_ret)) { */ + if (waitRet == 0) + WMT_ERR_FUNC("opId(%d) completion timeout\n", pOp->op.opId); + 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 (pOp && atomic_dec_and_test(&pOp->ref_count)) { + /* put Op back to freeQ */ + wmt_lib_put_op(&pWmtDev->rFreeOpQ, pOp); + } + + return bRet; +} + +MTK_WCN_BOOL wmt_lib_put_worker_op(P_OSAL_OP pOp) +{ + P_DEV_WMT pWmtDev = &gDevWmt; + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + + osal_assert(pWmtDev); + osal_assert(pOp); + + do { + if (!pWmtDev || !pOp) { + WMT_ERR_FUNC("pWmtDev(0x%p), pOp(0x%p)\n", pWmtDev, pOp); + break; + } + + /* put to activeWorker Q */ + bRet = wmt_lib_put_op(&pWmtDev->rWorkerOpQ, pOp); + if (bRet == MTK_WCN_BOOL_FALSE) { + WMT_WARN_FUNC("put to ActiveWorker queue fail\n"); + break; + } + + /* wake up wmtd_worker */ + osal_trigger_event(&pWmtDev->rWmtdWorkerWq); + } while (0); + + 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_DBG_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 (bRet != MTK_WCN_BOOL_FALSE) { + WMT_DBG_FUNC("OPID_REG_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x) ok\n", + isWrite, offset, *plv, mask); + if (!isWrite) + *pvalue = *plv; + } else { + WMT_WARN_FUNC + ("OPID_REG_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x) bRet(%d)\n", + isWrite, offset, *plv, mask, bRet); + } + + return bRet; +} +#endif + +/* TODO:[ChangeFeature][George] is this function obsoleted? */ +#if 0 +static VOID wmt_lib_clear_chip_id(VOID) +{ +/* + * gDevWmt.pChipInfo = NULL; +*/ + gDevWmt.hw_ver = WMTHWVER_INVALID; +} +#endif + +UINT32 wmt_lib_get_icinfo(ENUM_WMT_CHIPINFO_TYPE_T index) +{ + UINT32 chip_id = 0; + + if (index == WMTCHIN_CHIPID) { + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_COMBO) + chip_id = gDevWmt.chip_id; + else + chip_id = mtk_wcn_consys_soc_chipid(); + WMT_INFO_FUNC("chip_id=[%x]", chip_id); + return chip_id; + } else if (index == WMTCHIN_HWVER) + return gDevWmt.hw_ver; + else if (index == WMTCHIN_FWVER) + return gDevWmt.fw_ver; + else if (index == WMTCHIN_IPVER) + return gDevWmt.ip_ver; + else if (index == WMTCHIN_ADIE) + return mtk_wcn_consys_get_adie_chipid(); + + return 0; + +} + + +PUINT8 wmt_lib_def_patch_name(VOID) +{ + WMT_INFO_FUNC("wmt-lib: use default patch name (%s)\n", gDevWmt.cPatchName); + return gDevWmt.cPatchName; +} + + +MTK_WCN_BOOL wmt_lib_is_therm_ctrl_support(ENUM_WMTTHERM_TYPE_T eType) +{ + MTK_WCN_BOOL bIsSupportTherm = MTK_WCN_BOOL_TRUE; + /* TODO:[FixMe][GeorgeKuo]: move IC-dependent checking to ic-implementation file */ + if ((gDevWmt.chip_id == 0x6620) && (gDevWmt.hw_ver == 0x8A00 /*E1*/ || gDevWmt.hw_ver == 0x8A01 /*E2*/)) { + WMT_ERR_FUNC("thermal command fail: chip version(HWVER:0x%04x) is not valid\n", + gDevWmt.hw_ver); + bIsSupportTherm = MTK_WCN_BOOL_FALSE; + } + if ((!osal_test_bit(WMT_STAT_STP_EN, &gDevWmt.state)) + || (!osal_test_bit(WMT_STAT_STP_RDY, &gDevWmt.state))) { + if (eType == WMTTHERM_READ) + WMT_INFO_FUNC + ("thermal command can`t send: STP is not enable(%d) or ready(%d)\n", + osal_test_bit(WMT_STAT_STP_EN, &gDevWmt.state), + osal_test_bit(WMT_STAT_STP_RDY, &gDevWmt.state)); + 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 ((gDevWmt.chip_id == 0x6620) && (gDevWmt.hw_ver == 0x8A00 /*E1*/ || gDevWmt.hw_ver == 0x8A01 /*E2*/)) { + WMT_ERR_FUNC("thermal command fail: chip version(HWVER:0x%04x) is not valid\n", + gDevWmt.hw_ver); + 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 (id >= WMT_IC_PIN_MAX) { + WMT_ERR_FUNC("invalid ic pin id(%d)\n", id); + return -1; + } + if (stat >= WMT_IC_PIN_STATE_MAX) { + WMT_ERR_FUNC("invalid ic pin state (%d)\n", stat); + return -2; + } + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_DBG_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 (bRet == MTK_WCN_BOOL_FALSE) + WMT_WARN_FUNC("PIN_ID(%d) PIN_STATE(%d) flag(%d) fail\n", id, stat, flag); + else + WMT_DBG_FUNC("OPID(%d) type(%zu) 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_DBG_FUNC("get_free_lxop fail\n"); + return -1; + } + + pSignal = &pOp->signal; + pSignal->timeoutValue = MAX_WMT_OP_TIMEOUT; + value = *pvalue; + WMT_DBG_FUNC("OPID_REG_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x)\n\n", + isWrite, offset, *pvalue, mask); + pOp->op.opId = WMT_OPID_REG_RW; + pOp->op.au4OpData[0] = isWrite; + pOp->op.au4OpData[1] = offset; + pOp->op.au4OpData[2] = (size_t) &value; + pOp->op.au4OpData[3] = mask; + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + wmt_lib_put_op_to_free_queue(pOp); + return -1; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + + if (bRet != MTK_WCN_BOOL_FALSE) { + WMT_DBG_FUNC("OPID_REG_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x) ok\n", + isWrite, offset, value, mask); + if (!isWrite) + *pvalue = value; + + return 0; + } + WMT_WARN_FUNC("OPID_REG_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x) bRet(%d)\n", + isWrite, offset, value, mask, bRet); + + return -1; +} + +INT32 wmt_lib_efuse_rw(UINT32 isWrite, UINT32 offset, PUINT32 pvalue, UINT32 mask) +{ + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + UINT32 value; + P_OSAL_SIGNAL pSignal; + + if (!pvalue) { + WMT_WARN_FUNC("!pvalue\n"); + return -1; + } + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_DBG_FUNC("get_free_lxop fail\n"); + return -1; + } + + pSignal = &pOp->signal; + pSignal->timeoutValue = MAX_WMT_OP_TIMEOUT; + value = *pvalue; + WMT_DBG_FUNC("OPID_EFUSE_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x)\n\n", + isWrite, offset, *pvalue, mask); + pOp->op.opId = WMT_OPID_EFUSE_RW; + pOp->op.au4OpData[0] = isWrite; + pOp->op.au4OpData[1] = offset; + pOp->op.au4OpData[2] = (size_t) &value; + pOp->op.au4OpData[3] = mask; + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + wmt_lib_put_op_to_free_queue(pOp); + return -1; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + + if (bRet != MTK_WCN_BOOL_FALSE) { + WMT_DBG_FUNC("OPID_EFUSE_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x) ok\n", + isWrite, offset, value, mask); + if (!isWrite) + *pvalue = value; + return 0; + } + WMT_WARN_FUNC("OPID_REG_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x) bRet(%d)\n", + isWrite, offset, value, mask, bRet); + return -1; +} + +INT32 wmt_lib_utc_time_sync(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 -1; + } + + pSignal = &pOp->signal; + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + pOp->op.opId = WMT_OPID_UTC_TIME_SYNC; + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + wmt_lib_put_op_to_free_queue(pOp); + return -2; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + if (bRet == MTK_WCN_BOOL_FALSE) { + WMT_WARN_FUNC("WMT_OPID_UTC_TIME_SYNC fail(%d)\n", bRet); + return -3; + } + WMT_DBG_FUNC("wmt_lib_utc_time_sync OPID(%d) ok\n", pOp->op.opId); + + return 0; +} + +INT32 wmt_lib_try_pwr_off(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 -1; + } + + pSignal = &pOp->signal; + pSignal->timeoutValue = MAX_FUNC_OFF_TIME; + pOp->op.opId = WMT_OPID_TRY_PWR_OFF; + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + wmt_lib_put_op_to_free_queue(pOp); + return -2; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + if (bRet == MTK_WCN_BOOL_FALSE) { + WMT_WARN_FUNC("WMT_OPID_TRY_PWR_OFF fail(%d)\n", bRet); + return -2; + } + WMT_DBG_FUNC("wmt_lib_try_pwr_off OPID(%d) ok\n", pOp->op.opId); + + return 0; +} + +P_WMT_PATCH_INFO wmt_lib_get_patch_info(VOID) +{ + return gDevWmt.pWmtPatchInfo; +} + +/*! + * \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(enum CMB_STUB_AIF_X aif, MTK_WCN_BOOL share) +{ + if (aif < 0 || aif >= CMB_STUB_AIF_MAX) { + WMT_ERR_FUNC("invalid aif (%d)\n", aif); + return -1; + } + WMT_DBG_FUNC("call pin_ctrl for aif:%d, share:%d\n", aif, + (share == MTK_WCN_BOOL_TRUE) ? 1 : 0); + /* Translate enum 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(); + } else if (op == BTM_TRIGGER_STP_ASSERT_OP) { + bRet = wmt_core_trigger_stp_assert(); + } + return bRet; +} + +MTK_WCN_BOOL wmt_cdev_rstmsg_snd(ENUM_WMTRSTMSG_TYPE_T msg) +{ + + INT32 i = 0; + P_DEV_WMT pDevWmt = &gDevWmt; + UINT8 *drv_name[] = { + "DRV_TYPE_BT", + "DRV_TYPE_FM", + "DRV_TYPE_GPS", + "DRV_TYPE_WIFI", + "DRV_TYPE_ANT", + "UNKNOWN" + }; + + for (i = 0; i <= WMTDRV_TYPE_ANT; i++) { + /* <1> check if reset callback is registered */ + if (pDevWmt->rFdrvCb.fDrvRst[i]) { + /* <2> send the msg to this subfucntion */ + /*src, dst, msg_type, msg_data, msg_size */ + pDevWmt->rFdrvCb.fDrvRst[i] (WMTDRV_TYPE_WMT, i, WMTMSG_TYPE_RESET, &msg, + sizeof(ENUM_WMTRSTMSG_TYPE_T)); + WMT_INFO_FUNC("type = %s, msg sent\n", drv_name[i]); + } else { + WMT_DBG_FUNC("type = %s, unregistered\n", drv_name[i]); + } + } + + return MTK_WCN_BOOL_TRUE; +} + +VOID wmt_lib_state_init(VOID) +{ + /* UINT32 i = 0; */ + P_DEV_WMT pDevWmt = &gDevWmt; + P_OSAL_OP pOp; + + /* Initialize op queue */ + /* RB_INIT(&pDevWmt->rFreeOpQ, WMT_OP_BUF_SIZE); */ + /* RB_INIT(&pDevWmt->rActiveOpQ, WMT_OP_BUF_SIZE); */ + + while (!RB_EMPTY(&pDevWmt->rActiveOpQ)) { + pOp = wmt_lib_get_op(&pDevWmt->rActiveOpQ); + if (pOp) { + if (atomic_dec_and_test(&pOp->ref_count)) + wmt_lib_put_op(&pDevWmt->rFreeOpQ, pOp); + else if (osal_op_is_wait_for_signal(pOp)) + osal_op_raise_signal(pOp, -1); + } + } +} + + +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_DBG_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 (bRet == MTK_WCN_BOOL_FALSE) { + WMT_WARN_FUNC("WMT_OPID_SDIO_CTRL failed\n"); + return -1; + } + 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_DBG_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 (bRet == MTK_WCN_BOOL_FALSE) { + WMT_WARN_FUNC("WMT_OPID_HW_STATE_SHOW failed\n"); + return MTK_WCN_BOOL_FALSE; + } + WMT_DBG_FUNC("OPID(WMT_OPID_HW_STATE_SHOW)ok\n"); + + return MTK_WCN_BOOL_TRUE; +} + + +MTK_WCN_BOOL wmt_lib_hw_rst(VOID) +{ + + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal; + P_DEV_WMT pDevWmt = &gDevWmt; + + wmt_lib_state_init(); + + osal_clear_bit(WMT_STAT_STP_REG, &pDevWmt->state); + osal_clear_bit(WMT_STAT_STP_OPEN, &pDevWmt->state); + osal_clear_bit(WMT_STAT_STP_EN, &pDevWmt->state); + osal_clear_bit(WMT_STAT_STP_RDY, &pDevWmt->state); + osal_clear_bit(WMT_STAT_RX, &pDevWmt->state); + osal_clear_bit(WMT_STAT_CMD, &pDevWmt->state); + + /*Before do hardware reset, we show GPIO state to check if others modified our pin state accidentially */ + wmt_lib_hw_state_show(); + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_DBG_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 (bRet == MTK_WCN_BOOL_FALSE) { + WMT_WARN_FUNC("WMT_OPID_HW_RST failed\n"); + return MTK_WCN_BOOL_FALSE; + } + WMT_DBG_FUNC("OPID(WMT_OPID_HW_RST)ok\n"); + + return MTK_WCN_BOOL_TRUE; +} + +MTK_WCN_BOOL wmt_lib_sw_rst(INT32 baudRst) +{ + + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal; + + /* <1> wmt state reset */ + wmt_lib_state_init(); + + /* <2> Reset STP data structure */ + WMT_DBG_FUNC("Cleanup STP context\n"); + mtk_wcn_stp_flush_context(); + stp_dbg_reset(); + + /* <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 (bRet == MTK_WCN_BOOL_FALSE) { + WMT_WARN_FUNC("WMT_OPID_SW_RST failed\n"); + return MTK_WCN_BOOL_FALSE; + } + WMT_DBG_FUNC("OPID(WMT_OPID_SW_RST)ok\n"); + + return MTK_WCN_BOOL_TRUE; +} + + +ENUM_WMTRSTRET_TYPE_T wmt_lib_cmb_rst(ENUM_WMTRSTSRC_TYPE_T src) +{ +#define RETRYTIMES 10 + MTK_WCN_BOOL bRet; + ENUM_WMTRSTRET_TYPE_T retval = WMTRSTRET_MAX; + ENUM_WMTRSTMSG_TYPE_T rstMsg = WMTRSTMSG_RESET_MAX; + INT32 retries = RETRYTIMES; + P_DEV_WMT pDevWmt = &gDevWmt; + P_OSAL_OP pOp; + UINT8 *srcName[] = { "WMTRSTSRC_RESET_BT", + "WMTRSTSRC_RESET_FM", + "WMTRSTSRC_RESET_GPS", + "WMTRSTSRC_RESET_WIFI", + "WMTRSTSRC_RESET_STP", + "WMTRSTSRC_RESET_TEST" + }; + INT32 coredump_mode = mtk_wcn_stp_coredump_flag_get(); + + WMT_INFO_FUNC("coredump mode == %d. Connsys coredump is %s.", + coredump_mode, coredump_mode ? "enabled" : "disabled"); + + if (src >= 0 && src < WMTRSTSRC_RESET_MAX) + WMT_INFO_FUNC("reset source = %s\n", srcName[src]); + + if (src == WMTRSTSRC_RESET_TEST) { + pOp = wmt_lib_get_current_op(pDevWmt); + if (pOp && ((pOp->op.opId == WMT_OPID_FUNC_ON) + || (pOp->op.opId == WMT_OPID_FUNC_OFF))) { + 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 */ + if (wmt_lib_psm_lock_trylock() == 0) { + if (chip_reset_only == 1) { + wmt_lib_fw_patch_update_rst_ctrl(1); + fw_patch_rst_time = 0; + retval = WMTRSTRET_RETRY; + goto rstDone; + } + mtk_wcn_stp_enable(0); + } else { + mtk_wcn_stp_enable(0); + wmt_lib_psm_lock_release(); + } + + /* <3> RESET_START notification */ + bRet = wmt_cdev_rstmsg_snd(WMTRSTMSG_RESET_START); + if (bRet == MTK_WCN_BOOL_FALSE) { + WMT_ERR_FUNC("[whole chip reset] fail at wmt_lib_rstmsg_snd!\n"); + retval = WMTRSTRET_FAIL; + goto rstDone; + } + /* wakeup blocked opid */ + pOp = wmt_lib_get_current_op(pDevWmt); + if (osal_op_is_wait_for_signal(pOp)) + osal_op_raise_signal(pOp, -1); + /* wakeup blocked cmd */ + wmt_dev_rx_event_cb(); + + /* <4> retry until reset flow successful */ + while (retries > 0) { + /* <4.1> reset combo hw */ + bRet = wmt_lib_hw_rst(); + if (bRet == MTK_WCN_BOOL_FALSE) { + WMT_ERR_FUNC("[whole chip reset] fail at wmt_lib_hw_rst!\n"); + retries--; + continue; + } + /* <4.2> reset driver/combo sw */ + bRet = wmt_lib_sw_rst(1); + if (bRet == MTK_WCN_BOOL_FALSE) { + WMT_ERR_FUNC("[whole chip reset] fail at wmt_lib_sw_rst!\n"); + retries--; + continue; + } + break; + } + osal_clear_bit(WMT_STAT_RST_ON, &pDevWmt->state); + if (bRet == MTK_WCN_BOOL_FALSE) { + rstMsg = WMTRSTMSG_RESET_END_FAIL; + WMT_INFO_FUNC("[whole chip reset] fail! retries = %d\n", RETRYTIMES - retries); + } else { + rstMsg = WMTRSTMSG_RESET_END; + WMT_INFO_FUNC("[whole chip reset] ok! retries = %d\n", RETRYTIMES - retries); + } + + + /* <5> RESET_END notification */ + bRet = wmt_cdev_rstmsg_snd(rstMsg); + if (bRet == MTK_WCN_BOOL_FALSE) { + WMT_ERR_FUNC("[whole chip reset] fail at wmt_lib_rstmsg_snd!\n"); + retval = WMTRSTRET_FAIL; + } else { + retval = rstMsg == WMTRSTMSG_RESET_END ? WMTRSTRET_SUCCESS : WMTRSTRET_FAIL; + } + mtk_wcn_stp_assert_flow_ctrl(0); + mtk_wcn_stp_coredump_start_ctrl(0); + mtk_wcn_stp_set_wmt_trg_assert(0); + mtk_wcn_stp_emi_dump_flag_ctrl(0); +rstDone: + osal_clear_bit(WMT_STAT_RST_ON, &pDevWmt->state); + chip_reset_only = 0; + mtk_wcn_consys_sleep_info_restore(); + 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_ANT) { + 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; +} +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT +INT32 wmt_lib_deep_sleep_ctrl(INT32 value) +{ + MTK_WCN_BOOL ret = MTK_WCN_BOOL_FALSE; + + WMT_INFO_FUNC("g_deep_sleep_flag value (%d) set form wmt_dbg.\n", value); + ret = wmt_core_deep_sleep_ctrl(value); + if (sdio_deep_sleep_flag_set) { + if (value) + (*sdio_deep_sleep_flag_set)(MTK_WCN_BOOL_TRUE); + else + (*sdio_deep_sleep_flag_set)(MTK_WCN_BOOL_FALSE); + } else { + WMT_ERR_FUNC("sdio_deep_sleep_flag_set is not register"); + return -1; + } + return 0; +} + +MTK_WCN_BOOL wmt_lib_deep_sleep_flag_set(MTK_WCN_BOOL flag) +{ + if (sdio_deep_sleep_flag_set) { + (*sdio_deep_sleep_flag_set)(flag); + } else { + WMT_ERR_FUNC("sdio_deep_sleep_flag_set is not register"); + return MTK_WCN_BOOL_FALSE; + } + return MTK_WCN_BOOL_TRUE; +} +#endif +INT32 wmt_lib_set_stp_wmt_last_close(UINT32 value) +{ + return mtk_wcn_stp_set_wmt_last_close(value); +} + +INT32 wmt_lib_notify_stp_sleep(VOID) +{ + INT32 iRet = 0x0; + + iRet = wmt_lib_psm_lock_aquire(); + if (iRet) { + WMT_ERR_FUNC("--->lock psm_lock failed, iRet=%d\n", iRet); + return iRet; + } + + iRet = mtk_wcn_stp_notify_sleep_for_thermal(); + wmt_lib_psm_lock_release(); + + return iRet; +} + +VOID wmt_lib_set_patch_num(UINT32 num) +{ + P_DEV_WMT pWmtDev = &gDevWmt; + + pWmtDev->patchNum = num; +} + +VOID wmt_lib_set_patch_info(P_WMT_PATCH_INFO pPatchinfo) +{ + P_DEV_WMT pWmtDev = &gDevWmt; + + pWmtDev->pWmtPatchInfo = pPatchinfo; +} + +VOID wmt_lib_set_rom_patch_info(struct wmt_rom_patch_info *PatchInfo, ENUM_WMTDRV_TYPE_T type) +{ + P_DEV_WMT pWmtDev = &gDevWmt; + + if (type < 0) + return; + + /* Allow info of a type to be set only once, to avoid inproper usage */ + if (pWmtDev->pWmtRomPatchInfo[type]) + return; + + pWmtDev->pWmtRomPatchInfo[type] = kcalloc(1, sizeof(struct wmt_rom_patch_info), + GFP_ATOMIC); + + if (pWmtDev->pWmtRomPatchInfo[type]) + osal_memcpy(pWmtDev->pWmtRomPatchInfo[type], PatchInfo, + sizeof(struct wmt_rom_patch_info)); +} + +INT32 wmt_lib_set_current_op(P_DEV_WMT pWmtDev, P_OSAL_OP pOp) +{ + if (pWmtDev) { + pWmtDev->pCurOP = pOp; + WMT_DBG_FUNC("pOp=0x%p\n", pOp); + return 0; + } + WMT_ERR_FUNC("Invalid pointer\n"); + return -1; +} + +P_OSAL_OP wmt_lib_get_current_op(P_DEV_WMT pWmtDev) +{ + if (pWmtDev) + return pWmtDev->pCurOP; + WMT_ERR_FUNC("Invalid pointer\n"); + return NULL; +} + +INT32 wmt_lib_set_worker_op(P_DEV_WMT pWmtDev, P_OSAL_OP pOp) +{ + if (pWmtDev) { + pWmtDev->pWorkerOP = pOp; + WMT_DBG_FUNC("pOp=0x%p\n", pOp); + return 0; + } + WMT_ERR_FUNC("Invalid pointer\n"); + return -1; +} + +P_OSAL_OP wmt_lib_get_worker_op(P_DEV_WMT pWmtDev) +{ + if (pWmtDev) + return pWmtDev->pWorkerOP; + WMT_ERR_FUNC("Invalid pointer\n"); + return NULL; +} + +UINT8 *wmt_lib_get_fwinfor_from_emi(UINT8 section, UINT32 offset, UINT8 *buf, UINT32 len) +{ + UINT8 *pAddr = NULL; + UINT32 sublen1 = 0; + UINT32 sublen2 = 0; + P_CONSYS_EMI_ADDR_INFO p_consys_info; + + p_consys_info = wmt_plat_get_emi_phy_add(); + osal_assert(p_consys_info); + + if (section == 0) { + pAddr = wmt_plat_get_emi_virt_add(0x0); + if (len > 1024) + len = 1024; + if (!pAddr) { + WMT_ERR_FUNC("wmt-lib: get EMI virtual base address fail\n"); + } else { + WMT_INFO_FUNC("vir addr(0x%p)\n", pAddr); + osal_memcpy_fromio(&buf[0], pAddr, len); + } + } else { + if (p_consys_info == NULL) { + WMT_ERR_FUNC("wmt-lib: get EMI physical address fail!\n"); + return 0; + } + + if (offset >= 0x7fff) + offset = 0x0; + + if (offset + len > 32768) { + pAddr = wmt_plat_get_emi_virt_add(offset + p_consys_info->paged_trace_off); + if (!pAddr) { + WMT_ERR_FUNC("wmt-lib: get part1 EMI virtual base address fail\n"); + } else { + WMT_INFO_FUNC("part1 vir addr(0x%p)\n", pAddr); + sublen1 = 0x7fff - offset; + osal_memcpy_fromio(&buf[0], pAddr, sublen1); + } + pAddr = wmt_plat_get_emi_virt_add(p_consys_info->paged_trace_off); + if (!pAddr) { + WMT_ERR_FUNC("wmt-lib: get part2 EMI virtual base address fail\n"); + } else { + WMT_INFO_FUNC("part2 vir addr(0x%p)\n", pAddr); + sublen2 = len - sublen1; + osal_memcpy_fromio(&buf[sublen1], pAddr, sublen2); + } + } else { + pAddr = wmt_plat_get_emi_virt_add(offset + p_consys_info->paged_trace_off); + if (!pAddr) { + WMT_ERR_FUNC("wmt-lib: get EMI virtual base address fail\n"); + } else { + WMT_INFO_FUNC("vir addr(0x%p)\n", pAddr); + osal_memcpy_fromio(&buf[0], pAddr, len); + } + } + } + + return 0; +} +EXPORT_SYMBOL(wmt_lib_get_fwinfor_from_emi); + +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 +} + + +PUINT8 wmt_lib_get_cpupcr_xml_format(PUINT32 pLen) +{ + PUINT8 temp; + + osal_memset(&g_cpupcr_buf[0], 0, WMT_STP_CPUPCR_BUF_SIZE); + temp = g_cpupcr_buf; + *pLen += stp_dbg_cpupcr_infor_format(temp, WMT_STP_CPUPCR_BUF_SIZE); + *pLen += mtk_stp_dbg_dmp_append(temp + *pLen, WMT_STP_CPUPCR_BUF_SIZE - *pLen); + + WMT_INFO_FUNC("print xml buffer,len(%d):\n\n", *pLen); + + WMT_INFO_FUNC("%s", g_cpupcr_buf); + + return &g_cpupcr_buf[0]; +} + + +/** + * called by wmt_dev wmt_dev_proc_for_dump_info_read + */ +PUINT8 wmt_lib_get_cpupcr_reg_info(PUINT32 pLen, PUINT32 consys_reg) +{ + osal_memset(&g_cpupcr_buf[0], 0, WMT_STP_CPUPCR_BUF_SIZE); + if (consys_reg != NULL) + *pLen += stp_dbg_dump_cpupcr_reg_info(g_cpupcr_buf, consys_reg[1]); + else + *pLen += osal_sprintf(g_cpupcr_buf + *pLen, "0\n"); + WMT_INFO_FUNC("print buffer,len(%d):\n\n", *pLen); + WMT_INFO_FUNC("%s", g_cpupcr_buf); + return &g_cpupcr_buf[0]; +} + +INT32 wmt_lib_tm_temp_query(VOID) +{ + return wmt_dev_tm_temp_query(); +} + +INT32 wmt_lib_register_thermal_ctrl_cb(thermal_query_ctrl_cb thermal_ctrl) +{ + wmt_plat_thermal_ctrl_cb_reg(thermal_ctrl); + return 0; +} + +INT32 wmt_lib_register_trigger_assert_cb(trigger_assert_cb trigger_assert) +{ + wmt_plat_trigger_assert_cb_reg(trigger_assert); + return 0; +} + +UINT32 wmt_lib_set_host_assert_info(UINT32 type, UINT32 reason, UINT32 en) +{ + return stp_dbg_set_host_assert_info(type, reason, en); +} + +INT8 wmt_lib_co_clock_get(void) +{ + if (gDevWmt.rWmtGenConf.cfgExist) + return gDevWmt.rWmtGenConf.co_clock_flag; + else + return -1; +} + + +UINT32 wmt_lib_get_drv_status(UINT32 type) +{ + return wmt_core_get_drv_status((ENUM_WMTDRV_TYPE_T) type); +} + +INT32 wmt_lib_trigger_reset(VOID) +{ + return wmt_btm_trigger_reset(); +} + +INT32 wmt_lib_trigger_assert(ENUM_WMTDRV_TYPE_T type, UINT32 reason) +{ + return wmt_lib_trigger_assert_keyword(type, reason, NULL); +} + +INT32 wmt_lib_trigger_assert_keyword(ENUM_WMTDRV_TYPE_T type, UINT32 reason, PUINT8 keyword) +{ + INT32 iRet = -1; + WMT_CTRL_DATA ctrlData; + + if (wmt_lib_assert_lock_trylock() == 0) { + WMT_INFO_FUNC("Can't lock assert mutex which might be held by another trigger assert procedure.\n"); + return iRet; + } + + wmt_core_set_coredump_state(DRV_STS_FUNC_ON); + + ctrlData.ctrlId = (SIZE_T) WMT_CTRL_TRG_ASSERT; + ctrlData.au4CtrlData[0] = (SIZE_T) type; + ctrlData.au4CtrlData[1] = (SIZE_T) reason; + ctrlData.au4CtrlData[2] = (SIZE_T) keyword; + + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + /* ERROR */ + WMT_ERR_FUNC + ("WMT-CORE: wmt_core_ctrl failed: type(%d), reason(%d), keyword(%s), iRet(%d)\n", + type, reason, keyword, iRet); + osal_assert(0); + } + wmt_lib_assert_lock_release(); + + return iRet; +} + +#if CFG_WMT_PS_SUPPORT +UINT32 wmt_lib_quick_sleep_ctrl(UINT32 en) +{ + WMT_WARN_FUNC("%s quick sleep mode\n", en ? "enable" : "disable"); + g_quick_sleep_ctrl = en; + return 0; +} +#endif + +UINT32 wmt_lib_fw_patch_update_rst_ctrl(UINT32 en) +{ + WMT_WARN_FUNC("%s fw patch update reset\n", en ? "enable" : "disable"); + g_fw_patch_update_rst = en; + return 0; +} + +#if CONSYS_ENALBE_SET_JTAG +UINT32 wmt_lib_jtag_flag_set(UINT32 en) +{ + return wmt_plat_jtag_flag_ctrl(en); +} +#endif + +UINT32 wmt_lib_soc_set_wifiver(UINT32 wifiver) +{ + return stp_dbg_set_wifiver(wifiver); +} + +UINT32 wmt_lib_co_clock_flag_get(VOID) +{ + return wmt_plat_soc_co_clock_flag_get(); +} + +INT32 wmt_lib_wifi_fem_cfg_report(PVOID pvInfoBuf) +{ + INT32 iRet = 0; + ULONG addr = 0; + WMT_GEN_CONF *pWmtGenConf = NULL; + + /* sanity check */ + ASSERT(pvInfoBuf); + + 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; + } + + pWmtGenConf = (P_WMT_GEN_CONF) addr; + + WMT_DBG_FUNC("pWmtGenConf->coex_wmt_wifi_path=0x%x\n", pWmtGenConf->coex_wmt_wifi_path); + + /* Memory copy */ + osal_memcpy((PUINT8)(pvInfoBuf), &pWmtGenConf->coex_wmt_wifi_path, + osal_sizeof(pWmtGenConf->coex_wmt_wifi_path)); + return iRet; +} + +INT32 wmt_lib_sdio_reg_rw(INT32 func_num, INT32 direction, UINT32 offset, UINT32 value) +{ + INT32 ret = -1; + ENUM_WMT_CHIP_TYPE chip_type; + + chip_type = wmt_detect_get_chip_type(); + + if (chip_type == WMT_CHIP_TYPE_COMBO) { + if (sdio_reg_rw) + ret = sdio_reg_rw(func_num, direction, offset, value); + else + WMT_ERR_FUNC("sdio_reg_rw callback is not set, maybe the sdio funcxx write/read not used\n"); + } else + WMT_ERR_FUNC("It`s soc project, this function is not used\n"); + return ret; +} + +VOID wmt_lib_dump_wmtd_backtrace(VOID) +{ + osal_thread_show_stack(&gDevWmt.thread); +} + +INT32 wmt_lib_met_cmd(UINT32 value) +{ + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal; + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_DBG_FUNC("get_free_lxop fail\n"); + return -1; + } + + pSignal = &pOp->signal; + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + WMT_DBG_FUNC("met ctrl value(0x%x)\n", value); + pOp->op.opId = WMT_OPID_MET_CTRL; + pOp->op.au4OpData[0] = value; + 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 (bRet != MTK_WCN_BOOL_FALSE) + return 0; + + return -1; +} + +UINT32 wmt_lib_get_gps_lna_pin_num(VOID) +{ + return mtk_consys_get_gps_lna_pin_num(); +} + +INT32 wmt_lib_met_ctrl(INT32 met_ctrl, INT32 log_ctrl) +{ + P_DEV_WMT p_devwmt; + P_OSAL_THREAD p_thread; + INT32 ret; + P_CONSYS_EMI_ADDR_INFO emi_info; + + emi_info = mtk_wcn_consys_soc_get_emi_phy_add(); + if (emi_info == NULL) { + WMT_ERR_FUNC("get EMI info failed\n"); + return -1; + } + + if (!emi_info->emi_met_size) { + WMT_ERR_FUNC("met debug function is not support\n"); + return -1; + } + + ret = wmt_lib_met_cmd(met_ctrl); + if (ret) { + WMT_ERR_FUNC("send MET ctrl command fail(%d)\n", ret); + return -1; + } + + p_devwmt = &gDevWmt; + p_thread = &gDevWmt.met_thread; + if (met_ctrl & 0x1) { + /*met enable*/ + /* Create mtk_wmt_met thread */ + osal_strncpy(p_thread->threadName, "mtk_wmt_met", sizeof(p_thread->threadName)); + p_devwmt->met_log_ctrl = log_ctrl; + p_thread->pThreadData = (PVOID) p_devwmt; + p_thread->pThreadFunc = (PVOID) met_thread; + ret = osal_thread_create(p_thread); + if (ret) { + WMT_ERR_FUNC("osal_thread_create(0x%p) fail(%d)\n", p_thread, ret); + return -1; + } + /* start running mtk_wmt_met */ + ret = osal_thread_run(p_thread); + if (ret) { + WMT_ERR_FUNC("osal_thread_run(0x%p) fail(%d)\n", p_thread, ret); + return -1; + } + } else { + /*met disable*/ + /* stop running mtk_wmt_met */ + ret = osal_thread_stop(p_thread); + if (ret) { + WMT_ERR_FUNC("osal_thread_stop(0x%p) fail(%d)\n", p_thread, ret); + return -1; + } + } + + return 0; +} + +VOID wmt_lib_set_ext_ldo(UINT32 flag) +{ + gDevWmt.ext_ldo_flag = flag; +} + +UINT32 wmt_lib_get_ext_ldo(VOID) +{ + return gDevWmt.ext_ldo_flag; +} + +static VOID wmt_lib_utc_sync_timeout_handler(timer_handler_arg arg) +{ + schedule_work(&gDevWmt.utcSyncWorker); +} + +static VOID wmt_lib_utc_sync_worker_handler(struct work_struct *work) +{ + wmt_lib_utc_time_sync(); +} + +INT32 wmt_lib_fw_log_ctrl(enum wmt_fw_log_type type, UINT8 onoff, UINT8 level) +{ + 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 -1; + } + + pSignal = &pOp->signal; + pSignal->timeoutValue = 0; + pOp->op.opId = WMT_OPID_FW_LOG_CTRL; + pOp->op.au4OpData[0] = type; + pOp->op.au4OpData[1] = onoff; + pOp->op.au4OpData[2] = level; + + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + wmt_lib_put_op_to_free_queue(pOp); + return -2; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + if (bRet == MTK_WCN_BOOL_FALSE) { + WMT_WARN_FUNC("OPID(%d) fail\n", pOp->op.opId); + return -3; + } + WMT_DBG_FUNC("OPID(%d) ok\n", pOp->op.opId); + + return 0; +} + +INT32 wmt_lib_gps_mcu_ctrl(PUINT8 p_tx_data_buf, UINT32 tx_data_len, PUINT8 p_rx_data_buf, + UINT32 rx_data_buf_len, PUINT32 p_rx_data_len) +{ + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal; + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_DBG_FUNC("get_free_lxop fail\n"); + return -1; + } + + pSignal = &pOp->signal; + pSignal->timeoutValue = MAX_WMT_OP_TIMEOUT; + pOp->op.opId = WMT_OPID_GPS_MCU_CTRL; + pOp->op.au4OpData[0] = (SIZE_T)p_tx_data_buf; + pOp->op.au4OpData[1] = tx_data_len; + pOp->op.au4OpData[2] = (SIZE_T)p_rx_data_buf; + pOp->op.au4OpData[3] = rx_data_buf_len; + pOp->op.au4OpData[4] = (SIZE_T)p_rx_data_len; + 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 (bRet == MTK_WCN_BOOL_FALSE) { + WMT_WARN_FUNC("WMT_OPID_GPS_MCU_CTRL fail(%zu)\n", pOp->op.au4OpData[5]); + return -1; + } + + return 0; +} + +VOID wmt_lib_print_wmtd_op_history(VOID) +{ + osal_op_history_print(&gDevWmt.wmtd_op_history, "wmtd_thread"); +} + +VOID wmt_lib_print_worker_op_history(VOID) +{ + osal_op_history_print(&gDevWmt.worker_op_history, "wmtd_worker_thread"); +} +VOID wmt_lib_set_blank_status(UINT32 on_off_flag) +{ + wmt_core_set_blank_status(on_off_flag); +} + +UINT32 wmt_lib_get_blank_status(VOID) +{ + return wmt_core_get_blank_status(); +} + +INT32 wmt_lib_blank_status_ctrl(UINT32 on_off_flag) +{ + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal; + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_DBG_FUNC("get_free_lxop fail\n"); + return -1; + } + + pSignal = &pOp->signal; + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + WMT_DBG_FUNC("WMT_OPID_BLANK_STATUS_CTRL on_off_flag(0x%x)\n\n", on_off_flag); + pOp->op.opId = WMT_OPID_BLANK_STATUS_CTRL; + pOp->op.au4OpData[0] = on_off_flag; + 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 (bRet != MTK_WCN_BOOL_FALSE) { + WMT_DBG_FUNC("WMT_OPID_BLANK_STATUS_CTRL on_off_flag(0x%x) ok\n", on_off_flag); + return 0; + } + WMT_WARN_FUNC("WMT_OPID_BLANK_STATUS_CTRL on_off_flag(0x%x) bRet(%d)\n", on_off_flag, bRet); + return -1; +} + +/** + * Desinged for native service to get number of patches + * resides in /vendor/firmware + */ +INT32 wmt_lib_get_vendor_patch_num(VOID) +{ + return gDevWmt.patch_table.num; +} + +INT32 wmt_lib_set_vendor_patch_version(struct wmt_vendor_patch *p) +{ + struct vendor_patch_table *table = &(gDevWmt.patch_table); + struct wmt_vendor_patch *patch = table->patch; + + if (patch == NULL) { + INT32 init_capacity = 5; + + patch = (struct wmt_vendor_patch *)osal_malloc( + sizeof(struct wmt_vendor_patch) * init_capacity); + if (patch == NULL) { + WMT_ERR_FUNC("[oom]set vendor patch version"); + return -1; + } + + table->patch = patch; + table->capacity = init_capacity; + table->num = 0; + + table->active_version = (PUINT8 *)osal_malloc(sizeof(PUINT8) * init_capacity); + if (table->active_version == NULL) { + osal_free(table->patch); + table->patch = NULL; + WMT_ERR_FUNC("[oom]alloc active patch"); + return -1; + } + osal_memset(table->active_version, 0, sizeof(PUINT8) * init_capacity); + } + + if (table->capacity == table->num) { + WMT_ERR_FUNC("reach to limit"); + return -1; + } + + /* copy patch info to table */ + patch = patch + table->num; + patch->type = p->type; + osal_strncpy(patch->file_name, p->file_name, sizeof(p->file_name)); + osal_strncpy(patch->version, p->version, sizeof(p->version)); + + table->num++; + WMT_INFO_FUNC("set version %s %s %d", + patch->file_name, patch->version, patch->type); + return 0; +} + +INT32 wmt_lib_get_vendor_patch_version(struct wmt_vendor_patch *p) +{ + struct vendor_patch_table *table = &(gDevWmt.patch_table); + + if (p->id >= table->num || p->id < 0) { + WMT_ERR_FUNC("id %d out of range", p->id); + return -1; + } + + osal_memcpy(p, &table->patch[p->id], sizeof(struct wmt_vendor_patch)); + WMT_INFO_FUNC("get version: %s %s t:%d", + p->file_name, p->version, p->type); + return 0; +} + +INT32 wmt_lib_set_check_patch_status(INT32 status) +{ + gDevWmt.patch_table.status = status; + return 0; +} + +INT32 wmt_lib_get_check_patch_status(VOID) +{ + return gDevWmt.patch_table.status; +} + +INT32 wmt_lib_set_active_patch_version(struct wmt_vendor_patch *p) +{ + struct vendor_patch_table *table = &(gDevWmt.patch_table); + + if (p->id < 0 || p->id >= table->num) { + WMT_ERR_FUNC("patch id: %d is invalid. num = %d", p->id, table->num); + return -1; + } + + if (table->active_version == NULL) { + WMT_ERR_FUNC("active version is NULL"); + return -1; + } + + if (table->active_version[p->id] == NULL) { + table->active_version[p->id] = osal_malloc(sizeof(UINT8) * (WMT_FIRMWARE_VERSION_LENGTH + 1)); + if (table->active_version[p->id] == NULL) { + WMT_ERR_FUNC("oom when alloc active_version"); + return -1; + } + } else if (osal_strcmp(p->version, table->active_version[p->id]) == 0) + return 0; + + wmt_lib_set_need_update_patch_version(1); + osal_strncpy(table->active_version[p->id], p->version, WMT_FIRMWARE_VERSION_LENGTH + 1); + return 0; +} + +INT32 wmt_lib_get_active_patch_version(struct wmt_vendor_patch *p) +{ + struct vendor_patch_table *table = &(gDevWmt.patch_table); + INT32 id = p->id; + + if (id >= table->num || id < 0) { + WMT_ERR_FUNC("id %d out of range", p->id); + return -1; + } + if (table->active_version[id] == NULL) { + WMT_ERR_FUNC("active_version is null: id = %d", id); + return -1; + } + + osal_memcpy(p, &table->patch[id], sizeof(struct wmt_vendor_patch)); + osal_strncpy(p->version, table->active_version[id], + WMT_FIRMWARE_VERSION_LENGTH + 1); + WMT_INFO_FUNC("get active version: %s %s t:%d id:%d", + p->file_name, p->version, p->type, id); + return 0; +} + +INT32 wmt_lib_get_need_update_patch_version(VOID) +{ + return gDevWmt.patch_table.need_update; +} + + +INT32 wmt_lib_set_need_update_patch_version(INT32 need) +{ + gDevWmt.patch_table.need_update = need > 0 ? 1 : 0; + return 0; +} + +VOID mtk_lib_set_mcif_mpu_protection(MTK_WCN_BOOL enable) +{ + mtk_consys_set_mcif_mpu_protection(enable); +} + +static VOID wmt_lib_assert_work_cb(struct work_struct *work) +{ + struct assert_work_st *a = &wmt_assert_work; + + wmt_lib_trigger_assert_keyword(a->type, a->reason, a->keyword); +} + +VOID wmt_lib_trigger_assert_keyword_delay(ENUM_WMTDRV_TYPE_T type, UINT32 reason, PUINT8 keyword) +{ + struct assert_work_st *a = &wmt_assert_work; + + a->type = type; + a->reason = reason; + if (snprintf(a->keyword, sizeof(a->keyword), "%s", keyword) < 0) { + WMT_INFO_FUNC("snprintf a->keyword fail\n"); + } else { + WMT_ERR_FUNC("Assert: type = %d, reason = %d, keyword = %s", type, reason, keyword); + schedule_work(&(a->work)); + } +} + +INT32 wmt_lib_dmp_consys_state(P_CONSYS_STATE_DMP_INFO dmp_info, + unsigned int cpupcr_times, unsigned int slp_ms) +{ + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_TRUE; + P_OSAL_SIGNAL pSignal; + P_CONSYS_STATE_DMP_OP dmp_op = NULL; + P_CONSYS_STATE_DMP_OP tmp_op; + int i, wait_ms = 1000, tmp; + struct consys_state_dmp_req *p_req = &gDevWmt.state_dmp_req; + + + if (cpupcr_times > WMT_LIB_DMP_CONSYS_MAX_TIMES) { + pr_warn("dump too many times [%d]\n", cpupcr_times); + return MTK_WCN_BOOL_FALSE; + } + + /* make sure: */ + /* 1. consys already power on */ + /* 2. consys register is readable */ + if (wmt_lib_get_drv_status(WMTDRV_TYPE_WMT) != DRV_STS_FUNC_ON + || osal_test_bit(WMT_STAT_PWR, &gDevWmt.state) == 0) { + return MTK_WCN_BOOL_FALSE; + } + + for (i = 0; i < WMT_LIB_DMP_SLOT; i++) { + tmp_op = &p_req->consys_ops[i]; + if (osal_trylock_sleepable_lock(&tmp_op->lock) == 1) { + if (tmp_op->status == WMT_DUMP_STATE_NONE) { + tmp = atomic_add_return(1, &p_req->version); + dmp_op = tmp_op; + dmp_op->status = WMT_DUMP_STATE_SCHEDULED; + dmp_op->version = tmp; + } + osal_unlock_sleepable_lock(&tmp_op->lock); + if (dmp_op != NULL) + break; + } + } + + if (dmp_op == NULL) + return MTK_WCN_BOOL_FALSE; + + memset(&dmp_op->dmp_info, 0, sizeof(struct consys_state_dmp_info)); + dmp_op->times = cpupcr_times; + dmp_op->cpu_sleep_ms = slp_ms; + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_DBG_FUNC("get_free_op fail\n"); + bRet = MTK_WCN_BOOL_FALSE; + goto err; + } + + tmp = cpupcr_times * slp_ms; + if (wait_ms < tmp) + wait_ms = tmp + 300; + + pSignal = &pOp->signal; + pOp->op.opId = WMT_OPID_GET_CONSYS_STATE; + pOp->op.au4OpData[0] = (SIZE_T)dmp_op; + pOp->op.au4OpData[1] = (SIZE_T)dmp_op->version; + pSignal->timeoutValue = wait_ms; + + bRet = wmt_lib_put_act_op(pOp); + + if (bRet == MTK_WCN_BOOL_FALSE) { + WMT_WARN_FUNC("WMT_OPID_GET_CONSYS_STATE failed\n"); + goto err; + } + + memcpy(dmp_info, &dmp_op->dmp_info, sizeof(struct consys_state_dmp_info)); +err: + osal_lock_sleepable_lock(&dmp_op->lock); + dmp_op->status = WMT_DUMP_STATE_NONE; + osal_unlock_sleepable_lock(&dmp_op->lock); + return bRet; +} + +INT32 wmt_lib_reg_readable(VOID) +{ + return wmt_lib_reg_readable_by_addr(0); +} + +INT32 wmt_lib_reg_readable_by_addr(SIZE_T addr) +{ + if (wmt_lib_get_drv_status(WMTDRV_TYPE_WMT) == DRV_STS_POWER_OFF + || osal_test_bit(WMT_STAT_PWR, &gDevWmt.state) == 0) { + return MTK_WCN_BOOL_FALSE; + } + return mtk_consys_check_reg_readable_by_addr(addr); +} + diff --git a/drivers/misc/mediatek/connectivity/common/common_main/include/mtk_wcn_cmb_hw.h b/drivers/misc/mediatek/connectivity/common/common_main/include/mtk_wcn_cmb_hw.h new file mode 100644 index 0000000000000..adbd4399a872e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/include/mtk_wcn_cmb_hw.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \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_ + + +/******************************************************************************* +* 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 + +/******************************************************************************* +* 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/misc/mediatek/connectivity/common/common_main/include/stp_exp.h b/drivers/misc/mediatek/connectivity/common/common_main/include/stp_exp.h new file mode 100644 index 0000000000000..b1c5e69e03a35 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/include/stp_exp.h @@ -0,0 +1,317 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/*! \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.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + + +#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + +#if (WMT_IDC_SUPPORT) +#define CFG_WMT_LTE_COEX_HANDLING 1 +#define CFG_WMT_LTE_ENABLE_MSGID_MAPPING 0 +#else +#define CFG_WMT_LTE_COEX_HANDLING 0 +#endif + +#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 GPSL5_TASK_INDX (6) +#define INFO_TASK_INDX (6) +#define ANT_TASK_INDX (7) +#if CFG_WMT_LTE_COEX_HANDLING +#define COEX_TASK_INDX (8) +#define MTKSTP_MAX_TASK_NUM (9) +#else +#define MTKSTP_MAX_TASK_NUM (8) +#endif + +#define MTKSTP_BUFFER_SIZE (16384) /* Size of RX Queue */ + +#define STP_EXP_HID_API_EXPORT 0 + +#else + +#define STP_EXP_HID_API_EXPORT 1 + +#endif + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + +typedef VOID (*MTK_WCN_STP_EVENT_CB) (VOID); +typedef INT32 (*MTK_WCN_STP_IF_TX) (const PUINT8 data, const UINT32 size, PUINT32 written_size); +/* export for HIF driver */ +typedef VOID(*MTK_WCN_STP_IF_RX)(const PUINT8 data, INT32 size); +typedef INT32 (*MTK_WCN_STP_RX_HAS_PENDING_DATA) (VOID); +typedef INT32 (*MTK_WCN_STP_TX_HAS_PENDING_DATA) (VOID); +typedef P_OSAL_THREAD (*MTK_WCN_STP_RX_THREAD_GET) (VOID); + +typedef enum { + STP_UART_IF_TX = 0, + STP_SDIO_IF_TX = 1, + STP_BTIF_IF_TX = 2, + STP_MAX_IF_TX +} ENUM_STP_TX_IF_TYPE; +#endif +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_receive_data +* DESCRIPTION +* receive data from serial protocol engine +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* RETURNS +* INT32 >= 0: size of data received; < 0: error +*****************************************************************************/ +extern INT32 mtk_wcn_stp_receive_data(PUINT8 buffer, UINT32 length, UINT8 type); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_send_data +* DESCRIPTION +* subfunction send data through STP +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* type [IN] subfunction type +* RETURNS +* INT32 >= 0: length transmitted; < 0: error +*****************************************************************************/ +extern INT32 mtk_wcn_stp_send_data(const PUINT8 buffer, const UINT32 length, const UINT8 type); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_rxqueue_empty +* DESCRIPTION +* Is certain rx queue empty? +* PARAMETERS +* type [IN] subfunction type +* RETURNS +* INT32 0: queue is NOT empyt; !0: queue is empty +*****************************************************************************/ +extern MTK_WCN_BOOL mtk_wcn_stp_is_rxqueue_empty(UINT8 type); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_enable +* DESCRIPTION +* Is STP ready? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:ready, FALSE:not ready +*****************************************************************************/ +extern MTK_WCN_BOOL mtk_wcn_stp_is_ready(VOID); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_parser_data +* DESCRIPTION +* push data to serial transport protocol parser engine +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* RETURNS +* void +*****************************************************************************/ +extern INT32 mtk_wcn_stp_parser_data(PUINT8 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 +* int: 0:successful , -1: fail +*****************************************************************************/ +extern INT32 mtk_wcn_stp_register_if_rx(MTK_WCN_STP_IF_RX func); + +/***************************************************************************** +* 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_register_rx_has_pending_data +* DESCRIPTION +* regiter rx has pending data call back function +* PARAMETERS +* stp_if: SDIO or UART, fnnc: Call back function +* RETURNS +* int: 0:successful , -1: fail +*****************************************************************************/ +extern INT32 mtk_wcn_stp_register_rx_has_pending_data(ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_RX_HAS_PENDING_DATA func); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_register_tx_has_pending_data +* DESCRIPTION +* regiter tx has pending data call back function +* PARAMETERS +* stp_if: SDIO or UART, fnnc: Call back function +* RETURNS +* int: 0:successful , -1: fail +*****************************************************************************/ +extern INT32 mtk_wcn_stp_register_tx_has_pending_data(ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_TX_HAS_PENDING_DATA func); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_register_rx_thread_get +* DESCRIPTION +* regiter rx thread call back function +* PARAMETERS +* stp_if: SDIO or UART, fnnc: Call back function +* RETURNS +* int: 0:successful , -1: fail +*****************************************************************************/ +extern INT32 mtk_wcn_stp_register_rx_thread_get(ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_RX_THREAD_GET func); + +extern INT32 mtk_stp_dbg_poll_cpupcr(UINT32 times, UINT32 sleep, UINT32 cmd); +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#else +extern INT32 _mtk_wcn_stp_receive_data(PUINT8 buffer, UINT32 length, UINT8 type); +extern INT32 _mtk_wcn_stp_send_data_raw(const PUINT8 buffer, const UINT32 length, const UINT8 type); +extern INT32 _mtk_wcn_stp_send_data(const PUINT8 buffer, const UINT32 length, const UINT8 type); +extern MTK_WCN_BOOL _mtk_wcn_stp_is_rxqueue_empty(UINT8 type); +extern MTK_WCN_BOOL _mtk_wcn_stp_is_ready(VOID); +extern INT32 _mtk_wcn_stp_parser_data(PUINT8 buffer, UINT32 length); +extern VOID _mtk_wcn_stp_set_bluez(MTK_WCN_BOOL sdio_flag); +extern INT32 _mtk_wcn_stp_register_tx_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func); +extern INT32 _mtk_wcn_stp_register_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func); +extern INT32 _mtk_wcn_stp_register_if_tx(ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_IF_TX func); +extern INT32 _mtk_wcn_stp_register_if_rx(MTK_WCN_STP_IF_RX func); +extern INT32 _mtk_wcn_stp_coredump_start_get(VOID); +extern INT32 _mtk_wcn_stp_register_rx_has_pending_data(ENUM_STP_TX_IF_TYPE stp_if, + MTK_WCN_STP_RX_HAS_PENDING_DATA func); +extern INT32 _mtk_wcn_stp_register_tx_has_pending_data(ENUM_STP_TX_IF_TYPE stp_if, + MTK_WCN_STP_TX_HAS_PENDING_DATA func); +extern INT32 _mtk_wcn_stp_register_rx_thread_get(ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_RX_THREAD_GET func); + +#endif /* MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT */ + +#endif /* _STP_EXP_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/include/wmt.h b/drivers/misc/mediatek/connectivity/common/common_main/include/wmt.h new file mode 100644 index 0000000000000..c65f504b48b84 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/include/wmt.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef _MTKWMT_H_ +#define _MTKWMT_H_ +#include "wmt_core.h" + +#endif /*_MTKWMT_H_*/ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/include/wmt_exp.h b/drivers/misc/mediatek/connectivity/common/common_main/include/wmt_exp.h new file mode 100644 index 0000000000000..ea08503a02f30 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/include/wmt_exp.h @@ -0,0 +1,450 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _WMT_EXP_H_ +#define _WMT_EXP_H_ + +#include +#include "osal.h" +#include "wmt_plat.h" +#include "osal_typedef.h" +/* not to reference to internal wmt */ +/* #include "wmt_core.h" */ +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#if 1 /* moved from wmt_lib.h */ +#ifndef DFT_TAG +#define DFT_TAG "[WMT-DFT]" +#endif + +#define WMT_LOUD_FUNC(fmt, arg...) \ +do { \ + if (gWmtDbgLvl >= WMT_LOG_LOUD) \ + osal_warn_print(DFT_TAG "[L]%s:" fmt, __func__, ##arg); \ +} while (0) +#define WMT_INFO_FUNC(fmt, arg...) \ +do { \ + if (gWmtDbgLvl >= WMT_LOG_INFO) \ + osal_warn_print(DFT_TAG "[I]%s:" fmt, __func__, ##arg); \ +} while (0) +#define WMT_WARN_FUNC(fmt, arg...) \ +do { \ + if (gWmtDbgLvl >= WMT_LOG_WARN) \ + osal_warn_print(DFT_TAG "[W]%s:" fmt, __func__, ##arg); \ +} while (0) +#define WMT_ERR_FUNC(fmt, arg...) \ +do { \ + if (gWmtDbgLvl >= WMT_LOG_ERR) \ + osal_err_print(DFT_TAG "[E]%s(%d):" fmt, __func__, __LINE__, ##arg); \ +} while (0) +#define WMT_DBG_FUNC(fmt, arg...) \ +do { \ + if (gWmtDbgLvl >= WMT_LOG_DBG) \ + osal_warn_print(DFT_TAG "[D]%s:" fmt, __func__, ##arg); \ +} while (0) +#define WMT_TRC_FUNC(f) \ +do { \ + if (gWmtDbgLvl >= WMT_LOG_DBG) \ + osal_warn_print(DFT_TAG "<%s> <%d>\n", __func__, __LINE__); \ +} while (0) + +#endif + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#if 1 /* moved from wmt_lib.h */ +extern INT32 gWmtDbgLvl; +#endif +extern OSAL_BIT_OP_VAR gBtWifiGpsState; +extern OSAL_BIT_OP_VAR gGpsFmState; +extern UINT32 gWifiProbed; +extern MTK_WCN_BOOL g_pwr_off_flag; +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#if 1 /* moved from wmt_lib.h */ +#define WMT_LOG_LOUD 4 +#define WMT_LOG_DBG 3 +#define WMT_LOG_INFO 2 +#define WMT_LOG_WARN 1 +#define WMT_LOG_ERR 0 +#endif +#define CFG_CORE_INTERNAL_TXRX 0 /*just do TX/RX in host side */ + +#define CFG_WMT_PS_SUPPORT 1 /* moved from wmt_lib.h */ +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + +typedef enum _ENUM_WMTDRV_TYPE_T { + WMTDRV_TYPE_BT = 0, + WMTDRV_TYPE_FM = 1, + WMTDRV_TYPE_GPS = 2, + WMTDRV_TYPE_WIFI = 3, + WMTDRV_TYPE_WMT = 4, + WMTDRV_TYPE_ANT = 5, + WMTDRV_TYPE_STP = 6, + WMTDRV_TYPE_SDIO1 = 7, + WMTDRV_TYPE_SDIO2 = 8, + WMTDRV_TYPE_LPBK = 9, + WMTDRV_TYPE_COREDUMP = 10, + WMTDRV_TYPE_GPSL5 = 11, + WMTDRV_TYPE_MAX +} ENUM_WMTDRV_TYPE_T, *P_ENUM_WMTDRV_TYPE_T; + +/* TODO: [ChangeFeature][GeorgeKuo] Reconsider usage of this type */ +/* TODO: how do we extend for new chip and newer revision? */ +/* TODO: This way is hard to extend */ +typedef enum _ENUM_WMTHWVER_TYPE_T { + WMTHWVER_E1 = 0x0, + WMTHWVER_E2 = 0x1, + WMTHWVER_E3 = 0x2, + WMTHWVER_E4 = 0x3, + WMTHWVER_E5 = 0x4, + WMTHWVER_E6 = 0x5, + WMTHWVER_E7 = 0x6, + WMTHWVER_MAX, + WMTHWVER_INVALID = 0xff +} ENUM_WMTHWVER_TYPE_T, *P_ENUM_WMTHWVER_TYPE_T; + +typedef enum _ENUM_WMTDSNS_TYPE_T { + WMTDSNS_FM_DISABLE = 0, + WMTDSNS_FM_ENABLE = 1, + WMTDSNS_FM_GPS_DISABLE = 2, + WMTDSNS_FM_GPS_ENABLE = 3, + WMTDSNS_MAX +} ENUM_WMTDSNS_TYPE_T, *P_ENUM_WMTDSNS_TYPE_T; + +typedef enum _ENUM_WMTTHERM_TYPE_T { + WMTTHERM_ZERO = 0, + WMTTHERM_ENABLE = WMTTHERM_ZERO + 1, + WMTTHERM_READ = WMTTHERM_ENABLE + 1, + WMTTHERM_DISABLE = WMTTHERM_READ + 1, + WMTTHERM_MAX +} ENUM_WMTTHERM_TYPE_T, *P_ENUM_WMTTHERM_TYPE_T; + +typedef enum _ENUM_WMTMSG_TYPE_T { + WMTMSG_TYPE_POWER_ON = 0, + WMTMSG_TYPE_POWER_OFF = 1, + WMTMSG_TYPE_RESET = 2, + WMTMSG_TYPE_STP_RDY = 3, + WMTMSG_TYPE_HW_FUNC_ON = 4, + WMTMSG_TYPE_MAX +} ENUM_WMTMSG_TYPE_T, *P_ENUM_WMTMSG_TYPE_T; + +typedef VOID(*PF_WMT_CB) (ENUM_WMTDRV_TYPE_T, /* Source driver type */ + ENUM_WMTDRV_TYPE_T, /* Destination driver type */ + ENUM_WMTMSG_TYPE_T, /* Message type */ + /* READ-ONLY buffer. Buffer is allocated and freed by WMT_drv. + * Client can't touch this buffer after this function return. + */ + PVOID, + UINT32 /* Buffer size in unit of byte */ + ); + +typedef enum _SDIO_PS_OP { + OWN_SET = 0, + OWN_CLR = 1, + OWN_STATE = 2, +} SDIO_PS_OP; + +typedef INT32(*PF_WMT_SDIO_PSOP) (SDIO_PS_OP); +typedef INT32(*PF_WMT_SDIO_DEEP_SLEEP)(MTK_WCN_BOOL); +typedef INT32(*PF_WMT_SDIO_DEBUG)(INT32, INT32, UINT32, UINT32); + + +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_IPVER = WMTCHIN_FWVER + 1, + WMTCHIN_ADIE = WMTCHIN_IPVER + 1, + WMTCHIN_MAX, +} ENUM_WMT_CHIPINFO_TYPE_T, *P_ENUM_WMT_CHIPINFO_TYPE_T; + +typedef enum _ENUM_WMT_FLASH_PATCH_CTRL_T { + WMT_FLASH_PATCH_VERSION_GET = 0, + WMT_FLASH_PATCH_DOWNLOAD = WMT_FLASH_PATCH_VERSION_GET + 1, + WMT_FLASH_PATCH_CTRL_MAX, +} ENUM_WMT_FLASH_PATCH_CTRL, *P_ENUM_WMT_FLASH_PATCH_CTRL; + +typedef enum _ENUM_WMT_FLASH_PATCH_SEQ_T { + WMT_FLASH_PATCH_HEAD_PKT = 0, + WMT_FLASH_PATCH_START_PKT = WMT_FLASH_PATCH_HEAD_PKT + 1, + WMT_FLASH_PATCH_CONTINUE_PKT = WMT_FLASH_PATCH_START_PKT + 1, + WMT_FLASH_PATCH_END_PKT = WMT_FLASH_PATCH_CONTINUE_PKT + 1, + WMT_FLASH_PATCH_SEQ_MAX, +} ENUM_WMT_FLASH_PATCH_SEQ, *P_ENUM_WMT_FLASH_PATCH_SEQ; + +typedef enum _ENUM_WMT_FLASH_PATCH_TYPE_T { + WMT_FLASH_PATCH_HIF_SW_EFUSE = 0, + WMT_FLASH_PATCH_GATT = WMT_FLASH_PATCH_HIF_SW_EFUSE + 1, + WMT_FLASH_PATCH_SYSROM = WMT_FLASH_PATCH_GATT + 1, + WMT_FLASH_PATCH_ILM = WMT_FLASH_PATCH_SYSROM + 1, + WMT_FLASH_PATCH_FLP1 = WMT_FLASH_PATCH_ILM + 1, + WMT_FLASH_PATCH_FLP2 = WMT_FLASH_PATCH_FLP1 + 1, + WMT_FLASH_PATCH_TYPE_MAX, +} ENUM_WMT_FLASH_PATCH_TYPE, *P_ENUM_WMT_FLASH_PATCH_TYPE; + +typedef enum _ENUM_WMT_FLASH_PATCH_STATUS_T { + WMT_FLASH_PATCH_VERSION_GET_OK = 0, + WMT_FLASH_PATCH_VERSION_GET_FAIL = WMT_FLASH_PATCH_VERSION_GET_OK + 1, + WMT_FLASH_PATCH_DOWNLOAD_OK = WMT_FLASH_PATCH_VERSION_GET_FAIL + 1, + WMT_FLASH_PATCH_DOWNLOAD_FAIL = WMT_FLASH_PATCH_DOWNLOAD_OK + 1, + WMT_FLASH_PATCH_PARA_ERR = WMT_FLASH_PATCH_DOWNLOAD_FAIL + 1, + WMT_FLASH_PATCH_OP_ERR = WMT_FLASH_PATCH_PARA_ERR + 1, + WMT_FLASH_PATCH_MAX +} ENUM_WMT_FLASH_PATCH_STATUS, *P_ENUM_WMT_FLASH_PATCH_STATUS; + +typedef MTK_WCN_BOOL(*MTK_WCN_WMT_FUNC_CTRL) (ENUM_WMTDRV_TYPE_T type); +typedef INT8(*MTK_WCN_WMT_THERM_CTRL) (ENUM_WMTTHERM_TYPE_T eType); +typedef ENUM_WMTHWVER_TYPE_T(*MTK_WCN_WMT_HWVER_GET) (VOID); +typedef MTK_WCN_BOOL(*MTK_WCN_WMT_DSNS_CTRL) (ENUM_WMTDSNS_TYPE_T eType); +typedef INT32(*MTK_WCN_WMT_MSGCB_REG) (ENUM_WMTDRV_TYPE_T eType, PF_WMT_CB pCb); +typedef INT32(*MTK_WCN_WMT_MSGCB_UNREG) (ENUM_WMTDRV_TYPE_T eType); +typedef INT32(*MTK_WCN_WMT_SDIO_OP_REG) (PF_WMT_SDIO_PSOP own_cb); +typedef INT32(*MTK_WCN_WMT_SDIO_HOST_AWAKE) (VOID); +typedef MTK_WCN_BOOL(*MTK_WCN_WMT_ASSERT) (ENUM_WMTDRV_TYPE_T type, UINT32 reason); +typedef MTK_WCN_BOOL(*MTK_WCN_WMT_ASSERT_TIMEOUT)(ENUM_WMTDRV_TYPE_T type, + UINT32 reason, INT32 timeout); +typedef UINT32(*MTK_WCN_WMT_IC_INFO_GET) (ENUM_WMT_CHIPINFO_TYPE_T type); +typedef INT32 (*MTK_WCN_WMT_PSM_CTRL)(MTK_WCN_BOOL flag); + +typedef ENUM_WMT_FLASH_PATCH_STATUS(*MTK_WCN_WMT_FLASH_PATCH_CTRL)(ENUM_WMT_FLASH_PATCH_CTRL ctrlId, + PUINT8 pBuf, UINT32 length, ENUM_WMT_FLASH_PATCH_SEQ seq, ENUM_WMT_FLASH_PATCH_TYPE type, + PUINT32 version, UINT32 checksum); + +typedef struct _MTK_WCN_WMT_EXP_CB_INFO_ { + MTK_WCN_WMT_FUNC_CTRL wmt_func_on_cb; + MTK_WCN_WMT_FUNC_CTRL wmt_func_off_cb; + MTK_WCN_WMT_THERM_CTRL wmt_therm_ctrl_cb; + MTK_WCN_WMT_HWVER_GET wmt_hwver_get_cb; + MTK_WCN_WMT_DSNS_CTRL wmt_dsns_ctrl_cb; + MTK_WCN_WMT_MSGCB_REG wmt_msgcb_reg_cb; + MTK_WCN_WMT_MSGCB_UNREG wmt_msgcb_unreg_cb; + MTK_WCN_WMT_SDIO_OP_REG wmt_sdio_op_reg_cb; + MTK_WCN_WMT_SDIO_HOST_AWAKE wmt_sdio_host_awake_cb; + MTK_WCN_WMT_ASSERT wmt_assert_cb; + MTK_WCN_WMT_ASSERT_TIMEOUT wmt_assert_timeout_cb; + MTK_WCN_WMT_IC_INFO_GET wmt_ic_info_get_cb; + MTK_WCN_WMT_PSM_CTRL wmt_psm_ctrl_cb; + MTK_WCN_WMT_FLASH_PATCH_CTRL wmt_flash_patch_ctrl_cb; +} MTK_WCN_WMT_EXP_CB_INFO, *P_MTK_WCN_WMT_EXP_CB_INFO; + +#endif + +typedef enum _ENUM_WMTRSTMSG_TYPE_T { + WMTRSTMSG_RESET_START = 0x0, + WMTRSTMSG_RESET_END = 0x1, + WMTRSTMSG_RESET_END_FAIL = 0x2, + WMTRSTMSG_RESET_MAX, + WMTRSTMSG_RESET_INVALID = 0xff +} ENUM_WMTRSTMSG_TYPE_T, *P_ENUM_WMTRSTMSG_TYPE_T; + +typedef enum _ENUM_BT_GPS_ONOFF_STATE_T { + WMT_BT_ON = 0, + WMT_GPS_ON = 1, + WMT_WIFI_ON = 2, + WMT_FM_ON = 3, + WMT_GPS_SUSPEND = 4, + WMT_GPSL5_ON = 5, + WMT_GPSL5_SUSPEND = 6, + WMT_BT_GPS_STATE_MAX, + WMT_BT_GPS_STATE_INVALID = 0xff +} ENUM_BT_GPS_ONOFF_STATE_T, *P_ENUM_BT_GPS_ONOFF_STATE_T; + +#if 1 /* moved from wmt_core.h */ +typedef enum { + WMT_SDIO_SLOT_INVALID = 0, + WMT_SDIO_SLOT_SDIO1 = 1, /* Wi-Fi dedicated SDIO1 */ + WMT_SDIO_SLOT_SDIO2 = 2, + WMT_SDIO_SLOT_MAX +} WMT_SDIO_SLOT_NUM; + +typedef enum { + WMT_SDIO_FUNC_STP = 0, + WMT_SDIO_FUNC_WIFI = 1, + WMT_SDIO_FUNC_MAX +} WMT_SDIO_FUNC_TYPE; +#endif + +typedef INT32(*wmt_wlan_probe_cb) (VOID); +typedef INT32(*wmt_wlan_remove_cb) (VOID); +typedef INT32(*wmt_wlan_bus_cnt_get_cb) (VOID); +typedef INT32(*wmt_wlan_bus_cnt_clr_cb) (VOID); +typedef INT32(*wmt_wlan_emi_mpu_set_protection_cb) (bool); +typedef INT32(*wmt_wlan_is_wifi_drv_own_cb) (VOID); + +typedef struct _MTK_WCN_WMT_WLAN_CB_INFO { + wmt_wlan_probe_cb wlan_probe_cb; + wmt_wlan_remove_cb wlan_remove_cb; + wmt_wlan_bus_cnt_get_cb wlan_bus_cnt_get_cb; + wmt_wlan_bus_cnt_clr_cb wlan_bus_cnt_clr_cb; + wmt_wlan_emi_mpu_set_protection_cb wlan_emi_mpu_set_protection_cb; + wmt_wlan_is_wifi_drv_own_cb wlan_is_wifi_drv_own_cb; +} MTK_WCN_WMT_WLAN_CB_INFO, *P_MTK_WCN_WMT_WLAN_CB_INFO; + +#ifdef CONFIG_MTK_COMBO_ANT +typedef enum _ENUM_WMT_ANT_RAM_CTRL_T { + WMT_ANT_RAM_GET_STATUS = 0, + WMT_ANT_RAM_DOWNLOAD = WMT_ANT_RAM_GET_STATUS + 1, + WMT_ANT_RAM_CTRL_MAX +} ENUM_WMT_ANT_RAM_CTRL, *P_ENUM_WMT_ANT_RAM_CTRL; + +typedef enum _ENUM_WMT_ANT_RAM_SEQ_T { + WMT_ANT_RAM_START_PKT = 1, + WMT_ANT_RAM_CONTINUE_PKT = WMT_ANT_RAM_START_PKT + 1, + WMT_ANT_RAM_END_PKT = WMT_ANT_RAM_CONTINUE_PKT + 1, + WMT_ANT_RAM_SEQ_MAX +} ENUM_WMT_ANT_RAM_SEQ, *P_ENUM_WMT_ANT_RAM_SEQ; + +typedef enum _ENUM_WMT_ANT_RAM_STATUS_T { + WMT_ANT_RAM_NOT_EXIST = 0, + WMT_ANT_RAM_EXIST = WMT_ANT_RAM_NOT_EXIST + 1, + WMT_ANT_RAM_DOWN_OK = WMT_ANT_RAM_EXIST + 1, + WMT_ANT_RAM_DOWN_FAIL = WMT_ANT_RAM_DOWN_OK + 1, + WMT_ANT_RAM_PARA_ERR = WMT_ANT_RAM_DOWN_FAIL + 1, + WMT_ANT_RAM_OP_ERR = WMT_ANT_RAM_PARA_ERR + 1, + WMT_ANT_RAM_MAX +} ENUM_WMT_ANT_RAM_STATUS, *P_ENUM_WMT_ANT_RAM_STATUS; +#endif + +extern INT32 mtk_wcn_wmt_wlan_reg(P_MTK_WCN_WMT_WLAN_CB_INFO pWmtWlanCbInfo); +extern INT32 mtk_wcn_wmt_wlan_unreg(VOID); +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +extern wmt_wlan_probe_cb mtk_wcn_wlan_probe; +extern wmt_wlan_remove_cb mtk_wcn_wlan_remove; +extern wmt_wlan_bus_cnt_get_cb mtk_wcn_wlan_bus_tx_cnt; +extern wmt_wlan_bus_cnt_clr_cb mtk_wcn_wlan_bus_tx_cnt_clr; +extern wmt_wlan_emi_mpu_set_protection_cb mtk_wcn_wlan_emi_mpu_set_protection; +extern wmt_wlan_is_wifi_drv_own_cb mtk_wcn_wlan_is_wifi_drv_own; +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*subsystem function ctrl APIs*/ +extern MTK_WCN_BOOL mtk_wcn_wmt_assert(ENUM_WMTDRV_TYPE_T type, UINT32 reason); + +#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + +extern MTK_WCN_BOOL mtk_wcn_wmt_func_off(ENUM_WMTDRV_TYPE_T type); + +extern MTK_WCN_BOOL mtk_wcn_wmt_func_on(ENUM_WMTDRV_TYPE_T type); + +extern MTK_WCN_BOOL mtk_wcn_wmt_dsns_ctrl(ENUM_WMTDSNS_TYPE_T eType); + +extern MTK_WCN_BOOL mtk_wcn_wmt_assert(ENUM_WMTDRV_TYPE_T type, UINT32 reason); + +extern MTK_WCN_BOOL mtk_wcn_wmt_assert_timeout(ENUM_WMTDRV_TYPE_T type, UINT32 reason, INT32 timeout); + +extern MTK_WCN_BOOL mtk_wcn_wmt_assert_keyword(ENUM_WMTDRV_TYPE_T type, PUINT8 keyword); + +extern MTK_WCN_BOOL mtk_wcn_wmt_do_reset(ENUM_WMTDRV_TYPE_T type); + +extern MTK_WCN_BOOL mtk_wcn_wmt_do_reset_only(ENUM_WMTDRV_TYPE_T type); + +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 UINT32 mtk_wcn_wmt_ic_info_get(ENUM_WMT_CHIPINFO_TYPE_T type); + + +extern INT32 mtk_wcn_wmt_chipid_query(VOID); + +extern INT32 mtk_wcn_wmt_psm_ctrl(MTK_WCN_BOOL flag); +extern ENUM_WMT_FLASH_PATCH_STATUS mtk_wcn_wmt_flash_patch_ctrl(ENUM_WMT_FLASH_PATCH_CTRL ctrlId, + PUINT8 pBuf, UINT32 length, ENUM_WMT_FLASH_PATCH_SEQ seq, ENUM_WMT_FLASH_PATCH_TYPE type, + PUINT32 version, UINT32 checksum); + +#endif +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT +extern INT32 mtk_wcn_wmt_sdio_deep_sleep_flag_cb_reg(PF_WMT_SDIO_DEEP_SLEEP flag_cb); +#endif +extern INT32 mtk_wcn_wmt_sdio_rw_cb_reg(PF_WMT_SDIO_DEBUG reg_rw_cb); + +#ifdef CONFIG_MTK_COMBO_ANT +extern ENUM_WMT_ANT_RAM_STATUS mtk_wcn_wmt_ant_ram_ctrl(ENUM_WMT_ANT_RAM_CTRL ctrlId, PUINT8 pBuf, + UINT32 length, ENUM_WMT_ANT_RAM_SEQ seq); +#endif +extern INT32 wmt_lib_set_aif(enum CMB_STUB_AIF_X aif, MTK_WCN_BOOL share); /* set AUDIO interface options */ +extern VOID wmt_lib_ps_irq_cb(VOID); + +extern VOID mtk_wcn_wmt_func_ctrl_for_plat(UINT32 on, ENUM_WMTDRV_TYPE_T type); + +extern INT32 mtk_wcn_wmt_system_state_reset(VOID); +extern MTK_WCN_BOOL mtk_wcn_set_connsys_power_off_flag(MTK_WCN_BOOL value); +#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT +extern VOID mtk_wcn_wmt_exp_init(VOID); +extern VOID mtk_wcn_wmt_exp_deinit(VOID); +#endif +extern INT8 mtk_wcn_wmt_co_clock_flag_get(VOID); +extern INT32 mtk_wcn_wmt_wifi_fem_cfg_report(PVOID pvInfoBuf); +extern VOID mtk_wcn_wmt_dump_wmtd_backtrace(VOID); +extern UINT32 mtk_wmt_get_gps_lna_pin_num(VOID); +extern VOID mtk_wmt_set_ext_ldo(UINT32 flag); +extern INT32 mtk_wmt_gps_mcu_ctrl(PUINT8 p_tx_data_buf, UINT32 tx_data_len, PUINT8 p_rx_data_buf, + UINT32 rx_data_buf_len, PUINT32 p_rx_data_len); +extern VOID mtk_wcn_wmt_set_mcif_mpu_protection(MTK_WCN_BOOL enable); +extern MTK_WCN_BOOL mtk_wmt_gps_suspend_ctrl(MTK_WCN_BOOL suspend); +extern MTK_WCN_BOOL mtk_wmt_gps_l1_suspend_ctrl(MTK_WCN_BOOL suspend); +extern MTK_WCN_BOOL mtk_wmt_gps_l5_suspend_ctrl(MTK_WCN_BOOL suspend); + +extern INT32 mtk_wcn_wmt_mpu_lock_aquire(VOID); +extern VOID mtk_wcn_wmt_mpu_lock_release(VOID); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _WMT_EXP_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/include/wmt_plat.h b/drivers/misc/mediatek/connectivity/common/common_main/include/wmt_plat.h new file mode 100644 index 0000000000000..1b20ca283c62e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/include/wmt_plat.h @@ -0,0 +1,404 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _WMT_PLAT_H_ +#define _WMT_PLAT_H_ +#include "osal_typedef.h" +#include "stp_exp.h" +#include +#include "mtk_wcn_cmb_hw.h" + +/* #include "mtk_wcn_consys_hw.h" */ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#if 1 /* moved from wmt_exp.h */ +#ifndef DFT_TAG +#define DFT_TAG "[WMT-DFT]" +#endif + +#define WMT_PLAT_LOG_LOUD 4 +#define WMT_PLAT_LOG_DBG 3 +#define WMT_PLAT_LOG_INFO 2 +#define WMT_PLAT_LOG_WARN 1 +#define WMT_PLAT_LOG_ERR 0 + +extern INT32 wmtPlatLogLvl; + +#define WMT_PLAT_PR_LOUD(fmt, arg...) \ +do { \ + if (wmtPlatLogLvl >= WMT_PLAT_LOG_LOUD) \ + pr_info(DFT_TAG "[L]%s:" fmt, __func__, ##arg); \ +} while (0) +#define WMT_PLAT_PR_INFO(fmt, arg...) \ +do { \ + if (wmtPlatLogLvl >= WMT_PLAT_LOG_INFO) \ + pr_info(DFT_TAG "[I]%s:" fmt, __func__, ##arg); \ +} while (0) +#define WMT_PLAT_PR_WARN(fmt, arg...) \ +do { \ + if (wmtPlatLogLvl >= WMT_PLAT_LOG_WARN) \ + pr_warn(DFT_TAG "[W]%s:" fmt, __func__, ##arg); \ +} while (0) +#define WMT_PLAT_PR_ERR(fmt, arg...) \ +do { \ + if (wmtPlatLogLvl >= WMT_PLAT_LOG_ERR) \ + pr_err(DFT_TAG "[E]%s(%d):" fmt, __func__, __LINE__, ##arg); \ +} while (0) +#define WMT_PLAT_PR_DBG(fmt, arg...) \ +do { \ + if (wmtPlatLogLvl >= WMT_PLAT_LOG_DBG) \ + pr_info(DFT_TAG "[D]%s:" fmt, __func__, ##arg); \ +} while (0) + +#endif + +#define CFG_WMT_PS_SUPPORT 1 /* moved from wmt_exp.h */ + +#define CFG_WMT_DUMP_INT_STATUS 0 +#define CONSYS_ENALBE_SET_JTAG 1 + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#if (defined(MT6630) || defined(MT6632)) +#define CONSYS_WMT_REG_SUSPEND_CB_ENABLE 1 +#else +#define CONSYS_WMT_REG_SUSPEND_CB_ENABLE 0 +#endif + +#if defined(MERGE_INTERFACE_SUPPORT) && (defined(MT6628) || defined(MT6630) || defined(MT6632)) +#define MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT 1 +#else +#define MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT 0 +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +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_UART_RX = 13, +#if CFG_WMT_LTE_COEX_HANDLING + PIN_TDM_REQ = 14, +#endif + PIN_ID_MAX +} ENUM_PIN_ID, *P_ENUM_PIN_ID; +#if 0 +typedef enum _ENUM_PIN_ID_ { + PIN_BGF_EINT = 0, + PIN_I2S_GRP = 1, + PIN_GPS_SYNC = 2, + PIN_GPS_LNA = 3, +#if CFG_WMT_LTE_COEX_HANDLING + PIN_TDM_REQ = 4, +#endif + PIN_ID_MAX +} ENUM_PIN_ID, *P_ENUM_PIN_ID; +#endif + +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_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_IN_PU = 9, + PIN_STA_IN_NP = 10, + PIN_STA_IN_H = 11, + PIN_STA_MAX +} ENUM_PIN_STATE, *P_ENUM_PIN_STATE; + +typedef enum _CMB_IF_TYPE_ { + CMB_IF_UART = 0, + CMB_IF_WIFI_SDIO = 1, + CMB_IF_BGF_SDIO = 2, + CMB_IF_BGWF_SDIO = 3, + CMB_IF_TYPE_MAX +} CMB_IF_TYPE, *P_CMB_IF_TYPE; + +typedef INT32(*fp_set_pin) (ENUM_PIN_STATE); + +typedef enum _ENUM_WL_OP_ { + WL_OP_GET = 0, + WL_OP_PUT = 1, + WL_OP_MAX +} ENUM_WL_OP, *P_ENUM_WL_OP; + +typedef enum _ENUM_PALDO_TYPE_ { + BT_PALDO = 0, + WIFI_PALDO = 1, + FM_PALDO = 2, + GPS_PALDO = 3, + PMIC_CHIPID_PALDO = 4, + WIFI_5G_PALDO = 5, + EFUSE_PALDO = 6, + PALDO_TYPE_MAX +} ENUM_PALDO_TYPE, *P_ENUM_PALDO_TYPE; + +typedef enum _ENUM_PALDO_OP_ { + PALDO_OFF = 0, + PALDO_ON = 1, + PALDO_OP_MAX +} ENUM_PALDO_OP, *P_ENUM_PALDO_OP; + +typedef enum _ENUM_HOST_DUMP_STATE_T { + STP_HOST_DUMP_NOT_START = 0, + STP_HOST_DUMP_GET = 1, + STP_HOST_DUMP_GET_DONE = 2, + STP_HOST_DUMP_END = 3, + STP_HOST_DUMP_MAX +} ENUM_HOST_DUMP_STATE, *P_ENUM_HOST_DUMP_STATE_T; + +typedef enum _ENUM_FORCE_TRG_ASSERT_T { + STP_FORCE_TRG_ASSERT_EMI = 0, + STP_FORCE_TRG_ASSERT_DEBUG_PIN = 1, + STP_FORCE_TRG_ASSERT_MAX = 2 +} ENUM_FORCE_TRG_ASSERT_T, *P_ENUM_FORCE_TRG_ASSERT_T; + +typedef enum _ENUM_CHIP_DUMP_STATE_T { + STP_CHIP_DUMP_NOT_START = 0, + STP_CHIP_DUMP_PUT = 1, + STP_CHIP_DUMP_PUT_DONE = 2, + STP_CHIP_DUMP_END = 3, + STP_CHIP_DUMP_MAX +} ENUM_CHIP_DUMP_STATE, *P_ENUM_CHIP_DUMP_STATE_T; + +#define CONSYS_BUS_CLK_STATUS_OFFSET 0x00000100 +#define CONSYS_CPU_CLK_STATUS_OFFSET 0x0000010c +#define CONSYS_DBG_CR1_OFFSET 0x00000408 +#define CONSYS_DBG_CR2_OFFSET 0x0000040c +typedef enum _ENUM_CONNSYS_DEBUG_CR { + CONNSYS_CPU_CLK = 0, + CONNSYS_BUS_CLK = 1, + CONNSYS_DEBUG_CR1 = 2, + CONNSYS_DEBUG_CR2 = 3, + CONNSYS_EMI_REMAP = 4, + CONNSYS_CR_MAX +} ENUM_CONNSYS_DEBUG_CR, *P_ENUM_CONNSYS_DEBUG_CR; + +typedef enum { + WMT_SLEEP_COUNT_TOP = 0, + WMT_SLEEP_COUNT_MCU = 1, + WMT_SLEEP_COUNT_BT = 2, + WMT_SLEEP_COUNT_WF = 3, + WMT_SLEEP_COUNT_GPS = 4, + WMT_SLEEP_COUNT_MAX +} WMT_SLEEP_COUNT_TYPE; + +typedef struct _EMI_CTRL_STATE_OFFSET_ { + UINT32 emi_apmem_ctrl_state; + UINT32 emi_apmem_ctrl_host_sync_state; + UINT32 emi_apmem_ctrl_host_sync_num; + UINT32 emi_apmem_ctrl_chip_sync_state; + UINT32 emi_apmem_ctrl_chip_sync_num; + UINT32 emi_apmem_ctrl_chip_sync_addr; + UINT32 emi_apmem_ctrl_chip_sync_len; + UINT32 emi_apmem_ctrl_chip_print_buff_start; + UINT32 emi_apmem_ctrl_chip_print_buff_len; + UINT32 emi_apmem_ctrl_chip_print_buff_idx; + UINT32 emi_apmem_ctrl_chip_int_status; + UINT32 emi_apmem_ctrl_chip_paded_dump_end; + UINT32 emi_apmem_ctrl_host_outband_assert_w1; + UINT32 emi_apmem_ctrl_chip_page_dump_num; + UINT32 emi_apmem_ctrl_assert_flag; + UINT32 emi_apmem_ctrl_chip_check_sleep; +} EMI_CTRL_STATE_OFFSET, *P_EMI_CTRL_STATE_OFFSET; + +typedef struct _BGF_IRQ_BALANCE_ { + UINT32 counter; + unsigned long flags; + spinlock_t lock; +} BGF_IRQ_BALANCE, *P_BGF_IRQ_BALANCE; + +typedef struct _CONSYS_EMI_ADDR_INFO_ { + UINT32 emi_phy_addr; + UINT32 emi_ap_phy_addr; + UINT32 paged_trace_off; + UINT32 paged_dump_off; + UINT32 full_dump_off; + UINT32 emi_remap_offset; + P_EMI_CTRL_STATE_OFFSET p_ecso; + UINT32 emi_size; + UINT32 pda_dl_patch_flag; + UINT32 emi_met_size; + UINT32 emi_met_data_offset; + UINT32 emi_core_dump_offset; + UINT32 emi_direct_path_ap_phy_addr; + UINT32 emi_direct_path_size; + UINT32 emi_ram_bt_buildtime_offset; + UINT32 emi_ram_wifi_buildtime_offset; + UINT32 emi_ram_mcu_buildtime_offset; + UINT32 emi_patch_mcu_buildtime_offset; +} CONSYS_EMI_ADDR_INFO, *P_CONSYS_EMI_ADDR_INFO; + +typedef struct _GPIO_TDM_REQ_INFO_ { + UINT32 ant_sel_index; + UINT32 gpio_number; + UINT32 cr_address; +} GPIO_TDM_REQ_INFO, *P_GPIO_TDM_REQ_INFO; + +struct consys_sw_state { + UINT16 clock_hif_ctrl; + UINT16 clock_umac_ctrl; + UINT32 resource_disable_sleep; + UINT32 clock_mcu; + UINT32 info_time; + UINT8 is_gating; + UINT8 sub_system; +}; + +typedef struct consys_state { + UINT32 lp[2]; + UINT32 gating[2]; + UINT64 sleep_counter[WMT_SLEEP_COUNT_MAX]; + UINT64 sleep_timer[WMT_SLEEP_COUNT_MAX]; + struct consys_sw_state sw_state; +} CONSYS_STATE, *P_CONSYS_STATE; + + +typedef VOID(*irq_cb) (VOID); +typedef INT32(*device_audio_if_cb) (enum CMB_STUB_AIF_X aif, MTK_WCN_BOOL share); +typedef VOID(*func_ctrl_cb) (UINT32 on, UINT32 type); +typedef long (*thermal_query_ctrl_cb) (VOID); +typedef INT32(*trigger_assert_cb) (UINT32 type, UINT32 reason); +typedef INT32(*deep_idle_ctrl_cb) (UINT32); + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +extern INT32 gWmtDbgLvl; +extern struct device *wmt_dev; +#ifdef CFG_WMT_READ_EFUSE_VCN33 +extern INT32 wmt_set_pmic_voltage(UINT32 level); +#endif +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +INT32 wmt_plat_init(P_PWR_SEQ_TIME pPwrSeqTime, UINT32 co_clock_type); +INT32 wmt_plat_deinit(VOID); +INT32 wmt_plat_merge_if_flag_get(VOID); +INT32 wmt_plat_set_comm_if_type(ENUM_STP_TX_IF_TYPE type); +INT32 wmt_plat_merge_if_flag_ctrl(UINT32 enagle); +ENUM_STP_TX_IF_TYPE wmt_plat_get_comm_if_type(VOID); + +INT32 wmt_plat_pwr_ctrl(ENUM_FUNC_STATE state); + +INT32 wmt_plat_gpio_ctrl(ENUM_PIN_ID id, ENUM_PIN_STATE state); + +INT32 wmt_plat_eirq_ctrl(ENUM_PIN_ID id, ENUM_PIN_STATE state); + +INT32 wmt_plat_wake_lock_ctrl(ENUM_WL_OP opId); +INT32 wmt_plat_sdio_ctrl(UINT32 sdioPortNum, ENUM_FUNC_STATE on); + +INT32 wmt_plat_audio_ctrl(enum CMB_STUB_AIF_X state, enum CMB_STUB_AIF_CTRL ctrl); +VOID wmt_lib_plat_irq_cb_reg(irq_cb bgf_irq_cb); +VOID wmt_lib_plat_aif_cb_reg(device_audio_if_cb aif_ctrl_cb); + +VOID wmt_plat_irq_cb_reg(irq_cb bgf_irq_cb); +VOID wmt_plat_aif_cb_reg(device_audio_if_cb aif_ctrl_cb); +VOID wmt_plat_func_ctrl_cb_reg(func_ctrl_cb subsys_func_ctrl); +VOID wmt_plat_thermal_ctrl_cb_reg(thermal_query_ctrl_cb thermal_query_ctrl); +VOID wmt_plat_trigger_assert_cb_reg(trigger_assert_cb trigger_assert); +VOID wmt_plat_deep_idle_ctrl_cb_reg(deep_idle_ctrl_cb deep_idle_ctrl); + +INT32 wmt_plat_soc_paldo_ctrl(ENUM_PALDO_TYPE ePt, ENUM_PALDO_OP ePo); +UINT8 *wmt_plat_get_emi_virt_add(UINT32 offset); +#if CONSYS_ENALBE_SET_JTAG +UINT32 wmt_plat_jtag_flag_ctrl(UINT32 en); +#endif +#if CFG_WMT_DUMP_INT_STATUS +VOID wmt_plat_BGF_irq_dump_status(VOID); +MTK_WCN_BOOL wmt_plat_dump_BGF_irq_status(VOID); +#endif +P_CONSYS_EMI_ADDR_INFO wmt_plat_get_emi_phy_add(VOID); +UINT32 wmt_plat_read_cpupcr(VOID); +UINT32 wmt_plat_read_dmaregs(UINT32); +INT32 wmt_plat_set_host_dump_state(ENUM_HOST_DUMP_STATE state); +UINT32 wmt_plat_force_trigger_assert(ENUM_FORCE_TRG_ASSERT_T type); +INT32 wmt_plat_update_host_sync_num(VOID); +INT32 wmt_plat_get_dump_info(UINT32 offset); +INT32 wmt_plat_write_emi_l(UINT32 offset, UINT32 value); +UINT32 wmt_plat_get_soc_chipid(VOID); +INT32 wmt_plat_get_adie_chipid(VOID); +UINT32 wmt_plat_soc_co_clock_flag_get(VOID); +INT32 wmt_plat_set_dbg_mode(UINT32 flag); +INT32 wmt_plat_set_dynamic_dumpmem(PUINT32 buf); +#if CFG_WMT_LTE_COEX_HANDLING +INT32 wmt_plat_get_tdm_antsel_index(VOID); +#endif +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _WMT_PLAT_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/include/wmt_plat_stub.h b/drivers/misc/mediatek/connectivity/common/common_main/include/wmt_plat_stub.h new file mode 100644 index 0000000000000..59d30fa735a2e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/include/wmt_plat_stub.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + + +#ifndef _WMT_PLAT_STUB_H_ +#define _WMT_PLAT_STUB_H_ + + +INT32 wmt_plat_audio_ctrl(enum CMB_STUB_AIF_X state, enum CMB_STUB_AIF_CTRL ctrl); + +INT32 wmt_plat_stub_init(VOID); + +#endif /*_WMT_PLAT_STUB_H_*/ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/bgw_desense.c b/drivers/misc/mediatek/connectivity/common/common_main/linux/bgw_desense.c new file mode 100644 index 0000000000000..35d6a7c6a00e1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/bgw_desense.c @@ -0,0 +1,141 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include "bgw_desense.h" + +static struct sock *g_nl_sk; +/* static struct sockaddr_nl src_addr, des_addr; */ +/* static struct iovec iov; */ +static int pid; +/* static struct msghdr msg; */ + +void bgw_destroy_netlink_kernel(void) +{ + if (g_nl_sk != NULL) { + /* sock_release(g_nl_sk->sk_socket); */ + netlink_kernel_release(g_nl_sk); + MSG("release socket\n"); + return; + } + ERR("no socket yet\n"); +} + +void send_command_to_daemon(const int command /*struct sk_buff *skb */) +{ + struct nlmsghdr *nlh = NULL; + struct sk_buff *nl_skb = NULL; + int res; + + MSG("here we will send command to native daemon\n"); + if (!g_nl_sk) { + ERR("invalid socket\n"); + return; + } + if (pid == 0) { + ERR("invalid native process pid\n"); + return; + } + /*alloc data buffer for sending to native */ + /*malloc data space at least 1500 bytes, which is ethernet data length */ + nl_skb = alloc_skb(NLMSG_SPACE(MAX_NL_MSG_LEN), GFP_ATOMIC); + if (nl_skb == NULL) { + ERR("malloc skb error\n"); + return; + } + MSG("malloc data space done\n"); + +/* nlh = NLMSG_PUT(nl_skb, 0, 0, 0, NLMSG_SPACE(1500)-sizeof(struct nlmsghdr)); */ + nlh = nlmsg_put(nl_skb, 0, 0, 0, MAX_NL_MSG_LEN, 0); + if (nlh == NULL) { + MSG("nlh is NULL\n"); + kfree_skb(nl_skb); + return; + } + NETLINK_CB(nl_skb).portid = 0; + +/* memcpy(NLMSG_DATA(nlh), ACK, 5); */ + *(char *)NLMSG_DATA(nlh) = command; + res = netlink_unicast(g_nl_sk, nl_skb, pid, MSG_DONTWAIT); + if (res == 0) { + MSG("send to user space process error\n"); + return; + } + ERR("send to user space process done, data length = %d\n", res); +} + +static void nl_data_handler(struct sk_buff *__skb) +{ + struct sk_buff *skb = NULL; + struct nlmsghdr *nlh = NULL; + int i; + int len; + char str[128]; + + MSG("we got netlink message\n"); + len = NLMSG_SPACE(MAX_NL_MSG_LEN); + skb = skb_get(__skb); + if (skb == NULL) { + ERR("skb_get return NULL"); + return; + } + if (skb->len >= NLMSG_SPACE(0)) { /*presume there is 5byte payload at leaset */ + MSG("length is enough\n"); + nlh = nlmsg_hdr(skb); /* point to data which include in skb */ + memcpy(str, NLMSG_DATA(nlh), sizeof(str)); + for (i = 0; i < 3; i++) + MSG("str[%d = %c]", i, str[i]); + MSG("str[0] = %d, str[1] = %d, str[2] = %d\n", str[0], str[1], str[2]); + if (str[0] == 'B' && str[1] == 'G' && str[2] == 'W') { + MSG("got native daemon init command, record it's pid\n"); + pid = nlh->nlmsg_pid; /*record the native process PID */ + MSG("native daemon pid is %d\n", pid); + } else { + ERR("this is not BGW message, ignore it\n"); + return; + } + } else { + ERR("not engouth data length\n"); + return; + } + + kfree_skb(skb); + + send_command_to_daemon(ACK); +} + +int bgw_init_socket(void) +{ + struct netlink_kernel_cfg cfg; + + memset(&cfg, 0, sizeof(cfg)); + cfg.input = nl_data_handler; + + g_nl_sk = __netlink_kernel_create(&init_net, NETLINK_TEST, THIS_MODULE, &cfg); + + if (g_nl_sk == NULL) { + ERR("netlink_kernel_create error\n"); + return -1; + } + MSG("netlink_kernel_create ok\n"); + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/fw_log_wmt.c b/drivers/misc/mediatek/connectivity/common/common_main/linux/fw_log_wmt.c new file mode 100644 index 0000000000000..bf495f83f06ed --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/fw_log_wmt.c @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH +#include "fw_log_wmt.h" +#include "connsys_debug_utility.h" +#include +#include +#include +#include +#include "wmt_lib.h" + +#define DRIVER_NAME "fw_log_wmt" +#define WMT_FW_LOG_IOC_MAGIC 0xfc +#define WMT_FW_LOG_IOCTL_ON_OFF _IOW(WMT_FW_LOG_IOC_MAGIC, 0, int) +#define WMT_FW_LOG_IOCTL_SET_LEVEL _IOW(WMT_FW_LOG_IOC_MAGIC, 1, int) + +static dev_t gDevId; +static struct cdev gLogCdev; +static struct class *fw_log_wmt_class; +static struct device *fw_log_wmt_dev; +static wait_queue_head_t wq; + +static int fw_log_wmt_open(struct inode *inode, struct file *file) +{ + pr_info("%s\n", __func__); + return 0; +} + +static int fw_log_wmt_close(struct inode *inode, struct file *file) +{ + pr_info("%s\n", __func__); + return 0; +} + +static ssize_t fw_log_wmt_read(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + ssize_t size = 0; + + pr_debug("%s\n", __func__); + size = connsys_log_read_to_user(CONNLOG_TYPE_MCU, buf, count); + return size; +} + +static ssize_t fw_log_wmt_write(struct file *filp, const char __user *buf, + size_t count, loff_t *f_pos) +{ + pr_debug("%s\n", __func__); + return 0; +} + +static unsigned int fw_log_wmt_poll(struct file *filp, poll_table *wait) +{ + pr_debug("%s\n", __func__); + + poll_wait(filp, &wq, wait); + if (connsys_log_get_buf_size(CONNLOG_TYPE_MCU) > 0) + return POLLIN | POLLRDNORM; + + return 0; +} + +static long fw_log_wmt_unlocked_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg) +{ + long ret = 0; + + switch (cmd) { + case WMT_FW_LOG_IOCTL_ON_OFF: + pr_debug("ioctl: WMT_FW_LOG_IOCTL_ON_OFF(%lu)", arg); + if (arg == 0 || arg == 1) + wmt_lib_fw_log_ctrl(WMT_FWLOG_MCU, (unsigned char)arg, 0xFF); + break; + case WMT_FW_LOG_IOCTL_SET_LEVEL: + pr_debug("ioctl: WMT_FW_LOG_IOCTL_SET_LEVEL(%lu)", arg); + if (arg <= 4) + wmt_lib_fw_log_ctrl(WMT_FWLOG_MCU, 0xFF, (unsigned char)arg); + break; + default: + /*no action*/ + break; + } + return ret; +} + +#ifdef CONFIG_COMPAT +static long fw_log_wmt_compat_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg) +{ + return fw_log_wmt_unlocked_ioctl(filp, cmd, arg); +} +#endif + +const struct file_operations gLogFops = { + .open = fw_log_wmt_open, + .release = fw_log_wmt_close, + .read = fw_log_wmt_read, + .write = fw_log_wmt_write, + .poll = fw_log_wmt_poll, + .unlocked_ioctl = fw_log_wmt_unlocked_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = fw_log_wmt_compat_ioctl, +#endif +}; + +static void fw_log_wmt_event_cb(void) +{ + wake_up_interruptible(&wq); +} + +int fw_log_wmt_init(void) +{ + int cdevErr = -1; + int ret = -1; + + ret = alloc_chrdev_region(&gDevId, 0, 1, DRIVER_NAME); + if (ret) + pr_err("fail to alloc_chrdev_region\n"); + + cdev_init(&gLogCdev, &gLogFops); + gLogCdev.owner = THIS_MODULE; + + cdevErr = cdev_add(&gLogCdev, gDevId, 1); + if (cdevErr) { + pr_err("cdev_add() fails (%d)\n", cdevErr); + goto error; + } + + fw_log_wmt_class = class_create(THIS_MODULE, DRIVER_NAME); + if (IS_ERR(fw_log_wmt_class)) { + pr_err("class_create fail\n"); + goto error; + } + + fw_log_wmt_dev = device_create(fw_log_wmt_class, NULL, gDevId, NULL, + DRIVER_NAME); + if (IS_ERR(fw_log_wmt_dev)) { + pr_err("device_create fail\n"); + goto error; + } + + init_waitqueue_head(&wq); + ret = connsys_log_init(CONNLOG_TYPE_MCU); + if (ret) + pr_err("fail to connsys_log_init\n"); + + ret = connsys_log_register_event_cb(CONNLOG_TYPE_MCU, + fw_log_wmt_event_cb); + if (ret) + pr_err("fail to connsys_log_register_event_cb\n"); + + return 0; + +error: + if (!(IS_ERR(fw_log_wmt_dev))) + device_destroy(fw_log_wmt_class, gDevId); + if (!(IS_ERR(fw_log_wmt_class))) { + class_destroy(fw_log_wmt_class); + fw_log_wmt_class = NULL; + } + + if (cdevErr == 0) + cdev_del(&gLogCdev); + if (ret == 0) + unregister_chrdev_region(gDevId, 1); + pr_err("fw_log_wmt_init fail\n"); + return -1; +} +EXPORT_SYMBOL(fw_log_wmt_init); + +void fw_log_wmt_deinit(void) +{ + connsys_log_deinit(CONNLOG_TYPE_MCU); + if (fw_log_wmt_dev) { + device_destroy(fw_log_wmt_class, gDevId); + fw_log_wmt_dev = NULL; + } + + if (fw_log_wmt_class) { + class_destroy(fw_log_wmt_class); + fw_log_wmt_class = NULL; + } + + cdev_del(&gLogCdev); + unregister_chrdev_region(gDevId, 1); + pr_warn("fw_log_wmt_driver_deinit done\n"); +} +EXPORT_SYMBOL(fw_log_wmt_deinit); +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/hif_sdio.c b/drivers/misc/mediatek/connectivity/common/common_main/linux/hif_sdio.c new file mode 100644 index 0000000000000..207064aa7f87e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/hif_sdio.c @@ -0,0 +1,2924 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/* + * + * 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) +#define HIF_SDIO_SUPPORT_SUSPEND (1) +#define HIF_SDIO_SUPPORT_WAKEUP (0) + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include +#include "hif_sdio.h" +#include "wmt_gpio.h" +/* #include "hif_sdio_chrdev.h" */ +#include +#include +#include + +#define mmc_power_up_ext(x) +#define mmc_power_off_ext(x) +MTK_WCN_BOOL g_hif_deep_sleep_flag = MTK_WCN_BOOL_FALSE; + +#ifndef MMC_CARD_REMOVED +#define MMC_CARD_REMOVED (1<<4) +#endif + +#ifndef mmc_card_removed +#define mmc_card_removed(c) ((c) && ((c)->state & MMC_CARD_REMOVED)) +#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 +******************************************************************************** +*/ + + +/******************************************************************************* +* 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 INT32 hif_sdio_suspend(struct device *dev); + +static INT32 hif_sdio_resume(struct device *dev); +#endif +static INT32 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 _osal_inline_ INT32 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 _osal_inline_ INT32 hif_sdio_find_probed_list_index_by_func(struct sdio_func *func); + +#if 0 /* TODO:[ChangeFeature][George] remove obsolete function? */ +static INT32 hif_sdio_find_probed_list_index_by_clt_index(INT32 clt_index); +#endif + +static _osal_inline_ INT32 hif_sdio_find_probed_list_index_by_id_func(UINT16 vendor, UINT16 device, + UINT16 func_num); + +static _osal_inline_ VOID hif_sdio_init_clt_list(INT32 index); + +static _osal_inline_ INT32 hif_sdio_find_clt_list_index(UINT16 vendor, UINT16 device, UINT16 func_num); + +static _osal_inline_ INT32 hif_sdio_check_supported_sdio_id(UINT16 vendor, UINT16 device); + +static _osal_inline_ INT32 hif_sdio_check_duplicate_sdio_id(UINT16 vendor, UINT16 device, UINT16 func_num); + +static _osal_inline_ INT32 hif_sdio_add_clt_list(PINT32 clt_index_p, const MTK_WCN_HIF_SDIO_CLTINFO *pinfo, + UINT32 tbl_index); + +static _osal_inline_ INT32 hif_sdio_stp_on(VOID); + +static _osal_inline_ INT32 hif_sdio_stp_off(VOID); + +static _osal_inline_ INT32 hif_sdio_wifi_on(VOID); + +static _osal_inline_ INT32 hif_sdio_wifi_off(VOID); + +static _osal_inline_ INT32 hif_sdio_deep_sleep_info_init(VOID); + +static _osal_inline_ INT32 hif_sdio_deep_sleep_info_set_act(UINT32 chipid, UINT16 func_num, + MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT8 act_flag); + +static INT32 _hif_sdio_wake_up_ctrl(MTK_WCN_HIF_SDIO_CLTCTX ctx); + +static _osal_inline_ INT32 wmt_tra_sdio_update(VOID); + +static _osal_inline_ INT32 hif_sdio_deep_sleep_info_dmp(MTK_WCN_HIF_SDIO_DS_INFO *p_ds_info); + +static _osal_inline_ VOID hif_sdio_dump_probe_list(VOID); + +static _osal_inline_ VOID hif_sdio_init_probed_list(INT32 index); + +/******************************************************************************* +* 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)}, + + /* MT6630 *//* SDIO1: Wi-Fi, SDIO2: BGF */ + {SDIO_DEVICE(0x037A, 0x6630)}, + + /* MT6632 *//* SDIO1: Wi-Fi */ + {SDIO_DEVICE(0x037A, 0x6602)}, + + /* MT6632 *//* SDIO2: BGF */ + {SDIO_DEVICE(0x037A, 0x6632)}, + + { /* 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 INT32 gRefCount; +static INT32 (*fp_wmt_tra_sdio_update)(VOID); +static atomic_t hif_sdio_irq_enable_flag = ATOMIC_INIT(0); + +/*deep sleep related information*/ +MTK_WCN_HIF_SDIO_DS_INFO g_hif_sdio_ds_info_list[] = { + { + .chip_id = 0x6630, + .reg_offset = 0xF1, + .value = 0x1, + }, + { + .chip_id = 0x6632, + .reg_offset = 0xF1, + .value = 0x1, + }, + { /* end: all zeroes */ } +}; + + + +/******************************************************************************* +* 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); + +INT32 gHifSdioDbgLvl = HIF_SDIO_LOG_INFO; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#if 0 +INT32 __weak mtk_wcn_sdio_irq_flag_set(INT32 falg) +{ + HIF_SDIO_INFO_FUNC("mtk_wcn_sdio_irq_flag_set is not define!!!!!\n"); + + return 0; +} +#endif + +INT32 mtk_wcn_hif_sdio_irq_flag_set(INT32 flag) +{ + + if (flag == 0) { + atomic_dec(&hif_sdio_irq_enable_flag); + if (atomic_read(&hif_sdio_irq_enable_flag) == 0) + wmt_export_mtk_wcn_sdio_irq_flag_set(0); + } else { + atomic_inc(&hif_sdio_irq_enable_flag); + if (atomic_read(&hif_sdio_irq_enable_flag) == 1) + wmt_export_mtk_wcn_sdio_irq_flag_set(1); + } + + return 0; +} + + +/*! + * \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 + */ +INT32 mtk_wcn_hif_sdio_update_cb_reg(INT32(*ts_update) (VOID)) +{ + if (ts_update) { + fp_wmt_tra_sdio_update = ts_update; + return 0; + } else { + return -EINVAL; + } +} +EXPORT_SYMBOL(mtk_wcn_hif_sdio_update_cb_reg); + +/*! + * \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 _osal_inline_ INT32 wmt_tra_sdio_update(VOID) +{ + if (fp_wmt_tra_sdio_update) + return (*fp_wmt_tra_sdio_update) (); + /* 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 _osal_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_UIDX_VALID(probe_index))) { /* invalid index in CLTCTX */ + HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx); + return NULL; + } + /* the client has not been registered */ + if (unlikely(g_hif_sdio_probed_func_list[probe_index].clt_idx < 0)) { + 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; +} + +static _osal_inline_ INT32 hif_sdio_deep_sleep_info_dmp(MTK_WCN_HIF_SDIO_DS_INFO *p_ds_info) +{ + UINT32 i = 0; + MTK_WCN_HIF_SDIO_DS_CLT_INFO *ctl_info = NULL; + UINT32 ctl_info_array_size = ARRAY_SIZE(p_ds_info->clt_info); + + mutex_lock(&p_ds_info->lock); + HIF_SDIO_DBG_FUNC("p_ds_info: %p, chipid:0x%x, reg_offset:0x%x, value:0x%x\n", + p_ds_info, p_ds_info->chip_id, p_ds_info->reg_offset, p_ds_info->value); + + for (i = 0; i < ctl_info_array_size; i++) { + ctl_info = &p_ds_info->clt_info[i]; + + HIF_SDIO_DBG_FUNC + ("ctl_info[%d]--ctx:0x%08x, func_num:%d, act_flag:%d, en_flag:%d\n", i, + ctl_info->ctx, ctl_info->func_num, ctl_info->act_flag, ctl_info->ds_en_flag); + } + mutex_unlock(&p_ds_info->lock); + return 0; +} + +static _osal_inline_ INT32 hif_sdio_deep_sleep_info_init(VOID) +{ + UINT32 array_size = 0; + UINT32 clt_info_size = 0; + UINT32 i = 0; + UINT32 j = 0; + + array_size = ARRAY_SIZE(g_hif_sdio_ds_info_list); + + /*set clt_info segment to 0 by default, when do stp/wifi on, write real information back */ + for (i = 0; i < array_size; i++) { + mutex_init(&g_hif_sdio_ds_info_list[i].lock); + clt_info_size = ARRAY_SIZE(g_hif_sdio_ds_info_list[i].clt_info); + + mutex_lock(&g_hif_sdio_ds_info_list[i].lock); + for (j = 0; j < clt_info_size; j++) + memset(&g_hif_sdio_ds_info_list[i].clt_info[j], + 0, sizeof(MTK_WCN_HIF_SDIO_DS_CLT_INFO)); + mutex_unlock(&g_hif_sdio_ds_info_list[i].lock); + + hif_sdio_deep_sleep_info_dmp(&g_hif_sdio_ds_info_list[i]); + } + + return 0; +} + +static _osal_inline_ INT32 hif_sdio_deep_sleep_info_set_act(UINT32 chipid, UINT16 func_num, + MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT8 act_flag) +{ + UINT32 i = 0; + UINT32 array_size = 0; + UINT32 clt_info_size = 0; + UINT32 idx = 0; + MTK_WCN_HIF_SDIO_DS_CLT_INFO *p_ds_clt_info = NULL; + + array_size = ARRAY_SIZE(g_hif_sdio_ds_info_list); + + /*search write index */ + for (i = 0; i < array_size; i++) { + if (g_hif_sdio_ds_info_list[i].chip_id == chipid) + break; + } + if (i >= array_size) { + HIF_SDIO_WARN_FUNC("no valid ds info found for 0x%x\n", chipid); + return -1; + } + HIF_SDIO_DBG_FUNC("valid ds info found for 0x%x\n", chipid); + + clt_info_size = ARRAY_SIZE(g_hif_sdio_ds_info_list[i].clt_info); + + if (func_num > clt_info_size) { + HIF_SDIO_WARN_FUNC("func num <%d> exceed max clt info size <%d>\n", func_num, + clt_info_size); + return -2; + } + idx = func_num - 1; + p_ds_clt_info = &g_hif_sdio_ds_info_list[i].clt_info[idx]; + + mutex_lock(&g_hif_sdio_ds_info_list[i].lock); + p_ds_clt_info->func_num = func_num; + p_ds_clt_info->ctx = ctx; + p_ds_clt_info->act_flag = act_flag; + p_ds_clt_info->ds_en_flag = 0; + mutex_unlock(&g_hif_sdio_ds_info_list[i].lock); + + HIF_SDIO_DBG_FUNC("set act_flag to %d for ctx:0x%x whose chipid:0x%x, func_num:%d done\n", + act_flag, ctx, chipid, func_num); + /* hif_sdio_deep_sleep_info_dmp(&g_hif_sdio_ds_info_list[0]); */ + + return 0; +} + +static INT32 _hif_sdio_wake_up_ctrl(MTK_WCN_HIF_SDIO_CLTCTX ctx) +{ + INT32 ret = 0; + INT32 gpio_state = -1; + INT32 sec_old = 0; + INT32 usec_old = 0; + INT32 sec = 0; + INT32 usec = 0; + INT32 polling_counter = 0; + UINT8 cccr_value = 0x0; + UINT32 cpupcr_value = 0x00; + INT32 i = 0; + UINT32 delay_us = 500; + WMT_GPIO_STATE_INFO gpio_state_list[2]; + + HIF_SDIO_DBG_FUNC("wakeup chip from deep sleep!\n"); + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_CHIP_WAKE_UP_PIN].gpio_num != DEFAULT_PIN_ID) { + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_CHIP_WAKE_UP_PIN].gpio_num, 1); + HIF_SDIO_DBG_FUNC("wmt_gpio:set GPIO_CHIP_WAKE_UP_PIN out to 1: %d!\n", + gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[GPIO_CHIP_WAKE_UP_PIN].gpio_num)); + } else { + HIF_SDIO_ERR_FUNC("wmt_gpio:get GPIO_CHIP_WAKE_UP_PIN number error!\n"); + return -2; + } + /*1.pull GPIO_CHIP_WAKE_UP_PIN out 0*/ + gpio_state_list[0].gpio_num = gpio_ctrl_info.gpio_ctrl_state[GPIO_CHIP_WAKE_UP_PIN].gpio_num-280; + _wmt_gpio_pre_regs(gpio_state_list[0].gpio_num, &gpio_state_list[0]); + gpio_state_list[1].gpio_num = gpio_ctrl_info.gpio_ctrl_state[GPIO_CHIP_DEEP_SLEEP_PIN].gpio_num-280; + _wmt_gpio_pre_regs(gpio_state_list[1].gpio_num, &gpio_state_list[1]); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_CHIP_WAKE_UP_PIN].gpio_num != DEFAULT_PIN_ID) { + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_CHIP_WAKE_UP_PIN].gpio_num, 0); + HIF_SDIO_DBG_FUNC("wmt_gpio:set GPIO_CHIP_WAKE_UP_PIN out to 0: %d!\n", + gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[GPIO_CHIP_WAKE_UP_PIN].gpio_num)); + } else { + HIF_SDIO_ERR_FUNC("wmt_gpio:get GPIO_CHIP_WAKE_UP_PIN number error!\n"); + return -2; + } + /*2.waiting for DEEP_SLEEP_PIN become high*/ + osal_gettimeofday(&sec_old, &usec_old); + HIF_SDIO_DBG_FUNC("wakeup flow, prepare polling DEEP_SLEEP_PIN high state, timing: %d us\n", usec_old); + while (1) { + osal_gettimeofday(&sec, &usec); + gpio_state = + gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[GPIO_CHIP_DEEP_SLEEP_PIN].gpio_num); + if (gpio_state == 0) { + HIF_SDIO_DBG_FUNC("wmt_gpio:Polling GPIO_CHIP_DEEP_SLEEP_PIN low success!\n"); + if (polling_counter >= 20) + HIF_SDIO_WARN_FUNC + ("polling ACK_B pin low success but over 20 count, time:%dus, count:%d\n", + (usec - usec_old), polling_counter); + polling_counter = 0; + break; + } + if (polling_counter >= 60) { + HIF_SDIO_ERR_FUNC + ("wake up fail!, polling ACK_B pin low over 60 count, time:%dus, count:%d\n", + (usec - usec_old), polling_counter); + HIF_SDIO_INFO_FUNC("Dump EINT_B, ACT_B history states!\n"); + _wmt_dump_gpio_pre_regs(gpio_state_list[0]); + _wmt_dump_gpio_pre_regs(gpio_state_list[1]); + HIF_SDIO_INFO_FUNC("Dump EINT_B, ACT_B current states!\n"); + _wmt_dump_gpio_regs(gpio_state_list[0].gpio_num); + _wmt_dump_gpio_regs(gpio_state_list[1].gpio_num); + + HIF_SDIO_INFO_FUNC("read cccr info !\n"); + for (i = 0; i < 8; i++) { + ret = mtk_wcn_hif_sdio_f0_readb(ctx, CCCR_F8 + i, &cccr_value); + if (ret) + HIF_SDIO_ERR_FUNC("read CCCR fail(%d), address(0x%x)\n", ret, CCCR_F8 + i); + else + HIF_SDIO_INFO_FUNC("read CCCR value(0x%x), address(0x%x)\n", + cccr_value, CCCR_F8 + i); + cccr_value = 0x0; + } + + HIF_SDIO_INFO_FUNC("read cpupcr info !\n"); + for (i = 0; i < 5; i++) { + ret = mtk_wcn_hif_sdio_readl(ctx, SWPCDBGR, &cpupcr_value); + if (ret) + HIF_SDIO_ERR_FUNC("read cpupcr fail, ret(%d)\n", ret); + else + HIF_SDIO_ERR_FUNC("read cpupcr value (0x%x)\n", cpupcr_value); + msleep(20); + } + _wmt_dump_gpio_regs(gpio_state_list[0].gpio_num); + _wmt_dump_gpio_regs(gpio_state_list[1].gpio_num); + ret = -11; + break; + } + polling_counter++; + osal_usleep_range(delay_us, 2 * delay_us); + } + /*3.pull GPIO_CHIP_WAKE_UP_PIN high, clear interrupt*/ + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_CHIP_WAKE_UP_PIN].gpio_num != DEFAULT_PIN_ID) { + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_CHIP_WAKE_UP_PIN].gpio_num, 1); + HIF_SDIO_DBG_FUNC("wmt_gpio:set GPIO_CHIP_WAKE_UP_PIN out to 1: %d!\n", + gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[GPIO_CHIP_WAKE_UP_PIN].gpio_num)); + } else { + HIF_SDIO_ERR_FUNC("wmt_gpio:get GPIO_CHIP_WAKE_UP_PIN number error!\n"); + return -3; + } + + return ret; +} +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT +INT32 mtk_wcn_hif_sdio_deep_sleep_flag_set(MTK_WCN_BOOL flag) +{ + g_hif_deep_sleep_flag = flag; + return 0; +} +#endif +INT32 hif_sdio_wake_up_ctrl(MTK_WCN_HIF_SDIO_CLTCTX ctx) +{ + UINT32 i = 0; + UINT32 j = 0; + INT32 ret = 0; + UINT32 array_size = 0; + UINT32 clt_info_size = 0; + MTK_WCN_HIF_SDIO_DS_CLT_INFO *p_ds_clt_info = NULL; + MTK_WCN_HIF_SDIO_DS_INFO *p_ds_info = NULL; + UINT8 do_ds_op_flag = 0; + + array_size = ARRAY_SIZE(g_hif_sdio_ds_info_list); + /*search write index */ + for (i = 0; i < array_size; i++) { + mutex_lock(&(g_hif_sdio_ds_info_list[i].lock)); + clt_info_size = ARRAY_SIZE(g_hif_sdio_ds_info_list[i].clt_info); + + for (j = 0; j < clt_info_size; j++) { + if (g_hif_sdio_ds_info_list[i].clt_info[j].ctx == ctx) { + do_ds_op_flag = 1; + break; + } + } + + if (do_ds_op_flag != 0) + break; + mutex_unlock(&(g_hif_sdio_ds_info_list[i].lock)); + } + + if ((i >= array_size) || (j >= clt_info_size)) { + HIF_SDIO_ERR_FUNC("mtk_wcn_hif_sdio_wake_up_ctrl, no valid ds info found for ctx 0x%08x\n", ctx); + return -1; + } + HIF_SDIO_DBG_FUNC("mtk_wcn_hif_sdio_wake_up_ctrl, valid ds info found for ctx 0x%08x\n", ctx); + p_ds_info = &g_hif_sdio_ds_info_list[i]; + p_ds_clt_info = &p_ds_info->clt_info[j]; + HIF_SDIO_DBG_FUNC("mtk_wcn_hif_sdio_wake_up_ctrl, func_num:(%d), chid(%x)\n", + p_ds_clt_info->func_num, p_ds_info->chip_id); + if (g_hif_deep_sleep_flag) { + HIF_SDIO_DBG_FUNC("deep sleep feature is enable!\n"); + ret = _hif_sdio_wake_up_ctrl(ctx); + if (ret == -11) { + HIF_SDIO_DBG_FUNC("wake up chip from deep sleep fail, retry wake up operation\n"); + ret = _hif_sdio_wake_up_ctrl(ctx); + if (ret == 0) + HIF_SDIO_INFO_FUNC("retry wake up from deep sleep success\n"); + else if (ret == -11) + HIF_SDIO_INFO_FUNC("retry wake up from deep sleep fail!\n"); + } + } else + HIF_SDIO_DBG_FUNC("deep sleep feature is disable!\n"); + mutex_unlock(&(g_hif_sdio_ds_info_list[i].lock)); + return ret; +} + +/*! + * \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_DBG_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!\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\n", + pinfo->func_tbl[i].manf_id, pinfo->func_tbl[i].card_id, + pinfo->func_tbl[i].func_num); + HIF_SDIO_WARN_FUNC("sdio_func are duplicated in g_hif_sdio_clt_drv_list!\n"); + 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); + if (g_hif_sdio_probed_func_list[j].func->num != 1 + || (g_hif_sdio_probed_func_list[j].on_by_wmt == MTK_WCN_BOOL_TRUE + && g_hif_sdio_probed_func_list[j].func->num == 1)) { + /* use worker thread to perform the client's .hif_clt_probe() */ + clt_probe_worker_info = + vmalloc(sizeof(MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO)); + if (clt_probe_worker_info) { + 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_hif_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 error handling */ + + HIF_SDIO_DBG_FUNC("end!\n"); + return ret; +} /* end of mtk_wcn_hif_sdio_client_reg() */ +EXPORT_SYMBOL(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),", pinfo->func_tbl[i].manf_id); + HIF_SDIO_WARN_FUNC(" device id(0x%x),", pinfo->func_tbl[i].card_id); + HIF_SDIO_WARN_FUNC(" and fun_num(%d)", pinfo->func_tbl[i].func_num); + HIF_SDIO_WARN_FUNC(" client info is not in the client's registed list!\n"); + 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() */ +EXPORT_SYMBOL(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 = NULL; +#else + INT32 ret = -HIF_SDIO_ERR_FAIL; + INT32 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 (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */ + HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx); + goto out; + } + if (probe_index < 0 || probe_index >= CFG_CLIENT_COUNT) { /* 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> */ + osal_ftrace_print("%s|S\n", __func__); + sdio_claim_host(func); + *pvb = sdio_readb(func, offset, &ret); + sdio_release_host(func); + osal_ftrace_print("%s|E\n", __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() */ +EXPORT_SYMBOL(mtk_wcn_hif_sdio_readb); + +/*! + * \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 = NULL; +#else + INT32 ret = -HIF_SDIO_ERR_FAIL; + INT32 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 (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */ + HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx); + goto out; + } + if (probe_index < 0 || probe_index >= CFG_CLIENT_COUNT) { /* 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(); + osal_ftrace_print("%s|S\n", __func__); + sdio_claim_host(func); + sdio_writeb(func, vb, offset, &ret); + sdio_release_host(func); + osal_ftrace_print("%s|E\n", __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() */ +EXPORT_SYMBOL(mtk_wcn_hif_sdio_writeb); + +/*! + * \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 = NULL; +#else + INT32 ret = -HIF_SDIO_ERR_FAIL; + INT32 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 (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */ + HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx); + goto out; + } + if (probe_index < 0 || probe_index >= CFG_CLIENT_COUNT) { /* 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> */ + osal_ftrace_print("%s|S\n", __func__); + sdio_claim_host(func); + *pvl = sdio_readl(func, offset, &ret); + sdio_release_host(func); + osal_ftrace_print("%s|E\n", __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() */ +EXPORT_SYMBOL(mtk_wcn_hif_sdio_readl); + +/*! + * \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 = NULL; +#else + INT32 ret = -HIF_SDIO_ERR_FAIL; + INT32 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 (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */ + HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx); + goto out; + } + if (probe_index < 0 || probe_index >= CFG_CLIENT_COUNT) { /* 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(); + osal_ftrace_print("%s|S\n", __func__); + sdio_claim_host(func); + sdio_writel(func, vl, offset, &ret); + sdio_release_host(func); + osal_ftrace_print("%s|E\n", __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() */ +EXPORT_SYMBOL(mtk_wcn_hif_sdio_writel); + +/*! + * \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 = NULL; +#else + INT32 ret = -HIF_SDIO_ERR_FAIL; + INT32 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 (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */ + HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx); + goto out; + } + if (probe_index < 0 || probe_index >= CFG_CLIENT_COUNT) { /* 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> */ + osal_ftrace_print("%s|S|L|%d\n", __func__, len); + sdio_claim_host(func); + ret = sdio_readsb(func, pbuf, offset, len); + sdio_release_host(func); + osal_ftrace_print("%s|E|L|%d\n", __func__, len); + + /* 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() */ +EXPORT_SYMBOL(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 = NULL; +#else + INT32 ret = -HIF_SDIO_ERR_FAIL; + INT32 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 (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */ + HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx); + goto out; + } + if (probe_index < 0 || probe_index >= CFG_CLIENT_COUNT) { /* 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(); + osal_ftrace_print("%s|S|L|%d\n", __func__, len); + sdio_claim_host(func); + ret = sdio_writesb(func, offset, pbuf, len); + sdio_release_host(func); + osal_ftrace_print("%s|E|L|%d\n", __func__, len); + + /* 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() */ +EXPORT_SYMBOL(mtk_wcn_hif_sdio_write_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_abort(MTK_WCN_HIF_SDIO_CLTCTX ctx) +{ +#if HIF_SDIO_UPDATE + INT32 ret; + struct sdio_func *func = NULL; +#else + INT32 ret = -HIF_SDIO_ERR_FAIL; + INT32 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 (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */ + HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx); + goto out; + } + if (probe_index < 0 || probe_index >= CFG_CLIENT_COUNT) { /* 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> */ + osal_ftrace_print("%s|S|L|\n", __func__); + sdio_claim_host(func); + /* SDIO Control must be switched to function 2 before the abort command send + * firmware can receive function 2 abort interrupt + * read CTMDPCR1(0xBC) to switch function 2 + */ + sdio_readl(func, 0xBC, &ret); + ret = KERNEL_mmc_io_rw_direct(func->card, 1, 0, SDIO_CCCR_ABORT, func->num, NULL); + sdio_release_host(func); + osal_ftrace_print("%s|E|L|\n", __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() */ +EXPORT_SYMBOL(mtk_wcn_hif_sdio_abort); + +/*! + * \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, PVOID private_data_p) +{ + UINT8 probed_idx = CLTCTX_IDX(ctx); + + if (unlikely(!CLTCTX_UIDX_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); + } +} +EXPORT_SYMBOL(mtk_wcn_hif_sdio_set_drvdata); + +/*! + * \brief get client driver's private data function. + * + * + * \param clent's MTK_WCN_HIF_SDIO_CLTCTX. + * + * \retval private data pointer. + */ +PVOID 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_UIDX_VALID(probed_idx))) + return g_hif_sdio_probed_func_list[probed_idx].private_data_p; + /* invalid index in CLTCTX */ + HIF_SDIO_WARN_FUNC("invalid idx in ctx(0x%x), return null!\n", ctx); + return NULL; +} +EXPORT_SYMBOL(mtk_wcn_hif_sdio_get_drvdata); + +/*! + * \brief control stp/wifi on/off from wmt. + * + * + * \param (1)control function type, (2)on/off control. + * + * \retval (1)control results ,(2)unknown 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; + } +} +EXPORT_SYMBOL(mtk_wcn_hif_sdio_wmt_control); + +/*! + * \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 = NULL; +#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; + } + *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; + } + *dev = &g_hif_sdio_probed_func_list[probe_index].func->dev; +#endif +} +EXPORT_SYMBOL(mtk_wcn_hif_sdio_get_dev); + +/*! + * \brief client's probe() function. + * + * + * \param work queue structure. + * + * \retval none. + */ +static _osal_inline_ INT32 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; + INT32 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_DBG_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 _osal_inline_ VOID hif_sdio_dump_probe_list(VOID) +{ + INT32 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 _osal_inline_ 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 _osal_inline_ 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 _osal_inline_ INT32 hif_sdio_find_probed_list_index_by_func(struct sdio_func *func) +{ + INT32 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 _osal_inline_ INT32 hif_sdio_find_probed_list_index_by_id_func(UINT16 vendor, UINT16 device, + UINT16 func_num) +{ + INT32 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) { + /* + * pr_warn(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 _osal_inline_ INT32 hif_sdio_find_clt_list_index(UINT16 vendor, UINT16 device, UINT16 func_num) +{ + INT32 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 supported + * \retval HIF_SDIO_ERR_SUCCESS vendor, device ids are supported + */ +static _osal_inline_ INT32 hif_sdio_check_supported_sdio_id(UINT16 vendor, UINT16 device) +{ + INT32 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 _osal_inline_ INT32 hif_sdio_check_duplicate_sdio_id(UINT16 vendor, UINT16 device, UINT16 func_num) +{ + INT32 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 _osal_inline_ INT32 hif_sdio_add_clt_list(PINT32 clt_index_p, + const MTK_WCN_HIF_SDIO_CLTINFO *pinfo, UINT32 tbl_index) +{ + INT32 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 INT32 hif_sdio_suspend(struct device *dev) +{ + struct sdio_func *func = NULL; + mmc_pm_flag_t flag; + INT32 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 HIF_SDIO_SUPPORT_WAKEUP + if (!(flag & MMC_PM_KEEP_POWER) || !(flag & MMC_PM_WAKE_SDIO_IRQ)) { + HIF_SDIO_WARN_FUNC + ("neither MMC_PM_KEEP_POWER or 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; +#else + if (!(flag & MMC_PM_KEEP_POWER)) { + HIF_SDIO_WARN_FUNC + ("neither MMC_PM_KEEP_POWER is supported by host, return -ENOTSUPP\n"); + return -ENOTSUPP; + } + flag |= MMC_PM_KEEP_POWER; +#endif + ret = sdio_set_host_pm_flags(func, flag); + if (ret) { + HIF_SDIO_INFO_FUNC + ("set MMC_PM_KEEP_POWER to host fail(%d)\n", ret); + return -EFAULT; + } +#if HIF_SDIO_SUPPORT_WAKEUP + sdio_claim_host(func); +#endif + HIF_SDIO_INFO_FUNC("set MMC_PM_KEEP_POWER ok\n"); + return 0; +} + +static INT32 hif_sdio_resume(struct device *dev) +{ +#if HIF_SDIO_SUPPORT_WAKEUP + struct sdio_func *func = NULL; +#endif + if (!dev) { + HIF_SDIO_WARN_FUNC("null dev!\n"); + return -EINVAL; + } +#if HIF_SDIO_SUPPORT_WAKEUP + func = dev_to_sdio_func(dev); + sdio_release_host(func); +#endif + HIF_SDIO_INFO_FUNC("do nothing\n"); + + 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 INT32 hif_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) +{ + INT32 ret = 0; + INT32 i = 0; + MTK_WCN_HIF_SDIO_PROBEINFO *hif_sdio_probed_funcp = 0; + INT32 probe_index = -1; + INT32 idx; +#if 0 + INT32 clt_index = -1; + MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO *clt_probe_worker_info = 0; +#endif + + HIF_SDIO_DBG_FUNC("start!\n"); + HIF_SDIO_ASSERT(func); +#if !(DELETE_HIF_SDIO_CHRDEV) + hif_sdio_match_chipid_by_dev_id(id); +#endif + /* 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_DBG_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; + } + /* 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; + } + /* 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 && + hif_sdio_probed_funcp->clt_idx < CFG_CLIENT_COUNT) { + /* The clt contex has been registed */ + sdio_claim_host(func); + idx = hif_sdio_probed_funcp->clt_idx; + ret = sdio_set_block_size(func, g_hif_sdio_clt_drv_list[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_DBG_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); + + + hif_sdio_dump_probe_list(); + +out: + /* 4 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) +{ + INT32 probed_list_index = 0; +#if 0 + INT32 registed_list_index = 0; +#endif + + HIF_SDIO_DBG_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_DBG_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) +{ + INT32 probed_list_index = -1; + INT32 registed_list_index = -1; + INT32 ret; + + HIF_SDIO_DBG_FUNC("start!\n"); + + osal_ftrace_print("%s|S\n", __func__); + /* 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 (g_hif_sdio_probed_func_list[probed_list_index].sdio_irq_enabled == MTK_WCN_BOOL_FALSE) { + 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)) { + HIF_SDIO_DBG_FUNC("[%d]SDIO IRQ (func:0x%p) v(0x%x) d(0x%x) n(0x%x)\n", + probed_list_index, func, func->vendor, func->device, func->num); + + 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_hif_sdio_irq_flag_set(0); + ret = sdio_release_irq(func); + if (ret) + HIF_SDIO_WARN_FUNC("sdio_release_irq() fail(%d)\n", ret); + } + osal_ftrace_print("%s|E\n", __func__); +} + +/*! + * \brief hif_sdio init function + * + * detailed descriptions + * + * \retval + */ +static INT32 hif_sdio_init(VOID) +{ + INT32 ret = 0; + INT32 i = 0; + + HIF_SDIO_INFO_FUNC("start!\n"); + + /* 4 <1> init all private variables */ + /* init reference count to 0 */ + gRefCount = 0; + + atomic_set(&hif_sdio_irq_enable_flag, 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); + if (ret != 0) + HIF_SDIO_INFO_FUNC("sdio_register_driver() fail, ret=%d\n", ret); + +#if !(DELETE_HIF_SDIO_CHRDEV) + /* 4 <3> create thread for query chip id and device node for launcher to access */ + if (hifsdiod_start() == 0) + hif_sdio_create_dev_node(); +#endif + hif_sdio_deep_sleep_info_init(); + HIF_SDIO_DBG_FUNC("end!\n"); + return ret; +} + +/*! + * \brief hif_sdio init function + * + * detailed descriptions + * + * \retval + */ +static VOID hif_sdio_exit(VOID) +{ + HIF_SDIO_INFO_FUNC("start!\n"); + +#if !(DELETE_HIF_SDIO_CHRDEV) + hif_sdio_remove_dev_node(); + hifsdiod_stop(); +#endif + + /* 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); + atomic_set(&hif_sdio_irq_enable_flag, 0); + HIF_SDIO_DBG_FUNC("end!\n"); +} /* 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. + */ +static _osal_inline_ 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; + INT32 ret = -1; + INT32 ret2 = -1; + struct sdio_func *func = NULL; + UINT32 chip_id = 0; + UINT16 func_num = 0; + + const MTK_WCN_HIF_SDIO_FUNCINFO *func_info = NULL; + + HIF_SDIO_DBG_FUNC("hif_sdio_stp_on, start!\n"); + + /* 4 <1> If stp client drv has not been probed, return error code */ + /* MT6620 */ + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020B, 1); + if (probe_index >= 0) + goto stp_on_exist; + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020C, 1); + if (probe_index >= 0) + goto stp_on_exist; + + /* MT6628 */ + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6628, 2); + if (probe_index >= 0) + goto stp_on_exist; + /* MT6630 */ + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6630, 2); + if (probe_index >= 0) { + chip_id = 0x6630; + func_num = 2; + goto stp_on_exist; + } + /* MT6632 */ + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6632, 2); + if (probe_index >= 0) { + chip_id = 0x6632; + func_num = 2; + goto stp_on_exist; + } + /* MT6619 */ + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6619, 1); + if (probe_index >= 0) + goto stp_on_exist; + + /* MT6618 */ + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018B, 1); + if (probe_index >= 0) + goto stp_on_exist; + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018C, 1); + if (probe_index >= 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 (g_hif_sdio_probed_func_list[probe_index].on_by_wmt != MTK_WCN_BOOL_FALSE) { + HIF_SDIO_INFO_FUNC("already on...\n"); + return HIF_SDIO_ERR_ALRDY_ON; + } + g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_TRUE; + + clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx; + if (clt_index >= 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; + if (unlikely(!(func) || !(func->card) || !(func->card->host) + || mmc_card_removed(func->card))) { + HIF_SDIO_ERR_FUNC("sdio host is missing\n"); + return HIF_SDIO_ERR_NOT_PROBED; + } + sdio_claim_host(func); + ret = sdio_claim_irq(func, hif_sdio_irq); + mtk_wcn_hif_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_DBG_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_hif_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; + } + g_hif_sdio_probed_func_list[probe_index].sdio_irq_enabled = MTK_WCN_BOOL_TRUE; + + /*set deep sleep information to global data struct */ + func_info = g_hif_sdio_clt_drv_list[clt_index].func_info; + hif_sdio_deep_sleep_info_set_act(chip_id, func_num, + CLTCTX(func_info->card_id, func_info->func_num, + func_info->blk_sz, probe_index), 1); + + + HIF_SDIO_DBG_FUNC("hif_sdio_stp_on, 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. + */ +static _osal_inline_ INT32 hif_sdio_stp_off(VOID) +{ + INT32 clt_index = -1; + INT32 probe_index = -1; + INT32 ret = -1; + INT32 ret2 = -1; + struct sdio_func *func = NULL; + UINT32 chip_id = 0; + UINT16 func_num = 0; + const MTK_WCN_HIF_SDIO_FUNCINFO *func_info = NULL; + + HIF_SDIO_DBG_FUNC("hif_sdio_stp_off, start!\n"); + + /* 4 <1> If stp client drv has not been probed, return error code */ + /* MT6620 */ + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020B, 1); + if (probe_index >= 0) + goto stp_off_exist; + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020C, 1); + if (probe_index >= 0) + goto stp_off_exist; + + /* MT6628 */ + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6628, 2); + if (probe_index >= 0) + goto stp_off_exist; + /* MT6630 */ + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6630, 2); + if (probe_index >= 0) { + chip_id = 0x6630; + func_num = 2; + goto stp_off_exist; + } + /* MT6632 */ + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6632, 2); + if (probe_index >= 0) { + chip_id = 0x6632; + func_num = 2; + goto stp_off_exist; + } + + /* MT6619 */ + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6619, 1); + if (probe_index >= 0) + goto stp_off_exist; + + /* MT6618 */ + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018B, 1); + if (probe_index >= 0) + goto stp_off_exist; + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018C, 1); + if (probe_index >= 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 (g_hif_sdio_probed_func_list[probe_index].on_by_wmt == MTK_WCN_BOOL_FALSE) { + HIF_SDIO_WARN_FUNC("already off...\n"); + return HIF_SDIO_ERR_ALRDY_OFF; + } + 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) + pr_warn(DRV_NAME "sdio_release_irq for stp fail(%d)\n", ret); + else + pr_warn(DRV_NAME "sdio_release_irq for stp ok\n"); +#endif + clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx; + if (clt_index >= 0) { /* the function has been registered */ + func = g_hif_sdio_probed_func_list[probe_index].func; + + if (unlikely(!(func) || !(func->card) || !(func->card->host) + || mmc_card_removed(func->card))) { + HIF_SDIO_ERR_FUNC("sdio host is missing\n"); + return HIF_SDIO_ERR_ALRDY_OFF; + } + /* 4 <4> release irq for this function */ + sdio_claim_host(func); + mtk_wcn_hif_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); + else + HIF_SDIO_DBG_FUNC("sdio_release_irq() for stp ok\n"); + + /* 4 <5> 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_DBG_FUNC("hif_sdio_stp_off, ok!\n"); + + /*set deep sleep information to global data struct */ + func_info = g_hif_sdio_clt_drv_list[clt_index].func_info; + hif_sdio_deep_sleep_info_set_act(chip_id, func_num, + CLTCTX(func_info->card_id, func_info->func_num, + func_info->blk_sz, probe_index), 0); + return ret + ret2; + } + /* 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. + */ +static _osal_inline_ 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; + INT32 ret = 0; + INT32 ret2 = 0; + struct sdio_func *func = NULL; + UINT32 chip_id = 0; + UINT16 func_num = 0; + const MTK_WCN_HIF_SDIO_FUNCINFO *func_info = NULL; + + HIF_SDIO_DBG_FUNC("start!\n"); + + /* 4 <1> If wifi client drv has not been probed, return error code */ + /* MT6620 */ + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020A, 1); + if (probe_index >= 0) + goto wifi_on_exist; + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020C, 2); + if (probe_index >= 0) + goto wifi_on_exist; + /* MT6628 */ + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6628, 1); + if (probe_index == 0) + goto wifi_on_exist; + /* MT6630 */ + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6630, 1); + if (probe_index >= 0) { + chip_id = 0x6630; + func_num = 1; + goto wifi_on_exist; + } + /* MT6632 */ + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6602, 1); + if (probe_index >= 0) { + chip_id = 0x6632; + func_num = 1; + goto wifi_on_exist; + } + + /* MT6618 */ + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018A, 1); + if (probe_index == 0) + goto wifi_on_exist; + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018C, 2); + if (probe_index >= 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; + } + clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx; + if (clt_index >= 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; + if (unlikely(!(func) || !(func->card) || !(func->card->host) + || mmc_card_removed(func->card))) { + HIF_SDIO_ERR_FUNC("sdio host is missing\n"); + return HIF_SDIO_ERR_NOT_PROBED; + } + sdio_claim_host(func); + ret = sdio_claim_irq(func, hif_sdio_irq); + mtk_wcn_hif_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 + /*set deep sleep information to global data struct */ + func_info = g_hif_sdio_clt_drv_list[clt_index].func_info; + hif_sdio_deep_sleep_info_set_act(chip_id, func_num, + CLTCTX(func_info->card_id, func_info->func_num, + func_info->blk_sz, probe_index), 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_hif_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); + + hif_sdio_deep_sleep_info_set_act(chip_id, func_num, + CLTCTX(func_info->card_id, + func_info->func_num, + func_info->blk_sz, probe_index), + 0); + g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_FALSE; + return ret; + } + g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_TRUE; + + HIF_SDIO_DBG_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); + g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_TRUE; + 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. + */ +static _osal_inline_ INT32 hif_sdio_wifi_off(VOID) +{ + INT32 clt_index = -1; + INT32 probe_index = -1; + INT32 ret = -1; + INT32 ret2 = -1; + struct sdio_func *func = NULL; + UINT32 chip_id = 0; + UINT16 func_num = 0; + const MTK_WCN_HIF_SDIO_FUNCINFO *func_info = NULL; + + HIF_SDIO_INFO_FUNC("start!\n"); + + /* 4 <1> If wifi client drv has not been probed, return error code */ + /* MT6620 */ + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020A, 1); + if (probe_index >= 0) + goto wifi_off_exist; + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020C, 2); + if (probe_index >= 0) + goto wifi_off_exist; + + /* MT6628 */ + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6628, 1); + if (probe_index >= 0) + goto wifi_off_exist; + /* MT6630 */ + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6630, 1); + if (probe_index >= 0) { + chip_id = 0x6630; + func_num = 1; + goto wifi_off_exist; + } + /* MT6632 */ + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6602, 1); + if (probe_index >= 0) { + chip_id = 0x6632; + func_num = 1; + goto wifi_off_exist; + } + + /* MT6618 */ + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018A, 1); + if (probe_index >= 0) + goto wifi_off_exist; + probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018C, 2); + if (probe_index >= 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 (g_hif_sdio_probed_func_list[probe_index].on_by_wmt == MTK_WCN_BOOL_FALSE) { + HIF_SDIO_WARN_FUNC("already off...\n"); + return HIF_SDIO_ERR_ALRDY_OFF; + } + 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) + pr_warn(DRV_NAME "sdio_release_irq for wifi fail(%d)\n", ret); + else + pr_warn(DRV_NAME "sdio_release_irq for wifi ok\n"); + +#endif + clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx; + if (clt_index >= 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"); + + if (unlikely(!(func) || !(func->card) || !(func->card->host) + || mmc_card_removed(func->card))) { + HIF_SDIO_ERR_FUNC("sdio host is missing\n"); + return HIF_SDIO_ERR_ALRDY_OFF; + } + /* 4 <5> release irq for this function */ + sdio_claim_host(func); + mtk_wcn_hif_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"); + + /*set deep sleep information to global data struct */ + func_info = g_hif_sdio_clt_drv_list[clt_index].func_info; + hif_sdio_deep_sleep_info_set_act(chip_id, func_num, + CLTCTX(func_info->card_id, func_info->func_num, + func_info->blk_sz, probe_index), 0); + + return ret + ret2; + } + /* 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) +{ + INT32 probe_index = -1; + struct sdio_func *func = 0; + + HIF_SDIO_INFO_FUNC("turn Bus Power to: %d\n", pwrState); + + 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 -1; + } + func = g_hif_sdio_probed_func_list[probe_index].func; + + if (!func) { + HIF_SDIO_WARN_FUNC("Cannot find sdio_func !!!\n"); + return -1; + } + + if (pwrState == 1) { + 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; +} +EXPORT_SYMBOL(mtk_wcn_hif_sdio_bus_set_power); + +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_UIDX_VALID(probed_idx))) { /* invalid index in CLTCTX */ + HIF_SDIO_WARN_FUNC("invalid idx in ctx(0x%x), sdio_irq no change\n", ctx); + return; + } + if (unlikely(!CLTCTX_UIDX_VALID(probed_idx))) { /* invalid index in CLTCTX */ + HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\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_DBG_FUNC("ctx(0x%x) sdio irq enable(%d)\n", + ctx, (enable == MTK_WCN_BOOL_FALSE) ? 0 : 1); + + +} +EXPORT_SYMBOL(mtk_wcn_hif_sdio_enable_irq); + +/*! + * \brief + * + * detailed descriptions + * + * \param ctx client's context variable + * + * \retval 0 register successfully + * \retval < 0 list error code here + */ +INT32 mtk_wcn_hif_sdio_f0_readb(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT32 offset, PUINT8 pvb) +{ +#if HIF_SDIO_UPDATE + INT32 ret; + struct sdio_func *func = NULL; +#else + INT32 ret = -HIF_SDIO_ERR_FAIL; + INT32 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 (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */ + HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx); + return -1; + } + if (probe_index < 0 || probe_index >= CFG_CLIENT_COUNT) { /* 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_f0_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_f0_readb() */ + + +/*! + * \brief + * + * detailed descriptions + * + * \param ctx client's context variable + * + * \retval 0register successfully + * \retval < 0 list error code here + */ +INT32 mtk_wcn_hif_sdio_f0_writeb(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT32 offset, UINT8 vb) +{ +#if HIF_SDIO_UPDATE + INT32 ret; + struct sdio_func *func = NULL; +#else + INT32 ret = -HIF_SDIO_ERR_FAIL; + INT32 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 (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */ + HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx); + goto out; + } + 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_f0_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_f0_writeb() */ + + +INT32 mtk_wcn_hif_sdio_drv_init(VOID) +{ + return hif_sdio_init(); + +} +EXPORT_SYMBOL(mtk_wcn_hif_sdio_drv_init); + +VOID mtk_wcn_hif_sdio_driver_exit(VOID) +{ + return hif_sdio_exit(); +} +EXPORT_SYMBOL(mtk_wcn_hif_sdio_driver_exit); diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/include/bgw_desense.h b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/bgw_desense.h new file mode 100644 index 0000000000000..4e9db7cbeb933 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/bgw_desense.h @@ -0,0 +1,73 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef __BGW_DESENSE_H_ +#define __BGW_DESENSE_H_ + +#ifdef MSG +#undef MSG +#endif + +#ifdef ERR +#undef ERR +#endif + +#define PFX1 "[BWG] " +#define MSG(fmt, arg ...) pr_debug(PFX1 "[D]%s: " fmt, __func__, ##arg) +#define ERR(fmt, arg ...) pr_debug(PFX1 "[D]%s: " fmt, __func__, ##arg) + +#ifdef NETLINK_TEST +#undef NETLINK_TEST +#endif + +#define NETLINK_TEST 17 + +#ifdef MAX_NL_MSG_LEN +#undef MAX_NL_MSG_LEN +#endif + +#define MAX_NL_MSG_LEN 1024 + + +#ifdef ON +#undef ON +#endif +#ifdef OFF +#undef OFF +#endif +#ifdef ACK +#undef ACK +#endif + +#define ON 1 +#define OFF 0 +#define ACK 2 + +/* + * used send command to native process + * + * parameter: command could be macro ON: enable co-exist; OFF: disable co-exist; + * ACK: after get native process init message send ACK + */ +extern void send_command_to_daemon(const int command); + +/* + * before use kernel socket, please call init socket first + * return value: 0: ok; -1: fail + */ +extern int bgw_init_socket(void); + +extern void bgw_destroy_netlink_kernel(void); + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/include/fw_log_wmt.h b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/fw_log_wmt.h new file mode 100644 index 0000000000000..7871f467e64d1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/fw_log_wmt.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef _FW_LOG_WMT_H_ +#define _FW_LOG_WMT_H_ + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH +int fw_log_wmt_init(void); +void fw_log_wmt_deinit(void); +#endif + +#endif /*_FW_LOG_WMT_H_*/ + diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/include/hif_sdio.h b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/hif_sdio.h new file mode 100644 index 0000000000000..bafbc26fd8b21 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/hif_sdio.h @@ -0,0 +1,371 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/*! + * \file "hif_sdio.h" + * \brief + */ + +/* + * + * 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:turn off debug msg and assert, 1:turn off debug msg and assert */ +#define HIF_SDIO_API_EXTENSION (0) +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "osal_typedef.h" +#include "osal.h" +#include "wmt_exp.h" + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define CFG_CLIENT_COUNT (12) + +#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 + +#define CCCR_F8 (0X00F8) +#define SWPCDBGR (0x0154) + +/******************************************************************************* +* 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 */ + PVOID 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 */ + INT32 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; + +/* SDIO Deep Sleep Information by chip, maintained by HIF-SDIO itself */ +typedef struct _MTK_WCN_HIF_SDIO_DS_CLT_INFO { + MTK_WCN_HIF_SDIO_CLTCTX ctx; + UINT16 func_num; + UINT8 act_flag; + UINT8 ds_en_flag; +} MTK_WCN_HIF_SDIO_DS_CLT_INFO; + +typedef struct _MTK_WCN_HIF_SDIO_DS_INFO { + UINT32 chip_id; /*chipid */ + UINT32 reg_offset; /*offset in CCCR of control register of deep sleep */ + UINT8 value; /*value to set to CCCR reg_offset, when enable deep sleep */ + MTK_WCN_HIF_SDIO_DS_CLT_INFO clt_info[2]; /*currently, only BGF and WIFI function need this function */ + struct mutex lock; +} MTK_WCN_HIF_SDIO_DS_INFO; + + +/* 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 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)) +#define CLTCTX_UIDX_VALID(idx) (idx < CFG_CLIENT_COUNT) + + +/*! + * \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) + +#ifdef DFT_TAG +#undef DFT_TAG +#endif + +#ifndef DFT_TAG +#define DFT_TAG "[HIF-SDIO]" +#endif + +extern INT32 gHifSdioDbgLvl; + + +#define HIF_SDIO_LOUD_FUNC(fmt, arg...) \ +do { if (gHifSdioDbgLvl >= HIF_SDIO_LOG_LOUD) \ + osal_warn_print(DFT_TAG"[L]%s:" fmt, __func__, ##arg); \ +} while (0) +#define HIF_SDIO_DBG_FUNC(fmt, arg...) \ +do { if (gHifSdioDbgLvl >= HIF_SDIO_LOG_DBG) \ + osal_warn_print(DFT_TAG"[D]%s:" fmt, __func__, ##arg); \ +} while (0) +#define HIF_SDIO_INFO_FUNC(fmt, arg...) \ +do { if (gHifSdioDbgLvl >= HIF_SDIO_LOG_INFO) \ + osal_warn_print(DFT_TAG"[I]%s:" fmt, __func__, ##arg); \ +} while (0) +#define HIF_SDIO_WARN_FUNC(fmt, arg...) \ +do { if (gHifSdioDbgLvl >= HIF_SDIO_LOG_WARN) \ + osal_warn_print(DFT_TAG"[W]%s(%d):" fmt, __func__, __LINE__, ##arg); \ +} while (0) +#define HIF_SDIO_ERR_FUNC(fmt, arg...) \ +do { if (gHifSdioDbgLvl >= HIF_SDIO_LOG_ERR) \ + osal_err_print(DFT_TAG"[E]%s(%d):" fmt, __func__, __LINE__, ##arg); \ +} while (0) + +/*! + * \brief ASSERT function definition. + * + */ +#if HIF_SDIO_DEBUG +#define HIF_SDIO_ASSERT(expr) \ +{ \ + if (!(expr)) { \ + osal_warn_print("assertion failed! %s[%d]: %s\n",\ + __func__, __LINE__, #expr); \ + osal_bug_on(!(expr));\ + } \ +} +#else +#define HIF_SDIO_ASSERT(expr) do {} while (0) +#endif + +/* define function 0 CR */ +#define CCCR_06 (0x06) +#define CCCR_F0 (0xF0) + +/******************************************************************************* +* 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 INT32 mtk_wcn_hif_sdio_abort(MTK_WCN_HIF_SDIO_CLTCTX ctx); + +INT32 hif_sdio_wake_up_ctrl(MTK_WCN_HIF_SDIO_CLTCTX ctx); + +extern VOID mtk_wcn_hif_sdio_set_drvdata(MTK_WCN_HIF_SDIO_CLTCTX ctx, PVOID private_data_p); + +extern PVOID 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(INT32(*ts_update)(VOID)); + +extern VOID mtk_wcn_hif_sdio_enable_irq(MTK_WCN_HIF_SDIO_CLTCTX ctx, MTK_WCN_BOOL enable); + +extern INT32 mtk_wcn_hif_sdio_f0_writeb(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT32 offset, UINT8 vb); + +extern INT32 mtk_wcn_hif_sdio_f0_readb(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT32 offset, PUINT8 pvb); +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT +INT32 mtk_wcn_hif_sdio_deep_sleep_flag_set(MTK_WCN_BOOL flag); +#endif + +#define DELETE_HIF_SDIO_CHRDEV 1 +#if !(DELETE_HIF_SDIO_CHRDEV) +INT32 mtk_wcn_hif_sdio_tell_chipid(INT32 chipId); +INT32 mtk_wcn_hif_sdio_query_chipid(INT32 waitFlag); +#endif + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _HIF_SDIO_H */ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/include/osal.h b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/osal.h new file mode 100644 index 0000000000000..c006d2f5cbaec --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/osal.h @@ -0,0 +1,443 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + + +/*! \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 "osal_typedef.h" +#include "../../debug_utility/ring.h" +#include +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define OS_BIT_OPS_SUPPORT 1 + +#define _osal_inline_ inline + +#define MAX_THREAD_NAME_LEN 16 +#define MAX_WAKE_LOCK_NAME_LEN 16 +#define MAX_HISTORY_NAME_LEN 16 +#define OSAL_OP_BUF_SIZE 64 + + +#if (defined(CONFIG_MTK_GMO_RAM_OPTIMIZE) && !defined(CONFIG_MTK_ENG_BUILD)) +#define OSAL_OP_DATA_SIZE 8 +#else +#define OSAL_OP_DATA_SIZE 32 +#endif + +#define DBG_LOG_STR_SIZE 256 + +#define osal_sizeof(x) sizeof(x) + +#define osal_array_size(x) ARRAY_SIZE(x) + +#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 GET_BIT_MASK(value, mask) ((value) & (mask)) +#define SET_BIT_MASK(pdest, value, mask) (*(pdest) = (GET_BIT_MASK(*(pdest), ~(mask)) | GET_BIT_MASK(value, mask))) +#define GET_BIT_RANGE(data, end, begin) ((data) & GENMASK(end, begin)) +#define SET_BIT_RANGE(pdest, data, end, begin) (SET_BIT_MASK(pdest, data, GENMASK(end, begin))) + +#define RB_LATEST(prb) ((prb)->write - 1) +#define RB_SIZE(prb) ((prb)->size) +#define RB_MASK(prb) (RB_SIZE(prb) - 1) +#define RB_COUNT(prb) ((prb)->write - (prb)->read) +#define RB_FULL(prb) (RB_COUNT(prb) >= RB_SIZE(prb)) +#define RB_EMPTY(prb) ((prb)->write == (prb)->read) + +#define RB_INIT(prb, qsize) \ +do { \ + (prb)->read = (prb)->write = 0; \ + (prb)->size = (qsize); \ +} while (0) + +#define RB_PUT(prb, value) \ +do { \ + if (!RB_FULL(prb)) { \ + (prb)->queue[(prb)->write & RB_MASK(prb)] = value; \ + ++((prb)->write); \ + } \ + else { \ + osal_assert(!RB_FULL(prb)); \ + } \ +} while (0) + +#define RB_GET(prb, value) \ +do { \ + if (!RB_EMPTY(prb)) { \ + value = (prb)->queue[(prb)->read & RB_MASK(prb)]; \ + ++((prb)->read); \ + if (RB_EMPTY(prb)) { \ + (prb)->read = (prb)->write = 0; \ + } \ + } \ + else { \ + value = NULL; \ + osal_assert(!RB_EMPTY(prb)); \ + } \ +} while (0) + +#define RB_GET_LATEST(prb, value) \ +do { \ + if (!RB_EMPTY(prb)) { \ + value = (prb)->queue[RB_LATEST(prb) & RB_MASK(prb)]; \ + if (RB_EMPTY(prb)) { \ + (prb)->read = (prb)->write = 0; \ + } \ + } \ + else { \ + value = NULL; \ + } \ +} while (0) + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) +typedef VOID(*P_TIMEOUT_HANDLER) (struct timer_list *t); +typedef struct timer_list *timer_handler_arg; +#define GET_HANDLER_DATA(arg, data) \ +do { \ + P_OSAL_TIMER osal_timer = from_timer(osal_timer, arg, timer); \ + data = osal_timer->timeroutHandlerData; \ +} while (0) +#else +typedef VOID(*P_TIMEOUT_HANDLER) (ULONG); +typedef ULONG timer_handler_arg; +#define GET_HANDLER_DATA(arg, data) (data = arg) +#endif + +typedef INT32(*P_COND) (PVOID); + +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; + UINT32 timeoutExtension; /* max number of timeout caused by thread not able to acquire CPU */ +} 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; + +/* Data collected from sched_entity and sched_statistics */ +typedef struct _OSAL_THREAD_SCHEDSTATS_ { + UINT64 time; /* when marked: the profiling start time(ms), when unmarked: total duration(ms) */ + UINT64 exec; /* time spent in exec (sum_exec_runtime) */ + UINT64 runnable; /* time spent in run-queue while not being scheduled (wait_sum) */ + UINT64 iowait; /* time spent waiting for I/O (iowait_sum) */ +} OSAL_THREAD_SCHEDSTATS, *P_OSAL_THREAD_SCHEDSTATS; + +typedef struct _OSAL_THREAD_ { + struct task_struct *pThread; + PVOID pThreadFunc; + PVOID pThreadData; + INT8 threadName[MAX_THREAD_NAME_LEN]; +} OSAL_THREAD, *P_OSAL_THREAD; + + +typedef struct _OSAL_FIFO_ { + /*fifo definition */ + PVOID pFifoBody; + spinlock_t fifoSpinlock; + /*fifo operations */ + INT32 (*FifoInit)(struct _OSAL_FIFO_ *pFifo, PUINT8 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 PVOID buf, UINT32 len); + INT32 (*FifoDataOut)(struct _OSAL_FIFO_ *pFifo, PVOID buf, UINT32 len); +} OSAL_FIFO, *P_OSAL_FIFO; + +typedef struct firmware osal_firmware; + +typedef struct _OSAL_OP_DAT { + UINT32 opId; /* Event ID */ + UINT32 u4InfoBit; /* Reserved */ + SIZE_T au4OpData[OSAL_OP_DATA_SIZE]; /* OP Data */ +} OSAL_OP_DAT, *P_OSAL_OP_DAT; + +typedef struct _OSAL_LXOP_ { + OSAL_OP_DAT op; + OSAL_SIGNAL signal; + INT32 result; + atomic_t ref_count; +} 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 wakeup_source *wake_lock; + UINT8 name[MAX_WAKE_LOCK_NAME_LEN]; + INT32 init_flag; +} 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 unsigned long +#define P_OSAL_BIT_OP_VAR unsigned long * + +#endif +typedef UINT32(*P_OSAL_EVENT_CHECKER) (P_OSAL_THREAD pThread); + +struct osal_op_history_entry { + VOID *opbuf_address; + UINT32 op_id; + UINT32 opbuf_ref_count; + UINT32 op_info_bit; + SIZE_T param_0; + SIZE_T param_1; + SIZE_T param_2; + SIZE_T param_3; + UINT64 ts; + ULONG usec; +}; + +struct osal_op_history { + struct ring ring_buffer; + struct osal_op_history_entry *queue; + spinlock_t lock; + struct ring dump_ring_buffer; + struct work_struct dump_work; + UINT8 name[MAX_HISTORY_NAME_LEN]; +}; + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + +UINT32 osal_strlen(const PINT8 str); +INT32 osal_strcmp(const PINT8 dst, const PINT8 src); +INT32 osal_strncmp(const PINT8 dst, const PINT8 src, UINT32 len); +PINT8 osal_strcpy(PINT8 dst, const PINT8 src); +PINT8 osal_strncpy(PINT8 dst, const PINT8 src, UINT32 len); +PINT8 osal_strcat(PINT8 dst, const PINT8 src); +PINT8 osal_strncat(PINT8 dst, const PINT8 src, UINT32 len); +PINT8 osal_strchr(const PINT8 str, UINT8 c); +PINT8 osal_strsep(PPINT8 str, const PINT8 c); +INT32 osal_strtol(const PINT8 str, UINT32 adecimal, PLONG res); +PINT8 osal_strstr(PINT8 str1, const PINT8 str2); +PINT8 osal_strnstr(PINT8 str1, const PINT8 str2, INT32 n); + +VOID osal_bug_on(UINT32 val); + +INT32 osal_snprintf(PINT8 buf, UINT32 len, const PINT8 fmt, ...); +INT32 osal_err_print(const PINT8 str, ...); +INT32 osal_dbg_print(const PINT8 str, ...); +INT32 osal_warn_print(const PINT8 str, ...); + +INT32 osal_dbg_assert(INT32 expr, const PINT8 file, INT32 line); +INT32 osal_dbg_assert_aee(const PINT8 module, const PINT8 detail_description, ...); +INT32 osal_sprintf(PINT8 str, const PINT8 format, ...); +PVOID osal_malloc(UINT32 size); +VOID osal_free(const PVOID dst); +PVOID osal_memset(PVOID buf, INT32 i, UINT32 len); +PVOID osal_memcpy(PVOID dst, const PVOID src, UINT32 len); +VOID osal_memcpy_fromio(PVOID dst, const PVOID src, UINT32 len); +VOID osal_memcpy_toio(PVOID dst, const PVOID src, UINT32 len); +INT32 osal_memcmp(const PVOID buf1, const PVOID buf2, UINT32 len); + +UINT16 osal_crc16(const PUINT8 buffer, const UINT32 length); +VOID osal_thread_show_stack(P_OSAL_THREAD pThread); + +INT32 osal_sleep_ms(UINT32 ms); +INT32 osal_udelay(UINT32 us); +INT32 osal_usleep_range(ULONG min, ULONG max); +INT32 osal_timer_create(P_OSAL_TIMER); +INT32 osal_timer_start(P_OSAL_TIMER, UINT32); +INT32 osal_timer_stop(P_OSAL_TIMER); +INT32 osal_timer_stop_sync(P_OSAL_TIMER pTimer); +INT32 osal_timer_modify(P_OSAL_TIMER, UINT32); +INT32 osal_timer_delete(P_OSAL_TIMER); + +INT32 osal_fifo_init(P_OSAL_FIFO pFifo, PUINT8 buffer, UINT32 size); +VOID osal_fifo_deinit(P_OSAL_FIFO pFifo); +INT32 osal_fifo_reset(P_OSAL_FIFO pFifo); +UINT32 osal_fifo_in(P_OSAL_FIFO pFifo, PUINT8 buffer, UINT32 size); +UINT32 osal_fifo_out(P_OSAL_FIFO pFifo, PUINT8 buffer, UINT32 size); +UINT32 osal_fifo_len(P_OSAL_FIFO pFifo); +UINT32 osal_fifo_sz(P_OSAL_FIFO pFifo); +UINT32 osal_fifo_avail(P_OSAL_FIFO pFifo); +UINT32 osal_fifo_is_empty(P_OSAL_FIFO pFifo); +UINT32 osal_fifo_is_full(P_OSAL_FIFO pFifo); + +INT32 osal_wake_lock_init(P_OSAL_WAKE_LOCK plock); +INT32 osal_wake_lock(P_OSAL_WAKE_LOCK plock); +INT32 osal_wake_unlock(P_OSAL_WAKE_LOCK plock); +INT32 osal_wake_lock_count(P_OSAL_WAKE_LOCK plock); +INT32 osal_wake_lock_deinit(P_OSAL_WAKE_LOCK plock); + +#if defined(CONFIG_PROVE_LOCKING) +#define osal_unsleepable_lock_init(l) { spin_lock_init(&((l)->lock)); } +#else +INT32 osal_unsleepable_lock_init(P_OSAL_UNSLEEPABLE_LOCK); +#endif +INT32 osal_lock_unsleepable_lock(P_OSAL_UNSLEEPABLE_LOCK); +INT32 osal_unlock_unsleepable_lock(P_OSAL_UNSLEEPABLE_LOCK); +INT32 osal_trylock_unsleepable_lock(P_OSAL_UNSLEEPABLE_LOCK); +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 +INT32 osal_sleepable_lock_init(P_OSAL_SLEEPABLE_LOCK); +#endif +INT32 osal_lock_sleepable_lock(P_OSAL_SLEEPABLE_LOCK); +INT32 osal_unlock_sleepable_lock(P_OSAL_SLEEPABLE_LOCK); +INT32 osal_trylock_sleepable_lock(P_OSAL_SLEEPABLE_LOCK); +INT32 osal_sleepable_lock_deinit(P_OSAL_SLEEPABLE_LOCK); + +INT32 osal_signal_init(P_OSAL_SIGNAL); +INT32 osal_wait_for_signal(P_OSAL_SIGNAL); +INT32 osal_wait_for_signal_timeout(P_OSAL_SIGNAL, P_OSAL_THREAD); +INT32 osal_raise_signal(P_OSAL_SIGNAL); +INT32 osal_signal_active_state(P_OSAL_SIGNAL pSignal); +INT32 osal_signal_deinit(P_OSAL_SIGNAL); + +INT32 osal_event_init(P_OSAL_EVENT); +INT32 osal_wait_for_event(P_OSAL_EVENT, P_COND, PVOID); +INT32 osal_wait_for_event_timeout(P_OSAL_EVENT, P_COND, PVOID); +extern INT32 osal_trigger_event(P_OSAL_EVENT); + +INT32 osal_event_deinit(P_OSAL_EVENT); +LONG osal_wait_for_event_bit_set(P_OSAL_EVENT pEvent, PULONG pState, UINT32 bitOffset); +LONG osal_wait_for_event_bit_clr(P_OSAL_EVENT pEvent, PULONG pState, UINT32 bitOffset); + +INT32 osal_thread_create(P_OSAL_THREAD); +INT32 osal_thread_run(P_OSAL_THREAD); +INT32 osal_thread_should_stop(P_OSAL_THREAD); +INT32 osal_thread_stop(P_OSAL_THREAD); +/*INT32 osal_thread_wait_for_event(P_OSAL_THREAD, P_OSAL_EVENT);*/ +INT32 osal_thread_wait_for_event(P_OSAL_THREAD, P_OSAL_EVENT, P_OSAL_EVENT_CHECKER); +/*check pOsalLxOp and OSAL_THREAD_SHOULD_STOP*/ +INT32 osal_thread_destroy(P_OSAL_THREAD); +INT32 osal_thread_sched_mark(P_OSAL_THREAD, P_OSAL_THREAD_SCHEDSTATS schedstats); +INT32 osal_thread_sched_unmark(P_OSAL_THREAD pThread, P_OSAL_THREAD_SCHEDSTATS schedstats); + +INT32 osal_clear_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData); +INT32 osal_set_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData); +INT32 osal_test_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData); +INT32 osal_test_and_clear_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData); +INT32 osal_test_and_set_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData); + +INT32 osal_gettimeofday(PINT32 sec, PINT32 usec); +void osal_do_gettimeofday(struct timeval *tv); +INT32 osal_printtimeofday(const PUINT8 prefix); +VOID osal_get_local_time(PUINT64 sec, PULONG nsec); +UINT64 osal_elapsed_us(UINT64 ts, ULONG usec); + +VOID osal_buffer_dump(const PUINT8 buf, const PUINT8 title, UINT32 len, UINT32 limit); +VOID osal_buffer_dump_data(const PUINT32 buf, const PUINT8 title, const UINT32 len, const UINT32 limit, + const INT32 flag); + +UINT32 osal_op_get_id(P_OSAL_OP pOp); +MTK_WCN_BOOL osal_op_is_wait_for_signal(P_OSAL_OP pOp); +VOID osal_op_raise_signal(P_OSAL_OP pOp, INT32 result); +VOID osal_set_op_result(P_OSAL_OP pOp, INT32 result); +VOID osal_opq_dump(const char *qName, P_OSAL_OP_Q pOpQ); +VOID osal_opq_dump_locked(const char *qName, P_OSAL_OP_Q pOpQ); +MTK_WCN_BOOL osal_opq_has_op(P_OSAL_OP_Q pOpQ, P_OSAL_OP pOp); + +INT32 osal_ftrace_print(const PINT8 str, ...); +INT32 osal_ftrace_print_ctrl(INT32 flag); + +VOID osal_dump_thread_state(const PUINT8 name); +VOID osal_op_history_init(struct osal_op_history *log_history, INT32 queue_size); +VOID osal_op_history_save(struct osal_op_history *log_history, P_OSAL_OP pOp); +VOID osal_op_history_print(struct osal_op_history *log_history, PINT8 name); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#define osal_assert(condition) \ +do { \ + if (!(condition)) \ + osal_err_print("%s, %d, (%s)\n", __FILE__, __LINE__, #condition); \ +} while (0) + +#endif /* _OSAL_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/include/osal_typedef.h b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/osal_typedef.h new file mode 100644 index 0000000000000..ca48a7b7bac51 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/osal_typedef.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/*! \file + * \brief Declaration of library functions + * Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. + */ + +#ifndef _OSAL_TYPEDEF_H_ +#define _OSAL_TYPEDEF_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(WMT_PLAT_ALPS) && WMT_PLAT_ALPS +#if IS_ENABLED(CONFIG_MTK_AEE_AED) +#include +#endif +#endif +#include +#include +#include +#include +#include +#include + +#ifndef _TYPEDEFS_H /*fix redifine */ +typedef signed char INT8; +#endif + +typedef void VOID, *PVOID, **PPVOID; +typedef char *PINT8, **PPINT8; +typedef short INT16, *PINT16, **PPINT16; +typedef int INT32, *PINT32, **PPINT32; +typedef long LONG, *PLONG, **PPLONG; +typedef long long INT64, *PINT64, **PPINT64; + +typedef unsigned char UINT8, *PUINT8, **PPUINT8; +typedef unsigned short UINT16, *PUINT16, **PPUINT16; +typedef unsigned int UINT32, *PUINT32, **PPUINT32; +typedef unsigned long ULONG, *PULONG, **PPULONG; +typedef unsigned long long UINT64, *PUINT64, **PPUINT64; + +typedef size_t SIZE_T; + +typedef int MTK_WCN_BOOL; +#ifndef MTK_WCN_BOOL_TRUE +#define MTK_WCN_BOOL_FALSE ((MTK_WCN_BOOL) 0) +#define MTK_WCN_BOOL_TRUE ((MTK_WCN_BOOL) 1) +#endif + +#endif /*_OSAL_TYPEDEF_H_*/ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/include/stp_btif.h b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/stp_btif.h new file mode 100644 index 0000000000000..68f6d2ae5f9ab --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/stp_btif.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef _STP_BTIF_H_ +#define _STP_BTIF_H_ + +#include "osal_typedef.h" +#include "mtk_btif_exp.h" +#include "osal.h" + +struct stp_btif { + ULONG stpBtifId; + OSAL_THREAD btif_thread; +}; + +INT32 mtk_wcn_consys_stp_btif_open(VOID); +INT32 mtk_wcn_consys_stp_btif_close(VOID); +INT32 mtk_wcn_consys_stp_btif_rx_cb_register(MTK_WCN_BTIF_RX_CB rx_cb); +INT32 mtk_wcn_consys_stp_btif_tx(const PUINT8 pBuf, const UINT32 len, PUINT32 written_len); +INT32 mtk_wcn_consys_stp_btif_wakeup(VOID); +INT32 mtk_wcn_consys_stp_btif_dpidle_ctrl(UINT32 en_flag); +INT32 mtk_wcn_consys_stp_btif_lpbk_ctrl(enum _ENUM_BTIF_LPBK_MODE_ mode); +INT32 mtk_wcn_consys_stp_btif_logger_ctrl(enum _ENUM_BTIF_DBG_ID_ flag); +INT32 mtk_wcn_consys_stp_btif_parser_wmt_evt(const PUINT8 str, UINT32 len); +INT32 mtk_wcn_consys_stp_btif_rx_has_pending_data(VOID); +INT32 mtk_wcn_consys_stp_btif_tx_has_pending_data(VOID); +P_OSAL_THREAD mtk_wcn_consys_stp_btif_rx_thread_get(VOID); + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/include/stp_dbg.h b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/stp_dbg.h new file mode 100644 index 0000000000000..9915eab428536 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/stp_dbg.h @@ -0,0 +1,424 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef _STP_DEBUG_H_ +#define _STP_DEBUG_H_ + +#include +#include "stp_btif.h" +#include "osal.h" +#include "wmt_exp.h" + +#define CONFIG_LOG_STP_INTERNAL + +#ifndef LOG_STP_DEBUG_DISABLE /* #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 1024 +#define STP_DBG_LOG_ENTRY_SZ 96 + +#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 96 + +#endif +#define EMICOREDUMP_CMD "emicoredump" +#define FAKECOREDUMPEND "coredump end - fake" + +#define MAX_DUMP_HEAD_LEN 512 +/* netlink header packet length is 5 "[M](3 bytes) + length(2 bypes)" */ +#define NL_PKT_HEADER_LEN 5 + +#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 + +extern INT32 gStpDbgDbgLevel; + +#define STP_DBG_PR_LOUD(fmt, arg...) \ +do { \ + if (gStpDbgDbgLevel >= STP_DBG_LOG_LOUD) \ + pr_info(PFX_STP_DBG "%s: " fmt, __func__, ##arg); \ +} while (0) +#define STP_DBG_PR_DBG(fmt, arg...) \ +do { \ + if (gStpDbgDbgLevel >= STP_DBG_LOG_DBG) \ + pr_info(PFX_STP_DBG "%s: " fmt, __func__, ##arg); \ +} while (0) +#define STP_DBG_PR_INFO(fmt, arg...) \ +do { \ + if (gStpDbgDbgLevel >= STP_DBG_LOG_INFO) \ + pr_info(PFX_STP_DBG "%s: " fmt, __func__, ##arg); \ +} while (0) +#define STP_DBG_PR_WARN(fmt, arg...) \ +do { \ + if (gStpDbgDbgLevel >= STP_DBG_LOG_WARN) \ + pr_warn(PFX_STP_DBG "%s: " fmt, __func__, ##arg); \ +} while (0) +#define STP_DBG_PR_ERR(fmt, arg...) \ +do { \ + if (gStpDbgDbgLevel >= STP_DBG_LOG_ERR) \ + pr_err(PFX_STP_DBG "%s: " fmt, __func__, ##arg); \ +} while (0) + +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 PINT8 const comboStpDbgType[] = { + "< BT>", + "< FM>", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" +}; + +static PINT8 const socStpDbgType[] = { + "< BT>", + "< FM>", + "", + "", + "", + "", + "", + "", + "" +}; + +enum STP_DBG_TAKS_ID_T { + STP_DBG_TASK_WMT = 0, + STP_DBG_TASK_BT, + STP_DBG_TASK_WIFI, + STP_DBG_TASK_TST, + STP_DBG_TASK_FM, + STP_DBG_TASK_GPS, + STP_DBG_TASK_FLP, + STP_DBG_TASK_BT2, + STP_DBG_TASK_IDLE, + STP_DBG_TASK_DRVSTP, + STP_DBG_TASK_BUS, + STP_DBG_TASK_NATBT, + STP_DBG_TASK_DRVWIFI, + STP_DBG_TASK_DRVGPS, + STP_DBG_TASK_ID_MAX, +}; + +typedef enum { + STP_DBG_DR_MAX = 0, +} STP_DBG_DR_FIL_T; + +typedef enum { + STP_DBG_FW_MAX = 0, +} STP_DBG_FW_FIL_T; + +typedef enum { + PKT_DIR_RX = 0, + PKT_DIR_TX +} STP_DBG_PKT_DIR_T; + +/*simple log system ++*/ + +typedef struct { + /*type: 0. pkt trace 1. fw info + * 2. assert info 3. trace32 dump . + * -1. linked to the the previous + */ + INT32 id; + INT32 len; + INT8 buffer[STP_DBG_LOG_ENTRY_SZ]; +} MTKSTP_LOG_ENTRY_T; + +typedef struct log_sys { + MTKSTP_LOG_ENTRY_T queue[STP_DBG_LOG_ENTRY_NUM]; + UINT32 size; + UINT32 in; + UINT32 out; + spinlock_t lock; + MTKSTP_LOG_ENTRY_T *dump_queue; + UINT32 dump_size; + struct work_struct dump_work; +} MTKSTP_LOG_SYS_T; +/*--*/ + +typedef struct stp_dbg_pkt_hdr { + /* packet information */ + UINT32 sec; + UINT32 usec; + UINT32 dbg_type; + UINT32 last_dbg_type; + UINT32 dmy; + UINT32 no; + UINT32 dir; + + /* packet content */ + UINT32 type; + UINT32 len; + UINT32 ack; + UINT32 seq; + UINT32 chs; + UINT32 crc; + UINT64 l_sec; + ULONG l_nsec; +} STP_DBG_HDR_T; + +typedef struct stp_dbg_pkt { + struct stp_dbg_pkt_hdr hdr; + UINT8 raw[STP_DMP_SZ]; +} STP_PACKET_T; + +typedef struct mtkstp_dbg_t { + /*log_sys */ + INT32 pkt_trace_no; + PVOID btm; + INT32 is_enable; + MTKSTP_LOG_SYS_T *logsys; +} MTKSTP_DBG_T; + +/* extern void aed_combo_exception(const int *, int, const int *, int, const char *); */ +#if WMT_DBG_SUPPORT +#define STP_CORE_DUMP_TIMEOUT (1*60*1000) /* default 1 minutes */ +#else +#define STP_CORE_DUMP_TIMEOUT (10*1000) /* user load default 10 seconds */ +#endif +#if WMT_DBG_SUPPORT +#define STP_EMI_DUMP_TIMEOUT (30*1000) +#else +#define STP_EMI_DUMP_TIMEOUT (5*1000) +#endif +#define STP_OJB_NAME_SZ 20 +#define STP_CORE_DUMP_INFO_SZ 500 +#define STP_CORE_DUMP_INIT_SIZE 512 +typedef enum wcn_compress_algorithm_t { + GZIP = 0, + BZIP2 = 1, + RAR = 2, + LMA = 3, + MAX +} WCN_COMPRESS_ALG_T; + +typedef INT32 (*COMPRESS_HANDLER) (PVOID worker, UINT8 *in_buf, INT32 in_sz, PUINT8 out_buf, PINT32 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; + PVOID worker; + COMPRESS_HANDLER handler; +} WCN_COMPRESSOR_T, *P_WCN_COMPRESSOR_T; + +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; + LONG dmp_num; + UINT32 count; + OSAL_SLEEPABLE_LOCK dmp_lock; + + /* timer for monitor emi dump */ + OSAL_TIMER dmp_emi_timer; + UINT32 emi_timeout; + + /* state machine for core dump flow */ + CORE_DUMP_STA sm; + + /* dump info */ + INT8 info[STP_CORE_DUMP_INFO_SZ + 1]; + + PUINT8 p_head; + UINT32 head_len; +} WCN_CORE_DUMP_T, *P_WCN_CORE_DUMP_T; + +typedef enum _ENUM_STP_FW_ISSUE_TYPE_ { + STP_FW_ISSUE_TYPE_INVALID = 0x0, + STP_FW_ASSERT_ISSUE = 0x1, + STP_FW_NOACK_ISSUE = 0x2, + STP_FW_WARM_RST_ISSUE = 0x3, + STP_DBG_PROC_TEST = 0x4, + STP_HOST_TRIGGER_FW_ASSERT = 0x5, + STP_HOST_TRIGGER_ASSERT_TIMEOUT = 0x6, + STP_FW_ABT = 0x7, + STP_HOST_TRIGGER_COLLECT_FTRACE = 0x8, + STP_FW_ISSUE_TYPE_MAX +} ENUM_STP_FW_ISSUE_TYPE, *P_ENUM_STP_FW_ISSUE_TYPE; + +/* this was added for support dmareg's issue */ +typedef enum _ENUM_DMA_ISSUE_TYPE_ { + CONNSYS_CLK_GATE_STATUS = 0x00, + CONSYS_EMI_STATUS, + SYSRAM1, + SYSRAM2, + SYSRAM3, + DMA_REGS_MAX +} ENUM_DMA_ISSUE_TYPE; +#define STP_PATCH_TIME_SIZE 12 +#define STP_DBG_CPUPCR_NUM 30 +#define STP_DBG_DMAREGS_NUM 16 +#define STP_PATCH_BRANCH_SZIE 8 +#define STP_ASSERT_INFO_SIZE 164 +#define STP_DBG_ROM_VER_SIZE 4 +#define STP_ASSERT_TYPE_SIZE 64 + +#define STP_DBG_KEYWORD_SIZE 256 +typedef struct stp_dbg_host_assert_t { + UINT32 drv_type; + UINT32 reason; + UINT32 assert_from_host; +} STP_DBG_HOST_ASSERT_T, *P_STP_DBG_HOST_ASSERT_T; + +typedef struct stp_dbg_cpupcr_t { + UINT32 chipId; + UINT8 romVer[STP_DBG_ROM_VER_SIZE]; + UINT8 patchVer[STP_PATCH_TIME_SIZE]; + UINT8 branchVer[STP_PATCH_BRANCH_SZIE]; + UINT32 wifiVer; + UINT32 count; + UINT32 stop_flag; + UINT32 buffer[STP_DBG_CPUPCR_NUM]; + UINT64 sec_buffer[STP_DBG_CPUPCR_NUM]; + ULONG nsec_buffer[STP_DBG_CPUPCR_NUM]; + UINT8 assert_info[STP_ASSERT_INFO_SIZE]; + UINT32 fwTaskId; + UINT32 fwRrq; + UINT32 fwIsr; + STP_DBG_HOST_ASSERT_T host_assert_info; + UINT8 assert_type[STP_ASSERT_TYPE_SIZE]; + ENUM_STP_FW_ISSUE_TYPE issue_type; + UINT8 keyword[STP_DBG_KEYWORD_SIZE]; + OSAL_SLEEPABLE_LOCK lock; +} STP_DBG_CPUPCR_T, *P_STP_DBG_CPUPCR_T; + +typedef struct stp_dbg_dmaregs_t { + UINT32 count; + UINT32 dmaIssue[DMA_REGS_MAX][STP_DBG_DMAREGS_NUM]; + OSAL_SLEEPABLE_LOCK lock; +} STP_DBG_DMAREGS_T, *P_STP_DBG_DMAREGS_T; + +typedef enum _ENUM_ASSERT_INFO_PARSER_TYPE_ { + STP_DBG_ASSERT_INFO = 0x0, + STP_DBG_FW_TASK_ID = 0x1, + STP_DBG_FW_ISR = 0x2, + STP_DBG_FW_IRQ = 0x3, + STP_DBG_ASSERT_TYPE = 0x4, + STP_DBG_PARSER_TYPE_MAX +} ENUM_ASSERT_INFO_PARSER_TYPE, *P_ENUM_ASSERT_INFO_PARSER_TYPE; + +VOID stp_dbg_nl_init(VOID); +VOID stp_dbg_nl_deinit(VOID); +INT32 stp_dbg_core_dump_deinit_gcoredump(VOID); +INT32 stp_dbg_core_dump_flush(INT32 rst, MTK_WCN_BOOL coredump_is_timeout); +INT32 stp_dbg_core_dump(INT32 dump_sink); +INT32 stp_dbg_trigger_collect_ftrace(PUINT8 pbuf, INT32 len); +#if BTIF_RXD_BE_BLOCKED_DETECT +MTK_WCN_BOOL stp_dbg_is_btif_rxd_be_blocked(VOID); +#endif +INT32 stp_dbg_enable(MTKSTP_DBG_T *stp_dbg); +INT32 stp_dbg_disable(MTKSTP_DBG_T *stp_dbg); +INT32 stp_dbg_dmp_print(MTKSTP_DBG_T *stp_dbg); +INT32 stp_dbg_dmp_out(MTKSTP_DBG_T *stp_dbg, PINT8 buf, PINT32 len); +INT32 stp_dbg_dmp_append(MTKSTP_DBG_T *stp_dbg, PUINT8 pBuf, INT32 max_len); + +INT32 stp_dbg_dmp_out_ex(PINT8 buf, PINT32 len); +INT32 stp_dbg_log_pkt(MTKSTP_DBG_T *stp_dbg, INT32 dbg_type, + INT32 type, INT32 ack_no, INT32 seq_no, INT32 crc, INT32 dir, INT32 len, + const PUINT8 body); +INT32 stp_dbg_log_ctrl(UINT32 on); +INT32 stp_dbg_aee_send(PUINT8 aucMsg, INT32 len, INT32 cmd); +INT32 stp_dbg_dump_num(LONG dmp_num); +INT32 stp_dbg_nl_send(PINT8 aucMsg, UINT8 cmd, INT32 len); +INT32 stp_dbg_dump_send_retry_handler(PINT8 tmp, INT32 len); +VOID stp_dbg_set_coredump_timer_state(CORE_DUMP_STA state); +INT32 stp_dbg_get_coredump_timer_state(VOID); +INT32 stp_dbg_poll_cpupcr(UINT32 times, UINT32 sleep, UINT32 cmd); +INT32 stp_dbg_poll_dmaregs(UINT32 times, UINT32 sleep); +INT32 stp_dbg_poll_cpupcr_ctrl(UINT32 en); +INT32 stp_dbg_set_version_info(UINT32 chipid, PUINT8 pRomVer, PUINT8 pPatchVer, PUINT8 pPatchBrh); +INT32 stp_dbg_set_wifiver(UINT32 wifiver); +INT32 stp_dbg_set_host_assert_info(UINT32 drv_type, UINT32 reason, UINT32 en); +VOID stp_dbg_set_keyword(PINT8 keyword); +UINT32 stp_dbg_get_host_trigger_assert(VOID); +INT32 stp_dbg_set_fw_info(PUINT8 issue_info, UINT32 len, ENUM_STP_FW_ISSUE_TYPE issue_type); +INT32 stp_dbg_cpupcr_infor_format(PUINT8 buf, UINT32 max_len); +INT32 stp_dbg_dump_cpupcr_reg_info(PUINT8 buf, UINT32 consys_lp_reg); +VOID stp_dbg_clear_cpupcr_reg_info(VOID); +PUINT8 stp_dbg_id_to_task(UINT32 id); +VOID stp_dbg_reset(VOID); + +MTKSTP_DBG_T *stp_dbg_init(PVOID btm_half); +INT32 stp_dbg_deinit(MTKSTP_DBG_T *stp_dbg); +INT32 stp_dbg_start_coredump_timer(VOID); +INT32 stp_dbg_start_emi_dump(VOID); +INT32 stp_dbg_stop_emi_dump(VOID); +INT32 stp_dbg_nl_send_data(const PINT8 buf, INT32 len); +#endif /* end of _STP_DEBUG_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/include/stp_dbg_combo.h b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/stp_dbg_combo.h new file mode 100644 index 0000000000000..ab5a137e56cfa --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/stp_dbg_combo.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef _STP_DEBUG_COMBO_H_ +#define _STP_DEBUG_COMBO_H_ + +#include +#include "osal.h" + +INT32 stp_dbg_combo_core_dump(INT32 dump_sink); +PUINT8 stp_dbg_combo_id_to_task(UINT32 id); + +#endif /* end of _STP_DEBUG_COMBO_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/include/stp_dbg_soc.h b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/stp_dbg_soc.h new file mode 100644 index 0000000000000..6c070f9a88d3d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/stp_dbg_soc.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef _STP_DEBUG_SOC_H_ +#define _STP_DEBUG_SOC_H_ + +#include +#include "osal.h" +#include "wmt_plat.h" + +#define STP_DBG_PAGED_DUMP_BUFFER_SIZE (32*1024*sizeof(char)) + +INT32 stp_dbg_soc_core_dump(INT32 dump_sink); +PUINT8 stp_dbg_soc_id_to_task(UINT32 id); +UINT32 stp_dbg_soc_read_debug_crs(ENUM_CONNSYS_DEBUG_CR cr); +INT32 stp_dbg_soc_poll_cpupcr(UINT32 times, UINT32 sleep, UINT32 cmd); + +#endif /* end of _STP_DEBUG_SOC_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/include/stp_sdio.h b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/stp_sdio.h new file mode 100644 index 0000000000000..c1b9f45082c9b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/stp_sdio.h @@ -0,0 +1,322 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/* + * 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) +#define CTMDPCR0 (0x00B8) +#define CTMDPCR1 (0x00BC) +#define CSR (0x00D8) /* MT6630 & MT6632 only for the moment */ + + + +/* Common HIF register bit field address */ +/* CCCR_F0*/ +#define CCCR_F0_RX_CRC (0x1) +#define CCCR_F0_RX_INT (0x8) + +/* 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_RETRY (0x00000200) +#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 */ + +#define STP_SDIO_DBG_SUPPORT 1 +#define STP_SDIO_RXDBG 1 /* depends on STP_SDIO_DBG_SUPPORT */ +#define STP_SDIO_TXDBG 1 /* depends on STP_SDIO_DBG_SUPPORT */ +#define STP_TXDBG 1 + +/* 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) + +#define STP_SDIO_FW_CPUPCR_POLLING_CNT (5) + +#define STP_SDIO_RETRY_LIMIT (10) +#define STP_SDIO_MAX_RETRY_NUM (100) + +#define STP_SDIO_RETRY_NONE (0) +#define STP_SDIO_RETRY_CRC_ERROR (1) +#define STP_SDIO_RETRY_INT (2) + +/* 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 + +#define COHEC_00006052 (1) +/* #define COHEC_00006052 (0) */ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_STP_SDIO_HIF_TYPE_T { + HIF_TYPE_READB = 0, + HIF_TYPE_READL = HIF_TYPE_READB + 1, + HIF_TYPE_READ_BUF = HIF_TYPE_READL + 1, + HIF_TYPE_WRITEB = HIF_TYPE_READ_BUF + 1, + HIF_TYPE_WRITEL = HIF_TYPE_WRITEB + 1, + HIF_TYPE_WRITE_BUF = HIF_TYPE_WRITEL + 1, + HIF_TYPE_MAX +} ENUM_STP_SDIO_HIF_TYPE_T, *P_ENUM_STP_SDIO_HIF_TYPE_T; + +/* 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 + PUINT8 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]; + UINT64 tx_buf_local_ts[STP_SDIO_TX_BUF_CNT]; + ULONG tx_buf_local_nsec[STP_SDIO_TX_BUF_CNT]; + +#if KMALLOC_UPDATE + PUINT8 rx_buf; +#else + UINT8 rx_buf[STP_SDIO_RX_BUF_SIZE]; /* Rx buffer (not ring) */ +#endif +#if STP_SDIO_NEW_TXRING + atomic_t wr_cnt; /* Tx entry ring buffer write count */ + atomic_t rd_cnt; /* Tx entry ring buffer read count */ + spinlock_t rd_cnt_lock; /* Tx entry ring buffer read count spin lock */ +#else + atomic_t wr_idx; /* Tx ring buffer write index *//*George: obsolete */ + atomic_t 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 */ + ULONG 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; + INT32 txwkr_flag; + OSAL_EVENT tx_rx_event; + OSAL_SIGNAL isr_check_complete; + INT32 dump_flag; +#endif + INT32 tx_dbg_dump_flag; + INT32 tx_retry_flag; + INT32 retry_enable_flag; + INT32 tx_retry_count; + INT32 rx_retry_count; + 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 +******************************************************************************** +*/ +extern MTK_WCN_STP_SDIO_HIF_INFO g_stp_sdio_host_info; + +/******************************************************************************* +* 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 stp_sdio_reg_rw(INT32 func_num, INT32 direction, UINT32 offset, UINT32 value); + +#if STP_SDIO_DBG_SUPPORT && (STP_SDIO_TXDBG || STP_SDIO_TXPERFDBG) +VOID stp_sdio_txdbg_dump(VOID); +#endif + +extern INT32 mtk_wcn_stp_sdio_do_own_clr(VOID); +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT +INT32 stp_sdio_deep_sleep_flag_set(MTK_WCN_BOOL flag); +#endif +/* extern INT32 */ +/* mtk_wcn_stp_sdio_do_own_set (void); */ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +INT32 stp_sdio_rw_retry(ENUM_STP_SDIO_HIF_TYPE_T type, UINT32 retry_limit, + MTK_WCN_HIF_SDIO_CLTCTX clt_ctx, UINT32 offset, PUINT32 pData, UINT32 len); +VOID stp_sdio_retry_flag_ctrl(INT32 flag); +INT32 stp_sdio_retry_flag_get(VOID); +INT32 stp_sdio_wake_up_ctrl(MTK_WCN_HIF_SDIO_CLTCTX ctx); +VOID stp_sdio_dump_register(VOID); +INT32 stp_sdio_issue_fake_coredump(UINT8 *str); +VOID stp_sdio_dump_info(MTK_WCN_STP_SDIO_HIF_INFO *p_info); + + +#endif /* _STP_SDIO_H */ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_alarm.h b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_alarm.h new file mode 100644 index 0000000000000..d45d632770578 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_alarm.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#ifndef _WMT_ALARM_H_ +#define _WMT_ALARM_H_ + +int wmt_alarm_init(void); +int wmt_alarm_deinit(void); + +int wmt_alarm_start(unsigned int sec); +int wmt_alarm_cancel(void); + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_dbg.h b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_dbg.h new file mode 100644 index 0000000000000..bc16dbd6acd3d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_dbg.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef _WMT_DBG_H_ +#define _WMT_DBG_H_ +#include "osal.h" + +#define STP_SDIO 0x04 +#define STP_UART_MAND 0x02 +#define STP_UART_FULL 0x01 + +#if (WMT_DBG_SUPPORT) +#define CFG_WMT_DBG_SUPPORT 1 /* support wmt_dbg or not */ +#else +#define CFG_WMT_DBG_SUPPORT 0 +#endif + +#define CFG_WMT_PROC_FOR_AEE 1 + +typedef struct _COEX_BUF { + UINT8 buffer[128]; + INT32 availSize; +} COEX_BUF, *P_COEX_BUF; + +typedef enum _ENUM_CMD_TYPE_T { + WMTDRV_CMD_ASSERT = 0, + WMTDRV_CMD_EXCEPTION = 1, + WMTDRV_CMD_COEXDBG_00 = 2, + WMTDRV_CMD_COEXDBG_01 = 3, + WMTDRV_CMD_COEXDBG_02 = 4, + WMTDRV_CMD_COEXDBG_03 = 5, + WMTDRV_CMD_COEXDBG_04 = 6, + WMTDRV_CMD_COEXDBG_05 = 7, + WMTDRV_CMD_COEXDBG_06 = 8, + WMTDRV_CMD_COEXDBG_07 = 9, + WMTDRV_CMD_COEXDBG_08 = 10, + WMTDRV_CMD_COEXDBG_09 = 11, + WMTDRV_CMD_COEXDBG_10 = 12, + WMTDRV_CMD_COEXDBG_11 = 13, + WMTDRV_CMD_COEXDBG_12 = 14, + WMTDRV_CMD_COEXDBG_13 = 15, + WMTDRV_CMD_COEXDBG_14 = 16, + WMTDRV_CMD_COEXDBG_15 = 17, + WMTDRV_CMD_NOACK_TEST = 18, + WMTDRV_CMD_WARNRST_TEST = 19, + WMTDRV_CMD_FWTRACE_TEST = 20, + WMTDRV_CMD_MAX +} ENUM_WMTDRV_CMD_T, *P_ENUM_WMTDRV_CMD_T; + + +typedef INT32(*WMT_DEV_DBG_FUNC) (INT32 par1, INT32 par2, INT32 par3); +INT32 wmt_dev_dbg_setup(VOID); +INT32 wmt_dev_dbg_remove(VOID); +INT32 wmt_dbg_fwinfor_from_emi(INT32 par1, INT32 par2, INT32 par3); + +#endif /* _WMT_DBG_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_dev.h b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_dev.h new file mode 100644 index 0000000000000..0aec923213db5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_dev.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef _WMT_DEV_H_ +#define _WMT_DEV_H_ + +#include "osal.h" + +#define STP_UART_FULL 0x01 +#define STP_UART_MAND 0x02 +#define STP_BTIF_FULL 0x03 +#define STP_SDIO 0x04 + +VOID wmt_dev_rx_event_cb(VOID); +INT32 wmt_dev_rx_timeout(P_OSAL_EVENT pEvent); +INT32 wmt_dev_patch_get(PUINT8 pPatchName, osal_firmware **ppPatch); +INT32 wmt_dev_patch_put(osal_firmware **ppPatch); +VOID wmt_dev_patch_info_free(VOID); +VOID wmt_dev_send_cmd_to_daemon(UINT32 cmd); +MTK_WCN_BOOL wmt_dev_get_early_suspend_state(VOID); +INT32 wmt_lpbk_handler(UINT32 on_off_flag, UINT32 retry); +VOID wmt_dev_blank_handler(VOID); +UINT32 wmt_dev_get_blank_state(VOID); +INT32 wmt_dev_apo_ctrl(UINT32 enable); +VOID wmt_dev_set_temp_threshold(INT32 val); +UINT8 wmt_dev_is_close(VOID); +extern LONG wmt_dev_tm_temp_query(VOID); + +INT32 mtk_wcn_common_drv_init(VOID); +VOID mtk_wcn_common_drv_exit(VOID); + +int mtk_wcn_hif_sdio_drv_init(VOID); +int mtk_wcn_stp_uart_drv_init(VOID); +int mtk_wcn_stp_sdio_drv_init(VOID); +int mtk_wcn_hif_sdio_driver_exit(VOID); +int mtk_wcn_stp_sdio_drv_exit(VOID); +int mtk_wcn_stp_uart_drv_exit(VOID); + +#endif /*_WMT_DEV_H_*/ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_idc.h b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_idc.h new file mode 100644 index 0000000000000..3ea0635619492 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_idc.h @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef _WMT_IDC_H_ +#define _WMT_IDC_H_ + +#include "osal.h" +#include "stp_exp.h" + +#if CFG_WMT_LTE_COEX_HANDLING + +#include +#include "conn_md_exp.h" + +#define LTE_IDC_BUFFER_MAX_SIZE 1024 +/*comment from firmware owner,max pckage num is 5,but should not happened*/ +#define WMT_IDC_RX_MAX_LEN 384 +#define LTE_MSG_ID_OFFSET 0x30 + +typedef enum { + WMT_IDC_TX_OPCODE_MIN = 0, + WMT_IDC_TX_OPCODE_LTE_PARA = 0x0a, + WMT_IDC_TX_OPCODE_LTE_FREQ = 0x0b, + WMT_IDC_TX_OPCODE_WIFI_MAX_POWER = 0x0c, + WMT_IDC_TX_OPCODE_DEBUG_MONITOR = 0x0e, + WMT_IDC_TX_OPCODE_SPLIT_FILTER = 0x0f, + WMT_IDC_TX_OPCODE_LTE_CONNECTION_STAS = 0x16, + WMT_IDC_TX_OPCODE_LTE_HW_IF_INDICATION = 0x17, + WMT_IDC_TX_OPCODE_LTE_INDICATION = 0x20, + WMT_IDC_TX_OPCODE_MAX +} WMT_IDC_TX_OPCODE; + +typedef enum { + WMT_IDC_RX_OPCODE_BTWF_DEF_PARA = 0x0, + WMT_IDC_RX_OPCODE_BTWF_CHAN_RAN = 0x1, + /* WMT_IDC_RX_OPCODE_TDM_REQ = 0x10, */ + WMT_IDC_RX_OPCODE_DEBUG_MONITOR = 0x02, + WMT_IDC_RX_OPCODE_LTE_FREQ_IDX_TABLE = 0x03, + WMT_IDC_RX_OPCODE_BTWF_PROFILE_IND = 0x04, + WMT_IDC_RX_OPCODE_UART_PIN_SEL = 0x05, + WMT_IDC_RX_OPCODE_MAX +} WMT_IDC_RX_OPCODE; + +#if (CFG_WMT_LTE_ENABLE_MSGID_MAPPING == 0) +typedef enum { + IPC_L4C_MSG_ID_INVALID = IPC_L4C_MSG_ID_BEGIN, + IPC_L4C_MSG_ID_END, + IPC_EL1_MSG_ID_INVALID = IPC_EL1_MSG_ID_BEGIN, + /* below are EL1 IPC messages sent from AP */ + IPC_MSG_ID_EL1_LTE_TX_ALLOW_IND, + IPC_MSG_ID_EL1_WIFIBT_OPER_DEFAULT_PARAM_IND, + IPC_MSG_ID_EL1_WIFIBT_OPER_FREQ_IND, + IPC_MSG_ID_EL1_WIFIBT_FREQ_IDX_TABLE_IND, + IPC_MSG_ID_EL1_WIFIBT_PROFILE_IND, + + /* below are EL1 messages sent to AP */ + IPC_MSG_ID_EL1_LTE_DEFAULT_PARAM_IND, + IPC_MSG_ID_EL1_LTE_OPER_FREQ_PARAM_IND, + IPC_MSG_ID_EL1_WIFI_MAX_PWR_IND, + IPC_MSG_ID_EL1_LTE_TX_IND, + IPC_MSG_ID_EL1_LTE_CONNECTION_STATUS_IND, + IPC_MSG_ID_EL1_PIN_TYPE_IND, + IPC_MSG_ID_EL1_LTE_HW_INTERFACE_IND, + IPC_MSG_ID_EL1_DUMMY13_IND, + IPC_MSG_ID_EL1_DUMMY14_IND, + IPC_MSG_ID_EL1_DUMMY15_IND, + IPC_MSG_ID_EL1_DUMMY16_IND, + IPC_MSG_ID_EL1_DUMMY17_IND, + IPC_MSG_ID_EL1_DUMMY18_IND, + IPC_MSG_ID_EL1_DUMMY19_IND, + IPC_MSG_ID_EL1_DUMMY20_IND, + IPC_MSG_ID_EL1_DUMMY21_IND, + IPC_MSG_ID_EL1_DUMMY22_IND, + IPC_MSG_ID_EL1_DUMMY23_IND, + IPC_MSG_ID_EL1_DUMMY24_IND, + IPC_MSG_ID_EL1_DUMMY25_IND, + IPC_MSG_ID_EL1_DUMMY26_IND, + IPC_MSG_ID_EL1_DUMMY27_IND, + IPC_MSG_ID_EL1_DUMMY28_IND, + IPC_MSG_ID_EL1_DUMMY29_IND, + IPC_MSG_ID_EL1_DUMMY30_IND, + IPC_MSG_ID_MD_CONSYS_VERIFICATION_IND, + IPC_MSG_ID_MD_CONSYS_VERIFICATION_REQ, + IPC_EL1_MSG_ID_END, +} IPC_MSG_ID_CODE; +#endif + +typedef struct _MTK_WCN_WMT_IDC_INFO_ { + conn_md_ipc_ilm_t iit; + struct conn_md_bridge_ops ops; + UINT8 buffer[LTE_IDC_BUFFER_MAX_SIZE]; +} MTK_WCN_WMT_IDC_INFO, *P_MTK_WCN_WMT_IDC_INFO; + +INT32 wmt_idc_init(VOID); +INT32 wmt_idc_deinit(VOID); +INT32 wmt_idc_msg_from_lte_handing(conn_md_ipc_ilm_t *ilm); +INT32 wmt_idc_msg_to_lte_handing(VOID); +UINT32 wmt_idc_msg_to_lte_handing_for_test(PUINT8 p_buf, UINT32 len); + +#endif /* endif CFG_WMT_LTE_COEX_HANDLING */ + +#endif /* _WMT_IDC_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_proc_dbg.h b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_proc_dbg.h new file mode 100644 index 0000000000000..1e8ed9be99f8d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_proc_dbg.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#ifndef _WMT_PROC_DBG_H_ +#define _WMT_PROC_DBG_H_ + +#include "osal.h" + +#define CFG_WMT_PROC_FOR_AEE 1 +#define CFG_WMT_PROC_FOR_DUMP_INFO 1 + +#if CFG_WMT_PROC_FOR_DUMP_INFO +INT32 wmt_dev_proc_for_dump_info_setup(VOID); +INT32 wmt_dev_proc_for_dump_info_remove(VOID); +#else +INT32 wmt_dev_proc_for_dump_info_setup(VOID) {} +INT32 wmt_dev_proc_for_dump_info_remove(VOID) {} +#endif + +INT32 wmt_dev_proc_init(VOID); +INT32 wmt_dev_proc_deinit(VOID); + + +#endif /* _WMT_PROC_DBG_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_step.h b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_step.h new file mode 100644 index 0000000000000..8be5dc860b610 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_step.h @@ -0,0 +1,373 @@ +/* + * Copyright (C) 2016 MediaTek Inc. * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef _WMT_STEP_H_ +#define _WMT_STEP_H_ + +#include + +#include "osal.h" +#include "wmt_exp.h" +#include "wmt_core.h" + +#define STEP_CONFIG_NAME "WMT_STEP.cfg" +#define STEP_VERSION 2 + +#define STEP_PERIODIC_DUMP_WORK_QUEUE "wmt_step_pd_wq" +#define STEP_PERIODIC_DUMP_THREAD "wmt_pd" + +#define STEP_ACTION_NAME_EMI "_EMI" +#define STEP_ACTION_NAME_REGISTER "_REG" +#define STEP_ACTION_NAME_GPIO "GPIO" +#define STEP_ACTION_NAME_DISABLE_RESET "DRST" +#define STEP_ACTION_NAME_CHIP_RESET "_RST" +#define STEP_ACTION_NAME_KEEP_WAKEUP "WAK+" +#define STEP_ACTION_NAME_CANCEL_WAKEUP "WAK-" +#define STEP_ACTION_NAME_SHOW_STRING "SHOW" +#define STEP_ACTION_NAME_SLEEP "_SLP" +#define STEP_ACTION_NAME_CONDITION "COND" +#define STEP_ACTION_NAME_VALUE "_VAL" +#define STEP_ACTION_NAME_CONDITION_EMI "CEMI" +#define STEP_ACTION_NAME_CONDITION_REGISTER "CREG" + +extern struct platform_device *g_pdev; + +enum step_action_id { + STEP_ACTION_INDEX_NO_DEFINE = 0, + STEP_ACTION_INDEX_EMI = 1, + STEP_ACTION_INDEX_REGISTER, + STEP_ACTION_INDEX_GPIO, + STEP_ACTION_INDEX_DISABLE_RESET, + STEP_ACTION_INDEX_CHIP_RESET, + STEP_ACTION_INDEX_KEEP_WAKEUP, + STEP_ACTION_INDEX_CANCEL_WAKEUP, + STEP_ACTION_INDEX_PERIODIC_DUMP, + STEP_ACTION_INDEX_SHOW_STRING, + STEP_ACTION_INDEX_SLEEP, + STEP_ACTION_INDEX_CONDITION, + STEP_ACTION_INDEX_VALUE, + STEP_ACTION_INDEX_CONDITION_EMI, + STEP_ACTION_INDEX_CONDITION_REGISTER, + STEP_ACTION_INDEX_MAX, +}; + +enum step_trigger_point_id { + STEP_TRIGGER_POINT_NO_DEFINE = 0, + STEP_TRIGGER_POINT_COMMAND_TIMEOUT = 1, + STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT, + STEP_TRIGGER_POINT_BEFORE_CHIP_RESET, + STEP_TRIGGER_POINT_AFTER_CHIP_RESET, + STEP_TRIGGER_POINT_BEFORE_WIFI_FUNC_ON, + STEP_TRIGGER_POINT_BEFORE_WIFI_FUNC_OFF, + STEP_TRIGGER_POINT_BEFORE_BT_FUNC_ON, + STEP_TRIGGER_POINT_BEFORE_BT_FUNC_OFF, + STEP_TRIGGER_POINT_BEFORE_FM_FUNC_ON, + STEP_TRIGGER_POINT_BEFORE_FM_FUNC_OFF, + STEP_TRIGGER_POINT_BEFORE_GPS_FUNC_ON, + STEP_TRIGGER_POINT_BEFORE_GPS_FUNC_OFF, + STEP_TRIGGER_POINT_BEFORE_READ_THERMAL, + STEP_TRIGGER_POINT_POWER_ON_START, + STEP_TRIGGER_POINT_POWER_ON_BEFORE_GET_CONNSYS_ID, + STEP_TRIGGER_POINT_POWER_ON_BEFORE_SEND_DOWNLOAD_PATCH, + STEP_TRIGGER_POINT_POWER_ON_BEFORE_CONNSYS_RESET, + STEP_TRIGGER_POINT_POWER_ON_BEFORE_SET_WIFI_LTE_COEX, + STEP_TRIGGER_POINT_POWER_ON_BEFORE_BT_WIFI_CALIBRATION, + STEP_TRIGGER_POINT_POWER_ON_END, + STEP_TRIGGER_POINT_BEFORE_POWER_OFF, + STEP_TRIGGER_POINT_WHEN_AP_SUSPEND, + STEP_TRIGGER_POINT_WHEN_AP_RESUME, + STEP_TRIGGER_POINT_POWER_OFF_HANDSHAKE, + STEP_TRIGGER_POINT_BEFORE_RESTORE_CAL_RESULT, + STEP_TRIGGER_POINT_AFTER_RESTORE_CAL_RESULT, + STEP_TRIGGER_POINT_POWER_ON_AFTER_BT_WIFI_CALIBRATION, + STEP_TRIGGER_POINT_AFTER_RESTORE_CAL_CMD, + STEP_TRIGGER_POINT_WHEN_CLOCK_FAIL, + STEP_TRIGGER_POINT_BEFORE_GPSL5_FUNC_ON, + STEP_TRIGGER_POINT_BEFORE_GPSL5_FUNC_OFF, + STEP_TRIGGER_POINT_MAX, +}; + +enum step_base_address_index { + STEP_MCU_BASE_INDEX = 0, + STEP_TOP_RGU_BASE_INDEX, + STEP_INFRACFG_AO_BASE_INDEX, + STEP_SPM_BASE_INDEX, + STEP_MCU_CONN_HIF_ON_BASE_INDEX, + STEP_MCU_TOP_MISC_OFF_BASE_INDEX, + STEP_MCU_CFG_ON_BASE_INDEX, + STEP_MCU_CIRQ_BASE_INDEX, + STEP_MCU_TOP_MISC_ON_BASE_INDEX, + STEP_BASE_ADDRESS_MAX, +}; + +enum step_register_base_id { + STEP_REGISTER_PHYSICAL_ADDRESS = 0, + STEP_REGISTER_CONN_MCU_CONFIG_BASE, + STEP_REGISTER_AP_RGU_BASE, + STEP_REGISTER_TOPCKGEN_BASE, + STEP_REGISTER_SPM_BASE, + STEP_REGISTER_HIF_ON_BASE, + STEP_REGISTER_MISC_OFF_BASE, + STEP_REGISTER_CFG_ON_BASE, + STEP_CIRQ_BASE, + STEP_MCU_TOP_MISC_ON_BASE, + STEP_REGISTER_MAX, +}; + +enum step_condition_operator_id { + STEP_OPERATOR_GREATER = 0, + STEP_OPERATOR_GREATER_EQUAL, + STEP_OPERATOR_LESS, + STEP_OPERATOR_LESS_EQUAL, + STEP_OPERATOR_EQUAL, + STEP_OPERATOR_NOT_EQUAL, + STEP_OPERATOR_AND, + STEP_OPERATOR_OR, + STEP_OPERATOR_MAX, +}; + +struct step_register_base_struct { + unsigned long vir_addr; + unsigned long long size; +}; + +struct step_action_list { + struct list_head list; +}; + +struct step_pd_entry { + bool is_enable; + unsigned int expires_ms; + struct step_action_list action_list; + struct delayed_work pd_work; + struct list_head list; +}; + +struct step_pd_struct { + bool is_init; + struct workqueue_struct *step_pd_wq; + struct list_head pd_list; +}; + +struct step_action { + struct list_head list; + enum step_action_id action_id; +}; + +typedef int (*STEP_WRITE_ACT_TO_LIST) (struct step_action_list *, enum step_action_id, int, char **); +typedef void (*STEP_DO_EXTRA) (unsigned int, ...); + +#define STEP_OUTPUT_LOG 0 +#define STEP_OUTPUT_REGISTER 1 + +struct step_emi_info { + bool is_write; + unsigned int begin_offset; + unsigned int end_offset; + int value; + unsigned int temp_reg_id; + int output_mode; + int mask; +}; + +struct step_emi_action { + struct step_emi_info info; + struct step_action base; +}; + +struct step_reigster_info { + bool is_write; + enum step_register_base_id address_type; + unsigned long address; + unsigned int offset; + unsigned int times; + unsigned int delay_time; + int value; + int mask; + unsigned int temp_reg_id; + int output_mode; +}; + +struct step_register_action { + struct step_reigster_info info; + struct step_action base; +}; + +struct step_gpio_action { + bool is_write; + unsigned int pin_symbol; + struct step_action base; +}; + +struct step_disable_reset_action { + struct step_action base; +}; + +struct step_chip_reset_action { + struct step_action base; +}; + +struct step_keep_wakeup_action { + struct step_action base; +}; + +struct step_cancel_wakeup_action { + struct step_action base; +}; + +struct step_periodic_dump_action { + struct step_pd_entry *pd_entry; + struct step_action base; +}; + +struct step_show_string_action { + char *content; + struct step_action base; +}; + +struct step_sleep_action { + unsigned int ms; + struct step_action base; +}; + +#define STEP_CONDITION_RIGHT_REGISTER 0 +#define STEP_CONDITION_RIGHT_VALUE 1 +struct step_condition_action { + unsigned int result_temp_reg_id; + unsigned int l_temp_reg_id; + unsigned int r_temp_reg_id; + int value; + int mode; + enum step_condition_operator_id operator_id; + struct step_action base; +}; + +struct step_value_action { + unsigned int temp_reg_id; + int value; + struct step_action base; +}; + +struct step_condition_emi_action { + unsigned int cond_reg_id; + struct step_emi_info info; + struct step_action base; +}; + +struct step_condition_register_action { + unsigned int cond_reg_id; + struct step_reigster_info info; + struct step_action base; +}; + +#define list_entry_action(act_struct, ptr) \ + container_of(ptr, struct step_##act_struct##_action, base) + +struct step_reg_addr_info { + int address_type; + unsigned long address; +}; + +struct step_target_act_list_info { + enum step_trigger_point_id tp_id; + struct step_action_list *p_target_list; + struct step_pd_entry *p_pd_entry; +}; + +#define STEP_PARAMETER_SIZE 10 +struct step_parse_line_data_param_info { + int state; + enum step_action_id act_id; + char *act_params[STEP_PARAMETER_SIZE]; + int param_index; +}; + +typedef struct step_action *(*STEP_CREATE_ACTION) (int, char *[]); +typedef int (*STEP_DO_ACTIONS) (struct step_action *, STEP_DO_EXTRA); +typedef void (*STEP_REMOVE_ACTION) (struct step_action *); +struct step_action_contrl { + STEP_CREATE_ACTION func_create_action; + STEP_DO_ACTIONS func_do_action; + STEP_REMOVE_ACTION func_remove_action; +}; + +#define STEP_REGISTER_BASE_SYMBOL '#' +#define STEP_TEMP_REGISTER_SYMBOL '$' + +#define STEP_VALUE_INFO_UNKNOWN -1 +#define STEP_VALUE_INFO_NUMBER 0 +#define STEP_VALUE_INFO_SYMBOL_REG_BASE 1 +#define STEP_VALUE_INFO_SYMBOL_TEMP_REG 2 + +#define STEP_TEMP_REGISTER_SIZE 10 +struct step_env_struct { + bool is_enable; + bool is_keep_wakeup; + struct step_action_list actions[STEP_TRIGGER_POINT_MAX]; + unsigned char __iomem *emi_base_addr; + struct step_register_base_struct reg_base[STEP_REGISTER_MAX]; + struct step_pd_struct pd_struct; + int temp_register[STEP_TEMP_REGISTER_SIZE]; + bool is_setup; + struct rw_semaphore init_rwsem; +}; + +/******************************************************************************** + * F U N C T I O N D E C L A R A T I O N S +*********************************************************************************/ +void wmt_step_init(void); +void wmt_step_deinit(void); +void wmt_step_do_actions(enum step_trigger_point_id tp_id); +void wmt_step_func_crtl_do_actions(ENUM_WMTDRV_TYPE_T type, ENUM_WMT_OPID_T opId); +void wmt_step_command_timeout_do_actions(char *reason); +#ifdef CFG_WMT_STEP +#define WMT_STEP_INIT_FUNC() wmt_step_init() +#define WMT_STEP_DEINIT_FUNC() wmt_step_deinit() +#define WMT_STEP_DO_ACTIONS_FUNC(tp) wmt_step_do_actions(tp) +#define WMT_STEP_FUNC_CTRL_DO_ACTIONS_FUNC(type, id) wmt_step_func_crtl_do_actions(type, id) +#define WMT_STEP_COMMAND_TIMEOUT_DO_ACTIONS_FUNC(reason) wmt_step_command_timeout_do_actions(reason) +#else +#define WMT_STEP_INIT_FUNC() +#define WMT_STEP_DEINIT_FUNC() +#define WMT_STEP_DO_ACTIONS_FUNC(tp) +#define WMT_STEP_FUNC_CTRL_DO_ACTIONS_FUNC(type, id) +#define WMT_STEP_COMMAND_TIMEOUT_DO_ACTIONS_FUNC(reason) +#endif + +/******************************************************************************** + * D E C L A R E F O R T E S T +*********************************************************************************/ +int wmt_step_read_file(const char *file_name); +int wmt_step_parse_data(const char *in_buf, unsigned int size, STEP_WRITE_ACT_TO_LIST func_act_to_list); +int wmt_step_init_pd_env(void); +int wmt_step_deinit_pd_env(void); +struct step_pd_entry *wmt_step_get_periodic_dump_entry(unsigned int expires); +struct step_action *wmt_step_create_action(enum step_action_id act_id, int param_num, char *params[]); +int wmt_step_do_emi_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra); +int wmt_step_do_register_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra); +int wmt_step_do_gpio_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra); +int wmt_step_do_disable_reset_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra); +int wmt_step_do_chip_reset_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra); +int wmt_step_do_keep_wakeup_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra); +int wmt_step_do_cancel_wakeup_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra); +int wmt_step_do_periodic_dump_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra); +int wmt_step_do_show_string_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra); +int wmt_step_do_sleep_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra); +int wmt_step_do_condition_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra); +int wmt_step_do_value_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra); +int wmt_step_do_condition_emi_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra); +int wmt_step_do_condition_register_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra); +void wmt_step_remove_action(struct step_action *p_act); +void wmt_step_print_version(void); + +#endif /* end of _WMT_STEP_H_ */ + diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_user_proc.h b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_user_proc.h new file mode 100644 index 0000000000000..1bef0e0f78ddd --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/include/wmt_user_proc.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ + +#ifndef _WMT_USER_PROC_H_ +#define _WMT_USER_PROC_H_ +#include "osal.h" + +typedef INT32(*WMT_DEV_USER_PROC_FUNC) (INT32 par1, INT32 par2, INT32 par3); +INT32 wmt_dev_user_proc_setup(VOID); +INT32 wmt_dev_user_proc_remove(VOID); + +#endif /* _WMT_USER_PROC_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/osal.c b/drivers/misc/mediatek/connectivity/common/common_main/linux/osal.c new file mode 100644 index 0000000000000..d0a31a63c3c53 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/osal.c @@ -0,0 +1,1803 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/*! \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.h" +#include "connectivity_build_in_adapter.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define GPIO_ASSERT 70 +/******************************************************************************* +* 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 +}; + +INT32 ftrace_flag; +/******************************************************************************* +* 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*/ +UINT32 osal_strlen(const PINT8 str) +{ + return strlen(str); +} + +INT32 osal_strcmp(const PINT8 dst, const PINT8 src) +{ + return strcmp(dst, src); +} + +INT32 osal_strncmp(const PINT8 dst, const PINT8 src, UINT32 len) +{ + return strncmp(dst, src, len); +} + +PINT8 osal_strcpy(PINT8 dst, const PINT8 src) +{ + return strncpy(dst, src, strlen(src)+1); +} + +PINT8 osal_strncpy(PINT8 dst, const PINT8 src, UINT32 len) +{ + return strncpy(dst, src, len); +} + +PINT8 osal_strcat(PINT8 dst, const PINT8 src) +{ + return strncat(dst, src, strlen(src)); +} + +PINT8 osal_strncat(PINT8 dst, const PINT8 src, UINT32 len) +{ + return strncat(dst, src, len); +} + +PINT8 osal_strchr(const PINT8 str, UINT8 c) +{ + return strchr(str, c); +} + +PINT8 osal_strsep(PPINT8 str, const PINT8 c) +{ + return strsep(str, c); +} + +INT32 osal_strtol(const PINT8 str, UINT32 adecimal, PLONG res) +{ + if (sizeof(LONG) == 4) + return kstrtou32(str, adecimal, (UINT32 *) res); + else + return kstrtol(str, adecimal, res); +} + +PINT8 osal_strstr(PINT8 str1, const PINT8 str2) +{ + return strstr(str1, str2); +} + +PINT8 osal_strnstr(PINT8 str1, const PINT8 str2, INT32 n) +{ + return strnstr(str1, str2, n); +} + +VOID osal_bug_on(UINT32 val) +{ + WARN_ON(val); +} + +INT32 osal_snprintf(PINT8 buf, UINT32 len, const PINT8 fmt, ...) +{ + INT32 iRet = 0; + va_list args; + + va_start(args, fmt); + iRet = vsnprintf(buf, len, fmt, args); + va_end(args); + + if (iRet < 0) + pr_info("vsnprintf error:%d\n", iRet); + + return iRet; +} + +INT32 osal_err_print(const PINT8 str, ...) +{ + va_list args; + INT32 ret; + INT8 tempString[DBG_LOG_STR_SIZE]; + + va_start(args, str); + ret = vsnprintf(tempString, DBG_LOG_STR_SIZE, str, args); + va_end(args); + + if (ret > 0) + pr_err("%s", tempString); + + return ret; +} + +INT32 osal_dbg_print(const PINT8 str, ...) +{ + va_list args; + INT32 ret; + INT8 tempString[DBG_LOG_STR_SIZE]; + + va_start(args, str); + ret = vsnprintf(tempString, DBG_LOG_STR_SIZE, str, args); + va_end(args); + + if (ret > 0) + pr_debug("%s", tempString); + + return ret; +} + +INT32 osal_warn_print(const PINT8 str, ...) +{ + va_list args; + INT32 ret; + INT8 tempString[DBG_LOG_STR_SIZE]; + + va_start(args, str); + ret = vsnprintf(tempString, DBG_LOG_STR_SIZE, str, args); + va_end(args); + + if (ret > 0) + pr_warn("%s", tempString); + + return ret; +} + +INT32 osal_dbg_assert(INT32 expr, const PINT8 file, INT32 line) +{ + if (!expr) { + pr_warn("%s (%d)\n", file, line); + /*BUG_ON(!expr); */ +#ifdef CFG_COMMON_GPIO_DBG_PIN +/* package this part */ + gpio_direction_output(GPIO_ASSERT, 0); + pr_warn("toggle GPIO_ASSERT = %d\n", GPIO_ASSERT); + udelay(10); + gpio_set_value(GPIO_ASSERT, 1); +#endif + return 1; + } + return 0; + +} + +INT32 osal_dbg_assert_aee(const PINT8 module, const PINT8 detail_description, ...) +{ + INT8 tempString[DBG_LOG_STR_SIZE]; + va_list args; + + va_start(args, detail_description); + if (vsnprintf(tempString, DBG_LOG_STR_SIZE, detail_description, args) > 0) { + osal_err_print("[WMT-ASSERT][E][Module]:%s, [INFO]%s\n", module, tempString); +#ifdef WMT_PLAT_ALPS + /* There exists Format-String vulnerability. For safety, we must use the %s + * format parameter to read data. + */ +#if IS_ENABLED(CONFIG_MTK_AEE_AED) + aee_kernel_warning_api(__FILE__, __LINE__, DB_OPT_WCN_ISSUE_INFO, module, + detail_description, "%s", tempString); +#endif +#endif + } + va_end(args); + return 0; +} + +INT32 osal_sprintf(PINT8 str, const PINT8 format, ...) +{ + INT32 iRet = 0; + va_list args; + + va_start(args, format); + iRet = vsnprintf(str, DBG_LOG_STR_SIZE, format, args); + if (iRet < 0) + osal_err_print("vsnprintf error [%d]\n", iRet); + va_end(args); + + return iRet; +} + +PVOID osal_malloc(UINT32 size) +{ + PVOID p = NULL; + + if (size > (PAGE_SIZE << 1)) + p = vmalloc(size); + else + p = kmalloc(size, GFP_KERNEL); + + /* If there is fragment, kmalloc may not get memory when size > one page. + * For this case, use vmalloc instead. + */ + if (p == NULL && size > PAGE_SIZE) + p = vmalloc(size); + return p; +} + +VOID osal_free(const PVOID dst) +{ + kvfree(dst); +} + +PVOID osal_memset(PVOID buf, INT32 i, UINT32 len) +{ + return memset(buf, i, len); +} + +PVOID osal_memcpy(PVOID dst, const PVOID src, UINT32 len) +{ + return memcpy(dst, src, len); +} + +VOID osal_memcpy_fromio(PVOID dst, const PVOID src, UINT32 len) +{ + return memcpy_fromio(dst, src, len); +} + +VOID osal_memcpy_toio(PVOID dst, const PVOID src, UINT32 len) +{ + return memcpy_toio(dst, src, len); +} + +INT32 osal_memcmp(const PVOID buf1, const PVOID buf2, UINT32 len) +{ + return memcmp(buf1, buf2, len); +} + +UINT16 osal_crc16(const PUINT8 buffer, const UINT32 length) +{ + UINT16 crc = 0; + UINT32 i = 0; + PUINT8 temp = buffer; + + /* FIXME: Add STP checksum feature */ + crc = 0; + for (i = 0; i < length; i++, temp++) + crc = (crc >> 8) ^ crc16_table[(crc ^ (*temp)) & 0xff]; + return crc; +} + +VOID osal_dump_thread_state(const PUINT8 name) +{ +#if defined(KERNEL_dump_thread_state) + return KERNEL_dump_thread_state(name); +#endif +} + +VOID osal_thread_show_stack(P_OSAL_THREAD pThread) +{ + if ((pThread) && (pThread->pThread)) + KERNEL_show_stack(pThread->pThread, NULL); +} + +/* + *OSAL layer Thread Opeartion related APIs + * + * +*/ +INT32 osal_thread_create(P_OSAL_THREAD pThread) +{ + if (!pThread) + return -1; + + pThread->pThread = kthread_create(pThread->pThreadFunc, pThread->pThreadData, pThread->threadName); + if (pThread->pThread == NULL) + return -1; + + return 0; +} + +INT32 osal_thread_run(P_OSAL_THREAD pThread) +{ + if ((pThread) && (pThread->pThread)) { + wake_up_process(pThread->pThread); + return 0; + } else { + return -1; + } +} + +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; +} + +INT32 osal_thread_should_stop(P_OSAL_THREAD pThread) +{ + if ((pThread) && (pThread->pThread)) + return kthread_should_stop(); + else + return 1; + +} + +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; +} + +INT32 osal_thread_destroy(P_OSAL_THREAD pThread) +{ + if (pThread && (pThread->pThread)) { + kthread_stop(pThread->pThread); + pThread->pThread = NULL; + } + return 0; +} + +/* + * osal_thread_sched_retrieve + * Retrieve thread's current scheduling statistics and stored in output "sched". + * Return value: + * 0 : Schedstats successfully retrieved + * -1 : Kernel's schedstats feature not enabled + * -2 : pThread not yet initialized or sched is a NULL pointer + */ +static INT32 osal_thread_sched_retrieve(P_OSAL_THREAD pThread, P_OSAL_THREAD_SCHEDSTATS sched) +{ +#ifdef CONFIG_SCHEDSTATS + struct sched_entity se; + UINT64 sec; + ULONG usec; + + if (!sched) + return -2; + + /* always clear sched to simplify error handling at caller side */ + memset(sched, 0, sizeof(OSAL_THREAD_SCHEDSTATS)); + + if (!pThread || !pThread->pThread) + return -2; + + memcpy(&se, &pThread->pThread->se, sizeof(struct sched_entity)); + osal_get_local_time(&sec, &usec); + + sched->time = sec*1000 + usec/1000; + sched->exec = se.sum_exec_runtime; + sched->runnable = se.statistics.wait_sum; + sched->iowait = se.statistics.iowait_sum; + + return 0; +#else + /* always clear sched to simplify error handling at caller side */ + if (sched) + memset(sched, 0, sizeof(OSAL_THREAD_SCHEDSTATS)); + return -1; +#endif +} + +/* + * osal_thread_sched_mark + * Record the thread's current schedstats and stored in output "schedstats" parameter for profiling at later time. + * Return value: + * 0 : Schedstats successfully recorded + * -1 : Kernel's schedstats feature not enabled + * -2 : pThread not yet initialized or invalid parameters + */ +INT32 osal_thread_sched_mark(P_OSAL_THREAD pThread, P_OSAL_THREAD_SCHEDSTATS schedstats) +{ + return osal_thread_sched_retrieve(pThread, schedstats); +} + +/* + * osal_thread_sched_unmark + * Calculate scheduling statistics against the previously marked point. + * The result will be filled back into the schedstats output parameter. + * Return value: + * 0 : Schedstats successfully calculated + * -1 : Kernel's schedstats feature not enabled + * -2 : pThread not yet initialized or invalid parameters + */ +INT32 osal_thread_sched_unmark(P_OSAL_THREAD pThread, P_OSAL_THREAD_SCHEDSTATS schedstats) +{ + INT32 ret; + OSAL_THREAD_SCHEDSTATS sched_now; + + if (unlikely(!schedstats)) { + ret = -2; + } else { + ret = osal_thread_sched_retrieve(pThread, &sched_now); + if (ret == 0) { + schedstats->time = sched_now.time - schedstats->time; + schedstats->exec = sched_now.exec - schedstats->exec; + schedstats->runnable = sched_now.runnable - schedstats->runnable; + schedstats->iowait = sched_now.iowait - schedstats->iowait; + } + } + return ret; +} + +/* + *OSAL layer Signal Opeartion related APIs + *initialization + *wait for signal + *wait for signal timerout + *raise signal + *destroy a signal + * +*/ + +INT32 osal_signal_init(P_OSAL_SIGNAL pSignal) +{ + if (pSignal) { + init_completion(&pSignal->comp); + return 0; + } else { + return -1; + } +} + +INT32 osal_wait_for_signal(P_OSAL_SIGNAL pSignal) +{ + if (pSignal) { + wait_for_completion_interruptible(&pSignal->comp); + return 0; + } else { + return -1; + } +} + +/* + * osal_wait_for_signal_timeout + * + * Wait for a signal to be triggered by the corresponding thread, within the + * expected timeout specified by the signal's timeoutValue. + * When the pThread parameter is specified, the thread's scheduling ability is + * considered, the timeout will be extended when thread cannot acquire CPU + * resource, and will only extend for a number of times specified by the + * signal's timeoutExtension should the situation continues. + * + * Return value: + * 0 : timeout + * >0 : signal triggered + */ +INT32 osal_wait_for_signal_timeout(P_OSAL_SIGNAL pSignal, P_OSAL_THREAD pThread) +{ + OSAL_THREAD_SCHEDSTATS schedstats; + INT32 waitRet; + + /* 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. + */ + if (!pThread || !pThread->pThread) + return wait_for_completion_timeout(&pSignal->comp, msecs_to_jiffies(pSignal->timeoutValue)); + + do { + osal_thread_sched_mark(pThread, &schedstats); + waitRet = wait_for_completion_timeout(&pSignal->comp, msecs_to_jiffies(pSignal->timeoutValue)); + osal_thread_sched_unmark(pThread, &schedstats); + + if (waitRet > 0) + break; + + if (schedstats.runnable > schedstats.exec) { + osal_err_print( + "[E]%s:wait completion timeout, %s cannot get CPU, extension(%d), show backtrace:\n", + __func__, + pThread->threadName, + pSignal->timeoutExtension); + } else { + osal_err_print("[E]%s:wait completion timeout, show %s backtrace:\n", + __func__, + pThread->threadName); + pSignal->timeoutExtension = 0; + } + osal_err_print("[E]%s:\tduration:%llums, sched(x%llu/r%llu/i%llu)\n", + __func__, + schedstats.time, + schedstats.exec, + schedstats.runnable, + schedstats.iowait); + /* + * no need to disginguish combo or A/D die projects + * osal_dump_thread_state will just return if target thread does not exist + */ + osal_dump_thread_state("mtk_wmtd"); + osal_dump_thread_state("mtk_wmtd_worker"); + osal_dump_thread_state("btif_rxd"); + osal_dump_thread_state("mtk_stp_psm"); + osal_dump_thread_state("mtk_stp_btm"); + osal_dump_thread_state("stp_sdio_tx_rx"); + } while (pSignal->timeoutExtension--); + return waitRet; +} + +INT32 osal_raise_signal(P_OSAL_SIGNAL pSignal) +{ + if (pSignal) { + complete(&pSignal->comp); + return 0; + } else + return -1; +} + +INT32 osal_signal_active_state(P_OSAL_SIGNAL pSignal) +{ + if (pSignal) + return pSignal->timeoutValue; + else + return -1; +} + +INT32 osal_signal_deinit(P_OSAL_SIGNAL pSignal) +{ + if (pSignal) { + pSignal->timeoutValue = 0; + return 0; + } else + return -1; +} + +/* + *OSAL layer Event Opeartion related APIs + *initialization + *wait for signal + *wait for signal timerout + *raise signal + *destroy a signal + * +*/ + +INT32 osal_event_init(P_OSAL_EVENT pEvent) +{ + if (pEvent) { + init_waitqueue_head(&pEvent->waitQueue); + return 0; + } + return -1; +} + +INT32 osal_trigger_event(P_OSAL_EVENT pEvent) +{ + INT32 ret = 0; + + if (pEvent) { + wake_up_interruptible(&pEvent->waitQueue); + return ret; + } + return -1; +} + +INT32 osal_wait_for_event(P_OSAL_EVENT pEvent, INT32(*condition) (PVOID), PVOID cond_pa) +{ + if (pEvent) + return wait_event_interruptible(pEvent->waitQueue, condition(cond_pa)); + else + return -1; +} + +INT32 osal_wait_for_event_timeout(P_OSAL_EVENT pEvent, INT32(*condition) (PVOID), PVOID cond_pa) +{ + if (pEvent) + return wait_event_interruptible_timeout(pEvent->waitQueue, + condition(cond_pa), + msecs_to_jiffies(pEvent->timeoutValue)); + return -1; +} + + + +INT32 osal_event_deinit(P_OSAL_EVENT pEvent) +{ + return 0; +} + +LONG osal_wait_for_event_bit_set(P_OSAL_EVENT pEvent, PULONG pState, UINT32 bitOffset) +{ + UINT32 ms = 0; + + if (pEvent) { + 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)); + } else + return -1; + +} + +LONG osal_wait_for_event_bit_clr(P_OSAL_EVENT pEvent, PULONG pState, UINT32 bitOffset) +{ + UINT32 ms = 0; + + if (pEvent) { + 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)); + } else + return -1; +} + +/* + *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 + +INT32 osal_bit_op_lock(P_OSAL_UNSLEEPABLE_LOCK pLock) +{ + + return 0; +} + +INT32 osal_bit_op_unlock(P_OSAL_UNSLEEPABLE_LOCK pLock) +{ + + return 0; +} +#endif +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; +} + +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; +} + +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; +} + +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; + +} + +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; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) + timer_setup(timer, pTimer->timeoutHandler, 0); +#else + init_timer(timer); + timer->function = pTimer->timeoutHandler; + timer->data = (ULONG)pTimer->timeroutHandlerData; +#endif + 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, PUINT8 buf, UINT32 size) +{ + struct kfifo *fifo = NULL; + INT32 ret = -1; + + if (!pFifo) { + pr_err("pFifo must be !NULL\n"); + return -1; + } + if (pFifo->pFifoBody) { + pr_err("pFifo->pFifoBody must be NULL\n"); + pr_err("pFifo(0x%p), pFifo->pFifoBody(0x%p)\n", pFifo, pFifo->pFifoBody); + return -1; + } + fifo = kzalloc(sizeof(struct kfifo), GFP_ATOMIC); + if (!buf) { + /*fifo's buffer is not ready, we allocate automatically */ + ret = kfifo_alloc(fifo, size, /*GFP_KERNEL */ GFP_ATOMIC); + } else { + if (is_power_of_2(size)) { + kfifo_init(fifo, buf, size); + ret = 0; + } else { + kfifo_free(fifo); + fifo = NULL; + ret = -1; + } + } + + pFifo->pFifoBody = fifo; + return (ret < 0) ? (-1) : (0); +} + +INT32 _osal_fifo_deinit(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo) + kfifo_free(fifo); + + return 0; +} + +INT32 _osal_fifo_size(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + INT32 ret = 0; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo) + ret = kfifo_size(fifo); + + return ret; +} + +/*returns unused bytes in fifo*/ +INT32 _osal_fifo_avail_size(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + INT32 ret = 0; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo) + ret = kfifo_avail(fifo); + + return ret; +} + +/*returns used bytes in fifo*/ +INT32 _osal_fifo_len(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + INT32 ret = 0; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo) + ret = kfifo_len(fifo); + + return ret; +} + +INT32 _osal_fifo_is_empty(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + INT32 ret = 0; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo) + ret = kfifo_is_empty(fifo); + + return ret; +} + +INT32 _osal_fifo_is_full(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + INT32 ret = 0; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo) + ret = kfifo_is_full(fifo); + + return ret; +} + +INT32 _osal_fifo_data_in(OSAL_FIFO *pFifo, const PVOID buf, UINT32 len) +{ + struct kfifo *fifo = NULL; + INT32 ret = 0; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo && buf && (len <= _osal_fifo_avail_size(pFifo))) { + ret = kfifo_in(fifo, buf, len); + } else { + pr_err("%s: kfifo_in, error, len = %d, _osal_fifo_avail_size = %d, buf=%p\n", + __func__, len, _osal_fifo_avail_size(pFifo), buf); + + ret = 0; + } + + return ret; +} + +INT32 _osal_fifo_data_out(OSAL_FIFO *pFifo, PVOID buf, UINT32 len) +{ + struct kfifo *fifo = NULL; + INT32 ret = 0; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo && buf && (len <= _osal_fifo_len(pFifo))) { + ret = kfifo_out(fifo, buf, len); + } else { + pr_err("%s: kfifo_out, error, len = %d, osal_fifo_len = %d, buf=%p\n", + __func__, len, _osal_fifo_len(pFifo), buf); + + ret = 0; + } + + return ret; +} + +INT32 _osal_fifo_reset(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo) + kfifo_reset(fifo); + + return 0; +} + +INT32 osal_fifo_init(P_OSAL_FIFO pFifo, UINT8 *buffer, UINT32 size) +{ + if (!pFifo) { + pr_err("%s:pFifo = NULL, error\n", __func__); + return -1; + } + + pFifo->FifoInit = _osal_fifo_init; + pFifo->FifoDeInit = _osal_fifo_deinit; + pFifo->FifoSz = _osal_fifo_size; + pFifo->FifoAvailSz = _osal_fifo_avail_size; + pFifo->FifoLen = _osal_fifo_len; + pFifo->FifoIsEmpty = _osal_fifo_is_empty; + pFifo->FifoIsFull = _osal_fifo_is_full; + pFifo->FifoDataIn = _osal_fifo_data_in; + pFifo->FifoDataOut = _osal_fifo_data_out; + pFifo->FifoReset = _osal_fifo_reset; + + if (pFifo->pFifoBody != NULL) { + pr_err("%s:Because pFifo room is avialable, we clear the room and allocate them again.\n", __func__); + pFifo->FifoDeInit(pFifo); + pFifo->pFifoBody = NULL; + } + + pFifo->FifoInit(pFifo, buffer, size); + + return 0; +} + +VOID osal_fifo_deinit(P_OSAL_FIFO pFifo) +{ + if (pFifo) + pFifo->FifoDeInit(pFifo); + else { + pr_err("%s:pFifo = NULL, error\n", __func__); + return; + } + kfree(pFifo->pFifoBody); + pFifo->pFifoBody = NULL; +} + +INT32 osal_fifo_reset(P_OSAL_FIFO pFifo) +{ + INT32 ret = -1; + + if (pFifo) { + ret = pFifo->FifoReset(pFifo); + } else { + pr_err("%s:pFifo = NULL, error\n", __func__); + ret = -1; + } + return ret; +} + +UINT32 osal_fifo_in(P_OSAL_FIFO pFifo, PUINT8 buffer, UINT32 size) +{ + UINT32 ret = 0; + + if (pFifo) { + ret = pFifo->FifoDataIn(pFifo, buffer, size); + } else { + pr_err("%s:pFifo = NULL, error\n", __func__); + ret = 0; + } + + return ret; +} + +UINT32 osal_fifo_out(P_OSAL_FIFO pFifo, PUINT8 buffer, UINT32 size) +{ + UINT32 ret = 0; + + if (pFifo) { + ret = pFifo->FifoDataOut(pFifo, buffer, size); + } else { + pr_err("%s:pFifo = NULL, error\n", __func__); + ret = 0; + } + + return ret; +} + +UINT32 osal_fifo_len(P_OSAL_FIFO pFifo) +{ + UINT32 ret = 0; + + if (pFifo) { + ret = pFifo->FifoLen(pFifo); + } else { + pr_err("%s:pFifo = NULL, error\n", __func__); + ret = 0; + } + + return ret; +} + +UINT32 osal_fifo_sz(P_OSAL_FIFO pFifo) +{ + UINT32 ret = 0; + + if (pFifo) { + ret = pFifo->FifoSz(pFifo); + } else { + pr_err("%s:pFifo = NULL, error\n", __func__); + ret = 0; + } + + return ret; +} + +UINT32 osal_fifo_avail(P_OSAL_FIFO pFifo) +{ + UINT32 ret = 0; + + if (pFifo) { + ret = pFifo->FifoAvailSz(pFifo); + } else { + pr_err("%s:pFifo = NULL, error\n", __func__); + ret = 0; + } + + return ret; +} + +UINT32 osal_fifo_is_empty(P_OSAL_FIFO pFifo) +{ + UINT32 ret = 0; + + if (pFifo) { + ret = pFifo->FifoIsEmpty(pFifo); + } else { + pr_err("%s:pFifo = NULL, error\n", __func__); + ret = 0; + } + + return ret; +} + +UINT32 osal_fifo_is_full(P_OSAL_FIFO pFifo) +{ + UINT32 ret = 0; + + if (pFifo) { + ret = pFifo->FifoIsFull(pFifo); + } else { + pr_err("%s:pFifo = NULL, error\n", __func__); + ret = 0; + } + return ret; +} + +INT32 osal_wake_lock_init(P_OSAL_WAKE_LOCK pLock) +{ + if (!pLock) + return -1; + + if (pLock->init_flag == 0) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 149)) + pLock->wake_lock = wakeup_source_register(NULL, pLock->name); +#else + pLock->wake_lock = wakeup_source_register(pLock->name); +#endif + pLock->init_flag = 1; + } + + return 0; +} + +INT32 osal_wake_lock_deinit(P_OSAL_WAKE_LOCK pLock) +{ + if (!pLock) + return -1; + + if (pLock->init_flag == 1) { + wakeup_source_unregister(pLock->wake_lock); + pLock->init_flag = 0; + } else + pr_info("%s: wake_lock is not initialized!\n", __func__); + + return 0; +} + +INT32 osal_wake_lock(P_OSAL_WAKE_LOCK pLock) +{ + if (!pLock) + return -1; + + if (pLock->init_flag == 1) + __pm_stay_awake(pLock->wake_lock); + else + pr_info("%s: wake_lock is not initialized!\n", __func__); + + return 0; +} + +INT32 osal_wake_unlock(P_OSAL_WAKE_LOCK pLock) +{ + if (!pLock) + return -1; + + if (pLock->init_flag == 1) + __pm_relax(pLock->wake_lock); + else + pr_info("%s: wake_lock is not initialized!\n", __func__); + + return 0; + +} + +INT32 osal_wake_lock_count(P_OSAL_WAKE_LOCK pLock) +{ + INT32 count = 0; + + if (!pLock) + return -1; + + if (pLock->init_flag == 1) + count = pLock->wake_lock->active; + else + pr_info("%s: wake_lock is not initialized!\n", __func__); + + return count; +} + +/* + *sleepable lock operations APIs + *init + *lock + *unlock + *destroy + * +*/ + +#if !defined(CONFIG_PROVE_LOCKING) +INT32 osal_unsleepable_lock_init(P_OSAL_UNSLEEPABLE_LOCK pUSL) +{ + spin_lock_init(&(pUSL->lock)); + return 0; +} +#endif + +INT32 osal_lock_unsleepable_lock(P_OSAL_UNSLEEPABLE_LOCK pUSL) +{ + spin_lock_irqsave(&(pUSL->lock), pUSL->flag); + return 0; +} + +INT32 osal_unlock_unsleepable_lock(P_OSAL_UNSLEEPABLE_LOCK pUSL) +{ + spin_unlock_irqrestore(&(pUSL->lock), pUSL->flag); + return 0; +} + +INT32 osal_trylock_unsleepable_lock(P_OSAL_UNSLEEPABLE_LOCK pUSL) +{ + return spin_trylock_irqsave(&(pUSL->lock), pUSL->flag); +} + +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_trylock_sleepable_lock(P_OSAL_SLEEPABLE_LOCK pSL) +{ + return mutex_trylock(&pSL->lock); +} + +INT32 osal_sleepable_lock_deinit(P_OSAL_SLEEPABLE_LOCK pSL) +{ + mutex_destroy(&pSL->lock); + return 0; +} + +INT32 osal_sleep_ms(UINT32 ms) +{ + msleep(ms); + return 0; +} + +INT32 osal_udelay(UINT32 us) +{ + udelay(us); + return 0; +} + +INT32 osal_usleep_range(ULONG min, ULONG max) +{ + usleep_range(min, max); + return 0; +} + +INT32 osal_gettimeofday(PINT32 sec, PINT32 usec) +{ + INT32 ret = 0; + struct timeval now; + + osal_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; +} + +void osal_do_gettimeofday(struct timeval *tv) +{ + struct timespec64 now; + + ktime_get_real_ts64(&now); + tv->tv_sec = now.tv_sec; + tv->tv_usec = now.tv_nsec / NSEC_PER_USEC; +} + +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_get_local_time(PUINT64 sec, PULONG nsec) +{ + if (sec != NULL && nsec != NULL) { + *sec = local_clock(); + *nsec = do_div(*sec, 1000000000)/1000; + } else + pr_err("The input parameters error when get local time\n"); +} + +UINT64 osal_elapsed_us(UINT64 ts, ULONG usec) +{ + UINT64 current_ts = 0; + ULONG current_usec = 0; + + osal_get_local_time(¤t_ts, ¤t_usec); + return (current_ts*1000000 + current_usec) - (ts*1000000 + usec); +} + +VOID osal_buffer_dump(const PUINT8 buf, const PUINT8 title, const UINT32 len, const UINT32 limit) +{ + INT32 k; + UINT32 dump_len; + char str[DBG_LOG_STR_SIZE] = {""}; + INT32 strlen = 0; + char *p = NULL; + + pr_info("[%s] len=%d, limit=%d, start dump\n", title, len, limit); + + dump_len = ((limit != 0) && (len > limit)) ? limit : len; + p = str; + for (k = 0; k < dump_len; k++) { + if ((k+1) % 16 != 0) { + strlen = osal_sprintf(p, "%02x ", buf[k]); + p += strlen; + } else { + strlen = osal_sprintf(p, "%02x\n", buf[k]); + pr_info("%s", str); + p = str; + } + } + if (k % 16 != 0) + pr_info("%s\n", str); + + pr_info("end of dump\n"); +} + +VOID osal_buffer_dump_data(const PUINT32 buf, const PUINT8 title, const UINT32 len, const UINT32 limit, + const INT32 flag) +{ + INT32 k; + UINT32 dump_len; + char str[DBG_LOG_STR_SIZE] = {""}; + INT32 strlen = 0; + char *p = NULL; + INT32 count = 0; + + dump_len = ((limit != 0) && (len > limit)) ? limit : len; + p = str; + for (k = 0; k < dump_len; k++) { + count++; + if (count % 8 != 0) { + strlen = osal_sprintf(p, "0x%08x,", buf[k]); + p += strlen; + } else { + strlen = osal_sprintf(p, "0x%08x\n", buf[k]); + if (flag) + osal_ftrace_print("%s%s", title, str); + else + pr_info("%s%s", title, str); + p = str; + } + } + if (count % 8 != 0) { + if (flag) + osal_ftrace_print("%s%s\n", title, str); + else + pr_info("%s%s\n", title, str); + } +} + +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); + } +} + +INT32 osal_ftrace_print(const PINT8 str, ...) +{ + int ret = 0; +#ifdef CONFIG_TRACING + va_list args; + INT8 tempString[DBG_LOG_STR_SIZE]; + + if (ftrace_flag) { + va_start(args, str); + ret = vsnprintf(tempString, DBG_LOG_STR_SIZE, str, args); + va_end(args); + + if (ret > 0) + trace_printk("%s\n", tempString); + } +#endif + return ret; +} + +INT32 osal_ftrace_print_ctrl(INT32 flag) +{ +#ifdef CONFIG_TRACING + if (flag) + ftrace_flag = 1; + else + ftrace_flag = 0; +#endif + return 0; +} + +VOID osal_set_op_result(P_OSAL_OP pOp, INT32 result) +{ + if (pOp) + pOp->result = result; + +} + +static VOID _osal_opq_dump(const char *qName, P_OSAL_OP_Q pOpQ) +{ + /* Line format: + * [LogicalIdx(PhysicalIdx)]Address:OpId(Ref)(Result)-Info-OpData0,OpData1,OpData2,OpData3,OpData5_ + * [LogicalIdx] max 10+2=12 chars (decimal) + * (PhysicalIdx) max 10+2=12 chars (decimal) + * Address: max 16+1=17 chars (hex) + * OpId max 10 chars (decimal) + * (Ref) max 2+2=4 chars (should only be 1 digit, reserve 2 in case of negative number) + * (Result) max 11+2=13 chars (signed decimal) + * -Info- max 8+2=10 chars (hex) + * OpData, max 16+1=17 chars (hex) + */ +#define OPQ_DUMP_OP_PER_LINE 1 +#define OPQ_DUMP_OPDATA_PER_OP 6 +#define OPQ_DUMP_OP_BUF_SIZE (12 + 12 + 17 + 10 + 4 + 13 + 10 + (17 * (OPQ_DUMP_OPDATA_PER_OP)) + 1) +#define OPQ_DUMP_LINE_BUF_SIZE ((OPQ_DUMP_OP_BUF_SIZE * OPQ_DUMP_OP_PER_LINE) + 1) + UINT32 rd; + UINT32 wt; + UINT32 idx = 0; + UINT32 opDataIdx; + UINT32 idxInBuf; + int printed; + P_OSAL_OP op; + char buf[OPQ_DUMP_LINE_BUF_SIZE]; + + rd = pOpQ->read; + wt = pOpQ->write; + + pr_info("%s(%p), sz:%u/%u, rd:%u, wt:%u\n", qName, pOpQ, RB_COUNT(pOpQ), RB_SIZE(pOpQ), rd, wt); + while (rd != wt && idx < RB_SIZE(pOpQ)) { + idxInBuf = idx % OPQ_DUMP_OP_PER_LINE; + op = pOpQ->queue[rd & RB_MASK(pOpQ)]; + + if (idxInBuf == 0) { + printed = 0; + buf[0] = 0; + } + + if (op) { + printed += snprintf(buf + printed, OPQ_DUMP_LINE_BUF_SIZE - printed, + "[%u(%u)]%p:%u(%d)(%d)-%u-", + idx, + (rd & RB_MASK(pOpQ)), + op, + op->op.opId, + atomic_read(&op->ref_count), + op->result, + op->op.u4InfoBit); + for (opDataIdx = 0; opDataIdx < OPQ_DUMP_OPDATA_PER_OP; opDataIdx++) + printed += snprintf(buf + printed, OPQ_DUMP_LINE_BUF_SIZE - printed, + "%zx,", op->op.au4OpData[opDataIdx]); + if (printed > 0) + buf[printed-1] = ' '; + } else { + printed += snprintf(buf + printed, OPQ_DUMP_LINE_BUF_SIZE - printed, + "[%u(%u)]%p ", idx, (rd & RB_MASK(pOpQ)), op); + } + if (printed < 1 || printed >= (sizeof(buf) - 1)) + return; + + buf[printed++] = ' '; + + if (idxInBuf == OPQ_DUMP_OP_PER_LINE - 1 || rd == wt - 1) { + buf[printed - 1] = 0; + pr_info("%s\n", buf); + } + rd++; + idx++; + } +} + +VOID osal_opq_dump(const char *qName, P_OSAL_OP_Q pOpQ) +{ + int err; + + err = osal_lock_sleepable_lock(&pOpQ->sLock); + if (err) { + pr_info("Failed to lock queue (%d)\n", err); + return; + } + + _osal_opq_dump(qName, pOpQ); + + osal_unlock_sleepable_lock(&pOpQ->sLock); +} + +VOID osal_opq_dump_locked(const char *qName, P_OSAL_OP_Q pOpQ) +{ + _osal_opq_dump(qName, pOpQ); +} + +MTK_WCN_BOOL osal_opq_has_op(P_OSAL_OP_Q pOpQ, P_OSAL_OP pOp) +{ + UINT32 rd; + UINT32 wt; + P_OSAL_OP op; + + rd = pOpQ->read; + wt = pOpQ->write; + + while (rd != wt) { + op = pOpQ->queue[rd & RB_MASK(pOpQ)]; + if (op == pOp) + return MTK_WCN_BOOL_TRUE; + rd++; + } + return MTK_WCN_BOOL_FALSE; +} + +static VOID osal_op_history_print_work(struct work_struct *work) +{ + struct osal_op_history *log_history = container_of(work, struct osal_op_history, dump_work); + struct ring *ring_buffer = &log_history->dump_ring_buffer; + struct ring_segment seg; + struct osal_op_history_entry *queue = ring_buffer->base; + struct osal_op_history_entry *entry = NULL; + INT32 index = 0; + + if (queue == NULL) { + pr_info("queue shouldn't be NULL, %s", log_history->name); + return; + } + + RING_READ_FOR_EACH_ITEM(RING_SIZE(ring_buffer), seg, ring_buffer) { + index = seg.ring_pt - ring_buffer->base; + entry = &queue[index]; + pr_info("(%llu.%06lu) %s: pOp(%p):%u(%d)-%x-%zx,%zx,%zx,%zx\n", + entry->ts, + entry->usec, + log_history->name, + entry->opbuf_address, + entry->op_id, + entry->opbuf_ref_count, + entry->op_info_bit, + entry->param_0, + entry->param_1, + entry->param_2, + entry->param_3); + } + kfree(queue); + ring_buffer->base = NULL; +} + +VOID osal_op_history_init(struct osal_op_history *log_history, INT32 queue_size) +{ + int size = queue_size * sizeof(struct osal_op_history_entry); + + spin_lock_init(&(log_history->lock)); + + log_history->queue = kzalloc(size, GFP_ATOMIC); + if (log_history->queue == NULL) + return; + + /* queue_size must be power of 2 */ + ring_init( + &log_history->queue, + queue_size, + 0, + 0, + &log_history->ring_buffer); + + INIT_WORK(&log_history->dump_work, osal_op_history_print_work); +} + +VOID osal_op_history_print(struct osal_op_history *log_history, PINT8 name) +{ + struct osal_op_history_entry *queue = NULL; + struct ring *ring_buffer = NULL, *dump_ring_buffer = NULL; + INT32 queue_size; + ULONG flags; + struct work_struct *work = &log_history->dump_work; + spinlock_t *lock = &(log_history->lock); + + if (log_history->queue == NULL) { + pr_info("Queue is NULL, name: %s\n", name); + return; + } + + spin_lock_irqsave(lock, flags); + ring_buffer = &log_history->ring_buffer; + queue_size = sizeof(struct osal_op_history_entry) + * RING_SIZE(ring_buffer); + + /* Allocate memory before getting lock to save time of holding lock */ + queue = kmalloc(queue_size, GFP_ATOMIC); + if (queue == NULL) { + spin_unlock_irqrestore(lock, flags); + return; + } + dump_ring_buffer = &log_history->dump_ring_buffer; + + if (dump_ring_buffer->base != NULL) { + spin_unlock_irqrestore(lock, flags); + kfree(queue); + pr_info("print is ongoing: %s\n", name); + return; + } + + osal_snprintf(log_history->name, sizeof(log_history->name), "%s", name); + osal_memcpy(queue, log_history->queue, queue_size); + osal_memcpy(dump_ring_buffer, ring_buffer, sizeof(struct ring)); + /* assign value to base after memory copy */ + dump_ring_buffer->base = queue; + spin_unlock_irqrestore(lock, flags); + schedule_work(work); +} + +VOID osal_op_history_save(struct osal_op_history *log_history, P_OSAL_OP pOp) +{ + struct osal_op_history_entry *entry = NULL; + struct ring_segment seg; + INT32 index; + UINT64 sec = 0; + ULONG usec = 0; + ULONG flags; + + if (log_history->queue == NULL) + return; + + osal_get_local_time(&sec, &usec); + + spin_lock_irqsave(&(log_history->lock), flags); + RING_OVERWRITE_FOR_EACH(1, seg, &log_history->ring_buffer) { + index = seg.ring_pt - log_history->ring_buffer.base; + entry = &log_history->queue[index]; + } + + if (entry == NULL) { + pr_info("Entry is null, size %d\n", RING_SIZE(&log_history->ring_buffer)); + spin_unlock_irqrestore(&(log_history->lock), flags); + return; + } + + entry->opbuf_address = pOp; + entry->op_id = pOp->op.opId; + entry->opbuf_ref_count = atomic_read(&pOp->ref_count); + entry->op_info_bit = pOp->op.u4InfoBit; + entry->param_0 = pOp->op.au4OpData[0]; + entry->param_1 = pOp->op.au4OpData[1]; + entry->param_2 = pOp->op.au4OpData[2]; + entry->param_3 = pOp->op.au4OpData[3]; + entry->ts = sec; + entry->usec = usec; + spin_unlock_irqrestore(&(log_history->lock), flags); +} diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/stp_btif.c b/drivers/misc/mediatek/connectivity/common/common_main/linux/stp_btif.c new file mode 100644 index 0000000000000..3d26156b878f6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/stp_btif.c @@ -0,0 +1,304 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/*file: stp_btif, mainly control stp & btif interaction*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[STP-BTIF]" + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "osal_typedef.h" +#include "wmt_exp.h" +#include "stp_exp.h" +#include "stp_btif.h" + +#include +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define BTIF_OWNER_NAME "CONSYS_STP" + +#define STP_MAX_PACKAGE_ALLOWED (2000) + +#define STP_BTIF_TX_RTY_LMT (10) +#define STP_BTIF_TX_RTY_DLY (5) +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +struct stp_btif g_stp_btif; +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +INT32 mtk_wcn_consys_stp_btif_open(VOID) +{ + INT32 iRet = -1; + P_OSAL_THREAD thread = &g_stp_btif.btif_thread; + + iRet = mtk_wcn_btif_open(BTIF_OWNER_NAME, &g_stp_btif.stpBtifId); + if (iRet) { + WMT_WARN_FUNC("STP open btif fail(%d)\n", iRet); + return -1; + } + WMT_DBG_FUNC("STP open bitf OK\n"); + + thread->pThread = mtk_btif_exp_rx_thread_get(g_stp_btif.stpBtifId); + if (!thread->pThread) { + WMT_INFO_FUNC("thread->pThread is NULL\n"); + return -1; + } + + osal_strncpy(thread->threadName, thread->pThread->comm, sizeof(thread->pThread->comm)); + mtk_wcn_stp_register_if_tx(STP_BTIF_IF_TX, (MTK_WCN_STP_IF_TX) mtk_wcn_consys_stp_btif_tx); + mtk_wcn_stp_register_rx_has_pending_data(STP_BTIF_IF_TX, + (MTK_WCN_STP_RX_HAS_PENDING_DATA) mtk_wcn_consys_stp_btif_rx_has_pending_data); + mtk_wcn_stp_register_tx_has_pending_data(STP_BTIF_IF_TX, + (MTK_WCN_STP_TX_HAS_PENDING_DATA) mtk_wcn_consys_stp_btif_tx_has_pending_data); + mtk_wcn_stp_register_rx_thread_get(STP_BTIF_IF_TX, + (MTK_WCN_STP_RX_THREAD_GET) mtk_wcn_consys_stp_btif_rx_thread_get); + + return 0; +} + +INT32 mtk_wcn_consys_stp_btif_close(VOID) +{ + INT32 iRet = 0; + + if (!g_stp_btif.stpBtifId) + WMT_WARN_FUNC("NULL BTIF ID reference!\n"); + else { + iRet = mtk_wcn_btif_close(g_stp_btif.stpBtifId); + if (iRet) { + WMT_WARN_FUNC("STP close btif fail(%d)\n", iRet); + iRet = -2; + } else { + g_stp_btif.stpBtifId = 0; + WMT_DBG_FUNC("STP close btif OK\n"); + } + } + + return iRet; +} + +INT32 mtk_wcn_consys_stp_btif_rx_cb_register(MTK_WCN_BTIF_RX_CB rx_cb) +{ + INT32 iRet = 0; + + if (!g_stp_btif.stpBtifId) { + WMT_WARN_FUNC("NULL BTIF ID reference\n!"); + if (rx_cb) + iRet = -1; + } else { + iRet = mtk_wcn_btif_rx_cb_register(g_stp_btif.stpBtifId, rx_cb); + if (iRet) { + WMT_WARN_FUNC("STP register rxcb to btif fail(%d)\n", iRet); + iRet = -2; + } else + WMT_DBG_FUNC("STP register rxcb to btif OK\n"); + } + + return iRet; +} + +INT32 mtk_wcn_consys_stp_btif_tx(const PUINT8 pBuf, const UINT32 len, PUINT32 written_len) +{ + INT32 retry_left = STP_BTIF_TX_RTY_LMT; + INT32 wr_count = 0; + INT32 written = 0; + + if (!g_stp_btif.stpBtifId) { + WMT_WARN_FUNC("NULL BTIF ID reference!\n"); + return -1; + } + + if (len == 0) { + *written_len = 0; + WMT_INFO_FUNC("special case for STP-CORE,pbuf(%p)\n", pBuf); + return 0; + } + + *written_len = 0; + + if (len > STP_MAX_PACKAGE_ALLOWED) { + WMT_WARN_FUNC("abnormal pacage length,len(%d),pid[%d/%s]\n", len, current->pid, current->comm); + return -2; + } + wr_count = mtk_wcn_btif_write(g_stp_btif.stpBtifId, pBuf, len); + + if (wr_count < 0) { + WMT_ERR_FUNC("mtk_wcn_btif_write err(%d)\n", wr_count); + *written_len = 0; + return -3; + } + if (wr_count == len) { + /*perfect case */ + *written_len = wr_count; + return wr_count; + } + + while ((retry_left--) && (wr_count < len)) { + osal_sleep_ms(STP_BTIF_TX_RTY_DLY); + written = mtk_wcn_btif_write(g_stp_btif.stpBtifId, pBuf + wr_count, len - wr_count); + if (written < 0) { + WMT_ERR_FUNC("mtk_wcn_btif_write err(%d)when do recovered\n", written); + break; + } + wr_count += written; + } + + if (wr_count == len) { + WMT_INFO_FUNC("recovered,len(%d),retry_left(%d)\n", len, retry_left); + /*recovered case */ + *written_len = wr_count; + return wr_count; + } + + WMT_ERR_FUNC("stp btif write fail,len(%d),written(%d),retry_left(%d),pid[%d/%s]\n", + len, wr_count, retry_left, current->pid, current->comm); + *written_len = 0; + + return -wr_count; +} + +INT32 mtk_wcn_consys_stp_btif_rx(PUINT8 pBuf, UINT32 len) +{ + return 0; +} + +INT32 mtk_wcn_consys_stp_btif_wakeup(VOID) +{ + INT32 iRet = 0; + + if (!g_stp_btif.stpBtifId) { + WMT_WARN_FUNC("NULL BTIF ID reference!\n"); + iRet = -1; + } else { + iRet = mtk_wcn_btif_wakeup_consys(g_stp_btif.stpBtifId); + if (iRet) { + WMT_WARN_FUNC("STP btif wakeup consys fail(%d)\n", iRet); + iRet = -2; + } else + WMT_DBG_FUNC("STP btif wakeup consys ok\n"); + } + + return iRet; +} + +INT32 mtk_wcn_consys_stp_btif_dpidle_ctrl(UINT32 en_flag) +{ + INT32 iRet = 0; + + if (!g_stp_btif.stpBtifId) { + WMT_WARN_FUNC("NULL BTIF ID reference!\n"); + iRet = -1; + } else { + mtk_wcn_btif_dpidle_ctrl(g_stp_btif.stpBtifId, (enum _ENUM_BTIF_DPIDLE_) en_flag); + WMT_DBG_FUNC("stp btif dpidle ctrl done,en_flag(%d)\n", en_flag); + } + + return iRet; +} + +INT32 mtk_wcn_consys_stp_btif_lpbk_ctrl(enum _ENUM_BTIF_LPBK_MODE_ mode) +{ + INT32 iRet = 0; + + if (!g_stp_btif.stpBtifId) { + WMT_WARN_FUNC("NULL BTIF ID reference!\n"); + iRet = -1; + } else { + iRet = mtk_wcn_btif_loopback_ctrl(g_stp_btif.stpBtifId, mode); + if (iRet) { + WMT_WARN_FUNC("STP btif lpbk ctrl fail(%d)\n", iRet); + iRet = -2; + } else + WMT_INFO_FUNC("stp btif lpbk ctrl ok,mode(%d)\n", mode); + } + + return iRet; +} + +INT32 mtk_wcn_consys_stp_btif_logger_ctrl(enum _ENUM_BTIF_DBG_ID_ flag) +{ + INT32 iRet = 0; + + if (!g_stp_btif.stpBtifId) { + WMT_WARN_FUNC("NULL BTIF ID reference!\n"); + iRet = -1; + } else { + iRet = mtk_wcn_btif_dbg_ctrl(g_stp_btif.stpBtifId, flag); + if (iRet) { + WMT_WARN_FUNC("STP btif log dbg ctrl fail(%d)\n", iRet); + iRet = -2; + } else + WMT_INFO_FUNC("stp btif log dbg ctrl ok,flag(%d)\n", flag); + } + + return iRet; +} + +INT32 mtk_wcn_consys_stp_btif_parser_wmt_evt(const PUINT8 str, UINT32 len) +{ + if (!g_stp_btif.stpBtifId) { + WMT_WARN_FUNC("NULL BTIF ID reference!\n"); + return -1; + } else + return (INT32) mtk_wcn_btif_parser_wmt_evt(g_stp_btif.stpBtifId, str, len); +} + +INT32 mtk_wcn_consys_stp_btif_rx_has_pending_data(VOID) +{ + return mtk_btif_exp_rx_has_pending_data(g_stp_btif.stpBtifId); +} + +INT32 mtk_wcn_consys_stp_btif_tx_has_pending_data(VOID) +{ + return mtk_btif_exp_tx_has_pending_data(g_stp_btif.stpBtifId); +} + +P_OSAL_THREAD mtk_wcn_consys_stp_btif_rx_thread_get(VOID) +{ + return &g_stp_btif.btif_thread; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/stp_dbg.c b/drivers/misc/mediatek/connectivity/common/common_main/linux/stp_dbg.c new file mode 100644 index 0000000000000..36056f406756f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/stp_dbg.c @@ -0,0 +1,2902 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include /* GFP_KERNEL */ +#include /* init_timer, add_time, del_timer_sync */ +#include /* gettimeofday */ +#include +#include /* kzalloc */ +#include /* task's status */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "osal.h" +#include "stp_dbg.h" +#include "stp_dbg_combo.h" +#include "stp_dbg_soc.h" +/* #include "stp_btm.h" */ +#include "btm_core.h" +#include "wmt_plat.h" +#include "wmt_detect.h" +#include "stp_sdio.h" +#include "stp_core.h" +#include "mtk_wcn_consys_hw.h" +#include "wmt_lib.h" + + +UINT32 gStpDbgLogOut; +UINT32 gStpDbgDumpType = STP_DBG_PKT; +INT32 gStpDbgDbgLevel = STP_DBG_LOG_INFO; +static CONSYS_STATE_DMP_INFO g_dmp_info; + +MTKSTP_DBG_T *g_stp_dbg; + +static OSAL_SLEEPABLE_LOCK g_dbg_nl_lock; + +#define STP_DBG_FAMILY_NAME "STP_DBG" +#define MAX_BIND_PROCESS (4) +#ifdef WMT_PLAT_ALPS +#ifndef LOG_STP_DEBUG_DISABLE +#define STP_DBG_AEE_EXP_API (1) +#else +#define STP_DBG_AEE_EXP_API (0) +#endif +#else +#define STP_DBG_AEE_EXP_API (0) +#endif + +#define STP_MAGIC_NUM (0xDEADFEED) + +#ifndef GENL_ID_GENERATE +#define GENL_ID_GENERATE 0 +#endif + +enum { + __STP_DBG_ATTR_INVALID, + STP_DBG_ATTR_MSG, + __STP_DBG_ATTR_MAX, +}; +#define STP_DBG_ATTR_MAX (__STP_DBG_ATTR_MAX - 1) + +enum { + __STP_DBG_COMMAND_INVALID, + STP_DBG_COMMAND_BIND, + STP_DBG_COMMAND_RESET, + __STP_DBG_COMMAND_MAX, +}; +#define MTK_WIFI_COMMAND_MAX (__STP_DBG_COMMAND_MAX - 1) + +/* attribute policy */ +static struct nla_policy stp_dbg_genl_policy[STP_DBG_ATTR_MAX + 1] = { + [STP_DBG_ATTR_MSG] = {.type = NLA_NUL_STRING}, +}; + +static UINT32 stp_dbg_seqnum; +static INT32 num_bind_process; +static pid_t bind_pid[MAX_BIND_PROCESS]; +static P_WCN_CORE_DUMP_T g_core_dump; +static P_STP_DBG_CPUPCR_T g_stp_dbg_cpupcr; +/* just show in log at present */ +static P_STP_DBG_DMAREGS_T g_stp_dbg_dmaregs; + +static VOID stp_dbg_core_dump_timeout_handler(timer_handler_arg arg); +static VOID stp_dbg_dump_emi_timeout_handler(timer_handler_arg arg); +static _osal_inline_ P_WCN_CORE_DUMP_T stp_dbg_core_dump_init(UINT32 timeout); +static _osal_inline_ INT32 stp_dbg_core_dump_deinit(P_WCN_CORE_DUMP_T dmp); +static _osal_inline_ INT32 stp_dbg_core_dump_check_end(PUINT8 buf, INT32 len); +static _osal_inline_ INT32 stp_dbg_core_dump_in(P_WCN_CORE_DUMP_T dmp, PUINT8 buf, INT32 len); +static _osal_inline_ INT32 stp_dbg_core_dump_post_handle(P_WCN_CORE_DUMP_T dmp); +static _osal_inline_ INT32 stp_dbg_core_dump_out(P_WCN_CORE_DUMP_T dmp, PPUINT8 pbuf, PINT32 plen); +static _osal_inline_ INT32 stp_dbg_core_dump_reset(P_WCN_CORE_DUMP_T dmp, UINT32 timeout); +static _osal_inline_ INT32 stp_dbg_core_dump_nl(P_WCN_CORE_DUMP_T dmp, PUINT8 buf, INT32 len); +static _osal_inline_ UINT32 stp_dbg_get_chip_id(VOID); +static _osal_inline_ INT32 stp_dbg_gzip_compressor(PVOID worker, PUINT8 in_buf, INT32 in_sz, PUINT8 out_buf, + PINT32 out_sz, INT32 finish); +static _osal_inline_ P_WCN_COMPRESSOR_T stp_dbg_compressor_init(PUINT8 name, INT32 L1_buf_sz, INT32 L2_buf_sz); +static _osal_inline_ INT32 stp_dbg_compressor_deinit(P_WCN_COMPRESSOR_T cprs); +static _osal_inline_ INT32 stp_dbg_compressor_in(P_WCN_COMPRESSOR_T cprs, + PUINT8 buf, INT32 len, INT32 is_iobuf, INT32 finish); +static _osal_inline_ INT32 stp_dbg_compressor_out(P_WCN_COMPRESSOR_T cprs, PPUINT8 pbuf, PINT32 plen); +static _osal_inline_ INT32 stp_dbg_compressor_reset(P_WCN_COMPRESSOR_T cprs, UINT8 enable, WCN_COMPRESS_ALG_T type); +static _osal_inline_ VOID stp_dbg_dump_data(PUINT8 pBuf, PINT8 title, INT32 len); +static _osal_inline_ INT32 stp_dbg_dmp_in(MTKSTP_DBG_T *stp_dbg, PINT8 buf, INT32 len); +static _osal_inline_ INT32 stp_dbg_notify_btm_dmp_wq(MTKSTP_DBG_T *stp_dbg); +static _osal_inline_ INT32 stp_dbg_get_avl_entry_num(MTKSTP_DBG_T *stp_dbg); +static _osal_inline_ INT32 stp_dbg_fill_hdr(STP_DBG_HDR_T *hdr, INT32 type, INT32 ack, INT32 seq, + INT32 crc, INT32 dir, INT32 len, INT32 dbg_type); +static _osal_inline_ INT32 stp_dbg_add_pkt(MTKSTP_DBG_T *stp_dbg, STP_DBG_HDR_T *hdr, const PUINT8 body); +static INT32 stp_dbg_nl_bind(struct sk_buff *skb, struct genl_info *info); +static INT32 stp_dbg_nl_reset(struct sk_buff *skb, struct genl_info *info); +static _osal_inline_ INT32 stp_dbg_parser_assert_str(PINT8 str, ENUM_ASSERT_INFO_PARSER_TYPE type); +static _osal_inline_ P_STP_DBG_CPUPCR_T stp_dbg_cpupcr_init(VOID); +static _osal_inline_ VOID stp_dbg_cpupcr_deinit(P_STP_DBG_CPUPCR_T pCpupcr); +static _osal_inline_ P_STP_DBG_DMAREGS_T stp_dbg_dmaregs_init(VOID); +static _osal_inline_ VOID stp_dbg_dmaregs_deinit(P_STP_DBG_DMAREGS_T pDmaRegs); + +INT32 __weak mtk_btif_rxd_be_blocked_flag_get(VOID) +{ + STP_DBG_PR_INFO("mtk_btif_rxd_be_blocked_flag_get is not define!!!\n"); + return 0; +} + +/* operation definition */ +static struct genl_ops stp_dbg_gnl_ops_array[] = { + { + .cmd = STP_DBG_COMMAND_BIND, + .flags = 0, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)) + .policy = stp_dbg_genl_policy, +#endif + .doit = stp_dbg_nl_bind, + .dumpit = NULL, + }, + { + .cmd = STP_DBG_COMMAND_RESET, + .flags = 0, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)) + .policy = stp_dbg_genl_policy, +#endif + .doit = stp_dbg_nl_reset, + .dumpit = NULL, + }, +}; + +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, + .ops = stp_dbg_gnl_ops_array, + .n_ops = ARRAY_SIZE(stp_dbg_gnl_ops_array), +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)) + .policy = stp_dbg_genl_policy, +#endif +}; +/* stp_dbg_core_dump_timeout_handler - handler of coredump timeout + * @ data - core dump object's pointer + * + * No return value + */ +static VOID stp_dbg_core_dump_timeout_handler(timer_handler_arg arg) +{ + stp_dbg_set_coredump_timer_state(CORE_DUMP_TIMEOUT); + stp_btm_notify_coredump_timeout_wq(g_stp_dbg->btm); + STP_DBG_PR_WARN(" coredump timer timeout, coredump maybe not finished successfully\n"); +} + +/* stp_dbg_dump_emi_timeout_handler - handler of emi dump timeout + * @ data - core dump object's pointer + * + * No return value + */ +static VOID stp_dbg_dump_emi_timeout_handler(timer_handler_arg arg) +{ + STP_DBG_PR_ERR("dump emi timeout!\n"); + mtk_stp_notify_emi_dump_end(); +} + +/* stp_dbg_core_dump_init - create core dump sys + * @ packet_num - core dump packet number unit 32k + * @ timeout - core dump time out value + * + * Return object pointer if success, else NULL + */ +static _osal_inline_ P_WCN_CORE_DUMP_T stp_dbg_core_dump_init(UINT32 timeout) +{ + 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_PR_ERR("alloc mem failed!\n"); + return NULL; + } + + osal_memset(core_dmp, 0, sizeof(WCN_CORE_DUMP_T)); + + core_dmp->dmp_timer.timeoutHandler = stp_dbg_core_dump_timeout_handler; + core_dmp->dmp_timer.timeroutHandlerData = (ULONG)core_dmp; + osal_timer_create(&core_dmp->dmp_timer); + core_dmp->timeout = timeout; + core_dmp->dmp_emi_timer.timeoutHandler = stp_dbg_dump_emi_timeout_handler; + core_dmp->dmp_emi_timer.timeroutHandlerData = (ULONG)core_dmp; + osal_timer_create(&core_dmp->dmp_emi_timer); + + osal_sleepable_lock_init(&core_dmp->dmp_lock); + + core_dmp->sm = CORE_DUMP_INIT; + STP_DBG_PR_INFO("create coredump object OK!\n"); + + return core_dmp; +} + + +/* stp_dbg_core_dump_deinit - destroy core dump object + * @ dmp - pointer of object + * + * Retunr 0 if success, else error code + */ +static _osal_inline_ INT32 stp_dbg_core_dump_deinit(P_WCN_CORE_DUMP_T dmp) +{ + if (dmp) { + if (dmp->p_head != NULL) { + osal_free(dmp->p_head); + dmp->p_head = NULL; + } + osal_sleepable_lock_deinit(&dmp->dmp_lock); + osal_timer_stop(&dmp->dmp_timer); + osal_timer_stop(&dmp->dmp_emi_timer); + osal_free(dmp); + dmp = NULL; + } + + return 0; +} + +INT32 stp_dbg_core_dump_deinit_gcoredump(VOID) +{ + stp_dbg_core_dump_deinit(g_core_dump); + return 0; +} + +static _osal_inline_ INT32 stp_dbg_core_dump_check_end(PUINT8 buf, INT32 len) +{ + if (strnstr(buf, "coredump end", len)) + return 1; + else + return 0; +} + +static UINT32 stp_dbg_core_dump_header_init(P_WCN_CORE_DUMP_T dmp) +{ + dmp->head_len = 0; + if (dmp->p_head == NULL) { + dmp->p_head = osal_malloc(MAX_DUMP_HEAD_LEN); + if (dmp->p_head == NULL) { + STP_DBG_PR_ERR("alloc memory for head information failed\n"); + return -1; + } + } + if (dmp->p_head != NULL) + osal_memset(dmp->p_head, 0, MAX_DUMP_HEAD_LEN); + + return 0; +} + +static UINT32 stp_dbg_core_dump_header_append(P_WCN_CORE_DUMP_T dmp, PUINT8 buf, INT32 len) +{ + INT32 tmp = 0; + + if ((dmp->p_head != NULL) && (dmp->head_len < (MAX_DUMP_HEAD_LEN - 1))) { + tmp = + (dmp->head_len + len) > + (MAX_DUMP_HEAD_LEN - 1) ? (MAX_DUMP_HEAD_LEN - 1 - dmp->head_len) : len; + osal_memcpy(dmp->p_head + dmp->head_len, buf, tmp); + dmp->head_len += tmp; + return tmp; + } + return 0; +} + +/* stp_dbg_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 + */ +static _osal_inline_ INT32 stp_dbg_core_dump_in(P_WCN_CORE_DUMP_T dmp, PUINT8 buf, INT32 len) +{ + INT32 ret = 0; + + if ((!dmp) || (!buf)) { + STP_DBG_PR_ERR("invalid pointer!\n"); + return -1; + } + + ret = osal_lock_sleepable_lock(&dmp->dmp_lock); + if (ret) { + STP_DBG_PR_ERR("--->lock dmp->dmp_lock failed, ret=%d\n", ret); + return ret; + } + + switch (dmp->sm) { + case CORE_DUMP_INIT: + stp_dbg_compressor_reset(dmp->compressor, 1, GZIP); + stp_dbg_core_dump_header_init(dmp); + /* show coredump start info on UI */ + /* osal_dbg_assert_aee("MT662x f/w coredump start", "MT662x firmware coredump start"); */ + /* parsing data, and check end srting */ + ret = stp_dbg_core_dump_check_end(buf, len); + if (ret == 1) { + STP_DBG_PR_INFO("core dump end!\n"); + dmp->sm = CORE_DUMP_DONE; + stp_dbg_compressor_in(dmp->compressor, buf, len, 0, 0); + } else { + dmp->sm = CORE_DUMP_DOING; + stp_dbg_compressor_in(dmp->compressor, buf, len, 0, 0); + } + break; + + case CORE_DUMP_DOING: + /* parsing data, and check end srting */ + ret = stp_dbg_core_dump_check_end(buf, len); + if (ret == 1) { + STP_DBG_PR_INFO("core dump end!\n"); + dmp->sm = CORE_DUMP_DONE; + stp_dbg_compressor_in(dmp->compressor, buf, len, 0, 0); + } else { + dmp->sm = CORE_DUMP_DOING; + stp_dbg_compressor_in(dmp->compressor, buf, len, 0, 0); + } + break; + + case CORE_DUMP_DONE: + stp_dbg_compressor_reset(dmp->compressor, 1, GZIP); + osal_timer_stop(&dmp->dmp_timer); + stp_dbg_compressor_in(dmp->compressor, buf, len, 0, 0); + dmp->sm = CORE_DUMP_DOING; + break; + + case CORE_DUMP_TIMEOUT: + ret = -1; + break; + default: + break; + } + + stp_dbg_core_dump_header_append(dmp, buf, len); + osal_unlock_sleepable_lock(&dmp->dmp_lock); + + return ret; +} + +static _osal_inline_ INT32 stp_dbg_core_dump_post_handle(P_WCN_CORE_DUMP_T dmp) +{ +#define INFO_HEAD ";CONSYS FW CORE, " + INT32 ret = 0; + INT32 tmp = 0; + ENUM_STP_FW_ISSUE_TYPE issue_type; + + if ((dmp->p_head != NULL) + && ((osal_strnstr(dmp->p_head, "", dmp->head_len)) != NULL || + stp_dbg_get_host_trigger_assert())) { + PINT8 pStr = dmp->p_head; + PINT8 pDtr = NULL; + + if (stp_dbg_get_host_trigger_assert()) + issue_type = STP_HOST_TRIGGER_FW_ASSERT; + else + issue_type = STP_FW_ASSERT_ISSUE; + STP_DBG_PR_INFO("dmp->head_len = %d\n", dmp->head_len); + /*parse f/w assert additional informationi for f/w's analysis */ + ret = stp_dbg_set_fw_info(dmp->p_head, dmp->head_len, issue_type); + if (ret) { + STP_DBG_PR_ERR("set fw issue infor fail(%d),maybe fw warm reset...\n", + ret); + stp_dbg_set_fw_info("Fw Warm reset", osal_strlen("Fw Warm reset"), + STP_FW_WARM_RST_ISSUE); + } + /* first package, copy to info buffer */ + osal_strcpy(&dmp->info[0], INFO_HEAD); + + /* set f/w assert information to warm reset */ + pStr = osal_strnstr(pStr, "", dmp->head_len); + if (pStr != NULL) { + pDtr = osal_strchr(pStr, '-'); + if (pDtr != NULL) { + tmp = STP_CORE_DUMP_INFO_SZ - osal_strlen(INFO_HEAD); + tmp = ((pDtr - pStr) > tmp) ? tmp : (pDtr - pStr); + osal_memcpy(&dmp->info[osal_strlen(INFO_HEAD)], pStr, tmp); + dmp->info[osal_strlen(dmp->info) + 1] = '\0'; + } else { + tmp = STP_CORE_DUMP_INFO_SZ - osal_strlen(INFO_HEAD); + tmp = (dmp->head_len > tmp) ? tmp : dmp->head_len; + osal_memcpy(&dmp->info[osal_strlen(INFO_HEAD)], pStr, tmp); + dmp->info[STP_CORE_DUMP_INFO_SZ] = '\0'; + } + } + } else if ((dmp->p_head != NULL) + && ((osal_strnstr(dmp->p_head, "", dmp->head_len) != NULL) + || (osal_strnstr(dmp->p_head, "ABT", dmp->head_len) != NULL))) { + stp_dbg_set_fw_info(dmp->p_head, dmp->head_len, STP_FW_ABT); + osal_strcpy(&dmp->info[0], INFO_HEAD); + osal_memcpy(&dmp->info[osal_strlen(INFO_HEAD)], "Fw ABT Exception...", + osal_strlen("Fw ABT Exception...")); + dmp->info[osal_strlen(INFO_HEAD) + osal_strlen("Fw ABT Exception...") + 1] = '\0'; + } else { + STP_DBG_PR_INFO(" string not found, dmp->head_len:%d\n", dmp->head_len); + if (dmp->p_head == NULL) + STP_DBG_PR_INFO(" dmp->p_head is NULL\n"); + else + STP_DBG_PR_INFO(" dmp->p_head:%s\n", dmp->p_head); + + /* first package, copy to info buffer */ + osal_strcpy(&dmp->info[0], INFO_HEAD); + /* set f/w assert information to warm reset */ + osal_memcpy(&dmp->info[osal_strlen(INFO_HEAD)], "Fw warm reset exception...", + osal_strlen("Fw warm reset exception...")); + dmp->info[osal_strlen(INFO_HEAD) + osal_strlen("Fw warm reset exception...") + 1] = + '\0'; + + } + dmp->head_len = 0; + + /*set ret value to notify upper layer do dump flush operation */ + ret = 1; + + return ret; +} + +/* stp_dbg_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 + */ +static _osal_inline_ INT32 stp_dbg_core_dump_out(P_WCN_CORE_DUMP_T dmp, PPUINT8 pbuf, PINT32 plen) +{ + INT32 ret = 0; + + if ((!dmp) || (!pbuf) || (!plen)) { + STP_DBG_PR_ERR("invalid pointer!\n"); + return -1; + } + + ret = osal_lock_sleepable_lock(&dmp->dmp_lock); + if (ret) { + STP_DBG_PR_ERR("--->lock dmp->dmp_lock failed, ret=%d\n", ret); + return ret; + } + + ret = stp_dbg_compressor_out(dmp->compressor, pbuf, plen); + + osal_unlock_sleepable_lock(&dmp->dmp_lock); + + return ret; +} + +/* stp_dbg_core_dump_reset - reset core dump sys + * @ dmp - pointer of object + * @ timeout - core dump time out value + * + * Retunr 0 if success, else error code + */ +static _osal_inline_ INT32 stp_dbg_core_dump_reset(P_WCN_CORE_DUMP_T dmp, UINT32 timeout) +{ + if (!dmp) { + STP_DBG_PR_ERR("invalid pointer!\n"); + return -1; + } + + dmp->sm = CORE_DUMP_INIT; + dmp->timeout = timeout; + osal_timer_stop(&dmp->dmp_timer); + osal_timer_stop(&dmp->dmp_emi_timer); + osal_memset(dmp->info, 0, STP_CORE_DUMP_INFO_SZ + 1); + + stp_dbg_core_dump_deinit(dmp); + g_core_dump = stp_dbg_core_dump_init(STP_CORE_DUMP_TIMEOUT); + + return 0; +} + +#define ENABLE_F_TRACE 0 +/* stp_dbg_core_dump_flush - Fulsh dump data and reset core dump sys + * + * Retunr 0 if success, else error code + */ +INT32 stp_dbg_core_dump_flush(INT32 rst, MTK_WCN_BOOL coredump_is_timeout) +{ + PUINT8 pbuf = NULL; + INT32 len = 0; + + if (!g_core_dump) { + STP_DBG_PR_ERR("invalid pointer!\n"); + return -1; + } + + osal_lock_sleepable_lock(&g_core_dump->dmp_lock); + stp_dbg_core_dump_post_handle(g_core_dump); + osal_unlock_sleepable_lock(&g_core_dump->dmp_lock); + stp_dbg_core_dump_out(g_core_dump, &pbuf, &len); + STP_DBG_PR_INFO("buf 0x%zx, len %d\n", (SIZE_T) pbuf, len); + +#if IS_ENABLED(CONFIG_MTK_AEE_AED) + /* show coredump end info on UI */ + /* osal_dbg_assert_aee("MT662x f/w coredump end", "MT662x firmware coredump ends"); */ +#if STP_DBG_AEE_EXP_API +#if ENABLE_F_TRACE + aed_combo_exception_api(NULL, 0, (const PINT32)pbuf, len, (const PINT8)g_core_dump->info, + DB_OPT_FTRACE); +#else + aed_combo_exception(NULL, 0, (const PINT32)pbuf, len, (const PINT8)g_core_dump->info); +#endif +#endif + +#endif + /* reset */ + g_core_dump->count = 0; + stp_dbg_compressor_deinit(g_core_dump->compressor); + stp_dbg_core_dump_reset(g_core_dump, STP_CORE_DUMP_TIMEOUT); + + return 0; +} + +static _osal_inline_ INT32 stp_dbg_core_dump_nl(P_WCN_CORE_DUMP_T dmp, PUINT8 buf, INT32 len) +{ + INT32 ret = 0; + + if ((!dmp) || (!buf)) { + STP_DBG_PR_ERR("invalid pointer!\n"); + return -1; + } + + ret = osal_lock_sleepable_lock(&dmp->dmp_lock); + if (ret) { + STP_DBG_PR_ERR("--->lock dmp->dmp_lock failed, ret=%d\n", ret); + return ret; + } + + switch (dmp->sm) { + case CORE_DUMP_INIT: + STP_DBG_PR_WARN("CONSYS coredump start, please wait up to %d minutes.\n", + STP_CORE_DUMP_TIMEOUT/60000); + stp_dbg_core_dump_header_init(dmp); + /* check end srting */ + ret = stp_dbg_core_dump_check_end(buf, len); + if (ret == 1) { + STP_DBG_PR_INFO("core dump end!\n"); + osal_timer_stop(&dmp->dmp_timer); + dmp->sm = CORE_DUMP_INIT; + } else { + dmp->sm = CORE_DUMP_DOING; + } + break; + + case CORE_DUMP_DOING: + /* check end srting */ + ret = stp_dbg_core_dump_check_end(buf, len); + if (ret == 1) { + STP_DBG_PR_INFO("core dump end!\n"); + osal_timer_stop(&dmp->dmp_timer); + dmp->sm = CORE_DUMP_INIT; + } else { + dmp->sm = CORE_DUMP_DOING; + } + break; + + case CORE_DUMP_DONE: + osal_timer_stop(&dmp->dmp_timer); + dmp->sm = CORE_DUMP_INIT; + break; + + case CORE_DUMP_TIMEOUT: + ret = 32; + break; + default: + break; + } + + /* Skip nl packet header */ + stp_dbg_core_dump_header_append(dmp, buf + NL_PKT_HEADER_LEN, len - NL_PKT_HEADER_LEN); + osal_unlock_sleepable_lock(&dmp->dmp_lock); + + return ret; +} + +INT32 stp_dbg_core_dump(INT32 dump_sink) +{ + ENUM_WMT_CHIP_TYPE chip_type; + INT32 ret = 0; + + chip_type = wmt_detect_get_chip_type(); + switch (chip_type) { + case WMT_CHIP_TYPE_COMBO: + ret = stp_dbg_combo_core_dump(dump_sink); + break; + case WMT_CHIP_TYPE_SOC: + ret = stp_dbg_soc_core_dump(dump_sink); + break; + default: + STP_DBG_PR_ERR("error chip type(%d)\n", chip_type); + } + + return ret; +} + +static _osal_inline_ UINT32 stp_dbg_get_chip_id(VOID) +{ + ENUM_WMT_CHIP_TYPE chip_type; + UINT32 chip_id = 0; + + chip_type = wmt_detect_get_chip_type(); + switch (chip_type) { + case WMT_CHIP_TYPE_COMBO: + chip_id = mtk_wcn_wmt_chipid_query(); + break; + case WMT_CHIP_TYPE_SOC: + chip_id = wmt_plat_get_soc_chipid(); + break; + default: + STP_DBG_PR_ERR("error chip type(%d)\n", chip_type); + } + + return chip_id; +} + +/* stp_dbg_trigger_collect_ftrace - this func can collect SYS_FTRACE + * + * Retunr 0 if success + */ +INT32 stp_dbg_trigger_collect_ftrace(PUINT8 pbuf, INT32 len) +{ + if (!pbuf) { + STP_DBG_PR_ERR("Parameter error\n"); + return -1; + } + + if (mtk_wcn_stp_coredump_start_get()) { + STP_DBG_PR_ERR("assert has been triggered\n"); + return -1; + } + + stp_dbg_set_host_assert_info(WMTDRV_TYPE_WMT, 30, 1); + + if (stp_dbg_set_fw_info(pbuf, len, STP_HOST_TRIGGER_COLLECT_FTRACE)) + return -1; + + if (g_core_dump) { + osal_strncpy(&g_core_dump->info[0], pbuf, len); +#if IS_ENABLED(CONFIG_MTK_AEE_AED) + aed_combo_exception(NULL, 0, (const PINT32)pbuf, len, (const PINT8)g_core_dump->info); +#endif + } else { + STP_DBG_PR_INFO("g_core_dump is not initialized\n"); +#if IS_ENABLED(CONFIG_MTK_AEE_AED) + aed_combo_exception(NULL, 0, (const PINT32)pbuf, len, (const PINT8)pbuf); +#endif + } + + return 0; +} + +#if BTIF_RXD_BE_BLOCKED_DETECT +MTK_WCN_BOOL stp_dbg_is_btif_rxd_be_blocked(VOID) +{ + MTK_WCN_BOOL flag = MTK_WCN_BOOL_FALSE; + + if (mtk_btif_rxd_be_blocked_flag_get()) + flag = MTK_WCN_BOOL_TRUE; + return flag; +} +#endif + +static _osal_inline_ INT32 stp_dbg_gzip_compressor(PVOID worker, PUINT8 in_buf, INT32 in_sz, PUINT8 out_buf, + PINT32 out_sz, INT32 finish) +{ + INT32 ret = 0; + z_stream *stream = NULL; + INT32 tmp = *out_sz; + + STP_DBG_PR_DBG("before compressor:buf 0x%zx, size %d, avalible buf: 0x%zx, size %d\n", + (SIZE_T) in_buf, in_sz, (SIZE_T) out_buf, tmp); + + stream = (z_stream *) worker; + if (!stream) { + STP_DBG_PR_ERR("invalid workspace!\n"); + return -1; + } + + if (in_sz > 0) { +#if 0 + ret = zlib_deflateReset(stream); + if (ret != Z_OK) { + STP_DBG_PR_ERR("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) { + INT32 val = zlib_deflate(stream, Z_FINISH); + + if (val == Z_OK) + continue; + else if (val == Z_STREAM_END) + break; + STP_DBG_PR_ERR("finish operation failed %d\n", val); + return -3; + } + } + *out_sz = tmp - stream->avail_out; + } + + STP_DBG_PR_DBG("after compressor,avalible buf: 0x%zx, compress rate %d -> %d\n", + (SIZE_T) out_buf, in_sz, *out_sz); + + return ret; +} + +/* stp_dbg_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 + */ +static _osal_inline_ P_WCN_COMPRESSOR_T stp_dbg_compressor_init(PUINT8 name, INT32 L1_buf_sz, + INT32 L2_buf_sz) +{ + INT32 ret = 0; + 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_PR_ERR("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_PR_ERR("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_PR_ERR("alloc workspace failed!\n"); + goto fail; + } + ret = zlib_deflateInit2(pstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS, + DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); + if (ret != Z_OK) { + STP_DBG_PR_INFO("[%s::%d] zlib_deflateInit2 failed!\n", __func__, __LINE__); + goto fail; + } + } + + compress->handler = stp_dbg_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_PR_ERR("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_PR_ERR("alloc %d bytes for L2 buf failed!\n", compress->L2_buf_sz); + goto fail; + } + + STP_DBG_PR_INFO("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_PR_ERR("init failed!\n"); + + return NULL; +} + +/* stp_dbg_compressor_deinit - distroy a compressor + * @ cprs - compressor's pointer + * + * Retunr 0 if success, else NULL + */ +static _osal_inline_ INT32 stp_dbg_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_PR_INFO("destroy OK\n"); + + return 0; +} + +/* stp_dbg_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 + * @ is_iobuf - is buf a pointer to EMI? 1: yes, 0: no + * @ finish - core dump finish or not, 1: finished; 0: not finish + * + * Retunr 0 if success, else NULL + */ +static _osal_inline_ INT32 stp_dbg_compressor_in(P_WCN_COMPRESSOR_T cprs, PUINT8 buf, INT32 len, + INT32 is_iobuf, INT32 finish) +{ + INT32 tmp_len = 0; + INT32 ret = 0; + + if (!cprs) { + STP_DBG_PR_ERR("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_PR_DBG("L1 buffer full\n"); + + if (cprs->f_compress_en && cprs->handler) { + /* need compress */ + /* compress L1 buffer, and put result to L2 buffer */ + tmp_len = cprs->L2_buf_sz - cprs->L2_pos; + ret = + cprs->handler(cprs->worker, cprs->L1_buf, cprs->L1_pos, + &cprs->L2_buf[cprs->L2_pos], &tmp_len, finish); + if (!ret) { + cprs->crc32 = (crc32(cprs->crc32, cprs->L1_buf, cprs->L1_pos)); + cprs->L2_pos += tmp_len; + if (cprs->L2_pos >= cprs->L2_buf_sz) + STP_DBG_PR_ERR("coredump size too large(%d), L2 buf overflow\n", + cprs->L2_pos); + + if (finish) { + /* Add 8 byte suffix + * === + * 32 bits UNCOMPRESS SIZE + * 32 bits CRC + */ + *(uint32_t *) (&cprs->L2_buf[cprs->L2_pos]) = + (cprs->crc32 ^ 0xffffffffUL); + *(uint32_t *) (&cprs->L2_buf[cprs->L2_pos + 4]) = cprs->uncomp_size; + cprs->L2_pos += 8; + } + STP_DBG_PR_DBG("compress OK!\n"); + } else + STP_DBG_PR_ERR("compress error!\n"); + } else { + /* no need compress */ + /* Flush L1 buffer to L2 buffer */ + STP_DBG_PR_INFO("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_PR_ERR("len=%d, too long err!\n", len); + } else { + STP_DBG_PR_DBG("L1 Flushed, and Put %d bytes to L1 buf\n", len); + if (is_iobuf) + osal_memcpy_fromio(&cprs->L1_buf[cprs->L1_pos], buf, len); + else + osal_memcpy(&cprs->L1_buf[cprs->L1_pos], buf, len); + cprs->L1_pos += len; + } + } else { + /* put to L1 buffer */ + STP_DBG_PR_DBG("Put %d bytes to L1 buf\n", len); + if (is_iobuf) + osal_memcpy_fromio(&cprs->L1_buf[cprs->L1_pos], buf, len); + else + osal_memcpy(&cprs->L1_buf[cprs->L1_pos], buf, len); + cprs->L1_pos += len; + } + + return ret; +} + +/* stp_dbg_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 + */ +static _osal_inline_ INT32 stp_dbg_compressor_out(P_WCN_COMPRESSOR_T cprs, PPUINT8 pbuf, PINT32 plen) +{ + INT32 ret = 0; + INT32 tmp_len = 0; + + if ((!cprs) || (!pbuf) || (!plen)) { + STP_DBG_PR_ERR("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_PR_INFO("compress OK!\n"); + } else { + STP_DBG_PR_ERR("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_PR_INFO("0x%zx, len %d, l2_buf_remain %d\n", (SIZE_T)*pbuf, *plen, cprs->L2_buf_sz - cprs->L2_pos); + +#if 1 + ret = zlib_deflateReset((z_stream *) cprs->worker); + if (ret != Z_OK) { + STP_DBG_PR_ERR("reset failed!\n"); + return -2; + } +#endif + return 0; +} + +/* stp_dbg_compressor_reset - reset compressor + * @ cprs - compressor's pointer + * @ enable - enable/disable compress + * @ type - compress algorithm + * + * Retunr 0 if success, else NULL + */ +static _osal_inline_ INT32 stp_dbg_compressor_reset(P_WCN_COMPRESSOR_T cprs, UINT8 enable, + WCN_COMPRESS_ALG_T type) +{ + if (!cprs) { + STP_DBG_PR_ERR("invalid para!\n"); + return -1; + } + + cprs->f_compress_en = enable; + /* cprs->f_compress_en = 0; // disable compress for test */ + cprs->compress_type = type; + cprs->L1_pos = 0; + cprs->L2_pos = 0; + cprs->uncomp_size = 0; + cprs->crc32 = 0xffffffffUL; + + /* zlib_deflateEnd((z_stream*)cprs->worker); */ + + STP_DBG_PR_INFO("OK! compress algorithm %d\n", type); + + return 0; +} + +#if 0 +static _osal_inline_ VOID stp_dbg_dump_data(PUINT8 pBuf, PINT8 title, INT32 len) +{ + INT32 idx = 0; + UINT8 str[240]; + PUINT8 p_str; + + p_str = &str[0]; + pr_debug(" %s-len:%d\n", title, len); + for (idx = 0; idx < len; idx++, pBuf++) { + sprintf(p_str, "%02x ", *pBuf); + p_str += 3; + if (15 == (idx % 16)) { + sprintf(p_str, "--end\n"); + *(p_str + 6) = '\0'; + pr_debug("%s", str); + p_str = 0; + } + } + if (len % 16) { + sprintf(p_str, "--end\n"); + *(p_str + 6) = '\0'; + pr_debug("%s", str); + } +} +#endif +static VOID stp_dbg_dump_data(PUINT8 pBuf, PINT8 title, INT32 len) +{ + INT32 k = 0; + char str[240] = {""}; + char buf_str[32] = {""}; + + pr_warn(" %s-len:%d\n", title, len); + /* pr_warn(" ", title, len); */ + for (k = 0; k < len; k++) { + if (strlen(str) < 200) { + if (snprintf(buf_str, sizeof(buf_str), "0x%02x ", pBuf[k]) > 0) + strncat(str, buf_str, strlen(buf_str)); + } else { + pr_warn("More than 200 of the data is too much\n"); + break; + } + } + strncat(str, "--end\n", strlen("--end\n")); + pr_warn("%s", str); +} + + +INT32 stp_dbg_enable(MTKSTP_DBG_T *stp_dbg) +{ + ULONG 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; +} + +INT32 stp_dbg_disable(MTKSTP_DBG_T *stp_dbg) +{ + ULONG 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 PINT8 stp_get_dbg_type_string(const PINT8 *pType, UINT32 type) +{ + PINT8 info_task_type = ""; + + if (!pType) + return NULL; + + if ((mtk_wcn_stp_is_support_gpsl5() == 0) && (type == INFO_TASK_INDX)) + return info_task_type; + else + return pType[type]; +} + +static _osal_inline_ INT32 stp_dbg_dmp_in(MTKSTP_DBG_T *stp_dbg, PINT8 buf, INT32 len) +{ + ULONG flags; + STP_DBG_HDR_T *pHdr = NULL; + PINT8 pBuf = NULL; + UINT32 length = 0; + const PINT8 *pType = NULL; + + pType = wmt_detect_get_chip_type() == WMT_CHIP_TYPE_COMBO ? + comboStpDbgType : socStpDbgType; + + spin_lock_irqsave(&(stp_dbg->logsys->lock), flags); + + 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 (gStpDbgLogOut != 0) { + pHdr = (STP_DBG_HDR_T *) &(stp_dbg->logsys->queue[stp_dbg->logsys->in].buffer[0]); + pBuf = (PINT8)&(stp_dbg->logsys->queue[stp_dbg->logsys->in].buffer[0]) + + sizeof(STP_DBG_HDR_T); + length = stp_dbg->logsys->queue[stp_dbg->logsys->in].len - sizeof(STP_DBG_HDR_T); + pr_info("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", + stp_get_dbg_type_string(pType, pHdr->type), + pHdr->no, pHdr->len, pHdr->seq, pHdr->ack); + + if (length > 0) + stp_dbg_dump_data(pBuf, pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx", length); + } + stp_dbg->logsys->in = + (stp_dbg->logsys->in >= (STP_DBG_LOG_ENTRY_NUM - 1)) ? (0) : (stp_dbg->logsys->in + 1); + STP_DBG_PR_DBG("logsys size = %d, in = %d\n", stp_dbg->logsys->size, stp_dbg->logsys->in); + + spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags); + + return 0; +} + +static _osal_inline_ INT32 stp_dbg_notify_btm_dmp_wq(MTKSTP_DBG_T *stp_dbg) +{ + INT32 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; +} + +static VOID stp_dbg_dmp_print_work(struct work_struct *work) +{ + MTKSTP_LOG_SYS_T *logsys = container_of(work, MTKSTP_LOG_SYS_T, dump_work); + INT32 dumpSize = logsys->dump_size; + MTKSTP_LOG_ENTRY_T *queue = logsys->dump_queue; + INT32 i; + PINT8 pBuf = NULL; + INT32 len = 0; + STP_DBG_HDR_T *pHdr = NULL; + const PINT8 *pType = NULL; + + if (queue == NULL || queue == (MTKSTP_LOG_ENTRY_T *)STP_MAGIC_NUM) + return; + + pType = wmt_detect_get_chip_type() == WMT_CHIP_TYPE_COMBO ? + comboStpDbgType : socStpDbgType; + + for (i = 0; i < dumpSize; i++) { + pHdr = (STP_DBG_HDR_T *) &(queue[i].buffer[0]); + pBuf = &(queue[i].buffer[0]) + sizeof(STP_DBG_HDR_T); + len = queue[i].len - sizeof(STP_DBG_HDR_T); + len = len > STP_PKT_SZ ? STP_PKT_SZ : len; + pr_info("STP-DBG:%d.%ds, %s:pT%sn(%d)l(%d)s(%d)a(%d), time[%llu.%06lu]\n", + pHdr->sec, + pHdr->usec, + pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx", + stp_get_dbg_type_string(pType, pHdr->type), + pHdr->no, pHdr->len, pHdr->seq, + pHdr->ack, pHdr->l_sec, pHdr->l_nsec); + + if (len > 0) + stp_dbg_dump_data(pBuf, pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx", len); + + } + vfree(queue); + logsys->dump_queue = NULL; +} + +INT32 stp_dbg_dmp_print(MTKSTP_DBG_T *stp_dbg) +{ +#define MAX_DMP_NUM 80 + ULONG flags; + UINT32 dumpSize = 0; + UINT32 inIndex = 0; + UINT32 outIndex = 0; + MTKSTP_LOG_ENTRY_T *dump_queue = NULL; + MTKSTP_LOG_ENTRY_T *queue = stp_dbg->logsys->queue; + + spin_lock_irqsave(&(stp_dbg->logsys->lock), flags); + if (stp_dbg->logsys->dump_queue != NULL) { + spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags); + return 0; + } + + stp_dbg->logsys->dump_queue = (MTKSTP_LOG_ENTRY_T *)STP_MAGIC_NUM; + spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags); + + /* allocate memory may take long time, thus allocate it before get lock */ + dump_queue = vmalloc(sizeof(MTKSTP_LOG_ENTRY_T) * MAX_DMP_NUM); + if (dump_queue == NULL) { + stp_dbg->logsys->dump_queue = NULL; + pr_info("fail to allocate memory"); + return -1; + } + + if (spin_trylock_irqsave(&(stp_dbg->logsys->lock), flags) == 0) { + stp_dbg->logsys->dump_queue = NULL; + vfree(dump_queue); + pr_info("fail to get lock"); + return -1; + } + /* Not to dequeue from loging system */ + inIndex = stp_dbg->logsys->in; + dumpSize = stp_dbg->logsys->size; + + /* chance is little but still needs to check */ + if (dumpSize == 0) { + stp_dbg->logsys->dump_queue = NULL; + spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags); + vfree(dump_queue); + return 0; + } + + if (dumpSize == STP_DBG_LOG_ENTRY_NUM) + 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->logsys->dump_queue = dump_queue; + stp_dbg->logsys->dump_size = dumpSize; + + /* copy content of stp_dbg->logsys->queue out, don't print log while holding */ + /* spinlock to prevent blocking other process */ + if (outIndex + dumpSize > STP_DBG_LOG_ENTRY_NUM) { + UINT32 tailNum = STP_DBG_LOG_ENTRY_NUM - outIndex; + + osal_memcpy(dump_queue, &(queue[outIndex]), sizeof(MTKSTP_LOG_ENTRY_T) * tailNum); + osal_memcpy(dump_queue + tailNum, &(queue[0]), sizeof(MTKSTP_LOG_ENTRY_T) * + (dumpSize - tailNum)); + } else { + osal_memcpy(dump_queue, &(queue[outIndex]), sizeof(MTKSTP_LOG_ENTRY_T) * dumpSize); + } + + spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags); + STP_DBG_PR_INFO("loged packet size = %d, in(%d), out(%d)\n", dumpSize, inIndex, outIndex); + schedule_work(&(stp_dbg->logsys->dump_work)); + return 0; +} + +INT32 stp_dbg_dmp_out(MTKSTP_DBG_T *stp_dbg, PINT8 buf, PINT32 len) +{ + ULONG flags; + INT32 remaining = 0; + *len = 0; + spin_lock_irqsave(&(stp_dbg->logsys->lock), flags); + + if (stp_dbg->logsys->size > 0) { + if (stp_dbg->logsys->queue[stp_dbg->logsys->out].len >= STP_DBG_LOG_ENTRY_SZ) + stp_dbg->logsys->queue[stp_dbg->logsys->out].len = STP_DBG_LOG_ENTRY_SZ - 1; + 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_PR_DBG("logsys size = %d, out = %d\n", stp_dbg->logsys->size, + stp_dbg->logsys->out); + } else + STP_DBG_PR_LOUD("logsys EMPTY!\n"); + + remaining = (stp_dbg->logsys->size == 0) ? (0) : (1); + + spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags); + + return remaining; +} + +INT32 stp_dbg_dmp_out_ex(PINT8 buf, PINT32 len) +{ + return stp_dbg_dmp_out(g_stp_dbg, buf, len); +} + +INT32 stp_dbg_dmp_append(MTKSTP_DBG_T *stp_dbg, PUINT8 pBuf, INT32 max_len) +{ + PUINT8 p = NULL; + UINT32 l = 0; + UINT32 i = 0; + INT32 j = 0; + ULONG flags; + UINT32 len = 0; + UINT32 dumpSize = 0; + STP_DBG_HDR_T *pHdr = NULL; + const PINT8 *pType = NULL; + + if (!pBuf || max_len < 8) { /* 8: length of "\n" */ + STP_DBG_PR_WARN("invalid param, pBuf:%p, max_len:%d\n", pBuf, max_len); + return 0; + } + + pType = wmt_detect_get_chip_type() == WMT_CHIP_TYPE_COMBO ? + comboStpDbgType : socStpDbgType; + spin_lock_irqsave(&(stp_dbg->logsys->lock), flags); + /* Not to dequeue from loging system */ + dumpSize = stp_dbg->logsys->size; + j = stp_dbg->logsys->in; + + /* format */ + len += osal_sprintf(pBuf, "\n" + */ + if ((len + 53 + 3 * l + 4) > max_len) + break; + + pHdr = (STP_DBG_HDR_T *) &(stp_dbg->logsys->queue[j].buffer[0]); + p = (PUINT8)pHdr + sizeof(STP_DBG_HDR_T); + + len += osal_sprintf(pBuf + len, "\t%llu.%06lus, %s:pT%sn(%d)l(%4d)s(%d)a(%d)\t", + pHdr->l_sec, pHdr->l_nsec, + pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx", + stp_get_dbg_type_string(pType, pHdr->type), + pHdr->no, pHdr->len, pHdr->seq, + pHdr->ack); + + for (i = 0; i < l; i++, p++) + len += osal_sprintf(pBuf + len, " %02x", *p, 3); + + pBuf[len] = '\n'; + len += 1; + + dumpSize--; + } + + len += osal_sprintf(pBuf + len, "-->\n"); + + spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags); + + return len; +} + +static _osal_inline_ INT32 stp_dbg_get_avl_entry_num(MTKSTP_DBG_T *stp_dbg) +{ + if (stp_dbg->logsys->size == 0) + return STP_DBG_LOG_ENTRY_NUM; + else + return (stp_dbg->logsys->in > stp_dbg->logsys->out) ? + (STP_DBG_LOG_ENTRY_NUM - stp_dbg->logsys->in + stp_dbg->logsys->out) : + (stp_dbg->logsys->out - stp_dbg->logsys->in); +} + +static _osal_inline_ INT32 stp_dbg_fill_hdr(STP_DBG_HDR_T *hdr, INT32 type, INT32 ack, INT32 seq, + INT32 crc, INT32 dir, INT32 len, INT32 dbg_type) +{ + + struct timeval now; + UINT64 ts; + ULONG nsec; + + if (!hdr) { + STP_DBG_PR_ERR("function invalid\n"); + return -EINVAL; + } + + osal_do_gettimeofday(&now); + osal_get_local_time(&ts, &nsec); + hdr->last_dbg_type = gStpDbgDumpType; + gStpDbgDumpType = dbg_type; + 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; + hdr->l_sec = ts; + hdr->l_nsec = nsec; + return 0; +} + +static _osal_inline_ INT32 stp_dbg_add_pkt(MTKSTP_DBG_T *stp_dbg, STP_DBG_HDR_T *hdr, const PUINT8 body) +{ + /* fix the frame size large issues. */ + static STP_PACKET_T stp_pkt; + UINT32 hdr_sz = sizeof(struct stp_dbg_pkt_hdr); + UINT32 body_sz = 0; + ULONG flags; + UINT32 avl_num; + + 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((PUINT8) &stp_pkt.hdr, (PUINT8) hdr, hdr_sz); + if (body != NULL) + memcpy((PUINT8) &stp_pkt.raw[0], body, body_sz); + + if (hdr->dbg_type == STP_DBG_FW_DMP) { + if (hdr->last_dbg_type != STP_DBG_FW_DMP) { + + STP_DBG_PR_INFO + ("reset stp_dbg logsys when queue fw coredump package(%d)\n", + hdr->last_dbg_type); + STP_DBG_PR_INFO("dump 1st fw coredump package len(%d) for confirming\n", + hdr->len); + spin_lock_irqsave(&(stp_dbg->logsys->lock), flags); + stp_dbg->logsys->in = 0; + stp_dbg->logsys->out = 0; + stp_dbg->logsys->size = 0; + spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags); + } else { + avl_num = stp_dbg_get_avl_entry_num(stp_dbg); + + if (!avl_num) + STP_DBG_PR_ERR("there is no avl entry stp_dbg logsys!!!\n"); + } + } + stp_dbg_dmp_in(stp_dbg, (PINT8) &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_dbg_notify_btm_dmp_wq(stp_dbg); + + return 0; +} + +INT32 stp_dbg_log_pkt(MTKSTP_DBG_T *stp_dbg, INT32 dbg_type, + INT32 type, INT32 ack_no, INT32 seq_no, INT32 crc, INT32 dir, INT32 len, + const PUINT8 body) +{ + STP_DBG_HDR_T hdr; + + osal_bug_on(!stp_dbg); + + if (!stp_dbg) + return -1; + + if (stp_dbg->is_enable == 0) { + /*dbg is disable,and not to log */ + } else { + hdr.no = 0; + hdr.chs = 0; + stp_dbg_fill_hdr(&hdr, + (INT32) type, + (INT32) ack_no, + (INT32) seq_no, (INT32) crc, (INT32) dir, (INT32) len, + (INT32) dbg_type); + + stp_dbg_add_pkt(stp_dbg, &hdr, body); + } + + return 0; +} + +INT32 stp_dbg_log_ctrl(UINT32 on) +{ + if (on != 0) { + gStpDbgLogOut = 1; + pr_warn("STP-DBG: enable pkt log dump out.\n"); + } else { + gStpDbgLogOut = 0; + pr_warn("STP-DBG: disable pkt log dump out.\n"); + } + + return 0; +} + +VOID stp_dbg_nl_init(VOID) +{ +#if 0 + if (genl_register_family(&stp_dbg_gnl_family) != 0) { + STP_DBG_PR_ERR("%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_PR_ERR("%s(): BIND operation registration fail\n", __func__); + + if (genl_register_ops(&stp_dbg_gnl_family, &stp_dbg_gnl_ops_reset) != 0) + STP_DBG_PR_ERR("%s(): RESET operation registration fail\n", __func__); + + } +#endif + osal_sleepable_lock_init(&g_dbg_nl_lock); + if (genl_register_family(&stp_dbg_gnl_family) != 0) + STP_DBG_PR_ERR("%s(): GE_NELINK family registration fail\n", __func__); +} + +VOID stp_dbg_nl_deinit(VOID) +{ + int i; + + num_bind_process = 0; + for (i = 0; i < MAX_BIND_PROCESS; i++) + bind_pid[i] = 0; + genl_unregister_family(&stp_dbg_gnl_family); + osal_sleepable_lock_deinit(&g_dbg_nl_lock); +} + +static INT32 stp_dbg_nl_bind(struct sk_buff *skb, struct genl_info *info) +{ + struct nlattr *na = NULL; + PINT8 mydata; + INT32 i; + + if (info == NULL) + goto out; + + STP_DBG_PR_INFO("%s():->\n", __func__); + + na = info->attrs[STP_DBG_ATTR_MSG]; + + if (na) + mydata = (PINT8) nla_data(na); + + if (osal_lock_sleepable_lock(&g_dbg_nl_lock)) + return -1; + + for (i = 0; i < MAX_BIND_PROCESS; i++) { + if (bind_pid[i] == 0) { + bind_pid[i] = info->snd_portid; + num_bind_process++; + STP_DBG_PR_INFO("%s():-> pid = %d\n", __func__, info->snd_portid); + break; + } + } + + if (i == MAX_BIND_PROCESS) { + STP_DBG_PR_ERR("%s(): exceeding binding limit %d\n", __func__, MAX_BIND_PROCESS); + bind_pid[0] = info->snd_portid; + } + + osal_unlock_sleepable_lock(&g_dbg_nl_lock); + +out: + return 0; +} + +static INT32 stp_dbg_nl_reset(struct sk_buff *skb, struct genl_info *info) +{ + STP_DBG_PR_ERR("%s(): should not be invoked\n", __func__); + + return 0; +} + +INT32 stp_dbg_nl_send(PINT8 aucMsg, UINT8 cmd, INT32 len) +{ + struct sk_buff *skb = NULL; + PVOID msg_head = NULL; + INT32 rc = -1; + INT32 i, j; + INT32 ret = 0; + INT32 killed_num = 0; + + if (num_bind_process == 0) { + /* no listening process */ + STP_DBG_PR_ERR("%s(): the process is not invoked\n", __func__); + return 0; + } + + ret = stp_dbg_core_dump_nl(g_core_dump, aucMsg, len); + if (ret < 0) + return ret; + if (ret == 32) + return ret; + + ret = -1; + for (i = 0; i < num_bind_process; i++) { + if (bind_pid[i] == 0) { + killed_num++; + continue; + } + + 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_PR_ERR("%s(): genlmsg_put fail...\n", __func__); + return -1; + } + + rc = nla_put(skb, STP_DBG_ATTR_MSG, len, aucMsg); + if (rc != 0) { + nlmsg_free(skb); + STP_DBG_PR_ERR("%s(): nla_put_string fail...: %d\n", __func__, rc); + return rc; + } + + /* finalize the message */ + genlmsg_end(skb, msg_head); + + /* sending message */ + rc = genlmsg_unicast(&init_net, skb, bind_pid[i]); + if (rc != 0) { + STP_DBG_PR_INFO("%s(): genlmsg_unicast fail...: %d pid: %d\n", + __func__, rc, bind_pid[i]); + if (rc == -ECONNREFUSED) { + bind_pid[i] = 0; + killed_num++; + } + } else { + /* don't retry as long as at least one process receives data */ + ret = 0; + } + } else { + STP_DBG_PR_ERR("%s(): genlmsg_new fail...\n", __func__); + } + } + + if (killed_num > 0) { + if (osal_lock_sleepable_lock(&g_dbg_nl_lock)) { + /* if fail to get lock, it is fine to update bind_pid[] later */ + return ret; + } + + for (i = 0; i < num_bind_process - killed_num; i++) { + if (bind_pid[i] == 0) { + for (j = num_bind_process - 1; j > i; j--) { + if (bind_pid[j] > 0) { + bind_pid[i] = bind_pid[j]; + bind_pid[j] = 0; + } + } + } + } + num_bind_process -= killed_num; + osal_unlock_sleepable_lock(&g_dbg_nl_lock); + } + + return ret; +} + +INT32 stp_dbg_dump_send_retry_handler(PINT8 tmp, INT32 len) +{ + INT32 ret = 0; + INT32 nl_retry = 0; + + if (tmp == NULL) + return -1; + + ret = stp_dbg_nl_send(tmp, 2, len+5); + while (ret) { + nl_retry++; + if (ret == 32) { + STP_DBG_PR_ERR("**dump send timeout : %d**\n", ret); + ret = 1; + break; + } + if (nl_retry > 1000) { + STP_DBG_PR_ERR("**dump send fails, and retry more than 1000: %d.**\n", ret); + ret = 2; + break; + } + STP_DBG_PR_WARN("**dump send fails, and retry again.**\n"); + osal_sleep_ms(3); + ret = stp_dbg_nl_send(tmp, 2, len+5); + if (!ret) + STP_DBG_PR_DBG("****retry again ok!**\n"); + } + + return ret; +} + +INT32 stp_dbg_aee_send(PUINT8 aucMsg, INT32 len, INT32 cmd) +{ +#define KBYTES (1024*sizeof(char)) +#ifndef LOG_STP_DEBUG_DISABLE +#define L1_BUF_SIZE (32*KBYTES) +#define PKT_MULTIPLIER 18 +#else +#define L1_BUF_SIZE (4*KBYTES) +#define PKT_MULTIPLIER 1 +#endif + INT32 ret = 0; + + if (g_core_dump->count == 0) { + g_core_dump->compressor = stp_dbg_compressor_init("core_dump_compressor", + L1_BUF_SIZE, + PKT_MULTIPLIER*g_core_dump->dmp_num*KBYTES); + g_core_dump->count++; + if (!g_core_dump->compressor) { + STP_DBG_PR_ERR("create compressor failed!\n"); + stp_dbg_compressor_deinit(g_core_dump->compressor); + return -1; + } + } + /* buffered to compressor */ + ret = stp_dbg_core_dump_in(g_core_dump, aucMsg, len); + if (ret == 1 && wmt_detect_get_chip_type() == WMT_CHIP_TYPE_COMBO) + stp_dbg_core_dump_flush(0, MTK_WCN_BOOL_FALSE); + + return ret; +} + +INT32 stp_dbg_dump_num(LONG dmp_num) +{ + g_core_dump->dmp_num = dmp_num; + return 0; +} + +static _osal_inline_ INT32 stp_dbg_parser_assert_str(PINT8 str, ENUM_ASSERT_INFO_PARSER_TYPE type) +{ +#define WDT_INFO_HEAD "Watch Dog Timeout" + PINT8 pStr = NULL; + PINT8 pDtr = NULL; + PINT8 pTemp = NULL; + PINT8 pTemp2 = NULL; + INT8 tempBuf[STP_ASSERT_TYPE_SIZE] = { 0 }; + UINT32 len = 0; + LONG res; + INT32 ret; + INT32 remain_array_len = 0; + + PUINT8 parser_sub_string[] = { + " ", + "id=", + "isr=", + "irq=", + "rc=" + }; + + if (!str) { + STP_DBG_PR_ERR("NULL string source\n"); + return -1; + } + + if (!g_stp_dbg_cpupcr) { + STP_DBG_PR_ERR("NULL pointer\n"); + return -2; + } + + pStr = str; + STP_DBG_PR_DBG("source infor:%s\n", pStr); + switch (type) { + case STP_DBG_ASSERT_INFO: + + + pDtr = osal_strstr(pStr, parser_sub_string[type]); + if (pDtr != NULL) { + pDtr += osal_strlen(parser_sub_string[type]); + pTemp = osal_strchr(pDtr, ' '); + } else { + STP_DBG_PR_ERR("parser str is NULL,substring(%s)\n", parser_sub_string[type]); + return -3; + } + + if (pTemp == NULL) { + STP_DBG_PR_ERR("delimiter( ) is not found,substring(%s)\n", + parser_sub_string[type]); + return -4; + } + + len = pTemp - pDtr; + osal_memcpy(&g_stp_dbg_cpupcr->assert_info[0], "assert@", osal_strlen("assert@")); + osal_memcpy(&g_stp_dbg_cpupcr->assert_info[osal_strlen("assert@")], pDtr, len); + g_stp_dbg_cpupcr->assert_info[osal_strlen("assert@") + len] = '_'; + + pTemp = osal_strchr(pDtr, '#'); + if (pTemp == NULL) { + STP_DBG_PR_ERR("parser '#' is not find\n"); + return -5; + } + pTemp += 1; + + pTemp2 = osal_strchr(pTemp, ' '); + if (pTemp2 == NULL) { + STP_DBG_PR_ERR("parser ' ' is not find\n"); + pTemp2 = pTemp + 1; + } + remain_array_len = osal_array_size(g_stp_dbg_cpupcr->assert_info) - (osal_strlen("assert@") + len + 1); + if (remain_array_len - 1 > pTemp2 - pTemp) { + osal_memcpy(&g_stp_dbg_cpupcr->assert_info[osal_strlen("assert@") + len + 1], pTemp, + pTemp2 - pTemp); + g_stp_dbg_cpupcr->assert_info[osal_strlen("assert@") + len + 1 + pTemp2 - pTemp] = '\0'; + } else { + osal_memcpy(&g_stp_dbg_cpupcr->assert_info[osal_strlen("assert@") + len + 1], pTemp, + remain_array_len - 1); + g_stp_dbg_cpupcr->assert_info[STP_ASSERT_INFO_SIZE - 1] = '\0'; + } + STP_DBG_PR_INFO("assert info:%s\n", &g_stp_dbg_cpupcr->assert_info[0]); + break; + case STP_DBG_FW_TASK_ID: + pDtr = osal_strstr(pStr, parser_sub_string[type]); + if (pDtr != NULL) { + pDtr += osal_strlen(parser_sub_string[type]); + pTemp = osal_strchr(pDtr, ' '); + } else { + STP_DBG_PR_ERR("parser str is NULL,substring(%s)\n", parser_sub_string[type]); + return -3; + } + + if (pTemp == NULL) { + STP_DBG_PR_ERR("delimiter( ) is not found,substring(%s)\n", + parser_sub_string[type]); + return -4; + } + + len = pTemp - pDtr; + len = (len >= STP_ASSERT_TYPE_SIZE) ? STP_ASSERT_TYPE_SIZE - 1 : len; + osal_memcpy(&tempBuf[0], pDtr, len); + tempBuf[len] = '\0'; + ret = osal_strtol(tempBuf, 16, &res); + if (ret) { + STP_DBG_PR_ERR("get fw task id fail(%d)\n", ret); + return -4; + } + g_stp_dbg_cpupcr->fwTaskId = (UINT32)res; + + STP_DBG_PR_INFO("fw task id :%x\n", (UINT32)res); + break; + case STP_DBG_FW_ISR: + pDtr = osal_strstr(pStr, parser_sub_string[type]); + + if (pDtr != NULL) { + pDtr += osal_strlen(parser_sub_string[type]); + pTemp = osal_strchr(pDtr, ','); + } else { + STP_DBG_PR_ERR("parser str is NULL,substring(%s)\n", + parser_sub_string[type]); + return -3; + } + + if (pTemp == NULL) { + STP_DBG_PR_ERR("delimiter(,) is not found,substring(%s)\n", + parser_sub_string[type]); + return -4; + } + + len = pTemp - pDtr; + len = (len >= STP_ASSERT_TYPE_SIZE) ? STP_ASSERT_TYPE_SIZE - 1 : len; + osal_memcpy(&tempBuf[0], pDtr, len); + tempBuf[len] = '\0'; + ret = osal_strtol(tempBuf, 16, &res); + if (ret) { + STP_DBG_PR_ERR("get fw isr id fail(%d)\n", ret); + return -4; + } + g_stp_dbg_cpupcr->fwIsr = (UINT32)res; + + STP_DBG_PR_INFO("fw isr str:%x\n", (UINT32)res); + break; + case STP_DBG_FW_IRQ: + pDtr = osal_strstr(pStr, parser_sub_string[type]); + if (pDtr != NULL) { + pDtr += osal_strlen(parser_sub_string[type]); + pTemp = osal_strchr(pDtr, ','); + } else { + STP_DBG_PR_ERR("parser str is NULL,substring(%s)\n", parser_sub_string[type]); + return -3; + } + + if (pTemp == NULL) { + STP_DBG_PR_ERR("delimiter(,) is not found,substring(%s)\n", + parser_sub_string[type]); + return -4; + } + + len = pTemp - pDtr; + len = (len >= STP_ASSERT_TYPE_SIZE) ? STP_ASSERT_TYPE_SIZE - 1 : len; + osal_memcpy(&tempBuf[0], pDtr, len); + tempBuf[len] = '\0'; + ret = osal_strtol(tempBuf, 16, &res); + if (ret) { + STP_DBG_PR_ERR("get fw irq id fail(%d)\n", ret); + return -4; + } + g_stp_dbg_cpupcr->fwRrq = (UINT32)res; + + STP_DBG_PR_INFO("fw irq value:%x\n", (UINT32)res); + break; + case STP_DBG_ASSERT_TYPE: + pDtr = osal_strstr(pStr, parser_sub_string[type]); + if (pDtr != NULL) { + pDtr += osal_strlen(parser_sub_string[type]); + pTemp = osal_strchr(pDtr, ','); + } else { + STP_DBG_PR_ERR("parser str is NULL,substring(%s)\n", parser_sub_string[type]); + return -3; + } + + if (pTemp == NULL) { + STP_DBG_PR_ERR("delimiter(,) is not found,substring(%s)\n", + parser_sub_string[type]); + return -4; + } + + len = pTemp - pDtr; + len = (len >= STP_ASSERT_TYPE_SIZE) ? STP_ASSERT_TYPE_SIZE - 1 : len; + osal_memcpy(&tempBuf[0], pDtr, len); + tempBuf[len] = '\0'; + + if (osal_memcmp(tempBuf, "*", osal_strlen("*")) == 0) + osal_memcpy(&g_stp_dbg_cpupcr->assert_type[0], "general assert", + osal_strlen("general assert")); + if (osal_memcmp(tempBuf, WDT_INFO_HEAD, osal_strlen(WDT_INFO_HEAD)) == 0) + osal_memcpy(&g_stp_dbg_cpupcr->assert_type[0], "wdt", osal_strlen("wdt")); + if (osal_memcmp(tempBuf, "RB_FULL", osal_strlen("RB_FULL")) == 0) { + osal_memcpy(&g_stp_dbg_cpupcr->assert_type[0], tempBuf, len); + + pDtr = osal_strstr(&g_stp_dbg_cpupcr->assert_type[0], "RB_FULL("); + if (pDtr != NULL) { + pDtr += osal_strlen("RB_FULL("); + pTemp = osal_strchr(pDtr, ')'); + } else { + STP_DBG_PR_ERR("parser str is NULL,substring(RB_FULL()\n"); + return -5; + } + len = pTemp - pDtr; + len = (len >= STP_ASSERT_TYPE_SIZE) ? STP_ASSERT_TYPE_SIZE - 1 : len; + osal_memcpy(&tempBuf[0], pDtr, len); + tempBuf[len] = '\0'; + ret = osal_strtol(tempBuf, 16, &res); + if (ret) { + STP_DBG_PR_ERR("get fw task id fail(%d)\n", ret); + return -5; + } + g_stp_dbg_cpupcr->fwTaskId = (UINT32)res; + + STP_DBG_PR_INFO("update fw task id :%x\n", (UINT32)res); + } + + STP_DBG_PR_INFO("fw asert type:%s\n", g_stp_dbg_cpupcr->assert_type); + break; + default: + STP_DBG_PR_ERR("unknown parser type\n"); + break; + } + + return 0; +} + +static _osal_inline_ P_STP_DBG_CPUPCR_T stp_dbg_cpupcr_init(VOID) +{ + P_STP_DBG_CPUPCR_T pSdCpupcr = NULL; + + pSdCpupcr = (P_STP_DBG_CPUPCR_T) osal_malloc(osal_sizeof(STP_DBG_CPUPCR_T)); + if (!pSdCpupcr) { + STP_DBG_PR_ERR("stp dbg cpupcr allocate memory fail!\n"); + return NULL; + } + + osal_memset(pSdCpupcr, 0, osal_sizeof(STP_DBG_CPUPCR_T)); + + osal_sleepable_lock_init(&pSdCpupcr->lock); + + return pSdCpupcr; +} + +static _osal_inline_ VOID stp_dbg_cpupcr_deinit(P_STP_DBG_CPUPCR_T pCpupcr) +{ + if (pCpupcr) { + osal_sleepable_lock_deinit(&pCpupcr->lock); + osal_free(pCpupcr); + pCpupcr = NULL; + } +} + +static _osal_inline_ P_STP_DBG_DMAREGS_T stp_dbg_dmaregs_init(VOID) +{ + P_STP_DBG_DMAREGS_T pDmaRegs = NULL; + + pDmaRegs = (P_STP_DBG_DMAREGS_T) osal_malloc(osal_sizeof(STP_DBG_DMAREGS_T)); + if (!pDmaRegs) { + STP_DBG_PR_ERR("stp dbg dmareg allocate memory fail!\n"); + return NULL; + } + + osal_memset(pDmaRegs, 0, osal_sizeof(STP_DBG_DMAREGS_T)); + + osal_sleepable_lock_init(&pDmaRegs->lock); + + return pDmaRegs; +} + +static VOID stp_dbg_dmaregs_deinit(P_STP_DBG_DMAREGS_T pDmaRegs) +{ + if (pDmaRegs) { + osal_sleepable_lock_deinit(&pDmaRegs->lock); + osal_free(pDmaRegs); + pDmaRegs = NULL; + } +} + +/* + * who call this ? + * - stp_dbg_soc_paged_dump + * generate coredump and coredump timeout + * - wmt_dbg_poll_cpupcr + * dump cpupcr through command + * - mtk_stp_dbg_poll_cpupcr (should remove this) + * export to other drivers + * - _stp_btm_handler + * coredump timeout + * - wmt_ctrl_rx + * rx timeout + * - stp_do_tx_timeout + * tx timeout + * + */ +INT32 stp_dbg_poll_cpupcr(UINT32 times, UINT32 sleep, UINT32 cmd) +{ + INT32 i = 0; + UINT32 value = 0x0; + ENUM_WMT_CHIP_TYPE chip_type; + UINT8 cccr_value = 0x0; + INT32 chip_id = -1; + INT32 i_ret = 0; + INT32 count = 0; + + if (!g_stp_dbg_cpupcr) { + STP_DBG_PR_ERR("NULL reference pointer\n"); + return -1; + } + + chip_type = wmt_detect_get_chip_type(); + + if (times > STP_DBG_CPUPCR_NUM) + times = STP_DBG_CPUPCR_NUM; + + switch (chip_type) { + case WMT_CHIP_TYPE_COMBO: + osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + for (i = 0; i < times; i++) { + stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, + g_stp_sdio_host_info.sdio_cltctx, SWPCDBGR, &value, 0); + g_stp_dbg_cpupcr->buffer[g_stp_dbg_cpupcr->count] = value; + osal_get_local_time(&(g_stp_dbg_cpupcr->sec_buffer[g_stp_dbg_cpupcr->count]), + &(g_stp_dbg_cpupcr->nsec_buffer[g_stp_dbg_cpupcr->count])); + if (sleep > 0) + osal_sleep_ms(sleep); + g_stp_dbg_cpupcr->count++; + if (g_stp_dbg_cpupcr->count >= STP_DBG_CPUPCR_NUM) + g_stp_dbg_cpupcr->count = 0; + } + osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + break; + case WMT_CHIP_TYPE_SOC: + if (times > WMT_CORE_DMP_CPUPCR_NUM) + times = WMT_CORE_DMP_CPUPCR_NUM; + if (wmt_lib_dmp_consys_state(&g_dmp_info, times, sleep) == MTK_WCN_BOOL_TRUE) { + osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + for (i = 0; i < times; i++) { + g_stp_dbg_cpupcr->buffer[g_stp_dbg_cpupcr->count] = g_dmp_info.cpu_pcr[i]; + osal_get_local_time(&(g_stp_dbg_cpupcr->sec_buffer[g_stp_dbg_cpupcr->count]), + &(g_stp_dbg_cpupcr->nsec_buffer[g_stp_dbg_cpupcr->count])); + g_stp_dbg_cpupcr->count++; + if (g_stp_dbg_cpupcr->count >= STP_DBG_CPUPCR_NUM) + g_stp_dbg_cpupcr->count = 0; + } + osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + } + break; + default: + STP_DBG_PR_INFO("error chip type(%d)\n", chip_type); + } + + if (cmd) { + UINT8 str[DBG_LOG_STR_SIZE] = {""}; + PUINT8 p = str; + INT32 str_len = 0; + + for (i = 0; i < STP_DBG_CPUPCR_NUM; i++) { + if (g_stp_dbg_cpupcr->sec_buffer[i] == 0 && + g_stp_dbg_cpupcr->nsec_buffer[i] == 0) + continue; + + count++; + if (count % 4 != 0) { + str_len = osal_sprintf(p, "%llu.%06lu/0x%08x;", + g_stp_dbg_cpupcr->sec_buffer[i], + g_stp_dbg_cpupcr->nsec_buffer[i], + g_stp_dbg_cpupcr->buffer[i]); + p += str_len; + } else { + str_len = osal_sprintf(p, "%llu.%06lu/0x%08x;", + g_stp_dbg_cpupcr->sec_buffer[i], + g_stp_dbg_cpupcr->nsec_buffer[i], + g_stp_dbg_cpupcr->buffer[i]); + STP_DBG_PR_INFO("TIME/CPUPCR: %s\n", str); + p = str; + } + } + if (count % 4 != 0) + STP_DBG_PR_INFO("TIME/CPUPCR: %s\n", str); + + if (wmt_lib_power_lock_trylock()) { + if (chip_type == WMT_CHIP_TYPE_SOC && wmt_lib_reg_readable()) { + STP_DBG_PR_INFO("CONNSYS cpu:0x%x/bus:0x%x/dbg_cr1:0x%x/dbg_cr2:0x%x/EMIaddr:0x%x\n", + stp_dbg_soc_read_debug_crs(CONNSYS_CPU_CLK), + stp_dbg_soc_read_debug_crs(CONNSYS_BUS_CLK), + stp_dbg_soc_read_debug_crs(CONNSYS_DEBUG_CR1), + stp_dbg_soc_read_debug_crs(CONNSYS_DEBUG_CR2), + stp_dbg_soc_read_debug_crs(CONNSYS_EMI_REMAP)); + } + wmt_lib_power_lock_release(); + } + + chip_id = mtk_wcn_wmt_chipid_query(); + if (chip_id == 0x6632) { + for (i = 0; i < 8; i++) { + i_ret = mtk_wcn_hif_sdio_f0_readb(g_stp_sdio_host_info.sdio_cltctx, + CCCR_F8 + i, &cccr_value); + if (i_ret) + STP_DBG_PR_ERR("read CCCR fail(%d), address(0x%x)\n", + i_ret, CCCR_F8 + i); + else + STP_DBG_PR_INFO("read CCCR value(0x%x), address(0x%x)\n", + cccr_value, CCCR_F8 + i); + cccr_value = 0x0; + } + } + /* Need in platform code - mtxxxx.c to provide function implementation */ + mtk_wcn_consys_hang_debug(); + } + if (chip_type == WMT_CHIP_TYPE_COMBO) { + STP_DBG_PR_INFO("dump sdio register for debug\n"); + mtk_stp_dump_sdio_register(); + } + return 0; +} + +INT32 stp_dbg_dump_cpupcr_reg_info(PUINT8 buf, UINT32 consys_lp_reg) +{ + INT32 i = 0; + INT32 count = 0; + UINT32 len = 0; + + /* never retrun negative value */ + if (!g_stp_dbg_cpupcr || !buf) { + STP_DBG_PR_DBG("NULL pointer, g_stp_dbg_cpupcr:%p, buf:%p\n", + g_stp_dbg_cpupcr, buf); + return 0; + } + + for (i = 0; i < STP_DBG_CPUPCR_NUM; i++) { + if (g_stp_dbg_cpupcr->sec_buffer[i] == 0 && + g_stp_dbg_cpupcr->nsec_buffer[i] == 0) + continue; + count++; + if (count == 1) + len += osal_sprintf(buf + len, "0x%08x", g_stp_dbg_cpupcr->buffer[i]); + else + len += osal_sprintf(buf + len, ";0x%08x", g_stp_dbg_cpupcr->buffer[i]); + } + + if (count == 0) + len += osal_sprintf(buf + len, "0x%08x\n", consys_lp_reg); + else + len += osal_sprintf(buf + len, ";0x%08x\n", consys_lp_reg); + + stp_dbg_clear_cpupcr_reg_info(); + + return len; +} + +VOID stp_dbg_clear_cpupcr_reg_info(VOID) +{ + if (osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock)) { + STP_DBG_PR_DBG("lock failed\n"); + return; + } + + osal_memset(&g_stp_dbg_cpupcr->buffer[0], 0, STP_DBG_CPUPCR_NUM); + g_stp_dbg_cpupcr->count = 0; + g_stp_dbg_cpupcr->host_assert_info.reason = 0; + g_stp_dbg_cpupcr->host_assert_info.drv_type = 0; + g_stp_dbg_cpupcr->issue_type = STP_FW_ISSUE_TYPE_INVALID; + g_stp_dbg_cpupcr->keyword[0] = '\0'; + osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); +} + +INT32 stp_dbg_poll_dmaregs(UINT32 times, UINT32 sleep) +{ +#if 0 + INT32 i = 0; + + if (!g_stp_dbg_dmaregs) { + STP_DBG_PR_ERR("NULL reference pointer\n"); + return -1; + } + + osal_lock_sleepable_lock(&g_stp_dbg_dmaregs->lock); + + if (g_stp_dbg_dmaregs->count + times > STP_DBG_DMAREGS_NUM) { + if (g_stp_dbg_dmaregs->count > STP_DBG_DMAREGS_NUM) { + STP_DBG_PR_ERR("g_stp_dbg_dmaregs->count:%d must less than STP_DBG_DMAREGS_NUM:%d\n", + g_stp_dbg_dmaregs->count, STP_DBG_DMAREGS_NUM); + g_stp_dbg_dmaregs->count = 0; + STP_DBG_PR_ERR("g_stp_dbg_dmaregs->count be set default value 0\n"); + } + times = STP_DBG_DMAREGS_NUM - g_stp_dbg_dmaregs->count; + } + if (times > STP_DBG_DMAREGS_NUM) { + STP_DBG_PR_ERR("times overflow, set default value:0\n"); + times = 0; + } + + for (i = 0; i < times; i++) { + INT32 k = 0; + + for (; k < DMA_REGS_MAX; k++) { + STP_DBG_PR_INFO("times:%d,i:%d reg: %s, regs:%08x\n", times, i, dmaRegsStr[k], + wmt_plat_read_dmaregs(k)); + /* g_stp_dbg_dmaregs->dmaIssue[k][g_stp_dbg_dmaregs->count + i] = + * wmt_plat_read_dmaregs(k); + */ + } + osal_sleep_ms(sleep); + } + + g_stp_dbg_dmaregs->count += times; + + osal_unlock_sleepable_lock(&g_stp_dbg_dmaregs->lock); +#else + return 0; +#endif +} + +INT32 stp_dbg_poll_cpupcr_ctrl(UINT32 en) +{ + STP_DBG_PR_INFO("%s polling cpupcr\n", en == 0 ? "start" : "stop"); + + osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + g_stp_dbg_cpupcr->stop_flag = en; + osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + + return 0; +} + +INT32 stp_dbg_set_version_info(UINT32 chipid, PUINT8 pRomVer, PUINT8 pPatchVer, PUINT8 pPatchBrh) +{ + if (g_stp_dbg_cpupcr) { + osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + g_stp_dbg_cpupcr->chipId = chipid; + + if (pRomVer) + osal_memcpy(g_stp_dbg_cpupcr->romVer, pRomVer, 2); + if (pPatchVer) + osal_memcpy(g_stp_dbg_cpupcr->patchVer, pPatchVer, 8); + if (pPatchBrh) + osal_memcpy(g_stp_dbg_cpupcr->branchVer, pPatchBrh, 4); + + osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + } else { + STP_DBG_PR_ERR("NULL pointer\n"); + return -1; + } + + STP_DBG_PR_DBG("chipid(0x%x),romver(%s),patchver(%s),branchver(%s)\n", + g_stp_dbg_cpupcr->chipId, + &g_stp_dbg_cpupcr->romVer[0], + &g_stp_dbg_cpupcr->patchVer[0], + &g_stp_dbg_cpupcr->branchVer[0]); + + return 0; +} + +INT32 stp_dbg_set_wifiver(UINT32 wifiver) +{ + if (!g_stp_dbg_cpupcr) { + STP_DBG_PR_ERR("NULL pointer\n"); + return -1; + } + + osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + g_stp_dbg_cpupcr->wifiVer = wifiver; + osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + + STP_DBG_PR_INFO("wifiver(%x)\n", g_stp_dbg_cpupcr->wifiVer); + + return 0; +} + +INT32 stp_dbg_set_host_assert_info(UINT32 drv_type, UINT32 reason, UINT32 en) +{ + osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + + g_stp_dbg_cpupcr->host_assert_info.assert_from_host = en; + g_stp_dbg_cpupcr->host_assert_info.drv_type = drv_type; + g_stp_dbg_cpupcr->host_assert_info.reason = reason; + + osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + + return 0; +} + +VOID stp_dbg_set_keyword(PINT8 keyword) +{ + osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + if (keyword != NULL) { + if (osal_strlen(keyword) >= STP_DBG_KEYWORD_SIZE) + STP_DBG_PR_INFO("Keyword over max size(%d)\n", STP_DBG_KEYWORD_SIZE); + else if (osal_strchr(keyword, '<') != NULL || osal_strchr(keyword, '>') != NULL) + STP_DBG_PR_INFO("Keyword has < or >, keywrod: %s\n", keyword); + else + osal_strncat(&g_stp_dbg_cpupcr->keyword[0], keyword, osal_strlen(keyword)); + } else { + g_stp_dbg_cpupcr->keyword[0] = '\0'; + } + osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); +} + +UINT32 stp_dbg_get_host_trigger_assert(VOID) +{ + return g_stp_dbg_cpupcr->host_assert_info.assert_from_host; +} + +VOID stp_dbg_set_coredump_timer_state(CORE_DUMP_STA state) +{ + if (g_core_dump) + g_core_dump->sm = state; +} + +INT32 stp_dbg_get_coredump_timer_state(VOID) +{ + if (g_core_dump) + return g_core_dump->sm; + return -1; +} + +INT32 stp_dbg_set_fw_info(PUINT8 issue_info, UINT32 len, ENUM_STP_FW_ISSUE_TYPE issue_type) +{ + ENUM_ASSERT_INFO_PARSER_TYPE type_index; + PUINT8 tempbuf = NULL; + UINT32 i = 0; + INT32 iRet = 0; + + if (issue_info == NULL) { + STP_DBG_PR_ERR("null issue infor\n"); + return -1; + } + + if (g_stp_dbg_cpupcr->issue_type && + g_stp_dbg_cpupcr->issue_type != STP_HOST_TRIGGER_COLLECT_FTRACE) { + STP_DBG_PR_ERR("assert information has been set up\n"); + return -1; + } + + STP_DBG_PR_INFO("issue type(%d)\n", issue_type); + g_stp_dbg_cpupcr->issue_type = issue_type; + osal_memset(&g_stp_dbg_cpupcr->assert_info[0], 0, STP_ASSERT_INFO_SIZE); + + /*print patch version when assert happened */ + STP_DBG_PR_INFO("[consys patch]patch version:%s\n", g_stp_dbg_cpupcr->patchVer); + STP_DBG_PR_INFO("[consys patch]ALPS branch:%s\n", g_stp_dbg_cpupcr->branchVer); + + if ((issue_type == STP_FW_ASSERT_ISSUE) || + (issue_type == STP_HOST_TRIGGER_FW_ASSERT) || + (issue_type == STP_HOST_TRIGGER_ASSERT_TIMEOUT) || + (issue_type == STP_HOST_TRIGGER_COLLECT_FTRACE) || + (issue_type == STP_FW_ABT)) { + if ((issue_type == STP_FW_ASSERT_ISSUE) || (issue_type == STP_HOST_TRIGGER_FW_ASSERT) + || (issue_type == STP_FW_ABT)) { + tempbuf = osal_malloc(len + 1); + if (!tempbuf) + return -2; + + osal_memcpy(&tempbuf[0], issue_info, len); + + for (i = 0; i < len; i++) { + if (tempbuf[i] == '\0') + tempbuf[i] = '?'; + } + + tempbuf[len] = '\0'; + + for (type_index = STP_DBG_ASSERT_INFO; type_index < STP_DBG_PARSER_TYPE_MAX; + type_index++) { + iRet = stp_dbg_parser_assert_str(&tempbuf[0], type_index); + if (iRet) + STP_DBG_PR_INFO("fail to parse assert str %s, type = %d, ret = %d\n", + &tempbuf[0], type_index, iRet); + } + + } + if ((issue_type == STP_HOST_TRIGGER_FW_ASSERT) || + (issue_type == STP_HOST_TRIGGER_ASSERT_TIMEOUT) || + (issue_type == STP_HOST_TRIGGER_COLLECT_FTRACE)) { + g_stp_dbg_cpupcr->fwIsr = 0; + g_stp_dbg_cpupcr->fwRrq = 0; + + osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + switch (g_stp_dbg_cpupcr->host_assert_info.drv_type) { + case WMTDRV_TYPE_BT: + STP_DBG_PR_INFO("BT trigger assert\n"); + if (g_stp_dbg_cpupcr->host_assert_info.reason != 31) + g_stp_dbg_cpupcr->fwTaskId = STP_DBG_TASK_BT; /*BT firmware trigger assert */ + else { + /*BT stack trigger assert */ + g_stp_dbg_cpupcr->fwTaskId = STP_DBG_TASK_NATBT; + } + break; + case WMTDRV_TYPE_FM: + STP_DBG_PR_INFO("FM trigger assert\n"); + g_stp_dbg_cpupcr->fwTaskId = STP_DBG_TASK_FM; + break; + case WMTDRV_TYPE_GPS: + STP_DBG_PR_INFO("GPS trigger assert\n"); + g_stp_dbg_cpupcr->fwTaskId = STP_DBG_TASK_DRVGPS; + break; + case WMTDRV_TYPE_GPSL5: + STP_DBG_PR_INFO("GPSL5 trigger assert\n"); + g_stp_dbg_cpupcr->fwTaskId = STP_DBG_TASK_DRVGPS; + break; + case WMTDRV_TYPE_WIFI: + STP_DBG_PR_INFO("WIFI trigger assert\n"); + g_stp_dbg_cpupcr->fwTaskId = STP_DBG_TASK_DRVWIFI; + break; + case WMTDRV_TYPE_WMT: + STP_DBG_PR_INFO("WMT trigger assert\n"); + if (issue_type == STP_HOST_TRIGGER_ASSERT_TIMEOUT) + osal_memcpy(&g_stp_dbg_cpupcr->assert_info[0], issue_info, len); + /* 30: adb trigger assert */ + /* 43: process packet fail count > 10 */ + /* 44: rx timeout with pending data */ + /* 45: tx timeout with pending data */ + if (g_stp_dbg_cpupcr->host_assert_info.reason == 30 || + g_stp_dbg_cpupcr->host_assert_info.reason == 43 || + g_stp_dbg_cpupcr->host_assert_info.reason == 44 || + g_stp_dbg_cpupcr->host_assert_info.reason == 45) + g_stp_dbg_cpupcr->fwTaskId = STP_DBG_TASK_DRVSTP; + else + g_stp_dbg_cpupcr->fwTaskId = STP_DBG_TASK_WMT; + break; + default: + break; + } + g_stp_dbg_cpupcr->host_assert_info.assert_from_host = 0; + osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + + } else if (issue_type == STP_FW_ABT) { + INT32 copyLen = (len < STP_ASSERT_INFO_SIZE ? len : STP_ASSERT_INFO_SIZE - 1); + + osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + osal_memcpy(&g_stp_dbg_cpupcr->assert_info[0], tempbuf, copyLen); + g_stp_dbg_cpupcr->assert_info[copyLen] = '\0'; + osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + } + + if (tempbuf) + osal_free(tempbuf); + } else if (issue_type == STP_FW_NOACK_ISSUE) { + osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + osal_memcpy(&g_stp_dbg_cpupcr->assert_info[0], issue_info, len); + g_stp_dbg_cpupcr->fwTaskId = STP_DBG_TASK_DRVSTP; + g_stp_dbg_cpupcr->fwRrq = 0; + g_stp_dbg_cpupcr->fwIsr = 0; + osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + } else if (issue_type == STP_DBG_PROC_TEST) { + osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + osal_memcpy(&g_stp_dbg_cpupcr->assert_info[0], issue_info, len); + g_stp_dbg_cpupcr->fwTaskId = STP_DBG_TASK_WMT; + g_stp_dbg_cpupcr->fwRrq = 0; + g_stp_dbg_cpupcr->fwIsr = 0; + osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + } else if (issue_type == STP_FW_WARM_RST_ISSUE) { + osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + osal_memcpy(&g_stp_dbg_cpupcr->assert_info[0], issue_info, len); + g_stp_dbg_cpupcr->fwTaskId = STP_DBG_TASK_WMT; + g_stp_dbg_cpupcr->fwRrq = 0; + g_stp_dbg_cpupcr->fwIsr = 0; + osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + } else { + STP_DBG_PR_ERR("invalid issue type(%d)\n", issue_type); + return -3; + } + + return 0; +} + +INT32 stp_dbg_cpupcr_infor_format(PUINT8 buf, UINT32 max_len) +{ + UINT32 len = 0; + UINT32 i = 0; + + /* never retrun negative value */ + if (!g_stp_dbg_cpupcr || !buf) { + STP_DBG_PR_ERR("NULL pointer, g_stp_dbg_cpupcr:%p, buf:%p\n", + g_stp_dbg_cpupcr, buf); + return 0; + } + + /* format common information about issue */ + /* max_len can guarantee there's enough buffer for
section */ + len = osal_sprintf(buf, "
\n\t"); + len += osal_sprintf(buf + len, "\n\t\tMT%x\n\t\n\t", + g_stp_dbg_cpupcr->chipId); + len += osal_sprintf(buf + len, "\n\t\t"); + len += osal_sprintf(buf + len, "%s\n\t\t", g_stp_dbg_cpupcr->romVer); + if (!(osal_memcmp(g_stp_dbg_cpupcr->branchVer, "ALPS", strlen("ALPS")))) + len += osal_sprintf(buf + len, "Internal Dev\n\t\t", + g_stp_dbg_cpupcr->branchVer); + else + len += osal_sprintf(buf + len, "W%sMP\n\t\t", + g_stp_dbg_cpupcr->branchVer); + + len += osal_sprintf(buf + len, "%s\n\t\t", g_stp_dbg_cpupcr->patchVer); + + if (g_stp_dbg_cpupcr->wifiVer == 0) + len += osal_sprintf(buf + len, "NULL\n\t"); + else + len += osal_sprintf(buf + len, "0x%X.%X\n\t", + (UINT8)((g_stp_dbg_cpupcr->wifiVer & 0xFF00)>>8), + (UINT8)(g_stp_dbg_cpupcr->wifiVer & 0xFF)); + + len += osal_sprintf(buf + len, "\n\t"); + + /*format issue information: no ack, assert */ + len += osal_sprintf(buf + len, "\n\t\t\n\t\t\t"); + if ((g_stp_dbg_cpupcr->issue_type == STP_FW_NOACK_ISSUE) || + (g_stp_dbg_cpupcr->issue_type == STP_DBG_PROC_TEST) || + (g_stp_dbg_cpupcr->issue_type == STP_FW_WARM_RST_ISSUE) || + (g_stp_dbg_cpupcr->issue_type == STP_FW_ABT)) { + len += osal_sprintf(buf + len, "%s\n\t\t\n\t\t\n\t\t\t", + g_stp_dbg_cpupcr->assert_info); + len += osal_sprintf(buf + len, "NULL\n\t\t\n\t\n\t"); + len += osal_sprintf(buf + len, "\n\t\tNULL\n\t\t"); + len += osal_sprintf(buf + len, "NULL\n\t\t"); + len += osal_sprintf(buf + len, "\n\t\t\t%s\n\t\t\t", + stp_dbg_id_to_task(g_stp_dbg_cpupcr->fwTaskId)); + len += osal_sprintf(buf + len, "IRQ_0x%x\n\t\t\t", g_stp_dbg_cpupcr->fwRrq); + len += osal_sprintf(buf + len, "0x%x\n\t\t\t", g_stp_dbg_cpupcr->fwIsr); + len += osal_sprintf(buf + len, "NULL\n\t\t\t"); + len += osal_sprintf(buf + len, "NULL\n\t\t\t"); + len += osal_sprintf(buf + len, "%s\n\t\t\t", + g_stp_dbg_cpupcr->keyword); + } else if ((g_stp_dbg_cpupcr->issue_type == STP_FW_ASSERT_ISSUE) || + (g_stp_dbg_cpupcr->issue_type == STP_HOST_TRIGGER_FW_ASSERT) || + (g_stp_dbg_cpupcr->issue_type == STP_HOST_TRIGGER_ASSERT_TIMEOUT)) { + len += osal_sprintf(buf + len, "%s\n\t\t\n\t\t\n\t\t\t", + g_stp_dbg_cpupcr->assert_info); + len += osal_sprintf(buf + len, "%s\n\t\t\n\t\n\t", + g_stp_dbg_cpupcr->assert_type); + len += osal_sprintf(buf + len, "\n\t\tNULL\n\t\t"); + len += osal_sprintf(buf + len, "NULL\n\t\t"); + len += osal_sprintf(buf + len, "\n\t\t\t%s\n\t\t\t", + stp_dbg_id_to_task(g_stp_dbg_cpupcr->fwTaskId)); + if (g_stp_dbg_cpupcr->host_assert_info.reason == 32 || + g_stp_dbg_cpupcr->host_assert_info.reason == 33 || + g_stp_dbg_cpupcr->host_assert_info.reason == 34 || + g_stp_dbg_cpupcr->host_assert_info.reason == 35 || + g_stp_dbg_cpupcr->host_assert_info.reason == 36 || + g_stp_dbg_cpupcr->host_assert_info.reason == 37 || + g_stp_dbg_cpupcr->host_assert_info.reason == 38 || + g_stp_dbg_cpupcr->host_assert_info.reason == 39 || + g_stp_dbg_cpupcr->host_assert_info.reason == 40) { + /*handling wmt turn on/off bt cmd has ack but no evt issue */ + /*one of both the irqx and irs is nULL, then use task to find MOF */ + len += osal_sprintf(buf + len, "NULL\n\t\t\t"); + } else + len += osal_sprintf(buf + len, "IRQ_0x%x\n\t\t\t", + g_stp_dbg_cpupcr->fwRrq); + len += osal_sprintf(buf + len, "0x%x\n\t\t\t", g_stp_dbg_cpupcr->fwIsr); + + if (g_stp_dbg_cpupcr->issue_type == STP_FW_ASSERT_ISSUE) { + len += osal_sprintf(buf + len, "NULL\n\t\t\t"); + len += osal_sprintf(buf + len, "NULL\n\t\t\t"); + } + + if ((g_stp_dbg_cpupcr->issue_type == STP_HOST_TRIGGER_FW_ASSERT) || + (g_stp_dbg_cpupcr->issue_type == STP_HOST_TRIGGER_ASSERT_TIMEOUT)) { + len += osal_sprintf(buf + len, "%d\n\t\t\t", + g_stp_dbg_cpupcr->host_assert_info.drv_type); + len += osal_sprintf(buf + len, "%d\n\t\t\t", + g_stp_dbg_cpupcr->host_assert_info.reason); + } + + len += osal_sprintf(buf + len, "%s\n\t\t\t", + g_stp_dbg_cpupcr->keyword); + } else { + len += osal_sprintf(buf + len, "NULL\n\t\t\n\t\t\n\t\t\t"); + len += osal_sprintf(buf + len, "NULL\n\t\t\n\t\n\t"); + len += osal_sprintf(buf + len, "\n\t\tNULL\n\t\t"); + len += osal_sprintf(buf + len, "NULL\n\t\t"); + len += osal_sprintf(buf + len, "\n\t\t\t%s\n\t\t\t", + stp_dbg_id_to_task(g_stp_dbg_cpupcr->fwTaskId)); + len += osal_sprintf(buf + len, "NULL\n\t\t\t"); + len += osal_sprintf(buf + len, "NULL\n\t\t\t"); + len += osal_sprintf(buf + len, "NULL\n\t\t\t"); + len += osal_sprintf(buf + len, "NULL\n\t\t\t"); + len += osal_sprintf(buf + len, "%s\n\t\t\t", + g_stp_dbg_cpupcr->keyword); + } + + len += osal_sprintf(buf + len, ""); + STP_DBG_PR_INFO("stp-dbg:sub len1 for debug(%d)\n", len); + + if (!g_stp_dbg_cpupcr->count) + len += osal_sprintf(buf + len, "NULL"); + else { + for (i = 0; i < g_stp_dbg_cpupcr->count; i++) + len += osal_sprintf(buf + len, "%08x,", g_stp_dbg_cpupcr->buffer[i]); + } + STP_DBG_PR_INFO("stp-dbg:sub len2 for debug(%d)\n", len); + len += osal_sprintf(buf + len, "\n\t\t\t"); + len += osal_sprintf(buf + len, + "NULL\n\t\t\n\t\n
\n"); + + STP_DBG_PR_INFO("buffer len[%d]\n", len); + /* STP_DBG_PR_INFO("Format infor:\n%s\n",buf); */ + + osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + osal_memset(&g_stp_dbg_cpupcr->buffer[0], 0, STP_DBG_CPUPCR_NUM); + g_stp_dbg_cpupcr->count = 0; + g_stp_dbg_cpupcr->host_assert_info.reason = 0; + g_stp_dbg_cpupcr->host_assert_info.drv_type = 0; + g_stp_dbg_cpupcr->issue_type = STP_FW_ISSUE_TYPE_INVALID; + g_stp_dbg_cpupcr->keyword[0] = '\0'; + g_stp_dbg_cpupcr->fwRrq = 0; + g_stp_dbg_cpupcr->fwIsr = 0; + osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + + return len; +} + +PUINT8 stp_dbg_id_to_task(UINT32 id) +{ + ENUM_WMT_CHIP_TYPE chip_type; + PUINT8 task_id = NULL; + + chip_type = wmt_detect_get_chip_type(); + switch (chip_type) { + case WMT_CHIP_TYPE_COMBO: + task_id = stp_dbg_combo_id_to_task(id); + break; + case WMT_CHIP_TYPE_SOC: + task_id = stp_dbg_soc_id_to_task(id); + break; + default: + STP_DBG_PR_ERR("error chip type(%d)\n", chip_type); + } + + return task_id; +} + +VOID stp_dbg_reset(VOID) +{ + if (g_stp_dbg_cpupcr) { + osal_memset(g_stp_dbg_cpupcr->buffer, 0, osal_sizeof(g_stp_dbg_cpupcr->buffer)); + osal_memset(g_stp_dbg_cpupcr->sec_buffer, 0, osal_sizeof(g_stp_dbg_cpupcr->sec_buffer)); + osal_memset(g_stp_dbg_cpupcr->nsec_buffer, 0, osal_sizeof(g_stp_dbg_cpupcr->nsec_buffer)); + } + + if (g_stp_dbg_dmaregs) { + g_stp_dbg_dmaregs->count = 0; + osal_memset(g_stp_dbg_dmaregs->dmaIssue, 0, osal_sizeof(g_stp_dbg_dmaregs->dmaIssue)); + } +} + +MTKSTP_DBG_T *stp_dbg_init(PVOID btm_half) +{ + MTKSTP_DBG_T *stp_dbg = NULL; + + stp_dbg = kzalloc(sizeof(MTKSTP_DBG_T), GFP_KERNEL); + if (stp_dbg == NULL) + goto ERR_EXIT1; + if (IS_ERR(stp_dbg)) { + STP_DBG_PR_ERR("-ENOMEM\n"); + goto ERR_EXIT1; + } + + stp_dbg->logsys = vmalloc(sizeof(MTKSTP_LOG_SYS_T)); + if (stp_dbg->logsys == NULL) + goto ERR_EXIT2; + if (IS_ERR(stp_dbg->logsys)) { + STP_DBG_PR_ERR("-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)); + INIT_WORK(&(stp_dbg->logsys->dump_work), stp_dbg_dmp_print_work); + 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; + + g_core_dump = stp_dbg_core_dump_init(STP_CORE_DUMP_TIMEOUT); + if (!g_core_dump) { + STP_DBG_PR_ERR("-ENOMEM wcn_coer_dump_init fail!"); + goto ERR_EXIT2; + } + g_stp_dbg_cpupcr = stp_dbg_cpupcr_init(); + if (!g_stp_dbg_cpupcr) { + STP_DBG_PR_ERR("-ENOMEM stp_dbg_cpupcr_init fail!"); + goto ERR_EXIT2; + } + g_stp_dbg_dmaregs = stp_dbg_dmaregs_init(); + if (!g_stp_dbg_dmaregs) { + STP_DBG_PR_ERR("-ENOMEM stp_dbg_dmaregs_init fail!"); + goto ERR_EXIT2; + } + return stp_dbg; + +ERR_EXIT2: + stp_dbg_deinit(stp_dbg); + return NULL; + +ERR_EXIT1: + kfree(stp_dbg); + return NULL; +} + +INT32 stp_dbg_deinit(MTKSTP_DBG_T *stp_dbg) +{ + stp_dbg_core_dump_deinit(g_core_dump); + + stp_dbg_cpupcr_deinit(g_stp_dbg_cpupcr); + stp_dbg_dmaregs_deinit(g_stp_dbg_dmaregs); + /* unbind with netlink */ + stp_dbg_nl_deinit(); + + if (stp_dbg->logsys) + vfree(stp_dbg->logsys); + + kfree(stp_dbg); + + return 0; +} + +INT32 stp_dbg_start_coredump_timer(VOID) +{ + if (!g_core_dump) { + STP_DBG_PR_ERR("invalid pointer!\n"); + return -1; + } + + return osal_timer_modify(&g_core_dump->dmp_timer, STP_CORE_DUMP_TIMEOUT); +} + +INT32 stp_dbg_start_emi_dump(VOID) +{ + INT32 ret = 0; + + if (!g_core_dump) { + STP_DBG_PR_ERR("invalid pointer!\n"); + return -1; + } + + if (mtk_wcn_wlan_emi_mpu_set_protection) + (*mtk_wcn_wlan_emi_mpu_set_protection)(false); + /* Disable MCIF EMI protection */ + mtk_wcn_wmt_set_mcif_mpu_protection(false); + stp_dbg_set_coredump_timer_state(CORE_DUMP_DOING); + osal_timer_modify(&g_core_dump->dmp_emi_timer, STP_EMI_DUMP_TIMEOUT); + ret = stp_dbg_nl_send_data(EMICOREDUMP_CMD, sizeof(EMICOREDUMP_CMD)); + if (ret) + stp_dbg_stop_emi_dump(); + + return ret ? -1 : 0; +} + +INT32 stp_dbg_stop_emi_dump(VOID) +{ + if (!g_core_dump) { + STP_DBG_PR_ERR("invalid pointer!\n"); + return -1; + } + + if (mtk_wcn_stp_emi_dump_flag_get() == 1) { + STP_DBG_PR_ERR("stopping emi dump!\n"); + return -2; + } + + mtk_wcn_stp_emi_dump_flag_ctrl(1); + /* Enable MCIF EMI protection */ + mtk_wcn_wmt_set_mcif_mpu_protection(true); + if (mtk_wcn_wlan_emi_mpu_set_protection) + (*mtk_wcn_wlan_emi_mpu_set_protection)(true); + osal_timer_stop(&g_core_dump->dmp_emi_timer); + return 0; +} + +INT32 stp_dbg_nl_send_data(const PINT8 buf, INT32 len) +{ + PINT8 pdata = NULL; + INT32 ret = 0; + + pdata = kmalloc(len+5, GFP_KERNEL); + if (!pdata) + return -1; + pdata[0] = '['; + pdata[1] = 'M'; + pdata[2] = ']'; + osal_memcpy(&pdata[3], &len, 2); + osal_memcpy(&pdata[5], buf, len); + ret = stp_dbg_dump_send_retry_handler(pdata, len); + kfree(pdata); + return ret; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/stp_dbg_combo.c b/drivers/misc/mediatek/connectivity/common/common_main/linux/stp_dbg_combo.c new file mode 100644 index 0000000000000..796c98fce8d6f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/stp_dbg_combo.c @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include "stp_dbg.h" +#include "stp_dbg_combo.h" + +static _osal_inline_ INT32 stp_dbg_combo_put_dump_to_aee(VOID); +static _osal_inline_ INT32 stp_dbg_combo_put_dump_to_nl(VOID); + +static PUINT8 combo_task_str[STP_DBG_TASK_ID_MAX] = { + "Task_WMT", + "Task_BT", + "Task_Wifi", + "Task_Tst", + "Task_FM", + "Task_GPS", + "Task_FLP", + "Task_BAL", + "Task_Idle", + "Task_DrvStp", + "Task_DrvSdio", + "Task_NatBt", + "Task_DrvWifi", + "Task_GPS" +}; + +INT32 const combo_legacy_task_id_adapter[STP_DBG_TASK_ID_MAX] = { + STP_DBG_TASK_WMT, + STP_DBG_TASK_BT, + STP_DBG_TASK_WIFI, + STP_DBG_TASK_TST, + STP_DBG_TASK_FM, + STP_DBG_TASK_IDLE, + STP_DBG_TASK_WMT, + STP_DBG_TASK_WMT, + STP_DBG_TASK_WMT, + STP_DBG_TASK_DRVSTP, + STP_DBG_TASK_BUS, + STP_DBG_TASK_NATBT, + STP_DBG_TASK_DRVWIFI, + STP_DBG_TASK_DRVGPS +}; + +static _osal_inline_ INT32 stp_dbg_combo_put_dump_to_aee(VOID) +{ + static UINT8 buf[2048]; + static UINT8 tmp[2048]; + + UINT32 buf_len; + STP_PACKET_T *pkt = NULL; + STP_DBG_HDR_T *hdr = NULL; + INT32 remain = 0; + INT32 retry = 0; + INT32 ret = 0; + + 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) { + if (pkt->hdr.len <= 1500) { + tmp[pkt->hdr.len] = '\n'; + tmp[pkt->hdr.len + 1] = '\0'; + if (pkt->hdr.len < STP_DMP_SZ) + osal_memcpy(&tmp[0], pkt->raw, pkt->hdr.len); + else + osal_memcpy(&tmp[0], pkt->raw, STP_DMP_SZ); + ret = stp_dbg_aee_send(tmp, pkt->hdr.len, 0); + } else { + STP_DBG_PR_INFO("dump entry length is over long\n"); + osal_bug_on(0); + } + retry = 0; + } + retry = 0; + } else { + retry++; + osal_sleep_ms(20); + } + } while ((remain > 0) || (retry < 10)); + + return ret; +} + +static _osal_inline_ INT32 stp_dbg_combo_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 = NULL; + STP_DBG_HDR_T *hdr = NULL; + INT32 remain = 0; + INT32 index = 0; + INT32 retry = 0; + INT32 ret = 0; + INT32 len; + + index = 0; + tmp[index++] = '['; + tmp[index++] = 'M'; + tmp[index++] = ']'; + + do { + index = 3; + remain = stp_dbg_dmp_out_ex(&buf[0], &buf_len); + if (buf_len > 0) { + pkt = (STP_PACKET_T *) buf; + hdr = &pkt->hdr; + len = pkt->hdr.len; + osal_memcpy(&tmp[index], &len, 2); + index += 2; + if (hdr->dbg_type == STP_DBG_FW_DMP) { + osal_memcpy(&tmp[index], pkt->raw, pkt->hdr.len); + + if (pkt->hdr.len <= 1500) { + tmp[index + pkt->hdr.len] = '\n'; + tmp[index + pkt->hdr.len + 1] = '\0'; + + /* pr_warn("\n%s\n+++\n", tmp); */ + ret = stp_dbg_dump_send_retry_handler((PINT8)&tmp, len); + if (ret) + break; + + /* schedule(); */ + } else { + STP_DBG_PR_INFO("dump entry length is over long\n"); + osal_bug_on(0); + } + retry = 0; + } + } else { + retry++; + osal_sleep_ms(100); + } + } while ((remain > 0) || (retry < 2)); + + return ret; +} + +INT32 stp_dbg_combo_core_dump(INT32 dump_sink) +{ + INT32 ret = 0; + + switch (dump_sink) { + case 0: + STP_DBG_PR_INFO("coredump is disabled!\n"); + break; + case 1: + ret = stp_dbg_combo_put_dump_to_aee(); + break; + case 2: + ret = stp_dbg_combo_put_dump_to_nl(); + break; + default: + ret = -1; + STP_DBG_PR_ERR("unknown sink %d\n", dump_sink); + } + + return ret; +} + +PUINT8 stp_dbg_combo_id_to_task(UINT32 id) +{ + UINT32 chip_id = mtk_wcn_wmt_chipid_query(); + UINT32 temp_id; + + if (id >= STP_DBG_TASK_ID_MAX) { + STP_DBG_PR_ERR("task id(%d) overflow(%d)\n", id, STP_DBG_TASK_ID_MAX); + return NULL; + } + + switch (chip_id) { + case 0x6632: + temp_id = id; + break; + default: + temp_id = combo_legacy_task_id_adapter[id]; + break; + } + + return combo_task_str[temp_id]; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/stp_dbg_soc.c b/drivers/misc/mediatek/connectivity/common/common_main/linux/stp_dbg_soc.c new file mode 100644 index 0000000000000..72dbda0e0f88f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/stp_dbg_soc.c @@ -0,0 +1,577 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include "stp_dbg.h" +#include "stp_dbg_soc.h" +#include "btm_core.h" +#include "stp_core.h" +#include "mtk_wcn_consys_hw.h" +#include "wmt_step.h" +#include "wmt_lib.h" +#include + +#define STP_DBG_PAGED_TRACE_SIZE (2048*sizeof(char)) +#define SUB_PKT_SIZE 1024 +#define EMI_SYNC_TIMEOUT 100 /* FW guarantee that MCU copy data time is ~20ms. We set 100ms for safety */ +#define IS_VISIBLE_CHAR(c) ((c) >= 32 && (c) <= 126) +#define DUMP_LOG_BYTES_PER_LINE (128) + +#define ROM_V2_PATCH "ROMv2" +#define ROM_V3_PATCH "ROMv3" +#define ROM_V4_PATCH "ROMv4" + +ENUM_STP_FW_ISSUE_TYPE issue_type; +UINT8 g_paged_trace_buffer[STP_DBG_PAGED_TRACE_SIZE] = { 0 }; +UINT32 g_paged_trace_len; +UINT8 g_paged_dump_buffer[STP_DBG_PAGED_DUMP_BUFFER_SIZE] = { 0 }; +UINT32 g_paged_dump_len; + +static PUINT8 soc_task_str[STP_DBG_TASK_ID_MAX] = { + "Task_WMT", + "Task_BT", + "Task_Wifi", + "Task_Tst", + "Task_FM", + "Task_GPS", + "Task_FLP", + "Task_BT2", + "Task_Idle", + "Task_DrvStp", + "Task_DrvBtif", + "Task_NatBt", + "Task_DrvWifi", + "Task_GPS" +}; + +INT32 const soc_gen_two_task_id_adapter[STP_DBG_TASK_ID_MAX] = { + STP_DBG_TASK_WMT, + STP_DBG_TASK_BT, + STP_DBG_TASK_WIFI, + STP_DBG_TASK_TST, + STP_DBG_TASK_FM, + STP_DBG_TASK_IDLE, + STP_DBG_TASK_WMT, + STP_DBG_TASK_WMT, + STP_DBG_TASK_WMT, + STP_DBG_TASK_DRVSTP, + STP_DBG_TASK_BUS, + STP_DBG_TASK_NATBT, + STP_DBG_TASK_DRVWIFI, + STP_DBG_TASK_DRVGPS +}; + +INT32 const soc_gen_three_task_id_adapter[STP_DBG_TASK_ID_MAX] = { + STP_DBG_TASK_WMT, + STP_DBG_TASK_BT, + STP_DBG_TASK_WIFI, + STP_DBG_TASK_TST, + STP_DBG_TASK_FM, + STP_DBG_TASK_GPS, + STP_DBG_TASK_FLP, + STP_DBG_TASK_IDLE, + STP_DBG_TASK_WMT, + STP_DBG_TASK_DRVSTP, + STP_DBG_TASK_BUS, + STP_DBG_TASK_NATBT, + STP_DBG_TASK_DRVWIFI, + STP_DBG_TASK_DRVGPS +}; + +static _osal_inline_ INT32 stp_dbg_soc_paged_dump(INT32 dump_sink); +static _osal_inline_ INT32 stp_dbg_soc_paged_trace(VOID); +static _osal_inline_ INT32 stp_dbg_soc_put_emi_dump_to_nl(PUINT8 data_buf, INT32 dump_len); +static _osal_inline_ VOID stp_dbg_soc_emi_dump_buffer(UINT8 *buffer, UINT32 len); + +static VOID stp_dbg_dump_log(PUINT8 buf, INT32 size) +{ + INT32 i = 0; + UINT8 line[DUMP_LOG_BYTES_PER_LINE + 1]; + + while (size--) { + if (IS_VISIBLE_CHAR(*buf)) + line[i] = *buf; + else + line[i] = '.'; + i++; + buf++; + + if (i >= DUMP_LOG_BYTES_PER_LINE || !size) { + line[i] = 0; + pr_info("page_trace: %s\n", line); + i = 0; + } + } +} + +static _osal_inline_ VOID stp_dbg_soc_emi_dump_buffer(UINT8 *buffer, UINT32 len) +{ + UINT32 i = 0; + + if (len > 16) + len = 16; + for (i = 0; i < len; i++) { + if (i % 16 == 0 && i != 0) + pr_cont("\n "); + + if (buffer[i] == ']' || buffer[i] == '[' || buffer[i] == ',') + pr_cont("%c", buffer[i]); + else + pr_cont("0x%02x ", buffer[i]); + } +} + +static _osal_inline_ INT32 stp_dbg_soc_put_emi_dump_to_nl(PUINT8 data_buf, INT32 dump_len) +{ + static UINT8 tmp[SUB_PKT_SIZE + NL_PKT_HEADER_LEN]; + INT32 remain = dump_len, index = 0; + INT32 ret = 0; + INT32 len; + INT32 offset = 0; + + if (dump_len > 0) { + index = 0; + tmp[index++] = '['; + tmp[index++] = 'M'; + tmp[index++] = ']'; + + do { + index = 3; + if (remain >= SUB_PKT_SIZE) + len = SUB_PKT_SIZE; + else + len = remain; + remain -= len; + + osal_memcpy(&tmp[index], &len, 2); + index += 2; + osal_memcpy(&tmp[index], data_buf + offset, len); + offset += len; + STP_DBG_PR_DBG("send %d remain %d\n", len, remain); + + ret = stp_dbg_dump_send_retry_handler((PINT8)&tmp, len); + if (ret) + break; + + /* schedule(); */ + } while (remain > 0); + } else + STP_DBG_PR_INFO("dump entry length is 0\n"); + + return ret; +} + +static _osal_inline_ UINT64 stp_dbg_soc_elapsed_time(UINT64 ts, ULONG nsec) +{ + UINT64 current_ts = 0; + ULONG current_nsec = 0; + + osal_get_local_time(¤t_ts, ¤t_nsec); + return (current_ts*1000 + current_nsec/1000) - (ts*1000 + nsec/1000); +} + +static _osal_inline_ INT32 stp_dbg_soc_paged_dump(INT32 dump_sink) +{ + INT32 ret = 0; + UINT32 counter = 0; + UINT32 dump_num = 0; + UINT32 packet_num = STP_PAGED_DUMP_TIME_LIMIT/100; + UINT32 page_counter = 0; + ENUM_CHIP_DUMP_STATE chip_state; + UINT32 dump_phy_addr = 0; + PUINT8 dump_vir_addr = NULL; + INT32 dump_len = 0; + P_CONSYS_EMI_ADDR_INFO p_ecsi; + UINT64 start_ts = 0; + ULONG start_nsec = 0; + UINT64 elapsed_time = 0; + INT32 abort = 0; +#if WMT_DBG_SUPPORT + static DEFINE_RATELIMIT_STATE(_rs, 10 * HZ, 1); +#endif + + g_paged_dump_len = 0; + p_ecsi = wmt_plat_get_emi_phy_add(); + osal_assert(p_ecsi); + if (p_ecsi == NULL) + return -1; + + issue_type = STP_FW_ASSERT_ISSUE; + if (chip_reset_only) { + STP_DBG_PR_WARN("is chip reset only\n"); + ret = -3; + return ret; + } + + if (dump_sink == 0) + return 0; + + /* handshake error handle: notify FW assert in abnormal case */ + if (p_ecsi->p_ecso->emi_apmem_ctrl_state == 0x0) { + mtk_wcn_force_trigger_assert_debug_pin(); + osal_sleep_ms(100); + } + + /*packet number depend on dump_num get from register:0xf0080044 ,support jade*/ + dump_num = wmt_plat_get_dump_info(p_ecsi->p_ecso->emi_apmem_ctrl_chip_page_dump_num); + if (dump_num != 0) { + packet_num = dump_num; + STP_DBG_PR_INFO("get consys dump num packet_num(%d)\n", packet_num); + } else { + dump_num = CORE_DUMP_NUM; + STP_DBG_PR_ERR("can not get consys dump num and default num is %d\n", CORE_DUMP_NUM); + } + + stp_dbg_dump_num(dump_num); + stp_dbg_start_coredump_timer(); + wmt_plat_set_host_dump_state(STP_HOST_DUMP_NOT_START); + page_counter = 0; + if (mtk_wcn_stp_get_wmt_trg_assert() == 0) + WMT_STEP_DO_ACTIONS_FUNC(STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT); + + while (1) { + /* assert flag 2 means mcu is ready to start coredump */ + if (wmt_plat_get_dump_info(p_ecsi->p_ecso->emi_apmem_ctrl_assert_flag) == 2) { + STP_DBG_PR_INFO("coredump handshake start\n"); + break; + } else if (stp_dbg_get_coredump_timer_state() == CORE_DUMP_TIMEOUT) + goto paged_dump_end; + osal_sleep_ms(1); + } + + do { + dump_phy_addr = 0; + dump_vir_addr = NULL; + dump_len = 0; + + counter++; + osal_get_local_time(&start_ts, &start_nsec); + while (1) { + elapsed_time = stp_dbg_soc_elapsed_time(start_ts, start_nsec); + chip_state = (ENUM_CHIP_DUMP_STATE)wmt_plat_get_dump_info( + p_ecsi->p_ecso->emi_apmem_ctrl_chip_sync_state); + if (chip_state == STP_CHIP_DUMP_PUT_DONE) { + STP_DBG_PR_DBG("chip put done\n"); + break; + } + STP_DBG_PR_DBG("waiting chip put done, chip_state: %d\n", chip_state); +#if WMT_DBG_SUPPORT + if (chip_state == 0 && __ratelimit(&_rs)) + stp_dbg_poll_cpupcr(5, 1, 1); +#endif + + if (elapsed_time > EMI_SYNC_TIMEOUT) { +#if !WMT_DBG_SUPPORT + STP_DBG_PR_ERR("Wait Timeout: %llu > %d\n", elapsed_time, EMI_SYNC_TIMEOUT); + /* Since customer's user/userdebug load get coredump via netlink(dump_sink==2). */ + /* For UX, if get coredump timeout, skip it and do chip reset ASAP. */ + if (dump_sink == 2) + abort = 1; +#endif + goto paged_dump_end; + } + osal_sleep_ms(1); + } + + dump_phy_addr = wmt_plat_get_dump_info( + p_ecsi->p_ecso->emi_apmem_ctrl_chip_sync_addr); + + if (!dump_phy_addr) { + STP_DBG_PR_ERR("get paged dump phy address fail\n"); + ret = -1; + break; + } + + dump_vir_addr = wmt_plat_get_emi_virt_add(dump_phy_addr - p_ecsi->emi_phy_addr); + if (!dump_vir_addr) { + STP_DBG_PR_ERR("get paged dump phy address fail\n"); + ret = -2; + break; + } + dump_len = wmt_plat_get_dump_info(p_ecsi->p_ecso->emi_apmem_ctrl_chip_sync_len); + STP_DBG_PR_DBG("dump_phy_ddr(%08x),dump_vir_add(0x%p),dump_len(%d)\n", + dump_phy_addr, dump_vir_addr, dump_len); + + /* dump_len should not be negative */ + if (dump_len < 0) + dump_len = 0; + + /*move dump info according to dump_addr & dump_len */ + osal_memcpy_fromio(&g_paged_dump_buffer[0], dump_vir_addr, dump_len); + + if (dump_len <= 32 * 1024) { + STP_DBG_PR_DBG("coredump mode: %d!\n", dump_sink); + switch (dump_sink) { + case 1: + ret = stp_dbg_aee_send(&g_paged_dump_buffer[0], dump_len, 0); + if (ret == 0) + STP_DBG_PR_DBG("aee send ok!\n"); + else if (ret == 1) + STP_DBG_PR_DBG("aee send fisish!\n"); + else if (ret == -1) { + STP_DBG_PR_ERR("aee send timeout!\n"); + abort = 1; + goto paged_dump_end; + } else + STP_DBG_PR_ERR("aee send error!\n"); + break; + case 2: + ret = stp_dbg_soc_put_emi_dump_to_nl(&g_paged_dump_buffer[0], dump_len); + if (ret == 0) + STP_DBG_PR_DBG("dump send ok!\n"); + else if (ret == 1) { + STP_DBG_PR_ERR("dump send timeout!\n"); + abort = 1; + goto paged_dump_end; + } else + STP_DBG_PR_ERR("dump send error!\n"); + break; + default: + STP_DBG_PR_ERR("unknown sink %d\n", dump_sink); + return -1; + } + } else + STP_DBG_PR_ERR("dump len is over than 32K(%d)\n", dump_len); + + g_paged_dump_len += dump_len; + wmt_plat_update_host_sync_num(); + wmt_plat_set_host_dump_state(STP_HOST_DUMP_GET_DONE); + + STP_DBG_PR_DBG("host sync num(%d),chip sync num(%d)\n", + wmt_plat_get_dump_info(p_ecsi->p_ecso->emi_apmem_ctrl_host_sync_num), + wmt_plat_get_dump_info(p_ecsi->p_ecso->emi_apmem_ctrl_chip_sync_num)); + page_counter++; + STP_DBG_PR_DBG("++ paged dump counter(%d) ++\n", page_counter); + /* dump 1st 512 bytes data to kernel log for fw requirement */ + if (page_counter == 1) + stp_dbg_dump_log(&g_paged_dump_buffer[0], dump_len < 512 ? dump_len : 512); + + osal_get_local_time(&start_ts, &start_nsec); + while (1) { + elapsed_time = stp_dbg_soc_elapsed_time(start_ts, start_nsec); + chip_state = (ENUM_CHIP_DUMP_STATE)wmt_plat_get_dump_info( + p_ecsi->p_ecso->emi_apmem_ctrl_chip_sync_state); + if (chip_state == STP_CHIP_DUMP_END) { + STP_DBG_PR_DBG("chip put end\n"); + break; + } + STP_DBG_PR_DBG("waiting chip put end, chip_state: %d\n", chip_state); + if (elapsed_time > EMI_SYNC_TIMEOUT) { +#if !WMT_DBG_SUPPORT + STP_DBG_PR_ERR("Wait Timeout: %llu > %d\n", elapsed_time, EMI_SYNC_TIMEOUT); + /* Since customer's user/userdebug load get coredump via netlink(dump_sink==2). */ + /* For UX, if wait sync state timeout, skip it and do chip reset ASAP. */ + if (dump_sink == 2) + abort = 1; +#endif + goto paged_dump_end; + } + osal_sleep_ms(1); + } + +paged_dump_end: + wmt_plat_set_host_dump_state(STP_HOST_DUMP_NOT_START); + STP_DBG_PR_INFO("++ counter(%d) packet_num(%d) page_counter(%d) g_paged_dump_len(%d) fw_state(%d)++\n", + counter, packet_num, page_counter, g_paged_dump_len, + wmt_plat_get_dump_info(p_ecsi->p_ecso->emi_apmem_ctrl_state)); + if (wmt_plat_get_dump_info(p_ecsi->p_ecso->emi_apmem_ctrl_chip_paded_dump_end) || + (wmt_plat_get_dump_info(p_ecsi->p_ecso->emi_apmem_ctrl_state) == 0x8)) { + if (stp_dbg_get_coredump_timer_state() == CORE_DUMP_DOING) { + STP_DBG_PR_INFO("paged dump end by emi flag\n"); + if (dump_sink == 1) + stp_dbg_aee_send(FAKECOREDUMPEND, osal_sizeof(FAKECOREDUMPEND), 0); + else if (dump_sink == 2) + stp_dbg_nl_send_data(FAKECOREDUMPEND, osal_sizeof(FAKECOREDUMPEND)); + } else + STP_DBG_PR_INFO("paged dump end\n"); + ret = 0; + break; + } else if (abort || stp_dbg_get_coredump_timer_state() == CORE_DUMP_TIMEOUT) { + STP_DBG_PR_ERR("paged dump fail, generate fake coredump message\n"); + stp_dbg_set_coredump_timer_state(CORE_DUMP_DOING); + if (dump_sink == 1) + stp_dbg_aee_send(FAKECOREDUMPEND, osal_sizeof(FAKECOREDUMPEND), 0); + else if (dump_sink == 2) + stp_dbg_nl_send_data(FAKECOREDUMPEND, osal_sizeof(FAKECOREDUMPEND)); + stp_dbg_set_coredump_timer_state(CORE_DUMP_TIMEOUT); + stp_dbg_poll_cpupcr(5, 5, 0); + stp_dbg_poll_dmaregs(5, 1); + ret = -1; + break; + } + } while (1); + + return ret; +} + +static _osal_inline_ INT32 stp_dbg_soc_paged_trace(VOID) +{ + INT32 ret = 0; + UINT32 ctrl_val = 0; + UINT32 loop_cnt1 = 0; + UINT32 buffer_start = 0; + UINT32 buffer_idx = 0; + PUINT8 dump_vir_addr = NULL; + P_CONSYS_EMI_ADDR_INFO p_ecsi; + INT32 dump_len = 0; + + p_ecsi = wmt_plat_get_emi_phy_add(); + if (p_ecsi == NULL) { + STP_DBG_PR_ERR("get EMI info failed.\n"); + return -1; + } + + do { + ctrl_val = 0; + loop_cnt1 = 0; + buffer_start = 0; + buffer_idx = 0; + dump_vir_addr = NULL; + + while (loop_cnt1 < 10) { + ctrl_val = wmt_plat_get_dump_info(p_ecsi->p_ecso->emi_apmem_ctrl_state); + if (ctrl_val == 0x8) + break; + osal_sleep_ms(10); + loop_cnt1++; + } + if (loop_cnt1 >= 10) { + STP_DBG_PR_ERR("polling CTRL STATE fail\n"); + ret = -1; + break; + } + + buffer_start = wmt_plat_get_dump_info(p_ecsi->p_ecso->emi_apmem_ctrl_chip_print_buff_start); + buffer_idx = wmt_plat_get_dump_info(p_ecsi->p_ecso->emi_apmem_ctrl_chip_print_buff_idx); + g_paged_trace_len = buffer_idx; + STP_DBG_PR_INFO("paged trace buffer addr(%08x),buffer_len(%d)\n", buffer_start, + buffer_idx); + dump_vir_addr = wmt_plat_get_emi_virt_add(buffer_start - p_ecsi->emi_phy_addr); + if (!dump_vir_addr) { + STP_DBG_PR_ERR("get vir dump address fail\n"); + ret = -2; + break; + } + osal_memcpy_fromio(&g_paged_trace_buffer[0], dump_vir_addr, + buffer_idx < STP_DBG_PAGED_TRACE_SIZE ? buffer_idx : STP_DBG_PAGED_TRACE_SIZE); + /*moving paged trace according to buffer_start & buffer_len */ + + dump_len = + buffer_idx < STP_DBG_PAGED_TRACE_SIZE ? buffer_idx : STP_DBG_PAGED_TRACE_SIZE; + pr_info("-- paged trace ascii output --"); + stp_dbg_dump_log(&g_paged_trace_buffer[0], dump_len); + ret = 0; + } while (0); + + return ret; +} + +INT32 stp_dbg_soc_core_dump(INT32 dump_sink) +{ + INT32 ret = 0; + + if (dump_sink == 0 || chip_reset_only == 1) { + if (chip_reset_only) { + STP_DBG_PR_INFO("Chip reset only\n"); + chip_reset_only = 0; + } + mtk_wcn_stp_ctx_restore(); + } else if (dump_sink == 1 || dump_sink == 2) { + stp_dbg_soc_paged_dump(dump_sink); + ret = stp_dbg_soc_paged_trace(); + if (ret) + STP_DBG_PR_ERR("stp_dbg_soc_paged_trace fail: %d!\n", ret); + if (stp_dbg_start_emi_dump() < 0) + mtk_wcn_stp_ctx_restore(); + } + + return ret; +} + +PUINT8 stp_dbg_soc_id_to_task(UINT32 id) +{ + P_WMT_PATCH_INFO p_patch_info; + PUINT8 patch_name = NULL; + UINT32 temp_id; + + if (id >= STP_DBG_TASK_ID_MAX) { + STP_DBG_PR_ERR("task id(%d) overflow(%d)\n", id, STP_DBG_TASK_ID_MAX); + return NULL; + } + + p_patch_info = wmt_lib_get_patch_info(); + if (p_patch_info) + patch_name = p_patch_info->patchName; + + if (patch_name == NULL) { + STP_DBG_PR_ERR("patch_name is null\n"); + return NULL; + } + + if (osal_strncmp(patch_name, ROM_V2_PATCH, strlen(ROM_V2_PATCH)) == 0) { + temp_id = soc_gen_two_task_id_adapter[id]; + STP_DBG_PR_INFO("id = %d, gen two task_id = %d\n", id, temp_id); + } else if (osal_strncmp(patch_name, ROM_V3_PATCH, strlen(ROM_V3_PATCH)) == 0) { + temp_id = soc_gen_three_task_id_adapter[id]; + STP_DBG_PR_INFO("id = %d, gen three task_id = %d\n", id, temp_id); + } else if (osal_strncmp(patch_name, ROM_V4_PATCH, strlen(ROM_V4_PATCH)) == 0) { + temp_id = soc_gen_three_task_id_adapter[id]; + STP_DBG_PR_INFO("id = %d, gen three (ROMv4) task_id = %d\n", id, temp_id); + } else { + temp_id = id; + STP_DBG_PR_INFO("id = %d, CONNAC project task_id = %d\n", id, temp_id); + } + + return soc_task_str[temp_id]; +} + +UINT32 stp_dbg_soc_read_debug_crs(ENUM_CONNSYS_DEBUG_CR cr) +{ +#define CONSYS_REG_READ(addr) (*((volatile UINT32 *)(addr))) +#ifdef CONFIG_OF /*use DT */ + P_CONSYS_EMI_ADDR_INFO emi_phy_addr; + UINT32 chip_id = 0; + + chip_id = wmt_plat_get_soc_chipid(); + emi_phy_addr = mtk_wcn_consys_soc_get_emi_phy_add(); + + if (cr == CONNSYS_EMI_REMAP) { + if (emi_phy_addr != NULL && emi_phy_addr->emi_remap_offset) + return CONSYS_REG_READ(conn_reg.topckgen_base + + emi_phy_addr->emi_remap_offset); + else + STP_DBG_PR_INFO("EMI remap has no value\n"); + } + + if (chip_id == 0x6765 || chip_id == 0x3967 || chip_id == 0x6761 + || chip_id == 0x6779 || chip_id == 0x6768 || chip_id == 0x6785 + || chip_id == 0x6873 || chip_id == 0x8168 || chip_id == 0x6853 + || chip_id == 0x6833) + return 0; + + if (conn_reg.mcu_base) { + switch (cr) { + case CONNSYS_CPU_CLK: + return CONSYS_REG_READ(conn_reg.mcu_base + CONSYS_CPU_CLK_STATUS_OFFSET); + case CONNSYS_BUS_CLK: + return CONSYS_REG_READ(conn_reg.mcu_base + CONSYS_BUS_CLK_STATUS_OFFSET); + case CONNSYS_DEBUG_CR1: + return CONSYS_REG_READ(conn_reg.mcu_base + CONSYS_DBG_CR1_OFFSET); + case CONNSYS_DEBUG_CR2: + return CONSYS_REG_READ(conn_reg.mcu_base + CONSYS_DBG_CR2_OFFSET); + default: + return 0; + } + } +#endif + return -1; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/stp_sdio.c b/drivers/misc/mediatek/connectivity/common/common_main/linux/stp_sdio.c new file mode 100644 index 0000000000000..6c663ed5cb374 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/stp_sdio.c @@ -0,0 +1,3584 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/*! \file "stp_sdio.c" + * \brief + * + * detailed description +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +#define STP_SDIO_TXPERFDBG 1 /* depends on STP_SDIO_DBG_SUPPORT */ +#define STP_SDIO_OWNBACKDBG 1 /* depends on STP_SDIO_DBG_SUPPORT */ +#define STP_SDIO_NEW_IRQ_HANDLER 1 + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "osal.h" +#include "stp_exp.h" +#include "hif_sdio.h" +#include "stp_sdio.h" +#include "stp_dbg.h" +#include "wmt_lib.h" +#include "wmt_exp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[STP SDIO]" + +#define STPSDIO_LOG_LOUD 5 +#define STPSDIO_LOG_DBG 4 +#define STPSDIO_LOG_HINT 3 +#define STPSDIO_LOG_INFO 2 +#define STPSDIO_LOG_WARN 1 +#define STPSDIO_LOG_ERR 0 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +#if STP_SDIO_DBG_SUPPORT && STP_SDIO_RXDBG +#define STP_SDIO_RXDBG_COUNT (0x10UL) +#define STP_SDIO_RXDBG_COUNT_MASK (STP_SDIO_RXDBG_COUNT - 1) +struct stp_sdio_rxdbg { + UINT32 ts; + UINT32 bus_rxlen; + UINT32 chisr_rxlen; + UINT8 rx_pkt_buf[STP_SDIO_RX_BUF_SIZE]; +}; +#endif + +#if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXDBG +#define STP_SDIO_TXDBG_COUNT (0x10UL) +#define STP_SDIO_TXDBG_COUNT_MASK (STP_SDIO_TXDBG_COUNT - 1) +struct stp_sdio_txdbg { + UINT32 ts; + UINT32 bus_txlen; + UINT64 l_sec; + ULONG l_nsec; + UINT32 four_byte_align_len; + UINT8 tx_pkt_buf[STP_SDIO_TX_ENTRY_SIZE]; +}; +#define STP_SDIO_TXDBG_MAX_SIZE (0x20) +#endif +OSAL_SLEEPABLE_LOCK fake_coredump_lock; +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static INT32 stp_sdio_func0_reg_rw(INT32 direction, UINT32 offset, UINT32 value); +static INT32 stp_sdio_func_reg_rw(INT32 direction, UINT32 offset, UINT32 value); + +static INT32 stp_sdio_irq(const MTK_WCN_HIF_SDIO_CLTCTX clt_ctx); +static INT32 stp_sdio_probe(const MTK_WCN_HIF_SDIO_CLTCTX clt_ctx, + const MTK_WCN_HIF_SDIO_FUNCINFO *sdio_func_infop); +static INT32 stp_sdio_remove(const MTK_WCN_HIF_SDIO_CLTCTX clt_ctx); + +static VOID stp_sdio_rx_wkr(struct work_struct *work); +static VOID stp_sdio_tx_wkr(struct work_struct *work); +#if STP_SDIO_OWN_THREAD +static INT32 stp_sdio_wait_for_msg(PVOID pvData); +static VOID stp_sdio_tx_rx_handling(PVOID pData); +#endif +static _osal_inline_ INT32 stp_sdio_host_info_deinit(PPUINT8 ppTxBuf, PPUINT8 ppRxBuf); +static _osal_inline_ INT32 stp_sdio_host_info_init(PPUINT8 ppTxBuf, PPUINT8 ppRxBuf); +static _osal_inline_ INT32 stp_sdio_host_info_op(INT32 opId); +static _osal_inline_ SDIO_PS_OP stp_sdio_get_own_state(VOID); +static _osal_inline_ INT32 stp_sdio_do_own_set(MTK_WCN_STP_SDIO_HIF_INFO *p_info); +static _osal_inline_ INT32 stp_sdio_do_own_clr(INT32 wait); +static _osal_inline_ VOID stp_sdio_check_tx_sanity(const MTK_WCN_STP_SDIO_HIF_INFO *p_info, const UINT32 id); +static _osal_inline_ VOID stp_sdio_tx_wkr_comp(MTK_WCN_STP_SDIO_HIF_INFO * const p_info); +static _osal_inline_ INT32 stp_sdio_ownback_poll(const MTK_WCN_HIF_SDIO_CLTCTX clt_ctx, UINT32 retry, + UINT32 delay_us); +static _osal_inline_ VOID stp_sdio_txperf_dump(VOID); +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/* Supported SDIO device table */ +static const MTK_WCN_HIF_SDIO_FUNCINFO mtk_stp_sdio_id_tbl[] = { + /* MT6618 *//* Not an SDIO standard class device */ + {MTK_WCN_HIF_SDIO_FUNC(0x037A, 0x018B, 1, STP_SDIO_BLK_SIZE)}, + {MTK_WCN_HIF_SDIO_FUNC(0x037A, 0x018C, 1, STP_SDIO_BLK_SIZE)}, /* 2-function */ + + /* MT6619 *//* Not an SDIO standard class device */ + {MTK_WCN_HIF_SDIO_FUNC(0x037A, 0x6619, 1, STP_SDIO_BLK_SIZE)}, + + /* MT6620 *//* Not an SDIO standard class device */ + {MTK_WCN_HIF_SDIO_FUNC(0x037A, 0x020B, 1, STP_SDIO_BLK_SIZE)}, + {MTK_WCN_HIF_SDIO_FUNC(0x037A, 0x020C, 1, STP_SDIO_BLK_SIZE)}, /* 2-function */ + + /* MT6628 *//* Not an SDIO standard class device */ + {MTK_WCN_HIF_SDIO_FUNC(0x037A, 0x6628, 2, STP_SDIO_BLK_SIZE)}, /* 2-function */ + + /* MT6630 *//* Not an SDIO standard class device */ + {MTK_WCN_HIF_SDIO_FUNC(0x037A, 0x6630, 2, STP_SDIO_BLK_SIZE)}, /* 2-function */ + + /* MT6632 *//* Not an SDIO standard class device */ + {MTK_WCN_HIF_SDIO_FUNC(0x037A, 0x6632, 2, STP_SDIO_BLK_SIZE)}, /* 2-function */ + { /* end: all zeroes */ }, +}; + +wait_queue_head_t g_ownback_done; +INT32 is_wait_ownback; +/* static void (*cmb_bgf_eirq_cb)(void) = NULL; */ + +/* STP SDIO client information for hif sdio driver registration */ +const MTK_WCN_HIF_SDIO_CLTINFO g_stp_sdio_cltinfo = { + .func_tbl = mtk_stp_sdio_id_tbl, + .func_tbl_size = (sizeof(mtk_stp_sdio_id_tbl) / sizeof(MTK_WCN_HIF_SDIO_FUNCINFO) - 1), + .hif_clt_irq = stp_sdio_irq, + .hif_clt_probe = stp_sdio_probe, + .hif_clt_remove = stp_sdio_remove, +}; + +/* STP SDIO host array for multiple hosts maintenance */ +MTK_WCN_STP_SDIO_HIF_INFO g_stp_sdio_host_info; /*[STP_SDIO_HOST_COUNT]; */ +/* STP SDIO host information pointer (for stp if_tx() function) */ +MTK_WCN_STP_SDIO_HIF_INFO *const gp_info = &g_stp_sdio_host_info; + +/* STP-SDIO probe count (not support multiple probe and hosts) */ +UINT32 g_stp_sdio_host_count; + +#if STP_SDIO_DBG_SUPPORT && STP_SDIO_RXDBG +#define STP_SDIO_RXDBG_PROCNAME "driver/stp_sdio_rxdbg" +static struct proc_dir_entry *gStpSdioRxDbgEntry; +static INT32 stp_sdio_rxdbg_cnt; +static struct stp_sdio_rxdbg stp_sdio_rxdbg_buffer[STP_SDIO_RXDBG_COUNT]; +static struct timeval old = {0}; +#define TX_NO_ACK_TIMEOUT_ASSERT 5 /* tx no ack timeout assert, unit:second*/ + +static ssize_t stp_sdio_rxdbg_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos); +static ssize_t stp_sdio_rxdbg_write(struct file *filp, const char __user *buf, size_t count, + loff_t *f_pos); +static const struct file_operations stp_sdio_rxdbg_fops = { + .read = stp_sdio_rxdbg_read, + .write = stp_sdio_rxdbg_write, +}; + +#endif + +#if STP_SDIO_DBG_SUPPORT && STP_SDIO_OWNBACKDBG +#define STP_SDIO_OWNDBG_PROCNAME "driver/stp_sdio_own" +static struct proc_dir_entry *gStpSdioOwnEntry; +static ssize_t stp_sdio_own_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos); +static ssize_t stp_sdio_own_write(struct file *filp, const char __user *buf, size_t count, + loff_t *f_pos); +static const struct file_operations stp_sdio_own_fops = { + .read = stp_sdio_own_read, + .write = stp_sdio_own_write, +}; + +#endif + +#if STP_SDIO_DBG_SUPPORT && (STP_SDIO_TXDBG || STP_SDIO_TXPERFDBG) +#define STP_SDIO_TXDBG_PROCNAME "driver/stp_sdio_txdbg" +static struct proc_dir_entry *gStpSdioTxDbgEntry; + +static ssize_t stp_sdio_txdbg_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos); +static ssize_t stp_sdio_txdbg_write(struct file *filp, const char __user *buf, size_t count, + loff_t *f_pos); +static const struct file_operations stp_sdio_txdbg_fops = { + .read = stp_sdio_txdbg_read, + .write = stp_sdio_txdbg_write, +}; + +#if STP_SDIO_TXDBG +static INT32 stp_sdio_txdbg_cnt; +static struct stp_sdio_txdbg stp_sdio_txdbg_buffer[STP_SDIO_TXDBG_COUNT]; +#endif + +#if STP_SDIO_TXPERFDBG +/* a record for tx worker loop counter */ +static UINT32 stp_sdio_txperf_worker_cnt; + +/* a record for left fifo size in hw when tx wait */ +static UINT32 stp_sdio_txperf_fifo_left; +/* a record for data length when tx wait */ +static UINT32 stp_sdio_txperf_to_send; +/* a record for tx wait fifo limit counter */ +static UINT32 stp_sdio_txperf_fifo_lmt_cnt; + +/* a record for left txed pkt number in tx worker */ +static UINT32 stp_sdio_txperf_txed_pkt_num; +/* a record for tx wait pkt_num limit counter */ +static UINT32 stp_sdio_txperf_pkt_num_lmt_cnt; +#endif +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("MediaTek Inc WCN_SE_CS3"); +MODULE_DESCRIPTION("Read-Copy Update tracing for hierarchical implementation"); + +INT32 gStpSdioDbgLvl = STPSDIO_LOG_INFO; +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define STPSDIO_PR_LOUD(fmt, arg...) \ +do { \ + if (gStpSdioDbgLvl >= STPSDIO_LOG_LOUD) \ + pr_info(DFT_TAG "[L]%s:" fmt, __func__, ##arg); \ +} while (0) + +#define STPSDIO_PR_DBG(fmt, arg...) \ +do { \ + if (gStpSdioDbgLvl >= STPSDIO_LOG_DBG) \ + pr_info(DFT_TAG "[D]%s:" fmt, __func__, ##arg); \ +} while (0) + +#define STPSDIO_PR_HINT(fmt, arg...) \ +do { \ + if (gStpSdioDbgLvl >= STPSDIO_LOG_HINT) \ + pr_info(DFT_TAG "[I]%s:" fmt, __func__, ##arg); \ +} while (0) + +#define STPSDIO_PR_INFO(fmt, arg...) \ +do { \ + if (gStpSdioDbgLvl >= STPSDIO_LOG_INFO) \ + pr_info(DFT_TAG "[I]%s:" fmt, __func__, ##arg); \ +} while (0) + +#define STPSDIO_PR_WARN(fmt, arg...) \ +do { \ + if (gStpSdioDbgLvl >= STPSDIO_LOG_WARN) \ + pr_warn(DFT_TAG "[W]%s:" fmt, __func__, ##arg); \ +} while (0) + +#define STPSDIO_PR_ERR(fmt, arg...) \ +do { \ + if (gStpSdioDbgLvl >= STPSDIO_LOG_ERR) \ + pr_err(DFT_TAG "[E]%s(%d):" fmt, __func__, __LINE__, ##arg); \ +} while (0) + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT +INT32 stp_sdio_deep_sleep_flag_set(MTK_WCN_BOOL flag) +{ + return mtk_wcn_hif_sdio_deep_sleep_flag_set(flag); +} +#endif + +VOID stp_sdio_retry_flag_ctrl(INT32 flag) +{ + gp_info->retry_enable_flag = flag == 0 ? 0 : 1; +} + +INT32 stp_sdio_retry_flag_get(VOID) +{ + return gp_info->retry_enable_flag; +} + +static _osal_inline_ INT32 stp_sdio_host_info_op(INT32 opId) +{ + INT32 iRet = 0; +#if KMALLOC_UPDATE + static PUINT8 p_tx_buffer; + static PUINT8 p_rx_buffer; + + if (p_tx_buffer == NULL) { + p_tx_buffer = kmalloc(STP_SDIO_TX_BUF_CNT * STP_SDIO_TX_ENTRY_SIZE, GFP_ATOMIC); + if (p_tx_buffer == NULL) { + STPSDIO_PR_ERR + ("memory allocate for g_stp_sdio_host_info.pkt_buf.tx_buf fail!\n"); + iRet = -1; + } else { + STPSDIO_PR_DBG + ("memory allocate for g_stp_sdio_host_info.pkt_buf.tx_buf succeed!\n"); + iRet = 0; + } + } else { + STPSDIO_PR_DBG + ("memory already allocated for g_stp_sdio_host_info.pkt_buf.tx_buf!\n"); + iRet = 0; + } + if (p_rx_buffer == NULL) { + p_rx_buffer = kmalloc(STP_SDIO_RX_BUF_SIZE, GFP_ATOMIC); + if (p_rx_buffer == NULL) { + STPSDIO_PR_ERR + ("memory allocate for g_stp_sdio_host_info.pkt_buf.rx_buf fail!\n"); + iRet = -1; + } else { + STPSDIO_PR_DBG + ("memory allocate for g_stp_sdio_host_info.pkt_buf.rx_buf succeed!\n"); + iRet = 0; + } + } else { + STPSDIO_PR_DBG + ("memory already allocated for g_stp_sdio_host_info.pkt_buf.rx_buf!\n"); + iRet = 0; + } +#endif /* KMALLOC_UPDATE */ + + if (iRet == 0 && opId == 0) + iRet = stp_sdio_host_info_deinit(&p_tx_buffer, &p_rx_buffer); + else if (iRet == 0) + iRet = stp_sdio_host_info_init(&p_tx_buffer, &p_rx_buffer); + else + STPSDIO_PR_ERR("iRet (%d)!\n", iRet); + + return iRet; +} + +static _osal_inline_ INT32 stp_sdio_host_info_init(PPUINT8 ppTxBuf, PPUINT8 ppRxBuf) +{ + /* Init host count */ + memset(&g_stp_sdio_host_info, 0, sizeof(g_stp_sdio_host_info)); + +#if KMALLOC_UPDATE + g_stp_sdio_host_info.pkt_buf.tx_buf = *ppTxBuf; + g_stp_sdio_host_info.pkt_buf.rx_buf = *ppRxBuf; +#endif + + return 0; +} + +static _osal_inline_ INT32 stp_sdio_host_info_deinit(PPUINT8 ppTxBuf, PPUINT8 ppRxBuf) +{ +#if KMALLOC_UPDATE + if (*ppTxBuf != NULL) { + kfree(*ppTxBuf); + *ppTxBuf = NULL; + } + if (*ppRxBuf != NULL) { + kfree(*ppRxBuf); + *ppRxBuf = NULL; + } +#endif + + return 0; +} + +INT32 stp_sdio_issue_fake_coredump(UINT8 *str) +{ +#define MAX_STRING_LENGTH 140 + UINT8 AssertStr[4 + MAX_STRING_LENGTH + 1 + 2] = { 0 }; + UINT32 length = strlen(str) >= MAX_STRING_LENGTH ? MAX_STRING_LENGTH : strlen(str); + /*pack str into STP SDIO packet format */ + osal_lock_sleepable_lock(&fake_coredump_lock); + /*STP header */ + AssertStr[0] = 0x80; + AssertStr[1] = 0x50; + AssertStr[2] = (length + 1) & 0xff; + AssertStr[3] = 0x0; + /*STP content */ + memcpy(&AssertStr[4], str, length); + /*string end character */ + AssertStr[4 + length] = '\n'; + /*STP CRC */ + AssertStr[4 + length + 1] = 0x0; + AssertStr[4 + length + 2] = 0x0; + /*send to STP layer coredump content */ + mtk_wcn_stp_parser_data(&AssertStr[0], 4 + length + 1 + 2); + + /*send coredump end content */ + length = strlen("coredump end"); + AssertStr[0] = 0x80; + AssertStr[1] = 0x50; + AssertStr[2] = (length + 2) & 0xff; + AssertStr[3] = 0x0; + memcpy(&AssertStr[4], "coredump end", length); + /*string end character */ + AssertStr[4 + length] = '\r'; + AssertStr[4 + length + 1] = '\n'; + /*STP CRC */ + AssertStr[4 + length + 2] = 0x0; + AssertStr[4 + length + 3] = 0x0; + mtk_wcn_stp_parser_data(&AssertStr[0], 4 + length + 2 + 2); + osal_unlock_sleepable_lock(&fake_coredump_lock); + + STPSDIO_PR_ERR("trigger fake coredump with str:[%s] finished\n", str); + + return 0; +} + +/*! + * \brief + * + * \details + * + * \retval 0 success + * \retval !=0 fail + */ +static _osal_inline_ SDIO_PS_OP stp_sdio_get_own_state(VOID) +{ + SDIO_PS_OP ret = OWN_SET; + INT32 i_ret = 0; + UINT32 chlcpr_value = 0x0; + MTK_WCN_HIF_SDIO_CLTCTX clt_ctx; + + clt_ctx = gp_info->sdio_cltctx; + i_ret = stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, clt_ctx, CHLPCR, &chlcpr_value, + 0); + if (i_ret) { + ret = OWN_SET; + STPSDIO_PR_ERR("read CHLPCR fail(%d), return\n", ret); + return ret; + } + if ((chlcpr_value & C_FW_COM_DRV_OWN) == C_FW_COM_DRV_OWN) + ret = OWN_CLR; + else + ret = OWN_SET; + + return ret; +} + +static _osal_inline_ INT32 stp_sdio_do_own_set(MTK_WCN_STP_SDIO_HIF_INFO *p_info) +{ + UINT32 value = 0; + UINT32 iRet = 0; + + /* [COHEC_00006052] SW work-around solution: + * using CMD52 write instead of CMD53 write for CCIR, CHLPCR, CSDIOCSR + */ +#if COHEC_00006052 + value = (C_FW_OWN_REQ_SET >> 8); + iRet = stp_sdio_rw_retry(HIF_TYPE_WRITEB, STP_SDIO_RETRY_LIMIT, p_info->sdio_cltctx, + (UINT32)(CHLPCR + 0x01), &value, 0); +#else + value = C_FW_OWN_REQ_SET; + iRet = stp_sdio_rw_retry(HIF_TYPE_WRITEL, STP_SDIO_RETRY_LIMIT, p_info->sdio_cltctx, CHLPCR, &value, + 0); +#endif /* COHEC_00006052 */ + if (iRet) { + STPSDIO_PR_ERR("write CHLPCR, set firmware own! (sleeping) fail\n"); + } else { + iRet = stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, p_info->sdio_cltctx, CHLPCR, + &value, 0); + if (iRet) + STPSDIO_PR_ERR("get firmware own! (sleeping) fail iRet:%d\n", iRet); + else { + if (!(value & C_FW_COM_DRV_OWN)) { + STPSDIO_PR_DBG("set firmware own! (sleeping) ok\n"); + osal_ftrace_print("set F own okay, sleep_flag(%d), wakeup_flag(%d), awake_falg(%d)", + p_info->sleep_flag, p_info->wakeup_flag, p_info->awake_flag); + p_info->awake_flag = 0; + p_info->sleep_flag = 0; + osal_raise_signal(&p_info->isr_check_complete); + osal_ftrace_print("set F own okay and raise signal done"); + } else { + STPSDIO_PR_WARN("set firmware own fail!, set CLR BACK\n"); + osal_ftrace_print("set F own fail, set CLR BACK\n"); + /* if set firmware own not successful(possibly pending interrupts), + * indicate an own clear event + */ + /* [COHEC_00006052] SW work-around solution: + * using CMD52 write instead of CMD53 write for CCIR, CHLPCR, CSDIOCSR + */ +#if COHEC_00006052 + value = (C_FW_OWN_REQ_CLR >> 8); + iRet = stp_sdio_rw_retry(HIF_TYPE_WRITEB, STP_SDIO_RETRY_LIMIT, + p_info->sdio_cltctx, (UINT32)(CHLPCR + 0x01), &value, 0); +#else + value = C_FW_OWN_REQ_CLR; + iRet = stp_sdio_rw_retry(HIF_TYPE_WRITEL, STP_SDIO_RETRY_LIMIT, + p_info->sdio_cltctx, CHLPCR, &value, 0); +#endif /* COHEC_00006052 */ + } + } + } + + return 0; +} + +/*! + * \brief + * + * \details + * + * \retval 0 success + * \retval !=0 fail + */ +static _osal_inline_ INT32 stp_sdio_do_own_clr(INT32 wait) +{ +#define CLR_OWN_RETRY 50 + INT32 ret = -1; + UINT32 time_out; + INT32 retry; + UINT32 chlcpr_value = 0x0; + UINT32 write_value = 0x0; + UINT32 delay_us = 500; + MTK_WCN_HIF_SDIO_CLTCTX clt_ctx; + + clt_ctx = gp_info->sdio_cltctx; + retry = 40; + + /* <1> request firmware-own back */ + STPSDIO_PR_DBG("Do FW-Own back!(Wakeup)\n"); + if (wait) { + /* TODO:[FixMe][George] why use both polling & interrupt methods here??? */ + init_waitqueue_head(&g_ownback_done); + + is_wait_ownback = 1; + } +/* need to wait for the ownback completion */ +/* [COHEC_00006052] SW work-around solution: + * using CMD52 write instead of CMD53 write for CCIR, CHLPCR, CSDIOCSR + */ + while (retry-- > 0) { +#if COHEC_00006052 + write_value = (C_FW_OWN_REQ_CLR>>8); + ret = stp_sdio_rw_retry(HIF_TYPE_WRITEB, STP_SDIO_RETRY_LIMIT, clt_ctx, + (UINT32)(CHLPCR+0x1), &write_value, 0); +#else + write_value = C_FW_OWN_REQ_CLR; + ret = stp_sdio_rw_retry(HIF_TYPE_WRITEL, STP_SDIO_RETRY_LIMIT, clt_ctx, CHLPCR, + &write_value, 0); +#endif /* COHEC_00006052 */ + if (ret) { + STPSDIO_PR_ERR("request firmware own back fail(%d)\n", ret); + osal_dbg_assert_aee(" sdio_write ERROR", + "write CHLPCR by SDIO report error"); + if (retry == 0) + goto out; + } else + break; + } + retry = 1200;/*wait for 1200*500 = 600 000 us*/ + do { + ret = stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, clt_ctx, CHLPCR, + &chlcpr_value, 0); + if (ret) { + /* 4 <1.1> get CHISR Rx error handling */ + STPSDIO_PR_ERR("get CHLPCR information rx error!(%d)\n", ret); + goto out; + } + + if ((chlcpr_value & C_FW_COM_DRV_OWN) == C_FW_COM_DRV_OWN) { + /* 4 <2> handle ownership back interrupt */ + STPSDIO_PR_DBG("firmware ownback is polled!(%d)\n", + CLR_OWN_RETRY - retry); + /*osal_usleep_range(2000, 2000);*/ + break; + } + STPSDIO_PR_DBG("firmware ownback is no polled, wait for (%d us) and retry\n", delay_us); + osal_usleep_range(delay_us, 2*delay_us); + if (0 == (retry - 1)%40) + STPSDIO_PR_ERR("own back failed in %d us, something might goes wrong\n", + 40*delay_us); + + if (0 == (retry - 1)%200) { +#if COHEC_00006052 + write_value = (C_FW_OWN_REQ_CLR>>8); + ret = stp_sdio_rw_retry(HIF_TYPE_WRITEB, STP_SDIO_RETRY_LIMIT, clt_ctx, + (UINT32)(CHLPCR+0x1), &write_value, 0); +#else + write_value = C_FW_OWN_REQ_CLR; + ret = stp_sdio_rw_retry(HIF_TYPE_WRITEL, STP_SDIO_RETRY_LIMIT, clt_ctx, CHLPCR, + &write_value, 0); +#endif /* COHEC_00006052 */ + if (ret) + STPSDIO_PR_ERR("request firmware own back fail(%d)\n", ret); + STPSDIO_PR_ERR("own back failed in %d us, write again\n", 200*delay_us); + stp_dbg_poll_cpupcr(5, 1, 1); + } + } while (retry-- > 0); + if (wait) { + /* <2> wait own_back bit is set. */ + time_out = wait_event_timeout(g_ownback_done, + is_wait_ownback == 0, (1000 / (1000 / HZ))); + + if (time_out != 0) { + STPSDIO_PR_INFO("Do FW-Own back!(Wakeup) succeed\n"); + ret = 0; + } else { + STPSDIO_PR_ERR("Do FW-Own back!(Wakeup) fail\n"); + ret = -1; + } + } else + ret = retry > 0 ? 0 : -1; + +out: + return ret; +} + +/*! + * \brief + * + * \details + * + * \param[IN] op code for SDIO PS and OWN control + * + * \retval 0 success + * \retval !=0 fail + */ +INT32 stp_sdio_own_ctrl(SDIO_PS_OP op) +{ + INT32 ret = -1; + P_OSAL_SIGNAL pOsalSignal = NULL; + + if (g_stp_sdio_host_count == 0) { + STPSDIO_PR_WARN("g_stp_sdio_host_count is 0, do nothing!\n"); + return 0; + } + pOsalSignal = &gp_info->isr_check_complete; + switch (op) { + case OWN_SET: + gp_info->wakeup_flag = 0; + gp_info->sleep_flag = 1; + osal_trigger_event(&gp_info->tx_rx_event); + STPSDIO_PR_LOUD("before op(%d)\n", op); + osal_ftrace_print("own set start, wakeup_flag(%d), sleep_flag(%d), wait signal", + gp_info->wakeup_flag, gp_info->sleep_flag); + ret = osal_wait_for_signal_timeout(pOsalSignal, NULL); + if (!ret) + STPSDIO_PR_ERR("OWN_SET fail, done(%d), sleep(%d), wakeup(%d)\n", + pOsalSignal->comp.done, gp_info->sleep_flag, gp_info->wakeup_flag); + STPSDIO_PR_LOUD("after op(%d)\n", op); + ret = 0; + break; + + case OWN_CLR: + /* ret = stp_sdio_do_own_clr(1); */ + gp_info->sleep_flag = 0; + gp_info->wakeup_flag = 1; + osal_trigger_event(&gp_info->tx_rx_event); + osal_ftrace_print("own clear start, wakeup_flag(%d), sleep_flag(%d), wait signal", + gp_info->wakeup_flag, gp_info->sleep_flag); + STPSDIO_PR_LOUD("before op(%d)\n", op); + ret = osal_wait_for_signal_timeout(pOsalSignal, NULL); + if (!ret) + STPSDIO_PR_ERR("OWN_CLER fail, done(%d), sleep(%d), wakeup(%d)\n", + pOsalSignal->comp.done, gp_info->sleep_flag, gp_info->wakeup_flag); + STPSDIO_PR_LOUD("after op(%d)\n", op); + ret = 0; + break; + case OWN_STATE: + /* ret = stp_sdio_get_own_state(); */ + STPSDIO_PR_INFO("omit op(%d)\n", op); + ret = 0; + break; + default: + STPSDIO_PR_WARN("omit op(%d)\n", op); + ret = -1; + break; + } + osal_ftrace_print("own control end, wakeup_flag(%d), sleep_flag(%d), signal done", + gp_info->wakeup_flag, gp_info->sleep_flag); + return ret; +} + +#if STP_SDIO_OWN_THREAD + +static INT32 stp_sdio_wait_for_msg(PVOID pvData) +{ + MTK_WCN_STP_SDIO_HIF_INFO *pInfo = (MTK_WCN_STP_SDIO_HIF_INFO *) pvData; +#if STP_SDIO_NEW_TXRING + STPSDIO_PR_LOUD + ("len(%u), wr_cnt(%u), rd_cnt(%u), irq_pending(%u), sleep(%u), wakeup(%u)\n", + pInfo->rx_pkt_len, atomic_read(&pInfo->pkt_buf.wr_cnt), atomic_read(&pInfo->pkt_buf.rd_cnt), + pInfo->irq_pending, pInfo->sleep_flag, pInfo->wakeup_flag); + osal_ftrace_print("len(%u), txwkr(%u), irq(%u), sleep(%u), wakeup(%u), tx_pkt_num(%u))\n", + pInfo->rx_pkt_len, pInfo->txwkr_flag, pInfo->irq_pending, pInfo->sleep_flag, pInfo->wakeup_flag, + pInfo->firmware_info.tx_packet_num); + return (pInfo->rx_pkt_len != 0) + || (pInfo->txwkr_flag != 0) + || (pInfo->irq_pending != 0) + || (pInfo->sleep_flag != 0) + || (pInfo->wakeup_flag != 0) + || (osal_thread_should_stop(&pInfo->tx_rx_thread)); +#else + STPSDIO_PR_LOUD + ("len(%u), rd_idx(%u), wr_idx(%u), irq_pending(%u), sleep(%u), wakeup(%u)\n", + pInfo->rx_pkt_len, atomic_read(&pInfo->pkt_buf.rd_idx), atomic_read(&pInfo->pkt_buf.wr_idx), + pInfo->irq_pending, pInfo->sleep_flag, pInfo->wakeup_flag); + osal_ftrace_print("len(%u), txwkr(%u), irq(%u), sleep(%u), wakeup(%u), tx_pkt_num(%u)\n", + pInfo->rx_pkt_len, pInfo->txwkr_flag, pInfo->irq_pending, pInfo->sleep_flag, pInfo->wakeup_flag, + pInfo->firmware_info.tx_packet_num); + return (pInfo->rx_pkt_len != 0) + || (pInfo->txwkr_flag != 0) + || (pInfo->irq_pending != 0) + || (pInfo->sleep_flag != 0) + || (pInfo->wakeup_flag != 0) + || (osal_thread_should_stop(&pInfo->tx_rx_thread)); +#endif /* STP_SDIO_NEW_TXRING */ +} + +static VOID stp_sdio_tx_rx_handling(PVOID pData) +{ + MTK_WCN_STP_SDIO_HIF_INFO *pInfo = (MTK_WCN_STP_SDIO_HIF_INFO *) pData; + UINT32 iRet = 0; + UINT32 chisr = 0; + UINT32 chlcpr_value = 0; + UINT32 write_value = 0; + UINT32 tx_comp = 0; + MTK_WCN_HIF_SDIO_CLTCTX clt_ctx; + UINT32 while_loop_counter = 0; + UINT32 own_fail_counter = 0; + UINT32 val = 0; + UINT32 delay_us = 10000; + UINT32 chisr_error_count = 3; + + STPSDIO_PR_INFO("stp_tx_rx_thread start running...\n"); + if (pInfo == NULL) { + STPSDIO_PR_WARN("sanity check fail, (pInfo == NULL)\n"); + return; + } + clt_ctx = pInfo->sdio_cltctx; + + while (!osal_thread_should_stop(&pInfo->tx_rx_thread)) { + while_loop_counter++; + osal_ftrace_print("loop_count:%d\n", while_loop_counter); + /* <0> get CHLPCR information */ + if (pInfo->awake_flag == 0) { + if (CLTCTX_CID(clt_ctx) == 0x6632) + stp_sdio_wake_up_ctrl(clt_ctx); + if (stp_sdio_do_own_clr(0) == 0) { + STPSDIO_PR_DBG("set OWN to driver side ok!\n"); + pInfo->awake_flag = 1; + osal_ftrace_print("set OWN D ok!, sleep_flag(%d), wakeup_flag(%d), awake_falg(%d)", + pInfo->sleep_flag, pInfo->wakeup_flag, pInfo->awake_flag); + own_fail_counter = 0; + } else { + if ((pInfo->sleep_flag != 0) || (pInfo->wakeup_flag != 0)) { + pInfo->wakeup_flag = 0; + pInfo->sleep_flag = 0; + STPSDIO_PR_WARN("clr fw own fail,signal for sleep/wakeup to return\n"); + osal_raise_signal(&pInfo->isr_check_complete); + } + if ((own_fail_counter % 50) == 0) { + STPSDIO_PR_ERR("set OWN to driver side error!\n"); + /*trigger whole chip reset by send fake coredump content */ + if (own_fail_counter == 0) + stp_sdio_issue_fake_coredump + ("ABT: STP-SDIO clear f/w own failed"); + } + own_fail_counter++; + } + } else { + STPSDIO_PR_DBG("OWN on driver side!\n"); + osal_ftrace_print("OWN D , sleep_flag(%d), wakeup_flag(%d), awake_falg(%d)", + pInfo->sleep_flag, pInfo->wakeup_flag, pInfo->awake_flag); + } + + if ((pInfo->wakeup_flag != 0) && (pInfo->awake_flag != 0)) { + while_loop_counter = 0; + STPSDIO_PR_DBG("clr firmware own! (wakeup) ok\n"); + pInfo->wakeup_flag = 0; + osal_raise_signal(&pInfo->isr_check_complete); + osal_ftrace_print("wakeup done\n"); + } + + if ((pInfo->irq_pending != 0) && (pInfo->awake_flag == 1)) { + while_loop_counter = 0; + + /* <1> get CHISR information */ + iRet = mtk_wcn_hif_sdio_readl(clt_ctx, CHISR, &chisr); + if (iRet) { + /* 4 <1.1> get CHISR Rx error handling */ + /* TODO: error handling! */ + STPSDIO_PR_ERR("get CHISR information rx error, ret:%d\n", iRet); + if (-5 == iRet) { + iRet = stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_MAX_RETRY_NUM, + clt_ctx, CSR, &chisr, 0); + pInfo->irq_pending = 0; + } + } else { + pInfo->irq_pending = 0; + osal_ftrace_print("CHISR(0x%08x)\n", chisr); + } + + if (pInfo->dump_flag != 0) + STPSDIO_PR_ERR("CHISR(0x%08x)\n", chisr); + else + STPSDIO_PR_DBG("CHISR(0x%08x)\n", chisr); + + + if (chisr == 0x0) { + STPSDIO_PR_ERR("******CHISR == 0*****\n"); + while (chisr_error_count) { + stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, + clt_ctx, CCIR, &val, 0); + STPSDIO_PR_ERR("******CCIR == 0x%x*****\n", val); + stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, + clt_ctx, CHLPCR, &val, 0); + STPSDIO_PR_ERR("******CHLPCR == 0x%x*****\n", val); + stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, + clt_ctx, CSDIOCSR, &val, 0); + STPSDIO_PR_ERR("******CSDIOCSR == 0x%x*****\n", val); + stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, + clt_ctx, CHCR, &val, 0); + STPSDIO_PR_ERR("******CHCR == 0x%x*****\n", val); + stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, + clt_ctx, CHISR, &chisr, 0); + STPSDIO_PR_ERR("******CHISR == 0x%x*****\n", chisr); + if (chisr) + break; + stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, + clt_ctx, CHIER, &val, 0); + STPSDIO_PR_ERR("******CHIER == 0x%x*****\n", val); + stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, + clt_ctx, CTFSR, &val, 0); + STPSDIO_PR_ERR("******CTFSR == 0x%x*****\n", val); + stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, + clt_ctx, CRPLR, &val, 0); + STPSDIO_PR_ERR("******CRPLR == 0x%x*****\n", val); + chisr_error_count--; + osal_usleep_range(delay_us, 2 * delay_us); + } + } + + if (chisr & FW_OWN_BACK_INT) + STPSDIO_PR_HINT("FW_OWN_BACK_INT\n"); + + /* <4> handle Tx interrupt */ + if ((chisr & TX_EMPTY) || (chisr & TX_UNDER_THOLD) || (chisr & TX_RETRY)) { + while_loop_counter = 0; + STPSDIO_PR_DBG("Tx interrupt\n"); + /* get complete count */ + tx_comp = (chisr & TX_COMPLETE_COUNT) >> 4; + + tx_comp = + atomic_add_return(tx_comp, &pInfo->firmware_info.tx_comp_num); + if (tx_comp > STP_SDIO_TX_PKT_MAX_CNT) + STPSDIO_PR_ERR + ("Abnormal accumulated comp count(%d) chisr(0x%x)\n", + tx_comp, chisr); + if (chisr & TX_RETRY) + pInfo->tx_retry_flag = STP_SDIO_RETRY_INT; + } + if (pInfo->awake_flag == 1 && pInfo->tx_retry_flag != STP_SDIO_RETRY_CRC_ERROR) + stp_sdio_tx_wkr(&pInfo->tx_work); + + if (chisr & RX_DONE) { + /* STPSDIO_PR_INFO("RX_DONE_INT\n"); */ + if (pInfo->rx_pkt_len) + STPSDIO_PR_ERR("rx worker is not finished yet!\n"); + + /* get Rx packet length */ + pInfo->rx_pkt_len = (chisr & RX_PKT_LEN) >> 16; + STPSDIO_PR_HINT("rx_pkt_len(%d)\n", pInfo->rx_pkt_len); + /* sanity check */ + if ((pInfo->rx_pkt_len == 0) || + (pInfo->rx_pkt_len > STP_SDIO_RX_FIFO_SIZE)) { + STPSDIO_PR_ERR + ("abnormal rx_pkt_len(%d) in CHISR(0x%08x) skip rx_worker\n", + pInfo->rx_pkt_len, chisr); + pInfo->rx_pkt_len = 0; + } else { + /* Before host driver read all rx data, chip/fw will not send more + * data to host. No need to mask rx interrupt. schedule rx worker to + * get data back and handle it. + */ + if (pInfo->rx_pkt_len & 0x3) + STPSDIO_PR_WARN("rx len not 4 bytes, CHISR(0x%08x), rx len (%d).\n", + chisr, pInfo->rx_pkt_len); + } + /*Rx job */ + stp_sdio_rx_wkr(&pInfo->rx_work); + mtk_wcn_stp_wmt_sdio_host_awake(); + } + + } + + /* We schedule Tx job here without condition */ + /*Tx job */ + if (pInfo->awake_flag == 1 && pInfo->tx_retry_flag != STP_SDIO_RETRY_CRC_ERROR) + stp_sdio_tx_wkr(&pInfo->tx_work); + + /*Enable IRQ */ + /*Disable Common interrupt output in CHLPCR */ + STPSDIO_PR_DBG("enable COM IRQ\n"); + osal_ftrace_print("enable COM IRQ\n"); +/* need to wait for the ownback completion */ +/* [COHEC_00006052] SW work-around solution: + * using CMD52 write instead of CMD53 write for CCIR, CHLPCR, CSDIOCSR + */ +#if COHEC_00006052 + write_value = C_FW_INT_EN_SET; + iRet = stp_sdio_rw_retry(HIF_TYPE_WRITEB, STP_SDIO_RETRY_LIMIT, clt_ctx, CHLPCR, + &write_value, 0); +#else + write_value = C_FW_INT_EN_SET; + iRet = stp_sdio_rw_retry(HIF_TYPE_WRITEL, STP_SDIO_RETRY_LIMIT, clt_ctx, CHLPCR, + &write_value, 0); +#endif /* COHEC_00006052 */ + if (iRet) { + STPSDIO_PR_ERR("enable IRQ fail. iRet:%d\n", iRet); + osal_ftrace_print("enable COM IRQ fail, iRet:%d\n", iRet); + } else { + STPSDIO_PR_HINT("enable COM IRQ\n"); + iRet = stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, clt_ctx, CHLPCR, + &chlcpr_value, 0); + if (iRet) { + STPSDIO_PR_ERR("read CHLPCR fail. iRet:%d\n", iRet); + } else { + if (chlcpr_value & C_FW_INT_EN_SET) { + STPSDIO_PR_HINT("enable COM IRQ okay (0x%x)\n", + chlcpr_value); + osal_ftrace_print("enable COM IRQ done\n"); + + /* INTR_STATUS CHECK */ +#if 0 + write_value = 0x00000002; + iRet = stp_sdio_rw_retry(HIF_TYPE_WRITEL, STP_SDIO_RETRY_LIMIT, + clt_ctx, CHCR, &write_value, 0); + + iRet = stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, + clt_ctx, CHISR, &chisr, 0); + STPSDIO_PR_INFO("Query CHISR(0x%08x)\n", chisr); + + write_value = 0x00000000; + iRet = stp_sdio_rw_retry(HIF_TYPE_WRITEL, STP_SDIO_RETRY_LIMIT, + clt_ctx, CHCR, &write_value, 0); +#endif + } + } + + } + + if ((pInfo->sleep_flag != 0) + && (pInfo->wakeup_flag == 0) + && (pInfo->irq_pending == 0) + && (pInfo->rx_pkt_len == 0) + && mtk_wcn_stp_is_ready() + && !mtk_wcn_stp_coredump_start_get() /* f/w assert disable sdio sleep */ + ) { + if (pInfo->firmware_info.tx_packet_num == 0) { + /* pInfo->awake_flag = 0; */ + /* STPSDIO_PR_INFO("set firmware own! (sleeping)\n"); */ + while_loop_counter = 0; + osal_ftrace_print("|S|set F own\n"); + stp_sdio_do_own_set(pInfo); + osal_ftrace_print("|E|set F own, sleep_flag(%d), wakeup_flag(%d), awake_falg(%d)", + pInfo->sleep_flag, pInfo->wakeup_flag, pInfo->awake_flag); + } else { +#if 0 + /* debug code */ + if (while_loop_counter > 150) { + osal_ftrace_print("assert, w_l_c > %u\n", while_loop_counter); + stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, clt_ctx, + CHLPCR, &val, 0); + osal_ftrace_print("CHLPCR(0x%x)\n", val); + stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, clt_ctx, + CHISR, &val, 0); + osal_ftrace_print("CHISR(0x%x)\n", val); + iRet = wmt_core_trigger_stp_assert(); + if (!iRet) + STPSDIO_PR_INFO("trigger assert fail\n"); + } +#endif + /*Avoid competition for SDIO operations with ksdioirqd/mmc2 thread*/ + osal_usleep_range(300, 500); + } + } + if (while_loop_counter > 1000) { + while_loop_counter = 0; + pInfo->dump_flag = 1; + STPSDIO_PR_ERR("stp_sdio_tx_rx thread while_loop_counter over1000\n"); + stp_sdio_dump_info(pInfo); + osal_ftrace_print("stp(%d)irq(%d)tx_pkt_num(%d)rx_pkt_len(%d)", + mtk_wcn_stp_is_ready(), pInfo->irq_pending, + pInfo->firmware_info.tx_packet_num, pInfo->rx_pkt_len); + /*make fake irq flag to dump CHISR information */ + pInfo->irq_pending = 1; + + if ((pInfo->sleep_flag != 0) || (pInfo->wakeup_flag != 0)) { + osal_ftrace_print("loop_count > 1000, sleep_flag(%d), wakeup_flag(%d), awake_flag(%d)", + pInfo->sleep_flag, pInfo->wakeup_flag, pInfo->awake_flag); + /*clear wakeup/sleep pending flag, wakeup wmtd thread */ + pInfo->wakeup_flag = 0; + pInfo->sleep_flag = 0; + osal_raise_signal(&pInfo->isr_check_complete); + if (pInfo->firmware_info.tx_packet_num == STP_SDIO_TX_PKT_MAX_CNT) { + STPSDIO_PR_ERR("STP-SDIO can't handle tx request. tx_packet_num:%d\n", + pInfo->firmware_info.tx_packet_num); + osal_sleep_ms(200); + } + } + } else { + pInfo->dump_flag = 0; + } + osal_wait_for_event(&pInfo->tx_rx_event, stp_sdio_wait_for_msg, (PVOID) pInfo); + /* Read Packet from Firmware until firmware rx packet empty */ + STPSDIO_PR_DBG("stp_tx_rx_thread receive signal\n"); + } + /*make sure thread who is waiting for STP-SDIO's sleep/wakeup completion event */ + if ((pInfo->sleep_flag != 0) || (pInfo->wakeup_flag != 0)) { + osal_ftrace_print("wait for sleep/wakeup event, sleep_flag(%d), wakeup_flag(%d), awake_falg(%d)", + pInfo->sleep_flag, pInfo->wakeup_flag, pInfo->awake_flag); + pInfo->wakeup_flag = 0; + pInfo->sleep_flag = 0; + STPSDIO_PR_WARN("someone is wait for sleep/wakeup event, signal it to return\n"); + osal_raise_signal(&pInfo->isr_check_complete); + } + STPSDIO_PR_INFO("stp_tx_rx_thread exit\n"); +} +#endif /* STP_SDIO_OWN_THREAD */ + +/*! + * \brief Tx callback function for STP-CORE module + * + * \details A function registered to STP-CORE to provide STP-SDIO tx method. + * Multiple STP packet may be aggregated when available. + * + * \param[IN] data STP packet buffer to be sent through STP-SDIO + * \param[IN] size STP packet length to be sent + * \param[OUT] written_size Accepted buffer length by STP-SDIO. Shall be $size + * if success. + * + *\note Tx may do aggregation to previous entry with lock protection. If no + * aggregation is done, protection is NOT required. + * + * \retval 0 success + * \retval -1 invalid input parameters + * \todo return !0 when fail case (TBD) + */ +#if STP_SDIO_NEW_TXRING +INT32 stp_sdio_tx(const PUINT8 data, const UINT32 size, PUINT32 written_size) +{ + PUINT8 pkt_bufp; + UINT32 prev_wr_idx; + UINT32 prev_size; + MTK_WCN_STP_SDIO_PKT_BUF *pb = NULL; + UINT32 idx; + + osal_ftrace_print("%s|S|L|%d\n", __func__, size); + if (written_size) + *written_size = 0; + + /* do sanity check */ + if ((size > STP_SDIO_TX_FIFO_SIZE) + || (!data)) { + STPSDIO_PR_LOUD("invalid size(%ld) > fifo(%d) or data(0x%p)\n", + size, STP_SDIO_TX_FIFO_SIZE, data); + return -1; + } + + pb = &gp_info->pkt_buf; + /* 4 <1> enqueue the stp Tx packet */ + + spin_lock_irqsave(&pb->rd_cnt_lock, pb->rd_irq_flag); + /* Case 1: buffer is empty (No aggregation). Full flag is useless in this + * condition. + */ + if (atomic_read(&pb->rd_cnt) == atomic_read(&pb->wr_cnt)) { + spin_unlock_irqrestore(&pb->rd_cnt_lock, pb->rd_irq_flag); + /* Set the size in SDIO packet header later in tx_worker, not here */ + idx = atomic_read(&pb->wr_cnt) & STP_SDIO_TX_BUF_CNT_MASK; + pb->tx_buf_ts[idx] = jiffies; + pb->tx_buf_sz[idx] = size + STP_SDIO_HDR_SIZE; +#if KMALLOC_UPDATE + pkt_bufp = pb->tx_buf + idx * STP_SDIO_TX_ENTRY_SIZE + STP_SDIO_HDR_SIZE; +#else + pkt_bufp = &pb->tx_buf[idx][STP_SDIO_HDR_SIZE]; +#endif + memcpy(pkt_bufp, data, size); + gp_info->txwkr_flag = 1; + atomic_inc(&pb->wr_cnt); + + if (written_size) + *written_size = size; + STPSDIO_PR_DBG("(Empty) Enqueue done\n"); + } + /* Case 2: buffer is neither empty(w != r) nor full (w-r < s) */ + else if ((atomic_read(&pb->wr_cnt) - atomic_read(&pb->rd_cnt)) < STP_SDIO_TX_BUF_CNT) { + prev_wr_idx = (atomic_read(&pb->wr_cnt) - 1) & STP_SDIO_TX_BUF_CNT_MASK; + prev_size = pb->tx_buf_sz[prev_wr_idx]; + + /* Case 2.1 Aggregate if rd_cnt+1 != wr_cnt */ + /* George: do length check using add instead of sub operation. Compare + * to FIFO size instead of sw entry size. + */ + if (((atomic_read(&pb->rd_cnt) + 1) != atomic_read(&pb->wr_cnt)) + && ((size + prev_size) <= STP_SDIO_TX_FIFO_SIZE)) { +#if KMALLOC_UPDATE + pkt_bufp = pb->tx_buf + prev_wr_idx * STP_SDIO_TX_ENTRY_SIZE + prev_size; +#else + pkt_bufp = &pb->tx_buf[prev_wr_idx][prev_size]; +#endif + pb->tx_buf_sz[prev_wr_idx] += size; + + memcpy(pkt_bufp, data, size); + spin_unlock_irqrestore(&pb->rd_cnt_lock, pb->rd_irq_flag); + + STPSDIO_PR_DBG("(Not empty-aggre) Enqueue done\n"); + + if (written_size) + *written_size = size; + } + /* Case 2.2 Use next entry w/o aggregation */ + else { + /* Check the ring buf is full or not */ + if ((atomic_read(&pb->wr_cnt) - atomic_read(&pb->rd_cnt)) == 1) + pb->full_flag = MTK_WCN_BOOL_TRUE; + spin_unlock_irqrestore(&pb->rd_cnt_lock, pb->rd_irq_flag); + + /* George: if tx_wkr preempts here and pop out all buffered entries, + * ie increase rd_idx utill wr_idx, tx_wkr will encounter buffer + * empty condition and stop, then being scheduled before end of this + * function. It's safe! + */ + idx = atomic_read(&pb->wr_cnt) & STP_SDIO_TX_BUF_CNT_MASK; + pb->tx_buf_ts[idx] = jiffies; + pb->tx_buf_sz[idx] = size + STP_SDIO_HDR_SIZE; +#if KMALLOC_UPDATE + pkt_bufp = pb->tx_buf + idx * STP_SDIO_TX_ENTRY_SIZE + STP_SDIO_HDR_SIZE; +#else + pkt_bufp = &pb->tx_buf[idx][STP_SDIO_HDR_SIZE]; +#endif + memcpy(pkt_bufp, data, size); + gp_info->txwkr_flag = 1; + atomic_inc(&pb->wr_cnt); + + STPSDIO_PR_DBG("(Not empty-no aggre) Enqueue done\n"); + if (written_size) + *written_size = size; + } + } + /* Case 3: buffer is full (w-r >= s), (try aggregation) */ + else { + if (!((atomic_read(&pb->wr_cnt) - atomic_read(&pb->rd_cnt)) >= STP_SDIO_TX_BUF_CNT)) { + STPSDIO_PR_ERR + ("abnormal condition and flow, wr_cnt(0x%x), rd_cnt(0x%x)\n", + atomic_read(&pb->wr_cnt), atomic_read(&pb->rd_cnt)); + } + prev_wr_idx = (atomic_read(&pb->wr_cnt) - 1) & STP_SDIO_TX_BUF_CNT_MASK; + prev_size = pb->tx_buf_sz[prev_wr_idx]; + + /* George: do length check using add instead of sub operation. Compare + * to FIFO size instead of sw entry size. (buf_allocation != 0) shall be + * an assert true condition, not a if () condition...... + */ + /* Case 3.1 Aggregation */ + if ((size + prev_size) <= STP_SDIO_TX_FIFO_SIZE) { + if (prev_size != 0) + STPSDIO_PR_ERR("abnormal, wr_cnt(0x%x), rd_cnt(0x%x), prev(%d), prev_size(%d)\n", + atomic_read(&pb->wr_cnt), atomic_read(&pb->rd_cnt), + prev_wr_idx, prev_size); +#if KMALLOC_UPDATE + pkt_bufp = pb->tx_buf + prev_wr_idx * STP_SDIO_TX_ENTRY_SIZE + prev_size; +#else + pkt_bufp = &pb->tx_buf[prev_wr_idx][prev_size]; +#endif + pb->tx_buf_sz[prev_wr_idx] += size; + + /* unlock after copying data to ring buffer done so that rd_cnt can + * move forward and may overlap to prev_wr_idx. + */ + memcpy(pkt_bufp, data, size); + spin_unlock_irqrestore(&pb->rd_cnt_lock, pb->rd_irq_flag); + + STPSDIO_PR_DBG("(full-aggre) Enqueue done\n"); + + if (written_size) + *written_size = size; + } + /* Case 3.2 Buffer is full */ + else { + spin_unlock_irqrestore(&pb->rd_cnt_lock, pb->rd_irq_flag); + STPSDIO_PR_WARN("Local Tx buffer is full !\n"); + + /* Wait for tx ring buffer is not full */ + /* TODO:[FixMe][George] This wait() call IS a problem if caller runs + * in interrupt context (sw or hw) !! + */ + /* TODO:[FixMe][George] should use timeout version, + * not interruptible version. Return error when timeout! + */ + wait_event_interruptible(pb->fullwait_q, + (pb->full_flag == MTK_WCN_BOOL_FALSE)); + STPSDIO_PR_INFO("wait event return\n"); + + spin_lock_irqsave(&pb->rd_cnt_lock, pb->rd_irq_flag); + /* Check if the local buf is free enough */ + if ((atomic_read(&pb->wr_cnt) - atomic_read(&pb->rd_cnt)) == 1) + pb->full_flag = MTK_WCN_BOOL_TRUE; + spin_unlock_irqrestore(&pb->rd_cnt_lock, pb->rd_irq_flag); + + /* George: use this new entry w/o protection */ + idx = atomic(&pb->wr_cnt) & STP_SDIO_TX_BUF_CNT_MASK; + pb->tx_buf_ts[idx] = jiffies; + pb->tx_buf_sz[idx] = size + STP_SDIO_HDR_SIZE; +#if KMALLOC_UPDATE + pkt_bufp = pb->tx_buf + idx * STP_SDIO_TX_ENTRY_SIZE + STP_SDIO_HDR_SIZE; +#else + pkt_bufp = &pb->tx_buf[idx][STP_SDIO_HDR_SIZE]; +#endif + /* Copy data to ring buffer */ + memcpy(pkt_bufp, data, size); + gp_info->txwkr_flag = 1; + atomic_inc(&pb->wr_cnt); + + if (written_size) + *written_size = size; + } + } + + /* <2> schedule for Tx worker tasklet */ + osal_ftrace_print("%s|E|signal stp_sdio_tx_rx\n", __func__); +#if STP_SDIO_OWN_THREAD + /* tasklet_schedule(&gp_info->tx_rx_job); */ + STPSDIO_PR_DBG("osal_trigger_event gp_info->tx_rx_event\n"); + osal_trigger_event(&gp_info->tx_rx_event); +#else + schedule_work(&gp_info->tx_work); +#endif + osal_ftrace_print("%s|E|L|%d\n", __func__, size); + + return 0; +} + +#else +INT32 stp_sdio_tx(const PUINT8 data, const UINT32 size, PUINT32 written_size) +{ + PUINT8 pkt_bufp; + UINT32 prev_wr_idx; + UINT32 buf_allocation; + UINT32 room; + UINT64 ts; + ULONG nsec; + + osal_ftrace_print("%s|S|L|%d\n", __func__, size); + + /* 4 <1> enqueue the stp Tx packet */ + *written_size = 0; + + spin_lock_irqsave(&gp_info->pkt_buf.rd_idx_lock, gp_info->pkt_buf.rd_irq_flag); + /* Case 1: buffer is empty (Not aggregation) */ + if ((atomic_read(&gp_info->pkt_buf.rd_idx) == atomic_read(&gp_info->pkt_buf.wr_idx)) + && (gp_info->pkt_buf.full_flag == MTK_WCN_BOOL_FALSE)) { + spin_unlock_irqrestore(&gp_info->pkt_buf.rd_idx_lock, gp_info->pkt_buf.rd_irq_flag); + /* set the size in SDIO packet header */ +#if KMALLOC_UPDATE + *(gp_info->pkt_buf.tx_buf + atomic_read(&gp_info->pkt_buf.wr_idx) * + STP_SDIO_TX_ENTRY_SIZE + 0) = (UINT8)((size + STP_SDIO_HDR_SIZE) & 0xff); + *(gp_info->pkt_buf.tx_buf + atomic_read(&gp_info->pkt_buf.wr_idx) * + STP_SDIO_TX_ENTRY_SIZE + 1) = (UINT8)((size + STP_SDIO_HDR_SIZE) >> 8); +#else + gp_info->pkt_buf.tx_buf[atomic_read(&gp_info->pkt_buf.wr_idx)][0] = + (UINT8) ((size + STP_SDIO_HDR_SIZE) & 0xff); + gp_info->pkt_buf.tx_buf[atomic_read(&gp_info->pkt_buf.wr_idx)][1] = + (UINT8) ((size + STP_SDIO_HDR_SIZE) >> 8); +#endif + gp_info->pkt_buf.tx_buf_ts[atomic_read(&gp_info->pkt_buf.wr_idx)] = jiffies; + osal_get_local_time(&ts, &nsec); + gp_info->pkt_buf.tx_buf_local_ts[atomic_read(&gp_info->pkt_buf.wr_idx)] = ts; + gp_info->pkt_buf.tx_buf_local_nsec[atomic_read(&gp_info->pkt_buf.wr_idx)] = nsec; + + STPSDIO_PR_DBG("(Empty) Enqueue done\n"); +#if KMALLOC_UPDATE + pkt_bufp = gp_info->pkt_buf.tx_buf + atomic_read(&gp_info->pkt_buf.wr_idx) * + STP_SDIO_TX_ENTRY_SIZE + STP_SDIO_HDR_SIZE; +#else + pkt_bufp = &gp_info->pkt_buf.tx_buf[atomic_read(&gp_info->pkt_buf.wr_idx)][STP_SDIO_HDR_SIZE]; +#endif + memcpy(pkt_bufp, data, size); + *written_size = size; + gp_info->txwkr_flag = 1; + atomic_set(&gp_info->pkt_buf.wr_idx, + (atomic_read(&gp_info->pkt_buf.wr_idx) + 1) % STP_SDIO_TX_BUF_CNT); + } + /* Case 2: buffer is not empty */ + else if (atomic_read(&gp_info->pkt_buf.rd_idx) != atomic_read(&gp_info->pkt_buf.wr_idx)) { + prev_wr_idx = (atomic_read(&gp_info->pkt_buf.wr_idx) - 1 + STP_SDIO_TX_BUF_CNT) % + STP_SDIO_TX_BUF_CNT; + /* set the packet size form previous SDIO packet header */ +#if KMALLOC_UPDATE + buf_allocation = + *(gp_info->pkt_buf.tx_buf + prev_wr_idx * STP_SDIO_TX_ENTRY_SIZE + 1); + buf_allocation = + (buf_allocation << 8) | *(gp_info->pkt_buf.tx_buf + + prev_wr_idx * STP_SDIO_TX_ENTRY_SIZE + 0); +#else + buf_allocation = gp_info->pkt_buf.tx_buf[prev_wr_idx][1]; + buf_allocation = (buf_allocation << 8) | gp_info->pkt_buf.tx_buf[prev_wr_idx][0]; +#endif + /* Case 2.1 Aggregation */ + /* George: do length check using add instead of sub operation. Compare + * to FIFO size instead of sw entry size. + */ + if ((prev_wr_idx != atomic_read(&gp_info->pkt_buf.rd_idx)) + && ((size + buf_allocation) <= STP_SDIO_TX_FIFO_SIZE)) { +#if KMALLOC_UPDATE + pkt_bufp = + gp_info->pkt_buf.tx_buf + prev_wr_idx * STP_SDIO_TX_ENTRY_SIZE + + buf_allocation; + + buf_allocation += size; + *(gp_info->pkt_buf.tx_buf + prev_wr_idx * STP_SDIO_TX_ENTRY_SIZE + 0) = + (UINT8) (buf_allocation & 0xff); + *(gp_info->pkt_buf.tx_buf + prev_wr_idx * STP_SDIO_TX_ENTRY_SIZE + 1) = + (UINT8) (buf_allocation >> 8); +#else + pkt_bufp = &gp_info->pkt_buf.tx_buf[prev_wr_idx][buf_allocation]; + + buf_allocation += size; + gp_info->pkt_buf.tx_buf[prev_wr_idx][0] = (UINT8) (buf_allocation & 0xff); + gp_info->pkt_buf.tx_buf[prev_wr_idx][1] = (UINT8) (buf_allocation >> 8); +#endif + memcpy(pkt_bufp, data, size); + spin_unlock_irqrestore(&gp_info->pkt_buf.rd_idx_lock, + gp_info->pkt_buf.rd_irq_flag); + + STPSDIO_PR_DBG("(Not empty-aggre) Enqueue done\n"); + + *written_size = size; + } + /* Case 2.2 Not aggregation */ + else { + /* Check the ring buf is full or not */ + room = (atomic_read(&gp_info->pkt_buf.wr_idx) >= + atomic_read(&gp_info->pkt_buf.rd_idx)) ? (STP_SDIO_TX_BUF_CNT - + (atomic_read(&gp_info->pkt_buf.wr_idx) - + atomic_read(&gp_info->pkt_buf.rd_idx))) : + (atomic_read(&gp_info->pkt_buf.rd_idx) - + atomic_read(&gp_info->pkt_buf.wr_idx)); + if (room == 1) + gp_info->pkt_buf.full_flag = MTK_WCN_BOOL_TRUE; + spin_unlock_irqrestore(&gp_info->pkt_buf.rd_idx_lock, + gp_info->pkt_buf.rd_irq_flag); + + /* George: if tx_wkr preempts here and pop out all buffered entries, + * ie increase rd_idx utill wr_idx, tx_wkr will encounter buffer + * empty condition and stop, then being scheduled before end of this + * function. It's safe! + */ + + /* set the size in SDIO packet header */ +#if KMALLOC_UPDATE + *(gp_info->pkt_buf.tx_buf + + atomic_read(&gp_info->pkt_buf.wr_idx) * STP_SDIO_TX_ENTRY_SIZE + 0) = + (UINT8) ((size + STP_SDIO_HDR_SIZE) & 0xff); + *(gp_info->pkt_buf.tx_buf + + atomic_read(&gp_info->pkt_buf.wr_idx) * STP_SDIO_TX_ENTRY_SIZE + 1) = + (UINT8) ((size + STP_SDIO_HDR_SIZE) >> 8); + gp_info->pkt_buf.tx_buf_ts[atomic_read(&gp_info->pkt_buf.wr_idx)] = jiffies; + osal_get_local_time(&ts, &nsec); + gp_info->pkt_buf.tx_buf_local_ts[atomic_read(&gp_info->pkt_buf.wr_idx)] = ts; + gp_info->pkt_buf.tx_buf_local_nsec[atomic_read(&gp_info->pkt_buf.wr_idx)] = nsec; + + pkt_bufp = + gp_info->pkt_buf.tx_buf + + atomic_read(&gp_info->pkt_buf.wr_idx) * STP_SDIO_TX_ENTRY_SIZE + STP_SDIO_HDR_SIZE; +#else + gp_info->pkt_buf.tx_buf[atomic_read(&gp_info->pkt_buf.wr_idx)][0] = + (UINT8) ((size + STP_SDIO_HDR_SIZE) & 0xff); + gp_info->pkt_buf.tx_buf[atomic_read(&gp_info->pkt_buf.wr_idx)][1] = + (UINT8) ((size + STP_SDIO_HDR_SIZE) >> 8); + gp_info->pkt_buf.tx_buf_ts[atomic_read(&gp_info->pkt_buf.wr_idx)] = jiffies; + + pkt_bufp = &gp_info->pkt_buf. + tx_buf[atomic_read(&gp_info->pkt_buf.wr_idx)][STP_SDIO_HDR_SIZE]; +#endif + memcpy(pkt_bufp, data, size); + + STPSDIO_PR_DBG("(Not empty-no aggre) Enqueue done\n"); + + *written_size = size; + gp_info->txwkr_flag = 1; + atomic_set(&gp_info->pkt_buf.wr_idx, + (atomic_read(&gp_info->pkt_buf.wr_idx) + 1) % STP_SDIO_TX_BUF_CNT); + } + } + /* Case 3: buffer is full (Aggregation) */ + else if (gp_info->pkt_buf.full_flag != MTK_WCN_BOOL_FALSE) { + prev_wr_idx = (atomic_read(&gp_info->pkt_buf.wr_idx) - 1 + STP_SDIO_TX_BUF_CNT) % + STP_SDIO_TX_BUF_CNT; +#if KMALLOC_UPDATE + buf_allocation = + *(gp_info->pkt_buf.tx_buf + prev_wr_idx * STP_SDIO_TX_ENTRY_SIZE + 1); + buf_allocation = + (buf_allocation << 8) | *(gp_info->pkt_buf.tx_buf + + prev_wr_idx * STP_SDIO_TX_ENTRY_SIZE + 0); +#else + buf_allocation = gp_info->pkt_buf.tx_buf[prev_wr_idx][1]; + buf_allocation = (buf_allocation << 8) | gp_info->pkt_buf.tx_buf[prev_wr_idx][0]; +#endif + /* Case 3.1 Aggregation */ + /* George: do length check using add instead of sub operation. Compare + * to FIFO size instead of sw entry size. (buf_allocation != 0) shall be + * an assert true condition, not a if () condition...... + */ + if ((buf_allocation != 0) + && ((size + buf_allocation) <= STP_SDIO_TX_FIFO_SIZE)) { +#if KMALLOC_UPDATE + pkt_bufp = + gp_info->pkt_buf.tx_buf + prev_wr_idx * STP_SDIO_TX_ENTRY_SIZE + + buf_allocation; +#else + pkt_bufp = &gp_info->pkt_buf.tx_buf[prev_wr_idx][buf_allocation]; +#endif + buf_allocation += size; +#if KMALLOC_UPDATE + *(gp_info->pkt_buf.tx_buf + prev_wr_idx * STP_SDIO_TX_ENTRY_SIZE + 0) = + (UINT8) (buf_allocation & 0xff); + *(gp_info->pkt_buf.tx_buf + prev_wr_idx * STP_SDIO_TX_ENTRY_SIZE + 1) = + (UINT8) (buf_allocation >> 8); +#else + gp_info->pkt_buf.tx_buf[prev_wr_idx][0] = (UINT8) (buf_allocation & 0xff); + gp_info->pkt_buf.tx_buf[prev_wr_idx][1] = (UINT8) (buf_allocation >> 8); +#endif + /* Copy data to ring buffer */ + memcpy(pkt_bufp, data, size); + spin_unlock_irqrestore(&gp_info->pkt_buf.rd_idx_lock, + gp_info->pkt_buf.rd_irq_flag); + + STPSDIO_PR_DBG("(full-aggre) Enqueue done\n"); + + *written_size = size; + } + /* Case 3.2 Buffer is full */ + else { + spin_unlock_irqrestore(&gp_info->pkt_buf.rd_idx_lock, + gp_info->pkt_buf.rd_irq_flag); + STPSDIO_PR_WARN("Local Tx buffer is full !!!!!\n"); + + /* Wait for tx ring buffer is not full + * TODO:[FixMe][George] This wait() call IS a problem + * if caller runs in interrupt context (sw or hw) !! + * TODO:[FixMe][George] should use timeout version, + * not interruptible version. Return error when timeout! + */ + wait_event_interruptible(gp_info->pkt_buf.fullwait_q, + (!gp_info->pkt_buf.full_flag)); + STPSDIO_PR_INFO("wait event return\n"); + + spin_lock_irqsave(&gp_info->pkt_buf.rd_idx_lock, + gp_info->pkt_buf.rd_irq_flag); + /* Check if the local buf is free enough */ + room = (atomic_read(&gp_info->pkt_buf.wr_idx) >= + atomic_read(&gp_info->pkt_buf.rd_idx)) ? + (STP_SDIO_TX_BUF_CNT - (atomic_read(&gp_info->pkt_buf.wr_idx) - + atomic_read(&gp_info->pkt_buf.rd_idx))) : + (atomic_read(&gp_info->pkt_buf.rd_idx) - + atomic_read(&gp_info->pkt_buf.wr_idx)); + if (room == 1) + gp_info->pkt_buf.full_flag = MTK_WCN_BOOL_TRUE; + spin_unlock_irqrestore(&gp_info->pkt_buf.rd_idx_lock, + gp_info->pkt_buf.rd_irq_flag); + + /* George: use this new entry w/o protection */ +#if KMALLOC_UPDATE + *(gp_info->pkt_buf.tx_buf + atomic_read(&gp_info->pkt_buf.wr_idx) * + STP_SDIO_TX_ENTRY_SIZE + 0) = + (UINT8) ((size + STP_SDIO_HDR_SIZE) & 0xff); + *(gp_info->pkt_buf.tx_buf + atomic_read(&gp_info->pkt_buf.wr_idx) * + STP_SDIO_TX_ENTRY_SIZE + 1) = + (UINT8) ((size + STP_SDIO_HDR_SIZE) >> 8); + gp_info->pkt_buf.tx_buf_ts[atomic_read(&gp_info->pkt_buf.wr_idx)] = jiffies; + osal_get_local_time(&ts, &nsec); + gp_info->pkt_buf.tx_buf_local_ts[atomic_read(&gp_info->pkt_buf.wr_idx)] = ts; + gp_info->pkt_buf.tx_buf_local_nsec[atomic_read(&gp_info->pkt_buf.wr_idx)] = nsec; + + pkt_bufp = gp_info->pkt_buf.tx_buf + atomic_read(&gp_info->pkt_buf.wr_idx) + * STP_SDIO_TX_ENTRY_SIZE + STP_SDIO_HDR_SIZE; +#else + gp_info->pkt_buf.tx_buf[atomic_read(&gp_info->pkt_buf.wr_idx)][0] = + (UINT8) ((size + STP_SDIO_HDR_SIZE) & 0xff); + gp_info->pkt_buf.tx_buf[atomic_read(&gp_info->pkt_buf.wr_idx)][1] = + (UINT8) ((size + STP_SDIO_HDR_SIZE) >> 8); + gp_info->pkt_buf.tx_buf_ts[atomic_read(&gp_info->pkt_buf.wr_idx)] = jiffies; + + pkt_bufp = &gp_info->pkt_buf. + tx_buf[atomic_read(&gp_info->pkt_buf.wr_idx)][STP_SDIO_HDR_SIZE]; +#endif + /* Copy data to ring buffer */ + memcpy(pkt_bufp, data, size); + *written_size = size; + gp_info->txwkr_flag = 1; + atomic_set(&gp_info->pkt_buf.wr_idx, + (atomic_read(&gp_info->pkt_buf.wr_idx) + 1) % STP_SDIO_TX_BUF_CNT); + } + } + /* <2> schedule for Tx worker tasklet */ + osal_ftrace_print("%s|E|signal stp_sdio_tx_rx\n", __func__); +#if STP_SDIO_OWN_THREAD + /* tasklet_schedule(&gp_info->tx_rx_job); */ + STPSDIO_PR_DBG("osal_trigger_event gp_info->tx_rx_event\n"); + osal_trigger_event(&gp_info->tx_rx_event); +#else + schedule_work(&gp_info->tx_work); +#endif + osal_ftrace_print("%s|E|L|%d\n", __func__, size); + + return 0; +} +#endif /* end of !STP_SDIO_NEW_TXRING */ + +/*! + * \brief Do STP-SDIO tx status, counters, debug information sanity check + * + * \details A function doing sanity checks on STP-SDIO Tx-related status, + * counters, debugging information. Used in tx_worker before and after bus + * write to check if any abnormal status happened. + * + * \param[IN] p_info The STP-SDIO HIF information structure pointer + * \param[IN] id The sanity check location ID, assigned by caller + * + * \retval none. + */ +static _osal_inline_ VOID stp_sdio_check_tx_sanity(const MTK_WCN_STP_SDIO_HIF_INFO *p_info, const UINT32 id) +{ +#if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXDBG + if ((p_info) && (p_info->firmware_info.tx_packet_num == 0)) { + if (!(p_info->tx_pkt_list.pkt_rd_cnt == p_info->tx_pkt_list.pkt_wr_cnt)) { + STPSDIO_PR_ERR + ("abnormal fifo_size(%d) pkt_num(%d) pkt_rd(0x%x, %ld) pkt_wr(0x%x, %ld)!(%d)\n", + p_info->firmware_info.tx_fifo_size, + p_info->firmware_info.tx_packet_num, p_info->tx_pkt_list.pkt_rd_cnt, + STP_SDIO_GET_PKT_AR_IDX(p_info->tx_pkt_list.pkt_rd_cnt), + p_info->tx_pkt_list.pkt_wr_cnt, + STP_SDIO_GET_PKT_AR_IDX(p_info->tx_pkt_list.pkt_wr_cnt), id); + /* stp_sdio_dump_txdbg(); */ + } + if (p_info->firmware_info.tx_fifo_size != STP_SDIO_TX_FIFO_SIZE) { + STPSDIO_PR_ERR + ("abnormal fifo_size(%d) pkt_num(%d) pkt_rd(0x%x, %ld) pkt_wr(0x%x, %ld)!(%d)\n", + p_info->firmware_info.tx_fifo_size, + p_info->firmware_info.tx_packet_num, p_info->tx_pkt_list.pkt_rd_cnt, + STP_SDIO_GET_PKT_AR_IDX(p_info->tx_pkt_list.pkt_rd_cnt), + p_info->tx_pkt_list.pkt_wr_cnt, + STP_SDIO_GET_PKT_AR_IDX(p_info->tx_pkt_list.pkt_wr_cnt), id); + /* stp_sdio_dump_txdbg(); */ + } + } else { + if ((p_info) && (p_info->tx_pkt_list.pkt_rd_cnt == p_info->tx_pkt_list.pkt_wr_cnt)) { + STPSDIO_PR_ERR + ("abnormal fifo_size(%d) pkt_num(%d) pkt_rd(0x%x, %ld) pkt_wr(0x%x, %ld)!(%d)\n", + p_info->firmware_info.tx_fifo_size, + p_info->firmware_info.tx_packet_num, p_info->tx_pkt_list.pkt_rd_cnt, + STP_SDIO_GET_PKT_AR_IDX(p_info->tx_pkt_list.pkt_rd_cnt), + p_info->tx_pkt_list.pkt_wr_cnt, + STP_SDIO_GET_PKT_AR_IDX(p_info->tx_pkt_list.pkt_wr_cnt), id); + /* stp_sdio_dump_txdbg(); */ + } + } +#endif +} + +/*! + * \brief Handle STP-SDIO TX IRQ BH part and complete count + * + * \details Handle STP-SDIO TX IRQ bottom half part and reported tx complete + * coount. This function is used in tx_worker ONLY to avoid race condition. + * + * \note tx_comp_num in firmware_info structure shall be handled atomically. + * It is added in STP-SDIO Tx IRQ top half handler with the number reported + * in CHISR. It is deducted in this function. + * + * \note tx_fifo_size is deducted in tx_worker when writing data to bus and + * added back in this function when tx complete. + * + * \param[IN] p_info The STP-SDIO HIF information structure pointer + * + * \retval none. + */ +static VOID stp_sdio_tx_wkr_comp(MTK_WCN_STP_SDIO_HIF_INFO * const p_info) +{ + INT32 comp_count; + UINT32 idx; + INT32 i; + INT32 max; + INT32 ret; + UINT32 value = 0; + + comp_count = atomic_read(&p_info->firmware_info.tx_comp_num); + atomic_sub(comp_count, &p_info->firmware_info.tx_comp_num); + + /* update tx to firemware information */ + if (p_info->firmware_info.tx_packet_num >= comp_count) { + STPSDIO_PR_DBG("tx_pack_num(%d), comp_count(%d),tx_comp_num(%d), retry flag(%d)\n", + p_info->firmware_info.tx_packet_num, comp_count, + atomic_read(&p_info->firmware_info.tx_comp_num), + p_info->tx_retry_flag); + p_info->firmware_info.tx_packet_num -= comp_count; + } else { + STPSDIO_PR_INFO("abnormal complete count(%d), tx_packet_num(%d), retry flag(%d)!\n", + comp_count, p_info->firmware_info.tx_packet_num, p_info->tx_retry_flag); + /* TODO: [FixMe][George] Add error handling or bug report!! */ + STPSDIO_PR_INFO("tx_fifo_size(%d), tx_packet_num(%d)\n", + p_info->firmware_info.tx_fifo_size, + p_info->firmware_info.tx_packet_num); + } + + while (comp_count > 0) { + if (p_info->tx_pkt_list.pkt_rd_cnt == p_info->tx_pkt_list.pkt_wr_cnt) { + STPSDIO_PR_ERR("tx complete count(%d) but tx_pkt_list empty\n", + comp_count); + STPSDIO_PR_ERR("rd_cnt(%u, idx:%lx), wr_cnt(%u, idx:%lx)!\n", + p_info->tx_pkt_list.pkt_rd_cnt, + p_info->tx_pkt_list.pkt_rd_cnt & STP_SDIO_TX_PKT_LIST_SIZE_MASK, + p_info->tx_pkt_list.pkt_wr_cnt, + p_info->tx_pkt_list.pkt_wr_cnt & STP_SDIO_TX_PKT_LIST_SIZE_MASK); + break; + } + + idx = p_info->tx_pkt_list.pkt_rd_cnt++ & STP_SDIO_TX_PKT_LIST_SIZE_MASK; + p_info->firmware_info.tx_fifo_size += p_info->tx_pkt_list.pkt_size_list[idx]; + p_info->tx_pkt_list.out_ts[idx] = jiffies; + --comp_count; + } + if (p_info->retry_enable_flag) { + if (p_info->tx_retry_flag == STP_SDIO_RETRY_INT) { + for (i = 0; i < 100; i++) { + ret = stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, p_info->sdio_cltctx, + CTMDPCR0, &value, 0); + if (value & 1) + break; + osal_sleep_ms(10); + } + if (!(value & 1)) { + stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, p_info->sdio_cltctx, + CTMDPCR0, &value, 0); + STPSDIO_PR_ERR("tx retry: firmware rx buffer is disable CTMDPCR0 value(%x)!\n", + value); + stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, p_info->sdio_cltctx, + CTMDPCR1, &value, 0); + STPSDIO_PR_ERR("tx retry: firmware rx buffer is disable CTMDPCR1 value(%x)!\n", + value); + stp_sdio_issue_fake_coredump + ("ABT: tx retry ERROR: firmware rx buffer is disable"); + } + idx = p_info->tx_pkt_list.pkt_rd_cnt & STP_SDIO_TX_PKT_LIST_SIZE_MASK; + max = p_info->firmware_info.tx_packet_num; + STPSDIO_PR_ERR("tx retry idx(%d) tx retry max(%d)\n", idx, max); + for (i = 0; i < max; i++) { + /* sdio crc error tx retry */ + ret = stp_sdio_rw_retry(HIF_TYPE_WRITE_BUF, STP_SDIO_RETRY_LIMIT, + p_info->sdio_cltctx, CTDR, + (PUINT32)(p_info->pkt_buf.tx_buf + idx * STP_SDIO_TX_ENTRY_SIZE + 0), + p_info->tx_pkt_list.pkt_size_list[idx]); + if (ret) { + STPSDIO_PR_ERR("sdio tx retry get CTDR information Tx error(%d)!\n", + ret); + /* TODO: error handling! */ + p_info->tx_retry_count++; + if (p_info->tx_retry_count > STP_SDIO_RETRY_LIMIT) { + STPSDIO_PR_INFO("sdio tx retry fail complete count(%d)\n", + comp_count); + STPSDIO_PR_INFO("tx_packet_num(%d), tx_fifo_size(%d)\n", + p_info->firmware_info.tx_packet_num, + p_info->firmware_info.tx_fifo_size); + STPSDIO_PR_INFO("retry flag(%d)!\n", p_info->tx_retry_flag); + /* TODO: error handling! */ +#if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXDBG + stp_sdio_txdbg_dump(); +#endif + p_info->tx_retry_count = 0; + stp_sdio_issue_fake_coredump + ("ABT: write_readsb retry ERROR"); + } + } else + p_info->tx_retry_count = 0; + idx++; + idx = idx & STP_SDIO_TX_PKT_LIST_SIZE_MASK; + } + p_info->tx_retry_flag = STP_SDIO_RETRY_NONE; + } + } +} + +/*! + * \brief Handle STP-SDIO Tx buffer and send to bus + * + * \details Handle STP-SDIO Tx buffer and send SDIO packet to bus if everything + * is checked ok. + * + * \note Tx count to FIFO is counted on a 4-byte aligned base. 1~3 bytes padding + * are also sent into HW FIFO and SHALL be trimmed off by firmware. + * tx_fifo_size is deducted in this bus when writing data to bus and added + * back in handle_tx_comp() function. + * + * \note Data length written to bus shall be 4-byte aligned AND block_size + * aligned if length > block_size. Padding bytes added for block_size is + * removed by HW. + * + * \note Max accumulated Tx size to FIFO is limited by STP_SDIO_TX_FIFO_SIZE and + * it is (2080) for MT6620. It is NOT limited to 256*5=1280 bytes. + * + * \note Max outstanding Tx packet count is limited by STP_SDIO_TX_PKT_MAX_CNT + * and it is (7) for MT6620. + * + * \param[IN] work Tx work struct work_struct pointer used by STP-SDIO + * + * \retval none. + */ +#if STP_SDIO_NEW_TXRING +static VOID stp_sdio_tx_wkr(struct work_struct *work) +{ + MTK_WCN_STP_SDIO_HIF_INFO *p_info; + UINT32 bus_txlen; + UINT32 four_byte_align_len; + PUINT8 buf_tx; + INT32 ret; + UINT32 idx; + MTK_WCN_STP_SDIO_PKT_BUF *pb; + struct timeval now; + UINT64 ts; + ULONG nsec; + + p_info = container_of(work, MTK_WCN_STP_SDIO_HIF_INFO, tx_work); + ret = HIF_SDIO_ERR_SUCCESS; + pb = &p_info->pkt_buf; + + /* 4 <0> Tx worker has been scheduled to send data */ + do { + /* handle tx complete count if any */ + stp_sdio_tx_wkr_comp(p_info); + /* check sanity of local tx information */ + stp_sdio_check_tx_sanity(p_info, 1); + + /* check if Tx ring buffer is empty */ + if (atomic_read(&p_info->pkt_buf.wr_cnt) == atomic_read(&p_info->pkt_buf.rd_cnt)) { + /* full flag is use less in this condition */ + STPSDIO_PR_DBG("Tx entry ring buffer empty\n"); + break; + } + p_info->txwkr_flag = 0; +#if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXPERFDBG + ++stp_sdio_txperf_worker_cnt; +#endif + + /* George: check txed packet number < limit(7) + * tx_packet_num is maintained only in tw_worker, no protection. + */ + if (p_info->firmware_info.tx_packet_num >= STP_SDIO_TX_PKT_MAX_CNT) { + STPSDIO_PR_DBG + ("tx_packet_num(%ld) limit, tx_fifo_size(%ld), four_byte_align_len(%ld)\n", + p_info->firmware_info.tx_packet_num, + p_info->firmware_info.tx_fifo_size, four_byte_align_len); +#if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXPERFDBG + ++stp_sdio_txperf_pkt_num_lmt_cnt; +#endif + break; + } +#if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXPERFDBG + stp_sdio_txperf_txed_pkt_num += p_info->firmware_info.tx_packet_num; +#endif + + /* Access content in rd_cnt is safe because it will not be aggregated + * anymore in sdio_tx(). Check current tx condition with info in rd_cnt. + */ + idx = atomic(&pb->rd_cnt) & STP_SDIO_TX_BUF_CNT_MASK; + + /* Get Tx packet size from Tx size ring buf */ + bus_txlen = pb->tx_buf_sz[idx]; + /* Update packet length in Tx entry */ +#if KMALLOC_UPDATE + buf_tx = gp_info->pkt_buf.tx_buf + idx * STP_SDIO_TX_ENTRY_SIZE + 0; +#else + buf_tx = &pb->tx_buf[idx][0]; +#endif + buf_tx[0] = (UINT8) (bus_txlen & 0xff); + buf_tx[1] = (UINT8) ((bus_txlen >> 8) & 0xff); + + /* George: hw always count fifo in 4-byte aligned length */ + bus_txlen += 0x3; + bus_txlen &= ~(0x3UL); + four_byte_align_len = bus_txlen; + + /* Sanity check: 4-byte aligned length shall not exceed HW FIFO Size */ + if (four_byte_align_len > STP_SDIO_TX_FIFO_SIZE) { + STPSDIO_PR_ERR("abnormal four_byte_align_len(%d) > TX_FIFO_SIZE(%ld)!!\n", + four_byte_align_len, STP_SDIO_TX_FIFO_SIZE); + } + + /* George: check if tx FIFO space is enough for 4-byte aligned length. + * If enough, tx this entry and increase rd_cnt. + */ + if (p_info->firmware_info.tx_fifo_size >= four_byte_align_len) { + /* George: refine block_size alignment with the assumption: block_size is 2^*x */ + if (bus_txlen > STP_SDIO_BLK_SIZE) { + bus_txlen += (STP_SDIO_BLK_SIZE - 1); + bus_txlen &= ~((UINT32) STP_SDIO_BLK_SIZE - 1); + } + + /* Sanity check: bus_txlen shall not exceed SW entry size */ + if (bus_txlen > STP_SDIO_TX_ENTRY_SIZE) { + STPSDIO_PR_ERR + ("abnormal bus_txlen(%d) > STP_SDIO_TX_ENTRY_SIZE(%ld)!!\n", + bus_txlen, STP_SDIO_TX_ENTRY_SIZE); + } + + ++(p_info->firmware_info.tx_packet_num); + /* decrease Tx FIFO size: using 4-byte aligned length! */ + p_info->firmware_info.tx_fifo_size -= four_byte_align_len; + /* record the SDIO packet size in packet size list: using 4-byte aligned length! */ + idx = p_info->tx_pkt_list.pkt_wr_cnt++ & STP_SDIO_TX_PKT_LIST_SIZE_MASK; + p_info->tx_pkt_list.pkt_size_list[idx] = four_byte_align_len; + p_info->tx_pkt_list.in_ts[idx] = jiffies; + p_info->tx_pkt_list.out_ts[idx] = 0; + + STPSDIO_PR_DBG("wr(0x%x, %ld) rd(0x%x, %ld), tx fifo(size:%d), pkt_num(%d)done\n", + p_info->tx_pkt_list.pkt_wr_cnt, + STP_SDIO_GET_PKT_AR_IDX(p_info->tx_pkt_list.pkt_wr_cnt), + p_info->tx_pkt_list.pkt_rd_cnt, + STP_SDIO_GET_PKT_AR_IDX(p_info->tx_pkt_list.pkt_rd_cnt), + p_info->firmware_info.tx_fifo_size, + p_info->firmware_info.tx_packet_num); + + /* port write the packet to CTDR */ + ret = stp_sdio_rw_retry(HIF_TYPE_WRITE_BUF, STP_SDIO_RETRY_LIMIT, p_info->sdio_cltctx, + CTDR, (PUINT32) buf_tx, bus_txlen); + STPSDIO_PR_DBG("write to CTDR done\n"); + +#if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXDBG + do { + osal_get_local_time(&ts, &nsec); + idx = stp_sdio_txdbg_cnt++ & STP_SDIO_TXDBG_COUNT_MASK; + /* skip clear buf */ + stp_sdio_txdbg_buffer[idx].ts = jiffies; + stp_sdio_txdbg_buffer[idx].l_sec = ts; + stp_sdio_txdbg_buffer[idx].l_nsec = nsec; + stp_sdio_txdbg_buffer[idx].bus_txlen = bus_txlen; + stp_sdio_txdbg_buffer[idx].four_byte_align_len = + four_byte_align_len; + /* store content */ + if (bus_txlen <= STP_SDIO_TX_ENTRY_SIZE) { + memcpy(&stp_sdio_txdbg_buffer[idx].tx_pkt_buf[0], buf_tx, + bus_txlen); + } else { + memcpy(&stp_sdio_txdbg_buffer[idx].tx_pkt_buf[0], buf_tx, + STP_SDIO_TX_ENTRY_SIZE); + STPSDIO_PR_ERR("abnormal bus_txlen (%d)!\n", bus_txlen); + } + } while (0); +#endif + if (ret) { + STPSDIO_PR_ERR("get CTDR information Tx error(%d)!\n", ret); + if (p_info->retry_enable_flag) { + if (ret == -EIO || ret == -EILSEQ || ret == -EBUSY) + p_info->tx_retry_flag = STP_SDIO_RETRY_CRC_ERROR; + else { + p_info->tx_retry_count = 0; + p_info->tx_retry_flag = STP_SDIO_RETRY_NONE; + stp_sdio_issue_fake_coredump + ("ABT: write_readsb retry ERROR"); + } + } else + stp_sdio_issue_fake_coredump("ABT: write_readsb retry ERROR"); + } + + /* clear rd index entry of Tx ring buffer */ + /*memset(buf_tx, 0, STP_SDIO_TX_ENTRY_SIZE); */ + /* George: clear STP-SDIO header only for debugging. */ + /*memset(buf_tx, 0, 4); */ + /* need clear??? skip it for debugging */ + + spin_lock_irqsave(&pb->rd_cnt_lock, pb->rd_irq_flag); + atomic_inc(&pb->rd_cnt); + /* TODO: [FixMe][George] check if full_flag needed? */ + if (pb->full_flag != MTK_WCN_BOOL_FALSE) { + pb->full_flag = MTK_WCN_BOOL_FALSE; + wake_up_interruptible(&pb->fullwait_q); + } + spin_unlock_irqrestore(&pb->rd_cnt_lock, pb->rd_irq_flag); + osal_do_gettimeofday(&old); + } else { + /* tx FIFO free space < packet size, wait next time */ +#if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXPERFDBG + stp_sdio_txperf_fifo_left += p_info->firmware_info.tx_fifo_size; + stp_sdio_txperf_to_send += four_byte_align_len; + ++stp_sdio_txperf_fifo_lmt_cnt; +#endif + + osal_do_gettimeofday(&now); + if ((now.tv_sec - old.tv_sec) > TX_NO_ACK_TIMEOUT_ASSERT) { + STPSDIO_PR_INFO("tx_fifo_size(%d), four_byte_align_len(%d), tx_packet_num(%d)\n", + p_info->firmware_info.tx_fifo_size, four_byte_align_len, + p_info->firmware_info.tx_packet_num); + STPSDIO_PR_INFO("No ack trigger assert, tx %d seconds later\n", + TX_NO_ACK_TIMEOUT_ASSERT); + stp_dbg_poll_cpupcr(5, 1, 1); + p_info->firmware_info.tx_fifo_size = STP_SDIO_TX_FIFO_SIZE; + p_info->firmware_info.tx_packet_num = 0; + if (pb->full_flag != MTK_WCN_BOOL_FALSE) { + pb->full_flag = MTK_WCN_BOOL_FALSE; + wake_up_interruptible(&pb->fullwait_q); + } + ret = mtk_wcn_wmt_assert_timeout(WMTDRV_TYPE_STP, 33, 0); + if (!ret) + STPSDIO_PR_INFO("trigger assert fail\n"); + } + break; + } + + stp_sdio_check_tx_sanity(p_info, 2); + } while (1); +} + +#else +static VOID stp_sdio_tx_wkr(struct work_struct *work) +{ + MTK_WCN_STP_SDIO_HIF_INFO *p_info; + UINT32 bus_txlen; + UINT32 four_byte_align_len; + PUINT8 buf_tx; + INT32 ret; + UINT32 idx; + MTK_WCN_STP_SDIO_PKT_BUF *pb; + struct timeval now; + UINT64 ts; + ULONG nsec; + + p_info = container_of(work, MTK_WCN_STP_SDIO_HIF_INFO, tx_work); + ret = HIF_SDIO_ERR_SUCCESS; + pb = &p_info->pkt_buf; + + /* 4 <0> Tx worker has been scheduled to send data */ + do { + /* handle tx complete count if any */ + stp_sdio_tx_wkr_comp(p_info); + stp_sdio_check_tx_sanity(p_info, 1); + + /* check if Tx ring buffer is empty */ + if ((atomic_read(&p_info->pkt_buf.wr_idx) == atomic_read(&p_info->pkt_buf.rd_idx)) + && (p_info->pkt_buf.full_flag == MTK_WCN_BOOL_FALSE)) { + STPSDIO_PR_DBG("Tx ring buffer is empty\n"); + break; + } + p_info->txwkr_flag = 0; + + /* George: no race condition here! Updating rd_idx content will not be + * put into more data by stp_sdio_tx + */ + /* Get Tx packet size from Tx ring buf */ +#if KMALLOC_UPDATE + buf_tx = gp_info->pkt_buf.tx_buf + + atomic_read(&p_info->pkt_buf.rd_idx) * STP_SDIO_TX_ENTRY_SIZE + 0; +#else + buf_tx = &p_info->pkt_buf.tx_buf[atomic_read(&p_info->pkt_buf.rd_idx)][0]; +#endif + bus_txlen = buf_tx[1]; + bus_txlen = (bus_txlen << 8) | buf_tx[0]; + + /* George: hw always count fifo in 4-byte aligned length */ + bus_txlen += 0x3; + bus_txlen &= ~(0x3UL); + four_byte_align_len = bus_txlen; + /* Sanity check: 4-byte aligned length shall not exceed HW FIFO Size */ + if (four_byte_align_len > STP_SDIO_TX_FIFO_SIZE) { + STPSDIO_PR_ERR("abnormal four_byte_align_len(%d) > TX_FIFO_SIZE(%ld)!!\n", + four_byte_align_len, STP_SDIO_TX_FIFO_SIZE); + } + + osal_ftrace_print("%s|S|bus_txlen(%d)\n", __func__, four_byte_align_len); + /* George: check if + * 1. tx FIFO free space is enough using 4-byte aligned length + * 2. tx max pkt count is not reached + */ + if ((p_info->firmware_info.tx_fifo_size >= four_byte_align_len) + && (p_info->firmware_info.tx_packet_num < STP_SDIO_TX_PKT_MAX_CNT)) { + /* George: refine block_size alignment with the assumption: block_size is 2^*x */ + if (bus_txlen > STP_SDIO_BLK_SIZE) { + bus_txlen += (STP_SDIO_BLK_SIZE - 1); + bus_txlen &= ~((UINT32) STP_SDIO_BLK_SIZE - 1); + } + + /* Sanity check: bus_txlen shall not exceed SW entry size */ + if (bus_txlen > STP_SDIO_TX_ENTRY_SIZE) { + STPSDIO_PR_ERR + ("abnormal bus_txlen(%d) > STP_SDIO_TX_ENTRY_SIZE(%ld)!!\n", + bus_txlen, STP_SDIO_TX_ENTRY_SIZE); + } + + ++(p_info->firmware_info.tx_packet_num); + /* decrease Tx FIFO size: using 4-byte aligned length! */ + p_info->firmware_info.tx_fifo_size -= four_byte_align_len; + /* record the SDIO packet size in packet size list: using 4-byte aligned length! */ + idx = p_info->tx_pkt_list.pkt_wr_cnt++ & STP_SDIO_TX_PKT_LIST_SIZE_MASK; + p_info->tx_pkt_list.pkt_size_list[idx] = four_byte_align_len; + p_info->tx_pkt_list.in_ts[idx] = jiffies; + p_info->tx_pkt_list.out_ts[idx] = 0; + + STPSDIO_PR_DBG("wr(0x%x, %ld) rd(0x%x, %ld), tx fifo(size:%d), pkt_num(%d)done\n", + p_info->tx_pkt_list.pkt_wr_cnt, + STP_SDIO_GET_PKT_AR_IDX(p_info->tx_pkt_list.pkt_wr_cnt), + p_info->tx_pkt_list.pkt_rd_cnt, + STP_SDIO_GET_PKT_AR_IDX(p_info->tx_pkt_list.pkt_rd_cnt), + p_info->firmware_info.tx_fifo_size, + p_info->firmware_info.tx_packet_num); + + /* port write the packet to CTDR */ + ret = stp_sdio_rw_retry(HIF_TYPE_WRITE_BUF, STP_SDIO_RETRY_LIMIT, p_info->sdio_cltctx, + CTDR, (PUINT32) buf_tx, bus_txlen); + STPSDIO_PR_DBG("write to CTDR done\n"); + +#if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXDBG + do { + osal_get_local_time(&ts, &nsec); + idx = stp_sdio_txdbg_cnt++ & STP_SDIO_TXDBG_COUNT_MASK; + /* skip clear buf */ + stp_sdio_txdbg_buffer[idx].ts = jiffies; + stp_sdio_txdbg_buffer[idx].l_sec = ts; + stp_sdio_txdbg_buffer[idx].l_nsec = nsec; + stp_sdio_txdbg_buffer[idx].bus_txlen = bus_txlen; + stp_sdio_txdbg_buffer[idx].four_byte_align_len = + four_byte_align_len; + /* store content */ + if (bus_txlen <= STP_SDIO_TX_ENTRY_SIZE) { + memcpy(&stp_sdio_txdbg_buffer[idx].tx_pkt_buf[0], buf_tx, + bus_txlen); + } else { + memcpy(&stp_sdio_txdbg_buffer[idx].tx_pkt_buf[0], buf_tx, + STP_SDIO_TX_ENTRY_SIZE); + STPSDIO_PR_ERR("abnormal bus_txlen(%d)!\n", bus_txlen); + } + } while (0); +#endif + + if (ret) { + STPSDIO_PR_ERR("get CTDR information Tx error(%d)!\n", ret); + if (p_info->retry_enable_flag) { + if (ret == -EIO || ret == -EILSEQ || ret == -EBUSY) + p_info->tx_retry_flag = STP_SDIO_RETRY_CRC_ERROR; + else { + p_info->tx_retry_count = 0; + p_info->tx_retry_flag = STP_SDIO_RETRY_NONE; + stp_sdio_issue_fake_coredump + ("ABT: write_readsb retry ERROR"); + } + } else + stp_sdio_issue_fake_coredump("ABT: write_readsb retry ERROR"); + } + + /* clear rd index entry of Tx ring buffer */ + /*memset(buf_tx, 0, STP_SDIO_TX_ENTRY_SIZE); */ + /* George: clear STP-SDIO header only for debugging. */ + /*memset(buf_tx, 0, 4); */ + /* need clear??? skip it for debugging */ + + spin_lock_irqsave(&p_info->pkt_buf.rd_idx_lock, + p_info->pkt_buf.rd_irq_flag); + /* release tx ring buffer */ + atomic_set(&p_info->pkt_buf.rd_idx, + (atomic_read(&p_info->pkt_buf.rd_idx) + 1) % STP_SDIO_TX_BUF_CNT); + /* Set Tx ring buffer is not full */ + if (p_info->pkt_buf.full_flag != MTK_WCN_BOOL_FALSE) { + p_info->pkt_buf.full_flag = MTK_WCN_BOOL_FALSE; + wake_up_interruptible(&p_info->pkt_buf.fullwait_q); + } + spin_unlock_irqrestore(&p_info->pkt_buf.rd_idx_lock, + p_info->pkt_buf.rd_irq_flag); + osal_do_gettimeofday(&old); + } else { +#if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXPERFDBG + stp_sdio_txperf_fifo_left += p_info->firmware_info.tx_fifo_size; + stp_sdio_txperf_to_send += four_byte_align_len; + ++stp_sdio_txperf_fifo_lmt_cnt; +#endif + /* (tx FIFO free space < packet size) or (the number of tx packets >= 7) */ + osal_do_gettimeofday(&now); + if ((now.tv_sec - old.tv_sec) > TX_NO_ACK_TIMEOUT_ASSERT) { + STPSDIO_PR_INFO("tx_fifo_size(%d), four_byte_align_len(%d), tx_packet_num(%d)\n", + p_info->firmware_info.tx_fifo_size, four_byte_align_len, + p_info->firmware_info.tx_packet_num); + STPSDIO_PR_INFO("No ack trigger assert, tx %d seconds later\n", + TX_NO_ACK_TIMEOUT_ASSERT); + stp_dbg_poll_cpupcr(5, 1, 1); + osal_ftrace_print("tx_fifo_size:%d, four_byte_align_len:%d, tx_packet_num(%d)\n", + p_info->firmware_info.tx_fifo_size, four_byte_align_len, + p_info->firmware_info.tx_packet_num); + p_info->firmware_info.tx_fifo_size = STP_SDIO_TX_FIFO_SIZE; + p_info->firmware_info.tx_packet_num = 0; + if (pb->full_flag != MTK_WCN_BOOL_FALSE) { + pb->full_flag = MTK_WCN_BOOL_FALSE; + wake_up_interruptible(&pb->fullwait_q); + } + ret = mtk_wcn_wmt_assert_timeout(WMTDRV_TYPE_STP, 33, 0); + if (!ret) + STPSDIO_PR_INFO("trigger assert fail\n"); + } + break; + } + + stp_sdio_check_tx_sanity(p_info, 2); + } while (1); + + osal_ftrace_print("%s|E|\n", __func__); +} +#endif /* end of stp_sdio_tx_wkr and STP_SDIO_NEW_TXRING */ + +/*! + * \brief Handle STP-SDIO Rx IRQ BH and read data from bus + * + * \details Handle STP-SDIO Rx IRQ buttom half and read data from bus according + * to the length read in Rx IRQ top half (stp_sdio_irq()) from CHISR + * + * \note rx_pkt_len read in stp_sdio_irq() from CHISR. No Rx IRQ would be + * triggered by FW before all Rx FIFO data is read by host driver. Do + * sanity check for this condition. + * + * \note HW Rx FIFO size is (2304 = 256*9) for MT6620 + * + * \param[IN] work Rx work struct work_struct pointer used by STP-SDIO + * + * \retval none. + */ +static VOID stp_sdio_rx_wkr(struct work_struct *work) +{ + PUINT8 bufp; + UINT32 bus_rxlen; + UINT32 chisr_rxlen; + INT32 ret; + INT32 ret_1; + UINT8 cccr_value = 0; + MTK_WCN_STP_SDIO_HIF_INFO *p_info; + + p_info = container_of(work, MTK_WCN_STP_SDIO_HIF_INFO, rx_work); + + /* 4 <0> receive data from CRDR */ + /* George: refine 4-byte alignment */ + chisr_rxlen = p_info->rx_pkt_len; + + + if (chisr_rxlen > STP_SDIO_RX_FIFO_SIZE) { + /* TODO: error handling! */ + STPSDIO_PR_ERR("abnormal chisr_rxlen(%d) rx_worker stop\n", chisr_rxlen); + return; + } + + bus_rxlen = chisr_rxlen; + bus_rxlen += 0x3; + bus_rxlen &= ~(0x3UL); + + /* George: refine block_size alignment with the assumption: BLK_SIZE is 2^x. */ + if (bus_rxlen > STP_SDIO_BLK_SIZE) { + bus_rxlen += (STP_SDIO_BLK_SIZE - 1); + bus_rxlen &= ~((UINT32) STP_SDIO_BLK_SIZE - 1); + } + + ret = stp_sdio_rw_retry(HIF_TYPE_READ_BUF, STP_SDIO_RETRY_LIMIT, p_info->sdio_cltctx, CRDR, + (PUINT32)(&(p_info->pkt_buf.rx_buf[0])), bus_rxlen); + if (p_info->retry_enable_flag) { + if (ret) { + if (ret == -EIO || ret == -EILSEQ || ret == -EBUSY) { + cccr_value = 0; + ret_1 = mtk_wcn_hif_sdio_f0_readb(p_info->sdio_cltctx, CCCR_F0, &cccr_value); + if (ret_1) + STPSDIO_PR_ERR("read CCCR_F0 fail(%d)\n", ret_1); + STPSDIO_PR_ERR("read CCCR_F0: (0x%x)\n", cccr_value); + cccr_value |= CCCR_F0_RX_CRC; + cccr_value |= CCCR_F0_RX_INT; + ret_1 = mtk_wcn_hif_sdio_f0_writeb(p_info->sdio_cltctx, CCCR_F0, cccr_value); + if (ret_1) + STPSDIO_PR_ERR("write CCCR_F0 fail(%d)\n", ret_1); + STPSDIO_PR_ERR("write CCCR_F0: (0x%x)\n", cccr_value); + cccr_value = 0; + ret_1 = mtk_wcn_hif_sdio_f0_readb(p_info->sdio_cltctx, CCCR_F0, &cccr_value); + if (ret_1) + STPSDIO_PR_ERR("read CCCR_F0 fail(%d)\n", ret_1); + STPSDIO_PR_ERR("read CCCR_F0: (0x%x)\n", cccr_value); + STPSDIO_PR_ERR("sdio read buffer happen crc error will be retry(%d)\n", ret); + p_info->rx_retry_count++; + if (p_info->rx_retry_count > STP_SDIO_RETRY_LIMIT) { + p_info->rx_retry_count = 0; + stp_sdio_issue_fake_coredump("ABT: sdio_readsb retry ERROR"); + } + } else { + p_info->rx_retry_count = 0; + stp_sdio_issue_fake_coredump("ABT: sdio_readsb retry ERROR"); + } + } else { + cccr_value = 0; + ret_1 = mtk_wcn_hif_sdio_f0_readb(p_info->sdio_cltctx, CCCR_F0, &cccr_value); + if (ret_1) + STPSDIO_PR_ERR("read CCCR_F0 fail(%d)\n", ret_1); + STPSDIO_PR_DBG("read CCCR_F0: (0x%x)\n", cccr_value); + cccr_value &= ~CCCR_F0_RX_CRC; + cccr_value |= CCCR_F0_RX_INT; + ret_1 = mtk_wcn_hif_sdio_f0_writeb(p_info->sdio_cltctx, CCCR_F0, cccr_value); + if (ret_1) + STPSDIO_PR_ERR("write CCCR_F0 fail(%d)\n", ret_1); + STPSDIO_PR_DBG("write CCCR_F0: (0x%x)\n", cccr_value); + cccr_value = 0; + ret_1 = mtk_wcn_hif_sdio_f0_readb(p_info->sdio_cltctx, CCCR_F0, &cccr_value); + if (ret_1) + STPSDIO_PR_ERR("read CCCR_F0 fail(%d)\n", ret_1); + STPSDIO_PR_DBG("read CCCR_F0: (0x%x)\n", cccr_value); + STPSDIO_PR_DBG("sdio read buffer success(%d)\n", ret); + + p_info->rx_retry_count = 0; + } + } else { + if (ret) { + STPSDIO_PR_HINT("set to p_info->rx_pkt_len 0\n"); + stp_sdio_issue_fake_coredump("ABT: sdio_readsb retry ERROR"); + } + } + if (ret) { + /* TODO: error handling! */ + STPSDIO_PR_ERR("read CRDR len(%d) rx error!(%d)\n", bus_rxlen, ret); + p_info->rx_pkt_len = 0; + return; + } + p_info->rx_pkt_len = 0; + STPSDIO_PR_HINT("set to p_info->rx_pkt_len 0\n"); +#if STP_SDIO_DBG_SUPPORT && STP_SDIO_RXDBG + do { + UINT32 idx = stp_sdio_rxdbg_cnt++ & (STP_SDIO_RXDBG_COUNT - 1); + /* skip clear buf */ + stp_sdio_rxdbg_buffer[idx].ts = jiffies; + stp_sdio_rxdbg_buffer[idx].chisr_rxlen = chisr_rxlen; + stp_sdio_rxdbg_buffer[idx].bus_rxlen = bus_rxlen; + /* store content */ + memcpy(&stp_sdio_rxdbg_buffer[idx].rx_pkt_buf[0], &p_info->pkt_buf.rx_buf[0], + bus_rxlen); + } while (0); +#endif + + bufp = &p_info->pkt_buf.rx_buf[4]; + + /* Notice: len = SDIO_HDR(4) + (STP Packet + padding)*N */ + /* George: refine sanity check */ + bus_rxlen = p_info->pkt_buf.rx_buf[1]; + bus_rxlen = (bus_rxlen << 8) | p_info->pkt_buf.rx_buf[0]; + STPSDIO_PR_DBG("bus_rxlen(%d) rx_len in chisr(%d)\n", bus_rxlen, chisr_rxlen); + if (bus_rxlen != chisr_rxlen) { + STPSDIO_PR_ERR("abnormal bus_rxlen(%d) in SDIO packet header!in chisr(%d)\n", + bus_rxlen, chisr_rxlen); + return; + } + if (p_info->pkt_buf.rx_buf[2] || p_info->pkt_buf.rx_buf[3]) { + STPSDIO_PR_ERR("abnormal p_info->pkt_buf.rx_buf[2](0x%02x) [3](0x%02x)\n", + p_info->pkt_buf.rx_buf[2], p_info->pkt_buf.rx_buf[3]); + return; + } + + if (bus_rxlen > STP_SDIO_HDR_SIZE) { + bus_rxlen -= STP_SDIO_HDR_SIZE; + /* transmit data to stp core driver */ + osal_ftrace_print("%s|B|parser|L|%d\n", __func__, bus_rxlen); + ret = mtk_wcn_stp_parser_data(bufp, bus_rxlen); + osal_ftrace_print("%s|A|parser|L|%d\n", __func__, bus_rxlen); +#if STP_SDIO_DBG_SUPPORT && (STP_SDIO_TXDBG || STP_SDIO_TXPERFDBG) + if (ret && (p_info->tx_dbg_dump_flag == 0)) { + p_info->tx_dbg_dump_flag = 1; + stp_sdio_txdbg_dump(); + } +#endif + } else { + STPSDIO_PR_ERR("abnormal rx length(%d, %d)\n", bus_rxlen, chisr_rxlen); + } + + /* [George]: no need to mask/unmask rx interrupt. chip/fw assert next rx int + * if and only if host reads all rx data. + */ +} + +#if STP_SDIO_NEW_IRQ_HANDLER +static INT32 stp_sdio_irq(const MTK_WCN_HIF_SDIO_CLTCTX clt_ctx) +{ + INT32 iRet = 0; + UINT32 chlcpr_value = 0; + UINT32 write_value = 0; + MTK_WCN_STP_SDIO_HIF_INFO *p_info = gp_info; + + STPSDIO_PR_HINT("disable IRQ\n"); + /*Disable Common interrupt output in CHLPCR */ +/* [COHEC_00006052] SW work-around solution: + * using CMD52 write instead of CMD53 write for CCIR, CHLPCR, CSDIOCSR + */ +#if COHEC_00006052 + write_value = C_FW_INT_EN_CLR; + iRet = stp_sdio_rw_retry(HIF_TYPE_WRITEB, STP_SDIO_RETRY_LIMIT, clt_ctx, CHLPCR, + &write_value, 0); +#else + write_value = C_FW_INT_EN_CLR; + iRet = stp_sdio_rw_retry(HIF_TYPE_WRITEL, STP_SDIO_RETRY_LIMIT, clt_ctx, CHLPCR, + &write_value, 0); +#endif /* COHEC_00006052 */ + if (iRet) + STPSDIO_PR_ERR("disalbe IRQ fail\n"); + else { + iRet = stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, clt_ctx, CHLPCR, + &chlcpr_value, 0); + if (iRet) + STPSDIO_PR_ERR("read CHLPCR fail. iRet(%d)\n", iRet); + else { + if (!(chlcpr_value & C_FW_INT_EN_SET)) { + STPSDIO_PR_DBG("disable COM IRQ okay (0x%x)\n", chlcpr_value); + p_info->irq_pending = 1; + + /*inform stp_sdio thread to to rx/tx job */ + STPSDIO_PR_DBG("signal stp_tx_rx\n"); + osal_trigger_event(&gp_info->tx_rx_event); + osal_ftrace_print("%s|stp_tx_rx\n", __func__); + } else + STPSDIO_PR_ERR + ("**********disable COM IRQ fail, don't signal stp-sdio thread******\n"); + } + + } + return 0; + +} + +#else +/*! + * \brief Handle STP-SDIO interrupt + * + * \details Top half interrupt handler of STP-SDIO. Most of Tx/Rx jobs are put + * to bottom half workers respectively. + * + * \note Rx ok interrupt shall be asserted by hw ONLY after last data are all + * read by driver. Do sanity check on rx_pkt_len and should be 0: rx BH + * finished. + * + * \note Tx complete count shall be handled atomically TH here and BH in + * tx_worker. + * + * \param[IN] clt_ctx A HIF-SDIO client context + * + * \retval 0 success + * \retval !=0 fail + */ +static INT32 stp_sdio_irq(const MTK_WCN_HIF_SDIO_CLTCTX clt_ctx) +{ + /*MTK_WCN_STP_SDIO_PRIVATE_INFO *p_priv; */ + MTK_WCN_STP_SDIO_HIF_INFO *p_info = NULL; + UINT32 chisr = 0; + UINT32 tx_comp; + INT32 ret; + +#if 0 + p_priv = mtk_wcn_hif_sdio_get_drvdata(clt_ctx); +TODO:[FixMe][George] do sanity check ! + p_info = &g_stp_sdio_host_info[p_priv->stp_sdio_host_idx]; +#endif + p_info = gp_info; + ret = HIF_SDIO_ERR_SUCCESS; + /* 4 <0> get CHLPCR information */ + if (stp_sdio_get_own_state() == OWN_CLR) + STPSDIO_PR_DBG("OWN on driver side!\n"); + else { + STPSDIO_PR_DBG("OWN on fw side!\n"); + if (stp_sdio_do_own_clr(0) == 0) + STPSDIO_PR_DBG("set OWN to driver side ok!\n"); + else { + STPSDIO_PR_ERR("set OWN to driver side error!\n"); + return -1; + } + + } +retry: + /* 4 <1> get CHISR information */ + ret = mtk_wcn_hif_sdio_readl(clt_ctx, CHISR, &chisr); + if (ret) { + /* 4 <1.1> get CHISR Rx error handling */ + /* TODO: error handling! */ + STPSDIO_PR_ERR("get CHISR information rx error,ret:%d\n", ret); + if (ret == -5) { + STPSDIO_PR_ERR("get CHISR DAT CRC error, retry.\n"); + ret = stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_MAX_RETRY_NUM, clt_ctx, CSR, &chisr, + 0); + } else + goto retry; + } + STPSDIO_PR_HINT("CHISR(0x%08x)\n", chisr); + if (chisr == 0x0) { + STPSDIO_PR_ERR("******CHISR == 0*****\n"); + return 0; + } + /* 4 <2> handle ownership back interrupt */ + if (chisr & FW_OWN_BACK_INT) { + STPSDIO_PR_INFO("FW_OWN_BACK_INT\n"); + + if (is_wait_ownback) { + is_wait_ownback = 0; + wake_up(&g_ownback_done); + } else { + mtk_wcn_stp_wmt_sdio_host_awake(); + /* if (cmb_bgf_eirq_cb) { */ + /* (*cmb_bgf_eirq_cb)(); */ + /* } */ + } + } + /* 4 <3> handle Rx interrupt */ + if (chisr & RX_DONE) { + /* STPSDIO_PR_INFO("RX_DONE_INT\n"); */ + + /* TODO: [FixMe][George] testing... */ + if (p_info->rx_pkt_len) + STPSDIO_PR_ERR("rx worker is not finished yet!!!(%d)\n", + p_info->rx_pkt_len); + + /* get Rx packet length */ + p_info->rx_pkt_len = (chisr & RX_PKT_LEN) >> 16; + STPSDIO_PR_HINT("rx_pkt_len(%d)\n", p_info->rx_pkt_len); + /* sanity check */ + if ((p_info->rx_pkt_len == 0) + || (p_info->rx_pkt_len > STP_SDIO_RX_FIFO_SIZE)) { + STPSDIO_PR_ERR + ("abnormal rx_pkt_len(%d) in CHISR(0x%08x) skip rx_worker\n", + p_info->rx_pkt_len, chisr); + p_info->rx_pkt_len = 0; + } else { + /* Before host driver read all rx data, chip/fw will not send more data + * to host. No need to mask rx interrupt. schedule rx worker to get data + * back and handle it. + */ + if (p_info->rx_pkt_len & 0x3) { + STPSDIO_PR_WARN + ("rx data len is not 4 bytes allignment, CHISR(0x%08x), rx len (%d).\n", + chisr, p_info->rx_pkt_len); + } +#if STP_SDIO_OWN_THREAD + /* tasklet_schedule(&p_info->tx_rx_job); */ + STPSDIO_PR_DBG("osal_trigger_event gp_info->tx_rx_event\n"); + osal_trigger_event(&gp_info->tx_rx_event); +#else + schedule_work(&p_info->rx_work); +#endif + } + } + /* 4 <4> handle Tx interrupt */ + if ((chisr & TX_EMPTY) || (chisr & TX_UNDER_THOLD)) { + STPSDIO_PR_DBG("Tx interrupt\n"); + /* get complete count */ + tx_comp = (chisr & TX_COMPLETE_COUNT) >> 4; +#if 0 + atomic_add(tx_comp, &p_info->firmware_info.tx_comp_num); + /* TODO:[FixMe][George]: debug and to be removed... */ + tx_comp = atomic_read(&p_info->firmware_info.tx_comp_num); +#else + tx_comp = atomic_add_return(tx_comp, &p_info->firmware_info.tx_comp_num); +#endif + if (tx_comp > STP_SDIO_TX_PKT_MAX_CNT) { + STPSDIO_PR_ERR("Abnormal accumulated comp count(%d) chisr(0x%x)\n", + tx_comp, chisr); + } + + /* move most of tx jobs to tx_worker */ + /* schedule tx worker for tx complete count and following tx data */ +#if STP_SDIO_OWN_THREAD + /* tasklet_schedule(&p_info->tx_rx_job); */ + STPSDIO_PR_DBG("osal_trigger_event gp_info->tx_rx_event\n"); + osal_trigger_event(&gp_info->tx_rx_event); +#else + schedule_work(&p_info->tx_work); +#endif + } + + return ret; +} +#endif /* STP_SDIO_NEW_IRQ_HANDLER */ + +#if STP_SDIO_POLL_OWNBACK_INTR +/***************************************************************************** + * FUNCTION + * stp_sdio_ownback_poll + * DESCRIPTION + * Poll ownback interrupt + * PARAMETERS + * 1. *func [IN] sdio driver function pointer + * 2. retryp [IN] polling retry times + * 3. delay_us [IN] polling delay (unit: us) + * RETURNS + * ret: Probe result + *****************************************************************************/ +static INT32 stp_sdio_ownback_poll(const MTK_WCN_HIF_SDIO_CLTCTX clt_ctx, UINT32 retry, UINT32 delay_us) +{ + INT32 ret; + UINT32 chlpcr = 0; + + do { +#if 0 + ret = stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, clt_ctx, CHISR, &chisr_value, + 0); +#endif + /* 20111020: change to poll CHLPCR instead of read-cleared CHISR */ + ret = stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, clt_ctx, CHLPCR, &chlpcr, 0); + if (ret) { + /* 4 <1.1> get CHISR Rx error handling */ + STPSDIO_PR_ERR("get CHLPCR information rx error!(%d)\n", ret); + return ret; + } + + /*if (chisr_value & FW_OWN_BACK_INT) { */ + if (chlpcr & C_FW_COM_DRV_OWN) { + /* 4 <2> handle ownership back interrupt */ + STPSDIO_PR_DBG("Driver own is polled!(%d)\n", retry); + gp_info->awake_flag = 1; + break; + } + osal_usleep_range(delay_us, delay_us); + } while (retry-- > 0); + + /*return (chisr_value & FW_OWN_BACK_INT) ? 0 : -HIF_SDIO_ERR_FAIL; */ + return (chlpcr & C_FW_COM_DRV_OWN) ? 0 : -HIF_SDIO_ERR_FAIL; +} +#endif /* STP_SDIO_POLL_OWNBACK_INTR */ + +/***************************************************************************** + * FUNCTION + * stp_sdio_probe + * DESCRIPTION + * Probe function of SDIO driver + * PARAMETERS + * 1. *func [IN] sdio driver function pointer + * 2. *id [IN] sdio function id + * RETURNS + * ret: Probe result + *****************************************************************************/ +/* typedef INT32 (*MTK_WCN_HIF_SDIO_PROBE)(MTK_WCN_HIF_SDIO_CLTCTX, const MTK_WCN_HIF_SDIO_FUNCINFO *); */ +static INT32 stp_sdio_probe(const MTK_WCN_HIF_SDIO_CLTCTX clt_ctx, + const MTK_WCN_HIF_SDIO_FUNCINFO *sdio_func_infop) +{ + INT32 ret = HIF_SDIO_ERR_SUCCESS; + UINT32 i = 0, chlcpr_value = 0; + UINT32 write_value = 0; + + STPSDIO_PR_DBG("sdio_cltctx: 0x%08x\n", clt_ctx); + + if (g_stp_sdio_host_count) { + STPSDIO_PR_ERR("g_stp_sdio_host_count(%d) probed already!\n", + g_stp_sdio_host_count); + return -1; + } + /* 4 <1> check if input pointer is valid */ + if (g_stp_sdio_host_info.sdio_cltctx == clt_ctx) { + STPSDIO_PR_WARN("sdio_cltctx(%d) already probed!\n", clt_ctx); + return 0; + } + /* 4 <2> allocate host inform structure and initialize private variables */ + /* init host info private variables */ + g_stp_sdio_host_info.sdio_cltctx = clt_ctx; + + /* init Tx packet ring buffer */ + for (i = 0; i < STP_SDIO_TX_BUF_CNT; ++i) { +#if KMALLOC_UPDATE + UINT8 *pData = g_stp_sdio_host_info.pkt_buf.tx_buf + i * STP_SDIO_TX_ENTRY_SIZE + 0; + + memset(pData, 0, STP_SDIO_TX_ENTRY_SIZE); +#else + memset(&g_stp_sdio_host_info.pkt_buf.tx_buf[i][0], 0, + sizeof(g_stp_sdio_host_info.pkt_buf.tx_buf[i])); +#endif + } + osal_sleepable_lock_init(&fake_coredump_lock); + +#if STP_SDIO_NEW_TXRING + spin_lock_init(&g_stp_sdio_host_info.pkt_buf.rd_cnt_lock); + atomic_set(&g_stp_sdio_host_info.pkt_buf.wr_cnt, 0); + atomic_set(&g_stp_sdio_host_info.pkt_buf.rd_cnt, 0); +#else + /*g_stp_sdio_host_info.pkt_buf.rd_idx_lock = SPIN_LOCK_UNLOCKED; */ + spin_lock_init(&g_stp_sdio_host_info.pkt_buf.rd_idx_lock); + atomic_set(&g_stp_sdio_host_info.pkt_buf.wr_idx, 0); + atomic_set(&g_stp_sdio_host_info.pkt_buf.rd_idx, 0); +#endif + g_stp_sdio_host_info.pkt_buf.full_flag = MTK_WCN_BOOL_FALSE; + + /* init wait queue head for Tx ring buf full */ + init_waitqueue_head(&g_stp_sdio_host_info.pkt_buf.fullwait_q); + + /* init Tx packet size list information */ + memset(&g_stp_sdio_host_info.tx_pkt_list.pkt_size_list[0], 0, + sizeof(g_stp_sdio_host_info.tx_pkt_list.pkt_size_list)); + g_stp_sdio_host_info.tx_pkt_list.pkt_rd_cnt = 0; + g_stp_sdio_host_info.tx_pkt_list.pkt_wr_cnt = 0; + + /* init Rx interrupt mask */ + /* g_stp_sdio_host_info.rx_intr_mask = MTK_WCN_BOOL_FALSE; */ + + /* init firmware related information */ + g_stp_sdio_host_info.firmware_info.tx_fifo_size = STP_SDIO_TX_FIFO_SIZE; + g_stp_sdio_host_info.firmware_info.tx_packet_num = 0; + atomic_set(&g_stp_sdio_host_info.firmware_info.tx_comp_num, 0); + + /* init SDIO data path retry flag */ + g_stp_sdio_host_info.retry_enable_flag = 0; + g_stp_sdio_host_info.tx_retry_flag = STP_SDIO_RETRY_NONE; + + g_stp_sdio_host_info.isr_check_complete.timeoutValue = 1000; + osal_signal_init(&g_stp_sdio_host_info.isr_check_complete); + +#if STP_SDIO_OWN_THREAD + /* tasklet_init(&g_stp_sdio_host_info.tx_rx_job, stp_sdio_tx_rx_handling, */ + /* (unsigned long) &g_stp_sdio_host_info); */ + /* Create stp_sdio_tx_rx_thread, in suspend state */ + g_stp_sdio_host_info.irq_pending = 0; + g_stp_sdio_host_info.sleep_flag = 0; + g_stp_sdio_host_info.wakeup_flag = 0; + osal_event_init(&g_stp_sdio_host_info.tx_rx_event); + g_stp_sdio_host_info.tx_rx_thread.pThreadFunc = stp_sdio_tx_rx_handling; + g_stp_sdio_host_info.tx_rx_thread.pThreadData = (PVOID) &g_stp_sdio_host_info; + g_stp_sdio_host_info.tx_dbg_dump_flag = 0; + osal_strncpy((PINT8)&g_stp_sdio_host_info.tx_rx_thread.threadName, + "stp_sdio_tx_rx", osal_sizeof(g_stp_sdio_host_info.tx_rx_thread.threadName)); + ret = osal_thread_create(&g_stp_sdio_host_info.tx_rx_thread); + if (ret < 0) { + STPSDIO_PR_ERR("osal_thread_create fail...: %p\n", + g_stp_sdio_host_info.tx_rx_thread.pThread); + return ret; + } +#else + /* init tx_tasklet and rx work_queue */ + INIT_WORK(&g_stp_sdio_host_info.tx_work, stp_sdio_tx_wkr); + INIT_WORK(&g_stp_sdio_host_info.rx_work, stp_sdio_rx_wkr); +#endif + /* init stp sdio host private information *//* TODO: [FixMe][George] Still need this? */ + g_stp_sdio_host_info.private_info.stp_sdio_host_idx = g_stp_sdio_host_count; + mtk_wcn_hif_sdio_set_drvdata(clt_ctx, &g_stp_sdio_host_info.private_info); + + ++g_stp_sdio_host_count; + + /* 4 <3> request firmware-own back */ +/* [COHEC_00006052] SW work-around solution: */ +/* using CMD52 write instead of CMD53 write for CCIR, CHLPCR, CSDIOCSR */ +#if COHEC_00006052 + write_value = (C_FW_OWN_REQ_CLR >> 8); + ret = stp_sdio_rw_retry(HIF_TYPE_WRITEB, STP_SDIO_RETRY_LIMIT, clt_ctx, (UINT32)(CHLPCR + 0x1), + &write_value, 0); +#else + write_value = C_FW_OWN_REQ_CLR; + ret = stp_sdio_rw_retry(HIF_TYPE_WRITEL, STP_SDIO_RETRY_LIMIT, clt_ctx, CHLPCR, + &write_value, 0); +#endif /* COHEC_00006052 */ + if (ret) { + STPSDIO_PR_ERR("request FW-Own back fail!(%d)\n", ret); + goto out; + } + STPSDIO_PR_DBG("request FW-Own back done\n"); + +#if STP_SDIO_POLL_OWNBACK_INTR + /* 4 <3.1> polling own back bit */ + ret = stp_sdio_ownback_poll(clt_ctx, 10, 100); + if (ret) { + STPSDIO_PR_ERR("poll FW-Own back fail!(%d)\n", ret); + goto out; + } +#endif + /* 4 <4.0> enable irq flag in HIF-SDIO */ + mtk_wcn_hif_sdio_enable_irq(clt_ctx, MTK_WCN_BOOL_TRUE); + /* 4 <4> enabling all host interrupt except abnormal ones */ + /*write_value = (CHISR_EN_15_7 | CHISR_EN_3_0);*/ /* enable CHISR interrupt output */ + /*ret = stp_sdio_rw_retry(HIF_TYPE_WRITEL, STP_SDIO_RETRY_LIMIT, clt_ctx, CHIER, &write_value, 0);*/ + write_value = (FIRMWARE_INT | TX_FIFO_OVERFLOW | FW_INT_IND_INDICATOR | TX_COMPLETE_COUNT + | TX_UNDER_THOLD | TX_EMPTY | RX_DONE); + ret = stp_sdio_rw_retry(HIF_TYPE_WRITEL, STP_SDIO_RETRY_LIMIT, clt_ctx, CHIER, + &write_value, 0); + if (ret) { + STPSDIO_PR_ERR("set interrupt output fail!(%d)\n", ret); + goto out; + } + STPSDIO_PR_DBG("set interrupt output done\n"); +/* [COHEC_00006052] SW work-around solution: */ +/* using CMD52 write instead of CMD53 write for CCIR, CHLPCR, CSDIOCSR */ +#if COHEC_00006052 + write_value = C_FW_INT_EN_SET; + ret = stp_sdio_rw_retry(HIF_TYPE_WRITEB, STP_SDIO_RETRY_LIMIT, clt_ctx, CHLPCR, &write_value, + 0); /* enable interrupt */ +#else + write_value = C_FW_INT_EN_SET; + ret = stp_sdio_rw_retry(HIF_TYPE_WRITEL, STP_SDIO_RETRY_LIMIT, clt_ctx, CHLPCR, &write_value, + 0); /* enable interrupt */ +#endif /* COHEC_00006052 */ + if (ret) { + STPSDIO_PR_ERR("enable interrupt fail!(%d)\n", ret); + goto out; + } + ret = stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, clt_ctx, CHLPCR, &chlcpr_value, + 0); + if (ret) { + STPSDIO_PR_ERR("Read CHLPCR fail!(%d)\n", ret); + goto out; + } else { + if (chlcpr_value & C_FW_INT_EN_SET) + STPSDIO_PR_DBG("enable interrupt okay (0x%x)\n", chlcpr_value); + } + + STPSDIO_PR_DBG("enable interrupt done\n"); + +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT + stp_sdio_deep_sleep_flag_set(MTK_WCN_BOOL_FALSE); +#endif + +#if STP_SDIO_OWN_THREAD + ret = osal_thread_run(&g_stp_sdio_host_info.tx_rx_thread); + if (ret < 0) { + STPSDIO_PR_ERR("osal_thread_run fail...\n"); + goto out; + } +#endif + + /* 4 <5> register mtk_wcn_stp_if_tx() to stp driver */ + mtk_wcn_stp_register_if_tx(STP_SDIO_IF_TX, (MTK_WCN_STP_IF_TX) stp_sdio_tx); + +#if 0 /* controlled by 6620_launcher & WMT */ + /*set STP sdio mode */ + pr_warn(DFT_TAG "%s: set stp sdio mode\n", __func__); + mtk_wcn_stp_set_sdio_mode(1); + + /*indicate the stp the sdio ready */ + pr_warn(DFT_TAG "%s: stp enable\n", __func__); + mtk_wcn_stp_enable(1); +#endif + +out: + /* 4 <6> error handling */ + /* TODO: error handling */ + if (ret) { +#if STP_SDIO_OWN_THREAD + osal_thread_destroy(&g_stp_sdio_host_info.tx_rx_thread); +#endif + if (g_stp_sdio_host_count > 0) + --g_stp_sdio_host_count; + } + + return ret; +} + +/***************************************************************************** + * FUNCTION + * stp_sdio_probe + * DESCRIPTION + * SDIO hardware remove function. + * PARAMETERS + * *func [IN] SDIO driver handler pointer. + * RETURNS + * none. + *****************************************************************************/ +static INT32 stp_sdio_remove(const MTK_WCN_HIF_SDIO_CLTCTX clt_ctx) +{ +#if 0 + MTK_WCN_STP_SDIO_PRIVATE_INFO *p_priv; + + p_priv = mtk_wcn_hif_sdio_get_drvdata(clt_ctx); +#endif + + if (g_stp_sdio_host_info.sdio_cltctx == clt_ctx) + STPSDIO_PR_DBG("sdio_cltctx(%d) found\n", clt_ctx); + else { + STPSDIO_PR_ERR("sdio_cltctx(%d) not found\n", clt_ctx); + return -1; + } + osal_sleepable_lock_deinit(&fake_coredump_lock); + if (g_stp_sdio_host_count > 0) + --g_stp_sdio_host_count; + /* 4 <0> disable irq flag in HIF-SDIO */ + mtk_wcn_hif_sdio_enable_irq(clt_ctx, MTK_WCN_BOOL_FALSE); + /* 4 <1> unregister if_tx() function */ + mtk_wcn_stp_register_if_tx(STP_SDIO_IF_TX, NULL); + + /* <2> stop Tx tasklet/Rx work queue of the host */ +#if STP_SDIO_OWN_THREAD + /* tasklet_kill(&g_stp_sdio_host_info.tx_rx_job); */ + /* STPSDIO_PR_INFO("kill tasklet finished\n"); */ + osal_thread_destroy(&g_stp_sdio_host_info.tx_rx_thread); + osal_event_deinit(&g_stp_sdio_host_info.tx_rx_event); + osal_signal_deinit(&g_stp_sdio_host_info.isr_check_complete); + STPSDIO_PR_DBG("destroy STP-SDIO tx_rx_thread\n"); +#else + flush_scheduled_work(); + STPSDIO_PR_INFO("flush scheduled work end\n"); +#endif + + /* 4 <3> return ownership to firmware of the host */ + /* TODO: check set which register ! */ + + /* 4 <4> clear the host struct list */ + stp_sdio_host_info_op(1); + + + STPSDIO_PR_DBG("clear g_stp_sdio_host_info[p_priv->stp_sdio_host_idx] done\n"); + + return 0; +} + +INT32 stp_sdio_rw_retry(ENUM_STP_SDIO_HIF_TYPE_T type, UINT32 retry_limit, + MTK_WCN_HIF_SDIO_CLTCTX clt_ctx, UINT32 offset, PUINT32 pData, UINT32 len) +{ + INT32 ret = -1; + INT32 ret_1 = -1; + UINT32 value = 0; + INT32 retry_flag = 0; + + UINT32 card_id = CLTCTX_CID(clt_ctx); + + if (card_id != 0x6630 && card_id != 0x6632) { + STPSDIO_PR_LOUD("card_id is :0x%x, does not support CSR (Common Snapshot Register)\n", + card_id); + retry_limit = 1; + } + STPSDIO_PR_LOUD("clt_ctx:0x%x, offset:0x%x, retry_limit:%d\n", clt_ctx, offset, retry_limit); + + retry_limit = retry_limit == 0 ? 1 : retry_limit; + retry_limit = retry_limit > STP_SDIO_MAX_RETRY_NUM ? STP_SDIO_MAX_RETRY_NUM : retry_limit; + + while (retry_limit > 0) { + switch (type) { + case HIF_TYPE_READB: + if (retry_flag) + ret = mtk_wcn_hif_sdio_readb(clt_ctx, CSR, (PUINT8)pData); + else + ret = mtk_wcn_hif_sdio_readb(clt_ctx, offset, (PUINT8)pData); + break; + case HIF_TYPE_READL: + if (retry_flag) + ret = mtk_wcn_hif_sdio_readl(clt_ctx, CSR, pData); + else + ret = mtk_wcn_hif_sdio_readl(clt_ctx, offset, pData); + break; + case HIF_TYPE_READ_BUF: + ret = mtk_wcn_hif_sdio_read_buf(clt_ctx, offset, pData, len); + break; + case HIF_TYPE_WRITEB: + ret = mtk_wcn_hif_sdio_writeb(clt_ctx, offset, (UINT8)(*pData)); + break; + case HIF_TYPE_WRITEL: + ret = mtk_wcn_hif_sdio_writel(clt_ctx, offset, *pData); + break; + case HIF_TYPE_WRITE_BUF: + ret = mtk_wcn_hif_sdio_write_buf(clt_ctx, offset, pData, len); + break; + default: + STPSDIO_PR_ERR("unknown hif sdio type!\n"); + goto exit; + } + + if (ret) { + STPSDIO_PR_ERR("sdio read or write failed, ret:%d\n", ret); + if (ret == -ETIMEDOUT) { + ret_1 = mtk_wcn_hif_sdio_readl(clt_ctx, CCIR, &value); + STPSDIO_PR_ERR("sdio read or write timeout, ret:%d ret_1:%d, read chip id:%x\n", + ret, ret_1, value); + stp_sdio_dump_register(); + } + /* sdio CRC error read CSR */ + if (type == HIF_TYPE_READ_BUF || type == HIF_TYPE_WRITE_BUF) { + if (ret == -EIO || ret == -EILSEQ || ret == -EBUSY) { + ret_1 = mtk_wcn_hif_sdio_abort(clt_ctx); + if (ret_1) + STPSDIO_PR_ERR("sdio crc error send abort fail, ret_1:%d\n", + ret_1); + else + STPSDIO_PR_ERR("sdio crc error send abort success, ret_1:%d\n", + ret_1); + goto exit; + } + } else + retry_flag = 1; + } else { + STPSDIO_PR_LOUD("CR:0x:%x value:0x%x\n", offset, *pData); + break; + } + retry_limit--; + } + +exit: + return ret; +} + + +#if STP_SDIO_DBG_SUPPORT && STP_SDIO_RXDBG + +/*! + * \brief /proc debug read interface and dump rx dbg information + * + * \details Dump all rx debug information to console. + * + * \retval 0 success + */ +ssize_t stp_sdio_rxdbg_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + UINT32 idx; + UINT32 i; + UINT32 j; + PUINT8 pbuf; + UINT32 len; + + if (*f_pos > 0) + return 0; + + for (i = 0; i < STP_SDIO_RXDBG_COUNT; ++i) { + idx = (stp_sdio_rxdbg_cnt - 1 - i) & STP_SDIO_TXDBG_COUNT_MASK; + len = stp_sdio_rxdbg_buffer[idx].bus_rxlen; + if (len == 0) { + pr_warn(DFT_TAG "idx(0x%x) 0 == len dump skip\n", + stp_sdio_rxdbg_cnt); + } + pr_warn(DFT_TAG "idx(0x%x) chisr_rxlen(%d) bus_rxlen(%d) ts(%d)\n", + stp_sdio_rxdbg_cnt, stp_sdio_rxdbg_buffer[idx].chisr_rxlen, len, + stp_sdio_rxdbg_buffer[idx].ts); + for (j = 0; j < STP_SDIO_RX_BUF_SIZE && j < len; j += 16) { + pbuf = &stp_sdio_rxdbg_buffer[idx].rx_pkt_buf[j]; + pr_warn(DFT_TAG "[0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x ", + pbuf[0], pbuf[1], pbuf[2], pbuf[3], pbuf[4], pbuf[5], pbuf[6], + pbuf[7]); + pr_warn(DFT_TAG "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x]\n", + pbuf[8], pbuf[9], pbuf[10], pbuf[11], pbuf[12], pbuf[13], + pbuf[14], pbuf[15]); + msleep(20); + } + pr_warn(DFT_TAG "dump ok\n"); + } + + return 0; +} + +/*! + * \brief /proc debug write interface. do nothing. + * + * \details + * + * \retval 0 success + */ +ssize_t stp_sdio_rxdbg_write(struct file *filp, const char __user *buf, size_t count, + loff_t *f_pos) +{ + ULONG len = count; + + pr_warn(DFT_TAG "write parameter len = %lu\n\r", len); + + return len; +} + +/*! + * \brief /proc initial procedures. Initialize global debugging information. + * + * \details Setup entry for /proc debugging for rx + * + * \retval 0 success + */ +INT32 stp_sdio_rxdbg_setup(VOID) +{ + stp_sdio_rxdbg_cnt = 0; + + gStpSdioRxDbgEntry = proc_create(STP_SDIO_RXDBG_PROCNAME, 0644, NULL, &stp_sdio_rxdbg_fops); + if (gStpSdioRxDbgEntry == NULL) { + pr_warn(DFT_TAG "Unable to create /proc entry\n\r"); + return -1; + } + + return 0; +} + +/*! + * \brief /proc de-init procedures. + * + * \details remove entry for /proc debugging for rx + * + * \retval 0 success + */ +INT32 stp_sdio_rxdbg_remove(VOID) +{ + if (gStpSdioRxDbgEntry != NULL) + proc_remove(gStpSdioRxDbgEntry); + + return 0; +} +#endif + +#if STP_SDIO_DBG_SUPPORT && (STP_SDIO_TXDBG || STP_SDIO_TXPERFDBG) + +static VOID stp_sdio_txperf_dump(VOID) +{ +#if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXPERFDBG + UINT32 cnt; + UINT32 fifo; + UINT32 data; + UINT32 wkr; + UINT32 pkt_num; + UINT32 lmt_cnt; + + /* get debug counter snapshot */ + cnt = stp_sdio_txperf_fifo_lmt_cnt; + fifo = stp_sdio_txperf_fifo_left; + data = stp_sdio_txperf_to_send; + + wkr = stp_sdio_txperf_worker_cnt; + pkt_num = stp_sdio_txperf_txed_pkt_num; + lmt_cnt = stp_sdio_txperf_pkt_num_lmt_cnt; + + pr_warn(DFT_TAG "txwait_fifo_left(%d), txwait_to_send(%d), txwait_count(%d)\n", + fifo, data, cnt); + if (cnt) + pr_warn(DFT_TAG "avg left(%d), to_send(%d)\n", (fifo / cnt), (data / cnt)); + pr_warn(DFT_TAG "tx_worker_cnt(%d), pkt_num(%d), pkt_num_lmt_cnt(%d)\n", + wkr, pkt_num, lmt_cnt); + +#endif +} + +VOID stp_sdio_dump_info(MTK_WCN_STP_SDIO_HIF_INFO *p_info) +{ + STPSDIO_PR_INFO("stp_is_ready(%d) irq_pending(%d) tx_packet_num(%d) rx_pkt_len(%d)\n", + mtk_wcn_stp_is_ready(), p_info->irq_pending, + p_info->firmware_info.tx_packet_num, p_info->rx_pkt_len); + STPSDIO_PR_INFO("sleep_flag(%d) wakeup_flag(%d) awake_flag(%d) txwkr_flag(%d)\n", + p_info->sleep_flag, p_info->wakeup_flag, p_info->awake_flag, p_info->txwkr_flag); + STPSDIO_PR_INFO("wr_idx(%d), rd_idx(%d), full_flag(%d), tx_fifo_size(%d)\n", + atomic_read(&p_info->pkt_buf.wr_idx), atomic_read(&p_info->pkt_buf.rd_idx), + p_info->pkt_buf.full_flag, p_info->firmware_info.tx_fifo_size); +} + +VOID stp_sdio_txdbg_dump(VOID) +{ +#if STP_SDIO_TXDBG + UINT32 idx; + UINT32 i; + UINT32 j; + PUINT8 pbuf; + UINT32 len; + + for (i = 0; i < STP_SDIO_TXDBG_COUNT; ++i) { + idx = (stp_sdio_txdbg_cnt - 1 - i) & STP_SDIO_TXDBG_COUNT_MASK; + len = stp_sdio_txdbg_buffer[idx].bus_txlen; + if (len == 0) { + STPSDIO_PR_INFO("idx(%x) 0 == len dump skip\n", idx); + continue; + } + + len = len > STP_SDIO_TXDBG_MAX_SIZE ? STP_SDIO_TXDBG_MAX_SIZE : len; + STPSDIO_PR_INFO( + "stp_sdio_txdbg_buffer idx(%x) bus_txlen(0x%x, %d), time[%llu.%06lu]\n", + idx, len, len, stp_sdio_txdbg_buffer[idx].l_sec, stp_sdio_txdbg_buffer[idx].l_nsec); + for (j = 0; j < STP_SDIO_TX_ENTRY_SIZE && j < len; j += 16) { + pbuf = &stp_sdio_txdbg_buffer[idx].tx_pkt_buf[j]; + STPSDIO_PR_INFO("[0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x]\n", + pbuf[0], pbuf[1], pbuf[2], pbuf[3], pbuf[4], pbuf[5], pbuf[6], pbuf[7]); + STPSDIO_PR_INFO("[0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x]\n", + pbuf[8], pbuf[9], pbuf[10], pbuf[11], pbuf[12], pbuf[13], pbuf[14], + pbuf[15]); + msleep(20); + } + STPSDIO_PR_INFO("stp_sdio_txdbg_buffer dump ok\n"); + } +#if STP_TXDBG + for (i = 0; i < STP_SDIO_TXDBG_COUNT; ++i) { + idx = (stp_sdio_txdbg_cnt - 1 - i) & STP_SDIO_TXDBG_COUNT_MASK; + len = stp_sdio_txdbg_buffer[idx].bus_txlen; + STPSDIO_PR_INFO( + "stp_sdio_txdbg_buffer idx(%x) bus_txlen(0x%x, %d) ts(%d)\n", idx, len, len, + stp_sdio_txdbg_buffer[idx].ts); + } + STPSDIO_PR_INFO( + "Dump tx info: pkt_num(%d) fifo(%d) pkt_list.rd(0x%x, %ld) pkt_list.wr(0x%x, %ld)\n", + gp_info->firmware_info.tx_packet_num, gp_info->firmware_info.tx_fifo_size, + gp_info->tx_pkt_list.pkt_rd_cnt, + STP_SDIO_GET_PKT_AR_IDX(gp_info->tx_pkt_list.pkt_rd_cnt), + gp_info->tx_pkt_list.pkt_wr_cnt, + STP_SDIO_GET_PKT_AR_IDX(gp_info->tx_pkt_list.pkt_wr_cnt)); + + for (i = 0; i < STP_SDIO_TX_PKT_LIST_SIZE; ++i) { + idx = STP_SDIO_GET_PKT_AR_IDX(gp_info->tx_pkt_list.pkt_wr_cnt - 1 - i); + STPSDIO_PR_INFO( + "tx_pkt_list idx(0x%x, %d) size(0x%x, %d), in_ts(%d), out_ts(%d)\n", + (gp_info->tx_pkt_list.pkt_wr_cnt - 1 - i), idx, + gp_info->tx_pkt_list.pkt_size_list[idx], + gp_info->tx_pkt_list.pkt_size_list[idx], gp_info->tx_pkt_list.in_ts[idx], + gp_info->tx_pkt_list.out_ts[idx]); + } + +#if STP_SDIO_NEW_TXRING + STPSDIO_PR_INFO("\n\ndump pkt_buf.tx_buf: rd(%d) wr(%d) full(%d)\n", + atomic_read(&gp_info->pkt_buf.rd_cnt), atomic_read(&gp_info->pkt_buf.wr_cnt), + gp_info->pkt_buf.full_flag); +#else + STPSDIO_PR_INFO("\n\ndump pkt_buf.tx_buf: rdi(%d) wri(%d) full(%d)\n", + atomic_read(&gp_info->pkt_buf.rd_idx), atomic_read(&gp_info->pkt_buf.wr_idx), + gp_info->pkt_buf.full_flag); +#endif + + for (i = 0; i < STP_SDIO_TX_BUF_CNT; ++i) { +#if STP_SDIO_NEW_TXRING + idx = (atomic_read(&gp_info->pkt_buf.wr_cnt) - 1 - i) & STP_SDIO_TX_BUF_CNT_MASK; + len = gp_info->pkt_buf.tx_buf_sz[idx]; +#else + idx = (atomic_read(&gp_info->pkt_buf.wr_idx) - 1 - i + STP_SDIO_TX_BUF_CNT) % + STP_SDIO_TX_BUF_CNT; +#if KMALLOC_UPDATE + len = *(gp_info->pkt_buf.tx_buf + idx * STP_SDIO_TX_ENTRY_SIZE + 1); + len = (len << 8) | *(gp_info->pkt_buf.tx_buf + idx * STP_SDIO_TX_ENTRY_SIZE + 0); +#else + len = gp_info->pkt_buf.tx_buf[idx][1]; + len = (len << 8) | gp_info->pkt_buf.tx_buf[idx][0]; +#endif + +#endif + STPSDIO_PR_INFO("pkt_buf.tx_buf idx(%x) ts(%d) len(%d), time[%llu.%06lu]\n", + idx, gp_info->pkt_buf.tx_buf_ts[idx], len, + gp_info->pkt_buf.tx_buf_local_ts[idx], gp_info->pkt_buf.tx_buf_local_nsec[idx]); + if (len == 0) { + STPSDIO_PR_INFO("idx(%x) 0 == len dump skip\n", idx); + continue; + } + len = len > STP_SDIO_TXDBG_MAX_SIZE ? STP_SDIO_TXDBG_MAX_SIZE : len; + for (j = 0; j < STP_SDIO_TX_ENTRY_SIZE && j < len; j += 16) { +#if KMALLOC_UPDATE + pbuf = gp_info->pkt_buf.tx_buf + idx * STP_SDIO_TX_ENTRY_SIZE + j; +#else + pbuf = &gp_info->pkt_buf.tx_buf[idx][j]; +#endif + STPSDIO_PR_INFO("[0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x]\n", + pbuf[0], pbuf[1], pbuf[2], pbuf[3], pbuf[4], pbuf[5], pbuf[6], + pbuf[7]); + STPSDIO_PR_INFO("[0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x]\n", + pbuf[8], pbuf[9], pbuf[10], pbuf[11], pbuf[12], pbuf[13], pbuf[14], + pbuf[15]); + msleep(20); + } + STPSDIO_PR_INFO("pkt_buf.tx_buf dump ok\n"); + } +#endif /*end of STP_TXDBG*/ +#endif /* end of STP_SDIO_TXDBG */ +} + +/*! + * \brief /proc debug read interface and dump tx dbg information + * + * \details Dump all tx debug information to console. + * + * \retval 0 success + */ +ssize_t stp_sdio_txdbg_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + if (*f_pos > 0) + return 0; + + stp_sdio_txdbg_dump(); + stp_sdio_txperf_dump(); + + return 0; +} + +/*! + * \brief /proc debug write interface. do nothing. + * + * \details + * + * \retval 0 success + */ +ssize_t stp_sdio_txdbg_write(struct file *filp, const char __user *buf, size_t count, + loff_t *f_pos) +{ + ULONG len = count; + + pr_warn(DFT_TAG "write parameter len = %lu\n\r", len); + + return len; +} + +/*! + * \brief /proc debug read interface and dump tx dbg information + * + * \details Dump all tx debug information to console. + * + * \retval 0 success + */ +ssize_t stp_sdio_own_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + if (*f_pos > 0) + return 0; + + return 0; +} + +/*! + * \brief /proc debug write interface. do nothing. + * + * \details + * + * \retval 0 success + */ +ssize_t stp_sdio_own_write(struct file *filp, const char __user *buffer, size_t count, + loff_t *f_pos) +{ + ULONG len = count; + PINT8 pBuf = NULL; + PINT8 pToken = NULL; + PINT8 pDelimiter = " \t"; + INT32 x = 0; + INT8 buf[128] = { 0 }; + LONG res = 0; + + if (len >= osal_sizeof(buf)) { + STPSDIO_PR_ERR("input handling fail!\n"); + len = osal_sizeof(buf) - 1; + return -1; + } + + if (copy_from_user(buf, buffer, len)) { + STPSDIO_PR_ERR("copy_from_user error.\n"); + return -EFAULT; + } + + buf[len] = '\0'; + pBuf = buf; + pToken = osal_strsep(&pBuf, pDelimiter); + if (pToken != NULL) { + osal_strtol(pToken, 16, &res); + x = (INT32)res; + } else { + x = 0; + } + + if (x == 0) { + STPSDIO_PR_INFO("stp_sdio_own_ctrl(OWN_CLR)\n\r"); + stp_sdio_own_ctrl(OWN_CLR); + } else if (x == 2) { + STPSDIO_PR_INFO("stp_sdio_own_ctrl(OWN_SET) -->Sleep\n\r"); + stp_sdio_own_ctrl(OWN_SET); + } else if (x == 3) { + gStpSdioDbgLvl = STPSDIO_LOG_WARN; + STPSDIO_PR_WARN("set STP-SDIO LogLevel to STPSDIO_LOG_WARN\n\r"); + } else if (x == 4) { + gStpSdioDbgLvl = STPSDIO_LOG_INFO; + STPSDIO_PR_INFO("set STP-SDIO LogLevel to STPSDIO_LOG_INFO\n\r"); + } else if (x == 5) { + gStpSdioDbgLvl = STPSDIO_LOG_HINT; + STPSDIO_PR_INFO("set STP-SDIO LogLevel to STPSDIO_LOG_HINT\n\r"); + } else if (x == 6) { + gStpSdioDbgLvl = STPSDIO_LOG_DBG; + STPSDIO_PR_INFO("set STP-SDIO LogLevel to STPSDIO_LOG_DBG\n\r"); + } else if (x == 7) { + gStpSdioDbgLvl = STPSDIO_LOG_LOUD; + STPSDIO_PR_INFO("set STP-SDIO LogLevel to STPSDIO_LOG_LOUD\n\r"); + } + + return len; +} + + +/*! + * \brief /proc initial procedures. Initialize global debugging information. + * + * \details Setup entry for /proc debugging for tx + * + * \retval 0 success + */ +INT32 stp_sdio_txdbg_setup(VOID) +{ + gStpSdioTxDbgEntry = proc_create(STP_SDIO_TXDBG_PROCNAME, 0644, NULL, &stp_sdio_txdbg_fops); + if (gStpSdioTxDbgEntry == NULL) { + pr_warn(DFT_TAG "Unable to create /proc entry\n\r"); + return -1; + } + +#if STP_SDIO_TXPERFDBG + stp_sdio_txperf_worker_cnt = 0; + + stp_sdio_txperf_fifo_left = 0; + stp_sdio_txperf_to_send = 0; + stp_sdio_txperf_fifo_lmt_cnt = 0; + + stp_sdio_txperf_txed_pkt_num = 0; + stp_sdio_txperf_pkt_num_lmt_cnt = 0; +#endif + +#if STP_SDIO_TXDBG + stp_sdio_txdbg_cnt = 0; +#endif + + return 0; +} + +/*! + * \brief /proc de-init procedures. + * + * \details remove entry for /proc debugging for tx + * + * \retval 0 success + */ +INT32 stp_sdio_txdbg_remove(VOID) +{ + if (gStpSdioTxDbgEntry != NULL) + proc_remove(gStpSdioTxDbgEntry); + + return 0; +} + +#endif /* end of STP_SDIO_DBG_SUPPORT && (STP_SDIO_TXDBG || STP_SDIO_TXPERFDBG) */ + +#if STP_SDIO_DBG_SUPPORT && STP_SDIO_OWNBACKDBG + +/*! + * \brief /proc initial procedures. Initialize global debugging information. + * + * \details Setup entry for /proc debugging for tx + * + * \retval 0 success + */ +INT32 stp_sdio_owndbg_setup(VOID) +{ + gStpSdioOwnEntry = proc_create(STP_SDIO_OWNDBG_PROCNAME, 0644, NULL, &stp_sdio_own_fops); + if (gStpSdioOwnEntry == NULL) { + pr_warn(DFT_TAG "Unable to create /proc entry\n\r"); + return -1; + } + + return 0; +} + + + +/*! + * \brief /proc de-init procedures. + * + * \details remove entry for /proc debugging for tx + * + * \retval 0 success + */ +INT32 stp_sdio_owndbg_remove(VOID) +{ + if (gStpSdioOwnEntry != NULL) + proc_remove(gStpSdioOwnEntry); + + return 0; +} +#endif + +/*! + * \brief hif_sdio init function + * + * detailed descriptions + * + * \retval + */ +static INT32 stp_sdio_init(VOID) +{ + INT32 ret; + INT32 i; + + /* 4 <1> initialize all private variables */ + stp_sdio_host_info_op(1); + g_stp_sdio_host_count = 0; + /* Init stp sdio client info */ +#if 0 /* George: chage to be a constant struct */ + g_stp_sdio_cltinfo.func_tbl = mtk_stp_sdio_id_tbl; + g_stp_sdio_cltinfo.func_tbl_size = + sizeof(mtk_stp_sdio_id_tbl) / sizeof(MTK_WCN_HIF_SDIO_FUNCINFO) - 1; + g_stp_sdio_cltinfo.hif_clt_irq = stp_sdio_irq; + g_stp_sdio_cltinfo.hif_clt_probe = stp_sdio_probe; + g_stp_sdio_cltinfo.hif_clt_remove = stp_sdio_remove; +#endif + + STPSDIO_PR_DBG("cltinfo func table size:%d\n", g_stp_sdio_cltinfo.func_tbl_size); + for (i = 0; i < g_stp_sdio_cltinfo.func_tbl_size; i++) { + STPSDIO_PR_DBG("manf_id:0x%x, card_id:0x%x, func_num:%d, blk_size:%d\n", + mtk_stp_sdio_id_tbl[i].manf_id, mtk_stp_sdio_id_tbl[i].card_id, + mtk_stp_sdio_id_tbl[i].func_num, mtk_stp_sdio_id_tbl[i].blk_sz); + } + + /* 4 <2> register supported functions from sdio id table to hif sdio driver */ + ret = mtk_wcn_hif_sdio_client_reg(&g_stp_sdio_cltinfo); + if (ret) + STPSDIO_PR_ERR("mtk_wcn_hif_sdio_client_reg fail(%d)!\n", ret); + + ret = mtk_wcn_stp_wmt_sdio_op_reg(stp_sdio_own_ctrl); + if (ret) + STPSDIO_PR_ERR + ("mtk_wcn_stp_wmt_sdio_op_reg(mtk_wcn_stp_sdio_own_ctrl) fail(%d)!\n", ret); +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT + mtk_wcn_wmt_sdio_deep_sleep_flag_cb_reg(stp_sdio_deep_sleep_flag_set); +#endif + mtk_wcn_wmt_sdio_rw_cb_reg(stp_sdio_reg_rw); + +#if STP_SDIO_DBG_SUPPORT && STP_SDIO_RXDBG + stp_sdio_rxdbg_setup(); +#endif + +#if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXDBG + stp_sdio_txdbg_setup(); +#endif + +#if STP_SDIO_DBG_SUPPORT && STP_SDIO_OWNBACKDBG + stp_sdio_owndbg_setup(); +#endif + + STPSDIO_PR_DBG + ("blk_size(%ld), tx_buf_cnt(%ld), fifo tx(%ld) rx(%ld), buf tx(%ld) rx(%ld)\n", + STP_SDIO_BLK_SIZE, STP_SDIO_TX_BUF_CNT, STP_SDIO_TX_FIFO_SIZE, STP_SDIO_RX_FIFO_SIZE, + STP_SDIO_TX_ENTRY_SIZE, STP_SDIO_TX_ENTRY_SIZE); + + return ret; +} + +INT32 stp_sdio_reg_rw(INT32 func_num, INT32 direction, UINT32 offset, UINT32 value) +{ + + if (func_num == 0) + return stp_sdio_func0_reg_rw(direction, offset, value); + else if (func_num == 2) + return stp_sdio_func_reg_rw(direction, offset, value); + + STPSDIO_PR_ERR("func_num(%d) is not support!\n", func_num); + return -1; +} + +INT32 stp_sdio_func0_reg_rw(INT32 direction, UINT32 offset, UINT32 value) +{ + INT32 ret = -1; + UINT8 val = 0x00; + + val = (UINT8) value; + switch (direction) { + case 0: + ret = mtk_wcn_hif_sdio_f0_readb(g_stp_sdio_host_info.sdio_cltctx, offset, &val); + STPSDIO_PR_INFO("read func0 CR(0x%x), value(0x%x)\n", offset, val); + break; + case 1: + ret = mtk_wcn_hif_sdio_f0_writeb(g_stp_sdio_host_info.sdio_cltctx, offset, val); + STPSDIO_PR_INFO("write func0 CR(0x%x), value(0x%x)\n", offset, val); + break; + default: + break; + } + return ret; + +} + +INT32 stp_sdio_func_reg_rw(INT32 direction, UINT32 offset, UINT32 value) +{ + INT32 ret = -1; + UINT32 val = 0x00; + + val = (UINT32) value; + switch (direction) { + case 0: + ret = mtk_wcn_hif_sdio_readl(g_stp_sdio_host_info.sdio_cltctx, offset, &val); + STPSDIO_PR_INFO("read sdio CR(0x%x), value(0x%x)\n", offset, val); + break; + case 1: + ret = mtk_wcn_hif_sdio_writel(g_stp_sdio_host_info.sdio_cltctx, offset, val); + STPSDIO_PR_INFO("write sdio CR(0x%x), value(0x%x)\n", offset, val); + break; + default: + break; + } + return ret; +} + +INT32 stp_sdio_wake_up_ctrl(MTK_WCN_HIF_SDIO_CLTCTX ctx) +{ + INT32 ret; + + ret = hif_sdio_wake_up_ctrl(ctx); + if (ret == -11) { + STPSDIO_PR_ERR("wake up fail, polling [GPIO_CHIP_DEEP_SLEEP_PIN] low over 30ms\n"); + ret = stp_sdio_issue_fake_coredump + (" wake up fail, polling [GPIO_CHIP_DEEP_SLEEP_PIN] low over 30ms # -"); + } else if (ret == -2 || ret == -3) + STPSDIO_PR_ERR("get wake up, sleep pin error\n"); + + return ret; +} + +VOID stp_sdio_dump_register(VOID) +{ + UINT32 count = 3; + MTK_WCN_HIF_SDIO_CLTCTX clt_ctx; + UINT32 val = 0; + UINT32 delay_us = 10000; + + clt_ctx = gp_info->sdio_cltctx; + while (count) { + stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, clt_ctx, CCIR, &val, 0); + STPSDIO_PR_ERR("******CCIR == 0x%x*****\n", val); + stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, clt_ctx, CHLPCR, &val, 0); + STPSDIO_PR_ERR("******CHLPCR == 0x%x*****\n", val); + stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, clt_ctx, CSDIOCSR, &val, 0); + STPSDIO_PR_ERR("******CSDIOCSR == 0x%x*****\n", val); + stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, clt_ctx, CHCR, &val, 0); + STPSDIO_PR_ERR("******CHCR == 0x%x*****\n", val); + stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, clt_ctx, CHISR, &val, 0); + STPSDIO_PR_ERR("******CHISR == 0x%x*****\n", val); + stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, clt_ctx, CHIER, &val, 0); + STPSDIO_PR_ERR("******CHIER == 0x%x*****\n", val); + stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, clt_ctx, CTFSR, &val, 0); + STPSDIO_PR_ERR("******CTFSR == 0x%x*****\n", val); + stp_sdio_rw_retry(HIF_TYPE_READL, STP_SDIO_RETRY_LIMIT, clt_ctx, CRPLR, &val, 0); + STPSDIO_PR_ERR("******CRPLR == 0x%x*****\n", val); + count--; + osal_usleep_range(delay_us, 2 * delay_us); + } + +} + +/*! + * \brief hif_sdio init function + * + * detailed descriptions + * + * \retval + */ +static VOID stp_sdio_exit(VOID) +{ +#if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXDBG + stp_sdio_txdbg_remove(); +#endif + +#if STP_SDIO_DBG_SUPPORT && STP_SDIO_RXDBG + stp_sdio_rxdbg_remove(); +#endif + +#if STP_SDIO_DBG_SUPPORT && STP_SDIO_OWNBACKDBG + stp_sdio_owndbg_remove(); +#endif + + /* 4 <0> unregister if_tx() function */ + mtk_wcn_stp_register_if_tx(STP_SDIO_IF_TX, 0x0); + + /* 4 <1> for all functions that have not been unregistered */ + /* 4 <1.1> unregister stp sdio func of the host */ + mtk_wcn_hif_sdio_client_unreg(&g_stp_sdio_cltinfo); + + /* 4 <1.2> stop Tx tasklet/Rx work queue of the host */ + flush_scheduled_work(); + STPSDIO_PR_DBG("flush scheduled work end\n"); + + /* 4 <1.3> return ownership to firmware of the host */ + /* TODO: check set which register ! */ + + /* 4 <1.4> clear the host struct list and free the memory allocation of the host */ + g_stp_sdio_host_count = 0; + stp_sdio_host_info_op(0); + /* 4 <1.5> Notice: while rmmod client driver, the stp_sdio_remove() */ + /* will not be called after stp_sdio_exit() ! */ +} + +INT32 mtk_wcn_stp_sdio_drv_init(VOID) +{ + return stp_sdio_init(); + +} +EXPORT_SYMBOL(mtk_wcn_stp_sdio_drv_init); + +VOID mtk_wcn_stp_sdio_drv_exit(VOID) +{ + return stp_sdio_exit(); +} +EXPORT_SYMBOL(mtk_wcn_stp_sdio_drv_exit); diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/stp_uart.c b/drivers/misc/mediatek/connectivity/common/common_main/linux/stp_uart.c new file mode 100644 index 0000000000000..8803c2375b25c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/stp_uart.c @@ -0,0 +1,843 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + + +#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 + + +static INT32 gDbgLevel = UART_LOG_INFO; + +#define UART_PR_DBG(fmt, arg...) \ +do { if (gDbgLevel >= UART_LOG_DBG) \ + pr_info(PFX "%s: " fmt, __func__, ##arg); \ +} while (0) +#define UART_PR_INFO(fmt, arg...) \ +do { if (gDbgLevel >= UART_LOG_INFO) \ + pr_info(PFX "%s: " fmt, __func__, ##arg); \ +} while (0) +#define UART_PR_WARN(fmt, arg...) \ +do { if (gDbgLevel >= UART_LOG_WARN) \ + pr_warn(PFX "%s: " fmt, __func__, ##arg); \ +} while (0) +#define UART_PR_ERR(fmt, arg...) \ +do { if (gDbgLevel >= UART_LOG_ERR) \ + pr_err(PFX "%s: " fmt, __func__, ##arg); \ +} while (0) + + +#include +#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; +spinlock_t g_stp_uart_rx_fifo_spinlock; +struct tasklet_struct g_stp_uart_rx_fifo_tasklet; +#define RX_BUFFER_LEN 1024 +UINT8 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 */ + +PUINT8 g_stp_uart_rx_buf; /* for stp rx data parsing */ +struct kfifo *g_stp_uart_rx_fifo; /* 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; + +UINT8 tx_buf[MTKSTP_BUFFER_SIZE] = { 0x0 }; + +INT32 rd_idx; +INT32 wr_idx; +/* struct semaphore buf_mtx; */ +spinlock_t buf_lock; +static INT32 mtk_wcn_uart_tx(const PUINT8 data, const UINT32 size, PUINT32 written_size); + + +static _osal_inline_ INT32 stp_uart_tx_wakeup(struct tty_struct *tty) +{ + INT32 len = 0; + INT32 written = 0; + INT32 written_count = 0; + static INT32 i; + /* UINT32 flags; */ + /* get data from ring buffer */ +/* down(&buf_mtx); */ +/* // spin_lock_irqsave(&buf_lock, flags); */ + +#if 0 + if ((i > 1000) && (i % 5) == 0) { + UART_PR_INFO("i=(%d), ****** drop data from uart******\n", i); + i++; + return 0; + } + UART_PR_INFO("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_PR_ERR + ("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; + /* pr_debug("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_PR_ERR("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_PR_ERR("Warnning(i-%d):[pid(%d)(%s)]length verfication(external)\n", + i, current->pid, current->comm); + UART_PR_ERR("warnning,len(%d), wr_idx(%d), rd_idx(%d)!\n\r", len, wr_idx, rd_idx); + return -1; + } + } else { + UART_PR_ERR("Warnning(i-%d):[pid(%d)(%s)]length verfication(external)\n", + i, current->pid, current->comm); + UART_PR_ERR("warnning,len(%d), wr_idx(%d), rd_idx(%d)!\n\r", len, wr_idx, rd_idx); + return -1; + } + /* up(&buf_mtx); */ +/* // spin_unlock_irqrestore(&buf_lock, flags); */ + 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 INT32 stp_uart_tty_open(struct tty_struct *tty) +{ + UART_PR_DBG("stp_uart_tty_opentty: %p\n", tty); + + tty->receive_room = 65536; + tty->port->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 */ + + /* definition changed!! */ + if (tty->ldisc->ops->flush_buffer) + tty->ldisc->ops->flush_buffer(tty); + + 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_STP_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_PR_DBG("stp_uart_tty_close(): tty %p\n", tty); + mtk_wcn_stp_register_if_tx(STP_UART_IF_TX, NULL); +} + +/* 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) +{ + /* pr_debug("%s: start !!\n", __FUNCTION__); */ + + /* clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); */ + + /* stp_uart_tx_wakeup(tty); */ +} + +/* 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 INT32 stp_uart_fifo_init(VOID) +{ + INT32 err = 0; + /*add rx fifo */ + g_stp_uart_rx_fifo = kzalloc(sizeof(struct kfifo), GFP_ATOMIC); + if (g_stp_uart_rx_fifo == NULL) { + err = -2; + UART_PR_ERR("kzalloc for g_stp_uart_rx_fifo failed (kernel version > 2.6.35)\n"); + return err; + } + err = kfifo_alloc(g_stp_uart_rx_fifo, LDISC_RX_FIFO_SIZE, GFP_ATOMIC); + if (err != 0) { + UART_PR_ERR("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; + return err; + } + if (err == 0) { + if (g_stp_uart_rx_fifo != NULL) { + kfifo_reset(g_stp_uart_rx_fifo); + UART_PR_DBG("stp_uart_fifo_init() success.\n"); + } else { + err = -4; + UART_PR_ERR + ("abnormal case, err = 0 but g_stp_uart_rx_fifo = NULL, set err to %d\n", + err); + } + } else + UART_PR_ERR("stp_uart_fifo_init() failed.\n"); + + return err; +} + +static INT32 stp_uart_fifo_deinit(VOID) +{ + if (g_stp_uart_rx_fifo != NULL) { + kfifo_free(g_stp_uart_rx_fifo); + kfree(g_stp_uart_rx_fifo); + g_stp_uart_rx_fifo = NULL; + } + return 0; +} + +static VOID stp_uart_rx_handling(ULONG func_data) +{ + UINT32 how_much_get = 0; + UINT32 how_much_to_get = 0; + UINT32 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_PR_INFO("fifolen(%d)\n", how_much_to_get); + } + + do { + how_much_get = kfifo_out(g_stp_uart_rx_fifo, g_rx_data, RX_BUFFER_LEN); + /* UART_PR_INFO ("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 (flag == 1) + UART_PR_INFO("finish, fifolen(%d)\n", kfifo_len(g_stp_uart_rx_fifo)); +} + +static VOID stp_uart_tty_receive(struct tty_struct *tty, const unsigned char *data, PINT8 flags, INT32 count) +{ + UINT32 fifo_avail_len = LDISC_RX_FIFO_SIZE - kfifo_len(g_stp_uart_rx_fifo); + UINT32 how_much_put = 0; +#if 0 + { + struct timeval now; + + osal_do_gettimeofday(&now); + pr_warn("[+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_PR_ERR("abnormal: buffer count = %d\n", count); + } + /*How much empty seat? */ + if (fifo_avail_len > 0) { + /* UART_PR_INFO ("fifo left(%d), count(%d)\n", fifo_avail_len, count); */ + how_much_put = kfifo_in(g_stp_uart_rx_fifo, (PUINT8) data, count); + + /*schedule it! */ + tasklet_schedule(&g_stp_uart_rx_fifo_tasklet); + } else { + UART_PR_ERR("stp_uart_tty_receive rxfifo is full!!\n"); + } + +#if 0 + { + struct timeval now; + + osal_do_gettimeofday(&now); + pr_warn("[-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 INT32 stp_uart_fifo_init(VOID) +{ + INT32 err = 0; + + g_stp_uart_rx_buf = vzalloc(LDISC_RX_BUF_SIZE); + if (!g_stp_uart_rx_buf) { + UART_PR_ERR("kfifo_alloc failed (kernel version >= 2.6.37)\n"); + err = -4; + goto fifo_init_end; + } + + UART_PR_INFO("g_stp_uart_rx_buf alloc ok(0x%p, %d)\n", + g_stp_uart_rx_buf, LDISC_RX_BUF_SIZE); + + /*add rx fifo */ + /* allocate struct kfifo first */ + g_stp_uart_rx_fifo = kzalloc(sizeof(struct kfifo), GFP_KERNEL); + if (g_stp_uart_rx_fifo == NULL) { + err = -2; + UART_PR_ERR("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 (err != 0) { + UART_PR_ERR("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; + } + UART_PR_INFO("g_stp_uart_rx_fifo alloc ok\n"); + +fifo_init_end: + + if (err == 0) { + /* kfifo init ok */ + kfifo_reset(g_stp_uart_rx_fifo); + UART_PR_DBG("g_stp_uart_rx_fifo init success\n"); + } else { + UART_PR_ERR("stp_uart_fifo_init() fail(%d)\n", err); + if (g_stp_uart_rx_buf) { + UART_PR_DBG("free g_stp_uart_rx_buf\n"); + vfree(g_stp_uart_rx_buf); + g_stp_uart_rx_buf = NULL; + } + } + + return err; +} + +static INT32 stp_uart_fifo_deinit(VOID) +{ + if (g_stp_uart_rx_buf) { + vfree(g_stp_uart_rx_buf); + g_stp_uart_rx_buf = NULL; + } + + if (g_stp_uart_rx_fifo != NULL) { + kfifo_free(g_stp_uart_rx_fifo); + kfree(g_stp_uart_rx_fifo); + g_stp_uart_rx_fifo = NULL; + } + return 0; +} + +static VOID stp_uart_rx_worker(struct work_struct *work) +{ + UINT32 read; + + if (unlikely(!g_stp_uart_rx_fifo)) { + UART_PR_ERR("NULL rx fifo!\n"); + return; + } + if (unlikely(!g_stp_uart_rx_buf)) { + UART_PR_ERR("NULL rx buf!\n"); + return; + } + + + /* run until fifo becomes empty */ + 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); + /* pr_debug("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); */ + } + } +} + +/* 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 PUINT8 data, PINT8 flags, INT32 count) +{ + UINT32 written; + + /* UART_LOUD_FUNC("URX:%d\n", count); */ + if (unlikely(count > 2000)) + UART_PR_WARN("abnormal: buffer count = %d\n", count); + + if (unlikely(!g_stp_uart_rx_fifo || !g_stp_uart_rx_work || !g_stp_uart_rx_wq)) { + UART_PR_ERR + ("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! */ + + written = kfifo_in(g_stp_uart_rx_fifo, (PUINT8) data, count); + /* pr_debug("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_PR_ERR("c(%d),w(%d) bytes dropped\n", count, written); +} + +#else + +static VOID stp_uart_tty_receive(struct tty_struct *tty, const PUINT8 data, PINT8 flags, INT32 count) +{ + +#if 0 + mtk_wcn_stp_debug_gpio_assert(IDX_STP_RX_PROC, DBG_TIE_LOW); +#endif + + if (count > 2000) { + /*this is abnormal */ + UART_PR_ERR("stp_uart_tty_receive buffer count = %d\n", count); + } +#if 0 + { + struct timeval now; + + osal_do_gettimeofday(&now); + } +#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; + + osal_do_gettimeofday(&now); + } +#endif +} +#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 INT32 stp_uart_tty_ioctl(struct tty_struct *tty, struct file *file, UINT32 cmd, ULONG arg) +{ + INT32 err = 0; + + switch (cmd) { + case HCIUARTSETPROTO: + UART_PR_DBG(" Set low_latency to TRUE \n"); + tty->port->low_latency = 1; + + break; + default: + UART_PR_DBG(" n_tty_ioctl_helper \n"); + err = n_tty_ioctl_helper(tty, file, cmd, arg); + break; + }; + + 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 UINT32 stp_uart_tty_poll(struct tty_struct *tty, struct file *filp, poll_table *wait) +{ + return 0; +} + +INT32 mtk_wcn_uart_tx(const PUINT8 data, const UINT32 size, PUINT32 written_size) +{ + INT32 room; + /* int idx = 0; */ + /* unsigned long flags; */ + INT32 ret = 0; + UINT32 len; + /* static int tmp=0; */ + static INT32 i; + + if (stp_tty == NULL) + return -1; + + (*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_PR_DBG("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_PR_ERR("pid(%d)(%s): data is NULL\n", current->pid, current->comm); + (*written_size) = 0; + return -2; + } +#if 1 + if (unlikely(size > room)) { + UART_PR_ERR + ("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); + (*written_size) = 0; + return -3; + } + /* wr_idx : the position next to write */ + /* rd_idx : the position next to read */ + len = min(size, MTKSTP_BUFFER_SIZE - (UINT32) 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_PR_DBG("r(%d)s(%d)wr_i(%d)rd_i(%d)\n\r", room, size, wr_idx, rd_idx); + i++; + if (size == 0) { + (*written_size) = 0; + } else if (size < MAX_PACKET_ALLOWED) { + /* only size ~(0, 2000) is allowed */ + ret = stp_uart_tx_wakeup(stp_tty); + if (ret < 0) { + /* reset read and write index of tx_buffer, is there any risk? */ + wr_idx = rd_idx = 0; + *written_size = 0; + } else + *written_size = ret; + } else { + /* we filter all packet with size > 2000 */ + UART_PR_ERR("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 */ + + return 0; +} + +static INT32 mtk_wcn_stp_uart_init(VOID) +{ + static struct tty_ldisc_ops stp_uart_ldisc; + INT32 err; + INT32 fifo_init_done = 0; + + UART_PR_DBG("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, (ULONG)0); + +#elif (LDISC_RX == LDISC_RX_WORK) + err = stp_uart_fifo_init(); + if (err != 0) { + UART_PR_ERR("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_PR_ERR("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_PR_ERR("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; + + err = tty_register_ldisc(N_MTKSTP, &stp_uart_ldisc); + if (err) { + UART_PR_ERR("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_PR_ERR("init fail, return(%d)\n", err); + + return err; + +} + +static VOID mtk_wcn_stp_uart_exit(VOID) +{ + INT32 err; + + mtk_wcn_stp_register_if_tx(STP_UART_IF_TX, NULL); /* unregister if_tx function */ + + /* Release tty registration of line discipline */ + err = tty_unregister_ldisc(N_MTKSTP); + if (err) + UART_PR_ERR("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 +} + +INT32 mtk_wcn_stp_uart_drv_init(VOID) +{ + return mtk_wcn_stp_uart_init(); + +} +EXPORT_SYMBOL(mtk_wcn_stp_uart_drv_init); + +VOID mtk_wcn_stp_uart_drv_exit(VOID) +{ + return mtk_wcn_stp_uart_exit(); +} +EXPORT_SYMBOL(mtk_wcn_stp_uart_drv_exit); diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_alarm.c b/drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_alarm.c new file mode 100644 index 0000000000000..1ad1c263156bd --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_alarm.c @@ -0,0 +1,150 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#include +#include +#include "osal.h" +#include "wmt_alarm.h" +#include "wmt_lib.h" + +#define WMT_ALARM_STATE_UNINIT 0x0 +#define WMT_ALARM_STATE_DISABLE 0x01 +#define WMT_ALARM_STATE_ENABLE 0x03 + +struct wmt_alarm { + struct alarm alarm_timer; + unsigned int alarm_state; + unsigned int alarm_sec; + spinlock_t alarm_lock; + struct work_struct dmp_info_worker; + unsigned long flags; +}; + +struct wmt_alarm g_wmt_alarm; +static CONSYS_STATE_DMP_INFO g_dmp_info; + + +static void wmt_alarm_dmp_info_handler(struct work_struct *work) +{ + UINT8 dmp_info_buf[DBG_LOG_STR_SIZE]; + int len = 0, i, dmp_cnt = 5; + + if (wmt_lib_dmp_consys_state(&g_dmp_info, dmp_cnt, 0) == MTK_WCN_BOOL_TRUE) { + + len += snprintf(dmp_info_buf + len, + DBG_LOG_STR_SIZE - len, "0x%08x", g_dmp_info.cpu_pcr[0]); + for (i = 1; i < dmp_cnt; i++) + len += snprintf(dmp_info_buf + len, + DBG_LOG_STR_SIZE - len, ";0x%08x", g_dmp_info.cpu_pcr[i]); + + len += snprintf(dmp_info_buf + len, + DBG_LOG_STR_SIZE - len, ";<0x%08x>", g_dmp_info.state.lp[1]); + + len += snprintf(dmp_info_buf + len, + DBG_LOG_STR_SIZE - len, ";<0x%08x>", g_dmp_info.state.gating[1]); + + len += snprintf(dmp_info_buf + len, DBG_LOG_STR_SIZE - len, + ";[0x%08x", g_dmp_info.state.sw_state.info_time); + len += snprintf(dmp_info_buf + len, DBG_LOG_STR_SIZE - len, + ";0x%08x", g_dmp_info.state.sw_state.is_gating); + len += snprintf(dmp_info_buf + len, DBG_LOG_STR_SIZE - len, + ";0x%08x", g_dmp_info.state.sw_state.resource_disable_sleep); + len += snprintf(dmp_info_buf + len, DBG_LOG_STR_SIZE - len, + ";0x%08x", g_dmp_info.state.sw_state.clock_hif_ctrl); + len += snprintf(dmp_info_buf + len, DBG_LOG_STR_SIZE - len, + ";0x%08x", g_dmp_info.state.sw_state.clock_umac_ctrl); + len += snprintf(dmp_info_buf + len, DBG_LOG_STR_SIZE - len, + ";0x%08x", g_dmp_info.state.sw_state.clock_mcu); + len += snprintf(dmp_info_buf + len, DBG_LOG_STR_SIZE - len, + ";0x%08x]", g_dmp_info.state.sw_state.sub_system); + + WMT_INFO_FUNC("%s", dmp_info_buf); + } +} + +static enum alarmtimer_restart alarm_timer_handler(struct alarm *alarm, + ktime_t now) +{ + ktime_t kt; + + spin_lock_irqsave(&g_wmt_alarm.alarm_lock, g_wmt_alarm.flags); + + schedule_work(&g_wmt_alarm.dmp_info_worker); + kt = ktime_set(g_wmt_alarm.alarm_sec, 0); + alarm_start_relative(&g_wmt_alarm.alarm_timer, kt); + + spin_unlock_irqrestore(&g_wmt_alarm.alarm_lock, g_wmt_alarm.flags); + + return ALARMTIMER_NORESTART; +} + +static int _wmt_alarm_start_timer_nolock(unsigned int sec) +{ + ktime_t kt; + + g_wmt_alarm.alarm_sec = sec; + kt = ktime_set(g_wmt_alarm.alarm_sec, 0); + alarm_start_relative(&g_wmt_alarm.alarm_timer, kt); + g_wmt_alarm.alarm_state = WMT_ALARM_STATE_ENABLE; + + pr_info("[wmt_alarm] alarm timer enabled timeout=[%d]", g_wmt_alarm.alarm_sec); + return 0; +} + +int wmt_alarm_init(void) +{ + spin_lock_init(&g_wmt_alarm.alarm_lock); + + spin_lock_irqsave(&g_wmt_alarm.alarm_lock, g_wmt_alarm.flags); + alarm_init(&g_wmt_alarm.alarm_timer, ALARM_REALTIME, alarm_timer_handler); + INIT_WORK(&g_wmt_alarm.dmp_info_worker, wmt_alarm_dmp_info_handler); + g_wmt_alarm.alarm_state = WMT_ALARM_STATE_DISABLE; + + spin_unlock_irqrestore(&g_wmt_alarm.alarm_lock, g_wmt_alarm.flags); + + return 0; +} + +int wmt_alarm_deinit(void) +{ + wmt_alarm_cancel(); + return 0; +} + + +int _wmt_alarm_cancel_nolock(void) +{ + if (g_wmt_alarm.alarm_state == WMT_ALARM_STATE_ENABLE) { + pr_info("disable wmt_alarm"); + alarm_cancel(&g_wmt_alarm.alarm_timer); + g_wmt_alarm.alarm_state = WMT_ALARM_STATE_DISABLE; + } + return 0; +} + +int wmt_alarm_start(unsigned int sec) +{ + spin_lock_irqsave(&g_wmt_alarm.alarm_lock, g_wmt_alarm.flags); + if (g_wmt_alarm.alarm_state == WMT_ALARM_STATE_UNINIT) { + spin_unlock_irqrestore(&g_wmt_alarm.alarm_lock, g_wmt_alarm.flags); + return -1; + } + + if (g_wmt_alarm.alarm_state == WMT_ALARM_STATE_ENABLE) + _wmt_alarm_cancel_nolock(); + _wmt_alarm_start_timer_nolock(sec); + spin_unlock_irqrestore(&g_wmt_alarm.alarm_lock, g_wmt_alarm.flags); + return 0; +} + +int wmt_alarm_cancel(void) +{ + int ret; + + spin_lock_irqsave(&g_wmt_alarm.alarm_lock, g_wmt_alarm.flags); + ret = _wmt_alarm_cancel_nolock(); + spin_unlock_irqrestore(&g_wmt_alarm.alarm_lock, g_wmt_alarm.flags); + return ret; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_dbg.c b/drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_dbg.c new file mode 100644 index 0000000000000..5736dfcd3ed6e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_dbg.c @@ -0,0 +1,1627 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#include "osal_typedef.h" +#include "wmt_dbg.h" +#include "wmt_dev.h" +#include "wmt_core.h" +#include "wmt_lib.h" +#include "wmt_conf.h" +#include "psm_core.h" +#include "stp_core.h" +#include "stp_dbg.h" +#include "connsys_debug_utility.h" +#include "wmt_step.h" +#include "wmt_alarm.h" +#ifdef CONFIG_MTK_ENG_BUILD +#include "wmt_step_test.h" +#endif + +#ifdef DFT_TAG +#undef DFT_TAG +#define DFT_TAG "[WMT-DEV]" +#endif + +#define WMT_DBG_PROCNAME "driver/wmt_dbg" + +#define BUF_LEN_MAX 384 + +#if (defined(CONFIG_MTK_GMO_RAM_OPTIMIZE) && !defined(CONFIG_MTK_ENG_BUILD)) +#define WMT_EMI_DEBUG_BUF_SIZE (8*1024) +#else +#define WMT_EMI_DEBUG_BUF_SIZE (32*1024) +#endif + +struct wmt_dbg_work { + struct work_struct work; + INT32 x; + INT32 y; + INT32 z; +}; + +static struct proc_dir_entry *gWmtDbgEntry; +COEX_BUF gCoexBuf; +static UINT8 gEmiBuf[WMT_EMI_DEBUG_BUF_SIZE]; +PUINT8 buf_emi; +static OSAL_SLEEPABLE_LOCK g_dbg_emi_lock; + +static ssize_t wmt_dbg_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos); +static ssize_t wmt_dbg_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos); + + +static INT32 wmt_dbg_psm_ctrl(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_quick_sleep_ctrl(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_dsns_ctrl(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_hwver_get(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_inband_rst(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_chip_rst(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_func_ctrl(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_raed_chipid(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_wmt_dbg_level(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_stp_dbg_level(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_reg_read(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_reg_write(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_coex_test(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_assert_test(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_cmd_test_api(ENUM_WMTDRV_CMD_T cmd); +static INT32 wmt_dbg_rst_ctrl(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_ut_test(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_efuse_read(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_efuse_write(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_sdio_ctrl(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_stp_dbg_ctrl(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_stp_dbg_log_ctrl(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_wmt_assert_ctrl(INT32 par1, INT32 par2, INT32 par3); +#if CFG_CORE_INTERNAL_TXRX +static INT32 wmt_dbg_internal_lpbk_test(INT32 par1, INT32 par2, INT32 par3); +#endif +static INT32 wmt_dbg_stp_trigger_assert(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_ap_reg_read(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_ap_reg_write(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_set_mcu_clock(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_poll_cpupcr(INT32 par1, INT32 par2, INT32 par3); +#if CONSYS_ENALBE_SET_JTAG +static INT32 wmt_dbg_jtag_flag_ctrl(INT32 par1, INT32 par2, INT32 par3); +#endif +#if CFG_WMT_LTE_COEX_HANDLING +static INT32 wmt_dbg_lte_coex_test(INT32 par1, INT32 par2, INT32 par3); +#endif +#ifdef CONFIG_TRACING +static INT32 wmt_dbg_ftrace_dbg_log_ctrl(INT32 par1, INT32 par2, INT32 par3); +#endif +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT +static INT32 wmt_dbg_deep_sleep_ctrl(INT32 par1, INT32 par2, INT32 par3); +#endif +static INT32 wmt_dbg_sdio_retry_ctrl(INT32 par1, INT32 par2, INT32 par3); + +static INT32 wmt_dbg_func0_reg_read(INT32 par1, INT32 address, INT32 value); +static INT32 wmt_dbg_func0_reg_write(INT32 par1, INT32 address, INT32 value); +static INT32 wmt_dbg_stp_sdio_reg_read(INT32 par1, INT32 address, INT32 value); +static INT32 wmt_dbg_stp_sdio_reg_write(INT32 par1, INT32 address, INT32 value); +static INT32 wmt_dbg_show_thread_debug_info(INT32 par1, INT32 address, INT32 value); +static INT32 wmt_dbg_met_ctrl(INT32 par1, INT32 met_ctrl, INT32 log_ctrl); +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH +static INT32 wmt_dbg_set_fw_log_mode(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_emi_dump(INT32 par1, INT32 offset, INT32 size); +#endif +static INT32 wmt_dbg_suspend_debug(INT32 par1, INT32 offset, INT32 size); +static INT32 wmt_dbg_fw_log_ctrl(INT32 par1, INT32 onoff, INT32 level); +static INT32 wmt_dbg_pre_pwr_on_ctrl(INT32 par1, INT32 enable, INT32 par3); +#ifdef CONFIG_MTK_ENG_BUILD +static INT32 wmt_dbg_step_test(INT32 par1, INT32 address, INT32 value); +#endif + +static INT32 wmt_dbg_alarm_ctrl(INT32 par1, INT32 offset, INT32 size); + +static INT32 wmt_dbg_thermal_query(INT32 par1, INT32 count, INT32 interval); +static INT32 wmt_dbg_thermal_ctrl(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_step_ctrl(INT32 par1, INT32 par2, INT32 par3); + +static INT32 wmt_dbg_gps_suspend(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_set_bt_link_status(INT32 par1, INT32 par2, INT32 par3); + +static const WMT_DEV_DBG_FUNC wmt_dev_dbg_func[] = { + [0x0] = wmt_dbg_psm_ctrl, + [0x1] = wmt_dbg_quick_sleep_ctrl, + [0x2] = wmt_dbg_dsns_ctrl, + [0x3] = wmt_dbg_hwver_get, + [0x4] = wmt_dbg_assert_test, + [0x5] = wmt_dbg_inband_rst, + [0x6] = wmt_dbg_chip_rst, + [0x7] = wmt_dbg_func_ctrl, + [0x8] = wmt_dbg_raed_chipid, + [0x9] = wmt_dbg_wmt_dbg_level, + [0xa] = wmt_dbg_stp_dbg_level, + [0xb] = wmt_dbg_reg_read, + [0xc] = wmt_dbg_reg_write, + [0xd] = wmt_dbg_coex_test, + [0xe] = wmt_dbg_rst_ctrl, + [0xf] = wmt_dbg_ut_test, + [0x10] = wmt_dbg_efuse_read, + [0x11] = wmt_dbg_efuse_write, + [0x12] = wmt_dbg_sdio_ctrl, + [0x13] = wmt_dbg_stp_dbg_ctrl, + [0x14] = wmt_dbg_stp_dbg_log_ctrl, + [0x15] = wmt_dbg_wmt_assert_ctrl, + [0x16] = wmt_dbg_stp_trigger_assert, + [0x17] = wmt_dbg_ap_reg_read, + [0x18] = wmt_dbg_ap_reg_write, + [0x19] = wmt_dbg_fwinfor_from_emi, + [0x1a] = wmt_dbg_set_mcu_clock, + [0x1b] = wmt_dbg_poll_cpupcr, + [0x1c] = wmt_dbg_jtag_flag_ctrl, + +#if CFG_WMT_LTE_COEX_HANDLING + [0x1d] = wmt_dbg_lte_coex_test, +#endif +#ifdef CONFIG_TRACING + [0x1e] = wmt_dbg_ftrace_dbg_log_ctrl, +#endif +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT + [0x1f] = wmt_dbg_deep_sleep_ctrl, +#endif + [0x20] = wmt_dbg_sdio_retry_ctrl, + [0x22] = wmt_dbg_func0_reg_read, + [0x23] = wmt_dbg_func0_reg_write, + [0x24] = wmt_dbg_stp_sdio_reg_read, + [0x25] = wmt_dbg_stp_sdio_reg_write, + [0x26] = wmt_dbg_met_ctrl, + [0x27] = wmt_dbg_fw_log_ctrl, + [0x28] = wmt_dbg_pre_pwr_on_ctrl, + [0x29] = wmt_dbg_thermal_query, + [0x2a] = wmt_dbg_thermal_ctrl, + [0x2b] = wmt_dbg_step_ctrl, +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + [0x2c] = wmt_dbg_set_fw_log_mode, + [0x2d] = wmt_dbg_emi_dump, +#endif + [0x2e] = wmt_dbg_suspend_debug, + [0x2f] = wmt_dbg_set_bt_link_status, + [0x30] = wmt_dbg_show_thread_debug_info, + [0x31] = wmt_dbg_gps_suspend, + [0x32] = wmt_dbg_alarm_ctrl, +#ifdef CONFIG_MTK_ENG_BUILD + [0xa0] = wmt_dbg_step_test, +#endif +}; + +static VOID wmt_dbg_fwinfor_print_buff(UINT32 len) +{ + UINT32 i = 0; + UINT32 idx = 0; + + for (i = 0; i < len; i++) { + buf_emi[idx] = gEmiBuf[i]; + if (gEmiBuf[i] == '\n') { + WMT_INFO_FUNC("%s", buf_emi); + osal_memset(buf_emi, 0, BUF_LEN_MAX); + idx = 0; + } else { + idx++; + if (idx == BUF_LEN_MAX-1) { + buf_emi[idx] = '\0'; + WMT_INFO_FUNC("%s", buf_emi); + osal_memset(buf_emi, 0, BUF_LEN_MAX); + idx = 0; + } + } + } + if ((idx != 0) && (idx < BUF_LEN_MAX)) { + buf_emi[idx] = '\0'; + WMT_INFO_FUNC("%s", buf_emi); + osal_memset(buf_emi, 0, BUF_LEN_MAX); + idx = 0; + } +} + +INT32 wmt_dbg_psm_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ +#if CFG_WMT_PS_SUPPORT + if (par2 == 0) { + wmt_lib_ps_ctrl(0); + WMT_INFO_FUNC("disable PSM\n"); + } else { + par2 = (par2 < 1 || par2 > 2000) ? STP_PSM_IDLE_TIME_SLEEP : par2; + wmt_lib_ps_set_idle_time(par2); + wmt_lib_ps_ctrl(1); + WMT_WARN_FUNC("enable PSM, idle to sleep time = %d ms\n", par2); + } +#else + WMT_INFO_FUNC("WMT PS not supported\n"); +#endif + return 0; +} + +INT32 wmt_dbg_quick_sleep_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ +#if CFG_WMT_PS_SUPPORT + UINT32 en_flag = par2; + + wmt_lib_quick_sleep_ctrl(en_flag); +#else + WMT_WARN_FUNC("WMT PS not supported\n"); +#endif + return 0; +} + +INT32 wmt_dbg_dsns_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + if (WMTDSNS_FM_DISABLE <= par2 && WMTDSNS_MAX > par2) { + WMT_INFO_FUNC("DSNS type (%d)\n", par2); + mtk_wcn_wmt_dsns_ctrl(par2); + } else { + WMT_WARN_FUNC("invalid DSNS type\n"); + } + return 0; +} + +INT32 wmt_dbg_hwver_get(INT32 par1, INT32 par2, INT32 par3) +{ + WMT_INFO_FUNC("query chip version\n"); + wmt_lib_get_icinfo(WMTCHIN_HWVER); + return 0; +} + +INT32 wmt_dbg_assert_test(INT32 par1, INT32 par2, INT32 par3) +{ + INT32 sec = 8; + INT32 times = 0; + + if (par3 == 0) { + /* par2 = 0: send assert command */ + /* par2 != 0: send exception command */ + return wmt_dbg_cmd_test_api(par2 == 0 ? 0 : 1); + } else if (par3 == 1) { + /* send noack command */ + return wmt_dbg_cmd_test_api(WMTDRV_CMD_NOACK_TEST); + } else if (par3 == 2) { + /* warn reset test */ + return wmt_dbg_cmd_test_api(WMTDRV_CMD_WARNRST_TEST); + } else if (par3 == 3) { + /* firmware trace test - for soc usage, not used in combo chip */ + return wmt_dbg_cmd_test_api(WMTDRV_CMD_FWTRACE_TEST); + } else if (par3 == 4) { + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + return -1; + } + /* driver type */ + wmt_lib_trigger_assert(par2, 30); + ENABLE_PSM_MONITOR(); + return 0; + } else if (par3 == 5) { + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + return -1; + } + /* assert reason */ + wmt_lib_trigger_assert(4, par2); + ENABLE_PSM_MONITOR(); + return 0; + } + + times = par3; + do { + WMT_INFO_FUNC("Send Assert Command per 8 secs!!\n"); + wmt_dbg_cmd_test_api(0); + osal_sleep_ms(sec * 1000); + } while (--times); + + return 0; +} + +INT32 wmt_dbg_cmd_test_api(ENUM_WMTDRV_CMD_T cmd) +{ + P_OSAL_OP pOp = NULL; + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + P_OSAL_SIGNAL pSignal; + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_DBG_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + + pSignal = &pOp->signal; + + pOp->op.opId = WMT_OPID_CMD_TEST; + + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + /*this test command should be run with usb cable connected, so no host awake is needed */ + /* wmt_lib_host_awake_get(); */ + + switch (cmd) { + case WMTDRV_CMD_ASSERT: + pOp->op.au4OpData[0] = 0; + break; + case WMTDRV_CMD_EXCEPTION: + pOp->op.au4OpData[0] = 1; + break; + case WMTDRV_CMD_NOACK_TEST: + pOp->op.au4OpData[0] = 3; + break; + case WMTDRV_CMD_WARNRST_TEST: + pOp->op.au4OpData[0] = 4; + break; + case WMTDRV_CMD_FWTRACE_TEST: + pOp->op.au4OpData[0] = 5; + break; + default: + if (WMTDRV_CMD_COEXDBG_00 <= cmd && WMTDRV_CMD_COEXDBG_15 >= cmd) { + pOp->op.au4OpData[0] = 2; + pOp->op.au4OpData[1] = cmd - 2; + } else { + pOp->op.au4OpData[0] = 0xff; + pOp->op.au4OpData[1] = 0xff; + } + pOp->op.au4OpData[2] = (ULONG) gCoexBuf.buffer; + pOp->op.au4OpData[3] = osal_sizeof(gCoexBuf.buffer); + break; + } + WMT_INFO_FUNC("CMD_TEST, opid(%d), par(%zu, %zu)\n", pOp->op.opId, pOp->op.au4OpData[0], + pOp->op.au4OpData[1]); + /*wake up chip first */ + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + wmt_lib_put_op_to_free_queue(pOp); + return -1; + } + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + if ((cmd != WMTDRV_CMD_ASSERT) && + (cmd != WMTDRV_CMD_EXCEPTION) && + (cmd != WMTDRV_CMD_NOACK_TEST) && + (cmd != WMTDRV_CMD_WARNRST_TEST) && + (cmd != WMTDRV_CMD_FWTRACE_TEST)) { + if (bRet == MTK_WCN_BOOL_FALSE) { + gCoexBuf.availSize = 0; + } else { + gCoexBuf.availSize = pOp->op.au4OpData[3]; + WMT_INFO_FUNC("gCoexBuf.availSize = %d\n", gCoexBuf.availSize); + } + } + /* wmt_lib_host_awake_put(); */ + WMT_INFO_FUNC("CMD_TEST, opid (%d), par(%zu, %zu), ret(%d), result(%s)\n", + pOp->op.opId, + pOp->op.au4OpData[0], + pOp->op.au4OpData[1], + bRet, MTK_WCN_BOOL_FALSE == bRet ? "failed" : "succeed"); + + if (bRet == MTK_WCN_BOOL_TRUE) + wmt_lib_set_host_assert_info(WMTDRV_TYPE_WMT, 0, 1); + + return 0; +} + +INT32 wmt_dbg_inband_rst(INT32 par1, INT32 par2, INT32 par3) +{ + if (par2 == 0) { + WMT_INFO_FUNC("inband reset test!!\n"); + mtk_wcn_stp_inband_reset(); + } else { + WMT_INFO_FUNC("STP context reset in host side!!\n"); + mtk_wcn_stp_flush_context(); + } + + return 0; +} + +INT32 wmt_dbg_chip_rst(INT32 par1, INT32 par2, INT32 par3) +{ + if (par2 == 0) { + if (mtk_wcn_stp_is_ready()) { + WMT_INFO_FUNC("whole chip reset test\n"); + wmt_lib_cmb_rst(WMTRSTSRC_RESET_TEST); + } else { + WMT_INFO_FUNC("STP not ready , not to launch whole chip reset test\n"); + } + } else if (par2 == 1) { + WMT_INFO_FUNC("chip hardware reset test\n"); + wmt_lib_hw_rst(); + } else { + WMT_INFO_FUNC("chip software reset test\n"); + wmt_lib_sw_rst(1); + } + + return 0; +} + +INT32 wmt_dbg_func_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + MTK_WCN_BOOL ret = MTK_WCN_BOOL_FALSE; + + if (par2 < WMTDRV_TYPE_WMT || par2 == WMTDRV_TYPE_LPBK || par2 == WMTDRV_TYPE_GPSL5) { + if (par3 == 0) { + WMT_INFO_FUNC("function off test, type(%d)\n", par2); + ret = mtk_wcn_wmt_func_off(par2); + } else { + WMT_INFO_FUNC("function on test, type(%d)\n", par2); + ret = mtk_wcn_wmt_func_on(par2); + } + WMT_INFO_FUNC("function test return %d\n", ret); + } else + WMT_INFO_FUNC("function ctrl test, invalid type(%d)\n", par2); + + return 0; +} + +INT32 wmt_dbg_raed_chipid(INT32 par1, INT32 par2, INT32 par3) +{ + WMT_INFO_FUNC("chip id = %d\n", wmt_lib_get_icinfo(WMTCHIN_CHIPID)); + + return 0; +} + +INT32 wmt_dbg_wmt_dbg_level(INT32 par1, INT32 par2, INT32 par3) +{ + par2 = (WMT_LOG_ERR <= par2 && WMT_LOG_LOUD >= par2) ? par2 : WMT_LOG_INFO; + wmt_lib_dbg_level_set(par2); + WMT_INFO_FUNC("set wmt log level to %d\n", par2); + + return 0; +} + +INT32 wmt_dbg_stp_dbg_level(INT32 par1, INT32 par2, INT32 par3) +{ + par2 = (0 <= par2 && 4 >= par2) ? par2 : 2; + mtk_wcn_stp_dbg_level(par2); + WMT_INFO_FUNC("set stp log level to %d\n", par2); + + return 0; +} + +INT32 wmt_dbg_reg_read(INT32 par1, INT32 par2, INT32 par3) +{ + /* par2-->register address */ + /* par3-->register mask */ + UINT32 value = 0x0; + UINT32 iRet = -1; +#if 0 + DISABLE_PSM_MONITOR(); + iRet = wmt_core_reg_rw_raw(0, par2, &value, par3); + ENABLE_PSM_MONITOR(); +#endif + iRet = wmt_lib_reg_rw(0, par2, &value, par3); + WMT_INFO_FUNC("read combo chip register (0x%08x) with mask (0x%08x) %s, value = 0x%08x\n", + par2, par3, iRet != 0 ? "failed" : "succeed", iRet != 0 ? -1 : value); + + return 0; +} + +INT32 wmt_dbg_reg_write(INT32 par1, INT32 par2, INT32 par3) +{ + /* par2-->register address */ + /* par3-->value to set */ + UINT32 iRet = -1; +#if 0 + DISABLE_PSM_MONITOR(); + iRet = wmt_core_reg_rw_raw(1, par2, &par3, 0xffffffff); + ENABLE_PSM_MONITOR(); +#endif + iRet = wmt_lib_reg_rw(1, par2, &par3, 0xffffffff); + WMT_INFO_FUNC("write combo chip register (0x%08x) with value (0x%08x) %s\n", + par2, par3, iRet != 0 ? "failed" : "succeed"); + + return 0; +} + +INT32 wmt_dbg_efuse_read(INT32 par1, INT32 par2, INT32 par3) +{ + /* par2-->efuse address */ + /* par3-->register mask */ + UINT32 value = 0x0; + UINT32 iRet = -1; + + iRet = wmt_lib_efuse_rw(0, par2, &value, par3); + WMT_INFO_FUNC("read combo chip efuse (0x%08x) with mask (0x%08x) %s, value = 0x%08x\n", + par2, par3, iRet != 0 ? "failed" : "succeed", iRet != 0 ? -1 : value); + + return 0; +} + +INT32 wmt_dbg_efuse_write(INT32 par1, INT32 par2, INT32 par3) +{ + /* par2-->efuse address */ + /* par3-->value to set */ + UINT32 iRet = -1; + + iRet = wmt_lib_efuse_rw(1, par2, &par3, 0xffffffff); + WMT_INFO_FUNC("write combo chip efuse (0x%08x) with value (0x%08x) %s\n", + par2, par3, iRet != 0 ? "failed" : "succeed"); + + return 0; +} + +INT32 wmt_dbg_sdio_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ +/*remove sdio card detect/remove control because of btif is used*/ +#if 0 + INT32 iRet = -1; + + iRet = wmt_lib_sdio_ctrl(par2 != 0 ? 1 : 0); + WMT_INFO_FUNC("ctrl SDIO function %s\n", 0 == iRet ? "succeed" : "failed"); +#endif + return 0; +} + +INT32 wmt_dbg_stp_dbg_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + if (par2 > 1) { + mtk_wcn_stp_dbg_dump_package(); + return 0; + } + + WMT_INFO_FUNC("%s stp debug function\n", par2 == 0 ? "disable" : "enable"); + + if (par2 == 0) + mtk_wcn_stp_dbg_disable(); + else if (par2 == 1) + mtk_wcn_stp_dbg_enable(); + + return 0; +} + +INT32 wmt_dbg_stp_dbg_log_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + mtk_wcn_stp_dbg_log_ctrl(par2 != 0 ? 1 : 0); + + return 0; +} + +INT32 wmt_dbg_wmt_assert_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + if (par2 > 2 || par2 < 0) + return -1; + + mtk_wcn_stp_coredump_flag_ctrl(par2); + + return 0; +} + +INT32 wmt_dbg_fwinfor_from_emi(INT32 par1, INT32 par2, INT32 par3) +{ + UINT32 offset = 0; + UINT32 len = 0; + UINT32 *pAddr = NULL; + UINT32 cur_idx_pagedtrace; + static UINT32 prev_idx_pagedtrace; + MTK_WCN_BOOL isBreak = MTK_WCN_BOOL_TRUE; + + offset = par2; + len = par3; + + if (osal_lock_sleepable_lock(&g_dbg_emi_lock)) { + WMT_ERR_FUNC("lock failed\n"); + return -1; + } + + buf_emi = kmalloc(sizeof(UINT8) * BUF_LEN_MAX, GFP_KERNEL); + if (!buf_emi) { + WMT_ERR_FUNC("buf kmalloc memory fail\n"); + return 0; + } + osal_memset(buf_emi, 0, BUF_LEN_MAX); + osal_memset(&gEmiBuf[0], 0, WMT_EMI_DEBUG_BUF_SIZE); + wmt_lib_get_fwinfor_from_emi(0, offset, &gEmiBuf[0], 0x100); + + if (offset == 1) { + do { + pAddr = (PUINT32) wmt_plat_get_emi_virt_add(0x24); + if (pAddr == NULL) { + WMT_ERR_FUNC("get virtual emi address 0x24 fail!\n"); + return -1; + } + cur_idx_pagedtrace = *pAddr; + + if (cur_idx_pagedtrace > prev_idx_pagedtrace) { + len = cur_idx_pagedtrace - prev_idx_pagedtrace; + wmt_lib_get_fwinfor_from_emi(1, prev_idx_pagedtrace, &gEmiBuf[0], len); + wmt_dbg_fwinfor_print_buff(len); + prev_idx_pagedtrace = cur_idx_pagedtrace; + } + + if (cur_idx_pagedtrace < prev_idx_pagedtrace) { + if (prev_idx_pagedtrace >= 0x8000) { + WMT_INFO_FUNC("++ prev_idx_pagedtrace invalid ...++\n\\n"); + prev_idx_pagedtrace = 0x8000 - 1; + continue; + } + + len = 0x8000 - prev_idx_pagedtrace - 1; + wmt_lib_get_fwinfor_from_emi(1, prev_idx_pagedtrace, &gEmiBuf[0], len); + WMT_INFO_FUNC("\n\n -- CONNSYS paged trace ascii output (cont...) --\n\n"); + wmt_dbg_fwinfor_print_buff(len); + + len = cur_idx_pagedtrace; + wmt_lib_get_fwinfor_from_emi(1, 0x0, &gEmiBuf[0], len); + WMT_INFO_FUNC("\n\n -- CONNSYS paged trace ascii output (end) --\n\n"); + wmt_dbg_fwinfor_print_buff(len); + prev_idx_pagedtrace = cur_idx_pagedtrace; + } + msleep(100); + } while (isBreak); + } + + WMT_INFO_FUNC("\n\n -- control word --\n\n"); + wmt_dbg_fwinfor_print_buff(256); + if (len > 1024 * 4) + len = 1024 * 4; + + WMT_WARN_FUNC("get fw infor from emi at offset(0x%x),len(0x%x)\n", offset, len); + osal_memset(&gEmiBuf[0], 0, WMT_EMI_DEBUG_BUF_SIZE); + wmt_lib_get_fwinfor_from_emi(1, offset, &gEmiBuf[0], len); + + WMT_INFO_FUNC("\n\n -- paged trace hex output --\n\n"); + wmt_dbg_fwinfor_print_buff(len); + WMT_INFO_FUNC("\n\n -- paged trace ascii output --\n\n"); + wmt_dbg_fwinfor_print_buff(len); + kfree(buf_emi); + osal_unlock_sleepable_lock(&g_dbg_emi_lock); + + return 0; +} + +INT32 wmt_dbg_stp_trigger_assert(INT32 par1, INT32 par2, INT32 par3) +{ + wmt_lib_btm_cb(BTM_TRIGGER_STP_ASSERT_OP); + + return 0; +} + +static INT32 wmt_dbg_ap_reg_read(INT32 par1, INT32 par2, INT32 par3) +{ + INT32 value = 0x0; + PUINT8 ap_reg_base = NULL; + + WMT_INFO_FUNC("AP register read, reg address:0x%x\n", par2); + ap_reg_base = ioremap_nocache(par2, 0x4); + if (ap_reg_base) { + value = readl(ap_reg_base); + WMT_INFO_FUNC("AP register read, reg address:0x%x, value:0x%x\n", par2, value); + iounmap(ap_reg_base); + } else + WMT_ERR_FUNC("AP register ioremap fail!\n"); + + return 0; +} + +static INT32 wmt_dbg_ap_reg_write(INT32 par1, INT32 par2, INT32 par3) +{ + INT32 value = 0x0; + PUINT8 ap_reg_base = NULL; + + WMT_INFO_FUNC("AP register write, reg address:0x%x, value:0x%x\n", par2, par3); + + ap_reg_base = ioremap_nocache(par2, 0x4); + if (ap_reg_base) { + writel(par3, ap_reg_base); + value = readl(ap_reg_base); + WMT_INFO_FUNC("AP register write done, value after write:0x%x\n", value); + iounmap(ap_reg_base); + } else + WMT_ERR_FUNC("AP register ioremap fail!\n"); + + return 0; +} + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH +static INT32 wmt_dbg_set_fw_log_mode(INT32 par1, INT32 par2, INT32 par3) +{ + connsys_dedicated_log_set_log_mode(par2); + return 0; +} + +static INT32 wmt_dbg_emi_dump(INT32 par1, INT32 offset, INT32 size) +{ + connsys_dedicated_log_dump_emi(offset, size); + return 0; +} +#endif + +/********************************************************/ +/* par2: */ +/* 0: Off */ +/* others: alarm time (seconds) */ +/********************************************************/ +static INT32 wmt_dbg_suspend_debug(INT32 par1, INT32 par2, INT32 par3) +{ + if (par2 > 0) + connsys_log_alarm_enable(par2); + else + connsys_log_alarm_disable(); + return 0; +} + +static INT32 wmt_dbg_alarm_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + if (par2 > 0) + wmt_alarm_start(par2); + else + wmt_alarm_cancel(); + return 0; +} + +static INT32 wmt_dbg_set_bt_link_status(INT32 par1, INT32 par2, INT32 par3) +{ + if (par2 != 0 && par2 != 1) + return 0; + + wmt_lib_set_bt_link_status(par2, par3); + return 0; +} + +#ifdef CONFIG_TRACING +static INT32 wmt_dbg_ftrace_dbg_log_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + WMT_INFO_FUNC("%s ftrace print!!\n", par2 == 0 ? "disable" : "enable"); + + return osal_ftrace_print_ctrl(par2 == 0 ? 0 : 1); +} +#endif + +#ifdef CONFIG_MTK_COMBO_CHIP_DEEP_SLEEP_SUPPORT +static INT32 wmt_dbg_deep_sleep_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + WMT_INFO_FUNC("%s deep_sleep !!\n", par2 == 0 ? "disable" : "enable"); + return wmt_lib_deep_sleep_ctrl(par2); +} +#endif + +static INT32 wmt_dbg_sdio_retry_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + WMT_INFO_FUNC("%s sdio retry!!\n", par2 == 0 ? "disable" : "enable"); + + mtk_stp_dbg_sdio_retry_flag_ctrl(par2 == 0 ? 0 : 1); + + return 0; +} + +INT32 wmt_dbg_coex_test(INT32 par1, INT32 par2, INT32 par3) +{ + WMT_INFO_FUNC("coexistance test cmd!!\n"); + + return wmt_dbg_cmd_test_api(par2 + WMTDRV_CMD_COEXDBG_00); +} + +INT32 wmt_dbg_rst_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + WMT_INFO_FUNC("%s audo rst\n", par2 == 0 ? "disable" : "enable"); + mtk_wcn_stp_set_auto_rst(par2 == 0 ? 0 : 1); + + return 0; +} + +INT32 wmt_dbg_func0_reg_read(INT32 par1, INT32 address, INT32 value) +{ + INT32 ret = -1; + + ret = wmt_lib_sdio_reg_rw(0, 0, (UINT32)address, (UINT32)value); + if (ret) { + WMT_ERR_FUNC("read fucn0 SDIO register fail"); + return ret; + } + return ret; +} + +INT32 wmt_dbg_func0_reg_write(INT32 par1, INT32 address, INT32 value) +{ + INT32 ret = -1; + + ret = wmt_lib_sdio_reg_rw(0, 1, (UINT32)address, (UINT32)value); + if (ret) { + WMT_ERR_FUNC("write func0 SDIO register fail"); + return ret; + } + + return ret; +} + +INT32 wmt_dbg_stp_sdio_reg_read(INT32 par1, INT32 address, INT32 value) +{ + INT32 ret = -1; + + ret = wmt_lib_sdio_reg_rw(2, 0, (UINT32)address, (UINT32)value); + if (ret) { + WMT_ERR_FUNC("read SDIO register fail"); + return ret; + } + + return ret; +} + +INT32 wmt_dbg_stp_sdio_reg_write(INT32 par1, INT32 address, INT32 value) +{ + INT32 ret = -1; + + ret = wmt_lib_sdio_reg_rw(2, 1, (UINT32)address, (UINT32)value); + if (ret) { + WMT_ERR_FUNC("write SDIO register fail"); + return ret; + } + + return ret; +} + +static INT32 wmt_dbg_show_thread_debug_info(INT32 par1, INT32 address, INT32 value) +{ + + osal_dump_thread_state("btif_rxd"); + osal_dump_thread_state("mtk_wmtd"); + osal_dump_thread_state("mtk_stp_psm"); + osal_dump_thread_state("mtk_stp_btm"); + + return 0; +} + +INT32 wmt_dbg_met_ctrl(INT32 par1, INT32 met_ctrl, INT32 log_ctrl) +{ + UINT32 ret = -1; + + ret = wmt_lib_met_ctrl(met_ctrl, log_ctrl); + WMT_INFO_FUNC("met ctrl(0x%08x) met log print to %s, %s\n", + met_ctrl, + log_ctrl == 0 ? "kernel log" : "ftrace log", + ret != 0 ? "failed" : "succeed"); + + return ret; +} + +static INT32 wmt_dbg_fw_log_ctrl(INT32 par1, INT32 onoff, INT32 level) +{ + /* Parameter format + * onoff: + * - bit 24~31: unused + * - bit 16~23: subsys type + * - bit 8~15 : unused + * - bit 0~7 : on/off setting + * level: only lowest 8 bites will be used. + * - bit 8~31 : unused + * - bit 0~7 : log level setting + * Example: + * 1. To turn on MCU log + * onoff = 0x0001 + * 2. To turn on Subsys Z log + * onoff = 0x0z01 (z = subsys) + * 3. To turn off Subsys Z log + * onoff = 0x0z00 (z = subsys) + */ + UINT8 type = (unsigned char)(onoff >> 16); + + WMT_INFO_FUNC("Configuring firmware log: type:%d, on/off:%d, level:%d\n", + type, (unsigned char)onoff, (unsigned char)level); + wmt_lib_fw_log_ctrl(type, (unsigned char)onoff, (unsigned char)level); + + return 0; +} + +INT32 wmt_dbg_pre_pwr_on_ctrl(INT32 par1, INT32 enable, INT32 par3) +{ + MTK_WCN_BOOL ret = MTK_WCN_BOOL_FALSE; + + WMT_INFO_FUNC("%s pre power on function\n", enable ? "enable" : "disable"); + + if (enable) { + /* Turn LPBK off and set always power on flag to 1 */ + ret = mtk_wcn_wmt_func_off(WMTDRV_TYPE_LPBK); + if (!ret) + WMT_WARN_FUNC("mtk_wcn_wmt_func_off(WMTDRV_TYPE_LPBK) return %d\n", ret); + wmt_dev_apo_ctrl(1); + } else { + /* Just set always power on flag to 0 */ + wmt_dev_apo_ctrl(0); + } + + return 0; +} + +#ifdef CONFIG_MTK_ENG_BUILD +INT32 wmt_dbg_step_test(INT32 par1, INT32 par2, INT32 par3) +{ + wmt_step_test_all(); + + return 0; +} +#endif + +INT32 wmt_dbg_thermal_query(INT32 par1, INT32 count, INT32 interval) +{ + LONG tm; + + if (count < 0) + count = 0; + if (interval < 0) + interval = 0; + + WMT_INFO_FUNC("Performing thermal query for %d times with %dms interval\n", count, interval); + while (count--) { + mtk_wcn_wmt_therm_ctrl(WMTTHERM_ENABLE); + tm = mtk_wcn_wmt_therm_ctrl(WMTTHERM_READ); + mtk_wcn_wmt_therm_ctrl(WMTTHERM_DISABLE); + + WMT_INFO_FUNC("Temperature: %ld\n", tm); + if (count > 0) + osal_sleep_ms(interval); + } + return 0; +} + +INT32 wmt_dbg_thermal_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + if (par2 == 0) { + if (par3 >= 99) { + WMT_INFO_FUNC("Can`t set temp threshold greater or queal 99\n"); + return -1; + } + wmt_dev_set_temp_threshold(par3); + } + + return 0; +} + +static INT32 wmt_dbg_step_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + if (par2 == 0) + wmt_step_print_version(); + else if (par2 == 1) { + WMT_INFO_FUNC("STEP show: Start to change config\n"); + wmt_step_deinit(); + wmt_step_init(); + WMT_INFO_FUNC("STEP show: End to change config\n"); + } + + return 0; +} + +INT32 wmt_dbg_ut_test(INT32 par1, INT32 par2, INT32 par3) +{ + INT32 i = 0; + INT32 j = 0; + INT32 iRet = 0; + + i = 20; + while ((i--) > 0) { + WMT_INFO_FUNC("#### UT WMT and STP Function On/Off .... %d\n", i); + j = 10; + while ((j--) > 0) { + WMT_INFO_FUNC("#### BT On .... (%d, %d)\n", i, j); + iRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_BT); + if (iRet == MTK_WCN_BOOL_FALSE) + break; + WMT_INFO_FUNC("#### GPS On .... (%d, %d)\n", i, j); + iRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_GPS); + if (iRet == MTK_WCN_BOOL_FALSE) + break; + WMT_INFO_FUNC("#### GPSL5 On .... (%d, %d)\n", i, j); + iRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_GPSL5); + if (iRet == MTK_WCN_BOOL_FALSE) + break; + WMT_INFO_FUNC("#### FM On .... (%d, %d)\n", i, j); + iRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_FM); + if (iRet == MTK_WCN_BOOL_FALSE) + break; + WMT_INFO_FUNC("#### WIFI On .... (%d, %d)\n", i, j); + iRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_WIFI); + if (iRet == MTK_WCN_BOOL_FALSE) + break; + WMT_INFO_FUNC("#### ANT On .... (%d, %d)\n", i, j); + iRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_ANT); + if (iRet == MTK_WCN_BOOL_FALSE) + break; + + WMT_INFO_FUNC("#### BT Off .... (%d, %d)\n", i, j); + iRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_BT); + if (iRet == MTK_WCN_BOOL_FALSE) + break; + + WMT_INFO_FUNC("#### GPS Off ....(%d, %d)\n", i, j); + iRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_GPS); + if (iRet == MTK_WCN_BOOL_FALSE) + break; + + WMT_INFO_FUNC("#### GPSL5 Off ....(%d, %d)\n", i, j); + iRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_GPSL5); + if (iRet == MTK_WCN_BOOL_FALSE) + break; + + WMT_INFO_FUNC("#### FM Off .... (%d, %d)\n", i, j); + iRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_FM); + if (iRet == MTK_WCN_BOOL_FALSE) + break; + WMT_INFO_FUNC("#### WIFI Off ....(%d, %d)\n", i, j); + iRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_WIFI); + if (iRet == MTK_WCN_BOOL_FALSE) + break; + WMT_INFO_FUNC("#### ANT Off ....(%d, %d)\n", i, j); + iRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_ANT); + if (iRet == MTK_WCN_BOOL_FALSE) + break; + } + + if (iRet == MTK_WCN_BOOL_FALSE) + break; + } + if (iRet == MTK_WCN_BOOL_FALSE) + WMT_INFO_FUNC("#### UT FAIL!!\n"); + else + WMT_INFO_FUNC("#### UT PASS!!\n"); + + return iRet; +} + +#if CFG_CORE_INTERNAL_TXRX +struct lpbk_package { + UINT32 payload_length; + UINT8 out_payload[2048]; + UINT8 in_payload[2048]; +}; + +static INT32 wmt_internal_loopback(INT32 count, INT32 max) +{ + INT32 ret = 0; + INT32 loop; + INT32 offset; + struct lpbk_package lpbk_buffer; + P_OSAL_OP pOp; + P_OSAL_SIGNAL pSignal = NULL; + + for (loop = 0; loop < count; loop++) { + /* <1> init buffer */ + osal_memset((PVOID)&lpbk_buffer, 0, sizeof(struct lpbk_package)); + lpbk_buffer.payload_length = max; + for (offset = 0; offset < max; offset++) + lpbk_buffer.out_payload[offset] = (offset + 1) & 0xFF;/*for test use: begin from 1 */ + + memcpy(&gLpbkBuf[0], &lpbk_buffer.out_payload[0], max); + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + ret = -1; + break; + } + pSignal = &pOp->signal; + pOp->op.opId = WMT_OPID_LPBK; + pOp->op.au4OpData[0] = lpbk_buffer.payload_length; /* packet length */ + pOp->op.au4OpData[1] = (UINT32) &gLpbkBuf[0]; + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + WMT_INFO_FUNC("OPID(%d) type(%zu) start\n", pOp->op.opId, pOp->op.au4OpData[0]); + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed,OPID(%d) type(%zu) abort\n", pOp->op.opId, + pOp->op.au4OpData[0]); + wmt_lib_put_op_to_free_queue(pOp); + ret = -2; + } + + ret = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + if (ret == MTK_WCN_BOOL_FALSE) { + WMT_WARN_FUNC("OPID(%d) type(%zu)fail\n", + pOp->op.opId, pOp->op.au4OpData[0]); + ret = -3; + break; + } + WMT_INFO_FUNC("OPID(%d) length(%zu) ok\n", pOp->op.opId, pOp->op.au4OpData[0]); + + memcpy(&lpbk_buffer.in_payload[0], &gLpbkBuf[0], max); + + ret = pOp->op.au4OpData[0]; + /*<3> compare result */ + if (memcmp(lpbk_buffer.in_payload, lpbk_buffer.out_payload, lpbk_buffer.payload_length)) { + WMT_INFO_FUNC("[%s] WMT_TEST_LPBK_CMD payload compare error\n", __func__); + ret = -4; + break; + } + WMT_ERR_FUNC("[%s] exec WMT_TEST_LPBK_CMD succeed(loop = %d, size = %ld)\n", __func__, loop, + lpbk_buffer.payload_length); + } + + if (loop != count) + WMT_ERR_FUNC("fail at loop(%d) buf_length(%d)\n", loop, max); + + return ret; +} + +INT32 wmt_dbg_internal_lpbk_test(INT32 par1, INT32 par2, INT32 par3) +{ + UINT32 count; + UINT32 length; + + count = par1; + length = par2; + + WMT_INFO_FUNC("count[%d],length[%d]\n", count, length); + + wmt_core_lpbk_do_stp_init(); + + wmt_internal_loopback(count, length); + + wmt_core_lpbk_do_stp_deinit(); + return 0; +} +#endif /* CFG_CORE_INTERNAL_TXRX */ + +static INT32 wmt_dbg_set_mcu_clock(INT32 par1, INT32 par2, INT32 par3) +{ + INT32 ret = 0; + P_OSAL_OP pOp; + P_OSAL_SIGNAL pSignal = NULL; + UINT32 kind = 0; + UINT32 version = 0; + + version = par2; + kind = par3; + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + return -1; + } + pSignal = &pOp->signal; + pOp->op.opId = WMT_OPID_SET_MCU_CLK; + pOp->op.au4OpData[0] = kind; + pOp->op.au4OpData[1] = version; + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + + WMT_INFO_FUNC("OPID(%d) kind(%zu) start\n", pOp->op.opId, pOp->op.au4OpData[0]); + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed,OPID(%d) kind(%zu) abort\n", + pOp->op.opId, pOp->op.au4OpData[0]); + wmt_lib_put_op_to_free_queue(pOp); + return -2; + } + + ret = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + if (ret == MTK_WCN_BOOL_FALSE) { + WMT_WARN_FUNC("OPID(%d) kind(%zu)fail(%d)\n", + pOp->op.opId, pOp->op.au4OpData[0], ret); + return -3; + } + WMT_INFO_FUNC("OPID(%d) kind(%zu) ok\n", pOp->op.opId, pOp->op.au4OpData[0]); + + return ret; +} + +static INT32 wmt_dbg_poll_cpupcr(INT32 par1, INT32 par2, INT32 par3) +{ + UINT32 count = 0; + UINT16 sleep = 0; + UINT16 toAee = 0; + + count = par2; + sleep = (par3 & 0xF0) >> 4; + toAee = (par3 & 0x0F); + + WMT_INFO_FUNC("polling count[%d],polling sleep[%d],toaee[%d]\n", count, sleep, toAee); + stp_dbg_poll_cpupcr(count, sleep, toAee); + + return 0; +} + +#if CONSYS_ENALBE_SET_JTAG +static INT32 wmt_dbg_jtag_flag_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + UINT32 en_flag = par2; + + switch (en_flag) { + case 1: + case 2: + /* gen2 consys does not support 2-wire jtag*/ + wmt_lib_jtag_flag_set(en_flag); + WMT_INFO_FUNC("enable %s mcu jtag pinmux setting\n", en_flag == 1 ? "7-wire" : "2-wire"); + break; + default: + WMT_INFO_FUNC("enable mcu jtag does not support %d options\n", en_flag); + } + + return 0; +} +#endif + +#if CFG_WMT_LTE_COEX_HANDLING +static INT32 wmt_dbg_lte_to_wmt_test(UINT32 opcode, UINT32 msg_len) +{ + conn_md_ipc_ilm_t ilm; + struct local_para *p_buf_str = NULL; + INT32 i = 0; + INT32 iRet = -1; + + WMT_INFO_FUNC("opcode(0x%02x),msg_len(%d)\n", opcode, msg_len); + p_buf_str = osal_malloc(osal_sizeof(struct local_para) + msg_len); + if (p_buf_str == NULL) { + WMT_ERR_FUNC("kmalloc for local para ptr structure failed.\n"); + return -1; + } + p_buf_str->msg_len = msg_len; + for (i = 0; i < msg_len; i++) + p_buf_str->data[i] = i; + + ilm.local_para_ptr = p_buf_str; + ilm.msg_id = opcode; + + iRet = wmt_lib_handle_idc_msg(&ilm); + osal_free(p_buf_str); + return iRet; + +} + +static INT32 wmt_dbg_lte_coex_test(INT32 par1, INT32 par2, INT32 par3) +{ + PUINT8 local_buffer = NULL; + UINT32 handle_len; + INT32 iRet = -1; + + static UINT8 wmt_to_lte_test_evt1[] = { 0x02, 0x16, 0x0d, 0x00, + 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0xa, 0xb + }; + static UINT8 wmt_to_lte_test_evt2[] = { 0x02, 0x16, 0x09, 0x00, + 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 + }; + static UINT8 wmt_to_lte_test_evt3[] = { 0x02, 0x16, 0x02, 0x00, + 0x02, 0xff + }; + static UINT8 wmt_to_lte_test_evt4[] = { 0x02, 0x16, 0x0d, 0x00, + 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0xa, 0xb + }; + + local_buffer = kmalloc(512, GFP_KERNEL); + if (!local_buffer) { + WMT_ERR_FUNC("local_buffer kmalloc memory fail\n"); + return 0; + } + + if (par2 == 1) { + handle_len = wmt_idc_msg_to_lte_handing_for_test(&wmt_to_lte_test_evt1[0], + osal_sizeof(wmt_to_lte_test_evt1)); + if (handle_len != osal_sizeof(wmt_to_lte_test_evt1)) { + WMT_ERR_FUNC("par2=1,wmt send to lte msg fail:handle_len(%d),buff_len(%zu)\n", + handle_len, osal_sizeof(wmt_to_lte_test_evt1)); + } else + WMT_INFO_FUNC("par2=1,wmt send to lte msg OK! send_len(%d)\n", handle_len); + } + if (par2 == 2) { + osal_memcpy(&local_buffer[0], &wmt_to_lte_test_evt1[0], osal_sizeof(wmt_to_lte_test_evt1)); + osal_memcpy(&local_buffer[osal_sizeof(wmt_to_lte_test_evt1)], &wmt_to_lte_test_evt2[0], + osal_sizeof(wmt_to_lte_test_evt2)); + + handle_len = wmt_idc_msg_to_lte_handing_for_test(&local_buffer[0], + osal_sizeof(wmt_to_lte_test_evt1) + osal_sizeof(wmt_to_lte_test_evt2)); + if (handle_len != osal_sizeof(wmt_to_lte_test_evt1) + osal_sizeof(wmt_to_lte_test_evt2)) { + WMT_ERR_FUNC("par2=2,wmt send to lte msg fail:handle_len(%d),buff_len(%zu)\n", + handle_len, + osal_sizeof(wmt_to_lte_test_evt1) + + osal_sizeof(wmt_to_lte_test_evt2)); + } else + WMT_INFO_FUNC("par2=1,wmt send to lte msg OK! send_len(%d)\n", handle_len); + } + if (par2 == 3) { + osal_memcpy(&local_buffer[0], &wmt_to_lte_test_evt1[0], osal_sizeof(wmt_to_lte_test_evt1)); + osal_memcpy(&local_buffer[osal_sizeof(wmt_to_lte_test_evt1)], &wmt_to_lte_test_evt2[0], + osal_sizeof(wmt_to_lte_test_evt2)); + osal_memcpy(&local_buffer[osal_sizeof(wmt_to_lte_test_evt1) + + osal_sizeof(wmt_to_lte_test_evt2)], + &wmt_to_lte_test_evt3[0], osal_sizeof(wmt_to_lte_test_evt3)); + + handle_len = wmt_idc_msg_to_lte_handing_for_test(&local_buffer[0], + osal_sizeof(wmt_to_lte_test_evt1) + + osal_sizeof(wmt_to_lte_test_evt2) + + osal_sizeof(wmt_to_lte_test_evt3)); + if (handle_len != osal_sizeof(wmt_to_lte_test_evt1) + + osal_sizeof(wmt_to_lte_test_evt2) + + osal_sizeof(wmt_to_lte_test_evt3)) { + WMT_ERR_FUNC("par2=3,wmt send to lte msg fail:handle_len(%d),buff_len(%zu)\n", + handle_len, + osal_sizeof(wmt_to_lte_test_evt1) + + osal_sizeof(wmt_to_lte_test_evt2) + + osal_sizeof(wmt_to_lte_test_evt3)); + } else + WMT_INFO_FUNC("par3=1,wmt send to lte msg OK! send_len(%d)\n", handle_len); + } + if (par2 == 4) { + handle_len = wmt_idc_msg_to_lte_handing_for_test(&wmt_to_lte_test_evt4[0], + osal_sizeof(wmt_to_lte_test_evt4)); + if (handle_len != osal_sizeof(wmt_to_lte_test_evt4)) { + WMT_ERR_FUNC("par2=1,wmt send to lte msg fail:handle_len(%d),buff_len(%zu)\n", + handle_len, osal_sizeof(wmt_to_lte_test_evt4)); + } else + WMT_INFO_FUNC("par2=1,wmt send to lte msg OK! send_len(%d)\n", handle_len); + } + if (par2 == 5) { + if (par3 >= 1024) + par3 = 1024; + iRet = wmt_dbg_lte_to_wmt_test(IPC_MSG_ID_EL1_LTE_DEFAULT_PARAM_IND, par3); + WMT_INFO_FUNC("IPC_MSG_ID_EL1_LTE_DEFAULT_PARAM_IND test result(%d)\n", iRet); + } + if (par2 == 6) { + if (par3 >= 1024) + par3 = 1024; + iRet = wmt_dbg_lte_to_wmt_test(IPC_MSG_ID_EL1_LTE_OPER_FREQ_PARAM_IND, par3); + WMT_INFO_FUNC("IPC_MSG_ID_EL1_LTE_OPER_FREQ_PARAM_IND test result(%d)\n", iRet); + } + if (par2 == 7) { + if (par3 >= 1024) + par3 = 1024; + iRet = wmt_dbg_lte_to_wmt_test(IPC_MSG_ID_EL1_WIFI_MAX_PWR_IND, par3); + WMT_INFO_FUNC("IPC_MSG_ID_EL1_WIFI_MAX_PWR_IND test result(%d)\n", iRet); + } + if (par2 == 8) { + if (par3 >= 1024) + par3 = 1024; + iRet = wmt_dbg_lte_to_wmt_test(IPC_MSG_ID_EL1_LTE_TX_IND, par3); + WMT_INFO_FUNC("IPC_MSG_ID_EL1_LTE_TX_IND test result(%d)\n", iRet); + } + if (par2 == 9) { + if (par3 > 0) + wmt_core_set_flag_for_test(1); + else + wmt_core_set_flag_for_test(0); + } + + kfree(local_buffer); + + return 0; +} +#endif /* CFG_WMT_LTE_COEX_HANDLING */ + +ssize_t wmt_dbg_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + INT32 retval = 0; + INT32 i_ret = 0; + PINT8 warn_msg = "no data available, please run echo 15 xx > /proc/driver/wmt_psm first\n"; + + if (*f_pos > 0) + retval = 0; + else { + /*len = sprintf(page, "%d\n", g_psm_enable); */ + if (gCoexBuf.availSize <= 0) { + WMT_INFO_FUNC + ("no data available, please run echo 15 xx > /proc/driver/wmt_psm first\n"); + retval = osal_strlen(warn_msg) + 1; + if (count < retval) + retval = count; + i_ret = copy_to_user(buf, warn_msg, retval); + if (i_ret) { + WMT_ERR_FUNC("copy to buffer failed, ret:%d\n", retval); + retval = -EFAULT; + goto err_exit; + } + *f_pos += retval; + } else { + INT32 i = 0; + INT32 len = 0; + INT8 msg_info[512]; + INT32 max_num = 0; + + /*we do not check page buffer, because there are only 100 bytes in g_coex_buf, */ + /* no reason page buffer is not enough, */ + /* a bomb is placed here on unexpected condition */ + WMT_INFO_FUNC("%d bytes available\n", gCoexBuf.availSize); + max_num = + ((osal_sizeof(msg_info) > + count ? osal_sizeof(msg_info) : count) - 1) / 5; + + if (max_num > gCoexBuf.availSize) { + max_num = gCoexBuf.availSize; + } else { + WMT_INFO_FUNC + ("round to %d bytes due to local buffer size limitation\n", + max_num); + } + + for (i = 0; i < max_num; i++) + len += osal_sprintf(msg_info + len, "0x%02x ", gCoexBuf.buffer[i]); + + len += osal_sprintf(msg_info + len, "\n"); + retval = len; + + i_ret = copy_to_user(buf, msg_info, retval); + if (i_ret) { + WMT_ERR_FUNC("copy to buffer failed, ret:%d\n", retval); + retval = -EFAULT; + goto err_exit; + } + *f_pos += retval; + } + } + gCoexBuf.availSize = 0; + +err_exit: + return retval; +} + +static VOID delay_work_func(struct work_struct *work) +{ + struct wmt_dbg_work *dbgWork = container_of(work, struct wmt_dbg_work, work); + + if (!dbgWork) { + WMT_ERR_FUNC("fail to get dbgWork"); + return; + } + + if ((dbgWork->x >= 0) && (dbgWork->x < 0x33)) + (*wmt_dev_dbg_func[dbgWork->x]) (dbgWork->x, dbgWork->y, dbgWork->z); + + kvfree(dbgWork); +} + +static VOID wmt_dbg_delay_work(INT32 x, INT32 y, INT32 z) +{ + struct wmt_dbg_work *dbgWork; + + dbgWork = kmalloc(sizeof(struct wmt_dbg_work), GFP_KERNEL); + if (!dbgWork) { + WMT_ERR_FUNC("fail to allocate memory"); + return; + } + + dbgWork->x = x; + dbgWork->y = y; + dbgWork->z = z; + + INIT_WORK(&dbgWork->work, delay_work_func); + schedule_work(&dbgWork->work); +} + +ssize_t wmt_dbg_write(struct file *filp, const char __user *buffer, size_t count, loff_t *f_pos) +{ + ULONG len = count; + INT8 buf[256]; + PINT8 pBuf; + INT32 x = 0, y = 0, z = 0; + PINT8 pToken = NULL; + PINT8 pDelimiter = " \t"; + LONG res = 0; + static INT8 dbgEnabled; + + WMT_INFO_FUNC("write parameter len = %d\n\r", (INT32) len); + if (len >= osal_sizeof(buf)) { + WMT_ERR_FUNC("input handling fail!\n"); + len = osal_sizeof(buf) - 1; + return -1; + } + + if (copy_from_user(buf, buffer, len)) + return -EFAULT; + + buf[len] = '\0'; + WMT_INFO_FUNC("write parameter data = %s\n\r", buf); + + pBuf = buf; + pToken = osal_strsep(&pBuf, pDelimiter); + if (pToken != NULL) { + osal_strtol(pToken, 16, &res); + x = (INT32)res; + } else { + x = 0; + } + + pToken = osal_strsep(&pBuf, "\t\n "); + if (pToken != NULL) { + osal_strtol(pToken, 16, &res); + y = (INT32)res; + WMT_INFO_FUNC("y = 0x%08x\n\r", y); + } else { + y = 3000; + /*efuse, register read write default value */ + if (0x11 == x || 0x12 == x || 0x13 == x) + y = 0x80000000; + } + + pToken = osal_strsep(&pBuf, "\t\n "); + if (pToken != NULL) { + if (0x2f == x) + z = osal_strcmp(pToken, "true") ? 0 : 1; + else { + osal_strtol(pToken, 16, &res); + z = (INT32)res; + } + } else { + z = 10; + /*efuse, register read write default value */ + if (0x11 == x || 0x12 == x || 0x13 == x) + z = 0xffffffff; + } + + WMT_INFO_FUNC("x(0x%08x), y(0x%08x), z(0x%08x)\n\r", x, y, z); + + /* For eng and userdebug load, have to enable wmt_dbg by writing 0xDB9DB9 to + * "/proc/driver/wmt_dbg" to avoid some malicious use + */ +#if (WMT_DBG_SUPPORT) + if (0xDB9DB9 == x) { + dbgEnabled = 1; + return len; + } +#endif + /* Commands allowed to execute in user load + * 0x15: assert control + * 0x2e: enable catch connsys log + * 0x2f: set bt link status + * 0x32: alarm dump control + */ + if (0 == dbgEnabled && 0x15 != x && 0x2e != x && 0x2f != x && + 0x7 != x && x != 0x32) { + WMT_INFO_FUNC("please enable WMT debug first\n\r"); + return len; + } + + if (osal_array_size(wmt_dev_dbg_func) > x && NULL != wmt_dev_dbg_func[x]) + if (x == 0x7) + wmt_dbg_delay_work(x, y, z); + else + (*wmt_dev_dbg_func[x]) (x, y, z); + else + WMT_WARN_FUNC("no handler defined for command id(0x%08x)\n\r", x); + + return len; +} + +INT32 wmt_dev_dbg_setup(VOID) +{ + static const struct file_operations wmt_dbg_fops = { + .owner = THIS_MODULE, + .read = wmt_dbg_read, + .write = wmt_dbg_write, + }; + INT32 i_ret = 0; + + gWmtDbgEntry = proc_create(WMT_DBG_PROCNAME, 0664, NULL, &wmt_dbg_fops); + if (gWmtDbgEntry == NULL) { + WMT_ERR_FUNC("Unable to create / wmt_aee proc entry\n\r"); + i_ret = -1; + } + osal_sleepable_lock_init(&g_dbg_emi_lock); + + return i_ret; +} + +INT32 wmt_dev_dbg_remove(VOID) +{ + if (gWmtDbgEntry != NULL) + proc_remove(gWmtDbgEntry); + + osal_sleepable_lock_deinit(&g_dbg_emi_lock); + +#if CFG_WMT_PS_SUPPORT + wmt_lib_ps_deinit(); +#endif + return 0; +} + +INT32 wmt_dbg_gps_suspend(INT32 par1, INT32 par2, INT32 par3) +{ + MTK_WCN_BOOL suspend = (par2 != 0) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE; + + WMT_INFO_FUNC("GPS %s mode test, type(%d, %s)\n", + (par2 != 0) ? "suspend" : "resume", + par3, (par3 == 0) ? "L1+L5" : ((par3 == 1) ? "L1" : "L5")); + + if (par3 == 0) + mtk_wmt_gps_suspend_ctrl(suspend); + else if (par3 == 1) + mtk_wmt_gps_l1_suspend_ctrl(suspend); + else + mtk_wmt_gps_l5_suspend_ctrl(suspend); + + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_dev.c b/drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_dev.c new file mode 100644 index 0000000000000..61e0e1444a7cf --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_dev.c @@ -0,0 +1,1779 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/*! \file + * \brief brief description + * + * Detailed descriptions here. + * + */ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-DEV]" + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#ifdef CONFIG_COMPAT +#include +#endif +#include +#if WMT_CREATE_NODE_DYNAMIC +#include +#endif +#ifdef CONFIG_EARLYSUSPEND +#include +#else +#include +#endif +#include +#include +#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_dbg.h" +#include "wmt_user_proc.h" +#include "psm_core.h" +#include "stp_core.h" +#include "stp_exp.h" +#include "bgw_desense.h" +#include "wmt_idc.h" +#include "wmt_detect.h" +#include "hif_sdio.h" +#include "wmt_step.h" +#include "wmt_proc_dbg.h" +#include "wmt_alarm.h" + +#include "connsys_debug_utility.h" + +#ifdef CONFIG_COMPAT +#define COMPAT_WMT_IOCTL_SET_PATCH_NAME _IOW(WMT_IOC_MAGIC, 4, compat_uptr_t) +#define COMPAT_WMT_IOCTL_LPBK_TEST _IOWR(WMT_IOC_MAGIC, 8, compat_uptr_t) +#define COMPAT_WMT_IOCTL_SET_PATCH_INFO _IOW(WMT_IOC_MAGIC, 15, compat_uptr_t) +#define COMPAT_WMT_IOCTL_PORT_NAME _IOWR(WMT_IOC_MAGIC, 20, compat_uptr_t) +#define COMPAT_WMT_IOCTL_WMT_CFG_NAME _IOWR(WMT_IOC_MAGIC, 21, compat_uptr_t) +#define COMPAT_WMT_IOCTL_SEND_BGW_DS_CMD _IOW(WMT_IOC_MAGIC, 25, compat_uptr_t) +#define COMPAT_WMT_IOCTL_ADIE_LPBK_TEST _IOWR(WMT_IOC_MAGIC, 26, compat_uptr_t) +#define COMPAT_WMT_IOCTL_DYNAMIC_DUMP_CTRL _IOR(WMT_IOC_MAGIC, 30, compat_uptr_t) +#define COMPAT_WMT_IOCTL_SET_ROM_PATCH_INFO _IOW(WMT_IOC_MAGIC, 31, compat_uptr_t) +#define COMPAT_WMT_IOCTL_GET_VENDOR_PATCH_VERSION _IOR(WMT_IOC_MAGIC, 36, compat_uptr_t) +#define COMPAT_WMT_IOCTL_SET_VENDOR_PATCH_VERSION _IOW(WMT_IOC_MAGIC, 37, compat_uptr_t) +#define COMPAT_WMT_IOCTL_SET_ACTIVE_PATCH_VERSION _IOR(WMT_IOC_MAGIC, 40, compat_uptr_t) +#define COMPAT_WMT_IOCTL_GET_ACTIVE_PATCH_VERSION _IOR(WMT_IOC_MAGIC, 41, compat_uptr_t) +#endif + +#define WMT_IOC_MAGIC 0xa0 +#define WMT_IOCTL_SET_PATCH_NAME _IOW(WMT_IOC_MAGIC, 4, char*) +#define WMT_IOCTL_SET_STP_MODE _IOW(WMT_IOC_MAGIC, 5, int) +#define WMT_IOCTL_FUNC_ONOFF_CTRL _IOW(WMT_IOC_MAGIC, 6, int) +#define WMT_IOCTL_LPBK_POWER_CTRL _IOW(WMT_IOC_MAGIC, 7, int) +#define WMT_IOCTL_LPBK_TEST _IOWR(WMT_IOC_MAGIC, 8, char*) +#define WMT_IOCTL_GET_CHIP_INFO _IOR(WMT_IOC_MAGIC, 12, int) +#define WMT_IOCTL_SET_LAUNCHER_KILL _IOW(WMT_IOC_MAGIC, 13, int) +#define WMT_IOCTL_SET_PATCH_NUM _IOW(WMT_IOC_MAGIC, 14, int) +#define WMT_IOCTL_SET_PATCH_INFO _IOW(WMT_IOC_MAGIC, 15, char*) +#define WMT_IOCTL_PORT_NAME _IOWR(WMT_IOC_MAGIC, 20, char*) +#define WMT_IOCTL_WMT_CFG_NAME _IOWR(WMT_IOC_MAGIC, 21, char*) +#define WMT_IOCTL_WMT_QUERY_CHIPID _IOR(WMT_IOC_MAGIC, 22, int) +#define WMT_IOCTL_WMT_TELL_CHIPID _IOW(WMT_IOC_MAGIC, 23, int) +#define WMT_IOCTL_WMT_COREDUMP_CTRL _IOW(WMT_IOC_MAGIC, 24, int) +#define WMT_IOCTL_SEND_BGW_DS_CMD _IOW(WMT_IOC_MAGIC, 25, char*) +#define WMT_IOCTL_ADIE_LPBK_TEST _IOWR(WMT_IOC_MAGIC, 26, char*) +#define WMT_IOCTL_WMT_STP_ASSERT_CTRL _IOW(WMT_IOC_MAGIC, 27, int) +#define WMT_IOCTL_FW_DBGLOG_CTRL _IOR(WMT_IOC_MAGIC, 29, int) +#define WMT_IOCTL_DYNAMIC_DUMP_CTRL _IOR(WMT_IOC_MAGIC, 30, char*) +#define WMT_IOCTL_SET_ROM_PATCH_INFO _IOW(WMT_IOC_MAGIC, 31, char*) +#define WMT_IOCTL_GET_EMI_PHY_SIZE _IOR(WMT_IOC_MAGIC, 33, unsigned int) +#define WMT_IOCTL_FW_PATCH_UPDATE_RST _IOR(WMT_IOC_MAGIC, 34, int) +#define WMT_IOCTL_GET_VENDOR_PATCH_NUM _IOW(WMT_IOC_MAGIC, 35, int) +#define WMT_IOCTL_GET_VENDOR_PATCH_VERSION _IOR(WMT_IOC_MAGIC, 36, char*) +#define WMT_IOCTL_SET_VENDOR_PATCH_VERSION _IOW(WMT_IOC_MAGIC, 37, char*) +#define WMT_IOCTL_GET_CHECK_PATCH_STATUS _IOR(WMT_IOC_MAGIC, 38, int) +#define WMT_IOCTL_SET_CHECK_PATCH_STATUS _IOW(WMT_IOC_MAGIC, 39, int) +#define WMT_IOCTL_SET_ACTIVE_PATCH_VERSION _IOR(WMT_IOC_MAGIC, 40, char*) +#define WMT_IOCTL_GET_ACTIVE_PATCH_VERSION _IOR(WMT_IOC_MAGIC, 41, char*) +#define WMT_IOCTL_GET_DIRECT_PATH_EMI_SIZE _IOR(WMT_IOC_MAGIC, 42, unsigned int) + +#define MTK_WMT_VERSION "Consys WMT Driver - v1.0" +#define MTK_WMT_DATE "2013/01/20" +#define WMT_DEV_MAJOR 190 /* never used number */ +#define WMT_DEV_NUM 1 +#define WMT_DEV_INIT_TO_MS (2 * 1000) +#define DYNAMIC_DUMP_BUF 109 + +#define WMT_DRIVER_NAME "mtk_stp_wmt" + +P_OSAL_EVENT gpRxEvent; + +UINT32 u4RxFlag; +static atomic_t gRxCount = ATOMIC_INIT(0); + +/* Linux UINT8 device */ +static INT32 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 }; + +static UINT32 gLpbkBufLog; /* George LPBK debug */ + +enum wmt_init_status { + WMT_INIT_NOT_START, + WMT_INIT_START, + WMT_INIT_DONE, +}; +static INT32 gWmtInitStatus = WMT_INIT_NOT_START; +static wait_queue_head_t gWmtInitWq; +#ifdef CONFIG_MTK_COMBO_COMM_APO +UINT32 always_pwr_on_flag = 1; +#else +UINT32 always_pwr_on_flag; +#endif +P_WMT_PATCH_INFO pPatchInfo; +UINT32 pAtchNum; +UINT32 currentLpbkStatus; +#define TEMP_THRESHOLD 60 +static INT32 gTemperatureThreshold = TEMP_THRESHOLD; + +#if WMT_CREATE_NODE_DYNAMIC +struct class *wmt_class; +struct device *wmt_dev; +#endif + + +/*LCM on/off ctrl for wmt varabile*/ +UINT32 hif_info; +UINT8 gWmtClose; +static struct work_struct gPwrOnOffWork; +static atomic_t g_es_lr_flag_for_quick_sleep = ATOMIC_INIT(1); /* for ctrl quick sleep flag */ +static atomic_t g_es_lr_flag_for_lpbk_onoff = ATOMIC_INIT(0); /* for ctrl lpbk on off */ + +/*BLANK on/off ctrl for wmt varabile*/ +static atomic_t g_es_lr_flag_for_blank = ATOMIC_INIT(0); /* for ctrl blank flag */ +static atomic_t g_late_pwr_on_for_blank = ATOMIC_INIT(0); /* PwrOnOff Late flag */ + +/* Prevent race condition when wmt_dev_tm_temp_query is called concurrently */ +static OSAL_UNSLEEPABLE_LOCK g_temp_query_spinlock; + +#ifdef CONFIG_EARLYSUSPEND +static VOID wmt_dev_early_suspend(struct early_suspend *h) +{ + atomic_set(&g_es_lr_flag_for_quick_sleep, 1); + atomic_set(&g_es_lr_flag_for_lpbk_onoff, 0); + atomic_set(&g_es_lr_flag_for_blank, 0); + + WMT_WARN_FUNC("@@@@@@@@@@wmt enter early suspend@@@@@@@@@@@@@@\n"); + + schedule_work(&gPwrOnOffWork); +} + +static VOID wmt_dev_late_resume(struct early_suspend *h) +{ + atomic_set(&g_es_lr_flag_for_quick_sleep, 0); + atomic_set(&g_es_lr_flag_for_lpbk_onoff, 1); + atomic_set(&g_es_lr_flag_for_blank, 1); + + WMT_WARN_FUNC("@@@@@@@@@@wmt enter late resume@@@@@@@@@@@@@@\n"); + + schedule_work(&gPwrOnOffWork); + +} + +struct early_suspend wmt_early_suspend_handler = { + .suspend = wmt_dev_early_suspend, + .resume = wmt_dev_late_resume, +}; + +#else + +static struct notifier_block wmt_fb_notifier; +static INT32 wmt_fb_notifier_callback(struct notifier_block *self, ULONG event, PVOID data) +{ + struct fb_event *evdata = data; + INT32 blank; + + WMT_DBG_FUNC("wmt_fb_notifier_callback\n"); + + /* If we aren't interested in this event, skip it immediately ... */ + if (event != FB_EVENT_BLANK) + return 0; + + blank = *(INT32 *)evdata->data; + WMT_DBG_FUNC("fb_notify(blank=%d)\n", blank); + + switch (blank) { + case FB_BLANK_UNBLANK: + atomic_set(&g_es_lr_flag_for_quick_sleep, 0); + atomic_set(&g_es_lr_flag_for_lpbk_onoff, 1); + atomic_set(&g_es_lr_flag_for_blank, 1); + WMT_WARN_FUNC("@@@@@@@@@@wmt enter UNBLANK @@@@@@@@@@@@@@\n"); + if (hif_info == 0) { + atomic_set(&g_late_pwr_on_for_blank, 1); + break; + } + schedule_work(&gPwrOnOffWork); + break; + case FB_BLANK_POWERDOWN: + atomic_set(&g_es_lr_flag_for_quick_sleep, 1); + atomic_set(&g_es_lr_flag_for_lpbk_onoff, 0); + atomic_set(&g_es_lr_flag_for_blank, 0); + WMT_WARN_FUNC("@@@@@@@@@@wmt enter early POWERDOWN @@@@@@@@@@@@@@\n"); + schedule_work(&gPwrOnOffWork); + break; + default: + break; + } + return 0; +} +#endif /* CONFIG_EARLYSUSPEND */ +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +INT32 wmt_dev_apo_ctrl(UINT32 enable) +{ + always_pwr_on_flag = enable ? 1 : 0; + if (!always_pwr_on_flag) + schedule_work(&gPwrOnOffWork); + WMT_INFO_FUNC("always_pwr_on_flag: %d\n", always_pwr_on_flag); + + return 0; +} + +static VOID wmt_pwr_on_off_handler(struct work_struct *work) +{ + INT32 retry = 5; + INT32 desync = 0; + + WMT_DBG_FUNC("wmt_pwr_on_off_handler start to run\n"); + + /* Update blank off status before wmt power off */ + if (wmt_dev_get_blank_state() == 0) { + wmt_dev_blank_handler(); + connsys_log_blank_state_changed(0); + } + + if (always_pwr_on_flag == 0) { + while ((wmt_lib_get_drv_status(WMTDRV_TYPE_LPBK) == DRV_STS_FUNC_ON) != + atomic_read(&g_es_lr_flag_for_lpbk_onoff)) { + if (++desync > 1) + WMT_WARN_FUNC("suspend/resume not sync count:%d\n", desync); + if (wmt_lpbk_handler(atomic_read(&g_es_lr_flag_for_lpbk_onoff), retry) < 0) + break; + } + } + + /* Update blank on status after wmt power on */ + if (wmt_dev_get_blank_state() == 1) { + wmt_dev_blank_handler(); + connsys_log_blank_state_changed(1); + } +} + +INT32 wmt_lpbk_handler(UINT32 on_off_flag, UINT32 retry) +{ + UINT32 retry_count; + + retry_count = retry; + do { + if (on_off_flag) { + if (mtk_wcn_wmt_func_on(WMTDRV_TYPE_LPBK) == MTK_WCN_BOOL_FALSE) { + WMT_WARN_FUNC("WMT turn on LPBK fail, retrying, retryCounter left:%d!\n", + retry_count); + retry_count--; + osal_sleep_ms(1000); + } else { + WMT_DBG_FUNC("WMT turn on LPBK suceed\n"); + break; + } + } else { + if (mtk_wcn_wmt_func_off(WMTDRV_TYPE_LPBK) == MTK_WCN_BOOL_FALSE) { + WMT_WARN_FUNC("WMT turn off LPBK fail, retrying, retryCounter left:%d!\n", + retry_count); + retry_count--; + osal_sleep_ms(1000); + } else { + WMT_DBG_FUNC("WMT turn off LPBK suceed\n"); + break; + } + } + } while (retry_count > 0); + return ((wmt_lib_get_drv_status(WMTDRV_TYPE_LPBK) == DRV_STS_FUNC_ON) == on_off_flag) - 1; +} + +VOID wmt_dev_blank_handler(VOID) +{ + WMT_DBG_FUNC("wmt_dev_blank_handler start to run\n"); + + if (wmt_lib_get_blank_status() != wmt_dev_get_blank_state()) + if (wmt_lib_blank_status_ctrl(wmt_dev_get_blank_state())) + WMT_WARN_FUNC("mtk_lib_blank_status_ctrl failed\n"); +} + +UINT32 wmt_dev_get_blank_state(VOID) +{ + return atomic_read(&g_es_lr_flag_for_blank); +} + +MTK_WCN_BOOL wmt_dev_get_early_suspend_state(VOID) +{ + MTK_WCN_BOOL bRet = + (atomic_read(&g_es_lr_flag_for_quick_sleep) == 0) ? MTK_WCN_BOOL_FALSE : MTK_WCN_BOOL_TRUE; + /* WMT_INFO_FUNC("bRet:%d\n", bRet); */ + return bRet; +} + +VOID wmt_dev_rx_event_cb(VOID) +{ + u4RxFlag = 1; + atomic_inc(&gRxCount); + if (gpRxEvent != NULL) { + /* 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 (ms != 0) + 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; +} + +/* TODO: [ChangeFeature][George] refine this function name for general filesystem read operation, not patch only. */ +INT32 wmt_dev_patch_get(PUINT8 pPatchName, osal_firmware **ppPatch) +{ + INT32 iRet = -1; + osal_firmware *fw = NULL; + + if (!ppPatch) { + WMT_ERR_FUNC("invalid ppBufptr!\n"); + return -1; + } + *ppPatch = NULL; + do { + iRet = request_firmware((const struct firmware **)&fw, pPatchName, NULL); + if (iRet == -EAGAIN) { + WMT_ERR_FUNC("failed to open or read!(%s), retry again!\n", pPatchName); + osal_sleep_ms(100); + } + } while (iRet == -EAGAIN); + if (iRet != 0) { + WMT_ERR_FUNC("failed to open or read!(%s)\n", pPatchName); + release_firmware(fw); + return -1; + } + WMT_DBG_FUNC("loader firmware %s ok!!\n", pPatchName); + iRet = 0; + *ppPatch = fw; + + return iRet; +} +EXPORT_SYMBOL(wmt_dev_patch_get); + +INT32 wmt_dev_patch_put(osal_firmware **ppPatch) +{ + if (*ppPatch != NULL) { + release_firmware((const struct firmware *)*ppPatch); + *ppPatch = NULL; + } + return 0; +} + +VOID wmt_dev_patch_info_free(VOID) +{ + kfree(pPatchInfo); + pPatchInfo = NULL; + wmt_lib_set_patch_info(NULL); +} + +MTK_WCN_BOOL wmt_dev_is_file_exist(PUINT8 pFileName) +{ + INT32 iRet = 0; + osal_firmware *fw = NULL; + + 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; + } + + iRet = request_firmware((const struct firmware **)&fw, pFileName, NULL); + if (iRet != 0) { + WMT_ERR_FUNC("failed to open or read!(%s)\n", pFileName); + release_firmware(fw); + return MTK_WCN_BOOL_FALSE; + } + release_firmware(fw); + return true; +} + +static ULONG count_last_access_sdio; +static ULONG count_last_access_btif; +static ULONG count_last_access_uart; +static ULONG jiffies_last_poll; + +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_bitf_update(VOID) +{ + count_last_access_btif += 1; + /* WMT_INFO_FUNC("jiffies_last_access_btif: 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_btif: jiffies = %ul\n", jiffies); */ + + return 0; +} + +static UINT32 wmt_dev_tra_poll(VOID) +{ +#define TIME_THRESHOLD_TO_TEMP_QUERY 3000 +#define COUNT_THRESHOLD_TO_TEMP_QUERY 200 + + ULONG during_count = 0; + ULONG poll_during_time = 0; + ENUM_WMT_CHIP_TYPE chip_type; + + chip_type = wmt_detect_get_chip_type(); + /* if (jiffies > jiffies_last_poll) */ + if (time_after(jiffies, jiffies_last_poll)) + poll_during_time = jiffies - jiffies_last_poll; + else + poll_during_time = 0xffffffff; + + WMT_DBG_FUNC("**jiffies_to_mesecs(0xffffffff) = %d\n", jiffies_to_msecs(0xffffffff)); + + if (jiffies_to_msecs(poll_during_time) < TIME_THRESHOLD_TO_TEMP_QUERY) { + WMT_DBG_FUNC("**poll_during_time = %d < %d, not to query\n", + jiffies_to_msecs(poll_during_time), TIME_THRESHOLD_TO_TEMP_QUERY); + return -1; + } + + switch (chip_type) { + case WMT_CHIP_TYPE_COMBO: + during_count = count_last_access_sdio; + break; + case WMT_CHIP_TYPE_SOC: + if (mtk_wcn_wlan_bus_tx_cnt == NULL) { + WMT_ERR_FUNC("WMT-DEV:mtk_wcn_wlan_bus_tx_cnt null pointer\n"); + return -1; + } + if (mtk_wcn_wlan_bus_tx_cnt_clr == NULL) { + WMT_ERR_FUNC("WMT-DEV:mtk_wcn_wlan_bus_tx_cnt_clr null pointer\n"); + return -3; + } + during_count = (*mtk_wcn_wlan_bus_tx_cnt)(); + break; + default: + WMT_ERR_FUNC("WMT-DEV:error chip type(%d)\n", chip_type); + } + + if (during_count < COUNT_THRESHOLD_TO_TEMP_QUERY) { + WMT_DBG_FUNC("**during_count = %lu < %d, not to query\n", during_count, + COUNT_THRESHOLD_TO_TEMP_QUERY); + return -2; + } + + jiffies_last_poll = jiffies; + if (chip_type == WMT_CHIP_TYPE_COMBO) + count_last_access_sdio = 0; + else if (chip_type == WMT_CHIP_TYPE_SOC) + (*mtk_wcn_wlan_bus_tx_cnt_clr)(); + else + WMT_ERR_FUNC("WMT-DEV:error chip type(%d)\n", chip_type); + WMT_INFO_FUNC("**poll_during_time = %d > %d, during_count = %d > %d, query\n", + jiffies_to_msecs(poll_during_time), TIME_THRESHOLD_TO_TEMP_QUERY, + jiffies_to_msecs(during_count), COUNT_THRESHOLD_TO_TEMP_QUERY); + + return 0; +} + +VOID wmt_dev_set_temp_threshold(INT32 val) +{ + gTemperatureThreshold = val; + WMT_INFO_FUNC("Set temperature threashold to %d\n", val); +} + +LONG wmt_dev_tm_temp_query(VOID) +{ +#define HISTORY_NUM 3 +#define REFRESH_TIME 300 /* sec */ +#define ONE_DAY_LONG 86400 /* sec */ + + static INT32 s_temp_table[HISTORY_NUM] = { 99 }; /* not query yet. */ + static INT32 s_idx_temp_table; + static struct timeval s_query_time; + static struct timeval sync_log_last_time = {0, 0}; + + INT32 temp_table[HISTORY_NUM]; + INT32 idx_temp_table; + struct timeval query_time; + + struct timeval now_time; + INT32 current_temp = 0; + INT32 index = 0; + LONG return_temp = 0; + INT8 query_cond = 0; + + /* Let us work on the copied version of function static variables */ + osal_lock_unsleepable_lock(&g_temp_query_spinlock); + osal_memcpy(temp_table, s_temp_table, sizeof(s_temp_table)); + osal_memcpy(&query_time, &s_query_time, sizeof(struct timeval)); + idx_temp_table = s_idx_temp_table; + osal_unlock_unsleepable_lock(&g_temp_query_spinlock); + + /* 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] >= gTemperatureThreshold) { + query_cond = 1; + WMT_DBG_FUNC + ("temperature table is still initial value, we should query temp temperature..\n"); + } + } + + osal_do_gettimeofday(&now_time); +#if 1 + /* Query condition 2: */ + /* Moniter the bus activity to decide if we have the need to query temperature. */ + if (!query_cond) { + if (wmt_dev_tra_poll() == 0) { + query_cond = 1; + WMT_DBG_FUNC("traffic , we must query temperature..\n"); + } else if (temp_table[idx_temp_table] >= gTemperatureThreshold) { + WMT_INFO_FUNC("temperature maybe greater than %d, query temperature\n", gTemperatureThreshold); + query_cond = 1; + } else + WMT_DBG_FUNC("idle traffic ....\n"); + + /* only WIFI tx power might make temperature varies largely */ +#if 0 + if (!query_cond) { + last_access_time = wmt_dev_tra_uart_poll(); + if (jiffies_to_msecs(last_access_time) < TIME_THRESHOLD_TO_TEMP_QUERY) { + query_cond = 1; + WMT_DBG_FUNC("uart busy traffic , we must query temperature..\n"); + } else { + WMT_DBG_FUNC("uart still idle traffic , we don't query temp temperature..\n"); + } + } +#endif + } +#endif + /* Query condition 3: */ + /* If the query time exceeds the a certain of period, refresh temp table. */ + /* */ + if (!query_cond) { + /* time overflow, we refresh temp table again for simplicity! */ + if ((now_time.tv_sec < query_time.tv_sec) || + ((now_time.tv_sec > query_time.tv_sec) && + (now_time.tv_sec - query_time.tv_sec) > REFRESH_TIME)) { + query_cond = 1; + + WMT_INFO_FUNC + ("It is long time (prev(%lu), now(%lu), > %d sec) not to query, query temp again..\n", + query_time.tv_sec, now_time.tv_sec, REFRESH_TIME); + for (index = 0; index < HISTORY_NUM; index++) + temp_table[index] = 99; + + } + } + + /* update utc time for fw once a day */ + if ((now_time.tv_sec < sync_log_last_time.tv_sec) || + ((now_time.tv_sec - sync_log_last_time.tv_sec) > ONE_DAY_LONG)) { + sync_log_last_time.tv_sec = now_time.tv_sec; + wmt_lib_utc_time_sync(); + } + + 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); + + /* Only update temperature if our index hasn't been modified by the concurrent thread */ + osal_lock_unsleepable_lock(&g_temp_query_spinlock); + if (idx_temp_table == s_idx_temp_table) { + osal_memcpy(s_temp_table, temp_table, sizeof(s_temp_table)); + s_idx_temp_table = (s_idx_temp_table + 1) % HISTORY_NUM; + s_temp_table[s_idx_temp_table] = current_temp; + osal_do_gettimeofday(&s_query_time); + index = -1; + } else { + index = s_idx_temp_table; + } + osal_unlock_unsleepable_lock(&g_temp_query_spinlock); + + if (index == -1) { + WMT_INFO_FUNC("[Thermal] current_temp = 0x%x\n", (current_temp & 0xFF)); + } else { + WMT_ERR_FUNC("Temperature(0x%x) update failed due to modified idx_temp_table(%d, %d)", + (current_temp & 0xFF), idx_temp_table, index); + } + } else { + /* Only update temperature if our index hasn't been modified by the concurrent thread */ + osal_lock_unsleepable_lock(&g_temp_query_spinlock); + if (idx_temp_table == s_idx_temp_table) { + current_temp = s_temp_table[s_idx_temp_table]; + s_idx_temp_table = (s_idx_temp_table + 1) % HISTORY_NUM; + s_temp_table[s_idx_temp_table] = current_temp; + index = -1; + } else { + /* Return the last valid temperature which has just been modified by the concurrent thread */ + current_temp = s_temp_table[s_idx_temp_table]; + index = s_idx_temp_table; + } + osal_unlock_unsleepable_lock(&g_temp_query_spinlock); + if (index != -1) { + WMT_DBG_FUNC("Use last valid temperature (0x%x) due to modified idx_temp_table(%d, %d)", + (current_temp & 0xFF), idx_temp_table, index); + } + } + + /* */ + /* Dump information */ + /* */ + if (gWmtDbgLvl >= WMT_LOG_DBG) { + osal_lock_unsleepable_lock(&g_temp_query_spinlock); + WMT_DBG_FUNC("[Thermal] s_idx_temp_table = %d, idx_temp_table = %d\n", + s_idx_temp_table, idx_temp_table); + WMT_DBG_FUNC("[Thermal] now.time = %lu, s_query.time = %lu, query.time = %lu, REFRESH_TIME = %d\n", + now_time.tv_sec, s_query_time.tv_sec, query_time.tv_sec, REFRESH_TIME); + + WMT_DBG_FUNC("[0] = %d, [1] = %d, [2] = %d\n----\n", + s_temp_table[0], s_temp_table[1], s_temp_table[2]); + osal_unlock_unsleepable_lock(&g_temp_query_spinlock); + } + + return_temp = ((current_temp & 0x80) == 0x0) ? current_temp : (-1) * (current_temp & 0x7f); + + return return_temp; +} + +ssize_t WMT_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) +{ + INT32 iRet = 0; + UINT8 wrBuf[NAME_MAX + 1] = { 0 }; + INT32 copySize = (count < NAME_MAX) ? count : NAME_MAX; + + WMT_LOUD_FUNC("count:%zu copySize:%d\n", count, copySize); + + if (copySize > 0) { + if (copy_from_user(wrBuf, buf, copySize)) { + iRet = -EFAULT; + goto write_done; + } + iRet = copySize; + wrBuf[NAME_MAX] = '\0'; + + if (!strncasecmp(wrBuf, "ok", NAME_MAX)) { + WMT_DBG_FUNC("resp str ok\n"); + /* pWmtDevCtx->cmd_result = 0; */ + wmt_lib_trigger_cmd_signal(0); + } else { + WMT_WARN_FUNC("warning resp str (%s)\n", wrBuf); + /* pWmtDevCtx->cmd_result = -1; */ + wmt_lib_trigger_cmd_signal(-1); + } + /* complete(&pWmtDevCtx->cmd_comp); */ + } + +write_done: + return iRet; +} + +ssize_t WMT_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + INT32 iRet = 0; + PUINT8 pCmd = NULL; + UINT32 cmdLen = 0; + + pCmd = wmt_lib_get_cmd(); + + if (pCmd != NULL) { + cmdLen = osal_strlen(pCmd) < NAME_MAX ? osal_strlen(pCmd) : NAME_MAX; + if (cmdLen > count) + cmdLen = count; + 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; +} + +UINT32 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 (wmt_lib_get_cmd_status() == MTK_WCN_BOOL_TRUE) + 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, UINT32 cmd, ULONG arg) +{ + INT32 iRet = 0; + UINT8 *pBuffer = NULL; + + WMT_DBG_FUNC("cmd (%u), arg (0x%lx)\n", cmd, arg); + switch (cmd) { + case WMT_IOCTL_SET_PATCH_NAME: /* patch location */ + { + pBuffer = kmalloc(NAME_MAX + 1, GFP_KERNEL); + if (!pBuffer) { + WMT_ERR_FUNC("pBuffer kmalloc memory fail\n"); + return 0; + } + if (copy_from_user(pBuffer, (PVOID)arg, NAME_MAX)) { + iRet = -EFAULT; + kfree(pBuffer); + break; + } + pBuffer[NAME_MAX] = '\0'; + wmt_lib_set_patch_name(pBuffer); + kfree(pBuffer); + } + break; + case WMT_IOCTL_SET_STP_MODE: /* stp/hif/fm mode */ + /* set hif conf */ + do { + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal = NULL; + P_WMT_HIF_CONF pHif = NULL; + + if (hif_info == 1) { + WMT_INFO_FUNC("hif_info had been set!\n"); + break; + } + + iRet = wmt_lib_set_hif(arg); + if (iRet != 0) { + WMT_INFO_FUNC("wmt_lib_set_hif fail (%lu)\n", arg); + 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 = (bRet == MTK_WCN_BOOL_FALSE) ? -EFAULT : 0; + if (iRet == 0) { + WMT_INFO_FUNC("luncher set STP mode success!\n"); + hif_info = 1; + + if (atomic_read(&g_late_pwr_on_for_blank) && + atomic_read(&g_es_lr_flag_for_blank)) { + atomic_set(&g_late_pwr_on_for_blank, 0); + schedule_work(&gPwrOnOffWork); + } + } + } while (0); + break; + case WMT_IOCTL_FUNC_ONOFF_CTRL: /* test turn on/off func */ +#if WMT_DBG_SUPPORT + do { + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + + if (arg >> 4 == 0xBEEF000) + bRet = mtk_wcn_wmt_func_on(arg & 0xF); + else if (arg >> 4 == 0xDEAD000) + bRet = mtk_wcn_wmt_func_off(arg & 0xF); + + iRet = (bRet == MTK_WCN_BOOL_FALSE) ? -EFAULT : 0; + } while (0); +#endif + break; + case WMT_IOCTL_LPBK_POWER_CTRL: + do { + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_TRUE; + + switch (arg) { + case 0: + if (always_pwr_on_flag) + bRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_LPBK); + break; + case 1: + if (always_pwr_on_flag) + bRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_LPBK); + break; + case 2: + bRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_LPBK); + break; + case 3: + bRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_LPBK); + break; + } + iRet = (bRet == MTK_WCN_BOOL_TRUE) ? 0 : -EFAULT; + } 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, (PVOID)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); + + u4Wait = 2000; + if (copy_from_user(&gLpbkBuf[0], (PVOID)arg + sizeof(effectiveLen), effectiveLen)) { + WMT_ERR_FUNC("copy_from_user failed at %d\n", __LINE__); + iRet = -EFAULT; + break; + } + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + iRet = -EFAULT; + break; + } + pSignal = &pOp->signal; + pOp->op.opId = WMT_OPID_LPBK; + pOp->op.au4OpData[0] = effectiveLen; /* packet length */ + pOp->op.au4OpData[1] = (SIZE_T)&gLpbkBuf[0]; /* packet buffer pointer */ + memcpy(&gLpbkBufLog, &gLpbkBuf[((effectiveLen >= 4) ? effectiveLen - 4 : 0)], 4); + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + WMT_INFO_FUNC("OPID(%d) type(%zu) start\n", pOp->op.opId, pOp->op.au4OpData[0]); + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed,OPID(%d) type(%d) abort\n", + pOp->op.opId, pOp->op.au4OpData[0]); + wmt_lib_put_op_to_free_queue(pOp); + iRet = -1; + break; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + if (bRet == MTK_WCN_BOOL_FALSE) { + WMT_WARN_FUNC("OPID(%d) type(%d) buf tail(0x%08x) fail\n", + pOp->op.opId, pOp->op.au4OpData[0], gLpbkBufLog); + iRet = -1; + break; + } + WMT_INFO_FUNC("OPID(%d) length(%d) ok\n", pOp->op.opId, pOp->op.au4OpData[0]); + iRet = pOp->op.au4OpData[0]; + if ((iRet > sizeof(gLpbkBuf)) || (iRet < 0)) { + iRet = -EFAULT; + WMT_ERR_FUNC("length is too long\n"); + break; + } + if (copy_to_user((PVOID)arg + sizeof(effectiveLen) + sizeof(UINT8[2048]), gLpbkBuf, iRet)) { + iRet = -EFAULT; + break; + } + + } while (0); + break; + case WMT_IOCTL_ADIE_LPBK_TEST: + do { + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal = NULL; + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + iRet = -EFAULT; + break; + } + + pSignal = &pOp->signal; + pOp->op.opId = WMT_OPID_ADIE_LPBK_TEST; + pOp->op.au4OpData[0] = 0; + pOp->op.au4OpData[1] = (SIZE_T)&gLpbkBuf[0]; + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + WMT_INFO_FUNC("OPID(%d) start\n", pOp->op.opId); + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed,OPID(%d)abort\n", pOp->op.opId); + wmt_lib_put_op_to_free_queue(pOp); + return -1; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + if (bRet == MTK_WCN_BOOL_FALSE) { + WMT_WARN_FUNC("OPID(%d) fail\n", pOp->op.opId); + iRet = -1; + break; + } + WMT_INFO_FUNC("OPID(%d) length(%d) ok\n", pOp->op.opId, pOp->op.au4OpData[0]); + iRet = pOp->op.au4OpData[0]; + if ((iRet > sizeof(gLpbkBuf)) || (iRet < 0)) { + iRet = -EFAULT; + WMT_ERR_FUNC("length is too long\n"); + break; + } + if (copy_to_user((PVOID)arg + sizeof(SIZE_T), gLpbkBuf, iRet)) { + iRet = -EFAULT; + break; + } + } while (0); + break; + case 10: + if (mtk_wcn_stp_coredump_start_get()) { + wmt_lib_host_awake_get(); + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) + WMT_INFO_FUNC("stp dump start.\n"); + else { + WMT_INFO_FUNC("Trigger kernel api dump.\n"); + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_COMBO || + mtk_wcn_stp_coredump_flag_get() == 2) { + pBuffer = kmalloc(NAME_MAX + 1, GFP_KERNEL); + if (!pBuffer) { + WMT_ERR_FUNC("pBuffer kmalloc memory fail\n"); + return 0; + } + + osal_strcpy(pBuffer, "MT662x f/w coredump start-"); + if (copy_from_user(pBuffer + osal_strlen(pBuffer), (PVOID)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, "%s", pBuffer); + kfree(pBuffer); + } + } + } + break; + case 11: + if (mtk_wcn_stp_coredump_start_get()) { + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) { + WMT_INFO_FUNC("Dump connsys EMI done.\n"); + mtk_stp_notify_emi_dump_end(); + } + wmt_lib_host_awake_put(); + } + break; + case WMT_IOCTL_GET_CHIP_INFO: + if (arg == 0) + return wmt_lib_get_icinfo(WMTCHIN_CHIPID); + else if (arg == 1) + return wmt_lib_get_icinfo(WMTCHIN_HWVER); + else if (arg == 2) + return wmt_lib_get_icinfo(WMTCHIN_FWVER); + else if (arg == 3) + return wmt_lib_get_icinfo(WMTCHIN_IPVER); + else if (arg == 4) + return wmt_detect_get_chip_type(); + break; + case WMT_IOCTL_WMT_CFG_NAME: + { + INT8 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_SET_LAUNCHER_KILL: + if (arg == 1) { + 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: + if (arg == 0 || arg > MAX_PATCH_NUM || pAtchNum > 0) { + WMT_ERR_FUNC("patch num(%lu) == 0 or > %d or has set!\n", arg, MAX_PATCH_NUM); + iRet = -1; + break; + } + + pAtchNum = arg; + + if (pPatchInfo == NULL) + pPatchInfo = kcalloc(pAtchNum, sizeof(WMT_PATCH_INFO), GFP_ATOMIC); + if (!pPatchInfo) { + WMT_ERR_FUNC("allocate memory fail!\n"); + iRet = -EFAULT; + break; + } + + WMT_DBG_FUNC(" get patch num from launcher = %d\n", pAtchNum); + wmt_lib_set_patch_num(pAtchNum); + break; + case WMT_IOCTL_SET_PATCH_INFO: + do { + WMT_PATCH_INFO wMtPatchInfo; + P_WMT_PATCH_INFO pTemp = NULL; + UINT32 dWloadSeq; + static UINT32 counter; + + if (!pPatchInfo) { + WMT_ERR_FUNC("NULL patch info pointer\n"); + break; + } + + if (copy_from_user(&wMtPatchInfo, (PVOID)arg, sizeof(WMT_PATCH_INFO))) { + WMT_ERR_FUNC("copy_from_user failed at %d\n", __LINE__); + iRet = -EFAULT; + break; + } + if (wMtPatchInfo.dowloadSeq > pAtchNum || wMtPatchInfo.dowloadSeq == 0) { + WMT_ERR_FUNC("dowloadSeq num(%u) > %u or == 0!\n", wMtPatchInfo.dowloadSeq, pAtchNum); + iRet = -EFAULT; + counter = 0; + break; + } + + dWloadSeq = wMtPatchInfo.dowloadSeq; + WMT_DBG_FUNC( + "patch dl seq %d,name %s,address info 0x%02x,0x%02x,0x%02x,0x%02x\n", + dWloadSeq, wMtPatchInfo.patchName, + wMtPatchInfo.addRess[0], + wMtPatchInfo.addRess[1], + wMtPatchInfo.addRess[2], + wMtPatchInfo.addRess[3]); + osal_memcpy(pPatchInfo + dWloadSeq - 1, &wMtPatchInfo, sizeof(WMT_PATCH_INFO)); + pTemp = pPatchInfo + dWloadSeq - 1; + if (++counter == pAtchNum) { + wmt_lib_set_patch_info(pPatchInfo); + counter = 0; + } + } while (0); + break; + case WMT_IOCTL_WMT_COREDUMP_CTRL: + mtk_wcn_stp_coredump_flag_ctrl(arg); + break; + case WMT_IOCTL_WMT_STP_ASSERT_CTRL: + if (wmt_lib_btm_cb(BTM_TRIGGER_STP_ASSERT_OP) == MTK_WCN_BOOL_TRUE) { + WMT_INFO_FUNC("trigger stp assert succeed\n"); + iRet = 0; + } else { + WMT_INFO_FUNC("trigger stp assert failed\n"); + iRet = -1; + } + break; + case WMT_IOCTL_WMT_QUERY_CHIPID: + iRet = mtk_wcn_wmt_chipid_query(); + WMT_WARN_FUNC("chipid = 0x%x\n", iRet); + break; + case WMT_IOCTL_WMT_TELL_CHIPID: + { +#if !(DELETE_HIF_SDIO_CHRDEV) + iRet = mtk_wcn_hif_sdio_tell_chipid(arg); +#endif + if (0x6628 == arg || 0x6630 == arg || 0x6632 == arg) + wmt_lib_merge_if_flag_ctrl(1); + else + wmt_lib_merge_if_flag_ctrl(0); + } + break; + case WMT_IOCTL_SEND_BGW_DS_CMD: + do { + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + UINT8 desense_buf[14] = { 0 }; + UINT32 effectiveLen = 14; + P_OSAL_SIGNAL pSignal = NULL; + + if (!mtk_wcn_stp_is_ready()) { + iRet = -EFAULT; + break; + } + + if (copy_from_user(&desense_buf[0], (PVOID)arg, effectiveLen)) { + WMT_ERR_FUNC("copy_from_user failed at %d\n", __LINE__); + iRet = -EFAULT; + break; + } + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + iRet = -EFAULT; + break; + } + pSignal = &pOp->signal; + pOp->op.opId = WMT_OPID_BGW_DS; + pOp->op.au4OpData[0] = effectiveLen; /* packet length */ + pOp->op.au4OpData[1] = (SIZE_T)&desense_buf[0]; /* packet buffer pointer */ + pSignal->timeoutValue = MAX_WMT_OP_TIMEOUT; + WMT_INFO_FUNC("OPID(%d) start\n", pOp->op.opId); + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed,opid(%d) abort\n", pOp->op.opId); + wmt_lib_put_op_to_free_queue(pOp); + return -1; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + if (bRet == MTK_WCN_BOOL_FALSE) { + WMT_WARN_FUNC("OPID(%d) fail\n", pOp->op.opId); + iRet = -1; + break; + } + WMT_INFO_FUNC("OPID(%d) length(%zu) ok\n", pOp->op.opId, pOp->op.au4OpData[0]); + iRet = pOp->op.au4OpData[0]; + + } while (0); + break; + case WMT_IOCTL_FW_DBGLOG_CTRL: + iRet = wmt_plat_set_dbg_mode(arg); + if (iRet == 0) + wmt_dbg_fwinfor_from_emi(0, 1, 0); + break; + case WMT_IOCTL_DYNAMIC_DUMP_CTRL: + do { + UINT32 i = 0, j = 0, k = 0; + PUINT8 pBuf = NULL; + UINT32 int_buf[10] = {0}; + INT8 Buffer[10][11]; + + pBuf = kmalloc(DYNAMIC_DUMP_BUF + 1, GFP_KERNEL); + if (!pBuf) { + WMT_ERR_FUNC("pBuf kmalloc memory fail\n"); + return 0; + } + if (copy_from_user(pBuf, (PVOID)arg, DYNAMIC_DUMP_BUF)) { + iRet = -EFAULT; + kfree(pBuf); + break; + } + pBuf[DYNAMIC_DUMP_BUF] = '\0'; + WMT_INFO_FUNC("get dynamic dump data from property(%s)\n", pBuf); + memset(Buffer, 0, 10*11); + for (i = 0; i < DYNAMIC_DUMP_BUF && j <= 9; i++) { + if (pBuf[i] == '/') { + k = 0; + j++; + } else if (isascii(pBuf[i]) && k <= 10) { + Buffer[j][k] = pBuf[i]; + k++; + } + } + for (i = 0; i < (j > 10 ? 10 : j); i++) { + iRet = kstrtou32(Buffer[i], 0, &int_buf[i]); + if (iRet) { + WMT_ERR_FUNC("string convert fail(%d)\n", iRet); + break; + } + WMT_INFO_FUNC("dynamic dump data buf[%d]:(0x%x)\n", i, int_buf[i]); + } + wmt_plat_set_dynamic_dumpmem(int_buf); + kfree(pBuf); + } while (0); + break; + case WMT_IOCTL_SET_ROM_PATCH_INFO: + do { + struct wmt_rom_patch_info wmtRomPatchInfo; + + if (copy_from_user(&wmtRomPatchInfo, (PVOID)arg, sizeof(struct wmt_rom_patch_info))) { + WMT_ERR_FUNC("copy_from_user failed at %d\n", __LINE__); + iRet = -EFAULT; + break; + } + + if (wmtRomPatchInfo.type >= WMTDRV_TYPE_ANT) { + WMT_ERR_FUNC("rom patch type(%d) >= %d!\n", + wmtRomPatchInfo.type, WMTDRV_TYPE_WMT); + iRet = -EFAULT; + break; + } + + WMT_DBG_FUNC("rom patch type %d,name %s,address info 0x%02x,0x%02x,0x%02x,0x%02x\n", + wmtRomPatchInfo.type, wmtRomPatchInfo.patchName, + wmtRomPatchInfo.addRess[0], + wmtRomPatchInfo.addRess[1], + wmtRomPatchInfo.addRess[2], + wmtRomPatchInfo.addRess[3]); + wmt_lib_set_rom_patch_info(&wmtRomPatchInfo, wmtRomPatchInfo.type); + } while (0); + break; + case WMT_IOCTL_GET_EMI_PHY_SIZE: + do { + WMT_INFO_FUNC("gConEmiSize %llu\n", gConEmiSize); + return (UINT32)gConEmiSize; + } while (0); + break; + case WMT_IOCTL_FW_PATCH_UPDATE_RST: + wmt_lib_fw_patch_update_rst_ctrl(arg); + break; + case WMT_IOCTL_GET_DIRECT_PATH_EMI_SIZE: + do { + P_CONSYS_EMI_ADDR_INFO emiInfo = mtk_wcn_consys_soc_get_emi_phy_add(); + + if (emiInfo == NULL) { + WMT_INFO_FUNC("Get emi info fail. Return 0.\n"); + return 0; + } + WMT_INFO_FUNC("Direct path emi size=%d\n", emiInfo->emi_direct_path_size); + return (UINT32)emiInfo->emi_direct_path_size; + } while (0); + break; + case WMT_IOCTL_GET_VENDOR_PATCH_NUM: + iRet = wmt_lib_get_vendor_patch_num(); + break; + case WMT_IOCTL_SET_VENDOR_PATCH_VERSION: + do { + struct wmt_vendor_patch patch; + + if (copy_from_user(&patch, (PVOID)arg, + sizeof(struct wmt_vendor_patch))) { + WMT_ERR_FUNC("copy_from_user failed at %d\n", __LINE__); + iRet = -EFAULT; + break; + } + + iRet = wmt_lib_set_vendor_patch_version(&patch); + if (iRet) { + iRet = -EFAULT; + break; + } + } while (0); + break; + case WMT_IOCTL_GET_VENDOR_PATCH_VERSION: + do { + struct wmt_vendor_patch patch; + + if (copy_from_user(&patch, (PVOID)arg, sizeof(struct wmt_vendor_patch))) { + WMT_ERR_FUNC("copy_from_user failed at %d\n", __LINE__); + iRet = -EFAULT; + break; + } + + iRet = wmt_lib_get_vendor_patch_version(&patch); + if (iRet) { + iRet = -EFAULT; + break; + } + + if (copy_to_user((PVOID)arg, &patch, sizeof(struct wmt_vendor_patch))) + iRet = -EFAULT; + } while (0); + break; + case WMT_IOCTL_SET_ACTIVE_PATCH_VERSION: + do { + struct wmt_vendor_patch patch; + + if (copy_from_user(&patch, (PVOID)arg, + sizeof(struct wmt_vendor_patch))) { + WMT_ERR_FUNC("copy_from_user failed at %d\n", __LINE__); + iRet = -EFAULT; + break; + } + + iRet = wmt_lib_set_active_patch_version(&patch); + WMT_ERR_FUNC("wmt_lib_set_active_patch_version ret = %d\n", iRet); + if (iRet) { + iRet = -EFAULT; + break; + } + } while (0); + break; + case WMT_IOCTL_GET_ACTIVE_PATCH_VERSION: + do { + struct wmt_vendor_patch patch; + + if (copy_from_user(&patch, (PVOID)arg, sizeof(struct wmt_vendor_patch))) { + WMT_ERR_FUNC("copy_from_user failed at %d\n", __LINE__); + iRet = -EFAULT; + break; + } + + iRet = wmt_lib_get_active_patch_version(&patch); + if (iRet) { + iRet = -EFAULT; + break; + } + + if (copy_to_user((PVOID)arg, &patch, sizeof(struct wmt_vendor_patch))) + iRet = -EFAULT; + } while (0); + break; + case WMT_IOCTL_SET_CHECK_PATCH_STATUS: + iRet = wmt_lib_set_check_patch_status(arg); + break; + case WMT_IOCTL_GET_CHECK_PATCH_STATUS: + iRet = wmt_lib_get_check_patch_status(); + break; + default: + iRet = -EINVAL; + WMT_WARN_FUNC("unknown cmd (0x%x)\n", cmd); + break; + } + + return iRet; +} + +#ifdef CONFIG_COMPAT +LONG WMT_compat_ioctl(struct file *filp, UINT32 cmd, ULONG arg) +{ + LONG ret; + + WMT_INFO_FUNC("cmd[0x%x]\n", cmd); + switch (cmd) { + case COMPAT_WMT_IOCTL_SET_PATCH_NAME: + ret = WMT_unlocked_ioctl(filp, WMT_IOCTL_SET_PATCH_NAME, (ULONG)compat_ptr(arg)); + break; + case COMPAT_WMT_IOCTL_LPBK_TEST: + ret = WMT_unlocked_ioctl(filp, WMT_IOCTL_LPBK_TEST, (ULONG)compat_ptr(arg)); + break; + case COMPAT_WMT_IOCTL_SET_PATCH_INFO: + ret = WMT_unlocked_ioctl(filp, WMT_IOCTL_SET_PATCH_INFO, (ULONG)compat_ptr(arg)); + break; + case COMPAT_WMT_IOCTL_PORT_NAME: + ret = WMT_unlocked_ioctl(filp, WMT_IOCTL_PORT_NAME, (ULONG)compat_ptr(arg)); + break; + case COMPAT_WMT_IOCTL_WMT_CFG_NAME: + ret = WMT_unlocked_ioctl(filp, WMT_IOCTL_WMT_CFG_NAME, (ULONG)compat_ptr(arg)); + break; + case COMPAT_WMT_IOCTL_SEND_BGW_DS_CMD: + ret = WMT_unlocked_ioctl(filp, WMT_IOCTL_SEND_BGW_DS_CMD, (ULONG)compat_ptr(arg)); + break; + case COMPAT_WMT_IOCTL_ADIE_LPBK_TEST: + ret = WMT_unlocked_ioctl(filp, WMT_IOCTL_ADIE_LPBK_TEST, (ULONG)compat_ptr(arg)); + break; + case COMPAT_WMT_IOCTL_DYNAMIC_DUMP_CTRL: + ret = WMT_unlocked_ioctl(filp, WMT_IOCTL_DYNAMIC_DUMP_CTRL, (ULONG)compat_ptr(arg)); + break; + case COMPAT_WMT_IOCTL_SET_ROM_PATCH_INFO: + ret = WMT_unlocked_ioctl(filp, WMT_IOCTL_SET_ROM_PATCH_INFO, (ULONG)compat_ptr(arg)); + break; + default: { + ret = WMT_unlocked_ioctl(filp, cmd, arg); + break; + } + } + return ret; +} +#endif /* CONFIG_COMPAT */ + +static INT32 WMT_open(struct inode *inode, struct file *file) +{ + LONG ret; + + WMT_INFO_FUNC("major %d minor %d (pid %d)\n", imajor(inode), iminor(inode), current->pid); + ret = wait_event_timeout(gWmtInitWq, gWmtInitStatus == WMT_INIT_DONE, msecs_to_jiffies(WMT_DEV_INIT_TO_MS)); + if (!ret) { + WMT_WARN_FUNC("wait_event_timeout (%d)ms,(%lu)jiffies,return -EIO\n", + WMT_DEV_INIT_TO_MS, msecs_to_jiffies(WMT_DEV_INIT_TO_MS)); + return -EIO; + } + + if (atomic_inc_return(&gWmtRefCnt) == 1) { + WMT_INFO_FUNC("1st call\n"); + gWmtClose = 0; + } + + return 0; +} + +static INT32 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"); + gWmtClose = 1; + } + + return 0; +} + +static INT32 WMT_mmap(struct file *pFile, struct vm_area_struct *pVma) +{ + unsigned long bufId = pVma->vm_pgoff; + P_CONSYS_EMI_ADDR_INFO emiInfo = mtk_wcn_consys_soc_get_emi_phy_add(); + + pVma->vm_flags &= ~(VM_WRITE | VM_MAYWRITE); + WMT_INFO_FUNC("WMT_mmap start:%lu end:%lu size: %lu buffer id=%lu\n", + pVma->vm_start, pVma->vm_end, + pVma->vm_end - pVma->vm_start, bufId); + + if (bufId == 0) { + if (pVma->vm_end - pVma->vm_start > gConEmiSize) + return -EINVAL; + WMT_INFO_FUNC("WMT_mmap size: %lu\n", pVma->vm_end - pVma->vm_start); + if (remap_pfn_range(pVma, pVma->vm_start, gConEmiPhyBase >> PAGE_SHIFT, + pVma->vm_end - pVma->vm_start, pVma->vm_page_prot)) + return -EAGAIN; + return 0; + } else if (bufId == 1) { + if (emiInfo == NULL) + return -EINVAL; + if (emiInfo->emi_direct_path_size == 0 || + pVma->vm_end - pVma->vm_start > emiInfo->emi_direct_path_size) + return -EINVAL; + WMT_INFO_FUNC("MD direct path size=%d map size=%lu\n", + emiInfo->emi_direct_path_size, + pVma->vm_end - pVma->vm_start); + if (remap_pfn_range(pVma, pVma->vm_start, + emiInfo->emi_direct_path_ap_phy_addr >> PAGE_SHIFT, + pVma->vm_end - pVma->vm_start, pVma->vm_page_prot)) + return -EAGAIN; + return 0; + } + /* Invalid buff id */ + return -EINVAL; +} + +const struct file_operations gWmtFops = { + .open = WMT_open, + .release = WMT_close, + .read = WMT_read, + .write = WMT_write, +/* .ioctl = WMT_ioctl, */ + .unlocked_ioctl = WMT_unlocked_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = WMT_compat_ioctl, +#endif + .poll = WMT_poll, + .mmap = WMT_mmap, +}; + +VOID wmt_dev_bgw_desense_init(VOID) +{ + bgw_init_socket(); +} + +VOID wmt_dev_bgw_desense_deinit(VOID) +{ + bgw_destroy_netlink_kernel(); +} + +VOID wmt_dev_send_cmd_to_daemon(UINT32 cmd) +{ + send_command_to_daemon(cmd); +} + +UINT8 wmt_dev_is_close(VOID) +{ + return gWmtClose; +} + +static INT32 WMT_init(VOID) +{ + dev_t devID = MKDEV(gWmtMajor, 0); + INT32 cdevErr = -1; + INT32 ret = -1; + ENUM_WMT_CHIP_TYPE chip_type; + + WMT_DBG_FUNC("WMT Version= %s DATE=%s\n", MTK_WMT_VERSION, MTK_WMT_DATE); + if (gWmtInitStatus != WMT_INIT_NOT_START) + return 0; + /* Prepare a UINT8 device */ + /*static allocate chrdev */ + gWmtInitStatus = WMT_INIT_START; + init_waitqueue_head((wait_queue_head_t *) &gWmtInitWq); +#if (MTK_WCN_REMOVE_KO) + /* called in do_common_drv_init() */ +#else + mtk_wcn_hif_sdio_drv_init(); +#endif + stp_drv_init(); + + ret = register_chrdev_region(devID, WMT_DEV_NUM, WMT_DRIVER_NAME); + if (ret) { + WMT_ERR_FUNC("fail to register chrdev\n"); + gWmtInitStatus = WMT_INIT_NOT_START; + return ret; + } + + cdev_init(&gWmtCdev, &gWmtFops); + gWmtCdev.owner = THIS_MODULE; + + cdevErr = cdev_add(&gWmtCdev, devID, WMT_DEV_NUM); + if (cdevErr) { + WMT_ERR_FUNC("cdev_add() fails (%d)\n", cdevErr); + goto error; + } + WMT_INFO_FUNC("driver(major %d) installed\n", gWmtMajor); + +#if WMT_CREATE_NODE_DYNAMIC + wmt_class = class_create(THIS_MODULE, "stpwmt"); + if (IS_ERR(wmt_class)) + goto error; + wmt_dev = device_create(wmt_class, NULL, devID, NULL, "stpwmt"); + if (IS_ERR(wmt_dev)) + goto error; +#endif + +#if 0 + pWmtDevCtx = wmt_drv_create(); + if (!pWmtDevCtx) { + WMT_ERR_FUNC("wmt_drv_create() fails\n"); + goto error; + } + + ret = wmt_drv_init(pWmtDevCtx); + if (ret) { + WMT_ERR_FUNC("wmt_drv_init() fails (%d)\n", ret); + goto error; + } + + WMT_INFO_FUNC("stp_btmcb_reg\n"); + wmt_cdev_btmcb_reg(); + + ret = wmt_drv_start(pWmtDevCtx); + if (ret) { + WMT_ERR_FUNC("wmt_drv_start() fails (%d)\n", ret); + goto error; + } +#endif + ret = wmt_lib_init(); + if (ret) { + WMT_ERR_FUNC("wmt_lib_init() fails (%d)\n", ret); + goto error; + } +#if CFG_WMT_DBG_SUPPORT + wmt_dev_dbg_setup(); +#endif + wmt_dev_user_proc_setup(); + + wmt_dev_proc_init(); + wmt_alarm_init(); + + WMT_STEP_INIT_FUNC(); + + chip_type = wmt_detect_get_chip_type(); + if (chip_type == WMT_CHIP_TYPE_COMBO) + mtk_wcn_hif_sdio_update_cb_reg(wmt_dev_tra_sdio_update); + + WMT_DBG_FUNC("wmt_dev register thermal cb\n"); + osal_unsleepable_lock_init(&g_temp_query_spinlock); + wmt_lib_register_thermal_ctrl_cb(wmt_dev_tm_temp_query); + wmt_lib_register_trigger_assert_cb(wmt_lib_trigger_assert); + + if (chip_type == WMT_CHIP_TYPE_SOC) + wmt_dev_bgw_desense_init(); + + gWmtInitStatus = WMT_INIT_DONE; + wake_up(&gWmtInitWq); + + INIT_WORK(&gPwrOnOffWork, wmt_pwr_on_off_handler); +#ifdef CONFIG_EARLYSUSPEND + register_early_suspend(&wmt_early_suspend_handler); + WMT_INFO_FUNC("register_early_suspend finished\n"); +#else + wmt_fb_notifier.notifier_call = wmt_fb_notifier_callback; + ret = fb_register_client(&wmt_fb_notifier); + if (ret) + WMT_ERR_FUNC("wmt register fb_notifier failed! ret(%d)\n", ret); + else + WMT_DBG_FUNC("wmt register fb_notifier OK!\n"); +#endif /* CONFIG_EARLYSUSPEND */ + WMT_DBG_FUNC("success\n"); + +#if (MTK_WCN_REMOVE_KO) + /* called in do_common_drv_init() */ +#else + mtk_wcn_stp_uart_drv_init(); + mtk_wcn_stp_sdio_drv_init(); +#endif + + return 0; + +error: + wmt_lib_deinit(); +#if CFG_WMT_DBG_SUPPORT + wmt_dev_dbg_remove(); +#endif + wmt_dev_user_proc_remove(); +#if WMT_CREATE_NODE_DYNAMIC + if (!(IS_ERR(wmt_dev))) + device_destroy(wmt_class, devID); + if (!(IS_ERR(wmt_class))) { + class_destroy(wmt_class); + wmt_class = NULL; + } +#endif + + if (cdevErr == 0) + cdev_del(&gWmtCdev); + + if (ret == 0) { + unregister_chrdev_region(devID, WMT_DEV_NUM); + gWmtMajor = -1; + } + + gWmtInitStatus = WMT_INIT_NOT_START; + WMT_ERR_FUNC("fail\n"); + + return -1; +} + +static VOID WMT_exit(VOID) +{ + dev_t dev = MKDEV(gWmtMajor, 0); + + if (gWmtInitStatus != WMT_INIT_DONE) + return; + + osal_unsleepable_lock_deinit(&g_temp_query_spinlock); +#ifdef CONFIG_EARLYSUSPEND + unregister_early_suspend(&wmt_early_suspend_handler); + WMT_INFO_FUNC("unregister_early_suspend finished\n"); +#else + fb_unregister_client(&wmt_fb_notifier); +#endif /* CONFIG_EARLYSUSPEND */ + + wmt_dev_patch_info_free(); + mtk_wcn_stp_uart_drv_exit(); + mtk_wcn_stp_sdio_drv_exit(); + + wmt_dev_bgw_desense_deinit(); + + wmt_lib_register_thermal_ctrl_cb(NULL); + + wmt_lib_deinit(); + +#if CFG_WMT_DBG_SUPPORT + wmt_dev_dbg_remove(); +#endif + wmt_dev_user_proc_remove(); + + wmt_dev_proc_deinit(); + wmt_alarm_deinit(); + +#if WMT_CREATE_NODE_DYNAMIC + if (wmt_dev) { + device_destroy(wmt_class, dev); + wmt_dev = NULL; + } + if (wmt_class) { + class_destroy(wmt_class); + wmt_class = NULL; + } +#endif + cdev_del(&gWmtCdev); + unregister_chrdev_region(dev, WMT_DEV_NUM); + gWmtMajor = -1; + + stp_drv_exit(); + mtk_wcn_hif_sdio_driver_exit(); + gWmtInitStatus = WMT_INIT_NOT_START; + WMT_INFO_FUNC("done\n"); +} + +INT32 mtk_wcn_common_drv_init(VOID) +{ + return WMT_init(); +} +EXPORT_SYMBOL(mtk_wcn_common_drv_init); + +VOID mtk_wcn_common_drv_exit(VOID) +{ + WMT_exit(); +} +EXPORT_SYMBOL(mtk_wcn_common_drv_exit); + diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_idc.c b/drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_idc.c new file mode 100644 index 0000000000000..864b2ac18eb65 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_idc.c @@ -0,0 +1,318 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include "osal.h" +#include "wmt_idc.h" +#include "wmt_lib.h" + +#if CFG_WMT_LTE_COEX_HANDLING + +MTK_WCN_WMT_IDC_INFO gWmtIdcInfo; + +INT32 wmt_idc_init(VOID) +{ + INT32 iRet; + + osal_memset(&gWmtIdcInfo, 0, osal_sizeof(gWmtIdcInfo)); + gWmtIdcInfo.iit.src_mod_id = AP_MOD_WMT; + gWmtIdcInfo.iit.dest_mod_id = MD_MOD_EL1; + gWmtIdcInfo.iit.sap_id = 0; + gWmtIdcInfo.ops.rx_cb = wmt_idc_msg_from_lte_handing; + + iRet = mtk_conn_md_bridge_reg(gWmtIdcInfo.iit.src_mod_id, &gWmtIdcInfo.ops); + if (iRet) { + WMT_ERR_FUNC("mtk_conn_md_bridge_reg fail(%d)\n", iRet); + return -1; + } + /* mtk_wcn_stp_flush_rx_queue(COEX_TASK_INDX); */ + return 0; +} + +INT32 wmt_idc_deinit(VOID) +{ + INT32 iRet; + + iRet = mtk_conn_md_bridge_unreg(gWmtIdcInfo.iit.src_mod_id); + if (iRet) + WMT_ERR_FUNC("mtk_conn_md_bridge_unreg fail(%d)\n", iRet); + + osal_memset(&gWmtIdcInfo, 0, osal_sizeof(gWmtIdcInfo)); + + return 0; +} + +INT32 wmt_idc_msg_from_lte_handing(conn_md_ipc_ilm_t *ilm) +{ + MTK_WCN_BOOL bRet; + + if (ilm == NULL) { + WMT_ERR_FUNC("NULL pointer\n"); + return -1; + } + if (mtk_wcn_stp_is_ready()) { + bRet = wmt_lib_handle_idc_msg(ilm); + if (bRet == MTK_WCN_BOOL_FALSE) { + WMT_ERR_FUNC("wmt handing idc msg fail\n"); + return -2; + } + } else + WMT_INFO_FUNC("Received LTE msg,but STP is not ready,drop it!\n"); + + return 0; +} + +VOID wmt_idc_dump_debug_msg(PUINT8 str, PUINT8 p_buf, UINT32 buf_len) +{ + UINT32 idx = 0; + + WMT_DBG_FUNC("%s:, length:%d\n", str, buf_len); + + WMT_DBG_FUNC("ASCII output:\n"); + + for (idx = 0; idx < buf_len;) { + WMT_DBG_FUNC("%c", p_buf[idx]); + idx++; + if (idx % 16 == 0) + WMT_DBG_FUNC("\n"); + } + + WMT_DBG_FUNC("HEX output:\n"); + + for (idx = 0; idx < buf_len;) { + WMT_DBG_FUNC("%02x ", p_buf[idx]); + idx++; + if (idx % 16 == 0) + WMT_DBG_FUNC("\n"); + } +} + +INT32 wmt_idc_msg_to_lte_handing(VOID) +{ + UINT32 readlen = 0; + struct local_para *p_lps = NULL; + PUINT8 p_data = NULL; + UINT8 opcode = 0; + UINT16 msg_len = 0; +#if CFG_WMT_LTE_ENABLE_MSGID_MAPPING + MTK_WCN_BOOL unknown_msgid = MTK_WCN_BOOL_FALSE; +#endif + + readlen = mtk_wcn_stp_receive_data(&gWmtIdcInfo.buffer[0], 4, COEX_TASK_INDX); + if (readlen == 0) { + osal_sleep_ms(5); + readlen = mtk_wcn_stp_receive_data(&gWmtIdcInfo.buffer[0], 4, COEX_TASK_INDX); + } + + if (readlen > 0) { + WMT_DBG_FUNC("read data len from fw(%d)\n", readlen); + wmt_idc_dump_debug_msg("WMT->LTE from STP buffer", &gWmtIdcInfo.buffer[0], readlen); + + while (readlen) { + p_data = &gWmtIdcInfo.buffer[0]; + p_data += 2; /*omit direction & opcode 2 bytes */ + osal_memcpy(&msg_len, p_data, 2); + WMT_DBG_FUNC("current raw data len(%d) from connsys firmware\n", msg_len); + + msg_len = msg_len > LTE_IDC_BUFFER_MAX_SIZE ? LTE_IDC_BUFFER_MAX_SIZE : msg_len; + osal_memset(&gWmtIdcInfo.buffer[0], 0, LTE_IDC_BUFFER_MAX_SIZE); + readlen = mtk_wcn_stp_receive_data(&gWmtIdcInfo.buffer[0], msg_len, COEX_TASK_INDX); + p_data = &gWmtIdcInfo.buffer[0]; + + if (msg_len > 0) + msg_len -= 1; /*flag byte */ + else + WMT_ERR_FUNC("msg_len is ERROR!"); + + /*how to handle flag(msg type) need to Scott comment */ + /************************************************/ + + if (*p_data == WMT_IDC_RX_OPCODE_DEBUG_MONITOR) + /*do not need transfer to LTE */ + { + p_data += 1; /*flag : 1 byte */ + /*need to handle these debug message */ + wmt_idc_dump_debug_msg("WIFI DEBUG MONITOR", p_data, msg_len); + } else + /*need to transfer to LTE */ + { + p_lps = + (struct local_para *) osal_malloc(osal_sizeof(struct local_para) + + osal_sizeof(UINT8) * msg_len); + if (p_lps == NULL) { + WMT_ERR_FUNC("allocate struct local_para memory fail\n"); + return -1; + } + + p_lps->msg_len = msg_len + osal_sizeof(struct local_para); + + opcode = *p_data; + WMT_DBG_FUNC("current opcode(%d) to LTE\n", opcode); + + p_data += 1; /*flag : 1 byte */ + osal_memcpy(p_lps->data, p_data, msg_len); + + gWmtIdcInfo.iit.local_para_ptr = p_lps; + +#if CFG_WMT_LTE_ENABLE_MSGID_MAPPING + switch (opcode) { + case WMT_IDC_RX_OPCODE_BTWF_DEF_PARA: + gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_WIFIBT_OPER_DEFAULT_PARAM_IND; + break; + case WMT_IDC_RX_OPCODE_BTWF_CHAN_RAN: + gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_WIFIBT_OPER_FREQ_IND; + break; + case WMT_IDC_RX_OPCODE_LTE_FREQ_IDX_TABLE: + gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_WIFIBT_FREQ_IDX_TABLE_IND; + break; + case WMT_IDC_RX_OPCODE_BTWF_PROFILE_IND: + gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_WIFIBT_PROFILE_IND; + break; + case WMT_IDC_RX_OPCODE_UART_PIN_SEL: + gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_PIN_TYPE_IND; + break; + /* case WMT_IDC_RX_OPCODE_TDM_REQ: */ + /* gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_WIFIBT_OPER_FREQ_IND; */ + /* break; */ + default: + unknown_msgid = MTK_WCN_BOOL_TRUE; + WMT_ERR_FUNC("unknown opcode(%d) from connsys firmware\n", opcode); + break; + } + if (unknown_msgid == MTK_WCN_BOOL_FALSE) { + /*handling flag value in wmt cmd */ + mtk_conn_md_bridge_send_msg(&gWmtIdcInfo.iit); + } +#else + if (opcode >= LTE_MSG_ID_OFFSET) { + gWmtIdcInfo.iit.msg_id = + opcode + IPC_EL1_MSG_ID_BEGIN - LTE_MSG_ID_OFFSET + 1; + /*handling flag value in wmt cmd */ + if (gWmtIdcInfo.iit.msg_id == IPC_MSG_ID_MD_CONSYS_VERIFICATION_REQ) + gWmtIdcInfo.iit.dest_mod_id = MD_MOD_GMMGR; + else + gWmtIdcInfo.iit.dest_mod_id = MD_MOD_EL1; + + mtk_conn_md_bridge_send_msg(&gWmtIdcInfo.iit); + WMT_DBG_FUNC("CONN->LTE: (0x%x->0x%x)\n", opcode, + gWmtIdcInfo.iit.msg_id); + } else + WMT_ERR_FUNC("opcode(%d)from connsys fw is out of range,drop it!\n", + opcode); +#endif + osal_free(p_lps); + } + + osal_memset(&gWmtIdcInfo.buffer[0], 0, LTE_IDC_BUFFER_MAX_SIZE); + readlen = mtk_wcn_stp_receive_data(&gWmtIdcInfo.buffer[0], 4, COEX_TASK_INDX); + WMT_DBG_FUNC("read data len from fw(%d)\n", readlen); + } + + } else + WMT_ERR_FUNC("there is no coex data in stp buffer\n"); + + osal_memset(&gWmtIdcInfo.buffer[0], 0, LTE_IDC_BUFFER_MAX_SIZE); + + return 0; +} + +UINT32 wmt_idc_msg_to_lte_handing_for_test(PUINT8 p_buf, UINT32 len) +{ + UINT32 readlen = len; + struct local_para *p_lps = NULL; + PUINT8 p_data = NULL; + UINT8 opcode = 0; + UINT16 msg_len = 0; + MTK_WCN_BOOL unknown_msgid = MTK_WCN_BOOL_FALSE; + + osal_memcpy(&gWmtIdcInfo.buffer[0], p_buf, len); + + if (readlen > 0) { + WMT_DBG_FUNC("read data len from fw(%d)\n", readlen); + + while (readlen) { + p_data = &gWmtIdcInfo.buffer[0]; + p_data += 2; /*omit direction & opcode 2 bytes */ + osal_memcpy(&msg_len, p_data, 2); + + msg_len = msg_len > LTE_IDC_BUFFER_MAX_SIZE ? LTE_IDC_BUFFER_MAX_SIZE : msg_len; + osal_memset(&gWmtIdcInfo.buffer[0], 0, LTE_IDC_BUFFER_MAX_SIZE); + readlen = mtk_wcn_stp_receive_data(&gWmtIdcInfo.buffer[0], msg_len, COEX_TASK_INDX); + p_data = &gWmtIdcInfo.buffer[0]; + + if (msg_len > 0) + msg_len -= 1; /*flag byte */ + else + WMT_ERR_FUNC("msg_len is ERROR!"); + WMT_DBG_FUNC("current raw data len(%d) from connsys firmware\n", msg_len); + + /*how to handle flag(msg type) need to Scott comment */ + /************************************************/ + + if (*p_data == WMT_IDC_RX_OPCODE_DEBUG_MONITOR) + /*do not need transfer to LTE */ + { + p_data += 1; /*flag : 1 byte */ + /*need to handle these debug message */ + wmt_idc_dump_debug_msg("WIFI DEBUG MONITOR", p_data, msg_len); + } else { + /*need to transfer to LTE */ + p_lps = (struct local_para *) osal_malloc(osal_sizeof(struct local_para) + + osal_sizeof(UINT8) * msg_len); + if (p_lps == NULL) { + WMT_ERR_FUNC("allocate struct local_para memory fail\n"); + return -1; + } + + p_lps->msg_len = msg_len + osal_sizeof(struct local_para); + + opcode = *p_data; + WMT_DBG_FUNC("current opcode(%d) to LTE\n", opcode); + + p_data += 1; /*flag : 1 byte */ + osal_memcpy(p_lps->data, p_data, msg_len); + + gWmtIdcInfo.iit.local_para_ptr = p_lps; + + switch (opcode) { + case WMT_IDC_RX_OPCODE_BTWF_DEF_PARA: + gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_WIFIBT_OPER_DEFAULT_PARAM_IND; + break; + case WMT_IDC_RX_OPCODE_BTWF_CHAN_RAN: + gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_WIFIBT_OPER_FREQ_IND; + break; + /* case WMT_IDC_RX_OPCODE_TDM_REQ: */ + /* gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_WIFIBT_OPER_FREQ_IND; */ + /* break; */ + default: + unknown_msgid = MTK_WCN_BOOL_TRUE; + WMT_ERR_FUNC("unknown opcode(%d) from connsys firmware\n", opcode); + } + if (unknown_msgid == MTK_WCN_BOOL_FALSE) { + /*handling flag value in wmt cmd */ + mtk_conn_md_bridge_send_msg(&gWmtIdcInfo.iit); + } + osal_free(p_lps); + } + + osal_memset(&gWmtIdcInfo.buffer[0], 0, LTE_IDC_BUFFER_MAX_SIZE); + readlen = mtk_wcn_stp_receive_data(&gWmtIdcInfo.buffer[0], 4, COEX_TASK_INDX); + } + + } else + WMT_ERR_FUNC("there is no coex data in stp buffer\n"); + + osal_memset(&gWmtIdcInfo.buffer[0], 0, LTE_IDC_BUFFER_MAX_SIZE); + + return 0; +} +#endif /* CFG_WMT_LTE_COEX_HANDLING */ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_proc_dbg.c b/drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_proc_dbg.c new file mode 100644 index 0000000000000..bb26f2dd0ec13 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_proc_dbg.c @@ -0,0 +1,299 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#include +#include "osal.h" +#include "wmt_core.h" +#include "wmt_lib.h" +#include "wmt_proc_dbg.h" + +#if CFG_WMT_PROC_FOR_AEE +static struct proc_dir_entry *gWmtAeeEntry; +#define WMT_AEE_PROCNAME "driver/wmt_aee" +#define WMT_PROC_AEE_SIZE 3072 +static UINT32 g_buf_len; +static PUINT8 pBuf; + +static OSAL_SLEEPABLE_LOCK g_aee_read_lock; +#endif + + +#if CFG_WMT_PROC_FOR_DUMP_INFO + +static struct proc_dir_entry *gWmtdumpinfoEntry; +#define WMT_DUMP_INFO_PROCNAME "driver/wmt_dump_info" +static CONSYS_STATE_DMP_INFO g_dmp_info; +static UINT32 g_dump_info_buf_len; +static UINT8 dmp_info_buf[DBG_LOG_STR_SIZE]; +static PUINT8 dmp_info_buf_ptr; + +static OSAL_SLEEPABLE_LOCK g_dump_info_read_lock; + +static ssize_t wmt_dev_proc_for_dump_info_read(struct file *filp, char __user *buf, size_t count, + loff_t *f_pos) +{ + INT32 retval = 0; + UINT32 len = 0; + INT32 i, dmp_cnt = 5; + + WMT_INFO_FUNC("%s: count %lu pos %lld\n", __func__, count, *f_pos); + + if (osal_lock_sleepable_lock(&g_dump_info_read_lock)) { + WMT_ERR_FUNC("lock failed\n"); + return 0; + } + + if (*f_pos == 0) { + g_dump_info_buf_len = 0; + if (wmt_lib_dmp_consys_state(&g_dmp_info, dmp_cnt, 0) == MTK_WCN_BOOL_TRUE) { + g_dump_info_buf_len = len; + memset(dmp_info_buf, '\0', DBG_LOG_STR_SIZE); + g_dump_info_buf_len = 0; + g_dump_info_buf_len += snprintf(dmp_info_buf + g_dump_info_buf_len, + DBG_LOG_STR_SIZE - g_dump_info_buf_len, + "0x%08x", g_dmp_info.cpu_pcr[0]); + + for (i = 1; i < dmp_cnt; i++) + g_dump_info_buf_len += snprintf(dmp_info_buf + g_dump_info_buf_len, + DBG_LOG_STR_SIZE - g_dump_info_buf_len, + ";0x%08x", g_dmp_info.cpu_pcr[i]); + + g_dump_info_buf_len += snprintf(dmp_info_buf + g_dump_info_buf_len, + DBG_LOG_STR_SIZE - g_dump_info_buf_len, ";0x%08x", g_dmp_info.state.lp[1]); + + g_dump_info_buf_len += snprintf(dmp_info_buf + g_dump_info_buf_len, + DBG_LOG_STR_SIZE - g_dump_info_buf_len, ";0x%08x", g_dmp_info.state.gating[1]); + + g_dump_info_buf_len += snprintf(dmp_info_buf + g_dump_info_buf_len, + DBG_LOG_STR_SIZE - len, + ";[0x%08x", g_dmp_info.state.sw_state.info_time); + + g_dump_info_buf_len += snprintf(dmp_info_buf + g_dump_info_buf_len, + DBG_LOG_STR_SIZE - len, + ";0x%08x", g_dmp_info.state.sw_state.is_gating); + g_dump_info_buf_len += snprintf(dmp_info_buf + g_dump_info_buf_len, + DBG_LOG_STR_SIZE - len, + ";0x%08x", g_dmp_info.state.sw_state.resource_disable_sleep); + g_dump_info_buf_len += snprintf(dmp_info_buf + g_dump_info_buf_len, + DBG_LOG_STR_SIZE - len, + ";0x%08x", g_dmp_info.state.sw_state.clock_hif_ctrl); + g_dump_info_buf_len += snprintf(dmp_info_buf + g_dump_info_buf_len, + DBG_LOG_STR_SIZE - len, + ";0x%08x", g_dmp_info.state.sw_state.clock_umac_ctrl); + g_dump_info_buf_len += snprintf(dmp_info_buf + g_dump_info_buf_len, + DBG_LOG_STR_SIZE - len, + ";0x%08x", g_dmp_info.state.sw_state.clock_mcu); + g_dump_info_buf_len += snprintf(dmp_info_buf + g_dump_info_buf_len, + DBG_LOG_STR_SIZE - len, + ";0x%08x]", g_dmp_info.state.sw_state.sub_system); + + + dmp_info_buf_ptr = dmp_info_buf; + } + + WMT_INFO_FUNC("wmt_dev:wmt for dump info buffer len(%d)\n", g_dump_info_buf_len); + } + + if (g_dump_info_buf_len >= count) { + retval = copy_to_user(buf, dmp_info_buf_ptr, count); + if (retval) { + WMT_ERR_FUNC("copy to dump info buffer failed, ret:%d\n", retval); + retval = -EFAULT; + goto dump_info_err_exit; + } + + *f_pos += count; + g_dump_info_buf_len -= count; + dmp_info_buf_ptr += count; + WMT_INFO_FUNC("wmt_dev:after read,wmt for dump info buffer len(%d)\n", g_dump_info_buf_len); + + retval = count; + } else if (g_dump_info_buf_len != 0) { + retval = copy_to_user(buf, dmp_info_buf_ptr, g_dump_info_buf_len); + if (retval) { + WMT_ERR_FUNC("copy to dump info buffer failed, ret:%d\n", retval); + retval = -EFAULT; + goto dump_info_err_exit; + } + + *f_pos += g_dump_info_buf_len; + len = g_dump_info_buf_len; + g_dump_info_buf_len = 0; + dmp_info_buf_ptr += len; + retval = len; + WMT_INFO_FUNC("wmt_dev:after read,wmt for dump info buffer len(%d)\n", g_dump_info_buf_len); + } else { + WMT_INFO_FUNC("wmt_dev: no data available for dump info\n"); + retval = 0; + } + +dump_info_err_exit: + osal_unlock_sleepable_lock(&g_dump_info_read_lock); + + return retval; +} + +static ssize_t wmt_dev_proc_for_dump_info_write(struct file *filp, const char __user *buf, size_t count, + loff_t *f_pos) +{ + WMT_TRC_FUNC(); + return 0; +} + +INT32 wmt_dev_proc_for_dump_info_setup(VOID) +{ + static const struct file_operations wmt_dump_info_fops = { + .owner = THIS_MODULE, + .read = wmt_dev_proc_for_dump_info_read, + .write = wmt_dev_proc_for_dump_info_write, + }; + + osal_sleepable_lock_init(&g_dump_info_read_lock); + + gWmtdumpinfoEntry = proc_create(WMT_DUMP_INFO_PROCNAME, 0664, NULL, &wmt_dump_info_fops); + if (gWmtdumpinfoEntry == NULL) { + WMT_ERR_FUNC("Unable to create /proc entry\n\r"); + return -1; + } + + return 0; +} + +INT32 wmt_dev_proc_for_dump_info_remove(VOID) +{ + if (gWmtdumpinfoEntry != NULL) + remove_proc_entry(WMT_DUMP_INFO_PROCNAME, NULL); + osal_sleepable_lock_deinit(&g_dump_info_read_lock); + + return 0; +} +#endif /* CFG_WMT_PROC_FOR_DUMP_INFO */ + +#if CFG_WMT_PROC_FOR_AEE +static ssize_t wmt_dev_proc_for_aee_read(struct file *filp, char __user *buf, size_t count, + loff_t *f_pos) +{ + INT32 retval = 0; + UINT32 len = 0; + + WMT_INFO_FUNC("%s: count %lu pos %lld\n", __func__, count, *f_pos); + + if (osal_lock_sleepable_lock(&g_aee_read_lock)) { + WMT_ERR_FUNC("lock failed\n"); + return 0; + } + + if (*f_pos == 0) { + pBuf = wmt_lib_get_cpupcr_xml_format(&len); + g_buf_len = len; + WMT_INFO_FUNC("wmt_dev:wmt for aee buffer len(%d)\n", g_buf_len); + } + + if (g_buf_len >= count) { + retval = copy_to_user(buf, pBuf, count); + if (retval) { + WMT_ERR_FUNC("copy to aee buffer failed, ret:%d\n", retval); + retval = -EFAULT; + goto err_exit; + } + + *f_pos += count; + g_buf_len -= count; + pBuf += count; + WMT_INFO_FUNC("wmt_dev:after read,wmt for aee buffer len(%d)\n", g_buf_len); + + retval = count; + } else if (g_buf_len != 0) { + retval = copy_to_user(buf, pBuf, g_buf_len); + if (retval) { + WMT_ERR_FUNC("copy to aee buffer failed, ret:%d\n", retval); + retval = -EFAULT; + goto err_exit; + } + + *f_pos += g_buf_len; + len = g_buf_len; + g_buf_len = 0; + pBuf += len; + retval = len; + WMT_INFO_FUNC("wmt_dev:after read,wmt for aee buffer len(%d)\n", g_buf_len); + } else { + WMT_INFO_FUNC("wmt_dev: no data available for aee\n"); + retval = 0; + } + +err_exit: + osal_unlock_sleepable_lock(&g_aee_read_lock); + + return retval; +} + +static ssize_t wmt_dev_proc_for_aee_write(struct file *filp, const char __user *buf, size_t count, + loff_t *f_pos) +{ + WMT_TRC_FUNC(); + return 0; +} + +INT32 wmt_dev_proc_for_aee_setup(VOID) +{ + static const struct file_operations wmt_aee_fops = { + .owner = THIS_MODULE, + .read = wmt_dev_proc_for_aee_read, + .write = wmt_dev_proc_for_aee_write, + }; + + osal_sleepable_lock_init(&g_aee_read_lock); + gWmtAeeEntry = proc_create(WMT_AEE_PROCNAME, 0664, NULL, &wmt_aee_fops); + if (gWmtAeeEntry == NULL) { + WMT_ERR_FUNC("Unable to create /proc entry\n\r"); + return -1; + } + + return 0; +} + +INT32 wmt_dev_proc_for_aee_remove(VOID) +{ + if (gWmtAeeEntry != NULL) + remove_proc_entry(WMT_AEE_PROCNAME, NULL); + osal_sleepable_lock_deinit(&g_aee_read_lock); + + return 0; +} +#endif /* CFG_WMT_PROC_FOR_AEE */ + + + +INT32 wmt_dev_proc_init(VOID) +{ + int ret = 0; +#if CFG_WMT_PROC_FOR_DUMP_INFO + ret = wmt_dev_proc_for_dump_info_setup(); + if (ret) + return ret; +#endif + +#if CFG_WMT_PROC_FOR_AEE + ret = wmt_dev_proc_for_aee_setup(); +#endif + return ret; +} +INT32 wmt_dev_proc_deinit(VOID) +{ + int ret = 0; + +#if CFG_WMT_PROC_FOR_DUMP_INFO + ret = wmt_dev_proc_for_dump_info_remove(); + if (ret) + return ret; +#endif +#if CFG_WMT_PROC_FOR_AEE + ret = wmt_dev_proc_for_aee_remove(); +#endif + return ret; +} + + diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_step.c b/drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_step.c new file mode 100644 index 0000000000000..b76414ff212ae --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_step.c @@ -0,0 +1,2433 @@ +/* + * Copyright (C) 2016 MediaTek Inc. * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include +#include + +#include "osal.h" +#include "wmt_step.h" +#include "wmt_dev.h" +#include "wmt_plat.h" +#include "mtk_wcn_consys_hw.h" +#include "stp_core.h" +#include "wmt_lib.h" + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S +********************************************************************************/ +static struct step_action *wmt_step_create_emi_action(int param_num, char *params[]); +static struct step_action *wmt_step_create_register_action(int param_num, char *params[]); +static struct step_action *wmt_step_create_gpio_action(int param_num, char *params[]); +static struct step_action *wmt_step_create_disable_reset_action(int param_num, char *params[]); +static struct step_action *wmt_step_create_chip_reset_action(int param_num, char *params[]); +static struct step_action *wmt_step_create_keep_wakeup_action(int param_num, char *params[]); +static struct step_action *wmt_step_create_cancel_wakeup_action(int param_num, char *params[]); +static struct step_action *wmt_step_create_periodic_dump_action(int param_num, char *params[]); +static struct step_action *wmt_step_create_show_string_action(int param_num, char *params[]); +static struct step_action *wmt_step_create_sleep_action(int param_num, char *params[]); +static struct step_action *wmt_step_create_condition_action(int param_num, char *params[]); +static struct step_action *wmt_step_create_value_action(int param_num, char *params[]); +static struct step_action *wmt_step_create_condition_emi_action(int param_num, char *params[]); +static struct step_action *wmt_step_create_condition_register_action(int param_num, char *params[]); + +static void wmt_step_remove_emi_action(struct step_action *p_act); +static void wmt_step_remove_register_action(struct step_action *p_act); +static void wmt_step_remove_gpio_action(struct step_action *p_act); +static void wmt_step_remove_disable_reset_action(struct step_action *p_act); +static void wmt_step_remove_chip_reset_action(struct step_action *p_act); +static void wmt_step_remove_keep_wakeup_action(struct step_action *p_act); +static void wmt_step_remove_cancel_wakeup_action(struct step_action *p_act); +static void wmt_step_remove_periodic_dump_action(struct step_action *p_act); +static void wmt_step_remove_show_string_action(struct step_action *p_act); +static void wmt_step_remove_sleep_action(struct step_action *p_act); +static void wmt_step_remove_condition_action(struct step_action *p_act); +static void wmt_step_remove_value_action(struct step_action *p_act); +static void wmt_step_remove_condition_emi_action(struct step_action *p_act); +static void wmt_step_remove_condition_register_action(struct step_action *p_act); + +static int wmt_step_access_line_state_init(char *tok, + struct step_target_act_list_info *p_parse_info, + struct step_parse_line_data_param_info *p_parse_line_info); +static int wmt_step_access_line_state_tp(char *tok, + struct step_target_act_list_info *p_parse_info, + struct step_parse_line_data_param_info *p_parse_line_info); +static int wmt_step_access_line_state_at(char *tok, + struct step_target_act_list_info *p_parse_info, + struct step_parse_line_data_param_info *p_parse_line_info); +static int wmt_step_access_line_state_at_op(char *tok, + struct step_target_act_list_info *p_parse_info, + struct step_parse_line_data_param_info *p_parse_line_info); +static int wmt_step_access_line_state_pd(char *tok, + struct step_target_act_list_info *p_parse_info, + struct step_parse_line_data_param_info *p_parse_line_info); + +static int wmt_step_operator_result_greater(int l_val, int r_val); +static int wmt_step_operator_result_greater_equal(int l_val, int r_val); +static int wmt_step_operator_result_less(int l_val, int r_val); +static int wmt_step_operator_result_less_equal(int l_val, int r_val); +static int wmt_step_operator_result_equal(int l_val, int r_val); +static int wmt_step_operator_result_not_equal(int l_val, int r_val); +static int wmt_step_operator_result_and(int l_val, int r_val); +static int wmt_step_operator_result_or(int l_val, int r_val); + +/******************************************************************************* + * D E F I N E +********************************************************************************/ +#define STEP_EMI_ACT_INT (int)(*(int *)STEP_ACTION_NAME_EMI) +#define STEP_REG_ACT_INT (int)(*(int *)STEP_ACTION_NAME_REGISTER) +#define STEP_GPIO_ACT_INT (int)(*(int *)STEP_ACTION_NAME_GPIO) +#define STEP_DISABLE_RESET_ACT_INT (int)(*(int *)STEP_ACTION_NAME_DISABLE_RESET) +#define STEP_CHIP_RESET_ACT_INT (int)(*(int *)STEP_ACTION_NAME_CHIP_RESET) +#define STEP_KEEP_WAKEUP_ACT_INT (int)(*(int *)STEP_ACTION_NAME_KEEP_WAKEUP) +#define STEP_CANCEL_KEEP_WAKEUP_ACT_INT (int)(*(int *)STEP_ACTION_NAME_CANCEL_WAKEUP) +#define STEP_SHOW_STRING_ACT_INT (int)(*(int *)STEP_ACTION_NAME_SHOW_STRING) +#define STEP_SLEEP_ACT_INT (int)(*(int *)STEP_ACTION_NAME_SLEEP) +#define STEP_CONDITION_ACT_INT (int)(*(int *)STEP_ACTION_NAME_CONDITION) +#define STEP_VALUE_ACT_INT (int)(*(int *)STEP_ACTION_NAME_VALUE) +#define STEP_CONDITION_EMI_ACT_INT (int)(*(int *)STEP_ACTION_NAME_CONDITION_EMI) +#define STEP_CONDITION_REG_ACT_INT (int)(*(int *)STEP_ACTION_NAME_CONDITION_REGISTER) + +#define STEP_PARSE_LINE_STATE_INIT 0 +#define STEP_PARSE_LINE_STATE_TP 1 +#define STEP_PARSE_LINE_STATE_AT 2 +#define STEP_PARSE_LINE_STATE_AT_OP 3 +#define STEP_PARSE_LINE_STATE_PD_START 4 +#define STEP_PARSE_LINE_STATE_PD_END 5 +/******************************************************************************* + * P R I V A T E D A T A +********************************************************************************/ +struct step_env_struct g_step_env; + +static const struct step_action_contrl wmt_step_action_map[] = { + [STEP_ACTION_INDEX_EMI] = { + wmt_step_create_emi_action, + wmt_step_do_emi_action, + wmt_step_remove_emi_action + }, + [STEP_ACTION_INDEX_REGISTER] = { + wmt_step_create_register_action, + wmt_step_do_register_action, + wmt_step_remove_register_action + }, + [STEP_ACTION_INDEX_GPIO] = { + wmt_step_create_gpio_action, + wmt_step_do_gpio_action, + wmt_step_remove_gpio_action + }, + [STEP_ACTION_INDEX_DISABLE_RESET] = { + wmt_step_create_disable_reset_action, + wmt_step_do_disable_reset_action, + wmt_step_remove_disable_reset_action + }, + [STEP_ACTION_INDEX_CHIP_RESET] = { + wmt_step_create_chip_reset_action, + wmt_step_do_chip_reset_action, + wmt_step_remove_chip_reset_action + }, + [STEP_ACTION_INDEX_KEEP_WAKEUP] = { + wmt_step_create_keep_wakeup_action, + wmt_step_do_keep_wakeup_action, + wmt_step_remove_keep_wakeup_action + }, + [STEP_ACTION_INDEX_CANCEL_WAKEUP] = { + wmt_step_create_cancel_wakeup_action, + wmt_step_do_cancel_wakeup_action, + wmt_step_remove_cancel_wakeup_action + }, + [STEP_ACTION_INDEX_PERIODIC_DUMP] = { + wmt_step_create_periodic_dump_action, + wmt_step_do_periodic_dump_action, + wmt_step_remove_periodic_dump_action, + }, + [STEP_ACTION_INDEX_SHOW_STRING] = { + wmt_step_create_show_string_action, + wmt_step_do_show_string_action, + wmt_step_remove_show_string_action + }, + [STEP_ACTION_INDEX_SLEEP] = { + wmt_step_create_sleep_action, + wmt_step_do_sleep_action, + wmt_step_remove_sleep_action + }, + [STEP_ACTION_INDEX_CONDITION] = { + wmt_step_create_condition_action, + wmt_step_do_condition_action, + wmt_step_remove_condition_action + }, + [STEP_ACTION_INDEX_VALUE] = { + wmt_step_create_value_action, + wmt_step_do_value_action, + wmt_step_remove_value_action + }, + [STEP_ACTION_INDEX_CONDITION_EMI] = { + wmt_step_create_condition_emi_action, + wmt_step_do_condition_emi_action, + wmt_step_remove_condition_emi_action + }, + [STEP_ACTION_INDEX_CONDITION_REGISTER] = { + wmt_step_create_condition_register_action, + wmt_step_do_condition_register_action, + wmt_step_remove_condition_register_action + }, +}; + +static const char * const STEP_TRIGGER_TIME_NAME[] = { + [STEP_TRIGGER_POINT_COMMAND_TIMEOUT] = + "[TP 1] When Command timeout", + [STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT] = + "[TP 2] When Firmware trigger assert", + [STEP_TRIGGER_POINT_BEFORE_CHIP_RESET] = + "[TP 3] Before Chip reset", + [STEP_TRIGGER_POINT_AFTER_CHIP_RESET] = + "[TP 4] After Chip reset", + [STEP_TRIGGER_POINT_BEFORE_WIFI_FUNC_ON] = + "[TP 5] Before Wifi function on", + [STEP_TRIGGER_POINT_BEFORE_WIFI_FUNC_OFF] = + "[TP 6] Before Wifi function off", + [STEP_TRIGGER_POINT_BEFORE_BT_FUNC_ON] = + "[TP 7] Before BT function on", + [STEP_TRIGGER_POINT_BEFORE_BT_FUNC_OFF] = + "[TP 8] Before BT function off", + [STEP_TRIGGER_POINT_BEFORE_FM_FUNC_ON] = + "[TP 9] Before FM function on", + [STEP_TRIGGER_POINT_BEFORE_FM_FUNC_OFF] = + "[TP 10] Before FM function off", + [STEP_TRIGGER_POINT_BEFORE_GPS_FUNC_ON] = + "[TP 11] Before GPS function on", + [STEP_TRIGGER_POINT_BEFORE_GPS_FUNC_OFF] = + "[TP 12] Before GPS function off", + [STEP_TRIGGER_POINT_BEFORE_READ_THERMAL] = + "[TP 13] Before read consys thermal", + [STEP_TRIGGER_POINT_POWER_ON_START] = + "[TP 14] Power on sequence(0): Start power on", + [STEP_TRIGGER_POINT_POWER_ON_BEFORE_GET_CONNSYS_ID] = + "[TP 15] Power on sequence(1): Before can get connsys id", + [STEP_TRIGGER_POINT_POWER_ON_BEFORE_SEND_DOWNLOAD_PATCH] = + "[TP 16] Power on sequence(2): Before send download patch", + [STEP_TRIGGER_POINT_POWER_ON_BEFORE_CONNSYS_RESET] = + "[TP 17] Power on sequence(3): Before connsys reset (donwload patch)", + [STEP_TRIGGER_POINT_POWER_ON_BEFORE_SET_WIFI_LTE_COEX] = + "[TP 18] Power on sequence(4): Before set wifi and lte coex", + [STEP_TRIGGER_POINT_POWER_ON_BEFORE_BT_WIFI_CALIBRATION] = + "[TP 19] Power on sequence(5): Before set BT and Wifi calibration", + [STEP_TRIGGER_POINT_POWER_ON_END] = + "[TP 20] Power on sequence(6): End power on", + [STEP_TRIGGER_POINT_BEFORE_POWER_OFF] = + "[TP 21] Before WMT power off", + [STEP_TRIGGER_POINT_WHEN_AP_SUSPEND] = + "[TP 22] When AP suspend", + [STEP_TRIGGER_POINT_WHEN_AP_RESUME] = + "[TP 23] When AP resume", + [STEP_TRIGGER_POINT_POWER_OFF_HANDSHAKE] = + "[TP 24] When power off handshake", + [STEP_TRIGGER_POINT_BEFORE_RESTORE_CAL_RESULT] = + "[TP 25] Before restore calibration result", + [STEP_TRIGGER_POINT_AFTER_RESTORE_CAL_RESULT] = + "[TP 26] After restore calibration result", + [STEP_TRIGGER_POINT_POWER_ON_AFTER_BT_WIFI_CALIBRATION] = + "[TP 27] Power on sequence(5): After BT and Wi-Fi calibration", + [STEP_TRIGGER_POINT_AFTER_RESTORE_CAL_CMD] = + "[TP 28] After send calibration restore command", + [STEP_TRIGGER_POINT_WHEN_CLOCK_FAIL] = + "[TP 29] When clock fail", + [STEP_TRIGGER_POINT_BEFORE_GPSL5_FUNC_ON] = + "[TP 30] Before GPSL5 function on", + [STEP_TRIGGER_POINT_BEFORE_GPSL5_FUNC_OFF] = + "[TP 31] Before GPSL5 function off", +}; + +static const int wmt_step_func_ctrl_id[WMTDRV_TYPE_MAX][2] = { + [WMTDRV_TYPE_BT] = { + STEP_TRIGGER_POINT_BEFORE_BT_FUNC_OFF, + STEP_TRIGGER_POINT_BEFORE_BT_FUNC_ON + }, + [WMTDRV_TYPE_FM] = { + STEP_TRIGGER_POINT_BEFORE_FM_FUNC_OFF, + STEP_TRIGGER_POINT_BEFORE_FM_FUNC_ON + }, + [WMTDRV_TYPE_GPS] = { + STEP_TRIGGER_POINT_BEFORE_GPS_FUNC_OFF, + STEP_TRIGGER_POINT_BEFORE_GPS_FUNC_ON + }, + [WMTDRV_TYPE_WIFI] = { + STEP_TRIGGER_POINT_BEFORE_WIFI_FUNC_OFF, + STEP_TRIGGER_POINT_BEFORE_WIFI_FUNC_ON + }, + [WMTDRV_TYPE_GPSL5] = { + STEP_TRIGGER_POINT_BEFORE_GPSL5_FUNC_OFF, + STEP_TRIGGER_POINT_BEFORE_GPSL5_FUNC_ON + }, +}; + +typedef int (*STEP_LINE_STATE) (char *, + struct step_target_act_list_info *, struct step_parse_line_data_param_info *); +static const STEP_LINE_STATE wmt_step_line_state_action_map[] = { + [STEP_PARSE_LINE_STATE_INIT] = wmt_step_access_line_state_init, + [STEP_PARSE_LINE_STATE_TP] = wmt_step_access_line_state_tp, + [STEP_PARSE_LINE_STATE_AT] = wmt_step_access_line_state_at, + [STEP_PARSE_LINE_STATE_AT_OP] = wmt_step_access_line_state_at_op, + [STEP_PARSE_LINE_STATE_PD_START] = wmt_step_access_line_state_pd, +}; + +typedef int (*STEP_OPERATOR_RESULT) (int, int); +static const STEP_OPERATOR_RESULT wmt_step_operator_result_map[] = { + [STEP_OPERATOR_GREATER] = wmt_step_operator_result_greater, + [STEP_OPERATOR_GREATER_EQUAL] = wmt_step_operator_result_greater_equal, + [STEP_OPERATOR_LESS] = wmt_step_operator_result_less, + [STEP_OPERATOR_LESS_EQUAL] = wmt_step_operator_result_less_equal, + [STEP_OPERATOR_EQUAL] = wmt_step_operator_result_equal, + [STEP_OPERATOR_NOT_EQUAL] = wmt_step_operator_result_not_equal, + [STEP_OPERATOR_AND] = wmt_step_operator_result_and, + [STEP_OPERATOR_OR] = wmt_step_operator_result_or, +}; + +/******************************************************************************* + * I N T E R N A L F U N C T I O N S +********************************************************************************/ +#ifdef CFG_WMT_STEP +static void wmt_step_init_list(void) +{ + unsigned int i = 0; + + for (i = 0; i < STEP_TRIGGER_POINT_MAX; i++) + INIT_LIST_HEAD(&(g_step_env.actions[i].list)); +} +#endif + +static unsigned char __iomem *wmt_step_get_emi_base_address(void) +{ + if (g_step_env.emi_base_addr == NULL) { + if (gConEmiPhyBase) + g_step_env.emi_base_addr = ioremap_nocache(gConEmiPhyBase, gConEmiSize); + } + + return g_step_env.emi_base_addr; +} + +static void _wmt_step_init_register_base_size(struct device_node *node, int index, int step_index, unsigned long addr) +{ + int flag; + + if (step_index < 0) + return; + + g_step_env.reg_base[step_index].vir_addr = addr; + if (addr != 0) + of_get_address(node, index, &(g_step_env.reg_base[step_index].size), &flag); +} + +static void wmt_step_init_register_base_size(void) +{ + struct device_node *node = NULL; + + /* If you need to change the register index, address. Please update STEP Config comment */ + if (g_pdev != NULL) { + node = g_pdev->dev.of_node; + _wmt_step_init_register_base_size(node, STEP_MCU_BASE_INDEX, + STEP_REGISTER_CONN_MCU_CONFIG_BASE, conn_reg.mcu_base); + _wmt_step_init_register_base_size(node, STEP_TOP_RGU_BASE_INDEX, + STEP_REGISTER_AP_RGU_BASE, conn_reg.ap_rgu_base); + _wmt_step_init_register_base_size(node, STEP_INFRACFG_AO_BASE_INDEX, + STEP_REGISTER_TOPCKGEN_BASE, conn_reg.topckgen_base); + _wmt_step_init_register_base_size(node, STEP_SPM_BASE_INDEX, + STEP_REGISTER_SPM_BASE, conn_reg.spm_base); + _wmt_step_init_register_base_size(node, STEP_MCU_CONN_HIF_ON_BASE_INDEX, + STEP_REGISTER_HIF_ON_BASE, conn_reg.mcu_conn_hif_on_base); + _wmt_step_init_register_base_size(node, STEP_MCU_TOP_MISC_OFF_BASE_INDEX, + STEP_REGISTER_MISC_OFF_BASE, conn_reg.mcu_top_misc_off_base); + _wmt_step_init_register_base_size(node, STEP_MCU_CFG_ON_BASE_INDEX, + STEP_REGISTER_CFG_ON_BASE, conn_reg.mcu_cfg_on_base); + _wmt_step_init_register_base_size(node, STEP_MCU_CIRQ_BASE_INDEX, + STEP_CIRQ_BASE, conn_reg.mcu_cirq_base); + _wmt_step_init_register_base_size(node, STEP_MCU_TOP_MISC_ON_BASE_INDEX, + STEP_MCU_TOP_MISC_ON_BASE, conn_reg.mcu_top_misc_on_base); + } +} + +static void wmt_step_clear_action_list(struct step_action_list *action_list) +{ + struct step_action *p_act = NULL, *p_act_next = NULL; + + list_for_each_entry_safe(p_act, p_act_next, &(action_list->list), list) { + list_del_init(&p_act->list); + wmt_step_remove_action(p_act); + } +} + +static void wmt_step_clear_list(void) +{ + unsigned int i = 0; + + for (i = 0; i < STEP_TRIGGER_POINT_MAX; i++) + wmt_step_clear_action_list(&g_step_env.actions[i]); +} + +static void wmt_step_unioremap_emi(void) +{ + if (g_step_env.emi_base_addr != NULL) { + iounmap(g_step_env.emi_base_addr); + g_step_env.emi_base_addr = NULL; + } +} + +static unsigned char *mtk_step_get_emi_virt_addr(unsigned char *emi_base_addr, unsigned int offset) +{ + unsigned char *p_virtual_addr = NULL; + + if (offset > gConEmiSize) { + WMT_ERR_FUNC("STEP failed: offset size %d over MAX size(%llu)\n", offset, + gConEmiSize); + return NULL; + } + p_virtual_addr = emi_base_addr + offset; + + return p_virtual_addr; +} + +static int wmt_step_get_cfg(const char *p_patch_name, osal_firmware **pp_patch) +{ + osal_firmware *fw = NULL; + + *pp_patch = NULL; + if (request_firmware((const struct firmware **)&fw, p_patch_name, NULL) != 0) { + release_firmware(fw); + return -1; + } + + WMT_DBG_FUNC("Load step cfg %s ok!!\n", p_patch_name); + *pp_patch = fw; + + return 0; +} + +static void wmt_step_sleep_or_delay(int ms) +{ + /* msleep < 20ms can sleep for up to 20ms */ + if (ms < 20) + udelay(ms * 1000); + else + osal_sleep_ms(ms); +} + +static unsigned char wmt_step_to_upper(char str) +{ + if ((str >= 'a') && (str <= 'z')) + return str + ('A' - 'a'); + else + return str; +} + +static void wmt_step_string_to_upper(char *tok) +{ + for (; *tok != '\0'; tok++) + *tok = wmt_step_to_upper(*tok); +} + +static int wmt_step_get_int_from_four_char(char *str) +{ + unsigned char char_array[4]; + int i; + + for (i = 0; i < 4; i++) { + if (*(str + i) == '\0') + return -1; + + char_array[i] = wmt_step_to_upper(*(str + i)); + } + + return *(int *)char_array; +} + +static enum step_trigger_point_id wmt_step_parse_tp_id(char *str) +{ + long tp_id = STEP_TRIGGER_POINT_NO_DEFINE; + + if (osal_strtol(str, 10, &tp_id)) { + WMT_ERR_FUNC("STEP failed: str to value %s\n", str); + return STEP_TRIGGER_POINT_NO_DEFINE; + } + if (tp_id <= STEP_TRIGGER_POINT_NO_DEFINE || tp_id >= STEP_TRIGGER_POINT_MAX) + return STEP_TRIGGER_POINT_NO_DEFINE; + + return (enum step_trigger_point_id)tp_id; +} + +static int wmt_step_parse_pd_expires(PINT8 ptr) +{ + long expires_ms; + + if (osal_strtol(ptr, 0, &expires_ms)) + return -1; + + return (int)expires_ms; +} + +static int wmt_step_parse_act_id(char *str) +{ + int str_to_int = STEP_ACTION_INDEX_NO_DEFINE; + + if (str == NULL) + return STEP_ACTION_INDEX_NO_DEFINE; + + str_to_int = wmt_step_get_int_from_four_char(str); + if (str_to_int == STEP_EMI_ACT_INT) + return STEP_ACTION_INDEX_EMI; + else if (str_to_int == STEP_REG_ACT_INT) + return STEP_ACTION_INDEX_REGISTER; + else if (str_to_int == STEP_GPIO_ACT_INT) + return STEP_ACTION_INDEX_GPIO; + else if (str_to_int == STEP_DISABLE_RESET_ACT_INT) + return STEP_ACTION_INDEX_DISABLE_RESET; + else if (str_to_int == STEP_CHIP_RESET_ACT_INT) + return STEP_ACTION_INDEX_CHIP_RESET; + else if (str_to_int == STEP_KEEP_WAKEUP_ACT_INT) + return STEP_ACTION_INDEX_KEEP_WAKEUP; + else if (str_to_int == STEP_CANCEL_KEEP_WAKEUP_ACT_INT) + return STEP_ACTION_INDEX_CANCEL_WAKEUP; + else if (str_to_int == STEP_SHOW_STRING_ACT_INT) + return STEP_ACTION_INDEX_SHOW_STRING; + else if (str_to_int == STEP_SLEEP_ACT_INT) + return STEP_ACTION_INDEX_SLEEP; + else if (str_to_int == STEP_CONDITION_ACT_INT) + return STEP_ACTION_INDEX_CONDITION; + else if (str_to_int == STEP_VALUE_ACT_INT) + return STEP_ACTION_INDEX_VALUE; + else if (str_to_int == STEP_CONDITION_EMI_ACT_INT) + return STEP_ACTION_INDEX_CONDITION_EMI; + else if (str_to_int == STEP_CONDITION_REG_ACT_INT) + return STEP_ACTION_INDEX_CONDITION_REGISTER; + else + return STEP_ACTION_INDEX_NO_DEFINE; + +} + +static struct step_action_list *wmt_step_get_tp_list(int tp_id) +{ + if (tp_id <= STEP_TRIGGER_POINT_NO_DEFINE || tp_id >= STEP_TRIGGER_POINT_MAX) { + WMT_ERR_FUNC("STEP failed: Write action to tp_id: %d\n", tp_id); + return NULL; + } + + return &g_step_env.actions[tp_id]; +} + +#define STEP_PARSE_LINE_RET_CONTINUE 0 +#define STEP_PARSE_LINE_RET_BREAK 1 + +static void wmt_step_set_line_state(int *p_state, int value) +{ + *p_state = value; +} + +static int wmt_step_access_line_state_init(char *tok, + struct step_target_act_list_info *p_parse_info, + struct step_parse_line_data_param_info *p_parse_line_info) +{ + wmt_step_string_to_upper(tok); + if (osal_strcmp(tok, "[TP") == 0) { + wmt_step_set_line_state(&p_parse_line_info->state, STEP_PARSE_LINE_STATE_TP); + return STEP_PARSE_LINE_RET_CONTINUE; + } + + if (p_parse_info->tp_id == STEP_TRIGGER_POINT_NO_DEFINE) { + WMT_ERR_FUNC("STEP failed: Set trigger point first: %s\n", tok); + return STEP_PARSE_LINE_RET_BREAK; + } + + if (osal_strcmp(tok, "[PD+]") == 0) { + wmt_step_set_line_state(&p_parse_line_info->state, STEP_PARSE_LINE_STATE_PD_START); + return STEP_PARSE_LINE_RET_CONTINUE; + } + + if (osal_strcmp(tok, "[PD-]") == 0) { + wmt_step_set_line_state(&p_parse_line_info->state, STEP_PARSE_LINE_STATE_PD_END); + return STEP_PARSE_LINE_RET_BREAK; + } + + if (osal_strcmp(tok, "[AT]") == 0) { + wmt_step_set_line_state(&p_parse_line_info->state, STEP_PARSE_LINE_STATE_AT); + return STEP_PARSE_LINE_RET_CONTINUE; + } + + return STEP_PARSE_LINE_RET_BREAK; +} + +static int wmt_step_access_line_state_tp(char *tok, + struct step_target_act_list_info *p_parse_info, + struct step_parse_line_data_param_info *p_parse_line_info) +{ + char *pch = NULL; + + if (p_parse_info->p_pd_entry != NULL) { + WMT_ERR_FUNC("STEP failed: Please add [PD-] after [PD+], tok = %s\n", tok); + p_parse_info->p_pd_entry = NULL; + } + + pch = osal_strchr(tok, ']'); + if (pch == NULL) { + WMT_ERR_FUNC("STEP failed: Trigger point format is wrong: %s\n", tok); + } else { + *pch = '\0'; + p_parse_info->tp_id = wmt_step_parse_tp_id(tok); + p_parse_info->p_target_list = wmt_step_get_tp_list(p_parse_info->tp_id); + + if (p_parse_info->tp_id == STEP_TRIGGER_POINT_NO_DEFINE) + WMT_ERR_FUNC("STEP failed: Trigger point no define: %s\n", tok); + } + + return STEP_PARSE_LINE_RET_BREAK; +} + +static int wmt_step_access_line_state_at(char *tok, + struct step_target_act_list_info *p_parse_info, + struct step_parse_line_data_param_info *p_parse_line_info) +{ + p_parse_line_info->act_id = wmt_step_parse_act_id(tok); + if (p_parse_line_info->act_id == STEP_ACTION_INDEX_NO_DEFINE) { + WMT_ERR_FUNC("STEP failed: Action no define: %s\n", tok); + return STEP_PARSE_LINE_RET_BREAK; + } + wmt_step_set_line_state(&p_parse_line_info->state, STEP_PARSE_LINE_STATE_AT_OP); + + return STEP_PARSE_LINE_RET_CONTINUE; +} + +static int wmt_step_access_line_state_at_op(char *tok, + struct step_target_act_list_info *p_parse_info, + struct step_parse_line_data_param_info *p_parse_line_info) +{ + if (p_parse_line_info->param_index >= 0) + p_parse_line_info->act_params[p_parse_line_info->param_index] = tok; + (p_parse_line_info->param_index)++; + + if (p_parse_line_info->param_index >= STEP_PARAMETER_SIZE) { + WMT_ERR_FUNC("STEP failed: Param too much"); + return STEP_PARSE_LINE_RET_BREAK; + } + + return STEP_PARSE_LINE_RET_CONTINUE; +} + +static int wmt_step_access_line_state_pd(char *tok, + struct step_target_act_list_info *p_parse_info, + struct step_parse_line_data_param_info *p_parse_line_info) +{ + int pd_ms = -1; + + pd_ms = wmt_step_parse_pd_expires(tok); + if (pd_ms == -1) + WMT_ERR_FUNC("STEP failed: PD ms failed %s\n", tok); + + if (p_parse_info->p_pd_entry != NULL) + WMT_ERR_FUNC("STEP failed: Please add [PD-] after [PD+], tok = %s\n", tok); + + p_parse_info->p_pd_entry = wmt_step_get_periodic_dump_entry(pd_ms); + if (p_parse_info->p_pd_entry == NULL) + WMT_ERR_FUNC("STEP failed: p_pd_entry create fail\n"); + else + p_parse_info->p_target_list = &(p_parse_info->p_pd_entry->action_list); + + return STEP_PARSE_LINE_RET_BREAK; +} + +static void wmt_step_parse_line_data(char *line, struct step_target_act_list_info *p_parse_info, + STEP_WRITE_ACT_TO_LIST func_act_to_list) +{ + char *tok; + int line_ret = STEP_PARSE_LINE_RET_BREAK; + struct step_parse_line_data_param_info parse_line_info; + + parse_line_info.param_index = 0; + parse_line_info.act_id = STEP_ACTION_INDEX_NO_DEFINE; + parse_line_info.state = STEP_PARSE_LINE_STATE_INIT; + + while ((tok = osal_strsep(&line, " \t")) != NULL) { + if (*tok == '\0') + continue; + if (osal_strcmp(tok, "//") == 0) + break; + + if (wmt_step_line_state_action_map[parse_line_info.state] != NULL) { + line_ret = wmt_step_line_state_action_map[parse_line_info.state] (tok, + p_parse_info, &parse_line_info); + } + + if (line_ret == STEP_PARSE_LINE_RET_CONTINUE) + continue; + else + break; + } + + if (parse_line_info.state == STEP_PARSE_LINE_STATE_AT_OP) { + func_act_to_list(p_parse_info->p_target_list, + parse_line_info.act_id, parse_line_info.param_index, parse_line_info.act_params); + } else if (parse_line_info.state == STEP_PARSE_LINE_STATE_PD_END) { + p_parse_info->p_target_list = wmt_step_get_tp_list(p_parse_info->tp_id); + if (p_parse_info->p_pd_entry != NULL) { + parse_line_info.act_params[0] = (PINT8)p_parse_info->p_pd_entry; + func_act_to_list(p_parse_info->p_target_list, + STEP_ACTION_INDEX_PERIODIC_DUMP, parse_line_info.param_index, + parse_line_info.act_params); + p_parse_info->p_pd_entry = NULL; + } + } +} + +static void _wmt_step_do_actions(struct step_action_list *action_list) +{ + struct step_action *p_act = NULL, *p_act_next = NULL; + + list_for_each_entry_safe(p_act, p_act_next, &action_list->list, list) { + if (p_act->action_id <= STEP_ACTION_INDEX_NO_DEFINE || p_act->action_id >= STEP_ACTION_INDEX_MAX) { + WMT_ERR_FUNC("STEP failed: Wrong action id %d\n", (int)p_act->action_id); + continue; + } + + if (wmt_step_action_map[p_act->action_id].func_do_action != NULL) + wmt_step_action_map[p_act->action_id].func_do_action(p_act, NULL); + else + WMT_ERR_FUNC("STEP failed: Action is NULL\n"); + } +} + +static void wmt_step_start_work(struct step_pd_entry *p_entry) +{ + unsigned int timeout; + int result = 0; + + if (!g_step_env.pd_struct.step_pd_wq) { + WMT_ERR_FUNC("STEP failed: step wq doesn't run\n"); + result = -1; + } + + if (p_entry == NULL) { + WMT_ERR_FUNC("STEP failed: entry is null\n"); + result = -1; + } + + if (result == 0) { + timeout = p_entry->expires_ms; + queue_delayed_work(g_step_env.pd_struct.step_pd_wq, &p_entry->pd_work, timeout); + } +} + +static void wmt_step_pd_work(struct work_struct *work) +{ + struct step_pd_entry *p_entry = NULL; + struct delayed_work *delayed_work = NULL; + int result = 0; + + if (down_read_trylock(&g_step_env.init_rwsem)) { + if (!g_step_env.is_enable) { + WMT_ERR_FUNC("STEP failed: step doesn`t enable\n"); + result = -1; + } + + delayed_work = to_delayed_work(work); + if (delayed_work == NULL) { + WMT_ERR_FUNC("STEP failed: work is NULL\n"); + result = -1; + } + + if (result == 0) { + p_entry = container_of(delayed_work, struct step_pd_entry, pd_work); + + WMT_INFO_FUNC("STEP show: Periodic dump: %d ms\n", p_entry->expires_ms); + _wmt_step_do_actions(&p_entry->action_list); + wmt_step_start_work(p_entry); + } + + up_read(&g_step_env.init_rwsem); + } +} + +static struct step_pd_entry *wmt_step_create_periodic_dump_entry(unsigned int expires) +{ + struct step_pd_entry *p_pd_entry = NULL; + + p_pd_entry = kzalloc(sizeof(struct step_pd_entry), GFP_KERNEL); + if (p_pd_entry == NULL) { + WMT_ERR_FUNC("STEP failed: kzalloc fail\n"); + return NULL; + } + p_pd_entry->expires_ms = expires; + + INIT_DELAYED_WORK(&p_pd_entry->pd_work, wmt_step_pd_work); + INIT_LIST_HEAD(&(p_pd_entry->action_list.list)); + + return p_pd_entry; +} + +static void wmt_step_print_trigger_time(enum step_trigger_point_id tp_id, char *reason) +{ + const char *p_trigger_name = NULL; + + if (tp_id < 0) + return; + + p_trigger_name = STEP_TRIGGER_TIME_NAME[tp_id]; + if (reason != NULL) + WMT_INFO_FUNC("STEP show: Trigger point: %s reason: %s\n", p_trigger_name, reason); + else + WMT_INFO_FUNC("STEP show: Trigger point: %s\n", p_trigger_name); +} + +static VOID wmt_step_do_actions_from_tp(enum step_trigger_point_id tp_id, char *reason) +{ + int result = 0; + + if (down_read_trylock(&g_step_env.init_rwsem)) { + if (g_step_env.is_enable == 0) + result = -1; + + if (tp_id <= STEP_TRIGGER_POINT_NO_DEFINE || tp_id >= STEP_TRIGGER_POINT_MAX) { + WMT_ERR_FUNC("STEP failed: Do actions from tp_id: %d\n", tp_id); + result = -1; + } else if (list_empty(&g_step_env.actions[tp_id].list)) { + result = -1; + } + + if (result == 0) { + wmt_step_print_trigger_time(tp_id, reason); + _wmt_step_do_actions(&g_step_env.actions[tp_id]); + } + + up_read(&g_step_env.init_rwsem); + } +} + +static int wmt_step_write_action(struct step_action_list *p_list, enum step_action_id act_id, + int param_num, char *params[]) +{ + struct step_action *p_action = NULL; + + if (p_list == NULL) { + WMT_ERR_FUNC("STEP failed: p_list is null\n"); + return -1; + } + + p_action = wmt_step_create_action(act_id, param_num, params); + if (p_action != NULL) { + list_add_tail(&(p_action->list), &(p_list->list)); + return 0; + } + + return -1; +} + +static int wmt_step_parse_number_with_symbol(char *ptr, long *value) +{ + int ret = STEP_VALUE_INFO_UNKNOWN; + + if (*ptr == '#') { + if (osal_strtol(ptr + 1, 10, value)) { + WMT_ERR_FUNC("STEP failed: str to value %s\n", ptr); + ret = STEP_VALUE_INFO_UNKNOWN; + } else { + ret = STEP_VALUE_INFO_SYMBOL_REG_BASE; + } + } else if (*ptr == '$') { + if (osal_strtol(ptr + 1, 10, value)) { + WMT_ERR_FUNC("STEP failed: str to value %s\n", ptr); + ret = STEP_VALUE_INFO_UNKNOWN; + } else { + ret = STEP_VALUE_INFO_SYMBOL_TEMP_REG; + } + } else { + if (osal_strtol(ptr, 0, value)) { + WMT_ERR_FUNC("STEP failed: str to value %s\n", ptr); + ret = STEP_VALUE_INFO_UNKNOWN; + } else { + ret = STEP_VALUE_INFO_NUMBER; + } + } + + return ret; +} + +static int wmt_step_parse_register_address(struct step_reg_addr_info *p_reg_addr, char *ptr, long offset) +{ + unsigned long res; + unsigned int symbol; + int num_sym; + + num_sym = wmt_step_parse_number_with_symbol(ptr, &res); + if (num_sym == STEP_VALUE_INFO_SYMBOL_REG_BASE) { + symbol = (unsigned int) res; + if (symbol <= STEP_REGISTER_PHYSICAL_ADDRESS || symbol >= STEP_REGISTER_MAX) { + WMT_ERR_FUNC("STEP failed: No support the base %s\n", ptr); + return -1; + } + res = g_step_env.reg_base[symbol].vir_addr; + + if (res == 0) { + WMT_ERR_FUNC("STEP failed: No support the base %s is 0\n", ptr); + return -1; + } + + if (offset >= g_step_env.reg_base[symbol].size) { + WMT_ERR_FUNC("STEP failed: symbol(%d), offset(%d) over max size(%llu)\n", + symbol, (int) offset, g_step_env.reg_base[symbol].size); + return -1; + } + + p_reg_addr->address = res; + p_reg_addr->address_type = symbol; + } else if (num_sym == STEP_VALUE_INFO_NUMBER) { + p_reg_addr->address = res; + p_reg_addr->address_type = STEP_REGISTER_PHYSICAL_ADDRESS; + } else { + WMT_ERR_FUNC("STEP failed: number with symbol parse fail %s\n", ptr); + return -1; + } + + return 0; +} + +static unsigned int wmt_step_parse_temp_register_id(char *ptr) +{ + unsigned long res; + int num_sym; + + num_sym = wmt_step_parse_number_with_symbol(ptr, &res); + + if (num_sym == STEP_VALUE_INFO_SYMBOL_TEMP_REG) + return res; + else + return STEP_TEMP_REGISTER_SIZE; +} + +static enum step_condition_operator_id wmt_step_parse_operator_id(char *ptr) +{ + if (osal_strcmp(ptr, ">") == 0) + return STEP_OPERATOR_GREATER; + else if (osal_strcmp(ptr, ">=") == 0) + return STEP_OPERATOR_GREATER_EQUAL; + else if (osal_strcmp(ptr, "<") == 0) + return STEP_OPERATOR_LESS; + else if (osal_strcmp(ptr, "<=") == 0) + return STEP_OPERATOR_LESS_EQUAL; + else if (osal_strcmp(ptr, "==") == 0) + return STEP_OPERATOR_EQUAL; + else if (osal_strcmp(ptr, "!=") == 0) + return STEP_OPERATOR_NOT_EQUAL; + else if (osal_strcmp(ptr, "&&") == 0) + return STEP_OPERATOR_AND; + else if (osal_strcmp(ptr, "||") == 0) + return STEP_OPERATOR_OR; + + return STEP_OPERATOR_MAX; +} + +static int wmt_step_operator_result_greater(int l_val, int r_val) +{ + return (l_val > r_val); +} + +static int wmt_step_operator_result_greater_equal(int l_val, int r_val) +{ + return (l_val >= r_val); +} + +static int wmt_step_operator_result_less(int l_val, int r_val) +{ + return (l_val < r_val); +} + +static int wmt_step_operator_result_less_equal(int l_val, int r_val) +{ + return (l_val <= r_val); +} + +static int wmt_step_operator_result_equal(int l_val, int r_val) +{ + return (l_val == r_val); +} + +static int wmt_step_operator_result_not_equal(int l_val, int r_val) +{ + return (l_val != r_val); +} + +static int wmt_step_operator_result_and(int l_val, int r_val) +{ + return (l_val && r_val); +} + +static int wmt_step_operator_result_or(int l_val, int r_val) +{ + return (l_val || r_val); +} + +static char *wmt_step_save_params_msg(int num, char *params[], char *buf, int buf_size) +{ + int i, len, temp; + + for (i = 0, len = 0; i < num; i++) { + if (params[i] == NULL) + break; + + temp = osal_strlen(params[i]) + 1; + + if ((len + temp) >= (buf_size - 1)) + break; + + len += temp; + osal_strncat(buf, params[i], temp); + osal_strncat(buf, " ", 1); + } + osal_strncat(buf, "\0", 1); + + return buf; +} + +static void wmt_step_create_emi_output_log(struct step_emi_info *p_emi_info, int write, + unsigned int begin, unsigned int end) +{ + p_emi_info->is_write = write; + p_emi_info->begin_offset = begin; + p_emi_info->end_offset = end; + p_emi_info->output_mode = STEP_OUTPUT_LOG; +} + +static void wmt_step_create_emi_output_register(struct step_emi_info *p_emi_info, int write, + unsigned int begin, unsigned int mask, unsigned int reg_id) +{ + p_emi_info->is_write = write; + p_emi_info->begin_offset = begin; + p_emi_info->end_offset = begin + 0x4; + p_emi_info->mask = mask; + p_emi_info->temp_reg_id = reg_id; + p_emi_info->output_mode = STEP_OUTPUT_REGISTER; +} + +static int _wmt_step_create_emi_action(struct step_emi_info *p_emi_info, int param_num, char *params[]) +{ + long write, begin, end; + unsigned int reg_id; + char buf[128] = ""; + long mask = 0xFFFFFFFF; + + if (param_num < 3) { + WMT_ERR_FUNC("STEP failed: Init EMI to log param(%d): %s\n", param_num, + wmt_step_save_params_msg(param_num, params, buf, 128)); + return -1; + } + + if (osal_strtol(params[0], 0, &write) || + osal_strtol(params[1], 0, &begin)) { + WMT_ERR_FUNC("STEP failed: str to value %s\n", + wmt_step_save_params_msg(param_num, params, buf, 128)); + return -1; + } + + if (*params[(param_num - 1)] == STEP_TEMP_REGISTER_SYMBOL) { + reg_id = wmt_step_parse_temp_register_id(params[(param_num - 1)]); + if (reg_id >= STEP_PARAMETER_SIZE) { + WMT_ERR_FUNC("STEP failed: register id failed: %s\n", + wmt_step_save_params_msg(param_num, params, buf, 128)); + return -1; + } + + if (param_num > 3) { + if (osal_strtol(params[2], 0, &mask)) { + WMT_ERR_FUNC("STEP failed: str to value %s\n", + wmt_step_save_params_msg(param_num, params, buf, 128)); + return -1; + } + } + + wmt_step_create_emi_output_register(p_emi_info, write, begin, mask, reg_id); + } else { + if (osal_strtol(params[2], 0, &end)) { + WMT_ERR_FUNC("STEP failed: str to value %s\n", + wmt_step_save_params_msg(param_num, params, buf, 128)); + return -1; + } + wmt_step_create_emi_output_log(p_emi_info, write, begin, end); + } + + return 0; +} + +/* + * Support: + * _EMI | R(0) | Begin offset | End offset + * _EMI | R(0) | Begin offset | mask | Output temp register ID ($) + * _EMI | R(0) | Begin offset | Output temp register ID ($) + */ +static struct step_action *wmt_step_create_emi_action(int param_num, char *params[]) +{ + struct step_emi_action *p_emi_act = NULL; + struct step_emi_info *p_emi_info = NULL; + int ret; + + p_emi_act = kzalloc(sizeof(struct step_emi_action), GFP_KERNEL); + if (p_emi_act == NULL) { + WMT_ERR_FUNC("STEP failed: kzalloc emi fail\n"); + return NULL; + } + + p_emi_info = &p_emi_act->info; + ret = _wmt_step_create_emi_action(p_emi_info, param_num, params); + + if (ret != 0) { + kfree(p_emi_act); + return NULL; + } + + return &(p_emi_act->base); +} + +/* + * Support: + * CEMI | Check temp register ID (#) | R(0) | Begin offset | End offset + * CEMI | Check temp register ID (#) | R(0) | Begin offset | mask | Output temp register ID ($) + * CEMI | Check temp register ID (#) | R(0) | Begin offset | Output temp register ID ($) + */ +static struct step_action *wmt_step_create_condition_emi_action(int param_num, char *params[]) +{ + struct step_condition_emi_action *p_cond_emi_act = NULL; + struct step_emi_info *p_emi_info = NULL; + unsigned int reg_id; + char buf[128] = ""; + int ret; + + if (param_num < 1) { + WMT_ERR_FUNC("STEP failed: EMI no params\n"); + return NULL; + } + + reg_id = wmt_step_parse_temp_register_id(params[0]); + if (reg_id >= STEP_PARAMETER_SIZE) { + WMT_ERR_FUNC("STEP failed: condition register id failed: %s\n", + wmt_step_save_params_msg(param_num, params, buf, 128)); + return NULL; + } + + p_cond_emi_act = kzalloc(sizeof(struct step_condition_emi_action), GFP_KERNEL); + if (p_cond_emi_act == NULL) { + WMT_ERR_FUNC("STEP failed: kzalloc condition emi fail\n"); + return NULL; + } + + p_emi_info = &p_cond_emi_act->info; + p_cond_emi_act->cond_reg_id = reg_id; + ret = _wmt_step_create_emi_action(p_emi_info, param_num - 1, ¶ms[1]); + + if (ret != 0) { + kfree(p_cond_emi_act); + return NULL; + } + + return &(p_cond_emi_act->base); +} + +static void wmt_step_create_read_register_output_register(struct step_reigster_info *p_reg_info, + struct step_reg_addr_info reg_addr_info, unsigned int offset, int mask, unsigned int reg_id) +{ + p_reg_info->is_write = 0; + p_reg_info->address_type = reg_addr_info.address_type; + p_reg_info->address = reg_addr_info.address; + p_reg_info->offset = offset; + p_reg_info->times = 1; + p_reg_info->delay_time = 0; + p_reg_info->mask = mask; + p_reg_info->temp_reg_id = reg_id; + p_reg_info->output_mode = STEP_OUTPUT_REGISTER; +} + +static void wmt_step_create_read_register_output_log(struct step_reigster_info *p_reg_info, + struct step_reg_addr_info reg_addr_info, unsigned int offset, unsigned int times, unsigned int delay_time) +{ + p_reg_info->is_write = 0; + p_reg_info->address_type = reg_addr_info.address_type; + p_reg_info->address = reg_addr_info.address; + p_reg_info->offset = offset; + p_reg_info->times = times; + p_reg_info->delay_time = delay_time; + p_reg_info->output_mode = STEP_OUTPUT_LOG; +} + +static void wmt_step_create_write_register_action(struct step_reigster_info *p_reg_info, + struct step_reg_addr_info reg_addr_info, unsigned int offset, int value, int mask) +{ + p_reg_info->is_write = 1; + p_reg_info->address_type = reg_addr_info.address_type; + p_reg_info->address = reg_addr_info.address; + p_reg_info->offset = offset; + p_reg_info->value = value; + p_reg_info->mask = mask; +} + +static int _wmt_step_create_register_action(struct step_reigster_info *p_reg_info, + int param_num, char *params[]) +{ + long write; + struct step_reg_addr_info reg_addr_info; + long offset, value; + unsigned int reg_id = 0; + char buf[128] = ""; + long mask = 0xFFFFFFFF; + long times = 1; + long delay_time = 0; + + if (param_num < 4) { + WMT_ERR_FUNC("STEP failed: Register no params\n"); + return -1; + } + + if (osal_strtol(params[0], 0, &write)) { + WMT_ERR_FUNC("STEP failed: str to value %s\n", + params[0]); + return -1; + } + + if (osal_strtol(params[2], 0, &offset)) { + WMT_ERR_FUNC("STEP failed: str to value %s\n", + wmt_step_save_params_msg(param_num, params, buf, 128)); + return -1; + } + + if (wmt_step_parse_register_address(®_addr_info, params[1], offset) == -1) { + WMT_ERR_FUNC("STEP failed: init write register symbol: %s\n", + wmt_step_save_params_msg(param_num, params, buf, 128)); + return -1; + } + + if (write == 0) { + if (*params[(param_num - 1)] == STEP_TEMP_REGISTER_SYMBOL) { + reg_id = wmt_step_parse_temp_register_id(params[(param_num - 1)]); + if (reg_id >= STEP_PARAMETER_SIZE) { + WMT_ERR_FUNC("STEP failed: register id failed: %s\n", + wmt_step_save_params_msg(param_num, params, buf, 128)); + return -1; + } + + if (param_num > 4) { + if (osal_strtol(params[3], 0, &mask)) { + WMT_ERR_FUNC("STEP failed: str to value %s\n", + wmt_step_save_params_msg(param_num, params, buf, 128)); + return -1; + } + } + + wmt_step_create_read_register_output_register(p_reg_info, reg_addr_info, offset, mask, reg_id); + } else { + if (param_num < 5 || + osal_strtol(params[3], 0, ×) || + osal_strtol(params[4], 0, &delay_time)) { + WMT_ERR_FUNC("STEP failed: str to value %s\n", + wmt_step_save_params_msg(param_num, params, buf, 128)); + return -1; + } + + wmt_step_create_read_register_output_log(p_reg_info, reg_addr_info, offset, times, delay_time); + } + } else { + if (osal_strtol(params[3], 0, &value)) { + WMT_ERR_FUNC("STEP failed: str to value %s\n", + wmt_step_save_params_msg(param_num, params, buf, 128)); + return -1; + } + + if (param_num > 4) { + if (osal_strtol(params[4], 0, &mask)) { + WMT_ERR_FUNC("STEP failed: str to value %s\n", + wmt_step_save_params_msg(param_num, params, buf, 128)); + return -1; + } + } + + wmt_step_create_write_register_action(p_reg_info, reg_addr_info, offset, value, mask); + } + + return 0; +} + +/* + * Support: + * _REG | R(0) | Pre-define base address ID | offset | times | delay time(ms) + * _REG | R(0) | AP Physical address | offset | times | delay time(ms) + * _REG | R(0) | Pre-define base address ID | offset | mask | Output temp register ID ($) + * _REG | R(0) | AP Physical address | offset | mask | Output temp register ID ($) + * _REG | R(0) | Pre-define base address ID | offset | Output temp register ID ($) + * _REG | R(0) | AP Physical address | offset | Output temp register ID ($) + * _REG | W(1) | AP Physical address | offset | value + * _REG | W(1) | AP Physical address | offset | value + * _REG | W(1) | AP Physical address | offset | value | mask + * _REG | W(1) | AP Physical address | offset | value | mask + */ +static struct step_action *wmt_step_create_register_action(int param_num, char *params[]) +{ + struct step_register_action *p_reg_act = NULL; + struct step_reigster_info *p_reg_info = NULL; + int ret; + + p_reg_act = kzalloc(sizeof(struct step_register_action), GFP_KERNEL); + if (p_reg_act == NULL) { + WMT_ERR_FUNC("STEP failed: kzalloc register fail\n"); + return NULL; + } + + p_reg_info = &p_reg_act->info; + ret = _wmt_step_create_register_action(p_reg_info, param_num, params); + + if (ret != 0) { + kfree(p_reg_act); + return NULL; + } + + return &(p_reg_act->base); +} + +/* + * Support: + * CREG | Check temp register ID (#) | R(0) | Pre-define base address ID | offset | times | delay time(ms) + * CREG | Check temp register ID (#) | R(0) | AP Physical address | offset | times | delay time(ms) + * CREG | Check temp register ID (#) | R(0) | Pre-define base address ID | offset | mask | Output temp register ID ($) + * CREG | Check temp register ID (#) | R(0) | AP Physical address | offset | mask | Output temp register ID ($) + * CREG | Check temp register ID (#) | R(0) | Pre-define base address ID | offset | Output temp register ID ($) + * CREG | Check temp register ID (#) | R(0) | AP Physical address | offset | Output temp register ID ($) + * CREG | Check temp register ID (#) | W(1) | AP Physical address | offset | value + * CREG | Check temp register ID (#) | W(1) | AP Physical address | offset | value + * CREG | Check temp register ID (#) | W(1) | AP Physical address | offset | value | mask + * CREG | Check temp register ID (#) | W(1) | AP Physical address | offset | value | mask + */ +static struct step_action *wmt_step_create_condition_register_action(int param_num, char *params[]) +{ + struct step_condition_register_action *p_cond_reg_act = NULL; + struct step_reigster_info *p_reg_info = NULL; + unsigned int reg_id; + char buf[128] = ""; + int ret; + + if (param_num < 0) { + WMT_ERR_FUNC("STEP failed: Init EMI param(%d): %s\n", param_num, + wmt_step_save_params_msg(param_num, params, buf, 128)); + return NULL; + } + + reg_id = wmt_step_parse_temp_register_id(params[0]); + if (reg_id >= STEP_PARAMETER_SIZE) { + WMT_ERR_FUNC("STEP failed: condition register id failed: %s\n", + wmt_step_save_params_msg(param_num, params, buf, 128)); + return NULL; + } + + p_cond_reg_act = kzalloc(sizeof(struct step_condition_register_action), GFP_KERNEL); + if (p_cond_reg_act == NULL) { + WMT_ERR_FUNC("STEP failed: kzalloc condition register fail\n"); + return NULL; + } + + p_reg_info = &p_cond_reg_act->info; + p_cond_reg_act->cond_reg_id = reg_id; + ret = _wmt_step_create_register_action(p_reg_info, param_num - 1, ¶ms[1]); + + if (ret != 0) { + kfree(p_cond_reg_act); + return NULL; + } + + return &(p_cond_reg_act->base); +} + +/* + * Support: + * GPIO | R(0) | Pin number + */ +static struct step_action *wmt_step_create_gpio_action(int param_num, char *params[]) +{ + struct step_gpio_action *p_gpio_act = NULL; + long write, symbol; + char buf[128] = ""; + + if (param_num != 2) { + WMT_ERR_FUNC("STEP failed: init gpio param(%d): %s\n", param_num, + wmt_step_save_params_msg(param_num, params, buf, 128)); + return NULL; + } + + if (osal_strtol(params[0], 0, &write) || + osal_strtol(params[1], 0, &symbol)) { + WMT_ERR_FUNC("STEP failed: str to value %s\n", + wmt_step_save_params_msg(param_num, params, buf, 128)); + return NULL; + } + + p_gpio_act = kzalloc(sizeof(struct step_gpio_action), GFP_KERNEL); + if (p_gpio_act == NULL) { + WMT_ERR_FUNC("STEP failed: kzalloc gpio fail\n"); + return NULL; + } + p_gpio_act->is_write = write; + p_gpio_act->pin_symbol = symbol; + + return &(p_gpio_act->base); +} + +/* + * Support: + * DRST + */ +static struct step_action *wmt_step_create_disable_reset_action(int param_num, char *params[]) +{ + struct step_disable_reset_action *p_drst_act = NULL; + + p_drst_act = kzalloc(sizeof(struct step_disable_reset_action), GFP_KERNEL); + if (p_drst_act == NULL) { + WMT_ERR_FUNC("STEP failed: kzalloc disalbe reset fail\n"); + return NULL; + } + + return &(p_drst_act->base); +} + +/* + * Support: + * _RST + */ +static struct step_action *wmt_step_create_chip_reset_action(int param_num, char *params[]) +{ + struct step_chip_reset_action *p_crst_act = NULL; + + p_crst_act = kzalloc(sizeof(struct step_chip_reset_action), GFP_KERNEL); + if (p_crst_act == NULL) { + WMT_ERR_FUNC("STEP failed: kzalloc chip reset fail\n"); + return NULL; + } + + return &(p_crst_act->base); +} + +/* + * Support: + * WAK+ + */ +static struct step_action *wmt_step_create_keep_wakeup_action(int param_num, char *params[]) +{ + struct step_keep_wakeup_action *p_kwak_act = NULL; + + p_kwak_act = kzalloc(sizeof(struct step_keep_wakeup_action), GFP_KERNEL); + if (p_kwak_act == NULL) { + WMT_ERR_FUNC("STEP failed: kzalloc keep wakeup fail\n"); + return NULL; + } + + return &(p_kwak_act->base); +} + +/* + * Support: + * WAK- + */ +static struct step_action *wmt_step_create_cancel_wakeup_action(int param_num, char *params[]) +{ + struct step_cancel_wakeup_action *p_cwak_act = NULL; + + p_cwak_act = kzalloc(sizeof(struct step_cancel_wakeup_action), GFP_KERNEL); + if (p_cwak_act == NULL) { + WMT_ERR_FUNC("STEP failed: kzalloc cancel wakeup fail\n"); + return NULL; + } + + return &(p_cwak_act->base); +} + +/* + * Support: + * [PD+] | ms + */ +static struct step_action *wmt_step_create_periodic_dump_action(int param_num, char *params[]) +{ + struct step_periodic_dump_action *p_pd_act = NULL; + + if (params[0] == NULL) { + WMT_ERR_FUNC("STEP failed: param null\n"); + return NULL; + } + + p_pd_act = kzalloc(sizeof(struct step_periodic_dump_action), GFP_KERNEL); + if (p_pd_act == NULL) { + WMT_ERR_FUNC("STEP failed: kzalloc fail\n"); + return NULL; + } + + p_pd_act->pd_entry = (struct step_pd_entry *)params[0]; + return &(p_pd_act->base); +} + +/* + * Support: + * SHOW | Message (no space) + */ +static struct step_action *wmt_step_create_show_string_action(int param_num, char *params[]) +{ + struct step_show_string_action *p_show_act = NULL; + char buf[128] = ""; + + if (param_num != 1) { + WMT_ERR_FUNC("STEP failed: init show param(%d): %s\n", param_num, + wmt_step_save_params_msg(param_num, params, buf, 128)); + return NULL; + } + + p_show_act = kzalloc(sizeof(struct step_show_string_action), GFP_KERNEL); + if (p_show_act == NULL) { + WMT_ERR_FUNC("STEP failed: kzalloc show string fail\n"); + return NULL; + } + + p_show_act->content = kzalloc((osal_strlen(params[0]) + 1), GFP_KERNEL); + if (p_show_act->content == NULL) { + WMT_ERR_FUNC("STEP failed: kzalloc show string content fail\n"); + kfree(p_show_act); + return NULL; + } + osal_memcpy(p_show_act->content, params[0], osal_strlen(params[0])); + return &(p_show_act->base); +} + +/* + * Support: + * _SLP | time (ms) + */ +static struct step_action *wmt_step_create_sleep_action(int param_num, char *params[]) +{ + struct step_sleep_action *p_sleep_act = NULL; + long ms; + char buf[128] = ""; + + if (param_num != 1) { + WMT_ERR_FUNC("STEP failed: init sleep param(%d): %s\n", param_num, + wmt_step_save_params_msg(param_num, params, buf, 128)); + return NULL; + } + + if (osal_strtol(params[0], 0, &ms)) { + WMT_ERR_FUNC("STEP failed: str to value %s\n", + params[0]); + return NULL; + } + + p_sleep_act = kzalloc(sizeof(struct step_sleep_action), GFP_KERNEL); + if (p_sleep_act == NULL) { + WMT_ERR_FUNC("STEP failed: kzalloc sleep fail\n"); + return NULL; + } + p_sleep_act->ms = ms; + + return &(p_sleep_act->base); +} + +/* + * Support: + * COND | Check temp register ID ($) | Left temp register ID ($) | Operator | Right temp register ID ($) + * COND | Check temp register ID ($) | Left temp register ID ($) | Operator | value + */ +static struct step_action *wmt_step_create_condition_action(int param_num, char *params[]) +{ + struct step_condition_action *p_cond_act = NULL; + unsigned int res_reg_id, l_reg_id, r_reg_id = 0; + long value = 0; + int mode; + enum step_condition_operator_id op_id; + char buf[128] = ""; + + if (param_num != 4) { + WMT_ERR_FUNC("STEP failed: init sleep param(%d): %s\n", param_num, + wmt_step_save_params_msg(param_num, params, buf, 128)); + return NULL; + } + + res_reg_id = wmt_step_parse_temp_register_id(params[0]); + l_reg_id = wmt_step_parse_temp_register_id(params[1]); + if (res_reg_id >= STEP_PARAMETER_SIZE || l_reg_id >= STEP_PARAMETER_SIZE) { + WMT_ERR_FUNC("STEP failed: register id failed: %s\n", + wmt_step_save_params_msg(param_num, params, buf, 128)); + return NULL; + } + + op_id = wmt_step_parse_operator_id(params[2]); + if (op_id >= STEP_OPERATOR_MAX) { + WMT_ERR_FUNC("STEP failed: operator id failed: %s\n", + wmt_step_save_params_msg(param_num, params, buf, 128)); + return NULL; + } + + if (*params[(param_num - 1)] == STEP_TEMP_REGISTER_SYMBOL) { + r_reg_id = wmt_step_parse_temp_register_id(params[3]); + mode = STEP_CONDITION_RIGHT_REGISTER; + if (r_reg_id >= STEP_PARAMETER_SIZE) { + WMT_ERR_FUNC("STEP failed: register id failed: %s\n", + wmt_step_save_params_msg(param_num, params, buf, 128)); + return NULL; + } + } else { + if (osal_strtol(params[3], 0, &value)) { + WMT_ERR_FUNC("STEP failed: str to value %s\n", + wmt_step_save_params_msg(param_num, params, buf, 128)); + return NULL; + } + mode = STEP_CONDITION_RIGHT_VALUE; + } + + p_cond_act = kzalloc(sizeof(struct step_condition_action), GFP_KERNEL); + if (p_cond_act == NULL) { + WMT_ERR_FUNC("STEP failed: kzalloc condition fail\n"); + return NULL; + } + + p_cond_act->result_temp_reg_id = res_reg_id; + p_cond_act->l_temp_reg_id = l_reg_id; + p_cond_act->operator_id = op_id; + p_cond_act->r_temp_reg_id = r_reg_id; + p_cond_act->value = value; + p_cond_act->mode = mode; + + return &(p_cond_act->base); +} + +/* + * Support: + * _VAL | Save temp register ID ($) | Value + */ +static struct step_action *wmt_step_create_value_action(int param_num, char *params[]) +{ + struct step_value_action *p_val_act = NULL; + unsigned int reg_id; + long value; + char buf[128] = ""; + + if (param_num != 2) { + WMT_ERR_FUNC("STEP failed: init sleep param(%d): %s\n", param_num, + wmt_step_save_params_msg(param_num, params, buf, 128)); + return NULL; + } + + reg_id = wmt_step_parse_temp_register_id(params[0]); + if (reg_id >= STEP_PARAMETER_SIZE) { + WMT_ERR_FUNC("STEP failed: register id failed: %s\n", + wmt_step_save_params_msg(param_num, params, buf, 128)); + return NULL; + } + + if (osal_strtol(params[1], 0, &value)) { + WMT_ERR_FUNC("STEP failed: str to value %s\n", + wmt_step_save_params_msg(param_num, params, buf, 128)); + return NULL; + } + + p_val_act = kzalloc(sizeof(struct step_value_action), GFP_KERNEL); + if (p_val_act == NULL) { + WMT_ERR_FUNC("STEP failed: kzalloc value fail\n"); + return NULL; + } + + p_val_act->temp_reg_id = reg_id; + p_val_act->value = value; + + return &(p_val_act->base); +} + +static int wmt_step_do_write_register_action(struct step_reigster_info *p_reg_info, + STEP_DO_EXTRA func_do_extra) +{ + phys_addr_t phy_addr; + void __iomem *p_addr = NULL; + SIZE_T vir_addr; + + if (p_reg_info->address_type == STEP_REGISTER_PHYSICAL_ADDRESS) { + phy_addr = p_reg_info->address + p_reg_info->offset; + if (phy_addr & 0x3) { + WMT_ERR_FUNC("STEP failed: phy_addr(0x%08x) page failed\n", + (unsigned int)phy_addr); + return -1; + } + + p_addr = ioremap_nocache(phy_addr, 0x4); + if (p_addr) { + CONSYS_REG_WRITE_MASK((unsigned int *)p_addr, p_reg_info->value, p_reg_info->mask); + WMT_INFO_FUNC( + "STEP show: reg write Phy addr(0x%08x): 0x%08x\n", + (unsigned int)phy_addr, CONSYS_REG_READ(p_addr)); + if (func_do_extra != NULL) + func_do_extra(1, CONSYS_REG_READ(p_addr)); + iounmap(p_addr); + } else { + WMT_ERR_FUNC("STEP failed: ioremap(0x%08x) is NULL\n", + (unsigned int)phy_addr); + return -1; + } + } else { + vir_addr = p_reg_info->address + p_reg_info->offset; + if (vir_addr & 0x3) { + WMT_ERR_FUNC("STEP failed: vir_addr(0x%08x) page failed\n", + (unsigned int)vir_addr); + return -1; + } + + CONSYS_REG_WRITE_MASK((unsigned int *)vir_addr, p_reg_info->value, p_reg_info->mask); + WMT_INFO_FUNC( + "STEP show: reg write (symbol, offset)(%d, 0x%08x): 0x%08x\n", + p_reg_info->address_type, p_reg_info->offset, + CONSYS_REG_READ(vir_addr)); + if (func_do_extra != NULL) + func_do_extra(1, CONSYS_REG_READ(vir_addr)); + } + + return 0; +} + +static void _wmt_step_do_read_register_action(struct step_reigster_info *p_reg_info, + STEP_DO_EXTRA func_do_extra, char *info, int value) +{ + int i; + + for (i = 0; i < p_reg_info->times; i++) { + if (i > 0) + wmt_step_sleep_or_delay(p_reg_info->delay_time); + + if (p_reg_info->output_mode == STEP_OUTPUT_REGISTER) + g_step_env.temp_register[p_reg_info->temp_reg_id] = value & p_reg_info->mask; + else + WMT_INFO_FUNC("%s", info); + + if (func_do_extra != NULL) + func_do_extra(1, value); + } +} + +static int wmt_step_do_read_register_action(struct step_reigster_info *p_reg_info, + STEP_DO_EXTRA func_do_extra) +{ +#define WMT_STEP_REGISTER_ACTION_BUF_LEN 128 + phys_addr_t phy_addr; + void __iomem *p_addr = NULL; + SIZE_T vir_addr; + char buf[WMT_STEP_REGISTER_ACTION_BUF_LEN]; + + if (p_reg_info->address_type == STEP_REGISTER_PHYSICAL_ADDRESS) { + phy_addr = p_reg_info->address + p_reg_info->offset; + if (phy_addr & 0x3) { + WMT_ERR_FUNC("STEP failed: phy_addr(0x%08x) page failed\n", + (unsigned int)phy_addr); + return -1; + } + + p_addr = ioremap_nocache(phy_addr, 0x4); + if (p_addr) { + if (snprintf(buf, WMT_STEP_REGISTER_ACTION_BUF_LEN, + "STEP show: reg read Phy addr(0x%08x): 0x%08x\n", + (unsigned int)phy_addr, CONSYS_REG_READ(p_addr)) < 0) + WMT_INFO_FUNC("snprintf buf fail\n"); + else + _wmt_step_do_read_register_action(p_reg_info, func_do_extra, buf, + CONSYS_REG_READ(p_addr)); + iounmap(p_addr); + } else { + WMT_ERR_FUNC("STEP failed: ioremap(0x%08x) is NULL\n", + (unsigned int)phy_addr); + return -1; + } + } else { + vir_addr = p_reg_info->address + p_reg_info->offset; + if (vir_addr & 0x3) { + WMT_ERR_FUNC("STEP failed: vir_addr(0x%08x) page failed\n", + (unsigned int)vir_addr); + return -1; + } + + if (snprintf(buf, WMT_STEP_REGISTER_ACTION_BUF_LEN, + "STEP show: reg read (symbol, offset)(%d, 0x%08x): 0x%08x\n", + p_reg_info->address_type, p_reg_info->offset, + CONSYS_REG_READ(vir_addr)) < 0) + WMT_INFO_FUNC("snprintf buf fail\n"); + else + _wmt_step_do_read_register_action(p_reg_info, func_do_extra, buf, + CONSYS_REG_READ(vir_addr)); + } + + return 0; +} + +static void wmt_step_remove_emi_action(struct step_action *p_act) +{ + struct step_emi_action *p_emi_act = NULL; + + p_emi_act = list_entry_action(emi, p_act); + kfree(p_emi_act); +} + +static void wmt_step_remove_register_action(struct step_action *p_act) +{ + struct step_register_action *p_reg_act = NULL; + + p_reg_act = list_entry_action(register, p_act); + kfree(p_reg_act); +} + +static void wmt_step_remove_gpio_action(struct step_action *p_act) +{ + struct step_gpio_action *p_gpio_act = NULL; + + p_gpio_act = list_entry_action(gpio, p_act); + kfree(p_gpio_act); +} + +static void wmt_step_remove_disable_reset_action(struct step_action *p_act) +{ + struct step_disable_reset_action *p_drst = NULL; + + p_drst = list_entry_action(disable_reset, p_act); + kfree(p_drst); +} + +static void wmt_step_remove_chip_reset_action(struct step_action *p_act) +{ + struct step_chip_reset_action *p_crst = NULL; + + p_crst = list_entry_action(chip_reset, p_act); + kfree(p_crst); +} + +static void wmt_step_remove_keep_wakeup_action(struct step_action *p_act) +{ + struct step_keep_wakeup_action *p_kwak = NULL; + + p_kwak = list_entry_action(keep_wakeup, p_act); + kfree(p_kwak); +} + +static void wmt_step_remove_cancel_wakeup_action(struct step_action *p_act) +{ + struct step_cancel_wakeup_action *p_cwak = NULL; + + p_cwak = list_entry_action(cancel_wakeup, p_act); + kfree(p_cwak); +} + +static void wmt_step_remove_periodic_dump_action(struct step_action *p_act) +{ + struct step_periodic_dump_action *p_pd = NULL; + + p_pd = list_entry_action(periodic_dump, p_act); + kfree(p_pd); +} + +static void wmt_step_remove_show_string_action(struct step_action *p_act) +{ + struct step_show_string_action *p_show = NULL; + + p_show = list_entry_action(show_string, p_act); + if (p_show->content != NULL) + kfree(p_show->content); + + kfree(p_show); +} + +static void wmt_step_remove_sleep_action(struct step_action *p_act) +{ + struct step_sleep_action *p_sleep = NULL; + + p_sleep = list_entry_action(sleep, p_act); + kfree(p_sleep); +} + +static void wmt_step_remove_condition_action(struct step_action *p_act) +{ + struct step_condition_action *p_cond = NULL; + + p_cond = list_entry_action(condition, p_act); + kfree(p_cond); +} + +static void wmt_step_remove_value_action(struct step_action *p_act) +{ + struct step_value_action *p_val = NULL; + + p_val = list_entry_action(value, p_act); + kfree(p_val); +} + +static void wmt_step_remove_condition_emi_action(struct step_action *p_act) +{ + struct step_condition_emi_action *p_cond_emi_act = NULL; + + p_cond_emi_act = list_entry_action(condition_emi, p_act); + kfree(p_cond_emi_act); +} + +static void wmt_step_remove_condition_register_action(struct step_action *p_act) +{ + struct step_condition_register_action *p_cond_reg_act = NULL; + + p_cond_reg_act = list_entry_action(condition_register, p_act); + kfree(p_cond_reg_act); +} + +static int _wmt_step_do_emi_action(struct step_emi_info *p_emi_info, STEP_DO_EXTRA func_do_extra) +{ + unsigned char *p_emi_begin_addr = NULL, *p_emi_end_addr = NULL; + unsigned char __iomem *emi_base_addr = NULL; + unsigned int dis = 0, temp = 0, i = 0; + + if (p_emi_info->is_write != 0) { + WMT_ERR_FUNC("STEP failed: Only support dump EMI region\n"); + return -1; + } + + if (p_emi_info->begin_offset > p_emi_info->end_offset) { + temp = p_emi_info->begin_offset; + p_emi_info->begin_offset = p_emi_info->end_offset; + p_emi_info->end_offset = temp; + } + dis = p_emi_info->end_offset - p_emi_info->begin_offset; + + emi_base_addr = wmt_step_get_emi_base_address(); + if (emi_base_addr == NULL) { + WMT_ERR_FUNC("STEP failed: EMI base address is NULL\n"); + return -1; + } + + if (p_emi_info->begin_offset & 0x3) { + WMT_ERR_FUNC("STEP failed: begin offset(0x%08x) page failed\n", + p_emi_info->begin_offset); + return -1; + } + + p_emi_begin_addr = mtk_step_get_emi_virt_addr(emi_base_addr, p_emi_info->begin_offset); + p_emi_end_addr = mtk_step_get_emi_virt_addr(emi_base_addr, p_emi_info->end_offset); + if (!p_emi_begin_addr) { + WMT_ERR_FUNC("STEP failed: Get NULL begin virtual address 0x%08x\n", + p_emi_info->begin_offset); + return -1; + } + + if (!p_emi_end_addr) { + WMT_ERR_FUNC("STEP failed: Get NULL end virtual address 0x%08x\n", + p_emi_info->end_offset); + return -1; + } + + for (i = 0; i < dis; i += 0x4) { + if (p_emi_info->output_mode == STEP_OUTPUT_REGISTER) { + g_step_env.temp_register[p_emi_info->temp_reg_id] = + (CONSYS_REG_READ(p_emi_begin_addr + i) & p_emi_info->mask); + } else { + WMT_INFO_FUNC("STEP show: EMI action, Phy address(0x%08x): 0x%08x\n", + (unsigned int) (gConEmiPhyBase + p_emi_info->begin_offset + i), + CONSYS_REG_READ(p_emi_begin_addr + i)); + } + + if (func_do_extra != NULL) + func_do_extra(1, CONSYS_REG_READ(p_emi_begin_addr + i)); + } + + return 0; +} + +static bool wmt_step_reg_readable(struct step_reigster_info *p_reg_info) +{ + phys_addr_t phy_addr; + SIZE_T vir_addr; + + if (p_reg_info->address_type == STEP_REGISTER_PHYSICAL_ADDRESS) { + phy_addr = p_reg_info->address + p_reg_info->offset; + if (mtk_consys_is_connsys_reg(phy_addr)) + return wmt_lib_reg_readable(); + else + return 1; + + } else { + if (p_reg_info->address_type == STEP_REGISTER_CONN_MCU_CONFIG_BASE || + p_reg_info->address_type == STEP_REGISTER_MISC_OFF_BASE || + p_reg_info->address_type == STEP_REGISTER_CFG_ON_BASE || + p_reg_info->address_type == STEP_REGISTER_HIF_ON_BASE || + p_reg_info->address_type == STEP_MCU_TOP_MISC_ON_BASE || + p_reg_info->address_type == STEP_CIRQ_BASE) { + vir_addr = p_reg_info->address + p_reg_info->offset; + return wmt_lib_reg_readable_by_addr(vir_addr); + } + } + + return 1; +} + +int _wmt_step_do_register_action(struct step_reigster_info *p_reg_info, STEP_DO_EXTRA func_do_extra) +{ + int ret = 0; + bool is_wakeup = g_step_env.is_keep_wakeup; + + if (is_wakeup == 1) { + if (DISABLE_PSM_MONITOR()) + WMT_ERR_FUNC("STEP failed: Wake up, continue to show register\n"); + } + + if (wmt_lib_power_lock_trylock() == 0) { + WMT_INFO_FUNC("STEP failed: can't get lock\n"); + if (is_wakeup == 1) + ENABLE_PSM_MONITOR(); + return -1; + } + + if (!wmt_step_reg_readable(p_reg_info)) { + wmt_lib_power_lock_release(); + WMT_ERR_FUNC("STEP failed: register cant read (No clock)\n"); + if (is_wakeup == 1) + ENABLE_PSM_MONITOR(); + + return -2; + } + + if (p_reg_info->is_write == 1) + ret = wmt_step_do_write_register_action(p_reg_info, func_do_extra); + else + ret = wmt_step_do_read_register_action(p_reg_info, func_do_extra); + wmt_lib_power_lock_release(); + + if (is_wakeup == 1) + ENABLE_PSM_MONITOR(); + + return ret; +} + +void wmt_step_setup(void) +{ + if (!g_step_env.is_setup) { + g_step_env.is_setup = true; + init_rwsem(&g_step_env.init_rwsem); + wmt_step_init_register_base_size(); + } +} + +/******************************************************************************* + * I N T E R N A L F U N C T I O N S W I T H U T +********************************************************************************/ +int wmt_step_do_emi_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra) +{ + struct step_emi_action *p_emi_act = NULL; + struct step_emi_info *p_emi_info = NULL; + + p_emi_act = list_entry_action(emi, p_act); + p_emi_info = &p_emi_act->info; + return _wmt_step_do_emi_action(p_emi_info, func_do_extra); +} + +int wmt_step_do_condition_emi_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra) +{ + struct step_condition_emi_action *p_cond_emi_act = NULL; + struct step_emi_info *p_emi_info = NULL; + + p_cond_emi_act = list_entry_action(condition_emi, p_act); + p_emi_info = &p_cond_emi_act->info; + + if (g_step_env.temp_register[p_cond_emi_act->cond_reg_id] == 0) { + WMT_INFO_FUNC("STEP show: Dont do emi, condition %c%d is %d\n", + STEP_TEMP_REGISTER_SYMBOL, p_emi_info->temp_reg_id, + g_step_env.temp_register[p_cond_emi_act->cond_reg_id]); + return -1; + } + + return _wmt_step_do_emi_action(p_emi_info, func_do_extra); +} + +int wmt_step_do_register_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra) +{ + struct step_register_action *p_reg_act = NULL; + struct step_reigster_info *p_reg_info = NULL; + + p_reg_act = list_entry_action(register, p_act); + p_reg_info = &p_reg_act->info; + + return _wmt_step_do_register_action(p_reg_info, func_do_extra); +} + +int wmt_step_do_condition_register_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra) +{ + struct step_condition_register_action *p_cond_reg_act = NULL; + struct step_reigster_info *p_reg_info = NULL; + + p_cond_reg_act = list_entry_action(condition_register, p_act); + p_reg_info = &p_cond_reg_act->info; + + if (g_step_env.temp_register[p_cond_reg_act->cond_reg_id] == 0) { + WMT_INFO_FUNC("STEP show: Dont do register, condition %c%d is %d\n", + STEP_TEMP_REGISTER_SYMBOL, p_reg_info->temp_reg_id, + g_step_env.temp_register[p_cond_reg_act->cond_reg_id]); + return -1; + } + + return _wmt_step_do_register_action(p_reg_info, func_do_extra); +} + +int wmt_step_do_gpio_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra) +{ + struct step_gpio_action *p_gpio_act = NULL; + + p_gpio_act = list_entry_action(gpio, p_act); + if (p_gpio_act->is_write == 1) { + WMT_ERR_FUNC("STEP failed: Only support dump GPIO\n"); + return -1; + } + +#ifdef KERNEL_gpio_dump_regs_range + KERNEL_gpio_dump_regs_range(p_gpio_act->pin_symbol, p_gpio_act->pin_symbol); +#else + WMT_INFO_FUNC("STEP show: No support gpio dump\n"); +#endif + if (func_do_extra != NULL) + func_do_extra(0); + + return 0; +} + +int wmt_step_do_disable_reset_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra) +{ + WMT_INFO_FUNC("STEP show: Do disable reset\n"); + mtk_wcn_stp_set_auto_rst(0); + if (func_do_extra != NULL) + func_do_extra(0); + + return 0; +} + +int wmt_step_do_chip_reset_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra) +{ + WMT_INFO_FUNC("STEP show: Do chip reset\n"); + mtk_wcn_wmt_do_reset(WMTDRV_TYPE_WMT); + if (func_do_extra != NULL) + func_do_extra(0); + + return 0; +} + +int wmt_step_do_keep_wakeup_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra) +{ + WMT_INFO_FUNC("STEP show: Do keep wake up\n"); + g_step_env.is_keep_wakeup = 1; + if (func_do_extra != NULL) + func_do_extra(0); + + return 0; +} + +int wmt_step_do_cancel_wakeup_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra) +{ + WMT_INFO_FUNC("STEP show: Do cancel keep wake up\n"); + g_step_env.is_keep_wakeup = 0; + if (func_do_extra != NULL) + func_do_extra(0); + + return 0; +} + +int wmt_step_do_periodic_dump_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra) +{ + struct step_periodic_dump_action *p_pd_act = NULL; + + p_pd_act = list_entry_action(periodic_dump, p_act); + if (p_pd_act->pd_entry->is_enable == 0) { + WMT_INFO_FUNC("STEP show: Start periodic dump(%d ms)\n", + p_pd_act->pd_entry->expires_ms); + wmt_step_start_work(p_pd_act->pd_entry); + p_pd_act->pd_entry->is_enable = 1; + } + + if (func_do_extra != NULL) + func_do_extra(0); + + return 0; +} + +int wmt_step_do_show_string_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra) +{ + struct step_show_string_action *p_show_act = NULL; + + p_show_act = list_entry_action(show_string, p_act); + + WMT_INFO_FUNC("STEP show: %s\n", p_show_act->content); + + if (func_do_extra != NULL) + func_do_extra(1, p_show_act->content); + + return 0; +} + +int wmt_step_do_sleep_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra) +{ + struct step_sleep_action *p_sleep_act = NULL; + + p_sleep_act = list_entry_action(sleep, p_act); + + wmt_step_sleep_or_delay(p_sleep_act->ms); + + if (func_do_extra != NULL) + func_do_extra(0); + + return 0; +} + +int wmt_step_do_condition_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra) +{ + struct step_condition_action *p_cond_act = NULL; + int result, l_val, r_val; + + p_cond_act = list_entry_action(condition, p_act); + + l_val = g_step_env.temp_register[p_cond_act->l_temp_reg_id]; + + if (p_cond_act->mode == STEP_CONDITION_RIGHT_REGISTER) + r_val = g_step_env.temp_register[p_cond_act->r_temp_reg_id]; + else + r_val = p_cond_act->value; + + if ((p_cond_act->operator_id >= 0) && wmt_step_operator_result_map[p_cond_act->operator_id]) { + result = wmt_step_operator_result_map[p_cond_act->operator_id] (l_val, r_val); + g_step_env.temp_register[p_cond_act->result_temp_reg_id] = result; + + WMT_INFO_FUNC("STEP show: Condition %d(%c%d) op %d(%c%d) => %d(%c%d)\n", + l_val, STEP_TEMP_REGISTER_SYMBOL, p_cond_act->l_temp_reg_id, + r_val, STEP_TEMP_REGISTER_SYMBOL, p_cond_act->r_temp_reg_id, + result, STEP_TEMP_REGISTER_SYMBOL, p_cond_act->result_temp_reg_id); + } else { + WMT_ERR_FUNC("STEP failed: operator no define id: %d\n", p_cond_act->operator_id); + } + + if (func_do_extra != NULL) + func_do_extra(1, g_step_env.temp_register[p_cond_act->result_temp_reg_id]); + + return 0; +} + +int wmt_step_do_value_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra) +{ + struct step_value_action *p_val_act = NULL; + + p_val_act = list_entry_action(value, p_act); + + g_step_env.temp_register[p_val_act->temp_reg_id] = p_val_act->value; + + if (func_do_extra != NULL) + func_do_extra(1, g_step_env.temp_register[p_val_act->temp_reg_id]); + + return 0; +} + +struct step_action *wmt_step_create_action(enum step_action_id act_id, int param_num, char *params[]) +{ + struct step_action *p_act = NULL; + + if (act_id <= STEP_ACTION_INDEX_NO_DEFINE || act_id >= STEP_ACTION_INDEX_MAX) { + WMT_ERR_FUNC("STEP failed: Create action id: %d\n", act_id); + return NULL; + } + + if (wmt_step_action_map[act_id].func_create_action != NULL) + p_act = wmt_step_action_map[act_id].func_create_action(param_num, params); + else + WMT_ERR_FUNC("STEP failed: Create no define id: %d\n", act_id); + + if (p_act != NULL) + p_act->action_id = act_id; + + return p_act; +} + +int wmt_step_init_pd_env(void) +{ + g_step_env.pd_struct.step_pd_wq = create_workqueue(STEP_PERIODIC_DUMP_WORK_QUEUE); + if (!g_step_env.pd_struct.step_pd_wq) { + WMT_ERR_FUNC("create_workqueue fail\n"); + return -1; + } + INIT_LIST_HEAD(&g_step_env.pd_struct.pd_list); + + return 0; +} + +int wmt_step_deinit_pd_env(void) +{ + struct step_pd_entry *p_current = NULL; + struct step_pd_entry *p_next = NULL; + + if (!g_step_env.pd_struct.step_pd_wq) + return -1; + + list_for_each_entry_safe(p_current, p_next, &g_step_env.pd_struct.pd_list, list) { + cancel_delayed_work(&p_current->pd_work); + wmt_step_clear_action_list(&p_current->action_list); + } + destroy_workqueue(g_step_env.pd_struct.step_pd_wq); + + return 0; +} + +struct step_pd_entry *wmt_step_get_periodic_dump_entry(unsigned int expires) +{ + struct step_pd_entry *p_current = NULL; + + if (expires <= 0) + return NULL; + + if (!g_step_env.pd_struct.step_pd_wq) { + if (wmt_step_init_pd_env() != 0) + return NULL; + } + + p_current = wmt_step_create_periodic_dump_entry(expires); + if (p_current == NULL) + return NULL; + list_add_tail(&(p_current->list), &(g_step_env.pd_struct.pd_list)); + + return p_current; +} + +int wmt_step_parse_data(const char *in_buf, unsigned int size, + STEP_WRITE_ACT_TO_LIST func_act_to_list) +{ + struct step_target_act_list_info parse_info; + char *buf = NULL, *tmp_buf = NULL; + char *line = NULL; + + buf = osal_malloc(size + 1); + if (!buf) { + WMT_ERR_FUNC("STEP failed: Buf malloc\n"); + return -1; + } + + osal_memcpy(buf, (char *)in_buf, size); + buf[size] = '\0'; + + parse_info.tp_id = STEP_TRIGGER_POINT_NO_DEFINE; + parse_info.p_target_list = NULL; + parse_info.p_pd_entry = NULL; + + tmp_buf = buf; + while ((line = osal_strsep(&tmp_buf, "\r\n")) != NULL) + wmt_step_parse_line_data(line, &parse_info, func_act_to_list); + + osal_free(buf); + + return 0; +} + + +int wmt_step_read_file(const char *file_name) +{ + int ret = -1; + const osal_firmware *p_step_cfg = NULL; + + if (g_step_env.is_enable == 1) + return 0; + + if (0 == wmt_step_get_cfg(file_name, (osal_firmware **) &p_step_cfg)) { + if (0 == wmt_step_parse_data((const char *)p_step_cfg->data, p_step_cfg->size, + wmt_step_write_action)) { + ret = 0; + } else { + ret = -1; + } + + wmt_dev_patch_put((osal_firmware **) &p_step_cfg); + return ret; + } + + WMT_INFO_FUNC("STEP read file, %s is not exist\n", file_name); + + return ret; +} + +void wmt_step_remove_action(struct step_action *p_act) +{ + if (p_act != NULL) { + if (p_act->action_id <= STEP_ACTION_INDEX_NO_DEFINE || p_act->action_id >= STEP_ACTION_INDEX_MAX) { + WMT_ERR_FUNC("STEP failed: Wrong action id %d\n", (int)p_act->action_id); + return; + } + + if (wmt_step_action_map[p_act->action_id].func_remove_action != NULL) + wmt_step_action_map[p_act->action_id].func_remove_action(p_act); + } else { + WMT_ERR_FUNC("STEP failed: Action is NULL\n"); + } +} + +void wmt_step_print_version(void) +{ + WMT_INFO_FUNC("STEP version: %d\n", STEP_VERSION); +} + +/******************************************************************************* + * E X T E R N A L F U N C T I O N S +********************************************************************************/ +void wmt_step_init(void) +{ +#ifdef CFG_WMT_STEP + wmt_step_setup(); + wmt_step_init_list(); + if (wmt_step_read_file(STEP_CONFIG_NAME) == 0) { + wmt_step_print_version(); + down_write(&g_step_env.init_rwsem); + g_step_env.is_enable = 1; + up_write(&g_step_env.init_rwsem); + } +#endif +} + +void wmt_step_deinit(void) +{ + down_write(&g_step_env.init_rwsem); + g_step_env.is_enable = 0; + up_write(&g_step_env.init_rwsem); + wmt_step_clear_list(); + wmt_step_unioremap_emi(); + wmt_step_deinit_pd_env(); +} + +void wmt_step_do_actions(enum step_trigger_point_id tp_id) +{ + wmt_step_do_actions_from_tp(tp_id, NULL); +} + +void wmt_step_func_crtl_do_actions(ENUM_WMTDRV_TYPE_T type, ENUM_WMT_OPID_T opId) +{ + enum step_trigger_point_id tp_id = STEP_TRIGGER_POINT_NO_DEFINE; + + if (type < WMTDRV_TYPE_BT || type >= WMTDRV_TYPE_MAX) { + WMT_ERR_FUNC("STEP failed: Do actions from type: %d\n", type); + return; + } + + switch (opId) { + case WMT_OPID_FUNC_OFF: + tp_id = wmt_step_func_ctrl_id[type][0]; + break; + case WMT_OPID_FUNC_ON: + tp_id = wmt_step_func_ctrl_id[type][1]; + break; + default: + break; + } + + if (tp_id != STEP_TRIGGER_POINT_NO_DEFINE) { + /* default value is 0*/ + wmt_step_do_actions(tp_id); + } +} + +void wmt_step_command_timeout_do_actions(char *reason) +{ + wmt_step_do_actions_from_tp(STEP_TRIGGER_POINT_COMMAND_TIMEOUT, reason); +} + diff --git a/drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_user_proc.c b/drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_user_proc.c new file mode 100644 index 0000000000000..b03e20a4792cd --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/linux/wmt_user_proc.c @@ -0,0 +1,194 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#include "osal_typedef.h" +#include "wmt_user_proc.h" +#include "wmt_lib.h" +#include "stp_core.h" +#include "connsys_debug_utility.h" +#include "wmt_alarm.h" + +#ifdef DFT_TAG +#undef DFT_TAG +#define DFT_TAG "[WMT-DEV]" +#endif + +#define WMT_USER_PROCNAME "driver/wmt_user_proc" +static struct proc_dir_entry *gWmtUserProcEntry; + +static ssize_t wmt_user_proc_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos); + +static INT32 wmt_user_proc_func_ctrl(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_user_proc_wmt_assert_ctrl(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_user_proc_suspend_debug(INT32 par1, INT32 offset, INT32 size); +static INT32 wmt_user_proc_alarm_ctrl(INT32 par1, INT32 offset, INT32 size); +static INT32 wmt_user_proc_set_bt_link_status(INT32 par1, INT32 par2, INT32 par3); + +static const WMT_DEV_USER_PROC_FUNC wmt_dev_user_proc_func[] = { + [0x0] = wmt_user_proc_func_ctrl, + [0x1] = wmt_user_proc_wmt_assert_ctrl, + [0x2] = wmt_user_proc_suspend_debug, + [0x3] = wmt_user_proc_set_bt_link_status, + [0x4] = wmt_user_proc_alarm_ctrl, +}; + +INT32 wmt_user_proc_func_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + MTK_WCN_BOOL ret = MTK_WCN_BOOL_FALSE; + + if (par2 < WMTDRV_TYPE_WMT || par2 == WMTDRV_TYPE_LPBK) { + if (par3 == 0) { + WMT_INFO_FUNC("function off test, type(%d)\n", par2); + ret = mtk_wcn_wmt_func_off(par2); + } else { + WMT_INFO_FUNC("function on test, type(%d)\n", par2); + ret = mtk_wcn_wmt_func_on(par2); + } + WMT_INFO_FUNC("function test return %d\n", ret); + } else + WMT_INFO_FUNC("function ctrl test, invalid type(%d)\n", par2); + + return 0; +} + +INT32 wmt_user_proc_wmt_assert_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + if (par2 > 2 || par2 < 0) + return -1; + + mtk_wcn_stp_coredump_flag_ctrl(par2); + + return 0; +} + +/********************************************************/ +/* par2: */ +/* 0: Off */ +/* others: alarm time (seconds) */ +/********************************************************/ +static INT32 wmt_user_proc_suspend_debug(INT32 par1, INT32 par2, INT32 par3) +{ + if (par2 > 0) + connsys_log_alarm_enable(par2); + else + connsys_log_alarm_disable(); + return 0; +} + +static INT32 wmt_user_proc_alarm_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + if (par2 > 0) + wmt_alarm_start(par2); + else + wmt_alarm_cancel(); + return 0; +} + +static INT32 wmt_user_proc_set_bt_link_status(INT32 par1, INT32 par2, INT32 par3) +{ + if (par2 != 0 && par2 != 1) + return 0; + + wmt_lib_set_bt_link_status(par2, par3); + return 0; +} + +ssize_t wmt_user_proc_write(struct file *filp, const char __user *buffer, size_t count, loff_t *f_pos) +{ + ULONG len = count; + INT8 buf[256]; + PINT8 pBuf; + INT32 x = 0, y = 0, z = 0; + PINT8 pToken = NULL; + PINT8 pDelimiter = " \t"; + LONG res = 0; + + WMT_INFO_FUNC("write parameter len = %d\n\r", (INT32) len); + if (len >= osal_sizeof(buf)) { + WMT_ERR_FUNC("input handling fail!\n"); + len = osal_sizeof(buf) - 1; + return -1; + } + + if (copy_from_user(buf, buffer, len)) + return -EFAULT; + + buf[len] = '\0'; + WMT_INFO_FUNC("write parameter data = %s\n\r", buf); + + pBuf = buf; + pToken = osal_strsep(&pBuf, pDelimiter); + if (pToken != NULL) { + osal_strtol(pToken, 16, &res); + x = (INT32)res; + } else { + x = 0; + } + + pToken = osal_strsep(&pBuf, "\t\n "); + if (pToken != NULL) { + osal_strtol(pToken, 16, &res); + y = (INT32)res; + WMT_INFO_FUNC("y = 0x%08x\n\r", y); + } else { + y = 3000; + } + + pToken = osal_strsep(&pBuf, "\t\n "); + if (pToken != NULL) { + if (0x3 == x) + z = osal_strcmp(pToken, "true") ? 0 : 1; + else { + osal_strtol(pToken, 16, &res); + z = (INT32)res; + } + } else { + z = 10; + } + + WMT_INFO_FUNC("x(0x%08x), y(0x%08x), z(0x%08x)\n\r", x, y, z); + + if (osal_array_size(wmt_dev_user_proc_func) > x && NULL != wmt_dev_user_proc_func[x]) + (*wmt_dev_user_proc_func[x]) (x, y, z); + else + WMT_WARN_FUNC("no handler defined for command id(0x%08x)\n\r", x); + + return len; +} + +INT32 wmt_dev_user_proc_setup(VOID) +{ + static const struct file_operations wmt_user_proc_fops = { + .owner = THIS_MODULE, + .write = wmt_user_proc_write, + }; + INT32 i_ret = 0; + + gWmtUserProcEntry = proc_create(WMT_USER_PROCNAME, 0664, NULL, &wmt_user_proc_fops); + if (gWmtUserProcEntry == NULL) { + WMT_ERR_FUNC("Unable to create / wmt_user_proc proc entry\n\r"); + i_ret = -1; + } + + return i_ret; +} + +INT32 wmt_dev_user_proc_remove(VOID) +{ + if (gWmtUserProcEntry != NULL) + proc_remove(gWmtUserProcEntry); + gWmtUserProcEntry = NULL; + + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_main/platform/include/mtk_wcn_consys_hw.h b/drivers/misc/mediatek/connectivity/common/common_main/platform/include/mtk_wcn_consys_hw.h new file mode 100644 index 0000000000000..15f8541c7fb56 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/platform/include/mtk_wcn_consys_hw.h @@ -0,0 +1,418 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/*! \file + * \brief Declaration of library functions + * + * Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _MTK_WCN_CONSYS_HW_H_ +#define _MTK_WCN_CONSYS_HW_H_ + +/*#include */ +#include "wmt_plat.h" + +/*device tree mode*/ +#ifdef CONFIG_OF +#include +#include +#include +#include +#endif +#include +#include + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) +#include +#endif + +#define ENABLE MTK_WCN_BOOL_TRUE +#define DISABLE MTK_WCN_BOOL_FALSE + +#define KBYTE (1024*sizeof(char)) +#define CONSYS_PAGED_DUMP_SIZE (32*KBYTE) +#define CONSYS_EMI_MEM_SIZE (96*KBYTE) /*coredump space , 96K is enough */ + +#define CONSYS_SET_BIT(REG, BITVAL) (*((volatile UINT32 *)(REG)) |= ((UINT32)(BITVAL))) +#define CONSYS_CLR_BIT(REG, BITVAL) ((*(volatile UINT32 *)(REG)) &= ~((UINT32)(BITVAL))) +#define CONSYS_CLR_BIT_WITH_KEY(REG, BITVAL, KEY) {\ + UINT32 val = (*(volatile UINT32 *)(REG)); \ + val &= ~((UINT32)(BITVAL)); \ + val |= ((UINT32)(KEY)); \ + (*(volatile UINT32 *)(REG)) = val;\ +} +#define CONSYS_REG_READ(addr) (*((volatile UINT32 *)(addr))) +#define CONSYS_REG_WRITE(addr, data) do {\ + writel(data, (volatile void *)addr); \ + mb(); \ +} while (0) +#define CONSYS_REG_WRITE_RANGE(reg, data, end, begin) {\ + UINT32 val = CONSYS_REG_READ(reg); \ + SET_BIT_RANGE(&val, data, end, begin); \ + CONSYS_REG_WRITE(reg, val); \ +} +#define CONSYS_REG_WRITE_MASK(reg, data, mask) {\ + UINT32 val = CONSYS_REG_READ(reg); \ + SET_BIT_MASK(&val, data, mask); \ + CONSYS_REG_WRITE(reg, val); \ +} + +/* + * Write value with value_offset bits of right shift and size bits, + * to the reg_offset-th bit of address reg + * value -----------XXXXXXXXXXXX------------------- + * |<--size-->|<--value_offset-->| + * reg -------------OOOOOOOOOOOO----------------- + * |<--size-->|<--reg_offset-->| + * result -------------XXXXXXXXXXXX----------------- + */ +#define CONSYS_REG_WRITE_OFFSET_RANGE(reg, value, reg_offset, value_offset, size) ({\ + UINT32 data = (value) >> (value_offset); \ + data = GET_BIT_RANGE(data, size, 0); \ + data = data << (reg_offset); \ + CONSYS_REG_WRITE_RANGE(reg, data, ((reg_offset) + ((size) - 1)), reg_offset); \ +}) + +#define CONSYS_REG_WRITE_BIT(reg, offset, val) CONSYS_REG_WRITE_OFFSET_RANGE(reg, ((val) & 1), offset, 0, 1) + +/*force fw assert pattern*/ +#define EXP_APMEM_HOST_OUTBAND_ASSERT_MAGIC_W1 (0x19b30bb1) + +#define DYNAMIC_DUMP_GROUP_NUM 5 + + +#define OPT_POWER_ON_DLM_TABLE (0x1) +#define OPT_SET_MCUCLK_TABLE_1_2 (0x1 << 1) +#define OPT_SET_MCUCLK_TABLE_3_4 (0x1 << 2) +#define OPT_QUERY_ADIE (0x1 << 3) +#define OPT_SET_WIFI_EXT_COMPONENT (0x1 << 4) +#define OPT_WIFI_LTE_COEX (0x1 << 5) +#define OPT_COEX_TDM_REQ_ANTSEL_NUM (0x1 << 6) +#define OPT_BT_TSSI_FROM_WIFI_CONFIG_NEW_OPID (0x1 << 7) +#define OPT_INIT_COEX_BEFORE_RF_CALIBRATION (0x1 << 8) +#define OPT_INIT_COEX_AFTER_RF_CALIBRATION (0x1 << 9) +#define OPT_COEX_CONFIG_ADJUST (0x1 << 10) +#define OPT_COEX_CONFIG_ADJUST_NEW_FLAG (0x1 << 11) +#define OPT_SET_OSC_TYPE (0x1 << 12) +#define OPT_SET_COREDUMP_LEVEL (0x1 << 13) +#define OPT_WIFI_5G_PALDO (0x1 << 14) +#define OPT_GPS_SYNC (0x1 << 15) +#define OPT_WIFI_LTE_COEX_TABLE_0 (0x1 << 16) +#define OPT_WIFI_LTE_COEX_TABLE_1 (0x1 << 17) +#define OPT_WIFI_LTE_COEX_TABLE_2 (0x1 << 18) +#define OPT_WIFI_LTE_COEX_TABLE_3 (0x1 << 19) +#define OPT_COEX_EXT_ELNA_GAIN_P1_SUPPORT (0x1 << 20) +#define OPT_NORMAL_PATCH_DWN_0 (0x1 << 21) +#define OPT_NORMAL_PATCH_DWN_1 (0x1 << 22) +#define OPT_NORMAL_PATCH_DWN_2 (0x1 << 23) +#define OPT_NORMAL_PATCH_DWN_3 (0x1 << 24) +#define OPT_PATCH_CHECKSUM (0x1 << 25) +#define OPT_DISABLE_ROM_PATCH_DWN (0x1 << 26) + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + +struct CONSYS_BASE_ADDRESS { + SIZE_T mcu_base; + SIZE_T ap_rgu_base; + SIZE_T topckgen_base; + SIZE_T spm_base; + SIZE_T mcu_conn_hif_on_base; + SIZE_T mcu_top_misc_off_base; + SIZE_T mcu_cfg_on_base; + SIZE_T mcu_cirq_base; + SIZE_T da_xobuf_base; + SIZE_T mcu_top_misc_on_base; + SIZE_T mcu_conn_hif_pdma_base; + SIZE_T ap_pccif4_base; + SIZE_T infra_ao_pericfg_base; + SIZE_T infracfg_reg_base; +}; + +enum CONSYS_BASE_ADDRESS_INDEX { + MCU_BASE_INDEX = 0, + TOP_RGU_BASE_INDEX, + INFRACFG_AO_BASE_INDEX, + SPM_BASE_INDEX, + MCU_CONN_HIF_ON_BASE_INDEX, + MCU_TOP_MISC_OFF_BASE_INDEX, + MCU_CFG_ON_BASE_INDEX, + MCU_CIRQ_BASE_INDEX, + MCU_TOP_MISC_ON_BASE_INDEX, + MCU_CONN_HIF_PDMA_BASE_INDEX, + AP_PCCIF4_BASE_INDEX, + INFRA_AO_PERICFG_BASE_INDEX, + INFRACFG_REG_BASE_INDEX, +}; + +typedef enum _ENUM_EMI_CTRL_STATE_OFFSET_ { + EXP_APMEM_CTRL_STATE = 0x0, + EXP_APMEM_CTRL_HOST_SYNC_STATE = 0x4, + EXP_APMEM_CTRL_HOST_SYNC_NUM = 0x8, + EXP_APMEM_CTRL_CHIP_SYNC_STATE = 0xc, + EXP_APMEM_CTRL_CHIP_SYNC_NUM = 0x10, + EXP_APMEM_CTRL_CHIP_SYNC_ADDR = 0x14, + EXP_APMEM_CTRL_CHIP_SYNC_LEN = 0x18, + EXP_APMEM_CTRL_CHIP_PRINT_BUFF_START = 0x1c, + EXP_APMEM_CTRL_CHIP_PRINT_BUFF_LEN = 0x20, + EXP_APMEM_CTRL_CHIP_PRINT_BUFF_IDX = 0x24, + EXP_APMEM_CTRL_CHIP_INT_STATUS = 0x28, + EXP_APMEM_CTRL_CHIP_PAGED_DUMP_END = 0x2c, + EXP_APMEM_CTRL_HOST_OUTBAND_ASSERT_W1 = 0x30, + EXP_APMEM_CTRL_CHIP_PAGE_DUMP_NUM = 0x44, + EXP_APMEM_CTRL_CHIP_FW_DBGLOG_MODE = 0x40, + EXP_APMEM_CTRL_CHIP_DYNAMIC_DUMP = 0x48, + EXP_APMEM_CTRL_CHIP_CHECK_SLEEP = 0x4c, + EXP_APMEM_CTRL_ASSERT_FLAG = 0x100, + EXP_APMEM_CTRL_MAX +} ENUM_EMI_CTRL_STATE_OFFSET, *P_ENUM_EMI_CTRL_STATE_OFFSET; + +typedef enum _CONSYS_GPS_CO_CLOCK_TYPE_ { + GPS_TCXO_TYPE = 0, + GPS_CO_TSX_TYPE = 1, + GPS_CO_DCXO_TYPE = 2, + GPS_CO_VCTCXO_TYPE = 3, + GPS_CO_CLOCK_TYPE_MAX +} CONSYS_GPS_CO_CLOCK_TYPE, *P_CONSYS_GPS_CO_CLOCK_TYPE; + +typedef INT32(*CONSYS_IC_CLOCK_BUFFER_CTRL) (MTK_WCN_BOOL enable); +typedef VOID(*CONSYS_IC_HW_RESET_BIT_SET) (MTK_WCN_BOOL enable); +typedef VOID(*CONSYS_IC_HW_SPM_CLK_GATING_ENABLE) (VOID); +typedef INT32(*CONSYS_IC_HW_POWER_CTRL) (MTK_WCN_BOOL enable); +typedef INT32(*CONSYS_IC_AHB_CLOCK_CTRL) (MTK_WCN_BOOL enable); +typedef INT32(*POLLING_CONSYS_IC_CHIPID) (VOID); +typedef VOID(*UPDATE_CONSYS_ROM_DESEL_VALUE) (VOID); +typedef VOID(*CONSYS_HANG_DEBUG)(VOID); +typedef VOID(*CONSYS_IC_ARC_REG_SETTING) (VOID); +typedef VOID(*CONSYS_IC_AFE_REG_SETTING) (VOID); +typedef INT32(*CONSYS_IC_HW_VCN18_CTRL) (MTK_WCN_BOOL enable); +typedef VOID(*CONSYS_IC_VCN28_HW_MODE_CTRL) (UINT32 enable); +typedef INT32(*CONSYS_IC_HW_VCN28_CTRL) (UINT32 enable); +typedef INT32(*CONSYS_IC_HW_WIFI_VCN33_CTRL) (UINT32 enable); +typedef INT32(*CONSYS_IC_HW_BT_VCN33_CTRL) (UINT32 enable); +typedef INT32(*CONSYS_IC_HW_VCN_CTRL_AFTER_IDLE) (VOID); +typedef UINT32(*CONSYS_IC_SOC_CHIPID_GET) (VOID); +typedef INT32(*CONSYS_IC_ADIE_CHIPID_DETECT) (VOID); +typedef INT32(*CONSYS_IC_EMI_MPU_SET_REGION_PROTECTION) (VOID); +typedef UINT32(*CONSYS_IC_EMI_SET_REMAPPING_REG) (VOID); +typedef INT32(*IC_BT_WIFI_SHARE_V33_SPIN_LOCK_INIT) (VOID); +typedef INT32(*CONSYS_IC_CLK_GET_FROM_DTS) (struct platform_device *pdev); +typedef INT32(*CONSYS_IC_PMIC_GET_FROM_DTS) (struct platform_device *pdev); +typedef INT32(*CONSYS_IC_READ_IRQ_INFO_FROM_DTS) (struct platform_device *pdev, PINT32 irq_num, PUINT32 irq_flag); +typedef INT32(*CONSYS_IC_READ_REG_FROM_DTS) (struct platform_device *pdev); +typedef UINT32(*CONSYS_IC_READ_CPUPCR) (VOID); +typedef VOID(*IC_FORCE_TRIGGER_ASSERT_DEBUG_PIN) (VOID); +typedef INT32(*CONSYS_IC_CO_CLOCK_TYPE) (VOID); +typedef P_CONSYS_EMI_ADDR_INFO(*CONSYS_IC_SOC_GET_EMI_PHY_ADD) (VOID); +typedef MTK_WCN_BOOL(*CONSYS_IC_NEED_STORE_PDEV) (VOID); +typedef UINT32(*CONSYS_IC_STORE_PDEV) (struct platform_device *pdev); +typedef UINT32(*CONSYS_IC_STORE_RESET_CONTROL) (struct platform_device *pdev); +typedef MTK_WCN_BOOL(*CONSYS_IC_NEED_GPS) (VOID); +typedef VOID(*CONSYS_IC_SET_IF_PINMUX) (MTK_WCN_BOOL enable); +typedef VOID(*CONSYS_IC_SET_DL_ROM_PATCH_FLAG) (INT32 flag); +typedef INT32(*CONSYS_IC_DEDICATED_LOG_PATH_INIT) (struct platform_device *pdev); +typedef VOID(*CONSYS_IC_DEDICATED_LOG_PATH_DEINIT) (VOID); +typedef INT32(*CONSYS_IC_CHECK_REG_READABLE) (VOID); +typedef INT32(*CONSYS_IC_EMI_COREDUMP_REMAPPING) (UINT8 __iomem **addr, UINT32 enable); +typedef INT32(*CONSYS_IC_RESET_EMI_COREDUMP) (UINT8 __iomem *addr); +typedef VOID(*CONSYS_IC_CLOCK_FAIL_DUMP) (VOID); +typedef INT32(*CONSYS_IC_IS_CONNSYS_REG) (UINT32 addr); +typedef INT32(*CONSYS_IC_IS_HOST_CSR) (SIZE_T addr); +typedef INT32(*CONSYS_IC_DUMP_OSC_STATE) (P_CONSYS_STATE state); +typedef VOID(*CONSYS_IC_SET_PDMA_AXI_RREADY_FORCE_HIGH) (UINT32 enable); +typedef VOID(*CONSYS_IC_SET_MCIF_EMI_MPU_PROTECTION)(MTK_WCN_BOOL enable); +typedef INT32(*CONSYS_IC_CALIBRATION_BACKUP_RESTORE) (VOID); +typedef VOID(*CONSYS_IC_REGISTER_DEVAPC_CB) (VOID); +typedef VOID(*CONSYS_IC_INFRA_REG_DUMP)(VOID); +typedef INT32(*CONSYS_IC_IS_ANT_SWAP_ENABLE_BY_HWID) (INT32 pin_num); +typedef VOID(*CONSYS_IC_GET_ANT_SEL_CR_ADDR) (PUINT32 default_invert_cr, PUINT32 default_invert_bit); +typedef VOID(*CONSYS_IC_EMI_ENTRY_ADDRESS) (VOID); +typedef VOID(*CONSYS_IC_SET_XO_OSC_CTRL) (VOID); +typedef VOID(*CONSYS_IC_IDENTIFY_ADIE) (VOID); +typedef VOID(*CONSYS_IC_WIFI_CTRL_SETTING) (VOID); +typedef VOID(*CONSYS_IC_BUS_TIMEOUT_CONFIG) (VOID); +typedef VOID(*CONSYS_IC_SET_ACCESS_EMI_HW_MODE) (VOID); +typedef INT32(*CONSYS_IC_DUMP_GATING_STATE) (P_CONSYS_STATE state); +typedef INT32(*CONSYS_IC_SLEEP_INFO_ENABLE_CTRL) (UINT32 enable); +typedef INT32(*CONSYS_IC_SLEEP_INFO_READ_CTRL) (WMT_SLEEP_COUNT_TYPE type, PUINT64 sleep_counter, PUINT64 sleep_timer); +typedef INT32(*CONSYS_IC_SLEEP_INFO_CLEAR) (VOID); +typedef UINT64(*CONSYS_IC_GET_OPTIONS) (VOID); + +typedef struct _WMT_CONSYS_IC_OPS_ { + CONSYS_IC_CLOCK_BUFFER_CTRL consys_ic_clock_buffer_ctrl; + CONSYS_IC_HW_RESET_BIT_SET consys_ic_hw_reset_bit_set; + CONSYS_IC_HW_SPM_CLK_GATING_ENABLE consys_ic_hw_spm_clk_gating_enable; + CONSYS_IC_HW_POWER_CTRL consys_ic_hw_power_ctrl; + CONSYS_IC_AHB_CLOCK_CTRL consys_ic_ahb_clock_ctrl; + POLLING_CONSYS_IC_CHIPID polling_consys_ic_chipid; + UPDATE_CONSYS_ROM_DESEL_VALUE update_consys_rom_desel_value; + CONSYS_HANG_DEBUG consys_hang_debug; + CONSYS_IC_ARC_REG_SETTING consys_ic_acr_reg_setting; + CONSYS_IC_AFE_REG_SETTING consys_ic_afe_reg_setting; + CONSYS_IC_HW_VCN18_CTRL consys_ic_hw_vcn18_ctrl; + CONSYS_IC_VCN28_HW_MODE_CTRL consys_ic_vcn28_hw_mode_ctrl; + CONSYS_IC_HW_VCN28_CTRL consys_ic_hw_vcn28_ctrl; + CONSYS_IC_HW_WIFI_VCN33_CTRL consys_ic_hw_wifi_vcn33_ctrl; + CONSYS_IC_HW_BT_VCN33_CTRL consys_ic_hw_bt_vcn33_ctrl; + CONSYS_IC_HW_VCN_CTRL_AFTER_IDLE consys_ic_hw_vcn_ctrl_after_idle; + CONSYS_IC_SOC_CHIPID_GET consys_ic_soc_chipid_get; + CONSYS_IC_ADIE_CHIPID_DETECT consys_ic_adie_chipid_detect; + CONSYS_IC_EMI_MPU_SET_REGION_PROTECTION consys_ic_emi_mpu_set_region_protection; + CONSYS_IC_EMI_SET_REMAPPING_REG consys_ic_emi_set_remapping_reg; + IC_BT_WIFI_SHARE_V33_SPIN_LOCK_INIT ic_bt_wifi_share_v33_spin_lock_init; + CONSYS_IC_CLK_GET_FROM_DTS consys_ic_clk_get_from_dts; + CONSYS_IC_PMIC_GET_FROM_DTS consys_ic_pmic_get_from_dts; + CONSYS_IC_READ_IRQ_INFO_FROM_DTS consys_ic_read_irq_info_from_dts; + CONSYS_IC_READ_REG_FROM_DTS consys_ic_read_reg_from_dts; + CONSYS_IC_READ_CPUPCR consys_ic_read_cpupcr; + IC_FORCE_TRIGGER_ASSERT_DEBUG_PIN ic_force_trigger_assert_debug_pin; + CONSYS_IC_CO_CLOCK_TYPE consys_ic_co_clock_type; + CONSYS_IC_SOC_GET_EMI_PHY_ADD consys_ic_soc_get_emi_phy_add; + CONSYS_IC_NEED_STORE_PDEV consys_ic_need_store_pdev; + CONSYS_IC_STORE_PDEV consys_ic_store_pdev; + CONSYS_IC_STORE_RESET_CONTROL consys_ic_store_reset_control; + CONSYS_IC_NEED_GPS consys_ic_need_gps; + CONSYS_IC_SET_IF_PINMUX consys_ic_set_if_pinmux; + CONSYS_IC_SET_DL_ROM_PATCH_FLAG consys_ic_set_dl_rom_patch_flag; + CONSYS_IC_DEDICATED_LOG_PATH_INIT consys_ic_dedicated_log_path_init; + CONSYS_IC_DEDICATED_LOG_PATH_DEINIT consys_ic_dedicated_log_path_deinit; + CONSYS_IC_CHECK_REG_READABLE consys_ic_check_reg_readable; + CONSYS_IC_EMI_COREDUMP_REMAPPING consys_ic_emi_coredump_remapping; + CONSYS_IC_RESET_EMI_COREDUMP consys_ic_reset_emi_coredump; + CONSYS_IC_CLOCK_FAIL_DUMP consys_ic_clock_fail_dump; + CONSYS_IC_IS_CONNSYS_REG consys_ic_is_connsys_reg; + CONSYS_IC_IS_HOST_CSR consys_ic_is_host_csr; + CONSYS_IC_DUMP_OSC_STATE consys_ic_dump_osc_state; + CONSYS_IC_SET_PDMA_AXI_RREADY_FORCE_HIGH consys_ic_set_pdma_axi_rready_force_high; + CONSYS_IC_SET_MCIF_EMI_MPU_PROTECTION consys_ic_set_mcif_emi_mpu_protection; + CONSYS_IC_CALIBRATION_BACKUP_RESTORE consys_ic_calibration_backup_restore; + CONSYS_IC_REGISTER_DEVAPC_CB consys_ic_register_devapc_cb; + CONSYS_IC_INFRA_REG_DUMP consys_ic_infra_reg_dump; + CONSYS_IC_IS_ANT_SWAP_ENABLE_BY_HWID consys_ic_is_ant_swap_enable_by_hwid; + CONSYS_IC_GET_ANT_SEL_CR_ADDR consys_ic_get_ant_sel_cr_addr; + CONSYS_IC_EMI_ENTRY_ADDRESS consys_ic_emi_entry_address; + CONSYS_IC_SET_XO_OSC_CTRL consys_ic_set_xo_osc_ctrl; + CONSYS_IC_IDENTIFY_ADIE consys_ic_identify_adie; + CONSYS_IC_WIFI_CTRL_SETTING consys_ic_wifi_ctrl_setting; + CONSYS_IC_BUS_TIMEOUT_CONFIG consys_ic_bus_timeout_config; + CONSYS_IC_SET_ACCESS_EMI_HW_MODE consys_ic_set_access_emi_hw_mode; + CONSYS_IC_DUMP_GATING_STATE consys_ic_dump_gating_state; + CONSYS_IC_SLEEP_INFO_ENABLE_CTRL consys_ic_sleep_info_enable_ctrl; + CONSYS_IC_SLEEP_INFO_READ_CTRL consys_ic_sleep_info_read_ctrl; + CONSYS_IC_SLEEP_INFO_CLEAR consys_ic_sleep_info_clear; + CONSYS_IC_GET_OPTIONS consys_ic_get_options; +} WMT_CONSYS_IC_OPS, *P_WMT_CONSYS_IC_OPS; +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +#if CFG_WMT_DUMP_INT_STATUS +extern void mt_irq_dump_status(int irq); +#endif +extern struct CONSYS_BASE_ADDRESS conn_reg; +extern UINT32 gCoClockFlag; +extern EMI_CTRL_STATE_OFFSET mtk_wcn_emi_state_off; +extern CONSYS_EMI_ADDR_INFO mtk_wcn_emi_addr_info; + +extern UINT64 gConEmiSize; +extern phys_addr_t gConEmiPhyBase; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) +extern struct regmap *g_regmap; +#endif + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +INT32 mtk_wcn_consys_hw_init(VOID); +INT32 mtk_wcn_consys_hw_deinit(VOID); +INT32 mtk_wcn_consys_hw_pwr_off(UINT32 co_clock_type); +INT32 mtk_wcn_consys_hw_pwr_on(UINT32 co_clock_type); +INT32 mtk_wcn_consys_hw_rst(UINT32 co_clock_type); +INT32 mtk_wcn_consys_hw_bt_paldo_ctrl(UINT32 enable); +INT32 mtk_wcn_consys_hw_wifi_paldo_ctrl(UINT32 enable); +INT32 mtk_wcn_consys_hw_efuse_paldo_ctrl(UINT32 enable, UINT32 co_clock_type); +INT32 mtk_wcn_consys_hw_vcn28_ctrl(UINT32 enable); +INT32 mtk_wcn_consys_hw_state_show(VOID); +PUINT8 mtk_wcn_consys_emi_virt_addr_get(UINT32 ctrl_state_offset); +P_CONSYS_EMI_ADDR_INFO mtk_wcn_consys_soc_get_emi_phy_add(VOID); +UINT32 mtk_wcn_consys_read_cpupcr(VOID); + +VOID mtk_wcn_force_trigger_assert_debug_pin(VOID); +INT32 mtk_wcn_consys_read_irq_info_from_dts(PINT32 irq_num, PUINT32 irq_flag); +INT32 mtk_wcn_consys_reg_ctrl(UINT32 is_write, enum CONSYS_BASE_ADDRESS_INDEX index, UINT32 offset, + PUINT32 value); + +P_WMT_CONSYS_IC_OPS mtk_wcn_get_consys_ic_ops(VOID); +INT32 mtk_wcn_consys_jtag_set_for_mcu(VOID); +#if CONSYS_ENALBE_SET_JTAG +UINT32 mtk_wcn_consys_jtag_flag_ctrl(UINT32 en); +#endif +#ifdef CONSYS_WMT_REG_SUSPEND_CB_ENABLE +UINT32 mtk_wcn_consys_hw_osc_en_ctrl(UINT32 en); +#endif +UINT32 mtk_wcn_consys_soc_chipid(VOID); +UINT32 mtk_wcn_consys_get_adie_chipid(VOID); +INT32 mtk_wcn_consys_detect_adie_chipid(UINT32 co_clock_type); +#if !defined(CONFIG_MTK_GPIO_LEGACY) +struct pinctrl *mtk_wcn_consys_get_pinctrl(VOID); +#endif +INT32 mtk_wcn_consys_co_clock_type(VOID); +INT32 mtk_wcn_consys_set_dbg_mode(UINT32 flag); +INT32 mtk_wcn_consys_set_dynamic_dump(PUINT32 buf); +INT32 mtk_wdt_swsysret_config(INT32 bit, INT32 set_value); +VOID mtk_wcn_consys_hang_debug(VOID); +UINT32 mtk_consys_get_gps_lna_pin_num(VOID); +INT32 mtk_consys_check_reg_readable(VOID); +INT32 mtk_consys_check_reg_readable_by_addr(SIZE_T addr); +VOID mtk_wcn_consys_clock_fail_dump(VOID); +INT32 mtk_consys_is_connsys_reg(UINT32 addr); +VOID mtk_consys_set_mcif_mpu_protection(MTK_WCN_BOOL enable); +INT32 mtk_consys_is_calibration_backup_restore_support(VOID); +VOID mtk_consys_set_chip_reset_status(INT32 status); +INT32 mtk_consys_chip_reset_status(VOID); +INT32 mtk_consys_is_ant_swap_enable_by_hwid(VOID); +INT32 mtk_consys_dump_osc_state(P_CONSYS_STATE state); +VOID mtk_wcn_consys_ic_get_ant_sel_cr_addr(PUINT32 default_invert_cr, PUINT32 default_invert_bit); +INT32 mtk_wcn_consys_dump_gating_state(P_CONSYS_STATE state); +INT32 mtk_wcn_consys_sleep_info_read_all_ctrl(P_CONSYS_STATE state); +INT32 mtk_wcn_consys_sleep_info_clear(VOID); +INT32 mtk_wcn_consys_sleep_info_restore(VOID); +UINT64 mtk_wcn_consys_get_options(VOID); +#endif /* _MTK_WCN_CONSYS_HW_H_ */ + diff --git a/drivers/misc/mediatek/connectivity/common/common_main/platform/mtk_wcn_cmb_hw.c b/drivers/misc/mediatek/connectivity/common/common_main/platform/mtk_wcn_cmb_hw.c new file mode 100644 index 0000000000000..b2fd526e632f1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/platform/mtk_wcn_cmb_hw.c @@ -0,0 +1,340 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + + + +/******************************************************************************* +* 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 "wmt_plat.h" +#include "wmt_lib.h" +#include "mtk_wcn_cmb_hw.h" +#include "osal_typedef.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; + UINT32 chip_id = 0x0; + + WMT_DBG_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 */ + chip_id = mtk_wcn_wmt_chipid_query(); + if (!((chip_id == 0x6630 || chip_id == 0x6632) + && (wmt_plat_get_comm_if_type() == STP_SDIO_IF_TX))) { + iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); + WMT_INFO_FUNC("CMB-HW, BGF_EINT IRQ unregistered and disabled\n"); + iRet += wmt_plat_gpio_ctrl(PIN_BGF_EINT, PIN_STA_DEINIT); + } + /* 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_DEINIT); + WMT_DBG_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); + if (chip_id != 0x6632) + 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_DBG_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; + UINT32 chip_id = 0x0; + + WMT_DBG_FUNC("CMB-HW, hw_pwr_on start\n"); + + /* disable interrupt firstly */ + chip_id = mtk_wcn_wmt_chipid_query(); + if (!((chip_id == 0x6630 || chip_id == 0x6632) + && (wmt_plat_get_comm_if_type() == STP_SDIO_IF_TX))) + iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); + iRet += wmt_plat_eirq_ctrl(PIN_ALL_EINT, PIN_STA_EINT_DIS); + + /*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); + if (chip_id != 0x6632) + iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_INIT); + iRet += wmt_plat_gpio_ctrl(PIN_SDIO_GRP, PIN_STA_INIT); + if (!((chip_id == 0X6630 || chip_id == 0X6632) + && (wmt_plat_get_comm_if_type() == STP_SDIO_IF_TX))) + 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_sleep_ms(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_sleep_ms(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); + + if (0x6630 == chip_id || 0x6632 == chip_id) { + switch (wmt_plat_get_comm_if_type()) { + case STP_UART_IF_TX: + iRet += wmt_plat_gpio_ctrl(PIN_UART_RX, PIN_STA_OUT_H); + break; + case STP_SDIO_IF_TX: + iRet += wmt_plat_gpio_ctrl(PIN_UART_RX, PIN_STA_OUT_L); + break; + default: + WMT_ERR_FUNC("not supported common interface\n"); + break; + } + } + /*4. PMU->output low, RST->output low, sleep off stable time */ + iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_OUT_L); + if (chip_id != 0x6632) + iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_OUT_L); + osal_sleep_ms(gPwrSeqTime.offStableTime); + + /*5. PMU->output high, sleep rst stable time */ + iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_OUT_H); + osal_sleep_ms(gPwrSeqTime.rstStableTime); + + /*6. RST->output high, sleep on stable time */ + if (chip_id != 0x6632) + iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_OUT_H); + osal_sleep_ms(gPwrSeqTime.onStableTime); + + /*set UART Tx/Rx to UART mode */ + if (0x6630 == chip_id || 0x6632 == chip_id) + iRet += wmt_plat_gpio_ctrl(PIN_UART_RX, PIN_STA_IN_NP); + + + /*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 */ + if (!((chip_id == 0x6630 || chip_id == 0x6632) + && (wmt_plat_get_comm_if_type() == STP_SDIO_IF_TX))) { + iRet += wmt_plat_gpio_ctrl(PIN_BGF_EINT, PIN_STA_MUX); + iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_INIT); + WMT_INFO_FUNC("CMB-HW, BGF_EINT IRQ registered and disabled\n"); + } else { + WMT_DBG_FUNC("CMB-HW, no need to register BGF_EINT for MT6630 & MT6632 SDIO mode\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); + WMT_DBG_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; + UINT32 chip_id = 0x0; + + WMT_INFO_FUNC("CMB-HW, hw_rst start, eirq should be disabled before this step\n"); + chip_id = mtk_wcn_wmt_chipid_query(); + iRet += wmt_plat_gpio_ctrl(PIN_UART_GRP, PIN_STA_INIT); + if (0x6630 == chip_id || 0x6632 == chip_id) { + switch (wmt_plat_get_comm_if_type()) { + case STP_UART_IF_TX: + iRet += wmt_plat_gpio_ctrl(PIN_UART_RX, PIN_STA_OUT_H); + break; + case STP_SDIO_IF_TX: + iRet += wmt_plat_gpio_ctrl(PIN_UART_RX, PIN_STA_OUT_L); + break; + default: + WMT_ERR_FUNC("not supported common interface\n"); + break; + } + } + + /*1. PMU->output low, RST->output low, sleep off stable time */ + iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_OUT_L); + if (chip_id != 0x6632) + iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_OUT_L); + osal_sleep_ms(gPwrSeqTime.offStableTime); + + /*2. PMU->output high, sleep rst stable time */ + iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_OUT_H); + osal_sleep_ms(gPwrSeqTime.rstStableTime); + + /*3. RST->output high, sleep on stable time */ + if (chip_id != 0x6632) + iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_OUT_H); + osal_sleep_ms(gPwrSeqTime.onStableTime); + + /*set UART Tx/Rx to UART mode */ + if (0x6630 == chip_id || 0x6632 == chip_id) + iRet += wmt_plat_gpio_ctrl(PIN_UART_RX, PIN_STA_IN_NP); + + 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] + ); +} + +INT32 mtk_wcn_cmb_hw_state_show(VOID) +{ + wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_SHOW); + wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_SHOW); + wmt_plat_gpio_ctrl(PIN_RTC, PIN_STA_SHOW); + return 0; +} + + + +INT32 mtk_wcn_cmb_hw_init(P_PWR_SEQ_TIME pPwrSeqTime) +{ + if (pPwrSeqTime != NULL && + 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_DBG_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/misc/mediatek/connectivity/common/common_main/platform/mtk_wcn_consys_hw.c b/drivers/misc/mediatek/connectivity/common/common_main/platform/mtk_wcn_consys_hw.c new file mode 100644 index 0000000000000..a828df9574552 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/platform/mtk_wcn_consys_hw.c @@ -0,0 +1,1237 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/*! \file + * \brief Declaration of library functions + * + * Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-CONSYS-HW]" + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "osal_typedef.h" +#include "mtk_wcn_consys_hw.h" +#include "wmt_step.h" +#include "wmt_ic.h" +#include +#include +#include +#include +#include +#include "wmt_lib.h" + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) +#include +#include +#include +#include +#include +#define ALLOCATE_CONNSYS_EMI_FROM_KO 1 +#endif + +#include + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static INT32 mtk_wmt_probe(struct platform_device *pdev); +static INT32 mtk_wmt_remove(struct platform_device *pdev); +static INT32 mtk_wmt_suspend(VOID); +static void mtk_wmt_resume(VOID); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +UINT8 __iomem *pEmibaseaddr; + +P_WMT_CONSYS_IC_OPS wmt_consys_ic_ops; + +struct platform_device *g_pdev; + +#ifdef ALLOCATE_CONNSYS_EMI_FROM_KO +phys_addr_t gConEmiPhyBase; +EXPORT_SYMBOL(gConEmiPhyBase); +unsigned long long gConEmiSize; +EXPORT_SYMBOL(gConEmiSize); +#endif + +UINT32 gps_lna_pin_num = 0xffffffff; + +INT32 chip_reset_status = -1; +static INT32 wifi_ant_swap_gpio_pin_num; + +static UINT32 g_adie_chipid; +static OSAL_SLEEPABLE_LOCK g_adie_chipid_lock; + +static atomic64_t g_sleep_counter_enable = ATOMIC64_INIT(1); +static OSAL_UNSLEEPABLE_LOCK g_sleep_counter_spinlock; + +static atomic_t g_probe_called = ATOMIC_INIT(0); + +#ifdef CONFIG_OF +const struct of_device_id apwmt_of_ids[] = { + {.compatible = "mediatek,mt3967-consys",}, + {.compatible = "mediatek,mt6570-consys",}, + {.compatible = "mediatek,mt6580-consys",}, + {.compatible = "mediatek,mt6735-consys",}, + {.compatible = "mediatek,mt6739-consys",}, + {.compatible = "mediatek,mt6755-consys",}, + {.compatible = "mediatek,mt6757-consys",}, + {.compatible = "mediatek,mt6758-consys",}, + {.compatible = "mediatek,mt6759-consys",}, + {.compatible = "mediatek,mt6763-consys",}, + {.compatible = "mediatek,mt6797-consys",}, + {.compatible = "mediatek,mt8127-consys",}, + {.compatible = "mediatek,mt8163-consys",}, + {.compatible = "mediatek,mt8167-consys",}, + {.compatible = "mediatek,mt6775-consys",}, + {.compatible = "mediatek,mt6771-consys",}, + {.compatible = "mediatek,mt6765-consys",}, + {.compatible = "mediatek,mt6761-consys",}, + {.compatible = "mediatek,mt6779-consys",}, + {.compatible = "mediatek,mt6768-consys",}, + {.compatible = "mediatek,mt6785-consys",}, + {.compatible = "mediatek,mt6833-consys",}, + {.compatible = "mediatek,mt6853-consys",}, + {.compatible = "mediatek,mt6873-consys",}, + {.compatible = "mediatek,mt8168-consys",}, + {} +}; +struct CONSYS_BASE_ADDRESS conn_reg; +#endif + +static struct platform_driver mtk_wmt_dev_drv = { + .probe = mtk_wmt_probe, + .remove = mtk_wmt_remove, + .driver = { + .name = "mtk_wmt", + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = apwmt_of_ids, +#endif + }, +}; + +static struct syscore_ops wmt_dbg_syscore_ops = { + .suspend = mtk_wmt_suspend, + .resume = mtk_wmt_resume, +}; + +/* GPIO part */ +struct pinctrl *consys_pinctrl; + +struct work_struct plt_resume_worker; +static void plat_resume_handler(struct work_struct *work); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) +struct regmap *g_regmap; +#endif + +static int wmt_thermal_get_temp_cb(void *data, int *temp); +static const struct thermal_zone_of_device_ops tz_wmt_thermal_ops = { + .get_temp = wmt_thermal_get_temp_cb, +}; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +INT32 __weak mtk_wcn_consys_jtag_set_for_mcu(VOID) +{ + WMT_PLAT_PR_WARN("Does not support on combo\n"); + return 0; +} + +#if CONSYS_ENALBE_SET_JTAG +UINT32 __weak mtk_wcn_consys_jtag_flag_ctrl(UINT32 en) +{ + WMT_PLAT_PR_WARN("Does not support on combo\n"); + return 0; +} +#endif + +#ifdef CONSYS_WMT_REG_SUSPEND_CB_ENABLE +UINT32 __weak mtk_wcn_consys_hw_osc_en_ctrl(UINT32 en) +{ + WMT_PLAT_PR_WARN("Does not support on combo\n"); + return 0; +} +#endif + +P_WMT_CONSYS_IC_OPS __weak mtk_wcn_get_consys_ic_ops(VOID) +{ + WMT_PLAT_PR_WARN("Does not support on combo\n"); + return NULL; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) +static VOID mtk_wcn_get_regmap(struct platform_device *pdev) +{ + struct device_node *pmic_node; + struct platform_device *pmic_pdev; + struct mt6397_chip *chip; + + pmic_node = of_parse_phandle(pdev->dev.of_node, "pmic", 0); + if (!pmic_node) { + WMT_PLAT_PR_INFO("get pmic_node fail\n"); + return; + } + + pmic_pdev = of_find_device_by_node(pmic_node); + if (!pmic_pdev) { + WMT_PLAT_PR_INFO("get pmic_pdev fail\n"); + return; + } + + chip = dev_get_drvdata(&(pmic_pdev->dev)); + if (!chip) { + WMT_PLAT_PR_INFO("get chip fail\n"); + return; + } + + g_regmap = chip->regmap; + if (IS_ERR_VALUE(g_regmap)) { + g_regmap = NULL; + WMT_PLAT_PR_INFO("get regmap fail\n"); + } +} +#endif + +static INT32 wmt_allocate_connsys_emi(struct platform_device *pdev) +{ +#ifdef ALLOCATE_CONNSYS_EMI_FROM_KO + struct device_node *np; + struct reserved_mem *rmem; + + np = of_parse_phandle(pdev->dev.of_node, "memory-region", 0); + if (!np) { + WMT_PLAT_PR_INFO("no memory-region, np is NULL\n"); + return -1; + } + + rmem = of_reserved_mem_lookup(np); + of_node_put(np); + + if (!rmem) { + WMT_PLAT_PR_INFO("no memory-region\n"); + return -1; + } + + gConEmiPhyBase = rmem->base; + gConEmiSize = rmem->size; +#endif + return 0; +} + +static int wmt_thermal_get_temp_cb(void *data, int *temp) +{ + if (temp) { + *temp = wmt_lib_tm_temp_query() * 1000; + WMT_PLAT_PR_INFO("thermal = %d\n", *temp); + } + return 0; +} + +static INT32 wmt_thermal_register(struct platform_device *pdev) +{ + struct thermal_zone_device *tz; + int ret; + + /* register thermal zone */ + tz = devm_thermal_zone_of_sensor_register( + &pdev->dev, 0, NULL, &tz_wmt_thermal_ops); + + if (IS_ERR(tz)) { + ret = PTR_ERR(tz); + WMT_PLAT_PR_INFO("Failed to register thermal zone device %d\n", ret); + return -1; + } + WMT_PLAT_PR_INFO("Register thermal zone device.\n"); + return 0; +} + +static INT32 mtk_wmt_probe(struct platform_device *pdev) +{ + INT32 iRet = -1; + INT32 pin_ret = 0; + UINT32 pinmux = 0; + struct device_node *pinctl_node = NULL, *pins_node = NULL; + UINT8 __iomem *pConnsysEmiStart = NULL; + + if (pdev) + g_pdev = pdev; + else { + WMT_PLAT_PR_ERR("pdev is NULL\n"); + return -1; + } + + wmt_allocate_connsys_emi(pdev); + wmt_thermal_register(pdev); + + if (wmt_consys_ic_ops->consys_ic_need_store_pdev) { + if (wmt_consys_ic_ops->consys_ic_need_store_pdev() == MTK_WCN_BOOL_TRUE) { + if (wmt_consys_ic_ops->consys_ic_store_pdev) + wmt_consys_ic_ops->consys_ic_store_pdev(pdev); + pm_runtime_enable(&pdev->dev); + } + } + + if (wmt_consys_ic_ops->consys_ic_read_reg_from_dts) + iRet = wmt_consys_ic_ops->consys_ic_read_reg_from_dts(pdev); + else + iRet = -1; + + if (iRet) + return iRet; + + if (wmt_consys_ic_ops->consys_ic_clk_get_from_dts) + iRet = wmt_consys_ic_ops->consys_ic_clk_get_from_dts(pdev); + else + iRet = -1; + + if (iRet) + return iRet; + + if (gConEmiPhyBase) { + pConnsysEmiStart = ioremap_nocache(gConEmiPhyBase, gConEmiSize); + WMT_PLAT_PR_INFO("Clearing Connsys EMI (virtual(0x%p) physical(0x%pa)) %llu bytes\n", + pConnsysEmiStart, &gConEmiPhyBase, gConEmiSize); + memset_io(pConnsysEmiStart, 0, gConEmiSize); + iounmap(pConnsysEmiStart); + pConnsysEmiStart = NULL; + + if (wmt_consys_ic_ops->consys_ic_emi_mpu_set_region_protection) + wmt_consys_ic_ops->consys_ic_emi_mpu_set_region_protection(); + if (wmt_consys_ic_ops->consys_ic_emi_set_remapping_reg) + wmt_consys_ic_ops->consys_ic_emi_set_remapping_reg(); + if (wmt_consys_ic_ops->consys_ic_emi_coredump_remapping) + wmt_consys_ic_ops->consys_ic_emi_coredump_remapping(&pEmibaseaddr, 1); +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + if (wmt_consys_ic_ops->consys_ic_dedicated_log_path_init) + wmt_consys_ic_ops->consys_ic_dedicated_log_path_init(pdev); +#endif + } else { + WMT_PLAT_PR_ERR("consys emi memory address gConEmiPhyBase invalid\n"); + } + +#ifdef CONFIG_MTK_HIBERNATION + WMT_PLAT_PR_INFO("register connsys restore cb for complying with IPOH function\n"); + register_swsusp_restore_noirq_func(ID_M_CONNSYS, mtk_wcn_consys_hw_restore, NULL); +#endif + + if (wmt_consys_ic_ops->ic_bt_wifi_share_v33_spin_lock_init) + wmt_consys_ic_ops->ic_bt_wifi_share_v33_spin_lock_init(); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) + mtk_wcn_get_regmap(pdev); +#endif + if (wmt_consys_ic_ops->consys_ic_pmic_get_from_dts) + wmt_consys_ic_ops->consys_ic_pmic_get_from_dts(pdev); + + consys_pinctrl = devm_pinctrl_get(&pdev->dev); + if (IS_ERR(consys_pinctrl)) { + WMT_PLAT_PR_ERR("cannot find consys pinctrl.\n"); + consys_pinctrl = NULL; + } + + /* find gps lna gpio number */ + if (consys_pinctrl) { + pinctl_node = of_parse_phandle(pdev->dev.of_node, "pinctrl-1", 0); + if (pinctl_node) { + pins_node = of_get_child_by_name(pinctl_node, "pins_cmd_dat"); + if (pins_node) { + pin_ret = of_property_read_u32(pins_node, "pinmux", &pinmux); + if (pin_ret) + pin_ret = of_property_read_u32(pins_node, "pins", &pinmux); + gps_lna_pin_num = (pinmux >> 8) & 0xff; + WMT_PLAT_PR_INFO("GPS LNA gpio pin number:%d, pinmux:0x%08x.\n", + gps_lna_pin_num, pinmux); + } + } + } + + wifi_ant_swap_gpio_pin_num = of_get_named_gpio(pdev->dev.of_node, "wifi_ant_swap_gpio", 0); + WMT_PLAT_PR_INFO("ant swap pin number:%d\n", wifi_ant_swap_gpio_pin_num); + + if (wmt_consys_ic_ops->consys_ic_store_reset_control) + wmt_consys_ic_ops->consys_ic_store_reset_control(pdev); + + if (wmt_consys_ic_ops->consys_ic_register_devapc_cb) + wmt_consys_ic_ops->consys_ic_register_devapc_cb(); + + osal_unsleepable_lock_init(&g_sleep_counter_spinlock); + osal_sleepable_lock_init(&g_adie_chipid_lock); + + INIT_WORK(&plt_resume_worker, plat_resume_handler); + + atomic_set(&g_probe_called, 1); + + return 0; +} + +static INT32 mtk_wmt_remove(struct platform_device *pdev) +{ + if (wmt_consys_ic_ops->consys_ic_need_store_pdev) { + if (wmt_consys_ic_ops->consys_ic_need_store_pdev() == MTK_WCN_BOOL_TRUE) + pm_runtime_disable(&pdev->dev); + } + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + if (wmt_consys_ic_ops->consys_ic_dedicated_log_path_deinit) + wmt_consys_ic_ops->consys_ic_dedicated_log_path_deinit(); +#endif + if (wmt_consys_ic_ops->consys_ic_emi_coredump_remapping) + wmt_consys_ic_ops->consys_ic_emi_coredump_remapping(&pEmibaseaddr, 0); + + if (g_pdev) + g_pdev = NULL; + + osal_unsleepable_lock_deinit(&g_sleep_counter_spinlock); + osal_sleepable_lock_deinit(&g_adie_chipid_lock); + + atomic_set(&g_probe_called, 0); + return 0; +} + +static INT32 mtk_wmt_suspend(VOID) +{ + WMT_PLAT_PR_INFO(" mtk_wmt_suspend !!"); + WMT_STEP_DO_ACTIONS_FUNC(STEP_TRIGGER_POINT_WHEN_AP_SUSPEND); + + mtk_wcn_consys_sleep_info_clear(); + return 0; +} + + +static void plat_resume_handler(struct work_struct *work) +{ + CONSYS_STATE_DMP_INFO dmp_info; + UINT8 dmp_info_buf[DBG_LOG_STR_SIZE]; + int len = 0, i, dmp_cnt = 5; + P_DEV_WMT pDev = &gDevWmt; + + if (wmt_lib_dmp_consys_state(&dmp_info, dmp_cnt, 0) == MTK_WCN_BOOL_TRUE) { + len += snprintf(dmp_info_buf + len, + DBG_LOG_STR_SIZE - len, "0x%08x", dmp_info.cpu_pcr[0]); + + for (i = 1; i < dmp_cnt; i++) + len += snprintf(dmp_info_buf + len, + DBG_LOG_STR_SIZE - len, ";0x%08x", dmp_info.cpu_pcr[i]); + + len += snprintf(dmp_info_buf + len, + DBG_LOG_STR_SIZE - len, ";0x%08x", dmp_info.state.lp[1]); + + len += snprintf(dmp_info_buf + len, + DBG_LOG_STR_SIZE - len, ";0x%08x", dmp_info.state.gating[1]); + + len += snprintf(dmp_info_buf + len, + DBG_LOG_STR_SIZE - len, ";%llu", dmp_info.state.sleep_counter[0]); + for (i = 1; i < WMT_SLEEP_COUNT_MAX; i++) { + len += snprintf(dmp_info_buf + len, + DBG_LOG_STR_SIZE - len, ",%llu", dmp_info.state.sleep_counter[i]); + } + + len += snprintf(dmp_info_buf + len, + DBG_LOG_STR_SIZE - len, ";%llu", dmp_info.state.sleep_timer[0]); + for (i = 1; i < WMT_SLEEP_COUNT_MAX; i++) { + len += snprintf(dmp_info_buf + len, + DBG_LOG_STR_SIZE - len, ",%llu", dmp_info.state.sleep_timer[i]); + } + + WMT_PLAT_PR_INFO("%s\n", dmp_info_buf); + } else { + if ((wmt_lib_get_drv_status(WMTDRV_TYPE_WMT) != DRV_STS_FUNC_ON) + || (osal_test_bit(WMT_STAT_PWR, &pDev->state)) == 0) { + WMT_PLAT_PR_INFO("TOP:0,0;MCU:0,0;BT:0,0;WIFI:0,0;GPS:0,0\n"); + } + } +} + +static void mtk_wmt_resume(VOID) +{ + WMT_PLAT_PR_INFO(" mtk_wmt_resume !!"); + schedule_work(&plt_resume_worker); +} + +INT32 mtk_wcn_consys_sleep_info_read_all_ctrl(P_CONSYS_STATE state) +{ + INT32 ret = 0; + INT32 i = 0; + UINT64 sleep_counter = 0, sleep_timer = 0; + UINT8 strbuf[DBG_LOG_STR_SIZE] = {""}; + UINT32 len = 0; + + WMT_PLAT_PR_DBG("sleep count info read all ctrl start\n"); + + if (wmt_consys_ic_ops->consys_ic_sleep_info_enable_ctrl && + wmt_consys_ic_ops->consys_ic_sleep_info_read_ctrl && + wmt_consys_ic_ops->consys_ic_sleep_info_clear) { + osal_lock_unsleepable_lock(&g_sleep_counter_spinlock); + if (atomic64_read(&g_sleep_counter_enable) == 1) { + for (i = 0; i < WMT_SLEEP_COUNT_MAX; i++) { + sleep_counter = 0; + sleep_timer = 0; + wmt_consys_ic_ops->consys_ic_sleep_info_read_ctrl(i, &sleep_counter, &sleep_timer); + if (state) { + state->sleep_counter[i] = sleep_counter; + state->sleep_timer[i] = sleep_timer; + } + len += osal_sprintf(strbuf + len, "%s%s%s%s%s:%llu,%llu;", + ((i == WMT_SLEEP_COUNT_TOP) ? "TOP" : ""), + ((i == WMT_SLEEP_COUNT_MCU) ? "MCU" : ""), + ((i == WMT_SLEEP_COUNT_BT) ? "BT" : ""), + ((i == WMT_SLEEP_COUNT_WF) ? "WIFI" : ""), + ((i == WMT_SLEEP_COUNT_GPS) ? "GPS" : ""), + sleep_counter, sleep_timer); + } + len += osal_sprintf(strbuf + len - 1, ""); + WMT_PLAT_PR_INFO("%s\n", strbuf); + } else { + ret = -21; + } + osal_unlock_unsleepable_lock(&g_sleep_counter_spinlock); + } + + return ret; +} + +INT32 mtk_wcn_consys_sleep_info_clear(VOID) +{ + INT32 ret = 0; + P_DEV_WMT pDev = &gDevWmt; + + WMT_PLAT_PR_DBG("sleep count info clear start\n"); + + if (wmt_consys_ic_ops->consys_ic_sleep_info_enable_ctrl && + wmt_consys_ic_ops->consys_ic_sleep_info_read_ctrl && + wmt_consys_ic_ops->consys_ic_sleep_info_clear) { + + osal_lock_unsleepable_lock(&g_sleep_counter_spinlock); + + if ((wmt_lib_get_drv_status(WMTDRV_TYPE_WMT) == DRV_STS_FUNC_ON) + && (osal_test_bit(WMT_STAT_PWR, &pDev->state))) + ret = wmt_consys_ic_ops->consys_ic_sleep_info_clear(); + osal_unlock_unsleepable_lock(&g_sleep_counter_spinlock); + } + + return ret; +} + +INT32 mtk_wcn_consys_sleep_info_restore(VOID) +{ + P_DEV_WMT pDev = &gDevWmt; + + WMT_PLAT_PR_DBG("sleep count info restore start\n"); + + if (NULL != wmt_consys_ic_ops && + wmt_consys_ic_ops->consys_ic_sleep_info_enable_ctrl && + wmt_consys_ic_ops->consys_ic_sleep_info_read_ctrl && + wmt_consys_ic_ops->consys_ic_sleep_info_clear) { + if ((wmt_lib_get_drv_status(WMTDRV_TYPE_WMT) == DRV_STS_FUNC_ON) + && (osal_test_bit(WMT_STAT_PWR, &pDev->state))) { + osal_lock_unsleepable_lock(&g_sleep_counter_spinlock); + if (atomic64_read(&g_sleep_counter_enable) == 1) + wmt_consys_ic_ops->consys_ic_sleep_info_enable_ctrl(1); + osal_unlock_unsleepable_lock(&g_sleep_counter_spinlock); + } + } + + return 0; +} + +INT32 mtk_wcn_consys_hw_reg_ctrl(UINT32 on, UINT32 co_clock_type) +{ + INT32 iRet = 0; + + WMT_PLAT_PR_INFO("CONSYS-HW-REG-CTRL(0x%08x),start\n", on); + + if (on) { + WMT_PLAT_PR_DBG("++\n"); + if (wmt_consys_ic_ops->consys_ic_reset_emi_coredump) + wmt_consys_ic_ops->consys_ic_reset_emi_coredump(pEmibaseaddr); + + if (wmt_consys_ic_ops->consys_ic_hw_vcn18_ctrl) + wmt_consys_ic_ops->consys_ic_hw_vcn18_ctrl(ENABLE); + + if (wmt_consys_ic_ops->consys_ic_set_if_pinmux) + wmt_consys_ic_ops->consys_ic_set_if_pinmux(ENABLE); + + udelay(150); + + if (co_clock_type) { + WMT_PLAT_PR_INFO("co clock type(%d),turn on clk buf\n", co_clock_type); + if (wmt_consys_ic_ops->consys_ic_clock_buffer_ctrl) + wmt_consys_ic_ops->consys_ic_clock_buffer_ctrl(ENABLE); + } + + if (co_clock_type) { + /*if co-clock mode: */ + /*1.set VCN28 to SW control mode (with PMIC_WRAP API) */ + if (wmt_consys_ic_ops->consys_ic_vcn28_hw_mode_ctrl) + wmt_consys_ic_ops->consys_ic_vcn28_hw_mode_ctrl(DISABLE); + } else { + /*if NOT co-clock: */ + /*1.set VCN28 to HW control mode (with PMIC_WRAP API) */ + /*2.turn on VCN28 LDO (with PMIC_WRAP API)" */ + if (wmt_consys_ic_ops->consys_ic_vcn28_hw_mode_ctrl) + wmt_consys_ic_ops->consys_ic_vcn28_hw_mode_ctrl(ENABLE); + if (wmt_consys_ic_ops->consys_ic_hw_vcn28_ctrl) + wmt_consys_ic_ops->consys_ic_hw_vcn28_ctrl(ENABLE); + } + + /* turn on VCN28 LDO for reading efuse usage */ + mtk_wcn_consys_hw_efuse_paldo_ctrl(ENABLE, co_clock_type); + + if (wmt_consys_ic_ops->consys_ic_hw_reset_bit_set) + wmt_consys_ic_ops->consys_ic_hw_reset_bit_set(ENABLE); + if (wmt_consys_ic_ops->consys_ic_hw_spm_clk_gating_enable) + wmt_consys_ic_ops->consys_ic_hw_spm_clk_gating_enable(); + if (wmt_consys_ic_ops->consys_ic_hw_power_ctrl) + wmt_consys_ic_ops->consys_ic_hw_power_ctrl(ENABLE); + + udelay(10); + + if (wmt_consys_ic_ops->consys_ic_ahb_clock_ctrl) + wmt_consys_ic_ops->consys_ic_ahb_clock_ctrl(ENABLE); + + WMT_STEP_DO_ACTIONS_FUNC(STEP_TRIGGER_POINT_POWER_ON_BEFORE_GET_CONNSYS_ID); + + if (wmt_consys_ic_ops->polling_consys_ic_chipid && + wmt_consys_ic_ops->polling_consys_ic_chipid() < 0) + return -1; + + if (wmt_consys_ic_ops->consys_ic_hw_vcn_ctrl_after_idle) + wmt_consys_ic_ops->consys_ic_hw_vcn_ctrl_after_idle(); + if (wmt_consys_ic_ops->consys_ic_set_access_emi_hw_mode) + wmt_consys_ic_ops->consys_ic_set_access_emi_hw_mode(); + if (wmt_consys_ic_ops->update_consys_rom_desel_value) + wmt_consys_ic_ops->update_consys_rom_desel_value(); + if (wmt_consys_ic_ops->consys_ic_acr_reg_setting) + wmt_consys_ic_ops->consys_ic_acr_reg_setting(); + if (wmt_consys_ic_ops->consys_ic_afe_reg_setting) + wmt_consys_ic_ops->consys_ic_afe_reg_setting(); + if (wmt_consys_ic_ops->consys_ic_emi_entry_address) + wmt_consys_ic_ops->consys_ic_emi_entry_address(); + if (wmt_consys_ic_ops->consys_ic_set_xo_osc_ctrl) + wmt_consys_ic_ops->consys_ic_set_xo_osc_ctrl(); + if (wmt_consys_ic_ops->consys_ic_identify_adie) + wmt_consys_ic_ops->consys_ic_identify_adie(); + if (wmt_consys_ic_ops->consys_ic_wifi_ctrl_setting) + wmt_consys_ic_ops->consys_ic_wifi_ctrl_setting(); + if (wmt_consys_ic_ops->consys_ic_bus_timeout_config) + wmt_consys_ic_ops->consys_ic_bus_timeout_config(); + if (wmt_consys_ic_ops->consys_ic_hw_reset_bit_set) + wmt_consys_ic_ops->consys_ic_hw_reset_bit_set(DISABLE); + + msleep(20); + + } else { + if (wmt_consys_ic_ops->consys_ic_ahb_clock_ctrl) + wmt_consys_ic_ops->consys_ic_ahb_clock_ctrl(DISABLE); + if (wmt_consys_ic_ops->consys_ic_hw_power_ctrl) + wmt_consys_ic_ops->consys_ic_hw_power_ctrl(DISABLE); + if (co_clock_type) { + if (wmt_consys_ic_ops->consys_ic_clock_buffer_ctrl) + wmt_consys_ic_ops->consys_ic_clock_buffer_ctrl(DISABLE); + } + + if (co_clock_type == 0) { + if (wmt_consys_ic_ops->consys_ic_vcn28_hw_mode_ctrl) + wmt_consys_ic_ops->consys_ic_vcn28_hw_mode_ctrl(DISABLE); + /*turn off VCN28 LDO (with PMIC_WRAP API)" */ + if (wmt_consys_ic_ops->consys_ic_hw_vcn28_ctrl) + wmt_consys_ic_ops->consys_ic_hw_vcn28_ctrl(DISABLE); + } + + if (wmt_consys_ic_ops->consys_ic_set_if_pinmux) + wmt_consys_ic_ops->consys_ic_set_if_pinmux(DISABLE); + + if (wmt_consys_ic_ops->consys_ic_hw_vcn18_ctrl) + wmt_consys_ic_ops->consys_ic_hw_vcn18_ctrl(DISABLE); + } + WMT_PLAT_PR_INFO("CONSYS-HW-REG-CTRL(0x%08x),finish\n", on); + return iRet; +} +/*tag4 wujun api big difference end*/ + +INT32 mtk_wcn_consys_hw_bt_paldo_ctrl(UINT32 enable) +{ + if (wmt_consys_ic_ops->consys_ic_hw_bt_vcn33_ctrl) + wmt_consys_ic_ops->consys_ic_hw_bt_vcn33_ctrl(enable); + return 0; +} + +INT32 mtk_wcn_consys_hw_wifi_paldo_ctrl(UINT32 enable) +{ + if (wmt_consys_ic_ops->consys_ic_hw_wifi_vcn33_ctrl) + wmt_consys_ic_ops->consys_ic_hw_wifi_vcn33_ctrl(enable); + return 0; +} +EXPORT_SYMBOL(mtk_wcn_consys_hw_wifi_paldo_ctrl); + +INT32 mtk_wcn_consys_hw_efuse_paldo_ctrl(UINT32 enable, UINT32 co_clock_type) +{ + if (co_clock_type) { + if (wmt_consys_ic_ops->consys_ic_hw_vcn28_ctrl) + wmt_consys_ic_ops->consys_ic_hw_vcn28_ctrl(enable); + if (enable) + WMT_PLAT_PR_INFO("turn on vcn28 for efuse usage in co-clock mode\n"); + else + WMT_PLAT_PR_INFO("turn off vcn28 for efuse usage in co-clock mode\n"); + } + return 0; +} +EXPORT_SYMBOL(mtk_wcn_consys_hw_efuse_paldo_ctrl); + +INT32 mtk_wcn_consys_hw_vcn28_ctrl(UINT32 enable) +{ + if (wmt_consys_ic_ops->consys_ic_hw_vcn28_ctrl) + wmt_consys_ic_ops->consys_ic_hw_vcn28_ctrl(enable); + if (enable) + WMT_PLAT_PR_INFO("turn on vcn28 for fm/gps usage in co-clock mode\n"); + else + WMT_PLAT_PR_INFO("turn off vcn28 for fm/gps usage in co-clock mode\n"); + return 0; +} + +UINT32 mtk_wcn_consys_soc_chipid(VOID) +{ + if (wmt_consys_ic_ops == NULL) + wmt_consys_ic_ops = mtk_wcn_get_consys_ic_ops(); + + if (wmt_consys_ic_ops && wmt_consys_ic_ops->consys_ic_soc_chipid_get) + return wmt_consys_ic_ops->consys_ic_soc_chipid_get(); + else + return 0; +} + +UINT32 mtk_wcn_consys_get_adie_chipid(VOID) +{ + return g_adie_chipid; +} + +INT32 mtk_wcn_consys_detect_adie_chipid(UINT32 co_clock_type) +{ + INT32 chipid = 0; + + if (osal_lock_sleepable_lock(&g_adie_chipid_lock)) + return 0; + + /* detect a-die only once */ + if (g_adie_chipid) { + osal_unlock_sleepable_lock(&g_adie_chipid_lock); + return g_adie_chipid; + } + + if (wmt_consys_ic_ops == NULL) + wmt_consys_ic_ops = mtk_wcn_get_consys_ic_ops(); + + if (wmt_consys_ic_ops && wmt_consys_ic_ops->consys_ic_adie_chipid_detect) { + WMT_PLAT_PR_INFO("CONSYS A-DIE DETECT start\n"); + chipid = wmt_consys_ic_ops->consys_ic_adie_chipid_detect(); + if (chipid > 0) { + g_adie_chipid = chipid; + WMT_PLAT_PR_INFO("Set a-die chipid = %x\n", chipid); + } else + WMT_PLAT_PR_INFO("Detect a-die chipid = %x failed!\n", chipid); + WMT_PLAT_PR_INFO("CONSYS A-DIE DETECT finish\n"); + } + + osal_unlock_sleepable_lock(&g_adie_chipid_lock); + + return chipid; +} + +struct pinctrl *mtk_wcn_consys_get_pinctrl() +{ + return consys_pinctrl; +} + +INT32 mtk_wcn_consys_hw_gpio_ctrl(UINT32 on) +{ + INT32 iRet = 0; + + WMT_PLAT_PR_DBG("CONSYS-HW-GPIO-CTRL(0x%08x), start\n", on); + + if (on) { + + if (wmt_consys_ic_ops->consys_ic_need_gps) { + if (wmt_consys_ic_ops->consys_ic_need_gps() == MTK_WCN_BOOL_TRUE) { + /*if external modem used,GPS_SYNC still needed to control */ + iRet += wmt_plat_gpio_ctrl(PIN_GPS_SYNC, PIN_STA_INIT); + iRet += wmt_plat_gpio_ctrl(PIN_GPS_LNA, PIN_STA_INIT); + + iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_INIT); + } + } else { + iRet += wmt_plat_gpio_ctrl(PIN_GPS_SYNC, PIN_STA_INIT); + iRet += wmt_plat_gpio_ctrl(PIN_GPS_LNA, PIN_STA_INIT); + + iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_INIT); + } + /* TODO: [FixMe][GeorgeKuo] double check if BGF_INT is implemented ok */ + /* iRet += wmt_plat_gpio_ctrl(PIN_BGF_EINT, PIN_STA_MUX); */ + iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_INIT); + iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); + WMT_PLAT_PR_DBG("CONSYS-HW, BGF IRQ registered and disabled\n"); + + } else { + + /* set bgf eint/all eint to deinit state, namely input low state */ + iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); + iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_DEINIT); + WMT_PLAT_PR_DBG("CONSYS-HW, BGF IRQ unregistered and disabled\n"); + /* iRet += wmt_plat_gpio_ctrl(PIN_BGF_EINT, PIN_STA_DEINIT); */ + if (wmt_consys_ic_ops->consys_ic_need_gps) { + if (wmt_consys_ic_ops->consys_ic_need_gps() == MTK_WCN_BOOL_TRUE) { + /*if external modem used,GPS_SYNC still needed to control */ + iRet += wmt_plat_gpio_ctrl(PIN_GPS_SYNC, PIN_STA_DEINIT); + iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_DEINIT); + /* deinit gps_lna */ + iRet += wmt_plat_gpio_ctrl(PIN_GPS_LNA, PIN_STA_DEINIT); + } + } else { + iRet += wmt_plat_gpio_ctrl(PIN_GPS_SYNC, PIN_STA_DEINIT); + iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_DEINIT); + iRet += wmt_plat_gpio_ctrl(PIN_GPS_LNA, PIN_STA_DEINIT); + } + } + WMT_PLAT_PR_DBG("CONSYS-HW-GPIO-CTRL(0x%08x), finish\n", on); + return iRet; + +} + +INT32 mtk_wcn_consys_hw_pwr_on(UINT32 co_clock_type) +{ + INT32 iRet = 0; + + WMT_PLAT_PR_INFO("CONSYS-HW-PWR-ON, start\n"); + WMT_STEP_DO_ACTIONS_FUNC(STEP_TRIGGER_POINT_POWER_ON_START); + if (!gConEmiPhyBase) { + WMT_PLAT_PR_ERR("EMI base address is invalid, CONNSYS can not be powered on!"); + return -1; + } + iRet += mtk_wcn_consys_hw_reg_ctrl(1, co_clock_type); + iRet += mtk_wcn_consys_hw_gpio_ctrl(1); + mtk_wcn_consys_jtag_set_for_mcu(); + + WMT_PLAT_PR_INFO("CONSYS-HW-PWR-ON, finish(%d)\n", iRet); + return iRet; +} + +INT32 mtk_wcn_consys_hw_pwr_off(UINT32 co_clock_type) +{ + INT32 iRet = 0; + + WMT_PLAT_PR_INFO("CONSYS-HW-PWR-OFF, start\n"); + WMT_STEP_DO_ACTIONS_FUNC(STEP_TRIGGER_POINT_BEFORE_POWER_OFF); + + iRet += mtk_wcn_consys_hw_reg_ctrl(0, co_clock_type); + iRet += mtk_wcn_consys_hw_gpio_ctrl(0); + + WMT_PLAT_PR_INFO("CONSYS-HW-PWR-OFF, finish(%d)\n", iRet); + return iRet; +} + +INT32 mtk_wcn_consys_hw_rst(UINT32 co_clock_type) +{ + INT32 iRet = 0; + + WMT_PLAT_PR_INFO("CONSYS-HW, hw_rst start, eirq should be disabled before this step\n"); + + mtk_consys_set_chip_reset_status(1); + + if (wmt_consys_ic_ops->consys_ic_set_dl_rom_patch_flag) + wmt_consys_ic_ops->consys_ic_set_dl_rom_patch_flag(1); + + /* Dump infra register for debug purpose */ + if (wmt_consys_ic_ops->consys_ic_infra_reg_dump) + wmt_consys_ic_ops->consys_ic_infra_reg_dump(); + + /* write 0x5000_0154.Bit[1] = 1 (pdma_axi_rready_force_high) to prevent pdma block slpprot */ + if (wmt_consys_ic_ops->consys_ic_set_pdma_axi_rready_force_high) + wmt_consys_ic_ops->consys_ic_set_pdma_axi_rready_force_high(1); + + /*1. do whole hw power off flow */ + iRet += mtk_wcn_consys_hw_reg_ctrl(0, co_clock_type); + + /* Write Wi-Fi calibration data back to EMI */ + mtk_wcn_soc_restore_wifi_cal_result(); + + /*2. do whole hw power on flow */ + iRet += mtk_wcn_consys_hw_reg_ctrl(1, co_clock_type); + + /* Make sure pdma_axi_rready_force_high set to 0 after reset */ + if (wmt_consys_ic_ops->consys_ic_set_pdma_axi_rready_force_high) + wmt_consys_ic_ops->consys_ic_set_pdma_axi_rready_force_high(0); + + mtk_consys_set_chip_reset_status(0); + + WMT_PLAT_PR_INFO("CONSYS-HW, hw_rst finish, eirq should be enabled after this step\n"); + return iRet; +} + +INT32 mtk_wcn_consys_hw_state_show(VOID) +{ + return 0; +} + +INT32 mtk_wcn_consys_hw_restore(struct device *device) +{ + if (gConEmiPhyBase) { + if (wmt_consys_ic_ops->consys_ic_emi_mpu_set_region_protection) + wmt_consys_ic_ops->consys_ic_emi_mpu_set_region_protection(); + if (wmt_consys_ic_ops->consys_ic_emi_set_remapping_reg) + wmt_consys_ic_ops->consys_ic_emi_set_remapping_reg(); + if (wmt_consys_ic_ops->consys_ic_emi_coredump_remapping) + wmt_consys_ic_ops->consys_ic_emi_coredump_remapping(&pEmibaseaddr, 1); + } else { + WMT_PLAT_PR_ERR("consys emi memory address gConEmiPhyBase invalid\n"); + } + + return 0; +} + +INT32 mtk_wcn_consys_hw_init(VOID) +{ + INT32 iRet = -1, retry = 0; + + if (wmt_consys_ic_ops == NULL) + wmt_consys_ic_ops = mtk_wcn_get_consys_ic_ops(); + + iRet = platform_driver_register(&mtk_wmt_dev_drv); + if (iRet) + WMT_PLAT_PR_ERR("WMT platform driver registered failed(%d)\n", iRet); + else { + while (atomic_read(&g_probe_called) == 0 && retry < 100) { + osal_sleep_ms(50); + retry++; + WMT_PLAT_PR_INFO("g_probe_called = 0, retry = %d\n", retry); + } + register_syscore_ops(&wmt_dbg_syscore_ops); + } + + return iRet; + +} + +INT32 mtk_wcn_consys_hw_deinit(VOID) +{ + + if (pEmibaseaddr) { + if (wmt_consys_ic_ops->consys_ic_emi_coredump_remapping) + wmt_consys_ic_ops->consys_ic_emi_coredump_remapping(&pEmibaseaddr, 0); + } +#ifdef CONFIG_MTK_HIBERNATION + unregister_swsusp_restore_noirq_func(ID_M_CONNSYS); +#endif + + platform_driver_unregister(&mtk_wmt_dev_drv); + unregister_syscore_ops(&wmt_dbg_syscore_ops); + + if (wmt_consys_ic_ops) + wmt_consys_ic_ops = NULL; + + return 0; +} + +PUINT8 mtk_wcn_consys_emi_virt_addr_get(UINT32 ctrl_state_offset) +{ + UINT8 *p_virtual_addr = NULL; + + if (!pEmibaseaddr) { + WMT_PLAT_PR_ERR("EMI base address is NULL\n"); + return NULL; + } + WMT_PLAT_PR_DBG("ctrl_state_offset(%08x)\n", ctrl_state_offset); + p_virtual_addr = pEmibaseaddr + ctrl_state_offset; + + return p_virtual_addr; +} + +INT32 mtk_wcn_consys_set_dbg_mode(UINT32 flag) +{ + INT32 ret = -1; + PUINT8 vir_addr = NULL; + + vir_addr = mtk_wcn_consys_emi_virt_addr_get(EXP_APMEM_CTRL_CHIP_FW_DBGLOG_MODE); + if (!vir_addr) { + WMT_PLAT_PR_ERR("get vir address fail\n"); + return -2; + } + if (flag) { + ret = 0; + CONSYS_REG_WRITE(vir_addr, 0x1); + } else { + CONSYS_REG_WRITE(vir_addr, 0x0); + } + WMT_PLAT_PR_INFO("fw dbg mode register value(0x%08x)\n", CONSYS_REG_READ(vir_addr)); + return ret; +} + +INT32 mtk_wcn_consys_set_dynamic_dump(PUINT32 str_buf) +{ + PUINT8 vir_addr = NULL; + + vir_addr = mtk_wcn_consys_emi_virt_addr_get(EXP_APMEM_CTRL_CHIP_DYNAMIC_DUMP); + if (!vir_addr) { + WMT_PLAT_PR_ERR("get vir address fail\n"); + return -2; + } + memcpy(vir_addr, str_buf, DYNAMIC_DUMP_GROUP_NUM*8); + WMT_PLAT_PR_INFO("dynamic dump register value(0x%08x)\n", CONSYS_REG_READ(vir_addr)); + return 0; +} + +INT32 mtk_wcn_consys_co_clock_type(VOID) +{ + if (wmt_consys_ic_ops == NULL) + wmt_consys_ic_ops = mtk_wcn_get_consys_ic_ops(); + + if (wmt_consys_ic_ops && wmt_consys_ic_ops->consys_ic_co_clock_type) + return wmt_consys_ic_ops->consys_ic_co_clock_type(); + else + return -1; +} + +P_CONSYS_EMI_ADDR_INFO mtk_wcn_consys_soc_get_emi_phy_add(VOID) +{ + if (wmt_consys_ic_ops->consys_ic_soc_get_emi_phy_add) + return wmt_consys_ic_ops->consys_ic_soc_get_emi_phy_add(); + else + return NULL; +} + +UINT32 mtk_wcn_consys_read_cpupcr(VOID) +{ + if (wmt_consys_ic_ops->consys_ic_read_cpupcr) + return wmt_consys_ic_ops->consys_ic_read_cpupcr(); + else + return 0; +} + +VOID mtk_wcn_force_trigger_assert_debug_pin(VOID) +{ + if (wmt_consys_ic_ops->ic_force_trigger_assert_debug_pin) + wmt_consys_ic_ops->ic_force_trigger_assert_debug_pin(); +} + +INT32 mtk_wcn_consys_read_irq_info_from_dts(PINT32 irq_num, PUINT32 irq_flag) +{ + if (wmt_consys_ic_ops->consys_ic_read_irq_info_from_dts) + return wmt_consys_ic_ops->consys_ic_read_irq_info_from_dts(g_pdev, irq_num, irq_flag); + else + return 0; +} + +VOID mtk_wcn_consys_hang_debug(VOID) +{ + if (wmt_consys_ic_ops && wmt_consys_ic_ops->consys_hang_debug) + wmt_consys_ic_ops->consys_hang_debug(); +} + +UINT32 mtk_consys_get_gps_lna_pin_num(VOID) +{ + return gps_lna_pin_num; +} + +INT32 mtk_wcn_consys_reg_ctrl(UINT32 is_write, enum CONSYS_BASE_ADDRESS_INDEX index, UINT32 offset, + PUINT32 value) +{ + INT32 iRet = -1; + PUINT32 reg_info = NULL; + UINT32 reg_info_size = index * 4 + 4; + struct device_node *node; + PVOID remap_addr = NULL; + + reg_info = osal_malloc(reg_info_size * sizeof(UINT32)); + if (!reg_info) { + WMT_PLAT_PR_ERR("reg_info osal_malloc fail\n"); + goto fail; + } + + node = g_pdev->dev.of_node; + if (node) { + if (of_property_read_u32_array(node, "reg", reg_info, reg_info_size)) { + WMT_PLAT_PR_ERR("get reg from DTS fail!!\n"); + goto fail; + } + } else { + WMT_PLAT_PR_ERR("[%s] can't find CONSYS compatible node\n", __func__); + goto fail; + } + + if (reg_info[index*4 + 3] < offset) { + WMT_PLAT_PR_ERR("Access overflow of address(0x%x), offset(0x%x)!\n", + reg_info[index*4 + 1], reg_info[index*4 + 3]); + goto fail; + } + + remap_addr = ioremap(reg_info[index*4 + 1] + offset, 0x4); + if (remap_addr == NULL) { + WMT_PLAT_PR_ERR("ioremap fail!\n"); + goto fail; + } + + if (is_write) + CONSYS_REG_WRITE(remap_addr, *value); + else + *value = CONSYS_REG_READ(remap_addr); + + if (remap_addr) + iounmap(remap_addr); + + iRet = 0; + +fail: + if (reg_info) + osal_free(reg_info); + return iRet; +} + +/* Who call this? + * - wmt_step + * - stp_dbg.c stp_dbg_poll_cpupcr + * - wmt_core + */ +INT32 mtk_consys_check_reg_readable(VOID) +{ + return mtk_consys_check_reg_readable_by_addr(0); +} + +INT32 mtk_consys_check_reg_readable_by_addr(SIZE_T addr) +{ + INT32 is_host_csr = 0; + + if (wmt_consys_ic_ops->consys_ic_is_host_csr) + is_host_csr = wmt_consys_ic_ops->consys_ic_is_host_csr(addr); + + if (wmt_consys_ic_ops->consys_ic_check_reg_readable && is_host_csr == 0) + return wmt_consys_ic_ops->consys_ic_check_reg_readable(); + else + return 1; +} + +VOID mtk_wcn_consys_clock_fail_dump(VOID) +{ + if (wmt_consys_ic_ops->consys_ic_clock_fail_dump) + wmt_consys_ic_ops->consys_ic_clock_fail_dump(); + WMT_STEP_DO_ACTIONS_FUNC(STEP_TRIGGER_POINT_WHEN_CLOCK_FAIL); +} + +INT32 mtk_consys_is_connsys_reg(UINT32 addr) +{ + if (wmt_consys_ic_ops->consys_ic_is_connsys_reg) + return wmt_consys_ic_ops->consys_ic_is_connsys_reg(addr); + else + return 0; +} + +VOID mtk_consys_set_mcif_mpu_protection(MTK_WCN_BOOL enable) +{ + if (wmt_consys_ic_ops->consys_ic_set_mcif_emi_mpu_protection) + wmt_consys_ic_ops->consys_ic_set_mcif_emi_mpu_protection(enable); +} + +INT32 mtk_consys_is_calibration_backup_restore_support(VOID) +{ + if (wmt_consys_ic_ops->consys_ic_calibration_backup_restore) + return wmt_consys_ic_ops->consys_ic_calibration_backup_restore(); + else + return 0; + +} + +VOID mtk_consys_set_chip_reset_status(INT32 status) +{ + chip_reset_status = status; +} + +INT32 mtk_consys_chip_reset_status(VOID) +{ + return chip_reset_status; +} + +INT32 mtk_consys_is_ant_swap_enable_by_hwid(VOID) +{ + if (wmt_consys_ic_ops->consys_ic_is_ant_swap_enable_by_hwid) + return wmt_consys_ic_ops->consys_ic_is_ant_swap_enable_by_hwid(wifi_ant_swap_gpio_pin_num); + else + return 0; +} + +INT32 mtk_consys_dump_osc_state(P_CONSYS_STATE state) +{ + if (wmt_consys_ic_ops->consys_ic_dump_osc_state) + return wmt_consys_ic_ops->consys_ic_dump_osc_state(state); + + return MTK_WCN_BOOL_FALSE; +} + +VOID mtk_wcn_consys_ic_get_ant_sel_cr_addr(PUINT32 default_invert_cr, PUINT32 default_invert_bit) +{ + if (wmt_consys_ic_ops->consys_ic_get_ant_sel_cr_addr) + wmt_consys_ic_ops->consys_ic_get_ant_sel_cr_addr(default_invert_cr, default_invert_bit); +} + +INT32 mtk_wcn_consys_dump_gating_state(P_CONSYS_STATE state) +{ + if (wmt_consys_ic_ops->consys_ic_dump_gating_state) + return wmt_consys_ic_ops->consys_ic_dump_gating_state(state); + + return MTK_WCN_BOOL_FALSE; +} + +UINT64 mtk_wcn_consys_get_options(VOID) +{ + if (wmt_consys_ic_ops->consys_ic_get_options) + return wmt_consys_ic_ops->consys_ic_get_options(); + + WMT_PLAT_PR_INFO("Please implement consys_ic_get_options!"); + wmt_lib_trigger_assert(WMTDRV_TYPE_WMT, 45); + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_main/platform/wmt_plat_alps.c b/drivers/misc/mediatek/connectivity/common/common_main/platform/wmt_plat_alps.c new file mode 100644 index 0000000000000..2ec5808b5ed75 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/platform/wmt_plat_alps.c @@ -0,0 +1,1851 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-PLAT]" + +#include + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include + +/* ALPS header files */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)) +#ifndef CONFIG_RTC_DRV_MT6397 +#include +#else +#include +#endif +#endif + +#ifdef CONFIG_MTK_MT6306_GPIO_SUPPORT +#include +#endif +/* ALPS and COMBO header files */ +#include +/* MTK_WCN_COMBO header files */ +#include "wmt_plat.h" +#include "wmt_dev.h" +#include "wmt_lib.h" +#include "mtk_wcn_cmb_hw.h" +#include "mtk_wcn_consys_hw.h" +#include "stp_dbg.h" +#include "osal.h" +#include "wmt_gpio.h" +#include "wmt_detect.h" +#include + +#include +#include +#include + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +#if CFG_WMT_PS_SUPPORT +static VOID wmt_plat_bgf_eirq_cb(VOID); +#endif +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_uart_rx_ctrl(ENUM_PIN_STATE state); +#if CFG_WMT_LTE_COEX_HANDLING +static INT32 wmt_plat_tdm_req_ctrl(ENUM_PIN_STATE state); +#endif +static INT32 wmt_plat_dump_pin_conf(VOID); + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +INT32 gWmtMergeIfSupport; +UINT32 gCoClockFlag; +BGF_IRQ_BALANCE g_bgf_irq_lock; +INT32 wmtPlatLogLvl = WMT_PLAT_LOG_INFO; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +static ENUM_STP_TX_IF_TYPE gCommIfType = STP_MAX_IF_TX; +static OSAL_SLEEPABLE_LOCK gOsSLock; +static OSAL_WAKE_LOCK wmt_wake_lock; + +irq_cb wmt_plat_bgf_irq_cb; +device_audio_if_cb wmt_plat_audio_if_cb; +func_ctrl_cb wmt_plat_func_ctrl_cb; +thermal_query_ctrl_cb wmt_plat_thermal_query_ctrl_cb; +trigger_assert_cb wmt_plat_trigger_assert_cb; +deep_idle_ctrl_cb wmt_plat_deep_idle_ctrl_cb; + +static const 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, + [PIN_UART_RX] = wmt_plat_uart_rx_ctrl, +#if CFG_WMT_LTE_COEX_HANDLING + [PIN_TDM_REQ] = wmt_plat_tdm_req_ctrl, +#endif +}; + +/******************************************************************************* +* 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(enum CMB_STUB_AIF_X state, enum CMB_STUB_AIF_CTRL ctrl) +{ + INT32 iRet = 0; + UINT32 mergeIfSupport = 0; + + /* input sanity check */ + if ((state >= CMB_STUB_AIF_MAX) || (ctrl >= CMB_STUB_AIF_CTRL_MAX)) + return -1; + + iRet = 0; + + /* set host side first */ + switch (state) { + case CMB_STUB_AIF_0: + /* BT_PCM_OFF & FM line in/out */ + iRet += wmt_plat_gpio_ctrl(PIN_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_I2S_GRP, PIN_STA_DEINIT); + iRet += wmt_plat_gpio_ctrl(PIN_PCM_GRP, PIN_STA_INIT); + 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; + } + + if (wmt_plat_merge_if_flag_get() != 0) { +#if (MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT) + WMT_DBG_FUNC("[MT6628] no need to ctrl combo chip side GPIO\n"); +#else + mergeIfSupport = 1; +#endif + } else + mergeIfSupport = 1; + + if (mergeIfSupport != 0) { + if (ctrl == CMB_STUB_AIF_CTRL_EN) { + WMT_INFO_FUNC("call chip aif setting\n"); + /* need to control chip side GPIO */ + if (wmt_plat_audio_if_cb != NULL) + iRet += (*wmt_plat_audio_if_cb)(state, 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; +} + +static VOID wmt_plat_func_ctrl(UINT32 type, UINT32 on) +{ + if (wmt_plat_func_ctrl_cb) + (*wmt_plat_func_ctrl_cb)(on, type); +} + +static long wmt_plat_thermal_ctrl(VOID) +{ + long temp = 0; + + if (wmt_plat_thermal_query_ctrl_cb) + temp = (*wmt_plat_thermal_query_ctrl_cb)(); + + return temp; +} + +static INT32 wmt_plat_assert_ctrl(VOID) +{ + INT32 ret = 0; + + if (wmt_plat_trigger_assert_cb) + ret = (*wmt_plat_trigger_assert_cb)(WMTDRV_TYPE_WMT, 45); + + return ret; +} + +static INT32 wmt_plat_deep_idle_ctrl(UINT32 dpilde_ctrl) +{ + INT32 iRet = -1; + + if (wmt_plat_deep_idle_ctrl_cb) + iRet = (*wmt_plat_deep_idle_ctrl_cb)(dpilde_ctrl); + + return iRet; +} + +static VOID wmt_plat_clock_fail_dump(VOID) +{ + mtk_wcn_consys_clock_fail_dump(); +} + +#if CFG_WMT_PS_SUPPORT +static VOID wmt_plat_bgf_eirq_cb(VOID) +{ +/* #error "need to disable EINT here" */ + /* wmt_lib_ps_irq_cb(); */ + if (wmt_plat_bgf_irq_cb != NULL) + (*(wmt_plat_bgf_irq_cb))(); + else + WMT_PLAT_PR_WARN("WMT-PLAT: wmt_plat_bgf_irq_cb not registered\n"); +} +#endif + +irqreturn_t wmt_plat_bgf_irq_isr(INT32 irq, PVOID arg) +{ +#if CFG_WMT_PS_SUPPORT + wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); + wmt_plat_bgf_eirq_cb(); +#else + WMT_PLAT_PR_INFO("skip irq handing because psm is disable"); +#endif + + return IRQ_HANDLED; +} + +VOID wmt_plat_irq_cb_reg(irq_cb bgf_irq_cb) +{ + wmt_plat_bgf_irq_cb = bgf_irq_cb; +} + +VOID wmt_plat_aif_cb_reg(device_audio_if_cb aif_ctrl_cb) +{ + wmt_plat_audio_if_cb = aif_ctrl_cb; +} + +VOID wmt_plat_func_ctrl_cb_reg(func_ctrl_cb subsys_func_ctrl) +{ + wmt_plat_func_ctrl_cb = subsys_func_ctrl; +} + +VOID wmt_plat_thermal_ctrl_cb_reg(thermal_query_ctrl_cb thermal_query_ctrl) +{ + wmt_plat_thermal_query_ctrl_cb = thermal_query_ctrl; +} + +VOID wmt_plat_trigger_assert_cb_reg(trigger_assert_cb trigger_assert) +{ + wmt_plat_trigger_assert_cb = trigger_assert; +} + +VOID wmt_plat_deep_idle_ctrl_cb_reg(deep_idle_ctrl_cb deep_idle_ctrl) +{ + wmt_plat_deep_idle_ctrl_cb = deep_idle_ctrl; +} + +UINT32 wmt_plat_soc_co_clock_flag_get(VOID) +{ + return gCoClockFlag; +} + +static UINT32 wmt_plat_soc_co_clock_flag_set(UINT32 flag) +{ + gCoClockFlag = flag; + return 0; +} + +INT32 wmt_plat_init(P_PWR_SEQ_TIME pPwrSeqTime, UINT32 co_clock_type) +{ + struct _CMB_STUB_CB_ stub_cb; + INT32 iret = -1; + + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) { + iret = mtk_wcn_consys_co_clock_type(); + if ((co_clock_type == 0) && (iret >= 0)) + co_clock_type = iret; + wmt_plat_soc_co_clock_flag_set(co_clock_type); + } + + stub_cb.aif_ctrl_cb = wmt_plat_audio_ctrl; + stub_cb.func_ctrl_cb = wmt_plat_func_ctrl; + stub_cb.thermal_query_cb = wmt_plat_thermal_ctrl; + stub_cb.trigger_assert_cb = wmt_plat_assert_ctrl; + stub_cb.deep_idle_ctrl_cb = wmt_plat_deep_idle_ctrl; + stub_cb.wmt_do_reset_cb = NULL; + stub_cb.clock_fail_dump_cb = wmt_plat_clock_fail_dump; + stub_cb.size = sizeof(stub_cb); + + /* register to cmb_stub */ + iret = mtk_wcn_cmb_stub_reg(&stub_cb); + + /*init wmt function ctrl wakelock if wake lock is supported by host platform */ + osal_strcpy(wmt_wake_lock.name, "wmtFuncCtrl"); + wmt_wake_lock.init_flag = 0; + osal_wake_lock_init(&wmt_wake_lock); + osal_sleepable_lock_init(&gOsSLock); + + /* init hw */ + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) + iret += mtk_wcn_consys_hw_init(); + else + iret += mtk_wcn_cmb_hw_init(pPwrSeqTime); + + spin_lock_init(&g_bgf_irq_lock.lock); + + mtk_wcn_consys_detect_adie_chipid(co_clock_type); + + WMT_DBG_FUNC("WMT-PLAT: ALPS platform init (%d)\n", iret); + + return 0; +} + +INT32 wmt_plat_deinit(VOID) +{ + INT32 iret = 0; + + /* 1. de-init hw */ + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) + iret += mtk_wcn_consys_hw_deinit(); + else + iret = mtk_wcn_cmb_hw_deinit(); + /* 2. unreg to cmb_stub */ + iret += mtk_wcn_cmb_stub_unreg(); + /*3. wmt wakelock deinit */ + osal_wake_lock_deinit(&wmt_wake_lock); + osal_sleepable_lock_deinit(&gOsSLock); + WMT_DBG_FUNC("destroy wmt_wake_lock\n"); + 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) +{ + return board_sdio_ctrl(sdioPortType, (on == FUNC_OFF) ? 0 : 1); +} + +INT32 wmt_plat_irq_ctrl(ENUM_FUNC_STATE state) +{ + return -1; +} + +static INT32 wmt_plat_dump_pin_conf(VOID) +{ + WMT_DBG_FUNC("[WMT-PLAT]=>dump wmt pin configuration start<=\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_LDO_EN_PIN].gpio_num != DEFAULT_PIN_ID) { + WMT_DBG_FUNC("LDO(GPIO%d)\n", + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_LDO_EN_PIN].gpio_num); + } else + WMT_DBG_FUNC("LDO(not defined)\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num != DEFAULT_PIN_ID) { + WMT_DBG_FUNC("PMU(GPIO%d)\n", + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num); + } else + WMT_DBG_FUNC("PMU(not defined)\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMUV28_EN_PIN].gpio_num != DEFAULT_PIN_ID) { + WMT_DBG_FUNC("PMUV28(GPIO%d)\n", + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMUV28_EN_PIN].gpio_num); + } else + WMT_DBG_FUNC("PMUV28(not defined)\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num != DEFAULT_PIN_ID) { + WMT_DBG_FUNC("RST(GPIO%d)\n", + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num); + } else + WMT_DBG_FUNC("RST(not defined)\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_BGF_EINT_PIN].gpio_num != DEFAULT_PIN_ID) { + WMT_DBG_FUNC("BGF_EINT(GPIO%d)\n", + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_BGF_EINT_PIN].gpio_num); + } else + WMT_DBG_FUNC("BGF_EINT(not defined)\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_BGF_EINT_PIN].gpio_num != DEFAULT_PIN_ID) { + WMT_DBG_FUNC("BGF_EINT_NUM(%d)\n", + gpio_to_irq(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_BGF_EINT_PIN].gpio_num)); + } else + WMT_DBG_FUNC("BGF_EINT_NUM(not defined)\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_num != DEFAULT_PIN_ID) { + WMT_DBG_FUNC("WIFI_EINT(GPIO%d)\n", + gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_num); + } else + WMT_DBG_FUNC("WIFI_EINT(not defined)\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_num != DEFAULT_PIN_ID) { + WMT_DBG_FUNC("WIFI_EINT_NUM(%d)\n", + gpio_to_irq(gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_num)); + } else + WMT_DBG_FUNC("WIFI_EINT_NUM(not defined)\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_URXD_PIN].gpio_num != DEFAULT_PIN_ID) { + WMT_DBG_FUNC("UART_RX(GPIO%d)\n", + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_URXD_PIN].gpio_num); + } else + WMT_DBG_FUNC("UART_RX(not defined)\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_UTXD_PIN].gpio_num != DEFAULT_PIN_ID) { + WMT_DBG_FUNC("UART_TX(GPIO%d)\n", + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_UTXD_PIN].gpio_num); + } else + WMT_DBG_FUNC("UART_TX(not defined)\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAICLK_PIN].gpio_num != DEFAULT_PIN_ID) { + WMT_DBG_FUNC("DAICLK(GPIO%d)\n", + gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAICLK_PIN].gpio_num); + } else + WMT_DBG_FUNC("DAICLK(not defined)\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAIPCMOUT_PIN].gpio_num != DEFAULT_PIN_ID) { + WMT_DBG_FUNC("PCMOUT(GPIO%d)\n", + gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAIPCMOUT_PIN].gpio_num); + } else + WMT_DBG_FUNC("PCMOUT(not defined)\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAIPCMIN_PIN].gpio_num != DEFAULT_PIN_ID) { + WMT_DBG_FUNC("PCMIN(GPIO%d)\n", + gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAIPCMIN_PIN].gpio_num); + } else + WMT_DBG_FUNC("PCMIN(not defined)\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAISYNC_PIN].gpio_num != DEFAULT_PIN_ID) { + WMT_DBG_FUNC("PCMSYNC(GPIO%d)\n", + gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAISYNC_PIN].gpio_num); + } else + WMT_DBG_FUNC("PCMSYNC(not defined)\n"); +#if defined(FM_DIGITAL_INPUT) || defined(FM_DIGITAL_OUTPUT) + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_I2S_CK_PIN].gpio_num != DEFAULT_PIN_ID) { + WMT_DBG_FUNC("I2S_CK(GPIO%d)\n", + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_I2S_CK_PIN].gpio_num); + } else + WMT_DBG_FUNC("I2S_CK(not defined)\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_I2S_WS_PIN].gpio_num != DEFAULT_PIN_ID) { + WMT_DBG_FUNC("I2S_WS(GPIO%d)\n", + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_I2S_WS_PIN].gpio_num); + } else + WMT_DBG_FUNC("I2S_WS(not defined)\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_I2S_DAT_PIN].gpio_num != DEFAULT_PIN_ID) { + WMT_DBG_FUNC("I2S_DAT(GPIO%d)\n", + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_I2S_DAT_PIN].gpio_num); + } else + WMT_DBG_FUNC("I2S_DAT(not defined)\n"); + +#else /* FM_ANALOG_INPUT || FM_ANALOG_OUTPUT */ + WMT_DBG_FUNC("FM digital mode is not set, no need for I2S GPIOs\n"); +#endif + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_GPS_SYNC_PIN].gpio_num != DEFAULT_PIN_ID) { + WMT_DBG_FUNC("GPS_SYNC(GPIO%d)\n", + gpio_ctrl_info.gpio_ctrl_state[GPIO_GPS_SYNC_PIN].gpio_num); + } else + WMT_DBG_FUNC("GPS_SYNC(not defined)\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_GPS_LNA_PIN].gpio_num != DEFAULT_PIN_ID) { + WMT_DBG_FUNC("GPS_LNA(GPIO%d)\n", + gpio_ctrl_info.gpio_ctrl_state[GPIO_GPS_LNA_PIN].gpio_num); + } else + WMT_DBG_FUNC("GPS_LNA(not defined)\n"); + + WMT_DBG_FUNC("[WMT-PLAT]=>dump wmt pin configuration emds<=\n"); + + return 0; +} + +INT32 wmt_plat_pwr_ctrl(ENUM_FUNC_STATE state) +{ + INT32 ret = -1; + + switch (state) { + case FUNC_ON: + /* TODO:[ChangeFeature][George] always output this or by request throuth /proc or sysfs? */ + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) + ret = mtk_wcn_consys_hw_pwr_on(gCoClockFlag); + else { + wmt_plat_dump_pin_conf(); + ret = mtk_wcn_cmb_hw_pwr_on(); + } + break; + + case FUNC_OFF: + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) + ret = mtk_wcn_consys_hw_pwr_off(gCoClockFlag); + else + ret = mtk_wcn_cmb_hw_pwr_off(); + break; + + case FUNC_RST: + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) + ret = mtk_wcn_consys_hw_rst(gCoClockFlag); + else + ret = mtk_wcn_cmb_hw_rst(); + break; + case FUNC_STAT: + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) + ret = mtk_wcn_consys_hw_state_show(); + else + ret = mtk_wcn_cmb_hw_state_show(); + 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; + static UINT32 bgf_irq_num = -1; + static UINT32 bgf_irq_flag; + + /* TODO: [ChangeFeature][GeorgeKuo]: use another function to handle this, as done in gpio_ctrls */ + + if ((state != PIN_STA_INIT) && (state != PIN_STA_DEINIT) && (state != PIN_STA_EINT_EN) + && (state != PIN_STA_EINT_DIS)) { + WMT_WARN_FUNC("WMT-PLAT:invalid PIN_STATE(%d) in eirq_ctrl for PIN(%d)\n", state, id); + return -1; + } + + iret = -2; + switch (id) { + case PIN_BGF_EINT: + if (state == PIN_STA_INIT) { + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) { +#ifdef CONFIG_OF + iret = mtk_wcn_consys_read_irq_info_from_dts(&bgf_irq_num, &bgf_irq_flag); + if (iret) + return iret; +#else + bgf_irq_num = MT_CONN2AP_BTIF_WAKEUP_IRQ_ID; + bgf_irq_flag = IRQF_TRIGGER_LOW; +#endif + iret = request_irq(bgf_irq_num, wmt_plat_bgf_irq_isr, bgf_irq_flag, + "BTIF_WAKEUP_IRQ", NULL); + if (iret) { + WMT_PLAT_PR_ERR("request_irq fail,irq_no(%d),iret(%d)\n", + bgf_irq_num, iret); + return iret; + } else { + iret = enable_irq_wake(bgf_irq_num); + if (iret) + WMT_PLAT_PR_ERR("enable irq wake fail,irq_no(%d),iret(%d)\n", + bgf_irq_num, iret); + iret = 0; + } + } else { + struct device_node *node; + INT32 ret = -EINVAL; + + node = of_find_compatible_node(NULL, NULL, "mediatek,connectivity-combo"); + if (node) { + /*BGF-eint name maybe wrong*/ + bgf_irq_num = irq_of_parse_and_map(node, 1); + ret = request_irq(bgf_irq_num, wmt_plat_bgf_irq_isr, + IRQF_TRIGGER_LOW, "BGF-eint", NULL); + if (ret) + WMT_ERR_FUNC("BGF EINT IRQ LINE NOT AVAILABLE!!\n"); + else + WMT_INFO_FUNC("BGF EINT request_irq success!!\n"); + } else + WMT_ERR_FUNC("[%s] can't find BGF eint compatible node\n", + __func__); + } + g_bgf_irq_lock.counter = 1; + } else if (state == PIN_STA_EINT_EN) { + spin_lock_irqsave(&g_bgf_irq_lock.lock, g_bgf_irq_lock.flags); + if (g_bgf_irq_lock.counter) { + WMT_PLAT_PR_DBG("BGF INT has been enabled,counter(%d)\n", + g_bgf_irq_lock.counter); + } else { + enable_irq(bgf_irq_num); + g_bgf_irq_lock.counter++; + WMT_DBG_FUNC("WMT-PLAT:BGFInt (en)\n"); + } + spin_unlock_irqrestore(&g_bgf_irq_lock.lock, g_bgf_irq_lock.flags); + } else if (state == PIN_STA_EINT_DIS) { + spin_lock_irqsave(&g_bgf_irq_lock.lock, g_bgf_irq_lock.flags); + if (!g_bgf_irq_lock.counter) { + WMT_PLAT_PR_DBG("BGF INT has been disabled,counter(%d)\n", + g_bgf_irq_lock.counter); + } else { + disable_irq_nosync(bgf_irq_num); + g_bgf_irq_lock.counter--; + WMT_DBG_FUNC("WMT-PLAT:BGFInt (dis)\n"); + } + spin_unlock_irqrestore(&g_bgf_irq_lock.lock, g_bgf_irq_lock.flags); + } else { + free_irq(bgf_irq_num, NULL); + WMT_DBG_FUNC("WMT-PLAT:BGFInt (free)\n"); + /* de-init: nothing to do in ALPS, such as un-registration... */ + } + + iret = 0; + break; + case PIN_ALL_EINT: + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_ALL_EINT_PIN].gpio_num != DEFAULT_PIN_ID) { + if (state == PIN_STA_INIT) { + disable_irq_nosync(gpio_to_irq(gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_ALL_EINT_PIN].gpio_num)); + WMT_DBG_FUNC("WMT-PLAT:ALLInt (INIT but not used yet)\n"); + } else if (state == PIN_STA_EINT_EN) { + enable_irq(gpio_to_irq(gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_ALL_EINT_PIN].gpio_num)); + WMT_DBG_FUNC("WMT-PLAT:ALLInt (EN but not used yet)\n"); + } else if (state == PIN_STA_EINT_DIS) { + disable_irq_nosync(gpio_to_irq(gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_ALL_EINT_PIN].gpio_num)); + WMT_DBG_FUNC("WMT-PLAT:ALLInt (DIS but not used yet)\n"); + } else { + disable_irq_nosync(gpio_to_irq(gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_ALL_EINT_PIN].gpio_num)); + 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:ALL EINT not defined\n"); + + iret = 0; + break; + + default: + WMT_WARN_FUNC("WMT-PLAT:unsupported EIRQ(PIN_ID:%d) in eirq_ctrl\n", id); + iret = -1; + break; + } + + return iret; +} + +INT32 wmt_plat_gpio_ctrl(ENUM_PIN_ID id, ENUM_PIN_STATE state) +{ + INT32 iret = -1; + + if ((id >= 0) && (id < PIN_ID_MAX) && (state < PIN_STA_MAX)) { + /* TODO: [FixMe][GeorgeKuo] do sanity check to const function table when init and skip checking here */ + if (gfp_set_pin_table[id]) + iret = (*(gfp_set_pin_table[id]))(state); /* .handler */ + else { + WMT_WARN_FUNC("WMT-PLAT: null fp for gpio_ctrl(%d)\n", id); + iret = -2; + } + } + + return iret; +} + +static INT32 wmt_plat_ldo_ctrl(ENUM_PIN_STATE state) +{ + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_LDO_EN_PIN].gpio_num == DEFAULT_PIN_ID) { + WMT_DBG_FUNC("WMT-PLAT:LDO is not used\n"); + return 0; + } + + switch (state) { + case PIN_STA_INIT: + /*set to gpio output low, disable pull */ + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_LDO_EN_PIN].gpio_state[GPIO_PULL_DIS]); + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_LDO_EN_PIN].gpio_num, 0); + WMT_DBG_FUNC("WMT-PLAT:LDO init (out 0)\n"); + break; + case PIN_STA_OUT_H: + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_LDO_EN_PIN].gpio_num, 1); + WMT_DBG_FUNC("WMT-PLAT:LDO (out 1)\n"); + break; + case PIN_STA_OUT_L: + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_LDO_EN_PIN].gpio_num, 0); + 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 */ + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_LDO_EN_PIN].gpio_state[GPIO_IN_PULLDOWN]); + 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; +} + +static INT32 wmt_plat_pmu_ctrl(ENUM_PIN_STATE state) +{ + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num == DEFAULT_PIN_ID) { + WMT_ERR_FUNC("WMT-PLAT:PMU not define\n"); + return -1; + } + + switch (state) { + case PIN_STA_INIT: + /*set to gpio output low, disable pull */ + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_state[GPIO_PULL_DIS]); + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num, 0); + WMT_DBG_FUNC("WMT-PLAT:PMU init (out %d)\n", + gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num)); + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMUV28_EN_PIN].gpio_num != DEFAULT_PIN_ID) { + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_PMUV28_EN_PIN].gpio_state[GPIO_PULL_DIS]); + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMUV28_EN_PIN].gpio_num, + 0); + } + WMT_DBG_FUNC("WMT-PLAT:PMU init (out 0)\n"); + break; + + case PIN_STA_OUT_H: + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num, 1); + WMT_DBG_FUNC("WMT-PLAT:PMU (out 1): %d\n", + gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num)); + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMUV28_EN_PIN].gpio_num != DEFAULT_PIN_ID) + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMUV28_EN_PIN].gpio_num, + 1); + WMT_DBG_FUNC("WMT-PLAT:PMU (out 1)\n"); + break; + + case PIN_STA_OUT_L: + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num, 0); + WMT_DBG_FUNC("WMT-PLAT:PMU (out 0): %d\n", + gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num)); + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMUV28_EN_PIN].gpio_num != DEFAULT_PIN_ID) + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMUV28_EN_PIN].gpio_num, + 0); + WMT_DBG_FUNC("WMT-PLAT:PMU (out 0)\n"); + break; + + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + /*set to gpio input low, pull down enable */ + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_state[GPIO_IN_PULLDOWN]); + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMUV28_EN_PIN].gpio_num != DEFAULT_PIN_ID) + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_PMUV28_EN_PIN].gpio_state[GPIO_IN_PULLDOWN]); + WMT_DBG_FUNC("WMT-PLAT:PMU deinit (in pd)\n"); + break; + case PIN_STA_SHOW: + WMT_INFO_FUNC("WMT-PLAT:PMU PIN_STA_SHOW start\n"); + WMT_INFO_FUNC("WMT-PLAT:PMU out(%d)\n", + gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMUV28_EN_PIN].gpio_num)); + WMT_INFO_FUNC("WMT-PLAT:PMU PIN_STA_SHOW end\n"); + break; + default: + WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on PMU\n", state); + break; + } + + return 0; +} + +static INT32 wmt_plat_rtc_ctrl(ENUM_PIN_STATE state) +{ + switch (state) { + case PIN_STA_INIT: +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) + rtc_gpio_enable_32k(RTC_GPIO_USER_GPS); + WMT_DBG_FUNC("WMT-PLAT:RTC init\n"); +#endif + break; + case PIN_STA_SHOW: + WMT_INFO_FUNC("WMT-PLAT:RTC PIN_STA_SHOW start\n"); + /* WMT_INFO_FUNC("WMT-PLAT:RTC Status(%d)\n", rtc_gpio_32k_status()); */ + WMT_INFO_FUNC("WMT-PLAT:RTC PIN_STA_SHOW end\n"); + break; + default: + WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on RTC\n", state); + break; + } + + return 0; +} + +static INT32 wmt_plat_rst_ctrl(ENUM_PIN_STATE state) +{ + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num == DEFAULT_PIN_ID) { + WMT_ERR_FUNC("WMT-PLAT:RST not define\n"); + return -1; + } + + switch (state) { + case PIN_STA_INIT: + /*set to gpio output low, disable pull */ + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_state[GPIO_PULL_DIS]); + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num, 0); + WMT_DBG_FUNC("WMT-PLAT:RST init (out 0)\n"); + break; + + case PIN_STA_OUT_H: + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num, 1); + WMT_DBG_FUNC("WMT-PLAT:RST (out 1): %d\n", + gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num)); + break; + + case PIN_STA_OUT_L: + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num, 0); + WMT_DBG_FUNC("WMT-PLAT:RST (out 0): %d\n", + gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num)); + break; + + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + /*set to gpio input low, pull down enable */ + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_state[GPIO_IN_PULLDOWN]); + WMT_DBG_FUNC("WMT-PLAT:RST deinit (in pd)\n"); + break; + case PIN_STA_SHOW: + WMT_INFO_FUNC("WMT-PLAT:RST PIN_STA_SHOW start\n"); + WMT_INFO_FUNC("WMT-PLAT:RST out(%d)\n", + gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num)); + WMT_INFO_FUNC("WMT-PLAT:RST PIN_STA_SHOW end\n"); + break; + + default: + WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on RST\n", state); + break; + } + + return 0; +} + +static INT32 wmt_plat_bgf_eint_ctrl(ENUM_PIN_STATE state) +{ + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_BGF_EINT_PIN].gpio_num == DEFAULT_PIN_ID) { + WMT_INFO_FUNC("WMT-PLAT:BGF EINT not defined\n"); + return 0; + } + + switch (state) { + case PIN_STA_INIT: + /*set to gpio input low, pull down enable */ + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_BGF_EINT_PIN].gpio_state[GPIO_IN_PULLDOWN]); + WMT_DBG_FUNC("WMT-PLAT:BGFInt init(in pd)\n"); + break; + case PIN_STA_MUX: + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_BGF_EINT_PIN].gpio_state[GPIO_IN_PULLUP]); + WMT_DBG_FUNC("WMT-PLAT:BGFInt mux (eint)\n"); + break; + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + /*set to gpio input low, pull down enable */ + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_BGF_EINT_PIN].gpio_state[GPIO_IN_PULLDOWN]); + 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; +} + + +static INT32 wmt_plat_wifi_eint_ctrl(ENUM_PIN_STATE state) +{ +#if 0 /*def GPIO_WIFI_EINT_PIN */ + switch (state) { + case PIN_STA_INIT: + mt_set_gpio_pull_enable(GPIO_WIFI_EINT_PIN, GPIO_PULL_DISABLE); + mt_set_gpio_dir(GPIO_WIFI_EINT_PIN, GPIO_DIR_OUT); + mt_set_gpio_mode(GPIO_WIFI_EINT_PIN, GPIO_MODE_GPIO); + mt_set_gpio_out(GPIO_WIFI_EINT_PIN, GPIO_OUT_ONE); + break; + case PIN_STA_MUX: + mt_set_gpio_mode(GPIO_WIFI_EINT_PIN, GPIO_WIFI_EINT_PIN_M_GPIO); + mt_set_gpio_pull_enable(GPIO_WIFI_EINT_PIN, GPIO_PULL_ENABLE); + mt_set_gpio_pull_select(GPIO_WIFI_EINT_PIN, GPIO_PULL_UP); + mt_set_gpio_mode(GPIO_WIFI_EINT_PIN, GPIO_WIFI_EINT_PIN_M_EINT); + + break; + case PIN_STA_EINT_EN: + mt_eint_unmask(CUST_EINT_WIFI_NUM); + break; + case PIN_STA_EINT_DIS: + mt_eint_mask(CUST_EINT_WIFI_NUM); + break; + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + /*set to gpio input low, pull down enable */ + mt_set_gpio_mode(GPIO_WIFI_EINT_PIN, GPIO_COMBO_BGF_EINT_PIN_M_GPIO); + mt_set_gpio_dir(GPIO_WIFI_EINT_PIN, GPIO_DIR_IN); + mt_set_gpio_pull_select(GPIO_WIFI_EINT_PIN, GPIO_PULL_DOWN); + mt_set_gpio_pull_enable(GPIO_WIFI_EINT_PIN, GPIO_PULL_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; +} + + +static INT32 wmt_plat_all_eint_ctrl(ENUM_PIN_STATE state) +{ + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_ALL_EINT_PIN].gpio_num == DEFAULT_PIN_ID) { + WMT_DBG_FUNC("WMT-PLAT:ALL EINT not defined\n"); + return 0; + } + + switch (state) { + case PIN_STA_INIT: + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_ALL_EINT_PIN].gpio_state[GPIO_IN_PULLDOWN]); + WMT_DBG_FUNC("WMT-PLAT:ALLInt init(in pd)\n"); + break; + case PIN_STA_MUX: + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_ALL_EINT_PIN].gpio_state[GPIO_IN_PULLUP]); + break; + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + /*set to gpio input low, pull down enable */ + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_ALL_EINT_PIN].gpio_state[GPIO_IN_PULLDOWN]); + break; + default: + WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on ALL EINT\n", state); + break; + } + + return 0; +} + +static INT32 wmt_plat_uart_ctrl(ENUM_PIN_STATE state) +{ + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_UTXD_PIN].gpio_num == DEFAULT_PIN_ID) { + WMT_DBG_FUNC("WMT-PLAT:UART TX not defined\n"); + return 0; + } + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_URXD_PIN].gpio_num == DEFAULT_PIN_ID) { + WMT_DBG_FUNC("WMT-PLAT:UART RX not defined\n"); + return 0; + } + + switch (state) { + case PIN_STA_MUX: + case PIN_STA_INIT: + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_URXD_PIN].gpio_state[GPIO_PULL_DIS]); + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_UTXD_PIN].gpio_state[GPIO_PULL_DIS]); + WMT_DBG_FUNC("WMT-PLAT:UART init (mode_01, uart)\n"); + break; + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_URXD_PIN].gpio_num, 0); + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_UTXD_PIN].gpio_num, 0); + WMT_DBG_FUNC("WMT-PLAT:UART deinit (out 0)\n"); + break; + case PIN_STA_IN_PU: + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_URXD_PIN].gpio_state[GPIO_IN_PULLUP]); + break; + default: + WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on UART Group\n", state); + break; + } + + return 0; +} + +static INT32 wmt_plat_pcm_ctrl(ENUM_PIN_STATE state) +{ + UINT32 normalPCMFlag = 0; + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAICLK_PIN].gpio_num == DEFAULT_PIN_ID) { + WMT_INFO_FUNC("WMT-PLAT:PCM DAICLK not defined\n"); + return 0; + } + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAIPCMOUT_PIN].gpio_num == DEFAULT_PIN_ID) { + WMT_INFO_FUNC("WMT-PLAT:PCM DAIPCMOUT not defined\n"); + return 0; + } + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAIPCMIN_PIN].gpio_num == DEFAULT_PIN_ID) { + WMT_INFO_FUNC("WMT-PLAT:PCM DAIPCMIN not defined\n"); + return 0; + } + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAISYNC_PIN].gpio_num == DEFAULT_PIN_ID) { + WMT_INFO_FUNC("WMT-PLAT:PCM DAISYNC not defined\n"); + return 0; + } + /*check if combo chip support merge if or not */ + if (wmt_plat_merge_if_flag_get() != 0) { +#if (MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT) + /* Hardware support Merge IF function */ + WMT_DBG_FUNC("WMT-PLAT:set to Merge PCM function\n"); + /*merge PCM function define */ + switch (state) { + case PIN_STA_MUX: + case PIN_STA_INIT: + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_PCM_DAICLK_PIN].gpio_state[GPIO_PULL_DIS]); + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_PCM_DAIPCMOUT_PIN].gpio_state[GPIO_PULL_DIS]); + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_PCM_DAIPCMIN_PIN].gpio_state[GPIO_PULL_DIS]); + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_PCM_DAISYNC_PIN].gpio_state[GPIO_PULL_DIS]); + WMT_DBG_FUNC("WMT-PLAT:PCM init (pcm)\n"); + break; + + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAICLK_PIN].gpio_state[GPIO_PULL_DIS]); + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_PCM_DAIPCMOUT_PIN].gpio_state[GPIO_PULL_DIS]); + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_PCM_DAIPCMIN_PIN].gpio_state[GPIO_PULL_DIS]); + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_PCM_DAISYNC_PIN].gpio_state[GPIO_PULL_DIS]); + 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; + } + +#else + /* Hardware does not support Merge IF function */ + normalPCMFlag = 1; + WMT_DBG_FUNC("WMT-PLAT:set to normal PCM function\n"); +#endif + + } else { + normalPCMFlag = 1; + } + + if (normalPCMFlag != 0) { + /*normal PCM function define */ + switch (state) { + case PIN_STA_MUX: + case PIN_STA_INIT: + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAICLK_PIN].gpio_state[GPIO_PULL_DIS]); + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_PCM_DAIPCMOUT_PIN].gpio_state[GPIO_PULL_DIS]); + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_PCM_DAIPCMIN_PIN].gpio_state[GPIO_PULL_DIS]); + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_PCM_DAISYNC_PIN].gpio_state[GPIO_PULL_DIS]); + WMT_DBG_FUNC("WMT-PLAT:MT6589 PCM init (pcm)\n"); + break; + + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAICLK_PIN].gpio_state[GPIO_PULL_DIS]); + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_PCM_DAIPCMOUT_PIN].gpio_state[GPIO_PULL_DIS]); + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_PCM_DAIPCMIN_PIN].gpio_state[GPIO_PULL_DIS]); + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_PCM_DAISYNC_PIN].gpio_state[GPIO_PULL_DIS]); + WMT_DBG_FUNC("WMT-PLAT:MT6589 PCM deinit (out 0)\n"); + break; + + default: + WMT_WARN_FUNC("WMT-PLAT:MT6589 Warnning, invalid state(%d) on PCM Group\n", + state); + break; + } + } + + return 0; +} + +static INT32 wmt_plat_cmb_i2s_ctrl(ENUM_PIN_STATE state) +{ + UINT32 normalI2SFlag = 0; + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_I2S_CK_PIN].gpio_num == DEFAULT_PIN_ID) { + WMT_DBG_FUNC("WMT-PLAT:I2S CK not defined\n"); + return 0; + } + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_I2S_WS_PIN].gpio_num == DEFAULT_PIN_ID) { + WMT_DBG_FUNC("WMT-PLAT:I2S WS not defined\n"); + return 0; + } + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_I2S_DAT_PIN].gpio_num == DEFAULT_PIN_ID) { + WMT_DBG_FUNC("WMT-PLAT:DAT CK not defined\n"); + return 0; + } + /*check if combo chip support merge if or not */ + if (wmt_plat_merge_if_flag_get() != 0) { +#if (MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT) + /* Hardware support Merge IF function */ +#if defined(FM_DIGITAL_INPUT) || defined(FM_DIGITAL_OUTPUT) + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_I2S_CK_PIN].gpio_num != DEFAULT_PIN_ID) { + switch (state) { + case PIN_STA_INIT: + case PIN_STA_MUX: + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_I2S_CK_PIN].gpio_state[GPIO_PULL_DIS]); + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_I2S_WS_PIN].gpio_state[GPIO_PULL_DIS]); + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_I2S_DAT_PIN].gpio_state[GPIO_PULL_DIS]); + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_PCM_DAIPMCOUT_PIN]. + gpio_state[GPIO_PULL_DIS]); + WMT_DBG_FUNC("WMT-PLAT:I2S init (I2S0 system)\n"); + break; + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + gpio_direction_output(gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_I2S_CK_PIN].gpio_num, 0); + gpio_direction_output(gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_I2S_WS_PIN].gpio_num, 0); + gpio_direction_output(gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_I2S_DAT_PIN].gpio_num, 0); + 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_ERR_FUNC("[MT662x]Error:FM digital mode set, no I2S GPIOs defined\n"); +#else + WMT_INFO_FUNC("[MT662x]warnning:FM digital mode is not set\n"); + WMT_INFO_FUNC("no I2S GPIO settings should be modified by combo driver\n"); +#endif +#else + /* Hardware does support Merge IF function */ + normalI2SFlag = 1; +#endif + } else + normalI2SFlag = 1; + + if (normalI2SFlag != 0) { +#if defined(FM_DIGITAL_INPUT) || defined(FM_DIGITAL_OUTPUT) + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_I2S_CK_PIN].gpio_num != DEFAULT_PIN_ID) { + switch (state) { + case PIN_STA_INIT: + case PIN_STA_MUX: + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_I2S_CK_PIN].gpio_state[GPIO_PULL_DIS]); + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_I2S_WS_PIN].gpio_state[GPIO_PULL_DIS]); + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_I2S_DAT_PIN].gpio_state[GPIO_PULL_DIS]); + WMT_DBG_FUNC("WMT-PLAT:I2S init (I2S0 system)\n"); + break; + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + gpio_direction_output(gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_I2S_CK_PIN].gpio_num, 0); + gpio_direction_output(gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_I2S_WS_PIN].gpio_num, 0); + gpio_direction_output(gpio_ctrl_info. + gpio_ctrl_state[GPIO_COMBO_I2S_DAT_PIN].gpio_num, 0); + 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_ERR_FUNC("[MT662x]Error:FM digital mode set, but no I2S GPIOs defined\n"); +#else + WMT_INFO_FUNC("[MT662x]warnning:FM digital mode is not set\n"); + WMT_INFO_FUNC("no I2S GPIO settings should be modified by combo driver\n"); +#endif + } + + return 0; +} + +static INT32 wmt_plat_soc_i2s_ctrl(ENUM_PIN_STATE state) +{ + WMT_PLAT_PR_WARN("host i2s pin not defined!!!\n"); + + return 0; +} + +static INT32 wmt_plat_i2s_ctrl(ENUM_PIN_STATE state) +{ + INT32 ret = -1; + + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) + ret = wmt_plat_soc_i2s_ctrl(state); + else + ret = wmt_plat_cmb_i2s_ctrl(state); + + return ret; +} + +static INT32 wmt_plat_sdio_pin_ctrl(ENUM_PIN_STATE state) +{ + return 0; +} + +static INT32 wmt_plat_cmb_gps_sync_ctrl(ENUM_PIN_STATE state) +{ + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_GPS_SYNC_PIN].gpio_num == DEFAULT_PIN_ID) { + WMT_INFO_FUNC("WMT-PLAT:GPS SYNC not defined\n"); + return 0; + } + + switch (state) { + case PIN_STA_INIT: + case PIN_STA_DEINIT: + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_GPS_SYNC_PIN].gpio_state[GPIO_PULL_DIS]); + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_GPS_SYNC_PIN].gpio_num, 0); + break; + case PIN_STA_MUX: + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_GPS_SYNC_PIN].gpio_state[GPIO_PULL_DIS]); + break; + default: + break; + } + + return 0; +} + +static INT32 wmt_plat_soc_gps_sync_ctrl(ENUM_PIN_STATE state) +{ + WMT_PLAT_PR_WARN("host gps sync pin not defined!!!\n"); + + return 0; +} + +static INT32 wmt_plat_gps_sync_ctrl(ENUM_PIN_STATE state) +{ + INT32 ret = -1; + + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) + ret = wmt_plat_soc_gps_sync_ctrl(state); + else + ret = wmt_plat_cmb_gps_sync_ctrl(state); + + return ret; +} + +static INT32 wmt_plat_soc_gps_lna_ctrl(ENUM_PIN_STATE state) +{ +#ifdef CONFIG_MTK_MT6306_GPIO_SUPPORT + switch (state) { + case PIN_STA_INIT: + case PIN_STA_DEINIT: + KERNEL_mt6306_set_gpio_dir(MT6306_GPIO_01, MT6306_GPIO_DIR_OUT); + KERNEL_mt6306_set_gpio_out(MT6306_GPIO_01, MT6306_GPIO_OUT_LOW); + WMT_PLAT_PR_DBG("set gps lna to init\n"); + break; + case PIN_STA_OUT_H: + KERNEL_mt6306_set_gpio_out(MT6306_GPIO_01, MT6306_GPIO_OUT_HIGH); + WMT_PLAT_PR_DBG("set gps lna to oh\n"); + break; + case PIN_STA_OUT_L: + KERNEL_mt6306_set_gpio_out(MT6306_GPIO_01, MT6306_GPIO_OUT_LOW); + WMT_PLAT_PR_DBG("set gps lna to ol\n"); + break; + default: + WMT_PLAT_PR_WARN("%d mode not defined for gps lna pin !!!\n", state); + break; + } +#else + struct pinctrl_state *gps_lna_init = NULL; + struct pinctrl_state *gps_lna_oh = NULL; + struct pinctrl_state *gps_lna_ol = NULL; + struct pinctrl *consys_pinctrl = NULL; + + WMT_PLAT_PR_DBG("ENTER++\n"); + consys_pinctrl = mtk_wcn_consys_get_pinctrl(); + if (!consys_pinctrl) { + WMT_PLAT_PR_ERR("get consys pinctrl fail\n"); + return 0; + } + + gps_lna_init = pinctrl_lookup_state(consys_pinctrl, "gps_lna_state_init"); + if (IS_ERR(gps_lna_init)) { + WMT_PLAT_PR_ERR("Cannot find gps lna pin init state!\n"); + return 0; + } + + gps_lna_oh = pinctrl_lookup_state(consys_pinctrl, "gps_lna_state_oh"); + if (IS_ERR(gps_lna_oh)) { + WMT_PLAT_PR_ERR("Cannot find gps lna pin oh state!\n"); + return 0; + } + + gps_lna_ol = pinctrl_lookup_state(consys_pinctrl, "gps_lna_state_ol"); + if (IS_ERR(gps_lna_ol)) { + WMT_PLAT_PR_ERR("Cannot find gps lna pin ol state!\n"); + return 0; + } + + switch (state) { + case PIN_STA_INIT: + case PIN_STA_DEINIT: + pinctrl_select_state(consys_pinctrl, gps_lna_init); + WMT_PLAT_PR_DBG("set gps lna to init\n"); + break; + case PIN_STA_OUT_H: + pinctrl_select_state(consys_pinctrl, gps_lna_oh); + WMT_PLAT_PR_DBG("set gps lna to oh\n"); + break; + case PIN_STA_OUT_L: + pinctrl_select_state(consys_pinctrl, gps_lna_ol); + WMT_PLAT_PR_DBG("set gps lna to ol\n"); + break; + default: + WMT_PLAT_PR_WARN("%d mode not defined for gps lna pin !!!\n", state); + break; + } +#endif + + return 0; +} + +static INT32 wmt_plat_cmb_gps_lna_ctrl(ENUM_PIN_STATE state) +{ + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_GPS_LNA_PIN].gpio_num != DEFAULT_PIN_ID) { + switch (state) { + case PIN_STA_INIT: + case PIN_STA_DEINIT: + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_GPS_LNA_PIN].gpio_state[GPIO_PULL_DIS]); + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_GPS_LNA_PIN].gpio_num, 0); + break; + case PIN_STA_OUT_H: + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_GPS_LNA_PIN].gpio_num, 1); + break; + case PIN_STA_OUT_L: + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_GPS_LNA_PIN].gpio_num, 0); + break; + default: + WMT_WARN_FUNC("%d mode not defined for gps lna pin !!!\n", state); + break; + } + } else { +#ifdef CONFIG_MTK_MT6306_GPIO_SUPPORT + WMT_WARN_FUNC("/******************************************************************/\n"); + WMT_WARN_FUNC("use MT6306 GPIO7 for gps lna pin.\n this HARD CODE may hurt other\n"); + WMT_WARN_FUNC("system module, if GPIO7 of MT6306 is not defined as GPS_LNA function\n"); + WMT_WARN_FUNC("/******************************************************************/\n"); + + switch (state) { + case PIN_STA_INIT: + case PIN_STA_DEINIT: + /* KERNEL_mt6306_set_gpio_dir(GPIO7, GPIO_DIR_OUT); */ + /* KERNEL_mt6306_set_gpio_out(GPIO7, GPIO_OUT_ZERO); */ + break; + case PIN_STA_OUT_H: + /* KERNEL_mt6306_set_gpio_out(GPIO7, GPIO_OUT_ONE); */ + break; + case PIN_STA_OUT_L: + /* KERNEL_mt6306_set_gpio_out(GPIO7, GPIO_OUT_ZERO); */ + break; + default: + WMT_WARN_FUNC("%d mode not defined for gps lna pin !!!\n", state); + break; + } +#else + WMT_WARN_FUNC("host gps lna pin not defined!!!\n"); + WMT_WARN_FUNC("if you donot use eighter AP or MT6306's pin as GPS_LNA\n"); + WMT_WARN_FUNC("please customize your own GPS_LNA related code here\n"); +#endif + } + + return 0; +} + +static INT32 wmt_plat_gps_lna_ctrl(ENUM_PIN_STATE state) +{ + INT32 ret = -1; + + if (wmt_detect_get_chip_type() == WMT_CHIP_TYPE_SOC) + ret = wmt_plat_soc_gps_lna_ctrl(state); + else + ret = wmt_plat_cmb_gps_lna_ctrl(state); + + return ret; +} + +static INT32 wmt_plat_uart_rx_ctrl(ENUM_PIN_STATE state) +{ + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_URXD_PIN].gpio_num == DEFAULT_PIN_ID) { + WMT_DBG_FUNC("WMT-PLAT:UART RX not defined\n"); + return 0; + } + + switch (state) { + case PIN_STA_MUX: + case PIN_STA_INIT: + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_URXD_PIN].gpio_state[GPIO_PULL_DIS]); + WMT_DBG_FUNC("WMT-PLAT:UART Rx init\n"); + break; + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_URXD_PIN].gpio_state[GPIO_PULL_DIS]); + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_URXD_PIN].gpio_num, 0); + WMT_DBG_FUNC("WMT-PLAT:UART Rx deinit (out 0)\n"); + break; + case PIN_STA_IN_NP: + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_URXD_PIN].gpio_state[GPIO_IN_PULL_DIS]); + WMT_DBG_FUNC("WMT-PLAT:UART Rx input pull none\n"); + break; + case PIN_STA_IN_H: + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_URXD_PIN].gpio_state[GPIO_IN_PULLUP]); + WMT_DBG_FUNC("WMT-PLAT:UART Rx input pull high\n"); + break; + case PIN_STA_OUT_H: + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_URXD_PIN].gpio_num, 1); + WMT_DBG_FUNC("WMT-PLAT:UART Rx output high\n"); + break; + case PIN_STA_OUT_L: + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_URXD_PIN].gpio_num, 0); + WMT_DBG_FUNC("WMT-PLAT:UART Rx deinit (out 0)\n"); + break; + default: + WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on UART Rx\n", state); + break; + } + + return 0; +} + +#if CFG_WMT_LTE_COEX_HANDLING +static INT32 wmt_plat_tdm_req_ctrl(ENUM_PIN_STATE state) +{ + return 0; +} +#endif + +INT32 wmt_plat_wake_lock_ctrl(ENUM_WL_OP opId) +{ + static INT32 counter; + INT32 ret = 0; + + ret = osal_lock_sleepable_lock(&gOsSLock); + if (ret) { + WMT_ERR_FUNC("--->lock gOsSLock failed, ret=%d\n", ret); + return ret; + } + + if (opId == WL_OP_GET) + ++counter; + else if (opId == WL_OP_PUT) + --counter; + + osal_unlock_sleepable_lock(&gOsSLock); + if (opId == WL_OP_GET && counter == 1) { + osal_wake_lock(&wmt_wake_lock); + WMT_DBG_FUNC("WMT-PLAT: after wake_lock(%d), counter(%d)\n", + osal_wake_lock_count(&wmt_wake_lock), counter); + + } else if (opId == WL_OP_PUT && counter == 0) { + osal_wake_unlock(&wmt_wake_lock); + WMT_DBG_FUNC("WMT-PLAT: after wake_unlock(%d), counter(%d)\n", + osal_wake_lock_count(&wmt_wake_lock), counter); + } else { + WMT_WARN_FUNC("WMT-PLAT: wakelock status(%d), counter(%d)\n", + osal_wake_lock_count(&wmt_wake_lock), counter); + } + + return 0; +} + + +INT32 wmt_plat_merge_if_flag_ctrl(UINT32 enable) +{ + if (enable) { +#if (MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT) + gWmtMergeIfSupport = 1; +#else + gWmtMergeIfSupport = 0; + WMT_WARN_FUNC("neither MT6589, MTK_MERGE_INTERFACE_SUPPORT nor MT6628 is not set to 1\n"); + WMT_WARN_FUNC("so set gWmtMergeIfSupport to %d\n", gWmtMergeIfSupport); +#endif + } else + gWmtMergeIfSupport = 0; + + WMT_INFO_FUNC("set gWmtMergeIfSupport to %d\n", gWmtMergeIfSupport); + + return gWmtMergeIfSupport; +} + +INT32 wmt_plat_merge_if_flag_get(VOID) +{ + return gWmtMergeIfSupport; +} + +INT32 wmt_plat_set_comm_if_type(ENUM_STP_TX_IF_TYPE type) +{ + gCommIfType = type; + + return 0; +} + +ENUM_STP_TX_IF_TYPE wmt_plat_get_comm_if_type(VOID) +{ + return gCommIfType; +} + +INT32 wmt_plat_soc_paldo_ctrl(ENUM_PALDO_TYPE ePt, ENUM_PALDO_OP ePo) +{ + INT32 iRet = 0; + + switch (ePt) { + case BT_PALDO: + iRet = mtk_wcn_consys_hw_bt_paldo_ctrl(ePo); + break; + case WIFI_PALDO: + iRet = mtk_wcn_consys_hw_wifi_paldo_ctrl(ePo); + break; + case FM_PALDO: + case GPS_PALDO: + iRet = mtk_wcn_consys_hw_vcn28_ctrl(ePo); + break; + case EFUSE_PALDO: + iRet = mtk_wcn_consys_hw_efuse_paldo_ctrl(ePo, wmt_plat_soc_co_clock_flag_get()); + break; + default: + WMT_PLAT_PR_WARN("WMT-PLAT:Warnning, invalid type(%d) in palod_ctrl\n", ePt); + break; + } + + return iRet; +} + +#if CONSYS_WMT_REG_SUSPEND_CB_ENABLE +UINT32 wmt_plat_soc_osc_en_ctrl(UINT32 en) +{ + return mtk_wcn_consys_hw_osc_en_ctrl(en); +} +#endif + +UINT8 *wmt_plat_get_emi_virt_add(UINT32 offset) +{ + return mtk_wcn_consys_emi_virt_addr_get(offset); +} + +P_CONSYS_EMI_ADDR_INFO wmt_plat_get_emi_phy_add(VOID) +{ + return mtk_wcn_consys_soc_get_emi_phy_add(); +} + +#if CONSYS_ENALBE_SET_JTAG +UINT32 wmt_plat_jtag_flag_ctrl(UINT32 en) +{ + return mtk_wcn_consys_jtag_flag_ctrl(en); +} +#endif + +#if CFG_WMT_DUMP_INT_STATUS +VOID wmt_plat_BGF_irq_dump_status(VOID) +{ + mt_irq_dump_status(269);/*tag3 wujun rainier is enabled */ + + WMT_PLAT_PR_INFO("this function is null in MT6735\n"); +} + +MTK_WCN_BOOL wmt_plat_dump_BGF_irq_status(VOID) +{ + return MTK_WCN_BOOL_FALSE;/*tag4 wujun rainier is enabled */ +} +#endif + +UINT32 wmt_plat_read_cpupcr(VOID) +{ + return mtk_wcn_consys_read_cpupcr(); +} +EXPORT_SYMBOL(wmt_plat_read_cpupcr); + +UINT32 wmt_plat_read_dmaregs(UINT32 type) +{ + return 0; +#if 0 + switch (type) { + case CONNSYS_CLK_GATE_STATUS: + return CONSYS_REG_READ(CONNSYS_CLK_GATE_STATUS_REG); + case CONSYS_EMI_STATUS: + return CONSYS_REG_READ(CONSYS_EMI_STATUS_REG); + case SYSRAM1: + return CONSYS_REG_READ(SYSRAM1_REG); + case SYSRAM2: + return CONSYS_REG_READ(SYSRAM2_REG); + case SYSRAM3: + return CONSYS_REG_READ(SYSRAM3_REG); + default: + return 0; + } +#endif +} + +INT32 wmt_plat_set_host_dump_state(ENUM_HOST_DUMP_STATE state) +{ + PUINT8 p_virtual_addr = NULL; + + p_virtual_addr = wmt_plat_get_emi_virt_add(EXP_APMEM_CTRL_HOST_SYNC_STATE); + if (!p_virtual_addr) { + WMT_PLAT_PR_ERR("get virtual address fail\n"); + return -1; + } + + CONSYS_REG_WRITE(p_virtual_addr, state); + + return 0; +} + +UINT32 wmt_plat_force_trigger_assert(ENUM_FORCE_TRG_ASSERT_T type) +{ + PUINT8 p_virtual_addr = NULL; + + switch (type) { + case STP_FORCE_TRG_ASSERT_EMI: + + WMT_PLAT_PR_INFO("[Force Assert] stp_trigger_firmware_assert_via_emi -->\n"); + p_virtual_addr = wmt_plat_get_emi_virt_add(EXP_APMEM_CTRL_HOST_OUTBAND_ASSERT_W1); + if (!p_virtual_addr) { + WMT_PLAT_PR_ERR("get virtual address fail\n"); + return -1; + } + + CONSYS_REG_WRITE(p_virtual_addr, EXP_APMEM_HOST_OUTBAND_ASSERT_MAGIC_W1); + WMT_PLAT_PR_INFO("[Force Assert] stp_trigger_firmware_assert_via_emi <--\n"); + break; + case STP_FORCE_TRG_ASSERT_DEBUG_PIN: + mtk_wcn_force_trigger_assert_debug_pin(); + break; + default: + WMT_PLAT_PR_ERR("unknown force trigger assert type\n"); + break; + } + + return 0; +} + +INT32 wmt_plat_update_host_sync_num(VOID) +{ + PUINT8 p_virtual_addr = NULL; + UINT32 sync_num = 0; + + p_virtual_addr = wmt_plat_get_emi_virt_add(EXP_APMEM_CTRL_HOST_SYNC_NUM); + if (!p_virtual_addr) { + WMT_PLAT_PR_ERR("get virtual address fail\n"); + return -1; + } + + sync_num = CONSYS_REG_READ(p_virtual_addr); + CONSYS_REG_WRITE(p_virtual_addr, sync_num + 1); + + return 0; +} + +INT32 wmt_plat_get_dump_info(UINT32 offset) +{ + PUINT8 p_virtual_addr = NULL; + + p_virtual_addr = wmt_plat_get_emi_virt_add(offset); + if (!p_virtual_addr) { + WMT_PLAT_PR_ERR("get virtual address fail\n"); + return -1; + } + WMT_PLAT_PR_DBG("connsys_reg_read (0x%x), (0x%p), (0x%x)\n", CONSYS_REG_READ(p_virtual_addr), p_virtual_addr, + offset); + return CONSYS_REG_READ(p_virtual_addr); +} + +INT32 wmt_plat_write_emi_l(UINT32 offset, UINT32 value) +{ + PUINT8 p_virtual_addr = NULL; + + p_virtual_addr = wmt_plat_get_emi_virt_add(offset); + if (!p_virtual_addr) { + WMT_PLAT_PR_ERR("get virtual address fail\n"); + return -1; + } + + CONSYS_REG_WRITE(p_virtual_addr, value); + return 0; +} + +UINT32 wmt_plat_get_soc_chipid(VOID) +{ + UINT32 chipId = mtk_wcn_consys_soc_chipid(); + + return chipId; +} +EXPORT_SYMBOL(wmt_plat_get_soc_chipid); + +INT32 wmt_plat_get_adie_chipid(VOID) +{ + return mtk_wcn_consys_detect_adie_chipid(gCoClockFlag); +} + +#if CFG_WMT_LTE_COEX_HANDLING +INT32 wmt_plat_get_tdm_antsel_index(VOID) +{ + WMT_PLAT_PR_INFO("not support LTE in this platform\n"); + return 0; +} +#endif + +INT32 wmt_plat_set_dbg_mode(UINT32 flag) +{ + INT32 ret = -1; + PUINT8 vir_addr = NULL; + + vir_addr = mtk_wcn_consys_emi_virt_addr_get(EXP_APMEM_CTRL_CHIP_FW_DBGLOG_MODE); + if (!vir_addr) { + WMT_PLAT_PR_ERR("get vir address fail\n"); + return ret; + } + if (flag) { + CONSYS_REG_WRITE(vir_addr, 0x1); + ret = 0; + } else { + CONSYS_REG_WRITE(vir_addr, 0x0); + ret = 1; + } + WMT_PLAT_PR_INFO("fw dbg mode register value(0x%08x)\n", CONSYS_REG_READ(vir_addr)); + + return ret; +} + +INT32 wmt_plat_set_dynamic_dumpmem(PUINT32 str_buf) +{ + PUINT8 vir_addr = NULL; + + vir_addr = mtk_wcn_consys_emi_virt_addr_get(EXP_APMEM_CTRL_CHIP_DYNAMIC_DUMP); + if (!vir_addr) { + WMT_PLAT_PR_ERR("get vir address fail\n"); + return -1; + } + memcpy(vir_addr, str_buf, DYNAMIC_DUMP_GROUP_NUM*8); + WMT_PLAT_PR_INFO("dynamic dump register value(0x%08x)\n", CONSYS_REG_READ(vir_addr)); + + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_main/platform/wmt_plat_stub.c b/drivers/misc/mediatek/connectivity/common/common_main/platform/wmt_plat_stub.c new file mode 100644 index 0000000000000..09547b390b78c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/platform/wmt_plat_stub.c @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + + + + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-PLAT]" + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/* ALPS and COMBO header files */ +#include + +/* MTK_WCN_COMBO header files */ +#include "wmt_plat.h" +#include "wmt_plat_stub.h" +#include "wmt_exp.h" +#include "wmt_lib.h" +#include "osal.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(unsigned int type, unsigned int on) +{ + if (on) + mtk_wcn_wmt_func_on((ENUM_WMTDRV_TYPE_T) type); + else + mtk_wcn_wmt_func_off((ENUM_WMTDRV_TYPE_T) type); +} + +static signed long wmt_plat_thremal_query(void) +{ + return wmt_lib_tm_temp_query(); +} + +INT32 wmt_plat_stub_init(VOID) +{ + INT32 iRet = -1; + struct _CMB_STUB_CB_ stub_cb = {0}; + + stub_cb.aif_ctrl_cb = wmt_plat_audio_ctrl; + stub_cb.func_ctrl_cb = wmt_plat_func_ctrl; + stub_cb.thermal_query_cb = wmt_plat_thremal_query; + stub_cb.size = sizeof(stub_cb); + + /* register to cmb_stub */ + iRet = mtk_wcn_cmb_stub_reg(&stub_cb); + return iRet; +} diff --git a/drivers/misc/mediatek/connectivity/common/init.wmt_drv.rc b/drivers/misc/mediatek/connectivity/common/init.wmt_drv.rc new file mode 100644 index 0000000000000..732a4cd8c3b27 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/init.wmt_drv.rc @@ -0,0 +1,2 @@ +on boot + insmod /vendor/lib/modules/wmt_drv.ko diff --git a/drivers/misc/mediatek/connectivity/common/test/include/wmt_step_test.h b/drivers/misc/mediatek/connectivity/common/test/include/wmt_step_test.h new file mode 100644 index 0000000000000..c8de0418cac77 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/test/include/wmt_step_test.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2016 MediaTek Inc. * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef _WMT_STEP_TEST_H_ +#define _WMT_STEP_TEST_H_ + +#include "osal.h" +#include "wmt_step.h" + +#define STEP_TEST_CONSYS_EMI_WMT_OFFSET 0x68000 + +#define TEST_FAIL -1 +#define TEST_PASS 0 +#define TEST_CHECK 1 +#define STEP_TEST_ACTION_NUMBER 30 + +extern struct step_env_struct g_step_env; +extern struct platform_device *g_pdev; + +struct step_test_report { + unsigned int pass; + unsigned int fail; + unsigned int check; +}; + +struct step_test_check { + unsigned int step_check_total; + int step_check_test_tp_id[STEP_TEST_ACTION_NUMBER]; + int step_check_test_act_id[STEP_TEST_ACTION_NUMBER]; + char *step_check_params[STEP_TEST_ACTION_NUMBER][STEP_PARAMETER_SIZE]; + int step_check_params_num[STEP_TEST_ACTION_NUMBER]; + unsigned int step_check_index; + int step_check_result; + char *step_check_result_string; + int step_check_result_value; + unsigned int step_check_emi_offset[STEP_TEST_ACTION_NUMBER]; + SIZE_T step_check_register_addr; + SIZE_T step_check_write_value; + unsigned int step_test_mask; + unsigned int step_recovery_value; + int step_check_temp_register_id; +}; + +void wmt_step_test_all(void); +void wmt_step_test_read_file(struct step_test_report *p_report); +void wmt_step_test_parse_data(struct step_test_report *p_report); +void wmt_step_test_create_emi_action(struct step_test_report *p_report); +void wmt_step_test_create_cond_emi_action(struct step_test_report *p_report); +void wmt_step_test_create_register_action(struct step_test_report *p_report); +void wmt_step_test_create_cond_register_action(struct step_test_report *p_report); +void wmt_step_test_check_register_symbol(struct step_test_report *p_report); +void wmt_step_test_create_other_action(struct step_test_report *p_report); +void wmt_step_test_do_emi_action(struct step_test_report *p_report); +void wmt_step_test_do_cond_emi_action(struct step_test_report *p_report); +void wmt_step_test_do_register_action(struct step_test_report *p_report); +void wmt_step_test_do_cond_register_action(struct step_test_report *p_report); +void wmt_step_test_do_gpio_action(struct step_test_report *p_report); +void wmt_step_test_do_disable_reset_action(struct step_test_report *p_report); +void wmt_step_test_do_chip_reset_action(struct step_test_report *p_report); +void wmt_step_test_do_wakeup_action(struct step_test_report *p_report); +void wmt_step_test_create_periodic_dump(struct step_test_report *p_report); +void wmt_step_test_do_show_action(struct step_test_report *p_report); +void wmt_step_test_do_sleep_action(struct step_test_report *p_report); +void wmt_step_test_do_condition_action(struct step_test_report *p_report); +void wmt_step_test_do_value_action(struct step_test_report *p_report); + +#endif /* end of _WMT_STEP_TEST_H_ */ + diff --git a/drivers/misc/mediatek/connectivity/common/test/wmt_step_test.c b/drivers/misc/mediatek/connectivity/common/test/wmt_step_test.c new file mode 100644 index 0000000000000..f28a2b1a40c33 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/test/wmt_step_test.c @@ -0,0 +1,4966 @@ +/* + * Copyright (C) 2016 MediaTek Inc. * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include +#include "osal.h" +#include "wmt_step_test.h" +#include "wmt_step.h" +#include "wmt_exp.h" +#include "wmt_lib.h" +#include "mtk_wcn_consys_hw.h" +#include "stp_core.h" +#include "wmt_dbg.h" + +struct step_test_check g_step_test_check; + +void wmt_step_test_clear_parameter(char *params[]) +{ + int i = 0; + + for (i = 0; i < STEP_PARAMETER_SIZE; i++) + params[i] = NULL; +} + +#define index_of_array(current_addr, base_addr, type) \ + (((unsigned long)current_addr - (unsigned long)base_addr) / sizeof(type)) + +int wmt_step_test_check_write_tp(struct step_action_list *p_act_list, enum step_action_id act_id, + int param_num, char *params[]) +{ + int index = g_step_test_check.step_check_index; + int i; + int tp_id; + + if (g_step_test_check.step_check_result == TEST_FAIL) + return 0; + + if (index < 0) + return 0; + + g_step_test_check.step_check_index++; + + if (g_step_test_check.step_check_test_tp_id[index] != -1) { + tp_id = index_of_array(p_act_list, &g_step_env.actions, struct step_action_list); + if (tp_id != g_step_test_check.step_check_test_tp_id[index]) { + g_step_test_check.step_check_result = TEST_FAIL; + WMT_ERR_FUNC("STEP test failed: tp_id %d: expect %d(%d)\n", tp_id, + g_step_test_check.step_check_test_tp_id[index], index); + return 0; + } + } + + if (act_id != g_step_test_check.step_check_test_act_id[index]) { + g_step_test_check.step_check_result = TEST_FAIL; + WMT_ERR_FUNC("STEP test failed: act_id %d: expect %d(%d)\n", act_id, + g_step_test_check.step_check_test_tp_id[index], index); + return 0; + } + + if (param_num != g_step_test_check.step_check_params_num[index]) { + g_step_test_check.step_check_result = TEST_FAIL; + WMT_ERR_FUNC("STEP test failed: param num %d: expect %d(%d)\n", param_num, + g_step_test_check.step_check_params_num[index], index); + return 0; + } + + for (i = 0; i < STEP_PARAMETER_SIZE; i++) { + if (osal_strcmp(g_step_test_check.step_check_params[index][0], "") == 0) + break; + + if (params[0] == NULL || osal_strcmp(params[0], g_step_test_check.step_check_params[index][0]) != 0) { + g_step_test_check.step_check_result = TEST_FAIL; + WMT_ERR_FUNC("STEP test failed: params[%d] %s: expect %s(%d)\n", i, params[0], + g_step_test_check.step_check_params[index][0], index); + return 0; + } + } + + g_step_test_check.step_check_result = TEST_PASS; + + return 0; +} + +int wmt_step_test_check_create_emi(struct step_emi_action *p_emi_act, int check_params[], + char *err_result) +{ + struct step_emi_info *p_emi_info = NULL; + int result = TEST_FAIL; + + p_emi_info = &p_emi_act->info; + if (p_emi_act->base.action_id != STEP_ACTION_INDEX_EMI) { + WMT_ERR_FUNC("%s, id wrong: %d\n", err_result, p_emi_act->base.action_id); + result = TEST_FAIL; + } else if (p_emi_info->output_mode == STEP_OUTPUT_LOG) { + if (p_emi_info->is_write != check_params[0] || + p_emi_info->begin_offset != check_params[1] || + p_emi_info->end_offset != check_params[2]) { + WMT_ERR_FUNC("%s, C1 emi log params: %d, %d, %d\n", + err_result, p_emi_info->is_write, p_emi_info->begin_offset, + p_emi_info->end_offset); + result = TEST_FAIL; + } else { + result = TEST_PASS; + } + } else if (p_emi_info->output_mode == STEP_OUTPUT_REGISTER) { + if (p_emi_info->is_write != check_params[0] || + p_emi_info->begin_offset != check_params[1] || + p_emi_info->mask != check_params[2] || + p_emi_info->temp_reg_id != check_params[3]) { + WMT_ERR_FUNC("%s, C2 emi reg params: %d, %d, %d, %d\n", + err_result, p_emi_info->is_write, p_emi_info->begin_offset, + p_emi_info->mask, p_emi_info->temp_reg_id); + result = TEST_FAIL; + } else { + result = TEST_PASS; + } + } else { + result = TEST_FAIL; + } + + return result; +} + +int wmt_step_test_check_create_condition_emi(struct step_condition_emi_action *p_cond_emi_act, int check_params[], + char *err_result) +{ + struct step_emi_info *p_emi_info = NULL; + int result = TEST_FAIL; + + p_emi_info = &p_cond_emi_act->info; + if (p_cond_emi_act->base.action_id != STEP_ACTION_INDEX_CONDITION_EMI) { + WMT_ERR_FUNC("%s, id wrong: %d\n", err_result, p_cond_emi_act->base.action_id); + result = TEST_FAIL; + } else if (p_emi_info->output_mode == STEP_OUTPUT_LOG) { + if (p_cond_emi_act->cond_reg_id != check_params[0] || + p_emi_info->is_write != check_params[1] || + p_emi_info->begin_offset != check_params[2] || + p_emi_info->end_offset != check_params[3]) { + WMT_ERR_FUNC("%s, C1 emi log params: %d, %d, %d, %d\n", + err_result, p_cond_emi_act->cond_reg_id, p_emi_info->is_write, + p_emi_info->begin_offset, p_emi_info->end_offset); + result = TEST_FAIL; + } else { + result = TEST_PASS; + } + } else if (p_emi_info->output_mode == STEP_OUTPUT_REGISTER) { + if (p_cond_emi_act->cond_reg_id != check_params[0] || + p_emi_info->is_write != check_params[1] || + p_emi_info->begin_offset != check_params[2] || + p_emi_info->mask != check_params[3] || + p_emi_info->temp_reg_id != check_params[4]) { + WMT_ERR_FUNC("%s, C2 emi reg params: %d, %d, %d, %d, %d\n", + err_result, p_cond_emi_act->cond_reg_id, p_emi_info->is_write, + p_emi_info->begin_offset, p_emi_info->mask, p_emi_info->temp_reg_id); + result = TEST_FAIL; + } else { + result = TEST_PASS; + } + } else { + result = TEST_FAIL; + } + + return result; +} + +int wmt_step_test_check_create_read_reg(struct step_reigster_info *p_reg_info, + int check_params[], char *err_result, int check_index) +{ + int result = TEST_FAIL; + + if (p_reg_info->address_type == STEP_REGISTER_PHYSICAL_ADDRESS) { + if (p_reg_info->address != check_params[check_index + 1] || + p_reg_info->offset != check_params[check_index + 2]) { + WMT_ERR_FUNC( + "%s, C1 reg params: %d, 0x%08x, %d\n", + err_result, p_reg_info->is_write, (unsigned int)p_reg_info->address, + p_reg_info->offset); + return TEST_FAIL; + } + } else { + if (p_reg_info->address_type != check_params[check_index + 1] || + p_reg_info->offset != check_params[check_index + 2]) { + WMT_ERR_FUNC( + "%s, C2 reg params: %d, 0x%08x, %d\n", + err_result, p_reg_info->is_write, (unsigned int)p_reg_info->address, + p_reg_info->offset); + return TEST_FAIL; + } + } + + if (p_reg_info->output_mode == STEP_OUTPUT_LOG) { + if (p_reg_info->times != check_params[check_index + 3] || + p_reg_info->delay_time != check_params[check_index + 4]) { + WMT_ERR_FUNC( + "%s, C3 reg params: %d, 0x%08x, %d, %d, %d\n", + err_result, p_reg_info->is_write, (unsigned int)p_reg_info->address, + p_reg_info->offset, p_reg_info->times, p_reg_info->delay_time); + result = TEST_FAIL; + } else { + result = TEST_PASS; + } + } else if (p_reg_info->output_mode == STEP_OUTPUT_REGISTER) { + if (p_reg_info->mask != check_params[check_index + 3] || + p_reg_info->temp_reg_id != check_params[check_index + 4]) { + WMT_ERR_FUNC( + "%s, C4 reg params: %d, 0x%08x, %d, %d, %d\n", + err_result, p_reg_info->is_write, (unsigned int)p_reg_info->address, + p_reg_info->offset, p_reg_info->mask, p_reg_info->temp_reg_id); + result = TEST_FAIL; + } else { + result = TEST_PASS; + } + } else { + result = TEST_FAIL; + } + + return result; +} + +int wmt_step_test_check_create_write_reg(struct step_reigster_info *p_reg_info, + int check_params[], char *err_result, int check_index) +{ + int result = TEST_FAIL; + + if (p_reg_info->address_type == STEP_REGISTER_PHYSICAL_ADDRESS) { + if (p_reg_info->address != check_params[check_index + 1] || + p_reg_info->offset != check_params[check_index + 2] || + p_reg_info->value != check_params[check_index + 3]) { + WMT_ERR_FUNC( + "%s, C1 reg params: %d, 0x%08x, %d, %d\n", + err_result, p_reg_info->is_write, (unsigned int)p_reg_info->address, + p_reg_info->offset, p_reg_info->value); + result = TEST_FAIL; + } else { + result = TEST_PASS; + } + } else { + if (p_reg_info->address_type != check_params[check_index + 1] || + p_reg_info->offset != check_params[check_index + 2] || + p_reg_info->value != check_params[check_index + 3]) { + WMT_ERR_FUNC( + "%s, C2 reg params: %d, %d, %d, %d\n", + err_result, p_reg_info->is_write, p_reg_info->address_type, + p_reg_info->offset, p_reg_info->value); + result = TEST_FAIL; + } else { + result = TEST_PASS; + } + } + + return result; +} + +int wmt_step_test_check_create_reg(struct step_register_action *p_reg_act, int check_params[], + char *err_result) +{ + struct step_reigster_info *p_reg_info = NULL; + int result = TEST_FAIL; + + p_reg_info = &p_reg_act->info; + if (p_reg_act->base.action_id != STEP_ACTION_INDEX_REGISTER) { + WMT_ERR_FUNC("%s, id wrong: %d\n", err_result, p_reg_act->base.action_id); + result = TEST_FAIL; + } else if (p_reg_info->is_write != check_params[0]) { + WMT_ERR_FUNC("%s, write failed: %d expect(%d)", err_result, p_reg_info->is_write, check_params[0]); + result = TEST_FAIL; + } else { + if (p_reg_info->is_write == 0) + result = wmt_step_test_check_create_read_reg(p_reg_info, check_params, err_result, 0); + else + result = wmt_step_test_check_create_write_reg(p_reg_info, check_params, err_result, 0); + } + + return result; +} + +int wmt_step_test_check_create_condition_reg(struct step_condition_register_action *p_cond_reg_act, int check_params[], + char *err_result) +{ + struct step_reigster_info *p_reg_info = NULL; + int result = TEST_FAIL; + + p_reg_info = &p_cond_reg_act->info; + if (p_cond_reg_act->base.action_id != STEP_ACTION_INDEX_CONDITION_REGISTER) { + WMT_ERR_FUNC("%s, id wrong: %d\n", err_result, p_cond_reg_act->base.action_id); + result = TEST_FAIL; + } else if (p_cond_reg_act->cond_reg_id != check_params[0]) { + WMT_ERR_FUNC("%s, reg id failed: %d expect(%d)", err_result, + p_cond_reg_act->cond_reg_id, check_params[0]); + result = TEST_FAIL; + } else if (p_reg_info->is_write != check_params[1]) { + WMT_ERR_FUNC("%s, write failed: %d expect(%d)", err_result, + p_reg_info->is_write, check_params[1]); + result = TEST_FAIL; + } else { + if (p_reg_info->is_write == 0) + result = wmt_step_test_check_create_read_reg(p_reg_info, check_params, err_result, 1); + else + result = wmt_step_test_check_create_write_reg(p_reg_info, check_params, err_result, 1); + } + + return result; +} + +int wmt_step_test_check_create_gpio(struct step_gpio_action *p_gpio_act, int check_params[], + char *err_result) +{ + int result = TEST_FAIL; + + if (p_gpio_act->base.action_id != STEP_ACTION_INDEX_GPIO) { + WMT_ERR_FUNC("%s, id wrong: %d\n", err_result, p_gpio_act->base.action_id); + result = TEST_FAIL; + } else if (p_gpio_act->is_write != check_params[0]) { + WMT_ERR_FUNC("%s, write failed: %d", err_result, p_gpio_act->is_write); + result = TEST_FAIL; + } else { + if (p_gpio_act->pin_symbol != check_params[1]) { + WMT_ERR_FUNC("%s, gpio params: %d, %d\n", + err_result, p_gpio_act->is_write, p_gpio_act->pin_symbol); + result = TEST_FAIL; + } else { + result = TEST_PASS; + } + } + + return result; +} + +int wmt_step_test_check_create_drst(struct step_disable_reset_action *p_drst_act, int check_params[], + char *err_result) +{ + int result = TEST_FAIL; + + if (p_drst_act->base.action_id != STEP_ACTION_INDEX_DISABLE_RESET) { + WMT_ERR_FUNC("%s, id wrong: %d\n", err_result, p_drst_act->base.action_id); + result = TEST_FAIL; + } else { + result = TEST_PASS; + } + + return result; +} + +int wmt_step_test_check_create_crst(struct step_chip_reset_action *p_crst_act, int check_params[], + char *err_result) +{ + int result = TEST_FAIL; + + if (p_crst_act->base.action_id != STEP_ACTION_INDEX_CHIP_RESET) { + WMT_ERR_FUNC("%s, id wrong: %d\n", err_result, p_crst_act->base.action_id); + result = TEST_FAIL; + } else { + result = TEST_PASS; + } + + return result; +} + +int wmt_step_test_check_create_keep_wakeup(struct step_keep_wakeup_action *p_kwak_act, + int check_params[], char *err_result) +{ + int result = TEST_FAIL; + + if (p_kwak_act->base.action_id != STEP_ACTION_INDEX_KEEP_WAKEUP) { + WMT_ERR_FUNC("%s, id wrong: %d\n", err_result, p_kwak_act->base.action_id); + result = TEST_FAIL; + } else { + result = TEST_PASS; + } + + return result; +} + +int wmt_step_test_check_create_cancel_wakeup(struct step_cancel_wakeup_action *p_cwak_act, + int check_params[], char *err_result) +{ + int result = TEST_FAIL; + + if (p_cwak_act->base.action_id != STEP_ACTION_INDEX_CANCEL_WAKEUP) { + WMT_ERR_FUNC("%s, id wrong: %d\n", err_result, p_cwak_act->base.action_id); + result = TEST_FAIL; + } else { + result = TEST_PASS; + } + + return result; +} + +int wmt_step_test_check_create_periodic_dump(struct step_periodic_dump_action *p_pd_act, + int check_params[], char *err_result) +{ + int result = TEST_FAIL; + + if (p_pd_act->base.action_id != STEP_ACTION_INDEX_PERIODIC_DUMP) { + WMT_ERR_FUNC("%s, id wrong: %d\n", err_result, p_pd_act->base.action_id); + result = TEST_FAIL; + } else { + result = TEST_PASS; + } + + return result; +} + +int wmt_step_test_check_create_show_string(struct step_show_string_action *p_show_act, + int check_params[], char *err_result) +{ + int result = TEST_FAIL; + + if (p_show_act->base.action_id != STEP_ACTION_INDEX_SHOW_STRING) { + WMT_ERR_FUNC("%s, id wrong: %d\n", err_result, p_show_act->base.action_id); + result = TEST_FAIL; + } else { + result = TEST_PASS; + } + + return result; +} + +int wmt_step_test_check_create_sleep(struct step_sleep_action *p_sleep_act, + int check_params[], char *err_result) +{ + int result = TEST_FAIL; + + if (p_sleep_act->base.action_id != STEP_ACTION_INDEX_SLEEP) { + WMT_ERR_FUNC("%s, id wrong: %d\n", err_result, p_sleep_act->base.action_id); + result = TEST_FAIL; + } else if (p_sleep_act->ms != check_params[0]) { + WMT_ERR_FUNC("%s, param failed: %d expect(%d)", err_result, p_sleep_act->ms, check_params[0]); + result = TEST_FAIL; + } else { + result = TEST_PASS; + } + + return result; +} + +int wmt_step_test_check_create_condition(struct step_condition_action *p_cond_act, + int check_params[], char *err_result) +{ + int result = TEST_FAIL; + + if (p_cond_act->base.action_id != STEP_ACTION_INDEX_CONDITION) { + WMT_ERR_FUNC("%s, id wrong: %d\n", err_result, p_cond_act->base.action_id); + result = TEST_FAIL; + } else if (p_cond_act->result_temp_reg_id != check_params[0] || + p_cond_act->l_temp_reg_id != check_params[1] || + p_cond_act->operator_id != check_params[2]) { + WMT_ERR_FUNC("%s, C1 param failed: %d %d %d %d expect(%d %d %d %d)", + err_result, p_cond_act->result_temp_reg_id, p_cond_act->l_temp_reg_id, + p_cond_act->operator_id, p_cond_act->r_temp_reg_id, + check_params[0], check_params[1], check_params[2], check_params[3]); + result = TEST_FAIL; + } else { + if (p_cond_act->mode == STEP_CONDITION_RIGHT_REGISTER && p_cond_act->r_temp_reg_id != check_params[3]) { + WMT_ERR_FUNC("%s, C2 param failed: %d %d %d %d expect(%d %d %d %d)", + err_result, p_cond_act->result_temp_reg_id, p_cond_act->l_temp_reg_id, + p_cond_act->operator_id, p_cond_act->r_temp_reg_id, + check_params[0], check_params[1], check_params[2], check_params[3]); + result = TEST_FAIL; + } else if (p_cond_act->mode == STEP_CONDITION_RIGHT_VALUE && p_cond_act->value != check_params[3]) { + WMT_ERR_FUNC("%s, C3 param failed: %d %d %d %d expect(%d %d %d %d)", + err_result, p_cond_act->result_temp_reg_id, p_cond_act->l_temp_reg_id, + p_cond_act->operator_id, p_cond_act->value, + check_params[0], check_params[1], check_params[2], check_params[3]); + result = TEST_FAIL; + } else { + result = TEST_PASS; + } + } + + return result; +} + +int wmt_step_test_check_create_value(struct step_value_action *p_val_act, + int check_params[], char *err_result) +{ + int result = TEST_FAIL; + + if (p_val_act->base.action_id != STEP_ACTION_INDEX_VALUE) { + WMT_ERR_FUNC("%s, id wrong: %d\n", err_result, p_val_act->base.action_id); + result = TEST_FAIL; + } else if (p_val_act->temp_reg_id != check_params[0] || + p_val_act->value != check_params[1]) { + WMT_ERR_FUNC("%s, param failed: %d %d expect(%d %d)", + err_result, p_val_act->temp_reg_id, p_val_act->value, + check_params[0], check_params[1]); + result = TEST_FAIL; + } else { + result = TEST_PASS; + } + + return result; +} + +void wmt_step_test_check_emi_act(unsigned int len, ...) +{ + unsigned int offset; + unsigned int check_result; + unsigned int value; + PUINT8 p_virtual_addr = NULL; + va_list args; + + if (g_step_test_check.step_check_result == TEST_FAIL) + return; + + offset = g_step_test_check.step_check_emi_offset[g_step_test_check.step_check_index]; + p_virtual_addr = wmt_plat_get_emi_virt_add(offset); + if (!p_virtual_addr) { + g_step_test_check.step_check_result = TEST_FAIL; + WMT_ERR_FUNC("STEP test failed: p_virtual_addr offset(%d) is null", offset); + return; + } + check_result = CONSYS_REG_READ(p_virtual_addr); + + va_start(args, len); + value = va_arg(args, unsigned int); + va_end(args); + + if (check_result == value) { + g_step_test_check.step_check_result = TEST_PASS; + } else { + WMT_ERR_FUNC("STEP test failed: Value is %d, expect %d", value, check_result); + g_step_test_check.step_check_result = TEST_FAIL; + return; + } + + if (g_step_test_check.step_check_temp_register_id != -1) { + if (g_step_env.temp_register[g_step_test_check.step_check_temp_register_id] != + (check_result & g_step_test_check.step_test_mask)) { + WMT_ERR_FUNC("STEP test failed: Register id(%d) value is %d, expect %d mask 0x%08x", + g_step_test_check.step_check_temp_register_id, + g_step_env.temp_register[g_step_test_check.step_check_temp_register_id], + check_result, g_step_test_check.step_test_mask); + g_step_test_check.step_check_result = TEST_FAIL; + } + } + + g_step_test_check.step_check_index++; +} + +void wmt_step_test_check_reg_read_act(unsigned int len, ...) +{ + unsigned int check_result; + unsigned int value; + va_list args; + + if (g_step_test_check.step_check_result == TEST_FAIL) + return; + + va_start(args, len); + value = va_arg(args, unsigned int); + check_result = CONSYS_REG_READ(g_step_test_check.step_check_register_addr); + + if (check_result == value) { + g_step_test_check.step_check_result = TEST_PASS; + } else { + WMT_ERR_FUNC("STEP test failed: Value is %d, expect %d(0x%08x)", value, check_result, + (unsigned int)g_step_test_check.step_check_register_addr); + g_step_test_check.step_check_result = TEST_FAIL; + } + + if (g_step_test_check.step_check_temp_register_id != -1) { + if (g_step_env.temp_register[g_step_test_check.step_check_temp_register_id] != + (check_result & g_step_test_check.step_test_mask)) { + WMT_ERR_FUNC("STEP test failed: Register id(%d) value is %d, expect %d", + g_step_test_check.step_check_temp_register_id, + g_step_env.temp_register[g_step_test_check.step_check_temp_register_id], + check_result); + g_step_test_check.step_check_result = TEST_FAIL; + } + } + + va_end(args); +} + +void wmt_step_test_check_reg_write_act(unsigned int len, ...) +{ + unsigned int value; + va_list args; + unsigned int mask = g_step_test_check.step_test_mask; + + va_start(args, len); + value = va_arg(args, unsigned int); + + if (value == 0xdeadfeed) { + g_step_test_check.step_check_result = TEST_PASS; + } else if (mask == 0xFFFFFFFF) { + if (g_step_test_check.step_check_write_value == value) { + g_step_test_check.step_check_result = TEST_PASS; + } else { + WMT_ERR_FUNC("STEP test failed: Value is %d, expect %zu", value, + g_step_test_check.step_check_write_value); + g_step_test_check.step_check_result = TEST_FAIL; + } + } else { + if ((mask & value) != (mask & g_step_test_check.step_check_write_value)) { + WMT_ERR_FUNC("STEP test failed: Overrite:%d, expect:%zu origin %d mask %d", + value, + g_step_test_check.step_check_write_value, + g_step_test_check.step_recovery_value, + mask); + g_step_test_check.step_check_result = TEST_FAIL; + } else if ((~mask & value) != (~mask & g_step_test_check.step_recovery_value)) { + WMT_ERR_FUNC("STEP test failed: No change:%d, expect:%zu origin %d mask %d", + value, + g_step_test_check.step_check_write_value, + g_step_test_check.step_recovery_value, + mask); + g_step_test_check.step_check_result = TEST_FAIL; + } else { + g_step_test_check.step_check_result = TEST_PASS; + } + } + + va_end(args); +} + +void wmt_step_test_check_show_act(unsigned int len, ...) +{ + char *content = NULL; + va_list args; + + va_start(args, len); + content = va_arg(args, char*); + if (content == NULL || g_step_test_check.step_check_result_string == NULL) { + WMT_ERR_FUNC("STEP test failed: content is NULL"); + g_step_test_check.step_check_result = TEST_FAIL; + } else if (osal_strcmp(content, g_step_test_check.step_check_result_string) == 0) { + g_step_test_check.step_check_result = TEST_PASS; + } else { + WMT_ERR_FUNC("STEP test failed: content(%s), expect(%s)", + content, g_step_test_check.step_check_result_string); + g_step_test_check.step_check_result = TEST_FAIL; + } + va_end(args); +} + +void wmt_step_test_check_condition_act(unsigned int len, ...) +{ + int value; + va_list args; + + va_start(args, len); + value = va_arg(args, int); + if (value == g_step_test_check.step_check_result_value) { + g_step_test_check.step_check_result = TEST_PASS; + } else { + WMT_ERR_FUNC("STEP test failed: value(%d), expect(%d)", + value, g_step_test_check.step_check_result_value); + g_step_test_check.step_check_result = TEST_FAIL; + } + va_end(args); +} + +void wmt_step_test_check_value_act(unsigned int len, ...) +{ + int value; + va_list args; + + va_start(args, len); + value = va_arg(args, int); + if (value == g_step_test_check.step_check_result_value) { + g_step_test_check.step_check_result = TEST_PASS; + } else { + WMT_ERR_FUNC("STEP test failed: value(%d), expect(%d)", + value, g_step_test_check.step_check_result_value); + g_step_test_check.step_check_result = TEST_FAIL; + } + va_end(args); +} + +void wmt_step_test_clear_check_data(void) +{ + unsigned int i = 0, j = 0; + + for (i = 0; i < STEP_TEST_ACTION_NUMBER; i++) { + g_step_test_check.step_check_test_tp_id[i] = 0; + g_step_test_check.step_check_test_act_id[i] = 0; + g_step_test_check.step_check_params_num[i] = 0; + g_step_test_check.step_check_emi_offset[i] = 0; + for (j = 0; j < STEP_PARAMETER_SIZE; j++) + g_step_test_check.step_check_params[i][j] = ""; + } + + g_step_test_check.step_check_total = 0; + g_step_test_check.step_check_index = 0; + g_step_test_check.step_check_result = TEST_PASS; + g_step_test_check.step_check_register_addr = 0; + g_step_test_check.step_test_mask = 0xFFFFFFFF; + g_step_test_check.step_recovery_value = 0; + g_step_test_check.step_check_result_value = 0; + g_step_test_check.step_check_temp_register_id = -1; +} + +void wmt_step_test_clear_temp_register(void) +{ + int i; + + for (i = 0; i < STEP_TEMP_REGISTER_SIZE; i++) + g_step_env.temp_register[i] = 0; +} + +#define STEP_CAN_WRITE_UNKNOWN 0 +#define STEP_CAN_WRITE_YES 1 +#define STEP_CAN_WRITE_NO 2 +int wmt_step_test_is_can_write(SIZE_T addr, unsigned int mask) +{ + unsigned int before, after; + int ret = STEP_CAN_WRITE_UNKNOWN; + + before = CONSYS_REG_READ(addr); + CONSYS_REG_WRITE_MASK(addr, 0xFFFFFFFF, mask); + after = CONSYS_REG_READ(addr); + if ((after & mask) != (0xFFFFFFFF & mask)) + ret = STEP_CAN_WRITE_NO; + + CONSYS_REG_WRITE_MASK(addr, 0x0, mask); + after = CONSYS_REG_READ(addr); + if ((after & mask) != (0x0 & mask)) + ret = STEP_CAN_WRITE_NO; + + CONSYS_REG_WRITE_MASK(addr, before, mask); + if (ret != STEP_CAN_WRITE_NO) + ret = STEP_CAN_WRITE_YES; + + return ret; +} + +int wmt_step_test_find_can_write_register(SIZE_T addr, int max, unsigned int mask) +{ + int i; + int write_able; + + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + return -1; + } + + for (i = 0x0; i < max; i += 0x4) { + write_able = wmt_step_test_is_can_write(addr + i, mask); + if (write_able == STEP_CAN_WRITE_YES) { + ENABLE_PSM_MONITOR(); + return i; + } + } + ENABLE_PSM_MONITOR(); + + return -1; +} + +void wmt_step_test_update_result(int result, struct step_test_report *p_report, char *err_result) +{ + if (result != TEST_FAIL) { + p_report->pass++; + } else { + WMT_ERR_FUNC("%s", err_result); + p_report->fail++; + } +} + +void wmt_step_test_update_result_report(struct step_test_report *p_dest_report, + struct step_test_report *p_src_report) +{ + p_dest_report->pass += p_src_report->pass; + p_dest_report->fail += p_src_report->fail; + p_dest_report->check += p_src_report->check; +} + +void wmt_step_test_show_result_report(char *test_name, struct step_test_report *p_report, int sec_begin, int usec_begin, + int sec_end, int usec_end) +{ + unsigned int total = 0; + unsigned int pass = 0; + unsigned int fail = 0; + unsigned int check = 0; + int sec = 0; + int usec = 0; + + pass = p_report->pass; + fail = p_report->fail; + check = p_report->check; + + if (usec_end >= usec_begin) { + sec = sec_end - sec_begin; + usec = usec_end - usec_begin; + } else { + sec = sec_end - sec_begin - 1; + usec = usec_end - usec_begin + 1000000; + } + + total = pass + fail + check; + WMT_INFO_FUNC("%s Total: %d, PASS: %d, FAIL: %d, CHECK: %d, Spend Time: %d.%.6d\n", + test_name, total, pass, fail, check, sec, usec); +} + +void __wmt_step_test_parse_data(const char *buf, struct step_test_report *p_report, char *err_result) +{ + wmt_step_parse_data(buf, osal_strlen((char *)buf), wmt_step_test_check_write_tp); + if (g_step_test_check.step_check_total != g_step_test_check.step_check_index) { + WMT_ERR_FUNC("STEP test failed: index %d: expect total %d\n", g_step_test_check.step_check_index, + g_step_test_check.step_check_total); + g_step_test_check.step_check_result = TEST_FAIL; + } + wmt_step_test_update_result(g_step_test_check.step_check_result, p_report, err_result); +} + +void __wmt_step_test_create_action(enum step_action_id act_id, int param_num, char *params[], int result_of_action, + int check_params[], struct step_test_report *p_report, char *err_result) +{ + struct step_action *p_act = NULL; + int result = TEST_FAIL; + + p_act = wmt_step_create_action(act_id, param_num, params); + if (p_act != NULL) { + switch (p_act->action_id) { + case STEP_ACTION_INDEX_EMI: + { + struct step_emi_action *p_emi_act = NULL; + + p_emi_act = list_entry_action(emi, p_act); + result = wmt_step_test_check_create_emi(p_emi_act, check_params, + err_result); + } + break; + case STEP_ACTION_INDEX_REGISTER: + { + struct step_register_action *p_reg_act = NULL; + + p_reg_act = list_entry_action(register, p_act); + result = wmt_step_test_check_create_reg(p_reg_act, check_params, + err_result); + } + break; + case STEP_ACTION_INDEX_GPIO: + { + struct step_gpio_action *p_gpio_act = NULL; + + p_gpio_act = list_entry_action(gpio, p_act); + result = wmt_step_test_check_create_gpio(p_gpio_act, check_params, + err_result); + } + break; + case STEP_ACTION_INDEX_DISABLE_RESET: + { + struct step_disable_reset_action *p_drst_act = NULL; + + p_drst_act = list_entry_action(disable_reset, p_act); + result = wmt_step_test_check_create_drst(p_drst_act, + check_params, err_result); + } + break; + case STEP_ACTION_INDEX_CHIP_RESET: + { + struct step_chip_reset_action *p_crst_act = NULL; + + p_crst_act = list_entry_action(chip_reset, p_act); + result = wmt_step_test_check_create_crst(p_crst_act, + check_params, err_result); + } + break; + case STEP_ACTION_INDEX_KEEP_WAKEUP: + { + struct step_keep_wakeup_action *p_kwak_act = NULL; + + p_kwak_act = list_entry_action(keep_wakeup, p_act); + result = wmt_step_test_check_create_keep_wakeup(p_kwak_act, + check_params, err_result); + } + break; + case STEP_ACTION_INDEX_CANCEL_WAKEUP: + { + struct step_cancel_wakeup_action *p_cwak_act = NULL; + + p_cwak_act = list_entry_action(cancel_wakeup, p_act); + result = wmt_step_test_check_create_cancel_wakeup(p_cwak_act, + check_params, err_result); + } + break; + case STEP_ACTION_INDEX_PERIODIC_DUMP: + { + struct step_periodic_dump_action *p_pd_act = NULL; + + p_pd_act = list_entry_action(periodic_dump, p_act); + result = wmt_step_test_check_create_periodic_dump(p_pd_act, + check_params, err_result); + } + break; + case STEP_ACTION_INDEX_SHOW_STRING: + { + struct step_show_string_action *p_show_act = NULL; + + p_show_act = list_entry_action(show_string, p_act); + result = wmt_step_test_check_create_show_string(p_show_act, + check_params, err_result); + } + break; + case STEP_ACTION_INDEX_SLEEP: + { + struct step_sleep_action *p_sleep_act = NULL; + + p_sleep_act = list_entry_action(sleep, p_act); + result = wmt_step_test_check_create_sleep(p_sleep_act, + check_params, err_result); + } + break; + case STEP_ACTION_INDEX_CONDITION: + { + struct step_condition_action *p_cond_act = NULL; + + p_cond_act = list_entry_action(condition, p_act); + result = wmt_step_test_check_create_condition(p_cond_act, + check_params, err_result); + } + break; + case STEP_ACTION_INDEX_VALUE: + { + struct step_value_action *p_val_act = NULL; + + p_val_act = list_entry_action(value, p_act); + result = wmt_step_test_check_create_value(p_val_act, + check_params, err_result); + } + break; + case STEP_ACTION_INDEX_CONDITION_EMI: + { + struct step_condition_emi_action *p_cond_emi_act = NULL; + + p_cond_emi_act = list_entry_action(condition_emi, p_act); + result = wmt_step_test_check_create_condition_emi(p_cond_emi_act, check_params, + err_result); + } + break; + case STEP_ACTION_INDEX_CONDITION_REGISTER: + { + struct step_condition_register_action *p_cond_reg_act = NULL; + + p_cond_reg_act = list_entry_action(condition_register, p_act); + result = wmt_step_test_check_create_condition_reg(p_cond_reg_act, check_params, + err_result); + } + break; + default: + result = TEST_FAIL; + break; + } + + if (result_of_action == -1) + result = TEST_FAIL; + + wmt_step_remove_action(p_act); + } else { + if (result_of_action == -1) + result = TEST_PASS; + else + result = TEST_FAIL; + } + wmt_step_test_update_result(result, p_report, err_result); +} + +void __wmt_step_test_do_emi_action(enum step_action_id act_id, int param_num, char *params[], int result_of_action, + struct step_test_report *p_report, char *err_result) +{ + struct step_action *p_act = NULL; + + p_act = wmt_step_create_action(act_id, param_num, params); + if (p_act != NULL) { + if (wmt_step_do_emi_action(p_act, wmt_step_test_check_emi_act) == + result_of_action) { + if (g_step_test_check.step_check_total != g_step_test_check.step_check_index) { + p_report->fail++; + WMT_ERR_FUNC("%s, index %d: expect total %d\n", err_result, + g_step_test_check.step_check_index, g_step_test_check.step_check_total); + } else if (g_step_test_check.step_check_result == TEST_PASS) { + p_report->pass++; + } else { + p_report->fail++; + WMT_ERR_FUNC("%s\n", err_result); + } + } else { + WMT_ERR_FUNC("%s, expect result is %d\n", err_result, result_of_action); + p_report->fail++; + } + wmt_step_remove_action(p_act); + } else { + if (result_of_action == -1) { + p_report->pass++; + } else { + p_report->fail++; + WMT_ERR_FUNC("%s, Create failed\n", err_result); + } + } +} + +void __wmt_step_test_do_cond_emi_action(enum step_action_id act_id, int param_num, char *params[], int result_of_action, + struct step_test_report *p_report, char *err_result) +{ + struct step_action *p_act = NULL; + + p_act = wmt_step_create_action(act_id, param_num, params); + if (p_act != NULL) { + if (wmt_step_do_condition_emi_action(p_act, wmt_step_test_check_emi_act) == + result_of_action) { + if (g_step_test_check.step_check_total != g_step_test_check.step_check_index) { + p_report->fail++; + WMT_ERR_FUNC("%s, index %d: expect total %d\n", err_result, + g_step_test_check.step_check_index, g_step_test_check.step_check_total); + } else if (g_step_test_check.step_check_result == TEST_PASS) { + p_report->pass++; + } else { + p_report->fail++; + WMT_ERR_FUNC("%s\n", err_result); + } + } else { + WMT_ERR_FUNC("%s, expect result is %d\n", err_result, result_of_action); + p_report->fail++; + } + wmt_step_remove_action(p_act); + } else { + if (result_of_action == -1) { + p_report->pass++; + } else { + p_report->fail++; + WMT_ERR_FUNC("%s, Create failed\n", err_result); + } + } +} + + +void __wmt_step_test_do_register_action(enum step_action_id act_id, int param_num, char *params[], int result_of_action, + struct step_test_report *p_report, char *err_result) +{ + struct step_action *p_act = NULL; + int result; + + p_act = wmt_step_create_action(act_id, param_num, params); + if (p_act != NULL) { + if (osal_strcmp(params[0], "1") == 0) { + /* Write register test */ + if (g_step_test_check.step_check_register_addr != 0) { + g_step_test_check.step_recovery_value = + CONSYS_REG_READ(g_step_test_check.step_check_register_addr); + } + result = wmt_step_do_register_action(p_act, wmt_step_test_check_reg_write_act); + if (result == result_of_action) { + if (g_step_test_check.step_check_result == TEST_PASS) { + p_report->pass++; + } else { + p_report->fail++; + WMT_ERR_FUNC("%s\n", err_result); + } + } else if (result == -2) { + p_report->check++; + WMT_INFO_FUNC("STEP check: %s, no clock is ok?\n", err_result); + } else { + WMT_ERR_FUNC("%s, expect result is %d\n", err_result, + result_of_action); + p_report->fail++; + } + if (g_step_test_check.step_check_register_addr != 0) { + CONSYS_REG_WRITE(g_step_test_check.step_check_register_addr, + g_step_test_check.step_recovery_value); + } + } else { + /* Read register test */ + g_step_test_check.step_check_result = TEST_PASS; + result = wmt_step_do_register_action(p_act, wmt_step_test_check_reg_read_act); + if (result == result_of_action) { + if (g_step_test_check.step_check_result == TEST_PASS) { + p_report->pass++; + } else { + p_report->fail++; + WMT_ERR_FUNC("%s\n", err_result); + } + } else if (result == -2) { + p_report->check++; + WMT_INFO_FUNC("STEP check: %s, no clock is ok?\n", err_result); + } else { + WMT_ERR_FUNC("%s, expect result is %d\n", err_result, + result_of_action); + p_report->fail++; + } + } + wmt_step_remove_action(p_act); + } else { + if (result_of_action == -1) { + p_report->pass++; + } else { + p_report->fail++; + WMT_ERR_FUNC("%s, Create failed\n", err_result); + } + } +} + +void __wmt_step_test_do_cond_register_action(enum step_action_id act_id, int param_num, + char *params[], int result_of_action, + struct step_test_report *p_report, char *err_result) +{ + struct step_action *p_act = NULL; + int result; + + p_act = wmt_step_create_action(act_id, param_num, params); + if (p_act != NULL) { + if (osal_strcmp(params[1], "1") == 0) { + /* Write register test */ + if (g_step_test_check.step_check_register_addr != 0) { + g_step_test_check.step_recovery_value = + CONSYS_REG_READ(g_step_test_check.step_check_register_addr); + } + + result = wmt_step_do_condition_register_action(p_act, wmt_step_test_check_reg_write_act); + if (result == result_of_action) { + if (g_step_test_check.step_check_result == TEST_PASS) { + p_report->pass++; + } else { + p_report->fail++; + WMT_ERR_FUNC("%s\n", err_result); + } + } else if (result == -2) { + p_report->check++; + WMT_INFO_FUNC("STEP check: %s, no clock is ok?\n", err_result); + } else { + WMT_ERR_FUNC("%s, expect result is %d\n", err_result, result_of_action); + p_report->fail++; + } + if (g_step_test_check.step_check_register_addr != 0) { + CONSYS_REG_WRITE(g_step_test_check.step_check_register_addr, + g_step_test_check.step_recovery_value); + } + } else { + /* Read register test */ + g_step_test_check.step_check_result = TEST_PASS; + result = wmt_step_do_condition_register_action(p_act, wmt_step_test_check_reg_read_act); + if (result == result_of_action) { + if (g_step_test_check.step_check_result == TEST_PASS) { + p_report->pass++; + } else { + p_report->fail++; + WMT_ERR_FUNC("%s\n", err_result); + } + } else if (result == -2) { + p_report->check++; + WMT_INFO_FUNC("STEP check: %s, no clock is ok?\n", err_result); + } else { + WMT_ERR_FUNC("%s, expect result is %d\n", err_result, result_of_action); + p_report->fail++; + } + } + wmt_step_remove_action(p_act); + } else { + if (result_of_action == -1) { + p_report->pass++; + } else { + p_report->fail++; + WMT_ERR_FUNC("%s, Create failed\n", err_result); + } + } +} + +void wmt_step_test_all(void) +{ + struct step_test_report report = {0, 0, 0}; + bool is_enable_step = g_step_env.is_enable; + int sec_begin = 0; + int usec_begin = 0; + int sec_end = 0; + int usec_end = 0; + + report.pass = 0; + report.fail = 0; + report.check = 0; + + WMT_INFO_FUNC("STEP test: All start\n"); + osal_gettimeofday(&sec_begin, &usec_begin); + g_step_env.is_enable = 0; + wmt_step_test_read_file(&report); + g_step_env.is_enable = 1; + wmt_step_test_create_emi_action(&report); + wmt_step_test_create_cond_emi_action(&report); + wmt_step_test_create_register_action(&report); + wmt_step_test_create_cond_register_action(&report); + wmt_step_test_check_register_symbol(&report); + wmt_step_test_create_other_action(&report); + wmt_step_test_parse_data(&report); + wmt_step_test_do_emi_action(&report); + wmt_step_test_do_cond_emi_action(&report); + wmt_step_test_do_register_action(&report); + wmt_step_test_do_cond_register_action(&report); + wmt_step_test_do_gpio_action(&report); + wmt_step_test_do_wakeup_action(&report); + wmt_step_test_create_periodic_dump(&report); + wmt_step_test_do_show_action(&report); + wmt_step_test_do_sleep_action(&report); + wmt_step_test_do_condition_action(&report); + wmt_step_test_do_value_action(&report); + + wmt_step_test_do_chip_reset_action(&report); + g_step_env.is_enable = is_enable_step; + + osal_gettimeofday(&sec_end, &usec_end); + wmt_step_test_show_result_report("STEP result: All result", + &report, sec_begin, usec_begin, sec_end, usec_end); +} + +void wmt_step_test_read_file(struct step_test_report *p_report) +{ + struct step_test_report temp_report = {0, 0, 0}; + int sec_begin = 0; + int usec_begin = 0; + int sec_end = 0; + int usec_end = 0; + + WMT_INFO_FUNC("STEP test: Read file start\n"); + osal_gettimeofday(&sec_begin, &usec_begin); + /******************************** + ******** Test case 1 *********** + ******* Wrong file name ******** + ********************************/ + if (-1 == wmt_step_read_file("wmt_failed.cfg")) { + temp_report.pass++; + } else { + WMT_ERR_FUNC("STEP test failed: (Read file TC-1) expect no file\n"); + temp_report.fail++; + } + + osal_gettimeofday(&sec_end, &usec_end); + wmt_step_test_show_result_report("STEP result: Read file result", + &temp_report, sec_begin, usec_begin, sec_end, usec_end); + wmt_step_test_update_result_report(p_report, &temp_report); +} + +void wmt_step_test_parse_data(struct step_test_report *p_report) +{ + char *buf = NULL; + struct step_test_report temp_report = {0, 0, 0}; + int sec_begin = 0; + int usec_begin = 0; + int sec_end = 0; + int usec_end = 0; + + WMT_INFO_FUNC("STEP test: Parse data start\n"); + osal_gettimeofday(&sec_begin, &usec_begin); + /******************************** + ******** Test case 1 *********** + ******** Normal case *********** + ********************************/ + WMT_INFO_FUNC("STEP test: TC 1\n"); + wmt_step_test_clear_check_data(); + + buf = + "// TEST NOW\r\n" + "\r\n" + "[TP 1] When Command timeout\r\n" + "[AT] _EMI 0 0x50 0x9c\r\n" + "[AT] _REG 0 0x08 5 2\r\n" + "[AT] DRST\r\n" + "[AT] _RST\r\n" + "[TP 2] When Firmware trigger assert\r\n" + "[AT] _REG 1 0x08 30\r\n" + "[AT] GPIO 0 8\r\n" + "[AT] GPIO 1 6 3\r\n" + "[AT] WAK+\r\n" + "[AT] WAK-\r\n" + "[AT] _REG 1 0x08 30 0xFF00FF00\r\n" + "[TP 3] Before Chip reset\r\n" + "[AT] SHOW Hello_World\r\n" + "[AT] _SLP 1000\r\n" + "[AT] COND $1 $2 == $3\r\n" + "[AT] COND $1 $2 == 16\r\n" + "[AT] _VAL $0 0x66\r\n" + "[TP 4] After Chip reset\r\n" + "[AT] _EMI 0 0x50 0xFFFFFFFF $1\r\n" + "[AT] _REG 0 0x08 0xFFFFFFFF $1\r\n" + "[AT] CEMI $2 0 0x50 0xFFFFFFFF $1\r\n" + "[AT] CREG $2 0 0x08 0xFFFFFFFF $1\r\n" + "\r\n"; + + g_step_test_check.step_check_total = 19; + g_step_test_check.step_check_test_tp_id[0] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[0] = STEP_ACTION_INDEX_EMI; + g_step_test_check.step_check_test_tp_id[1] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[1] = STEP_ACTION_INDEX_REGISTER; + g_step_test_check.step_check_test_tp_id[2] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[2] = STEP_ACTION_INDEX_DISABLE_RESET; + g_step_test_check.step_check_test_tp_id[3] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[3] = STEP_ACTION_INDEX_CHIP_RESET; + g_step_test_check.step_check_test_tp_id[4] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[4] = STEP_ACTION_INDEX_REGISTER; + g_step_test_check.step_check_test_tp_id[5] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[5] = STEP_ACTION_INDEX_GPIO; + g_step_test_check.step_check_test_tp_id[6] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[6] = STEP_ACTION_INDEX_GPIO; + g_step_test_check.step_check_test_tp_id[7] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[7] = STEP_ACTION_INDEX_KEEP_WAKEUP; + g_step_test_check.step_check_test_tp_id[8] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[8] = STEP_ACTION_INDEX_CANCEL_WAKEUP; + g_step_test_check.step_check_test_tp_id[9] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[9] = STEP_ACTION_INDEX_REGISTER; + g_step_test_check.step_check_test_tp_id[10] = STEP_TRIGGER_POINT_BEFORE_CHIP_RESET; + g_step_test_check.step_check_test_act_id[10] = STEP_ACTION_INDEX_SHOW_STRING; + g_step_test_check.step_check_test_tp_id[11] = STEP_TRIGGER_POINT_BEFORE_CHIP_RESET; + g_step_test_check.step_check_test_act_id[11] = STEP_ACTION_INDEX_SLEEP; + g_step_test_check.step_check_test_tp_id[12] = STEP_TRIGGER_POINT_BEFORE_CHIP_RESET; + g_step_test_check.step_check_test_act_id[12] = STEP_ACTION_INDEX_CONDITION; + g_step_test_check.step_check_test_tp_id[13] = STEP_TRIGGER_POINT_BEFORE_CHIP_RESET; + g_step_test_check.step_check_test_act_id[13] = STEP_ACTION_INDEX_CONDITION; + g_step_test_check.step_check_test_tp_id[14] = STEP_TRIGGER_POINT_BEFORE_CHIP_RESET; + g_step_test_check.step_check_test_act_id[14] = STEP_ACTION_INDEX_VALUE; + g_step_test_check.step_check_test_tp_id[15] = STEP_TRIGGER_POINT_AFTER_CHIP_RESET; + g_step_test_check.step_check_test_act_id[15] = STEP_ACTION_INDEX_EMI; + g_step_test_check.step_check_test_tp_id[16] = STEP_TRIGGER_POINT_AFTER_CHIP_RESET; + g_step_test_check.step_check_test_act_id[16] = STEP_ACTION_INDEX_REGISTER; + g_step_test_check.step_check_test_tp_id[17] = STEP_TRIGGER_POINT_AFTER_CHIP_RESET; + g_step_test_check.step_check_test_act_id[17] = STEP_ACTION_INDEX_CONDITION_EMI; + g_step_test_check.step_check_test_tp_id[18] = STEP_TRIGGER_POINT_AFTER_CHIP_RESET; + g_step_test_check.step_check_test_act_id[18] = STEP_ACTION_INDEX_CONDITION_REGISTER; + + g_step_test_check.step_check_params[0][0] = "0"; + g_step_test_check.step_check_params[0][1] = "0x50"; + g_step_test_check.step_check_params[0][2] = "0x9c"; + g_step_test_check.step_check_params_num[0] = 3; + g_step_test_check.step_check_params[1][0] = "0"; + g_step_test_check.step_check_params[1][1] = "0x08"; + g_step_test_check.step_check_params[1][2] = "5"; + g_step_test_check.step_check_params[1][3] = "2"; + g_step_test_check.step_check_params_num[1] = 4; + g_step_test_check.step_check_params[4][0] = "1"; + g_step_test_check.step_check_params[4][1] = "0x08"; + g_step_test_check.step_check_params[4][2] = "30"; + g_step_test_check.step_check_params_num[4] = 3; + g_step_test_check.step_check_params[5][0] = "0"; + g_step_test_check.step_check_params[5][1] = "8"; + g_step_test_check.step_check_params_num[5] = 2; + g_step_test_check.step_check_params[6][0] = "1"; + g_step_test_check.step_check_params[6][1] = "6"; + g_step_test_check.step_check_params[6][2] = "3"; + g_step_test_check.step_check_params_num[6] = 3; + g_step_test_check.step_check_params[9][0] = "1"; + g_step_test_check.step_check_params[9][1] = "0x08"; + g_step_test_check.step_check_params[9][2] = "30"; + g_step_test_check.step_check_params[9][3] = "0xFF00FF00"; + g_step_test_check.step_check_params_num[9] = 4; + g_step_test_check.step_check_params[10][0] = "Hello_World"; + g_step_test_check.step_check_params_num[10] = 1; + g_step_test_check.step_check_params[11][0] = "1000"; + g_step_test_check.step_check_params_num[11] = 1; + g_step_test_check.step_check_params[12][0] = "$1"; + g_step_test_check.step_check_params[12][1] = "$2"; + g_step_test_check.step_check_params[12][2] = "=="; + g_step_test_check.step_check_params[12][3] = "$3"; + g_step_test_check.step_check_params_num[12] = 4; + g_step_test_check.step_check_params[13][0] = "$1"; + g_step_test_check.step_check_params[13][1] = "$2"; + g_step_test_check.step_check_params[13][2] = "=="; + g_step_test_check.step_check_params[13][3] = "16"; + g_step_test_check.step_check_params_num[13] = 4; + g_step_test_check.step_check_params[14][0] = "$0"; + g_step_test_check.step_check_params[14][1] = "0x66"; + g_step_test_check.step_check_params_num[14] = 2; + g_step_test_check.step_check_params[15][0] = "0"; + g_step_test_check.step_check_params[15][1] = "0x50"; + g_step_test_check.step_check_params[15][2] = "0xFFFFFFFF"; + g_step_test_check.step_check_params[15][3] = "$1"; + g_step_test_check.step_check_params_num[15] = 4; + g_step_test_check.step_check_params[16][0] = "0"; + g_step_test_check.step_check_params[16][1] = "0x08"; + g_step_test_check.step_check_params[16][2] = "0xFFFFFFFF"; + g_step_test_check.step_check_params[16][3] = "$1"; + g_step_test_check.step_check_params_num[16] = 4; + g_step_test_check.step_check_params[17][0] = "$2"; + g_step_test_check.step_check_params[17][1] = "0"; + g_step_test_check.step_check_params[17][2] = "0x50"; + g_step_test_check.step_check_params[17][3] = "0xFFFFFFFF"; + g_step_test_check.step_check_params[17][4] = "$1"; + g_step_test_check.step_check_params_num[17] = 5; + g_step_test_check.step_check_params[18][0] = "$2"; + g_step_test_check.step_check_params[18][1] = "0"; + g_step_test_check.step_check_params[18][2] = "0x08"; + g_step_test_check.step_check_params[18][3] = "0xFFFFFFFF"; + g_step_test_check.step_check_params[18][4] = "$1"; + g_step_test_check.step_check_params_num[18] = 5; + __wmt_step_test_parse_data(buf, &temp_report, + "STEP test case failed: (Parse data TC-1) Normal case\n"); + + /********************************* + ******** Test case 2 ************ + ** Normal case with some space ** + *********************************/ + WMT_INFO_FUNC("STEP test: TC 2\n"); + wmt_step_test_clear_check_data(); + buf = + "// TEST NOW\r\n" + "\r\n" + "[TP 1] When Command timeout\r\n" + "[AT] _EMI 0 0x50 0x9c \r\n" + "[AT] _REG 0 0x08 5 2\r\n" + "[AT] DRST\r\n" + "[AT] _RST\r\n" + " [PD+] 2\r\n" + " [AT] _EMI 0 0x50 0x9c\r\n" + " [PD-] \r\n" + " [TP 2] When Firmware trigger assert\r\n" + "[AT] _REG 1 0x08 30\r\n" + "[AT] GPIO 0 8\r\n" + " [AT] GPIO 1 6 3\r\n" + " [AT] WAK+\r\n" + " [AT] WAK-\r\n" + " [PD+] 5\r\n" + " [AT] _EMI 0 0x50 0x9c\r\n" + " [PD-] \r\n" + "[TP 3] Before Chip reset\r\n" + " [AT] SHOW Hello\r\n" + "[AT] _SLP 1000\r\n" + " [AT] COND $1 $2 == $3\r\n" + " [AT] _VAL $0 0x66\r\n" + "[TP 4] After Chip reset\r\n" + "[AT] CEMI $2 0 0x50 0xFFFFFFFF $1\r\n" + " [AT] CREG $2 0 0x08 0xFFFFFFFF $1\r\n" + "\r\n"; + + g_step_test_check.step_check_total = 19; + g_step_test_check.step_check_test_tp_id[0] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[0] = STEP_ACTION_INDEX_EMI; + g_step_test_check.step_check_test_tp_id[1] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[1] = STEP_ACTION_INDEX_REGISTER; + g_step_test_check.step_check_test_tp_id[2] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[2] = STEP_ACTION_INDEX_DISABLE_RESET; + g_step_test_check.step_check_test_tp_id[3] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[3] = STEP_ACTION_INDEX_CHIP_RESET; + g_step_test_check.step_check_test_tp_id[4] = -1; + g_step_test_check.step_check_test_act_id[4] = STEP_ACTION_INDEX_EMI; + g_step_test_check.step_check_test_tp_id[5] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[5] = STEP_ACTION_INDEX_PERIODIC_DUMP; + g_step_test_check.step_check_test_tp_id[6] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[6] = STEP_ACTION_INDEX_REGISTER; + g_step_test_check.step_check_test_tp_id[7] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[7] = STEP_ACTION_INDEX_GPIO; + g_step_test_check.step_check_test_tp_id[8] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[8] = STEP_ACTION_INDEX_GPIO; + g_step_test_check.step_check_test_tp_id[9] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[9] = STEP_ACTION_INDEX_KEEP_WAKEUP; + g_step_test_check.step_check_test_tp_id[10] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[10] = STEP_ACTION_INDEX_CANCEL_WAKEUP; + g_step_test_check.step_check_test_tp_id[11] = -1; + g_step_test_check.step_check_test_act_id[11] = STEP_ACTION_INDEX_EMI; + g_step_test_check.step_check_test_tp_id[12] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[12] = STEP_ACTION_INDEX_PERIODIC_DUMP; + g_step_test_check.step_check_test_tp_id[13] = STEP_TRIGGER_POINT_BEFORE_CHIP_RESET; + g_step_test_check.step_check_test_act_id[13] = STEP_ACTION_INDEX_SHOW_STRING; + g_step_test_check.step_check_test_tp_id[14] = STEP_TRIGGER_POINT_BEFORE_CHIP_RESET; + g_step_test_check.step_check_test_act_id[14] = STEP_ACTION_INDEX_SLEEP; + g_step_test_check.step_check_test_tp_id[15] = STEP_TRIGGER_POINT_BEFORE_CHIP_RESET; + g_step_test_check.step_check_test_act_id[15] = STEP_ACTION_INDEX_CONDITION; + g_step_test_check.step_check_test_tp_id[16] = STEP_TRIGGER_POINT_BEFORE_CHIP_RESET; + g_step_test_check.step_check_test_act_id[16] = STEP_ACTION_INDEX_VALUE; + g_step_test_check.step_check_test_tp_id[17] = STEP_TRIGGER_POINT_AFTER_CHIP_RESET; + g_step_test_check.step_check_test_act_id[17] = STEP_ACTION_INDEX_CONDITION_EMI; + g_step_test_check.step_check_test_tp_id[18] = STEP_TRIGGER_POINT_AFTER_CHIP_RESET; + g_step_test_check.step_check_test_act_id[18] = STEP_ACTION_INDEX_CONDITION_REGISTER; + g_step_test_check.step_check_params[0][0] = "0"; + g_step_test_check.step_check_params[0][1] = "0x50"; + g_step_test_check.step_check_params[0][2] = "0x9c"; + g_step_test_check.step_check_params_num[0] = 3; + g_step_test_check.step_check_params[1][0] = "0"; + g_step_test_check.step_check_params[1][1] = "0x08"; + g_step_test_check.step_check_params[1][2] = "5"; + g_step_test_check.step_check_params[1][3] = "2"; + g_step_test_check.step_check_params_num[1] = 4; + g_step_test_check.step_check_params[4][0] = "0"; + g_step_test_check.step_check_params[4][1] = "0x50"; + g_step_test_check.step_check_params[4][2] = "0x9c"; + g_step_test_check.step_check_params_num[4] = 3; + g_step_test_check.step_check_params[6][0] = "1"; + g_step_test_check.step_check_params[6][1] = "0x08"; + g_step_test_check.step_check_params[6][2] = "30"; + g_step_test_check.step_check_params_num[6] = 3; + g_step_test_check.step_check_params[7][0] = "0"; + g_step_test_check.step_check_params[7][1] = "8"; + g_step_test_check.step_check_params_num[7] = 2; + g_step_test_check.step_check_params[8][0] = "1"; + g_step_test_check.step_check_params[8][1] = "6"; + g_step_test_check.step_check_params[8][2] = "3"; + g_step_test_check.step_check_params_num[8] = 3; + g_step_test_check.step_check_params[11][0] = "0"; + g_step_test_check.step_check_params[11][1] = "0x50"; + g_step_test_check.step_check_params[11][2] = "0x9c"; + g_step_test_check.step_check_params_num[11] = 3; + g_step_test_check.step_check_params[13][0] = "Hello"; + g_step_test_check.step_check_params_num[13] = 1; + g_step_test_check.step_check_params[14][0] = "1000"; + g_step_test_check.step_check_params_num[14] = 1; + g_step_test_check.step_check_params[15][0] = "$1"; + g_step_test_check.step_check_params[15][1] = "$2"; + g_step_test_check.step_check_params[15][2] = "=="; + g_step_test_check.step_check_params[15][3] = "$3"; + g_step_test_check.step_check_params_num[15] = 4; + g_step_test_check.step_check_params[16][0] = "$0"; + g_step_test_check.step_check_params[16][1] = "0x66"; + g_step_test_check.step_check_params_num[16] = 2; + g_step_test_check.step_check_params[17][0] = "$2"; + g_step_test_check.step_check_params[17][1] = "0"; + g_step_test_check.step_check_params[17][2] = "0x50"; + g_step_test_check.step_check_params[17][3] = "0xFFFFFFFF"; + g_step_test_check.step_check_params[17][4] = "$1"; + g_step_test_check.step_check_params_num[17] = 5; + g_step_test_check.step_check_params[18][0] = "$2"; + g_step_test_check.step_check_params[18][1] = "0"; + g_step_test_check.step_check_params[18][2] = "0x08"; + g_step_test_check.step_check_params[18][3] = "0xFFFFFFFF"; + g_step_test_check.step_check_params[18][4] = "$1"; + g_step_test_check.step_check_params_num[18] = 5; + __wmt_step_test_parse_data(buf, &temp_report, + "STEP test case failed: (Parse data TC-2) Normal case with some space\n"); + + /*************************************************** + ****************** Test case 3 ******************** + ** Failed case not enough parameter (Can parser) ** + ***************************************************/ + WMT_INFO_FUNC("STEP test: TC 3\n"); + wmt_step_test_clear_check_data(); + buf = + "// TEST NOW\r\n" + "\r\n" + "[TP 1] When Command timeout\r\n" + "[AT] _EMI 0x50 0x9c\r\n" + "[AT] _REG 0 5 2\r\n" + "[AT] DRST\r\n" + "[AT] _RST\r\n" + "[TP 2] When Firmware trigger assert\r\n" + "[AT] _REG 1 0x08\r\n" + "[AT] GPIO 0\r\n" + "[AT] GPIO 6 3\r\n" + "[TP 3] Before Chip reset\r\n" + "[AT] SHOW\r\n" + "[AT] _SLP\r\n" + "[AT] COND $1 $2 >\r\n" + "[AT] _VAL 0x66\r\n" + "\r\n"; + + g_step_test_check.step_check_total = 11; + g_step_test_check.step_check_test_tp_id[0] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[0] = STEP_ACTION_INDEX_EMI; + g_step_test_check.step_check_test_tp_id[1] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[1] = STEP_ACTION_INDEX_REGISTER; + g_step_test_check.step_check_test_tp_id[2] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[2] = STEP_ACTION_INDEX_DISABLE_RESET; + g_step_test_check.step_check_test_tp_id[3] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[3] = STEP_ACTION_INDEX_CHIP_RESET; + g_step_test_check.step_check_test_tp_id[4] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[4] = STEP_ACTION_INDEX_REGISTER; + g_step_test_check.step_check_test_tp_id[5] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[5] = STEP_ACTION_INDEX_GPIO; + g_step_test_check.step_check_test_tp_id[6] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[6] = STEP_ACTION_INDEX_GPIO; + g_step_test_check.step_check_test_tp_id[7] = STEP_TRIGGER_POINT_BEFORE_CHIP_RESET; + g_step_test_check.step_check_test_act_id[7] = STEP_ACTION_INDEX_SHOW_STRING; + g_step_test_check.step_check_test_tp_id[8] = STEP_TRIGGER_POINT_BEFORE_CHIP_RESET; + g_step_test_check.step_check_test_act_id[8] = STEP_ACTION_INDEX_SLEEP; + g_step_test_check.step_check_test_tp_id[9] = STEP_TRIGGER_POINT_BEFORE_CHIP_RESET; + g_step_test_check.step_check_test_act_id[9] = STEP_ACTION_INDEX_CONDITION; + g_step_test_check.step_check_test_tp_id[10] = STEP_TRIGGER_POINT_BEFORE_CHIP_RESET; + g_step_test_check.step_check_test_act_id[10] = STEP_ACTION_INDEX_VALUE; + + g_step_test_check.step_check_params[0][0] = "0x50"; + g_step_test_check.step_check_params[0][1] = "0x9c"; + g_step_test_check.step_check_params_num[0] = 2; + g_step_test_check.step_check_params[1][0] = "0"; + g_step_test_check.step_check_params[1][1] = "5"; + g_step_test_check.step_check_params[1][2] = "2"; + g_step_test_check.step_check_params_num[1] = 3; + g_step_test_check.step_check_params[4][0] = "1"; + g_step_test_check.step_check_params[4][1] = "0x08"; + g_step_test_check.step_check_params_num[4] = 2; + g_step_test_check.step_check_params[5][0] = "0"; + g_step_test_check.step_check_params_num[5] = 1; + g_step_test_check.step_check_params[6][0] = "6"; + g_step_test_check.step_check_params[6][1] = "3"; + g_step_test_check.step_check_params_num[6] = 2; + g_step_test_check.step_check_params[9][0] = "$1"; + g_step_test_check.step_check_params[9][1] = "$2"; + g_step_test_check.step_check_params[9][2] = ">"; + g_step_test_check.step_check_params_num[9] = 3; + g_step_test_check.step_check_params[10][0] = "0x66"; + g_step_test_check.step_check_params_num[10] = 1; + + __wmt_step_test_parse_data(buf, &temp_report, + "STEP test case failed: (Parse data TC-3) Not enough parameter\n"); + + /*************************************************** + ****************** Test case 4 ******************** + ************** Upcase and lowercase *************** + ***************************************************/ + WMT_INFO_FUNC("STEP test: TC 4\n"); + wmt_step_test_clear_check_data(); + buf = + "// TEST NOW\r\n" + "\r\n" + "[Tp 1] When Command timeout\r\n" + "[aT] _emi 0 0x50 0x9c\r\n" + "[At] _reg 0 0x08 5 2\r\n" + "[AT] drst\r\n" + "[at] _rst\r\n" + "[tP 2] When Firmware trigger assert\r\n" + "[at] _reg 1 0x08 30\r\n" + "[at] gpio 0 8\r\n" + "[AT] gpio 1 6 3\r\n" + "[AT] wak+\r\n" + "[AT] wak--\r\n" + "[AT] _reg 1 0x08 30 0xFF00FF00\r\n" + "[pd+] 5\r\n" + "[At] gpio 0 8\r\n" + "[pd-]\r\n" + "[tp 3] Before Chip reset\r\n" + "[AT] show Hello_World\r\n" + "[AT] _slp 1000\r\n" + "[AT] cond $1 $2 == $3\r\n" + "[AT] _val $0 0x66\r\n" + "[TP 4] After Chip reset\r\n" + "[AT] cemi $2 0 0x50 0xFFFFFFFF $1\r\n" + "[at] creg $2 0 0x08 0xffffffff $1\r\n" + "\r\n"; + + g_step_test_check.step_check_total = 18; + g_step_test_check.step_check_test_tp_id[0] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[0] = STEP_ACTION_INDEX_EMI; + g_step_test_check.step_check_test_tp_id[1] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[1] = STEP_ACTION_INDEX_REGISTER; + g_step_test_check.step_check_test_tp_id[2] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[2] = STEP_ACTION_INDEX_DISABLE_RESET; + g_step_test_check.step_check_test_tp_id[3] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[3] = STEP_ACTION_INDEX_CHIP_RESET; + g_step_test_check.step_check_test_tp_id[4] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[4] = STEP_ACTION_INDEX_REGISTER; + g_step_test_check.step_check_test_tp_id[5] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[5] = STEP_ACTION_INDEX_GPIO; + g_step_test_check.step_check_test_tp_id[6] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[6] = STEP_ACTION_INDEX_GPIO; + g_step_test_check.step_check_test_tp_id[7] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[7] = STEP_ACTION_INDEX_KEEP_WAKEUP; + g_step_test_check.step_check_test_tp_id[8] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[8] = STEP_ACTION_INDEX_CANCEL_WAKEUP; + g_step_test_check.step_check_test_tp_id[9] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[9] = STEP_ACTION_INDEX_REGISTER; + g_step_test_check.step_check_test_tp_id[10] = -1; + g_step_test_check.step_check_test_act_id[10] = STEP_ACTION_INDEX_GPIO; + g_step_test_check.step_check_test_tp_id[11] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[11] = STEP_ACTION_INDEX_PERIODIC_DUMP; + g_step_test_check.step_check_test_tp_id[12] = STEP_TRIGGER_POINT_BEFORE_CHIP_RESET; + g_step_test_check.step_check_test_act_id[12] = STEP_ACTION_INDEX_SHOW_STRING; + g_step_test_check.step_check_test_tp_id[13] = STEP_TRIGGER_POINT_BEFORE_CHIP_RESET; + g_step_test_check.step_check_test_act_id[13] = STEP_ACTION_INDEX_SLEEP; + g_step_test_check.step_check_test_tp_id[14] = STEP_TRIGGER_POINT_BEFORE_CHIP_RESET; + g_step_test_check.step_check_test_act_id[14] = STEP_ACTION_INDEX_CONDITION; + g_step_test_check.step_check_test_tp_id[15] = STEP_TRIGGER_POINT_BEFORE_CHIP_RESET; + g_step_test_check.step_check_test_act_id[15] = STEP_ACTION_INDEX_VALUE; + g_step_test_check.step_check_test_tp_id[16] = STEP_TRIGGER_POINT_AFTER_CHIP_RESET; + g_step_test_check.step_check_test_act_id[16] = STEP_ACTION_INDEX_CONDITION_EMI; + g_step_test_check.step_check_test_tp_id[17] = STEP_TRIGGER_POINT_AFTER_CHIP_RESET; + g_step_test_check.step_check_test_act_id[17] = STEP_ACTION_INDEX_CONDITION_REGISTER; + + g_step_test_check.step_check_params[0][0] = "0"; + g_step_test_check.step_check_params[0][1] = "0x50"; + g_step_test_check.step_check_params[0][2] = "0x9c"; + g_step_test_check.step_check_params_num[0] = 3; + g_step_test_check.step_check_params[1][0] = "0"; + g_step_test_check.step_check_params[1][1] = "0x08"; + g_step_test_check.step_check_params[1][2] = "5"; + g_step_test_check.step_check_params[1][3] = "2"; + g_step_test_check.step_check_params_num[1] = 4; + g_step_test_check.step_check_params[4][0] = "1"; + g_step_test_check.step_check_params[4][1] = "0x08"; + g_step_test_check.step_check_params[4][2] = "30"; + g_step_test_check.step_check_params_num[4] = 3; + g_step_test_check.step_check_params[5][0] = "0"; + g_step_test_check.step_check_params[5][1] = "8"; + g_step_test_check.step_check_params_num[5] = 2; + g_step_test_check.step_check_params[6][0] = "1"; + g_step_test_check.step_check_params[6][1] = "6"; + g_step_test_check.step_check_params[6][2] = "3"; + g_step_test_check.step_check_params_num[6] = 3; + g_step_test_check.step_check_params[9][0] = "1"; + g_step_test_check.step_check_params[9][1] = "0x08"; + g_step_test_check.step_check_params[9][2] = "30"; + g_step_test_check.step_check_params[9][3] = "0xFF00FF00"; + g_step_test_check.step_check_params_num[9] = 4; + g_step_test_check.step_check_params[10][0] = "0"; + g_step_test_check.step_check_params[10][1] = "8"; + g_step_test_check.step_check_params_num[10] = 2; + g_step_test_check.step_check_params[12][0] = "Hello_World"; + g_step_test_check.step_check_params_num[12] = 1; + g_step_test_check.step_check_params[13][0] = "1000"; + g_step_test_check.step_check_params_num[13] = 1; + g_step_test_check.step_check_params[14][0] = "$1"; + g_step_test_check.step_check_params[14][1] = "$2"; + g_step_test_check.step_check_params[14][2] = "=="; + g_step_test_check.step_check_params[14][3] = "$3"; + g_step_test_check.step_check_params_num[14] = 4; + g_step_test_check.step_check_params[15][0] = "$0"; + g_step_test_check.step_check_params[15][1] = "0x66"; + g_step_test_check.step_check_params_num[15] = 2; + g_step_test_check.step_check_params[16][0] = "$2"; + g_step_test_check.step_check_params[16][1] = "0"; + g_step_test_check.step_check_params[16][2] = "0x50"; + g_step_test_check.step_check_params[16][3] = "0xFFFFFFFF"; + g_step_test_check.step_check_params[16][4] = "$1"; + g_step_test_check.step_check_params_num[16] = 5; + g_step_test_check.step_check_params[17][0] = "$2"; + g_step_test_check.step_check_params[17][1] = "0"; + g_step_test_check.step_check_params[17][2] = "0x08"; + g_step_test_check.step_check_params[17][3] = "0xFFFFFFFF"; + g_step_test_check.step_check_params[17][4] = "$1"; + g_step_test_check.step_check_params_num[17] = 5; + + __wmt_step_test_parse_data(buf, &temp_report, + "STEP test case failed: (Parse data TC-4) Upcase and lowercase\n"); + + /************************************************* + ****************** Test case 5 ****************** + ************** TP sequence switch *************** + *************************************************/ + WMT_INFO_FUNC("STEP test: TC 5\n"); + wmt_step_test_clear_check_data(); + buf = + "// TEST NOW\r\n" + "\r\n" + "[TP 2] When Firmware trigger assert\r\n" + "[AT] _REG 1 0x08 30\r\n" + "[AT] GPIO 0 8\r\n" + "[AT] GPIO 1 6 3\r\n" + "[tp 3] Before Chip reset\r\n" + "[AT] DRST\r\n" + "[AT] _RST\r\n" + "[TP 1] When Command timeout\r\n" + "[AT] _EMI 0 0x50 0x9c\r\n" + "[AT] _REG 0 0x08 5 2\r\n" + "\r\n"; + + g_step_test_check.step_check_total = 7; + g_step_test_check.step_check_test_tp_id[0] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[0] = STEP_ACTION_INDEX_REGISTER; + g_step_test_check.step_check_test_tp_id[1] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[1] = STEP_ACTION_INDEX_GPIO; + g_step_test_check.step_check_test_tp_id[2] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[2] = STEP_ACTION_INDEX_GPIO; + g_step_test_check.step_check_test_tp_id[3] = STEP_TRIGGER_POINT_BEFORE_CHIP_RESET; + g_step_test_check.step_check_test_act_id[3] = STEP_ACTION_INDEX_DISABLE_RESET; + g_step_test_check.step_check_test_tp_id[4] = STEP_TRIGGER_POINT_BEFORE_CHIP_RESET; + g_step_test_check.step_check_test_act_id[4] = STEP_ACTION_INDEX_CHIP_RESET; + g_step_test_check.step_check_test_tp_id[5] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[5] = STEP_ACTION_INDEX_EMI; + g_step_test_check.step_check_test_tp_id[6] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[6] = STEP_ACTION_INDEX_REGISTER; + g_step_test_check.step_check_params[0][0] = "1"; + g_step_test_check.step_check_params[0][1] = "0x08"; + g_step_test_check.step_check_params[0][2] = "30"; + g_step_test_check.step_check_params_num[0] = 3; + g_step_test_check.step_check_params[1][0] = "0"; + g_step_test_check.step_check_params[1][1] = "8"; + g_step_test_check.step_check_params_num[1] = 2; + g_step_test_check.step_check_params[2][0] = "1"; + g_step_test_check.step_check_params[2][1] = "6"; + g_step_test_check.step_check_params[2][2] = "3"; + g_step_test_check.step_check_params_num[2] = 3; + g_step_test_check.step_check_params[5][0] = "0"; + g_step_test_check.step_check_params[5][1] = "0x50"; + g_step_test_check.step_check_params[5][2] = "0x9c"; + g_step_test_check.step_check_params_num[5] = 3; + g_step_test_check.step_check_params[6][0] = "0"; + g_step_test_check.step_check_params[6][1] = "0x08"; + g_step_test_check.step_check_params[6][2] = "5"; + g_step_test_check.step_check_params[6][3] = "2"; + g_step_test_check.step_check_params_num[6] = 4; + __wmt_step_test_parse_data(buf, &temp_report, + "STEP test case failed: (Parse data TC-5) TP sequence switch\n"); + + /********************************* + ********* Test case 6 *********** + ********* More comment ********** + *********************************/ + WMT_INFO_FUNC("STEP test: TC 6\n"); + wmt_step_test_clear_check_data(); + + buf = + "// TEST NOW\r\n" + "\r\n" + "[TP 1] When Command timeout\r\n" + "[AT] _EMI 0 0x50 0x9c // show emi 0x50~0x9c\r\n" + "// show cregister\r\n" + "[AT] _REG 0 0x08 5 2\r\n" + "// Do some action\r\n" + "[AT] DRST // just do it\r\n" + "[AT] _RST // is ok?\r\n" + "[TP 2] When Firmware trigger assert\r\n" + "[AT] _REG 1 0x08 30\r\n" + "[AT] GPIO 0 8\r\n" + "[AT] GPIO 1 6 3\r\n" + "[PD+] 5 // pd start\r\n" + "[AT] GPIO 0 8 // just do it\r\n" + "// Do some action\r\n" + "[PD-] // pd ned\r\n" + "\r\n"; + + g_step_test_check.step_check_total = 9; + g_step_test_check.step_check_test_tp_id[0] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[0] = STEP_ACTION_INDEX_EMI; + g_step_test_check.step_check_test_tp_id[1] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[1] = STEP_ACTION_INDEX_REGISTER; + g_step_test_check.step_check_test_tp_id[2] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[2] = STEP_ACTION_INDEX_DISABLE_RESET; + g_step_test_check.step_check_test_tp_id[3] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[3] = STEP_ACTION_INDEX_CHIP_RESET; + g_step_test_check.step_check_test_tp_id[4] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[4] = STEP_ACTION_INDEX_REGISTER; + g_step_test_check.step_check_test_tp_id[5] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[5] = STEP_ACTION_INDEX_GPIO; + g_step_test_check.step_check_test_tp_id[6] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[6] = STEP_ACTION_INDEX_GPIO; + g_step_test_check.step_check_test_tp_id[7] = -1; + g_step_test_check.step_check_test_act_id[7] = STEP_ACTION_INDEX_GPIO; + g_step_test_check.step_check_test_tp_id[8] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[8] = STEP_ACTION_INDEX_PERIODIC_DUMP; + g_step_test_check.step_check_params[0][0] = "0"; + g_step_test_check.step_check_params[0][1] = "0x50"; + g_step_test_check.step_check_params[0][2] = "0x9c"; + g_step_test_check.step_check_params_num[0] = 3; + g_step_test_check.step_check_params[1][0] = "0"; + g_step_test_check.step_check_params[1][1] = "0x08"; + g_step_test_check.step_check_params[1][2] = "5"; + g_step_test_check.step_check_params[1][3] = "2"; + g_step_test_check.step_check_params_num[1] = 4; + g_step_test_check.step_check_params[4][0] = "1"; + g_step_test_check.step_check_params[4][1] = "0x08"; + g_step_test_check.step_check_params[4][2] = "30"; + g_step_test_check.step_check_params_num[4] = 3; + g_step_test_check.step_check_params[5][0] = "0"; + g_step_test_check.step_check_params[5][1] = "8"; + g_step_test_check.step_check_params_num[5] = 2; + g_step_test_check.step_check_params[6][0] = "1"; + g_step_test_check.step_check_params[6][1] = "6"; + g_step_test_check.step_check_params[6][2] = "3"; + g_step_test_check.step_check_params_num[6] = 3; + g_step_test_check.step_check_params[7][0] = "0"; + g_step_test_check.step_check_params[7][1] = "8"; + g_step_test_check.step_check_params_num[7] = 2; + __wmt_step_test_parse_data(buf, &temp_report, + "STEP test case failed: (Parse data TC-6) More comment\n"); + + /********************************* + ********* Test case 7 *********** + ********* Wrong format ********** + *********************************/ + WMT_INFO_FUNC("STEP test: TC 7\n"); + wmt_step_test_clear_check_data(); + + buf = + "// TEST NOW\r\n" + "\r\n" + "[TP adfacdadf]When Command timeout\r\n" + "[AT] _EMI 0 0x50 0x9c\r\n" + "[TP1]When Command timeout\r\n" + "[AT] DRST\r\n" + "[TP-1]When Command timeout\r\n" + "[AT] _RST\r\n" + "[T P 2] When Firmware trigger assert\r\n" + "[AT] WAK+\r\n" + "[TP 2 When Firmware trigger assert\r\n" + "[AT] WAK+\r\n" + "[PD+]\r\n" + "[PD-]\r\n" + "[TP 2] When Firmware trigger assert\r\n" + "[AT]_REG 1 0x08 30\r\n" + "[A T] GPIO 0 8\r\n" + "[ AT ] GPIO 1 6 3\r\n" + "AT GPIO 0 8\r\n" + "[AT WAK+\r\n" + "\r\n"; + + g_step_test_check.step_check_total = 0; + __wmt_step_test_parse_data(buf, &temp_report, + "STEP test case failed: (Parse data TC-7) Wrong format\n"); + + /******************************** + ******** Test case 8 *********** + ******* Periodic dump ********** + ********************************/ + WMT_INFO_FUNC("STEP test: TC 8\n"); + wmt_step_test_clear_check_data(); + + buf = + "// TEST NOW\r\n" + "\r\n" + "[TP 1] When Command timeout\r\n" + "[PD+] 5\r\n" + "[AT] _EMI 0 0x50 0x9c\r\n" + "[AT] _REG 0 0x08 5 2\r\n" + "[PD-]\r\n" + "[AT] DRST\r\n" + "[AT] _RST\r\n" + "[TP 2] When Firmware trigger assert\r\n" + "[AT] _REG 1 0x08 30\r\n" + "[PD+] 3\r\n" + "[AT] GPIO 0 8\r\n" + "[PD-]\r\n" + "[AT] GPIO 1 6 3\r\n" + "[AT] WAK+\r\n" + "[AT] WAK-\r\n" + "\r\n"; + + g_step_test_check.step_check_total = 11; + g_step_test_check.step_check_test_tp_id[0] = -1; + g_step_test_check.step_check_test_act_id[0] = STEP_ACTION_INDEX_EMI; + g_step_test_check.step_check_test_tp_id[1] = -1; + g_step_test_check.step_check_test_act_id[1] = STEP_ACTION_INDEX_REGISTER; + g_step_test_check.step_check_test_tp_id[2] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[2] = STEP_ACTION_INDEX_PERIODIC_DUMP; + g_step_test_check.step_check_test_tp_id[3] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[3] = STEP_ACTION_INDEX_DISABLE_RESET; + g_step_test_check.step_check_test_tp_id[4] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[4] = STEP_ACTION_INDEX_CHIP_RESET; + g_step_test_check.step_check_test_tp_id[5] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[5] = STEP_ACTION_INDEX_REGISTER; + g_step_test_check.step_check_test_tp_id[6] = -1; + g_step_test_check.step_check_test_act_id[6] = STEP_ACTION_INDEX_GPIO; + g_step_test_check.step_check_test_tp_id[7] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[7] = STEP_ACTION_INDEX_PERIODIC_DUMP; + g_step_test_check.step_check_test_tp_id[8] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[8] = STEP_ACTION_INDEX_GPIO; + g_step_test_check.step_check_test_tp_id[9] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[9] = STEP_ACTION_INDEX_KEEP_WAKEUP; + g_step_test_check.step_check_test_tp_id[10] = STEP_TRIGGER_POINT_FIRMWARE_TRIGGER_ASSERT; + g_step_test_check.step_check_test_act_id[10] = STEP_ACTION_INDEX_CANCEL_WAKEUP; + g_step_test_check.step_check_params[0][0] = "0"; + g_step_test_check.step_check_params[0][1] = "0x50"; + g_step_test_check.step_check_params[0][2] = "0x9c"; + g_step_test_check.step_check_params_num[0] = 3; + g_step_test_check.step_check_params[1][0] = "0"; + g_step_test_check.step_check_params[1][1] = "0x08"; + g_step_test_check.step_check_params[1][2] = "5"; + g_step_test_check.step_check_params[1][3] = "2"; + g_step_test_check.step_check_params_num[1] = 4; + g_step_test_check.step_check_params[5][0] = "1"; + g_step_test_check.step_check_params[5][1] = "0x08"; + g_step_test_check.step_check_params[5][2] = "30"; + g_step_test_check.step_check_params_num[5] = 3; + g_step_test_check.step_check_params[6][0] = "0"; + g_step_test_check.step_check_params[6][1] = "8"; + g_step_test_check.step_check_params_num[6] = 2; + g_step_test_check.step_check_params[8][0] = "1"; + g_step_test_check.step_check_params[8][1] = "6"; + g_step_test_check.step_check_params[8][2] = "3"; + g_step_test_check.step_check_params_num[8] = 3; + __wmt_step_test_parse_data(buf, &temp_report, + "STEP test case failed: (Parse data TC-8) Periodic dump\n"); + + /********************************* + ******** Test case 9 ************ + *** Boundary: Much parameter **** + *********************************/ + WMT_INFO_FUNC("STEP test: TC 9\n"); + wmt_step_test_clear_check_data(); + buf = + "// TEST NOW\r\n" + "\r\n" + "[TP 1] When Command timeout\r\n" + "[AT] _EMI 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0x10 0x11 0x12 0x13\r\n" + "\r\n"; + + g_step_test_check.step_check_total = 1; + g_step_test_check.step_check_test_tp_id[0] = STEP_TRIGGER_POINT_COMMAND_TIMEOUT; + g_step_test_check.step_check_test_act_id[0] = STEP_ACTION_INDEX_EMI; + g_step_test_check.step_check_params[0][0] = "0x1"; + g_step_test_check.step_check_params[0][1] = "0x2"; + g_step_test_check.step_check_params[0][2] = "0x3"; + g_step_test_check.step_check_params[0][3] = "0x4"; + g_step_test_check.step_check_params[0][4] = "0x5"; + g_step_test_check.step_check_params[0][5] = "0x6"; + g_step_test_check.step_check_params[0][6] = "0x7"; + g_step_test_check.step_check_params[0][7] = "0x8"; + g_step_test_check.step_check_params[0][8] = "0x9"; + g_step_test_check.step_check_params[0][9] = "0x10"; + g_step_test_check.step_check_params_num[0] = 10; + + __wmt_step_test_parse_data(buf, &temp_report, + "STEP test case failed: (Parse data TC-9) Boundary: Much parameter\n"); + + osal_gettimeofday(&sec_end, &usec_end); + wmt_step_test_show_result_report("STEP result: Parse data result", + &temp_report, sec_begin, usec_begin, sec_end, usec_end); + wmt_step_test_update_result_report(p_report, &temp_report); +} + +void wmt_step_test_create_emi_action(struct step_test_report *p_report) +{ + enum step_action_id act_id; + char *params[STEP_PARAMETER_SIZE]; + int check_params[STEP_PARAMETER_SIZE]; + struct step_test_report temp_report = {0, 0, 0}; + int sec_begin = 0; + int usec_begin = 0; + int sec_end = 0; + int usec_end = 0; + int param_num = 0; + + WMT_INFO_FUNC("STEP test: Create EMI action start\n"); + osal_gettimeofday(&sec_begin, &usec_begin); + act_id = STEP_ACTION_INDEX_EMI; + + /***************************** + ******** Test case 1 ******** + **** EMI create for read **** + *****************************/ + WMT_INFO_FUNC("STEP test: TC 1\n"); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + params[1] = "0x50"; + params[2] = "0x9c"; + param_num = 3; + check_params[0] = 0; + check_params[1] = 0x50; + check_params[2] = 0x9c; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-1) EMI create"); + + /************************************ + ********** Test case 2 ************ + **** EMI create fail less param **** + ************************************/ + WMT_INFO_FUNC("STEP test: TC 2\n"); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + params[1] = "0x50"; + param_num = 2; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-2) EMI create fail"); + + /************************************************* + **************** Test case 3 ******************* + ********** Save emi to temp register ************ + *************************************************/ + WMT_INFO_FUNC("STEP test: TC 3\n"); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + params[1] = "0x50"; + params[2] = "0x00000030"; + params[3] = "$3"; + param_num = 4; + check_params[0] = 0; + check_params[1] = 0x50; + check_params[2] = 0x00000030; + check_params[3] = 3; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-3) Save emi to temp register"); + + /************************************************* + **************** Test case 4 ******************* + ** Boundary: Save emi to wrong temp register **** + *************************************************/ + WMT_INFO_FUNC("STEP test: TC 4\n"); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + params[1] = "0x50"; + params[2] = "0x00000030"; + params[3] = "$30"; + param_num = 4; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-4) Boundary: Save emi to wrong temp register"); + + osal_gettimeofday(&sec_end, &usec_end); + wmt_step_test_show_result_report("STEP result: Create EMI action result", + &temp_report, sec_begin, usec_begin, sec_end, usec_end); + wmt_step_test_update_result_report(p_report, &temp_report); +} + +void wmt_step_test_create_cond_emi_action(struct step_test_report *p_report) +{ + enum step_action_id act_id; + char *params[STEP_PARAMETER_SIZE]; + int check_params[STEP_PARAMETER_SIZE]; + struct step_test_report temp_report = {0, 0, 0}; + int sec_begin = 0; + int usec_begin = 0; + int sec_end = 0; + int usec_end = 0; + int param_num = 0; + + WMT_INFO_FUNC("STEP test: Create condition EMI action start\n"); + osal_gettimeofday(&sec_begin, &usec_begin); + act_id = STEP_ACTION_INDEX_CONDITION_EMI; + + /************************************************* + **************** Test case 1 ******************* + ************ Condition emi create *************** + *************************************************/ + WMT_INFO_FUNC("STEP test: TC 1\n"); + wmt_step_test_clear_parameter(params); + params[0] = "$1"; + params[1] = "0"; + params[2] = "0x50"; + params[3] = "0x70"; + param_num = 4; + check_params[0] = 1; + check_params[1] = 0; + check_params[2] = 0x50; + check_params[3] = 0x70; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-1) Condition emi create"); + + /************************************************* + **************** Test case 2 ******************* + ****** Save condition emi to temp register ****** + *************************************************/ + WMT_INFO_FUNC("STEP test: TC 2\n"); + wmt_step_test_clear_parameter(params); + params[0] = "$2"; + params[1] = "0"; + params[2] = "0x50"; + params[3] = "0x00000030"; + params[4] = "$3"; + param_num = 5; + check_params[0] = 2; + check_params[1] = 0; + check_params[2] = 0x50; + check_params[3] = 0x00000030; + check_params[4] = 3; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-2) Save condition emi to temp register"); + + /*********************************************************** + ******************** Test case 3 ************************* + ** Boundary: Save condition emi to wrong temp register **** + ***********************************************************/ + WMT_INFO_FUNC("STEP test: TC 3\n"); + wmt_step_test_clear_parameter(params); + params[0] = "$1"; + params[1] = "0"; + params[2] = "0x50"; + params[3] = "0x00000030"; + params[4] = "$30"; + param_num = 5; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-3) Boundary: Boundary: Save condition emi to wrong temp register"); + + /*********************************************************** + ******************** Test case 4 ************************* + ** Boundary: Save condition emi is wrong temp register **** + ***********************************************************/ + WMT_INFO_FUNC("STEP test: TC 4\n"); + wmt_step_test_clear_parameter(params); + params[0] = "$30"; + params[1] = "0"; + params[2] = "0x50"; + params[3] = "0x00000030"; + params[4] = "$1"; + param_num = 5; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-4) Boundary: Boundary: Save condition emi is wrong temp register"); + + /************************************************* + **************** Test case 5 ******************* + ******* Condition emi create less params ******** + *************************************************/ + WMT_INFO_FUNC("STEP test: TC 5\n"); + wmt_step_test_clear_parameter(params); + params[0] = "$1"; + params[1] = "0"; + params[2] = "0x50"; + param_num = 3; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-5) Condition emi create less params"); + + /************************************************* + **************** Test case 6 ******************* + ******* Condition emi create wrong symbol ******* + *************************************************/ + WMT_INFO_FUNC("STEP test: TC 6\n"); + wmt_step_test_clear_parameter(params); + params[0] = "1"; + params[1] = "0"; + params[2] = "0x50"; + params[3] = "0x00000030"; + params[4] = "$1"; + param_num = 5; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-6) Condition emi create wrong symbol"); + + osal_gettimeofday(&sec_end, &usec_end); + wmt_step_test_show_result_report("STEP result: Create condition EMI action result", + &temp_report, sec_begin, usec_begin, sec_end, usec_end); + wmt_step_test_update_result_report(p_report, &temp_report); +} + +void wmt_step_test_create_register_action(struct step_test_report *p_report) +{ + enum step_action_id act_id; + char *params[STEP_PARAMETER_SIZE]; + int check_params[STEP_PARAMETER_SIZE]; + struct step_test_report temp_report = {0, 0, 0}; + int sec_begin = 0; + int usec_begin = 0; + int sec_end = 0; + int usec_end = 0; + int param_num = 0; + + WMT_INFO_FUNC("STEP test: Create Register action start\n"); + osal_gettimeofday(&sec_begin, &usec_begin); + act_id = STEP_ACTION_INDEX_REGISTER; + + /**************************************** + ************ Test case 1 *************** + **** REGISTER(Addr) create for read **** + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 1\n"); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + params[1] = "0x124dfad"; + params[2] = "0x9c"; + params[3] = "2"; + params[4] = "10"; + param_num = 5; + check_params[0] = 0; + check_params[1] = 0x124dfad; + check_params[2] = 0x9c; + check_params[3] = 2; + check_params[4] = 10; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-1) REG create read"); + + /***************************************** + ************ Test case 2 **************** + **** REGISTER(Addr) create for write **** + *****************************************/ + WMT_INFO_FUNC("STEP test: TC 2\n"); + wmt_step_test_clear_parameter(params); + params[0] = "1"; + params[1] = "0x124dfad"; + params[2] = "0x9c"; + params[3] = "15"; + param_num = 4; + check_params[0] = 1; + check_params[1] = 0x124dfad; + check_params[2] = 0x9c; + check_params[3] = 15; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-2) REG create write"); + + /****************************************** + ************** Test case 3 *************** + ******* Boundary: read wrong symbol ****** + ******************************************/ + WMT_INFO_FUNC("STEP test: TC 3\n"); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + params[1] = "#10000"; + params[2] = "0x204"; + params[3] = "1"; + params[4] = "0"; + param_num = 5; + check_params[0] = 0; + check_params[1] = 0x124dfad; + check_params[2] = 0x9c; + check_params[3] = 2; + check_params[4] = 10; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-3) Boundary: read wrong symbol"); + + /**************************************************** + **************** Test case 4 ********************** + **** REGISTER(Addr) create read fail less param **** + ****************************************************/ + WMT_INFO_FUNC("STEP test: TC 4\n"); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + params[1] = "0x124dfad"; + params[2] = "0x9c"; + param_num = 3; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-4) REG create read fail"); + + /***************************************************** + ************ Test case 5 *************************** + **** REGISTER(Addr) create write fail less param **** + *****************************************************/ + WMT_INFO_FUNC("STEP test: TC 5\n"); + wmt_step_test_clear_parameter(params); + params[0] = "1"; + params[1] = "0x124dfad"; + params[2] = "0x9c"; + param_num = 3; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-5) REG create write fail"); + + /***************************************** + ************ Test case 6 **************** + ** REGISTER(Addr) create for write bit *** + *****************************************/ + WMT_INFO_FUNC("STEP test: TC 6\n"); + wmt_step_test_clear_parameter(params); + params[0] = "1"; + params[1] = "0x124dfad"; + params[2] = "0x9c"; + params[3] = "15"; + params[4] = "0xFF00FF00"; + param_num = 5; + check_params[0] = 1; + check_params[1] = 0x124dfad; + check_params[2] = 0x9c; + check_params[3] = 15; + check_params[4] = 0xFF00FF00; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-6) REG create write"); + + /********************************************************* + ******************** Test case 7 *********************** + **** REGISTER(Addr) create for read to temp register **** + *********************************************************/ + WMT_INFO_FUNC("STEP test: TC 7\n"); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + params[1] = "0x124dfad"; + params[2] = "0x9c"; + params[3] = "0x00000030"; + params[4] = "$5"; + param_num = 5; + check_params[0] = 0; + check_params[1] = 0x124dfad; + check_params[2] = 0x9c; + check_params[3] = 0x00000030; + check_params[4] = 5; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-7) REGISTER(Addr) create for read to temp register"); + + /********************************************************* + ******************** Test case 8 *********************** + *** REGISTER(Symbol) create for read to temp register *** + *********************************************************/ + WMT_INFO_FUNC("STEP test: TC 8\n"); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + params[1] = "#1"; + params[2] = "0x9c"; + params[3] = "0x00000030"; + params[4] = "$7"; + param_num = 5; + check_params[0] = 0; + check_params[1] = 1; + check_params[2] = 0x9c; + check_params[3] = 0x00000030; + check_params[4] = 7; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-8) REGISTER(Symbol) create for read to temp register"); + + /********************************************************* + ******************** Test case 9 *********************** + ********** REGISTER(Symbol) create for read ************* + *********************************************************/ + WMT_INFO_FUNC("STEP test: TC 9\n"); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + params[1] = "#1"; + params[2] = "0x9c"; + params[3] = "1"; + params[4] = "10"; + param_num = 5; + check_params[0] = 0; + check_params[1] = 1; + check_params[2] = 0x9c; + check_params[3] = 1; + check_params[4] = 10; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-9) REGISTER(Symbol) create for read"); + + /********************************************************* + ******************** Test case 10 *********************** + ************ REGISTER(Addr) less parameter ************** + *********************************************************/ + WMT_INFO_FUNC("STEP test: TC 10\n"); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + params[1] = "0x124dfad"; + params[2] = "0x9c"; + params[3] = "0x555"; + param_num = 4; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-10) REGISTER(Addr) less parameter"); + + /********************************************************* + ******************** Test case 11 *********************** + ************ REGISTER(Symbol) less parameter ************** + *********************************************************/ + WMT_INFO_FUNC("STEP test: TC 11\n"); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + params[1] = "#1"; + params[2] = "0x9c"; + params[3] = "0x555"; + param_num = 4; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-11) REGISTER(Symbol) less parameter"); + + /********************************************************** + *********************** Test case 12 ********************* + ** Boundary: REGISTER(Addr) read to worng temp register ** + **********************************************************/ + WMT_INFO_FUNC("STEP test: TC 12\n"); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + params[1] = "0x124dfad"; + params[2] = "0x9c"; + params[3] = "0x00000030"; + params[4] = "$35"; + param_num = 5; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-12) Boundary: REGISTER(Addr) read to worng temp registe"); + + /************************************************************ + *********************** Test case 13 *********************** + ** Boundary: REGISTER(Symbol) read to worng temp register ** + ************************************************************/ + WMT_INFO_FUNC("STEP test: TC 13\n"); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + params[1] = "#1"; + params[2] = "0x9c"; + params[3] = "0x00000030"; + params[4] = "$35"; + param_num = 5; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-13) Boundary: REGISTER(Symbol) read to worng temp registe"); + + osal_gettimeofday(&sec_end, &usec_end); + wmt_step_test_show_result_report("STEP result: Create register action result", + &temp_report, sec_begin, usec_begin, sec_end, usec_end); + wmt_step_test_update_result_report(p_report, &temp_report); +} + +void wmt_step_test_create_cond_register_action(struct step_test_report *p_report) +{ + enum step_action_id act_id; + char *params[STEP_PARAMETER_SIZE]; + int check_params[STEP_PARAMETER_SIZE]; + struct step_test_report temp_report = {0, 0, 0}; + int sec_begin = 0; + int usec_begin = 0; + int sec_end = 0; + int usec_end = 0; + int param_num = 0; + + WMT_INFO_FUNC("STEP test: Create condition Register action start\n"); + osal_gettimeofday(&sec_begin, &usec_begin); + act_id = STEP_ACTION_INDEX_CONDITION_REGISTER; + + /**************************************** + ************ Test case 1 *************** + **** COND_REG(Addr) create for read **** + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 1\n"); + wmt_step_test_clear_parameter(params); + params[0] = "$5"; + params[1] = "0"; + params[2] = "0x124dfad"; + params[3] = "0x9c"; + params[4] = "2"; + params[5] = "10"; + param_num = 6; + check_params[0] = 5; + check_params[1] = 0; + check_params[2] = 0x124dfad; + check_params[3] = 0x9c; + check_params[4] = 2; + check_params[5] = 10; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-1) COND_REG(Addr) create for read"); + + /***************************************** + ************ Test case 2 **************** + **** COND_REG(Addr) create for write **** + *****************************************/ + WMT_INFO_FUNC("STEP test: TC 2\n"); + wmt_step_test_clear_parameter(params); + params[0] = "$7"; + params[1] = "1"; + params[2] = "0x124dfad"; + params[3] = "0x9c"; + params[4] = "15"; + param_num = 5; + check_params[0] = 7; + check_params[1] = 1; + check_params[2] = 0x124dfad; + check_params[3] = 0x9c; + check_params[4] = 15; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-2) COND_REG(Addr) create write"); + + /****************************************** + ************** Test case 3 *************** + ******* Boundary: read wrong symbol ****** + ******************************************/ + WMT_INFO_FUNC("STEP test: TC 3\n"); + wmt_step_test_clear_parameter(params); + params[0] = "$2"; + params[1] = "0"; + params[2] = "#10000"; + params[3] = "0x204"; + params[4] = "1"; + params[5] = "0"; + param_num = 6; + check_params[0] = 2; + check_params[1] = 0; + check_params[2] = 0x124dfad; + check_params[3] = 0x9c; + check_params[4] = 2; + check_params[5] = 10; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-3) Boundary: read wrong symbol"); + + /**************************************************** + **************** Test case 4 ********************** + **** COND_REG(Addr) create read fail less param **** + ****************************************************/ + WMT_INFO_FUNC("STEP test: TC 4\n"); + wmt_step_test_clear_parameter(params); + params[0] = "$3"; + params[1] = "0"; + params[2] = "0x124dfad"; + params[3] = "0x9c"; + param_num = 4; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-4) COND_REG create read fail"); + + /***************************************************** + ************ Test case 5 *************************** + **** COND_REG(Addr) create write fail less param **** + *****************************************************/ + WMT_INFO_FUNC("STEP test: TC 5\n"); + wmt_step_test_clear_parameter(params); + params[0] = "$4"; + params[1] = "1"; + params[2] = "0x124dfad"; + params[3] = "0x9c"; + param_num = 4; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-5) COND_REG create write fail"); + + /***************************************** + ************ Test case 6 **************** + ** COND_REG(Addr) create for write bit *** + *****************************************/ + WMT_INFO_FUNC("STEP test: TC 6\n"); + wmt_step_test_clear_parameter(params); + params[0] = "$9"; + params[1] = "1"; + params[2] = "0x124dfad"; + params[3] = "0x9c"; + params[4] = "15"; + params[5] = "0xFF00FF00"; + param_num = 6; + check_params[0] = 9; + check_params[1] = 1; + check_params[2] = 0x124dfad; + check_params[3] = 0x9c; + check_params[4] = 15; + check_params[5] = 0xFF00FF00; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-6) COND_REG create write"); + + /********************************************************* + ******************** Test case 7 *********************** + **** COND_REG(Addr) create for read to temp register **** + *********************************************************/ + WMT_INFO_FUNC("STEP test: TC 7\n"); + wmt_step_test_clear_parameter(params); + params[0] = "$9"; + params[1] = "0"; + params[2] = "0x124dfad"; + params[3] = "0x9c"; + params[4] = "0x00000030"; + params[5] = "$5"; + param_num = 6; + check_params[0] = 9; + check_params[1] = 0; + check_params[2] = 0x124dfad; + check_params[3] = 0x9c; + check_params[4] = 0x00000030; + check_params[5] = 5; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-7) COND_REG(Addr) create for read to temp register"); + + /********************************************************* + ******************** Test case 8 *********************** + *** COND_REG(Symbol) create for read to temp register *** + *********************************************************/ + WMT_INFO_FUNC("STEP test: TC 8\n"); + wmt_step_test_clear_parameter(params); + params[0] = "$1"; + params[1] = "0"; + params[2] = "#1"; + params[3] = "0x9c"; + params[4] = "0x00000030"; + params[5] = "$7"; + param_num = 6; + check_params[0] = 1; + check_params[1] = 0; + check_params[2] = 1; + check_params[3] = 0x9c; + check_params[4] = 0x00000030; + check_params[5] = 7; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-8) COND_REG(Symbol) create for read to temp register"); + + /********************************************************* + ******************** Test case 9 *********************** + ********** COND_REG(Symbol) create for read ************* + *********************************************************/ + WMT_INFO_FUNC("STEP test: TC 9\n"); + wmt_step_test_clear_parameter(params); + params[0] = "$2"; + params[1] = "0"; + params[2] = "#1"; + params[3] = "0x9c"; + params[4] = "1"; + params[5] = "10"; + param_num = 6; + check_params[0] = 2; + check_params[1] = 0; + check_params[2] = 1; + check_params[3] = 0x9c; + check_params[4] = 1; + check_params[5] = 10; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-9) COND_REG(Symbol) create for read"); + + /********************************************************* + ******************** Test case 10 *********************** + ************ COND_REG(Addr) less parameter ************** + *********************************************************/ + WMT_INFO_FUNC("STEP test: TC 10\n"); + wmt_step_test_clear_parameter(params); + params[0] = "$3"; + params[1] = "0"; + params[2] = "0x124dfad"; + params[3] = "0x9c"; + params[4] = "0x555"; + param_num = 5; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-10) COND_REG(Addr) less parameter"); + + /********************************************************* + ******************** Test case 11 *********************** + ************ COND_REG(Symbol) less parameter ************** + *********************************************************/ + WMT_INFO_FUNC("STEP test: TC 11\n"); + wmt_step_test_clear_parameter(params); + params[0] = "$4"; + params[1] = "0"; + params[2] = "#1"; + params[3] = "0x9c"; + params[4] = "0x555"; + param_num = 5; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-11) COND_REG(Symbol) less parameter"); + + /********************************************************** + *********************** Test case 12 ********************* + ** Boundary: COND_REG(Addr) read to worng temp register ** + **********************************************************/ + WMT_INFO_FUNC("STEP test: TC 12\n"); + wmt_step_test_clear_parameter(params); + params[0] = "$5"; + params[1] = "0"; + params[2] = "0x124dfad"; + params[3] = "0x9c"; + params[4] = "0x00000030"; + params[5] = "$35"; + param_num = 6; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-12) Boundary: COND_REG(Addr) read to worng temp registe"); + + /************************************************************ + *********************** Test case 13 *********************** + ** Boundary: COND_REG(Symbol) read to worng temp register ** + ************************************************************/ + WMT_INFO_FUNC("STEP test: TC 13\n"); + wmt_step_test_clear_parameter(params); + params[0] = "$6"; + params[1] = "0"; + params[2] = "#1"; + params[3] = "0x9c"; + params[4] = "0x00000030"; + params[5] = "$35"; + param_num = 6; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-13) Boundary: COND_REG(Symbol) read to worng temp registe"); + + /********************************************************* + ******************** Test case 14 *********************** + ************* COND_REG(Symbol) worng symbol ************* + *********************************************************/ + WMT_INFO_FUNC("STEP test: TC 14\n"); + wmt_step_test_clear_parameter(params); + params[0] = "8"; + params[1] = "0"; + params[2] = "#1"; + params[3] = "0x9c"; + params[4] = "1"; + params[5] = "10"; + param_num = 6; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-14) Boundary: COND_REG(Symbol) worng symbol"); + + /********************************************************* + ******************** Test case 15 *********************** + ********* COND_REG(Symbol) worng temp register id ******* + *********************************************************/ + WMT_INFO_FUNC("STEP test: TC 15\n"); + wmt_step_test_clear_parameter(params); + params[0] = "$88"; + params[1] = "0"; + params[2] = "#1"; + params[3] = "0x9c"; + params[4] = "1"; + params[5] = "10"; + param_num = 6; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-15) Boundary: COND_REG(Symbol) read to worng temp registe"); + + + osal_gettimeofday(&sec_end, &usec_end); + wmt_step_test_show_result_report("STEP result: Create condition register action result", + &temp_report, sec_begin, usec_begin, sec_end, usec_end); + wmt_step_test_update_result_report(p_report, &temp_report); +} + +int wmt_step_test_get_symbol_num(void) +{ + int len = 0; + struct device_node *node = NULL; + + if (g_pdev != NULL) { + node = g_pdev->dev.of_node; + if (node) { + of_get_property(node, "reg", &len); + len /= (of_n_addr_cells(node) + of_n_size_cells(node)); + len /= (sizeof(int)); + } else { + WMT_ERR_FUNC("STEP test failed: node null"); + return -1; + } + } else { + WMT_ERR_FUNC("STEP test failed: gdev null"); + return -1; + } + + return len; +} + +void wmt_step_test_check_register_symbol(struct step_test_report *p_report) +{ + enum step_action_id act_id; + char *params[STEP_PARAMETER_SIZE]; + int check_params[STEP_PARAMETER_SIZE]; + struct step_test_report temp_report = {0, 0, 0}; + int sec_begin = 0; + int usec_begin = 0; + int sec_end = 0; + int usec_end = 0; + int param_num = 0; + int i = 0; + int symbol_num = wmt_step_test_get_symbol_num(); + unsigned char buf[4]; + + WMT_INFO_FUNC("STEP test: Check Register symbol start\n"); + osal_gettimeofday(&sec_begin, &usec_begin); + act_id = STEP_ACTION_INDEX_REGISTER; + /********************************************************* + ******************** Test case 1 *********************** + ********** REGISTER(Symbol) create for read ************* + *********************************************************/ + WMT_INFO_FUNC("STEP test: TC 1\n"); + if (symbol_num < 0) { + temp_report.fail++; + } else { + if (symbol_num >= STEP_REGISTER_MAX) { + symbol_num = STEP_REGISTER_MAX - 1; + } + + for (i = 1; i <= symbol_num; i++) { + wmt_step_test_clear_parameter(params); + params[0] = "0"; + if (snprintf(buf, 4, "#%d", i) < 0) + WMT_INFO_FUNC("[%s::%d] snprintf buf fail\n", __func__, __LINE__); + else + params[1] = buf; + params[2] = "0x9c"; + params[3] = "1"; + params[4] = "10"; + param_num = 5; + check_params[0] = 0; + check_params[1] = i; + check_params[2] = 0x9c; + check_params[3] = 1; + check_params[4] = 10; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Check Register symbol TC-1) REGISTER(Symbol) create for read"); + } + } + + osal_gettimeofday(&sec_end, &usec_end); + wmt_step_test_show_result_report("STEP result: Check Register symbol result", + &temp_report, sec_begin, usec_begin, sec_end, usec_end); + wmt_step_test_update_result_report(p_report, &temp_report); +} + +void wmt_step_test_create_other_action(struct step_test_report *p_report) +{ + enum step_action_id act_id; + char *params[STEP_PARAMETER_SIZE]; + int check_params[STEP_PARAMETER_SIZE]; + struct step_test_report temp_report = {0, 0, 0}; + int sec_begin = 0; + int usec_begin = 0; + int sec_end = 0; + int usec_end = 0; + struct step_pd_entry fack_pd_entry; + int param_num = 0; + + WMT_INFO_FUNC("STEP test: Create other action start\n"); + osal_gettimeofday(&sec_begin, &usec_begin); + /****************************************** + ************ Test case 1 ***************** + ********** GPIO create for read ********** + ******************************************/ + WMT_INFO_FUNC("STEP test: TC 1\n"); + wmt_step_test_clear_parameter(params); + act_id = STEP_ACTION_INDEX_GPIO; + params[0] = "0"; + params[1] = "8"; + param_num = 2; + check_params[0] = 0; + check_params[1] = 8; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-1) GPIO create read"); + + /***************************************** + ************ Test case 2 **************** + ********* DISABLE REST create *********** + *****************************************/ + WMT_INFO_FUNC("STEP test: TC 2\n"); + wmt_step_test_clear_parameter(params); + act_id = STEP_ACTION_INDEX_DISABLE_RESET; + param_num = 0; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-2) DISABLE REST"); + + /***************************************** + ************ Test case 3 **************** + ********** CHIP REST create ************* + *****************************************/ + WMT_INFO_FUNC("STEP test: TC 3\n"); + wmt_step_test_clear_parameter(params); + act_id = STEP_ACTION_INDEX_CHIP_RESET; + param_num = 0; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-3) CHIP REST"); + + /***************************************** + ************ Test case 4 **************** + ******** Keep Wakeup create ************* + *****************************************/ + WMT_INFO_FUNC("STEP test: TC 4\n"); + wmt_step_test_clear_parameter(params); + act_id = STEP_ACTION_INDEX_KEEP_WAKEUP; + param_num = 0; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-4) Keep wakeup"); + + /***************************************** + ************ Test case 5 **************** + ***** Cancel keep wakeup create ********* + *****************************************/ + WMT_INFO_FUNC("STEP test: TC 5\n"); + wmt_step_test_clear_parameter(params); + act_id = STEP_ACTION_INDEX_CANCEL_WAKEUP; + param_num = 0; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-5) Cancel keep wakeup"); + + /************************************************* + **************** Test case 6 ******************* + ********** GPIO create fail less param ********** + *************************************************/ + WMT_INFO_FUNC("STEP test: TC 6\n"); + wmt_step_test_clear_parameter(params); + act_id = STEP_ACTION_INDEX_GPIO; + params[0] = "0"; + param_num = 1; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-6) GPIO create fail"); + + /************************************************* + **************** Test case 7 ******************* + ************** Periodic dump create ************* + *************************************************/ + WMT_INFO_FUNC("STEP test: TC 7\n"); + wmt_step_test_clear_parameter(params); + act_id = STEP_ACTION_INDEX_PERIODIC_DUMP; + params[0] = (PINT8)&fack_pd_entry; + param_num = 1; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-7) Periodic dump create fail"); + + /************************************************* + **************** Test case 8 ******************* + ****** Periodic dump create fail no param ******* + *************************************************/ + WMT_INFO_FUNC("STEP test: TC 8\n"); + wmt_step_test_clear_parameter(params); + act_id = STEP_ACTION_INDEX_PERIODIC_DUMP; + param_num = 0; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-8) Periodic dump create fail"); + + /************************************************* + **************** Test case 9 ******************* + **************** Show create ******************** + *************************************************/ + WMT_INFO_FUNC("STEP test: TC 9\n"); + wmt_step_test_clear_parameter(params); + act_id = STEP_ACTION_INDEX_SHOW_STRING; + params[0] = "Hello"; + param_num = 1; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-9) Show create"); + + /************************************************* + **************** Test case 10 ******************* + ******** Show create failed no param ************ + *************************************************/ + WMT_INFO_FUNC("STEP test: TC 10\n"); + wmt_step_test_clear_parameter(params); + act_id = STEP_ACTION_INDEX_SHOW_STRING; + param_num = 0; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-10) Show create failed no param"); + + /************************************************* + **************** Test case 11 ******************* + **************** Sleep create ******************* + *************************************************/ + WMT_INFO_FUNC("STEP test: TC 11\n"); + wmt_step_test_clear_parameter(params); + act_id = STEP_ACTION_INDEX_SLEEP; + params[0] = "1000"; + param_num = 1; + check_params[0] = 1000; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-11) Sleep create"); + + /************************************************* + **************** Test case 12 ******************* + ********* Sleep create failed no param ********** + *************************************************/ + WMT_INFO_FUNC("STEP test: TC 12\n"); + wmt_step_test_clear_parameter(params); + act_id = STEP_ACTION_INDEX_SLEEP; + param_num = 0; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-12) Sleep create failed no param"); + + /************************************************* + **************** Test case 13 ******************* + ************** Condition create ***************** + *************************************************/ + WMT_INFO_FUNC("STEP test: TC 13\n"); + wmt_step_test_clear_parameter(params); + act_id = STEP_ACTION_INDEX_CONDITION; + params[0] = "$0"; + params[1] = "$1"; + params[2] = "=="; + params[3] = "$2"; + param_num = 4; + check_params[0] = 0; + check_params[1] = 1; + check_params[2] = STEP_OPERATOR_EQUAL; + check_params[3] = 2; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-13) Condition create"); + + /************************************************* + **************** Test case 14 ******************* + *********** Condition create value ************** + *************************************************/ + WMT_INFO_FUNC("STEP test: TC 14\n"); + wmt_step_test_clear_parameter(params); + act_id = STEP_ACTION_INDEX_CONDITION; + params[0] = "$0"; + params[1] = "$1"; + params[2] = "=="; + params[3] = "16"; + param_num = 4; + check_params[0] = 0; + check_params[1] = 1; + check_params[2] = STEP_OPERATOR_EQUAL; + check_params[3] = 16; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-14) Condition create"); + + /************************************************* + **************** Test case 15 ******************* + ****** Condition create failed less param ******* + *************************************************/ + WMT_INFO_FUNC("STEP test: TC 15\n"); + wmt_step_test_clear_parameter(params); + act_id = STEP_ACTION_INDEX_CONDITION; + params[0] = "$0"; + params[1] = "$1"; + params[2] = "$2"; + param_num = 3; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-15) Condition create failed less param"); + + /************************************************* + **************** Test case 16 ******************* + ******** Condition create failed no value******** + *************************************************/ + WMT_INFO_FUNC("STEP test: TC 16\n"); + wmt_step_test_clear_parameter(params); + act_id = STEP_ACTION_INDEX_CONDITION; + params[0] = "=="; + param_num = 1; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-16) Condition create failed no value"); + + /************************************************* + **************** Test case 17 ******************* + * Boundary: Condition create failed over reg id * + *************************************************/ + WMT_INFO_FUNC("STEP test: TC 17\n"); + wmt_step_test_clear_parameter(params); + act_id = STEP_ACTION_INDEX_CONDITION; + params[0] = "$25"; + params[1] = "$1"; + params[2] = "=="; + params[3] = "$2"; + param_num = 4; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-17) Boundary: Condition create failed over reg id"); + + /************************************************* + **************** Test case 18 ******************* + * Boundary: Condition create failed over reg id * + *************************************************/ + WMT_INFO_FUNC("STEP test: TC 18\n"); + wmt_step_test_clear_parameter(params); + act_id = STEP_ACTION_INDEX_CONDITION; + params[0] = "$0"; + params[1] = "$1"; + params[2] = "=="; + params[3] = "$20"; + param_num = 4; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-18) Boundary: Condition create failed over reg id"); + + /************************************************* + **************** Test case 19 ******************* + ******** Condition create failed operator******** + *************************************************/ + WMT_INFO_FUNC("STEP test: TC 19\n"); + wmt_step_test_clear_parameter(params); + act_id = STEP_ACTION_INDEX_CONDITION; + params[0] = "$0"; + params[1] = "$1"; + params[2] = "&"; + params[3] = "$2"; + param_num = 4; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-19) Condition create failed operator"); + + /************************************************* + **************** Test case 20 ******************* + **************** Value create ******************* + *************************************************/ + WMT_INFO_FUNC("STEP test: TC 20\n"); + wmt_step_test_clear_parameter(params); + act_id = STEP_ACTION_INDEX_VALUE; + params[0] = "$0"; + params[1] = "0x123"; + param_num = 2; + check_params[0] = 0; + check_params[1] = 0x123; + __wmt_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report, + "STEP test case failed: (Create action TC-20) Condition create"); + + /************************************************* + **************** Test case 21 ******************* + ******* Value create failed wrong order ********* + *************************************************/ + WMT_INFO_FUNC("STEP test: TC 21\n"); + wmt_step_test_clear_parameter(params); + act_id = STEP_ACTION_INDEX_VALUE; + params[0] = "0x123"; + params[1] = "$1"; + param_num = 2; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-21) Value create failed wrong order"); + + /************************************************* + **************** Test case 22 ******************* + ********* Value create failed no value ********** + *************************************************/ + WMT_INFO_FUNC("STEP test: TC 22\n"); + wmt_step_test_clear_parameter(params); + act_id = STEP_ACTION_INDEX_VALUE; + params[0] = "$1"; + param_num = 1; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-22) Value create failed no value"); + + /************************************************* + **************** Test case 23 ******************* + *** Boundary: Value create failed over reg id *** + *************************************************/ + WMT_INFO_FUNC("STEP test: TC 23\n"); + wmt_step_test_clear_parameter(params); + act_id = STEP_ACTION_INDEX_VALUE; + params[0] = "$25"; + params[1] = "0x123"; + param_num = 2; + __wmt_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report, + "STEP test case failed: (Create action TC-23) Boundary: Value create failed over reg id"); + + osal_gettimeofday(&sec_end, &usec_end); + wmt_step_test_show_result_report("STEP result: Create other action result", + &temp_report, sec_begin, usec_begin, sec_end, usec_end); + wmt_step_test_update_result_report(p_report, &temp_report); +} + +int wmt_step_test_get_emi_wmt_offset(unsigned char buf[], int offset) +{ + P_CONSYS_EMI_ADDR_INFO emi_phy_addr; + + emi_phy_addr = mtk_wcn_consys_soc_get_emi_phy_add(); + if (emi_phy_addr != NULL) { + if (snprintf(buf, 11, "0x%08x", ((unsigned int)emi_phy_addr->emi_core_dump_offset + offset)) < 0) { + WMT_INFO_FUNC("[%s::%d] snprintf buf fail\n", __func__, __LINE__); + return -1; + } + } else { + WMT_ERR_FUNC("STEP test failed: emi_phy_addr is NULL\n"); + return -1; + } + + return 0; +} + +void wmt_step_test_do_emi_action(struct step_test_report *p_report) +{ + enum step_action_id act_id; + char *params[STEP_PARAMETER_SIZE]; + struct step_test_report temp_report = {0, 0, 0}; + int sec_begin = 0; + int usec_begin = 0; + int sec_end = 0; + int usec_end = 0; + unsigned char buf_begin[11]; + unsigned char buf_end[11]; + int param_num; + + WMT_INFO_FUNC("STEP test: Do EMI action start\n"); + osal_gettimeofday(&sec_begin, &usec_begin); + act_id = STEP_ACTION_INDEX_EMI; + + if (wmt_step_test_get_emi_wmt_offset(buf_begin, 0x0) != 0) { + temp_report.fail++; + osal_gettimeofday(&sec_end, &usec_end); + wmt_step_test_show_result_report("STEP result: Do EMI action result", + &temp_report, sec_begin, usec_begin, sec_end, usec_end); + wmt_step_test_update_result_report(p_report, &temp_report); + return; + } + + /***************************************** + ************ Test case 1 **************** + ********** EMI dump 32 bit ************** + *****************************************/ + WMT_INFO_FUNC("STEP test: TC 1\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + wmt_step_test_get_emi_wmt_offset(buf_begin, 0x44); + params[1] = buf_begin; + wmt_step_test_get_emi_wmt_offset(buf_end, 0x48); + params[2] = buf_end; + param_num = 3; + g_step_test_check.step_check_total = 1; + g_step_test_check.step_check_emi_offset[0] = 0x44; + __wmt_step_test_do_emi_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do EMI action TC-1) dump 32bit"); + + /***************************************** + ************ Test case 2 **************** + ****** EMI dump check for address ******* + *****************************************/ + WMT_INFO_FUNC("STEP test: TC 2\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + wmt_step_test_get_emi_wmt_offset(buf_begin, 0x24); + params[1] = buf_begin; + wmt_step_test_get_emi_wmt_offset(buf_end, 0x44); + params[2] = buf_end; + param_num = 3; + g_step_test_check.step_check_total = 8; + g_step_test_check.step_check_emi_offset[0] = 0x24; + g_step_test_check.step_check_emi_offset[1] = 0x28; + g_step_test_check.step_check_emi_offset[2] = 0x2c; + g_step_test_check.step_check_emi_offset[3] = 0x30; + g_step_test_check.step_check_emi_offset[4] = 0x34; + g_step_test_check.step_check_emi_offset[5] = 0x38; + g_step_test_check.step_check_emi_offset[6] = 0x3c; + g_step_test_check.step_check_emi_offset[7] = 0x40; + __wmt_step_test_do_emi_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do EMI action TC-2) more address"); + + /***************************************** + ************ Test case 3 **************** + **** EMI dump begin larger than end ***** + *****************************************/ + WMT_INFO_FUNC("STEP test: TC 3\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + wmt_step_test_get_emi_wmt_offset(buf_begin, 0x20); + params[1] = buf_begin; + wmt_step_test_get_emi_wmt_offset(buf_end, 0x08); + params[2] = buf_end; + param_num = 3; + g_step_test_check.step_check_total = 6; + g_step_test_check.step_check_emi_offset[0] = 0x08; + g_step_test_check.step_check_emi_offset[1] = 0x0c; + g_step_test_check.step_check_emi_offset[2] = 0x10; + g_step_test_check.step_check_emi_offset[3] = 0x14; + g_step_test_check.step_check_emi_offset[4] = 0x18; + g_step_test_check.step_check_emi_offset[5] = 0x1c; + __wmt_step_test_do_emi_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do EMI action TC-3) begin larger than end"); + + /**************************************** + ************ Test case 4 *************** + ******** EMI only support read ********* + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 4\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + params[0] = "1"; + wmt_step_test_get_emi_wmt_offset(buf_begin, 0x08); + params[1] = buf_begin; + wmt_step_test_get_emi_wmt_offset(buf_end, 0x20); + params[2] = buf_end; + param_num = 3; + __wmt_step_test_do_emi_action(act_id, param_num, params, -1, &temp_report, + "STEP test case failed: (Do EMI action TC-4) only support read"); + + /**************************************** + ************ Test case 5 *************** + ********* EMI dump not 32bit *********** + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 5\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + wmt_step_test_get_emi_wmt_offset(buf_begin, 0x08); + params[1] = buf_begin; + wmt_step_test_get_emi_wmt_offset(buf_end, 0x0e); + params[2] = buf_end; + param_num = 3; + g_step_test_check.step_check_total = 2; + g_step_test_check.step_check_emi_offset[0] = 0x08; + g_step_test_check.step_check_emi_offset[1] = 0x0c; + __wmt_step_test_do_emi_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do EMI action TC-5) not 32bit"); + + /***************************************** + ************ Test case 6 **************** + ***** EMI dump over emi max size ******** + *****************************************/ + WMT_INFO_FUNC("STEP test: TC 6\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + wmt_step_test_get_emi_wmt_offset(buf_begin, (gConEmiSize + 0x08)); + params[1] = buf_begin; + wmt_step_test_get_emi_wmt_offset(buf_end, (gConEmiSize + 0x0e)); + params[2] = buf_end; + param_num = 3; + __wmt_step_test_do_emi_action(act_id, param_num, params, -1, &temp_report, + "STEP test case failed: (Do EMI action TC-6) over emi max size"); + + /***************************************** + ************ Test case 7 **************** + ************* page fault **************** + *****************************************/ + WMT_INFO_FUNC("STEP test: TC 7\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + wmt_step_test_get_emi_wmt_offset(buf_begin, 0x02); + params[1] = buf_begin; + wmt_step_test_get_emi_wmt_offset(buf_end, 0x08); + params[2] = buf_end; + param_num = 3; + __wmt_step_test_do_emi_action(act_id, param_num, params, -1, &temp_report, + "STEP test case failed: (Do EMI action TC-7) page fault"); + + /***************************************** + ************ Test case 8 **************** + ********** save to temp reg ************* + *****************************************/ + WMT_INFO_FUNC("STEP test: TC 8\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "0"; + wmt_step_test_get_emi_wmt_offset(buf_begin, 0x08); + params[1] = buf_begin; + params[2] = "0x0F0F0F0F"; + params[3] = "$1"; + param_num = 4; + g_step_test_check.step_check_total = 1; + g_step_test_check.step_check_emi_offset[0] = 0x08; + g_step_test_check.step_test_mask = 0x0F0F0F0F; + g_step_test_check.step_check_temp_register_id = 1; + __wmt_step_test_do_emi_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do EMI action TC-8) save to temp reg"); + + osal_gettimeofday(&sec_end, &usec_end); + wmt_step_test_show_result_report("STEP result: Do EMI action result", + &temp_report, sec_begin, usec_begin, sec_end, usec_end); + wmt_step_test_update_result_report(p_report, &temp_report); +} + +void wmt_step_test_do_cond_emi_action(struct step_test_report *p_report) +{ + enum step_action_id act_id; + char *params[STEP_PARAMETER_SIZE]; + struct step_test_report temp_report = {0, 0, 0}; + int sec_begin = 0; + int usec_begin = 0; + int sec_end = 0; + int usec_end = 0; + unsigned char buf_begin[11]; + unsigned char buf_end[11]; + int param_num; + + WMT_INFO_FUNC("STEP test: Do condition EMI action start\n"); + osal_gettimeofday(&sec_begin, &usec_begin); + act_id = STEP_ACTION_INDEX_CONDITION_EMI; + /***************************************** + ************ Test case 1 **************** + ********** EMI dump 32 bit ************** + *****************************************/ + WMT_INFO_FUNC("STEP test: TC 1\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "$0"; + params[1] = "0"; + wmt_step_test_get_emi_wmt_offset(buf_begin, 0x44); + params[2] = buf_begin; + wmt_step_test_get_emi_wmt_offset(buf_end, 0x48); + params[3] = buf_end; + param_num = 4; + g_step_env.temp_register[0] = 1; + + g_step_test_check.step_check_total = 1; + g_step_test_check.step_check_emi_offset[0] = 0x44; + __wmt_step_test_do_cond_emi_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do COND EMI action TC-1) dump 32bit"); + + /***************************************** + ************ Test case 2 **************** + ****** EMI dump check for address ******* + *****************************************/ + WMT_INFO_FUNC("STEP test: TC 2\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "$1"; + params[1] = "0"; + wmt_step_test_get_emi_wmt_offset(buf_begin, 0x24); + params[2] = buf_begin; + wmt_step_test_get_emi_wmt_offset(buf_end, 0x44); + params[3] = buf_end; + param_num = 4; + g_step_env.temp_register[1] = 1; + + g_step_test_check.step_check_total = 8; + g_step_test_check.step_check_emi_offset[0] = 0x24; + g_step_test_check.step_check_emi_offset[1] = 0x28; + g_step_test_check.step_check_emi_offset[2] = 0x2c; + g_step_test_check.step_check_emi_offset[3] = 0x30; + g_step_test_check.step_check_emi_offset[4] = 0x34; + g_step_test_check.step_check_emi_offset[5] = 0x38; + g_step_test_check.step_check_emi_offset[6] = 0x3c; + g_step_test_check.step_check_emi_offset[7] = 0x40; + __wmt_step_test_do_cond_emi_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do COND EMI action TC-2) more address"); + + /***************************************** + ************ Test case 3 **************** + **** EMI dump begin larger than end ***** + *****************************************/ + WMT_INFO_FUNC("STEP test: TC 3\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "$0"; + params[1] = "0"; + wmt_step_test_get_emi_wmt_offset(buf_begin, 0x20); + params[2] = buf_begin; + wmt_step_test_get_emi_wmt_offset(buf_end, 0x08); + params[3] = buf_end; + param_num = 4; + g_step_env.temp_register[0] = 15; + + g_step_test_check.step_check_total = 6; + g_step_test_check.step_check_emi_offset[0] = 0x08; + g_step_test_check.step_check_emi_offset[1] = 0x0c; + g_step_test_check.step_check_emi_offset[2] = 0x10; + g_step_test_check.step_check_emi_offset[3] = 0x14; + g_step_test_check.step_check_emi_offset[4] = 0x18; + g_step_test_check.step_check_emi_offset[5] = 0x1c; + __wmt_step_test_do_cond_emi_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do COND EMI action TC-3) begin larger than end"); + + /**************************************** + ************ Test case 4 *************** + ******** EMI only support read ********* + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 4\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "$1"; + params[1] = "1"; + wmt_step_test_get_emi_wmt_offset(buf_begin, 0x08); + params[2] = buf_begin; + wmt_step_test_get_emi_wmt_offset(buf_end, 0x20); + params[3] = buf_end; + param_num = 4; + g_step_env.temp_register[1] = 1; + + __wmt_step_test_do_cond_emi_action(act_id, param_num, params, -1, &temp_report, + "STEP test case failed: (Do COND EMI action TC-4) only support read"); + + /**************************************** + ************ Test case 5 *************** + ********* EMI dump not 32bit *********** + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 5\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "$0"; + params[1] = "0"; + wmt_step_test_get_emi_wmt_offset(buf_begin, 0x08); + params[2] = buf_begin; + wmt_step_test_get_emi_wmt_offset(buf_end, 0x0e); + params[3] = buf_end; + param_num = 4; + g_step_env.temp_register[0] = 1; + + g_step_test_check.step_check_total = 2; + g_step_test_check.step_check_emi_offset[0] = 0x08; + g_step_test_check.step_check_emi_offset[1] = 0x0c; + __wmt_step_test_do_cond_emi_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do COND EMI action TC-5) not 32bit"); + + /***************************************** + ************ Test case 6 **************** + ***** EMI dump over emi max size ******** + *****************************************/ + WMT_INFO_FUNC("STEP test: TC 6\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "$9"; + params[1] = "0"; + wmt_step_test_get_emi_wmt_offset(buf_begin, (gConEmiSize + 0x08)); + params[2] = buf_begin; + wmt_step_test_get_emi_wmt_offset(buf_end, (gConEmiSize + 0x0e)); + params[3] = buf_end; + param_num = 4; + g_step_env.temp_register[9] = 1; + + __wmt_step_test_do_cond_emi_action(act_id, param_num, params, -1, &temp_report, + "STEP test case failed: (Do COND EMI action TC-6) over emi max size"); + + /***************************************** + ************ Test case 7 **************** + ************* page fault **************** + *****************************************/ + WMT_INFO_FUNC("STEP test: TC 7\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "$0"; + params[1] = "0"; + wmt_step_test_get_emi_wmt_offset(buf_begin, 0x02); + params[2] = buf_begin; + wmt_step_test_get_emi_wmt_offset(buf_end, 0x08); + params[3] = buf_end; + param_num = 4; + g_step_env.temp_register[0] = 1; + + __wmt_step_test_do_cond_emi_action(act_id, param_num, params, -1, &temp_report, + "STEP test case failed: (Do COND EMI action TC-7) page fault"); + + /***************************************** + ************ Test case 8 **************** + ********** save to temp reg ************* + *****************************************/ + WMT_INFO_FUNC("STEP test: TC 8\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "$0"; + params[1] = "0"; + wmt_step_test_get_emi_wmt_offset(buf_begin, 0x08); + params[2] = buf_begin; + params[3] = "0x0F0F0F0F"; + params[4] = "$1"; + param_num = 5; + g_step_test_check.step_check_total = 1; + g_step_test_check.step_check_emi_offset[0] = 0x08; + g_step_test_check.step_test_mask = 0x0F0F0F0F; + g_step_test_check.step_check_temp_register_id = 1; + g_step_env.temp_register[0] = 1; + __wmt_step_test_do_cond_emi_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do EMI action TC-8) save to temp reg"); + + + /***************************************** + ************ Test case 9 **************** + ******** condition invalid ************** + *****************************************/ + WMT_INFO_FUNC("STEP test: TC 9\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "$0"; + params[1] = "0"; + wmt_step_test_get_emi_wmt_offset(buf_begin, 0x08); + params[2] = buf_begin; + wmt_step_test_get_emi_wmt_offset(buf_end, 0x0e); + params[3] = buf_end; + param_num = 4; + g_step_env.temp_register[0] = 0; + + __wmt_step_test_do_cond_emi_action(act_id, param_num, params, -1, &temp_report, + "STEP test case failed: (Do COND EMI action TC-9) condition invalid"); + + osal_gettimeofday(&sec_end, &usec_end); + wmt_step_test_show_result_report("STEP result: Do condition EMI action result", + &temp_report, sec_begin, usec_begin, sec_end, usec_end); + wmt_step_test_update_result_report(p_report, &temp_report); +} + +int wmt_step_test_get_reg_base_phy_addr(unsigned char buf[], unsigned int index) +{ + struct device_node *node = NULL; + struct resource res; + int ret; + + if (g_pdev != NULL) { + node = g_pdev->dev.of_node; + if (node) { + ret = of_address_to_resource(node, index, &res); + if (ret) { + WMT_ERR_FUNC("STEP test failed: of_address_to_resource null"); + return ret; + } + } else { + WMT_ERR_FUNC("STEP test failed: node null"); + return -1; + } + } else { + WMT_ERR_FUNC("STEP test failed: gdev null"); + return -1; + } + snprintf(buf, 11, "0x%08x", ((unsigned int)res.start)); + + return 0; +} + +void wmt_step_test_do_register_action(struct step_test_report *p_report) +{ + enum step_action_id act_id; + char *params[STEP_PARAMETER_SIZE]; + struct step_test_report temp_report = {0, 0, 0}; + int sec_begin = 0; + int usec_begin = 0; + int sec_end = 0; + int usec_end = 0; + unsigned char buf[11]; + int param_num; + int can_write_offset = 0; + unsigned char can_write_offset_char[11]; + + WMT_INFO_FUNC("STEP test: Do register action start\n"); + + can_write_offset = + wmt_step_test_find_can_write_register(conn_reg.mcu_base, 0x200, 0x0000000F); + if (can_write_offset == -1) { + p_report->fail++; + WMT_ERR_FUNC("STEP test: Do register action init can_write_offset failed\n"); + return; + } + if (snprintf(can_write_offset_char, 11, "0x%08x", can_write_offset) < 0) + WMT_INFO_FUNC("[%s::%d] snprintf can_write_offset_char fail\n", __func__, __LINE__); + + osal_gettimeofday(&sec_begin, &usec_begin); + act_id = STEP_ACTION_INDEX_REGISTER; + /**************************************** + ************ Test case 1 *************** + ******** REG read MCU chip id ********** + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 1\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + params[1] = "#1"; + params[2] = "0x08"; + params[3] = "1"; + params[4] = "0"; + param_num = 5; + g_step_test_check.step_check_register_addr = (conn_reg.mcu_base + 0x08); + __wmt_step_test_do_register_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do register action TC-1) MCU chip id"); + + /**************************************** + ************ Test case 2 *************** + *** REG read cpucpr 5 times / 3ms **** + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 2\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + params[1] = "#1"; + params[2] = "0x160"; + params[3] = "5"; + params[4] = "3"; + param_num = 5; + g_step_test_check.step_check_register_addr = (conn_reg.mcu_base + 0x160); + __wmt_step_test_do_register_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do register action TC-2) cpucpr 5 times / 3ms"); + + /********************************************** + *************** Test case 3 ****************** + ** REG read MCU chip id by physical address ** + **********************************************/ + WMT_INFO_FUNC("STEP test: TC 3\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + if (wmt_step_test_get_reg_base_phy_addr(buf, 0) == 0) { + params[1] = buf; + params[2] = "0x08"; + params[3] = "1"; + params[4] = "0"; + param_num = 5; + g_step_test_check.step_check_register_addr = (conn_reg.mcu_base + 0x08); + __wmt_step_test_do_register_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do register action TC-3) MCU chip id by phy"); + } else { + p_report->fail++; + WMT_ERR_FUNC("STEP test case failed: get physical address failed\n"); + } + + /********************************************************* + ********************* Test case 4 *********************** + ** REG read cpucpr 5 times / 3ms by physical address ** + *********************************************************/ + WMT_INFO_FUNC("STEP test: TC 4\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + if (wmt_step_test_get_reg_base_phy_addr(buf, 0) == 0) { + params[1] = buf; + params[2] = "0x160"; + params[3] = "5"; + params[4] = "3"; + param_num = 5; + g_step_test_check.step_check_register_addr = (conn_reg.mcu_base + 0x160); + __wmt_step_test_do_register_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do register action TC-4) cpucpr 5 times / 3ms by phy"); + } else { + p_report->fail++; + WMT_ERR_FUNC("STEP test case failed: get physical address failed\n"); + } + + /***************************************** + ************* Test case 5 *************** + ******** REG read over base size ******** + *****************************************/ + WMT_INFO_FUNC("STEP test: TC 5\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + params[1] = "#1"; + params[2] = "0x11204"; + params[3] = "1"; + params[4] = "0"; + param_num = 5; + __wmt_step_test_do_register_action(act_id, param_num, params, -1, &temp_report, + "STEP test case failed: (Do register action TC-5) Over size"); + + /****************************************** + ************** Test case 6 *************** + ***** REG read over base size by phy ***** + ******************************************/ + WMT_INFO_FUNC("STEP test: TC 6\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + if (wmt_step_test_get_reg_base_phy_addr(buf, 0) == 0) { + params[1] = buf; + params[2] = "0x204"; + params[3] = "1"; + params[4] = "0"; + param_num = 5; + g_step_test_check.step_check_register_addr = (conn_reg.mcu_base + 0x204); + __wmt_step_test_do_register_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do register action TC-6) Over size by phy"); + } else { + p_report->fail++; + WMT_ERR_FUNC("STEP test case failed: get physical address failed\n"); + } + + /****************************************** + ************** Test case 7 *************** + *************** REG write **************** + ******************************************/ + WMT_INFO_FUNC("STEP test: TC 7\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + params[0] = "1"; + params[1] = "#1"; + params[2] = can_write_offset_char; + params[3] = "0x2"; + param_num = 4; + g_step_test_check.step_check_register_addr = (conn_reg.mcu_base + can_write_offset); + g_step_test_check.step_check_write_value = 0x2; + __wmt_step_test_do_register_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do register action TC-7) REG write"); + + /****************************************** + ************** Test case 8 *************** + *********** REG write by phy ************* + ******************************************/ + WMT_INFO_FUNC("STEP test: TC 8\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + params[0] = "1"; + if (wmt_step_test_get_reg_base_phy_addr(buf, 0) == 0) { + params[1] = buf; + params[2] = can_write_offset_char; + params[3] = "0x7"; + param_num = 4; + g_step_test_check.step_check_register_addr = (conn_reg.mcu_base + can_write_offset); + g_step_test_check.step_check_write_value = 0x7; + __wmt_step_test_do_register_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do register action TC-8) REG write by phy"); + } else { + p_report->fail++; + WMT_ERR_FUNC("STEP test case failed: get physical address failed\n"); + } + + /****************************************** + ************** Test case 9 *************** + ************* REG write bit ************** + ******************************************/ + WMT_INFO_FUNC("STEP test: TC 9\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + params[0] = "1"; + params[1] = "#1"; + params[2] = can_write_offset_char; + params[3] = "0x321"; + params[4] = "0x00F"; + param_num = 5; + g_step_test_check.step_check_register_addr = (conn_reg.mcu_base + can_write_offset); + g_step_test_check.step_check_write_value = 0x001; + g_step_test_check.step_test_mask = 0x00F; + __wmt_step_test_do_register_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do register action TC-9) REG write bit"); + + /****************************************** + ************** Test case 10 ************** + ********* REG write bit by phy *********** + ******************************************/ + WMT_INFO_FUNC("STEP test: TC 10\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + params[0] = "1"; + if (wmt_step_test_get_reg_base_phy_addr(buf, 0) == 0) { + params[1] = buf; + params[2] = can_write_offset_char; + params[3] = "0x32f"; + params[4] = "0x002"; + param_num = 5; + g_step_test_check.step_check_register_addr = (conn_reg.mcu_base + can_write_offset); + g_step_test_check.step_check_write_value = 0x002; + g_step_test_check.step_test_mask = 0x002; + __wmt_step_test_do_register_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do register action TC-10) REG write bit by phy"); + } else { + p_report->fail++; + WMT_ERR_FUNC("STEP test case failed: get physical address failed\n"); + } + + /****************************************** + ************** Test case 11 ************** + ********* REG read to temp reg *********** + ******************************************/ + WMT_INFO_FUNC("STEP test: TC 11\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "0"; + params[1] = "#1"; + params[2] = "0x08"; + params[3] = "0x0F0F0F0F"; + params[4] = "$2"; + param_num = 5; + g_step_test_check.step_check_register_addr = (conn_reg.mcu_base + 0x08); + g_step_test_check.step_test_mask = 0x0F0F0F0F; + g_step_test_check.step_check_temp_register_id = 2; + __wmt_step_test_do_register_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do register action TC-11) REG read to temp reg"); + + /****************************************** + ************** Test case 12 ************** + ******* REG read phy to temp reg ********* + ******************************************/ + WMT_INFO_FUNC("STEP test: TC 12\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "0"; + if (wmt_step_test_get_reg_base_phy_addr(buf, 0) == 0) { + params[1] = buf; + params[2] = "0x08"; + params[3] = "0x0F0F0F0F"; + params[4] = "$3"; + param_num = 5; + g_step_test_check.step_check_register_addr = (conn_reg.mcu_base + 0x08); + g_step_test_check.step_test_mask = 0x0F0F0F0F; + g_step_test_check.step_check_temp_register_id = 3; + __wmt_step_test_do_register_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do register action TC-12) REG read phy to temp reg"); + } else { + p_report->fail++; + WMT_ERR_FUNC("STEP test case failed: get physical address failed\n"); + } + + osal_gettimeofday(&sec_end, &usec_end); + wmt_step_test_show_result_report("STEP result: Do register action result", + &temp_report, sec_begin, usec_begin, sec_end, usec_end); + wmt_step_test_update_result_report(p_report, &temp_report); +} + +void wmt_step_test_do_cond_register_action(struct step_test_report *p_report) +{ + enum step_action_id act_id; + char *params[STEP_PARAMETER_SIZE]; + struct step_test_report temp_report = {0, 0, 0}; + int sec_begin = 0; + int usec_begin = 0; + int sec_end = 0; + int usec_end = 0; + unsigned char buf[11]; + int param_num; + int can_write_offset = 0; + unsigned char can_write_offset_char[11]; + + WMT_INFO_FUNC("STEP test: Do condition register action start\n"); + + can_write_offset = + wmt_step_test_find_can_write_register(conn_reg.mcu_base, 0x200, 0x0000000F); + if (can_write_offset == -1) { + p_report->fail++; + WMT_ERR_FUNC("STEP test: Do register action init can_write_offset failed\n"); + return; + } + if (snprintf(can_write_offset_char, 11, "0x%08x", can_write_offset) < 0) + WMT_INFO_FUNC("[%s::%d] snprintf can_write_offset_char fail\n", __func__, __LINE__); + + osal_gettimeofday(&sec_begin, &usec_begin); + act_id = STEP_ACTION_INDEX_CONDITION_REGISTER; + /**************************************** + ************ Test case 1 *************** + ******** REG read MCU chip id ********** + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 1\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "$0"; + params[1] = "0"; + params[2] = "#1"; + params[3] = "0x08"; + params[4] = "1"; + params[5] = "0"; + param_num = 6; + g_step_env.temp_register[0] = 1; + + g_step_test_check.step_check_register_addr = (conn_reg.mcu_base + 0x08); + __wmt_step_test_do_cond_register_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do cond register action TC-1) MCU chip id"); + + /**************************************** + ************ Test case 2 *************** + *** REG read cpucpr 5 times / 3ms **** + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 2\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "$1"; + params[1] = "0"; + params[2] = "#1"; + params[3] = "0x160"; + params[4] = "5"; + params[5] = "3"; + param_num = 6; + g_step_env.temp_register[1] = 1; + + g_step_test_check.step_check_register_addr = (conn_reg.mcu_base + 0x160); + __wmt_step_test_do_cond_register_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do cond register action TC-2) cpucpr 5 times / 3ms"); + + /********************************************** + *************** Test case 3 ****************** + ** REG read MCU chip id by physical address ** + **********************************************/ + WMT_INFO_FUNC("STEP test: TC 3\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "$2"; + params[1] = "0"; + if (wmt_step_test_get_reg_base_phy_addr(buf, 0) == 0) { + params[2] = buf; + params[3] = "0x08"; + params[4] = "1"; + params[5] = "0"; + param_num = 6; + g_step_env.temp_register[2] = 1; + + g_step_test_check.step_check_register_addr = (conn_reg.mcu_base + 0x08); + __wmt_step_test_do_cond_register_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do cond register action TC-3) MCU chip id by phy"); + } else { + p_report->fail++; + WMT_ERR_FUNC("STEP test case failed: get physical address failed\n"); + } + + /********************************************************* + ********************* Test case 4 *********************** + ** REG read cpucpr 5 times / 3ms by physical address ** + *********************************************************/ + WMT_INFO_FUNC("STEP test: TC 4\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "$3"; + params[1] = "0"; + if (wmt_step_test_get_reg_base_phy_addr(buf, 0) == 0) { + params[2] = buf; + params[3] = "0x160"; + params[4] = "5"; + params[5] = "3"; + param_num = 6; + g_step_env.temp_register[3] = 11; + + g_step_test_check.step_check_register_addr = (conn_reg.mcu_base + 0x160); + __wmt_step_test_do_cond_register_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do cond register action TC-4) cpucpr 5 times / 3ms by phy"); + } else { + p_report->fail++; + WMT_ERR_FUNC("STEP test case failed: get physical address failed\n"); + } + + /***************************************** + ************* Test case 5 *************** + ******** REG read over base size ******** + *****************************************/ + WMT_INFO_FUNC("STEP test: TC 5\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "$4"; + params[1] = "0"; + params[2] = "#1"; + params[3] = "0x11204"; + params[4] = "1"; + params[5] = "0"; + param_num = 6; + g_step_env.temp_register[4] = 10; + + __wmt_step_test_do_cond_register_action(act_id, param_num, params, -1, &temp_report, + "STEP test case failed: (Do cond register action TC-5) Over size"); + + /****************************************** + ************** Test case 6 *************** + ***** REG read over base size by phy ***** + ******************************************/ + WMT_INFO_FUNC("STEP test: TC 6\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "$5"; + params[1] = "0"; + if (wmt_step_test_get_reg_base_phy_addr(buf, 0) == 0) { + params[2] = buf; + params[3] = "0x204"; + params[4] = "1"; + params[5] = "0"; + param_num = 6; + g_step_env.temp_register[5] = 1; + + g_step_test_check.step_check_register_addr = (conn_reg.mcu_base + 0x204); + __wmt_step_test_do_cond_register_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do cond register action TC-6) Over size by phy"); + } else { + p_report->fail++; + WMT_ERR_FUNC("STEP test case failed: get physical address failed\n"); + } + + /****************************************** + ************** Test case 7 *************** + *************** REG write **************** + ******************************************/ + WMT_INFO_FUNC("STEP test: TC 7\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "$6"; + params[1] = "1"; + params[2] = "#1"; + params[3] = can_write_offset_char; + params[4] = "0x2"; + param_num = 5; + g_step_env.temp_register[6] = 1; + + g_step_test_check.step_check_register_addr = (conn_reg.mcu_base + can_write_offset); + g_step_test_check.step_check_write_value = 0x2; + __wmt_step_test_do_cond_register_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do cond register action TC-7) REG write"); + + /****************************************** + ************** Test case 8 *************** + *********** REG write by phy ************* + ******************************************/ + WMT_INFO_FUNC("STEP test: TC 8\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "$7"; + params[1] = "1"; + if (wmt_step_test_get_reg_base_phy_addr(buf, 0) == 0) { + params[2] = buf; + params[3] = can_write_offset_char; + params[4] = "0x7"; + param_num = 5; + g_step_env.temp_register[7] = 1; + + g_step_test_check.step_check_register_addr = (conn_reg.mcu_base + can_write_offset); + g_step_test_check.step_check_write_value = 0x7; + __wmt_step_test_do_cond_register_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do cond register action TC-8) REG write by phy"); + } else { + p_report->fail++; + WMT_ERR_FUNC("STEP test case failed: get physical address failed\n"); + } + + /****************************************** + ************** Test case 9 *************** + ************* REG write bit ************** + ******************************************/ + WMT_INFO_FUNC("STEP test: TC 9\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "$8"; + params[1] = "1"; + params[2] = "#1"; + params[3] = can_write_offset_char; + params[4] = "0x321"; + params[5] = "0x00F"; + param_num = 6; + g_step_env.temp_register[8] = 1; + + g_step_test_check.step_check_register_addr = (conn_reg.mcu_base + can_write_offset); + g_step_test_check.step_check_write_value = 0x001; + g_step_test_check.step_test_mask = 0x00F; + __wmt_step_test_do_cond_register_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do cond register action TC-9) REG write bit"); + + /****************************************** + ************** Test case 10 ************** + ********* REG write bit by phy *********** + ******************************************/ + WMT_INFO_FUNC("STEP test: TC 10\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "$9"; + params[1] = "1"; + if (wmt_step_test_get_reg_base_phy_addr(buf, 0) == 0) { + params[2] = buf; + params[3] = can_write_offset_char; + params[4] = "0x32f"; + params[5] = "0x002"; + param_num = 6; + g_step_env.temp_register[9] = 1; + + g_step_test_check.step_check_register_addr = (conn_reg.mcu_base + can_write_offset); + g_step_test_check.step_check_write_value = 0x002; + g_step_test_check.step_test_mask = 0x002; + __wmt_step_test_do_cond_register_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do cond register action TC-10) REG write bit by phy"); + } else { + p_report->fail++; + WMT_ERR_FUNC("STEP test case failed: get physical address failed\n"); + } + + /****************************************** + ************** Test case 11 ************** + ********* REG read to temp reg *********** + ******************************************/ + WMT_INFO_FUNC("STEP test: TC 11\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "$8"; + params[1] = "0"; + params[2] = "#1"; + params[3] = "0x08"; + params[4] = "0x0F0F0F0F"; + params[5] = "$2"; + param_num = 6; + g_step_test_check.step_check_register_addr = (conn_reg.mcu_base + 0x08); + g_step_test_check.step_test_mask = 0x0F0F0F0F; + g_step_test_check.step_check_temp_register_id = 2; + g_step_env.temp_register[8] = 1; + __wmt_step_test_do_register_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do register action TC-11) REG read to temp reg"); + + /****************************************** + ************** Test case 12 ************** + ******* REG read phy to temp reg ********* + ******************************************/ + WMT_INFO_FUNC("STEP test: TC 12\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "$8"; + params[1] = "0"; + if (wmt_step_test_get_reg_base_phy_addr(buf, 0) == 0) { + params[2] = buf; + params[3] = "0x08"; + params[4] = "0x0F0F0F0F"; + params[5] = "$3"; + param_num = 6; + g_step_test_check.step_check_register_addr = (conn_reg.mcu_base + 0x08); + g_step_test_check.step_test_mask = 0x0F0F0F0F; + g_step_test_check.step_check_temp_register_id = 3; + g_step_env.temp_register[8] = 1; + __wmt_step_test_do_register_action(act_id, param_num, params, 0, &temp_report, + "STEP test case failed: (Do register action TC-12) REG read phy to temp reg"); + } else { + p_report->fail++; + WMT_ERR_FUNC("STEP test case failed: get physical address failed\n"); + } + + /****************************************** + ************** Test case 13 ************** + ************* condition invalid ********** + ******************************************/ + WMT_INFO_FUNC("STEP test: TC 13\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "$8"; + params[1] = "1"; + params[2] = "#1"; + params[3] = "0x160"; + params[4] = "0x123"; + params[5] = "0xF00"; + param_num = 6; + g_step_env.temp_register[8] = 0; + + __wmt_step_test_do_cond_register_action(act_id, param_num, params, -1, &temp_report, + "STEP test case failed: (Do cond register action TC-13) condition invalid"); + + /****************************************** + ************** Test case 14 ************** + ********** condition invalid write ******* + ******************************************/ + WMT_INFO_FUNC("STEP test: TC 14\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "$6"; + params[1] = "1"; + params[2] = "#1"; + params[3] = "0x110"; + params[4] = "0x200"; + param_num = 5; + g_step_env.temp_register[6] = 0; + + __wmt_step_test_do_cond_register_action(act_id, param_num, params, -1, &temp_report, + "STEP test case failed: (Do cond register action TC-14) condition invalid write"); + + /****************************************** + ************** Test case 15 ************** + ********** condition invalid read ******* + ******************************************/ + WMT_INFO_FUNC("STEP test: TC 15\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + wmt_step_test_clear_temp_register(); + params[0] = "$0"; + params[1] = "0"; + params[2] = "#1"; + params[3] = "0x08"; + params[4] = "1"; + params[5] = "0"; + param_num = 6; + g_step_env.temp_register[0] = 0; + + __wmt_step_test_do_cond_register_action(act_id, param_num, params, -1, &temp_report, + "STEP test case failed: (Do cond register action TC-15) REG write"); + + + osal_gettimeofday(&sec_end, &usec_end); + wmt_step_test_show_result_report("STEP result: Do condition register action result", + &temp_report, sec_begin, usec_begin, sec_end, usec_end); + wmt_step_test_update_result_report(p_report, &temp_report); +} + + +void wmt_step_test_do_gpio_action(struct step_test_report *p_report) +{ + enum step_action_id act_id; + char *params[STEP_PARAMETER_SIZE]; + struct step_action *p_act = NULL; + struct step_test_report temp_report = {0, 0, 0}; + int sec_begin = 0; + int usec_begin = 0; + int sec_end = 0; + int usec_end = 0; + int param_num; + + WMT_INFO_FUNC("STEP test: Do GPIO action start\n"); + osal_gettimeofday(&sec_begin, &usec_begin); + act_id = STEP_ACTION_INDEX_GPIO; + /**************************************** + ************* Test case 1 ************** + ************* GPIO read #8 ************* + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 1\n"); + wmt_step_test_clear_parameter(params); + params[0] = "0"; + params[1] = "8"; + param_num = 2; + + p_act = wmt_step_create_action(act_id, param_num, params); + if (p_act != NULL) { + if (wmt_step_do_gpio_action(p_act, NULL) == 0) { + WMT_INFO_FUNC("STEP check: Do gpio action TC-1(Read #8): search(8: )"); + temp_report.check++; + } else { + WMT_ERR_FUNC("STEP test case failed: (Do gpio action TC-1) Read #8\n"); + temp_report.fail++; + } + wmt_step_remove_action(p_act); + } else { + temp_report.fail++; + WMT_ERR_FUNC("STEP test case failed: (Do gpio action TC-1) Create failed\n"); + } + + osal_gettimeofday(&sec_end, &usec_end); + wmt_step_test_show_result_report("STEP result: Do GPIO action result", + &temp_report, sec_begin, usec_begin, sec_end, usec_end); + wmt_step_test_update_result_report(p_report, &temp_report); +} + +void wmt_step_test_do_chip_reset_action(struct step_test_report *p_report) +{ + enum step_action_id act_id; + char *params[STEP_PARAMETER_SIZE]; + struct step_action *p_act = NULL; + struct step_test_report temp_report = {0, 0, 0}; + int sec_begin = 0; + int usec_begin = 0; + int sec_end = 0; + int usec_end = 0; + int param_num; + + WMT_INFO_FUNC("STEP test: Do chip reset action start\n"); + osal_gettimeofday(&sec_begin, &usec_begin); + act_id = STEP_ACTION_INDEX_CHIP_RESET; + /**************************************** + ************* Test case 1 ************** + ************* chip reset *************** + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 1\n"); + param_num = 0; + + p_act = wmt_step_create_action(act_id, param_num, params); + if (p_act != NULL) { + if (wmt_step_do_chip_reset_action(p_act, NULL) == 0) { + WMT_INFO_FUNC("STEP check: Do chip reset TC-1(chip reset): Trigger AEE"); + temp_report.check++; + } else { + WMT_ERR_FUNC("STEP test case failed: (Do chip reset action TC-1) chip reset\n"); + temp_report.fail++; + } + wmt_step_remove_action(p_act); + } else { + temp_report.fail++; + WMT_ERR_FUNC("STEP test case failed: (Do chip reset action TC-1) Create failed\n"); + } + + osal_gettimeofday(&sec_end, &usec_end); + wmt_step_test_show_result_report("STEP result: Do chip reset action result", + &temp_report, sec_begin, usec_begin, sec_end, usec_end); + wmt_step_test_update_result_report(p_report, &temp_report); +} + +void wmt_step_test_do_wakeup_action(struct step_test_report *p_report) +{ + enum step_action_id act_id; + char *params[STEP_PARAMETER_SIZE]; + struct step_action *p_act = NULL; + struct step_test_report temp_report = {0, 0, 0}; + int sec_begin = 0; + int usec_begin = 0; + int sec_end = 0; + int usec_end = 0; + int param_num; + + WMT_INFO_FUNC("STEP test: Do wakeup action start\n"); + osal_gettimeofday(&sec_begin, &usec_begin); + /**************************************** + ************* Test case 1 ************** + ***** Wakeup then read/write reg ******* + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 1\n"); + act_id = STEP_ACTION_INDEX_KEEP_WAKEUP; + param_num = 0; + + p_act = wmt_step_create_action(act_id, param_num, params); + if (p_act != NULL) { + wmt_step_do_keep_wakeup_action(p_act, NULL); + wmt_step_test_do_register_action(&temp_report); + wmt_step_remove_action(p_act); + } else { + temp_report.fail++; + WMT_ERR_FUNC("STEP test case failed: (Do wakeup) Create failed\n"); + } + + act_id = STEP_ACTION_INDEX_CANCEL_WAKEUP; + param_num = 0; + + p_act = wmt_step_create_action(act_id, param_num, params); + if (p_act != NULL) { + wmt_step_do_cancel_wakeup_action(p_act, NULL); + wmt_step_remove_action(p_act); + } else { + temp_report.fail++; + WMT_ERR_FUNC("STEP test case failed: (Do cancel wakeup) Create failed\n"); + } + + osal_gettimeofday(&sec_end, &usec_end); + wmt_step_test_show_result_report("STEP result: Do wakeup action result", + &temp_report, sec_begin, usec_begin, sec_end, usec_end); + wmt_step_test_update_result_report(p_report, &temp_report); +} + +void wmt_step_test_do_show_action(struct step_test_report *p_report) +{ + enum step_action_id act_id; + char *params[STEP_PARAMETER_SIZE]; + struct step_action *p_act = NULL; + struct step_test_report temp_report = {0, 0, 0}; + int sec_begin = 0; + int usec_begin = 0; + int sec_end = 0; + int usec_end = 0; + int param_num; + + WMT_INFO_FUNC("STEP test: Do show action start\n"); + osal_gettimeofday(&sec_begin, &usec_begin); + act_id = STEP_ACTION_INDEX_SHOW_STRING; + /**************************************** + ************* Test case 1 ************** + ********** Show Hello world ************ + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 1\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_parameter(params); + params[0] = "Hello_World"; + param_num = 1; + + g_step_test_check.step_check_result_string = "Hello_World"; + p_act = wmt_step_create_action(act_id, param_num, params); + if (p_act != NULL) { + wmt_step_do_show_string_action(p_act, wmt_step_test_check_show_act); + if (g_step_test_check.step_check_result == TEST_PASS) { + temp_report.pass++; + } else { + WMT_ERR_FUNC("STEP test case failed: Do show TC-1(Show Hello world)\n"); + temp_report.fail++; + } + wmt_step_remove_action(p_act); + } else { + temp_report.fail++; + WMT_ERR_FUNC("STEP test case failed: Do show TC-1(Show Hello world) Create failed\n"); + } + + osal_gettimeofday(&sec_end, &usec_end); + wmt_step_test_show_result_report("STEP result: Do show action result", + &temp_report, sec_begin, usec_begin, sec_end, usec_end); + wmt_step_test_update_result_report(p_report, &temp_report); +} + +void wmt_step_test_do_sleep_action(struct step_test_report *p_report) +{ + enum step_action_id act_id; + char *params[STEP_PARAMETER_SIZE]; + struct step_action *p_act = NULL; + struct step_test_report temp_report = {0, 0, 0}; + int sec_begin = 0; + int usec_begin = 0; + int sec_end = 0; + int usec_end = 0; + int check_sec_b, check_sec_e; + int check_usec_b, check_usec_e; + int param_num; + + WMT_INFO_FUNC("STEP test: Do sleep action start\n"); + osal_gettimeofday(&sec_begin, &usec_begin); + act_id = STEP_ACTION_INDEX_SLEEP; + /**************************************** + ************* Test case 1 ************** + *************** Sleep 1s *************** + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 1\n"); + wmt_step_test_clear_parameter(params); + params[0] = "1000"; + param_num = 1; + + p_act = wmt_step_create_action(act_id, param_num, params); + if (p_act != NULL) { + osal_gettimeofday(&check_sec_b, &check_usec_b); + wmt_step_do_sleep_action(p_act, NULL); + osal_gettimeofday(&check_sec_e, &check_usec_e); + if (check_sec_e > check_sec_b) { + temp_report.pass++; + } else { + WMT_ERR_FUNC("STEP test case failed: Do show TC-1(Sleep 1s), begin(%d.%d) end(%d.%d)\n", + check_sec_b, check_usec_b, check_sec_e, check_usec_e); + temp_report.fail++; + } + wmt_step_remove_action(p_act); + } else { + temp_report.fail++; + WMT_ERR_FUNC("STEP test case failed: Do show TC-1(Sleep 1s) Create failed\n"); + } + + osal_gettimeofday(&sec_end, &usec_end); + wmt_step_test_show_result_report("STEP result: Do sleep action result", + &temp_report, sec_begin, usec_begin, sec_end, usec_end); + wmt_step_test_update_result_report(p_report, &temp_report); +} + +void wmt_step_test_do_condition_action(struct step_test_report *p_report) +{ + enum step_action_id act_id; + char *params[STEP_PARAMETER_SIZE]; + struct step_action *p_act = NULL; + struct step_test_report temp_report = {0, 0, 0}; + int sec_begin = 0; + int usec_begin = 0; + int sec_end = 0; + int usec_end = 0; + int param_num; + + WMT_INFO_FUNC("STEP test: Do condition action start\n"); + osal_gettimeofday(&sec_begin, &usec_begin); + act_id = STEP_ACTION_INDEX_CONDITION; + /**************************************** + ************* Test case 1 ************** + *********** Condition equal ************ + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 1\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_temp_register(); + wmt_step_test_clear_parameter(params); + params[0] = "$0"; + params[1] = "$1"; + params[2] = "=="; + params[3] = "$2"; + param_num = 4; + + g_step_test_check.step_check_result_value = 1; + p_act = wmt_step_create_action(act_id, param_num, params); + if (p_act != NULL) { + wmt_step_do_condition_action(p_act, wmt_step_test_check_condition_act); + if (g_step_test_check.step_check_result == TEST_PASS) { + temp_report.pass++; + } else { + WMT_ERR_FUNC("STEP test case failed: Do condition TC-1(equal)\n"); + temp_report.fail++; + } + wmt_step_remove_action(p_act); + } else { + temp_report.fail++; + WMT_ERR_FUNC("STEP test case failed: Do condition TC-1(equal) Create failed\n"); + } + + /**************************************** + ************* Test case 2 ************** + ********** Condition greater *********** + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 2\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_temp_register(); + wmt_step_test_clear_parameter(params); + params[0] = "$0"; + params[1] = "$1"; + params[2] = ">"; + params[3] = "$2"; + param_num = 4; + g_step_env.temp_register[1] = 0; + g_step_env.temp_register[2] = 1; + + g_step_test_check.step_check_result_value = 0; + p_act = wmt_step_create_action(act_id, param_num, params); + if (p_act != NULL) { + wmt_step_do_condition_action(p_act, wmt_step_test_check_condition_act); + if (g_step_test_check.step_check_result == TEST_PASS) { + temp_report.pass++; + } else { + WMT_ERR_FUNC("STEP test case failed: Do condition TC-2(greater)\n"); + temp_report.fail++; + } + wmt_step_remove_action(p_act); + } else { + temp_report.fail++; + WMT_ERR_FUNC("STEP test case failed: Do condition TC-2(greater) Create failed\n"); + } + + /**************************************** + ************* Test case 3 ************** + ******* Condition greater equal ******** + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 3\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_temp_register(); + wmt_step_test_clear_parameter(params); + params[0] = "$0"; + params[1] = "$1"; + params[2] = ">="; + params[3] = "$2"; + param_num = 4; + g_step_env.temp_register[1] = 2; + g_step_env.temp_register[2] = 2; + + g_step_test_check.step_check_result_value = 1; + p_act = wmt_step_create_action(act_id, param_num, params); + if (p_act != NULL) { + wmt_step_do_condition_action(p_act, wmt_step_test_check_condition_act); + if (g_step_test_check.step_check_result == TEST_PASS) { + temp_report.pass++; + } else { + WMT_ERR_FUNC("STEP test case failed: Do condition TC-3(greater equal)\n"); + temp_report.fail++; + } + wmt_step_remove_action(p_act); + } else { + temp_report.fail++; + WMT_ERR_FUNC("STEP test case failed: Do condition TC-3(greater equal) Create failed\n"); + } + + /**************************************** + ************* Test case 4 ************** + ************ Condition less ************ + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 4\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_temp_register(); + wmt_step_test_clear_parameter(params); + params[0] = "$0"; + params[1] = "$1"; + params[2] = "<"; + params[3] = "$2"; + param_num = 4; + g_step_env.temp_register[1] = 10; + g_step_env.temp_register[2] = 0; + + g_step_test_check.step_check_result_value = 0; + p_act = wmt_step_create_action(act_id, param_num, params); + if (p_act != NULL) { + wmt_step_do_condition_action(p_act, wmt_step_test_check_condition_act); + if (g_step_test_check.step_check_result == TEST_PASS) { + temp_report.pass++; + } else { + WMT_ERR_FUNC("STEP test case failed: Do condition TC-4(less)\n"); + temp_report.fail++; + } + wmt_step_remove_action(p_act); + } else { + temp_report.fail++; + WMT_ERR_FUNC("STEP test case failed: Do condition TC-4(less) Create failed\n"); + } + + /**************************************** + ************* Test case 5 ************** + ********* Condition less equal ********* + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 5\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_temp_register(); + wmt_step_test_clear_parameter(params); + params[0] = "$0"; + params[1] = "$1"; + params[2] = "<="; + params[3] = "$2"; + param_num = 4; + g_step_env.temp_register[1] = 0; + g_step_env.temp_register[2] = 10; + + g_step_test_check.step_check_result_value = 1; + p_act = wmt_step_create_action(act_id, param_num, params); + if (p_act != NULL) { + wmt_step_do_condition_action(p_act, wmt_step_test_check_condition_act); + if (g_step_test_check.step_check_result == TEST_PASS) { + temp_report.pass++; + } else { + WMT_ERR_FUNC("STEP test case failed: Do condition TC-5(less equal)\n"); + temp_report.fail++; + } + wmt_step_remove_action(p_act); + } else { + temp_report.fail++; + WMT_ERR_FUNC("STEP test case failed: Do condition TC-5(less equal) Create failed\n"); + } + + /**************************************** + ************* Test case 6 ************** + ********* Condition not equal ********** + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 6\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_temp_register(); + wmt_step_test_clear_parameter(params); + params[0] = "$1"; + params[1] = "$2"; + params[2] = "!="; + params[3] = "$3"; + param_num = 4; + g_step_env.temp_register[2] = 3; + g_step_env.temp_register[3] = 3; + + g_step_test_check.step_check_result_value = 0; + p_act = wmt_step_create_action(act_id, param_num, params); + if (p_act != NULL) { + wmt_step_do_condition_action(p_act, wmt_step_test_check_condition_act); + if (g_step_test_check.step_check_result == TEST_PASS) { + temp_report.pass++; + } else { + WMT_ERR_FUNC("STEP test case failed: Do condition TC-6(not equal)\n"); + temp_report.fail++; + } + wmt_step_remove_action(p_act); + } else { + temp_report.fail++; + WMT_ERR_FUNC("STEP test case failed: Do condition TC-6(not equal) Create failed\n"); + } + + /**************************************** + ************* Test case 7 ************** + ************ Condition and ************* + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 7\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_temp_register(); + wmt_step_test_clear_parameter(params); + params[0] = "$1"; + params[1] = "$2"; + params[2] = "&&"; + params[3] = "$3"; + param_num = 4; + g_step_env.temp_register[2] = 0x10; + g_step_env.temp_register[3] = 0x00; + + g_step_test_check.step_check_result_value = 0; + p_act = wmt_step_create_action(act_id, param_num, params); + if (p_act != NULL) { + wmt_step_do_condition_action(p_act, wmt_step_test_check_condition_act); + if (g_step_test_check.step_check_result == TEST_PASS) { + temp_report.pass++; + } else { + WMT_ERR_FUNC("STEP test case failed: Do condition TC-7(and)\n"); + temp_report.fail++; + } + wmt_step_remove_action(p_act); + } else { + temp_report.fail++; + WMT_ERR_FUNC("STEP test case failed: Do condition TC-7(and) Create failed\n"); + } + + /**************************************** + ************* Test case 8 ************** + ************* Condition or ************* + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 8\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_temp_register(); + wmt_step_test_clear_parameter(params); + params[0] = "$1"; + params[1] = "$2"; + params[2] = "||"; + params[3] = "$3"; + param_num = 4; + g_step_env.temp_register[2] = 0x10; + g_step_env.temp_register[3] = 0x00; + + g_step_test_check.step_check_result_value = 1; + p_act = wmt_step_create_action(act_id, param_num, params); + if (p_act != NULL) { + wmt_step_do_condition_action(p_act, wmt_step_test_check_condition_act); + if (g_step_test_check.step_check_result == TEST_PASS) { + temp_report.pass++; + } else { + WMT_ERR_FUNC("STEP test case failed: Do condition TC-8(or)\n"); + temp_report.fail++; + } + wmt_step_remove_action(p_act); + } else { + temp_report.fail++; + WMT_ERR_FUNC("STEP test case failed: Do condition TC-8(or) Create failed\n"); + } + + /**************************************** + ************* Test case 9 ************** + ****** Condition not equal value ******* + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 9\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_temp_register(); + wmt_step_test_clear_parameter(params); + params[0] = "$1"; + params[1] = "$2"; + params[2] = "!="; + params[3] = "99"; + param_num = 4; + g_step_env.temp_register[2] = 99; + + g_step_test_check.step_check_result_value = 0; + p_act = wmt_step_create_action(act_id, param_num, params); + if (p_act != NULL) { + wmt_step_do_condition_action(p_act, wmt_step_test_check_condition_act); + if (g_step_test_check.step_check_result == TEST_PASS) { + temp_report.pass++; + } else { + WMT_ERR_FUNC("STEP test case failed: Do condition TC-9(not equal value)\n"); + temp_report.fail++; + } + wmt_step_remove_action(p_act); + } else { + temp_report.fail++; + WMT_ERR_FUNC("STEP test case failed: Do condition TC-9(not equal value) Create failed\n"); + } + + /**************************************** + ************* Test case 10 ************* + ********* Condition equal value ******** + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 10\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_temp_register(); + wmt_step_test_clear_parameter(params); + params[0] = "$1"; + params[1] = "$2"; + params[2] = "=="; + params[3] = "18"; + param_num = 4; + g_step_env.temp_register[2] = 18; + + g_step_test_check.step_check_result_value = 1; + p_act = wmt_step_create_action(act_id, param_num, params); + if (p_act != NULL) { + wmt_step_do_condition_action(p_act, wmt_step_test_check_condition_act); + if (g_step_test_check.step_check_result == TEST_PASS) { + temp_report.pass++; + } else { + WMT_ERR_FUNC("STEP test case failed: Do condition TC-10(equal value)\n"); + temp_report.fail++; + } + wmt_step_remove_action(p_act); + } else { + temp_report.fail++; + WMT_ERR_FUNC("STEP test case failed: Do condition TC-10(equal value) Create failed\n"); + } + + /**************************************** + ************* Test case 11 ************* + ****** Condition equal value (HEX) ***** + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 10\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_temp_register(); + wmt_step_test_clear_parameter(params); + params[0] = "$1"; + params[1] = "$2"; + params[2] = "=="; + params[3] = "0x18"; + param_num = 4; + g_step_env.temp_register[2] = 24; + + g_step_test_check.step_check_result_value = 1; + p_act = wmt_step_create_action(act_id, param_num, params); + if (p_act != NULL) { + wmt_step_do_condition_action(p_act, wmt_step_test_check_condition_act); + if (g_step_test_check.step_check_result == TEST_PASS) { + temp_report.pass++; + } else { + WMT_ERR_FUNC("STEP test case failed: Do condition TC-11(equal value HEX)\n"); + temp_report.fail++; + } + wmt_step_remove_action(p_act); + } else { + temp_report.fail++; + WMT_ERR_FUNC("STEP test case failed: Do condition TC-11(equal value HEX) Create failed\n"); + } + + osal_gettimeofday(&sec_end, &usec_end); + wmt_step_test_show_result_report("STEP result: Do condition action result", + &temp_report, sec_begin, usec_begin, sec_end, usec_end); + wmt_step_test_update_result_report(p_report, &temp_report); +} + +void wmt_step_test_do_value_action(struct step_test_report *p_report) +{ + enum step_action_id act_id; + char *params[STEP_PARAMETER_SIZE]; + struct step_action *p_act = NULL; + struct step_test_report temp_report = {0, 0, 0}; + int sec_begin = 0; + int usec_begin = 0; + int sec_end = 0; + int usec_end = 0; + int param_num; + + WMT_INFO_FUNC("STEP test: Do value action start\n"); + osal_gettimeofday(&sec_begin, &usec_begin); + act_id = STEP_ACTION_INDEX_VALUE; + /**************************************** + ************* Test case 1 ************** + ******* Save value to register ********* + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 1\n"); + wmt_step_test_clear_check_data(); + wmt_step_test_clear_temp_register(); + wmt_step_test_clear_parameter(params); + params[0] = "$2"; + params[1] = "0x66"; + param_num = 2; + + g_step_test_check.step_check_result_value = 0x66; + p_act = wmt_step_create_action(act_id, param_num, params); + if (p_act != NULL) { + wmt_step_do_value_action(p_act, wmt_step_test_check_value_act); + if (g_step_test_check.step_check_result == TEST_PASS) { + temp_report.pass++; + } else { + WMT_ERR_FUNC("STEP test case failed: Do show TC-1(Save value to register)"); + temp_report.fail++; + } + wmt_step_remove_action(p_act); + } else { + temp_report.fail++; + WMT_ERR_FUNC("STEP test case failed: Do show TC-1(Save value to register) Create failed\n"); + } + + osal_gettimeofday(&sec_end, &usec_end); + wmt_step_test_show_result_report("STEP result: Do value action result", + &temp_report, sec_begin, usec_begin, sec_end, usec_end); + wmt_step_test_update_result_report(p_report, &temp_report); +} + +void wmt_step_test_create_periodic_dump(struct step_test_report *p_report) +{ + int expires_ms; + struct step_test_report temp_report = {0, 0, 0}; + int sec_begin = 0; + int usec_begin = 0; + int sec_end = 0; + int usec_end = 0; + struct step_pd_entry *p_current = NULL; + bool is_thread_run_for_test = 0; + + WMT_INFO_FUNC("STEP test: Create periodic dump start\n"); + osal_gettimeofday(&sec_begin, &usec_begin); + + if (g_step_env.pd_struct.step_pd_wq == NULL) { + if (wmt_step_init_pd_env() != 0) { + WMT_ERR_FUNC("STEP test case failed: Start thread failed\n"); + return; + } + is_thread_run_for_test = 1; + } + + /**************************************** + ************* Test case 1 ************** + *************** Normal ***************** + ****************************************/ + WMT_INFO_FUNC("STEP test: TC 1\n"); + expires_ms = 5; + p_current = wmt_step_get_periodic_dump_entry(expires_ms); + if (p_current == NULL) { + WMT_ERR_FUNC("STEP test case failed: (Create periodic dump TC-1) No entry\n"); + temp_report.fail++; + } else { + if (p_current->expires_ms == expires_ms) { + temp_report.pass++; + } else { + WMT_ERR_FUNC("STEP test case failed: (Create periodic dump TC-1) Currect %d not %d\n", + p_current->expires_ms, expires_ms); + temp_report.fail++; + } + list_del_init(&p_current->list); + kfree(p_current); + } + + if (is_thread_run_for_test == 1) + wmt_step_deinit_pd_env(); + + osal_gettimeofday(&sec_end, &usec_end); + wmt_step_test_show_result_report("STEP result: Create periodic dump result", + &temp_report, sec_begin, usec_begin, sec_end, usec_end); + wmt_step_test_update_result_report(p_report, &temp_report); +} + From 35a1e4e6f94fbf1560557a2a27ce30d13d76977a Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 21:49:40 +0800 Subject: [PATCH 12/32] Add files via upload --- .../debug_utility/connsys_debug_utility.c | 1349 +++++++++++++++++ .../debug_utility/connsys_debug_utility.h | 89 ++ .../debug_utility/connsys_debug_utility_emi.h | 71 + .../connectivity/common/debug_utility/ring.c | 139 ++ .../connectivity/common/debug_utility/ring.h | 95 ++ .../common/debug_utility/ring_emi.c | 148 ++ .../common/debug_utility/ring_emi.h | 84 + .../connsys_debut_utility_tester.bat | 5 + .../connsys_log_AT/dedicated_log_path_test.py | 134 ++ .../connsys_log_tool/connsys_log_converter.py | 174 +++ .../tool/connsys_log_tool/kernel_to_utc.py | 158 ++ 11 files changed, 2446 insertions(+) create mode 100644 drivers/misc/mediatek/connectivity/common/debug_utility/connsys_debug_utility.c create mode 100644 drivers/misc/mediatek/connectivity/common/debug_utility/connsys_debug_utility.h create mode 100644 drivers/misc/mediatek/connectivity/common/debug_utility/connsys_debug_utility_emi.h create mode 100644 drivers/misc/mediatek/connectivity/common/debug_utility/ring.c create mode 100644 drivers/misc/mediatek/connectivity/common/debug_utility/ring.h create mode 100644 drivers/misc/mediatek/connectivity/common/debug_utility/ring_emi.c create mode 100644 drivers/misc/mediatek/connectivity/common/debug_utility/ring_emi.h create mode 100644 drivers/misc/mediatek/connectivity/common/debug_utility/tool/connsys_log_AT/connsys_debut_utility_tester.bat create mode 100644 drivers/misc/mediatek/connectivity/common/debug_utility/tool/connsys_log_AT/dedicated_log_path_test.py create mode 100644 drivers/misc/mediatek/connectivity/common/debug_utility/tool/connsys_log_tool/connsys_log_converter.py create mode 100644 drivers/misc/mediatek/connectivity/common/debug_utility/tool/connsys_log_tool/kernel_to_utc.py diff --git a/drivers/misc/mediatek/connectivity/common/debug_utility/connsys_debug_utility.c b/drivers/misc/mediatek/connectivity/common/debug_utility/connsys_debug_utility.c new file mode 100644 index 0000000000000..4c9baf0c0902b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/debug_utility/connsys_debug_utility.c @@ -0,0 +1,1349 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#include +#include +#include +#include "connsys_debug_utility.h" +#include "ring_emi.h" +#include "ring.h" +#include "wmt_exp.h" +#include +#include +#include +#include + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +enum FW_LOG_MODE { + PRINT_TO_KERNEL_LOG = 0, + LOG_TO_FILE = 1, +}; + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH +static atomic_t log_mode = ATOMIC_INIT(LOG_TO_FILE); +#else +static atomic_t log_mode = ATOMIC_INIT(PRINT_TO_KERNEL_LOG); +#endif + +#define CONNLOG_ALARM_STATE_DISABLE 0x0 +#define CONNLOG_ALARM_STATE_ENABLE 0x01 +#define CONNLOG_ALARM_STATE_RUNNING 0x03 + +#define CONNLOG_LOG_BUFFER_SIZE (64*1024) + +struct connlog_alarm { + struct alarm alarm_timer; + unsigned int alarm_state; + unsigned int blank_state; + unsigned int alarm_sec; + spinlock_t alarm_lock; + unsigned long flags; +}; + +struct connlog_dev { + phys_addr_t phyAddrEmiBase; + void __iomem *virAddrEmiLogBase; + struct connlog_emi_config emi_config; + int conn2ApIrqId; + bool eirqOn; + spinlock_t irq_lock; + unsigned long flags; + unsigned int irq_counter; + CONNLOG_IRQ_CB irq_callback; + struct timer_list workTimer; + struct work_struct logDataWorker; + /* alarm timer for suspend */ + struct connlog_alarm log_alarm; + void *log_data; +}; +static struct connlog_dev gDev = { 0 }; + +static CONNLOG_EVENT_CB event_callback_table[CONNLOG_TYPE_END] = { 0x0 }; + +struct connlog_buffer { + struct ring_emi ring_emi; + struct ring ring_cache; + void *cache_base; +}; +static struct connlog_buffer connlog_buffer_table[CONNLOG_TYPE_END]; + +struct connlog_offset { + unsigned int emi_base_offset; + unsigned int emi_size; + unsigned int emi_read; + unsigned int emi_write; + unsigned int emi_buf; +}; + +static struct connlog_offset emi_offset_table[CONNLOG_TYPE_END]; + +static char *type_to_title[CONNLOG_TYPE_END] = { + "wifi_fw", "bt_fw", "gps_fw", "mcu_fw" +}; + +static size_t cache_size_table[CONNLOG_TYPE_END]; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static int connlog_eirq_init(const struct connlog_irq_config *irq_config); +static void connlog_eirq_deinit(void); +static int connlog_emi_init(phys_addr_t emi_base, const struct connlog_emi_config *emi_config); +static void connlog_emi_deinit(void); +static int connlog_ring_buffer_init(void); +static void connlog_ring_buffer_deinit(void); +static int connlog_set_ring_buffer_base_addr(void); +static irqreturn_t connlog_eirq_isr(int irq, void *arg); +static void connlog_set_ring_ready(void); +static void connlog_buffer_init(int conn_type); +static void connlog_ring_emi_to_cache(int conn_type); +static void connlog_dump_buf(const char *title, const char *buf, ssize_t sz); +static void connlog_ring_print(int conn_type); +static void connlog_event_set(int conn_type); +static void connlog_log_data_handler(struct work_struct *work); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) +static void work_timer_handler(struct timer_list *t); +#else +static void work_timer_handler(unsigned long data); +#endif +static void connlog_do_schedule_work(bool count); +static void connlog_emi_status_dump(void); + +/* connlog when suspend */ +static int connlog_alarm_init(void); +static enum alarmtimer_restart alarm_timer_handler(struct alarm *alarm, ktime_t); +static inline bool connlog_is_alarm_enable(void); +static int connlog_set_alarm_timer(void); +static int connlog_cancel_alarm_timer(void); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +static void connlog_set_ring_ready(void); + + +/***************************************************************************** +* FUNCTION +* connlog_emi_status_dump +* DESCRIPTION +* Dump emi control block . +*****************************************************************************/ +void connlog_emi_status_dump(void) +{ + /* Dump header (0x40) and MCU read/write pointer */ + connsys_dedicated_log_dump_emi(0x0, 0x60); + /* 32 byte wifi read/write pointer */ + connsys_dedicated_log_dump_emi(emi_offset_table[CONNLOG_TYPE_WIFI].emi_base_offset, 0x20); + /* 32 byte bt read/write pointer */ + connsys_dedicated_log_dump_emi(emi_offset_table[CONNLOG_TYPE_BT].emi_base_offset, 0x20); + /* 32 byte gps read/write pointer */ + connsys_dedicated_log_dump_emi(emi_offset_table[CONNLOG_TYPE_GPS].emi_base_offset, 0x20); +} + + +/***************************************************************************** +* FUNCTION +* connlog_cache_allocate +* DESCRIPTION +* Allocate memroy for cache . +* PARAMETERS +* size [IN] data buffer length +* RETURNS +* void* buffer pointer +*****************************************************************************/ +void *connlog_cache_allocate(size_t size) +{ + void *pBuffer = NULL; + + pBuffer = vmalloc(size); + if (!pBuffer) + return NULL; + return pBuffer; +} + +/* */ +/***************************************************************************** +* FUNCTION +* connlog_set_ring_ready +* DESCRIPTION +* set reserved bit be EMIFWLOG to indicate that init is ready. +* PARAMETERS +* void +* RETURNS +* void +*****************************************************************************/ +static void connlog_set_ring_ready(void) +{ + const char ready_str[] = "EMIFWLOG"; + + memcpy_toio(gDev.virAddrEmiLogBase + CONNLOG_READY_PATTERN_BASE, + ready_str, CONNLOG_READY_PATTERN_BASE_SIZE); +} + +/***************************************************************************** +* FUNCTION +* connlog_buffer_init +* DESCRIPTION +* Initialize ring and cache buffer +* PARAMETERS +* conn_type [IN] subsys type +* RETURNS +* void +*****************************************************************************/ +static void connlog_buffer_init(int conn_type) +{ + if (conn_type < 0 || conn_type >= CONNLOG_TYPE_END) + return; + + /* init ring emi */ + ring_emi_init( + gDev.virAddrEmiLogBase + emi_offset_table[conn_type].emi_buf, + emi_offset_table[conn_type].emi_size, + gDev.virAddrEmiLogBase + emi_offset_table[conn_type].emi_read, + gDev.virAddrEmiLogBase + emi_offset_table[conn_type].emi_write, + &connlog_buffer_table[conn_type].ring_emi + ); + + /* init ring cache */ + connlog_buffer_table[conn_type].cache_base = connlog_cache_allocate(cache_size_table[conn_type]); + memset(connlog_buffer_table[conn_type].cache_base, 0, cache_size_table[conn_type]); + ring_init( + connlog_buffer_table[conn_type].cache_base, + cache_size_table[conn_type], + 0, + 0, + &connlog_buffer_table[conn_type].ring_cache + ); +} + +/***************************************************************************** +* FUNCTION +* connlog_ring_emi_to_cache +* DESCRIPTION +* copy data from emi ring buffer to cache +* PARAMETERS +* conn_type [IN] subsys type +* RETURNS +* int 0=failed, others=buffer length +*****************************************************************************/ +static void connlog_ring_emi_to_cache(int conn_type) +{ + struct ring_emi_segment ring_emi_seg; + struct ring_emi *ring_emi; + struct ring *ring_cache; + int total_size = 0; + int count = 0; + unsigned int cache_max_size = 0; + static DEFINE_RATELIMIT_STATE(_rs, 10 * HZ, 1); + static DEFINE_RATELIMIT_STATE(_rs2, HZ, 1); + + if (conn_type < 0 || conn_type >= CONNLOG_TYPE_END) + return; + + ring_emi = &connlog_buffer_table[conn_type].ring_emi; + ring_cache = &connlog_buffer_table[conn_type].ring_cache; + + if (RING_FULL(ring_cache)) { + if (__ratelimit(&_rs)) + pr_warn("%s cache is full.\n", type_to_title[conn_type]); + return; + } + + cache_max_size = RING_WRITE_REMAIN_SIZE(ring_cache); + if (RING_EMI_EMPTY(ring_emi) || !ring_emi_read_prepare(cache_max_size, &ring_emi_seg, ring_emi)) { + if (__ratelimit(&_rs)) + pr_err("%s no data, possibly taken by concurrent reader.\n", type_to_title[conn_type]); + return; + } + + /* Check ring_emi buffer memory. Dump EMI data if it's corruption. */ + if (EMI_READ32(ring_emi->read) > emi_offset_table[conn_type].emi_size || + EMI_READ32(ring_emi->write) > emi_offset_table[conn_type].emi_size) { + if (__ratelimit(&_rs)) + pr_err("%s read/write pointer out-of-bounds.\n", type_to_title[conn_type]); + connlog_emi_status_dump(); + /* Trigger Connsys Assert */ + mtk_wcn_wmt_assert(WMTDRV_TYPE_WMT, 46); + return; + } + + RING_EMI_READ_ALL_FOR_EACH(ring_emi_seg, ring_emi) { + struct ring_segment ring_cache_seg; + unsigned int emi_buf_size = ring_emi_seg.sz; + unsigned int written = 0; + +#ifdef DEBUG_RING + ring_emi_dump(__func__, ring_emi); + ring_emi_dump_segment(__func__, &ring_emi_seg); +#endif + RING_WRITE_FOR_EACH(ring_emi_seg.sz, ring_cache_seg, &connlog_buffer_table[conn_type].ring_cache) { +#ifdef DEBUG_RING + ring_dump(__func__, &connlog_buffer_table[conn_type].ring_cache); + ring_dump_segment(__func__, &ring_cache_seg); +#endif + if (__ratelimit(&_rs2)) + pr_info("%s: ring_emi_seg.sz=%d, ring_cache_pt=%p, ring_cache_seg.sz=%d\n", + type_to_title[conn_type], ring_emi_seg.sz, ring_cache_seg.ring_pt, + ring_cache_seg.sz); + memcpy_fromio(ring_cache_seg.ring_pt, ring_emi_seg.ring_emi_pt + ring_cache_seg.data_pos, + ring_cache_seg.sz); + emi_buf_size -= ring_cache_seg.sz; + written += ring_cache_seg.sz; + } + + total_size += ring_emi_seg.sz; + count++; + } +} + +/* output format + * xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx ................ + * 3 digits hex * 16 + 16 single char + 1 NULL terminate = 64+1 bytes + */ +#define BYETES_PER_LINE 16 +#define LOG_LINE_SIZE (3*BYETES_PER_LINE + BYETES_PER_LINE + 1) +#define IS_VISIBLE_CHAR(c) ((c) >= 32 && (c) <= 126) +static void connlog_dump_buf(const char *title, const char *buf, ssize_t sz) +{ + int i; + char line[LOG_LINE_SIZE]; + + i = 0; + line[LOG_LINE_SIZE-1] = 0; + while (sz--) { + if (snprintf(line + i*3, 3, "%02x", *buf) < 0) + return; + line[i*3 + 2] = ' '; + + if (IS_VISIBLE_CHAR(*buf)) + line[3*BYETES_PER_LINE + i] = *buf; + else + line[3*BYETES_PER_LINE + i] = '`'; + + i++; + buf++; + + if (i >= BYETES_PER_LINE || !sz) { + if (i < BYETES_PER_LINE) { + memset(line+i*3, ' ', (BYETES_PER_LINE-i)*3); + memset(line+3*BYETES_PER_LINE+i, '.', BYETES_PER_LINE-i); + } + pr_info("%s: %s\n", title, line); + i = 0; + } + } +} + +#define LOG_MAX_LEN 1024 +#define LOG_HEAD_LENG 16 +#define TIMESYNC_LENG 40 +const char log_head[] = {0x55, 0x00, 0x00, 0x62}; +const char timesync_head[] = {0x55, 0x00, 0x25, 0x62}; +static char log_line[LOG_MAX_LEN]; +static void connlog_fw_log_parser(int conn_type, const char *buf, ssize_t sz) +{ + unsigned int systime = 0; + unsigned int utc_s = 0; + unsigned int utc_us = 0; + unsigned int buf_len = 0; + unsigned int print_len = 0; + + if (conn_type < 0 || conn_type >= CONNLOG_TYPE_END) + return; + + while (sz > LOG_HEAD_LENG) { + if (*buf == log_head[0]) { + if (!memcmp(buf, log_head, sizeof(log_head))) { + buf_len = buf[14] + (buf[15] << 8); + print_len = buf_len >= LOG_MAX_LEN ? LOG_MAX_LEN - 1 : buf_len; + memcpy(log_line, buf + LOG_HEAD_LENG, print_len); + log_line[print_len] = 0; + pr_info("%s: %s\n", type_to_title[conn_type], log_line); + sz -= (LOG_HEAD_LENG + buf_len); + buf += (LOG_HEAD_LENG + buf_len); + continue; + } else if (sz >= TIMESYNC_LENG && + !memcmp(buf, timesync_head, sizeof(timesync_head))) { + memcpy(&systime, buf + 28, sizeof(systime)); + memcpy(&utc_s, buf + 32, sizeof(utc_s)); + memcpy(&utc_us, buf + 36, sizeof(utc_us)); + pr_info("%s: timesync : (%u) %u.%06u\n", + type_to_title[conn_type], systime, utc_s, utc_us); + sz -= TIMESYNC_LENG; + buf += TIMESYNC_LENG; + continue; + } + } + sz--; + buf++; + } +} +/***************************************************************************** +* FUNCTION +* connlog_ring_print +* DESCRIPTION +* print log data on kernel log +* PARAMETERS +* conn_type [IN] subsys type +* RETURNS +* void +*****************************************************************************/ +static void connlog_ring_print(int conn_type) +{ + unsigned int written = 0; + unsigned int buf_size; + struct ring_emi_segment ring_emi_seg; + struct ring_emi *ring_emi; + + if (conn_type < 0 || conn_type >= CONNLOG_TYPE_END) + return; + + ring_emi = &connlog_buffer_table[conn_type].ring_emi; + if (RING_EMI_EMPTY(ring_emi) || !ring_emi_read_all_prepare(&ring_emi_seg, ring_emi)) { + pr_err("type(%s) no data, possibly taken by concurrent reader.\n", type_to_title[conn_type]); + return; + } + buf_size = ring_emi_seg.remain; + memset(gDev.log_data, 0, CONNLOG_LOG_BUFFER_SIZE); + + /* Check ring_emi buffer memory. Dump EMI data if it's corruption. */ + if (EMI_READ32(ring_emi->read) > emi_offset_table[conn_type].emi_size || + EMI_READ32(ring_emi->write) > emi_offset_table[conn_type].emi_size) { + pr_err("%s read/write pointer out-of-bounds.\n", type_to_title[conn_type]); + connlog_emi_status_dump(); + /* Trigger Connsys Assert */ + mtk_wcn_wmt_assert(WMTDRV_TYPE_WMT, 46); + return; + } + + RING_EMI_READ_ALL_FOR_EACH(ring_emi_seg, ring_emi) { + memcpy_fromio(gDev.log_data + written, ring_emi_seg.ring_emi_pt, ring_emi_seg.sz); + /* connlog_dump_buf("fw_log", gDev.log_data + written, ring_emi_seg.sz); */ + buf_size -= ring_emi_seg.sz; + written += ring_emi_seg.sz; + } + if (conn_type != CONNLOG_TYPE_BT) + connlog_fw_log_parser(conn_type, gDev.log_data, written); +} + +/***************************************************************************** +* FUNCTION +* connlog_event_set +* DESCRIPTION +* Trigger event call back to wakeup waitqueue +* PARAMETERS +* conn_type [IN] subsys type +* RETURNS +* void +*****************************************************************************/ +static void connlog_event_set(int conn_type) +{ + if ((conn_type >= 0) && (conn_type < CONNLOG_TYPE_END) && + (event_callback_table[conn_type] != 0x0)) + (*event_callback_table[conn_type])(); +} + +/***************************************************************************** +* FUNCTION +* connlog_do_schedule_work +* DESCRIPTION +* schedule work to read emi log data +* PARAMETERS +* count [IN] write irq counter to EMI +* RETURNS +* void +*****************************************************************************/ +static void connlog_do_schedule_work(bool count) +{ + spin_lock_irqsave(&gDev.irq_lock, gDev.flags); + if (count) { + gDev.irq_counter++; + EMI_WRITE32(gDev.virAddrEmiLogBase + CONNLOG_IRQ_COUNTER_BASE, gDev.irq_counter); + } + gDev.eirqOn = !schedule_work(&gDev.logDataWorker); + spin_unlock_irqrestore(&gDev.irq_lock, gDev.flags); +} + +/***************************************************************************** +* FUNCTION +* work_timer_handler +* DESCRIPTION +* IRQ is still on, do schedule_work again +* PARAMETERS +* data [IN] input data +* RETURNS +* void +*****************************************************************************/ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) +static void work_timer_handler(struct timer_list *t) +#else +static void work_timer_handler(unsigned long data) +#endif +{ + connlog_do_schedule_work(false); +} + +/***************************************************************************** +* FUNCTION +* connlog_alarm_init +* DESCRIPTION +* init alarm timer +* PARAMETERS +* void +* RETURNS +* void +*****************************************************************************/ +static int connlog_alarm_init(void) +{ + alarm_init(&gDev.log_alarm.alarm_timer, ALARM_REALTIME, alarm_timer_handler); + gDev.log_alarm.alarm_state = CONNLOG_ALARM_STATE_DISABLE; + spin_lock_init(&gDev.log_alarm.alarm_lock); + return 0; +} + +/***************************************************************************** +* FUNCTION +* connlog_is_alarm_enable +* DESCRIPTION +* is alarm timer enable +* PARAMETERS +* void +* RETURNS +* void +*****************************************************************************/ +static inline bool connlog_is_alarm_enable(void) +{ + if ((gDev.log_alarm.alarm_state & CONNLOG_ALARM_STATE_ENABLE) > 0) + return true; + return false; +} + +/***************************************************************************** +* FUNCTION +* connlog_set_alarm_timer +* DESCRIPTION +* setup alarm timer +* PARAMETERS +* void +* RETURNS +* void +*****************************************************************************/ +static int connlog_set_alarm_timer(void) +{ + ktime_t kt; + + kt = ktime_set(gDev.log_alarm.alarm_sec, 0); + alarm_start_relative(&gDev.log_alarm.alarm_timer, kt); + + pr_info("[connsys_log_alarm] alarm timer enabled timeout=[%d]", gDev.log_alarm.alarm_sec); + return 0; +} + +/***************************************************************************** +* FUNCTION +* connlog_cancel_alarm_timer +* DESCRIPTION +* cancel alarm timer +* PARAMETERS +* void +* RETURNS +* void +*****************************************************************************/ +static int connlog_cancel_alarm_timer(void) +{ + pr_info("[connsys_log_alarm] alarm timer cancel"); + return alarm_cancel(&gDev.log_alarm.alarm_timer); +} + +/***************************************************************************** +* FUNCTION +* connsys_log_alarm_enable +* DESCRIPTION +* enable screen off alarm timer mechanism +* PARAMETERS +* sec [IN] alarm timeout in seconds +* RETURNS +* void +*****************************************************************************/ +int connsys_log_alarm_enable(unsigned int sec) +{ + if (!gDev.virAddrEmiLogBase) + return -1; + + spin_lock_irqsave(&gDev.log_alarm.alarm_lock, gDev.log_alarm.flags); + + gDev.log_alarm.alarm_sec = sec; + if (!connlog_is_alarm_enable()) { + gDev.log_alarm.alarm_state = CONNLOG_ALARM_STATE_ENABLE; + pr_info("[connsys_log_alarm] alarm timer enabled timeout=[%d]", sec); + } + if (gDev.log_alarm.blank_state == 0) + connlog_set_alarm_timer(); + + spin_unlock_irqrestore(&gDev.log_alarm.alarm_lock, gDev.log_alarm.flags); + return 0; +} +EXPORT_SYMBOL(connsys_log_alarm_enable); + +/***************************************************************************** +* FUNCTION +* connsys_log_alarm_disable +* DESCRIPTION +* disable screen off alarm timer mechanism +* PARAMETERS +* void +* RETURNS +* void +*****************************************************************************/ +int connsys_log_alarm_disable(void) +{ + int ret = 0; + + if (!gDev.virAddrEmiLogBase) + return -1; + + spin_lock_irqsave(&gDev.log_alarm.alarm_lock, gDev.log_alarm.flags); + if (connlog_is_alarm_enable()) { + ret = connlog_cancel_alarm_timer(); + gDev.log_alarm.alarm_state = CONNLOG_ALARM_STATE_DISABLE; + pr_info("[connsys_log_alarm] alarm timer disable"); + } + + spin_unlock_irqrestore(&gDev.log_alarm.alarm_lock, gDev.log_alarm.flags); + return ret; +} +EXPORT_SYMBOL(connsys_log_alarm_disable); + +/***************************************************************************** +* FUNCTION +* connsys_log_blank_state_changed +* DESCRIPTION +* listen blank on/off to suspend/reusme alarm timer +* PARAMETERS +* int [IN] blank state +* RETURNS +* void +*****************************************************************************/ +int connsys_log_blank_state_changed(int blank_state) +{ + int ret = 0; + + if (!gDev.virAddrEmiLogBase) + return -1; + + spin_lock_irqsave(&gDev.log_alarm.alarm_lock, gDev.log_alarm.flags); + gDev.log_alarm.blank_state = blank_state; + if (connlog_is_alarm_enable()) { + if (blank_state == 0) + ret = connlog_set_alarm_timer(); + else + ret = connlog_cancel_alarm_timer(); + } + spin_unlock_irqrestore(&gDev.log_alarm.alarm_lock, gDev.log_alarm.flags); + + return ret; +} +EXPORT_SYMBOL(connsys_log_blank_state_changed); + +/***************************************************************************** +* FUNCTION +* alarm_timer_handler +* DESCRIPTION +* handler for alarm timer +* PARAMETERS +* int [IN] blank state +* RETURNS +* void +*****************************************************************************/ +static enum alarmtimer_restart alarm_timer_handler(struct alarm *alarm, + ktime_t now) +{ + ktime_t kt; + struct rtc_time tm; + unsigned int tsec, tusec; + + connsys_dedicated_log_get_utc_time(&tsec, &tusec); + rtc_time_to_tm(tsec, &tm); + pr_info("[connsys_log_alarm] alarm_timer triggered [%d-%02d-%02d %02d:%02d:%02d.%09u]" + , tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday + , tm.tm_hour, tm.tm_min, tm.tm_sec, tusec); + + connlog_do_schedule_work(false); + + spin_lock_irqsave(&gDev.log_alarm.alarm_lock, gDev.log_alarm.flags); + kt = ktime_set(gDev.log_alarm.alarm_sec, 0); + alarm_start_relative(&gDev.log_alarm.alarm_timer, kt); + spin_unlock_irqrestore(&gDev.log_alarm.alarm_lock, gDev.log_alarm.flags); + + return ALARMTIMER_NORESTART; +} + +/***************************************************************************** +* FUNCTION +* connlog_print_log +* DESCRIPTION +* Print FW log to kernel log +* PARAMETERS +* conn_type [IN] subsys type +* RETURNS +* void +*****************************************************************************/ +static void connlog_log_data_handler(struct work_struct *work) +{ + int ret = 0; + int i; + int module = 0; + static DEFINE_RATELIMIT_STATE(_rs, 10 * HZ, 1); + static DEFINE_RATELIMIT_STATE(_rs2, 2 * HZ, 1); + + do { + ret = 0; + for (i = 0; i < CONNLOG_TYPE_END; i++) { + if (!RING_EMI_EMPTY(&connlog_buffer_table[i].ring_emi)) { + if (atomic_read(&log_mode) == LOG_TO_FILE) + connlog_ring_emi_to_cache(i); + else + connlog_ring_print(i); + + connlog_event_set(i); + /* Set module bit */ + module |= (1 << i); + /* ret++; */ + } else { + if (__ratelimit(&_rs)) + pr_info("[connlog] %s emi ring is empty!!\n", type_to_title[i]); + } + } + } while (ret); + + if (__ratelimit(&_rs2)) + pr_info("[connlog] irq counter=%d module=0x%04x\n", + EMI_READ32(gDev.virAddrEmiLogBase + CONNLOG_IRQ_COUNTER_BASE), module); + spin_lock_irqsave(&gDev.irq_lock, gDev.flags); + if (gDev.eirqOn) + mod_timer(&gDev.workTimer, jiffies + 1); + spin_unlock_irqrestore(&gDev.irq_lock, gDev.flags); +} + +/***************************************************************************** +* FUNCTION +* connlog_eirq_isr +* DESCRIPTION +* IRQ handler to notify subsys that EMI has logs. +* PARAMETERS +* irq [IN] irq number +* art [IN] other argument +* RETURNS +* irqreturn_t irq status +* @IRQ_HANDLED interrupt was handled by this device +*****************************************************************************/ +static irqreturn_t connlog_eirq_isr(int irq, void *arg) +{ + connlog_do_schedule_work(true); + + if (gDev.irq_callback) + (*gDev.irq_callback)(); + + return IRQ_HANDLED; +} + +/***************************************************************************** +* FUNCTION +* connlog_eirq_init +* DESCRIPTION +* To register IRQ +* PARAMETERS +* irq_id [IN] irq number +* irq_flag [IN] irq type +* RETURNS +* int 0=success, others=error +*****************************************************************************/ +static int connlog_eirq_init(const struct connlog_irq_config *irq_config) +{ + int iret = 0; + + if (irq_config == NULL) { + pr_info("irq_config is NULL\n"); + return -1; + } + + if (gDev.conn2ApIrqId == 0) + gDev.conn2ApIrqId = irq_config->irq_num; + else { + pr_warn("IRQ has been initialized\n"); + return -1; + } + + gDev.irq_callback = irq_config->irq_callback; + + pr_info("EINT CONN_LOG_IRQ(%d, %d)\n", irq_config->irq_num, irq_config->irq_flag); + + iret = request_irq(gDev.conn2ApIrqId, connlog_eirq_isr, irq_config->irq_flag, "CONN_LOG_IRQ", NULL); + if (iret) { + pr_err("EINT IRQ(%d) NOT AVAILABLE!!\n", gDev.conn2ApIrqId); + } else { + iret = enable_irq_wake(gDev.conn2ApIrqId); + if (iret) + pr_err("enable irq wake fail,irq_no(%d),iret(%d)\n", gDev.conn2ApIrqId, iret); + iret = 0; + } + + return iret; +} + +/***************************************************************************** +* FUNCTION +* connlog_eirq_deinit +* DESCRIPTION +* unrigester irq +* PARAMETERS +* void +* RETURNS +* void +*****************************************************************************/ +static void connlog_eirq_deinit(void) +{ + free_irq(gDev.conn2ApIrqId, NULL); +} + +/***************************************************************************** +* FUNCTION +* connlog_set_ring_buffer_base_addr +* DESCRIPTION +* Set subsys log base address on EMI for FW +* PARAMETERS +* void +* RETURNS +* void +*****************************************************************************/ +static int connlog_set_ring_buffer_base_addr(void) +{ + if (!gDev.virAddrEmiLogBase) + return -1; + + /* set up subsys base address */ + EMI_WRITE32(gDev.virAddrEmiLogBase + 0, emi_offset_table[CONNLOG_TYPE_MCU].emi_base_offset); + EMI_WRITE32(gDev.virAddrEmiLogBase + 4, emi_offset_table[CONNLOG_TYPE_MCU].emi_size); + EMI_WRITE32(gDev.virAddrEmiLogBase + 8, emi_offset_table[CONNLOG_TYPE_WIFI].emi_base_offset); + EMI_WRITE32(gDev.virAddrEmiLogBase + 12, emi_offset_table[CONNLOG_TYPE_WIFI].emi_size); + EMI_WRITE32(gDev.virAddrEmiLogBase + 16, emi_offset_table[CONNLOG_TYPE_BT].emi_base_offset); + EMI_WRITE32(gDev.virAddrEmiLogBase + 20, emi_offset_table[CONNLOG_TYPE_BT].emi_size); + EMI_WRITE32(gDev.virAddrEmiLogBase + 24, emi_offset_table[CONNLOG_TYPE_GPS].emi_base_offset); + EMI_WRITE32(gDev.virAddrEmiLogBase + 28, emi_offset_table[CONNLOG_TYPE_GPS].emi_size); + return 0; +} + +/***************************************************************************** +* FUNCTION +* connlog_emi_init +* DESCRIPTION +* Do ioremap for log buffer on EMI +* PARAMETERS +* emiaddr [IN] physical EMI base address +* RETURNS +* void +*****************************************************************************/ +static int connlog_emi_init(phys_addr_t emi_base, const struct connlog_emi_config *emi_config) +{ + unsigned int mcu_base, wifi_base, bt_base, gps_base; + + if (emi_config == 0) { + pr_err("consys emi memory address gPhyAddrEmiBase invalid\n"); + return -1; + } + + if (gDev.phyAddrEmiBase) { + pr_warn("emi base address has been initialized\n"); + return -2; + } + + gDev.phyAddrEmiBase = emi_base; + gDev.virAddrEmiLogBase = ioremap_nocache(gDev.phyAddrEmiBase + + emi_config->emi_offset, emi_config->emi_size_total); + if (gDev.virAddrEmiLogBase) { + pr_info("EMI mapping OK virtual(0x%p) physical(0x%x)\n", + gDev.virAddrEmiLogBase, + (unsigned int)(gDev.phyAddrEmiBase + emi_config->emi_offset)); + memset_io(gDev.virAddrEmiLogBase, 0, emi_config->emi_size_total); + } else + pr_err("EMI mapping fail\n"); + + memcpy(&gDev.emi_config, emi_config, sizeof(struct connlog_emi_config)); + + mcu_base = CONNLOG_CONTROL_RING_BUFFER_BASE_SIZE; + wifi_base = + mcu_base + gDev.emi_config.emi_size_mcu + CONNLOG_CONTROL_RING_BUFFER_RESERVE_SIZE + + CONNLOG_EMI_32_BYTE_ALIGNED; + bt_base = + wifi_base + gDev.emi_config.emi_size_wifi + CONNLOG_CONTROL_RING_BUFFER_RESERVE_SIZE + + CONNLOG_EMI_32_BYTE_ALIGNED; + gps_base = + bt_base + gDev.emi_config.emi_size_bt + CONNLOG_CONTROL_RING_BUFFER_RESERVE_SIZE + + CONNLOG_EMI_32_BYTE_ALIGNED; + +#define INIT_EMI_OFFSET_TABLE(index, base, size, read_offset, write_offset, buf_offset) \ + emi_offset_table[index].emi_base_offset = base; \ + emi_offset_table[index].emi_size = size; \ + emi_offset_table[index].emi_read = read_offset; \ + emi_offset_table[index].emi_write = write_offset; \ + emi_offset_table[index].emi_buf = buf_offset + + INIT_EMI_OFFSET_TABLE( + CONNLOG_TYPE_MCU, + mcu_base, gDev.emi_config.emi_size_mcu, + mcu_base + 0, mcu_base + 4, + mcu_base + CONNLOG_EMI_32_BYTE_ALIGNED); + INIT_EMI_OFFSET_TABLE( + CONNLOG_TYPE_WIFI, + wifi_base, gDev.emi_config.emi_size_wifi, + wifi_base + 0, wifi_base + 4, + wifi_base + CONNLOG_EMI_32_BYTE_ALIGNED); + INIT_EMI_OFFSET_TABLE( + CONNLOG_TYPE_BT, + bt_base, gDev.emi_config.emi_size_bt, + bt_base + 0, bt_base + 4, + bt_base + CONNLOG_EMI_32_BYTE_ALIGNED); + INIT_EMI_OFFSET_TABLE( + CONNLOG_TYPE_GPS, + gps_base, gDev.emi_config.emi_size_gps, + gps_base + 0, gps_base + 4, + gps_base + CONNLOG_EMI_32_BYTE_ALIGNED); + + return 0; +} + +/***************************************************************************** +* FUNCTION +* connlog_emi_deinit +* DESCRIPTION +* Do iounmap for log buffer on EMI +* PARAMETERS +* void +* RETURNS +* void +*****************************************************************************/ +static void connlog_emi_deinit(void) +{ + iounmap(gDev.virAddrEmiLogBase); +} + +/***************************************************************************** +* FUNCTION +* connlog_ring_buffer_init +* DESCRIPTION +* Initialize ring buffer setting for subsys +* PARAMETERS +* void +* RETURNS +* void +*****************************************************************************/ +static int connlog_ring_buffer_init(void) +{ + if (!gDev.virAddrEmiLogBase) { + pr_err("consys emi memory address phyAddrEmiBase invalid\n"); + return -1; + } + + connlog_set_ring_buffer_base_addr(); + /* cache table size init */ + cache_size_table[CONNLOG_TYPE_WIFI] = (emi_offset_table[CONNLOG_TYPE_WIFI].emi_size * 2); + cache_size_table[CONNLOG_TYPE_BT] = (emi_offset_table[CONNLOG_TYPE_BT].emi_size * 2); + cache_size_table[CONNLOG_TYPE_GPS] = emi_offset_table[CONNLOG_TYPE_GPS].emi_size; + cache_size_table[CONNLOG_TYPE_MCU] = emi_offset_table[CONNLOG_TYPE_MCU].emi_size; + + connlog_buffer_init(CONNLOG_TYPE_WIFI); + connlog_buffer_init(CONNLOG_TYPE_BT); + connlog_buffer_init(CONNLOG_TYPE_GPS); + connlog_buffer_init(CONNLOG_TYPE_MCU); + gDev.log_data = connlog_cache_allocate(CONNLOG_LOG_BUFFER_SIZE); + connlog_set_ring_ready(); + + return 0; +} + +/***************************************************************************** +* FUNCTION +* connlog_ring_buffer_deinit +* DESCRIPTION +* Initialize ring buffer setting for subsys +* PARAMETERS +* void +* RETURNS +* void +*****************************************************************************/ +static void connlog_ring_buffer_deinit(void) +{ + int i = 0; + + for (i = 0; i < CONNLOG_TYPE_END; i++) { + kvfree(connlog_buffer_table[i].cache_base); + connlog_buffer_table[i].cache_base = NULL; + } + kvfree(gDev.log_data); + gDev.log_data = NULL; +} + +/***************************************************************************** +* FUNCTION +* connsys_dedicated_log_path_apsoc_init +* DESCRIPTION +* Initialize API for common driver to initialize connsys dedicated log +* for APSOC platform +* PARAMETERS +* emiaddr [IN] EMI physical base address +* irq_num [IN] IRQ id from device tree +* irq_flag [IN] IRQ flag from device tree +* RETURNS +* void +*****************************************************************************/ +int connsys_dedicated_log_path_apsoc_init( + phys_addr_t emi_base, + const struct connlog_emi_config *emi_config, + const struct connlog_irq_config *irq_config) +{ + gDev.phyAddrEmiBase = 0; + gDev.virAddrEmiLogBase = 0; + gDev.conn2ApIrqId = 0; + gDev.eirqOn = false; + gDev.irq_counter = 0; + gDev.irq_callback = NULL; + memset(&gDev.emi_config, 0, sizeof(struct connlog_emi_config)); + + if (connlog_emi_init(emi_base, emi_config)) { + pr_err("EMI init failed\n"); + return -1; + } + + if (connlog_ring_buffer_init()) { + pr_err("Ring buffer init failed\n"); + return -2; + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) + timer_setup(&gDev.workTimer, work_timer_handler, 0); +#else + init_timer(&gDev.workTimer); +#endif + gDev.workTimer.function = work_timer_handler; + spin_lock_init(&gDev.irq_lock); + INIT_WORK(&gDev.logDataWorker, connlog_log_data_handler); + if (connlog_eirq_init(irq_config)) { + pr_err("EIRQ init failed\n"); + return -3; + } + + /* alarm_timer */ + connlog_alarm_init(); + return 0; +} +EXPORT_SYMBOL(connsys_dedicated_log_path_apsoc_init); + +/***************************************************************************** +* FUNCTION +* connsys_dedicated_log_path_apsoc_deinit +* DESCRIPTION +* De-Initialize API for common driver to release cache, un-remap emi and free +* irq for APSOC platform +* PARAMETERS +* void +* RETURNS +* void +*****************************************************************************/ +void connsys_dedicated_log_path_apsoc_deinit(void) +{ + connlog_emi_deinit(); + connlog_eirq_deinit(); + connlog_ring_buffer_deinit(); +} +EXPORT_SYMBOL(connsys_dedicated_log_path_apsoc_deinit); + +/***************************************************************************** +* FUNCTION +* connsys_log_init +* DESCRIPTION +* Init API for subsys driver. +* PARAMETERS +* conn_type [IN] subsys type +* RETURNS +* int 0=success, others=error +*****************************************************************************/ +int connsys_log_init(int conn_type) +{ + return 0; +} +EXPORT_SYMBOL(connsys_log_init); + +/***************************************************************************** +* FUNCTION +* connsys_log_deinit +* DESCRIPTION +* De-init API for subsys driver. +* PARAMETERS +* conn_type [IN] subsys type +* RETURNS +* int 0=success, others=error +*****************************************************************************/ +int connsys_log_deinit(int conn_type) +{ + if (conn_type >= CONNLOG_TYPE_END || conn_type < 0) + return -1; + event_callback_table[conn_type] = 0x0; + return 0; +} +EXPORT_SYMBOL(connsys_log_deinit); + +/***************************************************************************** +* FUNCTION +* connsys_log_get_buf_size +* DESCRIPTION +* Get ring buffer unread size on EMI. +* PARAMETERS +* conn_type [IN] subsys type +* RETURNS +* unsigned int Ring buffer unread size +*****************************************************************************/ +unsigned int connsys_log_get_buf_size(int conn_type) +{ + if (conn_type >= CONNLOG_TYPE_END || conn_type < 0) + return -1; + return RING_SIZE(&connlog_buffer_table[conn_type].ring_cache); +} +EXPORT_SYMBOL(connsys_log_get_buf_size); + +/***************************************************************************** +* FUNCTION +* connsys_log_register_event_cb +* DESCRIPTION +* Register callback function. It'll be trigger while receive conn2ap IRQ. +* PARAMETERS +* conn_type [IN] subsys type +* func [IN] callback function pointer +* RETURNS +* int 0=success, others=error +*****************************************************************************/ +int connsys_log_register_event_cb(int conn_type, CONNLOG_EVENT_CB func) +{ + if (conn_type >= CONNLOG_TYPE_END || conn_type < 0) + return -1; + event_callback_table[conn_type] = func; + return 0; +} +EXPORT_SYMBOL(connsys_log_register_event_cb); + +/***************************************************************************** +* FUNCTION +* connsys_log_read +* DESCRIPTION +* Copy EMI ring buffer data to the buffer that provided by sub-module. +* PARAMETERS +* conn_type [IN] subsys type +* buf [IN] buffer from driver +* count [IN] buffer length +* RETURNS +* ssize_t read buffer size +*****************************************************************************/ +ssize_t connsys_log_read(int conn_type, char *buf, size_t count) +{ + unsigned int written = 0; + unsigned int cache_buf_size; + struct ring_segment ring_seg; + struct ring *ring; + unsigned int size = 0; + + if (conn_type < 0 || conn_type >= CONNLOG_TYPE_END) + return 0; + + ring = &connlog_buffer_table[conn_type].ring_cache; + + if (atomic_read(&log_mode) != LOG_TO_FILE) + goto done; + + size = count < RING_SIZE(ring) ? count : RING_SIZE(ring); + if (RING_EMPTY(ring) || !ring_read_prepare(size, &ring_seg, ring)) { + pr_err("type(%d) no data, possibly taken by concurrent reader.\n", conn_type); + goto done; + } + cache_buf_size = ring_seg.remain; + + RING_READ_FOR_EACH(size, ring_seg, ring) { + memcpy(buf + written, ring_seg.ring_pt, ring_seg.sz); + cache_buf_size -= ring_seg.sz; + written += ring_seg.sz; + } +done: + return written; +} +EXPORT_SYMBOL(connsys_log_read); + +/***************************************************************************** +* FUNCTION +* connsys_log_read_to_user +* DESCRIPTION +* Copy EMI ring buffer data to the user buffer. +* PARAMETERS +* conn_type [IN] subsys type +* buf [IN] user buffer +* count [IN] buffer length +* RETURNS +* ssize_t read buffer size +*****************************************************************************/ +ssize_t connsys_log_read_to_user(int conn_type, char __user *buf, size_t count) +{ + int retval; + unsigned int written = 0; + static DEFINE_RATELIMIT_STATE(_rs, 10 * HZ, 1); + unsigned int cache_buf_size; + struct ring_segment ring_seg; + struct ring *ring; + unsigned int size = 0; + + if (conn_type < 0 || conn_type >= CONNLOG_TYPE_END) + return 0; + + ring = &connlog_buffer_table[conn_type].ring_cache; + + if (atomic_read(&log_mode) != LOG_TO_FILE) + goto done; + + size = count < RING_SIZE(ring) ? count : RING_SIZE(ring); + if (RING_EMPTY(ring) || !ring_read_prepare(size, &ring_seg, ring)) { + pr_err("type(%d) no data, possibly taken by concurrent reader.\n", conn_type); + goto done; + } + cache_buf_size = ring_seg.remain; + + RING_READ_FOR_EACH(size, ring_seg, ring) { + retval = copy_to_user(buf + written, ring_seg.ring_pt, ring_seg.sz); + if (retval) { + if (__ratelimit(&_rs)) + pr_err("copy to user buffer failed, ret:%d\n", retval); + goto done; + } + cache_buf_size -= ring_seg.sz; + written += ring_seg.sz; + } +done: + return written; +} +EXPORT_SYMBOL(connsys_log_read_to_user); + +/***************************************************************************** +* FUNCTION +* connsys_log_get_emi_log_base_vir_addr +* DESCRIPTION +* return EMI log base address whitch has done ioremap. +* PARAMETERS +* void +* RETURNS +* void __iomem * ioremap EMI log base address +*****************************************************************************/ +void __iomem *connsys_log_get_emi_log_base_vir_addr(void) +{ + return gDev.virAddrEmiLogBase; +} +EXPORT_SYMBOL(connsys_log_get_emi_log_base_vir_addr); + +/***************************************************************************** +* FUNCTION +* connsys_dedicated_log_get_utc_time +* DESCRIPTION +* return EMI log base address whitch has done ioremap. +* PARAMETERS +* second [IN] UTC seconds +* usecond [IN] UTC usecons +* RETURNS +* void +*****************************************************************************/ +void connsys_dedicated_log_get_utc_time(unsigned int *second, + unsigned int *usecond) +{ + struct timespec64 time; + + ktime_get_real_ts64(&time); + *second = (unsigned int)time.tv_sec; /* UTC time second unit */ + *usecond = (unsigned int)(time.tv_nsec / NSEC_PER_USEC); /* UTC time microsecond unit */ +} +EXPORT_SYMBOL(connsys_dedicated_log_get_utc_time); + +/***************************************************************************** +* FUNCTION +* connsys_dedicated_log_flush_emi +* DESCRIPTION +* flush EMI buffer to log cache. +* PARAMETERS +* void +* RETURNS +* void +*****************************************************************************/ +void connsys_dedicated_log_flush_emi(void) +{ + connlog_do_schedule_work(false); +} + +/***************************************************************************** +* FUNCTION +* connsys_dedicated_log_dump_emi +* DESCRIPTION +* dump EMI buffer for debug. +* PARAMETERS +* offset [IN] buffer offset +* size [IN] dump buffer size +* RETURNS +* void +*****************************************************************************/ +void connsys_dedicated_log_dump_emi(int offset, int size) +{ + connlog_dump_buf("emi", gDev.virAddrEmiLogBase + offset, size); +} + +/***************************************************************************** +* FUNCTION +* connsys_dedicated_log_set_log_to_file +* DESCRIPTION +* set log mode. +* PARAMETERS +* mode [IN] log mode +* RETURNS +* void +*****************************************************************************/ +void connsys_dedicated_log_set_log_mode(int mode) +{ + atomic_set(&log_mode, (mode > 0 ? LOG_TO_FILE : PRINT_TO_KERNEL_LOG)); +} + +/***************************************************************************** +* FUNCTION +* connsys_dedicated_log_get_log_mode +* DESCRIPTION +* get log mode. +* PARAMETERS +* void +* RETURNS +* int log mode +*****************************************************************************/ +int connsys_dedicated_log_get_log_mode(void) +{ + return atomic_read(&log_mode); +} diff --git a/drivers/misc/mediatek/connectivity/common/debug_utility/connsys_debug_utility.h b/drivers/misc/mediatek/connectivity/common/debug_utility/connsys_debug_utility.h new file mode 100644 index 0000000000000..14d8c2a06ea52 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/debug_utility/connsys_debug_utility.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef _CONNSYS_DEBUG_UTILITY_H_ +#define _CONNSYS_DEBUG_UTILITY_H_ + +#include "connsys_debug_utility_emi.h" +#include +#include + + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +enum CONNLOG_TYPE { + CONNLOG_TYPE_WIFI = 0, + CONNLOG_TYPE_BT = 1, + CONNLOG_TYPE_GPS = 2, + CONNLOG_TYPE_MCU = 3, + CONNLOG_TYPE_END, +}; + +typedef void (*CONNLOG_EVENT_CB) (void); +typedef void (*CONNLOG_IRQ_CB) (void); + +struct connlog_emi_config { + /* basic information */ + phys_addr_t emi_offset; + unsigned int emi_size_total; + /* for individual radio */ + unsigned int emi_size_mcu; + unsigned int emi_size_wifi; + unsigned int emi_size_bt; + unsigned int emi_size_gps; +}; + +struct connlog_irq_config { + unsigned int irq_num; + unsigned int irq_flag; + CONNLOG_IRQ_CB irq_callback; +}; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/* Common Driver API */ +int connsys_dedicated_log_path_apsoc_init( + phys_addr_t emi_base, + const struct connlog_emi_config *emi_config, + const struct connlog_irq_config *irq_config); +void connsys_dedicated_log_path_apsoc_deinit(void); +void __iomem *connsys_log_get_emi_log_base_vir_addr(void); +void connsys_dedicated_log_get_utc_time(unsigned int *second, unsigned int *usecond); +void connsys_dedicated_log_flush_emi(void); +void connsys_dedicated_log_set_log_mode(int mode); +int connsys_dedicated_log_get_log_mode(void); +void connsys_dedicated_log_dump_emi(int offset, int size); + +/* Debug Utility API */ +int connsys_log_init(int conn_type); +int connsys_log_deinit(int conn_type); +unsigned int connsys_log_get_buf_size(int conn_type); +int connsys_log_register_event_cb(int conn_type, CONNLOG_EVENT_CB func); +ssize_t connsys_log_read_to_user(int conn_type, char __user *buf, size_t count); +ssize_t connsys_log_read(int conn_type, char *buf, size_t count); + +int connsys_log_alarm_enable(unsigned int sec); +int connsys_log_alarm_disable(void); +int connsys_log_blank_state_changed(int blank_state); + +#endif /*_CONNSYS_DEBUG_UTILITY_H_*/ diff --git a/drivers/misc/mediatek/connectivity/common/debug_utility/connsys_debug_utility_emi.h b/drivers/misc/mediatek/connectivity/common/debug_utility/connsys_debug_utility_emi.h new file mode 100644 index 0000000000000..485c8119aa108 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/debug_utility/connsys_debug_utility_emi.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _CONN_DEDICATED_LOG_EMI_H_ +#define _CONN_DEDICATED_LOG_EMI_H_ + +#define CONNLOG_EMI_32_BYTE_ALIGNED 32 /* connsys EMI cache is 32-byte aligned */ +#define CONNLOG_CONTROL_RING_BUFFER_BASE_SIZE 64 /* Reserve for setup ring buffer base address */ +#define CONNLOG_CONTROL_RING_BUFFER_RESERVE_SIZE 32 +#define CONNLOG_IRQ_COUNTER_BASE 48 +#define CONNLOG_READY_PATTERN_BASE 56 +#define CONNLOG_READY_PATTERN_BASE_SIZE 8 + +/* Init emi_offset_table */ +/* EMI structure + * +-+-+ +----------------------+ Offset + * | | Header | + * | | size: 0x40 | + * | +----------------------+ +0x40 //CONNLOG_CONTROL_RING_BUFFER_BASE_SIZE + * | | | +0x00: read + * | | MCU | +0x04: write + * | | | +0x20: buf start //CONNLOG_CONTROL_RING_BUFFER_RESERVE_SIZE + * | +----------------------+ + * | | | //reserved, CONNLOG_EMI_32_BYTE_ALIGNED + * | +----------------------+ +(0x40 + 0x20 + MCU_SIZE + 0x20) + * | | | +0x00: read + * | | WIFI | +0x04: write + * v | | +0x20: buf + * | | + * +----------------------+ + * Size | | //reserved, CONNLOG_EMI_32_BYTE_ALIGNED + * +----------------------+ +(0x40 + 0x20 + MCU_SIZE + 0x20) + + * | | (WIFI_SIZE + 0x20 + 0x20) + * | BT | +0x00: read + * ^ | | +0x04: write + * | | | +0x20: buf + * | +----------------------+ + * | | | //reserved, CONNLOG_EMI_32_BYTE_ALIGNED + * | +----------------------+ +(0x40 + 0x20 + MCU_SIZE + 0x20) + + * | | | (WIFI_SIZE + 0x20 + 0x20) + + * | | GPS | (BT_SIZE + 0x20 + 0x20) + * | | | +0x00: read + * | +----------------------+ +0x04: write + * | | padding | +0x20: buf + * +-+-+ +----------------------+ + * + * Header detail: + * +---------------+--------------+---------------+--------------+ Offset + * | MCU base | MCU size | WIFI base | WIFI size | + * +---------------+--------------+---------------+--------------+ +0x10 + * | BT base | BT size | GPS base | GPS size | + * +---------------+--------------+---------------+--------------+ +0x20 + * | Reserved 16 byte | + * +---------------+--------------+---------------+--------------+ +0x30 + * | IRQ count | IRQ submit | | + * | received by | by MCU | "EMIFWLOG" | + * | driver | | | + * +---------------+--------------+---------------+--------------+ +0x40 + * +0 +4 +8 +C +F + */ + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/debug_utility/ring.c b/drivers/misc/mediatek/connectivity/common/debug_utility/ring.c new file mode 100644 index 0000000000000..51fbf82160621 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/debug_utility/ring.c @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "ring.h" +#include +#include +#include + + + +void ring_init(void *base, unsigned int max_size, unsigned int read, + unsigned int write, struct ring *ring) +{ + WARN_ON(!base); + + /* making sure max_size is power of 2 */ + WARN_ON(!max_size || (max_size & (max_size - 1))); + + /* making sure write largger than read */ + WARN_ON(read > write); + + ring->base = base; + ring->read = read; + ring->write = write; + ring->max_size = max_size; +} + +void ring_dump(const char *title, struct ring *ring) +{ + pr_info("[%s] ring:{write=%d, read=%d, max_size=%d}\n", + title, ring->write, ring->read, ring->max_size); +} + +void ring_dump_segment(const char *title, struct ring_segment *seg) +{ + pr_info("[%s] seg:{ring_pt=0x%p, data_pos=%d, sz=%d, remain=%d}\n", + title, seg->ring_pt, seg->data_pos, seg->sz, seg->remain); +} + +/* + * Function prepares the ring_segment and returns the number of valid bytes for read. + */ +unsigned int ring_read_prepare(unsigned int sz, struct ring_segment *seg, struct ring *ring) +{ + unsigned int wt = ring->write; + unsigned int rd = ring->read; + + memset(seg, 0, sizeof(struct ring_segment)); + if (sz > wt - rd) + sz = wt - rd; + seg->remain = sz; + /* ring_dump(__func__, ring); */ + /* ring_dump_segment(__func__, seg); */ + return seg->remain; +} + +/* + * Function prepares the ring_segment and returns the number of bytes available for write. + */ +unsigned int ring_write_prepare(unsigned int sz, struct ring_segment *seg, struct ring *ring) +{ + unsigned int wt = ring->write; + unsigned int rd = ring->read; + + memset(seg, 0, sizeof(struct ring_segment)); + if (sz > ring->max_size - (wt - rd)) + sz = ring->max_size - (wt - rd); + seg->remain = sz; + /* ring_dump(__func__, ring); */ + /* ring_dump_segment(__func__, seg); */ + return seg->remain; +} + +unsigned int ring_overwrite_prepare(unsigned int sz, struct ring_segment *seg, + struct ring *ring) +{ + unsigned int wt = ring->write; + unsigned int rd = ring->read; + + memset(seg, 0, sizeof(struct ring_segment)); + if (sz > ring->max_size - (wt - rd)) + ring->read += sz - (ring->max_size - (wt - rd)); + seg->remain = sz; + /* ring_dump(__func__, ring); */ + /* ring_dump_segment(__func__, seg); */ + return seg->remain; +} + +void __ring_segment_prepare(unsigned int from, unsigned int sz, struct ring_segment *seg, + struct ring *ring) +{ + unsigned int ring_pos = from & (ring->max_size - 1); + + seg->ring_pt = ring->base + ring_pos; + seg->data_pos = (seg->sz ? seg->data_pos + seg->sz : 0); + if (ring_pos + sz <= ring->max_size) + seg->sz = sz; + else + seg->sz = ring->max_size - ring_pos; + seg->remain -= seg->sz; + /* ring_dump(__func__, ring); */ + /* ring_dump_segment(__func__, seg); */ +} + +void _ring_segment_prepare(unsigned int from, struct ring_segment *seg, struct ring *ring) +{ + __ring_segment_prepare(from, seg->remain, seg, ring); +} + +void _ring_segment_prepare_item(unsigned int from, struct ring_segment *seg, struct ring *ring) +{ + unsigned int size; + + size = (seg->remain ? 1 : 0); + __ring_segment_prepare(from, size, seg, ring); +} + +void _ring_read_commit(struct ring_segment *seg, struct ring *ring) +{ + ring->read += seg->sz; + /* ring_dump(__func__, ring); */ + /* ring_dump_segment(__func__, seg); */ +} +void _ring_write_commit(struct ring_segment *seg, struct ring *ring) +{ + ring->write += seg->sz; + /* ring_dump(__func__, ring); */ + /* ring_dump_segment(__func__, seg); */ +} + diff --git a/drivers/misc/mediatek/connectivity/common/debug_utility/ring.h b/drivers/misc/mediatek/connectivity/common/debug_utility/ring.h new file mode 100644 index 0000000000000..81168ce866151 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/debug_utility/ring.h @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _RING_H_ +#define _RING_H_ + +struct ring { + /* addr where ring buffer starts */ + void *base; + /* addr storing the next writable pos, guaranteed to be >= read except when write overflow, but it's ok. */ + unsigned int write; + /* addr storing the next readable pos, except when read == write as buffer empty */ + unsigned int read; + /* must be power of 2 */ + unsigned int max_size; +}; + +struct ring_segment { + /* addr points into ring buffer for read/write */ + void *ring_pt; + /* size to read/write */ + unsigned int sz; + /* pos in external data buffer to read/write */ + unsigned int data_pos; + /* the size to be read/write after this segment completed */ + unsigned int remain; +}; + +void ring_init(void *base, unsigned int max_size, unsigned int read, + unsigned int write, struct ring *ring); +unsigned int ring_read_prepare(unsigned int sz, struct ring_segment *seg, struct ring *ring); +#define ring_read_all_prepare(seg, ring) ring_read_prepare((ring)->max_size, seg, ring) +unsigned int ring_write_prepare(unsigned int sz, struct ring_segment *seg, struct ring *ring); +unsigned int ring_overwrite_prepare(unsigned int sz, + struct ring_segment *seg, struct ring *ring); + +/* making sure max_size is power of 2 */ +#define RING_VALIDATE_SIZE(max_size) WARN_ON(!max_size || (max_size & (max_size - 1))) + +#define RING_EMPTY(ring) ((ring)->read == (ring)->write) +/* equation works even when write overflow */ +#define RING_SIZE(ring) ((ring)->write - (ring)->read) +#define RING_FULL(ring) (RING_SIZE(ring) == (ring)->max_size) +#define RING_WRITE_REMAIN_SIZE(ring) ((ring)->max_size - RING_SIZE(ring)) + +#define RING_READ_FOR_EACH(_sz, _seg, _ring) \ + for (ring_read_prepare(_sz, &(_seg), _ring), \ + _ring_segment_prepare((_ring)->read, &(_seg), (_ring)); \ + (_seg).sz > 0; \ + _ring_read_commit(&(_seg), (_ring)), _ring_segment_prepare((_ring)->read, \ + &(_seg), (_ring))) + +#define RING_READ_ALL_FOR_EACH(seg, ring) RING_READ_FOR_EACH((ring)->max_size, seg, ring) + +#define RING_READ_FOR_EACH_ITEM(_sz, _seg, _ring) \ + for (ring_read_prepare(_sz, &(_seg), _ring), \ + _ring_segment_prepare_item((_ring)->read, &(_seg), (_ring)); \ + (_seg).sz > 0; \ + _ring_read_commit(&(_seg), (_ring)), _ring_segment_prepare_item((_ring)->read, \ + &(_seg), (_ring))) + +#define RING_WRITE_FOR_EACH(_sz, _seg, _ring) \ + for (ring_write_prepare(_sz, &(_seg), _ring),\ + _ring_segment_prepare((_ring)->write, &(_seg), (_ring)); \ + (_seg).sz > 0; \ + _ring_write_commit(&(_seg), (_ring)), _ring_segment_prepare((_ring)->write, \ + &(_seg), (_ring))) + +#define RING_OVERWRITE_FOR_EACH(_sz, _seg, _ring) \ + for (ring_overwrite_prepare(_sz, &(_seg), _ring), \ + _ring_segment_prepare((_ring)->write, &(_seg), (_ring)); \ + (_seg).sz > 0; \ + _ring_write_commit(&(_seg), (_ring)), _ring_segment_prepare((_ring)->write, \ + &(_seg), (_ring))) + +void ring_dump(const char *title, struct ring *ring); +void ring_dump_segment(const char *title, struct ring_segment *seg); + + +/* ring Buffer Internal API */ +void _ring_segment_prepare(unsigned int from, struct ring_segment *seg, struct ring *ring); +void _ring_segment_prepare_item(unsigned int from, struct ring_segment *seg, struct ring *ring); +void _ring_read_commit(struct ring_segment *seg, struct ring *ring); +void _ring_write_commit(struct ring_segment *seg, struct ring *ring); + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/debug_utility/ring_emi.c b/drivers/misc/mediatek/connectivity/common/debug_utility/ring_emi.c new file mode 100644 index 0000000000000..3d0d111dfd4c9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/debug_utility/ring_emi.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include "ring_emi.h" +#include +#include +#include + +void ring_emi_init(void *base, unsigned int max_size, void *read, void *write, struct ring_emi *ring_emi) +{ + WARN_ON(!base || !read || !write); + + /* making sure max_size is power of 2 */ + WARN_ON(!max_size || (max_size & (max_size - 1))); + + /* making sure read & write pointers are 4 bytes aligned */ + WARN_ON(((long)read & 0x3) != 0 || ((long)write & 0x3) != 0); + + ring_emi->base = base; + ring_emi->read = read; + ring_emi->write = write; + if (ring_emi->write) + EMI_WRITE32(ring_emi->write, 0); + if (ring_emi->read) + EMI_WRITE32(ring_emi->read, 0); + ring_emi->max_size = max_size; + pr_info("base: %p, read: %p, write: %p, max_size: %d\n", base, read, write, max_size); +} + +void ring_emi_dump(const char *title, struct ring_emi *ring_emi) +{ + pr_info("[%s] ring_emi:{base=0x%p, write=%d, read=%d, max_size=%d}\n", + title, ring_emi->base, EMI_READ32(ring_emi->write), + EMI_READ32(ring_emi->read), ring_emi->max_size); +} + +void ring_emi_dump_segment(const char *title, struct ring_emi_segment *seg) +{ + pr_info("[%s] seg:{ring_emi_pt=0x%p, data_pos=%d, sz=%d, remain=%d}\n", + title, seg->ring_emi_pt, seg->data_pos, seg->sz, seg->remain); +} + +/* + * Function prepares the ring_emi_segment and returns the number of valid bytes for read. + */ +unsigned int ring_emi_read_prepare(unsigned int sz, struct ring_emi_segment *seg, struct ring_emi *ring_emi) +{ + unsigned int wt = EMI_READ32(ring_emi->write); + unsigned int rd = EMI_READ32(ring_emi->read); + + memset(seg, 0, sizeof(struct ring_emi_segment)); +#ifdef ROUND_REPEAT + if (wt >= rd) { + if (sz > wt - rd) + sz = wt - rd; + seg->remain = sz; + } else { + if (sz > ring_emi->max_size - (rd - wt)) + sz = ring_emi->max_size - (rd - wt); + seg->remain = sz; + } +#else + if (sz > wt - rd) + sz = wt - rd; + seg->remain = sz; +#endif + /* ring_emi_dump(__func__, ring_emi); */ + /* ring_emi_dump_segment(__func__, seg); */ + return seg->remain; +} + +/* + * Function prepares the ring_emi_segment and returns the number of bytes available for write. + */ +unsigned int ring_emi_write_prepare(unsigned int sz, struct ring_emi_segment *seg, struct ring_emi *ring_emi) +{ + unsigned int wt = EMI_READ32(ring_emi->write); + unsigned int rd = EMI_READ32(ring_emi->read); + + memset(seg, 0, sizeof(struct ring_emi_segment)); +#ifdef ROUND_REPEAT + if (wt >= rd) + seg->remain = ring_emi->max_size - (wt - rd + 1); + else + seg->remain = ring_emi->max_size - (rd - wt + 1); + + if (sz <= seg->remain) + seg->remain = sz; +#else + if (sz > ring_emi->max_size - (wt - rd)) + sz = ring_emi->max_size - (wt - rd); + seg->remain = sz; +#endif + /* ring_emi_dump(__func__, ring_emi); */ + /* ring_emi_dump_segment(__func__, seg); */ + return seg->remain; +} + +void _ring_emi_segment_prepare(unsigned int from, struct ring_emi_segment *seg, struct ring_emi *ring_emi) +{ +#ifndef ROUND_REPEAT + unsigned int ring_emi_pos = from & (ring_emi->max_size - 1); + + seg->ring_emi_pt = ring_emi->base + ring_emi_pos; +#else + seg->ring_emi_pt = ring_emi->base + from; +#endif + seg->data_pos = (seg->sz ? seg->data_pos + seg->sz : 0); + if (from + seg->remain <= ring_emi->max_size) + seg->sz = seg->remain; + else + seg->sz = ring_emi->max_size - from; + seg->remain -= seg->sz; + /* ring_emi_dump(__func__, ring_emi); */ + /* ring_emi_dump_segment(__func__, seg); */ +} + +void _ring_emi_read_commit(struct ring_emi_segment *seg, struct ring_emi *ring_emi) +{ +#ifdef ROUND_REPEAT + EMI_WRITE32(ring_emi->read, (EMI_READ32(ring_emi->read) + seg->sz) & (ring_emi->max_size - 1)); +#else + EMI_WRITE32(ring_emi->read, EMI_READ32(ring_emi->read) + seg->sz); +#endif + /* *(ring_emi->read) += seg->sz; */ + /* ring_emi_dump(__func__, ring_emi); */ + /* ring_emi_dump_segment(__func__, seg); */ +} +void _ring_emi_write_commit(struct ring_emi_segment *seg, struct ring_emi *ring_emi) +{ +#ifdef ROUND_REPEAT + EMI_WRITE32(ring_emi->write, (EMI_READ32(ring_emi->write) + seg->sz) & (ring_emi->max_size - 1)); +#else + EMI_WRITE32(ring_emi->write, EMI_READ32(ring_emi->write) + seg->sz); +#endif + /* ring_emi_dump(__func__, ring_emi); */ + /* ring_emi_dump_segment(__func__, seg); */ +} + diff --git a/drivers/misc/mediatek/connectivity/common/debug_utility/ring_emi.h b/drivers/misc/mediatek/connectivity/common/debug_utility/ring_emi.h new file mode 100644 index 0000000000000..30e9e475e7c0f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/debug_utility/ring_emi.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef _RING_EMI_H_ +#define _RING_EMI_H_ + +#include +#define ROUND_REPEAT +#define EMI_READ32(addr) (readl(addr)) +#define EMI_WRITE32(addr, data) (writel(data, addr)) + +struct ring_emi { + /* addr where ring buffer starts */ + void *base; + /* addr storing the next writable pos, guaranteed to be >= read except when write overflow, but it's ok. */ + void *write; + /* addr storing the next readable pos, except when read == write as buffer empty */ + void *read; + /* must be power of 2 */ + unsigned int max_size; +}; + +struct ring_emi_segment { + /* addr points into ring buffer for read/write */ + void *ring_emi_pt; + /* size to read/write */ + unsigned int sz; + /* pos in external data buffer to read/write */ + unsigned int data_pos; + /* the size to be read/write after this segment completed */ + unsigned int remain; +}; + +void ring_emi_init(void *base, unsigned int max_size, void *read, void *write, struct ring_emi *ring_emi); +unsigned int ring_emi_read_prepare(unsigned int sz, struct ring_emi_segment *seg, struct ring_emi *ring_emi); +#define ring_emi_read_all_prepare(seg, ring_emi) ring_emi_read_prepare((ring_emi)->max_size, seg, ring_emi) +unsigned int ring_emi_write_prepare(unsigned int sz, struct ring_emi_segment *seg, struct ring_emi *ring_emi); + +/* making sure max_size is power of 2 */ +#define RING_EMI_VALIDATE_SIZE(max_size) WARN_ON(!max_size || (max_size & (max_size - 1))) + +#define RING_EMI_EMPTY(ring_emi) (EMI_READ32((ring_emi)->read) == EMI_READ32((ring_emi)->write)) +/* equation works even when write overflow */ +#define RING_EMI_SIZE(ring_emi) (EMI_READ32((ring_emi)->write) - EMI_READ32((ring_emi)->read)) +#ifdef ROUND_REPEAT +#define RING_EMI_FULL(ring_emi) (((EMI_READ32((ring_emi)->write) + 1) & ((ring_emi)->max_size - 1)) \ + == EMI_READ32((ring_emi)->read)) +#else +#define RING_EMI_FULL(ring_emi) (RING_EMI_SIZE(ring_emi) == (ring_emi)->max_size) +#endif + +#define RING_EMI_READ_FOR_EACH(_sz, _seg, _ring_emi) \ + for (_ring_emi_segment_prepare(EMI_READ32((_ring_emi)->read), &(_seg), (_ring_emi)); \ + (_seg).sz > 0; \ + _ring_emi_read_commit(&(_seg), (_ring_emi)), \ + _ring_emi_segment_prepare(EMI_READ32((_ring_emi)->read), &(_seg), (_ring_emi))) + +#define RING_EMI_READ_ALL_FOR_EACH(seg, ring_emi) RING_EMI_READ_FOR_EACH((ring_emi)->max_size, seg, ring_emi) + +#define RING_EMI_WRITE_FOR_EACH(_sz, _seg, _ring_emi) \ + for (_ring_emi_segment_prepare(EMI_READ32((_ring_emi)->write), &(_seg), (_ring_emi)); \ + (_seg).sz > 0; \ + _ring_emi_write_commit(&(_seg), (_ring_emi)), \ + _ring_emi_segment_prepare(EMI_READ32((_ring_emi)->write), &(_seg), (_ring_emi))) + +void ring_emi_dump(const char *title, struct ring_emi *ring_emi); +void ring_emi_dump_segment(const char *title, struct ring_emi_segment *seg); + + +/* Ring Buffer Internal API */ +void _ring_emi_segment_prepare(unsigned int from, struct ring_emi_segment *seg, struct ring_emi *ring_emi); +void _ring_emi_read_commit(struct ring_emi_segment *seg, struct ring_emi *ring_emi); +void _ring_emi_write_commit(struct ring_emi_segment *seg, struct ring_emi *ring_emi); + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/debug_utility/tool/connsys_log_AT/connsys_debut_utility_tester.bat b/drivers/misc/mediatek/connectivity/common/debug_utility/tool/connsys_log_AT/connsys_debut_utility_tester.bat new file mode 100644 index 0000000000000..ad6610c04477f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/debug_utility/tool/connsys_log_AT/connsys_debut_utility_tester.bat @@ -0,0 +1,5 @@ +SET log_path=output + +python dedicated_log_path_test.py %log_path% + +PAUSE \ No newline at end of file diff --git a/drivers/misc/mediatek/connectivity/common/debug_utility/tool/connsys_log_AT/dedicated_log_path_test.py b/drivers/misc/mediatek/connectivity/common/debug_utility/tool/connsys_log_AT/dedicated_log_path_test.py new file mode 100644 index 0000000000000..7ce453428120e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/debug_utility/tool/connsys_log_AT/dedicated_log_path_test.py @@ -0,0 +1,134 @@ +# +# Copyright (C) 2016 MediaTek Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See http://www.gnu.org/licenses/gpl-2.0.html for more details. +# + +import sys, os, time +import subprocess +import re +import optparse + +emi_log = 'emi.log' +out_path = '' +MCU_INDEX = 0 +WIFI_INDEX = 1 +BT_INDEX =2 +GPS_INDEX = 3 +WMTDRV_TYPE_BT = 0 +WMTDRV_TYPE_GPS = 2 +WMTDRV_TYPE_WIFI = 3 + +def get_last_emi_log(log_fd, num_line): + log_list = [] + for line in log_fd: + if line.find('emi:') > 0: + log_list.append(line) + num_line *= -1 + return log_list[num_line:] + +def dump_emi(offset, size): + global out_path + dump_emi_init_cmd = "adb shell \"echo 0x2d " + hex(offset) + " " + hex(size) + " " + "> /proc/driver/wmt_dbg\"" + get_emi_log_cmd = "adb shell \"dmesg | grep emi\" > " + os.path.join(out_path, emi_log) + subprocess.call(dump_emi_init_cmd, shell=True) + subprocess.call(get_emi_log_cmd, shell=True) + log_fd = open(os.path.join(out_path, emi_log), 'rb') + log_list = get_last_emi_log(log_fd, 4) + log_fd.close + return log_list + +def find_base_addr(line_list): + base_addr_list = [] + count = 0 + for line in line_list: + # print line + base_addr = '' + pos = line.find('emi:') + digit_list = line[pos+4:].split(' ') + for no, dig in enumerate(digit_list, start=1): + if len(dig) == 2: + base_addr = dig + base_addr + if no % 4 == 1: + count+=1 + if count % 2 == 1: + base_addr_list.append(int(base_addr, 16)) + base_addr = '' + if count >= 8: + break + return base_addr_list + +def subsys_test(line_list, subsys_name): + for line in line_list: + base_addr = '' + count = 0 + pos = line.find('emi:') + digit_list = line[pos+4:].split(' ') + for no, dig in enumerate(digit_list, start=1): + if len(dig) == 2: + base_addr = dig + base_addr + if no % 4 == 1: + if int(base_addr, 16) > 0: + count += 1 + if count == 2: + print '------------------->' + subsys_name + ' connsys log Test PASS!' + return; + base_addr = '' + print '------------------->' + subsys_name + ' connsys log Test FAIL!' + +def subsys_fucn_ctrl(wmtdrv_type, on): + func_ctrl_cmd = "adb shell \"echo 0x07 " + hex(wmtdrv_type) + " " + hex(on) + " " + "> /proc/driver/wmt_dbg\"" + subprocess.call(func_ctrl_cmd, shell=True) + if on == 1: + time.sleep(5) + else: + time.sleep(1) + +def main(): + global out_path + out_folder = sys.argv[1] + out_path = os.path.join(os.getcwd(), out_folder) + print out_path + if(not os.path.exists(out_path)): + os.makedirs(out_path) + + line_list = dump_emi(0, 64) + base_addr_list = [] + + # TEST CASE1 INIT + if line_list[-1].find('EMIFWLOG'): + print '------------------->' + 'Connsys Debug Utility init Test PASS!' + else: + print 'EMIFWLOG not found.' + print '------------------->' + 'Connsys Debug Utility init Test FAIL!' + return + + base_addr_list = find_base_addr(line_list) + print 'subsys base address offset:' + print base_addr_list + + subsys_fucn_ctrl(WMTDRV_TYPE_WIFI, 1) + line_list = dump_emi(base_addr_list[WIFI_INDEX], 64) + subsys_test(line_list, 'WIFI') + + subsys_fucn_ctrl(WMTDRV_TYPE_BT, 1) + line_list = dump_emi(base_addr_list[BT_INDEX], 64) + subsys_test(line_list, 'BT') + + ygps_cmd = "adb shell \"am start -n com.mediatek.ygps/.YgpsActivity\"" + subprocess.call(ygps_cmd, shell=True) + time.sleep(30) + line_list = dump_emi(base_addr_list[GPS_INDEX], 64) + subsys_test(line_list, 'GPS') + ygps_cmd = "adb shell \"am force-stop com.mediatek.ygps\"" + time.sleep(1) + +if __name__ == '__main__': + main() diff --git a/drivers/misc/mediatek/connectivity/common/debug_utility/tool/connsys_log_tool/connsys_log_converter.py b/drivers/misc/mediatek/connectivity/common/debug_utility/tool/connsys_log_tool/connsys_log_converter.py new file mode 100644 index 0000000000000..56db892dc4228 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/debug_utility/tool/connsys_log_tool/connsys_log_converter.py @@ -0,0 +1,174 @@ + +# +# Copyright (C) 2016 MediaTek Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See http://www.gnu.org/licenses/gpl-2.0.html for more details. +# + +import sys +import re +import time +import os +import datetime +import codecs +import struct + +LogHeader = b'\x00\x00\x62' +InfoHeader = b'\x00\x25\x62' +TimeSyncLog = b'\x74\x69\x6D\x65' +LostLog = b'\x6C\x6F\x73\x74' +UTC_DIFF = 0 +UtcTime = 0 +systemTime = 0 + +# write time log +# ex: 01-01 08:34:46.372470 ( 79.231659) +def write_time_title(fh_out, utc_time, system_time): + utcTimeInt = int(utc_time) + utcTimeFrac = utc_time - utcTimeInt + systemTimeInt = int(system_time) + systemTimeFrac = system_time - systemTimeInt + fh_out.write(time.strftime("%m-%d %H:%M:%S", time.gmtime(utcTimeInt)) + ("%.6f " % utcTimeFrac)[1:] + "(%5d" % systemTimeInt + ("%.6f) " % systemTimeFrac)[1:]) + +# check time sync log +# update UTC_DIFF if utc log is chaged +def update_time_sync(fh, fh_out): + global UTC_DIFF + global UtcTime + global systemTime + fh.read(8) # skip 24 byte in header + systemTime = struct.unpack("] ... android time + +such as: +<4>[12175.130847] (0)[62:wdtk-0][cpu-0:thread:62] 2012-08-02 03:41:18.94083 UTC; android time 2012-08-02 11:41:18.94083 +<5>[25676.236787] (0)[313:InputReader][request_suspend_state]: wakeup (0->0) at 25665623103493 (2012-11-19 08:03:43.654473155 UTC) +<6>[ 344.427890] (0)[41:binder_watchdog]binder: 54296 exec 1354:1380 to 110:333 over 4.011 sec () dex_code 4 start_at 581.260 2012-01-02 00:06:18.728 +<6>[ 160.699284] (0)[44:binder_watchdog]binder: 15889 read 563:1223 to 1076:0 over 2.257 sec () dex_code 44 start_at 158.372 android 2013-04-26 21:57:28.624 +<6>[26064.469194].(4)[6320:kworker/u:1]PM: suspend exit 2013-10-12 06:18:48.551577654 UTC +[ 5.219499] .(2)[1:swapper/0]mt-rtc mt-rtc: setting system clock to 2018-01-25 01:24:36 UTC (1516843476) +[ 67.101501] .(1)[249:wdtk-1][name:wd_common_drv&][thread:249][RT:67101493390] 2018-01-25 01:25:38.382875 UTC;android time 2018-01-25 01:25:38.382875 + +''' + +import sys +import re +import time +import os +import datetime +from bisect import bisect_right + +def kernel_to_utc(klog, llog): + # if llog == '-', output to stdout + line = 0 + line_timestamp = [] + diff_timestamp = [] + debug_enable = False + _stdout = True if llog == '-' else False + + # first pass + try: + fh = open(klog, "rb") + if _stdout: + fhout = sys.stdout + else: + fhout = open(llog, "w") + except IOError as err: + print err + sys.exit() + + _re_utc_time = re.compile(r"[^\[]*?\[[ ]*(\d+?\.\d+)\].*?(\d+-\d+-\d+ \d+:\d+:\d+)(\.\d+) UTC") + + for linebuf in fh: + line = line + 1 + + if "UTC" not in linebuf: + continue + + m = _re_utc_time.match(linebuf) + if m: + (ktime, atime, usec) = m.group(1,2,3) + time_sec_int = time.mktime(time.strptime(atime, "%Y-%m-%d %H:%M:%S")) + time_sec = time_sec_int + float(usec) - float(ktime) + + if (debug_enable): + print "*" + print linebuf + print ktime, atime, usec + + line_timestamp.append(line) + diff_timestamp.append(time_sec) + + + # second pass + fh.seek(0, os.SEEK_SET) + + if debug_enable: + print len(line_timestamp),",",len(diff_timestamp) + print line_timestamp + print diff_timestamp + + line_ts_ref = -1 + diff_ts_ref = 0 + + # in case no timestamp exist + if line_timestamp: + line_ts_ref = line_timestamp[0] + diff_ts_ref = diff_timestamp[0] + + # _re_ktime = re.compile(r"^[ ]*?<[^>]+>\[[ ]*?(\d+?\.\d+?)\]") + _re_ktime = re.compile(r"^[^\[]*?\[[ ]*?(\d+?\.\d+?)\]") + + line = 0 + for linebuf in fh: + diff_ts = -1 + line = line + 1 + + m = _re_ktime.match(linebuf) + if m: + diff_ts = float(m.group(1)) + + if line == line_ts_ref: + line_timestamp.pop(0) + line_ts_ref = line_timestamp[0] if line_timestamp else sys.maxint + diff_ts_ref = diff_timestamp.pop(0) + + if debug_enable: print "diff_ts_ref: ", diff_ts_ref + + if diff_ts != -1: + if line_ts_ref != -1: + android_time = diff_ts + diff_ts_ref + android_time_int = int(android_time) + android_time_frac = android_time - android_time_int + + ts = time.localtime(android_time_int) + + fhout.write(time.strftime("%m-%d %H:%M:%S", ts) + ("%.6f " % android_time_frac)[1:]) + else: + fhout.write("??-?? ??:??:??.?????? ") + + fhout.write(linebuf) + + # for debug + # print linebuf, + + try: + fhout.close() + if not _stdout: + fh.close() + except IOError as err: + print err + sys.exit() + + +if __name__ == "__main__": + if (len(sys.argv) not in [2, 3]): + print "Usage: ", sys.argv[0], " [-]" + sys.exit() + + _stdout = False + if len(sys.argv) == 3 and sys.argv[2] == '-': + _stdout = True + + if _stdout: + kernel_to_utc(sys.argv[1],'-') + else: + kernel_to_utc(sys.argv[1],sys.argv[1]+".utc") + sys.exit() From 9b242d8374e64358989c4c2932e3fe9f2501c27b Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 21:50:43 +0800 Subject: [PATCH 13/32] Add files via upload --- .../connectivity/wlan/adaptor/Android.mk | 19 + .../connectivity/wlan/adaptor/Makefile | 67 ++ .../mediatek/connectivity/wlan/adaptor/README | 2 + .../connectivity/wlan/adaptor/fw_log_wifi.c | 405 +++++++++ .../connectivity/wlan/adaptor/fw_log_wifi.h | 34 + .../wlan/adaptor/init.wlan_drv.rc | 6 + .../connectivity/wlan/adaptor/wifi_pwr_on.c | 230 +++++ .../connectivity/wlan/adaptor/wifi_pwr_on.h | 66 ++ .../connectivity/wlan/adaptor/wmt_cdev_wifi.c | 848 ++++++++++++++++++ 9 files changed, 1677 insertions(+) create mode 100644 drivers/misc/mediatek/connectivity/wlan/adaptor/Android.mk create mode 100644 drivers/misc/mediatek/connectivity/wlan/adaptor/Makefile create mode 100644 drivers/misc/mediatek/connectivity/wlan/adaptor/README create mode 100644 drivers/misc/mediatek/connectivity/wlan/adaptor/fw_log_wifi.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/adaptor/fw_log_wifi.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/adaptor/init.wlan_drv.rc create mode 100644 drivers/misc/mediatek/connectivity/wlan/adaptor/wifi_pwr_on.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/adaptor/wifi_pwr_on.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/adaptor/wmt_cdev_wifi.c diff --git a/drivers/misc/mediatek/connectivity/wlan/adaptor/Android.mk b/drivers/misc/mediatek/connectivity/wlan/adaptor/Android.mk new file mode 100644 index 0000000000000..a88532db57075 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/adaptor/Android.mk @@ -0,0 +1,19 @@ +LOCAL_PATH := $(call my-dir) + +ifeq ($(MTK_WLAN_SUPPORT), yes) + +include $(CLEAR_VARS) +LOCAL_MODULE := wmt_chrdev_wifi.ko +LOCAL_PROPRIETARY_MODULE := true +LOCAL_MODULE_OWNER := mtk +LOCAL_INIT_RC := init.wlan_drv.rc +ifeq ($(WIFI_CHIP), CONNAC2X2_SOC3_0) +LOCAL_REQUIRED_MODULES := conninfra.ko +else +LOCAL_REQUIRED_MODULES := wmt_drv.ko +endif +WIFI_ADAPTOR_OPTS := ADAPTOR_OPTS=$(WIFI_CHIP) +include $(MTK_KERNEL_MODULE) +$(linked_module): OPTS += $(WIFI_ADAPTOR_OPTS) + +endif diff --git a/drivers/misc/mediatek/connectivity/wlan/adaptor/Makefile b/drivers/misc/mediatek/connectivity/wlan/adaptor/Makefile new file mode 100644 index 0000000000000..bed786678a83e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/adaptor/Makefile @@ -0,0 +1,67 @@ +############################################################################### +# Necessary Check + +ifneq ($(KERNEL_OUT),) + ccflags-y += -imacros $(KERNEL_OUT)/include/generated/autoconf.h +endif + +ifndef TOP + TOP := $(srctree)/.. +endif + +# Force build fail on modpost warning +KBUILD_MODPOST_FAIL_ON_WARNINGS := y + +ccflags-y += \ + -I$(srctree)/drivers/misc/mediatek/include/mt-plat \ + -I$(TOP)/vendor/mediatek/kernel_modules/connectivity/common/common_main/include \ + -I$(TOP)/vendor/mediatek/kernel_modules/connectivity/common/common_main/linux/include + +ifeq ($(ADAPTOR_OPTS),CONNAC2X2_SOC3_0) +ccflags-y += -I$(TOP)/vendor/mediatek/kernel_modules/connectivity/conninfra/include +ccflags-y += -I$(TOP)/vendor/mediatek/kernel_modules/connectivity/conninfra/debug_utility +ccflags-y += -I$(TOP)/vendor/mediatek/kernel_modules/connectivity/conninfra/debug_utility/include +ccflags-y += -I$(TOP)/vendor/mediatek/kernel_modules/connectivity/conninfra/debug_utility/connsyslog +ccflags-y += -I$(TOP)/vendor/mediatek/kernel_modules/connectivity/conninfra/debug_utility/coredump +endif + +ifneq ($(CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH),) +ccflags-y += -DCONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH +ccflags-y += -I$(TOP)/vendor/mediatek/kernel_modules/connectivity/common/debug_utility +endif + +ifeq ($(CONFIG_MTK_CONN_LTE_IDC_SUPPORT),y) + ccflags-y += -DWMT_IDC_SUPPORT=1 +else + ccflags-y += -DWMT_IDC_SUPPORT=0 +endif + +ifeq ($(ADAPTOR_OPTS),CONNAC2X2_SOC3_0) +ccflags-y += -DCFG_ANDORID_CONNINFRA_SUPPORT=1 +ccflags-y += -DCFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT=1 +else +ccflags-y += -DCFG_ANDORID_CONNINFRA_SUPPORT=0 +ccflags-y += -DCFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT=0 +endif + +ccflags-y += -D MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + +ccflags-y += -D CREATE_NODE_DYNAMIC=1 + +MODULE_NAME := wmt_chrdev_wifi +ifeq ($(CONFIG_WLAN_DRV_BUILD_IN),y) +$(warning $(MODULE_NAME) build-in boot.img) +obj-y += $(MODULE_NAME).o +else +$(warning $(MODULE_NAME) is kernel module) +obj-m += $(MODULE_NAME).o +endif + +# Wi-Fi character device driver +$(MODULE_NAME)-objs += wmt_cdev_wifi.o +ifneq ($(CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH),) +$(MODULE_NAME)-objs += fw_log_wifi.o +endif +ifeq ($(ADAPTOR_OPTS),CONNAC2X2_SOC3_0) +$(MODULE_NAME)-objs += wifi_pwr_on.o +endif diff --git a/drivers/misc/mediatek/connectivity/wlan/adaptor/README b/drivers/misc/mediatek/connectivity/wlan/adaptor/README new file mode 100644 index 0000000000000..a0e1af5ea8937 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/adaptor/README @@ -0,0 +1,2 @@ +Wlan character device driver - kernel modules move out of kernel tree + diff --git a/drivers/misc/mediatek/connectivity/wlan/adaptor/fw_log_wifi.c b/drivers/misc/mediatek/connectivity/wlan/adaptor/fw_log_wifi.c new file mode 100644 index 0000000000000..3f3e5cdc3d583 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/adaptor/fw_log_wifi.c @@ -0,0 +1,405 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wmt_exp.h" +#include "stp_exp.h" +#include "connsys_debug_utility.h" + +#if (CFG_ANDORID_CONNINFRA_SUPPORT == 1) +#include "fw_log_wifi.h" +#include "conninfra.h" +#endif + +MODULE_LICENSE("Dual BSD/GPL"); + +#define PFX "[WIFI-FW] " +#define WIFI_FW_LOG_DBG 3 +#define WIFI_FW_LOG_INFO 2 +#define WIFI_FW_LOG_WARN 1 +#define WIFI_FW_LOG_ERR 0 + +uint32_t fwDbgLevel = WIFI_FW_LOG_DBG; + +#define WIFI_DBG_FUNC(fmt, arg...) \ + do { \ + if (fwDbgLevel >= WIFI_FW_LOG_DBG) \ + pr_info(PFX "%s[D]: " fmt, __func__, ##arg); \ + } while (0) +#define WIFI_INFO_FUNC(fmt, arg...) \ + do { \ + if (fwDbgLevel >= WIFI_FW_LOG_INFO) \ + pr_info(PFX "%s[I]: " fmt, __func__, ##arg); \ + } while (0) +#define WIFI_INFO_FUNC_LIMITED(fmt, arg...) \ + do { \ + if (fwDbgLevel >= WIFI_FW_LOG_INFO) \ + pr_info_ratelimited(PFX "%s[L]: " fmt, __func__, ##arg); \ + } while (0) +#define WIFI_WARN_FUNC(fmt, arg...) \ + do { \ + if (fwDbgLevel >= WIFI_FW_LOG_WARN) \ + pr_info(PFX "%s[W]: " fmt, __func__, ##arg); \ + } while (0) +#define WIFI_ERR_FUNC(fmt, arg...) \ + do { \ + if (fwDbgLevel >= WIFI_FW_LOG_ERR) \ + pr_info(PFX "%s[E]: " fmt, __func__, ##arg); \ + } while (0) + + +#define WIFI_FW_LOG_IOC_MAGIC (0xfc) +#define WIFI_FW_LOG_IOCTL_ON_OFF _IOW(WIFI_FW_LOG_IOC_MAGIC, 0, int) +#define WIFI_FW_LOG_IOCTL_SET_LEVEL _IOW(WIFI_FW_LOG_IOC_MAGIC, 1, int) + +#define WIFI_FW_LOG_CMD_ON_OFF 0 +#define WIFI_FW_LOG_CMD_SET_LEVEL 1 + +#if (CFG_ANDORID_CONNINFRA_SUPPORT == 1) +#define CONNLOG_TYPE_WIFI 0 /* CONN_DEBUG_TYPE_WIFI */ +#endif + +typedef void (*wifi_fwlog_event_func_cb)(int, int); +wifi_fwlog_event_func_cb pfFwEventFuncCB; +static wait_queue_head_t wq; + +#if (CFG_ANDORID_CONNINFRA_SUPPORT == 1) +typedef int (*wifi_fwlog_chkbushang_func_cb)(void *, uint8_t); +wifi_fwlog_chkbushang_func_cb gpfn_check_bus_hang; +#endif + +static struct semaphore ioctl_mtx; + +#if (CFG_ANDORID_CONNINFRA_SUPPORT == 1) +#if (CFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT == 1) +struct connsys_dump_ctx *g_wifi_coredump_handler; +struct coredump_event_cb g_wifi_coredump_cb = { + .reg_readable = fw_log_reg_readable, + .poll_cpupcr = NULL, +}; +#endif /* CFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT */ +#endif /* CFG_ANDORID_CONNINFRA_SUPPORT */ + +void wifi_fwlog_event_func_register(wifi_fwlog_event_func_cb func) +{ + WIFI_INFO_FUNC("wifi_fwlog_event_func_register %p\n", func); + pfFwEventFuncCB = func; +} +EXPORT_SYMBOL(wifi_fwlog_event_func_register); + +int wifi_fwlog_onoff_status(void) +{ + int ret = 88; + return ret; +} +EXPORT_SYMBOL(wifi_fwlog_onoff_status); + +static int fw_log_wifi_open(struct inode *inode, struct file *file) +{ + WIFI_INFO_FUNC("major %d minor %d (pid %d)\n", imajor(inode), iminor(inode), current->pid); + + return 0; +} + +static int fw_log_wifi_release(struct inode *inode, struct file *file) +{ + WIFI_INFO_FUNC("major %d minor %d (pid %d)\n", imajor(inode), iminor(inode), current->pid); + + return 0; +} + +static ssize_t fw_log_wifi_read(struct file *filp, char __user *buf, size_t len, loff_t *off) +{ + size_t ret = 0; + + WIFI_INFO_FUNC_LIMITED("fw_log_wifi_read len --> %d\n", (uint32_t) len); + + ret = connsys_log_read_to_user(CONNLOG_TYPE_WIFI, buf, len); + + return ret; +} + +static unsigned int fw_log_wifi_poll(struct file *filp, poll_table *wait) +{ + poll_wait(filp, &wq, wait); + + if (connsys_log_get_buf_size(CONNLOG_TYPE_WIFI) > 0) + return POLLIN|POLLRDNORM; + return 0; +} + + +static long fw_log_wifi_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + int ret = 0; + + down(&ioctl_mtx); + switch (cmd) { + case WIFI_FW_LOG_IOCTL_ON_OFF:{ + unsigned int log_on_off = (unsigned int) arg; + + WIFI_INFO_FUNC("fw_log_wifi_unlocked_ioctl WIFI_FW_LOG_IOCTL_ON_OFF start\n"); + + if (pfFwEventFuncCB) { + WIFI_INFO_FUNC("WIFI_FW_LOG_IOCTL_ON_OFF invoke:%d\n", (int)log_on_off); + pfFwEventFuncCB(WIFI_FW_LOG_CMD_ON_OFF, log_on_off); + } else + WIFI_ERR_FUNC("WIFI_FW_LOG_IOCTL_ON_OFF invoke failed\n"); + + WIFI_INFO_FUNC("fw_log_wifi_unlocked_ioctl WIFI_FW_LOG_IOCTL_ON_OFF end\n"); + break; + } + case WIFI_FW_LOG_IOCTL_SET_LEVEL:{ + unsigned int log_level = (unsigned int) arg; + + WIFI_INFO_FUNC("fw_log_wifi_unlocked_ioctl WIFI_FW_LOG_IOCTL_SET_LEVEL start\n"); + + if (pfFwEventFuncCB) { + WIFI_INFO_FUNC("WIFI_FW_LOG_IOCTL_SET_LEVEL invoke:%d\n", (int)log_level); + pfFwEventFuncCB(WIFI_FW_LOG_CMD_SET_LEVEL, log_level); + } else + WIFI_ERR_FUNC("WIFI_FW_LOG_IOCTL_ON_OFF invoke failed\n"); + + WIFI_INFO_FUNC("fw_log_wifi_unlocked_ioctl WIFI_FW_LOG_IOCTL_SET_LEVEL end\n"); + break; + } + default: + ret = -EPERM; + } + WIFI_INFO_FUNC("fw_log_wifi_unlocked_ioctl cmd --> %d, ret=%d\n", cmd, ret); + up(&ioctl_mtx); + return ret; +} + + +#if (CFG_ANDORID_CONNINFRA_SUPPORT == 1) +int fw_log_wifi_irq_handler(void) +{ + return connsys_log_irq_handler(CONN_DEBUG_TYPE_WIFI); +} +EXPORT_SYMBOL(fw_log_wifi_irq_handler); + +#if (CFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT == 1) + +void fw_log_bug_hang_register(void *func) +{ + WIFI_INFO_FUNC("fw_log_bug_hang_register: %p\n", func); + gpfn_check_bus_hang = (wifi_fwlog_chkbushang_func_cb)func; +} +EXPORT_SYMBOL(fw_log_bug_hang_register); + +int fw_log_reg_readable(void) +{ + int ret = 1; + + if (conninfra_reg_readable() == 0) { + WIFI_INFO_FUNC("conninfra_reg_readable: 0\n"); + ret = 0; + } + + if (gpfn_check_bus_hang) { + if (gpfn_check_bus_hang(NULL, 0) != 0) { + WIFI_INFO_FUNC("gpfn_check_bus_hang: 1\n"); + ret = 0; + } + } + + WIFI_INFO_FUNC("fw_log_reg_readable: %d\n", ret); + + return ret; +} + +void fw_log_connsys_coredump_init(void) +{ + g_wifi_coredump_handler = connsys_coredump_init(CONN_DEBUG_TYPE_WIFI, &g_wifi_coredump_cb); + if (g_wifi_coredump_handler == NULL) + WIFI_INFO_FUNC("connsys_coredump_init init fail!\n"); +} +EXPORT_SYMBOL(fw_log_connsys_coredump_init); + +void fw_log_connsys_coredump_deinit(void) +{ + connsys_coredump_deinit(g_wifi_coredump_handler); +} +EXPORT_SYMBOL(fw_log_connsys_coredump_deinit); + +void fw_log_connsys_coredump_start(unsigned int drv, char *reason) +{ + connsys_coredump_start(g_wifi_coredump_handler, 0, (enum consys_drv_type)drv, reason); + connsys_coredump_clean(g_wifi_coredump_handler); +} +EXPORT_SYMBOL(fw_log_connsys_coredump_start); +#endif /* CFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT */ +#endif /* CFG_ANDORID_CONNINFRA_SUPPORT */ + +#ifdef CONFIG_COMPAT +static long fw_log_wifi_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + long ret = 0; + int32_t wait_cnt = 0; + + WIFI_INFO_FUNC("COMPAT fw_log_wifi_compact_ioctl cmd --> %d\n", cmd); + + if (!filp->f_op || !filp->f_op->unlocked_ioctl) + return -ENOTTY; + + while (wait_cnt < 2000) { + if (pfFwEventFuncCB) + break; + if (wait_cnt % 20 == 0) + WIFI_ERR_FUNC("Wi-Fi driver is not ready for 2s\n"); + msleep(100); + wait_cnt++; + } + fw_log_wifi_unlocked_ioctl(filp, cmd, arg); + + return ret; +} +#endif + +const struct file_operations fw_log_wifi_fops = { + .open = fw_log_wifi_open, + .release = fw_log_wifi_release, + .read = fw_log_wifi_read, + .poll = fw_log_wifi_poll, + .unlocked_ioctl = fw_log_wifi_unlocked_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = fw_log_wifi_compat_ioctl, +#endif +}; + +struct fw_log_wifi_device { + struct cdev cdev; + dev_t devno; + struct class *driver_class; + struct device *class_dev; +}; + +#define FW_LOG_WIFI_DRIVER_NAME "fw_log_wifi" +static struct fw_log_wifi_device *fw_log_wifi_dev; +static int fw_log_wifi_major; + +static void fw_log_wifi_event_cb(void) +{ + wake_up_interruptible(&wq); +} + +int fw_log_wifi_init(void) +{ + int result = 0; + int err = 0; + + fw_log_wifi_dev = kmalloc(sizeof(struct fw_log_wifi_device), GFP_KERNEL); + + if (fw_log_wifi_dev == NULL) { + result = -ENOMEM; + goto return_fn; + } + + fw_log_wifi_dev->devno = MKDEV(fw_log_wifi_major, 0); + + result = alloc_chrdev_region(&fw_log_wifi_dev->devno, 0, 1, FW_LOG_WIFI_DRIVER_NAME); + fw_log_wifi_major = MAJOR(fw_log_wifi_dev->devno); + WIFI_INFO_FUNC("alloc_chrdev_region result %d, major %d\n", result, fw_log_wifi_major); + + if (result < 0) + return result; + + fw_log_wifi_dev->driver_class = class_create(THIS_MODULE, FW_LOG_WIFI_DRIVER_NAME); + + if (IS_ERR(fw_log_wifi_dev->driver_class)) { + result = -ENOMEM; + WIFI_ERR_FUNC("class_create failed %d.\n", result); + goto unregister_chrdev_region; + } + + fw_log_wifi_dev->class_dev = device_create(fw_log_wifi_dev->driver_class, + NULL, fw_log_wifi_dev->devno, NULL, FW_LOG_WIFI_DRIVER_NAME); + + if (!fw_log_wifi_dev->class_dev) { + result = -ENOMEM; + WIFI_ERR_FUNC("class_device_create failed %d.\n", result); + goto class_destroy; + } + + sema_init(&ioctl_mtx, 1); + + cdev_init(&fw_log_wifi_dev->cdev, &fw_log_wifi_fops); + + fw_log_wifi_dev->cdev.owner = THIS_MODULE; + fw_log_wifi_dev->cdev.ops = &fw_log_wifi_fops; + + err = cdev_add(&fw_log_wifi_dev->cdev, fw_log_wifi_dev->devno, 1); + if (err) { + result = -ENOMEM; + WIFI_ERR_FUNC("Error %d adding fw_log_wifi dev.\n", err); + goto cdev_del; + } + + /* integrated with common debug utility */ + init_waitqueue_head(&wq); + connsys_log_init(CONNLOG_TYPE_WIFI); + connsys_log_register_event_cb(CONNLOG_TYPE_WIFI, fw_log_wifi_event_cb); + pfFwEventFuncCB = NULL; +#if (CFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT == 1) + gpfn_check_bus_hang = NULL; +#endif + goto return_fn; + +cdev_del: + cdev_del(&fw_log_wifi_dev->cdev); +class_destroy: + class_destroy(fw_log_wifi_dev->driver_class); +unregister_chrdev_region: + unregister_chrdev_region(fw_log_wifi_dev->devno, 1); + kfree(fw_log_wifi_dev); +return_fn: + return result; +} +EXPORT_SYMBOL(fw_log_wifi_init); + +int fw_log_wifi_deinit(void) +{ + device_destroy(fw_log_wifi_dev->driver_class, fw_log_wifi_dev->devno); + class_destroy(fw_log_wifi_dev->driver_class); + cdev_del(&fw_log_wifi_dev->cdev); + kfree(fw_log_wifi_dev); + unregister_chrdev_region(MKDEV(fw_log_wifi_major, 0), 1); + WIFI_INFO_FUNC("unregister_chrdev_region major %d\n", fw_log_wifi_major); + + /* integrated with common debug utility */ + connsys_log_deinit(CONNLOG_TYPE_WIFI); + return 0; +} +EXPORT_SYMBOL(fw_log_wifi_deinit); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/adaptor/fw_log_wifi.h b/drivers/misc/mediatek/connectivity/wlan/adaptor/fw_log_wifi.h new file mode 100644 index 0000000000000..c8776f12e1ae8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/adaptor/fw_log_wifi.h @@ -0,0 +1,34 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _FW_LOG_WIFI_H_ +#define _FW_LOG_WIFI_H_ + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH +int fw_log_wifi_init(void); +int fw_log_wifi_deinit(void); +#endif /* CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH */ + +#if (CFG_ANDORID_CONNINFRA_SUPPORT == 1) +int fw_log_wifi_irq_handler(void); +#endif /* CFG_ANDORID_CONNINFRA_SUPPORT */ + +#if (CFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT == 1) +void fw_log_connsys_coredump_init(void); +void fw_log_connsys_coredump_deinit(void); +void fw_log_connsys_coredump_start(unsigned int, char *); +int fw_log_reg_readable(void); +#endif + +#endif /*_FW_LOG_WIFI_H_*/ diff --git a/drivers/misc/mediatek/connectivity/wlan/adaptor/init.wlan_drv.rc b/drivers/misc/mediatek/connectivity/wlan/adaptor/init.wlan_drv.rc new file mode 100644 index 0000000000000..b880d95df6046 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/adaptor/init.wlan_drv.rc @@ -0,0 +1,6 @@ + +# load wifi driver after wmt_loader finish +on property:vendor.connsys.driver.ready=yes + insmod /vendor/lib/modules/wmt_chrdev_wifi.ko + insmod /vendor/lib/modules/wlan_drv_${ro.vendor.wlan.gen}.ko + start wlan_assistant diff --git a/drivers/misc/mediatek/connectivity/wlan/adaptor/wifi_pwr_on.c b/drivers/misc/mediatek/connectivity/wlan/adaptor/wifi_pwr_on.c new file mode 100644 index 0000000000000..3bd43912edd82 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/adaptor/wifi_pwr_on.c @@ -0,0 +1,230 @@ + +/* +* Copyright (C) 2019 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + + +#include +#include +#include +#include +#include +#include +#include "wifi_pwr_on.h" + + + + + +MODULE_LICENSE("Dual BSD/GPL"); + +#define PFX "[WIFI-FW] " +#define WIFI_FW_LOG_DBG 3 +#define WIFI_FW_LOG_INFO 2 +#define WIFI_FW_LOG_WARN 1 +#define WIFI_FW_LOG_ERR 0 + +uint32_t DbgLevel = WIFI_FW_LOG_INFO; + +#define WIFI_DBG_FUNC(fmt, arg...) \ + do { \ + if (DbgLevel >= WIFI_FW_LOG_DBG) \ + pr_info(PFX "%s[D]: " fmt, __func__, ##arg); \ + } while (0) +#define WIFI_INFO_FUNC(fmt, arg...) \ + do { \ + if (DbgLevel >= WIFI_FW_LOG_INFO) \ + pr_info(PFX "%s[I]: " fmt, __func__, ##arg); \ + } while (0) +#define WIFI_INFO_FUNC_LIMITED(fmt, arg...) \ + do { \ + if (DbgLevel >= WIFI_FW_LOG_INFO) \ + pr_info_ratelimited(PFX "%s[L]: " fmt, __func__, ##arg); \ + } while (0) +#define WIFI_WARN_FUNC(fmt, arg...) \ + do { \ + if (DbgLevel >= WIFI_FW_LOG_WARN) \ + pr_info(PFX "%s[W]: " fmt, __func__, ##arg); \ + } while (0) +#define WIFI_ERR_FUNC(fmt, arg...) \ + do { \ + if (DbgLevel >= WIFI_FW_LOG_ERR) \ + pr_info(PFX "%s[E]: " fmt, __func__, ##arg); \ + } while (0) + + +wlan_probe_cb mtk_wlan_probe_function; +wlan_remove_cb mtk_wlan_remove_function; + + +struct completion wlan_pendComp; + +int g_data; + +wait_queue_head_t g_waitq_onoff; +unsigned long g_ulOnoffFlag; +struct completion g_RstOffComp; +bool g_fgIsWiFiOn; +struct task_struct *wland_thread; + +static int mtk_wland_thread_main(void *data); + +int wifi_pwr_on_init(void) +{ + int result = 0; + + init_completion(&wlan_pendComp); + init_waitqueue_head(&g_waitq_onoff); + + wland_thread = kthread_run(mtk_wland_thread_main, + NULL, "mtk_wland_thread"); + WIFI_INFO_FUNC("Do wifi_pwr_on_init.\n"); + return result; +} +EXPORT_SYMBOL(wifi_pwr_on_init); + +int wifi_pwr_on_deinit(void) +{ + WIFI_INFO_FUNC("Do wifi_pwr_on_deinit.\n"); + set_bit(ADAPTOR_FLAG_HALT_BIT, &g_ulOnoffFlag); + wake_up_interruptible(&g_waitq_onoff); + return 0; +} +EXPORT_SYMBOL(wifi_pwr_on_deinit); +int mtk_wcn_wlan_reg(struct MTK_WCN_WLAN_CB_INFO *pWlanCbInfo) +{ + if (!pWlanCbInfo) { + WIFI_ERR_FUNC("wlan cb info in null!\n"); + return -1; + } + WIFI_INFO_FUNC("wmt wlan cb register\n"); + mtk_wlan_probe_function = pWlanCbInfo->wlan_probe_cb; + mtk_wlan_remove_function = pWlanCbInfo->wlan_remove_cb; + + return 0; +} +EXPORT_SYMBOL(mtk_wcn_wlan_reg); + +int mtk_wcn_wlan_unreg(void) +{ + WIFI_INFO_FUNC("wmt wlan cb unregister\n"); + mtk_wlan_probe_function = NULL; + mtk_wlan_remove_function = NULL; + + return 0; +} +EXPORT_SYMBOL(mtk_wcn_wlan_unreg); + +void kalSetOnoffEvent(enum ENUM_WLAN_OPID opId) +{ + + if (opId == WLAN_OPID_FUNC_ON) + set_bit(ADAPTOR_FLAG_ON_BIT, &g_ulOnoffFlag); + else if (opId == WLAN_OPID_FUNC_OFF) + set_bit(ADAPTOR_FLAG_OFF_BIT, &g_ulOnoffFlag); + else { + WIFI_ERR_FUNC("Invalid OPID\n"); + return; + } + /* when we got event, we wake up servie thread */ + wake_up_interruptible(&g_waitq_onoff); +} + + +int mtk_wland_thread_main(void *data) +{ + int ret = 0; + + WIFI_INFO_FUNC("%s:%u starts running...\n", + current->comm, current->pid); + while (1) { + + /* + * sleep on waitqueue if no events occurred. Event contain + * (1) ADAPTOR_FLAG_HALT (2) ADAPTOR_FLAG_ON + * (3) ADAPTOR_FLAG_OFF + */ + do { + ret = wait_event_interruptible(g_waitq_onoff, + ((g_ulOnoffFlag & ADAPTOR_FLAG_ON_OFF_PROCESS) + != 0)); + } while (ret != 0); + + if (test_and_clear_bit(ADAPTOR_FLAG_HALT_BIT, &g_ulOnoffFlag)) { + WIFI_INFO_FUNC("mtk_wland_thread should stop now...\n"); + break; + } + + if (test_and_clear_bit(ADAPTOR_FLAG_ON_BIT, &g_ulOnoffFlag)) { + if (!g_fgIsWiFiOn) { + if (mtk_wlan_probe_function != NULL) { + while (get_pre_cal_status() == 1) { + WIFI_DBG_FUNC("Precal is ongoing.\n"); + msleep(300); + } + g_data = (*mtk_wlan_probe_function)(); + if (g_data == 0) + g_fgIsWiFiOn = MTK_WCN_BOOL_TRUE; + } else { + g_data = ADAPTOR_INVALID_POINTER; + WIFI_ERR_FUNC("Invalid pointer\n"); + } + } else { + WIFI_ERR_FUNC("Wi-Fi is already on\n"); + } + } else if (test_and_clear_bit(ADAPTOR_FLAG_OFF_BIT, &g_ulOnoffFlag)) { + if (g_fgIsWiFiOn) { + if (mtk_wlan_remove_function != NULL) { + g_data = (*mtk_wlan_remove_function)(); + if (g_data == 0) + g_fgIsWiFiOn = MTK_WCN_BOOL_FALSE; + } else { + g_data = ADAPTOR_INVALID_POINTER; + WIFI_ERR_FUNC("Invalid pointer\n"); + } + } else { + WIFI_ERR_FUNC("Wi-Fi is already off\n"); + } + } + complete(&wlan_pendComp); + } + + WIFI_INFO_FUNC("%s:%u stopped!\n", current->comm, current->pid); + + return 0; +} + +int mtk_wcn_wlan_func_ctrl(enum ENUM_WLAN_OPID opId) +{ + bool bRet = MTK_WCN_BOOL_TRUE; + uint32_t waitRet = 0; + reinit_completion(&wlan_pendComp); + + kalSetOnoffEvent(opId); + waitRet = wait_for_completion_timeout(&wlan_pendComp, MSEC_TO_JIFFIES(WIFI_PWR_ON_TIMEOUT)); + if (waitRet > 0) { + /* Case 1: No timeout. */ + if (g_data != 0) + bRet = MTK_WCN_BOOL_FALSE; + } else { + /* Case 2: timeout */ + WIFI_ERR_FUNC("WiFi on/off takes more than %d seconds\n", WIFI_PWR_ON_TIMEOUT/1000); + bRet = MTK_WCN_BOOL_FALSE; + } + return bRet; +} +EXPORT_SYMBOL(mtk_wcn_wlan_func_ctrl); + + + + diff --git a/drivers/misc/mediatek/connectivity/wlan/adaptor/wifi_pwr_on.h b/drivers/misc/mediatek/connectivity/wlan/adaptor/wifi_pwr_on.h new file mode 100644 index 0000000000000..76f479d920ad4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/adaptor/wifi_pwr_on.h @@ -0,0 +1,66 @@ +/* +* Copyright (C) 2019 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _WIFI_PWR_ON_H_ +#define _WIFI_PWR_ON_H_ + +int wifi_pwr_on_init(void); +int wifi_pwr_on_deinit(void); + +typedef int(*wlan_probe_cb) (void); +typedef int(*wlan_remove_cb) (void); + + +struct MTK_WCN_WLAN_CB_INFO { + wlan_probe_cb wlan_probe_cb; + wlan_remove_cb wlan_remove_cb; +}; +extern int mtk_wcn_wlan_reg(struct MTK_WCN_WLAN_CB_INFO *pWlanCbInfo); + +extern uint8_t get_pre_cal_status(void); + +enum ENUM_WLAN_OPID { + WLAN_OPID_FUNC_ON = 0, + WLAN_OPID_FUNC_OFF = 1, + WLAN_OPID_MAX +}; +extern int mtk_wcn_wlan_func_ctrl(enum ENUM_WLAN_OPID opId); + +extern wlan_probe_cb mtk_wlan_probe_function; +extern wlan_remove_cb mtk_wlan_remove_function; + +extern bool g_fgIsWiFiOn; + +#ifndef MTK_WCN_BOOL_TRUE +#define MTK_WCN_BOOL_FALSE ((int) 0) +#define MTK_WCN_BOOL_TRUE ((int) 1) +#endif + +#define MSEC_TO_JIFFIES(_msec) msecs_to_jiffies(_msec) + +#define WIFI_PWR_ON_TIMEOUT 10000 + +#define ADAPTOR_FLAG_HALT BIT(0) +#define ADAPTOR_FLAG_ON BIT(1) +#define ADAPTOR_FLAG_OFF BIT(2) + +#define ADAPTOR_FLAG_HALT_BIT (0) +#define ADAPTOR_FLAG_ON_BIT (1) +#define ADAPTOR_FLAG_OFF_BIT (2) + +#define ADAPTOR_FLAG_ON_OFF_PROCESS (ADAPTOR_FLAG_HALT |\ + ADAPTOR_FLAG_ON |\ + ADAPTOR_FLAG_OFF) +#define ADAPTOR_INVALID_POINTER 0xdeaddead +#endif /*_WIFI_PWR_ON_H_*/ diff --git a/drivers/misc/mediatek/connectivity/wlan/adaptor/wmt_cdev_wifi.c b/drivers/misc/mediatek/connectivity/wlan/adaptor/wmt_cdev_wifi.c new file mode 100644 index 0000000000000..6fbde9b0f981e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/adaptor/wmt_cdev_wifi.c @@ -0,0 +1,848 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fw_log_wifi.h" +#if (CFG_ANDORID_CONNINFRA_SUPPORT == 1) +#include "wifi_pwr_on.h" +#else +#include "wmt_exp.h" +#include "stp_exp.h" +#endif +MODULE_LICENSE("Dual BSD/GPL"); + +#define WIFI_DRIVER_NAME "mtk_wmt_wifi_chrdev" +#define WIFI_DEV_MAJOR 0 + +#define PFX "[MTK-WIFI] " +#define WIFI_LOG_DBG 3 +#define WIFI_LOG_INFO 2 +#define WIFI_LOG_WARN 1 +#define WIFI_LOG_ERR 0 + +uint32_t gDbgLevel = WIFI_LOG_DBG; + +#define WIFI_DBG_FUNC(fmt, arg...) \ + do { \ + if (gDbgLevel >= WIFI_LOG_DBG) \ + pr_info(PFX "%s[D]: " fmt, __func__, ##arg); \ + } while (0) +#define WIFI_INFO_FUNC(fmt, arg...) \ + do { \ + if (gDbgLevel >= WIFI_LOG_INFO) \ + pr_info(PFX "%s[I]: " fmt, __func__, ##arg); \ + } while (0) +#define WIFI_INFO_FUNC_LIMITED(fmt, arg...) \ + do { \ + if (gDbgLevel >= WIFI_LOG_INFO) \ + pr_info_ratelimited(PFX "%s[L]: " fmt, __func__, ##arg); \ + } while (0) +#define WIFI_WARN_FUNC(fmt, arg...) \ + do { \ + if (gDbgLevel >= WIFI_LOG_WARN) \ + pr_info(PFX "%s[W]: " fmt, __func__, ##arg); \ + } while (0) +#define WIFI_ERR_FUNC(fmt, arg...) \ + do { \ + if (gDbgLevel >= WIFI_LOG_ERR) \ + pr_info(PFX "%s[E]: " fmt, __func__, ##arg); \ + } while (0) + +#define VERSION "2.0" + +static int32_t WIFI_devs = 1; +static int32_t WIFI_major = WIFI_DEV_MAJOR; +static dev_t wifi_devno; +module_param(WIFI_major, uint, 0); +static struct cdev WIFI_cdev; +#if CREATE_NODE_DYNAMIC +static struct class *wmtwifi_class; +static struct device *wmtwifi_dev; +#endif + +static struct semaphore wr_mtx; + +#define WLAN_IFACE_NAME "wlan0" + +enum { + WLAN_MODE_HALT, + WLAN_MODE_AP, + WLAN_MODE_STA_P2P, + WLAN_MODE_STA_AP_P2P, + WLAN_MODE_MAX +}; +static int32_t wlan_mode = WLAN_MODE_HALT; +static int32_t powered; +static int32_t isconcurrent; +static char *ifname = WLAN_IFACE_NAME; +static uint32_t driver_loaded; +static int32_t low_latency_mode; +static int32_t wifi_standalone_log_mode; +#if (CFG_ANDORID_CONNINFRA_SUPPORT == 1) +static uint8_t driver_resetting; +static uint8_t write_processing; +static uint8_t pre_cal_ongoing; +#endif +/******************************************************************* + */ +enum ENUM_RESET_STATUS { + RESET_FAIL, + RESET_SUCCESS +}; + +/* + * enable = 1, mode = 0 => init P2P network + * enable = 1, mode = 1 => init Soft AP network + * enable = 0 => uninit P2P/AP network + */ +struct PARAM_CUSTOM_P2P_SET_STRUCT { + uint32_t u4Enable; + uint32_t u4Mode; +}; +typedef int32_t(*set_p2p_mode) (struct net_device *netdev, struct PARAM_CUSTOM_P2P_SET_STRUCT p2pmode); + +static set_p2p_mode pf_set_p2p_mode; +void register_set_p2p_mode_handler(set_p2p_mode handler) +{ + WIFI_INFO_FUNC("(pid %d) register set p2p mode handler %p\n", current->pid, handler); + pf_set_p2p_mode = handler; +} +EXPORT_SYMBOL(register_set_p2p_mode_handler); + +void update_driver_loaded_status(uint8_t loaded) +{ + WIFI_INFO_FUNC("update_driver_loaded_status: %d\n", loaded); + driver_loaded = loaded; +} +EXPORT_SYMBOL(update_driver_loaded_status); + +static int atoh(const char *str, uint32_t *hval) +{ + unsigned int i; + uint32_t val = 0; + + WIFI_INFO_FUNC("*str : %s, len = %zu\n", str, + strlen((const char *)str)); + for (i = 0; i < strlen((const char *)str); i++) { + if (str[i] >= 'a' && str[i] <= 'f') + val = (val << 4) + (str[i] - 'a' + 10); + else if (str[i] >= 'A' && str[i] <= 'F') + val = (val << 4) + (str[i] - 'A' + 10); + else if (*(str + i) >= '0' && *(str + i) <= '9') + val = (val << 4) + (*(str + i) - '0'); + } + + *hval = val; + + return 0; +} + +void set_low_latency_mode(const char *mode) +{ + atoh(mode, &low_latency_mode); + WIFI_INFO_FUNC("LLM : %d\n", low_latency_mode); +} + +uint32_t get_low_latency_mode(void) +{ + WIFI_INFO_FUNC("LLM : %d\n", low_latency_mode); + return low_latency_mode; +} +EXPORT_SYMBOL(get_low_latency_mode); + +void set_wifi_standalone_log_mode(const int mode) +{ + wifi_standalone_log_mode = mode; +} + +uint32_t get_wifi_standalone_log_mode(void) +{ + return wifi_standalone_log_mode; +} +EXPORT_SYMBOL(get_wifi_standalone_log_mode); + +#if (CFG_ANDORID_CONNINFRA_SUPPORT == 1) +void update_driver_reset_status(uint8_t fgIsResetting) +{ + WIFI_INFO_FUNC("update_driver_reset_status: %d\n", fgIsResetting); + driver_resetting = fgIsResetting; +} +EXPORT_SYMBOL(update_driver_reset_status); +int32_t get_wifi_powered_status(void) +{ + WIFI_INFO_FUNC("wifi power status : %d\n", powered); + return powered; +} +EXPORT_SYMBOL(get_wifi_powered_status); +int32_t get_wifi_process_status(void) +{ + WIFI_INFO_FUNC("wifi write status: %d\n", write_processing); + return write_processing; +} +EXPORT_SYMBOL(get_wifi_process_status); +void update_pre_cal_status(uint8_t fgIsPreCal) +{ + WIFI_INFO_FUNC("update_pre_cal_status: %d\n", fgIsPreCal); + pre_cal_ongoing = fgIsPreCal; +} +EXPORT_SYMBOL(update_pre_cal_status); +uint8_t get_pre_cal_status(void) +{ + WIFI_INFO_FUNC("pre cal status: %d\n", pre_cal_ongoing); + return pre_cal_ongoing; +} +EXPORT_SYMBOL(get_pre_cal_status); +#endif + +enum ENUM_WLAN_DRV_BUF_TYPE_T { + BUF_TYPE_NVRAM, + BUF_TYPE_DRV_CFG, + BUF_TYPE_FW_CFG, + BUF_TYPE_NUM +}; + +typedef uint8_t(*file_buf_handler)(void *ctx, const char __user *buf, uint16_t length); +static file_buf_handler buf_handler[BUF_TYPE_NUM]; +static void *buf_handler_ctx[BUF_TYPE_NUM]; +void register_file_buf_handler(file_buf_handler handler, void *handler_ctx, uint8_t ucType) +{ + if (ucType < BUF_TYPE_NUM) { + buf_handler[ucType] = handler; + buf_handler_ctx[ucType] = handler_ctx; + } +} +EXPORT_SYMBOL(register_file_buf_handler); + +/******************************************************************* + * WHOLE CHIP RESET PROCEDURE: + * + * WMTRSTMSG_RESET_START callback + * -> wlanRemove + * -> WMTRSTMSG_RESET_END callback + * + ******************************************************************* +*/ +/*-----------------------------------------------------------------*/ +/* + * Receiving RESET_START message + */ +/*-----------------------------------------------------------------*/ +int32_t wifi_reset_start(void) +{ + struct net_device *netdev = NULL; + struct PARAM_CUSTOM_P2P_SET_STRUCT p2pmode; + + down(&wr_mtx); + + if (powered == 1) { + netdev = dev_get_by_name(&init_net, ifname); + if (netdev == NULL) { + WIFI_ERR_FUNC("Fail to get %s net device\n", ifname); + } else { + p2pmode.u4Enable = 0; + p2pmode.u4Mode = 0; + + if (pf_set_p2p_mode) { + if (pf_set_p2p_mode(netdev, p2pmode) != 0) + WIFI_ERR_FUNC("Turn off p2p/ap mode fail"); + else + WIFI_INFO_FUNC("Turn off p2p/ap mode"); + } + dev_put(netdev); + netdev = NULL; + } + } else { + /* WIFI is off before whole chip reset, do nothing */ + } + + return 0; +} +EXPORT_SYMBOL(wifi_reset_start); + +/*-----------------------------------------------------------------*/ +/* + * Receiving RESET_END/RESET_END_FAIL message + */ +/*-----------------------------------------------------------------*/ +int32_t wifi_reset_end(enum ENUM_RESET_STATUS status) +{ + struct net_device *netdev = NULL; + struct PARAM_CUSTOM_P2P_SET_STRUCT p2pmode; + int32_t wait_cnt = 0; + int32_t ret = -1; + + if (status == RESET_FAIL) { + /* whole chip reset fail, donot recover WIFI */ + ret = 0; + up(&wr_mtx); + } else if (status == RESET_SUCCESS) { + WIFI_WARN_FUNC("WIFI state recovering...\n"); + + if (powered == 1) { + /* WIFI is on before whole chip reset, reopen it now */ +#if (CFG_ANDORID_CONNINFRA_SUPPORT == 1) + /* + * mtk_wland_thread_main will check this flag for current state. + * if this flag is TRUE, mtk_wland_thread_main will not do power on again. + * Set this flag to FALSE to finish the reset procedure + */ + g_fgIsWiFiOn = MTK_WCN_BOOL_FALSE; + if (mtk_wcn_wlan_func_ctrl(WLAN_OPID_FUNC_ON) == MTK_WCN_BOOL_FALSE) { +#else + if (mtk_wcn_wmt_func_on(WMTDRV_TYPE_WIFI) == MTK_WCN_BOOL_FALSE) { +#endif + WIFI_ERR_FUNC("WMT turn on WIFI fail!\n"); + goto done; + } else { + WIFI_INFO_FUNC("WMT turn on WIFI success!\n"); + } + + if (pf_set_p2p_mode == NULL) { + WIFI_ERR_FUNC("Set p2p mode handler is NULL\n"); + goto done; + } + + netdev = dev_get_by_name(&init_net, ifname); + wait_cnt = 0; + while (netdev == NULL && wait_cnt < 10) { + WIFI_ERR_FUNC("Fail to get %s net device, sleep 300ms\n", ifname); + msleep(300); + wait_cnt++; + netdev = dev_get_by_name(&init_net, ifname); + } + if (wait_cnt >= 10) { + WIFI_ERR_FUNC("Get %s net device timeout\n", ifname); + goto done; + } + + if (wlan_mode == WLAN_MODE_STA_P2P) { + p2pmode.u4Enable = 1; + p2pmode.u4Mode = 0; + if (pf_set_p2p_mode(netdev, p2pmode) != 0) { + WIFI_ERR_FUNC("Set wlan mode 0 fail\n"); + } else { + WIFI_WARN_FUNC("Set wlan mode %d\n", WLAN_MODE_STA_P2P); + ret = 0; + } + } else if (wlan_mode == WLAN_MODE_AP) { + p2pmode.u4Enable = 1; + p2pmode.u4Mode = 1; + if (pf_set_p2p_mode(netdev, p2pmode) != 0) { + WIFI_ERR_FUNC("Set wlan mode 1 fail\n"); + } else { + WIFI_WARN_FUNC("Set wlan mode %d\n", WLAN_MODE_AP); + ret = 0; + } + } else if (wlan_mode == WLAN_MODE_STA_AP_P2P) { + p2pmode.u4Enable = 1; + p2pmode.u4Mode = 3; + if (pf_set_p2p_mode(netdev, p2pmode) != 0) { + WIFI_ERR_FUNC("Set wlan mode 3 fail\n"); + } else { + WIFI_WARN_FUNC("Set wlan mode %d\n", WLAN_MODE_STA_AP_P2P); + ret = 0; + } + } else + ret = 0; +done: + if (netdev != NULL) + dev_put(netdev); + } else { + /* WIFI is off before whole chip reset, do nothing */ + ret = 0; + } + up(&wr_mtx); + } + + return ret; +} +EXPORT_SYMBOL(wifi_reset_end); + +static int WIFI_open(struct inode *inode, struct file *file) +{ + WIFI_INFO_FUNC("major %d minor %d (pid %d)\n", imajor(inode), iminor(inode), current->pid); + + return 0; +} + +static int WIFI_close(struct inode *inode, struct file *file) +{ + WIFI_INFO_FUNC("major %d minor %d (pid %d)\n", imajor(inode), iminor(inode), current->pid); + + return 0; +} + +ssize_t WIFI_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) +{ + int32_t retval = -EIO; + int8_t local[20] = { 0 }; + struct net_device *netdev = NULL; + struct PARAM_CUSTOM_P2P_SET_STRUCT p2pmode; + int32_t wait_cnt = 0; + int copy_size = 0; + + down(&wr_mtx); + if (count <= 0) { + WIFI_ERR_FUNC("WIFI_write invalid param\n"); + goto done; + } +#if (CFG_ANDORID_CONNINFRA_SUPPORT == 1) + if (driver_resetting == 1) { + WIFI_ERR_FUNC("Wi-Fi is resetting\n"); + goto done; + } +#endif + copy_size = min(sizeof(local) - 1, count); + if (copy_size < 0) { + WIFI_ERR_FUNC("Invalid copy_size: %d\n", copy_size); + goto done; + } + if (copy_from_user(local, buf, copy_size) == 0) { + local[copy_size] = '\0'; + WIFI_INFO_FUNC("WIFI_write %s, length %zu, copy_size %d\n", + local, count, copy_size); + + if (local[0] == '0') { +#if (CFG_ANDORID_CONNINFRA_SUPPORT == 1) + write_processing = 1; +#endif + if (powered == 0) { + WIFI_INFO_FUNC("WIFI is already power off!\n"); + retval = count; + wlan_mode = WLAN_MODE_HALT; + goto done; + } + + netdev = dev_get_by_name(&init_net, ifname); + if (netdev == NULL) { + WIFI_ERR_FUNC("Fail to get %s net device\n", ifname); + } else { + p2pmode.u4Enable = 0; + p2pmode.u4Mode = 0; + + if (pf_set_p2p_mode) { + if (pf_set_p2p_mode(netdev, p2pmode) != 0) { + WIFI_ERR_FUNC("Turn off p2p/ap mode fail"); + } else { + WIFI_INFO_FUNC("Turn off p2p/ap mode"); + wlan_mode = WLAN_MODE_HALT; + } + } + dev_put(netdev); + netdev = NULL; + } + +#if (CFG_ANDORID_CONNINFRA_SUPPORT == 1) + if (mtk_wcn_wlan_func_ctrl(WLAN_OPID_FUNC_OFF) == MTK_WCN_BOOL_FALSE) { +#else + if (mtk_wcn_wmt_func_off(WMTDRV_TYPE_WIFI) == MTK_WCN_BOOL_FALSE) { +#endif + WIFI_ERR_FUNC("WMT turn off WIFI fail!\n"); + } else { + WIFI_INFO_FUNC("WMT turn off WIFI success!\n"); + powered = 0; + retval = count; + wlan_mode = WLAN_MODE_HALT; + } + } else if (local[0] == '1') { +#if (CFG_ANDORID_CONNINFRA_SUPPORT == 1) + write_processing = 1; +#endif + if (powered == 1) { + WIFI_INFO_FUNC("WIFI is already power on!\n"); + retval = count; + goto done; + } +#if (CFG_ANDORID_CONNINFRA_SUPPORT == 1) + if (mtk_wcn_wlan_func_ctrl(WLAN_OPID_FUNC_ON) == MTK_WCN_BOOL_FALSE) { +#else + if (mtk_wcn_wmt_func_on(WMTDRV_TYPE_WIFI) == MTK_WCN_BOOL_FALSE) { +#endif + WIFI_ERR_FUNC("WMT turn on WIFI fail!\n"); + } else { + powered = 1; + retval = count; + WIFI_INFO_FUNC("WMT turn on WIFI success!\n"); + wlan_mode = WLAN_MODE_HALT; + } + } else if (!strncmp(local, "WR-BUF:", 7)) { + file_buf_handler handler = NULL; + void *ctx = NULL; + + if (!strncmp(&local[7], "NVRAM", 5)) { + copy_size = count - 12; + buf += 12; + wait_cnt = 0; + while (wait_cnt < 2000) { + handler = buf_handler[BUF_TYPE_NVRAM]; + ctx = buf_handler_ctx[BUF_TYPE_NVRAM]; + if (handler) + break; + if (wait_cnt % 20 == 0) + WIFI_ERR_FUNC("Wi-Fi driver is not ready for 2s\n"); + msleep(100); + wait_cnt++; + } + + if (!handler) { + WIFI_ERR_FUNC("Wi-Fi driver is not ready for write NVRAM\n"); + aee_kernel_warning("wlan", "Wi-Fi driver is not ready for write NVRAM\n"); + } else + WIFI_INFO_FUNC("Wi-Fi handler = %p\n", handler); + } else if (!strncmp(&local[7], "DRVCFG", 6)) { + copy_size = count - 13; + buf += 13; + handler = buf_handler[BUF_TYPE_DRV_CFG]; + ctx = buf_handler_ctx[BUF_TYPE_DRV_CFG]; + } else if (!strncmp(&local[7], "FWCFG", 5)) { + copy_size = count - 12; + buf += 12; + handler = buf_handler[BUF_TYPE_FW_CFG]; + ctx = buf_handler_ctx[BUF_TYPE_FW_CFG]; + } + if (handler && !handler(ctx, buf, (uint16_t)copy_size)) + retval = count; + else + retval = -ENOTSUPP; + } else if (!strncmp(local, "RM-BUF:", 7)) { + file_buf_handler handler = NULL; + void *ctx = NULL; + + if (!strncmp(&local[7], "DRVCFG", 6)) { + handler = buf_handler[BUF_TYPE_DRV_CFG]; + ctx = buf_handler_ctx[BUF_TYPE_DRV_CFG]; + } else if (!strncmp(&local[7], "FWCFG", 5)) { + handler = buf_handler[BUF_TYPE_FW_CFG]; + ctx = buf_handler_ctx[BUF_TYPE_FW_CFG]; + } + + if (handler && !handler(ctx, NULL, 0)) + retval = count; + else + retval = -ENOTSUPP; + } else if (local[0] == 'S' || local[0] == 'P' || local[0] == 'A') { + if (powered == 1 && driver_loaded == 0) { + WIFI_INFO_FUNC("In fact wifi is already turned off! reset related states.\n"); + powered = 0; + wlan_mode = WLAN_MODE_HALT; + } + + if (powered == 0) { + /* If WIFI is off, turn on WIFI first */ +#if (CFG_ANDORID_CONNINFRA_SUPPORT == 1) + if (mtk_wcn_wlan_func_ctrl(WLAN_OPID_FUNC_ON) == MTK_WCN_BOOL_FALSE) { +#else + if (mtk_wcn_wmt_func_on(WMTDRV_TYPE_WIFI) == MTK_WCN_BOOL_FALSE) { +#endif + WIFI_ERR_FUNC("WMT turn on WIFI fail!\n"); + goto done; + } else { + powered = 1; + WIFI_INFO_FUNC("WMT turn on WIFI success!\n"); + wlan_mode = WLAN_MODE_HALT; + } + } + + if (pf_set_p2p_mode == NULL) { + WIFI_ERR_FUNC("Set p2p mode handler is NULL\n"); + goto done; + } + + netdev = dev_get_by_name(&init_net, ifname); + wait_cnt = 0; + while (netdev == NULL && wait_cnt < 10) { + WIFI_ERR_FUNC("Fail to get %s net device, sleep 300ms\n", ifname); + msleep(300); + wait_cnt++; + netdev = dev_get_by_name(&init_net, ifname); + } + if (wait_cnt >= 10) { + WIFI_ERR_FUNC("Get %s net device timeout\n", ifname); + goto done; + } + + /* 1. Concurrent mode */ + if (isconcurrent) { + if (wlan_mode == WLAN_MODE_STA_AP_P2P) { + WIFI_INFO_FUNC("WIFI is already in cocurrent mode %d!\n", wlan_mode); + retval = count; + goto done; + } + p2pmode.u4Enable = 1; + p2pmode.u4Mode = 3; + if (pf_set_p2p_mode(netdev, p2pmode) != 0) { + WIFI_ERR_FUNC("Set wlan mode fail\n"); + /* Goto Non-concurrent mode */ + } else { + WIFI_INFO_FUNC("Set wlan mode %d --> %d\n", wlan_mode, WLAN_MODE_STA_AP_P2P); + wlan_mode = WLAN_MODE_STA_AP_P2P; + retval = count; + goto done; + } + } + + /* 2. Non-concurrent mode */ + if ((wlan_mode == WLAN_MODE_STA_P2P && (local[0] == 'S' || local[0] == 'P')) || + (wlan_mode == WLAN_MODE_AP && (local[0] == 'A'))) { + WIFI_INFO_FUNC("WIFI is already in mode %d!\n", wlan_mode); + retval = count; + goto done; + } + + if ((wlan_mode == WLAN_MODE_AP && (local[0] == 'S' || local[0] == 'P')) || + (wlan_mode == WLAN_MODE_STA_P2P && (local[0] == 'A'))) { + p2pmode.u4Enable = 0; + p2pmode.u4Mode = 0; + if (pf_set_p2p_mode(netdev, p2pmode) != 0) { + WIFI_ERR_FUNC("Turn off p2p/ap mode fail"); + goto done; + } + } + + if (local[0] == 'S' || local[0] == 'P') { + p2pmode.u4Enable = 1; + p2pmode.u4Mode = 0; + if (pf_set_p2p_mode(netdev, p2pmode) != 0) { + WIFI_ERR_FUNC("Set wlan mode fail\n"); + } else { + WIFI_INFO_FUNC("Set wlan mode %d --> %d\n", wlan_mode, WLAN_MODE_STA_P2P); + wlan_mode = WLAN_MODE_STA_P2P; + retval = count; + } + } else if (local[0] == 'A') { + p2pmode.u4Enable = 1; + p2pmode.u4Mode = 1; + if (pf_set_p2p_mode(netdev, p2pmode) != 0) { + WIFI_ERR_FUNC("Set wlan mode fail\n"); + } else { + WIFI_INFO_FUNC("Set wlan mode %d --> %d\n", wlan_mode, WLAN_MODE_AP); + wlan_mode = WLAN_MODE_AP; + retval = count; + } + } + dev_put(netdev); + netdev = NULL; + } else if (local[0] == 'C') { + if ((isconcurrent == 0) && + ((wlan_mode == WLAN_MODE_STA_P2P) + || (wlan_mode == WLAN_MODE_AP))) { + netdev = dev_get_by_name(&init_net, ifname); + if (netdev && pf_set_p2p_mode) { + p2pmode.u4Enable = 0; + p2pmode.u4Mode = 0; + if (pf_set_p2p_mode(netdev, p2pmode) != 0) + WIFI_ERR_FUNC("Turn off p2p/ap mode fail"); + else + WIFI_INFO_FUNC("Turn off p2p/ap mode success"); + } else + WIFI_ERR_FUNC("Fail to get %s netdev\n", ifname); + } + isconcurrent = 1; + WIFI_INFO_FUNC("Enable concurrent mode\n"); + retval = count; + } else if (local[0] == 'N') { + if ((isconcurrent == 1) && + (wlan_mode == WLAN_MODE_STA_AP_P2P)) { + netdev = dev_get_by_name(&init_net, ifname); + if (netdev && pf_set_p2p_mode) { + p2pmode.u4Enable = 0; + p2pmode.u4Mode = 0; + if (pf_set_p2p_mode(netdev, p2pmode) != 0) + WIFI_ERR_FUNC("Turn off p2p/ap mode fail"); + else + WIFI_INFO_FUNC("Turn off p2p/ap mode success"); + } else + WIFI_ERR_FUNC("Fail to get %s netdev\n", ifname); + } + isconcurrent = 0; + WIFI_INFO_FUNC("Disable concurrent mode\n"); + retval = count; + } else if (!strncmp(local, "LLM", 3)) { + WIFI_INFO_FUNC("local = %s", local); + if (!strncmp(local + 4, "0x", 2)) { + WIFI_INFO_FUNC("LLM val = %s", local + 6); + set_low_latency_mode(local + 6); + retval = count; + } else { + retval = -ENOTSUPP; + } + } else if (!strncmp(local, "wifiSLog", 8)) { + if (!strncmp(local + 9, "1", 1)) { + WIFI_INFO_FUNC("local = %s, wifiSLog val = %s", local, local + 9); + set_wifi_standalone_log_mode(1); + retval = count; + } else if (!strncmp(local + 9, "0", 1)) { + WIFI_INFO_FUNC("local = %s, wifiSLog val = %s", local, local + 9); + set_wifi_standalone_log_mode(0); + retval = count; + } else { + retval = -ENOTSUPP; + } + } + } +done: + if (netdev != NULL) + dev_put(netdev); +#if (CFG_ANDORID_CONNINFRA_SUPPORT == 1) + write_processing = 0; +#endif + up(&wr_mtx); + return retval; +} + +const struct file_operations WIFI_fops = { + .open = WIFI_open, + .release = WIFI_close, + .write = WIFI_write, +}; + +static int WIFI_init(void) +{ + int32_t alloc_ret = 0; + int32_t cdev_err = 0; + + low_latency_mode = 0; + wifi_standalone_log_mode = 0; + + sema_init(&wr_mtx, 1); + +#if (CFG_ANDORID_CONNINFRA_SUPPORT == 1) + wifi_pwr_on_init(); +#endif + + /* Allocate char device */ + if (WIFI_major) { + wifi_devno = MKDEV(WIFI_major, 0); + alloc_ret = register_chrdev_region(wifi_devno, WIFI_devs, + WIFI_DRIVER_NAME); + } else { + alloc_ret = alloc_chrdev_region(&wifi_devno, 0, WIFI_devs, + WIFI_DRIVER_NAME); + } + if (alloc_ret) { + WIFI_ERR_FUNC("Fail to register device numbers\n"); + return alloc_ret; + } + + cdev_init(&WIFI_cdev, &WIFI_fops); + WIFI_cdev.owner = THIS_MODULE; + + cdev_err = cdev_add(&WIFI_cdev, wifi_devno, WIFI_devs); + if (cdev_err) + goto error; + +#if CREATE_NODE_DYNAMIC /* mknod replace */ + wmtwifi_class = class_create(THIS_MODULE, "wmtWifi"); + if (IS_ERR(wmtwifi_class)) + goto error; + wmtwifi_dev = device_create(wmtwifi_class, NULL, wifi_devno, NULL, + "wmtWifi"); + if (IS_ERR(wmtwifi_dev)) + goto error; +#endif + + WIFI_INFO_FUNC("%s driver(major %d %d) installed.\n", WIFI_DRIVER_NAME, + WIFI_major, MAJOR(wifi_devno)); + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + if (fw_log_wifi_init() < 0) { + WIFI_INFO_FUNC("connsys debug node init failed!!\n"); + goto error; + } +#endif + return 0; + +error: +#if CREATE_NODE_DYNAMIC + if (wmtwifi_dev && !IS_ERR(wmtwifi_dev)) { + device_destroy(wmtwifi_class, wifi_devno); + wmtwifi_dev = NULL; + } + if (wmtwifi_class && !IS_ERR(wmtwifi_class)) { + class_destroy(wmtwifi_class); + wmtwifi_class = NULL; + } +#endif + if (cdev_err == 0) + cdev_del(&WIFI_cdev); + + if (alloc_ret == 0) + unregister_chrdev_region(wifi_devno, WIFI_devs); + + return -1; +} + +static void WIFI_exit(void) +{ +#if CREATE_NODE_DYNAMIC + if (wmtwifi_dev && !IS_ERR(wmtwifi_dev)) { + device_destroy(wmtwifi_class, wifi_devno); + wmtwifi_dev = NULL; + } + if (wmtwifi_class && !IS_ERR(wmtwifi_class)) { + class_destroy(wmtwifi_class); + wmtwifi_class = NULL; + } +#endif + + cdev_del(&WIFI_cdev); + unregister_chrdev_region(wifi_devno, WIFI_devs); + + WIFI_INFO_FUNC("%s driver removed\n", WIFI_DRIVER_NAME); + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + fw_log_wifi_deinit(); +#endif +#if (CFG_ANDORID_CONNINFRA_SUPPORT == 1) + wifi_pwr_on_deinit(); +#endif +} + +#ifdef MTK_WCN_BUILT_IN_DRIVER + +int mtk_wcn_wmt_wifi_init(void) +{ + return WIFI_init(); +} +EXPORT_SYMBOL(mtk_wcn_wmt_wifi_init); + +void mtk_wcn_wmt_wifi_exit(void) +{ + return WIFI_exit(); +} +EXPORT_SYMBOL(mtk_wcn_wmt_wifi_exit); + +#else + +module_init(WIFI_init); +module_exit(WIFI_exit); + +#endif From a3a1e5f29a169089095dfc2150e34f8e2021bd94 Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 21:53:50 +0800 Subject: [PATCH 14/32] Add files via upload --- .../connectivity/wlan/core/gen2/Android.mk | 15 + .../connectivity/wlan/core/gen2/Makefile | 361 + .../connectivity/wlan/core/gen2/README | 2 + .../wlan/core/gen2/common/debug.c | 1601 ++ .../connectivity/wlan/core/gen2/common/dump.c | 357 + .../wlan/core/gen2/common/fwcfg.c | 283 + .../wlan/core/gen2/common/wlan_bow.c | 3152 ++++ .../wlan/core/gen2/common/wlan_lib.c | 5923 +++++++ .../wlan/core/gen2/common/wlan_oid.c | 12725 ++++++++++++++++ .../wlan/core/gen2/common/wlan_p2p.c | 1601 ++ .../wlan/core/gen2/mgmt/aaa_fsm.c | 1237 ++ .../wlan/core/gen2/mgmt/ais_fsm.c | 6023 ++++++++ .../connectivity/wlan/core/gen2/mgmt/assoc.c | 1695 ++ .../connectivity/wlan/core/gen2/mgmt/auth.c | 1232 ++ .../connectivity/wlan/core/gen2/mgmt/bss.c | 2089 +++ .../connectivity/wlan/core/gen2/mgmt/cnm.c | 673 + .../wlan/core/gen2/mgmt/cnm_mem.c | 912 ++ .../wlan/core/gen2/mgmt/cnm_timer.c | 416 + .../wlan/core/gen2/mgmt/hem_mbox.c | 524 + .../connectivity/wlan/core/gen2/mgmt/hs20.c | 437 + .../connectivity/wlan/core/gen2/mgmt/mib.c | 92 + .../wlan/core/gen2/mgmt/p2p_assoc.c | 90 + .../wlan/core/gen2/mgmt/p2p_bss.c | 59 + .../wlan/core/gen2/mgmt/p2p_fsm.c | 3045 ++++ .../wlan/core/gen2/mgmt/p2p_func.c | 4473 ++++++ .../connectivity/wlan/core/gen2/mgmt/p2p_ie.c | 627 + .../wlan/core/gen2/mgmt/p2p_rlm.c | 949 ++ .../wlan/core/gen2/mgmt/p2p_rlm_obss.c | 314 + .../wlan/core/gen2/mgmt/p2p_scan.c | 886 ++ .../wlan/core/gen2/mgmt/p2p_state.c | 488 + .../wlan/core/gen2/mgmt/privacy.c | 905 ++ .../connectivity/wlan/core/gen2/mgmt/qosmap.c | 224 + .../connectivity/wlan/core/gen2/mgmt/rate.c | 447 + .../connectivity/wlan/core/gen2/mgmt/rlm.c | 2850 ++++ .../wlan/core/gen2/mgmt/rlm_domain.c | 1828 +++ .../wlan/core/gen2/mgmt/rlm_obss.c | 315 + .../wlan/core/gen2/mgmt/rlm_protection.c | 57 + .../wlan/core/gen2/mgmt/roaming_fsm.c | 610 + .../connectivity/wlan/core/gen2/mgmt/rsn.c | 3533 +++++ .../wlan/core/gen2/mgmt/saa_fsm.c | 1858 +++ .../connectivity/wlan/core/gen2/mgmt/scan.c | 3956 +++++ .../wlan/core/gen2/mgmt/scan_fsm.c | 2460 +++ .../wlan/core/gen2/mgmt/sec_fsm.c | 978 ++ .../connectivity/wlan/core/gen2/mgmt/stats.c | 1451 ++ .../connectivity/wlan/core/gen2/mgmt/swcr.c | 1079 ++ .../connectivity/wlan/core/gen2/mgmt/tdls.c | 5667 +++++++ .../wlan/core/gen2/mgmt/tdls_com.c | 764 + .../connectivity/wlan/core/gen2/mgmt/wapi.c | 421 + .../connectivity/wlan/core/gen2/mgmt/wmm.c | 1203 ++ .../connectivity/wlan/core/gen2/mgmt/wnm.c | 554 + .../connectivity/wlan/core/gen2/nic/cmd_buf.c | 221 + .../connectivity/wlan/core/gen2/nic/nic.c | 3707 +++++ .../wlan/core/gen2/nic/nic_cmd_event.c | 1349 ++ .../wlan/core/gen2/nic/nic_pwr_mgt.c | 492 + .../connectivity/wlan/core/gen2/nic/nic_rx.c | 3284 ++++ .../connectivity/wlan/core/gen2/nic/nic_tx.c | 2010 +++ .../connectivity/wlan/core/gen2/nic/p2p_nic.c | 195 + .../connectivity/wlan/core/gen2/nic/que_mgt.c | 5363 +++++++ .../wlan/core/gen2/os/linux/gl_bow.c | 1006 ++ .../wlan/core/gen2/os/linux/gl_cfg80211.c | 3661 +++++ .../wlan/core/gen2/os/linux/gl_init.c | 3668 +++++ .../wlan/core/gen2/os/linux/gl_kal.c | 5198 +++++++ .../wlan/core/gen2/os/linux/gl_p2p.c | 4343 ++++++ .../wlan/core/gen2/os/linux/gl_p2p_cfg80211.c | 2084 +++ .../wlan/core/gen2/os/linux/gl_p2p_init.c | 325 + .../wlan/core/gen2/os/linux/gl_p2p_kal.c | 1729 +++ .../wlan/core/gen2/os/linux/gl_proc.c | 1313 ++ .../wlan/core/gen2/os/linux/gl_rst.c | 282 + .../wlan/core/gen2/os/linux/gl_sys.c | 606 + .../wlan/core/gen2/os/linux/gl_vendor.c | 2269 +++ .../wlan/core/gen2/os/linux/gl_wext.c | 4359 ++++++ .../wlan/core/gen2/os/linux/gl_wext_priv.c | 5338 +++++++ .../wlan/core/gen2/os/linux/hif/ahb/ahb.c | 1696 ++ .../wlan/core/gen2/os/linux/hif/ahb/arm.c | 12 + .../core/gen2/os/linux/hif/ahb/include/hif.h | 316 + .../gen2/os/linux/hif/ahb/include/hif_gdma.h | 148 + .../gen2/os/linux/hif/ahb/include/hif_pdma.h | 141 + .../os/linux/hif/ahb/include/mtk_porting.h | 103 + .../core/gen2/os/linux/include/gl_cfg80211.h | 333 + .../wlan/core/gen2/os/linux/include/gl_kal.h | 952 ++ .../wlan/core/gen2/os/linux/include/gl_os.h | 997 ++ .../core/gen2/os/linux/include/gl_p2p_ioctl.h | 581 + .../core/gen2/os/linux/include/gl_p2p_kal.h | 223 + .../core/gen2/os/linux/include/gl_p2p_os.h | 264 + .../wlan/core/gen2/os/linux/include/gl_rst.h | 111 + .../wlan/core/gen2/os/linux/include/gl_sec.h | 24 + .../core/gen2/os/linux/include/gl_typedef.h | 227 + .../core/gen2/os/linux/include/gl_vendor.h | 878 ++ .../wlan/core/gen2/os/linux/include/gl_wext.h | 312 + .../core/gen2/os/linux/include/gl_wext_priv.h | 329 + .../wlan/core/gen2/os/linux/platform.c | 636 + .../connectivity/wlan/core/gen2/os/version.h | 100 + 92 files changed, 144626 insertions(+) create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/Android.mk create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/Makefile create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/README create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/common/debug.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/common/dump.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/common/fwcfg.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/common/wlan_bow.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/common/wlan_lib.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/common/wlan_oid.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/common/wlan_p2p.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/aaa_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/ais_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/assoc.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/auth.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/bss.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/cnm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/cnm_mem.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/cnm_timer.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/hem_mbox.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/hs20.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/mib.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_assoc.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_bss.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_func.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_ie.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_rlm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_rlm_obss.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_scan.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_state.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/privacy.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/qosmap.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/rate.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/rlm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/rlm_domain.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/rlm_obss.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/rlm_protection.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/roaming_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/rsn.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/saa_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/scan.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/scan_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/sec_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/stats.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/swcr.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/tdls.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/tdls_com.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/wapi.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/wmm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/wnm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/cmd_buf.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/nic.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/nic_cmd_event.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/nic_pwr_mgt.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/nic_rx.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/nic_tx.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/p2p_nic.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/que_mgt.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_bow.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_cfg80211.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_init.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_kal.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_p2p.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_p2p_cfg80211.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_p2p_init.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_p2p_kal.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_proc.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_rst.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_sys.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_vendor.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_wext.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_wext_priv.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/hif/ahb/ahb.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/hif/ahb/arm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/hif/ahb/include/hif.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/hif/ahb/include/hif_gdma.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/hif/ahb/include/hif_pdma.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/hif/ahb/include/mtk_porting.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_cfg80211.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_kal.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_os.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_p2p_ioctl.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_p2p_kal.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_p2p_os.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_rst.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_sec.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_typedef.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_vendor.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_wext.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_wext_priv.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/platform.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/os/version.h diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/Android.mk b/drivers/misc/mediatek/connectivity/wlan/core/gen2/Android.mk new file mode 100644 index 0000000000000..9592a436dfb1c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/Android.mk @@ -0,0 +1,15 @@ +LOCAL_PATH := $(call my-dir) + +ifeq ($(MTK_WLAN_SUPPORT), yes) + +# to decide using which generation wlan driver is in wlan_product_package.mk +# (gen2/gen3/gen4/connac/...) + +include $(CLEAR_VARS) +LOCAL_MODULE := wlan_drv_gen2.ko +LOCAL_PROPRIETARY_MODULE := true +LOCAL_MODULE_OWNER := mtk +LOCAL_REQUIRED_MODULES := wmt_chrdev_wifi.ko +include $(MTK_KERNEL_MODULE) + +endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/Makefile b/drivers/misc/mediatek/connectivity/wlan/core/gen2/Makefile new file mode 100644 index 0000000000000..3266d7fe311ea --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/Makefile @@ -0,0 +1,361 @@ +MTK_PLATFORM := $(subst ",,$(CONFIG_MTK_PLATFORM)) +############################################################################### +# Necessary Check + +ifneq ($(KERNEL_OUT),) + ccflags-y += -imacros $(KERNEL_OUT)/include/generated/autoconf.h +endif + +ifeq ($(CONFIG_MTK_COMBO_CHIP),) + $(error CONFIG_MTK_COMBO_CHIP not defined) +endif + +#Force to m +export CONFIG_MTK_COMBO_WIFI=m + +# Force build fail on modpost warning +KBUILD_MODPOST_FAIL_ON_WARNINGS := y +############################################################################### + +# Driver Configure +CONFIG_MTK_COMBO_WIFI_HIF=sdio +CONFIG_MTK_WIFI_ONLY=n + +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/$(MTK_PLATFORM) + +DRIVER_BUILD_DATE=$(shell date +%Y%m%d%H%M%S) +ccflags-y += -DDRIVER_BUILD_DATE='"$(DRIVER_BUILD_DATE)"' + +# --------------------------------------------------- +# Compile Options +# --------------------------------------------------- +ccflags-y += -DLINUX -DMT6628 + +ccflags-y += -DCFG_SUPPORT_WIFI_FW_LOG_UI=1 + +ccflags-y += -DCFG_SUPPORT_AGPS_ASSIST=1 +ccflags-y += -DCFG_SUPPORT_TSF_USING_BOOTTIME=1 +ccflags-y += -DCFG_P2P_LEGACY_COEX_REVISE=1 +ccflags-y += -DARP_MONITER_ENABLE=1 + +ifeq ($(CONFIG_MTK_CONN_LTE_IDC_SUPPORT), y) + ccflags-y += -DWMT_IDC_SUPPORT=1 +else + ccflags-y += -DWMT_IDC_SUPPORT=0 +endif + +ifeq ($(CONFIG_MTK_WIFI_MCC_SUPPORT), y) + ccflags-y += -DCFG_SUPPORT_MCC=1 +else + ccflags-y += -DCFG_SUPPORT_MCC=0 +endif + +ifeq ($(CONFIG_HAVE_XLOG_FEATURE), y) + ccflags-y += -DCFG_SUPPORT_XLOG=1 +else + ccflags-y += -DCFG_SUPPORT_XLOG=0 +endif + +ifeq ($(CONFIG_MTK_AEE_FEATURE), y) + ccflags-y += -DCFG_SUPPORT_AEE=1 +else + ccflags-y += -DCFG_SUPPORT_AEE=0 +endif + +#ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF_SDIO1), y) +# ccflags-y += -D_HIF_SDIO=1 +#endif + +ifeq ($(CONFIG_MTK_PASSPOINT_R2_SUPPORT), y) + ccflags-y += -DCFG_SUPPORT_HOTSPOT_2_0=1 + ccflags-y += -DCFG_HS20_DEBUG=1 + ccflags-y += -DCFG_ENABLE_GTK_FRAME_FILTER=1 +else + ccflags-y += -DCFG_SUPPORT_HOTSPOT_2_0=0 + ccflags-y += -DCFG_HS20_DEBUG=0 + ccflags-y += -DCFG_ENABLE_GTK_FRAME_FILTER=0 +endif + +MTK_MET_PROFILING_SUPPORT = yes +ifeq ($(MTK_MET_PROFILING_SUPPORT), yes) + ccflags-y += -DCFG_SUPPORT_MET_PROFILING=1 +else + ccflags-y += -DCFG_SUPPORT_MET_PROFILING=0 +endif + +ifeq ($(CONFIG_MTK_TC1_FEATURE), y) + ccflags-y += -I$(srctree)/drivers/misc/mediatek/tc1_interface + ccflags-y += -DCFG_TC1_FEATURE=1 + ccflags-y += -DCFG_SUPPORT_CFG_FILE=1 +else + ccflags-y += -DCFG_TC1_FEATURE=0 +endif + +ifeq ($(CONFIG_MTK_TC10_FEATURE), y) + ccflags-y += -DCFG_TC10_FEATURE=1 + ccflags-y += -DCFG_SKIP_MAC_INFO_CHECK +else + ccflags-y += -DCFG_TC10_FEATURE=0 +endif + +MTK_SRAM_SIZE_OPTION=0 +ifeq ($(CONFIG_ARCH_MT6755), y) + MTK_SRAM_SIZE_OPTION=2 +endif +ifeq ($(CONFIG_MACH_MT6757), y) + MTK_SRAM_SIZE_OPTION=2 +endif +ifeq ($(CONFIG_ARCH_MT6735), y) + MTK_SRAM_SIZE_OPTION=1 +endif +ifeq ($(CONFIG_ARCH_MT6735M), y) + MTK_SRAM_SIZE_OPTION=1 +endif +ifeq ($(CONFIG_MACH_MT6739), y) + MTK_SRAM_SIZE_OPTION=2 +endif +ifeq ($(CONFIG_ARCH_MT6753), y) + MTK_SRAM_SIZE_OPTION=1 +endif +ifeq ($(CONFIG_MACH_MT6763), y) + MTK_SRAM_SIZE_OPTION=2 +endif +ifeq ($(CONFIG_ARCH_MT6580), y) + MTK_SRAM_SIZE_OPTION=1 +endif +ifeq ($(CONFIG_ARCH_MT6570), y) + MTK_SRAM_SIZE_OPTION=1 +endif +ifeq ($(CONFIG_ARCH_MT8163), y) + MTK_SRAM_SIZE_OPTION=1 +endif +ifeq ($(CONFIG_ARCH_MT8167), y) + MTK_SRAM_SIZE_OPTION=2 +endif +ccflags-y += -DCFG_SRAM_SIZE_OPTION=$(MTK_SRAM_SIZE_OPTION) + +ifeq ($(strip $(TRUSTONIC_TEE_SUPPORT)),yes) +ifeq ($(strip $(MTK_TEE_CCCI_SECURE_SHARE_MEM_SUPPORT)),yes) + ccflags-y += -DTRUSTONIC_TEE_SUPPORT + ccflags-y += -DMTK_TEE_CCCI_SECURE_SHARE_MEM_SUPPORT +endif +endif + +ccflags-y += -D_HIF_SDIO=1 + +ccflags-y += -DDBG=0 +ccflags-y += -I$(src)/os -I$(src)/os/linux/include -I$(src)/os/linux/hif/ahb/include +ccflags-y += -I$(src)/include -I$(src)/include/nic -I$(src)/include/mgmt +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/$(MTK_PLATFORM)/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/emi/submodule +ccflags-y += -I$(srctree)/drivers/misc/mediatek/emi/$(MTK_PLATFORM) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/connectivity/common +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include/mach/ +ccflags-y += -I$(src)/../../../common/common_main/include +ccflags-y += -I$(src)/../../../common/common_main/linux/include +ccflags-y += -DMTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + +MODULE_NAME := wlan_drv_gen2 +#obj-$(CONFIG_MTK_COMBO_WIFI) += $(MODULE_NAME).o + +#if CONFIG_MTK_COMBO_WIFI=m ==> obj-m means ko module, not build in obj-y +obj-m += $(MODULE_NAME).o + +# --------------------------------------------------- +# Directory List +# --------------------------------------------------- +COMMON_DIR := common/ +OS_DIR := os/linux/ +HIF_DIR := os/linux/hif/ahb/ +NIC_DIR := nic/ +MGMT_DIR := mgmt/ +FWCFG_DIR := $(srctree)/drivers/misc/mediatek/connectivity/wlan/gen2/$(MTK_PROJECT)/ +DMA_DIR := ../../../../platform/$(call lc,$(MTK_PLATFORM))/kernel/drivers/wifi/ +PLAT_DIR := os/linux/plat/$(MTK_PLATFORM)/ +HIF_AHB_PDMA := $(HIF_DIR)$(MTK_PLATFORM)/ +#$(call lc,$(MTK_PLATFORM)) + + +# --------------------------------------------------- +# Objects List +# --------------------------------------------------- + +COMMON_OBJS := $(COMMON_DIR)dump.o \ + $(COMMON_DIR)wlan_lib.o \ + $(COMMON_DIR)wlan_oid.o \ + $(COMMON_DIR)wlan_bow.o \ + $(COMMON_DIR)debug.o + +NIC_OBJS := $(NIC_DIR)nic.o \ + $(NIC_DIR)nic_tx.o \ + $(NIC_DIR)nic_rx.o \ + $(NIC_DIR)nic_pwr_mgt.o \ + $(NIC_DIR)cmd_buf.o \ + $(NIC_DIR)que_mgt.o \ + $(NIC_DIR)nic_cmd_event.o + +OS_OBJS := $(OS_DIR)gl_init.o \ + $(OS_DIR)gl_kal.o \ + $(OS_DIR)gl_bow.o \ + $(OS_DIR)gl_wext.o \ + $(OS_DIR)gl_wext_priv.o \ + $(OS_DIR)gl_rst.o \ + $(OS_DIR)gl_cfg80211.o \ + $(OS_DIR)gl_vendor.o \ + $(OS_DIR)platform.o \ + $(OS_DIR)gl_sys.o \ + $(OS_DIR)gl_proc.o + +MGMT_OBJS := $(MGMT_DIR)ais_fsm.o \ + $(MGMT_DIR)aaa_fsm.o \ + $(MGMT_DIR)assoc.o \ + $(MGMT_DIR)auth.o \ + $(MGMT_DIR)bss.o \ + $(MGMT_DIR)cnm.o \ + $(MGMT_DIR)cnm_timer.o \ + $(MGMT_DIR)cnm_mem.o \ + $(MGMT_DIR)hem_mbox.o \ + $(MGMT_DIR)mib.o \ + $(MGMT_DIR)privacy.o \ + $(MGMT_DIR)rate.o \ + $(MGMT_DIR)rlm.o \ + $(MGMT_DIR)rlm_domain.o \ + $(MGMT_DIR)rlm_obss.o \ + $(MGMT_DIR)rlm_protection.o \ + $(MGMT_DIR)rsn.o \ + $(MGMT_DIR)saa_fsm.o \ + $(MGMT_DIR)scan.o \ + $(MGMT_DIR)scan_fsm.o \ + $(MGMT_DIR)sec_fsm.o \ + $(MGMT_DIR)swcr.o \ + $(MGMT_DIR)swcr.o \ + $(MGMT_DIR)roaming_fsm.o \ + $(MGMT_DIR)hs20.o \ + $(MGMT_DIR)wnm.o \ + $(MGMT_DIR)qosmap.o \ + +# --------------------------------------------------- +# TDLS Objects List +# --------------------------------------------------- +MGMT_OBJS += $(MGMT_DIR)tdls.o \ + $(MGMT_DIR)tdls_com.o + +# --------------------------------------------------- +# STATS Objects List +# --------------------------------------------------- +MGMT_OBJS += $(MGMT_DIR)stats.o + +# --------------------------------------------------- +# P2P Objects List +# --------------------------------------------------- + +COMMON_OBJS += $(COMMON_DIR)wlan_p2p.o + +NIC_OBJS += $(NIC_DIR)p2p_nic.o + +OS_OBJS += $(OS_DIR)gl_p2p.o \ + $(OS_DIR)gl_p2p_cfg80211.o \ + $(OS_DIR)gl_p2p_init.o \ + $(OS_DIR)gl_p2p_kal.o + +MGMT_OBJS += $(MGMT_DIR)p2p_assoc.o \ + $(MGMT_DIR)p2p_bss.o \ + $(MGMT_DIR)p2p_fsm.o \ + $(MGMT_DIR)p2p_func.o \ + $(MGMT_DIR)p2p_rlm.o \ + $(MGMT_DIR)p2p_rlm_obss.o \ + $(MGMT_DIR)p2p_scan.o \ + $(MGMT_DIR)p2p_ie.o \ + $(MGMT_DIR)p2p_state.o \ + $(MGMT_DIR)wnm.o \ + $(MGMT_DIR)wmm.o + +MGMT_OBJS += $(MGMT_DIR)wapi.o + +ifeq ($(WLAN_PROC), y) +OS_OBJS += gl_proc.o +endif + +ifeq ($(CONFIG_ARCH_MT7623), y) +HIF_AHB_PDMA = $(HIF_DIR)mt8127/ +endif +HIF_OBJS := $(HIF_DIR)arm.o \ + $(HIF_DIR)ahb.o \ + $(HIF_AHB_PDMA)ahb_pdma.o +ifeq ($(CONFIG_ARCH_MT6755), y) +PLAT_OBJS := $(PLAT_DIR)plat_priv.o +$(MODULE_NAME)-objs += $(PLAT_OBJS) +endif + +ifeq ($(CONFIG_MACH_MT6757), y) +PLAT_OBJS := $(PLAT_DIR)plat_priv.o +$(MODULE_NAME)-objs += $(PLAT_OBJS) +endif + +ifeq ($(CONFIG_ARCH_MT6570), y) +PLAT_OBJS := $(PLAT_DIR)plat_priv.o +$(MODULE_NAME)-objs += $(PLAT_OBJS) +endif + +ifeq ($(CONFIG_ARCH_MT6735), y) +PLAT_OBJS := $(PLAT_DIR)plat_priv.o +$(MODULE_NAME)-objs += $(PLAT_OBJS) +endif + +ifeq ($(CONFIG_ARCH_MT6735M), y) +PLAT_OBJS := $(PLAT_DIR)plat_priv.o +$(MODULE_NAME)-objs += $(PLAT_OBJS) +endif + +ifeq ($(CONFIG_MACH_MT6735M), y) +PLAT_OBJS := $(PLAT_DIR)plat_priv.o +$(MODULE_NAME)-objs += $(PLAT_OBJS) +endif + +ifeq ($(CONFIG_MACH_MT6763), y) +PLAT_OBJS := $(PLAT_DIR)plat_priv.o +$(MODULE_NAME)-objs += $(PLAT_OBJS) +endif + +ifeq ($(CONFIG_MACH_MT6739), y) +PLAT_OBJS := $(PLAT_DIR)plat_priv.o +$(MODULE_NAME)-objs += $(PLAT_OBJS) +endif + + +# --------------------------------------------------- +# FW customization +# --------------------------------------------------- +FW_CUSTOMIZATION = y +ifeq ($(FW_CUSTOMIZATION), y) + ifneq ($(wildcard $(FWCFG_DIR)fw_config.c),) + COMMON_OBJS += $(MTK_PROJECT)/fw_config.o + endif + COMMON_OBJS += $(COMMON_DIR)fwcfg.o + ccflags-y += -DFW_CFG_SUPPORT + ccflags-y += -DENABLED_IN_ENGUSERDEBUG +endif +# --------------------------------------------------- +# WLAN Parse BUILD VARINAT +# --------------------------------------------------- +ifeq ($(TARGET_BUILD_VARIANT), eng) + ccflags-y += -DWLAN_ENG_LOAD +endif +ifeq ($(TARGET_BUILD_VARIANT), userdebug) + ccflags-y += -DWLAN_USERDEBUG_LOAD +endif +ifeq ($(TARGET_BUILD_VARIANT), user) + ccflags-y += -DWLAN_USER_LOAD +endif +# --------------------------------------------------- + +$(MODULE_NAME)-objs += $(COMMON_OBJS) +$(MODULE_NAME)-objs += $(NIC_OBJS) +$(MODULE_NAME)-objs += $(OS_OBJS) +$(MODULE_NAME)-objs += $(HIF_OBJS) +$(MODULE_NAME)-objs += $(MGMT_OBJS) + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/README b/drivers/misc/mediatek/connectivity/wlan/core/gen2/README new file mode 100644 index 0000000000000..cde67dab65fd4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/README @@ -0,0 +1,2 @@ +Wlan gen2 driver - kernel modules move out of kernel tree + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/common/debug.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/common/debug.c new file mode 100644 index 0000000000000..de16129259eb9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/common/debug.c @@ -0,0 +1,1601 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#include "precomp.h" +#include "gl_kal.h" + +struct COMMAND { + UINT_8 ucCID; + BOOLEAN fgSetQuery; + BOOLEAN fgNeedResp; + UINT_8 ucCmdSeqNum; +}; + +struct SECURITY_FRAME { + UINT_16 u2EthType; + UINT_16 u2Reserved; +}; + +struct MGMT_FRAME { + UINT_16 u2FrameCtl; + UINT_16 u2DurationID; +}; + +typedef struct _TC_RES_RELEASE_ENTRY { + UINT_64 u8RelaseTime; + UINT_32 u4RelCID; + UINT_8 ucTc4RelCnt; + UINT_8 ucAvailableTc4; +} TC_RES_RELEASE_ENTRY, *P_TC_RES_RELEASE_ENTRY; + +typedef struct _CMD_TRACE_ENTRY { + UINT_64 u8TxTime; + COMMAND_TYPE eCmdType; + UINT_32 u4RelCID; + union { + struct COMMAND rCmd; + struct SECURITY_FRAME rSecFrame; + struct MGMT_FRAME rMgmtFrame; + } u; +} CMD_TRACE_ENTRY, *P_CMD_TRACE_ENTRY; + +#define READ_CPUPCR_MAX_NUM 3 +typedef struct _COMMAND_ENTRY { + UINT_64 u8TxTime; + UINT_64 u8ReadFwTime; + UINT_32 u4ReadFwValue; + UINT_32 arCpupcrValue[READ_CPUPCR_MAX_NUM]; + UINT_32 u4RelCID; + UINT_16 u2Counter; + struct COMMAND rCmd; +} COMMAND_ENTRY, *P_COMMAND_ENTRY; + +struct COMMAND_DEBUG_INFO { + UINT_8 ucCID; + UINT_8 ucCmdSeqNum; + UINT_32 u4InqueTime; + UINT_32 u4SendToFwTime; + UINT_32 u4FwResponseTime; +}; +typedef struct _PKT_INFO_ENTRY { + UINT_64 u8Timestamp; + UINT_8 status; + UINT_16 u2EtherType; + UINT_8 ucIpProto; + UINT_16 u2IpId; + UINT_16 u2ArpOpCode; + +} PKT_INFO_ENTRY, *P_PKT_INFO_ENTRY; + +typedef struct _PKT_TRACE_RECORD { + P_PKT_INFO_ENTRY pTxPkt; + P_PKT_INFO_ENTRY pRxPkt; + UINT_32 u4TxIndex; + UINT_32 u4RxIndex; +} PKT_TRACE_RECORD, *P_PKT_TRACE_RECORD; + +typedef struct _SCAN_HIF_DESC_RECORD { + P_HIF_TX_DESC_T pTxDescScanWriteBefore; + P_HIF_TX_DESC_T pTxDescScanWriteDone; + UINT_64 u8ScanWriteBeforeTime; + UINT_64 u8ScanWriteDoneTime; + UINT_32 aucFreeBufCntScanWriteBefore; + UINT_32 aucFreeBufCntScanWriteDone; +} SCAN_HIF_DESC_RECORD, *P_SCAN_HIF_DESC_RECORD; + +typedef struct _FWDL_DEBUG_T { + UINT_32 u4TxStartTime; + UINT_32 u4TxDoneTime; + UINT_32 u4RxStartTime; + UINT_32 u4RxDoneTime; + UINT_32 u4Section; + UINT_32 u4DownloadSize; + UINT_32 u4ResponseTime; +} FWDL_DEBUG_T, *P_FWDL_DEBUG_T; + +typedef struct _BSS_TRACE_RECORD { + UINT_8 aucBSSID[MAC_ADDR_LEN]; + UINT_8 ucRCPI; +} BSS_TRACE_RECORD, *P_BSS_TRACE_RECORD; + +typedef struct _SCAN_TARGET_BSS_LIST { + P_BSS_TRACE_RECORD prBssTraceRecord; + UINT_32 u4BSSIDCount; +} SCAN_TARGET_BSS_LIST, *P_SCAN_TARGET_BSS_LIST; + +#define PKT_INFO_BUF_MAX_NUM 50 +#define PKT_INFO_MSG_LENGTH 200 +#define PKT_INFO_MSG_GROUP_RANGE 3 + +typedef struct _PKT_STATUS_ENTRY { + UINT_8 u1Type; + UINT_16 u2IpId; + UINT_8 status; + UINT_64 u4pktXmitTime; /* unit: naro seconds */ + UINT_64 u4pktToHifTime; /* unit: naro seconds */ + UINT_32 u4ProcessTimeDiff; /*ms*/ +} PKT_STATUS_ENTRY, *P_PKT_STATUS_ENTRY; + +typedef struct _PKT_STATUS_RECORD { + P_PKT_STATUS_ENTRY pTxPkt; + P_PKT_STATUS_ENTRY pRxPkt; + UINT_32 u4TxIndex; + UINT_32 u4RxIndex; +} PKT_STATUS_RECORD, *P_PKT_STATUS_RECORD; + +#define TC_RELEASE_TRACE_BUF_MAX_NUM 100 +#define TXED_CMD_TRACE_BUF_MAX_NUM 100 +#define TXED_COMMAND_BUF_MAX_NUM 10 +#define MAX_FW_IMAGE_PACKET_COUNT 500 +#define SCAN_TARGET_BSS_MAX_NUM 20 +#define SCAN_MSG_MAX_LEN 256 + +#define PKT_STATUS_BUF_MAX_NUM 450 +#define PKT_STATUS_MSG_GROUP_RANGE 80 +#define PKT_STATUS_MSG_LENGTH 900 + +#define CMD_BUF_MSG_LENGTH 1024 + +#if CFG_SUPPORT_EMI_DEBUG +#define WLAN_EMI_DEBUG_BUF_SIZE 512 +#define WLAN_EMI_DEBUG_LINE_SIZE 256 +#endif + +static P_TC_RES_RELEASE_ENTRY gprTcReleaseTraceBuffer; +static P_CMD_TRACE_ENTRY gprCmdTraceEntry; +static P_COMMAND_ENTRY gprCommandEntry; +static struct COMMAND_DEBUG_INFO *gprCommandDebugInfo; + + +static PKT_TRACE_RECORD grPktRec; +static PKT_STATUS_RECORD grPktStaRec; +static SCAN_HIF_DESC_RECORD grScanHifDescRecord; +P_FWDL_DEBUG_T gprFWDLDebug; + + + +UINT_32 u4FWDL_packet_count; +static SCAN_TARGET_BSS_LIST grScanTargetBssList; +static UINT_16 gau2PktSeq[PKT_STATUS_BUF_MAX_NUM]; +UINT_32 u4PktSeqCount; + + + +VOID wlanPktDebugTraceInfoARP(UINT_8 status, UINT_8 eventType, UINT_16 u2ArpOpCode) +{ + if (eventType == PKT_TX) + status = 0xFF; + + wlanPktDebugTraceInfo(status, eventType, ETH_P_ARP, 0, 0, u2ArpOpCode); + +} +VOID wlanPktDebugTraceInfoIP(UINT_8 status, UINT_8 eventType, UINT_8 ucIpProto, UINT_16 u2IpId) +{ + if (eventType == PKT_TX) + status = 0xFF; + + wlanPktDebugTraceInfo(status, eventType, ETH_P_IP, ucIpProto, u2IpId, 0); + +} + +VOID wlanPktDebugTraceInfo(UINT_8 status, UINT_8 eventType + , UINT_16 u2EtherType, UINT_8 ucIpProto, UINT_16 u2IpId, UINT_16 u2ArpOpCode) +{ + + P_PKT_INFO_ENTRY prPkt = NULL; + UINT_32 index; + + DBGLOG(TX, LOUD, "PKT id = 0x%02x, status =%d, Proto = %d, type =%d\n" + , u2IpId, status, ucIpProto, eventType); + do { + if (grPktRec.pTxPkt == NULL || grPktRec.pRxPkt == NULL) { + DBGLOG(TX, ERROR, "pTxPkt is null point !"); + break; + } + + /* debug for Package info begin */ + if (eventType == PKT_TX) { + prPkt = &grPktRec.pTxPkt[grPktRec.u4TxIndex]; + grPktRec.u4TxIndex++; + if (grPktRec.u4TxIndex == PKT_INFO_BUF_MAX_NUM) + grPktRec.u4TxIndex = 0; + } else if (eventType == PKT_RX) { + prPkt = &grPktRec.pRxPkt[grPktRec.u4RxIndex]; + grPktRec.u4RxIndex++; + if (grPktRec.u4RxIndex == PKT_INFO_BUF_MAX_NUM) + grPktRec.u4RxIndex = 0; + } + + if (prPkt) { + prPkt->u8Timestamp = sched_clock(); + prPkt->status = status; + prPkt->u2EtherType = u2EtherType; + prPkt->ucIpProto = ucIpProto; + prPkt->u2IpId = u2IpId; + prPkt->u2ArpOpCode = u2ArpOpCode; + } + + /* Update tx status */ + if (eventType == PKT_TX_DONE) { + /* Support Ethernet type = IP*/ + if (u2EtherType == ETH_P_IP) { + for (index = 0; index < PKT_INFO_BUF_MAX_NUM; index++) { + if (grPktRec.pTxPkt[index].u2IpId == u2IpId) { + grPktRec.pTxPkt[index].status = status; + DBGLOG(TX, LOUD, "PKT_TX_DONE match\n"); + break; + } + } + } + } + } while (FALSE); +} + +VOID wlanPktDebugDumpInfo(P_ADAPTER_T prAdapter) +{ + + UINT_32 i; + UINT_32 index; + UINT_32 offsetMsg; + UINT_32 pktIndex; + P_PKT_INFO_ENTRY prPktInfo; + UINT_8 pucMsg[PKT_INFO_MSG_LENGTH]; + + do { + if (grPktRec.pTxPkt == NULL || grPktRec.pRxPkt == NULL) + break; + + if (grPktRec.u4TxIndex == 0 && grPktRec.u4RxIndex == 0) + break; + + offsetMsg = 0; + /* start dump pkt info of tx/rx by decrease timestap */ + + for (i = 0 ; i < 2 ; i++) { + for (index = 0; index < PKT_INFO_BUF_MAX_NUM ; index++) { + if (i == 0) { + /* TX */ + pktIndex = (PKT_INFO_BUF_MAX_NUM + (grPktRec.u4TxIndex - 1) - index) + % PKT_INFO_BUF_MAX_NUM; + prPktInfo = &grPktRec.pTxPkt[pktIndex]; + } else if (i == 1) { + /* RX */ + pktIndex = (PKT_INFO_BUF_MAX_NUM + (grPktRec.u4RxIndex - 1) - index) + % PKT_INFO_BUF_MAX_NUM; + prPktInfo = &grPktRec.pRxPkt[pktIndex]; + } + + /*ucIpProto = 0x01 ICMP */ + /*ucIpProto = 0x11 UPD */ + /*ucIpProto = 0x06 TCP */ + offsetMsg += kalSnprintf(pucMsg + offsetMsg + , PKT_INFO_MSG_LENGTH - offsetMsg + , "(%2d)t=%llu s=%d e=0x%02x,p=0x%2x id=0x%4x,op=%d " + , index, prPktInfo->u8Timestamp + , prPktInfo->status + , prPktInfo->u2EtherType + , prPktInfo->ucIpProto + , prPktInfo->u2IpId + , prPktInfo->u2ArpOpCode); + + if ((index == PKT_INFO_BUF_MAX_NUM - 1) || + (index % PKT_INFO_MSG_GROUP_RANGE == (PKT_INFO_MSG_GROUP_RANGE - 1))) { + + if (i == 0) + DBGLOG(TX, INFO, "%s\n", pucMsg); + else if (i == 1) + DBGLOG(RX, INFO, "%s\n", pucMsg); + + offsetMsg = 0; + kalMemSet(pucMsg, '\0', PKT_INFO_MSG_LENGTH); + } + } + } + + } while (FALSE); + +} +VOID wlanPktStausDebugUpdateProcessTime(UINT_32 u4DbgTxPktStatusIndex) +{ + P_PKT_STATUS_ENTRY prPktInfo; + + if (u4DbgTxPktStatusIndex == 0xffff || u4DbgTxPktStatusIndex >= PKT_STATUS_BUF_MAX_NUM) { + DBGLOG(TX, WARN, "Can't support the index %d!\n", u4DbgTxPktStatusIndex); + return; + } + + prPktInfo = &grPktStaRec.pTxPkt[u4DbgTxPktStatusIndex]; + if (prPktInfo != NULL) { + + prPktInfo->u4pktToHifTime = sched_clock(); + if (prPktInfo->u4pktToHifTime > prPktInfo->u4pktXmitTime) + prPktInfo->u4ProcessTimeDiff = (UINT_32)(prPktInfo->u4pktToHifTime - prPktInfo->u4pktXmitTime); + else + prPktInfo->u4ProcessTimeDiff = 0; + + /* transfer the time's uint from 'ns' to 'ms'*/ + prPktInfo->u4ProcessTimeDiff /= 1000000; + } + +} + + +VOID wlanPktStatusDebugTraceInfoSeq(P_ADAPTER_T prAdapter, UINT_16 u2NoSeq) +{ + if (u4PktSeqCount >= PKT_STATUS_BUF_MAX_NUM) + u4PktSeqCount = 0; + gau2PktSeq[u4PktSeqCount] = u2NoSeq; + u4PktSeqCount++; +} + + + +VOID wlanPktStatusDebugTraceInfoARP(UINT_8 status, UINT_8 eventType, UINT_16 u2ArpOpCode, PUINT_8 pucPkt + , P_MSDU_INFO_T prMsduInfo) +{ + if (eventType == PKT_TX) + status = 0xFF; + wlanPktStatusDebugTraceInfo(status, eventType, ETH_P_ARP, 0, 0, u2ArpOpCode, pucPkt, prMsduInfo); +} + +VOID wlanPktStatusDebugTraceInfoIP(UINT_8 status, UINT_8 eventType, UINT_8 ucIpProto, UINT_16 u2IpId, PUINT_8 pucPkt + , P_MSDU_INFO_T prMsduInfo) +{ + if (eventType == PKT_TX) + status = 0xFF; + wlanPktStatusDebugTraceInfo(status, eventType, ETH_P_IP, ucIpProto, u2IpId, 0, pucPkt, prMsduInfo); +} + +VOID wlanPktStatusDebugTraceInfo(UINT_8 status, UINT_8 eventType + , UINT_16 u2EtherType, UINT_8 ucIpProto, UINT_16 u2IpId, UINT_16 u2ArpOpCode + , PUINT_8 pucPkt, P_MSDU_INFO_T prMsduInfo) +{ + P_PKT_STATUS_ENTRY prPktSta = NULL; + UINT_32 index; + + DBGLOG(TX, LOUD, "PKT id = 0x%02x, status =%d, Proto = %d, type =%d\n" + , u2IpId, status, ucIpProto, eventType); + do { + if (grPktStaRec.pTxPkt == NULL) { + DBGLOG(TX, ERROR, "pTxStaPkt is null point !"); + break; + } + + /* debug for Package info begin */ + if (eventType == PKT_TX) + prPktSta = &grPktStaRec.pTxPkt[grPktStaRec.u4TxIndex]; + else if (eventType == PKT_RX) + prPktSta = &grPktStaRec.pRxPkt[grPktStaRec.u4RxIndex]; + + + if (prPktSta) { + prPktSta->u1Type = kalGetPktEtherType(pucPkt); + prPktSta->status = status; + prPktSta->u2IpId = u2IpId; + if (eventType == PKT_TX) { + prMsduInfo->u4DbgTxPktStatusIndex = grPktStaRec.u4TxIndex; + prPktSta->u4pktXmitTime = GLUE_GET_PKT_XTIME(prMsduInfo->prPacket); + + } + } + + /* Update tx status */ + if (eventType == PKT_TX_DONE) { + /* Support Ethernet type = IP*/ + if (u2EtherType == ETH_P_IP) { + for (index = 0; index < PKT_STATUS_BUF_MAX_NUM; index++) { + if (grPktStaRec.pTxPkt[index].u2IpId == u2IpId) { + grPktStaRec.pTxPkt[index].status = status; + DBGLOG(TX, TRACE, "Status: PKT_TX_DONE match\n"); + break; + } + } + } + } + + /*update the index of record */ + if (eventType == PKT_TX) { + grPktStaRec.u4TxIndex++; + if (grPktStaRec.u4TxIndex == PKT_STATUS_BUF_MAX_NUM) { + DBGLOG(TX, INFO, "grPktStaRec.u4TxIndex reset"); + grPktStaRec.u4TxIndex = 0; + } + } else if (eventType == PKT_RX) { + grPktStaRec.u4RxIndex++; + if (grPktStaRec.u4RxIndex == PKT_STATUS_BUF_MAX_NUM) { + DBGLOG(TX, INFO, "grPktStaRec.u4RxIndex reset"); + grPktStaRec.u4RxIndex = 0; + } + } + + } while (FALSE); +} + +VOID wlanPktStatusDebugDumpInfo(P_ADAPTER_T prAdapter) +{ + UINT_32 i; + UINT_32 index; + UINT_32 offsetMsg; + P_PKT_STATUS_ENTRY prPktInfo; + UINT_8 pucMsg[PKT_STATUS_MSG_LENGTH]; + UINT_32 u4PktCnt; + UINT_64 u8TxTimeBase; /*ns*/ + UINT_32 u4TxTimeOffset; /*ms*/ + UINT_8 uMsgGroupRange; + + do { + + if (grPktStaRec.pTxPkt == NULL || grPktStaRec.pRxPkt == NULL) + break; + + if (grPktStaRec.u4TxIndex == 0 && grPktStaRec.u4RxIndex == 0) + break; + + offsetMsg = 0; + u4TxTimeOffset = 0; + u8TxTimeBase = grPktStaRec.pTxPkt[0].u4pktXmitTime; + + DBGLOG(TX, INFO, "Pkt dump: TxCnt %d, RxCnt %d tx_pkt timebase:%lld ns\n" + , grPktStaRec.u4TxIndex, grPktStaRec.u4RxIndex, u8TxTimeBase); + + /* start dump pkt info of tx/rx by decrease timestap */ + for (i = 0 ; i < 2 ; i++) { + if (i == 0) { + u4PktCnt = grPktStaRec.u4TxIndex; + uMsgGroupRange = PKT_STATUS_MSG_GROUP_RANGE/2; + } else { + u4PktCnt = grPktStaRec.u4RxIndex; + uMsgGroupRange = PKT_STATUS_MSG_GROUP_RANGE; + } + + for (index = 0; index < u4PktCnt; index++) { + if (i == 0) + prPktInfo = &grPktStaRec.pTxPkt[index]; + else + prPktInfo = &grPktStaRec.pRxPkt[index]; + /*ucIpProto = 0x01 ICMP */ + /*ucIpProto = 0x11 UPD */ + /*ucIpProto = 0x06 TCP */ + + if (i == 0) { + /*tx format*/ + u4TxTimeOffset = prPktInfo->u4pktXmitTime - u8TxTimeBase; + /*transfer the time's uint form 'ns' to 'ms'*/ + u4TxTimeOffset /= 1000000; + + DBGLOG(TX, LOUD, "ipid=0x%x,(%lld - %lld = %d ms),offset=%d ms\n" + , prPktInfo->u2IpId, prPktInfo->u4pktToHifTime + , prPktInfo->u4pktXmitTime, prPktInfo->u4ProcessTimeDiff + , u4TxTimeOffset); + + + offsetMsg += kalSnprintf(pucMsg + offsetMsg + , (PKT_STATUS_MSG_LENGTH - offsetMsg) + , "%d,%02x,%x,%d,%d " + , prPktInfo->u1Type + , prPktInfo->u2IpId + , prPktInfo->status + , u4TxTimeOffset /*ms*/ + , prPktInfo->u4ProcessTimeDiff /*ms*/ + ); + } else { + /*rx format*/ + offsetMsg += kalSnprintf(pucMsg + offsetMsg + , (PKT_STATUS_MSG_LENGTH - offsetMsg) + , "%d,%02x,%x " + , prPktInfo->u1Type + , prPktInfo->u2IpId + , prPktInfo->status); + } + + if (((index + 1) % uMsgGroupRange == 0) || (index == (u4PktCnt - 1))) { + if (i == 0) + DBGLOG(TX, INFO, "%s\n", pucMsg); + else if (i == 1) + DBGLOG(RX, INFO, "%s\n", pucMsg); + + offsetMsg = 0; + kalMemSet(pucMsg, '\0', PKT_STATUS_MSG_LENGTH); + } + } + } + + /*dump rx sequence*/ + kalMemZero(pucMsg, PKT_STATUS_MSG_LENGTH * sizeof(UINT_8)); + offsetMsg = 0; + offsetMsg += kalSnprintf(pucMsg + offsetMsg, (PKT_STATUS_MSG_LENGTH - offsetMsg) + , "RX Seq count: %d [", u4PktSeqCount); + + for (index = 0; index < u4PktSeqCount; index++) + offsetMsg += kalSnprintf(pucMsg + offsetMsg, (PKT_STATUS_MSG_LENGTH - offsetMsg) + , "%x,", gau2PktSeq[index]); + + DBGLOG(RX, INFO, "%s]\n", pucMsg); + + u4PktSeqCount = 0; + kalMemZero(gau2PktSeq, sizeof(UINT_16) * PKT_STATUS_BUF_MAX_NUM); + } while (FALSE); + u4PktCnt = grPktStaRec.u4TxIndex = 0; + u4PktCnt = grPktStaRec.u4RxIndex = 0; + +} +#if CFG_SUPPORT_EMI_DEBUG +static UINT32 gPrevIdxPagedtrace; +#endif +VOID wlanDebugInit(VOID) +{ + wlanDbgLogLevelInit(); + /* debug for command/tc4 resource begin */ + gprTcReleaseTraceBuffer = + kalMemAlloc(TC_RELEASE_TRACE_BUF_MAX_NUM * sizeof(TC_RES_RELEASE_ENTRY), PHY_MEM_TYPE); + kalMemZero(gprTcReleaseTraceBuffer, TC_RELEASE_TRACE_BUF_MAX_NUM * sizeof(TC_RES_RELEASE_ENTRY)); + gprCmdTraceEntry = kalMemAlloc(TXED_CMD_TRACE_BUF_MAX_NUM * sizeof(CMD_TRACE_ENTRY), PHY_MEM_TYPE); + kalMemZero(gprCmdTraceEntry, TXED_CMD_TRACE_BUF_MAX_NUM * sizeof(CMD_TRACE_ENTRY)); + + gprCommandEntry = kalMemAlloc(TXED_COMMAND_BUF_MAX_NUM * sizeof(COMMAND_ENTRY), PHY_MEM_TYPE); + kalMemZero(gprCommandEntry, TXED_COMMAND_BUF_MAX_NUM * sizeof(COMMAND_ENTRY)); +#if CFG_SUPPORT_EMI_DEBUG + gPrevIdxPagedtrace = 0xFFFF; +#endif + /* debug for command/tc4 resource end */ + + /* debug for package info begin */ + grPktRec.pTxPkt = kalMemAlloc(PKT_INFO_BUF_MAX_NUM * sizeof(PKT_INFO_ENTRY), VIR_MEM_TYPE); + kalMemZero(grPktRec.pTxPkt, PKT_INFO_BUF_MAX_NUM * sizeof(PKT_INFO_ENTRY)); + grPktRec.u4TxIndex = 0; + grPktRec.pRxPkt = kalMemAlloc(PKT_INFO_BUF_MAX_NUM * sizeof(PKT_INFO_ENTRY), VIR_MEM_TYPE); + kalMemZero(grPktRec.pRxPkt, PKT_INFO_BUF_MAX_NUM * sizeof(PKT_INFO_ENTRY)); + grPktRec.u4RxIndex = 0; + /* debug for package info end */ + + + /*debug for scan request tx_description begin*/ + grScanHifDescRecord.pTxDescScanWriteBefore = kalMemAlloc(NIC_TX_BUFF_COUNT_TC4 * sizeof(HIF_TX_DESC_T) + , VIR_MEM_TYPE); + grScanHifDescRecord.aucFreeBufCntScanWriteBefore = 0; + grScanHifDescRecord.pTxDescScanWriteDone = kalMemAlloc(NIC_TX_BUFF_COUNT_TC4 * sizeof(HIF_TX_DESC_T) + , VIR_MEM_TYPE); + grScanHifDescRecord.aucFreeBufCntScanWriteDone = 0; + /*debug for scan request tx_description end*/ + + /*debug for scan target bss begin*/ + grScanTargetBssList.prBssTraceRecord = kalMemAlloc(SCAN_TARGET_BSS_MAX_NUM * sizeof(BSS_TRACE_RECORD) + , VIR_MEM_TYPE); + kalMemZero(grScanTargetBssList.prBssTraceRecord, SCAN_TARGET_BSS_MAX_NUM * sizeof(BSS_TRACE_RECORD)); + grScanTargetBssList.u4BSSIDCount = 0; + /*debug for scan target bss end*/ + + grPktStaRec.pTxPkt = kalMemAlloc(PKT_STATUS_BUF_MAX_NUM * sizeof(PKT_STATUS_ENTRY), VIR_MEM_TYPE); + kalMemZero(grPktStaRec.pTxPkt, PKT_STATUS_BUF_MAX_NUM * sizeof(PKT_STATUS_ENTRY)); + grPktStaRec.u4TxIndex = 0; + grPktStaRec.pRxPkt = kalMemAlloc(PKT_STATUS_BUF_MAX_NUM * sizeof(PKT_STATUS_ENTRY), VIR_MEM_TYPE); + kalMemZero(grPktStaRec.pRxPkt, PKT_STATUS_BUF_MAX_NUM * sizeof(PKT_STATUS_ENTRY)); + grPktStaRec.u4RxIndex = 0; + /* debug for package info end */ + + /*debug for rx sequence tid begin*/ + kalMemZero(gau2PktSeq, PKT_STATUS_BUF_MAX_NUM * sizeof(UINT_16)); + u4PktSeqCount = 0; + /* debug for rx sequence tid end*/ + + /*debug for command record begin*/ + gprCommandDebugInfo = kalMemAlloc(TXED_CMD_TRACE_BUF_MAX_NUM * sizeof(struct COMMAND_DEBUG_INFO) + , PHY_MEM_TYPE); + kalMemZero(gprCommandDebugInfo, TXED_CMD_TRACE_BUF_MAX_NUM * sizeof(struct COMMAND_DEBUG_INFO)); + /*debug for command record end*/ + +} + +VOID wlanDebugUninit(VOID) +{ + /* debug for command/tc4 resource begin */ + kalMemFree(gprTcReleaseTraceBuffer, PHY_MEM_TYPE, + TC_RELEASE_TRACE_BUF_MAX_NUM * sizeof(TC_RES_RELEASE_ENTRY)); + kalMemFree(gprCmdTraceEntry, PHY_MEM_TYPE, TXED_CMD_TRACE_BUF_MAX_NUM * sizeof(CMD_TRACE_ENTRY)); + kalMemFree(gprCommandEntry, PHY_MEM_TYPE, TXED_COMMAND_BUF_MAX_NUM * sizeof(COMMAND_ENTRY)); + /* debug for command/tc4 resource end */ + + /* debug for package info begin */ + kalMemFree(grPktRec.pTxPkt, VIR_MEM_TYPE, PKT_INFO_BUF_MAX_NUM * sizeof(PKT_INFO_ENTRY)); + grPktRec.u4TxIndex = 0; + kalMemFree(grPktRec.pRxPkt, VIR_MEM_TYPE, PKT_INFO_BUF_MAX_NUM * sizeof(PKT_INFO_ENTRY)); + grPktRec.u4RxIndex = 0; + /* debug for package info end */ + + + /*debug for scan request tx_description begin*/ + kalMemFree(grScanHifDescRecord.pTxDescScanWriteBefore + , VIR_MEM_TYPE, NIC_TX_BUFF_COUNT_TC4 * sizeof(HIF_TX_DESC_T)); + grScanHifDescRecord.aucFreeBufCntScanWriteBefore = 0; + kalMemFree(grScanHifDescRecord.pTxDescScanWriteDone + , VIR_MEM_TYPE, NIC_TX_BUFF_COUNT_TC4 * sizeof(HIF_TX_DESC_T)); + grScanHifDescRecord.aucFreeBufCntScanWriteDone = 0; + /*debug for scan request tx_description end*/ + + /*debug for scan target bss begin*/ + kalMemFree(grScanTargetBssList.prBssTraceRecord + , VIR_MEM_TYPE, SCAN_TARGET_BSS_MAX_NUM * sizeof(BSS_TRACE_RECORD)); + grScanTargetBssList.u4BSSIDCount = 0; + /*debug for scan target bss end*/ + + /* debug for package status info begin */ + kalMemFree(grPktStaRec.pTxPkt, VIR_MEM_TYPE, PKT_STATUS_BUF_MAX_NUM * sizeof(PKT_STATUS_ENTRY)); + grPktStaRec.u4TxIndex = 0; + kalMemFree(grPktStaRec.pRxPkt, VIR_MEM_TYPE, PKT_STATUS_BUF_MAX_NUM * sizeof(PKT_STATUS_ENTRY)); + grPktStaRec.u4RxIndex = 0; + /* debug for package status info end */ + + /*debug for rx sequence tid begin*/ + u4PktSeqCount = 0; + /* debug for rx sequence tid end*/ + + /*debug for command record begin*/ + kalMemFree(gprCommandDebugInfo, PHY_MEM_TYPE + , TXED_CMD_TRACE_BUF_MAX_NUM * sizeof(struct COMMAND_DEBUG_INFO)); + /*debug for command record end*/ + + wlanDbgLogLevelUninit(); +} +VOID wlanDebugScanTargetBSSRecord(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + P_SCAN_INFO_T prScanInfo; + P_BSS_TRACE_RECORD prBssTraceRecord; + UINT_32 i; + + ASSERT(prAdapter); + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + + if (prBssDesc == NULL) { + DBGLOG(SCN, LOUD, "Scan Desc bss is null !\n"); + return; + } + if (prConnSettings->ucSSIDLen == 0) { + DBGLOG(SCN, LOUD, "Target BSS length is 0, ignore it!\n"); + return; + } + if (prScanInfo->eCurrentState == SCAN_STATE_IDLE) { + DBGLOG(SCN, LOUD, "Ignore beacon/probeRsp, during SCAN Idle!\n"); + return; + } + + + /*dump beacon and probeRsp by connect setting SSID and ignore null bss*/ + if (EQUAL_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, + prConnSettings->aucSSID, + prConnSettings->ucSSIDLen) && (prConnSettings->ucSSIDLen > 0)) { + /*Insert BssDesc and ignore repeats*/ + + if (grScanTargetBssList.u4BSSIDCount > SCAN_TARGET_BSS_MAX_NUM) { + DBGLOG(SCN, LOUD, "u4BSSIDCount out of bound!\n"); + return; + } + + for (i = 0 ; i < grScanTargetBssList.u4BSSIDCount ; i++) { + prBssTraceRecord = &(grScanTargetBssList.prBssTraceRecord[i]); + if (EQUAL_MAC_ADDR(prBssTraceRecord->aucBSSID, prBssDesc->aucBSSID)) { + /*if exist ,update it*/ + prBssTraceRecord->ucRCPI = prBssDesc->ucRCPI; + break; + } + } + if ((i == grScanTargetBssList.u4BSSIDCount) && + (grScanTargetBssList.u4BSSIDCount < SCAN_TARGET_BSS_MAX_NUM)) { + prBssTraceRecord = &(grScanTargetBssList.prBssTraceRecord[i]); + /*add the new bssDesc recored*/ + COPY_MAC_ADDR(prBssTraceRecord->aucBSSID, prBssDesc->aucBSSID); + prBssTraceRecord->ucRCPI = prBssDesc->ucRCPI; + grScanTargetBssList.u4BSSIDCount++; + } + + } + +} + +VOID wlanDebugScanTargetBSSDump(P_ADAPTER_T prAdapter) +{ + + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_TRACE_RECORD prBssTraceRecord; + UINT_32 i; + UINT_8 aucMsg[SCAN_MSG_MAX_LEN]; + UINT_8 offset = 0; + + ASSERT(prAdapter); + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + if (prConnSettings->ucSSIDLen == 0) { + DBGLOG(SCN, LOUD, "Target BSS length is 0, ignore it!\n"); + return; + } + + if (grScanTargetBssList.u4BSSIDCount > SCAN_TARGET_BSS_MAX_NUM) { + DBGLOG(SCN, WARN, "u4BSSIDCount out of bound :%d\n", grScanTargetBssList.u4BSSIDCount); + return; + + } + + offset += kalSnprintf(aucMsg + offset, SCAN_MSG_MAX_LEN - offset + , "[%s: BSSIDNum:%d]:" + , prConnSettings->aucSSID + , grScanTargetBssList.u4BSSIDCount); + + for (i = 0 ; i < grScanTargetBssList.u4BSSIDCount ; i++) { + prBssTraceRecord = &(grScanTargetBssList.prBssTraceRecord[i]); + + DBGLOG(SCN, LOUD, "dump:[%pM],Rssi=%d\n" + , prBssTraceRecord->aucBSSID, RCPI_TO_dBm(prBssTraceRecord->ucRCPI)); + + if (i == (SCAN_TARGET_BSS_MAX_NUM/2) || + (i == grScanTargetBssList.u4BSSIDCount-1)) { + DBGLOG(SCN, INFO, "%s\n", aucMsg); + offset = 0; + kalMemZero(aucMsg, sizeof(aucMsg)); + } + + offset += kalSnprintf(aucMsg + offset, SCAN_MSG_MAX_LEN - offset + , "%pM/%d," + , prBssTraceRecord->aucBSSID + , RCPI_TO_dBm(prBssTraceRecord->ucRCPI)); + } + + grScanTargetBssList.u4BSSIDCount = 0; + kalMemZero(grScanTargetBssList.prBssTraceRecord, sizeof(BSS_TRACE_RECORD) * SCAN_TARGET_BSS_MAX_NUM); + +} + +VOID wlanDebugHifDescriptorRecord(P_ADAPTER_T prAdapter, ENUM_AMPDU_TYPE type + , ENUM_DEBUG_TRAFFIC_CLASS_INDEX_T tcIndex, PUINT_8 pucBuffer) +{ + UINT_32 i; + UINT_32 u4Offset; + UINT_32 u4StartAddr; + P_HIF_TX_DESC_T prTxDesc; + P_HIF_RX_DESC_T prRxDesc; + UINT_32 u4TcCount; + + if (pucBuffer == NULL) { + DBGLOG(TX, ERROR, "wlanDebugHifDescriptorRecord pucBuffer is Null !"); + return; + } + + + if (type == MTK_AMPDU_TX_DESC) { + + if (tcIndex == DEBUG_TC0_INDEX) { + u4TcCount = NIC_TX_INIT_BUFF_COUNT_TC0; + u4StartAddr = AP_MCU_TX_DESC_ADDR; + u4Offset = AP_MCU_BANK_OFFSET; + } else if (tcIndex == DEBUG_TC4_INDEX) { + u4TcCount = NIC_TX_BUFF_COUNT_TC4; + u4StartAddr = AP_MCU_TC_INDEX_4_ADDR; + u4Offset = AP_MCU_TC_INDEX_4_OFFSET; + } else { + DBGLOG(TX, ERROR, "Type :%d TC_INDEX :%d don't support !", type, tcIndex); + return; + } + + prTxDesc = (P_HIF_TX_DESC_T)pucBuffer; + for (i = 0; i < u4TcCount ; i++) + HAL_GET_APMCU_MEM(prAdapter, u4StartAddr, u4Offset, i, (PUINT_8) &prTxDesc[i] + , sizeof(HIF_TX_DESC_T)); + + + } else if (type == MTK_AMPDU_RX_DESC) { + + if (tcIndex == DEBUG_TC0_INDEX) { + u4TcCount = NIC_TX_INIT_BUFF_COUNT_TC0; + u4StartAddr = AP_MCU_RX_DESC_ADDR; + u4Offset = AP_MCU_BANK_OFFSET; + } else { + DBGLOG(RX, ERROR, "Type :%d TC_INDEX :%d don't support !", type, tcIndex); + return; + } + + prRxDesc = (P_HIF_RX_DESC_T)pucBuffer; + for (i = 0; i < u4TcCount ; i++) + HAL_GET_APMCU_MEM(prAdapter, u4StartAddr, u4Offset, i, (PUINT_8) &prRxDesc[i] + , sizeof(HIF_RX_DESC_T)); + } + +} + +VOID wlanDebugHifDescriptorPrint(P_ADAPTER_T prAdapter, ENUM_AMPDU_TYPE type + , ENUM_DEBUG_TRAFFIC_CLASS_INDEX_T tcIndex, PUINT_8 pucBuffer) +{ + UINT_32 i; + UINT_32 u4TcCount; + P_HIF_TX_DESC_T prTxDesc; + P_HIF_RX_DESC_T prRxDesc; + + if (pucBuffer == NULL) { + DBGLOG(TX, ERROR, "wlanDebugHifDescriptorDump pucBuffer is Null !"); + return; + } + + if (type == MTK_AMPDU_TX_DESC) { + if (tcIndex == DEBUG_TC0_INDEX) + u4TcCount = NIC_TX_INIT_BUFF_COUNT_TC0; + else if (tcIndex == DEBUG_TC4_INDEX) + u4TcCount = NIC_TX_BUFF_COUNT_TC4; + else { + DBGLOG(TX, ERROR, "Type :%d TC_INDEX :%d don't support !", type, tcIndex); + return; + } + + prTxDesc = (P_HIF_TX_DESC_T)pucBuffer; + DBGLOG(TX, INFO, "Start dump Tx_desc from APMCU\n"); + for (i = 0; i < u4TcCount ; i++) { + DBGLOG(TX, INFO + , "TC%d[%d]uOwn:%2x,CS:%2x,R1:%2x,ND:0x%08x,SA: 0x%08x,R2:%x\n" + , tcIndex, i, prTxDesc[i].ucOwn, prTxDesc[i].ucDescChksum + , prTxDesc[i].u2Rsrv1, prTxDesc[i].u4NextDesc + , prTxDesc[i].u4BufStartAddr, prTxDesc[i].u4Rsrv2); + } + + } else if (type == MTK_AMPDU_RX_DESC) { + + if (tcIndex == DEBUG_TC0_INDEX) + u4TcCount = NIC_TX_INIT_BUFF_COUNT_TC0; + else { + DBGLOG(RX, ERROR, "Type :%d TC_INDEX :%d don't support !", type, tcIndex); + return; + } + + prRxDesc = (P_HIF_RX_DESC_T)pucBuffer; + DBGLOG(RX, INFO, "Start dump rx_desc from APMCU\n"); + for (i = 0; i < u4TcCount ; i++) { + DBGLOG(RX, INFO + , "RX%d[%d]uOwn:%2x,CS:%2x,TO:%x,CSI:%x,ND:0x%08x,SA:0x%08x,len:%x,R1:%x\n" + , tcIndex, i, prRxDesc[i].ucOwn, prRxDesc[i].ucDescChksum + , prRxDesc[i].ucEtherTypeOffset, prRxDesc[i].ucChkSumInfo + , prRxDesc[i].u4NextDesc, prRxDesc[i].u4BufStartAddr + , prRxDesc[i].u2RxBufLen, prRxDesc[i].u2Rsrv1); + + } + } + +} + +VOID wlanDebugHifDescriptorDump(P_ADAPTER_T prAdapter, ENUM_AMPDU_TYPE type + , ENUM_DEBUG_TRAFFIC_CLASS_INDEX_T tcIndex) +{ + UINT_32 size = NIC_TX_BUFF_SUM; + P_HIF_TX_DESC_T prTxDesc; + P_HIF_RX_DESC_T prRxDesc; + + + if (type == MTK_AMPDU_TX_DESC) { + + prTxDesc = (P_HIF_TX_DESC_T) kalMemAlloc(sizeof(HIF_TX_DESC_T) * size, VIR_MEM_TYPE); + if (prTxDesc == NULL) { + DBGLOG(TX, WARN, "wlanDebugHifDescriptorDump prTxDesc alloc fail!\n"); + return; + } + kalMemZero(prTxDesc, sizeof(HIF_TX_DESC_T) * size); + wlanDebugHifDescriptorRecord(prAdapter, type, tcIndex, (PUINT_8)prTxDesc); + wlanDebugHifDescriptorPrint(prAdapter, type, tcIndex, (PUINT_8)prTxDesc); + kalMemFree(prTxDesc, VIR_MEM_TYPE, sizeof(HIF_TX_DESC_T)); + + } else if (type == MTK_AMPDU_RX_DESC) { + + prRxDesc = (P_HIF_RX_DESC_T) kalMemAlloc(sizeof(HIF_RX_DESC_T) * size, VIR_MEM_TYPE); + if (prRxDesc == NULL) { + DBGLOG(RX, WARN, "wlanDebugHifDescriptorDump prRxDesc alloc fail!\n"); + return; + } + kalMemZero(prRxDesc, sizeof(HIF_RX_DESC_T) * size); + wlanDebugHifDescriptorRecord(prAdapter, type, tcIndex, (PUINT_8)prRxDesc); + wlanDebugHifDescriptorPrint(prAdapter, type, tcIndex, (PUINT_8)prRxDesc); + kalMemFree(prRxDesc, VIR_MEM_TYPE, sizeof(P_HIF_RX_DESC_T)); + } +} +VOID wlanDebugScanRecord(P_ADAPTER_T prAdapter, ENUM_DBG_SCAN_T recordType) +{ + + UINT_32 tcIndex = DEBUG_TC4_INDEX; + UINT_32 type = MTK_AMPDU_TX_DESC; + P_TX_CTRL_T pTxCtrl = &prAdapter->rTxCtrl; + + if (recordType == DBG_SCAN_WRITE_BEFORE) { + wlanDebugHifDescriptorRecord(prAdapter, type, tcIndex + , (PUINT_8)grScanHifDescRecord.pTxDescScanWriteBefore); + grScanHifDescRecord.aucFreeBufCntScanWriteBefore = pTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX]; + grScanHifDescRecord.u8ScanWriteBeforeTime = sched_clock(); + } else if (recordType == DBG_SCAN_WRITE_DONE) { + wlanDebugHifDescriptorRecord(prAdapter, type, tcIndex + , (PUINT_8)grScanHifDescRecord.pTxDescScanWriteDone); + grScanHifDescRecord.aucFreeBufCntScanWriteDone = pTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX]; + grScanHifDescRecord.u8ScanWriteDoneTime = sched_clock(); + } + +} +VOID wlanDebugScanDump(P_ADAPTER_T prAdapter) +{ + UINT_32 tcIndex = DEBUG_TC4_INDEX; + UINT_32 type = MTK_AMPDU_TX_DESC; + + DBGLOG(TX, INFO, "ScanReq hal write before:Time=%llu ,freeCnt=%d,dump tc4[0]~[3] desc!\n" + , grScanHifDescRecord.u8ScanWriteBeforeTime + , grScanHifDescRecord.aucFreeBufCntScanWriteBefore); + wlanDebugHifDescriptorPrint(prAdapter, type, tcIndex + , (PUINT_8)grScanHifDescRecord.pTxDescScanWriteBefore); + + DBGLOG(TX, INFO, "ScanReq hal write done:Time=%llu ,freeCnt=%d,dump tc4[0]~[3] desc!\n" + , grScanHifDescRecord.u8ScanWriteDoneTime + , grScanHifDescRecord.aucFreeBufCntScanWriteDone); + wlanDebugHifDescriptorPrint(prAdapter, type, tcIndex + , (PUINT_8)grScanHifDescRecord.pTxDescScanWriteDone); +} + + +VOID wlanReadFwStatus(P_ADAPTER_T prAdapter) +{ + static UINT_16 u2CurEntryCmd; + P_COMMAND_ENTRY prCurCommand = &gprCommandEntry[u2CurEntryCmd]; + UINT_8 i = 0; + GL_HIF_INFO_T *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + prCurCommand->u8ReadFwTime = sched_clock(); + HAL_MCR_RD(prAdapter, MCR_D2HRM2R, &prCurCommand->u4ReadFwValue); + for (i = 0; i < READ_CPUPCR_MAX_NUM; i++) + prCurCommand->arCpupcrValue[i] = MCU_REG_READL(prHifInfo, CONN_MCU_CPUPCR); + u2CurEntryCmd++; + if (u2CurEntryCmd == TXED_COMMAND_BUF_MAX_NUM) + u2CurEntryCmd = 0; +} + + +VOID wlanTraceTxCmd(P_ADAPTER_T prAdapter, P_CMD_INFO_T prCmd) +{ + static UINT_16 u2CurEntry; + static UINT_16 u2CurEntryCmd; + P_CMD_TRACE_ENTRY prCurCmd = &gprCmdTraceEntry[u2CurEntry]; + P_COMMAND_ENTRY prCurCommand = &gprCommandEntry[u2CurEntryCmd]; + + prCurCmd->u8TxTime = sched_clock(); + prCurCommand->u8TxTime = prCurCmd->u8TxTime; + prCurCmd->eCmdType = prCmd->eCmdType; + if (prCmd->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) { + P_WLAN_MAC_MGMT_HEADER_T prMgmt = (P_WLAN_MAC_MGMT_HEADER_T)((P_MSDU_INFO_T)prCmd->prPacket)->prPacket; + + prCurCmd->u.rMgmtFrame.u2FrameCtl = prMgmt->u2FrameCtrl; + prCurCmd->u.rMgmtFrame.u2DurationID = prMgmt->u2Duration; + } else if (prCmd->eCmdType == COMMAND_TYPE_SECURITY_FRAME) { + PUINT_8 pucPkt = (PUINT_8)((struct sk_buff *)prCmd->prPacket)->data; + + prCurCmd->u.rSecFrame.u2EthType = + (pucPkt[ETH_TYPE_LEN_OFFSET] << 8) | (pucPkt[ETH_TYPE_LEN_OFFSET + 1]); + } else { + prCurCmd->u.rCmd.ucCID = prCmd->ucCID; + prCurCmd->u.rCmd.ucCmdSeqNum = prCmd->ucCmdSeqNum; + prCurCmd->u.rCmd.fgNeedResp = prCmd->fgNeedResp; + prCurCmd->u.rCmd.fgSetQuery = prCmd->fgSetQuery; + + prCurCommand->rCmd.ucCID = prCmd->ucCID; + prCurCommand->rCmd.ucCmdSeqNum = prCmd->ucCmdSeqNum; + prCurCommand->rCmd.fgNeedResp = prCmd->fgNeedResp; + prCurCommand->rCmd.fgSetQuery = prCmd->fgSetQuery; + + prCurCommand->u2Counter = u2CurEntryCmd; + u2CurEntryCmd++; + if (u2CurEntryCmd == TXED_COMMAND_BUF_MAX_NUM) + u2CurEntryCmd = 0; + HAL_MCR_RD(prAdapter, MCR_D2HRM2R, &prCurCommand->u4RelCID); + } + /*for every cmd record FW mailbox*/ + HAL_MCR_RD(prAdapter, MCR_D2HRM2R, &prCurCmd->u4RelCID); + + u2CurEntry++; + if (u2CurEntry == TC_RELEASE_TRACE_BUF_MAX_NUM) + u2CurEntry = 0; +} + +VOID wlanTraceReleaseTcRes(P_ADAPTER_T prAdapter, PUINT_8 aucTxRlsCnt, UINT_8 ucAvailable) +{ + static UINT_16 u2CurEntry; + P_TC_RES_RELEASE_ENTRY prCurBuf = &gprTcReleaseTraceBuffer[u2CurEntry]; + + HAL_MCR_RD(prAdapter, MCR_D2HRM2R, &prCurBuf->u4RelCID); + prCurBuf->u8RelaseTime = sched_clock(); + prCurBuf->ucTc4RelCnt = aucTxRlsCnt[TC4_INDEX]; + prCurBuf->ucAvailableTc4 = ucAvailable; + u2CurEntry++; + if (u2CurEntry == TXED_CMD_TRACE_BUF_MAX_NUM) + u2CurEntry = 0; +} +VOID wlanDumpTxReleaseCount(P_ADAPTER_T prAdapter) +{ + UINT_32 au4WTSR[2]; + + HAL_READ_TX_RELEASED_COUNT(prAdapter, au4WTSR); + DBGLOG(TX, INFO, "WTSR[1]=%d, WTSR[0]=%d\n", au4WTSR[1], au4WTSR[0]); +} + +VOID wlanDumpTcResAndTxedCmd(PUINT_8 pucBuf, UINT_32 maxLen) +{ + UINT_16 i = 0; + P_CMD_TRACE_ENTRY prCmd = gprCmdTraceEntry; + P_TC_RES_RELEASE_ENTRY prTcRel = gprTcReleaseTraceBuffer; + + if (pucBuf) { + int bufLen = 0; + + for (; i < TXED_CMD_TRACE_BUF_MAX_NUM/2; i++) { + bufLen = snprintf(pucBuf, maxLen, + "%2d: Time %llu, Type %d, Content %08x, RelCID:%08x; %d: Time %llu, Type %d, Content %08x, RelCID:%08x\n", + i*2, prCmd[i*2].u8TxTime, prCmd[i*2].eCmdType, *(PUINT_32)(&prCmd[i*2].u.rCmd.ucCID), + prCmd[i*2].u4RelCID, + i*2+1, prCmd[i*2+1].u8TxTime, prCmd[i*2+1].eCmdType, + *(PUINT_32)(&prCmd[i*2+1].u.rCmd.ucCID), + prCmd[i*2+1].u4RelCID); + if (bufLen <= 0 || (UINT_32)bufLen >= maxLen) + break; + pucBuf += bufLen; + maxLen -= bufLen; + } + for (i = 0; i < TC_RELEASE_TRACE_BUF_MAX_NUM/2; i++) { + bufLen = snprintf(pucBuf, maxLen, + "%2d: Time %llu, Tc4Cnt %d, Free %d, CID %08x; %2d: Time %llu, Tc4Cnt %d, Free %d CID %08x\n", + i*2, prTcRel[i*2].u8RelaseTime, prTcRel[i*2].ucTc4RelCnt, prTcRel[i*2].ucAvailableTc4, + prTcRel[i*2].u4RelCID, + i*2+1, prTcRel[i*2+1].u8RelaseTime, prTcRel[i*2+1].ucTc4RelCnt, + prTcRel[i*2+1].ucAvailableTc4, prTcRel[i*2+1].u4RelCID); + if (bufLen <= 0 || (UINT_32)bufLen >= maxLen) + break; + pucBuf += bufLen; + maxLen -= bufLen; + } + return; + } + for (; i < TXED_CMD_TRACE_BUF_MAX_NUM/4; i++) { + DBGLOG(TX, INFO, + "%2d: Time %llu, Type %d, Content %08x, RelCID:%08x; %2d: Time %llu, Type %d, Content %08x, RelCID:%08x\n", + i*2, prCmd[i*2].u8TxTime, prCmd[i*2].eCmdType, *(PUINT_32)(&prCmd[i*2].u.rCmd.ucCID), + prCmd[i*2].u4RelCID, + i*2+1, prCmd[i*2+1].u8TxTime, prCmd[i*2+1].eCmdType, + *(PUINT_32)(&prCmd[i*2+1].u.rCmd.ucCID), + prCmd[i*2+1].u4RelCID); + DBGLOG(TX, INFO, + "%2d: Time %llu, Type %d, Content %08x, RelCID:%08x; %2d: Time %llu, Type %d, Content %08x, RelCID:%08x\n", + i*4+2, prCmd[i*4+2].u8TxTime, prCmd[i*4+2].eCmdType, + *(PUINT_32)(&prCmd[i*4+2].u.rCmd.ucCID), prCmd[i*4+2].u4RelCID, + i*4+3, prCmd[i*4+3].u8TxTime, prCmd[i*4+3].eCmdType, + *(PUINT_32)(&prCmd[i*4+3].u.rCmd.ucCID), + prCmd[i*4+3].u4RelCID); + } + for (i = 0; i < TC_RELEASE_TRACE_BUF_MAX_NUM/4; i++) { + DBGLOG(TX, INFO, + "%2d: Time %llu, Tc4Cnt %d, Free %d, CID %08x; %2d: Time %llu, Tc4Cnt %d, Free %d, CID %08x;", + i*4, prTcRel[i*4].u8RelaseTime, prTcRel[i*4].ucTc4RelCnt, + prTcRel[i*4].ucAvailableTc4, prTcRel[i*4].u4RelCID, + i*4+1, prTcRel[i*4+1].u8RelaseTime, prTcRel[i*4+1].ucTc4RelCnt, + prTcRel[i*4+1].ucAvailableTc4, prTcRel[i*4+1].u4RelCID); + DBGLOG(TX, INFO, + "%2d: Time %llu, Tc4Cnt %d, Free %d, CID %08x; %2d: Time %llu, Tc4Cnt %d, Free %d, CID %08x\n", + i*4+2, prTcRel[i*4+2].u8RelaseTime, prTcRel[i*4+2].ucTc4RelCnt, + prTcRel[i*4+2].ucAvailableTc4, prTcRel[i*4+2].u4RelCID, + i*4+3, prTcRel[i*4+3].u8RelaseTime, prTcRel[i*4+3].ucTc4RelCnt, + prTcRel[i*4+3].ucAvailableTc4, prTcRel[i*4+3].u4RelCID); + } +} +VOID wlanDumpCommandFwStatus(VOID) +{ + UINT_16 i = 0; + P_COMMAND_ENTRY prCmd = gprCommandEntry; + + LOG_FUNC("Start\n"); + for (; i < TXED_COMMAND_BUF_MAX_NUM; i++) { + LOG_FUNC( + "%d: Time %llu,Content %08x,Count %x,RelCID %08x,FwValue %08x,Time %llu,CPUPCR 0x%08x 0x%08x 0x%08x\n", + i, prCmd[i].u8TxTime, *(PUINT_32)(&prCmd[i].rCmd.ucCID), + prCmd[i].u2Counter, prCmd[i].u4RelCID, + prCmd[i].u4ReadFwValue, prCmd[i].u8ReadFwTime, + prCmd[i].arCpupcrValue[0], prCmd[i].arCpupcrValue[1], prCmd[i].arCpupcrValue[2]); + } +} + +VOID wlanFWDLDebugInit(VOID) +{ + u4FWDL_packet_count = -1; + gprFWDLDebug = (P_FWDL_DEBUG_T) kalMemAlloc(sizeof(FWDL_DEBUG_T)*MAX_FW_IMAGE_PACKET_COUNT, + VIR_MEM_TYPE); + + if (gprFWDLDebug) + kalMemZero(gprFWDLDebug, sizeof(FWDL_DEBUG_T)*MAX_FW_IMAGE_PACKET_COUNT); + else + DBGLOG(INIT, ERROR, "wlanFWDLDebugInit alloc memory error\n"); +} + +VOID wlanFWDLDebugAddTxStartTime(UINT_32 u4TxStartTime) +{ + if ((gprFWDLDebug != NULL) && (u4FWDL_packet_count < MAX_FW_IMAGE_PACKET_COUNT)) + (*(gprFWDLDebug+u4FWDL_packet_count)).u4TxStartTime = u4TxStartTime; +} + +VOID wlanFWDLDebugAddTxDoneTime(UINT_32 u4TxDoneTime) +{ + if ((gprFWDLDebug != NULL) && (u4FWDL_packet_count < MAX_FW_IMAGE_PACKET_COUNT)) + (*(gprFWDLDebug+u4FWDL_packet_count)).u4TxDoneTime = u4TxDoneTime; +} + +VOID wlanFWDLDebugAddRxStartTime(UINT_32 u4RxStartTime) +{ + if ((gprFWDLDebug != NULL) && (u4FWDL_packet_count < MAX_FW_IMAGE_PACKET_COUNT)) + (*(gprFWDLDebug+u4FWDL_packet_count)).u4RxStartTime = u4RxStartTime; +} + +VOID wlanFWDLDebugAddRxDoneTime(UINT_32 u4RxDoneTime) +{ + if ((gprFWDLDebug != NULL) && (u4FWDL_packet_count < MAX_FW_IMAGE_PACKET_COUNT)) + (*(gprFWDLDebug+u4FWDL_packet_count)).u4RxDoneTime = u4RxDoneTime; +} + +VOID wlanFWDLDebugStartSectionPacketInfo(UINT_32 u4Section, UINT_32 u4DownloadSize, + UINT_32 u4ResponseTime) +{ + u4FWDL_packet_count++; + if ((gprFWDLDebug != NULL) && (u4FWDL_packet_count < MAX_FW_IMAGE_PACKET_COUNT)) { + (*(gprFWDLDebug+u4FWDL_packet_count)).u4Section = u4Section; + (*(gprFWDLDebug+u4FWDL_packet_count)).u4DownloadSize = u4DownloadSize; + (*(gprFWDLDebug+u4FWDL_packet_count)).u4ResponseTime = u4ResponseTime; + } +} + +VOID wlanFWDLDebugDumpInfo(VOID) +{ + UINT_32 i; + + for (i = 0; i <= u4FWDL_packet_count; i++) { + /* Tx:[TxStartTime][TxDoneTime] + * Pkt:[DL Pkt Section][DL Pkt Size][DL Pkt Resp Time] + */ + DBGLOG(INIT, TRACE, "wlanFWDLDumpLog > Tx:[%u][%u] Rx:[%u][%u] Pkt:[%d][%d][%u]\n" + , (*(gprFWDLDebug+i)).u4TxStartTime, (*(gprFWDLDebug+i)).u4TxDoneTime + , (*(gprFWDLDebug+i)).u4RxStartTime, (*(gprFWDLDebug+i)).u4RxDoneTime + , (*(gprFWDLDebug+i)).u4Section, (*(gprFWDLDebug+i)).u4DownloadSize + , (*(gprFWDLDebug+i)).u4ResponseTime); + } +} + +UINT_32 wlanFWDLDebugGetPktCnt(VOID) +{ + return (u4FWDL_packet_count + 1); +} + +VOID wlanFWDLDebugUninit(VOID) +{ + kalMemFree(gprFWDLDebug, VIR_MEM_TYPE, sizeof(FWDL_DEBUG_T)*MAX_FW_IMAGE_PACKET_COUNT); + gprFWDLDebug = NULL; + u4FWDL_packet_count = -1; +} +VOID wlanDumpMcuChipId(P_ADAPTER_T prAdapter) +{ + GL_HIF_INFO_T *pHifInfo; + + ASSERT(prAdapter); + + pHifInfo = &prAdapter->prGlueInfo->rHifInfo; + DBGLOG(INIT, INFO, "Offset:0x%x, Value:0x%08x ", CONN_MCU_CHIPID, MCU_REG_READL(pHifInfo, CONN_MCU_CHIPID)); +} +#if CFG_SUPPORT_EMI_DEBUG +void wlanDumpFwInforPrintBuff(PUINT8 pBuffer, UINT32 u4Len) +{ + UINT32 i = 0; + UINT32 idx = 0; + UINT8 aucOutput[WLAN_EMI_DEBUG_LINE_SIZE] = {0}; + + DBGLOG(RX, TRACE, "%s Start Print %d B!\n", __func__, u4Len); +#if 0 + dumpMemory8(pBuffer, u4Len); +#endif + for (i = 0; i < u4Len; i++) { + aucOutput[idx] = pBuffer[i]; + if (pBuffer[i] == '\n' || i == u4Len - 1) { + aucOutput[idx + 1] = '\0'; + DBGLOG(RX, INFO, "%s", aucOutput); + idx = 0; + } else + idx++; + + if (idx == WLAN_EMI_DEBUG_LINE_SIZE - 1) { + pBuffer[idx] = '\0'; + aucOutput[idx] = '\0'; + DBGLOG(RX, INFO, "%s", aucOutput); + idx = 0; + } + } +} + + +VOID wlanReadFwInfoFromEmi(IN PUINT32 pAddr) +{ + UINT32 offset = 0; + UINT32 u4Buflen = 0; + UINT32 cur_idx_pagedtrace; + PUINT8 pEmiBuf; + UINT32 i = 0; + + offset = 0; + u4Buflen = 0; + + DBGLOG(RX, TRACE, "%s Start !\n", __func__); + + if (gPrevIdxPagedtrace == 0xFFFF) { + /* FW will provide start index for the first time. */ + gPrevIdxPagedtrace = *pAddr; + DBGLOG(RX, WARN, "Invalid PreIdx, reset PreIdx to %d\n", gPrevIdxPagedtrace); + return; + } + + pEmiBuf = kalMemAlloc(WLAN_EMI_DEBUG_BUF_SIZE, VIR_MEM_TYPE); + if (pEmiBuf == NULL) { + DBGLOG(RX, WARN, "Buffer allocate fail !\n"); + return; + } + + kalMemSet(pEmiBuf, 0, WLAN_EMI_DEBUG_BUF_SIZE); + cur_idx_pagedtrace = *pAddr; + + DBGLOG(RX, TRACE, ">>Addr:0x%p CurIdx:%d,PreIdx:%d!\n", pAddr, cur_idx_pagedtrace, gPrevIdxPagedtrace); + + if (cur_idx_pagedtrace > gPrevIdxPagedtrace) { + + u4Buflen = cur_idx_pagedtrace - gPrevIdxPagedtrace; + if (u4Buflen > WLAN_EMI_DEBUG_BUF_SIZE) { + for (offset = gPrevIdxPagedtrace ; offset < cur_idx_pagedtrace + ; offset += WLAN_EMI_DEBUG_BUF_SIZE) { + kalGetFwInfoFormEmi(1, offset, (PUINT_8)pEmiBuf, WLAN_EMI_DEBUG_BUF_SIZE); + wlanDumpFwInforPrintBuff((PUINT_8)pEmiBuf, WLAN_EMI_DEBUG_BUF_SIZE); + i++; + } + u4Buflen = cur_idx_pagedtrace - (i-1)*WLAN_EMI_DEBUG_BUF_SIZE - gPrevIdxPagedtrace; + kalGetFwInfoFormEmi(1, (i-1)*WLAN_EMI_DEBUG_BUF_SIZE, (PUINT_8)pEmiBuf, u4Buflen); + wlanDumpFwInforPrintBuff((PUINT_8)pEmiBuf, u4Buflen); + } else { + kalGetFwInfoFormEmi(1, gPrevIdxPagedtrace, (PUINT_8)pEmiBuf, u4Buflen); + wlanDumpFwInforPrintBuff((PUINT_8)pEmiBuf, u4Buflen); + } + gPrevIdxPagedtrace = cur_idx_pagedtrace; + } else if (cur_idx_pagedtrace < gPrevIdxPagedtrace) { + if (gPrevIdxPagedtrace >= 0x8000) { + DBGLOG(RX, WARN, "++ prev_idx_pagedtrace invalid ...+\n"); + gPrevIdxPagedtrace = 0x8000 - 1; + kalMemFree(pEmiBuf, VIR_MEM_TYPE, WLAN_EMI_DEBUG_BUF_SIZE); + return; + } + + i = 0; + u4Buflen = 0x8000 - gPrevIdxPagedtrace - 1; + DBGLOG(RX, WARN, "-- CONNSYS paged trace ascii output (cont...) --\n"); + if (u4Buflen > WLAN_EMI_DEBUG_BUF_SIZE) { + for (offset = gPrevIdxPagedtrace ; offset < 0x8000 + ; offset += WLAN_EMI_DEBUG_BUF_SIZE) { + kalGetFwInfoFormEmi(1, offset, (PUINT_8)pEmiBuf, WLAN_EMI_DEBUG_BUF_SIZE); + wlanDumpFwInforPrintBuff((PUINT_8)pEmiBuf, WLAN_EMI_DEBUG_BUF_SIZE); + i++; + } + u4Buflen = 0x8000 - (i-1)*WLAN_EMI_DEBUG_BUF_SIZE - gPrevIdxPagedtrace-1; + kalGetFwInfoFormEmi(1, (i-1)*WLAN_EMI_DEBUG_BUF_SIZE, (PUINT_8)pEmiBuf, u4Buflen); + wlanDumpFwInforPrintBuff((PUINT_8)pEmiBuf, u4Buflen); + } else { + kalGetFwInfoFormEmi(1, gPrevIdxPagedtrace, (PUINT_8)pEmiBuf, u4Buflen); + wlanDumpFwInforPrintBuff((PUINT_8)pEmiBuf, u4Buflen); + } + + i = 0; + u4Buflen = cur_idx_pagedtrace; + DBGLOG(RX, WARN, " -- CONNSYS paged trace ascii output (end) --\n"); + if (u4Buflen > WLAN_EMI_DEBUG_BUF_SIZE) { + for (offset = 0x0 ; offset < u4Buflen ; offset += WLAN_EMI_DEBUG_BUF_SIZE) { + kalGetFwInfoFormEmi(1, offset, (PUINT_8)pEmiBuf, WLAN_EMI_DEBUG_BUF_SIZE); + wlanDumpFwInforPrintBuff((PUINT_8)pEmiBuf, WLAN_EMI_DEBUG_BUF_SIZE); + i++; + } + u4Buflen = cur_idx_pagedtrace - (i-1)*WLAN_EMI_DEBUG_BUF_SIZE; + kalGetFwInfoFormEmi(1, (i-1)*WLAN_EMI_DEBUG_BUF_SIZE, (PUINT_8)pEmiBuf, u4Buflen); + wlanDumpFwInforPrintBuff((PUINT_8)pEmiBuf, u4Buflen); + } else { + kalGetFwInfoFormEmi(1, 0x0, (PUINT_8)pEmiBuf, u4Buflen); + wlanDumpFwInforPrintBuff((PUINT_8)pEmiBuf, u4Buflen); + } + + + + gPrevIdxPagedtrace = cur_idx_pagedtrace; + } + + kalMemFree(pEmiBuf, VIR_MEM_TYPE, WLAN_EMI_DEBUG_BUF_SIZE); +} +#endif +/* Begin: Functions used to breakdown packet jitter, for test case VoE 5.7 */ +static VOID wlanSetBE32(UINT_32 u4Val, PUINT_8 pucBuf) +{ + PUINT_8 littleEn = (PUINT_8)&u4Val; + + pucBuf[0] = littleEn[3]; + pucBuf[1] = littleEn[2]; + pucBuf[2] = littleEn[1]; + pucBuf[3] = littleEn[0]; +} + +VOID wlanFillTimestamp(P_ADAPTER_T prAdapter, PVOID pvPacket, UINT_8 ucPhase) +{ + struct sk_buff *skb = (struct sk_buff *)pvPacket; + PUINT_8 pucEth = NULL; + UINT_32 u4Length = 0; + PUINT_8 pucUdp = NULL; + struct timeval tval; + + if (!prAdapter || !prAdapter->rDebugInfo.fgVoE5_7Test || !skb) + return; + pucEth = skb->data; + u4Length = skb->len; + if (u4Length < 200 || + ((pucEth[ETH_TYPE_LEN_OFFSET] << 8) | (pucEth[ETH_TYPE_LEN_OFFSET + 1])) != ETH_P_IP) + return; + if (pucEth[ETH_HLEN+9] != IP_PRO_UDP) + return; + pucUdp = &pucEth[ETH_HLEN+28]; + if (kalStrnCmp(pucUdp, "1345678", 7)) + return; + do_gettimeofday(&tval); + switch (ucPhase) { + case PHASE_XMIT_RCV: /* xmit */ + pucUdp += 20; + break; + case PHASE_ENQ_QM: /* enq */ + pucUdp += 28; + break; + case PHASE_HIF_TX: /* tx */ + pucUdp += 36; + break; + } + wlanSetBE32(tval.tv_sec, pucUdp); + wlanSetBE32(tval.tv_usec, pucUdp+4); +} +/* End: Functions used to breakdown packet jitter, for test case VoE 5.7 */ +VOID wlanDebugCommandRecodTime(P_CMD_INFO_T prCmdInfo) +{ + UINT_32 u4CurCmdIndex = 0; + struct COMMAND_DEBUG_INFO *pCommandDebugInfo = NULL; + + if (prCmdInfo == NULL) { + DBGLOG(RX, WARN, "prCmdInfo is NULL!\n"); + return; + } + /*Getting a index by using (seq mod size)*/ + u4CurCmdIndex = prCmdInfo->ucCmdSeqNum % TXED_CMD_TRACE_BUF_MAX_NUM; + pCommandDebugInfo = &(gprCommandDebugInfo[u4CurCmdIndex]); + + pCommandDebugInfo->ucCID = prCmdInfo->ucCID; + pCommandDebugInfo->ucCmdSeqNum = prCmdInfo->ucCmdSeqNum; + pCommandDebugInfo->u4InqueTime = prCmdInfo->u4InqueTime; + pCommandDebugInfo->u4SendToFwTime = prCmdInfo->u4SendToFwTime; + pCommandDebugInfo->u4FwResponseTime = prCmdInfo->u4FwResponseTime; + + DBGLOG(RX, LOUD, "(%d),CID:0x%02x,SEQ:%d,INQ[%u],SEND[%u],RSP[%u],now[%u]\n" + , u4CurCmdIndex + , pCommandDebugInfo->ucCID + , pCommandDebugInfo->ucCmdSeqNum + , pCommandDebugInfo->u4InqueTime + , pCommandDebugInfo->u4SendToFwTime + , pCommandDebugInfo->u4FwResponseTime, kalGetTimeTick()); + +} +VOID wlanDebugCommandRecodDump(VOID) +{ + UINT_16 i = 0; + UINT_8 pucMsg[CMD_BUF_MSG_LENGTH]; + UINT_32 offsetMsg = 0; + + DBGLOG(RX, INFO, "now getTimeTick:%u\n", kalGetTimeTick()); + kalMemZero(pucMsg, sizeof(UINT_8)*CMD_BUF_MSG_LENGTH); + + for (i = 0; i < TXED_CMD_TRACE_BUF_MAX_NUM; i++) { + offsetMsg += kalSnprintf(pucMsg + offsetMsg, CMD_BUF_MSG_LENGTH - offsetMsg + , "SEQ:%d,CID:0x%02x,,INQ:%u,SEND:%u,RSP:%u |" + , gprCommandDebugInfo[i].ucCmdSeqNum + , gprCommandDebugInfo[i].ucCID + , gprCommandDebugInfo[i].u4InqueTime + , gprCommandDebugInfo[i].u4SendToFwTime + , gprCommandDebugInfo[i].u4FwResponseTime); + + if (i%5 == 0 && i > 0) { + DBGLOG(RX, INFO, "%s\n", pucMsg); + kalMemZero(pucMsg, sizeof(UINT_8)*CMD_BUF_MSG_LENGTH); + offsetMsg = 0; + } + } + DBGLOG(RX, INFO, "%s\n", pucMsg); + kalMemZero(gprCommandDebugInfo, sizeof(struct COMMAND_DEBUG_INFO)*TXED_CMD_TRACE_BUF_MAX_NUM); +} + +VOID wlanDbgLogLevelInit(VOID) +{ +#if DBG + /* Adjust log level to extreme in DBG mode */ + u4DriverLogLevel = ENUM_WIFI_LOG_LEVEL_EXTREME; + u4FwLogLevel = ENUM_WIFI_LOG_LEVEL_EXTREME; +#else + u4DriverLogLevel = ENUM_WIFI_LOG_LEVEL_OFF; + u4FwLogLevel = ENUM_WIFI_LOG_LEVEL_OFF; +#endif /* DBG */ + + /* Set driver level first, and set fw log level until fw is ready */ + wlanDbgSetLogLevelImpl(NULL, ENUM_WIFI_LOG_LEVEL_VERSION_V1, + ENUM_WIFI_LOG_MODULE_DRIVER, u4DriverLogLevel); +} + +VOID wlanDbgLogLevelUninit(VOID) +{ + UINT_8 i; + + if (u4DriverLogLevel > ENUM_WIFI_LOG_LEVEL_OFF || + u4FwLogLevel > ENUM_WIFI_LOG_LEVEL_OFF) { + u4DriverLogLevel = ENUM_WIFI_LOG_LEVEL_OFF; + u4FwLogLevel = ENUM_WIFI_LOG_LEVEL_OFF; + for (i = 0; i < DBG_MODULE_NUM; i++) + aucDebugModule[i] = DBG_LOG_LEVEL_OFF; + } + +} + +UINT_32 wlanDbgLevelUiSupport(IN P_ADAPTER_T prAdapter, UINT_32 u4Version, UINT_32 ucModule) +{ + UINT_32 u4Enable = ENUM_WIFI_LOG_LEVEL_SUPPORT_DISABLE; + + switch (u4Version) { + case ENUM_WIFI_LOG_LEVEL_VERSION_V1: + switch (ucModule) { + case ENUM_WIFI_LOG_MODULE_DRIVER: + u4Enable = ENUM_WIFI_LOG_LEVEL_SUPPORT_ENABLE; + break; + case ENUM_WIFI_LOG_MODULE_FW: +#if CFG_SUPPORT_WIFI_FW_LOG_UI + u4Enable = ENUM_WIFI_LOG_LEVEL_SUPPORT_ENABLE; +#else + u4Enable = ENUM_WIFI_LOG_LEVEL_SUPPORT_DISABLE; +#endif + break; + } + break; + default: + break; + } + + return u4Enable; +} + +UINT_32 wlanDbgGetLogLevelImpl(IN P_ADAPTER_T prAdapter, UINT_32 u4Version, + UINT_32 ucModule) +{ + UINT_32 u4Level = ENUM_WIFI_LOG_LEVEL_OFF; + + switch (u4Version) { + case ENUM_WIFI_LOG_LEVEL_VERSION_V1: + switch (ucModule) { + case ENUM_WIFI_LOG_MODULE_DRIVER: + u4Level = u4DriverLogLevel; + break; + case ENUM_WIFI_LOG_MODULE_FW: + u4Level = u4FwLogLevel; + break; + default: + break; + } + break; + default: + break; + } + return u4Level; +} + +VOID wlanDbgSetLogLevelImpl(IN P_ADAPTER_T prAdapter, UINT_32 u4Version, + UINT_32 u4Module, UINT_32 u4level) +{ + do { + switch (u4Version) { + case ENUM_WIFI_LOG_LEVEL_VERSION_V1: + switch (u4Module) { + case ENUM_WIFI_LOG_MODULE_DRIVER: + { + UINT_8 i; + UINT_32 u4DriverLogMask; + + if (u4level >= ENUM_WIFI_LOG_LEVEL_NUM) + return; + + u4DriverLogLevel = u4level; + + if (u4DriverLogLevel == ENUM_WIFI_LOG_LEVEL_OFF) + u4DriverLogMask = DBG_LOG_LEVEL_OFF; + else if (u4DriverLogLevel == ENUM_WIFI_LOG_LEVEL_DEFAULT) + u4DriverLogMask = DBG_LOG_LEVEL_DEFAULT; + else + u4DriverLogMask = DBG_LOG_LEVEL_EXTREME; + + for (i = 0; i < DBG_MODULE_NUM; i++) + aucDebugModule[i] = u4DriverLogMask & DBG_CLASS_MASK; + } + break; + case ENUM_WIFI_LOG_MODULE_FW: + { + struct CMD_EVENT_LOG_LEVEL cmd; + + if (u4level >= ENUM_WIFI_LOG_LEVEL_NUM) + return; + + u4FwLogLevel = u4level; + + kalMemZero(&cmd, sizeof(struct CMD_EVENT_LOG_LEVEL)); + cmd.u4Version = u4Version; + cmd.u4LogLevel = u4FwLogLevel; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_WIFI_LOG_LEVEL, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_EVENT_LOG_LEVEL), (PUINT_8)&cmd, NULL, 0); + } + break; + default: + break; + } + break; + default: + break; + } + } while (FALSE); +#if KERNEL_VERSION(4, 14, 0) >= CFG80211_VERSION_CODE + if (u4DriverLogLevel > ENUM_WIFI_LOG_LEVEL_OFF || + u4FwLogLevel > ENUM_WIFI_LOG_LEVEL_OFF) { + DBGLOG(OID, INFO, + "Disable printk to much. driver: %d, fw: %d\n", + u4DriverLogLevel, + u4FwLogLevel); + set_logtoomuch_enable(0); + } +#endif +} + +VOID wlanDbgLevelSync(VOID) +{ + UINT_8 i = 0; + UINT_32 u4Level = ENUM_WIFI_LOG_LEVEL_EXTREME; + + do { + /* get the lowest level as module's level */ + for (i = 0; i < DBG_MODULE_NUM; i++) + u4Level &= aucDebugModule[i]; + + if (u4Level & ENUM_WIFI_LOG_LEVEL_EXTREME) + u4DriverLogLevel = ENUM_WIFI_LOG_LEVEL_EXTREME; + else if (u4Level & ENUM_WIFI_LOG_LEVEL_DEFAULT) + u4DriverLogLevel = ENUM_WIFI_LOG_LEVEL_DEFAULT; + else + u4DriverLogLevel = ENUM_WIFI_LOG_LEVEL_OFF; + + DBGLOG(OID, INFO, + "Driver log level after sync from proc: %d\n", + u4DriverLogLevel); + } while (FALSE); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/common/dump.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/common/dump.c new file mode 100644 index 0000000000000..812ccbebf29de --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/common/dump.c @@ -0,0 +1,357 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to dump a segment of memory in bytes. +* +* \param[in] pucStartAddr Pointer to the starting address of the memory to be dumped. +* \param[in] u4Length Length of the memory to be dumped. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +#define BUF_MSG_LENGTH 1024 + +VOID dumpMemory8IEOneLine(IN PUINT_8 aucBSSID, IN PUINT_8 pucStartAddr, IN UINT_32 u4Length) +{ + UINT_8 pucMsg[BUF_MSG_LENGTH]; + UINT_32 offsetMsg; + UINT_32 i; + + ASSERT(pucStartAddr); + + kalMemZero(pucMsg, BUF_MSG_LENGTH); + offsetMsg = 0; + + offsetMsg += kalSnprintf(pucMsg + offsetMsg, BUF_MSG_LENGTH - offsetMsg, "[%pM],Len:%u:[", aucBSSID, u4Length); + + if (u4Length > CFG_IE_BUFFER_SIZE) + u4Length = CFG_IE_BUFFER_SIZE; + + for (i = 0 ; i < u4Length ; i++) + offsetMsg += kalSnprintf(pucMsg + offsetMsg, BUF_MSG_LENGTH - offsetMsg, "%02x,", pucStartAddr[i]); + + offsetMsg += kalSnprintf(pucMsg + offsetMsg, BUF_MSG_LENGTH - offsetMsg, "%s", "]"); + + LOG_FUNC("%s\n", pucMsg); + +} /* end of dumpMemory8() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to dump a segment of memory in bytes. +* +* \param[in] pucStartAddr Pointer to the starting address of the memory to be dumped. +* \param[in] u4Length Length of the memory to be dumped. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID dumpMemory8(IN PUINT_8 pucStartAddr, IN UINT_32 u4Length) +{ + ASSERT(pucStartAddr); + + LOG_FUNC("DUMP8 ADDRESS: %p, Length: %u\n", pucStartAddr, u4Length); + + while (u4Length > 0) { + if (u4Length >= 16) { + LOG_FUNC( + "(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x %02x %02x %02x\n", + pucStartAddr, pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], pucStartAddr[8], + pucStartAddr[9], pucStartAddr[10], pucStartAddr[11], pucStartAddr[12], pucStartAddr[13], + pucStartAddr[14], pucStartAddr[15]); + u4Length -= 16; + pucStartAddr += 16; + } else { + switch (u4Length) { + case 1: + LOG_FUNC("(%p) %02x\n", pucStartAddr, pucStartAddr[0]); + break; + case 2: + LOG_FUNC("(%p) %02x %02x\n", pucStartAddr, pucStartAddr[0], pucStartAddr[1]); + break; + case 3: + LOG_FUNC("(%p) %02x %02x %02x\n", + pucStartAddr, pucStartAddr[0], pucStartAddr[1], pucStartAddr[2]); + break; + case 4: + LOG_FUNC("(%p) %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3]); + break; + case 5: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4]); + break; + case 6: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5]); + break; + case 7: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6]); + break; + case 8: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7]); + break; + case 9: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8]); + break; + case 10: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8], pucStartAddr[9]); + break; + case 11: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8], pucStartAddr[9], pucStartAddr[10]); + break; + case 12: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8], pucStartAddr[9], pucStartAddr[10], pucStartAddr[11]); + break; + case 13: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8], pucStartAddr[9], pucStartAddr[10], pucStartAddr[11], + pucStartAddr[12]); + break; + case 14: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x %02x\n", + pucStartAddr, pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8], pucStartAddr[9], pucStartAddr[10], pucStartAddr[11], + pucStartAddr[12], pucStartAddr[13]); + break; + case 15: + LOG_FUNC( + "(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x %02x %02x\n", + pucStartAddr, pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8], pucStartAddr[9], pucStartAddr[10], pucStartAddr[11], + pucStartAddr[12], pucStartAddr[13], pucStartAddr[14]); + break; + /* + * default: + * break; + */ + } + u4Length = 0; + } + } + + LOG_FUNC("\n"); + +} /* end of dumpMemory8() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to dump a segment of memory in double words. +* +* \param[in] pucStartAddr Pointer to the starting address of the memory to be dumped. +* \param[in] u4Length Length of the memory to be dumped. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID dumpMemory32(IN PUINT_32 pu4StartAddr, IN UINT_32 u4Length) +{ + PUINT_8 pucAddr; + + ASSERT(pu4StartAddr); + + LOG_FUNC("DUMP32 ADDRESS: %p, Length: %u\n", pu4StartAddr, u4Length); + + if (IS_NOT_ALIGN_4((ULONG) pu4StartAddr)) { + UINT_32 u4ProtrudeLen = sizeof(UINT_32) - ((ULONG) pu4StartAddr % 4); + + u4ProtrudeLen = ((u4Length < u4ProtrudeLen) ? u4Length : u4ProtrudeLen); + LOG_FUNC("pu4StartAddr is not at DW boundary.\n"); + pucAddr = (PUINT_8) &pu4StartAddr[0]; + + switch (u4ProtrudeLen) { + case 1: + LOG_FUNC("(%p) %02x------\n", pu4StartAddr, pucAddr[0]); + break; + case 2: + LOG_FUNC("(%p) %02x%02x----\n", pu4StartAddr, pucAddr[1], pucAddr[0]); + break; + case 3: + LOG_FUNC("(%p) %02x%02x%02x--\n", pu4StartAddr, pucAddr[2], pucAddr[1], pucAddr[0]); + break; + default: + break; + } + + u4Length -= u4ProtrudeLen; + pu4StartAddr = (PUINT_32) ((ULONG) pu4StartAddr + u4ProtrudeLen); + } + + while (u4Length > 0) { + if (u4Length >= 16) { + LOG_FUNC("(%p) %08x %08x %08x %08x\n", + pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2], pu4StartAddr[3]); + pu4StartAddr += 4; + u4Length -= 16; + } else { + switch (u4Length) { + case 1: + pucAddr = (PUINT_8) &pu4StartAddr[0]; + LOG_FUNC("(%p) ------%02x\n", pu4StartAddr, pucAddr[0]); + break; + case 2: + pucAddr = (PUINT_8) &pu4StartAddr[0]; + LOG_FUNC("(%p) ----%02x%02x\n", pu4StartAddr, pucAddr[1], pucAddr[0]); + break; + case 3: + pucAddr = (PUINT_8) &pu4StartAddr[0]; + LOG_FUNC("(%p) --%02x%02x%02x\n", pu4StartAddr, pucAddr[2], pucAddr[1], pucAddr[0]); + break; + case 4: + LOG_FUNC("(%p) %08x\n", pu4StartAddr, pu4StartAddr[0]); + break; + case 5: + pucAddr = (PUINT_8) &pu4StartAddr[1]; + LOG_FUNC("(%p) %08x ------%02x\n", pu4StartAddr, pu4StartAddr[0], pucAddr[0]); + break; + case 6: + pucAddr = (PUINT_8) &pu4StartAddr[1]; + LOG_FUNC("(%p) %08x ----%02x%02x\n", + pu4StartAddr, pu4StartAddr[0], pucAddr[1], pucAddr[0]); + break; + case 7: + pucAddr = (PUINT_8) &pu4StartAddr[1]; + LOG_FUNC("(%p) %08x --%02x%02x%02x\n", + pu4StartAddr, pu4StartAddr[0], pucAddr[2], pucAddr[1], pucAddr[0]); + break; + case 8: + LOG_FUNC("(%p) %08x %08x\n", pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1]); + break; + case 9: + pucAddr = (PUINT_8) &pu4StartAddr[2]; + LOG_FUNC("(%p) %08x %08x ------%02x\n", + pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1], pucAddr[0]); + break; + case 10: + pucAddr = (PUINT_8) &pu4StartAddr[2]; + LOG_FUNC("(%p) %08x %08x ----%02x%02x\n", + pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1], pucAddr[1], pucAddr[0]); + break; + case 11: + pucAddr = (PUINT_8) &pu4StartAddr[2]; + LOG_FUNC("(%p) %08x %08x --%02x%02x%02x\n", + pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], pucAddr[2], pucAddr[1], pucAddr[0]); + break; + case 12: + LOG_FUNC("(%p) %08x %08x %08x\n", + pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2]); + break; + case 13: + pucAddr = (PUINT_8) &pu4StartAddr[3]; + LOG_FUNC("(%p) %08x %08x %08x ------%02x\n", + pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2], pucAddr[0]); + break; + case 14: + pucAddr = (PUINT_8) &pu4StartAddr[3]; + LOG_FUNC("(%p) %08x %08x %08x ----%02x%02x\n", + pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2], pucAddr[1], pucAddr[0]); + break; + case 15: + pucAddr = (PUINT_8) &pu4StartAddr[3]; + LOG_FUNC("(%p) %08x %08x %08x --%02x%02x%02x\n", + pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2], + pucAddr[2], pucAddr[1], pucAddr[0]); + break; + /* + * default: + * break; + */ + } + u4Length = 0; + } + } + +} /* end of dumpMemory32() */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/common/fwcfg.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/common/fwcfg.c new file mode 100644 index 0000000000000..2b46f25b8e790 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/common/fwcfg.c @@ -0,0 +1,283 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + + +#include "fwcfg.h" + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static char *strtok_r(char *s, const char *delim, char **last); +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +struct _FW_CFG __weak fwCfgArray[] = { + +}; +/* ****************************************************************************** +* F U N C T I O N S +********************************************************************************* +*/ +INT_32 __weak getFwCfgItemNum() +{ + return ARRAY_SIZE(fwCfgArray); +} + +PUINT_8 __weak getFwCfgItemKey(UINT_8 i) +{ + if (i < ARRAY_SIZE(fwCfgArray)) + return fwCfgArray[i].key; + else + return NULL; +} + +PUINT_8 __weak getFwCfgItemValue(UINT_8 i) +{ + if (i < ARRAY_SIZE(fwCfgArray)) + return fwCfgArray[i].value; + else + return NULL; +} + +void wlanCfgFwSetParam(PUINT_8 fwBuffer, PCHAR cmdStr, PCHAR value, int num, int type) +{ + struct _CMD_FORMAT_V1_T *cmd = (struct _CMD_FORMAT_V1_T *)fwBuffer + num; + + kalMemSet(cmd, 0, sizeof(struct _CMD_FORMAT_V1_T)); + cmd->itemType = type; + + cmd->itemStringLength = strlen(cmdStr); + if (cmd->itemStringLength > MAX_CMD_NAME_MAX_LENGTH) + cmd->itemStringLength = MAX_CMD_NAME_MAX_LENGTH; + + /* here will not ensure the end will be '\0' */ + kalMemCopy(cmd->itemString, cmdStr, cmd->itemStringLength); + + cmd->itemValueLength = strlen(value); + if (cmd->itemValueLength > MAX_CMD_VALUE_MAX_LENGTH) + cmd->itemValueLength = MAX_CMD_VALUE_MAX_LENGTH; + + /* here will not ensure the end will be '\0' */ + kalMemCopy(cmd->itemValue, value, cmd->itemValueLength); +} + +WLAN_STATUS wlanCfgSetGetFw(IN P_ADAPTER_T prAdapter, const PCHAR fwBuffer, int cmdNum, enum _CMD_TYPE_T cmdType) +{ + struct _CMD_HEADER_T *pcmdV1Header = NULL; + + pcmdV1Header = (struct _CMD_HEADER_T *) kalMemAlloc(sizeof(struct _CMD_HEADER_T), VIR_MEM_TYPE); + + if (pcmdV1Header == NULL) + return WLAN_STATUS_FAILURE; + + kalMemSet(pcmdV1Header->buffer, 0, MAX_CMD_BUFFER_LENGTH); + pcmdV1Header->cmdType = cmdType; + pcmdV1Header->cmdVersion = CMD_VER_1_EXT; + pcmdV1Header->itemNum = cmdNum; + pcmdV1Header->cmdBufferLen = cmdNum * sizeof(struct _CMD_FORMAT_V1_T); + kalMemCopy(pcmdV1Header->buffer, fwBuffer, pcmdV1Header->cmdBufferLen); + + wlanSendSetQueryCmd(prAdapter, CMD_ID_GET_SET_CUSTOMER_CFG, + TRUE, FALSE, FALSE, + NULL, NULL, + sizeof(struct _CMD_HEADER_T), + (PUINT_8) pcmdV1Header, + NULL, 0); + kalMemFree(pcmdV1Header, VIR_MEM_TYPE, sizeof(struct _CMD_HEADER_T)); + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS wlanFwArrayCfg(IN P_ADAPTER_T prAdapter) +{ + int kk = 0; + PUINT_8 cmdBuffer = NULL; + int fwCfgItemNum = getFwCfgItemNum(); + + if (!fwCfgItemNum) + return WLAN_STATUS_FAILURE; + + cmdBuffer = kalMemAlloc(MAX_CMD_BUFFER_LENGTH, VIR_MEM_TYPE); + + if (cmdBuffer == 0) + return WLAN_STATUS_FAILURE; + + kalMemSet(cmdBuffer, 0, MAX_CMD_BUFFER_LENGTH); + + for (; kk < fwCfgItemNum;) { + wlanCfgFwSetParam(cmdBuffer, getFwCfgItemKey(kk), + getFwCfgItemValue(kk), (kk % MAX_CMD_ITEM_MAX), 1); + kk++; + if (kk % MAX_CMD_ITEM_MAX == 0) { + wlanCfgSetGetFw(prAdapter, cmdBuffer, MAX_CMD_ITEM_MAX, CMD_TYPE_SET); + kalMemSet(cmdBuffer, 0, MAX_CMD_BUFFER_LENGTH); + } + } + if (kk % MAX_CMD_ITEM_MAX) + wlanCfgSetGetFw(prAdapter, cmdBuffer, (kk % MAX_CMD_ITEM_MAX), CMD_TYPE_SET); + + kalMemFree(cmdBuffer, VIR_MEM_TYPE, MAX_CMD_BUFFER_LENGTH); + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS wlanFwFileCfg(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4FwCfgReadLen = 0; + PUINT_8 pucFwCfgBuf = (PUINT_8) kalMemAlloc(WLAN_CFG_FILE_BUF_SIZE, VIR_MEM_TYPE); + INT32 ret = WLAN_STATUS_FAILURE; + + if (!pucFwCfgBuf) { + DBGLOG(INIT, INFO, "omega, pucFwCfgBuf alloc fail!"); + return WLAN_STATUS_FAILURE; + } + + kalMemZero(pucFwCfgBuf, WLAN_CFG_FILE_BUF_SIZE); + + if (kalReadToFile(FW_CFG_FILE_1, pucFwCfgBuf, + WLAN_CFG_FILE_BUF_SIZE, &u4FwCfgReadLen) == 0) + DBGLOG(INIT, INFO, "read wifi_fw.cfg :%s\n", FW_CFG_FILE_1); + else if (kalReadToFile(FW_CFG_FILE_2, pucFwCfgBuf, + WLAN_CFG_FILE_BUF_SIZE, &u4FwCfgReadLen) == 0) + DBGLOG(INIT, INFO, "read wifi_fw.cfg :%s\n", FW_CFG_FILE_2); + else if (kalReadToFile(FW_CFG_FILE_3, pucFwCfgBuf, + WLAN_CFG_FILE_BUF_SIZE, &u4FwCfgReadLen) == 0) + DBGLOG(INIT, INFO, "read wifi_fw.cfg :%s\n", FW_CFG_FILE_3); + + if (pucFwCfgBuf[0] != '\0' && u4FwCfgReadLen > 0) { + /* Here limited the file length < 2048, bcz only for dbg purpose + * Meanwhile, if the file length == 2048, it MAY cause the last + * several <= 4 cmd failed + */ + if (u4FwCfgReadLen == WLAN_CFG_FILE_BUF_SIZE) + pucFwCfgBuf[WLAN_CFG_FILE_BUF_SIZE - 1] = '\0'; + + wlanFwCfgParse(prAdapter, pucFwCfgBuf); + + ret = WLAN_STATUS_SUCCESS; + } else { + DBGLOG(INIT, INFO, "read wifi_fw.cfg fail\n"); + ret = WLAN_STATUS_FAILURE; + } + + kalMemFree(pucFwCfgBuf, VIR_MEM_TYPE, WLAN_CFG_FILE_BUF_SIZE); + return ret; + +} + +WLAN_STATUS wlanFwCfgParse(IN P_ADAPTER_T prAdapter, PUINT_8 pucConfigBuf) +{ + /* here return a list should be better */ + char *saveptr1, *saveptr2; + char *cfgItems = pucConfigBuf; + UINT_8 cmdNum = 0; + + PUINT_8 cmdBuffer = kalMemAlloc(MAX_CMD_BUFFER_LENGTH, VIR_MEM_TYPE); + + if (cmdBuffer == 0) { + DBGLOG(INIT, INFO, "omega, cmd buffer return fail!"); + return WLAN_STATUS_FAILURE; + } + kalMemSet(cmdBuffer, 0, MAX_CMD_BUFFER_LENGTH); + + while (1) { + char *keyStr = NULL; + char *valueStr = NULL; + char *cfgEntry = strtok_r(cfgItems, "\n\r", &saveptr1); + + if (!cfgEntry) { + if (cmdNum) + wlanCfgSetGetFw(prAdapter, cmdBuffer, cmdNum, CMD_TYPE_SET); + + if (cmdBuffer) + kalMemFree(cmdBuffer, VIR_MEM_TYPE, MAX_CMD_BUFFER_LENGTH); + return WLAN_STATUS_SUCCESS; + } + cfgItems = NULL; + + keyStr = strtok_r(cfgEntry, " \t", &saveptr2); + valueStr = strtok_r(NULL, "\0", &saveptr2); + + /* maybe a blank line, but with some tab or whitespace */ + if (!keyStr) + continue; + + /* here take '#' at the beginning of line as comment */ + if (keyStr[0] == '#') + continue; + + /* remove the \t " " at the beginning of the valueStr */ + while (valueStr && (*valueStr == '\t' || *valueStr == ' ')) + valueStr++; + + if (keyStr && valueStr) { + wlanCfgFwSetParam(cmdBuffer, keyStr, valueStr, cmdNum, 1); + cmdNum++; + if (cmdNum == MAX_CMD_ITEM_MAX) { + wlanCfgSetGetFw(prAdapter, cmdBuffer, MAX_CMD_ITEM_MAX, CMD_TYPE_SET); + kalMemSet(cmdBuffer, 0, MAX_CMD_BUFFER_LENGTH); + cmdNum = 0; + } + } else { + /* here will not to try send the cmd has been parsed, but not sent yet */ + if (cmdBuffer) + kalMemFree(cmdBuffer, VIR_MEM_TYPE, MAX_CMD_BUFFER_LENGTH); + return WLAN_STATUS_FAILURE; + } + } +} + +/* + * This func is mainly from bionic's strtok.c + */ +static char *strtok_r(char *s, const char *delim, char **last) +{ + char *spanp; + int c, sc; + char *tok; + + + if (s == NULL) { + s = *last; + if (s == 0) + return 0; + } +cont: + c = *s++; + for (spanp = (char *)delim; (sc = *spanp++) != 0;) { + if (c == sc) + goto cont; + } + + if (c == 0) { /* no non-delimiter characters */ + *last = NULL; + return NULL; + } + tok = s - 1; + + for (;;) { + c = *s++; + spanp = (char *)delim; + do { + sc = *spanp++; + if (sc == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + *last = s; + return tok; + } + } while (sc != 0); + } +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/common/wlan_bow.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/common/wlan_bow.c new file mode 100644 index 0000000000000..cc38d1cd0dfe6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/common/wlan_bow.c @@ -0,0 +1,3152 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/****************************************************************************** +* C O M P I L E R F L A G S +******************************************************************************* +*/ + +/****************************************************************************** +* E X T E R N A L R E F E R E N C E S +******************************************************************************* +*/ +#include "precomp.h" + +#if CFG_ENABLE_BT_OVER_WIFI + +/****************************************************************************** +* C O N S T A N T S +******************************************************************************* +*/ + +/****************************************************************************** +* D A T A T Y P E S +******************************************************************************* +*/ + +/****************************************************************************** +* P U B L I C D A T A +******************************************************************************* +*/ + +static UINT_32 g_u4LinkCount; +static UINT_32 g_u4Beaconing; +static BOW_TABLE_T arBowTable[CFG_BOW_PHYSICAL_LINK_NUM]; + +/****************************************************************************** +* P R I V A T E D A T A +******************************************************************************* +*/ + +const BOW_CMD_T arBowCmdTable[] = { + {BOW_CMD_ID_GET_MAC_STATUS, bowCmdGetMacStatus}, + {BOW_CMD_ID_SETUP_CONNECTION, bowCmdSetupConnection}, + {BOW_CMD_ID_DESTROY_CONNECTION, bowCmdDestroyConnection}, + {BOW_CMD_ID_SET_PTK, bowCmdSetPTK}, + {BOW_CMD_ID_READ_RSSI, bowCmdReadRSSI}, + {BOW_CMD_ID_READ_LINK_QUALITY, bowCmdReadLinkQuality}, + {BOW_CMD_ID_SHORT_RANGE_MODE, bowCmdShortRangeMode}, + {BOW_CMD_ID_GET_CHANNEL_LIST, bowCmdGetChannelList}, +}; + +/****************************************************************************** +* M A C R O S +******************************************************************************* +*/ + +/****************************************************************************** +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************* +*/ + +/****************************************************************************** +* F U N C T I O N S +******************************************************************************* +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief command packet generation utility +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] ucCID Command ID +* \param[in] fgSetQuery Set or Query +* \param[in] fgNeedResp Need for response +* \param[in] pfCmdDoneHandler Function pointer when command is done +* \param[in] u4SetQueryInfoLen The length of the set/query buffer +* \param[in] pucInfoBuffer Pointer to set/query buffer +* +* +* \retval WLAN_STATUS_PENDING +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendSetQueryBowCmd(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucCID, + IN BOOLEAN fgSetQuery, + IN BOOLEAN fgNeedResp, + IN PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + IN PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + IN UINT_32 u4SetQueryInfoLen, IN PUINT_8 pucInfoBuffer, IN UINT_8 ucSeqNumber) +{ + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_8 ucCmdSeqNum; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + ASSERT(prGlueInfo); + + DBGLOG(REQ, TRACE, "Command ID = 0x%08X\n", ucCID); + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + u4SetQueryInfoLen)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + DBGLOG(REQ, TRACE, "ucCmdSeqNum =%d\n", ucCmdSeqNum); + + /* Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->eNetworkType = NETWORK_TYPE_BOW_INDEX; + prCmdInfo->u2InfoBufLen = (UINT_16) (CMD_HDR_SIZE + u4SetQueryInfoLen); + prCmdInfo->pfCmdDoneHandler = pfCmdDoneHandler; + prCmdInfo->pfCmdTimeoutHandler = pfCmdTimeoutHandler; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = ucCID; + prCmdInfo->fgSetQuery = fgSetQuery; + prCmdInfo->fgNeedResp = fgNeedResp; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u4SetQueryInfoLen; + prCmdInfo->pvInformationBuffer = NULL; + prCmdInfo->u4InformationBufferLength = 0; + prCmdInfo->u4PrivateData = (UINT_32) ucSeqNumber; + + /* Setup WIFI_CMD_T (no payload) */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + if (u4SetQueryInfoLen > 0 && pucInfoBuffer != NULL) + kalMemCopy(prWifiCmd->aucBuffer, pucInfoBuffer, u4SetQueryInfoLen); + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + return WLAN_STATUS_PENDING; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to dispatch command coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanbowHandleCommand(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) +{ + WLAN_STATUS retval = WLAN_STATUS_FAILURE; + UINT_16 i; + + ASSERT(prAdapter); + + for (i = 0; i < sizeof(arBowCmdTable) / sizeof(BOW_CMD_T); i++) { + if ((arBowCmdTable[i].uCmdID == prCmd->rHeader.ucCommandId) && arBowCmdTable[i].pfCmdHandle) { + retval = arBowCmdTable[i].pfCmdHandle(prAdapter, prCmd); + break; + } + } + + return retval; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is command handler for BOW_CMD_ID_GET_MAC_STATUS +* coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS bowCmdGetMacStatus(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) +{ + P_AMPC_EVENT prEvent; + P_BOW_MAC_STATUS prMacStatus; + UINT_8 idx = 0; + UINT_8 ucPrimaryChannel; + ENUM_BAND_T eBand; + ENUM_CHNL_EXT_T eBssSCO; + UINT_8 ucNumOfChannel = 0; /* MAX_BOW_NUMBER_OF_CHANNEL; */ + + RF_CHANNEL_INFO_T aucChannelList[MAX_BOW_NUMBER_OF_CHANNEL]; + + ASSERT(prAdapter); + + /* 3 <1> If LinkCount != 0 -> OK (optional) */ + + eBand = BAND_2G4; + eBssSCO = CHNL_EXT_SCN; + + /* fill event header */ + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_MAC_STATUS)), VIR_MEM_TYPE); + if (!prEvent) { + ASSERT(FALSE); + return WLAN_STATUS_FAILURE; + } + prEvent->rHeader.ucEventId = BOW_EVENT_ID_MAC_STATUS; + prEvent->rHeader.ucSeqNumber = prCmd->rHeader.ucSeqNumber; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_MAC_STATUS); + + /* fill event body */ + prMacStatus = (P_BOW_MAC_STATUS) (prEvent->aucPayload); + kalMemZero(prMacStatus, sizeof(BOW_MAC_STATUS)); + + /* 3 <2> Call CNM to decide if BOW available. */ + if (cnmBowIsPermitted(prAdapter)) + prMacStatus->ucAvailability = TRUE; + else + prMacStatus->ucAvailability = FALSE; + + memcpy(prMacStatus->aucMacAddr, prAdapter->rWifiVar.aucDeviceAddress, PARAM_MAC_ADDR_LEN); + + if (cnmPreferredChannel(prAdapter, &eBand, &ucPrimaryChannel, &eBssSCO)) { +#if CFG_BOW_TEST + DBGLOG(BOW, TRACE, "bowCmdGetMacStatus, Get preferred channel.\n"); +#endif + + prMacStatus->ucNumOfChannel = 1; + prMacStatus->arChannelList[0].ucChannelBand = eBand; + prMacStatus->arChannelList[0].ucChannelNum = ucPrimaryChannel; + } else { +#if CFG_BOW_TEST + DBGLOG(BOW, TRACE, + "bowCmdGetMacStatus, Get channel list. Current number of channel, %d.\n", ucNumOfChannel); +#endif + + rlmDomainGetChnlList(prAdapter, BAND_2G4, FALSE, MAX_BOW_NUMBER_OF_CHANNEL_2G4, + &ucNumOfChannel, aucChannelList); + + if (ucNumOfChannel > 0) { + for (idx = 0; idx < ucNumOfChannel; idx++) { + prMacStatus->arChannelList[idx].ucChannelBand = aucChannelList[idx].eBand; + prMacStatus->arChannelList[idx].ucChannelNum = aucChannelList[idx].ucChannelNum; + } + + prMacStatus->ucNumOfChannel = ucNumOfChannel; + } + + rlmDomainGetChnlList(prAdapter, BAND_5G, FALSE, MAX_BOW_NUMBER_OF_CHANNEL_5G, + &ucNumOfChannel, aucChannelList); + + if (ucNumOfChannel > 0) { + for (idx = 0; idx < ucNumOfChannel; idx++) { + prMacStatus->arChannelList[prMacStatus->ucNumOfChannel + idx].ucChannelBand = + aucChannelList[idx].eBand; + prMacStatus->arChannelList[prMacStatus->ucNumOfChannel + idx].ucChannelNum = + aucChannelList[idx].ucChannelNum; + } + + prMacStatus->ucNumOfChannel = prMacStatus->ucNumOfChannel + ucNumOfChannel; + + } + } + +#if CFG_BOW_TEST + DBGLOG(BOW, TRACE, + "ucNumOfChannel,eBand,aucChannelList,%x,%x,%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x.\n", + ucNumOfChannel, aucChannelList[0].eBand, aucChannelList[0].ucChannelNum, aucChannelList[1].ucChannelNum, + aucChannelList[2].ucChannelNum, aucChannelList[3].ucChannelNum, aucChannelList[4].ucChannelNum, + aucChannelList[5].ucChannelNum, aucChannelList[6].ucChannelNum, aucChannelList[7].ucChannelNum, + aucChannelList[8].ucChannelNum, aucChannelList[9].ucChannelNum, aucChannelList[10].ucChannelNum, + aucChannelList[11].ucChannelNum, aucChannelList[12].ucChannelNum, aucChannelList[13].ucChannelNum, + aucChannelList[14].ucChannelNum, aucChannelList[15].ucChannelNum, aucChannelList[16].ucChannelNum, + aucChannelList[17].ucChannelNum)); + + DBGLOG(BOW, TRACE, + "prMacStatus->ucNumOfChannel, eBand, %x, %x.\n", + prMacStatus->ucNumOfChannel, prMacStatus->arChannelList[0].ucChannelBand); + DBGLOG(BOW, TRACE, + "prMacStatus->arChannelList, %x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x.\n", + prMacStatus->arChannelList[0].ucChannelNum, prMacStatus->arChannelList[1].ucChannelNum, + prMacStatus->arChannelList[2].ucChannelNum, prMacStatus->arChannelList[3].ucChannelNum, + prMacStatus->arChannelList[4].ucChannelNum, prMacStatus->arChannelList[5].ucChannelNum, + prMacStatus->arChannelList[6].ucChannelNum, prMacStatus->arChannelList[7].ucChannelNum, + prMacStatus->arChannelList[8].ucChannelNum, prMacStatus->arChannelList[9].ucChannelNum, + prMacStatus->arChannelList[10].ucChannelNum, prMacStatus->arChannelList[11].ucChannelNum, + prMacStatus->arChannelList[12].ucChannelNum, prMacStatus->arChannelList[13].ucChannelNum, + prMacStatus->arChannelList[14].ucChannelNum, prMacStatus->arChannelList[15].ucChannelNum, + prMacStatus->arChannelList[16].ucChannelNum, prMacStatus->arChannelList[17].ucChannelNum)); + + DBGLOG(BOW, TRACE, "prMacStatus->ucNumOfChannel, %x.\n", prMacStatus->ucNumOfChannel); + DBGLOG(BOW, TRACE, + "prMacStatus->arChannelList[0].ucChannelBand, %x.\n", prMacStatus->arChannelList[0].ucChannelBand); + DBGLOG(BOW, TRACE, + "prMacStatus->arChannelList[0].ucChannelNum, %x.\n", prMacStatus->arChannelList[0].ucChannelNum); + DBGLOG(BOW, TRACE, "prMacStatus->ucAvailability, %x.\n", prMacStatus->ucAvailability); + DBGLOG(BOW, TRACE, "prMacStatus->aucMacAddr, %x:%x:%x:%x:%x:%x.\n", + prMacStatus->aucMacAddr[0], + prMacStatus->aucMacAddr[1], + prMacStatus->aucMacAddr[2], + prMacStatus->aucMacAddr[3], prMacStatus->aucMacAddr[4], prMacStatus->aucMacAddr[5])); +#endif + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_MAC_STATUS))); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is command handler for BOW_CMD_ID_SETUP_CONNECTION +* coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS bowCmdSetupConnection(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) +{ + P_BOW_SETUP_CONNECTION prBowSetupConnection; + CMD_BT_OVER_WIFI rCmdBtOverWifi; + P_BOW_FSM_INFO_T prBowFsmInfo; + BOW_TABLE_T rBowTable; + + UINT_8 ucBowTableIdx = 0; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowSetupConnection = (P_BOW_SETUP_CONNECTION) &(prCmd->aucPayload[0]); + + /* parameter size check */ + if (prCmd->rHeader.u2PayloadLength != sizeof(BOW_SETUP_CONNECTION)) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_INVALID); + return WLAN_STATUS_INVALID_LENGTH; + } + /* 3 <1> If ucLinkCount >= 4 -> Fail. */ + if (g_u4LinkCount >= CFG_BOW_PHYSICAL_LINK_NUM) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_NOT_ACCEPTED; + } + /* 3 <2> Call CNM, check if BOW is available. */ + if (!cnmBowIsPermitted(prAdapter)) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_NOT_ACCEPTED; + } + /* 3 <3> Lookup BOW Table, if Peer MAC address exist and valid -> Fail. */ + if (bowCheckBowTableIfVaild(prAdapter, prBowSetupConnection->aucPeerAddress)) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_NOT_ACCEPTED; + } + + if (EQUAL_MAC_ADDR(prBowSetupConnection->aucPeerAddress, prAdapter->rWifiVar.aucDeviceAddress)) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_INVALID); + return WLAN_STATUS_NOT_ACCEPTED; + } + /* fill CMD_BT_OVER_WIFI */ + rCmdBtOverWifi.ucAction = BOW_SETUP_CMD; + rCmdBtOverWifi.ucChannelNum = prBowSetupConnection->ucChannelNum; + COPY_MAC_ADDR(rCmdBtOverWifi.rPeerAddr, prBowSetupConnection->aucPeerAddress); + rCmdBtOverWifi.u2BeaconInterval = prBowSetupConnection->u2BeaconInterval; + rCmdBtOverWifi.ucTimeoutDiscovery = prBowSetupConnection->ucTimeoutDiscovery; + rCmdBtOverWifi.ucTimeoutInactivity = prBowSetupConnection->ucTimeoutInactivity; + rCmdBtOverWifi.ucRole = prBowSetupConnection->ucRole; + rCmdBtOverWifi.PAL_Capabilities = prBowSetupConnection->ucPAL_Capabilities; + rCmdBtOverWifi.cMaxTxPower = prBowSetupConnection->cMaxTxPower; + + if (prBowSetupConnection->ucChannelNum > 14) + rCmdBtOverWifi.ucChannelBand = BAND_5G; + else + rCmdBtOverWifi.ucChannelBand = BAND_2G4; + + COPY_MAC_ADDR(prBowFsmInfo->aucPeerAddress, prBowSetupConnection->aucPeerAddress); + +#if CFG_BOW_PHYSICAL_LINK_NUM > 1 + /*Channel check for supporting multiple physical link */ + if (g_u4LinkCount > 0) { + if (prBowSetupConnection->ucChannelNum != prBowFsmInfo->ucPrimaryChannel) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_NOT_ACCEPTED; + } + } +#endif + + prBowFsmInfo->ucPrimaryChannel = prBowSetupConnection->ucChannelNum; + prBowFsmInfo->eBand = rCmdBtOverWifi.ucChannelBand; + prBowFsmInfo->u2BeaconInterval = prBowSetupConnection->u2BeaconInterval; + prBowFsmInfo->ucRole = prBowSetupConnection->ucRole; + + if (prBowSetupConnection->ucPAL_Capabilities > 0) + prBowFsmInfo->fgSupportQoS = TRUE; +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowCmdSetupConnection.\n"); + DBGLOG(BOW, EVENT, "rCmdBtOverWifi Channel Number - 0x%x.\n", rCmdBtOverWifi.ucChannelNum); + DBGLOG(BOW, EVENT, "rCmdBtOverWifi Peer address - %x:%x:%x:%x:%x:%x.\n", rCmdBtOverWifi.rPeerAddr[0], + rCmdBtOverWifi.rPeerAddr[1], + rCmdBtOverWifi.rPeerAddr[2], + rCmdBtOverWifi.rPeerAddr[3], rCmdBtOverWifi.rPeerAddr[4], rCmdBtOverWifi.rPeerAddr[5]); + DBGLOG(BOW, EVENT, "rCmdBtOverWifi Beacon interval - 0x%x.\n", rCmdBtOverWifi.u2BeaconInterval); + DBGLOG(BOW, EVENT, "rCmdBtOverWifi Timeout activity - 0x%x.\n", rCmdBtOverWifi.ucTimeoutDiscovery); + DBGLOG(BOW, EVENT, "rCmdBtOverWifi Timeout inactivity - 0x%x.\n", rCmdBtOverWifi.ucTimeoutInactivity); + DBGLOG(BOW, EVENT, "rCmdBtOverWifi Role - 0x%x.\n", rCmdBtOverWifi.ucRole); + DBGLOG(BOW, EVENT, "rCmdBtOverWifi PAL capability - 0x%x.\n", rCmdBtOverWifi.PAL_Capabilities); + DBGLOG(BOW, EVENT, "rCmdBtOverWifi Max Tx power - 0x%x.\n", rCmdBtOverWifi.cMaxTxPower); +#endif + + /* 3 <4> Get a free BOW entry, mark as Valid, fill in Peer MAC address, LinkCount += 1, state == Starting. */ + if (!bowGetBowTableFreeEntry(prAdapter, &ucBowTableIdx)) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_NOT_ACCEPTED; + } + + prBowFsmInfo->prTargetBssDesc = NULL; + + kalMemZero(&rBowTable, sizeof(BOW_TABLE_T)); + + COPY_MAC_ADDR(rBowTable.aucPeerAddress, prBowSetupConnection->aucPeerAddress); + /* owTable.eState = BOW_DEVICE_STATE_ACQUIRING_CHANNEL; */ + rBowTable.fgIsValid = TRUE; + rBowTable.ucAcquireID = prBowFsmInfo->ucSeqNumOfChReq; + /* rBowTable.ucRole = prBowSetupConnection->ucRole; */ + /* rBowTable.ucChannelNum = prBowSetupConnection->ucChannelNum; */ + bowSetBowTableContent(prAdapter, ucBowTableIdx, &rBowTable); + + kalSetBowRole(prAdapter->prGlueInfo, rCmdBtOverWifi.ucRole, prBowSetupConnection->aucPeerAddress); + + GLUE_INC_REF_CNT(g_u4LinkCount); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowStarting, g_u4LinkCount, %x.\n", g_u4LinkCount); +#endif + + if (g_u4LinkCount == 1) { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowStarting, cnmTimerInitTimer.\n"); + DBGLOG(BOW, EVENT, "prBowFsmInfo->u2BeaconInterval, %d.\n", prBowFsmInfo->u2BeaconInterval); +#endif + cnmTimerInitTimer(prAdapter, + &prBowFsmInfo->rStartingBeaconTimer, + (PFN_MGMT_TIMEOUT_FUNC) bowSendBeacon, (ULONG) NULL); + + cnmTimerInitTimer(prAdapter, + &prBowFsmInfo->rChGrantedTimer, + (PFN_MGMT_TIMEOUT_FUNC) bowChGrantedTimeout, (ULONG) NULL); + + /* Reset Global Variable */ + g_u4Beaconing = 0; + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowCmdSetupConnection, g_u4LinkCount, %x.\n", g_u4LinkCount); + DBGLOG(BOW, EVENT, "kalInitBowDevice, bow0\n"); +#endif +#if CFG_BOW_SEPARATE_DATA_PATH + kalInitBowDevice(prAdapter->prGlueInfo, BOWDEVNAME); +#endif + + /*Active BoW Network */ + SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX); + SET_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX); + nicActivateNetwork(prAdapter, NETWORK_TYPE_BOW_INDEX); + + } + + if (rCmdBtOverWifi.ucRole == BOW_INITIATOR) { + bowSetBowTableState(prAdapter, prBowSetupConnection->aucPeerAddress, + BOW_DEVICE_STATE_ACQUIRING_CHANNEL); + bowRequestCh(prAdapter); + } else { + bowSetBowTableState(prAdapter, prBowSetupConnection->aucPeerAddress, BOW_DEVICE_STATE_SCANNING); + bowResponderScan(prAdapter); + } + + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_SUCCESS); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is command handler for BOW_CMD_ID_DESTROY_CONNECTION +* coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS bowCmdDestroyConnection(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) +{ + P_BOW_DESTROY_CONNECTION prBowDestroyConnection; + CMD_BT_OVER_WIFI rCmdBtOverWifi; + P_BOW_FSM_INFO_T prBowFsmInfo; +#if CFG_BOW_TEST + UINT_8 ucIdx; +#endif + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + /* 3 <1> If LinkCount == 0 ->Fail (Optional) */ + if (g_u4LinkCount == 0) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_NOT_ACCEPTED; + } + /* parameter size check */ + if (prCmd->rHeader.u2PayloadLength != sizeof(BOW_DESTROY_CONNECTION)) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_INVALID_LENGTH; + } + /* 3 <2> Lookup BOW table, check if is not exist (Valid and Peer MAC address) -> Fail */ + prBowDestroyConnection = (P_BOW_DESTROY_CONNECTION) &(prCmd->aucPayload[0]); + + if (!bowCheckBowTableIfVaild(prAdapter, prBowDestroyConnection->aucPeerAddress)) { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowCmdDestroyConnection, bowCheckIfVaild, not accepted.\n"); +#endif + return WLAN_STATUS_NOT_ACCEPTED; + } +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, + "bowCmdDestroyConnection, destroy Peer address - %x:%x:%x:%x:%x:%x.\n", + prBowDestroyConnection->aucPeerAddress[0], prBowDestroyConnection->aucPeerAddress[1], + prBowDestroyConnection->aucPeerAddress[2], prBowDestroyConnection->aucPeerAddress[3], + prBowDestroyConnection->aucPeerAddress[4], prBowDestroyConnection->aucPeerAddress[5])); +#endif + + /* fill CMD_BT_OVER_WIFI */ + rCmdBtOverWifi.ucAction = 2; + COPY_MAC_ADDR(rCmdBtOverWifi.rPeerAddr, prBowDestroyConnection->aucPeerAddress); + COPY_MAC_ADDR(prBowFsmInfo->aucPeerAddress, prBowDestroyConnection->aucPeerAddress); +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, + "bowCmdDestroyConnection, rCmdBtOverWifi.rPeerAddr - %x:%x:%x:%x:%x:%x.\n", rCmdBtOverWifi.rPeerAddr[0], + rCmdBtOverWifi.rPeerAddr[1], rCmdBtOverWifi.rPeerAddr[2], rCmdBtOverWifi.rPeerAddr[3], + rCmdBtOverWifi.rPeerAddr[4], rCmdBtOverWifi.rPeerAddr[5]); +#endif + +#if CFG_BOW_TEST + for (ucIdx = 0; ucIdx < 11; ucIdx++) { + DBGLOG(BOW, EVENT, + "BoW receiving PAL packet delta time vs packet number -- %d ms vs %x.\n", ucIdx, + g_arBowRevPalPacketTime[ucIdx]); + } +#endif + + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_SUCCESS); + + return wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, + sizeof(CMD_BT_OVER_WIFI), + (PUINT_8)&rCmdBtOverWifi, prCmd->rHeader.ucSeqNumber); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is command handler for BOW_CMD_ID_SET_PTK +* coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS bowCmdSetPTK(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) +{ + P_BOW_SET_PTK prBowSetPTK; + CMD_802_11_KEY rCmdKey; + + ASSERT(prAdapter); + + /* parameter size check */ + if (prCmd->rHeader.u2PayloadLength != sizeof(BOW_SET_PTK)) + return WLAN_STATUS_INVALID_LENGTH; + + prBowSetPTK = (P_BOW_SET_PTK) &(prCmd->aucPayload[0]); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "prBowSetPTK->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + prBowSetPTK->aucPeerAddress[0], + prBowSetPTK->aucPeerAddress[1], + prBowSetPTK->aucPeerAddress[2], + prBowSetPTK->aucPeerAddress[3], + prBowSetPTK->aucPeerAddress[4], prBowSetPTK->aucPeerAddress[5])); + + DBGLOG(BOW, EVENT, + "rCmdKey.ucIsAuthenticator, %x.\n", kalGetBowRole(prAdapter->prGlueInfo, prBowSetPTK->aucPeerAddress)); +#endif + + if (!bowCheckBowTableIfVaild(prAdapter, prBowSetPTK->aucPeerAddress)) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + + return WLAN_STATUS_NOT_ACCEPTED; + } + + if (bowGetBowTableState(prAdapter, prBowSetPTK->aucPeerAddress) != BOW_DEVICE_STATE_CONNECTED) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_FAILURE); + + return WLAN_STATUS_NOT_ACCEPTED; + } + /* fill CMD_802_11_KEY */ + rCmdKey.ucAddRemove = 1; /* add */ + rCmdKey.ucTxKey = 1; + rCmdKey.ucKeyType = 1; + rCmdKey.ucIsAuthenticator = kalGetBowRole(prAdapter->prGlueInfo, prBowSetPTK->aucPeerAddress); + COPY_MAC_ADDR(rCmdKey.aucPeerAddr, prBowSetPTK->aucPeerAddress); + rCmdKey.ucNetType = NETWORK_TYPE_BOW_INDEX; /* BT Over Wi-Fi */ + rCmdKey.ucAlgorithmId = CIPHER_SUITE_CCMP; /* AES */ + rCmdKey.ucKeyId = 0; + rCmdKey.ucKeyLen = 16; /* AES = 128bit */ + kalMemCopy(rCmdKey.aucKeyMaterial, prBowSetPTK->aucTemporalKey, 16); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "prBowSetPTK->aucTemporalKey, %x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x.\n", + prBowSetPTK->aucTemporalKey[0], + prBowSetPTK->aucTemporalKey[1], + prBowSetPTK->aucTemporalKey[2], + prBowSetPTK->aucTemporalKey[3], + prBowSetPTK->aucTemporalKey[4], + prBowSetPTK->aucTemporalKey[5], + prBowSetPTK->aucTemporalKey[6], + prBowSetPTK->aucTemporalKey[7], + prBowSetPTK->aucTemporalKey[8], + prBowSetPTK->aucTemporalKey[9], + prBowSetPTK->aucTemporalKey[10], + prBowSetPTK->aucTemporalKey[11], + prBowSetPTK->aucTemporalKey[12], + prBowSetPTK->aucTemporalKey[13], + prBowSetPTK->aucTemporalKey[14], prBowSetPTK->aucTemporalKey[15])); + + DBGLOG(BOW, EVENT, "rCmdKey.aucKeyMaterial, %x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x.\n", + rCmdKey.aucKeyMaterial[0], + rCmdKey.aucKeyMaterial[1], + rCmdKey.aucKeyMaterial[2], + rCmdKey.aucKeyMaterial[3], + rCmdKey.aucKeyMaterial[4], + rCmdKey.aucKeyMaterial[5], + rCmdKey.aucKeyMaterial[6], + rCmdKey.aucKeyMaterial[7], + rCmdKey.aucKeyMaterial[8], + rCmdKey.aucKeyMaterial[9], + rCmdKey.aucKeyMaterial[10], + rCmdKey.aucKeyMaterial[11], + rCmdKey.aucKeyMaterial[12], + rCmdKey.aucKeyMaterial[13], rCmdKey.aucKeyMaterial[14], rCmdKey.aucKeyMaterial[15])); +#endif + + return wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_ADD_REMOVE_KEY, + TRUE, + FALSE, + wlanbowCmdEventSetCommon, + wlanbowCmdTimeoutHandler, + sizeof(CMD_802_11_KEY), (PUINT_8)&rCmdKey, prCmd->rHeader.ucSeqNumber); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is command handler for BOW_CMD_ID_READ_RSSI +* coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS bowCmdReadRSSI(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) +{ + P_BOW_READ_RSSI prBowReadRSSI; + + ASSERT(prAdapter); + + /* parameter size check */ + if (prCmd->rHeader.u2PayloadLength != sizeof(BOW_READ_RSSI)) + return WLAN_STATUS_INVALID_LENGTH; + + prBowReadRSSI = (P_BOW_READ_RSSI) &(prCmd->aucPayload[0]); + + return wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + wlanbowCmdEventReadRssi, + wlanbowCmdTimeoutHandler, 0, NULL, prCmd->rHeader.ucSeqNumber); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is command handler for BOW_CMD_ID_READ_LINK_QUALITY +* coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS bowCmdReadLinkQuality(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) +{ + P_BOW_READ_LINK_QUALITY prBowReadLinkQuality; + + ASSERT(prAdapter); + + /* parameter size check */ + if (prCmd->rHeader.u2PayloadLength != sizeof(P_BOW_READ_LINK_QUALITY)) + return WLAN_STATUS_INVALID_LENGTH; + + prBowReadLinkQuality = (P_BOW_READ_LINK_QUALITY) &(prCmd->aucPayload[0]); + + return wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + wlanbowCmdEventReadLinkQuality, + wlanbowCmdTimeoutHandler, 0, NULL, prCmd->rHeader.ucSeqNumber); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is command handler for BOW_CMD_ID_SHORT_RANGE_MODE +* coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS bowCmdShortRangeMode(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) +{ + P_BOW_SHORT_RANGE_MODE prBowShortRangeMode; + CMD_TX_PWR_T rTxPwrParam; + + ASSERT(prAdapter); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowCmdShortRangeMode.\n"); +#endif + + prBowShortRangeMode = (P_BOW_SHORT_RANGE_MODE) &(prCmd->aucPayload[0]); + + /* parameter size check */ + if (prCmd->rHeader.u2PayloadLength != sizeof(BOW_SHORT_RANGE_MODE)) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_INVALID_LENGTH; + } + + if (!bowCheckBowTableIfVaild(prAdapter, prBowShortRangeMode->aucPeerAddress)) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_NOT_ACCEPTED; + } + + if (bowGetBowTableState(prAdapter, prBowShortRangeMode->aucPeerAddress) != BOW_DEVICE_STATE_CONNECTED) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_FAILURE); + return WLAN_STATUS_NOT_ACCEPTED; + } +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "prBowShortRangeMode->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + prBowShortRangeMode->aucPeerAddress[0], + prBowShortRangeMode->aucPeerAddress[1], + prBowShortRangeMode->aucPeerAddress[2], + prBowShortRangeMode->aucPeerAddress[3], + prBowShortRangeMode->aucPeerAddress[4], prBowShortRangeMode->aucPeerAddress[5])); +#endif + + rTxPwrParam.cTxPwr2G4Cck = (prBowShortRangeMode->cTxPower << 1); + + rTxPwrParam.cTxPwr2G4OFDM_BPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4OFDM_QPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4OFDM_16QAM = (prBowShortRangeMode->cTxPower << 1); + + rTxPwrParam.cTxPwr2G4OFDM_48Mbps = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4OFDM_54Mbps = (prBowShortRangeMode->cTxPower << 1); + + rTxPwrParam.cTxPwr2G4HT20_BPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT20_QPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT20_16QAM = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT20_MCS5 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT20_MCS6 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT20_MCS7 = (prBowShortRangeMode->cTxPower << 1); + + rTxPwrParam.cTxPwr2G4HT40_BPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT40_QPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT40_16QAM = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT40_MCS5 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT40_MCS6 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT40_MCS7 = (prBowShortRangeMode->cTxPower << 1); + + rTxPwrParam.cTxPwr5GOFDM_BPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GOFDM_QPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GOFDM_16QAM = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GOFDM_48Mbps = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GOFDM_54Mbps = (prBowShortRangeMode->cTxPower << 1); + + rTxPwrParam.cTxPwr5GHT20_BPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT20_QPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT20_16QAM = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT20_MCS5 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT20_MCS6 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT20_MCS7 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT40_BPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT40_QPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT40_16QAM = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT40_MCS5 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT40_MCS6 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT40_MCS7 = (prBowShortRangeMode->cTxPower << 1); + + if (nicUpdateTxPower(prAdapter, &rTxPwrParam) == WLAN_STATUS_SUCCESS) { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowCmdShortRangeMode, %x.\n", WLAN_STATUS_SUCCESS); +#endif + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_SUCCESS); + return WLAN_STATUS_SUCCESS; + } + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_FAILURE); + return WLAN_STATUS_FAILURE; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is command handler for BOW_CMD_ID_GET_CHANNEL_LIST +* coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS bowCmdGetChannelList(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) +{ + ASSERT(prAdapter); + + /* not supported yet */ + return WLAN_STATUS_FAILURE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is generic command done handler +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanbowCmdEventSetStatus(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd, IN UINT_8 ucEventBuf) +{ + P_AMPC_EVENT prEvent; + P_BOW_COMMAND_STATUS prBowCmdStatus; + + ASSERT(prAdapter); + + /* fill event header */ + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS)), VIR_MEM_TYPE); + if (!prEvent) { + ASSERT(FALSE); + return; + } + prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; + prEvent->rHeader.ucSeqNumber = prCmd->rHeader.ucSeqNumber; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_COMMAND_STATUS); + + /* fill event body */ + prBowCmdStatus = (P_BOW_COMMAND_STATUS) (prEvent->aucPayload); + kalMemZero(prBowCmdStatus, sizeof(BOW_COMMAND_STATUS)); + + prBowCmdStatus->ucStatus = ucEventBuf; + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS))); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is generic command done handler +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanbowCmdEventSetCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_AMPC_EVENT prEvent; + P_BOW_COMMAND_STATUS prBowCmdStatus; + + ASSERT(prAdapter); + + /* fill event header */ + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS)), VIR_MEM_TYPE); + if (!prEvent) { + ASSERT(FALSE); + return; + } + prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_COMMAND_STATUS); + + /* fill event body */ + prBowCmdStatus = (P_BOW_COMMAND_STATUS) (prEvent->aucPayload); + kalMemZero(prBowCmdStatus, sizeof(BOW_COMMAND_STATUS)); + + prBowCmdStatus->ucStatus = BOWCMD_STATUS_SUCCESS; + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS))); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief command done handler for CMD_ID_CMD_BT_OVER_WIFI +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanbowCmdEventLinkConnected(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_AMPC_EVENT prEvent; + P_BOW_LINK_CONNECTED prBowLinkConnected; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + + /* fill event header */ + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_LINK_CONNECTED)), VIR_MEM_TYPE); + if (!prEvent) { + ASSERT(FALSE); + return; + } + prEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_CONNECTED; + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_LINK_CONNECTED); + + /* fill event body */ + prBowLinkConnected = (P_BOW_LINK_CONNECTED) (prEvent->aucPayload); + kalMemZero(prBowLinkConnected, sizeof(BOW_LINK_CONNECTED)); + prBowLinkConnected->rChannel.ucChannelNum = prBssInfo->ucPrimaryChannel; + prBowLinkConnected->rChannel.ucChannelBand = prBssInfo->eBand; + COPY_MAC_ADDR(prBowLinkConnected->aucPeerAddress, prBowFsmInfo->aucPeerAddress); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "prEvent->rHeader.ucEventId, 0x%x\n", prEvent->rHeader.ucEventId); + DBGLOG(BOW, EVENT, "prEvent->rHeader.ucSeqNumber, 0x%x\n", prEvent->rHeader.ucSeqNumber); + DBGLOG(BOW, EVENT, "prEvent->rHeader.u2PayloadLength, 0x%x\n", prEvent->rHeader.u2PayloadLength); + DBGLOG(BOW, EVENT, + "prBowLinkConnected->rChannel.ucChannelNum, 0x%x\n", prBowLinkConnected->rChannel.ucChannelNum); + DBGLOG(BOW, EVENT, + "prBowLinkConnected->rChannel.ucChannelBand, 0x%x\n", prBowLinkConnected->rChannel.ucChannelBand); + DBGLOG(BOW, EVENT, + "wlanbowCmdEventLinkConnected, prBowFsmInfo->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + prBowFsmInfo->aucPeerAddress[0], prBowFsmInfo->aucPeerAddress[1], prBowFsmInfo->aucPeerAddress[2], + prBowFsmInfo->aucPeerAddress[3], prBowFsmInfo->aucPeerAddress[4], prBowFsmInfo->aucPeerAddress[5]); + DBGLOG(BOW, EVENT, + "wlanbowCmdEventLinkConnected, prBowLinkConnected->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + prBowLinkConnected->aucPeerAddress[0], prBowLinkConnected->aucPeerAddress[1], + prBowLinkConnected->aucPeerAddress[2], prBowLinkConnected->aucPeerAddress[3], + prBowLinkConnected->aucPeerAddress[4], prBowLinkConnected->aucPeerAddress[5])); + DBGLOG(BOW, EVENT, "wlanbowCmdEventLinkConnected, g_u4LinkCount, %x.\n", g_u4LinkCount); +#endif + + /*Indicate Event to PAL */ + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_CONNECTED))); + + /*Release channel if granted */ + if (prBowFsmInfo->fgIsChannelGranted) { + cnmTimerStopTimer(prAdapter, &prBowFsmInfo->rChGrantedTimer); + /* bowReleaseCh(prAdapter); */ + /*Requested, not granted yet */ + } else if (prBowFsmInfo->fgIsChannelRequested) { + prBowFsmInfo->fgIsChannelRequested = FALSE; + } + + /* set to connected status */ + bowSetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress, BOW_DEVICE_STATE_CONNECTED); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief command done handler for CMD_ID_CMD_BT_OVER_WIFI +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanbowCmdEventLinkDisconnected(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_AMPC_EVENT prEvent; + P_BOW_LINK_DISCONNECTED prBowLinkDisconnected; + P_BOW_FSM_INFO_T prBowFsmInfo; + BOW_TABLE_T rBowTable; + UINT_8 ucBowTableIdx; + ENUM_BOW_DEVICE_STATE eFsmState; + BOOLEAN fgSendDeauth = FALSE; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + eFsmState = bowGetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress); + + if (eFsmState == BOW_DEVICE_STATE_DISCONNECTED) { + /*do nothing */ + return; + } + /*Cancel scan */ + else if (eFsmState == BOW_DEVICE_STATE_SCANNING && !(prBowFsmInfo->fgIsChannelRequested)) { + bowResponderCancelScan(prAdapter, FALSE); + bowSetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress, BOW_DEVICE_STATE_DISCONNECTING); + return; + } + /* fill event header */ + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_LINK_DISCONNECTED)), VIR_MEM_TYPE); + if (!prEvent) { + ASSERT(FALSE); + return; + } + prEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_DISCONNECTED; + if ((prCmdInfo->u4PrivateData)) + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + else + prEvent->rHeader.ucSeqNumber = 0; + + prEvent->rHeader.u2PayloadLength = sizeof(BOW_LINK_DISCONNECTED); + + /* fill event body */ + prBowLinkDisconnected = (P_BOW_LINK_DISCONNECTED) (prEvent->aucPayload); + kalMemZero(prBowLinkDisconnected, sizeof(BOW_LINK_DISCONNECTED)); + prBowLinkDisconnected->ucReason = 0x0; + COPY_MAC_ADDR(prBowLinkDisconnected->aucPeerAddress, prBowFsmInfo->aucPeerAddress); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "prEvent->rHeader.ucEventId, 0x%x\n", prEvent->rHeader.ucEventId); + DBGLOG(BOW, EVENT, "prEvent->rHeader.ucSeqNumber, 0x%x\n", prEvent->rHeader.ucSeqNumber); + DBGLOG(BOW, EVENT, "prEvent->rHeader.u2PayloadLength, 0x%x\n", prEvent->rHeader.u2PayloadLength); + + DBGLOG(BOW, EVENT, "wlanbowCmdEventLinkDisconnected, prBowFsmInfo->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + prBowFsmInfo->aucPeerAddress[0], + prBowFsmInfo->aucPeerAddress[1], + prBowFsmInfo->aucPeerAddress[2], + prBowFsmInfo->aucPeerAddress[3], + prBowFsmInfo->aucPeerAddress[4], prBowFsmInfo->aucPeerAddress[5])); + + DBGLOG(BOW, EVENT, + "wlanbowCmdEventLinkDisconnected, prBowLinkDisconnected->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + prBowLinkDisconnected->aucPeerAddress[0], prBowLinkDisconnected->aucPeerAddress[1], + prBowLinkDisconnected->aucPeerAddress[2], prBowLinkDisconnected->aucPeerAddress[3], + prBowLinkDisconnected->aucPeerAddress[4], prBowLinkDisconnected->aucPeerAddress[5])); + + DBGLOG(BOW, EVENT, "wlanbowCmdEventLinkDisconnected, g_u4LinkCount, %x.\n", g_u4LinkCount); +#endif + + /*Indicate BoW event to PAL */ +#if 0 + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_DISCONNECTED))); +#endif + + /* set to disconnected status */ + prBowFsmInfo->prTargetStaRec = + cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_BOW_INDEX, prBowLinkDisconnected->aucPeerAddress); + if (!(prBowFsmInfo->prTargetStaRec)) { + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_DISCONNECTED))); + ASSERT(FALSE); + return; + } + + /*Release channel if granted */ + if (prBowFsmInfo->fgIsChannelGranted) { + cnmTimerStopTimer(prAdapter, &prBowFsmInfo->rChGrantedTimer); + bowReleaseCh(prAdapter); + /*Requested, not granted yet */ + } else if (prBowFsmInfo->fgIsChannelRequested) { + prBowFsmInfo->fgIsChannelRequested = FALSE; + /* bowReleaseCh(prAdapter); */ + } +#if 1 + /*Send Deauth to connected peer */ + if (eFsmState == BOW_DEVICE_STATE_CONNECTED && (prBowFsmInfo->prTargetStaRec->ucStaState == STA_STATE_3)) { + fgSendDeauth = TRUE; +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, + "wlanbowCmdEventLinkDisconnected, bowGetBowTableState, %x.\n", + bowGetBowTableState(prAdapter, prBowLinkDisconnected->aucPeerAddress)); +#endif + authSendDeauthFrame(prAdapter, + prBowFsmInfo->prTargetStaRec, + (P_SW_RFB_T) NULL, + REASON_CODE_DEAUTH_LEAVING_BSS, (PFN_TX_DONE_HANDLER) bowDisconnectLink); + } +#endif + +#if 0 + /* 3 <3>Stop this link; flush Tx; + * send deAuthentication -> abort. SAA, AAA. need to check BOW table state == Connected. + */ + if (prAdapter->prGlueInfo->i4TxPendingFrameNum > 0) + kalFlushPendingTxPackets(prAdapter->prGlueInfo); + + /* flush pending security frames */ + if (prAdapter->prGlueInfo->i4TxPendingSecurityFrameNum > 0) + kalClearSecurityFrames(prAdapter->prGlueInfo); +#endif + + /*Update BoW table */ + bowGetBowTableEntryByPeerAddress(prAdapter, prBowLinkDisconnected->aucPeerAddress, &ucBowTableIdx); + rBowTable.fgIsValid = FALSE; + rBowTable.eState = BOW_DEVICE_STATE_DISCONNECTED; + rBowTable.ucAcquireID = prBowFsmInfo->ucSeqNumOfChReq; + kalMemZero(rBowTable.aucPeerAddress, sizeof(rBowTable.aucPeerAddress)); + bowSetBowTableContent(prAdapter, ucBowTableIdx, &rBowTable); + + /*Indicate BoW event to PAL */ + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_DISCONNECTED))); + + /*Decrease link count */ + GLUE_DEC_REF_CNT(g_u4LinkCount); + + /*If no need to send deauth, DO disconnect now */ + /*If need to send deauth, DO disconnect at deauth Tx done */ + if (!fgSendDeauth) + bowDisconnectLink(prAdapter, NULL, TX_RESULT_SUCCESS); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief command done handler for CMD_ID_CMD_BT_OVER_WIFI +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanbowCmdEventSetSetupConnection(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_AMPC_EVENT prEvent; + P_BOW_COMMAND_STATUS prBowCmdStatus; + P_WIFI_CMD_T prWifiCmd; + P_CMD_BT_OVER_WIFI prCmdBtOverWifi; + P_BOW_FSM_INFO_T prBowFsmInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + /* restore original command for rPeerAddr */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prCmdBtOverWifi = (P_CMD_BT_OVER_WIFI) (prWifiCmd->aucBuffer); + + /* fill event header */ + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS)), VIR_MEM_TYPE); + if (!prEvent) { + ASSERT(FALSE); + return; + } + prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_COMMAND_STATUS); + + /* fill event body */ + prBowCmdStatus = (P_BOW_COMMAND_STATUS) (prEvent->aucPayload); + kalMemZero(prBowCmdStatus, sizeof(BOW_COMMAND_STATUS)); + prBowCmdStatus->ucStatus = BOWCMD_STATUS_SUCCESS; + + /*Indicate BoW event to PAL */ + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS))); + + /* set to starting status */ + kalSetBowState(prAdapter->prGlueInfo, BOW_DEVICE_STATE_STARTING, prCmdBtOverWifi->rPeerAddr); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is the command done handler for BOW_CMD_ID_READ_LINK_QUALITY +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanbowCmdEventReadLinkQuality(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_LINK_QUALITY prLinkQuality; + P_AMPC_EVENT prEvent; + P_BOW_LINK_QUALITY prBowLinkQuality; + + ASSERT(prAdapter); + + prLinkQuality = (P_EVENT_LINK_QUALITY) pucEventBuf; + + /* fill event header */ + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_LINK_QUALITY)), VIR_MEM_TYPE); + if (!prEvent) { + ASSERT(FALSE); + return; + } + prEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_QUALITY; + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_LINK_QUALITY); + + /* fill event body */ + prBowLinkQuality = (P_BOW_LINK_QUALITY) (prEvent->aucPayload); + kalMemZero(prBowLinkQuality, sizeof(BOW_LINK_QUALITY)); + prBowLinkQuality->ucLinkQuality = (UINT_8) prLinkQuality->cLinkQuality; + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_QUALITY))); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is the command done handler for BOW_CMD_ID_READ_RSSI +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanbowCmdEventReadRssi(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_LINK_QUALITY prLinkQuality; + P_AMPC_EVENT prEvent; + P_BOW_RSSI prBowRssi; + + ASSERT(prAdapter); + + prLinkQuality = (P_EVENT_LINK_QUALITY) pucEventBuf; + + /* fill event header */ + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_LINK_QUALITY)), VIR_MEM_TYPE); + if (!prEvent) { + ASSERT(FALSE); + return; + } + prEvent->rHeader.ucEventId = BOW_EVENT_ID_RSSI; + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_RSSI); + + /* fill event body */ + prBowRssi = (P_BOW_RSSI) (prEvent->aucPayload); + kalMemZero(prBowRssi, sizeof(BOW_RSSI)); + prBowRssi->cRssi = (INT_8) prLinkQuality->cRssi; + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_QUALITY))); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is the default command timeout handler +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanbowCmdTimeoutHandler(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + P_AMPC_EVENT prEvent; + P_BOW_COMMAND_STATUS prBowCmdStatus; + + ASSERT(prAdapter); + + /* fill event header */ + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS)), VIR_MEM_TYPE); + if (!prEvent) { + ASSERT(FALSE); + return; + } + prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_COMMAND_STATUS); + + /* fill event body */ + prBowCmdStatus = (P_BOW_COMMAND_STATUS) (prEvent->aucPayload); + kalMemZero(prBowCmdStatus, sizeof(BOW_COMMAND_STATUS)); + + prBowCmdStatus->ucStatus = BOWCMD_STATUS_TIMEOUT; /* timeout */ + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS))); + +} + +VOID bowStopping(IN P_ADAPTER_T prAdapter) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + P_BSS_INFO_T prBowBssInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowStoping.\n"); + DBGLOG(BOW, EVENT, "bowStoping, SSID %s.\n", prBowBssInfo->aucSSID); + DBGLOG(BOW, EVENT, "bowStoping, prBowBssInfo->aucBSSID, %x:%x:%x:%x:%x:%x.\n", + prBowBssInfo->aucBSSID[0], + prBowBssInfo->aucBSSID[1], + prBowBssInfo->aucBSSID[2], + prBowBssInfo->aucBSSID[3], prBowBssInfo->aucBSSID[4], prBowBssInfo->aucBSSID[5])); + DBGLOG(BOW, EVENT, "bowStoping, prBssInfo->aucOwnMacAddr, %x:%x:%x:%x:%x:%x.\n", + prBowBssInfo->aucOwnMacAddr[0], + prBowBssInfo->aucOwnMacAddr[1], + prBowBssInfo->aucOwnMacAddr[2], + prBowBssInfo->aucOwnMacAddr[3], + prBowBssInfo->aucOwnMacAddr[4], prBowBssInfo->aucOwnMacAddr[5])); + DBGLOG(BOW, EVENT, "bowStoping, prAdapter->rWifiVar.aucDeviceAddress, %x:%x:%x:%x:%x:%x.\n", + prAdapter->rWifiVar.aucDeviceAddress[0], + prAdapter->rWifiVar.aucDeviceAddress[1], + prAdapter->rWifiVar.aucDeviceAddress[2], + prAdapter->rWifiVar.aucDeviceAddress[3], + prAdapter->rWifiVar.aucDeviceAddress[4], prAdapter->rWifiVar.aucDeviceAddress[5])); + DBGLOG(BOW, EVENT, "bowStopping, g_u4LinkCount, %x.\n", g_u4LinkCount); + DBGLOG(BOW, EVENT, "prBowFsmInfo->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", prBowFsmInfo->aucPeerAddress[0], + prBowFsmInfo->aucPeerAddress[1], + prBowFsmInfo->aucPeerAddress[2], + prBowFsmInfo->aucPeerAddress[3], + prBowFsmInfo->aucPeerAddress[4], prBowFsmInfo->aucPeerAddress[5])); + kalPrint("BoW Stoping,[%d,%d]\n", g_u4LinkCount, g_u4Beaconing); +#endif + + if (g_u4LinkCount == 0) { + /*Stop beaconing */ + GLUE_DEC_REF_CNT(g_u4Beaconing); + + /*Deactive BoW network */ + /* prBowBssInfo->fgIsNetActive = FALSE; */ + /* prBowBssInfo->fgIsBeaconActivated = FALSE; */ + nicPmIndicateBssAbort(prAdapter, NETWORK_TYPE_BOW_INDEX); + bowChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + nicUpdateBss(prAdapter, NETWORK_TYPE_BOW_INDEX); + /*temp solution for FW hal_pwr_mgt.c#3037 ASSERT */ + nicDeactivateNetwork(prAdapter, NETWORK_TYPE_BOW_INDEX); + SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_BOW_INDEX); + UNSET_NET_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX); + + } + +} + +VOID bowStarting(IN P_ADAPTER_T prAdapter) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if (g_u4LinkCount == 1) { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "BoW Starting.\n"); + DBGLOG(BOW, EVENT, "BoW channel granted.\n"); +#endif + +#if 0 + /*Active BoW Network */ + SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX); + SET_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX); + nicActivateNetwork(prAdapter, NETWORK_TYPE_BOW_INDEX); +#endif + + /* 3 <1> Update BSS_INFO_T per Network Basis */ + /* 4 <1.1> Setup Operation Mode */ + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + prBssInfo->ucNetTypeIndex = NETWORK_TYPE_BOW_INDEX; + prBssInfo->eCurrentOPMode = OP_MODE_BOW; + + /* 4 <1.2> Setup SSID */ + COPY_MAC_ADDR(prBssInfo->aucOwnMacAddr, prAdapter->rWifiVar.aucDeviceAddress); + COPY_MAC_ADDR(prBssInfo->aucBSSID, prAdapter->rWifiVar.aucDeviceAddress); + prBssInfo->ucSSIDLen = BOW_SSID_LEN; + bowAssignSsid(prBssInfo->aucSSID, prBssInfo->aucOwnMacAddr); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "SSID %s.\n", prBssInfo->aucSSID); + DBGLOG(BOW, EVENT, "prBssInfo->aucBSSID, %x:%x:%x:%x:%x:%x.\n", + prBssInfo->aucBSSID[0], + prBssInfo->aucBSSID[1], + prBssInfo->aucBSSID[2], + prBssInfo->aucBSSID[3], prBssInfo->aucBSSID[4], prBssInfo->aucBSSID[5])); + DBGLOG(BOW, EVENT, "prBssInfo->aucOwnMacAddr, %x:%x:%x:%x:%x:%x.\n", + prBssInfo->aucOwnMacAddr[0], + prBssInfo->aucOwnMacAddr[1], + prBssInfo->aucOwnMacAddr[2], + prBssInfo->aucOwnMacAddr[3], + prBssInfo->aucOwnMacAddr[4], prBssInfo->aucOwnMacAddr[5])); + DBGLOG(BOW, EVENT, "prAdapter->rWifiVar.aucDeviceAddress, %x:%x:%x:%x:%x:%x.\n", + prAdapter->rWifiVar.aucDeviceAddress[0], + prAdapter->rWifiVar.aucDeviceAddress[1], + prAdapter->rWifiVar.aucDeviceAddress[2], + prAdapter->rWifiVar.aucDeviceAddress[3], + prAdapter->rWifiVar.aucDeviceAddress[4], prAdapter->rWifiVar.aucDeviceAddress[5])); +#endif + + /* 4 <1.3> Clear current AP's STA_RECORD_T and current AID */ + prBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; + prBssInfo->u2AssocId = 0; + + /* 4 <1.4> Setup Channel, Band and Phy Attributes */ + prBssInfo->ucPrimaryChannel = prBowFsmInfo->ucPrimaryChannel; + if (prBowFsmInfo->eBand == BAND_2G4) + prBssInfo->eBand = BAND_2G4; + else + prBssInfo->eBand = BAND_5G; + +#if CFG_BOW_SUPPORT_11N + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11BGN; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; + + prBssInfo->ucNonHTBasicPhyType = (UINT_8) + rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].ePhyTypeIndex; + prBssInfo->u2BSSBasicRateSet = rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].u2BSSBasicRateSet; + + prBssInfo->u2OperationalRateSet = + rNonHTPhyAttributes[prBssInfo->ucNonHTBasicPhyType].u2SupportedRateSet; + + rateGetDataRatesFromRateSet(prBssInfo->u2OperationalRateSet, + prBssInfo->u2BSSBasicRateSet, + prBssInfo->aucAllSupportedRates, &prBssInfo->ucAllSupportedRatesLen); + +#else + if (prBssInfo->eBand == BAND_2G4) { + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11BG; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; + + /* RATE_SET_ERP; */ + prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_ERP; + prBssInfo->u2OperationalRateSet = RATE_SET_ERP; + prBssInfo->ucNonHTBasicPhyType = PHY_TYPE_ERP_INDEX; + } else { + /* Depend on eBand */ + /* prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11BG; */ + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + /* prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; */ + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11A; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_11A; + + /* RATE_SET_ERP; */ + /* prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_ERP; */ + /* prBssInfo->u2OperationalRateSet = RATE_SET_ERP; */ + + /* RATE_SET_ERP; */ + prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_OFDM; + prBssInfo->u2OperationalRateSet = RATE_SET_OFDM; + prBssInfo->ucNonHTBasicPhyType = PHY_TYPE_OFDM_INDEX; + } + +#endif + prBssInfo->fgErpProtectMode = FALSE; + + /* 4 <1.5> Setup MIB for current BSS */ + prBssInfo->u2BeaconInterval = prBowFsmInfo->u2BeaconInterval; + prBssInfo->ucDTIMPeriod = DOT11_DTIM_PERIOD_DEFAULT; + prBssInfo->u2ATIMWindow = 0; + prBssInfo->ucBeaconTimeoutCount = 0; + if (prBowFsmInfo->fgSupportQoS) { + prAdapter->rWifiVar.fgSupportQoS = TRUE; + prBssInfo->fgIsQBSS = TRUE; + } + /* 3 <2> Update BSS_INFO_T common part */ +#if CFG_SUPPORT_AAA + bssInitForAP(prAdapter, prBssInfo, TRUE); + nicQmUpdateWmmParms(prAdapter, NETWORK_TYPE_BOW_INDEX); +#endif /* CFG_SUPPORT_AAA */ + prBssInfo->fgIsNetActive = TRUE; + prBssInfo->fgIsBeaconActivated = TRUE; + + /* 3 <3> Set MAC HW */ + + /* 4 <2> Initiate BSS_INFO_T - common part */ + BOW_BSS_INFO_INIT(prAdapter, NETWORK_TYPE_BOW_INDEX); +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, + "prBowFsmInfo->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", prBowFsmInfo->aucPeerAddress[0], + prBowFsmInfo->aucPeerAddress[1], prBowFsmInfo->aucPeerAddress[2], + prBowFsmInfo->aucPeerAddress[3], prBowFsmInfo->aucPeerAddress[4], + prBowFsmInfo->aucPeerAddress[5])); +#endif + + /* 4 <3.1> use command packets to inform firmware */ + rlmBssInitForAPandIbss(prAdapter, prBssInfo); + nicUpdateBss(prAdapter, NETWORK_TYPE_BOW_INDEX); + + /* 4 <3.2> Update AdHoc PM parameter */ + nicPmIndicateBssCreated(prAdapter, NETWORK_TYPE_BOW_INDEX); + + /* 4 <3.1> Reset HW TSF Update Mode and Beacon Mode */ + + /* 4 <3.2> Setup BSSID */ + /* TODO: rxmSetRxFilterBSSID0 */ +/* rxmSetRxFilterBSSID0(prBssInfo->ucHwBssidId, prBssInfo->aucBSSID); */ + + /* 4 <3.3> Setup RX Filter to accept Probe Request */ + /* TODO: f get/set RX filter. */ + +#if 0 + { + UINT_32 u4RxFilter; + + if (halMacRxGetRxFilters(&u4RxFilter) == HAL_STATUS_SUCCESS) { + + u4RxFilter &= ~BIT(RXFILTER_DROP_PROBE_REQ); + + halMacRxSetRxFilters(u4RxFilter); + } + } +#endif + } + + /*Update BoW Table */ + bowSetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress, BOW_DEVICE_STATE_STARTING); + +#if CFG_BOW_TEST + kalPrint("BoW Starting,[%d,%d]\n", g_u4LinkCount, g_u4Beaconing); + DBGLOG(BOW, EVENT, "bowStarting, g_u4LinkCount, %x.\n", g_u4LinkCount); +#endif + + /*Start beaconing */ + if (g_u4Beaconing < 1) { + GLUE_INC_REF_CNT(g_u4Beaconing); + bssSendBeaconProbeResponse(prAdapter, NETWORK_TYPE_BOW_INDEX, NULL, 0); + cnmTimerStartTimer(prAdapter, &prBowFsmInfo->rStartingBeaconTimer, prBowFsmInfo->u2BeaconInterval); + } +#if 0 + /*Responder: Start to scan Initiator */ + if (prBowFsmInfo->ucRole == BOW_RESPONDER) { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowStarting responder, start scan result searching.\n"); +#endif + cnmTimerStopTimer(prAdapter, &prBowFsmInfo->rChGrantedTimer); + bowReleaseCh(prAdapter); + bowResponderScan(prAdapter); + } + /*Initiator: Request channel, wait for responder */ + else { + /* Todo:: Nothing*/ + /* bowRequestCh(prAdapter); */ + } +#endif + +} + +VOID bowAssignSsid(IN PUINT_8 pucSsid, IN PUINT_8 puOwnMacAddr) +{ + UINT_8 i; + UINT_8 aucSSID[] = BOW_WILDCARD_SSID; + + kalMemCopy(pucSsid, aucSSID, BOW_WILDCARD_SSID_LEN); + + for (i = 0; i < 6; i++) { + pucSsid[(3 * i) + 3] = 0x2D; + if ((*(puOwnMacAddr + i) >> 4) < 0xA) + *(pucSsid + (3 * i) + 4) = (*(puOwnMacAddr + i) >> 4) + 0x30; + else + *(pucSsid + (3 * i) + 4) = (*(puOwnMacAddr + i) >> 4) + 0x57; + + if ((*(puOwnMacAddr + i) & 0x0F) < 0xA) + pucSsid[(3 * i) + 5] = (*(puOwnMacAddr + i) & 0x0F) + 0x30; + else + pucSsid[(3 * i) + 5] = (*(puOwnMacAddr + i) & 0x0F) + 0x57; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Probe Request Frame and then return +* result to BSS to indicate if need to send the corresponding Probe Response +* Frame if the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu4ControlFlags Control flags for replying the Probe Response +* +* @retval TRUE Reply the Probe Response +* @retval FALSE Don't reply the Probe Response +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN bowValidateProbeReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_32 pu4ControlFlags) +{ + P_WLAN_MAC_MGMT_HEADER_T prMgtHdr; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_BSS_INFO_T prBssInfo; + P_IE_SSID_T prIeSsid = (P_IE_SSID_T) NULL; + PUINT_8 pucIE; + UINT_16 u2IELength; + UINT_16 u2Offset = 0; + BOOLEAN fgReplyProbeResp = FALSE; + + ASSERT(prSwRfb); + ASSERT(pu4ControlFlags); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + +#if 0 /* CFG_BOW_TEST */ + DBGLOG(BOW, EVENT, "bowValidateProbeReq.\n"); +#endif + + /* 4 <1> Parse Probe Req IE and Get IE ptr (SSID, Supported Rate IE, ...) */ + prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T) prSwRfb->pvHeader; + + u2IELength = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen; + pucIE = (PUINT_8) ((ULONG) prSwRfb->pvHeader + prSwRfb->u2HeaderLen); + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (IE_ID(pucIE) == ELEM_ID_SSID) { + 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 (IE_ID(pucIE) == ELEM_ID_SSID) { + if ((!prIeSsid) && (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) + prIeSsid = (P_IE_SSID_T) pucIE; + break; + } + } /* end of IE_FOR_EACH */ + + /* 4 <2> Check network conditions */ + /*If BoW AP is beaconing */ + if (prBssInfo->eCurrentOPMode == OP_MODE_BOW && g_u4Beaconing > 0) { + + /*Check the probe requset sender is our peer */ + if (bowCheckBowTableIfVaild(prAdapter, prMgtHdr->aucSrcAddr)) + fgReplyProbeResp = TRUE; + /*Check the probe request target SSID is our SSID */ + else if ((prIeSsid) && + EQUAL_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, prIeSsid->aucSSID, prIeSsid->ucLength)) + fgReplyProbeResp = TRUE; + else + fgReplyProbeResp = FALSE; + } + + return fgReplyProbeResp; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Media Disconnect" to HOST +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bowSendBeacon(IN P_ADAPTER_T prAdapter, IN ULONG ulParam) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if ((g_u4Beaconing != 0) && (g_u4LinkCount > 0) && (g_u4LinkCount < CFG_BOW_PHYSICAL_LINK_NUM)) { + /* Send beacon */ + bssSendBeaconProbeResponse(prAdapter, NETWORK_TYPE_BOW_INDEX, NULL, 0); + cnmTimerStartTimer(prAdapter, &prBowFsmInfo->rStartingBeaconTimer, prBowFsmInfo->u2BeaconInterval); + } +#if CFG_BOW_TEST + else + kalPrint("BoW Send Beacon,[%d,%d]\n", g_u4LinkCount, g_u4Beaconing); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Media Disconnect" to HOST +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bowResponderScan(IN P_ADAPTER_T prAdapter) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + P_MSG_SCN_SCAN_REQ prScanReqMsg; + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowResponderScan.\n"); + kalPrint("BOW SCAN [REQ:%d]\n", prBowFsmInfo->ucSeqNumOfScanReq + 1); +#endif + + prScanReqMsg = (P_MSG_SCN_SCAN_REQ) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_REQ)); + + if (!prScanReqMsg) { + ASSERT(0); /* Can't trigger SCAN FSM */ + return; + } + + /*Fill scan message */ + prScanReqMsg->rMsgHdr.eMsgId = MID_BOW_SCN_SCAN_REQ; + prScanReqMsg->ucSeqNum = ++prBowFsmInfo->ucSeqNumOfScanReq; + prScanReqMsg->ucNetTypeIndex = (UINT_8) NETWORK_TYPE_BOW_INDEX; + prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_SPECIFIED; + prScanReqMsg->ucSSIDLength = BOW_SSID_LEN; + bowAssignSsid(prScanReqMsg->aucSSID, prBowFsmInfo->aucPeerAddress); + prScanReqMsg->ucChannelListNum = 1; + + if (prBowFsmInfo->eBand == BAND_2G4) { + prScanReqMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; + prScanReqMsg->arChnlInfoList[0].eBand = BAND_2G4; + } else { + prScanReqMsg->eScanChannel = SCAN_CHANNEL_5G; + prScanReqMsg->arChnlInfoList[0].eBand = BAND_5G; + } + + prScanReqMsg->arChnlInfoList[0].ucChannelNum = prBowFsmInfo->ucPrimaryChannel; + prScanReqMsg->u2IELen = 0; + + /*Send scan message */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanReqMsg, MSG_SEND_METHOD_BUF); + + /*Change state to SCANNING */ + bowSetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress, BOW_DEVICE_STATE_SCANNING); + + /* prBowFsmInfo->fgTryScan = FALSE; */ /* Will enable background sleep for infrastructure */ + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID bowResponderScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_SCN_SCAN_DONE prScanDoneMsg; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_BSS_DESC_T prBssDesc; + UINT_8 ucSeqNumOfCompMsg; + P_CONNECTION_SETTINGS_T prConnSettings; + ENUM_BOW_DEVICE_STATE eFsmState; + ENUM_SCAN_STATUS eScanStatus; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prScanDoneMsg = (P_MSG_SCN_SCAN_DONE) prMsgHdr; + eFsmState = bowGetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress); + + ASSERT(prScanDoneMsg->ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX); + + ucSeqNumOfCompMsg = prScanDoneMsg->ucSeqNum; + eScanStatus = prScanDoneMsg->eScanStatus; + + cnmMemFree(prAdapter, prMsgHdr); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowResponderScanDone.\n"); + kalPrint("BOW SCAN [DONE:%d]\n", ucSeqNumOfCompMsg); +#endif + + if (eScanStatus == SCAN_STATUS_CANCELLED) { +#if CFG_BOW_TEST + kalPrint("BOW SCAN [CANCELLED:%d]\n", ucSeqNumOfCompMsg); +#endif + if (eFsmState == BOW_DEVICE_STATE_DISCONNECTING) { + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, 0, NULL, 0); + } + return; + } else if (eFsmState == BOW_DEVICE_STATE_DISCONNECTED) { + /* bowDisconnectLink(prAdapter, NULL, TX_RESULT_SUCCESS); */ + return; + } else if (ucSeqNumOfCompMsg != prBowFsmInfo->ucSeqNumOfScanReq) { + DBGLOG(BOW, EVENT, "Sequence no. of BOW Responder scan done is not matched.\n"); + return; + } + prConnSettings->fgIsScanReqIssued = FALSE; + prBssDesc = scanSearchBssDescByBssid(prAdapter, prBowFsmInfo->aucPeerAddress); +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "End scan result searching.\n"); +#endif + + /* Initiator is FOUND */ + if (prBssDesc != NULL) { + /* (prBssDesc->aucBSSID != NULL)) */ +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "Search Bow Peer address - %x:%x:%x:%x:%x:%x.\n", prBssDesc->aucBSSID[0], + prBssDesc->aucBSSID[1], + prBssDesc->aucBSSID[2], + prBssDesc->aucBSSID[3], prBssDesc->aucBSSID[4], prBssDesc->aucBSSID[5]); + DBGLOG(BOW, EVENT, "Starting to join initiator.\n"); +#endif + /*Set target BssDesc */ + prBowFsmInfo->prTargetBssDesc = prBssDesc; + /*Request channel to do JOIN */ + bowSetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress, + BOW_DEVICE_STATE_ACQUIRING_CHANNEL); + bowRequestCh(prAdapter); + } + /*Initiator is NOT FOUND */ + else { + /*Scan again, until PAL timeout */ + bowResponderScan(prAdapter); +#if 0 + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, 0, NULL, 0); +#endif + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Function for cancelling scan request. There is another option to extend channel privilige +* for another purpose. +* +* @param fgIsChannelExtention - Keep the channel previlege, but can cancel scan timer. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bowResponderCancelScan(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsChannelExtention) +{ + + P_MSG_SCN_SCAN_CANCEL prScanCancel = (P_MSG_SCN_SCAN_CANCEL) NULL; + P_BOW_FSM_INFO_T prBowFsmInfo = (P_BOW_FSM_INFO_T) NULL; + + DEBUGFUNC("bowResponderCancelScan()"); + + do { + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if (TRUE) { +#if CFG_BOW_TEST + kalPrint("BOW SCAN [CANCEL:%d]\n", prBowFsmInfo->ucSeqNumOfScanReq); +#endif + /* There is a channel privilege on hand. */ + + DBGLOG(P2P, TRACE, "BOW Cancel Scan\n"); + + prScanCancel = + (P_MSG_SCN_SCAN_CANCEL) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_CANCEL)); + if (!prScanCancel) { + /* Buffer not enough, can not cancel scan request. */ + DBGLOG(P2P, TRACE, "Buffer not enough, can not cancel scan.\n"); + ASSERT(FALSE); + break; + } + + prScanCancel->rMsgHdr.eMsgId = MID_BOW_SCN_SCAN_CANCEL; + prScanCancel->ucNetTypeIndex = NETWORK_TYPE_BOW_INDEX; + prScanCancel->ucSeqNum = prBowFsmInfo->ucSeqNumOfScanReq; +#if CFG_ENABLE_WIFI_DIRECT + prScanCancel->fgIsChannelExt = fgIsChannelExtention; +#endif + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanCancel, MSG_SEND_METHOD_BUF); + + } + + } while (FALSE); + +} /* bowResponderCancelScan */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Initialization of JOIN STATE +* +* @param[in] prBssDesc The pointer of BSS_DESC_T which is the BSS we will try to join with. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bowResponderJoin(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + P_BSS_INFO_T prBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_STA_RECORD_T prStaRec; + P_MSG_JOIN_REQ_T prJoinReqMsg; + + ASSERT(prBssDesc); + ASSERT(prAdapter); + + DBGLOG(BOW, EVENT, "Starting bowResponderJoin.\n"); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* 4 <1> We are going to connect to this BSS. */ + prBssDesc->fgIsConnecting = TRUE; + bowSetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress, BOW_DEVICE_STATE_CONNECTING); + + /* 4 <2> Setup corresponding STA_RECORD_T */ + /*Support First JOIN and retry */ + prStaRec = bssCreateStaRecFromBssDesc(prAdapter, STA_TYPE_BOW_AP, NETWORK_TYPE_BOW_INDEX, prBssDesc); + if (!prStaRec) + return; + + prBowFsmInfo->prTargetStaRec = prStaRec; + + /* 4 <3> Update ucAvailableAuthTypes which we can choice during SAA */ + prStaRec->fgIsReAssoc = FALSE; + prBowFsmInfo->ucAvailableAuthTypes = (UINT_8) AUTH_TYPE_OPEN_SYSTEM; + prStaRec->ucTxAuthAssocRetryLimit = TX_AUTH_ASSOCI_RETRY_LIMIT; + + /* 4 <4> Use an appropriate Authentication Algorithm Number among the ucAvailableAuthTypes */ + if (prBowFsmInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_OPEN_SYSTEM) { + + DBGLOG(BOW, LOUD, "JOIN INIT: Try to do Authentication with AuthType == OPEN_SYSTEM.\n"); + prBowFsmInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_OPEN_SYSTEM; + + prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_OPEN_SYSTEM; + } else { + ASSERT(0); + } + + /* 4 <4.1> sync. to firmware domain */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + /* 4 <5> Overwrite Connection Setting for eConnectionPolicy */ + if (prBssDesc->ucSSIDLen) { + COPY_SSID(prConnSettings->aucSSID, prConnSettings->ucSSIDLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowResponderJoin, SSID %s.\n", prBssDesc->aucSSID); + DBGLOG(BOW, EVENT, "bowResponderJoin, SSID %s.\n", prConnSettings->aucSSID); +#endif + } + /* 4 <6> Send a Msg to trigger SAA to start JOIN process. */ + prJoinReqMsg = (P_MSG_JOIN_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_REQ_T)); + if (!prJoinReqMsg) { + + ASSERT(0); /* Can't trigger SAA FSM */ + return; + } + + prJoinReqMsg->rMsgHdr.eMsgId = MID_BOW_SAA_FSM_START; + prJoinReqMsg->ucSeqNum = ++prBowFsmInfo->ucSeqNumOfReqMsg; + prJoinReqMsg->prStaRec = prStaRec; + + prBssInfo->prStaRecOfAP = prStaRec; + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "prStaRec->eStaType, %x.\n", prStaRec->eStaType); + DBGLOG(BOW, INFO, "BoW trigger SAA [%pM]\n", prStaRec->aucMacAddr); +#endif + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinReqMsg, MSG_SEND_METHOD_BUF); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Join Complete Event from SAA FSM for BOW FSM +* +* @param[in] prMsgHdr Message of Join Complete of SAA FSM. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bowFsmRunEventJoinComplete(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_JOIN_COMP_T prJoinCompMsg; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_STA_RECORD_T prStaRec; + P_SW_RFB_T prAssocRspSwRfb; + P_BSS_INFO_T prBssInfo; + P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) NULL; + UINT_16 u2IELength; + PUINT_8 pucIE; + P_BSS_INFO_T prBowBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prJoinCompMsg = (P_MSG_JOIN_COMP_T) prMsgHdr; + prStaRec = prJoinCompMsg->prStaRec; + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "Start bowfsmRunEventJoinComplete.\n"); + DBGLOG(BOW, EVENT, "bowfsmRunEventJoinComplete ptr check\n"); + DBGLOG(BOW, EVENT, "prMsgHdr %x\n", prMsgHdr); + DBGLOG(BOW, EVENT, "prAdapter %x\n", prAdapter); + DBGLOG(BOW, EVENT, "prBowFsmInfo %x\n", prBowFsmInfo); + DBGLOG(BOW, EVENT, "prStaRec %x\n", prStaRec); +#endif + + ASSERT(prStaRec); + ASSERT(prBowFsmInfo); + + /* Check SEQ NUM */ + if (prJoinCompMsg->ucSeqNum == prBowFsmInfo->ucSeqNumOfReqMsg) { + COPY_MAC_ADDR(prBowFsmInfo->aucPeerAddress, prStaRec->aucMacAddr); + + /* 4 <1> JOIN was successful */ + if (prJoinCompMsg->rJoinStatus == WLAN_STATUS_SUCCESS) { + prAssocRspSwRfb = prJoinCompMsg->prSwRfb; + prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) prAssocRspSwRfb->pvHeader; + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + + u2IELength = (UINT_16) ((prAssocRspSwRfb->u2PacketLen - prAssocRspSwRfb->u2HeaderLen) - + (OFFSET_OF(WLAN_ASSOC_RSP_FRAME_T, aucInfoElem[0]) - + WLAN_MAC_MGMT_HEADER_LEN)); + pucIE = prAssocRspFrame->aucInfoElem; + + prStaRec->eStaType = STA_TYPE_BOW_AP; + prStaRec->u2DesiredNonHTRateSet &= prBowBssInfo->u2OperationalRateSet; + prStaRec->ucDesiredPhyTypeSet = prStaRec->ucPhyTypeSet & prBowBssInfo->ucPhyTypeSet; +#if CFG_BOW_RATE_LIMITATION + /* 4 <1.2>Update Rate Set */ + /*Limit Rate Set to 24M, 48M, 54M */ + prStaRec->u2DesiredNonHTRateSet &= (RATE_SET_BIT_24M | RATE_SET_BIT_48M | RATE_SET_BIT_54M); + /*If peer cannot support the above rate set, fix on the available highest rate */ + if (prStaRec->u2DesiredNonHTRateSet == 0) { + UINT_8 ucHighestRateIndex; + + if (rateGetHighestRateIndexFromRateSet + (prBowBssInfo->u2OperationalRateSet, &ucHighestRateIndex)) { + prStaRec->u2DesiredNonHTRateSet = BIT(ucHighestRateIndex); + } + } +#endif + + /* 4 <1.1> Change FW's Media State immediately. */ + bowChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); + + mqmProcessAssocRsp(prAdapter, prAssocRspSwRfb, pucIE, u2IELength); + + /* 4 <1.2> Update HT information and set channel */ + /* Record HT related parameters in rStaRec and rBssInfo + * Note: it shall be called before nicUpdateBss() + */ +#if CFG_BOW_SUPPORT_11N + rlmProcessAssocRsp(prAdapter, prAssocRspSwRfb, pucIE, u2IELength); +#endif + + /* 4 <1.3> Update BSS_INFO_T */ + nicUpdateBss(prAdapter, NETWORK_TYPE_BOW_INDEX); +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "Finish bowUpdateBssInfoForJOIN.\n"); +#endif + /* 4 <1.4> Activate current AP's STA_RECORD_T in Driver. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowFsmRunEventJoinComplete, qmActivateStaRec.\n"); +#endif + + /* 4 <1.7> Set the Next State of BOW FSM */ + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + TRUE, + FALSE, + wlanbowCmdEventLinkConnected, wlanbowCmdTimeoutHandler, 0, NULL, 0); + } + /* 4 <2> JOIN was not successful */ + else { + /*Retry */ + bowResponderJoin(prAdapter, prBowFsmInfo->prTargetBssDesc); +#if 0 + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, 0, NULL, 0); +#endif +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "Start bowfsmRunEventJoinComplete -- Join failed.\n"); + DBGLOG(BOW, INFO, "BoW trigger SAA REJOIN\n"); +#endif + } + } + + cnmMemFree(prAdapter, prMsgHdr); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Media State to HOST +* +* @param[in] eConnectionState Current Media State +* @param[in] fgDelayIndication Set TRUE for postponing the Disconnect Indication. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bowIndicationOfMediaStateToHost(IN P_ADAPTER_T prAdapter, + IN ENUM_PARAM_MEDIA_STATE_T eConnectionState, IN BOOLEAN fgDelayIndication) +{ + EVENT_CONNECTION_STATUS rEventConnStatus; + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_INFO_T prBssInfo; + P_BOW_FSM_INFO_T prBowFsmInfo; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + /* NOTE(Kevin): Move following line to bowChangeMediaState() macro per CM's request. */ + /* prBowBssInfo->eConnectionState = eConnectionState; */ + + /* For indicating the Disconnect Event only if current media state is + * disconnected and we didn't do indication yet. + */ + if (prBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { + if (prBssInfo->eConnectionStateIndicated == eConnectionState) + return; + } + + if (!fgDelayIndication) { + /* 4 <0> Cancel Delay Timer */ + cnmTimerStopTimer(prAdapter, &prBowFsmInfo->rIndicationOfDisconnectTimer); + + /* 4 <1> Fill EVENT_CONNECTION_STATUS */ + rEventConnStatus.ucMediaStatus = (UINT_8) eConnectionState; + + if (eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + rEventConnStatus.ucReasonOfDisconnect = DISCONNECT_REASON_CODE_RESERVED; + + if (prBssInfo->eCurrentOPMode == OP_MODE_BOW) { + rEventConnStatus.ucInfraMode = (UINT_8) NET_TYPE_INFRA; + rEventConnStatus.u2AID = prBssInfo->u2AssocId; + rEventConnStatus.u2ATIMWindow = 0; + } else if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + rEventConnStatus.ucInfraMode = (UINT_8) NET_TYPE_IBSS; + rEventConnStatus.u2AID = 0; + rEventConnStatus.u2ATIMWindow = prBssInfo->u2ATIMWindow; + } else { + ASSERT(0); + } + + COPY_SSID(rEventConnStatus.aucSsid, + rEventConnStatus.ucSsidLen, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); + + COPY_MAC_ADDR(rEventConnStatus.aucBssid, prBssInfo->aucBSSID); + + rEventConnStatus.u2BeaconPeriod = prBssInfo->u2BeaconInterval; + rEventConnStatus.u4FreqInKHz = nicChannelNum2Freq(prBssInfo->ucPrimaryChannel); + + switch (prBssInfo->ucNonHTBasicPhyType) { + case PHY_TYPE_HR_DSSS_INDEX: + rEventConnStatus.ucNetworkType = (UINT_8) PARAM_NETWORK_TYPE_DS; + break; + + case PHY_TYPE_ERP_INDEX: + rEventConnStatus.ucNetworkType = (UINT_8) PARAM_NETWORK_TYPE_OFDM24; + break; + + case PHY_TYPE_OFDM_INDEX: + rEventConnStatus.ucNetworkType = (UINT_8) PARAM_NETWORK_TYPE_OFDM5; + break; + + default: + ASSERT(0); + rEventConnStatus.ucNetworkType = (UINT_8) PARAM_NETWORK_TYPE_DS; + break; + } + } else { +#if CFG_PRIVACY_MIGRATION +#if (CFG_REFACTORY_PMKSA == 0) + + /* Clear the pmkid cache while media disconnect */ + secClearPmkid(prAdapter); +#endif +#endif + + rEventConnStatus.ucReasonOfDisconnect = prBssInfo->ucReasonOfDisconnect; + + } + + /* 4 <2> Indication */ + nicMediaStateChange(prAdapter, NETWORK_TYPE_BOW_INDEX, &rEventConnStatus); + prBssInfo->eConnectionStateIndicated = eConnectionState; + } else { + /* NOTE: Only delay the Indication of Disconnect Event */ + ASSERT(eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED); + + DBGLOG(BOW, INFO, "Postpone the indication of Disconnect for %d seconds\n", + prConnSettings->ucDelayTimeOfDisconnectEvent); + + cnmTimerStartTimer(prAdapter, + &prBowFsmInfo->rIndicationOfDisconnectTimer, + SEC_TO_MSEC(prConnSettings->ucDelayTimeOfDisconnectEvent)); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Event of Tx Fail of AAA Module. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bowRunEventAAATxFail(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(prStaRec); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowRunEventAAATxFail , bssRemoveStaRecFromClientList.\n"); + DBGLOG(BOW, INFO, "BoW AAA TxFail, target state %d\n", prStaRec->ucStaState + 1); +#endif + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + bssRemoveStaRecFromClientList(prAdapter, prBssInfo, prStaRec); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Event of Successful Completion of AAA Module. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS bowRunEventAAAComplete(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + + ASSERT(prStaRec); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowRunEventAAAComplete, cnmStaRecChangeState, STA_STATE_3.\n"); + DBGLOG(BOW, INFO, "BoW AAA complete [%pM]\n", prStaRec->aucMacAddr); +#endif + + /*Update BssInfo to connected */ + bowChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); + nicUpdateBss(prAdapter, NETWORK_TYPE_BOW_INDEX); + + /*Update StaRec to State3 */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + /*Connected */ + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + TRUE, FALSE, wlanbowCmdEventLinkConnected, wlanbowCmdTimeoutHandler, 0, NULL, 0); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle RxDeauth +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS bowRunEventRxDeAuth(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb) +{ + P_BSS_INFO_T prBowBssInfo; + P_BOW_FSM_INFO_T prBowFsmInfo; + ENUM_BOW_DEVICE_STATE eFsmState; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + + if (!IS_STA_IN_BOW(prStaRec)) + return WLAN_STATUS_NOT_ACCEPTED; + + eFsmState = bowGetBowTableState(prAdapter, prStaRec->aucMacAddr); + + if (eFsmState == BOW_DEVICE_STATE_DISCONNECTED) { + /*do nothing */ + return WLAN_STATUS_NOT_ACCEPTED; + } + + if (prStaRec->ucStaState > STA_STATE_1) { + + if (prStaRec->ucStaState == STA_STATE_3) { + /* P_MSG_AIS_ABORT_T prAisAbortMsg; */ + + /* NOTE(Kevin): Change state immediately to avoid starvation of + * MSG buffer because of too many deauth frames before changing + * the STA state. + */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + } + + COPY_MAC_ADDR(prBowFsmInfo->aucPeerAddress, prStaRec->aucMacAddr); + + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + TRUE, + FALSE, wlanbowCmdEventLinkDisconnected, wlanbowCmdTimeoutHandler, 0, NULL, 0); + + return WLAN_STATUS_SUCCESS; + } + + return WLAN_STATUS_NOT_ACCEPTED; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function handle BoW Link disconnect. +* +* \param[in] pMsduInfo Pointer to the Msdu Info +* \param[in] rStatus The Tx done status +* +* \return - +* +* \note after receive deauth frame, callback function call this +*/ +/*----------------------------------------------------------------------------*/ +VOID bowDisconnectLink(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + /*Free target StaRec */ + if (prMsduInfo) + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + else + prStaRec = prBowFsmInfo->prTargetStaRec; + + if (prStaRec) + /* cnmStaRecFree(prAdapter, prStaRec, TRUE); */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + kalPrint("bowDisconnectLink\n"); + /*No one connected */ + if (g_u4LinkCount == 0 && g_u4Beaconing != 0) { + cnmTimerStopTimer(prAdapter, &prBowFsmInfo->rStartingBeaconTimer); + bowStopping(prAdapter); + kalPrint("bowStopping\n"); + /*Restore TxPower from Short range mode */ +#if CFG_SUPPORT_NVRAM && 0 + wlanLoadManufactureData(prAdapter, kalGetConfiguration(prAdapter->prGlueInfo)); +#endif + /*Uninit BoW Interface */ +#if CFG_BOW_SEPARATE_DATA_PATH + kalUninitBowDevice(prAdapter->prGlueInfo); +#endif + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Assoc Req Frame and then return +* the status code to AAA to indicate if need to perform following actions +* when the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu2StatusCode The Status Code of Validation Result +* +* @retval TRUE Reply the Assoc Resp +* @retval FALSE Don't reply the Assoc Resp +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN bowValidateAssocReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu2StatusCode) +{ + BOOLEAN fgReplyAssocResp = FALSE; + P_BSS_INFO_T prBowBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_WLAN_ASSOC_REQ_FRAME_T prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) NULL; + OS_SYSTIME rCurrentTime; + static OS_SYSTIME rLastRejectAssocTime; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) prSwRfb->pvHeader; + *pu2StatusCode = STATUS_CODE_REQ_DECLINED; + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowValidateAssocReq, prBowFsmInfo->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + prBowFsmInfo->aucPeerAddress[0], + prBowFsmInfo->aucPeerAddress[1], + prBowFsmInfo->aucPeerAddress[2], + prBowFsmInfo->aucPeerAddress[3], + prBowFsmInfo->aucPeerAddress[4], prBowFsmInfo->aucPeerAddress[5])); + DBGLOG(BOW, EVENT, "bowValidateAssocReq, prAssocReqFrame->aucSrcAddr, %x:%x:%x:%x:%x:%x.\n", + prAssocReqFrame->aucSrcAddr[0], + prAssocReqFrame->aucSrcAddr[1], + prAssocReqFrame->aucSrcAddr[2], + prAssocReqFrame->aucSrcAddr[3], + prAssocReqFrame->aucSrcAddr[4], prAssocReqFrame->aucSrcAddr[5])); +#endif + + /*Assoc Accept */ + while (EQUAL_MAC_ADDR(prAssocReqFrame->aucSrcAddr, prBowFsmInfo->aucPeerAddress)) { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowValidateAssocReq, return wlanbowCmdEventLinkConnected.\n"); +#endif + /*Update StaRec */ + prStaRec = cnmGetStaRecByAddress(prAdapter, + (UINT_8) NETWORK_TYPE_BOW_INDEX, prAssocReqFrame->aucSrcAddr); + if (!prStaRec) + break; + prStaRec->eStaType = STA_TYPE_BOW_CLIENT; + prStaRec->u2DesiredNonHTRateSet &= prBowBssInfo->u2OperationalRateSet; + prStaRec->ucDesiredPhyTypeSet = prStaRec->ucPhyTypeSet & prBowBssInfo->ucPhyTypeSet; + +#if CFG_BOW_RATE_LIMITATION + /*Limit Rate Set to 24M, 48M, 54M */ + prStaRec->u2DesiredNonHTRateSet &= (RATE_SET_BIT_24M | RATE_SET_BIT_48M | RATE_SET_BIT_54M); + /*If peer cannot support the above rate set, fix on the available highest rate */ + if (prStaRec->u2DesiredNonHTRateSet == 0) { + UINT_8 ucHighestRateIndex; + + if (rateGetHighestRateIndexFromRateSet(prBowBssInfo->u2OperationalRateSet, &ucHighestRateIndex)) + prStaRec->u2DesiredNonHTRateSet = BIT(ucHighestRateIndex); + else { + /*If no available rate is found, DECLINE the association */ + *pu2StatusCode = STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED; + break; + } + } +#endif + prStaRec->ucNetTypeIndex = NETWORK_TYPE_BOW_INDEX; + + /*Undpate BssInfo to FW */ + bowChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); + nicUpdateBss(prAdapter, NETWORK_TYPE_BOW_INDEX); + + /*reply successful */ + *pu2StatusCode = STATUS_CODE_SUCCESSFUL; + fgReplyAssocResp = TRUE; + break; + } + + /*Reject Assoc */ + if (*pu2StatusCode != STATUS_CODE_SUCCESSFUL) { + /*Reply Assoc with reject every 5s */ + rCurrentTime = kalGetTimeTick(); + if (CHECK_FOR_TIMEOUT(rCurrentTime, rLastRejectAssocTime, MSEC_TO_SYSTIME(5000)) || + rLastRejectAssocTime == 0) { + fgReplyAssocResp = TRUE; + rLastRejectAssocTime = rCurrentTime; + } + } + + return fgReplyAssocResp; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Auth Frame and then return +* the status code to AAA to indicate if need to perform following actions +* when the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[in] pprStaRec Pointer to pointer of STA_RECORD_T structure. +* @param[out] pu2StatusCode The Status Code of Validation Result +* +* @retval TRUE Reply the Auth +* @retval FALSE Don't reply the Auth +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +bowValidateAuth(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, IN PP_STA_RECORD_T pprStaRec, OUT PUINT_16 pu2StatusCode) +{ + BOOLEAN fgReplyAuth = FALSE; + P_BSS_INFO_T prBowBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_WLAN_AUTH_FRAME_T prAuthFrame = (P_WLAN_AUTH_FRAME_T) NULL; + OS_SYSTIME rCurrentTime; + static OS_SYSTIME rLastRejectAuthTime; + + /* + * TODO(Kevin): Call BoW functions to check .. + * 1. Check we are BoW now. + * 2. Check we can accept connection from thsi peer + * 3. Check Black List here. + */ + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowValidateAuth, prBowFsmInfo->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + prBowFsmInfo->aucPeerAddress[0], + prBowFsmInfo->aucPeerAddress[1], + prBowFsmInfo->aucPeerAddress[2], + prBowFsmInfo->aucPeerAddress[3], + prBowFsmInfo->aucPeerAddress[4], prBowFsmInfo->aucPeerAddress[5])); + DBGLOG(BOW, EVENT, "bowValidateAuth, prAuthFrame->aucSrcAddr, %x:%x:%x:%x:%x:%x.\n", + prAuthFrame->aucSrcAddr[0], + prAuthFrame->aucSrcAddr[1], + prAuthFrame->aucSrcAddr[2], + prAuthFrame->aucSrcAddr[3], prAuthFrame->aucSrcAddr[4], prAuthFrame->aucSrcAddr[5])); +#endif + + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_BOW_INDEX, prAuthFrame->aucSrcAddr); + if (!prStaRec) { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowValidateAuth, cnmStaRecAlloc.\n"); +#endif + prStaRec = cnmStaRecAlloc(prAdapter, (UINT_8) NETWORK_TYPE_BOW_INDEX); + + /* + * TODO(Kevin): Error handling of allocation of STA_RECORD_T for + * exhausted case and do removal of unused STA_RECORD_T. + */ + if (!prStaRec) + return fgReplyAuth; + COPY_MAC_ADDR(prStaRec->aucMacAddr, prAuthFrame->aucSrcAddr); + prSwRfb->ucStaRecIdx = prStaRec->ucIndex; + prBowBssInfo->prStaRecOfAP = prStaRec; + + /* NOTE(Kevin): Better to change state here, not at TX Done */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowValidateAuth, cnmStaRecChangeState.\n"); +#endif + } else { + prSwRfb->ucStaRecIdx = prStaRec->ucIndex; +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowValidateAuth, prStaRec->ucIndex, %x.\n", prStaRec->ucIndex); +#endif + bssRemoveStaRecFromClientList(prAdapter, prBowBssInfo, prStaRec); + } + + if (EQUAL_MAC_ADDR(prAuthFrame->aucSrcAddr, prBowFsmInfo->aucPeerAddress)) { + + prStaRec->eStaType = STA_TYPE_BOW_CLIENT; + prStaRec->ucNetTypeIndex = NETWORK_TYPE_BOW_INDEX; +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowValidateAuth, prStaRec->eStaType, %x.\n", prStaRec->eStaType); + DBGLOG(BOW, EVENT, "bowValidateAuth, prStaRec->ucNetTypeIndex, %x.\n", prStaRec->ucNetTypeIndex); +#endif + /* Update Station Record - Status/Reason Code */ + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + prStaRec->ucJoinFailureCount = 0; + *pprStaRec = prStaRec; + *pu2StatusCode = STATUS_CODE_SUCCESSFUL; + fgReplyAuth = TRUE; + } else { + cnmStaRecFree(prAdapter, prStaRec, FALSE); + *pu2StatusCode = STATUS_CODE_REQ_DECLINED; + + /* Reply auth with reject every 5s */ + rCurrentTime = kalGetTimeTick(); + if (CHECK_FOR_TIMEOUT(rCurrentTime, rLastRejectAuthTime, MSEC_TO_SYSTIME(5000)) || + rLastRejectAuthTime == 0) { + fgReplyAuth = TRUE; + rLastRejectAuthTime = rCurrentTime; + } + } + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowValidateAuth, fgReplyAuth, %x.\n", fgReplyAuth); +#endif + return fgReplyAuth; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is invoked when CNM granted channel privilege +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID bowRunEventChGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_BSS_INFO_T prBowBssInfo; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_MSG_CH_GRANT_T prMsgChGrant; + UINT_8 ucTokenID; + UINT_32 u4GrantInterval; + ENUM_BOW_DEVICE_STATE eFsmState; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prBowBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prMsgChGrant = (P_MSG_CH_GRANT_T) prMsgHdr; + ucTokenID = prMsgChGrant->ucTokenID; + u4GrantInterval = prMsgChGrant->u4GrantInterval; + + /* 1. free message */ + cnmMemFree(prAdapter, prMsgHdr); + prBowFsmInfo->fgIsChannelGranted = TRUE; + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "Entering bowRunEventChGrant.\n"); +#endif + + eFsmState = bowGetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress); + + /*Release channel */ + if ((!prBowFsmInfo->fgIsChannelRequested) || + (prBowFsmInfo->ucSeqNumOfChReq != ucTokenID) || + (eFsmState == BOW_DEVICE_STATE_DISCONNECTED) || (eFsmState == BOW_DEVICE_STATE_DISCONNECTING)) { +#if CFG_BOW_TEST + DBGLOG(BOW, INFO, "BoW Channel [GIVE UP:%d]\n", ucTokenID); + DBGLOG(BOW, INFO, "[Requested:%d][ucSeqNumOfChReq:%d][eFsmState:%d]\n", + prBowFsmInfo->fgIsChannelRequested, prBowFsmInfo->ucSeqNumOfChReq, eFsmState); +#endif + bowReleaseCh(prAdapter); + return; + } + + /* 2. channel privilege has been approved */ + prBowFsmInfo->u4ChGrantedInterval = u4GrantInterval; + +#if 0 + cnmTimerStartTimer(prAdapter, + &prBowFsmInfo->rChGrantedTimer, + prBowFsmInfo->u4ChGrantedInterval - BOW_JOIN_CH_GRANT_THRESHOLD); +#else + cnmTimerStartTimer(prAdapter, + &prBowFsmInfo->rChGrantedTimer, BOW_JOIN_CH_REQUEST_INTERVAL - BOW_JOIN_CH_GRANT_THRESHOLD); +#endif + + /* 3.2 set local variable to indicate join timer is ticking */ + prBowFsmInfo->fgIsInfraChannelFinished = FALSE; + +#if CFG_BOW_TEST + DBGLOG(BOW, INFO, "BoW Channel [GRANTED:%d].\n", ucTokenID); +#endif + + if (eFsmState == BOW_DEVICE_STATE_ACQUIRING_CHANNEL) { + bowStarting(prAdapter); + bowReleaseCh(prAdapter); + if (prBowFsmInfo->ucRole == BOW_RESPONDER) + bowResponderJoin(prAdapter, prBowFsmInfo->prTargetBssDesc); + } else { + /*update bssinfo */ + nicUpdateBss(prAdapter, NETWORK_TYPE_BOW_INDEX); + bowReleaseCh(prAdapter); + } + +} /* end of aisFsmRunEventChGrant() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is to inform CNM for channel privilege requesting +* has been released +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID bowRequestCh(IN P_ADAPTER_T prAdapter) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + P_MSG_CH_REQ_T prMsgChReq; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if (prBowFsmInfo->fgIsChannelGranted == FALSE) { + +#if CFG_BOW_TEST + DBGLOG(BOW, INFO, "BoW channel [REQUEST:%d], %d, %d.\n", prBowFsmInfo->ucSeqNumOfChReq + 1, + prBowFsmInfo->ucPrimaryChannel, prBowFsmInfo->eBand); +#endif + prMsgChReq = (P_MSG_CH_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_REQ_T)); + + if (!prMsgChReq) { + ASSERT(0); /* Can't indicate CNM for channel acquiring */ + return; + } + + prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; + prMsgChReq->ucNetTypeIndex = NETWORK_TYPE_BOW_INDEX; + prMsgChReq->ucTokenID = ++prBowFsmInfo->ucSeqNumOfChReq; + prMsgChReq->eReqType = CH_REQ_TYPE_JOIN; +#if 0 + prMsgChReq->u4MaxInterval = BOW_JOIN_CH_REQUEST_INTERVAL; +#else + prMsgChReq->u4MaxInterval = 1; +#endif + /* prBowFsmInfo->prTargetBssDesc->ucChannelNum; */ + prMsgChReq->ucPrimaryChannel = prBowFsmInfo->ucPrimaryChannel; + /* prBowFsmInfo->prTargetBssDesc->eSco; */ + prMsgChReq->eRfSco = CHNL_EXT_SCN; + /* prBowFsmInfo->prTargetBssDesc->eBand; */ + prMsgChReq->eRfBand = prBowFsmInfo->eBand; + COPY_MAC_ADDR(prMsgChReq->aucBSSID, prBowFsmInfo->aucPeerAddress); + + prBowFsmInfo->fgIsChannelRequested = TRUE; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChReq, MSG_SEND_METHOD_BUF); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is to inform BOW that channel privilege is granted +* has been released +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID bowReleaseCh(IN P_ADAPTER_T prAdapter) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + P_MSG_CH_ABORT_T prMsgChAbort; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if (prBowFsmInfo->fgIsChannelGranted != FALSE || prBowFsmInfo->fgIsChannelRequested != FALSE) { +#if CFG_BOW_TEST + DBGLOG(BOW, INFO, "BoW channel [RELEASE:%d] %d, %d.\n", prBowFsmInfo->ucSeqNumOfChReq, + prBowFsmInfo->ucPrimaryChannel, prBowFsmInfo->eBand); +#endif + + prBowFsmInfo->fgIsChannelRequested = FALSE; + prBowFsmInfo->fgIsChannelGranted = FALSE; + + /* 1. return channel privilege to CNM immediately */ + prMsgChAbort = (P_MSG_CH_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_ABORT_T)); + if (!prMsgChAbort) { + ASSERT(0); /* Can't release Channel to CNM */ + return; + } + + prMsgChAbort->rMsgHdr.eMsgId = MID_MNY_CNM_CH_ABORT; + prMsgChAbort->ucNetTypeIndex = NETWORK_TYPE_BOW_INDEX; + prMsgChAbort->ucTokenID = prBowFsmInfo->ucSeqNumOfChReq; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChAbort, MSG_SEND_METHOD_BUF); + } + +} /* end of aisFsmReleaseCh() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Media Disconnect" to HOST +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bowChGrantedTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParam) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + ENUM_BOW_DEVICE_STATE eFsmState; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + +#if CFG_BOW_TEST + DBGLOG(BOW, INFO, "BoW Channel [TIMEOUT]\n"); +#endif +#if 1 + /* bowReleaseCh(prAdapter); */ + eFsmState = bowGetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress); + + /*If connecting is not completed, request CH again */ + if ((eFsmState == BOW_DEVICE_STATE_CONNECTING) || (eFsmState == BOW_DEVICE_STATE_STARTING)) + bowRequestCh(prAdapter); +#endif +} + +BOOLEAN bowNotifyAllLinkDisconnected(IN P_ADAPTER_T prAdapter) +{ + UINT_8 ucBowTableIdx = 0; + CMD_INFO_T rCmdInfo; + + ASSERT(prAdapter); + + kalMemZero(&rCmdInfo, sizeof(CMD_INFO_T)); + + while (ucBowTableIdx < CFG_BOW_PHYSICAL_LINK_NUM) { + if (arBowTable[ucBowTableIdx].fgIsValid) { + COPY_MAC_ADDR(prAdapter->rWifiVar.rBowFsmInfo.aucPeerAddress, + arBowTable[ucBowTableIdx].aucPeerAddress); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, + "bowNotifyAllLinkDisconnected, arBowTable[%x].aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + ucBowTableIdx, arBowTable[ucBowTableIdx].aucPeerAddress[0], + arBowTable[ucBowTableIdx].aucPeerAddress[1], + arBowTable[ucBowTableIdx].aucPeerAddress[2], + arBowTable[ucBowTableIdx].aucPeerAddress[3], + arBowTable[ucBowTableIdx].aucPeerAddress[4], + arBowTable[ucBowTableIdx].aucPeerAddress[5])); + DBGLOG(BOW, EVENT, + "bowNotifyAllLinkDisconnected, arBowTable[%x].fgIsValid, %x.\n", ucBowTableIdx, + arBowTable[ucBowTableIdx].fgIsValid); +#endif +#if 1 + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, 0, NULL, 0); +#else + wlanbowCmdEventLinkDisconnected(prAdapter, &rCmdInfo, NULL); +#endif + } + + ucBowTableIdx += 1; + } + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Bluetooth-over-Wi-Fi state from glue layer +* +* \param[in] +* prGlueInfo +* rPeerAddr +* \return +* ENUM_BOW_DEVICE_STATE +*/ +/*----------------------------------------------------------------------------*/ + +BOOLEAN bowCheckBowTableIfVaild(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6]) +{ + UINT_8 idx; + + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + for (idx = 0; idx < CFG_BOW_PHYSICAL_LINK_NUM; idx++) { + if (arBowTable[idx].fgIsValid && EQUAL_MAC_ADDR(arBowTable[idx].aucPeerAddress, aucPeerAddress)) { + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "kalCheckBowifVaild, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, + aucPeerAddress[0], + aucPeerAddress[1], + aucPeerAddress[2], + aucPeerAddress[3], aucPeerAddress[4], aucPeerAddress[5])); + + DBGLOG(BOW, EVENT, + "kalCheckBowifVaild, arBowTable[idx].aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, + arBowTable[idx].aucPeerAddress[0], arBowTable[idx].aucPeerAddress[1], + arBowTable[idx].aucPeerAddress[2], arBowTable[idx].aucPeerAddress[3], + arBowTable[idx].aucPeerAddress[4], arBowTable[idx].aucPeerAddress[5])); + + DBGLOG(BOW, EVENT, + "kalCheckBowifVaild, arBowTable[idx].fgIsValid, %x, %x.\n", idx, + arBowTable[idx].fgIsValid); + +#endif + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + return TRUE; + } + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + return FALSE; +} + +BOOLEAN bowGetBowTableContent(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBowTableIdx, OUT P_BOW_TABLE_T prBowTable) +{ + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + if (arBowTable[ucBowTableIdx].fgIsValid) { + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, + "bowGetBowTableContent, arBowTable[idx].fgIsValid, %x, %x.\n", ucBowTableIdx, + arBowTable[ucBowTableIdx].fgIsValid); + DBGLOG(BOW, INFO, "GET State [%d]\n", arBowTable[ucBowTableIdx].eState); +#endif + prBowTable = &(arBowTable[ucBowTableIdx]); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + return TRUE; + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + return FALSE; +} + +BOOLEAN bowSetBowTableContent(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBowTableIdx, IN P_BOW_TABLE_T prBowTable) +{ + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + COPY_MAC_ADDR(arBowTable[ucBowTableIdx].aucPeerAddress, prBowTable->aucPeerAddress); + arBowTable[ucBowTableIdx].eState = prBowTable->eState; + arBowTable[ucBowTableIdx].fgIsValid = prBowTable->fgIsValid; + arBowTable[ucBowTableIdx].ucAcquireID = prBowTable->ucAcquireID; + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + kalSetBowState(prAdapter->prGlueInfo, prBowTable->eState, prBowTable->aucPeerAddress); + /* kalSetBowRole(prAdapter->prGlueInfo, prBowTable->ucRole, prBowTable->aucPeerAddress); */ + +#if CFG_BOW_TEST + DBGLOG(BOW, INFO, "SET State [%d]\n", arBowTable[ucBowTableIdx].eState); + DBGLOG(BOW, EVENT, + "kalCheckBowifVaild, arBowTable[ucBowTableIdx].fgIsValid, %x, %x.\n", ucBowTableIdx, + arBowTable[ucBowTableIdx].fgIsValid); +#endif + + return TRUE; + +} + +BOOLEAN +bowGetBowTableEntryByPeerAddress(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6], OUT PUINT_8 pucBowTableIdx) +{ + UINT_8 idx; + + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + for (idx = 0; idx < CFG_BOW_PHYSICAL_LINK_NUM; idx++) { + if (arBowTable[idx].fgIsValid && EQUAL_MAC_ADDR(arBowTable[idx].aucPeerAddress, aucPeerAddress)) { + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "kalCheckBowifVaild, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, + aucPeerAddress[0], + aucPeerAddress[1], + aucPeerAddress[2], + aucPeerAddress[3], aucPeerAddress[4], aucPeerAddress[5])); + DBGLOG(BOW, EVENT, + "kalCheckBowifVaild, arBowTable[idx].aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, + arBowTable[idx].aucPeerAddress[0], arBowTable[idx].aucPeerAddress[1], + arBowTable[idx].aucPeerAddress[2], arBowTable[idx].aucPeerAddress[3], + arBowTable[idx].aucPeerAddress[4], arBowTable[idx].aucPeerAddress[5])); + DBGLOG(BOW, EVENT, + "kalCheckBowifVaild, arBowTable[idx].fgIsValid, %x, %x.\n", idx, + arBowTable[idx].fgIsValid); +#endif + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + *pucBowTableIdx = idx; + + return TRUE; + } + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + return FALSE; +} + +BOOLEAN bowGetBowTableFreeEntry(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucBowTableIdx) +{ + UINT_8 idx; + + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + for (idx = 0; idx < CFG_BOW_PHYSICAL_LINK_NUM; idx++) { + if (!arBowTable[idx].fgIsValid) { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, + "bowGetBowTableFreeEntry, arBowTable[idx].fgIsValid, %x, %x.\n", idx, + arBowTable[idx].fgIsValid); +#endif + *pucBowTableIdx = idx; + arBowTable[idx].fgIsValid = TRUE; + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + return TRUE; + } + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + return FALSE; +} + +ENUM_BOW_DEVICE_STATE bowGetBowTableState(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6]) +{ + UINT_8 idx; + + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + for (idx = 0; idx < CFG_BOW_PHYSICAL_LINK_NUM; idx++) { + if (arBowTable[idx].fgIsValid && EQUAL_MAC_ADDR(arBowTable[idx].aucPeerAddress, aucPeerAddress)) { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowGetState, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, + aucPeerAddress[0], + aucPeerAddress[1], + aucPeerAddress[2], + aucPeerAddress[3], aucPeerAddress[4], aucPeerAddress[5])); + DBGLOG(BOW, EVENT, "bowGetState, arBowTable[idx].aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, + arBowTable[idx].aucPeerAddress[0], + arBowTable[idx].aucPeerAddress[1], + arBowTable[idx].aucPeerAddress[2], + arBowTable[idx].aucPeerAddress[3], + arBowTable[idx].aucPeerAddress[4], arBowTable[idx].aucPeerAddress[5])); + DBGLOG(BOW, EVENT, + "bowGetState, arBowTable[idx].fgIsValid, %x, %x.\n", idx, arBowTable[idx].fgIsValid); + DBGLOG(BOW, EVENT, + "bowGetState, arBowTable[idx].eState;, %x, %x.\n", idx, arBowTable[idx].eState); + DBGLOG(BOW, INFO, "GET State [%d]\n", arBowTable[idx].eState); +#endif + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + return arBowTable[idx].eState; + } + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + return BOW_DEVICE_STATE_DISCONNECTED; +} + +BOOLEAN bowSetBowTableState(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6], IN ENUM_BOW_DEVICE_STATE eState) +{ + UINT_8 ucBowTableIdx; + + if (bowGetBowTableEntryByPeerAddress(prAdapter, aucPeerAddress, &ucBowTableIdx)) { + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + arBowTable[ucBowTableIdx].eState = eState; +#if CFG_BOW_TEST + DBGLOG(BOW, INFO, "SET State [%d]\n", eState); +#endif + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + kalSetBowState(prAdapter->prGlueInfo, eState, aucPeerAddress); + return TRUE; + } + return FALSE; +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/common/wlan_lib.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/common/wlan_lib.c new file mode 100644 index 0000000000000..ca86d9e708e2c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/common/wlan_lib.c @@ -0,0 +1,5923 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E 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 +}; + +#define WLAN_WAIT_READY_BIT_TIMEOUT 3000 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef struct _CODE_MAPPING_T { + UINT_32 u4RegisterValue; + INT_32 i4TxpowerOffset; +} CODE_MAPPING_T, *P_CODE_MAPPING_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +BOOLEAN fgIsBusAccessFailed = FALSE; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define SIGNED_EXTEND(n, _sValue) \ + (((_sValue) & BIT((n)-1)) ? ((_sValue) | BITS(n, 31)) : \ + ((_sValue) & ~BITS(n, 31))) + +/* TODO: Check */ +/* OID set handlers without the need to access HW register */ +PFN_OID_HANDLER_FUNC apfnOidSetHandlerWOHwAccess[] = { + wlanoidSetChannel, + wlanoidSetBeaconInterval, + wlanoidSetAtimWindow, + wlanoidSetFrequency, +}; + +/* TODO: Check */ +/* OID query handlers without the need to access HW register */ +PFN_OID_HANDLER_FUNC apfnOidQueryHandlerWOHwAccess[] = { + wlanoidQueryBssid, + wlanoidQuerySsid, + wlanoidQueryInfrastructureMode, + wlanoidQueryAuthMode, + wlanoidQueryEncryptionStatus, +#if (CFG_REFACTORY_PMKSA == 0) + wlanoidQueryPmkid, +#endif + wlanoidQueryNetworkTypeInUse, + wlanoidQueryBssidList, + wlanoidQueryAcpiDevicePowerState, + wlanoidQuerySupportedRates, + wlanoidQueryDesiredRates, + wlanoidQuery802dot11PowerSaveProfile, + wlanoidQueryBeaconInterval, + wlanoidQueryAtimWindow, + wlanoidQueryFrequency, +}; + +/* OID set handlers allowed in RF test mode */ +PFN_OID_HANDLER_FUNC apfnOidSetHandlerAllowedInRFTest[] = { + wlanoidRftestSetTestMode, + wlanoidRftestSetAbortTestMode, + wlanoidRftestSetAutoTest, + wlanoidSetMcrWrite, + wlanoidSetEepromWrite +}; + +/* OID query handlers allowed in RF test mode */ +PFN_OID_HANDLER_FUNC apfnOidQueryHandlerAllowedInRFTest[] = { + wlanoidRftestQueryAutoTest, + wlanoidQueryMcrRead, + wlanoidQueryEepromRead +} + +; + +PFN_OID_HANDLER_FUNC apfnOidWOTimeoutCheck[] = { + wlanoidRftestSetTestMode, + wlanoidRftestSetAbortTestMode, + wlanoidSetAcpiDevicePowerState, +}; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#if 0 /* no use */ +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is a private routine, which is used to check if HW access is needed +* for the OID query/ set handlers. +* +* \param[IN] pfnOidHandler Pointer to the OID handler. +* \param[IN] fgSetInfo It is a Set information handler. +* +* \retval TRUE This function needs HW access +* \retval FALSE This function does not need HW access +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanIsHandlerNeedHwAccess(IN PFN_OID_HANDLER_FUNC pfnOidHandler, IN BOOLEAN fgSetInfo) +{ + PFN_OID_HANDLER_FUNC *apfnOidHandlerWOHwAccess; + UINT_32 i; + UINT_32 u4NumOfElem; + + if (fgSetInfo) { + apfnOidHandlerWOHwAccess = apfnOidSetHandlerWOHwAccess; + u4NumOfElem = sizeof(apfnOidSetHandlerWOHwAccess) / sizeof(PFN_OID_HANDLER_FUNC); + } else { + apfnOidHandlerWOHwAccess = apfnOidQueryHandlerWOHwAccess; + u4NumOfElem = sizeof(apfnOidQueryHandlerWOHwAccess) / sizeof(PFN_OID_HANDLER_FUNC); + } + + for (i = 0; i < u4NumOfElem; i++) { + if (apfnOidHandlerWOHwAccess[i] == pfnOidHandler) + return FALSE; + } + + return TRUE; +} /* wlanIsHandlerNeedHwAccess */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set flag for later handling card +* ejected event. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +* +* \note When surprised removal happens, Glue layer should invoke this +* function to notify WPDD not to do any hw access. +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanCardEjected(IN P_ADAPTER_T prAdapter) +{ + DEBUGFUNC("wlanCardEjected"); + /* INITLOG(("\n")); */ + + ASSERT(prAdapter); + + /* mark that the card is being ejected, NDIS will shut us down soon */ + nicTxRelease(prAdapter); + +} /* wlanCardEjected */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Create adapter object +* +* \param prAdapter This routine is call to allocate the driver software objects. +* If fails, return NULL. +* \retval NULL If it fails, NULL is returned. +* \retval NOT NULL If the adapter was initialized successfully. +*/ +/*----------------------------------------------------------------------------*/ +P_ADAPTER_T wlanAdapterCreate(IN P_GLUE_INFO_T prGlueInfo) +{ + P_ADAPTER_T prAdpater = (P_ADAPTER_T) NULL; + + DEBUGFUNC("wlanAdapterCreate"); + + do { + prAdpater = (P_ADAPTER_T) kalMemAlloc(sizeof(ADAPTER_T), VIR_MEM_TYPE); + + if (!prAdpater) { + DBGLOG(INIT, ERROR, "Allocate ADAPTER memory ==> FAILED\n"); + break; + } + + kalMemZero(prAdpater, sizeof(ADAPTER_T)); + prAdpater->prGlueInfo = prGlueInfo; + + } while (FALSE); + + return prAdpater; +} /* wlanAdapterCreate */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Destroy adapter object +* +* \param prAdapter This routine is call to destroy the driver software objects. +* If fails, return NULL. +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanAdapterDestroy(IN P_ADAPTER_T prAdapter) +{ + + if (!prAdapter) + return; + + kalMemFree(prAdapter, VIR_MEM_TYPE, sizeof(ADAPTER_T)); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Initialize the adapter. The sequence is +* 1. Disable interrupt +* 2. Read adapter configuration from EEPROM and registry, verify chip ID. +* 3. Create NIC Tx/Rx resource. +* 4. Initialize the chip +* 5. Initialize the protocol +* 6. Enable Interrupt +* +* \param prAdapter Pointer of Adapter Data Structure +* +* \retval WLAN_STATUS_SUCCESS: Success +* \retval WLAN_STATUS_FAILURE: Failed +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanAdapterStart(IN P_ADAPTER_T prAdapter, + IN P_REG_INFO_T prRegInfo, IN PVOID pvFwImageMapFile, IN UINT_32 u4FwImageFileLength) +{ + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + UINT_32 i, u4Value = 0; + UINT_32 u4WHISR = 0; + UINT_32 u4Time, u4Current; + UINT_8 aucTxCount[8]; +#if CFG_ENABLE_FW_DOWNLOAD + UINT_32 u4FwLoadAddr, u4ImgSecSize; + BOOLEAN fgFWDLDumped = FALSE; +#if CFG_ENABLE_FW_DIVIDED_DOWNLOAD + UINT_32 j; + P_FIRMWARE_DIVIDED_DOWNLOAD_T prFwHead; + BOOLEAN fgValidHead; + const UINT_32 u4CRCOffset = offsetof(FIRMWARE_DIVIDED_DOWNLOAD_T, u4NumOfEntries); +#endif +#endif + enum Adapter_Start_Fail_Reason { + ALLOC_ADAPTER_MEM_FAIL, + DRIVER_OWN_FAIL, + INIT_ADAPTER_FAIL, + RAM_CODE_DOWNLOAD_FAIL, + WAIT_FIRMWARE_READY_FAIL, + FAIL_REASON_MAX + } eFailReason; + + ASSERT(prAdapter); + + DEBUGFUNC("wlanAdapterStart"); + + eFailReason = FAIL_REASON_MAX; + /* 4 <0> Reset variables in ADAPTER_T */ + prAdapter->fgIsFwOwn = TRUE; + prAdapter->fgIsEnterD3ReqIssued = FALSE; + + QUEUE_INITIALIZE(&(prAdapter->rPendingCmdQueue)); + + /* Initialize rWlanInfo */ + kalMemSet(&(prAdapter->rWlanInfo), 0, sizeof(WLAN_INFO_T)); + + /* 4 <0.1> reset fgIsBusAccessFailed */ + fgIsBusAccessFailed = FALSE; + prAdapter->ulSuspendFlag = 0; + + do { + u4Status = nicAllocateAdapterMemory(prAdapter); + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "nicAllocateAdapterMemory Error!\n"); + u4Status = WLAN_STATUS_FAILURE; + eFailReason = ALLOC_ADAPTER_MEM_FAIL; +#if CFG_ENABLE_KEYWORD_EXCEPTION_MECHANISM + mtk_wcn_wmt_assert_keyword(WMTDRV_TYPE_WIFI, + "[Wi-Fi On] nicAllocateAdapterMemory Error!"); +#endif + break; + } + + prAdapter->u4OsPacketFilter = PARAM_PACKET_FILTER_SUPPORTED; + + DBGLOG(INIT, TRACE, "wlanAdapterStart(): Acquiring LP-OWN %d\n", fgIsResetting); + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + +#if !CFG_ENABLE_FULL_PM + nicpmSetDriverOwn(prAdapter); +#endif + + if (prAdapter->fgIsFwOwn == TRUE) { + DBGLOG(INIT, ERROR, "nicpmSetDriverOwn() failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + eFailReason = DRIVER_OWN_FAIL; +#if CFG_ENABLE_KEYWORD_EXCEPTION_MECHANISM + mtk_wcn_wmt_assert_keyword(WMTDRV_TYPE_WIFI, + "[Wi-Fi On] nicpmSetDriverOwn() failed!"); +#endif + break; + } + /* 4 <1> Initialize the Adapter */ + u4Status = nicInitializeAdapter(prAdapter); + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "nicInitializeAdapter failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + eFailReason = INIT_ADAPTER_FAIL; + break; + } + + /* init wake lock before interrupt enable and tx thread */ + KAL_WAKE_LOCK_INIT(prAdapter, prAdapter->rTxThreadWakeLock, "WLAN TX THREAD"); + + /* 4 <2> Initialize System Service (MGMT Memory pool and STA_REC) */ + nicInitSystemService(prAdapter); + + /* 4 <3> Initialize Tx */ + nicTxInitialize(prAdapter); + wlanDefTxPowerCfg(prAdapter); + + /* 4 <4> Initialize Rx */ + nicRxInitialize(prAdapter); + +#if CFG_ENABLE_FW_DOWNLOAD + + prAdapter->prGlueInfo->fgIsFwDlDone = FALSE; + + wlanFWDLDebugInit(); + + if (pvFwImageMapFile == NULL) { + DBGLOG(INIT, ERROR, "No Firmware found!\n"); + u4Status = WLAN_STATUS_FAILURE; + eFailReason = RAM_CODE_DOWNLOAD_FAIL; + break; + } + + /* 1. disable interrupt, download is done by polling mode only */ + nicDisableInterrupt(prAdapter); + + /* 2. Initialize Tx Resource to fw download state */ + nicTxInitResetResource(prAdapter); + + /* 3. FW download here */ + u4FwLoadAddr = prRegInfo->u4LoadAddress; + +#if CFG_ENABLE_FW_DIVIDED_DOWNLOAD + /* 3a. parse file header for decision of divided firmware download or not */ + prFwHead = (P_FIRMWARE_DIVIDED_DOWNLOAD_T) pvFwImageMapFile; + + if (prFwHead->u4Signature == MTK_WIFI_SIGNATURE && + prFwHead->u4CRC == wlanCRC32((PUINT_8) pvFwImageMapFile + u4CRCOffset, + u4FwImageFileLength - u4CRCOffset)) { + fgValidHead = TRUE; + } else { + fgValidHead = FALSE; + } + + u4Time = kalGetTimeTick(); + + DBGLOG(INIT, INFO, " Start to download firmware, time=%u\n", + u4Time); + + /* 3b. engage divided firmware downloading */ + if (fgValidHead == TRUE) { + DBGLOG(INIT, TRACE, "wlanAdapterStart(): fgValidHead == TRUE\n"); + wlanDumpMcuChipId(prAdapter); + for (i = 0; i < prFwHead->u4NumOfEntries; i++) { + +#if CFG_START_ADDRESS_IS_1ST_SECTION_ADDR + if (i == 0) { + prRegInfo->u4StartAddress = prFwHead->arSection[i].u4DestAddr; + DBGLOG(INIT, TRACE, + "wlanAdapterStart(): FW start address 0x%08x\n", + prRegInfo->u4StartAddress); + } +#endif + +#if CFG_ENABLE_FW_DOWNLOAD_AGGREGATION + if (wlanImageSectionDownloadAggregated(prAdapter, + prFwHead->arSection[i].u4DestAddr, + prFwHead->arSection[i].u4Length, + (PUINT_8) pvFwImageMapFile + + prFwHead->arSection[i].u4Offset) != + WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "Firmware scatter download failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + } +#else + for (j = 0; j < prFwHead->arSection[i].u4Length; j += CMD_PKT_SIZE_FOR_IMAGE) { + if (j + CMD_PKT_SIZE_FOR_IMAGE < prFwHead->arSection[i].u4Length) + u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; + else + u4ImgSecSize = prFwHead->arSection[i].u4Length - j; + + wlanFWDLDebugStartSectionPacketInfo(i, j, kalGetTimeTick()); + + if (wlanImageSectionDownload(prAdapter, + prFwHead->arSection[i].u4DestAddr + j, + u4ImgSecSize, + (PUINT_8) pvFwImageMapFile + + prFwHead->arSection[i].u4Offset + j) != + WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "Firmware scatter download failed %d!\n", (int)i); + u4Status = WLAN_STATUS_FAILURE; + break; + } + + /* timeout exceeding check, dump FWDL log if timeout (>2.5s) */ + u4Current = kalGetTimeTick(); + if ((u4Current > u4Time) && + ((u4Current - u4Time) > WLAN_DOWNLOAD_IMAGE_TIMEOUT) && + (fgFWDLDumped == FALSE)) { + DBGLOG(INIT, ERROR, "FW download timeout > 2.5s, FWDL dump info(%u)\n", + wlanFWDLDebugGetPktCnt()); + wlanFWDLDebugDumpInfo(); + fgFWDLDumped = TRUE; + } + } +#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; + + wlanFWDLDebugStartSectionPacketInfo(0, i, kalGetTimeTick()); + + 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; + } + + /* timeout exceeding check, dump FWDL log if timeout (>2.5s) */ + u4Current = kalGetTimeTick(); + if ((u4Current > u4Time) && + ((u4Current - u4Time) > WLAN_DOWNLOAD_IMAGE_TIMEOUT) && + (fgFWDLDumped == FALSE)) { + DBGLOG(INIT, ERROR, "FW download timeout > 2.5s, FWDL dump info! Pkt Cnt=%u\n", + wlanFWDLDebugGetPktCnt()); + wlanFWDLDebugDumpInfo(); + fgFWDLDumped = TRUE; + } + } +#endif + + DBGLOG(INIT, INFO, " Download FW done, total cnt11=%u spend time=%u\n", + wlanFWDLDebugGetPktCnt(), kalGetTimeTick() - u4Time); + + wlanFWDLDebugUninit(); + + if (u4Status != WLAN_STATUS_SUCCESS) { + eFailReason = RAM_CODE_DOWNLOAD_FAIL; + break; + } +#if !CFG_ENABLE_FW_DOWNLOAD_ACK + /* Send INIT_CMD_ID_QUERY_PENDING_ERROR command and wait for response */ + if (wlanImageQueryStatus(prAdapter) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "Firmware download failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } +#endif + + /* 4. send Wi-Fi Start command */ + DBGLOG(INIT, INFO, " send Wi-Fi Start command\n"); +#if CFG_OVERRIDE_FW_START_ADDRESS + wlanConfigWifiFunc(prAdapter, TRUE, prRegInfo->u4StartAddress); +#else + wlanConfigWifiFunc(prAdapter, FALSE, 0); +#endif +#endif + + DBGLOG(INIT, TRACE, "wlanAdapterStart(): Waiting for Ready bit..\n"); + /* 4 <5> check Wi-Fi FW asserts ready bit */ + i = 0; + while (1) { + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4Value); + + if (u4Value & WCIR_WLAN_READY) { + DBGLOG(INIT, TRACE, "Ready bit asserted\n"); + break; + } else if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + eFailReason = WAIT_FIRMWARE_READY_FAIL; + break; + } else if (i >= CFG_RESPONSE_POLLING_TIMEOUT) { + UINT_32 u4MailBox0; + + nicGetMailbox(prAdapter, 0, &u4MailBox0); + DBGLOG(INIT, ERROR, "Waiting for Ready bit: Timeout, ID=%u\n", + (u4MailBox0 & 0x0000FFFF)); + u4Status = WLAN_STATUS_FAILURE; + eFailReason = WAIT_FIRMWARE_READY_FAIL; + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP | RST_FLAG_PREVENT_POWER_OFF); + break; + } + i++; + kalMsleep(10); + } + + prAdapter->prGlueInfo->fgIsFwDlDone = TRUE; + + if (u4Status == WLAN_STATUS_SUCCESS) { + /* 1. reset interrupt status */ + HAL_READ_INTR_STATUS(prAdapter, 4, (PUINT_8)&u4WHISR); + if (HAL_IS_TX_DONE_INTR(u4WHISR)) + HAL_READ_TX_RELEASED_COUNT(prAdapter, aucTxCount); + + /* 2. reset TX Resource for normal operation */ + nicTxResetResource(prAdapter); + + /* 3. query for permanent address by polling */ + wlanQueryPermanentAddress(prAdapter); + +#if (CFG_SUPPORT_NIC_CAPABILITY == 1) + /* 4. query for NIC capability */ + wlanQueryNicCapability(prAdapter); +#endif + /* 4.1 query for compiler flags */ + wlanQueryCompileFlags(prAdapter); + + /* 5. Override network address */ + wlanUpdateNetworkAddress(prAdapter); + + /* 6. indicate disconnection as default status */ + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + } + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + + if (u4Status != WLAN_STATUS_SUCCESS) { + eFailReason = WAIT_FIRMWARE_READY_FAIL; + break; + } + + /* OID timeout timer initialize */ + cnmTimerInitTimer(prAdapter, + &prAdapter->rOidTimeoutTimer, + (PFN_MGMT_TIMEOUT_FUNC) wlanReleasePendingOid, (ULONG) NULL); + + /* Return Indicated Rfb list timer */ + cnmTimerInitTimer(prAdapter, + &prAdapter->rReturnIndicatedRfbListTimer, + (PFN_MGMT_TIMEOUT_FUNC) wlanReturnIndicatedPacketsTimeOut, (ULONG) NULL); + + /* Power state initialization */ + prAdapter->fgWiFiInSleepyState = FALSE; + prAdapter->rAcpiState = ACPI_STATE_D0; + + /* Online scan option */ + if (prRegInfo->fgDisOnlineScan == 0) + prAdapter->fgEnOnlineScan = TRUE; + else + prAdapter->fgEnOnlineScan = FALSE; + + /* Beacon lost detection option */ + if (prRegInfo->fgDisBcnLostDetection != 0) + prAdapter->fgDisBcnLostDetection = TRUE; + + /* Load compile time constant */ + prAdapter->rWlanInfo.u2BeaconPeriod = CFG_INIT_ADHOC_BEACON_INTERVAL; + prAdapter->rWlanInfo.u2AtimWindow = CFG_INIT_ADHOC_ATIM_WINDOW; + +#if 1 /* set PM parameters */ + prAdapter->fgEnArpFilter = prRegInfo->fgEnArpFilter; + prAdapter->u4PsCurrentMeasureEn = prRegInfo->u4PsCurrentMeasureEn; + + prAdapter->u4UapsdAcBmp = prRegInfo->u4UapsdAcBmp; + + prAdapter->u4MaxSpLen = prRegInfo->u4MaxSpLen; + + DBGLOG(INIT, TRACE, "[1] fgEnArpFilter:0x%x, u4UapsdAcBmp:0x%x, u4MaxSpLen:0x%x", + prAdapter->fgEnArpFilter, prAdapter->u4UapsdAcBmp, prAdapter->u4MaxSpLen); + + prAdapter->fgEnCtiaPowerMode = FALSE; + +#if CFG_SUPPORT_DBG_POWERMODE + prAdapter->fgEnDbgPowerMode = FALSE; +#endif + +#endif + + /* MGMT Initialization */ + nicInitMGMT(prAdapter, prRegInfo); + /* NCHO Initialization */ +#if CFG_SUPPORT_NCHO + prAdapter->rNchoInfo.fgECHOEnabled = FALSE; + prAdapter->rNchoInfo.eBand = NCHO_BAND_AUTO; + prAdapter->rNchoInfo.fgChGranted = FALSE; + prAdapter->rNchoInfo.fgIsSendingAF = FALSE; + prAdapter->rNchoInfo.u4RoamScanControl = FALSE; + prAdapter->rNchoInfo.rRoamScnChnl.ucChannelListNum = 0; + prAdapter->rNchoInfo.rRoamScnChnl.arChnlInfoList[0].eBand = BAND_2G4; + prAdapter->rNchoInfo.rRoamScnChnl.arChnlInfoList[0].ucChannelNum = 1; + prAdapter->rNchoInfo.eDFSScnMode = NCHO_DFS_SCN_ENABLE1; + prAdapter->rNchoInfo.i4RoamTrigger = -70; + prAdapter->rNchoInfo.i4RoamDelta = 5; + prAdapter->rNchoInfo.u4RoamScanPeriod = ROAMING_DISCOVERY_TIMEOUT_SEC; + prAdapter->rNchoInfo.u4ScanChannelTime = 50; + prAdapter->rNchoInfo.u4ScanHomeTime = 120; + prAdapter->rNchoInfo.u4ScanHomeawayTime = 120; + prAdapter->rNchoInfo.u4ScanNProbes = 2; + prAdapter->rNchoInfo.u4WesMode = 0; +#endif + + /* 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; + +#if CFG_RX_BA_REORDERING_ENHANCEMENT + /* Enable drop independent packets with Rx Ba reordering */ + prAdapter->rWifiVar.fgEnableReportIndependentPkt = TRUE; +#endif + + /* configure available PHY type set */ + nicSetAvailablePhyTypeSet(prAdapter); + +#ifdef CFG_TC1_FEATURE /* for Passive Scan */ + prAdapter->ucScanType = SCAN_TYPE_ACTIVE_SCAN; +#endif + +#if 1 /* set PM parameters */ + { +#if CFG_SUPPORT_PWR_MGT + prAdapter->u4PowerMode = prRegInfo->u4PowerMode; + prAdapter->rWlanInfo.arPowerSaveMode[NETWORK_TYPE_P2P_INDEX].ucNetTypeIndex = + NETWORK_TYPE_P2P_INDEX; + prAdapter->rWlanInfo.arPowerSaveMode[NETWORK_TYPE_P2P_INDEX].ucPsProfile = ENUM_PSP_FAST_SWITCH; +#else + prAdapter->u4PowerMode = ENUM_PSP_CONTINUOUS_ACTIVE; +#endif + + nicConfigPowerSaveProfile(prAdapter, NETWORK_TYPE_AIS_INDEX, /* FIXIT */ + prAdapter->u4PowerMode, FALSE); + } + +#endif + +#if CFG_SUPPORT_NVRAM + /* load manufacture data */ + wlanLoadManufactureData(prAdapter, prRegInfo); +#endif + +#if CFG_TC1_FEATURE /* 1 //keep alive packet time change from default 30secs to 20secs. //TC01// */ + { + CMD_SW_DBG_CTRL_T rCmdSwCtrl; + + rCmdSwCtrl.u4Id = 0x90100000; + rCmdSwCtrl.u4Data = 30; + DBGLOG(INIT, TRACE, "wlanAdapterStart Keepaliveapcket 0x%x, %d\n", + rCmdSwCtrl.u4Id, rCmdSwCtrl.u4Data); + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, + NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8) (&rCmdSwCtrl), NULL, 0); + } +#endif +#if (CFG_SRAM_SIZE_OPTION == 1 || CFG_SRAM_SIZE_OPTION == 0) + /* ALPS02494017 for DIR-635/DIR-655 IOT issue (BA size must be power of 2) */ + nicQmSetRxBASize(prAdapter, true, IOT_RX_BA_SIZE); +#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 + + prAdapter->u4QmRxBaMissTimeout = DEFAULT_QM_RX_BA_ENTRY_MISS_TIMEOUT_MS; + prAdapter->fgEnCfg80211Scan = TRUE; + +#if CFG_SUPPORT_GAMING_MODE + prAdapter->fgEnGamingMode = FALSE; +#endif +#if CFG_SUPPORT_OSHARE + prAdapter->fgEnOshareMode = FALSE; +#endif + } while (FALSE); + + if (u4Status == WLAN_STATUS_SUCCESS) { + /* restore to hardware default */ + HAL_SET_INTR_STATUS_READ_CLEAR(prAdapter); + HAL_SET_MAILBOX_READ_CLEAR(prAdapter, FALSE); + + /* Enable interrupt */ + nicEnableInterrupt(prAdapter); + + } else { + /* release allocated memory */ + switch (eFailReason) { + case WAIT_FIRMWARE_READY_FAIL: + DBGLOG(INIT, ERROR, "Wait firmware ready fail, FailReason: %d\n", + eFailReason); + kalSendAeeWarning("[Wait firmware ready fail!]", __func__); + KAL_WAKE_LOCK_DESTROY(prAdapter, prAdapter->rTxThreadWakeLock); + nicRxUninitialize(prAdapter); + nicTxRelease(prAdapter); + /* System Service Uninitialization */ + nicUninitSystemService(prAdapter); + nicReleaseAdapterMemory(prAdapter); + break; + case RAM_CODE_DOWNLOAD_FAIL: + DBGLOG(INIT, ERROR, "Ram code download fail, FailReason: %d\n", + eFailReason); + kalSendAeeWarning("[Ram code download fail!]", __func__); + KAL_WAKE_LOCK_DESTROY(prAdapter, prAdapter->rTxThreadWakeLock); + nicRxUninitialize(prAdapter); + nicTxRelease(prAdapter); + /* System Service Uninitialization */ + nicUninitSystemService(prAdapter); + nicReleaseAdapterMemory(prAdapter); + break; + case INIT_ADAPTER_FAIL: + nicReleaseAdapterMemory(prAdapter); + break; + case DRIVER_OWN_FAIL: + nicReleaseAdapterMemory(prAdapter); + break; + case ALLOC_ADAPTER_MEM_FAIL: + break; + default: + break; + } + } + + return u4Status; +} /* wlanAdapterStart */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Uninitialize the adapter +* +* \param prAdapter Pointer of Adapter Data Structure +* +* \retval WLAN_STATUS_SUCCESS: Success +* \retval WLAN_STATUS_FAILURE: Failed +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanAdapterStop(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i, u4Value = 0; + UINT_32 u4CurrTick; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + if (prAdapter->fgIsClockGatingEnabled == TRUE) + nicDisableClockGating(prAdapter); +#endif + + if (prAdapter->rAcpiState == ACPI_STATE_D0 && +#if (CFG_CHIP_RESET_SUPPORT == 1) + kalIsResetting() == FALSE && +#endif + kalIsCardRemoved(prAdapter->prGlueInfo) == FALSE) { + + /* 0. Disable interrupt, this can be done without Driver own */ + nicDisableInterrupt(prAdapter); + + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + /* 1. Set CMD to FW to tell WIFI to stop (enter power off state) */ + /* the command must be issue to firmware even in wlanRemove() */ + if (prAdapter->fgIsFwOwn == FALSE && wlanSendNicPowerCtrlCmd(prAdapter, 1) == WLAN_STATUS_SUCCESS) { + /* 2. Clear pending interrupt */ + i = 0; + while (i < CFG_IST_LOOP_COUNT && nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) { + i++; + }; + + /* 3. Wait til RDY bit has been cleaerd */ + u4CurrTick = kalGetTimeTick(); + while (1) { + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4Value); + + if ((u4Value & WCIR_WLAN_READY) == 0) + break; + else if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE || + CHECK_FOR_TIMEOUT(kalGetTimeTick(), u4CurrTick, WLAN_WAIT_READY_BIT_TIMEOUT)) { + wlanDumpCommandFwStatus(); + wlanDumpTcResAndTxedCmd(NULL, 0); + cmdBufDumpCmdQueue(&prAdapter->rPendingCmdQueue, "waiting response CMD queue"); + glDumpConnSysCpuInfo(prAdapter->prGlueInfo); + /* dump TC4[0] ~ TC4[3] TX_DESC */ + wlanDebugHifDescriptorDump(prAdapter, MTK_AMPDU_TX_DESC, DEBUG_TC4_INDEX); +#if CFG_ENABLE_KEYWORD_EXCEPTION_MECHANISM + mtk_wcn_wmt_assert_keyword(WMTDRV_TYPE_WIFI, + "[Wi-Fi On] [Read WCIR_WLAN_READY fail!]"); +#else + kalSendAeeWarning("[Read WCIR_WLAN_READY fail!]", __func__); +#endif + break; + } + } + } + + /* 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); + + /* MGMT - unitialization */ + nicUninitMGMT(prAdapter); + + /* System Service Uninitialization */ + nicUninitSystemService(prAdapter); + + nicReleaseAdapterMemory(prAdapter); + +#if defined(_HIF_SPI) + /* Note: restore the SPI Mode Select from 32 bit to default */ + nicRestoreSpiDefMode(prAdapter); +#endif + + return u4Status; +} /* wlanAdapterStop */ + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called by ISR (interrupt). +* +* \param prAdapter Pointer of Adapter Data Structure +* +* \retval TRUE: NIC's interrupt +* \retval FALSE: Not NIC's interrupt +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanISR(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgGlobalIntrCtrl) +{ + ASSERT(prAdapter); + + if (fgGlobalIntrCtrl) { + nicDisableInterrupt(prAdapter); + + /* wlanIST(prAdapter); */ + } + + return TRUE; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called by IST (task_let). +* +* \param prAdapter Pointer of Adapter Data Structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanIST(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + /* wake up CONNSYS */ + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + /* handle interrupts */ + nicProcessIST(prAdapter); + + /* re-enable HIF interrupts */ + nicEnableInterrupt(prAdapter); + + /* CONNSYS can decide to sleep */ + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will check command queue to find out if any could be dequeued +* and/or send to HIF to MT6620 +* +* \param prAdapter Pointer of Adapter Data Structure +* \param prCmdQue Pointer of Command Queue (in Glue Layer) +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanProcessCommandQueue(IN P_ADAPTER_T prAdapter, IN P_QUE_T prCmdQue) +{ + WLAN_STATUS rStatus; + QUE_T rTempCmdQue, rMergeCmdQue, rStandInCmdQue; + P_QUE_T prTempCmdQue, prMergeCmdQue, prStandInCmdQue; + P_QUE_ENTRY_T prQueueEntry; + P_CMD_INFO_T prCmdInfo; + P_MSDU_INFO_T prMsduInfo; + ENUM_FRAME_ACTION_T eFrameAction = FRAME_ACTION_DROP_PKT; + + KAL_SPIN_LOCK_DECLARATION(); + + /* sanity check */ + ASSERT(prAdapter); + ASSERT(prCmdQue); + + /* init */ + prTempCmdQue = &rTempCmdQue; + prMergeCmdQue = &rMergeCmdQue; + prStandInCmdQue = &rStandInCmdQue; + + QUEUE_INITIALIZE(prTempCmdQue); + QUEUE_INITIALIZE(prMergeCmdQue); + QUEUE_INITIALIZE(prStandInCmdQue); + + /* 4 <1> Move whole list of CMD_INFO to the temp queue */ + /* copy all commands to prTempCmdQue and empty prCmdQue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_QUE); + + /* 4 <2> Dequeue from head and check it is able to be sent */ + /* remove the first one */ + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + /* check how to handle the command: drop, queue, or tx */ + switch (prCmdInfo->eCmdType) { + case COMMAND_TYPE_KEY_IOCTL: + { + P_WIFI_CMD_T prWifiCmd = (P_WIFI_CMD_T) NULL; + P_CMD_802_11_KEY prKey = (P_CMD_802_11_KEY) NULL; + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; + + eFrameAction = FRAME_ACTION_TX_PKT; + do { + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prKey = (P_CMD_802_11_KEY) (prWifiCmd->aucBuffer); + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prKey->ucNetType]; + + /* TODO: only handle p2p case */ + if (prKey->ucNetType != NETWORK_TYPE_P2P_INDEX || + prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE || + prBssInfo->eConnectionState != PARAM_MEDIA_STATE_CONNECTED) + break; + if (!prKey->ucTxKey || + (prKey->ucAlgorithmId != CIPHER_SUITE_TKIP && + prKey->ucAlgorithmId != CIPHER_SUITE_CCMP)) + break; + switch (prBssInfo->eKeyAction) { + case SEC_DROP_KEY_COMMAND: + eFrameAction = FRAME_ACTION_DROP_PKT; + break; + case SEC_QUEUE_KEY_COMMAND: + eFrameAction = FRAME_ACTION_QUEUE_PKT; + break; + case SEC_TX_KEY_COMMAND: + eFrameAction = FRAME_ACTION_TX_PKT; + break; + default: + break; + } + DBGLOG(TX, INFO, "Add Key eKeyAction: %d\n", eFrameAction); + } while (FALSE); + break; + } + case COMMAND_TYPE_GENERAL_IOCTL: + case COMMAND_TYPE_NETWORK_IOCTL: + /* command packet will be always sent */ + eFrameAction = FRAME_ACTION_TX_PKT; + break; + + case COMMAND_TYPE_SECURITY_FRAME: + /* inquire with QM */ + eFrameAction = qmGetFrameAction(prAdapter, + prCmdInfo->eNetworkType, + prCmdInfo->ucStaRecIndex, NULL, FRAME_TYPE_802_1X); + break; + + case COMMAND_TYPE_MANAGEMENT_FRAME: + /* inquire with QM */ + prMsduInfo = (P_MSDU_INFO_T) (prCmdInfo->prPacket); + + eFrameAction = qmGetFrameAction(prAdapter, + prMsduInfo->ucNetworkType, + prMsduInfo->ucStaRecIndex, prMsduInfo, FRAME_TYPE_MMPDU); + break; + + default: + ASSERT(0); + break; + } + + /* 4 <3> handling upon dequeue result */ + if (eFrameAction == FRAME_ACTION_DROP_PKT) { + if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) + DBGLOG(TX, WARN, "Drop Security frame seqNo=%d\n", + prCmdInfo->ucCmdSeqNum); + wlanReleaseCommand(prAdapter, prCmdInfo); + } else if (eFrameAction == FRAME_ACTION_QUEUE_PKT) { + if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) + DBGLOG(TX, INFO, "Queue Security frame seqNo=%d\n", + prCmdInfo->ucCmdSeqNum); + QUEUE_INSERT_TAIL(prMergeCmdQue, prQueueEntry); + } else if (eFrameAction == FRAME_ACTION_TX_PKT) { + /* 4 <4> Send the command */ + rStatus = wlanSendCommand(prAdapter, prCmdInfo); + + if (rStatus == WLAN_STATUS_RESOURCES) { + QUEUE_INSERT_TAIL(prMergeCmdQue, prQueueEntry); + DBGLOGLIMITED(TX, INFO, + "No TC4 resource to send cmd, CID=0x%x, SEQ=%d, CMD type=%d, OID=%d\n", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum, + prCmdInfo->eCmdType, prCmdInfo->fgIsOid); + + /* + * We reserve one TC4 resource for CMD specially, only break + * checking the left tx request if no resource for true CMD. + */ + if ((prCmdInfo->eCmdType != COMMAND_TYPE_SECURITY_FRAME) && + (prCmdInfo->eCmdType != COMMAND_TYPE_MANAGEMENT_FRAME)) + break; + } else if (rStatus == WLAN_STATUS_PENDING) { + /* command packet which needs further handling upon response */ + /* i.e. we need to wait for FW's response */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + QUEUE_INSERT_TAIL(&(prAdapter->rPendingCmdQueue), prQueueEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + } else { + /* send success or fail */ + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + if (rStatus == WLAN_STATUS_SUCCESS) { + /* send success */ + if (prCmdInfo->pfCmdDoneHandler) { + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, + prCmdInfo->pucInfoBuffer); + } +#if CFG_SUPPORT_FCC_POWER_BACK_OFF + else + nicCmdEventSetCommon(prAdapter, prCmdInfo, + prCmdInfo->pucInfoBuffer); +#endif + } else { + /* send fail */ + if (prCmdInfo->fgIsOid) { + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, + prCmdInfo->u4SetInfoLen, rStatus); + } + DBGLOG(TX, WARN, "Send CMD, status=%u, CID=%d, SEQ=%d, CMD type=%d, OID=%d\n", + rStatus, prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum, + prCmdInfo->eCmdType, prCmdInfo->fgIsOid); + } + + /* free the command memory */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + } else { + + /* impossible, wrong eFrameAction */ + ASSERT(0); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + /* 4 <3> Merge back to original queue */ + /* 4 <3.1> Merge prMergeCmdQue & prTempCmdQue */ + QUEUE_CONCATENATE_QUEUES(prMergeCmdQue, prTempCmdQue); + + /* 4 <3.2> Move prCmdQue to prStandInQue, due to prCmdQue might differ due to incoming 802.1X frames */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_QUE); + + /* ??? here, prCmdQue shall be empty, why QUEUE_MOVE_ALL ??? */ + QUEUE_MOVE_ALL(prStandInCmdQue, prCmdQue); + + /* 4 <3.3> concatenate prStandInQue to prMergeCmdQue */ + QUEUE_CONCATENATE_QUEUES(prMergeCmdQue, prStandInCmdQue); + + /* 4 <3.4> then move prMergeCmdQue to prCmdQue */ + QUEUE_MOVE_ALL(prCmdQue, prMergeCmdQue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_QUE); + + return WLAN_STATUS_SUCCESS; +} /* end of wlanProcessCommandQueue() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will take CMD_INFO_T which carry some information of +* incoming OID and notify the NIC_TX to send CMD. +* +* \param prAdapter Pointer of Adapter Data Structure +* \param prCmdInfo Pointer of P_CMD_INFO_T +* +* \retval WLAN_STATUS_SUCCESS : CMD was written to HIF and be freed(CMD Done) immediately. +* \retval WLAN_STATUS_RESOURCE : No resource for current command, need to wait for previous +* frame finishing their transmission. +* \retval WLAN_STATUS_FAILURE : Get failure while access HIF or been rejected. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanSendCommand(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + P_TX_CTRL_T prTxCtrl; + UINT_8 ucTC; /* "Traffic Class" SW(Driver) resource classification */ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + BOOLEAN pfgIsSecOrMgmt = FALSE; + + /* sanity check */ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + /* init */ + prTxCtrl = &prAdapter->rTxCtrl; + + /* DbgPrint("wlanSendCommand()\n"); */ + /* */ + /* */ +#if DBG && 0 + LOG_FUNC("wlanSendCommand()\n"); + LOG_FUNC("CmdType %u NetworkType %u StaRecIndex %u Oid %u CID 0x%x SetQuery %u NeedResp %u CmdSeqNum %u\n", + prCmdInfo->eCmdType, + prCmdInfo->eNetworkType, + prCmdInfo->ucStaRecIndex, + prCmdInfo->fgIsOid, + prCmdInfo->ucCID, prCmdInfo->fgSetQuery, prCmdInfo->fgNeedResp, prCmdInfo->ucCmdSeqNum); +#endif + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + if (prAdapter->fgIsClockGatingEnabled == TRUE) + nicDisableClockGating(prAdapter); +#endif + + do { + /* <0> card removal check */ + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + rStatus = WLAN_STATUS_FAILURE; + break; + } + /* <1> Normal case of sending CMD Packet */ + if (!prCmdInfo->fgDriverDomainMCR) { + /* <1.1> Assign Traffic Class(TC) = TC4. */ + ucTC = TC4_INDEX; + + if ((prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) || + (prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME)) + pfgIsSecOrMgmt = TRUE; + + wlanReadFwStatus(prAdapter); + /* <1.2> Check if pending packet or resource was exhausted */ + rStatus = nicTxAcquireResource(prAdapter, ucTC, pfgIsSecOrMgmt); + if (rStatus == WLAN_STATUS_RESOURCES) { + DbgPrint("NO Resource:%d\n", ucTC); + break; + } + /* <1.3> Forward CMD_INFO_T to NIC Layer */ + rStatus = nicTxCmd(prAdapter, prCmdInfo, ucTC); + + /* <1.4> Set Pending in response to Query Command/Need Response */ + if (rStatus == WLAN_STATUS_SUCCESS) { + if ((!prCmdInfo->fgSetQuery) || (prCmdInfo->fgNeedResp)) + rStatus = WLAN_STATUS_PENDING; + } + } + /* <2> "Special case" for access Driver Domain MCR */ + else { + + P_CMD_ACCESS_REG prCmdAccessReg; + + prCmdAccessReg = (P_CMD_ACCESS_REG) (prCmdInfo->pucInfoBuffer + CMD_HDR_SIZE); + + if (prCmdInfo->fgSetQuery) { + /* address is in DWORD unit */ + HAL_MCR_WR(prAdapter, (prCmdAccessReg->u4Address & BITS(2, 31)), + prCmdAccessReg->u4Data); + } else { + P_CMD_ACCESS_REG prEventAccessReg; + UINT_32 u4Address; + + u4Address = prCmdAccessReg->u4Address; + prEventAccessReg = (P_CMD_ACCESS_REG) prCmdInfo->pucInfoBuffer; + prEventAccessReg->u4Address = u4Address; + /* address is in DWORD unit */ + HAL_MCR_RD(prAdapter, prEventAccessReg->u4Address & BITS(2, 31), + &prEventAccessReg->u4Data); + } + } + + } while (FALSE); + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + if (prAdapter->fgIsClockGatingEnabled == FALSE) + nicEnableClockGating(prAdapter); +#endif + + return rStatus; +} /* end of wlanSendCommand() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will release thd CMD_INFO upon its attribution + * + * \param prAdapter Pointer of Adapter Data Structure + * \param prCmdInfo Pointer of CMD_INFO_T + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +VOID wlanReleaseCommand(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + P_TX_CTRL_T prTxCtrl; + P_MSDU_INFO_T prMsduInfo; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prTxCtrl = &prAdapter->rTxCtrl; + + switch (prCmdInfo->eCmdType) { + case COMMAND_TYPE_GENERAL_IOCTL: + case COMMAND_TYPE_NETWORK_IOCTL: + if (prCmdInfo->fgIsOid) { + /* for OID command, we need to do complete() to wake up kalIoctl() */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, WLAN_STATUS_FAILURE); + } + break; + + case COMMAND_TYPE_SECURITY_FRAME: + /* free packets in kalSecurityFrameSendComplete() */ + kalSecurityFrameSendComplete(prAdapter->prGlueInfo, prCmdInfo->prPacket, WLAN_STATUS_FAILURE); + break; + + case COMMAND_TYPE_MANAGEMENT_FRAME: + prMsduInfo = (P_MSDU_INFO_T) prCmdInfo->prPacket; + + /* invoke callbacks */ + if (prMsduInfo->pfTxDoneHandler != NULL) + prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_DROPPED_IN_DRIVER); + + GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum); + cnmMgtPktFree(prAdapter, prMsduInfo); + break; + + default: + /* impossible, shall not be here */ + ASSERT(0); + break; + } + + /* free command buffer and return the command header to command pool */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + +} /* end of wlanReleaseCommand() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will search the CMD Queue to look for the pending OID and +* compelete it immediately when system request a reset. +* +* \param prAdapter ointer of Adapter Data Structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanReleasePendingOid(IN P_ADAPTER_T prAdapter, IN ULONG ulData) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("wlanReleasePendingOid"); + + ASSERT(prAdapter); + + DBGLOG(OID, ERROR, "OID Timeout! Releasing pending OIDs ..\n"); + + do { + /* 1: Handle OID commands in pending queue */ + /* Clear Pending OID in prAdapter->rPendingCmdQueue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + + /* move all pending commands to prTempCmdQue and empty prCmdQue */ + prCmdQue = &prAdapter->rPendingCmdQueue; + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + + /* get first pending command */ + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + if (prCmdInfo->fgIsOid) { + if (prCmdInfo->pfCmdTimeoutHandler) { + prCmdInfo->pfCmdTimeoutHandler(prAdapter, prCmdInfo); + } else { + /* send complete() to wake up kalIoctl() */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, 0, WLAN_STATUS_FAILURE); + } + + /* free command memory */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } else { + /* nothing to do so re-queue it to prCmdQue */ + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + + /* 2: Clear pending OID staying in command queue */ + kalOidCmdClearance(prAdapter->prGlueInfo); + + /* 3: Do complete(), do we need this? because we have completed in kalOidComplete */ + kalOidClearance(prAdapter->prGlueInfo); + + } while (FALSE); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will search the CMD Queue to look for the pending CMD/OID for specific +* NETWORK TYPE and compelete it immediately when system request a reset. +* +* \param prAdapter ointer of Adapter Data Structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanReleasePendingCMDbyNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + /* only free commands from the network interface, AIS, P2P, or BOW */ + + do { + /* 1: Clear Pending OID in prAdapter->rPendingCmdQueue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + + prCmdQue = &prAdapter->rPendingCmdQueue; + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + DBGLOG(P2P, TRACE, "Pending CMD for Network Type:%d\n", prCmdInfo->eNetworkType); + + if (prCmdInfo->eNetworkType == eNetworkType) { + if (prCmdInfo->pfCmdTimeoutHandler) { + prCmdInfo->pfCmdTimeoutHandler(prAdapter, prCmdInfo); + } else + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, 0, WLAN_STATUS_FAILURE); + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } else { + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + + } while (FALSE); + +} /* wlanReleasePendingCMDbyNetwork */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Return the packet buffer and reallocate one to the RFB +* +* \param prAdapter Pointer of Adapter Data Structure +* \param pvPacket Pointer of returned packet +* +* \retval WLAN_STATUS_SUCCESS: Success +* \retval WLAN_STATUS_FAILURE: Failed +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanReturnPacket(IN P_ADAPTER_T prAdapter, IN PVOID pvPacket) +{ + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = NULL; + BOOLEAN fgIsUninitRfb = FALSE; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("wlanReturnPacket"); + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + /* free the packet */ + if (pvPacket) { + kalPacketFree(prAdapter->prGlueInfo, pvPacket); + RX_ADD_CNT(prRxCtrl, RX_DATA_RETURNED_COUNT, 1); +#if CFG_NATIVE_802_11 + if (GLUE_TEST_FLAG(prAdapter->prGlueInfo, GLUE_FLAG_HALT)) { + /*Todo:: nothing*/ + /*Todo:: nothing*/ + } +#endif + } + + /* free the packet control block */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rIndicatedRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + if (!prSwRfb) { + ASSERT(0); + return; + } + + if (nicRxSetupRFB(prAdapter, prSwRfb)) { + ASSERT(0); + /* return; // Don't return here or it would lost SwRfb --kc */ + if (!timerPendingTimer(&prAdapter->rReturnIndicatedRfbListTimer)) { + DBGLOG(RX, WARN, + "wlanReturnPacket, Start ReturnIndicatedRfbList Timer (%ds)\n", + RX_RETURN_INDICATED_RFB_TIMEOUT_SEC); + cnmTimerStartTimer(prAdapter, &prAdapter->rReturnIndicatedRfbListTimer, + SEC_TO_MSEC(RX_RETURN_INDICATED_RFB_TIMEOUT_SEC)); + } + fgIsUninitRfb = TRUE; + } + nicRxReturnRFBwithUninit(prAdapter, prSwRfb, fgIsUninitRfb); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Return the indicated packet buffer and reallocate one to the RFB +* +* \param prAdapter Pointer of Adapter Data Structure +* \param pvPacket Pointer of returned packet +* +* \retval WLAN_STATUS_SUCCESS: Success +* \retval WLAN_STATUS_FAILURE: Failed +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanReturnIndicatedPacketsTimeOut(IN P_ADAPTER_T prAdapter, IN ULONG ulData) +{ + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = NULL; + BOOLEAN fgIsUninitRfb = FALSE; + + KAL_SPIN_LOCK_DECLARATION(); + WLAN_STATUS status = WLAN_STATUS_SUCCESS; + P_QUE_T prQueList; + + DEBUGFUNC("wlanReturnIndicatedPacketsTimeOut"); + DBGLOG(RX, WARN, "wlanReturnIndicatedPacketsTimeOut"); + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + prQueList = &prRxCtrl->rIndicatedRfbList; + DBGLOG(RX, WARN, "IndicatedRfbList num = %u\n", (unsigned int)prQueList->u4NumElem); + + while (QUEUE_IS_NOT_EMPTY(&prRxCtrl->rIndicatedRfbList)) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rIndicatedRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + if (nicRxSetupRFB(prAdapter, prSwRfb)) { + status = WLAN_STATUS_RESOURCES; + ASSERT(0); + fgIsUninitRfb = TRUE; + } + nicRxReturnRFBwithUninit(prAdapter, prSwRfb, fgIsUninitRfb); + if (status == WLAN_STATUS_RESOURCES) + break; + } + if (status == WLAN_STATUS_RESOURCES) { + DBGLOG(RX, WARN, "Start ReturnIndicatedRfbList Timer (%ds)\n", RX_RETURN_INDICATED_RFB_TIMEOUT_SEC); + /* restart timer */ + cnmTimerStartTimer(prAdapter, + &prAdapter->rReturnIndicatedRfbListTimer, + SEC_TO_MSEC(RX_RETURN_INDICATED_RFB_TIMEOUT_SEC)); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a required function that returns information about +* the capabilities and status of the driver and/or its network adapter. +* +* \param[IN] prAdapter Pointer to the Adapter structure. +* \param[IN] pfnOidQryHandler Function pointer for the OID query handler. +* \param[IN] pvInfoBuf Points to a buffer for return the query information. +* \param[IN] u4QueryBufferLen Specifies the number of bytes at pvInfoBuf. +* \param[OUT] pu4QueryInfoLen Points to the number of bytes it written or is needed. +* +* \retval WLAN_STATUS_xxx Different WLAN_STATUS code returned by different handlers. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanQueryInformation(IN P_ADAPTER_T prAdapter, + IN PFN_OID_HANDLER_FUNC pfnOidQryHandler, + IN PVOID pvInfoBuf, IN UINT_32 u4InfoBufLen, OUT PUINT_32 pu4QryInfoLen) +{ + WLAN_STATUS status = WLAN_STATUS_FAILURE; + + ASSERT(prAdapter); + ASSERT(pu4QryInfoLen); + + /* ignore any OID request after connected, under PS current measurement mode */ + /* note: return WLAN_STATUS_FAILURE or WLAN_STATUS_SUCCESS for + * blocking OIDs during current measurement + */ + if (prAdapter->u4PsCurrentMeasureEn && + (prAdapter->prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_CONNECTED)) + return WLAN_STATUS_SUCCESS; +#if 1 + /* most OID handler will just queue a command packet */ + status = pfnOidQryHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4QryInfoLen); +#else + if (wlanIsHandlerNeedHwAccess(pfnOidQryHandler, FALSE)) { + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + /* Reset sleepy state */ + if (prAdapter->fgWiFiInSleepyState == TRUE) + prAdapter->fgWiFiInSleepyState = FALSE; + + status = pfnOidQryHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4QryInfoLen); + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + } else + status = pfnOidQryHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4QryInfoLen); +#endif + + return status; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a required function that allows bound protocol drivers, +* or NDIS, to request changes in the state information that the miniport +* maintains for particular object identifiers, such as changes in multicast +* addresses. +* +* \param[IN] prAdapter Pointer to the Glue info structure. +* \param[IN] pfnOidSetHandler Points to the OID set handlers. +* \param[IN] pvInfoBuf Points to a buffer containing the OID-specific data for the set. +* \param[IN] u4InfoBufLen Specifies the number of bytes at prSetBuffer. +* \param[OUT] pu4SetInfoLen Points to the number of bytes it read or is needed. +* +* \retval WLAN_STATUS_xxx Different WLAN_STATUS code returned by different handlers. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanSetInformation(IN P_ADAPTER_T prAdapter, + IN PFN_OID_HANDLER_FUNC pfnOidSetHandler, + IN PVOID pvInfoBuf, IN UINT_32 u4InfoBufLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS status = WLAN_STATUS_FAILURE; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* ignore any OID request after connected, under PS current measurement mode */ + /* note: return WLAN_STATUS_FAILURE or WLAN_STATUS_SUCCESS for blocking + * OIDs during current measurement + */ + if (prAdapter->u4PsCurrentMeasureEn && + (prAdapter->prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_CONNECTED)) + return WLAN_STATUS_SUCCESS; +#if 1 + /* most OID handler will just queue a command packet + * for power state transition OIDs, handler will acquire power control by itself + */ + status = pfnOidSetHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4SetInfoLen); +#else + if (wlanIsHandlerNeedHwAccess(pfnOidSetHandler, TRUE)) { + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + /* Reset sleepy state */ + if (prAdapter->fgWiFiInSleepyState == TRUE) + prAdapter->fgWiFiInSleepyState = FALSE; + + status = pfnOidSetHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4SetInfoLen); + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + } else { + status = pfnOidSetHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4SetInfoLen); + } +#endif + + return status; +} + +#if CFG_SUPPORT_WAPI +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a used to query driver's config wapi mode or not +* +* \param[IN] prAdapter Pointer to the Glue info structure. +* +* \retval TRUE for use wapi mode +* +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanQueryWapiMode(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + return prAdapter->rWifiVar.rConnSettings.fgWapiMode; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to set RX filter to Promiscuous Mode. +* +* \param[IN] prAdapter Pointer to the Adapter structure. +* \param[IN] fgEnablePromiscuousMode Enable/ disable RX Promiscuous Mode. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanSetPromiscuousMode(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnablePromiscuousMode) +{ + ASSERT(prAdapter); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to set RX filter to allow to receive +* broadcast address packets. +* +* \param[IN] prAdapter Pointer to the Adapter structure. +* \param[IN] fgEnableBroadcast Enable/ disable broadcast packet to be received. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanRxSetBroadcast(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnableBroadcast) +{ + ASSERT(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to send out CMD_NIC_POWER_CTRL command packet +* +* \param[IN] prAdapter Pointer to the Adapter structure. +* \param[IN] ucPowerMode refer to CMD/EVENT document +* +* \return WLAN_STATUS_SUCCESS +* \return WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanSendNicPowerCtrlCmd(IN P_ADAPTER_T prAdapter, IN UINT_8 ucPowerMode) +{ + WLAN_STATUS status = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_8 ucTC, ucCmdSeqNum; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + + /* 1. Prepare CMD */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_NIC_POWER_CTRL))); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); +#if CFG_ENABLE_KEYWORD_EXCEPTION_MECHANISM + mtk_wcn_wmt_assert_keyword(WMTDRV_TYPE_WIFI, + "[Wi-Fi Off] Allocate CMD_INFO_T ==> FAILED."); +#endif + return WLAN_STATUS_FAILURE; + } + + /* 2.1 increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + DBGLOG(REQ, TRACE, "ucCmdSeqNum =%d\n", ucCmdSeqNum); + + /* 2.2 Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = (UINT_16) (CMD_HDR_SIZE + sizeof(CMD_NIC_POWER_CTRL)); + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->pfCmdTimeoutHandler = NULL; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_NIC_POWER_CTRL; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(CMD_NIC_POWER_CTRL); + + /* 2.3 Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + kalMemZero(prWifiCmd->aucBuffer, sizeof(CMD_NIC_POWER_CTRL)); + ((P_CMD_NIC_POWER_CTRL) (prWifiCmd->aucBuffer))->ucPowerMode = ucPowerMode; + + /* 3. Issue CMD for entering specific power mode */ + ucTC = TC4_INDEX; + + while (1) { + /* 3.0 Removal check */ + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + status = WLAN_STATUS_FAILURE; + break; + } + /* 3.1 Acquire TX Resource */ + if (nicTxAcquireResource(prAdapter, ucTC, FALSE) == WLAN_STATUS_RESOURCES) { + + /* wait and poll tx resource */ + if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); + status = WLAN_STATUS_FAILURE; +#if CFG_ENABLE_KEYWORD_EXCEPTION_MECHANISM + mtk_wcn_wmt_assert_keyword(WMTDRV_TYPE_WIFI, + "[Wi-Fi Off] Fail to get TX resource return within timeout"); +#endif + break; + } + continue; + } + /* 3.2 Send CMD Info Packet */ + if (nicTxCmd(prAdapter, prCmdInfo, ucTC) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "Fail to transmit CMD_NIC_POWER_CTRL command\n"); + status = WLAN_STATUS_FAILURE; +#if CFG_ENABLE_KEYWORD_EXCEPTION_MECHANISM + mtk_wcn_wmt_assert_keyword(WMTDRV_TYPE_WIFI, + "[Wi-Fi Off] Fail to transmit CMD_NIC_POWER_CTRL command"); +#endif + } + + break; + }; + + /* 4. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + /* 5. Add flag */ + if (ucPowerMode == 1) + prAdapter->fgIsEnterD3ReqIssued = TRUE; + + return status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to check if it is RF test mode and +* the OID is allowed to be called or not +* +* \param[IN] prAdapter Pointer to the Adapter structure. +* \param[IN] fgEnableBroadcast Enable/ disable broadcast packet to be received. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanIsHandlerAllowedInRFTest(IN PFN_OID_HANDLER_FUNC pfnOidHandler, IN BOOLEAN fgSetInfo) +{ + PFN_OID_HANDLER_FUNC *apfnOidHandlerAllowedInRFTest; + UINT_32 i; + UINT_32 u4NumOfElem; + + if (fgSetInfo) { + apfnOidHandlerAllowedInRFTest = apfnOidSetHandlerAllowedInRFTest; + u4NumOfElem = sizeof(apfnOidSetHandlerAllowedInRFTest) / sizeof(PFN_OID_HANDLER_FUNC); + } else { + apfnOidHandlerAllowedInRFTest = apfnOidQueryHandlerAllowedInRFTest; + u4NumOfElem = sizeof(apfnOidQueryHandlerAllowedInRFTest) / sizeof(PFN_OID_HANDLER_FUNC); + } + + for (i = 0; i < u4NumOfElem; i++) { + if (apfnOidHandlerAllowedInRFTest[i] == pfnOidHandler) + return TRUE; + } + + return FALSE; +} + +#if CFG_ENABLE_FW_DOWNLOAD +#if CFG_ENABLE_FW_DOWNLOAD_AGGREGATION +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to download FW image in an aggregated way +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanImageSectionDownloadAggregated(IN P_ADAPTER_T prAdapter, + IN UINT_32 u4DestAddr, IN UINT_32 u4ImgSecSize, IN PUINT_8 pucImgSecBuf) +{ +#if defined(MT6620) || defined(MT6628) + P_CMD_INFO_T prCmdInfo; + P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; + P_INIT_CMD_DOWNLOAD_BUF prInitCmdDownloadBuf; + UINT_8 ucTC, ucCmdSeqNum; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + PUINT_8 pucOutputBuf = (PUINT_8) NULL; /* Pointer to Transmit Data Structure Frame */ + UINT_32 u4PktCnt, u4Offset, u4Length; + UINT_32 u4TotalLength; + + ASSERT(prAdapter); + ASSERT(pucImgSecBuf); + + pucOutputBuf = prAdapter->rTxCtrl.pucTxCoalescingBufPtr; + + DEBUGFUNC("wlanImageSectionDownloadAggregated"); + + if (u4ImgSecSize == 0) + return WLAN_STATUS_SUCCESS; + /* 1. Allocate CMD Info Packet and Pre-fill Headers */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF) + + CMD_PKT_SIZE_FOR_IMAGE); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prCmdInfo->u2InfoBufLen = sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF) + CMD_PKT_SIZE_FOR_IMAGE; + + /* 2. Use TC0's resource to download image. (only TC0 is allowed) */ + ucTC = TC0_INDEX; + + /* 3. Setup common CMD Info Packet */ + prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->ucEtherTypeOffset = 0; + prInitHifTxHeader->ucCSflags = 0; + prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_DOWNLOAD_BUF; + + /* 4. Setup CMD_DOWNLOAD_BUF */ + prInitCmdDownloadBuf = (P_INIT_CMD_DOWNLOAD_BUF) (prInitHifTxHeader->rInitWifiCmd.aucBuffer); + prInitCmdDownloadBuf->u4DataMode = 0 +#if CFG_ENABLE_FW_ENCRYPTION + | DOWNLOAD_BUF_ENCRYPTION_MODE +#endif + ; + + /* 5.0 reset loop control variable */ + u4TotalLength = 0; + u4Offset = u4PktCnt = 0; + + /* 5.1 main loop for maximize transmission count per access */ + while (u4Offset < u4ImgSecSize) { + if (nicTxAcquireResource(prAdapter, ucTC, FALSE) == WLAN_STATUS_SUCCESS) { + /* 5.1.1 calculate u4Length */ + if (u4Offset + CMD_PKT_SIZE_FOR_IMAGE < u4ImgSecSize) + u4Length = CMD_PKT_SIZE_FOR_IMAGE; + else + u4Length = u4ImgSecSize - u4Offset; + + /* 5.1.1 increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + /* 5.1.2 update HIF TX hardware header */ + prInitHifTxHeader->u2TxByteCount = + ALIGN_4(sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF) + (UINT_16) u4Length); + + /* 5.1.3 fill command header */ + prInitCmdDownloadBuf->u4Address = u4DestAddr + u4Offset; + prInitCmdDownloadBuf->u4Length = u4Length; + prInitCmdDownloadBuf->u4CRC32 = wlanCRC32(pucImgSecBuf + u4Offset, u4Length); + + /* 5.1.4.1 copy header to coalescing buffer */ + kalMemCopy(pucOutputBuf + u4TotalLength, + (PVOID) prCmdInfo->pucInfoBuffer, + sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF)); + + /* 5.1.4.2 copy payload to coalescing buffer */ + kalMemCopy(pucOutputBuf + u4TotalLength + sizeof(INIT_HIF_TX_HEADER_T) + + sizeof(INIT_CMD_DOWNLOAD_BUF), pucImgSecBuf + u4Offset, u4Length); + + /* 5.1.4.3 update length and other variables */ + u4TotalLength += + ALIGN_4(sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF) + u4Length); + u4Offset += u4Length; + u4PktCnt++; + + if (u4Offset < u4ImgSecSize) + continue; + } else if (u4PktCnt == 0) { + /* no resource, so get some back */ + if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); + break; + } + } + + if (u4PktCnt != 0) { + /* start transmission */ + HAL_WRITE_TX_PORT(prAdapter, + 0, + u4TotalLength, (PUINT_8) pucOutputBuf, prAdapter->u4CoalescingBufCachedSize); + + /* reset varaibles */ + u4PktCnt = 0; + u4TotalLength = 0; + } + } + + /* 8. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; + +#else +#error "Only MT6620/MT6628/MT6582 supports firmware download in an aggregated way" + + return WLAN_STATUS_FAILURE; + +#endif +} + +#endif +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to download FW image. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanImageSectionDownload(IN P_ADAPTER_T prAdapter, + IN UINT_32 u4DestAddr, IN UINT_32 u4ImgSecSize, IN PUINT_8 pucImgSecBuf) +{ + P_CMD_INFO_T prCmdInfo; + P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; + P_INIT_CMD_DOWNLOAD_BUF prInitCmdDownloadBuf; + UINT_8 ucTC, ucCmdSeqNum; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(pucImgSecBuf); + ASSERT(u4ImgSecSize <= CMD_PKT_SIZE_FOR_IMAGE); + + DEBUGFUNC("wlanImageSectionDownload"); + + if (u4ImgSecSize == 0) + return WLAN_STATUS_SUCCESS; + /* 1. Allocate CMD Info Packet and its Buffer. */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF) + u4ImgSecSize); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prCmdInfo->u2InfoBufLen = sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF) + (UINT_16) u4ImgSecSize; + + /* 2. Use TC0's resource to download image. (only TC0 is allowed) */ + ucTC = TC0_INDEX; + + /* 3. increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* 4. Setup common CMD Info Packet */ + prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_DOWNLOAD_BUF; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + /* 5. Setup CMD_DOWNLOAD_BUF */ + prInitCmdDownloadBuf = (P_INIT_CMD_DOWNLOAD_BUF) (prInitHifTxHeader->rInitWifiCmd.aucBuffer); + prInitCmdDownloadBuf->u4Address = u4DestAddr; + prInitCmdDownloadBuf->u4Length = u4ImgSecSize; + prInitCmdDownloadBuf->u4CRC32 = wlanCRC32(pucImgSecBuf, u4ImgSecSize); + + prInitCmdDownloadBuf->u4DataMode = 0 +#if CFG_ENABLE_FW_DOWNLOAD_ACK + | DOWNLOAD_BUF_ACK_OPTION /* ACK needed */ +#endif +#if CFG_ENABLE_FW_ENCRYPTION + | DOWNLOAD_BUF_ENCRYPTION_MODE +#endif + ; + + kalMemCopy(prInitCmdDownloadBuf->aucBuffer, pucImgSecBuf, u4ImgSecSize); + + /* 6. Send FW_Download command */ + while (1) { + /* 6.1 Acquire TX Resource */ + if (nicTxAcquireResource(prAdapter, ucTC, FALSE) == WLAN_STATUS_RESOURCES) { + if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); + break; + } + continue; + } + + wlanFWDLDebugAddTxStartTime(kalGetTimeTick()); + + /* 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"); + } + + wlanFWDLDebugAddTxDoneTime(kalGetTimeTick()); + + break; + }; + +#if CFG_ENABLE_FW_DOWNLOAD_ACK + /* 7. Wait for INIT_EVENT_ID_CMD_RESULT */ + u4Status = wlanImageSectionDownloadStatus(prAdapter, ucCmdSeqNum); +#endif + + /* 8. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + +#if !CFG_ENABLE_FW_DOWNLOAD_ACK +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to confirm previously firmware download is done without error +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanImageQueryStatus(IN P_ADAPTER_T prAdapter) +{ + P_CMD_INFO_T prCmdInfo; + P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; + UINT_8 aucBuffer[sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_EVENT_PENDING_ERROR)]; + UINT_32 u4RxPktLength; + P_INIT_HIF_RX_HEADER_T prInitHifRxHeader; + P_INIT_EVENT_PENDING_ERROR prEventPendingError; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + UINT_8 ucTC, ucCmdSeqNum; + + ASSERT(prAdapter); + + DEBUGFUNC("wlanImageQueryStatus"); + + /* 1. Allocate CMD Info Packet and it Buffer. */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, sizeof(INIT_HIF_TX_HEADER_T)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + kalMemZero(prCmdInfo, sizeof(INIT_HIF_TX_HEADER_T)); + prCmdInfo->u2InfoBufLen = sizeof(INIT_HIF_TX_HEADER_T); + + /* 2. Use TC0's resource to download image. (only TC0 is allowed) */ + ucTC = TC0_INDEX; + + /* 3. increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* 4. Setup common CMD Info Packet */ + prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_QUERY_PENDING_ERROR; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + /* 5. Send command */ + while (1) { + /* 5.1 Acquire TX Resource */ + if (nicTxAcquireResource(prAdapter, ucTC, FALSE) == WLAN_STATUS_RESOURCES) { + if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); + break; + } + continue; + } + /* 5.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo, ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to transmit image download command\n"); + } + + break; + }; + + /* 6. Wait for INIT_EVENT_ID_PENDING_ERROR */ + do { + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + } else if (nicRxWaitResponse(prAdapter, + 0, + aucBuffer, + sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_EVENT_PENDING_ERROR), + &u4RxPktLength) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + } else { + prInitHifRxHeader = (P_INIT_HIF_RX_HEADER_T) aucBuffer; + + /* EID / SeqNum check */ + if (prInitHifRxHeader->rInitWifiEvent.ucEID != INIT_EVENT_ID_PENDING_ERROR) { + u4Status = WLAN_STATUS_FAILURE; + } else if (prInitHifRxHeader->rInitWifiEvent.ucSeqNum != ucCmdSeqNum) { + u4Status = WLAN_STATUS_FAILURE; + } else { + prEventPendingError = + (P_INIT_EVENT_PENDING_ERROR) (prInitHifRxHeader->rInitWifiEvent.aucBuffer); + if (prEventPendingError->ucStatus != 0) { /* 0 for download success */ + u4Status = WLAN_STATUS_FAILURE; + } else { + u4Status = WLAN_STATUS_SUCCESS; + } + } + } + } while (FALSE); + + /* 7. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + +#else +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to confirm the status of +* previously downloaded firmware scatter +* +* @param prAdapter Pointer to the Adapter structure. +* ucCmdSeqNum Sequence number of previous firmware scatter +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanImageSectionDownloadStatus(IN P_ADAPTER_T prAdapter, IN UINT_8 ucCmdSeqNum) +{ + UINT_8 aucBuffer[sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_EVENT_CMD_RESULT)]; + P_INIT_HIF_RX_HEADER_T prInitHifRxHeader; + P_INIT_EVENT_CMD_RESULT prEventCmdResult; + UINT_32 u4RxPktLength; + WLAN_STATUS u4Status; + + ASSERT(prAdapter); + + do { + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + DBGLOG(INIT, ERROR, "kalIsCardRemoved or fgIsBusAccessFailed\n"); + u4Status = WLAN_STATUS_FAILURE; + } else if (nicRxWaitResponse(prAdapter, + 0, + aucBuffer, + sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_EVENT_CMD_RESULT),/* 4B + 4B */ + &u4RxPktLength) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "nicRxWaitResponse fail at SeqNo (%d)\n", ucCmdSeqNum); + + /*Dump WLAN TX Status Register TQ0_CNT, make sure FW write ROM success before CMD send*/ + wlanDumpTxReleaseCount(prAdapter); + /*Dump TX_DESC and RX_DESC*/ + wlanDebugHifDescriptorDump(prAdapter, MTK_AMPDU_TX_DESC, DEBUG_TC0_INDEX); + wlanDebugHifDescriptorDump(prAdapter, MTK_AMPDU_RX_DESC, DEBUG_TC0_INDEX); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP | RST_FLAG_PREVENT_POWER_OFF); + u4Status = WLAN_STATUS_FAILURE; + } else { + prInitHifRxHeader = (P_INIT_HIF_RX_HEADER_T) aucBuffer; + /* EID / SeqNum check */ + if (prInitHifRxHeader->rInitWifiEvent.ucEID != INIT_EVENT_ID_CMD_RESULT) { + DBGLOG(INIT, ERROR, "rInitWifiEvent.ucEID != INIT_EVENT_ID_CMD_RESULT\n"); + u4Status = WLAN_STATUS_FAILURE; + kalSendAeeWarning("[Check EID error!]", __func__); + } else if (prInitHifRxHeader->rInitWifiEvent.ucSeqNum != ucCmdSeqNum) { + DBGLOG(INIT, ERROR, "rInitWifiEvent.ucSeqNum != ucCmdSeqNum\n"); + u4Status = WLAN_STATUS_FAILURE; + kalSendAeeWarning("[Check SeqNum error!]", __func__); + } else { + prEventCmdResult = + (P_INIT_EVENT_CMD_RESULT) (prInitHifRxHeader->rInitWifiEvent.aucBuffer); + if (prEventCmdResult->ucStatus != 0) { /* 0 for download success */ + /* + * 0: success + * 1: rejected by invalid param + * 2: rejected by incorrect CRC + * 3: rejected by decryption failure + * 4: unknown CMD + */ + DBGLOG(INIT, ERROR, "Read Response status error = %d\n", + prEventCmdResult->ucStatus); + u4Status = WLAN_STATUS_FAILURE; + } else { + u4Status = WLAN_STATUS_SUCCESS; + } + } + if (u4Status == WLAN_STATUS_FAILURE) + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP | RST_FLAG_PREVENT_POWER_OFF); + } + } while (FALSE); + + return u4Status; +} + +#endif +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to start FW normal operation. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanConfigWifiFunc(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnable, IN UINT_32 u4StartAddress) +{ + P_CMD_INFO_T prCmdInfo; + P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; + P_INIT_CMD_WIFI_START prInitCmdWifiStart; + UINT_8 ucTC, ucCmdSeqNum; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + + DEBUGFUNC("wlanConfigWifiFunc"); + + /* 1. Allocate CMD Info Packet and its Buffer. */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_WIFI_START)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + kalMemZero(prCmdInfo->pucInfoBuffer, sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_WIFI_START)); + prCmdInfo->u2InfoBufLen = sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_WIFI_START); + + /* 2. Always use TC0 */ + ucTC = TC0_INDEX; + + /* 3. increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* 4. Setup common CMD Info Packet */ + prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_WIFI_START; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + prInitCmdWifiStart = (P_INIT_CMD_WIFI_START) (prInitHifTxHeader->rInitWifiCmd.aucBuffer); + prInitCmdWifiStart->u4Override = (fgEnable == TRUE ? 1 : 0); + prInitCmdWifiStart->u4Address = u4StartAddress; + + /* 5. Seend WIFI start command */ + while (1) { + /* 5.1 Acquire TX Resource */ + if (nicTxAcquireResource(prAdapter, ucTC, FALSE) == WLAN_STATUS_RESOURCES) { + + /* wait and poll tx resource */ + if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); + break; + } + + continue; + } + /* 5.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo, ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to transmit WIFI start command\n"); + } + + break; + }; + + /* 6. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to generate CRC32 checksum +* +* @param buf Pointer to the data. +* @param len data length +* +* @return crc32 value +*/ +/*----------------------------------------------------------------------------*/ +static const UINT_32 crc32_ccitt_table[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d + }; + +UINT_32 wlanCRC32(PUINT_8 buf, UINT_32 len) +{ + UINT_32 i, crc32 = 0xFFFFFFFF; + + for (i = 0; i < len; i++) + crc32 = crc32_ccitt_table[(crc32 ^ buf[i]) & 0xff] ^ (crc32 >> 8); + + return ~crc32; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to process queued RX packets +* +* @param prAdapter Pointer to the Adapter structure. +* prSwRfbListHead Pointer to head of RX packets link list +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanProcessQueuedSwRfb(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfbListHead) +{ + P_SW_RFB_T prSwRfb, prNextSwRfb; + P_TX_CTRL_T prTxCtrl; + P_RX_CTRL_T prRxCtrl; + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + ASSERT(prSwRfbListHead); + + prTxCtrl = &prAdapter->rTxCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + + prSwRfb = prSwRfbListHead; + + do { + /* save next first */ + prNextSwRfb = (P_SW_RFB_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prSwRfb); + + switch (prSwRfb->eDst) { + case RX_PKT_DESTINATION_HOST: + /* to host */ + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (prStaRec && IS_STA_IN_AIS(prStaRec)) { +#if ARP_MONITER_ENABLE + qmHandleRxArpPackets(prAdapter, prSwRfb); +#endif + } + nicRxProcessPktWithoutReorder(prAdapter, prSwRfb); + break; + + case RX_PKT_DESTINATION_FORWARD: + /* need ot forward */ + nicRxProcessForwardPkt(prAdapter, prSwRfb); + break; + + case RX_PKT_DESTINATION_HOST_WITH_FORWARD: + /* to host and forward */ + nicRxProcessGOBroadcastPkt(prAdapter, prSwRfb); + break; + + case RX_PKT_DESTINATION_NULL: + /* free it */ + nicRxReturnRFB(prAdapter, prSwRfb); + break; + + default: + break; + } + +#if CFG_HIF_RX_STARVATION_WARNING + prRxCtrl->u4DequeuedCnt++; +#endif + + /* check next queued packet */ + prSwRfb = prNextSwRfb; + } while (prSwRfb); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to purge queued TX packets +* by indicating failure to OS and returned to free list +* +* @param prAdapter Pointer to the Adapter structure. +* prMsduInfoListHead Pointer to head of TX packets link list +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanProcessQueuedMsduInfo(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead) +{ + ASSERT(prAdapter); + ASSERT(prMsduInfoListHead); + + nicTxFreeMsduInfoPacket(prAdapter, prMsduInfoListHead); + nicTxReturnMsduInfo(prAdapter, prMsduInfoListHead); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to check if the OID handler needs timeout +* +* @param prAdapter Pointer to the Adapter structure. +* pfnOidHandler Pointer to the OID handler +* +* @return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanoidTimeoutCheck(IN P_ADAPTER_T prAdapter, IN PFN_OID_HANDLER_FUNC pfnOidHandler) +{ + PFN_OID_HANDLER_FUNC *apfnOidHandlerWOTimeoutCheck; + UINT_32 i; + UINT_32 u4NumOfElem; + + apfnOidHandlerWOTimeoutCheck = apfnOidWOTimeoutCheck; + u4NumOfElem = sizeof(apfnOidWOTimeoutCheck) / sizeof(PFN_OID_HANDLER_FUNC); + + /* skip some OID timeout checks ? */ + for (i = 0; i < u4NumOfElem; i++) { + if (apfnOidHandlerWOTimeoutCheck[i] == pfnOidHandler) + return FALSE; + } + + /* set timer if need timeout check */ + /* cnmTimerStartTimer(prAdapter, */ + /* &(prAdapter->rOidTimeoutTimer), */ + /* 1000); */ + cnmTimerStartTimer(prAdapter, &(prAdapter->rOidTimeoutTimer), 2000); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to clear any pending OID timeout check +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanoidClearTimeoutCheck(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + cnmTimerStopTimer(prAdapter, &(prAdapter->rOidTimeoutTimer)); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to update network address in firmware domain +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return WLAN_STATUS_FAILURE The request could not be processed +* WLAN_STATUS_PENDING The request has been queued for later processing +* WLAN_STATUS_SUCCESS The request has been processed +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanUpdateNetworkAddress(IN P_ADAPTER_T prAdapter) +{ + const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; + PARAM_MAC_ADDRESS rMacAddr = {0}; + UINT_8 ucCmdSeqNum; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_CMD_BASIC_CONFIG prCmdBasicConfig; + UINT_32 u4SysTime; + + DEBUGFUNC("wlanUpdateNetworkAddress"); + + ASSERT(prAdapter); + + if (kalRetrieveNetworkAddress(prAdapter->prGlueInfo, &rMacAddr) == FALSE || IS_BMCAST_MAC_ADDR(rMacAddr) + || EQUAL_MAC_ADDR(aucZeroMacAddr, rMacAddr)) { + /* eFUSE has a valid address, don't do anything */ + if (prAdapter->fgIsEmbbededMacAddrValid == TRUE) { +#if CFG_SHOW_MACADDR_SOURCE + DBGLOG(INIT, INFO, "Using embedded MAC address"); +#endif + return WLAN_STATUS_SUCCESS; + } +#if CFG_SHOW_MACADDR_SOURCE + DBGLOG(INIT, TRACE, "Using dynamically generated MAC address"); +#endif + /* dynamic generate */ + u4SysTime = kalGetTimeTick(); + + rMacAddr[0] = 0x00; + rMacAddr[1] = 0x08; + rMacAddr[2] = 0x22; + + kalMemCopy(&rMacAddr[3], &u4SysTime, 3); + } else { +#if CFG_SHOW_MACADDR_SOURCE + DBGLOG(INIT, INFO, "Using host-supplied MAC address"); +#endif + } + + /* allocate command memory */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE + sizeof(CMD_BASIC_CONFIG)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_BUILD_CONNECTION cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_BASIC_CONFIG); + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->pfCmdTimeoutHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_BASIC_CONFIG; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(CMD_BASIC_CONFIG); + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + /* configure CMD_BASIC_CONFIG */ + prCmdBasicConfig = (P_CMD_BASIC_CONFIG) (prWifiCmd->aucBuffer); + kalMemCopy(&(prCmdBasicConfig->rMyMacAddr), &rMacAddr, PARAM_MAC_ADDR_LEN); + prCmdBasicConfig->ucNative80211 = 0; + prCmdBasicConfig->rCsumOffload.u2RxChecksum = 0; + prCmdBasicConfig->rCsumOffload.u2TxChecksum = 0; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + if (prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_TX_TCP) + prCmdBasicConfig->rCsumOffload.u2TxChecksum |= BIT(2); + + if (prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_TX_UDP) + prCmdBasicConfig->rCsumOffload.u2TxChecksum |= BIT(1); + + if (prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_TX_IP) + prCmdBasicConfig->rCsumOffload.u2TxChecksum |= BIT(0); + + if (prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_RX_TCP) + prCmdBasicConfig->rCsumOffload.u2RxChecksum |= BIT(2); + + if (prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_RX_UDP) + prCmdBasicConfig->rCsumOffload.u2RxChecksum |= BIT(1); + + if (prAdapter->u4CSUMFlags & (CSUM_OFFLOAD_EN_RX_IPv4 | CSUM_OFFLOAD_EN_RX_IPv6)) + prCmdBasicConfig->rCsumOffload.u2RxChecksum |= BIT(0); +#endif + + /* send the command to FW */ + if (wlanSendCommand(prAdapter, prCmdInfo) == WLAN_STATUS_RESOURCES) { + + /* backup the command to wait response */ + prCmdInfo->pfCmdDoneHandler = nicCmdEventQueryAddress; + kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + return WLAN_STATUS_PENDING; + } + /* send ok without response */ + nicCmdEventQueryAddress(prAdapter, prCmdInfo, (PUINT_8) prCmdBasicConfig); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return WLAN_STATUS_SUCCESS; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to check if the device is in RF test mode +* +* @param pfnOidHandler Pointer to the OID handler +* +* @return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanQueryTestMode(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + return prAdapter->fgTestMode; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to identify 802.1x and Bluetooth-over-Wi-Fi +* security frames, and queued into command queue for strict ordering +* due to 802.1x frames before add-key OIDs are not to be encrypted +* +* @param prAdapter Pointer of Adapter Data Structure +* @param prPacket Pointer of native packet +* +* @return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanProcessSecurityFrame(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prPacket) +{ + UINT_8 ucPriorityParam; + UINT_8 aucEthDestAddr[PARAM_MAC_ADDR_LEN]; + BOOLEAN fgIs1x = FALSE; + BOOLEAN fgIsPAL = FALSE; + UINT_32 u4PacketLen; + ULONG u4SysTime; + UINT_8 ucNetworkType; + P_CMD_INFO_T prCmdInfo; + UINT_8 ucCmdSeqNo = 0; + + /* 1x data packets */ + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prPacket); + + /* retrieve some information for packet classification */ + if (kalQoSFrameClassifierAndPacketInfo(prAdapter->prGlueInfo, + prPacket, + &ucPriorityParam, + &u4PacketLen, + aucEthDestAddr, + &fgIs1x, + &fgIsPAL, + &ucNetworkType, + &ucCmdSeqNo) == TRUE) { + /* almost TRUE except frame length < 14B */ + + if (fgIs1x == FALSE) + return FALSE; + + /* get a free command entry */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + QUEUE_REMOVE_HEAD(&prAdapter->rFreeCmdList, prCmdInfo, P_CMD_INFO_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + + if (prCmdInfo) { + P_STA_RECORD_T prStaRec; + + /* fill arrival time */ + u4SysTime = (OS_SYSTIME) kalGetTimeTick(); + GLUE_SET_PKT_ARRIVAL_TIME(prPacket, u4SysTime); + + kalMemZero(prCmdInfo, sizeof(CMD_INFO_T)); + + prCmdInfo->eCmdType = COMMAND_TYPE_SECURITY_FRAME; + prCmdInfo->u2InfoBufLen = (UINT_16) u4PacketLen; + prCmdInfo->pucInfoBuffer = NULL; + prCmdInfo->prPacket = prPacket; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNo; +#if 0 + prCmdInfo->ucStaRecIndex = qmGetStaRecIdx(prAdapter, + aucEthDestAddr, + (ENUM_NETWORK_TYPE_INDEX_T) ucNetworkType); +#endif + prStaRec = cnmGetStaRecByAddress(prAdapter, + (ENUM_NETWORK_TYPE_INDEX_T) ucNetworkType, + aucEthDestAddr); + if (prStaRec) + prCmdInfo->ucStaRecIndex = prStaRec->ucIndex; + else + prCmdInfo->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; + + prCmdInfo->eNetworkType = (ENUM_NETWORK_TYPE_INDEX_T) ucNetworkType; + prCmdInfo->pfCmdDoneHandler = wlanSecurityFrameTxDone; + prCmdInfo->pfCmdTimeoutHandler = wlanSecurityFrameTxTimeout; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + + /* + * queue the 1x packet and we will send the packet to CONNSYS by + * using command queue + */ + kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* TRUE: means we have already handled it in the function */ + return TRUE; + } + + /* no memory, why assert ? can skip the packet ? */ + ASSERT(0); + return FALSE; + } + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when 802.1x or Bluetooth-over-Wi-Fi +* security frames has been sent to firmware +* +* @param prAdapter Pointer of Adapter Data Structure +* @param prCmdInfo Pointer of CMD_INFO_T +* @param pucEventBuf meaningless, only for API compatibility +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanSecurityFrameTxDone(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo->eNetworkType == NETWORK_TYPE_AIS_INDEX && + prAdapter->rWifiVar.rAisSpecificBssInfo.fgCounterMeasure) { + + /* AIS counter measure so change RSN FSM to SEND_DEAUTH state */ + P_STA_RECORD_T prSta = cnmGetStaRecByIndex(prAdapter, prCmdInfo->ucStaRecIndex); + + if (prSta) { + kalMsleep(10); + secFsmEventEapolTxDone(prAdapter, prSta, TX_RESULT_SUCCESS); + } + } + + /* free the packet */ + kalSecurityFrameSendComplete(prAdapter->prGlueInfo, prCmdInfo->prPacket, WLAN_STATUS_SUCCESS); + DBGLOG(TX, TRACE, "Security frame tx done, SeqNum: %d\n", prCmdInfo->ucCmdSeqNum); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when 802.1x or Bluetooth-over-Wi-Fi +* security frames has failed sending to firmware +* +* @param prAdapter Pointer of Adapter Data Structure +* @param prCmdInfo Pointer of CMD_INFO_T +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanSecurityFrameTxTimeout(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + /* free the packet */ + kalSecurityFrameSendComplete(prAdapter->prGlueInfo, prCmdInfo->prPacket, WLAN_STATUS_FAILURE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called before AIS is starting a new scan +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanClearScanningResult(IN P_ADAPTER_T prAdapter) +{ + BOOLEAN fgKeepCurrOne = FALSE; + UINT_32 i; + + ASSERT(prAdapter); + + /* clear scanning result except current one */ + /* copy current one to prAdapter->rWlanInfo.arScanResult[0] */ + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + + if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, + prAdapter->rWlanInfo.arScanResult[i].arMacAddress)) { + fgKeepCurrOne = TRUE; + + if (i != 0) { + /* copy structure */ + kalMemCopy(&(prAdapter->rWlanInfo.arScanResult[0]), + &(prAdapter->rWlanInfo.arScanResult[i]), + OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); + } + + if (prAdapter->rWlanInfo.arScanResult[i].u4IELength > 0) { + if (prAdapter->rWlanInfo.apucScanResultIEs[i] != + &(prAdapter->rWlanInfo.aucScanIEBuf[0])) { + /* move IEs to head */ + kalMemCopy(prAdapter->rWlanInfo.aucScanIEBuf, + prAdapter->rWlanInfo.apucScanResultIEs[i], + prAdapter->rWlanInfo.arScanResult[i].u4IELength); + } + /* modify IE pointer */ + prAdapter->rWlanInfo.apucScanResultIEs[0] = + &(prAdapter->rWlanInfo.aucScanIEBuf[0]); + } else { + prAdapter->rWlanInfo.apucScanResultIEs[0] = NULL; + } + + break; + } + } + } + + if (fgKeepCurrOne == TRUE) { + prAdapter->rWlanInfo.u4ScanResultNum = 1; + prAdapter->rWlanInfo.u4ScanIEBufferUsage = ALIGN_4(prAdapter->rWlanInfo.arScanResult[0].u4IELength); + } else { + prAdapter->rWlanInfo.u4ScanResultNum = 0; + prAdapter->rWlanInfo.u4ScanIEBufferUsage = 0; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when AIS received a beacon timeout event +* +* @param prAdapter Pointer of Adapter Data Structure +* @param arBSSID MAC address of the specified BSS +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanClearBssInScanningResult(IN P_ADAPTER_T prAdapter, IN PUINT_8 arBSSID) +{ + UINT_32 i, j, u4IELength = 0, u4IEMoveLength; + PUINT_8 pucIEPtr; + + ASSERT(prAdapter); + + /* clear the scanning result for arBSSID */ + i = 0; + while (1) { + if (i >= prAdapter->rWlanInfo.u4ScanResultNum) + break; + + if (EQUAL_MAC_ADDR(arBSSID, prAdapter->rWlanInfo.arScanResult[i].arMacAddress)) { + + /* backup current IE length */ + u4IELength = ALIGN_4(prAdapter->rWlanInfo.arScanResult[i].u4IELength); + pucIEPtr = prAdapter->rWlanInfo.apucScanResultIEs[i]; + + /* removed from middle */ + for (j = i + 1; j < prAdapter->rWlanInfo.u4ScanResultNum; j++) { + kalMemCopy(&(prAdapter->rWlanInfo.arScanResult[j - 1]), + &(prAdapter->rWlanInfo.arScanResult[j]), + OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); + + prAdapter->rWlanInfo.apucScanResultIEs[j - 1] = + prAdapter->rWlanInfo.apucScanResultIEs[j]; + } + + prAdapter->rWlanInfo.u4ScanResultNum--; + + /* remove IE buffer if needed := move rest of IE buffer */ + if (u4IELength > 0) { + u4IEMoveLength = prAdapter->rWlanInfo.u4ScanIEBufferUsage - + (((ULONG) pucIEPtr) + (ULONG) u4IELength - + ((ULONG) (&(prAdapter->rWlanInfo.aucScanIEBuf[0])))); + + kalMemCopy(pucIEPtr, pucIEPtr + u4IELength, u4IEMoveLength); + + prAdapter->rWlanInfo.u4ScanIEBufferUsage -= u4IELength; + + /* correction of pointers to IE buffer */ + for (j = 0; j < prAdapter->rWlanInfo.u4ScanResultNum; j++) { + if (prAdapter->rWlanInfo.apucScanResultIEs[j] > pucIEPtr) { + prAdapter->rWlanInfo.apucScanResultIEs[j] = + (PUINT_8) ((ULONG) (prAdapter->rWlanInfo.apucScanResultIEs[j]) - + u4IELength); + } + } + } + } + + i++; + } + +} + +#if CFG_TEST_WIFI_DIRECT_GO +VOID wlanEnableP2pFunction(IN P_ADAPTER_T prAdapter) +{ +#if 0 + P_MSG_P2P_FUNCTION_SWITCH_T prMsgFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) NULL; + + prMsgFuncSwitch = + (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_FUNCTION_SWITCH_T)); + if (!prMsgFuncSwitch) { + ASSERT(FALSE); + return; + } + + prMsgFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; + prMsgFuncSwitch->fgIsFuncOn = TRUE; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgFuncSwitch, MSG_SEND_METHOD_BUF); +#endif + +} + +VOID wlanEnableATGO(IN P_ADAPTER_T prAdapter) +{ + + P_MSG_P2P_CONNECTION_REQUEST_T prMsgConnReq = (P_MSG_P2P_CONNECTION_REQUEST_T) NULL; + UINT_8 aucTargetDeviceID[MAC_ADDR_LEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + + prMsgConnReq = + (P_MSG_P2P_CONNECTION_REQUEST_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_CONNECTION_REQUEST_T)); + if (!prMsgConnReq) { + ASSERT(FALSE); + return; + } + + prMsgConnReq->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_REQ; + + /*=====Param Modified for test=====*/ + COPY_MAC_ADDR(prMsgConnReq->aucDeviceID, aucTargetDeviceID); + prMsgConnReq->fgIsTobeGO = TRUE; + prMsgConnReq->fgIsPersistentGroup = FALSE; + + /*=====Param Modified for test=====*/ + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgConnReq, MSG_SEND_METHOD_BUF); + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to retrieve permanent address from firmware +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanQueryPermanentAddress(IN P_ADAPTER_T prAdapter) +{ + UINT_8 ucCmdSeqNum; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_32 u4RxPktLength; + UINT_8 aucBuffer[sizeof(WIFI_EVENT_T) + sizeof(EVENT_BASIC_CONFIG)]; + P_HIF_RX_HEADER_T prHifRxHdr; + P_WIFI_EVENT_T prEvent; + P_EVENT_BASIC_CONFIG prEventBasicConfig; + + ASSERT(prAdapter); + + DEBUGFUNC("wlanQueryPermanentAddress"); + + /* 1. Allocate CMD Info Packet and its Buffer */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE + sizeof(CMD_BASIC_CONFIG)); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_BUILD_CONNECTION cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_BASIC_CONFIG); + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_BASIC_CONFIG; + prCmdInfo->fgSetQuery = FALSE; + prCmdInfo->fgNeedResp = TRUE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(CMD_BASIC_CONFIG); + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + /* send the command */ + wlanSendCommand(prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + /* wait for response */ + if (nicRxWaitResponse(prAdapter, + 1, + aucBuffer, + sizeof(WIFI_EVENT_T) + sizeof(EVENT_BASIC_CONFIG), /* 8B + 12B */ + &u4RxPktLength) != WLAN_STATUS_SUCCESS) + return WLAN_STATUS_FAILURE; + /* header checking .. */ + prHifRxHdr = (P_HIF_RX_HEADER_T) aucBuffer; + if ((prHifRxHdr->u2PacketType & HIF_RX_HDR_PACKET_TYPE_MASK) != HIF_RX_PKT_TYPE_EVENT) + return WLAN_STATUS_FAILURE; + + prEvent = (P_WIFI_EVENT_T) aucBuffer; + if (prEvent->ucEID != EVENT_ID_BASIC_CONFIG) + return WLAN_STATUS_FAILURE; + + prEventBasicConfig = (P_EVENT_BASIC_CONFIG) (prEvent->aucBuffer); + + COPY_MAC_ADDR(prAdapter->rWifiVar.aucPermanentAddress, &(prEventBasicConfig->rMyMacAddr)); + COPY_MAC_ADDR(prAdapter->rWifiVar.aucMacAddress, &(prEventBasicConfig->rMyMacAddr)); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to retrieve NIC capability from firmware +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanQueryNicCapability(IN P_ADAPTER_T prAdapter) +{ + UINT_8 ucCmdSeqNum; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_32 u4RxPktLength; + UINT_32 u4FwIDVersion = 0; + UINT_8 aucBuffer[sizeof(WIFI_EVENT_T) + sizeof(EVENT_NIC_CAPABILITY)]; + P_HIF_RX_HEADER_T prHifRxHdr; + P_WIFI_EVENT_T prEvent; + P_EVENT_NIC_CAPABILITY prEventNicCapability; + + ASSERT(prAdapter); + + DEBUGFUNC("wlanQueryNicCapability"); + + /* 1. Allocate CMD Info Packet and its Buffer */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE + sizeof(EVENT_NIC_CAPABILITY)); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_BUILD_CONNECTION cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(EVENT_NIC_CAPABILITY); + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_GET_NIC_CAPABILITY; + prCmdInfo->fgSetQuery = FALSE; + prCmdInfo->fgNeedResp = TRUE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = 0; + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + /* send the command */ + wlanSendCommand(prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + /* wait for FW response */ + if (nicRxWaitResponse(prAdapter, + 1, + aucBuffer, + sizeof(WIFI_EVENT_T) + sizeof(EVENT_NIC_CAPABILITY), + &u4RxPktLength) != WLAN_STATUS_SUCCESS) + return WLAN_STATUS_FAILURE; + /* header checking .. */ + prHifRxHdr = (P_HIF_RX_HEADER_T) aucBuffer; + if ((prHifRxHdr->u2PacketType & HIF_RX_HDR_PACKET_TYPE_MASK) != HIF_RX_PKT_TYPE_EVENT) + return WLAN_STATUS_FAILURE; + + prEvent = (P_WIFI_EVENT_T) aucBuffer; + if (prEvent->ucEID != EVENT_ID_NIC_CAPABILITY) + return WLAN_STATUS_FAILURE; + + prEventNicCapability = (P_EVENT_NIC_CAPABILITY) (prEvent->aucBuffer); + + prAdapter->rVerInfo.u2FwProductID = prEventNicCapability->u2ProductID; + prAdapter->rVerInfo.u2FwOwnVersion = prEventNicCapability->u2FwVersion; + prAdapter->rVerInfo.u2FwPeerVersion = prEventNicCapability->u2DriverVersion; + prAdapter->rVerInfo.u2FwOwnVersionExtend = prEventNicCapability->aucReserved[0]; + + prAdapter->fgIsHw5GBandDisabled = (BOOLEAN) prEventNicCapability->ucHw5GBandDisabled; + prAdapter->fgIsEepromUsed = (BOOLEAN) prEventNicCapability->ucEepromUsed; + prAdapter->fgIsEfuseValid = (BOOLEAN) prEventNicCapability->ucEfuseValid; + prAdapter->fgIsEmbbededMacAddrValid = (BOOLEAN) prEventNicCapability->ucMacAddrValid; + + u4FwIDVersion = (prAdapter->rVerInfo.u2FwProductID << 16) | (prAdapter->rVerInfo.u2FwOwnVersion); + mtk_wcn_wmt_set_wifi_ver(u4FwIDVersion); + + DBGLOG(INIT, INFO, " ProductID: 0x%x FwVer: 0x%x.%x DriVer:%s\n" + , prAdapter->rVerInfo.u2FwProductID + , prAdapter->rVerInfo.u2FwOwnVersion + , prAdapter->rVerInfo.u2FwOwnVersionExtend + , WIFI_DRIVER_VERSION); + +#if (CFG_SUPPORT_TDLS == 1) + if (prEventNicCapability->ucFeatureSet & (1 << FEATURE_SET_OFFSET_TDLS)) + prAdapter->fgTdlsIsSup = TRUE; + DBGLOG(TDLS, TRACE, " support flag: 0x%x\n", prEventNicCapability->ucFeatureSet); +#else + prAdapter->fgTdlsIsSup = 0; +#endif /* CFG_SUPPORT_TDLS */ + + if (!(prEventNicCapability->ucFeatureSet & (1 << FEATURE_SET_OFFSET_5G_SUPPORT))) + prAdapter->fgEnable5GBand = FALSE; /* firmware does not support */ + +#if CFG_ENABLE_CAL_LOG + DBGLOG(INIT, LOUD, " RF CAL FAIL = (%d),BB CAL FAIL = (%d)\n", + prEventNicCapability->ucRfCalFail, prEventNicCapability->ucBbCalFail); +#endif + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to retrieve NIC capability from firmware +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanQueryDebugCode(IN P_ADAPTER_T prAdapter) +{ + UINT_8 ucCmdSeqNum; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + + ASSERT(prAdapter); + + DEBUGFUNC("wlanQueryDebugCode"); + + /* 1. Allocate CMD Info Packet and its Buffer */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_BUILD_CONNECTION cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE; + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_GET_DEBUG_CODE; + prCmdInfo->fgSetQuery = FALSE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = 0; + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + /* send the command */ + wlanSendCommand(prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to retrieve compiler flag from firmware +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanQueryCompileFlag(IN P_ADAPTER_T prAdapter, IN UINT_32 u4QueryID, OUT PUINT_32 pu4CompilerFlag) +{ + UINT_8 ucCmdSeqNum; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_32 u4RxPktLength; + UINT_8 aucBuffer[sizeof(WIFI_EVENT_T) + sizeof(CMD_SW_DBG_CTRL_T)]; + P_HIF_RX_HEADER_T prHifRxHdr; + P_WIFI_EVENT_T prEvent; + P_CMD_SW_DBG_CTRL_T prCmdNicCompileFlag, prEventNicCompileFlag; + + ASSERT(prAdapter); + + DEBUGFUNC(__func__); + + /* 1. Allocate CMD Info Packet and its Buffer */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE + sizeof(CMD_SW_DBG_CTRL_T)); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_BUILD_CONNECTION cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_SW_DBG_CTRL_T); + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_SW_DBG_CTRL; + prCmdInfo->fgSetQuery = FALSE; + prCmdInfo->fgNeedResp = TRUE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = 0; + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + /* Fill up SW CR */ + prCmdNicCompileFlag = (P_CMD_SW_DBG_CTRL_T) (prWifiCmd->aucBuffer); + + prCmdNicCompileFlag->u4Id = u4QueryID; + + wlanSendCommand(prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + if (nicRxWaitResponse(prAdapter, + 1, + aucBuffer, + sizeof(WIFI_EVENT_T) + sizeof(CMD_SW_DBG_CTRL_T), + &u4RxPktLength) != WLAN_STATUS_SUCCESS) + return WLAN_STATUS_FAILURE; + /* header checking .. */ + prHifRxHdr = (P_HIF_RX_HEADER_T) aucBuffer; + if ((prHifRxHdr->u2PacketType & HIF_RX_HDR_PACKET_TYPE_MASK) != HIF_RX_PKT_TYPE_EVENT) + return WLAN_STATUS_FAILURE; + + prEvent = (P_WIFI_EVENT_T) aucBuffer; + if (prEvent->ucEID != EVENT_ID_SW_DBG_CTRL) + return WLAN_STATUS_FAILURE; + + prEventNicCompileFlag = (P_CMD_SW_DBG_CTRL_T) (prEvent->aucBuffer); + + *pu4CompilerFlag = prEventNicCompileFlag->u4Data; + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS wlanQueryCompileFlags(IN P_ADAPTER_T prAdapter) +{ + wlanQueryCompileFlag(prAdapter, 0xA0240000, &prAdapter->u4FwCompileFlag0); + wlanQueryCompileFlag(prAdapter, 0xA0240001, &prAdapter->u4FwCompileFlag1); + + DBGLOG(INIT, TRACE, + "Compile Flags: 0x%08x 0x%08x\n", prAdapter->u4FwCompileFlag0, prAdapter->u4FwCompileFlag1); + + return WLAN_STATUS_SUCCESS; +} + +#if defined(MT6628) +static INT_32 wlanChangeCodeWord(INT_32 au4Input) +{ + + UINT_16 i; +#if TXPWR_USE_PDSLOPE + CODE_MAPPING_T arCodeTable[] = { + {0X100, -40}, + {0X104, -35}, + {0X128, -30}, + {0X14C, -25}, + {0X170, -20}, + {0X194, -15}, + {0X1B8, -10}, + {0X1DC, -5}, + {0, 0}, + {0X24, 5}, + {0X48, 10}, + {0X6C, 15}, + {0X90, 20}, + {0XB4, 25}, + {0XD8, 30}, + {0XFC, 35}, + {0XFF, 40}, + + }; +#else + CODE_MAPPING_T arCodeTable[] = { + {0X100, 0x80}, + {0X104, 0x80}, + {0X128, 0x80}, + {0X14C, 0x80}, + {0X170, 0x80}, + {0X194, 0x94}, + {0X1B8, 0XB8}, + {0X1DC, 0xDC}, + {0, 0}, + {0X24, 0x24}, + {0X48, 0x48}, + {0X6C, 0x6c}, + {0X90, 0x7F}, + {0XB4, 0x7F}, + {0XD8, 0x7F}, + {0XFC, 0x7F}, + {0XFF, 0x7F}, + + }; +#endif + + for (i = 0; i < sizeof(arCodeTable) / sizeof(CODE_MAPPING_T); i++) { + + if (arCodeTable[i].u4RegisterValue == au4Input) + return arCodeTable[i].i4TxpowerOffset; + } + + return 0; +} +#endif + +#if TXPWR_USE_PDSLOPE + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanQueryPdMcr(IN P_ADAPTER_T prAdapter, P_PARAM_MCR_RW_STRUCT_T prMcrRdInfo) +{ + UINT_8 ucCmdSeqNum; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_32 u4RxPktLength; + UINT_8 aucBuffer[sizeof(WIFI_EVENT_T) + sizeof(CMD_ACCESS_REG)]; + P_HIF_RX_HEADER_T prHifRxHdr; + P_WIFI_EVENT_T prEvent; + P_CMD_ACCESS_REG prCmdMcrQuery; + + ASSERT(prAdapter); + + /* 1. Allocate CMD Info Packet and its Buffer */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE + sizeof(CMD_ACCESS_REG)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_BUILD_CONNECTION cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = (UINT_16) (CMD_HDR_SIZE + sizeof(CMD_ACCESS_REG)); + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_ACCESS_REG; + prCmdInfo->fgSetQuery = FALSE; + prCmdInfo->fgNeedResp = TRUE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(CMD_ACCESS_REG); + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + kalMemCopy(prWifiCmd->aucBuffer, prMcrRdInfo, sizeof(CMD_ACCESS_REG)); + + wlanSendCommand(prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + if (nicRxWaitResponse(prAdapter, + 1, + aucBuffer, + sizeof(WIFI_EVENT_T) + sizeof(CMD_ACCESS_REG), &u4RxPktLength) != WLAN_STATUS_SUCCESS) + return WLAN_STATUS_FAILURE; + /* header checking .. */ + prHifRxHdr = (P_HIF_RX_HEADER_T) aucBuffer; + if ((prHifRxHdr->u2PacketType & HIF_RX_HDR_PACKET_TYPE_MASK) != HIF_RX_PKT_TYPE_EVENT) + return WLAN_STATUS_FAILURE; + + prEvent = (P_WIFI_EVENT_T) aucBuffer; + + if (prEvent->ucEID != EVENT_ID_ACCESS_REG) + return WLAN_STATUS_FAILURE; + + prCmdMcrQuery = (P_CMD_ACCESS_REG) (prEvent->aucBuffer); + prMcrRdInfo->u4McrOffset = prCmdMcrQuery->u4Address; + prMcrRdInfo->u4McrData = prCmdMcrQuery->u4Data; + + return WLAN_STATUS_SUCCESS; +} + +static INT_32 wlanIntRound(INT_32 au4Input) +{ + + if (au4Input >= 0) { + if ((au4Input % 10) == 5) { + au4Input = au4Input + 5; + return au4Input; + } + } + + if (au4Input < 0) { + if ((au4Input % 10) == -5) { + au4Input = au4Input - 5; + return au4Input; + } + } + + return au4Input; +} + +static INT_32 wlanCal6628EfuseForm(IN P_ADAPTER_T prAdapter, INT_32 au4Input) +{ + + PARAM_MCR_RW_STRUCT_T rMcrRdInfo; + INT_32 au4PdSlope, au4TxPwrOffset, au4TxPwrOffset_Round; + INT_8 auTxPwrOffset_Round; + + rMcrRdInfo.u4McrOffset = 0x60205c68; + rMcrRdInfo.u4McrData = 0; + au4TxPwrOffset = au4Input; + wlanQueryPdMcr(prAdapter, &rMcrRdInfo); + + au4PdSlope = (rMcrRdInfo.u4McrData) & BITS(0, 6); + au4TxPwrOffset_Round = wlanIntRound((au4TxPwrOffset * au4PdSlope)) / 10; + + au4TxPwrOffset_Round = -au4TxPwrOffset_Round; + + if (au4TxPwrOffset_Round < -128) + au4TxPwrOffset_Round = 128; + else if (au4TxPwrOffset_Round < 0) + au4TxPwrOffset_Round += 256; + else if (au4TxPwrOffset_Round > 127) + au4TxPwrOffset_Round = 127; + + auTxPwrOffset_Round = (UINT8) au4TxPwrOffset_Round; + + return au4TxPwrOffset_Round; +} + +#endif + +#if defined(MT6628) +static VOID wlanChangeNvram6620to6628(PUINT_8 pucEFUSE) +{ + +#define EFUSE_CH_OFFSET1_L_MASK_6620 BITS(0, 8) +#define EFUSE_CH_OFFSET1_L_SHIFT_6620 0 +#define EFUSE_CH_OFFSET1_M_MASK_6620 BITS(9, 17) +#define EFUSE_CH_OFFSET1_M_SHIFT_6620 9 +#define EFUSE_CH_OFFSET1_H_MASK_6620 BITS(18, 26) +#define EFUSE_CH_OFFSET1_H_SHIFT_6620 18 +#define EFUSE_CH_OFFSET1_VLD_MASK_6620 BIT(27) +#define EFUSE_CH_OFFSET1_VLD_SHIFT_6620 27 + +#define EFUSE_CH_OFFSET1_L_MASK_5931 BITS(0, 7) +#define EFUSE_CH_OFFSET1_L_SHIFT_5931 0 +#define EFUSE_CH_OFFSET1_M_MASK_5931 BITS(8, 15) +#define EFUSE_CH_OFFSET1_M_SHIFT_5931 8 +#define EFUSE_CH_OFFSET1_H_MASK_5931 BITS(16, 23) +#define EFUSE_CH_OFFSET1_H_SHIFT_5931 16 +#define EFUSE_CH_OFFSET1_VLD_MASK_5931 BIT(24) +#define EFUSE_CH_OFFSET1_VLD_SHIFT_5931 24 +#define EFUSE_ALL_CH_OFFSET1_MASK_5931 BITS(25, 27) +#define EFUSE_ALL_CH_OFFSET1_SHIFT_5931 25 + + INT_32 au4ChOffset; + INT_16 au2ChOffsetL, au2ChOffsetM, au2ChOffsetH; + + au4ChOffset = *(UINT_32 *) (pucEFUSE + 72); + + if ((au4ChOffset & EFUSE_CH_OFFSET1_VLD_MASK_6620) && ((*(UINT_32 *) (pucEFUSE + 28)) == 0)) { + + au2ChOffsetL = ((au4ChOffset & EFUSE_CH_OFFSET1_L_MASK_6620) >> EFUSE_CH_OFFSET1_L_SHIFT_6620); + + au2ChOffsetM = ((au4ChOffset & EFUSE_CH_OFFSET1_M_MASK_6620) >> EFUSE_CH_OFFSET1_M_SHIFT_6620); + + au2ChOffsetH = ((au4ChOffset & EFUSE_CH_OFFSET1_H_MASK_6620) >> EFUSE_CH_OFFSET1_H_SHIFT_6620); + + au2ChOffsetL = wlanChangeCodeWord(au2ChOffsetL); + au2ChOffsetM = wlanChangeCodeWord(au2ChOffsetM); + au2ChOffsetH = wlanChangeCodeWord(au2ChOffsetH); + + au4ChOffset = 0; + au4ChOffset |= *(UINT_32 *) (pucEFUSE + 72) + >> (EFUSE_CH_OFFSET1_VLD_SHIFT_6620 - + EFUSE_CH_OFFSET1_VLD_SHIFT_5931) & EFUSE_CH_OFFSET1_VLD_MASK_5931; + + au4ChOffset |= + ((((UINT_32) au2ChOffsetL) << EFUSE_CH_OFFSET1_L_SHIFT_5931) & EFUSE_CH_OFFSET1_L_MASK_5931); + au4ChOffset |= + ((((UINT_32) au2ChOffsetM) << EFUSE_CH_OFFSET1_M_SHIFT_5931) & EFUSE_CH_OFFSET1_M_MASK_5931); + au4ChOffset |= + ((((UINT_32) au2ChOffsetH) << EFUSE_CH_OFFSET1_H_SHIFT_5931) & EFUSE_CH_OFFSET1_H_MASK_5931); + + *((INT_32 *) ((pucEFUSE + 28))) = au4ChOffset; + + } + +} +#endif + +ENUM_BAND_EDGE_CERT_T getBandEdgeCert(P_ADAPTER_T prAdapter) +{ + P_DOMAIN_INFO_ENTRY prDomainInfo; + P_DOMAIN_SUBBAND_INFO prSubband; + UINT32 i; + + prDomainInfo = rlmDomainGetDomainInfo(prAdapter); + ASSERT(prDomainInfo); + + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubband = &prDomainInfo->rSubBand[i]; + + if (prSubband->ucBand == BAND_2G4) { + if (prSubband->ucFirstChannelNum == 1) { + if (prSubband->ucNumChannels == 13) + return BAND_EDGE_CERT_KCC; + else + return BAND_EDGE_CERT_FCC; + } + } + } + return BAND_EDGE_CERT_FCC; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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 +#if CFG_SUPPORT_FCC_DYNAMIC_TX_PWR_ADJUST + CMD_FCC_TX_PWR_ADJUST FccTxPwrAdjust = {0x00}; +#endif + CMD_BAND_SUPPORT_T rCmdBandSupport; + + UINT8 uc_NVRAM[EXTEND_NVRAM_SIZE] = {0x0}; + UINT16 NVRAMSize = 0; + + 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 (prAdapter->rVerInfo.u2Part1CfgPeerVersion > CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part2CfgPeerVersion > CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part1CfgOwnVersion <= CFG_DRV_PEER_VERSION + || prAdapter->rVerInfo.u2Part2CfgOwnVersion <= CFG_DRV_PEER_VERSION) { + return WLAN_STATUS_FAILURE; + } +#endif + + /* Only when NVRAM size is EXTEND_NVRAM_SIZE bytes, send the whole NVRAM data to FW */ + if (kalCfgDataRead16(prAdapter->prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2SizeOfNvram), + (PUINT_16)&NVRAMSize) == TRUE) { + DBGLOG(INIT, INFO, "current NVRAMSize :%d and extend Size:%d\n" + , NVRAMSize, EXTEND_NVRAM_SIZE); + if (NVRAMSize >= EXTEND_NVRAM_SIZE) { + if (kalCfgDataRead(prAdapter->prGlueInfo, + 0, + sizeof(UINT_8)*EXTEND_NVRAM_SIZE, + (PUINT_16)&uc_NVRAM[0]) == TRUE) + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_NVRAM_SETTINGS, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(UINT_8) * EXTEND_NVRAM_SIZE, + (PUINT_8)(&uc_NVRAM[0]), NULL, 0); + else + DBGLOG(INIT, WARN, "Nvram read fail!\n"); + + /* MT6620 E1/E2 would be ignored directly */ + } + } else + DBGLOG(INIT, WARN, "u2SizeOfNvram read fail!\n"); + + 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))); + +#if CFG_SUPPORT_TX_POWER_BACK_OFF + if (prRegInfo->fgRlmMitigatedPwrByChByMode) + nicUpdateTxPowerOffset(prAdapter, + (P_CMD_MITIGATED_PWR_OFFSET_T) (prRegInfo->arRlmMitigatedPwrByChByMode)); +#endif + } + } + +#if CFG_SUPPORT_FCC_DYNAMIC_TX_PWR_ADJUST + /* Tx Power Adjust for FCC/CE Certification */ + FccTxPwrAdjust.fgFccTxPwrAdjust = 1; /* 1:enable; 0:disable */ + FccTxPwrAdjust.Offset_CCK = 14; /* drop 7dB */ + FccTxPwrAdjust.Offset_HT20 = 16; /* drop 8dB */ + FccTxPwrAdjust.Offset_HT40 = 14; /* drop 7dB*/ + FccTxPwrAdjust.Channel_CCK[0] = 11; /* [0] for start channel */ + FccTxPwrAdjust.Channel_CCK[1] = 13; /* [1] for ending channel */ + FccTxPwrAdjust.Channel_HT20[0] = 11; /* [0] for start channel */ + FccTxPwrAdjust.Channel_HT20[1] = 13; /* [1] for ending channel */ + FccTxPwrAdjust.Channel_HT40[0] = 7; /* [0] for start channel,engineer mode ch9(2452) */ + FccTxPwrAdjust.Channel_HT40[1] = 9; /* [1] for ending channel,engineer mode ch11(2462) */ + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_FCC_TX_PWR_CERT, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_FCC_TX_PWR_ADJUST), (PUINT_8) (&FccTxPwrAdjust), NULL, 0); + +#endif + + /* 3. Check if needs to support 5GHz */ + /* if(prRegInfo->ucEnable5GBand) { // Frank workaround */ + if (1) { + /* check if it is disabled by hardware */ + if (prAdapter->fgIsHw5GBandDisabled || prRegInfo->ucSupport5GBand == 0) + prAdapter->fgEnable5GBand = FALSE; + else + prAdapter->fgEnable5GBand = TRUE; + } else + prAdapter->fgEnable5GBand = FALSE; + + /* + * DBGLOG(INIT, INFO, "NVRAM 5G Enable(%d) SW_En(%d) HW_Dis(%d)\n", + * prRegInfo->ucEnable5GBand, prRegInfo->ucSupport5GBand, prAdapter->fgIsHw5GBandDisabled); + */ + DBGLOG(INIT, INFO, "HW_Dis(%d), TxPwrValid(%d)\n", + prAdapter->fgIsHw5GBandDisabled, + prRegInfo->ucTxPwrValid); + /* 4. Send EFUSE data */ +#if defined(MT6628) + wlanChangeNvram6620to6628(prRegInfo->aucEFUSE); +#endif + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_PHY_PARAM, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_PHY_PARAM_T), (PUINT_8) (prRegInfo->aucEFUSE), NULL, 0); + +#if CFG_SUPPORT_RDD_TEST_MODE + rRddParam.ucRddTestMode = (UINT_8) prRegInfo->u4RddTestMode; + rRddParam.ucRddShutCh = (UINT_8) prRegInfo->u4RddShutFreq; + rRddParam.ucRddStartCh = (UINT_8) nicFreq2ChannelNum(prRegInfo->u4RddStartFreq); + rRddParam.ucRddStopCh = (UINT_8) nicFreq2ChannelNum(prRegInfo->u4RddStopFreq); + rRddParam.ucRddDfs = (UINT_8) prRegInfo->u4RddDfs; + prAdapter->ucRddStatus = 0; + nicUpdateRddTestMode(prAdapter, (P_CMD_RDD_CH_T) (&rRddParam)); +#endif + + /* 5. Get 16-bits Country Code and Bandwidth */ + prAdapter->rWifiVar.rConnSettings.u2CountryCode = + (((UINT_16) prRegInfo->au2CountryCode[0]) << 8) | (((UINT_16) prRegInfo->au2CountryCode[1]) & BITS(0, 7)); + + DBGLOG(INIT, INFO, "NVRAM 5G Enable(%d) SW_En(%d) HW_Dis(%d) CountryCode(0x%x 0x%x)\n", + prRegInfo->ucEnable5GBand, prRegInfo->ucSupport5GBand, prAdapter->fgIsHw5GBandDisabled, + prRegInfo->au2CountryCode[0], prRegInfo->au2CountryCode[1]); + +#if 0 /* Bandwidth control will be controlled by GUI. 20110930 + * So ignore the setting from registry/NVRAM + */ + prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode = + prRegInfo->uc2G4BwFixed20M ? CONFIG_BW_20M : CONFIG_BW_20_40M; + prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode = + prRegInfo->uc5GBwFixed20M ? CONFIG_BW_20M : CONFIG_BW_20_40M; +#endif + + /* 6. Set domain and channel information to chip */ + rlmDomainSendCmd(prAdapter, FALSE); + /* Update supported channel list in channel table */ + wlanUpdateChannelTable(prAdapter->prGlueInfo); + + /* 7. Set band edge tx power if available */ + if (prRegInfo->fg2G4BandEdgePwrUsed) { + CMD_EDGE_TXPWR_LIMIT_T rCmdEdgeTxPwrLimit; + + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrCCK = prRegInfo->cBandEdgeMaxPwrCCK; + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM20 = prRegInfo->cBandEdgeMaxPwrOFDM20; + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM40 = prRegInfo->cBandEdgeMaxPwrOFDM40; + rCmdEdgeTxPwrLimit.cBandEdgeCert = getBandEdgeCert(prAdapter); + + DBGLOG(INIT, TRACE, "NVRAM 2G Bandedge CCK(%d) HT20(%d)HT40(%d)\n", + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrCCK, + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM20, rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM40); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_EDGE_TXPWR_LIMIT, + TRUE, + FALSE, + FALSE, + NULL, + NULL, sizeof(CMD_EDGE_TXPWR_LIMIT_T), (PUINT_8)&rCmdEdgeTxPwrLimit, NULL, 0); + } + /* 8. set 5G band edge tx power if available (add for 6625) */ + if (prAdapter->fgEnable5GBand) { +#define NVRAM_5G_TX_BANDEDGE_VALID_OFFSET 10 +#define NVRAM_5G_TX_BANDEDGE_OFDM20_OFFSET 11 +#define NVRAM_5G_TX_BANDEDGE_OFDM40_OFFSET 12 + + if (prRegInfo->aucEFUSE[NVRAM_5G_TX_BANDEDGE_VALID_OFFSET]) { + CMD_EDGE_TXPWR_LIMIT_T rCmdEdgeTxPwrLimit; + + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM20 + = prRegInfo->aucEFUSE[NVRAM_5G_TX_BANDEDGE_OFDM20_OFFSET]; + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM40 + = prRegInfo->aucEFUSE[NVRAM_5G_TX_BANDEDGE_OFDM40_OFFSET]; + + DBGLOG(INIT, TRACE, "NVRAM 5G Bandedge HT20(%d)HT40(%d)\n", + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM20, rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM40); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_5G_EDGE_TXPWR_LIMIT, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_EDGE_TXPWR_LIMIT_T), (PUINT_8)&rCmdEdgeTxPwrLimit, NULL, 0); + } + } + /* 9. set RSSI compensation */ + /* + * DBGLOG(INIT, INFO, ("[frank] RSSI valid(%d) 2G(%d) 5G(%d)", + * prRegInfo->fgRssiCompensationValidbit, + * prRegInfo->uc2GRssiCompensation, + * prRegInfo->uc5GRssiCompensation)); + */ + if (prRegInfo->fgRssiCompensationValidbit) { + CMD_RSSI_COMPENSATE_T rCmdRssiCompensate; + + rCmdRssiCompensate.uc2GRssiCompensation = prRegInfo->uc2GRssiCompensation; + rCmdRssiCompensate.uc5GRssiCompensation = prRegInfo->uc5GRssiCompensation; + + DBGLOG(INIT, LOUD, "NVRAM RSSI Comp. 2G(%d)5G(%d)\n", + rCmdRssiCompensate.uc2GRssiCompensation, rCmdRssiCompensate.uc5GRssiCompensation); + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RSSI_COMPENSATE, + TRUE, + FALSE, + FALSE, + NULL, NULL, sizeof(CMD_RSSI_COMPENSATE_T), (PUINT_8)&rCmdRssiCompensate, NULL, 0); + } + /* 10. notify FW Band Support 5G */ + + rCmdBandSupport.uc5GBandSupport = prAdapter->fgEnable5GBand; + DBGLOG(INIT, TRACE, "notify NVRAM 5G BandSupport %d\n", rCmdBandSupport.uc5GBandSupport); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_BAND_SUPPORT, + TRUE, + FALSE, + FALSE, + NULL, NULL, sizeof(CMD_BAND_SUPPORT_T), (PUINT_8)&rCmdBandSupport, NULL, 0); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to check +* Media Stream Mode is set to non-default value or not, +* and clear to default value if above criteria is met +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return TRUE +* The media stream mode was non-default value and has been reset +* FALSE +* The media stream mode is default value +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanResetMediaStreamMode(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + if (prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode != 0) { + prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode = 0; + + return TRUE; + } else { + return FALSE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to check if any pending timer has expired +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanTimerTimeoutCheck(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + /* check timer status */ + cnmTimerDoTimeOutCheck(prAdapter); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to check if any pending mailbox message +* to be handled +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanProcessMboxMessage(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i; + + ASSERT(prAdapter); + + for (i = 0; i < MBOX_ID_TOTAL_NUM; i++) { /* MBOX_ID_TOTAL_NUM = 1 */ + mboxRcvAllMsg(prAdapter, (ENUM_MBOX_ID_T) i); + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to enqueue a single TX packet into CORE +* +* @param prAdapter Pointer of Adapter Data Structure +* prNativePacket Pointer of Native Packet +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_RESOURCES +* WLAN_STATUS_INVALID_PACKET +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanEnqueueTxPacket(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prNativePacket) +{ + P_TX_CTRL_T prTxCtrl; + P_MSDU_INFO_T prMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + + /* get a free packet header */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + QUEUE_REMOVE_HEAD(&prTxCtrl->rFreeMsduInfoList, prMsduInfo, P_MSDU_INFO_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + + if (prMsduInfo == NULL) { + DBGLOG(TX, WARN, "%s prMsduInfo is null!\n", __func__); + return WLAN_STATUS_RESOURCES; + } + prMsduInfo->eSrc = TX_PACKET_OS; + + if (nicTxFillMsduInfo(prAdapter, prMsduInfo, prNativePacket) == FALSE) { + /* packet is not extractable */ + + /* fill fails */ + kalSendComplete(prAdapter->prGlueInfo, prNativePacket, WLAN_STATUS_INVALID_PACKET); + + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + + DBGLOG(TX, WARN, "%s WLAN_STATUS_INVALID_PACKET!\n", __func__); + + return WLAN_STATUS_INVALID_PACKET; + } + /* enqueue to QM */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to flush pending TX packets in CORE +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanFlushTxPendingPackets(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + return nicTxFlush(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief this function sends pending MSDU_INFO_T to MT6620 +* +* @param prAdapter Pointer to the Adapter structure. +* @param pfgHwAccess Pointer for tracking LP-OWN status +* +* @retval WLAN_STATUS_SUCCESS Reset is done successfully. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanTxPendingPackets(IN P_ADAPTER_T prAdapter, IN OUT PBOOLEAN pfgHwAccess) +{ + P_TX_CTRL_T prTxCtrl; + P_MSDU_INFO_T prMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + ASSERT(pfgHwAccess); + + /* <1> dequeue packets by txDequeuTxPackets() */ + /* Note: prMsduInfo is a packet list queue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + prMsduInfo = qmDequeueTxPackets(prAdapter, &prTxCtrl->rTc); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + + if (prMsduInfo != NULL) { + if (kalIsCardRemoved(prAdapter->prGlueInfo) == FALSE) { + /* <2> Acquire LP-OWN if necessary */ + if (*pfgHwAccess == FALSE) { + *pfgHwAccess = TRUE; + + wlanAcquirePowerControl(prAdapter); + } +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + if (prAdapter->fgIsClockGatingEnabled == TRUE) + nicDisableClockGating(prAdapter); +#endif + /* <3> send packet"s" to HIF */ + nicTxMsduInfoList(prAdapter, prMsduInfo); + + /* <4> update TC by txAdjustTcQuotas() */ + nicTxAdjustTcq(prAdapter); + } else + wlanProcessQueuedMsduInfo(prAdapter, prMsduInfo); /* free the packet */ + } else { + if (prAdapter->prGlueInfo->i4TxPendingFrameNum > 0) + DBGLOGLIMITED(INIT, WARN, "prMsduInfo is Null and PendingPKT(%u)\n" + , prAdapter->prGlueInfo->i4TxPendingFrameNum); + } + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + if (prAdapter->fgIsClockGatingEnabled == FALSE) + nicEnableClockGating(prAdapter); +#endif + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to acquire power control from firmware +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanAcquirePowerControl(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + /* do driver own */ + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + /* Reset sleepy state *//* no use */ + if (prAdapter->fgWiFiInSleepyState == TRUE) + prAdapter->fgWiFiInSleepyState = FALSE; + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to release power control to firmware +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanReleasePowerControl(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + /* do FW own */ + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to report currently pending TX frames count +* (command packets are not included) +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return number of pending TX frames +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 wlanGetTxPendingFrameCount(IN P_ADAPTER_T prAdapter) +{ + P_TX_CTRL_T prTxCtrl; + UINT_32 u4Num; + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + /* number in prTxQueue + number in RX forward */ + u4Num = kalGetTxPendingFrameCount(prAdapter->prGlueInfo) + (UINT_32) (prTxCtrl->i4PendingFwdFrameCount); + + return u4Num; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to report current ACPI state +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return ACPI_STATE_D0 Normal Operation Mode +* ACPI_STATE_D3 Suspend Mode +*/ +/*----------------------------------------------------------------------------*/ +ENUM_ACPI_STATE_T wlanGetAcpiState(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + return prAdapter->rAcpiState; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to update current ACPI state only +* +* @param prAdapter Pointer of Adapter Data Structure +* @param ePowerState ACPI_STATE_D0 Normal Operation Mode +* ACPI_STATE_D3 Suspend Mode +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanSetAcpiState(IN P_ADAPTER_T prAdapter, IN ENUM_ACPI_STATE_T ePowerState) +{ + ASSERT(prAdapter); + ASSERT(ePowerState <= ACPI_STATE_D3); + + prAdapter->rAcpiState = ePowerState; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to query ECO version from HIFSYS CR +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return zero Unable to retrieve ECO version information +* non-zero ECO version (1-based) +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 wlanGetEcoVersion(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + if (nicVerifyChipID(prAdapter) == TRUE) + return prAdapter->ucRevID + 1; + else + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to setting the default Tx Power configuration +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return zero Unable to retrieve ECO version information +* non-zero ECO version (1-based) +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanDefTxPowerCfg(IN P_ADAPTER_T prAdapter) +{ + UINT_8 i; + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + P_SET_TXPWR_CTRL_T prTxpwr; +#if CFG_SUPPORT_TX_POWER_BACK_OFF + P_REG_INFO_T prRegInfo; +#endif + ASSERT(prGlueInfo); + +#if CFG_SUPPORT_TX_POWER_BACK_OFF + prRegInfo = &prGlueInfo->rRegInfo; + ASSERT(prRegInfo); +#endif + 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; + +#if CFG_SUPPORT_TX_POWER_BACK_OFF + for (i = 0; i < 40; i++) { + /* 40 : MAXNUM_MITIGATED_PWR_BY_CH_BY_MODE */ + prTxpwr->arRlmMitigatedPwrByChByMode[i].channel = + prRegInfo->arRlmMitigatedPwrByChByMode[i].channel; + prTxpwr->arRlmMitigatedPwrByChByMode[i].mitigatedCckDsss = + prRegInfo->arRlmMitigatedPwrByChByMode[i].mitigatedCckDsss; + prTxpwr->arRlmMitigatedPwrByChByMode[i].mitigatedOfdm = + prRegInfo->arRlmMitigatedPwrByChByMode[i].mitigatedOfdm; + prTxpwr->arRlmMitigatedPwrByChByMode[i].mitigatedHt20 = + prRegInfo->arRlmMitigatedPwrByChByMode[i].mitigatedHt20; + prTxpwr->arRlmMitigatedPwrByChByMode[i].mitigatedHt40 = + prRegInfo->arRlmMitigatedPwrByChByMode[i].mitigatedHt40; + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to +* set preferred band configuration corresponding to network type +* +* @param prAdapter Pointer of Adapter Data Structure +* @param eBand Given band +* @param eNetTypeIndex Given Network Type +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanSetPreferBandByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_BAND_T eBand, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex) +{ + ASSERT(prAdapter); + ASSERT(eBand <= BAND_NUM); + ASSERT(eNetTypeIndex <= NETWORK_TYPE_INDEX_NUM); + + /* 1. set prefer band according to network type */ + prAdapter->aePreferBand[eNetTypeIndex] = eBand; + + /* 2. remove buffered BSS descriptors correspondingly */ + if (eBand == BAND_2G4) + scanRemoveBssDescByBandAndNetwork(prAdapter, BAND_5G, eNetTypeIndex); + else if (eBand == BAND_5G) + scanRemoveBssDescByBandAndNetwork(prAdapter, BAND_2G4, eNetTypeIndex); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to +* get channel information corresponding to specified network type +* +* @param prAdapter Pointer of Adapter Data Structure +* @param eNetTypeIndex Given Network Type +* +* @return channel number +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 wlanGetChannelNumberByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex) +{ + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(eNetTypeIndex <= NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); + + return prBssInfo->ucPrimaryChannel; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to +* get BSS descriptor information corresponding to specified network type +* +* @param prAdapter Pointer of Adapter Data Structure +* @param eNetTypeIndex Given Network Type +* +* @return pointer to BSS_DESC_T +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T wlanGetTargetBssDescByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex) +{ + ASSERT(prAdapter); + ASSERT(eNetTypeIndex <= NETWORK_TYPE_INDEX_NUM); + + switch (eNetTypeIndex) { + case NETWORK_TYPE_AIS_INDEX: + return prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc; + + case NETWORK_TYPE_P2P_INDEX: + return NULL; + + case NETWORK_TYPE_BOW_INDEX: + return prAdapter->rWifiVar.rBowFsmInfo.prTargetBssDesc; + + default: + return NULL; + } +} + +#if CFG_SUPPORT_ADD_CONN_AP +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to +* check if there is the connected AP in the scan list while the connected AP is weak signal. If there is no, +* add a connected AP to scan result list. +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanCheckConnectedAP(IN P_ADAPTER_T prAdapter) +{ + const UINT_8 aucBCAddr[] = BC_MAC_ADDR; + BOOLEAN fgGenAPMsg = FALSE; + P_WLAN_BEACON_FRAME_T prBeacon = NULL; + P_IE_SSID_T prSsid = NULL; + PARAM_SSID_T rSsid; + PARAM_802_11_CONFIG_T rConfiguration; + PARAM_RATES_EX rSupportedRates; + P_BSS_DESC_T prBssDesc = NULL; + ENUM_PARAM_NETWORK_TYPE_T eNetworkType; + ENUM_PARAM_OP_MODE_T eOpMode; + + DEBUGFUNC("wlanCheckConnectedAP"); + + ASSERT(prAdapter); + + prBssDesc = prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc; + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_DISCONNECTED) { + DBGLOG(SCN, WARN, "disconnect state, no need to report!\n"); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (prBssDesc && + (prBssDesc->u2RawLength == 0) && + prAdapter->fgIsLinkQualityValid && + (prAdapter->rLinkQuality.cRssi != -127)) { + DBGLOG(SCN, WARN, + "connected state but no connected ap in scan results and poll signal is %d!\n", + (PARAM_RSSI)prAdapter->rLinkQuality.cRssi); + fgGenAPMsg = TRUE; + } + + if (fgGenAPMsg == TRUE) { + if (!prBssDesc->u2IELength) + return WLAN_STATUS_FAILURE; + prBeacon = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(WLAN_BEACON_FRAME_T) + prBssDesc->u2IELength); + if (!prBeacon) { + ASSERT(FALSE); + return WLAN_STATUS_FAILURE; + } + + /* initialization */ + kalMemZero(prBeacon, sizeof(WLAN_BEACON_FRAME_T) + prBssDesc->u2IELength); + + /* prBeacon initialization */ + prBeacon->u2FrameCtrl = MAC_FRAME_BEACON; + COPY_MAC_ADDR(prBeacon->aucDestAddr, aucBCAddr); + COPY_MAC_ADDR(prBeacon->aucSrcAddr, prBssDesc->aucSrcAddr); + COPY_MAC_ADDR(prBeacon->aucBSSID, prBssDesc->aucBSSID); + prBeacon->u2BeaconInterval = prBssDesc->u2BeaconInterval; + prBeacon->u2CapInfo = prBssDesc->u2CapInfo; + + /* prSSID initialization */ + if (prBssDesc->ucSSIDLen > ELEM_MAX_LEN_SSID) + prBssDesc->ucSSIDLen = ELEM_MAX_LEN_SSID; + kalMemCopy(prBeacon->aucInfoElem, prBssDesc->aucIEBuf, + prBssDesc->ucSSIDLen + OFFSET_OF(IE_SSID_T, aucSSID)); + prSsid = (P_IE_SSID_T) (&prBeacon->aucInfoElem[0]); + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, prSsid->aucSSID, prSsid->ucLength); + + /* rConfiguration initialization */ + rConfiguration.u4Length = sizeof(PARAM_802_11_CONFIG_T); + rConfiguration.u4BeaconPeriod = (UINT_32) prBeacon->u2BeaconInterval; + rConfiguration.u4ATIMWindow = prBssDesc->u2ATIMWindow; + rConfiguration.u4DSConfig = nicChannelNum2Freq(prBssDesc->ucChannelNum); + rConfiguration.rFHConfig.u4Length = sizeof(PARAM_802_11_CONFIG_FH_T); + + 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; + } + + 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; + } + /* rSupportedRates initialization */ + kalMemZero(rSupportedRates, sizeof(PARAM_RATES_EX)); + } + if (prBeacon) { + kalIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) prBeacon, + sizeof(WLAN_BEACON_FRAME_T) + prBssDesc->u2IELength, + prBssDesc->ucChannelNum, (PARAM_RSSI) prAdapter->rLinkQuality.cRssi); + nicAddScanResult(prAdapter, + prBeacon->aucBSSID, + &rSsid, + prBeacon->u2CapInfo & CAP_INFO_PRIVACY ? 1 : 0, + (PARAM_RSSI) prAdapter->rLinkQuality.cRssi, + eNetworkType, + &rConfiguration, + eOpMode, + rSupportedRates, + prBssDesc->u2IELength, (PUINT_8) ((ULONG) (prBeacon) + WLAN_MAC_MGMT_HEADER_LEN)); + cnmMemFree(prAdapter, prBeacon); + } + + return WLAN_STATUS_SUCCESS; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @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 && (prAdapter->rVerInfo.u2Part1CfgPeerVersion > CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part2CfgPeerVersion > CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part1CfgOwnVersion <= CFG_DRV_PEER_VERSION + || prAdapter->rVerInfo.u2Part2CfgOwnVersion <= CFG_DRV_PEER_VERSION /* NVRAM */ + || prAdapter->rVerInfo.u2FwPeerVersion > CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2FwOwnVersion <= CFG_DRV_PEER_VERSION +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + || prAdapter->fgIsPowerLimitTableValid == FALSE +#endif + || (prAdapter->fgIsEmbbededMacAddrValid == FALSE && + (IS_BMCAST_MAC_ADDR(prRegInfo->aucMacAddr) + || EQUAL_MAC_ADDR(aucZeroMacAddr, prRegInfo->aucMacAddr))) + || prRegInfo->ucTxPwrValid == 0)) + fgGenErrMsg = TRUE; +#endif + + if (fgGenErrMsg == TRUE) { + prBeacon = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(WLAN_BEACON_FRAME_T) + sizeof(IE_SSID_T)); + if (!prBeacon) { + ASSERT(FALSE); + return WLAN_STATUS_FAILURE; + } + + /* initialization */ + kalMemZero(prBeacon, sizeof(WLAN_BEACON_FRAME_T) + sizeof(IE_SSID_T)); + + /* prBeacon initialization */ + prBeacon->u2FrameCtrl = MAC_FRAME_BEACON; + COPY_MAC_ADDR(prBeacon->aucDestAddr, aucBCAddr); + COPY_MAC_ADDR(prBeacon->aucSrcAddr, aucZeroMacAddr); + COPY_MAC_ADDR(prBeacon->aucBSSID, aucBCAddr); + prBeacon->u2BeaconInterval = 100; + prBeacon->u2CapInfo = CAP_INFO_ESS; + + /* prSSID initialization */ + prSsid = (P_IE_SSID_T) (&prBeacon->aucInfoElem[0]); + prSsid->ucId = ELEM_ID_SSID; + + /* rConfiguration initialization */ + rConfiguration.u4Length = sizeof(PARAM_802_11_CONFIG_T); + rConfiguration.u4BeaconPeriod = 100; + rConfiguration.u4ATIMWindow = 1; + rConfiguration.u4DSConfig = 2412; + rConfiguration.rFHConfig.u4Length = sizeof(PARAM_802_11_CONFIG_FH_T); + + /* rSupportedRates initialization */ + kalMemZero(rSupportedRates, sizeof(PARAM_RATES_EX)); + } +#if (CFG_NVRAM_EXISTENCE_CHECK == 1) +#define NVRAM_ERR_MSG "NVRAM WARNING: Err = 0x01" + if ((kalIsConfigurationExist(prAdapter->prGlueInfo) == FALSE) && (prBeacon) && (prSsid)) { + COPY_SSID(prSsid->aucSSID, prSsid->ucLength, NVRAM_ERR_MSG, strlen(NVRAM_ERR_MSG)); + + kalIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) prBeacon, + OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem) + OFFSET_OF(IE_SSID_T, + aucSSID) + prSsid->ucLength, + 1, 0); + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, NVRAM_ERR_MSG, strlen(NVRAM_ERR_MSG)); + nicAddScanResult(prAdapter, + prBeacon->aucBSSID, + &rSsid, + 0, + 0, + PARAM_NETWORK_TYPE_FH, + &rConfiguration, + NET_TYPE_INFRA, + rSupportedRates, + OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem) + OFFSET_OF(IE_SSID_T, + aucSSID) + prSsid->ucLength - + WLAN_MAC_MGMT_HEADER_LEN, (PUINT_8) ((ULONG) (prBeacon) + WLAN_MAC_MGMT_HEADER_LEN)); + } +#endif + +#if (CFG_SW_NVRAM_VERSION_CHECK == 1) +#define VER_ERR_MSG "NVRAM WARNING: Err = 0x%02X" + if ((fgIsConfExist == TRUE) && (prBeacon) && (prSsid)) { + if ((prAdapter->rVerInfo.u2Part1CfgPeerVersion > CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part2CfgPeerVersion > CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part1CfgOwnVersion <= CFG_DRV_PEER_VERSION + || prAdapter->rVerInfo.u2Part2CfgOwnVersion <= CFG_DRV_PEER_VERSION /* NVRAM */ + || prAdapter->rVerInfo.u2FwPeerVersion > CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2FwOwnVersion <= CFG_DRV_PEER_VERSION)) + u4ErrCode |= NVRAM_ERROR_VERSION_MISMATCH; + + if (prRegInfo->ucTxPwrValid == 0) + u4ErrCode |= NVRAM_ERROR_INVALID_TXPWR; + + if (prAdapter->fgIsEmbbededMacAddrValid == FALSE && (IS_BMCAST_MAC_ADDR(prRegInfo->aucMacAddr) + || EQUAL_MAC_ADDR(aucZeroMacAddr, + prRegInfo->aucMacAddr))) + u4ErrCode |= NVRAM_ERROR_INVALID_MAC_ADDR; + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + if (prAdapter->fgIsPowerLimitTableValid == FALSE) + u4ErrCode |= NVRAM_POWER_LIMIT_TABLE_INVALID; +#endif + if (u4ErrCode != 0) { + sprintf(aucErrMsg, VER_ERR_MSG, (unsigned int)u4ErrCode); + COPY_SSID(prSsid->aucSSID, prSsid->ucLength, aucErrMsg, strlen(aucErrMsg)); + + kalIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) prBeacon, + OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem) + OFFSET_OF(IE_SSID_T, + aucSSID) + + prSsid->ucLength, 1, 0); + + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, NVRAM_ERR_MSG, strlen(NVRAM_ERR_MSG)); + nicAddScanResult(prAdapter, + prBeacon->aucBSSID, + &rSsid, + 0, + 0, + PARAM_NETWORK_TYPE_FH, + &rConfiguration, + NET_TYPE_INFRA, + rSupportedRates, + OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem) + OFFSET_OF(IE_SSID_T, + aucSSID) + + prSsid->ucLength - WLAN_MAC_MGMT_HEADER_LEN, + (PUINT_8) ((ULONG) (prBeacon) + WLAN_MAC_MGMT_HEADER_LEN)); + } + } +#endif + + if (fgGenErrMsg == TRUE) + cnmMemFree(prAdapter, prBeacon); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidQueryStaStatistics(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + WLAN_STATUS rResult = WLAN_STATUS_FAILURE; + P_STA_RECORD_T prStaRec, prTempStaRec; + P_PARAM_GET_STA_STATISTICS prQueryStaStatistics; + UINT_8 ucStaRecIdx; + P_QUE_MGT_T prQM; + CMD_GET_STA_STATISTICS_T rQueryCmdStaStatistics; + UINT_8 ucIdx; + P_GLUE_INFO_T prGlueInfo; + + if (prAdapter == NULL) { + DBGLOG(INIT, ERROR, "prAdapter is Null\n"); + return rResult; + } + prQM = &prAdapter->rQM; + prGlueInfo = prAdapter->prGlueInfo; + do { + ASSERT(pvQueryBuffer); + + /* 4 1. Sanity test */ + if ((prAdapter == NULL) || (pu4QueryInfoLen == NULL)) + break; + + if ((u4QueryBufferLen) && (pvQueryBuffer == NULL)) + break; + + if (u4QueryBufferLen < sizeof(PARAM_GET_STA_STA_STATISTICS)) { + *pu4QueryInfoLen = sizeof(PARAM_GET_STA_STA_STATISTICS); + rResult = WLAN_STATUS_BUFFER_TOO_SHORT; + break; + } + + prGlueInfo = prAdapter->prGlueInfo; + if (prGlueInfo == NULL) + break; + + prQueryStaStatistics = (P_PARAM_GET_STA_STATISTICS) pvQueryBuffer; + *pu4QueryInfoLen = sizeof(PARAM_GET_STA_STA_STATISTICS); + + /* 4 5. Get driver global QM counter */ + for (ucIdx = TC0_INDEX; ucIdx <= TC3_INDEX; ucIdx++) { + prQueryStaStatistics->au4TcAverageQueLen[ucIdx] = prQM->au4AverageQueLen[ucIdx]; + prQueryStaStatistics->au4TcCurrentQueLen[ucIdx] = prQM->au4CurrentTcResource[ucIdx]; + } + + /* 4 2. Get StaRec by MAC address */ + prStaRec = NULL; + + for (ucStaRecIdx = 0; ucStaRecIdx < CFG_NUM_OF_STA_RECORD; ucStaRecIdx++) { + prTempStaRec = &(prAdapter->arStaRec[ucStaRecIdx]); + if (prTempStaRec->fgIsValid && prTempStaRec->fgIsInUse) { + if (EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, prQueryStaStatistics->aucMacAddr)) { + prStaRec = prTempStaRec; + break; + } + } + } + + if (!prStaRec) { + rResult = WLAN_STATUS_INVALID_DATA; + break; + } + + prQueryStaStatistics->u4Flag |= BIT(0); + +#if CFG_ENABLE_PER_STA_STATISTICS + /* 4 3. Get driver statistics */ + DBGLOG(TX, INFO, "skbToDriver %lld, skbFreed: %lld\n", + prAdapter->prGlueInfo->u8SkbToDriver, + prAdapter->prGlueInfo->u8SkbFreed); + prAdapter->prGlueInfo->u8SkbFreed = 0; + prAdapter->prGlueInfo->u8SkbToDriver = 0; + + prQueryStaStatistics->u4TxTotalCount = prStaRec->u4TotalTxPktsNumber; + prQueryStaStatistics->u4TxExceedThresholdCount = prStaRec->u4ThresholdCounter; + prQueryStaStatistics->u4TxMaxTime = prStaRec->u4MaxTxPktsTime; + prQueryStaStatistics->u4TxMaxHifTime = prStaRec->u4MaxTxPktsHifTime; + if (prStaRec->u4TotalTxPktsNumber) { + prQueryStaStatistics->u4TxAverageProcessTime = + (prStaRec->u4TotalTxPktsTime / prStaRec->u4TotalTxPktsNumber); + prQueryStaStatistics->u4TxAverageHifTime = + (prStaRec->u4TotalTxPktsHifTime / prStaRec->u4TotalTxPktsNumber); + } else + prQueryStaStatistics->u4TxAverageProcessTime = 0; + + for (ucIdx = TC0_INDEX; ucIdx <= TC3_INDEX; ucIdx++) { + prQueryStaStatistics->au4TcResourceEmptyCount[ucIdx] = + prQM->au4QmTcResourceEmptyCounter[prStaRec->ucNetTypeIndex][ucIdx]; + /* Reset */ + prQM->au4QmTcResourceEmptyCounter[prStaRec->ucNetTypeIndex][ucIdx] = 0; + prQueryStaStatistics->au4TcResourceBackCount[ucIdx] = + prQM->au4QmTcResourceBackCounter[ucIdx]; + prQM->au4QmTcResourceBackCounter[ucIdx] = 0; + + prQueryStaStatistics->au4DequeueNoTcResource[ucIdx] = + prQM->au4DequeueNoTcResourceCounter[ucIdx]; + prQM->au4DequeueNoTcResourceCounter[ucIdx] = 0; + prQueryStaStatistics->au4TcResourceUsedCount[ucIdx] = + prQM->au4ResourceUsedCounter[ucIdx]; + prQM->au4ResourceUsedCounter[ucIdx] = 0; + prQueryStaStatistics->au4TcResourceWantedCount[ucIdx] = + prQM->au4ResourceWantedCounter[ucIdx]; + prQM->au4ResourceWantedCounter[ucIdx] = 0; + } + + prQueryStaStatistics->u4EnqueueCounter = prQM->u4EnqeueuCounter; + prQueryStaStatistics->u4DequeueCounter = prQM->u4DequeueCounter; + prQueryStaStatistics->u4EnqueueStaCounter = prStaRec->u4EnqeueuCounter; + prQueryStaStatistics->u4DequeueStaCounter = prStaRec->u4DeqeueuCounter; + + prQueryStaStatistics->IsrCnt = prGlueInfo->IsrCnt - prGlueInfo->IsrPreCnt; + prQueryStaStatistics->IsrPassCnt = prGlueInfo->IsrPassCnt - prGlueInfo->IsrPrePassCnt; + prQueryStaStatistics->TaskIsrCnt = prGlueInfo->TaskIsrCnt - prGlueInfo->TaskPreIsrCnt; + + prQueryStaStatistics->IsrAbnormalCnt = prGlueInfo->IsrAbnormalCnt; + prQueryStaStatistics->IsrSoftWareCnt = prGlueInfo->IsrSoftWareCnt; + prQueryStaStatistics->IsrRxCnt = prGlueInfo->IsrRxCnt; + prQueryStaStatistics->IsrTxCnt = prGlueInfo->IsrTxCnt; + + /* 4 4.1 Reset statistics */ + prStaRec->u4ThresholdCounter = 0; + prStaRec->u4TotalTxPktsNumber = 0; + prStaRec->u4TotalTxPktsTime = 0; + prStaRec->u4MaxTxPktsTime = 0; + prStaRec->u4MaxTxPktsHifTime = 0; + + prStaRec->u4EnqeueuCounter = 0; + prStaRec->u4DeqeueuCounter = 0; + + prQM->u4EnqeueuCounter = 0; + prQM->u4DequeueCounter = 0; + + prGlueInfo->IsrPreCnt = prGlueInfo->IsrCnt; + prGlueInfo->IsrPrePassCnt = prGlueInfo->IsrPassCnt; + prGlueInfo->TaskPreIsrCnt = prGlueInfo->TaskIsrCnt; + prGlueInfo->IsrAbnormalCnt = 0; + prGlueInfo->IsrSoftWareCnt = 0; + prGlueInfo->IsrRxCnt = 0; + prGlueInfo->IsrTxCnt = 0; +#endif + + for (ucIdx = TC0_INDEX; ucIdx <= TC3_INDEX; ucIdx++) + prQueryStaStatistics->au4TcQueLen[ucIdx] = prStaRec->arTxQueue[ucIdx].u4NumElem; + + rResult = WLAN_STATUS_SUCCESS; + + /* 4 6. Ensure FW supports get station link status */ + if (prAdapter->u4FwCompileFlag0 & COMPILE_FLAG0_GET_STA_LINK_STATUS) { + + rQueryCmdStaStatistics.ucIndex = prStaRec->ucIndex; + COPY_MAC_ADDR(rQueryCmdStaStatistics.aucMacAddr, prQueryStaStatistics->aucMacAddr); + rQueryCmdStaStatistics.ucReadClear = TRUE; + + rResult = wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STA_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryStaStatistics, + nicOidCmdTimeoutCommon, + sizeof(CMD_GET_STA_STATISTICS_T), + (PUINT_8)&rQueryCmdStaStatistics, + pvQueryBuffer, u4QueryBufferLen); + + prQueryStaStatistics->u4Flag |= BIT(1); + } else { + rResult = WLAN_STATUS_NOT_SUPPORTED; + } + + } while (FALSE); + + return rResult; +} /* wlanoidQueryP2pVersion */ + +#if CFG_SUPPORT_CFG_FILE + +P_WLAN_CFG_ENTRY_T wlanCfgGetEntry(IN P_ADAPTER_T prAdapter, const PCHAR pucKey) +{ + + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + P_WLAN_CFG_T prWlanCfg; + UINT_32 i; + + prWlanCfg = prAdapter->prWlanCfg; + + ASSERT(prWlanCfg); + ASSERT(pucKey); + + prWlanCfgEntry = NULL; + + for (i = 0; i < WLAN_CFG_ENTRY_NUM_MAX; i++) { + prWlanCfgEntry = &prWlanCfg->arWlanCfgBuf[i]; + if (prWlanCfgEntry->aucKey[0] != '\0') { + DBGLOG(INIT, LOUD, "compare key %s saved key %s\n", pucKey, prWlanCfgEntry->aucKey); + if (kalStrniCmp(pucKey, prWlanCfgEntry->aucKey, WLAN_CFG_KEY_LEN_MAX - 1) == 0) + return prWlanCfgEntry; + } + } + + DBGLOG(INIT, LOUD, "wifi config there is no entry \'%s\'\n", pucKey); + return NULL; + +} + +WLAN_STATUS wlanCfgGet(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, PCHAR pucValue, PCHAR pucValueDef, UINT_32 u4Flags) +{ + + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + P_WLAN_CFG_T prWlanCfg; + + prWlanCfg = prAdapter->prWlanCfg; + + ASSERT(prWlanCfg); + ASSERT(pucValue); + + /* Find the exist */ + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey); + + if (prWlanCfgEntry) { + kalStrnCpy(pucValue, prWlanCfgEntry->aucValue, WLAN_CFG_VALUE_LEN_MAX - 1); + return WLAN_STATUS_SUCCESS; + } + if (pucValueDef) + kalStrnCpy(pucValue, pucValueDef, WLAN_CFG_VALUE_LEN_MAX - 1); + return WLAN_STATUS_FAILURE; + +} + +UINT_32 wlanCfgGetUint32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, UINT_32 u4ValueDef) +{ + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + P_WLAN_CFG_T prWlanCfg; + UINT_32 u4Value; + INT_32 u4Ret; + + prWlanCfg = prAdapter->prWlanCfg; + + ASSERT(prWlanCfg); + + u4Value = u4ValueDef; + /* Find the exist */ + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey); + + if (prWlanCfgEntry) { + u4Ret = kalkStrtou32(prWlanCfgEntry->aucValue, 0, &u4Value); + if (u4Ret) + DBGLOG(INIT, ERROR, "parse prWlanCfgEntry->aucValue u4Ret=%u\n", u4Ret); + /* u4Value = kalStrtoul(prWlanCfgEntry->aucValue, NULL, 0); */ + } + + return u4Value; +} + +INT_32 wlanCfgGetInt32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, INT_32 i4ValueDef) +{ + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + P_WLAN_CFG_T prWlanCfg; + INT_32 i4Value; + INT_32 i4Ret; + + prWlanCfg = prAdapter->prWlanCfg; + + ASSERT(prWlanCfg); + + i4Value = i4ValueDef; + /* Find the exist */ + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey); + + if (prWlanCfgEntry) { + i4Ret = kalkStrtos32(prWlanCfgEntry->aucValue, 0, &i4Value); + /* i4Ret = kalStrtol(prWlanCfgEntry->aucValue, NULL, 0); */ + if (i4Ret) + DBGLOG(INIT, ERROR, "parse prWlanCfgEntry->aucValue i4Ret=%u\n\r", i4Ret); + } + + return i4Value; +} + +WLAN_STATUS wlanCfgSet(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, PCHAR pucValue, UINT_32 u4Flags) +{ + + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + P_WLAN_CFG_T prWlanCfg; + UINT_32 u4EntryIndex; + UINT_32 i; + UINT_8 ucExist; + + prWlanCfg = prAdapter->prWlanCfg; + ASSERT(prWlanCfg); + ASSERT(pucKey); + + /* Find the exist */ + ucExist = 0; + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey); + + if (!prWlanCfgEntry) { + /* Find the empty */ + for (i = 0; i < WLAN_CFG_ENTRY_NUM_MAX; i++) { + prWlanCfgEntry = &prWlanCfg->arWlanCfgBuf[i]; + if (prWlanCfgEntry->aucKey[0] == '\0') + break; + } + + u4EntryIndex = i; + if (u4EntryIndex < WLAN_CFG_ENTRY_NUM_MAX) { + prWlanCfgEntry = &prWlanCfg->arWlanCfgBuf[u4EntryIndex]; + kalMemZero(prWlanCfgEntry, sizeof(WLAN_CFG_ENTRY_T)); + } else { + prWlanCfgEntry = NULL; + DBGLOG(INIT, ERROR, "wifi config there is no empty entry\n"); + } + } /* !prWlanCfgEntry */ + else + ucExist = 1; + + if (prWlanCfgEntry) { + if (ucExist == 0) { + kalStrnCpy(prWlanCfgEntry->aucKey, pucKey, WLAN_CFG_KEY_LEN_MAX - 1); + prWlanCfgEntry->aucKey[WLAN_CFG_KEY_LEN_MAX - 1] = '\0'; + } + + if (pucValue && pucValue[0] != '\0') { + kalStrnCpy(prWlanCfgEntry->aucValue, pucValue, WLAN_CFG_VALUE_LEN_MAX - 1); + prWlanCfgEntry->aucValue[WLAN_CFG_VALUE_LEN_MAX - 1] = '\0'; + + if (ucExist) { + if (prWlanCfgEntry->pfSetCb) + prWlanCfgEntry->pfSetCb(prAdapter, + prWlanCfgEntry->aucKey, + prWlanCfgEntry->aucValue, prWlanCfgEntry->pPrivate, 0); + } + } else { + /* Call the pfSetCb if value is empty ? */ + /* remove the entry if value is empty */ + kalMemZero(prWlanCfgEntry, sizeof(WLAN_CFG_ENTRY_T)); + } + + } + /* prWlanCfgEntry */ + if (prWlanCfgEntry) { + DBGLOG(INIT, LOUD, "Set wifi config exist %u \'%s\' \'%s\'\n", + ucExist, prWlanCfgEntry->aucKey, prWlanCfgEntry->aucValue); + return WLAN_STATUS_SUCCESS; + } + if (pucKey) + DBGLOG(INIT, ERROR, "Set wifi config error key \'%s\'\n", pucKey); + if (pucValue) + DBGLOG(INIT, ERROR, "Set wifi config error value \'%s\'\n", pucValue); + return WLAN_STATUS_FAILURE; + +} + +WLAN_STATUS +wlanCfgSetCb(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, WLAN_CFG_SET_CB pfSetCb, void *pPrivate, UINT_32 u4Flags) +{ + + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + P_WLAN_CFG_T prWlanCfg; + + prWlanCfg = prAdapter->prWlanCfg; + ASSERT(prWlanCfg); + + /* Find the exist */ + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey); + + if (prWlanCfgEntry) { + prWlanCfgEntry->pfSetCb = pfSetCb; + prWlanCfgEntry->pPrivate = pPrivate; + } + + if (prWlanCfgEntry) + return WLAN_STATUS_SUCCESS; + else + return WLAN_STATUS_FAILURE; + +} + +WLAN_STATUS wlanCfgSetUint32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, UINT_32 u4Value) +{ + + P_WLAN_CFG_T prWlanCfg; + UINT_8 aucBuf[WLAN_CFG_VALUE_LEN_MAX]; + + prWlanCfg = prAdapter->prWlanCfg; + + ASSERT(prWlanCfg); + + kalMemZero(aucBuf, sizeof(aucBuf)); + + kalSnprintf(aucBuf, WLAN_CFG_VALUE_LEN_MAX, "0x%x", (unsigned int)u4Value); + + return wlanCfgSet(prAdapter, pucKey, aucBuf, 0); +} + +enum { + STATE_EOF = 0, + STATE_TEXT = 1, + STATE_NEWLINE = 2 +}; + +struct WLAN_CFG_PARSE_STATE_S { + CHAR *ptr; + CHAR *text; + INT_32 nexttoken; + UINT_32 maxSize; +}; + +INT_32 wlanCfgFindNextToken(struct WLAN_CFG_PARSE_STATE_S *state) +{ + CHAR *x = state->ptr; + CHAR *s; + + if (state->nexttoken) { + INT_32 t = state->nexttoken; + + state->nexttoken = 0; + return t; + } + + for (;;) { + switch (*x) { + case 0: + state->ptr = x; + return STATE_EOF; + case '\n': + x++; + state->ptr = x; + return STATE_NEWLINE; + case ' ': + case '\t': + case '\r': + x++; + continue; + case '#': + while (*x && (*x != '\n')) + x++; + if (*x == '\n') { + state->ptr = x + 1; + return STATE_NEWLINE; + } + state->ptr = x; + return STATE_EOF; + default: + goto text; + } + } + +textdone: + state->ptr = x; + *s = 0; + return STATE_TEXT; +text: + state->text = s = x; +textresume: + for (;;) { + switch (*x) { + case 0: + goto textdone; + case ' ': + case '\t': + case '\r': + x++; + goto textdone; + case '\n': + state->nexttoken = STATE_NEWLINE; + x++; + goto textdone; + case '"': + x++; + for (;;) { + switch (*x) { + case 0: + /* unterminated quoted thing */ + state->ptr = x; + return STATE_EOF; + case '"': + x++; + goto textresume; + default: + *s++ = *x++; + } + } + break; + case '\\': + x++; + switch (*x) { + case 0: + goto textdone; + case 'n': + *s++ = '\n'; + break; + case 'r': + *s++ = '\r'; + break; + case 't': + *s++ = '\t'; + break; + case '\\': + *s++ = '\\'; + break; + case '\r': + /* \ -> line continuation */ + if (x[1] != '\n') { + x++; + continue; + } + case '\n': + /* \ -> line continuation */ + x++; + /* eat any extra whitespace */ + while ((*x == ' ') || (*x == '\t')) + x++; + continue; + default: + /* unknown escape -- just copy */ + *s++ = *x++; + } + continue; + default: + *s++ = *x++; + } + } + return STATE_EOF; +} + +WLAN_STATUS wlanCfgParseArgument(CHAR *cmdLine, INT_32 *argc, CHAR *argv[]) +{ + struct WLAN_CFG_PARSE_STATE_S state; + CHAR **args; + INT_32 nargs; + + if (cmdLine == NULL || argc == NULL || argv == NULL) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + args = argv; + nargs = 0; + state.ptr = cmdLine; + state.nexttoken = 0; + state.maxSize = 0; + + if (kalStrnLen(cmdLine, 512) >= 512) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + for (;;) { + switch (wlanCfgFindNextToken(&state)) { + case STATE_EOF: + goto exit; + case STATE_NEWLINE: + goto exit; + case STATE_TEXT: + if (nargs < WLAN_CFG_ARGV_MAX) + args[nargs++] = state.text; + break; + } + } + +exit: + *argc = nargs; + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanCfgParseAddEntry(IN P_ADAPTER_T prAdapter, + PUINT_8 pucKeyHead, PUINT_8 pucKeyTail, PUINT_8 pucValueHead, PUINT_8 pucValueTail) +{ + + UINT_8 aucKey[WLAN_CFG_KEY_LEN_MAX]; + UINT_8 aucValue[WLAN_CFG_VALUE_LEN_MAX]; + UINT_32 u4Len; + + kalMemZero(aucKey, sizeof(aucKey)); + kalMemZero(aucValue, sizeof(aucValue)); + + if ((pucKeyHead == NULL) + || (pucValueHead == NULL) + ) + return WLAN_STATUS_FAILURE; + + if (pucKeyTail) { + if (pucKeyHead > pucKeyTail) + return WLAN_STATUS_FAILURE; + u4Len = pucKeyTail - pucKeyHead + 1; + } else + u4Len = kalStrnLen(pucKeyHead, WLAN_CFG_KEY_LEN_MAX - 1); + + if (u4Len >= WLAN_CFG_KEY_LEN_MAX) + u4Len = WLAN_CFG_KEY_LEN_MAX - 1; + + if (u4Len < WLAN_CFG_VALUE_LEN_MAX) + kalStrnCpy(aucKey, pucKeyHead, u4Len); + else + DBGLOG(INIT, ERROR, "wifi entry parse error: Data len > %d\n", u4Len); + + if (pucValueTail) { + if (pucValueHead > pucValueTail) + return WLAN_STATUS_FAILURE; + u4Len = pucValueTail - pucValueHead + 1; + } else + u4Len = kalStrnLen(pucValueHead, WLAN_CFG_VALUE_LEN_MAX - 1); + + if (u4Len >= WLAN_CFG_VALUE_LEN_MAX) + u4Len = WLAN_CFG_VALUE_LEN_MAX - 1; + + if (u4Len < WLAN_CFG_VALUE_LEN_MAX) + kalStrnCpy(aucValue, pucValueHead, u4Len); + else + DBGLOG(INIT, ERROR, "wifi entry parse error: Data len > %d\n", u4Len); + + return wlanCfgSet(prAdapter, aucKey, aucValue, 0); +} + +enum { + WAIT_KEY_HEAD = 0, + WAIT_KEY_TAIL, + WAIT_VALUE_HEAD, + WAIT_VALUE_TAIL, + WAIT_COMMENT_TAIL +}; + +WLAN_STATUS wlanCfgParse(IN P_ADAPTER_T prAdapter, PUINT_8 pucConfigBuf, UINT_32 u4ConfigBufLen) +{ + + struct WLAN_CFG_PARSE_STATE_S state; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + CHAR **args; + INT_32 nargs; + + if (pucConfigBuf == NULL) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + if (kalStrnLen(pucConfigBuf, 4000) >= 4000) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + if (u4ConfigBufLen == 0) + return WLAN_STATUS_FAILURE; + args = apcArgv; + nargs = 0; + state.ptr = pucConfigBuf; + state.nexttoken = 0; + state.maxSize = u4ConfigBufLen; + + for (;;) { + switch (wlanCfgFindNextToken(&state)) { + case STATE_EOF: + if (nargs > 1) + wlanCfgParseAddEntry(prAdapter, args[0], NULL, args[1], NULL); + goto exit; + case STATE_NEWLINE: + if (nargs > 1) + wlanCfgParseAddEntry(prAdapter, args[0], NULL, args[1], NULL); + nargs = 0; + break; + case STATE_TEXT: + if (nargs < WLAN_CFG_ARGV_MAX) + args[nargs++] = state.text; + break; + } + } + +exit: + return WLAN_STATUS_SUCCESS; + +#if 0 + /* Old version */ + UINT_32 i; + UINT_8 c; + PUINT_8 pbuf; + UINT_8 ucState; + PUINT_8 pucKeyTail = NULL; + PUINT_8 pucKeyHead = NULL; + PUINT_8 pucValueHead = NULL; + PUINT_8 pucValueTail = NULL; + + ucState = WAIT_KEY_HEAD; + pbuf = pucConfigBuf; + + for (i = 0; i < u4ConfigBufLen; i++) { + c = pbuf[i]; + if (c == '\r' || c == '\n') { + + if (ucState == WAIT_VALUE_TAIL) { + /* Entry found */ + if (pucValueHead) + wlanCfgParseAddEntry(prAdapter, pucKeyHead, pucKeyTail, + pucValueHead, pucValueTail); + } + ucState = WAIT_KEY_HEAD; + pucKeyTail = NULL; + pucKeyHead = NULL; + pucValueHead = NULL; + pucValueTail = NULL; + + } else if (c == '=') { + if (ucState == WAIT_KEY_TAIL) { + pucKeyTail = &pbuf[i - 1]; + ucState = WAIT_VALUE_HEAD; + } + } else if (c == ' ' || c == '\t') { + if (ucState == WAIT_KEY_HEAD) + ; + else if (ucState == WAIT_KEY_TAIL) { + pucKeyTail = &pbuf[i - 1]; + ucState = WAIT_VALUE_HEAD; + } + } else { + + if (c == '#') { + /* comments */ + if (ucState == WAIT_KEY_HEAD) + ucState = WAIT_COMMENT_TAIL; + else if (ucState == WAIT_VALUE_TAIL) + pucValueTail = &pbuf[i]; + + } else { + if (ucState == WAIT_KEY_HEAD) { + pucKeyHead = &pbuf[i]; + pucKeyTail = &pbuf[i]; + ucState = WAIT_KEY_TAIL; + } else if (ucState == WAIT_VALUE_HEAD) { + pucValueHead = &pbuf[i]; + pucValueTail = &pbuf[i]; + ucState = WAIT_VALUE_TAIL; + } else if (ucState == WAIT_VALUE_TAIL) + pucValueTail = &pbuf[i]; + } + } + + } /* for */ + + if (ucState == WAIT_VALUE_TAIL) { + /* Entry found */ + if (pucValueTail) + wlanCfgParseAddEntry(prAdapter, pucKeyHead, pucKeyTail, pucValueHead, pucValueTail); + } +#endif + + return WLAN_STATUS_SUCCESS; +} +#endif + +#if CFG_SUPPORT_CFG_FILE +WLAN_STATUS wlanCfgInit(IN P_ADAPTER_T prAdapter, PUINT_8 pucConfigBuf, UINT_32 u4ConfigBufLen, UINT_32 u4Flags) +{ + P_WLAN_CFG_T prWlanCfg; + /* P_WLAN_CFG_ENTRY_T prWlanCfgEntry; */ + prAdapter->prWlanCfg = &prAdapter->rWlanCfg; + prWlanCfg = prAdapter->prWlanCfg; + + kalMemZero(prWlanCfg, sizeof(WLAN_CFG_T)); + ASSERT(prWlanCfg); + prWlanCfg->u4WlanCfgEntryNumMax = WLAN_CFG_ENTRY_NUM_MAX; + prWlanCfg->u4WlanCfgKeyLenMax = WLAN_CFG_KEY_LEN_MAX; + prWlanCfg->u4WlanCfgValueLenMax = WLAN_CFG_VALUE_LEN_MAX; +#if 0 + DBGLOG(INIT, INFO, "Init wifi config len %u max entry %u\n", u4ConfigBufLen, prWlanCfg->u4WlanCfgEntryNumMax); +#endif + /* self test */ + wlanCfgSet(prAdapter, "ConfigValid", "0x123", 0); + if (wlanCfgGetUint32(prAdapter, "ConfigValid", 0) != 0x123) + DBGLOG(INIT, ERROR, "wifi config error %u\n", __LINE__); + wlanCfgSet(prAdapter, "ConfigValid", "1", 0); + if (wlanCfgGetUint32(prAdapter, "ConfigValid", 0) != 1) + DBGLOG(INIT, ERROR, "wifi config error %u\n", __LINE__); +#if 0 /* soc chip didn't support these parameters now */ + /* Add initil config */ + /* use g,wlan,p2p,ap as prefix */ + /* Don't set cb here , overwrite by another api */ + wlanCfgSet(prAdapter, "TxLdpc", "1", 0); + wlanCfgSet(prAdapter, "RxLdpc", "1", 0); + wlanCfgSet(prAdapter, "RxBeamformee", "1", 0); + wlanCfgSet(prAdapter, "RoamTh1", "100", 0); + wlanCfgSet(prAdapter, "RoamTh2", "150", 0); + wlanCfgSet(prAdapter, "wlanRxLdpc", "1", 0); + wlanCfgSet(prAdapter, "apRxLdpc", "1", 0); + wlanCfgSet(prAdapter, "p2pRxLdpc", "1", 0); +#endif + /* Parse the pucConfigBuff */ + + if (pucConfigBuf && (u4ConfigBufLen > 0)) + wlanCfgParse(prAdapter, pucConfigBuf, u4ConfigBufLen); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to initialize WLAN feature options +* +* @param prAdapter Pointer of ADAPTER_T +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanCfgApply(IN P_ADAPTER_T prAdapter) +{ +#define STR2BYTE(s) (((((PUINT_8)s)[0]-'0')*10)+(((PUINT_8)s)[1]-'0')) + CHAR aucValue[WLAN_CFG_VALUE_LEN_MAX]; + P_WIFI_VAR_T prWifiVar = &prAdapter->rWifiVar; + P_REG_INFO_T prRegInfo = &prAdapter->prGlueInfo->rRegInfo; + P_TX_PWR_PARAM_T prTxPwr = &prRegInfo->rTxPwr; + + kalMemZero(aucValue, sizeof(aucValue)); + DBGLOG(INIT, LOUD, "CFG_FILE: Apply Config File\n"); + /* Apply COUNTRY Config */ + if (wlanCfgGet(prAdapter, "country", aucValue, "", 0) == WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, LOUD, "CFG_FILE: Found Country Key, Value=%s\n", aucValue); + prAdapter->rWifiVar.rConnSettings.u2CountryCode = + (((UINT_16) aucValue[0]) << 8) | ((UINT_16) aucValue[1]); + prRegInfo->au2CountryCode[0] = aucValue[0]; + prRegInfo->au2CountryCode[1] = aucValue[1]; + } + prWifiVar->ucApWpsMode = (UINT_8) wlanCfgGetUint32(prAdapter, "ApWpsMode", 0); + prWifiVar->ucCert11nMode = (UINT_8)wlanCfgGetUint32(prAdapter, "Cert11nMode", 0); + prWifiVar->ucApChannel = (UINT_8) wlanCfgGetUint32(prAdapter, "ApChannel", 0); + DBGLOG(INIT, LOUD, "CFG_FILE: ucApWpsMode = %u, ucCert11nMode = %u, ucApChannel = %u\n", + prWifiVar->ucApWpsMode, prWifiVar->ucCert11nMode, prWifiVar->ucApChannel); +#if 0 + if (prWifiVar->ucCert11nMode == 1) + nicWriteMcr(prAdapter, 0x11111115, 1); +#endif +#if CFG_SUPPORT_MTK_SYNERGY + prWifiVar->ucMtkOui = (UINT_8) wlanCfgGetUint32(prAdapter, "MtkOui", 1); + prWifiVar->u4MtkOuiCap = (UINT_32) wlanCfgGetUint32(prAdapter, "MtkOuiCap", 0); + prWifiVar->aucMtkFeature[0] = 0xff; + prWifiVar->aucMtkFeature[1] = 0xff; + prWifiVar->aucMtkFeature[2] = 0xff; + prWifiVar->aucMtkFeature[3] = 0xff; +#endif + + if (wlanCfgGet(prAdapter, "5G_support", aucValue, "", 0) == WLAN_STATUS_SUCCESS) + prRegInfo->ucSupport5GBand = (*aucValue == 'y') ? 1 : 0; + if (wlanCfgGet(prAdapter, "TxPower2G4CCK", aucValue, "", 0) == WLAN_STATUS_SUCCESS + && kalStrLen(aucValue) == 2) { + prTxPwr->cTxPwr2G4Cck = STR2BYTE(aucValue); + DBGLOG(INIT, LOUD, "2.4G cck=%d\n", prTxPwr->cTxPwr2G4Cck); + } + if (wlanCfgGet(prAdapter, "TxPower2G4OFDM", aucValue, "", 0) == WLAN_STATUS_SUCCESS && + kalStrLen(aucValue) == 10) { + prTxPwr->cTxPwr2G4OFDM_BPSK = STR2BYTE(aucValue); + prTxPwr->cTxPwr2G4OFDM_QPSK = STR2BYTE(aucValue + 2); + prTxPwr->cTxPwr2G4OFDM_16QAM = STR2BYTE(aucValue + 4); + prTxPwr->cTxPwr2G4OFDM_48Mbps = STR2BYTE(aucValue + 6); + prTxPwr->cTxPwr2G4OFDM_54Mbps = STR2BYTE(aucValue + 8); + DBGLOG(INIT, LOUD, "2.4G OFDM=%d,%d,%d,%d,%d\n", + prTxPwr->cTxPwr2G4OFDM_BPSK, prTxPwr->cTxPwr2G4OFDM_QPSK, + prTxPwr->cTxPwr2G4OFDM_16QAM, prTxPwr->cTxPwr2G4OFDM_48Mbps, + prTxPwr->cTxPwr2G4OFDM_54Mbps); + } + if (wlanCfgGet(prAdapter, "TxPower2G4HT20", aucValue, "", 0) == WLAN_STATUS_SUCCESS && + kalStrLen(aucValue) == 12) { + prTxPwr->cTxPwr2G4HT20_BPSK = STR2BYTE(aucValue); + prTxPwr->cTxPwr2G4HT20_QPSK = STR2BYTE(aucValue + 2); + prTxPwr->cTxPwr2G4HT20_16QAM = STR2BYTE(aucValue + 4); + prTxPwr->cTxPwr2G4HT20_MCS5 = STR2BYTE(aucValue + 6); + prTxPwr->cTxPwr2G4HT20_MCS6 = STR2BYTE(aucValue + 8); + prTxPwr->cTxPwr2G4HT20_MCS7 = STR2BYTE(aucValue + 10); + DBGLOG(INIT, LOUD, "2.4G HT20=%d,%d,%d,%d,%d,%d\n", + prTxPwr->cTxPwr2G4HT20_BPSK, prTxPwr->cTxPwr2G4HT20_QPSK, + prTxPwr->cTxPwr2G4HT20_16QAM, prTxPwr->cTxPwr2G4HT20_MCS5, + prTxPwr->cTxPwr2G4HT20_MCS6, prTxPwr->cTxPwr2G4HT20_MCS7); + } + if (wlanCfgGet(prAdapter, "TxPower2G4HT40", aucValue, "", 0) == WLAN_STATUS_SUCCESS && + kalStrLen(aucValue) == 12) { + prTxPwr->cTxPwr2G4HT40_BPSK = STR2BYTE(aucValue); + prTxPwr->cTxPwr2G4HT40_QPSK = STR2BYTE(aucValue + 2); + prTxPwr->cTxPwr2G4HT40_16QAM = STR2BYTE(aucValue + 4); + prTxPwr->cTxPwr2G4HT40_MCS5 = STR2BYTE(aucValue + 6); + prTxPwr->cTxPwr2G4HT40_MCS6 = STR2BYTE(aucValue + 8); + prTxPwr->cTxPwr2G4HT40_MCS7 = STR2BYTE(aucValue + 10); + DBGLOG(INIT, LOUD, "2.4G HT40=%d,%d,%d,%d,%d,%d\n", + prTxPwr->cTxPwr2G4HT40_BPSK, prTxPwr->cTxPwr2G4HT40_QPSK, + prTxPwr->cTxPwr2G4HT40_16QAM, prTxPwr->cTxPwr2G4HT40_MCS5, + prTxPwr->cTxPwr2G4HT40_MCS6, prTxPwr->cTxPwr2G4HT40_MCS7); + } + if (wlanCfgGet(prAdapter, "TxPower5GOFDM", aucValue, "", 0) == WLAN_STATUS_SUCCESS + && kalStrLen(aucValue) == 10) { + prTxPwr->cTxPwr5GOFDM_BPSK = STR2BYTE(aucValue); + prTxPwr->cTxPwr5GOFDM_QPSK = STR2BYTE(aucValue + 2); + prTxPwr->cTxPwr5GOFDM_16QAM = STR2BYTE(aucValue + 4); + prTxPwr->cTxPwr5GOFDM_48Mbps = STR2BYTE(aucValue + 6); + prTxPwr->cTxPwr5GOFDM_54Mbps = STR2BYTE(aucValue + 8); + DBGLOG(INIT, LOUD, "5G OFDM=%d,%d,%d,%d,%d\n", + prTxPwr->cTxPwr5GOFDM_BPSK, prTxPwr->cTxPwr5GOFDM_QPSK, + prTxPwr->cTxPwr5GOFDM_16QAM, prTxPwr->cTxPwr5GOFDM_48Mbps, + prTxPwr->cTxPwr5GOFDM_54Mbps); + } + if (wlanCfgGet(prAdapter, "TxPower5GHT20", aucValue, "", 0) == WLAN_STATUS_SUCCESS + && kalStrLen(aucValue) == 12) { + prTxPwr->cTxPwr5GHT20_BPSK = STR2BYTE(aucValue); + prTxPwr->cTxPwr5GHT20_QPSK = STR2BYTE(aucValue + 2); + prTxPwr->cTxPwr5GHT20_16QAM = STR2BYTE(aucValue + 4); + prTxPwr->cTxPwr5GHT20_MCS5 = STR2BYTE(aucValue + 6); + prTxPwr->cTxPwr5GHT20_MCS6 = STR2BYTE(aucValue + 8); + prTxPwr->cTxPwr5GHT20_MCS7 = STR2BYTE(aucValue + 10); + DBGLOG(INIT, LOUD, "5G HT20=%d,%d,%d,%d,%d,%d\n", + prTxPwr->cTxPwr5GHT20_BPSK, prTxPwr->cTxPwr5GHT20_QPSK, + prTxPwr->cTxPwr5GHT20_16QAM, prTxPwr->cTxPwr5GHT20_MCS5, prTxPwr->cTxPwr5GHT20_MCS6, + prTxPwr->cTxPwr5GHT20_MCS7); + } + if (wlanCfgGet(prAdapter, "TxPower5GHT40", aucValue, "", 0) == WLAN_STATUS_SUCCESS + && kalStrLen(aucValue) == 12) { + prTxPwr->cTxPwr5GHT40_BPSK = STR2BYTE(aucValue); + prTxPwr->cTxPwr5GHT40_QPSK = STR2BYTE(aucValue + 2); + prTxPwr->cTxPwr5GHT40_16QAM = STR2BYTE(aucValue + 4); + prTxPwr->cTxPwr5GHT40_MCS5 = STR2BYTE(aucValue + 6); + prTxPwr->cTxPwr5GHT40_MCS6 = STR2BYTE(aucValue + 8); + prTxPwr->cTxPwr5GHT40_MCS7 = STR2BYTE(aucValue + 10); + DBGLOG(INIT, LOUD, "5G HT40=%d,%d,%d,%d,%d,%d\n", + prTxPwr->cTxPwr5GHT40_BPSK, prTxPwr->cTxPwr5GHT40_QPSK, + prTxPwr->cTxPwr5GHT40_16QAM, prTxPwr->cTxPwr5GHT40_MCS5, prTxPwr->cTxPwr5GHT40_MCS6, + prTxPwr->cTxPwr5GHT40_MCS7); + } + if (wlanCfgGet(prAdapter, "MacAddr", aucValue, "", 0) == WLAN_STATUS_SUCCESS) { + PUINT_8 pucMac = &prRegInfo->aucMacAddr[0]; + + if (sscanf(aucValue, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", + pucMac, pucMac+1, pucMac+2, pucMac+3, pucMac+4, pucMac+5) != 6) { + DBGLOG(INIT, ERROR, "Parse mac address failed, macstr %s\n", aucValue); + kalMemZero(pucMac, MAC_ADDR_LEN); + } + } + if (wlanCfgGet(prAdapter, "ApUapsd", aucValue, "", 0) == WLAN_STATUS_SUCCESS) { + if (*aucValue == '1') + prAdapter->rWifiVar.fgSupportUAPSD = TRUE; + else if (*aucValue == '0') + prAdapter->rWifiVar.fgSupportUAPSD = FALSE; + + DBGLOG(INIT, INFO, "Ap Mode Uapsd Status: %s\n", aucValue); + } + + prWifiVar->aucAifsN[WMM_AC_BE_INDEX] = + (UINT_8) wlanCfgGetUint32(prAdapter, "BeAifsN", 3); + prWifiVar->aucAifsN[WMM_AC_BK_INDEX] = + (UINT_8) wlanCfgGetUint32(prAdapter, "BkAifsN", 7); + prWifiVar->aucAifsN[WMM_AC_VI_INDEX] = + (UINT_8) wlanCfgGetUint32(prAdapter, "ViAifsN", 1); + prWifiVar->aucAifsN[WMM_AC_VO_INDEX] = + (UINT_8) wlanCfgGetUint32(prAdapter, "VoAifsN", 1); + + prWifiVar->aucCwMin[WMM_AC_BE_INDEX] = + (UINT_8) wlanCfgGetUint32(prAdapter, "BeCwMin", 4); + prWifiVar->aucCwMin[WMM_AC_BK_INDEX] = + (UINT_8) wlanCfgGetUint32(prAdapter, "BkCwMin", 4); + prWifiVar->aucCwMin[WMM_AC_VI_INDEX] = + (UINT_8) wlanCfgGetUint32(prAdapter, "ViCwMin", 3); + prWifiVar->aucCwMin[WMM_AC_VO_INDEX] = + (UINT_8) wlanCfgGetUint32(prAdapter, "VoCwMin", 2); + + prWifiVar->au2CwMax[WMM_AC_BE_INDEX] = + (UINT_16) wlanCfgGetUint32(prAdapter, "BeCwMax", 7); + prWifiVar->au2CwMax[WMM_AC_BK_INDEX] = + (UINT_16) wlanCfgGetUint32(prAdapter, "BkCwMax", 10); + prWifiVar->au2CwMax[WMM_AC_VI_INDEX] = + (UINT_16) wlanCfgGetUint32(prAdapter, "ViCwMax", 4); + prWifiVar->au2CwMax[WMM_AC_VO_INDEX] = + (UINT_16) wlanCfgGetUint32(prAdapter, "VoCwMax", 3); + + prWifiVar->au2TxOp[WMM_AC_BE_INDEX] = + (UINT_16) wlanCfgGetUint32(prAdapter, "BeTxOp", 0); + prWifiVar->au2TxOp[WMM_AC_BK_INDEX] = + (UINT_16) wlanCfgGetUint32(prAdapter, "BkTxOp", 0); + prWifiVar->au2TxOp[WMM_AC_VI_INDEX] = + (UINT_16) wlanCfgGetUint32(prAdapter, "ViTxOp", 94); + prWifiVar->au2TxOp[WMM_AC_VO_INDEX] = + (UINT_16) wlanCfgGetUint32(prAdapter, "VoTxOp", 47); + + prAdapter->prGlueInfo->i4Priority = wlanCfgGetInt32(prAdapter, "RTPri", 0); + /* TODO: Apply other Config */ +} +#endif /* CFG_SUPPORT_CFG_FILE */ + +VOID wlanReleasePendingCmdById(P_ADAPTER_T prAdapter, UINT_8 ucCid) +{ + 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); + DBGLOG(OID, INFO, "Remove pending Cmd: CID %d\n", ucCid); + + /* 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->ucCID != ucCid) { + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + continue; + } + + if (prCmdInfo->pfCmdTimeoutHandler) { + prCmdInfo->pfCmdTimeoutHandler(prAdapter, prCmdInfo); + } else if (prCmdInfo->fgIsOid) { + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, 0, WLAN_STATUS_FAILURE); + } + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); +} + +/* Translate Decimals string to Hex +** The result will be put in a 2bytes variable. +** Integer part will occupy the left most 3 bits, and decimal part is in the left 13 bits +** Integer part can be parsed by kstrtou16, decimal part should be translated by mutiplying +** 16 and then pick integer part. +** For example +*/ +UINT_32 wlanDecimalStr2Hexadecimals(PUINT_8 pucDecimalStr, PUINT_16 pu2Out) +{ + UINT_8 aucDecimalStr[32] = {0,}; + PUINT_8 pucDecimalPart = NULL; + PUINT_8 tmp = NULL; + UINT_32 u4Result = 0; + UINT_32 u4Ret = 0; + UINT_32 u4Degree = 0; + UINT_32 u4Remain = 0; + UINT_8 ucAccuracy = 4; /* Hex decimals accuarcy is 4 bytes */ + UINT_32 u4Base = 1; + + if (!pu2Out || !pucDecimalStr) + return 1; + + while (*pucDecimalStr == '0') + pucDecimalStr++; + kalStrnCpy(aucDecimalStr, pucDecimalStr, sizeof(aucDecimalStr) - 1); + pucDecimalPart = strchr(aucDecimalStr, '.'); + if (!pucDecimalPart) { + DBGLOG(INIT, INFO, "No decimal part, ori str %s\n", pucDecimalStr); + goto integer_part; + } + *pucDecimalPart++ = 0; + /* get decimal degree */ + tmp = pucDecimalPart + strlen(pucDecimalPart); + do { + if (tmp == pucDecimalPart) { + DBGLOG(INIT, INFO, "Decimal part are all 0, ori str %s\n", pucDecimalStr); + goto integer_part; + } + tmp--; + } while (*tmp == '0'); + + *(++tmp) = 0; + u4Degree = (UINT_32)(tmp - pucDecimalPart); + /* if decimal part is not 0, translate it to hexadecimal decimals */ + /* Power(10, degree) */ + for (; u4Remain < u4Degree; u4Remain++) + u4Base *= 10; + + while (*pucDecimalPart == '0') + pucDecimalPart++; + + u4Ret = kstrtou32(pucDecimalPart, 0, &u4Remain); + if (u4Ret) { + DBGLOG(INIT, ERROR, "Parse decimal str %s error, degree %u\n", + pucDecimalPart, u4Degree); + return u4Ret; + } + + do { + u4Remain *= 16; + u4Result |= (u4Remain / u4Base) << ((ucAccuracy-1) * 4); + u4Remain %= u4Base; + ucAccuracy--; + } while (u4Remain && ucAccuracy > 0); + /* Each Hex Decimal byte was left shift more than 3 bits, so need + ** right shift 3 bits at last + ** For example, mmmnnnnnnnnnnnnn. + ** mmm is integer part, n represents decimals part. + ** the left most 4 n are shift 9 bits. But in for loop, we shift 12 bits + **/ + u4Result >>= 3; + u4Remain = 0; + +integer_part: + u4Ret = kstrtou32(aucDecimalStr, 0, &u4Remain); + u4Result |= u4Remain << 13; + + if (u4Ret) + DBGLOG(INIT, ERROR, "Parse integer str %s error\n", aucDecimalStr); + else { + *pu2Out = u4Result & 0xffff; + DBGLOG(INIT, TRACE, "Result 0x%04x\n", *pu2Out); + } + return u4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query LTE safe channels. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanQueryLteSafeChannel(IN P_ADAPTER_T prAdapter) +{ + WLAN_STATUS rResult = WLAN_STATUS_FAILURE; + PARAM_GET_CHN_INFO rQueryLteChn; + + DBGLOG(P2P, TRACE, "[ACS]Get LTE safe channels\n"); + + do { + if (!prAdapter) + break; + + kalMemZero(&rQueryLteChn, sizeof(PARAM_GET_CHN_INFO)); + + /* Get LTE safe channel list */ + wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LTE_CHN, + FALSE, + TRUE, + FALSE, + nicCmdEventQueryLteSafeChn, + nicOidCmdTimeoutCommon, + 0, + NULL, + &rQueryLteChn, + 0); + rResult = WLAN_STATUS_SUCCESS; + } while (FALSE); + + return rResult; +} /* wlanoidQueryLteSafeChannel */ + +uint8_t +wlanGetChannelIndex(IN uint8_t channel) +{ + uint8_t ucIdx = 1; + + if (channel <= 14) + ucIdx = channel - 1; + else if (channel >= 36 && channel <= 64) + ucIdx = 14 + (channel - 36) / 4; + else if (channel >= 100 && channel <= 140) + ucIdx = 14 + 8 + (channel - 100) / 4; + else if (channel >= 149 && channel <= 173) + ucIdx = 14 + 8 + 11 + (channel - 149) / 4; + else if (channel >= 184 && channel <= 216) + ucIdx = 14 + 8 + 11 + 7 + (channel - 184) / 4; + else + DBGLOG(SCN, ERROR, "Invalid ch %u\n", channel); + + return ucIdx; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/common/wlan_oid.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/common/wlan_oid.c new file mode 100644 index 0000000000000..dcb5148c4b57b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/common/wlan_oid.c @@ -0,0 +1,12725 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/****************************************************************************** + * C O M P I L E 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" + +#ifdef FW_CFG_SUPPORT +#include "fwcfg.h" +#endif +#include + +/****************************************************************************** +* C O N S T A N T S +******************************************************************************* +*/ + +/****************************************************************************** +* D A T A T Y P E S +******************************************************************************* +*/ + +/****************************************************************************** +* P U B L I C D A T A +******************************************************************************* +*/ +/* tx power scenario enum: + * declared in /hardware/libhardware_legacy/include/hardware_legacy/wifi_hal.h + * enum ENUM_TX_POWER_SCENARIO { + * WIFI_POWER_SCENARIO_VOICE_CALL = 0, + * WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF = 1, + * WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON = 2, + * WIFI_POWER_SCENARIO_ON_BODY_CELL_OFF = 3, + * WIFI_POWER_SCENARIO_ON_BODY_CELL_ON = 4, + * }; + */ +static struct TX_POWER_SCENARIO_ENTRY g_txPowerScenario[] = { + { TRUE, 12, TRUE, 12 }, /* WIFI_POWER_SCENARIO_VOICE_CALL */ + { TRUE, 12, TRUE, 12 }, /* WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF */ + { TRUE, 12, TRUE, 12 }, /* WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON */ + { TRUE, 12, TRUE, 12 }, /* WIFI_POWER_SCENARIO_ON_BODY_CELL_OFF */ + { TRUE, 12, TRUE, 12 }, /* WIFI_POWER_SCENARIO_ON_BODY_CELL_ON */ +}; + +/****************************************************************************** +* P R I V A T E D A T A +******************************************************************************* +*/ + +/****************************************************************************** +* M A C R O S +******************************************************************************* +*/ + +/****************************************************************************** +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************* +*/ + +/****************************************************************************** +* F U N C T I O N S +******************************************************************************* +*/ +#if CFG_ENABLE_STATISTICS_BUFFERING +static BOOLEAN IsBufferedStatisticsUsable(P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + if (prAdapter->fgIsStatValid == TRUE && + (kalGetTimeTick() - prAdapter->rStatUpdateTime) <= CFG_STATISTICS_VALID_CYCLE) + return TRUE; + else + return FALSE; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the supported physical layer network +* type that can be used by the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryNetworkTypesSupported(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + UINT_32 u4NumItem = 0; + ENUM_PARAM_NETWORK_TYPE_T eSupportedNetworks[PARAM_NETWORK_TYPE_NUM]; + PPARAM_NETWORK_TYPE_LIST prSupported; + + /* The array of all physical layer network subtypes that the driver supports. */ + + DEBUGFUNC("wlanoidQueryNetworkTypesSupported"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + /* Init. */ + for (u4NumItem = 0; u4NumItem < PARAM_NETWORK_TYPE_NUM; u4NumItem++) + eSupportedNetworks[u4NumItem] = 0; + + u4NumItem = 0; + + eSupportedNetworks[u4NumItem] = PARAM_NETWORK_TYPE_DS; + u4NumItem++; + + eSupportedNetworks[u4NumItem] = PARAM_NETWORK_TYPE_OFDM24; + u4NumItem++; + + *pu4QueryInfoLen = + (UINT_32) OFFSET_OF(PARAM_NETWORK_TYPE_LIST, eNetworkType) + + (u4NumItem * sizeof(ENUM_PARAM_NETWORK_TYPE_T)); + + if (u4QueryBufferLen < *pu4QueryInfoLen) + return WLAN_STATUS_INVALID_LENGTH; + + prSupported = (PPARAM_NETWORK_TYPE_LIST) pvQueryBuffer; + prSupported->NumberOfItems = u4NumItem; + kalMemCopy(prSupported->eNetworkType, eSupportedNetworks, u4NumItem * sizeof(ENUM_PARAM_NETWORK_TYPE_T)); + + DBGLOG(OID, TRACE, "NDIS supported network type list: %u\n", prSupported->NumberOfItems); + DBGLOG_MEM8(OID, TRACE, prSupported, *pu4QueryInfoLen); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryNetworkTypesSupported */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current physical layer network +* type used by the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the +* call failed due to invalid length of the query +* buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryNetworkTypeInUse(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + /* TODO: need to check the OID handler content again!! */ + + ENUM_PARAM_NETWORK_TYPE_T rCurrentNetworkTypeInUse = PARAM_NETWORK_TYPE_OFDM24; + + DEBUGFUNC("wlanoidQueryNetworkTypeInUse"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(ENUM_PARAM_NETWORK_TYPE_T)) { + *pu4QueryInfoLen = sizeof(ENUM_PARAM_NETWORK_TYPE_T); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) + rCurrentNetworkTypeInUse = (ENUM_PARAM_NETWORK_TYPE_T) (prAdapter->rWlanInfo.ucNetworkType); + else + rCurrentNetworkTypeInUse = (ENUM_PARAM_NETWORK_TYPE_T) (prAdapter->rWlanInfo.ucNetworkTypeInUse); + + *(P_ENUM_PARAM_NETWORK_TYPE_T) pvQueryBuffer = rCurrentNetworkTypeInUse; + *pu4QueryInfoLen = sizeof(ENUM_PARAM_NETWORK_TYPE_T); + + DBGLOG(OID, TRACE, "Network type in use: %d\n", rCurrentNetworkTypeInUse); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryNetworkTypeInUse */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the physical layer network type used +* by the driver. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns the +* amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS The given network type is supported and accepted. +* \retval WLAN_STATUS_INVALID_DATA The given network type is not in the +* supported list. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetNetworkTypeInUse(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + /* TODO: need to check the OID handler content again!! */ + + ENUM_PARAM_NETWORK_TYPE_T eNewNetworkType; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidSetNetworkTypeInUse"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(ENUM_PARAM_NETWORK_TYPE_T)) { + *pu4SetInfoLen = sizeof(ENUM_PARAM_NETWORK_TYPE_T); + return WLAN_STATUS_INVALID_LENGTH; + } + + eNewNetworkType = *(P_ENUM_PARAM_NETWORK_TYPE_T) pvSetBuffer; + *pu4SetInfoLen = sizeof(ENUM_PARAM_NETWORK_TYPE_T); + + DBGLOG(OID, INFO, "New network type: %d mode\n", eNewNetworkType); + + switch (eNewNetworkType) { + + case PARAM_NETWORK_TYPE_DS: + prAdapter->rWlanInfo.ucNetworkTypeInUse = (UINT_8) PARAM_NETWORK_TYPE_DS; + break; + + case PARAM_NETWORK_TYPE_OFDM5: + prAdapter->rWlanInfo.ucNetworkTypeInUse = (UINT_8) PARAM_NETWORK_TYPE_OFDM5; + break; + + case PARAM_NETWORK_TYPE_OFDM24: + prAdapter->rWlanInfo.ucNetworkTypeInUse = (UINT_8) PARAM_NETWORK_TYPE_OFDM24; + break; + + case PARAM_NETWORK_TYPE_AUTOMODE: + prAdapter->rWlanInfo.ucNetworkTypeInUse = (UINT_8) PARAM_NETWORK_TYPE_AUTOMODE; + break; + + case PARAM_NETWORK_TYPE_FH: + DBGLOG(OID, INFO, "Not support network type: %d\n", eNewNetworkType); + rStatus = WLAN_STATUS_NOT_SUPPORTED; + break; + + default: + DBGLOG(OID, INFO, "Unknown network type: %d\n", eNewNetworkType); + rStatus = WLAN_STATUS_INVALID_DATA; + break; + } + + /* Verify if we support the new network type. */ + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(OID, WARN, "Unknown network type: %d\n", eNewNetworkType); + + return rStatus; +} /* wlanoidSetNetworkTypeInUse */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current BSSID. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryBssid(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryBssid"); + + ASSERT(prAdapter); + + if (u4QueryBufferLen < MAC_ADDR_LEN) { + ASSERT(pu4QueryInfoLen); + *pu4QueryInfoLen = MAC_ADDR_LEN; + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + ASSERT(u4QueryBufferLen >= MAC_ADDR_LEN); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) + kalMemCopy(pvQueryBuffer, prAdapter->rWlanInfo.rCurrBssId.arMacAddress, MAC_ADDR_LEN); + else if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_IBSS) { + PARAM_MAC_ADDRESS aucTemp; /*!< BSSID */ + + COPY_MAC_ADDR(aucTemp, prAdapter->rWlanInfo.rCurrBssId.arMacAddress); + aucTemp[0] &= ~BIT(0); + aucTemp[1] |= BIT(1); + COPY_MAC_ADDR(pvQueryBuffer, aucTemp); + } else + rStatus = WLAN_STATUS_ADAPTER_NOT_READY; + + *pu4QueryInfoLen = MAC_ADDR_LEN; + return rStatus; +} /* wlanoidQueryBssid */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the list of all BSSIDs detected by +* the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryBssidList(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + UINT_32 i, u4BssidListExLen; + P_PARAM_BSSID_LIST_EX_T prList; + P_PARAM_BSSID_EX_T prBssidEx; + PUINT_8 cp; + + DEBUGFUNC("wlanoidQueryBssidList"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + + if (!pvQueryBuffer) + return WLAN_STATUS_INVALID_DATA; + } + + prGlueInfo = prAdapter->prGlueInfo; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in qeury BSSID list! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + u4BssidListExLen = 0; + + if (prAdapter->fgIsRadioOff == FALSE) { + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) + u4BssidListExLen += ALIGN_4(prAdapter->rWlanInfo.arScanResult[i].u4Length); + } + + if (u4BssidListExLen) + u4BssidListExLen += 4; /* u4NumberOfItems. */ + else + u4BssidListExLen = sizeof(PARAM_BSSID_LIST_EX_T); + + *pu4QueryInfoLen = u4BssidListExLen; + + if (u4QueryBufferLen < *pu4QueryInfoLen) + return WLAN_STATUS_INVALID_LENGTH; + + /* Clear the buffer */ + kalMemZero(pvQueryBuffer, u4BssidListExLen); + + prList = (P_PARAM_BSSID_LIST_EX_T) pvQueryBuffer; + cp = (PUINT_8) &prList->arBssid[0]; + + if (prAdapter->fgIsRadioOff == FALSE && prAdapter->rWlanInfo.u4ScanResultNum > 0) { + /* fill up for each entry */ + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + prBssidEx = (P_PARAM_BSSID_EX_T) cp; + + /* copy structure */ + kalMemCopy(prBssidEx, + &(prAdapter->rWlanInfo.arScanResult[i]), OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); + + /*For WHQL test, Rssi should be in range -10 ~ -200 dBm */ + if (prBssidEx->rRssi > PARAM_WHQL_RSSI_MAX_DBM) + prBssidEx->rRssi = PARAM_WHQL_RSSI_MAX_DBM; + + if (prAdapter->rWlanInfo.arScanResult[i].u4IELength > 0) { + /* copy IEs */ + kalMemCopy(prBssidEx->aucIEs, + prAdapter->rWlanInfo.apucScanResultIEs[i], + prAdapter->rWlanInfo.arScanResult[i].u4IELength); + } + /* 4-bytes alignement */ + prBssidEx->u4Length = ALIGN_4(prBssidEx->u4Length); + + cp += prBssidEx->u4Length; + prList->u4NumberOfItems++; + } + } + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryBssidList */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request the driver to perform +* scanning. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBssidListScan(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_SSID_T prSsid; + PARAM_SSID_T rSsid; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidSetBssidListScan()"); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set BSSID list scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pu4SetInfoLen); + *pu4SetInfoLen = 0; + + if (prAdapter->fgIsRadioOff) { + DBGLOG(OID, WARN, "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + DBGLOG(OID, TRACE, "Scan\n"); + + if (pvSetBuffer != NULL && u4SetBufferLen != 0) { + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, pvSetBuffer, u4SetBufferLen); + prSsid = &rSsid; + } else { + prSsid = NULL; + } + +#if CFG_SUPPORT_RDD_TEST_MODE + if (prAdapter->prGlueInfo->rRegInfo.u4RddTestMode) { + if ((prAdapter->fgEnOnlineScan == TRUE) && (prAdapter->ucRddStatus)) { + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) { + aisFsmScanRequest(prAdapter, prSsid, NULL, 0); + } else { + /* reject the scan request */ + rStatus = WLAN_STATUS_FAILURE; + } + } else { + /* reject the scan request */ + rStatus = WLAN_STATUS_FAILURE; + } + } else +#endif + { + if (prAdapter->fgEnOnlineScan == TRUE) { + aisFsmScanRequest(prAdapter, prSsid, NULL, 0); + } else if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) { + aisFsmScanRequest(prAdapter, prSsid, NULL, 0); + } else { + /* reject the scan request */ + rStatus = WLAN_STATUS_FAILURE; + } + } + + return rStatus; +} /* wlanoidSetBssidListScan */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanoidGetChannelInfo(IN P_ADAPTER_T prAdapter, IN PUINT_8 puPartialScanReq) +{ + struct cfg80211_scan_request *scan_req_t = NULL; + struct ieee80211_channel *channel_tmp = NULL; + P_PARTIAL_SCAN_INFO PartialScanChannel = NULL; + int i = 0; + int j = 0; + UINT_8 channel_num = 0; + UINT_8 channel_counts = 0; + + if ((prAdapter == NULL) || (prAdapter->prGlueInfo == NULL) || + (puPartialScanReq == NULL)) + return FALSE; + + scan_req_t = (struct cfg80211_scan_request *)puPartialScanReq; + if (scan_req_t->n_channels != 0) { + + channel_counts = scan_req_t->n_channels; + DBGLOG(OID, TRACE, "scan channel number: n_channels=%d\n", channel_counts); + if (channel_counts > MAXIMUM_OPERATION_CHANNEL_LIST) + return TRUE; + /* + * if (scan_req_t->n_channels > MAXIMUM_OPERATION_CHANNEL_LIST) { + * DBGLOG(REQ, TRACE, "request channel great max num, reset channel num\n"); + * } + */ + PartialScanChannel = (P_PARTIAL_SCAN_INFO) kalMemAlloc(sizeof(PARTIAL_SCAN_INFO), VIR_MEM_TYPE); + if (PartialScanChannel == NULL) { + DBGLOG(OID, ERROR, "alloc PartialScanChannel fail\n"); + return FALSE; + } + kalMemSet(PartialScanChannel, 0, sizeof(PARTIAL_SCAN_INFO)); + while (j < channel_counts) { + channel_tmp = scan_req_t->channels[j]; + + DBGLOG(OID, TRACE, "set channel band=%d\n", channel_tmp->band); + if (channel_tmp->band >= IEEE80211_BAND_60GHZ) { + j++; + continue; + } + + if (i >= MAXIMUM_OPERATION_CHANNEL_LIST) + break; + if (channel_tmp->band == IEEE80211_BAND_2GHZ) + PartialScanChannel->arChnlInfoList[i].eBand = BAND_2G4; + else if (channel_tmp->band == IEEE80211_BAND_5GHZ) + PartialScanChannel->arChnlInfoList[i].eBand = BAND_5G; + + DBGLOG(OID, TRACE, "set channel channel_center_freq =%d\n", + channel_tmp->center_freq); + + channel_num = (UINT_8)nicFreq2ChannelNum( + channel_tmp->center_freq * 1000); + + DBGLOG(OID, TRACE, "set channel channel_num=%d\n", + channel_num); + PartialScanChannel->arChnlInfoList[i].ucChannelNum = channel_num; + + j++; + i++; + } + } + DBGLOG(OID, INFO, "Partial Scan: set channel i=%d\n", i); + if (i > 0) { + PartialScanChannel->ucChannelListNum = i; + /*ScanReqMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED;*/ + prAdapter->prGlueInfo->puScanChannel = (PUINT_8)PartialScanChannel; + return TRUE; + } + + kalMemFree(PartialScanChannel, VIR_MEM_TYPE, sizeof(PARTIAL_SCAN_INFO)); + return FALSE; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request the driver to perform +* scanning with attaching information elements(IEs) specified from user space +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBssidListScanExt(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_SCAN_REQUEST_EXT_T prScanRequest; + P_AIS_FSM_INFO_T prAisFsmInfo; + P_PARAM_SSID_T prSsid; + PUINT_8 pucIe; + UINT_32 u4IeLength; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_8 ucScanTime = AIS_SCN_DONE_TIMEOUT_SEC; + BOOLEAN partial_result = FALSE; + + DEBUGFUNC("wlanoidSetBssidListScanExt()"); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, ERROR, "Fail in set BSSID list scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (prAdapter->fgTestMode) { + DBGLOG(OID, WARN, "didn't support Scan in test mode\n"); + return WLAN_STATUS_FAILURE; + } + + ASSERT(pu4SetInfoLen); + *pu4SetInfoLen = 0; + + if (u4SetBufferLen != sizeof(PARAM_SCAN_REQUEST_EXT_T)) { + DBGLOG(OID, ERROR, "u4SetBufferLen != sizeof(PARAM_SCAN_REQUEST_EXT_T)\n"); + return WLAN_STATUS_INVALID_LENGTH; + } + + if (prAdapter->fgIsRadioOff) { + DBGLOG(OID, INFO, "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + DBGLOG(OID, TRACE, "ScanEx\n"); + + /* clear old scan backup results if exists */ + { + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + if (prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) { + kalMemZero(prBssDesc->aucRawBuf, CFG_RAW_BUFFER_SIZE); + prBssDesc->u2RawLength = 0; + } + } + } + + if (pvSetBuffer != NULL && u4SetBufferLen != 0) { + prScanRequest = (P_PARAM_SCAN_REQUEST_EXT_T) pvSetBuffer; + prSsid = &(prScanRequest->rSsid); + pucIe = prScanRequest->pucIE; + u4IeLength = prScanRequest->u4IELength; + } else { + prScanRequest = NULL; + prSsid = NULL; + pucIe = NULL; + u4IeLength = 0; + } + +/* P_AIS_FSM_INFO_T prAisFsmInfo; */ + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + +/* #if CFG_SUPPORT_WFD */ +#if 0 + if ((prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings.ucWfdEnable) && + ((prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings.u4WfdFlag & WFD_FLAGS_DEV_INFO_VALID))) { + + if (prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].eConnectionState == + PARAM_MEDIA_STATE_CONNECTED) { + DBGLOG(OID, TRACE, "Twice the Scan Time for WFD\n"); + ucScanTime *= 2; + } + } +#endif /* CFG_SUPPORT_WFD */ + cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer, SEC_TO_MSEC(ucScanTime)); + +#if CFG_SUPPORT_RDD_TEST_MODE + if (prAdapter->prGlueInfo->rRegInfo.u4RddTestMode) { + if ((prAdapter->fgEnOnlineScan == TRUE) && (prAdapter->ucRddStatus)) { + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) { + partial_result = wlanoidGetChannelInfo(prAdapter, prScanRequest->puPartialScanReq); + if (partial_result == FALSE) + return WLAN_STATUS_FAILURE; + aisFsmScanRequest(prAdapter, prSsid, pucIe, u4IeLength); + } else { + /* reject the scan request */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); + rStatus = WLAN_STATUS_FAILURE; + } + } else { + /* reject the scan request */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); + rStatus = WLAN_STATUS_FAILURE; + } + } else +#endif + { + if (prAdapter->fgEnOnlineScan == TRUE) { + if (prScanRequest == NULL) + return WLAN_STATUS_FAILURE; + partial_result = wlanoidGetChannelInfo(prAdapter, prScanRequest->puPartialScanReq); + if (partial_result == FALSE) + return WLAN_STATUS_FAILURE; + aisFsmScanRequest(prAdapter, prSsid, pucIe, u4IeLength); + } else if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) { + if (prScanRequest == NULL) + return WLAN_STATUS_FAILURE; + partial_result = wlanoidGetChannelInfo(prAdapter, prScanRequest->puPartialScanReq); + if (partial_result == FALSE) + return WLAN_STATUS_FAILURE; + aisFsmScanRequest(prAdapter, prSsid, pucIe, u4IeLength); + } else { + /* reject the scan request */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); + rStatus = WLAN_STATUS_FAILURE; + DBGLOG(OID, WARN, "ScanEx fail %d!\n", prAdapter->fgEnOnlineScan); + } + } + + return rStatus; +} /* wlanoidSetBssidListScanWithIE */ + +#if CFG_MULTI_SSID_SCAN +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request the driver to perform +* scanning with attaching information elements(IEs) specified from user space +* and multiple SSID +* +* \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 wlanoidSetBssidListScanAdv(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_SCAN_REQUEST_ADV_T prScanRequest; + PARAM_SSID_T rSsid[CFG_SCAN_SSID_MAX_NUM]; + PUINT_8 pucIe; + UINT_8 ucSsidNum; + UINT_32 i, u4IeLength; + BOOLEAN partial_result = FALSE; + P_AIS_FSM_INFO_T prAisFsmInfo; + + DEBUGFUNC("wlanoidSetBssidListScanAdv()"); + + 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; + } else if (prAdapter->fgTestMode) { + DBGLOG(OID, WARN, "didn't support Scan in test mode\n"); + return WLAN_STATUS_FAILURE; + } + + ASSERT(pu4SetInfoLen); + *pu4SetInfoLen = 0; + + if (u4SetBufferLen != sizeof(PARAM_SCAN_REQUEST_ADV_T)) + return WLAN_STATUS_INVALID_LENGTH; + else if (pvSetBuffer == NULL) + return WLAN_STATUS_INVALID_DATA; + + 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; + } + + prScanRequest = (P_PARAM_SCAN_REQUEST_ADV_T)pvSetBuffer; + /* P_AIS_FSM_INFO_T prAisFsmInfo; */ + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + ucSsidNum = (UINT_8)(prScanRequest->u4SsidNum); + for (i = 0; i < prScanRequest->u4SsidNum; i++) { + COPY_SSID(rSsid[i].aucSsid, rSsid[i].u4SsidLen, prScanRequest->rSsid[i].aucSsid, + prScanRequest->rSsid[i].u4SsidLen); + } + + pucIe = prScanRequest->pucIE; + u4IeLength = prScanRequest->u4IELength; + +#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) { + partial_result = wlanoidGetChannelInfo(prAdapter, prScanRequest->puPartialScanReq); + if (partial_result == FALSE) + return WLAN_STATUS_FAILURE; + aisFsmScanRequestAdv(prAdapter, ucSsidNum, rSsid, pucIe, u4IeLength, + prScanRequest->aucRandomMac); + } else + return WLAN_STATUS_FAILURE; + } else { + return WLAN_STATUS_FAILURE; + } + } else +#endif + { + if (prAdapter->fgEnOnlineScan == TRUE) { + partial_result = wlanoidGetChannelInfo(prAdapter, prScanRequest->puPartialScanReq); + if (partial_result == FALSE) + return WLAN_STATUS_FAILURE; + aisFsmScanRequestAdv(prAdapter, ucSsidNum, rSsid, pucIe, u4IeLength, + prScanRequest->aucRandomMac); + } else if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) { + partial_result = wlanoidGetChannelInfo(prAdapter, prScanRequest->puPartialScanReq); + if (partial_result == FALSE) + return WLAN_STATUS_FAILURE; + aisFsmScanRequestAdv(prAdapter, ucSsidNum, rSsid, pucIe, u4IeLength, + prScanRequest->aucRandomMac); + } else + return WLAN_STATUS_FAILURE; + } + cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer + , SEC_TO_MSEC(AIS_SCN_DONE_TIMEOUT_SEC)); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetBssidListScanAdv */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine will initiate the join procedure to attempt to associate +* with the specified BSSID. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBssid(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + P_UINT_8 pAddr; + UINT_32 i; + INT_32 i4Idx = -1; + P_MSG_AIS_ABORT_T prAisAbortMsg; + UINT_8 ucReasonOfDisconnect; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = MAC_ADDR_LEN; + if (u4SetBufferLen != MAC_ADDR_LEN) { + *pu4SetInfoLen = MAC_ADDR_LEN; + return WLAN_STATUS_INVALID_LENGTH; + } else if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set ssid! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + prGlueInfo = prAdapter->prGlueInfo; + pAddr = (P_UINT_8) pvSetBuffer; + + /* re-association check */ + if (kalGetMediaStateIndicated(prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, pAddr)) { + kalSetMediaStateIndicated(prGlueInfo, PARAM_MEDIA_STATE_TO_BE_INDICATED); + ucReasonOfDisconnect = DISCONNECT_REASON_CODE_REASSOCIATION; + } else { + DBGLOG(OID, TRACE, "DisByBssid\n"); + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; + } + } else { + ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; + } + + /* check if any scanned result matchs with the BSSID */ + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.arScanResult[i].arMacAddress, pAddr)) { + i4Idx = (INT_32) i; + break; + } + } + + /* prepare message to AIS */ + if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_IBSS + || prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_DEDICATED_IBSS) { + /* IBSS *//* beacon period */ + prAdapter->rWifiVar.rConnSettings.u2BeaconPeriod = prAdapter->rWlanInfo.u2BeaconPeriod; + prAdapter->rWifiVar.rConnSettings.u2AtimWindow = prAdapter->rWlanInfo.u2AtimWindow; + } + + /* Set Connection Request Issued Flag */ + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = TRUE; + prAdapter->rWifiVar.rConnSettings.eConnectionPolicy = CONNECT_BY_BSSID; + + /* Send AIS Abort Message */ + prAisAbortMsg = (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); + if (!prAisAbortMsg) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; + prAisAbortMsg->ucReasonOfDisconnect = ucReasonOfDisconnect; + + /* Update the information to CONNECTION_SETTINGS_T */ + prAdapter->rWifiVar.rConnSettings.ucSSIDLen = 0; + prAdapter->rWifiVar.rConnSettings.aucSSID[0] = '\0'; + + COPY_MAC_ADDR(prAdapter->rWifiVar.rConnSettings.aucBSSID, pAddr); + + if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, pAddr)) + prAisAbortMsg->fgDelayIndication = TRUE; + else + prAisAbortMsg->fgDelayIndication = FALSE; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); + + DBGLOG(OID, INFO, "SetBssid\n"); + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetBssid() */ + +WLAN_STATUS +wlanoidSetConnect(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + P_PARAM_CONNECT_T pParamConn; + P_CONNECTION_SETTINGS_T prConnSettings; + UINT_32 i; + /*INT_32 i4Idx = -1, i4MaxRSSI = INT_MIN;*/ + P_MSG_AIS_ABORT_T prAisAbortMsg; + BOOLEAN fgIsValidSsid = TRUE; + BOOLEAN fgEqualSsid = FALSE; + BOOLEAN fgEqualBssid = FALSE; + const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* MSDN: + * Powering on the radio if the radio is powered off through a setting of OID_802_11_DISASSOCIATE + */ + if (prAdapter->fgIsRadioOff == TRUE) + prAdapter->fgIsRadioOff = FALSE; + + if (u4SetBufferLen != sizeof(PARAM_CONNECT_T)) + return WLAN_STATUS_INVALID_LENGTH; + else if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set ssid! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + prAisAbortMsg = (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); + if (!prAisAbortMsg) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; + + pParamConn = (P_PARAM_CONNECT_T) pvSetBuffer; + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + + if (pParamConn->u4SsidLen > 32) { + cnmMemFree(prAdapter, prAisAbortMsg); + return WLAN_STATUS_INVALID_LENGTH; + } else if (!pParamConn->pucBssid && !pParamConn->pucSsid) { + cnmMemFree(prAdapter, prAisAbortMsg); + return WLAN_STATUS_INVALID_LENGTH; + } + + prGlueInfo = prAdapter->prGlueInfo; + kalMemZero(prConnSettings->aucSSID, sizeof(prConnSettings->aucSSID)); + kalMemZero(prConnSettings->aucBSSID, sizeof(prConnSettings->aucBSSID)); + prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_ANY; + prConnSettings->fgIsConnByBssidIssued = FALSE; + + if (pParamConn->pucSsid) { + prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_BEST_RSSI; + COPY_SSID(prConnSettings->aucSSID, + prConnSettings->ucSSIDLen, pParamConn->pucSsid, (UINT_8) pParamConn->u4SsidLen); + if (EQUAL_SSID(prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, + prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen, + pParamConn->pucSsid, pParamConn->u4SsidLen)) + fgEqualSsid = TRUE; + } + if (pParamConn->pucBssid) { + if (!EQUAL_MAC_ADDR(aucZeroMacAddr, pParamConn->pucBssid) && IS_UCAST_MAC_ADDR(pParamConn->pucBssid)) { + prConnSettings->eConnectionPolicy = CONNECT_BY_BSSID; + prConnSettings->fgIsConnByBssidIssued = TRUE; + COPY_MAC_ADDR(prConnSettings->aucBSSID, pParamConn->pucBssid); + if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, pParamConn->pucBssid)) + fgEqualBssid = TRUE; + } else + DBGLOG(OID, TRACE, "wrong bssid %pM to connect\n", pParamConn->pucBssid); + } else + DBGLOG(OID, TRACE, "No Bssid set\n"); + prConnSettings->u4FreqInKHz = pParamConn->u4CenterFreq; + + /* prepare for CMD_BUILD_CONNECTION & CMD_GET_CONNECTION_STATUS */ + /* re-association check */ + if (kalGetMediaStateIndicated(prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + if (fgEqualSsid) { + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_ROAMING; + if (fgEqualBssid) { + kalSetMediaStateIndicated(prGlueInfo, PARAM_MEDIA_STATE_TO_BE_INDICATED); + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_REASSOCIATION; + } + } else { + DBGLOG(OID, TRACE, "DisBySsid\n"); + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; + } + } else + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; +#if 0 + /* check if any scanned result matchs with the SSID */ + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + PUINT_8 aucSsid = prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid; + UINT_8 ucSsidLength = (UINT_8) prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen; + INT_32 i4RSSI = prAdapter->rWlanInfo.arScanResult[i].rRssi; + + if (EQUAL_SSID(aucSsid, ucSsidLength, pParamConn->pucSsid, pParamConn->u4SsidLen) && + i4RSSI >= i4MaxRSSI) { + i4Idx = (INT_32) i; + i4MaxRSSI = i4RSSI; + } + if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.arScanResult[i].arMacAddress, pAddr)) { + i4Idx = (INT_32) i; + break; + } + } +#endif + /* prepare message to AIS */ + if (prConnSettings->eOPMode == NET_TYPE_IBSS || prConnSettings->eOPMode == NET_TYPE_DEDICATED_IBSS) { + /* IBSS *//* beacon period */ + prConnSettings->u2BeaconPeriod = prAdapter->rWlanInfo.u2BeaconPeriod; + prConnSettings->u2AtimWindow = prAdapter->rWlanInfo.u2AtimWindow; + } + + if (prAdapter->rWifiVar.fgSupportWZCDisassociation) { + if (pParamConn->u4SsidLen == ELEM_MAX_LEN_SSID) { + fgIsValidSsid = FALSE; + + for (i = 0; i < ELEM_MAX_LEN_SSID; i++) { + if (pParamConn->pucSsid) { + if (!((pParamConn->pucSsid[i] > 0) && (pParamConn->pucSsid[i] <= 0x1F))) { + fgIsValidSsid = TRUE; + break; + } + } + } + } + } + + /* Set Connection Request Issued Flag */ + if (fgIsValidSsid) + prConnSettings->fgIsConnReqIssued = TRUE; + else { + prConnSettings->eReConnectLevel = RECONNECT_LEVEL_USER_SET; + prConnSettings->fgIsConnReqIssued = FALSE; + } + + if (fgEqualSsid || fgEqualBssid) + prAisAbortMsg->fgDelayIndication = TRUE; + else + /* Update the information to CONNECTION_SETTINGS_T */ + prAisAbortMsg->fgDelayIndication = FALSE; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); + + cnmTimerStopTimer(prAdapter, &prAdapter->rScanNloTimeoutTimer); + + DBGLOG(OID, INFO, "ssid %s, bssid %pM, conn policy %d, disc reason %d\n", + HIDE(prConnSettings->aucSSID), prConnSettings->aucBSSID, + prConnSettings->eConnectionPolicy, prAisAbortMsg->ucReasonOfDisconnect); + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine will initiate the join procedure to attempt +* to associate with the new SSID. If the previous scanning +* result is aged, we will scan the channels at first. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetSsid(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + P_PARAM_SSID_T pParamSsid; + UINT_32 i; + INT_32 i4Idx = -1, i4MaxRSSI = INT_MIN; + P_MSG_AIS_ABORT_T prAisAbortMsg; + BOOLEAN fgIsValidSsid = TRUE; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* MSDN: + * Powering on the radio if the radio is powered off through a setting of OID_802_11_DISASSOCIATE + */ + if (prAdapter->fgIsRadioOff == TRUE) + prAdapter->fgIsRadioOff = FALSE; + + if (u4SetBufferLen < sizeof(PARAM_SSID_T) || u4SetBufferLen > sizeof(PARAM_SSID_T)) { + return WLAN_STATUS_INVALID_LENGTH; + } else if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set ssid! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + pParamSsid = (P_PARAM_SSID_T) pvSetBuffer; + + if (pParamSsid->u4SsidLen > 32) + return WLAN_STATUS_INVALID_LENGTH; + + prGlueInfo = prAdapter->prGlueInfo; + + /* prepare for CMD_BUILD_CONNECTION & CMD_GET_CONNECTION_STATUS */ + /* re-association check */ + if (kalGetMediaStateIndicated(prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + if (EQUAL_SSID(prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, + prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen, + pParamSsid->aucSsid, pParamSsid->u4SsidLen)) { + kalSetMediaStateIndicated(prGlueInfo, PARAM_MEDIA_STATE_TO_BE_INDICATED); + } else { + DBGLOG(OID, TRACE, "DisBySsid\n"); + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + } + } + /* check if any scanned result matchs with the SSID */ + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + PUINT_8 aucSsid = prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid; + UINT_8 ucSsidLength = (UINT_8) prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen; + INT_32 i4RSSI = prAdapter->rWlanInfo.arScanResult[i].rRssi; + + if (EQUAL_SSID(aucSsid, ucSsidLength, pParamSsid->aucSsid, pParamSsid->u4SsidLen) && + i4RSSI >= i4MaxRSSI) { + i4Idx = (INT_32) i; + i4MaxRSSI = i4RSSI; + } + } + + /* prepare message to AIS */ + if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_IBSS + || prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_DEDICATED_IBSS) { + /* IBSS *//* beacon period */ + prAdapter->rWifiVar.rConnSettings.u2BeaconPeriod = prAdapter->rWlanInfo.u2BeaconPeriod; + prAdapter->rWifiVar.rConnSettings.u2AtimWindow = prAdapter->rWlanInfo.u2AtimWindow; + } + + if (prAdapter->rWifiVar.fgSupportWZCDisassociation) { + if (pParamSsid->u4SsidLen == ELEM_MAX_LEN_SSID) { + fgIsValidSsid = FALSE; + + for (i = 0; i < ELEM_MAX_LEN_SSID; i++) { + if (!((pParamSsid->aucSsid[i] > 0) && (pParamSsid->aucSsid[i] <= 0x1F))) { + fgIsValidSsid = TRUE; + break; + } + } + } + } + + /* Set Connection Request Issued Flag */ + if (fgIsValidSsid) { + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = TRUE; + + if (pParamSsid->u4SsidLen) { + prAdapter->rWifiVar.rConnSettings.eConnectionPolicy = CONNECT_BY_SSID_BEST_RSSI; + } else { + /* wildcard SSID */ + prAdapter->rWifiVar.rConnSettings.eConnectionPolicy = CONNECT_BY_SSID_ANY; + } + } else { + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = FALSE; + } + + /* Send AIS Abort Message */ + prAisAbortMsg = (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); + if (!prAisAbortMsg) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; + + COPY_SSID(prAdapter->rWifiVar.rConnSettings.aucSSID, + prAdapter->rWifiVar.rConnSettings.ucSSIDLen, pParamSsid->aucSsid, (UINT_8) pParamSsid->u4SsidLen); + +#if !defined(CFG_MULTI_SSID_SCAN) + prAdapter->rWifiVar.rConnSettings.u4FreqInKHz = pParamSsid->u4CenterFreq; +#endif + if (EQUAL_SSID(prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, + prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen, pParamSsid->aucSsid, pParamSsid->u4SsidLen)) { + prAisAbortMsg->fgDelayIndication = TRUE; + } else { + /* Update the information to CONNECTION_SETTINGS_T */ + prAisAbortMsg->fgDelayIndication = FALSE; + } + DBGLOG(OID, INFO, "u4ScanResultNum=%d, SSID=%s, ucSSIDLen=%d\n", + prAdapter->rWlanInfo.u4ScanResultNum, + HIDE(prAdapter->rWifiVar.rConnSettings.aucSSID), + prAdapter->rWifiVar.rConnSettings.ucSSIDLen); + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); + + return WLAN_STATUS_SUCCESS; + +} /* end of wlanoidSetSsid() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the currently associated SSID. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQuerySsid(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_SSID_T prAssociatedSsid; + + DEBUGFUNC("wlanoidQuerySsid"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_SSID_T); + + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prAssociatedSsid = (P_PARAM_SSID_T) pvQueryBuffer; + + kalMemZero(prAssociatedSsid->aucSsid, sizeof(prAssociatedSsid->aucSsid)); + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + prAssociatedSsid->u4SsidLen = prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen; + + if (prAssociatedSsid->u4SsidLen) { + kalMemCopy(prAssociatedSsid->aucSsid, + prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, prAssociatedSsid->u4SsidLen); + } + } else { + prAssociatedSsid->u4SsidLen = 0; + + DBGLOG(OID, TRACE, "Null SSID\n"); + } + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQuerySsid */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current 802.11 network type. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryInfrastructureMode(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryInfrastructureMode"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(ENUM_PARAM_OP_MODE_T); + + if (u4QueryBufferLen < sizeof(ENUM_PARAM_OP_MODE_T)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *(P_ENUM_PARAM_OP_MODE_T) pvQueryBuffer = prAdapter->rWifiVar.rConnSettings.eOPMode; + + /* + ** According to OID_802_11_INFRASTRUCTURE_MODE + ** If there is no prior OID_802_11_INFRASTRUCTURE_MODE, + ** NDIS_STATUS_ADAPTER_NOT_READY shall be returned. + */ +#if DBG + switch (*(P_ENUM_PARAM_OP_MODE_T) pvQueryBuffer) { + case NET_TYPE_IBSS: + DBGLOG(OID, INFO, "IBSS mode\n"); + break; + case NET_TYPE_INFRA: + DBGLOG(OID, INFO, "Infrastructure mode\n"); + break; + default: + DBGLOG(OID, INFO, "Automatic mode\n"); + } +#endif + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryInfrastructureMode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set mode to infrastructure or +* IBSS, or automatic switch between the two. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid +* length of the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetInfrastructureMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + ENUM_PARAM_OP_MODE_T eOpMode; + + DEBUGFUNC("wlanoidSetInfrastructureMode"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prGlueInfo = prAdapter->prGlueInfo; + + if (u4SetBufferLen < sizeof(ENUM_PARAM_OP_MODE_T)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + *pu4SetInfoLen = sizeof(ENUM_PARAM_OP_MODE_T); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set infrastructure mode! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + eOpMode = *(P_ENUM_PARAM_OP_MODE_T) pvSetBuffer; + /* Verify the new infrastructure mode. */ + if (eOpMode >= NET_TYPE_NUM) { + DBGLOG(OID, INFO, "Invalid mode value %d\n", eOpMode); + return WLAN_STATUS_INVALID_DATA; + } + + /* check if possible to switch to AdHoc mode */ + if (eOpMode == NET_TYPE_IBSS || eOpMode == NET_TYPE_DEDICATED_IBSS) { + if (cnmAisIbssIsPermitted(prAdapter) == FALSE) { + DBGLOG(OID, INFO, "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_802_11W + prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = FALSE; + prAdapter->rWifiVar.rAisSpecificBssInfo.fgBipKeyInstalled = FALSE; +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_INFRASTRUCTURE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, nicOidCmdTimeoutCommon, + 0, NULL, pvSetBuffer, u4SetBufferLen); + +} /* wlanoidSetInfrastructureMode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current 802.11 authentication +* mode. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryAuthMode(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryAuthMode"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(ENUM_PARAM_AUTH_MODE_T); + + if (u4QueryBufferLen < sizeof(ENUM_PARAM_AUTH_MODE_T)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + *(P_ENUM_PARAM_AUTH_MODE_T) pvQueryBuffer = prAdapter->rWifiVar.rConnSettings.eAuthMode; + +#if DBG + switch (*(P_ENUM_PARAM_AUTH_MODE_T) pvQueryBuffer) { + case AUTH_MODE_OPEN: + DBGLOG(OID, INFO, "Current auth mode: Open\n"); + break; + + case AUTH_MODE_SHARED: + DBGLOG(OID, INFO, "Current auth mode: Shared\n"); + break; + + case AUTH_MODE_AUTO_SWITCH: + DBGLOG(OID, INFO, "Current auth mode: Auto-switch\n"); + break; + + case AUTH_MODE_WPA: + DBGLOG(OID, INFO, "Current auth mode: WPA\n"); + break; + + case AUTH_MODE_WPA_PSK: + DBGLOG(OID, INFO, "Current auth mode: WPA PSK\n"); + break; + + case AUTH_MODE_WPA_NONE: + DBGLOG(OID, INFO, "Current auth mode: WPA None\n"); + break; + + case AUTH_MODE_WPA2: + DBGLOG(OID, INFO, "Current auth mode: WPA2\n"); + break; + + case AUTH_MODE_WPA2_PSK: + DBGLOG(OID, INFO, "Current auth mode: WPA2 PSK\n"); + break; + + default: + DBGLOG(OID, INFO, "Current auth mode: %d\n", *(P_ENUM_PARAM_AUTH_MODE_T) pvQueryBuffer); + break; + } +#endif + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryAuthMode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the IEEE 802.11 authentication mode +* to the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_NOT_ACCEPTED +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAuthMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + + DEBUGFUNC("wlanoidSetAuthMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + prGlueInfo = prAdapter->prGlueInfo; + + *pu4SetInfoLen = sizeof(ENUM_PARAM_AUTH_MODE_T); + + if (u4SetBufferLen < sizeof(ENUM_PARAM_AUTH_MODE_T)) + return WLAN_STATUS_INVALID_LENGTH; + + /* RF Test */ + /* if (IS_ARB_IN_RFTEST_STATE(prAdapter)) { */ + /* return WLAN_STATUS_SUCCESS; */ + /* } */ + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set Authentication mode! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + /* Check if the new authentication mode is valid. */ + if (*(P_ENUM_PARAM_AUTH_MODE_T) pvSetBuffer >= AUTH_MODE_NUM) { + DBGLOG(OID, TRACE, "Invalid auth mode %d\n", *(P_ENUM_PARAM_AUTH_MODE_T) pvSetBuffer); + return WLAN_STATUS_INVALID_DATA; + } + + switch (*(P_ENUM_PARAM_AUTH_MODE_T) pvSetBuffer) { +#if CFG_SUPPORT_HOTSPOT_2_0 + case AUTH_MODE_WPA_OSEN: +#endif + case AUTH_MODE_WPA: + case AUTH_MODE_WPA_PSK: + case AUTH_MODE_WPA2: + case AUTH_MODE_WPA2_PSK: + case AUTH_MODE_WPA2_FT: + case AUTH_MODE_WPA2_FT_PSK: + case AUTH_MODE_WPA3_SAE: + case AUTH_MODE_WPA3_OWE: + /* infrastructure mode only */ + if (prAdapter->rWifiVar.rConnSettings.eOPMode != NET_TYPE_INFRA) + return WLAN_STATUS_NOT_ACCEPTED; + break; + + case AUTH_MODE_WPA_NONE: + /* ad hoc mode only */ + if (prAdapter->rWifiVar.rConnSettings.eOPMode != NET_TYPE_IBSS) + return WLAN_STATUS_NOT_ACCEPTED; + break; + + default: + break; + } + + /* Save the new authentication mode. */ + prAdapter->rWifiVar.rConnSettings.eAuthMode = *(P_ENUM_PARAM_AUTH_MODE_T) pvSetBuffer; + +#if DBG + switch (prAdapter->rWifiVar.rConnSettings.eAuthMode) { + case AUTH_MODE_OPEN: + DBGLOG(RSN, TRACE, "New auth mode: open\n"); + break; + + case AUTH_MODE_SHARED: + DBGLOG(RSN, TRACE, "New auth mode: shared\n"); + break; + + case AUTH_MODE_AUTO_SWITCH: + DBGLOG(RSN, TRACE, "New auth mode: auto-switch\n"); + break; + + case AUTH_MODE_WPA: + DBGLOG(RSN, TRACE, "New auth mode: WPA\n"); + break; + + case AUTH_MODE_WPA_PSK: + DBGLOG(RSN, TRACE, "New auth mode: WPA PSK\n"); + break; + + case AUTH_MODE_WPA_NONE: + DBGLOG(RSN, TRACE, "New auth mode: WPA None\n"); + break; + + case AUTH_MODE_WPA2: + DBGLOG(RSN, TRACE, "New auth mode: WPA2\n"); + break; + + case AUTH_MODE_WPA2_PSK: + DBGLOG(RSN, TRACE, "New auth mode: WPA2 PSK\n"); + break; + + case AUTH_MODE_WPA3_SAE: + DBGLOG(RSN, INFO, "New auth mode: SAE\n"); + break; + + default: + DBGLOG(RSN, TRACE, "New auth mode: unknown (%d)\n", prAdapter->rWifiVar.rConnSettings.eAuthMode); + } +#endif + +#if 0 + 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; +#if CFG_SUPPORT_HOTSPOT_2_0 + case AUTH_MODE_WPA_OSEN: + u4AkmSuite = WFA_AKM_SUITE_OSEN; + break; +#endif + case AUTH_MODE_WPA2_FT: + u4AkmSuite = RSN_AKM_SUITE_FT_802_1X; + break; + + case AUTH_MODE_WPA2_FT_PSK: + u4AkmSuite = RSN_AKM_SUITE_FT_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 + } +#endif + return WLAN_STATUS_SUCCESS; + +} /* wlanoidSetAuthMode */ + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current 802.11 privacy filter +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryPrivacyFilter(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryPrivacyFilter"); + + ASSERT(prAdapter); + + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(ENUM_PARAM_PRIVACY_FILTER_T); + + if (u4QueryBufferLen < sizeof(ENUM_PARAM_PRIVACY_FILTER_T)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + *(P_ENUM_PARAM_PRIVACY_FILTER_T) pvQueryBuffer = prAdapter->rWlanInfo.ePrivacyFilter; + +#if DBG + switch (*(P_ENUM_PARAM_PRIVACY_FILTER_T) pvQueryBuffer) { + case PRIVACY_FILTER_ACCEPT_ALL: + DBGLOG(OID, INFO, "Current privacy mode: open mode\n"); + break; + + case PRIVACY_FILTER_8021xWEP: + DBGLOG(OID, INFO, "Current privacy mode: filtering mode\n"); + break; + + default: + DBGLOG(OID, INFO, "Current auth mode: %d\n", *(P_ENUM_PARAM_AUTH_MODE_T) pvQueryBuffer); + } +#endif + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryPrivacyFilter */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the IEEE 802.11 privacy filter +* to the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_NOT_ACCEPTED +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetPrivacyFilter(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + + DEBUGFUNC("wlanoidSetPrivacyFilter"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + prGlueInfo = prAdapter->prGlueInfo; + + *pu4SetInfoLen = sizeof(ENUM_PARAM_PRIVACY_FILTER_T); + + if (u4SetBufferLen < sizeof(ENUM_PARAM_PRIVACY_FILTER_T)) + return WLAN_STATUS_INVALID_LENGTH; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set Authentication mode! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + /* Check if the new authentication mode is valid. */ + if (*(P_ENUM_PARAM_PRIVACY_FILTER_T) pvSetBuffer >= PRIVACY_FILTER_NUM) { + DBGLOG(OID, TRACE, "Invalid privacy filter %d\n", *(P_ENUM_PARAM_PRIVACY_FILTER_T) pvSetBuffer); + return WLAN_STATUS_INVALID_DATA; + } + + switch (*(P_ENUM_PARAM_PRIVACY_FILTER_T) pvSetBuffer) { + default: + break; + } + + /* Save the new authentication mode. */ + prAdapter->rWlanInfo.ePrivacyFilter = *(ENUM_PARAM_PRIVACY_FILTER_T) pvSetBuffer; + + return WLAN_STATUS_SUCCESS; + +} /* wlanoidSetPrivacyFilter */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to reload the available default settings for +* the specified type field. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetReloadDefaults(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + ENUM_PARAM_NETWORK_TYPE_T eNetworkType; + UINT_32 u4Len; + UINT_8 ucCmdSeqNum; + + DEBUGFUNC("wlanoidSetReloadDefaults"); + + ASSERT(prAdapter); + + ASSERT(pu4SetInfoLen); + *pu4SetInfoLen = sizeof(PARAM_RELOAD_DEFAULTS); + + /* if (IS_ARB_IN_RFTEST_STATE(prAdapter)) { */ + /* return WLAN_STATUS_SUCCESS; */ + /* } */ + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set Reload default! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pvSetBuffer); + /* Verify the available reload options and reload the settings. */ + switch (*(P_PARAM_RELOAD_DEFAULTS) pvSetBuffer) { + case ENUM_RELOAD_WEP_KEYS: + /* + * Reload available default WEP keys from the permanent + * storage. + */ + prAdapter->rWifiVar.rConnSettings.eAuthMode = AUTH_MODE_OPEN; + /* ENUM_ENCRYPTION_DISABLED; */ + prAdapter->rWifiVar.rConnSettings.eEncStatus = ENUM_ENCRYPTION1_KEY_ABSENT; + { + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_CMD_802_11_KEY prCmdKey; + UINT_8 aucBCAddr[] = BC_MAC_ADDR; + + prGlueInfo = prAdapter->prGlueInfo; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_802_11_KEY))); + + if (!prCmdInfo) { + DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_802_11_KEY cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->eNetworkType = NETWORK_TYPE_AIS_INDEX; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_802_11_KEY); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_ADD_REMOVE_KEY; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(PARAM_REMOVE_KEY_T); + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prCmdKey = (P_CMD_802_11_KEY) (prWifiCmd->aucBuffer); + + kalMemZero((PUINT_8) prCmdKey, sizeof(CMD_802_11_KEY)); + + prCmdKey->ucAddRemove = 0; /* Remove */ + prCmdKey->ucKeyId = 0; /* (UINT_8)(prRemovedKey->u4KeyIndex & 0x000000ff); */ + kalMemCopy(prCmdKey->aucPeerAddr, aucBCAddr, MAC_ADDR_LEN); + + ASSERT(prCmdKey->ucKeyId < MAX_KEY_NUM); + + prCmdKey->ucKeyType = 0; + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; + } + + break; + + default: + DBGLOG(OID, TRACE, "Invalid reload option %d\n", *(P_PARAM_RELOAD_DEFAULTS) pvSetBuffer); + rStatus = WLAN_STATUS_INVALID_DATA; + } + + /* OID_802_11_RELOAD_DEFAULTS requiest to reset to auto mode */ + eNetworkType = PARAM_NETWORK_TYPE_AUTOMODE; + wlanoidSetNetworkTypeInUse(prAdapter, &eNetworkType, sizeof(eNetworkType), &u4Len); + + return rStatus; +} /* wlanoidSetReloadDefaults */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a WEP key to the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +#ifdef LINUX +UINT_8 keyBuffer[sizeof(PARAM_KEY_T) + 16 /* LEGACY_KEY_MAX_LEN */]; +UINT_8 aucBCAddr[] = BC_MAC_ADDR; +#endif +WLAN_STATUS +wlanoidSetAddWep(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ +#ifndef LINUX + UINT_8 keyBuffer[sizeof(PARAM_KEY_T) + 16 /* LEGACY_KEY_MAX_LEN */]; + UINT_8 aucBCAddr[] = BC_MAC_ADDR; +#endif + P_PARAM_WEP_T prNewWepKey; + P_PARAM_KEY_T prParamKey = (P_PARAM_KEY_T) keyBuffer; + UINT_32 u4KeyId, u4SetLen; + + DEBUGFUNC("wlanoidSetAddWep"); + + ASSERT(prAdapter); + + *pu4SetInfoLen = OFFSET_OF(PARAM_WEP_T, aucKeyMaterial); + + if (u4SetBufferLen < OFFSET_OF(PARAM_WEP_T, aucKeyMaterial)) { + ASSERT(pu4SetInfoLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set add WEP! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + prNewWepKey = (P_PARAM_WEP_T) pvSetBuffer; + + /* Verify the total buffer for minimum length. */ + if (u4SetBufferLen < OFFSET_OF(PARAM_WEP_T, aucKeyMaterial) + prNewWepKey->u4KeyLength) { + DBGLOG(OID, WARN, "Invalid total buffer length (%d) than minimum length (%d)\n", + (UINT_8) u4SetBufferLen, (UINT_8) OFFSET_OF(PARAM_WEP_T, aucKeyMaterial)); + + *pu4SetInfoLen = OFFSET_OF(PARAM_WEP_T, aucKeyMaterial); + return WLAN_STATUS_INVALID_DATA; + } + + /* Verify the key structure length. */ + if (prNewWepKey->u4Length > u4SetBufferLen) { + DBGLOG(OID, WARN, "Invalid key structure length (%d) greater than total buffer length (%d)\n", + (UINT_8) prNewWepKey->u4Length, (UINT_8) u4SetBufferLen); + + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_INVALID_DATA; + } + + /* Verify the key material length for maximum key material length:16 */ + if (prNewWepKey->u4KeyLength > 16 /* LEGACY_KEY_MAX_LEN */) { + DBGLOG(OID, WARN, "Invalid key material length (%d) greater than maximum key material length (16)\n", + (UINT_8) prNewWepKey->u4KeyLength); + + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_INVALID_DATA; + } + + *pu4SetInfoLen = u4SetBufferLen; + + u4KeyId = prNewWepKey->u4KeyIndex & BITS(0, 29) /* WEP_KEY_ID_FIELD */; + + /* + * Verify whether key index is valid or not, current version + * driver support only 4 global WEP keys setting by this OID + */ + if (u4KeyId > MAX_KEY_NUM - 1) { + DBGLOG(OID, ERROR, "Error, invalid WEP key ID: %d\n", (UINT_8) u4KeyId); + return WLAN_STATUS_INVALID_DATA; + } + + prParamKey->u4KeyIndex = u4KeyId; + + /* Transmit key */ + if (prNewWepKey->u4KeyIndex & IS_TRANSMIT_KEY) + prParamKey->u4KeyIndex |= IS_TRANSMIT_KEY; + + /* Per client key */ + if (prNewWepKey->u4KeyIndex & IS_UNICAST_KEY) + prParamKey->u4KeyIndex |= IS_UNICAST_KEY; + + prParamKey->u4KeyLength = prNewWepKey->u4KeyLength; + + kalMemCopy(prParamKey->arBSSID, aucBCAddr, MAC_ADDR_LEN); + + kalMemCopy(prParamKey->aucKeyMaterial, prNewWepKey->aucKeyMaterial, prNewWepKey->u4KeyLength); + + prParamKey->u4Length = OFFSET_OF(PARAM_KEY_T, aucKeyMaterial) + prNewWepKey->u4KeyLength; + + wlanoidSetAddKey(prAdapter, (PVOID) prParamKey, prParamKey->u4Length, &u4SetLen); + + return WLAN_STATUS_PENDING; +} /* wlanoidSetAddWep */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request the driver to remove the WEP key +* at the specified key index. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetRemoveWep(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + UINT_32 u4KeyId, u4SetLen; + PARAM_REMOVE_KEY_T rRemoveKey; + UINT_8 aucBCAddr[] = BC_MAC_ADDR; + + DEBUGFUNC("wlanoidSetRemoveWep"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_KEY_INDEX); + + if (u4SetBufferLen < sizeof(PARAM_KEY_INDEX)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + u4KeyId = *(PUINT_32) pvSetBuffer; + + /* Dump PARAM_WEP content. */ + DBGLOG(OID, INFO, "Set: Dump PARAM_KEY_INDEX content\n"); + DBGLOG(OID, INFO, "Index : 0x%08x\n", u4KeyId); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set remove WEP! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + if (u4KeyId & IS_TRANSMIT_KEY) { + /* Bit 31 should not be set */ + DBGLOG(OID, ERROR, "Invalid WEP key index: 0x%08x\n", u4KeyId); + return WLAN_STATUS_INVALID_DATA; + } + + u4KeyId &= BITS(0, 7); + + /* + * Verify whether key index is valid or not. Current version + * driver support only 4 global WEP keys. + */ + if (u4KeyId > MAX_KEY_NUM - 1) { + DBGLOG(OID, ERROR, "invalid WEP key ID %u\n", u4KeyId); + return WLAN_STATUS_INVALID_DATA; + } + + rRemoveKey.u4Length = sizeof(PARAM_REMOVE_KEY_T); + rRemoveKey.u4KeyIndex = *(PUINT_32) pvSetBuffer; + + kalMemCopy(rRemoveKey.arBSSID, aucBCAddr, MAC_ADDR_LEN); + + wlanoidSetRemoveKey(prAdapter, (PVOID)&rRemoveKey, sizeof(PARAM_REMOVE_KEY_T), &u4SetLen); + + return WLAN_STATUS_PENDING; +} /* wlanoidSetRemoveWep */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a key to the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer PARAM_KEY_T, which is set by NDIS, is unpacked. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +_wlanoidSetAddKey(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, IN BOOLEAN fgIsOid, IN UINT_8 ucAlgorithmId, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_PARAM_KEY_T prNewKey; + P_CMD_802_11_KEY prCmdKey; + UINT_8 ucCmdSeqNum; + +#if 0 + DEBUGFUNC("wlanoidSetAddKey"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set add key! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } +#endif + + prNewKey = (P_PARAM_KEY_T) pvSetBuffer; + +#if 0 + /* Verify the key structure length. */ + if (prNewKey->u4Length > u4SetBufferLen) { + DBGLOG(OID, WARN, "Invalid key structure length (%d) greater than total buffer length (%d)\n", + (UINT_8) prNewKey->u4Length, (UINT_8) u4SetBufferLen); + + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_INVALID_LENGTH; + } + + /* Verify the key material length for key material buffer */ + if (prNewKey->u4KeyLength > prNewKey->u4Length - OFFSET_OF(PARAM_KEY_T, aucKeyMaterial)) { + DBGLOG(OID, WARN, "Invalid key material length (%d)\n", (UINT_8) prNewKey->u4KeyLength); + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_INVALID_DATA; + } + + /* Exception check */ + if (prNewKey->u4KeyIndex & 0x0fffff00) + return WLAN_STATUS_INVALID_DATA; + + /* Exception check, pairwise key must with transmit bit enabled */ + if ((prNewKey->u4KeyIndex & BITS(30, 31)) == IS_UNICAST_KEY) + return WLAN_STATUS_INVALID_DATA; + + if (!(prNewKey->u4KeyLength == WEP_40_LEN || prNewKey->u4KeyLength == WEP_104_LEN || + prNewKey->u4KeyLength == CCMP_KEY_LEN || prNewKey->u4KeyLength == TKIP_KEY_LEN)) { + return WLAN_STATUS_INVALID_DATA; + } + + /* Exception check, pairwise key must with transmit bit enabled */ + if ((prNewKey->u4KeyIndex & BITS(30, 31)) == BITS(30, 31)) { + if (((prNewKey->u4KeyIndex & 0xff) != 0) || + ((prNewKey->arBSSID[0] == 0xff) && (prNewKey->arBSSID[1] == 0xff) && (prNewKey->arBSSID[2] == 0xff) + && (prNewKey->arBSSID[3] == 0xff) && (prNewKey->arBSSID[4] == 0xff) + && (prNewKey->arBSSID[5] == 0xff))) { + return WLAN_STATUS_INVALID_DATA; + } + } + + *pu4SetInfoLen = u4SetBufferLen; +#endif + + /* Dump PARAM_KEY content. */ + DBGLOG(OID, TRACE, "Set: PARAM_KEY Length: 0x%08x, Key Index: 0x%08x, Key Length: 0x%08x\n", + prNewKey->u4Length, prNewKey->u4KeyIndex, prNewKey->u4KeyLength); + DBGLOG(OID, TRACE, "BSSID:\n"); + DBGLOG_MEM8(OID, TRACE, prNewKey->arBSSID, sizeof(PARAM_MAC_ADDRESS)); + DBGLOG(OID, TRACE, "Key RSC:\n"); + DBGLOG_MEM8(OID, TRACE, &prNewKey->rKeyRSC, sizeof(PARAM_KEY_RSC)); + DBGLOG(OID, TRACE, "Key Material:\n"); + DBGLOG_MEM8(OID, TRACE, prNewKey->aucKeyMaterial, prNewKey->u4KeyLength); + + if (prAdapter->rWifiVar.rConnSettings.eAuthMode < AUTH_MODE_WPA) { + /* Todo:: Store the legacy wep key for OID_802_11_RELOAD_DEFAULTS */ + /* Todo:: Nothing */ + } + + if (prNewKey->u4KeyIndex & IS_TRANSMIT_KEY) + prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist = TRUE; + + prGlueInfo = prAdapter->prGlueInfo; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_802_11_KEY))); + + if (!prCmdInfo) { + DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + DBGLOG(OID, TRACE, "ucCmdSeqNum = %d\n", ucCmdSeqNum); + + /* compose CMD_802_11_KEY cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->eNetworkType = NETWORK_TYPE_AIS_INDEX; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_802_11_KEY); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = fgIsOid; + prCmdInfo->ucCID = CMD_ID_ADD_REMOVE_KEY; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u4SetBufferLen; + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prCmdKey = (P_CMD_802_11_KEY) (prWifiCmd->aucBuffer); + + kalMemZero(prCmdKey, sizeof(CMD_802_11_KEY)); + + prCmdKey->ucAddRemove = 1; /* Add */ + + prCmdKey->ucTxKey = ((prNewKey->u4KeyIndex & IS_TRANSMIT_KEY) == IS_TRANSMIT_KEY) ? 1 : 0; + prCmdKey->ucKeyType = ((prNewKey->u4KeyIndex & IS_UNICAST_KEY) == IS_UNICAST_KEY) ? 1 : 0; + prCmdKey->ucIsAuthenticator = ((prNewKey->u4KeyIndex & IS_AUTHENTICATOR) == IS_AUTHENTICATOR) ? 1 : 0; + + kalMemCopy(prCmdKey->aucPeerAddr, (PUINT_8) prNewKey->arBSSID, MAC_ADDR_LEN); + + prCmdKey->ucNetType = 0; /* AIS */ + + prCmdKey->ucKeyId = (UINT_8) (prNewKey->u4KeyIndex & 0xff); + + /* Note: adjust the key length for WPA-None */ + prCmdKey->ucKeyLen = (UINT_8) prNewKey->u4KeyLength; + + kalMemCopy(prCmdKey->aucKeyMaterial, (PUINT_8) prNewKey->aucKeyMaterial, prCmdKey->ucKeyLen); + + prCmdKey->ucAlgorithmId = ucAlgorithmId; + if (prNewKey->u4KeyLength == 5) { + prCmdKey->ucAlgorithmId = CIPHER_SUITE_WEP40; + } else if (prNewKey->u4KeyLength == 13) { + prCmdKey->ucAlgorithmId = CIPHER_SUITE_WEP104; + } else if (prNewKey->u4KeyLength == 16) { + if ((ucAlgorithmId != CIPHER_SUITE_CCMP) && + /*Notes: WPA3 will use BIP for management pkts and WPA3 reconnect will use OPEN auth mode */ + (ucAlgorithmId != CIPHER_SUITE_BIP) && + (prAdapter->rWifiVar.rConnSettings.eAuthMode < AUTH_MODE_WPA)) + prCmdKey->ucAlgorithmId = CIPHER_SUITE_WEP128; + else { +#if CFG_SUPPORT_802_11W + if (prCmdKey->ucKeyId >= 4) { + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + prCmdKey->ucAlgorithmId = CIPHER_SUITE_BIP; + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + prAisSpecBssInfo->fgBipKeyInstalled = TRUE; + } else +#endif + prCmdKey->ucAlgorithmId = CIPHER_SUITE_CCMP; +#if (CFG_REFACTORY_PMKSA == 0) + 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)); + } +#endif + } + } else if (prNewKey->u4KeyLength == 32) { + if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA_NONE) { + if (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION2_ENABLED) + prCmdKey->ucAlgorithmId = CIPHER_SUITE_TKIP; + else if (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION3_ENABLED) { + prCmdKey->ucAlgorithmId = CIPHER_SUITE_CCMP; + prCmdKey->ucKeyLen = CCMP_KEY_LEN; + } + } else + prCmdKey->ucAlgorithmId = CIPHER_SUITE_TKIP; + } + prAdapter->rWifiVar.rAisSpecificBssInfo.ucKeyAlgorithmId = prCmdKey->ucAlgorithmId; + + DBGLOG(RSN, TRACE, "prCmdKey->ucAlgorithmId=%d, key len=%d\n", + prCmdKey->ucAlgorithmId, (UINT32) prNewKey->u4KeyLength); + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; +} + +WLAN_STATUS +wlanoidSetAddKey(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_KEY_T prNewKey; + + DEBUGFUNC("wlanoidSetAddKey"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set add key! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + prNewKey = (P_PARAM_KEY_T) pvSetBuffer; + + /* Verify the key structure length. */ + if (prNewKey->u4Length > u4SetBufferLen) { + DBGLOG(OID, WARN, "Invalid key structure length (%d) greater than total buffer length (%d)\n", + (UINT_8) prNewKey->u4Length, (UINT_8) u4SetBufferLen); + + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_INVALID_LENGTH; + } + + /* Verify the key material length for key material buffer */ + if (prNewKey->u4KeyLength > prNewKey->u4Length - OFFSET_OF(PARAM_KEY_T, aucKeyMaterial)) { + DBGLOG(OID, WARN, "Invalid key material length (%d)\n", (UINT_8) prNewKey->u4KeyLength); + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_INVALID_DATA; + } + + /* Exception check */ + if (prNewKey->u4KeyIndex & 0x0fffff00) + return WLAN_STATUS_INVALID_DATA; + + /* Exception check, pairwise key must with transmit bit enabled */ + if ((prNewKey->u4KeyIndex & BITS(30, 31)) == BITS(30, 31)) { + if (EQUAL_MAC_ADDR(prNewKey->arBSSID, "\xff\xff\xff\xff\xff\xff")) + return WLAN_STATUS_INVALID_DATA; + if (prNewKey->u4KeyLength == CCMP_KEY_LEN || prNewKey->u4KeyLength == TKIP_KEY_LEN) { + if ((prNewKey->u4KeyIndex & 0xff) != 0) + return WLAN_STATUS_INVALID_DATA; +#if 0 + else { + P_STA_RECORD_T prStaRec = + cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_AIS_INDEX, prNewKey->arBSSID); + if (!prStaRec || prStaRec->ucStaState != STA_STATE_3) { + DBGLOG(OID, WARN, "station record is null[%d] or state is not 3\n", !prStaRec); + return WLAN_STATUS_INVALID_DATA; + } + } +#endif + } + } else if ((prNewKey->u4KeyIndex & BITS(30, 31)) == IS_UNICAST_KEY) + return WLAN_STATUS_INVALID_DATA; + + if (!(prNewKey->u4KeyLength == WEP_40_LEN || prNewKey->u4KeyLength == WEP_104_LEN || + prNewKey->u4KeyLength == CCMP_KEY_LEN || prNewKey->u4KeyLength == TKIP_KEY_LEN)) { + return WLAN_STATUS_INVALID_DATA; + } + + *pu4SetInfoLen = u4SetBufferLen; + +#if (CFG_SUPPORT_TDLS == 1) + /* + * supplicant will set key before updating station & enabling the link so we need to + * backup the key information and set key when link is enabled + */ + if (TdlsexKeyHandle(prAdapter, prNewKey, NETWORK_TYPE_AIS_INDEX) == TDLS_STATUS_SUCCESS) + return WLAN_STATUS_SUCCESS; +#endif /* CFG_SUPPORT_TDLS */ + + return _wlanoidSetAddKey(prAdapter, pvSetBuffer, u4SetBufferLen, TRUE, prNewKey->ucCipher, pu4SetInfoLen); +} /* wlanoidSetAddKey */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request the driver to remove the key at +* the specified key index. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetRemoveKey(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_PARAM_REMOVE_KEY_T prRemovedKey; + P_CMD_802_11_KEY prCmdKey; + UINT_8 ucCmdSeqNum; + + DEBUGFUNC("wlanoidSetRemoveKey"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_REMOVE_KEY_T); + + if (u4SetBufferLen < sizeof(PARAM_REMOVE_KEY_T)) + return WLAN_STATUS_INVALID_LENGTH; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set remove key! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pvSetBuffer); + prRemovedKey = (P_PARAM_REMOVE_KEY_T) pvSetBuffer; + + /* Dump PARAM_REMOVE_KEY content. */ + DBGLOG(OID, TRACE, "Set: Dump PARAM_REMOVE_KEY content\n"); + DBGLOG(OID, TRACE, "Length : 0x%08x\n", prRemovedKey->u4Length); + DBGLOG(OID, TRACE, "Key Index : 0x%08x\n", prRemovedKey->u4KeyIndex); + DBGLOG(OID, TRACE, "BSSID:\n"); + DBGLOG_MEM8(OID, TRACE, prRemovedKey->arBSSID, MAC_ADDR_LEN); + + /* Check bit 31: this bit should always 0 */ + if (prRemovedKey->u4KeyIndex & IS_TRANSMIT_KEY) { + /* Bit 31 should not be set */ + DBGLOG(OID, ERROR, "invalid key index: 0x%08x\n", prRemovedKey->u4KeyIndex); + return WLAN_STATUS_INVALID_DATA; + } + + /* Check bits 8 ~ 29 should always be 0 */ + if (prRemovedKey->u4KeyIndex & BITS(8, 29)) { + /* Bit 31 should not be set */ + DBGLOG(OID, ERROR, "invalid key index: 0x%08x\n", prRemovedKey->u4KeyIndex); + return WLAN_STATUS_INVALID_DATA; + } + + /* Clean up the Tx key flag */ + if (prRemovedKey->u4KeyIndex & IS_UNICAST_KEY) + prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist = FALSE; + + prGlueInfo = prAdapter->prGlueInfo; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_802_11_KEY))); + + if (!prCmdInfo) { + DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_802_11_KEY cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->eNetworkType = NETWORK_TYPE_AIS_INDEX; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_802_11_KEY); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_ADD_REMOVE_KEY; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(PARAM_REMOVE_KEY_T); + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prCmdKey = (P_CMD_802_11_KEY) (prWifiCmd->aucBuffer); + + kalMemZero((PUINT_8) prCmdKey, sizeof(CMD_802_11_KEY)); + + prCmdKey->ucAddRemove = 0; /* Remove */ + prCmdKey->ucKeyId = (UINT_8) (prRemovedKey->u4KeyIndex & 0x000000ff); + kalMemCopy(prCmdKey->aucPeerAddr, (PUINT_8) prRemovedKey->arBSSID, MAC_ADDR_LEN); + +#if CFG_SUPPORT_802_11W + ASSERT(prCmdKey->ucKeyId < MAX_KEY_NUM + 2); +#else + /* ASSERT(prCmdKey->ucKeyId < MAX_KEY_NUM); */ +#endif + + if (prRemovedKey->u4KeyIndex & IS_UNICAST_KEY) + prCmdKey->ucKeyType = 1; + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; +} /* wlanoidSetRemoveKey */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current encryption status. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryEncryptionStatus(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + BOOLEAN fgTransmitKeyAvailable = TRUE; + ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus = 0; + + DEBUGFUNC("wlanoidQueryEncryptionStatus"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(ENUM_PARAM_ENCRYPTION_STATUS_T); + + fgTransmitKeyAvailable = prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist; + + switch (prAdapter->rWifiVar.rConnSettings.eEncStatus) { + case ENUM_ENCRYPTION3_ENABLED: + if (fgTransmitKeyAvailable) + eEncStatus = ENUM_ENCRYPTION3_ENABLED; + else + eEncStatus = ENUM_ENCRYPTION3_KEY_ABSENT; + break; + + case ENUM_ENCRYPTION2_ENABLED: + if (fgTransmitKeyAvailable) { + eEncStatus = ENUM_ENCRYPTION2_ENABLED; + break; + } + eEncStatus = ENUM_ENCRYPTION2_KEY_ABSENT; + break; + + case ENUM_ENCRYPTION1_ENABLED: + if (fgTransmitKeyAvailable) + eEncStatus = ENUM_ENCRYPTION1_ENABLED; + else + eEncStatus = ENUM_ENCRYPTION1_KEY_ABSENT; + break; + + case ENUM_ENCRYPTION_DISABLED: + eEncStatus = ENUM_ENCRYPTION_DISABLED; + break; + + default: + DBGLOG(OID, ERROR, "Unknown Encryption Status Setting:%d\n", + prAdapter->rWifiVar.rConnSettings.eEncStatus); + } + +#if DBG + DBGLOG(OID, INFO, + "Encryption status: %d Return:%d\n", prAdapter->rWifiVar.rConnSettings.eEncStatus, eEncStatus); +#endif + + *(P_ENUM_PARAM_ENCRYPTION_STATUS_T) pvQueryBuffer = eEncStatus; + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryEncryptionStatus */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the encryption status to the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_NOT_SUPPORTED +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetEncryptionStatus(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + ENUM_PARAM_ENCRYPTION_STATUS_T eEewEncrypt; + + DEBUGFUNC("wlanoidSetEncryptionStatus"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prGlueInfo = prAdapter->prGlueInfo; + + *pu4SetInfoLen = sizeof(ENUM_PARAM_ENCRYPTION_STATUS_T); + + /* if (IS_ARB_IN_RFTEST_STATE(prAdapter)) { */ + /* return WLAN_STATUS_SUCCESS; */ + /* } */ + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set encryption status! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + eEewEncrypt = *(P_ENUM_PARAM_ENCRYPTION_STATUS_T) pvSetBuffer; + DBGLOG(OID, TRACE, "ENCRYPTION_STATUS %d\n", eEewEncrypt); + + switch (eEewEncrypt) { + case ENUM_ENCRYPTION_DISABLED: /* Disable WEP, TKIP, AES */ + DBGLOG(RSN, TRACE, "Disable Encryption\n"); + secSetCipherSuite(prAdapter, CIPHER_FLAG_WEP40 | CIPHER_FLAG_WEP104 | CIPHER_FLAG_WEP128); + break; + + case ENUM_ENCRYPTION1_ENABLED: /* Enable WEP. Disable TKIP, AES */ + DBGLOG(RSN, TRACE, "Enable Encryption1\n"); + secSetCipherSuite(prAdapter, CIPHER_FLAG_WEP40 | CIPHER_FLAG_WEP104 | CIPHER_FLAG_WEP128); + break; + + case ENUM_ENCRYPTION2_ENABLED: /* Enable WEP, TKIP. Disable AES */ + secSetCipherSuite(prAdapter, + CIPHER_FLAG_WEP40 | CIPHER_FLAG_WEP104 | CIPHER_FLAG_WEP128 | CIPHER_FLAG_TKIP); + DBGLOG(RSN, TRACE, "Enable Encryption2\n"); + break; + + case ENUM_ENCRYPTION3_ENABLED: /* Enable WEP, TKIP, AES */ + secSetCipherSuite(prAdapter, + CIPHER_FLAG_WEP40 | + CIPHER_FLAG_WEP104 | CIPHER_FLAG_WEP128 | CIPHER_FLAG_TKIP | CIPHER_FLAG_CCMP); + DBGLOG(RSN, TRACE, "Enable Encryption3\n"); + break; + + default: + DBGLOG(RSN, WARN, "Unacceptible encryption status: %d\n", + *(P_ENUM_PARAM_ENCRYPTION_STATUS_T) pvSetBuffer); + + rStatus = WLAN_STATUS_NOT_SUPPORTED; + } + + if (rStatus == WLAN_STATUS_SUCCESS) { + /* Save the new encryption status. */ + prAdapter->rWifiVar.rConnSettings.eEncStatus = *(P_ENUM_PARAM_ENCRYPTION_STATUS_T) pvSetBuffer; + + DBGLOG(RSN, TRACE, "wlanoidSetEncryptionStatus to %d\n", + prAdapter->rWifiVar.rConnSettings.eEncStatus); + } + + return rStatus; +} /* wlanoidSetEncryptionStatus */ +#if (CFG_REFACTORY_PMKSA == 0) +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to test the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetTest(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_802_11_TEST_T prTest; + PVOID pvTestData; + PVOID pvStatusBuffer; + UINT_32 u4StatusBufferSize; + + DEBUGFUNC("wlanoidSetTest"); + + ASSERT(prAdapter); + + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = u4SetBufferLen; + + prTest = (P_PARAM_802_11_TEST_T) pvSetBuffer; + + DBGLOG(OID, TRACE, "Test - Type %u\n", prTest->u4Type); + + switch (prTest->u4Type) { + case 1: /* Type 1: generate an authentication event */ + pvTestData = (PVOID) &prTest->u.AuthenticationEvent; + pvStatusBuffer = (PVOID) prAdapter->aucIndicationEventBuffer; + u4StatusBufferSize = prTest->u4Length - 8; + if (u4StatusBufferSize > sizeof(PARAM_AUTH_EVENT_T)) { + DBGLOG(OID, TRACE, "prTest->u4Length error %u\n", u4StatusBufferSize); + ASSERT(FALSE); + return WLAN_STATUS_INVALID_LENGTH; + } + 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 */ +#endif +/*----------------------------------------------------------------------------*/ +/*! +* \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 */ +#if (CFG_REFACTORY_PMKSA == 0) + prCap->u4NoOfPMKIDs = CFG_MAX_PMKID_CACHE; +#endif + 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 */ +#if (CFG_REFACTORY_PMKSA == 0) +/*----------------------------------------------------------------------------*/ +/*! +* \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 */ +#endif +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ +#if (CFG_REFACTORY_PMKSA == 0) + UINT_32 i, j = 0; + P_PARAM_PMKID_T prPmkid; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + DEBUGFUNC("wlanoidSetPmkid"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = u4SetBufferLen; + + /* It's possibble BSSIDInfoCount is zero, because OS wishes to clean PMKID */ + if (u4SetBufferLen < OFFSET_OF(PARAM_PMKID_T, arBSSIDInfo)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + ASSERT(pvSetBuffer); + prPmkid = (P_PARAM_PMKID_T) pvSetBuffer; + + if (u4SetBufferLen < + ((prPmkid->u4BSSIDInfoCount * sizeof(PARAM_BSSID_INFO_T)) + OFFSET_OF(PARAM_PMKID_T, arBSSIDInfo))) + return WLAN_STATUS_INVALID_DATA; + + if (prPmkid->u4BSSIDInfoCount > CFG_MAX_PMKID_CACHE) + return WLAN_STATUS_INVALID_DATA; + + DBGLOG(OID, TRACE, "Count %u\n", prPmkid->u4BSSIDInfoCount); + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + /* This OID replace everything in the PMKID cache. */ + if (prPmkid->u4BSSIDInfoCount == 0) { + prAisSpecBssInfo->u4PmkidCacheCount = 0; + kalMemZero(prAisSpecBssInfo->arPmkidCache, sizeof(PMKID_ENTRY_T) * CFG_MAX_PMKID_CACHE); + } + if ((prAisSpecBssInfo->u4PmkidCacheCount + prPmkid->u4BSSIDInfoCount > CFG_MAX_PMKID_CACHE)) { + prAisSpecBssInfo->u4PmkidCacheCount = 0; + kalMemZero(prAisSpecBssInfo->arPmkidCache, sizeof(PMKID_ENTRY_T) * CFG_MAX_PMKID_CACHE); + } + + /* + * The driver can only clear its PMKID cache whenever it make a media disconnect + * indication. Otherwise, it must change the PMKID cache only when set through this OID. + */ +#if CFG_RSN_MIGRATION + for (i = 0; i < prPmkid->u4BSSIDInfoCount; i++) { + /* + * Search for desired BSSID. If desired BSSID is found, + * then set the PMKID + */ + if (!rsnSearchPmkidEntry(prAdapter, (PUINT_8) prPmkid->arBSSIDInfo[i].arBSSID, &j)) { + /* No entry found for the specified BSSID, so add one entry */ + if (prAisSpecBssInfo->u4PmkidCacheCount < CFG_MAX_PMKID_CACHE - 1) { + j = prAisSpecBssInfo->u4PmkidCacheCount; + kalMemCopy(prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arBSSID, + prPmkid->arBSSIDInfo[i].arBSSID, sizeof(PARAM_MAC_ADDRESS)); + prAisSpecBssInfo->u4PmkidCacheCount++; + } else { + j = CFG_MAX_PMKID_CACHE; + } + } + + if (j < CFG_MAX_PMKID_CACHE) { + kalMemCopy(prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arPMKID, + prPmkid->arBSSIDInfo[i].arPMKID, sizeof(PARAM_PMKID_VALUE)); + DBGLOG(RSN, TRACE, "Add BSSID %pM idx=%d PMKID value %pM\n", + (prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arBSSID), (UINT_32) j, + (prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arPMKID)); + prAisSpecBssInfo->arPmkidCache[j].fgPmkidExist = TRUE; + } + } +#endif + if (prAdapter->rWifiVar.rConnSettings.fgOkcEnabled && + prPmkid->u4BSSIDInfoCount > 0) { + P_BSS_DESC_T prBssDesc = prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc; + P_UINT_8 pucPmkID = NULL; + + if ((prPmkid->u4Length & BIT(31)) || (prBssDesc && + EQUAL_MAC_ADDR(prPmkid->arBSSIDInfo[0].arBSSID, prBssDesc->aucBSSID))) { + if (j == CFG_MAX_PMKID_CACHE) { + j = 0; + kalMemCopy(prAisSpecBssInfo->arPmkidCache[0].rBssidInfo.arBSSID, + prPmkid->arBSSIDInfo[0].arBSSID, sizeof(PARAM_MAC_ADDRESS)); + kalMemCopy(prAisSpecBssInfo->arPmkidCache[0].rBssidInfo.arPMKID, + prPmkid->arBSSIDInfo[0].arPMKID, sizeof(PARAM_PMKID_VALUE)); + prAisSpecBssInfo->arPmkidCache[0].fgPmkidExist = TRUE; + } + pucPmkID = prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arPMKID; + DBGLOG(RSN, INFO, + "%pM OKC PMKID %02x%02x%02x%02x%02x%02x%02x%02x...\n", + prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arBSSID, + pucPmkID[0], pucPmkID[1], pucPmkID[2], pucPmkID[3], + pucPmkID[4], pucPmkID[5], pucPmkID[6], pucPmkID[7]); + } + aisFsmRunEventSetOkcPmk(prAdapter); + } + + return WLAN_STATUS_SUCCESS; +#else + P_PARAM_PMKID_T prPmkid; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = u4SetBufferLen; + prPmkid = (P_PARAM_PMKID_T) pvSetBuffer; + if (u4SetBufferLen < sizeof(PARAM_PMKID_T)) + return WLAN_STATUS_INVALID_DATA; + return rsnSetPmkid(prAdapter, prPmkid); +#endif +} /* wlanoidSetPmkid */ + +#if (CFG_REFACTORY_PMKSA == 1) +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to delete the PMKID in the PMK cache. + * + * \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 status + */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidDelPmkid(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_PMKID_T prPmkid; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = u4SetBufferLen; + prPmkid = (P_PARAM_PMKID_T) pvSetBuffer; + + if (u4SetBufferLen < sizeof(PARAM_PMKID_T)) + return WLAN_STATUS_INVALID_DATA; + return rsnDelPmkid(prAdapter, prPmkid); +} /* wlanoidDelPmkid */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to delete all the PMKIDs in the PMK cache. + * + * \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 status + */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidFlushPmkid(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + ASSERT(prAdapter); + + return rsnFlushPmkid(prAdapter); +} /* wlanoidFlushPmkid */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the set of supported data rates that +* the radio is capable of running +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query +* \param[in] u4QueryBufferLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number +* of bytes written into the query buffer. If the +* call failed due to invalid length of the query +* buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQuerySupportedRates(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + PARAM_RATES eRate = { + /* BSSBasicRateSet for 802.11n Non-HT rates */ + 0x8C, /* 6M */ + 0x92, /* 9M */ + 0x98, /* 12M */ + 0xA4, /* 18M */ + 0xB0, /* 24M */ + 0xC8, /* 36M */ + 0xE0, /* 48M */ + 0xEC /* 54M */ + }; + + DEBUGFUNC("wlanoidQuerySupportedRates"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_RATES_EX); + + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + kalMemCopy(pvQueryBuffer, (PVOID) &eRate, sizeof(PARAM_RATES)); + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidQuerySupportedRates() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query current desired rates. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryDesiredRates(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryDesiredRates"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_RATES_EX); + + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + kalMemCopy(pvQueryBuffer, (PVOID) &(prAdapter->rWlanInfo.eDesiredRates), sizeof(PARAM_RATES)); + + return WLAN_STATUS_SUCCESS; + +} /* end of wlanoidQueryDesiredRates() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set the desired rates. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetDesiredRates(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + UINT_32 i; + + DEBUGFUNC("wlanoidSetDesiredRates"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(PARAM_RATES)) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = sizeof(PARAM_RATES); + + if (u4SetBufferLen < sizeof(PARAM_RATES)) + return WLAN_STATUS_INVALID_LENGTH; + + kalMemCopy((PVOID) &(prAdapter->rWlanInfo.eDesiredRates), pvSetBuffer, sizeof(PARAM_RATES)); + + prAdapter->rWlanInfo.eLinkAttr.ucDesiredRateLen = PARAM_MAX_LEN_RATES; + for (i = 0; i < PARAM_MAX_LEN_RATES; i++) + prAdapter->rWlanInfo.eLinkAttr.u2DesiredRate[i] = (UINT_16) (prAdapter->rWlanInfo.eDesiredRates[i]); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_LINK_ATTRIB, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_LINK_ATTRIB), + (PUINT_8) &(prAdapter->rWlanInfo.eLinkAttr), pvSetBuffer, u4SetBufferLen); + +} /* end of wlanoidSetDesiredRates() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the maximum frame size in bytes, +* not including the header. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the +* call failed due to invalid length of the query +* buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMaxFrameSize(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryMaxFrameSize"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_INVALID_LENGTH; + } + + *(PUINT_32) pvQueryBuffer = ETHERNET_MAX_PKT_SZ - ETHERNET_HEADER_SZ; + *pu4QueryInfoLen = sizeof(UINT_32); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryMaxFrameSize */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the maximum total packet length +* in bytes. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMaxTotalSize(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryMaxTotalSize"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_INVALID_LENGTH; + } + + *(PUINT_32) pvQueryBuffer = ETHERNET_MAX_PKT_SZ; + *pu4QueryInfoLen = sizeof(UINT_32); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryMaxTotalSize */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the vendor ID of the NIC. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryVendorId(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ +#if DBG + PUINT_8 cp; +#endif + DEBUGFUNC("wlanoidQueryVendorId"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_INVALID_LENGTH; + } + + kalMemCopy(pvQueryBuffer, prAdapter->aucMacAddress, 3); + *((PUINT_8) pvQueryBuffer + 3) = 1; + *pu4QueryInfoLen = sizeof(UINT_32); + +#if DBG + cp = (PUINT_8) pvQueryBuffer; + DBGLOG(OID, LOUD, "Vendor ID=%02x-%02x-%02x-%02x\n", cp[0], cp[1], cp[2], cp[3]); +#endif + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryVendorId */ + +WLAN_STATUS +wlanoidRssiMonitor(IN P_ADAPTER_T prAdapter, OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + PARAM_RSSI_MONITOR_T rRssi; + WLAN_STATUS rStatus1 = WLAN_STATUS_SUCCESS; + WLAN_STATUS rStatus2; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_RSSI_MONITOR_T); + + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(OID, WARN, "Too short length %u\n", u4QueryBufferLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == + PARAM_MEDIA_STATE_DISCONNECTED) + rStatus1 = WLAN_STATUS_ADAPTER_NOT_READY; + + kalMemZero(&rRssi, sizeof(PARAM_RSSI_MONITOR_T)); + kalMemCopy(&rRssi, pvQueryBuffer, sizeof(PARAM_RSSI_MONITOR_T)); + if (rRssi.enable) { + if (rRssi.max_rssi_value > PARAM_WHQL_RSSI_MAX_DBM) + rRssi.max_rssi_value = PARAM_WHQL_RSSI_MAX_DBM; + if (rRssi.min_rssi_value < -120) + rRssi.min_rssi_value = -120; + } else { + rRssi.max_rssi_value = 0; + rRssi.min_rssi_value = 0; + } + + DBGLOG(OID, INFO, "enable=%d, max_rssi_value=%d, min_rssi_value=%d\n", + rRssi.enable, rRssi.max_rssi_value, rRssi.min_rssi_value); + + /* + * If status == WLAN_STATUS_ADAPTER_NOT_READY + * driver needs to info FW to stop mointor but set oid flag to false + * to prevent from multiple complete + */ + rStatus2 = wlanSendSetQueryCmd(prAdapter, + CMD_ID_RSSI_MONITOR, + TRUE, + FALSE, + (rStatus1 != WLAN_STATUS_ADAPTER_NOT_READY), + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(PARAM_RSSI_MONITOR_T), + (PUINT_8)&rRssi, NULL, 0); + + return (rStatus1 == WLAN_STATUS_ADAPTER_NOT_READY) ? + rStatus1 : rStatus2; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current RSSI value. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call failed due to invalid length of +* the query buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRssi(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryRssi"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_RSSI); + + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(OID, WARN, "Too short length %u\n", u4QueryBufferLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_DISCONNECTED) { + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (prAdapter->fgIsLinkQualityValid == TRUE && + (kalGetTimeTick() - prAdapter->rLinkQualityUpdateTime) <= CFG_LINK_QUALITY_VALID_PERIOD) { + PARAM_RSSI rRssi; + + rRssi = (PARAM_RSSI) prAdapter->rLinkQuality.cRssi; /* ranged from (-128 ~ 30) in unit of dBm */ + + if (rRssi > PARAM_WHQL_RSSI_MAX_DBM) + rRssi = PARAM_WHQL_RSSI_MAX_DBM; + else if (rRssi < PARAM_WHQL_RSSI_MIN_DBM) + rRssi = PARAM_WHQL_RSSI_MIN_DBM; + + kalMemCopy(pvQueryBuffer, &rRssi, sizeof(PARAM_RSSI)); + return WLAN_STATUS_SUCCESS; + } +#ifdef LINUX + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryLinkQuality, + nicOidCmdTimeoutCommon, + *pu4QueryInfoLen, pvQueryBuffer, pvQueryBuffer, u4QueryBufferLen); +#else + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryLinkQuality, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + +#endif +} /* end of wlanoidQueryRssi() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current RSSI trigger value. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call failed due to invalid length of +* the query buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRssiTrigger(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryRssiTrigger"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (prAdapter->rWlanInfo.eRssiTriggerType == ENUM_RSSI_TRIGGER_NONE) + return WLAN_STATUS_ADAPTER_NOT_READY; + + *pu4QueryInfoLen = sizeof(PARAM_RSSI); + + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(OID, WARN, "Too short length %u\n", u4QueryBufferLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + *(PARAM_RSSI *) pvQueryBuffer = prAdapter->rWlanInfo.rRssiTriggerValue; + DBGLOG(OID, INFO, "RSSI trigger: %d dBm\n", *(PARAM_RSSI *) pvQueryBuffer); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryRssiTrigger */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a trigger value of the RSSI event. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns the +* amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetRssiTrigger(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PARAM_RSSI rRssiTriggerValue; + + DEBUGFUNC("wlanoidSetRssiTrigger"); + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_RSSI); + rRssiTriggerValue = *(PARAM_RSSI *) pvSetBuffer; + + if (rRssiTriggerValue > PARAM_WHQL_RSSI_MAX_DBM || rRssiTriggerValue < PARAM_WHQL_RSSI_MIN_DBM) + return + /* Save the RSSI trigger value to the Adapter structure */ + prAdapter->rWlanInfo.rRssiTriggerValue = rRssiTriggerValue; + + /* + * If the RSSI trigger value is equal to the current RSSI value, the + * indication triggers immediately. We need to indicate the protocol + * that an RSSI status indication event triggers. + */ + if (rRssiTriggerValue == (PARAM_RSSI) (prAdapter->rLinkQuality.cRssi)) { + prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_TRIGGERED; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID) &prAdapter->rWlanInfo.rRssiTriggerValue, sizeof(PARAM_RSSI)); + } else if (rRssiTriggerValue < (PARAM_RSSI) (prAdapter->rLinkQuality.cRssi)) + prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_GREATER; + else if (rRssiTriggerValue > (PARAM_RSSI) (prAdapter->rLinkQuality.cRssi)) + prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_LESS; + + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetRssiTrigger */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a suggested value for the number of +* bytes of received packet data that will be indicated to the protocol +* driver. We just accept the set and ignore this value. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetCurrentLookahead(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + DEBUGFUNC("wlanoidSetCurrentLookahead"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(UINT_32)) { + *pu4SetInfoLen = sizeof(UINT_32); + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = sizeof(UINT_32); + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetCurrentLookahead */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of frames that the driver +* receives but does not indicate to the protocols due to errors. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRcvError(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryRcvError"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + /* @FIXME, RX_ERROR_DROP_COUNT/RX_FIFO_FULL_DROP_COUNT is not calculated */ + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rFCSErrorCount.QuadPart; + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rFCSErrorCount.QuadPart; + } + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryRecvError, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryRcvError */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the number of frames that the NIC +* cannot receive due to lack of NIC receive buffer space. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS If success; +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRcvNoBuffer(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryRcvNoBuffer"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) 0; /* @FIXME */ + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) 0; /* @FIXME */ + } + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryRecvNoBuffer, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryRcvNoBuffer */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the number of frames that the NIC +* received and it is CRC error. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS If success; +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRcvCrcError(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryRcvCrcError"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rFCSErrorCount.QuadPart; + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rFCSErrorCount.QuadPart; + } + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryRecvCrcError, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryRcvCrcError */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the current 802.11 statistics. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryStatisticsPL(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(PARAM_802_11_STATISTICS_STRUCT_T)) { + DBGLOG(OID, WARN, "Too short length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + P_PARAM_802_11_STATISTICS_STRUCT_T prStatistics; + + *pu4QueryInfoLen = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + prStatistics = (P_PARAM_802_11_STATISTICS_STRUCT_T) pvQueryBuffer; + + prStatistics->u4Length = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + prStatistics->rTransmittedFragmentCount = prAdapter->rStatStruct.rTransmittedFragmentCount; + prStatistics->rMulticastTransmittedFrameCount = prAdapter->rStatStruct.rMulticastTransmittedFrameCount; + prStatistics->rFailedCount = prAdapter->rStatStruct.rFailedCount; + prStatistics->rRetryCount = prAdapter->rStatStruct.rRetryCount; + prStatistics->rMultipleRetryCount = prAdapter->rStatStruct.rMultipleRetryCount; + prStatistics->rRTSSuccessCount = prAdapter->rStatStruct.rRTSSuccessCount; + prStatistics->rRTSFailureCount = prAdapter->rStatStruct.rRTSFailureCount; + prStatistics->rACKFailureCount = prAdapter->rStatStruct.rACKFailureCount; + prStatistics->rFrameDuplicateCount = prAdapter->rStatStruct.rFrameDuplicateCount; + prStatistics->rReceivedFragmentCount = prAdapter->rStatStruct.rReceivedFragmentCount; + prStatistics->rMulticastReceivedFrameCount = prAdapter->rStatStruct.rMulticastReceivedFrameCount; + prStatistics->rFCSErrorCount = prAdapter->rStatStruct.rFCSErrorCount; + prStatistics->rTKIPLocalMICFailures.QuadPart = 0; + prStatistics->rTKIPICVErrors.QuadPart = 0; + prStatistics->rTKIPCounterMeasuresInvoked.QuadPart = 0; + prStatistics->rTKIPReplays.QuadPart = 0; + prStatistics->rCCMPFormatErrors.QuadPart = 0; + prStatistics->rCCMPReplays.QuadPart = 0; + prStatistics->rCCMPDecryptErrors.QuadPart = 0; + prStatistics->rFourWayHandshakeFailures.QuadPart = 0; + prStatistics->rWEPUndecryptableCount.QuadPart = 0; + prStatistics->rWEPICVErrorCount.QuadPart = 0; + prStatistics->rDecryptSuccessCount.QuadPart = 0; + prStatistics->rDecryptFailureCount.QuadPart = 0; + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS_PL, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryStatistics, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryStatistics */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the current 802.11 statistics. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryStatistics(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryStatistics"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(PARAM_802_11_STATISTICS_STRUCT_T)) { + DBGLOG(OID, WARN, "Too short length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + P_PARAM_802_11_STATISTICS_STRUCT_T prStatistics; + + *pu4QueryInfoLen = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + prStatistics = (P_PARAM_802_11_STATISTICS_STRUCT_T) pvQueryBuffer; + + prStatistics->u4Length = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + prStatistics->rTransmittedFragmentCount = prAdapter->rStatStruct.rTransmittedFragmentCount; + prStatistics->rMulticastTransmittedFrameCount = prAdapter->rStatStruct.rMulticastTransmittedFrameCount; + prStatistics->rFailedCount = prAdapter->rStatStruct.rFailedCount; + prStatistics->rRetryCount = prAdapter->rStatStruct.rRetryCount; + prStatistics->rMultipleRetryCount = prAdapter->rStatStruct.rMultipleRetryCount; + prStatistics->rRTSSuccessCount = prAdapter->rStatStruct.rRTSSuccessCount; + prStatistics->rRTSFailureCount = prAdapter->rStatStruct.rRTSFailureCount; + prStatistics->rACKFailureCount = prAdapter->rStatStruct.rACKFailureCount; + prStatistics->rFrameDuplicateCount = prAdapter->rStatStruct.rFrameDuplicateCount; + prStatistics->rReceivedFragmentCount = prAdapter->rStatStruct.rReceivedFragmentCount; + prStatistics->rMulticastReceivedFrameCount = prAdapter->rStatStruct.rMulticastReceivedFrameCount; + prStatistics->rFCSErrorCount = prAdapter->rStatStruct.rFCSErrorCount; + prStatistics->rTKIPLocalMICFailures.QuadPart = 0; + prStatistics->rTKIPICVErrors.QuadPart = 0; + prStatistics->rTKIPCounterMeasuresInvoked.QuadPart = 0; + prStatistics->rTKIPReplays.QuadPart = 0; + prStatistics->rCCMPFormatErrors.QuadPart = 0; + prStatistics->rCCMPReplays.QuadPart = 0; + prStatistics->rCCMPDecryptErrors.QuadPart = 0; + prStatistics->rFourWayHandshakeFailures.QuadPart = 0; + prStatistics->rWEPUndecryptableCount.QuadPart = 0; + prStatistics->rWEPICVErrorCount.QuadPart = 0; + prStatistics->rDecryptSuccessCount.QuadPart = 0; + prStatistics->rDecryptFailureCount.QuadPart = 0; + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryStatistics, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryStatistics */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query current media streaming status. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMediaStreamMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryMediaStreamMode"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(ENUM_MEDIA_STREAM_MODE); + + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + *(P_ENUM_MEDIA_STREAM_MODE) pvQueryBuffer = + prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode == 0 ? ENUM_MEDIA_STREAM_OFF : ENUM_MEDIA_STREAM_ON; + + return WLAN_STATUS_SUCCESS; + +} /* wlanoidQueryMediaStreamMode */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to enter media streaming mode or exit media streaming mode +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetMediaStreamMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + ENUM_MEDIA_STREAM_MODE eStreamMode; + + DEBUGFUNC("wlanoidSetMediaStreamMode"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(ENUM_MEDIA_STREAM_MODE)) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = sizeof(ENUM_MEDIA_STREAM_MODE); + + eStreamMode = *(P_ENUM_MEDIA_STREAM_MODE) pvSetBuffer; + + if (eStreamMode == ENUM_MEDIA_STREAM_OFF) + prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode = 0; + else + prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode = 1; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_LINK_ATTRIB, + TRUE, + FALSE, + TRUE, + nicCmdEventSetMediaStreamMode, + nicOidCmdTimeoutCommon, + sizeof(CMD_LINK_ATTRIB), + (PUINT_8) &(prAdapter->rWlanInfo.eLinkAttr), pvSetBuffer, u4SetBufferLen); +} /* wlanoidSetMediaStreamMode */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the permanent MAC address of the NIC. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryPermanentAddr(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryPermanentAddr"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < MAC_ADDR_LEN) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + COPY_MAC_ADDR(pvQueryBuffer, prAdapter->rWifiVar.aucPermanentAddress); + *pu4QueryInfoLen = MAC_ADDR_LEN; + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryPermanentAddr */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the MAC address the NIC is currently using. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryCurrentAddr(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + CMD_BASIC_CONFIG rCmdBasicConfig; + + DEBUGFUNC("wlanoidQueryCurrentAddr"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < MAC_ADDR_LEN) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + kalMemZero(&rCmdBasicConfig, sizeof(CMD_BASIC_CONFIG)); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_BASIC_CONFIG, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryAddress, + nicOidCmdTimeoutCommon, + sizeof(CMD_BASIC_CONFIG), + (PUINT_8) &rCmdBasicConfig, pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryCurrentAddr */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query NIC link speed. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryLinkSpeed(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryLinkSpeed"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(UINT_32); + + if (u4QueryBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) { + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (prAdapter->fgIsLinkRateValid == TRUE && + (kalGetTimeTick() - prAdapter->rLinkRateUpdateTime) <= CFG_LINK_QUALITY_VALID_PERIOD) { + *(PUINT_32) pvQueryBuffer = prAdapter->rLinkQuality.u2LinkSpeed * 5000; /* change to unit of 100bps */ + return WLAN_STATUS_SUCCESS; + } else { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryLinkSpeed, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + } +} /* end of wlanoidQueryLinkSpeed() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query MCR value. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMcrRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_CUSTOM_MCR_RW_STRUCT_T prMcrRdInfo; + CMD_ACCESS_REG rCmdAccessReg; + + DEBUGFUNC("wlanoidQueryMcrRead"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T); + + if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + prMcrRdInfo = (P_PARAM_CUSTOM_MCR_RW_STRUCT_T) pvQueryBuffer; + + /* 0x9000 - 0x9EFF reserved for FW */ +#if CFG_SUPPORT_SWCR + if ((prMcrRdInfo->u4McrOffset >> 16) == 0x9F00) { + swCrReadWriteCmd(prAdapter, + SWCR_READ, + (UINT_16) (prMcrRdInfo->u4McrOffset & BITS(0, 15)), &prMcrRdInfo->u4McrData); + return WLAN_STATUS_SUCCESS; + } +#endif /* CFG_SUPPORT_SWCR */ + + /* Check if access F/W Domain MCR (due to WiFiSYS is placed from 0x6000-0000 */ + if (prMcrRdInfo->u4McrOffset & 0xFFFF0000) { + /* fill command */ + rCmdAccessReg.u4Address = prMcrRdInfo->u4McrOffset; + rCmdAccessReg.u4Data = 0; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryMcrRead, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8) &rCmdAccessReg, pvQueryBuffer, u4QueryBufferLen); + } else { + HAL_MCR_RD(prAdapter, prMcrRdInfo->u4McrOffset & BITS(2, 31), /* address is in DWORD unit */ + &prMcrRdInfo->u4McrData); + + DBGLOG(OID, TRACE, "MCR Read: Offset = %#08x, Data = %#08x\n", + prMcrRdInfo->u4McrOffset, prMcrRdInfo->u4McrData); + return WLAN_STATUS_SUCCESS; + } +} /* end of wlanoidQueryMcrRead() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to write MCR and enable specific function. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetMcrWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_MCR_RW_STRUCT_T prMcrWrInfo; + CMD_ACCESS_REG rCmdAccessReg; + +#if CFG_STRESS_TEST_SUPPORT + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prBssInfo = &(prAdapter->rWifiVar.arBssInfo[(NETWORK_TYPE_AIS_INDEX)]); + P_STA_RECORD_T prStaRec = prBssInfo->prStaRecOfAP; + UINT_32 u4McrOffset, u4McrData; +#endif + + DEBUGFUNC("wlanoidSetMcrWrite"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prMcrWrInfo = (P_PARAM_CUSTOM_MCR_RW_STRUCT_T) pvSetBuffer; + + /* 0x9000 - 0x9EFF reserved for FW */ + /* 0xFFFE reserved for FW */ + + /* -- Puff Stress Test Begin */ +#if CFG_STRESS_TEST_SUPPORT + + /* 0xFFFFFFFE for Control Rate */ + if (prMcrWrInfo->u4McrOffset == 0xFFFFFFFE) { + if (prMcrWrInfo->u4McrData < FIXED_RATE_NUM && prMcrWrInfo->u4McrData > 0) + prAdapter->rWifiVar.eRateSetting = (ENUM_REGISTRY_FIXED_RATE_T) (prMcrWrInfo->u4McrData); + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + DEBUGFUNC("[Stress Test]Complete Rate is Changed...\n"); + DBGLOG(OID, TRACE, + "[Stress Test] Rate is Changed to index %d...\n", prAdapter->rWifiVar.eRateSetting); + } + /* 0xFFFFFFFD for Switch Channel */ + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFFD) { + if (prMcrWrInfo->u4McrData <= 11 && prMcrWrInfo->u4McrData >= 1) + prBssInfo->ucPrimaryChannel = prMcrWrInfo->u4McrData; + nicUpdateBss(prAdapter, prBssInfo->ucNetTypeIndex); + DBGLOG(OID, TRACE, "[Stress Test] Channel is switched to %d ...\n", prBssInfo->ucPrimaryChannel); + + return WLAN_STATUS_SUCCESS; + } + /* 0xFFFFFFFFC for Control RF Band and SCO */ + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFFC) { + /* Band */ + if (prMcrWrInfo->u4McrData & 0x80000000) { + /* prBssInfo->eBand = BAND_5G; */ + /* prBssInfo->ucPrimaryChannel = 52; // Bond to Channel 52 */ + } else { + prBssInfo->eBand = BAND_2G4; + prBssInfo->ucPrimaryChannel = 8; /* Bond to Channel 6 */ + } + + /* Bandwidth */ + if (prMcrWrInfo->u4McrData & 0x00010000) { + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; + prStaRec->ucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + + if (prMcrWrInfo->u4McrData == 0x00010002) { + prBssInfo->eBssSCO = CHNL_EXT_SCB; /* U20 */ + prBssInfo->ucPrimaryChannel += 2; + } else if (prMcrWrInfo->u4McrData == 0x00010001) { + prBssInfo->eBssSCO = CHNL_EXT_SCA; /* L20 */ + prBssInfo->ucPrimaryChannel -= 2; + } else { + prBssInfo->eBssSCO = CHNL_EXT_SCA; /* 40 */ + } + } + + if (prMcrWrInfo->u4McrData & 0x00000000) { + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SUP_CHNL_WIDTH; + prBssInfo->eBssSCO = CHNL_EXT_SCN; + } + rlmBssInitForAPandIbss(prAdapter, prBssInfo); + } + /* 0xFFFFFFFB for HT Capability */ + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFFB) { + /* Enable HT Capability */ + if (prMcrWrInfo->u4McrData & 0x00000001) { + prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + DEBUGFUNC("[Stress Test]Enable HT capability...\n"); + } else { + prStaRec->u2HtCapInfo &= (~HT_CAP_INFO_HT_GF); + DEBUGFUNC("[Stress Test]Disable HT capability...\n"); + } + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + } + /* 0xFFFFFFFA for Enable Random Rx Reset */ + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFFA) { + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_RANDOM_RX_RESET_EN, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); + } + /* 0xFFFFFFF9 for Disable Random Rx Reset */ + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFF9) { + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_RANDOM_RX_RESET_DE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); + } + /* 0xFFFFFFF8 for Enable SAPP */ + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFF8) { + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SAPP_EN, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); + } + /* 0xFFFFFFF7 for Disable SAPP */ + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFF7) { + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SAPP_DE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); + } + + else +#endif + /* -- Puff Stress Test End */ + + /* Check if access F/W Domain MCR */ + if (prMcrWrInfo->u4McrOffset & 0xFFFF0000) { + + /* 0x9000 - 0x9EFF reserved for FW */ +#if CFG_SUPPORT_SWCR + if ((prMcrWrInfo->u4McrOffset >> 16) == 0x9F00) { + swCrReadWriteCmd(prAdapter, + SWCR_WRITE, + (UINT_16) (prMcrWrInfo->u4McrOffset & BITS(0, 15)), &prMcrWrInfo->u4McrData); + return WLAN_STATUS_SUCCESS; + } +#endif /* CFG_SUPPORT_SWCR */ + +#if 1 + /* low power test special command */ + if (prMcrWrInfo->u4McrOffset == 0x11111110) { + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + /* DbgPrint("Enter test mode\n"); */ + prAdapter->fgTestMode = TRUE; + return rStatus; + } + if (prMcrWrInfo->u4McrOffset == 0x11111111) { + /* DbgPrint("nicpmSetAcpiPowerD3\n"); */ + + nicpmSetAcpiPowerD3(prAdapter); + kalDevSetPowerState(prAdapter->prGlueInfo, (UINT_32) ParamDeviceStateD3); + return WLAN_STATUS_SUCCESS; + } + if (prMcrWrInfo->u4McrOffset == 0x11111112) { + + /* DbgPrint("LP enter sleep\n"); */ + + /* fill command */ + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); + } +#endif + +#if 1 + /* low power test special command */ + if (prMcrWrInfo->u4McrOffset == 0x11111110) { + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + /* DbgPrint("Enter test mode\n"); */ + prAdapter->fgTestMode = TRUE; + return rStatus; + } + if (prMcrWrInfo->u4McrOffset == 0x11111111) { + /* DbgPrint("nicpmSetAcpiPowerD3\n"); */ + + nicpmSetAcpiPowerD3(prAdapter); + kalDevSetPowerState(prAdapter->prGlueInfo, (UINT_32) ParamDeviceStateD3); + return WLAN_STATUS_SUCCESS; + } + if (prMcrWrInfo->u4McrOffset == 0x11111112) { + + /* DbgPrint("LP enter sleep\n"); */ + + /* fill command */ + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); + } +#endif + /* fill command */ + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); + } else { + HAL_MCR_WR(prAdapter, (prMcrWrInfo->u4McrOffset & BITS(2, 31)), /* address is in DWORD unit */ + prMcrWrInfo->u4McrData); + + DBGLOG(OID, TRACE, "MCR Write: Offset = %#08x, Data = %#08x\n", + prMcrWrInfo->u4McrOffset, prMcrWrInfo->u4McrData); + + return WLAN_STATUS_SUCCESS; + } +} /* wlanoidSetMcrWrite */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query SW CTRL +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQuerySwCtrlRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_CUSTOM_SW_CTRL_STRUCT_T prSwCtrlInfo; + WLAN_STATUS rWlanStatus; + UINT_16 u2Id, u2SubId; + UINT_32 u4Data; + + CMD_SW_DBG_CTRL_T rCmdSwCtrl; + + DEBUGFUNC("wlanoidQuerySwCtrlRead"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T); + + if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + prSwCtrlInfo = (P_PARAM_CUSTOM_SW_CTRL_STRUCT_T) pvQueryBuffer; + + u2Id = (UINT_16) (prSwCtrlInfo->u4Id >> 16); + u2SubId = (UINT_16) (prSwCtrlInfo->u4Id & BITS(0, 15)); + u4Data = 0; + rWlanStatus = WLAN_STATUS_SUCCESS; + + switch (u2Id) { + /* 0x9000 - 0x9EFF reserved for FW */ + /* 0xFFFE reserved for FW */ + +#if CFG_SUPPORT_SWCR + case 0x9F00: + swCrReadWriteCmd(prAdapter, SWCR_READ /* Read */, + (UINT_16) u2SubId, &u4Data); + break; +#endif /* CFG_SUPPORT_SWCR */ + + case 0xFFFF: + { + u4Data = 0x5AA56620; + } + break; + + case 0x9000: + default: + { + rCmdSwCtrl.u4Id = prSwCtrlInfo->u4Id; + rCmdSwCtrl.u4Data = 0; + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + FALSE, + TRUE, + TRUE, + nicCmdEventQuerySwCtrlRead, + nicOidCmdTimeoutCommon, + sizeof(CMD_SW_DBG_CTRL_T), + (PUINT_8) &rCmdSwCtrl, pvQueryBuffer, u4QueryBufferLen); + } + } /* switch(u2Id) */ + + prSwCtrlInfo->u4Data = u4Data; + + return rWlanStatus; + +} + + /* end of wlanoidQuerySwCtrlRead() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to write SW CTRL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetSwCtrlWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_SW_CTRL_STRUCT_T prSwCtrlInfo; + CMD_SW_DBG_CTRL_T rCmdSwCtrl; + WLAN_STATUS rWlanStatus; + UINT_16 u2Id, u2SubId; + UINT_32 u4Data; +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION + P_GLUE_INFO_T prGlueInfo; + CMD_HOTSPOT_OPTIMIZATION_CONFIG arHotspotOptimizationCfg; +#endif + + DEBUGFUNC("wlanoidSetSwCtrlWrite"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION + prGlueInfo = prAdapter->prGlueInfo; +#endif + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prSwCtrlInfo = (P_PARAM_CUSTOM_SW_CTRL_STRUCT_T) pvSetBuffer; + + u2Id = (UINT_16) (prSwCtrlInfo->u4Id >> 16); + u2SubId = (UINT_16) (prSwCtrlInfo->u4Id & BITS(0, 15)); + u4Data = prSwCtrlInfo->u4Data; + rWlanStatus = WLAN_STATUS_SUCCESS; + + switch (u2Id) { + + /* 0x9000 - 0x9EFF reserved for FW */ + /* 0xFFFE reserved for FW */ + +#if CFG_SUPPORT_SWCR + case 0x9F00: + swCrReadWriteCmd(prAdapter, SWCR_WRITE, (UINT_16) u2SubId, &u4Data); + break; +#endif /* CFG_SUPPORT_SWCR */ + + case 0x1000: + if (u2SubId == 0x8000) { + /* CTIA power save mode setting (code: 0x10008000) */ + prAdapter->u4CtiaPowerMode = u4Data; + prAdapter->fgEnCtiaPowerMode = TRUE; + + /* */ + { + PARAM_POWER_MODE ePowerMode; + + if (prAdapter->u4CtiaPowerMode == 0) + /* force to keep in CAM mode */ + ePowerMode = Param_PowerModeCAM; + else if (prAdapter->u4CtiaPowerMode == 1) + ePowerMode = Param_PowerModeMAX_PSP; + else + ePowerMode = Param_PowerModeFast_PSP; + + rWlanStatus = nicConfigPowerSaveProfile(prAdapter, + NETWORK_TYPE_AIS_INDEX, ePowerMode, TRUE); + } + } + break; + case 0x1001: + if (u2SubId == 0x0) + prAdapter->fgEnOnlineScan = (BOOLEAN) u4Data; + else if (u2SubId == 0x1) + prAdapter->fgDisBcnLostDetection = (BOOLEAN) u4Data; + else if (u2SubId == 0x2) + prAdapter->rWifiVar.fgSupportUAPSD = (BOOLEAN) u4Data; + else if (u2SubId == 0x3) { + prAdapter->u4UapsdAcBmp = u4Data & BITS(0, 15); + prAdapter->rWifiVar.arBssInfo[u4Data >> 16].rPmProfSetupInfo.ucBmpDeliveryAC = + (UINT_8) prAdapter->u4UapsdAcBmp; + prAdapter->rWifiVar.arBssInfo[u4Data >> 16].rPmProfSetupInfo.ucBmpTriggerAC = + (UINT_8) prAdapter->u4UapsdAcBmp; + } else if (u2SubId == 0x4) + prAdapter->fgDisStaAgingTimeoutDetection = (BOOLEAN) u4Data; + else if (u2SubId == 0x5) + prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode = (UINT_8) u4Data; +#if CFG_RX_BA_REORDERING_ENHANCEMENT + else if (u2SubId == 0x6) + prAdapter->rWifiVar.fgEnableReportIndependentPkt = (BOOLEAN) u4Data; +#endif + else if (u2SubId == 0x0100) + prAdapter->rWifiVar.u8SupportRxGf = (UINT_8) u4Data; + else if (u2SubId == 0x0101) { + prAdapter->rWifiVar.u8SupportRxSgi20 = (UINT_8) u4Data; + prAdapter->rWifiVar.u8SupportRxSgi40 = (UINT_8) u4Data; + } else if (u2SubId == 0x0102) + prAdapter->rWifiVar.u8SupportRxSTBC = (UINT_8) u4Data; + else if (u2SubId == 0x0103) { /* AP Mode WMMPS */ + DBGLOG(OID, INFO, "ApUapsd 0x10010103 cmd received: %d\n", u4Data); + if ((BOOLEAN)u4Data) { + PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T rUapsdParams; + + kalMemZero(&rUapsdParams, sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T)); + prAdapter->rWifiVar.fgSupportUAPSD = TRUE; + rUapsdParams.fgEnAPSD = 1; + rUapsdParams.fgEnAPSD_AcBe = 1; + rUapsdParams.fgEnAPSD_AcBk = 1; + rUapsdParams.fgEnAPSD_AcVi = 1; + rUapsdParams.fgEnAPSD_AcVo = 1; + rUapsdParams.ucMaxSpLen = 0; /* default:0, Do not limit delivery pkt num */ + + nicSetUApsdParam(prAdapter, rUapsdParams, NETWORK_TYPE_P2P_INDEX); + } else { + prAdapter->rWifiVar.fgSupportUAPSD = FALSE; + } + } + 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 + case 0x1003: /* for debug switches */ + switch (u2SubId) { + case 1: + DBGLOG(OID, INFO, "Enable VoE 5.7 Packet Jitter test\n"); + prAdapter->rDebugInfo.fgVoE5_7Test = !!u4Data; + break; + case 0x02: + if (prAdapter->prGlueInfo != NULL) { + DBGLOG(OID, INFO, "usleep 0x1003002 cmd received: %d\n", u4Data); + prAdapter->prGlueInfo->rHifInfo.fgDmaUsleepEnable = (BOOLEAN) u4Data; + } + break; + default: + break; + } + break; +#if CFG_SUPPORT_802_11W + case 0x2000: + DBGLOG(RSN, TRACE, "802.11w test 0x%x\n", u2SubId); + if (u2SubId == 0x0) + rsnStartSaQuery(prAdapter); + if (u2SubId == 0x1) + rsnStopSaQuery(prAdapter); + if (u2SubId == 0x2) + rsnSaQueryRequest(prAdapter, NULL); + if (u2SubId == 0x3) { + P_BSS_INFO_T prBssInfo = &(prAdapter->rWifiVar.arBssInfo[(NETWORK_TYPE_AIS_INDEX)]); + + authSendDeauthFrame(prAdapter, prBssInfo->prStaRecOfAP, NULL, 7, NULL); + } + if (u2SubId == 0x4) { + P_BSS_INFO_T prBssInfo = &(prAdapter->rWifiVar.arBssInfo[(NETWORK_TYPE_AIS_INDEX)]); + + DBGLOG(RSN, INFO, "Send deauth\n"); + authSendDeauthFrame(prAdapter, prBssInfo->prStaRecOfAP, NULL, 1, NULL); + } + /* wext_set_mode */ + /* + * if (u2SubId == 0x3) { + * prAdapter->prGlueInfo->rWpaInfo.u4Mfp = RSN_AUTH_MFP_DISABLED; + * } + * if (u2SubId == 0x4) { + * //prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = TRUE; + * prAdapter->prGlueInfo->rWpaInfo.u4Mfp = RSN_AUTH_MFP_OPTIONAL; + * } + * if (u2SubId == 0x5) { + * //prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = TRUE; + * prAdapter->prGlueInfo->rWpaInfo.u4Mfp = RSN_AUTH_MFP_REQUIRED; + * } + */ + break; +#endif + case 0xFFFF: + { +/* CMD_ACCESS_REG rCmdAccessReg; */ +#if 1 /* CFG_MT6573_SMT_TEST */ + if (u2SubId == 0x0123) { + + DBGLOG(HAL, TRACE, "set smt fixed rate: %u\n", u4Data); + + if ((ENUM_REGISTRY_FIXED_RATE_T) (u4Data) < FIXED_RATE_NUM) + prAdapter->rWifiVar.eRateSetting = (ENUM_REGISTRY_FIXED_RATE_T) (u4Data); + else + prAdapter->rWifiVar.eRateSetting = FIXED_RATE_NONE; + + if (prAdapter->rWifiVar.eRateSetting == FIXED_RATE_NONE) + /* Enable Auto (Long/Short) Preamble */ + prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_AUTO; + else if ((prAdapter->rWifiVar.eRateSetting >= FIXED_RATE_MCS0_20M_400NS && + prAdapter->rWifiVar.eRateSetting <= FIXED_RATE_MCS7_20M_400NS) + || (prAdapter->rWifiVar.eRateSetting >= FIXED_RATE_MCS0_40M_400NS && + prAdapter->rWifiVar.eRateSetting <= FIXED_RATE_MCS32_400NS)) + /* Force Short Preamble */ + prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_SHORT; + else + /* Force Long Preamble */ + prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_LONG; + + /* abort to re-connect */ +#if 1 + DBGLOG(OID, TRACE, "DisBySwC\n"); + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); +#else + aisBssBeaconTimeout(prAdapter); +#endif + + return WLAN_STATUS_SUCCESS; + + } else if (u2SubId == 0x1234) { + /* 1. Disable On-Lin Scan */ + /* 3. Disable FIFO FULL no ack */ + /* 4. Disable Roaming */ + /* Disalbe auto tx power */ + /* 2. Keep at CAM mode */ + /* 5. Disable Beacon Timeout Detection */ + rWlanStatus = nicEnterCtiaMode(prAdapter, TRUE, TRUE); + } else if (u2SubId == 0x1235) { + /* 1. Enaable On-Lin Scan */ + /* 3. Enable FIFO FULL no ack */ + /* 4. Enable Roaming */ + /* Enable auto tx power */ + /* 2. Keep at Fast PS */ + /* 5. Enable Beacon Timeout Detection */ + rWlanStatus = nicEnterCtiaMode(prAdapter, FALSE, TRUE); + } +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION + else if (u2SubId == 0x1240) { + DBGLOG(P2P, TRACE, "Disable Hotspot Optimization!\n"); + + arHotspotOptimizationCfg.fgHotspotOptimizationEn = FALSE; + arHotspotOptimizationCfg.u4Level = 0; + wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_HOTSPOT_OPTIMIZATION, + TRUE, + FALSE, + TRUE, + NULL, + NULL, + sizeof(CMD_HOTSPOT_OPTIMIZATION_CONFIG), + (PUINT_8) &arHotspotOptimizationCfg, NULL, 0); + } else if (u2SubId == 0x1241) { + DBGLOG(P2P, TRACE, "Enable Hotspot Optimization!\n"); + + arHotspotOptimizationCfg.fgHotspotOptimizationEn = TRUE; + arHotspotOptimizationCfg.u4Level = 5; + wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_HOTSPOT_OPTIMIZATION, + TRUE, + FALSE, + TRUE, + NULL, + NULL, + sizeof(CMD_HOTSPOT_OPTIMIZATION_CONFIG), + (PUINT_8) &arHotspotOptimizationCfg, NULL, 0); + } +#endif /* CFG_SUPPORT_HOTSPOT_OPTIMIZATION */ + else if (u2SubId == 0x1250) { + DBGLOG(OID, TRACE, "LTE_COEX: SW SET DUAL BAND\n"); + prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] = BAND_NULL; + } else if (u2SubId == 0x1251) { + DBGLOG(OID, TRACE, "LTE_COEX: SW SET 2.4G BAND\n"); + prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] = BAND_2G4; + } else if (u2SubId == 0x1252) { + DBGLOG(OID, TRACE, "LTE_COEX: SW SET 5G BAND\n"); + prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] = BAND_5G; + } +#endif + } + break; + + case 0x9000: + default: + { + rCmdSwCtrl.u4Id = prSwCtrlInfo->u4Id; + rCmdSwCtrl.u4Data = prSwCtrlInfo->u4Data; + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_SW_DBG_CTRL_T), + (PUINT_8) &rCmdSwCtrl, pvSetBuffer, u4SetBufferLen); + } + } /* switch(u2Id) */ + + return rWlanStatus; +} + + /* wlanoidSetSwCtrlWrite */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query EEPROM value. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryEepromRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T prEepromRwInfo; + CMD_ACCESS_EEPROM rCmdAccessEeprom; + + DEBUGFUNC("wlanoidQueryEepromRead"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T); + + if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + prEepromRwInfo = (P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T) pvQueryBuffer; + + kalMemZero(&rCmdAccessEeprom, sizeof(CMD_ACCESS_EEPROM)); + rCmdAccessEeprom.u2Offset = prEepromRwInfo->ucEepromIndex; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_EEPROM, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryEepromRead, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_EEPROM), + (PUINT_8) &rCmdAccessEeprom, pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryEepromRead */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to write EEPROM value. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetEepromWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T prEepromRwInfo; + CMD_ACCESS_EEPROM rCmdAccessEeprom; + + DEBUGFUNC("wlanoidSetEepromWrite"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prEepromRwInfo = (P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T) pvSetBuffer; + + kalMemZero(&rCmdAccessEeprom, sizeof(CMD_ACCESS_EEPROM)); + rCmdAccessEeprom.u2Offset = prEepromRwInfo->ucEepromIndex; + rCmdAccessEeprom.u2Data = prEepromRwInfo->u2EepromData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_EEPROM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_EEPROM), + (PUINT_8) &rCmdAccessEeprom, pvSetBuffer, u4SetBufferLen); + +} /* wlanoidSetEepromWrite */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of the successfully transmitted +* packets. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryXmitOk(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryXmitOk"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rTransmittedFragmentCount.QuadPart; + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rTransmittedFragmentCount.QuadPart; + } + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryXmitOk, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryXmitOk */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of the successfully received +* packets. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRcvOk(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryRcvOk"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rReceivedFragmentCount.QuadPart; + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rReceivedFragmentCount.QuadPart; + } + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryRecvOk, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryRcvOk */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of frames that the driver +* fails to transmit. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryXmitError(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryXmitError"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rFailedCount.QuadPart; + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rFailedCount.QuadPart; + } + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryXmitError, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryXmitError */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of frames successfully +* transmitted after exactly one collision. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryXmitOneCollision(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryXmitOneCollision"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) + (prAdapter->rStatStruct.rMultipleRetryCount.QuadPart - + prAdapter->rStatStruct.rRetryCount.QuadPart); + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) + (prAdapter->rStatStruct.rMultipleRetryCount.QuadPart - + prAdapter->rStatStruct.rRetryCount.QuadPart); + } + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryXmitOneCollision, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryXmitOneCollision */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of frames successfully +* transmitted after more than one collision. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryXmitMoreCollisions(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryXmitMoreCollisions"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) (prAdapter->rStatStruct.rMultipleRetryCount.QuadPart); + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) (prAdapter->rStatStruct.rMultipleRetryCount.QuadPart); + } + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryXmitMoreCollisions, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); +} /* wlanoidQueryXmitMoreCollisions */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of frames +* not transmitted due to excessive collisions. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryXmitMaxCollisions(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryXmitMaxCollisions"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rFailedCount.QuadPart; + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rFailedCount.QuadPart; + } + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryXmitMaxCollisions, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); +} /* wlanoidQueryXmitMaxCollisions */ + +#define MTK_CUSTOM_OID_INTERFACE_VERSION 0x00006620 /* for WPDWifi DLL */ +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query current the OID interface version, +* which is the interface between the application and driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryOidInterfaceVersion(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryOidInterfaceVersion"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *(PUINT_32) pvQueryBuffer = MTK_CUSTOM_OID_INTERFACE_VERSION; + *pu4QueryInfoLen = sizeof(UINT_32); + + DBGLOG(OID, WARN, "Custom OID interface version: %#08X\n", *(PUINT_32) pvQueryBuffer); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryOidInterfaceVersion */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query current Multicast Address List. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMulticastList(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ +#ifndef LINUX + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_MAC_MCAST_ADDR, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryMcastAddr, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); +#else + return WLAN_STATUS_SUCCESS; +#endif +} /* end of wlanoidQueryMulticastList() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set Multicast Address List. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetMulticastList(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + UINT_8 ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; /* Caller should provide this information */ + CMD_MAC_MCAST_ADDR rCmdMacMcastAddr; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* The data must be a multiple of the Ethernet address size. */ + if ((u4SetBufferLen % MAC_ADDR_LEN)) { + DBGLOG(OID, WARN, "Invalid MC list length %u\n", u4SetBufferLen); + + *pu4SetInfoLen = (((u4SetBufferLen + MAC_ADDR_LEN) - 1) / MAC_ADDR_LEN) * MAC_ADDR_LEN; + + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = u4SetBufferLen; + + /* Verify if we can support so many multicast addresses. */ + if (u4SetBufferLen > MAC_ADDR_LEN * MAX_NUM_GROUP_ADDR) { + DBGLOG(OID, WARN, "Too many MC addresses\n"); + + return WLAN_STATUS_MULTICAST_FULL; + } + + /* NOTE(Kevin): Windows may set u4SetBufferLen == 0 && + * pvSetBuffer == NULL to clear exist Multicast List. + */ + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set multicast list! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + rCmdMacMcastAddr.u4NumOfGroupAddr = u4SetBufferLen / MAC_ADDR_LEN; + rCmdMacMcastAddr.ucNetTypeIndex = ucNetTypeIndex; + kalMemCopy(rCmdMacMcastAddr.arAddress, pvSetBuffer, u4SetBufferLen); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_MAC_MCAST_ADDR, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_MAC_MCAST_ADDR), + (PUINT_8) &rCmdMacMcastAddr, pvSetBuffer, u4SetBufferLen); +} /* end of wlanoidSetMulticastList() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set Packet Filter. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_NOT_SUPPORTED +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetCurrentPacketFilter(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + UINT_32 u4NewPacketFilter; + UINT_32 u4RealPacketFilter; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(UINT_32)) { + *pu4SetInfoLen = sizeof(UINT_32); + DBGLOG(OID, INFO, "iput buffer is too small"); + return WLAN_STATUS_INVALID_LENGTH; + } + ASSERT(pvSetBuffer); + + /* Set the new packet filter. */ + u4NewPacketFilter = *(PUINT_32) pvSetBuffer; + + DBGLOG(OID, TRACE, "New packet filter: %#08x\n", u4NewPacketFilter); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set current packet filter! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + do { + /* + * Verify the bits of the new packet filter. If any bits are set that + * we don't support, leave. + */ + if (u4NewPacketFilter & ~(PARAM_PACKET_FILTER_SUPPORTED)) { + rStatus = WLAN_STATUS_NOT_SUPPORTED; + break; + } +#if DBG + /* + * Need to enable or disable promiscuous support depending on the new + * filter. + */ + if (u4NewPacketFilter & PARAM_PACKET_FILTER_PROMISCUOUS) + DBGLOG(OID, TRACE, "Enable promiscuous mode\n"); + else + DBGLOG(OID, TRACE, "Disable promiscuous mode\n"); + + if (u4NewPacketFilter & PARAM_PACKET_FILTER_ALL_MULTICAST) + DBGLOG(OID, TRACE, "Enable all-multicast mode\n"); + else if (u4NewPacketFilter & PARAM_PACKET_FILTER_MULTICAST) + DBGLOG(OID, TRACE, "Enable multicast\n"); + else + DBGLOG(OID, TRACE, "Disable multicast\n"); + + if (u4NewPacketFilter & PARAM_PACKET_FILTER_BROADCAST) + DBGLOG(OID, TRACE, "Enable Broadcast\n"); + else + DBGLOG(OID, TRACE, "Disable Broadcast\n"); +#endif + } while (FALSE); + + if (rStatus == WLAN_STATUS_SUCCESS) { + /* Store the packet filter */ + + prAdapter->u4OsPacketFilter &= PARAM_PACKET_FILTER_P2P_MASK; + prAdapter->u4OsPacketFilter |= u4NewPacketFilter; + u4RealPacketFilter = prAdapter->u4OsPacketFilter | swCrGetDNSRxFilter(); + + rStatus = wlanoidSetPacketFilter(prAdapter, u4RealPacketFilter, + TRUE, pvSetBuffer, u4SetBufferLen); + } + DBGLOG(REQ, INFO, "[MC debug] u4OsPacketFilter=%x\n", prAdapter->u4OsPacketFilter); + return rStatus; +} /* wlanoidSetCurrentPacketFilter */ + +WLAN_STATUS wlanoidSetPacketFilter(P_ADAPTER_T prAdapter, UINT_32 u4PacketFilter, + BOOLEAN fgIsOid, PVOID pvSetBuffer, UINT_32 u4SetBufferLen) +{ +#if CFG_SUPPORT_DROP_MC_PACKET + /* Note: + * If PARAM_PACKET_FILTER_ALL_MULTICAST is set in PacketFilter, + * Firmware will pass multicast frame. + * Else if PARAM_PACKET_FILTER_MULTICAST is set in PacketFilter, + * Firmware will pass some multicast frame in multicast table. + * Else firmware will drop all multicast frame. + */ + if (fgIsUnderSuspend) + u4PacketFilter &= ~(PARAM_PACKET_FILTER_MULTICAST | PARAM_PACKET_FILTER_ALL_MULTICAST); +#endif + + DBGLOGLIMITED(REQ, INFO, "[MC debug] u4PacketFilter=%x, IsSuspend=%d\n", u4PacketFilter, fgIsUnderSuspend); + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RX_FILTER, + TRUE, + FALSE, + fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(UINT_32), + (PUINT_8)&u4PacketFilter, + pvSetBuffer, u4SetBufferLen); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query current packet filter. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryCurrentPacketFilter(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryCurrentPacketFilter"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(UINT_32); + + if (u4QueryBufferLen >= sizeof(UINT_32)) { + ASSERT(pvQueryBuffer); + *(PUINT_32) pvQueryBuffer = prAdapter->u4OsPacketFilter; + } + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryCurrentPacketFilter */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query ACPI device power state. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryAcpiDevicePowerState(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ +#if DBG + PPARAM_DEVICE_POWER_STATE prPowerState; +#endif + + DEBUGFUNC("wlanoidQueryAcpiDevicePowerState"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_DEVICE_POWER_STATE); + +#if DBG + prPowerState = (PPARAM_DEVICE_POWER_STATE) pvQueryBuffer; + switch (*prPowerState) { + case ParamDeviceStateD0: + DBGLOG(OID, INFO, "Query Power State: D0\n"); + break; + case ParamDeviceStateD1: + DBGLOG(OID, INFO, "Query Power State: D1\n"); + break; + case ParamDeviceStateD2: + DBGLOG(OID, INFO, "Query Power State: D2\n"); + break; + case ParamDeviceStateD3: + DBGLOG(OID, INFO, "Query Power State: D3\n"); + break; + default: + break; + } +#endif + + /* + * Since we will disconnect the newwork, therefore we do not + * need to check queue empty + */ + *(PPARAM_DEVICE_POWER_STATE) pvQueryBuffer = ParamDeviceStateD3; + /* WARNLOG(("Ready to transition to D3\n")); */ + return WLAN_STATUS_SUCCESS; + +} /* pwrmgtQueryPower */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set ACPI device power state. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAcpiDevicePowerState(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PPARAM_DEVICE_POWER_STATE prPowerState; + BOOLEAN fgRetValue = TRUE; + + DEBUGFUNC("wlanoidSetAcpiDevicePowerState"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_DEVICE_POWER_STATE); + + ASSERT(pvSetBuffer); + prPowerState = (PPARAM_DEVICE_POWER_STATE) pvSetBuffer; + switch (*prPowerState) { + case ParamDeviceStateD0: + DBGLOG(OID, INFO, "Set Power State: D0\n"); + kalDevSetPowerState(prAdapter->prGlueInfo, (UINT_32) ParamDeviceStateD0); + fgRetValue = nicpmSetAcpiPowerD0(prAdapter); + break; + case ParamDeviceStateD1: + DBGLOG(OID, INFO, "Set Power State: D1\n"); + /* no break here */ + case ParamDeviceStateD2: + DBGLOG(OID, INFO, "Set Power State: D2\n"); + /* no break here */ + case ParamDeviceStateD3: + DBGLOG(OID, INFO, "Set Power State: D3\n"); + fgRetValue = nicpmSetAcpiPowerD3(prAdapter); + kalDevSetPowerState(prAdapter->prGlueInfo, (UINT_32) ParamDeviceStateD3); + break; + default: + break; + } + + if (fgRetValue == TRUE) + return WLAN_STATUS_SUCCESS; + else + return WLAN_STATUS_FAILURE; +} /* end of wlanoidSetAcpiDevicePowerState() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current fragmentation threshold. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryFragThreshold(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryFragThreshold"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + DBGLOG(OID, LOUD, "\n"); + +#if CFG_TX_FRAGMENT + + return WLAN_STATUS_SUCCESS; + +#else + + return WLAN_STATUS_NOT_SUPPORTED; +#endif /* CFG_TX_FRAGMENT */ +} /* end of wlanoidQueryFragThreshold() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a new fragmentation threshold to the +* driver. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetFragThreshold(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ +#if CFG_TX_FRAGMENT + + return WLAN_STATUS_SUCCESS; + +#else + + return WLAN_STATUS_NOT_SUPPORTED; +#endif /* CFG_TX_FRAGMENT */ + +} /* end of wlanoidSetFragThreshold() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current RTS threshold. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRtsThreshold(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryRtsThreshold"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + DBGLOG(OID, LOUD, "\n"); + + if (u4QueryBufferLen < sizeof(PARAM_RTS_THRESHOLD)) { + *pu4QueryInfoLen = sizeof(PARAM_RTS_THRESHOLD); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + *((PARAM_RTS_THRESHOLD *) pvQueryBuffer) = prAdapter->rWlanInfo.eRtsThreshold; + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryRtsThreshold */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a new RTS threshold to the driver. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetRtsThreshold(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PARAM_RTS_THRESHOLD *prRtsThreshold; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_RTS_THRESHOLD); + if (u4SetBufferLen < sizeof(PARAM_RTS_THRESHOLD)) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prRtsThreshold = (PARAM_RTS_THRESHOLD *) pvSetBuffer; + *prRtsThreshold = prAdapter->rWlanInfo.eRtsThreshold; + + return WLAN_STATUS_SUCCESS; + +} /* wlanoidSetRtsThreshold */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to turn radio off. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetDisassociate(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_MSG_AIS_ABORT_T prAisAbortMsg; + + DEBUGFUNC("wlanoidSetDisassociate"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 0; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set disassociate! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + /* prepare message to AIS */ + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = FALSE; + prAdapter->rWifiVar.rConnSettings.eReConnectLevel = RECONNECT_LEVEL_USER_SET; + + /* Send AIS Abort Message */ + prAisAbortMsg = (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); + if (!prAisAbortMsg) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; + prAisAbortMsg->fgDelayIndication = FALSE; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); + + /* indicate for disconnection */ + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + DBGLOG(OID, INFO, "DisconnectByOid\n"); + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY, NULL, 0); + } +#if !defined(LINUX) + prAdapter->fgIsRadioOff = TRUE; +#endif + + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetDisassociate */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to query the power save profile. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQuery802dot11PowerSaveProfile(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQuery802dot11PowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen != 0) { + ASSERT(pvQueryBuffer); + + /* + * *(PPARAM_POWER_MODE) pvQueryBuffer = + * (PARAM_POWER_MODE)(prAdapter->rWlanInfo.ePowerSaveMode.ucPsProfile); + */ + *(PPARAM_POWER_MODE) pvQueryBuffer = + (PARAM_POWER_MODE) (prAdapter->rWlanInfo.arPowerSaveMode[NETWORK_TYPE_AIS_INDEX].ucPsProfile); + *pu4QueryInfoLen = sizeof(PARAM_POWER_MODE); + + /* hack for CTIA power mode setting function */ + if (prAdapter->fgEnCtiaPowerMode) { + /* set to non-zero value (to prevent MMI query 0, before it intends to set 0, */ + /* which will skip its following state machine) */ + *(PPARAM_POWER_MODE) pvQueryBuffer = (PARAM_POWER_MODE) 2; + } + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to set the power save profile. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSet802dot11PowerSaveProfile(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS status; + PARAM_POWER_MODE ePowerMode; + + DEBUGFUNC("wlanoidSet802dot11PowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_POWER_MODE); + if (u4SetBufferLen < sizeof(PARAM_POWER_MODE)) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } else if (*(PPARAM_POWER_MODE) pvSetBuffer >= Param_PowerModeMax) { + /* WARNLOG(("Invalid power mode %d\n", */ + /* *(PPARAM_POWER_MODE) pvSetBuffer)); */ + return WLAN_STATUS_INVALID_DATA; + } + + ePowerMode = *(PPARAM_POWER_MODE) pvSetBuffer; + + if (prAdapter->fgEnCtiaPowerMode) { + if (ePowerMode == Param_PowerModeCAM) + ; + else { + /* User setting to PS mode (Param_PowerModeMAX_PSP or Param_PowerModeFast_PSP) */ + + if (prAdapter->u4CtiaPowerMode == 0) + /* force to keep in CAM mode */ + ePowerMode = Param_PowerModeCAM; + else if (prAdapter->u4CtiaPowerMode == 1) + ePowerMode = Param_PowerModeMAX_PSP; + else if (prAdapter->u4CtiaPowerMode == 2) + ePowerMode = Param_PowerModeFast_PSP; + } + } + + status = nicConfigPowerSaveProfile(prAdapter, NETWORK_TYPE_AIS_INDEX, ePowerMode, TRUE); + + switch (ePowerMode) { + case Param_PowerModeCAM: + DBGLOG(OID, INFO, "Set Wi-Fi PS mode to CAM (%d)\n", ePowerMode); + break; + case Param_PowerModeMAX_PSP: + DBGLOG(OID, INFO, "Set Wi-Fi PS mode to MAX PS (%d)\n", ePowerMode); + break; + case Param_PowerModeFast_PSP: + DBGLOG(OID, INFO, "Set Wi-Fi PS mode to FAST PS (%d)\n", ePowerMode); + break; + default: + DBGLOG(OID, INFO, "invalid Wi-Fi PS mode setting (%d)\n", ePowerMode); + break; + } + + return status; + +} /* end of wlanoidSetAcpiDevicePowerStateMode() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query current status of AdHoc Mode. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryAdHocMode(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidQueryAdHocMode() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set AdHoc Mode. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAdHocMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetAdHocMode() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query RF frequency. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryFrequency(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryFrequency"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_INFRA) { + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + *(PUINT_32) pvQueryBuffer = + nicChannelNum2Freq(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].ucPrimaryChannel); + } else { + *(PUINT_32) pvQueryBuffer = 0; + } + } else { + *(PUINT_32) pvQueryBuffer = nicChannelNum2Freq(prAdapter->rWifiVar.rConnSettings.ucAdHocChannelNum); + } + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidQueryFrequency() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set RF frequency by User Settings. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetFrequency(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PUINT_32 pu4FreqInKHz; + + DEBUGFUNC("wlanoidSetFrequency"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(UINT_32); + + if (u4SetBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + pu4FreqInKHz = (PUINT_32) pvSetBuffer; + + prAdapter->rWifiVar.rConnSettings.ucAdHocChannelNum = (UINT_8) nicFreq2ChannelNum(*pu4FreqInKHz); + prAdapter->rWifiVar.rConnSettings.eAdHocBand = *pu4FreqInKHz < 5000000 ? BAND_2G4 : BAND_5G; + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetFrequency() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set 802.11 channel of the radio frequency. +* This is a proprietary function call to Lunux currently. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetChannel(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + ASSERT(0); /* // */ + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the Beacon Interval from User Settings. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryBeaconInterval(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryBeaconInterval"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(UINT_32); + + if (u4QueryBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_INFRA) + *(PUINT_32) pvQueryBuffer = prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4BeaconPeriod; + else + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rWlanInfo.u2BeaconPeriod; + } else { + if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_INFRA) + *(PUINT_32) pvQueryBuffer = 0; + else + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rWlanInfo.u2BeaconPeriod; + } + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidQueryBeaconInterval() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the Beacon Interval to User Settings. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBeaconInterval(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PUINT_32 pu4BeaconInterval; + + DEBUGFUNC("wlanoidSetBeaconInterval"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(UINT_32); + if (u4SetBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + pu4BeaconInterval = (PUINT_32) pvSetBuffer; + + if ((*pu4BeaconInterval < DOT11_BEACON_PERIOD_MIN) || (*pu4BeaconInterval > DOT11_BEACON_PERIOD_MAX)) { + DBGLOG(OID, TRACE, "Invalid Beacon Interval = %u\n", *pu4BeaconInterval); + return WLAN_STATUS_INVALID_DATA; + } + + prAdapter->rWlanInfo.u2BeaconPeriod = (UINT_16) *pu4BeaconInterval; + + DBGLOG(OID, INFO, "Set beacon interval: %d\n", prAdapter->rWlanInfo.u2BeaconPeriod); + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetBeaconInterval() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the ATIM window from User Settings. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryAtimWindow(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryAtimWindow"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(UINT_32); + + if (u4QueryBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_INFRA) + *(PUINT_32) pvQueryBuffer = 0; + else + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rWlanInfo.u2AtimWindow; + + return WLAN_STATUS_SUCCESS; + +} /* end of wlanoidQueryAtimWindow() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the ATIM window to User Settings. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAtimWindow(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PUINT_32 pu4AtimWindow; + + DEBUGFUNC("wlanoidSetAtimWindow"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(UINT_32); + + if (u4SetBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + pu4AtimWindow = (PUINT_32) pvSetBuffer; + + prAdapter->rWlanInfo.u2AtimWindow = (UINT_16) *pu4AtimWindow; + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetAtimWindow() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set the MAC address which is currently used by the NIC. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetCurrentAddr(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + ASSERT(0); /* // */ + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetCurrentAddr() */ + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setting the checksum offload function. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetCSUMOffload(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + UINT_32 i, u4CSUMFlags; + CMD_BASIC_CONFIG rCmdBasicConfig; + + DEBUGFUNC("wlanoidSetCSUMOffload"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(UINT_32); + + if (u4SetBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + u4CSUMFlags = *(PUINT_32) pvSetBuffer; + + kalMemZero(&rCmdBasicConfig, sizeof(CMD_BASIC_CONFIG)); + + for (i = 0; i < 6; i++) { /* set to broadcast address for not-specified */ + rCmdBasicConfig.rMyMacAddr[i] = 0xff; + } + + rCmdBasicConfig.ucNative80211 = 0; /* @FIXME: for Vista */ + + if (u4CSUMFlags & CSUM_OFFLOAD_EN_TX_TCP) + rCmdBasicConfig.rCsumOffload.u2TxChecksum |= BIT(2); + + if (u4CSUMFlags & CSUM_OFFLOAD_EN_TX_UDP) + rCmdBasicConfig.rCsumOffload.u2TxChecksum |= BIT(1); + + if (u4CSUMFlags & CSUM_OFFLOAD_EN_TX_IP) + rCmdBasicConfig.rCsumOffload.u2TxChecksum |= BIT(0); + + if (u4CSUMFlags & CSUM_OFFLOAD_EN_RX_TCP) + rCmdBasicConfig.rCsumOffload.u2RxChecksum |= BIT(2); + + if (u4CSUMFlags & CSUM_OFFLOAD_EN_RX_UDP) + rCmdBasicConfig.rCsumOffload.u2RxChecksum |= BIT(1); + + if (u4CSUMFlags & (CSUM_OFFLOAD_EN_RX_IPv4 | CSUM_OFFLOAD_EN_RX_IPv6)) + rCmdBasicConfig.rCsumOffload.u2RxChecksum |= BIT(0); + + prAdapter->u4CSUMFlags = u4CSUMFlags; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_BASIC_CONFIG, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_BASIC_CONFIG), (PUINT_8) &rCmdBasicConfig, pvSetBuffer, u4SetBufferLen); +} +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setting the IP address for pattern search function. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +* \return WLAN_STATUS_ADAPTER_NOT_READY +* \return WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetNetworkAddress(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 i, j; + P_CMD_SET_NETWORK_ADDRESS_LIST prCmdNetworkAddressList; + P_PARAM_NETWORK_ADDRESS_LIST prNetworkAddressList = (P_PARAM_NETWORK_ADDRESS_LIST) pvSetBuffer; + P_PARAM_NETWORK_ADDRESS prNetworkAddress; + P_PARAM_NETWORK_ADDRESS_IP prNetAddrIp; + UINT_32 u4IpAddressCount, u4CmdSize; + PUINT_8 pucBuf = (PUINT_8) pvSetBuffer; +#if CFG_ENABLE_GTK_FRAME_FILTER + UINT_32 u4IpV4AddrListSize; + P_BSS_INFO_T prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; +#endif + + DEBUGFUNC("wlanoidSetNetworkAddress"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 4; + + if (u4SetBufferLen < sizeof(PARAM_NETWORK_ADDRESS_LIST)) + return WLAN_STATUS_INVALID_DATA; + + *pu4SetInfoLen = 0; + u4IpAddressCount = 0; + + prNetworkAddress = prNetworkAddressList->arAddress; + for (i = 0; i < prNetworkAddressList->u4AddressCount; i++) { + if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { + u4IpAddressCount++; + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) (prNetworkAddress + + (ULONG) (prNetworkAddress->u2AddressLength + + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + + /* construct payload of command packet */ + u4CmdSize = OFFSET_OF(CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress) + + sizeof(IPV4_NETWORK_ADDRESS) * u4IpAddressCount; + if (u4IpAddressCount == 0) + u4CmdSize = sizeof(CMD_SET_NETWORK_ADDRESS_LIST); + + prCmdNetworkAddressList = (P_CMD_SET_NETWORK_ADDRESS_LIST) kalMemAlloc(u4CmdSize, VIR_MEM_TYPE); + + if (prCmdNetworkAddressList == NULL) + return WLAN_STATUS_FAILURE; + +#if CFG_ENABLE_GTK_FRAME_FILTER + u4IpV4AddrListSize = OFFSET_OF(IPV4_NETWORK_ADDRESS_LIST, arNetAddr) + + (u4IpAddressCount * sizeof(IPV4_NETWORK_ADDRESS)); + if (prBssInfo->prIpV4NetAddrList) + FREE_IPV4_NETWORK_ADDR_LIST(prBssInfo->prIpV4NetAddrList); + prBssInfo->prIpV4NetAddrList = (P_IPV4_NETWORK_ADDRESS_LIST) kalMemAlloc(u4IpV4AddrListSize, VIR_MEM_TYPE); + if (prBssInfo->prIpV4NetAddrList == NULL) { + kalMemFree(prCmdNetworkAddressList, VIR_MEM_TYPE, u4CmdSize); + return WLAN_STATUS_FAILURE; + } + prBssInfo->prIpV4NetAddrList->ucAddrCount = (UINT_8) u4IpAddressCount; +#endif + + /* fill P_CMD_SET_NETWORK_ADDRESS_LIST */ + prCmdNetworkAddressList->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + + /* only to set IP address to FW once ARP filter is enabled */ + if (prAdapter->fgEnArpFilter) { + prCmdNetworkAddressList->ucAddressCount = (UINT_8) u4IpAddressCount; + prNetworkAddress = prNetworkAddressList->arAddress; + + DBGLOG(OID, INFO, "u4IpAddressCount (%u)\n", u4IpAddressCount); + + for (i = 0, j = 0; i < prNetworkAddressList->u4AddressCount; i++) { + if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { + prNetAddrIp = (P_PARAM_NETWORK_ADDRESS_IP) prNetworkAddress->aucAddress; + + kalMemCopy(prCmdNetworkAddressList->arNetAddress[j].aucIpAddr, + &(prNetAddrIp->in_addr), sizeof(UINT_32)); + +#if CFG_ENABLE_GTK_FRAME_FILTER + kalMemCopy(prBssInfo->prIpV4NetAddrList->arNetAddr[j].aucIpAddr, + &(prNetAddrIp->in_addr), sizeof(UINT_32)); +#endif + + j++; + + pucBuf = (PUINT_8) &prNetAddrIp->in_addr; + DBGLOG(OID, INFO, + "prNetAddrIp->in_addr:%d:%d:%d:%d\n", pucBuf[0], pucBuf[1], pucBuf[2], + pucBuf[3]); + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) (prNetworkAddress + + (ULONG) (prNetworkAddress->u2AddressLength + + OFFSET_OF(PARAM_NETWORK_ADDRESS, + aucAddress))); + } + + } else { + prCmdNetworkAddressList->ucAddressCount = 0; + } + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_IP_ADDRESS, + TRUE, + FALSE, + TRUE, + nicCmdEventSetIpAddress, + nicOidCmdTimeoutCommon, + u4CmdSize, (PUINT_8) prCmdNetworkAddressList, pvSetBuffer, u4SetBufferLen); + + kalMemFree(prCmdNetworkAddressList, VIR_MEM_TYPE, u4CmdSize); + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set driver to switch into RF test mode +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set, +* should be NULL +* \param[in] u4SetBufferLen The length of the set buffer, should be 0 +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +* \return WLAN_STATUS_ADAPTER_NOT_READY +* \return WLAN_STATUS_INVALID_DATA +* \return WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidRftestSetTestMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus; + CMD_TEST_CTRL_T rCmdTestCtrl; + + DEBUGFUNC("wlanoidRftestSetTestMode"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 0; + + if (u4SetBufferLen == 0) { + if (prAdapter->fgTestMode == FALSE) { + /* switch to RF Test mode */ + rCmdTestCtrl.ucAction = 0; /* Switch mode */ + rCmdTestCtrl.u.u4OpMode = 1; /* RF test mode */ + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_TEST_MODE, + TRUE, + TRUE, + TRUE, + nicCmdEventEnterRfTest, + nicOidCmdEnterRFTestTimeout, + sizeof(CMD_TEST_CTRL_T), + (PUINT_8) &rCmdTestCtrl, pvSetBuffer, u4SetBufferLen); + } else { + /* already in test mode .. */ + rStatus = WLAN_STATUS_SUCCESS; + } + } else { + rStatus = WLAN_STATUS_INVALID_DATA; + } + DBGLOG(OID, INFO, "Enter TestMode, setBufLen %u, InTestMode %d, rStatus %u\n", + u4SetBufferLen, prAdapter->fgTestMode, rStatus); + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set driver to switch into normal operation mode from RF test mode +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* should be NULL +* \param[in] u4SetBufferLen The length of the set buffer, should be 0 +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +* \return WLAN_STATUS_ADAPTER_NOT_READY +* \return WLAN_STATUS_INVALID_DATA +* \return WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidRftestSetAbortTestMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus; + CMD_TEST_CTRL_T rCmdTestCtrl; + + DEBUGFUNC("wlanoidRftestSetTestMode"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 0; + + if (u4SetBufferLen == 0) { + if (prAdapter->fgTestMode == TRUE) { + /* switch to normal mode */ + rCmdTestCtrl.ucAction = 0; /* Switch mode */ + rCmdTestCtrl.u.u4OpMode = 0; /* normal mode */ + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_TEST_MODE, + TRUE, + FALSE, + TRUE, + nicCmdEventLeaveRfTest, + nicOidCmdTimeoutCommon, + sizeof(CMD_TEST_CTRL_T), + (PUINT_8) &rCmdTestCtrl, pvSetBuffer, u4SetBufferLen); + } else { + /* already in normal mode .. */ + rStatus = WLAN_STATUS_SUCCESS; + } + } else { + rStatus = WLAN_STATUS_INVALID_DATA; + } + DBGLOG(OID, INFO, "Abort TestMode, setBufLen %u, InTestMode %d, rStatus %u\n", + u4SetBufferLen, prAdapter->fgTestMode, rStatus); + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief query for RF test parameter +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +* \retval WLAN_STATUS_NOT_SUPPORTED +* \retval WLAN_STATUS_NOT_ACCEPTED +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidRftestQueryAutoTest(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_MTK_WIFI_TEST_STRUCT_T prRfATInfo; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidRftestQueryAutoTest"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + /*pu4QueryInfoLen is depended on upper-layer*/ + *pu4QueryInfoLen = u4QueryBufferLen; + + if (u4QueryBufferLen != sizeof(PARAM_MTK_WIFI_TEST_STRUCT_T)) + DBGLOG(OID, WARN, "Invalid data. QueryBufferLen: %u.\n", u4QueryBufferLen); + + prRfATInfo = (P_PARAM_MTK_WIFI_TEST_STRUCT_T) pvQueryBuffer; + rStatus = rftestQueryATInfo(prAdapter, + prRfATInfo->u4FuncIndex, prRfATInfo->u4FuncData, pvQueryBuffer, u4QueryBufferLen); + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set RF test parameter +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +* \return WLAN_STATUS_ADAPTER_NOT_READY +* \return WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidRftestSetAutoTest(IN P_ADAPTER_T prAdapter, + OUT PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_MTK_WIFI_TEST_STRUCT_T prRfATInfo; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidRftestSetAutoTest"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_MTK_WIFI_TEST_STRUCT_T); + + if (u4SetBufferLen != sizeof(PARAM_MTK_WIFI_TEST_STRUCT_T)) + DBGLOG(OID, WARN, "Invalid data. SetBufferLen: %u.\n", u4SetBufferLen); + + + prRfATInfo = (P_PARAM_MTK_WIFI_TEST_STRUCT_T) pvSetBuffer; + rStatus = rftestSetATInfo(prAdapter, prRfATInfo->u4FuncIndex, prRfATInfo->u4FuncData); + + return rStatus; +} + +/* RF test OID set handler */ +WLAN_STATUS rftestSetATInfo(IN P_ADAPTER_T prAdapter, UINT_32 u4FuncIndex, UINT_32 u4FuncData) +{ + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_CMD_TEST_CTRL_T pCmdTestCtrl; + UINT_8 ucCmdSeqNum; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_TEST_CTRL_T))); + + if (!prCmdInfo) { + DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_TEST_CTRL_T); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_TEST_MODE; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(CMD_TEST_CTRL_T); + prCmdInfo->pvInformationBuffer = NULL; + prCmdInfo->u4InformationBufferLength = 0; + + /* Setup WIFI_CMD_T (payload = CMD_TEST_CTRL_T) */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + pCmdTestCtrl = (P_CMD_TEST_CTRL_T) (prWifiCmd->aucBuffer); + pCmdTestCtrl->ucAction = 1; /* Set ATInfo */ + pCmdTestCtrl->u.rRfATInfo.u4FuncIndex = u4FuncIndex; + pCmdTestCtrl->u.rRfATInfo.u4FuncData = u4FuncData; + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prAdapter->prGlueInfo); + + return WLAN_STATUS_PENDING; +} + +WLAN_STATUS +rftestQueryATInfo(IN P_ADAPTER_T prAdapter, + UINT_32 u4FuncIndex, UINT_32 u4FuncData, OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen) +{ + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_CMD_TEST_CTRL_T pCmdTestCtrl; + UINT_8 ucCmdSeqNum; + P_EVENT_TEST_STATUS prTestStatus; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + + if (u4FuncIndex == RF_AT_FUNCID_FW_INFO) { + /* driver implementation */ + prTestStatus = (P_EVENT_TEST_STATUS) pvQueryBuffer; + + prTestStatus->rATInfo.u4FuncData = + (prAdapter->rVerInfo.u2FwProductID << 16) | (prAdapter->rVerInfo.u2FwOwnVersion); + if (u4QueryBufferLen > 8) { + /*support FW version extended*/ + prTestStatus->rATInfo.u4FuncData2 = prAdapter->rVerInfo.u2FwOwnVersionExtend; + + DBGLOG(OID, INFO, " version: 0x%x ,extended : 0x%x\n" + , prTestStatus->rATInfo.u4FuncData + , prTestStatus->rATInfo.u4FuncData2); + } else + DBGLOG(OID, INFO, " version: 0x%x\n" + , prTestStatus->rATInfo.u4FuncData); + + 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; + + return WLAN_STATUS_SUCCESS; + } + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_TEST_CTRL_T))); + + if (!prCmdInfo) { + DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_TEST_CTRL_T); + prCmdInfo->pfCmdDoneHandler = nicCmdEventQueryRfTestATInfo; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_TEST_MODE; + prCmdInfo->fgSetQuery = FALSE; + prCmdInfo->fgNeedResp = TRUE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(CMD_TEST_CTRL_T); + prCmdInfo->pvInformationBuffer = pvQueryBuffer; + prCmdInfo->u4InformationBufferLength = u4QueryBufferLen; + + /* Setup WIFI_CMD_T (payload = CMD_TEST_CTRL_T) */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + pCmdTestCtrl = (P_CMD_TEST_CTRL_T) (prWifiCmd->aucBuffer); + pCmdTestCtrl->ucAction = 2; /* Get ATInfo */ + pCmdTestCtrl->u.rRfATInfo.u4FuncIndex = u4FuncIndex; + pCmdTestCtrl->u.rRfATInfo.u4FuncData = u4FuncData; + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prAdapter->prGlueInfo); + + return WLAN_STATUS_PENDING; +} + +WLAN_STATUS rftestSetFrequency(IN P_ADAPTER_T prAdapter, IN UINT_32 u4FreqInKHz, IN PUINT_32 pu4SetInfoLen) +{ + CMD_TEST_CTRL_T rCmdTestCtrl; + + ASSERT(prAdapter); + + rCmdTestCtrl.ucAction = 5; /* Set Channel Frequency */ + rCmdTestCtrl.u.u4ChannelFreq = u4FreqInKHz; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_TEST_MODE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, sizeof(CMD_TEST_CTRL_T), (PUINT_8) &rCmdTestCtrl, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief command packet generation utility +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] ucCID Command ID +* \param[in] fgSetQuery Set or Query +* \param[in] fgNeedResp Need for response +* \param[in] pfCmdDoneHandler Function pointer when command is done +* \param[in] u4SetQueryInfoLen The length of the set/query buffer +* \param[in] pucInfoBuffer Pointer to set/query buffer +* +* +* \retval WLAN_STATUS_PENDING +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanSendSetQueryCmd(IN P_ADAPTER_T prAdapter, + UINT_8 ucCID, + BOOLEAN fgSetQuery, + BOOLEAN fgNeedResp, + BOOLEAN fgIsOid, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + UINT_32 u4SetQueryInfoLen, + PUINT_8 pucInfoBuffer, OUT PVOID pvSetQueryBuffer, IN UINT_32 u4SetQueryBufferLen) +{ + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_8 ucCmdSeqNum; + + prGlueInfo = prAdapter->prGlueInfo; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + u4SetQueryInfoLen)); + + DEBUGFUNC("wlanSendSetQueryCmd"); + + if (!prCmdInfo) { + DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + DBGLOG(OID, TRACE, "ucCmdSeqNum =%d, ucCID =%d\n", ucCmdSeqNum, ucCID); + + /* Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->eNetworkType = NETWORK_TYPE_AIS_INDEX; + prCmdInfo->u2InfoBufLen = (UINT_16) (CMD_HDR_SIZE + u4SetQueryInfoLen); + prCmdInfo->pfCmdDoneHandler = pfCmdDoneHandler; + prCmdInfo->pfCmdTimeoutHandler = pfCmdTimeoutHandler; + prCmdInfo->fgIsOid = fgIsOid; + prCmdInfo->ucCID = ucCID; + prCmdInfo->fgSetQuery = fgSetQuery; + prCmdInfo->fgNeedResp = fgNeedResp; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u4SetQueryInfoLen; + prCmdInfo->pvInformationBuffer = pvSetQueryBuffer; + prCmdInfo->u4InformationBufferLength = u4SetQueryBufferLen; + + /* Setup WIFI_CMD_T (no payload) */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + if (u4SetQueryInfoLen > 0 && pucInfoBuffer != NULL) + kalMemCopy(prWifiCmd->aucBuffer, pucInfoBuffer, u4SetQueryInfoLen); + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + return WLAN_STATUS_PENDING; +} + +#if CFG_SUPPORT_WAPI +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called by WAPI ui to set wapi mode, which is needed to info the the driver +* to operation at WAPI mode while driver initialize. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. +* \retval WLAN_STATUS_INVALID_LENGTH +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetWapiMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + DEBUGFUNC("wlanoidSetWapiMode"); + DBGLOG(OID, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + /* Todo:: For support WAPI and Wi-Fi at same driver, use the set wapi assoc ie at the check point */ + /* The Adapter Connection setting fgUseWapi will cleat whil oid set mode (infra), */ + /* And set fgUseWapi True while set wapi assoc ie */ + /* policay selection, add key all depend on this flag, */ + /* The fgUseWapi may remove later */ + if (*(PUINT_32) pvSetBuffer) + prAdapter->fgUseWapi = TRUE; + else + prAdapter->fgUseWapi = FALSE; + +#if 0 + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + 4)); + + if (!prCmdInfo) { + DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_BUILD_CONNECTION cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->eNetworkType = NETWORK_TYPE_AIS_INDEX; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + 4; + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = NULL; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_WAPI_MODE; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u4SetBufferLen; + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + cp = (PUINT_8) (prWifiCmd->aucBuffer); + + kalMemCopy(cp, (PUINT_8) pvSetBuffer, 4); + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; +#else + return WLAN_STATUS_SUCCESS; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called by WAPI to set the assoc info, which is needed to add to +* Association request frame while join WAPI AP. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. +* \retval WLAN_STATUS_INVALID_LENGTH +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetWapiAssocInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_WAPI_INFO_ELEM_T prWapiInfo; + PUINT_8 cp; + UINT_16 u2AuthSuiteCount = 0; + UINT_16 u2PairSuiteCount = 0; + UINT_32 u4AuthKeyMgtSuite = 0; + UINT_32 u4PairSuite = 0; + UINT_32 u4GroupSuite = 0; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + DEBUGFUNC("wlanoidSetWapiAssocInfo"); + DBGLOG(OID, LOUD, "\r\n"); + + if (u4SetBufferLen < 20 /* From EID to Group cipher */) { + prAdapter->rWifiVar.rConnSettings.fgWapiMode = FALSE; + DBGLOG(SEC, INFO, "fgWapiMode = FALSE due to u4SetBufferLen %u < 20!\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + if (u4SetBufferLen > sizeof(prAdapter->prGlueInfo->aucWapiAssocInfoIEs)) + return WLAN_STATUS_INVALID_LENGTH; + + prAdapter->rWifiVar.rConnSettings.fgWapiMode = TRUE; + + /* if (prWapiInfo->ucElemId != ELEM_ID_WAPI) */ + /* DBGLOG(SEC, TRACE, ("Not WAPI IE ?!\n")); */ + + /* if (prWapiInfo->ucLength < 18) */ + /* return WLAN_STATUS_INVALID_LENGTH; */ + + *pu4SetInfoLen = u4SetBufferLen; + + prWapiInfo = (P_WAPI_INFO_ELEM_T) pvSetBuffer; + + if (prWapiInfo->ucElemId != ELEM_ID_WAPI) { + DBGLOG(SEC, INFO, "Not WAPI IE ?! u4SetBufferLen = %u\n", u4SetBufferLen); + prAdapter->rWifiVar.rConnSettings.fgWapiMode = FALSE; + return WLAN_STATUS_INVALID_LENGTH; + } + + if (prWapiInfo->ucLength < 18) + return WLAN_STATUS_INVALID_LENGTH; + + /* Skip Version check */ + cp = (PUINT_8) &prWapiInfo->u2AuthKeyMgtSuiteCount; + + WLAN_GET_FIELD_16(cp, &u2AuthSuiteCount); + + if (u2AuthSuiteCount > 1) + return WLAN_STATUS_INVALID_LENGTH; + + cp = (PUINT_8) &prWapiInfo->aucAuthKeyMgtSuite1[0]; + WLAN_GET_FIELD_32(cp, &u4AuthKeyMgtSuite); + + DBGLOG(SEC, TRACE, "WAPI: Assoc Info auth mgt suite [%d]: %02x-%02x-%02x-%02x\n", + u2AuthSuiteCount, + (UCHAR) (u4AuthKeyMgtSuite & 0x000000FF), + (UCHAR) ((u4AuthKeyMgtSuite >> 8) & 0x000000FF), + (UCHAR) ((u4AuthKeyMgtSuite >> 16) & 0x000000FF), + (UCHAR) ((u4AuthKeyMgtSuite >> 24) & 0x000000FF)); + + if (u4AuthKeyMgtSuite != WAPI_AKM_SUITE_802_1X && u4AuthKeyMgtSuite != WAPI_AKM_SUITE_PSK) + ASSERT(FALSE); + + cp += 4; + WLAN_GET_FIELD_16(cp, &u2PairSuiteCount); + if (u2PairSuiteCount > 1) + return WLAN_STATUS_INVALID_LENGTH; + + cp += 2; + WLAN_GET_FIELD_32(cp, &u4PairSuite); + DBGLOG(SEC, TRACE, "WAPI: Assoc Info pairwise cipher suite [%d]: %02x-%02x-%02x-%02x\n", + u2PairSuiteCount, + (UCHAR) (u4PairSuite & 0x000000FF), + (UCHAR) ((u4PairSuite >> 8) & 0x000000FF), + (UCHAR) ((u4PairSuite >> 16) & 0x000000FF), (UCHAR) ((u4PairSuite >> 24) & 0x000000FF)); + + if (u4PairSuite != WAPI_CIPHER_SUITE_WPI) + ASSERT(FALSE); + + cp += 4; + WLAN_GET_FIELD_32(cp, &u4GroupSuite); + DBGLOG(SEC, TRACE, "WAPI: Assoc Info group cipher suite : %02x-%02x-%02x-%02x\n", + (UCHAR) (u4GroupSuite & 0x000000FF), + (UCHAR) ((u4GroupSuite >> 8) & 0x000000FF), + (UCHAR) ((u4GroupSuite >> 16) & 0x000000FF), (UCHAR) ((u4GroupSuite >> 24) & 0x000000FF)); + + if (u4GroupSuite != WAPI_CIPHER_SUITE_WPI) + ASSERT(FALSE); + + prAdapter->rWifiVar.rConnSettings.u4WapiSelectedAKMSuite = u4AuthKeyMgtSuite; + prAdapter->rWifiVar.rConnSettings.u4WapiSelectedPairwiseCipher = u4PairSuite; + prAdapter->rWifiVar.rConnSettings.u4WapiSelectedGroupCipher = u4GroupSuite; + + return WLAN_STATUS_SUCCESS; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the wpi key to the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer P_PARAM_WPI_KEY, which is set by NDIS, is unpacked. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetWapiKey(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_PARAM_WPI_KEY_T prNewKey; + P_CMD_802_11_KEY prCmdKey; + PUINT_8 pc; + UINT_8 ucCmdSeqNum; + + DEBUGFUNC("wlanoidSetWapiKey"); + DBGLOG(OID, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set add key! (Adapter not ready). ACPI=D%d, Radio=%d\r\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + prNewKey = (P_PARAM_WPI_KEY_T) pvSetBuffer; + + DBGLOG_MEM8(OID, TRACE, (PUINT_8) pvSetBuffer, 560); + pc = (PUINT_8) pvSetBuffer; + + *pu4SetInfoLen = u4SetBufferLen; + + /* Exception check */ + if (prNewKey->ucKeyID != 0x1 && prNewKey->ucKeyID != 0x0) { + prNewKey->ucKeyID = prNewKey->ucKeyID & BIT(0); + /* DBGLOG(SEC, INFO, ("Invalid WAPI key ID (%d)\r\n", prNewKey->ucKeyID)); */ + } + + /* Dump P_PARAM_WPI_KEY_T content. */ + DBGLOG(OID, TRACE, "Set: Dump P_PARAM_WPI_KEY_T content\r\n"); + DBGLOG(OID, TRACE, "TYPE : %d\r\n", prNewKey->eKeyType); + DBGLOG(OID, TRACE, "Direction : %d\r\n", prNewKey->eDirection); + DBGLOG(OID, TRACE, "KeyID : %d\r\n", prNewKey->ucKeyID); + DBGLOG(OID, TRACE, "AddressIndex:\r\n"); + DBGLOG_MEM8(OID, TRACE, prNewKey->aucAddrIndex, 12); + prNewKey->u4LenWPIEK = 16; + + DBGLOG_MEM8(OID, TRACE, (PUINT_8) prNewKey->aucWPIEK, (UINT_8) prNewKey->u4LenWPIEK); + prNewKey->u4LenWPICK = 16; + + DBGLOG(OID, TRACE, "CK Key(%d):\r\n", (UINT_8) prNewKey->u4LenWPICK); + DBGLOG_MEM8(OID, TRACE, (PUINT_8) prNewKey->aucWPICK, (UINT_8) prNewKey->u4LenWPICK); + DBGLOG(OID, TRACE, "PN:\r\n"); + if (prNewKey->eKeyType == 0) { + prNewKey->aucPN[0] = 0x5c; + prNewKey->aucPN[1] = 0x36; + prNewKey->aucPN[2] = 0x5c; + prNewKey->aucPN[3] = 0x36; + prNewKey->aucPN[4] = 0x5c; + prNewKey->aucPN[5] = 0x36; + prNewKey->aucPN[6] = 0x5c; + prNewKey->aucPN[7] = 0x36; + prNewKey->aucPN[8] = 0x5c; + prNewKey->aucPN[9] = 0x36; + prNewKey->aucPN[10] = 0x5c; + prNewKey->aucPN[11] = 0x36; + prNewKey->aucPN[12] = 0x5c; + prNewKey->aucPN[13] = 0x36; + prNewKey->aucPN[14] = 0x5c; + prNewKey->aucPN[15] = 0x36; + } + + DBGLOG_MEM8(OID, TRACE, (PUINT_8) prNewKey->aucPN, 16); + + prGlueInfo = prAdapter->prGlueInfo; + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + u4SetBufferLen)); + + if (!prCmdInfo) { + DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_ID_ADD_REMOVE_KEY cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->eNetworkType = NETWORK_TYPE_AIS_INDEX; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_802_11_KEY); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_ADD_REMOVE_KEY; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u4SetBufferLen; + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prCmdKey = (P_CMD_802_11_KEY) (prWifiCmd->aucBuffer); + + kalMemZero(prCmdKey, sizeof(CMD_802_11_KEY)); + + prCmdKey->ucAddRemove = 1; /* Add */ + + if (prNewKey->eKeyType == ENUM_WPI_PAIRWISE_KEY) { + prCmdKey->ucTxKey = 1; + prCmdKey->ucKeyType = 1; + } + + kalMemCopy(prCmdKey->aucPeerAddr, (PUINT_8) prNewKey->aucAddrIndex, MAC_ADDR_LEN); + + prCmdKey->ucNetType = 0; /* AIS */ + + prCmdKey->ucKeyId = prNewKey->ucKeyID; + + prCmdKey->ucKeyLen = 32; + + prCmdKey->ucAlgorithmId = CIPHER_SUITE_WPI; + + kalMemCopy(prCmdKey->aucKeyMaterial, (PUINT_8) prNewKey->aucWPIEK, 16); + + kalMemCopy(prCmdKey->aucKeyMaterial + 16, (PUINT_8) prNewKey->aucWPICK, 16); + + kalMemCopy(prCmdKey->aucKeyRsc, (PUINT_8) prNewKey->aucPN, 16); + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; +} /* wlanoidSetAddKey */ +#endif + +#if CFG_ENABLE_WAKEUP_ON_LAN +WLAN_STATUS +wlanoidSetAddWakeupPattern(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_PM_PACKET_PATTERN prPacketPattern; + + DEBUGFUNC("wlanoidSetAddWakeupPattern"); + DBGLOG(OID, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_PM_PACKET_PATTERN); + + if (u4SetBufferLen < sizeof(PARAM_PM_PACKET_PATTERN)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prPacketPattern = (P_PARAM_PM_PACKET_PATTERN) pvSetBuffer; + + /* + * FIXME: + * Send the struct to firmware + */ + + return WLAN_STATUS_FAILURE; +} + +WLAN_STATUS +wlanoidSetRemoveWakeupPattern(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_PM_PACKET_PATTERN prPacketPattern; + + DEBUGFUNC("wlanoidSetAddWakeupPattern"); + DBGLOG(OID, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_PM_PACKET_PATTERN); + + if (u4SetBufferLen < sizeof(PARAM_PM_PACKET_PATTERN)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prPacketPattern = (P_PARAM_PM_PACKET_PATTERN) pvSetBuffer; + + /* + * FIXME: + * Send the struct to firmware + */ + + return WLAN_STATUS_FAILURE; +} + +WLAN_STATUS +wlanoidQueryEnableWakeup(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + PUINT_32 pu4WakeupEventEnable; + + DEBUGFUNC("wlanoidQueryEnableWakeup"); + DBGLOG(OID, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(UINT_32); + + if (u4QueryBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + pu4WakeupEventEnable = (PUINT_32) pvQueryBuffer; + + *pu4WakeupEventEnable = prAdapter->u4WakeupEventEnable; + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidSetEnableWakeup(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PUINT_32 pu4WakeupEventEnable; + + DEBUGFUNC("wlanoidSetEnableWakup"); + DBGLOG(OID, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(UINT_32); + + if (u4SetBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + pu4WakeupEventEnable = (PUINT_32) pvSetBuffer; + prAdapter->u4WakeupEventEnable = *pu4WakeupEventEnable; + + /* + * FIXME: + * Send Command Event for setting wakeup-pattern / Magic Packet to firmware + */ + + return WLAN_STATUS_FAILURE; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to configure PS related settings for WMM-PS test. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetWiFiWmmPsTest(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T prWmmPsTestInfo; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + CMD_SET_WMM_PS_TEST_STRUCT_T rSetWmmPsTestParam; + UINT_16 u2CmdBufLen; + P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo; + P_BSS_INFO_T prBssInfo; + + DEBUGFUNC("wlanoidSetWiFiWmmPsTest"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T); + + prWmmPsTestInfo = (P_PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T) pvSetBuffer; + + rSetWmmPsTestParam.ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + rSetWmmPsTestParam.bmfgApsdEnAc = prWmmPsTestInfo->bmfgApsdEnAc; + rSetWmmPsTestParam.ucIsEnterPsAtOnce = prWmmPsTestInfo->ucIsEnterPsAtOnce; + rSetWmmPsTestParam.ucIsDisableUcTrigger = prWmmPsTestInfo->ucIsDisableUcTrigger; + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[rSetWmmPsTestParam.ucNetTypeIndex]); + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + prPmProfSetupInfo->ucBmpDeliveryAC = (rSetWmmPsTestParam.bmfgApsdEnAc >> 4) & BITS(0, 3); + prPmProfSetupInfo->ucBmpTriggerAC = rSetWmmPsTestParam.bmfgApsdEnAc & BITS(0, 3); + + u2CmdBufLen = sizeof(CMD_SET_WMM_PS_TEST_STRUCT_T); + +#if 0 + /* it will apply the disable trig or not immediately */ + if (prPmInfo->ucWmmPsDisableUcPoll && prPmInfo->ucWmmPsConnWithTrig) + ; /* NIC_PM_WMM_PS_DISABLE_UC_TRIG(prAdapter, TRUE); */ + else + ; /* NIC_PM_WMM_PS_DISABLE_UC_TRIG(prAdapter, FALSE); */ +#endif + + rStatus = wlanSendSetQueryCmd(prAdapter, CMD_ID_SET_WMM_PS_TEST_PARMS, TRUE, FALSE, TRUE, NULL, /* TODO? */ + NULL, u2CmdBufLen, (PUINT_8) &rSetWmmPsTestParam, NULL, 0); + + return rStatus; +} /* wlanoidSetWiFiWmmPsTest */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to configure enable/disable TX A-MPDU feature. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetTxAmpdu(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + CMD_TX_AMPDU_T rTxAmpdu; + UINT_16 u2CmdBufLen; + PBOOLEAN pfgEnable; + + DEBUGFUNC("wlanoidSetTxAmpdu"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(BOOLEAN); + + pfgEnable = (PBOOLEAN) pvSetBuffer; + + rTxAmpdu.fgEnable = *pfgEnable; + + u2CmdBufLen = sizeof(CMD_TX_AMPDU_T); + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_TX_AMPDU, + TRUE, FALSE, TRUE, NULL, NULL, u2CmdBufLen, (PUINT_8) &rTxAmpdu, NULL, 0); + + return rStatus; +} /* wlanoidSetTxAmpdu */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to configure reject/accept ADDBA Request. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAddbaReject(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + CMD_ADDBA_REJECT_T rAddbaReject; + UINT_16 u2CmdBufLen; + PBOOLEAN pfgEnable; + + DEBUGFUNC("wlanoidSetAddbaReject"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(BOOLEAN); + + pfgEnable = (PBOOLEAN) pvSetBuffer; + + rAddbaReject.fgEnable = *pfgEnable; + + u2CmdBufLen = sizeof(CMD_ADDBA_REJECT_T); + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_ADDBA_REJECT, + TRUE, FALSE, TRUE, NULL, NULL, u2CmdBufLen, (PUINT_8) &rAddbaReject, NULL, 0); + + return rStatus; +} /* wlanoidSetAddbaReject */ + +#if CFG_SLT_SUPPORT + +WLAN_STATUS +wlanoidQuerySLTStatus(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_PARAM_MTK_SLT_TEST_STRUCT_T prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUCT_T) NULL; + P_SLT_INFO_T prSltInfo = (P_SLT_INFO_T) NULL; + + DEBUGFUNC("wlanoidQuerySLTStatus"); + DBGLOG(OID, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(PARAM_MTK_SLT_TEST_STRUCT_T); + + if (u4QueryBufferLen < sizeof(PARAM_MTK_SLT_TEST_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvQueryBuffer); + + prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUCT_T) pvQueryBuffer; + + prSltInfo = &(prAdapter->rWifiVar.rSltInfo); + + switch (prMtkSltInfo->rSltFuncIdx) { + case ENUM_MTK_SLT_FUNC_LP_SET: + { + P_PARAM_MTK_SLT_LP_TEST_STRUCT_T prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUCT_T) NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_LP_TEST_STRUCT_T)); + + prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUCT_T) &prMtkSltInfo->unFuncInfoContent; + + prLpSetting->u4BcnRcvNum = prSltInfo->u4BeaconReceiveCnt; + } + break; + default: + /* TBD... */ + break; + } + + return rWlanStatus; +} /* wlanoidQuerySLTStatus */ + +WLAN_STATUS +wlanoidUpdateSLTMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_PARAM_MTK_SLT_TEST_STRUCT_T prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUCT_T) NULL; + P_SLT_INFO_T prSltInfo = (P_SLT_INFO_T) NULL; + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; + + /* 1. Action: Update or Initial Set + * 2. Role. + * 3. Target MAC address. + * 4. RF BW & Rate Settings + */ + + DEBUGFUNC("wlanoidUpdateSLTMode"); + DBGLOG(OID, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_MTK_SLT_TEST_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_MTK_SLT_TEST_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUCT_T) pvSetBuffer; + + prSltInfo = &(prAdapter->rWifiVar.rSltInfo); + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + + switch (prMtkSltInfo->rSltFuncIdx) { + case ENUM_MTK_SLT_FUNC_INITIAL: /* Initialize */ + { + P_PARAM_MTK_SLT_INITIAL_STRUCT_T prMtkSltInit = (P_PARAM_MTK_SLT_INITIAL_STRUCT_T) NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_INITIAL_STRUCT_T)); + + prMtkSltInit = (P_PARAM_MTK_SLT_INITIAL_STRUCT_T) &prMtkSltInfo->unFuncInfoContent; + + if (prSltInfo->prPseudoStaRec != NULL) { + /* The driver has been initialized. */ + prSltInfo->prPseudoStaRec = NULL; + } + + prSltInfo->prPseudoBssDesc = scanSearchExistingBssDesc(prAdapter, + BSS_TYPE_IBSS, + prMtkSltInit->aucTargetMacAddr, + prMtkSltInit->aucTargetMacAddr); + + prSltInfo->u2SiteID = prMtkSltInit->u2SiteID; + + /* Bandwidth 2.4G: Channel 1~14 + * Bandwidth 5G: *36, 40, 44, 48, 52, 56, 60, 64, + * *100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, + * 149, 153, *157, 161, + * 184, 188, 192, 196, 200, 204, 208, 212, *216 + */ + prSltInfo->ucChannel2G4 = 1 + (prSltInfo->u2SiteID % 4) * 5; + + switch (prSltInfo->ucChannel2G4) { + case 1: + prSltInfo->ucChannel5G = 36; + break; + case 6: + prSltInfo->ucChannel5G = 52; + break; + case 11: + prSltInfo->ucChannel5G = 104; + break; + case 16: + prSltInfo->ucChannel2G4 = 14; + prSltInfo->ucChannel5G = 161; + break; + default: + ASSERT(FALSE); + } + + if (prSltInfo->prPseudoBssDesc == NULL) { + do { + prSltInfo->prPseudoBssDesc = scanAllocateBssDesc(prAdapter); + + if (prSltInfo->prPseudoBssDesc == NULL) { + rWlanStatus = WLAN_STATUS_FAILURE; + break; + } + prBssDesc = prSltInfo->prPseudoBssDesc; + } while (FALSE); + } else { + prBssDesc = prSltInfo->prPseudoBssDesc; + } + + if (prBssDesc) { + prBssDesc->eBSSType = BSS_TYPE_IBSS; + + COPY_MAC_ADDR(prBssDesc->aucSrcAddr, prMtkSltInit->aucTargetMacAddr); + COPY_MAC_ADDR(prBssDesc->aucBSSID, prBssInfo->aucOwnMacAddr); + + prBssDesc->u2BeaconInterval = 100; + prBssDesc->u2ATIMWindow = 0; + prBssDesc->ucDTIMPeriod = 1; + + prBssDesc->u2IELength = 0; + + prBssDesc->fgIsERPPresent = TRUE; + prBssDesc->fgIsHTPresent = TRUE; + + prBssDesc->u2OperationalRateSet = BIT(RATE_36M_INDEX); + prBssDesc->u2BSSBasicRateSet = BIT(RATE_36M_INDEX); + prBssDesc->fgIsUnknownBssBasicRate = FALSE; + + prBssDesc->fgIsLargerTSF = TRUE; + + prBssDesc->eBand = BAND_2G4; + + prBssDesc->ucChannelNum = prSltInfo->ucChannel2G4; + + prBssDesc->ucPhyTypeSet = PHY_TYPE_SET_802_11ABGN; + + GET_CURRENT_SYSTIME(&prBssDesc->rUpdateTime); + } + } + break; + case ENUM_MTK_SLT_FUNC_RATE_SET: /* Update RF Settings. */ + if (prSltInfo->prPseudoStaRec == NULL) { + rWlanStatus = WLAN_STATUS_FAILURE; + break; + } + + P_PARAM_MTK_SLT_TR_TEST_STRUCT_T prTRSetting = (P_PARAM_MTK_SLT_TR_TEST_STRUCT_T) NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_TR_TEST_STRUCT_T)); + + prStaRec = prSltInfo->prPseudoStaRec; + prTRSetting = (P_PARAM_MTK_SLT_TR_TEST_STRUCT_T) &prMtkSltInfo->unFuncInfoContent; + + if (prTRSetting->rNetworkType == PARAM_NETWORK_TYPE_OFDM5) { + prBssInfo->eBand = BAND_5G; + prBssInfo->ucPrimaryChannel = prSltInfo->ucChannel5G; + } + if (prTRSetting->rNetworkType == PARAM_NETWORK_TYPE_OFDM24) { + prBssInfo->eBand = BAND_2G4; + prBssInfo->ucPrimaryChannel = prSltInfo->ucChannel2G4; + } + + if ((prTRSetting->u4FixedRate & FIXED_BW_DL40) != 0) { + /* RF 40 */ + /* It would controls RFBW capability in WTBL. */ + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; + /* This controls RF BW, RF BW would be 40 only if */ + /* 1. PHY_TYPE_BIT_HT is TRUE. */ + /* 2. SCO is SCA/SCB. */ + prStaRec->ucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + + /* U20/L20 Control. */ + switch (prTRSetting->u4FixedRate & 0xC000) { + case FIXED_EXT_CHNL_U20: + prBssInfo->eBssSCO = CHNL_EXT_SCB; /* +2 */ + if (prTRSetting->rNetworkType == PARAM_NETWORK_TYPE_OFDM5) + prBssInfo->ucPrimaryChannel += 2; + else { + /* For channel 1, testing L20 at channel 8. */ + if (prBssInfo->ucPrimaryChannel < 5) + prBssInfo->ucPrimaryChannel = 8; + } + break; + case FIXED_EXT_CHNL_L20: + default: /* 40M */ + prBssInfo->eBssSCO = CHNL_EXT_SCA; /* -2 */ + if (prTRSetting->rNetworkType == PARAM_NETWORK_TYPE_OFDM5) { + prBssInfo->ucPrimaryChannel -= 2; + } else { + /* For channel 11 / 14. testing U20 at channel 3. */ + if (prBssInfo->ucPrimaryChannel > 10) + prBssInfo->ucPrimaryChannel = 3; + } + break; + } + } else { + /* RF 20 */ + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SUP_CHNL_WIDTH; + prBssInfo->eBssSCO = CHNL_EXT_SCN; + } + + prBssInfo->fgErpProtectMode = FALSE; + prBssInfo->eHtProtectMode = HT_PROTECT_MODE_NONE; + prBssInfo->eGfOperationMode = GF_MODE_NORMAL; + + nicUpdateBss(prAdapter, prBssInfo->ucNetTypeIndex); + + prStaRec->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); + + switch (prTRSetting->u4FixedRate & 0xFF) { + case RATE_OFDM_54M: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_54M_INDEX); + break; + case RATE_OFDM_48M: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_48M_INDEX); + break; + case RATE_OFDM_36M: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_36M_INDEX); + break; + case RATE_OFDM_24M: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_24M_INDEX); + break; + case RATE_OFDM_6M: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_6M_INDEX); + break; + case RATE_CCK_11M_LONG: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_11M_INDEX); + break; + case RATE_CCK_1M_LONG: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_1M_INDEX); + break; + case RATE_GF_MCS_0: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_HT_PHY_INDEX); + prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + break; + case RATE_MM_MCS_7: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_HT_PHY_INDEX); + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_HT_GF; +#if 0 /* Only for Current Measurement Mode. */ + prStaRec->u2HtCapInfo |= (HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); +#endif + break; + case RATE_GF_MCS_7: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_HT_PHY_INDEX); + prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + break; + default: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_36M_INDEX); + break; + } + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + break; + case ENUM_MTK_SLT_FUNC_LP_SET: /* Reset LP Test Result. */ + { + P_PARAM_MTK_SLT_LP_TEST_STRUCT_T prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUCT_T) NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_LP_TEST_STRUCT_T)); + + prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUCT_T) &prMtkSltInfo->unFuncInfoContent; + + if (prSltInfo->prPseudoBssDesc == NULL) { + /* Please initial SLT Mode first. */ + break; + } + prBssDesc = prSltInfo->prPseudoBssDesc; + + switch (prLpSetting->rLpTestMode) { + case ENUM_MTK_LP_TEST_NORMAL: + /* In normal mode, we would use target MAC address to be the BSSID. */ + COPY_MAC_ADDR(prBssDesc->aucBSSID, prBssInfo->aucOwnMacAddr); + prSltInfo->fgIsDUT = FALSE; + break; + case ENUM_MTK_LP_TEST_GOLDEN_SAMPLE: + /* 1. Lower AIFS of BCN queue. + * 2. Fixed Random Number tobe 0. + */ + prSltInfo->fgIsDUT = FALSE; + /* In LP test mode, we would use MAC address of Golden Sample to be the BSSID. */ + COPY_MAC_ADDR(prBssDesc->aucBSSID, prBssInfo->aucOwnMacAddr); + break; + case ENUM_MTK_LP_TEST_DUT: + /* 1. Enter Sleep Mode. + * 2. Fix random number a large value & enlarge AIFN of BCN queue. + */ + COPY_MAC_ADDR(prBssDesc->aucBSSID, prBssDesc->aucSrcAddr); + prSltInfo->u4BeaconReceiveCnt = 0; + prSltInfo->fgIsDUT = TRUE; + break; + } + + } + + break; + default: + break; + } + + return WLAN_STATUS_FAILURE; + + return rWlanStatus; +} /* wlanoidUpdateSLTMode */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query NVRAM value. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryNvramRead(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T prNvramRwInfo; + UINT_16 u2Data; + BOOLEAN fgStatus; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryNvramRead"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_NVRAM_RW_STRUCT_T); + + if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_NVRAM_RW_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + prNvramRwInfo = (P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T) pvQueryBuffer; + + if (prNvramRwInfo->ucEepromMethod == PARAM_EEPROM_READ_METHOD_READ) { + /* change to byte offset */ + fgStatus = kalCfgDataRead16(prAdapter->prGlueInfo, + prNvramRwInfo->ucEepromIndex << 1, + &u2Data); + + if (fgStatus) { + prNvramRwInfo->u2EepromData = u2Data; + DBGLOG(OID, INFO, "NVRAM Read: index=%#X, data=%#02X\r\n", + prNvramRwInfo->ucEepromIndex, u2Data); + } else { + DBGLOG(OID, ERROR, "NVRAM Read Failed: index=%#x.\r\n", prNvramRwInfo->ucEepromIndex); + rStatus = WLAN_STATUS_FAILURE; + } + } else if (prNvramRwInfo->ucEepromMethod == PARAM_EEPROM_READ_METHOD_GETSIZE) { + prNvramRwInfo->u2EepromData = CFG_FILE_WIFI_REC_SIZE; + DBGLOG(OID, INFO, "EEPROM size =%d\r\n", prNvramRwInfo->u2EepromData); + } + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T); + + return rStatus; +} /* wlanoidQueryNvramRead */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to write NVRAM value. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetNvramWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T prNvramRwInfo; + BOOLEAN fgStatus; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidSetNvramWrite"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_NVRAM_RW_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_NVRAM_RW_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prNvramRwInfo = (P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T) pvSetBuffer; + + /* change to byte offset */ + fgStatus = kalCfgDataWrite16(prAdapter->prGlueInfo, + prNvramRwInfo->ucEepromIndex << 1, + prNvramRwInfo->u2EepromData); + + if (fgStatus == FALSE) { + DBGLOG(OID, ERROR, "NVRAM Write Failed.\r\n"); + rStatus = WLAN_STATUS_FAILURE; + } + + return rStatus; +} /* wlanoidSetNvramWrite */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get the config data source type. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryCfgSrcType(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + ASSERT(prAdapter); + + *pu4QueryInfoLen = sizeof(ENUM_CFG_SRC_TYPE_T); + + if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) + *(P_ENUM_CFG_SRC_TYPE_T) pvQueryBuffer = CFG_SRC_TYPE_NVRAM; + else + *(P_ENUM_CFG_SRC_TYPE_T) pvQueryBuffer = CFG_SRC_TYPE_EEPROM; + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get the config data source type. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryEepromType(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + ASSERT(prAdapter); + + *pu4QueryInfoLen = sizeof(P_ENUM_EEPROM_TYPE_T); + +#if CFG_SUPPORT_NIC_CAPABILITY + if (prAdapter->fgIsEepromUsed == TRUE) + *(P_ENUM_EEPROM_TYPE_T) pvQueryBuffer = EEPROM_TYPE_PRESENT; + else + *(P_ENUM_EEPROM_TYPE_T) pvQueryBuffer = EEPROM_TYPE_NO; +#else + *(P_ENUM_EEPROM_TYPE_T) pvQueryBuffer = EEPROM_TYPE_NO; +#endif + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get the config data source type. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetCountryCode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PUINT_8 pucCountry; + UINT_16 u2CountryCode; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(u4SetBufferLen == 2); + + *pu4SetInfoLen = 2; + + pucCountry = pvSetBuffer; + u2CountryCode = (((UINT_16) pucCountry[0]) << 8) | ((UINT_16) pucCountry[1]); + + /* previous country code == FF : ignore country code, current country code == FE : resume */ + if (prAdapter->rWifiVar.rConnSettings.u2CountryCodeBakup == COUNTRY_CODE_FF) { + if (u2CountryCode != COUNTRY_CODE_FE) { + DBGLOG(OID, INFO, "Skip country code cmd (0x%04x)\n", u2CountryCode); + return WLAN_STATUS_SUCCESS; + } + DBGLOG(OID, INFO, "Resume handle country code cmd (0x%04x)\n", u2CountryCode); + } + + prAdapter->rWifiVar.rConnSettings.u2CountryCode = u2CountryCode; + prAdapter->rWifiVar.rConnSettings.u2CountryCodeBakup = prAdapter->rWifiVar.rConnSettings.u2CountryCode; + DBGLOG(OID, LOUD, "u2CountryCodeBakup=0x%04x\n", prAdapter->rWifiVar.rConnSettings.u2CountryCodeBakup); + + /* Force to re-search country code in country domains */ + prAdapter->prDomainInfo = NULL; + rlmDomainSendCmd(prAdapter, FALSE); + + /* Update supported channel list in channel table based on current country domain */ + wlanUpdateChannelTable(prAdapter->prGlueInfo); + + return WLAN_STATUS_SUCCESS; +} + +#if 0 +WLAN_STATUS +wlanoidSetNoaParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T prNoaParam; + CMD_CUSTOM_NOA_PARAM_STRUCT_T rCmdNoaParam; + + DEBUGFUNC("wlanoidSetNoaParam"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_NOA_PARAM_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_NOA_PARAM_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prNoaParam = (P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T) pvSetBuffer; + + kalMemZero(&rCmdNoaParam, sizeof(CMD_CUSTOM_NOA_PARAM_STRUCT_T)); + rCmdNoaParam.u4NoaDurationMs = prNoaParam->u4NoaDurationMs; + rCmdNoaParam.u4NoaIntervalMs = prNoaParam->u4NoaIntervalMs; + rCmdNoaParam.u4NoaCount = prNoaParam->u4NoaCount; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_NOA_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_NOA_PARAM_STRUCT_T), + (PUINT_8) &rCmdNoaParam, pvSetBuffer, u4SetBufferLen); +} + +WLAN_STATUS +wlanoidSetOppPsParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T prOppPsParam; + CMD_CUSTOM_OPPPS_PARAM_STRUCT_T rCmdOppPsParam; + + DEBUGFUNC("wlanoidSetOppPsParam"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prOppPsParam = (P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T) pvSetBuffer; + + kalMemZero(&rCmdOppPsParam, sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T)); + rCmdOppPsParam.u4CTwindowMs = prOppPsParam->u4CTwindowMs; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_OPPPS_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T), + (PUINT_8) &rCmdOppPsParam, pvSetBuffer, u4SetBufferLen); +} + +WLAN_STATUS +wlanoidSetUApsdParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T prUapsdParam; + CMD_CUSTOM_UAPSD_PARAM_STRUCT_T rCmdUapsdParam; + P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo; + P_BSS_INFO_T prBssInfo; + + DEBUGFUNC("wlanoidSetUApsdParam"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + + prUapsdParam = (P_PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T) pvSetBuffer; + + kalMemZero(&rCmdUapsdParam, sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T)); + rCmdUapsdParam.fgEnAPSD = prUapsdParam->fgEnAPSD; + prAdapter->rWifiVar.fgSupportUAPSD = prUapsdParam->fgEnAPSD; + + rCmdUapsdParam.fgEnAPSD_AcBe = prUapsdParam->fgEnAPSD_AcBe; + rCmdUapsdParam.fgEnAPSD_AcBk = prUapsdParam->fgEnAPSD_AcBk; + rCmdUapsdParam.fgEnAPSD_AcVo = prUapsdParam->fgEnAPSD_AcVo; + rCmdUapsdParam.fgEnAPSD_AcVi = prUapsdParam->fgEnAPSD_AcVi; + prPmProfSetupInfo->ucBmpDeliveryAC = + ((prUapsdParam->fgEnAPSD_AcBe << 0) | + (prUapsdParam->fgEnAPSD_AcBk << 1) | + (prUapsdParam->fgEnAPSD_AcVi << 2) | (prUapsdParam->fgEnAPSD_AcVo << 3)); + prPmProfSetupInfo->ucBmpTriggerAC = + ((prUapsdParam->fgEnAPSD_AcBe << 0) | + (prUapsdParam->fgEnAPSD_AcBk << 1) | + (prUapsdParam->fgEnAPSD_AcVi << 2) | (prUapsdParam->fgEnAPSD_AcVo << 3)); + + rCmdUapsdParam.ucMaxSpLen = prUapsdParam->ucMaxSpLen; + prPmProfSetupInfo->ucUapsdSp = prUapsdParam->ucMaxSpLen; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_UAPSD_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T), + (PUINT_8) &rCmdUapsdParam, pvSetBuffer, u4SetBufferLen); +} +#endif + +#ifdef CFG_TC1_FEATURE /* for Passive Scan */ +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set Passive Scan mode. +* +* \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 +wlanoidSetPassiveScan(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PUINT_8 pucScanType; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(u4SetBufferLen == 1); + + *pu4SetInfoLen = 1; + + pucScanType = pvSetBuffer; + + if (*pucScanType == 0x2) + prAdapter->ucScanType = SCAN_TYPE_PASSIVE_SCAN; + else + prAdapter->ucScanType = SCAN_TYPE_ACTIVE_SCAN; + + return WLAN_STATUS_SUCCESS; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set BT profile or BT information and the +* driver will set the built-in PTA configuration into chip. +* +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBT(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + + P_PTA_IPC_T prPtaIpc; + + DEBUGFUNC("wlanoidSetBT.\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PTA_IPC_T); + if (u4SetBufferLen != sizeof(PTA_IPC_T)) { + WARNLOG(("Invalid length %u\n", u4SetBufferLen)); + return WLAN_STATUS_INVALID_LENGTH; + } + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail to set BT profile because of ACPI_D3\n"); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pvSetBuffer); + prPtaIpc = (P_PTA_IPC_T) pvSetBuffer; + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS && CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(OID, INFO, + "BCM BWCS CMD: BTPParams[0]=%02x, BTPParams[1]=%02x, BTPParams[2]=%02x, BTPParams[3]=%02x.\n", + prPtaIpc->u.aucBTPParams[0], prPtaIpc->u.aucBTPParams[1], prPtaIpc->u.aucBTPParams[2], + prPtaIpc->u.aucBTPParams[3]; + +#endif + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_BWCS, + TRUE, FALSE, FALSE, NULL, NULL, sizeof(PTA_IPC_T), (PUINT_8) prPtaIpc, NULL, 0); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query current BT profile and BTCR values +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryBT(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ +/* P_PARAM_PTA_IPC_T prPtaIpc; */ +/* UINT_32 u4QueryBuffLen; */ + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PTA_IPC_T); + + /* Check for query buffer length */ + if (u4QueryBufferLen != sizeof(PTA_IPC_T)) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvQueryBuffer); +/* prPtaIpc = (P_PTA_IPC_T)pvQueryBuffer; */ +/* prPtaIpc->ucCmd = BT_CMD_PROFILE; */ +/* prPtaIpc->ucLen = sizeof(prPtaIpc->u); */ +/* nicPtaGetProfile(prAdapter, (PUINT_8)&prPtaIpc->u, &u4QueryBuffLen); */ + + return WLAN_STATUS_SUCCESS; +} + +#if 0 +WLAN_STATUS +wlanoidQueryBtSingleAntenna(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PTA_INFO_T prPtaInfo; + PUINT_32 pu4SingleAntenna; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(UINT_32); + + /* Check for query buffer length */ + if (u4QueryBufferLen != sizeof(UINT_32)) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvQueryBuffer); + + prPtaInfo = &prAdapter->rPtaInfo; + pu4SingleAntenna = (PUINT_32) pvQueryBuffer; + + if (prPtaInfo->fgSingleAntenna) { + /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"Q Single Ant = 1\r\n")); */ + *pu4SingleAntenna = 1; + } else { + /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"Q Single Ant = 0\r\n")); */ + *pu4SingleAntenna = 0; + } + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidSetBtSingleAntenna(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + + PUINT_32 pu4SingleAntenna; + UINT_32 u4SingleAntenna; + P_PTA_INFO_T prPtaInfo; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + prPtaInfo = &prAdapter->rPtaInfo; + + *pu4SetInfoLen = sizeof(UINT_32); + if (u4SetBufferLen != sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + if (IS_ARB_IN_RFTEST_STATE(prAdapter)) + return WLAN_STATUS_SUCCESS; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail to set antenna because of ACPI_D3\n"); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pvSetBuffer); + pu4SingleAntenna = (PUINT_32) pvSetBuffer; + u4SingleAntenna = *pu4SingleAntenna; + + if (u4SingleAntenna == 0) { + /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"Set Single Ant = 0\r\n")); */ + prPtaInfo->fgSingleAntenna = FALSE; + } else { + /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"Set Single Ant = 1\r\n")); */ + prPtaInfo->fgSingleAntenna = TRUE; + } + ptaFsmRunEventSetConfig(prAdapter, &prPtaInfo->rPtaParam); + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS +WLAN_STATUS +wlanoidQueryPta(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PTA_INFO_T prPtaInfo; + PUINT_32 pu4Pta; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(UINT_32); + + /* Check for query buffer length */ + if (u4QueryBufferLen != sizeof(UINT_32)) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvQueryBuffer); + + prPtaInfo = &prAdapter->rPtaInfo; + pu4Pta = (PUINT_32) pvQueryBuffer; + + if (prPtaInfo->fgEnabled) { + /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"PTA = 1\r\n")); */ + *pu4Pta = 1; + } else { + /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"PTA = 0\r\n")); */ + *pu4Pta = 0; + } + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidSetPta(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PUINT_32 pu4PtaCtrl; + UINT_32 u4PtaCtrl; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(UINT_32); + if (u4SetBufferLen != sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + if (IS_ARB_IN_RFTEST_STATE(prAdapter)) + return WLAN_STATUS_SUCCESS; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail to set BT setting because of ACPI_D3\n"); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pvSetBuffer); + pu4PtaCtrl = (PUINT_32) pvSetBuffer; + u4PtaCtrl = *pu4PtaCtrl; + + if (u4PtaCtrl == 0) { + /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"Set Pta= 0\r\n")); */ + nicPtaSetFunc(prAdapter, FALSE); + } else { + /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"Set Pta= 1\r\n")); */ + nicPtaSetFunc(prAdapter, TRUE); + } + + return WLAN_STATUS_SUCCESS; +} +#endif + +#endif + + +WLAN_STATUS +wlanoidSetRxPacketFilterPriv( + IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + + WLAN_STATUS rStatus; + + DEBUGFUNC("wlanoidSetPacketFilter"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + + DBGLOG(OID, TRACE, "wlanoidSetRxPacketFilterPriv\n"); + + rStatus = wlanSendSetQueryCmd( + prAdapter, /* prAdapter */ + CMD_ID_SET_DROP_PACKET_CFG, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + TRUE, /* fgIsOid */ + nicCmdEventSetCommon, /* pfCmdDoneHandler*/ + nicOidCmdTimeoutCommon, /* pfCmdTimeoutHandler */ + u4SetBufferLen, /* u4SetQueryInfoLen */ + (PUINT_8) pvSetBuffer, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); + + return rStatus; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set Tx power profile. +* +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetTxPower(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + /* P_SET_TXPWR_CTRL_T pTxPwr = (P_SET_TXPWR_CTRL_T)pvSetBuffer; */ + /* UINT_32 i; */ + WLAN_STATUS rStatus; + + DEBUGFUNC("wlanoidSetTxPower"); + DBGLOG(OID, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + +#if 0 + DBGLOG(OID, INFO, "c2GLegacyStaPwrOffset=%d\n", pTxPwr->c2GLegacyStaPwrOffset); + DBGLOG(OID, INFO, "c2GHotspotPwrOffset=%d\n", pTxPwr->c2GHotspotPwrOffset); + DBGLOG(OID, INFO, "c2GP2pPwrOffset=%d\n", pTxPwr->c2GP2pPwrOffset); + DBGLOG(OID, INFO, "c2GBowPwrOffset=%d\n", pTxPwr->c2GBowPwrOffset); + DBGLOG(OID, INFO, "c5GLegacyStaPwrOffset=%d\n", pTxPwr->c5GLegacyStaPwrOffset); + DBGLOG(OID, INFO, "c5GHotspotPwrOffset=%d\n", pTxPwr->c5GHotspotPwrOffset); + DBGLOG(OID, INFO, "c5GP2pPwrOffset=%d\n", pTxPwr->c5GP2pPwrOffset); + DBGLOG(OID, INFO, "c5GBowPwrOffset=%d\n", pTxPwr->c5GBowPwrOffset); + DBGLOG(OID, INFO, "ucConcurrencePolicy=%d\n", pTxPwr->ucConcurrencePolicy); + + for (i = 0; i < 14; i++) + DBGLOG(OID, INFO, "acTxPwrLimit2G[%d]=%d\n", i, pTxPwr->acTxPwrLimit2G[i]); + + for (i = 0; i < 4; i++) + DBGLOG(OID, INFO, "acTxPwrLimit5G[%d]=%d\n", i, pTxPwr->acTxPwrLimit5G[i]); +#endif + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_TXPWR_CTRL, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + TRUE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + u4SetBufferLen, /* u4SetQueryInfoLen */ + (PUINT_8) pvSetBuffer, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); + + return rStatus; + +} + +WLAN_STATUS wlanSendMemDumpCmd(IN P_ADAPTER_T prAdapter, IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen) +{ + P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T prMemDumpInfo; + P_CMD_DUMP_MEM prCmdDumpMem; + CMD_DUMP_MEM rCmdDumpMem; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4MemSize = PARAM_MEM_DUMP_MAX_SIZE; + + UINT_32 u4RemainLeng = 0; + UINT_32 u4CurAddr = 0; + UINT_8 ucFragNum = 0; + + prCmdDumpMem = &rCmdDumpMem; + prMemDumpInfo = (P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T) pvQueryBuffer; + + u4RemainLeng = prMemDumpInfo->u4RemainLength; + u4CurAddr = prMemDumpInfo->u4Address + prMemDumpInfo->u4Length; + ucFragNum = prMemDumpInfo->ucFragNum + 1; + + /* Query. If request length is larger than max length, do it as ping pong. + * Send a command and wait for a event. Send next command while the event is received. + * + */ + do { + UINT_32 u4CurLeng = 0; + + if (u4RemainLeng > u4MemSize) { + u4CurLeng = u4MemSize; + u4RemainLeng -= u4MemSize; + } else { + u4CurLeng = u4RemainLeng; + u4RemainLeng = 0; + } + + prCmdDumpMem->u4Address = u4CurAddr; + prCmdDumpMem->u4Length = u4CurLeng; + prCmdDumpMem->u4RemainLength = u4RemainLeng; + prCmdDumpMem->ucFragNum = ucFragNum; + + DBGLOG(OID, TRACE, "[%d] 0x%X, len %u, remain len %u\n", + ucFragNum, + prCmdDumpMem->u4Address, prCmdDumpMem->u4Length, prCmdDumpMem->u4RemainLength); + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_DUMP_MEM, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryMemDump, + nicOidCmdTimeoutCommon, + sizeof(CMD_DUMP_MEM), + (PUINT_8) prCmdDumpMem, pvQueryBuffer, u4QueryBufferLen); + + } while (FALSE); + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to dump memory. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMemDump(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T prMemDumpInfo; + + DEBUGFUNC("wlanoidQueryMemDump"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(UINT_32); + + prMemDumpInfo = (P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T) pvQueryBuffer; + DBGLOG(OID, TRACE, "Dump 0x%X, len %u\n", prMemDumpInfo->u4Address, prMemDumpInfo->u4Length); + + prMemDumpInfo->u4RemainLength = prMemDumpInfo->u4Length; + prMemDumpInfo->u4Length = 0; + prMemDumpInfo->ucFragNum = 0; + + return wlanSendMemDumpCmd(prAdapter, pvQueryBuffer, u4QueryBufferLen); + +} /* end of wlanoidQueryMcrRead() */ + +#if CFG_ENABLE_WIFI_DIRECT +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to set the p2p mode. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2pMode(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS status = WLAN_STATUS_SUCCESS; + P_PARAM_CUSTOM_P2P_SET_STRUCT_T prSetP2P = (P_PARAM_CUSTOM_P2P_SET_STRUCT_T) NULL; + /* P_MSG_P2P_NETDEV_REGISTER_T prP2pNetdevRegMsg = (P_MSG_P2P_NETDEV_REGISTER_T)NULL; */ + DEBUGFUNC("wlanoidSetP2pMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_P2P_SET_STRUCT_T); + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_P2P_SET_STRUCT_T)) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prSetP2P = (P_PARAM_CUSTOM_P2P_SET_STRUCT_T) pvSetBuffer; + + DBGLOG(P2P, INFO, "Set P2P enable %p [%u] mode[%u]\n", prSetP2P, prSetP2P->u4Enable, prSetP2P->u4Mode); + + /* + * enable = 1, mode = 0 => init P2P network + * enable = 1, mode = 1 => init Soft AP network + * enable = 0 => uninit P2P/AP network + */ + + if (prSetP2P->u4Enable) { + p2pSetMode((prSetP2P->u4Mode == 1) ? TRUE : FALSE); + + if (p2pLaunch(prAdapter->prGlueInfo)) + ASSERT(prAdapter->fgIsP2PRegistered); + + if (prAdapter->rWifiVar.fgSupportUAPSD && prSetP2P->u4Mode == 1) { + PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T rUapsdParams; + + DBGLOG(OID, INFO, "wlanoidSetP2pMode Default enable ApUapsd\n"); + + kalMemZero(&rUapsdParams, sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T)); + rUapsdParams.fgEnAPSD = 1; + rUapsdParams.fgEnAPSD_AcBe = 1; + rUapsdParams.fgEnAPSD_AcBk = 1; + rUapsdParams.fgEnAPSD_AcVi = 1; + rUapsdParams.fgEnAPSD_AcVo = 1; + rUapsdParams.ucMaxSpLen = 0; /* default:0, Do not limit delivery pkt num */ + + nicSetUApsdParam(prAdapter, rUapsdParams, NETWORK_TYPE_P2P_INDEX); + } + + } else { + DBGLOG(P2P, TRACE, "prAdapter->fgIsP2PRegistered = %d\n", prAdapter->fgIsP2PRegistered); + + if (prAdapter->fgIsP2PRegistered) { + DBGLOG(P2P, INFO, "p2pRemove\n"); + p2pRemove(prAdapter->prGlueInfo); + } + + } + +#if 0 + prP2pNetdevRegMsg = (P_MSG_P2P_NETDEV_REGISTER_T) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + (sizeof(MSG_P2P_NETDEV_REGISTER_T))); + + if (prP2pNetdevRegMsg == NULL) { + ASSERT(FALSE); + status = WLAN_STATUS_RESOURCES; + return status; + } + + prP2pNetdevRegMsg->rMsgHdr.eMsgId = MID_MNY_P2P_NET_DEV_REGISTER; + prP2pNetdevRegMsg->fgIsEnable = (prSetP2P->u4Enable == 1) ? TRUE : FALSE; + prP2pNetdevRegMsg->ucMode = (UINT_8) prSetP2P->u4Mode; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prP2pNetdevRegMsg, MSG_SEND_METHOD_BUF); +#endif + + return status; +} +#endif + +#if CFG_SUPPORT_BUILD_DATE_CODE +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to query build date code information from firmware +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryBuildDateCode(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + CMD_GET_BUILD_DATE_CODE rCmdGetBuildDateCode; + + DEBUGFUNC("wlanoidQueryBuildDateCode"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(UINT_8) * 16; + + if (u4QueryBufferLen < sizeof(UINT_8) * 16) + return WLAN_STATUS_INVALID_LENGTH; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_BUILD_DATE_CODE, + FALSE, + TRUE, + TRUE, + nicCmdEventBuildDateCode, + nicOidCmdTimeoutCommon, + sizeof(CMD_GET_BUILD_DATE_CODE), + (PUINT_8) &rCmdGetBuildDateCode, pvQueryBuffer, u4QueryBufferLen); + +} /* end of wlanoidQueryBuildDateCode() */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to query BSS info from firmware +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryBSSInfo(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + EVENT_AIS_BSS_INFO_T rCmdBSSInfo; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(EVENT_AIS_BSS_INFO_T); + + if (u4QueryBufferLen < sizeof(EVENT_AIS_BSS_INFO_T)) + return WLAN_STATUS_INVALID_LENGTH; + kalMemZero(&rCmdBSSInfo, sizeof(EVENT_AIS_BSS_INFO_T)); + /* + * rStatus = wlanSendSetQueryCmd(prAdapter, + * CMD_ID_GET_BSS_INFO, + * FALSE, + * TRUE, + * TRUE, + * nicCmdEventGetBSSInfo, + * nicOidCmdTimeoutCommon, + * sizeof(P_EVENT_AIS_BSS_INFO_T), + * (PUINT_8) &rCmdBSSInfo, pvQueryBuffer, u4QueryBufferLen); + */ + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_BSS_INFO, + FALSE, + TRUE, + TRUE, + nicCmdEventGetBSSInfo, + nicOidCmdTimeoutCommon, + sizeof(EVENT_AIS_BSS_INFO_T), + (PUINT_8) &rCmdBSSInfo, pvQueryBuffer, u4QueryBufferLen); + + return rStatus; +} /* wlanoidSetWiFiWmmPsTest */ + +#if CFG_SUPPORT_BATCH_SCAN + +#define CMD_WLS_BATCHING "WLS_BATCHING" + +#define BATCHING_SET "SET" +#define BATCHING_GET "GET" +#define BATCHING_STOP "STOP" + +#define PARAM_SCANFREQ "SCANFREQ" +#define PARAM_MSCAN "MSCAN" +#define PARAM_BESTN "BESTN" +#define PARAM_CHANNEL "CHANNEL" +#define PARAM_RTT "RTT" + +WLAN_STATUS +batchSetCmd(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4WritenLen) +{ + P_CHANNEL_INFO_T prRfChannelInfo; + CMD_BATCH_REQ_T rCmdBatchReq; + + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + PCHAR head, p, p2; + UINT_32 tokens; + INT_32 scanfreq, mscan, bestn, rtt; + + DBGLOG(SCN, TRACE, "[BATCH] command=%s, len=%u\n", (PCHAR) pvSetBuffer, (UINT_32) u4SetBufferLen); + + if (!pu4WritenLen) + return -EINVAL; + *pu4WritenLen = 0; + + if (u4SetBufferLen < kalStrLen(CMD_WLS_BATCHING)) { + DBGLOG(SCN, TRACE, "[BATCH] invalid len %u\n", (UINT_32) u4SetBufferLen); + return -EINVAL; + } + + head = pvSetBuffer + kalStrLen(CMD_WLS_BATCHING) + 1; + kalMemSet(&rCmdBatchReq, 0, sizeof(CMD_BATCH_REQ_T)); + + if (!kalStrnCmp(head, BATCHING_SET, kalStrLen(BATCHING_SET))) { + + DBGLOG(SCN, TRACE, "XXX Start Batch Scan XXX\n"); + + head += kalStrLen(BATCHING_SET) + 1; + + /* SCANFREQ, MSCAN, BESTN */ + tokens = kalSScanf(head, "SCANFREQ=%d MSCAN=%d BESTN=%d", &scanfreq, &mscan, &bestn); + if (tokens != 3) { + DBGLOG(SCN, TRACE, "[BATCH] Parse fail: tokens=%u, SCANFREQ=%d MSCAN=%d BESTN=%d\n", + (UINT_32) tokens, scanfreq, mscan, bestn); + return -EINVAL; + } + /* RTT */ + p = kalStrStr(head, PARAM_RTT); + if (!p) { + DBGLOG(SCN, TRACE, "[BATCH] Parse RTT fail. head=%s\n", head); + return -EINVAL; + } + tokens = kalSScanf(p, "RTT=%d", &rtt); + if (tokens != 1) { + DBGLOG(SCN, TRACE, "[BATCH] Parse fail: tokens=%u, rtt=%d\n", (UINT_32) tokens, rtt); + return -EINVAL; + } + /* CHANNEL */ + p = kalStrStr(head, PARAM_CHANNEL); + if (!p) { + DBGLOG(SCN, TRACE, "[BATCH] Parse CHANNEL fail(1)\n"); + return -EINVAL; + } + head = p; + p = kalStrChr(head, '>'); + if (!p) { + DBGLOG(SCN, TRACE, "[BATCH] Parse CHANNEL fail(2)\n"); + return -EINVAL; + } + /* + * else { + * *p = '.'; // remove '>' because sscanf can not parse <%s> + * } + */ + /* + * tokens = kalSScanf(head, "CHANNEL=<%s", c_channel); + * if (tokens != 1) { + * DBGLOG(SCN, TRACE, ("[BATCH] Parse fail: tokens=%d, CHANNEL=<%s>\n", + * tokens, c_channel)); + * return -EINVAL; + * } + */ + rCmdBatchReq.ucChannelType = SCAN_CHANNEL_SPECIFIED; + rCmdBatchReq.ucChannelListNum = 0; + prRfChannelInfo = &rCmdBatchReq.arChannelList[0]; + p = head + kalStrLen(PARAM_CHANNEL) + 2; /* c_channel; */ + while ((p2 = kalStrSep((char **)&p, ",")) != NULL) { + if (p2 == NULL || *p2 == 0) + break; + if (*p2 == '\0') + continue; + if (*p2 == 'A') { + rCmdBatchReq.ucChannelType = + rCmdBatchReq.ucChannelType == + SCAN_CHANNEL_2G4 ? SCAN_CHANNEL_FULL : SCAN_CHANNEL_5G; + } else if (*p2 == 'B') { + rCmdBatchReq.ucChannelType = + rCmdBatchReq.ucChannelType == + SCAN_CHANNEL_5G ? SCAN_CHANNEL_FULL : SCAN_CHANNEL_2G4; + } else { + + /* Translate Freq from MHz to channel number. */ + prRfChannelInfo->ucChannelNum = kalStrtol(p2, NULL, 0); + DBGLOG(SCN, TRACE, "Scanning Channel:%u, freq: %d\n", + (UINT_32) prRfChannelInfo->ucChannelNum, + (UINT_32) nicChannelNum2Freq(prRfChannelInfo->ucChannelNum)); + prRfChannelInfo->ucBand = prRfChannelInfo->ucChannelNum < 15 ? BAND_2G4 : BAND_5G; + + rCmdBatchReq.ucChannelListNum++; + if (rCmdBatchReq.ucChannelListNum >= 32) + break; + prRfChannelInfo++; + } + } + + /* set channel for test */ +#if 0 + rCmdBatchReq.ucChannelType = 4; /* SCAN_CHANNEL_SPECIFIED; */ + rCmdBatchReq.ucChannelListNum = 0; + prRfChannelInfo = &rCmdBatchReq.arChannelList[0]; + for (i = 1; i <= 14; i++) { + + /* filter out some */ + if (i == 1 || i == 5 || i == 11) + continue; + + /* Translate Freq from MHz to channel number. */ + prRfChannelInfo->ucChannelNum = i; + DBGLOG(SCN, TRACE, "Scanning Channel:%d, freq: %d\n", + prRfChannelInfo->ucChannelNum, + nicChannelNum2Freq(prRfChannelInfo->ucChannelNum)); + prRfChannelInfo->ucBand = BAND_2G4; + + rCmdBatchReq.ucChannelListNum++; + prRfChannelInfo++; + } +#endif +#if 0 + rCmdBatchReq.ucChannelType = 0; /* SCAN_CHANNEL_FULL; */ +#endif + + rCmdBatchReq.u4Scanfreq = scanfreq; + rCmdBatchReq.ucMScan = mscan > CFG_BATCH_MAX_MSCAN ? CFG_BATCH_MAX_MSCAN : mscan; + rCmdBatchReq.ucBestn = bestn; + rCmdBatchReq.ucRtt = rtt; + DBGLOG(SCN, TRACE, "[BATCH] SCANFREQ=%u MSCAN=%u BESTN=%u RTT=%u\n", + (UINT_32) rCmdBatchReq.u4Scanfreq, + (UINT_32) rCmdBatchReq.ucMScan, + (UINT_32) rCmdBatchReq.ucBestn, (UINT_32) rCmdBatchReq.ucRtt; + + if (rCmdBatchReq.ucChannelType != SCAN_CHANNEL_SPECIFIED) { + DBGLOG(SCN, TRACE, "[BATCH] CHANNELS = %s\n", + rCmdBatchReq.ucChannelType == SCAN_CHANNEL_FULL ? "FULL" : + rCmdBatchReq.ucChannelType == SCAN_CHANNEL_2G4 ? "2.4G all" : "5G all"); + } else { + DBGLOG(SCN, TRACE, "[BATCH] CHANNEL list\n"); + prRfChannelInfo = &rCmdBatchReq.arChannelList[0]; + for (tokens = 0; tokens < rCmdBatchReq.ucChannelListNum; tokens++) { + DBGLOG(SCN, TRACE, "[BATCH] %s, %d\n", + prRfChannelInfo->ucBand == BAND_2G4 ? "2.4G" : "5G", + prRfChannelInfo->ucChannelNum); + prRfChannelInfo++; + } + } + + rCmdBatchReq.ucSeqNum = 1; + rCmdBatchReq.ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + rCmdBatchReq.ucCmd = SCAN_BATCH_REQ_START; + + *pu4WritenLen = kalSnprintf(pvSetBuffer, 3, "%d", rCmdBatchReq.ucMScan); + + } else if (!kalStrnCmp(head, BATCHING_STOP, kalStrLen(BATCHING_STOP))) { + + DBGLOG(SCN, TRACE, "XXX Stop Batch Scan XXX\n"); + + rCmdBatchReq.ucSeqNum = 1; + rCmdBatchReq.ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + rCmdBatchReq.ucCmd = SCAN_BATCH_REQ_STOP; + } else { + return -EINVAL; + } + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_BATCH_REQ, + TRUE, FALSE, TRUE, NULL, NULL, sizeof(CMD_BATCH_REQ_T), (PUINT_8) &rCmdBatchReq, NULL, 0); + + /* kalMemSet(pvSetBuffer, 0, u4SetBufferLen); */ + /* rStatus = kalSnprintf(pvSetBuffer, 2, "%s", "OK"); */ + + return rStatus; +} + +WLAN_STATUS +batchGetCmd(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + CMD_BATCH_REQ_T rCmdBatchReq; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_EVENT_BATCH_RESULT_T prEventBatchResult; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + prEventBatchResult = (P_EVENT_BATCH_RESULT_T) pvQueryBuffer; + + DBGLOG(SCN, TRACE, "XXX Get Batch Scan Result (%u) XXX\n", (UINT_32) prEventBatchResult->ucScanCount); + + *pu4QueryInfoLen = sizeof(EVENT_BATCH_RESULT_T); + + rCmdBatchReq.ucSeqNum = 2; + rCmdBatchReq.ucCmd = SCAN_BATCH_REQ_RESULT; + rCmdBatchReq.ucMScan = prEventBatchResult->ucScanCount; /* Get which round result */ + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_BATCH_REQ, + FALSE, + TRUE, + TRUE, + nicCmdEventBatchScanResult, + nicOidCmdTimeoutCommon, + sizeof(CMD_BATCH_REQ_T), + (PUINT_8) &rCmdBatchReq, (PVOID) pvQueryBuffer, u4QueryBufferLen); + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. +* \retval WLAN_STATUS_INVALID_LENGTH +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBatchScanReq(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + return batchSetCmd(prAdapter, pvSetBuffer, u4SetBufferLen, pu4SetInfoLen); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryBatchScanResult(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + return batchGetCmd(prAdapter, pvQueryBuffer, u4QueryBufferLen, pu4QueryInfoLen); + +} /* end of wlanoidQueryBatchScanResult() */ + +#endif /* CFG_SUPPORT_BATCH_SCAN */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request starting of schedule scan +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetStartSchedScan(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_SCHED_SCAN_REQUEST prSchedScanRequest; + P_SCAN_INFO_T prScanInfo; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + DEBUGFUNC("wlanoidSetStartSchedScan()"); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(SCN, WARN, "Fail in set scheduled scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pu4SetInfoLen); + *pu4SetInfoLen = 0; + + if (u4SetBufferLen != sizeof(PARAM_SCHED_SCAN_REQUEST)) { + return WLAN_STATUS_INVALID_LENGTH; + } else if (pvSetBuffer == NULL) { + return WLAN_STATUS_INVALID_DATA; + } else if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED && + prAdapter->fgEnOnlineScan == FALSE) { + return WLAN_STATUS_FAILURE; + } + + if (prAdapter->fgIsRadioOff) { + DBGLOG(SCN, WARN, "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + prSchedScanRequest = (P_PARAM_SCHED_SCAN_REQUEST) pvSetBuffer; + + /*if schedScanReq is pending ,save it*/ + kalMemCopy(&prScanInfo->rSchedScanRequest, prSchedScanRequest, sizeof(PARAM_SCHED_SCAN_REQUEST)); + + if (scnFsmSchedScanRequest(prAdapter) == TRUE) + return WLAN_STATUS_SUCCESS; + else + return WLAN_STATUS_FAILURE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request termination of schedule scan +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetStopSchedScan(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + ASSERT(prAdapter); + + /* ask SCN module to stop scan request */ + if (scnFsmSchedScanStopRequest(prAdapter) == TRUE) + return WLAN_STATUS_SUCCESS; + else + return WLAN_STATUS_FAILURE; +} + +#if CFG_SUPPORT_GSCN +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a periodically PSCN action +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetGSCNAction(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_CMD_SET_PSCAN_ENABLE prCmdPscnAction; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(SCN, ERROR, "Adapter not ready: ACPI=%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + if (u4SetBufferLen != sizeof(CMD_SET_PSCAN_ENABLE)) { + DBGLOG(SCN, ERROR, "u4SetBufferLen != sizeof(CMD_SET_PSCAN_ENABLE)\n"); + return WLAN_STATUS_INVALID_LENGTH; + } else if (pvSetBuffer == NULL) { + DBGLOG(SCN, ERROR, "pvSetBuffer == NULL\n"); + return WLAN_STATUS_INVALID_DATA; + } + + if (prAdapter->fgIsRadioOff) { + DBGLOG(SCN, ERROR, "Radio off: ACPI=%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + prCmdPscnAction = (P_CMD_SET_PSCAN_ENABLE) pvSetBuffer; + + if (prCmdPscnAction) { + DBGLOG(SCN, TRACE, "ucPscanAct=[%d]\n", prCmdPscnAction->ucPscanAct); + if (prCmdPscnAction->ucPscanAct == PSCAN_ACT_ENABLE) { + prAdapter->rWifiVar.rScanInfo.fgGScnAction = TRUE; + scnPSCNFsm(prAdapter, PSCN_SCANNING); + } else if (prCmdPscnAction->ucPscanAct == PSCAN_ACT_DISABLE) { + scnCombineParamsIntoPSCN(prAdapter, NULL, NULL, NULL, NULL, FALSE, FALSE, TRUE); + if (prAdapter->rWifiVar.rScanInfo.prPscnParam->fgNLOScnEnable + || prAdapter->rWifiVar.rScanInfo.prPscnParam->fgBatchScnEnable) + scnPSCNFsm(prAdapter, PSCN_RESET); /* in case there is any PSCN */ + else + scnPSCNFsm(prAdapter, PSCN_IDLE); + } + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to configure GScan PARAMs +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetGSCNParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_WIFI_GSCAN_CMD_PARAMS prCmdGscnParam; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(SCN, ERROR, "Adapter not ready: ACPI=%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + if (u4SetBufferLen != sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)) { + DBGLOG(SCN, ERROR, "u4SetBufferLen != sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)\n"); + return WLAN_STATUS_INVALID_LENGTH; + } else if (pvSetBuffer == NULL) { + DBGLOG(SCN, ERROR, "pvSetBuffer == NULL\n"); + return WLAN_STATUS_INVALID_DATA; + } + if (prAdapter->fgIsRadioOff) { + DBGLOG(SCN, ERROR, "Radio off: ACPI=%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + prCmdGscnParam = (P_PARAM_WIFI_GSCAN_CMD_PARAMS) pvSetBuffer; + + DBGLOG(SCN, TRACE, "prCmdGscnParam: base_period[%u], num_buckets[%u] band[%d] num_channels[%u]\n", + prCmdGscnParam->base_period, prCmdGscnParam->num_buckets, + prCmdGscnParam->buckets[0].band, prCmdGscnParam->buckets[0].num_channels); + + if (scnSetGSCNParam(prAdapter, prCmdGscnParam) == TRUE) + return WLAN_STATUS_SUCCESS; + else + return WLAN_STATUS_FAILURE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to configure GScan PARAMs +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetGSCNConfig(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_WIFI_GSCAN_CMD_PARAMS prCmdGscnConfigParam; + CMD_GSCN_SCN_COFIG_T rCmdGscnConfig; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(SCN, ERROR, "Adapter not ready: ACPI=%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + if (u4SetBufferLen != sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)) { + DBGLOG(SCN, ERROR, "u4SetBufferLen != sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)\n"); + return WLAN_STATUS_INVALID_LENGTH; + } else if (pvSetBuffer == NULL) { + DBGLOG(SCN, ERROR, "pvSetBuffer == NULL\n"); + return WLAN_STATUS_INVALID_DATA; + } + if (prAdapter->fgIsRadioOff) { + DBGLOG(SCN, ERROR, "Radio off: ACPI=%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + prCmdGscnConfigParam = (P_PARAM_WIFI_GSCAN_CMD_PARAMS) pvSetBuffer; + kalMemZero(&rCmdGscnConfig, sizeof(CMD_GSCN_SCN_COFIG_T)); + + if (prCmdGscnConfigParam) { + rCmdGscnConfig.u4BufferThreshold = prCmdGscnConfigParam->report_threshold_percent; + rCmdGscnConfig.ucNumApPerScn = prCmdGscnConfigParam->max_ap_per_scan; + rCmdGscnConfig.u4NumScnToCache = prCmdGscnConfigParam->report_threshold_num_scans; + } + DBGLOG(SCN, TRACE, "rCmdGscnScnConfig: threshold_percent[%d] max_ap_per_scan[%d] num_scans[%d]\n", + rCmdGscnConfig.u4BufferThreshold, + rCmdGscnConfig.ucNumApPerScn, rCmdGscnConfig.u4NumScnToCache); + + if (scnSetGSCNConfig(prAdapter, &rCmdGscnConfig) == TRUE) + return WLAN_STATUS_SUCCESS; + else + return WLAN_STATUS_FAILURE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get a GScan result +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidGetGSCNResult(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_WIFI_GSCAN_GET_RESULT_PARAMS prGetGscnScnResultParm; + CMD_GET_GSCAN_RESULT_T rGetGscnScnResultCmd; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(SCN, ERROR, "Adapter not ready: ACPI=%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + if (u4SetBufferLen != sizeof(PARAM_WIFI_GSCAN_GET_RESULT_PARAMS)) { + DBGLOG(SCN, ERROR, "u4SetBufferLen != sizeof(PARAM_WIFI_GSCAN_GET_RESULT_PARAMS))\n"); + return WLAN_STATUS_INVALID_LENGTH; + } else if (pvSetBuffer == NULL) { + DBGLOG(SCN, ERROR, "pvSetBuffer == NULL\n"); + return WLAN_STATUS_INVALID_DATA; + } + + if (prAdapter->fgIsRadioOff) { + DBGLOG(SCN, ERROR, "Radio off: ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + prGetGscnScnResultParm = (P_PARAM_WIFI_GSCAN_GET_RESULT_PARAMS) pvSetBuffer; + kalMemZero(&rGetGscnScnResultCmd, sizeof(CMD_GET_GSCAN_RESULT_T)); + + if (prGetGscnScnResultParm) { + rGetGscnScnResultCmd.u4Num = prGetGscnScnResultParm->get_num; + rGetGscnScnResultCmd.ucFlush = prGetGscnScnResultParm->flush; + rGetGscnScnResultCmd.ucVersion = PSCAN_VERSION; + } + + if (scnFsmGetGSCNResult(prAdapter, &rGetGscnScnResultCmd, pu4SetInfoLen) == TRUE) + return WLAN_STATUS_SUCCESS; + else + return WLAN_STATUS_FAILURE; +} +#endif /* CFG_SUPPORT_GSCN */ + + +#if CFG_SUPPORT_HOTSPOT_2_0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called by HS2.0 to set the assoc info, which is needed to add to +* Association request frame while join HS2.0 AP. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. +* \retval WLAN_STATUS_INVALID_LENGTH +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetHS20Info(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_IE_HS20_INDICATION_T prHS20IndicationIe; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + DEBUGFUNC("wlanoidSetHS20AssocInfo"); + DBGLOG(OID, LOUD, "\r\n"); + + if (u4SetBufferLen == 0) + return WLAN_STATUS_INVALID_LENGTH; + + *pu4SetInfoLen = u4SetBufferLen; + + prHS20IndicationIe = (P_IE_HS20_INDICATION_T) pvSetBuffer; + + prAdapter->prGlueInfo->ucHotspotConfig = prHS20IndicationIe->ucHotspotConfig; + prAdapter->prGlueInfo->fgConnectHS20AP = TRUE; + + DBGLOG(SEC, TRACE, "HS20 IE sz %u\n", u4SetBufferLen); + + return WLAN_STATUS_SUCCESS; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set_bssid_pool +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetHS20BssidPool(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (u4SetBufferLen < sizeof(PARAM_HS20_SET_BSSID_POOL)) { + *pu4SetInfoLen = sizeof(PARAM_HS20_SET_BSSID_POOL); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + rWlanStatus = hs20SetBssidPool(prAdapter, pvSetBuffer, NETWORK_TYPE_AIS_INDEX); + + return rWlanStatus; +} /* end of wlanoidSendHS20GASRequest() */ + +#endif + +#if CFG_SUPPORT_ROAMING_ENC +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the MAC address the NIC is currently using. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetRoamingInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + CMD_ROAMING_INFO_T *prCmdRoamingInfo; + + DEBUGFUNC("wlanoidSetRoamingInfo"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(CMD_ROAMING_INFO_T); + + if (u4SetBufferLen < sizeof(CMD_ROAMING_INFO_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + prCmdRoamingInfo = (CMD_ROAMING_INFO_T *) pvSetBuffer; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_ROAMING_INFO, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ROAMING_INFO_T), (PUINT_8) prCmdRoamingInfo, NULL, 0); +} +#endif /* CFG_SUPPORT_ROAMING_ENC */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set chip +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetChipConfig(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T prChipConfigInfo; + CMD_CHIP_CONFIG_T rCmdChipConfig; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DATA_STRUCT_INSPECTING_ASSERT(sizeof(prChipConfigInfo->aucCmd) == CHIP_CONFIG_RESP_SIZE); + DEBUGFUNC("wlanoidSetChipConfig"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prChipConfigInfo = (P_PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T) pvSetBuffer; + kalMemZero(&rCmdChipConfig, sizeof(rCmdChipConfig)); + + rCmdChipConfig.u2Id = prChipConfigInfo->u2Id; + rCmdChipConfig.ucType = prChipConfigInfo->ucType; + rCmdChipConfig.ucRespType = prChipConfigInfo->ucRespType; + rCmdChipConfig.u2MsgSize = prChipConfigInfo->u2MsgSize; + if (rCmdChipConfig.u2MsgSize > CHIP_CONFIG_RESP_SIZE) { + DBGLOG(OID, INFO, "Chip config Msg Size %u is not valid (set)\n", rCmdChipConfig.u2MsgSize); + rCmdChipConfig.u2MsgSize = CHIP_CONFIG_RESP_SIZE; + } + kalMemCopy(rCmdChipConfig.aucCmd, prChipConfigInfo->aucCmd, rCmdChipConfig.u2MsgSize); + + DBGLOG(OID, TRACE, "rCmdChipConfig.aucCmd=%s\n", rCmdChipConfig.aucCmd); +#if 1 + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_CHIP_CONFIG, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CHIP_CONFIG_T), + (PUINT_8) &rCmdChipConfig, pvSetBuffer, u4SetBufferLen); +#endif + return rWlanStatus; +} /* wlanoidSetChipConfig */ +#if CFG_SUPPORT_P2P_ECSA +WLAN_STATUS +wlanoidSetECSAConfig(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_ECSA_CONFIG_STRUCT_T prCsInfo; + CMD_SET_ECSA_PARAM rCmdCsConfig; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + prCsInfo = (P_PARAM_ECSA_CONFIG_STRUCT_T) pvSetBuffer; + kalMemZero(&rCmdCsConfig, sizeof(rCmdCsConfig)); + + rCmdCsConfig.ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX, + rCmdCsConfig.ucOperatingClass = prCsInfo->op_class; + rCmdCsConfig.ucPrimaryChannel = prCsInfo->channel; + rCmdCsConfig.ucRfSco = prCsInfo->sco; + rCmdCsConfig.ucSwitchMode = prCsInfo->mode; + rCmdCsConfig.ucSwitchTotalCount = prCsInfo->count; + + DBGLOG(OID, INFO, "index:op_class:channel:sco:mode:count %d:%d:%d:%d:%d:%d\n", + rCmdCsConfig.ucNetTypeIndex, + rCmdCsConfig.ucOperatingClass, + rCmdCsConfig.ucPrimaryChannel, + rCmdCsConfig.ucRfSco, + rCmdCsConfig.ucSwitchMode, + rCmdCsConfig.ucSwitchTotalCount); + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_ECSA_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CHIP_CONFIG_T), + (PUINT_8)&rCmdCsConfig, + pvSetBuffer, u4SetBufferLen); + return rWlanStatus; +} +#endif +WLAN_STATUS +wlanoidSetWfdDebugMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_CMD_WFD_DEBUG_MODE_INFO_T prCmdWfdDebugModeInfo; + + DEBUGFUNC("wlanoidSetWFDDebugMode"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(CMD_WFD_DEBUG_MODE_INFO_T); + + if (u4SetBufferLen < sizeof(CMD_WFD_DEBUG_MODE_INFO_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + prCmdWfdDebugModeInfo = (CMD_WFD_DEBUG_MODE_INFO_T *) pvSetBuffer; + + DBGLOG(OID, INFO, "New WFD Debug: %d mode and period=0x%x\n", prCmdWfdDebugModeInfo->ucDebugMode, + prCmdWfdDebugModeInfo->u2PeriodInteval); + + prAdapter->rWifiVar.prP2pFsmInfo->rWfdDebugSetting.ucWfdDebugMode = (UINT_8) prCmdWfdDebugModeInfo->ucDebugMode; + prAdapter->rWifiVar.prP2pFsmInfo->rWfdDebugSetting.u2WfdSNShowPeiroid = + (UINT_16) prCmdWfdDebugModeInfo->u2PeriodInteval; + + return WLAN_STATUS_SUCCESS; +} /*wlanoidSetWfdDebugMode */ + + +#if (CFG_SUPPORT_TXR_ENC == 1) +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the MAC address the NIC is currently using. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetTxRateInfo( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + CMD_RLM_INFO_T *prCmdTxRInfo; + + DEBUGFUNC("wlanoidSetTxRateInfo"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(CMD_RLM_INFO_T); + + if (u4SetBufferLen < sizeof(CMD_RLM_INFO_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + prCmdTxRInfo = (CMD_RLM_INFO_T *)pvSetBuffer; + + DBGLOG(OID, INFO, " command = %u %u %u %u %d %u %u\n", + prCmdTxRInfo->u4Version, + prCmdTxRInfo->fgIsErrRatioEnhanceApplied, + prCmdTxRInfo->ucErrRatio2LimitMinRate, + prCmdTxRInfo->ucMinLegacyRateIdx, + prCmdTxRInfo->cMinRssiThreshold, + prCmdTxRInfo->fgIsRtsApplied, + prCmdTxRInfo->ucRecoverTime)); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_TX_AR_ERR_CONFIG, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_RLM_INFO_T), + (PUINT_8)prCmdTxRInfo, + NULL, + 0 + ); +} +#endif /* CFG_SUPPORT_TXR_ENC */ + + +WLAN_STATUS +wlanoidSetAlwaysScan( +IN P_ADAPTER_T prAdapter, +IN PVOID pvSetBuffer, +IN UINT_32 u4SetBufferLen, +OUT PUINT_32 pu4SetInfoLen +) +{ + WLAN_STATUS rStatus; + UINT_8 u8AlwaysScan; + + DEBUGFUNC("wlanoidSetAlwaysScan"); + + if (!prAdapter || !pvSetBuffer) + return WLAN_STATUS_INVALID_DATA; + + u8AlwaysScan = *(PUINT_8)pvSetBuffer - '0'; + + if ((u8AlwaysScan != 0) && (u8AlwaysScan != 1)) + return WLAN_STATUS_INVALID_DATA; + + rStatus = wlanSendSetQueryCmd( + prAdapter, /* prAdapter */ + CMD_ID_SET_ALWAYS_SCAN_PARAM,/* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + TRUE, /* fgIsOid */ + nicCmdEventSetCommon, /* pfCmdDoneHandler*/ + nicOidCmdTimeoutCommon, /* pfCmdTimeoutHandler */ + sizeof(u8AlwaysScan), /* u4SetQueryInfoLen */ + (PUINT_8)&u8AlwaysScan, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + DBGLOG(OID, INFO, "u8AlwaysScan %d rStatus %x\n", u8AlwaysScan, rStatus); + + ASSERT(rStatus == WLAN_STATUS_PENDING); + + return rStatus; + +} + +#if CFG_SUPPORT_OSHARE +WLAN_STATUS +wlanoidSetOshareMode( +IN P_ADAPTER_T prAdapter, +IN PVOID pvSetBuffer, +IN UINT_32 u4SetBufferLen, +OUT PUINT_32 pu4SetInfoLen +) +{ + if (!prAdapter || !pvSetBuffer) + return WLAN_STATUS_INVALID_DATA; + + DBGLOG(OID, TRACE, "wlanoidSetOshareMode\n"); + + return wlanSendSetQueryCmd( + prAdapter,/* prAdapter */ + CMD_ID_SET_OSHARE_MODE,/* ucCID */ + TRUE,/* fgSetQuery */ + FALSE,/* fgNeedResp */ + TRUE,/* fgIsOid */ + nicCmdEventSetCommon,/* pfCmdDoneHandler*/ + nicOidCmdTimeoutCommon,/* pfCmdTimeoutHandler */ + u4SetBufferLen,/* u4SetQueryInfoLen */ + (PUINT_8) pvSetBuffer,/* pucInfoBuffer */ + NULL,/* pvSetQueryBuffer */ + 0/* u4SetQueryBufferLen */ + ); +} +#endif + +WLAN_STATUS +wlanoidNotifyFwSuspend(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WIFI_SYSTEM_SUSPEND_CMD_T rSuspendCmd; + + if (!prAdapter || !pvSetBuffer) + return WLAN_STATUS_INVALID_DATA; + + rSuspendCmd.fgIsSystemSuspend = *(PBOOLEAN)pvSetBuffer; + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_SYSTEM_SUSPEND, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(BOOLEAN), + (PUINT_8)&rSuspendCmd, + NULL, + 0); +} + +#if CFG_SUPPORT_TDLS +WLAN_STATUS +wlanoidDisableTdlsPs(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + struct CMD_TDLS_PS_T rTdlsPs; + + if (!prAdapter || !pvSetBuffer) + return WLAN_STATUS_INVALID_DATA; + + rTdlsPs.ucIsEnablePs = *(PUINT_8)pvSetBuffer - '0'; + DBGLOG(OID, INFO, "enable tdls ps %d\n", rTdlsPs.ucIsEnablePs); + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_TDLS_PS, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(rTdlsPs), + (PUINT_8)&rTdlsPs, + NULL, + 0); +} +#endif + +WLAN_STATUS +wlanoidPacketKeepAlive(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_PARAM_PACKET_KEEPALIVE_T prPacket; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(PARAM_PACKET_KEEPALIVE_T); + + /* Check for query buffer length */ + if (u4SetBufferLen < *pu4SetInfoLen) { + DBGLOG(OID, WARN, "Too short length %u\n", u4SetBufferLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + prPacket = (P_PARAM_PACKET_KEEPALIVE_T)kalMemAlloc(sizeof(PARAM_PACKET_KEEPALIVE_T), VIR_MEM_TYPE); + if (!prPacket) { + DBGLOG(OID, ERROR, "Can not alloc memory for PARAM_PACKET_KEEPALIVE_T\n"); + return -ENOMEM; + } + kalMemCopy(prPacket, pvSetBuffer, sizeof(PARAM_PACKET_KEEPALIVE_T)); + + DBGLOG(OID, INFO, "enable=%d, index=%d\r\n", prPacket->enable, prPacket->index); + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_WFC_KEEP_ALIVE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(PARAM_PACKET_KEEPALIVE_T), (PUINT_8)prPacket, NULL, 0); + kalMemFree(prPacket, VIR_MEM_TYPE, sizeof(PARAM_PACKET_KEEPALIVE_T)); + return rStatus; +} + +#ifdef FW_CFG_SUPPORT +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query fw cfg info +* +* \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_PENDING +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanoidQueryCfgRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + struct _CMD_HEADER_T *prCmdV1Header = (struct _CMD_HEADER_T *)pvQueryBuffer; + struct _CMD_HEADER_T cmdV1Header; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct _CMD_HEADER_T); + + if (u4QueryBufferLen < sizeof(struct _CMD_HEADER_T)) + return WLAN_STATUS_INVALID_LENGTH; + + kalMemCopy(&cmdV1Header, prCmdV1Header, sizeof(struct _CMD_HEADER_T)); + rStatus = wlanSendSetQueryCmd( + prAdapter, + CMD_ID_GET_SET_CUSTOMER_CFG, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryCfgRead, + nicCmdTimeoutCommon, + sizeof(struct _CMD_HEADER_T), + (PUINT_8) &cmdV1Header, + pvQueryBuffer, + u4QueryBufferLen); + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set fw cfg info + * + * \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_INVALID_DATA + * \retval WLAN_STATUS_SUCCESS + */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanoidSetFwParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + ASSERT(prAdapter); + + if (!pvSetBuffer || !u4SetBufferLen) { + DBGLOG(OID, ERROR, "Buffer is NULL\n"); + return WLAN_STATUS_INVALID_DATA; + } + DBGLOG(OID, INFO, "Fw Params: %s\n", (PUINT_8)pvSetBuffer); + return wlanFwCfgParse(prAdapter, (PUINT_8)pvSetBuffer); +} +#endif + +WLAN_STATUS +wlanoidSetDrvRoamingPolicy(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + UINT_32 u4RoamingPoily; + P_ROAMING_INFO_T prRoamingFsmInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + UINT_32 u4CurConPolicy; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + + u4RoamingPoily = *(PUINT_32)pvSetBuffer; + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + prConnSettings = (P_CONNECTION_SETTINGS_T) &prAdapter->rWifiVar.rConnSettings; + u4CurConPolicy = prConnSettings->eConnectionPolicy; + + if (u4RoamingPoily == 1) { + if (((prAdapter->rWifiVar.rAisFsmInfo.eCurrentState == AIS_STATE_NORMAL_TR) + || (prAdapter->rWifiVar.rAisFsmInfo.eCurrentState == AIS_STATE_ONLINE_SCAN)) + && (prRoamingFsmInfo->eCurrentState == ROAMING_STATE_IDLE)) + roamingFsmRunEventStart(prAdapter); + + /*Change Connect by any , avoid to connect by BSSID on roaming or beacon timeout!*/ + prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_ANY; + + } else { + if (prRoamingFsmInfo->eCurrentState != ROAMING_STATE_IDLE) + roamingFsmRunEventAbort(prAdapter); + } + prRoamingFsmInfo->DrvRoamingAllow = u4RoamingPoily; + + DBGLOG(REQ, INFO, "wlanoidSetDrvRoamingPolicy, RoamingPoily= %d, conn policy= [%d] -> [%d]\n" + , u4RoamingPoily, u4CurConPolicy, prRoamingFsmInfo->DrvRoamingAllow); + + return WLAN_STATUS_SUCCESS; +} +#if CFG_SUPPORT_EMI_DEBUG +WLAN_STATUS +wlanoidSetEnableDumpEMILog(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_CMD_DRIVER_DUMP_EMI_LOG_T pDriverDumpEMI; + + if (!prAdapter || !pvSetBuffer) + return WLAN_STATUS_INVALID_DATA; + + pDriverDumpEMI = (P_CMD_DRIVER_DUMP_EMI_LOG_T)pvSetBuffer; + DBGLOG(OID, TRACE, "%s: enable:0x%x", __func__, + pDriverDumpEMI->fgIsDriverDumpEmiLogEnable); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_DRIVER_DUMP_EMI_LOG, + TRUE, + FALSE, + FALSE, + NULL, + nicOidCmdTimeoutCommon, + sizeof(CMD_DRIVER_DUMP_EMI_LOG_T), + (PUINT_8)pDriverDumpEMI, + NULL, + 0); + return WLAN_STATUS_SUCCESS; +} +#endif + +WLAN_STATUS +wlanoidUpdateFtIes(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, + PUINT_32 pu4SetInfoLen) +{ + struct FT_IES *prFtIes = NULL; + UINT_32 u4IeLen = 0; + PUINT_8 pucIEStart = NULL; + struct cfg80211_update_ft_ies_params *ftie = NULL; + P_STA_RECORD_T prStaRec = NULL; + struct MSG_SAA_FT_CONTINUE *prFtContinueMsg = NULL; + + if (!pvSetBuffer || u4SetBufferLen == 0) { + DBGLOG(OID, ERROR, "pvSetBuffer is Null %d, Buffer Len %u\n", !pvSetBuffer, u4SetBufferLen); + return WLAN_STATUS_INVALID_DATA; + } + prStaRec = prAdapter->rWifiVar.rAisFsmInfo.prTargetStaRec; + ftie = (struct cfg80211_update_ft_ies_params *)pvSetBuffer; + prFtIes = &prAdapter->prGlueInfo->rFtIeForTx; + if (ftie->ie_len == 0) { + DBGLOG(OID, WARN, "FT Ies length is 0\n"); + return WLAN_STATUS_SUCCESS; + } + if (prFtIes->u4IeLength != ftie->ie_len) { + kalMemFree(prFtIes->pucIEBuf, VIR_MEM_TYPE, prFtIes->u4IeLength); + prFtIes->pucIEBuf = kalMemAlloc(ftie->ie_len, VIR_MEM_TYPE); + prFtIes->u4IeLength = ftie->ie_len; + } + + if (!prFtIes->pucIEBuf) { + DBGLOG(OID, ERROR, "FT: memory allocation failed\n"); + return WLAN_STATUS_FAILURE; + } + + pucIEStart = prFtIes->pucIEBuf; + u4IeLen = prFtIes->u4IeLength; + prFtIes->u2MDID = ftie->md; + prFtIes->prFTIE = NULL; + prFtIes->prMDIE = NULL; + prFtIes->prRsnIE = NULL; + prFtIes->prTIE = NULL; + if (u4IeLen) + kalMemCopy(pucIEStart, ftie->ie, u4IeLen); + while (u4IeLen >= 2) { + UINT_32 u4InfoElemLen = IE_SIZE(pucIEStart); + + if (u4InfoElemLen > u4IeLen) + break; + switch (pucIEStart[0]) { + case ELEM_ID_MOBILITY_DOMAIN: + prFtIes->prMDIE = (struct IE_MOBILITY_DOMAIN_T *)pucIEStart; + break; + case ELEM_ID_FAST_TRANSITION: + prFtIes->prFTIE = (struct IE_FAST_TRANSITION_T *)pucIEStart; + break; + case ELEM_ID_RESOURCE_INFO_CONTAINER: + break; + case ELEM_ID_TIMEOUT_INTERVAL: + prFtIes->prTIE = (IE_TIMEOUT_INTERVAL_T *)pucIEStart; + break; + case ELEM_ID_RSN: + prFtIes->prRsnIE = (P_RSN_INFO_ELEM_T)pucIEStart; + break; + } + u4IeLen -= u4InfoElemLen; + pucIEStart += u4InfoElemLen; + } + DBGLOG(OID, INFO, "MdId %d IesLen %u, MDIE %d FTIE %d RSN %d TIE %d\n", ftie->md, prFtIes->u4IeLength, + !!prFtIes->prMDIE, !!prFtIes->prFTIE, !!prFtIes->prRsnIE, !!prFtIes->prTIE); + /* check if SAA is waiting to send Reassoc req */ + if (!prStaRec || prStaRec->ucAuthTranNum != AUTH_TRANSACTION_SEQ_2 || + !prStaRec->fgIsReAssoc || prStaRec->ucStaState != STA_STATE_1) + return WLAN_STATUS_SUCCESS; + + prFtContinueMsg = (struct MSG_SAA_FT_CONTINUE *) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_SAA_FT_CONTINUE)); + if (!prFtContinueMsg) { + DBGLOG(OID, WARN, "failed to allocate Join Req Msg\n"); + return WLAN_STATUS_FAILURE; + } + prFtContinueMsg->rMsgHdr.eMsgId = MID_OID_SAA_FSM_CONTINUE; + prFtContinueMsg->prStaRec = prStaRec; + /* ToDo: for Resource Request Protocol, we need to check if RIC request is included. */ + if (prFtIes->prMDIE && (prFtIes->prMDIE->ucBitMap & BIT(1))) + prFtContinueMsg->fgFTRicRequest = TRUE; + else + prFtContinueMsg->fgFTRicRequest = FALSE; + DBGLOG(OID, INFO, "continue to do auth/assoc, Ft Request %d\n", prFtContinueMsg->fgFTRicRequest); + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prFtContinueMsg, MSG_SEND_METHOD_BUF); + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidSendNeighborRequest(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, + PUINT_32 pu4SetInfoLen) +{ + struct SUB_ELEMENT_LIST *prSSIDIE = NULL; + P_BSS_INFO_T prAisBssInfo = NULL; + UINT_8 ucSSIDIELen = 0; + PUINT_8 pucSSID = (PUINT_8)pvSetBuffer; + + if (!prAdapter) + return WLAN_STATUS_INVALID_DATA; + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + if (prAisBssInfo->eConnectionState != PARAM_MEDIA_STATE_CONNECTED) { + DBGLOG(OID, ERROR, "didn't connected any Access Point\n"); + return WLAN_STATUS_FAILURE; + } + if (u4SetBufferLen == 0 || !pucSSID) { + rlmTxNeighborReportRequest(prAdapter, prAisBssInfo->prStaRecOfAP, NULL); + return WLAN_STATUS_SUCCESS; + } + + ucSSIDIELen = (UINT_8)(u4SetBufferLen + sizeof(*prSSIDIE)); + prSSIDIE = kalMemAlloc(ucSSIDIELen, PHY_MEM_TYPE); + if (!prSSIDIE) { + DBGLOG(OID, ERROR, "No Memory\n"); + return WLAN_STATUS_FAILURE; + } + prSSIDIE->prNext = NULL; + prSSIDIE->rSubIE.ucSubID = ELEM_ID_SSID; + prSSIDIE->rSubIE.ucLength = (UINT_8)u4SetBufferLen; + kalMemCopy(&prSSIDIE->rSubIE.aucOptInfo[0], pucSSID, (UINT_8)u4SetBufferLen); + DBGLOG(OID, INFO, "Send Neighbor Request, SSID=%s\n", HIDE(pucSSID)); + rlmTxNeighborReportRequest(prAdapter, prAisBssInfo->prStaRecOfAP, prSSIDIE); + kalMemFree(prSSIDIE, PHY_MEM_TYPE, ucSSIDIELen); + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidSync11kCapbilities(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, + PUINT_32 pu4SetInfoLen) +{ + struct CMD_SET_RRM_CAPABILITY rCmdRrmCapa; + + kalMemZero(&rCmdRrmCapa, sizeof(rCmdRrmCapa)); + rCmdRrmCapa.ucDot11RadioMeasurementEnabled = 1; + rlmFillRrmCapa(&rCmdRrmCapa.aucCapabilities[0]); + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RRM_CAPABILITY, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_SET_RRM_CAPABILITY), + (PUINT_8)&rCmdRrmCapa, pvSetBuffer, u4SetBufferLen); +} + +WLAN_STATUS +wlanoidSendBTMQuery(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, + PUINT_32 pu4SetInfoLen) +{ + P_STA_RECORD_T prStaRec = prAdapter->rWifiVar.rAisFsmInfo.prTargetStaRec; + struct BSS_TRANSITION_MGT_PARAM_T *prBtmMgt = NULL; + + if (prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].eConnectionState != + PARAM_MEDIA_STATE_CONNECTED || !prStaRec) { + DBGLOG(OID, INFO, "Didn't Connect, Target StaRec is NULL %d\n", !prStaRec); + return WLAN_STATUS_FAILURE; + } + if (!prStaRec->fgSupportBTM) { + DBGLOG(OID, INFO, "Target BSS didn't support Bss Transition Management\n"); + return WLAN_STATUS_FAILURE; + } + prBtmMgt = &prAdapter->rWifiVar.rAisSpecificBssInfo.rBTMParam; + prBtmMgt->ucDialogToken = wnmGetBtmToken(); + prBtmMgt->ucQueryReason = pvSetBuffer ? (*(PUINT_8)pvSetBuffer - '0'):BSS_TRANSITION_LOW_RSSI; + DBGLOG(OID, INFO, "Send BssTransitionManagementQuery, Reason %d\n", prBtmMgt->ucQueryReason); + wnmSendBTMQueryFrame(prAdapter, prStaRec); + return WLAN_STATUS_SUCCESS; +} + +/* + * This func is mainly from bionic's strtok.c + */ +static CHAR *strtok_r(CHAR *s, const CHAR *delim, CHAR **last) +{ + char *spanp; + int c, sc; + char *tok; + + + if (s == NULL) { + s = *last; + if (s == 0) + return NULL; + } +cont: + c = *s++; + for (spanp = (char *)delim; (sc = *spanp++) != 0;) { + if (c == sc) + goto cont; + } + + if (c == 0) { /* no non-delimiter characters */ + *last = NULL; + return NULL; + } + tok = s - 1; + + for (;;) { + c = *s++; + spanp = (char *)delim; + do { + sc = *spanp++; + if (sc == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + *last = s; + return tok; + } + } while (sc != 0); + } +} + +WLAN_STATUS wlanoidTspecOperation(P_ADAPTER_T prAdapter, PVOID pvBuffer, UINT_32 u4BufferLen, + PUINT_32 pu4InfoLen) +{ + P_PARAM_QOS_TSPEC prTspecParam = NULL; + struct MSG_TS_OPERATE *prMsgTsOperate = NULL; + PUINT_8 pucCmd = (PUINT_8)pvBuffer; + PUINT_8 pucSavedPtr = NULL; + PUINT_8 pucItem = NULL; + UINT_32 u4Ret = 1; + UINT_8 ucApsdSetting = 2; /* 0: legacy; 1: u-apsd; 2: not set yet */ + enum TSPEC_OP_CODE eTsOp; + +#if !CFG_SUPPORT_WMM_AC + DBGLOG(OID, INFO, "WMM AC is not supported\n"); + return WLAN_STATUS_FAILURE; +#endif + if (kalStrniCmp(pucCmd, "dumpts", 6) == 0) { + *pu4InfoLen = kalSnprintf(pucCmd, u4BufferLen, "%s", "\nAll Active Tspecs:\n"); + u4BufferLen -= *pu4InfoLen; + pucCmd += *pu4InfoLen; + *pu4InfoLen += wmmDumpActiveTspecs(prAdapter, pucCmd, u4BufferLen); + return WLAN_STATUS_SUCCESS; + } + + if (kalStrniCmp(pucCmd, "addts", 5) == 0) + eTsOp = TX_ADDTS_REQ; + else if (kalStrniCmp(pucCmd, "delts", 5) == 0) + eTsOp = TX_DELTS_REQ; + else { + DBGLOG(OID, INFO, "wrong operation %s\n", pucCmd); + return WLAN_STATUS_FAILURE; + } + /* addts token n,tid n,dir n,psb n,up n,fixed n,size n,maxsize n,maxsrvint n, minsrvint n, + ** inact n, suspension n, srvstarttime n, minrate n,meanrate n,peakrate n,burst n,delaybound n, + ** phyrate n,SBA n,mediumtime n + */ + prMsgTsOperate = (struct MSG_TS_OPERATE *)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(struct MSG_TS_OPERATE)); + if (!prMsgTsOperate) + return WLAN_STATUS_FAILURE; + + kalMemZero(prMsgTsOperate, sizeof(struct MSG_TS_OPERATE)); + prMsgTsOperate->rMsgHdr.eMsgId = MID_OID_WMM_TSPEC_OPERATE; + prMsgTsOperate->eOpCode = eTsOp; + prTspecParam = &prMsgTsOperate->rTspecParam; + pucCmd += 6; + pucItem = (PUINT_8)strtok_r((CHAR *)pucCmd, ",", (CHAR **)&pucSavedPtr); + while (pucItem) { + if (kalStrniCmp(pucItem, "token ", 6) == 0) + u4Ret = kstrtou8(pucItem+6, 0, &prTspecParam->ucDialogToken); + else if (kalStrniCmp(pucItem, "tid ", 4) == 0) { + u4Ret = kstrtou8(pucItem+4, 0, &prMsgTsOperate->ucTid); + prTspecParam->rTsInfo.ucTid = prMsgTsOperate->ucTid; + } else if (kalStrniCmp(pucItem, "dir ", 4) == 0) + u4Ret = kstrtou8(pucItem+4, 0, &prTspecParam->rTsInfo.ucDirection); + else if (kalStrniCmp(pucItem, "psb ", 4) == 0) + u4Ret = kstrtou8(pucItem+4, 0, &ucApsdSetting); + else if (kalStrniCmp(pucItem, "up ", 3) == 0) + u4Ret = kstrtou8(pucItem+3, 0, &prTspecParam->rTsInfo.ucuserPriority); + else if (kalStrniCmp(pucItem, "size ", 5) == 0) { + UINT_16 u2Size = 0; + + u4Ret = kstrtou16(pucItem+5, 0, &u2Size); + prTspecParam->u2NominalMSDUSize |= u2Size; + } else if (kalStrniCmp(pucItem, "fixed ", 6) == 0) { + UINT_8 ucFixed = 0; + + u4Ret = kstrtou8(pucItem+6, 0, &ucFixed); + if (ucFixed) + prTspecParam->u2NominalMSDUSize |= BIT(15); + } else if (kalStrniCmp(pucItem, "maxsize ", 8) == 0) + u4Ret = kstrtou16(pucItem+8, 0, &prTspecParam->u2MaxMSDUsize); + else if (kalStrniCmp(pucItem, "maxsrvint ", 10) == 0) + u4Ret = kalkStrtou32(pucItem+10, 0, &prTspecParam->u4MaxSvcIntv); + else if (kalStrniCmp(pucItem, "minsrvint ", 10) == 0) + u4Ret = kalkStrtou32(pucItem+10, 0, &prTspecParam->u4MinSvcIntv); + else if (kalStrniCmp(pucItem, "inact ", 6) == 0) + u4Ret = kalkStrtou32(pucItem+6, 0, &prTspecParam->u4InactIntv); + else if (kalStrniCmp(pucItem, "suspension ", 11) == 0) + u4Ret = kalkStrtou32(pucItem+11, 0, &prTspecParam->u4SpsIntv); + else if (kalStrniCmp(pucItem, "srvstarttime ", 13) == 0) + u4Ret = kalkStrtou32(pucItem+13, 0, &prTspecParam->u4SvcStartTime); + else if (kalStrniCmp(pucItem, "minrate ", 8) == 0) + u4Ret = kalkStrtou32(pucItem+8, 0, &prTspecParam->u4MinDataRate); + else if (kalStrniCmp(pucItem, "meanrate ", 9) == 0) + u4Ret = kalkStrtou32(pucItem+9, 0, &prTspecParam->u4MeanDataRate); + else if (kalStrniCmp(pucItem, "peakrate ", 9) == 0) + u4Ret = kalkStrtou32(pucItem+9, 0, &prTspecParam->u4PeakDataRate); + else if (kalStrniCmp(pucItem, "burst ", 6) == 0) + u4Ret = kalkStrtou32(pucItem+6, 0, &prTspecParam->u4MaxBurstSize); + else if (kalStrniCmp(pucItem, "delaybound ", 11) == 0) + u4Ret = kalkStrtou32(pucItem+11, 0, &prTspecParam->u4DelayBound); + else if (kalStrniCmp(pucItem, "phyrate ", 8) == 0) + u4Ret = kalkStrtou32(pucItem+8, 0, &prTspecParam->u4MinPHYRate); + else if (kalStrniCmp(pucItem, "sba ", 4) == 0) + u4Ret = wlanDecimalStr2Hexadecimals(pucItem+4, &prTspecParam->u2Sba); + else if (kalStrniCmp(pucItem, "mediumtime ", 11) == 0) + u4Ret = kstrtou16(pucItem+11, 0, &prTspecParam->u2MediumTime); + + if (u4Ret) { + DBGLOG(OID, ERROR, "Parse %s error\n", pucItem); + cnmMemFree(prAdapter, prMsgTsOperate); + return WLAN_STATUS_FAILURE; + } + pucItem = (PUINT_8)strtok_r(NULL, ",", (CHAR **)&pucSavedPtr); + } + /* if APSD is not set in addts request, use global wmmps settings */ + if (ucApsdSetting == 2) { + P_PM_PROFILE_SETUP_INFO_T prPmProf = + &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].rPmProfSetupInfo; + ENUM_ACI_T eAc = aucUp2ACIMap[prTspecParam->rTsInfo.ucuserPriority]; + + switch (prTspecParam->rTsInfo.ucDirection) { + case UPLINK_TS: /* UpLink*/ + if (prPmProf->ucBmpTriggerAC & BIT(eAc)) + prTspecParam->rTsInfo.ucApsd = 1; + break; + case DOWNLINK_TS:/* DownLink */ + if (prPmProf->ucBmpDeliveryAC & BIT(eAc)) + prTspecParam->rTsInfo.ucApsd = 1; + break; + case BI_DIR_TS: /* Bi-directional */ + if ((prPmProf->ucBmpTriggerAC & BIT(eAc)) && + (prPmProf->ucBmpDeliveryAC & BIT(eAc))) + prTspecParam->rTsInfo.ucApsd = 1; + break; + } + } else + prTspecParam->rTsInfo.ucApsd = ucApsdSetting; + *(--pucCmd) = 0; + pucCmd -= 5; + DBGLOG(OID, INFO, "%s %d %d %d %d %d %d %d %u %u %u %u %u %u %u %u %u %u %u 0x%04x %d\n", pucCmd, + prTspecParam->ucDialogToken, prTspecParam->rTsInfo.ucTid, prTspecParam->rTsInfo.ucDirection, + prTspecParam->rTsInfo.ucApsd, prTspecParam->rTsInfo.ucuserPriority, prTspecParam->u2NominalMSDUSize, + prTspecParam->u2MaxMSDUsize, prTspecParam->u4MaxSvcIntv, prTspecParam->u4MinSvcIntv, + prTspecParam->u4InactIntv, prTspecParam->u4SpsIntv, prTspecParam->u4SvcStartTime, + prTspecParam->u4MinDataRate, prTspecParam->u4MeanDataRate, prTspecParam->u4PeakDataRate, + prTspecParam->u4MaxBurstSize, prTspecParam->u4DelayBound, prTspecParam->u4MinPHYRate, + prTspecParam->u2Sba, prTspecParam->u2MediumTime); + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T)prMsgTsOperate, MSG_SEND_METHOD_BUF); + return WLAN_STATUS_SUCCESS; +} +#if CFG_SUPPORT_FCC_POWER_BACK_OFF +WLAN_STATUS +wlanoidSetFccCert(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + P_CMD_FCC_TX_PWR_ADJUST prFccTxPwrAdjust = (P_CMD_FCC_TX_PWR_ADJUST)pvSetBuffer; + + if (!pvSetBuffer || u4SetBufferLen != sizeof(CMD_FCC_TX_PWR_ADJUST)) + return WLAN_STATUS_INVALID_DATA; + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_FCC_TX_PWR_CERT, + TRUE, + FALSE, + TRUE, + NULL, + NULL, + sizeof(CMD_FCC_TX_PWR_ADJUST), + (PUINT_8) (prFccTxPwrAdjust), + NULL, + 0); + } +#endif + +/* It's a Integretion Test function for RadioMeasurement. If you found errors during doing Radio Measurement, +** you can run this IT function with iwpriv wlan0 set_str_cmd \"31 RM-IT xx,xx,xx, xx\" +** xx,xx,xx,xx is the RM request frame data +*/ +WLAN_STATUS +wlanoidRadioMeasurementIT(P_ADAPTER_T prAdapter, PVOID pvBuffer, UINT_32 u4BufferLen, + PUINT_32 pu4InfoLen) +{ + SW_RFB_T rSwRfb; + UINT_8 aucPacket[200] = {0,}; + PUINT_8 pucSavedPtr = NULL; + PUINT_8 pucItem = NULL; + UINT_8 j = 0; + INT_8 i = 0; + UINT_8 ucByte; + + if (!pvBuffer) { + DBGLOG(OID, ERROR, "pvBuffer is NULL\n"); + return WLAN_STATUS_FAILURE; + } + + pucItem = strtok_r((CHAR *)pvBuffer, ",", (CHAR **)&pucSavedPtr); + while (pucItem) { + ucByte = *pucItem; + i = 0; + while (ucByte) { + if (i > 1) { + DBGLOG(OID, ERROR, "more than 2 char for one byte\n"); + return WLAN_STATUS_FAILURE; + } else if (i == 1) + aucPacket[j] <<= 4; + if (ucByte >= '0' && ucByte <= '9') + aucPacket[j] |= ucByte - '0'; + else if (ucByte >= 'a' && ucByte <= 'f') + aucPacket[j] |= ucByte - 'a' + 10; + else if (ucByte >= 'A' && ucByte <= 'F') + aucPacket[j] |= ucByte - 'A' + 10; + else { + DBGLOG(OID, ERROR, "not a hex char %c\n", ucByte); + return WLAN_STATUS_FAILURE; + } + ucByte = *(++pucItem); + i++; + } + j++; + pucItem = strtok_r(NULL, ",", (CHAR **)&pucSavedPtr); + } + DBGLOG(OID, INFO, "Dump RadioMeasurement IT packet, len %d\n", j); + dumpMemory8(aucPacket, j); + if (j < WLAN_MAC_MGMT_HEADER_LEN) { + DBGLOG(OID, ERROR, "packet length %d less than mac header 24\n", j); + return WLAN_STATUS_FAILURE; + } + rSwRfb.pvHeader = (PVOID)&aucPacket[0]; + rSwRfb.u2PacketLen = j; + rSwRfb.u2HeaderLen = WLAN_MAC_MGMT_HEADER_LEN; + rlmProcessRadioMeasurementRequest(prAdapter, &rSwRfb); + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidDumpUapsdSetting(P_ADAPTER_T prAdapter, PVOID pvBuffer, UINT_32 u4BufferLen, + PUINT_32 pu4InfoLen) +{ + PUINT_8 pucCmd = (PUINT_8)pvBuffer; + UINT_8 ucFinalSetting = 0; + UINT_8 ucStaticSetting = 0; + P_PM_PROFILE_SETUP_INFO_T prPmProf = NULL; + + if (!pvBuffer) { + DBGLOG(OID, ERROR, "pvBuffer is NULL\n"); + return WLAN_STATUS_FAILURE; + } + prPmProf = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].rPmProfSetupInfo; + ucStaticSetting = (prPmProf->ucBmpDeliveryAC << 4) | prPmProf->ucBmpTriggerAC; + ucFinalSetting = wmmCalculateUapsdSetting(prAdapter); + *pu4InfoLen = kalSnprintf(pucCmd, u4BufferLen, + "\nStatic Uapsd Setting:0x%02x\nFinal Uapsd Setting:0x%02x", ucStaticSetting, ucFinalSetting); + return WLAN_STATUS_SUCCESS; +} +#if CFG_SUPPORT_NCHO +#define FW_CFG_KEY_NCHO_ENABLE "NCHOEnable" +#define FW_CFG_KEY_NCHO_ROAM_RCPI "RoamingRCPIValue" +#define FW_CFG_KEY_NCHO_SCN_CHANNEL_TIME "NCHOScnChannelTime" +#define FW_CFG_KEY_NCHO_SCN_HOME_TIME "NCHOScnHomeTime" +#define FW_CFG_KEY_NCHO_SCN_HOME_AWAY_TIME "NCHOScnHomeAwayTime" +#define FW_CFG_KEY_NCHO_SCN_NPROBES "NCHOScnNumProbs" +#define FW_CFG_KEY_NCHO_WES_MODE "NCHOWesMode" +#define FW_CFG_KEY_NCHO_SCAN_DFS_MODE "NCHOScnDfsMode" + +WLAN_STATUS +wlanoidSetNchoHeader(struct _CMD_HEADER_T *prCmdHeader, + struct _CMD_FORMAT_V1_T *pr_cmd_v1, + char *pStr, UINT_32 u4Len) +{ + prCmdHeader->cmdVersion = CMD_VER_1_EXT; + prCmdHeader->cmdType = CMD_TYPE_QUERY; + prCmdHeader->itemNum = 1; + prCmdHeader->cmdBufferLen = sizeof(struct _CMD_FORMAT_V1_T); + kalMemSet(prCmdHeader->buffer, 0, MAX_CMD_BUFFER_LENGTH); + + if (!prCmdHeader || !pStr || u4Len == 0) + return WLAN_STATUS_FAILURE; + + pr_cmd_v1->itemStringLength = u4Len; + kalMemCopy(pr_cmd_v1->itemString, pStr, u4Len); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidSetNchoRoamTrigger(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) { + PINT_32 pi4Param = NULL; + char acCmd[NCHO_CMD_MAX_LENGTH] = {0}; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoRoamTrigger"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(INT_32); + + if (u4SetBufferLen < sizeof(INT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + pi4Param = (PINT_32) pvSetBuffer; + *pi4Param = dBm_TO_RCPI(*pi4Param); /* DB to RCPI */ + if (*pi4Param < RCPI_LOW_BOUND || *pi4Param > RCPI_HIGH_BOUND) { + DBGLOG(INIT, ERROR, "NCHO roam trigger invalid %d\n", *pi4Param); + return WLAN_STATUS_INVALID_DATA; + } + + kalSprintf(acCmd, "%s %d", FW_CFG_KEY_NCHO_ROAM_RCPI, *pi4Param); + rStatus = wlanFwCfgParse(prAdapter, acCmd); + if (rStatus == WLAN_STATUS_SUCCESS) { + prAdapter->rNchoInfo.i4RoamTrigger = RCPI_TO_dBm(*pi4Param); + DBGLOG(INIT, TRACE, "NCHO roam trigger is %d\n", prAdapter->rNchoInfo.i4RoamTrigger); + } + + return rStatus; +} + +WLAN_STATUS +wlanoidQueryNchoRoamTrigger(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + struct _CMD_HEADER_T cmdV1Header; + struct _CMD_HEADER_T *prCmdV1Header = (struct _CMD_HEADER_T *)pvQueryBuffer; + struct _CMD_FORMAT_V1_T *prCmdV1 = NULL; + + DEBUGFUNC("wlanoidQueryNchoRoamTrigger"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct _CMD_HEADER_T); + + if (u4QueryBufferLen < sizeof(struct _CMD_HEADER_T)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgECHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + prCmdV1 = (struct _CMD_FORMAT_V1_T *) prCmdV1Header->buffer; + rStatus = wlanoidSetNchoHeader(prCmdV1Header, + prCmdV1, + FW_CFG_KEY_NCHO_ROAM_RCPI, + kalStrLen(FW_CFG_KEY_NCHO_ROAM_RCPI)); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "NCHO no enough memory\n"); + return rStatus; + } + kalMemCopy(&cmdV1Header, prCmdV1Header, sizeof(struct _CMD_HEADER_T)); + rStatus = wlanSendSetQueryCmd( + prAdapter, + CMD_ID_GET_SET_CUSTOMER_CFG, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryCfgRead, + nicOidCmdTimeoutCommon, + sizeof(struct _CMD_HEADER_T), + (PUINT_8)&cmdV1Header, + pvQueryBuffer, + u4QueryBufferLen); + return rStatus; +} + +WLAN_STATUS +wlanoidSetNchoRoamDelta(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) { + INT_32 *pi4Param = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoRoamDelta"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(INT_32); + + if (u4SetBufferLen < sizeof(INT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + pi4Param = (PINT_32) pvSetBuffer; + if (*pi4Param > 100) { + DBGLOG(INIT, ERROR, "NCHO roam delta invalid %d\n", *pi4Param); + return WLAN_STATUS_INVALID_DATA; + } + + prAdapter->rNchoInfo.i4RoamDelta = *pi4Param; + DBGLOG(INIT, TRACE, "NCHO roam delta is %d\n", *pi4Param); + rStatus = WLAN_STATUS_SUCCESS; + + return rStatus; +} + +WLAN_STATUS +wlanoidQueryNchoRoamDelta(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) { + INT_32 *pParam = NULL; + + DEBUGFUNC("wlanoidQueryNchoRoamDelta"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(PINT_32)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgECHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + pParam = (PINT_32) pvQueryBuffer; + *pParam = prAdapter->rNchoInfo.i4RoamDelta; + DBGLOG(INIT, TRACE, "NCHO roam delta is %d\n", *pParam); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidSetNchoRoamScnPeriod(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) { + UINT_32 *pParam = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoRoamScnPeriod"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(UINT_32); + + if (u4SetBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (PUINT_32) pvSetBuffer; + + prAdapter->rNchoInfo.u4RoamScanPeriod = *pParam; + DBGLOG(INIT, TRACE, "NCHO roam scan period is %d\n", *pParam); + rStatus = WLAN_STATUS_SUCCESS; + + return rStatus; +} + +WLAN_STATUS +wlanoidQueryNchoRoamScnPeriod(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) { + UINT_32 *pParam = NULL; + + DEBUGFUNC("wlanoidQueryNchoRoamScnPeriod"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgECHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + pParam = (PUINT_32) pvQueryBuffer; + *pParam = prAdapter->rNchoInfo.u4RoamScanPeriod; + DBGLOG(INIT, TRACE, "NCHO roam scan period is %d\n", *pParam); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidSetNchoRoamScnChnl(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) { + PCFG_NCHO_SCAN_CHNL_T prRoamScnChnl = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoRoamScnChnl"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(CFG_NCHO_SCAN_CHNL_T); + + if (u4SetBufferLen < sizeof(CFG_NCHO_SCAN_CHNL_T)) + return WLAN_STATUS_INVALID_LENGTH; + + prRoamScnChnl = (PCFG_NCHO_SCAN_CHNL_T) pvSetBuffer; + + kalMemCopy(&prAdapter->rNchoInfo.rRoamScnChnl, prRoamScnChnl, *pu4SetInfoLen); + prAdapter->rNchoInfo.u4RoamScanControl = TRUE; + DBGLOG(INIT, TRACE, "NCHO set roam scan channel num is %d\n", prRoamScnChnl->ucChannelListNum); + rStatus = WLAN_STATUS_SUCCESS; + + + return rStatus; +} + +WLAN_STATUS +wlanoidQueryNchoRoamScnChnl(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) { + PCFG_NCHO_SCAN_CHNL_T prRoamScnChnl = NULL; + + DEBUGFUNC("wlanoidQueryNchoRoamScnChnl"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(CFG_NCHO_SCAN_CHNL_T)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgECHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + prRoamScnChnl = (PCFG_NCHO_SCAN_CHNL_T) pvQueryBuffer; + kalMemCopy(prRoamScnChnl, &prAdapter->rNchoInfo.rRoamScnChnl, u4QueryBufferLen); + DBGLOG(INIT, TRACE, "NCHO roam scan channel num is %d\n", prRoamScnChnl->ucChannelListNum); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidSetNchoRoamScnCtrl(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) { + UINT_32 *pParam = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoRoamScnChnl"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(UINT_32); + + if (u4SetBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (PUINT_32) pvSetBuffer; + if (*pParam != TRUE && *pParam != FALSE) { + DBGLOG(INIT, ERROR, "NCHO roam scan control invalid %d\n", *pParam); + return WLAN_STATUS_INVALID_DATA; + } + + prAdapter->rNchoInfo.u4RoamScanControl = *pParam; + DBGLOG(INIT, TRACE, "NCHO roam scan control is %d\n", *pParam); + rStatus = WLAN_STATUS_SUCCESS; + + return rStatus; +} + +WLAN_STATUS +wlanoidQueryNchoRoamScnCtrl(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) { + UINT_32 *pParam = NULL; + + DEBUGFUNC("wlanoidQueryNchoRoamScnCtrl"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgECHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + pParam = (PUINT_32) pvQueryBuffer; + *pParam = prAdapter->rNchoInfo.u4RoamScanControl; + DBGLOG(INIT, TRACE, "NCHO roam scan control is %d\n", *pParam); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidSetNchoScnChnlTime(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) { + UINT_32 *pParam = NULL; + char acCmd[NCHO_CMD_MAX_LENGTH] = {0}; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoScnChnlTime"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(UINT_32); + + if (u4SetBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (PUINT_32) pvSetBuffer; + if (*pParam < 10 && *pParam > 1000) { + DBGLOG(INIT, ERROR, "NCHO scan channel time invalid %d\n", *pParam); + return WLAN_STATUS_INVALID_DATA; + } + + kalSprintf(acCmd, "%s %d", FW_CFG_KEY_NCHO_SCN_CHANNEL_TIME, *pParam); + rStatus = wlanFwCfgParse(prAdapter, acCmd); + if (rStatus == WLAN_STATUS_SUCCESS) { + prAdapter->rNchoInfo.u4ScanChannelTime = *pParam; + DBGLOG(INIT, TRACE, "NCHO scan channel time is %d\n", *pParam); + } + + return rStatus; +} + +WLAN_STATUS +wlanoidQueryNchoScnChnlTime(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + struct _CMD_HEADER_T cmdV1Header; + struct _CMD_HEADER_T *prCmdV1Header = (struct _CMD_HEADER_T *)pvQueryBuffer; + struct _CMD_FORMAT_V1_T *prCmdV1 = NULL; + + DEBUGFUNC("wlanoidQueryNchoScnChnlTime"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct _CMD_HEADER_T); + + if (u4QueryBufferLen < sizeof(struct _CMD_HEADER_T)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgECHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + prCmdV1 = (struct _CMD_FORMAT_V1_T *) prCmdV1Header->buffer; + rStatus = wlanoidSetNchoHeader(prCmdV1Header, + prCmdV1, + FW_CFG_KEY_NCHO_SCN_CHANNEL_TIME, + kalStrLen(FW_CFG_KEY_NCHO_SCN_CHANNEL_TIME)); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "NCHO no enough memory\n"); + return rStatus; + } + kalMemCopy(&cmdV1Header, prCmdV1Header, sizeof(struct _CMD_HEADER_T)); + rStatus = wlanSendSetQueryCmd( + prAdapter, + CMD_ID_GET_SET_CUSTOMER_CFG, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryCfgRead, + nicOidCmdTimeoutCommon, + sizeof(struct _CMD_HEADER_T), + (PUINT_8)&cmdV1Header, + pvQueryBuffer, + u4QueryBufferLen); + return rStatus; +} + +WLAN_STATUS +wlanoidSetNchoScnHomeTime(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) { + UINT_32 *pParam = NULL; + char acCmd[NCHO_CMD_MAX_LENGTH] = {0}; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoScnHomeTime"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(UINT_32); + + if (u4SetBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (PUINT_32) pvSetBuffer; + if (*pParam < 10 && *pParam > 1000) { + DBGLOG(INIT, ERROR, "NCHO scan home time invalid %d\n", *pParam); + return WLAN_STATUS_INVALID_DATA; + } + + kalSprintf(acCmd, "%s %d", FW_CFG_KEY_NCHO_SCN_HOME_TIME, *pParam); + DBGLOG(REQ, TRACE, "NCHO cmd is %s\n", acCmd); + rStatus = wlanFwCfgParse(prAdapter, acCmd); + if (rStatus == WLAN_STATUS_SUCCESS) { + prAdapter->rNchoInfo.u4ScanHomeTime = *pParam; + DBGLOG(INIT, TRACE, "NCHO scan home time is %d\n", *pParam); + } + + return rStatus; +} + +WLAN_STATUS +wlanoidQueryNchoScnHomeTime(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + struct _CMD_HEADER_T cmdV1Header; + struct _CMD_HEADER_T *prCmdV1Header = (struct _CMD_HEADER_T *)pvQueryBuffer; + struct _CMD_FORMAT_V1_T *prCmdV1 = NULL; + + DEBUGFUNC("wlanoidQueryNchoScnHomeTime"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct _CMD_HEADER_T); + + if (u4QueryBufferLen < sizeof(struct _CMD_HEADER_T)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgECHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + prCmdV1 = (struct _CMD_FORMAT_V1_T *) prCmdV1Header->buffer; + rStatus = wlanoidSetNchoHeader(prCmdV1Header, + prCmdV1, + FW_CFG_KEY_NCHO_SCN_HOME_TIME, + kalStrLen(FW_CFG_KEY_NCHO_SCN_HOME_TIME)); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "NCHO no enough memory\n"); + return rStatus; + } + kalMemCopy(&cmdV1Header, prCmdV1Header, sizeof(struct _CMD_HEADER_T)); + rStatus = wlanSendSetQueryCmd( + prAdapter, + CMD_ID_GET_SET_CUSTOMER_CFG, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryCfgRead, + nicOidCmdTimeoutCommon, + sizeof(struct _CMD_HEADER_T), + (PUINT_8)&cmdV1Header, + pvQueryBuffer, + u4QueryBufferLen); + return rStatus; +} + +WLAN_STATUS +wlanoidSetNchoScnHomeAwayTime(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) { + UINT_32 *pParam = NULL; + char acCmd[NCHO_CMD_MAX_LENGTH] = {0}; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoScnHomeAwayTime"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(UINT_32); + + if (u4SetBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (PUINT_32) pvSetBuffer; + if (*pParam < 10 && *pParam > 1000) { + DBGLOG(INIT, ERROR, "NCHO scan home away time invalid %d\n", *pParam); + return WLAN_STATUS_INVALID_DATA; + } + + + kalSprintf(acCmd, "%s %d", FW_CFG_KEY_NCHO_SCN_HOME_AWAY_TIME, *pParam); + DBGLOG(REQ, TRACE, "NCHO cmd is %s\n", acCmd); + rStatus = wlanFwCfgParse(prAdapter, acCmd); + if (rStatus == WLAN_STATUS_SUCCESS) { + prAdapter->rNchoInfo.u4ScanHomeawayTime = *pParam; + DBGLOG(INIT, TRACE, "NCHO scan home away is %d\n", *pParam); + } + + return rStatus; +} + +WLAN_STATUS +wlanoidQueryNchoScnHomeAwayTime(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + struct _CMD_HEADER_T cmdV1Header; + struct _CMD_HEADER_T *prCmdV1Header = (struct _CMD_HEADER_T *)pvQueryBuffer; + struct _CMD_FORMAT_V1_T *prCmdV1 = NULL; + + DEBUGFUNC("wlanoidQueryNchoScnHomeTime"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct _CMD_HEADER_T); + + if (u4QueryBufferLen < sizeof(struct _CMD_HEADER_T)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgECHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + prCmdV1 = (struct _CMD_FORMAT_V1_T *) prCmdV1Header->buffer; + rStatus = wlanoidSetNchoHeader(prCmdV1Header, + prCmdV1, + FW_CFG_KEY_NCHO_SCN_HOME_AWAY_TIME, + kalStrLen(FW_CFG_KEY_NCHO_SCN_HOME_AWAY_TIME)); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "NCHO no enough memory\n"); + return rStatus; + } + kalMemCopy(&cmdV1Header, prCmdV1Header, sizeof(struct _CMD_HEADER_T)); + rStatus = wlanSendSetQueryCmd( + prAdapter, + CMD_ID_GET_SET_CUSTOMER_CFG, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryCfgRead, + nicOidCmdTimeoutCommon, + sizeof(struct _CMD_HEADER_T), + (PUINT_8)&cmdV1Header, + pvQueryBuffer, + u4QueryBufferLen); + return rStatus; +} + +WLAN_STATUS +wlanoidSetNchoScnNprobes(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) { + UINT_32 *pParam = NULL; + char acCmd[NCHO_CMD_MAX_LENGTH] = {0}; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoScnNprobes"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(UINT_32); + + if (u4SetBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (PUINT_32) pvSetBuffer; + if (*pParam > 16) { + DBGLOG(INIT, ERROR, "NCHO scan Nprobes invalid %d\n", *pParam); + return WLAN_STATUS_INVALID_DATA; + } + + + kalSprintf(acCmd, "%s %d", FW_CFG_KEY_NCHO_SCN_NPROBES, *pParam); + rStatus = wlanFwCfgParse(prAdapter, acCmd); + if (rStatus == WLAN_STATUS_SUCCESS) { + prAdapter->rNchoInfo.u4ScanNProbes = *pParam; + DBGLOG(INIT, TRACE, "NCHO Nprobes is %d\n", *pParam); + } + return rStatus; +} + +WLAN_STATUS +wlanoidQueryNchoScnNprobes(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + struct _CMD_HEADER_T cmdV1Header; + struct _CMD_HEADER_T *prCmdV1Header = (struct _CMD_HEADER_T *)pvQueryBuffer; + struct _CMD_FORMAT_V1_T *prCmdV1 = NULL; + + DEBUGFUNC("wlanoidQueryNchoScnNprobes"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct _CMD_HEADER_T); + + if (u4QueryBufferLen < sizeof(struct _CMD_HEADER_T)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgECHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + prCmdV1 = (struct _CMD_FORMAT_V1_T *) prCmdV1Header->buffer; + rStatus = wlanoidSetNchoHeader(prCmdV1Header, + prCmdV1, + FW_CFG_KEY_NCHO_SCN_NPROBES, + kalStrLen(FW_CFG_KEY_NCHO_SCN_NPROBES)); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "NCHO no enough memory\n"); + return rStatus; + } + kalMemCopy(&cmdV1Header, prCmdV1Header, sizeof(struct _CMD_HEADER_T)); + rStatus = wlanSendSetQueryCmd( + prAdapter, + CMD_ID_GET_SET_CUSTOMER_CFG, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryCfgRead, + nicOidCmdTimeoutCommon, + sizeof(struct _CMD_HEADER_T), + (PUINT_8)&cmdV1Header, + pvQueryBuffer, + u4QueryBufferLen); + return rStatus; +} + +WLAN_STATUS +wlanoidGetNchoReassocInfo(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + P_BSS_DESC_T prBssDesc = NULL; + P_PARAM_CONNECT_T prParamConn; + + DEBUGFUNC("wlanoidGetNchoReassocInfo"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + ASSERT(pvQueryBuffer); + + prParamConn = (P_PARAM_CONNECT_T)pvQueryBuffer; + if (prAdapter->rNchoInfo.fgECHOEnabled == TRUE) { + prBssDesc = scanSearchBssDescByBssid(prAdapter, prParamConn->pucBssid); + if (prBssDesc != NULL) { + prParamConn->u4SsidLen = prBssDesc->ucSSIDLen; + COPY_SSID(prParamConn->pucSsid, + prParamConn->u4SsidLen, + prBssDesc->aucSSID, + prBssDesc->ucSSIDLen); + rStatus = WLAN_STATUS_SUCCESS; + } + } + return rStatus; +} + +WLAN_STATUS +wlanoidSendNchoActionFrameStart(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + P_NCHO_INFO prNchoInfo = NULL; + P_NCHO_ACTION_FRAME_PARAMS prParamActionFrame = NULL; + + DEBUGFUNC("wlanoidSendNchoActionFrameStart"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + + prNchoInfo = &prAdapter->rNchoInfo; + prParamActionFrame = (P_NCHO_ACTION_FRAME_PARAMS)pvSetBuffer; + prNchoInfo->fgIsSendingAF = TRUE; + prNchoInfo->fgChGranted = FALSE; + COPY_MAC_ADDR(prNchoInfo->rParamActionFrame.aucBssid, prParamActionFrame->aucBssid); + prNchoInfo->rParamActionFrame.i4channel = prParamActionFrame->i4channel; + prNchoInfo->rParamActionFrame.i4DwellTime = prParamActionFrame->i4DwellTime; + prNchoInfo->rParamActionFrame.i4len = prParamActionFrame->i4len; + kalMemCopy(prNchoInfo->rParamActionFrame.aucData, + prParamActionFrame->aucData, + prParamActionFrame->i4len); + DBGLOG(INIT, TRACE, "NCHO send ncho action frame start\n"); + rStatus = WLAN_STATUS_SUCCESS; + + return rStatus; +} + +WLAN_STATUS +wlanoidSendNchoActionFrameEnd(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSendNchoActionFrameEnd"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + prAdapter->rNchoInfo.fgIsSendingAF = FALSE; + prAdapter->rNchoInfo.fgChGranted = TRUE; + DBGLOG(INIT, TRACE, "NCHO send action frame end\n"); + rStatus = WLAN_STATUS_SUCCESS; + + return rStatus; +} + +WLAN_STATUS +wlanoidSetNchoWesMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) { + UINT_32 *pParam = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoWesMode"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(UINT_32); + + if (u4SetBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (PUINT_32) pvSetBuffer; + if (*pParam != TRUE && *pParam != FALSE) { + DBGLOG(INIT, ERROR, "NCHO wes mode invalid %d\n", *pParam); + return WLAN_STATUS_INVALID_DATA; + } + + + prAdapter->rNchoInfo.u4WesMode = *pParam; + DBGLOG(INIT, TRACE, "NCHO WES mode is %d\n", *pParam); + rStatus = WLAN_STATUS_SUCCESS; + + return rStatus; +} + +WLAN_STATUS +wlanoidQueryNchoWesMode(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) { + UINT_32 *pParam = NULL; + + DEBUGFUNC("wlanoidQueryNchoWesMode"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgECHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + pParam = (PUINT_32) pvQueryBuffer; + *pParam = prAdapter->rNchoInfo.u4WesMode; + DBGLOG(INIT, TRACE, "NCHO Wes mode is %d\n", *pParam); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidSetNchoBand(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) { + UINT_32 *pParam = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoBand"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(UINT_32); + + if (u4SetBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (PUINT_32) pvSetBuffer; + + switch (*pParam) { + case NCHO_BAND_AUTO: + prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] = BAND_NULL; + prAdapter->rNchoInfo.eBand = NCHO_BAND_AUTO; + rStatus = WLAN_STATUS_SUCCESS; + break; + case NCHO_BAND_2G4: + prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] = BAND_2G4; + prAdapter->rNchoInfo.eBand = NCHO_BAND_2G4; + rStatus = WLAN_STATUS_SUCCESS; + break; + case NCHO_BAND_5G: + prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] = BAND_5G; + prAdapter->rNchoInfo.eBand = NCHO_BAND_5G; + rStatus = WLAN_STATUS_SUCCESS; + break; + default: + DBGLOG(INIT, ERROR, "NCHO wes mode invalid %d\n", *pParam); + rStatus = WLAN_STATUS_INVALID_DATA; + break; + } + + DBGLOG(INIT, INFO, "NCHO enabled:%d ,band:%d,status:%d\n" + , prAdapter->rNchoInfo.fgECHOEnabled, *pParam, rStatus); + + + return rStatus; +} + +WLAN_STATUS +wlanoidQueryNchoBand(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) { + UINT_32 *pParam = NULL; + + DEBUGFUNC("wlanoidQueryNchoBand"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgECHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + pParam = (PUINT_32) pvQueryBuffer; + *pParam = prAdapter->rNchoInfo.eBand; + DBGLOG(INIT, TRACE, "NCHO band is %d\n", *pParam); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidSetNchoDfsScnMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) { + UINT_32 *pParam = NULL; + char acCmd[NCHO_CMD_MAX_LENGTH] = {0}; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoDfsScnMode"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(UINT_32); + + if (u4SetBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (PUINT_32) pvSetBuffer; + if (*pParam >= NCHO_DFS_SCN_NUM) { + DBGLOG(INIT, ERROR, "NCHO DFS scan mode invalid %d\n", *pParam); + return WLAN_STATUS_INVALID_DATA; + } + + + kalSprintf(acCmd, "%s %d", FW_CFG_KEY_NCHO_SCAN_DFS_MODE, *pParam); + rStatus = wlanFwCfgParse(prAdapter, acCmd); + if (rStatus == WLAN_STATUS_SUCCESS) { + prAdapter->rNchoInfo.eDFSScnMode = *pParam; + DBGLOG(INIT, TRACE, "NCHO DFS scan mode is %d\n", *pParam); + } + + return rStatus; +} + +WLAN_STATUS +wlanoidQueryNchoDfsScnMode(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + struct _CMD_HEADER_T cmdV1Header; + struct _CMD_HEADER_T *prCmdV1Header = (struct _CMD_HEADER_T *)pvQueryBuffer; + struct _CMD_FORMAT_V1_T *prCmdV1 = NULL; + + DEBUGFUNC("wlanoidQueryNchoDfsScnMode"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct _CMD_HEADER_T); + + if (u4QueryBufferLen < sizeof(struct _CMD_HEADER_T)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgECHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + prCmdV1 = (struct _CMD_FORMAT_V1_T *) prCmdV1Header->buffer; + rStatus = wlanoidSetNchoHeader(prCmdV1Header, + prCmdV1, + FW_CFG_KEY_NCHO_SCAN_DFS_MODE, + kalStrLen(FW_CFG_KEY_NCHO_SCAN_DFS_MODE)); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "NCHO no enough memory\n"); + return rStatus; + } + kalMemCopy(&cmdV1Header, prCmdV1Header, sizeof(struct _CMD_HEADER_T)); + rStatus = wlanSendSetQueryCmd( + prAdapter, + CMD_ID_GET_SET_CUSTOMER_CFG, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryCfgRead, + nicOidCmdTimeoutCommon, + sizeof(struct _CMD_HEADER_T), + (PUINT_8)&cmdV1Header, + pvQueryBuffer, + u4QueryBufferLen); + return rStatus; +} + +WLAN_STATUS +wlanoidSetNchoEnable(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) { + UINT_32 *pParam = NULL; + char acCmd[NCHO_CMD_MAX_LENGTH] = { 0 }; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoEnable"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(UINT_32); + + if (u4SetBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (PUINT_32) pvSetBuffer; + if (*pParam != 0 && *pParam != 1) { + DBGLOG(INIT, ERROR, "NCHO DFS scan mode invalid %d\n", *pParam); + return WLAN_STATUS_INVALID_DATA; + } + + kalSprintf(acCmd, "%s %d", FW_CFG_KEY_NCHO_ENABLE, *pParam); + rStatus = wlanFwCfgParse(prAdapter, acCmd); + if (rStatus == WLAN_STATUS_SUCCESS) { + prAdapter->rNchoInfo.fgECHOEnabled = *pParam; + DBGLOG(INIT, INFO, "NCHO enable is %d\n", *pParam); + } + + return rStatus; +} + +WLAN_STATUS +wlanoidQueryNchoEnable(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + struct _CMD_HEADER_T cmdV1Header; + struct _CMD_HEADER_T *prCmdV1Header = (struct _CMD_HEADER_T *)pvQueryBuffer; + struct _CMD_FORMAT_V1_T *prCmdV1 = NULL; + + DEBUGFUNC("wlanoidQueryNchoRoamTrigger"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct _CMD_HEADER_T); + + if (u4QueryBufferLen < sizeof(struct _CMD_HEADER_T)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + prCmdV1 = (struct _CMD_FORMAT_V1_T *) prCmdV1Header->buffer; + rStatus = wlanoidSetNchoHeader(prCmdV1Header, + prCmdV1, + FW_CFG_KEY_NCHO_ENABLE, + kalStrLen(FW_CFG_KEY_NCHO_ENABLE)); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "NCHO no enough memory\n"); + return rStatus; + } + kalMemCopy(&cmdV1Header, prCmdV1Header, sizeof(struct _CMD_HEADER_T)); + rStatus = wlanSendSetQueryCmd( + prAdapter, + CMD_ID_GET_SET_CUSTOMER_CFG, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryCfgRead, + nicOidCmdTimeoutCommon, + sizeof(struct _CMD_HEADER_T), + (PUINT_8)&cmdV1Header, + pvQueryBuffer, + u4QueryBufferLen); + return rStatus; +} +#endif /* CFG_SUPPORT_NCHO */ +WLAN_STATUS +wlanoidAbortScan(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen) { + + P_AIS_FSM_INFO_T prAisFsmInfo = NULL; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + if (prAisFsmInfo->eCurrentState == AIS_STATE_SCAN || + prAisFsmInfo->eCurrentState == AIS_STATE_ONLINE_SCAN) { + DBGLOG(OID, INFO, "wlanoidAbortScan\n"); + aisFsmStateAbort_SCAN(prAdapter); + } + return WLAN_STATUS_SUCCESS; +} + +#if CFG_SUPPORT_GAMING_MODE +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to enable/disable gaming mode +* +* \param[in] pvAdapter A 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 wlanoidSetGamingMode(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + struct CMD_GAMING_MODE_HEADER rGameModeHeader; + BOOLEAN fgEnable, fgEnScan; + UINT_32 u4Events; + + DEBUGFUNC("wlanoidSetGamingMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen != sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + kalMemCopy(&u4Events, pvSetBuffer, u4SetBufferLen); + + DBGLOG(OID, INFO, "Event change gaming=%d, network:%d whitelist:%d\n", + (u4Events & GED_EVENT_GAS), + (u4Events & GED_EVENT_NETWORK), + (u4Events & GED_EVENT_DOPT_WIFI_SCAN)); + + fgEnable = ((u4Events & GED_EVENT_GAS) != 0) && ((u4Events & GED_EVENT_NETWORK) != 0) && + (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED); + fgEnScan = (!fgEnable || ((u4Events & GED_EVENT_DOPT_WIFI_SCAN) != 0)); + + if (fgEnScan != prAdapter->fgEnCfg80211Scan || fgEnable != prAdapter->fgEnGamingMode) + DBGLOG(OID, INFO, "Gaming mode event change Enable=%d EnableScan:%d\n", + fgEnable, fgEnScan); + + prAdapter->fgEnCfg80211Scan = fgEnScan; + + if (fgEnable == prAdapter->fgEnGamingMode) + return WLAN_STATUS_SUCCESS; + + prAdapter->fgEnGamingMode = fgEnable; + prAdapter->u4QmRxBaMissTimeout = fgEnable ? + SHORT_QM_RX_BA_ENTRY_MISS_TIMEOUT_MS : DEFAULT_QM_RX_BA_ENTRY_MISS_TIMEOUT_MS; + + rGameModeHeader.ucVersion = GAMING_MODE_CMD_V1; + rGameModeHeader.ucType = 0; + rGameModeHeader.ucMagicCode = GAMING_MODE_MAGIC_CODE; + rGameModeHeader.ucBufferLen = sizeof(struct GAMING_MODE_SETTING); + rGameModeHeader.rSetting.fgEnable = fgEnable; + + wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_GAMING_MODE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + TRUE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct CMD_GAMING_MODE_HEADER), /* u4SetQueryInfoLen */ + (PUINT_8)&rGameModeHeader, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + return WLAN_STATUS_SUCCESS; +} +#endif /* CFG_SUPPORT_GAMING_MODE */ + +WLAN_STATUS +wlanoidQueryWifiLogLevelSupport(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + struct PARAM_WIFI_LOG_LEVEL_UI *pparam; + + DEBUGFUNC("wlanoidQueryWifiLogLevelSupport"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + pparam = (struct PARAM_WIFI_LOG_LEVEL_UI *) pvQueryBuffer; + + DBGLOG(OID, INFO, "version: %d, module: %d, enable: %d\n", pparam->u4Version, + pparam->u4Module, pparam->u4Enable); + + pparam->u4Enable = wlanDbgLevelUiSupport(prAdapter, pparam->u4Version, pparam->u4Module); + *pu4QueryInfoLen = sizeof(struct PARAM_WIFI_LOG_LEVEL_UI); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidQueryWifiLogLevel(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + struct PARAM_WIFI_LOG_LEVEL *pparam; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryWifiLogLevel"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + pparam = (struct PARAM_WIFI_LOG_LEVEL *) pvQueryBuffer; + + DBGLOG(OID, INFO, "version: %d, module: %d\n", pparam->u4Version, pparam->u4Module); + + pparam->u4Level = wlanDbgGetLogLevelImpl(prAdapter, pparam->u4Version, pparam->u4Module); + *pu4QueryInfoLen = sizeof(struct PARAM_WIFI_LOG_LEVEL_UI); + + return rStatus; +} + +WLAN_STATUS +wlanoidSetWifiLogLevel(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + struct PARAM_WIFI_LOG_LEVEL *pparam; + + DEBUGFUNC("wlanoidSetWifiLogLevel"); + + ASSERT(prAdapter); + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + pparam = (struct PARAM_WIFI_LOG_LEVEL *) pvSetBuffer; + + DBGLOG(OID, INFO, "version: %d, module: %d, level: %d\n", pparam->u4Version, + pparam->u4Module, pparam->u4Level); + + wlanDbgSetLogLevelImpl(prAdapter, pparam->u4Version, pparam->u4Module, + pparam->u4Level); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanoidSetTxPowerLimit(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + /* TxPwrBackOffParam's 0th byte contains enable/disable TxPowerBackOff for 2G */ + /* TxPwrBackOffParam's 1st byte contains default TxPowerBackOff value for 2G */ + /* TxPwrBackOffParam's 2nd byte contains enable/disable TxPowerBackOff for 5G */ + /* TxPwrBackOffParam's 3rd byte contains default TxPowerBackOff value for 5G */ + unsigned long TxPwrBackOffParam = 0; + struct PARAM_TX_POWER_LIMIT *prTxPwrLimit; + bool fgGotData = FALSE; + uint32_t rStatus; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + + prTxPwrLimit = (struct PARAM_TX_POWER_LIMIT *)pvSetBuffer; + DBGLOG(OID, INFO, + "scenario=%d, enable2G=%d, txPowerLimit2G=%u, enable5G=%d, txPowerLimit5G=%u\n", + prTxPwrLimit->iScenario, + prTxPwrLimit->fgEnable2G, prTxPwrLimit->ucTxPowerLimit2G, + prTxPwrLimit->fgEnable5G, prTxPwrLimit->ucTxPowerLimit5G); + + if (prTxPwrLimit->iScenario == -1) { + /* reset tx power limitation */ + TxPwrBackOffParam = 0; /* First byte is start/stop */ + fgGotData = TRUE; + } else if (prTxPwrLimit->iScenario == -2) { + /* use the values in prTxPwrLimit */ + TxPwrBackOffParam |= prTxPwrLimit->fgEnable2G; + TxPwrBackOffParam |= (prTxPwrLimit->ucTxPowerLimit2G * 2) << 8; + TxPwrBackOffParam |= prTxPwrLimit->fgEnable5G << 16; + TxPwrBackOffParam |= (unsigned long) + (prTxPwrLimit->ucTxPowerLimit5G * 2) << 24; + fgGotData = TRUE; + } else if (prTxPwrLimit->iScenario >= 0) { + /* use the global variable g_txPowerScenario + * by scenario index + */ + uint32_t u4Idx = (uint32_t)prTxPwrLimit->iScenario; + uint32_t u4IdxMax = sizeof(g_txPowerScenario) / + sizeof(struct TX_POWER_SCENARIO_ENTRY); + + if (u4IdxMax > 0) { + if (u4Idx >= u4IdxMax) { + DBGLOG(OID, ERROR, + "invalid index=%u, max=%u\n", + u4Idx, u4IdxMax); + return -EINVAL; + } + + TxPwrBackOffParam |= + g_txPowerScenario[u4Idx].fgEnable2G; + TxPwrBackOffParam |= + (g_txPowerScenario[u4Idx].ucTxPowerLimit2G * 2) + << 8; + TxPwrBackOffParam |= + g_txPowerScenario[u4Idx].fgEnable5G << 16; + TxPwrBackOffParam |= (unsigned long) + (g_txPowerScenario[u4Idx].ucTxPowerLimit5G * 2) + << 24; + fgGotData = TRUE; + } else { + /* if size of g_txPowerScenario == 0, + * try to use NVRAM setting + */ + DBGLOG(OID, INFO, + "size of g_txPowerScenario=%u\n", u4IdxMax); + } + } else { + DBGLOG(OID, ERROR, "invalid iScenario=%d\n", + prTxPwrLimit->iScenario); + return -EINVAL; + } + + /* try to use NVRAM setting if values cannot be desided at last step */ + if (!fgGotData) { + P_REG_INFO_T prRegInfo = &(prAdapter->prGlueInfo->rRegInfo); + + if (!prRegInfo) { + DBGLOG(OID, INFO, "prRegInfo is NULL\n"); + return -EFAULT; + } + + if (prRegInfo->bTxPowerLimitEnable2G || + prRegInfo->bTxPowerLimitEnable5G) { + TxPwrBackOffParam |= prRegInfo->bTxPowerLimitEnable2G; + TxPwrBackOffParam |= (prRegInfo->cTxBackOffMaxPower2G) + << 8; + TxPwrBackOffParam |= prRegInfo->bTxPowerLimitEnable5G + << 16; + TxPwrBackOffParam |= (unsigned long) + (prRegInfo->cTxBackOffMaxPower5G) + << 24; + fgGotData = TRUE; + } + } + + if (!fgGotData) { + DBGLOG(OID, ERROR, "fgGotData is FALSE\n"); + return -EFAULT; + } + + DBGLOG(OID, INFO, + "set tx power limitation: TxPwrBackOffParam=0x%lx\n", + TxPwrBackOffParam); + + rStatus = nicTxPowerBackOff(prAdapter, TxPwrBackOffParam); + if (rStatus == WLAN_STATUS_PENDING) + rStatus = 0; + else + rStatus = -EINVAL; + + return rStatus; +} + +WLAN_STATUS wlanoidGetWifiType(IN P_ADAPTER_T prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct PARAM_GET_WIFI_TYPE *prParamGetWifiType; + P_BSS_INFO_T prBssInfo = NULL; + uint8_t ucBssIdx; + uint8_t ucPhyType; + uint8_t ucMaxCopySize; + uint8_t *pNameBuf; + + *pu4SetInfoLen = 0; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, ERROR, + "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + prParamGetWifiType = (struct PARAM_GET_WIFI_TYPE *)pvSetBuffer; + if ((gPrDev != NULL) && + (prParamGetWifiType->prNetDev == gPrDev)) + ucBssIdx = (uint8_t)NETWORK_TYPE_AIS_INDEX; + else if ((g_P2pPrDev != NULL) && + (prParamGetWifiType->prNetDev == g_P2pPrDev)) + ucBssIdx = (uint8_t)NETWORK_TYPE_P2P_INDEX; + else { + DBGLOG(OID, ERROR, + "network type index error! %p, %p, %p\n", + prParamGetWifiType->prNetDev, gPrDev, g_P2pPrDev); + return WLAN_STATUS_INVALID_DATA; + } + + DBGLOG(OID, INFO, "bss index=%d\n", ucBssIdx); + + kalMemZero(prParamGetWifiType->arWifiTypeName, + sizeof(prParamGetWifiType->arWifiTypeName)); + pNameBuf = &prParamGetWifiType->arWifiTypeName[0]; + ucMaxCopySize = sizeof(prParamGetWifiType->arWifiTypeName) - 1; + + if (ucBssIdx >= NETWORK_TYPE_INDEX_NUM) { + DBGLOG(OID, ERROR, "invalid bss index: %u\n", ucBssIdx); + return WLAN_STATUS_INVALID_DATA; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + if ((!prBssInfo) || (!IS_BSS_ACTIVE(prBssInfo))) { + DBGLOG(OID, ERROR, "invalid BssInfo: %p, %u\n", + prBssInfo, ucBssIdx); + return WLAN_STATUS_INVALID_DATA; + } + + ucPhyType = prBssInfo->ucPhyTypeSet; + if (ucPhyType & PHY_TYPE_SET_802_11N) + kalStrnCpy(pNameBuf, "11N", ucMaxCopySize); + else if (ucPhyType & PHY_TYPE_SET_802_11B) + kalStrnCpy(pNameBuf, "11B", ucMaxCopySize); + else if (ucPhyType & PHY_TYPE_SET_802_11G) + kalStrnCpy(pNameBuf, "11G", ucMaxCopySize); + else if (ucPhyType & PHY_TYPE_SET_802_11A) + kalStrnCpy(pNameBuf, "11A", ucMaxCopySize); + else + DBGLOG(OID, INFO, + "unknown wifi type, prBssInfo->ucPhyTypeSet: %u\n", + ucPhyType); + + *pu4SetInfoLen = kalStrLen(pNameBuf); + + DBGLOG(OID, INFO, "wifi type=[%s](%d), phyType=%u\n", + pNameBuf, *pu4SetInfoLen, ucPhyType); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidConfigRoaming(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + struct nlattr *attrlist; + struct AIS_BLACKLIST_ITEM *prBlackList; + P_BSS_DESC_T prBssDesc = NULL; + UINT_32 len_shift = 0; + UINT_32 numOfList[2] = { 0 }; + int i; + + attrlist = (struct nlattr *)pvSetBuffer; + + /* get the number of blacklist and copy those mac addresses from HAL */ + if (attrlist->nla_type == WIFI_ATTRIBUTE_ROAMING_BLACKLIST_NUM) + numOfList[0] = nla_get_u32(attrlist); + + DBGLOG(REQ, INFO, "Get the number of blacklist=%d\n", numOfList[0]); + /*Refresh all the FWKBlacklist */ + aisRefreshFWKBlacklist(prAdapter); + + if (numOfList[0] < 0 || numOfList[0] > MAX_FW_ROAMING_BLACKLIST_SIZE) + return -EINVAL; + + /* Start to receive blacklist mac addresses and set to FWK blacklist */ + for (i = 0; i < numOfList[0] && len_shift < u4SetBufferLen; i++) { + len_shift += NLA_ALIGN(attrlist->nla_len); + attrlist = (struct nlattr *)((UINT_8 *) pvSetBuffer + + len_shift); + if (attrlist->nla_type == + WIFI_ATTRIBUTE_ROAMING_BLACKLIST_BSSID) { + prBssDesc = scanSearchBssDescByBssid(prAdapter, + nla_data(attrlist)); + + if (prBssDesc == NULL) { + DBGLOG(REQ, ERROR, + "Cannot find the blacklist BSS=%pM\n", + nla_data(attrlist)); + continue; + } + + prBlackList = aisAddBlacklist(prAdapter, prBssDesc); + prBlackList->fgIsInFWKBlacklist = TRUE; + DBGLOG(REQ, INFO, + "Receives roaming blacklist SSID=%s addr=%pM len=%d %d\n", + prBlackList->aucSSID, prBlackList->aucBSSID, + len_shift, u4SetBufferLen); + } + } + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidExternalAuthDone(IN P_ADAPTER_T prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + P_STA_RECORD_T prStaRec = NULL; + uint8_t ucBssIndex = 0; + struct PARAM_EXTERNAL_AUTH *params; + struct MSG_SAA_EXTERNAL_AUTH_DONE *prExternalAuthMsg = NULL; + + params = (struct PARAM_EXTERNAL_AUTH *) pvSetBuffer; + ucBssIndex = params->ucBssIdx; + if (!IS_BSS_INDEX_VALID(ucBssIndex)) { + DBGLOG(REQ, ERROR, + "SAE-confirm failed with invalid BssIdx in ndev\n"); + return WLAN_STATUS_INVALID_DATA; + } + + prExternalAuthMsg = (struct MSG_SAA_EXTERNAL_AUTH_DONE *)cnmMemAlloc( + prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_SAA_EXTERNAL_AUTH_DONE)); + if (!prExternalAuthMsg) { + DBGLOG(OID, WARN, + "SAE-confirm failed to allocate Msg\n"); + return WLAN_STATUS_RESOURCES; + } + + prStaRec = cnmGetStaRecByAddress(prAdapter, + (UINT_8) NETWORK_TYPE_AIS_INDEX, + params->bssid); + if (!prStaRec) { + DBGLOG(REQ, WARN, "SAE-confirm failed with bssid:" MACSTR "\n", + params->bssid); + return WLAN_STATUS_INVALID_DATA; + } + + prExternalAuthMsg->rMsgHdr.eMsgId = MID_OID_SAA_FSM_EXTERNAL_AUTH; + prExternalAuthMsg->prStaRec = prStaRec; + prExternalAuthMsg->status = params->status; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T)prExternalAuthMsg, + MSG_SEND_METHOD_BUF); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidSetScanMacOui(IN P_ADAPTER_T prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + P_BSS_INFO_T prBssInfo = NULL; + + ASSERT(prAdapter); + ASSERT(prAdapter->prGlueInfo); + ASSERT(u4SetBufferLen == MAC_OUI_LEN); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + if (!pvSetBuffer) { + DBGLOG(REQ, WARN, "Buffer is NULL!\n"); + return WLAN_STATUS_FAILURE; + } + + kalMemCopy(prBssInfo->ucScanOui, pvSetBuffer, MAC_OUI_LEN); + prBssInfo->fgIsScanOuiSet = TRUE; + *pu4SetInfoLen = MAC_OUI_LEN; + + return WLAN_STATUS_SUCCESS; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/common/wlan_p2p.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/common/wlan_p2p.c new file mode 100644 index 0000000000000..6e2341310818f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/common/wlan_p2p.c @@ -0,0 +1,1601 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/****************************************************************************** +* C O M P I L E R F L A G S +******************************************************************************* +*/ + +/****************************************************************************** +* E X T E R N A L R E F E R E N C E S +******************************************************************************* +*/ +#include "precomp.h" +#include "gl_p2p_ioctl.h" + +/****************************************************************************** +* C O N S T A N T S +******************************************************************************* +*/ + +/****************************************************************************** +* D A T A T Y P E S +******************************************************************************* +*/ + +/****************************************************************************** +* P U B L I C D A T A +******************************************************************************* +*/ + +/****************************************************************************** +* P R I V A T E D A T A +******************************************************************************* +*/ + +/****************************************************************************** +* M A C R O S +******************************************************************************* +*/ + +/****************************************************************************** +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************* +*/ + +/****************************************************************************** +* F U N C T I O N S +******************************************************************************* +*/ +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, + IN COMMAND_TYPE eCmdType) +{ + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_8 ucCmdSeqNum; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + ASSERT(prGlueInfo); + + DEBUGFUNC("wlanoidSendSetQueryP2PCmd"); + DBGLOG(REQ, TRACE, "Command ID = 0x%08X\n", ucCID); + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + u4SetQueryInfoLen)); + + if (!prCmdInfo) { + DBGLOG(P2P, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + DBGLOG(REQ, TRACE, "ucCmdSeqNum =%d\n", ucCmdSeqNum); + + /* Setup common CMD Info Packet */ + prCmdInfo->eCmdType = eCmdType; + 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 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) +{ + return _wlanoidSendSetQueryP2PCmd(prAdapter, ucCID, fgSetQuery, fgNeedResp, fgIsOid, + pfCmdDoneHandler, pfCmdTimeoutHandler, u4SetQueryInfoLen, pucInfoBuffer, pvSetQueryBuffer, + u4SetQueryBufferLen, COMMAND_TYPE_NETWORK_IOCTL); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \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 == 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 */ + 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->ucCipher) + rCmdKey.ucAlgorithmId = prNewKey->ucCipher; + rCmdKey.ucKeyId = (UINT_8) (prNewKey->u4KeyIndex & 0xff); + rCmdKey.ucKeyLen = (UINT_8) prNewKey->u4KeyLength; + kalMemCopy(rCmdKey.aucKeyMaterial, (PUINT_8) prNewKey->aucKeyMaterial, rCmdKey.ucKeyLen); +#if (CFG_SUPPORT_TDLS == 1) + /* + * supplicant will set key before updating station & enabling the link so we need to + * backup the key information and set key when link is enabled + */ + if (TdlsexKeyHandle(prAdapter, prNewKey, NETWORK_TYPE_P2P_INDEX) == TDLS_STATUS_SUCCESS) + return WLAN_STATUS_SUCCESS; +#endif /* CFG_SUPPORT_TDLS */ + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if ((rCmdKey.ucKeyId >= 4 && rCmdKey.ucKeyId <= 5) && + (rCmdKey.ucAlgorithmId == CIPHER_SUITE_BIP)) { + P_BSS_INFO_T prBssInfo = + &(prAdapter->rWifiVar.arBssInfo[(NETWORK_TYPE_P2P_INDEX)]); + + DBGLOG(RSN, INFO, "AP mode set BIP\n"); + prBssInfo->rApPmfCfg.fgBipKeyInstalled = TRUE; + } +#endif + + return _wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_ADD_REMOVE_KEY, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + NULL, + sizeof(CMD_802_11_KEY), (PUINT_8)&rCmdKey, + pvSetBuffer, u4SetBufferLen, COMMAND_TYPE_KEY_IOCTL); +} + + +WLAN_STATUS +_wlanoidSetAddP2PTDLSKey(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, + FALSE, + nicCmdEventSetCommon, + NULL, + sizeof(CMD_802_11_KEY), (PUINT_8) &rCmdKey, pvSetBuffer, u4SetBufferLen); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request Wi-Fi Direct driver to remove keys +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetRemoveP2PKey(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + CMD_802_11_KEY rCmdKey; + P_PARAM_REMOVE_KEY_T prRemovedKey; + + DEBUGFUNC("wlanoidSetRemoveP2PKey"); + ASSERT(prAdapter); + + if (u4SetBufferLen < sizeof(PARAM_REMOVE_KEY_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + prRemovedKey = (P_PARAM_REMOVE_KEY_T) pvSetBuffer; + + /* Check bit 31: this bit should always 0 */ + if (prRemovedKey->u4KeyIndex & IS_TRANSMIT_KEY) { + /* Bit 31 should not be set */ + DBGLOG(REQ, ERROR, "invalid key index: 0x%08x\n", prRemovedKey->u4KeyIndex); + return WLAN_STATUS_INVALID_DATA; + } + + /* Check bits 8 ~ 29 should always be 0 */ + if (prRemovedKey->u4KeyIndex & BITS(8, 29)) { + /* Bit 31 should not be set */ + DBGLOG(REQ, ERROR, "invalid key index: 0x%08x\n", prRemovedKey->u4KeyIndex); + return WLAN_STATUS_INVALID_DATA; + } + + /* There should not be any key operation for P2P Device */ + if (kalP2PGetRole(prAdapter->prGlueInfo) == 0) + ; /* return WLAN_STATUS_NOT_ACCEPTED; */ + + kalMemZero((PUINT_8) &rCmdKey, sizeof(CMD_802_11_KEY)); + + rCmdKey.ucAddRemove = 0; /* remove */ + if (kalP2PGetRole(prAdapter->prGlueInfo) == 1) { /* group client */ + rCmdKey.ucIsAuthenticator = 0; + } else { /* group owner */ + rCmdKey.ucIsAuthenticator = 1; + } + kalMemCopy(rCmdKey.aucPeerAddr, (PUINT_8) prRemovedKey->arBSSID, MAC_ADDR_LEN); + rCmdKey.ucNetType = NETWORK_TYPE_P2P_INDEX; + rCmdKey.ucKeyId = (UINT_8) (prRemovedKey->u4KeyIndex & 0x000000ff); + + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_ADD_REMOVE_KEY, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + NULL, + sizeof(CMD_802_11_KEY), (PUINT_8) &rCmdKey, pvSetBuffer, u4SetBufferLen); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setting the IP address for pattern search function. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +* \return WLAN_STATUS_ADAPTER_NOT_READY +* \return WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2pNetworkAddress(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 i, j; + P_CMD_SET_NETWORK_ADDRESS_LIST prCmdNetworkAddressList; + P_PARAM_NETWORK_ADDRESS_LIST prNetworkAddressList = (P_PARAM_NETWORK_ADDRESS_LIST) pvSetBuffer; + P_PARAM_NETWORK_ADDRESS prNetworkAddress; + P_PARAM_NETWORK_ADDRESS_IP prNetAddrIp; + UINT_32 u4IpAddressCount, u4CmdSize; + + DEBUGFUNC("wlanoidSetP2pNetworkAddress"); + DBGLOG(P2P, TRACE, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 4; + + if (u4SetBufferLen < sizeof(PARAM_NETWORK_ADDRESS_LIST)) + return WLAN_STATUS_INVALID_DATA; + + *pu4SetInfoLen = 0; + u4IpAddressCount = 0; + + prNetworkAddress = prNetworkAddressList->arAddress; + for (i = 0; i < prNetworkAddressList->u4AddressCount; i++) { + if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { + u4IpAddressCount++; + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prNetworkAddress + + (ULONG) (prNetworkAddress->u2AddressLength + + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + + /* construct payload of command packet */ + u4CmdSize = OFFSET_OF(CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress) + + sizeof(IPV4_NETWORK_ADDRESS) * u4IpAddressCount; + + prCmdNetworkAddressList = (P_CMD_SET_NETWORK_ADDRESS_LIST) kalMemAlloc(u4CmdSize, VIR_MEM_TYPE); + + if (prCmdNetworkAddressList == NULL) + return WLAN_STATUS_FAILURE; + + /* fill P_CMD_SET_NETWORK_ADDRESS_LIST */ + prCmdNetworkAddressList->ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + prCmdNetworkAddressList->ucAddressCount = (UINT_8) u4IpAddressCount; + prNetworkAddress = prNetworkAddressList->arAddress; + for (i = 0, j = 0; i < prNetworkAddressList->u4AddressCount; i++) { + if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { + prNetAddrIp = (P_PARAM_NETWORK_ADDRESS_IP) prNetworkAddress->aucAddress; + + kalMemCopy(prCmdNetworkAddressList->arNetAddress[j].aucIpAddr, + &(prNetAddrIp->in_addr), sizeof(UINT_32)); + + j++; + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prNetworkAddress + + (ULONG) (prNetworkAddress->u2AddressLength + + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_IP_ADDRESS, + TRUE, + FALSE, + TRUE, + nicCmdEventSetIpAddress, + nicOidCmdTimeoutCommon, + u4CmdSize, (PUINT_8) prCmdNetworkAddressList, pvSetBuffer, u4SetBufferLen); + + kalMemFree(prCmdNetworkAddressList, VIR_MEM_TYPE, u4CmdSize); + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to query the power save profile. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryP2pPowerSaveProfile(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryP2pPowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen != 0) { + ASSERT(pvQueryBuffer); + + *(PPARAM_POWER_MODE) pvQueryBuffer = + (PARAM_POWER_MODE) (prAdapter->rWlanInfo.arPowerSaveMode[NETWORK_TYPE_P2P_INDEX].ucPsProfile); + *pu4QueryInfoLen = sizeof(PARAM_POWER_MODE); + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to set the power save profile. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2pPowerSaveProfile(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS status; + PARAM_POWER_MODE ePowerMode; + + DEBUGFUNC("wlanoidSetP2pPowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_POWER_MODE); + if (u4SetBufferLen < sizeof(PARAM_POWER_MODE)) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } else if (*(PPARAM_POWER_MODE) pvSetBuffer >= Param_PowerModeMax) { + WARNLOG(("Invalid power mode %d\n", *(PPARAM_POWER_MODE) pvSetBuffer)); + return WLAN_STATUS_INVALID_DATA; + } + + ePowerMode = *(PPARAM_POWER_MODE) pvSetBuffer; + + if (prAdapter->fgEnCtiaPowerMode) { + if (ePowerMode == Param_PowerModeCAM) { + /*Todo:: Nothing*/ + /*Todo:: Nothing*/ + } else { + /* User setting to PS mode (Param_PowerModeMAX_PSP or Param_PowerModeFast_PSP) */ + + if (prAdapter->u4CtiaPowerMode == 0) { + /* force to keep in CAM mode */ + ePowerMode = Param_PowerModeCAM; + } else if (prAdapter->u4CtiaPowerMode == 1) { + ePowerMode = Param_PowerModeMAX_PSP; + } else if (prAdapter->u4CtiaPowerMode == 2) { + ePowerMode = Param_PowerModeFast_PSP; + } + } + } + + status = nicConfigPowerSaveProfile(prAdapter, NETWORK_TYPE_P2P_INDEX, ePowerMode, TRUE); + return status; +} /* end of wlanoidSetP2pPowerSaveProfile() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to set the power save profile. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2pSetNetworkAddress(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 i, j; + P_CMD_SET_NETWORK_ADDRESS_LIST prCmdNetworkAddressList; + P_PARAM_NETWORK_ADDRESS_LIST prNetworkAddressList = (P_PARAM_NETWORK_ADDRESS_LIST) pvSetBuffer; + P_PARAM_NETWORK_ADDRESS prNetworkAddress; + P_PARAM_NETWORK_ADDRESS_IP prNetAddrIp; + UINT_32 u4IpAddressCount, u4CmdSize; + PUINT_8 pucBuf = (PUINT_8) pvSetBuffer; + + DEBUGFUNC("wlanoidSetP2pSetNetworkAddress"); + DBGLOG(P2P, TRACE, "\n"); + DBGLOG(P2P, INFO, "wlanoidSetP2pSetNetworkAddress (%d)\n", (INT_16) u4SetBufferLen); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 4; + + if (u4SetBufferLen < sizeof(PARAM_NETWORK_ADDRESS_LIST)) + return WLAN_STATUS_INVALID_DATA; + + *pu4SetInfoLen = 0; + u4IpAddressCount = 0; + + prNetworkAddress = prNetworkAddressList->arAddress; + for (i = 0; i < prNetworkAddressList->u4AddressCount; i++) { + if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { + u4IpAddressCount++; + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prNetworkAddress + + (ULONG) (prNetworkAddress->u2AddressLength + + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + + /* construct payload of command packet */ + u4CmdSize = OFFSET_OF(CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress) + + sizeof(IPV4_NETWORK_ADDRESS) * u4IpAddressCount; + + if (u4IpAddressCount == 0) + u4CmdSize = sizeof(CMD_SET_NETWORK_ADDRESS_LIST); + + prCmdNetworkAddressList = (P_CMD_SET_NETWORK_ADDRESS_LIST) kalMemAlloc(u4CmdSize, VIR_MEM_TYPE); + + if (prCmdNetworkAddressList == NULL) + return WLAN_STATUS_FAILURE; + + /* fill P_CMD_SET_NETWORK_ADDRESS_LIST */ + prCmdNetworkAddressList->ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + + /* only to set IP address to FW once ARP filter is enabled */ + if (prAdapter->fgEnArpFilter) { + prCmdNetworkAddressList->ucAddressCount = (UINT_8) u4IpAddressCount; + prNetworkAddress = prNetworkAddressList->arAddress; + + DBGLOG(P2P, INFO, "u4IpAddressCount (%u)\n", u4IpAddressCount); + for (i = 0, j = 0; i < prNetworkAddressList->u4AddressCount; i++) { + if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { + prNetAddrIp = (P_PARAM_NETWORK_ADDRESS_IP) prNetworkAddress->aucAddress; + + kalMemCopy(prCmdNetworkAddressList->arNetAddress[j].aucIpAddr, + &(prNetAddrIp->in_addr), sizeof(UINT_32)); + + j++; + + pucBuf = (PUINT_8) &prNetAddrIp->in_addr; + DBGLOG(P2P, INFO, "prNetAddrIp->in_addr:%d:%d:%d:%d\n", + (UINT_8) pucBuf[0], (UINT_8) pucBuf[1], + (UINT_8) pucBuf[2], (UINT_8) pucBuf[3]); + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prNetworkAddress + + (ULONG) (prNetworkAddress->u2AddressLength + + OFFSET_OF(PARAM_NETWORK_ADDRESS, + aucAddress))); + } + + } else { + prCmdNetworkAddressList->ucAddressCount = 0; + } + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_IP_ADDRESS, + TRUE, + FALSE, + TRUE, + nicCmdEventSetIpAddress, + nicOidCmdTimeoutCommon, + u4CmdSize, (PUINT_8) prCmdNetworkAddressList, pvSetBuffer, u4SetBufferLen); + + kalMemFree(prCmdNetworkAddressList, VIR_MEM_TYPE, u4CmdSize); + return rStatus; +} /* end of wlanoidSetP2pSetNetworkAddress() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set Multicast Address List. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2PMulticastList(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + CMD_MAC_MCAST_ADDR rCmdMacMcastAddr; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* The data must be a multiple of the Ethernet address size. */ + if ((u4SetBufferLen % MAC_ADDR_LEN)) { + DBGLOG(REQ, WARN, "Invalid MC list length %u\n", u4SetBufferLen); + + *pu4SetInfoLen = (((u4SetBufferLen + MAC_ADDR_LEN) - 1) / MAC_ADDR_LEN) * MAC_ADDR_LEN; + + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = u4SetBufferLen; + + /* Verify if we can support so many multicast addresses. */ + if ((u4SetBufferLen / MAC_ADDR_LEN) > MAX_NUM_GROUP_ADDR) { + DBGLOG(REQ, WARN, "Too many MC addresses\n"); + + return WLAN_STATUS_MULTICAST_FULL; + } + + /* NOTE(Kevin): Windows may set u4SetBufferLen == 0 && + * pvSetBuffer == NULL to clear exist Multicast List. + */ + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, "Fail in set multicast list! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + rCmdMacMcastAddr.u4NumOfGroupAddr = u4SetBufferLen / MAC_ADDR_LEN; + rCmdMacMcastAddr.ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + kalMemCopy(rCmdMacMcastAddr.arAddress, pvSetBuffer, u4SetBufferLen); + + /* This CMD response is no need to complete the OID. Or the event would unsync. */ + return wlanoidSendSetQueryP2PCmd(prAdapter, CMD_ID_MAC_MCAST_ADDR, TRUE, FALSE, FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_MAC_MCAST_ADDR), + (PUINT_8) &rCmdMacMcastAddr, pvSetBuffer, u4SetBufferLen); + +} /* end of wlanoidSetP2PMulticastList() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to send GAS frame for P2P Service Discovery Request +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendP2PSDRequest(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (u4SetBufferLen < sizeof(PARAM_P2P_SEND_SD_REQUEST)) { + *pu4SetInfoLen = sizeof(PARAM_P2P_SEND_SD_REQUEST); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } +/* rWlanStatus = p2pFsmRunEventSDRequest(prAdapter, (P_PARAM_P2P_SEND_SD_REQUEST)pvSetBuffer); */ + + return rWlanStatus; +} /* end of wlanoidSendP2PSDRequest() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to send GAS frame for P2P Service Discovery Response +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendP2PSDResponse(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (u4SetBufferLen < sizeof(PARAM_P2P_SEND_SD_RESPONSE)) { + *pu4SetInfoLen = sizeof(PARAM_P2P_SEND_SD_RESPONSE); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } +/* rWlanStatus = p2pFsmRunEventSDResponse(prAdapter, (P_PARAM_P2P_SEND_SD_RESPONSE)pvSetBuffer); */ + + return rWlanStatus; +} /* end of wlanoidGetP2PSDRequest() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get GAS frame for P2P Service Discovery Request +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidGetP2PSDRequest(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + /*PUINT_8 pucPacketBuffer = NULL, pucTA = NULL;*/ +/* PUINT_8 pucChannelNum = NULL; */ + /*PUINT_16 pu2PacketLength = NULL;*/ + /*P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T) NULL;*/ + /*UINT_8 ucVersionNum = 0;*/ +/* UINT_8 ucChannelNum = 0, ucSeqNum = 0; */ + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(PARAM_P2P_GET_SD_REQUEST)) { + *pu4QueryInfoLen = sizeof(PARAM_P2P_GET_SD_REQUEST); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + DBGLOG(P2P, TRACE, "Get Service Discovery Request\n"); +#if 0 + ucVersionNum = p2pFuncGetVersionNumOfSD(prAdapter); + if (ucVersionNum == 0) { + P_PARAM_P2P_GET_SD_REQUEST prP2pGetSdReq = (P_PARAM_P2P_GET_SD_REQUEST) pvQueryBuffer; + + pucPacketBuffer = prP2pGetSdReq->aucPacketContent; + pu2PacketLength = &prP2pGetSdReq->u2PacketLength; + pucTA = &prP2pGetSdReq->rTransmitterAddr; + } else { + P_PARAM_P2P_GET_SD_REQUEST_EX prP2pGetSdReqEx = (P_PARAM_P2P_GET_SD_REQUEST_EX) NULL; + + prP2pGetSdReqEx = (P_PARAM_P2P_GET_SD_REQUEST) pvQueryBuffer; + pucPacketBuffer = prP2pGetSdReqEx->aucPacketContent; + pu2PacketLength = &prP2pGetSdReqEx->u2PacketLength; + pucTA = &prP2pGetSdReqEx->rTransmitterAddr; + pucChannelNum = &prP2pGetSdReqEx->ucChannelNum; + ucSeqNum = prP2pGetSdReqEx->ucSeqNum; + } + + rWlanStatus = p2pFuncGetServiceDiscoveryFrame(prAdapter, + pucPacketBuffer, + (u4QueryBufferLen - sizeof(PARAM_P2P_GET_SD_REQUEST)), + (PUINT_32) pu2PacketLength, pucChannelNum, ucSeqNum); +#else + *pu4QueryInfoLen = 0; + return rWlanStatus; +#endif + /* + * prWlanHdr = (P_WLAN_MAC_HEADER_T) pucPacketBuffer; + * + * kalMemCopy(pucTA, prWlanHdr->aucAddr2, MAC_ADDR_LEN); + * + * if (pu4QueryInfoLen) { + * if (ucVersionNum == 0) + * *pu4QueryInfoLen = (UINT_32) (sizeof(PARAM_P2P_GET_SD_REQUEST) + (*pu2PacketLength)); + * else + * *pu4QueryInfoLen = (UINT_32) (sizeof(PARAM_P2P_GET_SD_REQUEST_EX) + (*pu2PacketLength)); + * + * } + * + * return rWlanStatus; + */ +} /* end of wlanoidGetP2PSDRequest() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get GAS frame for P2P Service Discovery Response +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidGetP2PSDResponse(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + /*P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T) NULL;*/ + /* UINT_8 ucSeqNum = 0, */ + /*UINT_8 ucVersionNum = 0;*/ + /*PUINT_8 pucPacketContent = (PUINT_8) NULL, pucTA = (PUINT_8) NULL;*/ + /*PUINT_16 pu2PacketLength = (PUINT_16) NULL;*/ + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(PARAM_P2P_GET_SD_RESPONSE)) { + *pu4QueryInfoLen = sizeof(PARAM_P2P_GET_SD_RESPONSE); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + DBGLOG(P2P, TRACE, "Get Service Discovery Response\n"); + +#if 0 + ucVersionNum = p2pFuncGetVersionNumOfSD(prAdapter); + if (ucVersionNum == 0) { + P_PARAM_P2P_GET_SD_RESPONSE prP2pGetSdRsp = (P_PARAM_P2P_GET_SD_RESPONSE) NULL; + + prP2pGetSdRsp = (P_PARAM_P2P_GET_SD_REQUEST) pvQueryBuffer; + pucPacketContent = prP2pGetSdRsp->aucPacketContent; + pucTA = &prP2pGetSdRsp->rTransmitterAddr; + pu2PacketLength = &prP2pGetSdRsp->u2PacketLength; + } else { + P_PARAM_P2P_GET_SD_RESPONSE_EX prP2pGetSdRspEx = (P_PARAM_P2P_GET_SD_RESPONSE_EX) NULL; + + prP2pGetSdRspEx = (P_PARAM_P2P_GET_SD_RESPONSE_EX) pvQueryBuffer; + pucPacketContent = prP2pGetSdRspEx->aucPacketContent; + pucTA = &prP2pGetSdRspEx->rTransmitterAddr; + pu2PacketLength = &prP2pGetSdRspEx->u2PacketLength; + ucSeqNum = prP2pGetSdRspEx->ucSeqNum; + } + +/* rWlanStatus = p2pFuncGetServiceDiscoveryFrame(prAdapter, */ +/* pucPacketContent, */ +/* (u4QueryBufferLen - sizeof(PARAM_P2P_GET_SD_RESPONSE)), */ +/* (PUINT_32)pu2PacketLength, */ +/* NULL, */ +/* ucSeqNum); */ +#else + *pu4QueryInfoLen = 0; + return rWlanStatus; +#endif + /* + * prWlanHdr = (P_WLAN_MAC_HEADER_T) pucPacketContent; + * + * kalMemCopy(pucTA, prWlanHdr->aucAddr2, MAC_ADDR_LEN); + * + * if (pu4QueryInfoLen) { + * if (ucVersionNum == 0) + * *pu4QueryInfoLen = (UINT_32) (sizeof(PARAM_P2P_GET_SD_RESPONSE) + *pu2PacketLength); + * else + * *pu4QueryInfoLen = (UINT_32) (sizeof(PARAM_P2P_GET_SD_RESPONSE_EX) + *pu2PacketLength); + * } + * + * return rWlanStatus; + */ +} /* end of wlanoidGetP2PSDResponse() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to terminate P2P Service Discovery Phase +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2PTerminateSDPhase(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_PARAM_P2P_TERMINATE_SD_PHASE prP2pTerminateSD = (P_PARAM_P2P_TERMINATE_SD_PHASE) NULL; + UINT_8 aucNullAddr[] = NULL_MAC_ADDR; + + do { + if ((prAdapter == NULL) || (pu4SetInfoLen == NULL)) + break; + + if ((u4SetBufferLen) && (pvSetBuffer == NULL)) + break; + + if (u4SetBufferLen < sizeof(PARAM_P2P_TERMINATE_SD_PHASE)) { + *pu4SetInfoLen = sizeof(PARAM_P2P_TERMINATE_SD_PHASE); + rWlanStatus = WLAN_STATUS_BUFFER_TOO_SHORT; + break; + } + + prP2pTerminateSD = (P_PARAM_P2P_TERMINATE_SD_PHASE) pvSetBuffer; + + if (EQUAL_MAC_ADDR(prP2pTerminateSD->rPeerAddr, aucNullAddr)) { + DBGLOG(P2P, TRACE, "Service Discovery Version 2.0\n"); +/* p2pFuncSetVersionNumOfSD(prAdapter, 2); */ + } + /* rWlanStatus = p2pFsmRunEventSDAbort(prAdapter); */ + + } while (FALSE); + + return rWlanStatus; +} /* end of wlanoidSetP2PTerminateSDPhase() */ + +#if CFG_SUPPORT_ANTI_PIRACY +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetSecCheckRequest(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SEC_CHECK, + FALSE, + TRUE, + TRUE, + NULL, + nicOidCmdTimeoutCommon, + u4SetBufferLen, (PUINT_8) pvSetBuffer, pvSetBuffer, u4SetBufferLen); + +} /* end of wlanoidSetSecCheckRequest() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidGetSecCheckResponse(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + /* P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T)NULL; */ + P_GLUE_INFO_T prGlueInfo; + + prGlueInfo = prAdapter->prGlueInfo; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen > 256) + u4QueryBufferLen = 256; + + *pu4QueryInfoLen = u4QueryBufferLen; + +#if DBG + DBGLOG_MEM8(SEC, LOUD, prGlueInfo->prP2PInfo->aucSecCheckRsp, u4QueryBufferLen); +#endif + kalMemCopy((PUINT_8) (pvQueryBuffer + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer)), + prGlueInfo->prP2PInfo->aucSecCheckRsp, u4QueryBufferLen); + + return rWlanStatus; +} /* end of wlanoidGetSecCheckResponse() */ +#endif + +WLAN_STATUS +wlanoidSetNoaParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T prNoaParam; + CMD_CUSTOM_NOA_PARAM_STRUCT_T rCmdNoaParam; + + DEBUGFUNC("wlanoidSetNoaParam"); + DBGLOG(P2P, TRACE, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_NOA_PARAM_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_NOA_PARAM_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prNoaParam = (P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T) pvSetBuffer; + + kalMemZero(&rCmdNoaParam, sizeof(CMD_CUSTOM_NOA_PARAM_STRUCT_T)); + rCmdNoaParam.u4NoaDurationMs = prNoaParam->u4NoaDurationMs; + rCmdNoaParam.u4NoaIntervalMs = prNoaParam->u4NoaIntervalMs; + rCmdNoaParam.u4NoaCount = prNoaParam->u4NoaCount; + +#if 0 + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_NOA_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_NOA_PARAM_STRUCT_T), + (PUINT_8) &rCmdNoaParam, pvSetBuffer, u4SetBufferLen); +#else + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_NOA_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_NOA_PARAM_STRUCT_T), + (PUINT_8) &rCmdNoaParam, pvSetBuffer, u4SetBufferLen); + +#endif + +} + +WLAN_STATUS +wlanoidSetOppPsParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T prOppPsParam; + CMD_CUSTOM_OPPPS_PARAM_STRUCT_T rCmdOppPsParam; + + DEBUGFUNC("wlanoidSetOppPsParam"); + DBGLOG(P2P, TRACE, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prOppPsParam = (P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T) pvSetBuffer; + + kalMemZero(&rCmdOppPsParam, sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T)); + rCmdOppPsParam.u4CTwindowMs = prOppPsParam->u4CTwindowMs; + +#if 0 + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_OPPPS_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T), + (PUINT_8) &rCmdOppPsParam, pvSetBuffer, u4SetBufferLen); +#else + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_OPPPS_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T), + (PUINT_8) &rCmdOppPsParam, pvSetBuffer, u4SetBufferLen); + +#endif + +} + +WLAN_STATUS +wlanoidSetUApsdParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T prUapsdParam; + CMD_CUSTOM_UAPSD_PARAM_STRUCT_T rCmdUapsdParam; + P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo; + P_BSS_INFO_T prBssInfo; + + DEBUGFUNC("wlanoidSetUApsdParam"); + DBGLOG(P2P, TRACE, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + + prUapsdParam = (P_PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T) pvSetBuffer; + + kalMemZero(&rCmdUapsdParam, sizeof(CMD_CUSTOM_UAPSD_PARAM_STRUCT_T)); + rCmdUapsdParam.fgEnAPSD = prUapsdParam->fgEnAPSD; + prAdapter->rWifiVar.fgSupportUAPSD = prUapsdParam->fgEnAPSD; + + rCmdUapsdParam.fgEnAPSD_AcBe = prUapsdParam->fgEnAPSD_AcBe; + rCmdUapsdParam.fgEnAPSD_AcBk = prUapsdParam->fgEnAPSD_AcBk; + rCmdUapsdParam.fgEnAPSD_AcVo = prUapsdParam->fgEnAPSD_AcVo; + rCmdUapsdParam.fgEnAPSD_AcVi = prUapsdParam->fgEnAPSD_AcVi; + prPmProfSetupInfo->ucBmpDeliveryAC = + ((prUapsdParam->fgEnAPSD_AcBe << 0) | + (prUapsdParam->fgEnAPSD_AcBk << 1) | + (prUapsdParam->fgEnAPSD_AcVi << 2) | (prUapsdParam->fgEnAPSD_AcVo << 3)); + prPmProfSetupInfo->ucBmpTriggerAC = + ((prUapsdParam->fgEnAPSD_AcBe << 0) | + (prUapsdParam->fgEnAPSD_AcBk << 1) | + (prUapsdParam->fgEnAPSD_AcVi << 2) | (prUapsdParam->fgEnAPSD_AcVo << 3)); + + rCmdUapsdParam.ucMaxSpLen = prUapsdParam->ucMaxSpLen; + prPmProfSetupInfo->ucUapsdSp = prUapsdParam->ucMaxSpLen; + + DBGLOG(P2P, INFO, "wlanoidSetUApsdParam EnAPSD[%d] Be[%d] Bk[%d] Vo[%d] Vi[%d] SPLen[%d]\n", + rCmdUapsdParam.fgEnAPSD, rCmdUapsdParam.fgEnAPSD_AcBe, rCmdUapsdParam.fgEnAPSD_AcBk, + rCmdUapsdParam.fgEnAPSD_AcVo, rCmdUapsdParam.fgEnAPSD_AcVi, rCmdUapsdParam.ucMaxSpLen); + +#if 0 + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_UAPSD_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_UAPSD_PARAM_STRUCT_T), + (PUINT_8) &rCmdUapsdParam, pvSetBuffer, u4SetBufferLen); +#else + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_UAPSD_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_UAPSD_PARAM_STRUCT_T), + (PUINT_8) &rCmdUapsdParam, pvSetBuffer, u4SetBufferLen); + +#endif +} + +WLAN_STATUS +wlanoidQueryP2pOpChannel(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + + WLAN_STATUS rResult = WLAN_STATUS_FAILURE; +/* PUINT_8 pucOpChnl = (PUINT_8)pvQueryBuffer; */ + + do { + if ((prAdapter == NULL) || (pu4QueryInfoLen == NULL)) + break; + + if ((u4QueryBufferLen) && (pvQueryBuffer == NULL)) + break; + + if (u4QueryBufferLen < sizeof(UINT_8)) { + *pu4QueryInfoLen = sizeof(UINT_8); + rResult = WLAN_STATUS_BUFFER_TOO_SHORT; + break; + } +#if 0 + if (!p2pFuncGetCurrentOpChnl(prAdapter, pucOpChnl)) { + rResult = WLAN_STATUS_INVALID_DATA; + break; + } +#else + rResult = WLAN_STATUS_INVALID_DATA; + break; +#endif + /* + *pu4QueryInfoLen = sizeof(UINT_8); + rResult = WLAN_STATUS_SUCCESS; + */ + + } while (FALSE); + + return rResult; +} /* wlanoidQueryP2pOpChannel */ + +WLAN_STATUS +wlanoidQueryP2pVersion(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + WLAN_STATUS rResult = WLAN_STATUS_FAILURE; +/* PUINT_8 pucVersionNum = (PUINT_8)pvQueryBuffer; */ + + do { + if ((prAdapter == NULL) || (pu4QueryInfoLen == NULL)) + break; + + if ((u4QueryBufferLen) && (pvQueryBuffer == NULL)) + break; + + if (u4QueryBufferLen < sizeof(UINT_8)) { + *pu4QueryInfoLen = sizeof(UINT_8); + rResult = WLAN_STATUS_BUFFER_TOO_SHORT; + break; + } + + } while (FALSE); + + return rResult; +} /* wlanoidQueryP2pVersion */ + +WLAN_STATUS +wlanoidSetP2pSupplicantVersion(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rResult = WLAN_STATUS_FAILURE; + UINT_8 ucVersionNum; + + do { + if ((prAdapter == NULL) || (pu4SetInfoLen == NULL)) { + + rResult = WLAN_STATUS_INVALID_DATA; + break; + } + + if ((u4SetBufferLen) && (pvSetBuffer == NULL)) { + rResult = WLAN_STATUS_INVALID_DATA; + break; + } + + *pu4SetInfoLen = sizeof(UINT_8); + + if (u4SetBufferLen < sizeof(UINT_8)) { + rResult = WLAN_STATUS_INVALID_LENGTH; + break; + } + + ucVersionNum = *((PUINT_8) pvSetBuffer); + + rResult = WLAN_STATUS_SUCCESS; + } while (FALSE); + + return rResult; +} /* wlanoidSetP2pSupplicantVersion */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to set the WPS mode. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2pWPSmode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS status; + UINT_32 u4IsWPSmode = 0; + + DEBUGFUNC("wlanoidSetP2pWPSmode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (pvSetBuffer) + u4IsWPSmode = *(PUINT_32) pvSetBuffer; + else + u4IsWPSmode = 0; + + if (u4IsWPSmode) + prAdapter->rWifiVar.prP2pFsmInfo->fgIsWPSMode = 1; + else + prAdapter->rWifiVar.prP2pFsmInfo->fgIsWPSMode = 0; + + status = nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); + + return status; +} /* end of wlanoidSetP2pWPSmode() */ + +#if CFG_SUPPORT_P2P_RSSI_QUERY +WLAN_STATUS +wlanoidQueryP2pRssi(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryP2pRssi"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_RSSI); + + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(REQ, WARN, "Too short length %u\n", u4QueryBufferLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + if (prAdapter->fgIsP2pLinkQualityValid == TRUE && + (kalGetTimeTick() - prAdapter->rP2pLinkQualityUpdateTime) <= CFG_LINK_QUALITY_VALID_PERIOD) { + PARAM_RSSI rRssi; + + rRssi = (PARAM_RSSI) prAdapter->rP2pLinkQuality.cRssi; /* ranged from (-128 ~ 30) in unit of dBm */ + + if (rRssi > PARAM_WHQL_RSSI_MAX_DBM) + rRssi = PARAM_WHQL_RSSI_MAX_DBM; + else if (rRssi < PARAM_WHQL_RSSI_MIN_DBM) + rRssi = PARAM_WHQL_RSSI_MIN_DBM; + + kalMemCopy(pvQueryBuffer, &rRssi, sizeof(PARAM_RSSI)); + return WLAN_STATUS_SUCCESS; + } +#ifdef LINUX + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryLinkQuality, + nicOidCmdTimeoutCommon, + *pu4QueryInfoLen, pvQueryBuffer, pvQueryBuffer, u4QueryBufferLen); +#else + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryLinkQuality, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + +#endif +} /* wlanoidQueryP2pRssi */ +#endif + +WLAN_STATUS +wlanoidAbortP2pScan(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen) { + + DBGLOG(P2P, INFO, "wlanoidAbortP2pScan\n"); + + ASSERT(prAdapter); + + p2pFsmRunEventScanAbort(prAdapter, NULL); + + return WLAN_STATUS_SUCCESS; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/aaa_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/aaa_fsm.c new file mode 100644 index 0000000000000..f3670a09d9e64 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/aaa_fsm.c @@ -0,0 +1,1237 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send Event to AIS/BOW/P2P +* +* @param[in] rJoinStatus To indicate JOIN success or failure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] prSwRfb Pointer to the SW_RFB_T + +* @return none +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS aaaFsmSendEventJoinComplete(WLAN_STATUS rJoinStatus, P_STA_RECORD_T prStaRec, P_SW_RFB_T prSwRfb) +{ + P_MSG_SAA_JOIN_COMP_T prJoinCompMsg; + + ASSERT(prStaRec); + + prJoinCompMsg = cnmMemAlloc(RAM_TYPE_TCM, sizeof(MSG_SAA_JOIN_COMP_T)); + if (!prJoinCompMsg) + return WLAN_STATUS_RESOURCES; + + if (IS_STA_IN_AIS(prStaRec)) + prJoinCompMsg->rMsgHdr.eMsgId = MID_SAA_AIS_JOIN_COMPLETE; + else if (IS_STA_IN_P2P(prStaRec)) + prJoinCompMsg->rMsgHdr.eMsgId = MID_SAA_P2P_JOIN_COMPLETE; + else if (IS_STA_IN_BOW(prStaRec)) + prJoinCompMsg->rMsgHdr.eMsgId = MID_SAA_BOW_JOIN_COMPLETE; + else + ASSERT(0); + + prJoinCompMsg->rJoinStatus = rJoinStatus; + prJoinCompMsg->prStaRec = prStaRec; + prJoinCompMsg->prSwRfb = prSwRfb; + + mboxSendMsg(MBOX_ID_0, (P_MSG_HDR_T) prJoinCompMsg, MSG_SEND_METHOD_BUF); + + return WLAN_STATUS_SUCCESS; + +} /* end of saaFsmSendEventJoinComplete() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Start Event to AAA FSM. +* +* @param[in] prMsgHdr Message of Join Request for a particular STA. +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID aaaFsmRunEventStart(IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_SAA_JOIN_REQ_T prJoinReqMsg; + P_STA_RECORD_T prStaRec; + P_AIS_BSS_INFO_T prAisBssInfo; + + ASSERT(prMsgHdr); + + prJoinReqMsg = (P_MSG_SAA_JOIN_REQ_T) prMsgHdr; + prStaRec = prJoinReqMsg->prStaRec; + + ASSERT(prStaRec); + + DBGLOG(SAA, LOUD, "EVENT-START: Trigger SAA FSM\n"); + + cnmMemFree(prMsgHdr); + + /* 4 <1> Validation of SAA Start Event */ + if (!IS_AP_STA(prStaRec->eStaType)) { + + DBGLOG(SAA, ERROR, "EVENT-START: STA Type - %d was not supported.\n", prStaRec->eStaType); + + /* Ignore the return value because don't care the prSwRfb */ + saaFsmSendEventJoinComplete(WLAN_STATUS_FAILURE, prStaRec, NULL); + + return; + } + /* 4 <2> The previous JOIN process is not completed ? */ + if (prStaRec->eAuthAssocState != AA_STATE_IDLE) { + DBGLOG(SAA, ERROR, "EVENT-START: Reentry of SAA Module.\n"); + prStaRec->eAuthAssocState = AA_STATE_IDLE; + } + /* 4 <3> Reset Status Code and Time */ + /* Update Station Record - Status/Reason Code */ + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + + /* Update the record join time. */ + GET_CURRENT_SYSTIME(&prStaRec->rLastJoinTime); + + prStaRec->ucTxAuthAssocRetryCount = 0; + + if (prStaRec->prChallengeText) { + cnmMemFree(prStaRec->prChallengeText); + prStaRec->prChallengeText = (P_IE_CHALLENGE_TEXT_T) NULL; + } + + cnmTimerStopTimer(&prStaRec->rTxReqDoneOrRxRespTimer); + + prStaRec->ucStaState = STA_STATE_1; + + /* Trigger SAA MODULE */ + saaFsmSteps(prStaRec, SAA_STATE_SEND_AUTH1, (P_SW_RFB_T) NULL); + +} /* end of saaFsmRunEventStart() */ +#endif + +#if CFG_SUPPORT_AAA +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will process the Rx Auth Request Frame and then +* trigger AAA FSM. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to the SW_RFB_T structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aaaFsmRunEventRxAuth(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + UINT_16 u2StatusCode; + BOOLEAN fgReplyAuth = FALSE; + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex; + P_WLAN_AUTH_FRAME_T prAuthFrame; + + ASSERT(prAdapter); + + do { + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; + + DBGLOG(AAA, INFO, + "SA: " MACSTR ", bssid: " MACSTR ", %d %d sta idx: %d\n", + MAC2STR(prAuthFrame->aucSrcAddr), + MAC2STR(prAuthFrame->aucBSSID), + prAuthFrame->u2AuthTransSeqNo, + prAuthFrame->u2AuthAlgNum, + prSwRfb->ucStaRecIdx); + + /* 4 <1> Check P2P network conditions */ +#if CFG_ENABLE_WIFI_DIRECT + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + if (!prAdapter->fgIsP2PRegistered) + goto bow_proc; + + if (prBssInfo && prBssInfo->fgIsNetActive) { + /* 4 <1.1> Validate Auth Frame by Auth Algorithm/Transation Seq */ + if (authProcessRxAuthFrame(prAdapter, + prSwRfb, + prBssInfo, + &u2StatusCode) == WLAN_STATUS_SUCCESS) { + + if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + DBGLOG(AAA, TRACE, + "process RxAuth status success\n"); + /* 4 <1.2> Validate Auth Frame for Network Specific Conditions */ + fgReplyAuth = p2pFuncValidateAuth(prAdapter, + prSwRfb, &prStaRec, &u2StatusCode); +#if CFG_SUPPORT_802_11W + /* AP PMF, if PMF connection, ignore Rx auth */ + /* Certification 4.3.3.4 */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(AAA, INFO, "Drop RxAuth\n"); + return; + } +#endif + } else { + fgReplyAuth = TRUE; + } + eNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + break; + } + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +bow_proc: + + /* 4 <2> Check BOW network conditions */ +#if CFG_ENABLE_BT_OVER_WIFI + { + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + + if ((prBssInfo->fgIsNetActive) && (prBssInfo->eCurrentOPMode == OP_MODE_BOW)) { + + /* 4 <2.1> Validate Auth Frame by Auth Algorithm/Transation Seq */ + /* Check if for this BSSID */ + if (authProcessRxAuth1Frame(prAdapter, + prSwRfb, + prBssInfo->aucBSSID, + AUTH_ALGORITHM_NUM_OPEN_SYSTEM, + AUTH_TRANSACTION_SEQ_1, &u2StatusCode) == WLAN_STATUS_SUCCESS) { + + if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + /* 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 (fgReplyAuth) { + + /* 4 <3> Update STA_RECORD_T before reply Auth */ + if (prStaRec) { + + /* Update RCPI */ + prStaRec->ucRCPI = prSwRfb->prHifRxHdr->ucRcpi; + + 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 Status/Reason Code */ + prStaRec->u2StatusCode = u2StatusCode; + + prStaRec->ucAuthAlgNum = prAuthFrame->u2AuthAlgNum; + } else { + /* NOTE(Kevin): We should have STA_RECORD_T if the status code was successful */ + ASSERT(!(u2StatusCode == STATUS_CODE_SUCCESSFUL)); + } + + if (prBssInfo->u4RsnSelectedAKMSuite == + RSN_AKM_SUITE_SAE) { + kalP2PIndicateRxMgmtFrame( + prAdapter->prGlueInfo, + prSwRfb); + DBGLOG(AAA, INFO, "Forward RxAuth\n"); + return; + } + + /* 4 <4> Reply Auth_2 Frame */ + authSendAuthFrame(prAdapter, prStaRec, eNetTypeIndex, prSwRfb, AUTH_TRANSACTION_SEQ_2, u2StatusCode); + + } else { + if (prStaRec) + cnmStaRecFree(prAdapter, prStaRec, FALSE); + } + +} /* 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; + BOOLEAN fgSendSAQ = FALSE; + + ASSERT(prAdapter); + + do { + + /* 4 <1> Check if we have the STA_RECORD_T for incoming Assoc Req */ + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + /* We should have the corresponding Sta Record. */ + if ((!prStaRec) || (!prStaRec->fgIsInUse)) { + ASSERT(0); /* Only for debug phase */ + break; + } + + if (!IS_CLIENT_STA(prStaRec)) + break; + + if (prStaRec->ucStaState == STA_STATE_3) { + /* Do Reassocation */ + } else if ((prStaRec->ucStaState == STA_STATE_2) && + (prStaRec->eAuthAssocState == AAA_STATE_SEND_AUTH2)) { + /* Normal case */ + } else { + DBGLOG(AAA, INFO, "Previous AuthAssocState (%d) != SEND_AUTH2, ucStaState:%d.\n", + prStaRec->eAuthAssocState, + prStaRec->ucStaState); + /* TODO: Why assoc req event is faster than tx done of auth */ + if (prStaRec->eAuthAssocState != AAA_STATE_SEND_AUTH2) + break; + } + + /* update RCPI */ + prStaRec->ucRCPI = prSwRfb->prHifRxHdr->ucRcpi; + + /* 4 <2> Check P2P network conditions */ +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) { + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + if (prBssInfo->fgIsNetActive) { + + /* 4 <2.1> Validate Assoc Req Frame and get Status Code */ + /* Check if for this BSSID */ + if (WLAN_STATUS_SUCCESS == + assocProcessRxAssocReqFrame(prAdapter, prSwRfb, &u2StatusCode)) { + + if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + /* 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) && (prBssInfo->eCurrentOPMode == OP_MODE_BOW)) { + + /* 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 (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + + /* 4 <3.2> Validate Auth Frame for Network Specific Conditions */ + fgReplyAssocResp = + bowValidateAssocReq(prAdapter, prSwRfb, &u2StatusCode); + + } else { + + fgReplyAssocResp = TRUE; + } + + /* TODO(Kevin): Allocate a STA_RECORD_T for new client */ + break; + } + } + } +#endif /* CFG_ENABLE_BT_OVER_WIFI */ + + return WLAN_STATUS_SUCCESS; /* To release the SW_RFB_T */ + } while (FALSE); + + /* 4 <4> Update STA_RECORD_T and reply Assoc Resp Frame */ + if (fgReplyAssocResp) { + UINT_16 u2IELength; + PUINT_8 pucIE; + + if ((((P_WLAN_ASSOC_REQ_FRAME_T) (prSwRfb->pvHeader))->u2FrameCtrl & MASK_FRAME_TYPE) == + MAC_FRAME_REASSOC_REQ) { + + u2IELength = prSwRfb->u2PacketLen - + (UINT_16) OFFSET_OF(WLAN_REASSOC_REQ_FRAME_T, aucInfoElem[0]); + + pucIE = ((P_WLAN_REASSOC_REQ_FRAME_T) (prSwRfb->pvHeader))->aucInfoElem; + } else { + u2IELength = prSwRfb->u2PacketLen - (UINT_16) OFFSET_OF(WLAN_ASSOC_REQ_FRAME_T, aucInfoElem[0]); + + pucIE = ((P_WLAN_ASSOC_REQ_FRAME_T) (prSwRfb->pvHeader))->aucInfoElem; + } + + rlmProcessAssocReq(prAdapter, prSwRfb, pucIE, u2IELength); + + /* 4 <4.1> Assign Association ID */ + if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) { + if (p2pRunEventAAAComplete(prAdapter, prStaRec) == WLAN_STATUS_SUCCESS) { + prStaRec->u2AssocId = bssAssignAssocID(prStaRec); + /* prStaRec->eAuthAssocState = AA_STATE_IDLE; */ + prStaRec->eAuthAssocState = AAA_STATE_SEND_ASSOC2;/* NOTE(Kevin): for TX done */ + + /* NOTE(Kevin): Method A: Change to STATE_3 before handle TX Done */ + /* cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); */ + } else { + /* Client List FULL. */ + u2StatusCode = STATUS_CODE_REQ_DECLINED; + + prStaRec->u2AssocId = 0; /* Invalid Association ID */ + + /* If (Re)association fail, the peer can try Association w/o Auth immediately */ + prStaRec->eAuthAssocState = AAA_STATE_SEND_AUTH2; + + /* NOTE(Kevin): Better to change state here, not at TX Done */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + } + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + if (IS_STA_IN_BOW(prStaRec)) { + /* if (bowRunEventAAAComplete(prAdapter, prStaRec) == WLAN_STATUS_SUCCESS) { */ + prStaRec->u2AssocId = bssAssignAssocID(prStaRec); + prStaRec->eAuthAssocState = AAA_STATE_SEND_ASSOC2; /* NOTE(Kevin): for TX done */ + + /* NOTE(Kevin): Method A: Change to STATE_3 before handle TX Done */ + /* cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); */ + } +#if 0 + else { + /* Client List FULL. */ + u2StatusCode = STATUS_CODE_REQ_DECLINED; + + prStaRec->u2AssocId = 0; /* Invalid Association ID */ + + /* If (Re)association fail, the peer can try Association w/o Auth immediately */ + prStaRec->eAuthAssocState = AAA_STATE_SEND_AUTH2; + + /* NOTE(Kevin): Better to change state here, not at TX Done */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + } + } +#endif +#endif + } else { +#if CFG_SUPPORT_802_11W + /* AP PMF */ + /* don't change state, just send assoc resp (NO need TX done, TIE + code30 + * ) and then SAQ + */ + if (u2StatusCode == STATUS_CODE_ASSOC_REJECTED_TEMPORARILY) { + DBGLOG(AAA, INFO, "AP send SAQ\n"); + fgSendSAQ = TRUE; + } else +#endif + { + prStaRec->u2AssocId = 0; /* Invalid Association ID */ + + /* If (Re)association fail, + * remove sta record and use class error to handle sta + */ + prStaRec->eAuthAssocState = AA_STATE_IDLE; + /* Remove from client list if it was previously associated */ + if ((prStaRec->ucStaState > STA_STATE_1) + && prAdapter->fgIsP2PRegistered + && (IS_STA_IN_P2P(prStaRec))) { + P_BSS_INFO_T prBssInfo = NULL; + + prBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, + NETWORK_TYPE_P2P_INDEX); + if (prBssInfo) { + DBGLOG(AAA, INFO, "Remove client!\n"); + bssRemoveStaRecFromClientList(prAdapter, + prBssInfo, prStaRec); + } + } + + /* 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); + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if (fgSendSAQ) { + /* if PMF connection, and return code 30, send SAQ */ + rsnApStartSaQuery(prAdapter, prStaRec); + } +#endif + +} + +return WLAN_STATUS_SUCCESS; + +} /* end of aaaFsmRunEventRxAssoc() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle TxDone(Auth2/AssocReq) Event of AAA FSM. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prMsduInfo Pointer to the MSDU_INFO_T. +* @param[in] rTxDoneStatus Return TX status of the Auth1/Auth3/AssocReq frame. +* +* @retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +aaaFsmRunEventTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + DBGLOG(AAA, LOUD, "EVENT-TX DONE: Current Time = %lu\n", (unsigned long)kalGetTimeTick()); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if ((!prStaRec) || (!prStaRec->fgIsInUse)) { + DBGLOG(AAA, INFO, "EVENT-TX DONE: Invalid StaRec"); + return WLAN_STATUS_SUCCESS; /* For the case of replying ERROR STATUS CODE */ + } + + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + DBGLOG(AAA, INFO, "TX DONE status: %d, AuthAssocState: %d, SeqNo: %d\n", + rTxDoneStatus, prStaRec->eAuthAssocState, + prMsduInfo->ucTxSeqNum); + + switch (prStaRec->eAuthAssocState) { + case AAA_STATE_SEND_AUTH2: + { + /* Strictly check the outgoing frame is matched with current AA STATE */ + if (authCheckTxAuthFrame(prAdapter, prMsduInfo, AUTH_TRANSACTION_SEQ_2) != WLAN_STATUS_SUCCESS) + break; + + if (prStaRec->u2StatusCode == STATUS_CODE_SUCCESSFUL) { + if (rTxDoneStatus == TX_RESULT_SUCCESS) { + + /* 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 (prStaRec->u2StatusCode == STATUS_CODE_SUCCESSFUL + || prStaRec->u2StatusCode == STATUS_CODE_ASSOC_REJECTED_TEMPORARILY) { + if (rTxDoneStatus == TX_RESULT_SUCCESS) { + + 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 */ + } + + DBGLOG(AAA, LOUD, + "TxDone end ucStaState:%d, eAuthAssocState:%d, u2StatusCode:%d\n", + prStaRec->ucStaState, prStaRec->eAuthAssocState, prStaRec->u2StatusCode); + + return WLAN_STATUS_SUCCESS; + +} /* end of aaaFsmRunEventTxDone() */ +#endif /* CFG_SUPPORT_AAA */ + +#if 0 /* TODO(Kevin): for abort event, just reset the STA_RECORD_T. */ +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will send ABORT Event to JOIN FSM. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID saaFsmRunEventAbort(IN P_MSG_HDR_T prMsgHdr) +{ + P_JOIN_INFO_T prJoinInfo; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("joinFsmRunEventAbort"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + + DBGLOG(JOIN, EVENT, "JOIN EVENT: ABORT\n"); + + /* NOTE(Kevin): when reach here, the ARB_STATE should be in ARB_STATE_JOIN. */ + ASSERT(prJoinInfo->prBssDesc); + + /* 4 <1> Update Flags and Elements of JOIN Module. */ + /* Reset Send Auth/(Re)Assoc Frame Count */ + prJoinInfo->ucTxAuthAssocRetryCount = 0; + + /* Cancel all JOIN relative Timer */ + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rTxRequestTimer); + + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rRxResponseTimer); + + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rJoinTimer); + + /* 4 <2> Update the associated STA_RECORD_T during JOIN. */ + /* Get a Station Record if possible, TA == BSSID for AP */ + prStaRec = staRecGetStaRecordByAddr(prAdapter, prJoinInfo->prBssDesc->aucBSSID); + if (prStaRec) + prStaRec->ucStaState = STA_STATE_1; /* Update Station Record - Class 1 Flag */ +#if DBG + else + ASSERT(0); /* Shouldn't happened, because we already add this STA_RECORD_T at JOIN_STATE_INIT */ +#endif /* DBG */ + + /* 4 <3> Pull back to IDLE. */ + joinFsmSteps(prAdapter, JOIN_STATE_IDLE); + + /* 4 <4> If we are in Roaming, recover the settings of previous BSS. */ + /* NOTE: JOIN FAIL - + * Restore original setting from current BSS_INFO_T. + */ + if (prAdapter->eConnectionState == MEDIA_STATE_CONNECTED) + joinAdoptParametersFromCurrentBss(prAdapter); + +} /* end of joinFsmRunEventAbort() */ +#endif + +/* TODO(Kevin): following code will be modified and move to AIS FSM */ +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will send Join Timeout Event to JOIN FSM. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \retval WLAN_STATUS_FAILURE Fail because of Join Timeout +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS joinFsmRunEventJoinTimeOut(IN P_ADAPTER_T prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("joinFsmRunEventJoinTimeOut"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + + DBGLOG(JOIN, EVENT, "JOIN EVENT: JOIN TIMEOUT\n"); + + /* Get a Station Record if possible, TA == BSSID for AP */ + prStaRec = staRecGetStaRecordByAddr(prAdapter, prJoinInfo->prBssDesc->aucBSSID); + + /* We have renew this Sta Record when in JOIN_STATE_INIT */ + ASSERT(prStaRec); + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_JOIN_TIMEOUT; + + /* Increase Failure Count */ + prStaRec->ucJoinFailureCount++; + + /* Reset Send Auth/(Re)Assoc Frame Count */ + prJoinInfo->ucTxAuthAssocRetryCount = 0; + + /* Cancel other JOIN relative Timer */ + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rTxRequestTimer); + + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rRxResponseTimer); + + /* Restore original setting from current BSS_INFO_T */ + if (prAdapter->eConnectionState == MEDIA_STATE_CONNECTED) + joinAdoptParametersFromCurrentBss(prAdapter); + + /* Pull back to IDLE */ + joinFsmSteps(prAdapter, JOIN_STATE_IDLE); + + return WLAN_STATUS_FAILURE; + +} /* end of joinFsmRunEventJoinTimeOut() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will adopt the parameters from Peer BSS. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID joinAdoptParametersFromPeerBss(IN P_ADAPTER_T prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + P_BSS_DESC_T prBssDesc; + + DEBUGFUNC("joinAdoptParametersFromPeerBss"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + prBssDesc = prJoinInfo->prBssDesc; + + /* 4 <1> Adopt Peer BSS' PHY TYPE */ + prAdapter->eCurrentPhyType = prBssDesc->ePhyType; + + DBGLOG(JOIN, INFO, "Target BSS[%s]'s PhyType = %s\n", + prBssDesc->aucSSID, (prBssDesc->ePhyType == PHY_TYPE_ERP_INDEX) ? "ERP" : "HR_DSSS"); + + /* 4 <2> Adopt Peer BSS' Frequency(Band/Channel) */ + DBGLOG(JOIN, INFO, "Target BSS's Channel = %d, Band = %d\n", prBssDesc->ucChannelNum, prBssDesc->eBand); + + nicSwitchChannel(prAdapter, prBssDesc->eBand, prBssDesc->ucChannelNum, 10); + + prJoinInfo->fgIsParameterAdopted = TRUE; + +} /* end of joinAdoptParametersFromPeerBss() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will adopt the parameters from current associated BSS. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID joinAdoptParametersFromCurrentBss(IN P_ADAPTER_T prAdapter) +{ + /* P_JOIN_INFO_T prJoinInfo = &prAdapter->rJoinInfo; */ + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + prBssInfo = &prAdapter->rBssInfo; + + /* 4 <1> Adopt current BSS' PHY TYPE */ + prAdapter->eCurrentPhyType = prBssInfo->ePhyType; + + /* 4 <2> Adopt current BSS' Frequency(Band/Channel) */ + DBGLOG(JOIN, INFO, "Current BSS's Channel = %d, Band = %d\n", prBssInfo->ucChnl, prBssInfo->eBand); + + nicSwitchChannel(prAdapter, prBssInfo->eBand, prBssInfo->ucChnl, 10); + +} /* end of joinAdoptParametersFromCurrentBss() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will update all the SW variables and HW MCR registers after +* the association with target BSS. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID joinComplete(IN P_ADAPTER_T prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + P_BSS_DESC_T prBssDesc; + P_PEER_BSS_INFO_T prPeerBssInfo; + P_BSS_INFO_T prBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_STA_RECORD_T prStaRec; + P_TX_CTRL_T prTxCtrl; +#if CFG_SUPPORT_802_11D + P_IE_COUNTRY_T prIECountry; +#endif + + DEBUGFUNC("joinComplete"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + prBssDesc = prJoinInfo->prBssDesc; + prPeerBssInfo = &prAdapter->rPeerBssInfo; + prBssInfo = &prAdapter->rBssInfo; + prConnSettings = &prAdapter->rConnSettings; + prTxCtrl = &prAdapter->rTxCtrl; + +/* 4 <1> Update Connecting & Connected Flag of BSS_DESC_T. */ + /* Remove previous AP's Connection Flags if have */ + scanRemoveConnectionFlagOfBssDescByBssid(prAdapter, prBssInfo->aucBSSID); + + prBssDesc->fgIsConnected = TRUE; /* Mask as Connected */ + + if (prBssDesc->fgIsHiddenSSID) { + /* NOTE(Kevin): This is for the case of Passive Scan and the target BSS didn't + * broadcast SSID on its Beacon Frame. + */ + COPY_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, prAdapter->rConnSettings.aucSSID, prAdapter->rConnSettings.ucSSIDLen); + + if (prBssDesc->ucSSIDLen) + prBssDesc->fgIsHiddenSSID = FALSE; +#if DBG + else + ASSERT(0); +#endif /* DBG */ + + DBGLOG(JOIN, INFO, "Hidden SSID! - Update SSID : %s\n", prBssDesc->aucSSID); + } +/* 4 <2> Update BSS_INFO_T from BSS_DESC_T */ + /* 4 <2.A> PHY Type */ + prBssInfo->ePhyType = prBssDesc->ePhyType; + + /* 4 <2.B> BSS Type */ + prBssInfo->eBSSType = BSS_TYPE_INFRASTRUCTURE; + + /* 4 <2.C> BSSID */ + COPY_MAC_ADDR(prBssInfo->aucBSSID, prBssDesc->aucBSSID); + + DBGLOG(JOIN, INFO, "JOIN to BSSID: [%pM]\n", prBssDesc->aucBSSID); + + /* 4 <2.D> SSID */ + COPY_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + + /* 4 <2.E> Channel / Band information. */ + prBssInfo->eBand = prBssDesc->eBand; + prBssInfo->ucChnl = prBssDesc->ucChannelNum; + + /* 4 <2.F> RSN/WPA information. */ + secFsmRunEventStart(prAdapter); + prBssInfo->u4RsnSelectedPairwiseCipher = prBssDesc->u4RsnSelectedPairwiseCipher; + prBssInfo->u4RsnSelectedGroupCipher = prBssDesc->u4RsnSelectedGroupCipher; + prBssInfo->u4RsnSelectedAKMSuite = prBssDesc->u4RsnSelectedAKMSuite; + + if (secRsnKeyHandshakeEnabled()) + prBssInfo->fgIsWPAorWPA2Enabled = TRUE; + else + prBssInfo->fgIsWPAorWPA2Enabled = FALSE; + + /* 4 <2.G> Beacon interval. */ + prBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval; + + /* 4 <2.H> DTIM period. */ + prBssInfo->ucDtimPeriod = prBssDesc->ucDTIMPeriod; + + /* 4 <2.I> ERP Information */ + if ((prBssInfo->ePhyType == PHY_TYPE_ERP_INDEX) && /* Our BSS's PHY_TYPE is ERP now. */ + (prBssDesc->fgIsERPPresent)) { + + prBssInfo->fgIsERPPresent = TRUE; + prBssInfo->ucERP = prBssDesc->ucERP; /* Save the ERP for later check */ + } else { /* Some AP, may send ProbeResp without ERP IE. Thus prBssDesc->fgIsERPPresent is FALSE. */ + prBssInfo->fgIsERPPresent = FALSE; + prBssInfo->ucERP = 0; + } + +#if CFG_SUPPORT_802_11D + /* 4 <2.J> Country inforamtion of the associated AP */ + if (prConnSettings->fgMultiDomainCapabilityEnabled) { + DOMAIN_INFO_ENTRY rDomainInfo; + + if (domainGetDomainInfoByScanResult(prAdapter, &rDomainInfo)) { + if (prBssDesc->prIECountry) { + prIECountry = prBssDesc->prIECountry; + + domainParseCountryInfoElem(prIECountry, &prBssInfo->rDomainInfo); + + /* use the domain get from the BSS info */ + prBssInfo->fgIsCountryInfoPresent = TRUE; + nicSetupOpChnlList(prAdapter, prBssInfo->rDomainInfo.u2CountryCode, FALSE); + } else { + /* use the domain get from the scan result */ + prBssInfo->fgIsCountryInfoPresent = TRUE; + nicSetupOpChnlList(prAdapter, rDomainInfo.u2CountryCode, FALSE); + } + } + } +#endif + + /* 4 <2.K> Signal Power of the associated AP */ + prBssInfo->rRcpi = prBssDesc->rRcpi; + prBssInfo->rRssi = RCPI_TO_dBm(prBssInfo->rRcpi); + GET_CURRENT_SYSTIME(&prBssInfo->rRssiLastUpdateTime); + + /* 4 <2.L> Capability Field of the associated AP */ + prBssInfo->u2CapInfo = prBssDesc->u2CapInfo; + + DBGLOG(JOIN, INFO, "prBssInfo-> fgIsERPPresent = %d, ucERP = %02x, rRcpi = %d, rRssi = %ld\n", + prBssInfo->fgIsERPPresent, prBssInfo->ucERP, prBssInfo->rRcpi, prBssInfo->rRssi); + +/* 4 <3> Update BSS_INFO_T from PEER_BSS_INFO_T & NIC RATE FUNC */ + /* 4 <3.A> Association ID */ + prBssInfo->u2AssocId = prPeerBssInfo->u2AssocId; + + /* 4 <3.B> WMM Information */ + if (prAdapter->fgIsEnableWMM && (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_SUPPORT_WMM)) { + + prBssInfo->fgIsWmmAssoc = TRUE; + prTxCtrl->rTxQForVoipAccess = TXQ_AC3; + + qosWmmInfoInit(&prBssInfo->rWmmInfo, (prBssInfo->ePhyType == PHY_TYPE_HR_DSSS_INDEX) ? TRUE : FALSE); + + if (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_AC_PARAM_PRESENT) { + kalMemCopy(&prBssInfo->rWmmInfo, &prPeerBssInfo->rWmmInfo, sizeof(WMM_INFO_T)); + } else { + kalMemCopy(&prBssInfo->rWmmInfo, + &prPeerBssInfo->rWmmInfo, + sizeof(WMM_INFO_T) - sizeof(prPeerBssInfo->rWmmInfo.arWmmAcParams)); + } + } else { + prBssInfo->fgIsWmmAssoc = FALSE; + prTxCtrl->rTxQForVoipAccess = TXQ_AC1; + + kalMemZero(&prBssInfo->rWmmInfo, sizeof(WMM_INFO_T)); + } + + /* 4 <3.C> Operational Rate Set & BSS Basic Rate Set */ + prBssInfo->u2OperationalRateSet = prPeerBssInfo->u2OperationalRateSet; + prBssInfo->u2BSSBasicRateSet = prPeerBssInfo->u2BSSBasicRateSet; + + /* 4 <3.D> Short Preamble */ + if (prBssInfo->fgIsERPPresent) { + + /* NOTE(Kevin 2007/12/24): Truth Table. + * Short Preamble Bit in + * Final Driver Setting(Short) + * TRUE FALSE FALSE FALSE(shouldn't have such case, + * use the AssocResp) + * TRUE FALSE TRUE FALSE + * FALSE FALSE FALSE FALSE(shouldn't have such case, + * use the AssocResp) + * FALSE FALSE TRUE FALSE + * TRUE TRUE FALSE TRUE(follow ERP) + * TRUE TRUE TRUE FALSE(follow ERP) + * FALSE TRUE FALSE FALSE(shouldn't have such case, + * and we should set to FALSE) + * FALSE TRUE TRUE FALSE(we should set to FALSE) + */ + if ((prPeerBssInfo->fgIsShortPreambleAllowed) && + ((prConnSettings->ePreambleType == PREAMBLE_TYPE_SHORT) || /* Short Preamble Option Enable is TRUE */ + ((prConnSettings->ePreambleType == PREAMBLE_TYPE_AUTO) && + (prBssDesc->u2CapInfo & CAP_INFO_SHORT_PREAMBLE)))) { + + prBssInfo->fgIsShortPreambleAllowed = TRUE; + + if (prBssInfo->ucERP & ERP_INFO_BARKER_PREAMBLE_MODE) + prBssInfo->fgUseShortPreamble = FALSE; + else + prBssInfo->fgUseShortPreamble = TRUE; + } else { + prBssInfo->fgIsShortPreambleAllowed = FALSE; + prBssInfo->fgUseShortPreamble = FALSE; + } + } else { + /* NOTE(Kevin 2007/12/24): Truth Table. + * Short Preamble Bit in + * Final Driver Setting(Short) + * TRUE FALSE FALSE + * FALSE FALSE FALSE + * TRUE TRUE TRUE + * FALSE TRUE(status success) TRUE + * --> Honor the result of prPeerBssInfo. + */ + + prBssInfo->fgIsShortPreambleAllowed = prBssInfo->fgUseShortPreamble = + prPeerBssInfo->fgIsShortPreambleAllowed; + } + + DBGLOG(JOIN, INFO, "prBssInfo->fgIsShortPreambleAllowed = %d, prBssInfo->fgUseShortPreamble = %d\n", + prBssInfo->fgIsShortPreambleAllowed, prBssInfo->fgUseShortPreamble); + + /* 4 <3.E> Short Slot Time */ + prBssInfo->fgUseShortSlotTime = prPeerBssInfo->fgUseShortSlotTime; /* AP support Short Slot Time */ + + DBGLOG(JOIN, INFO, "prBssInfo->fgUseShortSlotTime = %d\n", prBssInfo->fgUseShortSlotTime); + + nicSetSlotTime(prAdapter, + prBssInfo->ePhyType, + ((prConnSettings->fgIsShortSlotTimeOptionEnable && + prBssInfo->fgUseShortSlotTime) ? TRUE : FALSE)); + + /* 4 <3.F> Update Tx Rate for Control Frame */ + bssUpdateTxRateForControlFrame(prAdapter); + + /* 4 <3.G> Save the available Auth Types during Roaming (Design for Fast BSS Transition). */ + /* if (prAdapter->fgIsEnableRoaming) */ /* NOTE(Kevin): Always prepare info for roaming */ + { + + if (prJoinInfo->ucCurrAuthAlgNum == AUTH_ALGORITHM_NUM_OPEN_SYSTEM) + prJoinInfo->ucRoamingAuthTypes |= AUTH_TYPE_OPEN_SYSTEM; + else if (prJoinInfo->ucCurrAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY) + prJoinInfo->ucRoamingAuthTypes |= AUTH_TYPE_SHARED_KEY; + + prBssInfo->ucRoamingAuthTypes = prJoinInfo->ucRoamingAuthTypes; + + /* Set the stable time of the associated BSS. We won't do roaming decision + * during the stable time. + */ + SET_EXPIRATION_TIME(prBssInfo->rRoamingStableExpirationTime, + SEC_TO_SYSTIME(ROAMING_STABLE_TIMEOUT_SEC)); + } + + /* 4 <3.H> Update Parameter for TX Fragmentation Threshold */ +#if CFG_TX_FRAGMENT + txFragInfoUpdate(prAdapter); +#endif /* CFG_TX_FRAGMENT */ + +/* 4 <4> Update STA_RECORD_T */ + /* Get a Station Record if possible */ + prStaRec = staRecGetStaRecordByAddr(prAdapter, prBssDesc->aucBSSID); + + if (prStaRec) { + UINT_16 u2OperationalRateSet, u2DesiredRateSet; + + /* 4 <4.A> Desired Rate Set */ + u2OperationalRateSet = (rPhyAttributes[prBssInfo->ePhyType].u2SupportedRateSet & + prBssInfo->u2OperationalRateSet); + + u2DesiredRateSet = (u2OperationalRateSet & prConnSettings->u2DesiredRateSet); + if (u2DesiredRateSet) { + prStaRec->u2DesiredRateSet = u2DesiredRateSet; + } else { + /* For Error Handling - The Desired Rate Set is not covered in Operational Rate Set. */ + prStaRec->u2DesiredRateSet = u2OperationalRateSet; + } + + /* Try to set the best initial rate for this entry */ + if (!rateGetBestInitialRateIndex(prStaRec->u2DesiredRateSet, + prStaRec->rRcpi, &prStaRec->ucCurrRate1Index)) { + + if (!rateGetLowestRateIndexFromRateSet(prStaRec->u2DesiredRateSet, &prStaRec->ucCurrRate1Index)) + ASSERT(0); + } + + DBGLOG(JOIN, INFO, "prStaRec->ucCurrRate1Index = %d\n", prStaRec->ucCurrRate1Index); + + /* 4 <4.B> Preamble Mode */ + prStaRec->fgIsShortPreambleOptionEnable = prBssInfo->fgUseShortPreamble; + + /* 4 <4.C> QoS Flag */ + prStaRec->fgIsQoS = prBssInfo->fgIsWmmAssoc; + } +#if DBG + else + ASSERT(0); +#endif /* DBG */ + +/* 4 <5> Update NIC */ + /* 4 <5.A> Update BSSID & Operation Mode */ + nicSetupBSS(prAdapter, prBssInfo); + + /* 4 <5.B> Update WLAN Table. */ + if (nicSetHwBySta(prAdapter, prStaRec) == FALSE) + ASSERT(FALSE); + /* 4 <5.C> Update Desired Rate Set for BT. */ +#if CFG_TX_FRAGMENT + if (prConnSettings->fgIsEnableTxAutoFragmentForBT) + txRateSetInitForBT(prAdapter, prStaRec); +#endif /* CFG_TX_FRAGMENT */ + + /* 4 <5.D> TX AC Parameter and TX/RX Queue Control */ + if (prBssInfo->fgIsWmmAssoc) { + +#if CFG_TX_AGGREGATE_HW_FIFO + nicTxAggregateTXQ(prAdapter, FALSE); +#endif /* CFG_TX_AGGREGATE_HW_FIFO */ + + qosUpdateWMMParametersAndAssignAllowedACI(prAdapter, &prBssInfo->rWmmInfo); + } else { + +#if CFG_TX_AGGREGATE_HW_FIFO + nicTxAggregateTXQ(prAdapter, TRUE); +#endif /* CFG_TX_AGGREGATE_HW_FIFO */ + + nicTxNonQoSAssignDefaultAdmittedTXQ(prAdapter); + + nicTxNonQoSUpdateTXQParameters(prAdapter, prBssInfo->ePhyType); + } + +#if CFG_TX_STOP_WRITE_TX_FIFO_UNTIL_JOIN + { + prTxCtrl->fgBlockTxDuringJoin = FALSE; + +#if !CFG_TX_AGGREGATE_HW_FIFO /* TX FIFO AGGREGATE already do flush once */ + nicTxFlushStopQueues(prAdapter, (UINT_8) TXQ_DATA_MASK, (UINT_8) NULL); +#endif /* CFG_TX_AGGREGATE_HW_FIFO */ + + nicTxRetransmitOfSendWaitQue(prAdapter); + + if (prTxCtrl->fgIsPacketInOsSendQueue) + nicTxRetransmitOfOsSendQue(prAdapter); +#if CFG_SDIO_TX_ENHANCE + halTxLeftClusteredMpdu(prAdapter); +#endif /* CFG_SDIO_TX_ENHANCE */ + + } +#endif /* CFG_TX_STOP_WRITE_TX_FIFO_UNTIL_JOIN */ + +/* 4 <6> Setup CONNECTION flag. */ + prAdapter->eConnectionState = MEDIA_STATE_CONNECTED; + prAdapter->eConnectionStateIndicated = MEDIA_STATE_CONNECTED; + + if (prJoinInfo->fgIsReAssoc) + prAdapter->fgBypassPortCtrlForRoaming = TRUE; + else + prAdapter->fgBypassPortCtrlForRoaming = FALSE; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_CONNECT, (PVOID) NULL, 0); + +} /* end of joinComplete() */ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/ais_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/ais_fsm.c new file mode 100644 index 0000000000000..7b1674f5c0576 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/ais_fsm.c @@ -0,0 +1,6023 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E 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 "fwcfg.h" +static VOID aisFsmSetOkcTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam); +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define AIS_ROAMING_CONNECTION_TRIAL_LIMIT 2 +#define AIS_ROAMING_SCAN_CHANNEL_DWELL_TIME 80 +#if CFG_SUPPORT_ROAMING_RETRY +#define AIS_ROAMING_RETRY_BSS_THRESHOLD 1 +#endif +#define CTIA_MAGIC_SSID "ctia_test_only_*#*#3646633#*#*" +#define CTIA_MAGIC_SSID_LEN 30 + +#define AIS_JOIN_TIMEOUT 7 +#define AIS_DEFAULT_ROAMING_THRESHOLD -75 /* dbm */ + +#define AIS_DEFAULT_ROAMING_THRESHOLD -75 /* dbm */ +#define AIS_DRT_ROAMING_THRESHOLD -85 /* DRT=Dynamic Roaming Threshold, dbm */ +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if DBG +/*lint -save -e64 Type mismatch */ +static PUINT_8 apucDebugAisState[AIS_STATE_NUM] = { + (PUINT_8) DISP_STRING("AIS_STATE_IDLE"), + (PUINT_8) DISP_STRING("AIS_STATE_SEARCH"), + (PUINT_8) DISP_STRING("AIS_STATE_SCAN"), + (PUINT_8) DISP_STRING("AIS_STATE_ONLINE_SCAN"), + (PUINT_8) DISP_STRING("AIS_STATE_LOOKING_FOR"), + (PUINT_8) DISP_STRING("AIS_STATE_WAIT_FOR_NEXT_SCAN"), + (PUINT_8) DISP_STRING("AIS_STATE_REQ_CHANNEL_JOIN"), + (PUINT_8) DISP_STRING("AIS_STATE_JOIN"), + (PUINT_8) DISP_STRING("AIS_STATE_IBSS_ALONE"), + (PUINT_8) DISP_STRING("AIS_STATE_IBSS_MERGE"), + (PUINT_8) DISP_STRING("AIS_STATE_NORMAL_TR"), + (PUINT_8) DISP_STRING("AIS_STATE_DISCONNECTING"), + (PUINT_8) DISP_STRING("AIS_STATE_REQ_REMAIN_ON_CHANNEL"), + (PUINT_8) DISP_STRING("AIS_STATE_REMAIN_ON_CHANNEL") +}; + +/*lint -restore */ +#endif /* DBG */ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static VOID aisRemoveOldestBcnTimeout(P_AIS_FSM_INFO_T prAisFsmInfo); +static VOID aisRemoveDisappearedBlacklist(P_ADAPTER_T prAdapter); + +static VOID +aisSendNeighborRequest(P_ADAPTER_T prAdapter); +#if CFG_SUPPORT_DYNAMIC_ROAM +static VOID aisFsmSetRoamingThreshold(P_ADAPTER_T prAdapter, INT_8 cThreshold); +#endif +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +static VOID aisResetBssTranstionMgtParam(P_AIS_SPECIFIC_BSS_INFO_T prSpecificBssInfo) +{ + struct BSS_TRANSITION_MGT_PARAM_T *prBtmParam = &prSpecificBssInfo->rBTMParam; + +#if !CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT + return; +#endif + if (prBtmParam->u2PeerNeighborBssLen > 0) + kalMemFree(prBtmParam->pucPeerNeighborBss, VIR_MEM_TYPE, prBtmParam->u2PeerNeighborBssLen); + kalMemZero(prBtmParam, sizeof(*prBtmParam)); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief the function is used to initialize the value of the connection settings for +* AIS network +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisInitializeConnectionSettings(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + UINT_8 aucAnyBSSID[] = BC_BSSID; + UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; + int i = 0; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* Setup default values for operation */ + COPY_MAC_ADDR(prConnSettings->aucMacAddress, aucZeroMacAddr); + + if (prRegInfo) + prConnSettings->ucDelayTimeOfDisconnectEvent = + (!prAdapter->fgIsHw5GBandDisabled && prRegInfo->ucSupport5GBand) ? + AIS_DELAY_TIME_OF_DISC_SEC_DUALBAND : AIS_DELAY_TIME_OF_DISC_SEC_ONLY_2G4; + else + prConnSettings->ucDelayTimeOfDisconnectEvent = AIS_DELAY_TIME_OF_DISC_SEC_ONLY_2G4; + + COPY_MAC_ADDR(prConnSettings->aucBSSID, aucAnyBSSID); + prConnSettings->fgIsConnByBssidIssued = FALSE; + + prConnSettings->eReConnectLevel = RECONNECT_LEVEL_MIN; + 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; + +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE + prConnSettings->fgSecModeChangeStartTimer = FALSE; +#endif + + prConnSettings->eDesiredPhyConfig = PHY_CONFIG_802_11ABGN; + + /* Set default bandwidth modes */ + prConnSettings->uc2G4BandwidthMode = CONFIG_BW_20M; + prConnSettings->uc5GBandwidthMode = CONFIG_BW_20_40M; + + prConnSettings->rRsnInfo.ucElemId = 0x30; + prConnSettings->rRsnInfo.u2Version = 0x0001; + prConnSettings->rRsnInfo.u4GroupKeyCipherSuite = 0; + prConnSettings->rRsnInfo.u4PairwiseKeyCipherSuiteCount = 0; + for (i = 0; i < MAX_NUM_SUPPORTED_CIPHER_SUITES; i++) + prConnSettings->rRsnInfo.au4PairwiseKeyCipherSuite[i] = 0; + prConnSettings->rRsnInfo.u4AuthKeyMgtSuiteCount = 0; + for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) + prConnSettings->rRsnInfo.au4AuthKeyMgtSuite[i] = 0; + prConnSettings->rRsnInfo.u2RsnCap = 0; + prConnSettings->rRsnInfo.fgRsnCapPresent = FALSE; + +} /* end of aisFsmInitializeConnectionSettings() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief the function is used to initialize the value in AIS_FSM_INFO_T for +* AIS FSM operation +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 ucScanTimeoutTimes; +VOID aisFsmInit(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecificBssInfo; + + DEBUGFUNC("aisFsmInit()"); + DBGLOG(SW1, TRACE, "->aisFsmInit()\n"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prAisSpecificBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); + + /* 4 <1> Initiate FSM */ + prAisFsmInfo->ePreviousState = AIS_STATE_IDLE; + prAisFsmInfo->eCurrentState = AIS_STATE_IDLE; + + prAisFsmInfo->ucAvailableAuthTypes = 0; + + prAisFsmInfo->prTargetBssDesc = (P_BSS_DESC_T) NULL; + + prAisFsmInfo->ucSeqNumOfReqMsg = 0; + prAisFsmInfo->ucSeqNumOfChReq = 0; + prAisFsmInfo->ucSeqNumOfScanReq = 0; + + prAisFsmInfo->fgIsInfraChannelFinished = TRUE; +#if CFG_SUPPORT_ROAMING + prAisFsmInfo->fgIsRoamingScanPending = FALSE; +#endif /* CFG_SUPPORT_ROAMING */ + prAisFsmInfo->fgIsChannelRequested = FALSE; + prAisFsmInfo->fgIsChannelGranted = FALSE; +#if CFG_SCAN_ABORT_HANDLE + prAisFsmInfo->fgIsAbortEvnetDuringScan = FALSE; +#endif + prAisFsmInfo->ucJoinFailCntAfterScan = 0; +#if CFG_SUPPORT_DYNAMIC_ROAM + prAisFsmInfo->cRoamTriggerThreshold = 0; +#endif + + /* 4 <1.1> Initiate FSM - Timer INIT */ + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rBGScanTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventBGSleepTimeOut, (ULONG) NULL); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rIbssAloneTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventIbssAloneTimeOut, (ULONG) NULL); + + prAisFsmInfo->u4PostponeIndStartTime = 0; + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rJoinTimeoutTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventJoinTimeout, (ULONG) NULL); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rScanDoneTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventScanDoneTimeOut, (ULONG) NULL); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rChannelTimeoutTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventChannelTimeout, (ULONG) NULL); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rDeauthDoneTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventDeauthTimeout, (ULONG) NULL); +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rSecModeChangeTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventSecModeChangeTimeout, (ULONG) NULL); +#endif + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rWaitOkcPMKTimer, + (PFN_MGMT_TIMEOUT_FUNC)aisFsmSetOkcTimeout, (ULONG) NULL); + /* 4 <1.2> Initiate PWR STATE */ + SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* 4 <2> Initiate BSS_INFO_T - common part */ + BSS_INFO_INIT(prAdapter, NETWORK_TYPE_AIS_INDEX); + COPY_MAC_ADDR(prAisBssInfo->aucOwnMacAddr, prAdapter->rWifiVar.aucMacAddress); + + /* 4 <3> Initiate BSS_INFO_T - private part */ + /* TODO */ + prAisBssInfo->eBand = BAND_2G4; + prAisBssInfo->ucPrimaryChannel = 1; + prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; + + /* 4 <4> Allocate MSDU_INFO_T for Beacon */ + prAisBssInfo->prBeacon = cnmMgtPktAlloc(prAdapter, + OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem[0]) + MAX_IE_LENGTH); + + if (prAisBssInfo->prBeacon) { + prAisBssInfo->prBeacon->eSrc = TX_PACKET_MGMT; + prAisBssInfo->prBeacon->ucStaRecIndex = 0xFF; /* NULL STA_REC */ + } else { + ASSERT(0); + } + +#if 0 + prAisBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC = PM_UAPSD_ALL; + prAisBssInfo->rPmProfSetupInfo.ucBmpTriggerAC = PM_UAPSD_ALL; + prAisBssInfo->rPmProfSetupInfo.ucUapsdSp = WMM_MAX_SP_LENGTH_2; +#else + if (prAdapter->u4UapsdAcBmp == 0) { + prAdapter->u4UapsdAcBmp = CFG_INIT_UAPSD_AC_BMP; + /* ASSERT(prAdapter->u4UapsdAcBmp); */ + } + prAisBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC = (UINT_8) prAdapter->u4UapsdAcBmp; + prAisBssInfo->rPmProfSetupInfo.ucBmpTriggerAC = (UINT_8) prAdapter->u4UapsdAcBmp; + prAisBssInfo->rPmProfSetupInfo.ucUapsdSp = (UINT_8) prAdapter->u4MaxSpLen; +#endif + + /* request list initialization */ + LINK_INITIALIZE(&prAisFsmInfo->rPendingReqList); + LINK_MGMT_INIT(&prAdapter->rWifiVar.rConnSettings.rBlackList); + LINK_MGMT_INIT(&prAisFsmInfo->rBcnTimeout); + kalMemZero(&prAisSpecificBssInfo->arCurEssChnlInfo[0], + sizeof(prAisSpecificBssInfo->arCurEssChnlInfo)); + LINK_INITIALIZE(&prAisSpecificBssInfo->rCurEssLink); + kalMemZero(&prAisSpecificBssInfo->rBTMParam, sizeof(prAisSpecificBssInfo->rBTMParam)); + +#if (CFG_REFACTORY_PMKSA == 1) + LINK_INITIALIZE(&prAisSpecificBssInfo->rPmkidCache); +#endif + + /* DBGPRINTF("[2] ucBmpDeliveryAC:0x%x, ucBmpTriggerAC:0x%x, ucUapsdSp:0x%x", */ + /* prAisBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC, */ + /* prAisBssInfo->rPmProfSetupInfo.ucBmpTriggerAC, */ + /* prAisBssInfo->rPmProfSetupInfo.ucUapsdSp); */ + + /*reset ucScanTimeoutTimes value*/ + ucScanTimeoutTimes = 0; + +} /* end of aisFsmInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief the function is used to uninitialize the value in AIS_FSM_INFO_T for +* AIS FSM operation +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmUninit(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecificBssInfo; + + DEBUGFUNC("aisFsmUninit()"); + DBGLOG(SW1, INFO, "->aisFsmUninit()\n"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prAisSpecificBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); + + /* 4 <1> Stop all timers */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rBGScanTimer); + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rIbssAloneTimer); + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rJoinTimeoutTimer); + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); /* Add by Enlai */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer); + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rWaitOkcPMKTimer); + /* 4 <2> flush pending request */ + aisFsmFlushRequest(prAdapter); + aisResetBssTranstionMgtParam(prAisSpecificBssInfo); + + /* 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 + LINK_MGMT_UNINIT(&prAdapter->rWifiVar.rConnSettings.rBlackList, + struct AIS_BLACKLIST_ITEM, VIR_MEM_TYPE); + LINK_MGMT_UNINIT(&prAisFsmInfo->rBcnTimeout, struct AIS_BEACON_TIMEOUT_BSS, VIR_MEM_TYPE); + +#if (CFG_REFACTORY_PMKSA == 1) + /* make sure pmkid cached is empty after uninit*/ + rsnFlushPmkid(prAdapter); +#endif +} /* end of aisFsmUninit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Initialization of JOIN STATE +* +* @param[in] prBssDesc The pointer of BSS_DESC_T which is the BSS we will try to join with. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmStateInit_JOIN(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecificBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_STA_RECORD_T prStaRec; + P_MSG_JOIN_REQ_T prJoinReqMsg; +#if (CFG_REFACTORY_PMKSA == 0) + UINT_32 u4Entry = 0; +#endif + + DEBUGFUNC("aisFsmStateInit_JOIN()"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prAisSpecificBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + ASSERT(prBssDesc); + + /* 4 <1> We are going to connect to this BSS. */ + prBssDesc->fgIsConnecting = TRUE; + + /* 4 <2> Setup corresponding STA_RECORD_T */ + prStaRec = bssCreateStaRecFromBssDesc(prAdapter, STA_TYPE_LEGACY_AP, NETWORK_TYPE_AIS_INDEX, prBssDesc); + if (prStaRec == NULL) { + DBGLOG(AIS, WARN, "Create station record fail\n"); + return; + } + + prAisFsmInfo->prTargetStaRec = prStaRec; + + /* 4 <2.1> sync. to firmware domain */ + if (prStaRec->ucStaState == STA_STATE_1) + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + /* 4 <3> Update ucAvailableAuthTypes which we can choice during SAA */ + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { + + prStaRec->fgIsReAssoc = FALSE; + + switch (prConnSettings->eAuthMode) { + case AUTH_MODE_NON_RSN_FT: /* FT initial mobility doamin association always use Open AA */ + case AUTH_MODE_WPA2_FT: + case AUTH_MODE_WPA2_FT_PSK: + 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: + case AUTH_MODE_WPA_OSEN: + case AUTH_MODE_WPA3_OWE: + 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; + + case AUTH_MODE_WPA3_SAE: + DBGLOG(AIS, LOUD, + "JOIN INIT: eAuthMode == AUTH_MODE_SAE\n"); + prAisFsmInfo->ucAvailableAuthTypes = + (uint8_t) AUTH_TYPE_SAE; + 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; + /* reset Bss Transition Management Params when do first connection */ + aisResetBssTranstionMgtParam(prAisSpecificBssInfo); + } 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 */ + /* FT and FT Resource Request Protocol should use FT AA(Auth Algorithm) */ + switch (prConnSettings->eAuthMode) { + case AUTH_MODE_WPA2_FT: + case AUTH_MODE_WPA2_FT_PSK: + case AUTH_MODE_NON_RSN_FT: + prAisFsmInfo->ucAvailableAuthTypes = + (uint8_t) AUTH_TYPE_FAST_BSS_TRANSITION; + break; + case AUTH_MODE_WPA3_SAE: +#if (CFG_REFACTORY_PMKSA == 0) + if (rsnSearchPmkidEntry(prAdapter, prBssDesc->aucBSSID, + &u4Entry)) { +#else + if (rsnSearchPmkidEntry(prAdapter, prBssDesc->aucBSSID)) { +#endif + prAisFsmInfo->ucAvailableAuthTypes = + (uint8_t) AUTH_TYPE_OPEN_SYSTEM; + DBGLOG(AIS, INFO, + "SAE: change AUTH to OPEN when roaming with PMK\n"); + } else { + prAisFsmInfo->ucAvailableAuthTypes = + (uint8_t) AUTH_TYPE_SAE; + } + break; + default: + prAisFsmInfo->ucAvailableAuthTypes = + prAisSpecificBssInfo->ucRoamingAuthTypes; + break; + } + + 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_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_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_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 if (prAisFsmInfo->ucAvailableAuthTypes & (uint8_t) + AUTH_TYPE_SAE) { + DBGLOG(AIS, LOUD, + "JOIN INIT: Try to do Authentication with AuthType == SAE.\n"); + /*the following one line used to fix WPA3-SAE Certification 5.2.4*/ + /*when finish test 5.2.3, the aisFsmState will always in JOIN state which make*/ + /*5.2.4 fail to connect AP */ + /*the following one line can let the aisFsmState will back to IDLE after 5.2.3*/ + prAisFsmInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_SAE; + prStaRec->ucAuthAlgNum = (uint8_t) AUTH_ALGORITHM_NUM_SAE; + } else { + DBGLOG(AIS, ERROR, + "JOIN INIT: No available AuthType found, %d\n", + prAisFsmInfo->ucAvailableAuthTypes); + } + + /* 4 <5> Overwrite Connection Setting for eConnectionPolicy == ANY (Used by Assoc Req) */ + if (prBssDesc->ucSSIDLen) + COPY_SSID(prConnSettings->aucSSID, prConnSettings->ucSSIDLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + /* 4 <6> Send a Msg to trigger SAA to start JOIN process. */ + prJoinReqMsg = (P_MSG_JOIN_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_REQ_T)); + if (!prJoinReqMsg) { + + ASSERT(0); /* Can't trigger SAA FSM */ + return; + } + + prJoinReqMsg->rMsgHdr.eMsgId = MID_AIS_SAA_FSM_START; + prJoinReqMsg->ucSeqNum = ++prAisFsmInfo->ucSeqNumOfReqMsg; + prJoinReqMsg->prStaRec = prStaRec; + + if (1) { + int j; + P_FRAG_INFO_T prFragInfo; + + for (j = 0; j < MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS; j++) { + prFragInfo = &prStaRec->rFragInfo[j]; + + if (prFragInfo->pr1stFrag) { + /* nicRxReturnRFB(prAdapter, prFragInfo->pr1stFrag); */ + prFragInfo->pr1stFrag = (P_SW_RFB_T) NULL; + } + } + } +#if CFG_SUPPORT_802_11K + if (prBssDesc->cPowerLimit != RLM_INVALID_POWER_LIMIT) + rlmSetMaxTxPwrLimit(prAdapter, prBssDesc->cPowerLimit, 1); +#endif + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinReqMsg, MSG_SEND_METHOD_BUF); + +} /* end of aisFsmInit_JOIN() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Retry JOIN for AUTH_MODE_AUTO_SWITCH +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @retval TRUE We will retry JOIN +* @retval FALSE We will not retry JOIN +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN aisFsmStateInit_RetryJOIN(IN P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_MSG_JOIN_REQ_T prJoinReqMsg; + INT_32 rssi = 0; + + DEBUGFUNC("aisFsmStateInit_RetryJOIN()"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + rssi = RCPI_TO_dBm(prStaRec->ucRCPI); + /*check if driver exists pending scan reques and candiate bss's signal is too weak.*/ + if ((aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, FALSE) == TRUE) + && (rssi < AIS_DEFAULT_ROAMING_THRESHOLD)) { + DBGLOG(AIS, WARN + , "Retry BSS :[%pM] Rss:%d is too weak!Skipping retry join and doing next scan!\n" + , prStaRec->aucMacAddr, rssi); + return FALSE; + } + + DBGLOG(AIS, INFO, "AvailableAuthTypes = %d\n", prAisFsmInfo->ucAvailableAuthTypes); + + /* Retry other AuthType if possible */ + if (!prAisFsmInfo->ucAvailableAuthTypes) + return FALSE; + + if (prStaRec->u2StatusCode != STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED) { + prAisFsmInfo->ucAvailableAuthTypes = 0; + return FALSE; + } + + if (prAisFsmInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_OPEN_SYSTEM) { + + DBGLOG(AIS, INFO, "RETRY JOIN INIT: Retry Authentication with AuthType == OPEN SYSTEM.\n"); + + prAisFsmInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_OPEN_SYSTEM; + + prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_OPEN_SYSTEM; + } else { + DBGLOG(AIS, ERROR, "RETRY JOIN INIT: Retry Authentication with Unexpected AuthType.\n"); + ASSERT(0); + } + + prAisFsmInfo->ucAvailableAuthTypes = 0; /* No more available Auth Types */ + + /* Trigger SAA to start JOIN process. */ + prJoinReqMsg = (P_MSG_JOIN_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_REQ_T)); + if (!prJoinReqMsg) { + + ASSERT(0); /* Can't trigger SAA FSM */ + return FALSE; + } + + prJoinReqMsg->rMsgHdr.eMsgId = MID_AIS_SAA_FSM_START; + prJoinReqMsg->ucSeqNum = ++prAisFsmInfo->ucSeqNumOfReqMsg; + prJoinReqMsg->prStaRec = prStaRec; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinReqMsg, MSG_SEND_METHOD_BUF); + + return TRUE; + +} /* end of aisFsmRetryJOIN() */ + +#if CFG_SUPPORT_ADHOC +/*----------------------------------------------------------------------------*/ +/*! +* @brief State Initialization of AIS_STATE_IBSS_ALONE +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmStateInit_IBSS_ALONE(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_INFO_T prAisBssInfo; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + /* 4 <1> Check if IBSS was created before ? */ + if (prAisBssInfo->fgIsBeaconActivated) { + + /* 4 <2> Start IBSS Alone Timer for periodic SCAN and then SEARCH */ +#if !CFG_SLT_SUPPORT + cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rIbssAloneTimer, SEC_TO_MSEC(AIS_IBSS_ALONE_TIMEOUT_SEC)); +#endif + } + + aisFsmCreateIBSS(prAdapter); + +} /* end of aisFsmStateInit_IBSS_ALONE() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief State Initialization of AIS_STATE_IBSS_MERGE +* +* @param[in] prBssDesc The pointer of BSS_DESC_T which is the IBSS we will try to merge with. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmStateInit_IBSS_MERGE(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_INFO_T prAisBssInfo; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + + ASSERT(prBssDesc); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + /* 4 <1> We will merge with to this BSS immediately. */ + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + + /* 4 <2> Setup corresponding STA_RECORD_T */ + prStaRec = bssCreateStaRecFromBssDesc(prAdapter, STA_TYPE_ADHOC_PEER, NETWORK_TYPE_AIS_INDEX, prBssDesc); + if (prStaRec == NULL) { + DBGLOG(AIS, WARN, "Create station record fail\n"); + return; + } + + prStaRec->fgIsMerging = TRUE; + + prAisFsmInfo->prTargetStaRec = prStaRec; + + /* 4 <2.1> sync. to firmware domain */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + /* 4 <3> IBSS-Merge */ + aisFsmMergeIBSS(prAdapter, prStaRec); + +} /* end of aisFsmStateInit_IBSS_MERGE() */ + +#endif /* CFG_SUPPORT_ADHOC */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process of JOIN Abort +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmStateAbort_JOIN(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_MSG_JOIN_ABORT_T prJoinAbortMsg; + P_AIS_BSS_INFO_T prAisBSSInfo; + + prAisBSSInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + /* 1. Abort JOIN process */ + prJoinAbortMsg = (P_MSG_JOIN_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_ABORT_T)); + if (!prJoinAbortMsg) { + + ASSERT(0); /* Can't abort SAA FSM */ + return; + } + + prJoinAbortMsg->rMsgHdr.eMsgId = MID_AIS_SAA_FSM_ABORT; + prJoinAbortMsg->ucSeqNum = prAisFsmInfo->ucSeqNumOfReqMsg; + prJoinAbortMsg->prStaRec = prAisFsmInfo->prTargetStaRec; + + scanRemoveConnFlagOfBssDescByBssid(prAdapter, prAisFsmInfo->prTargetStaRec->aucMacAddr); + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinAbortMsg, MSG_SEND_METHOD_BUF); + + /* 2. Return channel privilege */ + aisFsmReleaseCh(prAdapter); + + /* 3.1 stop join timeout timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rJoinTimeoutTimer); + + /* 3.2 reset local variable */ + prAisFsmInfo->fgIsInfraChannelFinished = TRUE; +} /* end of aisFsmAbortJOIN() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process of SCAN Abort +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmStateAbort_SCAN(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_MSG_SCN_SCAN_CANCEL prScanCancelMsg; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + /* Abort JOIN process. */ + prScanCancelMsg = (P_MSG_SCN_SCAN_CANCEL) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_CANCEL)); + if (!prScanCancelMsg) { + + ASSERT(0); /* Can't abort SCN FSM */ + return; + } + + prScanCancelMsg->rMsgHdr.eMsgId = MID_AIS_SCN_SCAN_CANCEL; + prScanCancelMsg->ucSeqNum = prAisFsmInfo->ucSeqNumOfScanReq; + prScanCancelMsg->ucNetTypeIndex = (UINT_8) NETWORK_TYPE_AIS_INDEX; +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) + prScanCancelMsg->fgIsChannelExt = FALSE; +#endif + + /* unbuffered message to guarantee scan is cancelled in sequence */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanCancelMsg, MSG_SEND_METHOD_UNBUF); + +} /* end of aisFsmAbortSCAN() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process of NORMAL_TR Abort +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmStateAbort_NORMAL_TR(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_AIS_BSS_INFO_T prAisBssInfo; + + ASSERT(prAdapter); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + DBGLOG(AIS, TRACE, "aisFsmStateAbort_NORMAL_TR\n"); + + /* TODO(Kevin): Do abort other MGMT func */ + + /* 1. Release channel to CNM */ + aisFsmReleaseCh(prAdapter); + + /* 2.1 stop join timeout timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rJoinTimeoutTimer); + + /* 2.2 reset local variable */ + prAisFsmInfo->fgIsInfraChannelFinished = TRUE; + /* 2.3 need check ReasonOfDisconnect */ + + if (prAisBssInfo->ucReasonOfDisconnect == DISCONNECT_REASON_CODE_RADIO_LOST) + /*Beacon timeout and driver will try to connect to this the same SSID but different BSSID*/ + DBGLOG(AIS, INFO, "Radio lost don't clear SSID len!\n"); + else + prAdapter->rWifiVar.rConnSettings.ucSSIDLen = 0; + +} /* end of aisFsmAbortNORMAL_TR() */ + +#if CFG_SUPPORT_ADHOC +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process of NORMAL_TR Abort +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmStateAbort_IBSS(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_DESC_T prBssDesc; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + /* reset BSS-DESC */ + if (prAisFsmInfo->prTargetStaRec) { + prBssDesc = scanSearchBssDescByTA(prAdapter, prAisFsmInfo->prTargetStaRec->aucMacAddr); + + if (prBssDesc) { + prBssDesc->fgIsConnected = FALSE; + prBssDesc->fgIsConnecting = FALSE; + } + } + /* release channel privilege */ + aisFsmReleaseCh(prAdapter); + +} +#endif /* CFG_SUPPORT_ADHOC */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Change array index to channel number. +* +* @param[in] ucIndex array index. +* +* @retval ucChannelNum ucChannelNum +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 aisIndex2ChannelNum(IN UINT_8 ucIndex) +{ + UINT_8 ucChannel; + + /*Full2Partial*/ + if (ucIndex >= 1 && ucIndex <= 14) + /*1---14*/ + ucChannel = ucIndex; + /*1---14*/ + else if (ucIndex >= 15 && ucIndex <= 22) + /*15---22*/ + ucChannel = (ucIndex - 6) << 2; + /*36---64*/ + else if (ucIndex >= 23 && ucIndex <= 34) + /*23---34*/ + ucChannel = (ucIndex + 2) << 2; + /*100---144*/ + else if (ucIndex >= 35 && ucIndex <= 39) { + /*35---39*/ + ucIndex = ucIndex + 2; + ucChannel = (ucIndex << 2) + 1; + /*149---164*/ + } else { + /*error*/ + ucChannel = 0; + } + return ucChannel; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Full2Partial Process full scan channel info +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ + +VOID aisGetAndSetScanChannel(IN P_ADAPTER_T prAdapter) +{ + P_PARTIAL_SCAN_INFO PartialScanChannel = NULL; + UINT_8 *ucChannelp; + UINT_8 ucChannelNum; + int i = 1; + int t = 0; + /*Full2Partial*/ + + if (prAdapter->prGlueInfo->u4LastFullScanTime == 0) { + /*there is full scan before this time*/ + DBGLOG(AIS, INFO, "Full2Partial u4LastFullScanTime=0\n"); + return; + } + /* + *if (prAdapter->prGlueInfo->ucChannelListNum == 0) { + * DBGLOG(AIS, TRACE, "aisGetAndSetScanChannel ucChannelListNum=0\n"); + * return; + *} + */ + if (prAdapter->prGlueInfo->puFullScan2PartialChannel != NULL) { + DBGLOG(AIS, TRACE, "Full2Partial puFullScan2PartialChannel not null\n"); + return; + } + + /*at here set channel info*/ + PartialScanChannel = (P_PARTIAL_SCAN_INFO) kalMemAlloc(sizeof(PARTIAL_SCAN_INFO), VIR_MEM_TYPE); + if (PartialScanChannel == NULL) { + DBGLOG(AIS, INFO, "Full2Partial alloc PartialScanChannel fail\n"); + return; + } + kalMemSet(PartialScanChannel, 0, sizeof(PARTIAL_SCAN_INFO)); + + ucChannelp = prAdapter->prGlueInfo->ucChannelNum; + while (i < FULL_SCAN_MAX_CHANNEL_NUM) { + if (ucChannelp[i] != 0) { + ucChannelNum = aisIndex2ChannelNum(i); + DBGLOG(AIS, TRACE, "Full2Partial i=%d, channel value=%d\n", i, ucChannelNum); + if (ucChannelNum != 0) { + if ((ucChannelNum >= 1) && (ucChannelNum <= 14)) + PartialScanChannel->arChnlInfoList[t].eBand = BAND_2G4; + else + PartialScanChannel->arChnlInfoList[t].eBand = BAND_5G; + + PartialScanChannel->arChnlInfoList[t].ucChannelNum = ucChannelNum; + t++; + } + } + i++; + } + DBGLOG(AIS, INFO, "Full2Partial channel num=%d\n", t); + if ((t > 0) && (t <= MAXIMUM_OPERATION_CHANNEL_LIST)) { + PartialScanChannel->ucChannelListNum = t; + prAdapter->prGlueInfo->puFullScan2PartialChannel = (PUINT_8)PartialScanChannel; + } else { + DBGLOG(AIS, INFO, "Full2Partial channel num great %d max channel number\n", + MAXIMUM_OPERATION_CHANNEL_LIST); + kalMemFree(PartialScanChannel, VIR_MEM_TYPE, sizeof(PARTIAL_SCAN_INFO)); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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; +#if CFG_MULTI_SSID_SCAN + P_MSG_SCN_SCAN_REQ_V2 prScanReqMsg; +#else + P_MSG_SCN_SCAN_REQ prScanReqMsg; +#endif + P_AIS_REQ_HDR_T prAisReq; + P_SCAN_INFO_T prScanInfo; + ENUM_BAND_T eBand; + UINT_8 ucChannel; + UINT_16 u2ScanIELen; + ENUM_AIS_STATE_T eOriPreState; + OS_SYSTIME rCurrentTime; + + BOOLEAN fgIsTransition = (BOOLEAN) FALSE; + BOOLEAN fgIsRequestScanPending = (BOOLEAN) FALSE; + + DEBUGFUNC("aisFsmSteps()"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + eOriPreState = prAisFsmInfo->ePreviousState; + + do { + + /* Do entering Next State */ + prAisFsmInfo->ePreviousState = prAisFsmInfo->eCurrentState; + +#if DBG + DBGLOG(AIS, STATE, "TRANSITION: [%s] -> [%s]\n", + apucDebugAisState[prAisFsmInfo->eCurrentState], apucDebugAisState[eNextState]); +#else + DBGLOG(AIS, STATE, "[%d] TRANSITION: [%d] -> [%d]\n", + DBG_AIS_IDX, prAisFsmInfo->eCurrentState, eNextState); +#endif + /* NOTE(Kevin): This is the only place to change the eCurrentState(except initial) */ + prAisFsmInfo->eCurrentState = eNextState; + + fgIsTransition = (BOOLEAN) FALSE; + + aisPostponedEventOfDisconnTimeout(prAdapter, prAisFsmInfo); + + /* Do tasks of the State that we just entered */ + switch (prAisFsmInfo->eCurrentState) { + /* NOTE(Kevin): we don't have to rearrange the sequence of following + * switch case. Instead I would like to use a common lookup table of array + * of function pointer to speed up state search. + */ + case AIS_STATE_IDLE: + + prAisReq = aisFsmGetNextRequest(prAdapter); + + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rWaitOkcPMKTimer); + + if (prAisReq) + DBGLOG(AIS, TRACE, "eReqType=%d, fgIsConnReqIssued=%d, DisByNonRequest=%d\n", + prAisReq->eReqType, prConnSettings->fgIsConnReqIssued, + prConnSettings->fgIsDisconnectedByNonRequest); + if (prAisReq == NULL || prAisReq->eReqType == AIS_REQUEST_RECONNECT) { + if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX)) { +#if !CFG_SUPPORT_RLM_ACT_NETWORK + UNSET_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX); + nicDeactivateNetwork(prAdapter, NETWORK_TYPE_AIS_INDEX); +#else + rlmDeactivateNetwork(prAdapter, NETWORK_TYPE_AIS_INDEX, + NET_ACTIVE_SRC_CONNECT | NET_ACTIVE_SRC_SCAN); +#endif + } + if (prConnSettings->fgIsConnReqIssued == TRUE && + prConnSettings->fgIsDisconnectedByNonRequest == FALSE) { + + prAisFsmInfo->fgTryScan = TRUE; + + SET_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* sync with firmware */ +#if !CFG_SUPPORT_RLM_ACT_NETWORK + SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX); + nicActivateNetwork(prAdapter, NETWORK_TYPE_AIS_INDEX); +#else + rlmActivateNetwork(prAdapter, NETWORK_TYPE_AIS_INDEX, NET_ACTIVE_SRC_CONNECT); +#endif + /* reset trial count */ + prAisFsmInfo->ucConnTrialCount = 0; + + eNextState = AIS_STATE_COLLECT_ESS_INFO; + fgIsTransition = TRUE; + } else { + SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* check for other pending request */ + + fgIsRequestScanPending = + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, TRUE); + + if (prAisReq && fgIsRequestScanPending == TRUE) { + + wlanClearScanningResult(prAdapter); + eNextState = AIS_STATE_SCAN; + + fgIsTransition = TRUE; + } + /*check for pending sched scan request*/ + if (prAisReq == NULL && + fgIsRequestScanPending == FALSE && + prScanInfo->fgIsPostponeSchedScan == TRUE) + aisPostponedEventOfSchedScanReq(prAdapter, prAisFsmInfo); + +#if CFG_SCAN_ABORT_HANDLE + if (prAisFsmInfo->fgIsAbortEvnetDuringScan) { + DBGLOG(AIS, WARN, "proccess the pending abort event(%d)!\n" + , prAisBssInfo->ucReasonOfDisconnect); + prAisFsmInfo->fgIsAbortEvnetDuringScan = FALSE; + aisFsmStateAbort(prAdapter, + prAisBssInfo->ucReasonOfDisconnect, + prAisBssInfo->fgIsDelayIndication); + } +#endif + } + if (prAisReq) { + /* free the message */ + cnmMemFree(prAdapter, prAisReq); + } + } else if (prAisReq->eReqType == AIS_REQUEST_SCAN) { +#if CFG_SUPPORT_ROAMING + prAisFsmInfo->fgIsRoamingScanPending = FALSE; +#endif /* CFG_SUPPORT_ROAMING */ + wlanClearScanningResult(prAdapter); + + eNextState = AIS_STATE_SCAN; + fgIsTransition = TRUE; + + /* free the message */ + cnmMemFree(prAdapter, prAisReq); + } else if (prAisReq->eReqType == AIS_REQUEST_ROAMING_CONNECT + || prAisReq->eReqType == AIS_REQUEST_ROAMING_SEARCH) { + /* ignore */ + /* free the message */ + cnmMemFree(prAdapter, prAisReq); + } else if (prAisReq->eReqType == AIS_REQUEST_REMAIN_ON_CHANNEL) { + eNextState = AIS_STATE_REQ_REMAIN_ON_CHANNEL; + fgIsTransition = TRUE; + + /* free the message */ + cnmMemFree(prAdapter, prAisReq); + } + + prAisFsmInfo->u4SleepInterval = AIS_BG_SCAN_INTERVAL_MIN_SEC; + + break; + + case AIS_STATE_SEARCH: + /* 4 <1> Search for a matched candidate and save it to prTargetBssDesc. */ +#if CFG_SLT_SUPPORT + prBssDesc = prAdapter->rWifiVar.rSltInfo.prPseudoBssDesc; +#else + if (prAisFsmInfo->ucJoinFailCntAfterScan >= 4) { + prBssDesc = NULL; + DBGLOG(AIS, STATE, + "Failed to connect %s more than 4 times after last scan, scan again\n", + prConnSettings->aucSSID); + } else { +#if CFG_SELECT_BSS_BASE_ON_MULTI_PARAM + prBssDesc = scanSearchBssDescByScoreForAis(prAdapter); +#else + prBssDesc = scanSearchBssDescByPolicy(prAdapter, NETWORK_TYPE_AIS_INDEX); +#endif + } +#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 + DBGLOG(AIS, STATE, + "Roaming retry count :%d fail!\n", prAisFsmInfo->ucConnTrialCount); + roamingFsmRunEventFail(prAdapter, ROAMING_FAIL_REASON_CONNLIMIT); +#endif /* CFG_SUPPORT_ROAMING */ + /* reset retry count */ + prAisFsmInfo->ucConnTrialCount = 0; + + /* abort connection trial */ + if (prConnSettings->eReConnectLevel < RECONNECT_LEVEL_BEACON_TIMEOUT) { + prConnSettings->eReConnectLevel = RECONNECT_LEVEL_ROAMING_FAIL; + prConnSettings->fgIsConnReqIssued = FALSE; + } else { + DBGLOG(AIS, INFO, + "Do not set fgIsConnReqIssued, Level is %d\n", + prConnSettings->eReConnectLevel); + } + + eNextState = AIS_STATE_NORMAL_TR; + fgIsTransition = TRUE; + + break; + } + } + /* 4 <2> We are not under Roaming Condition. */ + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { + + /* 4 <2.a> If we have the matched one */ + if (prBssDesc) { + + /* + * 4 Stored the Selected BSS security cipher. + * For later asoc req compose IE + */ + prAisBssInfo->u4RsnSelectedGroupCipher = prBssDesc->u4RsnSelectedGroupCipher; + prAisBssInfo->u4RsnSelectedPairwiseCipher = + prBssDesc->u4RsnSelectedPairwiseCipher; + prAisBssInfo->u4RsnSelectedAKMSuite = prBssDesc->u4RsnSelectedAKMSuite; + + /* 4 Do STATE transition and update current Operation Mode. */ + if (prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) { + + prAisBssInfo->eCurrentOPMode = OP_MODE_INFRASTRUCTURE; + + /* Record the target BSS_DESC_T for next STATE. */ + prAisFsmInfo->prTargetBssDesc = prBssDesc; + + /* Transit to channel acquire */ + eNextState = AIS_STATE_REQ_CHANNEL_JOIN; + fgIsTransition = TRUE; + + /* increase connection trial count */ + prAisFsmInfo->ucConnTrialCount++; + } +#if CFG_SUPPORT_ADHOC + else if (prBssDesc->eBSSType == BSS_TYPE_IBSS) { + + prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; + + /* Record the target BSS_DESC_T for next STATE. */ + prAisFsmInfo->prTargetBssDesc = prBssDesc; + + eNextState = AIS_STATE_IBSS_MERGE; + fgIsTransition = TRUE; + } +#endif /* CFG_SUPPORT_ADHOC */ + else { + ASSERT(0); + eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; + fgIsTransition = TRUE; + } + } + /* 4 <2.b> If we don't have the matched one */ + else { +#if CFG_SUPPORT_RN + if (prAisBssInfo->fgDisConnReassoc == TRUE) { + /* abort connection trial */ + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = FALSE; + prAdapter->rWifiVar.rConnSettings.eReConnectLevel = RECONNECT_LEVEL_MIN; + prAisBssInfo->fgDisConnReassoc = FALSE; + aisIndicationOfMediaStateToHost(prAdapter, + PARAM_MEDIA_STATE_DISCONNECTED, FALSE); + eNextState = AIS_STATE_IDLE; + fgIsTransition = TRUE; + break; + } +#endif /* CFG_SUPPORT_RN */ + if (prAisFsmInfo->rJoinReqTime != 0 && + CHECK_FOR_TIMEOUT(kalGetTimeTick(), + prAisFsmInfo->rJoinReqTime, + SEC_TO_SYSTIME(AIS_JOIN_TIMEOUT))) { + UINT_16 u2StaTusCode = STATUS_CODE_JOIN_TIMEOUT; + + /* abort connection trial */ + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = FALSE; + prAdapter->rWifiVar.rConnSettings.eReConnectLevel = RECONNECT_LEVEL_MIN; + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_JOIN_FAILURE, + (PVOID) & u2StaTusCode, sizeof(u2StaTusCode)); + + eNextState = AIS_STATE_IDLE; + fgIsTransition = TRUE; + break; + } + /* increase connection trial count for infrastructure connection */ + if (prConnSettings->eOPMode == NET_TYPE_INFRA) + prAisFsmInfo->ucConnTrialCount++; + + /* if alway can't find traget bss, during new connect */ + GET_CURRENT_SYSTIME(&rCurrentTime); + if ((prAisBssInfo->ucReasonOfDisconnect == + DISCONNECT_REASON_CODE_NEW_CONNECTION) && + prAisFsmInfo->rJoinReqTime != 0 && + CHECK_FOR_TIMEOUT(rCurrentTime, + prAisFsmInfo->rJoinReqTime, + SEC_TO_SYSTIME(AIS_JOIN_TIMEOUT))) { + /* abort connection trial */ + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = FALSE; + prAdapter->rWifiVar.rConnSettings.eReConnectLevel + = RECONNECT_LEVEL_MIN; + + DBGLOG(AIS, WARN, + "Target BSS is NULL ,timeout and report disconnect!\n"); + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_JOIN_FAILURE, NULL, 0); + eNextState = AIS_STATE_IDLE; + fgIsTransition = TRUE; + prAisFsmInfo->rJoinReqTime = 0; + break; + } + + /* 4 Try to SCAN */ + if (prAisFsmInfo->fgTryScan) { + eNextState = AIS_STATE_LOOKING_FOR; + + fgIsTransition = TRUE; + break; + } + /* 4 We've do SCAN already, now wait in some STATE. */ + if (prConnSettings->eOPMode == NET_TYPE_INFRA) { + + /* + * issue reconnect request, + * and retreat to idle state for scheduling + */ + aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); + + eNextState = AIS_STATE_IDLE; + fgIsTransition = TRUE; + } +#if CFG_SUPPORT_ADHOC + else if ((prConnSettings->eOPMode == NET_TYPE_IBSS) + || (prConnSettings->eOPMode == NET_TYPE_AUTO_SWITCH) + || (prConnSettings->eOPMode == NET_TYPE_DEDICATED_IBSS)) { + + prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; + prAisFsmInfo->prTargetBssDesc = NULL; + + eNextState = AIS_STATE_IBSS_ALONE; + fgIsTransition = TRUE; + } +#endif /* CFG_SUPPORT_ADHOC */ + else { + ASSERT(0); + eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; + fgIsTransition = TRUE; + } + } + } + /* 4 <3> We are under Roaming Condition. */ + else { /* prAdapter->eConnectionState == MEDIA_STATE_CONNECTED. */ + + /* 4 <3.a> This BSS_DESC_T is our AP. */ + /* NOTE(Kevin 2008/05/16): Following cases will go back to NORMAL_TR. + * CASE I: During Roaming, APP(WZC/NDISTEST) change the connection + * settings. That make we can NOT match the original AP, so the + * prBssDesc is NULL. + * CASE II: The same reason as CASE I. Because APP change the + * eOPMode to other network type in connection setting + * (e.g. NET_TYPE_IBSS), so the BssDesc become the IBSS node. + * (For CASE I/II, before WZC/NDISTEST set the OID_SSID, it will change + * other parameters in connection setting first. So if we do roaming + * at the same time, it will hit these cases.) + * + * CASE III: Normal case, we can't find other candidate to roam + * out, so only the current AP will be matched. + * + * CASE IV: Timestamp of the current AP might be reset + */ + if (prAisBssInfo->ucReasonOfDisconnect != DISCONNECT_REASON_CODE_REASSOCIATION && + ((!prBssDesc) || /* CASE I */ + (prBssDesc->eBSSType != BSS_TYPE_INFRASTRUCTURE) || /* CASE II */ + (prBssDesc->fgIsConnected) || /* CASE III */ + (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID))) /* CASE IV */) { +#if DBG + if ((prBssDesc) && (prBssDesc->fgIsConnected)) + ASSERT(EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID)); +#endif /* DBG */ + if (prAisFsmInfo->fgTargetChnlScanIssued) { + /* if target channel scan has issued, + ** and no roaming target is found, need to do full scan again + */ + DBGLOG(AIS, INFO, + "[Roaming] No target found, try to full scan again\n"); + prAisFsmInfo->fgTargetChnlScanIssued = FALSE; + eNextState = AIS_STATE_LOOKING_FOR; + fgIsTransition = TRUE; + break; + } + /* We already associated with it, go back to NORMAL_TR */ + /* TODO(Kevin): Roaming Fail */ +#if CFG_SUPPORT_ROAMING + roamingFsmRunEventFail(prAdapter, ROAMING_FAIL_REASON_NOCANDIDATE); +#endif /* CFG_SUPPORT_ROAMING */ + + /* Retreat to NORMAL_TR state */ + eNextState = AIS_STATE_NORMAL_TR; + fgIsTransition = TRUE; + break; + } + + /* 4 <3.b> Try to roam out for JOIN this BSS_DESC_T. */ + if (prBssDesc == NULL) { + /* increase connection trial count for infrastructure connection */ + if (prConnSettings->eOPMode == NET_TYPE_INFRA) + prAisFsmInfo->ucConnTrialCount++; + /* 4 Try to SCAN */ + if (prAisFsmInfo->fgTryScan) { + eNextState = AIS_STATE_LOOKING_FOR; + + fgIsTransition = TRUE; + break; + } + + /* 4 We've do SCAN already, now wait in some STATE. */ + if (prConnSettings->eOPMode == NET_TYPE_INFRA) { + + /* + * issue reconnect request, and retreat to idle state + * for scheduling + */ + aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); + + eNextState = AIS_STATE_IDLE; + fgIsTransition = TRUE; + } +#if CFG_SUPPORT_ADHOC + else if ((prConnSettings->eOPMode == NET_TYPE_IBSS) + || (prConnSettings->eOPMode == NET_TYPE_AUTO_SWITCH) + || (prConnSettings->eOPMode == + NET_TYPE_DEDICATED_IBSS)) { + + prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; + prAisFsmInfo->prTargetBssDesc = NULL; + + eNextState = AIS_STATE_IBSS_ALONE; + fgIsTransition = TRUE; + } +#endif /* CFG_SUPPORT_ADHOC */ + else { + ASSERT(0); + eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; + fgIsTransition = TRUE; + } + } else { +#if DBG + if (prAisBssInfo->ucReasonOfDisconnect != + DISCONNECT_REASON_CODE_REASSOCIATION) { + ASSERT(UNEQUAL_MAC_ADDR + (prBssDesc->aucBSSID, prAisBssInfo->aucBSSID)); + } +#endif /* DBG */ + + /* 4 Record the target BSS_DESC_T for next STATE. */ + prAisFsmInfo->prTargetBssDesc = prBssDesc; + + /* tyhsu: increase connection trial count */ + prAisFsmInfo->ucConnTrialCount++; + /* stop Tx due to we need to connect a new AP. even the new + * AP is operating on the same channel with current, we still + * need to stop Tx, because firmware should ensure all mgmt and + * dhcp packets are Tx in time, and may cause normal data + * packets was queued and eventually flushed in firmware + */ + if (prAisBssInfo->prStaRecOfAP && + prAisBssInfo->ucReasonOfDisconnect != + DISCONNECT_REASON_CODE_REASSOCIATION) + prAisBssInfo->prStaRecOfAP->fgIsTxAllowed = FALSE; + /* Transit to channel acquire */ + eNextState = AIS_STATE_REQ_CHANNEL_JOIN; + /* Find target AP to roaming and set fgTargetChnlScanIssued to false */ + if (prAisFsmInfo->fgTargetChnlScanIssued) + prAisFsmInfo->fgTargetChnlScanIssued = FALSE; + fgIsTransition = TRUE; + } + } +#if (CFG_REFACTORY_PMKSA == 0) + if (prBssDesc && prConnSettings->fgOkcEnabled) { + UINT_8 aucBuf[sizeof(PARAM_PMKID_CANDIDATE_LIST_T) + sizeof(PARAM_STATUS_INDICATION_T)]; + P_PARAM_STATUS_INDICATION_T prStatusEvent = (P_PARAM_STATUS_INDICATION_T)aucBuf; + P_PARAM_PMKID_CANDIDATE_LIST_T prPmkidCandicate = + (P_PARAM_PMKID_CANDIDATE_LIST_T)(prStatusEvent+1); + UINT_32 u4Entry = 0; + + if (rsnSearchPmkidEntry(prAdapter, prBssDesc->aucBSSID, &u4Entry) && + prAdapter->rWifiVar.rAisSpecificBssInfo.arPmkidCache[u4Entry].fgPmkidExist) + break; + DBGLOG(AIS, INFO, "No PMK for %pM, try to generate a OKC PMK\n", prBssDesc->aucBSSID); + prStatusEvent->eStatusType = ENUM_STATUS_TYPE_CANDIDATE_LIST; + prPmkidCandicate->u4Version = 1; + prPmkidCandicate->u4NumCandidates = 1; + prPmkidCandicate->arCandidateList[0].u4Flags = 0; /* don't request preauth */ + COPY_MAC_ADDR(prPmkidCandicate->arCandidateList[0].arBSSID, prBssDesc->aucBSSID); + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, (PVOID)aucBuf, sizeof(aucBuf)); + cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rWaitOkcPMKTimer, AIS_WAIT_OKC_PMKID_SEC); + } +#endif + break; + + case AIS_STATE_WAIT_FOR_NEXT_SCAN: + + DBGLOG(AIS, LOUD, "SCAN: Idle Begin - Current Time = %u\n", kalGetTimeTick()); + + cnmTimerStartTimer(prAdapter, + &prAisFsmInfo->rBGScanTimer, SEC_TO_MSEC(prAisFsmInfo->u4SleepInterval)); + + SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_AIS_INDEX); + + if (prAisFsmInfo->u4SleepInterval < AIS_BG_SCAN_INTERVAL_MAX_SEC) + prAisFsmInfo->u4SleepInterval <<= 1; + break; + + case AIS_STATE_SCAN: + case AIS_STATE_ONLINE_SCAN: + case AIS_STATE_LOOKING_FOR: + +#if !CFG_SUPPORT_RLM_ACT_NETWORK + 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); + } +#else + rlmActivateNetwork(prAdapter, NETWORK_TYPE_AIS_INDEX, NET_ACTIVE_SRC_SCAN); +#endif + /* 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 + } + +#if CFG_MULTI_SSID_SCAN + if (rlmBcnRmRunning(prAdapter)) { + P_MSG_SCN_SCAN_REQ prRmReqMsg = + (P_MSG_SCN_SCAN_REQ) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + OFFSET_OF(MSG_SCN_SCAN_REQ, aucIE) + u2ScanIELen); + + if (!prRmReqMsg) { + ASSERT(0); /* Can't trigger SCAN FSM */ + return; + } + + prRmReqMsg->rMsgHdr.eMsgId = MID_AIS_SCN_SCAN_REQ; + prRmReqMsg->ucSeqNum = ++prAisFsmInfo->ucSeqNumOfScanReq; + prRmReqMsg->ucNetTypeIndex = (UINT_8) NETWORK_TYPE_AIS_INDEX; + rlmFillScanMsg(prAdapter, prRmReqMsg); + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prRmReqMsg, MSG_SEND_METHOD_BUF); + break; + } + + prScanReqMsg = (P_MSG_SCN_SCAN_REQ_V2) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + OFFSET_OF(MSG_SCN_SCAN_REQ_V2, + aucIE) + u2ScanIELen); + if (!prScanReqMsg) { + ASSERT(0); /* Can't trigger SCAN FSM */ + return; + } + + prScanReqMsg->rMsgHdr.eMsgId = MID_AIS_SCN_SCAN_REQ_V2; + prScanReqMsg->ucSeqNum = ++prAisFsmInfo->ucSeqNumOfScanReq; + prScanReqMsg->ucNetTypeIndex = (UINT_8) NETWORK_TYPE_AIS_INDEX; +#else + 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 (rlmFillScanMsg(prAdapter, prScanReqMsg)) { + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanReqMsg, MSG_SEND_METHOD_BUF); + break; + } + prScanReqMsg->u2ChannelDwellTime = 0; + prScanReqMsg->u2MinChannelDwellTime = 0; + COPY_MAC_ADDR(prScanReqMsg->aucBSSID, "\xff\xff\xff\xff\xff\xff"); +#endif + +#if CFG_SUPPORT_RDD_TEST_MODE + prScanReqMsg->eScanType = SCAN_TYPE_PASSIVE_SCAN; +#else +#ifdef CFG_TC1_FEATURE /* for Passive Scan */ + prScanReqMsg->eScanType = (ENUM_SCAN_TYPE_T)prAdapter->ucScanType; +#else + prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; +#endif +#endif + +#if CFG_SUPPORT_ROAMING_ENC + if (prAdapter->fgIsRoamingEncEnabled == TRUE) { + if (prAisFsmInfo->eCurrentState == AIS_STATE_LOOKING_FOR && + prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + prScanReqMsg->u2ChannelDwellTime = AIS_ROAMING_SCAN_CHANNEL_DWELL_TIME; + } + } +#endif /* CFG_SUPPORT_ROAMING_ENC */ + +#if CFG_MULTI_SSID_SCAN + if (prAisFsmInfo->eCurrentState == AIS_STATE_SCAN + || prAisFsmInfo->eCurrentState == AIS_STATE_ONLINE_SCAN) { + if (prAisFsmInfo->ucScanSSIDNum == 0) { + /* Scan for all available SSID */ + /* prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; */ + prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_WILDCARD; + prScanReqMsg->ucSSIDNum = 0; + } else if (prAisFsmInfo->ucScanSSIDNum == 1 && + prAisFsmInfo->arScanSSID[0].u4SsidLen == 0) { + /* prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; */ + prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_WILDCARD; + prScanReqMsg->ucSSIDNum = 0; + } else { + /* prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; */ + prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_SPECIFIED; + prScanReqMsg->ucSSIDNum = prAisFsmInfo->ucScanSSIDNum; + prScanReqMsg->prSsid = prAisFsmInfo->arScanSSID; + } + kalMemCopy(prScanReqMsg->aucRandomMac, + prAisFsmInfo->aucRandomMac, MAC_ADDR_LEN); + } else { + /* prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; */ + + COPY_SSID(prAisFsmInfo->rRoamingSSID.aucSsid, + prAisFsmInfo->rRoamingSSID.u4SsidLen, + prConnSettings->aucSSID, + prConnSettings->ucSSIDLen); + + /* Scan for determined SSID */ + prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_SPECIFIED; + prScanReqMsg->ucSSIDNum = 1; + prScanReqMsg->prSsid = &(prAisFsmInfo->rRoamingSSID); + } + + /* using default channel dwell time/timeout value */ + prScanReqMsg->u2ProbeDelay = 0; + prScanReqMsg->u2ChannelDwellTime = 0; + prScanReqMsg->u2TimeoutValue = 0; +#else + 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); + } +#endif + /* 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 (prAisFsmInfo->eCurrentState == AIS_STATE_LOOKING_FOR && + prAisFsmInfo->aucNeighborAPChnl[0] != 0) { + PUINT_8 pucChnl = &prAisFsmInfo->aucNeighborAPChnl[0]; + P_RF_CHANNEL_INFO_T prChnlInfo = &prScanReqMsg->arChnlInfoList[0]; + UINT_8 ucChnlNum = 0; + + while (pucChnl[ucChnlNum] > 0 && ucChnlNum < MAXIMUM_OPERATION_CHANNEL_LIST) { + prChnlInfo[ucChnlNum].ucChannelNum = pucChnl[ucChnlNum]; + prChnlInfo[ucChnlNum].eBand = pucChnl[ucChnlNum] > 14 ? BAND_5G:BAND_2G4; + ucChnlNum++; + } + prScanReqMsg->ucChannelListNum = ucChnlNum; + prScanReqMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; + DBGLOG(AIS, INFO, "Looking %s in %d channels, first 5 channels %d %d %d %d %d\n", + prConnSettings->aucSSID, ucChnlNum, pucChnl[0], pucChnl[1], pucChnl[2], + pucChnl[3], pucChnl[4]); + } else if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED && + prAdapter->rWifiVar.rRoamingInfo.eCurrentState == ROAMING_STATE_DISCOVERY && + prAisFsmInfo->fgTargetChnlScanIssued) { + P_RF_CHANNEL_INFO_T prChnlInfo = &prScanReqMsg->arChnlInfoList[0]; + UINT_8 ucChannelNum = 0; + UINT_8 i = 0; + + for (i = 0; i < prAdapter->rWifiVar.rAisSpecificBssInfo.ucCurEssChnlInfoNum; i++) { + ucChannelNum = + prAdapter->rWifiVar.rAisSpecificBssInfo.arCurEssChnlInfo[i].ucChannel; + if ((ucChannelNum >= 1) && (ucChannelNum <= 14)) + prChnlInfo[i].eBand = BAND_2G4; + else + prChnlInfo[i].eBand = BAND_5G; + prChnlInfo[i].ucChannelNum = ucChannelNum; + } + prScanReqMsg->ucChannelListNum = + prAdapter->rWifiVar.rAisSpecificBssInfo.ucCurEssChnlInfoNum; + prScanReqMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; + DBGLOG(AIS, INFO, + "[Roaming] Target Scan: ucChannelListNum=%d\n", prScanReqMsg->ucChannelListNum); + } else if ((prAdapter->prGlueInfo != NULL) && + (prAdapter->prGlueInfo->puScanChannel != NULL)) { + /* handle partial scan channel info */ + P_PARTIAL_SCAN_INFO channel_t; + UINT_32 u4size; + + channel_t = (P_PARTIAL_SCAN_INFO)prAdapter->prGlueInfo->puScanChannel; + + /* set partial scan */ + prScanReqMsg->ucChannelListNum = channel_t->ucChannelListNum; + u4size = sizeof(channel_t->arChnlInfoList); + + DBGLOG(AIS, TRACE, + "Partial Scan: ucChannelListNum=%d, total size=%d\n", + prScanReqMsg->ucChannelListNum, u4size); + + kalMemCopy(&(prScanReqMsg->arChnlInfoList), &(channel_t->arChnlInfoList), + u4size); + + /* clear prGlueInfo partial scan info */ + prAdapter->prGlueInfo->puScanChannel = NULL; + kalMemFree(channel_t, VIR_MEM_TYPE, sizeof(PARTIAL_SCAN_INFO)); + + /* set scan channel type for partial scan */ + prScanReqMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; +#if CFG_SUPPORT_NCHO + } else if (prAdapter->rNchoInfo.fgECHOEnabled && + prAdapter->rNchoInfo.u4RoamScanControl == TRUE && + prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED && + prAdapter->rWifiVar.rRoamingInfo.eCurrentState == ROAMING_STATE_DISCOVERY) { + /* handle NCHO scan channel info */ + UINT_32 u4size = 0; + PCFG_NCHO_SCAN_CHNL_T prRoamScnChnl = NULL; + + prRoamScnChnl = &prAdapter->rNchoInfo.rRoamScnChnl; + /* set partial scan */ + prScanReqMsg->ucChannelListNum = prRoamScnChnl->ucChannelListNum; + u4size = sizeof(prRoamScnChnl->arChnlInfoList); + + DBGLOG(AIS, TRACE, + "NCHO SCAN channel num = %d, total size=%d\n", + prScanReqMsg->ucChannelListNum, u4size); + + kalMemCopy(&(prScanReqMsg->arChnlInfoList), &(prRoamScnChnl->arChnlInfoList), + u4size); + + /* set scan channel type for NCHO scan */ + prScanReqMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; +#endif + } else { + prScanReqMsg->eScanChannel = SCAN_CHANNEL_FULL; + ASSERT(0); + } + + 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; + + if (prAdapter->rWifiVar.rRoamingInfo.eCurrentState == ROAMING_STATE_DISCOVERY) { + if (prAdapter->aeSetBand[NETWORK_TYPE_AIS_INDEX] == BAND_2G4) + prScanReqMsg->eScanChannel = SCAN_CHANNEL_2G4; + else if (prAdapter->aeSetBand[NETWORK_TYPE_AIS_INDEX] == BAND_5G) + prScanReqMsg->eScanChannel = SCAN_CHANNEL_5G; + } + + DBGLOG(AIS, TRACE, "Full2Partial eScanChannel = %d, ucChannelListNum=%d\n", + prScanReqMsg->eScanChannel, prScanReqMsg->ucChannelListNum); + /*Full2Partial at here, chech sould update full scan to partial scan or not*/ + if ((prAisFsmInfo->eCurrentState == AIS_STATE_ONLINE_SCAN) + && (prScanReqMsg->eScanChannel == SCAN_CHANNEL_FULL + || prScanReqMsg->ucChannelListNum == 0)) { + /*this is a full scan*/ + OS_SYSTIME rCurrentTime; + P_PARTIAL_SCAN_INFO channel_t; + P_GLUE_INFO_T pGlinfo; + UINT_32 u4size; + + pGlinfo = prAdapter->prGlueInfo; + GET_CURRENT_SYSTIME(&rCurrentTime); + DBGLOG(AIS, TRACE, "Full2Partial LastFullST= %d,CurrentT=%d\n", + pGlinfo->u4LastFullScanTime, rCurrentTime); + if ((pGlinfo->u4LastFullScanTime == 0) || + (CHECK_FOR_TIMEOUT(rCurrentTime, pGlinfo->u4LastFullScanTime, + SEC_TO_SYSTIME(UPDATE_FULL_TO_PARTIAL_SCAN_TIMEOUT)))) { + /*first full scan during connected*/ + /*or time over 60s from last full scan*/ + DBGLOG(AIS, INFO, "Full2Partial not update full scan\n"); + pGlinfo->u4LastFullScanTime = rCurrentTime; + pGlinfo->ucTrScanType = 1; + kalMemSet(pGlinfo->ucChannelNum, 0, FULL_SCAN_MAX_CHANNEL_NUM); + if (pGlinfo->puFullScan2PartialChannel != NULL) { + kalMemFree(pGlinfo->puFullScan2PartialChannel, + VIR_MEM_TYPE, sizeof(PARTIAL_SCAN_INFO)); + pGlinfo->puFullScan2PartialChannel = NULL; + } + } else { + DBGLOG(AIS, INFO, "Full2Partial update full scan to partial scan\n"); + + /*at here, we should update full scan to partial scan*/ + aisGetAndSetScanChannel(prAdapter); + + if (pGlinfo->puFullScan2PartialChannel != NULL) { + PUINT_8 pChanneltmp; + /* update full scan to partial scan */ + pChanneltmp = pGlinfo->puFullScan2PartialChannel; + channel_t = (P_PARTIAL_SCAN_INFO)pChanneltmp; + + /* set partial scan */ + prScanReqMsg->ucChannelListNum = channel_t->ucChannelListNum; + u4size = sizeof(channel_t->arChnlInfoList); + + DBGLOG(AIS, TRACE, "Full2Partial ChList=%d,u4size=%d\n", + channel_t->ucChannelListNum, u4size); + + kalMemCopy(&(prScanReqMsg->arChnlInfoList), + &(channel_t->arChnlInfoList), u4size); + /* set scan channel type for partial scan */ + prScanReqMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; + } + } + } + + if (prAisFsmInfo->u4ScanIELength > 0) { + kalMemCopy(prScanReqMsg->aucIE, prAisFsmInfo->aucScanIEBuf, + prAisFsmInfo->u4ScanIELength); + } else { +#if CFG_SUPPORT_WPS2 + if (prAdapter->prGlueInfo->u2WSCIELen > 0) { + kalMemCopy(prScanReqMsg->aucIE, &prAdapter->prGlueInfo->aucWSCIE, + prAdapter->prGlueInfo->u2WSCIELen); + } + } +#endif + + prScanReqMsg->u2IELen = u2ScanIELen; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanReqMsg, MSG_SEND_METHOD_BUF); + DBGLOG(AIS, TRACE, "SendSR%d\n", prScanReqMsg->ucSeqNum); + kalMemZero(prAisFsmInfo->aucRandomMac, MAC_ADDR_LEN); + prAisFsmInfo->fgTryScan = FALSE; /* Will enable background sleep for infrastructure */ + prAisFsmInfo->ucJoinFailCntAfterScan = 0; + + prAdapter->ucScanTime++; + break; + + case AIS_STATE_REQ_CHANNEL_JOIN: + + /*set timeout timer*/ + cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer + , AIS_JOIN_CH_REQUEST_INTERVAL); + + /* send message to CNM for acquiring channel */ + prMsgChReq = (P_MSG_CH_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_REQ_T)); + if (!prMsgChReq) { + ASSERT(0); /* Can't indicate CNM for channel acquiring */ + return; + } + + prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; + prMsgChReq->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + prMsgChReq->ucTokenID = ++prAisFsmInfo->ucSeqNumOfChReq; + prMsgChReq->eReqType = CH_REQ_TYPE_JOIN; + prMsgChReq->u4MaxInterval = AIS_JOIN_CH_REQUEST_INTERVAL; + + if (prAisFsmInfo->prTargetBssDesc != NULL) { + prMsgChReq->ucPrimaryChannel = prAisFsmInfo->prTargetBssDesc->ucChannelNum; + prMsgChReq->eRfSco = prAisFsmInfo->prTargetBssDesc->eSco; + prMsgChReq->eRfBand = prAisFsmInfo->prTargetBssDesc->eBand; + COPY_MAC_ADDR(prMsgChReq->aucBSSID, prAisFsmInfo->prTargetBssDesc->aucBSSID); + } + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChReq, MSG_SEND_METHOD_BUF); + + prAisFsmInfo->fgIsChannelRequested = TRUE; + break; + + case AIS_STATE_JOIN: + aisFsmStateInit_JOIN(prAdapter, prAisFsmInfo->prTargetBssDesc); + break; + +#if CFG_SUPPORT_ADHOC + case AIS_STATE_IBSS_ALONE: + aisFsmStateInit_IBSS_ALONE(prAdapter); + break; + + case AIS_STATE_IBSS_MERGE: + aisFsmStateInit_IBSS_MERGE(prAdapter, prAisFsmInfo->prTargetBssDesc); + break; +#endif /* CFG_SUPPORT_ADHOC */ + + case AIS_STATE_NORMAL_TR: + if (prAisFsmInfo->fgIsInfraChannelFinished == FALSE) { + /* Don't do anything when rJoinTimeoutTimer is still ticking */ + } else { + /* 1. Process for pending scan */ + if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, TRUE) == TRUE) { + wlanClearScanningResult(prAdapter); + eNextState = AIS_STATE_ONLINE_SCAN; + fgIsTransition = TRUE; + } + /* 2. Process for pending roaming scan */ + else if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_SEARCH, TRUE) == TRUE) { + eNextState = AIS_STATE_LOOKING_FOR; + fgIsTransition = TRUE; + } + /* 3. Process for pending roaming scan */ + else if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, TRUE) == TRUE) { + eNextState = AIS_STATE_COLLECT_ESS_INFO; + fgIsTransition = TRUE; + } else if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_REMAIN_ON_CHANNEL, TRUE) == + TRUE) { + eNextState = AIS_STATE_REQ_REMAIN_ON_CHANNEL; + fgIsTransition = TRUE; + } +#if CFG_SCAN_ABORT_HANDLE + if (prAisFsmInfo->fgIsAbortEvnetDuringScan) { + DBGLOG(AIS, WARN, "proccess the pending abort event(%d)!\n" + , prAisBssInfo->ucReasonOfDisconnect); + prAisFsmInfo->fgIsAbortEvnetDuringScan = FALSE; + aisFsmStateAbort(prAdapter, + prAisBssInfo->ucReasonOfDisconnect, + prAisBssInfo->fgIsDelayIndication); + } +#endif + } + + break; + + case AIS_STATE_DISCONNECTING: + /* send for deauth frame for disconnection */ + authSendDeauthFrame(prAdapter, + prAisBssInfo->prStaRecOfAP, + (P_SW_RFB_T) NULL, REASON_CODE_DEAUTH_LEAVING_BSS, aisDeauthXmitComplete); + cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rDeauthDoneTimer, 100); + break; + + case AIS_STATE_REQ_REMAIN_ON_CHANNEL: + /* send message to CNM for acquiring channel */ + prMsgChReq = (P_MSG_CH_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_REQ_T)); + if (!prMsgChReq) { + ASSERT(0); /* Can't indicate CNM for channel acquiring */ + return; + } + + /* release channel */ + aisFsmReleaseCh(prAdapter); + + /* zero-ize */ + kalMemZero(prMsgChReq, sizeof(MSG_CH_REQ_T)); + + /* filling */ + prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; + prMsgChReq->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + prMsgChReq->ucTokenID = ++prAisFsmInfo->ucSeqNumOfChReq; + prMsgChReq->eReqType = CH_REQ_TYPE_JOIN; + prMsgChReq->u4MaxInterval = prAisFsmInfo->rChReqInfo.u4DurationMs; + prMsgChReq->ucPrimaryChannel = prAisFsmInfo->rChReqInfo.ucChannelNum; + prMsgChReq->eRfSco = prAisFsmInfo->rChReqInfo.eSco; + prMsgChReq->eRfBand = prAisFsmInfo->rChReqInfo.eBand; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChReq, MSG_SEND_METHOD_BUF); + + prAisFsmInfo->fgIsChannelRequested = TRUE; + + break; + + case AIS_STATE_REMAIN_ON_CHANNEL: +#if !CFG_SUPPORT_RLM_ACT_NETWORK + SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX); + /* sync with firmware */ + nicActivateNetwork(prAdapter, NETWORK_TYPE_AIS_INDEX); +#else + rlmActivateNetwork(prAdapter, NETWORK_TYPE_AIS_INDEX, NET_ACTIVE_SRC_CONNECT); +#endif + break; + + case AIS_STATE_COLLECT_ESS_INFO: + { +#if CFG_SELECT_BSS_BASE_ON_MULTI_PARAM && 0 /* disable channel utilization now */ + UINT_8 i = 0; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + struct MSG_REQ_CH_UTIL *prMsgReqChUtil = NULL; + + /* don't request channel utilization if user asked to connect a specific bss */ + if (prConnSettings->eConnectionPolicy == CONNECT_BY_BSSID) { + eNextState = AIS_STATE_SEARCH; + fgIsTransition = TRUE; + break; + } + prMsgReqChUtil = (struct MSG_REQ_CH_UTIL *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(struct MSG_REQ_CH_UTIL)); + if (!prMsgReqChUtil) { + DBGLOG(AIS, ERROR, "No memory!"); + return; + } + kalMemZero(prMsgReqChUtil, sizeof(*prMsgReqChUtil)); + prMsgReqChUtil->rMsgHdr.eMsgId = MID_MNY_CNM_REQ_CH_UTIL; + prMsgReqChUtil->u2ReturnMID = MID_CNM_AIS_RSP_CH_UTIL; + prMsgReqChUtil->u2Duration = 100; /* 100ms */ + prMsgReqChUtil->ucChnlNum = prAisSpecBssInfo->ucCurEssChnlInfoNum; + for (; i < prMsgReqChUtil->ucChnlNum && i < sizeof(prMsgReqChUtil->aucChnlList); i++) + prMsgReqChUtil->aucChnlList[i] = prAisSpecBssInfo->arCurEssChnlInfo[i].ucChannel; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T)prMsgReqChUtil, MSG_SEND_METHOD_BUF); +#else + eNextState = AIS_STATE_SEARCH; + fgIsTransition = TRUE; +#endif + break; + } + + default: + ASSERT(0); /* Make sure we have handle all STATEs */ + break; + + } + } while (fgIsTransition); + + return; + +} /* end of aisFsmSteps() */ +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmSetChannelInfo(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_SCAN_REQ ScanReqMsg, IN ENUM_AIS_STATE_T CurrentState) +{ + /*get scan channel infro from prAdapter->prGlueInfo->prScanRequest*/ + struct cfg80211_scan_request *scan_req_t = NULL; + struct ieee80211_channel *channel_tmp = NULL; + int i = 0; + int j = 0; + UINT_8 channel_num = 0; + UINT_8 channel_counts = 0; + + if ((prAdapter == NULL) || (ScanReqMsg == NULL)) + return; + if ((CurrentState == AIS_STATE_SCAN) || (CurrentState == AIS_STATE_ONLINE_SCAN)) { + if (prAdapter->prGlueInfo->prScanRequest != NULL) { + scan_req_t = prAdapter->prGlueInfo->prScanRequest; + if ((scan_req_t != NULL) && (scan_req_t->n_channels != 0) && + (scan_req_t->channels != NULL)) { + channel_counts = scan_req_t->n_channels; + DBGLOG(AIS, TRACE, "channel_counts=%d\n", channel_counts); + + while (j < channel_counts) { + channel_tmp = scan_req_t->channels[j]; + if (channel_tmp == NULL) + break; + + DBGLOG(AIS, TRACE, "set channel band=%d\n", channel_tmp->band); + if (channel_tmp->band >= IEEE80211_BAND_60GHZ) { + j++; + continue; + } + if (i >= MAXIMUM_OPERATION_CHANNEL_LIST) + break; + if (channel_tmp->band == IEEE80211_BAND_2GHZ) + ScanReqMsg->arChnlInfoList[i].eBand = BAND_2G4; + else if (channel_tmp->band == IEEE80211_BAND_5GHZ) + ScanReqMsg->arChnlInfoList[i].eBand = BAND_5G; + + DBGLOG(AIS, TRACE, "set channel channel_rer =%d\n", + channel_tmp->center_freq); + + channel_num = (UINT_8)nicFreq2ChannelNum( + channel_tmp->center_freq * 1000); + + DBGLOG(AIS, TRACE, "set channel channel_num=%d\n", + channel_num); + ScanReqMsg->arChnlInfoList[i].ucChannelNum = channel_num; + + j++; + i++; + } + } + } + } + + DBGLOG(AIS, INFO, "set channel i=%d\n", i); + if (i > 0) { + ScanReqMsg->ucChannelListNum = i; + ScanReqMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; + + return; + } + + if (prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] + == BAND_NULL) { + if (prAdapter->fgEnable5GBand == TRUE) + ScanReqMsg->eScanChannel = SCAN_CHANNEL_FULL; + else + ScanReqMsg->eScanChannel = SCAN_CHANNEL_2G4; + } else if (prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] + == BAND_2G4) { + ScanReqMsg->eScanChannel = SCAN_CHANNEL_2G4; + } else if (prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] + == BAND_5G) { + ScanReqMsg->eScanChannel = SCAN_CHANNEL_5G; + } else { + ScanReqMsg->eScanChannel = SCAN_CHANNEL_FULL; + ASSERT(0); + } + + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ + +VOID aisFsmRunEventScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_SCN_SCAN_DONE prScanDoneMsg; + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + UINT_8 ucSeqNumOfCompMsg; + P_CONNECTION_SETTINGS_T prConnSettings; + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq = &prAdapter->rWifiVar.rRmReqParams; + struct BCN_RM_PARAMS *prBcnRmParam = &prRmReq->rBcnRmParam; + + DEBUGFUNC("aisFsmRunEventScanDone()"); + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + ucScanTimeoutTimes = 0; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + prScanDoneMsg = (P_MSG_SCN_SCAN_DONE) prMsgHdr; + ASSERT(prScanDoneMsg->ucNetTypeIndex == (UINT_8) NETWORK_TYPE_AIS_INDEX); + + ucSeqNumOfCompMsg = prScanDoneMsg->ucSeqNum; + cnmMemFree(prAdapter, prMsgHdr); + + eNextState = prAisFsmInfo->eCurrentState; + + + if (ucSeqNumOfCompMsg != prAisFsmInfo->ucSeqNumOfScanReq) { + DBGLOG(AIS, WARN, "SEQ NO of AIS SCN DONE MSG is not matched %d %d.\n", + ucSeqNumOfCompMsg, prAisFsmInfo->ucSeqNumOfScanReq); + } else { + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_SCAN: + prConnSettings->fgIsScanReqIssued = FALSE; + + /* reset scan IE buffer */ + prAisFsmInfo->u4ScanIELength = 0; + + kalScanDone(prAdapter->prGlueInfo, KAL_NETWORK_TYPE_AIS_INDEX, WLAN_STATUS_SUCCESS); + eNextState = AIS_STATE_IDLE; +#if CFG_SUPPORT_AGPS_ASSIST + scanReportScanResultToAgps(prAdapter); +#endif + break; + + case AIS_STATE_ONLINE_SCAN: + prConnSettings->fgIsScanReqIssued = FALSE; + + /* reset scan IE buffer */ + prAisFsmInfo->u4ScanIELength = 0; + + kalScanDone(prAdapter->prGlueInfo, KAL_NETWORK_TYPE_AIS_INDEX, WLAN_STATUS_SUCCESS); +#if CFG_SUPPORT_ROAMING + eNextState = aisFsmRoamingScanResultsUpdate(prAdapter); +#else + eNextState = AIS_STATE_NORMAL_TR; +#endif /* CFG_SUPPORT_ROAMING */ +#if CFG_SUPPORT_AGPS_ASSIST + scanReportScanResultToAgps(prAdapter); +#endif +#if CFG_SELECT_BSS_BASE_ON_MULTI_PARAM + scanGetCurrentEssChnlList(prAdapter); +#endif + break; + + case AIS_STATE_LOOKING_FOR: + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); + scanReportBss2Cfg80211(prAdapter, BSS_TYPE_INFRASTRUCTURE, NULL); +#if CFG_SUPPORT_ROAMING + eNextState = aisFsmRoamingScanResultsUpdate(prAdapter); +#else + eNextState = AIS_STATE_COLLECT_ESS_INFO; +#endif /* CFG_SUPPORT_ROAMING */ +#if CFG_SELECT_BSS_BASE_ON_MULTI_PARAM + scanGetCurrentEssChnlList(prAdapter); +#endif + + break; + + default: + DBGLOG(AIS, WARN, "current state[%d],ScanSeqNum=%d can't report SCAN_DONE!\n", + prAisFsmInfo->eCurrentState, prAisFsmInfo->ucSeqNumOfScanReq); + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); + break; + + } + } + aisRemoveOldestBcnTimeout(prAisFsmInfo); + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); + + if (prBcnRmParam->eState == RM_NO_REQUEST) + return; + /* normal mode scan done, and beacon measurement is pending, schedule to do measurement */ + if (prBcnRmParam->eState == RM_WAITING) { + rlmDoBeaconMeasurement(prAdapter, 0); + } else if (prBcnRmParam->rNormalScan.fgExist) {/* pending normal scan here, should schedule it on time */ + struct NORMAL_SCAN_PARAMS *prParam = &prBcnRmParam->rNormalScan; + + DBGLOG(AIS, INFO, "Schedule normal scan after a beacon measurement done\n"); + prBcnRmParam->eState = RM_WAITING; + prBcnRmParam->rNormalScan.fgExist = FALSE; + cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer, + SEC_TO_MSEC(AIS_SCN_DONE_TIMEOUT_SEC)); + aisFsmScanRequestAdv(prAdapter, prParam->ucSsidNum, prParam->arSSID, + prParam->aucScanIEBuf, prParam->u4IELen, prParam->aucRandomMac); + } else /* Radio Measurement is on-going, schedule to next Measurement Element */ + rlmStartNextMeasurement(prAdapter, FALSE); + +} /* end of aisFsmRunEventScanDone() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_AIS_ABORT_T prAisAbortMsg; + P_AIS_FSM_INFO_T prAisFsmInfo; + UINT_8 ucReasonOfDisconnect; + BOOLEAN fgDelayIndication; + P_CONNECTION_SETTINGS_T prConnSettings; + + DEBUGFUNC("aisFsmRunEventAbort()"); + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* 4 <1> Extract information of Abort Message and then free memory. */ + prAisAbortMsg = (P_MSG_AIS_ABORT_T) prMsgHdr; + ucReasonOfDisconnect = prAisAbortMsg->ucReasonOfDisconnect; + fgDelayIndication = prAisAbortMsg->fgDelayIndication; + + cnmMemFree(prAdapter, prMsgHdr); + +#if DBG + DBGLOG(AIS, STATE, "EVENT-ABORT: Current State %s %d\n", + apucDebugAisState[prAisFsmInfo->eCurrentState], ucReasonOfDisconnect); +#else + DBGLOG(AIS, STATE, "[%d] EVENT-ABORT: Current State [%d %d] fgIsConnReqIssue:%d\n", + DBG_AIS_IDX, prAisFsmInfo->eCurrentState, ucReasonOfDisconnect + , prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued); + +#endif + + GET_CURRENT_SYSTIME(&(prAisFsmInfo->rJoinReqTime)); + + /* 4 <2> clear previous pending connection request and insert new one */ + if (ucReasonOfDisconnect == DISCONNECT_REASON_CODE_DEAUTHENTICATED + || ucReasonOfDisconnect == DISCONNECT_REASON_CODE_DISASSOCIATED) { + P_STA_RECORD_T prSta = prAisFsmInfo->prTargetStaRec; + P_BSS_DESC_T prBss = prAisFsmInfo->prTargetBssDesc; + + if (prSta && prBss && prSta->u2ReasonCode == REASON_CODE_DISASSOC_AP_OVERLOAD) { + struct AIS_BLACKLIST_ITEM *prBlackList = aisAddBlacklist(prAdapter, prBss); + + if (prBlackList) + prBlackList->u2DeauthReason = prSta->u2ReasonCode; + } + if (prAisFsmInfo->prTargetBssDesc) + prAisFsmInfo->prTargetBssDesc->fgDeauthLastTime = TRUE; + prConnSettings->fgIsDisconnectedByNonRequest = TRUE; + } else { + prConnSettings->fgIsDisconnectedByNonRequest = FALSE; + } + /* to support user space triggered roaming */ + if (ucReasonOfDisconnect == DISCONNECT_REASON_CODE_ROAMING && + prAisFsmInfo->eCurrentState != AIS_STATE_DISCONNECTING) { + + if (prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR && + prAisFsmInfo->fgIsInfraChannelFinished == TRUE) { + aisFsmSteps(prAdapter, AIS_STATE_COLLECT_ESS_INFO); + } else { + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_SEARCH, TRUE); + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, TRUE); + aisFsmInsertRequest(prAdapter, AIS_REQUEST_ROAMING_CONNECT); + } + return; + } +#if CFG_SELECT_BSS_BASE_ON_MULTI_PARAM + scanGetCurrentEssChnlList(prAdapter); +#endif + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_RECONNECT, TRUE); + aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); + + if (prAisFsmInfo->eCurrentState != AIS_STATE_DISCONNECTING) { + /* 4 <3> invoke abort handler */ + aisFsmStateAbort(prAdapter, ucReasonOfDisconnect, fgDelayIndication); + } + +} /* end of aisFsmRunEventAbort() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function handles AIS-FSM abort event/command +* +* \param[in] prAdapter Pointer of ADAPTER_T +* ucReasonOfDisconnect Reason for disonnection +* fgDelayIndication Option to delay disconnection indication +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmStateAbort(IN P_ADAPTER_T prAdapter, UINT_8 ucReasonOfDisconnect, BOOLEAN fgDelayIndication) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + BOOLEAN fgIsCheckConnected; + + ASSERT(prAdapter); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + fgIsCheckConnected = FALSE; + + /* 4 <1> Save information of Abort Message and then free memory. */ + prAisBssInfo->ucReasonOfDisconnect = ucReasonOfDisconnect; + prAisBssInfo->fgIsDelayIndication = fgDelayIndication; + + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED && + prAisFsmInfo->eCurrentState != AIS_STATE_DISCONNECTING && + ucReasonOfDisconnect != DISCONNECT_REASON_CODE_REASSOCIATION && + ucReasonOfDisconnect != DISCONNECT_REASON_CODE_ROAMING) + wmmNotifyDisconnected(prAdapter); + + /* 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: +#if CFG_SCAN_ABORT_HANDLE + /* + * when driver received the disconnected event from AP. + * driver will insert a AIS_REQUEST_SCAN, it leads scan request not match when scan_done report before! + * AIS_FSM poended the abort event and wait scan_done to report to upper layer and process + * the disconnected event from AP at Idle state! + */ + if ((ucReasonOfDisconnect == DISCONNECT_REASON_CODE_RADIO_LOST) || + (ucReasonOfDisconnect == DISCONNECT_REASON_CODE_DEAUTHENTICATED) || + (ucReasonOfDisconnect == DISCONNECT_REASON_CODE_DISASSOCIATED)) { + prAisFsmInfo->fgIsAbortEvnetDuringScan = TRUE; + DBGLOG(AIS, INFO, "Reason code:%d! Postpone the evnet of abort for AIS scanning\n" + , prAisBssInfo->ucReasonOfDisconnect); + return; + } +#endif + /* Do abort SCAN */ + aisFsmStateAbort_SCAN(prAdapter); + +#if CFG_SCAN_ABORT_HANDLE + /* To avoid the AIS_FSM took a lot of time to connect and leads to scan pending too long + * AIS_FSM abort scan and wait scan_done (scan_cancel) to report to upper layer + * and process AIS_REQUEST_RECONNECT at Idle state. + */ + if (ucReasonOfDisconnect == DISCONNECT_REASON_CODE_NEW_CONNECTION + && prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued == TRUE) { + DBGLOG(AIS, WARN, "Reason code:%d! Abort the AIS scanning and wait for AIS scan done!\n" + , prAisBssInfo->ucReasonOfDisconnect); + return; + } +#endif + /* 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; + + /* stop okc timeout timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rWaitOkcPMKTimer); + 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: +#if CFG_SCAN_ABORT_HANDLE + /* + * when driver received the disconnected event from AP. + * driver will insert a AIS_REQUEST_SCAN, it leads scan request not match when scan_done report before! + * AIS_FSM poended the abort event and wait scan_done to report to upper layer and process + * the disconnected event from AP at Idle state! + */ + if ((ucReasonOfDisconnect == DISCONNECT_REASON_CODE_RADIO_LOST) || + (ucReasonOfDisconnect == DISCONNECT_REASON_CODE_DEAUTHENTICATED) || + (ucReasonOfDisconnect == DISCONNECT_REASON_CODE_DISASSOCIATED)) { + prAisFsmInfo->fgIsAbortEvnetDuringScan = TRUE; + DBGLOG(AIS, INFO, "Reason code:%d! Postpone the evnet of abort for AIS online scanning\n" + , prAisBssInfo->ucReasonOfDisconnect); + return; + } +#endif + /* Do abort SCAN */ + aisFsmStateAbort_SCAN(prAdapter); + +#if CFG_SCAN_ABORT_HANDLE + /* New connection will abort the scan + * To avoid the AIS_FSM took a lot of time to connect and leads to scan pending too long + * AIS_FSM abort scan and wait scan_done (scan_cancel) to report to upper layer + * and process AIS_REQUEST_RECONNECT at Idle state. + */ + if (ucReasonOfDisconnect == DISCONNECT_REASON_CODE_NEW_CONNECTION + && prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued == TRUE) { + DBGLOG(AIS, WARN, "Reason code:%d! Abort the AIS scanning and wait for AIS scan done!\n" + , prAisBssInfo->ucReasonOfDisconnect); + return; + } +#endif + /* queue for later handling */ + if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, FALSE) == FALSE) + aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); + + fgIsCheckConnected = TRUE; + break; + + case AIS_STATE_NORMAL_TR: + fgIsCheckConnected = TRUE; + break; + + case AIS_STATE_DISCONNECTING: + /* Do abort NORMAL_TR */ + aisFsmStateAbort_NORMAL_TR(prAdapter); + + break; + + case AIS_STATE_REQ_REMAIN_ON_CHANNEL: + /* release channel */ + aisFsmReleaseCh(prAdapter); + break; + + case AIS_STATE_REMAIN_ON_CHANNEL: + /* 1. release channel */ + aisFsmReleaseCh(prAdapter); + + /* 2. stop channel timeout timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer); + + break; + + default: + break; + } + + if (fgIsCheckConnected && (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED)) { + + /* switch into DISCONNECTING state for sending DEAUTH if necessary */ + if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE && + prAisBssInfo->ucReasonOfDisconnect == DISCONNECT_REASON_CODE_NEW_CONNECTION && + prAisBssInfo->prStaRecOfAP && prAisBssInfo->prStaRecOfAP->fgIsInUse) { + aisFsmSteps(prAdapter, AIS_STATE_DISCONNECTING); + + return; + } + /* Do abort NORMAL_TR */ + aisFsmStateAbort_NORMAL_TR(prAdapter); + + } + + if (!fgDelayIndication) + kalMemZero(prAisFsmInfo->aucNeighborAPChnl, CFG_NEIGHBOR_AP_CHANNEL_NUM); + + rlmCancelRadioMeasurement(prAdapter); + /* restore tx power control */ + rlmSetMaxTxPwrLimit(prAdapter, 0, 0); + aisFsmDisconnect(prAdapter, fgDelayIndication); + + +} /* end of aisFsmStateAbort() */ + +#if CFG_SUPPORT_DETECT_ATHEROS_AP +VOID configDelBaToFw(P_ADAPTER_T prAdapter, BOOLEAN fgEnable) +{ + struct _CMD_HEADER_T *pcmdV1Header = NULL; + UINT_8 itemString[] = "CoexRemoveBA"; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + struct _CMD_FORMAT_V1_T *pr_cmd_v1 = NULL; + + pcmdV1Header = (struct _CMD_HEADER_T *) kalMemAlloc(sizeof(struct _CMD_HEADER_T), VIR_MEM_TYPE); + if (pcmdV1Header == NULL) + return; + + kalMemSet(pcmdV1Header->buffer, 0, MAX_CMD_BUFFER_LENGTH); + + pr_cmd_v1 = (struct _CMD_FORMAT_V1_T *) pcmdV1Header->buffer; + pr_cmd_v1->itemStringLength = strlen(itemString); + kalMemCopy(pr_cmd_v1->itemString, itemString, pr_cmd_v1->itemStringLength); + pr_cmd_v1->itemType = 1; + pr_cmd_v1->itemValueLength = 1; + if (fgEnable) + kalMemCopy(pr_cmd_v1->itemValue, "1", pr_cmd_v1->itemValueLength); + else + kalMemCopy(pr_cmd_v1->itemValue, "0", pr_cmd_v1->itemValueLength); + + pcmdV1Header->cmdVersion = CMD_VER_1_EXT; + pcmdV1Header->cmdType = CMD_TYPE_SET; + pcmdV1Header->itemNum = 1; + pcmdV1Header->cmdBufferLen = sizeof(struct _CMD_FORMAT_V1_T); + + rStatus = wlanSendSetQueryCmd(prAdapter, CMD_ID_GET_SET_CUSTOMER_CFG, + TRUE, FALSE, FALSE, + NULL, NULL, + sizeof(struct _CMD_HEADER_T), + (PUINT_8) pcmdV1Header, + NULL, 0); + kalMemFree(pcmdV1Header, VIR_MEM_TYPE, sizeof(struct _CMD_HEADER_T)); + + if (rStatus == WLAN_STATUS_FAILURE) + DBGLOG(INIT, ERROR, "wifiSefCFG fail 0x%x\n", rStatus); +} + +VOID aisSendBaCmdByAtherosAp(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc) +{ + static BOOLEAN fgSetDelBatoFw = FALSE; + + if (fgSetDelBatoFw) { + configDelBaToFw(prAdapter, FALSE); + fgSetDelBatoFw = FALSE; + } + + if (prBssDesc) { + if (prBssDesc->fgIsAtherosAP) { + DBGLOG(AIS, INFO, "Connect to AtherosAP,Del BA\n"); + configDelBaToFw(prAdapter, TRUE); + fgSetDelBatoFw = TRUE; + } + } else { + return; + } +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Join Complete Event from SAA FSM for AIS FSM +* +* @param[in] prMsgHdr Message of Join Complete of SAA FSM. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventJoinComplete(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_JOIN_COMP_T prJoinCompMsg; + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + P_STA_RECORD_T prStaRec; + P_SW_RFB_T prAssocRspSwRfb; + P_BSS_INFO_T prAisBssInfo; + UINT_8 aucP2pSsid[] = CTIA_MAGIC_SSID; + OS_SYSTIME rCurrentTime; + P_CONNECTION_SETTINGS_T prConnSettings; + UINT_16 u2StatusCode = 0; +#if CFG_SUPPORT_ROAMING_RETRY + P_LINK_T prEssLink = NULL; + BOOLEAN fgIsUnderRoaming; +#endif + + DEBUGFUNC("aisFsmRunEventJoinComplete()"); + + ASSERT(prMsgHdr); + + GET_CURRENT_SYSTIME(&rCurrentTime); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prJoinCompMsg = (P_MSG_JOIN_COMP_T) prMsgHdr; + prStaRec = prJoinCompMsg->prStaRec; + prAssocRspSwRfb = prJoinCompMsg->prSwRfb; +#if CFG_SUPPORT_ROAMING_RETRY + prEssLink = &prAdapter->rWifiVar.rAisSpecificBssInfo.rCurEssLink; + fgIsUnderRoaming = FALSE; +#endif + eNextState = prAisFsmInfo->eCurrentState; + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + + DBGLOG(AIS, TRACE, "AISOK\n"); + + /* Check State and SEQ NUM */ + do { + if (prAisFsmInfo->eCurrentState != AIS_STATE_JOIN) + break; + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + +#if CFG_SUPPORT_RN + GET_CURRENT_SYSTIME(&prAisBssInfo->rConnTime); +#endif + /* Check SEQ NUM */ + if (prJoinCompMsg->ucSeqNum != prAisFsmInfo->ucSeqNumOfReqMsg) { +#if DBG + DBGLOG(AIS, WARN, "SEQ NO of AIS JOIN COMP MSG is not matched.\n"); +#endif + break; + } + + /* 4 <1> JOIN was successful */ + if (prJoinCompMsg->rJoinStatus == WLAN_STATUS_SUCCESS) { +#if CFG_SUPPORT_RN + prAisBssInfo->fgDisConnReassoc = FALSE; +#endif + /* 1. Reset retry count */ + prAisFsmInfo->ucConnTrialCount = 0; + prAdapter->rWifiVar.rConnSettings.eReConnectLevel = RECONNECT_LEVEL_MIN; + /* 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 { + kalMemZero(&prAdapter->prGlueInfo->rNetDevStats, + sizeof(prAdapter->prGlueInfo->rNetDevStats)); + + /* 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); + cnmStaRecFree(prAdapter, prAisBssInfo->prStaRecOfAP, TRUE); + } + prAisFsmInfo->prTargetBssDesc->fgDeauthLastTime = FALSE; + /* 4 <1.3> Update BSS_INFO_T */ + aisUpdateBssInfoForJOIN(prAdapter, prStaRec, prAssocRspSwRfb); + + /* 4 <1.4> Activate current AP's STA_RECORD_T in Driver. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + /* 4 <1.5> Update RSSI if necessary */ + nicUpdateRSSI(prAdapter, NETWORK_TYPE_AIS_INDEX, + (INT_8) (RCPI_TO_dBm(prStaRec->ucRCPI)), 0); + + /* 4 <1.6> Indicate Connected Event to Host immediately. */ + /* Require BSSID, Association ID, Beacon Interval.. */ + /* from AIS_BSS_INFO_T */ + aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, + FALSE); + + /* add for ctia mode */ + if (EQUAL_SSID(aucP2pSsid, CTIA_MAGIC_SSID_LEN, prAisBssInfo->aucSSID, + prAisBssInfo->ucSSIDLen)) { + nicEnterCtiaMode(prAdapter, TRUE, FALSE); + } + } + + kalMemZero(prAisFsmInfo->aucNeighborAPChnl, CFG_NEIGHBOR_AP_CHANNEL_NUM); + aisSendNeighborRequest(prAdapter); + +#if CFG_SUPPORT_ROAMING + /* if bssid is given, it means we no need fw roaming */ + if ((prAdapter->rWifiVar.rConnSettings.eConnectionPolicy != CONNECT_BY_BSSID) + && (prAdapter->rWifiVar.rRoamingInfo.DrvRoamingAllow == 1)) + roamingFsmRunEventStart(prAdapter); +#endif /* CFG_SUPPORT_ROAMING */ + + /* clear rJoinReqTime if there is no more framework roaming connect request */ + if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, FALSE) == FALSE) + prAisFsmInfo->rJoinReqTime = 0; + + prAisFsmInfo->ucJoinFailCntAfterScan = 0; + /* 4 <1.7> Set the Next State of AIS FSM */ + eNextState = AIS_STATE_NORMAL_TR; +#if CFG_SUPPORT_DYNAMIC_ROAM + aisFsmSetRoamingThreshold(prAdapter, AIS_DEFAULT_ROAMING_THRESHOLD); +#endif + } + /* 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; + PARAM_SSID_T rSsid; + P_CONNECTION_SETTINGS_T prConnSettings; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prBssDesc = prAisFsmInfo->prTargetBssDesc; + + /* 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; + prAisFsmInfo->ucJoinFailCntAfterScan++; + + kalMemZero(&rSsid, sizeof(PARAM_SSID_T)); + if (prBssDesc) + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + else + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, + prConnSettings->aucSSID, prConnSettings->ucSSIDLen); + + prBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, + prStaRec->aucMacAddr, TRUE, &rSsid); + + if (prBssDesc == NULL) { + /* it maybe NULL when wlanRemove */ + /* + (1) UI does wifi off during SAA does auth/assoc procedure. + (2) We will do LINK_INITIALIZE(&prScanInfo->rBSSDescList); + in nicUninitMGMT(). + (3) We will handle prMsduInfo->pfTxDoneHandler + in nicTxRelease(). + (4) prMsduInfo->pfTxDoneHandler will point to + saaFsmRunEventTxDone(). + (5) Then jump to saaFsmSteps() -> saaFsmSendEventJoinComplete() + (6) Finally mboxSendMsg() -> aisFsmRunEventJoinComplete(). + (7) In aisFsmRunEventJoinComplete(), we will check + "prBssDesc = scanSearchBssDescByBssid(prAdapter, + prStaRec->aucMacAddr);" + (8) And prBssDesc will be NULL and hangs in + "ASSERT(prBssDesc->fgIsConnecting);" when DBG=0. + ASSERT(prBssDesc); + ASSERT(prBssDesc->fgIsConnecting); + */ + aisFsmStateAbort(prAdapter, + DISCONNECT_REASON_CODE_DEAUTHENTICATED, FALSE); + break; + } + DBGLOG(AIS, TRACE, + "ucJoinFailureCount=%d %d, Status=%d Reason=%d, eConnectionState=%d, fgDisConnReassoc=%d\n", + prStaRec->ucJoinFailureCount, prBssDesc->ucJoinFailureCount, + prStaRec->u2StatusCode, prStaRec->u2ReasonCode, + prAisBssInfo->eConnectionState, prAisBssInfo->fgDisConnReassoc); + + /* ASSERT(prBssDesc); */ + /* ASSERT(prBssDesc->fgIsConnecting); */ + u2StatusCode = prStaRec->u2StatusCode; + prBssDesc->ucJoinFailureCount++; + if (prBssDesc->ucJoinFailureCount >= SCN_BSS_JOIN_FAIL_THRESOLD) { + aisAddBlacklist(prAdapter, prBssDesc); + GET_CURRENT_SYSTIME(&prBssDesc->rJoinFailTime); + DBGLOG(AIS, INFO, + "Bss %pM join fail %d > %d times,temp disable it at time:%u\n", + prBssDesc->aucBSSID, + prBssDesc->ucJoinFailureCount, + SCN_BSS_JOIN_FAIL_THRESOLD, + prBssDesc->rJoinFailTime); + } + if (prBssDesc->prBlack) + prBssDesc->prBlack->u2AuthStatus = prStaRec->u2StatusCode; + + 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 + if (prAisBssInfo->prStaRecOfAP) + prAisBssInfo->prStaRecOfAP->fgIsTxAllowed = TRUE; +#if CFG_SUPPORT_ROAMING_RETRY + /*Under roamming case : After candidate BSS joined fail.*/ + /*STA will re-try other BSS.*/ + DBGLOG(AIS, INFO, + "Under roamming %pM join fail and STA will re-try other AP\n", + prBssDesc->aucBSSID); + prBssDesc->fgIsRoamFail = TRUE; + fgIsUnderRoaming = TRUE; + + eNextState = AIS_STATE_COLLECT_ESS_INFO; +#else + eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; +#endif /* CFG_SUPPORT_ROAMING_RETRY */ + if (prConnSettings->eConnectionPolicy == CONNECT_BY_BSSID && + (u2StatusCode == STATUS_CODE_ASSOC_DENIED_AP_OVERLOAD || + u2StatusCode == STATUS_CODE_ASSOC_DENIED_OUTSIDE_STANDARD)) { + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, + (PVOID)&u2StatusCode, + sizeof(u2StatusCode)); + prAisBssInfo->eConnectionStateIndicated = + PARAM_MEDIA_STATE_DISCONNECTED; + eNextState = AIS_STATE_IDLE; + } +#endif /* CFG_SUPPORT_ROAMING */ +#if CFG_SUPPORT_RN + } else if (prAisBssInfo->fgDisConnReassoc == TRUE) { + /* abort connection trial */ + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = FALSE; + prAdapter->rWifiVar.rConnSettings.eReConnectLevel = RECONNECT_LEVEL_MIN; + + prAisBssInfo->u2DeauthReason = prStaRec->u2ReasonCode; + + prAisBssInfo->fgDisConnReassoc = FALSE; + aisIndicationOfMediaStateToHost(prAdapter, + PARAM_MEDIA_STATE_DISCONNECTED, FALSE); + /* restore tx power control */ + rlmSetMaxTxPwrLimit(prAdapter, 0, 0); + eNextState = AIS_STATE_IDLE; +#endif + } else if (prAisFsmInfo->rJoinReqTime != 0 && + CHECK_FOR_TIMEOUT(rCurrentTime, + prAisFsmInfo->rJoinReqTime, + SEC_TO_SYSTIME(AIS_JOIN_TIMEOUT))) { + /* abort connection trial */ + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = FALSE; + prAdapter->rWifiVar.rConnSettings.eReConnectLevel = RECONNECT_LEVEL_MIN; + /* restore tx power control */ + rlmSetMaxTxPwrLimit(prAdapter, 0, 0); + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_JOIN_FAILURE, + (PVOID)&u2StatusCode, + sizeof(u2StatusCode)); + + eNextState = AIS_STATE_IDLE; + /* Don't send join fail if this join is the driver retry join (rJoinReqTime == 0) */ + } else if (prAisFsmInfo->rJoinReqTime != 0 && + prBssDesc->ucJoinFailureCount >= SCN_BSS_JOIN_FAIL_THRESOLD) { + /*Avoid STA to retry connect AP fenqency and printk too much.*/ + /*abort connection trial */ + DBGLOG(AIS, INFO, + "Bss %pM join fail over %d,response upper layer to connect fail\n", + prBssDesc->aucBSSID, SCN_BSS_JOIN_FAIL_THRESOLD); + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = FALSE; + prAdapter->rWifiVar.rConnSettings.eReConnectLevel = RECONNECT_LEVEL_MIN; + /* restore tx power control */ + rlmSetMaxTxPwrLimit(prAdapter, 0, 0); + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_JOIN_FAILURE, + (PVOID)&u2StatusCode, + sizeof(u2StatusCode)); + + eNextState = AIS_STATE_IDLE; + } else { + /* 4.b send reconnect request */ + aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); + eNextState = AIS_STATE_IDLE; + } + +#if CFG_SUPPORT_ROAMING_RETRY + if (fgIsUnderRoaming == TRUE && + prEssLink->u4NumElem > AIS_ROAMING_RETRY_BSS_THRESHOLD) { + /*Under roaming case : After candidate BSS joined fail.*/ + /*STA will re-try other BSS.*/ + /*if roaming failure was over then AIS_ROAMING_CONNECTION_TRIAL_LIMIT */ + /*ROAM_FSM was stopped and AIS_FSM was transferred to NORMAL_TR.*/ + DBGLOG(AIS, INFO, + "Under roamming %pM join fail and STA will re-try other AP :%d\n" + , prBssDesc->aucBSSID + , prEssLink->u4NumElem); + prBssDesc->fgIsRoamFail = TRUE; + fgIsUnderRoaming = FALSE; + eNextState = AIS_STATE_COLLECT_ESS_INFO; + } +#endif /* CFG_SUPPORT_ROAMING_RETRY */ + } + } + + /* try to remove timeout blacklist item */ + aisRemoveDisappearedBlacklist(prAdapter); + + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); + } while (FALSE); + + if (prAssocRspSwRfb) + nicRxReturnRFB(prAdapter, prAssocRspSwRfb); + + cnmMemFree(prAdapter, prMsgHdr); + +} /* end of aisFsmRunEventJoinComplete() */ + +#if CFG_SUPPORT_ADHOC +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Grant Msg of IBSS Create which was sent by +* CNM to indicate that channel was changed for creating IBSS. +* +* @param[in] prAdapter Pointer of ADAPTER_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmCreateIBSS(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + + ASSERT(prAdapter); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + do { + /* Check State */ + if (prAisFsmInfo->eCurrentState == AIS_STATE_IBSS_ALONE) + aisUpdateBssInfoForCreateIBSS(prAdapter); + } while (FALSE); + +} /* end of aisFsmCreateIBSS() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Grant Msg of IBSS Merge which was sent by +* CNM to indicate that channel was changed for merging IBSS. +* +* @param[in] prAdapter Pointer of ADAPTER_T +* @param[in] prStaRec Pointer of STA_RECORD_T for merge +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmMergeIBSS(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + P_BSS_INFO_T prAisBssInfo; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + do { + + eNextState = prAisFsmInfo->eCurrentState; + + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_IBSS_MERGE: + { + P_BSS_DESC_T prBssDesc; + + /* 4 <1.1> Change FW's Media State immediately. */ + aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); + + /* 4 <1.2> Deactivate previous Peers' STA_RECORD_T in Driver if have. */ + bssClearClientList(prAdapter, prAisBssInfo); + + /* 4 <1.3> Unmark connection flag of previous BSS_DESC_T. */ + prBssDesc = scanSearchBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); + if (prBssDesc != NULL) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = FALSE; + } + /* 4 <1.4> Update BSS_INFO_T */ + aisUpdateBssInfoForMergeIBSS(prAdapter, prStaRec); + + /* 4 <1.5> Add Peers' STA_RECORD_T to Client List */ + bssAddStaRecToClientList(prAdapter, prAisBssInfo, prStaRec); + + /* 4 <1.6> Activate current Peer's STA_RECORD_T in Driver. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + prStaRec->fgIsMerging = FALSE; + + /* 4 <1.7> Enable other features */ + + /* 4 <1.8> Indicate Connected Event to Host immediately. */ + aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, FALSE); + + /* 4 <1.9> Set the Next State of AIS FSM */ + eNextState = AIS_STATE_NORMAL_TR; + + /* 4 <1.10> Release channel privilege */ + aisFsmReleaseCh(prAdapter); + +#if CFG_SLT_SUPPORT + prAdapter->rWifiVar.rSltInfo.prPseudoStaRec = prStaRec; +#endif + } + break; + + default: + break; + } + + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); + + } while (FALSE); + +} /* end of aisFsmMergeIBSS() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Notification of existing IBSS was found +* from SCN. +* +* @param[in] prMsgHdr Message of Notification of an IBSS was present. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventFoundIBSSPeer(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_AIS_IBSS_PEER_FOUND_T prAisIbssPeerFoundMsg; + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prAisBssInfo; + P_BSS_DESC_T prBssDesc; + BOOLEAN fgIsMergeIn; + + ASSERT(prMsgHdr); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + prAisIbssPeerFoundMsg = (P_MSG_AIS_IBSS_PEER_FOUND_T) prMsgHdr; + + ASSERT(prAisIbssPeerFoundMsg->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX); + + prStaRec = prAisIbssPeerFoundMsg->prStaRec; + ASSERT(prStaRec); + + fgIsMergeIn = prAisIbssPeerFoundMsg->fgIsMergeIn; + + cnmMemFree(prAdapter, prMsgHdr); + + eNextState = prAisFsmInfo->eCurrentState; + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_IBSS_ALONE: + { + /* 4 <1> An IBSS Peer 'merged in'. */ + if (fgIsMergeIn) { + + /* 4 <1.1> Change FW's Media State immediately. */ + aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); + + /* 4 <1.2> Add Peers' STA_RECORD_T to Client List */ + bssAddStaRecToClientList(prAdapter, prAisBssInfo, prStaRec); + +#if CFG_SLT_SUPPORT + /* 4 <1.3> Mark connection flag of BSS_DESC_T. */ + prBssDesc = scanSearchBssDescByTA(prAdapter, prStaRec->aucMacAddr); + if (prBssDesc != NULL) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + } else { + ASSERT(0); /* Should be able to find a BSS_DESC_T here. */ + } + + /* 4 <1.4> Activate current Peer's STA_RECORD_T in Driver. */ + prStaRec->fgIsQoS = TRUE; /* TODO(Kevin): TBD */ +#else + /* 4 <1.3> Mark connection flag of BSS_DESC_T. */ + prBssDesc = scanSearchBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); + if (prBssDesc != NULL) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + } else { + ASSERT(0); /* Should be able to find a BSS_DESC_T here. */ + } + + /* 4 <1.4> Activate current Peer's STA_RECORD_T in Driver. */ + prStaRec->fgIsQoS = FALSE; /* TODO(Kevin): TBD */ + +#endif + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + prStaRec->fgIsMerging = FALSE; + + /* 4 <1.6> sync. to firmware */ + nicUpdateBss(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* 4 <1.7> Indicate Connected Event to Host immediately. */ + aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, FALSE); + + /* 4 <1.8> indicate PM for connected */ + nicPmIndicateBssConnected(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* 4 <1.9> Set the Next State of AIS FSM */ + eNextState = AIS_STATE_NORMAL_TR; + + /* 4 <1.10> Release channel privilege */ + aisFsmReleaseCh(prAdapter); + } + /* 4 <2> We need 'merge out' to this IBSS */ + else { + + /* 4 <2.1> Get corresponding BSS_DESC_T */ + prBssDesc = scanSearchBssDescByTA(prAdapter, prStaRec->aucMacAddr); + + prAisFsmInfo->prTargetBssDesc = prBssDesc; + + /* 4 <2.2> Set the Next State of AIS FSM */ + eNextState = AIS_STATE_IBSS_MERGE; + } + } + break; + + case AIS_STATE_NORMAL_TR: + { + + /* 4 <3> An IBSS Peer 'merged in'. */ + if (fgIsMergeIn) { + + /* 4 <3.1> Add Peers' STA_RECORD_T to Client List */ + bssAddStaRecToClientList(prAdapter, prAisBssInfo, prStaRec); + +#if CFG_SLT_SUPPORT + /* 4 <3.2> Activate current Peer's STA_RECORD_T in Driver. */ + prStaRec->fgIsQoS = TRUE; /* TODO(Kevin): TBD */ +#else + /* 4 <3.2> Activate current Peer's STA_RECORD_T in Driver. */ + prStaRec->fgIsQoS = FALSE; /* TODO(Kevin): TBD */ +#endif + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + prStaRec->fgIsMerging = FALSE; + + } + /* 4 <4> We need 'merge out' to this IBSS */ + else { + + /* 4 <4.1> Get corresponding BSS_DESC_T */ + prBssDesc = scanSearchBssDescByTA(prAdapter, prStaRec->aucMacAddr); + + prAisFsmInfo->prTargetBssDesc = prBssDesc; + + /* 4 <4.2> Set the Next State of AIS FSM */ + eNextState = AIS_STATE_IBSS_MERGE; + + } + } + break; + + default: + break; + } + + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); + +} /* end of aisFsmRunEventFoundIBSSPeer() */ +#endif /* CFG_SUPPORT_ADHOC */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Media State to HOST +* +* @param[in] eConnectionState Current Media State +* @param[in] fgDelayIndication Set TRUE for postponing the Disconnect Indication. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisIndicationOfMediaStateToHost(IN P_ADAPTER_T prAdapter, + ENUM_PARAM_MEDIA_STATE_T eConnectionState, BOOLEAN fgDelayIndication) +{ + EVENT_CONNECTION_STATUS rEventConnStatus; + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_INFO_T prAisBssInfo; + P_AIS_FSM_INFO_T prAisFsmInfo; + + DEBUGFUNC("aisIndicationOfMediaStateToHost()"); + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + /* NOTE(Kevin): Move following line to aisChangeMediaState() macro per CM's request. */ + /* prAisBssInfo->eConnectionState = eConnectionState; */ + + /* For indicating the Disconnect Event only if current media state is + * disconnected and we didn't do indication yet. + */ + DBGLOG(AIS, INFO, "Current state: %d, connection state indicated: %d\n", + prAisFsmInfo->eCurrentState, prAisBssInfo->eConnectionStateIndicated); + + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED && + /* if receive DEAUTH in JOIN state, report disconnect*/ + !(prAisBssInfo->ucReasonOfDisconnect == DISCONNECT_REASON_CODE_DEAUTHENTICATED && + prAisFsmInfo->eCurrentState == AIS_STATE_JOIN)) { + if (prAisBssInfo->eConnectionStateIndicated == eConnectionState) + return; + } + + if (!fgDelayIndication) { + /* 4 <0> Cancel Delay Timer */ + prAisFsmInfo->u4PostponeIndStartTime = 0; + + /* 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_REFACTORY_PMKSA == 0) +#if CFG_PRIVACY_MIGRATION + /* Clear the pmkid cache while media disconnect */ + secClearPmkid(prAdapter); +#endif +#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); + +#if CFG_SUPPORT_RN + if (prAisBssInfo->fgDisConnReassoc) + DBGLOG(AIS, INFO, "Reassoc the AP once beacause of receive deauth/deassoc\n"); + else +#endif + { + DBGLOG(AIS, INFO, "Postpone the indication of Disconnect for %d seconds\n", + prConnSettings->ucDelayTimeOfDisconnectEvent); + prAisFsmInfo->u4PostponeIndStartTime = kalGetTimeTick(); + } + + } + +} /* end of aisIndicationOfMediaStateToHost() */ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Sched Scan Start" +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisPostponedEventOfSchedScanReq(IN P_ADAPTER_T prAdapter, IN P_AIS_FSM_INFO_T prAisFsmInfo) +{ + P_SCAN_INFO_T prScanInfo; + P_PARAM_SCHED_SCAN_REQUEST prSchedScanRequest; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prSchedScanRequest = &prScanInfo->rSchedScanRequest; + + DBGLOG(AIS, INFO, "aisPostponedEventOfSchedScanReq:AIS CurState[%d] SchedScanReq:%d\n" + , prAisFsmInfo->eCurrentState + , prScanInfo->eCurrendSchedScanReq); + + if (prScanInfo->fgIsPostponeSchedScan == TRUE) { + if (prScanInfo->eCurrendSchedScanReq == SCHED_SCAN_POSTPONE_START) { + /*resume schedscan start*/ + if (scnFsmSchedScanRequest(prAdapter) == TRUE) + DBGLOG(AIS, INFO, "aisPostponedEventOf SchedScanStart: Success!\n"); + else + DBGLOG(AIS, WARN, "aisPostponedEventOf SchedScanStart: fail\n"); + + } else if (prScanInfo->eCurrendSchedScanReq == SCHED_SCAN_POSTPONE_STOP) { + /*resume schedscan stop*/ + if (scnFsmSchedScanStopRequest(prAdapter) == TRUE) + DBGLOG(AIS, INFO, "aisPostponedEventOf SchedScanStop: Success!\n"); + else + DBGLOG(AIS, INFO, "aisPostponedEventOf SchedScanStop: fail!\n"); + + } else + DBGLOG(AIS, INFO, "unexcept SchedScan Request!\n"); + } else { + DBGLOG(AIS, WARN, "driver don't resume schedScan Request\n"); + } + + + +} /* end of aisPostponedEventOfSchedScanReq() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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, IN P_AIS_FSM_INFO_T prAisFsmInfo) +{ + P_BSS_INFO_T prAisBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_SCAN_INFO_T prScanInfo; + BOOLEAN fgFound = TRUE; + BOOLEAN fgIsPostponeTimeout; + BOOLEAN fgIsBeaconTimeout; + + /* + * firstly, check if we have started postpone indication. + * otherwise, give a chance to do join before indicate to host + */ + if (prAisFsmInfo->u4PostponeIndStartTime == 0) + return; + + /* if we're in req channel/join/search state, don't report disconnect. */ + if (prAisFsmInfo->eCurrentState == AIS_STATE_JOIN || + prAisFsmInfo->eCurrentState == AIS_STATE_SEARCH || + prAisFsmInfo->eCurrentState == AIS_STATE_REQ_CHANNEL_JOIN || + prAisFsmInfo->eCurrentState == AIS_STATE_COLLECT_ESS_INFO) { + DBGLOG(AIS, INFO, "CurrentState: %d, don't report disconnect\n", + prAisFsmInfo->eCurrentState); + return; + } + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + if (prScanInfo->eCurrentState == SCAN_STATE_SCANNING) { + DBGLOG(AIS, INFO, "SCANNING, don't report disconnect\n"); + return; + } + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + fgIsPostponeTimeout = CHECK_FOR_TIMEOUT(kalGetTimeTick(), prAisFsmInfo->u4PostponeIndStartTime, + SEC_TO_MSEC(prConnSettings->ucDelayTimeOfDisconnectEvent)); + fgIsBeaconTimeout = prAisBssInfo->ucReasonOfDisconnect == DISCONNECT_REASON_CODE_RADIO_LOST; +#if CFG_SUPPORT_RN + fgIsBeaconTimeout &= !prAisBssInfo->fgDisConnReassoc; +#endif + /* only retry connect once when beacon timeout */ + if (!fgIsPostponeTimeout && !(fgIsBeaconTimeout && prAisFsmInfo->ucConnTrialCount > 1)) { + DBGLOG(AIS, INFO, "DelayTimeOfDisconnect, don't report disconnect\n"); + return; + } + + /* 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 all pending connection request */ + while (fgFound) + fgFound = aisFsmIsRequestPending(prAdapter, AIS_REQUEST_RECONNECT, TRUE); + + if (prAisFsmInfo->eCurrentState == AIS_STATE_LOOKING_FOR) + prAisFsmInfo->eCurrentState = AIS_STATE_IDLE; + prConnSettings->fgIsDisconnectedByNonRequest = TRUE; + prAisBssInfo->u2DeauthReason = REASON_CODE_BEACON_TIMEOUT; + /* 4 <3> Indicate Disconnected Event to Host immediately. */ + aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED, FALSE); + +} /* end of aisPostponedEventOfDisconnTimeout() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will update the contain of BSS_INFO_T for AIS network once +* the association was completed. +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] prAssocRspSwRfb Pointer to SW RFB of ASSOC RESP FRAME. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisUpdateBssInfoForJOIN(IN P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, P_SW_RFB_T prAssocRspSwRfb) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame; + P_BSS_DESC_T prBssDesc; + UINT_16 u2IELength; + PUINT_8 pucIE; + PARAM_SSID_T rSsid; + + DEBUGFUNC("aisUpdateBssInfoForJOIN()"); + + ASSERT(prStaRec); + ASSERT(prAssocRspSwRfb); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) prAssocRspSwRfb->pvHeader; + + DBGLOG(AIS, TRACE, "Update AIS_BSS_INFO_T and apply settings to MAC\n"); + + /* 3 <1> Update BSS_INFO_T from AIS_FSM_INFO_T or User Settings */ + /* 4 <1.1> Setup Operation Mode */ + prAisBssInfo->eCurrentOPMode = OP_MODE_INFRASTRUCTURE; + + /* 4 <1.2> Setup SSID */ + COPY_SSID(prAisBssInfo->aucSSID, prAisBssInfo->ucSSIDLen, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); + + /* 4 <1.3> Setup Channel, Band */ + prAisBssInfo->ucPrimaryChannel = prAisFsmInfo->prTargetBssDesc->ucChannelNum; + prAisBssInfo->eBand = prAisFsmInfo->prTargetBssDesc->eBand; + + /* 3 <2> Update BSS_INFO_T from STA_RECORD_T */ + /* 4 <2.1> Save current AP's STA_RECORD_T and current AID */ + prAisBssInfo->prStaRecOfAP = prStaRec; + prAisBssInfo->u2AssocId = prStaRec->u2AssocId; + + /* 4 <2.2> Setup Capability */ + prAisBssInfo->u2CapInfo = prStaRec->u2CapInfo; /* Use AP's Cap Info as BSS Cap Info */ + + if (prAisBssInfo->u2CapInfo & CAP_INFO_SHORT_PREAMBLE) + prAisBssInfo->fgIsShortPreambleAllowed = TRUE; + else + prAisBssInfo->fgIsShortPreambleAllowed = FALSE; + +#if (CFG_SUPPORT_TDLS == 1) + /* init the TDLS flags */ + prAisBssInfo->fgTdlsIsProhibited = prStaRec->fgTdlsIsProhibited; + prAisBssInfo->fgTdlsIsChSwProhibited = prStaRec->fgTdlsIsChSwProhibited; +#endif /* CFG_SUPPORT_TDLS */ + + /* 4 <2.3> Setup PHY Attributes and Basic Rate Set/Operational Rate Set */ + prAisBssInfo->ucPhyTypeSet = prStaRec->ucDesiredPhyTypeSet; + + prAisBssInfo->ucNonHTBasicPhyType = prStaRec->ucNonHTBasicPhyType; + + prAisBssInfo->u2OperationalRateSet = prStaRec->u2OperationalRateSet; + prAisBssInfo->u2BSSBasicRateSet = prStaRec->u2BSSBasicRateSet; + + /* 3 <3> Update BSS_INFO_T from SW_RFB_T (Association Resp Frame) */ + /* 4 <3.1> Setup BSSID */ + COPY_MAC_ADDR(prAisBssInfo->aucBSSID, prAssocRspFrame->aucBSSID); + + u2IELength = (UINT_16) ((prAssocRspSwRfb->u2PacketLen - prAssocRspSwRfb->u2HeaderLen) - + (OFFSET_OF(WLAN_ASSOC_RSP_FRAME_T, aucInfoElem[0]) - WLAN_MAC_MGMT_HEADER_LEN)); + pucIE = prAssocRspFrame->aucInfoElem; + + /* 4 <3.2> Parse WMM and setup QBSS flag */ + /* Parse WMM related IEs and configure HW CRs accordingly */ + mqmProcessAssocRsp(prAdapter, prAssocRspSwRfb, pucIE, u2IELength); + + prAisBssInfo->fgIsQBSS = prStaRec->fgIsQoS; + + /* 3 <4> Update BSS_INFO_T from BSS_DESC_T */ + prBssDesc = prAisFsmInfo->prTargetBssDesc; + if (prBssDesc) + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + else + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, + prConnSettings->aucSSID, prConnSettings->ucSSIDLen); + + prBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, prAssocRspFrame->aucBSSID, TRUE, &rSsid); + if (prBssDesc) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + prBssDesc->ucJoinFailureCount = 0; + aisRemoveBlackList(prAdapter, prBssDesc); + /* 4 <4.1> Setup MIB for current BSS */ + prAisBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval; + } else { + /* should never happen */ + DBGLOG(AIS, WARN, "no prBssDesc found!\n"); + ASSERT(0); + } +#if CFG_SUPPORT_DETECT_ATHEROS_AP + aisSendBaCmdByAtherosAp(prAdapter, prBssDesc); +#endif + /* NOTE: Defer ucDTIMPeriod updating to when beacon is received after connection */ + prAisBssInfo->ucDTIMPeriod = 0; + prAisBssInfo->u2ATIMWindow = 0; + + prAisBssInfo->ucBeaconTimeoutCount = AIS_BEACON_TIMEOUT_COUNT_INFRA; + prAisBssInfo->ucRoamSkipTimes = CFG_GOOG_RCPI_SCAN_SKIP_TIMES; + prAisBssInfo->fgGoodRcpiArea = FALSE; + prAisBssInfo->fgPoorRcpiArea = FALSE; + + /* 4 <4.2> Update HT information and set channel */ + /* Record HT related parameters in rStaRec and rBssInfo + * Note: it shall be called before nicUpdateBss() + */ + rlmProcessAssocRsp(prAdapter, prAssocRspSwRfb, pucIE, u2IELength); + + /* 4 <4.3> Sync with firmware for BSS-INFO */ + nicUpdateBss(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* 4 <4.4> *DEFER OPERATION* nicPmIndicateBssConnected() will be invoked */ + /* inside scanProcessBeaconAndProbeResp() after 1st beacon is received */ + +} /* end of aisUpdateBssInfoForJOIN() */ + +#if CFG_SUPPORT_ADHOC +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will create an Ad-Hoc network and start sending Beacon Frames. +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisUpdateBssInfoForCreateIBSS(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + if (prAisBssInfo->fgIsBeaconActivated) + return; + /* 3 <1> Update BSS_INFO_T per Network Basis */ + /* 4 <1.1> Setup Operation Mode */ + prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; + + /* 4 <1.2> Setup SSID */ + COPY_SSID(prAisBssInfo->aucSSID, prAisBssInfo->ucSSIDLen, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); + + /* 4 <1.3> Clear current AP's STA_RECORD_T and current AID */ + prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; + prAisBssInfo->u2AssocId = 0; + + /* 4 <1.4> Setup Channel, Band and Phy Attributes */ + prAisBssInfo->ucPrimaryChannel = prConnSettings->ucAdHocChannelNum; + prAisBssInfo->eBand = prConnSettings->eAdHocBand; + + if (prAisBssInfo->eBand == BAND_2G4) { + /* Depend on eBand */ + prAisBssInfo->ucPhyTypeSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11BGN; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prAisBssInfo->ucConfigAdHocAPMode = AD_HOC_MODE_MIXED_11BG; + } else { + /* Depend on eBand */ + prAisBssInfo->ucPhyTypeSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AN; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prAisBssInfo->ucConfigAdHocAPMode = AD_HOC_MODE_11A; + } + + /* 4 <1.5> Setup MIB for current BSS */ + prAisBssInfo->u2BeaconInterval = prConnSettings->u2BeaconPeriod; + prAisBssInfo->ucDTIMPeriod = 0; + prAisBssInfo->u2ATIMWindow = prConnSettings->u2AtimWindow; + + prAisBssInfo->ucBeaconTimeoutCount = AIS_BEACON_TIMEOUT_COUNT_ADHOC; + +#if CFG_PRIVACY_MIGRATION + if (prConnSettings->eEncStatus == ENUM_ENCRYPTION1_ENABLED || + prConnSettings->eEncStatus == ENUM_ENCRYPTION2_ENABLED || + prConnSettings->eEncStatus == ENUM_ENCRYPTION3_ENABLED) { + prAisBssInfo->fgIsProtection = TRUE; + } else { + prAisBssInfo->fgIsProtection = FALSE; + } +#else + prAisBssInfo->fgIsProtection = FALSE; +#endif + + /* 3 <2> Update BSS_INFO_T common part */ + ibssInitForAdHoc(prAdapter, prAisBssInfo); + + /* 3 <3> Set MAC HW */ + /* 4 <3.1> Setup channel and bandwidth */ + rlmBssInitForAPandIbss(prAdapter, prAisBssInfo); + + /* 4 <3.2> use command packets to inform firmware */ + nicUpdateBss(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* 4 <3.3> enable beaconing */ + bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* 4 <3.4> Update AdHoc PM parameter */ + nicPmIndicateBssCreated(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* 3 <4> Set ACTIVE flag. */ + prAisBssInfo->fgIsBeaconActivated = TRUE; + prAisBssInfo->fgHoldSameBssidForIBSS = TRUE; + + /* 3 <5> Start IBSS Alone Timer */ + cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rIbssAloneTimer, SEC_TO_MSEC(AIS_IBSS_ALONE_TIMEOUT_SEC)); + + return; + +} /* end of aisCreateIBSS() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will update the contain of BSS_INFO_T for AIS network once +* the existing IBSS was found. +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisUpdateBssInfoForMergeIBSS(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_DESC_T prBssDesc; + /* UINT_16 u2IELength; */ + /* PUINT_8 pucIE; */ + + ASSERT(prStaRec); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rIbssAloneTimer); + + if (!prAisBssInfo->fgIsBeaconActivated) { + + /* 3 <1> Update BSS_INFO_T per Network Basis */ + /* 4 <1.1> Setup Operation Mode */ + prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; + + /* 4 <1.2> Setup SSID */ + COPY_SSID(prAisBssInfo->aucSSID, + prAisBssInfo->ucSSIDLen, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); + + /* 4 <1.3> Clear current AP's STA_RECORD_T and current AID */ + prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; + prAisBssInfo->u2AssocId = 0; + } + /* 3 <2> Update BSS_INFO_T from STA_RECORD_T */ + /* 4 <2.1> Setup Capability */ + prAisBssInfo->u2CapInfo = prStaRec->u2CapInfo; /* Use Peer's Cap Info as IBSS Cap Info */ + + if (prAisBssInfo->u2CapInfo & CAP_INFO_SHORT_PREAMBLE) { + prAisBssInfo->fgIsShortPreambleAllowed = TRUE; + prAisBssInfo->fgUseShortPreamble = TRUE; + } else { + prAisBssInfo->fgIsShortPreambleAllowed = FALSE; + prAisBssInfo->fgUseShortPreamble = FALSE; + } + + /* 7.3.1.4 For IBSS, the Short Slot Time subfield shall be set to 0. */ + prAisBssInfo->fgUseShortSlotTime = FALSE; /* Set to FALSE for AdHoc */ + prAisBssInfo->u2CapInfo &= ~CAP_INFO_SHORT_SLOT_TIME; + + if (prAisBssInfo->u2CapInfo & CAP_INFO_PRIVACY) + prAisBssInfo->fgIsProtection = TRUE; + else + prAisBssInfo->fgIsProtection = FALSE; + + /* 4 <2.2> Setup PHY Attributes and Basic Rate Set/Operational Rate Set */ + prAisBssInfo->ucPhyTypeSet = prStaRec->ucDesiredPhyTypeSet; + + prAisBssInfo->ucNonHTBasicPhyType = prStaRec->ucNonHTBasicPhyType; + + prAisBssInfo->u2OperationalRateSet = prStaRec->u2OperationalRateSet; + prAisBssInfo->u2BSSBasicRateSet = prStaRec->u2BSSBasicRateSet; + + rateGetDataRatesFromRateSet(prAisBssInfo->u2OperationalRateSet, + prAisBssInfo->u2BSSBasicRateSet, + prAisBssInfo->aucAllSupportedRates, &prAisBssInfo->ucAllSupportedRatesLen); + + /* 3 <3> X Update BSS_INFO_T from SW_RFB_T (Association Resp Frame) */ + + /* 3 <4> Update BSS_INFO_T from BSS_DESC_T */ + prBssDesc = scanSearchBssDescByTA(prAdapter, prStaRec->aucMacAddr); + if (prBssDesc) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + + /* 4 <4.1> Setup BSSID */ + COPY_MAC_ADDR(prAisBssInfo->aucBSSID, prBssDesc->aucBSSID); + + /* 4 <4.2> Setup Channel, Band */ + prAisBssInfo->ucPrimaryChannel = prBssDesc->ucChannelNum; + prAisBssInfo->eBand = prBssDesc->eBand; + + /* 4 <4.3> Setup MIB for current BSS */ + prAisBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval; + prAisBssInfo->ucDTIMPeriod = 0; + prAisBssInfo->u2ATIMWindow = 0; /* TBD(Kevin) */ + + prAisBssInfo->ucBeaconTimeoutCount = AIS_BEACON_TIMEOUT_COUNT_ADHOC; + } else { + /* should never happen */ + ASSERT(0); + } + + /* 3 <5> Set MAC HW */ + /* 4 <5.1> Find Lowest Basic Rate Index for default TX Rate of MMPDU */ + { + UINT_8 ucLowestBasicRateIndex; + + if (!rateGetLowestRateIndexFromRateSet(prAisBssInfo->u2BSSBasicRateSet, &ucLowestBasicRateIndex)) { + + if (prAisBssInfo->ucPhyTypeSet & PHY_TYPE_BIT_OFDM) + ucLowestBasicRateIndex = RATE_6M_INDEX; + else + ucLowestBasicRateIndex = RATE_1M_INDEX; + } + + prAisBssInfo->ucHwDefaultFixedRateCode = + aucRateIndex2RateCode[prAisBssInfo->fgUseShortPreamble][ucLowestBasicRateIndex]; + } + + /* 4 <5.2> Setup channel and bandwidth */ + rlmBssInitForAPandIbss(prAdapter, prAisBssInfo); + + /* 4 <5.3> use command packets to inform firmware */ + nicUpdateBss(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* 4 <5.4> enable beaconing */ + bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* 4 <5.5> Update AdHoc PM parameter */ + nicPmIndicateBssConnected(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* 3 <6> Set ACTIVE flag. */ + prAisBssInfo->fgIsBeaconActivated = TRUE; + prAisBssInfo->fgHoldSameBssidForIBSS = TRUE; + +} /* end of aisUpdateBssInfoForMergeIBSS() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Probe Request Frame and then return +* result to BSS to indicate if need to send the corresponding Probe Response +* Frame if the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu4ControlFlags Control flags for replying the Probe Response +* +* @retval TRUE Reply the Probe Response +* @retval FALSE Don't reply the Probe Response +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN aisValidateProbeReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_32 pu4ControlFlags) +{ + P_WLAN_MAC_MGMT_HEADER_T prMgtHdr; + P_BSS_INFO_T prBssInfo; + P_IE_SSID_T prIeSsid = (P_IE_SSID_T) NULL; + PUINT_8 pucIE; + UINT_16 u2IELength; + UINT_16 u2Offset = 0; + BOOLEAN fgReplyProbeResp = FALSE; + + ASSERT(prSwRfb); + ASSERT(pu4ControlFlags); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + /* 4 <1> Parse Probe Req IE and Get IE ptr (SSID, Supported Rate IE, ...) */ + prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T) prSwRfb->pvHeader; + + u2IELength = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen; + pucIE = (PUINT_8) prSwRfb->pvHeader + prSwRfb->u2HeaderLen; + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (IE_ID(pucIE) == ELEM_ID_SSID) { + 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]); + + DBGLOG(AIS, INFO, "aisFsmDisconnect: ConnectionState=%d fgDelayIndication=%d\n" + , prAisBssInfo->eConnectionState + , fgDelayIndication); + + 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 (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + /* add for ctia mode */ + { + UINT_8 aucP2pSsid[] = CTIA_MAGIC_SSID; + + if (EQUAL_SSID(aucP2pSsid, CTIA_MAGIC_SSID_LEN, prAisBssInfo->aucSSID, prAisBssInfo->ucSSIDLen)) + nicEnterCtiaMode(prAdapter, FALSE, FALSE); + } + + if (prAisBssInfo->ucReasonOfDisconnect == DISCONNECT_REASON_CODE_RADIO_LOST) { +#if CFG_SUPPORT_RN + if (prAisBssInfo->fgDisConnReassoc == FALSE) +#endif + { + scanRemoveBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); + + /* remove from scanning results as well */ + wlanClearBssInScanningResult(prAdapter, prAisBssInfo->aucBSSID); + } + + /* trials for re-association */ + if (fgDelayIndication) { + DBGLOG(AIS, INFO, "try to do re-association due to radio lost!\n"); + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_RECONNECT, TRUE); + aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); + } + } else { + scanRemoveConnFlagOfBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); + } + + if (fgDelayIndication) { + if (prAisBssInfo->eCurrentOPMode != OP_MODE_IBSS) + prAisBssInfo->fgHoldSameBssidForIBSS = FALSE; + } else { + prAisBssInfo->fgHoldSameBssidForIBSS = FALSE; + } + } else { + prAisBssInfo->fgHoldSameBssidForIBSS = FALSE; + } + + /* 4 <4> Change Media State immediately. */ + if (prAisBssInfo->ucReasonOfDisconnect != DISCONNECT_REASON_CODE_REASSOCIATION) { + aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + + /* 4 <4.1> sync. with firmware */ + nicUpdateBss(prAdapter, NETWORK_TYPE_AIS_INDEX); + } + + if (!fgDelayIndication) { + /* 4 <5> Deactivate previous AP's STA_RECORD_T or all Clients in Driver if have. */ + if (prAisBssInfo->prStaRecOfAP) { + /* cnmStaRecChangeState(prAdapter, prAisBssInfo->prStaRecOfAP, STA_STATE_1); */ + + prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; + } + } +#if CFG_SUPPORT_ROAMING + roamingFsmRunEventAbort(prAdapter); + + /* clear pending roaming connection request */ + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_SEARCH, TRUE); + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, TRUE); +#endif /* CFG_SUPPORT_ROAMING */ + + /* 4 <6> Indicate Disconnected Event to Host */ + aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED, fgDelayIndication); + + /* 4 <7> Trigger AIS FSM */ + aisFsmSteps(prAdapter, AIS_STATE_IDLE); + +} /* end of aisFsmDisconnect() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of Scan done Time-Out to AIS FSM. +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 IsrCnt = 0, IsrPassCnt = 0, TaskIsrCnt = 0; +VOID aisFsmRunEventScanDoneTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParam) +{ +#define SCAN_DONE_TIMEOUT_TIMES_LIMIT 20 + + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + P_CONNECTION_SETTINGS_T prConnSettings; + GL_HIF_INFO_T *HifInfo; + UINT_32 u4FwCnt; + P_GLUE_INFO_T prGlueInfo; + + DEBUGFUNC("aisFsmRunEventScanDoneTimeOut()"); + + prGlueInfo = prAdapter->prGlueInfo; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + HifInfo = &prAdapter->prGlueInfo->rHifInfo; + + DBGLOG(AIS, WARN, "aisFsmRunEventScanDoneTimeOut Current[%d], ucScanTimeoutTimes=%d, u4NumElem=%d\n" + , prAisFsmInfo->eCurrentState, ucScanTimeoutTimes + , prAdapter->prGlueInfo->rCmdQueue.u4NumElem); + DBGLOG(AIS, WARN, "Isr/task %u %u %u (0x%x)\n", prGlueInfo->IsrCnt, prGlueInfo->IsrPassCnt, + prGlueInfo->TaskIsrCnt, prAdapter->fgIsIntEnable); + + /* dump firmware program counter */ + DBGLOG(AIS, WARN, "CONNSYS FW CPUINFO:\n"); + for (u4FwCnt = 0; u4FwCnt < 16; u4FwCnt++) + DBGLOG(AIS, WARN, "0x%08x ", MCU_REG_READL(HifInfo, CONN_MCU_CPUPCR)); + + /*dump firmware status */ + wlanDumpCommandFwStatus(); + + /* dump TX_Description for Scan Request */ + /* (1) dump Tc4[0]~[3] for Scan Request before hal write */ + /* (2) dump Tc4[0]~[3] for Scan Request after hal write done */ + /* if TC[X]ucOwn 1 -> 0,FW available and set 1, and Hardware receiced and set 0 */ + wlanDebugScanDump(prAdapter); + + ucScanTimeoutTimes++; + if (ucScanTimeoutTimes > SCAN_DONE_TIMEOUT_TIMES_LIMIT) { + kalSendAeeWarning("[Scan done timeout more than 20 times!]", __func__); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_CHIP_RESET); + } +#if 0 /* ALPS02018734: remove trigger assert */ + if (prAdapter->fgTestMode == FALSE) { + /* Titus - xxx */ + /* assert if and only if in normal mode */ + mtk_wcn_wmt_assert(WMTDRV_TYPE_WIFI, 0x40); + } +#endif + /* report all scanned frames to upper layer to avoid scanned frame is timeout */ + /* must be put before kalScanDone */ +/* scanReportBss2Cfg80211(prAdapter,BSS_TYPE_INFRASTRUCTURE,NULL); */ + + prConnSettings->fgIsScanReqIssued = FALSE; + kalScanDone(prAdapter->prGlueInfo, KAL_NETWORK_TYPE_AIS_INDEX, WLAN_STATUS_SUCCESS); + eNextState = prAisFsmInfo->eCurrentState; + + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_SCAN: + prAisFsmInfo->u4ScanIELength = 0; + eNextState = AIS_STATE_IDLE; + break; + case AIS_STATE_ONLINE_SCAN: + /* reset scan IE buffer */ + prAisFsmInfo->u4ScanIELength = 0; +#if CFG_SUPPORT_ROAMING + eNextState = aisFsmRoamingScanResultsUpdate(prAdapter); +#else + eNextState = AIS_STATE_NORMAL_TR; +#endif /* CFG_SUPPORT_ROAMING */ +#if CFG_SELECT_BSS_BASE_ON_MULTI_PARAM + scanGetCurrentEssChnlList(prAdapter); +#endif + break; + default: + break; + } + + /* try to stop scan in CONNSYS */ + aisFsmStateAbort_SCAN(prAdapter); + aisRemoveOldestBcnTimeout(prAisFsmInfo); + /* wlanQueryDebugCode(prAdapter); */ /* display current SCAN FSM in FW, debug use */ + + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); + +} /* end of aisFsmBGSleepTimeout() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Background Scan Time-Out" to AIS FSM. +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventBGSleepTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParam) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + + DEBUGFUNC("aisFsmRunEventBGSleepTimeOut()"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + eNextState = prAisFsmInfo->eCurrentState; + + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_WAIT_FOR_NEXT_SCAN: + DBGLOG(AIS, LOUD, "EVENT - SCAN TIMER: Idle End - Current Time = %u\n", kalGetTimeTick()); + + eNextState = AIS_STATE_LOOKING_FOR; + + SET_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX); + + break; + + default: + break; + } + + /* Call aisFsmSteps() when we are going to change AIS STATE */ + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); + +} /* end of aisFsmBGSleepTimeout() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "IBSS ALONE Time-Out" to AIS FSM. +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventIbssAloneTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParam) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + + DEBUGFUNC("aisFsmRunEventIbssAloneTimeOut()"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + eNextState = prAisFsmInfo->eCurrentState; + + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_IBSS_ALONE: + + /* There is no one participate in our AdHoc during this TIMEOUT Interval + * so go back to search for a valid IBSS again. + */ + + DBGLOG(AIS, LOUD, "EVENT-IBSS ALONE TIMER: Start pairing\n"); + + prAisFsmInfo->fgTryScan = TRUE; + + /* abort timer */ + aisFsmReleaseCh(prAdapter); + + /* Pull back to SEARCH to find candidate again */ + eNextState = AIS_STATE_SEARCH; + + break; + + default: + break; + } + + /* Call aisFsmSteps() when we are going to change AIS STATE */ + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); + +} /* end of aisIbssAloneTimeOut() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Join Time-Out" to AIS FSM. +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventJoinTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam) +{ + P_BSS_INFO_T prAisBssInfo; + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + OS_SYSTIME rCurrentTime; + P_MSG_SAA_FSM_COMP_T prSaaFsmCompMsg; + + DEBUGFUNC("aisFsmRunEventJoinTimeout()"); + prAisBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + eNextState = prAisFsmInfo->eCurrentState; + DBGLOG(AIS, INFO, "aisFsmRunEventJoinTimeout,CurrentState[%d]\n", prAisFsmInfo->eCurrentState); + + GET_CURRENT_SYSTIME(&rCurrentTime); + switch (prAisFsmInfo->eCurrentState) { + + case AIS_STATE_JOIN: + /* 1. Do abort JOIN */ + aisFsmStateAbort_JOIN(prAdapter); + aisAddBlacklist(prAdapter, prAisFsmInfo->prTargetBssDesc); +#if 0 + /* 2. Increase Join Failure Count */ + prAisFsmInfo->prTargetBssDesc->ucJoinFailureCount++; +/* For JB nl802.11 */ + if (prAisFsmInfo->prTargetBssDesc->ucJoinFailureCount < JOIN_MAX_RETRY_FAILURE_COUNT) { + /* 3.1 Retreat to AIS_STATE_SEARCH state for next try */ + eNextState = AIS_STATE_SEARCH; + /* restore tx power control */ + rlmSetMaxTxPwrLimit(prAdapter, 0, 0); + } else if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + /* 3.2 Retreat to AIS_STATE_WAIT_FOR_NEXT_SCAN state for next try */ + eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; + } else if (prAisFsmInfo->rJoinReqTime != 0 && + !CHECK_FOR_TIMEOUT(rCurrentTime, + prAisFsmInfo->rJoinReqTime, + SEC_TO_SYSTIME(AIS_JOIN_TIMEOUT))) { + /* 3.3 Retreat to AIS_STATE_WAIT_FOR_NEXT_SCAN state for next try */ + eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; + /* restore tx power control */ + rlmSetMaxTxPwrLimit(prAdapter, 0, 0); + } else { + /* restore tx power control */ + rlmSetMaxTxPwrLimit(prAdapter, 0, 0); + /* 3.4 Retreat to AIS_STATE_JOIN_FAILURE to terminate join operation */ + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_JOIN_FAILURE, NULL, 0); + eNextState = AIS_STATE_IDLE; + } +#else + /*request channel timeout, driver avoid to aisFsmStateInit_RetryJOIN*/ + if (prAisFsmInfo->ucAvailableAuthTypes != 0) + DBGLOG(AIS, INFO, "driver avoids to aisFsmStateInit_RetryJOIN retry!\n"); + + prAisFsmInfo->ucAvailableAuthTypes = 0; + + /* keep eNextState the same (so will not do action here), and do action in aisFsmRunEventJoinComplete */ + prSaaFsmCompMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SAA_FSM_COMP_T)); + if (!prSaaFsmCompMsg) { + DBGLOG(AIS, WARN, "aisFsmRunEventJoinTimeout memory alloc fail!\n"); + return; + } + prSaaFsmCompMsg->rMsgHdr.eMsgId = MID_SAA_AIS_JOIN_COMPLETE; + prSaaFsmCompMsg->ucSeqNum = prAisFsmInfo->ucSeqNumOfReqMsg; + prSaaFsmCompMsg->rJoinStatus = WLAN_STATUS_FAILURE; + prSaaFsmCompMsg->prStaRec = prAisFsmInfo->prTargetStaRec; + prSaaFsmCompMsg->prSwRfb = NULL; + /* joint complete only use it when rJoinStatus is WLAN_STATUS_SUCCESS*/ + /* NOTE(Kevin): Set to UNBUF for immediately JOIN complete */ + aisFsmRunEventJoinComplete(prAdapter, (P_MSG_HDR_T) prSaaFsmCompMsg); + eNextState = prAisFsmInfo->eCurrentState; +#endif + + 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; + } else if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, TRUE)) { + DBGLOG(AIS, INFO, "Upper layer trigger roaming, resume request!\n"); + eNextState = AIS_STATE_COLLECT_ESS_INFO; + } + + break; + + default: + /* release channel */ + aisFsmReleaseCh(prAdapter); + break; + + } + + /* Call aisFsmSteps() when we are going to change AIS STATE */ + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); + +} /* end of aisFsmRunEventJoinTimeout() */ + +VOID aisFsmRunEventDeauthTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam) +{ + aisDeauthXmitComplete(prAdapter, NULL, TX_RESULT_LIFE_TIMEOUT); +} +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE +VOID aisFsmRunEventSecModeChangeTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr) +{ + DBGLOG(AIS, INFO, "Beacon security mode change timeout, trigger disconnect!\n"); + aisBssSecurityChanged(prAdapter); +} +#endif + +#if defined(CFG_TEST_MGMT_FSM) && (CFG_TEST_MGMT_FSM != 0) +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID aisTest(VOID) +{ + P_MSG_AIS_ABORT_T prAisAbortMsg; + P_CONNECTION_SETTINGS_T prConnSettings; + UINT_8 aucSSID[] = "pci-11n"; + UINT_8 ucSSIDLen = 7; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* Set Connection Request Issued Flag */ + prConnSettings->fgIsConnReqIssued = TRUE; + prConnSettings->ucSSIDLen = ucSSIDLen; + kalMemCopy(prConnSettings->aucSSID, aucSSID, ucSSIDLen); + + prAisAbortMsg = (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); + if (!prAisAbortMsg) { + + ASSERT(0); /* Can't trigger SCAN FSM */ + return; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_HEM_AIS_FSM_ABORT; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); + + wifi_send_msg(INDX_WIFI, MSG_ID_WIFI_IST, 0); + +} +#endif /* CFG_TEST_MGMT_FSM */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to handle OID_802_11_BSSID_LIST_SCAN +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[in] prSsid Pointer of SSID_T if specified +* \param[in] pucIe Pointer to buffer of extra information elements to be attached +* \param[in] u4IeLength Length of information elements +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmScanRequest(IN P_ADAPTER_T prAdapter, IN P_PARAM_SSID_T prSsid, IN PUINT_8 pucIe, IN UINT_32 u4IeLength) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_INFO_T prAisBssInfo; + P_AIS_FSM_INFO_T prAisFsmInfo; + + DEBUGFUNC("aisFsmScanRequest()"); + + ASSERT(prAdapter); + ASSERT(u4IeLength <= MAX_IE_LENGTH); + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + DBGLOG(AIS, TRACE, "eCurrentState=%d, fgIsScanReqIssued = %d\n", + prAisFsmInfo->eCurrentState, prConnSettings->fgIsScanReqIssued); + if (!prConnSettings->fgIsScanReqIssued) { + prConnSettings->fgIsScanReqIssued = TRUE; + scanInitEssResult(prAdapter); + + if (prSsid == NULL) { + prAisFsmInfo->ucScanSSIDLen = 0; + } else { + COPY_SSID(prAisFsmInfo->aucScanSSID, + prAisFsmInfo->ucScanSSIDLen, prSsid->aucSsid, (UINT_8) prSsid->u4SsidLen); + } + + if (u4IeLength > 0 && u4IeLength <= MAX_IE_LENGTH) { + prAisFsmInfo->u4ScanIELength = u4IeLength; + kalMemCopy(prAisFsmInfo->aucScanIEBuf, pucIe, u4IeLength); + } else { + prAisFsmInfo->u4ScanIELength = 0; + } + + if (prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR) { + if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE + && prAisFsmInfo->fgIsInfraChannelFinished == FALSE) { + /* 802.1x might not finished yet, pend it for later handling .. */ + aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); + } else { + if (prAisFsmInfo->fgIsChannelGranted == TRUE) { + DBGLOG(AIS, WARN, + "Scan Request with channel granted for join operation: %d, %d", + prAisFsmInfo->fgIsChannelGranted, prAisFsmInfo->fgIsChannelRequested); + } + + /* start online scan */ + wlanClearScanningResult(prAdapter); + aisFsmSteps(prAdapter, AIS_STATE_ONLINE_SCAN); + } + } else if (prAisFsmInfo->eCurrentState == AIS_STATE_IDLE) { + wlanClearScanningResult(prAdapter); + aisFsmSteps(prAdapter, AIS_STATE_SCAN); + } else { + aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); + } + } else { + DBGLOG(AIS, WARN, "Scan Request dropped. (state: %d)\n", prAisFsmInfo->eCurrentState); + } + +} /* end of aisFsmScanRequest() */ + +#if CFG_MULTI_SSID_SCAN +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to handle OID_802_11_BSSID_LIST_SCAN +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[in] ucSsidNum Number of SSID +* \param[in] prSsid Pointer to the array 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 aisFsmScanRequestAdv(IN P_ADAPTER_T prAdapter, IN UINT_8 ucSsidNum, IN P_PARAM_SSID_T prSsid, + IN PUINT_8 pucIe, IN UINT_32 u4IeLength, IN PUINT_8 paucRandomMac) +{ + UINT_32 i; + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_INFO_T prAisBssInfo; + P_AIS_FSM_INFO_T prAisFsmInfo; + + DEBUGFUNC("aisFsmScanRequestAdv()"); + + ASSERT(prAdapter); + ASSERT(ucSsidNum <= SCN_SSID_MAX_NUM); + ASSERT(u4IeLength <= MAX_IE_LENGTH); + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + DBGLOG(AIS, TRACE, "eCurrentState=%d, fgIsScanReqIssued = %d\n", + prAisFsmInfo->eCurrentState, prConnSettings->fgIsScanReqIssued); + + if (!prConnSettings->fgIsScanReqIssued) { + prConnSettings->fgIsScanReqIssued = TRUE; + scanInitEssResult(prAdapter); + + if (ucSsidNum == 0) + prAisFsmInfo->ucScanSSIDNum = 0; + else { + prAisFsmInfo->ucScanSSIDNum = ucSsidNum; + + for (i = 0; i < ucSsidNum; i++) { + COPY_SSID(prAisFsmInfo->arScanSSID[i].aucSsid, + prAisFsmInfo->arScanSSID[i].u4SsidLen, + prSsid[i].aucSsid, + prSsid[i].u4SsidLen); + } + } + + kalMemCopy(prAisFsmInfo->aucRandomMac, paucRandomMac, + MAC_ADDR_LEN); + + if (u4IeLength > 0 && u4IeLength <= MAX_IE_LENGTH) { + prAisFsmInfo->u4ScanIELength = u4IeLength; + kalMemCopy(prAisFsmInfo->aucScanIEBuf, pucIe, u4IeLength); + } else + prAisFsmInfo->u4ScanIELength = 0; + + if (prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR) { + if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE + && prAisFsmInfo->fgIsInfraChannelFinished == FALSE) { + /* 802.1x might not finished yet, pend it for later handling .. */ + aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); + } else { + if (prAisFsmInfo->fgIsChannelGranted == TRUE) { + DBGLOG(AIS, WARN, + "Scan Request with channel granted for join operation: %d, %d", + prAisFsmInfo->fgIsChannelGranted, prAisFsmInfo->fgIsChannelRequested); + } + + /* start online scan */ + wlanClearScanningResult(prAdapter); + aisFsmSteps(prAdapter, AIS_STATE_ONLINE_SCAN); + } + } else if (prAisFsmInfo->eCurrentState == AIS_STATE_IDLE) { + wlanClearScanningResult(prAdapter); + aisFsmSteps(prAdapter, AIS_STATE_SCAN); + } else { + aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); + } + } else if (prAdapter->rWifiVar.rRmReqParams.rBcnRmParam.eState == RM_ON_GOING) { + struct NORMAL_SCAN_PARAMS *prNormalScan = &prAdapter->rWifiVar.rRmReqParams.rBcnRmParam.rNormalScan; + + prNormalScan->fgExist = TRUE; + if (ucSsidNum == 0) { + prNormalScan->ucSsidNum = 0; + } else { + prNormalScan->ucSsidNum = ucSsidNum; + + for (i = 0; i < ucSsidNum; i++) { + COPY_SSID(prNormalScan->arSSID[i].aucSsid, + prNormalScan->arSSID[i].u4SsidLen, + prSsid[i].aucSsid, prSsid[i].u4SsidLen); + } + } + + if (u4IeLength > 0 && u4IeLength <= MAX_IE_LENGTH) { + prNormalScan->u4IELen = u4IeLength; + kalMemCopy(prNormalScan->aucScanIEBuf, pucIe, u4IeLength); + } else { + prNormalScan->u4IELen = 0; + } + /* prNormalScan->fgFull2Partial = ucSetChannel; */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); + DBGLOG(AIS, INFO, "Buffer normal scan while Beacon request measurement\n"); + } else { + DBGLOG(AIS, WARN, "Scan Request dropped. (state: %d)\n", prAisFsmInfo->eCurrentState); + } +} /* end of aisFsmScanRequestAdv() */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \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; +#if (CFG_REFACTORY_PMKSA == 0) + UINT_32 u4Entry = 0; +#endif + + 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) { + /*release timer*/ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer); + + /* 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; +#if (CFG_REFACTORY_PMKSA == 0) + /* 3.3 switch to join state */ + /* Three cases can switch to join state: + ** 1. There's an available PMKSA in wpa_supplicant + ** 2. found okc pmkid entry for this BSS + ** 3. current state is disconnected. In this case, supplicant may not get a valid pmksa, + ** so no pmkid will be passed to driver, so we no need to wait pmkid anyway. + */ + if (!prAdapter->rWifiVar.rConnSettings.fgOkcPmksaReady || + (rsnSearchPmkidEntry(prAdapter, prAisFsmInfo->prTargetBssDesc->aucBSSID, &u4Entry) && + prAdapter->rWifiVar.rAisSpecificBssInfo.arPmkidCache[u4Entry].fgPmkidExist)) +#endif + aisFsmSteps(prAdapter, AIS_STATE_JOIN); + + prAisFsmInfo->fgIsChannelGranted = TRUE; + } else if (prAisFsmInfo->eCurrentState == AIS_STATE_REQ_REMAIN_ON_CHANNEL && + prAisFsmInfo->ucSeqNumOfChReq == ucTokenID) { + /* 2. channel privilege has been approved */ + prAisFsmInfo->u4ChGrantedInterval = u4GrantInterval; + +#if CFG_SUPPORT_NCHO + if (prAdapter->rNchoInfo.fgECHOEnabled == TRUE && + prAdapter->rNchoInfo.fgIsSendingAF == TRUE && + prAdapter->rNchoInfo.fgChGranted == FALSE) { + DBGLOG(INIT, TRACE, "NCHO complete rAisChGrntComp trace time is %u\n", kalGetTimeTick()); + prAdapter->rNchoInfo.fgChGranted = TRUE; + complete(&prAdapter->prGlueInfo->rAisChGrntComp); + } +#endif + /* 3.1 set timeout timer in cases upper layer cancel_remain_on_channel never comes */ + cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer, prAisFsmInfo->u4ChGrantedInterval); + + /* 3.2 switch to remain_on_channel state */ + aisFsmSteps(prAdapter, AIS_STATE_REMAIN_ON_CHANNEL); + + /* 3.3. indicate upper layer for channel ready */ + kalReadyOnChannel(prAdapter->prGlueInfo, + prAisFsmInfo->rChReqInfo.u8Cookie, + prAisFsmInfo->rChReqInfo.eBand, + prAisFsmInfo->rChReqInfo.eSco, + prAisFsmInfo->rChReqInfo.ucChannelNum, prAisFsmInfo->rChReqInfo.u4DurationMs); + + prAisFsmInfo->fgIsChannelGranted = TRUE; + } else { /* mismatched grant */ + /* 2. return channel privilege to CNM immediately */ + aisFsmReleaseCh(prAdapter); + } + +} /* end of aisFsmRunEventChGrant() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is to inform CNM that channel privilege +* has been released +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmReleaseCh(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_MSG_CH_ABORT_T prMsgChAbort; + + ASSERT(prAdapter); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + if (prAisFsmInfo->fgIsChannelGranted == TRUE || prAisFsmInfo->fgIsChannelRequested == TRUE) { + + prAisFsmInfo->fgIsChannelRequested = FALSE; + prAisFsmInfo->fgIsChannelGranted = FALSE; + + /* 1. return channel privilege to CNM immediately */ + prMsgChAbort = (P_MSG_CH_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_ABORT_T)); + if (!prMsgChAbort) { + ASSERT(0); /* Can't release Channel to CNM */ + return; + } + + prMsgChAbort->rMsgHdr.eMsgId = MID_MNY_CNM_CH_ABORT; + prMsgChAbort->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + prMsgChAbort->ucTokenID = prAisFsmInfo->ucSeqNumOfChReq; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChAbort, MSG_SEND_METHOD_BUF); + } + +} /* end of aisFsmReleaseCh() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is to inform AIS that corresponding beacon has not +* been received for a while and probing is not successful +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID aisBssBeaconTimeout(IN P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prAisBssInfo; + BOOLEAN fgDoAbortIndication = FALSE; + P_CONNECTION_SETTINGS_T prConnSettings; + + ASSERT(prAdapter); + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* 4 <1> Diagnose Connection for Beacon Timeout Event */ + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + P_STA_RECORD_T prStaRec = prAisBssInfo->prStaRecOfAP; + + if (prStaRec) + fgDoAbortIndication = TRUE; + } else if (prAisBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + fgDoAbortIndication = TRUE; + } + } + /* 4 <2> invoke abort handler */ + if (fgDoAbortIndication && (prAdapter->rWifiVar.rAisFsmInfo.u4PostponeIndStartTime == 0)) { +#if 0 + P_CONNECTION_SETTINGS_T prConnSettings; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prConnSettings->fgIsDisconnectedByNonRequest = TRUE; +#endif + + DBGLOG(AIS, INFO, "Beacon Timeout, Remove BSS [%pM]\n", prAisBssInfo->aucBSSID); + scanRemoveBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); + + /* + * Note: Cannot change TRUE to FALSE; or you will suffer the problem in + * ALPS01270257/ ALPS01804173 + */ + if (prConnSettings->eReConnectLevel < RECONNECT_LEVEL_USER_SET) { + prConnSettings->eReConnectLevel = RECONNECT_LEVEL_BEACON_TIMEOUT; + prConnSettings->fgIsConnReqIssued = TRUE; + } + aisFsmStateAbort(prAdapter, DISCONNECT_REASON_CODE_RADIO_LOST, TRUE); + } + +} /* end of aisBssBeaconTimeout() */ + +VOID aisBssSecurityChanged(P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + prAdapter->rWifiVar.rConnSettings.fgIsDisconnectedByNonRequest = TRUE; + /* To avoid unable to report disconnect to the upper layer */ + prAisBssInfo->fgDisConnReassoc = FALSE; + prAisBssInfo->u2DeauthReason = REASON_CODE_BSS_SECURITY_CHANGE; + aisFsmStateAbort(prAdapter, DISCONNECT_REASON_CODE_DEAUTHENTICATED, FALSE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is to inform AIS that DEAUTH frame has been +* sent and thus state machine could go ahead +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[in] prMsduInfo Pointer of MSDU_INFO_T for DEAUTH frame +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +aisDeauthXmitComplete(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + + ASSERT(prAdapter); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + if (rTxDoneStatus == TX_RESULT_SUCCESS) + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rDeauthDoneTimer); + + if (prAisFsmInfo->eCurrentState == AIS_STATE_DISCONNECTING) { + if (rTxDoneStatus != TX_RESULT_DROPPED_IN_DRIVER) + aisFsmStateAbort(prAdapter, DISCONNECT_REASON_CODE_NEW_CONNECTION, FALSE); + } else { + DBGLOG(AIS, WARN, "DEAUTH frame transmitted without further handling"); + } + + return WLAN_STATUS_SUCCESS; + +} /* end of aisDeauthXmitComplete() */ + +#if CFG_SUPPORT_ROAMING +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Looking for a candidate due to weak signal" to AIS FSM. +* +* @param[in] u4ReqScan Requesting Scan or not +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventRoamingDiscovery(IN P_ADAPTER_T prAdapter, UINT_32 u4ReqScan) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + ENUM_AIS_REQUEST_TYPE_T eAisRequest; + P_BSS_INFO_T prAisBssInfo = NULL; + + DBGLOG(AIS, LOUD, "aisFsmRunEventRoamingDiscovery()\n"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* search candidates by best rssi */ + prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_BEST_RSSI; + +#if CFG_SUPPORT_WFD +#if CFG_ENABLE_WIFI_DIRECT + { + /* Check WFD is running */ + P_BSS_INFO_T prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + + if (prAdapter->fgIsP2PRegistered && + IS_BSS_ACTIVE(prP2pBssInfo) && + (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT || + prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE)) { + DBGLOG(ROAMING, INFO, "Handle roaming when P2P is GC or GO.\n"); + if (prAdapter->rWifiVar.prP2pFsmInfo) { + prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + if ((prWfdCfgSettings->ucWfdEnable == 1) && + ((prWfdCfgSettings->u4WfdFlag & WFD_FLAGS_DEV_INFO_VALID))) { + DBGLOG(ROAMING, INFO, "WFD is running. Stop roaming.\n"); + roamingFsmRunEventRoam(prAdapter); + roamingFsmRunEventFail(prAdapter, ROAMING_FAIL_REASON_NOCANDIDATE); + return; + } + } else { + ASSERT(0); + } + } /* fgIsP2PRegistered */ + } +#endif +#endif + + /* results are still new */ + if (!u4ReqScan) { + roamingFsmRunEventRoam(prAdapter); + eAisRequest = AIS_REQUEST_ROAMING_CONNECT; + } else { + if (prAisFsmInfo->eCurrentState == AIS_STATE_ONLINE_SCAN + || prAisFsmInfo->eCurrentState == AIS_STATE_LOOKING_FOR) { + eAisRequest = AIS_REQUEST_ROAMING_CONNECT; + } else { + eAisRequest = AIS_REQUEST_ROAMING_SEARCH; + } + /* if AP supports Bss Transition Mgmt, then send BSS Transition Query frame to obtain possible + * Neighbor AP report, which can used to assist roaming candicate selection + */ + if (prAisFsmInfo->prTargetStaRec && prAisFsmInfo->prTargetStaRec->fgSupportBTM) { + prAdapter->rWifiVar.rAisSpecificBssInfo.rBTMParam.ucDialogToken = + wnmGetBtmToken(); + prAdapter->rWifiVar.rAisSpecificBssInfo.rBTMParam.ucQueryReason = + BSS_TRANSITION_LOW_RSSI; + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + wnmSendBTMQueryFrame(prAdapter, prAisBssInfo->prStaRecOfAP); + } + } + + if (prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR && prAisFsmInfo->fgIsInfraChannelFinished == TRUE) { + if (eAisRequest == AIS_REQUEST_ROAMING_SEARCH) { + prAisFsmInfo->fgTargetChnlScanIssued = TRUE; + aisFsmSteps(prAdapter, AIS_STATE_LOOKING_FOR); + } else + aisFsmSteps(prAdapter, AIS_STATE_COLLECT_ESS_INFO); + } else { + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_SEARCH, TRUE); + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, TRUE); + + aisFsmInsertRequest(prAdapter, eAisRequest); + } + +} /* end of aisFsmRunEventRoamingDiscovery() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Update the time of ScanDone for roaming and transit to Roam state. +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +ENUM_AIS_STATE_T aisFsmRoamingScanResultsUpdate(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_ROAMING_INFO_T prRoamingFsmInfo; + ENUM_AIS_STATE_T eNextState; + + DBGLOG(AIS, LOUD, "->aisFsmRoamingScanResultsUpdate()\n"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + roamingFsmScanResultsUpdate(prAdapter); + + eNextState = prAisFsmInfo->eCurrentState; + if (prRoamingFsmInfo->eCurrentState == ROAMING_STATE_DISCOVERY) { + roamingFsmRunEventRoam(prAdapter); + eNextState = AIS_STATE_COLLECT_ESS_INFO; + } else if (prAisFsmInfo->eCurrentState == AIS_STATE_LOOKING_FOR) { + eNextState = AIS_STATE_COLLECT_ESS_INFO; + } 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]); + if (prAisBssInfo->prStaRecOfAP != prTargetStaRec) + wmmNotifyDisconnected(prAdapter); + 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 (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) + scanRemoveConnFlagOfBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); + /* 4 <4> Change Media State immediately. */ + aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECT_PREV); + + /* 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 */ + /* before deactivate previous AP, should move its pending MSDUs to the new AP */ + if (prAisBssInfo->prStaRecOfAP) + if (prAisBssInfo->prStaRecOfAP != prTargetStaRec && prAisBssInfo->prStaRecOfAP->fgIsInUse) { + qmMoveStaTxQueue(prAisBssInfo->prStaRecOfAP, prTargetStaRec); + cnmStaRecFree(prAdapter, prAisBssInfo->prStaRecOfAP, FALSE); + } else + DBGLOG(AIS, WARN, "prStaRecOfAP is in use %d\n", prAisBssInfo->prStaRecOfAP->fgIsInUse); + else + DBGLOG(AIS, WARN, "NULL pointer of prAisBssInfo->prStaRecOfAP\n"); + kalClearSecurityFramesByNetType(prAdapter->prGlueInfo, NETWORK_TYPE_AIS_INDEX); +#if (CFG_SUPPORT_TDLS == 1) + TdlsexLinkHistoryRecord(prAdapter->prGlueInfo, TRUE, prAisBssInfo->aucBSSID, + TRUE, TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_ROAMING); +#endif /* CFG_SUPPORT_TDLS */ + +} /* end of aisFsmRoamingDisconnectPrevAP() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will update the contain of BSS_INFO_T for AIS network once +* the roaming was completed. +* +* @param IN prAdapter Pointer to the Adapter structure. +* prStaRec StaRec of roaming AP +* prAssocRspSwRfb +* +* @retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID aisUpdateBssInfoForRoamingAP(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prAssocRspSwRfb) +{ + P_BSS_INFO_T prAisBssInfo; + + DBGLOG(AIS, LOUD, "aisUpdateBssInfoForRoamingAP()"); + + ASSERT(prAdapter); + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + /* 4 <1.1> Change FW's Media State immediately. */ + aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); + + /* 4 <1.2> Deactivate previous AP's STA_RECORD_T in Driver if have. */ + if ((prAisBssInfo->prStaRecOfAP) && + (prAisBssInfo->prStaRecOfAP != prStaRec) && (prAisBssInfo->prStaRecOfAP->fgIsInUse)) { + /* before deactivate previous AP, should move its pending MSDUs to the new AP */ + qmMoveStaTxQueue(prAisBssInfo->prStaRecOfAP, prStaRec); + cnmStaRecChangeState(prAdapter, prAisBssInfo->prStaRecOfAP, STA_STATE_1); + } + /* 4 <1.3> Update BSS_INFO_T */ + aisUpdateBssInfoForJOIN(prAdapter, prStaRec, prAssocRspSwRfb); + + /* 4 <1.4> Activate current AP's STA_RECORD_T in Driver. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + /* 4 <1.6> Indicate Connected Event to Host immediately. */ + /* Require BSSID, Association ID, Beacon Interval.. from AIS_BSS_INFO_T */ + aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, FALSE); + +} /* end of aisFsmRoamingUpdateBss() */ + +#endif /* CFG_SUPPORT_ROAMING */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Check if there is any pending request and remove it (optional) +* +* @param prAdapter +* eReqType +* bRemove +* +* @return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN aisFsmIsRequestPending(IN P_ADAPTER_T prAdapter, IN ENUM_AIS_REQUEST_TYPE_T eReqType, IN BOOLEAN bRemove) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_AIS_REQ_HDR_T prPendingReqHdr, prPendingReqHdrNext; + + ASSERT(prAdapter); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + /* traverse through pending request list */ + LINK_FOR_EACH_ENTRY_SAFE(prPendingReqHdr, + prPendingReqHdrNext, &(prAisFsmInfo->rPendingReqList), rLinkEntry, AIS_REQ_HDR_T) { + /* check for specified type */ + if (prPendingReqHdr->eReqType == eReqType) { + /* check if need to remove */ + if (bRemove == TRUE) { + LINK_REMOVE_KNOWN_ENTRY(&(prAisFsmInfo->rPendingReqList), + &(prPendingReqHdr->rLinkEntry)); + if (eReqType == AIS_REQUEST_SCAN) { + if (prPendingReqHdr->pu8ChannelInfo != NULL) { + DBGLOG(AIS, INFO, "scan req pu8ChannelInfo no NULL\n"); + prAdapter->prGlueInfo->puScanChannel = prPendingReqHdr->pu8ChannelInfo; + prPendingReqHdr->pu8ChannelInfo = NULL; + } + } + 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); + DBGLOG(AIS, INFO, "aisFsmGetNextRequest\n"); + + LINK_REMOVE_HEAD(&(prAisFsmInfo->rPendingReqList), prPendingReqHdr, P_AIS_REQ_HDR_T); + /* save partial scan puScanChannel info to prGlueInfo */ + if ((prPendingReqHdr != NULL) && (prAdapter->prGlueInfo != NULL)) { + if (prAdapter->prGlueInfo->puScanChannel != NULL) + DBGLOG(INIT, TRACE, "prGlueInfo error puScanChannel=%p", prAdapter->prGlueInfo->puScanChannel); + + if (prPendingReqHdr->pu8ChannelInfo != NULL) { + prAdapter->prGlueInfo->puScanChannel = prPendingReqHdr->pu8ChannelInfo; + DBGLOG(AIS, INFO, "aisFsmGetNextRequest pu8ChannelInfo NOT NULL, SAVE\n"); + prPendingReqHdr->pu8ChannelInfo = NULL; + } + } + 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; + } + DBGLOG(AIS, TRACE, "aisFsmInsertRequest\n"); + + prAisReq->eReqType = eReqType; + prAisReq->pu8ChannelInfo = NULL; + /* save partial scan puScanChannel info to pending scan */ + if ((prAdapter->prGlueInfo != NULL) && + (prAdapter->prGlueInfo->puScanChannel != NULL)) { + DBGLOG(AIS, INFO, "aisFsmInsertRequest puScanChannel NOT NULL, SAVE\n"); + prAisReq->pu8ChannelInfo = prAdapter->prGlueInfo->puScanChannel; + prAdapter->prGlueInfo->puScanChannel = NULL; + } + /* attach request into pending request list */ + LINK_INSERT_TAIL(&prAisFsmInfo->rPendingReqList, &prAisReq->rLinkEntry); + + DBGLOG(AIS, INFO, "eCurrentState=%d, eReqType = %d, u4NumElem=%d\n", + prAisFsmInfo->eCurrentState, eReqType, prAisFsmInfo->rPendingReqList.u4NumElem); + + 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) { + /* for partional scan, if channel infor exist, free channel info */ + if (prAisReq->pu8ChannelInfo != NULL) + kalMemFree(prAisReq->pu8ChannelInfo, VIR_MEM_TYPE, sizeof(PARTIAL_SCAN_INFO)); + + cnmMemFree(prAdapter, prAisReq); + } + +} + +VOID aisFsmRunEventRemainOnChannel(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_REMAIN_ON_CHANNEL_T prRemainOnChannel; + P_AIS_FSM_INFO_T prAisFsmInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + + DEBUGFUNC("aisFsmRunEventRemainOnChannel()"); + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + prRemainOnChannel = (P_MSG_REMAIN_ON_CHANNEL_T) prMsgHdr; + + /* record parameters */ + prAisFsmInfo->rChReqInfo.eBand = prRemainOnChannel->eBand; + prAisFsmInfo->rChReqInfo.eSco = prRemainOnChannel->eSco; + prAisFsmInfo->rChReqInfo.ucChannelNum = prRemainOnChannel->ucChannelNum; + prAisFsmInfo->rChReqInfo.u4DurationMs = prRemainOnChannel->u4DurationMs; + prAisFsmInfo->rChReqInfo.u8Cookie = prRemainOnChannel->u8Cookie; + + if ((prAisFsmInfo->eCurrentState == AIS_STATE_IDLE) || + (prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR + && prAisFsmInfo->fgIsInfraChannelFinished == TRUE)) { + /* transit to next state */ + aisFsmSteps(prAdapter, AIS_STATE_REQ_REMAIN_ON_CHANNEL); + } else { + aisFsmInsertRequest(prAdapter, AIS_REQUEST_REMAIN_ON_CHANNEL); + } + + /* free messages */ + cnmMemFree(prAdapter, prMsgHdr); + +} + +VOID aisFsmRunEventCancelRemainOnChannel(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_MSG_CANCEL_REMAIN_ON_CHANNEL_T prCancelRemainOnChannel; + + ASSERT(prAdapter); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + prCancelRemainOnChannel = (P_MSG_CANCEL_REMAIN_ON_CHANNEL_T) prMsgHdr; + + /* 1. Check the cookie first */ + if (prCancelRemainOnChannel->u8Cookie == prAisFsmInfo->rChReqInfo.u8Cookie) { + + /* 2. release channel privilege/request */ + if (prAisFsmInfo->eCurrentState == AIS_STATE_REQ_REMAIN_ON_CHANNEL) { + /* 2.1 elease channel */ + aisFsmReleaseCh(prAdapter); + } else if (prAisFsmInfo->eCurrentState == AIS_STATE_REMAIN_ON_CHANNEL) { + /* 2.1 release channel */ + aisFsmReleaseCh(prAdapter); + + /* 2.2 stop channel timeout timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer); + } + + /* 3. clear pending request of remain_on_channel */ + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_REMAIN_ON_CHANNEL, TRUE); + + /* 4. decide which state to retreat */ + if (prAisFsmInfo->eCurrentState == AIS_STATE_REQ_REMAIN_ON_CHANNEL || + prAisFsmInfo->eCurrentState == AIS_STATE_REMAIN_ON_CHANNEL) { + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) + aisFsmSteps(prAdapter, AIS_STATE_NORMAL_TR); + else + aisFsmSteps(prAdapter, AIS_STATE_IDLE); + } + } + + /* 5. free message */ + cnmMemFree(prAdapter, prMsgHdr); + +} + +VOID aisFsmRunEventMgmtFrameTx(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_MSG_MGMT_TX_REQUEST_T prMgmtTxMsg = (P_MSG_MGMT_TX_REQUEST_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + /* prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); */ + + if (prAisFsmInfo == NULL) + break; + prMgmtTxMsg = (P_MSG_MGMT_TX_REQUEST_T) prMsgHdr; + + aisFuncTxMgmtFrame(prAdapter, + &prAisFsmInfo->rMgmtTxInfo, prMgmtTxMsg->prMgmtMsduInfo, prMgmtTxMsg->u8Cookie); + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* aisFsmRunEventMgmtFrameTx */ + +#if CFG_SUPPORT_NCHO +VOID aisFsmRunEventNchoActionFrameTx(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo = (P_BSS_INFO_T) NULL; + P_MSG_MGMT_TX_REQUEST_T prMgmtTxMsg = (P_MSG_MGMT_TX_REQUEST_T) NULL; + P_MSDU_INFO_T prMgmtFrame = (P_MSDU_INFO_T) NULL; + P_ACTION_VENDOR_SPEC_FRAME_T prVendorSpec = NULL; + PUINT_8 pucFrameBuf = (PUINT_8) NULL; + P_NCHO_INFO prNchoInfo = NULL; + UINT_16 u2PktLen = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + DBGLOG(REQ, TRACE, "NCHO in aisFsmRunEventNchoActionFrameTx\n"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prNchoInfo = &(prAdapter->rNchoInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + if (prAisFsmInfo == NULL) + break; + + prMgmtTxMsg = (P_MSG_MGMT_TX_REQUEST_T) prMsgHdr; + u2PktLen = (UINT_16) OFFSET_OF(ACTION_VENDOR_SPEC_FRAME_T, aucElemInfo[0]) + + prNchoInfo->rParamActionFrame.i4len + + MAC_TX_RESERVED_FIELD; + prMgmtFrame = cnmMgtPktAlloc(prAdapter, u2PktLen); + if (prMgmtFrame == NULL) { + ASSERT(FALSE); + DBGLOG(REQ, ERROR, "NCHO there is no memory for prMgmtFrame\n"); + break; + } + prMgmtTxMsg->prMgmtMsduInfo = prMgmtFrame; + + pucFrameBuf = (PUINT_8) ((ULONG) prMgmtFrame->prPacket + MAC_TX_RESERVED_FIELD); + prVendorSpec = (P_ACTION_VENDOR_SPEC_FRAME_T)pucFrameBuf; + prVendorSpec->u2FrameCtrl = MAC_FRAME_ACTION; + prVendorSpec->u2Duration = 0; + prVendorSpec->u2SeqCtrl = 0; + COPY_MAC_ADDR(prVendorSpec->aucDestAddr, prNchoInfo->rParamActionFrame.aucBssid); + COPY_MAC_ADDR(prVendorSpec->aucSrcAddr, prAisBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prVendorSpec->aucBSSID, prAisBssInfo->aucBSSID); + + kalMemCopy(prVendorSpec->aucElemInfo, + prNchoInfo->rParamActionFrame.aucData, + prNchoInfo->rParamActionFrame.i4len); + + prMgmtFrame->u2FrameLength = u2PktLen; + + aisFuncTxMgmtFrame(prAdapter, + &prAisFsmInfo->rMgmtTxInfo, prMgmtTxMsg->prMgmtMsduInfo, prMgmtTxMsg->u8Cookie); + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* aisFsmRunEventNchoActionFrameTx */ +#endif + +VOID aisFsmRunEventChannelTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + + DEBUGFUNC("aisFsmRunEventRemainOnChannel()"); + + ASSERT(prAdapter); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + DBGLOG(AIS, INFO, "aisFsmRunEventChannelTimeout, CurrentState = [%d]\n" + , prAisFsmInfo->eCurrentState); + + if (prAisFsmInfo->eCurrentState == AIS_STATE_REMAIN_ON_CHANNEL) { + /* 1. release channel */ + aisFsmReleaseCh(prAdapter); + + /* 2. stop channel timeout timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer); + + /* 3. expiration indication to upper layer */ + kalRemainOnChannelExpired(prAdapter->prGlueInfo, + prAisFsmInfo->rChReqInfo.u8Cookie, + prAisFsmInfo->rChReqInfo.eBand, + prAisFsmInfo->rChReqInfo.eSco, prAisFsmInfo->rChReqInfo.ucChannelNum); + + /* 4. decide which state to retreat */ + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) + aisFsmSteps(prAdapter, AIS_STATE_NORMAL_TR); + else + aisFsmSteps(prAdapter, AIS_STATE_IDLE); + } else if (prAisFsmInfo->eCurrentState == AIS_STATE_REQ_CHANNEL_JOIN) { + /* 1. release channel */ + aisFsmReleaseCh(prAdapter); + + /* 2. stop channel timeout timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer); + + prAisFsmInfo->fgIsInfraChannelFinished = FALSE; + + prAisFsmInfo->fgIsChannelGranted = FALSE; + /* 3 switch to idle state */ + aisFsmSteps(prAdapter, AIS_STATE_IDLE); + + } else { + DBGLOG(AIS, WARN, "Unexpected remain_on_channel timeout event\n"); +#if DBG + DBGLOG(AIS, STATE, "CURRENT State: [%s]\n", apucDebugAisState[prAisFsmInfo->eCurrentState]); +#else + DBGLOG(AIS, STATE, "[%d] CURRENT State: [%d]\n", DBG_AIS_IDX, prAisFsmInfo->eCurrentState); +#endif + } + +} + +WLAN_STATUS +aisFsmRunEventMgmtFrameTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_AIS_MGMT_TX_REQ_INFO_T prMgmtTxReqInfo = (P_AIS_MGMT_TX_REQ_INFO_T) NULL; + BOOLEAN fgIsSuccess = FALSE; + P_WLAN_MAC_HEADER_T prWlanFrame = NULL; + P_WLAN_ACTION_FRAME prActFrame = NULL; + UINT_16 u2TxFrameCtrl = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prMgmtTxReqInfo = &(prAisFsmInfo->rMgmtTxInfo); + prWlanFrame = (P_WLAN_MAC_HEADER_T) prMsduInfo->prPacket; + u2TxFrameCtrl = (prWlanFrame->u2FrameCtrl) & MASK_FRAME_TYPE; + + if (rTxDoneStatus != TX_RESULT_SUCCESS) { + DBGLOG(AIS, ERROR, "Mgmt Frame TX Fail, Status:%d.\n", rTxDoneStatus); + } else { + fgIsSuccess = TRUE; +#if CFG_SUPPORT_NCHO + if (prAdapter->rNchoInfo.fgECHOEnabled == TRUE && + prAdapter->rNchoInfo.fgIsSendingAF == TRUE && + prAdapter->rNchoInfo.fgChGranted == TRUE) { + prAdapter->rNchoInfo.fgIsSendingAF = FALSE; + DBGLOG(AIS, TRACE, "NCHO action frame tx done"); + } +#endif + /* printk("Mgmt Frame TX Done.\n"); */ + } + + if (prMgmtTxReqInfo->prMgmtTxMsdu == prMsduInfo) { + if (u2TxFrameCtrl == MAC_FRAME_ACTION) { + prActFrame = (P_WLAN_ACTION_FRAME) prMsduInfo->prPacket; + if (prActFrame->ucCategory == CATEGORY_PUBLIC_ACTION) { + switch (prActFrame->ucAction) { + case PUBLIC_ACTION_GAS_INITIAL_REQ: + DBGLOG(AIS, INFO, "Send GAS Initial Request frame successfully\n"); + break; + case PUBLIC_ACTION_GAS_INITIAL_RESP: + DBGLOG(AIS, INFO, "Send GAS Initial Response frame successfully\n"); + break; + default: + DBGLOG(AIS, TRACE, "Send other public action frame(%u) successfully\n", + prActFrame->ucAction); + break; + } + } + } + kalIndicateMgmtTxStatus(prAdapter->prGlueInfo, + prMgmtTxReqInfo->u8Cookie, + fgIsSuccess, prMsduInfo->prPacket, (UINT_32) prMsduInfo->u2FrameLength); + + prMgmtTxReqInfo->prMgmtTxMsdu = NULL; + } + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; + +} /* aisFsmRunEventMgmtFrameTxDone */ + +#if (CFG_REFACTORY_PMKSA == 0) +VOID aisFsmRunEventSetOkcPmk(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo = &prAdapter->rWifiVar.rAisFsmInfo; + + prAdapter->rWifiVar.rConnSettings.fgOkcPmksaReady = TRUE; + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rWaitOkcPMKTimer); + if (prAisFsmInfo->eCurrentState == AIS_STATE_REQ_CHANNEL_JOIN && + prAisFsmInfo->fgIsChannelGranted) + aisFsmSteps(prAdapter, AIS_STATE_JOIN); +} +#endif + +static VOID aisFsmSetOkcTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam) +{ + P_AIS_FSM_INFO_T prAisFsmInfo = &prAdapter->rWifiVar.rAisFsmInfo; + + DBGLOG(AIS, WARN, "Wait OKC PMKID timeout, current state[%d],fgIsChannelGranted=%d\n" + , prAisFsmInfo->eCurrentState, prAisFsmInfo->fgIsChannelGranted); + if (prAisFsmInfo->eCurrentState == AIS_STATE_REQ_CHANNEL_JOIN && + prAisFsmInfo->fgIsChannelGranted) + aisFsmSteps(prAdapter, AIS_STATE_JOIN); +} + +WLAN_STATUS +aisFuncTxMgmtFrame(IN P_ADAPTER_T prAdapter, + IN P_AIS_MGMT_TX_REQ_INFO_T prMgmtTxReqInfo, IN P_MSDU_INFO_T prMgmtTxMsdu, IN UINT_64 u8Cookie) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_MSDU_INFO_T prTxMsduInfo = (P_MSDU_INFO_T) NULL; + P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMgmtTxReqInfo != NULL)); + + if (prMgmtTxReqInfo->fgIsMgmtTxRequested) { + + /* 1. prMgmtTxReqInfo->prMgmtTxMsdu != NULL */ + /* Packet on driver, not done yet, drop it. */ + prTxMsduInfo = prMgmtTxReqInfo->prMgmtTxMsdu; + if (prTxMsduInfo != NULL) { + + kalIndicateMgmtTxStatus(prAdapter->prGlueInfo, + prMgmtTxReqInfo->u8Cookie, + FALSE, + prTxMsduInfo->prPacket, (UINT_32) prTxMsduInfo->u2FrameLength); + + /* Leave it to TX Done handler. */ + /* cnmMgtPktFree(prAdapter, prTxMsduInfo); */ + prMgmtTxReqInfo->prMgmtTxMsdu = NULL; + } + /* 2. prMgmtTxReqInfo->prMgmtTxMsdu == NULL */ + /* Packet transmitted, wait tx done. (cookie issue) */ + } + + ASSERT(prMgmtTxReqInfo->prMgmtTxMsdu == NULL); + + prWlanHdr = (P_WLAN_MAC_HEADER_T) ((ULONG) prMgmtTxMsdu->prPacket + MAC_TX_RESERVED_FIELD); + prStaRec = cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_AIS_INDEX, prWlanHdr->aucAddr1); + prMgmtTxMsdu->ucNetworkType = (UINT_8) NETWORK_TYPE_AIS_INDEX; + + prMgmtTxReqInfo->u8Cookie = u8Cookie; + prMgmtTxReqInfo->prMgmtTxMsdu = prMgmtTxMsdu; + prMgmtTxReqInfo->fgIsMgmtTxRequested = TRUE; + + prMgmtTxMsdu->eSrc = TX_PACKET_MGMT; + prMgmtTxMsdu->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMgmtTxMsdu->ucStaRecIndex = (prStaRec != NULL) ? (prStaRec->ucIndex) : (0xFF); + if (prStaRec != NULL) { + /* Do nothing */ + /* printk("Mgmt with station record: %pM .\n", prStaRec->aucMacAddr); */ + } + + prMgmtTxMsdu->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; /* TODO: undcertain. */ + prMgmtTxMsdu->fgIs802_1x = FALSE; + prMgmtTxMsdu->fgIs802_11 = TRUE; + prMgmtTxMsdu->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMgmtTxMsdu->pfTxDoneHandler = aisFsmRunEventMgmtFrameTxDone; + prMgmtTxMsdu->fgIsBasicRate = TRUE; + DBGLOG(AIS, TRACE, "Mgmt seq NO. %d .\n", prMgmtTxMsdu->ucTxSeqNum); + + nicTxEnqueueMsdu(prAdapter, prMgmtTxMsdu); + + } while (FALSE); + + return rWlanStatus; +} /* aisFuncTxMgmtFrame */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Action Frame and indicate to uppoer layer +* if the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu4ControlFlags Control flags for replying the Probe Response +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFuncValidateRxActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_AIS_FSM_INFO_T prAisFsmInfo = (P_AIS_FSM_INFO_T) NULL; + + DEBUGFUNC("aisFuncValidateRxActionFrame"); + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + if (1 /* prAisFsmInfo->u4AisPacketFilter & PARAM_PACKET_FILTER_ACTION_FRAME */) { + /* Leave the action frame to wpa_supplicant. */ + kalIndicateRxMgmtFrame(prAdapter->prGlueInfo, prSwRfb); + } + + } while (FALSE); + + return; + +} /* aisFuncValidateRxActionFrame */ + +VOID aisRefreshFWKBlacklist(P_ADAPTER_T prAdapter) +{ + P_CONNECTION_SETTINGS_T prConnSettings = &prAdapter->rWifiVar.rConnSettings; + struct AIS_BLACKLIST_ITEM *prEntry = NULL; + P_LINK_T prBlackList = &prConnSettings->rBlackList.rUsingLink; + + DBGLOG(AIS, INFO, "Refresh all the BSSes' fgIsInFWKBlacklist to FALSE\n"); + LINK_FOR_EACH_ENTRY(prEntry, prBlackList, rLinkEntry, struct AIS_BLACKLIST_ITEM) { + prEntry->fgIsInFWKBlacklist = FALSE; + } +} + +struct AIS_BLACKLIST_ITEM * +aisAddBlacklist(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc) +{ + P_CONNECTION_SETTINGS_T prConnSettings = &prAdapter->rWifiVar.rConnSettings; + struct AIS_BLACKLIST_ITEM *prEntry = NULL; + P_LINK_T prFreeList = &prConnSettings->rBlackList.rFreeLink; + P_LINK_T prBlackList = &prConnSettings->rBlackList.rUsingLink; + + if (!prBssDesc) { + DBGLOG(AIS, ERROR, "bss descriptor is NULL\n"); + return NULL; + } + if (prBssDesc->prBlack) { + GET_CURRENT_SYSTIME(&prBssDesc->prBlack->rAddTime); + prBssDesc->prBlack->ucCount++; + DBGLOG(AIS, INFO, "update blacklist for %pM, count %d\n", + prBssDesc->aucBSSID, prBssDesc->prBlack->ucCount); + return prBssDesc->prBlack; + } + + prEntry = aisQueryBlackList(prAdapter, prBssDesc); + + if (prEntry) { + GET_CURRENT_SYSTIME(&prEntry->rAddTime); + prBssDesc->prBlack = prEntry; + prEntry->ucCount++; + DBGLOG(AIS, INFO, "update blacklist for %pM, count %d\n", + prBssDesc->aucBSSID, prEntry->ucCount); + return prEntry; + } + + LINK_REMOVE_HEAD(prFreeList, prEntry, struct AIS_BLACKLIST_ITEM *); + if (!prEntry) + prEntry = kalMemAlloc(sizeof(struct AIS_BLACKLIST_ITEM), VIR_MEM_TYPE); + if (!prEntry) { + DBGLOG(AIS, WARN, "No memory to allocate\n"); + return NULL; + } + kalMemZero(prEntry, sizeof(*prEntry)); + prEntry->ucCount = 1; + prEntry->fgIsInFWKBlacklist = FALSE; + COPY_MAC_ADDR(prEntry->aucBSSID, prBssDesc->aucBSSID); + COPY_SSID(prEntry->aucSSID, prEntry->ucSSIDLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + GET_CURRENT_SYSTIME(&prEntry->rAddTime); + LINK_INSERT_HEAD(prBlackList, &prEntry->rLinkEntry); + prBssDesc->prBlack = prEntry; + + DBGLOG(AIS, INFO, "Add %pM to black List\n", prBssDesc->aucBSSID); + return prEntry; +} + +VOID aisRemoveBlackList(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc) +{ + P_CONNECTION_SETTINGS_T prConnSettings = &prAdapter->rWifiVar.rConnSettings; + struct AIS_BLACKLIST_ITEM *prEntry = NULL; + P_LINK_T prFreeList = &prConnSettings->rBlackList.rFreeLink; + P_LINK_T prBlackList = &prConnSettings->rBlackList.rUsingLink; + + prEntry = aisQueryBlackList(prAdapter, prBssDesc); + if (!prEntry) + return; + LINK_REMOVE_KNOWN_ENTRY(prBlackList, &prEntry->rLinkEntry); + LINK_INSERT_HEAD(prFreeList, &prEntry->rLinkEntry); + prBssDesc->prBlack = NULL; + DBGLOG(AIS, INFO, "Remove %pM from blacklist\n", prBssDesc->aucBSSID); +} + +struct AIS_BLACKLIST_ITEM * +aisQueryBlackList(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc) +{ + P_CONNECTION_SETTINGS_T prConnSettings = &prAdapter->rWifiVar.rConnSettings; + struct AIS_BLACKLIST_ITEM *prEntry = NULL; + P_LINK_T prBlackList = &prConnSettings->rBlackList.rUsingLink; + + if (!prBssDesc) + return NULL; + else if (prBssDesc->prBlack) + return prBssDesc->prBlack; + + LINK_FOR_EACH_ENTRY(prEntry, prBlackList, rLinkEntry, struct AIS_BLACKLIST_ITEM) { + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prEntry->aucBSSID) && + EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, + prEntry->aucSSID, prEntry->ucSSIDLen)) { + prBssDesc->prBlack = prEntry; + return prEntry; + } + } + DBGLOG(AIS, TRACE, "%pM is not in blacklist\n", prBssDesc->aucBSSID); + return NULL; +} + +VOID aisRemoveTimeoutBlacklist(P_ADAPTER_T prAdapter) +{ + P_CONNECTION_SETTINGS_T prConnSettings = &prAdapter->rWifiVar.rConnSettings; + struct AIS_BLACKLIST_ITEM *prEntry = NULL; + struct AIS_BLACKLIST_ITEM *prNextEntry = NULL; + P_LINK_T prBlackList = &prConnSettings->rBlackList.rUsingLink; + P_LINK_T prFreeList = &prConnSettings->rBlackList.rFreeLink; + OS_SYSTIME rCurrent; + P_BSS_DESC_T prBssDesc = NULL; + + GET_CURRENT_SYSTIME(&rCurrent); + + LINK_FOR_EACH_ENTRY_SAFE(prEntry, prNextEntry, prBlackList, rLinkEntry, struct AIS_BLACKLIST_ITEM) { + if (prEntry->fgIsInFWKBlacklist == TRUE) + continue; + if (!CHECK_FOR_TIMEOUT(rCurrent, prEntry->rAddTime, SEC_TO_MSEC(AIS_BLACKLIST_TIMEOUT))) + continue; + + prBssDesc = scanSearchBssDescByBssid(prAdapter, + prEntry->aucBSSID); + if (prBssDesc) { + prBssDesc->prBlack = NULL; + DBGLOG(AIS, INFO, "Remove Timeout %pM from blacklist\n", + prBssDesc->aucBSSID); + } + LINK_REMOVE_KNOWN_ENTRY(prBlackList, &prEntry->rLinkEntry); + LINK_INSERT_HEAD(prFreeList, &prEntry->rLinkEntry); + } +} + +static VOID aisRemoveDisappearedBlacklist(P_ADAPTER_T prAdapter) +{ + P_CONNECTION_SETTINGS_T prConnSettings = &prAdapter->rWifiVar.rConnSettings; + struct AIS_BLACKLIST_ITEM *prEntry = NULL; + struct AIS_BLACKLIST_ITEM *prNextEntry = NULL; + P_LINK_T prBlackList = &prConnSettings->rBlackList.rUsingLink; + P_LINK_T prFreeList = &prConnSettings->rBlackList.rFreeLink; + P_BSS_DESC_T prBssDesc = NULL; + P_LINK_T prBSSDescList = &prAdapter->rWifiVar.rScanInfo.rBSSDescList; + UINT_32 u4Current = (UINT_32)kalGetBootTime(); + BOOLEAN fgDisappeared = TRUE; + + LINK_FOR_EACH_ENTRY_SAFE(prEntry, prNextEntry, prBlackList, rLinkEntry, struct AIS_BLACKLIST_ITEM) { + fgDisappeared = TRUE; + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + if (prBssDesc->prBlack == prEntry || (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prEntry->aucBSSID) && + EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, + prEntry->aucSSID, prEntry->ucSSIDLen))) { + fgDisappeared = FALSE; + break; + } + } + if (!fgDisappeared || (u4Current - prEntry->u4DisapperTime) < 600 * USEC_PER_SEC) + continue; + + prBssDesc = scanSearchBssDescByBssid(prAdapter, + prEntry->aucBSSID); + if (prBssDesc) { + prBssDesc->prBlack = NULL; + DBGLOG(AIS, INFO, + "Remove disappeared blacklist %s %pM\n", + prEntry->aucSSID, prEntry->aucBSSID); + } + LINK_REMOVE_KNOWN_ENTRY(prBlackList, &prEntry->rLinkEntry); + LINK_INSERT_HEAD(prFreeList, &prEntry->rLinkEntry); + } +} + +BOOLEAN aisApOverload(struct AIS_BLACKLIST_ITEM *prBlack) +{ + switch (prBlack->u2AuthStatus) { + case STATUS_CODE_ASSOC_DENIED_AP_OVERLOAD: + case STATUS_CODE_ASSOC_DENIED_BANDWIDTH: + return TRUE; + } + switch (prBlack->u2DeauthReason) { + case REASON_CODE_DISASSOC_LACK_OF_BANDWIDTH: + case REASON_CODE_DISASSOC_AP_OVERLOAD: + return TRUE; + } + return FALSE; +} + +UINT_16 aisCalculateBlackListScore(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc) +{ + if (!prBssDesc->prBlack) + prBssDesc->prBlack = aisQueryBlackList(prAdapter, prBssDesc); + + if (!prBssDesc->prBlack) + return 100; + else if (aisApOverload(prBssDesc->prBlack) || prBssDesc->prBlack->ucCount >= 10) + return 0; + return 100 - prBssDesc->prBlack->ucCount * 10; +} + +VOID aisRecordBeaconTimeout(P_ADAPTER_T prAdapter, P_BSS_INFO_T prAisBssInfo) +{ +#if 0 /* wave2-feature */ + P_AIS_FSM_INFO_T prAisFsmInfo = &prAdapter->rWifiVar.rAisFsmInfo; + struct LINK_MGMT *prBcnTimeout = &prAisFsmInfo->rBcnTimeout; + struct AIS_BEACON_TIMEOUT_BSS *prEntry = NULL; + + LINK_MGMT_GET_ENTRY(prBcnTimeout, prEntry, struct AIS_BEACON_TIMEOUT_BSS, VIR_MEM_TYPE); + if (!prEntry) { + DBGLOG(CNM, WARN, "No memory to allocate\n"); + return; + } + COPY_MAC_ADDR(prEntry->aucBSSID, prAisBssInfo->aucBSSID); + COPY_SSID(prEntry->aucSSID, prEntry->ucSSIDLen, + prAisBssInfo->aucSSID, prAisBssInfo->ucSSIDLen); + prEntry->u8Tsf = prAisFsmInfo->prTargetBssDesc->u8TimeStamp.QuadPart; + prEntry->u8AddTime = kalGetBootTime(); + LINK_INSERT_TAIL(&prBcnTimeout->rUsingLink, &prEntry->rLinkEntry); +#endif +} + +VOID aisRemoveBeaconTimeoutEntry(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc) +{ +#if 0 /* wave2-feature */ + UINT_64 u8Tsf = 0; + P_AIS_FSM_INFO_T prAisFsmInfo = &prAdapter->rWifiVar.rAisFsmInfo; + struct LINK_MGMT *prBcnTimeout = &prAisFsmInfo->rBcnTimeout; + struct AIS_BEACON_TIMEOUT_BSS *prEntry = NULL; + + LINK_FOR_EACH_ENTRY(prEntry, &prBcnTimeout->rUsingLink, + rLinkEntry, struct AIS_BEACON_TIMEOUT_BSS) { + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prEntry->aucBSSID) && + EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, + prEntry->aucSSID, prEntry->ucSSIDLen)) { + u8Tsf = prBssDesc->u8TimeStamp.QuadPart; + if (u8Tsf < prEntry->u8Tsf) + DBGLOG(AIS, INFO, "%pM %s may reboot %llu seconds ago\n", + prBssDesc->aucBSSID, prBssDesc->aucSSID, u8Tsf/USEC_PER_SEC); + else + DBGLOG(AIS, INFO, "%pM %s\n", prBssDesc->aucBSSID, prBssDesc->aucSSID); + LINK_REMOVE_KNOWN_ENTRY(&prBcnTimeout->rUsingLink, prEntry); + LINK_INSERT_HEAD(&prBcnTimeout->rFreeLink, &prEntry->rLinkEntry); + return; + } + } +#endif +} + +static VOID aisRemoveOldestBcnTimeout(P_AIS_FSM_INFO_T prAisFsmInfo) +{ +#if 0 /* wave2-feature */ + struct AIS_BEACON_TIMEOUT_BSS *prEntry = NULL; + P_LINK_T prLink = &prAisFsmInfo->rBcnTimeout.rUsingLink; + UINT_64 u8Current = kalGetBootTime(); + + while (TRUE) { + prEntry = LINK_PEEK_HEAD(prLink, struct AIS_BEACON_TIMEOUT_BSS, rLinkEntry); + if (!prEntry || (u8Current - prEntry->u8AddTime < CFG_BSS_DISAPPEAR_THRESOLD * USEC_PER_SEC)) + break; + DBGLOG(AIS, INFO, "%pM %s has disappeard about %llu seconds\n", + prEntry->aucBSSID, prEntry->aucSSID, (u8Current - prEntry->u8AddTime)/USEC_PER_SEC); + LINK_REMOVE_HEAD(prLink, prEntry, struct AIS_BEACON_TIMEOUT_BSS *); + } +#endif +} + +VOID aisFsmRunEventBssTransition(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + struct MSG_AIS_BSS_TRANSITION_T *prMsg = (struct MSG_AIS_BSS_TRANSITION_T *)prMsgHdr; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecificBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + P_STA_RECORD_T prStaRec = NULL; + P_BSS_INFO_T prAisBssInfo = NULL; + + struct BSS_TRANSITION_MGT_PARAM_T *prBtmParam = &prAisSpecificBssInfo->rBTMParam; + enum WNM_AIS_BSS_TRANSITION eTransType = BSS_TRANSITION_MAX_NUM; + BOOLEAN fgNeedBtmResponse = FALSE; + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prStaRec = prAisBssInfo->prStaRecOfAP; + + if (!prMsg) { + DBGLOG(AIS, WARN, "Msg Header is NULL\n"); + return; + } + eTransType = prMsg->eTransitionType; + fgNeedBtmResponse = prMsg->fgNeedResponse; + cnmMemFree(prAdapter, prMsgHdr); + + DBGLOG(AIS, INFO, "Transition Type: %d\n", eTransType); + + switch (eTransType) { + case BSS_TRANSITION_DISASSOC: + break; + case BSS_TRANSITION_REQ_ROAMING: + break; + default: + break; + } + + /* always reject roaming request */ + prBtmParam->ucStatusCode = BSS_TRANSITION_MGT_STATUS_CAND_NO_CANDIDATES; + prBtmParam->ucTermDelay = 0; + kalMemZero(prBtmParam->aucTargetBssid, MAC_ADDR_LEN); + prBtmParam->u2OurNeighborBssLen = 0; + + if (fgNeedBtmResponse) + wnmSendBTMResponseFrame(prAdapter, prStaRec); +} + +static VOID +aisSendNeighborRequest(P_ADAPTER_T prAdapter) +{ + struct SUB_ELEMENT_LIST *prSSIDIE; + UINT_8 aucBuffer[sizeof(*prSSIDIE) + 31]; + P_BSS_INFO_T prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + kalMemZero(aucBuffer, sizeof(aucBuffer)); + prSSIDIE = (struct SUB_ELEMENT_LIST *)&aucBuffer[0]; + prSSIDIE->rSubIE.ucSubID = ELEM_ID_SSID; + COPY_SSID(&prSSIDIE->rSubIE.aucOptInfo[0], prSSIDIE->rSubIE.ucLength, + prBssInfo->aucSSID, prBssInfo->ucSSIDLen); + rlmTxNeighborReportRequest(prAdapter, prBssInfo->prStaRecOfAP, prSSIDIE); +} + +VOID aisCollectNeighborAPChannel(P_ADAPTER_T prAdapter, + struct IE_NEIGHBOR_REPORT_T *prNeiRep, UINT_16 u2Length) +{ + PUINT_8 pucChnlList = &prAdapter->rWifiVar.rAisFsmInfo.aucNeighborAPChnl[0]; + UINT_8 i = 0; + BOOLEAN fgValidChannel = FALSE; + + kalMemZero(pucChnlList, CFG_NEIGHBOR_AP_CHANNEL_NUM); + while (u2Length > ELEM_HDR_LEN && i < CFG_NEIGHBOR_AP_CHANNEL_NUM) { + fgValidChannel = rlmDomainIsLegalChannel(prAdapter, + prNeiRep->ucChnlNumber <= 14 ? BAND_2G4:BAND_5G, prNeiRep->ucChnlNumber); + if (fgValidChannel) { + *pucChnlList++ = prNeiRep->ucChnlNumber; + i++; + } + u2Length -= IE_SIZE(prNeiRep); + prNeiRep = (struct IE_NEIGHBOR_REPORT_T *)((PUINT_8)prNeiRep + IE_SIZE(prNeiRep)); + } + pucChnlList = &prAdapter->rWifiVar.rAisFsmInfo.aucNeighborAPChnl[0]; + DBGLOG(AIS, INFO, "Neighbor AP channel cnt %d, list %d %d %d %d %d %d\n", i, pucChnlList[0], + pucChnlList[1], pucChnlList[2], pucChnlList[3], pucChnlList[4], pucChnlList[5]); +} + +VOID aisRunEventChnlUtilRsp(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr) +{ + struct MSG_CH_UTIL_RSP *prChUtilRsp = (struct MSG_CH_UTIL_RSP *)prMsgHdr; + struct ESS_CHNL_INFO *prEssChnlInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo.arCurEssChnlInfo[0]; + PUINT_8 pucChnlList = NULL; + PUINT_8 pucUtilization = NULL; + UINT_8 i = 0; + UINT_8 j = 0; + + if (!prChUtilRsp) + return; + if (prAdapter->rWifiVar.rAisFsmInfo.eCurrentState != AIS_STATE_COLLECT_ESS_INFO) { + cnmMemFree(prAdapter, prChUtilRsp); + return; + } + pucChnlList = prChUtilRsp->aucChnlList; + pucUtilization = prChUtilRsp->aucChUtil; + for (i = 0; i < prChUtilRsp->ucChnlNum; i++) { + DBGLOG(AIS, INFO, "channel %d, utilization %d\n", pucChnlList[i], pucUtilization[i]); + for (j = 0; j < prAdapter->rWifiVar.rAisSpecificBssInfo.ucCurEssChnlInfoNum; j++) { + if (prEssChnlInfo[j].ucChannel != pucChnlList[i]) + continue; + if (prEssChnlInfo[j].ucUtilization >= pucUtilization[i]) + continue; + prEssChnlInfo[j].ucUtilization = pucUtilization[i]; + break; + } + } + cnmMemFree(prAdapter, prChUtilRsp); + aisFsmSteps(prAdapter, AIS_STATE_SEARCH); +} +#if CFG_SUPPORT_DYNAMIC_ROAM +#define CFG_BUF_SIZE 64 +static VOID aisFsmSetRoamingThreshold(P_ADAPTER_T prAdapter, INT_8 cThreshold) +{ + P_AIS_FSM_INFO_T prAisFsmInfo = &prAdapter->rWifiVar.rAisFsmInfo; + UINT_8 aucRoamingCfgBuf[CFG_BUF_SIZE]; + UINT_8 ucRCPI; + + DBGLOG(AIS, INFO, "cThreshold %d, cRoamTriggerThreshold %d\n", + cThreshold, prAisFsmInfo->cRoamTriggerThreshold); + +#if CFG_SUPPORT_NCHO + if (prAdapter->rNchoInfo.fgECHOEnabled) { + DBGLOG(AIS, WARN, "NCHO is enabled now! Don't support to set Roaming Threshold!\n"); + return; + } +#endif + if (prAisFsmInfo->cRoamTriggerThreshold == cThreshold) + return; + prAisFsmInfo->cRoamTriggerThreshold = cThreshold; + ucRCPI = dBm_TO_RCPI(cThreshold); + kalMemZero(aucRoamingCfgBuf, sizeof(aucRoamingCfgBuf)); + kalSnprintf(aucRoamingCfgBuf, CFG_BUF_SIZE, "RoamingRCPIGoodValue %d\nRoamingRCPIPoorValue %d" + , ucRCPI, ucRCPI); + if (wlanFwCfgParse(prAdapter, aucRoamingCfgBuf) != WLAN_STATUS_SUCCESS) + DBGLOG(AIS, INFO, "set cfg parse failed\n"); +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/assoc.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/assoc.c new file mode 100644 index 0000000000000..c27451c1b2dda --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/assoc.c @@ -0,0 +1,1695 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E 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[] = { + {0, assocCalculateConnIELen, assocGenerateConnIE} + , /* supplicant connect IE including rsn */ +#if CFG_SUPPORT_802_11K + {(ELEM_HDR_LEN + 2), NULL, rlmGerneratePowerCapIE}, /* Element ID: 33 */ +#endif + + {(ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP), NULL, rlmReqGenerateHtCapIE} + , /* 45 */ + {(ELEM_HDR_LEN + 1), NULL, assocGenerateMDIE}, /* Element ID: 54 */ + {0, rsnCalculateFTIELen, rsnGenerateFTIE}, /* Element ID: 55 */ +#if CFG_SUPPORT_802_11K + {(ELEM_HDR_LEN + 5), NULL, rlmGernerateRRMEnabledCapIE}, /* Element ID: 70 */ +#endif +#if CFG_SUPPORT_HOTSPOT_2_0 + {(ELEM_HDR_LEN + ELEM_MAX_LEN_HS20_INDICATION), NULL, hs20GenerateHS20IE} + , /* 221 */ +#endif + {(ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_INFO), NULL, mqmGenerateWmmInfoIE} + , /* 221 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_RSN + 4), NULL, rsnGenerateRSNIE} + , /* 48 */ +#if CFG_SUPPORT_MTK_SYNERGY + {(ELEM_HDR_LEN + ELEM_MIN_LEN_MTK_OUI), NULL, rlmGenerateMTKOuiIE} /* 221 */ +#endif +}; + +#if CFG_SUPPORT_AAA +VERIFY_IE_ENTRY_T rxAssocReqIETable[] = { + {ELEM_ID_RESERVED, NULL} /* 255 */ +}; + +APPEND_VAR_IE_ENTRY_T txAssocRespIETable[] = { + {(ELEM_HDR_LEN + ELEM_MAX_LEN_ERP), NULL, rlmRspGenerateErpIE} + , /* 42 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP), NULL, rlmRspGenerateHtCapIE} + , /* 45 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_HT_OP), NULL, rlmRspGenerateHtOpIE} + , /* 61 */ +#if CFG_ENABLE_WIFI_DIRECT + {(ELEM_HDR_LEN + ELEM_MAX_LEN_OBSS_SCAN), NULL, rlmRspGenerateObssScanIE} + , /* 74 */ + {(0), p2pFuncCalculateP2p_IELenForAssocRsp, p2pFuncGenerateP2p_IEForAssocRsp} + , /* 221 */ +#if CFG_SUPPORT_WFD + {(0), wfdFuncCalculateWfdIELenForAssocRsp, wfdFuncGenerateWfdIEForAssocRsp} + , /* 221 */ +#endif +#endif + {(ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP), NULL, rlmRspGenerateExtCapIE} + , /* 127 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_PARAM), NULL, mqmGenerateWmmParamIE} + , /* 221 */ +#if CFG_SUPPORT_MTK_SYNERGY + {(ELEM_HDR_LEN + ELEM_MIN_LEN_MTK_OUI), NULL, rlmGenerateMTKOuiIE} + , /* 221 */ +#endif + + {(0), p2pFuncCalculateWSC_IELenForAssocRsp, p2pFuncGenerateWSC_IEForAssocRsp} /* 221 */ + + , +#if CFG_SUPPORT_802_11W + {(ELEM_HDR_LEN + ELEM_MAX_LEN_TIMEOUT_IE), NULL, rsnPmfGenerateTimeoutIE} + /* 56 */ +#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 +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to compose the Capability Info Field. +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @retval Capability Info Field +*/ +/*----------------------------------------------------------------------------*/ +UINT_16 +assocBuildCapabilityInfo(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + UINT_32 u4NonHTPhyType; + UINT_16 u2CapInfo; + + /* Set up our requested capabilities. */ + u2CapInfo = CAP_INFO_ESS; + u2CapInfo |= CAP_CF_STA_NOT_POLLABLE; +#if CFG_SUPPORT_802_11K + u2CapInfo |= CAP_INFO_RADIO_MEASUREMENT; +#endif + + if (prStaRec == NULL) + u2CapInfo |= CAP_INFO_PRIVACY; + else { + if (prStaRec->u2CapInfo & CAP_INFO_PRIVACY) + u2CapInfo |= CAP_INFO_PRIVACY; + } + + /* 7.3.1.4 */ + if (prStaRec == NULL) { + if ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_SHORT) ||/* ShortPreambleOptionEnable is TRUE */ + (prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_AUTO)) + u2CapInfo |= CAP_INFO_SHORT_PREAMBLE; + if (prAdapter->rWifiVar.fgIsShortSlotTimeOptionEnable) + u2CapInfo |= CAP_INFO_SHORT_SLOT_TIME; + } else if (prStaRec->fgHasBasicPhyType) { + u4NonHTPhyType = prStaRec->ucNonHTBasicPhyType; + + if ((rNonHTPhyAttributes[u4NonHTPhyType].fgIsShortPreambleOptionImplemented) && + /* Short Preamble Option Enable is TRUE */ + ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_SHORT) || + ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_AUTO) && + (prStaRec->u2CapInfo & CAP_INFO_SHORT_PREAMBLE)))) { + + /* Case I: Implemented == TRUE and Short Preamble Option Enable == TRUE. + * Case II: Implemented == TRUE and Short Preamble == AUTO (depends on + * BSS_DESC_T's capability) + */ + u2CapInfo |= CAP_INFO_SHORT_PREAMBLE; + } +#if CFG_SUPPORT_SPEC_MGMT /*Add by Enlai */ + /* Support 802.11h */ + if (prStaRec->u2CapInfo & CAP_INFO_SPEC_MGT) { + /* + * 1. The Power Capability element shall be present if + * dot11SpectrumManagementRequired is true. + * + * 2. A STA shall set dot11SpectrumManagementRequired to TRUE before + * associating with a BSS or IBSS in which the Spectrum Management + * bit is set to 1 in the Capability Information field in Beacon frames + * and Probe Response frames received from the BSS or IBSS. + */ + if (prAdapter->fgEnable5GBand == TRUE) + u2CapInfo |= CAP_INFO_SPEC_MGT; + } +#endif + + if (rNonHTPhyAttributes[u4NonHTPhyType].fgIsShortSlotTimeOptionImplemented && + prAdapter->rWifiVar.fgIsShortSlotTimeOptionEnable) { + u2CapInfo |= CAP_INFO_SHORT_SLOT_TIME; + } + } + + if (prStaRec) { + DBGLOG(SAA, LOUD, "ASSOC REQ: Compose Capability = 0x%04x for Target BSS [%pM].\n", + u2CapInfo, prStaRec->aucMacAddr); + } + + return u2CapInfo; + +} /* end of assocBuildCapabilityInfo() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to compose Common Information Elements for Association +* Request Frame. +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID assocBuildReAssocReqFrameCommonIEs(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + P_STA_RECORD_T prStaRec; + PUINT_8 pucBuffer; + UINT_16 u2SupportedRateSet; + UINT_8 aucAllSupportedRates[RATE_NUM] = { 0 }; + UINT_8 ucAllSupportedRatesLen; + UINT_8 ucSupRatesLen; + UINT_8 ucExtSupRatesLen; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + ASSERT(prMsduInfo); + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + if (!prStaRec) + return; + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (ULONG) prMsduInfo->u2FrameLength); + ASSERT(pucBuffer); + + if (IS_STA_IN_AIS(prStaRec)) { + + /* Fill the SSID element. */ + SSID_IE(pucBuffer)->ucId = ELEM_ID_SSID; + + /* NOTE(Kevin): We copy the SSID from CONNECTION_SETTINGS for the case of + * Passive Scan and the target BSS didn't broadcast SSID on its Beacon Frame. + */ + + COPY_SSID(SSID_IE(pucBuffer)->aucSSID, + SSID_IE(pucBuffer)->ucLength, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + + } +#if CFG_ENABLE_WIFI_DIRECT + else if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) + pucBuffer = p2pBuildReAssocReqFrameCommonIEs(prAdapter, prMsduInfo, pucBuffer); +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (IS_STA_IN_BOW(prStaRec)) { + + SSID_IE(pucBuffer)->ucId = ELEM_ID_SSID; + + /* NOTE(Kevin): We copy the SSID from CONNECTION_SETTINGS for the case of + * Passive Scan and the target BSS didn't broadcast SSID on its Beacon Frame. + */ + + COPY_SSID(SSID_IE(pucBuffer)->aucSSID, + SSID_IE(pucBuffer)->ucLength, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } +#endif + else { + /* Do nothing */ + /* TODO(Kevin): For other network */ + } + + /* NOTE(Kevin 2008/12/19): 16.3.6.3 MLME-ASSOCIATE.indication - + * SupportedRates - The set of data rates that are supported by the STA + * that is requesting association. + * Original(Portable Driver): Only send the Rates that we'll support. + * New: Send the Phy Rates if the result of following & operation == NULL. + */ + /* rateGetDataRatesFromRateSet((prBssDesc->u2OperationalRateSet & */ + /* rPhyAttributes[prBssDesc->ePhyType].u2SupportedRateSet), */ + + if (prStaRec->ucDesiredPhyTypeSet) { + 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, prStaRec->u2BSSBasicRateSet, + aucAllSupportedRates, &ucAllSupportedRatesLen); + + ucSupRatesLen = ((ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) ? + ELEM_MAX_LEN_SUP_RATES : ucAllSupportedRatesLen); + + ucExtSupRatesLen = ucAllSupportedRatesLen - ucSupRatesLen; + + /* Fill the Supported Rates element. */ + if (ucSupRatesLen) { + SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_SUP_RATES; + SUP_RATES_IE(pucBuffer)->ucLength = ucSupRatesLen; + kalMemCopy(SUP_RATES_IE(pucBuffer)->aucSupportedRates, aucAllSupportedRates, ucSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } + + /* Fill the Extended Supported Rates element. */ + if (ucExtSupRatesLen) { + + EXT_SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_EXTENDED_SUP_RATES; + EXT_SUP_RATES_IE(pucBuffer)->ucLength = ucExtSupRatesLen; + + kalMemCopy(EXT_SUP_RATES_IE(pucBuffer)->aucExtSupportedRates, + &aucAllSupportedRates[ucSupRatesLen], ucExtSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } + + /* 7.3.2.19 Supported Channels element */ +#if CFG_SUPPORT_DFS /* Add by Enlai */ + if (prAdapter->fgEnable5GBand == TRUE) { + SUPPORTED_CHANNELS_IE(pucBuffer)->ucId = ELEM_ID_SUP_CHS; + SUPPORTED_CHANNELS_IE(pucBuffer)->ucLength = 8; + + SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[0] = 36; + SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[1] = 4; + SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[2] = 52; + SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[3] = 4; +/* Not China --- Start */ + /* SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[4] = 100; */ + /* SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[5] = 11; */ +/* Not China --- End */ + SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[4] = 149; + SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[5] = 4; + SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[6] = 165; + SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[7] = 1; + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } +#endif + } +} /* end of assocBuildReAssocReqFrameCommonIEs() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the (Re)Association Request frame header and +* its fixed fields +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] aucMACAddress Given Our MAC Address. +* @param[in out] pu2PayloadLen Return the length of the composed fixed fields +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID +assocComposeReAssocReqFrameHeaderAndFF(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN PUINT_8 pucBuffer, IN UINT_8 aucMACAddress[], IN OUT PUINT_16 pu2PayloadLen) +{ + P_WLAN_ASSOC_REQ_FRAME_T prAssocFrame; + BOOLEAN fgIsReAssoc; + + UINT_16 u2FrameCtrl; + UINT_16 u2CapInfo; + UINT_16 u2ListenInterval; + + ASSERT(prStaRec); + ASSERT(pucBuffer); + ASSERT(aucMACAddress); + ASSERT(pu2PayloadLen); + + prAssocFrame = (P_WLAN_ASSOC_REQ_FRAME_T) pucBuffer; + fgIsReAssoc = prStaRec->fgIsReAssoc; + + /* 4 <1> Compose the frame header of the (Re)Association Request frame. */ + /* Fill the Frame Control field. */ + if (fgIsReAssoc) + u2FrameCtrl = MAC_FRAME_REASSOC_REQ; + else + u2FrameCtrl = MAC_FRAME_ASSOC_REQ; + WLAN_SET_FIELD_16(&prAssocFrame->u2FrameCtrl, u2FrameCtrl); + + /* Fill the DA field with Target BSSID. */ + COPY_MAC_ADDR(prAssocFrame->aucDestAddr, prStaRec->aucMacAddr); + + /* Fill the SA field with our MAC Address. */ + COPY_MAC_ADDR(prAssocFrame->aucSrcAddr, aucMACAddress); + + /* Fill the BSSID field with Target BSSID. */ + COPY_MAC_ADDR(prAssocFrame->aucBSSID, prStaRec->aucMacAddr); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ + prAssocFrame->u2SeqCtrl = 0; + + /* 4 <2> Compose the frame body's common fixed field part of the (Re)Association Request frame. */ + u2CapInfo = assocBuildCapabilityInfo(prAdapter, prStaRec); + + /* Fill the Capability Information field. */ + WLAN_SET_FIELD_16(&prAssocFrame->u2CapInfo, u2CapInfo); + + /* + * Calculate the listen interval for the maximum power mode. Currently, we + * set it to the value 2 times DTIM period. + */ + if (prStaRec->ucDTIMPeriod) { + u2ListenInterval = prStaRec->ucDTIMPeriod * DEFAULT_LISTEN_INTERVAL_BY_DTIM_PERIOD; + } else { + DBGLOG(SAA, TRACE, "Use default listen interval\n"); + u2ListenInterval = DEFAULT_LISTEN_INTERVAL; + } + prStaRec->u2ListenInterval = u2ListenInterval; + + /* Fill the Listen Interval field. */ + WLAN_SET_FIELD_16(&prAssocFrame->u2ListenInterval, u2ListenInterval); + + /* 4 <3> Compose the Current AP Address field for ReAssociation Request frame. */ + /* Fill the Current AP Address field. */ + if (prStaRec->fgIsReAssoc) { + if (IS_STA_IN_AIS(prStaRec)) { + + P_AIS_BSS_INFO_T prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + P_WLAN_REASSOC_REQ_FRAME_T prReAssocFrame = (P_WLAN_REASSOC_REQ_FRAME_T) prAssocFrame; + + COPY_MAC_ADDR(prReAssocFrame->aucCurrentAPAddr, prAisBssInfo->aucBSSID); + } else { + ASSERT(0); /* We don't support ReAssociation for other network */ + } + + *pu2PayloadLen = (CAP_INFO_FIELD_LEN + LISTEN_INTERVAL_FIELD_LEN + CURR_AP_ADDR_FIELD_LEN); + } else { + *pu2PayloadLen = (CAP_INFO_FIELD_LEN + LISTEN_INTERVAL_FIELD_LEN); + } + +} /* end of assocComposeReAssocReqFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send the (Re)Association Request frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. +* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS assocSendReAssocReqFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + P_MSDU_INFO_T prMsduInfo; + P_BSS_INFO_T prBssInfo; + + UINT_16 u2PayloadLen; + UINT_16 u2EstimatedFrameLen; + UINT_16 u2EstimatedExtraIELen; + BOOLEAN fgIsReAssoc; + UINT_32 i; + uint16_t txAssocReqIENums; + + 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; + txAssocReqIENums = sizeof(txAssocReqIETable) / + sizeof(APPEND_VAR_IE_ENTRY_T); + +#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 < txAssocReqIENums; 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 < txAssocReqIENums; i++) { + if (txAssocReqIETable[i].u2EstimatedFixedIELen != 0) { + u2EstimatedExtraIELen += txAssocReqIETable[i].u2EstimatedFixedIELen; + } else { + u2EstimatedExtraIELen += (UINT_16) txAssocReqIETable[i].pfnCalculateVariableIELen(prAdapter, + prStaRec->ucNetTypeIndex, + prStaRec); + } + } +#endif + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SAA, WARN, "No PKT_INFO_T for sending (Re)Assoc Request.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose (Re)Association Request frame header and fixed fields in MSDU_INfO_T. */ + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + /* Compose Header and Fixed Field */ + assocComposeReAssocReqFrameHeaderAndFF(prAdapter, + prStaRec, + (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + prBssInfo->aucOwnMacAddr, &u2PayloadLen); + + /* 4 <3> Update information of MSDU_INFO_T */ + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = saaFsmRunEventTxDone; + prMsduInfo->fgIsBasicRate = TRUE; + + /* 4 <4> Compose the frame body's IEs of the (Re)Association Request frame. */ + assocBuildReAssocReqFrameCommonIEs(prAdapter, prMsduInfo); + + /* 4 <5> Compose IEs in MSDU_INFO_T */ +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 && CFG_ENABLE_WIFI_DIRECT + if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + if ((prAdapter->fgIsP2PRegistered)) { + p2pGenerate_IEForAssocReq(prAdapter, prMsduInfo); + } else { + DBGLOG(P2P, TRACE, "Function Linker Lost.\n"); + ASSERT(FALSE); + } + } else { + /* Append IE */ + for (i = 0; i < txAssocReqIENums; i++) { + if (txAssocReqIETable[i].pfnAppendIE) + txAssocReqIETable[i].pfnAppendIE(prAdapter, prMsduInfo); + } + } +#else + /* Append IE */ + for (i = 0; i < txAssocReqIENums; i++) { + if (txAssocReqIETable[i].pfnAppendIE) + txAssocReqIETable[i].pfnAppendIE(prAdapter, prMsduInfo); + } +#endif + + /* 4 <6> Update the (Re)association request information */ + if (IS_STA_IN_AIS(prStaRec)) { + P_WLAN_ASSOC_REQ_FRAME_T prAssocFrame; + + prAssocFrame = (P_WLAN_ASSOC_REQ_FRAME_T) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + +#if CFG_RSN_MIGRATION + kalUpdateReAssocReqInfo(prAdapter->prGlueInfo, + (PUINT_8) &prAssocFrame->u2CapInfo, + prMsduInfo->u2FrameLength - offsetof(WLAN_ASSOC_REQ_FRAME_T, u2CapInfo), + fgIsReAssoc); +#endif + } +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) { + P_WLAN_ASSOC_REQ_FRAME_T prAssocFrame; + + prAssocFrame = (P_WLAN_ASSOC_REQ_FRAME_T) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + kalP2PUpdateAssocInfo(prAdapter->prGlueInfo, + (PUINT_8) &prAssocFrame->u2CapInfo, + prMsduInfo->u2FrameLength - offsetof(WLAN_ASSOC_REQ_FRAME_T, u2CapInfo), + fgIsReAssoc); + } +#endif + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ + + /* 4 <6> Enqueue the frame to send this (Re)Association request frame. */ + DBGLOG(SAA, INFO, "Sending (Re)Assoc Request, network: %d seqNo: %d\n", + prMsduInfo->ucNetworkType, prMsduInfo->ucTxSeqNum); + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; +} /* end of assocSendReAssocReqFrame() */ + +UINT_32 assocCalculateConnIELen(IN P_ADAPTER_T prAdapter, + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + const uint8_t *rsnConn; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + if (IS_STA_IN_AIS(prStaRec) && prConnSettings->assocIeLen > 0) { + rsnConn = kalFindIeMatchMask(ELEM_ID_RSN, + prConnSettings->pucAssocIEs, + prConnSettings->assocIeLen, + NULL, 0, 0, NULL); + /* cut out RSN IE */ + if (rsnConn) + return prConnSettings->assocIeLen - + ELEM_HDR_LEN - RSN_IE(rsnConn)->ucLength; + else + return prConnSettings->assocIeLen; + } + + return 0; +} + +VOID assocGenerateConnIE(IN P_ADAPTER_T prAdapter, + IN OUT P_MSDU_INFO_T prMsduInfo) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + P_STA_RECORD_T prStaRec; + uint8_t *pucBuffer, *cp; + const uint8_t *rsnConn; + uint32_t len, rsnIeLen; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + if (!prStaRec) + return; + + pucBuffer = (uint8_t *) ((unsigned long) + prMsduInfo->prPacket + (unsigned long) + prMsduInfo->u2FrameLength); + cp = pucBuffer; + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + if (IS_STA_IN_AIS(prStaRec) && prConnSettings->assocIeLen > 0) { + rsnConn = kalFindIeMatchMask(ELEM_ID_RSN, + prConnSettings->pucAssocIEs, + prConnSettings->assocIeLen, + NULL, 0, 0, NULL); + + if (!rsnConn) { + kalMemCopy(cp, prConnSettings->pucAssocIEs, + prConnSettings->assocIeLen); + cp += prConnSettings->assocIeLen; + goto dump; + } + + rsnIeLen = ELEM_HDR_LEN + RSN_IE(rsnConn)->ucLength; + + /* Copy data before RSN IE to assoc req */ + len = rsnConn - prConnSettings->pucAssocIEs; + kalMemCopy(cp, prConnSettings->pucAssocIEs, len); + cp += len; + + /* jump to the end of RSN IE and copy Remaing IEs*/ + len = prConnSettings->assocIeLen - len - rsnIeLen; + kalMemCopy(cp, rsnConn + rsnIeLen, len); + cp += len; + } +dump: + prMsduInfo->u2FrameLength += cp - pucBuffer; + DBGLOG_MEM8(SAA, INFO, pucBuffer, cp - pucBuffer); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will strictly check the TX (Re)Association Request frame for +* SAA event handling. +* +* @param[in] prMsduInfo Pointer of MSDU_INFO_T +* +* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS assocCheckTxReAssocReqFrame(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_WLAN_ASSOC_REQ_FRAME_T prAssocReqFrame; + P_STA_RECORD_T prStaRec; + UINT_16 u2TxFrameCtrl; + + ASSERT(prMsduInfo); + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + + prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) (prMsduInfo->prPacket); + ASSERT(prAssocReqFrame); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + if (!prStaRec) + return WLAN_STATUS_INVALID_PACKET; + /* WLAN_GET_FIELD_16(&prAssocReqFrame->u2FrameCtrl, &u2TxFrameCtrl) */ + u2TxFrameCtrl = prAssocReqFrame->u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + u2TxFrameCtrl &= MASK_FRAME_TYPE; + if (prStaRec->fgIsReAssoc) { + if (u2TxFrameCtrl != MAC_FRAME_REASSOC_REQ) + return WLAN_STATUS_FAILURE; + } else { + if (u2TxFrameCtrl != MAC_FRAME_ASSOC_REQ) + return WLAN_STATUS_FAILURE; + } + + return WLAN_STATUS_SUCCESS; + +} /* end of assocCheckTxReAssocReqFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will strictly check the TX (Re)Association Response frame for +* AAA event handling. +* +* @param[in] prMsduInfo Pointer of MSDU_INFO_T +* +* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS assocCheckTxReAssocRespFrame(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame; + P_STA_RECORD_T prStaRec; + UINT_16 u2TxFrameCtrl; + + ASSERT(prMsduInfo); + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + + prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) (prMsduInfo->prPacket); + ASSERT(prAssocRspFrame); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + if (!prStaRec) + return WLAN_STATUS_INVALID_PACKET; + /* WLAN_GET_FIELD_16(&prAssocFrame->u2FrameCtrl, &u2TxFrameCtrl) */ + u2TxFrameCtrl = prAssocRspFrame->u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + u2TxFrameCtrl &= MASK_FRAME_TYPE; + if (prStaRec->fgIsReAssoc) { + if (u2TxFrameCtrl != MAC_FRAME_REASSOC_RSP) + return WLAN_STATUS_FAILURE; + } else { + if (u2TxFrameCtrl != MAC_FRAME_ASSOC_RSP) + return WLAN_STATUS_FAILURE; + } + + return WLAN_STATUS_SUCCESS; + +} /* end of assocCheckTxReAssocRespFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the incoming (Re)Association Frame and take out +* the status code. +* +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu2StatusCode Pointer to store the Status Code from Authentication. +* +* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +assocCheckRxReAssocRspFrameStatus(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu2StatusCode) +{ + P_STA_RECORD_T prStaRec; + P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame; + UINT_16 u2RxFrameCtrl; + UINT_16 u2RxCapInfo; + UINT_16 u2RxStatusCode; + UINT_16 u2RxAssocId; + + ASSERT(prSwRfb); + ASSERT(pu2StatusCode); + + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < (CAP_INFO_FIELD_LEN + + STATUS_CODE_FIELD_LEN + AID_FIELD_LEN)) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + DBGLOG(SAA, LOUD, "prSwRfb->u2PayloadLength = %d\n", prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ASSERT(prStaRec); + + if (!prStaRec) + return WLAN_STATUS_INVALID_PACKET; + /* 4 <1> locate the (Re)Association Resp Frame. */ + prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) prSwRfb->pvHeader; + + /* 4 <2> Parse the Header of (Re)Association Resp Frame. */ + /* WLAN_GET_FIELD_16(&prAssocRspFrame->u2FrameCtrl, &u2RxFrameCtrl); */ + u2RxFrameCtrl = prAssocRspFrame->u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + u2RxFrameCtrl &= MASK_FRAME_TYPE; + if (prStaRec->fgIsReAssoc) { + if (u2RxFrameCtrl != MAC_FRAME_REASSOC_RSP) + return WLAN_STATUS_FAILURE; + } else { + if (u2RxFrameCtrl != MAC_FRAME_ASSOC_RSP) + return WLAN_STATUS_FAILURE; + } + + /* 4 <3> Parse the Fixed Fields of (Re)Association Resp Frame Body. */ + /* WLAN_GET_FIELD_16(&prAssocRspFrame->u2CapInfo, &u2RxCapInfo); */ + u2RxCapInfo = prAssocRspFrame->u2CapInfo; /* NOTE(Kevin): Optimized for ARM */ + + /* WLAN_GET_FIELD_16(&prAssocRspFrame->u2StatusCode, &u2RxStatusCode); */ + u2RxStatusCode = prAssocRspFrame->u2StatusCode; /* NOTE(Kevin): Optimized for ARM */ + + /* 4 <4> Check CAP_INFO */ + /* NOTE(Kevin): CM suggest to add MGMT workaround for those APs didn't check + * the CAP Privacy Bit to overcome a corner case that the Privacy Bit + * of our SCAN result didn't consist with AP's Association Resp. + */ + if (u2RxStatusCode == STATUS_CODE_SUCCESSFUL) { +#if CFG_SUPPORT_WAPI + if (prAdapter->rWifiVar.rConnSettings.fgWapiMode) { + /* WAPI AP allow the customer use WZC to join mode, the privacy bit is 0 */ + /* even at WAI & WAPI_PSK mode, but the assoc respose set the privacy bit set 1 */ + DBGLOG(SEC, TRACE, "Workaround the WAPI AP allow the customer to use WZC to join\n"); + } else +#endif +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered && 1) { + /* Todo:: Fixed this */ + } else +#endif + { + } + +#if CFG_STRICT_CHECK_CAPINFO_PRIVACY + if ((prStaRec->u2CapInfo & CAP_INFO_PRIVACY) ^ (u2RxCapInfo & CAP_INFO_PRIVACY)) + u2RxStatusCode = STATUS_CODE_CAP_NOT_SUPPORTED; +#endif + } + + if (u2RxStatusCode == STATUS_CODE_SUCCESSFUL) { +#if CFG_RSN_MIGRATION + /* + * Update the information in the structure used to query and set + * OID_802_11_ASSOCIATION_INFORMATION. + */ + kalUpdateReAssocRspInfo(prAdapter->prGlueInfo, + (PUINT_8)&prAssocRspFrame->u2CapInfo, + prSwRfb->u2PacketLen - + prSwRfb->u2HeaderLen); +#endif + } + /* 4 <5> Update CAP_INFO and ASSOC_ID */ + if (u2RxStatusCode == STATUS_CODE_SUCCESSFUL) { + prStaRec->u2CapInfo = u2RxCapInfo; + + /* WLAN_GET_FIELD_16(&prAssocRspFrame->u2AssocId, &u2RxAssocId); */ + u2RxAssocId = prAssocRspFrame->u2AssocId; /* NOTE(Kevin): Optimized for ARM */ + + /* 20110715 Workaround for Kingnet 710 AP (Realtek 8186) + * This AP raises the bit 6&7 not bit 14&15 in AID field. + * It cause wrong AID assignment. + * For AID = 2 + * Normal case: 0xC002(1100 0000 0000 0010) => 2 + * Kingnet 710: 0x00C2(0000 0000 1100 0010) => 194 + * workaround: mask bit 6&7 for this AP + */ + if ((u2RxAssocId & BIT(6)) && (u2RxAssocId & BIT(7)) && !(u2RxAssocId & BITS(8, 15))) { + prStaRec->u2AssocId = u2RxAssocId & ~BITS(6, 7); + } else { + prStaRec->u2AssocId = u2RxAssocId & ~AID_MSB; +#if CFG_SUPPORT_802_11W + if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { + P_AIS_SPECIFIC_BSS_INFO_T prBssSpecInfo; + + prBssSpecInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + ASSERT(prBssSpecInfo); + + prBssSpecInfo->ucSaQueryTimedOut = 0; + } +#endif + } + } +#if CFG_SUPPORT_802_11W + if (u2RxStatusCode == STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED) { + DBGLOG(SAA, INFO, "AP rejected due the authentication algorithm not support\n"); + } else if (u2RxStatusCode == STATUS_CODE_ASSOC_REJECTED_TEMPORARILY) { + PUINT_8 pucIE, pucTime; + UINT_16 u2IELength; + UINT_16 u2Offset = 0; + + u2IELength = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen; + pucIE = (PUINT_8) ((ULONG) prSwRfb->pvHeader + prSwRfb->u2HeaderLen); + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (IE_ID(pucIE) == ELEM_ID_TIMEOUT_INTERVAL && IE_LEN(pucIE) == 5) { + pucTime = ((P_IE_HDR_T) pucIE)->aucInfo; + if (pucTime[0] == ACTION_SA_TIMEOUT_ASSOC_COMEBACK) { + UINT_32 tu; + + WLAN_GET_FIELD_32(pucTime + 1, &tu); + DBGLOG(SAA, INFO, + "AP rejected association temporarily;comeback duration %u TU (%u ms)\n", + tu, TU_TO_MSEC(tu)); + if (tu > TX_ASSOCIATION_RETRY_TIMEOUT_TU) { + DBGLOG(SAA, INFO, "Update timer based on comeback duration\n"); + /* ieee80211_reschedule_timer(wpa_s, ms); */ + } + } + break; + } + } /* end of IE_FOR_EACH */ + } +#endif + *pu2StatusCode = u2RxStatusCode; + + return WLAN_STATUS_SUCCESS; + +} /* end of assocCheckRxReAssocRspFrameStatus() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will compose the Disassociation frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] aucMACAddress Given Our MAC Address. +* @param[in] u2ReasonCode The reason code of disassociation +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID +assocComposeDisassocFrame(IN P_STA_RECORD_T prStaRec, + IN PUINT_8 pucBuffer, IN UINT_8 aucMACAddress[], IN UINT_16 u2ReasonCode) +{ + P_WLAN_DISASSOC_FRAME_T prDisAssocFrame; + UINT_16 u2FrameCtrl; + + ASSERT(pucBuffer); + ASSERT(pucBuffer); + ASSERT(aucMACAddress); + + prDisAssocFrame = (P_WLAN_DISASSOC_FRAME_T) pucBuffer; + + /* 4 <1> Compose the frame header of the DisAssociation frame. */ + /* Fill the Frame Control field. */ + u2FrameCtrl = MAC_FRAME_DISASSOC; + + WLAN_SET_FIELD_16(&prDisAssocFrame->u2FrameCtrl, u2FrameCtrl); + + /* Fill the DA field with Target BSSID. */ + COPY_MAC_ADDR(prDisAssocFrame->aucDestAddr, prStaRec->aucMacAddr); + + /* Fill the SA field with our MAC Address. */ + COPY_MAC_ADDR(prDisAssocFrame->aucSrcAddr, aucMACAddress); + + /* Fill the BSSID field with Target BSSID. */ + COPY_MAC_ADDR(prDisAssocFrame->aucBSSID, prStaRec->aucMacAddr); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ + prDisAssocFrame->u2SeqCtrl = 0; + + /* 4 <2> Compose the frame body's fixed field part of the Disassociation frame. */ + /* Fill the Reason Code field. */ + WLAN_SET_FIELD_16(&prDisAssocFrame->u2ReasonCode, u2ReasonCode); + +} /* end of assocComposeDisassocFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send the Disassociation frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] u2ReasonCode The reason code of disassociation +* +* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. +* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS assocSendDisAssocFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN UINT_16 u2ReasonCode) +{ + PUINT_8 pucMacAddress; + P_MSDU_INFO_T prMsduInfo; + UINT_16 u2PayloadLen; + UINT_16 u2EstimatedFrameLen; + /* UINT_32 u4Status = WLAN_STATUS_SUCCESS; */ + + ASSERT(prStaRec); + + DBGLOG(RSN, TRACE, "assocSendDisAssocFrame\n"); + + /* 4 <1> Allocate a PKT_INFO_T for Disassociation Frame */ + /* Init with MGMT Header Length + Length of Fixed Fields + IE Length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + WLAN_MAC_MGMT_HEADER_LEN + REASON_CODE_FIELD_LEN; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SAA, WARN, "No PKT_INFO_T for sending DisAssoc.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Disassociation frame header and fixed fields in MSDU_INfO_T. */ + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + pucMacAddress = prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex].aucOwnMacAddr; + + /* Compose Header and Fixed Field */ + assocComposeDisassocFrame(prStaRec, + (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + pucMacAddress, u2ReasonCode); + +#if CFG_SUPPORT_802_11W + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + /* PMF certification 4.3.3.1, 4.3.3.2 send unprotected deauth reason 6/7 */ + if (prStaRec->rPmfCfg.fgRxDeauthResp != TRUE) { + P_WLAN_DISASSOC_FRAME_T prDisassocFrame; + + prDisassocFrame = + (P_WLAN_DISASSOC_FRAME_T) (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + prDisassocFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + DBGLOG(TX, WARN, "assocSendDisAssocFrame with protection\n"); + } + } +#endif + + u2PayloadLen = REASON_CODE_FIELD_LEN; + + /* 4 <3> Update information of MSDU_INFO_T */ + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->fgIsBasicRate = TRUE; + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + /* caution: access prStaRec only if true */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + /* 4.3.3.1 send unprotected deauth reason 6/7 */ + if (prStaRec->rPmfCfg.fgRxDeauthResp != TRUE) { + DBGLOG(RSN, INFO, "Disassoc Set MSDU_OPT_PROTECTED_FRAME\n"); + nicTxConfigPktOption(prMsduInfo, + MSDU_OPT_PROTECTED_FRAME, TRUE); + } + + prStaRec->rPmfCfg.fgRxDeauthResp = FALSE; + } +#endif + + /* 4 <4> Enqueue the frame to send this (Re)Association request frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; +} /* end of assocSendDisAssocFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will parse and process the incoming Disassociation frame +* if the given BSSID is matched. +* +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[in] aucBSSID Given BSSID +* @param[out] pu2ReasonCode Pointer to store the Reason Code from Deauthentication. +* +* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +assocProcessRxDisassocFrame(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, IN UINT_8 aucBSSID[], OUT PUINT_16 pu2ReasonCode) +{ + P_WLAN_DISASSOC_FRAME_T prDisassocFrame; + UINT_16 u2RxReasonCode; + + ASSERT(prSwRfb); + ASSERT(aucBSSID); + ASSERT(pu2ReasonCode); + + /* 4 <1> locate the Disassociation Frame. */ + prDisassocFrame = (P_WLAN_DISASSOC_FRAME_T) prSwRfb->pvHeader; + + /* 4 <2> Parse the Header of Disassociation Frame. */ + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < REASON_CODE_FIELD_LEN) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + /* Check if this Disassoc Frame is coming from Target BSSID */ + if (UNEQUAL_MAC_ADDR(prDisassocFrame->aucBSSID, aucBSSID)) { + DBGLOG(SAA, LOUD, "Ignore Disassoc Frame from other BSS [ %pM ]\n", + prDisassocFrame->aucSrcAddr); + return WLAN_STATUS_FAILURE; + } + /* 4 <3> Parse the Fixed Fields of Deauthentication Frame Body. */ + WLAN_GET_FIELD_16(&prDisassocFrame->u2ReasonCode, &u2RxReasonCode); + *pu2ReasonCode = u2RxReasonCode; + + return WLAN_STATUS_SUCCESS; + +} /* end of assocProcessRxDisassocFrame() */ + +#if CFG_SUPPORT_AAA +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will parse and process the incoming Association Req frame +* and return a Status Code. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu2StatusCode Pointer to store the Status Code for carried in Association Response. +* +* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS assocProcessRxAssocReqFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu2StatusCode) +{ + P_WLAN_ASSOC_REQ_FRAME_T prAssocReqFrame; + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prBssInfo; + P_IE_SSID_T prIeSsid = (P_IE_SSID_T) NULL; + P_RSN_INFO_ELEM_T prIeRsn = (P_RSN_INFO_ELEM_T) NULL; + P_IE_SUPPORTED_RATE_T prIeSupportedRate = (P_IE_SUPPORTED_RATE_T) NULL; + P_IE_EXT_SUPPORTED_RATE_T prIeExtSupportedRate = (P_IE_EXT_SUPPORTED_RATE_T) NULL; + PUINT_8 pucIE, pucIEStart; + UINT_16 u2IELength; + UINT_16 u2Offset = 0; + UINT_16 u2StatusCode = STATUS_CODE_SUCCESSFUL; + UINT_16 u2RxFrameCtrl; + UINT_16 u2BSSBasicRateSet; + BOOLEAN fgIsUnknownBssBasicRate; + UINT_32 i; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + ASSERT(pu2StatusCode); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prStaRec == NULL) + return WLAN_STATUS_FAILURE; + /* 4 <1> locate the Association Req Frame. */ + prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) prSwRfb->pvHeader; + + /* 4 <2> Parse the Header of Association Req Frame. */ + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < (CAP_INFO_FIELD_LEN + LISTEN_INTERVAL_FIELD_LEN)) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + /* Check if this Disassoc Frame is coming from Target BSSID */ + if (UNEQUAL_MAC_ADDR(prAssocReqFrame->aucBSSID, prBssInfo->aucBSSID)) + return WLAN_STATUS_FAILURE; /* Just Ignore this MMPDU */ + /* WLAN_GET_FIELD_16(&prAssocReqFrame->u2FrameCtrl, &u2RxFrameCtrl); */ + u2RxFrameCtrl = prAssocReqFrame->u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + u2RxFrameCtrl &= MASK_FRAME_TYPE; + if (u2RxFrameCtrl == MAC_FRAME_REASSOC_REQ) { + prStaRec->fgIsReAssoc = TRUE; + + u2IELength = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - + (UINT_16) (OFFSET_OF(WLAN_REASSOC_REQ_FRAME_T, aucInfoElem[0]) - WLAN_MAC_MGMT_HEADER_LEN); + + pucIEStart = pucIE = ((P_WLAN_REASSOC_REQ_FRAME_T) (prSwRfb->pvHeader))->aucInfoElem; + } else { + prStaRec->fgIsReAssoc = FALSE; + + u2IELength = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - + (UINT_16) (OFFSET_OF(WLAN_ASSOC_REQ_FRAME_T, aucInfoElem[0]) - WLAN_MAC_MGMT_HEADER_LEN); + + pucIEStart = pucIE = prAssocReqFrame->aucInfoElem; + } + + /* 4 <3> Parse the Fixed Fields of Assoc Req Frame Body. */ + prStaRec->u2CapInfo = prAssocReqFrame->u2CapInfo; + +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_HOTSPOT_PRIVACY_CHECK + if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { + if (((prStaRec->u2CapInfo & CAP_INFO_PRIVACY) && !kalP2PGetCipher(prAdapter->prGlueInfo))) { + u2StatusCode = STATUS_CODE_CAP_NOT_SUPPORTED; + DBGLOG(RSN, TRACE, "STA Assoc req privacy bit check fail\n"); + return WLAN_STATUS_SUCCESS; + } + } +#endif + + prStaRec->u2ListenInterval = prAssocReqFrame->u2ListenInterval; + prStaRec->ucPhyTypeSet = 0; + + /* Might be legacy client or p2p gc. */ + prStaRec->eStaType = STA_TYPE_LEGACY_CLIENT; + + /* 4 <4> Parse the IE of Assoc Req Frame Body. */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_SSID: + if ((!prIeSsid) && /* NOTE(Kevin): Get SSID once */ + (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) { + prIeSsid = (P_IE_SSID_T) pucIE; + } + break; + + case ELEM_ID_SUP_RATES: + if ((!prIeSupportedRate) && (IE_LEN(pucIE) <= RATE_NUM)) + prIeSupportedRate = SUP_RATES_IE(pucIE); + break; + + case ELEM_ID_EXTENDED_SUP_RATES: + if (!prIeExtSupportedRate) + prIeExtSupportedRate = EXT_SUP_RATES_IE(pucIE); + break; + case ELEM_ID_HT_CAP: + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HT; + kalMemCopy(&prStaRec->u2HtCapInfo, &(HT_CAP_IE(pucIE)->u2HtCapInfo), 2); + break; + case ELEM_ID_RSN: +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_HOTSPOT_PRIVACY_CHECK + if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { + prIeRsn = RSN_IE(pucIE); + rsnParserCheckForRSNCCMPPSK(prAdapter, prIeRsn, + prStaRec, &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 != NULL)) { + 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 (HIF_RX_HDR_GET_RF_BAND(prSwRfb->prHifRxHdr) == BAND_2G4) { + 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; + } else { /* (BAND_5G == prBssDesc->eBande) */ + if (prStaRec->u2OperationalRateSet & RATE_SET_OFDM) + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_OFDM; + } + + } else { + ASSERT(0); + u2StatusCode = STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED; + break; + } + +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_HOTSPOT_PRIVACY_CHECK + if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { + if (prIeRsn) { + if (!kalP2PGetCipher(prAdapter->prGlueInfo)) { + u2StatusCode = STATUS_CODE_CIPHER_SUITE_REJECTED; + break; + } + } else { + prStaRec->rSecInfo.fgAllowOnly1x = FALSE; + if (kalP2PGetCipher(prAdapter->prGlueInfo)) { + /* Only Allow 1x */ + prStaRec->rSecInfo.fgAllowOnly1x = TRUE; + break; + } + } + } +#endif + + } while (FALSE); + +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { +#if 1 /* ICS */ + { + PUINT_8 cp = (PUINT_8) &prAssocReqFrame->u2CapInfo; + P_UINT_8 prNewAssocReqIe = NULL; + + if (u2IELength) { + prNewAssocReqIe = kalMemAlloc(u2IELength, VIR_MEM_TYPE); + if (prNewAssocReqIe == NULL) { + DBGLOG(AIS, WARN, "allocate memory for (Re)assocReqIe fail!\n"); + u2StatusCode = STATUS_CODE_INVALID_INFO_ELEMENT; + return WLAN_STATUS_FAILURE; + } + } + + if (prStaRec->fgIsReAssoc) + cp += 10; + else + cp += 4; + if (prStaRec->pucAssocReqIe) { + kalMemFree(prStaRec->pucAssocReqIe, VIR_MEM_TYPE, prStaRec->u2AssocReqIeLen); + prStaRec->pucAssocReqIe = NULL; + } + prStaRec->u2AssocReqIeLen = u2IELength; + if (u2IELength) { + prStaRec->pucAssocReqIe = prNewAssocReqIe; /* kalMemAlloc(u2IELength, VIR_MEM_TYPE); */ + kalMemCopy(prStaRec->pucAssocReqIe, cp, u2IELength); + } + } +#endif + kalP2PUpdateAssocInfo(prAdapter->prGlueInfo, (PUINT_8) &prAssocReqFrame->u2CapInfo, + u2IELength + (prStaRec->fgIsReAssoc ? 10 : 4), prStaRec->fgIsReAssoc); + } +#endif + + *pu2StatusCode = u2StatusCode; + + return WLAN_STATUS_SUCCESS; + +} /* end of assocProcessRxAssocReqFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to compose Common Information Elements for Association +* Response Frame. +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* @param[in] prBssInfo Pointer to the BSS_INFO_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID +assocBuildReAssocRespFrameCommonIEs(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN P_BSS_INFO_T prBssInfo) +{ + PUINT_8 pucBuffer; + P_STA_RECORD_T prStaRec; + UINT_8 ucSupRatesLen; + UINT_8 ucExtSupRatesLen; + + ASSERT(prMsduInfo); + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + ASSERT(pucBuffer); + + if (prBssInfo->ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) { + + ucSupRatesLen = ELEM_MAX_LEN_SUP_RATES; + ucExtSupRatesLen = prBssInfo->ucAllSupportedRatesLen - ELEM_MAX_LEN_SUP_RATES; + } else { + ucSupRatesLen = prBssInfo->ucAllSupportedRatesLen; + ucExtSupRatesLen = 0; + } + + /* Fill the Supported Rates element. */ + if (ucSupRatesLen) { + SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_SUP_RATES; + SUP_RATES_IE(pucBuffer)->ucLength = ucSupRatesLen; + kalMemCopy(SUP_RATES_IE(pucBuffer)->aucSupportedRates, prBssInfo->aucAllSupportedRates, ucSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } + + /* Fill the Extended Supported Rates element. */ + if (ucExtSupRatesLen) { + + EXT_SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_EXTENDED_SUP_RATES; + EXT_SUP_RATES_IE(pucBuffer)->ucLength = ucExtSupRatesLen; + + kalMemCopy(EXT_SUP_RATES_IE(pucBuffer)->aucExtSupportedRates, + &prBssInfo->aucAllSupportedRates[ucSupRatesLen], ucExtSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + } + +} /* end of assocBuildReAssocRespFrameCommonIEs() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the (Re)Association Response frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] aucBssid Given BSSID. +* @param[in] u2CapInfo Capability Field of current BSS. +* @param[in out] pu2PayloadLen Return the length of the composed fixed fields +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID +assocComposeReAssocRespFrameHeaderAndFF(IN P_STA_RECORD_T prStaRec, + IN PUINT_8 pucBuffer, + IN UINT_8 aucBSSID[], IN UINT_16 u2CapInfo, IN OUT PUINT_16 pu2PayloadLen) +{ + P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame; + BOOLEAN fgIsReAssoc; + + UINT_16 u2FrameCtrl; + + ASSERT(prStaRec); + ASSERT(pucBuffer); + ASSERT(aucBSSID); + ASSERT(pu2PayloadLen); + + prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) pucBuffer; + fgIsReAssoc = prStaRec->fgIsReAssoc; + + /* 4 <1> Compose the frame header of the (Re)Association Request frame. */ + /* Fill the Frame Control field. */ + if (fgIsReAssoc) + u2FrameCtrl = MAC_FRAME_REASSOC_RSP; + else + u2FrameCtrl = MAC_FRAME_ASSOC_RSP; + /* WLAN_SET_FIELD_16(&prAssocFrame->u2FrameCtrl, u2FrameCtrl); */ + prAssocRspFrame->u2FrameCtrl = u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the DA field with Target MAC Address. */ + COPY_MAC_ADDR(prAssocRspFrame->aucDestAddr, prStaRec->aucMacAddr); + + /* Fill the SA field with current BSSID. */ + COPY_MAC_ADDR(prAssocRspFrame->aucSrcAddr, aucBSSID); + + /* Fill the BSSID field with current BSSID. */ + COPY_MAC_ADDR(prAssocRspFrame->aucBSSID, aucBSSID); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ + prAssocRspFrame->u2SeqCtrl = 0; + + /* 4 <2> Compose the frame body's common fixed field part of the (Re)Association Request frame. */ + /* Fill the Capability Information field. */ + /* WLAN_SET_FIELD_16(&prAssocFrame->u2CapInfo, u2CapInfo); */ + prAssocRspFrame->u2CapInfo = u2CapInfo; /* NOTE(Kevin): Optimized for ARM */ + + /* WLAN_SET_FIELD_16(&prAssocFrame->u2StatusCode, prStaRec->u2StatusCode); */ + prAssocRspFrame->u2StatusCode = prStaRec->u2StatusCode; /* NOTE(Kevin): Optimized for ARM */ + + /* WLAN_SET_FIELD_16(&prAssocFrame->u2AssocId, ((prStaRec->u2AssocId & AID_MASK) | AID_MSB)); */ + prAssocRspFrame->u2AssocId = ((prStaRec->u2AssocId & AID_MASK) | AID_MSB); /* NOTE(Kevin): Optimized for ARM */ + + *pu2PayloadLen = (CAP_INFO_FIELD_LEN + STATUS_CODE_FIELD_LEN + AID_FIELD_LEN); + +} /* end of assocComposeReAssocRespFrameHeaderAndFF() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send the (Re)Association Resp frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. +* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS assocSendReAssocRespFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + P_BSS_INFO_T prBssInfo; + P_MSDU_INFO_T prMsduInfo; + + UINT_16 u2PayloadLen; + UINT_16 u2EstimatedFrameLen; + UINT_16 u2EstimatedExtraIELen; + BOOLEAN fgIsReAssoc; + UINT_32 i; + + ASSERT(prStaRec); + + /* 4 <1> Allocate a PKT_INFO_T for Authentication Frame */ + fgIsReAssoc = prStaRec->fgIsReAssoc; + + /* Init with MGMT Header Length + Length of Fixed Fields + Common IE Length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + + WLAN_MAC_MGMT_HEADER_LEN + + CAP_INFO_FIELD_LEN + + STATUS_CODE_FIELD_LEN + + AID_FIELD_LEN + + (ELEM_HDR_LEN + ELEM_MAX_LEN_SUP_RATES) + (ELEM_HDR_LEN + (RATE_NUM - ELEM_MAX_LEN_SUP_RATES)); + + /* + Extra IE Length */ + u2EstimatedExtraIELen = 0; + + for (i = 0; i < sizeof(txAssocRespIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); i++) { + if (txAssocRespIETable[i].u2EstimatedFixedIELen != 0) { + u2EstimatedExtraIELen += txAssocRespIETable[i].u2EstimatedFixedIELen; + } else if (txAssocRespIETable[i].pfnCalculateVariableIELen != NULL) { + u2EstimatedExtraIELen += (UINT_16) txAssocRespIETable[i].pfnCalculateVariableIELen(prAdapter, + prStaRec->ucNetTypeIndex, + prStaRec); + } + + } + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(AAA, WARN, "No PKT_INFO_T for sending (Re)Assoc Response.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose (Re)Association Request frame header and fixed fields in MSDU_INfO_T. */ + ASSERT(prStaRec->ucNetTypeIndex != NETWORK_TYPE_AIS_INDEX); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + /* Compose Header and Fixed Field */ + assocComposeReAssocRespFrameHeaderAndFF(prStaRec, + (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + prBssInfo->aucBSSID, prBssInfo->u2CapInfo, &u2PayloadLen); + + /* 4 <3> Update information of MSDU_INFO_T */ + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = aaaFsmRunEventTxDone; + prMsduInfo->fgIsBasicRate = TRUE; + + /* 4 <4> Compose the frame body's IEs of the (Re)Association Request frame. */ + assocBuildReAssocRespFrameCommonIEs(prAdapter, prMsduInfo, prBssInfo); + + /* 4 <5> Compose IEs in MSDU_INFO_T */ + + /* Append IE */ + for (i = 0; i < sizeof(txAssocRespIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); i++) { + if (txAssocRespIETable[i].pfnAppendIE) + txAssocRespIETable[i].pfnAppendIE(prAdapter, prMsduInfo); + } + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ + + /* 4 <6> Enqueue the frame to send this (Re)Association request frame. */ + DBGLOG(SAA, INFO, "Sending (Re)Assoc Response, network: %d seqNo: %d, status: %d\n", + prMsduInfo->ucNetworkType, + prMsduInfo->ucTxSeqNum, + prStaRec->u2StatusCode); + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; + +} /* end of assocSendReAssocRespFrame() */ +#endif /* CFG_SUPPORT_AAA */ + +VOID assocGenerateMDIE(IN P_ADAPTER_T prAdapter, IN OUT P_MSDU_INFO_T prMsduInfo) +{ + struct FT_IES *prFtIEs = &prAdapter->prGlueInfo->rFtIeForTx; + PUINT_8 pucBuffer = (PUINT_8)prMsduInfo->prPacket + prMsduInfo->u2FrameLength; + ENUM_PARAM_AUTH_MODE_T eAuthMode = prAdapter->rWifiVar.rConnSettings.eAuthMode; + + /* don't include MDIE in assoc request frame if auth mode is not FT related */ + if (eAuthMode != AUTH_MODE_NON_RSN_FT && eAuthMode != AUTH_MODE_WPA2_FT && + eAuthMode != AUTH_MODE_WPA2_FT_PSK) + return; + + if (!prFtIEs->prMDIE) { + P_BSS_DESC_T prBssDesc = prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc; + PUINT_8 pucIE = &prBssDesc->aucIEBuf[0]; + UINT_16 u2IeLen = prBssDesc->u2IELength; + UINT_16 u2IeOffSet = 0; + + IE_FOR_EACH(pucIE, u2IeLen, u2IeOffSet) { + if (IE_ID(pucIE) == ELEM_ID_MOBILITY_DOMAIN) { + prMsduInfo->u2FrameLength += 5; /* IE size for MD IE is fixed, it is 5 */ + kalMemCopy(pucBuffer, pucIE, 5); + break; + } + } + return; + } + prMsduInfo->u2FrameLength += 5; /* IE size for MD IE is fixed, it is 5 */ + kalMemCopy(pucBuffer, prFtIEs->prMDIE, 5); +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/auth.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/auth.c new file mode 100644 index 0000000000000..6357f6ab69f07 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/auth.c @@ -0,0 +1,1232 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E 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 txAuthIETable[] = { + {(ELEM_HDR_LEN + ELEM_MAX_LEN_CHALLENGE_TEXT), NULL, authAddIEChallengeText}, + {0, authCalculateRSNIELen, authAddRSNIE}, /* Element ID: 48 */ + {(ELEM_HDR_LEN + 1), NULL, authAddMDIE}, /* Element ID: 54 */ + {0, rsnCalculateFTIELen, rsnGenerateFTIE}, /* Element ID: 55 */ +}; + +HANDLE_IE_ENTRY_T rxAuthIETable[] = { + {ELEM_ID_CHALLENGE_TEXT, authHandleIEChallengeText}, +/* since we only need to indicate these IEs to supplicant, so process them in one function +* Now we disable it, because no FtIEs need to indicate to supplicant +**/ +#if 0 + {ELEM_ID_MOBILITY_DOMAIN, authHandleFtIEs}, + {ELEM_ID_FAST_TRANSITION, authHandleFtIEs}, + {ELEM_ID_RSN, authHandleFtIEs}, + {ELEM_ID_RESOURCE_INFO_CONTAINER, authHandleFtIEs}, + {ELEM_ID_TIMEOUT_INTERVAL, authHandleFtIEs}, +#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 will compose the Authentication frame header and fixed fields. +* +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] aucPeerMACAddress Given Peer MAC Address. +* @param[in] aucMACAddress Given Our MAC Address. +* @param[in] u2AuthAlgNum Authentication Algorithm Number +* @param[in] u2TransactionSeqNum Transaction Sequence Number +* @param[in] u2StatusCode Status Code +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID +authComposeAuthFrameHeaderAndFF(IN PUINT_8 pucBuffer, + IN UINT_8 aucPeerMACAddress[], + IN UINT_8 aucMACAddress[], + IN UINT_16 u2AuthAlgNum, IN UINT_16 u2TransactionSeqNum, IN UINT_16 u2StatusCode) +{ + P_WLAN_AUTH_FRAME_T prAuthFrame; + UINT_16 u2FrameCtrl; + + ASSERT(pucBuffer); + ASSERT(aucPeerMACAddress); + ASSERT(aucMACAddress); + + prAuthFrame = (P_WLAN_AUTH_FRAME_T) pucBuffer; + + /* 4 <1> Compose the frame header of the Authentication frame. */ + /* Fill the Frame Control field. */ + u2FrameCtrl = MAC_FRAME_AUTH; + + /* If this frame is the third frame in the shared key authentication + * sequence, it shall be encrypted. + */ + if ((u2AuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY) && (u2TransactionSeqNum == AUTH_TRANSACTION_SEQ_3)) + u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; /* HW will also detect this bit for applying encryption */ + /* WLAN_SET_FIELD_16(&prAuthFrame->u2FrameCtrl, u2FrameCtrl); */ + prAuthFrame->u2FrameCtrl = u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the DA field with Target BSSID. */ + COPY_MAC_ADDR(prAuthFrame->aucDestAddr, aucPeerMACAddress); + + /* Fill the SA field with our MAC Address. */ + COPY_MAC_ADDR(prAuthFrame->aucSrcAddr, aucMACAddress); + + switch (u2TransactionSeqNum) { + case AUTH_TRANSACTION_SEQ_1: + case AUTH_TRANSACTION_SEQ_3: + + /* Fill the BSSID field with Target BSSID. */ + COPY_MAC_ADDR(prAuthFrame->aucBSSID, aucPeerMACAddress); + break; + + case AUTH_TRANSACTION_SEQ_2: + case AUTH_TRANSACTION_SEQ_4: + + /* Fill the BSSID field with Current BSSID. */ + COPY_MAC_ADDR(prAuthFrame->aucBSSID, aucMACAddress); + break; + + default: + ASSERT(0); + } + + /* Clear the SEQ/FRAG_NO field. */ + prAuthFrame->u2SeqCtrl = 0; + + /* 4 <2> Compose the frame body's fixed field part of the Authentication frame. */ + /* Fill the Authentication Algorithm Number field. */ + /* WLAN_SET_FIELD_16(&prAuthFrame->u2AuthAlgNum, u2AuthAlgNum); */ + prAuthFrame->u2AuthAlgNum = u2AuthAlgNum; /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the Authentication Transaction Sequence Number field. */ + /* WLAN_SET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, u2TransactionSeqNum); */ + prAuthFrame->u2AuthTransSeqNo = u2TransactionSeqNum; /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the Status Code field. */ + /* WLAN_SET_FIELD_16(&prAuthFrame->u2StatusCode, u2StatusCode); */ + prAuthFrame->u2StatusCode = u2StatusCode; /* NOTE(Kevin): Optimized for ARM */ + +} /* end of authComposeAuthFrameHeaderAndFF() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will append Challenge Text IE to the Authentication frame +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID authAddIEChallengeText(IN P_ADAPTER_T prAdapter, IN OUT P_MSDU_INFO_T prMsduInfo) +{ + P_WLAN_AUTH_FRAME_T prAuthFrame; + P_STA_RECORD_T prStaRec; + UINT_16 u2TransactionSeqNum; + + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (!prStaRec) + return; + + ASSERT(prStaRec); + + /* For Management, frame header and payload are in a continuous buffer */ + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prMsduInfo->prPacket; + + WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, &u2TransactionSeqNum) + + /* Only consider SEQ_3 for Challenge Text */ + if ((u2TransactionSeqNum == AUTH_TRANSACTION_SEQ_3) && + (prStaRec->ucAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY) && (prStaRec->prChallengeText != NULL)) { + + COPY_IE(((ULONG) (prMsduInfo->prPacket) + prMsduInfo->u2FrameLength), (prStaRec->prChallengeText)); + + prMsduInfo->u2FrameLength += IE_SIZE(prStaRec->prChallengeText); + } + + return; + +} /* end of authAddIEChallengeText() */ + +#if !CFG_SUPPORT_AAA +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send the Authenticiation frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] u2TransactionSeqNum Transaction Sequence Number +* +* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. +* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS authSendAuthFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN UINT_16 u2TransactionSeqNum) +{ + P_MSDU_INFO_T prMsduInfo; + P_BSS_INFO_T prBssInfo; + UINT_16 u2EstimatedFrameLen; + UINT_16 u2EstimatedExtraIELen; + UINT_16 u2PayloadLen; + UINT_32 i; + + DBGLOG(SAA, LOUD, "Send Auth Frame\n"); + + ASSERT(prStaRec); + + /* 4 <1> Allocate a PKT_INFO_T for Authentication Frame */ + /* Init with MGMT Header Length + Length of Fixed Fields */ + u2EstimatedFrameLen = (MAC_TX_RESERVED_FIELD + + WLAN_MAC_MGMT_HEADER_LEN + + AUTH_ALGORITHM_NUM_FIELD_LEN + + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + STATUS_CODE_FIELD_LEN); + + /* + Extra IE Length */ + u2EstimatedExtraIELen = 0; + + for (i = 0; i < sizeof(txAuthIETable) / sizeof(APPEND_IE_ENTRY_T); i++) + if (txAuthIETable[i].u2EstimatedIELen != 0) + u2EstimatedExtraIELen += txAuthIETable[i].u2EstimatedIELen; + else + u2EstimatedExtraIELen += txAuthIETable[i].pfnCalculateVariableIELen(prAdapter, + prStaRec->ucNetTypeIndex, prStaRec); + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SAA, WARN, "No PKT_INFO_T for sending Auth Frame.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Authentication Request frame header and fixed fields in MSDU_INfO_T. */ + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + /* Compose Header and some Fixed Fields */ + authComposeAuthFrameHeaderAndFF((PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + prStaRec->aucMacAddr, + prBssInfo->aucOwnMacAddr, + prStaRec->ucAuthAlgNum, u2TransactionSeqNum, STATUS_CODE_RESERVED); + + u2PayloadLen = (AUTH_ALGORITHM_NUM_FIELD_LEN + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + STATUS_CODE_FIELD_LEN); + + /* 4 <3> Update information of MSDU_INFO_T */ + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = saaFsmRunEventTxDone; + prMsduInfo->fgIsBasicRate = TRUE; + + /* 4 <4> Compose IEs in MSDU_INFO_T */ + for (i = 0; i < sizeof(txAuthIETable) / sizeof(APPEND_IE_ENTRY_T); i++) { + if (txAuthIETable[i].pfnAppendIE) + txAuthIETable[i].pfnAppendIE(prAdapter, prMsduInfo); + } + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ + + /* 4 <6> Inform TXM to send this Authentication frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; +} /* end of authSendAuthFrame() */ + +#else + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send the Authenticiation frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] u2TransactionSeqNum Transaction Sequence Number +* +* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. +* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +authSendAuthFrame(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_SW_RFB_T prFalseAuthSwRfb, IN UINT_16 u2TransactionSeqNum, IN UINT_16 u2StatusCode) +{ + PUINT_8 pucReceiveAddr; + PUINT_8 pucTransmitAddr; + P_MSDU_INFO_T prMsduInfo; + P_BSS_INFO_T prBssInfo; + /*get from input parameter */ + /* ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex = NETWORK_TYPE_AIS_INDEX; */ + PFN_TX_DONE_HANDLER pfTxDoneHandler = (PFN_TX_DONE_HANDLER) NULL; + UINT_16 u2EstimatedFrameLen; + UINT_16 u2EstimatedExtraIELen; + UINT_16 u2PayloadLen; + UINT_16 ucAuthAlgNum; + UINT_32 i; + + DBGLOG(SAA, LOUD, "Send Auth Frame %d, Status Code = %d\n", u2TransactionSeqNum, u2StatusCode); + + /* 4 <1> Allocate a PKT_INFO_T for Authentication Frame */ + /* Init with MGMT Header Length + Length of Fixed Fields */ + u2EstimatedFrameLen = (MAC_TX_RESERVED_FIELD + + WLAN_MAC_MGMT_HEADER_LEN + + AUTH_ALGORITHM_NUM_FIELD_LEN + + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + STATUS_CODE_FIELD_LEN); + + /* + Extra IE Length */ + u2EstimatedExtraIELen = 0; + + for (i = 0; i < sizeof(txAuthIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); i++) + if (txAuthIETable[i].u2EstimatedFixedIELen != 0) + u2EstimatedExtraIELen += txAuthIETable[i].u2EstimatedFixedIELen; + else { + /*2016/12/16 add null check before access prStaRec*/ + if (prStaRec) + u2EstimatedExtraIELen += txAuthIETable[i].pfnCalculateVariableIELen(prAdapter, + prStaRec->ucNetTypeIndex, prStaRec); + else + DBGLOG(SAA, WARN, "prStaRec is NULL !\n"); + } + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SAA, WARN, "No PKT_INFO_T for sending Auth Frame.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Authentication Request frame header and fixed fields in MSDU_INfO_T. */ + if (prStaRec) { + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + pucTransmitAddr = prBssInfo->aucOwnMacAddr; + + pucReceiveAddr = prStaRec->aucMacAddr; + + ucAuthAlgNum = prStaRec->ucAuthAlgNum; + + switch (u2TransactionSeqNum) { + case AUTH_TRANSACTION_SEQ_1: + case AUTH_TRANSACTION_SEQ_3: + pfTxDoneHandler = saaFsmRunEventTxDone; + break; + + case AUTH_TRANSACTION_SEQ_2: + case AUTH_TRANSACTION_SEQ_4: + pfTxDoneHandler = aaaFsmRunEventTxDone; + break; + } + + } else { /* For Error Status Code */ + P_WLAN_AUTH_FRAME_T prFalseAuthFrame; + + ASSERT(prFalseAuthSwRfb); + prFalseAuthFrame = (P_WLAN_AUTH_FRAME_T) prFalseAuthSwRfb->pvHeader; + + ASSERT(u2StatusCode != STATUS_CODE_SUCCESSFUL); + + pucTransmitAddr = prFalseAuthFrame->aucDestAddr; + + pucReceiveAddr = prFalseAuthFrame->aucSrcAddr; + + ucAuthAlgNum = prFalseAuthFrame->u2AuthAlgNum; + + u2TransactionSeqNum = (prFalseAuthFrame->u2AuthTransSeqNo + 1); + } + + /* Compose Header and some Fixed Fields */ + authComposeAuthFrameHeaderAndFF((PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + pucReceiveAddr, + pucTransmitAddr, ucAuthAlgNum, u2TransactionSeqNum, u2StatusCode); + + u2PayloadLen = (AUTH_ALGORITHM_NUM_FIELD_LEN + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + STATUS_CODE_FIELD_LEN); + + /* 4 <3> Update information of MSDU_INFO_T */ + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + if (prStaRec) + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + else + prMsduInfo->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; /* false Auth frame */ + prMsduInfo->ucNetworkType = (UINT_8) eNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; + prMsduInfo->fgIsBasicRate = TRUE; + + /* 4 <4> Compose IEs in MSDU_INFO_T */ + for (i = 0; i < sizeof(txAuthIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); i++) { + if (txAuthIETable[i].pfnAppendIE) + txAuthIETable[i].pfnAppendIE(prAdapter, prMsduInfo); + } + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ + + /* 4 <6> Inform TXM to send this Authentication frame. */ + DBGLOG(SAA, INFO, "network: %d Send Auth Frame %d, Status Code = %d seq num %d\n", + eNetTypeIndex, u2TransactionSeqNum, u2StatusCode, prMsduInfo->ucTxSeqNum); + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; +} /* end of authSendAuthFrame() */ + +#endif /* CFG_SUPPORT_AAA */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will strictly check the TX Authentication frame for SAA/AAA event +* handling. +* +* @param[in] prMsduInfo Pointer of MSDU_INFO_T +* @param[in] u2TransactionSeqNum Transaction Sequence Number +* +* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS authCheckTxAuthFrame(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN UINT_16 u2TransactionSeqNum) +{ + P_WLAN_AUTH_FRAME_T prAuthFrame; + P_STA_RECORD_T prStaRec; + UINT_16 u2TxFrameCtrl; + UINT_16 u2TxAuthAlgNum; + UINT_16 u2TxTransactionSeqNum; + + ASSERT(prMsduInfo); + + prAuthFrame = (P_WLAN_AUTH_FRAME_T) (prMsduInfo->prPacket); + ASSERT(prAuthFrame); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + if (!prStaRec) + return WLAN_STATUS_INVALID_PACKET; + /* WLAN_GET_FIELD_16(&prAuthFrame->u2FrameCtrl, &u2TxFrameCtrl) */ + u2TxFrameCtrl = prAuthFrame->u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + u2TxFrameCtrl &= MASK_FRAME_TYPE; + if (u2TxFrameCtrl != MAC_FRAME_AUTH) + return WLAN_STATUS_FAILURE; + /* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthAlgNum, &u2TxAuthAlgNum) */ + u2TxAuthAlgNum = prAuthFrame->u2AuthAlgNum; /* NOTE(Kevin): Optimized for ARM */ + if (u2TxAuthAlgNum != (UINT_16) (prStaRec->ucAuthAlgNum)) + return WLAN_STATUS_FAILURE; + /* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, &u2TxTransactionSeqNum) */ + u2TxTransactionSeqNum = prAuthFrame->u2AuthTransSeqNo; /* NOTE(Kevin): Optimized for ARM */ + if (u2TxTransactionSeqNum != u2TransactionSeqNum) + return WLAN_STATUS_FAILURE; + + return WLAN_STATUS_SUCCESS; + +} /* end of authCheckTxAuthFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will check the incoming Auth Frame's Transaction Sequence +* Number before delivering it to the corresponding SAA or AAA Module. +* +* @param[in] prSwRfb Pointer to the SW_RFB_T structure. +* +* @retval WLAN_STATUS_SUCCESS Always not retain authentication frames +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS authCheckRxAuthFrameTransSeq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_WLAN_AUTH_FRAME_T prAuthFrame; + UINT_16 u2RxTransactionSeqNum; + P_STA_RECORD_T prStaRec; + + 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; + } + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (prStaRec && IS_STA_IN_AIS(prStaRec)) { + if (prStaRec->eAuthAssocState == SAA_STATE_EXTERNAL_AUTH) { + saaFsmRunEventRxAuth(prAdapter, prSwRfb); + 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 */ + + DBGLOG(SAA, LOUD, + "Authentication Packet: Auth Trans Seq No = %d\n", + u2RxTransactionSeqNum); + + switch (u2RxTransactionSeqNum) { + case AUTH_TRANSACTION_SEQ_2: + case AUTH_TRANSACTION_SEQ_4: + if (prStaRec && IS_STA_IN_P2P(prStaRec) && + !IS_AP_STA(prStaRec)) + aaaFsmRunEventRxAuth(prAdapter, prSwRfb); + else + 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); +#if CFG_IGNORE_INVALID_AUTH_TSN + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (!prStaRec) + return WLAN_STATUS_SUCCESS; + switch (prStaRec->eAuthAssocState) { + case SAA_STATE_SEND_AUTH1: + case SAA_STATE_WAIT_AUTH2: + case SAA_STATE_SEND_AUTH3: + case SAA_STATE_WAIT_AUTH4: + saaFsmRunEventRxAuth(prAdapter, prSwRfb); + break; + default: + break; + } +#endif + break; + } + + return WLAN_STATUS_SUCCESS; + +} /* end of authCheckRxAuthFrameTransSeq() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the incoming Authentication Frame and take +* the status code out. +* +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[in] u2TransactionSeqNum Transaction Sequence Number +* @param[out] pu2StatusCode Pointer to store the Status Code from Authentication. +* +* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +authCheckRxAuthFrameStatus(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, IN UINT_16 u2TransactionSeqNum, OUT PUINT_16 pu2StatusCode) +{ + P_STA_RECORD_T prStaRec; + P_WLAN_AUTH_FRAME_T prAuthFrame; + UINT_16 u2RxAuthAlgNum; + UINT_16 u2RxTransactionSeqNum; + /* UINT_16 u2RxStatusCode; // NOTE(Kevin): Optimized for ARM */ + + ASSERT(prSwRfb); + ASSERT(pu2StatusCode); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ASSERT(prStaRec); + + if (!prStaRec) + return WLAN_STATUS_INVALID_PACKET; + /* 4 <1> locate the Authentication Frame. */ + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; + + /* 4 <2> Parse the Fixed Fields of Authentication Frame Body. */ + /* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthAlgNum, &u2RxAuthAlgNum); */ + u2RxAuthAlgNum = prAuthFrame->u2AuthAlgNum; /* NOTE(Kevin): Optimized for ARM */ + if (u2RxAuthAlgNum != (UINT_16) prStaRec->ucAuthAlgNum) { + DBGLOG(SAA, WARN, "Discard Auth frame with auth type = %d, current = %d\n", + u2RxAuthAlgNum, prStaRec->ucAuthAlgNum); + *pu2StatusCode = STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED; + return WLAN_STATUS_SUCCESS; + } + /* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, &u2RxTransactionSeqNum); */ + u2RxTransactionSeqNum = prAuthFrame->u2AuthTransSeqNo; /* NOTE(Kevin): Optimized for ARM */ + if (u2RxTransactionSeqNum != u2TransactionSeqNum) { + DBGLOG(SAA, WARN, "Invalid Auth frame with Transaction Seq No = %d\n", u2RxTransactionSeqNum); +#if !CFG_IGNORE_INVALID_AUTH_TSN + *pu2StatusCode = STATUS_CODE_AUTH_OUT_OF_SEQ; + return WLAN_STATUS_FAILURE; +#endif + } + /* 4 <3> Get the Status code */ + /* WLAN_GET_FIELD_16(&prAuthFrame->u2StatusCode, &u2RxStatusCode); */ + /* *pu2StatusCode = u2RxStatusCode; */ + *pu2StatusCode = prAuthFrame->u2StatusCode; /* NOTE(Kevin): Optimized for ARM */ + + return WLAN_STATUS_SUCCESS; + +} /* end of authCheckRxAuthFrameStatus() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Challenge Text IE from the Authentication frame +* +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[in] prIEHdr Pointer to start address of IE +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID authHandleIEChallengeText(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, P_IE_HDR_T prIEHdr) +{ + P_WLAN_AUTH_FRAME_T prAuthFrame; + P_STA_RECORD_T prStaRec; + UINT_16 u2TransactionSeqNum; + + ASSERT(prSwRfb); + ASSERT(prIEHdr); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ASSERT(prStaRec); + + if (!prStaRec) + return; + + /* For Management, frame header and payload are in a continuous buffer */ + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; + + /* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, &u2TransactionSeqNum) */ + u2TransactionSeqNum = prAuthFrame->u2AuthTransSeqNo; /* NOTE(Kevin): Optimized for ARM */ + + /* Only consider SEQ_2 for Challenge Text */ + if ((u2TransactionSeqNum == AUTH_TRANSACTION_SEQ_2) && + (prStaRec->ucAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY)) { + + /* Free previous allocated TCM memory */ + if (prStaRec->prChallengeText) { + ASSERT(0); + cnmMemFree(prAdapter, prStaRec->prChallengeText); + prStaRec->prChallengeText = (P_IE_CHALLENGE_TEXT_T) NULL; + } + + prStaRec->prChallengeText = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, IE_SIZE(prIEHdr)); + if (prStaRec->prChallengeText == NULL) + return; + + /* Save the Challenge Text from Auth Seq 2 Frame, before sending Auth Seq 3 Frame */ + COPY_IE(prStaRec->prChallengeText, prIEHdr); + } + + return; + +} /* end of authAddIEChallengeText() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will parse and process the incoming Authentication frame. +* +* @param[in] prSwRfb Pointer to SW RFB data structure. +* +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS authProcessRxAuth2_Auth4Frame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_WLAN_AUTH_FRAME_T prAuthFrame; + PUINT_8 pucIEsBuffer; + UINT_16 u2IEsLen; + UINT_16 u2Offset; + UINT_8 ucIEID; + UINT_32 i; + + ASSERT(prSwRfb); + + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; + + pucIEsBuffer = &prAuthFrame->aucInfoElem[0]; + u2IEsLen = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - + (AUTH_ALGORITHM_NUM_FIELD_LEN + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + STATUS_CODE_FIELD_LEN); + + IE_FOR_EACH(pucIEsBuffer, u2IEsLen, u2Offset) { + ucIEID = IE_ID(pucIEsBuffer); + + for (i = 0; i < (sizeof(rxAuthIETable) / sizeof(HANDLE_IE_ENTRY_T)); i++) { + + if (ucIEID == rxAuthIETable[i].ucElemID) + rxAuthIETable[i].pfnHandleIE(prAdapter, prSwRfb, (P_IE_HDR_T) pucIEsBuffer); + } + } + if (prAuthFrame->u2AuthAlgNum == AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION) { + if (prAuthFrame->u2AuthTransSeqNo == AUTH_TRANSACTION_SEQ_4) { + /* todo: check MIC, if mic error, return WLAN_STATUS_FAILURE */ + } else if (prAuthFrame->u2AuthTransSeqNo == AUTH_TRANSACTION_SEQ_2) { + prAdapter->prGlueInfo->rFtEventParam.ies = &prAuthFrame->aucInfoElem[0]; + prAdapter->prGlueInfo->rFtEventParam.ies_len = u2IEsLen; + } + } + + return WLAN_STATUS_SUCCESS; + +} /* end of authProcessRxAuth2_Auth4Frame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the Deauthentication frame +* +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] aucPeerMACAddress Given Peer MAC Address. +* @param[in] aucMACAddress Given Our MAC Address. +* @param[in] u2StatusCode Status Code +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID +authComposeDeauthFrameHeaderAndFF(IN PUINT_8 pucBuffer, + IN UINT_8 aucPeerMACAddress[], + IN UINT_8 aucMACAddress[], IN UINT_8 aucBssid[], IN UINT_16 u2ReasonCode) +{ + P_WLAN_DEAUTH_FRAME_T prDeauthFrame; + UINT_16 u2FrameCtrl; + + ASSERT(pucBuffer); + ASSERT(aucPeerMACAddress); + ASSERT(aucMACAddress); + ASSERT(aucBssid); + + prDeauthFrame = (P_WLAN_DEAUTH_FRAME_T) pucBuffer; + + /* 4 <1> Compose the frame header of the Deauthentication frame. */ + /* Fill the Frame Control field. */ + u2FrameCtrl = MAC_FRAME_DEAUTH; + + /* WLAN_SET_FIELD_16(&prDeauthFrame->u2FrameCtrl, u2FrameCtrl); */ + prDeauthFrame->u2FrameCtrl = u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the DA field with Target BSSID. */ + COPY_MAC_ADDR(prDeauthFrame->aucDestAddr, aucPeerMACAddress); + + /* Fill the SA field with our MAC Address. */ + COPY_MAC_ADDR(prDeauthFrame->aucSrcAddr, aucMACAddress); + + /* Fill the BSSID field with Target BSSID. */ + COPY_MAC_ADDR(prDeauthFrame->aucBSSID, aucBssid); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ + prDeauthFrame->u2SeqCtrl = 0; + + /* 4 <2> Compose the frame body's fixed field part of the Authentication frame. */ + /* Fill the Status Code field. */ + /* WLAN_SET_FIELD_16(&prDeauthFrame->u2ReasonCode, u2ReasonCode); */ + prDeauthFrame->u2ReasonCode = u2ReasonCode; /* NOTE(Kevin): Optimized for ARM */ + +} /* end of authComposeDeauthFrameHeaderAndFF() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send the Deauthenticiation frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] prClassErrSwRfb Pointer to the SW_RFB_T which is Class Error. +* @param[in] u2ReasonCode A reason code to indicate why to leave BSS. +* @param[in] pfTxDoneHandler TX Done call back function +* +* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. +* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module +* @retval WLAN_STATUS_FAILURE Didn't send Deauth frame for various reasons. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +authSendDeauthFrame(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN P_SW_RFB_T prClassErrSwRfb, IN UINT_16 u2ReasonCode, IN PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + P_WLAN_MAC_HEADER_A4_T prWlanMacHeader = NULL; + PUINT_8 pucReceiveAddr; + PUINT_8 pucTransmitAddr; + PUINT_8 pucBssid = NULL; + + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + P_MSDU_INFO_T prMsduInfo; + UINT_16 u2EstimatedFrameLen; + UINT_16 u2RxFrameCtrl; + P_BSS_INFO_T prBssInfo; + + P_DEAUTH_INFO_T prDeauthInfo; + OS_SYSTIME rCurrentTime; + INT_32 i4NewEntryIndex, i; + UINT_8 ucStaRecIdx = STA_REC_INDEX_NOT_FOUND; + +#if CFG_ENABLE_WIFI_DIRECT + UINT_8 aucBMC[] = BC_MAC_ADDR; +#endif + + /* NOTE(Kevin): The best way to reply the Deauth is according to the incoming data + * frame + */ + /* 4 <1> Find the Receiver Address first. */ + if (prClassErrSwRfb) { + BOOLEAN fgIsAbleToSendDeauth = FALSE; + + prWlanMacHeader = (P_WLAN_MAC_HEADER_A4_T) prClassErrSwRfb->pvHeader; + + /* WLAN_GET_FIELD_16(&prWlanMacHeader->u2FrameCtrl, &u2RxFrameCtrl); */ + u2RxFrameCtrl = prWlanMacHeader->u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + + /* TODO(Kevin): Currently we won't send Deauth for IBSS node. How about DLS ? */ + if ((prWlanMacHeader->u2FrameCtrl & MASK_TO_DS_FROM_DS) == 0) + return WLAN_STATUS_FAILURE; + + /* Check if corresponding BSS is able to send Deauth */ + for (i = NETWORK_TYPE_AIS_INDEX; i < NETWORK_TYPE_INDEX_NUM; i++) { + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[i]); + + if (IS_NET_ACTIVE(prAdapter, i) && + (EQUAL_MAC_ADDR(prWlanMacHeader->aucAddr1, prBssInfo->aucOwnMacAddr))) { + { + fgIsAbleToSendDeauth = TRUE; + eNetTypeIndex = (ENUM_NETWORK_TYPE_INDEX_T) i; + break; + } + } + } + + if (!fgIsAbleToSendDeauth) + return WLAN_STATUS_FAILURE; + + pucReceiveAddr = prWlanMacHeader->aucAddr2; + + } else if (prStaRec) { + + pucReceiveAddr = prStaRec->aucMacAddr; + } else { +#if CFG_ENABLE_WIFI_DIRECT + pucReceiveAddr = aucBMC; +#else + return WLAN_STATUS_FAILURE; +#endif + } + + /* 4 <2> Check if already send a Deauth frame in MIN_DEAUTH_INTERVAL_MSEC */ + GET_CURRENT_SYSTIME(&rCurrentTime); + + i4NewEntryIndex = -1; + for (i = 0; i < MAX_DEAUTH_INFO_COUNT; i++) { + prDeauthInfo = &(prAdapter->rWifiVar.arDeauthInfo[i]); + + /* For continuously sending Deauth frame, the minimum interval is + * MIN_DEAUTH_INTERVAL_MSEC. + */ + if (CHECK_FOR_TIMEOUT(rCurrentTime, + prDeauthInfo->rLastSendTime, MSEC_TO_SYSTIME(MIN_DEAUTH_INTERVAL_MSEC))) { + + i4NewEntryIndex = i; + } else if (EQUAL_MAC_ADDR(pucReceiveAddr, prDeauthInfo->aucRxAddr) && (!pfTxDoneHandler)) { + + return WLAN_STATUS_FAILURE; + } + } + + /* 4 <3> Update information. */ + if (i4NewEntryIndex > 0) { + + prDeauthInfo = &(prAdapter->rWifiVar.arDeauthInfo[i4NewEntryIndex]); + + COPY_MAC_ADDR(prDeauthInfo->aucRxAddr, pucReceiveAddr); + prDeauthInfo->rLastSendTime = rCurrentTime; + } else { + /* NOTE(Kevin): for the case of AP mode, we may encounter this case + * if deauth all the associated clients. + */ + DBGLOG(SAA, WARN, "No unused DEAUTH_INFO_T !\n"); + } + + /* 4 <4> Allocate a PKT_INFO_T for Deauthentication Frame */ + /* Init with MGMT Header Length + Length of Fixed Fields + IE Length */ + u2EstimatedFrameLen = (MAC_TX_RESERVED_FIELD + WLAN_MAC_MGMT_HEADER_LEN + REASON_CODE_FIELD_LEN); + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SAA, WARN, "No PKT_INFO_T for sending Deauth Request.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <5> Find the Transmitter Address and BSSID. */ + if (prClassErrSwRfb) { + + /* The TA of Deauth is the A1 of RX frame */ + pucTransmitAddr = prWlanMacHeader->aucAddr1; + + switch (prWlanMacHeader->u2FrameCtrl & MASK_TO_DS_FROM_DS) { + + case MASK_FC_FROM_DS: + /* The BSSID of Deauth is the A2 of RX frame */ + pucBssid = prWlanMacHeader->aucAddr2; + break; + + case MASK_FC_TO_DS: + /* The BSSID of Deauth is the A1 of RX frame */ + pucBssid = prWlanMacHeader->aucAddr1; + break; + + case MASK_TO_DS_FROM_DS: + /* TODO(Kevin): Consider BOW, now we set the BSSID of Deauth + * to the A2 of RX frame for temporary solution. + */ + pucBssid = prWlanMacHeader->aucAddr2; + break; + + /* No Default */ + } + + } else if (prStaRec) { + eNetTypeIndex = prStaRec->ucNetTypeIndex; + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); + + pucTransmitAddr = prBssInfo->aucOwnMacAddr; + + pucBssid = prBssInfo->aucBSSID; + } +#if CFG_ENABLE_WIFI_DIRECT + else { + if (prAdapter->fgIsP2PRegistered) { + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + ucStaRecIdx = STA_REC_INDEX_BMCAST; + + pucTransmitAddr = prBssInfo->aucOwnMacAddr; + + pucBssid = prBssInfo->aucBSSID; + + eNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + } else { + /* 20130122: free packet by samplin */ + cnmMgtPktFree(prAdapter, prMsduInfo); + return WLAN_STATUS_FAILURE; + } + } + +#endif + + /* 4 <6> compose Deauthentication frame header and some fixed fields */ + authComposeDeauthFrameHeaderAndFF((PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + pucReceiveAddr, pucTransmitAddr, pucBssid, u2ReasonCode); + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + /* PMF certification 4.3.3.1, 4.3.3.2 send unprotected deauth reason 6/7 */ + /* if (AP mode & not for PMF reply case) OR (STA PMF) */ + if (((prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) && + (prStaRec->rPmfCfg.fgRxDeauthResp != TRUE)) || + (prBssInfo->ucNetTypeIndex == (UINT_8) NETWORK_TYPE_AIS_INDEX)) { + P_WLAN_DEAUTH_FRAME_T prDeauthFrame; + + prDeauthFrame = + (P_WLAN_DEAUTH_FRAME_T) (PUINT_8) ((ULONG) + (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prDeauthFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + DBGLOG(TX, WARN, "authSendDeauthFrame with protection\n"); + } + } +#endif + + /* 4 <7> Update information of MSDU_INFO_T */ + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfo->ucStaRecIndex = ((prStaRec == NULL) ? ucStaRecIdx : prStaRec->ucIndex); + prMsduInfo->ucNetworkType = (UINT_8) eNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + REASON_CODE_FIELD_LEN; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; + prMsduInfo->fgIsBasicRate = TRUE; + DBGLOG(SAA, INFO, "Sending Deauth, network: %d, seqNo %d, reason: %d\n", + eNetTypeIndex, prMsduInfo->ucTxSeqNum, u2ReasonCode); + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + /* caution: access prStaRec only if true */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + /* 4.3.3.1 send unprotected deauth reason 6/7 */ + if (prStaRec->rPmfCfg.fgRxDeauthResp != TRUE) { + DBGLOG(RSN, INFO, "Deauth Set MSDU_OPT_PROTECTED_FRAME\n"); + nicTxConfigPktOption(prMsduInfo, + MSDU_OPT_PROTECTED_FRAME, TRUE); + } + prStaRec->rPmfCfg.fgRxDeauthResp = FALSE; + } +#endif + + /* 4 <8> Inform TXM to send this Deauthentication frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; +} /* end of authSendDeauthFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will parse and process the incoming Deauthentication frame +* if the given BSSID is matched. +* +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[in] aucBSSID Given BSSID +* @param[out] pu2ReasonCode Pointer to store the Reason Code from Deauthentication. +* +* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS authProcessRxDeauthFrame(IN P_SW_RFB_T prSwRfb, IN UINT_8 aucBSSID[], OUT PUINT_16 pu2ReasonCode) +{ + P_WLAN_DEAUTH_FRAME_T prDeauthFrame; + UINT_16 u2RxReasonCode; + + ASSERT(prSwRfb); + ASSERT(aucBSSID); + ASSERT(pu2ReasonCode); + + /* 4 <1> locate the Deauthentication Frame. */ + prDeauthFrame = (P_WLAN_DEAUTH_FRAME_T) prSwRfb->pvHeader; + + /* 4 <2> Parse the Header of Deauthentication Frame. */ +#if 0 /* Kevin: Seems redundant */ + WLAN_GET_FIELD_16(&prDeauthFrame->u2FrameCtrl, &u2RxFrameCtrl) + u2RxFrameCtrl &= MASK_FRAME_TYPE; + if (u2RxFrameCtrl != MAC_FRAME_DEAUTH) + return WLAN_STATUS_FAILURE; +#endif + + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < REASON_CODE_FIELD_LEN) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + /* Check if this Deauth Frame is coming from Target BSSID */ + if (UNEQUAL_MAC_ADDR(prDeauthFrame->aucBSSID, aucBSSID)) { + DBGLOG(SAA, LOUD, "Ignore Deauth Frame from other BSS [ %pM ]\n", + prDeauthFrame->aucSrcAddr); + return WLAN_STATUS_FAILURE; + } + /* 4 <3> Parse the Fixed Fields of Deauthentication Frame Body. */ + WLAN_GET_FIELD_16(&prDeauthFrame->u2ReasonCode, &u2RxReasonCode); + *pu2ReasonCode = u2RxReasonCode; + + return WLAN_STATUS_SUCCESS; + +} /* end of authProcessRxDeauthFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will parse and process the incoming Authentication frame. +* +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[in] aucExpectedBSSID Given Expected BSSID. +* @param[in] u2ExpectedAuthAlgNum Given Expected Authentication Algorithm Number +* @param[in] u2ExpectedTransSeqNum Given Expected Transaction Sequence Number. +* @param[out] pu2ReturnStatusCode Return Status Code. +* +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +* @retval WLAN_STATUS_FAILURE The frame we will ignore. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +authProcessRxAuth1Frame(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN UINT_8 aucExpectedBSSID[], + IN UINT_16 u2ExpectedAuthAlgNum, + IN UINT_16 u2ExpectedTransSeqNum, OUT PUINT_16 pu2ReturnStatusCode) +{ + P_WLAN_AUTH_FRAME_T prAuthFrame; + UINT_16 u2ReturnStatusCode = STATUS_CODE_SUCCESSFUL; + + ASSERT(prSwRfb); + ASSERT(aucExpectedBSSID); + ASSERT(pu2ReturnStatusCode); + + /* 4 <1> locate the Authentication Frame. */ + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; + + /* 4 <2> Check the BSSID */ + if (UNEQUAL_MAC_ADDR(prAuthFrame->aucBSSID, aucExpectedBSSID)) + return WLAN_STATUS_FAILURE; /* Just Ignore this MMPDU */ + /* 4 <3> Check the SA, which should not be MC/BC */ + if (prAuthFrame->aucSrcAddr[0] & BIT(0)) { + DBGLOG(P2P, WARN, "Invalid STA MAC with MC/BC bit set: %pM\n", + prAuthFrame->aucSrcAddr); + return WLAN_STATUS_FAILURE; + } + /* 4 <4> Parse the Fixed Fields of Authentication Frame Body. */ + if (prAuthFrame->u2AuthAlgNum != u2ExpectedAuthAlgNum) + u2ReturnStatusCode = STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED; + + if (prAuthFrame->u2AuthTransSeqNo != u2ExpectedTransSeqNum) + u2ReturnStatusCode = STATUS_CODE_AUTH_OUT_OF_SEQ; + + *pu2ReturnStatusCode = u2ReturnStatusCode; + + return WLAN_STATUS_SUCCESS; + +} /* end of authProcessRxAuth1Frame() */ + +WLAN_STATUS +authProcessRxAuthFrame(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN P_BSS_INFO_T prBssInfo, + OUT PUINT_16 pu2ReturnStatusCode) +{ + P_WLAN_AUTH_FRAME_T prAuthFrame; + UINT_16 u2ReturnStatusCode = STATUS_CODE_SUCCESSFUL; + + ASSERT(prSwRfb); + ASSERT(pu2ReturnStatusCode); + + if (!prBssInfo) + return WLAN_STATUS_FAILURE; + + /* 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, prBssInfo->aucBSSID)) + return WLAN_STATUS_FAILURE; /* Just Ignore this MMPDU */ + /* 4 <3> Check the SA, which should not be MC/BC */ + if (prAuthFrame->aucSrcAddr[0] & BIT(0)) { + DBGLOG(P2P, WARN, "Invalid STA MAC with MC/BC bit set: %pM\n", + prAuthFrame->aucSrcAddr); + return WLAN_STATUS_FAILURE; + } + /* 4 <4> Parse the Fixed Fields of Authentication Frame Body. */ + if (prAuthFrame->u2AuthAlgNum != AUTH_ALGORITHM_NUM_OPEN_SYSTEM && + prAuthFrame->u2AuthAlgNum != AUTH_ALGORITHM_NUM_SAE) + u2ReturnStatusCode = STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED; + else if (prAuthFrame->u2AuthAlgNum == AUTH_ALGORITHM_NUM_OPEN_SYSTEM && + prAuthFrame->u2AuthTransSeqNo != AUTH_TRANSACTION_SEQ_1) + u2ReturnStatusCode = STATUS_CODE_AUTH_OUT_OF_SEQ; + else if (prAuthFrame->u2AuthAlgNum == AUTH_ALGORITHM_NUM_SAE && + prAuthFrame->u2AuthTransSeqNo != AUTH_TRANSACTION_SEQ_1 && + prAuthFrame->u2AuthTransSeqNo != AUTH_TRANSACTION_SEQ_2) + u2ReturnStatusCode = STATUS_CODE_AUTH_OUT_OF_SEQ; + + DBGLOG(AAA, LOUD, "u2ReturnStatusCode = %d\n", u2ReturnStatusCode); + + *pu2ReturnStatusCode = u2ReturnStatusCode; + + return WLAN_STATUS_SUCCESS; + +} /* end of authProcessRxAuth1Frame() */ + +/* ToDo: authAddRicIE, authHandleFtIEs, authAddTimeoutIE */ + +VOID authAddMDIE(IN P_ADAPTER_T prAdapter, IN OUT P_MSDU_INFO_T prMsduInfo) +{ + struct FT_IES *prFtIEs = &prAdapter->prGlueInfo->rFtIeForTx; + PUINT_8 pucBuffer = (PUINT_8)prMsduInfo->prPacket + prMsduInfo->u2FrameLength; + UINT_8 ucBssIdx = prMsduInfo->ucNetworkType; + + if (!IS_BSS_INDEX_VALID(ucBssIdx) || + !IS_BSS_AIS(GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx)) || !prFtIEs->prMDIE) + return; + prMsduInfo->u2FrameLength += 5; /* IE size for MD IE is fixed, it is 5 */ + kalMemCopy(pucBuffer, prFtIEs->prMDIE, 5); +} + +UINT_32 authCalculateRSNIELen(P_ADAPTER_T prAdapter, + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, P_STA_RECORD_T prStaRec) +{ + ENUM_PARAM_AUTH_MODE_T eAuthMode = prAdapter->rWifiVar.rConnSettings.eAuthMode; + struct FT_IES *prFtIEs = &prAdapter->prGlueInfo->rFtIeForTx; + + if (!IS_BSS_INDEX_VALID(eNetTypeIndex) || !IS_BSS_AIS(GET_BSS_INFO_BY_INDEX(prAdapter, eNetTypeIndex)) || + !prFtIEs->prRsnIE || (eAuthMode != AUTH_MODE_WPA2_FT && eAuthMode != AUTH_MODE_WPA2_FT_PSK)) + return 0; + return IE_SIZE(prFtIEs->prRsnIE); +} + +VOID authAddRSNIE(IN P_ADAPTER_T prAdapter, IN OUT P_MSDU_INFO_T prMsduInfo) +{ + ENUM_PARAM_AUTH_MODE_T eAuthMode = prAdapter->rWifiVar.rConnSettings.eAuthMode; + struct FT_IES *prFtIEs = &prAdapter->prGlueInfo->rFtIeForTx; + PUINT_8 pucBuffer = (PUINT_8)prMsduInfo->prPacket + prMsduInfo->u2FrameLength; + UINT_32 ucRSNIeSize = 0; + UINT_8 ucBssIdx = prMsduInfo->ucNetworkType; + + if (!IS_BSS_INDEX_VALID(ucBssIdx) || !IS_BSS_AIS(GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx)) || + !prFtIEs->prRsnIE || (eAuthMode != AUTH_MODE_WPA2_FT && eAuthMode != AUTH_MODE_WPA2_FT_PSK)) + return; + ucRSNIeSize = IE_SIZE(prFtIEs->prRsnIE); + prMsduInfo->u2FrameLength += ucRSNIeSize; + kalMemCopy(pucBuffer, prFtIEs->prRsnIE, ucRSNIeSize); +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/bss.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/bss.c new file mode 100644 index 0000000000000..763186fe98028 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/bss.c @@ -0,0 +1,2089 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +#if (CFG_SUPPORT_ADHOC) || (CFG_SUPPORT_AAA) +APPEND_VAR_IE_ENTRY_T txBcnIETable[] = { + {(ELEM_HDR_LEN + (RATE_NUM - ELEM_MAX_LEN_SUP_RATES)), NULL, bssGenerateExtSuppRate_IE}, /* 50 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_ERP), NULL, rlmRspGenerateErpIE}, /* 42 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP), NULL, rlmRspGenerateHtCapIE}, /* 45 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_HT_OP), NULL, rlmRspGenerateHtOpIE}, /* 61 */ +#if CFG_ENABLE_WIFI_DIRECT + {(ELEM_HDR_LEN + ELEM_MAX_LEN_OBSS_SCAN), NULL, rlmRspGenerateObssScanIE}, /* 74 */ +#endif + {(ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP), NULL, rlmRspGenerateExtCapIE}, /* 127 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_WPA), NULL, rsnGenerateWpaNoneIE}, /* 221 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_PARAM), NULL, mqmGenerateWmmParamIE}, /* 221 */ +#if CFG_ENABLE_WIFI_DIRECT + {(ELEM_HDR_LEN + ELEM_MAX_LEN_WPA), NULL, rsnGenerateWPAIE}, /* 221 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_RSN), NULL, rsnGenerateRSNIE}, /* 48 */ +#if 0 /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */ + {0, p2pFuncCalculateExtra_IELenForBeacon, p2pFuncGenerateExtra_IEForBeacon}, /* 221 */ +#else + {0, p2pFuncCalculateP2p_IELenForBeacon, p2pFuncGenerateP2p_IEForBeacon}, /* 221 */ + {0, p2pFuncCalculateWSC_IELenForBeacon, p2pFuncGenerateWSC_IEForBeacon}, /* 221 */ + {0, p2pFuncCalculateP2P_IE_NoA, p2pFuncGenerateP2P_IE_NoA}, /* 221 */ +#endif +#endif /* CFG_ENABLE_WIFI_DIRECT */ +#if CFG_SUPPORT_MTK_SYNERGY + {(ELEM_HDR_LEN + ELEM_MIN_LEN_MTK_OUI), NULL, rlmGenerateMTKOuiIE} /* 221 */ +#endif + +}; + +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 */ +#if CFG_SUPPORT_MTK_SYNERGY + {(ELEM_HDR_LEN + ELEM_MIN_LEN_MTK_OUI), NULL, rlmGenerateMTKOuiIE} /* 221 */ +#endif + +}; + +#endif /* CFG_SUPPORT_ADHOC || CFG_SUPPORT_AAA */ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Routines for all Operation Modes */ +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will create or reset a STA_RECORD_T by given BSS_DESC_T for +* Infrastructure or AdHoc Mode. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] eStaType Assign STA Type for this STA_RECORD_T +* @param[in] eNetTypeIndex Assign Net Type Index for this STA_RECORD_T +* @param[in] prBssDesc Received Beacon/ProbeResp from this STA +* +* @retval Pointer to STA_RECORD_T +*/ +/*----------------------------------------------------------------------------*/ +P_STA_RECORD_T +bssCreateStaRecFromBssDesc(IN P_ADAPTER_T prAdapter, + IN ENUM_STA_TYPE_T eStaType, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_BSS_DESC_T prBssDesc) +{ + P_STA_RECORD_T prStaRec; + UINT_8 ucNonHTPhyTypeSet; + + ASSERT(prBssDesc); + + /* 4 <1> Get a valid STA_RECORD_T */ + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) eNetTypeIndex, prBssDesc->aucSrcAddr); + if (!prStaRec) { + + prStaRec = cnmStaRecAlloc(prAdapter, (UINT_8) eNetTypeIndex); + + /* TODO(Kevin): Error handling of allocation of STA_RECORD_T for + * exhausted case and do removal of unused STA_RECORD_T. + */ + + if (!prStaRec) { + ASSERT(FALSE); + return NULL; + } + + ASSERT(prStaRec); + + prStaRec->ucStaState = STA_STATE_1; + prStaRec->ucJoinFailureCount = 0; + /* TODO(Kevin): If this is an old entry, we may also reset the ucJoinFailureCount to 0. + */ + + COPY_MAC_ADDR(prStaRec->aucMacAddr, prBssDesc->aucSrcAddr); + } + /* 4 <2> Setup STA TYPE and NETWORK */ + prStaRec->eStaType = eStaType; + + prStaRec->ucNetTypeIndex = eNetTypeIndex; + + /* 4 <3> Update information from BSS_DESC_T to current P_STA_RECORD_T */ + prStaRec->u2CapInfo = prBssDesc->u2CapInfo; + + prStaRec->u2OperationalRateSet = prBssDesc->u2OperationalRateSet; + prStaRec->u2BSSBasicRateSet = prBssDesc->u2BSSBasicRateSet; + + prStaRec->ucPhyTypeSet = prBssDesc->ucPhyTypeSet; + + prStaRec->ucRCPI = prBssDesc->ucRCPI; + if (IS_STA_IN_AIS(prStaRec)) { + if (!((prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION3_ENABLED) || + (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION3_KEY_ABSENT) || + (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION_DISABLED))) { + DBGLOG(BSS, TRACE, "Ignore the HT Bit for TKIP as pairwise cipher configured!\n"); + prStaRec->ucPhyTypeSet &= ~PHY_TYPE_BIT_HT; + } + } else { + DBGLOG(BSS, TRACE, "P2P skip TKIP limitation for HT Hit!\n"); + } + prStaRec->ucDesiredPhyTypeSet = prStaRec->ucPhyTypeSet & prAdapter->rWifiVar.ucAvailablePhyTypeSet; + + ucNonHTPhyTypeSet = prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11ABG; + + /* Check for Target BSS's non HT Phy Types */ + if (ucNonHTPhyTypeSet) { + + if (ucNonHTPhyTypeSet & PHY_TYPE_BIT_ERP) { + prStaRec->ucNonHTBasicPhyType = PHY_TYPE_ERP_INDEX; + } else if (ucNonHTPhyTypeSet & PHY_TYPE_BIT_OFDM) { + prStaRec->ucNonHTBasicPhyType = PHY_TYPE_OFDM_INDEX; + } else { /* if (ucNonHTPhyTypeSet & PHY_TYPE_HR_DSSS_INDEX) */ + + prStaRec->ucNonHTBasicPhyType = PHY_TYPE_HR_DSSS_INDEX; + } + + prStaRec->fgHasBasicPhyType = TRUE; + } else { + /* Use mandatory for 11N only BSS */ + ASSERT(prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N); + + { + /* TODO(Kevin): which value should we set for 11n ? ERP ? */ + prStaRec->ucNonHTBasicPhyType = PHY_TYPE_HR_DSSS_INDEX; + } + + prStaRec->fgHasBasicPhyType = FALSE; + } + + /* Update non HT Desired Rate Set */ + { + P_CONNECTION_SETTINGS_T prConnSettings; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + prStaRec->u2DesiredNonHTRateSet = + (prStaRec->u2OperationalRateSet & prConnSettings->u2DesiredNonHTRateSet); + } + + /* 4 <4> Update information from BSS_DESC_T to current P_STA_RECORD_T */ + if (IS_AP_STA(prStaRec)) { + /* do not need to parse IE for DTIM, + * which have been parsed before inserting into BSS_DESC_T + */ + if (prBssDesc->ucDTIMPeriod) + prStaRec->ucDTIMPeriod = prBssDesc->ucDTIMPeriod; + else + prStaRec->ucDTIMPeriod = 0; /* Means that TIM was not parsed. */ + } + /* 4 <5> Update default value */ + prStaRec->fgDiagnoseConnection = FALSE; + + /* 4 <6> Update default value for other Modules */ + /* Determine fgIsWmmSupported and fgIsUapsdSupported in STA_REC */ + mqmProcessScanResult(prAdapter, prBssDesc, prStaRec); + + return prStaRec; + +} /* end of bssCreateStaRecFromBssDesc() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the Null Data frame. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] prStaRec Pointer to the STA_RECORD_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bssComposeNullFrame(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuffer, IN P_STA_RECORD_T prStaRec) +{ + P_WLAN_MAC_HEADER_T prNullFrame; + P_BSS_INFO_T prBssInfo; + UINT_16 u2FrameCtrl; + + ASSERT(pucBuffer); + ASSERT(prStaRec); + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + ASSERT(prBssInfo); + + prNullFrame = (P_WLAN_MAC_HEADER_T) pucBuffer; + + /* 4 <1> Decide the Frame Control Field */ + u2FrameCtrl = MAC_FRAME_NULL; + + if (IS_AP_STA(prStaRec)) { + u2FrameCtrl |= MASK_FC_TO_DS; + + if (prStaRec->fgSetPwrMgtBit) + u2FrameCtrl |= MASK_FC_PWR_MGT; + } else if (IS_CLIENT_STA(prStaRec)) { + u2FrameCtrl |= MASK_FC_FROM_DS; + } else if (IS_DLS_STA(prStaRec)) { + /* TODO(Kevin) */ + } else { + /* NOTE(Kevin): We won't send Null frame for IBSS */ + ASSERT(0); + return; + } + + /* 4 <2> Compose the Null frame */ + /* Fill the Frame Control field. */ + /* WLAN_SET_FIELD_16(&prNullFrame->u2FrameCtrl, u2FrameCtrl); */ + prNullFrame->u2FrameCtrl = u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the Address 1 field with Target Peer Address. */ + COPY_MAC_ADDR(prNullFrame->aucAddr1, prStaRec->aucMacAddr); + + /* Fill the Address 2 field with our MAC Address. */ + COPY_MAC_ADDR(prNullFrame->aucAddr2, prBssInfo->aucOwnMacAddr); + + /* Fill the Address 3 field with Target BSSID. */ + COPY_MAC_ADDR(prNullFrame->aucAddr3, prBssInfo->aucBSSID); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ + prNullFrame->u2SeqCtrl = 0; + + return; + +} /* end of bssComposeNullFrameHeader() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the QoS Null Data frame. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] prStaRec Pointer to the STA_RECORD_T. +* @param[in] ucUP User Priority. +* @param[in] fgSetEOSP Set the EOSP bit. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bssComposeQoSNullFrame(IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBuffer, IN P_STA_RECORD_T prStaRec, IN UINT_8 ucUP, IN BOOLEAN fgSetEOSP) +{ + P_WLAN_MAC_HEADER_QOS_T prQoSNullFrame; + P_BSS_INFO_T prBssInfo; + UINT_16 u2FrameCtrl; + UINT_16 u2QosControl; + + ASSERT(pucBuffer); + ASSERT(prStaRec); + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + ASSERT(prBssInfo); + + prQoSNullFrame = (P_WLAN_MAC_HEADER_QOS_T) pucBuffer; + + /* 4 <1> Decide the Frame Control Field */ + u2FrameCtrl = MAC_FRAME_QOS_NULL; + + if (IS_AP_STA(prStaRec)) { + u2FrameCtrl |= MASK_FC_TO_DS; + + if (prStaRec->fgSetPwrMgtBit) + u2FrameCtrl |= MASK_FC_PWR_MGT; + } else if (IS_CLIENT_STA(prStaRec)) { + u2FrameCtrl |= MASK_FC_FROM_DS; + } else if (IS_DLS_STA(prStaRec)) { + /* TODO(Kevin) */ + } else { + /* NOTE(Kevin): We won't send QoS Null frame for IBSS */ + ASSERT(0); + return; + } + + /* 4 <2> Compose the QoS Null frame */ + /* Fill the Frame Control field. */ + /* WLAN_SET_FIELD_16(&prQoSNullFrame->u2FrameCtrl, u2FrameCtrl); */ + prQoSNullFrame->u2FrameCtrl = u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the Address 1 field with Target Peer Address. */ + COPY_MAC_ADDR(prQoSNullFrame->aucAddr1, prStaRec->aucMacAddr); + + /* Fill the Address 2 field with our MAC Address. */ + COPY_MAC_ADDR(prQoSNullFrame->aucAddr2, prBssInfo->aucOwnMacAddr); + + /* Fill the Address 3 field with Target BSSID. */ + COPY_MAC_ADDR(prQoSNullFrame->aucAddr3, prBssInfo->aucBSSID); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ + prQoSNullFrame->u2SeqCtrl = 0; + + u2QosControl = (UINT_16) (ucUP & WMM_QC_UP_MASK); + + if (fgSetEOSP) + u2QosControl |= WMM_QC_EOSP; + /* WLAN_SET_FIELD_16(&prQoSNullFrame->u2QosCtrl, u2QosControl); */ + prQoSNullFrame->u2QosCtrl = u2QosControl; /* NOTE(Kevin): Optimized for ARM */ + + return; + +} /* end of bssComposeQoSNullFrameHeader() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Send the Null Frame +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] pfTxDoneHandler TX Done call back function +* +* @retval WLAN_STATUS_RESOURCE No available resources to send frame. +* @retval WLAN_STATUS_SUCCESS Succe]ss. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +bssSendNullFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + P_MSDU_INFO_T prMsduInfo; + UINT_16 u2EstimatedFrameLen; + + /* 4 <1> Allocate a PKT_INFO_T for Null Frame */ + /* Init with MGMT Header Length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + WLAN_MAC_HEADER_LEN; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(BSS, WARN, "No PKT_INFO_T for sending Null Frame.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Null frame in MSDU_INfO_T. */ + bssComposeNullFrame(prAdapter, (PUINT_8) ((ULONG) prMsduInfo->prPacket + MAC_TX_RESERVED_FIELD), prStaRec); +#if 0 + /* 4 <3> Update information of MSDU_INFO_T */ + TXM_SET_DATA_PACKET( + /* STA_REC ptr */ prStaRec, + /* MSDU_INFO ptr */ prMsduInfo, + /* MAC HDR ptr */ (prMsduInfo->pucBuffer + MAC_TX_RESERVED_FIELD), + /* MAC HDR length */ WLAN_MAC_HEADER_LEN, + /* PAYLOAD ptr */ + (prMsduInfo->pucBuffer + MAC_TX_RESERVED_FIELD + WLAN_MAC_HEADER_LEN), + /* PAYLOAD length */ 0, + /* Network Type Index */ (UINT_8) prStaRec->ucNetTypeIndex, + /* TID */ 0 /* BE: AC1 */, + /* Flag 802.11 */ TRUE, + /* Pkt arrival time */ 0 /* TODO: Obtain the system time */, + /* Resource TC */ 0 /* Irrelevant */, + /* Flag 802.1x */ FALSE, + /* TX-done callback */ pfTxDoneHandler, + /* PS forwarding type */ PS_FORWARDING_TYPE_NON_PS, + /* PS Session ID */ 0 /* Irrelevant */, + /* Flag fixed rate */ TRUE, + /* Fixed tx rate */ g_aprBssInfo[prStaRec->ucNetTypeIndex]->ucHwDefaultFixedRateCode, + /* Fixed-rate retry */ BSS_DEFAULT_CONN_TEST_NULL_FRAME_RETRY_LIMIT, + /* PAL LLH */ 0 /* Irrelevant */, + /* ACL SN */ 0 /* Irrelevant */, + /* Flag No Ack */ FALSE + ); + + /* Terminate with a NULL pointer */ + NIC_HIF_TX_SET_NEXT_MSDU_INFO(prMsduInfo, NULL); + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ + + /* Indicate the packet to TXM */ + /* 4 <4> Inform TXM to send this Null frame. */ + txmSendFwDataPackets(prMsduInfo); +#endif + + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_DATA; + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_HEADER_LEN; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; + prMsduInfo->fgIsBasicRate = FALSE; + + /* 4 <4> Inform TXM to send this Null frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; + +} /* end of bssSendNullFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Send the QoS Null Frame +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] pfTxDoneHandler TX Done call back function +* +* @retval WLAN_STATUS_RESOURCE No available resources to send frame. +* @retval WLAN_STATUS_SUCCESS Success. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +bssSendQoSNullFrame(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, IN UINT_8 ucUP, IN PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + P_MSDU_INFO_T prMsduInfo; + UINT_16 u2EstimatedFrameLen; + + /* 4 <1> Allocate a PKT_INFO_T for Null Frame */ + /* Init with MGMT Header Length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + WLAN_MAC_HEADER_QOS_LEN; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(BSS, WARN, "No PKT_INFO_T for sending Null Frame.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Null frame in MSDU_INfO_T. */ + bssComposeQoSNullFrame(prAdapter, + (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + prStaRec, ucUP, FALSE); +#if 0 + /* 4 <3> Update information of MSDU_INFO_T */ + TXM_SET_DATA_PACKET( + /* STA_REC ptr */ prStaRec, + /* MSDU_INFO ptr */ prMsduInfo, + /* MAC HDR ptr */ (prMsduInfo->pucBuffer + MAC_TX_RESERVED_FIELD), + /* MAC HDR length */ WLAN_MAC_HEADER_QOS_LEN, + /* PAYLOAD ptr */ + (prMsduInfo->pucBuffer + MAC_TX_RESERVED_FIELD + WLAN_MAC_HEADER_QOS_LEN), + /* PAYLOAD length */ 0, + /* Network Type Index */ (UINT_8) prStaRec->ucNetTypeIndex, + /* TID */ 0 /* BE: AC1 */, + /* Flag 802.11 */ TRUE, + /* Pkt arrival time */ 0 /* TODO: Obtain the system time */, + /* Resource TC */ 0 /* Irrelevant */, + /* Flag 802.1x */ FALSE, + /* TX-done callback */ pfTxDoneHandler, + /* PS forwarding type */ PS_FORWARDING_TYPE_NON_PS, + /* PS Session ID */ 0 /* Irrelevant */, + /* Flag fixed rate */ TRUE, + /* Fixed tx rate */ g_aprBssInfo[prStaRec->ucNetTypeIndex]->ucHwDefaultFixedRateCode, + /* Fixed-rate retry */ TXM_DEFAULT_DATA_FRAME_RETRY_LIMIT, + /* PAL LLH */ 0 /* Irrelevant */, + /* ACL SN */ 0 /* Irrelevant */, + /* Flag No Ack */ FALSE + ); + + /* Terminate with a NULL pointer */ + NIC_HIF_TX_SET_NEXT_MSDU_INFO(prMsduInfo, NULL); + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ + + /* Indicate the packet to TXM */ + /* 4 <4> Inform TXM to send this Null frame. */ + txmSendFwDataPackets(prMsduInfo); +#endif + + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_HEADER_QOS_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_HEADER_QOS_LEN; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; + prMsduInfo->fgIsBasicRate = TRUE; + + /* 4 <4> Inform TXM to send this Null frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; + +} /* end of bssSendQoSNullFrame() */ + +#if (CFG_SUPPORT_ADHOC) || (CFG_SUPPORT_AAA) +/*----------------------------------------------------------------------------*/ +/* Routines for both IBSS(AdHoc) and BSS(AP) */ +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to generate Information Elements of Extended +* Support Rate +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bssGenerateExtSuppRate_IE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_BSS_INFO_T prBssInfo; + PUINT_8 pucBuffer; + UINT_8 ucExtSupRatesLen; + + ASSERT(prMsduInfo); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]); + ASSERT(prBssInfo); + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + ASSERT(pucBuffer); + + if (prBssInfo->ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) + ucExtSupRatesLen = prBssInfo->ucAllSupportedRatesLen - ELEM_MAX_LEN_SUP_RATES; + else + ucExtSupRatesLen = 0; + + /* Fill the Extended Supported Rates element. */ + if (ucExtSupRatesLen) { + + EXT_SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_EXTENDED_SUP_RATES; + EXT_SUP_RATES_IE(pucBuffer)->ucLength = ucExtSupRatesLen; + + kalMemCopy(EXT_SUP_RATES_IE(pucBuffer)->aucExtSupportedRates, + &prBssInfo->aucAllSupportedRates[ELEM_MAX_LEN_SUP_RATES], ucExtSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + } + +} /* end of bssGenerateExtSuppRate_IE() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to compose Common Information Elements for Beacon +* or Probe Response Frame. +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* @param[in] prBssInfo Pointer to the BSS_INFO_T. +* @param[in] pucDestAddr Pointer to the Destination Address, if NULL, means Beacon. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bssBuildBeaconProbeRespFrameCommonIEs(IN P_MSDU_INFO_T prMsduInfo, IN P_BSS_INFO_T prBssInfo, IN PUINT_8 pucDestAddr) +{ + PUINT_8 pucBuffer; + UINT_8 ucSupRatesLen; + + ASSERT(prMsduInfo); + ASSERT(prBssInfo); + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + ASSERT(pucBuffer); + + /* 4 <1> Fill the SSID element. */ + SSID_IE(pucBuffer)->ucId = ELEM_ID_SSID; + if ((!pucDestAddr) && (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { + /* For Beacon */ + if (prBssInfo->eHiddenSsidType == ENUM_HIDDEN_SSID_ZERO_CONTENT) { + /* clear the data, but keep the correct length of the SSID */ + SSID_IE(pucBuffer)->ucLength = prBssInfo->ucSSIDLen; + kalMemZero(SSID_IE(pucBuffer)->aucSSID, prBssInfo->ucSSIDLen); + } else if (prBssInfo->eHiddenSsidType == ENUM_HIDDEN_SSID_ZERO_LEN) { + /* empty SSID */ + SSID_IE(pucBuffer)->ucLength = 0; + } else { + SSID_IE(pucBuffer)->ucLength = prBssInfo->ucSSIDLen; + if (prBssInfo->ucSSIDLen) + kalMemCopy(SSID_IE(pucBuffer)->aucSSID, prBssInfo->aucSSID, prBssInfo->ucSSIDLen); + } + } else { /* Probe response */ + SSID_IE(pucBuffer)->ucLength = prBssInfo->ucSSIDLen; + if (prBssInfo->ucSSIDLen) + kalMemCopy(SSID_IE(pucBuffer)->aucSSID, prBssInfo->aucSSID, prBssInfo->ucSSIDLen); + } + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + + /* 4 <2> Fill the Supported Rates element. */ + if (prBssInfo->ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) + ucSupRatesLen = ELEM_MAX_LEN_SUP_RATES; + else + ucSupRatesLen = prBssInfo->ucAllSupportedRatesLen; + + if (ucSupRatesLen) { + SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_SUP_RATES; + SUP_RATES_IE(pucBuffer)->ucLength = ucSupRatesLen; + kalMemCopy(SUP_RATES_IE(pucBuffer)->aucSupportedRates, prBssInfo->aucAllSupportedRates, ucSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } + /* 4 <3> Fill the DS Parameter Set element. */ + if (prBssInfo->eBand == BAND_2G4) { + DS_PARAM_IE(pucBuffer)->ucId = ELEM_ID_DS_PARAM_SET; + DS_PARAM_IE(pucBuffer)->ucLength = ELEM_MAX_LEN_DS_PARAMETER_SET; + DS_PARAM_IE(pucBuffer)->ucCurrChnl = prBssInfo->ucPrimaryChannel; + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } + /* 4 <4> IBSS Parameter Set element, ID: 6 */ + if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + IBSS_PARAM_IE(pucBuffer)->ucId = ELEM_ID_IBSS_PARAM_SET; + IBSS_PARAM_IE(pucBuffer)->ucLength = ELEM_MAX_LEN_IBSS_PARAMETER_SET; + WLAN_SET_FIELD_16(&(IBSS_PARAM_IE(pucBuffer)->u2ATIMWindow), prBssInfo->u2ATIMWindow); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } + /* 4 <5> TIM element, ID: 5 */ + if ((!pucDestAddr) && /* For Beacon only. */ + (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { + +#if CFG_ENABLE_WIFI_DIRECT + /*no fgIsP2PRegistered protect */ + if (prBssInfo->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { +#if 0 + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo; + UINT_8 ucBitmapControl = 0; + UINT_32 u4N1, u4N2; + + prP2pSpecificBssInfo = &(prAdapter->rWifiVar.rP2pSpecificBssInfo); + + /* Clear existing value. */ + prP2pSpecificBssInfo->ucBitmapCtrl = 0; + kalMemZero(prP2pSpecificBssInfo->aucPartialVirtualBitmap, + sizeof(prP2pSpecificBssInfo->aucPartialVirtualBitmap)); + + /* IEEE 802.11 2007 - 7.3.2.6 */ + TIM_IE(pucBuffer)->ucId = ELEM_ID_TIM; + TIM_IE(pucBuffer)->ucDTIMCount = prBssInfo->ucDTIMCount; + TIM_IE(pucBuffer)->ucDTIMPeriod = prBssInfo->ucDTIMPeriod; + + /* Setup DTIM Count for next TBTT. */ + if (prBssInfo->ucDTIMCount == 0) { + /*Do nothing*/ + /* 3 *** pmQueryBufferedBCAST(); */ + } + /* 3 *** pmQueryBufferedPSNode(); */ + /* TODO(Kevin): Call PM Module here to loop all STA_RECORD_Ts and it + * will call bssSetTIMBitmap to toggle the Bitmap. + */ + + /* Set Virtual Bitmap for UCAST */ + u4N1 = (prP2pSpecificBssInfo->u2SmallestAID >> 4) << 1; /* Find the largest even number. */ + u4N2 = prP2pSpecificBssInfo->u2LargestAID >> 3; /* Find the smallest number. */ + + ASSERT(u4N2 >= u4N1); + + kalMemCopy(TIM_IE(pucBuffer)->aucPartialVirtualMap, + &prP2pSpecificBssInfo->aucPartialVirtualBitmap[u4N1], ((u4N2 - u4N1) + 1)); + + /* Set Virtual Bitmap for BMCAST */ + /* BMC bit only indicated when DTIM count == 0. */ + if (prBssInfo->ucDTIMCount == 0) + ucBitmapControl = prP2pSpecificBssInfo->ucBitmapCtrl; + TIM_IE(pucBuffer)->ucBitmapControl = ucBitmapControl | (UINT_8) u4N1; + + TIM_IE(pucBuffer)->ucLength = ((u4N2 - u4N1) + 4); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); +#else + + /* IEEE 802.11 2007 - 7.3.2.6 */ + TIM_IE(pucBuffer)->ucId = ELEM_ID_TIM; + /* NOTE: fixed PVB length (AID is allocated from 8 ~ 15 only) */ + TIM_IE(pucBuffer)->ucLength = (3 + MAX_LEN_TIM_PARTIAL_BMP); /*((u4N2 - u4N1) + 4) */ + /* will be overwrite by FW */ + TIM_IE(pucBuffer)->ucDTIMCount = 0; /*prBssInfo->ucDTIMCount */ + TIM_IE(pucBuffer)->ucDTIMPeriod = prBssInfo->ucDTIMPeriod; + /* will be overwrite by FW */ + TIM_IE(pucBuffer)->ucBitmapControl = 0; /*ucBitmapControl | (UINT_8)u4N1 */ + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + +#endif + + } else +#endif /* CFG_ENABLE_WIFI_DIRECT */ + { + /* NOTE(Kevin): 1. AIS - Didn't Support AP Mode. + * 2. BOW - Didn't Support BCAST and PS. + */ + } + + } + +} /* end of bssBuildBeaconProbeRespFrameCommonIEs() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the Beacon/Probe Response frame header and +* its fixed fields. +* +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] pucDestAddr Pointer to the Destination Address, if NULL, means Beacon. +* @param[in] pucOwnMACAddress Given Our MAC Address. +* @param[in] pucBSSID Given BSSID of the BSS. +* @param[in] u2BeaconInterval Given Beacon Interval. +* @param[in] u2CapInfo Given Capability Info. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bssComposeBeaconProbeRespFrameHeaderAndFF(IN PUINT_8 pucBuffer, + IN PUINT_8 pucDestAddr, + IN PUINT_8 pucOwnMACAddress, + IN PUINT_8 pucBSSID, IN UINT_16 u2BeaconInterval, IN UINT_16 u2CapInfo) +{ + P_WLAN_BEACON_FRAME_T prBcnProbRspFrame; + UINT_8 aucBCAddr[] = BC_MAC_ADDR; + UINT_16 u2FrameCtrl; + + DEBUGFUNC("bssComposeBeaconProbeRespFrameHeaderAndFF"); + /* DBGLOG(INIT, LOUD, ("\n")); */ + + ASSERT(pucBuffer); + ASSERT(pucOwnMACAddress); + ASSERT(pucBSSID); + + prBcnProbRspFrame = (P_WLAN_BEACON_FRAME_T) pucBuffer; + + /* 4 <1> Compose the frame header of the Beacon /ProbeResp frame. */ + /* Fill the Frame Control field. */ + if (pucDestAddr) { + u2FrameCtrl = MAC_FRAME_PROBE_RSP; + } else { + u2FrameCtrl = MAC_FRAME_BEACON; + pucDestAddr = aucBCAddr; + } + /* WLAN_SET_FIELD_16(&prBcnProbRspFrame->u2FrameCtrl, u2FrameCtrl); */ + prBcnProbRspFrame->u2FrameCtrl = u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the DA field with BCAST MAC ADDR or TA of ProbeReq. */ + COPY_MAC_ADDR(prBcnProbRspFrame->aucDestAddr, pucDestAddr); + + /* Fill the SA field with our MAC Address. */ + COPY_MAC_ADDR(prBcnProbRspFrame->aucSrcAddr, pucOwnMACAddress); + + /* Fill the BSSID field with current BSSID. */ + COPY_MAC_ADDR(prBcnProbRspFrame->aucBSSID, pucBSSID); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ + prBcnProbRspFrame->u2SeqCtrl = 0; + + /* 4 <2> Compose the frame body's common fixed field part of the Beacon /ProbeResp frame. */ + /* MAC will update TimeStamp field */ + + /* Fill the Beacon Interval field. */ + /* WLAN_SET_FIELD_16(&prBcnProbRspFrame->u2BeaconInterval, u2BeaconInterval); */ + prBcnProbRspFrame->u2BeaconInterval = u2BeaconInterval; /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the Capability Information field. */ + /* WLAN_SET_FIELD_16(&prBcnProbRspFrame->u2CapInfo, u2CapInfo); */ + prBcnProbRspFrame->u2CapInfo = u2CapInfo; /* NOTE(Kevin): Optimized for ARM */ + +} /* end of bssComposeBeaconProbeRespFrameHeaderAndFF() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Update the Beacon Frame Template to FW for AIS AdHoc and P2P GO. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] eNetTypeIndex Specify which network reply the Probe Response. +* +* @retval WLAN_STATUS_SUCCESS Success. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS bssUpdateBeaconContent(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex) +{ + P_BSS_INFO_T prBssInfo; + P_MSDU_INFO_T prBcnMsduInfo; + P_WLAN_BEACON_FRAME_T prBcnFrame; + UINT_32 i; + + DBGLOG(BSS, LOUD, "\n"); + + ASSERT(eNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); + + /* 4 <1> Retrieve MSDU_INFO_T for Beacon Frame */ + prBcnMsduInfo = prBssInfo->prBeacon; + /* prBcnMsduInfo will be NULL if once BSS deactivated, skip it */ + if (prBcnMsduInfo == NULL) + return WLAN_STATUS_SUCCESS; + + prBcnFrame = (P_WLAN_BEACON_FRAME_T) ((ULONG) prBcnMsduInfo->prPacket + MAC_TX_RESERVED_FIELD); + + /* 4 <2> Compose Beacon header */ + bssComposeBeaconProbeRespFrameHeaderAndFF((PUINT_8) prBcnFrame, + NULL, + prBssInfo->aucOwnMacAddr, + prBssInfo->aucBSSID, + prBssInfo->u2BeaconInterval, prBssInfo->u2CapInfo); + + prBcnMsduInfo->u2FrameLength = (WLAN_MAC_MGMT_HEADER_LEN + + (TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN)); + + prBcnMsduInfo->ucNetworkType = eNetTypeIndex; + + /* 4 <3> Compose Beacon body's common IEs */ + bssBuildBeaconProbeRespFrameCommonIEs(prBcnMsduInfo, prBssInfo, NULL); + + /* 4 <4> 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, prBcnMsduInfo); + } + +#if CFG_SUPPORT_P2P_ECSA + if (eNetTypeIndex == NETWORK_TYPE_P2P_INDEX && prBssInfo->fgChanSwitching) { + /* append CSA/ECSA IE */ + rlmGenerateCSAIE(prAdapter, prBcnMsduInfo); + rlmGenerateECSAIE(prAdapter, prBcnMsduInfo); + } +#endif + prBcnFrame = (P_WLAN_BEACON_FRAME_T) prBcnMsduInfo->prPacket; + + return nicUpdateBeaconIETemplate(prAdapter, + IE_UPD_METHOD_UPDATE_ALL, + eNetTypeIndex, + prBcnFrame->u2CapInfo, + (PUINT_8) prBcnFrame->aucInfoElem, + prBcnMsduInfo->u2FrameLength - OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem)); + +} /* end of bssUpdateBeaconContent() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Send the Beacon Frame(for BOW) or Probe Response Frame according to the given +* Destination Address. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] eNetTypeIndex Specify which network reply the Probe Response. +* @param[in] pucDestAddr Pointer to the Destination Address to reply +* @param[in] u4ControlFlags Control flags for information on Probe Response. +* +* @retval WLAN_STATUS_RESOURCE No available resources to send frame. +* @retval WLAN_STATUS_SUCCESS Success. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +bssSendBeaconProbeResponse(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN PUINT_8 pucDestAddr, IN UINT_32 u4ControlFlags) +{ + P_BSS_INFO_T prBssInfo; + P_MSDU_INFO_T prMsduInfo; + UINT_16 u2EstimatedFrameLen; + UINT_16 u2EstimatedFixedIELen; + UINT_16 u2EstimatedExtraIELen; + P_APPEND_VAR_IE_ENTRY_T prIeArray = NULL; + UINT_32 u4IeArraySize = 0; + UINT_32 i; + + ASSERT(eNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); + + if (!pucDestAddr) { /* For Beacon */ + prIeArray = &txBcnIETable[0]; + u4IeArraySize = sizeof(txBcnIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); + } else { + prIeArray = &txProbRspIETable[0]; + u4IeArraySize = sizeof(txProbRspIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); + } + + /* 4 <1> Allocate a PKT_INFO_T for Beacon /Probe Response Frame */ + /* Allocate a MSDU_INFO_T */ + + /* Init with MGMT Header Length + Length of Fixed Fields + Common IE Fields */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + + WLAN_MAC_MGMT_HEADER_LEN + + TIMESTAMP_FIELD_LEN + + BEACON_INTERVAL_FIELD_LEN + + CAP_INFO_FIELD_LEN + + (ELEM_HDR_LEN + ELEM_MAX_LEN_SSID) + + (ELEM_HDR_LEN + ELEM_MAX_LEN_SUP_RATES) + + (ELEM_HDR_LEN + ELEM_MAX_LEN_DS_PARAMETER_SET) + + (ELEM_HDR_LEN + ELEM_MAX_LEN_IBSS_PARAMETER_SET) + (ELEM_HDR_LEN + (3 + MAX_LEN_TIM_PARTIAL_BMP)); + + /* + Extra IE Length */ + u2EstimatedExtraIELen = 0; + + for (i = 0; i < u4IeArraySize; i++) { + u2EstimatedFixedIELen = prIeArray[i].u2EstimatedFixedIELen; + + if (u2EstimatedFixedIELen) { + u2EstimatedExtraIELen += u2EstimatedFixedIELen; + } else { + ASSERT(prIeArray[i].pfnCalculateVariableIELen); + + u2EstimatedExtraIELen += (UINT_16) + prIeArray[i].pfnCalculateVariableIELen(prAdapter, eNetTypeIndex, NULL); + } + } + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(BSS, WARN, "No PKT_INFO_T for sending %s.\n", ((!pucDestAddr) ? "Beacon" : "Probe Response")); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Beacon/Probe Response frame header and fixed fields in MSDU_INfO_T. */ + /* Compose Header and Fixed Field */ +#if CFG_ENABLE_WIFI_DIRECT + if (u4ControlFlags & BSS_PROBE_RESP_USE_P2P_DEV_ADDR) { + if (prAdapter->fgIsP2PRegistered) { + bssComposeBeaconProbeRespFrameHeaderAndFF((PUINT_8) + ((ULONG) (prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD), pucDestAddr, + prAdapter->rWifiVar.aucDeviceAddress, + prAdapter->rWifiVar.aucDeviceAddress, + DOT11_BEACON_PERIOD_DEFAULT, + (prBssInfo->u2CapInfo & + ~(CAP_INFO_ESS | CAP_INFO_IBSS))); + } + } else +#endif /* CFG_ENABLE_WIFI_DIRECT */ + { + bssComposeBeaconProbeRespFrameHeaderAndFF((PUINT_8) + ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + pucDestAddr, prBssInfo->aucOwnMacAddr, prBssInfo->aucBSSID, + prBssInfo->u2BeaconInterval, prBssInfo->u2CapInfo); + } + + /* 4 <3> Update information of MSDU_INFO_T */ + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfo->ucStaRecIndex = 0xFF; + prMsduInfo->ucNetworkType = (UINT_8) eNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = (WLAN_MAC_MGMT_HEADER_LEN + + TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN); + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->fgIsBasicRate = TRUE; + + /* 4 <4> Compose the frame body's Common IEs of the Beacon/ProbeResp frame. */ + bssBuildBeaconProbeRespFrameCommonIEs(prMsduInfo, prBssInfo, pucDestAddr); + + /* 4 <5> Compose IEs in MSDU_INFO_T */ + + /* Append IE */ + for (i = 0; i < u4IeArraySize; i++) { + if (prIeArray[i].pfnAppendIE) + prIeArray[i].pfnAppendIE(prAdapter, prMsduInfo); + } + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ + + /* 4 <6> Inform TXM to send this Beacon /Probe Response frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; + +} /* end of bssSendBeaconProbeResponse() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will process the Rx Probe Request Frame and then send +* back the corresponding Probe Response Frame if the specified conditions +* were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* +* @retval WLAN_STATUS_SUCCESS Always return success +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS bssProcessProbeRequest(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_WLAN_MAC_MGMT_HEADER_T prMgtHdr; + P_BSS_INFO_T prBssInfo; + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex; + UINT_8 aucBCBSSID[] = BC_BSSID; + BOOLEAN fgIsBcBssid; + BOOLEAN fgReplyProbeResp; + UINT_32 u4CtrlFlagsForProbeResp = 0; + ENUM_BAND_T eBand; + UINT_8 ucHwChannelNum; + + ASSERT(prSwRfb); + + /* 4 <1> Parse Probe Req and Get BSSID */ + prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T) prSwRfb->pvHeader; + + if (EQUAL_MAC_ADDR(aucBCBSSID, prMgtHdr->aucBSSID)) + fgIsBcBssid = TRUE; + else + fgIsBcBssid = FALSE; + + /* 4 <2> Check network conditions before reply Probe Response Frame (Consider Concurrent) */ + for (eNetTypeIndex = NETWORK_TYPE_AIS_INDEX; eNetTypeIndex < NETWORK_TYPE_INDEX_NUM; eNetTypeIndex++) { + + if (!IS_NET_ACTIVE(prAdapter, eNetTypeIndex)) + continue; + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); + + if ((!fgIsBcBssid) && UNEQUAL_MAC_ADDR(prBssInfo->aucBSSID, prMgtHdr->aucBSSID)) + continue; + + eBand = HIF_RX_HDR_GET_RF_BAND(prSwRfb->prHifRxHdr); + ucHwChannelNum = HIF_RX_HDR_GET_CHNL_NUM(prSwRfb->prHifRxHdr); + + if (prBssInfo->eBand != eBand) + continue; + + if (prBssInfo->ucPrimaryChannel != ucHwChannelNum) + continue; + + fgReplyProbeResp = FALSE; + + if (eNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { + +#if CFG_SUPPORT_ADHOC + fgReplyProbeResp = aisValidateProbeReq(prAdapter, prSwRfb, &u4CtrlFlagsForProbeResp); +#endif + } +#if CFG_ENABLE_WIFI_DIRECT + else if ((prAdapter->fgIsP2PRegistered) && (eNetTypeIndex == NETWORK_TYPE_P2P_INDEX)) { + if (nicTxGetFreeCmdCount(prAdapter) > (CFG_TX_MAX_CMD_PKT_NUM / 2)) { + /* Resource margin is enough */ + fgReplyProbeResp = + p2pFuncValidateProbeReq(prAdapter, prSwRfb, &u4CtrlFlagsForProbeResp); + } + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (eNetTypeIndex == NETWORK_TYPE_BOW_INDEX) + 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 (eNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { + + if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + + /* TODO(Kevin): Check if we are IBSS Master. */ + if (TRUE && prIeSsid) { + if ((prIeSsid->ucLength == BC_SSID_LEN) || /* WILDCARD SSID */ + EQUAL_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, + prIeSsid->aucSSID, prIeSsid->ucLength)) { + fgReplyProbeResp = TRUE; + } + } + } + } +#if CFG_ENABLE_WIFI_DIRECT + else if (eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + + /* TODO(Kevin): Move following lines to p2p_fsm.c */ + + if ((prIeSsid) && + ((prIeSsid->ucLength == BC_SSID_LEN) || + (EQUAL_SSID(aucP2PWildcardSSID, + P2P_WILDCARD_SSID_LEN, prIeSsid->aucSSID, prIeSsid->ucLength)))) { + /* + * if (p2pFsmRunEventRxProbeRequestFrame(prAdapter, prMgtHdr->aucSrcAddr, + * pucIE, u2IELength)) { + */ + if (p2pFsmRunEventRxProbeRequestFrame(prAdapter, prSwRfb)) { + /* Extand channel request time & cancel scan request. */ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + + /* TODO: RX probe request may not caused by LISTEN state. */ + /* TODO: It can be GO. */ + /* Generally speaking, cancel a non-exist scan request is fine. + * We can check P2P FSM here for only LISTEN state. + */ + + P_MSG_SCN_SCAN_CANCEL prScanCancelMsg; + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + /* Abort JOIN process. */ + prScanCancelMsg = + (P_MSG_SCN_SCAN_CANCEL) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(MSG_SCN_SCAN_CANCEL)); + if (!prScanCancelMsg) { + ASSERT(0); /* Can't abort SCN FSM */ + continue; + } + + prScanCancelMsg->rMsgHdr.eMsgId = MID_P2P_SCN_SCAN_CANCEL; + prScanCancelMsg->ucSeqNum = prP2pFsmInfo->ucSeqNumOfScnMsg; + prScanCancelMsg->ucNetTypeIndex = (UINT_8) NETWORK_TYPE_P2P_INDEX; + prScanCancelMsg->fgIsChannelExt = TRUE; + + mboxSendMsg(prAdapter, + MBOX_ID_0, (P_MSG_HDR_T) prScanCancelMsg, MSG_SEND_METHOD_BUF); + } + } else { + /* 1. Probe Request without SSID. + * 2. Probe Request with SSID not Wildcard SSID & not P2P Wildcard SSID. + */ + continue; + } + +#if 0 /* Frog */ + if (prAdapter->rWifiVar.prP2pFsmInfo->eCurrentState == P2P_STATE_LISTEN) { + /* + * P2P 2.4.1 - P2P Devices shall not respond to Probe Request frames + * which only contain 11b rates only. + */ + if (prIeSupportedRate || prIeExtSupportedRate) { + UINT_16 u2OperationalRateSet, u2BSSBasicRateSet; + BOOLEAN fgIsUnknownBssBasicRate; + + rateGetRateSetFromIEs(prIeSupportedRate, prIeExtSupportedRate, + &u2OperationalRateSet, + &u2BSSBasicRateSet, /* Ignore any Basic Bit */ + &fgIsUnknownBssBasicRate); + + if (u2OperationalRateSet & ~RATE_SET_HR_DSSS) + continue; + } + } + /* TODO: Check channel time before first check point to: */ + /* If Target device is selected: + * 1. Send XXXX request frame. + * else + * 1. Send Probe Response frame. + */ + + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + /* TODO(Kevin): During PROVISION state, can we reply Probe Response ? */ + + /* TODO(Kevin): + * If we are GO, accept legacy client --> accept Wildcard SSID + * If we are in Listen State, accept only P2P Device --> check P2P IE and WPS IE + */ + if (TRUE /* We are GO */ && prIeSsid) { + UINT_8 aucSSID[] = P2P_WILDCARD_SSID; + + if ((prIeSsid->ucLength == BC_SSID_LEN) || /* WILDCARD SSID */ + EQUAL_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, + prIeSsid->aucSSID, prIeSsid->ucLength) || + EQUAL_SSID(aucSSID, P2P_WILDCARD_SSID_LEN, + prIeSsid->aucSSID, prIeSsid->ucLength)) { + fgReplyProbeResp = TRUE; + } + } +/* else if (FALSE) { */ /* We are in Listen State */ +/* } */ + + /* TODO(Kevin): Check P2P IE and WPS IE */ + } +#endif + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (eNetTypeIndex == NETWORK_TYPE_BOW_INDEX) { + + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + /* Do nothing */ + /* TODO(Kevin): TBD */ + } + } +#endif + else + ASSERT(eNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + if (fgReplyProbeResp) + bssSendBeaconProbeResponse(prAdapter, eNetTypeIndex, prMgtHdr->aucSrcAddr); + + } + + return WLAN_STATUS_SUCCESS; + +} /* end of bssProcessProbeRequest() */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to clear the client list for AdHoc or AP Mode +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prBssInfo Given related BSS_INFO_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bssClearClientList(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo) +{ + P_LINK_T prStaRecOfClientList; + + ASSERT(prBssInfo); + + prStaRecOfClientList = &prBssInfo->rStaRecOfClientList; + + if (!LINK_IS_EMPTY(prStaRecOfClientList)) { + P_STA_RECORD_T prPeerStaRec; + + LINK_FOR_EACH_ENTRY(prPeerStaRec, prStaRecOfClientList, rLinkEntry, STA_RECORD_T) { + cnmStaRecChangeState(prAdapter, prPeerStaRec, STA_STATE_1); + } + + LINK_INITIALIZE(prStaRecOfClientList); + } + +} /* end of bssClearClientList() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to Add a STA_RECORD_T to the client list for AdHoc or AP Mode +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prBssInfo Given related BSS_INFO_T. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bssAddStaRecToClientList(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_STA_RECORD_T prStaRec) +{ + P_LINK_T prClientList; + + ASSERT(prBssInfo); + + prClientList = &prBssInfo->rStaRecOfClientList; + + if (!LINK_IS_EMPTY(prClientList)) { + P_STA_RECORD_T prCurrStaRec; + + LINK_FOR_EACH_ENTRY(prCurrStaRec, prClientList, rLinkEntry, STA_RECORD_T) { + + if (prCurrStaRec == prStaRec) { + DBGLOG(BSS, INFO, "Current client list already contains that STA_RECORD_T[%pM]\n", + prStaRec->aucMacAddr); + return; + } + } + } + + DBGLOG(BSS, INFO, "Add STA_RECORD_T[%pM] to the client list\n", prStaRec->aucMacAddr); + LINK_INSERT_TAIL(prClientList, &prStaRec->rLinkEntry); + +} /* end of bssAddStaRecToClientList() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to Remove a STA_RECORD_T from the client list for AdHoc or AP Mode +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bssRemoveStaRecFromClientList(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_STA_RECORD_T prStaRec) +{ + P_LINK_T prClientList; + + ASSERT(prBssInfo); + + prClientList = &prBssInfo->rStaRecOfClientList; + +#if 0 + if (!LINK_IS_EMPTY(prClientList)) { + P_STA_RECORD_T prCurrStaRec; + + LINK_FOR_EACH_ENTRY(prCurrStaRec, prClientList, rLinkEntry, STA_RECORD_T) { + + if (prCurrStaRec == prStaRec) { + DBGLOG(BSS, INFO, "Remove STA_RECORD_T[%pM] from the client list\n", + prStaRec->aucMacAddr); + LINK_REMOVE_KNOWN_ENTRY(prClientList, &prStaRec->rLinkEntry); + return; + } + } + } +#else + if (!LINK_IS_EMPTY(prClientList)) { + + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; + + LINK_FOR_EACH(prLinkEntry, prClientList) { + if ((ULONG) prStaRec == (ULONG) prLinkEntry) { + DBGLOG(BSS, INFO, "Remove STA_RECORD_T[%pM] from the client list\n", + prStaRec->aucMacAddr); + LINK_REMOVE_KNOWN_ENTRY(prClientList, &prStaRec->rLinkEntry); + return; + } + } + } +#endif + DBGLOG(BSS, INFO, "Current client list didn't contain that STA_RECORD_T[%pM] before removing\n", + prStaRec->aucMacAddr); + +} /* end of bssRemoveStaRecFromClientList() */ +#endif /* CFG_SUPPORT_ADHOC || CFG_SUPPORT_AAA */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Get station record by Address for AP mode +* +* @param[in] prBssInfo Pointer to BSS_INFO_T. +* @param[in] pucMacAddr Pointer to target mac address +* +* @return pointer of STA_RECORD_T if found, otherwise, return NULL +*/ +/*----------------------------------------------------------------------------*/ + +P_STA_RECORD_T bssGetClientByAddress(IN P_BSS_INFO_T prBssInfo, PUINT_8 pucMacAddr) +{ + P_LINK_T prStaRecOfClientList; + + ASSERT(prBssInfo); + ASSERT(pucMacAddr); + + prStaRecOfClientList = &prBssInfo->rStaRecOfClientList; + if (!LINK_IS_EMPTY(prStaRecOfClientList)) { + P_STA_RECORD_T prCurrStaRec; + + LINK_FOR_EACH_ENTRY(prCurrStaRec, prStaRecOfClientList, rLinkEntry, STA_RECORD_T) { + if (EQUAL_MAC_ADDR(prCurrStaRec->aucMacAddr, pucMacAddr)) + return prCurrStaRec; + } + } + return NULL; +} + +#if CFG_SUPPORT_ADHOC +/*----------------------------------------------------------------------------*/ +/* Routines for IBSS(AdHoc) only */ +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to process Beacons from current Ad-Hoc network peers. +* We also process Beacons from other Ad-Hoc network during SCAN. If it has +* the same SSID and we'll decide to merge into it if it has a larger TSF. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prBssInfo Pointer to the BSS_INFO_T. +* @param[in] prBSSDesc Pointer to the BSS Descriptor. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +ibssProcessMatchedBeacon(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, IN P_BSS_DESC_T prBssDesc, IN UINT_8 ucRCPI) +{ + P_STA_RECORD_T prStaRec = NULL; + + BOOLEAN fgIsCheckCapability = FALSE; + BOOLEAN fgIsCheckTSF = FALSE; + BOOLEAN fgIsGoingMerging = FALSE; + BOOLEAN fgIsSameBSSID; + + ASSERT(prBssInfo); + ASSERT(prBssDesc); + + /* 4 <1> Process IBSS Beacon only after we create or merge with other IBSS. */ + if (!prBssInfo->fgIsBeaconActivated) + return; + /* 4 <2> Get the STA_RECORD_T of TA. */ + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX, prBssDesc->aucSrcAddr); + + fgIsSameBSSID = UNEQUAL_MAC_ADDR(prBssInfo->aucBSSID, prBssDesc->aucBSSID) ? FALSE : TRUE; + + /* 4 <3> IBSS Merge Decision Flow for Processing Beacon. */ + if (fgIsSameBSSID) { + + /* Same BSSID: + * Case I. This is a new TA and it has decide to merged with us. + * a) If fgIsMerging == FALSE - we will send msg to notify AIS. + * b) If fgIsMerging == TRUE - already notify AIS. + * Case II. This is an old TA and we've already merged together. + */ + if (!prStaRec) { + + /* For Case I - Check this IBSS's capability first before adding this Sta Record. */ + fgIsCheckCapability = TRUE; + + /* If check is passed, then we perform merging with this new IBSS */ + fgIsGoingMerging = TRUE; + + } else { + + ASSERT((prStaRec->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) && IS_ADHOC_STA(prStaRec)); + + if (prStaRec->ucStaState != STA_STATE_3) { + + if (!prStaRec->fgIsMerging) { + + /* + * For Case I - Check this IBSS's capability first + * before adding this Sta Record. + */ + fgIsCheckCapability = TRUE; + + /* If check is passed, then we perform merging with this new IBSS */ + fgIsGoingMerging = TRUE; + } else { + /* For Case II - Update rExpirationTime of Sta Record */ + GET_CURRENT_SYSTIME(&prStaRec->rUpdateTime); + } + } else { + /* For Case II - Update rExpirationTime of Sta Record */ + GET_CURRENT_SYSTIME(&prStaRec->rUpdateTime); + } + + } + } else { + + /* Unequal BSSID: + * Case III. This is a new TA and we need to compare the TSF and get the winner. + * Case IV. This is an old TA and it merge into a new IBSS before we do the same thing. + * We need to compare the TSF to get the winner. + * Case V. This is an old TA and it restart a new IBSS. We also need to + * compare the TSF to get the winner. + */ + + /* For Case III, IV & V - We'll always check this new IBSS's capability first + * before merging into new IBSS. + */ + fgIsCheckCapability = TRUE; + + /* If check is passed, we need to perform TSF check to decide the major BSSID */ + fgIsCheckTSF = TRUE; + + /* For Case IV & V - We won't update rExpirationTime of Sta Record */ + } + + /* 4 <7> Check this BSS_DESC_T's capability. */ + if (fgIsCheckCapability) { + BOOLEAN fgIsCapabilityMatched = FALSE; + + do { + if (!(prBssDesc->ucPhyTypeSet & (prAdapter->rWifiVar.ucAvailablePhyTypeSet))) { + DBGLOG(BSS, LOUD, + "IBSS MERGE: Ignore Peer MAC: %pM - Unsupported Phy.\n", + prBssDesc->aucSrcAddr); + + break; + } + + if (prBssDesc->fgIsUnknownBssBasicRate) { + DBGLOG(BSS, LOUD, + "IBSS MERGE: Ignore Peer MAC: %pM - Unknown Basic Rate.\n", + prBssDesc->aucSrcAddr); + + break; + } + + if (ibssCheckCapabilityForAdHocMode(prAdapter, prBssDesc) == WLAN_STATUS_FAILURE) { + DBGLOG(BSS, LOUD, + "IBSS MERGE: Ignore Peer MAC: %pM - Capability is not matched.\n", + prBssDesc->aucSrcAddr); + + break; + } + + fgIsCapabilityMatched = TRUE; + } while (FALSE); + + if (!fgIsCapabilityMatched) { + + if (prStaRec) { + /* For Case II - We merge this STA_RECORD in RX Path. + * Case IV & V - They change their BSSID after we merge with them. + */ + + DBGLOG(BSS, LOUD, + "IBSS MERGE: Ignore Peer MAC: %pM - Capability is not matched.\n", + prBssDesc->aucSrcAddr); + } + + return; + } + + DBGLOG(BSS, LOUD, + "IBSS MERGE: Peer MAC: %pM - Check capability was passed.\n", + prBssDesc->aucSrcAddr); + } + + if (fgIsCheckTSF) { +#if CFG_SLT_SUPPORT + fgIsGoingMerging = TRUE; +#else + if (prBssDesc->fgIsLargerTSF) + fgIsGoingMerging = TRUE; + else + return; +#endif + } + + if (fgIsGoingMerging) { + P_MSG_AIS_IBSS_PEER_FOUND_T prAisIbssPeerFoundMsg; + + /* 4 <1> We will merge with to this BSS immediately. */ + prBssDesc->fgIsConnecting = TRUE; + prBssDesc->fgIsConnected = FALSE; + + /* 4 <2> Setup corresponding STA_RECORD_T */ + prStaRec = bssCreateStaRecFromBssDesc(prAdapter, + STA_TYPE_ADHOC_PEER, NETWORK_TYPE_AIS_INDEX, prBssDesc); + + if (!prStaRec) { + /* no memory ? */ + return; + } + + prStaRec->fgIsMerging = TRUE; + + /* update RCPI */ + prStaRec->ucRCPI = ucRCPI; + + /* 4 <3> Send Merge Msg to CNM to obtain the channel privilege. */ + prAisIbssPeerFoundMsg = (P_MSG_AIS_IBSS_PEER_FOUND_T) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_IBSS_PEER_FOUND_T)); + + if (!prAisIbssPeerFoundMsg) { + + ASSERT(0); /* Can't send Merge Msg */ + return; + } + + prAisIbssPeerFoundMsg->rMsgHdr.eMsgId = MID_SCN_AIS_FOUND_IBSS; + prAisIbssPeerFoundMsg->ucNetTypeIndex = (UINT_8) NETWORK_TYPE_AIS_INDEX; + prAisIbssPeerFoundMsg->prStaRec = prStaRec; + + /* Inform AIS to do STATE TRANSITION + * For Case I - If AIS in IBSS_ALONE, let it jump to NORMAL_TR after we know the new member. + * For Case III, IV - Now this new BSSID wins the TSF, follow it. + */ + if (fgIsSameBSSID) { + prAisIbssPeerFoundMsg->fgIsMergeIn = TRUE; + } else { +#if CFG_SLT_SUPPORT + prAisIbssPeerFoundMsg->fgIsMergeIn = TRUE; +#else + prAisIbssPeerFoundMsg->fgIsMergeIn = (prBssDesc->fgIsLargerTSF) ? FALSE : TRUE; +#endif + } + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisIbssPeerFoundMsg, MSG_SEND_METHOD_BUF); + + } + +} /* end of ibssProcessMatchedBeacon() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will check the Capability for Ad-Hoc to decide if we are +* able to merge with(same capability). +* +* @param[in] prBSSDesc Pointer to the BSS Descriptor. +* +* @retval WLAN_STATUS_FAILURE Can't pass the check of Capability. +* @retval WLAN_STATUS_SUCCESS Pass the check of Capability. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS ibssCheckCapabilityForAdHocMode(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prBssDesc); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + do { + /* 4 <1> Check the BSS Basic Rate Set for current AdHoc Mode */ + if ((prConnSettings->eAdHocMode == AD_HOC_MODE_11B) && + (prBssDesc->u2BSSBasicRateSet & ~RATE_SET_HR_DSSS)) { + break; + } else if ((prConnSettings->eAdHocMode == AD_HOC_MODE_11A) && + (prBssDesc->u2BSSBasicRateSet & ~RATE_SET_OFDM)) { + break; + } + /* 4 <2> Check the Short Slot Time. */ +#if 0 /* Do not check ShortSlotTime until Wi-Fi define such policy */ + if (prConnSettings->eAdHocMode == AD_HOC_MODE_11G) { + if (((prConnSettings->fgIsShortSlotTimeOptionEnable) && + !(prBssDesc->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME)) || + (!(prConnSettings->fgIsShortSlotTimeOptionEnable) && + (prBssDesc->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME))) { + break; + } + } +#endif + + /* 4 <3> Check the ATIM window setting. */ + if (prBssDesc->u2ATIMWindow) { + DBGLOG(BSS, INFO, "AdHoc PS was not supported(ATIM Window: %d)\n", prBssDesc->u2ATIMWindow); + break; + } +#if CFG_RSN_MIGRATION + /* 4 <4> Check the Security setting. */ + if (!rsnPerformPolicySelection(prAdapter, prBssDesc)) + break; +#endif + + rStatus = WLAN_STATUS_SUCCESS; + } while (FALSE); + + return rStatus; + +} /* end of ibssCheckCapabilityForAdHocMode() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will initial the BSS_INFO_T for IBSS Mode. +* +* @param[in] prBssInfo Pointer to the BSS_INFO_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID ibssInitForAdHoc(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo) +{ + UINT_8 ucLowestBasicRateIndex; + UINT_8 aucBSSID[MAC_ADDR_LEN]; + PUINT_16 pu2BSSID = (PUINT_16) &aucBSSID[0]; + UINT_32 i; + + ASSERT(prBssInfo); + ASSERT(prBssInfo->eCurrentOPMode == OP_MODE_IBSS); + + /* 4 <1> Setup PHY Attributes and Basic Rate Set/Operational Rate Set */ + prBssInfo->ucNonHTBasicPhyType = (UINT_8) + rNonHTAdHocModeAttributes[prBssInfo->ucConfigAdHocAPMode].ePhyTypeIndex; + prBssInfo->u2BSSBasicRateSet = rNonHTAdHocModeAttributes[prBssInfo->ucConfigAdHocAPMode].u2BSSBasicRateSet; + + prBssInfo->u2OperationalRateSet = rNonHTPhyAttributes[prBssInfo->ucNonHTBasicPhyType].u2SupportedRateSet; + + rateGetDataRatesFromRateSet(prBssInfo->u2OperationalRateSet, + prBssInfo->u2BSSBasicRateSet, + prBssInfo->aucAllSupportedRates, &prBssInfo->ucAllSupportedRatesLen); + + /* 4 <2> Setup BSSID */ + if (!prBssInfo->fgHoldSameBssidForIBSS) { + + for (i = 0; i < sizeof(aucBSSID) / sizeof(UINT_16); i++) + pu2BSSID[i] = (UINT_16) (kalRandomNumber() & 0xFFFF); + + aucBSSID[0] &= ~0x01; /* 7.1.3.3.3 - The individual/group bit of the address is set to 0. */ + aucBSSID[0] |= 0x02; /* 7.1.3.3.3 - The universal/local bit of the address is set to 1. */ + + COPY_MAC_ADDR(prBssInfo->aucBSSID, aucBSSID); + } + /* 4 <3> Setup Capability - Short Preamble */ + if (rNonHTPhyAttributes[prBssInfo->ucNonHTBasicPhyType].fgIsShortPreambleOptionImplemented && + ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_SHORT) || /* Short Preamble Option Enable is TRUE */ + (prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_AUTO))) { + prBssInfo->fgIsShortPreambleAllowed = TRUE; + prBssInfo->fgUseShortPreamble = TRUE; + } else { + prBssInfo->fgIsShortPreambleAllowed = FALSE; + prBssInfo->fgUseShortPreamble = FALSE; + } + + /* 4 <4> Setup Capability - Short Slot Time */ + /* 7.3.1.4 For IBSS, the Short Slot Time subfield shall be set to 0. */ + prBssInfo->fgUseShortSlotTime = FALSE; /* Set to FALSE for AdHoc */ + + /* 4 <5> Compoase Capability */ + prBssInfo->u2CapInfo = CAP_INFO_IBSS; + + if (prBssInfo->fgIsProtection) + prBssInfo->u2CapInfo |= CAP_INFO_PRIVACY; + + if (prBssInfo->fgIsShortPreambleAllowed) + prBssInfo->u2CapInfo |= CAP_INFO_SHORT_PREAMBLE; + + if (prBssInfo->fgUseShortSlotTime) + prBssInfo->u2CapInfo |= CAP_INFO_SHORT_SLOT_TIME; + /* 4 <6> Find Lowest Basic Rate Index for default TX Rate of MMPDU */ + rateGetLowestRateIndexFromRateSet(prBssInfo->u2BSSBasicRateSet, &ucLowestBasicRateIndex); + + prBssInfo->ucHwDefaultFixedRateCode = aucRateIndex2RateCode[PREAMBLE_DEFAULT_LONG_NONE][ucLowestBasicRateIndex]; + +} /* end of ibssInitForAdHoc() */ + +#endif /* CFG_SUPPORT_ADHOC */ + +#if CFG_SUPPORT_AAA + +/*----------------------------------------------------------------------------*/ +/* Routines for BSS(AP) only */ +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will initial the BSS_INFO_T for AP Mode. +* +* @param[in] prBssInfo Given related BSS_INFO_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bssInitForAP(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN BOOLEAN fgIsRateUpdate) +{ + UINT_8 ucLowestBasicRateIndex; + + P_AC_QUE_PARMS_T prACQueParms; + + ENUM_WMM_ACI_T eAci; + + UINT_8 auCWminLog2ForBcast[WMM_AC_INDEX_NUM] = { 4 /*BE*/, 4 /*BK*/, 3 /*VO*/, 2 /*VI*/ }; + UINT_8 auCWmaxLog2ForBcast[WMM_AC_INDEX_NUM] = { 10, 10, 4, 3 }; + UINT_8 auAifsForBcast[WMM_AC_INDEX_NUM] = { 3, 7, 2, 2 }; + UINT_8 auTxopForBcast[WMM_AC_INDEX_NUM] = { 0, 0, 94, 47 }; /* If the AP is OFDM */ + + DBGLOG(BSS, LOUD, "\n"); + + ASSERT(prBssInfo); + ASSERT((prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) || (prBssInfo->eCurrentOPMode == OP_MODE_BOW)); + + /* 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> Compose Capability */ + /* 4 <3.1> 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; + } + DBGLOG(BSS, TRACE, "BasicPhyType :%d, prBssInfo->u2CapInfo=0x%x !\n" + , prBssInfo->ucNonHTBasicPhyType + , prBssInfo->u2CapInfo); + + /* 4 <3.2> Setup Capability - Short Slot Time */ + prBssInfo->fgUseShortSlotTime = TRUE; +#if CFG_SET_BCN_CAPINFO_BY_DRIVER + 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; +#endif + /* 4 <4> Use lowest basic rate for default TX rate of MMPDU */ + rateGetLowestRateIndexFromRateSet(prBssInfo->u2BSSBasicRateSet, &ucLowestBasicRateIndex); + prBssInfo->ucHwDefaultFixedRateCode = aucRateIndex2RateCode[PREAMBLE_DEFAULT_LONG_NONE][ucLowestBasicRateIndex]; + + /* 4 <5> 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 = prAdapter->rWifiVar.aucAifsN[eAci]; + prACQueParms[eAci].u2CWmin = + BIT(prAdapter->rWifiVar.aucCwMin[eAci]) - 1; + prACQueParms[eAci].u2CWmax = + BIT(prAdapter->rWifiVar.au2CwMax[eAci]) - 1; + prACQueParms[eAci].u2TxopLimit = + prAdapter->rWifiVar.au2TxOp[eAci]; + + DBGLOG(BSS, INFO, "eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", + eAci, prACQueParms[eAci].fgIsACMSet, + prACQueParms[eAci].u2Aifsn, + prACQueParms[eAci].u2CWmin, + prACQueParms[eAci].u2CWmax, prACQueParms[eAci].u2TxopLimit); + } + + /* Note: Caller should update the EDCA setting to HW by nicQmUpdateWmmParms() it there is no AIS network */ + /* Note: In E2, only 4 HW queues. The the Edca parameters should be folow by AIS network */ + /* Note: In E3, 8 HW queues. the Wmm parameters should be updated to right queues according to BSS */ + +} /* end of bssInitForAP() */ + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* @brief Update DTIM Count +* +* @param[in] eNetTypeIndex Specify which network to update +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bssUpdateDTIMCount(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex) +{ + P_BSS_INFO_T prBssInfo; + + ASSERT(eNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); + + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + + /* Setup DTIM Count for next TBTT. */ + if (prBssInfo->ucDTIMCount > 0) { + prBssInfo->ucDTIMCount--; + } else { + + ASSERT(prBssInfo->ucDTIMPeriod > 0); + + prBssInfo->ucDTIMCount = prBssInfo->ucDTIMPeriod - 1; + } + } + +} /* end of bssUpdateDTIMIE() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to set the Virtual Bitmap in TIM Information Elements +* +* @param[in] prBssInfo Pointer to the BSS_INFO_T. +* @param[in] u2AssocId The association id to set in Virtual Bitmap. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bssSetTIMBitmap(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN UINT_16 u2AssocId) +{ + + ASSERT(prBssInfo); + + if (prBssInfo->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo; + + prP2pSpecificBssInfo = &(prAdapter->rWifiVar.rP2pSpecificBssInfo); + + /* Use Association ID == 0 for BMCAST indication */ + if (u2AssocId == 0) { + + prP2pSpecificBssInfo->ucBitmapCtrl |= (UINT_8) BIT(0); + } else { + PUINT_8 pucPartialVirtualBitmap; + UINT_8 ucBitmapToSet; + + /* (u2AssocId / 8) */ + pucPartialVirtualBitmap = &prP2pSpecificBssInfo->aucPartialVirtualBitmap[(u2AssocId >> 3)]; + ucBitmapToSet = (UINT_8) BIT((u2AssocId % 8)); + + if (*pucPartialVirtualBitmap & ucBitmapToSet) { + /* The virtual bitmap has been set */ + return; + } + + *pucPartialVirtualBitmap |= ucBitmapToSet; + + /* Update u2SmallestAID and u2LargestAID */ + if ((u2AssocId < prP2pSpecificBssInfo->u2SmallestAID) || + (prP2pSpecificBssInfo->u2SmallestAID == 0)) { + prP2pSpecificBssInfo->u2SmallestAID = u2AssocId; + } + + if ((u2AssocId > prP2pSpecificBssInfo->u2LargestAID) || + (prP2pSpecificBssInfo->u2LargestAID == 0)) { + prP2pSpecificBssInfo->u2LargestAID = u2AssocId; + } + } + } + +} /* end of bssSetTIMBitmap() */ +#endif + +#endif /* CFG_SUPPORT_AAA */ + +VOID bssCreateStaRecFromAuth(IN P_ADAPTER_T prAdapter) +{ + +} + +VOID bssUpdateStaRecFromAssocReq(IN P_ADAPTER_T prAdapter) +{ + +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/cnm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/cnm.c new file mode 100644 index 0000000000000..5246dbc9bf0ca --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/cnm.c @@ -0,0 +1,673 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E 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 +******************************************************************************** +*/ + +/* Be able to allow HT40 with different connection type concurrently */ +#define CONCURRENT_HT40_NOT_ALLOW 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 +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to initialize variables in CNM_INFO_T. +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmInit(P_ADAPTER_T prAdapter) +{ + cnmTimerInitTimer(prAdapter, &prAdapter->rCnmInfo.rReqChnlUtilTimer, + (PFN_MGMT_TIMEOUT_FUNC)cnmRunEventReqChnlUtilTimeout, (ULONG) NULL); +} /* 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) +{ + cnmTimerStopTimer(prAdapter, &prAdapter->rCnmInfo.rReqChnlUtilTimer); +} /* 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 d=%d\n", + prMsgChReq->ucNetTypeIndex, prMsgChReq->ucTokenID, + prMsgChReq->eRfBand, prMsgChReq->ucPrimaryChannel, + prMsgChReq->eRfSco, prMsgChReq->u4MaxInterval); + + prCmdBody->ucNetTypeIndex = prMsgChReq->ucNetTypeIndex; + prCmdBody->ucTokenID = prMsgChReq->ucTokenID; + prCmdBody->ucAction = CMD_CH_ACTION_REQ; /* Request */ + prCmdBody->ucPrimaryChannel = prMsgChReq->ucPrimaryChannel; + prCmdBody->ucRfSco = (UINT_8) prMsgChReq->eRfSco; + prCmdBody->ucRfBand = (UINT_8) prMsgChReq->eRfBand; + prCmdBody->ucReqType = (UINT_8) prMsgChReq->eReqType; + prCmdBody->ucReserved = 0; + prCmdBody->u4MaxInterval = prMsgChReq->u4MaxInterval; + COPY_MAC_ADDR(prCmdBody->aucBSSID, prMsgChReq->aucBSSID); + + ASSERT(prCmdBody->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + /* For monkey testing 20110901 */ + if (prCmdBody->ucNetTypeIndex >= NETWORK_TYPE_INDEX_NUM) + DBGLOG(CNM, ERROR, "CNM: ChReq with wrong netIdx=%d\n\n", prCmdBody->ucNetTypeIndex); + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_CH_PRIVILEGE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_CH_PRIVILEGE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdBody, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); + + cnmMemFree(prAdapter, prCmdBody); + cnmMemFree(prAdapter, prMsgHdr); + +} /* end of cnmChMngrRequestPrivilege() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Before deliver the message to other module, it need to release +* the Channel privilege to Channel Manager. +* +* @param[in] prMsgHdr The message need to be delivered +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmChMngrAbortPrivilege(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr) +{ + P_MSG_CH_ABORT_T prMsgChAbort; + P_CMD_CH_PRIVILEGE_T prCmdBody; + WLAN_STATUS rStatus; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prMsgChAbort = (P_MSG_CH_ABORT_T) prMsgHdr; + + prCmdBody = (P_CMD_CH_PRIVILEGE_T) + cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_CH_PRIVILEGE_T)); + ASSERT(prCmdBody); + + /* To do: exception handle */ + if (!prCmdBody) { + DBGLOG(CNM, ERROR, "ChAbort: fail to get buf (net=%d, token=%d)\n", + prMsgChAbort->ucNetTypeIndex, prMsgChAbort->ucTokenID); + + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + DBGLOG(CNM, INFO, "ChAbort net=%d token=%d\n", prMsgChAbort->ucNetTypeIndex, prMsgChAbort->ucTokenID); + + prCmdBody->ucNetTypeIndex = prMsgChAbort->ucNetTypeIndex; + prCmdBody->ucTokenID = prMsgChAbort->ucTokenID; + prCmdBody->ucAction = CMD_CH_ACTION_ABORT; /* Abort */ + + ASSERT(prCmdBody->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + /* For monkey testing 20110901 */ + if (prCmdBody->ucNetTypeIndex >= NETWORK_TYPE_INDEX_NUM) + DBGLOG(CNM, ERROR, "CNM: ChAbort with wrong netIdx=%d\n\n", prCmdBody->ucNetTypeIndex); + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_CH_PRIVILEGE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_CH_PRIVILEGE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdBody, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); + + cnmMemFree(prAdapter, prCmdBody); + cnmMemFree(prAdapter, prMsgHdr); + +} /* end of cnmChMngrAbortPrivilege() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmChMngrHandleChEvent(P_ADAPTER_T prAdapter, P_WIFI_EVENT_T prEvent) +{ + P_EVENT_CH_PRIVILEGE_T prEventBody; + P_MSG_CH_GRANT_T prChResp; + + ASSERT(prAdapter); + ASSERT(prEvent); + + prEventBody = (P_EVENT_CH_PRIVILEGE_T) (prEvent->aucBuffer); + prChResp = (P_MSG_CH_GRANT_T) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_GRANT_T)); + ASSERT(prChResp); + + /* To do: exception handle */ + if (!prChResp) { + DBGLOG(CNM, ERROR, "ChGrant: fail to get buf (net=%d, token=%d)\n", + prEventBody->ucNetTypeIndex, prEventBody->ucTokenID); + + return; + } + + DBGLOG(CNM, INFO, "ChGrant net=%d token=%d ch=%d sco=%d dur=%d\n", + prEventBody->ucNetTypeIndex, prEventBody->ucTokenID, + prEventBody->ucPrimaryChannel, prEventBody->ucRfSco, + prEventBody->u4GrantInterval); + + ASSERT(prEventBody->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + ASSERT(prEventBody->ucStatus == EVENT_CH_STATUS_GRANT); + + /* Decide message ID based on network and response status */ + if (prEventBody->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) + prChResp->rMsgHdr.eMsgId = MID_CNM_AIS_CH_GRANT; +#if CFG_ENABLE_WIFI_DIRECT + else if ((prAdapter->fgIsP2PRegistered) && (prEventBody->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX)) + prChResp->rMsgHdr.eMsgId = MID_CNM_P2P_CH_GRANT; +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (prEventBody->ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX) + prChResp->rMsgHdr.eMsgId = MID_CNM_BOW_CH_GRANT; +#endif + else { + cnmMemFree(prAdapter, prChResp); + return; + } + + prChResp->ucNetTypeIndex = prEventBody->ucNetTypeIndex; + prChResp->ucTokenID = prEventBody->ucTokenID; + prChResp->ucPrimaryChannel = prEventBody->ucPrimaryChannel; + prChResp->eRfSco = (ENUM_CHNL_EXT_T) prEventBody->ucRfSco; + prChResp->eRfBand = (ENUM_BAND_T) prEventBody->ucRfBand; + prChResp->eReqType = (ENUM_CH_REQ_TYPE_T) prEventBody->ucReqType; + prChResp->u4GrantInterval = prEventBody->u4GrantInterval; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prChResp, MSG_SEND_METHOD_BUF); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is invoked for P2P or BOW networks +* +* @param (none) +* +* @return TRUE: suggest to adopt the returned preferred channel +* FALSE: No suggestion. Caller should adopt its preference +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +cnmPreferredChannel(P_ADAPTER_T prAdapter, P_ENUM_BAND_T prBand, PUINT_8 pucPrimaryChannel, P_ENUM_CHNL_EXT_T prBssSCO) +{ + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(prBand); + ASSERT(pucPrimaryChannel); + ASSERT(prBssSCO); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + + if (RLM_NET_PARAM_VALID(prBssInfo)) { + *prBand = prBssInfo->eBand; + *pucPrimaryChannel = prBssInfo->ucPrimaryChannel; + *prBssSCO = prBssInfo->eBssSCO; + + return TRUE; + } + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param (none) +* +* @return TRUE: available channel is limited to return value +* FALSE: no limited +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN cnmAisInfraChannelFixed(P_ADAPTER_T prAdapter, P_ENUM_BAND_T prBand, PUINT_8 pucPrimaryChannel) +{ +#if CFG_ENABLE_WIFI_DIRECT || (CFG_ENABLE_BT_OVER_WIFI && CFG_BOW_LIMIT_AIS_CHNL) + P_BSS_INFO_T prBssInfo; +#endif + +#if CFG_ENABLE_WIFI_DIRECT + if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX) && p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) { + + ASSERT(prAdapter->fgIsP2PRegistered); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; + + *prBand = prBssInfo->eBand; + *pucPrimaryChannel = prBssInfo->ucPrimaryChannel; + + return TRUE; + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI && CFG_BOW_LIMIT_AIS_CHNL + if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX)) { + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]; + + *prBand = prBssInfo->eBand; + *pucPrimaryChannel = prBssInfo->ucPrimaryChannel; + + return TRUE; + } +#endif + + return FALSE; +} + +#if CFG_P2P_LEGACY_COEX_REVISE +BOOLEAN cnmAisDetectP2PChannel(P_ADAPTER_T prAdapter, P_ENUM_BAND_T prBand, PUINT_8 pucPrimaryChannel) +{ + P_WIFI_VAR_T prWifiVar = &prAdapter->rWifiVar; + P_BSS_INFO_T prP2PBssInfo = &prWifiVar->arBssInfo[NETWORK_TYPE_P2P_INDEX]; +#if CFG_ENABLE_WIFI_DIRECT + if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX) && + (prP2PBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED || + (prP2PBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT && prP2PBssInfo->eIntendOPMode == OP_MODE_NUM))) { + *prBand = prP2PBssInfo->eBand; + *pucPrimaryChannel = prP2PBssInfo->ucPrimaryChannel; +#if CFG_SUPPORT_MCC + if (nicFreq2ChannelNum(prWifiVar->rConnSettings.u4FreqInKHz * 1000) != *pucPrimaryChannel) { + DBGLOG(CNM, INFO, "p2p is running on Channel %d, but supplicant try to run as MCC\n", + *pucPrimaryChannel); + return FALSE; + } +#endif + DBGLOG(CNM, INFO, "p2p is running on Channel %d, supplicant try to run as SCC\n", + *pucPrimaryChannel); + return TRUE; + } +#endif + return FALSE; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmAisInfraConnectNotify(P_ADAPTER_T prAdapter) +{ +#if CFG_ENABLE_BT_OVER_WIFI + P_BSS_INFO_T prAisBssInfo, prBowBssInfo; + + prAisBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + prBowBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]; + + if (RLM_NET_PARAM_VALID(prAisBssInfo) && RLM_NET_PARAM_VALID(prBowBssInfo)) { + if (prAisBssInfo->eBand != prBowBssInfo->eBand || + prAisBssInfo->ucPrimaryChannel != prBowBssInfo->ucPrimaryChannel) { + + /* Notify BOW to do deactivation */ + bowNotifyAllLinkDisconnected(prAdapter); + } + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param (none) +* +* @return TRUE: permitted +* FALSE: Not permitted +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN cnmAisIbssIsPermitted(P_ADAPTER_T prAdapter) +{ +#if CFG_ENABLE_WIFI_DIRECT + if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX)) + return FALSE; +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX)) + return FALSE; +#endif + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param (none) +* +* @return TRUE: permitted +* FALSE: Not permitted +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN cnmP2PIsPermitted(P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prBssInfo; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + + if (IS_BSS_ACTIVE(prBssInfo) && prBssInfo->eCurrentOPMode == OP_MODE_IBSS) + return FALSE; +#if CFG_ENABLE_BT_OVER_WIFI + if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX)) { + /* Notify BOW to do deactivation */ + bowNotifyAllLinkDisconnected(prAdapter); + } +#endif + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param (none) +* +* @return TRUE: permitted +* FALSE: Not permitted +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN cnmBowIsPermitted(P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prBssInfo; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + + if (IS_BSS_ACTIVE(prBssInfo) && prBssInfo->eCurrentOPMode == OP_MODE_IBSS) + return FALSE; +#if CFG_ENABLE_WIFI_DIRECT + if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX)) + return FALSE; +#endif + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param (none) +* +* @return TRUE: permitted +* FALSE: Not permitted +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN cnmBss40mBwPermitted(P_ADAPTER_T prAdapter, ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx) +{ + P_BSS_DESC_T prBssDesc = NULL; +#if CONCURRENT_HT40_NOT_ALLOW + P_BSS_INFO_T prBssInfo; + UINT_8 i; +#endif +#if CFG_SUPPORT_CFG_FILE + P_WIFI_VAR_T prWifiVar = &(prAdapter->rWifiVar); +#endif + + /* 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 + */ + +#if CONCURRENT_HT40_NOT_ALLOW + 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; + } + } +#endif + + if (eNetTypeIdx == NETWORK_TYPE_AIS_INDEX) + prBssDesc = prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc; + else if ((eNetTypeIdx == NETWORK_TYPE_P2P_INDEX) && (prAdapter->rWifiVar.prP2pFsmInfo)) + prBssDesc = prAdapter->rWifiVar.prP2pFsmInfo->prTargetBss; + if (prBssDesc) { +#if CFG_SUPPORT_CFG_FILE + if (prWifiVar->ucCert11nMode == 1) { + DBGLOG(CNM, INFO, "cnmBss40mBwPermitted support Cert11n mode and allow BW40M\n"); + return TRUE; + } +#endif + +#if (CFG_FORCE_USE_20BW == 1) + if (prBssDesc->eBand == BAND_2G4) + return FALSE; +#endif + if (prBssDesc->eSco == CHNL_EXT_SCN) + return FALSE; + } + + return TRUE; +} + +VOID cnmRunEventReqChnlUtilTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr) +{ + P_CNM_INFO_T prCnmInfo = &prAdapter->rCnmInfo; + struct MSG_CH_UTIL_RSP *prMsgChUtil = NULL; + P_MSG_SCN_SCAN_REQ prScanReqMsg = NULL; + + DBGLOG(CNM, INFO, "Request Channel Utilization timeout\n"); + wlanReleasePendingCmdById(prAdapter, CMD_ID_REQ_CHNL_UTILIZATION); + prMsgChUtil = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(*prMsgChUtil)); + if (!prMsgChUtil) { + DBGLOG(CNM, ERROR, "No memory!"); + return; + } + kalMemZero(prMsgChUtil, sizeof(*prMsgChUtil)); + prMsgChUtil->rMsgHdr.eMsgId = prCnmInfo->u2ReturnMID; + prMsgChUtil->ucChnlNum = 0; + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T)prMsgChUtil, MSG_SEND_METHOD_BUF); + /* tell scan_fsm to continue to process scan request, if there's any pending */ + prScanReqMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(*prScanReqMsg)); + if (!prScanReqMsg) { + DBGLOG(CNM, ERROR, "prScanReqMsg: No memory!"); + return; + } + kalMemZero(prScanReqMsg, sizeof(*prScanReqMsg)); + prScanReqMsg->rMsgHdr.eMsgId = MID_MNY_CNM_SCAN_CONTINUE; + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T)prScanReqMsg, MSG_SEND_METHOD_BUF); +} + +VOID cnmHandleChannelUtilization(P_ADAPTER_T prAdapter, + struct EVENT_RSP_CHNL_UTILIZATION *prChnlUtil) +{ + P_CNM_INFO_T prCnmInfo = &prAdapter->rCnmInfo; + struct MSG_CH_UTIL_RSP *prMsgChUtil = NULL; + P_MSG_SCN_SCAN_REQ prScanReqMsg = NULL; + + if (!timerPendingTimer(&prCnmInfo->rReqChnlUtilTimer)) + return; + prMsgChUtil = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(*prMsgChUtil)); + if (!prMsgChUtil) { + DBGLOG(CNM, ERROR, "No memory!"); + return; + } + DBGLOG(CNM, INFO, "Receive Channel Utilization response\n"); + cnmTimerStopTimer(prAdapter, &prCnmInfo->rReqChnlUtilTimer); + kalMemZero(prMsgChUtil, sizeof(*prMsgChUtil)); + prMsgChUtil->rMsgHdr.eMsgId = prCnmInfo->u2ReturnMID; + prMsgChUtil->ucChnlNum = prChnlUtil->ucChannelNum; + kalMemCopy(prMsgChUtil->aucChnlList, prChnlUtil->aucChannelMeasureList, prChnlUtil->ucChannelNum); + kalMemCopy(prMsgChUtil->aucChUtil, prChnlUtil->aucChannelUtilization, prChnlUtil->ucChannelNum); + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T)prMsgChUtil, MSG_SEND_METHOD_BUF); + prScanReqMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(*prScanReqMsg)); + if (!prScanReqMsg) { + DBGLOG(CNM, ERROR, "prScanReqMsg: No memory!"); + return; + } + kalMemZero(prScanReqMsg, sizeof(*prScanReqMsg)); + prScanReqMsg->rMsgHdr.eMsgId = MID_MNY_CNM_SCAN_CONTINUE; + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T)prScanReqMsg, MSG_SEND_METHOD_BUF); +} + +VOID cnmRequestChannelUtilization(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_CNM_INFO_T prCnmInfo = &prAdapter->rCnmInfo; + struct MSG_REQ_CH_UTIL *prMsgReqChUtil = (struct MSG_REQ_CH_UTIL *)prMsgHdr; + struct CMD_REQ_CHNL_UTILIZATION rChnlUtilCmd; + + if (!prMsgReqChUtil) + return; + if (timerPendingTimer(&prCnmInfo->rReqChnlUtilTimer)) { + cnmMemFree(prAdapter, prMsgReqChUtil); + return; + } + DBGLOG(CNM, INFO, "Request Channel Utilization, channel count %d\n", prMsgReqChUtil->ucChnlNum); + kalMemZero(&rChnlUtilCmd, sizeof(rChnlUtilCmd)); + prCnmInfo->u2ReturnMID = prMsgReqChUtil->u2ReturnMID; + rChnlUtilCmd.u2MeasureDuration = prMsgReqChUtil->u2Duration; + if (prMsgReqChUtil->ucChnlNum > 9) + prMsgReqChUtil->ucChnlNum = 9; + rChnlUtilCmd.ucChannelNum = prMsgReqChUtil->ucChnlNum; + kalMemCopy(rChnlUtilCmd.aucChannelList, prMsgReqChUtil->aucChnlList, rChnlUtilCmd.ucChannelNum); + cnmMemFree(prAdapter, prMsgReqChUtil); + rStatus = wlanSendSetQueryCmd( + prAdapter, /* prAdapter */ + CMD_ID_REQ_CHNL_UTILIZATION,/* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + nicCmdEventSetCommon, /* pfCmdDoneHandler*/ + nicOidCmdTimeoutCommon, /* pfCmdTimeoutHandler */ + sizeof(rChnlUtilCmd),/* u4SetQueryInfoLen */ + (PUINT_8)&rChnlUtilCmd, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + cnmTimerStartTimer(prAdapter, &prCnmInfo->rReqChnlUtilTimer, 1000); +} + +BOOLEAN cnmChUtilIsRunning(P_ADAPTER_T prAdapter) +{ + return timerPendingTimer(&prAdapter->rCnmInfo.rReqChnlUtilTimer); +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/cnm_mem.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/cnm_mem.c new file mode 100644 index 0000000000000..a96b821e15cf4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/cnm_mem.c @@ -0,0 +1,912 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static VOID cnmStaRecHandleEventPkt(P_ADAPTER_T prAdapter, P_CMD_INFO_T prCmdInfo, PUINT_8 pucEventBuf); + +static VOID cnmStaSendUpdateCmd(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, BOOLEAN fgNeedResp); + +static VOID cnmStaSendRemoveCmd(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +P_MSDU_INFO_T cnmMgtPktAlloc(P_ADAPTER_T prAdapter, UINT_32 u4Length) +{ + P_MSDU_INFO_T prMsduInfo; + P_QUE_T prQueList; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prQueList = &prAdapter->rTxCtrl.rFreeMsduInfoList; + + /* Get a free MSDU_INFO_T */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + QUEUE_REMOVE_HEAD(prQueList, prMsduInfo, P_MSDU_INFO_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + + if (prMsduInfo) { + prMsduInfo->prPacket = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4Length); + prMsduInfo->eSrc = TX_PACKET_MGMT; + + if (prMsduInfo->prPacket == NULL) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + QUEUE_INSERT_TAIL(prQueList, &prMsduInfo->rQueEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + prMsduInfo = NULL; + } + if (prMsduInfo) { + prMsduInfo->eCmdType = COMMAND_TYPE_NUM; + prMsduInfo->ucCID = 0xff; + prMsduInfo->u4InqueTime = 0; + prMsduInfo->ucPacketType = TX_PACKET_NUM; + prMsduInfo->u4DbgTxPktStatusIndex = 0xffff; + } + } else { + P_QUE_T prTxingQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_MSDU_INFO_T prMsduInfo = (P_MSDU_INFO_T) NULL; + P_TX_TCQ_STATUS_T pTc = (P_TX_TCQ_STATUS_T) NULL; + + prTxingQue = &(prAdapter->rTxCtrl.rTxMgmtTxingQueue); + pTc = &(prAdapter->rTxCtrl.rTc); + + DBGLOG(MEM, LOUD, "++dump TxPendingMsdu=%u, Tc0=%d Tc1=%d Tc2=%d Tc3=%d, Tc4=%d Tc5=%d\n", + prTxingQue->u4NumElem, pTc->aucFreeBufferCount[TC0_INDEX], + pTc->aucFreeBufferCount[TC1_INDEX], pTc->aucFreeBufferCount[TC2_INDEX], + pTc->aucFreeBufferCount[TC3_INDEX], pTc->aucFreeBufferCount[TC4_INDEX], + pTc->aucFreeBufferCount[TC5_INDEX]); + + prQueueEntry = QUEUE_GET_HEAD(prTxingQue); + + while (prQueueEntry) { + prMsduInfo = (P_MSDU_INFO_T) prQueueEntry; + + DBGLOG(MEM, LOUD, + "msdu type=%u, ucid=%u, type=%d, time=%u, seq=%u, sta=%u\n", + prMsduInfo->ucPacketType, + prMsduInfo->ucCID, + prMsduInfo->eCmdType, + prMsduInfo->u4InqueTime, prMsduInfo->ucTxSeqNum, prMsduInfo->ucStaRecIndex); + prQueueEntry = QUEUE_GET_NEXT_ENTRY(prQueueEntry); + } + DBGLOG(MEM, LOUD, "--end dump\n"); + } + +#if DBG + if (prMsduInfo == NULL) { + DBGLOG(MEM, WARN, "MgtDesc#=%u\n", prQueList->u4NumElem); + +#if CFG_DBG_MGT_BUF + DBGLOG(MEM, WARN, "rMgtBufInfo: alloc#=%u, free#=%u, null#=%u\n", + prAdapter->rMgtBufInfo.u4AllocCount, + prAdapter->rMgtBufInfo.u4FreeCount, prAdapter->rMgtBufInfo.u4AllocNullCount); +#endif + + DBGLOG(MEM, WARN, "\n"); + } +#endif + + return prMsduInfo; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmMgtPktFree(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + P_QUE_T prQueList; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prQueList = &prAdapter->rTxCtrl.rFreeMsduInfoList; + + ASSERT(prMsduInfo->prPacket); + if (prMsduInfo->prPacket) { + cnmMemFree(prAdapter, prMsduInfo->prPacket); + prMsduInfo->prPacket = NULL; + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + prMsduInfo->fgIsBasicRate = FALSE; + QUEUE_INSERT_TAIL(prQueList, &prMsduInfo->rQueEntry) + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to initial the MGMT/MSG memory pool. +* +* \param (none) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmMemInit(P_ADAPTER_T prAdapter) +{ + P_BUF_INFO_T prBufInfo; + + /* Initialize Management buffer pool */ + prBufInfo = &prAdapter->rMgtBufInfo; + kalMemZero(prBufInfo, sizeof(prAdapter->rMgtBufInfo)); + prBufInfo->pucBuf = prAdapter->pucMgtBufCached; + + /* Setup available memory blocks. 1 indicates FREE */ + prBufInfo->rFreeBlocksBitmap = (BUF_BITMAP) BITS(0, MAX_NUM_OF_BUF_BLOCKS - 1); + + /* Initialize Message buffer pool */ + prBufInfo = &prAdapter->rMsgBufInfo; + kalMemZero(prBufInfo, sizeof(prAdapter->rMsgBufInfo)); + prBufInfo->pucBuf = &prAdapter->aucMsgBuf[0]; + + /* Setup available memory blocks. 1 indicates FREE */ + prBufInfo->rFreeBlocksBitmap = (BUF_BITMAP) BITS(0, MAX_NUM_OF_BUF_BLOCKS - 1); + + return; + +} /* end of cnmMemInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Allocate MGMT/MSG memory pool. +* +* \param[in] eRamType Target RAM type. +* TCM blk_sz= 16bytes, BUF blk_sz= 256bytes +* \param[in] u4Length Length of the buffer to allocate. +* +* \retval !NULL Pointer to the start address of allocated memory. +* \retval NULL Fail to allocat memory +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 u4MemAllocCnt = 0, u4MemFreeCnt = 0; +PVOID cnmMemAlloc(IN P_ADAPTER_T prAdapter, IN ENUM_RAM_TYPE_T eRamType, IN UINT_32 u4Length) +{ + P_BUF_INFO_T prBufInfo; + BUF_BITMAP rRequiredBitmap; + UINT_32 u4BlockNum; + UINT_32 i, u4BlkSz, u4BlkSzInPower; + PVOID pvMemory; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(u4Length); + + u4MemAllocCnt++; + + if (eRamType == RAM_TYPE_MSG && u4Length <= 256) { + prBufInfo = &prAdapter->rMsgBufInfo; + u4BlkSzInPower = MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2; + u4BlkSz = MSG_BUF_BLOCK_SIZE; + + u4BlockNum = (u4Length + u4BlkSz - 1) >> u4BlkSzInPower; + + ASSERT(u4BlockNum <= MAX_NUM_OF_BUF_BLOCKS); + } else { + eRamType = RAM_TYPE_BUF; + + prBufInfo = &prAdapter->rMgtBufInfo; + u4BlkSzInPower = MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2; + u4BlkSz = MGT_BUF_BLOCK_SIZE; + + u4BlockNum = (u4Length + u4BlkSz - 1) >> u4BlkSzInPower; + + 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); + + kalMemZero(prBufInfo->pucBuf + (i << u4BlkSzInPower), u4BlockNum*u4BlkSz); + /* Return the start address of allocated memory */ + return (PVOID) (prBufInfo->pucBuf + (i << u4BlkSzInPower)); + + } + + rRequiredBitmap <<= 1; + } + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF); + + /* cannot move the allocation between spin_lock_irqsave and spin_unlock_irqrestore */ +#ifdef LINUX + pvMemory = (PVOID) kalMemAlloc(u4Length, VIR_MEM_TYPE); + if (pvMemory) + kalMemZero(pvMemory, u4Length); +#else + pvMemory = (PVOID) NULL; +#endif + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF); + +#if CFG_DBG_MGT_BUF + prBufInfo->u4AllocNullCount++; + + if (pvMemory) + prAdapter->u4MemAllocDynamicCount++; +#endif + + KAL_RELEASE_SPIN_LOCK(prAdapter, eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF); + + return pvMemory; + +} /* end of cnmMemAlloc() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Release memory to MGT/MSG memory pool. +* +* \param pucMemory Start address of previous allocated memory +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmMemFree(IN P_ADAPTER_T prAdapter, IN PVOID pvMemory) +{ + P_BUF_INFO_T prBufInfo; + UINT_32 u4BlockIndex; + BUF_BITMAP rAllocatedBlocksBitmap; + ENUM_RAM_TYPE_T eRamType; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(pvMemory); + if (!pvMemory) + return; + + u4MemFreeCnt++; + + /* Judge it belongs to which RAM type */ + if (((ULONG) pvMemory >= (ULONG)&prAdapter->aucMsgBuf[0]) && + ((ULONG) pvMemory <= (ULONG)&prAdapter->aucMsgBuf[MSG_BUFFER_SIZE - 1])) { + + prBufInfo = &prAdapter->rMsgBufInfo; + u4BlockIndex = ((ULONG) pvMemory - (ULONG) prBufInfo->pucBuf) + >> MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2; + ASSERT(u4BlockIndex < MAX_NUM_OF_BUF_BLOCKS); + eRamType = RAM_TYPE_MSG; + } else if (((ULONG) pvMemory >= (ULONG) prAdapter->pucMgtBufCached) && + ((ULONG) pvMemory <= ((ULONG) prAdapter->pucMgtBufCached + MGT_BUFFER_SIZE - 1))) { + prBufInfo = &prAdapter->rMgtBufInfo; + u4BlockIndex = ((ULONG) pvMemory - (ULONG) prBufInfo->pucBuf) + >> MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2; + ASSERT(u4BlockIndex < MAX_NUM_OF_BUF_BLOCKS); + eRamType = RAM_TYPE_BUF; + } else { +#ifdef LINUX + /* For Linux, it is supported because size is not needed */ + kalMemFree(pvMemory, VIR_MEM_TYPE, 0); +#else + /* For Windows, it is not supported because of no size argument */ + ASSERT(0); +#endif + +#if CFG_DBG_MGT_BUF + prAdapter->u4MemFreeDynamicCount++; +#endif + return; + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF); + +#if CFG_DBG_MGT_BUF + prBufInfo->u4FreeCount++; +#endif + + /* Convert number of block into bit cluster */ + ASSERT(prBufInfo->aucAllocatedBlockNum[u4BlockIndex] > 0); + + rAllocatedBlocksBitmap = BITS(0, prBufInfo->aucAllocatedBlockNum[u4BlockIndex] - 1); + rAllocatedBlocksBitmap <<= u4BlockIndex; + + /* Clear saved block count for this memory segment */ + prBufInfo->aucAllocatedBlockNum[u4BlockIndex] = 0; + + /* Set corresponding bit of released memory block */ + prBufInfo->rFreeBlocksBitmap |= rAllocatedBlocksBitmap; + + KAL_RELEASE_SPIN_LOCK(prAdapter, eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF); + + return; + +} /* end of cnmMemFree() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmStaRecInit(P_ADAPTER_T prAdapter) +{ + P_STA_RECORD_T prStaRec; + UINT_16 i; + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + + prStaRec->ucIndex = (UINT_8) i; + prStaRec->fgIsInUse = FALSE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmStaRecUninit(IN P_ADAPTER_T prAdapter) +{ + P_STA_RECORD_T prStaRec; + UINT_16 i; + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + + if (prStaRec->fgIsInUse) + cnmStaRecFree(prAdapter, prStaRec, FALSE); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +P_STA_RECORD_T cnmStaRecAlloc(P_ADAPTER_T prAdapter, UINT_8 ucNetTypeIndex) +{ + P_STA_RECORD_T prStaRec; + UINT_16 i, k; + + ASSERT(prAdapter); + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + + if (!prStaRec->fgIsInUse) { + /*---- Initialize STA_REC_T here ----*/ + kalMemZero(prStaRec, sizeof(STA_RECORD_T)); + prStaRec->ucIndex = (UINT_8) i; + prStaRec->ucNetTypeIndex = ucNetTypeIndex; + prStaRec->fgIsInUse = TRUE; + prStaRec->fgIsTxAllowed = FALSE; + prStaRec->fgIsTxKeyReady = FALSE; + + if (prStaRec->pucAssocReqIe) { + kalMemFree(prStaRec->pucAssocReqIe, VIR_MEM_TYPE, prStaRec->u2AssocReqIeLen); + prStaRec->pucAssocReqIe = NULL; + prStaRec->u2AssocReqIeLen = 0; + } + + /* Initialize the SN caches for duplicate detection */ + for (k = 0; k < TID_NUM + 1; k++) + prStaRec->au2CachedSeqCtrl[k] = 0xFFFF; + + /* Initialize SW TX queues in STA_REC */ + for (k = 0; k < STA_WAIT_QUEUE_NUM; k++) + LINK_INITIALIZE(&prStaRec->arStaWaitQueue[k]); + + /* Default enable TX/RX AMPDU */ + prStaRec->fgTxAmpduEn = TRUE; + prStaRec->fgRxAmpduEn = TRUE; + +#if CFG_ENABLE_PER_STA_STATISTICS && CFG_ENABLE_PKT_LIFETIME_PROFILE + prStaRec->u4TotalTxPktsNumber = 0; + prStaRec->u4TotalTxPktsTime = 0; + prStaRec->u4MaxTxPktsTime = 0; +#endif + + for (k = 0; k < NUM_OF_PER_STA_TX_QUEUES; k++) + QUEUE_INITIALIZE(&prStaRec->arTxQueue[k]); + +#if DSCP_SUPPORT + qosMapSetInit(prStaRec); +#endif + 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); + cnmTimerStopTimer(prAdapter, &prStaRec->rDeauthTxDoneTimer); + prStaRec->fgTransmitKeyExist = FALSE; + prStaRec->fgSetPwrMgtBit = FALSE; + + if (prStaRec->pucAssocReqIe) { + kalMemFree(prStaRec->pucAssocReqIe, VIR_MEM_TYPE, prStaRec->u2AssocReqIeLen); + prStaRec->pucAssocReqIe = NULL; + prStaRec->u2AssocReqIeLen = 0; + } + + qmDeactivateStaRec(prAdapter, prStaRec->ucIndex); + + if (fgSyncToChip) + cnmStaSendRemoveCmd(prAdapter, prStaRec); + + prStaRec->fgIsInUse = FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmStaFreeAllStaByNetType(P_ADAPTER_T prAdapter, ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, BOOLEAN fgSyncToChip) +{ + P_STA_RECORD_T prStaRec; + UINT_16 i; + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = (P_STA_RECORD_T) &prAdapter->arStaRec[i]; + + if (prStaRec->fgIsInUse && prStaRec->ucNetTypeIndex == (UINT_8) eNetTypeIndex) + cnmStaRecFree(prAdapter, prStaRec, fgSyncToChip); + } /* end of for loop */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +P_STA_RECORD_T cnmGetStaRecByIndex(P_ADAPTER_T prAdapter, UINT_8 ucIndex) +{ + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + + prStaRec = (ucIndex < CFG_STA_REC_NUM) ? &prAdapter->arStaRec[ucIndex] : NULL; + + if (prStaRec && prStaRec->fgIsInUse == FALSE) { + DBGLOG(CNM, INFO, "[%pM] prStaRec->fgIsInUse = FALSE!\n", prStaRec->aucMacAddr); + 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 ((eNetTypeIndex == NETWORK_TYPE_AIS_INDEX) && IS_STA_IN_AIS(prStaRec->eStaType)) { + + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + prStaRec->u2ReasonCode = REASON_CODE_RESERVED; + prStaRec->ucJoinFailureCount = 0; + prStaRec->fgTransmitKeyExist = FALSE; + + prStaRec->fgSetPwrMgtBit = FALSE; + } + + /* TODO(Kevin): For P2P and BOW */ + } + } + + return; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will change the ucStaState of STA_RECORD_T and also do +* event indication to HOST to sync the STA_RECORD_T in driver. +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] u4NewState New STATE to change. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmStaRecChangeState(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, UINT_8 ucNewState) +{ + BOOLEAN fgNeedResp; + + ASSERT(prAdapter); + ASSERT(prStaRec); + ASSERT(prStaRec->fgIsInUse); + + /* Do nothing when following state transitions happen, + * other 6 conditions should be sync to FW, including 1-->1, 3-->3 + */ + if ((ucNewState == STA_STATE_2 && prStaRec->ucStaState != STA_STATE_3) || + (ucNewState == STA_STATE_1 && prStaRec->ucStaState == STA_STATE_2)) { + prStaRec->ucStaState = ucNewState; + return; + } + + fgNeedResp = FALSE; + if (ucNewState == STA_STATE_3) { + secFsmEventStart(prAdapter, prStaRec); + if (ucNewState != prStaRec->ucStaState) + fgNeedResp = TRUE; + } else { + if (ucNewState != prStaRec->ucStaState && prStaRec->ucStaState == STA_STATE_3) + qmDeactivateStaRec(prAdapter, prStaRec->ucIndex); + fgNeedResp = FALSE; + } + prStaRec->ucStaState = ucNewState; + + cnmStaSendUpdateCmd(prAdapter, prStaRec, fgNeedResp); + +#if CFG_ENABLE_WIFI_DIRECT + /* To do: Confirm if it is invoked here or other location, but it should + * be invoked after state sync of STA_REC + * Update system operation parameters for AP mode + */ + if (prAdapter->fgIsP2PRegistered && (IS_STA_IN_P2P(prStaRec))) { + P_BSS_INFO_T prBssInfo; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; + + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) + rlmUpdateParamsForAP(prAdapter, prBssInfo, FALSE); + } +#endif +} + +P_STA_RECORD_T +cnmStaTheTypeGet(P_ADAPTER_T prAdapter, + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, ENUM_STA_TYPE_T eStaType, UINT32 *pu4StartIdx) +{ + P_STA_RECORD_T prStaRec = NULL; + UINT_16 i; + + for (i = *pu4StartIdx; i < CFG_STA_REC_NUM; i++) { + prStaRec = (P_STA_RECORD_T) &prAdapter->arStaRec[i]; + + if (prStaRec->fgIsInUse && + prStaRec->ucNetTypeIndex == (UINT_8) eNetTypeIndex && prStaRec->eStaType == eStaType) { + i++; + break; + } + + prStaRec = NULL; /* reset */ + } /* end of for loop */ + + *pu4StartIdx = i; + return prStaRec; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID cnmStaRecHandleEventPkt(P_ADAPTER_T prAdapter, P_CMD_INFO_T prCmdInfo, PUINT_8 pucEventBuf) +{ + P_EVENT_ACTIVATE_STA_REC_T prEventContent; + P_STA_RECORD_T prStaRec; + + prEventContent = (P_EVENT_ACTIVATE_STA_REC_T) pucEventBuf; + prStaRec = cnmGetStaRecByIndex(prAdapter, prEventContent->ucStaRecIdx); + + if (prStaRec && prStaRec->ucStaState == STA_STATE_3 && + !kalMemCmp(&prStaRec->aucMacAddr[0], &prEventContent->aucMacAddr[0], MAC_ADDR_LEN)) { + + qmActivateStaRec(prAdapter, prStaRec); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID cnmStaSendUpdateCmd(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, BOOLEAN fgNeedResp) +{ + P_CMD_UPDATE_STA_RECORD_T prCmdContent; + WLAN_STATUS rStatus; + + ASSERT(prAdapter); + ASSERT(prStaRec); + ASSERT(prStaRec->fgIsInUse); + + /* To do: come out a mechanism to limit one STA_REC sync once for AP mode + * to avoid buffer empty case when many STAs are associated + * simultaneously. + */ + + /* To do: how to avoid 2 times of allocated memory. Use Stack? + * One is here, the other is in wlanSendQueryCmd() + */ + prCmdContent = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_UPDATE_STA_RECORD_T)); + ASSERT(prCmdContent); + + /* To do: exception handle */ + if (!prCmdContent) + return; + + prCmdContent->ucIndex = prStaRec->ucIndex; + prCmdContent->ucStaType = (UINT_8) prStaRec->eStaType; + kalMemCopy(&prCmdContent->aucMacAddr[0], &prStaRec->aucMacAddr[0], MAC_ADDR_LEN); + prCmdContent->u2AssocId = prStaRec->u2AssocId; + prCmdContent->u2ListenInterval = prStaRec->u2ListenInterval; + prCmdContent->ucNetTypeIndex = prStaRec->ucNetTypeIndex; + + prCmdContent->ucDesiredPhyTypeSet = prStaRec->ucDesiredPhyTypeSet; + prCmdContent->u2DesiredNonHTRateSet = prStaRec->u2DesiredNonHTRateSet; + prCmdContent->u2BSSBasicRateSet = prStaRec->u2BSSBasicRateSet; + prCmdContent->ucMcsSet = prStaRec->ucMcsSet; + prCmdContent->ucSupMcs32 = (UINT_8) prStaRec->fgSupMcs32; + prCmdContent->u2HtCapInfo = prStaRec->u2HtCapInfo; + prCmdContent->ucNeedResp = (UINT_8) fgNeedResp; + +#if !CFG_SLT_SUPPORT + if (prAdapter->rWifiVar.eRateSetting != FIXED_RATE_NONE) { + /* override rate configuration */ + nicUpdateRateParams(prAdapter, + prAdapter->rWifiVar.eRateSetting, + &(prCmdContent->ucDesiredPhyTypeSet), + &(prCmdContent->u2DesiredNonHTRateSet), + &(prCmdContent->u2BSSBasicRateSet), + &(prCmdContent->ucMcsSet), + &(prCmdContent->ucSupMcs32), &(prCmdContent->u2HtCapInfo)); + } +#endif + + prCmdContent->ucIsQoS = prStaRec->fgIsQoS; + prCmdContent->ucIsUapsdSupported = prStaRec->fgIsUapsdSupported; + prCmdContent->ucStaState = prStaRec->ucStaState; + + prCmdContent->ucAmpduParam = prStaRec->ucAmpduParam; + prCmdContent->u2HtExtendedCap = prStaRec->u2HtExtendedCap; + prCmdContent->u4TxBeamformingCap = prStaRec->u4TxBeamformingCap; + prCmdContent->ucAselCap = prStaRec->ucAselCap; + prCmdContent->ucRCPI = prStaRec->ucRCPI; + + prCmdContent->ucUapsdAc = prStaRec->ucBmpTriggerAC | (prStaRec->ucBmpDeliveryAC << 4); + prCmdContent->ucUapsdSp = prStaRec->ucUapsdSp; + /* if AP's max idle time is greater than 30s, then we send keep alive packets every 30 sec */ + prCmdContent->ucKeepAliveDuration = (UINT_8)prStaRec->u2MaxIdlePeriod; + prCmdContent->ucKeepAliveOption = prStaRec->ucIdleOption; + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + prCmdContent->ucApplyPmf = prStaRec->rPmfCfg.fgApplyPmf; +#endif + + if (prCmdContent->ucKeepAliveDuration > 0) + DBGLOG(CNM, INFO, "keep-alive duration is %d\n", prCmdContent->ucKeepAliveDuration); + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_UPDATE_STA_RECORD, /* ucCID */ + TRUE, /* fgSetQuery */ + fgNeedResp, /* fgNeedResp */ + FALSE, /* fgIsOid */ + fgNeedResp ? cnmStaRecHandleEventPkt : NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_UPDATE_STA_RECORD_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); + + cnmMemFree(prAdapter, prCmdContent); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID cnmStaSendRemoveCmd(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec) +{ + CMD_REMOVE_STA_RECORD_T rCmdContent; + WLAN_STATUS rStatus; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + rCmdContent.ucIndex = prStaRec->ucIndex; + kalMemCopy(&rCmdContent.aucMacAddr[0], &prStaRec->aucMacAddr[0], MAC_ADDR_LEN); + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_REMOVE_STA_RECORD, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_REMOVE_STA_RECORD_T), /* u4SetQueryInfoLen */ + (PUINT_8) &rCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/cnm_timer.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/cnm_timer.c new file mode 100644 index 0000000000000..e7c14a33c1b93 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/cnm_timer.c @@ -0,0 +1,416 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the time to do the time out check. +* +* \param[in] rTimeout Time out interval from current time. +* +* \retval TRUE Success. +* +*/ +/*----------------------------------------------------------------------------*/ +static BOOLEAN cnmTimerSetTimer(IN P_ADAPTER_T prAdapter, IN OS_SYSTIME rTimeout) +{ + P_ROOT_TIMER prRootTimer; + BOOLEAN fgNeedWakeLock; + + ASSERT(prAdapter); + + prRootTimer = &prAdapter->rRootTimer; + + kalSetTimer(prAdapter->prGlueInfo, rTimeout); + + if (rTimeout <= SEC_TO_SYSTIME(WAKE_LOCK_MAX_TIME)) { + fgNeedWakeLock = TRUE; + + if (!prRootTimer->fgWakeLocked) { + KAL_WAKE_LOCK(prAdapter, prRootTimer->rWakeLock); + prRootTimer->fgWakeLocked = TRUE; + } + } else { + fgNeedWakeLock = FALSE; + } + + return fgNeedWakeLock; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routines is called to initialize a root timer. +* +* \param[in] prAdapter +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmTimerInitialize(IN P_ADAPTER_T prAdapter) +{ + P_ROOT_TIMER prRootTimer; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prRootTimer = &prAdapter->rRootTimer; + + /* Note: glue layer have configured timer */ + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + LINK_INITIALIZE(&prRootTimer->rLinkHead); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + + KAL_WAKE_LOCK_INIT(prAdapter, prRootTimer->rWakeLock, "WLAN Timer"); + prRootTimer->fgWakeLocked = FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routines is called to destroy a root timer. +* When WIFI is off, the token shall be returned back to system. +* +* \param[in] +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmTimerDestroy(IN P_ADAPTER_T prAdapter) +{ + P_ROOT_TIMER prRootTimer; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prRootTimer = &prAdapter->rRootTimer; + + if (prRootTimer->fgWakeLocked) { + KAL_WAKE_UNLOCK(prAdapter, prRootTimer->rWakeLock); + prRootTimer->fgWakeLocked = FALSE; + } + KAL_WAKE_LOCK_DESTROY(prAdapter, prRootTimer->rWakeLock); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + LINK_INITIALIZE(&prRootTimer->rLinkHead); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + + /* Note: glue layer will be responsible for timer destruction */ + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routines is called to initialize a timer. +* +* \param[in] prTimer Pointer to a timer structure. +* \param[in] pfnFunc Pointer to the call back function. +* \param[in] u4Data Parameter for call back function. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmTimerInitTimer(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer, IN PFN_MGMT_TIMEOUT_FUNC pfFunc, IN ULONG ulData) +{ + ASSERT(prAdapter); + + ASSERT(prTimer); + +#if DBG + /* Note: NULL function pointer is permitted for HEM POWER */ + if (pfFunc == NULL) + DBGLOG(CNM, WARN, "Init timer with NULL callback function!\n"); +#endif + +#if DBG + ASSERT(prAdapter->rRootTimer.rLinkHead.prNext); + { + P_LINK_T prTimerList; + P_LINK_ENTRY_T prLinkEntry; + P_TIMER_T prPendingTimer; + + prTimerList = &(prAdapter->rRootTimer.rLinkHead); + + LINK_FOR_EACH(prLinkEntry, prTimerList) { + prPendingTimer = LINK_ENTRY(prLinkEntry, TIMER_T, rLinkEntry); + ASSERT(prPendingTimer); + ASSERT(prPendingTimer != prTimer); + } + } +#endif + + LINK_ENTRY_INITIALIZE(&prTimer->rLinkEntry); + + prTimer->pfMgmtTimeOutFunc = pfFunc; + prTimer->ulData = ulData; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routines is called to stop a timer. +* +* \param[in] prTimer Pointer to a timer structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID cnmTimerStopTimer_impl(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer, IN BOOLEAN fgAcquireSpinlock) +{ + P_ROOT_TIMER prRootTimer; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prTimer); + + prRootTimer = &prAdapter->rRootTimer; + + if (fgAcquireSpinlock) + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + + if (timerPendingTimer(prTimer)) { + LINK_REMOVE_KNOWN_ENTRY(&prRootTimer->rLinkHead, &prTimer->rLinkEntry); + + /* Reduce dummy timeout for power saving, especially HIF activity. + * If two or more timers exist and being removed timer is smallest, + * this dummy timeout will still happen, but it is OK. + */ + if (LINK_IS_EMPTY(&prRootTimer->rLinkHead)) { + kalCancelTimer(prAdapter->prGlueInfo); + + if (fgAcquireSpinlock && prRootTimer->fgWakeLocked) { + KAL_WAKE_UNLOCK(prAdapter, prRootTimer->rWakeLock); + prRootTimer->fgWakeLocked = FALSE; + } + } + } + + if (fgAcquireSpinlock) + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routines is called to stop a timer. +* +* \param[in] prTimer Pointer to a timer structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmTimerStopTimer(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer) +{ + ASSERT(prAdapter); + ASSERT(prTimer); + + cnmTimerStopTimer_impl(prAdapter, prTimer, TRUE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routines is called to start a timer with wake_lock. +* +* \param[in] prTimer Pointer to a timer structure. +* \param[in] u4TimeoutMs Timeout to issue the timer and call back function +* (unit: ms). +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmTimerStartTimer(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer, IN UINT_32 u4TimeoutMs) +{ + P_ROOT_TIMER prRootTimer; + P_LINK_T prTimerList; + OS_SYSTIME rExpiredSysTime, rTimeoutSystime; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prTimer); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + + prRootTimer = &prAdapter->rRootTimer; + prTimerList = &prRootTimer->rLinkHead; + + /* If timeout interval is larger than 1 minute, the mod value is set + * to the timeout value first, then per minutue. + */ + if (u4TimeoutMs > MSEC_PER_MIN) { + ASSERT(u4TimeoutMs <= ((UINT_32) 0xFFFF * MSEC_PER_MIN)); + + prTimer->u2Minutes = (UINT_16) (u4TimeoutMs / MSEC_PER_MIN); + u4TimeoutMs -= (prTimer->u2Minutes * MSEC_PER_MIN); + if (u4TimeoutMs == 0) { + u4TimeoutMs = MSEC_PER_MIN; + prTimer->u2Minutes--; + } + } else { + prTimer->u2Minutes = 0; + } + + /* The assertion check if MSEC_TO_SYSTIME() may be overflow. */ + ASSERT(u4TimeoutMs < (((UINT_32) 0x80000000 - MSEC_PER_SEC) / KAL_HZ)); + rTimeoutSystime = MSEC_TO_SYSTIME(u4TimeoutMs); + rExpiredSysTime = kalGetTimeTick() + rTimeoutSystime; + + /* If no timer pending or the fast time interval is used. */ + if (LINK_IS_EMPTY(prTimerList) || TIME_BEFORE(rExpiredSysTime, prRootTimer->rNextExpiredSysTime)) { + + prRootTimer->rNextExpiredSysTime = rExpiredSysTime; + cnmTimerSetTimer(prAdapter, rTimeoutSystime); + } + + /* Add this timer to checking list */ + prTimer->rExpiredSysTime = rExpiredSysTime; + + if (!timerPendingTimer(prTimer)) + LINK_INSERT_TAIL(prTimerList, &prTimer->rLinkEntry); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routines is called to check the timer list. +* +* \param[in] +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmTimerDoTimeOutCheck(IN P_ADAPTER_T prAdapter) +{ + P_ROOT_TIMER prRootTimer; + P_LINK_T prTimerList; + P_LINK_ENTRY_T prLinkEntry; + P_TIMER_T prTimer; + OS_SYSTIME rCurSysTime; + PFN_MGMT_TIMEOUT_FUNC pfMgmtTimeOutFunc; + ULONG ulTimeoutData; + BOOLEAN fgNeedWakeLock; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + /* acquire spin lock */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + + prRootTimer = &prAdapter->rRootTimer; + prTimerList = &prRootTimer->rLinkHead; + + rCurSysTime = kalGetTimeTick(); + + /* Set the permitted max timeout value for new one */ + prRootTimer->rNextExpiredSysTime = rCurSysTime + MGMT_MAX_TIMEOUT_INTERVAL; + + LINK_FOR_EACH(prLinkEntry, prTimerList) { + prTimer = LINK_ENTRY(prLinkEntry, TIMER_T, rLinkEntry); + ASSERT(prTimer); + + /* Check if this entry is timeout. */ + if (!TIME_BEFORE(rCurSysTime, prTimer->rExpiredSysTime)) { + cnmTimerStopTimer_impl(prAdapter, prTimer, FALSE); + + pfMgmtTimeOutFunc = prTimer->pfMgmtTimeOutFunc; + ulTimeoutData = prTimer->ulData; + + if (prTimer->u2Minutes > 0) { + prTimer->u2Minutes--; + prTimer->rExpiredSysTime = rCurSysTime + MSEC_TO_SYSTIME(MSEC_PER_MIN); + LINK_INSERT_TAIL(prTimerList, &prTimer->rLinkEntry); + } else if (pfMgmtTimeOutFunc) { + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + (pfMgmtTimeOutFunc) (prAdapter, ulTimeoutData); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + } + + /* Search entire list again because of nest del and add timers + * and current MGMT_TIMER could be volatile after stopped + */ + prLinkEntry = (P_LINK_ENTRY_T) prTimerList; + + prRootTimer->rNextExpiredSysTime = rCurSysTime + MGMT_MAX_TIMEOUT_INTERVAL; + } else if (TIME_BEFORE(prTimer->rExpiredSysTime, prRootTimer->rNextExpiredSysTime)) { + prRootTimer->rNextExpiredSysTime = prTimer->rExpiredSysTime; + } + } /* end of for loop */ + + /* Setup the prNext timeout event. It is possible the timer was already + * set in the above timeout callback function. + */ + fgNeedWakeLock = FALSE; + if (!LINK_IS_EMPTY(prTimerList)) { + ASSERT(TIME_AFTER(prRootTimer->rNextExpiredSysTime, rCurSysTime)); + + fgNeedWakeLock = cnmTimerSetTimer(prAdapter, (OS_SYSTIME) + ((INT_32) prRootTimer->rNextExpiredSysTime - (INT_32) rCurSysTime)); + } + + if (prRootTimer->fgWakeLocked && !fgNeedWakeLock) { + KAL_WAKE_UNLOCK(prAdapter, prRootTimer->rWakeLock); + prRootTimer->fgWakeLocked = FALSE; + } + + /* release spin lock */ + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/hem_mbox.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/hem_mbox.c new file mode 100644 index 0000000000000..cf0533636073e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/hem_mbox.c @@ -0,0 +1,524 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E 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_OID_SAA_FSM_CONTINUE"), + (PUINT_8) DISP_STRING("MID_OID_SAA_FSM_EXTERNAL_AUTH"), + (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_MGMT_FRAME_UPDATE"), + (PUINT_8) DISP_STRING("MID_MNY_P2P_EXTEND_LISTEN_INTERVAL"), +#if CFG_SUPPORT_P2P_ECSA + (PUINT_8) DISP_STRING("MID_MNY_P2P_CSA"), + (PUINT_8) DISP_STRING("MID_MNY_P2P_ECSA"), +#endif +#if CFG_SUPPORT_WFD + (PUINT_8) DISP_STRING("MID_MNY_P2P_WFD_CFG_UPDATE"), +#endif +#endif + +#if CFG_SUPPORT_ADHOC + /* (PUINT_8)DISP_STRING("MID_AIS_CNM_CREATE_IBSS_REQ"), */ + /* (PUINT_8)DISP_STRING("MID_CNM_AIS_CREATE_IBSS_GRANT"), */ + /* (PUINT_8)DISP_STRING("MID_AIS_CNM_MERGE_IBSS_REQ"), */ + /* (PUINT_8)DISP_STRING("MID_CNM_AIS_MERGE_IBSS_GRANT"), */ + (PUINT_8) DISP_STRING("MID_SCN_AIS_FOUND_IBSS"), +#endif /* CFG_SUPPORT_ADHOC */ + + (PUINT_8) DISP_STRING("MID_SAA_AIS_FSM_ABORT"), + (PUINT_8) DISP_STRING("MID_MNY_AIS_REMAIN_ON_CHANNEL"), + (PUINT_8) DISP_STRING("MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL"), + (PUINT_8) DISP_STRING("MID_MNY_AIS_MGMT_TX"), + (PUINT_8) DISP_STRING("MID_MNY_CNM_REQ_CH_UTIL"), + (PUINT_8) DISP_STRING("MID_CNM_AIS_RSP_CH_UTIL"), + (PUINT_8) DISP_STRING("MID_MNY_CNM_SCAN_CONTINUE"), + (PUINT_8) DISP_STRING("MID_WNM_AIS_BSS_TRANSITION"), + (PUINT_8) DISP_STRING("MID_OID_WMM_TSPEC_OPERATE"), + (PUINT_8) DISP_STRING("MID_RLM_RM_SCHEDULE"), +#if CFG_SUPPORT_NCHO + (PUINT_8) DISP_STRING("MID_MNY_AIS_NCHO_ACTION_FRAME"), +#endif + (PUINT_8) DISP_STRING("MID_MNY_P2P_ACS"), +}; + +/*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_OID_SAA_FSM_CONTINUE, saaFsmRunEventFTContinue}, + {MID_OID_SAA_FSM_EXTERNAL_AUTH, saaFsmRunEventExternalAuthDone}, + {MID_AIS_SAA_FSM_ABORT, saaFsmRunEventAbort}, + {MID_SAA_AIS_JOIN_COMPLETE, aisFsmRunEventJoinComplete}, + +#if CFG_ENABLE_BT_OVER_WIFI + /*--------------------------------------------------*/ + /* BOW Module Mailbox Messages */ + /*--------------------------------------------------*/ + {MID_BOW_SAA_FSM_START, saaFsmRunEventStart}, + {MID_BOW_SAA_FSM_ABORT, saaFsmRunEventAbort}, + {MID_SAA_BOW_JOIN_COMPLETE, bowFsmRunEventJoinComplete}, +#endif + +#if CFG_ENABLE_WIFI_DIRECT /*set in gl_p2p_init.c */ + {MID_P2P_SAA_FSM_START, saaFsmRunEventStart}, + {MID_P2P_SAA_FSM_ABORT, saaFsmRunEventAbort}, + {MID_SAA_P2P_JOIN_COMPLETE, p2pFsmRunEventJoinComplete}, /* TODO: p2pFsmRunEventJoinComplete */ + + {MID_MNY_P2P_FUN_SWITCH, p2pFsmRunEventSwitchOPMode}, + {MID_MNY_P2P_DEVICE_DISCOVERY, p2pFsmRunEventScanRequest}, + {MID_MNY_P2P_CONNECTION_REQ, p2pFsmRunEventConnectionRequest}, + {MID_MNY_P2P_CONNECTION_ABORT, p2pFsmRunEventConnectionAbort}, + {MID_MNY_P2P_BEACON_UPDATE, p2pFsmRunEventBeaconUpdate}, + {MID_MNY_P2P_STOP_AP, p2pFsmRunEventStopAP}, + {MID_MNY_P2P_CHNL_REQ, p2pFsmRunEventChannelRequest}, + {MID_MNY_P2P_CHNL_ABORT, p2pFsmRunEventChannelAbort}, + {MID_MNY_P2P_MGMT_TX, p2pFsmRunEventMgmtFrameTx}, + {MID_MNY_P2P_GROUP_DISSOLVE, p2pFsmRunEventDissolve}, + {MID_MNY_P2P_MGMT_FRAME_REGISTER, p2pFsmRunEventMgmtFrameRegister}, + {MID_MNY_P2P_NET_DEV_REGISTER, p2pFsmRunEventNetDeviceRegister}, + {MID_MNY_P2P_START_AP, p2pFsmRunEventStartAP}, + {MID_MNY_P2P_MGMT_FRAME_UPDATE, p2pFsmRunEventUpdateMgmtFrame}, + {MID_MNY_P2P_EXTEND_LISTEN_INTERVAL, p2pFsmRunEventExtendListen}, +#if CFG_SUPPORT_P2P_ECSA + {MID_MNY_P2P_CSA, p2pFsmRunEventSendCSA}, + {MID_MNY_P2P_ECSA, p2pFsmRunEventSendECSA}, +#endif +#if CFG_SUPPORT_WFD + {MID_MNY_P2P_WFD_CFG_UPDATE, p2pFsmRunEventWfdSettingUpdate}, +#endif + +#endif + +#if CFG_SUPPORT_ADHOC + {MID_SCN_AIS_FOUND_IBSS, aisFsmRunEventFoundIBSSPeer}, +#endif /* CFG_SUPPORT_ADHOC */ + + {MID_SAA_AIS_FSM_ABORT, aisFsmRunEventAbort}, + {MID_MNY_AIS_REMAIN_ON_CHANNEL, aisFsmRunEventRemainOnChannel}, + {MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL, aisFsmRunEventCancelRemainOnChannel}, + {MID_MNY_AIS_MGMT_TX, aisFsmRunEventMgmtFrameTx}, + {MID_MNY_CNM_REQ_CH_UTIL, cnmRequestChannelUtilization}, + {MID_CNM_AIS_RSP_CH_UTIL, aisRunEventChnlUtilRsp}, + {MID_MNY_CNM_SCAN_CONTINUE, scnFsmMsgStart}, + {MID_WNM_AIS_BSS_TRANSITION, aisFsmRunEventBssTransition}, + {MID_OID_WMM_TSPEC_OPERATE, wmmRunEventTSOperate}, + {MID_RLM_RM_SCHEDULE, rlmRunEventProcessNextRm}, +#if CFG_SUPPORT_NCHO + {MID_MNY_AIS_NCHO_ACTION_FRAME, aisFsmRunEventNchoActionFrameTx}, +#endif + {MID_MNY_P2P_ACS, p2pFsmRunEventAcs}, +}; + +/******************************************************************************* +* 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; +#if CFG_DBG_MGT_BUF + P_BUF_INFO_T prBufInfo; +#endif + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(eMboxId < MBOX_ID_TOTAL_NUM); + ASSERT(prMsg); + ASSERT(prAdapter); +#if CFG_DBG_MGT_BUF + prBufInfo = &prAdapter->rMgtBufInfo; + DBGLOG(CNM, TRACE, "MSG [%d],freeCnt:%d,AllocCnt:%d\n", prMsg->eMsgId + , prBufInfo->u4FreeCount, prBufInfo->u4AllocCount); +#endif + prMbox = &(prAdapter->arMbox[eMboxId]); + + switch (eMethod) { + case MSG_SEND_METHOD_BUF: + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); + LINK_INSERT_TAIL(&prMbox->rLinkHead, &prMsg->rLinkEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); + + /* to wake up main service thread */ + GLUE_SET_EVENT(prAdapter->prGlueInfo); + + break; + + case MSG_SEND_METHOD_UNBUF: + MBOX_HNDL_MSG(prAdapter, prMsg); + break; + + default: + ASSERT(0); + break; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mboxRcvAllMsg(IN P_ADAPTER_T prAdapter, ENUM_MBOX_ID_T eMboxId) +{ + P_MBOX_T prMbox; + P_MSG_HDR_T prMsg; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(eMboxId < MBOX_ID_TOTAL_NUM); + ASSERT(prAdapter); + + prMbox = &(prAdapter->arMbox[eMboxId]); + + while (!LINK_IS_EMPTY(&prMbox->rLinkHead)) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); + LINK_REMOVE_HEAD(&prMbox->rLinkHead, prMsg, P_MSG_HDR_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); + + ASSERT(prMsg); + MBOX_HNDL_MSG(prAdapter, prMsg); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mboxInitialize(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i; + + ASSERT(prAdapter); + + /* Initialize Mailbox */ + mboxInitMsgMap(); + + /* Setup/initialize each mailbox */ + for (i = 0; i < MBOX_ID_TOTAL_NUM; i++) + mboxSetup(prAdapter, i); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mboxDestroy(IN P_ADAPTER_T prAdapter) +{ + P_MBOX_T prMbox; + P_MSG_HDR_T prMsg; + UINT_8 i; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + for (i = 0; i < MBOX_ID_TOTAL_NUM; i++) { + prMbox = &(prAdapter->arMbox[i]); + + while (!LINK_IS_EMPTY(&prMbox->rLinkHead)) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); + LINK_REMOVE_HEAD(&prMbox->rLinkHead, prMsg, P_MSG_HDR_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); + + ASSERT(prMsg); + cnmMemFree(prAdapter, prMsg); + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is dummy function to prevent empty arMsgMapTable[] for compiling. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mboxDummy(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + ASSERT(prAdapter); + + cnmMemFree(prAdapter, prMsgHdr); + +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/hs20.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/hs20.c new file mode 100644 index 0000000000000..75a5a263b028f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/hs20.c @@ -0,0 +1,437 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +#if CFG_SUPPORT_HOTSPOT_2_0 + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +VOID hs20FillExtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo) +{ + P_HS20_EXT_CAP_T prExtCap; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + /* Add Extended Capabilities IE */ + prExtCap = (P_HS20_EXT_CAP_T) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + + prExtCap->ucId = ELEM_ID_EXTENDED_CAP; + if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) + prExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + else + prExtCap->ucLength = 3 - ELEM_HDR_LEN; + + kalMemZero(prExtCap->aucCapabilities, prExtCap->ucLength); + + prExtCap->aucCapabilities[0] = ELEM_EXT_CAP_DEFAULT_VAL; + + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + prExtCap->aucCapabilities[0] &= ~ELEM_EXT_CAP_PSMP_CAP; + + if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) { + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_BSS_TRANSITION_BIT); + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_UTC_TSF_OFFSET_BIT); + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_INTERWORKING_BIT); + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_QOSMAPSET_BIT); + + /* For R2 WNM-Notification */ + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_WNM_NOTIFICATION_BIT); + } + kalPrint("IE_SIZE(prExtCap) = %d, %d %d\n", IE_SIZE(prExtCap), ELEM_HDR_LEN, ELEM_MAX_LEN_EXT_CAP); + ASSERT(IE_SIZE(prExtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP)); + + prMsduInfo->u2FrameLength += IE_SIZE(prExtCap); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to fill up the content of Ext Cap IE bit 31. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[out] pucIE Pointer of the IE buffer +* +* \return VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID hs20FillProreqExtCapIE(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucIE) +{ + P_HS20_EXT_CAP_T prExtCap; + + ASSERT(prAdapter); + + /* Add Extended Capabilities IE */ + prExtCap = (P_HS20_EXT_CAP_T) pucIE; + + prExtCap->ucId = ELEM_ID_EXTENDED_CAP; + if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) + prExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + else + prExtCap->ucLength = 3 - ELEM_HDR_LEN; + + kalMemZero(prExtCap->aucCapabilities, prExtCap->ucLength); + + prExtCap->aucCapabilities[0] = ELEM_EXT_CAP_DEFAULT_VAL; + + if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) { + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_BSS_TRANSITION_BIT); + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_UTC_TSF_OFFSET_BIT); + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_INTERWORKING_BIT); + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_QOSMAPSET_BIT); + + /* For R2 WNM-Notification */ + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_WNM_NOTIFICATION_BIT); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to fill up the content of HS2.0 IE. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[out] pucIE Pointer of the IE buffer +* +* \return VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID hs20FillHS20IE(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucIE) +{ + P_IE_HS20_INDICATION_T prHS20IndicationIe; + /* P_HS20_INFO_T prHS20Info; */ + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + + /* prHS20Info = &(prAdapter->rWifiVar.rHS20Info); */ + + prHS20IndicationIe = (P_IE_HS20_INDICATION_T) pucIE; + + prHS20IndicationIe->ucId = ELEM_ID_VENDOR; + prHS20IndicationIe->ucLength = sizeof(IE_HS20_INDICATION_T) - ELEM_HDR_LEN; + prHS20IndicationIe->aucOui[0] = aucWfaOui[0]; + prHS20IndicationIe->aucOui[1] = aucWfaOui[1]; + prHS20IndicationIe->aucOui[2] = aucWfaOui[2]; + prHS20IndicationIe->ucType = VENDOR_OUI_TYPE_HS20; + prHS20IndicationIe->ucHotspotConfig = 0x00; /* prHS20Info->ucHotspotConfig; */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called while calculating length of hotspot 2.0 indication IE for Probe Request. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[in] pucTargetBSSID Pointer of target HESSID +* +* \return the length of composed HS20 IE +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 hs20CalculateHS20RelatedIEForProbeReq(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucTargetBSSID) +{ + UINT_32 u4IeLength; + + if (0) /* Todo:: Not HS20 STA */ + return 0; + + u4IeLength = + sizeof(IE_HS20_INDICATION_T) + /* sizeof(IE_INTERWORKING_T) */ + (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP); + + if (!pucTargetBSSID) { + /* Do nothing */ + /* u4IeLength -= MAC_ADDR_LEN; */ + } + + return u4IeLength; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called while composing hotspot 2.0 indication IE for Probe Request. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[in] pucTargetBSSID Pointer of target HESSID +* \param[out] prIE Pointer of the IE buffer +* +* \return the wlan status +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS hs20GenerateHS20RelatedIEForProbeReq(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucTargetBSSID, OUT PUINT_8 prIE) +{ + if (0) /* Todo:: Not HS20 STA */ + return 0; +#if 0 + P_HS20_INFO_T prHS20Info; + + prHS20Info = &(prAdapter->rWifiVar.rHS20Info); + + /* + * Generate 802.11u Interworking IE (107) + */ + hs20FillInterworkingIE(prAdapter, + prHS20Info->ucAccessNetworkOptions, + prHS20Info->ucVenueGroup, prHS20Info->ucVenueType, pucTargetBSSID, prIE); + prIE += IE_SIZE(prIE); +#endif + /* + * Generate Ext Cap IE (127) + */ + hs20FillProreqExtCapIE(prAdapter, prIE); + prIE += IE_SIZE(prIE); + + /* + * Generate HS2.0 Indication IE (221) + */ + hs20FillHS20IE(prAdapter, prIE); + prIE += IE_SIZE(prIE); + + return WLAN_STATUS_SUCCESS; +} + +BOOLEAN hs20IsGratuitousArp(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prCurrSwRfb) +{ + PUINT_8 pucSenderIP = prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + ARP_SENDER_IP_OFFSET; + PUINT_8 pucTargetIP = prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + ARP_TARGET_IP_OFFSET; + PUINT_8 pucSenderMac = ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + ARP_SNEDER_MAC_OFFSET); +#if CFG_HS20_DEBUG && 0 +/* UINT_8 aucIpAllZero[4] = {0,0,0,0}; */ +/* UINT_8 aucMACAllZero[MAC_ADDR_LEN] = {0,0,0,0,0,0}; */ + PUINT_8 pucTargetMac = ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + ARP_TARGET_MAC_OFFSET); +#endif + +#if CFG_HS20_DEBUG && 0 + PUINT_16 pu2ArpOper = (PUINT_16) ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + ARP_OPERATION_OFFSET); + + kalPrint("Recv ARP 0x%04X\n", htons(*pu2ArpOper)); + kalPrint("SENDER[ %pM ] [%pI4]\n", pucSenderMac, pucSenderIP); + kalPrint("TARGET[ %pM ] [%pI4]\n", pucTargetMac, pucTargetIP); +#endif + + /* IsGratuitousArp */ + if (!kalMemCmp(pucSenderIP, pucTargetIP, 4)) { + kalPrint("Drop Gratuitous ARP from [ %pM ] [%pI4]\n", pucSenderMac, pucTargetIP); + return TRUE; + } + return FALSE; +} + +BOOLEAN hs20IsUnsolicitedNeighborAdv(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prCurrSwRfb) +{ + PUINT_8 pucIpv6Protocol = ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + IPV6_HDR_IP_PROTOCOL_OFFSET); + + /* kalPrint("pucIpv6Protocol [%02X:%02X]\n", *pucIpv6Protocol, IPV6_PROTOCOL_ICMPV6); */ + if (*pucIpv6Protocol == IPV6_PROTOCOL_ICMPV6) { + PUINT_8 pucICMPv6Type = + ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + IPV6_HDR_LEN + ICMPV6_TYPE_OFFSET); + /* kalPrint("pucICMPv6Type [%02X:%02X]\n", *pucICMPv6Type, ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT); */ + if (*pucICMPv6Type == ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT) { + PUINT_8 pucICMPv6Flag = + ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + IPV6_HDR_LEN + ICMPV6_FLAG_OFFSET); + PUINT_8 pucSrcMAC = ((PUINT_8) prCurrSwRfb->pvHeader + MAC_ADDR_LEN); + +#if CFG_HS20_DEBUG + kalPrint("NAdv Flag [%02X] [R(%d)\\S(%d)\\O(%d)]\n", + *pucICMPv6Flag, + (UINT_8) (*pucICMPv6Flag & ICMPV6_FLAG_ROUTER_BIT) >> 7, + (UINT_8) (*pucICMPv6Flag & ICMPV6_FLAG_SOLICITED_BIT) >> 6, + (UINT_8) (*pucICMPv6Flag & ICMPV6_FLAG_OVERWRITE_BIT) >> 5); +#endif + if (!(*pucICMPv6Flag & ICMPV6_FLAG_SOLICITED_BIT)) { + kalPrint("Drop Unsolicited Neighbor Advertisement from [%pM]\n", pucSrcMAC); + return TRUE; + } + } + } + + return FALSE; +} + +#if CFG_ENABLE_GTK_FRAME_FILTER +BOOLEAN hs20IsForgedGTKFrame(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_SW_RFB_T prCurrSwRfb) +{ + /* + * P_CONNECTION_SETTINGS_T prConnSettings = &prAdapter->rWifiVar.rConnSettings; + * PUINT_8 pucEthDestAddr = prCurrSwRfb->pvHeader; + */ + /* 3 TODO: Need to verify this function before enable it */ + return FALSE; +#if 0 + if ((prConnSettings->eEncStatus != ENUM_ENCRYPTION_DISABLED) && IS_BMCAST_MAC_ADDR(pucEthDestAddr)) { + UINT_8 ucIdx = 0; + PUINT_32 prIpAddr, prPacketDA; + PUINT_16 pu2PktIpVer = + (PUINT_16) ((PUINT_8) prCurrSwRfb->pvHeader + (ETHER_HEADER_LEN - ETHER_TYPE_LEN)); + + if (*pu2PktIpVer == htons(ETH_P_IPV4)) { + if (!prBssInfo->prIpV4NetAddrList) + return FALSE; + for (ucIdx = 0; ucIdx < prBssInfo->prIpV4NetAddrList->ucAddrCount; ucIdx++) { + prIpAddr = (PUINT_32) &prBssInfo->prIpV4NetAddrList->arNetAddr[ucIdx].aucIpAddr[0]; + prPacketDA = + (PUINT_32) ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + + IPV4_HDR_IP_DST_ADDR_OFFSET); + + if (kalMemCmp(prIpAddr, prPacketDA, 4) == 0) { + kalPrint("Drop FORGED IPv4 packet\n"); + return TRUE; + } + } + } +#ifdef CONFIG_IPV6 + else if (*pu2PktIpVer == htons(ETH_P_IPV6)) { + UINT_8 aucIPv6Mac[MAC_ADDR_LEN]; + PUINT_8 pucIdx = + prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + IPV6_HDR_IP_DST_ADDR_MAC_HIGH_OFFSET; + + kalMemCopy(&aucIPv6Mac[0], pucIdx, 3); + pucIdx += 5; + kalMemCopy(&aucIPv6Mac[3], pucIdx, 3); + kalPrint("Get IPv6 frame Dst IP MAC part %pM\n", aucIPv6Mac); + if (EQUAL_MAC_ADDR(aucIPv6Mac, prBssInfo->aucOwnMacAddr)) { + kalPrint("Drop FORGED IPv6 packet\n"); + return TRUE; + } + } +#endif + } + + return FALSE; +#endif +} +#endif + +BOOLEAN hs20IsUnsecuredFrame(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_SW_RFB_T prCurrSwRfb) +{ + PUINT_16 pu2PktIpVer = (PUINT_16) ((PUINT_8) prCurrSwRfb->pvHeader + (ETHER_HEADER_LEN - ETHER_TYPE_LEN)); + + /* kalPrint("IPVER 0x%4X\n", htons(*pu2PktIpVer)); */ +#if CFG_HS20_DEBUG & 0 + UINT_8 i = 0; + + kalPrint("==============================================="); + for (i = 0; i < 96; i++) { + if (!(i % 16)) + kalPrint("\n"); + kalPrint("%02X ", *((PUINT_8) prCurrSwRfb->pvHeader + i)); + } + kalPrint("\n"); +#endif + +#if CFG_ENABLE_GTK_FRAME_FILTER + if (hs20IsForgedGTKFrame(prAdapter, prBssInfo, prCurrSwRfb)) + return TRUE; + +#endif + if (*pu2PktIpVer == htons(ETH_P_ARP)) + return hs20IsGratuitousArp(prAdapter, prCurrSwRfb); + else if (*pu2PktIpVer == htons(ETH_P_IPV6)) + return hs20IsUnsolicitedNeighborAdv(prAdapter, prCurrSwRfb); + + return FALSE; +} + +BOOLEAN hs20IsFrameFilterEnabled(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo) +{ +#if 1 + if (prAdapter->prGlueInfo->fgConnectHS20AP) + return TRUE; +#else + PARAM_SSID_T rParamSsid; + P_BSS_DESC_T prBssDesc; + + rParamSsid.u4SsidLen = prBssInfo->ucSSIDLen; + COPY_SSID(rParamSsid.aucSsid, rParamSsid.u4SsidLen, prBssInfo->aucSSID, prBssInfo->ucSSIDLen); + + prBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, prBssInfo->aucBSSID, TRUE, &rParamSsid); + if (!prBssDesc) + return FALSE; + + if (prBssDesc->fgIsSupportHS20) { + if (!(prBssDesc->ucHotspotConfig & ELEM_HS_CONFIG_DGAF_DISABLED_MASK)) + return TRUE; + + /* Disable frame filter only if DGAF == 1 */ + return FALSE; + + } +#endif + + /* For Now, always return true to run hs20 check even for legacy AP */ + return TRUE; +} + +WLAN_STATUS hs20SetBssidPool(IN P_ADAPTER_T prAdapter, IN PVOID pvBuffer, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx) +{ + P_PARAM_HS20_SET_BSSID_POOL prParamBssidPool = (P_PARAM_HS20_SET_BSSID_POOL) pvBuffer; + P_HS20_INFO_T prHS20Info; + UINT_8 ucIdx; + + prHS20Info = &(prAdapter->rWifiVar.rHS20Info); + kalPrint("[%s]Set Bssid Pool! enable[%d] num[%d]\n", __func__, prParamBssidPool->fgIsEnable, + prParamBssidPool->ucNumBssidPool); + for (ucIdx = 0; ucIdx < prParamBssidPool->ucNumBssidPool; ucIdx++) { + COPY_MAC_ADDR(prHS20Info->arBssidPool[ucIdx].aucBSSID, &prParamBssidPool->arBSSID[ucIdx]); + kalPrint("[%s][%d][ %pM ]\n", __func__, ucIdx, (prHS20Info->arBssidPool[ucIdx].aucBSSID)); + } + prHS20Info->fgIsHS2SigmaMode = prParamBssidPool->fgIsEnable; + prHS20Info->ucNumBssidPoolEntry = prParamBssidPool->ucNumBssidPool; + +#if 0 + wlanClearScanningResult(prAdapter); +#endif + + return WLAN_STATUS_SUCCESS; +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/mib.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/mib.c new file mode 100644 index 0000000000000..6c0677eb28a99 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/mib.c @@ -0,0 +1,92 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +NON_HT_PHY_ATTRIBUTE_T rNonHTPhyAttributes[] = { + {RATE_SET_HR_DSSS, TRUE, FALSE} + , /* For PHY_TYPE_HR_DSSS_INDEX(0) */ + {RATE_SET_ERP, TRUE, TRUE} + , /* For PHY_TYPE_ERP_INDEX(1) */ + {RATE_SET_ERP_P2P, TRUE, TRUE} + , /* For PHY_TYPE_ERP_P2P_INDEX(2) */ + {RATE_SET_OFDM, FALSE, FALSE} + , /* For PHY_TYPE_OFDM_INDEX(3) */ +}; + +NON_HT_ADHOC_MODE_ATTRIBUTE_T rNonHTAdHocModeAttributes[AD_HOC_MODE_NUM] = { + {PHY_TYPE_HR_DSSS_INDEX, BASIC_RATE_SET_HR_DSSS} + , /* For AD_HOC_MODE_11B(0) */ + {PHY_TYPE_ERP_INDEX, BASIC_RATE_SET_HR_DSSS_ERP} + , /* For AD_HOC_MODE_MIXED_11BG(1) */ + {PHY_TYPE_ERP_INDEX, BASIC_RATE_SET_ERP} + , /* For AD_HOC_MODE_11G(2) */ + {PHY_TYPE_OFDM_INDEX, BASIC_RATE_SET_OFDM} + , /* For AD_HOC_MODE_11A(3) */ +}; + +NON_HT_AP_MODE_ATTRIBUTE_T rNonHTApModeAttributes[AP_MODE_NUM] = { + {PHY_TYPE_HR_DSSS_INDEX, BASIC_RATE_SET_HR_DSSS} + , /* For AP_MODE_11B(0) */ + {PHY_TYPE_ERP_INDEX, BASIC_RATE_SET_HR_DSSS_ERP} + , /* For AP_MODE_MIXED_11BG(1) */ + {PHY_TYPE_ERP_INDEX, BASIC_RATE_SET_ERP} + , /* For AP_MODE_11G(2) */ + {PHY_TYPE_ERP_P2P_INDEX, BASIC_RATE_SET_ERP_P2P} + , /* For AP_MODE_11G_P2P(3) */ + {PHY_TYPE_OFDM_INDEX, BASIC_RATE_SET_OFDM} + , /* For AP_MODE_11A(4) */ +}; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_assoc.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_assoc.c new file mode 100644 index 0000000000000..4bc252f937fde --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_assoc.c @@ -0,0 +1,90 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to compose Common Information Elements for P2P Association +* Request Frame. +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +PUINT_8 p2pBuildReAssocReqFrameCommonIEs(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN PUINT_8 pucBuffer) +{ + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; + + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + /* Fill the SSID element. */ + SSID_IE(pucBuffer)->ucId = ELEM_ID_SSID; + + /* NOTE(Kevin): We copy the SSID from CONNECTION_SETTINGS for the case of + * Passive Scan and the target BSS didn't broadcast SSID on its Beacon Frame. + */ + + COPY_SSID(SSID_IE(pucBuffer)->aucSSID, + SSID_IE(pucBuffer)->ucLength, prP2pConnSettings->aucSSID, prP2pConnSettings->ucSSIDLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + return pucBuffer; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_bss.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_bss.c new file mode 100644 index 0000000000000..d4c6a5d7a67db --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_bss.c @@ -0,0 +1,59 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_fsm.c new file mode 100644 index 0000000000000..0fe3c316efcc1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_fsm.c @@ -0,0 +1,3045 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +#if CFG_ENABLE_WIFI_DIRECT + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if DBG +/*lint -save -e64 Type mismatch */ +static PUINT_8 apucDebugP2pState[P2P_STATE_NUM] = { + (PUINT_8) DISP_STRING("P2P_STATE_IDLE"), + (PUINT_8) DISP_STRING("P2P_STATE_SCAN"), + (PUINT_8) DISP_STRING("P2P_STATE_AP_CHANNEL_DETECT"), + (PUINT_8) DISP_STRING("P2P_STATE_REQING_CHANNEL"), + (PUINT_8) DISP_STRING("P2P_STATE_CHNL_ON_HAND"), + (PUINT_8) DISP_STRING("P2P_STATE_GC_JOIN") +}; + +/*lint -restore */ +#else +static UINT_8 apucDebugP2pState[P2P_STATE_NUM] = { + P2P_STATE_IDLE, + P2P_STATE_SCAN, + P2P_STATE_AP_CHANNEL_DETECT, + P2P_STATE_REQING_CHANNEL, + P2P_STATE_CHNL_ON_HAND, + P2P_STATE_GC_JOIN +}; + +#endif /* DBG */ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static VOID p2pFsmCheckDeauthComplete(IN P_ADAPTER_T prAdapter); +static u_int8_t p2pFsmIsAcsProcessing(IN P_ADAPTER_T prAdapter); +static void p2pFsmAbortCurrentAcsReq(IN P_ADAPTER_T prAdapter, + IN struct MSG_P2P_ACS_REQUEST *prMsgAcsRequest); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/* p2pStateXXX : Processing P2P FSM related action. + * p2pFSMXXX : Control P2P FSM flow. + * p2pFuncXXX : Function for doing one thing. + */ +VOID p2pFsmInit(IN P_ADAPTER_T prAdapter) +{ + + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + ASSERT_BREAK(prP2pFsmInfo != NULL); + + LINK_INITIALIZE(&(prP2pFsmInfo->rMsgEventQueue)); + LINK_INITIALIZE(&(prP2pBssInfo->rStaRecOfClientList)); + + prP2pFsmInfo->eCurrentState = prP2pFsmInfo->ePreviousState = P2P_STATE_IDLE; + prP2pFsmInfo->prTargetBss = NULL; + prP2pFsmInfo->fgIsWPSMode = 0; + + cnmTimerInitTimer(prAdapter, + &(prAdapter->rP2pFsmTimeoutTimer), + (PFN_MGMT_TIMEOUT_FUNC) p2pFsmRunEventFsmTimeout, (ULONG) prP2pFsmInfo); + cnmTimerInitTimer(prAdapter, + &(prAdapter->rTdlsStateTimer), + (PFN_MGMT_TIMEOUT_FUNC) p2pFsmRunEventTdlsTimeout, (ULONG) NULL); + + /* 4 <2> Initiate BSS_INFO_T - common part */ + BSS_INFO_INIT(prAdapter, NETWORK_TYPE_P2P_INDEX); + + /* init add key action */ + prP2pBssInfo->eKeyAction = SEC_TX_KEY_COMMAND; + + /* 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 CFG_SUPPORT_P2P_EAP_FAIL_WORKAROUND + prP2pBssInfo->fgP2PPendingDeauth = FALSE; + prP2pBssInfo->u4P2PEapTxDoneTime = 0; +#endif + if (prAdapter->rWifiVar.fgSupportQoS) + prP2pBssInfo->fgIsQBSS = TRUE; + else + prP2pBssInfo->fgIsQBSS = FALSE; + + SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_P2P_INDEX); + + if (prP2pFsmInfo->fgIsApMode) + p2pFuncSwitchOPMode(prAdapter, prP2pBssInfo, + OP_MODE_P2P_DEVICE, TRUE); + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + } while (FALSE); + +} /* p2pFsmInit */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief The function is used to uninitialize the value in P2P_FSM_INFO_T for +* P2P FSM operation +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFsmUninit(IN P_ADAPTER_T prAdapter) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + DEBUGFUNC("p2pFsmUninit()"); + DBGLOG(P2P, INFO, "->p2pFsmUninit()\n"); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + p2pFuncSwitchOPMode(prAdapter, prP2pBssInfo, OP_MODE_P2P_DEVICE, TRUE); + + p2pFsmRunEventAbort(prAdapter, prP2pFsmInfo); + + p2pStateAbort_IDLE(prAdapter, prP2pFsmInfo, P2P_STATE_NUM); + + UNSET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); + + wlanAcquirePowerControl(prAdapter); + + p2pFunCleanQueuedMgmtFrame(prAdapter, + &prP2pFsmInfo->rQueuedActionFrame); + + /* Release all pending CMD queue. */ + DBGLOG(P2P, TRACE, "p2pFsmUninit: wlanProcessCommandQueue, num of element:%d\n", + (UINT_32) prAdapter->prGlueInfo->rCmdQueue.u4NumElem); + wlanProcessCommandQueue(prAdapter, &prAdapter->prGlueInfo->rCmdQueue); + + wlanReleasePowerControl(prAdapter); + + /* Release pending mgmt frame, + * mgmt frame may be pending by CMD without resource. + */ + kalClearMgmtFramesByNetType(prAdapter->prGlueInfo, NETWORK_TYPE_P2P_INDEX); + + /* Clear PendingCmdQue */ + wlanReleasePendingCMDbyNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); + + if (prP2pBssInfo->prBeacon) { + cnmMgtPktFree(prAdapter, prP2pBssInfo->prBeacon); + prP2pBssInfo->prBeacon = NULL; + } + + } while (FALSE); + + return; + +} /* end of p2pFsmUninit() */ + +VOID p2pFsmStateTransition(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN ENUM_P2P_STATE_T eNextState) +{ + BOOLEAN fgIsTransOut = (BOOLEAN) FALSE; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + + ASSERT((prAdapter != NULL) && (prP2pFsmInfo != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + do { + if (!IS_BSS_ACTIVE(prP2pBssInfo)) { + if (!cnmP2PIsPermitted(prAdapter)) + return; + +#if !CFG_SUPPORT_RLM_ACT_NETWORK + SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); + nicActivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); + nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); +#else + rlmActivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX, NET_ACTIVE_SRC_NONE); +#endif + } + + fgIsTransOut = fgIsTransOut ? FALSE : TRUE; + + if (!fgIsTransOut) { +#if DBG + DBGLOG(P2P, STATE, "TRANSITION: [%s] -> [%s]\n", + apucDebugP2pState[prP2pFsmInfo->eCurrentState], + apucDebugP2pState[eNextState]); +#else + DBGLOG(P2P, STATE, "[%d] TRANSITION: [%d] -> [%d]\n", + DBG_P2P_IDX, apucDebugP2pState[prP2pFsmInfo->eCurrentState], + apucDebugP2pState[eNextState]); +#endif + + /* Transition into current state. */ + prP2pFsmInfo->ePreviousState = prP2pFsmInfo->eCurrentState; + prP2pFsmInfo->eCurrentState = eNextState; + } + + switch (prP2pFsmInfo->eCurrentState) { + case P2P_STATE_IDLE: + if (fgIsTransOut) + p2pStateAbort_IDLE(prAdapter, prP2pFsmInfo, eNextState); + else + fgIsTransOut = p2pStateInit_IDLE(prAdapter, prP2pFsmInfo, prP2pBssInfo, &eNextState); + break; + case P2P_STATE_SCAN: + if (fgIsTransOut) { + /* Scan done / scan canceled. */ + p2pStateAbort_SCAN(prAdapter, prP2pFsmInfo, eNextState); + } else { + /* Initial scan request. */ + p2pStateInit_SCAN(prAdapter, prP2pFsmInfo); + } + + break; + case P2P_STATE_AP_CHANNEL_DETECT: + if (fgIsTransOut) { + /* Scan done */ + /* Get sparse channel result. */ + p2pStateAbort_AP_CHANNEL_DETECT(prAdapter, + prP2pFsmInfo, prP2pSpecificBssInfo, eNextState); + } + + else { + /* Initial passive scan request. */ + p2pStateInit_AP_CHANNEL_DETECT(prAdapter, prP2pFsmInfo); + } + + break; + case P2P_STATE_REQING_CHANNEL: + if (fgIsTransOut) { + /* Channel on hand / Channel canceled. */ + p2pStateAbort_REQING_CHANNEL(prAdapter, prP2pFsmInfo, eNextState); + } else { + /* Initial channel request. */ + p2pFuncAcquireCh(prAdapter, &(prP2pFsmInfo->rChnlReqInfo)); + } + + break; + case P2P_STATE_CHNL_ON_HAND: + if (fgIsTransOut) { + p2pStateAbort_CHNL_ON_HAND(prAdapter, prP2pFsmInfo, prP2pBssInfo, eNextState); + } else { + /* Initial channel ready. */ + /* Send channel ready event. */ + /* Start a FSM timer. */ + p2pStateInit_CHNL_ON_HAND(prAdapter, prP2pBssInfo, prP2pFsmInfo); + } + + break; + case P2P_STATE_GC_JOIN: + if (fgIsTransOut) { + /* Join complete / join canceled. */ + p2pStateAbort_GC_JOIN(prAdapter, prP2pFsmInfo, &(prP2pFsmInfo->rJoinInfo), eNextState); + } else { + if (prP2pFsmInfo->prTargetBss == NULL) { + ASSERT(FALSE); + } else { + /* Send request to SAA module. */ + p2pStateInit_GC_JOIN(prAdapter, + prP2pFsmInfo, + prP2pBssInfo, + &(prP2pFsmInfo->rJoinInfo), prP2pFsmInfo->prTargetBss); + } + } + + break; + default: + break; + } + + } while (fgIsTransOut); + +} /* p2pFsmStateTransition */ + +VOID p2pFsmRunEventSwitchOPMode(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_MSG_P2P_SWITCH_OP_MODE_T prSwitchOpMode = (P_MSG_P2P_SWITCH_OP_MODE_T) prMsgHdr; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; + P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo = (P_P2P_CONNECTION_REQ_INFO_T) NULL; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_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; + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + prConnReqInfo = prP2pFsmInfo != NULL ? + &(prP2pFsmInfo->rConnReqInfo) : NULL; + + if (prSwitchOpMode == NULL) + break; + + if (prSwitchOpMode->eOpMode >= OP_MODE_NUM) { + ASSERT(FALSE); + break; + } + + /* P2P Device / GC. */ + p2pFuncSwitchOPMode(prAdapter, prP2pBssInfo, prSwitchOpMode->eOpMode, TRUE); + + if (prConnReqInfo && + prP2pBssInfo->eIftype == IFTYPE_P2P_CLIENT && + prSwitchOpMode->eIftype == IFTYPE_STATION) + kalP2pUnlinkBss(prAdapter->prGlueInfo, + prConnReqInfo->aucBssid); + + prP2pBssInfo->eIftype = prSwitchOpMode->eIftype; + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pFsmRunEventSwitchOPMode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to handle scan done event during Device Discovery. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFsmRunEventScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_P2P_SCAN_REQ_INFO_T prScanReqInfo = (P_P2P_SCAN_REQ_INFO_T) NULL; + P_MSG_SCN_SCAN_DONE prScanDoneMsg = (P_MSG_SCN_SCAN_DONE) NULL; + ENUM_P2P_STATE_T eNextState = P2P_STATE_NUM; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + /* This scan done event is either for "SCAN" phase or "SEARCH" state or "LISTEN" state. + * The scan done for SCAN phase & SEARCH state doesn't imply Device + * Discovery over. + */ + DBGLOG(P2P, TRACE, "P2P Scan Done Event\n"); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) + break; + + prScanReqInfo = &(prP2pFsmInfo->rScanReqInfo); + prScanDoneMsg = (P_MSG_SCN_SCAN_DONE) prMsgHdr; + + if (prScanDoneMsg->ucSeqNum != prScanReqInfo->ucSeqNumOfScnMsg) { + /* Scan Done message sequence number mismatch. + * Ignore this event. (P2P FSM issue two scan events.) + */ + /* The scan request has been cancelled. + * Ignore this message. It is possible. + */ + DBGLOG(P2P, TRACE, "P2P Scan Don SeqNum:%d <-> P2P Fsm SCAN Msg:%d\n", + prScanDoneMsg->ucSeqNum, prScanReqInfo->ucSeqNumOfScnMsg); + + break; + } + + switch (prP2pFsmInfo->eCurrentState) { + case P2P_STATE_SCAN: + { + P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo = &(prP2pFsmInfo->rConnReqInfo); + + prScanReqInfo->fgIsAbort = FALSE; + + if (prConnReqInfo->fgIsConnRequest) { + prP2pFsmInfo->prTargetBss = p2pFuncKeepOnConnection(prAdapter, + &prP2pFsmInfo->rConnReqInfo, + &prP2pFsmInfo->rChnlReqInfo, + &prP2pFsmInfo->rScanReqInfo); + if (prP2pFsmInfo->prTargetBss == NULL) + eNextState = P2P_STATE_SCAN; + else + eNextState = P2P_STATE_REQING_CHANNEL; + } else if (prScanReqInfo->fgIsAcsReq == TRUE) { + struct P2P_ACS_REQ_INFO *prAcsReqInfo; + + prAcsReqInfo = &prP2pFsmInfo->rAcsReqInfo; + prScanReqInfo->fgIsAcsReq = FALSE; + p2pFunCalAcsChnScores(prAdapter, + BAND_2G4); + if (wlanQueryLteSafeChannel(prAdapter) == + WLAN_STATUS_SUCCESS) { + /* do nothing & wait for FW event */ + } else { + DBGLOG(P2P, WARN, "query safe chn fail.\n"); + p2pFunProcessAcsReport(prAdapter, + NULL, + prAcsReqInfo); + } + eNextState = P2P_STATE_IDLE; + } else { + eNextState = P2P_STATE_IDLE; + } + + } + break; + case P2P_STATE_AP_CHANNEL_DETECT: + eNextState = P2P_STATE_REQING_CHANNEL; + break; + default: + /* Unexpected channel scan done event without being chanceled. */ + ASSERT(FALSE); + break; + } + + prScanReqInfo->fgIsScanRequest = FALSE; + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, eNextState); + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pFsmRunEventScanDone */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is call when channel is granted by CNM module from FW. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFsmRunEventChGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; + P_MSG_CH_GRANT_T prMsgChGrant = (P_MSG_CH_GRANT_T) NULL; + UINT_8 ucTokenID = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + DBGLOG(P2P, TRACE, "P2P Run Event Channel Grant\n"); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) + break; + + prMsgChGrant = (P_MSG_CH_GRANT_T) prMsgHdr; + ucTokenID = prMsgChGrant->ucTokenID; + prP2pFsmInfo->u4GrantInterval = prMsgChGrant->u4GrantInterval; + + /* Reset p2p conn state & channel extended flag */ + prP2pFsmInfo->fgIsChannelExtended = FALSE; + prP2pFsmInfo->eCNNState = P2P_CNN_NORMAL; + + prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); + + if (ucTokenID == prChnlReqInfo->ucSeqNumOfChReq) { + ENUM_P2P_STATE_T eNextState = P2P_STATE_NUM; + + switch (prP2pFsmInfo->eCurrentState) { + case P2P_STATE_REQING_CHANNEL: + switch (prChnlReqInfo->eChannelReqType) { + case CHANNEL_REQ_TYPE_REMAIN_ON_CHANNEL: + eNextState = P2P_STATE_CHNL_ON_HAND; + break; + case CHANNEL_REQ_TYPE_GC_JOIN_REQ: + eNextState = P2P_STATE_GC_JOIN; + break; + case CHANNEL_REQ_TYPE_GO_START_BSS: + eNextState = P2P_STATE_IDLE; + break; + default: + break; + } + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, eNextState); + break; + default: + /* Channel is granted under unexpected state. + * Driver should cancel channel privileagea before leaving the states. + */ + ASSERT(FALSE); + break; + } + + } else { + /* Channel requsted, but released. */ + /* ASSERT(!prChnlReqInfo->fgIsChannelRequested); */ + DBGLOG(P2P, TRACE, "Channel requsted, but released\n"); + } + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + + return; + +} /* p2pFsmRunEventChGrant */ + +VOID p2pFsmRunEventChannelRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; + P_MSG_P2P_CHNL_REQUEST_T prP2pChnlReqMsg = (P_MSG_P2P_CHNL_REQUEST_T) NULL; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + ENUM_P2P_STATE_T eNextState = P2P_STATE_NUM; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prP2pChnlReqMsg = (P_MSG_P2P_CHNL_REQUEST_T) prMsgHdr; + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) + break; + + prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); + + DBGLOG(P2P, TRACE, "p2pFsmRunEventChannelRequest\n"); + + /* Make sure the state is in IDLE state. */ + p2pFsmRunEventAbort(prAdapter, prP2pFsmInfo); + + /* Cookie can only be assign after abort.(for indication) */ + prChnlReqInfo->u8Cookie = prP2pChnlReqMsg->u8Cookie; + prChnlReqInfo->ucReqChnlNum = prP2pChnlReqMsg->rChannelInfo.ucChannelNum; + prChnlReqInfo->eBand = prP2pChnlReqMsg->rChannelInfo.eBand; + prChnlReqInfo->eChnlSco = prP2pChnlReqMsg->eChnlSco; + prChnlReqInfo->u4MaxInterval = prP2pChnlReqMsg->u4Duration; + prChnlReqInfo->eChannelReqType = CHANNEL_REQ_TYPE_REMAIN_ON_CHANNEL; + + eNextState = P2P_STATE_REQING_CHANNEL; + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, eNextState); + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pFsmRunEventChannelRequest */ + +VOID p2pFsmRunEventChannelAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_MSG_P2P_CHNL_ABORT_T prChnlAbortMsg = (P_MSG_P2P_CHNL_ABORT_T) NULL; + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prChnlAbortMsg = (P_MSG_P2P_CHNL_ABORT_T) prMsgHdr; + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) + break; + + prChnlReqInfo = &prP2pFsmInfo->rChnlReqInfo; + + DBGLOG(P2P, TRACE, "p2pFsmRunEventChannelAbort\n"); + + p2pFunCleanQueuedMgmtFrame(prAdapter, + &prP2pFsmInfo->rQueuedActionFrame); + + if ((prChnlAbortMsg->u8Cookie == prChnlReqInfo->u8Cookie) && (prChnlReqInfo->fgIsChannelRequested)) { + + ASSERT((prP2pFsmInfo->eCurrentState == P2P_STATE_REQING_CHANNEL || + (prP2pFsmInfo->eCurrentState == P2P_STATE_CHNL_ON_HAND))); + /* + * If cancel-roc cmd is called from Supplicant while driver is waiting + * for FW's channel grant event, roc event must be returned to Supplicant + * first to reset Supplicant's variables and then transition to idle state. + */ + if (prP2pFsmInfo->eCurrentState == P2P_STATE_REQING_CHANNEL) { + DBGLOG(P2P, INFO, "Transition to P2P_STATE_CHNL_ON_HAND first\n"); + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_CHNL_ON_HAND); + } + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + } else { + /* just avoid supplicant waiting too long */ + complete(&prAdapter->prGlueInfo->rP2pReq); + } + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pFsmRunEventChannelAbort */ + +VOID p2pFsmRunEventScanRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_MSG_P2P_SCAN_REQUEST_T prP2pScanReqMsg = (P_MSG_P2P_SCAN_REQUEST_T) NULL; + P_P2P_SCAN_REQ_INFO_T prScanReqInfo = (P_P2P_SCAN_REQ_INFO_T) NULL; + UINT_32 u4ChnlListSize = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) + break; + + prP2pScanReqMsg = (P_MSG_P2P_SCAN_REQUEST_T) prMsgHdr; + prScanReqInfo = &(prP2pFsmInfo->rScanReqInfo); + + DBGLOG(P2P, TRACE, "p2pFsmRunEventScanRequest\n"); + + /* Make sure the state is in IDLE state. */ + p2pFsmRunEventAbort(prAdapter, prP2pFsmInfo); + + ASSERT(prScanReqInfo->fgIsScanRequest == FALSE); + + prScanReqInfo->fgIsAbort = TRUE; + prScanReqInfo->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prScanReqInfo->eChannelSet = SCAN_CHANNEL_SPECIFIED; + + /* Channel List */ + prScanReqInfo->ucNumChannelList = prP2pScanReqMsg->u4NumChannel; + DBGLOG(P2P, TRACE, "Scan Request Channel List Number: %d\n", prScanReqInfo->ucNumChannelList); + if (prScanReqInfo->ucNumChannelList > MAXIMUM_OPERATION_CHANNEL_LIST) { + DBGLOG(P2P, TRACE, "Channel List Number Overloaded: %d, change to: %d\n", + prScanReqInfo->ucNumChannelList, MAXIMUM_OPERATION_CHANNEL_LIST); + prScanReqInfo->ucNumChannelList = MAXIMUM_OPERATION_CHANNEL_LIST; + } + + u4ChnlListSize = sizeof(RF_CHANNEL_INFO_T) * prScanReqInfo->ucNumChannelList; + kalMemCopy(prScanReqInfo->arScanChannelList, prP2pScanReqMsg->arChannelListInfo, u4ChnlListSize); + + /* TODO: I only take the first SSID. Multiple SSID may be needed in the future. */ + /* SSID */ + if (prP2pScanReqMsg->i4SsidNum >= 1) + kalMemCopy(&(prScanReqInfo->rSsidStruct), prP2pScanReqMsg->prSSID, sizeof(P2P_SSID_STRUCT_T)); + else + prScanReqInfo->rSsidStruct.ucSsidLen = 0; + + /* IE Buffer */ + kalMemCopy(prScanReqInfo->aucIEBuf, prP2pScanReqMsg->pucIEBuf, prP2pScanReqMsg->u4IELen); + + prScanReqInfo->u4BufLength = prP2pScanReqMsg->u4IELen; + prScanReqInfo->fgIsAcsReq = prP2pScanReqMsg->fgIsAcsReq; + prP2pFsmInfo->eCNNState = P2P_CNN_NORMAL; + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_SCAN); + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pFsmRunEventScanRequest */ + +VOID p2pFsmRunEventScanAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + DBGLOG(P2P, TRACE, "p2pFsmRunEventScanAbort\n"); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo->eCurrentState == P2P_STATE_SCAN) { + P_P2P_SCAN_REQ_INFO_T prScanReqInfo = &(prP2pFsmInfo->rScanReqInfo); + + prScanReqInfo->fgIsAbort = TRUE; + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + } + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pFsmRunEventScanAbort */ + +VOID p2pFsmRunEventAbort(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + DBGLOG(P2P, TRACE, "p2pFsmRunEventAbort\n"); + + if (prP2pFsmInfo->eCurrentState != P2P_STATE_IDLE) { + + if (prP2pFsmInfo->eCurrentState == P2P_STATE_SCAN) { + + P_P2P_SCAN_REQ_INFO_T prScanReqInfo = &(prP2pFsmInfo->rScanReqInfo); + + prScanReqInfo->fgIsAbort = TRUE; + } else if (prP2pFsmInfo->eCurrentState == P2P_STATE_REQING_CHANNEL) { + /* 2012/08/06: frog + * Prevent Start GO. + */ + prP2pBssInfo->eIntendOPMode = OP_MODE_NUM; + } + /* For other state, is there any special action that should be take before leaving? */ + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + } else { + /* P2P State IDLE. */ + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); + + if (prChnlReqInfo->fgIsChannelRequested) + p2pFuncReleaseCh(prAdapter, prChnlReqInfo); + + cnmTimerStopTimer(prAdapter, &(prAdapter->rP2pFsmTimeoutTimer)); + } + + } while (FALSE); + +} /* p2pFsmRunEventAbort */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to handle FSM Timeout. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFsmRunEventFsmTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParam) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) ulParam; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); + + DBGLOG(P2P, TRACE, "P2P FSM Timeout Event\n"); + + switch (prP2pFsmInfo->eCurrentState) { + case P2P_STATE_IDLE: + { + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = &prP2pFsmInfo->rChnlReqInfo; + + if (prChnlReqInfo->fgIsChannelRequested) { + p2pFuncReleaseCh(prAdapter, prChnlReqInfo); + } else if (IS_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_P2P_INDEX)) { + DBGLOG(P2P, INFO, "Force DeactivateNetwork"); + 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: +#if 0 + switch (prP2pFsmInfo->eListenExted) { + case P2P_DEV_NOT_EXT_LISTEN: + case P2P_DEV_EXT_LISTEN_WAITFOR_TIMEOUT: + DBGLOG(P2P, INFO, "p2p timeout, state==P2P_STATE_CHNL_ON_HAND, eListenExted: %d\n", + prP2pFsmInfo->eListenExted); + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + prP2pFsmInfo->eListenExted = P2P_DEV_NOT_EXT_LISTEN; + break; + case P2P_DEV_EXT_LISTEN_ING: + DBGLOG(P2P, INFO, "p2p timeout, state==P2P_STATE_CHNL_ON_HAND, eListenExted: %d\n", + prP2pFsmInfo->eListenExted); + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_CHNL_ON_HAND); + prP2pFsmInfo->eListenExted = P2P_DEV_EXT_LISTEN_WAITFOR_TIMEOUT; + break; + default: + ASSERT(FALSE); + DBGLOG(P2P, ERROR, + "Current P2P State %d is unexpected for FSM timeout event.\n", + prP2pFsmInfo->eCurrentState); +#else + if (prP2pFsmInfo->fgIsChannelExtended == TRUE) { + prP2pFsmInfo->fgIsChannelExtended = FALSE; + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + break; + } + switch (prP2pFsmInfo->eCNNState) { + case P2P_CNN_GO_NEG_REQ: + case P2P_CNN_GO_NEG_RESP: + case P2P_CNN_INVITATION_REQ: + case P2P_CNN_DEV_DISC_REQ: + case P2P_CNN_PROV_DISC_REQ: + DBGLOG(P2P, INFO, + "Re-enter channel on hand state, eCNNState: %d\n", + prP2pFsmInfo->eCNNState); + prP2pFsmInfo->fgIsChannelExtended = TRUE; + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_CHNL_ON_HAND); + break; + + case P2P_CNN_NORMAL: + case P2P_CNN_GO_NEG_CONF: + case P2P_CNN_INVITATION_RESP: + case P2P_CNN_DEV_DISC_RESP: + case P2P_CNN_PROV_DISC_RES: + default: + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + break; +#endif + } +/* case P2P_STATE_GC_JOIN: */ +/* break; */ + default: + break; + } + + } while (FALSE); + +} /* p2pFsmRunEventFsmTimeout */ + + +/* + * TDLS link monitor function + * teardown link if setup failed or + * no data traffic for 4s + */ +VOID p2pFsmRunEventTdlsTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParam) +{ + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + struct ksta_info *prTargetSta = prGlueInfo->prStaHash[STA_HASH_SIZE]; + + if (!prTargetSta) { + DBGLOG(TDLS, INFO, "TDLS: No target station, return\n"); + return; + } + + if (prTargetSta->eTdlsRole == MTK_TDLS_ROLE_RESPONDER) { + prTargetSta->u4Throughput = (prTargetSta->ulRxBytes * HZ) / TDLS_MONITOR_UT; + + if (prTargetSta->u4Throughput < TDLS_TEARDOWN_RX_THD) { + switch (prTargetSta->eTdlsStatus) { + case MTK_TDLS_LINK_ENABLE: + MTKTdlsTearDown(prGlueInfo, prTargetSta, "Low RX Throughput"); + default: + return; + } + } + DBGLOG(TDLS, INFO, "TDLS: Rx data stream OK\n"); + prTargetSta->ulRxBytes = 0; + goto start_timer; + } + + switch (prTargetSta->eTdlsStatus) { + case MTK_TDLS_NOT_SETUP: + DBGLOG(TDLS, INFO, "Last TDLS monitor timer\n"); + return; + case MTK_TDLS_SETUP_INPROCESS: + DBGLOG(TDLS, INFO, "TDLS: setup timeout\n"); + if (prTargetSta->u4SetupFailCount++ > TDLS_SETUP_COUNT) + MTKTdlsTearDown(prAdapter->prGlueInfo, prTargetSta, "Setup Failed"); + break; + case MTK_TDLS_LINK_ENABLE: + /* go through as we need restart timer to monitor tdls link */ + default: + if (time_after(jiffies, prGlueInfo->ulLastUpdate + 2 * SAMPLING_UT)) { + MTKTdlsTearDown(prAdapter->prGlueInfo, prTargetSta, "No Traffic"); + return; + } + DBGLOG(TDLS, INFO, "TDLS: TX data stream OK\n"); + break; + } + +start_timer: + DBGLOG(TDLS, TRACE, "Restart tdls monitor timer\n"); + cnmTimerStartTimer(prAdapter, &(prAdapter->rTdlsStateTimer), + SEC_TO_MSEC(TDLS_MONITOR_UT)); +} + + +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; + P_MSDU_INFO_T prMgmtFrame = (P_MSDU_INFO_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; + prMgmtFrame = prMgmtTxMsg->prMgmtMsduInfo; + + p2pFuncTxMgmtFrame(prAdapter, + &prP2pFsmInfo->rMgmtTxInfo, prMgmtFrame, prMgmtFrame->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; + P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo = (P_P2P_CONNECTION_REQ_INFO_T) NULL; + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo; + P_P2P_SCAN_REQ_INFO_T prScanReqInfo; + + 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; + prConnReqInfo = &(prP2pFsmInfo->rConnReqInfo); + + if (prP2pStartAPMsg->u4BcnInterval) { + DBGLOG(P2P, TRACE, "Beacon interval updated to: %u\n", prP2pStartAPMsg->u4BcnInterval); + prP2pBssInfo->u2BeaconInterval = (UINT_16) prP2pStartAPMsg->u4BcnInterval; + } else if (prP2pBssInfo->u2BeaconInterval == 0) { + prP2pBssInfo->u2BeaconInterval = DOT11_BEACON_PERIOD_DEFAULT; + } + + if (prP2pStartAPMsg->u4DtimPeriod) { + DBGLOG(P2P, TRACE, "DTIM interval updated to: %u\n", prP2pStartAPMsg->u4DtimPeriod); + prP2pBssInfo->ucDTIMPeriod = (UINT_8) prP2pStartAPMsg->u4DtimPeriod; + } else if (prP2pBssInfo->ucDTIMPeriod == 0) { + prP2pBssInfo->ucDTIMPeriod = DOT11_DTIM_PERIOD_DEFAULT; + } + + if (prP2pStartAPMsg->u2SsidLen != 0) { + kalMemCopy(prP2pBssInfo->aucSSID, prP2pStartAPMsg->aucSsid, prP2pStartAPMsg->u2SsidLen); + kalMemCopy(prP2pSpecificBssInfo->aucGroupSsid, prP2pStartAPMsg->aucSsid, + prP2pStartAPMsg->u2SsidLen); + prP2pBssInfo->ucSSIDLen = prP2pSpecificBssInfo->u2GroupSsidLen = prP2pStartAPMsg->u2SsidLen; + } + + prP2pBssInfo->eHiddenSsidType = prP2pStartAPMsg->ucHiddenSsidType; + + /* TODO: JB */ + /* Privacy & inactive timeout. */ + + if ((prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) || + (prP2pBssInfo->eIntendOPMode != OP_MODE_NUM)) { + UINT_8 ucPreferedChnl = 0; + ENUM_BAND_T eBand = BAND_NULL; + ENUM_CHNL_EXT_T eSco = CHNL_EXT_SCN; + ENUM_P2P_STATE_T eNextState = P2P_STATE_NUM; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + if (prP2pFsmInfo->eCurrentState != P2P_STATE_SCAN && + prP2pFsmInfo->eCurrentState != P2P_STATE_IDLE) { + /* Make sure the state is in IDLE state. */ + p2pFsmRunEventAbort(prAdapter, prP2pFsmInfo); + } + prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsGOInitialDone = 0; + DBGLOG(P2P, INFO, "NFC:fgIsGOInitialDone[%d]\n", + prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsGOInitialDone); + + /* Leave IDLE state. */ + SET_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); + + /* Trigger P2P FSM to REQING_CHANNEL state for AP mode. */ + prP2pBssInfo->eIntendOPMode = OP_MODE_ACCESS_POINT; + + /* Clear GC's connection request. */ + prConnReqInfo->fgIsConnRequest = FALSE; + +#if CFG_SUPPORT_CFG_FILE +#ifdef ENABLED_IN_ENGUSERDEBUG + /* Overwrite AP channel */ + if (prAdapter->rWifiVar.ucApChannel) { + DBGLOG(P2P, INFO, "p2pFsmRunEventStartAP: ucApChannel = %u\n", + prAdapter->rWifiVar.ucApChannel); + prP2pConnSettings->ucOperatingChnl = prAdapter->rWifiVar.ucApChannel; + if (prAdapter->rWifiVar.ucApChannel <= 14) + prP2pConnSettings->eBand = BAND_2G4; + else + prP2pConnSettings->eBand = BAND_5G; + } +#endif +#endif + + p2pFuncClearGcDeauthRetry(prAdapter); + + if ((cnmPreferredChannel(prAdapter, + &eBand, + &ucPreferedChnl, + &eSco) == FALSE) && (prP2pConnSettings->ucOperatingChnl == 0)) { + /* Sparse channel detection using passive mode. */ + eNextState = P2P_STATE_AP_CHANNEL_DETECT; + } else { + prChnlReqInfo = &prP2pFsmInfo->rChnlReqInfo; + prScanReqInfo = &(prP2pFsmInfo->rScanReqInfo); + +#if 1 + /* 2012-01-27: frog - Channel set from upper layer is the first priority. */ + /* Because the channel & beacon is decided by p2p_supplicant. */ + /* Channel set from upper layer is the first priority */ + if (prP2pConnSettings->ucOperatingChnl != 0) { + prP2pSpecificBssInfo->ucPreferredChannel = prP2pConnSettings->ucOperatingChnl; + prP2pSpecificBssInfo->eRfBand = prP2pConnSettings->eBand; + prP2pSpecificBssInfo->eRfSco = rlmDecideScoForAP(prAdapter, prP2pBssInfo); + } else { + ASSERT(ucPreferedChnl != 0); + prP2pSpecificBssInfo->ucPreferredChannel = ucPreferedChnl; + prP2pSpecificBssInfo->eRfBand = eBand; + prP2pSpecificBssInfo->eRfSco = rlmDecideScoForAP(prAdapter, prP2pBssInfo); + } +#else + if (ucPreferedChnl) { + prP2pSpecificBssInfo->ucPreferredChannel = ucPreferedChnl; + prP2pSpecificBssInfo->eRfBand = eBand; + prP2pSpecificBssInfo->eRfSco = rlmDecideScoForAP(prAdapter, prP2pBssInfo); + } else { + ASSERT(prP2pConnSettings->ucOperatingChnl != 0); + prP2pSpecificBssInfo->ucPreferredChannel = prP2pConnSettings->ucOperatingChnl; + prP2pSpecificBssInfo->eRfBand = prP2pConnSettings->eBand; + prP2pSpecificBssInfo->eRfSco = rlmDecideScoForAP(prAdapter, prP2pBssInfo); + } +#endif + prChnlReqInfo->ucReqChnlNum = prP2pSpecificBssInfo->ucPreferredChannel; + prChnlReqInfo->eBand = prP2pSpecificBssInfo->eRfBand; + prChnlReqInfo->u4MaxInterval = P2P_AP_CHNL_HOLD_TIME_MS; + prChnlReqInfo->eChannelReqType = CHANNEL_REQ_TYPE_GO_START_BSS; + + eNextState = P2P_STATE_REQING_CHANNEL; + } + + prP2pFsmInfo->eCNNState = P2P_CNN_NORMAL; + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, eNextState); + + } + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pFsmRunEventStartAP */ + +VOID p2pFsmRunEventNetDeviceRegister(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_P2P_NETDEV_REGISTER_T prNetDevRegisterMsg = (P_MSG_P2P_NETDEV_REGISTER_T) NULL; + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + DBGLOG(P2P, TRACE, "p2pFsmRunEventNetDeviceRegister\n"); + + prNetDevRegisterMsg = (P_MSG_P2P_NETDEV_REGISTER_T) prMsgHdr; + + if (prNetDevRegisterMsg->fgIsEnable) { + p2pSetMode((prNetDevRegisterMsg->ucMode == 1) ? TRUE : FALSE); + + if (p2pLaunch(prAdapter->prGlueInfo)) + ASSERT(prAdapter->fgIsP2PRegistered); + + } else { + if (prAdapter->fgIsP2PRegistered) + p2pRemove(prAdapter->prGlueInfo); + + } + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pFsmRunEventNetDeviceRegister */ + +VOID p2pFsmRunEventUpdateMgmtFrame(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_P2P_MGMT_FRAME_UPDATE_T prP2pMgmtFrameUpdateMsg = (P_MSG_P2P_MGMT_FRAME_UPDATE_T) NULL; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + DBGLOG(P2P, TRACE, "p2pFsmRunEventUpdateMgmtFrame\n"); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) + break; + + prP2pMgmtFrameUpdateMsg = (P_MSG_P2P_MGMT_FRAME_UPDATE_T) prMsgHdr; + + switch (prP2pMgmtFrameUpdateMsg->eBufferType) { + case ENUM_FRAME_TYPE_EXTRA_IE_BEACON: + break; + case ENUM_FRAME_TYPE_EXTRA_IE_ASSOC_RSP: + break; + case ENUM_FRAME_TYPE_EXTRA_IE_PROBE_RSP: + break; + case ENUM_FRAME_TYPE_PROBE_RSP_TEMPLATE: + break; + case ENUM_FRAME_TYPE_BEACON_TEMPLATE: + break; + default: + break; + } + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pFsmRunEventUpdateMgmtFrame */ + +VOID p2pFsmRunEventBeaconUpdate(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_MSG_P2P_BEACON_UPDATE_T prBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + DBGLOG(P2P, TRACE, "p2pFsmRunEventBeaconUpdate\n"); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + if (prP2pFsmInfo == NULL) + break; + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T) prMsgHdr; + + DBGLOG_MEM8_IE_ONE_LINE(P2P, TRACE, "BcnHdr" + , prBcnUpdateMsg->pucBcnHdr, prBcnUpdateMsg->u4BcnHdrLen) + DBGLOG_MEM8_IE_ONE_LINE(P2P, TRACE, "BcnBody" + , prBcnUpdateMsg->pucBcnBody, prBcnUpdateMsg->u4BcnBodyLen); + + p2pFuncProcessBeacon(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. */ + bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_P2P_INDEX); + +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP + p2pFuncUpdateProbeRspIEs(prAdapter, prBcnUpdateMsg, + NETWORK_TYPE_P2P_INDEX); +#endif + /* nicPmIndicateBssCreated(prAdapter, NETWORK_TYPE_P2P_INDEX); */ + } else + DBGLOG(P2P, WARN, "driver skipped the beacon update! CurrentOPMode :%d eIntendOPMode:%d\n" + , prP2pBssInfo->eCurrentOPMode, prP2pBssInfo->eIntendOPMode); + + } 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)) { + p2pFuncDissolve(prAdapter, prP2pBssInfo, TRUE, REASON_CODE_DEAUTH_LEAVING_BSS); + } + /* 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); + +#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); + + /* In P2P GC case, the interval of two ASSOC flow could be very short, */ + /* we must start to connect directly before Deauth done */ + p2pFsmCheckDeauthComplete(prAdapter); + + /* 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); + prP2pFsmInfo->eCNNState = P2P_CNN_NORMAL; + + p2pFuncClearGcDeauthRetry(prAdapter); + + if (prP2pFsmInfo->prTargetBss == NULL) { + /* Update scan parameter... to scan target device. */ + P_P2P_SCAN_REQ_INFO_T prScanReqInfo = &(prP2pFsmInfo->rScanReqInfo); + + DBGLOG(P2P, INFO, "p2pFsmRunEventConnectionRequest,Trigger New Scan\n"); + + prScanReqInfo->ucNumChannelList = 1; + prScanReqInfo->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prScanReqInfo->eChannelSet = SCAN_CHANNEL_SPECIFIED; + prScanReqInfo->arScanChannelList[0].ucChannelNum = prConnReqMsg->rChannelInfo.ucChannelNum; + kalMemCopy(&(prScanReqInfo->rSsidStruct), &(prConnReqMsg->rSsid), sizeof(P2P_SSID_STRUCT_T)); + prScanReqInfo->u4BufLength = 0; /* Prevent other P2P ID in IE. */ + prScanReqInfo->fgIsAbort = TRUE; + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_SCAN); + } else { + prChnlReqInfo->u8Cookie = 0; + prChnlReqInfo->ucReqChnlNum = prConnReqMsg->rChannelInfo.ucChannelNum; + prChnlReqInfo->eBand = prConnReqMsg->rChannelInfo.eBand; + prChnlReqInfo->eChnlSco = prConnReqMsg->eChnlSco; + prChnlReqInfo->u4MaxInterval = AIS_JOIN_CH_REQUEST_INTERVAL; + prChnlReqInfo->eChannelReqType = CHANNEL_REQ_TYPE_GC_JOIN_REQ; + DBGLOG(P2P, INFO, "p2pFsmRunEventConnectionRequest, Report the Connecting BSS Again.\n"); + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_REQING_CHANNEL); + } + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + + return; + +} /* p2pFsmRunEventConnectionRequest */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to handle Connection Request from Supplicant. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFsmRunEventConnectionAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_MSG_P2P_CONNECTION_ABORT_T prDisconnMsg = (P_MSG_P2P_CONNECTION_ABORT_T) NULL; + STA_RECORD_T *prStaRec = (P_STA_RECORD_T) NULL; + P_STA_RECORD_T prTargetStaRec = (P_STA_RECORD_T) NULL; + P_P2P_GC_DISCONNECTION_REQ_INFO_T prGcDisConnReqInfo; + + 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; + + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_P2P_INDEX, prDisconnMsg->aucTargetID); + + /* + * Do nothing as TDLS disable operation will free this STA REC + * when this is TDLS peer. + * This operation will go through when as GO/HP. + */ + if (prStaRec && prStaRec->eStaType == STA_TYPE_TDLS_PEER) { + DBGLOG(P2P, INFO, "TDLS peer, do nothing\n"); + return; + } + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_INFRASTRUCTURE: + { + UINT_8 aucBCBSSID[] = BC_BSSID; + + prTargetStaRec = prP2pBssInfo->prStaRecOfAP; + + if (!prTargetStaRec) { + DBGLOG(P2P, TRACE, "GO's StaRec is NULL\n"); + break; + } + if (UNEQUAL_MAC_ADDR(prTargetStaRec->aucMacAddr, prDisconnMsg->aucTargetID) + && UNEQUAL_MAC_ADDR(prDisconnMsg->aucTargetID, aucBCBSSID)) { + DBGLOG(P2P, TRACE, + "Unequal MAC ADDR [ %pM : %pM ]\n", + prTargetStaRec->aucMacAddr, + prDisconnMsg->aucTargetID); + break; + } + + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + NULL, NULL, 0, 0, + WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY); + + /* Stop rejoin timer if it is started. */ + /* TODO: If it has. */ + + prGcDisConnReqInfo = &(prP2pFsmInfo->rGcDisConnReqInfo); + prGcDisConnReqInfo->prTargetStaRec = prTargetStaRec; + prGcDisConnReqInfo->u4RetryCount = 0; + prGcDisConnReqInfo->u2ReasonCode = prDisconnMsg->u2ReasonCode; + prGcDisConnReqInfo->fgSendDeauth = prDisconnMsg->fgSendDeauth; + + p2pFuncDisconnect(prAdapter, prTargetStaRec, prDisconnMsg->fgSendDeauth, + prDisconnMsg->u2ReasonCode); + + DBGLOG(P2P, INFO, "start GC deauth timer for %pM\n", + prTargetStaRec->aucMacAddr); + cnmTimerStopTimer(prAdapter, &(prTargetStaRec->rDeauthTxDoneTimer)); + cnmTimerInitTimer(prAdapter, &(prTargetStaRec->rDeauthTxDoneTimer), + (PFN_MGMT_TIMEOUT_FUNC) p2pFsmRunEventDeauthTimeout, (ULONG) prTargetStaRec); + cnmTimerStartTimer(prAdapter, &(prTargetStaRec->rDeauthTxDoneTimer), + P2P_DEAUTH_TIMEOUT_TIME_MS); + + prP2pBssInfo->prStaRecOfAP = NULL; + + SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_P2P_INDEX); + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + + } + break; + case OP_MODE_ACCESS_POINT: + { + P_LINK_T prStaRecOfClientList = &prP2pBssInfo->rStaRecOfClientList; + /* Search specific client device, and disconnect. */ + /* 1. Send deauthentication frame. */ + /* 2. Indication: Device disconnect. */ + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; + P_STA_RECORD_T prCurrStaRec = (P_STA_RECORD_T) NULL; + + DBGLOG(P2P, TRACE, + "Disconnecting with Target ID: %pM\n", + prDisconnMsg->aucTargetID); + + LINK_FOR_EACH(prLinkEntry, prStaRecOfClientList) { + prCurrStaRec = LINK_ENTRY(prLinkEntry, STA_RECORD_T, rLinkEntry); + + if (prCurrStaRec + && EQUAL_MAC_ADDR(prCurrStaRec->aucMacAddr, prDisconnMsg->aucTargetID)) { + + DBGLOG(P2P, TRACE, + "Disconnecting: %pM\n", + prCurrStaRec->aucMacAddr); + + /* Remove STA from client list. */ + LINK_REMOVE_KNOWN_ENTRY(prStaRecOfClientList, + &prCurrStaRec->rLinkEntry); + + /* Glue layer indication. */ + /* kalP2PGOStationUpdate(prAdapter->prGlueInfo, prCurrStaRec, FALSE); */ + + /* Send deauth & do indication. */ + p2pFuncDisconnect(prAdapter, prCurrStaRec, prDisconnMsg->fgSendDeauth, + prDisconnMsg->u2ReasonCode); + + DBGLOG(P2P, INFO, "start GO deauth timer for %pM\n", + prCurrStaRec->aucMacAddr); + cnmTimerStopTimer(prAdapter, &(prCurrStaRec->rDeauthTxDoneTimer)); + cnmTimerInitTimer(prAdapter, &(prCurrStaRec->rDeauthTxDoneTimer), + (PFN_MGMT_TIMEOUT_FUNC) p2pFsmRunEventDeauthTimeout, + (ULONG) prCurrStaRec); + cnmTimerStartTimer(prAdapter, &(prCurrStaRec->rDeauthTxDoneTimer), + P2P_DEAUTH_TIMEOUT_TIME_MS); + + /* prTargetStaRec = prCurrStaRec; */ + + break; + } + } + + } + break; + case OP_MODE_P2P_DEVICE: + default: + ASSERT(FALSE); + break; + } + + } while (FALSE); + + /* 20120830 moved into p2pFuncDisconnect() */ + /* if ((!prDisconnMsg->fgSendDeauth) && (prTargetStaRec)) { */ + /* cnmStaRecFree(prAdapter, prTargetStaRec, TRUE); */ + /* } */ + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pFsmRunEventConnectionAbort */ + +VOID p2pFsmRunEventDissolve(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + + /* TODO: */ + + DBGLOG(P2P, TRACE, "p2pFsmRunEventDissolve\n"); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} + +static VOID p2pFsmDeauthComplete(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + + do { + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + /* Skip deauth tx done if AAA in progress */ + if ((prStaRec->eAuthAssocState == AAA_STATE_SEND_AUTH2 || + prStaRec->eAuthAssocState == AAA_STATE_SEND_ASSOC2) && + (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) && + (p2pFuncIsAPMode(prP2pFsmInfo) == FALSE)) { + DBGLOG(P2P, WARN, "Skip deauth tx done since AAA fsm is in progress.\n"); + break; + } else if (prStaRec->eAuthAssocState == SAA_STATE_SEND_AUTH1 || + prStaRec->eAuthAssocState == SAA_STATE_SEND_ASSOC1) { + DBGLOG(P2P, WARN, + "Skip deauth tx done since SAA fsm is in progress.\n"); + return; + } + + if ((prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) && + (p2pFuncRetryGcDeauth(prAdapter, prP2pFsmInfo, prStaRec, + rTxDoneStatus) == TRUE)) + break; + + /* Change station state. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + /* Reset Station Record Status. */ + p2pFuncResetStaRecStatus(prAdapter, prStaRec); + + bssRemoveStaRecFromClientList(prAdapter, prP2pBssInfo, prStaRec); + + cnmStaRecFree(prAdapter, prStaRec, TRUE); + + if (prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) { + p2pFuncClearGcDeauthRetry(prAdapter); + p2pFuncDeauthComplete(prAdapter, prP2pBssInfo); + } else if ((prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) && + (prP2pBssInfo->rStaRecOfClientList.u4NumElem == 0) && + IS_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_P2P_INDEX)) { + p2pFuncDeauthComplete(prAdapter, prP2pBssInfo); + } + } while (FALSE); +} + +static VOID p2pFsmCheckDeauthComplete(IN P_ADAPTER_T prAdapter) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_P2P_GC_DISCONNECTION_REQ_INFO_T prGcDisConnReqInfo; + + do { + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) + break; + + prGcDisConnReqInfo = &(prP2pFsmInfo->rGcDisConnReqInfo); + + DBGLOG(P2P, INFO, "p2pFsmCheckDeauthComplete\n"); + + if (prGcDisConnReqInfo && prGcDisConnReqInfo->fgSendDeauth) { + DBGLOG(P2P, INFO, "Force stop previous deauth process since new connection came.\n"); + p2pFsmDeauthComplete(prAdapter, + prGcDisConnReqInfo->prTargetStaRec, TX_RESULT_LIFE_TIMEOUT); + } + } while (FALSE); +} + +VOID p2pFsmRunEventDeauthTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParam) +{ + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) ulParam; + + if (prStaRec) { + DBGLOG(P2P, INFO, "Deauth frame timeout for %pM\n", prStaRec->aucMacAddr); + p2pFsmDeauthComplete(prAdapter, prStaRec, TX_RESULT_LIFE_TIMEOUT); + } +} + +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; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + DBGLOG(P2P, INFO, "Deauth TX Done Status: %d, seqNo %d, staRecIdx: %d\n", + rTxDoneStatus, prMsduInfo->ucTxSeqNum, prMsduInfo->ucStaRecIndex); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (prStaRec == NULL) { + DBGLOG(P2P, TRACE, "Station Record NULL, Index:%d\n", prMsduInfo->ucStaRecIndex); + break; + } + + p2pFsmDeauthComplete(prAdapter, prStaRec, rTxDoneStatus); + DBGLOG(P2P, INFO, "stop deauth timer for %pM\n", prStaRec->aucMacAddr); + /* Avoid re-entry */ + cnmTimerStopTimer(prAdapter, &(prStaRec->rDeauthTxDoneTimer)); + + } 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) + fgIsSuccess = TRUE; + + DBGLOG(P2P, INFO, "Mgmt Frame : Status: %d, seq NO. %d, Cookie: 0x%llx\n", + rTxDoneStatus, prMsduInfo->ucTxSeqNum, prMsduInfo->u8Cookie); + + + if (prMgmtTxReqInfo->prMgmtTxMsdu == prMsduInfo) { + kalP2PIndicateMgmtTxStatus(prAdapter->prGlueInfo, + prMsduInfo->u8Cookie, + fgIsSuccess, + prMsduInfo->prPacket, (UINT_32) prMsduInfo->u2FrameLength); + + prMgmtTxReqInfo->prMgmtTxMsdu = NULL; + } + /* + * wake up supplicant if it is waiting for tx done + */ + complete(&prAdapter->prGlueInfo->rP2pReq); + } while (FALSE); + + return WLAN_STATUS_SUCCESS; + +} /* p2pFsmRunEventMgmtFrameTxDone */ + +#if CFG_SUPPORT_P2P_ECSA +WLAN_STATUS +p2pFsmRunEventMgmtEcsaTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + if (rTxDoneStatus != TX_RESULT_SUCCESS) { + DBGLOG(P2P, INFO, "Mgmt ECSA Frame TX Fail, Status: %d, seq NO. %d\n", + rTxDoneStatus, prMsduInfo->ucTxSeqNum); + } else { + DBGLOG(P2P, INFO, "Mgmt ECSA Frame TX Done.\n"); + } + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; + +} +#endif +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called when JOIN complete message event is received from SAA. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFsmRunEventJoinComplete(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_P2P_JOIN_INFO_T prJoinInfo = (P_P2P_JOIN_INFO_T) NULL; + P_MSG_JOIN_COMP_T prJoinCompMsg = (P_MSG_JOIN_COMP_T) NULL; + P_SW_RFB_T prAssocRspSwRfb = (P_SW_RFB_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + DBGLOG(P2P, INFO, "P2P Join Complete\n"); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + if (prP2pFsmInfo == NULL) { + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + prJoinInfo = &(prP2pFsmInfo->rJoinInfo); + if (prMsgHdr == NULL) + return; + prJoinCompMsg = (P_MSG_JOIN_COMP_T) prMsgHdr; + prAssocRspSwRfb = prJoinCompMsg->prSwRfb; + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + if (prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + + prStaRec = prJoinCompMsg->prStaRec; + + /* Check SEQ NUM */ + if (prJoinCompMsg->ucSeqNum == ((prJoinInfo->ucSeqNumOfReqMsg)%256)) { + 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); + /* fire the update jiffies */ + prAdapter->prGlueInfo->ulLastUpdate = jiffies; + DBGLOG(P2P, INFO, "P2P GC Join Success\n"); + + /* reset add key action */ + prP2pBssInfo->eKeyAction = SEC_TX_KEY_COMMAND; + +#if CFG_SUPPORT_P2P_RSSI_QUERY + /* <1.5> Update RSSI if necessary */ + nicUpdateRSSI(prAdapter, NETWORK_TYPE_P2P_INDEX, + (INT_8) (RCPI_TO_dBm(prStaRec->ucRCPI)), 0); +#endif + + /* 4 <1.6> Indicate Connected Event to Host immediately. */ + /* Require BSSID, Association ID, Beacon Interval.. from AIS_BSS_INFO_T */ + /* p2pIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, */ + /* prStaRec->aucMacAddr); */ + if (prP2pFsmInfo->prTargetBss) + scanReportBss2Cfg80211(prAdapter, BSS_TYPE_P2P_DEVICE, + prP2pFsmInfo->prTargetBss); + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + &prP2pFsmInfo->rConnReqInfo, + prJoinInfo->aucIEBuf, prJoinInfo->u4BufLength, + prStaRec->u2StatusCode, + WLAN_STATUS_MEDIA_CONNECT); + + } else { + /* Join Fail */ + /* 4 <2.1> Redo JOIN process with other Auth Type if possible */ + if (p2pFuncRetryJOIN(prAdapter, prStaRec, prJoinInfo) == FALSE) { + P_BSS_DESC_T prBssDesc; + + /* Increase Failure Count */ + prStaRec->ucJoinFailureCount++; + + prBssDesc = prP2pFsmInfo->prTargetBss; + + ASSERT(prBssDesc); + ASSERT(prBssDesc->fgIsConnecting); + + prBssDesc->fgIsConnecting = FALSE; + + if (prStaRec->ucJoinFailureCount >= 3) { + + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + &prP2pFsmInfo->rConnReqInfo, + prJoinInfo->aucIEBuf, + prJoinInfo->u4BufLength, + prStaRec->u2StatusCode, + WLAN_STATUS_MEDIA_CONNECT); + } else { + /* Sometime the GO is not ready to response auth. */ + /* Connect it again */ + prP2pFsmInfo->prTargetBss = NULL; + } + DBGLOG(P2P, INFO, "P2P GC Join Failed\n"); + + } + + } + } + } + + if (prAssocRspSwRfb) + nicRxReturnRFB(prAdapter, prAssocRspSwRfb); + + if (prP2pFsmInfo->eCurrentState == P2P_STATE_GC_JOIN) { + + if (prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].eConnectionState == + PARAM_MEDIA_STATE_CONNECTED) { + /* do nothing & wait for timeout or EAPOL 4/4 TX done */ + } else { + /* p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); */ + /* one more scan */ + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_SCAN); + } + } + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pFsmRunEventJoinComplete */ + +VOID p2pFsmRunEventMgmtFrameRegister(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_P2P_MGMT_FRAME_REGISTER_T prMgmtFrameRegister = (P_MSG_P2P_MGMT_FRAME_REGISTER_T) NULL; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) + break; + + prMgmtFrameRegister = (P_MSG_P2P_MGMT_FRAME_REGISTER_T) prMsgHdr; + + p2pFuncMgmtFrameRegister(prAdapter, + prMgmtFrameRegister->u2FrameType, + prMgmtFrameRegister->fgIsRegister, &prP2pFsmInfo->u4P2pPacketFilter); + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + + return; + +} /* p2pFsmRunEventMgmtFrameRegister */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is call when RX deauthentication frame from the AIR. +* If we are under STA mode, we would go back to P2P Device. +* If we are under AP mode, we would stay in AP mode until disconnect event from HOST. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFsmRunEventRxDeauthentication(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb) +{ + + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + UINT_16 u2ReasonCode = 0; + BOOLEAN fgSendDeauth = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + + if (prStaRec == NULL) + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) + break; + + if (!prStaRec) + break; + + prP2pBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; + + if (prStaRec->ucStaState == STA_STATE_1) + break; + + DBGLOG(P2P, TRACE, "RX Deauth\n"); + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_INFRASTRUCTURE: + if (authProcessRxDeauthFrame(prSwRfb, + prStaRec->aucMacAddr, &u2ReasonCode) == WLAN_STATUS_SUCCESS) { + P_WLAN_DEAUTH_FRAME_T prDeauthFrame = (P_WLAN_DEAUTH_FRAME_T) prSwRfb->pvHeader; + UINT_16 u2IELength = 0; + + if (prP2pBssInfo->prStaRecOfAP != prStaRec) + break; + + prStaRec->u2ReasonCode = u2ReasonCode; + u2IELength = prSwRfb->u2PacketLen - (WLAN_MAC_HEADER_LEN + REASON_CODE_FIELD_LEN); + + ASSERT(prP2pBssInfo->prStaRecOfAP == prStaRec); + + /* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + NULL, + prDeauthFrame->aucInfoElem, u2IELength, + u2ReasonCode, + WLAN_STATUS_MEDIA_DISCONNECT); + + prP2pBssInfo->prStaRecOfAP = NULL; + DBGLOG(P2P, INFO, "GC RX Deauth Reason: %d\n", u2ReasonCode); + + p2pFuncDisconnect(prAdapter, prStaRec, FALSE, u2ReasonCode); + p2pFuncDeauthComplete(prAdapter, prP2pBssInfo); + + SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_P2P_INDEX); + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + } + break; + case OP_MODE_ACCESS_POINT: + /* Delete client from client list. */ + if (authProcessRxDeauthFrame(prSwRfb, + prP2pBssInfo->aucBSSID, &u2ReasonCode) == WLAN_STATUS_SUCCESS) { + P_LINK_T prStaRecOfClientList = (P_LINK_T) NULL; + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; + P_STA_RECORD_T prCurrStaRec = (P_STA_RECORD_T) NULL; + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + P_HIF_RX_HEADER_T prHifRxHdr = prSwRfb->prHifRxHdr; + + if (prHifRxHdr->ucReserved & CONTROL_FLAG_UC_MGMT_NO_ENC) { + /* if cipher mismatch, or incorrect encrypt, just drop */ + DBGLOG(P2P, ERROR, "Rx deauth CM/CLM=1\n"); + return; + } + + /* 4.3.3.1 send unprotected deauth reason 6/7 */ + DBGLOG(P2P, INFO, "deauth reason=6\n"); + fgSendDeauth = TRUE; + u2ReasonCode = REASON_CODE_CLASS_2_ERR; + prStaRec->rPmfCfg.fgRxDeauthResp = TRUE; + } +#endif + + prStaRecOfClientList = &prP2pBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH(prLinkEntry, prStaRecOfClientList) { + prCurrStaRec = LINK_ENTRY(prLinkEntry, STA_RECORD_T, rLinkEntry); + + ASSERT(prCurrStaRec); + + if (EQUAL_MAC_ADDR(prCurrStaRec->aucMacAddr, prStaRec->aucMacAddr)) { + + /* Remove STA from client list. */ + LINK_REMOVE_KNOWN_ENTRY(prStaRecOfClientList, + &prCurrStaRec->rLinkEntry); + + /* Indicate to Host. */ + /* kalP2PGOStationUpdate(prAdapter->prGlueInfo, prStaRec, FALSE); */ + + /* Indicate disconnect to Host. */ + DBGLOG(P2P, INFO, "GO RX Deauth Reason: %d\n", u2ReasonCode); + p2pFuncDisconnect(prAdapter, prStaRec, fgSendDeauth, u2ReasonCode); + + break; + } + } + } + break; + case OP_MODE_P2P_DEVICE: + default: + /* Findout why someone sent deauthentication frame to us. */ + ASSERT(FALSE); + break; + } + + DBGLOG(P2P, TRACE, "Deauth Reason:%d\n", u2ReasonCode); + + } while (FALSE); +} /* p2pFsmRunEventRxDeauthentication */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is call when RX deauthentication frame from the AIR. +* If we are under STA mode, we would go back to P2P Device. +* If we are under AP mode, we would stay in AP mode until disconnect event from HOST. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFsmRunEventRxDisassociation(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + UINT_16 u2ReasonCode = 0; + BOOLEAN fgSendDeauth = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) + break; + + if (prStaRec == NULL) { + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (prStaRec == NULL) + break; + } + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + if (prStaRec->ucStaState == STA_STATE_1) + break; + + DBGLOG(P2P, TRACE, "RX Disassoc\n"); + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_INFRASTRUCTURE: + if (assocProcessRxDisassocFrame(prAdapter, + prSwRfb, + prStaRec->aucMacAddr, + &prStaRec->u2ReasonCode) == WLAN_STATUS_SUCCESS) { + P_WLAN_DISASSOC_FRAME_T prDisassocFrame = (P_WLAN_DISASSOC_FRAME_T) prSwRfb->pvHeader; + UINT_16 u2IELength = 0; + + ASSERT(prP2pBssInfo->prStaRecOfAP == prStaRec); + + if (prP2pBssInfo->prStaRecOfAP != prStaRec) + break; + + u2IELength = prSwRfb->u2PacketLen - (WLAN_MAC_HEADER_LEN + REASON_CODE_FIELD_LEN); + + /* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + NULL, + prDisassocFrame->aucInfoElem, + u2IELength, prStaRec->u2ReasonCode, + WLAN_STATUS_MEDIA_DISCONNECT); + + prP2pBssInfo->prStaRecOfAP = NULL; + + DBGLOG(P2P, INFO, "GC RX Disassoc Reason %d\n", prStaRec->u2ReasonCode); + p2pFuncDisconnect(prAdapter, prStaRec, FALSE, prStaRec->u2ReasonCode); + p2pFuncDeauthComplete(prAdapter, prP2pBssInfo); + SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_P2P_INDEX); + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + + } + break; + case OP_MODE_ACCESS_POINT: + /* Delete client from client list. */ + if (assocProcessRxDisassocFrame(prAdapter, + prSwRfb, + prP2pBssInfo->aucBSSID, &u2ReasonCode) == WLAN_STATUS_SUCCESS) { + P_LINK_T prStaRecOfClientList = (P_LINK_T) NULL; + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; + P_STA_RECORD_T prCurrStaRec = (P_STA_RECORD_T) NULL; + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + P_HIF_RX_HEADER_T prHifRxHdr = prSwRfb->prHifRxHdr; + + if (prHifRxHdr->ucReserved & CONTROL_FLAG_UC_MGMT_NO_ENC) { + /* if cipher mismatch, or incorrect encrypt, just drop */ + DBGLOG(P2P, ERROR, "Rx disassoc CM/CLM=1\n"); + return; + } + + /* 4.3.3.1 send unprotected deauth reason 6/7 */ + DBGLOG(P2P, INFO, "deauth reason=6\n"); + fgSendDeauth = TRUE; + u2ReasonCode = REASON_CODE_CLASS_2_ERR; + prStaRec->rPmfCfg.fgRxDeauthResp = TRUE; + } +#endif + + prStaRecOfClientList = &prP2pBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH(prLinkEntry, prStaRecOfClientList) { + prCurrStaRec = LINK_ENTRY(prLinkEntry, STA_RECORD_T, rLinkEntry); + + ASSERT(prCurrStaRec); + + if (EQUAL_MAC_ADDR(prCurrStaRec->aucMacAddr, prStaRec->aucMacAddr)) { + + /* Remove STA from client list. */ + LINK_REMOVE_KNOWN_ENTRY(prStaRecOfClientList, + &prCurrStaRec->rLinkEntry); + + /* Indicate to Host. */ + /* kalP2PGOStationUpdate(prAdapter->prGlueInfo, prStaRec, FALSE); */ + + /* Indicate disconnect to Host. */ + DBGLOG(P2P, INFO, "GO RX Disassoc Reason %d\n", u2ReasonCode); + p2pFuncDisconnect(prAdapter, prStaRec, fgSendDeauth, u2ReasonCode); + + break; + } + } + } + break; + case OP_MODE_P2P_DEVICE: + default: + ASSERT(FALSE); + break; + } + + } while (FALSE); +} /* p2pFsmRunEventRxDisassociation */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called when a probe request frame is received. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return boolean value if probe response frame is accepted & need cancel scan request. +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFsmRunEventRxProbeResponseFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN P_BSS_DESC_T prBssDesc) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; + P_WLAN_MAC_MGMT_HEADER_T prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL) && (prBssDesc != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + prP2pBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; + + /* There is a connection request. */ + prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T) prSwRfb->pvHeader; + + } while (FALSE); + +} /* p2pFsmRunEventRxProbeResponseFrame */ + +VOID p2pFsmRunEventBeaconTimeout(IN P_ADAPTER_T prAdapter) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + DBGLOG(P2P, TRACE, "p2pFsmRunEventBeaconTimeout: Beacon Timeout\n"); + + /* Only client mode would have beacon lost event. */ + ASSERT(prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE); + + if (prP2pBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + /* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + NULL, NULL, 0, REASON_CODE_DEAUTH_LEAVING_BSS, + WLAN_STATUS_MEDIA_DISCONNECT); + if (prP2pBssInfo->prStaRecOfAP != NULL) { + P_STA_RECORD_T prStaRec = prP2pBssInfo->prStaRecOfAP; + + prP2pBssInfo->prStaRecOfAP = NULL; + + p2pFuncDisconnect(prAdapter, prStaRec, FALSE, REASON_CODE_DISASSOC_LEAVING_BSS); + + /* 20120830 moved into p2pFuncDisconnect() */ + /* cnmStaRecFree(prAdapter, prP2pBssInfo->prStaRecOfAP, TRUE); */ + p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_P2P_INDEX); + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + + } + } + } while (FALSE); + +} /* p2pFsmRunEventBeaconTimeout */ + +VOID p2pFsmRunEventExtendListen(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = NULL; + struct _MSG_P2P_EXTEND_LISTEN_INTERVAL_T *prExtListenMsg = NULL; + + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + if (prMsgHdr == NULL) /* for coverity issue */ + return; + + prExtListenMsg = (struct _MSG_P2P_EXTEND_LISTEN_INTERVAL_T *) prMsgHdr; + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + ASSERT_BREAK(prP2pFsmInfo); + + if (!prExtListenMsg->wait) { + DBGLOG(P2P, TRACE, "reset listen interval\n"); + prP2pFsmInfo->eListenExted = P2P_DEV_NOT_EXT_LISTEN; + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + if (prP2pFsmInfo && (prP2pFsmInfo->eListenExted == P2P_DEV_NOT_EXT_LISTEN)) { + DBGLOG(P2P, TRACE, "try to ext listen, p2p state: %d\n", prP2pFsmInfo->eCurrentState); + if (prP2pFsmInfo->eCurrentState == P2P_STATE_CHNL_ON_HAND) { + DBGLOG(P2P, TRACE, "here to ext listen interval\n"); + prP2pFsmInfo->eListenExted = P2P_DEV_EXT_LISTEN_ING; + } + } + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pFsmRunEventUpdateMgmtFrame */ +#if CFG_SUPPORT_P2P_ECSA +VOID p2pFsmRunEventSendCSA(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + MSDU_INFO_T *prMsduInfoMgmtCSA; + + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_MSG_P2P_ECSA_T prMsgCSA = NULL; + + UINT_8 aucBcMac[] = BC_MAC_ADDR; + + if (prMsgHdr == NULL) + return; + prMsgCSA = (P_MSG_P2P_ECSA_T)prMsgHdr; + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + prMsduInfoMgmtCSA = (MSDU_INFO_T *) + cnmMgtPktAlloc(prAdapter, PUBLIC_ACTION_MAX_LEN); + + if (prMsduInfoMgmtCSA == NULL) { + DBGLOG(P2P, ERROR, " %s: allocate mgmt pkt fail\n", __func__); + return; + } + + rlmGenActionCSHdr((u8 *)prMsduInfoMgmtCSA->prPacket, + aucBcMac, + prP2pBssInfo->aucBSSID, + prP2pBssInfo->aucBSSID, CATEGORY_SPEC_MGT, 4); + + + rlmGenActionCSA((u8 *)prMsduInfoMgmtCSA->prPacket, + prMsgCSA->rP2pECSA.mode, + prMsgCSA->rP2pECSA.channel, + prMsgCSA->rP2pECSA.count, + prMsgCSA->rP2pECSA.sco); + + prMsduInfoMgmtCSA->eSrc = TX_PACKET_MGMT; + prMsduInfoMgmtCSA->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfoMgmtCSA->ucStaRecIndex = STA_REC_INDEX_BMCAST; + prMsduInfoMgmtCSA->ucNetworkType = NETWORK_TYPE_P2P_INDEX; + prMsduInfoMgmtCSA->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfoMgmtCSA->fgIs802_1x = FALSE; + prMsduInfoMgmtCSA->fgIs802_11 = TRUE; + prMsduInfoMgmtCSA->u2FrameLength = 34; /* header len + payload */ + prMsduInfoMgmtCSA->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfoMgmtCSA->pfTxDoneHandler = p2pFsmRunEventMgmtEcsaTxDone; + prMsduInfoMgmtCSA->fgIsBasicRate = TRUE; /* use basic rate */ + + /* Send them to HW queue */ + nicTxEnqueueMsdu(prAdapter, prMsduInfoMgmtCSA); + cnmMemFree(prAdapter, prMsgHdr); +} + + +VOID p2pFsmRunEventSendECSA(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + MSDU_INFO_T *prMsduInfoMgmtECSA; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_MSG_P2P_ECSA_T prMsgECSA = NULL; + + UINT_8 aucBcMac[] = BC_MAC_ADDR; + + if (prMsgHdr == NULL) + return; + prMsgECSA = (P_MSG_P2P_ECSA_T)prMsgHdr; + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + prMsduInfoMgmtECSA = (MSDU_INFO_T *) + cnmMgtPktAlloc(prAdapter, PUBLIC_ACTION_MAX_LEN); + + if (prMsduInfoMgmtECSA == NULL) { + DBGLOG(P2P, ERROR, " %s: allocate mgmt pkt fail\n", __func__); + return; + } + + rlmGenActionCSHdr((u8 *)prMsduInfoMgmtECSA->prPacket, + aucBcMac, + prP2pBssInfo->aucBSSID, + prP2pBssInfo->aucBSSID, CATEGORY_PUBLIC_ACTION, 4); + + rlmGenActionECSA((u8 *)prMsduInfoMgmtECSA->prPacket, + prMsgECSA->rP2pECSA.mode, + prMsgECSA->rP2pECSA.channel, + prMsgECSA->rP2pECSA.count, + prMsgECSA->rP2pECSA.op_class); + + prP2pBssInfo->ucOpClass = prMsgECSA->rP2pECSA.op_class; + prP2pBssInfo->ucSwitchCount = prMsgECSA->rP2pECSA.count; + prP2pBssInfo->ucSwitchMode = prMsgECSA->rP2pECSA.mode; + prP2pBssInfo->ucEcsaChannel = prMsgECSA->rP2pECSA.channel; + prP2pBssInfo->fgChanSwitching = TRUE; + + prMsduInfoMgmtECSA->eSrc = TX_PACKET_MGMT; + prMsduInfoMgmtECSA->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfoMgmtECSA->ucStaRecIndex = STA_REC_INDEX_BMCAST; + prMsduInfoMgmtECSA->ucNetworkType = NETWORK_TYPE_P2P_INDEX; + prMsduInfoMgmtECSA->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfoMgmtECSA->fgIs802_1x = FALSE; + prMsduInfoMgmtECSA->fgIs802_11 = TRUE; + prMsduInfoMgmtECSA->u2FrameLength = 30; /* header len + payload */ + prMsduInfoMgmtECSA->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfoMgmtECSA->pfTxDoneHandler = p2pFsmRunEventMgmtEcsaTxDone; + prMsduInfoMgmtECSA->fgIsBasicRate = TRUE; /* use basic rate */ + + /* Send them to HW queue */ + nicTxEnqueueMsdu(prAdapter, prMsduInfoMgmtECSA); + cnmMemFree(prAdapter, prMsgHdr); +} +#endif + +#if CFG_SUPPORT_WFD +VOID p2pFsmRunEventWfdSettingUpdate(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T prMsgWfdCfgSettings = (P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T) NULL; + WLAN_STATUS rStatus; + + DBGLOG(P2P, INFO, "p2pFsmRunEventWfdSettingUpdate\n"); + + do { + ASSERT_BREAK((prAdapter != NULL)); + + if (prMsgHdr != NULL) { + prMsgWfdCfgSettings = (P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T) prMsgHdr; + prWfdCfgSettings = prMsgWfdCfgSettings->prWfdCfgSettings; + } else { + prWfdCfgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings; + } + + DBGLOG(P2P, INFO, "WFD Enalbe %x info %x state %x flag %x adv %x\n", + prWfdCfgSettings->ucWfdEnable, + prWfdCfgSettings->u2WfdDevInfo, + (UINT_32) prWfdCfgSettings->u4WfdState, + (UINT_32) prWfdCfgSettings->u4WfdFlag, + (UINT_32) prWfdCfgSettings->u4WfdAdvancedFlag); + + if (prWfdCfgSettings->ucWfdEnable == 0) + prAdapter->prGlueInfo->prP2PInfo->u2WFDIELen = 0; + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_WFD_CTRL, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(WFD_CFG_SETTINGS_T), /* u4SetQueryInfoLen */ + (PUINT_8) prWfdCfgSettings, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + } while (FALSE); + + return; + +} + +/* p2pFsmRunEventWfdSettingUpdate */ + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to generate P2P IE for Beacon frame. +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pGenerateP2P_IEForAssocReq(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (prStaRec != NULL) { + if (IS_STA_P2P_TYPE(prStaRec)) { + /* Do nothing */ + /* TODO: */ + } + } + + } while (FALSE); + + return; + +} /* end of p2pGenerateP2P_IEForAssocReq() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to generate P2P IE for Probe Request frame. +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pGenerateP2P_IEForProbeReq(IN P_ADAPTER_T prAdapter, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize) +{ + ASSERT(prAdapter); + ASSERT(pucBuf); + + /* TODO: */ + + return; + +} /* end of p2pGenerateP2P_IEForProbReq() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to calculate P2P IE length for Beacon frame. +* +* @param[in] eNetTypeIndex Specify which network +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return The length of P2P IE added +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +p2pCalculateP2P_IELenForProbeReq(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec) +{ + + if (eNetTypeIndex != NETWORK_TYPE_P2P_INDEX) + return 0; + /* TODO: */ + + return 0; + +} /* end of p2pCalculateP2P_IELenForProbeReq() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Event of Tx Fail of AAA Module. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pRunEventAAATxFail(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + bssRemoveStaRecFromClientList(prAdapter, prBssInfo, prStaRec); + + p2pFuncDisconnect(prAdapter, prStaRec, FALSE, REASON_CODE_UNSPECIFIED); + + /* 20120830 moved into p2puUncDisconnect. */ + /* cnmStaRecFree(prAdapter, prStaRec, TRUE); */ + +} /* p2pRunEventAAATxFail */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Event of Successful Completion of AAA Module. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS p2pRunEventAAAComplete(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + ENUM_PARAM_MEDIA_STATE_T eOriMediaState; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prStaRec != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + eOriMediaState = prP2pBssInfo->eConnectionState; + + bssAddStaRecToClientList(prAdapter, prP2pBssInfo, prStaRec); + + prStaRec->u2AssocId = bssAssignAssocID(prStaRec); + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); + + /* Update Connected state to FW. */ + if (eOriMediaState != prP2pBssInfo->eConnectionState) + nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); + + } while (FALSE); + + return rStatus; +} /* p2pRunEventAAAComplete */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Event of Successful Completion of AAA Module. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS p2pRunEventAAASuccess(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; +#if CFG_SUPPORT_P2P_EAP_FAIL_WORKAROUND + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + ASSERT((prAdapter != NULL)); + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prP2pBssInfo->fgP2PPendingDeauth = FALSE; + prP2pBssInfo->u4P2PEapTxDoneTime = 0; +#endif + 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 */ +#if CFG_SUPPORT_P2P_ECSA +WLAN_STATUS p2pUpdateBeaconEcsaIE(IN P_ADAPTER_T prAdapter, IN UINT_8 ucNetTypeIndex) +{ + if (!prAdapter) + return WLAN_STATUS_FAILURE; + + return bssUpdateBeaconContent(prAdapter, ucNetTypeIndex); +} +#endif + +VOID +p2pProcessEvent_UpdateNOAParam(IN P_ADAPTER_T prAdapter, + UINT_8 ucNetTypeIndex, P_EVENT_UPDATE_NOA_PARAMS_T prEventUpdateNoaParam) +{ + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo; + UINT_32 i; + BOOLEAN fgNoaAttrExisted = FALSE; + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[ucNetTypeIndex]); + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + prP2pSpecificBssInfo->fgEnableOppPS = prEventUpdateNoaParam->fgEnableOppPS; + prP2pSpecificBssInfo->u2CTWindow = prEventUpdateNoaParam->u2CTWindow; + prP2pSpecificBssInfo->ucNoAIndex = prEventUpdateNoaParam->ucNoAIndex; + prP2pSpecificBssInfo->ucNoATimingCount = prEventUpdateNoaParam->ucNoATimingCount; + + fgNoaAttrExisted |= prP2pSpecificBssInfo->fgEnableOppPS; + + DBGLOG(P2P, INFO, "Update NoA Count=%d.\n", prEventUpdateNoaParam->ucNoATimingCount); + + ASSERT(prP2pSpecificBssInfo->ucNoATimingCount <= P2P_MAXIMUM_NOA_COUNT); + + for (i = 0; i < prP2pSpecificBssInfo->ucNoATimingCount; i++) { + /* in used */ + prP2pSpecificBssInfo->arNoATiming[i].fgIsInUse = prEventUpdateNoaParam->arEventNoaTiming[i].fgIsInUse; + /* count */ + prP2pSpecificBssInfo->arNoATiming[i].ucCount = prEventUpdateNoaParam->arEventNoaTiming[i].ucCount; + /* duration */ + prP2pSpecificBssInfo->arNoATiming[i].u4Duration = prEventUpdateNoaParam->arEventNoaTiming[i].u4Duration; + /* interval */ + prP2pSpecificBssInfo->arNoATiming[i].u4Interval = prEventUpdateNoaParam->arEventNoaTiming[i].u4Interval; + /* start time */ + prP2pSpecificBssInfo->arNoATiming[i].u4StartTime = + prEventUpdateNoaParam->arEventNoaTiming[i].u4StartTime; + + fgNoaAttrExisted |= prP2pSpecificBssInfo->arNoATiming[i].fgIsInUse; + } + + prP2pSpecificBssInfo->fgIsNoaAttrExisted = fgNoaAttrExisted; + + /* update beacon content by the change */ + bssUpdateBeaconContent(prAdapter, ucNetTypeIndex); +} + +VOID p2pFsmNotifyTxStatus(IN P_ADAPTER_T prAdapter, UINT_8 *pucEvtBuf) +{ + EVENT_TX_DONE_STATUS_T *prTxDone; + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + PUINT_8 pucPkt; + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + prTxDone = (EVENT_TX_DONE_STATUS_T *) pucEvtBuf; + pucPkt = &prTxDone->aucPktBuf[64]; + + if (prBssInfo == NULL || prP2pFsmInfo == NULL || prTxDone == NULL || + pucPkt == NULL) + return; + + if (prBssInfo->eConnectionState != PARAM_MEDIA_STATE_CONNECTED || + prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + return; + + if (prP2pFsmInfo->eCurrentState != P2P_STATE_GC_JOIN) + return; + + if (secGetEapolKeyType(pucPkt) == EAPOL_KEY_4_OF_4 && + prTxDone->ucStatus == 0) { + /* Finish GC connection process. */ + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + } +} + +VOID p2pFsmNotifyRxP2pActionFrame(IN P_ADAPTER_T prAdapter, + IN enum P2P_ACTION_FRAME_TYPE eP2pFrameType, + OUT u_int8_t *prFgBufferFrame) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + if (prP2pFsmInfo->eCurrentState != P2P_STATE_CHNL_ON_HAND && + prP2pBssInfo->eConnectionState != PARAM_MEDIA_STATE_CONNECTED) { + switch (eP2pFrameType) { + case P2P_INVITATION_REQ: + *prFgBufferFrame = TRUE; + break; + default: + break; + } + return; + } + + if (prP2pFsmInfo->eCNNState != P2P_CNN_NORMAL) + return; + + switch (eP2pFrameType) { + case P2P_GO_NEG_REQ: + case P2P_GO_NEG_RESP: + case P2P_INVITATION_REQ: + case P2P_DEV_DISC_REQ: + case P2P_PROV_DISC_REQ: + DBGLOG(P2P, INFO, "Extend channel duration, p2pFrameType: %d.\n", eP2pFrameType); + prP2pFsmInfo->eCNNState = eP2pFrameType + 1; + break; + default: + break; + } +} + +static void initAcsParams(IN P_ADAPTER_T prAdapter, + IN struct MSG_P2P_ACS_REQUEST *prMsgAcsRequest, + IN struct P2P_ACS_REQ_INFO *prAcsReqInfo) { + P_RF_CHANNEL_INFO_T prRfChannelInfo; + uint8_t i; + + if (!prAdapter || !prMsgAcsRequest || !prAcsReqInfo) + return; + + prAcsReqInfo->fgIsProcessing = TRUE; + prAcsReqInfo->fgIsHtEnable = prMsgAcsRequest->fgIsHtEnable; + prAcsReqInfo->fgIsHt40Enable = prMsgAcsRequest->fgIsHt40Enable; + prAcsReqInfo->fgIsVhtEnable = prMsgAcsRequest->fgIsVhtEnable; + prAcsReqInfo->eChnlBw = prMsgAcsRequest->eChnlBw; + prAcsReqInfo->eHwMode = prMsgAcsRequest->eHwMode; + + if (prAcsReqInfo->eChnlBw == MAX_BW_UNKNOWN) { + if (prAcsReqInfo->fgIsHtEnable && + prAcsReqInfo->fgIsHt40Enable) { + prAcsReqInfo->eChnlBw = MAX_BW_40MHZ; + } else { + prAcsReqInfo->eChnlBw = MAX_BW_20MHZ; + } + } + + DBGLOG(P2P, INFO, "ht=%d, ht40=%d, vht=%d, bw=%d, mode=%d", + prMsgAcsRequest->fgIsHtEnable, + prMsgAcsRequest->fgIsHt40Enable, + prMsgAcsRequest->fgIsVhtEnable, + prMsgAcsRequest->eChnlBw, + prMsgAcsRequest->eHwMode); + if (prMsgAcsRequest->u4NumChannel) { + for (i = 0; i < prMsgAcsRequest->u4NumChannel; i++) { + prRfChannelInfo = + &(prMsgAcsRequest->arChannelListInfo[i]); + DBGLOG(REQ, INFO, "[%d] band=%d, ch=%d\n", i, + prRfChannelInfo->eBand, + prRfChannelInfo->ucChannelNum); + prRfChannelInfo++; + } + } +} + +static void trimAcsScanList(IN P_ADAPTER_T prAdapter, + IN struct MSG_P2P_ACS_REQUEST *prMsgAcsRequest, + IN struct P2P_ACS_REQ_INFO *prAcsReqInfo, + IN ENUM_BAND_T eBand) +{ + uint32_t u4NumChannel = 0; + uint8_t i; + P_RF_CHANNEL_INFO_T prRfChannelInfo1; + P_RF_CHANNEL_INFO_T prRfChannelInfo2; + + if (!prAdapter || !prAcsReqInfo) + return; + + for (i = 0; i < prMsgAcsRequest->u4NumChannel; i++) { + prRfChannelInfo1 = + &(prMsgAcsRequest->arChannelListInfo[i]); + if (eBand == prRfChannelInfo1->eBand) { + prRfChannelInfo2 = &(prMsgAcsRequest->arChannelListInfo[ + u4NumChannel]); + prRfChannelInfo2->eBand = prRfChannelInfo1->eBand; + prRfChannelInfo2->ucChannelNum = + prRfChannelInfo1->ucChannelNum; + prRfChannelInfo2->eDFS = prRfChannelInfo1->eDFS; + u4NumChannel++; + DBGLOG(P2P, INFO, "acs trim scan list, [%d]=%d %d\n", + u4NumChannel, + prRfChannelInfo1->eBand, + prRfChannelInfo2->ucChannelNum); + } + prRfChannelInfo1++; + } + prMsgAcsRequest->u4NumChannel = u4NumChannel; +} + +static void initAcsChnlMask(IN P_ADAPTER_T prAdapter, + IN struct MSG_P2P_ACS_REQUEST *prMsgAcsRequest, + IN struct P2P_ACS_REQ_INFO *prAcsReqInfo) +{ + uint8_t i; + P_RF_CHANNEL_INFO_T prRfChannelInfo; + + prAcsReqInfo->u4LteSafeChnMask_2G = 0; + prAcsReqInfo->u4LteSafeChnMask_5G_1 = 0; + prAcsReqInfo->u4LteSafeChnMask_5G_2 = 0; + + for (i = 0; i < prMsgAcsRequest->u4NumChannel; i++) { + prRfChannelInfo = &(prMsgAcsRequest->arChannelListInfo[i]); + if (prRfChannelInfo->ucChannelNum <= 14) { + prAcsReqInfo->u4LteSafeChnMask_2G |= BIT( + prRfChannelInfo->ucChannelNum); + } else if (prRfChannelInfo->ucChannelNum >= 36 && + prRfChannelInfo->ucChannelNum <= 144) { + prAcsReqInfo->u4LteSafeChnMask_5G_1 |= BIT( + (prRfChannelInfo->ucChannelNum - 36) / 4); + } else if (prRfChannelInfo->ucChannelNum >= 149 && + prRfChannelInfo->ucChannelNum <= 181) { + prAcsReqInfo->u4LteSafeChnMask_5G_2 |= BIT( + (prRfChannelInfo->ucChannelNum - 149) / 4); + } + } + + DBGLOG(P2P, INFO, "acs chnl mask=[0x%08x][0x%08x][0x%08x]\n", + prAcsReqInfo->u4LteSafeChnMask_2G, + prAcsReqInfo->u4LteSafeChnMask_5G_1, + prAcsReqInfo->u4LteSafeChnMask_5G_2); +} + +void p2pFsmRunEventAcs(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + struct MSG_P2P_ACS_REQUEST *prMsgAcsRequest; + P_P2P_FSM_INFO_T prP2pFsmInfo; + P_MSG_P2P_SCAN_REQUEST_T prP2pScanReqMsg; + struct P2P_ACS_REQ_INFO *prAcsReqInfo; + uint32_t u4MsgSize = 0; + + if (!prAdapter || !prMsgHdr) + return; + + prMsgAcsRequest = (struct MSG_P2P_ACS_REQUEST *) prMsgHdr; + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + prAcsReqInfo = &prP2pFsmInfo->rAcsReqInfo; + + p2pFsmAbortCurrentAcsReq(prAdapter, prMsgAcsRequest); + + initAcsParams(prAdapter, prMsgAcsRequest, prAcsReqInfo); + + if (prAcsReqInfo->eHwMode == P2P_VENDOR_ACS_HW_MODE_11ANY) { + if (prAdapter->fgEnable5GBand) { + trimAcsScanList(prAdapter, prMsgAcsRequest, + prAcsReqInfo, BAND_5G); + prAcsReqInfo->eHwMode = P2P_VENDOR_ACS_HW_MODE_11A; + } else { + trimAcsScanList(prAdapter, prMsgAcsRequest, + prAcsReqInfo, BAND_2G4); + prAcsReqInfo->eHwMode = P2P_VENDOR_ACS_HW_MODE_11G; + } + } + + initAcsChnlMask(prAdapter, prMsgAcsRequest, prAcsReqInfo); + + if (prAcsReqInfo->eHwMode == P2P_VENDOR_ACS_HW_MODE_11A) { + p2pFunCalAcsChnScores(prAdapter, + BAND_5G); + p2pFunProcessAcsReport(prAdapter, + NULL, + prAcsReqInfo); + goto exit; + } + + u4MsgSize = sizeof(MSG_P2P_SCAN_REQUEST_T) + ( + prMsgAcsRequest->u4NumChannel * + sizeof(RF_CHANNEL_INFO_T)); + + prP2pScanReqMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, u4MsgSize); + if (prP2pScanReqMsg == NULL) { + DBGLOG(P2P, ERROR, "alloc scan req. fail\n"); + return; + } + kalMemSet(prP2pScanReqMsg, 0, u4MsgSize); + prP2pScanReqMsg->i4SsidNum = 0; + prP2pScanReqMsg->u4NumChannel = prMsgAcsRequest->u4NumChannel; + prP2pScanReqMsg->u4IELen = 0; + prP2pScanReqMsg->fgIsAcsReq = TRUE; + kalMemCopy(&(prP2pScanReqMsg->arChannelListInfo), + &(prMsgAcsRequest->arChannelListInfo), + (prMsgAcsRequest->u4NumChannel * + sizeof(RF_CHANNEL_INFO_T))); + p2pFsmRunEventScanRequest(prAdapter, (P_MSG_HDR_T) prP2pScanReqMsg); + +exit: + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} + +static u_int8_t p2pFsmIsAcsProcessing(IN P_ADAPTER_T prAdapter) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo; + struct P2P_ACS_REQ_INFO *prAcsReqInfo; + + if (!prAdapter) + return FALSE; + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + if (!prP2pFsmInfo) + return FALSE; + + prAcsReqInfo = &prP2pFsmInfo->rAcsReqInfo; + if (!prAcsReqInfo) + return FALSE; + + return prAcsReqInfo->fgIsProcessing; +} + +static void +p2pFsmAbortCurrentAcsReq(IN P_ADAPTER_T prAdapter, + IN struct MSG_P2P_ACS_REQUEST *prMsgAcsRequest) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo; + P_P2P_SCAN_REQ_INFO_T prScanReqInfo = NULL; + + if (!prAdapter || !prMsgAcsRequest) + return; + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + prScanReqInfo = &(prP2pFsmInfo->rScanReqInfo); + + if (!p2pFsmIsAcsProcessing(prAdapter)) + return; + + if (prP2pFsmInfo->eCurrentState == P2P_STATE_SCAN && + prScanReqInfo->fgIsAcsReq) { + DBGLOG(P2P, INFO, "Cancel current ACS scan.\n"); + p2pFsmRunEventAbort(prAdapter, prP2pFsmInfo); + } +} + +#endif /* CFG_ENABLE_WIFI_DIRECT */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_func.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_func.c new file mode 100644 index 0000000000000..dfdb482fa8d63 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_func.c @@ -0,0 +1,4473 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#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 */ + , {(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 */ +#if CFG_SUPPORT_MTK_SYNERGY + , {(ELEM_HDR_LEN + ELEM_MIN_LEN_MTK_OUI), NULL, rlmGenerateMTKOuiIE} /* 221 */ +#endif +}; +#if CFG_SUPPORT_P2P_EAP_FAIL_WORKAROUND +#define P2P_DEAUTH_DELAY_TIME 50 /*ms*/ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Function for requesting scan. There is an option to do ACTIVE or PASSIVE scan. +* +* @param eScanType - Specify the scan type of the scan request. It can be an ACTIVE/PASSIVE +* Scan. +* eChannelSet - Specify the preferred channel set. +* A FULL scan would request a legacy full channel normal scan.(usually ACTIVE). +* A P2P_SOCIAL scan would scan 1+6+11 channels.(usually ACTIVE) +* A SPECIFIC scan would only 1/6/11 channels scan. (Passive Listen/Specific Search) +* ucChannelNum - A specific channel number. (Only when channel is specified) +* eBand - A specific band. (Only when channel is specified) +* +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFuncRequestScan(IN P_ADAPTER_T prAdapter, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo) +{ + + P_MSG_SCN_SCAN_REQ prScanReq = (P_MSG_SCN_SCAN_REQ) NULL; + UINT_8 aucP2pSsid[] = P2P_WILDCARD_SSID; + /*NFC Beam + Indication */ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + do { + ASSERT_BREAK((prAdapter != NULL) && (prScanReqInfo != NULL)); + + 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; + } + + kalMemZero(prScanReq, sizeof(MSG_SCN_SCAN_REQ)); + prScanReq->rMsgHdr.eMsgId = MID_P2P_SCN_SCAN_REQ; + prScanReq->ucSeqNum = ++prScanReqInfo->ucSeqNumOfScnMsg; + prScanReq->ucNetTypeIndex = (UINT_8) NETWORK_TYPE_P2P_INDEX; + prScanReq->eScanType = prScanReqInfo->eScanType; + + COPY_SSID(prScanReq->aucSSID, + prScanReq->ucSSIDLength, + prScanReqInfo->rSsidStruct.aucSsid, prScanReqInfo->rSsidStruct.ucSsidLen); + + 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; + else + prScanReq->ucSSIDType = SCAN_REQ_SSID_WILDCARD; + + prScanReq->u2ChannelDwellTime = prScanReqInfo->u2PassiveDewellTime; + prScanReq->u2MinChannelDwellTime = prScanReq->u2ChannelDwellTime; + COPY_MAC_ADDR(prScanReq->aucBSSID, "\xff\xff\xff\xff\xff\xff"); + + prScanReq->eScanChannel = prScanReqInfo->eChannelSet; + if (prScanReqInfo->eChannelSet == SCAN_CHANNEL_SPECIFIED) { + UINT_32 u4Idx = 0; + P_RF_CHANNEL_INFO_T prChnInfo = prScanReqInfo->arScanChannelList; + + ASSERT_BREAK(prScanReqInfo->ucNumChannelList > 0); + + if (prScanReqInfo->ucNumChannelList > MAXIMUM_OPERATION_CHANNEL_LIST) + prScanReqInfo->ucNumChannelList = MAXIMUM_OPERATION_CHANNEL_LIST; + + for (u4Idx = 0; u4Idx < prScanReqInfo->ucNumChannelList; u4Idx++) { + prScanReq->arChnlInfoList[u4Idx].ucChannelNum = prChnInfo->ucChannelNum; + prScanReq->arChnlInfoList[u4Idx].eBand = prChnInfo->eBand; + prChnInfo++; + } + + prScanReq->ucChannelListNum = prScanReqInfo->ucNumChannelList; + } + + /* Copy IE for Probe Request */ + if (prScanReqInfo->u4BufLength > MAX_IE_LENGTH) + prScanReqInfo->u4BufLength = MAX_IE_LENGTH; + + kalMemCopy(prScanReq->aucIE, prScanReqInfo->aucIEBuf, prScanReqInfo->u4BufLength); + prScanReq->u2IELen = (UINT_16) prScanReqInfo->u4BufLength; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanReq, MSG_SEND_METHOD_BUF); + + } while (FALSE); + +} /* p2pFuncRequestScan */ + +VOID p2pFuncCancelScan(IN P_ADAPTER_T prAdapter, IN P_P2P_SCAN_REQ_INFO_T prScanInfo) +{ + P_MSG_SCN_SCAN_CANCEL prScanCancelMsg = (P_MSG_SCN_SCAN_CANCEL) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prScanInfo != NULL)); + + if (!prScanInfo->fgIsScanRequest) + break; + + /* There is a channel privilege on hand. */ + DBGLOG(P2P, TRACE, "P2P Cancel Scan\n"); + + prScanCancelMsg = (P_MSG_SCN_SCAN_CANCEL) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_CANCEL)); + if (!prScanCancelMsg) { + /* Buffer not enough, can not cancel scan request. */ + DBGLOG(P2P, TRACE, "Buffer not enough, can not cancel scan.\n"); + ASSERT(FALSE); + break; + } + + prScanCancelMsg->rMsgHdr.eMsgId = MID_P2P_SCN_SCAN_CANCEL; + prScanCancelMsg->ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + prScanCancelMsg->ucSeqNum = prScanInfo->ucSeqNumOfScnMsg++; + prScanCancelMsg->fgIsChannelExt = FALSE; + prScanInfo->fgIsScanRequest = FALSE; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanCancelMsg, MSG_SEND_METHOD_BUF); + } while (FALSE); + +} /* p2pFuncCancelScan */ + +VOID p2pFuncSwitchOPMode(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, IN ENUM_OP_MODE_T eOpMode, IN BOOLEAN fgSyncToFW) +{ + P2P_DISCONNECT_INFO rP2PDisInfo; + + if (!prAdapter) { + DBGLOG(P2P, ERROR, "prAdapter NULL!\n"); + return; + } + + if (!prAdapter->prGlueInfo) { + DBGLOG(P2P, ERROR, "prGlueInfo NULL!\n"); + return; + } + + if (prAdapter->prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(P2P, ERROR, "GLUE_FLAG_HALT is set!\n"); + return; + } + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL) && (eOpMode < OP_MODE_NUM)); + + if (prP2pBssInfo->eCurrentOPMode != eOpMode) { + DBGLOG(P2P, TRACE, "Switch OP mode from %d to %d\n", prP2pBssInfo->eCurrentOPMode, eOpMode); + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_ACCESS_POINT: + if (prP2pBssInfo->eIntendOPMode + != OP_MODE_P2P_DEVICE) { + p2pFuncDissolve(prAdapter, + prP2pBssInfo, TRUE, + REASON_CODE_DEAUTH_LEAVING_BSS); + + p2pFsmRunEventStopAP(prAdapter, NULL); + } else if (IS_NET_PWR_STATE_IDLE(prAdapter, + NETWORK_TYPE_P2P_INDEX) && + IS_NET_ACTIVE(prAdapter, + NETWORK_TYPE_P2P_INDEX)) { + DBGLOG(P2P, TRACE, + "under deauth procedure, Quit.\n"); + return; + } + break; + default: + break; + } + + prP2pBssInfo->eIntendOPMode = eOpMode; + prP2pBssInfo->eCurrentOPMode = eOpMode; + + switch (eOpMode) { + case OP_MODE_INFRASTRUCTURE: + case OP_MODE_ACCESS_POINT: + /* Change interface address. */ + COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, prAdapter->rWifiVar.aucInterfaceAddress); + COPY_MAC_ADDR(prP2pBssInfo->aucBSSID, prAdapter->rWifiVar.aucInterfaceAddress); + + break; + case OP_MODE_P2P_DEVICE: + p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + + /* Change device address. */ + COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, prAdapter->rWifiVar.aucDeviceAddress); + COPY_MAC_ADDR(prP2pBssInfo->aucBSSID, prAdapter->rWifiVar.aucDeviceAddress); + + break; + default: + ASSERT(FALSE); + break; + } + + DBGLOG(P2P, TRACE, "The device address is changed to %pM\n", prP2pBssInfo->aucOwnMacAddr); + DBGLOG(P2P, TRACE, "The BSSID is changed to %pM\n", prP2pBssInfo->aucBSSID); + + rP2PDisInfo.ucRole = 2; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_P2P_ABORT, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(P2P_DISCONNECT_INFO), (PUINT_8)&rP2PDisInfo, NULL, 0); + + /* Update BSS INFO to FW. */ + if ((fgSyncToFW) && (eOpMode != OP_MODE_ACCESS_POINT)) + nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); + } else if (prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE && + eOpMode == OP_MODE_INFRASTRUCTURE) { + P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo = (P_P2P_CONNECTION_REQ_INFO_T) NULL; + + prConnReqInfo = &(prAdapter->rWifiVar.prP2pFsmInfo->rConnReqInfo); + + if (prConnReqInfo && prConnReqInfo->fgIsConnRequest == TRUE) { + DBGLOG(P2P, WARN, "Force stop connection request since mode switch.\n"); + prConnReqInfo->fgIsConnRequest = FALSE; + } + } + + } while (FALSE); + +} /* p2pFuncSwitchOPMode */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will start a P2P Group Owner and send Beacon Frames. +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFuncStartGO(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, + IN UINT_8 ucChannelNum, IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN BOOLEAN fgIsPureAP) +{ + do { + ASSERT_BREAK((prAdapter != NULL) && (prBssInfo != NULL)); + + prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsGOInitialDone = 1; + + /* 4 <1.1> Switch to AP mode */ + p2pFuncSwitchOPMode(prAdapter, prBssInfo, prBssInfo->eIntendOPMode, FALSE); + ASSERT(prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT); + prBssInfo->eIntendOPMode = OP_MODE_NUM; + + /* 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> Set Channel, Band, SCO */ + prBssInfo->ucPrimaryChannel = ucChannelNum; + prBssInfo->eBand = eBand; + prBssInfo->eBssSCO = eSco; + + /* 4 <1.4> Set PHY type */ + /* 11n */ + if (prAdapter->rWifiVar.ucWithPhyTypeSpecificIE & PHY_TYPE_SET_802_11N) + prBssInfo->ucPhyTypeSet |= PHY_TYPE_SET_802_11N; + /* 11g */ + if (prAdapter->rWifiVar.ucWithPhyTypeSpecificIE & PHY_TYPE_SET_802_11G) + prBssInfo->ucPhyTypeSet |= PHY_TYPE_SET_802_11G; + + if (prBssInfo->eBand == BAND_5G) { + ASSERT(prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11A); + prBssInfo->ucPhyTypeSet |= PHY_TYPE_SET_802_11A; + prBssInfo->ucConfigAdHocAPMode = AP_MODE_11A; + } else { /* prBssInfo->eBand == BAND_2G4 */ + if (fgIsPureAP) { + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11BG) { + ASSERT(prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11BG); + prBssInfo->ucPhyTypeSet |= PHY_TYPE_SET_802_11BG; + prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; + } else if (prBssInfo->ucPhyTypeSet & PHY_TYPE_SET_802_11G) { + ASSERT(prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11G); + prBssInfo->ucConfigAdHocAPMode = AP_MODE_11G; + } else { + ASSERT(prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11B); + prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11B; + prBssInfo->ucConfigAdHocAPMode = AP_MODE_11B; + } + } else { + ASSERT(prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11G); + prBssInfo->ucPhyTypeSet |= PHY_TYPE_SET_802_11G; + prBssInfo->ucConfigAdHocAPMode = AP_MODE_11G_P2P; + } + } + + if (prAdapter->rWifiVar.prP2pSpecificBssInfo) { + prAdapter->rWifiVar.prP2pSpecificBssInfo->ucNoAIndex = 0; + prAdapter->rWifiVar.prP2pSpecificBssInfo->ucNoATimingCount = 0; + prAdapter->rWifiVar.prP2pSpecificBssInfo->fgIsNoaAttrExisted = FALSE; + kalMemZero(prAdapter->rWifiVar.prP2pSpecificBssInfo->arNoATiming, + sizeof(prAdapter->rWifiVar.prP2pSpecificBssInfo->arNoATiming)); + } else + DBGLOG(BSS, WARN, "p2pFuncStartGO prP2pSpecificBssInfo is NULL"); + + DBGLOG(P2P, INFO, "NFC Done[%d] AP Channel=%d, Band=%d, SCO=%d, Phy=%d\n", + prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsGOInitialDone, + ucChannelNum, eBand, eSco, prBssInfo->ucPhyTypeSet); + + /* 4 <1.5> Setup MIB for current BSS */ + prBssInfo->u2ATIMWindow = 0; + prBssInfo->ucBeaconTimeoutCount = 0; + + /* 3 <2> Update BSS-INFO parameters */ + 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; + } + + bssInitForAP(prAdapter, prBssInfo, TRUE); + + nicQmUpdateWmmParms(prAdapter, NETWORK_TYPE_P2P_INDEX); + + /* 3 <3> Set MAC HW */ + /* 4 <3.1> Set SCO and Bandwidth */ + rlmBssInitForAPandIbss(prAdapter, prBssInfo); + + /* 4 <3.2> Update BSS-INFO to FW */ + nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); + + /* 4 <3.3> Re-compose and update Beacon content to FW after PHY type confirmed */ + bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_P2P_INDEX); + + /* 4 <3.4> Start Beaconing */ + nicPmIndicateBssCreated(prAdapter, NETWORK_TYPE_P2P_INDEX); + + } while (FALSE); + +} /* p2pFuncStartGO() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is to inform CNM that channel privilege +* has been released +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFuncReleaseCh(IN P_ADAPTER_T prAdapter, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo) +{ + P_MSG_CH_ABORT_T prMsgChRelease = (P_MSG_CH_ABORT_T) NULL; + + DEBUGFUNC("p2pFuncReleaseCh()"); + + do { + ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL)); + + if (!prChnlReqInfo->fgIsChannelRequested) + break; + + DBGLOG(P2P, TRACE, "P2P Release Channel\n"); + prChnlReqInfo->fgIsChannelRequested = FALSE; + + /* 1. return channel privilege to CNM immediately */ + prMsgChRelease = (P_MSG_CH_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_ABORT_T)); + if (!prMsgChRelease) { + ASSERT(0); /* Can't release Channel to CNM */ + break; + } + + prMsgChRelease->rMsgHdr.eMsgId = MID_MNY_CNM_CH_ABORT; + prMsgChRelease->ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + prMsgChRelease->ucTokenID = prChnlReqInfo->ucSeqNumOfChReq++; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChRelease, MSG_SEND_METHOD_BUF); + + } while (FALSE); + +} /* p2pFuncReleaseCh */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process of CHANNEL_REQ_JOIN Initial. Enter CHANNEL_REQ_JOIN State. +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFuncAcquireCh(IN P_ADAPTER_T prAdapter, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo) +{ + P_MSG_CH_REQ_T prMsgChReq = (P_MSG_CH_REQ_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL)); + + p2pFuncReleaseCh(prAdapter, prChnlReqInfo); + + /* send message to CNM for acquiring channel */ + prMsgChReq = (P_MSG_CH_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_REQ_T)); + + if (!prMsgChReq) { + ASSERT(0); /* Can't indicate CNM for channel acquiring */ + break; + } + + prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; + prMsgChReq->ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + prMsgChReq->ucTokenID = ++prChnlReqInfo->ucSeqNumOfChReq; + prMsgChReq->eReqType = CH_REQ_TYPE_JOIN; + prMsgChReq->u4MaxInterval = prChnlReqInfo->u4MaxInterval; + + prMsgChReq->ucPrimaryChannel = prChnlReqInfo->ucReqChnlNum; + prMsgChReq->eRfSco = prChnlReqInfo->eChnlSco; + prMsgChReq->eRfBand = prChnlReqInfo->eBand; + + kalMemZero(prMsgChReq->aucBSSID, MAC_ADDR_LEN); + + /* Channel request join BSSID. */ + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChReq, MSG_SEND_METHOD_BUF); + + prChnlReqInfo->fgIsChannelRequested = TRUE; + + } while (FALSE); + +} /* p2pFuncAcquireCh */ + +WLAN_STATUS p2pFuncProcessBeacon(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 pucCachedIEBuf = (PUINT_8) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prBcnUpdateInfo != NULL)); + + prBcnMsduInfo = prP2pBssInfo->prBeacon; + + prBcnFrame = (P_WLAN_BEACON_FRAME_T) ((ULONG) prBcnMsduInfo->prPacket + MAC_TX_RESERVED_FIELD); + + /* Beacon template from upper layer (without TIM IE) */ + + if (prBcnUpdateInfo->pucBcnHdr != NULL) + ASSERT(prBcnUpdateInfo->pucBcnHdr == (PUINT_8)prBcnFrame); + + if (prBcnUpdateInfo->pucBcnBody != NULL) + ASSERT(prBcnUpdateInfo->pucBcnBody == + (prBcnUpdateInfo->pucBcnHdr + prBcnUpdateInfo->u4BcnHdrLen)); + + if (!pucNewBcnBody) { + /* Cache old Beacon body in case of only new Beacon head update. */ + pucNewBcnBody = prBcnUpdateInfo->pucBcnBody; + ASSERT(u4NewBodyLen == 0); + u4NewBodyLen = prBcnUpdateInfo->u4BcnBodyLen; + } + + pucCachedIEBuf = kalMemAlloc(MAX_IE_LENGTH, VIR_MEM_TYPE); + if (pucCachedIEBuf == NULL) { + DBGLOG(P2P, ERROR, "Failed to allocate memory for cached IE buf\n"); + return WLAN_STATUS_FAILURE; + } + + kalMemCopy(pucCachedIEBuf, pucNewBcnBody, u4NewBodyLen); + + if (pucNewBcnHdr) { + kalMemCopy(prBcnFrame, pucNewBcnHdr, u4NewHdrLen); + prBcnUpdateInfo->pucBcnHdr = (PUINT_8) prBcnFrame; + prBcnUpdateInfo->u4BcnHdrLen = u4NewHdrLen; + } + + prBcnUpdateInfo->pucBcnBody = prBcnUpdateInfo->pucBcnHdr + prBcnUpdateInfo->u4BcnHdrLen; + kalMemCopy(prBcnUpdateInfo->pucBcnBody, pucCachedIEBuf, u4NewBodyLen); + prBcnUpdateInfo->u4BcnBodyLen = u4NewBodyLen; + + kalMemFree(pucCachedIEBuf, VIR_MEM_TYPE, MAX_IE_LENGTH); + + /* Frame Length */ + prBcnMsduInfo->u2FrameLength = (UINT_16) (prBcnUpdateInfo->u4BcnHdrLen + prBcnUpdateInfo->u4BcnBodyLen); + prBcnMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prBcnMsduInfo->fgIs802_11 = TRUE; + prBcnMsduInfo->ucNetworkType = NETWORK_TYPE_P2P_INDEX; + + /* Parse Beacon header */ + COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, prBcnFrame->aucSrcAddr); + COPY_MAC_ADDR(prP2pBssInfo->aucBSSID, prBcnFrame->aucBSSID); + prP2pBssInfo->u2BeaconInterval = prBcnFrame->u2BeaconInterval; + prP2pBssInfo->u2CapInfo = prBcnFrame->u2CapInfo; + + /* Parse Beacon IEs */ + p2pFuncParseBeaconIEs(prAdapter, + prP2pBssInfo, + prBcnFrame->aucInfoElem, + (prBcnMsduInfo->u2FrameLength - OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem))); + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncProcessBeacon */ + +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP +WLAN_STATUS p2pFuncUpdateProbeRspIEs(IN P_ADAPTER_T prAdapter, IN P_MSG_P2P_BEACON_UPDATE_T prIETemp, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex) +{ + P_BSS_INFO_T prBssInfo; + P_MSDU_INFO_T prMsduInfo; + UINT_32 u4IeArraySize = 0, u4Idx = 0; + P_UINT_8 pucP2pIe = NULL; + P_UINT_8 pucWpsIe = NULL; + P_UINT_8 pucWfdIe = NULL; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = NULL; + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + /* reuse beacon MsduInfo */ + prMsduInfo = prBssInfo->prBeacon; + + /* beacon prMsduInfo will be NULLify once BSS deactivated, so skip if it is */ + if (!prMsduInfo) + return WLAN_STATUS_SUCCESS; + + if (!prIETemp->pucProbeRsp) { + DBGLOG(BSS, INFO, "change beacon: has no extra probe response IEs\n"); + return WLAN_STATUS_SUCCESS; + } + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) { + DBGLOG(BSS, INFO, "change beacon: pure Ap mode do not add extra probe response IEs\n"); + return WLAN_STATUS_SUCCESS; + } + prMsduInfo->u2FrameLength = 0; + + bssBuildBeaconProbeRespFrameCommonIEs(prMsduInfo, prBssInfo, prIETemp->pucProbeRsp); + + u4IeArraySize = sizeof(txProbeRspIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); + + for (u4Idx = 0; u4Idx < u4IeArraySize; u4Idx++) { + if (txProbeRspIETable[u4Idx].pfnAppendIE) + txProbeRspIETable[u4Idx].pfnAppendIE(prAdapter, prMsduInfo); + } + + /* process probe response IE from supplicant */ + pucP2pIe = (P_UINT_8) cfg80211_find_vendor_ie(WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P, + prIETemp->pucProbeRsp, + prIETemp->u4ProbeRsp_len); + + pucWfdIe = (P_UINT_8) cfg80211_find_vendor_ie(WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P + 1, + prIETemp->pucProbeRsp, + prIETemp->u4ProbeRsp_len); + + pucWpsIe = (P_UINT_8) cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WPS, + prIETemp->pucProbeRsp, + prIETemp->u4ProbeRsp_len); + + if (pucP2pIe) { + kalMemCopy(prMsduInfo->prPacket + prMsduInfo->u2FrameLength, + pucP2pIe, IE_SIZE(pucP2pIe)); + prMsduInfo->u2FrameLength += IE_SIZE(pucP2pIe); + } + + if (pucWfdIe) { + kalMemCopy(prMsduInfo->prPacket + prMsduInfo->u2FrameLength, + pucWfdIe, IE_SIZE(pucWfdIe)); + prMsduInfo->u2FrameLength += IE_SIZE(pucWfdIe); + } + + if (pucWpsIe) { + kalMemCopy(prMsduInfo->prPacket + prMsduInfo->u2FrameLength, + pucWpsIe, IE_SIZE(pucWpsIe)); + prMsduInfo->u2FrameLength += IE_SIZE(pucWpsIe); + } + + kalMemFree(prIETemp->pucProbeRsp, VIR_MEM_TYPE, prIETemp->u4ProbeRsp_len); + + DBGLOG(BSS, INFO, "update probe response for network index: %d, IE len: %d\n", + eNetTypeIndex, prMsduInfo->u2FrameLength); + /* dumpMemory8(prMsduInfo->prPacket, prMsduInfo->u2FrameLength); */ + + return nicUpdateBeaconIETemplate(prAdapter, + IE_UPD_METHOD_UPDATE_PROBE_RSP, + eNetTypeIndex, + prBssInfo->u2CapInfo, + prMsduInfo->prPacket, + prMsduInfo->u2FrameLength); +} +#endif /*CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP*/ + +/* TODO: We do not apply IE in deauth frame set from upper layer now. */ +WLAN_STATUS +p2pFuncDeauth(IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucPeerMacAddr, + IN UINT_16 u2ReasonCode, IN PUINT_8 pucIEBuf, IN UINT_16 u2IELen, IN BOOLEAN fgSendDeauth) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_FAILURE; + P_STA_RECORD_T prCliStaRec = (P_STA_RECORD_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + BOOLEAN fgIsStaFound = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucPeerMacAddr != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + prCliStaRec = cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_P2P_INDEX, pucPeerMacAddr); + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_ACCESS_POINT: + { + P_LINK_T prStaRecOfClientList = (P_LINK_T) NULL; + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; + + prStaRecOfClientList = &(prP2pBssInfo->rStaRecOfClientList); + + LINK_FOR_EACH(prLinkEntry, prStaRecOfClientList) { + if ((ULONG) prCliStaRec == (ULONG) prLinkEntry) { + LINK_REMOVE_KNOWN_ENTRY(prStaRecOfClientList, &prCliStaRec->rLinkEntry); + fgIsStaFound = TRUE; + break; + } + } + + } + break; + case OP_MODE_INFRASTRUCTURE: + ASSERT(prCliStaRec == prP2pBssInfo->prStaRecOfAP); + if (prCliStaRec != prP2pBssInfo->prStaRecOfAP) + break; + prP2pBssInfo->prStaRecOfAP = NULL; + fgIsStaFound = TRUE; + break; + default: + break; + } + + if (fgIsStaFound) + p2pFuncDisconnect(prAdapter, prCliStaRec, fgSendDeauth, u2ReasonCode); + + rWlanStatus = WLAN_STATUS_SUCCESS; + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncDeauth */ + +/* TODO: We do not apply IE in disassoc frame set from upper layer now. */ +WLAN_STATUS +p2pFuncDisassoc(IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucPeerMacAddr, + IN UINT_16 u2ReasonCode, IN PUINT_8 pucIEBuf, IN UINT_16 u2IELen, IN BOOLEAN fgSendDisassoc) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_FAILURE; + P_STA_RECORD_T prCliStaRec = (P_STA_RECORD_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + BOOLEAN fgIsStaFound = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucPeerMacAddr != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + prCliStaRec = cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_P2P_INDEX, pucPeerMacAddr); + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_ACCESS_POINT: + { + P_LINK_T prStaRecOfClientList = (P_LINK_T) NULL; + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; + + prStaRecOfClientList = &(prP2pBssInfo->rStaRecOfClientList); + + LINK_FOR_EACH(prLinkEntry, prStaRecOfClientList) { + if ((ULONG) prCliStaRec == (ULONG) prLinkEntry) { + LINK_REMOVE_KNOWN_ENTRY(prStaRecOfClientList, &prCliStaRec->rLinkEntry); + fgIsStaFound = TRUE; + /* + * p2pFuncDisconnect(prAdapter, prCliStaRec, + * fgSendDisassoc, u2ReasonCode); + */ + break; + } + } + + } + break; + case OP_MODE_INFRASTRUCTURE: + ASSERT(prCliStaRec == prP2pBssInfo->prStaRecOfAP); + if (prCliStaRec != prP2pBssInfo->prStaRecOfAP) + break; + /* p2pFuncDisconnect(prAdapter, prCliStaRec, fgSendDisassoc, u2ReasonCode); */ + prP2pBssInfo->prStaRecOfAP = NULL; + fgIsStaFound = TRUE; + break; + default: + break; + } + + if (fgIsStaFound) { + + p2pFuncDisconnect(prAdapter, prCliStaRec, fgSendDisassoc, u2ReasonCode); + /* 20120830 moved into p2pFuncDisconnect(). */ + /* cnmStaRecFree(prAdapter, prCliStaRec, TRUE); */ + + } + + rWlanStatus = WLAN_STATUS_SUCCESS; + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncDisassoc */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to dissolve from group or one group. (Would not change P2P FSM.) +* 1. GC: Disconnect from AP. (Send Deauth) +* 2. GO: Disconnect all STA +* +* @param[in] prAdapter Pointer to the adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFuncDissolve(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, IN BOOLEAN fgSendDeauth, IN UINT_16 u2ReasonCode) +{ + DEBUGFUNC("p2pFuncDissolve()"); + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_INFRASTRUCTURE: + /* Reset station record status. */ + if (prP2pBssInfo->prStaRecOfAP) { + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + NULL, NULL, 0, REASON_CODE_DEAUTH_LEAVING_BSS, + WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY); + + /* 2012/02/14 frog: After formation before join group, prStaRecOfAP is NULL. */ + p2pFuncDisconnect(prAdapter, prP2pBssInfo->prStaRecOfAP, fgSendDeauth, u2ReasonCode); + } + + /* + * Fix possible KE when RX Beacon & call nicPmIndicateBssConnected(). + * hit prStaRecOfAP == NULL. + */ + p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + + prP2pBssInfo->prStaRecOfAP = NULL; + + break; + case OP_MODE_ACCESS_POINT: + /* + * Under AP mode, we would net send deauthentication frame to each STA. + * We only stop the Beacon & let all stations timeout. + */ + { + P_LINK_T prStaRecOfClientList = (P_LINK_T) NULL; + UINT_32 u4ClientCount = 0; + + /* Send deauth. */ + authSendDeauthFrame(prAdapter, + NULL, (P_SW_RFB_T) NULL, u2ReasonCode, (PFN_TX_DONE_HANDLER) NULL); + + prStaRecOfClientList = &prP2pBssInfo->rStaRecOfClientList; + u4ClientCount = prStaRecOfClientList->u4NumElem; + while (!LINK_IS_EMPTY(prStaRecOfClientList)) { + P_STA_RECORD_T prCurrStaRec; + + LINK_REMOVE_HEAD(prStaRecOfClientList, prCurrStaRec, P_STA_RECORD_T); + + /* Indicate to Host. */ + /* kalP2PGOStationUpdate(prAdapter->prGlueInfo, prCurrStaRec, FALSE); */ + + p2pFuncDisconnect(prAdapter, prCurrStaRec, TRUE, u2ReasonCode); + + } + prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsGOInitialDone = 0; + if (u4ClientCount == 0) + p2pFuncDeauthComplete(prAdapter, prP2pBssInfo); + } + + 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); + + if (prAdapter->rWifiVar.prP2pFsmInfo->fgIsApMode) { + DBGLOG(P2P, INFO, "Wait 500ms for deauth TX in Hotspot\n"); + if (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT + && prP2pBssInfo->eIntendOPMode == OP_MODE_NUM) + prP2pBssInfo->eIntendOPMode = OP_MODE_P2P_DEVICE; + kalMdelay(500); + DBGLOG(P2P, TRACE, "Wait done for deauth TX in Hotspot\n"); + } else { + DBGLOG(P2P, INFO, "Wait 500ms for deauth TX in case of GC in PS\n"); + kalMdelay(500); + } + + /* Change Connection Status. */ + p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + + } while (FALSE); + +} /* p2pFuncDissolve */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to dissolve from group or one group. (Would not change P2P FSM.) +* 1. GC: Disconnect from AP. (Send Deauth) +* 2. GO: Disconnect all STA +* +* @param[in] prAdapter Pointer to the adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFuncDisconnect(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, IN BOOLEAN fgSendDeauth, IN UINT_16 u2ReasonCode) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + ENUM_PARAM_MEDIA_STATE_T eOriMediaStatus; +#if CFG_SUPPORT_P2P_EAP_FAIL_WORKAROUND + UINT_32 u4DeauthDelayTimeDiff = 0; +#endif + do { + ASSERT_BREAK((prAdapter != NULL) && (prStaRec != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + eOriMediaStatus = prP2pBssInfo->eConnectionState; + + /* Indicate disconnect. */ + /* TODO: */ + /* kalP2PGOStationUpdate */ + /* kalP2PGCIndicateConnectionStatus */ + /* p2pIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED, prStaRec->aucMacAddr); */ + DBGLOG(P2P, INFO, "p2pFuncDisconnect, eCurrentOPMode: %d, sendDeauth: %s, u2ReasonCode: %d\n", + prP2pBssInfo->eCurrentOPMode, fgSendDeauth ? "True" : "False", u2ReasonCode); +#if CFG_SUPPORT_P2P_EAP_FAIL_WORKAROUND + u4DeauthDelayTimeDiff = kalGetTimeTick() - prP2pBssInfo->u4P2PEapTxDoneTime; + if (prP2pBssInfo->fgP2PPendingDeauth == TRUE && + u4DeauthDelayTimeDiff < P2P_DEAUTH_DELAY_TIME && + fgSendDeauth == TRUE) { + kalMdelay(u4DeauthDelayTimeDiff); + DBGLOG(P2P, WARN, "The end of the delayed deauth at %d ms....\n", u4DeauthDelayTimeDiff); + } + prP2pBssInfo->fgP2PPendingDeauth = FALSE; + prP2pBssInfo->u4P2PEapTxDoneTime = 0; +#endif + if (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) + kalP2PGOStationUpdate(prAdapter->prGlueInfo, prStaRec, FALSE); +#if CFG_SUPPORT_P2P_ECSA + /* clear channel switch flag to avoid scan issues */ + prP2pBssInfo->fgChanSwitching = FALSE; +#endif + if (fgSendDeauth) { + /* Send deauth. */ + authSendDeauthFrame(prAdapter, + prStaRec, + (P_SW_RFB_T) NULL, + u2ReasonCode, (PFN_TX_DONE_HANDLER) p2pFsmRunEventDeauthTxDone); + if (prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + /* Make the deauth frame send to FW ASAP. */ + DBGLOG(P2P, INFO, "GC: deauth frame send to FW ASAP\n"); + wlanAcquirePowerControl(prAdapter); + wlanProcessCommandQueue(prAdapter, &prAdapter->prGlueInfo->rCmdQueue); + wlanReleasePowerControl(prAdapter); + } + } 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); + } + + } + } while (FALSE); + + return; + +} /* p2pFuncDisconnect */ + +/* Action frame categories (IEEE 802.11-2007, 7.3.1.11, Table 7-24) */ +#define WLAN_ACTION_SPECTRUM_MGMT 0 +#define WLAN_ACTION_QOS 1 +#define WLAN_ACTION_DLS 2 +#define WLAN_ACTION_BLOCK_ACK 3 +#define WLAN_ACTION_PUBLIC 4 +#define WLAN_ACTION_RADIO_MEASUREMENT 5 +#define WLAN_ACTION_FT 6 +#define WLAN_ACTION_HT 7 +#define WLAN_ACTION_SA_QUERY 8 +#define WLAN_ACTION_PROTECTED_DUAL 9 +#define WLAN_ACTION_WNM 10 +#define WLAN_ACTION_UNPROTECTED_WNM 11 +#define WLAN_ACTION_TDLS 12 +#define WLAN_ACTION_SELF_PROTECTED 15 +#define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */ +#define WLAN_ACTION_VENDOR_SPECIFIC 127 + +/* Public action codes */ +#define WLAN_PA_20_40_BSS_COEX 0 +#define WLAN_PA_VENDOR_SPECIFIC 9 +#define WLAN_PA_GAS_INITIAL_REQ 10 +#define WLAN_PA_GAS_INITIAL_RESP 11 +#define WLAN_PA_GAS_COMEBACK_REQ 12 +#define WLAN_PA_GAS_COMEBACK_RESP 13 +#define WLAN_TDLS_DISCOVERY_RESPONSE 14 + +const char *p2p_to_string(enum P2P_ACTION_FRAME_TYPE p2p_action) +{ + switch (p2p_action) { + case P2P_GO_NEG_REQ: + return "GO_NEG_REQ"; + case P2P_GO_NEG_RESP: + return "GO_NEG_RESP"; + case P2P_GO_NEG_CONF: + return "GO_NEG_CONF"; + case P2P_INVITATION_REQ: + return "INVITATION_REQ"; + case P2P_INVITATION_RESP: + return "INVITATION_RESP"; + case P2P_DEV_DISC_REQ: + return "DEV_DISC_REQ"; + case P2P_DEV_DISC_RESP: + return "DEV_DISC_RESP"; + case P2P_PROV_DISC_REQ: + return "PROV_DISC_REQ"; + case P2P_PROV_DISC_RESP: + return "PROV_DISC_RESP"; + } + + return "UNKNOWN P2P Public Action"; +} +const char *pa_to_string(int pa_action) +{ + switch (pa_action) { + case WLAN_PA_20_40_BSS_COEX: + return "PA_20_40_BSS_COEX"; + case WLAN_PA_VENDOR_SPECIFIC: + return "PA_VENDOR_SPECIFIC"; + case WLAN_PA_GAS_INITIAL_REQ: + return "PA_GAS_INITIAL_REQ"; + case WLAN_PA_GAS_INITIAL_RESP: + return "PA_GAS_INITIAL_RESP"; + case WLAN_PA_GAS_COMEBACK_REQ: + return "PA_GAS_COMEBACK_REQ"; + case WLAN_PA_GAS_COMEBACK_RESP: + return "PA_GAS_COMEBACK_RESP"; + case WLAN_TDLS_DISCOVERY_RESPONSE: + return "TDLS_DISCOVERY_RESPONSE"; + } + + return "UNKNOWN Public Action"; +} + +const char *action_to_string(int wlan_action) +{ + switch (wlan_action) { + case WLAN_ACTION_SPECTRUM_MGMT: + return "SPECTRUM_MGMT"; + case WLAN_ACTION_QOS: + return "QOS"; + case WLAN_ACTION_DLS: + return "DLS"; + case WLAN_ACTION_BLOCK_ACK: + return "BLOCK_ACK"; + case WLAN_ACTION_PUBLIC: + return "PUBLIC"; + case WLAN_ACTION_RADIO_MEASUREMENT: + return "RADIO_MEASUREMENT"; + case WLAN_ACTION_FT: + return "FT"; + case WLAN_ACTION_HT: + return "HT"; + case WLAN_ACTION_SA_QUERY: + return "SA_QUERY"; + case WLAN_ACTION_PROTECTED_DUAL: + return "PROTECTED_DUAL"; + case WLAN_ACTION_WNM: + return "WNM"; + case WLAN_ACTION_UNPROTECTED_WNM: + return "UNPROTECTED_WNM"; + case WLAN_ACTION_TDLS: + return "TDLS"; + case WLAN_ACTION_SELF_PROTECTED: + return "SELF_PROTECTED"; + case WLAN_ACTION_WMM: + return "WMM"; + case WLAN_ACTION_VENDOR_SPECIFIC: + return "VENDOR_SPECIFIC"; + } + + return "UNKNOWN Action Frame"; +} + +ENUM_P2P_CNN_STATE_T p2pFuncTagActionActionP2PFrame(IN P_MSDU_INFO_T prMgmtTxMsdu, + IN P_WLAN_ACTION_FRAME prActFrame, + IN UINT_8 ucP2pAction, IN UINT_64 u8Cookie) +{ + DBGLOG(P2P, TRACE, "Found P2P_%s, SA: %pM - DA: %pM, cookie: 0x%llx, SeqNO: %d\n", + p2p_to_string(ucP2pAction), + prActFrame->aucSrcAddr, + prActFrame->aucDestAddr, + u8Cookie, + prMgmtTxMsdu->ucTxSeqNum); + return ucP2pAction + 1; +} + +#define P2P_INFO_MSG_LENGTH 200 +ENUM_P2P_CNN_STATE_T p2pFuncTagActionActionFrame(IN P_MSDU_INFO_T prMgmtTxMsdu, + IN P_WLAN_ACTION_FRAME prActFrame, + IN UINT_8 ucAction, IN UINT_64 u8Cookie) +{ + PUINT_8 pucVendor = NULL; + UINT_32 offsetMsg; + UINT8 aucMsg[P2P_INFO_MSG_LENGTH]; + ENUM_P2P_CNN_STATE_T eCNNState = P2P_CNN_NORMAL; + + offsetMsg = 0; + offsetMsg += kalSnprintf((aucMsg + offsetMsg), sizeof(aucMsg), "WLAN_%s, ", + pa_to_string(ucAction)); + + if (ucAction == WLAN_PA_VENDOR_SPECIFIC) { + pucVendor = (PUINT_8)prActFrame + 26; + if (*(pucVendor + 0) == 0x50 && + *(pucVendor + 1) == 0x6f && + *(pucVendor + 2) == 0x9a) { + if (*(pucVendor + 3) == 0x09) { + /* found p2p IE */ + eCNNState = p2pFuncTagActionActionP2PFrame(prMgmtTxMsdu, + prActFrame, *(pucVendor + 4), u8Cookie); + offsetMsg += kalSnprintf((aucMsg + offsetMsg), sizeof(aucMsg) - offsetMsg + , "P2P_%s, ", p2p_to_string(*(pucVendor + 4))); + } else if (*(pucVendor + 3) == 0x0a) { + /* found WFD IE */ + DBGLOG(P2P, TRACE, "Found WFD IE, SA: %pM - DA: %pM\n", + prActFrame->aucSrcAddr, + prActFrame->aucDestAddr); + offsetMsg += kalSnprintf((aucMsg + offsetMsg), sizeof(aucMsg) - offsetMsg + , "WFD IE%s, ", ""); + } else { + DBGLOG(P2P, TRACE, "Found Other vendor 0x%x, SA: %pM - DA: %pM\n", + *(pucVendor + 3), + prActFrame->aucSrcAddr, + prActFrame->aucDestAddr); + offsetMsg += kalSnprintf((aucMsg + offsetMsg), sizeof(aucMsg) - offsetMsg + , "Other vendor 0x%x, ", *(pucVendor + 3)); + } + } + } + + DBGLOG(P2P, INFO, "Found :%s\n", aucMsg); + return eCNNState; +} + +ENUM_P2P_CNN_STATE_T p2pFuncTagActionCategoryFrame(IN P_MSDU_INFO_T prMgmtTxMsdu, + P_WLAN_ACTION_FRAME prActFrame, + IN UINT_8 ucCategory, + IN UINT_64 u8Cookie) +{ + + UINT_8 ucAction = 0; + ENUM_P2P_CNN_STATE_T eCNNState = P2P_CNN_NORMAL; + + DBGLOG(P2P, INFO, "Found WLAN_ACTION_%s, SA: %pM - DA: %pM, u8Cookie: 0x%llx, SeqNO: %d\n", + action_to_string(ucCategory), + prActFrame->aucSrcAddr, + prActFrame->aucDestAddr, + u8Cookie, + prMgmtTxMsdu->ucTxSeqNum); + + if (ucCategory == WLAN_ACTION_PUBLIC) { + ucAction = prActFrame->ucAction; + eCNNState = p2pFuncTagActionActionFrame(prMgmtTxMsdu, prActFrame, ucAction, u8Cookie); + } + return eCNNState; +} + +/* + * used to debug p2p mgmt frame: + * GO Nego Req + * GO Nego Res + * GO Nego Confirm + * GO Invite Req + * GO Invite Res + * Device Discoverability Req + * Device Discoverability Res + * Provision Discovery Req + * Provision Discovery Res + */ + +ENUM_P2P_CNN_STATE_T +p2pFuncTagMgmtFrame(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMgmtTxMsdu, IN UINT_64 u8Cookie) +{ + /* P_MSDU_INFO_T prTxMsduInfo = (P_MSDU_INFO_T)NULL; */ + P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T) NULL; + P_WLAN_PROBE_RSP_FRAME_T prProbRspHdr = (P_WLAN_PROBE_RSP_FRAME_T)NULL; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = NULL; + UINT_16 u2TxFrameCtrl; + P_WLAN_ACTION_FRAME prActFrame; + UINT_8 ucCategory; + ENUM_P2P_CNN_STATE_T eCNNState = P2P_CNN_NORMAL; + + prWlanHdr = (P_WLAN_MAC_HEADER_T) ((ULONG) prMgmtTxMsdu->prPacket + MAC_TX_RESERVED_FIELD); + /* + * mgmt frame MASK_FC_TYPE = 0 + * use MASK_FRAME_TYPE is oK for frame type/subtype judge + */ + u2TxFrameCtrl = prWlanHdr->u2FrameCtrl & MASK_FRAME_TYPE; + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + switch (u2TxFrameCtrl) { + case MAC_FRAME_PROBE_RSP: + + prProbRspHdr = (P_WLAN_PROBE_RSP_FRAME_T) prWlanHdr; + DBGLOG(P2P, INFO, "TX Probe Response Frame, SA: %pM - DA: %pM, NoA[%d], cookie: 0x%llx, seqNo: %d\n", + prProbRspHdr->aucSrcAddr, prProbRspHdr->aucDestAddr, + (prP2pSpecificBssInfo == NULL ? -1 : prP2pSpecificBssInfo->ucNoATimingCount), + u8Cookie, + prMgmtTxMsdu->ucTxSeqNum); + + break; + + case MAC_FRAME_ACTION: + + prActFrame = (P_WLAN_ACTION_FRAME)prWlanHdr; + ucCategory = prActFrame->ucCategory; + eCNNState = p2pFuncTagActionCategoryFrame(prMgmtTxMsdu, prActFrame, + ucCategory, u8Cookie); + + break; + default: + DBGLOG(P2P, INFO, "MGMT:, un-tagged frame type: 0x%x, A1: %pM, A2: %pM, A3: %pM seqNo: %d\n", + u2TxFrameCtrl, + prWlanHdr->aucAddr1, + prWlanHdr->aucAddr2, + prWlanHdr->aucAddr3, + prMgmtTxMsdu->ucTxSeqNum); + break; + } + return eCNNState; +} + +WLAN_STATUS +p2pFuncTxMgmtFrame(IN P_ADAPTER_T prAdapter, + IN P_P2P_MGMT_TX_REQ_INFO_T prMgmtTxReqInfo, IN P_MSDU_INFO_T prMgmtTxMsdu, IN UINT_64 u8Cookie) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_MSDU_INFO_T prTxMsduInfo = (P_MSDU_INFO_T) NULL; + P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + BOOLEAN fgIsProbrsp = FALSE; +#if CFG_SUPPORT_P2P_ECSA + P_BSS_INFO_T prBssInfo; +#endif + BOOLEAN fgDropFrame = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMgmtTxReqInfo != NULL)); + + if (prMgmtTxReqInfo->fgIsMgmtTxRequested) { + + /* 1. prMgmtTxReqInfo->prMgmtTxMsdu != NULL */ + /* Packet on driver, not done yet, drop it. */ + prTxMsduInfo = prMgmtTxReqInfo->prMgmtTxMsdu; + if (prTxMsduInfo != NULL) { + prMgmtTxReqInfo->prMgmtTxMsdu = NULL; + DBGLOG(P2P, INFO, "mgmt has not RX tx done yet cookie: 0x%llx\n", + prMgmtTxReqInfo->u8Cookie); + } + /* 2. prMgmtTxReqInfo->prMgmtTxMsdu == NULL */ + /* Packet transmitted, wait tx done. (cookie issue) */ + /* 20120105 frog - use another u8cookie to store this value. */ + } + + prWlanHdr = (P_WLAN_MAC_HEADER_T) ((ULONG) prMgmtTxMsdu->prPacket + MAC_TX_RESERVED_FIELD); + prStaRec = cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_P2P_INDEX, prWlanHdr->aucAddr1); + prMgmtTxMsdu->ucNetworkType = (UINT_8) NETWORK_TYPE_P2P_INDEX; + + switch (prWlanHdr->u2FrameCtrl & MASK_FRAME_TYPE) { + case MAC_FRAME_PROBE_RSP: + DBGLOG(P2P, TRACE, "p2pFuncTxMgmtFrame: TX MAC_FRAME_PROBE_RSP\n"); +#if CFG_SUPPORT_P2P_ECSA + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMgmtTxMsdu->ucNetworkType]; + if (prBssInfo->fgChanSwitching) { + fgIsProbrsp = TRUE; + DBGLOG(P2P, INFO, "Bss is switching channel, not TX probe response\n"); + break; + } +#else + fgIsProbrsp = TRUE; +#endif + if (p2pFuncValidateProbeResp(prAdapter, prMgmtTxMsdu) == FALSE) { + fgDropFrame = TRUE; + break; + } + prMgmtTxMsdu = p2pFuncProcessP2pProbeRsp(prAdapter, prMgmtTxMsdu); + break; + default: + break; + } +#if CFG_SUPPORT_P2P_ECSA + if (fgIsProbrsp) { + /* Drop this frame */ + p2pFsmRunEventMgmtFrameTxDone(prAdapter, prMgmtTxMsdu, TX_RESULT_DROPPED_IN_DRIVER); + cnmMgtPktFree(prAdapter, prMgmtTxMsdu); + break; + } +#endif + if (fgDropFrame) { + /* Drop this frame */ + DBGLOG(P2P, INFO, "probe response cannot TX, dropped! cookie: 0x%llx\n", + u8Cookie); + p2pFsmRunEventMgmtFrameTxDone(prAdapter, prMgmtTxMsdu, TX_RESULT_DROPPED_IN_DRIVER); + cnmMgtPktFree(prAdapter, prMgmtTxMsdu); + break; + } + prMgmtTxReqInfo->u8Cookie = u8Cookie; + prMgmtTxMsdu->u8Cookie = u8Cookie; + prMgmtTxReqInfo->prMgmtTxMsdu = prMgmtTxMsdu; + prMgmtTxReqInfo->fgIsMgmtTxRequested = TRUE; + + prMgmtTxMsdu->eSrc = TX_PACKET_MGMT; + prMgmtTxMsdu->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMgmtTxMsdu->ucStaRecIndex = (prStaRec != NULL) ? (prStaRec->ucIndex) : (0xFF); + if (prStaRec != NULL) + DBGLOG(P2P, TRACE, "Mgmt with station record: %pM.\n", prStaRec->aucMacAddr); + + prMgmtTxMsdu->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; /* TODO: undcertain. */ + prMgmtTxMsdu->fgIs802_1x = FALSE; + prMgmtTxMsdu->fgIs802_11 = TRUE; + prMgmtTxMsdu->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMgmtTxMsdu->pfTxDoneHandler = p2pFsmRunEventMgmtFrameTxDone; + prMgmtTxMsdu->fgIsBasicRate = TRUE; + + /* record P2P CONNECT state */ + prAdapter->rWifiVar.prP2pFsmInfo->eCNNState = p2pFuncTagMgmtFrame(prAdapter, prMgmtTxMsdu, u8Cookie); + + nicTxEnqueueMsdu(prAdapter, prMgmtTxMsdu); + + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncTxMgmtFrame */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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; +#if (CFG_SUPPORT_TDLS == 1) + /* init the TDLS flags */ + prP2pBssInfo->fgTdlsIsProhibited = prStaRec->fgTdlsIsProhibited; + prP2pBssInfo->fgTdlsIsChSwProhibited = prStaRec->fgTdlsIsChSwProhibited; +#endif /* CFG_SUPPORT_TDLS */ + + /* 3 <3> Update BSS_INFO_T from SW_RFB_T (Association Resp Frame) */ + /* 4 <3.1> Setup BSSID */ + COPY_MAC_ADDR(prP2pBssInfo->aucBSSID, prAssocRspFrame->aucBSSID); + + u2IELength = (UINT_16) ((prAssocRspSwRfb->u2PacketLen - prAssocRspSwRfb->u2HeaderLen) - + (OFFSET_OF(WLAN_ASSOC_RSP_FRAME_T, aucInfoElem[0]) - WLAN_MAC_MGMT_HEADER_LEN)); + pucIE = prAssocRspFrame->aucInfoElem; + + /* 4 <3.2> Parse WMM and setup QBSS flag */ + /* Parse WMM related IEs and configure HW CRs accordingly */ + mqmProcessAssocRsp(prAdapter, prAssocRspSwRfb, pucIE, u2IELength); + + prP2pBssInfo->fgIsQBSS = prStaRec->fgIsQoS; + + /* 3 <4> Update BSS_INFO_T from BSS_DESC_T */ + ASSERT(prBssDesc); + + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + + /* 4 <4.1> Setup MIB for current BSS */ + prP2pBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval; + /* NOTE: Defer ucDTIMPeriod updating to when beacon is received after connection */ + prP2pBssInfo->ucDTIMPeriod = 0; + prP2pBssInfo->u2ATIMWindow = 0; + + prP2pBssInfo->ucBeaconTimeoutCount = AIS_BEACON_TIMEOUT_COUNT_INFRA; + + /* 4 <4.2> Update HT information and set channel */ + /* Record HT related parameters in rStaRec and rBssInfo + * Note: it shall be called before nicUpdateBss() + */ + rlmProcessAssocRsp(prAdapter, prAssocRspSwRfb, pucIE, u2IELength); + + /* 4 <4.3> Sync with firmware for BSS-INFO */ + nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); + + /* 4 <4.4> *DEFER OPERATION* nicPmIndicateBssConnected() will be invoked */ + /* inside scanProcessBeaconAndProbeResp() after 1st beacon is received */ + +} /* end of p2pUpdateBssInfoForJOIN() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Auth Frame and then return +* the status code to AAA to indicate if need to perform following actions +* when the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[in] pprStaRec Pointer to pointer of STA_RECORD_T structure. +* @param[out] pu2StatusCode The Status Code of Validation Result +* +* @retval TRUE Reply the Auth +* @retval FALSE Don't reply the Auth +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +p2pFuncValidateAuth(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, IN PP_STA_RECORD_T pprStaRec, OUT PUINT_16 pu2StatusCode) +{ + BOOLEAN fgPmfConn = FALSE; + BOOLEAN fgReplyAuth = TRUE; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + P_WLAN_AUTH_FRAME_T prAuthFrame = (P_WLAN_AUTH_FRAME_T) NULL; + + DBGLOG(P2P, INFO, "p2pValidate Authentication Frame\n"); + + do { + ASSERT_BREAK((prAdapter != NULL) && + (prSwRfb != NULL) && (pprStaRec != NULL) && (pu2StatusCode != NULL)); + + *pu2StatusCode = STATUS_CODE_REQ_DECLINED; + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; + + if ((prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) + || (prP2pBssInfo->eIntendOPMode != OP_MODE_NUM)) { + /* We are not under AP mode yet */ + fgReplyAuth = FALSE; + DBGLOG(P2P, WARN, + "Current OP mode is not under AP mode. (%d)\n", prP2pBssInfo->eCurrentOPMode); + break; + } + + if (prP2pBssInfo->rStaRecOfClientList.u4NumElem >= P2P_MAXIMUM_CLIENT_COUNT || + kalP2PReachMaxClients(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); + + *pu2StatusCode = STATUS_CODE_ASSOC_DENIED_AP_OVERLOAD; + break; + } + + if (kalP2PCmpBlackList(prAdapter->prGlueInfo, prAuthFrame->aucSrcAddr)) { + /* STA in the black list of Hotspot */ + *pu2StatusCode = STATUS_CODE_ASSOC_DENIED_OUTSIDE_STANDARD; + 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 STA_RECORD_T allocation for + * exhausted case and do removal of unused STA_RECORD_T. + */ + if (!prStaRec) { + DBGLOG(P2P, WARN, "StaRec exhausted!! Decline a new Authentication\n"); + break; + } + + COPY_MAC_ADDR(prStaRec->aucMacAddr, prAuthFrame->aucSrcAddr); + + prSwRfb->ucStaRecIdx = prStaRec->ucIndex; + + prStaRec->u2BSSBasicRateSet = prP2pBssInfo->u2BSSBasicRateSet; + prStaRec->u2DesiredNonHTRateSet = RATE_SET_ERP_P2P; + prStaRec->u2OperationalRateSet = RATE_SET_ERP_P2P; + prStaRec->ucPhyTypeSet = PHY_TYPE_SET_802_11GN; + prStaRec->eStaType = STA_TYPE_P2P_GC; + + /* NOTE(Kevin): Better to change state here, not at TX Done */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + } else { +#if CFG_SUPPORT_802_11W + /* AP PMF. if PMF connection, do not reset state & FSM */ + fgPmfConn = rsnCheckBipKeyInstalled(prAdapter, prStaRec); + if (fgPmfConn) { + DBGLOG(P2P, WARN, "PMF Connction, return false\n"); + return FALSE; + } +#endif + + prSwRfb->ucStaRecIdx = prStaRec->ucIndex; + + prStaRec->eStaType = STA_TYPE_P2P_GC; + + if ((prStaRec->ucStaState > STA_STATE_1) && (IS_STA_IN_P2P(prStaRec))) { + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + p2pFuncResetStaRecStatus(prAdapter, prStaRec); + + bssRemoveStaRecFromClientList(prAdapter, prP2pBssInfo, prStaRec); + } + } + + *pprStaRec = prStaRec; + + *pu2StatusCode = STATUS_CODE_SUCCESSFUL; + + } while (FALSE); + + return fgReplyAuth; + +} /* p2pFuncValidateAuth */ + +VOID p2pFuncResetStaRecStatus(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + do { + if ((prAdapter == NULL) || (prStaRec == NULL)) { + ASSERT(FALSE); + break; + } + + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + prStaRec->u2ReasonCode = REASON_CODE_RESERVED; + prStaRec->ucJoinFailureCount = 0; + prStaRec->fgTransmitKeyExist = FALSE; + + prStaRec->fgSetPwrMgtBit = FALSE; + + } while (FALSE); + +} /* p2pFuncResetStaRecStatus */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief The function is used to initialize the value of the connection settings for +* P2P network +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFuncInitConnectionSettings(IN P_ADAPTER_T prAdapter, IN P_P2P_CONNECTION_SETTINGS_T prP2PConnSettings) +{ + P_DEVICE_TYPE_T prDevType; + UINT_8 aucDefaultDevName[P2P_DEFAULT_DEV_NAME_LEN] = P2P_DEFAULT_DEV_NAME; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; +#if CFG_SUPPORT_CFG_FILE + P_WIFI_VAR_T prWifiVar = NULL; +#endif + + ASSERT(prP2PConnSettings); +#if CFG_SUPPORT_CFG_FILE + prWifiVar = &(prAdapter->rWifiVar); + ASSERT(prWifiVar); +#endif + + /* Setup Default Device Name */ + prP2PConnSettings->ucDevNameLen = P2P_DEFAULT_DEV_NAME_LEN; + kalMemCopy(prP2PConnSettings->aucDevName, aucDefaultDevName, sizeof(aucDefaultDevName)); + + /* Setup Primary Device Type (Big-Endian) */ + prDevType = &prP2PConnSettings->rPrimaryDevTypeBE; + + prDevType->u2CategoryId = HTONS(P2P_DEFAULT_PRIMARY_CATEGORY_ID); + prDevType->u2SubCategoryId = HTONS(P2P_DEFAULT_PRIMARY_SUB_CATEGORY_ID); + + prDevType->aucOui[0] = aucWfaOui[0]; + prDevType->aucOui[1] = aucWfaOui[1]; + prDevType->aucOui[2] = aucWfaOui[2]; + prDevType->aucOui[3] = VENDOR_OUI_TYPE_WPS; + + /* Setup Secondary Device Type */ + prP2PConnSettings->ucSecondaryDevTypeCount = 0; + + /* Setup Default Config Method */ + prP2PConnSettings->eConfigMethodSelType = ENUM_CONFIG_METHOD_SEL_AUTO; + prP2PConnSettings->u2ConfigMethodsSupport = P2P_DEFAULT_CONFIG_METHOD; + prP2PConnSettings->u2TargetConfigMethod = 0; + prP2PConnSettings->u2LocalConfigMethod = 0; + prP2PConnSettings->fgIsPasswordIDRdy = FALSE; + + /* For Device Capability */ + prP2PConnSettings->fgSupportServiceDiscovery = FALSE; + prP2PConnSettings->fgSupportClientDiscoverability = TRUE; + prP2PConnSettings->fgSupportConcurrentOperation = TRUE; + prP2PConnSettings->fgSupportInfraManaged = FALSE; + prP2PConnSettings->fgSupportInvitationProcedure = FALSE; + + /* For Group Capability */ +#if CFG_SUPPORT_PERSISTENT_GROUP + prP2PConnSettings->fgSupportPersistentP2PGroup = TRUE; +#else + prP2PConnSettings->fgSupportPersistentP2PGroup = FALSE; +#endif + prP2PConnSettings->fgSupportIntraBSSDistribution = TRUE; + prP2PConnSettings->fgSupportCrossConnection = TRUE; + prP2PConnSettings->fgSupportPersistentReconnect = FALSE; + + prP2PConnSettings->fgSupportOppPS = FALSE; + prP2PConnSettings->u2CTWindow = P2P_CTWINDOW_DEFAULT; + + /* For Connection Settings. */ + prP2PConnSettings->eAuthMode = AUTH_MODE_OPEN; + + prP2PConnSettings->prTargetP2pDesc = NULL; + prP2PConnSettings->ucSSIDLen = 0; + + /* Misc */ + prP2PConnSettings->fgIsScanReqIssued = FALSE; + prP2PConnSettings->fgIsServiceDiscoverIssued = FALSE; + prP2PConnSettings->fgP2pGroupLimit = FALSE; + prP2PConnSettings->ucOperatingChnl = 0; + prP2PConnSettings->ucListenChnl = 0; + prP2PConnSettings->ucTieBreaker = (UINT_8) (kalRandomNumber() & 0x1); + + prP2PConnSettings->eFormationPolicy = ENUM_P2P_FORMATION_POLICY_AUTO; +#if CFG_SUPPORT_CFG_FILE + /* prP2PConnSettings->fgIsWPSMode = prWifiVar->ucApWpsMode; */ + prAdapter->rWifiVar.prP2pFsmInfo->fgIsWPSMode = prWifiVar->ucApWpsMode; +#endif +} /* p2pFuncInitConnectionSettings */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Assoc Req Frame and then return +* the status code to AAA to indicate if need to perform following actions +* when the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu2StatusCode The Status Code of Validation Result +* +* @retval TRUE Reply the Assoc Resp +* @retval FALSE Don't reply the Assoc Resp +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2pFuncValidateAssocReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu2StatusCode) +{ + BOOLEAN fgReplyAssocResp = TRUE; + P_WLAN_ASSOC_REQ_FRAME_T prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; +#if CFG_SUPPORT_WFD + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + P_WFD_ATTRIBUTE_T prWfdAttribute = (P_WFD_ATTRIBUTE_T) NULL; + BOOLEAN fgNeedFree = FALSE; +#endif + /* UINT_16 u2AttriListLen = 0; */ + UINT_16 u2WfdDevInfo = 0; + P_WFD_DEVICE_INFORMATION_IE_T prAttriWfdDevInfo; + + /* + * TODO(Kevin): Call P2P functions to check .. + * 2. Check we can accept connection from thsi peer + * a. If we are in PROVISION state, only accept the peer we do the GO formation previously. + * b. If we are in OPERATION state, only accept the other peer when P2P_GROUP_LIMIT is 0. + * 3. Check Black List here. + */ + + do { + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL) && (pu2StatusCode != NULL)); + + *pu2StatusCode = STATUS_CODE_REQ_DECLINED; + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) prSwRfb->pvHeader; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prStaRec == NULL) { + /* Station record should be ready while RX AUTH frame. */ + fgReplyAssocResp = FALSE; + ASSERT(FALSE); + break; + } + prStaRec->ucRCPI = prSwRfb->prHifRxHdr->ucRcpi; + + prStaRec->u2DesiredNonHTRateSet &= prP2pBssInfo->u2OperationalRateSet; + prStaRec->ucDesiredPhyTypeSet = prStaRec->ucPhyTypeSet & prP2pBssInfo->ucPhyTypeSet; + + if (prStaRec->ucDesiredPhyTypeSet == 0) { + /* The station only support 11B rate. */ + *pu2StatusCode = STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED; + break; + } +#if CFG_SUPPORT_WFD && 1 + /* LOG_FUNC("Skip check WFD IE because some API is not ready\n"); */ + if (!prAdapter->rWifiVar.prP2pFsmInfo) { + fgReplyAssocResp = FALSE; + ASSERT(FALSE); + break; + } + + prWfdCfgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings; + DBGLOG(P2P, INFO, "AssocReq, wfd_en %u wfd_info 0x%x wfd_policy 0x%x wfd_flag 0x%x\n", + prWfdCfgSettings->ucWfdEnable, prWfdCfgSettings->u2WfdDevInfo, + prWfdCfgSettings->u4WfdPolicy, prWfdCfgSettings->u4WfdFlag); /* Eddie */ + if (prWfdCfgSettings->ucWfdEnable) { + if (prWfdCfgSettings->u4WfdPolicy & BIT(6)) { + /* Rejected all. */ + break; + } + + /* fgNeedFree = p2pFuncGetAttriList(prAdapter, */ + /* VENDOR_OUI_TYPE_WFD, */ + /* (PUINT_8)prAssocReqFrame->aucInfoElem, */ + /* (prSwRfb->u2PacketLen - OFFSET_OF(WLAN_ASSOC_REQ_FRAME_T, aucInfoElem)), */ + /* (PPUINT_8)&prWfdAttribute, */ + /* &u2AttriListLen); */ + + prAttriWfdDevInfo = (P_WFD_DEVICE_INFORMATION_IE_T) + p2pFuncGetSpecAttri(prAdapter, + VENDOR_OUI_TYPE_WFD, + (PUINT_8) prAssocReqFrame->aucInfoElem, + (prSwRfb->u2PacketLen - + OFFSET_OF(WLAN_ASSOC_REQ_FRAME_T, aucInfoElem)), + WFD_ATTRI_ID_DEV_INFO); + + if ((prWfdCfgSettings->u4WfdPolicy & BIT(5)) && (prAttriWfdDevInfo != NULL)) { + /* Rejected with WFD IE. */ + break; + } + + if ((prWfdCfgSettings->u4WfdPolicy & BIT(0)) && (prAttriWfdDevInfo == NULL)) { + /* Rejected without WFD IE. */ + break; + } + + if (prAttriWfdDevInfo == NULL) { + /* + * Without WFD IE. + * Do nothing. Accept the connection request. + */ + *pu2StatusCode = STATUS_CODE_SUCCESSFUL; + break; + } + + /* prAttriWfdDevInfo = */ + /* (P_WFD_DEVICE_INFORMATION_IE_T)p2pFuncGetSpecAttri(prAdapter, */ + /* VENDOR_OUI_TYPE_WFD, */ + /* (PUINT_8)prWfdAttribute, */ + /* u2AttriListLen, */ + /* WFD_ATTRI_ID_DEV_INFO); */ + /* if (prAttriWfdDevInfo == NULL) { */ + /* No such attribute. */ + /* break; */ + /* } */ + + WLAN_GET_FIELD_BE16(&prAttriWfdDevInfo->u2WfdDevInfo, &u2WfdDevInfo); + DBGLOG(P2P, INFO, "RX Assoc Req WFD Info:0x%x.\n", u2WfdDevInfo); + + if ((prWfdCfgSettings->u4WfdPolicy & BIT(1)) && ((u2WfdDevInfo & 0x3) == 0x0)) { + /* Rejected because of SOURCE. */ + break; + } + + if ((prWfdCfgSettings->u4WfdPolicy & BIT(2)) && ((u2WfdDevInfo & 0x3) == 0x1)) { + /* Rejected because of Primary Sink. */ + break; + } + + if ((prWfdCfgSettings->u4WfdPolicy & BIT(3)) && ((u2WfdDevInfo & 0x3) == 0x2)) { + /* Rejected because of Secondary Sink. */ + break; + } + + if ((prWfdCfgSettings->u4WfdPolicy & BIT(4)) && ((u2WfdDevInfo & 0x3) == 0x3)) { + /* Rejected because of Source & Primary Sink. */ + break; + } + + /* Check role */ + + if ((prWfdCfgSettings->u4WfdFlag & WFD_FLAGS_DEV_INFO_VALID) && + ((prWfdCfgSettings->u2WfdDevInfo & BITS(0, 1)) == 0x3)) { + /* + * P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T prMsgWfdCfgUpdate = + * (P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T)NULL; + */ + UINT_16 u2DevInfo = prWfdCfgSettings->u2WfdDevInfo; + + /* We may change role here if we are dual role */ + + if ((u2WfdDevInfo & BITS(0, 1)) == 0x00 /* Peer is Source */) { + DBGLOG(P2P, INFO, "WFD: Switch role to primary sink\n"); + + prWfdCfgSettings->u2WfdDevInfo &= ~BITS(0, 1); + prWfdCfgSettings->u2WfdDevInfo |= 0x1; + + /* event to annonce the role is chanaged to P-Sink */ + + } else if ((u2WfdDevInfo & BITS(0, 1)) == 0x01 /* Peer is P-Sink */) { + DBGLOG(P2P, INFO, "WFD: Switch role to source\n"); + + prWfdCfgSettings->u2WfdDevInfo &= ~BITS(0, 1); + /* event to annonce the role is chanaged to Source */ + } else { + DBGLOG(P2P, INFO, "WFD: Peer role is wrong type(dev 0x%x)\n", + (u2DevInfo)); + DBGLOG(P2P, INFO, "WFD: Switch role to source\n"); + + prWfdCfgSettings->u2WfdDevInfo &= ~BITS(0, 1); + /* event to annonce the role is chanaged to Source */ + } + + p2pFsmRunEventWfdSettingUpdate(prAdapter, NULL); + + } /* Dual role p2p->wfd_params->WfdDevInfo */ + + /* WFD_FLAG_DEV_INFO_VALID */ + } + /* ucWfdEnable */ +#endif + *pu2StatusCode = STATUS_CODE_SUCCESSFUL; + } while (FALSE); + +#if CFG_SUPPORT_WFD + if ((prWfdAttribute) && (fgNeedFree)) + kalMemFree(prWfdAttribute, VIR_MEM_TYPE, WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE); +#endif + + return fgReplyAssocResp; + +} /* p2pFuncValidateAssocReq */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to check the P2P IE +* +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2pFuncParseCheckForP2PInfoElem(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuf, OUT PUINT_8 pucOuiType) +{ + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + P_IE_WFA_T prWfaIE = (P_IE_WFA_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL) && (pucOuiType != NULL)); + + prWfaIE = (P_IE_WFA_T) pucBuf; + + if (IE_LEN(pucBuf) <= ELEM_MIN_LEN_WFA_OUI_TYPE_SUBTYPE) { + break; + } else if (prWfaIE->aucOui[0] != aucWfaOui[0] || + prWfaIE->aucOui[1] != aucWfaOui[1] || prWfaIE->aucOui[2] != aucWfaOui[2]) { + break; + } + + *pucOuiType = prWfaIE->ucOuiType; + + return TRUE; + } while (FALSE); + + return FALSE; +} /* p2pFuncParseCheckForP2PInfoElem */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Probe Request Frame and then return +* result to BSS to indicate if need to send the corresponding Probe Response +* Frame if the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu4ControlFlags Control flags for replying the Probe Response +* +* @retval TRUE Reply the Probe Response +* @retval FALSE Don't reply the Probe Response +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2pFuncValidateProbeReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_32 pu4ControlFlags) +{ + BOOLEAN fgIsReplyProbeRsp = FALSE; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + + DEBUGFUNC("p2pFuncValidateProbeReq"); + DBGLOG(P2P, TRACE, "p2pFuncValidateProbeReq\n"); + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo->u4P2pPacketFilter & PARAM_PACKET_FILTER_PROBE_REQ) { + + DBGLOG(P2P, TRACE, "report probe req to OS\n"); + /* Leave the probe response to p2p_supplicant. */ + kalP2PIndicateRxMgmtFrame(prAdapter->prGlueInfo, prSwRfb); + } + + } while (FALSE); + + return fgIsReplyProbeRsp; + +} /* end of p2pFuncValidateProbeReq() */ + +static void +p2pFunAbortOngoingScan(IN P_ADAPTER_T prAdapter) +{ + P_SCAN_INFO_T prScanInfo; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + if (prScanInfo->eCurrentState != SCAN_STATE_SCANNING) + return; + + switch (prScanInfo->rScanParam.eNetTypeIndex) { + case NETWORK_TYPE_AIS_INDEX: + aisFsmStateAbort_SCAN(prAdapter); + break; + case NETWORK_TYPE_P2P_INDEX: + p2pFsmRunEventScanAbort(prAdapter, NULL); + break; + default: + break; + } +} + +static void p2pProcessActionResponse(IN P_ADAPTER_T prAdapter, + IN enum P2P_ACTION_FRAME_TYPE eType) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + BOOLEAN fgIdle = FALSE; + + if (!prAdapter) + return; + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (!prP2pFsmInfo) + return; + + switch (prP2pFsmInfo->eCNNState) { + case P2P_CNN_GO_NEG_REQ: + if (eType == P2P_GO_NEG_RESP) + fgIdle = TRUE; + break; + case P2P_CNN_GO_NEG_RESP: + if (eType == P2P_GO_NEG_CONF || eType == P2P_GO_NEG_REQ) + fgIdle = TRUE; + break; + case P2P_CNN_INVITATION_REQ: + if (eType == P2P_INVITATION_RESP) + fgIdle = TRUE; + break; + case P2P_CNN_DEV_DISC_REQ: + if (eType == P2P_DEV_DISC_RESP) + fgIdle = TRUE; + break; + case P2P_CNN_PROV_DISC_REQ: + if (eType == P2P_PROV_DISC_RESP) + fgIdle = TRUE; + break; + default: + break; + } + + DBGLOG(P2P, INFO, "eConnState: %d, eType: %d\n", + prP2pFsmInfo->eCNNState, eType); + + if (fgIdle) + prP2pFsmInfo->eCNNState = P2P_CNN_NORMAL; +} + +static void p2pFunBufferP2pActionFrame(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + struct P2P_QUEUED_ACTION_FRAME *prFrame; + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) + return; + + prFrame = &prP2pFsmInfo->rQueuedActionFrame; + + if (prFrame->u2Length > 0) { + DBGLOG(P2P, WARN, "p2p action frames are pending, drop it.\n"); + return; + } + + if (prSwRfb->u2PacketLen <= 0) { + DBGLOG(P2P, WARN, "Invalid packet.\n"); + return; + } + + DBGLOG(P2P, INFO, "Buffer the p2p action frame.\n"); + prFrame->u4Freq = nicChannelNum2Freq(prSwRfb->prHifRxHdr->ucHwChannelNum) / 1000; + prFrame->u2Length = prSwRfb->u2PacketLen; + prFrame->prHeader = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, + prSwRfb->u2PacketLen); + if (prFrame->prHeader == NULL) { + DBGLOG(P2P, WARN, "Allocate buffer fail.\n"); + p2pFunCleanQueuedMgmtFrame(prAdapter, prFrame); + return; + } + kalMemCopy(prFrame->prHeader, prSwRfb->pvHeader, prSwRfb->u2PacketLen); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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; + P_WLAN_ACTION_FRAME prActFrame; + PUINT_8 pucVendor = NULL; + u_int8_t fgBufferFrame = FALSE; + + DEBUGFUNC("p2pFuncValidateProbeReq"); + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + prActFrame = (P_WLAN_ACTION_FRAME) prSwRfb->pvHeader; + pucVendor = (PUINT_8)prActFrame + 26; + + switch (prActFrame->ucCategory) { + case CATEGORY_PUBLIC_ACTION: + if (prActFrame->ucAction != 0x9) + break; + if ((*(pucVendor + 4)) == P2P_GO_NEG_REQ) { + /* Abort scan while receiving P2P_GO_NEG_REQ */ + p2pFunAbortOngoingScan(prAdapter); + } + p2pProcessActionResponse(prAdapter, *(pucVendor + 4)); + p2pFsmNotifyRxP2pActionFrame(prAdapter, *(pucVendor + 4), &fgBufferFrame); + break; + default: + break; + } + + if (fgBufferFrame) { + p2pFunBufferP2pActionFrame(prAdapter, prSwRfb); + break; + } + + if (prP2pFsmInfo->u4P2pPacketFilter & PARAM_PACKET_FILTER_ACTION_FRAME) { + /* Leave the probe response to p2p_supplicant. */ + kalP2PIndicateRxMgmtFrame(prAdapter->prGlueInfo, prSwRfb); + } + + } while (FALSE); + + return; + +} /* p2pFuncValidateRxMgmtFrame */ + +BOOLEAN p2pFuncIsAPMode(IN P_P2P_FSM_INFO_T prP2pFsmInfo) +{ + if (prP2pFsmInfo) { + if (prP2pFsmInfo->fgIsWPSMode == 1) + return FALSE; + return prP2pFsmInfo->fgIsApMode; + } else { + return FALSE; + } +} /* p2pFuncIsAPMode */ + +VOID p2pFuncParseBeaconIEs(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, IN PUINT_8 pucIEInfo, IN UINT_32 u4IELen) +{ + PUINT_8 pucIE = (PUINT_8) NULL; + UINT_16 u2Offset = 0; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + BOOLEAN ucNewSecMode = FALSE; + BOOLEAN ucOldSecMode = FALSE; + UINT_8 ucOuiType; + UINT_16 u2SubTypeVersion; + UINT_8 i = 0; + RSN_INFO_T rRsnIe; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); + + if ((!pucIEInfo) || (u4IELen == 0)) + break; + + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + prP2pSpecificBssInfo->u2AttributeLen = 0; + + pucIE = pucIEInfo; + + ucOldSecMode = kalP2PGetCipher(prAdapter->prGlueInfo); + + IE_FOR_EACH(pucIE, u4IELen, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_SSID: + /* 0 */ /* V */ + /* + * SSID is saved when start AP/GO, + * SSID IE of Beacon template from upper layer may not bring the actural info, + * e.g. hidden SSID case. + */ + /* DBGLOG(P2P, TRACE, ("SSID update\n")); */ + /* + * 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 */ + DBGLOG(P2P, TRACE, "Supported 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, + ELEM_MAX_LEN_SUP_RATES); + + break; + case ELEM_ID_DS_PARAM_SET: + /* 3 */ /* V */ + { + 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"); + 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 overwritten by driver\n"); + DBGLOG(P2P, TRACE, " ucERP: %x.\n", ERP_INFO_IE(pucIE)->ucERP); + + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11G) + prAdapter->rWifiVar.ucWithPhyTypeSpecificIE |= PHY_TYPE_SET_802_11G; +#else + /* This IE would dynamic change due to FW detection change is required. */ + DBGLOG(P2P, TRACE, "ERP IE.\n"); + + prP2pBssInfo->ucPhyTypeSet |= PHY_TYPE_SET_802_11GN; + + ASSERT(prP2pBssInfo->eBand == BAND_2G4); + + prP2pBssInfo->fgObssErpProtectMode = + ((ERP_INFO_IE(pucIE)->ucERP & ERP_INFO_USE_PROTECTION) ? TRUE : FALSE); + + prP2pBssInfo->fgErpProtectMode = + ((ERP_INFO_IE(pucIE)->ucERP & + (ERP_INFO_USE_PROTECTION | ERP_INFO_NON_ERP_PRESENT)) ? TRUE : FALSE); +#endif + + } + break; + case ELEM_ID_HT_CAP: /* 45 */ /* V */ + { +#if 1 + DBGLOG(P2P, TRACE, "HT CAP IE would be overwritten by driver\n"); + + DBGLOG(P2P, TRACE, + "HT Cap Info:%x, AMPDU Param:%x\n", HT_CAP_IE(pucIE)->u2HtCapInfo, + HT_CAP_IE(pucIE)->ucAmpduParam); + + DBGLOG(P2P, TRACE, + "HT Extended Cap Info%x,TX Beamforming Cap Info%x,Ant Selection Cap Info%x\n", + HT_CAP_IE(pucIE)->u2HtExtendedCap, HT_CAP_IE(pucIE)->u4TxBeamformingCap, + HT_CAP_IE(pucIE)->ucAselCap); + + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) + prAdapter->rWifiVar.ucWithPhyTypeSpecificIE |= PHY_TYPE_SET_802_11N; +#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 */ + { + 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; + DBGLOG(RSN, TRACE, "RsnIe CAP:0x%x\n", + rRsnIe.u2RsnCap); + } +#if CFG_SUPPORT_802_11W + /* AP PMF */ + prP2pBssInfo->rApPmfCfg.fgMfpc = + (rRsnIe.u2RsnCap & ELEM_WPA_CAP_MFPC) ? 1 : 0; + prP2pBssInfo->rApPmfCfg.fgMfpr = + (rRsnIe.u2RsnCap & ELEM_WPA_CAP_MFPR) ? 1 : 0; + prP2pSpecificBssInfo->u4KeyMgtSuiteCount + = (rRsnIe.u4AuthKeyMgtSuiteCount < P2P_MAX_AKM_SUITES) + ? rRsnIe.u4AuthKeyMgtSuiteCount + : P2P_MAX_AKM_SUITES; + for (i = 0; i < rRsnIe.u4AuthKeyMgtSuiteCount; i++) { + if ((rRsnIe.au4AuthKeyMgtSuite[i] == + RSN_AKM_SUITE_PSK_SHA256) || + (rRsnIe.au4AuthKeyMgtSuite[i] == + RSN_AKM_SUITE_802_1X_SHA256)) { + DBGLOG(RSN, INFO, "SHA256 support\n"); + /* over-write u4RsnSelectedAKMSuite by SHA256 AKM */ + prP2pBssInfo->u4RsnSelectedAKMSuite = + rRsnIe.au4AuthKeyMgtSuite[i]; + prP2pBssInfo->rApPmfCfg.fgSha256 = TRUE; + break; + } else if (rRsnIe.au4AuthKeyMgtSuite[i] + == RSN_AKM_SUITE_SAE) + prP2pBssInfo->u4RsnSelectedAKMSuite = + rRsnIe.au4AuthKeyMgtSuite[i]; + + if (i < P2P_MAX_AKM_SUITES) { + prP2pSpecificBssInfo->au4KeyMgtSuite[i] + = rRsnIe.au4AuthKeyMgtSuite[i]; + } + + } + DBGLOG(RSN, ERROR, "bcn mfpc:%d, mfpr:%d, sha256:%d, 0x%04x\n", + prP2pBssInfo->rApPmfCfg.fgMfpc, + prP2pBssInfo->rApPmfCfg.fgMfpr, + prP2pBssInfo->rApPmfCfg.fgSha256, + prP2pBssInfo->u4RsnSelectedAKMSuite); +#endif + } + 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, "Extended Supported Rate IE\n"); + ASSERT(prP2pBssInfo->ucAllSupportedRatesLen <= RATE_NUM); + 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 */ + { +#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); + + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) + prAdapter->rWifiVar.ucWithPhyTypeSpecificIE |= PHY_TYPE_SET_802_11N; +#else + UINT_16 u2Info2 = 0; + + prP2pBssInfo->ucPhyTypeSet |= PHY_TYPE_SET_802_11N; + + DBGLOG(P2P, TRACE, "HT OP IE\n"); + + /* ucPrimaryChannel. */ + ASSERT(HT_OP_IE(pucIE)->ucPrimaryChannel == prP2pBssInfo->ucPrimaryChannel); + + /* ucInfo1 */ + prP2pBssInfo->ucHtOpInfo1 = HT_OP_IE(pucIE)->ucInfo1; + + /* u2Info2 */ + u2Info2 = HT_OP_IE(pucIE)->u2Info2; + + if (u2Info2 & HT_OP_INFO2_NON_GF_HT_STA_PRESENT) { + ASSERT(prP2pBssInfo->eGfOperationMode != GF_MODE_NORMAL); + u2Info2 &= ~HT_OP_INFO2_NON_GF_HT_STA_PRESENT; + } + + if (u2Info2 & HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT) { + prP2pBssInfo->eObssHtProtectMode = HT_PROTECT_MODE_NON_MEMBER; + u2Info2 &= ~HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT; + } + + switch (u2Info2 & HT_OP_INFO2_HT_PROTECTION) { + case HT_PROTECT_MODE_NON_HT: + prP2pBssInfo->eHtProtectMode = HT_PROTECT_MODE_NON_HT; + break; + case HT_PROTECT_MODE_NON_MEMBER: + prP2pBssInfo->eHtProtectMode = HT_PROTECT_MODE_NONE; + prP2pBssInfo->eObssHtProtectMode = HT_PROTECT_MODE_NON_MEMBER; + break; + default: + prP2pBssInfo->eHtProtectMode = HT_OP_IE(pucIE)->u2Info2; + break; + } + + /* u2Info3 */ + prP2pBssInfo->u2HtOpInfo3 = HT_OP_IE(pucIE)->u2Info3; + + /* aucBasicMcsSet */ + DBGLOG_MEM8(P2P, TRACE, HT_OP_IE(pucIE)->aucBasicMcsSet, 16); +#endif + } + break; + case ELEM_ID_OBSS_SCAN_PARAMS: /* 74 */ /* V */ + DBGLOG(P2P, TRACE, "ELEM_ID_OBSS_SCAN_PARAMS IE would be replaced by driver\n"); + break; + case ELEM_ID_EXTENDED_CAP: /* 127 */ /* V */ + DBGLOG(P2P, TRACE, "ELEM_ID_EXTENDED_CAP IE would be replaced by driver\n"); + break; + case ELEM_ID_VENDOR: /* 221 */ /* V */ + DBGLOG(P2P, TRACE, "Vender Specific IE\n"); + + if (rsnParseCheckForWFAInfoElem + (prAdapter, pucIE, &ucOuiType, &u2SubTypeVersion)) { + if ((ucOuiType == VENDOR_OUI_TYPE_WPA) + && (u2SubTypeVersion == VERSION_WPA)) { + kalP2PSetCipher(prAdapter->prGlueInfo, IW_AUTH_CIPHER_TKIP); + ucNewSecMode = TRUE; + kalMemCopy(prP2pSpecificBssInfo->aucWpaIeBuffer, pucIE, + IE_SIZE(pucIE)); + prP2pSpecificBssInfo->u2WpaIeLen = IE_SIZE(pucIE); + } else if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + kalP2PUpdateWSC_IE(prAdapter->prGlueInfo, 0, pucIE, + IE_SIZE(pucIE)); + } + /* WMM here. */ + } else if (p2pFuncParseCheckForP2PInfoElem(prAdapter, pucIE, &ucOuiType)) { + /* TODO Store the whole P2P IE & generate later. */ + /* Be aware that there may be one or more P2P IE. */ + if (ucOuiType == VENDOR_OUI_TYPE_P2P) { + kalMemCopy(&prP2pSpecificBssInfo->aucAttributesCache + [prP2pSpecificBssInfo->u2AttributeLen], pucIE, + IE_SIZE(pucIE)); + + prP2pSpecificBssInfo->u2AttributeLen += IE_SIZE(pucIE); + } else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { + + kalMemCopy(&prP2pSpecificBssInfo->aucAttributesCache + [prP2pSpecificBssInfo->u2AttributeLen], pucIE, + IE_SIZE(pucIE)); + + prP2pSpecificBssInfo->u2AttributeLen += IE_SIZE(pucIE); + } + } else { + + kalMemCopy(&prP2pSpecificBssInfo->aucAttributesCache + [prP2pSpecificBssInfo->u2AttributeLen], pucIE, + IE_SIZE(pucIE)); + + prP2pSpecificBssInfo->u2AttributeLen += IE_SIZE(pucIE); + DBGLOG(P2P, TRACE, "Driver unprocessed Vender Specific IE\n"); + ASSERT(FALSE); + } + + /* TODO: Store other Vender IE except for WMM Param. */ + break; + default: + DBGLOG(P2P, TRACE, "Unprocessed element ID:%d\n", IE_ID(pucIE)); + break; + } + } + + if (!ucNewSecMode && ucOldSecMode) + kalP2PSetCipher(prAdapter->prGlueInfo, IW_AUTH_CIPHER_NONE); + + } while (FALSE); + +} /* p2pFuncParseBeaconContent */ + +P_BSS_DESC_T +p2pFuncKeepOnConnection(IN P_ADAPTER_T prAdapter, + IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo) +{ + P_BSS_DESC_T prTargetBss = (P_BSS_DESC_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && + (prConnReqInfo != NULL) && (prChnlReqInfo != NULL) && (prScanReqInfo != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + if (prP2pBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + break; + /* Update connection request information. */ + ASSERT(prConnReqInfo->fgIsConnRequest == TRUE); + + /* Find BSS Descriptor first. */ + prTargetBss = scanP2pSearchDesc(prAdapter, prP2pBssInfo, prConnReqInfo); + + if (prTargetBss == NULL) { + /* Update scan parameter... to scan target device. */ + prScanReqInfo->ucNumChannelList = 1; + prScanReqInfo->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prScanReqInfo->eChannelSet = SCAN_CHANNEL_FULL; + prScanReqInfo->u4BufLength = 0; /* Prevent other P2P ID in IE. */ + prScanReqInfo->fgIsAbort = TRUE; + } else { + prChnlReqInfo->u8Cookie = 0; + prChnlReqInfo->ucReqChnlNum = prTargetBss->ucChannelNum; + prChnlReqInfo->eBand = prTargetBss->eBand; + prChnlReqInfo->eChnlSco = prTargetBss->eSco; + prChnlReqInfo->u4MaxInterval = AIS_JOIN_CH_REQUEST_INTERVAL; + prChnlReqInfo->eChannelReqType = CHANNEL_REQ_TYPE_GC_JOIN_REQ; + } + + } while (FALSE); + + return prTargetBss; +} /* p2pFuncKeepOnConnection */ + +/* Currently Only for ASSOC Response Frame. */ +VOID p2pFuncStoreAssocRspIEBuffer(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_P2P_JOIN_INFO_T prJoinInfo = (P_P2P_JOIN_INFO_T) NULL; + P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) NULL; + INT_16 i2IELen = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + + prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) prSwRfb->pvHeader; + + if (prAssocRspFrame->u2FrameCtrl != MAC_FRAME_ASSOC_RSP) + break; + + i2IELen = prSwRfb->u2PacketLen - (WLAN_MAC_HEADER_LEN + + CAP_INFO_FIELD_LEN + STATUS_CODE_FIELD_LEN + AID_FIELD_LEN); + + if (i2IELen <= 0) + break; + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + prJoinInfo = &(prP2pFsmInfo->rJoinInfo); + prJoinInfo->u4BufLength = (UINT_32) i2IELen; + + kalMemCopy(prJoinInfo->aucIEBuf, prAssocRspFrame->aucInfoElem, prJoinInfo->u4BufLength); + + } while (FALSE); + +} /* p2pFuncStoreAssocRspIEBuffer */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set Packet Filter. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_NOT_SUPPORTED +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFuncMgmtFrameRegister(IN P_ADAPTER_T prAdapter, + IN UINT_16 u2FrameType, IN BOOLEAN fgIsRegistered, OUT PUINT_32 pu4P2pPacketFilter) +{ + UINT_32 u4NewPacketFilter = 0; + + DEBUGFUNC("p2pFuncMgmtFrameRegister"); + + do { + ASSERT_BREAK(prAdapter != NULL); + + if (pu4P2pPacketFilter) + u4NewPacketFilter = *pu4P2pPacketFilter; + + switch (u2FrameType) { + case MAC_FRAME_PROBE_REQ: + if (fgIsRegistered) { + u4NewPacketFilter |= PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(P2P, TRACE, "Open packet filer probe request\n"); + } else { + u4NewPacketFilter &= ~PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(P2P, TRACE, "Close packet filer probe request\n"); + } + break; + case MAC_FRAME_ACTION: + if (fgIsRegistered) { + u4NewPacketFilter |= PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(P2P, TRACE, "Open packet filer action frame.\n"); + } else { + u4NewPacketFilter &= ~PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(P2P, TRACE, "Close packet filer action frame.\n"); + } + break; + default: + DBGLOG(P2P, TRACE, "Ask frog to add code for mgmt:%x\n", u2FrameType); + break; + } + + if (pu4P2pPacketFilter) + *pu4P2pPacketFilter = u4NewPacketFilter; + + /* u4NewPacketFilter |= prAdapter->u4OsPacketFilter; */ + + prAdapter->u4OsPacketFilter &= ~PARAM_PACKET_FILTER_P2P_MASK; + prAdapter->u4OsPacketFilter |= u4NewPacketFilter; + + DBGLOG(P2P, TRACE, "P2P Set PACKET filter:0x%x\n", prAdapter->u4OsPacketFilter); + + wlanoidSetPacketFilter(prAdapter, prAdapter->u4OsPacketFilter, + FALSE, &u4NewPacketFilter, sizeof(u4NewPacketFilter)); + + } while (FALSE); + +} /* p2pFuncMgmtFrameRegister */ + +VOID p2pFuncUpdateMgmtFrameRegister(IN P_ADAPTER_T prAdapter, IN UINT_32 u4OsFilter) +{ + + do { + + prAdapter->rWifiVar.prP2pFsmInfo->u4P2pPacketFilter = u4OsFilter; + + if ((prAdapter->u4OsPacketFilter & PARAM_PACKET_FILTER_P2P_MASK) ^ u4OsFilter) { + + prAdapter->u4OsPacketFilter &= ~PARAM_PACKET_FILTER_P2P_MASK; + + prAdapter->u4OsPacketFilter |= (u4OsFilter & PARAM_PACKET_FILTER_P2P_MASK); + + wlanoidSetPacketFilter(prAdapter, prAdapter->u4OsPacketFilter, + FALSE, &u4OsFilter, sizeof(u4OsFilter)); + DBGLOG(P2P, TRACE, "P2P Set PACKET filter:0x%x\n", prAdapter->u4OsPacketFilter); + } + + } while (FALSE); + +} /* p2pFuncUpdateMgmtFrameRegister */ + +VOID p2pFuncGetStationInfo(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucMacAddr, OUT P_P2P_STATION_INFO_T prStaInfo) +{ + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucMacAddr != NULL) && (prStaInfo != NULL)); + + prStaInfo->u4InactiveTime = 0; + prStaInfo->u4RxBytes = 0; + prStaInfo->u4TxBytes = 0; + prStaInfo->u4RxPackets = 0; + prStaInfo->u4TxPackets = 0; + /* TODO: */ + + } while (FALSE); + +} /* p2pFuncGetStationInfo */ + +BOOLEAN +p2pFuncGetAttriList(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucOuiType, + IN PUINT_8 pucIE, IN UINT_16 u2IELength, OUT PPUINT_8 ppucAttriList, OUT PUINT_16 pu2AttriListLen) +{ + BOOLEAN fgIsAllocMem = FALSE; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + UINT_16 u2Offset = 0; + P_IE_P2P_T prIe = (P_IE_P2P_T) NULL; + PUINT_8 pucAttriListStart = (PUINT_8) NULL; + UINT_16 u2AttriListLen = 0, u2BufferSize = 0; + BOOLEAN fgBackupAttributes = FALSE; + UINT_16 u2CopyLen; + + ASSERT(prAdapter); + ASSERT(pucIE); + ASSERT(ppucAttriList); + ASSERT(pu2AttriListLen); + + if (ppucAttriList) + *ppucAttriList = NULL; + if (pu2AttriListLen) + *pu2AttriListLen = 0; + + if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + aucWfaOui[0] = 0x00; + aucWfaOui[1] = 0x50; + aucWfaOui[2] = 0xF2; + } else if ((ucOuiType != VENDOR_OUI_TYPE_P2P) +#if CFG_SUPPORT_WFD + && (ucOuiType != VENDOR_OUI_TYPE_WFD) +#endif + ) { + DBGLOG(P2P, INFO, "Not supported OUI Type to parsing 0x%x\n", ucOuiType); + return fgIsAllocMem; + } + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (IE_ID(pucIE) != ELEM_ID_VENDOR) + continue; + + prIe = (P_IE_P2P_T) pucIE; + + if (prIe->ucLength <= P2P_OUI_TYPE_LEN) + continue; + + if ((prIe->aucOui[0] == aucWfaOui[0]) && + (prIe->aucOui[1] == aucWfaOui[1]) && + (prIe->aucOui[2] == aucWfaOui[2]) && (ucOuiType == prIe->ucOuiType)) { + + if (!pucAttriListStart) { + pucAttriListStart = &prIe->aucP2PAttributes[0]; + if (prIe->ucLength > P2P_OUI_TYPE_LEN) + u2AttriListLen = (UINT_16) (prIe->ucLength - P2P_OUI_TYPE_LEN); + else + ASSERT(FALSE); + continue; + } + /* More than 2 attributes. */ + + if (fgBackupAttributes == FALSE) { + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = + prAdapter->rWifiVar.prP2pSpecificBssInfo; + + fgBackupAttributes = TRUE; + if (ucOuiType == VENDOR_OUI_TYPE_P2P) { + kalMemCopy(&prP2pSpecificBssInfo->aucAttributesCache[0], + pucAttriListStart, u2AttriListLen); + + pucAttriListStart = + &prP2pSpecificBssInfo->aucAttributesCache[0]; + + u2BufferSize = P2P_MAXIMUM_ATTRIBUTE_LEN; + } else if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + kalMemCopy(&prP2pSpecificBssInfo->aucWscAttributesCache + [0], pucAttriListStart, u2AttriListLen); + pucAttriListStart = + &prP2pSpecificBssInfo->aucWscAttributesCache[0]; + + u2BufferSize = WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE; + } +#if CFG_SUPPORT_WFD + else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { + PUINT_8 pucTmpBuf = (PUINT_8) NULL; + + pucTmpBuf = (PUINT_8) + kalMemAlloc(WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE, + VIR_MEM_TYPE); + + if (pucTmpBuf != NULL) { + fgIsAllocMem = TRUE; + } else { + /* Can't alloca memory for WFD IE relocate. */ + ASSERT(FALSE); + break; + } + + kalMemCopy(pucTmpBuf, + pucAttriListStart, u2AttriListLen); + + pucAttriListStart = pucTmpBuf; + + u2BufferSize = WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE; + } +#endif + else + fgBackupAttributes = FALSE; + } + + u2CopyLen = (UINT_16) (prIe->ucLength - P2P_OUI_TYPE_LEN); + + if ((u2AttriListLen + u2CopyLen) > u2BufferSize) { + u2CopyLen = u2BufferSize - u2AttriListLen; + DBGLOG(P2P, WARN, + "Length of received P2P attributes > maximum cache size.\n"); + } + + if (u2CopyLen) { + kalMemCopy((PUINT_8) + ((ULONG) pucAttriListStart + + (UINT_32) u2AttriListLen), + &prIe->aucP2PAttributes[0], u2CopyLen); + + u2AttriListLen += u2CopyLen; + } + } /* prIe->aucOui */ + } /* IE_FOR_EACH */ + + if (pucAttriListStart) { + PUINT_8 pucAttribute = pucAttriListStart; + + DBGLOG(P2P, LOUD, "Checking Attribute Length.\n"); + if (ucOuiType == VENDOR_OUI_TYPE_P2P) { + P2P_ATTRI_FOR_EACH(pucAttribute, u2AttriListLen, u2Offset); + } else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { + /* Do nothing */ + } else if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + /* Big Endian: WSC, WFD. */ + WSC_ATTRI_FOR_EACH(pucAttribute, u2AttriListLen, u2Offset) { + DBGLOG(P2P, LOUD, "Attribute ID:%d, Length:%d.\n", + WSC_ATTRI_ID(pucAttribute), WSC_ATTRI_LEN(pucAttribute)); + } + } else { + } + + ASSERT(u2Offset == u2AttriListLen); + + if (ppucAttriList) + *ppucAttriList = pucAttriListStart; + if (pu2AttriListLen) + *pu2AttriListLen = u2AttriListLen; + + } else { + if (ppucAttriList) + *ppucAttriList = (PUINT_8) NULL; + if (pu2AttriListLen) + *pu2AttriListLen = 0; + } + + return fgIsAllocMem; +} /* p2pFuncGetAttriList */ + +P_MSDU_INFO_T p2pFuncProcessP2pProbeRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMgmtTxMsdu) +{ + P_MSDU_INFO_T prRetMsduInfo = prMgmtTxMsdu; + P_WLAN_PROBE_RSP_FRAME_T prProbeRspFrame = (P_WLAN_PROBE_RSP_FRAME_T) NULL; + PUINT_8 pucIEBuf = (PUINT_8) NULL; + UINT_16 u2Offset = 0, u2IELength = 0, u2ProbeRspHdrLen = 0; + BOOLEAN fgIsP2PIE = FALSE, fgIsWSCIE = FALSE; + BOOLEAN fgIsWFDIE = FALSE; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + UINT_16 u2EstimateSize = 0, u2EstimatedExtraIELen = 0; + UINT_32 u4IeArraySize = 0, u4Idx = 0, u4P2PIeIdx = 0; + UINT_8 ucOuiType = 0; + UINT_16 u2SubTypeVersion = 0; + + BOOLEAN fgIsPureAP = prAdapter->rWifiVar.prP2pFsmInfo->fgIsApMode; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMgmtTxMsdu != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + /* 3 Make sure this is probe response frame. */ + prProbeRspFrame = (P_WLAN_PROBE_RSP_FRAME_T) ((ULONG) prMgmtTxMsdu->prPacket + MAC_TX_RESERVED_FIELD); + ASSERT_BREAK((prProbeRspFrame->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_PROBE_RSP); + + if (prP2pBssInfo->u2BeaconInterval) + prProbeRspFrame->u2BeaconInterval = prP2pBssInfo->u2BeaconInterval; + + /* 3 Get the importent P2P IE. */ + u2ProbeRspHdrLen = + (WLAN_MAC_MGMT_HEADER_LEN + TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN); + pucIEBuf = prProbeRspFrame->aucInfoElem; + u2IELength = prMgmtTxMsdu->u2FrameLength - u2ProbeRspHdrLen; + +#if CFG_SUPPORT_WFD + prAdapter->prGlueInfo->prP2PInfo->u2WFDIELen = 0; + prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen = 0; +#endif + + IE_FOR_EACH(pucIEBuf, u2IELength, u2Offset) { + switch (IE_ID(pucIEBuf)) { + case ELEM_ID_SSID: + { + + COPY_SSID(prP2pBssInfo->aucSSID, + prP2pBssInfo->ucSSIDLen, + SSID_IE(pucIEBuf)->aucSSID, SSID_IE(pucIEBuf)->ucLength); + } + break; + case ELEM_ID_VENDOR: +#if !CFG_SUPPORT_WFD + if (rsnParseCheckForWFAInfoElem(prAdapter, pucIEBuf, &ucOuiType, &u2SubTypeVersion)) { + if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + kalP2PUpdateWSC_IE(prAdapter->prGlueInfo, 2, pucIEBuf, + IE_SIZE(pucIEBuf)); + fgIsWSCIE = TRUE; + } + + } else if (p2pFuncParseCheckForP2PInfoElem(prAdapter, pucIEBuf, &ucOuiType) && + (ucOuiType == VENDOR_OUI_TYPE_P2P)) { + if (u4P2PIeIdx < MAX_P2P_IE_SIZE) { + kalP2PUpdateP2P_IE(prAdapter->prGlueInfo, + u4P2PIeIdx, pucIEBuf, IE_SIZE(pucIEBuf)); + u4P2PIeIdx++; + fgIsP2PIE = TRUE; + } else + DBGLOG(P2P, WARN, "Too much P2P IE for ProbeResp, skip update\n"); + } 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 */ + /* + * kernel 4.4 check patch perl script should have bugs: + * WARNING:SUSPECT_CODE_INDENT: suspect code indent for conditional statements (8, 32) + * #2751: FILE: drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_func.c:2751: + * + do { + * [...] + * + if (ucOuiType == VENDOR_OUI_TYPE_WMM) + * + * total: 0 errors, 1 warnings, 3721 lines checked + */ + if (rsnParseCheckForWFAInfoElem + (prAdapter, pucIEBuf, &ucOuiType, &u2SubTypeVersion)) { + + if (ucOuiType == VENDOR_OUI_TYPE_WMM) + break; + } + if (p2pFuncParseCheckForP2PInfoElem(prAdapter, pucIEBuf, &ucOuiType)) { + if (ucOuiType == VENDOR_OUI_TYPE_P2P) { + if (u4P2PIeIdx < MAX_P2P_IE_SIZE) { + kalP2PUpdateP2P_IE(prAdapter->prGlueInfo, + u4P2PIeIdx, pucIEBuf, IE_SIZE(pucIEBuf)); + u4P2PIeIdx++; + fgIsP2PIE = TRUE; + } else + DBGLOG(P2P, WARN, "Too much P2P IE for ProbeResp, skip update\n"); + } else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { + DBGLOG(P2P, INFO, + "WFD IE is found in probe resp (supp). Len %u\n", IE_SIZE(pucIEBuf)); + if ((sizeof(prAdapter->prGlueInfo->prP2PInfo->aucWFDIE) >= + (prAdapter->prGlueInfo->prP2PInfo->u2WFDIELen + IE_SIZE(pucIEBuf)))) { + fgIsWFDIE = TRUE; + kalMemCopy(prAdapter->prGlueInfo->prP2PInfo->aucWFDIE, + pucIEBuf, IE_SIZE(pucIEBuf)); + prAdapter->prGlueInfo->prP2PInfo->u2WFDIELen += IE_SIZE(pucIEBuf); + } + } /* VENDOR_OUI_TYPE_WFD */ + } else { + DBGLOG(P2P, TRACE, + "Other vender IE is found in probe resp (supp). Len %u\n", IE_SIZE(pucIEBuf)); + 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) { + for (u4Idx = 0; u4Idx < u4P2PIeIdx; u4Idx++) + u2EstimatedExtraIELen += kalP2PCalP2P_IELen(prAdapter->prGlueInfo, u4Idx); + + u2EstimatedExtraIELen += p2pFuncCalculateP2P_IE_NoA(prAdapter, 0, NULL); + } +#if CFG_SUPPORT_WFD + ASSERT(sizeof(prAdapter->prGlueInfo->prP2PInfo->aucWFDIE) >= + prAdapter->prGlueInfo->prP2PInfo->u2WFDIELen); + if (fgIsWFDIE) + u2EstimatedExtraIELen += prAdapter->prGlueInfo->prP2PInfo->u2WFDIELen; + + u2EstimatedExtraIELen += prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen; +#endif + + u2EstimateSize += u2EstimatedExtraIELen; + if (u2EstimateSize > (prRetMsduInfo->u2FrameLength)) { + prRetMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimateSize); + + if (prRetMsduInfo == NULL) { + DBGLOG(P2P, WARN, "No packet for sending new probe response, use original one\n"); + prRetMsduInfo = prMgmtTxMsdu; + break; + } + + prRetMsduInfo->ucNetworkType = NETWORK_TYPE_P2P_INDEX; + } + + prRetMsduInfo->ucStaRecIndex = 0xFF; + /* 3 Compose / Re-compose probe response frame. */ + bssComposeBeaconProbeRespFrameHeaderAndFF((PUINT_8) + ((ULONG) (prRetMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + prProbeRspFrame->aucDestAddr, prProbeRspFrame->aucSrcAddr, + prProbeRspFrame->aucBSSID, prProbeRspFrame->u2BeaconInterval, + fgIsPureAP ? prP2pBssInfo-> + u2CapInfo : prProbeRspFrame->u2CapInfo); + + prRetMsduInfo->u2FrameLength = + (WLAN_MAC_MGMT_HEADER_LEN + TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN); + + bssBuildBeaconProbeRespFrameCommonIEs(prRetMsduInfo, prP2pBssInfo, prProbeRspFrame->aucDestAddr); + + for (u4Idx = 0; u4Idx < u4IeArraySize; u4Idx++) { + if (txProbeRspIETable[u4Idx].pfnAppendIE) + txProbeRspIETable[u4Idx].pfnAppendIE(prAdapter, prRetMsduInfo); + + } + + if (fgIsWSCIE) { + kalP2PGenWSC_IE(prAdapter->prGlueInfo, + 2, + (PUINT_8) ((ULONG) prRetMsduInfo->prPacket + + (UINT_32) prRetMsduInfo->u2FrameLength)); + + prRetMsduInfo->u2FrameLength += (UINT_16) kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 2); + } + + if (fgIsP2PIE) { + for (u4Idx = 0; u4Idx < u4P2PIeIdx; u4Idx++) { + kalP2PGenP2P_IE(prAdapter->prGlueInfo, + u4Idx, + (PUINT_8) ((ULONG) prRetMsduInfo->prPacket + + (UINT_32) prRetMsduInfo->u2FrameLength)); + + prRetMsduInfo->u2FrameLength += + (UINT_16) kalP2PCalP2P_IELen(prAdapter->prGlueInfo, u4Idx); + } + + p2pFuncGenerateP2P_IE_NoA(prAdapter, prRetMsduInfo); + } +#if CFG_SUPPORT_WFD + if (fgIsWFDIE) { + ASSERT(prAdapter->prGlueInfo->prP2PInfo->u2WFDIELen > 0); + kalMemCopy((PUINT_8) + ((ULONG) prRetMsduInfo->prPacket + + (ULONG) prRetMsduInfo->u2FrameLength), + prAdapter->prGlueInfo->prP2PInfo->aucWFDIE, + prAdapter->prGlueInfo->prP2PInfo->u2WFDIELen); + prRetMsduInfo->u2FrameLength += (UINT_16) prAdapter->prGlueInfo->prP2PInfo->u2WFDIELen; + + } + + if (prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen > 0) { + kalMemCopy((PUINT_8) ((ULONG) prRetMsduInfo->prPacket + (UINT_32) prRetMsduInfo->u2FrameLength), + prAdapter->prGlueInfo->prP2PInfo->aucVenderIE, + prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen); + prRetMsduInfo->u2FrameLength += (UINT_16) prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen; + } +#endif + + } while (FALSE); + + if (prRetMsduInfo != prMgmtTxMsdu) + cnmMgtPktFree(prAdapter, prMgmtTxMsdu); + + return prRetMsduInfo; +} /* p2pFuncProcessP2pProbeRsp */ + +#if 0 /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */ +UINT_32 +p2pFuncCalculateExtra_IELenForBeacon(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec) +{ + + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpeBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + UINT_32 u4IELen = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (eNetTypeIndex == NETWORK_TYPE_P2P_INDEX)); + + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) + break; + + prP2pSpeBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + u4IELen = prP2pSpeBssInfo->u2IELenForBCN; + + } while (FALSE); + + return u4IELen; +} /* p2pFuncCalculateP2p_IELenForBeacon */ + +VOID p2pFuncGenerateExtra_IEForBeacon(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpeBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + PUINT_8 pucIEBuf = (PUINT_8) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + prP2pSpeBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) + break; + + pucIEBuf = (PUINT_8) ((UINT_32) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + + kalMemCopy(pucIEBuf, prP2pSpeBssInfo->aucBeaconIECache, prP2pSpeBssInfo->u2IELenForBCN); + + prMsduInfo->u2FrameLength += prP2pSpeBssInfo->u2IELenForBCN; + + } while (FALSE); + +} /* p2pFuncGenerateExtra_IEForBeacon */ + +#else +UINT_32 +p2pFuncCalculateP2p_IELenForBeacon(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec) +{ + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpeBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + UINT_32 u4IELen = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (eNetTypeIndex == NETWORK_TYPE_P2P_INDEX)); + + if (!prAdapter->fgIsP2PRegistered) + break; + + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) + break; + + prP2pSpeBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + u4IELen = prP2pSpeBssInfo->u2AttributeLen; + + } while (FALSE); + + return u4IELen; +} /* p2pFuncCalculateP2p_IELenForBeacon */ + +VOID p2pFuncGenerateP2p_IEForBeacon(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpeBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + PUINT_8 pucIEBuf = (PUINT_8) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + if (!prAdapter->fgIsP2PRegistered) + break; + + prP2pSpeBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) + break; + + pucIEBuf = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + + kalMemCopy(pucIEBuf, prP2pSpeBssInfo->aucAttributesCache, prP2pSpeBssInfo->u2AttributeLen); + + prMsduInfo->u2FrameLength += prP2pSpeBssInfo->u2AttributeLen; + + } while (FALSE); + +} /* p2pFuncGenerateP2p_IEForBeacon */ + +UINT_32 +p2pFuncCalculateWSC_IELenForBeacon(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec) +{ + if (eNetTypeIndex != NETWORK_TYPE_P2P_INDEX) + return 0; + + return kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 0); +} /* p2pFuncCalculateP2p_IELenForBeacon */ + +VOID p2pFuncGenerateWSC_IEForBeacon(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + PUINT_8 pucBuffer; + UINT_16 u2IELen = 0; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + if (prMsduInfo->ucNetworkType != NETWORK_TYPE_P2P_INDEX) + return; + + u2IELen = (UINT_16) kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 0); + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + + ASSERT(pucBuffer); + + /* TODO: Check P2P FSM State. */ + kalP2PGenWSC_IE(prAdapter->prGlueInfo, 0, pucBuffer); + + prMsduInfo->u2FrameLength += u2IELen; + +} /* p2pFuncGenerateP2p_IEForBeacon */ + +#endif +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to calculate P2P IE length for Beacon frame. +* +* @param[in] eNetTypeIndex Specify which network +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return The length of P2P IE added +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +p2pFuncCalculateP2p_IELenForAssocRsp(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec) +{ + + if (eNetTypeIndex != NETWORK_TYPE_P2P_INDEX) + return 0; + + return p2pFuncCalculateP2P_IELen(prAdapter, + eNetTypeIndex, + prStaRec, + txAssocRspAttributesTable, + sizeof(txAssocRspAttributesTable) / sizeof(APPEND_VAR_ATTRI_ENTRY_T)); + +} /* p2pFuncCalculateP2p_IELenForAssocRsp */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to generate P2P IE for Beacon frame. +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFuncGenerateP2p_IEForAssocRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + if (!prStaRec) + break; + + if (IS_STA_P2P_TYPE(prStaRec)) { + DBGLOG(P2P, TRACE, "Generate NULL P2P IE for Assoc Rsp.\n"); + + p2pFuncGenerateP2P_IE(prAdapter, + TRUE, + &prMsduInfo->u2FrameLength, + prMsduInfo->prPacket, + 1500, + txAssocRspAttributesTable, + sizeof(txAssocRspAttributesTable) / sizeof(APPEND_VAR_ATTRI_ENTRY_T)); + } else { + + DBGLOG(P2P, TRACE, "Legacy device, no P2P IE.\n"); + } + + } while (FALSE); + + return; + +} /* p2pFuncGenerateP2p_IEForAssocRsp */ + +UINT_32 +p2pFuncCalculateWSC_IELenForAssocRsp(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec) +{ + DBGLOG(P2P, TRACE, "p2pFuncCalculateWSC_IELenForAssocRsp\n"); + if (eNetTypeIndex != NETWORK_TYPE_P2P_INDEX) + return 0; + + return kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 0); +} /* p2pFuncCalculateP2p_IELenForAssocRsp */ + +VOID p2pFuncGenerateWSC_IEForAssocRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + PUINT_8 pucBuffer; + UINT_16 u2IELen = 0; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + if (prMsduInfo->ucNetworkType != NETWORK_TYPE_P2P_INDEX) + return; + DBGLOG(P2P, TRACE, "p2pFuncGenerateWSC_IEForAssocRsp\n"); + + u2IELen = (UINT_16) kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 0); + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + + ASSERT(pucBuffer); + + /* TODO: Check P2P FSM State. */ + kalP2PGenWSC_IE(prAdapter->prGlueInfo, 0, pucBuffer); + + prMsduInfo->u2FrameLength += u2IELen; + +} + +/* p2pFuncGenerateP2p_IEForAssocRsp */ + +UINT_32 +p2pFuncCalculateP2P_IELen(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec, + IN APPEND_VAR_ATTRI_ENTRY_T arAppendAttriTable[], IN UINT_32 u4AttriTableSize) +{ + + UINT_32 u4OverallAttriLen, u4Dummy; + UINT_16 u2EstimatedFixedAttriLen; + UINT_32 i; + + /* Overall length of all Attributes */ + u4OverallAttriLen = 0; + + for (i = 0; i < u4AttriTableSize; i++) { + u2EstimatedFixedAttriLen = arAppendAttriTable[i].u2EstimatedFixedAttriLen; + + if (u2EstimatedFixedAttriLen) { + u4OverallAttriLen += u2EstimatedFixedAttriLen; + } else { + ASSERT(arAppendAttriTable[i].pfnCalculateVariableAttriLen); + + u4OverallAttriLen += arAppendAttriTable[i].pfnCalculateVariableAttriLen(prAdapter, prStaRec); + } + } + + u4Dummy = u4OverallAttriLen; + u4OverallAttriLen += P2P_IE_OUI_HDR; + + for (; (u4Dummy > P2P_MAXIMUM_ATTRIBUTE_LEN);) { + u4OverallAttriLen += P2P_IE_OUI_HDR; + u4Dummy -= P2P_MAXIMUM_ATTRIBUTE_LEN; + } + + return u4OverallAttriLen; +} /* p2pFuncCalculateP2P_IELen */ + +VOID +p2pFuncGenerateP2P_IE(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize, + IN APPEND_VAR_ATTRI_ENTRY_T arAppendAttriTable[], IN UINT_32 u4AttriTableSize) +{ + PUINT_8 pucBuffer = (PUINT_8) NULL; + P_IE_P2P_T prIeP2P = (P_IE_P2P_T) NULL; + UINT_32 u4OverallAttriLen; + UINT_32 u4AttriLen; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + UINT_8 aucTempBuffer[P2P_MAXIMUM_ATTRIBUTE_LEN]; + UINT_32 i; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL)); + + pucBuffer = (PUINT_8) ((ULONG) pucBuf + (*pu2Offset)); + + ASSERT_BREAK(pucBuffer != NULL); + + /* Check buffer length is still enough. */ + ASSERT_BREAK((u2BufSize - (*pu2Offset)) >= P2P_IE_OUI_HDR); + + prIeP2P = (P_IE_P2P_T) pucBuffer; + + prIeP2P->ucId = ELEM_ID_P2P; + + prIeP2P->aucOui[0] = aucWfaOui[0]; + prIeP2P->aucOui[1] = aucWfaOui[1]; + prIeP2P->aucOui[2] = aucWfaOui[2]; + prIeP2P->ucOuiType = VENDOR_OUI_TYPE_P2P; + + (*pu2Offset) += P2P_IE_OUI_HDR; + + /* Overall length of all Attributes */ + u4OverallAttriLen = 0; + + for (i = 0; i < u4AttriTableSize; i++) { + + if (arAppendAttriTable[i].pfnAppendAttri) { + u4AttriLen = + arAppendAttriTable[i].pfnAppendAttri(prAdapter, fgIsAssocFrame, pu2Offset, pucBuf, + u2BufSize); + + u4OverallAttriLen += u4AttriLen; + + if (u4OverallAttriLen > P2P_MAXIMUM_ATTRIBUTE_LEN) { + u4OverallAttriLen -= P2P_MAXIMUM_ATTRIBUTE_LEN; + + prIeP2P->ucLength = (VENDOR_OUI_TYPE_LEN + P2P_MAXIMUM_ATTRIBUTE_LEN); + + pucBuffer = + (PUINT_8) ((ULONG) prIeP2P + + (VENDOR_OUI_TYPE_LEN + P2P_MAXIMUM_ATTRIBUTE_LEN)); + + prIeP2P = (P_IE_P2P_T) ((ULONG) prIeP2P + + (ELEM_HDR_LEN + + (VENDOR_OUI_TYPE_LEN + P2P_MAXIMUM_ATTRIBUTE_LEN))); + + kalMemCopy(aucTempBuffer, pucBuffer, u4OverallAttriLen); + + prIeP2P->ucId = ELEM_ID_P2P; + + prIeP2P->aucOui[0] = aucWfaOui[0]; + prIeP2P->aucOui[1] = aucWfaOui[1]; + prIeP2P->aucOui[2] = aucWfaOui[2]; + prIeP2P->ucOuiType = VENDOR_OUI_TYPE_P2P; + + kalMemCopy(prIeP2P->aucP2PAttributes, aucTempBuffer, u4OverallAttriLen); + (*pu2Offset) += P2P_IE_OUI_HDR; + } + + } + + } + + prIeP2P->ucLength = (UINT_8) (VENDOR_OUI_TYPE_LEN + u4OverallAttriLen); + + } while (FALSE); + +} /* p2pFuncGenerateP2P_IE */ + +UINT_32 +p2pFuncAppendAttriStatusForAssocRsp(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize) +{ + PUINT_8 pucBuffer; + P_P2P_ATTRI_STATUS_T prAttriStatus; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; + UINT_32 u4AttriLen = 0; + + ASSERT(prAdapter); + ASSERT(pucBuf); + + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + if (fgIsAssocFrame) + return u4AttriLen; + /* TODO: For assoc request P2P IE check in driver & return status in P2P IE. */ + + pucBuffer = (PUINT_8) ((ULONG) pucBuf + (UINT_32) (*pu2Offset)); + + ASSERT(pucBuffer); + prAttriStatus = (P_P2P_ATTRI_STATUS_T) pucBuffer; + + ASSERT(u2BufSize >= ((*pu2Offset) + (UINT_16) u4AttriLen)); + + prAttriStatus->ucId = P2P_ATTRI_ID_STATUS; + WLAN_SET_FIELD_16(&prAttriStatus->u2Length, P2P_ATTRI_MAX_LEN_STATUS); + + prAttriStatus->ucStatusCode = P2P_STATUS_FAIL_PREVIOUS_PROTOCOL_ERR; + + u4AttriLen = (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_STATUS); + + (*pu2Offset) += (UINT_16) u4AttriLen; + + return u4AttriLen; +} /* p2pFuncAppendAttriStatusForAssocRsp */ + +UINT_32 +p2pFuncAppendAttriExtListenTiming(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize) +{ + UINT_32 u4AttriLen = 0; + P_P2P_ATTRI_EXT_LISTEN_TIMING_T prP2pExtListenTiming = (P_P2P_ATTRI_EXT_LISTEN_TIMING_T) NULL; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + PUINT_8 pucBuffer = NULL; + + ASSERT(prAdapter); + ASSERT(pucBuf); + + if (fgIsAssocFrame) + return u4AttriLen; + /* TODO: For extend listen timing. */ + + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + u4AttriLen = (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_EXT_LISTEN_TIMING); + + ASSERT(u2BufSize >= ((*pu2Offset) + (UINT_16) u4AttriLen)); + + pucBuffer = (PUINT_8) ((ULONG) pucBuf + (UINT_32) (*pu2Offset)); + + ASSERT(pucBuffer); + + prP2pExtListenTiming = (P_P2P_ATTRI_EXT_LISTEN_TIMING_T) pucBuffer; + + prP2pExtListenTiming->ucId = P2P_ATTRI_ID_EXT_LISTEN_TIMING; + WLAN_SET_FIELD_16(&prP2pExtListenTiming->u2Length, P2P_ATTRI_MAX_LEN_EXT_LISTEN_TIMING); + WLAN_SET_FIELD_16(&prP2pExtListenTiming->u2AvailInterval, prP2pSpecificBssInfo->u2AvailabilityInterval); + WLAN_SET_FIELD_16(&prP2pExtListenTiming->u2AvailPeriod, prP2pSpecificBssInfo->u2AvailabilityPeriod); + + (*pu2Offset) += (UINT_16) u4AttriLen; + + return u4AttriLen; +} /* p2pFuncAppendAttriExtListenTiming */ + +P_IE_HDR_T +p2pFuncGetSpecIE(IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucIEBuf, IN UINT_16 u2BufferLen, IN UINT_8 ucElemID, IN PBOOLEAN pfgIsMore) +{ + P_IE_HDR_T prTargetIE = (P_IE_HDR_T) NULL; + PUINT_8 pucIE = (PUINT_8) NULL; + UINT_16 u2Offset = 0; + + if (pfgIsMore) + *pfgIsMore = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (pucIEBuf != NULL)); + + pucIE = pucIEBuf; + + IE_FOR_EACH(pucIE, u2BufferLen, u2Offset) { + if (IE_ID(pucIE) == ucElemID) { + if ((prTargetIE) && (pfgIsMore)) { + + *pfgIsMore = TRUE; + break; + } + prTargetIE = (P_IE_HDR_T) pucIE; + + if (pfgIsMore == NULL) + break; + + } + } + + } while (FALSE); + + return prTargetIE; +} /* p2pFuncGetSpecIE */ + +P_ATTRIBUTE_HDR_T +p2pFuncGetSpecAttri(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucOuiType, IN PUINT_8 pucIEBuf, IN UINT_16 u2BufferLen, IN UINT_16 u2AttriID) +{ + P_IE_P2P_T prP2pIE = (P_IE_P2P_T) NULL; + P_ATTRIBUTE_HDR_T prTargetAttri = (P_ATTRIBUTE_HDR_T) NULL; + BOOLEAN fgIsMore = FALSE; + PUINT_8 pucIE = (PUINT_8) NULL, pucAttri = (PUINT_8) NULL; + UINT_16 u2OffsetAttri = 0; + UINT_16 u2BufferLenLeft = 0; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + + DBGLOG(P2P, INFO, "Check AssocReq Oui type %u attri %u for len %u\n", ucOuiType, u2AttriID, u2BufferLen); + + ASSERT(prAdapter); + ASSERT(pucIEBuf); + + u2BufferLenLeft = u2BufferLen; + pucIE = pucIEBuf; + do { + fgIsMore = FALSE; + prP2pIE = (P_IE_P2P_T) p2pFuncGetSpecIE(prAdapter, + pucIE, u2BufferLenLeft, ELEM_ID_VENDOR, &fgIsMore); + if (prP2pIE == NULL) + continue; + + ASSERT((ULONG) prP2pIE >= (ULONG) pucIE); + + u2BufferLenLeft = u2BufferLen - (UINT_16) (((ULONG) prP2pIE) - ((ULONG) pucIEBuf)); + + DBGLOG(P2P, INFO, "Find vendor id %u len %u oui %u more %u LeftLen %u\n", + IE_ID(prP2pIE), IE_LEN(prP2pIE), prP2pIE->ucOuiType, fgIsMore, + u2BufferLenLeft); + + if ((IE_LEN(prP2pIE) > P2P_OUI_TYPE_LEN) && (prP2pIE->ucOuiType == ucOuiType)) { + switch (ucOuiType) { + case VENDOR_OUI_TYPE_WPS: + aucWfaOui[0] = 0x00; + aucWfaOui[1] = 0x50; + aucWfaOui[2] = 0xF2; + break; + case VENDOR_OUI_TYPE_P2P: + break; + case VENDOR_OUI_TYPE_WPA: + case VENDOR_OUI_TYPE_WMM: + case VENDOR_OUI_TYPE_WFD: + default: + break; + } + + if ((prP2pIE->aucOui[0] != aucWfaOui[0]) + || (prP2pIE->aucOui[1] != aucWfaOui[1]) + || (prP2pIE->aucOui[2] != aucWfaOui[2])) + continue; + + u2OffsetAttri = 0; + pucAttri = prP2pIE->aucP2PAttributes; + + if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + WSC_ATTRI_FOR_EACH(pucAttri, + (IE_LEN(prP2pIE) - P2P_OUI_TYPE_LEN), u2OffsetAttri) { + /* + * LOG_FUNC("WSC: attri id=%u len=%u\n", + * WSC_ATTRI_ID(pucAttri), + * WSC_ATTRI_LEN(pucAttri)); + */ + if (WSC_ATTRI_ID(pucAttri) == u2AttriID) { + prTargetAttri = + (P_ATTRIBUTE_HDR_T) pucAttri; + break; + } + } + + } else if (ucOuiType == VENDOR_OUI_TYPE_P2P) { + P2P_ATTRI_FOR_EACH(pucAttri, + (IE_LEN(prP2pIE) - P2P_OUI_TYPE_LEN), u2OffsetAttri) { + /* + * LOG_FUNC("P2P: attri id=%u len=%u\n", + * ATTRI_ID(pucAttri), ATTRI_LEN(pucAttri)); + */ + if (ATTRI_ID(pucAttri) == (UINT_8) u2AttriID) { + prTargetAttri = (P_ATTRIBUTE_HDR_T) pucAttri; + break; + } + } + } +#if CFG_SUPPORT_WFD + else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { + WFD_ATTRI_FOR_EACH(pucAttri, + (IE_LEN(prP2pIE) - P2P_OUI_TYPE_LEN), u2OffsetAttri) { + /* + * DBGLOG(P2P, INFO, ("WFD: attri id=%u + * len=%u\n",WFD_ATTRI_ID(pucAttri), + * WFD_ATTRI_LEN(pucAttri))); + */ + if (ATTRI_ID(pucAttri) == (UINT_8) u2AttriID) { + prTargetAttri = + (P_ATTRIBUTE_HDR_T) pucAttri; + break; + } + } + } +#endif + /* Do nothing */ + /* Possible or else. */ + } /* ucOuiType */ + /* P2P_OUI_TYPE_LEN */ + pucIE = (PUINT_8) (((ULONG) prP2pIE) + IE_SIZE(prP2pIE)); + /* prP2pIE */ + } while (prP2pIE && fgIsMore && u2BufferLenLeft); + + return prTargetAttri; +} + +/* p2pFuncGetSpecAttri */ + +WLAN_STATUS +p2pFuncGenerateBeaconProbeRsp(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, IN P_MSDU_INFO_T prMsduInfo, IN BOOLEAN fgIsProbeRsp) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_WLAN_BEACON_FRAME_T prBcnFrame = (P_WLAN_BEACON_FRAME_T) NULL; + /* P_APPEND_VAR_IE_ENTRY_T prAppendIeTable = (P_APPEND_VAR_IE_ENTRY_T)NULL; */ + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prBssInfo != NULL) && (prMsduInfo != NULL)); + + /* txBcnIETable */ + + /* txProbeRspIETable */ + + prBcnFrame = (P_WLAN_BEACON_FRAME_T) prMsduInfo->prPacket; + + return nicUpdateBeaconIETemplate(prAdapter, + IE_UPD_METHOD_UPDATE_ALL, + NETWORK_TYPE_P2P_INDEX, + prBssInfo->u2CapInfo, + (PUINT_8) prBcnFrame->aucInfoElem, + prMsduInfo->u2FrameLength - OFFSET_OF(WLAN_BEACON_FRAME_T, + aucInfoElem)); + + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncGenerateBeaconProbeRsp */ + +WLAN_STATUS +p2pFuncComposeBeaconProbeRspTemplate(IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBcnBuffer, + IN UINT_32 u4BcnBufLen, + IN BOOLEAN fgIsProbeRsp, + IN P_P2P_PROBE_RSP_UPDATE_INFO_T prP2pProbeRspInfo, IN BOOLEAN fgSynToFW) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_MSDU_INFO_T prMsduInfo = (P_MSDU_INFO_T) NULL; + P_WLAN_MAC_HEADER_T prWlanBcnFrame = (P_WLAN_MAC_HEADER_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + PUINT_8 pucBuffer = (PUINT_8) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBcnBuffer != NULL)); + + prWlanBcnFrame = (P_WLAN_MAC_HEADER_T) pucBcnBuffer; + + if ((prWlanBcnFrame->u2FrameCtrl != MAC_FRAME_BEACON) && (!fgIsProbeRsp)) { + rWlanStatus = WLAN_STATUS_INVALID_DATA; + break; + } + + else if (prWlanBcnFrame->u2FrameCtrl != MAC_FRAME_PROBE_RSP) { + rWlanStatus = WLAN_STATUS_INVALID_DATA; + break; + } + + if (fgIsProbeRsp) { + ASSERT_BREAK(prP2pProbeRspInfo != NULL); + + if (prP2pProbeRspInfo->prProbeRspMsduTemplate) + cnmMgtPktFree(prAdapter, prP2pProbeRspInfo->prProbeRspMsduTemplate); + + prP2pProbeRspInfo->prProbeRspMsduTemplate = cnmMgtPktAlloc(prAdapter, u4BcnBufLen); + + if (prP2pProbeRspInfo->prProbeRspMsduTemplate == NULL) { + rWlanStatus = WLAN_STATUS_FAILURE; + break; + } + + prMsduInfo = prP2pProbeRspInfo->prProbeRspMsduTemplate; + + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucStaRecIndex = 0xFF; + prMsduInfo->ucNetworkType = NETWORK_TYPE_P2P_INDEX; + + } else { + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prMsduInfo = prP2pBssInfo->prBeacon; + + if (prMsduInfo == NULL) { + rWlanStatus = WLAN_STATUS_FAILURE; + break; + } + + if (u4BcnBufLen > (OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem[0]) + MAX_IE_LENGTH)) { + /* Unexpected error, buffer overflow. */ + ASSERT(FALSE); + break; + } + + } + + pucBuffer = (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + kalMemCopy(pucBuffer, pucBcnBuffer, u4BcnBufLen); + + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = (UINT_16) u4BcnBufLen; + + if (fgSynToFW && prP2pBssInfo) + rWlanStatus = p2pFuncGenerateBeaconProbeRsp(prAdapter, prP2pBssInfo, prMsduInfo, fgIsProbeRsp); + + } while (FALSE); + + return rWlanStatus; + +} /* p2pFuncComposeBeaconTemplate */ + +#if CFG_SUPPORT_WFD +WLAN_STATUS wfdAdjustResource(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnable) +{ +#if 1 + /* The API shall be called in tx_thread */ + P_QUE_MGT_T prQM = &prAdapter->rQM; + + DBGLOG(P2P, INFO, "wfdAdjustResource %d\n", fgEnable); + if (fgEnable) { + prQM->au4MinReservedTcResource[TC2_INDEX] = QM_GUARANTEED_TC2_RESOURCE; + if (QM_GUARANTEED_TC0_RESOURCE > 2) { + prQM->au4GuaranteedTcResource[TC0_INDEX] = QM_GUARANTEED_TC0_RESOURCE - 2; + prQM->au4GuaranteedTcResource[TC2_INDEX] += 2; + } + if (QM_GUARANTEED_TC1_RESOURCE > 2) { + prQM->au4GuaranteedTcResource[TC1_INDEX] = QM_GUARANTEED_TC1_RESOURCE - 2; + prQM->au4GuaranteedTcResource[TC2_INDEX] += 2; + } + } else { + prQM->au4MinReservedTcResource[TC2_INDEX] = QM_MIN_RESERVED_TC2_RESOURCE; + prQM->au4GuaranteedTcResource[TC0_INDEX] = QM_GUARANTEED_TC0_RESOURCE; + prQM->au4GuaranteedTcResource[TC1_INDEX] = QM_GUARANTEED_TC1_RESOURCE; + prQM->au4GuaranteedTcResource[TC2_INDEX] = QM_GUARANTEED_TC2_RESOURCE; + } +#endif + return WLAN_STATUS_SUCCESS; +} +#define CFG_SUPPORT_WFD_ADJUST_THREAD 0 +WLAN_STATUS wfdAdjustThread(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnable) +{ +#if CFG_SUPPORT_WFD_ADJUST_THREAD +#define WFD_TX_THREAD_PRIORITY 70 + DBGLOG(P2P, INFO, "wfdAdjustResource %d\n", fgEnable); + if (prAdapter->prGlueInfo->main_thread != NULL) { + if (fgEnable) { +#ifdef LINUX + /* TODO the change schedule API shall be provided by OS glue layer */ + /* Or the API shall be put in os glue layer */ + struct sched_param param = {.sched_priority = WFD_TX_THREAD_PRIORITY }; + + sched_setscheduler(prAdapter->prGlueInfo->main_thread, SCHED_RR, ¶m); +#endif + } else { +#ifdef LINUX + /* TODO the change schedule API shall be provided by OS glue layer */ + struct sched_param param = {.sched_priority = 0 }; + + sched_setscheduler(prAdapter->prGlueInfo->main_thread, SCHED_NORMAL, ¶m); +#endif + } + } else { + + DBGLOG(P2P, WARN, "main_thread is null, please check if the wlanRemove is called in advance\n"); + } +#endif + return WLAN_STATUS_SUCCESS; +} + +#endif /* CFG_SUPPORT_WFD */ + +WLAN_STATUS wfdChangeMediaState(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx, ENUM_PARAM_MEDIA_STATE_T eConnectionState) +{ +#if CFG_SUPPORT_WFD + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + + if (prAdapter->fgIsP2PRegistered == FALSE) + return WLAN_STATUS_SUCCESS; + prWfdCfgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings; + + if ((prWfdCfgSettings->ucWfdEnable) && ((prWfdCfgSettings->u4WfdFlag & WFD_FLAGS_DEV_INFO_VALID))) { + + if (prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].eConnectionState == + PARAM_MEDIA_STATE_CONNECTED) { + wfdAdjustResource(prAdapter, TRUE); + wfdAdjustThread(prAdapter, TRUE); + } else { + wfdAdjustResource(prAdapter, FALSE); + wfdAdjustThread(prAdapter, FALSE); + } + + } +#endif + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Used to check the probe response should be dropped. +* +* @param[in] prAdapter Pointer of ADAPTER_T +* @param[in] prMgmtTxMsdu Pointer to the MSDU_INFO_T. +* +* @retval TRUE The probe response will be sent. +* @retval FALSE The probe response will be dropped. +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2pFuncValidateProbeResp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMgmtTxMsdu) +{ + P_WLAN_PROBE_RSP_FRAME_T prProbRspHdr = (P_WLAN_PROBE_RSP_FRAME_T)NULL; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + P_BSS_INFO_T prBssInfo; + UINT_16 u2CapInfo = 0; + BOOLEAN fgValidToSend = TRUE; + + do { + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + prProbRspHdr = (P_WLAN_PROBE_RSP_FRAME_T) ((ULONG) prMgmtTxMsdu->prPacket + MAC_TX_RESERVED_FIELD); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + u2CapInfo = prProbRspHdr->u2CapInfo; + + DBGLOG(P2P, INFO, "p2pFuncValidateProbeResp ESS/IBSS: %s: , current: %d, previous: %d, opMode: %d\n", + (u2CapInfo & CAP_INFO_BSS_TYPE) ? "true" : "false", + prP2pFsmInfo->eCurrentState, + prP2pFsmInfo->ePreviousState, + prBssInfo->eCurrentOPMode); + + /* always TX probe response from ESS/IBSS */ + if (u2CapInfo & CAP_INFO_BSS_TYPE) + break; + + switch (prP2pFsmInfo->eCurrentState) { + case P2P_STATE_IDLE: /* Cancel remain-on-channel case */ + case P2P_STATE_REQING_CHANNEL: /* Re-enter ChReq case */ + if (prP2pFsmInfo->ePreviousState == P2P_STATE_CHNL_ON_HAND && + prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + fgValidToSend = FALSE; + } + break; + default: + break; + } + } while (FALSE); + return fgValidToSend; +} +#if CFG_SUPPORT_P2P_EAP_FAIL_WORKAROUND +VOID p2pFuncEAPfailureWorkaround(IN P_ADAPTER_T prAdapter, + IN UINT_8 *pucEvtBuf) { + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_EVENT_TX_DONE_STATUS_T prTxDone = (P_EVENT_TX_DONE_STATUS_T) NULL; + PUINT_8 pucPkt = NULL; + UINT_16 u2EtherType = 0; + UINT_8 ucReasonCode = 0; + UINT_8 ucPktId = 0; + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + prTxDone = (EVENT_TX_DONE_STATUS_T *) pucEvtBuf; + + pucPkt = &prTxDone->aucPktBuf[64]; + u2EtherType = kalGetPktEtherType(pucPkt); + ucReasonCode = pucPkt[ETH_HLEN+4]; + ucPktId = pucPkt[ETH_HLEN+5]; + + /*fix p2p connetion issue, P2P GO driver needs delay the deauth frame + * following the EAP-Fail packet to avoid race condition (from management + * frame and data frame ) + */ + if ((prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) && (u2EtherType == ENUM_PKT_1X || + u2EtherType == ENUM_PKT_PROTECTED_1X) && ucReasonCode == 4) { + if (prTxDone->ucStatus == WLAN_STATUS_SUCCESS) { + + prP2pBssInfo->fgP2PPendingDeauth = TRUE; + prP2pBssInfo->u4P2PEapTxDoneTime = kalGetTimeTick(); /*ms*/ + DBGLOG(RX, WARN, "P2P GO fgP2PPendingDeauth = %d\n", prP2pBssInfo->fgP2PPendingDeauth); + } + } + +} +#endif + +BOOLEAN p2pFuncRetryGcDeauth(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_STA_RECORD_T prStaRec, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_P2P_GC_DISCONNECTION_REQ_INFO_T prGcDisConnReqInfo; + + do { + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prGcDisConnReqInfo = &(prP2pFsmInfo->rGcDisConnReqInfo); + + ASSERT_BREAK((prP2pBssInfo != NULL) && (prGcDisConnReqInfo != NULL)); + + if (!prGcDisConnReqInfo->prTargetStaRec || + !EQUAL_MAC_ADDR(prGcDisConnReqInfo->prTargetStaRec->aucMacAddr, prStaRec->aucMacAddr)) + break; + if (prP2pBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + break; + /* retry deauth frame only if MPDU error */ + if (rTxDoneStatus != TX_RESULT_MPDU_ERROR) + break; + if (++prGcDisConnReqInfo->u4RetryCount > MAX_GC_DEAUTH_RETRY_COUNT) + break; + + DBGLOG(P2P, INFO, "Retry sending deauth frame to %pM, retryCount: %d\n", + prGcDisConnReqInfo->prTargetStaRec->aucMacAddr, + prGcDisConnReqInfo->u4RetryCount); + p2pFuncDisconnect(prAdapter, + prGcDisConnReqInfo->prTargetStaRec, + prGcDisConnReqInfo->fgSendDeauth, + prGcDisConnReqInfo->u2ReasonCode); + /* restart timer */ + if (prGcDisConnReqInfo->fgSendDeauth) { + DBGLOG(P2P, INFO, "re-start GC deauth timer for %pM\n", prStaRec->aucMacAddr); + cnmTimerStopTimer(prAdapter, &(prStaRec->rDeauthTxDoneTimer)); + cnmTimerInitTimer(prAdapter, &(prStaRec->rDeauthTxDoneTimer), + (PFN_MGMT_TIMEOUT_FUNC) p2pFsmRunEventDeauthTimeout, (ULONG) prStaRec); + cnmTimerStartTimer(prAdapter, &(prStaRec->rDeauthTxDoneTimer), + P2P_DEAUTH_TIMEOUT_TIME_MS); + } + return TRUE; + } while (FALSE); + return FALSE; +} + +VOID p2pFuncClearGcDeauthRetry(IN P_ADAPTER_T prAdapter) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_P2P_GC_DISCONNECTION_REQ_INFO_T prGcDisConnReqInfo; + + do { + ASSERT_BREAK(prAdapter != NULL); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + prGcDisConnReqInfo = &(prP2pFsmInfo->rGcDisConnReqInfo); + + ASSERT_BREAK(prP2pFsmInfo != NULL); + + if (!prGcDisConnReqInfo) + break; + + prGcDisConnReqInfo->prTargetStaRec = NULL; + prGcDisConnReqInfo->u4RetryCount = 0; + prGcDisConnReqInfo->u2ReasonCode = 0; + prGcDisConnReqInfo->fgSendDeauth = FALSE; + } while (FALSE); +} + +VOID p2pFuncDeauthComplete(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo) +{ + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); + + DBGLOG(P2P, INFO, "p2pFuncDeauthComplete\n"); + + /* 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); + + p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + + DBGLOG(P2P, TRACE, "Force DeactivateNetwork"); + UNSET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); + nicDeactivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); + + /* Release CNM channel */ + nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); + } while (FALSE); +} + +void p2pFunCleanQueuedMgmtFrame(IN P_ADAPTER_T prAdapter, + IN struct P2P_QUEUED_ACTION_FRAME *prFrame) +{ + if (prAdapter == NULL || prFrame == NULL || prFrame->u2Length == 0 || + prFrame->prHeader == NULL) + return; + + DBGLOG(P2P, INFO, "Clean queued p2p action frame.\n"); + + prFrame->u4Freq = 0; + prFrame->u2Length = 0; + cnmMemFree(prAdapter, prFrame->prHeader); + prFrame->prHeader = NULL; +} + +uint8_t p2pFunGetSecCh(IN P_ADAPTER_T prAdapter, + IN ENUM_BAND_T eBand, + IN ENUM_CHNL_EXT_T eSCO, + IN uint8_t ucPrimaryCh) +{ + uint8_t ucSecondCh; + + if (eSCO == CHNL_EXT_SCN) + return 0; + + if (eSCO == CHNL_EXT_SCA) + ucSecondCh = ucPrimaryCh + CHNL_SPAN_20; + else + ucSecondCh = ucPrimaryCh - CHNL_SPAN_20; + + if (!rlmDomainIsLegalChannel(prAdapter, eBand, ucSecondCh)) + ucSecondCh = 0; + + return ucSecondCh; +} + +ENUM_CHNL_EXT_T p2pFunGetSco(IN P_ADAPTER_T prAdapter, + ENUM_BAND_T eBand, uint8_t ucPrimaryCh) { + ENUM_CHNL_EXT_T eSCO = CHNL_EXT_SCN; + + if (eBand == BAND_2G4) { + if (ucPrimaryCh != 14) + eSCO = (ucPrimaryCh > 7) ? CHNL_EXT_SCB : CHNL_EXT_SCA; + } else { + P_DOMAIN_INFO_ENTRY prDomainInfo = rlmDomainGetDomainInfo( + prAdapter); + P_DOMAIN_SUBBAND_INFO prSubband; + uint8_t i, j; + + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubband = &prDomainInfo->rSubBand[i]; + if (prSubband->ucBand != eBand) + continue; + for (j = 0; j < prSubband->ucNumChannels; j++) { + if ((prSubband->ucFirstChannelNum + + j * prSubband->ucChannelSpan) == + ucPrimaryCh) { + eSCO = (j & 1) ? + CHNL_EXT_SCB : + CHNL_EXT_SCA; + break; + } + } + + if (j < prSubband->ucNumChannels) + break; /* Found */ + } + } + + return eSCO; +} + +void p2pFunIndicateAcsResult(IN P_GLUE_INFO_T prGlueInfo, + IN struct P2P_ACS_REQ_INFO *prAcsReqInfo) +{ + if (prAcsReqInfo->ucPrimaryCh == 0) { + if (prAcsReqInfo->eHwMode == P2P_VENDOR_ACS_HW_MODE_11B || + prAcsReqInfo->eHwMode == + P2P_VENDOR_ACS_HW_MODE_11G) { + prAcsReqInfo->ucPrimaryCh = AP_DEFAULT_CHANNEL_2G; + } else { + prAcsReqInfo->ucPrimaryCh = AP_DEFAULT_CHANNEL_5G; + } + DBGLOG(P2P, WARN, "No chosed channel, use default channel %d\n", + prAcsReqInfo->ucPrimaryCh); + } + + if (prAcsReqInfo->eChnlBw > MAX_BW_20MHZ) { + ENUM_BAND_T eBand; + ENUM_CHNL_EXT_T eSCO; + + eBand = prAcsReqInfo->ucPrimaryCh <= 14 ? BAND_2G4 : BAND_5G; + eSCO = p2pFunGetSco(prGlueInfo->prAdapter, + eBand, + prAcsReqInfo->ucPrimaryCh); + + prAcsReqInfo->ucSecondCh = p2pFunGetSecCh( + prGlueInfo->prAdapter, + eBand, + eSCO, + prAcsReqInfo->ucPrimaryCh); + } + + prAcsReqInfo->ucCenterFreqS1 = 0; + prAcsReqInfo->ucCenterFreqS2 = 0; + + prAcsReqInfo->fgIsProcessing = FALSE; + kalP2pIndicateAcsResult(prGlueInfo, + prAcsReqInfo->ucPrimaryCh, + prAcsReqInfo->ucSecondCh, + prAcsReqInfo->ucCenterFreqS1, + prAcsReqInfo->ucCenterFreqS2, + prAcsReqInfo->eChnlBw); +} + +uint8_t p2pFunGetAcsBestCh(IN P_ADAPTER_T prAdapter, + IN ENUM_BAND_T eBand, + IN enum ENUM_MAX_BANDWIDTH_SETTING eChnlBw, + IN uint32_t u4LteSafeChnMask_2G, + IN uint32_t u4LteSafeChnMask_5G_1, + IN uint32_t u4LteSafeChnMask_5G_2) +{ + RF_CHANNEL_INFO_T aucChannelList[MAX_CHN_NUM]; + uint8_t ucNumOfChannel; + P_PARAM_GET_CHN_INFO prGetChnLoad; + uint8_t i; + PARAM_PREFER_CHN_INFO rPreferChannel = { 0, 0xFFFF, 0 }; + + rlmDomainGetChnlList(prAdapter, eBand, TRUE, MAX_CHN_NUM, + &ucNumOfChannel, aucChannelList); + + /* + * 2. Calculate each channel's dirty score + */ + prGetChnLoad = &(prAdapter->rWifiVar.rChnLoadInfo); + + DBGLOG(P2P, INFO, "2g mask=0x%08x\n", u4LteSafeChnMask_2G); + DBGLOG(P2P, INFO, "5g_1 mask=0x%08x\n", u4LteSafeChnMask_5G_1); + DBGLOG(P2P, INFO, "5g_2 mask=0x%08x\n", u4LteSafeChnMask_5G_2); + + for (i = 0; i < ucNumOfChannel; i++) { + uint8_t ucIdx; + P_PARAM_CHN_LOAD_INFO prEachChnLoad; + + ucIdx = wlanGetChannelIndex(aucChannelList[i].ucChannelNum); + prEachChnLoad = &prGetChnLoad->rEachChnLoad[ucIdx]; + + DBGLOG(P2P, INFO, "idx: %u, ch: %u, s: %d\n", + ucIdx, + aucChannelList[i].ucChannelNum, + prEachChnLoad->u2APNumScore); + + if (aucChannelList[i].ucChannelNum <= 14) { + if (!(u4LteSafeChnMask_2G & BIT( + aucChannelList[i].ucChannelNum))) + continue; + } else if ((aucChannelList[i].ucChannelNum >= 36) && + (aucChannelList[i].ucChannelNum <= 144)) { + if (!(u4LteSafeChnMask_5G_1 & BIT( + (aucChannelList[i].ucChannelNum - 36) / 4))) + continue; + } else if ((aucChannelList[i].ucChannelNum >= 149) && + (aucChannelList[i].ucChannelNum <= 181)) { + if (!(u4LteSafeChnMask_5G_2 & BIT( + (aucChannelList[i].ucChannelNum - 149) / 4))) + continue; + } + + if (rPreferChannel.u2APNumScore > prEachChnLoad->u2APNumScore) { + rPreferChannel.u2APNumScore = + prEachChnLoad->u2APNumScore; + rPreferChannel.ucChannel = + prEachChnLoad->ucChannel; + } + } + + return rPreferChannel.ucChannel; +} + +void p2pFunProcessAcsReport(IN P_ADAPTER_T prAdapter, + IN P_PARAM_GET_CHN_INFO prLteSafeChnInfo, + IN struct P2P_ACS_REQ_INFO *prAcsReqInfo) +{ + ENUM_BAND_T eBand; + uint32_t u4LteSafeChnMask_2G = -1; + + if (!prAdapter || !prAcsReqInfo) + return; + + if (prAcsReqInfo->eHwMode == P2P_VENDOR_ACS_HW_MODE_11B || + prAcsReqInfo->eHwMode == P2P_VENDOR_ACS_HW_MODE_11G) + eBand = BAND_2G4; + else + eBand = BAND_5G; + + if (prLteSafeChnInfo && (eBand == BAND_2G4)) { + P_CMD_LTE_SAFE_CHN_INFO_T prLteSafeChnList; + RF_CHANNEL_INFO_T aucChannelList[MAX_2G_BAND_CHN_NUM]; + uint8_t ucNumOfChannel; + uint8_t i; + u_int8_t fgIsMaskValid = FALSE; + + rlmDomainGetChnlList(prAdapter, eBand, TRUE, + MAX_2G_BAND_CHN_NUM, &ucNumOfChannel, aucChannelList); + + prLteSafeChnList = &prLteSafeChnInfo->rLteSafeChnList; + u4LteSafeChnMask_2G = prLteSafeChnList->au4SafeChannelBitmask[ + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_2G_BASE_1 - 1]; + +#if CFG_TC1_FEATURE + /* Restrict 2.4G band channel selection range + * to 1/6/11 per customer's request + */ + u4LteSafeChnMask_2G &= 0x0842; +#elif CFG_TC10_FEATURE + /* Restrict 2.4G band channel selection range + * to 1~11 per customer's request + */ + u4LteSafeChnMask_2G &= 0x0FFE; +#endif + prAcsReqInfo->u4LteSafeChnMask_2G &= u4LteSafeChnMask_2G; + for (i = 0; i < ucNumOfChannel; i++) { + if ((prAcsReqInfo->u4LteSafeChnMask_2G & BIT( + aucChannelList[i].ucChannelNum))) { + fgIsMaskValid = TRUE; + break; + } + } + if (!fgIsMaskValid) { + DBGLOG(P2P, WARN, + "All mask invalid, mark all as valid\n"); + prAcsReqInfo->u4LteSafeChnMask_2G = BITS(1, 14); + } + } + + prAcsReqInfo->ucPrimaryCh = p2pFunGetAcsBestCh(prAdapter, + eBand, + prAcsReqInfo->eChnlBw, + prAcsReqInfo->u4LteSafeChnMask_2G, + prAcsReqInfo->u4LteSafeChnMask_5G_1, + prAcsReqInfo->u4LteSafeChnMask_5G_2); + + p2pFunIndicateAcsResult(prAdapter->prGlueInfo, + prAcsReqInfo); +} + +void p2pFunCalAcsChnScores(IN P_ADAPTER_T prAdapter, + IN ENUM_BAND_T eBand) +{ + UINT_8 ucNumOfChannel; + RF_CHANNEL_INFO_T aucChannelList[MAX_CHN_NUM]; + P_PARAM_GET_CHN_INFO prGetChnLoad; + UINT_8 i, ucIdx; + + if (!prAdapter) + return; + + prGetChnLoad = &(prAdapter->rWifiVar.rChnLoadInfo); + + if (eBand == BAND_2G4) { + P_LINK_T prBSSDescList = (P_LINK_T) NULL; + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; + UINT_16 u2APNumScore = 0, u2UpThreshold = 0; + UINT_16 u2LowThreshold = 0, ucInnerIdx = 0; + + prBSSDescList = &(prAdapter->rWifiVar.rScanInfo.rBSSDescList); + + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, + BSS_DESC_T) { + /* Record channel loading with channel's AP number */ + UINT_8 ucIdx = 0; + + if (prBssDesc->eBand != eBand) + continue; + ucIdx = wlanGetChannelIndex(prBssDesc->ucChannelNum); + if (ucIdx >= MAX_CHN_NUM) + continue; + prGetChnLoad->rEachChnLoad[ucIdx].u2APNum++; + } + + rlmDomainGetChnlList(prAdapter, + BAND_2G4, + TRUE, + MAX_2G_BAND_CHN_NUM, + &ucNumOfChannel, + aucChannelList); + +#define CHN_DIRTY_WEIGHT_UPPERBOUND 4 + for (i = 0; i < ucNumOfChannel && i < MAX_2G_BAND_CHN_NUM; + i++) { + P_PARAM_CHN_LOAD_INFO prEachChnLoad; + + ucIdx = wlanGetChannelIndex( + aucChannelList[i].ucChannelNum); + + if (ucIdx >= MAX_CHN_NUM) + continue; + + prEachChnLoad = &prGetChnLoad->rEachChnLoad[ucIdx]; + + /* Current channel's dirty score */ + u2APNumScore = prEachChnLoad->u2APNum * + CHN_DIRTY_WEIGHT_UPPERBOUND; + u2LowThreshold = u2UpThreshold = 3; + + if (ucIdx < 3) { + u2LowThreshold = ucIdx; + u2UpThreshold = 3; + } else if (ucIdx >= (ucNumOfChannel - 3)) { + u2LowThreshold = 3; + u2UpThreshold = ucNumOfChannel - (ucIdx + 1); + } + + /* Lower channel's dirty score */ + for (ucInnerIdx = 0; ucInnerIdx < u2LowThreshold; + ucInnerIdx++) { + u2APNumScore += (prGetChnLoad->rEachChnLoad[ucIdx - ucInnerIdx - 1].u2APNum * + (CHN_DIRTY_WEIGHT_UPPERBOUND - 1 - ucInnerIdx)); + } + + /* Upper channel's dirty score */ + for (ucInnerIdx = 0; ucInnerIdx < u2UpThreshold; + ucInnerIdx++) { + u2APNumScore += + (prGetChnLoad->rEachChnLoad[ucIdx + ucInnerIdx + 1].u2APNum * + (CHN_DIRTY_WEIGHT_UPPERBOUND - 1 - ucInnerIdx)); + } + + prEachChnLoad->u2APNumScore = u2APNumScore; + prEachChnLoad->ucChannel = + aucChannelList[i].ucChannelNum; + } + } else { + rlmDomainGetChnlList(prAdapter, + BAND_5G, + TRUE, + MAX_CHN_NUM - MAX_2G_BAND_CHN_NUM, + &ucNumOfChannel, + aucChannelList); + + for (i = 0; i < ucNumOfChannel; i++) { + P_PARAM_CHN_LOAD_INFO prEachChnLoad; + + ucIdx = wlanGetChannelIndex( + aucChannelList[i].ucChannelNum); + + if (ucIdx >= MAX_CHN_NUM) + continue; + + prEachChnLoad = &prGetChnLoad->rEachChnLoad[ucIdx]; + get_random_bytes(&prEachChnLoad->u2APNumScore, + sizeof(UINT_16)); + prEachChnLoad->u2APNumScore %= 100; + prEachChnLoad->ucChannel = + aucChannelList[i].ucChannelNum; + } + } +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_ie.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_ie.c new file mode 100644 index 0000000000000..c33e9fa4f1a9e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_ie.c @@ -0,0 +1,627 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#include "p2p_precomp.h" + +#if CFG_SUPPORT_WFD +#if CFG_SUPPORT_WFD_COMPOSE_IE +#if 0 +APPEND_VAR_ATTRI_ENTRY_T txProbeRspWFDAttributesTable[] = { + {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_DEV_INFO), NULL, wfdFuncAppendAttriDevInfo} /* 0 */ + , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_ASSOC_BSSID), NULL, wfdFuncAppendAttriAssocBssid} /* 1 */ + , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO), NULL, wfdFuncAppendAttriCoupledSinkInfo} /* 6 */ + , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_EXT_CAPABILITY), NULL, wfdFuncAppendAttriExtCapability} /* 7 */ + , {0, wfdFuncCalculateAttriLenSessionInfo, wfdFuncAppendAttriSessionInfo} /* 9 */ +}; + +APPEND_VAR_ATTRI_ENTRY_T txBeaconWFDAttributesTable[] = { + {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_DEV_INFO), NULL, wfdFuncAppendAttriDevInfo} /* 0 */ + , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_ASSOC_BSSID), NULL, wfdFuncAppendAttriAssocBssid} /* 1 */ + , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO), NULL, wfdFuncAppendAttriCoupledSinkInfo} /* 6 */ +}; + +APPEND_VAR_ATTRI_ENTRY_T txAssocReqWFDAttributesTable[] = { + {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_DEV_INFO), NULL, wfdFuncAppendAttriDevInfo} /* 0 */ + , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_ASSOC_BSSID), NULL, wfdFuncAppendAttriAssocBssid} /* 1 */ + , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO), NULL, wfdFuncAppendAttriCoupledSinkInfo} /* 6 */ +}; +#endif + +APPEND_VAR_ATTRI_ENTRY_T txAssocRspWFDAttributesTable[] = { + {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_DEV_INFO), NULL, wfdFuncAppendAttriDevInfo} /* 0 */ + , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_ASSOC_BSSID), NULL, wfdFuncAppendAttriAssocBssid} /* 1 */ + , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO), NULL, wfdFuncAppendAttriCoupledSinkInfo} /* 6 */ + , {0, wfdFuncCalculateAttriLenSessionInfo, wfdFuncAppendAttriSessionInfo} /* 9 */ + +}; + +#endif + +UINT_32 +p2pCalculate_IEForAssocReq(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo = (P_P2P_CONNECTION_REQ_INFO_T) NULL; + UINT_32 u4RetValue = 0; + + do { + ASSERT_BREAK((eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) && (prAdapter != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + prConnReqInfo = &(prP2pFsmInfo->rConnReqInfo); + + u4RetValue = prConnReqInfo->u4BufLength; + + /* ADD HT Capability */ + u4RetValue += (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP); + + /* ADD WMM Information Element */ + u4RetValue += (ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_INFO); + + } while (FALSE); + + return u4RetValue; +} /* p2pCalculate_IEForAssocReq */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to generate P2P IE for Beacon frame. +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pGenerate_IEForAssocReq(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo = (P_P2P_CONNECTION_REQ_INFO_T) NULL; + PUINT_8 pucIEBuf = (PUINT_8) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + prConnReqInfo = &(prP2pFsmInfo->rConnReqInfo); + + pucIEBuf = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + + kalMemCopy(pucIEBuf, prConnReqInfo->aucIEBuf, prConnReqInfo->u4BufLength); + + prMsduInfo->u2FrameLength += prConnReqInfo->u4BufLength; + + rlmReqGenerateHtCapIE(prAdapter, prMsduInfo); + mqmGenerateWmmInfoIE(prAdapter, prMsduInfo); + + } while (FALSE); + + return; + +} /* p2pGenerate_IEForAssocReq */ + +UINT_32 +wfdFuncAppendAttriDevInfo(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize) +{ + UINT_32 u4AttriLen = 0; + PUINT_8 pucBuffer = NULL; + P_WFD_DEVICE_INFORMATION_IE_T prWfdDevInfo = (P_WFD_DEVICE_INFORMATION_IE_T) NULL; + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL) && (pu2Offset != NULL)); + + prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + + ASSERT_BREAK((prWfdCfgSettings != NULL)); + + if ((prWfdCfgSettings->ucWfdEnable == 0) || + ((prWfdCfgSettings->u4WfdFlag & WFD_FLAGS_DEV_INFO_VALID) == 0)) { + break; + } + + pucBuffer = (PUINT_8) ((ULONG) pucBuf + (UINT_32) (*pu2Offset)); + + ASSERT_BREAK(pucBuffer != NULL); + + prWfdDevInfo = (P_WFD_DEVICE_INFORMATION_IE_T) pucBuffer; + + prWfdDevInfo->ucElemID = WFD_ATTRI_ID_DEV_INFO; + + WLAN_SET_FIELD_BE16(&prWfdDevInfo->u2WfdDevInfo, prWfdCfgSettings->u2WfdDevInfo); + + WLAN_SET_FIELD_BE16(&prWfdDevInfo->u2SessionMgmtCtrlPort, prWfdCfgSettings->u2WfdControlPort); + + WLAN_SET_FIELD_BE16(&prWfdDevInfo->u2WfdDevMaxSpeed, prWfdCfgSettings->u2WfdMaximumTp); + + WLAN_SET_FIELD_BE16(&prWfdDevInfo->u2Length, WFD_ATTRI_MAX_LEN_DEV_INFO); + + u4AttriLen = WFD_ATTRI_MAX_LEN_DEV_INFO + WFD_ATTRI_HDR_LEN; + + } while (FALSE); + + (*pu2Offset) += (UINT_16) u4AttriLen; + + return u4AttriLen; +} + +/* wfdFuncAppendAttriDevInfo */ + +UINT_32 +wfdFuncAppendAttriAssocBssid(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize) +{ + UINT_32 u4AttriLen = 0; + PUINT_8 pucBuffer = NULL; + P_WFD_ASSOCIATED_BSSID_IE_T prWfdAssocBssid = (P_WFD_ASSOCIATED_BSSID_IE_T) NULL; + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + P_BSS_INFO_T prAisBssInfo = (P_BSS_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL) && (pu2Offset != NULL)); + + prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + + ASSERT_BREAK((prWfdCfgSettings != NULL)); + + if (prWfdCfgSettings->ucWfdEnable == 0) + break; + + /* AIS network. */ + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + if ((!IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX)) || + (prAisBssInfo->eConnectionState != PARAM_MEDIA_STATE_CONNECTED)) { + break; + } + + pucBuffer = (PUINT_8) ((ULONG) pucBuf + (UINT_32) (*pu2Offset)); + + ASSERT_BREAK(pucBuffer != NULL); + + prWfdAssocBssid = (P_WFD_ASSOCIATED_BSSID_IE_T) pucBuffer; + + prWfdAssocBssid->ucElemID = WFD_ATTRI_ID_ASSOC_BSSID; + + WLAN_SET_FIELD_BE16(&prWfdAssocBssid->u2Length, WFD_ATTRI_MAX_LEN_ASSOC_BSSID); + + COPY_MAC_ADDR(prWfdAssocBssid->aucAssocBssid, prAisBssInfo->aucBSSID); + + u4AttriLen = WFD_ATTRI_MAX_LEN_ASSOC_BSSID + WFD_ATTRI_HDR_LEN; + + } while (FALSE); + + (*pu2Offset) += (UINT_16) u4AttriLen; + + return u4AttriLen; +} + +/* wfdFuncAppendAttriAssocBssid */ + +UINT_32 +wfdFuncAppendAttriCoupledSinkInfo(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize) +{ + UINT_32 u4AttriLen = 0; + PUINT_8 pucBuffer = NULL; + P_WFD_COUPLE_SINK_INFORMATION_IE_T prWfdCoupleSinkInfo = (P_WFD_COUPLE_SINK_INFORMATION_IE_T) NULL; + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL) && (pu2Offset != NULL)); + + prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + + ASSERT_BREAK((prWfdCfgSettings != NULL)); + + if ((prWfdCfgSettings->ucWfdEnable == 0) || + ((prWfdCfgSettings->u4WfdFlag & WFD_FLAGS_SINK_INFO_VALID) == 0)) { + break; + } + + pucBuffer = (PUINT_8) ((ULONG) pucBuf + (UINT_32) (*pu2Offset)); + + ASSERT_BREAK(pucBuffer != NULL); + + prWfdCoupleSinkInfo = (P_WFD_COUPLE_SINK_INFORMATION_IE_T) pucBuffer; + + prWfdCoupleSinkInfo->ucElemID = WFD_ATTRI_ID_COUPLED_SINK_INFO; + + WLAN_SET_FIELD_BE16(&prWfdCoupleSinkInfo->u2Length, WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO); + + COPY_MAC_ADDR(prWfdCoupleSinkInfo->aucCoupleSinkMac, prWfdCfgSettings->aucWfdCoupleSinkAddress); + + prWfdCoupleSinkInfo->ucCoupleSinkStatusBp = prWfdCfgSettings->ucWfdCoupleSinkStatus; + + u4AttriLen = WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO + WFD_ATTRI_HDR_LEN; + + } while (FALSE); + + (*pu2Offset) += (UINT_16) u4AttriLen; + + return u4AttriLen; +} + +/* wfdFuncAppendAttriCoupledSinkInfo */ + +UINT_32 +wfdFuncAppendAttriExtCapability(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize) +{ + UINT_32 u4AttriLen = 0; + PUINT_8 pucBuffer = NULL; + P_WFD_EXTENDED_CAPABILITY_IE_T prWfdExtCapability = (P_WFD_EXTENDED_CAPABILITY_IE_T) NULL; + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL) && (pu2Offset != NULL)); + + prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + + ASSERT_BREAK((prWfdCfgSettings != NULL)); + + if ((prWfdCfgSettings->ucWfdEnable == 0) || + ((prWfdCfgSettings->u4WfdFlag & WFD_FLAGS_EXT_CAPABILITY_VALID) == 0)) { + break; + } + + pucBuffer = (PUINT_8) ((ULONG) pucBuf + (UINT_32) (*pu2Offset)); + + ASSERT_BREAK(pucBuffer != NULL); + + prWfdExtCapability = (P_WFD_EXTENDED_CAPABILITY_IE_T) pucBuffer; + + prWfdExtCapability->ucElemID = WFD_ATTRI_ID_EXT_CAPABILITY; + + WLAN_SET_FIELD_BE16(&prWfdExtCapability->u2Length, WFD_ATTRI_MAX_LEN_EXT_CAPABILITY); + + WLAN_SET_FIELD_BE16(&prWfdExtCapability->u2WfdExtCapabilityBp, prWfdCfgSettings->u2WfdExtendCap); + + u4AttriLen = WFD_ATTRI_MAX_LEN_EXT_CAPABILITY + WFD_ATTRI_HDR_LEN; + + } while (FALSE); + + (*pu2Offset) += (UINT_16) u4AttriLen; + + return u4AttriLen; +} + +/* wfdFuncAppendAttriExtCapability */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to calculate length of Channel List Attribute +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return The length of Attribute added +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 wfdFuncCalculateAttriLenSessionInfo(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + UINT_16 u2AttriLen = 0; + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prStaRec != NULL)); + + prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + + if (prWfdCfgSettings->ucWfdEnable == 0) + break; + + u2AttriLen = prWfdCfgSettings->u2WfdSessionInformationIELen + WFD_ATTRI_HDR_LEN; + + } while (FALSE); + + return (UINT_32) u2AttriLen; + +} /* wfdFuncCalculateAttriLenSessionInfo */ + +UINT_32 +wfdFuncAppendAttriSessionInfo(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize) +{ + UINT_32 u4AttriLen = 0; + PUINT_8 pucBuffer = NULL; + P_WFD_SESSION_INFORMATION_IE_T prWfdSessionInfo = (P_WFD_SESSION_INFORMATION_IE_T) NULL; + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL) && (pu2Offset != NULL)); + + prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + + ASSERT_BREAK((prWfdCfgSettings != NULL)); + + if ((prWfdCfgSettings->ucWfdEnable == 0) || (prWfdCfgSettings->u2WfdSessionInformationIELen == 0)) + break; + + pucBuffer = (PUINT_8) ((ULONG) pucBuf + (UINT_32) (*pu2Offset)); + + ASSERT_BREAK(pucBuffer != NULL); + + prWfdSessionInfo = (P_WFD_SESSION_INFORMATION_IE_T) pucBuffer; + + prWfdSessionInfo->ucElemID = WFD_ATTRI_ID_SESSION_INFO; + + /* TODO: Check endian issue? */ + kalMemCopy(prWfdSessionInfo->pucWfdDevInfoDesc, prWfdCfgSettings->aucWfdSessionInformationIE, + prWfdCfgSettings->u2WfdSessionInformationIELen); + + WLAN_SET_FIELD_16(&prWfdSessionInfo->u2Length, prWfdCfgSettings->u2WfdSessionInformationIELen); + + u4AttriLen = prWfdCfgSettings->u2WfdSessionInformationIELen + WFD_ATTRI_HDR_LEN; + + } while (FALSE); + + (*pu2Offset) += (UINT_16) u4AttriLen; + + return u4AttriLen; +} + +/* wfdFuncAppendAttriSessionInfo */ + +#if CFG_SUPPORT_WFD_COMPOSE_IE +VOID +wfdFuncGenerateWfd_IE(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize, + IN APPEND_VAR_ATTRI_ENTRY_T arAppendAttriTable[], IN UINT_32 u4AttriTableSize) +{ + + PUINT_8 pucBuffer = (PUINT_8) NULL; + P_IE_WFD_T prIeWFD = (P_IE_WFD_T) NULL; + UINT_32 u4OverallAttriLen; + UINT_32 u4AttriLen; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + UINT_8 aucTempBuffer[P2P_MAXIMUM_ATTRIBUTE_LEN]; + UINT_32 i; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL)); + + pucBuffer = (PUINT_8) ((ULONG) pucBuf + (*pu2Offset)); + + ASSERT_BREAK(pucBuffer != NULL); + + /* Check buffer length is still enough. */ + ASSERT_BREAK((u2BufSize - (*pu2Offset)) >= WFD_IE_OUI_HDR); + + prIeWFD = (P_IE_WFD_T) pucBuffer; + + prIeWFD->ucId = ELEM_ID_WFD; + + prIeWFD->aucOui[0] = aucWfaOui[0]; + prIeWFD->aucOui[1] = aucWfaOui[1]; + prIeWFD->aucOui[2] = aucWfaOui[2]; + prIeWFD->ucOuiType = VENDOR_OUI_TYPE_WFD; + + (*pu2Offset) += WFD_IE_OUI_HDR; + + /* Overall length of all Attributes */ + u4OverallAttriLen = 0; + + for (i = 0; i < u4AttriTableSize; i++) { + + if (arAppendAttriTable[i].pfnAppendAttri) { + u4AttriLen = + arAppendAttriTable[i].pfnAppendAttri(prAdapter, fgIsAssocFrame, pu2Offset, pucBuf, + u2BufSize); + + u4OverallAttriLen += u4AttriLen; + + if (u4OverallAttriLen > P2P_MAXIMUM_ATTRIBUTE_LEN) { + u4OverallAttriLen -= P2P_MAXIMUM_ATTRIBUTE_LEN; + + prIeWFD->ucLength = (VENDOR_OUI_TYPE_LEN + P2P_MAXIMUM_ATTRIBUTE_LEN); + + pucBuffer = + (PUINT_8) ((ULONG) prIeWFD + (WFD_IE_OUI_HDR + P2P_MAXIMUM_ATTRIBUTE_LEN)); + + prIeWFD = + (P_IE_WFD_T) ((ULONG) prIeWFD + + (WFD_IE_OUI_HDR + P2P_MAXIMUM_ATTRIBUTE_LEN)); + + kalMemCopy(aucTempBuffer, pucBuffer, u4OverallAttriLen); + + prIeWFD->ucId = ELEM_ID_WFD; + + prIeWFD->aucOui[0] = aucWfaOui[0]; + prIeWFD->aucOui[1] = aucWfaOui[1]; + prIeWFD->aucOui[2] = aucWfaOui[2]; + prIeWFD->ucOuiType = VENDOR_OUI_TYPE_WFD; + + kalMemCopy(prIeWFD->aucWFDAttributes, aucTempBuffer, u4OverallAttriLen); + (*pu2Offset) += WFD_IE_OUI_HDR; + } + + } + + } + + prIeWFD->ucLength = (UINT_8) (VENDOR_OUI_TYPE_LEN + u4OverallAttriLen); + + } while (FALSE); + +} /* wfdFuncGenerateWfd_IE */ + +#endif /* CFG_SUPPORT_WFD_COMPOSE_IE */ + +UINT_32 +wfdFuncCalculateWfdIELenForAssocRsp(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec) +{ + +#if CFG_SUPPORT_WFD_COMPOSE_IE + UINT_16 u2EstimatedExtraIELen = 0; + 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; + + u2EstimatedExtraIELen = prAdapter->prGlueInfo->prP2PInfo->u2WFDIELen; + ASSERT(u2EstimatedExtraIELen <= 400); + + return u2EstimatedExtraIELen; + +#else + return 0; +#endif +} /* wfdFuncCalculateWfdIELenForAssocRsp */ + +VOID wfdFuncGenerateWfdIEForAssocRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + +#if CFG_SUPPORT_WFD_COMPOSE_IE + UINT_16 u2EstimatedExtraIELen = 0; + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + P_STA_RECORD_T prStaRec; + + do { + ASSERT_BREAK((prMsduInfo != NULL) && (prAdapter != NULL)); + + prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (!prStaRec) { + ASSERT(FALSE); + } else if (IS_STA_P2P_TYPE(prStaRec)) { + if (prWfdCfgSettings->ucWfdEnable > 0) { + u2EstimatedExtraIELen = prAdapter->prGlueInfo->prP2PInfo->u2WFDIELen; + if (u2EstimatedExtraIELen > 0) { + ASSERT(u2EstimatedExtraIELen <= 400); + ASSERT(sizeof + (prAdapter->prGlueInfo->prP2PInfo->aucWFDIE) >= + prAdapter->prGlueInfo->prP2PInfo->u2WFDIELen); + kalMemCopy((prMsduInfo->prPacket + + prMsduInfo->u2FrameLength), + prAdapter->prGlueInfo->prP2PInfo->aucWFDIE, + u2EstimatedExtraIELen); + prMsduInfo->u2FrameLength += u2EstimatedExtraIELen; + } + } + } + } while (FALSE); + + return; +#else + + return; +#endif +} /* wfdFuncGenerateWfdIEForAssocRsp */ + +VOID p2pFuncComposeNoaAttribute(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + + P_IE_P2P_T prIeP2P; + P_P2P_ATTRI_NOA_T prNoaAttr = NULL; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = NULL; + P_NOA_DESCRIPTOR_T prNoaDesc = NULL; + + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + UINT_32 u4AttributeLen; + UINT_32 u4NumOfNoaDesc = 0; + UINT_32 i = 0; + /*P2P IE format */ + prIeP2P = (P_IE_P2P_T) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + prIeP2P->ucId = ELEM_ID_P2P; + prIeP2P->aucOui[0] = aucWfaOui[0]; + prIeP2P->aucOui[1] = aucWfaOui[1]; + prIeP2P->aucOui[2] = aucWfaOui[2]; + prIeP2P->ucOuiType = VENDOR_OUI_TYPE_P2P; + + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + /*P2P Attribute--NoA */ + prNoaAttr = (P_P2P_ATTRI_NOA_T) prIeP2P->aucP2PAttributes; + + prNoaAttr->ucId = P2P_ATTRI_ID_NOTICE_OF_ABSENCE; + prNoaAttr->ucIndex = prP2pSpecificBssInfo->ucNoAIndex; + /*OPP*/ if (prP2pSpecificBssInfo->fgEnableOppPS) { + prNoaAttr->ucCTWOppPSParam = P2P_CTW_OPPPS_PARAM_OPPPS_FIELD | + (prP2pSpecificBssInfo->u2CTWindow & P2P_CTW_OPPPS_PARAM_CTWINDOW_MASK); + } else { + prNoaAttr->ucCTWOppPSParam = 0; + } + /*NoA Description */ + DBGLOG(P2P, TRACE, "Compose NoA count=%d.\n", prP2pSpecificBssInfo->ucNoATimingCount); + for (i = 0; i < prP2pSpecificBssInfo->ucNoATimingCount; i++) { + if (prP2pSpecificBssInfo->arNoATiming[i].fgIsInUse) { + + prNoaDesc = (P_NOA_DESCRIPTOR_T)&prNoaAttr->aucNoADesc[i * sizeof(NOA_DESCRIPTOR_T)]; + + prNoaDesc->ucCountType = prP2pSpecificBssInfo->arNoATiming[i].ucCount; + prNoaDesc->u4Duration = prP2pSpecificBssInfo->arNoATiming[i].u4Duration; + prNoaDesc->u4Interval = prP2pSpecificBssInfo->arNoATiming[i].u4Interval; + prNoaDesc->u4StartTime = prP2pSpecificBssInfo->arNoATiming[i].u4StartTime; + + u4NumOfNoaDesc++; + } + } + + /* include "index" + "OppPs Params" + "NOA descriptors" */ + prNoaAttr->u2Length = 2 + u4NumOfNoaDesc * sizeof(NOA_DESCRIPTOR_T); + u4NumOfNoaDesc++; + + /* include "Attribute ID" + "Length" + "index" + "OppPs Params" + "NOA descriptors" */ + u4AttributeLen = P2P_ATTRI_HDR_LEN + prNoaAttr->u2Length; + + prIeP2P->ucLength = VENDOR_OUI_TYPE_LEN + u4AttributeLen; + prMsduInfo->u2FrameLength += (ELEM_HDR_LEN + prIeP2P->ucLength); + +} + +UINT_32 p2pFuncCalculateP2P_IE_NoA(IN P_ADAPTER_T prAdapter, IN UINT_32 ucBssIdx, IN P_STA_RECORD_T prStaRec) +{ + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = NULL; + UINT_8 ucIdx; + UINT_32 u4NumOfNoaDesc = 0; + + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) + return 0; + + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + for (ucIdx = 0; ucIdx < prP2pSpecificBssInfo->ucNoATimingCount; ucIdx++) { + if (prP2pSpecificBssInfo->arNoATiming[ucIdx].fgIsInUse) + u4NumOfNoaDesc++; + } + + /* include "index" + "OppPs Params" + "NOA descriptors" */ + /* include "Attribute ID" + "Length" + "index" + "OppPs Params" + "NOA descriptors" */ + + return P2P_ATTRI_LEN_NOTICE_OF_ABSENCE + (u4NumOfNoaDesc * sizeof(NOA_DESCRIPTOR_T)); +} + +VOID p2pFuncGenerateP2P_IE_NoA(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) { /* Hotspot */ + return; + } + + /* Compose NoA attribute */ + p2pFuncComposeNoaAttribute(prAdapter, + prMsduInfo /*prMsduInfo->ucBssIndex, prIeP2P->aucP2PAttributes, &u4AttributeLen */); + +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_rlm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_rlm.c new file mode 100644 index 0000000000000..cad6603484151 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_rlm.c @@ -0,0 +1,949 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Init AP Bss +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmBssInitForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) +{ + ENUM_BAND_T eBand; + UINT_8 ucChannel; + ENUM_CHNL_EXT_T eSCO; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + + if (prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) + return; + + /* Operation band, channel shall be ready before invoking this function, + * bandwidth may be ready if other network is connected. + */ + prBssInfo->fg40mBwAllowed = FALSE; + prBssInfo->fgAssoc40mBwAllowed = FALSE; + prBssInfo->eBssSCO = CHNL_EXT_SCN; + + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) && + RLM_NET_IS_11N(prBssInfo) && RLM_AP_IS_BW_40_ALLOWED(prAdapter, prBssInfo)) { + /* In this case, the first BSS's SCO is 40MHz and known, so GO 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 + 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, "AP SCO=%d\n", prBssInfo->eBssSCO); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief For probe response (GO, IBSS) and association response +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmRspGenerateObssScanIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + P_BSS_INFO_T prBssInfo; + P_IE_OBSS_SCAN_PARAM_T prObssScanIe; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + ASSERT(IS_NET_ACTIVE(prAdapter, prMsduInfo->ucNetworkType)); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; + ASSERT(prBssInfo); + + if (RLM_NET_IS_11N(prBssInfo) && !RLM_NET_IS_BOW(prBssInfo) && + prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT && + (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) && + prBssInfo->eBand == BAND_2G4 && prBssInfo->eBssSCO != CHNL_EXT_SCN) { + + prObssScanIe = (P_IE_OBSS_SCAN_PARAM_T) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + + /* Add 20/40 BSS coexistence IE */ + prObssScanIe->ucId = ELEM_ID_OBSS_SCAN_PARAMS; + prObssScanIe->ucLength = sizeof(IE_OBSS_SCAN_PARAM_T) - ELEM_HDR_LEN; + + prObssScanIe->u2ScanPassiveDwell = dot11OBSSScanPassiveDwell; + prObssScanIe->u2ScanActiveDwell = dot11OBSSScanActiveDwell; + prObssScanIe->u2TriggerScanInterval = dot11BSSWidthTriggerScanInterval; + prObssScanIe->u2ScanPassiveTotalPerChnl = dot11OBSSScanPassiveTotalPerChannel; + prObssScanIe->u2ScanActiveTotalPerChnl = dot11OBSSScanActiveTotalPerChannel; + prObssScanIe->u2WidthTransDelayFactor = dot11BSSWidthChannelTransitionDelayFactor; + prObssScanIe->u2ScanActivityThres = dot11OBSSScanActivityThreshold; + + ASSERT(IE_SIZE(prObssScanIe) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_OBSS_SCAN)); + + prMsduInfo->u2FrameLength += IE_SIZE(prObssScanIe); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P GO. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rlmUpdateBwByChListForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) +{ + UINT_8 ucLevel; + BOOLEAN fgBwChange; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + + fgBwChange = FALSE; + + if (prBssInfo->eBssSCO == CHNL_EXT_SCN) + return fgBwChange; + + ucLevel = rlmObssChnlLevel(prBssInfo, prBssInfo->eBand, prBssInfo->ucPrimaryChannel, prBssInfo->eBssSCO); + + if (ucLevel == CHNL_LEVEL0) { + /* Forced to 20MHz, so extended channel is SCN and STA width is zero */ + prBssInfo->fgObssActionForcedTo20M = TRUE; + + if (prBssInfo->ucHtOpInfo1 != (UINT_8) CHNL_EXT_SCN) { + prBssInfo->ucHtOpInfo1 = (UINT_8) CHNL_EXT_SCN; + fgBwChange = TRUE; + } + + cnmTimerStartTimer(prAdapter, &prBssInfo->rObssScanTimer, OBSS_20_40M_TIMEOUT * MSEC_PER_SEC); + } + + /* Clear up all channel lists */ + prBssInfo->auc2G_20mReqChnlList[0] = 0; + prBssInfo->auc2G_NonHtChnlList[0] = 0; + prBssInfo->auc2G_PriChnlList[0] = 0; + prBssInfo->auc2G_SecChnlList[0] = 0; + prBssInfo->auc5G_20mReqChnlList[0] = 0; + prBssInfo->auc5G_NonHtChnlList[0] = 0; + prBssInfo->auc5G_PriChnlList[0] = 0; + prBssInfo->auc5G_SecChnlList[0] = 0; + + return fgBwChange; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmProcessPublicAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) +{ + P_ACTION_20_40_COEXIST_FRAME prRxFrame; + P_IE_20_40_COEXIST_T prCoexist; + P_IE_INTOLERANT_CHNL_REPORT_T prChnlReport; + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + PUINT_8 pucIE; + UINT_16 u2IELength, u2Offset; + UINT_8 i, j; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxFrame = (P_ACTION_20_40_COEXIST_FRAME) prSwRfb->pvHeader; + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prRxFrame->ucAction != ACTION_PUBLIC_20_40_COEXIST || + !prStaRec || prStaRec->ucStaState != STA_STATE_3 || + prSwRfb->u2PacketLen < (WLAN_MAC_MGMT_HEADER_LEN + 5) || + HIF_RX_HDR_GET_NETWORK_IDX(prSwRfb->prHifRxHdr) != NETWORK_TYPE_P2P_INDEX) { + return; + } + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; + ASSERT(prBssInfo); + + if (!IS_BSS_ACTIVE(prBssInfo) || + prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT || prBssInfo->eBssSCO == CHNL_EXT_SCN) { + return; + } + + prCoexist = &prRxFrame->rBssCoexist; + if (prCoexist->ucData & (BSS_COEXIST_40M_INTOLERANT | BSS_COEXIST_20M_REQ)) { + ASSERT(prBssInfo->auc2G_20mReqChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_20mReqChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { + if (prBssInfo->auc2G_20mReqChnlList[i] == prBssInfo->ucPrimaryChannel) + break; + } + if ((i > prBssInfo->auc2G_20mReqChnlList[0]) && (i <= CHNL_LIST_SZ_2G)) { + prBssInfo->auc2G_20mReqChnlList[i] = prBssInfo->ucPrimaryChannel; + prBssInfo->auc2G_20mReqChnlList[0]++; + } + } + + /* Process intolerant channel report IE */ + pucIE = (PUINT_8) &prRxFrame->rChnlReport; + u2IELength = prSwRfb->u2PacketLen - (WLAN_MAC_MGMT_HEADER_LEN + 5); + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_20_40_INTOLERANT_CHNL_REPORT: + prChnlReport = (P_IE_INTOLERANT_CHNL_REPORT_T) pucIE; + + if (prChnlReport->ucLength <= 1) + break; + + /* To do: process regulatory class. Now we assume 2.4G band */ + + for (j = 0; j < prChnlReport->ucLength - 1; j++) { + /* Update non-HT channel list */ + ASSERT(prBssInfo->auc2G_NonHtChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_NonHtChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { + if (prBssInfo->auc2G_NonHtChnlList[i] == prChnlReport->aucChannelList[j]) + break; + } + if ((i > prBssInfo->auc2G_NonHtChnlList[0]) && (i <= CHNL_LIST_SZ_2G)) { + prBssInfo->auc2G_NonHtChnlList[i] = prChnlReport->aucChannelList[j]; + prBssInfo->auc2G_NonHtChnlList[0]++; + } + } + break; + + default: + break; + } + } /* end of IE_FOR_EACH */ + + if (rlmUpdateBwByChListForAP(prAdapter, prBssInfo)) { + bssUpdateBeaconContent(prAdapter, prBssInfo->ucNetTypeIndex); + rlmSyncOperationParams(prAdapter, prBssInfo); + } + + /* Check if OBSS scan exemption response should be sent */ + if (prCoexist->ucData & BSS_COEXIST_OBSS_SCAN_EXEMPTION_REQ) + rlmObssScanExemptionRsp(prAdapter, prBssInfo, prSwRfb); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmProcessHtAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) +{ + P_ACTION_NOTIFY_CHNL_WIDTH_FRAME prRxFrame; + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxFrame = (P_ACTION_NOTIFY_CHNL_WIDTH_FRAME) prSwRfb->pvHeader; + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prRxFrame->ucAction != ACTION_HT_NOTIFY_CHANNEL_WIDTH || + !prStaRec || prStaRec->ucStaState != STA_STATE_3 || + prSwRfb->u2PacketLen < sizeof(ACTION_NOTIFY_CHNL_WIDTH_FRAME)) { + return; + } + + /* To do: depending regulation class 13 and 14 based on spec + * Note: (ucChannelWidth==1) shall restored back to original capability, + * not current setting to 40MHz BW here + */ + if (prRxFrame->ucChannelWidth == 0) + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SUP_CHNL_WIDTH; + else if (prRxFrame->ucChannelWidth == 1) + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmHandleObssStatusEventPkt(P_ADAPTER_T prAdapter, P_EVENT_AP_OBSS_STATUS_T prObssStatus) +{ + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(prObssStatus); + ASSERT(prObssStatus->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prObssStatus->ucNetTypeIndex]; + ASSERT(prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT); + + prBssInfo->fgObssErpProtectMode = (BOOLEAN) prObssStatus->ucObssErpProtectMode; + prBssInfo->eObssHtProtectMode = (ENUM_HT_PROTECT_MODE_T) prObssStatus->ucObssHtProtectMode; + prBssInfo->eObssGfOperationMode = (ENUM_GF_MODE_T) prObssStatus->ucObssGfOperationMode; + prBssInfo->fgObssRifsOperationMode = (BOOLEAN) prObssStatus->ucObssRifsOperationMode; + prBssInfo->fgObssBeaconForcedTo20M = (BOOLEAN) prObssStatus->ucObssBeaconForcedTo20M; + + /* Check if Beacon content need to be updated */ + rlmUpdateParamsForAP(prAdapter, prBssInfo, TRUE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief It is only for AP mode in NETWORK_TYPE_P2P_INDEX. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmUpdateParamsForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, BOOLEAN fgUpdateBeacon) +{ + P_LINK_T prStaList; + P_STA_RECORD_T prStaRec; + BOOLEAN fgErpProtectMode, fgSta40mIntolerant; + BOOLEAN fgUseShortPreamble, fgUseShortSlotTime; + ENUM_HT_PROTECT_MODE_T eHtProtectMode; + ENUM_GF_MODE_T eGfOperationMode; + UINT_8 ucHtOpInfo1; +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION + P_GLUE_INFO_T prGlueInfo; +#endif + + ASSERT(prAdapter); + ASSERT(prBssInfo); + + if (!IS_BSS_ACTIVE(prBssInfo) || prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) + return; + + fgErpProtectMode = FALSE; + eHtProtectMode = HT_PROTECT_MODE_NONE; + eGfOperationMode = GF_MODE_NORMAL; + fgSta40mIntolerant = FALSE; + fgUseShortPreamble = prBssInfo->fgIsShortPreambleAllowed; + fgUseShortSlotTime = TRUE; + ucHtOpInfo1 = (UINT_8) CHNL_EXT_SCN; + + prStaList = &prBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH_ENTRY(prStaRec, prStaList, rLinkEntry, STA_RECORD_T) { + /* ASSERT(prStaRec); */ + if (!prStaRec) { + DBGLOG(P2P, TRACE, "prStaRec is NULL in rlmUpdateParamsForAP()\n"); + break; + } + if (prStaRec->fgIsInUse && prStaRec->ucStaState == STA_STATE_3 && + prStaRec->ucNetTypeIndex == prBssInfo->ucNetTypeIndex) { + if (!(prStaRec->ucPhyTypeSet & (PHY_TYPE_SET_802_11GN | PHY_TYPE_SET_802_11A))) { + /* B-only mode, so mode 1 (ERP protection) */ + fgErpProtectMode = TRUE; + } + + if (!(prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) { + /* BG-only or A-only */ + eHtProtectMode = HT_PROTECT_MODE_NON_HT; + } else if (!(prStaRec->u2HtCapInfo & HT_CAP_INFO_SUP_CHNL_WIDTH)) { + /* 20MHz-only */ + /* + * The HT Protection field may be set to 20 MHz protection + * mode only if the following are true: + * \A1X All STAs detected (by any means) in the primary channel + * and all STAs detected (by any means) in the secondary + * channel are HT STAs and all STAs that are members of + * this BSS are HT STAs, and + * \A1X This BSS is a 20/40 MHz BSS, and + * \A1X There is at least one 20 MHz HT STA associated with this BSS. + */ + if (eHtProtectMode == HT_PROTECT_MODE_NONE && prBssInfo->fgAssoc40mBwAllowed) + eHtProtectMode = HT_PROTECT_MODE_20M; + } + + if (!(prStaRec->u2HtCapInfo & HT_CAP_INFO_HT_GF)) + eGfOperationMode = GF_MODE_PROTECT; + + if (!(prStaRec->u2CapInfo & CAP_INFO_SHORT_PREAMBLE)) + fgUseShortPreamble = FALSE; + + if (!(prStaRec->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME)) + fgUseShortSlotTime = FALSE; + + if (prStaRec->u2HtCapInfo & HT_CAP_INFO_40M_INTOLERANT) + fgSta40mIntolerant = TRUE; + } + } /* end of LINK_FOR_EACH_ENTRY */ + + /* Check if HT operation IE about 20/40M bandwidth shall be updated */ + if (prBssInfo->eBssSCO != CHNL_EXT_SCN) { + if (/*!LINK_IS_EMPTY(prStaList) && */ !fgSta40mIntolerant && + !prBssInfo->fgObssActionForcedTo20M && !prBssInfo->fgObssBeaconForcedTo20M) { + + ucHtOpInfo1 = (UINT_8) + (((UINT_32) prBssInfo->eBssSCO) | HT_OP_INFO1_STA_CHNL_WIDTH); + } + } +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION + prGlueInfo = prAdapter->prGlueInfo; + if (prGlueInfo->prP2PInfo->u4PsLevel & BITS(8, 15)) + fgErpProtectMode = TRUE; +#endif + + /* Check if any new parameter may be updated */ + if (prBssInfo->fgErpProtectMode != fgErpProtectMode || + prBssInfo->eHtProtectMode != eHtProtectMode || + prBssInfo->eGfOperationMode != eGfOperationMode || + prBssInfo->ucHtOpInfo1 != ucHtOpInfo1 || + prBssInfo->fgUseShortPreamble != fgUseShortPreamble || + prBssInfo->fgUseShortSlotTime != fgUseShortSlotTime) { + + prBssInfo->fgErpProtectMode = fgErpProtectMode; + prBssInfo->eHtProtectMode = eHtProtectMode; + prBssInfo->eGfOperationMode = eGfOperationMode; + prBssInfo->ucHtOpInfo1 = ucHtOpInfo1; + prBssInfo->fgUseShortPreamble = fgUseShortPreamble; + prBssInfo->fgUseShortSlotTime = fgUseShortSlotTime; + + if (fgUseShortSlotTime) + prBssInfo->u2CapInfo |= CAP_INFO_SHORT_SLOT_TIME; + else + prBssInfo->u2CapInfo &= ~CAP_INFO_SHORT_SLOT_TIME; + + rlmSyncOperationParams(prAdapter, prBssInfo); + fgUpdateBeacon = TRUE; + } + + /* Update Beacon content if related IE content is changed */ + if (fgUpdateBeacon) + bssUpdateBeaconContent(prAdapter, prBssInfo->ucNetTypeIndex); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Initial the channel list from the domain information. +* This function is called after P2P initial and Domain information changed. +* Make sure the device is disconnected while changing domain information. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return boolean value if probe response frame is +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmFuncInitialChannelList(IN P_ADAPTER_T prAdapter) +{ + P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T) NULL; + P_DOMAIN_INFO_ENTRY prDomainInfoEntry = (P_DOMAIN_INFO_ENTRY) NULL; + P_DOMAIN_SUBBAND_INFO prDomainSubBand = (P_DOMAIN_SUBBAND_INFO) NULL; + P_CHANNEL_ENTRY_FIELD_T prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) NULL; + UINT_32 u4Idx = 0, u4IdxII = 0; + UINT_8 ucBufferSize = P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE; +#if 0 + UINT_8 ucSocialChnlSupport = 0, ucAutoChnl = 0; +#endif + + do { + ASSERT_BREAK(prAdapter != NULL); + + prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings; +#if 0 + ucAutoChnl = prP2pConnSetting->ucOperatingChnl; +#endif + + prDomainInfoEntry = rlmDomainGetDomainInfo(prAdapter); + + ASSERT_BREAK((prDomainInfoEntry != NULL) && (prP2pConnSetting != NULL)); + + prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) prP2pConnSetting->aucChannelEntriesField; + + for (u4Idx = 0; u4Idx < MAX_SUBBAND_NUM; u4Idx++) { + prDomainSubBand = &prDomainInfoEntry->rSubBand[u4Idx]; + + if (((prDomainSubBand->ucBand == BAND_5G) && (!prAdapter->fgEnable5GBand)) || + (prDomainSubBand->ucBand == BAND_NULL)) { + continue; + } + + if (ucBufferSize < (P2P_ATTRI_LEN_CHANNEL_ENTRY + prDomainSubBand->ucNumChannels)) { + /* Buffer is not enough to include all supported channels. */ + break; /* for */ + } + + prChannelEntryField->ucRegulatoryClass = prDomainSubBand->ucRegClass; + prChannelEntryField->ucNumberOfChannels = prDomainSubBand->ucNumChannels; + + for (u4IdxII = 0; u4IdxII < prDomainSubBand->ucNumChannels; u4IdxII++) { + prChannelEntryField->aucChannelList[u4IdxII] = prDomainSubBand->ucFirstChannelNum + + (u4IdxII * prDomainSubBand->ucChannelSpan); + +#if 0 + switch (prChannelEntryField->aucChannelList[u4IdxII]) { + case 1: + ucSocialChnlSupport = 1; + break; + case 6: + ucSocialChnlSupport = 6; + break; + case 11: + ucSocialChnlSupport = 11; + break; + default: + break; + } + +#endif + } + + if (ucBufferSize >= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels)) + ucBufferSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels); + else + break; + + prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntryField + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (ULONG) + prChannelEntryField->ucNumberOfChannels); + + } + +#if 0 + if (prP2pConnSetting->ucListenChnl == 0) { + prP2pConnSetting->ucListenChnl = P2P_DEFAULT_LISTEN_CHANNEL; + + if (ucSocialChnlSupport != 0) { + /* 1. User Not Set LISTEN channel. + * 2. Social channel is not empty. + */ + prP2pConnSetting->ucListenChnl = ucSocialChnlSupport; + } + } +#endif + + /* TODO: 20110921 frog - */ + /* If LISTEN channel is not set, + * a random supported channel would be set. + * If no social channel is supported, DEFAULT channel would be set. + */ + + prP2pConnSetting->ucRfChannelListSize = P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE - ucBufferSize; + +#if 0 + if (prP2pConnSetting->ucOperatingChnl == 0) { /* User not set OPERATE channel. */ + + if (scnQuerySparseChannel(prAdapter, NULL, &ucAutoChnl)) + break; /* while */ + + ucBufferSize = prP2pConnSetting->ucRfChannelListSize; + + prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) prP2pConnSetting->aucChannelEntriesField; + + while (ucBufferSize != 0) { + if (prChannelEntryField->ucNumberOfChannels != 0) { + ucAutoChnl = prChannelEntryField->aucChannelList[0]; + break; /* while */ + } + + else { + prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) ((UINT_32) prChannelEntryField + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (UINT_32)prChannelEntryField->ucNumberOfChannels); + + ucBufferSize -= + (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels); + } + + } + + } +#endif + /* We assume user would not set a channel not in the channel list. + * If so, the operating channel still depends on target device supporting capability. + */ + + /* TODO: 20110921 frog - */ + /* If the Operating channel is not set, a channel from supported channel list is set automatically. + * If there is no supported channel in channel list, a DEFAULT channel is set. + */ + + } while (FALSE); + +#if 0 + prP2pConnSetting->ucOperatingChnl = ucAutoChnl; +#endif + +} /* rlmFuncInitialChannelList */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find a common channel list from the local channel list info & target channel list info. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return boolean value if probe response frame is +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmFuncCommonChannelList(IN P_ADAPTER_T prAdapter, + IN P_CHANNEL_ENTRY_FIELD_T prChannelEntryII, IN UINT_8 ucChannelListSize) +{ + P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T) NULL; + P_CHANNEL_ENTRY_FIELD_T prChannelEntryI = (P_CHANNEL_ENTRY_FIELD_T) NULL, prChannelEntryIII = + (P_CHANNEL_ENTRY_FIELD_T) NULL; + UINT_8 aucCommonChannelList[P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE] = {0}; + UINT_8 ucOriChnlSize = 0, ucNewChnlSize = 0; + + do { + + ASSERT_BREAK(prAdapter != NULL); + + prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings; + + prChannelEntryIII = (P_CHANNEL_ENTRY_FIELD_T) aucCommonChannelList; + + while (ucChannelListSize > 0) { + + prChannelEntryI = (P_CHANNEL_ENTRY_FIELD_T) prP2pConnSetting->aucChannelEntriesField; + ucOriChnlSize = prP2pConnSetting->ucRfChannelListSize; + + while (ucOriChnlSize > 0) { + if (prChannelEntryI->ucRegulatoryClass == prChannelEntryII->ucRegulatoryClass) { + prChannelEntryIII->ucRegulatoryClass = prChannelEntryI->ucRegulatoryClass; + /* + * TODO: Currently we assume that the regulatory class the same, + * the channels are the same. + */ + kalMemCopy(prChannelEntryIII->aucChannelList, prChannelEntryII->aucChannelList, + prChannelEntryII->ucNumberOfChannels); + prChannelEntryIII->ucNumberOfChannels = prChannelEntryII->ucNumberOfChannels; + + ucNewChnlSize += + P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryIII->ucNumberOfChannels; + + prChannelEntryIII = (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntryIII + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (ULONG)prChannelEntryIII->ucNumberOfChannels); + } + + ucOriChnlSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryI->ucNumberOfChannels); + + prChannelEntryI = (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntryI + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (ULONG) + prChannelEntryI->ucNumberOfChannels); + + } + + ucChannelListSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryII->ucNumberOfChannels); + + prChannelEntryII = (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntryII + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (ULONG) prChannelEntryII->ucNumberOfChannels); + + } + + kalMemCopy(prP2pConnSetting->aucChannelEntriesField, aucCommonChannelList, ucNewChnlSize); + prP2pConnSetting->ucRfChannelListSize = ucNewChnlSize; + + } while (FALSE); + +} /* rlmFuncCommonChannelList */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 rlmFuncFindOperatingClass(IN P_ADAPTER_T prAdapter, IN UINT_8 ucChannelNum) +{ + UINT_8 ucRegulatoryClass = 0, ucBufferSize = 0; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T) NULL; + P_CHANNEL_ENTRY_FIELD_T prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) NULL; + UINT_32 u4Idx = 0; + + do { + ASSERT_BREAK(prAdapter != NULL); + + prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings; + ucBufferSize = prP2pConnSetting->ucRfChannelListSize; + prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) prP2pConnSetting->aucChannelEntriesField; + + while (ucBufferSize != 0) { + + for (u4Idx = 0; u4Idx < prChannelEntryField->ucNumberOfChannels; u4Idx++) { + if (prChannelEntryField->aucChannelList[u4Idx] == ucChannelNum) { + ucRegulatoryClass = prChannelEntryField->ucRegulatoryClass; + break; + } + + } + + if (ucRegulatoryClass != 0) + break; /* while */ + + prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntryField + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (ULONG)prChannelEntryField->ucNumberOfChannels); + + ucBufferSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels); + + } + + } while (FALSE); + + return ucRegulatoryClass; +} /* rlmFuncFindOperatingClass */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rlmFuncFindAvailableChannel(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucCheckChnl, + IN PUINT_8 pucSuggestChannel, IN BOOLEAN fgIsSocialChannel, IN BOOLEAN fgIsDefaultChannel) +{ + BOOLEAN fgIsResultAvailable = FALSE; + P_CHANNEL_ENTRY_FIELD_T prChannelEntry = (P_CHANNEL_ENTRY_FIELD_T) NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T) NULL; + UINT_8 ucBufferSize = 0, ucIdx = 0, ucChannelSelected = 0; + + do { + ASSERT_BREAK(prAdapter != NULL); + + if (fgIsDefaultChannel) + ucChannelSelected = P2P_DEFAULT_LISTEN_CHANNEL; + + prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings; + ucBufferSize = prP2pConnSetting->ucRfChannelListSize; + prChannelEntry = (P_CHANNEL_ENTRY_FIELD_T) prP2pConnSetting->aucChannelEntriesField; + + while ((ucBufferSize != 0) && (!fgIsResultAvailable)) { + + for (ucIdx = 0; ucIdx < prChannelEntry->ucNumberOfChannels; ucIdx++) { + if ((!fgIsSocialChannel) || + (prChannelEntry->aucChannelList[ucIdx] == 1) || + (prChannelEntry->aucChannelList[ucIdx] == 6) || + (prChannelEntry->aucChannelList[ucIdx] == 11)) { + + if (prChannelEntry->aucChannelList[ucIdx] <= 11) { + /* 2.4G. */ + ucChannelSelected = prChannelEntry->aucChannelList[ucIdx]; + } else if ((prChannelEntry->aucChannelList[ucIdx] < 52) && + (prChannelEntry->aucChannelList[ucIdx] > 14)) { + /* 2.4G + 5G. */ + ucChannelSelected = prChannelEntry->aucChannelList[ucIdx]; + } + + if (ucChannelSelected == ucCheckChnl) { + fgIsResultAvailable = TRUE; + break; + } + } + + } + + ucBufferSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntry->ucNumberOfChannels); + + prChannelEntry = (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntry + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (ULONG) prChannelEntry->ucNumberOfChannels); + + } + + if ((!fgIsResultAvailable) && (pucSuggestChannel != NULL)) { + DBGLOG(P2P, TRACE, + "The request channel %d is not available, sugguested channel:%d\n", ucCheckChnl, + ucChannelSelected); + /* Given a suggested channel. */ + *pucSuggestChannel = ucChannelSelected; + } + + } while (FALSE); + + return fgIsResultAvailable; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +ENUM_CHNL_EXT_T rlmDecideScoForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) +{ + P_DOMAIN_SUBBAND_INFO prSubband; + P_DOMAIN_INFO_ENTRY prDomainInfo; + UINT_8 ucSecondChannel, i, j; + ENUM_CHNL_EXT_T eSCO; + + eSCO = CHNL_EXT_SCN; + + if (prBssInfo->eBand == BAND_2G4) { + if (prBssInfo->ucPrimaryChannel != 14) + eSCO = (prBssInfo->ucPrimaryChannel > 7) ? CHNL_EXT_SCB : CHNL_EXT_SCA; + } else { + prDomainInfo = rlmDomainGetDomainInfo(prAdapter); + ASSERT(prDomainInfo); + + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubband = &prDomainInfo->rSubBand[i]; + if (prSubband->ucBand == prBssInfo->eBand) { + for (j = 0; j < prSubband->ucNumChannels; j++) { + if ((prSubband->ucFirstChannelNum + j * prSubband->ucChannelSpan) + == prBssInfo->ucPrimaryChannel) { + eSCO = (j & 1) ? CHNL_EXT_SCB : CHNL_EXT_SCA; + break; + } + } + + if (j < prSubband->ucNumChannels) + break; /* Found */ + } + } + } + + /* Check if it is boundary channel and 40MHz BW is permitted */ + if (eSCO != CHNL_EXT_SCN) { + ucSecondChannel = (eSCO == CHNL_EXT_SCA) ? + (prBssInfo->ucPrimaryChannel + 4) : (prBssInfo->ucPrimaryChannel - 4); + + if (!rlmDomainIsLegalChannel(prAdapter, prBssInfo->eBand, ucSecondChannel)) + eSCO = CHNL_EXT_SCN; + } + + return eSCO; +} +#if CFG_SUPPORT_P2P_ECSA +ENUM_CHNL_EXT_T rlmDecideSco(P_ADAPTER_T prAdapter, UINT_8 ucPrimaryChannel, ENUM_BAND_T eBand) +{ + P_DOMAIN_SUBBAND_INFO prSubband; + P_DOMAIN_INFO_ENTRY prDomainInfo; + UINT_8 i, j; + ENUM_CHNL_EXT_T eSCO; + + eSCO = CHNL_EXT_SCN; + + if (eBand == BAND_2G4) { + if (ucPrimaryChannel != 14) + eSCO = (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 == eBand) { + for (j = 0; j < prSubband->ucNumChannels; j++) { + if ((prSubband->ucFirstChannelNum + j * prSubband->ucChannelSpan) + == ucPrimaryChannel) { + eSCO = (j & 1) ? CHNL_EXT_SCB : CHNL_EXT_SCA; + break; + } + } + + if (j < prSubband->ucNumChannels) + break; /* Found */ + } + } + } + + return eSCO; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_rlm_obss.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_rlm_obss.c new file mode 100644 index 0000000000000..81b5c496708dd --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_rlm_obss.c @@ -0,0 +1,314 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#include "precomp.h" + +static UINT_8 rlmObssChnlLevelIn2G4(P_BSS_INFO_T prBssInfo, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend); + +static UINT_8 rlmObssChnlLevelIn5G(P_BSS_INFO_T prBssInfo, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend); + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Different concurrent network has itself channel lists, and +* concurrent networks should have been recorded in channel lists. +* If role of active P2P is GO, assume associated AP of AIS will +* record our Beacon for P2P GO because of same channel. +* +* Note: If we have scenario of different channel in the future, +* the internal FW communication channel shall be established. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 rlmObssChnlLevel(P_BSS_INFO_T prBssInfo, ENUM_BAND_T eBand, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend) +{ + UINT_8 ucChannelLevel; + + ASSERT(prBssInfo); + + if (eBand == BAND_2G4) { + ucChannelLevel = rlmObssChnlLevelIn2G4(prBssInfo, ucPriChannel, eExtend); + + /* (TBD) If concurrent networks permit different channel, extra + * channel judgement should be added. Please refer to + * previous version of this file. + */ + } else if (eBand == BAND_5G) { + ucChannelLevel = rlmObssChnlLevelIn5G(prBssInfo, ucPriChannel, eExtend); + + /* (TBD) If concurrent networks permit different channel, extra + * channel judgement should be added. Please refer to + * previous version of this file. + */ + } else { + ucChannelLevel = CHNL_LEVEL0; + } + + return ucChannelLevel; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static UINT_8 rlmObssChnlLevelIn2G4(P_BSS_INFO_T prBssInfo, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend) +{ + UINT_8 i, ucChannelLevel; + UINT_8 ucSecChannel, ucCenterChannel; + UINT_8 ucAffectedChnl_L, ucAffectedChnl_H; + + ASSERT(prBssInfo); + + ucChannelLevel = CHNL_LEVEL2; + + /* Calculate center channel for 2.4G band */ + if (eExtend == CHNL_EXT_SCA) { + ucCenterChannel = ucPriChannel + 2; + ucSecChannel = ucPriChannel + 4; + } else if (eExtend == CHNL_EXT_SCB) { + ucCenterChannel = ucPriChannel - 2; + ucSecChannel = ucPriChannel - 4; + } else { + return CHNL_LEVEL0; + } + ASSERT(ucCenterChannel >= 1 && ucCenterChannel <= 14); + + /* Calculated low/upper channels in affected freq range */ + ucAffectedChnl_L = (ucCenterChannel <= AFFECTED_CHNL_OFFSET) ? 1 : (ucCenterChannel - AFFECTED_CHNL_OFFSET); + + ucAffectedChnl_H = (ucCenterChannel >= (14 - AFFECTED_CHNL_OFFSET)) ? + 14 : (ucCenterChannel + AFFECTED_CHNL_OFFSET); + + /* Check intolerant (Non-HT) channel list */ + ASSERT(prBssInfo->auc2G_NonHtChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_NonHtChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { + if ((prBssInfo->auc2G_NonHtChnlList[i] >= ucAffectedChnl_L && + prBssInfo->auc2G_NonHtChnlList[i] <= ucAffectedChnl_H) && + prBssInfo->auc2G_NonHtChnlList[i] != ucPriChannel) { + + ucChannelLevel = CHNL_LEVEL0; + goto L_2G4_level_end; + } + } + + /* Check 20M BW request channel list */ + ASSERT(prBssInfo->auc2G_20mReqChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_20mReqChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { + if ((prBssInfo->auc2G_20mReqChnlList[i] >= ucAffectedChnl_L && + prBssInfo->auc2G_20mReqChnlList[i] <= ucAffectedChnl_H)) { + + ucChannelLevel = CHNL_LEVEL0; + goto L_2G4_level_end; + } + } + + /* Check 2.4G primary channel list */ + ASSERT(prBssInfo->auc2G_PriChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_PriChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { + if ((prBssInfo->auc2G_PriChnlList[i] >= ucAffectedChnl_L && + prBssInfo->auc2G_PriChnlList[i] <= ucAffectedChnl_H) && + prBssInfo->auc2G_PriChnlList[i] != ucPriChannel) { + + ucChannelLevel = CHNL_LEVEL0; + goto L_2G4_level_end; + } + } + + /* Check 2.4G secondary channel list */ + ASSERT(prBssInfo->auc2G_SecChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_SecChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { + if ((prBssInfo->auc2G_SecChnlList[i] >= ucAffectedChnl_L && + prBssInfo->auc2G_SecChnlList[i] <= ucAffectedChnl_H) && + prBssInfo->auc2G_SecChnlList[i] != ucSecChannel) { + + ucChannelLevel = CHNL_LEVEL0; + goto L_2G4_level_end; + } + } + +L_2G4_level_end: + + return ucChannelLevel; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static UINT_8 rlmObssChnlLevelIn5G(P_BSS_INFO_T prBssInfo, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend) +{ + UINT_8 i, ucChannelLevel; + UINT_8 ucSecChannel; + + ASSERT(prBssInfo); + + ucChannelLevel = CHNL_LEVEL2; + + /* Calculate center channel for 2.4G band */ + if (eExtend == CHNL_EXT_SCA) + ucSecChannel = ucPriChannel + 4; + else if (eExtend == CHNL_EXT_SCB) + ucSecChannel = ucPriChannel - 4; + else + return CHNL_LEVEL0; + ASSERT(ucSecChannel >= 36); + + /* Check 5G primary channel list */ + ASSERT(prBssInfo->auc5G_PriChnlList[0] <= CHNL_LIST_SZ_5G); + for (i = 1; i <= prBssInfo->auc5G_PriChnlList[0] && i <= CHNL_LIST_SZ_5G; i++) { + if (prBssInfo->auc5G_PriChnlList[i] == ucSecChannel) { + + ucChannelLevel = CHNL_LEVEL0; + goto L_5G_level_end; + } else if (prBssInfo->auc5G_PriChnlList[i] == ucPriChannel) { + ucChannelLevel = CHNL_LEVEL1; + } + } + + /* Check non-HT channel list */ + ASSERT(prBssInfo->auc5G_NonHtChnlList[0] <= CHNL_LIST_SZ_5G); + for (i = 1; i <= prBssInfo->auc5G_NonHtChnlList[0] && i <= CHNL_LIST_SZ_5G; i++) { + if (prBssInfo->auc5G_NonHtChnlList[i] == ucSecChannel) { + + ucChannelLevel = CHNL_LEVEL0; + goto L_5G_level_end; + } else if (prBssInfo->auc5G_NonHtChnlList[i] == ucPriChannel) { + ucChannelLevel = CHNL_LEVEL1; + } + } + + /* Check secondary channel list */ + ASSERT(prBssInfo->auc5G_SecChnlList[0] <= CHNL_LIST_SZ_5G); + for (i = 1; i <= prBssInfo->auc5G_SecChnlList[0] && i <= CHNL_LIST_SZ_5G; i++) { + if (prBssInfo->auc5G_SecChnlList[i] == ucPriChannel) { + + ucChannelLevel = CHNL_LEVEL0; + goto L_5G_level_end; + } + } + +L_5G_level_end: + + return ucChannelLevel; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmObssScanExemptionRsp(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_SW_RFB_T prSwRfb) +{ + P_MSDU_INFO_T prMsduInfo; + P_ACTION_20_40_COEXIST_FRAME prTxFrame; + + /* To do: need an algorithm to do judgement. Now always reject request */ + + prMsduInfo = (P_MSDU_INFO_T)cnmMgtPktAlloc(prAdapter, PUBLIC_ACTION_MAX_LEN); + if (prMsduInfo == NULL) + return; + + DBGLOG(RLM, INFO, "Send 20/40 coexistence rsp frame!\n"); + + prTxFrame = (P_ACTION_20_40_COEXIST_FRAME) prMsduInfo->prPacket; + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + COPY_MAC_ADDR(prTxFrame->aucDestAddr, ((P_ACTION_20_40_COEXIST_FRAME) prSwRfb->pvHeader)->aucSrcAddr); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); + + prTxFrame->ucCategory = CATEGORY_PUBLIC_ACTION; + prTxFrame->ucAction = ACTION_PUBLIC_20_40_COEXIST; + + /* To do: find correct algorithm */ + prTxFrame->rBssCoexist.ucId = ELEM_ID_20_40_BSS_COEXISTENCE; + prTxFrame->rBssCoexist.ucLength = 1; + prTxFrame->rBssCoexist.ucData = 0; + + ASSERT((WLAN_MAC_HEADER_LEN + 5) <= PUBLIC_ACTION_MAX_LEN); + + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfo->ucStaRecIndex = prSwRfb->ucStaRecIdx; + prMsduInfo->ucNetworkType = prBssInfo->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_HTC_LEN + 5; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->fgIsBasicRate = FALSE; + + /* Send them to HW queue */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_scan.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_scan.c new file mode 100644 index 0000000000000..0741c3e6b8f5b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_scan.c @@ -0,0 +1,886 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +P_P2P_DEVICE_DESC_T +scanSearchTargetP2pDesc(IN P_ADAPTER_T prAdapter, IN UINT_8 aucDeviceID[], IN PP_BSS_DESC_T pprBssDesc) +{ + + P_P2P_DEVICE_DESC_T prTargetP2pDesc = (P_P2P_DEVICE_DESC_T) NULL; + P_SCAN_INFO_T prScanInfo = (P_SCAN_INFO_T) NULL; + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; + + ASSERT(prAdapter); + ASSERT(aucDeviceID); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + + /* 4 <1> The outer loop to search for a candidate. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + /* Loop for each prBssDesc */ + prTargetP2pDesc = scanFindP2pDeviceDesc(prAdapter, prBssDesc, aucDeviceID, TRUE, FALSE); + + if (prTargetP2pDesc != NULL) + break; + } + + if ((pprBssDesc) && (prTargetP2pDesc != NULL)) { + /* Only valid if prTargetP2pDesc is not NULL. */ + *pprBssDesc = prBssDesc; + } + + return prTargetP2pDesc; +} /* scanSearchTargetP2pDesc */ + +VOID scanInvalidAllP2pClientDevice(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) +{ + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; + P_P2P_DEVICE_DESC_T prTargetDesc = (P_P2P_DEVICE_DESC_T) NULL; + + LINK_FOR_EACH(prLinkEntry, &prBssDesc->rP2pDeviceList) { + prTargetDesc = LINK_ENTRY(prLinkEntry, P2P_DEVICE_DESC_T, rLinkEntry); + + if (prTargetDesc->fgDevInfoValid) + prTargetDesc->fgDevInfoValid = FALSE; + } + +} /* scanRenewP2pClientDevice */ + +VOID scanRemoveInvalidP2pClientDevice(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) +{ + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL, prNexEntry = (P_LINK_ENTRY_T) NULL; + P_P2P_DEVICE_DESC_T prTargetDesc = (P_P2P_DEVICE_DESC_T) NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; + + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + LINK_FOR_EACH_SAFE(prLinkEntry, prNexEntry, &prBssDesc->rP2pDeviceList) { + prTargetDesc = LINK_ENTRY(prLinkEntry, P2P_DEVICE_DESC_T, rLinkEntry); + + if (!prTargetDesc->fgDevInfoValid) { + LINK_REMOVE_KNOWN_ENTRY(&prBssDesc->rP2pDeviceList, prLinkEntry); + if ((prP2pConnSettings) && (prP2pConnSettings->prTargetP2pDesc == prTargetDesc)) + prP2pConnSettings->prTargetP2pDesc = NULL; + kalMemFree(prTargetDesc, VIR_MEM_TYPE, sizeof(P2P_DEVICE_DESC_T)); + } + } + +} /* scanRenewP2pClientDevice */ + +P_P2P_DEVICE_DESC_T +scanFindP2pDeviceDesc(IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc, + IN UINT_8 aucMacAddr[], IN BOOLEAN fgIsDeviceAddr, IN BOOLEAN fgAddIfNoFound) +{ + + P_P2P_DEVICE_DESC_T prTargetDesc = (P_P2P_DEVICE_DESC_T) NULL; + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prBssDesc != NULL) && (aucMacAddr != NULL)); + + LINK_FOR_EACH(prLinkEntry, &prBssDesc->rP2pDeviceList) { + prTargetDesc = LINK_ENTRY(prLinkEntry, P2P_DEVICE_DESC_T, rLinkEntry); + + if (fgIsDeviceAddr) { + if (EQUAL_MAC_ADDR(prTargetDesc->aucDeviceAddr, aucMacAddr)) + break; + } else { + if (EQUAL_MAC_ADDR(prTargetDesc->aucInterfaceAddr, aucMacAddr)) + break; + } + + prTargetDesc = NULL; + } + + if ((fgAddIfNoFound) && (prTargetDesc == NULL)) { + /* Target Not Found. */ + /* TODO: Use memory pool in the future. */ + prTargetDesc = kalMemAlloc(sizeof(P2P_DEVICE_DESC_T), VIR_MEM_TYPE); + + if (prTargetDesc) { + kalMemZero(prTargetDesc, sizeof(P2P_DEVICE_DESC_T)); + LINK_ENTRY_INITIALIZE(&(prTargetDesc->rLinkEntry)); + COPY_MAC_ADDR(prTargetDesc->aucDeviceAddr, aucMacAddr); + LINK_INSERT_TAIL(&prBssDesc->rP2pDeviceList, &prTargetDesc->rLinkEntry); + prTargetDesc->fgDevInfoValid = TRUE; + } else { + ASSERT(FALSE); + } + } + + } while (FALSE); + + return prTargetDesc; +} /* scanFindP2pDeviceDesc */ + +P_P2P_DEVICE_DESC_T scanGetP2pDeviceDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) +{ + + P_P2P_DEVICE_DESC_T prTargetDesc = (P_P2P_DEVICE_DESC_T) NULL; + + ASSERT(prAdapter); + ASSERT(prBssDesc); + + if (prBssDesc->prP2pDesc == NULL) { + + prTargetDesc = kalMemAlloc(sizeof(P2P_DEVICE_DESC_T), VIR_MEM_TYPE); + + if (prTargetDesc) { + kalMemZero(prTargetDesc, sizeof(P2P_DEVICE_DESC_T)); + LINK_ENTRY_INITIALIZE(&(prTargetDesc->rLinkEntry)); + LINK_INSERT_TAIL(&prBssDesc->rP2pDeviceList, &prTargetDesc->rLinkEntry); + prTargetDesc->fgDevInfoValid = TRUE; + prBssDesc->prP2pDesc = prTargetDesc; + /* We are not sure the SrcAddr is Device Address or Interface Address. */ + COPY_MAC_ADDR(prTargetDesc->aucDeviceAddr, prBssDesc->aucSrcAddr); + COPY_MAC_ADDR(prTargetDesc->aucInterfaceAddr, prBssDesc->aucSrcAddr); + } else { + + ASSERT(FALSE); + } + } else { + prTargetDesc = prBssDesc->prP2pDesc; + } + + return prTargetDesc; + +} /* scanFindP2pDeviceDesc */ + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* @brief Convert the Beacon or ProbeResp Frame in SW_RFB_T to Event Packet +* +* @param[in] prSwRfb Pointer to the receiving SW_RFB_T structure. +* +* @retval WLAN_STATUS_SUCCESS It is a valid Scan Result and been sent to the host. +* @retval WLAN_STATUS_FAILURE It is not a valid Scan Result. +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN scanUpdateP2pDeviceDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) +{ + P_P2P_DEVICE_DESC_T prP2pDesc = (P_P2P_DEVICE_DESC_T) NULL; + P_P2P_ATTRIBUTE_T prP2pAttribute = (P_P2P_ATTRIBUTE_T) NULL; + UINT_16 u2AttributeLen = 0; + UINT_32 u4Idx = 0; + BOOLEAN fgUpdateDevInfo = FALSE; + + P_DEVICE_NAME_TLV_T prP2pDevName = (P_DEVICE_NAME_TLV_T) NULL; + P_P2P_ATTRI_GROUP_INFO_T prP2pAttriGroupInfo = (P_P2P_ATTRI_GROUP_INFO_T) NULL; + + ASSERT(prAdapter); + + prP2pDesc = scanGetP2pDeviceDesc(prAdapter, prBssDesc); + + if (!prP2pDesc) { + ASSERT(FALSE); + return fgUpdateDevInfo; + } + + p2pGetP2PAttriList(prAdapter, prBssDesc->aucIEBuf, prBssDesc->u2IELength, (PPUINT_8) & prP2pAttribute, + &u2AttributeLen); + + while (u2AttributeLen >= P2P_ATTRI_HDR_LEN) { + switch (prP2pAttribute->ucId) { + case P2P_ATTRI_ID_P2P_CAPABILITY: /* Beacon, Probe Response */ + { + P_P2P_ATTRI_CAPABILITY_T prP2pAttriCapability = (P_P2P_ATTRI_CAPABILITY_T) NULL; + + prP2pAttriCapability = (P_P2P_ATTRI_CAPABILITY_T) prP2pAttribute; + ASSERT(prP2pAttriCapability->u2Length == 2); + + prP2pDesc->ucDeviceCapabilityBitmap = prP2pAttriCapability->ucDeviceCap; + prP2pDesc->ucGroupCapabilityBitmap = prP2pAttriCapability->ucGroupCap; + } + break; + case P2P_ATTRI_ID_P2P_DEV_ID: /* Beacon */ + { + P_P2P_ATTRI_DEV_ID_T prP2pAttriDevID = (P_P2P_ATTRI_DEV_ID_T) NULL; + + prP2pAttriDevID = (P_P2P_ATTRI_DEV_ID_T) prP2pAttribute; + ASSERT(prP2pAttriDevID->u2Length == P2P_ATTRI_MAX_LEN_P2P_DEV_ID); + + kalMemCopy(prP2pDesc->aucDeviceAddr, prP2pAttriDevID->aucDevAddr, MAC_ADDR_LEN); + } + break; + case P2P_ATTRI_ID_P2P_DEV_INFO: /* Probe Response */ + { + P_P2P_ATTRI_DEV_INFO_T prP2pAttriDevInfo = (P_P2P_ATTRI_DEV_INFO_T) NULL; + P_P2P_DEVICE_TYPE_T prP2pDevType = (P_P2P_DEVICE_TYPE_T) NULL; + UINT_16 u2NameLen = 0, u2Id = 0; + + fgUpdateDevInfo = TRUE; + + prP2pAttriDevInfo = (P_P2P_ATTRI_DEV_INFO_T) prP2pAttribute; + + kalMemCopy(prP2pDesc->aucDeviceAddr, prP2pAttriDevInfo->aucDevAddr, MAC_ADDR_LEN); + + WLAN_GET_FIELD_BE16(&prP2pAttriDevInfo->u2ConfigMethodsBE, &prP2pDesc->u2ConfigMethod); + + prP2pDevType = &prP2pDesc->rPriDevType; + WLAN_GET_FIELD_BE16(&prP2pAttriDevInfo->rPrimaryDevTypeBE.u2CategoryId, + &prP2pDevType->u2CategoryID); + WLAN_GET_FIELD_BE16(&prP2pAttriDevInfo->rPrimaryDevTypeBE.u2SubCategoryId, + &prP2pDevType->u2SubCategoryID); + + ASSERT(prP2pAttriDevInfo->ucNumOfSecondaryDevType <= + P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT); + /* TODO: Fixme if secondary device type is more than 2. */ + prP2pDesc->ucSecDevTypeNum = 0; + for (u4Idx = 0; u4Idx < prP2pAttriDevInfo->ucNumOfSecondaryDevType; u4Idx++) { + if (u4Idx < P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT) { + prP2pDevType = &(prP2pDesc->arSecDevType[u4Idx]); + WLAN_GET_FIELD_BE16(&prP2pAttriDevInfo-> + arSecondaryDevTypeListBE[u4Idx].u2CategoryId, + &prP2pDevType->u2CategoryID); + WLAN_GET_FIELD_BE16(&prP2pAttriDevInfo-> + arSecondaryDevTypeListBE[u4Idx].u2SubCategoryId, + &prP2pDevType->u2SubCategoryID); + prP2pDesc->ucSecDevTypeNum++; + } + + } + prP2pDevName = + (P_DEVICE_NAME_TLV_T) ((PUINT_8) prP2pAttriDevInfo->arSecondaryDevTypeListBE + + (u4Idx * sizeof(DEVICE_TYPE_T))); + WLAN_GET_FIELD_BE16(&prP2pDevName->u2Length, &u2NameLen); + WLAN_GET_FIELD_BE16(&prP2pDevName->u2Id, &u2Id); + ASSERT(u2Id == WPS_ATTRI_ID_DEVICE_NAME); + if (u2NameLen > WPS_ATTRI_MAX_LEN_DEVICE_NAME) + u2NameLen = WPS_ATTRI_MAX_LEN_DEVICE_NAME; + prP2pDesc->u2NameLength = u2NameLen; + kalMemCopy(prP2pDesc->aucName, prP2pDevName->aucName, prP2pDesc->u2NameLength); + } + break; + case P2P_ATTRI_ID_P2P_GROUP_INFO: /* Probe Response */ + prP2pAttriGroupInfo = (P_P2P_ATTRI_GROUP_INFO_T) prP2pAttribute; + break; + case P2P_ATTRI_ID_NOTICE_OF_ABSENCE: + break; + case P2P_ATTRI_ID_EXT_LISTEN_TIMING: + /* TODO: Not implement yet. */ + /* ASSERT(FALSE); */ + break; + default: + break; + } + + u2AttributeLen -= (prP2pAttribute->u2Length + P2P_ATTRI_HDR_LEN); + + prP2pAttribute = + (P_P2P_ATTRIBUTE_T) ((UINT_32) prP2pAttribute + (prP2pAttribute->u2Length + P2P_ATTRI_HDR_LEN)); + + } + + if (prP2pAttriGroupInfo != NULL) { + P_P2P_CLIENT_INFO_DESC_T prClientInfoDesc = (P_P2P_CLIENT_INFO_DESC_T) NULL; + P_P2P_DEVICE_TYPE_T prP2pDevType = (P_P2P_DEVICE_TYPE_T) NULL; + + scanInvalidAllP2pClientDevice(prAdapter, prBssDesc); + + /* GO/Device itself. */ + prP2pDesc->fgDevInfoValid = TRUE; + + prClientInfoDesc = (P_P2P_CLIENT_INFO_DESC_T) prP2pAttriGroupInfo->arClientDesc; + u2AttributeLen = prP2pAttriGroupInfo->u2Length; + + while (u2AttributeLen > 0) { + prP2pDesc = + scanFindP2pDeviceDesc(prAdapter, prBssDesc, prClientInfoDesc->aucDevAddr, TRUE, TRUE); + + if (!prP2pDesc) { + ASSERT(FALSE); + break; /* while */ + } + + prP2pDesc->fgDevInfoValid = TRUE; + + /* Basic size for P2P client info descriptor. */ + ASSERT(u2AttributeLen >= 25); + if (u2AttributeLen < 25) { + DBGLOG(P2P, WARN, "Length incorrect warning.\n"); + break; + } + COPY_MAC_ADDR(prP2pDesc->aucInterfaceAddr, prClientInfoDesc->aucIfAddr); + + prP2pDesc->ucDeviceCapabilityBitmap = prClientInfoDesc->ucDeviceCap; + + WLAN_GET_FIELD_BE16(&prClientInfoDesc->u2ConfigMethodsBE, &prP2pDesc->u2ConfigMethod); + + prP2pDevType = &(prP2pDesc->rPriDevType); + WLAN_GET_FIELD_BE16(&prClientInfoDesc->rPrimaryDevTypeBE.u2CategoryId, + &prP2pDevType->u2CategoryID); + WLAN_GET_FIELD_BE16(&prClientInfoDesc->rPrimaryDevTypeBE.u2SubCategoryId, + &prP2pDevType->u2SubCategoryID); + + ASSERT(prClientInfoDesc->ucNumOfSecondaryDevType <= P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT); + prP2pDesc->ucSecDevTypeNum = 0; + for (u4Idx = 0; u4Idx < prClientInfoDesc->ucNumOfSecondaryDevType; u4Idx++) { + if (u4Idx < P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT) { + prP2pDevType = &(prP2pDesc->arSecDevType[u4Idx]); + WLAN_GET_FIELD_BE16(&prClientInfoDesc-> + arSecondaryDevTypeListBE[u4Idx].u2CategoryId, + &prP2pDevType->u2CategoryID); + WLAN_GET_FIELD_BE16(&prClientInfoDesc-> + arSecondaryDevTypeListBE[u4Idx].u2SubCategoryId, + &prP2pDevType->u2SubCategoryID); + prP2pDesc->ucSecDevTypeNum++; + } + + } + prP2pDevName = + (P_DEVICE_NAME_TLV_T) (prClientInfoDesc->arSecondaryDevTypeListBE + + (u4Idx * sizeof(DEVICE_TYPE_T))); + WLAN_GET_FIELD_BE16(&prP2pDevName->u2Length, &prP2pDesc->u2NameLength); + if (prP2pDesc->u2NameLength > WPS_ATTRI_MAX_LEN_DEVICE_NAME) + prP2pDesc->u2NameLength = WPS_ATTRI_MAX_LEN_DEVICE_NAME; + + kalMemCopy(prP2pDesc->aucName, prP2pDevName->aucName, prP2pDesc->u2NameLength); + + u2AttributeLen -= (prClientInfoDesc->ucLength + P2P_CLIENT_INFO_DESC_HDR_LEN); + prClientInfoDesc = + (P_P2P_CLIENT_INFO_DESC_T) ((UINT_32) prClientInfoDesc + + (UINT_32) prClientInfoDesc->ucLength + + P2P_CLIENT_INFO_DESC_HDR_LEN); + } + + scanRemoveInvalidP2pClientDevice(prAdapter, prBssDesc); + } + + return fgUpdateDevInfo; +} /* end of scanAddP2pDeviceInfo() */ + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Convert the Beacon or ProbeResp Frame in SW_RFB_T to Event Packet +* +* @param[in] prSwRfb Pointer to the receiving SW_RFB_T structure. +* +* @retval WLAN_STATUS_SUCCESS It is a valid Scan Result and been sent to the host. +* @retval WLAN_STATUS_FAILURE It is not a valid Scan Result. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS scanSendDeviceDiscoverEvent(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc, IN P_SW_RFB_T prSwRfb) +{ + EVENT_P2P_DEV_DISCOVER_RESULT_T rEventDevInfo; +#if 1 + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; + P_P2P_DEVICE_DESC_T prTargetDesc = (P_P2P_DEVICE_DESC_T) NULL; + + LINK_FOR_EACH(prLinkEntry, &prBssDesc->rP2pDeviceList) { + prTargetDesc = LINK_ENTRY(prLinkEntry, P2P_DEVICE_DESC_T, rLinkEntry); + + COPY_MAC_ADDR(rEventDevInfo.aucDeviceAddr, prTargetDesc->aucDeviceAddr); + COPY_MAC_ADDR(rEventDevInfo.aucInterfaceAddr, prTargetDesc->aucInterfaceAddr); + + rEventDevInfo.ucDeviceCapabilityBitmap = prTargetDesc->ucDeviceCapabilityBitmap; + rEventDevInfo.ucGroupCapabilityBitmap = prTargetDesc->ucGroupCapabilityBitmap; + rEventDevInfo.u2ConfigMethod = prTargetDesc->u2ConfigMethod; + + kalMemCopy(&rEventDevInfo.rPriDevType, &prTargetDesc->rPriDevType, sizeof(P2P_DEVICE_TYPE_T)); + + kalMemCopy(rEventDevInfo.arSecDevType, + prTargetDesc->arSecDevType, (prTargetDesc->ucSecDevTypeNum * sizeof(P2P_DEVICE_TYPE_T))); + + rEventDevInfo.ucSecDevTypeNum = prTargetDesc->ucSecDevTypeNum; + + rEventDevInfo.u2NameLength = prTargetDesc->u2NameLength; + kalMemCopy(rEventDevInfo.aucName, prTargetDesc->aucName, prTargetDesc->u2NameLength); + + COPY_MAC_ADDR(rEventDevInfo.aucBSSID, prBssDesc->aucBSSID); + + if (prTargetDesc == prBssDesc->prP2pDesc) + nicRxAddP2pDevice(prAdapter, &rEventDevInfo, prBssDesc->aucIEBuf, prBssDesc->u2IELength); + else + nicRxAddP2pDevice(prAdapter, &rEventDevInfo, NULL, 0); + } + + kalP2PIndicateFound(prAdapter->prGlueInfo); + +#else + + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + P_P2P_ATTRIBUTE_T prP2pAttribute = (P_P2P_ATTRIBUTE_T) NULL; + UINT_16 u2AttributeLen = 0; + UINT_32 u4Idx = 0; + P_P2P_ATTRI_GROUP_INFO_T prP2pAttriGroupInfo = (P_P2P_ATTRI_GROUP_INFO_T) NULL; + P_DEVICE_NAME_TLV_T prP2pDevName = (P_DEVICE_NAME_TLV_T) NULL; + + ASSERT(prAdapter); + + prP2pSpecificBssInfo = &prAdapter->rWifiVar.rP2pSpecificBssInfo; + +#if 1 + p2pGetP2PAttriList(prAdapter, prBssDesc->aucIEBuf, prBssDesc->u2IELength, (PPUINT_8) & prP2pAttribute, + &u2AttributeLen); +#else + prP2pAttribute = (P_P2P_ATTRIBUTE_T) &prP2pSpecificBssInfo->aucAttributesCache[0]; + u2AttributeLen = prP2pSpecificBssInfo->u2AttributeLen; +#endif + rEventDevInfo.fgDevInfoValid = FALSE; + + while (u2AttributeLen >= P2P_ATTRI_HDR_LEN) { + switch (prP2pAttribute->ucId) { + case P2P_ATTRI_ID_P2P_CAPABILITY: + { + P_P2P_ATTRI_CAPABILITY_T prP2pAttriCapability = (P_P2P_ATTRI_CAPABILITY_T) NULL; + + prP2pAttriCapability = (P_P2P_ATTRI_CAPABILITY_T) prP2pAttribute; + ASSERT(prP2pAttriCapability->u2Length == 2); + rEventDevInfo.ucDeviceCapabilityBitmap = prP2pAttriCapability->ucDeviceCap; + rEventDevInfo.ucGroupCapabilityBitmap = prP2pAttriCapability->ucGroupCap; + } + break; + case P2P_ATTRI_ID_P2P_DEV_ID: + { + P_P2P_ATTRI_DEV_ID_T prP2pAttriDevID = (P_P2P_ATTRI_DEV_ID_T) NULL; + + prP2pAttriDevID = (P_P2P_ATTRI_DEV_ID_T) prP2pAttribute; + ASSERT(prP2pAttriDevID->u2Length == 6); + kalMemCopy(rEventDevInfo.aucCommunicateAddr, prP2pAttriDevID->aucDevAddr, MAC_ADDR_LEN); + } + break; + case P2P_ATTRI_ID_P2P_DEV_INFO: + { + P_P2P_ATTRI_DEV_INFO_T prP2pAttriDevInfo = (P_P2P_ATTRI_DEV_INFO_T) NULL; + P_P2P_DEVICE_TYPE_T prP2pDevType = (P_P2P_DEVICE_TYPE_T) NULL; + + prP2pAttriDevInfo = (P_P2P_ATTRI_DEV_INFO_T) prP2pAttribute; + rEventDevInfo.fgDevInfoValid = TRUE; + kalMemCopy(rEventDevInfo.aucCommunicateAddr, prP2pAttriDevInfo->aucDevAddr, + MAC_ADDR_LEN); + rEventDevInfo.u2ConfigMethod = prP2pAttriDevInfo->u2ConfigMethodsBE; + + prP2pDevType = &rEventDevInfo.rPriDevType; + prP2pDevType->u2CategoryID = prP2pAttriDevInfo->rPrimaryDevTypeBE.u2CategoryId; + prP2pDevType->u2SubCategoryID = prP2pAttriDevInfo->rPrimaryDevTypeBE.u2SubCategoryId; + + ASSERT(prP2pAttriDevInfo->ucNumOfSecondaryDevType <= 2); + /* TODO: Fixme if secondary device type is more than 2. */ + for (u4Idx = 0; u4Idx < prP2pAttriDevInfo->ucNumOfSecondaryDevType; u4Idx++) { + /* TODO: Current sub device type can only support 2. */ + prP2pDevType = &rEventDevInfo.arSecDevType[u4Idx]; + prP2pDevType->u2CategoryID = prP2pAttriDevInfo->rPrimaryDevTypeBE.u2CategoryId; + prP2pDevType->u2SubCategoryID = + prP2pAttriDevInfo->rPrimaryDevTypeBE.u2SubCategoryId; + } + + prP2pDevName = + (P_DEVICE_NAME_TLV_T) (prP2pAttriDevInfo->arSecondaryDevTypeListBE + + (u4Idx * sizeof(DEVICE_TYPE_T))); + ASSERT(prP2pDevName->u2Id == 0x1011); + ASSERT(prP2pDevName->u2Length <= 32); + /* TODO: Fixme if device name length is longer than 32 bytes. */ + kalMemCopy(rEventDevInfo.aucName, prP2pDevName->aucName, prP2pDevName->u2Length); + } + break; + case P2P_ATTRI_ID_P2P_GROUP_INFO: + prP2pAttriGroupInfo = (P_P2P_ATTRI_GROUP_INFO_T) prP2pAttribute; + break; + } + + u2AttributeLen -= (prP2pAttribute->u2Length + P2P_ATTRI_HDR_LEN); + + prP2pAttribute = + (P_P2P_ATTRIBUTE_T) ((UINT_32) prP2pAttribute + (prP2pAttribute->u2Length + P2P_ATTRI_HDR_LEN)); + + } + + nicRxAddP2pDevice(prAdapter, &rEventDevInfo); + + if (prP2pAttriGroupInfo != NULL) { + P_P2P_CLIENT_INFO_DESC_T prClientInfoDesc = (P_P2P_CLIENT_INFO_DESC_T) NULL; + P_P2P_DEVICE_TYPE_T prP2pDevType = (P_P2P_DEVICE_TYPE_T) NULL; + + prClientInfoDesc = prP2pAttriGroupInfo->arClientDesc; + u2AttributeLen = prP2pAttriGroupInfo->u2Length; + + while (u2AttributeLen > 0) { + /* Basic size for P2P client info descriptor. */ + ASSERT(u2AttributeLen >= 25); + rEventDevInfo.fgDevInfoValid = TRUE; + kalMemCopy(rEventDevInfo.aucCommunicateAddr, prClientInfoDesc->aucIfAddr, MAC_ADDR_LEN); + rEventDevInfo.ucDeviceCapabilityBitmap = prClientInfoDesc->ucDeviceCap; + rEventDevInfo.u2ConfigMethod = prClientInfoDesc->u2ConfigMethodsBE; + + prP2pDevType = &rEventDevInfo.rPriDevType; + prP2pDevType->u2CategoryID = prClientInfoDesc->rPrimaryDevTypeBE.u2CategoryId; + prP2pDevType->u2SubCategoryID = prClientInfoDesc->rPrimaryDevTypeBE.u2SubCategoryId; + + ASSERT(prClientInfoDesc->ucNumOfSecondaryDevType <= 2); + /* TODO: Fixme if secondary device type is more than 2. */ + for (u4Idx = 0; u4Idx < prClientInfoDesc->ucNumOfSecondaryDevType; u4Idx++) { + /* TODO: Current sub device type can only support 2. */ + prP2pDevType = &rEventDevInfo.arSecDevType[u4Idx]; + prP2pDevType->u2CategoryID = + prClientInfoDesc->arSecondaryDevTypeListBE[u4Idx].u2CategoryId; + prP2pDevType->u2SubCategoryID = + prClientInfoDesc->arSecondaryDevTypeListBE[u4Idx].u2SubCategoryId; + } + + prP2pDevName = + (P_DEVICE_NAME_TLV_T) (prClientInfoDesc->arSecondaryDevTypeListBE + + (u4Idx * sizeof(DEVICE_TYPE_T))); + ASSERT(prP2pDevName->u2Id == 0x1011); + ASSERT(prP2pDevName->u2Length <= 32); + /* TODO: Fixme if device name length is longer than 32 bytes. */ + kalMemCopy(&rEventDevInfo.aucName, prP2pDevName->aucName, prP2pDevName->u2Length); + + nicRxAddP2pDevice(prAdapter, &rEventDevInfo); + + u2AttributeLen -= prP2pAttriGroupInfo->u2Length; + prP2pAttriGroupInfo = prP2pAttriGroupInfo + prP2pAttriGroupInfo->u2Length + 1; + } + + } +#endif + return WLAN_STATUS_SUCCESS; +} /* scanSendDeviceDiscoverEvent */ + +VOID +scanP2pUpdateBssChannel(IN UINT_8 ucHwChannel, + IN UINT_8 ucDsChannel, + IN UINT_8 ucHtChannel, + IN P_HIF_RX_HEADER_T prHifRxHdr, + IN P_BSS_DESC_T prBssDesc) +{ + DBGLOG(P2P, INFO, "[channel] hw:ds:ht: band: %d:%d:%d:%d\n", + ucHwChannel, + ucDsChannel, + ucHtChannel, + prBssDesc->eBand); + if (prBssDesc->eBand == BAND_2G4) { + + /* Update RCPI if in right channel */ + if (ucDsChannel >= 1 && ucDsChannel <= 14) { + + /* Receive Beacon/ProbeResp frame from adjacent channel. */ + if ((ucDsChannel == ucHwChannel) || (prHifRxHdr->ucRcpi > prBssDesc->ucRCPI)) + prBssDesc->ucRCPI = prHifRxHdr->ucRcpi; + /* trust channel information brought by IE */ + prBssDesc->ucChannelNum = ucDsChannel; + } else if (ucHtChannel >= 1 && ucHtChannel <= 14) { + /* Receive Beacon/ProbeResp frame from adjacent channel. */ + if ((ucHtChannel == ucHwChannel) || (prHifRxHdr->ucRcpi > prBssDesc->ucRCPI)) + prBssDesc->ucRCPI = prHifRxHdr->ucRcpi; + /* trust channel information brought by IE */ + prBssDesc->ucChannelNum = ucHtChannel; + } else { + prBssDesc->ucRCPI = prHifRxHdr->ucRcpi; + + prBssDesc->ucChannelNum = ucHwChannel; + } + } else { + if (ucHtChannel >= 1 && ucHtChannel < 200) { + /* Receive Beacon/ProbeResp frame from adjacent channel. */ + if ((ucHtChannel == ucHwChannel) || (prHifRxHdr->ucRcpi > prBssDesc->ucRCPI)) + prBssDesc->ucRCPI = prHifRxHdr->ucRcpi; + /* trust channel information brought by IE */ + prBssDesc->ucChannelNum = ucHtChannel; + } else { + /* Always update RCPI */ + prBssDesc->ucRCPI = prHifRxHdr->ucRcpi; + + prBssDesc->ucChannelNum = ucHwChannel; + } + } +} + +VOID +scanP2pGetBssChannel(IN P_SW_RFB_T prSwRfb, + OUT PUINT_8 opucDsChannel, + OUT PUINT_8 opucHtChannel) +{ + const u8 *pucDsIe; + const u8 *pucHtIe; + UINT_8 ucDSChannel = 0; + UINT_8 ucHTChannel = 0; + PUINT_8 pucIe = NULL; + UINT_32 u4PacketLen = 0; + UINT_32 u4IeLen = 0; + struct ieee80211_mgmt *prBcnProbeResponse = NULL; + + u4PacketLen = prSwRfb->u2PacketLen; + u4IeLen = u4PacketLen - offsetof(struct ieee80211_mgmt, u.probe_resp.variable); + prBcnProbeResponse = prSwRfb->pvHeader; + pucIe = prBcnProbeResponse->u.probe_resp.variable; + + pucDsIe = cfg80211_find_ie(ELEM_ID_DS_PARAM_SET, pucIe, u4IeLen); + if (pucDsIe && pucDsIe[1] == 1) + ucDSChannel = pucDsIe[2]; + + pucHtIe = cfg80211_find_ie(ELEM_ID_HT_OP, pucIe, u4IeLen); + if (pucHtIe && pucHtIe[1] >= sizeof(struct ieee80211_ht_operation)) { + + struct ieee80211_ht_operation *htop = (void *)(pucHtIe + 2); + + ucHTChannel = htop->primary_chan; + } + + *opucDsChannel = ucDSChannel; + *opucHtChannel = ucHTChannel; +} + +VOID +scanP2pUpdateBssBand(IN UINT_8 ucDsChannel, + IN UINT_8 ucHtChannel, + IN P_BSS_DESC_T prBssDesc) +{ + if ((ucDsChannel >= 1 && ucDsChannel <= 14) + || (ucHtChannel >= 1 && ucHtChannel <= 14)) + prBssDesc->eBand = BAND_2G4; + else + prBssDesc->eBand = BAND_5G; +} + +VOID +scanP2pProcessBeaconAndProbeResp(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN P_WLAN_STATUS prStatus, + IN P_BSS_DESC_T prBssDesc, IN P_WLAN_BEACON_FRAME_T prWlanBeaconFrame) +{ + BOOLEAN fgIsSkipThisBeacon; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; + UINT_8 ucHwChannel = 0; + UINT_8 ucDsChannel = 0; + UINT_8 ucHtChannel = 0; + + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + fgIsSkipThisBeacon = FALSE; + if (prBssDesc->fgIsP2PPresent) { + if ((prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) && /* P2P GC */ + (prP2pBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) && /* Connected */ + ((prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_BEACON)) { /* TX Beacon */ + + fgIsSkipThisBeacon = TRUE; + } + + if ((!prP2pBssInfo->ucDTIMPeriod) && /* First time. */ + fgIsSkipThisBeacon && (EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, + prP2pConnSettings->aucSSID, prP2pConnSettings->ucSSIDLen))) { /* SSID Match */ + prP2pBssInfo->ucDTIMPeriod = prBssDesc->ucDTIMPeriod; + nicPmIndicateBssConnected(prAdapter, NETWORK_TYPE_P2P_INDEX); + } + + if ((prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_BEACON && + prAdapter->prGlueInfo->prP2PInfo->prScanRequest == NULL) + fgIsSkipThisBeacon = TRUE; + + do { + RF_CHANNEL_INFO_T rChannelInfo; + + ASSERT_BREAK((prSwRfb != NULL) && (prBssDesc != NULL)); + + ucHwChannel = HIF_RX_HDR_GET_CHNL_NUM(prSwRfb->prHifRxHdr); + /* + * Should update channel information separately + */ + scanP2pGetBssChannel(prSwRfb, &ucDsChannel, &ucHtChannel); + + if (((prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) != MAC_FRAME_PROBE_RSP)) { + /* Only report Probe Response frame to supplicant. */ + /* Probe response collect much more information. */ + + if (fgIsSkipThisBeacon || prBssDesc->eBand == BAND_2G4) { + DBGLOG(P2P, TRACE, "Skip beacon [" MACSTR "][%s][ch %d]\n", + MAC2STR(prWlanBeaconFrame->aucBSSID), + prBssDesc->aucSSID, + prBssDesc->ucChannelNum); + break; + } + + prBssDesc->eBand = HIF_RX_HDR_GET_RF_BAND(prSwRfb->prHifRxHdr); + } else { + scanP2pUpdateBssBand(ucDsChannel, ucHtChannel, prBssDesc); + } + + scanP2pUpdateBssChannel(ucHwChannel, ucDsChannel, ucHtChannel, + prSwRfb->prHifRxHdr, + prBssDesc); + rChannelInfo.ucChannelNum = prBssDesc->ucChannelNum; + rChannelInfo.eBand = prBssDesc->eBand; + prBssDesc->fgIsP2PReport = TRUE; + + DBGLOG(P2P, INFO, "indicate %s %pM [%s] [channel: %d] [rcpi: %d] update time %u\n", + prBssDesc->aucSSID, prWlanBeaconFrame->aucBSSID, + (prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_BEACON ? + "beacon" : "probe response", + prBssDesc->ucChannelNum, + prBssDesc->ucRCPI, + prBssDesc->rUpdateTime); + + kalP2PIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) prSwRfb->pvHeader, + (UINT_32) prSwRfb->u2PacketLen, + &rChannelInfo, RCPI_TO_dBm(prBssDesc->ucRCPI)); + + } while (FALSE); + } +} + +VOID scnEventReturnChannel(IN P_ADAPTER_T prAdapter, IN UINT_8 ucScnSeqNum) +{ + + CMD_SCAN_CANCEL rCmdScanCancel; + + /* send cancel message to firmware domain */ + rCmdScanCancel.ucSeqNum = ucScnSeqNum; + rCmdScanCancel.ucIsExtChannel = (UINT_8) FALSE; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SCAN_CANCEL, + TRUE, + FALSE, FALSE, NULL, NULL, sizeof(CMD_SCAN_CANCEL), (PUINT_8)&rCmdScanCancel, NULL, 0); + +} /* scnEventReturnChannel */ + +VOID scanRemoveAllP2pBssDesc(IN P_ADAPTER_T prAdapter) +{ + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc; + P_BSS_DESC_T prBSSDescNext; + + ASSERT(prAdapter); + + prBSSDescList = &(prAdapter->rWifiVar.rScanInfo.rBSSDescList); + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) { + scanRemoveP2pBssDesc(prAdapter, prBssDesc); + } +} /* scanRemoveAllP2pBssDesc */ + +VOID scanRemoveP2pBssDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) +{ + + +} /* scanRemoveP2pBssDesc */ + +P_BSS_DESC_T +scanP2pSearchDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo, IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo) +{ + P_BSS_DESC_T prCandidateBssDesc = (P_BSS_DESC_T) NULL, prBssDesc = (P_BSS_DESC_T) NULL; + P_LINK_T prBssDescList = (P_LINK_T) NULL; + + do { + if ((prAdapter == NULL) || (prP2pBssInfo == NULL) || (prConnReqInfo == NULL)) + break; + + prBssDescList = &(prAdapter->rWifiVar.rScanInfo.rBSSDescList); + + DBGLOG(P2P, LOUD, "Connecting to BSSID: %pM\n", prConnReqInfo->aucBssid); + DBGLOG(P2P, LOUD, "Connecting to SSID:%s, length:%d\n", + HIDE(prConnReqInfo->rSsidStruct.aucSsid), + prConnReqInfo->rSsidStruct.ucSsidLen); + + LINK_FOR_EACH_ENTRY(prBssDesc, prBssDescList, rLinkEntry, BSS_DESC_T) { + DBGLOG(P2P, LOUD, "Checking BSS: %pM\n", prBssDesc->aucBSSID); + + if (prBssDesc->eBSSType != BSS_TYPE_INFRASTRUCTURE) { + DBGLOG(P2P, LOUD, "Ignore mismatch BSS type.\n"); + continue; + } + + if (UNEQUAL_MAC_ADDR(prBssDesc->aucBSSID, prConnReqInfo->aucBssid)) { + DBGLOG(P2P, LOUD, "Ignore mismatch BSSID.\n"); + continue; + } + + /* SSID should be the same? SSID is vary for each connection. so... */ + if (UNEQUAL_SSID(prConnReqInfo->rSsidStruct.aucSsid, + prConnReqInfo->rSsidStruct.ucSsidLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen)) { + + DBGLOG(P2P, TRACE, + "Connecting to BSSID: %pM\n", prConnReqInfo->aucBssid); + DBGLOG(P2P, TRACE, + "Connecting to SSID:%s, length:%d\n", + HIDE(prConnReqInfo->rSsidStruct.aucSsid), + prConnReqInfo->rSsidStruct.ucSsidLen); + DBGLOG(P2P, TRACE, + "Checking SSID:%s, length:%d\n", + HIDE(prBssDesc->aucSSID), prBssDesc->ucSSIDLen); + DBGLOG(P2P, TRACE, "Ignore mismatch SSID, (But BSSID match).\n"); + ASSERT(FALSE); + continue; + } + + if (!prBssDesc->fgIsP2PPresent) { + DBGLOG(P2P, ERROR, "SSID, BSSID, BSSTYPE match, but no P2P IE present.\n"); + continue; + } + + /* Final decision. */ + prCandidateBssDesc = prBssDesc; + break; + } + + } while (FALSE); + + return prCandidateBssDesc; +} /* scanP2pSearchDesc */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_state.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_state.c new file mode 100644 index 0000000000000..c0cc594ebcfd0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/p2p_state.c @@ -0,0 +1,488 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#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; + + do { + ASSERT_BREAK((prAdapter != NULL) && + (prP2pFsmInfo != NULL) && (prP2pBssInfo != NULL) && (peNextState != NULL)); + + cnmTimerStartTimer(prAdapter, &(prAdapter->rP2pFsmTimeoutTimer), P2P_AP_CHNL_HOLD_TIME_MS); + + } while (FALSE); + + return fgIsTransOut; +} /* p2pStateInit_IDLE */ + +VOID p2pStateAbort_IDLE(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN ENUM_P2P_STATE_T eNextState) +{ + + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); + + prChnlReqInfo = &prP2pFsmInfo->rChnlReqInfo; + + if (prChnlReqInfo->fgIsChannelRequested) { + /* Release channel before timeout. */ + p2pFuncReleaseCh(prAdapter, prChnlReqInfo); + } + + /* Stop timer for leaving this state. */ + cnmTimerStopTimer(prAdapter, &(prAdapter->rP2pFsmTimeoutTimer)); + + } while (FALSE); + +} /* p2pStateAbort_IDLE */ + +VOID p2pStateInit_CHNL_ON_HAND(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo, IN P_P2P_FSM_INFO_T prP2pFsmInfo) +{ + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); + + prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); + + /* Store the original channel info. */ + prChnlReqInfo->ucOriChnlNum = prP2pBssInfo->ucPrimaryChannel; + prChnlReqInfo->eOriBand = prP2pBssInfo->eBand; + prChnlReqInfo->eOriChnlSco = prP2pBssInfo->eBssSCO; + + /* RX Probe Request would check primary channel. */ + prP2pBssInfo->ucPrimaryChannel = prChnlReqInfo->ucReqChnlNum; + prP2pBssInfo->eBand = prChnlReqInfo->eBand; + prP2pBssInfo->eBssSCO = prChnlReqInfo->eChnlSco; + + DBGLOG(P2P, TRACE, "start a channel on hand timer.\n"); + if (prP2pFsmInfo->eListenExted != P2P_DEV_EXT_LISTEN_ING) { + UINT_32 u4TimeoutMs = 0; + + if (prP2pFsmInfo->fgIsChannelExtended) + u4TimeoutMs = P2P_CHNL_EXTEND_CHAN_TIME; + else + u4TimeoutMs = prChnlReqInfo->u4MaxInterval; + DBGLOG(P2P, INFO, "Channel on hand timer: %d.\n", u4TimeoutMs); + + cnmTimerStartTimer(prAdapter, &(prAdapter->rP2pFsmTimeoutTimer), + u4TimeoutMs); + + if (prP2pFsmInfo->fgIsChannelExtended == FALSE) { + kalP2PIndicateChannelReady(prAdapter->prGlueInfo, + prChnlReqInfo->u8Cookie, + prChnlReqInfo->ucReqChnlNum, + prChnlReqInfo->eBand, + prChnlReqInfo->eChnlSco, + prChnlReqInfo->u4MaxInterval); + /* Complete channel request */ + complete(&prAdapter->prGlueInfo->rP2pReq); + if (prP2pFsmInfo->rQueuedActionFrame.u2Length > 0) { + kalP2pIndicateQueuedMgmtFrame( + prAdapter->prGlueInfo, + &prP2pFsmInfo->rQueuedActionFrame); + p2pFunCleanQueuedMgmtFrame(prAdapter, + &prP2pFsmInfo->rQueuedActionFrame); + } + } + } else + cnmTimerStartTimer(prAdapter, &(prAdapter->rP2pFsmTimeoutTimer), + (P2P_EXT_LISTEN_TIME_MS - prChnlReqInfo->u4MaxInterval)); + } while (FALSE); + +} /* p2pStateInit_CHNL_ON_HAND */ + +VOID +p2pStateAbort_CHNL_ON_HAND(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_BSS_INFO_T prP2pBssInfo, IN ENUM_P2P_STATE_T eNextState) +{ + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); + if (prP2pFsmInfo->eListenExted != P2P_DEV_EXT_LISTEN_ING && + !prP2pFsmInfo->fgIsChannelExtended && + eNextState == P2P_STATE_CHNL_ON_HAND) + WARN_ON(1); + + prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); + + cnmTimerStopTimer(prAdapter, &(prAdapter->rP2pFsmTimeoutTimer)); + + /* Restore the original channel info. */ + prP2pBssInfo->ucPrimaryChannel = prChnlReqInfo->ucOriChnlNum; + prP2pBssInfo->eBand = prChnlReqInfo->eOriBand; + prP2pBssInfo->eBssSCO = prChnlReqInfo->eOriChnlSco; + + DBGLOG(P2P, INFO, "p2p state trans abort chann on hand, eListenExted: %d, eNextState: %d\n", + prP2pFsmInfo->eListenExted, eNextState); + if (prP2pFsmInfo->eListenExted != P2P_DEV_EXT_LISTEN_ING && + eNextState != P2P_STATE_CHNL_ON_HAND) { + /* + * Here maybe have a bug, when it's extlistening, a new remain_on_channel + * was sent to driver? need to verify + */ + prP2pFsmInfo->eListenExted = P2P_DEV_NOT_EXT_LISTEN; + /* Indicate channel return. */ + kalP2PIndicateChannelExpired(prAdapter->prGlueInfo, &prP2pFsmInfo->rChnlReqInfo); + + /* Return Channel. */ + p2pFuncReleaseCh(prAdapter, &(prP2pFsmInfo->rChnlReqInfo)); + /* case: if supplicant cancel remain on channel */ + complete(&prAdapter->prGlueInfo->rP2pReq); + p2pFunCleanQueuedMgmtFrame(prAdapter, + &prP2pFsmInfo->rQueuedActionFrame); + } + + } while (FALSE); +} /* p2pStateAbort_CHNL_ON_HAND */ + +VOID +p2pStateAbort_REQING_CHANNEL(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN ENUM_P2P_STATE_T eNextState) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL) && (eNextState < P2P_STATE_NUM)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + if (eNextState == P2P_STATE_IDLE) { + if (prP2pBssInfo->eIntendOPMode == OP_MODE_ACCESS_POINT) { + /* Intend to be AP. */ + /* Setup for AP mode. */ + p2pFuncStartGO(prAdapter, + prP2pBssInfo, + prP2pSpecificBssInfo->ucPreferredChannel, + prP2pSpecificBssInfo->eRfBand, + prP2pSpecificBssInfo->eRfSco, + prP2pFsmInfo->fgIsApMode); + + } else { + /* Return Channel. */ + p2pFuncReleaseCh(prAdapter, &(prP2pFsmInfo->rChnlReqInfo)); + /* possible have not acquire channel */ + complete(&prAdapter->prGlueInfo->rP2pReq); + } + + } + + } while (FALSE); + +} /* p2pStateInit_AP_CHANNEL_DETECT */ + +VOID p2pStateInit_AP_CHANNEL_DETECT(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo) +{ + P_P2P_SCAN_REQ_INFO_T prScanReqInfo = (P_P2P_SCAN_REQ_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); + + prScanReqInfo = &(prP2pFsmInfo->rScanReqInfo); + + prScanReqInfo->eScanType = SCAN_TYPE_PASSIVE_SCAN; + prScanReqInfo->eChannelSet = SCAN_CHANNEL_2G4; + prScanReqInfo->u2PassiveDewellTime = 50; /* 50ms for passive channel load detection */ + prScanReqInfo->fgIsAbort = TRUE; + prScanReqInfo->fgIsScanRequest = TRUE; + prScanReqInfo->ucNumChannelList = 0; + prScanReqInfo->u4BufLength = 0; + prScanReqInfo->rSsidStruct.ucSsidLen = 0; + + p2pFuncRequestScan(prAdapter, prScanReqInfo); + + } while (FALSE); + +} /* p2pStateInit_AP_CHANNEL_DETECT */ + +VOID +p2pStateAbort_AP_CHANNEL_DETECT(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo, IN ENUM_P2P_STATE_T eNextState) +{ + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; + + do { + + if (eNextState == P2P_STATE_REQING_CHANNEL) { + UINT_8 ucPreferedChnl = 0; + ENUM_BAND_T eBand = BAND_NULL; + ENUM_CHNL_EXT_T eSco = CHNL_EXT_SCN; + + prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); + + /* Determine the channel for AP. */ + if (cnmPreferredChannel(prAdapter, &eBand, &ucPreferedChnl, &eSco) == FALSE) { + + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + ucPreferedChnl = prP2pConnSettings->ucOperatingChnl; + if (ucPreferedChnl == 0) { + + if (scnQuerySparseChannel(prAdapter, &eBand, &ucPreferedChnl) == FALSE) { + + /* What to do? */ + ASSERT(FALSE); + /* TODO: Pick up a valid channel from channel list. */ + ucPreferedChnl = 1; + eBand = BAND_2G4; + } + } + } + + prChnlReqInfo->eChannelReqType = CHANNEL_REQ_TYPE_GO_START_BSS; + + DBGLOG(P2P, INFO, "p2pStateAbort_AP_CHANNEL_DETECT GO Scan\n"); + prChnlReqInfo->ucReqChnlNum = prP2pSpecificBssInfo->ucPreferredChannel = ucPreferedChnl; + prChnlReqInfo->eBand = prP2pSpecificBssInfo->eRfBand = eBand; + prChnlReqInfo->eChnlSco = prP2pSpecificBssInfo->eRfSco = eSco; + prChnlReqInfo->u4MaxInterval = P2P_AP_CHNL_HOLD_TIME_MS; + } else { + p2pFuncCancelScan(prAdapter, &(prP2pFsmInfo->rScanReqInfo)); + } + + } while (FALSE); + +} /* p2pStateAbort_AP_CHANNEL_DETECT */ + +VOID p2pStateInit_SCAN(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo) +{ + P_P2P_SCAN_REQ_INFO_T prScanReqInfo = (P_P2P_SCAN_REQ_INFO_T) NULL; + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); + + prScanReqInfo = &prP2pFsmInfo->rScanReqInfo; + + prScanReqInfo->fgIsScanRequest = TRUE; + + p2pFuncRequestScan(prAdapter, prScanReqInfo); + + } while (FALSE); + +} /* p2pStateInit_SCAN */ + +VOID p2pStateAbort_SCAN(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN ENUM_P2P_STATE_T eNextState) +{ + do { + ASSERT_BREAK(prAdapter != NULL); + + /* 1. Scan cancel. (Make sure the scan request is invalid. */ + p2pFuncCancelScan(prAdapter, &(prP2pFsmInfo->rScanReqInfo)); + + /* Scan done indication. */ + kalP2PIndicateScanDone(prAdapter->prGlueInfo, prP2pFsmInfo->rScanReqInfo.fgIsAbort); + } while (FALSE); + +} /* p2pStateAbort_SCAN */ + +VOID +p2pStateInit_GC_JOIN(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_BSS_INFO_T prP2pBssInfo, IN P_P2P_JOIN_INFO_T prJoinInfo, IN P_BSS_DESC_T prBssDesc) +{ + P_MSG_JOIN_REQ_T prJoinReqMsg = (P_MSG_JOIN_REQ_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && + (prP2pFsmInfo != NULL) && + (prP2pBssInfo != NULL) && (prJoinInfo != NULL) && (prBssDesc != NULL)); + + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + if (prBssDesc->ucSSIDLen) { + COPY_SSID(prP2pConnSettings->aucSSID, + prP2pConnSettings->ucSSIDLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + } + /* Setup a join timer. */ + DBGLOG(P2P, TRACE, "Start a join init timer\n"); + cnmTimerStartTimer(prAdapter, + &(prAdapter->rP2pFsmTimeoutTimer), + (prP2pFsmInfo->u4GrantInterval - AIS_JOIN_CH_GRANT_THRESHOLD)); + + /* 2 <1> We are goin to connect to this BSS */ + prBssDesc->fgIsConnecting = TRUE; + + /* 2 <2> Setup corresponding STA_RECORD_T */ + prStaRec = bssCreateStaRecFromBssDesc(prAdapter, + (prBssDesc->fgIsP2PPresent ? (STA_TYPE_P2P_GO) + : (STA_TYPE_LEGACY_AP)), NETWORK_TYPE_P2P_INDEX, prBssDesc); + + if (prStaRec == NULL) { + DBGLOG(P2P, TRACE, "Create station record fail\n"); + break; + } + + prJoinInfo->prTargetStaRec = prStaRec; + prJoinInfo->fgIsJoinComplete = FALSE; + prJoinInfo->u4BufLength = 0; + + /* 2 <2.1> Sync. to FW domain */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + if (prP2pBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; + + prStaRec->fgIsReAssoc = FALSE; + + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + switch (prP2pConnSettings->eAuthMode) { + case AUTH_MODE_OPEN: /* Note: Omit break here. */ + case AUTH_MODE_WPA: + case AUTH_MODE_WPA_PSK: + case AUTH_MODE_WPA2: + case AUTH_MODE_WPA2_PSK: + prJoinInfo->ucAvailableAuthTypes = (UINT_8) AUTH_TYPE_OPEN_SYSTEM; + break; + case AUTH_MODE_SHARED: + prJoinInfo->ucAvailableAuthTypes = (UINT_8) AUTH_TYPE_SHARED_KEY; + break; + case AUTH_MODE_AUTO_SWITCH: + DBGLOG(P2P, LOUD, "JOIN INIT: eAuthMode == AUTH_MODE_AUTO_SWITCH\n"); + prJoinInfo->ucAvailableAuthTypes = (UINT_8) (AUTH_TYPE_OPEN_SYSTEM | + AUTH_TYPE_SHARED_KEY); + break; + default: + ASSERT(!(prP2pConnSettings->eAuthMode == AUTH_MODE_WPA_NONE)); + DBGLOG(P2P, ERROR, "JOIN INIT: Auth Algorithm : %d was not supported by JOIN\n", + prP2pConnSettings->eAuthMode); + /* TODO(Kevin): error handling ? */ + return; + } + prStaRec->ucTxAuthAssocRetryLimit = TX_AUTH_ASSOCI_RETRY_LIMIT; + } else { + ASSERT(FALSE); + /* TODO: Shall we considering ROAMIN case for P2P Device?. */ + } + + /* 2 <4> Use an appropriate Authentication Algorithm Number among the ucAvailableAuthTypes. */ + if (prJoinInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_OPEN_SYSTEM) { + + DBGLOG(P2P, TRACE, "JOIN INIT: Try to do Authentication with AuthType == OPEN_SYSTEM.\n"); + + prJoinInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_OPEN_SYSTEM; + + prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_OPEN_SYSTEM; + } else if (prJoinInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_SHARED_KEY) { + + DBGLOG(P2P, TRACE, "JOIN INIT: Try to do Authentication with AuthType == SHARED_KEY.\n"); + + prJoinInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_SHARED_KEY; + + prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_SHARED_KEY; + } else if (prJoinInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_FAST_BSS_TRANSITION) { + + DBGLOG(P2P, TRACE, + "JOIN INIT: Try to do Authentication with AuthType == FAST_BSS_TRANSITION.\n"); + + prJoinInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_FAST_BSS_TRANSITION; + + prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION; + } else { + ASSERT(0); + } + + /* 4 <5> Overwrite Connection Setting for eConnectionPolicy == ANY (Used by Assoc Req) */ + if (prBssDesc->ucSSIDLen) { + COPY_SSID(prJoinInfo->rSsidStruct.aucSsid, + prJoinInfo->rSsidStruct.ucSsidLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + } + /* 2 <5> Backup desired channel. */ + + /* 2 <6> Send a Msg to trigger SAA to start JOIN process. */ + prJoinReqMsg = (P_MSG_JOIN_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_REQ_T)); + + if (!prJoinReqMsg) { + DBGLOG(P2P, TRACE, "Allocation Join Message Fail\n"); + ASSERT(FALSE); + return; + } + + prJoinReqMsg->rMsgHdr.eMsgId = MID_P2P_SAA_FSM_START; + prJoinReqMsg->ucSeqNum = ++prJoinInfo->ucSeqNumOfReqMsg; + prJoinReqMsg->prStaRec = prStaRec; + + /* TODO: Consider fragmentation info in station record. */ + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinReqMsg, MSG_SEND_METHOD_BUF); + + } while (FALSE); + +} /* p2pStateInit_GC_JOIN */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process of JOIN Abort. Leave JOIN State & Abort JOIN. +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pStateAbort_GC_JOIN(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN P_P2P_JOIN_INFO_T prJoinInfo, IN ENUM_P2P_STATE_T eNextState) +{ + P_MSG_JOIN_ABORT_T prJoinAbortMsg = (P_MSG_JOIN_ABORT_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL) && (prJoinInfo != NULL)); + + if (prJoinInfo->fgIsJoinComplete == FALSE) { + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; + + 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; + + /* Reset the flag to clear target BSS state */ + prBssDesc = prP2pFsmInfo->prTargetBss; + if (prBssDesc != NULL) + prBssDesc->fgIsConnecting = FALSE; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinAbortMsg, MSG_SEND_METHOD_BUF); + + } + + /* Stop Join Timer. */ + cnmTimerStopTimer(prAdapter, &(prAdapter->rP2pFsmTimeoutTimer)); + + /* Release channel requested. */ + p2pFuncReleaseCh(prAdapter, &(prP2pFsmInfo->rChnlReqInfo)); + + } while (FALSE); + + return; + +} /* p2pStateAbort_GC_JOIN */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/privacy.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/privacy.c new file mode 100644 index 0000000000000..6ec54d4e84956 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/privacy.c @@ -0,0 +1,905 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E 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; + prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[8].dot11RSNAConfigPairwiseCipher = + RSN_CIPHER_SUITE_GROUP_NOT_USED; + + 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; + + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[6].dot11RSNAConfigAuthenticationSuite = + RSN_AKM_SUITE_FT_802_1X; + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[7].dot11RSNAConfigAuthenticationSuite = + RSN_AKM_SUITE_FT_PSK; + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[8].dot11RSNAConfigAuthenticationSuite = + WFA_AKM_SUITE_OSEN; + +#if CFG_SUPPORT_802_11W + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[9].dot11RSNAConfigAuthenticationSuite = + RSN_AKM_SUITE_802_1X_SHA256; + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[10].dot11RSNAConfigAuthenticationSuite = + RSN_AKM_SUITE_PSK_SHA256; + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[11].dot11RSNAConfigAuthenticationSuite = + RSN_CIPHER_SUITE_SAE; + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[12].dot11RSNAConfigAuthenticationSuite = + RSN_CIPHER_SUITE_OWE; +#else + +#endif + + for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) { + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[i].dot11RSNAConfigAuthenticationSuiteEnabled = + FALSE; + } +#if (CFG_REFACTORY_PMKSA == 0) + secClearPmkid(prAdapter); + + cnmTimerInitTimer(prAdapter, + &prAisSpecBssInfo->rPreauthenticationTimer, + (PFN_MGMT_TIMEOUT_FUNC) rsnIndicatePmkidCand, (ULONG) NULL); +#endif +#if CFG_SUPPORT_802_11W + cnmTimerInitTimer(prAdapter, + &prAisSpecBssInfo->rSaQueryTimer, (PFN_MGMT_TIMEOUT_FUNC) rsnStartSaQueryTimer, (ULONG) NULL); +#endif + + prAisSpecBssInfo->fgCounterMeasure = FALSE; + prAisSpecBssInfo->ucWEPDefaultKeyID = 0; + +#if 0 + for (i = 0; i < WTBL_SIZE; i++) { + g_prWifiVar->arWtbl[i].fgUsed = FALSE; + g_prWifiVar->arWtbl[i].prSta = NULL; + g_prWifiVar->arWtbl[i].ucNetTypeIdx = NETWORK_TYPE_INDEX_NUM; + + } + nicPrivacyInitialize((UINT_8) NETWORK_TYPE_INDEX_NUM); +#endif +} /* secInit */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will indicate an Event of "Rx Class Error" to SEC_FSM for +* JOIN Module. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] prSwRfb Pointer to the SW RFB. +* +* \return FALSE Class Error +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN secCheckClassError(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN P_STA_RECORD_T prStaRec) +{ + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex; + P_BSS_INFO_T prBssInfo; + P_SW_RFB_T prCurrSwRfb; + P_HIF_RX_HEADER_T prHifRxHdr; + UINT_16 u2PktTmpLen; + + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_DESC_T prBssDesc; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + if (!prStaRec) + return FALSE; + + eNetTypeIndex = prStaRec->ucNetTypeIndex; + if (!IS_NET_ACTIVE(prAdapter, eNetTypeIndex)) + return FALSE; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]; + if ((prStaRec->ucStaState != STA_STATE_3) && prBssInfo->fgIsNetAbsent == FALSE) { + /*(IS_AP_STA(prStaRec) || IS_CLIENT_STA(prStaRec))) { */ + +#if 0 /* by scott's suggestions, do not put work-around in JB2,we need to find the root cause */ + /* work-around for CR ALPS00816361 */ + if (eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + DBGLOG(RSN, INFO, + "p2p> skip to send Deauth to MAC:[%pM] for Rx Class 3.\n", + prStaRec->aucMacAddr); + return TRUE; + } +#endif + /* Skip to send deaut to AP which STA is connecting */ + if (eNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prBssDesc = prAisFsmInfo->prTargetBssDesc; + if ((prBssDesc->fgIsConnected == TRUE || prBssDesc->fgIsConnecting == TRUE) + && EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prStaRec->aucMacAddr)) { + DBGLOG(RSN, INFO, "Skip to send Deauth to MAC:[%pM] for Rx Class 3", + prStaRec->aucMacAddr); + return TRUE; + } + } + + if (authSendDeauthFrame(prAdapter, + prStaRec, + NULL, + REASON_CODE_CLASS_3_ERR, + (PFN_TX_DONE_HANDLER) NULL) == WLAN_STATUS_SUCCESS) + DBGLOG(RSN, INFO, "Send Deauth to [ %pM ] for Rx Class 3 Error.\n", + prStaRec->aucMacAddr); + else + DBGLOG(RSN, INFO, "Host sends Deauth to [ %pM ] for Rx Class 3 fail.\n", + prStaRec->aucMacAddr); + DBGLOG(RSN, WARN, "received class 3 data frame !!!"); + + /* dump Rx Pkt */ + prCurrSwRfb = prSwRfb; + + prHifRxHdr = prCurrSwRfb->prHifRxHdr; + + DBGLOG(SW4, WARN, "QM RX DATA: net %u sta idx %u wlan idx %u ssn %u tid %u ptype %u 11 %u\n", + (UINT_32) HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr), + prHifRxHdr->ucStaRecIdx, prCurrSwRfb->ucWlanIdx, + (UINT_32) HIF_RX_HDR_GET_SN(prHifRxHdr), /* The new SN of the frame */ + (UINT_32) HIF_RX_HDR_GET_TID(prHifRxHdr), + prCurrSwRfb->ucPacketType, + (UINT_32) HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)); + + u2PktTmpLen = prCurrSwRfb->u2PacketLen; + if (u2PktTmpLen > 48) + u2PktTmpLen = 48; + + dumpMemory8((PUINT_8) prCurrSwRfb->pvHeader, u2PktTmpLen); + + return FALSE; + } + + return secRxPortControlCheck(prAdapter, prSwRfb); +} /* end of secCheckClassError() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to setting the sta port status. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] prSta Pointer to the sta +* \param[in] fgPortBlock The port status +* +* \retval none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID secSetPortBlocked(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta, IN BOOLEAN fgPortBlock) +{ + if (prSta == NULL) + return; + + prSta->fgPortBlock = fgPortBlock; + + DBGLOG(RSN, TRACE, + "The STA %pM port %s\n", prSta->aucMacAddr, fgPortBlock == TRUE ? "BLOCK" : " OPEN"); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to report the sta port status. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] prSta Pointer to the sta +* \param[out] fgPortBlock The port status +* +* \return TRUE sta exist, FALSE sta not exist +* +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN secGetPortStatus(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta, OUT PBOOLEAN pfgPortStatus) +{ + if (prSta == NULL) + return FALSE; + + *pfgPortStatus = prSta->fgPortBlock; + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to handle Peer device Tx Security process MSDU. +* +* \param[in] prMsduInfo pointer to the packet info pointer +* +* \retval TRUE Accept the packet +* \retval FALSE Refuse the MSDU packet due port blocked +* +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN /* ENUM_PORT_CONTROL_RESULT */ +secTxPortControlCheck(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN P_STA_RECORD_T prStaRec) +{ + ASSERT(prAdapter); + ASSERT(prMsduInfo); + ASSERT(prStaRec); + + if (prStaRec) { + + /* Todo:: */ + if (prMsduInfo->fgIs802_1x) + return TRUE; + + if (prStaRec->fgPortBlock == TRUE) { + DBGLOG(SEC, TRACE, "Drop Tx packet due Port Control!\n"); + return FALSE; + } +#if CFG_SUPPORT_WAPI + if (prAdapter->rWifiVar.rConnSettings.fgWapiMode) + return TRUE; +#endif + if (IS_STA_IN_AIS(prStaRec)) { + if (!prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist && + (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION1_ENABLED)) { + DBGLOG(SEC, TRACE, "Drop Tx packet due the key is removed!!!\n"); + return FALSE; + } + } + } + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to handle The Rx Security process MSDU. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] prSWRfb SW rfb pinter +* +* \retval TRUE Accept the packet +* \retval FALSE Refuse the MSDU packet due port control +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN secRxPortControlCheck(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSWRfb) +{ + ASSERT(prSWRfb); + +#if 0 + /* whsu:Todo: Process MGMT and DATA */ + if (prSWRfb->prStaRec) { + if (prSWRfb->prStaRec->fgPortBlock == TRUE) { + if (1 /* prSWRfb->fgIsDataFrame and not 1x */ && + (g_prWifiVar->rConnSettings.eAuthMode >= AUTH_MODE_WPA)) { + /* DBGLOG(SEC, WARN, ("Drop Rx data due port control !\r\n")); */ + return TRUE; /* Todo: whsu FALSE; */ + } + /* if (!RX_STATUS_IS_PROTECT(prSWRfb->prRxStatus)) { */ + /* DBGLOG(RSN, WARN, ("Drop rcv non-encrypted data frame!\n")); */ + /* return FALSE; */ + /* } */ + } + } else { + } +#endif + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine will enable/disable the cipher suite +* +* \param[in] prAdapter Pointer to the adapter object data area. +* \param[in] u4CipherSuitesFlags flag for cipher suite +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID secSetCipherSuite(IN P_ADAPTER_T prAdapter, IN UINT_32 u4CipherSuitesFlags) +{ + UINT_32 i; + P_DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY prEntry; + P_IEEE_802_11_MIB_T prMib; + + ASSERT(prAdapter); + + prMib = &prAdapter->rMib; + + ASSERT(prMib); + + if (u4CipherSuitesFlags == CIPHER_FLAG_NONE) { + /* Disable all the pairwise cipher suites. */ + for (i = 0; i < MAX_NUM_SUPPORTED_CIPHER_SUITES; i++) + prMib->dot11RSNAConfigPairwiseCiphersTable[i].dot11RSNAConfigPairwiseCipherEnabled = FALSE; + + /* Update the group cipher suite. */ + prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_NONE; + + return; + } + + for (i = 0; i < MAX_NUM_SUPPORTED_CIPHER_SUITES; i++) { + prEntry = &prMib->dot11RSNAConfigPairwiseCiphersTable[i]; + + switch (prEntry->dot11RSNAConfigPairwiseCipher) { + case WPA_CIPHER_SUITE_WEP40: + case RSN_CIPHER_SUITE_WEP40: + if (u4CipherSuitesFlags & CIPHER_FLAG_WEP40) + prEntry->dot11RSNAConfigPairwiseCipherEnabled = TRUE; + else + prEntry->dot11RSNAConfigPairwiseCipherEnabled = FALSE; + break; + + case WPA_CIPHER_SUITE_TKIP: + case RSN_CIPHER_SUITE_TKIP: + if (u4CipherSuitesFlags & CIPHER_FLAG_TKIP) + prEntry->dot11RSNAConfigPairwiseCipherEnabled = TRUE; + else + prEntry->dot11RSNAConfigPairwiseCipherEnabled = FALSE; + break; + + case WPA_CIPHER_SUITE_CCMP: + case RSN_CIPHER_SUITE_CCMP: + if (u4CipherSuitesFlags & CIPHER_FLAG_CCMP) + prEntry->dot11RSNAConfigPairwiseCipherEnabled = TRUE; + else + prEntry->dot11RSNAConfigPairwiseCipherEnabled = FALSE; + break; + case RSN_CIPHER_SUITE_GROUP_NOT_USED: + if (u4CipherSuitesFlags & (CIPHER_FLAG_CCMP | CIPHER_FLAG_TKIP)) + 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 if (rsnSearchSupportedCipher(prAdapter, RSN_CIPHER_SUITE_GROUP_NOT_USED, &i)) + prMib->dot11RSNAConfigGroupCipher = RSN_CIPHER_SUITE_GROUP_NOT_USED; + else + prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_NONE; + +} /* secSetCipherSuite */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to handle The 2nd Tx EAPoL Frame. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] prMsduInfo pointer to the packet info pointer +* \param[in] pucPayload pointer to the 1x hdr +* \param[in] u2PayloadLen the 1x payload length +* +* \retval TRUE Accept the packet +* \retval FALSE Refuse the MSDU packet due port control +* +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +secProcessEAPOL(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN P_STA_RECORD_T prStaRec, IN PUINT_8 pucPayload, IN UINT_16 u2PayloadLen) +{ + P_EAPOL_KEY prEapol = (P_EAPOL_KEY) NULL; + P_IEEE_802_1X_HDR pr1xHdr; + UINT_16 u2KeyInfo; + + ASSERT(prMsduInfo); + ASSERT(prStaRec); + + /* prStaRec = &(g_arStaRec[prMsduInfo->ucStaRecIndex]); */ + ASSERT(prStaRec); + + if (prStaRec && IS_AP_STA(prStaRec)) { + pr1xHdr = (P_IEEE_802_1X_HDR) pucPayload; + if ((pr1xHdr->ucType == 3) /* EAPoL key */ && ((u2PayloadLen - 4) > sizeof(EAPOL_KEY))) { + prEapol = (P_EAPOL_KEY) ((PUINT_32) (pucPayload + 4)); + WLAN_GET_FIELD_BE16(prEapol->aucKeyInfo, &u2KeyInfo); + if ((prEapol->ucType == 254) && (u2KeyInfo & MASK_2ND_EAPOL)) { + if (u2KeyInfo & WPA_KEY_INFO_SECURE) { + /* 4th EAPoL check at secHandleTxDoneCallback() */ + /* DBGLOG(RSN, TRACE, ("Tx 4th EAPoL frame\r\n")); */ + } else if (u2PayloadLen == 123 /* Not include LLC */) { + DBGLOG(RSN, INFO, "Tx 2nd EAPoL frame\r\n"); + secFsmEvent2ndEapolTx(prAdapter, prStaRec); + } + } + } + } + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will handle the 4th EAPoL Tx done and mic Error Report frame. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pMsduInfo Pointer to the Msdu Info +* \param[in] rStatus The Tx done status +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +VOID +secHandleTxDoneCallback(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN P_STA_RECORD_T prStaRec, IN WLAN_STATUS rStatus) +{ + PUINT_8 pucPayload; + P_IEEE_802_1X_HDR pr1xHdr = (P_IEEE_802_1X_HDR) NULL; + P_EAPOL_KEY prEapol = (P_EAPOL_KEY) NULL; + UINT_16 u2KeyInfo; + UINT_16 u2PayloadLen; + + DEBUGFUNC("secHandleTxDoneCallback"); + + ASSERT(prMsduInfo); + /* Todo:: Notice if using the TX free immediate after send to firmware, the payload may not correcttly!!!! */ + + ASSERT(prStaRec); + + /* Todo:: This call back may not need because the order of set key and send 4th 1x can be make sure */ + /* Todo:: Notice the LLC offset */ +#if 1 + pucPayload = (PUINT_8) prMsduInfo->prPacket; + ASSERT(pucPayload); + + u2PayloadLen = prMsduInfo->u2FrameLength; + + if (0 /* prMsduInfo->fgIs1xFrame */) { + + if (prStaRec && IS_AP_STA(prStaRec)) { + pr1xHdr = (P_IEEE_802_1X_HDR) (PUINT_32) (pucPayload + 8); + if ((pr1xHdr->ucType == 3) /* EAPoL key */ && ((u2PayloadLen - 4) > sizeof(EAPOL_KEY))) { + prEapol = (P_EAPOL_KEY) (PUINT_32) (pucPayload + 12); + WLAN_GET_FIELD_BE16(prEapol->aucKeyInfo, &u2KeyInfo); + if ((prEapol->ucType == 254) && (u2KeyInfo & MASK_2ND_EAPOL)) { + if (prStaRec->rSecInfo.fg2nd1xSend == TRUE + && u2PayloadLen == + 107 /* include LLC *//* u2KeyInfo & WPA_KEY_INFO_SECURE */) { + DBGLOG(RSN, INFO, "Tx 4th EAPoL frame\r\n"); + secFsmEvent4ndEapolTxDone(prAdapter, prStaRec); + } else if (prAdapter->rWifiVar.rAisSpecificBssInfo.fgCheckEAPoLTxDone) { + DBGLOG(RSN, INFO, "Tx EAPoL Error report frame\r\n"); + /* secFsmEventEapolTxDone(prAdapter, (UINT_32)prMsduInfo->prStaRec); */ + } + } + } + } + + } +#endif +} + +#if (CFG_REFACTORY_PMKSA == 0) +/*----------------------------------------------------------------------------*/ +/*! +* \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); +} +#endif +/*----------------------------------------------------------------------------*/ +/*! +* \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 */ + +BOOLEAN secWpaEnabledInAis(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: + case ENUM_ENCRYPTION1_ENABLED: + return FALSE; + 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; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the privacy bit at mac header for TxM +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] prMsdu the msdu for known the sta record +* +* \return TRUE the privacy need to set +* FALSE the privacy no need to set +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN secIsProtectedFrame(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsdu, IN P_STA_RECORD_T prStaRec) +{ + ASSERT(prAdapter); + + ASSERT(prMsdu); + + ASSERT(prStaRec); + /* prStaRec = &(g_arStaRec[prMsdu->ucStaRecIndex]); */ + + if (prStaRec == NULL) { + if (prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist) + return TRUE; + return FALSE; /* No privacy bit */ + } + + /* Todo:: */ + if (0 /* prMsdu->fgIs1xFrame */) { + if (IS_STA_IN_AIS(prStaRec) && prAdapter->rWifiVar.rConnSettings.eAuthMode < AUTH_MODE_WPA) { + DBGLOG(RSN, LOUD, "For AIS Legacy 1x, always not encryped\n"); + return FALSE; + } else if (!prStaRec->fgTransmitKeyExist) { + DBGLOG(RSN, LOUD, "1x Not Protected.\n"); + return FALSE; + } else if (prStaRec->rSecInfo.fgKeyStored) { + DBGLOG(RSN, LOUD, "1x not Protected due key stored!\n"); + return FALSE; + } + DBGLOG(RSN, LOUD, "1x Protected.\n"); + return TRUE; + } + if (!prStaRec->fgTransmitKeyExist) { + /* whsu , check for AIS only */ + if (prAdapter->rWifiVar.rConnSettings.eAuthMode < AUTH_MODE_WPA && + prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist) { + DBGLOG(RSN, LOUD, "Protected\n"); + return TRUE; + } + } else { + DBGLOG(RSN, LOUD, "Protected.\n"); + return TRUE; + } + + /* No sec or key is removed!!! */ + return FALSE; +} + +VOID secHandleEapolTxStatus(ADAPTER_T *prAdapter, UINT_8 *pucEvtBuf) +{ + EVENT_TX_DONE_STATUS_T *prTxDone; + UINT_8 status; + PUINT_8 pucPkt; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + enum ENUM_EAPOL_KEY_TYPE_T keyType; + + do { + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + /* TODO: only handle p2p case */ + if (prP2pBssInfo->eConnectionState != PARAM_MEDIA_STATE_CONNECTED || + prP2pBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + break; + prTxDone = (EVENT_TX_DONE_STATUS_T *) pucEvtBuf; + pucPkt = &prTxDone->aucPktBuf[64]; + status = prTxDone->ucStatus; + keyType = secGetEapolKeyType(pucPkt); + if (keyType == EAPOL_KEY_4_OF_4) { + if (status == 0) { + DBGLOG(RSN, INFO, "EAPOL key 4/4 TX success\n"); + prP2pBssInfo->eKeyAction = SEC_TX_KEY_COMMAND; + } else { + DBGLOG(RSN, INFO, "EAPOL key 4/4 TX fail\n"); + prP2pBssInfo->eKeyAction = SEC_DROP_KEY_COMMAND; + } + kalSetEvent(prAdapter->prGlueInfo); + } + } while (FALSE); + +} + +/* return the type of EAPOL frame. */ +enum ENUM_EAPOL_KEY_TYPE_T secGetEapolKeyType(PUINT_8 pucPkt) +{ + UINT_16 u2EtherType = 0; + PUINT_8 pucEthBody = NULL; + PUINT_8 pucEapol = NULL; + UINT_16 u2KeyInfo = 0; + UINT_8 ucEapolType; + + do { + ASSERT_BREAK(pucPkt != NULL); + u2EtherType = (pucPkt[ETH_TYPE_LEN_OFFSET] << 8) | (pucPkt[ETH_TYPE_LEN_OFFSET + 1]); + pucEthBody = &pucPkt[ETH_HLEN]; + if (u2EtherType != ETH_P_1X) + break; + pucEapol = pucEthBody; + ucEapolType = pucEapol[1]; + /* + * EAPOL type: + * 0: eap packet + * 1: eapol start + * 3: eapol key + */ + if (ucEapolType != 3) + break; + u2KeyInfo = pucEapol[5] << 8 | pucEapol[6]; + if (u2KeyInfo == 0x008a) + return EAPOL_KEY_1_OF_4; + else if (u2KeyInfo == 0x010a) + return EAPOL_KEY_2_OF_4; + else if (u2KeyInfo == 0x13ca) + return EAPOL_KEY_3_OF_4; + else if (u2KeyInfo == 0x030a) + return EAPOL_KEY_4_OF_4; + } while (FALSE); + + return EAPOL_KEY_NOT_KEY; +} + +VOID secHandleTxStatus(ADAPTER_T *prAdapter, UINT_8 *pucEvtBuf) +{ + STATS_TX_PKT_DONE_INFO_DISPLAY(prAdapter, pucEvtBuf); +#if CFG_SUPPORT_P2P_EAP_FAIL_WORKAROUND + p2pFuncEAPfailureWorkaround(prAdapter, pucEvtBuf); +#endif + secHandleEapolTxStatus(prAdapter, pucEvtBuf); + p2pFsmNotifyTxStatus(prAdapter, pucEvtBuf); +} + +VOID secHandleRxEapolPacket(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prRetSwRfb, + IN P_STA_RECORD_T prStaRec) +{ + enum ENUM_EAPOL_KEY_TYPE_T eKeyType; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + do { + if (prRetSwRfb->u2PacketLen <= ETHER_HEADER_LEN) + break; + + if (!prStaRec) { + DBGLOG(RSN, ERROR, "can NOT get prStaRec\n"); + break; + } + if (prStaRec->ucNetTypeIndex >= NETWORK_TYPE_INDEX_NUM) { + DBGLOG(RSN, ERROR, "invalid ucNetTypeIndex\n"); + break; + } + /* TODO: only handle p2p case */ + if (prStaRec->ucNetTypeIndex != NETWORK_TYPE_P2P_INDEX) + break; + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + if (prP2pBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE || + prP2pBssInfo->eConnectionState != PARAM_MEDIA_STATE_CONNECTED) + break; + + eKeyType = secGetEapolKeyType((PUINT_8) prRetSwRfb->pvHeader); + if (eKeyType != EAPOL_KEY_3_OF_4) + break; + DBGLOG(RSN, INFO, "RX EAPOL 3/4 key\n"); + prP2pBssInfo->eKeyAction = SEC_QUEUE_KEY_COMMAND; + } while (FALSE); +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/qosmap.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/qosmap.c new file mode 100644 index 0000000000000..4868176c96d07 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/qosmap.c @@ -0,0 +1,224 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E 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_PPR2 + +/******************************************************************************* +* 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 process the qos category action frame. +* +* +* \note +* Called by: Handle Rx mgmt request +*/ +/*----------------------------------------------------------------------------*/ +VOID handleQosMapConf(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; + + switch (prRxFrame->ucAction) { + case ACTION_ADDTS_REQ: + case ACTION_ADDTS_RSP: + case ACTION_SCHEDULE: + DBGLOG(INIT, INFO, "qos action frame received, action: %d\n", prRxFrame->ucAction); + break; + case ACTION_QOS_MAP_CONFIGURE: + qosHandleQosMapConfigure(prAdapter, prSwRfb); + DBGLOG(INIT, INFO, "qos map configure frame received, action: %d\n", prRxFrame->ucAction); + break; + default: + DBGLOG(INIT, INFO, "qos action frame: %d, try to send to supplicant\n", prRxFrame->ucAction); + break; + } +} + +int qosHandleQosMapConfigure(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + struct _ACTION_QOS_MAP_CONFIGURE_FRAME *prRxFrame = NULL; + P_STA_RECORD_T prStaRec; + + prRxFrame = (struct _ACTION_QOS_MAP_CONFIGURE_FRAME *) prSwRfb->pvHeader; + if (!prRxFrame) + return -1; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if ((!prStaRec) || (!prStaRec->fgIsInUse)) + return -1; + + DBGLOG(INIT, INFO, "IEEE 802.11: Received Qos Map Configure Frame from " MACSTR "\n", + MAC2STR(prStaRec->aucMacAddr)); + + qosParseQosMapSet(prAdapter, prStaRec, prRxFrame->qosMapSet); + + return 0; +} + +VOID qosParseQosMapSet(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN PUINT_8 qosMapSet) +{ + UINT_8 dscpExcNum = 0; + int i = 0; + PUINT_8 tempq = qosMapSet + 2; + PUINT_8 qosmapping = prStaRec->qosMapSet; + UINT_8 excTable[64]; + + if (IE_ID(qosMapSet) != ELEM_ID_QOS_MAP_SET) { + DBGLOG(INIT, WARN, "Wrong QosMapSet IE ID: %d\n", IE_ID(qosMapSet)); + return; + } + if ((IE_LEN(qosMapSet) < 16) || (IE_LEN(qosMapSet) > 58)) { + DBGLOG(INIT, WARN, "Error in QosMapSet IE len: %d\n", IE_LEN(qosMapSet)); + return; + } + + qosMapSetInit(prStaRec); + kalMemSet(excTable, 0, 64); + dscpExcNum = (IE_LEN(qosMapSet) - WMM_UP_INDEX_NUM * 2) / 2; + + for (i = 0; i < dscpExcNum; i++) { + UINT_8 dscp = *tempq++; + UINT_8 up = *tempq++; + + if (dscp < 64 && up < WMM_UP_INDEX_NUM) { + qosmapping[dscp] = up; + excTable[dscp] = TRUE; + } + } + + for (i = 0; i < WMM_UP_INDEX_NUM; i++) { + UINT_8 lDscp = *tempq++; + UINT_8 hDscp = *tempq++; + UINT_8 dscp; + + if (lDscp == 255 && hDscp == 255) { + DBGLOG(INIT, WARN, "UP %d is not used\n", i); + continue; + } + + if (hDscp < lDscp) { + DBGLOG(INIT, WARN, "CHECK: UP %d, h %d, l %d\n", + i, hDscp, lDscp); + continue; + } + + for (dscp = lDscp; dscp < 64 && dscp <= hDscp; dscp++) { + if (!excTable[dscp]) + qosmapping[dscp] = i; + } + } + + DBGLOG(INIT, INFO, "QosMapSet DSCP Exception number: %d\n", dscpExcNum); +} + +VOID qosMapSetInit(IN P_STA_RECORD_T prStaRec) +{ + /* DSCP to UP maaping based on RFC8325 in the range 0 to 63 */ + static UINT_8 dscp2up[64] = { + [0 ... 63] = 0xFF, + [0] = WMM_UP_BE_INDEX, + [8] = WMM_UP_BK_INDEX, + [10] = WMM_UP_BE_INDEX, + [12] = WMM_UP_BE_INDEX, + [14] = WMM_UP_BE_INDEX, + [16] = WMM_UP_BE_INDEX, + [18] = WMM_UP_EE_INDEX, + [20] = WMM_UP_EE_INDEX, + [22] = WMM_UP_EE_INDEX, + [24] = WMM_UP_CL_INDEX, + [26] = WMM_UP_CL_INDEX, + [28] = WMM_UP_CL_INDEX, + [30] = WMM_UP_CL_INDEX, + [32] = WMM_UP_CL_INDEX, + [34] = WMM_UP_CL_INDEX, + [36] = WMM_UP_CL_INDEX, + [38] = WMM_UP_CL_INDEX, + [40] = WMM_UP_VI_INDEX, + [44] = WMM_UP_VO_INDEX, + [46] = WMM_UP_VO_INDEX, + [48] = WMM_UP_VO_INDEX, + [56] = WMM_UP_NC_INDEX, + }; + + kalMemCopy(prStaRec->qosMapSet, dscp2up, 64); +} + +UINT_8 getUpFromDscp(IN P_GLUE_INFO_T prGlueInfo, IN int type, IN int dscp) +{ + P_BSS_INFO_T prAisBssInfo; + P_STA_RECORD_T prStaRec; + + prAisBssInfo = &(prGlueInfo->prAdapter->rWifiVar.arBssInfo[type]); + if (prAisBssInfo) + prStaRec = prAisBssInfo->prStaRecOfAP; + else + return 0xFF; + + if (prStaRec && dscp < 64) + return prStaRec->qosMapSet[dscp]; + + return 0xFF; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/rate.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/rate.c new file mode 100644 index 0000000000000..e1456b34c2309 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/rate.c @@ -0,0 +1,447 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* The list of valid data rates. */ +const UINT_8 aucDataRate[] = { + RATE_1M, /* RATE_1M_INDEX = 0 */ + RATE_2M, /* RATE_2M_INDEX */ + RATE_5_5M, /* RATE_5_5M_INDEX */ + RATE_11M, /* RATE_11M_INDEX */ + RATE_22M, /* RATE_22M_INDEX */ + RATE_33M, /* RATE_33M_INDEX */ + RATE_6M, /* RATE_6M_INDEX */ + RATE_9M, /* RATE_9M_INDEX */ + RATE_12M, /* RATE_12M_INDEX */ + RATE_18M, /* RATE_18M_INDEX */ + RATE_24M, /* RATE_24M_INDEX */ + RATE_36M, /* RATE_36M_INDEX */ + RATE_48M, /* RATE_48M_INDEX */ + RATE_54M, /* RATE_54M_INDEX */ + RATE_HT_PHY /* RATE_HT_PHY_INDEX */ +}; + +static const UINT_8 aucDefaultAckCtsRateIndex[RATE_NUM] = { + RATE_1M_INDEX, /* RATE_1M_INDEX = 0 */ + RATE_2M_INDEX, /* RATE_2M_INDEX */ + RATE_5_5M_INDEX, /* RATE_5_5M_INDEX */ + RATE_11M_INDEX, /* RATE_11M_INDEX */ + RATE_1M_INDEX, /* RATE_22M_INDEX - Not supported */ + RATE_1M_INDEX, /* RATE_33M_INDEX - Not supported */ + RATE_6M_INDEX, /* RATE_6M_INDEX */ + RATE_6M_INDEX, /* RATE_9M_INDEX */ + RATE_12M_INDEX, /* RATE_12M_INDEX */ + RATE_12M_INDEX, /* RATE_18M_INDEX */ + RATE_24M_INDEX, /* RATE_24M_INDEX */ + RATE_24M_INDEX, /* RATE_36M_INDEX */ + RATE_24M_INDEX, /* RATE_48M_INDEX */ + RATE_24M_INDEX /* RATE_54M_INDEX */ +}; + +const BOOLEAN afgIsOFDMRate[RATE_NUM] = { + FALSE, /* RATE_1M_INDEX = 0 */ + FALSE, /* RATE_2M_INDEX */ + FALSE, /* RATE_5_5M_INDEX */ + FALSE, /* RATE_11M_INDEX */ + FALSE, /* RATE_22M_INDEX - Not supported */ + FALSE, /* RATE_33M_INDEX - Not supported */ + TRUE, /* RATE_6M_INDEX */ + TRUE, /* RATE_9M_INDEX */ + TRUE, /* RATE_12M_INDEX */ + TRUE, /* RATE_18M_INDEX */ + TRUE, /* RATE_24M_INDEX */ + TRUE, /* RATE_36M_INDEX */ + TRUE, /* RATE_48M_INDEX */ + TRUE /* RATE_54M_INDEX */ +}; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief Convert the given Supported Rate & Extended Supported Rate IE to the +* Operational Rate Set and Basic Rate Set, and also check if any Basic +* Rate Code is unknown by driver. +* +* @param[in] prIeSupportedRate Pointer to the Supported Rate IE +* @param[in] prIeExtSupportedRate Pointer to the Ext Supported Rate IE +* @param[out] pu2OperationalRateSet Pointer to the Operational Rate Set +* @param[out] pu2BSSBasicRateSet Pointer to the Basic Rate Set +* @param[out] pfgIsUnknownBSSBasicRate Pointer to a Flag to indicate that Basic +* Rate Set has unknown Rate Code +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +rateGetRateSetFromIEs(IN P_IE_SUPPORTED_RATE_T prIeSupportedRate, + IN P_IE_EXT_SUPPORTED_RATE_T prIeExtSupportedRate, + OUT PUINT_16 pu2OperationalRateSet, + OUT PUINT_16 pu2BSSBasicRateSet, OUT PBOOLEAN pfgIsUnknownBSSBasicRate) +{ + UINT_16 u2OperationalRateSet = 0; + UINT_16 u2BSSBasicRateSet = 0; + BOOLEAN fgIsUnknownBSSBasicRate = FALSE; + UINT_8 ucRate; + UINT_32 i, j; + + ASSERT(pu2OperationalRateSet); + ASSERT(pu2BSSBasicRateSet); + ASSERT(pfgIsUnknownBSSBasicRate); + + if (prIeSupportedRate) { + /* NOTE(Kevin): Buffalo WHR-G54S's supported rate set IE exceed 8. + * IE_LEN(pucIE) == 12, "1(B), 2(B), 5.5(B), 6(B), 9(B), 11(B), + * 12(B), 18(B), 24(B), 36(B), 48(B), 54(B)" + */ + /* ASSERT(prIeSupportedRate->ucLength <= ELEM_MAX_LEN_SUP_RATES); */ + ASSERT(prIeSupportedRate->ucLength <= RATE_NUM); + + for (i = 0; i < prIeSupportedRate->ucLength; i++) { + ucRate = prIeSupportedRate->aucSupportedRates[i] & RATE_MASK; + + /* Search all valid data rates */ + for (j = 0; j < sizeof(aucDataRate) / sizeof(UINT_8); j++) { + if (ucRate == aucDataRate[j]) { + u2OperationalRateSet |= BIT(j); + + if (prIeSupportedRate->aucSupportedRates[i] & RATE_BASIC_BIT) + u2BSSBasicRateSet |= BIT(j); + + break; + } + } + + if ((j == sizeof(aucDataRate) / sizeof(UINT_8)) && + (prIeSupportedRate->aucSupportedRates[i] & RATE_BASIC_BIT)) { + fgIsUnknownBSSBasicRate = TRUE; /* A data rate not list in the aucDataRate[] */ + } + } + } + + if (prIeExtSupportedRate) { + /* ASSERT(prIeExtSupportedRate->ucLength <= ELEM_MAX_LEN_EXTENDED_SUP_RATES); */ + + for (i = 0; i < prIeExtSupportedRate->ucLength; i++) { + ucRate = prIeExtSupportedRate->aucExtSupportedRates[i] & RATE_MASK; + + /* Search all valid data rates */ + for (j = 0; j < sizeof(aucDataRate) / sizeof(UINT_8); j++) { + if (ucRate == aucDataRate[j]) { + u2OperationalRateSet |= BIT(j); + + if (prIeExtSupportedRate->aucExtSupportedRates[i] & RATE_BASIC_BIT) + u2BSSBasicRateSet |= BIT(j); + + break; + } + } + + if ((j == sizeof(aucDataRate) / sizeof(UINT_8)) && + (prIeExtSupportedRate->aucExtSupportedRates[i] & RATE_BASIC_BIT)) { + fgIsUnknownBSSBasicRate = TRUE; /* A data rate not list in the aucDataRate[] */ + } + } + } + + *pu2OperationalRateSet = u2OperationalRateSet; + *pu2BSSBasicRateSet = u2BSSBasicRateSet; + *pfgIsUnknownBSSBasicRate = fgIsUnknownBSSBasicRate; + + return; + +} /* end of rateGetRateSetFromIEs() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Convert the given Operational Rate Set & Basic Rate Set to the Rate Code +* Format for used in (Ext)Supportec Rate IE. +* +* @param[in] u2OperationalRateSet Operational Rate Set +* @param[in] u2BSSBasicRateSet Basic Rate Set +* @param[out] pucDataRates Pointer to the Data Rate Buffer +* @param[out] pucDataRatesLen Pointer to the Data Rate Buffer Length +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +rateGetDataRatesFromRateSet(IN UINT_16 u2OperationalRateSet, + IN UINT_16 u2BSSBasicRateSet, OUT PUINT_8 pucDataRates, OUT PUINT_8 pucDataRatesLen) +{ + UINT_32 i, j; + + ASSERT(pucDataRates); + ASSERT(pucDataRatesLen); + + ASSERT(u2BSSBasicRateSet == (u2OperationalRateSet & u2BSSBasicRateSet)); + + for (i = RATE_1M_INDEX, j = 0; i < RATE_NUM; i++) { + if (u2OperationalRateSet & BIT(i)) { + + *(pucDataRates + j) = aucDataRate[i]; + + if (u2BSSBasicRateSet & BIT(i)) + *(pucDataRates + j) |= RATE_BASIC_BIT; + + j++; + } + } + + *pucDataRatesLen = (UINT_8) j; + + return; + +} /* end of rateGetDataRatesFromRateSet() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Get the highest rate from given Rate Set. +* +* \param[in] u2RateSet Rate Set +* \param[out] pucHighestRateIndex Pointer to buffer of the Highest Rate Index +* +* \retval TRUE Highest Rate Index was found +* \retval FALSE Highest Rate Index was not found +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rateGetHighestRateIndexFromRateSet(IN UINT_16 u2RateSet, OUT PUINT_8 pucHighestRateIndex) +{ + INT_32 i; + + ASSERT(pucHighestRateIndex); + + for (i = RATE_54M_INDEX; i >= RATE_1M_INDEX; i--) { + if (u2RateSet & BIT(i)) { + *pucHighestRateIndex = (UINT_8) i; + return TRUE; + } + } + + return FALSE; + +} /* end of rateGetHighestRateIndexFromRateSet() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Get the lowest rate from given Rate Set. +* +* \param[in] u2RateSet Rate Set +* \param[out] pucLowestRateIndex Pointer to buffer of the Lowest Rate Index +* +* \retval TRUE Lowest Rate Index was found +* \retval FALSE Lowest Rate Index was not found +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rateGetLowestRateIndexFromRateSet(IN UINT_16 u2RateSet, OUT PUINT_8 pucLowestRateIndex) +{ + UINT_32 i; + + ASSERT(pucLowestRateIndex); + + for (i = RATE_1M_INDEX; i <= RATE_54M_INDEX; i++) { + if (u2RateSet & BIT(i)) { + *pucLowestRateIndex = (UINT_8) i; + return TRUE; + } + } + + return FALSE; + +} /* end of rateGetLowestRateIndexFromRateSet() */ + +#if 0 /* NOTE(Kevin): For reference */ +/*----------------------------------------------------------------------------*/ +/*! +* \brief Convert the given Data Rates to the Rate Set. +* +* \param[in] pucDataRates Pointer to the Data Rates +* \param[in] ucDataRatesLen Length of given Data Rates +* \param[out] pu2RateSet Pointer to the Rate Set +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rateGetRateSetFromDataRates(IN PUINT_8 pucDataRates, IN UINT_8 ucDataRatesLen, OUT PUINT_16 pu2RateSet) +{ + UINT_16 u2RateSet = 0; + UINT_8 ucRate; + UINT_32 i, j; + + ASSERT(pucDataRates); + ASSERT(pu2RateSet); + + if (pucDataRates) { + for (i = 0; i < ucDataRatesLen; i++) { + ucRate = pucDataRates[i] & RATE_MASK; + + /* Search all valid data rates */ + for (j = 0; j < sizeof(aucDataRate) / sizeof(UINT_8); j++) { + if (ucRate == aucDataRate[j]) { + u2RateSet |= BIT(j); + break; + } + } + } + } + + *pu2RateSet = u2RateSet; + + return; + +} /* end of rateGetRateSetFromDataRates() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Parse the Operational Rate Set and Basic Rate Set to get the corresponding +* ACK/CTS(Respnose) TX Rates. +* +* \param[in] u2OperationalRateSet Operational Rate Set +* \param[in] u2BSSBasicRateSet Basic Rate Set +* \param[out] aucAckCtsRateIndex Pointer to the Ack/Cts Data Rate Buffer +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +rateSetAckCtsDataRatesFromRateSet(IN UINT_16 u2OperationalRateSet, + IN UINT_16 u2BSSBasicRateSet, IN OUT UINT_8 aucAckCtsRateIndex[]) +{ + INT_32 i, j; + + ASSERT(aucAckCtsRateIndex); + ASSERT(u2BSSBasicRateSet == (u2OperationalRateSet & u2BSSBasicRateSet)); + + /* Setup default ACK/CTS response rate */ + kalMemCopy(aucAckCtsRateIndex, (PVOID) aucDefaultAckCtsRateIndex, sizeof(aucDefaultAckCtsRateIndex)); + + for (i = RATE_54M_INDEX; i >= RATE_1M_INDEX; i--) { + if (u2OperationalRateSet & BIT(i)) { + for (j = i; j >= RATE_1M_INDEX; j--) { + if (u2BSSBasicRateSet & BIT(j)) { + /* Reply ACK Frame at the same Modulation Scheme. */ + if ((afgIsOFDMRate[i] && afgIsOFDMRate[j]) || + (!afgIsOFDMRate[i] && !afgIsOFDMRate[j])) + aucAckCtsRateIndex[i] = (UINT_8) j; + break; + } + } + + /* NOTE(Kevin 2008/03/25): Following code is used for those AP which has + * NULL BasicRateSet. + * e.g. If input Operational Rate Set = [18M 12M 9M], Basic Rate Set = NULL. + * Originally we'll get Ack Rate for [18M 12M 9M] is [12M 12M "6M"]. + * Now we'll get Ack Rate for [18M 12M 9M] is [12M 12M 9M], + * The Ack Rate for Tx Rates which are not list in Operational Rate Set is still + * use highest mandatory rate as default. + */ + if (j < RATE_1M_INDEX) { /* The ACK/CTS rate was not found in BasicRateSet */ + if (!(BIT(aucAckCtsRateIndex[i]) & u2OperationalRateSet)) + aucAckCtsRateIndex[i] = (UINT_8) i; + } + } + } + + return; + +} /* end of rateSetAckCtsDataRatesFromRateSet() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Get the proper initial rate from Rate Set according to given RCPI value +* +* \param[in] u2RateSet Rate Set +* \param[in] rRcpi RCPI value from AP or Peer STA +* \param[out] pucInitialRateIndex Pointer to buffer of the initial Rate Index +* +* \retval TRUE Initial Rate Index was found +* \retval FALSE Initial Rate Index was not found +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rateGetBestInitialRateIndex(IN UINT_16 u2RateSet, IN RCPI rRcpi, OUT PUINT_8 pucInitialRateIndex) +{ + UINT_16 u2InitRateSet; + INT_32 i; + + ASSERT(pucInitialRateIndex); + + DBGLOG(MGT, TRACE, "rRcpi = %d\n", rRcpi); + + if (rRcpi >= RCPI_100) { /* Best Signal */ + u2InitRateSet = INITIAL_RATE_SET(RCPI_100); + } else if (rRcpi >= RCPI_80) { /* Better Signal */ + u2InitRateSet = INITIAL_RATE_SET(RCPI_80); + } else if (rRcpi >= RCPI_60) { /* Good Signal */ + u2InitRateSet = INITIAL_RATE_SET(RCPI_60); + } else { /* Worse Signal */ + /* NOTE(Kevin): If return FALSE, we should assign the BSS Basic Rate Index + * (prBssInfo->ucBasicRateIndex) to the initial rate. It was determined in + * function - bssUpdateTxRateForControlFrame(). + */ + return FALSE; + } + + u2RateSet &= u2InitRateSet; + + for (i = RATE_54M_INDEX; i >= RATE_1M_INDEX; i--) { + if (u2RateSet & BIT(i)) { + *pucInitialRateIndex = (UINT_8) i; + return TRUE; + } + } + + return FALSE; + +} /* end of rateGetBestInitialRateIndex() */ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/rlm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/rlm.c new file mode 100644 index 0000000000000..18840762a7617 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/rlm.c @@ -0,0 +1,2850 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E 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 FIX_P2P_HT20 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 +******************************************************************************** +*/ +TIMER_T rBeaconReqTimer; +TIMER_T rTSMReqTimer; +/******************************************************************************* +* M A 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); + +static BOOLEAN rlmAllMeasurementIssued(struct RADIO_MEASUREMENT_REQ_PARAMS *prReq); + +static VOID rlmFreeMeasurementResources(P_ADAPTER_T prAdapter); + +static VOID rlmCalibrateRepetions(struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmFsmEventInit(P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + /* Note: assume TIMER_T structures are reset to zero or stopped + * before invoking this function. + */ + + /* Initialize OBSS FSM */ + rlmObssInit(prAdapter); +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + rlmDomainCheckCountryPowerLimitTable(prAdapter); +#endif + { + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReqParam = + &prAdapter->rWifiVar.rRmReqParams; + struct RADIO_MEASUREMENT_REPORT_PARAMS *prRmRepParam = + &prAdapter->rWifiVar.rRmRepParams; + + kalMemZero(prRmRepParam, sizeof(*prRmRepParam)); + kalMemZero(prRmReqParam, sizeof(*prRmReqParam)); + prRmReqParam->rBcnRmParam.eState = RM_NO_REQUEST; + prRmReqParam->fgRmIsOngoing = FALSE; + LINK_INITIALIZE(&prRmRepParam->rFreeReportLink); + LINK_INITIALIZE(&prRmRepParam->rReportLink); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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); + } + rlmCancelRadioMeasurement(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief For probe request, association request +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmReqGenerateHtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; + ASSERT(prBssInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) && + (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N))) + rlmFillHtCapIE(prAdapter, prBssInfo, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief For probe request, association request +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmReqGenerateExtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; + ASSERT(prBssInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) && + (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N))) + rlmFillExtCapIE(prAdapter, prBssInfo, prMsduInfo); +#if CFG_SUPPORT_HOTSPOT_2_0 + else if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) + hs20FillExtCapIE(prAdapter, prBssInfo, prMsduInfo); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief For probe response (GO, IBSS) and association response +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmRspGenerateHtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + ASSERT(IS_NET_ACTIVE(prAdapter, prMsduInfo->ucNetworkType)); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; + ASSERT(prBssInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (prStaRec) + DBGLOG(RLM, TRACE, "%s index %d ,availPhyTypeSet:0x%x prStaRec->ucPhyTypeSet:0x%x [%pM]\n ", __func__ + , prMsduInfo->ucStaRecIndex, prAdapter->rWifiVar.ucAvailablePhyTypeSet + , prStaRec->ucPhyTypeSet, prStaRec->aucMacAddr); + else + DBGLOG(RLM, TRACE, "%s prStaRec is null ,availPhyTypeSet:0x%x, index :%d\n", __func__ + , prAdapter->rWifiVar.ucAvailablePhyTypeSet, prMsduInfo->ucStaRecIndex); + + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) { + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE || + prBssInfo->eCurrentOPMode == OP_MODE_P2P_DEVICE) { + if (prStaRec && (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) + rlmFillHtCapIE(prAdapter, prBssInfo, prMsduInfo); + } else if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT && RLM_NET_IS_11N(prBssInfo)) + 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 (prStaRec) + DBGLOG(RLM, TRACE, "%s index %d ,availPhyTypeSet:0x%x prStaRec->ucPhyTypeSet:0x%x [%pM]\n ", __func__ + , prMsduInfo->ucStaRecIndex, prAdapter->rWifiVar.ucAvailablePhyTypeSet + , prStaRec->ucPhyTypeSet, prStaRec->aucMacAddr); + else + DBGLOG(RLM, TRACE, "%s prStaRec is null ,availPhyTypeSet:0x%x, index :%d\n", __func__ + , prAdapter->rWifiVar.ucAvailablePhyTypeSet, prMsduInfo->ucStaRecIndex); + + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) { + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE || + prBssInfo->eCurrentOPMode == OP_MODE_P2P_DEVICE) { + if (prStaRec && (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) + rlmFillExtCapIE(prAdapter, prBssInfo, prMsduInfo); + } else if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT && RLM_NET_IS_11N(prBssInfo)) + 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 (prStaRec) + DBGLOG(RLM, TRACE, "%s index %d ,availPhyTypeSet:0x%x prStaRec->ucPhyTypeSet:0x%x [%pM]\n ", __func__ + , prMsduInfo->ucStaRecIndex, prAdapter->rWifiVar.ucAvailablePhyTypeSet + , prStaRec->ucPhyTypeSet, prStaRec->aucMacAddr); + else + DBGLOG(RLM, TRACE, "%s prStaRec is null ,availPhyTypeSet:0x%x, index :%d\n", __func__ + , prAdapter->rWifiVar.ucAvailablePhyTypeSet, prMsduInfo->ucStaRecIndex); + + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) { + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE || + prBssInfo->eCurrentOPMode == OP_MODE_P2P_DEVICE) { + if (prStaRec && (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) + rlmFillHtOpIE(prAdapter, prBssInfo, prMsduInfo); + } else if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT && RLM_NET_IS_11N(prBssInfo)) + 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); + } +} +#if CFG_SUPPORT_MTK_SYNERGY +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to generate MTK Vendor Specific OUI +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmGenerateMTKOuiIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + PUINT_8 pucBuffer; + UINT_8 aucMtkOui[] = VENDOR_OUI_MTK; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (ULONG) prMsduInfo->u2FrameLength); + MTK_OUI_IE(pucBuffer)->ucId = ELEM_ID_VENDOR; + MTK_OUI_IE(pucBuffer)->ucLength = ELEM_MIN_LEN_MTK_OUI; + MTK_OUI_IE(pucBuffer)->aucOui[0] = aucMtkOui[0]; + MTK_OUI_IE(pucBuffer)->aucOui[1] = aucMtkOui[1]; + MTK_OUI_IE(pucBuffer)->aucOui[2] = aucMtkOui[2]; + + MTK_OUI_IE(pucBuffer)->aucCapability[0] = MTK_SYNERGY_CAP0 & (prAdapter->rWifiVar.aucMtkFeature[0]); + MTK_OUI_IE(pucBuffer)->aucCapability[1] = MTK_SYNERGY_CAP1 & (prAdapter->rWifiVar.aucMtkFeature[1]); + MTK_OUI_IE(pucBuffer)->aucCapability[2] = MTK_SYNERGY_CAP2 & (prAdapter->rWifiVar.aucMtkFeature[2]); + MTK_OUI_IE(pucBuffer)->aucCapability[3] = MTK_SYNERGY_CAP3 & (prAdapter->rWifiVar.aucMtkFeature[3]); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); +} /* rlmGenerateMTKOuiIE */ +#endif +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +UINT32 +rlmFillHtCapIEByParams(BOOLEAN fg40mAllowed, + BOOLEAN fgShortGIDisabled, + UINT_8 u8SupportRxSgi20, + UINT_8 u8SupportRxSgi40, + UINT_8 u8SupportRxGf, UINT_8 u8SupportRxSTBC, ENUM_OP_MODE_T eCurrentOPMode, UINT_8 *pOutBuf) +{ + P_IE_HT_CAP_T prHtCap; + P_SUP_MCS_SET_FIELD prSupMcsSet; + + ASSERT(pOutBuf); + + prHtCap = (P_IE_HT_CAP_T) pOutBuf; + + /* Add HT capabilities IE */ + prHtCap->ucId = ELEM_ID_HT_CAP; + prHtCap->ucLength = sizeof(IE_HT_CAP_T) - ELEM_HDR_LEN; + + prHtCap->u2HtCapInfo = HT_CAP_INFO_DEFAULT_VAL; + if (!fg40mAllowed) { + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | + HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_DSSS_CCK_IN_40M); + } + if (fgShortGIDisabled) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); + + if (u8SupportRxSgi20 == 2) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_20M); + if (u8SupportRxSgi40 == 2) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_40M); + if (u8SupportRxGf == 2) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_HT_GF); + if (u8SupportRxSTBC == 2) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_RX_STBC_1_SS); + prHtCap->ucAmpduParam = AMPDU_PARAM_DEFAULT_VAL; + + prSupMcsSet = &prHtCap->rSupMcsSet; + kalMemZero((PVOID)&prSupMcsSet->aucRxMcsBitmask[0], SUP_MCS_RX_BITMASK_OCTET_NUM); + + prSupMcsSet->aucRxMcsBitmask[0] = BITS(0, 7); + + if (fg40mAllowed) + prSupMcsSet->aucRxMcsBitmask[32 / 8] = BIT(0); /* MCS32 */ + prSupMcsSet->u2RxHighestSupportedRate = SUP_MCS_RX_DEFAULT_HIGHEST_RATE; + prSupMcsSet->u4TxRateInfo = SUP_MCS_TX_DEFAULT_VAL; + + prHtCap->u2HtExtendedCap = HT_EXT_CAP_DEFAULT_VAL; + if (!fg40mAllowed || eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + prHtCap->u2HtExtendedCap &= ~(HT_EXT_CAP_PCO | HT_EXT_CAP_PCO_TRANS_TIME_NONE); + + prHtCap->u4TxBeamformingCap = TX_BEAMFORMING_CAP_DEFAULT_VAL; + + prHtCap->ucAselCap = ASEL_CAP_DEFAULT_VAL; + + ASSERT(IE_SIZE(prHtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP)); + + return IE_SIZE(prHtCap); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static VOID rlmFillHtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo) +{ + P_IE_HT_CAP_T prHtCap; +/* P_SUP_MCS_SET_FIELD prSupMcsSet; */ + BOOLEAN fg40mAllowed; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(prMsduInfo); + + fg40mAllowed = prBssInfo->fgAssoc40mBwAllowed; + + prHtCap = (P_IE_HT_CAP_T) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + +#if 0 + /* Add HT capabilities IE */ + prHtCap->ucId = ELEM_ID_HT_CAP; + prHtCap->ucLength = sizeof(IE_HT_CAP_T) - ELEM_HDR_LEN; + + prHtCap->u2HtCapInfo = HT_CAP_INFO_DEFAULT_VAL; + if (!fg40mAllowed) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | + HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_DSSS_CCK_IN_40M); + if (prAdapter->rWifiVar.rConnSettings.fgRxShortGIDisabled) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); + + if (prAdapter->rWifiVar.u8SupportRxSgi20 == 2) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_20M); + if (prAdapter->rWifiVar.u8SupportRxSgi40 == 2) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_40M); + if (prAdapter->rWifiVar.u8SupportRxGf == 2) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_HT_GF); + + prHtCap->ucAmpduParam = AMPDU_PARAM_DEFAULT_VAL; + + prSupMcsSet = &prHtCap->rSupMcsSet; + kalMemZero((PVOID)&prSupMcsSet->aucRxMcsBitmask[0], SUP_MCS_RX_BITMASK_OCTET_NUM); + + prSupMcsSet->aucRxMcsBitmask[0] = BITS(0, 7); + + if (fg40mAllowed) + prSupMcsSet->aucRxMcsBitmask[32 / 8] = BIT(0); /* MCS32 */ + prSupMcsSet->u2RxHighestSupportedRate = SUP_MCS_RX_DEFAULT_HIGHEST_RATE; + prSupMcsSet->u4TxRateInfo = SUP_MCS_TX_DEFAULT_VAL; + + prHtCap->u2HtExtendedCap = HT_EXT_CAP_DEFAULT_VAL; + if (!fg40mAllowed || prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + prHtCap->u2HtExtendedCap &= ~(HT_EXT_CAP_PCO | HT_EXT_CAP_PCO_TRANS_TIME_NONE); + + prHtCap->u4TxBeamformingCap = TX_BEAMFORMING_CAP_DEFAULT_VAL; + + prHtCap->ucAselCap = ASEL_CAP_DEFAULT_VAL; + + ASSERT(IE_SIZE(prHtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP)); + + prMsduInfo->u2FrameLength += IE_SIZE(prHtCap); +#else + + prMsduInfo->u2FrameLength += rlmFillHtCapIEByParams(fg40mAllowed, + prAdapter->rWifiVar.rConnSettings.fgRxShortGIDisabled, + prAdapter->rWifiVar.u8SupportRxSgi20, + prAdapter->rWifiVar.u8SupportRxSgi40, + prAdapter->rWifiVar.u8SupportRxGf, + prAdapter->rWifiVar.u8SupportRxSTBC, + prBssInfo->eCurrentOPMode, (UINT_8 *) prHtCap); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static VOID rlmFillExtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo) +{ +#if CFG_SUPPORT_HOTSPOT_2_0 + P_HS20_EXT_CAP_T prHsExtCap; +#else + P_EXT_CAP_T prExtCap; +#endif + BOOLEAN fg40mAllowed; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + fg40mAllowed = prBssInfo->fgAssoc40mBwAllowed; + +#if CFG_SUPPORT_HOTSPOT_2_0 + prHsExtCap = (P_HS20_EXT_CAP_T) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + prHsExtCap->ucId = ELEM_ID_EXTENDED_CAP; + + if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) + prHsExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + else + prHsExtCap->ucLength = 3 - ELEM_HDR_LEN; + + kalMemZero(prHsExtCap->aucCapabilities, sizeof(prHsExtCap->aucCapabilities)); + + prHsExtCap->aucCapabilities[0] = ELEM_EXT_CAP_DEFAULT_VAL; + + if (!fg40mAllowed) + prHsExtCap->aucCapabilities[0] &= ~ELEM_EXT_CAP_20_40_COEXIST_SUPPORT; + + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + prHsExtCap->aucCapabilities[0] &= ~ELEM_EXT_CAP_PSMP_CAP; +#if CFG_SUPPORT_P2P_ECSA + /* Only set Extended Channel Switch support bit when as GO */ + if (prBssInfo->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX && + prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT && + !prAdapter->rWifiVar.prP2pFsmInfo->fgIsApMode) + prHsExtCap->aucCapabilities[0] |= ELEM_EXT_CAP_ECS_SUPPORT; +#endif + if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) { + SET_EXT_CAP(prHsExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_INTERWORKING_BIT); + SET_EXT_CAP(prHsExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_QOSMAPSET_BIT); + + /* For R2 WNM-Notification */ + SET_EXT_CAP(prHsExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_WNM_NOTIFICATION_BIT); + } + +#if CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT + SET_EXT_CAP(prHsExtCap->aucCapabilities, 3, ELEM_EXT_CAP_BSS_TRANSITION_BIT); + prHsExtCap->ucLength = 3; +#endif + + ASSERT(IE_SIZE(prHsExtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP)); + + prMsduInfo->u2FrameLength += IE_SIZE(prHsExtCap); + +#else + /* Add Extended Capabilities IE */ + prExtCap = (P_EXT_CAP_T) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + + prExtCap->ucId = ELEM_ID_EXTENDED_CAP; + + prExtCap->ucLength = 3 - ELEM_HDR_LEN; + kalMemZero(prExtCap->aucCapabilities, sizeof(prExtCap->aucCapabilities)); + + prExtCap->aucCapabilities[0] = ELEM_EXT_CAP_DEFAULT_VAL; + + if (!fg40mAllowed) + prExtCap->aucCapabilities[0] &= ~ELEM_EXT_CAP_20_40_COEXIST_SUPPORT; + + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + prExtCap->aucCapabilities[0] &= ~ELEM_EXT_CAP_PSMP_CAP; + +#if CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT + SET_EXT_CAP(prExtCap->aucCapabilities, 3, ELEM_EXT_CAP_BSS_TRANSITION_BIT); + prExtCap->ucLength = 3; +#endif + +#if CFG_SUPPORT_P2P_ECSA + /* Only set Extended Channel Switch support bit when as GO */ + if (prBssInfo->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX && + prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT && + !prAdapter->rWifiVar.prP2pFsmInfo->fgIsApMode) + prExtCap->aucCapabilities[0] |= ELEM_EXT_CAP_ECS_SUPPORT; +#endif + + ASSERT(IE_SIZE(prExtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP)); + + prMsduInfo->u2FrameLength += IE_SIZE(prExtCap); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +UINT32 rlmFillHtOpIeBody(P_BSS_INFO_T prBssInfo, UINT_8 *pFme) +{ + P_IE_HT_OP_T prHtOp; + UINT_16 i; + + prHtOp = (P_IE_HT_OP_T) pFme; + + /* Add HT operation IE */ + prHtOp->ucId = ELEM_ID_HT_OP; + prHtOp->ucLength = sizeof(IE_HT_OP_T) - ELEM_HDR_LEN; + + /* RIFS and 20/40 bandwidth operations are included */ + prHtOp->ucPrimaryChannel = prBssInfo->ucPrimaryChannel; + prHtOp->ucInfo1 = prBssInfo->ucHtOpInfo1; + + /* Decide HT protection mode field */ + if (prBssInfo->eHtProtectMode == HT_PROTECT_MODE_NON_HT) + prHtOp->u2Info2 = (UINT_8) HT_PROTECT_MODE_NON_HT; + else if (prBssInfo->eObssHtProtectMode == HT_PROTECT_MODE_NON_MEMBER) + prHtOp->u2Info2 = (UINT_8) HT_PROTECT_MODE_NON_MEMBER; + else { + /* It may be SYS_PROTECT_MODE_NONE or SYS_PROTECT_MODE_20M */ + prHtOp->u2Info2 = (UINT_8) prBssInfo->eHtProtectMode; + } + + if (prBssInfo->eGfOperationMode != GF_MODE_NORMAL) { + /* It may be GF_MODE_PROTECT or GF_MODE_DISALLOWED + * Note: it will also be set in ad-hoc network + */ + prHtOp->u2Info2 |= HT_OP_INFO2_NON_GF_HT_STA_PRESENT; + } + + if (0 /* Regulatory class 16 */ && + prBssInfo->eObssHtProtectMode == HT_PROTECT_MODE_NON_MEMBER) { + /* (TBD) It is HT_PROTECT_MODE_NON_MEMBER, so require protection + * although it is possible to have no protection by spec. + */ + prHtOp->u2Info2 |= HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT; + } + + prHtOp->u2Info3 = prBssInfo->u2HtOpInfo3; /* To do: handle L-SIG TXOP */ + + /* No basic MCSx are needed temporarily */ + for (i = 0; i < 16; i++) + prHtOp->aucBasicMcsSet[i] = 0; + + return sizeof(IE_HT_OP_T); +} + +static VOID rlmFillHtOpIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo) +{ +/* P_IE_HT_OP_T prHtOp; */ +/* UINT_16 i; */ + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(prMsduInfo); + + prMsduInfo->u2FrameLength += rlmFillHtOpIeBody(prBssInfo, + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength)); +#if 0 + prHtOp = (P_IE_HT_OP_T) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + + /* Add HT operation IE */ + prHtOp->ucId = ELEM_ID_HT_OP; + prHtOp->ucLength = sizeof(IE_HT_OP_T) - ELEM_HDR_LEN; + + /* RIFS and 20/40 bandwidth operations are included */ + prHtOp->ucPrimaryChannel = prBssInfo->ucPrimaryChannel; + prHtOp->ucInfo1 = prBssInfo->ucHtOpInfo1; + + /* Decide HT protection mode field */ + if (prBssInfo->eHtProtectMode == HT_PROTECT_MODE_NON_HT) + prHtOp->u2Info2 = (UINT_8) HT_PROTECT_MODE_NON_HT; + else if (prBssInfo->eObssHtProtectMode == HT_PROTECT_MODE_NON_MEMBER) + prHtOp->u2Info2 = (UINT_8) HT_PROTECT_MODE_NON_MEMBER; + else { + /* It may be SYS_PROTECT_MODE_NONE or SYS_PROTECT_MODE_20M */ + prHtOp->u2Info2 = (UINT_8) prBssInfo->eHtProtectMode; + } + + if (prBssInfo->eGfOperationMode != GF_MODE_NORMAL) { + /* It may be GF_MODE_PROTECT or GF_MODE_DISALLOWED + * Note: it will also be set in ad-hoc network + */ + prHtOp->u2Info2 |= HT_OP_INFO2_NON_GF_HT_STA_PRESENT; + } + + if (0 /* Regulatory class 16 */ && + prBssInfo->eObssHtProtectMode == HT_PROTECT_MODE_NON_MEMBER) { + /* (TBD) It is HT_PROTECT_MODE_NON_MEMBER, so require protection + * although it is possible to have no protection by spec. + */ + prHtOp->u2Info2 |= HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT; + } + + prHtOp->u2Info3 = prBssInfo->u2HtOpInfo3; /* To do: handle L-SIG TXOP */ + + /* No basic MCSx are needed temporarily */ + for (i = 0; i < 16; i++) + prHtOp->aucBasicMcsSet[i] = 0; + + ASSERT(IE_SIZE(prHtOp) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_OP)); + + prMsduInfo->u2FrameLength += IE_SIZE(prHtOp); +#endif +} +#if CFG_SUPPORT_P2P_ECSA +VOID rlmGenerateCSAIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + P_IE_CHANNEL_SWITCH_T prCsaIe; + P_BSS_INFO_T prBssInfo; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; + + prCsaIe = (P_IE_CHANNEL_SWITCH_T) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + + /* Add CSA IE */ + prCsaIe->ucId = ELEM_ID_CH_SW_ANNOUNCEMENT; + prCsaIe->ucLength = 3; + prCsaIe->ucChannelSwitchCount = prBssInfo->ucSwitchCount; + prCsaIe->ucChannelSwitchMode = prBssInfo->ucSwitchMode; + prCsaIe->ucNewChannelNum = prBssInfo->ucEcsaChannel; + prMsduInfo->u2FrameLength += IE_SIZE(prCsaIe); +} + +VOID rlmGenerateECSAIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + P_IE_EXT_CHANNEL_SWITCH_T prEcsaIe; + P_BSS_INFO_T prBssInfo; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; + + prEcsaIe = (P_IE_EXT_CHANNEL_SWITCH_T) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + + /* Add ECSA IE */ + prEcsaIe->ucId = ELEM_ID_CH_ESW_ANNOUNCEMENT; + prEcsaIe->ucLength = 4; + prEcsaIe->ucOpClass = prBssInfo->ucOpClass; + prEcsaIe->ucChannelSwitchCount = prBssInfo->ucSwitchCount; + prEcsaIe->ucChannelSwitchMode = prBssInfo->ucSwitchMode; + prEcsaIe->ucNewChannelNum = prBssInfo->ucEcsaChannel; + prMsduInfo->u2FrameLength += IE_SIZE(prEcsaIe); +} + +VOID rlmFreqToChannelExt(unsigned int freq, + int sec_channel, + u8 *op_class, u8 *channel) +{ + /* TODO: more operating classes */ + if (sec_channel > 1 || sec_channel < -1 || !op_class || !channel) + return; + + if (freq >= 2412 && freq <= 2472) { + if ((freq - 2407) % 5) + return; + /* 2.407 GHz, channels 1..13 */ + if (sec_channel == 1) + *op_class = 83; + else if (sec_channel == -1) + *op_class = 84; + else + *op_class = 81; + *channel = (freq - 2407) / 5; + return; + } + + if (freq == 2484) { + if (sec_channel) + return; + *op_class = 82; /* channel 14 */ + *channel = 14; + return; + } + + if (freq >= 4900 && freq < 5000) { + if ((freq - 4000) % 5) + return; + *channel = (freq - 4000) / 5; + *op_class = 0; /* TODO */ + return; + } + + /* 5 GHz, channels 36..48 */ + if (freq >= 5180 && freq <= 5240) { + if ((freq - 5000) % 5) + return; + if (sec_channel == 1) + *op_class = 116; + else if (sec_channel == -1) + *op_class = 117; + else + *op_class = 115; + *channel = (freq - 5000) / 5; + return; + } + + /* 5 GHz, channels 149..169 */ + if (freq >= 5745 && freq <= 5845) { + if ((freq - 5000) % 5) + return; + + if (sec_channel == 1) + *op_class = 126; + else if (sec_channel == -1) + *op_class = 127; + else if (freq <= 5805) + *op_class = 124; + else + *op_class = 125; + *channel = (freq - 5000) / 5; + return; + } + + /* 5 GHz, channels 100..140 */ + if (freq >= 5000 && freq <= 5700) { + if ((freq - 5000) % 5) + return; + if (sec_channel == 1) + *op_class = 122; + else if (sec_channel == -1) + *op_class = 123; + else + *op_class = 121; + *channel = (freq - 5000) / 5; + return; + } + + if (freq >= 5000 && freq < 5900) { + if ((freq - 5000) % 5) + return; + *channel = (freq - 5000) / 5; + *op_class = 0; /* TODO */ + return; + } + + /* 56.16 GHz, channel 1..4 */ + if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 4) { + if (sec_channel) + return; + *channel = (freq - 56160) / 2160; + *op_class = 180; + return; + } +} + + +/* + * generate channel switch Action frame header + */ +void rlmGenActionCSHdr(u8 *buf, + u8 *da, u8 *sa, u8 *bssid, + u8 category, u8 action) +{ + P_ACTION_CHANNEL_SWITCH_FRAME p = (P_ACTION_CHANNEL_SWITCH_FRAME)buf; + + if (!buf || !da || !sa || !bssid) + return; + + /* build MAC header */ + p->u2FrameCtrl = MAC_FRAME_ACTION; + p->u2Duration = 0; + p->u2SeqCtrl = 0; + COPY_MAC_ADDR(p->aucDestAddr, da); + COPY_MAC_ADDR(p->aucSrcAddr, sa); + COPY_MAC_ADDR(p->aucBSSID, bssid); + + p->ucCategory = category; + p->ucAction = action; +} + +void rlmGenActionCSA(u8 *buf, + u8 mode, + u8 channel, + u8 count, + u8 sco) +{ + P_ACTION_CSA_T p = (P_ACTION_CSA_T)buf; + + p->csa_id = ELEM_ID_CH_SW_ANNOUNCEMENT; + p->clen = 3; + p->mode = mode; + p->new_ch_num = channel; + p->count = count; + + p->sco_id = ELEM_ID_SCO; + p->slen = 1; + p->sco = sco; +} + +void rlmGenActionECSA(u8 *buf, + u8 mode, + u8 channel, + u8 count, + u8 op_class) +{ + P_ACTION_ECSA_T p = (P_ACTION_ECSA_T)buf; + + p->mode = mode; + p->new_operating_class = op_class; + p->new_ch_num = channel; + p->count = count; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function should be invoked to update parameters of associated AP. +* (Association response and Beacon) +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static UINT_8 rlmRecIeInfoForClient(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, PUINT_8 pucIE, UINT_16 u2IELength) +{ + UINT_16 u2Offset; + P_STA_RECORD_T prStaRec; + P_IE_HT_CAP_T prHtCap; + P_IE_HT_OP_T prHtOp; + P_IE_OBSS_SCAN_PARAM_T prObssScnParam; + UINT_8 ucERP, ucPrimaryChannel; +#if CFG_SUPPORT_QUIET && 0 + BOOLEAN fgHasQuietIE = FALSE; +#endif + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(pucIE); + + prStaRec = prBssInfo->prStaRecOfAP; + ASSERT(prStaRec); + if (!prStaRec) + return 0; + + prBssInfo->fgUseShortPreamble = prBssInfo->fgIsShortPreambleAllowed; + ucPrimaryChannel = 0; + prObssScnParam = NULL; + + /* Note: HT-related members in staRec may not be zero before, so + * if following IE does not exist, they are still not zero. + * These HT-related parameters are valid only when the corresponding + * BssInfo supports 802.11n, i.e., RLM_NET_IS_11N() + */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_HT_CAP: + if (!RLM_NET_IS_11N(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_HT_CAP_T) - 2)) + break; + prHtCap = (P_IE_HT_CAP_T) pucIE; + prStaRec->ucMcsSet = prHtCap->rSupMcsSet.aucRxMcsBitmask[0]; + prStaRec->fgSupMcs32 = (prHtCap->rSupMcsSet.aucRxMcsBitmask[32 / 8] & BIT(0)) ? TRUE : FALSE; + + prStaRec->u2HtCapInfo = prHtCap->u2HtCapInfo; + prStaRec->ucAmpduParam = prHtCap->ucAmpduParam; + prStaRec->u2HtExtendedCap = prHtCap->u2HtExtendedCap; + prStaRec->u4TxBeamformingCap = prHtCap->u4TxBeamformingCap; + prStaRec->ucAselCap = prHtCap->ucAselCap; + break; + + case ELEM_ID_HT_OP: + if (!RLM_NET_IS_11N(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_HT_OP_T) - 2)) + break; + prHtOp = (P_IE_HT_OP_T) pucIE; + /* Workaround that some APs fill primary channel field by its + * secondary channel, but its DS IE is correct 20110610 + */ + if (ucPrimaryChannel == 0) + ucPrimaryChannel = prHtOp->ucPrimaryChannel; + prBssInfo->ucHtOpInfo1 = prHtOp->ucInfo1; + prBssInfo->u2HtOpInfo2 = prHtOp->u2Info2; + prBssInfo->u2HtOpInfo3 = prHtOp->u2Info3; + + if (!prBssInfo->fg40mBwAllowed) + prBssInfo->ucHtOpInfo1 &= ~(HT_OP_INFO1_SCO | HT_OP_INFO1_STA_CHNL_WIDTH); + + if ((prBssInfo->ucHtOpInfo1 & HT_OP_INFO1_SCO) != CHNL_EXT_RES) + prBssInfo->eBssSCO = (ENUM_CHNL_EXT_T)(prBssInfo->ucHtOpInfo1 & HT_OP_INFO1_SCO); + + prBssInfo->eHtProtectMode = (ENUM_HT_PROTECT_MODE_T) + (prBssInfo->u2HtOpInfo2 & HT_OP_INFO2_HT_PROTECTION); + + /* To do: process regulatory class 16 */ + if ((prBssInfo->u2HtOpInfo2 & HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT) + && 0 /* && regulatory class is 16 */) + prBssInfo->eGfOperationMode = GF_MODE_DISALLOWED; + else if (prBssInfo->u2HtOpInfo2 & HT_OP_INFO2_NON_GF_HT_STA_PRESENT) + prBssInfo->eGfOperationMode = GF_MODE_PROTECT; + else + prBssInfo->eGfOperationMode = GF_MODE_NORMAL; + + prBssInfo->eRifsOperationMode = + (prBssInfo->ucHtOpInfo1 & HT_OP_INFO1_RIFS_MODE) ? RIFS_MODE_NORMAL : RIFS_MODE_DISALLOWED; + + break; + + case ELEM_ID_20_40_BSS_COEXISTENCE: + if (!RLM_NET_IS_11N(prBssInfo)) + break; + /* To do: store if scanning exemption grant to BssInfo */ + break; + + case ELEM_ID_OBSS_SCAN_PARAMS: + if (!RLM_NET_IS_11N(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_OBSS_SCAN_PARAM_T) - 2)) + break; + /* Store OBSS parameters to BssInfo */ + prObssScnParam = (P_IE_OBSS_SCAN_PARAM_T) pucIE; + break; + + case ELEM_ID_EXTENDED_CAP: + if (!RLM_NET_IS_11N(prBssInfo)) + break; + /* To do: store extended capability (PSMP, coexist) to BssInfo */ + break; + + case ELEM_ID_ERP_INFO: + if (IE_LEN(pucIE) != (sizeof(IE_ERP_T) - 2) || prBssInfo->eBand != BAND_2G4) + break; + ucERP = ERP_INFO_IE(pucIE)->ucERP; + prBssInfo->fgErpProtectMode = (ucERP & ERP_INFO_USE_PROTECTION) ? TRUE : FALSE; + + if (ucERP & ERP_INFO_BARKER_PREAMBLE_MODE) + prBssInfo->fgUseShortPreamble = FALSE; + break; + + case ELEM_ID_DS_PARAM_SET: + if (IE_LEN(pucIE) == ELEM_MAX_LEN_DS_PARAMETER_SET) + ucPrimaryChannel = DS_PARAM_IE(pucIE)->ucCurrChnl; + break; + +#if CFG_SUPPORT_DFS /* Add by Enlai */ + case ELEM_ID_CH_SW_ANNOUNCEMENT: + { + rlmProcessChannelSwitchIE(prAdapter, (P_IE_CHANNEL_SWITCH_T) pucIE); + } + break; + +#if CFG_SUPPORT_QUIET && 0 + /* Note: RRM code should be moved to independent RRM function by + * component design rule. But we attach it to RLM temporarily + */ + case ELEM_ID_QUIET: + rrmQuietHandleQuietIE(prBssInfo, (P_IE_QUIET_T) pucIE); + fgHasQuietIE = TRUE; + break; +#endif +#endif + + default: + break; + } /* end of switch */ + } /* end of IE_FOR_EACH */ + + /* Some AP will have wrong channel number (255) when running time. + * Check if correct channel number information. 20110501 + */ + if ((prBssInfo->eBand == BAND_2G4 && ucPrimaryChannel > 14) || + (prBssInfo->eBand != BAND_2G4 && (ucPrimaryChannel >= 200 || ucPrimaryChannel <= 14))) + ucPrimaryChannel = 0; +#if CFG_SUPPORT_QUIET && 0 + if (!fgHasQuietIE) + rrmQuietIeNotExist(prAdapter, prBssInfo); +#endif + + /* Check if OBSS scan process will launch */ + if (!prAdapter->fgEnOnlineScan || !prObssScnParam || + !(prStaRec->u2HtCapInfo & HT_CAP_INFO_SUP_CHNL_WIDTH) || + prBssInfo->eBand != BAND_2G4 || !prBssInfo->fg40mBwAllowed) { + + /* Note: it is ok not to stop rObssScanTimer() here */ + prBssInfo->u2ObssScanInterval = 0; + } else { + if (prObssScnParam->u2TriggerScanInterval < OBSS_SCAN_MIN_INTERVAL) + prObssScnParam->u2TriggerScanInterval = OBSS_SCAN_MIN_INTERVAL; + if (prBssInfo->u2ObssScanInterval != prObssScnParam->u2TriggerScanInterval) { + + prBssInfo->u2ObssScanInterval = prObssScnParam->u2TriggerScanInterval; + + /* Start timer to trigger OBSS scanning */ + cnmTimerStartTimer(prAdapter, &prBssInfo->rObssScanTimer, + prBssInfo->u2ObssScanInterval * MSEC_PER_SEC); + } + } + + return ucPrimaryChannel; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief AIS or P2P GC. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static BOOLEAN +rlmRecBcnFromNeighborForClient(P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength) +{ + UINT_16 u2Offset, i; + UINT_8 ucPriChannel, ucSecChannel; + ENUM_CHNL_EXT_T eSCO; + BOOLEAN fgHtBss, fg20mReq; + + if ((prAdapter == NULL) + || (pucIE == NULL) + || (prBssInfo == NULL) + || (prSwRfb == NULL)) { + ASSERT(FALSE); + return FALSE; + } + + /* Record it to channel list to change 20/40 bandwidth */ + ucPriChannel = 0; + eSCO = CHNL_EXT_SCN; + + fgHtBss = FALSE; + fg20mReq = FALSE; + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_HT_CAP: + { + P_IE_HT_CAP_T prHtCap; + + if (IE_LEN(pucIE) != (sizeof(IE_HT_CAP_T) - 2)) + break; + + prHtCap = (P_IE_HT_CAP_T) pucIE; + if (prHtCap->u2HtCapInfo & HT_CAP_INFO_40M_INTOLERANT) + fg20mReq = TRUE; + fgHtBss = TRUE; + break; + } + case ELEM_ID_HT_OP: + { + P_IE_HT_OP_T prHtOp; + + if (IE_LEN(pucIE) != (sizeof(IE_HT_OP_T) - 2)) + break; + + prHtOp = (P_IE_HT_OP_T) pucIE; + /* Workaround that some APs fill primary channel field by its + * secondary channel, but its DS IE is correct 20110610 + */ + if (ucPriChannel == 0) + ucPriChannel = prHtOp->ucPrimaryChannel; + + if ((prHtOp->ucInfo1 & HT_OP_INFO1_SCO) != CHNL_EXT_RES) + eSCO = (ENUM_CHNL_EXT_T) (prHtOp->ucInfo1 & HT_OP_INFO1_SCO); + break; + } + case ELEM_ID_20_40_BSS_COEXISTENCE: + { + P_IE_20_40_COEXIST_T prCoexist; + + if (IE_LEN(pucIE) != (sizeof(IE_20_40_COEXIST_T) - 2)) + break; + + prCoexist = (P_IE_20_40_COEXIST_T) pucIE; + if (prCoexist->ucData & BSS_COEXIST_40M_INTOLERANT) + fg20mReq = TRUE; + break; + } + case ELEM_ID_DS_PARAM_SET: + if (IE_LEN(pucIE) != (sizeof(IE_DS_PARAM_SET_T) - 2)) + break; + ucPriChannel = DS_PARAM_IE(pucIE)->ucCurrChnl; + break; + + default: + break; + } + } + + /* To do: Update channel list and 5G band. All channel lists have the same + * update procedure. We should give it the entry pointer of desired + * channel list. + */ + if (HIF_RX_HDR_GET_RF_BAND(prSwRfb->prHifRxHdr) != BAND_2G4) + return FALSE; + + if (ucPriChannel == 0 || ucPriChannel > 14) + ucPriChannel = HIF_RX_HDR_GET_CHNL_NUM(prSwRfb->prHifRxHdr); + + if (fgHtBss) { + ASSERT(prBssInfo->auc2G_PriChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_PriChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { + if (prBssInfo->auc2G_PriChnlList[i] == ucPriChannel) + break; + } + if ((i > prBssInfo->auc2G_PriChnlList[0]) && (i <= CHNL_LIST_SZ_2G)) { + prBssInfo->auc2G_PriChnlList[i] = ucPriChannel; + prBssInfo->auc2G_PriChnlList[0]++; + } + + /* Update secondary channel */ + if (eSCO != CHNL_EXT_SCN) { + ucSecChannel = (eSCO == CHNL_EXT_SCA) ? (ucPriChannel + 4) : (ucPriChannel - 4); + + ASSERT(prBssInfo->auc2G_SecChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_SecChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { + if (prBssInfo->auc2G_SecChnlList[i] == ucSecChannel) + break; + } + if ((i > prBssInfo->auc2G_SecChnlList[0]) && (i <= CHNL_LIST_SZ_2G)) { + prBssInfo->auc2G_SecChnlList[i] = ucSecChannel; + prBssInfo->auc2G_SecChnlList[0]++; + } + } + + /* Update 20M bandwidth request channels */ + if (fg20mReq) { + ASSERT(prBssInfo->auc2G_20mReqChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_20mReqChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { + if (prBssInfo->auc2G_20mReqChnlList[i] == ucPriChannel) + break; + } + if ((i > prBssInfo->auc2G_20mReqChnlList[0]) && (i <= CHNL_LIST_SZ_2G)) { + prBssInfo->auc2G_20mReqChnlList[i] = ucPriChannel; + prBssInfo->auc2G_20mReqChnlList[0]++; + } + } + } else { + /* Update non-HT channel list */ + ASSERT(prBssInfo->auc2G_NonHtChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_NonHtChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { + if (prBssInfo->auc2G_NonHtChnlList[i] == ucPriChannel) + break; + } + if ((i > prBssInfo->auc2G_NonHtChnlList[0]) && (i <= CHNL_LIST_SZ_2G)) { + prBssInfo->auc2G_NonHtChnlList[i] = ucPriChannel; + prBssInfo->auc2G_NonHtChnlList[0]++; + } + + } + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief AIS or P2P GC. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static BOOLEAN +rlmRecBcnInfoForClient(P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength) +{ + /* For checking if syncing params are different from + * last syncing and need to sync again + */ + CMD_SET_BSS_RLM_PARAM_T rBssRlmParam; + BOOLEAN fgNewParameter = FALSE; + + if ((prAdapter == NULL) + || (pucIE == NULL) + || (prBssInfo == NULL) + || (prSwRfb == NULL)) { + ASSERT(FALSE); + return FALSE; + } + +#if 0 /* SW migration 2010/8/20 */ + /* Note: we shall not update parameters when scanning, otherwise + * channel and bandwidth will not be correct or asserted failure + * during scanning. + * Note: remove channel checking. All received Beacons should be processed + * if measurement or other actions are executed in adjacent channels + * and Beacon content checking mechanism is not disabled. + */ + if (IS_SCAN_ACTIVE() + /* || prBssInfo->ucPrimaryChannel != CHNL_NUM_BY_SWRFB(prSwRfb) */ + ) { + return FALSE; + } +#endif + + /* Handle change of slot time */ + prBssInfo->u2CapInfo = ((P_WLAN_BEACON_FRAME_T) (prSwRfb->pvHeader))->u2CapInfo; + prBssInfo->fgUseShortSlotTime = (prBssInfo->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME) ? TRUE : FALSE; + + rBssRlmParam.ucRfBand = (UINT_8) prBssInfo->eBand; + rBssRlmParam.ucPrimaryChannel = prBssInfo->ucPrimaryChannel; + rBssRlmParam.ucRfSco = (UINT_8) prBssInfo->eBssSCO; + rBssRlmParam.ucErpProtectMode = (UINT_8) prBssInfo->fgErpProtectMode; + rBssRlmParam.ucHtProtectMode = (UINT_8) prBssInfo->eHtProtectMode; + rBssRlmParam.ucGfOperationMode = (UINT_8) prBssInfo->eGfOperationMode; + rBssRlmParam.ucTxRifsMode = (UINT_8) prBssInfo->eRifsOperationMode; + rBssRlmParam.u2HtOpInfo3 = prBssInfo->u2HtOpInfo3; + rBssRlmParam.u2HtOpInfo2 = prBssInfo->u2HtOpInfo2; + rBssRlmParam.ucHtOpInfo1 = prBssInfo->ucHtOpInfo1; + rBssRlmParam.ucUseShortPreamble = prBssInfo->fgUseShortPreamble; + rBssRlmParam.ucUseShortSlotTime = prBssInfo->fgUseShortSlotTime; + + rlmRecIeInfoForClient(prAdapter, prBssInfo, pucIE, u2IELength); + + if (rBssRlmParam.ucRfBand != prBssInfo->eBand + || rBssRlmParam.ucPrimaryChannel != prBssInfo->ucPrimaryChannel + || rBssRlmParam.ucRfSco != prBssInfo->eBssSCO + || rBssRlmParam.ucErpProtectMode != prBssInfo->fgErpProtectMode + || rBssRlmParam.ucHtProtectMode != prBssInfo->eHtProtectMode + || rBssRlmParam.ucGfOperationMode != prBssInfo->eGfOperationMode + || rBssRlmParam.ucTxRifsMode != prBssInfo->eRifsOperationMode + || rBssRlmParam.u2HtOpInfo3 != prBssInfo->u2HtOpInfo3 + || rBssRlmParam.u2HtOpInfo2 != prBssInfo->u2HtOpInfo2 + || rBssRlmParam.ucHtOpInfo1 != prBssInfo->ucHtOpInfo1 + || rBssRlmParam.ucUseShortPreamble != prBssInfo->fgUseShortPreamble + || rBssRlmParam.ucUseShortSlotTime != prBssInfo->fgUseShortSlotTime) + fgNewParameter = TRUE; + else { + DBGLOG(RLM, TRACE, "prBssInfo's params are all the same! not to sync!\n"); + fgNewParameter = FALSE; + } + + return fgNewParameter; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmProcessBcn(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength) +{ + P_BSS_INFO_T prBssInfo; + BOOLEAN fgNewParameter; + UINT_8 ucNetIdx; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + ASSERT(pucIE); + + fgNewParameter = FALSE; + + /* When concurrent networks exist, GO shall have the same handle as + * the other BSS, so the Beacon shall be processed for bandwidth and + * protection mechanism. + * Note1: we do not have 2 AP (GO) cases simultaneously now. + * Note2: If we are GO, concurrent AIS AP should detect it and reflect + * action in its Beacon, so AIS STA just follows Beacon from AP. + */ + RLM_NET_FOR_EACH_NO_BOW(ucNetIdx) { + prBssInfo = &prAdapter->rWifiVar.arBssInfo[ucNetIdx]; + ASSERT(prBssInfo); + + if (IS_BSS_ACTIVE(prBssInfo)) { + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE && + prBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + /* P2P client or AIS infra STA */ + if (EQUAL_MAC_ADDR(prBssInfo->aucBSSID, ((P_WLAN_MAC_MGMT_HEADER_T) + (prSwRfb->pvHeader))->aucBSSID)) { + + fgNewParameter = rlmRecBcnInfoForClient(prAdapter, + prBssInfo, prSwRfb, pucIE, u2IELength); + } else { + fgNewParameter = rlmRecBcnFromNeighborForClient(prAdapter, + prBssInfo, prSwRfb, pucIE, + u2IELength); + } + } +#if CFG_ENABLE_WIFI_DIRECT + else if (prAdapter->fgIsP2PRegistered && + (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT || + prBssInfo->eCurrentOPMode == OP_MODE_P2P_DEVICE)) { + /* AP scan to check if 20/40M bandwidth is permitted */ + rlmRecBcnFromNeighborForClient(prAdapter, prBssInfo, prSwRfb, pucIE, u2IELength); + } +#endif + else if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + /* Do nothing */ + /* To do: Ad-hoc */ + } + + /* Appy new parameters if necessary */ + if (fgNewParameter) { + DBGLOG(RLM, TRACE, "rlmProcessBcn\n"); + rlmSyncOperationParams(prAdapter, prBssInfo); + fgNewParameter = FALSE; + } + } /* end of IS_BSS_ACTIVE() */ + } /* end of RLM_NET_FOR_EACH_NO_BOW */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function should be invoked after judging successful association. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmProcessAssocRsp(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + UINT_8 ucPriChannel; + UINT_16 u2Offset; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + ASSERT(pucIE); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ASSERT(prStaRec); + if (!prStaRec) + return; + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; + ASSERT(prStaRec == prBssInfo->prStaRecOfAP); + + /* To do: the invoked function is used to clear all members. It may be + * done by center mechanism in invoker. + */ + rlmBssReset(prAdapter, prBssInfo); + + prBssInfo->fgUseShortSlotTime = (prBssInfo->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME) ? TRUE : FALSE; + + ucPriChannel = rlmRecIeInfoForClient(prAdapter, prBssInfo, pucIE, u2IELength); + if (ucPriChannel > 0) + prBssInfo->ucPrimaryChannel = ucPriChannel; + + if (!RLM_NET_IS_11N(prBssInfo) || !(prStaRec->u2HtCapInfo & HT_CAP_INFO_SUP_CHNL_WIDTH)) + prBssInfo->fg40mBwAllowed = FALSE; + + /* Note: Update its capabilities to WTBL by cnmStaRecChangeState(), which + * shall be invoked afterwards. + * Update channel, bandwidth and protection mode by nicUpdateBss() + */ +#if FIX_P2P_HT20 + if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + + DBGLOG(P2P, WARN, "Force P2P BW to 20\n"); + prBssInfo->fgAssoc40mBwAllowed = FALSE; + } +#endif + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_BSS_MAX_IDLE_PERIOD: + { + struct IE_BSS_MAX_IDLE_PERIOD *prBssMaxIdle = (struct IE_BSS_MAX_IDLE_PERIOD *)pucIE; + + prStaRec->u2MaxIdlePeriod = prBssMaxIdle->u2MaxIdlePeriod; + prStaRec->ucIdleOption = prBssMaxIdle->ucIdleOption; + break; + } + default: + break; + } /* end of switch */ + } /* end of IE_FOR_EACH */ + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function should be invoked after judging successful association. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmFillSyncCmdParam(P_CMD_SET_BSS_RLM_PARAM_T prCmdBody, P_BSS_INFO_T prBssInfo) +{ + ASSERT(prCmdBody && prBssInfo); + if (!prCmdBody || !prBssInfo) + return; + + prCmdBody->ucNetTypeIndex = prBssInfo->ucNetTypeIndex; + prCmdBody->ucRfBand = (UINT_8) prBssInfo->eBand; + prCmdBody->ucPrimaryChannel = prBssInfo->ucPrimaryChannel; + prCmdBody->ucRfSco = (UINT_8) prBssInfo->eBssSCO; + prCmdBody->ucErpProtectMode = (UINT_8) prBssInfo->fgErpProtectMode; + prCmdBody->ucHtProtectMode = (UINT_8) prBssInfo->eHtProtectMode; + prCmdBody->ucGfOperationMode = (UINT_8) prBssInfo->eGfOperationMode; + prCmdBody->ucTxRifsMode = (UINT_8) prBssInfo->eRifsOperationMode; + prCmdBody->u2HtOpInfo3 = prBssInfo->u2HtOpInfo3; + prCmdBody->u2HtOpInfo2 = prBssInfo->u2HtOpInfo2; + prCmdBody->ucHtOpInfo1 = prBssInfo->ucHtOpInfo1; + prCmdBody->ucUseShortPreamble = prBssInfo->fgUseShortPreamble; + prCmdBody->ucUseShortSlotTime = prBssInfo->fgUseShortSlotTime; + prCmdBody->ucCheckId = 0x72; + + if (RLM_NET_PARAM_VALID(prBssInfo)) { + DBGLOG(RLM, INFO, "N=%d b=%d c=%d s=%d e=%d h=%d I=0x%02x l=%d p=%d\n", + prCmdBody->ucNetTypeIndex, prCmdBody->ucRfBand, + prCmdBody->ucPrimaryChannel, prCmdBody->ucRfSco, + prCmdBody->ucErpProtectMode, prCmdBody->ucHtProtectMode, + prCmdBody->ucHtOpInfo1, prCmdBody->ucUseShortSlotTime, + prCmdBody->ucUseShortPreamble); + } else { + DBGLOG(RLM, TRACE, "N=%d closed\n", prCmdBody->ucNetTypeIndex); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will operation parameters based on situations of +* concurrent networks. Channel, bandwidth, protection mode, supported +* rate will be modified. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmSyncOperationParams(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) +{ + P_CMD_SET_BSS_RLM_PARAM_T prCmdBody; + WLAN_STATUS rStatus; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + + prCmdBody = (P_CMD_SET_BSS_RLM_PARAM_T) + cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_SET_BSS_RLM_PARAM_T)); + ASSERT(prCmdBody); + + /* To do: exception handle */ + if (!prCmdBody) { + DBGLOG(RLM, WARN, "No buf for sync RLM params (Net=%d)\n", prBssInfo->ucNetTypeIndex); + return; + } + + rlmFillSyncCmdParam(prCmdBody, prBssInfo); + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_BSS_RLM_PARAM, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_SET_BSS_RLM_PARAM_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdBody, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); + + cnmMemFree(prAdapter, prCmdBody); +} + +#if CFG_SUPPORT_AAA +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function should be invoked after judging successful association. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmProcessAssocReq(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + UINT_16 u2Offset; + P_IE_HT_CAP_T prHtCap; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + ASSERT(pucIE); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ASSERT(prStaRec); + if (!prStaRec) + return; + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_HT_CAP: + if (!RLM_NET_IS_11N(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_HT_CAP_T) - 2)) + break; + prHtCap = (P_IE_HT_CAP_T) pucIE; + prStaRec->ucMcsSet = prHtCap->rSupMcsSet.aucRxMcsBitmask[0]; + prStaRec->fgSupMcs32 = (prHtCap->rSupMcsSet.aucRxMcsBitmask[32 / 8] & BIT(0)) ? TRUE : FALSE; + + prStaRec->u2HtCapInfo = prHtCap->u2HtCapInfo; + prStaRec->ucAmpduParam = prHtCap->ucAmpduParam; + prStaRec->u2HtExtendedCap = prHtCap->u2HtExtendedCap; + prStaRec->u4TxBeamformingCap = prHtCap->u4TxBeamformingCap; + prStaRec->ucAselCap = prHtCap->ucAselCap; + break; + + default: + break; + } /* end of switch */ + } /* end of IE_FOR_EACH */ +} +#endif /* CFG_SUPPORT_AAA */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief It is for both STA and AP modes +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmBssInitForAPandIbss(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) +{ + ASSERT(prAdapter); + ASSERT(prBssInfo); + +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered && prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) + rlmBssInitForAP(prAdapter, prBssInfo); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief It is for both STA and AP modes +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmBssAborted(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) +{ + ASSERT(prAdapter); + ASSERT(prBssInfo); + + rlmBssReset(prAdapter, prBssInfo); + + prBssInfo->fg40mBwAllowed = FALSE; + prBssInfo->fgAssoc40mBwAllowed = FALSE; + + /* Assume FW state is updated by CMD_ID_SET_BSS_INFO, so + * the sync CMD is not needed here. + */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief All RLM timers will also be stopped. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static VOID rlmBssReset(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) +{ + ASSERT(prAdapter); + ASSERT(prBssInfo); + + /* HT related parameters */ + prBssInfo->ucHtOpInfo1 = 0; /* RIFS disabled. 20MHz */ + prBssInfo->u2HtOpInfo2 = 0; + prBssInfo->u2HtOpInfo3 = 0; + + prBssInfo->eBssSCO = 0; + prBssInfo->fgErpProtectMode = 0; + prBssInfo->eHtProtectMode = 0; + prBssInfo->eGfOperationMode = 0; + prBssInfo->eRifsOperationMode = 0; + + /* OBSS related parameters */ + prBssInfo->auc2G_20mReqChnlList[0] = 0; + prBssInfo->auc2G_NonHtChnlList[0] = 0; + prBssInfo->auc2G_PriChnlList[0] = 0; + prBssInfo->auc2G_SecChnlList[0] = 0; + prBssInfo->auc5G_20mReqChnlList[0] = 0; + prBssInfo->auc5G_NonHtChnlList[0] = 0; + prBssInfo->auc5G_PriChnlList[0] = 0; + prBssInfo->auc5G_SecChnlList[0] = 0; + + /* All RLM timers will also be stopped */ + cnmTimerStopTimer(prAdapter, &prBssInfo->rObssScanTimer); + prBssInfo->u2ObssScanInterval = 0; + + prBssInfo->fgObssErpProtectMode = 0; /* GO only */ + prBssInfo->eObssHtProtectMode = 0; /* GO only */ + prBssInfo->eObssGfOperationMode = 0; /* GO only */ + prBssInfo->fgObssRifsOperationMode = 0; /* GO only */ + prBssInfo->fgObssActionForcedTo20M = 0; /* GO only */ + prBssInfo->fgObssBeaconForcedTo20M = 0; /* GO only */ +} + +#if CFG_SUPPORT_DFS /* Add by Enlai */ +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function handle spectrum management action frame +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmProcessSpecMgtAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) +{ + P_ACTION_CHANNEL_SWITCH_FRAME prRxFrame; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + DBGLOG(RLM, INFO, "[5G DFS]rlmProcessSpecMgtAction \r\n"); + + prRxFrame = (P_ACTION_CHANNEL_SWITCH_FRAME) prSwRfb->pvHeader; + DBGLOG(RLM, INFO, "[5G DFS]prRxFrame->ucAction[%d] \r\n", prRxFrame->ucAction); + if (prRxFrame->ucAction == ACTION_CHNL_SWITCH) + rlmProcessChannelSwitchIE(prAdapter, (P_IE_CHANNEL_SWITCH_T) prRxFrame->aucInfoElem); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function process Channel Switch IE +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmProcessChannelSwitchIE(P_ADAPTER_T prAdapter, P_IE_CHANNEL_SWITCH_T prChannelSwitchIE) +{ + P_BSS_INFO_T prAisBssInfo; + + ASSERT(prAdapter); + ASSERT(prChannelSwitchIE); + + DBGLOG(RLM, INFO, "[5G DFS] rlmProcessChannelSwitchIE \r\n"); + DBGLOG(RLM, INFO, "[5G DFS] ucChannelSwitchMode[%d], ucChannelSwitchCount[%d], ucNewChannelNum[%d] \r\n", + prChannelSwitchIE->ucChannelSwitchMode, + prChannelSwitchIE->ucChannelSwitchCount, prChannelSwitchIE->ucNewChannelNum); + if (prChannelSwitchIE->ucChannelSwitchMode == 1) { + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + DBGLOG(RLM, INFO, "[5G DFS] switch channel [%d]->[%d] \r\n", prAisBssInfo->ucPrimaryChannel, + prChannelSwitchIE->ucNewChannelNum); + prAisBssInfo->ucPrimaryChannel = prChannelSwitchIE->ucNewChannelNum; + nicUpdateBss(prAdapter, prAisBssInfo->ucNetTypeIndex); + } + +} + +#endif + +#if (CFG_SUPPORT_TXR_ENC == 1) +VOID +rlmTxRateEnhanceConfig( + P_ADAPTER_T prAdapter + ) +{ + P_GLUE_INFO_T prGlueInfo; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + CMD_RLM_INFO_T rTxRInfo; + UINT_32 u4SetInfoLen = 0; + + + /* init */ + prGlueInfo = prAdapter->prGlueInfo; + + /* suggestion from Tsaiyuan.Hsu */ + kalMemZero(&rTxRInfo, sizeof(CMD_RLM_INFO_T)); + rTxRInfo.fgIsErrRatioEnhanceApplied = TRUE; + rTxRInfo.ucErrRatio2LimitMinRate = 3; + rTxRInfo.ucMinLegacyRateIdx = 2; + rTxRInfo.cMinRssiThreshold = -60; + rTxRInfo.fgIsRtsApplied = TRUE; + rTxRInfo.ucRecoverTime = 60; + + DBGLOG(RLM, INFO, "Enable tx rate enhance function\n"); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetTxRateInfo, + &rTxRInfo, + sizeof(rTxRInfo), + TRUE, + TRUE, + TRUE, + FALSE, + &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(RLM, WARN, "set tx rate advance info fail 0x%lx\n", rStatus); +} + + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to send a command to TX Auto Rate module. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmCmd(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + UINT_32 u4Subcmd; + + + /* parse TAR sub-command */ + u4Subcmd = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + DBGLOG(RLM, INFO, " sub command = %u\n", (UINT32)u4Subcmd); + + /* handle different sub-command */ + switch (u4Subcmd) { + case 0x00: /* configure */ + /* iwpriv wlan0 set_str_cmd 1_0_0_1_3_2_60_1_60 */ + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + CMD_RLM_INFO_T rTxRInfo; + UINT_32 u4SetInfoLen = 0; + + kalMemZero(&rTxRInfo, sizeof(CMD_RLM_INFO_T)); + rTxRInfo.u4Version = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rTxRInfo.fgIsErrRatioEnhanceApplied = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rTxRInfo.ucErrRatio2LimitMinRate = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rTxRInfo.ucMinLegacyRateIdx = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rTxRInfo.cMinRssiThreshold = 0 - CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rTxRInfo.fgIsRtsApplied = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rTxRInfo.ucRecoverTime = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(RLM, INFO, " rlmCmd = %u %u %u %u %d %u %u\n", + rTxRInfo.u4Version, + rTxRInfo.fgIsErrRatioEnhanceApplied, + rTxRInfo.ucErrRatio2LimitMinRate, + rTxRInfo.ucMinLegacyRateIdx, + rTxRInfo.cMinRssiThreshold, + rTxRInfo.fgIsRtsApplied, + rTxRInfo.ucRecoverTime)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetTxRateInfo, + &rTxRInfo, + sizeof(rTxRInfo), + TRUE, + TRUE, + TRUE, + FALSE, + &u4SetInfoLen); + break; + + default: + break; + } +} +#endif /* CFG_SUPPORT_TXR_ENC */ + +VOID rlmComposeEmptyBeaconReport(P_ADAPTER_T prAdapter) +{ + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq = &prAdapter->rWifiVar.rRmReqParams; + struct RADIO_MEASUREMENT_REPORT_PARAMS *prRmRep = &prAdapter->rWifiVar.rRmRepParams; + PUINT_8 pucReportFrame = prRmRep->pucReportFrameBuff + prRmRep->u2ReportFrameLen; + P_IE_MEASUREMENT_REPORT_T prRepIE = (P_IE_MEASUREMENT_REPORT_T)pucReportFrame; + struct RM_BCN_REPORT *prBcnReport = (struct RM_BCN_REPORT *)prRepIE->aucReportFields; + + /* fill in basic content of Measurement report IE */ + prRepIE->ucId = ELEM_ID_MEASUREMENT_REPORT; + prRepIE->ucToken = prRmReq->prCurrMeasElem->ucToken; + prRepIE->ucMeasurementType = prRmReq->prCurrMeasElem->ucMeasurementType; + prRepIE->ucReportMode = 0; + prRepIE->ucLength = 3 + OFFSET_OF(struct RM_BCN_REPORT, aucOptElem); + kalMemZero(prBcnReport, OFFSET_OF(struct RM_BCN_REPORT, aucOptElem)); + prBcnReport->ucRegulatoryClass = 255; /* 255 means reglatory is not available */ + prBcnReport->ucChannel = 255; /* 255 means channel is not available */ + prBcnReport->ucReportInfo = 255; /* 255 means report frame info is not available */ + prBcnReport->ucRSNI = 255; /* 255 means RSNI is not available */ + prBcnReport->ucAntennaID = 1; + + prRmRep->u2ReportFrameLen += IE_SIZE(&prRepIE); +} + +VOID rlmFreeMeasurementResources(P_ADAPTER_T prAdapter) +{ + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq = &prAdapter->rWifiVar.rRmReqParams; + struct RADIO_MEASUREMENT_REPORT_PARAMS *prRmRep = &prAdapter->rWifiVar.rRmRepParams; + struct RM_MEASURE_REPORT_ENTRY *prReportEntry = NULL; + P_LINK_T prReportLink = &prRmRep->rReportLink; + P_LINK_T prFreeReportLink = &prRmRep->rFreeReportLink; + + kalMemFree(prRmReq->pucReqIeBuf, VIR_MEM_TYPE, prRmReq->u2ReqIeBufLen); + kalMemFree(prRmRep->pucReportFrameBuff, VIR_MEM_TYPE, RM_REPORT_FRAME_MAX_LENGTH); + while (!LINK_IS_EMPTY(prReportLink)) { + LINK_REMOVE_HEAD(prReportLink, prReportEntry, struct RM_MEASURE_REPORT_ENTRY *); + kalMemFree(prReportEntry, VIR_MEM_TYPE, sizeof(*prReportEntry)); + } + while (!LINK_IS_EMPTY(prFreeReportLink)) { + LINK_REMOVE_HEAD(prFreeReportLink, prReportEntry, struct RM_MEASURE_REPORT_ENTRY *); + kalMemFree(prReportEntry, VIR_MEM_TYPE, sizeof(*prReportEntry)); + } + kalMemZero(prRmReq, sizeof(*prRmReq)); + kalMemZero(prRmRep, sizeof(*prRmRep)); + prRmReq->rBcnRmParam.eState = RM_NO_REQUEST; + prRmReq->fgRmIsOngoing = FALSE; + LINK_INITIALIZE(&prRmRep->rFreeReportLink); + LINK_INITIALIZE(&prRmRep->rReportLink); +} + +/* purpose: check if Radio Measurement is done */ +static BOOLEAN rlmAllMeasurementIssued(struct RADIO_MEASUREMENT_REQ_PARAMS *prReq) +{ + return prReq->u2RemainReqLen > IE_SIZE(prReq->prCurrMeasElem) ? FALSE : TRUE; +} + +VOID rlmComposeIncapableRmRep( + struct RADIO_MEASUREMENT_REPORT_PARAMS *prRep, UINT_8 ucToken, UINT_8 ucMeasType) +{ + P_IE_MEASUREMENT_REPORT_T prRepIE = + (P_IE_MEASUREMENT_REPORT_T)(prRep->pucReportFrameBuff + prRep->u2ReportFrameLen); + + prRepIE->ucId = ELEM_ID_MEASUREMENT_REPORT; + prRepIE->ucToken = ucToken; + prRepIE->ucMeasurementType = ucMeasType; + prRepIE->ucLength = 3; + prRepIE->ucReportMode = RM_REP_MODE_INCAPABLE; + prRep->u2ReportFrameLen += 5; +} +/* Purpose: Interative processing Measurement Request Element. If it is not the first element, + will copy all collected report element to the report frame buffer. and may tx the radio report frame. + prAdapter: pointer to the Adapter + fgNewStarted: if it is the first element in measurement request frame +*/ +VOID rlmStartNextMeasurement(P_ADAPTER_T prAdapter, BOOLEAN fgNewStarted) +{ + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq = &prAdapter->rWifiVar.rRmReqParams; + struct RADIO_MEASUREMENT_REPORT_PARAMS *prRmRep = &prAdapter->rWifiVar.rRmRepParams; + P_IE_MEASUREMENT_REQ_T prCurrReq = prRmReq->prCurrMeasElem; + UINT_16 u2RandomTime = 0; + +schedule_next: + if (!prRmReq->fgRmIsOngoing) { + DBGLOG(RLM, INFO, "Rm has been stopped\n"); + return; + } + /* we don't support parallel measurement now */ + if (prCurrReq->ucRequestMode & RM_REQ_MODE_PARALLEL_BIT) { + DBGLOG(RLM, WARN, "Parallel request, compose incapable report\n"); + if (prRmRep->u2ReportFrameLen + 5 > RM_REPORT_FRAME_MAX_LENGTH) + rlmTxRadioMeasurementReport(prAdapter); + rlmComposeIncapableRmRep(prRmRep, prCurrReq->ucToken, prCurrReq->ucMeasurementType); + if (rlmAllMeasurementIssued(prRmReq)) { + if (prRmReq->rBcnRmParam.fgExistBcnReq && RM_EXIST_REPORT(prRmRep)) + rlmComposeEmptyBeaconReport(prAdapter); + rlmTxRadioMeasurementReport(prAdapter); + + /* repeat measurement if repetitions is required and not only parallel measurements. + ** otherwise, no need to repeat, it is not make sense to do that. + */ + if (prRmReq->u2Repetitions > 0) { + prRmReq->fgInitialLoop = FALSE; + prRmReq->u2Repetitions--; + prCurrReq = prRmReq->prCurrMeasElem = (P_IE_MEASUREMENT_REQ_T)prRmReq->pucReqIeBuf; + prRmReq->u2RemainReqLen = prRmReq->u2ReqIeBufLen; + } else { + rlmFreeMeasurementResources(prAdapter); + DBGLOG(RLM, INFO, "Radio Measurement done\n"); + return; + } + } else { + UINT_16 u2IeSize = IE_SIZE(prRmReq->prCurrMeasElem); + + prCurrReq = prRmReq->prCurrMeasElem = + (P_IE_MEASUREMENT_REQ_T)((PUINT_8)prRmReq->prCurrMeasElem + u2IeSize); + prRmReq->u2RemainReqLen -= u2IeSize; + } + fgNewStarted = FALSE; + goto schedule_next; + } + /* copy collected measurement report for specific measurement type */ + if (!fgNewStarted) { + struct RM_MEASURE_REPORT_ENTRY *prReportEntry = NULL; + P_LINK_T prReportLink = &prRmRep->rReportLink; + P_LINK_T prFreeReportLink = &prRmRep->rFreeReportLink; + PUINT_8 pucReportFrame = prRmRep->pucReportFrameBuff + prRmRep->u2ReportFrameLen; + UINT_16 u2IeSize = 0; + BOOLEAN fgNewLoop = FALSE; + + DBGLOG(RLM, INFO, "total %u report element for current request\n", prReportLink->u4NumElem); + /* copy collected report into the Measurement Report Frame Buffer. */ + while (1) { + LINK_REMOVE_HEAD(prReportLink, prReportEntry, struct RM_MEASURE_REPORT_ENTRY *); + if (!prReportEntry) + break; + u2IeSize = IE_SIZE(prReportEntry->aucMeasReport); + /* if reach the max length of a MMPDU size, send a Rm report first */ + if (u2IeSize + prRmRep->u2ReportFrameLen > RM_REPORT_FRAME_MAX_LENGTH) { + rlmTxRadioMeasurementReport(prAdapter); + pucReportFrame = prRmRep->pucReportFrameBuff + prRmRep->u2ReportFrameLen; + } + kalMemCopy(pucReportFrame, prReportEntry->aucMeasReport, u2IeSize); + pucReportFrame += u2IeSize; + prRmRep->u2ReportFrameLen += u2IeSize; + LINK_INSERT_TAIL(prFreeReportLink, &prReportEntry->rLinkEntry); + } + /* if Measurement is done, free report element memory */ + if (rlmAllMeasurementIssued(prRmReq)) { + if (prRmReq->rBcnRmParam.fgExistBcnReq && RM_EXIST_REPORT(prRmRep)) + rlmComposeEmptyBeaconReport(prAdapter); + rlmTxRadioMeasurementReport(prAdapter); + + /* repeat measurement if repetitions is required */ + if (prRmReq->u2Repetitions > 0) { + fgNewLoop = TRUE; + prRmReq->fgInitialLoop = FALSE; + prRmReq->u2Repetitions--; + prRmReq->prCurrMeasElem = (P_IE_MEASUREMENT_REQ_T)prRmReq->pucReqIeBuf; + prRmReq->u2RemainReqLen = prRmReq->u2ReqIeBufLen; + } else { + /* don't free radio measurement resource due to TSM is running */ + if (!wmmTsmIsOngoing(prAdapter)) { + rlmFreeMeasurementResources(prAdapter); + DBGLOG(RLM, INFO, "Radio Measurement done\n"); + } + return; + } + } + if (!fgNewLoop) { + u2IeSize = IE_SIZE(prRmReq->prCurrMeasElem); + prCurrReq = prRmReq->prCurrMeasElem = + (P_IE_MEASUREMENT_REQ_T)((PUINT_8)prRmReq->prCurrMeasElem + u2IeSize); + prRmReq->u2RemainReqLen -= u2IeSize; + } + } + + /* do specific measurement */ + switch (prCurrReq->ucMeasurementType) { + case ELEM_RM_TYPE_BEACON_REQ: + { + P_RM_BCN_REQ_T prBeaconReq = (P_RM_BCN_REQ_T)&prCurrReq->aucRequestFields[0]; + + if (!prRmReq->fgInitialLoop) { + /* If this is the repeating measurement, then wait next scan done */ + prRmReq->rBcnRmParam.eState = RM_WAITING; + break; + } + if (prBeaconReq->u2RandomInterval == 0) + rlmDoBeaconMeasurement(prAdapter, 0); + else { + get_random_bytes(&u2RandomTime, 2); + u2RandomTime = (u2RandomTime * prBeaconReq->u2RandomInterval) / 65535; + u2RandomTime = TU_TO_MSEC(u2RandomTime); + if (u2RandomTime > 0) { + cnmTimerStopTimer(prAdapter, &rBeaconReqTimer); + cnmTimerInitTimer(prAdapter, &rBeaconReqTimer, rlmDoBeaconMeasurement, 0); + cnmTimerStartTimer(prAdapter, &rBeaconReqTimer, u2RandomTime); + } else + rlmDoBeaconMeasurement(prAdapter, 0); + } + break; + } + case ELEM_RM_TYPE_TSM_REQ: + { + P_RM_TS_MEASURE_REQ_T prTsmReqIE = (P_RM_TS_MEASURE_REQ_T)&prCurrReq->aucRequestFields[0]; + struct RM_TSM_REQ *prTsmReq = NULL; + UINT_16 u2OffSet = 0; + PUINT_8 pucIE = prTsmReqIE->aucSubElements; + P_ACTION_RM_REPORT_FRAME prReportFrame = NULL; + + /* In case of repeating measurement, no need to start triggered measurement again. + ** According to current specification of Radio Measurement, only TSM has the triggered + ** type of measurement. + */ + if ((prCurrReq->ucRequestMode & RM_REQ_MODE_ENABLE_BIT) && !prRmReq->fgInitialLoop) + goto schedule_next; + + /* if enable bit is 1 and report bit is 0, need to stop all triggered TSM measurement */ + if ((prCurrReq->ucRequestMode & (RM_REQ_MODE_ENABLE_BIT|RM_REQ_MODE_REPORT_BIT)) == + RM_REQ_MODE_ENABLE_BIT) { + wmmRemoveAllTsmMeasurement(prAdapter, TRUE); + break; + } + prTsmReq = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(struct RM_TSM_REQ)); + if (!prTsmReq) { + DBGLOG(RLM, ERROR, "No memory\n"); + break; + } + prTsmReq->ucToken = prCurrReq->ucToken; + prTsmReq->u2Duration = prTsmReqIE->u2Duration; + prTsmReq->ucTID = (prTsmReqIE->ucTrafficID & 0xf0) >> 4; + prTsmReq->ucB0Range = prTsmReqIE->ucBin0Range; + prReportFrame = (P_ACTION_RM_REPORT_FRAME)prRmRep->pucReportFrameBuff; + COPY_MAC_ADDR(prTsmReq->aucPeerAddr, prReportFrame->aucDestAddr); + IE_FOR_EACH(pucIE, prCurrReq->ucLength - 3, u2OffSet) { + switch (IE_ID(pucIE)) { + case 1: /* Triggered Reporting */ + kalMemCopy(&prTsmReq->rTriggerCond, pucIE+2, IE_LEN(pucIE)); + break; + case 221: /* Vendor Specified */ + break; /* No vendor IE now */ + default: + break; + } + } + if (!prTsmReqIE->u2RandomInterval) { + wmmStartTsmMeasurement(prAdapter, (ULONG)prTsmReq); + break; + } + get_random_bytes(&u2RandomTime, 2); + u2RandomTime = (u2RandomTime * prTsmReqIE->u2RandomInterval) / 65535; + u2RandomTime = TU_TO_MSEC(u2RandomTime); + cnmTimerStopTimer(prAdapter, &rTSMReqTimer); + cnmTimerInitTimer(prAdapter, &rTSMReqTimer, wmmStartTsmMeasurement, (ULONG)prTsmReq); + cnmTimerStartTimer(prAdapter, &rTSMReqTimer, u2RandomTime); + break; + } + default: + { + if (prRmRep->u2ReportFrameLen + 5 > RM_REPORT_FRAME_MAX_LENGTH) + rlmTxRadioMeasurementReport(prAdapter); + rlmComposeIncapableRmRep(prRmRep, prCurrReq->ucToken, prCurrReq->ucMeasurementType); + fgNewStarted = FALSE; + DBGLOG(RLM, INFO, "RM type %d is not supported on this chip\n", prCurrReq->ucMeasurementType); + goto schedule_next; + } + } +} + +/* If disconnect with the target AP, radio measurement should be canceled. */ +VOID rlmCancelRadioMeasurement(P_ADAPTER_T prAdapter) +{ + BOOLEAN fgHasBcnReqTimer = timerPendingTimer(&rBeaconReqTimer); + BOOLEAN fgHasTsmTimer = timerPendingTimer(&rTSMReqTimer); + + DBGLOG(RLM, INFO, "Cancel measurement, Beacon Req timer is %d and TSM Req timer is %d\n", + fgHasBcnReqTimer, fgHasTsmTimer); + if (fgHasBcnReqTimer) + cnmTimerStopTimer(prAdapter, &rBeaconReqTimer); + if (fgHasTsmTimer) + cnmTimerStopTimer(prAdapter, &rTSMReqTimer); + rlmFreeMeasurementResources(prAdapter); +} + +BOOLEAN rlmBcnRmRunning(P_ADAPTER_T prAdapter) +{ + return prAdapter->rWifiVar.rRmReqParams.rBcnRmParam.eState == RM_ON_GOING; +} + +BOOLEAN rlmFillScanMsg(P_ADAPTER_T prAdapter, P_MSG_SCN_SCAN_REQ prMsg) +{ + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq = &prAdapter->rWifiVar.rRmReqParams; + P_IE_MEASUREMENT_REQ_T prCurrReq = NULL; + P_RM_BCN_REQ_T prBeaconReq = NULL; + UINT_16 u2RemainLen = 0; + PUINT_8 pucSubIE = NULL; + + if (prRmReq->rBcnRmParam.eState != RM_ON_GOING || !prMsg) + return FALSE; + + prCurrReq = prRmReq->prCurrMeasElem; + prBeaconReq = (P_RM_BCN_REQ_T)&prCurrReq->aucRequestFields[0]; + prMsg->ucSSIDType = SCAN_REQ_SSID_WILDCARD; + switch (prBeaconReq->ucMeasurementMode) { + case RM_BCN_REQ_PASSIVE_MODE: + prMsg->eScanType = SCAN_TYPE_PASSIVE_SCAN; + break; + case RM_BCN_REQ_ACTIVE_MODE: + prMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; + break; + } + + WLAN_GET_FIELD_16(&prBeaconReq->u2Duration, &prMsg->u2ChannelDwellTime); + COPY_MAC_ADDR(prMsg->aucBSSID, prBeaconReq->aucBssid); +#if 0 /* debug specific bssid scan */ + kalMemCopy(prMsg->aucBSSID, "\x74\x67\xf7\x17\xf4\xd0", MAC_ADDR_LEN); +#endif + /* if mandatory bit is set, we should do */ + if (prCurrReq->ucRequestMode & RM_REQ_MODE_DURATION_MANDATORY_BIT) + prMsg->u2MinChannelDwellTime = prMsg->u2ChannelDwellTime; + else + prMsg->u2MinChannelDwellTime = (prMsg->u2ChannelDwellTime * 2) / 3; + if (prBeaconReq->ucChannel == 0) + prMsg->eScanChannel = SCAN_CHANNEL_FULL; + else if (prBeaconReq->ucChannel == 255) { /* latest Ap Channel Report */ + P_BSS_DESC_T prBssDesc = prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc; + PUINT_8 pucChnl = NULL; + UINT_8 ucChnlNum = 0; + UINT_8 ucIndex = 0; + P_RF_CHANNEL_INFO_T prChnlInfo = prMsg->arChnlInfoList; + + prMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; + prMsg->ucChannelListNum = 0; + if (prBssDesc) { + PUINT_8 pucIE = NULL; + UINT_16 u2IELength = 0; + UINT_16 u2Offset = 0; + + pucIE = prBssDesc->aucIEBuf; + u2IELength = prBssDesc->u2IELength; + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (IE_ID(pucIE) != ELEM_ID_AP_CHANNEL_REPORT) + continue; + pucChnl = ((struct IE_AP_CHNL_REPORT_T *)pucIE)->aucChnlList; + ucChnlNum = pucIE[1] - 1; + DBGLOG(RLM, INFO, "Channel number in latest AP channel report %d\n", ucChnlNum); + while (ucIndex < ucChnlNum && + prMsg->ucChannelListNum < MAXIMUM_OPERATION_CHANNEL_LIST) { + if (pucChnl[ucIndex] <= 14) + prChnlInfo[prMsg->ucChannelListNum].eBand = BAND_2G4; + else + prChnlInfo[prMsg->ucChannelListNum].eBand = BAND_5G; + prChnlInfo[prMsg->ucChannelListNum].ucChannelNum = pucChnl[ucIndex]; + prMsg->ucChannelListNum++; + ucIndex++; + } + } + } + } else { + prMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; + prMsg->ucChannelListNum = 1; + prMsg->arChnlInfoList[0].ucChannelNum = prBeaconReq->ucChannel; + if (prBeaconReq->ucChannel <= 14) + prMsg->arChnlInfoList[0].eBand = BAND_2G4; + else + prMsg->arChnlInfoList[0].eBand = BAND_5G; + } + u2RemainLen = prCurrReq->ucLength - 3 - OFFSET_OF(RM_BCN_REQ_T, aucSubElements); + pucSubIE = &prBeaconReq->aucSubElements[0]; + while (u2RemainLen > 0) { + if (IE_SIZE(pucSubIE) > u2RemainLen) + break; + switch (pucSubIE[0]) { + case 0: /* SSID */ + /* length of sub-element ssid is 0 or first byte is 0, means wildcard ssid matching */ + if (!IE_LEN(pucSubIE) || !pucSubIE[2]) + break; + COPY_SSID(prMsg->aucSSID, prMsg->ucSSIDLength, &pucSubIE[2], pucSubIE[1]); + prMsg->ucSSIDType = SCAN_REQ_SSID_SPECIFIED_ONLY; + break; + case 51: /* AP channel report */ + { + struct IE_AP_CHNL_REPORT_T *prApChnl = (struct IE_AP_CHNL_REPORT_T *)pucSubIE; + UINT_8 ucChannelCnt = prApChnl->ucLength - 1; + UINT_8 ucIndex = 0; + + if (prBeaconReq->ucChannel == 0) + break; + prMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; + DBGLOG(RLM, INFO, "Channel number in measurement AP channel report %d\n", ucChannelCnt); + while (ucIndex < ucChannelCnt && + prMsg->ucChannelListNum < MAXIMUM_OPERATION_CHANNEL_LIST) { + if (prApChnl->aucChnlList[ucIndex] <= 14) + prMsg->arChnlInfoList[prMsg->ucChannelListNum].eBand = BAND_2G4; + else + prMsg->arChnlInfoList[prMsg->ucChannelListNum].eBand = BAND_5G; + prMsg->arChnlInfoList[prMsg->ucChannelListNum].ucChannelNum = + prApChnl->aucChnlList[ucIndex]; + prMsg->ucChannelListNum++; + ucIndex++; + } + break; + } + } + u2RemainLen -= IE_SIZE(pucSubIE); + pucSubIE += IE_SIZE(pucSubIE); + } + + /* + * If an AP Channel Report is not available in the STA, the STA shall + * iteratively conduct measurements on all supported channels in the + * specified Regulatory Class that are valid for the current + * regulatory domain. + */ + if (prMsg->ucChannelListNum == 0) + prMsg->eScanChannel = SCAN_CHANNEL_FULL; + + DBGLOG(RLM, INFO, "SSIDtype %d, ScanType %d, ChnlType %d, Dwell %d, MinDwell %d, ChnlNum %d\n", + prMsg->ucSSIDType, prMsg->eScanType, prMsg->eScanChannel, prMsg->u2ChannelDwellTime, + prMsg->u2MinChannelDwellTime, prMsg->ucChannelListNum); + return TRUE; +} + +VOID rlmDoBeaconMeasurement(P_ADAPTER_T prAdapter, ULONG ulParam) +{ + P_CONNECTION_SETTINGS_T prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq = &prAdapter->rWifiVar.rRmReqParams; + P_RM_BCN_REQ_T prBcnReq = (P_RM_BCN_REQ_T)&prRmReq->prCurrMeasElem->aucRequestFields[0]; + + if (prBcnReq->ucMeasurementMode == RM_BCN_REQ_TABLE_MODE) { + P_LINK_T prBSSDescList = &prAdapter->rWifiVar.rScanInfo.rBSSDescList; + P_BSS_DESC_T prBssDesc = NULL; + struct RM_BEACON_REPORT_PARAMS rRepParams; + PUINT_16 pu2BcnInterval = (PUINT_16)&rRepParams.aucBcnFixedField[8]; + PUINT_16 pu2CapInfo = (PUINT_16)&rRepParams.aucBcnFixedField[10]; + + kalMemZero(&rRepParams, sizeof(rRepParams)); + /* if this is a one antenna only device, the antenna id is always 1. 7.3.2.40 */ + rRepParams.ucAntennaID = 1; + rRepParams.ucRSNI = 255; /* 255 means RSNI not available. see 7.3.2.41 */ + rRepParams.ucFrameInfo = 255; + + prRmReq->rBcnRmParam.eState = RM_ON_GOING; + prBcnReq->ucChannel = 0; + DBGLOG(RLM, INFO, "Beacon Table Mode, Beacon Table Num %u\n", prBSSDescList->u4NumElem); + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + rRepParams.ucRCPI = prBssDesc->ucRCPI; + rRepParams.ucChannel = prBssDesc->ucChannelNum; + kalMemCopy(&rRepParams.aucBcnFixedField, &prBssDesc->u8TimeStamp, 8); + *pu2BcnInterval = prBssDesc->u2BeaconInterval; + *pu2CapInfo = prBssDesc->u2CapInfo; + scanCollectBeaconReport(prAdapter, prBssDesc->aucIEBuf, prBssDesc->u2IELength, + prBssDesc->aucBSSID, &rRepParams); + } + rlmStartNextMeasurement(prAdapter, FALSE); + return; + } + if (prConnSettings->fgIsScanReqIssued) { + prRmReq->rBcnRmParam.eState = RM_WAITING; + } else { + prRmReq->rBcnRmParam.eState = RM_ON_GOING; + GET_CURRENT_SYSTIME(&prRmReq->rStartTime); + aisFsmScanRequest(prAdapter, NULL, NULL, 0); + } +} + +static BOOLEAN rlmRmFrameIsValid(P_SW_RFB_T prSwRfb) +{ + UINT_16 u2ElemLen = 0; + UINT_16 u2Offset = (UINT_16)OFFSET_OF(ACTION_RM_REQ_FRAME, aucInfoElem); + PUINT_8 pucIE = (PUINT_8)prSwRfb->pvHeader; + P_IE_MEASUREMENT_REQ_T prCurrMeasElem = NULL; + UINT_16 u2CalcIELen = 0; + UINT_16 u2IELen = 0; + + if (prSwRfb->u2PacketLen <= u2Offset) { + DBGLOG(RLM, ERROR, "Rm Packet length %d is too short\n", prSwRfb->u2PacketLen); + return FALSE; + } + pucIE += u2Offset; + u2ElemLen = prSwRfb->u2PacketLen - u2Offset; + IE_FOR_EACH(pucIE, u2ElemLen, u2Offset) { + u2IELen = IE_LEN(pucIE); + + /* The minimum value of the Length field is 3 (based on a minimum length for the */ + /* Measurement Request field of 0 octets) */ + if (u2IELen <= 3) { + DBGLOG(RLM, ERROR, "Abnormal RM IE length is %d\n", u2IELen); + return FALSE; + } + + /* Check whether the length of each measurment request element is reasonable */ + prCurrMeasElem = (P_IE_MEASUREMENT_REQ_T)pucIE; + switch (prCurrMeasElem->ucMeasurementType) { + case ELEM_RM_TYPE_BEACON_REQ: + if (u2IELen < (3 + OFFSET_OF(RM_BCN_REQ_T, aucSubElements))) { + DBGLOG(RLM, ERROR, "Abnormal Becaon Req IE length is %d\n", u2IELen); + return FALSE; + } + break; + case ELEM_RM_TYPE_TSM_REQ: + if (u2IELen < (3 + OFFSET_OF(RM_TS_MEASURE_REQ_T, aucSubElements))) { + DBGLOG(RLM, ERROR, "Abnormal TSM Req IE length is %d\n", u2IELen); + return FALSE; + } + break; + default: + DBGLOG(RLM, ERROR, "Not support: MeasurementType is %d, IE length is %d\n", + prCurrMeasElem->ucMeasurementType, u2IELen); + return FALSE; + } + + u2CalcIELen += IE_SIZE(pucIE); + } + if (u2CalcIELen != u2ElemLen) { + DBGLOG(RLM, ERROR, "Calculated Total IE len is not equal to received length\n"); + return FALSE; + } + return TRUE; +} +/* +*/ +VOID rlmProcessRadioMeasurementRequest(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) +{ + P_ACTION_RM_REQ_FRAME prRmReqFrame = NULL; + P_ACTION_RM_REPORT_FRAME prReportFrame = NULL; + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReqParam = NULL; + struct RADIO_MEASUREMENT_REPORT_PARAMS *prRmRepParam = NULL; + enum RM_REQ_PRIORITY eNewPriority; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + prRmReqFrame = (P_ACTION_RM_REQ_FRAME)prSwRfb->pvHeader; + prRmReqParam = &prAdapter->rWifiVar.rRmReqParams; + prRmRepParam = &prAdapter->rWifiVar.rRmRepParams; + + if (!rlmRmFrameIsValid(prSwRfb)) + return; + DBGLOG(RLM, INFO, "RM Request From %pM, DialogToken %d\n", + prRmReqFrame->aucSrcAddr, prRmReqFrame->ucDialogToken); + eNewPriority = rlmGetRmRequestPriority(prRmReqFrame->aucDestAddr); + if (prRmReqParam->ePriority > eNewPriority) { + DBGLOG(RLM, INFO, "ignore lower precedence rm request\n"); + return; + } + prRmReqParam->ePriority = eNewPriority; + /* */ + if (prRmReqParam->fgRmIsOngoing) { + DBGLOG(RLM, INFO, "Old RM is on-going, cancel it first\n"); + rlmTxRadioMeasurementReport(prAdapter); + wmmRemoveAllTsmMeasurement(prAdapter, FALSE); + rlmCancelRadioMeasurement(prAdapter); + } + prRmReqParam->fgRmIsOngoing = TRUE; + /* Step1: Save Measurement Request Params */ + prRmReqParam->u2ReqIeBufLen = prRmReqParam->u2RemainReqLen = + prSwRfb->u2PacketLen - OFFSET_OF(ACTION_RM_REQ_FRAME, aucInfoElem); + if (prRmReqParam->u2RemainReqLen <= sizeof(IE_MEASUREMENT_REQ_T)) { + DBGLOG(RLM, ERROR, "empty Radio Measurement Request Frame, Elem Len %d\n", + prRmReqParam->u2RemainReqLen); + return; + } + WLAN_GET_FIELD_BE16(&prRmReqFrame->u2Repetitions, &prRmReqParam->u2Repetitions); + prRmReqParam->pucReqIeBuf = kalMemAlloc(prRmReqParam->u2RemainReqLen, VIR_MEM_TYPE); + if (!prRmReqParam->pucReqIeBuf) { + DBGLOG(RLM, ERROR, "Alloc %d bytes Req IE Buffer failed, No Memory\n", prRmReqParam->u2RemainReqLen); + return; + } + kalMemCopy(prRmReqParam->pucReqIeBuf, &prRmReqFrame->aucInfoElem[0], prRmReqParam->u2RemainReqLen); + prRmReqParam->prCurrMeasElem = (P_IE_MEASUREMENT_REQ_T)prRmReqParam->pucReqIeBuf; + prRmReqParam->fgInitialLoop = TRUE; + + /* Step2: Prepare Report Frame and fill in Frame Header */ + prRmRepParam->pucReportFrameBuff = kalMemAlloc(RM_REPORT_FRAME_MAX_LENGTH, VIR_MEM_TYPE); + if (!prRmRepParam->pucReportFrameBuff) { + DBGLOG(RLM, ERROR, "Alloc Memory for Measurement Report Frame buffer failed\n"); + return; + } + kalMemZero(prRmRepParam->pucReportFrameBuff, RM_REPORT_FRAME_MAX_LENGTH); + prReportFrame = (P_ACTION_RM_REPORT_FRAME)prRmRepParam->pucReportFrameBuff; + prReportFrame->u2FrameCtrl = MAC_FRAME_ACTION; + COPY_MAC_ADDR(prReportFrame->aucDestAddr, prRmReqFrame->aucSrcAddr); + COPY_MAC_ADDR(prReportFrame->aucSrcAddr, + prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].aucOwnMacAddr); + COPY_MAC_ADDR(prReportFrame->aucBSSID, prRmReqFrame->aucBSSID); + prReportFrame->ucCategory = CATEGORY_RM_ACTION; + prReportFrame->ucAction = RM_ACTION_RM_REPORT; + prReportFrame->ucDialogToken = prRmReqFrame->ucDialogToken; + prRmRepParam->u2ReportFrameLen = OFFSET_OF(ACTION_RM_REPORT_FRAME, aucInfoElem); + rlmCalibrateRepetions(prRmReqParam); + /* Step3: Start to process Measurement Request Element */ + rlmStartNextMeasurement(prAdapter, TRUE); +} + +/*VOID rlmProcessLinkMeasurementRequest(P_ADAPTER_T prAdapter, P_WLAN_ACTION_FRAME prAction) +*{ +* struct ACTION_LM_REQUEST_FRAME prLmRequest = (struct ACTION_LM_REQUEST_FRAME *)prAction; +* +* ASSERT(prAdapter); +* ASSERT(prLmRequest); +* DBGLOG(RLM, INFO, "LM Request From %pM, DialogToken %d\n", +* prLmRequest->aucSrcAddr, prLmRequest->ucDialogToken); +*} +*/ + +VOID rlmProcessNeighborReportResonse( + P_ADAPTER_T prAdapter, P_WLAN_ACTION_FRAME prAction, UINT_16 u2PacketLen) +{ + struct ACTION_NEIGHBOR_REPORT_FRAME *prNeighborResponse = + (struct ACTION_NEIGHBOR_REPORT_FRAME *)prAction; + + ASSERT(prAdapter); + ASSERT(prNeighborResponse); + DBGLOG(RLM, INFO, "Neighbor Resp From %pM, DialogToken %d\n", + prNeighborResponse->aucSrcAddr, prNeighborResponse->ucDialogToken); + aisCollectNeighborAPChannel(prAdapter, + (struct IE_NEIGHBOR_REPORT_T *)&prNeighborResponse->aucInfoElem[0], + u2PacketLen - OFFSET_OF(struct ACTION_NEIGHBOR_REPORT_FRAME, aucInfoElem)); +} + +VOID rlmTxNeighborReportRequest(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, + struct SUB_ELEMENT_LIST *prSubIEs) +{ + static UINT_8 ucDialogToken = 1; + P_MSDU_INFO_T prMsduInfo = NULL; + P_BSS_INFO_T prBssInfo = NULL; + PUINT_8 pucPayload = NULL; + struct ACTION_NEIGHBOR_REPORT_FRAME *prTxFrame = NULL; + UINT_16 u2TxFrameLen = 500; + UINT_16 u2FrameLen = 0; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; + ASSERT(prBssInfo); + /* 1 Allocate MSDU Info */ + prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, MAC_TX_RESERVED_FIELD + u2TxFrameLen); + if (!prMsduInfo) + return; + prTxFrame = (struct ACTION_NEIGHBOR_REPORT_FRAME *) + ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + /* 2 Compose The Mac Header. */ + 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_RM_ACTION; + prTxFrame->ucAction = RM_ACTION_NEIGHBOR_REQUEST; + u2FrameLen = OFFSET_OF(struct ACTION_NEIGHBOR_REPORT_FRAME, aucInfoElem); + /* 3 Compose the frame body's frame. */ + prTxFrame->ucDialogToken = ucDialogToken++; + u2TxFrameLen -= sizeof(*prTxFrame) - 1; + pucPayload = &prTxFrame->aucInfoElem[0]; + while (prSubIEs && u2TxFrameLen >= (prSubIEs->rSubIE.ucLength + 2)) { + kalMemCopy(pucPayload, &prSubIEs->rSubIE, prSubIEs->rSubIE.ucLength + 2); + pucPayload += prSubIEs->rSubIE.ucLength + 2; + u2FrameLen += prSubIEs->rSubIE.ucLength + 2; + prSubIEs = prSubIEs->prNext; + } + + /* 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 = u2FrameLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->fgIsBasicRate = FALSE; + + /* 5 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); +} + +VOID rlmTxRadioMeasurementReport(P_ADAPTER_T prAdapter) +{ + P_MSDU_INFO_T prMsduInfo = NULL; + struct RADIO_MEASUREMENT_REPORT_PARAMS *prRmRepParam = &prAdapter->rWifiVar.rRmRepParams; + + if (prRmRepParam->u2ReportFrameLen <= OFFSET_OF(ACTION_RM_REPORT_FRAME, aucInfoElem)) { + DBGLOG(RLM, INFO, "report frame length is too short, %d\n", prRmRepParam->u2ReportFrameLen); + return; + } + + if (prAdapter->rWifiVar.rAisFsmInfo.prTargetStaRec == NULL) { + DBGLOG(RLM, INFO, "prAdapter->rWifiVar.rAisFsmInfo.prTargetStaRec is NULL\n"); + return; + } + + prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, prRmRepParam->u2ReportFrameLen); + if (!prMsduInfo) { + DBGLOG(RLM, INFO, "Alloc MSDU Info failed, frame length %d\n", prRmRepParam->u2ReportFrameLen); + return; + } + DBGLOG(RLM, INFO, "frame length %d\n", prRmRepParam->u2ReportFrameLen); + kalMemCopy(prMsduInfo->prPacket, prRmRepParam->pucReportFrameBuff, prRmRepParam->u2ReportFrameLen); + + /* 2 Update information of MSDU_INFO_T */ + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; /* Management frame */ + prMsduInfo->ucStaRecIndex = prAdapter->rWifiVar.rAisFsmInfo.prTargetStaRec->ucIndex; + prMsduInfo->ucNetworkType = NETWORK_TYPE_AIS_INDEX; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = prRmRepParam->u2ReportFrameLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->fgIsBasicRate = FALSE; + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + /* reset u2ReportFrameLen after tx frame */ + prRmRepParam->u2ReportFrameLen = OFFSET_OF(ACTION_RM_REPORT_FRAME, aucInfoElem); +} + + + +VOID rlmGernerateRRMEnabledCapIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_IE_RRM_ENABLED_CAP_T prRrmEnabledCap = NULL; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prRrmEnabledCap = (P_IE_RRM_ENABLED_CAP_T) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + prRrmEnabledCap->ucId = ELEM_ID_RRM_ENABLED_CAP; + prRrmEnabledCap->ucLength = ELEM_MAX_LEN_RRM_CAP; + kalMemZero(&prRrmEnabledCap->aucCap[0], ELEM_MAX_LEN_RRM_CAP); + rlmFillRrmCapa(&prRrmEnabledCap->aucCap[0]); + prMsduInfo->u2FrameLength += IE_SIZE(prRrmEnabledCap); +} + +VOID rlmFillRrmCapa(PUINT_8 pucCapa) +{ + UINT_8 ucIndex = 0; + UINT_8 aucEnabledBits[] = {RRM_CAP_INFO_LINK_MEASURE_BIT, RRM_CAP_INFO_NEIGHBOR_REPORT_BIT, + RRM_CAP_INFO_BEACON_PASSIVE_MEASURE_BIT, RRM_CAP_INFO_BEACON_ACTIVE_MEASURE_BIT, + RRM_CAP_INFO_BEACON_TABLE_BIT, RRM_CAP_INFO_TSM_BIT, RRM_CAP_INFO_RRM_BIT}; + + for (; ucIndex < sizeof(aucEnabledBits); ucIndex++) + SET_EXT_CAP(pucCapa, ELEM_MAX_LEN_RRM_CAP, aucEnabledBits[ucIndex]); +} + +VOID rlmGerneratePowerCapIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_IE_POWER_CAP_T prPwrCap = NULL; + UINT_8 ucChannel = 0; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + ucChannel = prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc->ucChannelNum; + prPwrCap = (P_IE_POWER_CAP_T) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + prPwrCap->ucId = ELEM_ID_PWR_CAP; + prPwrCap->ucLength = 2; + prPwrCap->cMaxTxPowerCap = RLM_MAX_TX_PWR; + prPwrCap->cMinTxPowerCap = RLM_MIN_TX_PWR; + prMsduInfo->u2FrameLength += IE_SIZE(prPwrCap); +} + +VOID rlmSetMaxTxPwrLimit(IN P_ADAPTER_T prAdapter, INT_8 cLimit, UINT_8 ucEnable) +{ + struct CMD_SET_MAX_TXPWR_LIMIT rTxPwrLimit; + + kalMemZero(&rTxPwrLimit, sizeof(rTxPwrLimit)); + rTxPwrLimit.ucMaxTxPwrLimitEnable = ucEnable; + if (ucEnable) { + if (cLimit > RLM_MAX_TX_PWR) { + DBGLOG(RLM, TRACE, "Target MaxPwr %d Higher than Capability, reset to capability\n", cLimit); + cLimit = RLM_MAX_TX_PWR; + } + if (cLimit < RLM_MIN_TX_PWR) { + DBGLOG(RLM, TRACE, "Target MinPwr %d Lower than Capability, reset to capability\n", cLimit); + cLimit = RLM_MIN_TX_PWR; + } + DBGLOG(RLM, TRACE, "Set Max Tx Power Limit %d, Min Limit %d\n", cLimit, RLM_MIN_TX_PWR); + rTxPwrLimit.cMaxTxPwr = cLimit * 2; /* unit of cMaxTxPwr is 0.5 dBm */ + rTxPwrLimit.cMinTxPwr = RLM_MIN_TX_PWR * 2; + } else + DBGLOG(RLM, TRACE, "Disable Tx Power Limit\n"); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_MAX_TXPWR_LIMIT, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_SET_MAX_TXPWR_LIMIT), + (PUINT_8) &rTxPwrLimit, NULL, 0); +} + +enum RM_REQ_PRIORITY rlmGetRmRequestPriority(PUINT_8 pucDestAddr) +{ + if (IS_UCAST_MAC_ADDR(pucDestAddr)) + return RM_PRI_UNICAST; + else if (EQUAL_MAC_ADDR(pucDestAddr, "\xff\xff\xff\xff\xff\xff")) + return RM_PRI_BROADCAST; + return RM_PRI_MULTICAST; +} + +static VOID rlmCalibrateRepetions(struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq) +{ + UINT_16 u2IeSize = 0; + UINT_16 u2RemainReqLen = prRmReq->u2ReqIeBufLen; + P_IE_MEASUREMENT_REQ_T prCurrReq = (P_IE_MEASUREMENT_REQ_T)prRmReq->prCurrMeasElem; + + if (prRmReq->u2Repetitions == 0) + return; + + u2IeSize = IE_SIZE(prCurrReq); + while (u2RemainReqLen >= u2IeSize) { + /* 1. If all measurement request has enable bit, no need to repeat + ** see 11.10.6 Measurement request elements with the enable bit set to 1 shall be processed once + ** regardless of the value in the number of repetitions in the measurement request. + ** 2. Due to we don't support parallel measurement, if all request has parallel bit, no need to repeat + ** measurement, to avoid frequent composing incapable response IE and exhauste CPU resource + ** and then cause watch dog timeout. + ** 3. if all measurements are not supported, no need to repeat. currently we only support Beacon request + ** on this chip. + */ + if (!(prCurrReq->ucRequestMode & (RM_REQ_MODE_ENABLE_BIT | RM_REQ_MODE_PARALLEL_BIT))) { + if (prCurrReq->ucMeasurementType == ELEM_RM_TYPE_BEACON_REQ) + return; + } + u2RemainReqLen -= u2IeSize; + prCurrReq = (P_IE_MEASUREMENT_REQ_T)((PUINT_8)prCurrReq + u2IeSize); + u2IeSize = IE_SIZE(prCurrReq); + } + DBGLOG(RLM, INFO, + "All Measurement has set enable bit, or all are parallel or not supported, don't repeat\n"); + prRmReq->u2Repetitions = 0; +} + +VOID rlmRunEventProcessNextRm(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr) +{ + cnmMemFree(prAdapter, prMsgHdr); + rlmStartNextMeasurement(prAdapter, FALSE); +} + +VOID rlmScheduleNextRm(P_ADAPTER_T prAdapter) +{ + P_MSG_HDR_T prMsg = NULL; + + prMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(*prMsg)); + + if (!prMsg) { + DBGLOG(RLM, WARN, "No buf for schedule next rm\n"); + return; + } + prMsg->eMsgId = MID_RLM_RM_SCHEDULE; + mboxSendMsg(prAdapter, MBOX_ID_0, prMsg, MSG_SEND_METHOD_BUF); +} + +#if CFG_SUPPORT_RLM_ACT_NETWORK +VOID rlmActivateNetwork(P_ADAPTER_T prAdapter, ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx, + ENUM_NET_ACTIVE_SRC_T eNetActiveSrcIdx) +{ + bool isActive = false; + + ASSERT(prAdapter); + + if (eNetworkTypeIdx < NETWORK_TYPE_AIS_INDEX || + eNetworkTypeIdx >= NETWORK_TYPE_INDEX_NUM) { + DBGLOG(NIC, WARN, "rlmActivateNetwork, Idx=%d\n", + eNetworkTypeIdx); + return; + } + + prAdapter->rWifiVar.arBssInfo[eNetworkTypeIdx].ucNetActiveSrc |= eNetActiveSrcIdx; + + isActive = IS_NET_ACTIVE(prAdapter, eNetworkTypeIdx); + if (!isActive) { + SET_NET_ACTIVE(prAdapter, eNetworkTypeIdx); + /* sync with firmware */ + nicActivateNetwork(prAdapter, eNetworkTypeIdx); + if (eNetworkTypeIdx == NETWORK_TYPE_P2P_INDEX) + nicUpdateBss(prAdapter, eNetworkTypeIdx); + } + DBGLOG(RLM, INFO, "rlm: active=%d, Type=%d, Src=%d, SrcVal=%d\n", + isActive, eNetworkTypeIdx, eNetActiveSrcIdx, + prAdapter->rWifiVar.arBssInfo[eNetworkTypeIdx].ucNetActiveSrc); +} + +VOID rlmDeactivateNetwork(P_ADAPTER_T prAdapter, ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx, + ENUM_NET_ACTIVE_SRC_T eNetActiveSrcIdx) +{ + ASSERT(prAdapter); + + if (eNetworkTypeIdx < NETWORK_TYPE_AIS_INDEX || + eNetworkTypeIdx >= NETWORK_TYPE_INDEX_NUM) { + DBGLOG(NIC, WARN, "rlmDeactivateNetwork, Idx=%d\n", + eNetworkTypeIdx); + return; + } + + prAdapter->rWifiVar.arBssInfo[eNetworkTypeIdx].ucNetActiveSrc &= ~eNetActiveSrcIdx; + + DBGLOG(RLM, INFO, "rlmDeactivateNetwork, Type = %d, Src = %d, Active = %d, SrcVal= %d\n", + eNetworkTypeIdx, eNetActiveSrcIdx, IS_NET_ACTIVE(prAdapter, eNetworkTypeIdx), + prAdapter->rWifiVar.arBssInfo[eNetworkTypeIdx].ucNetActiveSrc); + + if ((IS_NET_ACTIVE(prAdapter, eNetworkTypeIdx)) && + prAdapter->rWifiVar.arBssInfo[eNetworkTypeIdx].ucNetActiveSrc == 0) { + UNSET_NET_ACTIVE(prAdapter, eNetworkTypeIdx); + /* sync with firmware */ + nicDeactivateNetwork(prAdapter, eNetworkTypeIdx); + } +} + +#endif + + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/rlm_domain.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/rlm_domain.c new file mode 100644 index 0000000000000..8040c5a7170cc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/rlm_domain.c @@ -0,0 +1,1828 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" +#include "rlm_txpwr_init.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/* The following country or domain shall be set from host driver. + * And host driver should pass specified DOMAIN_INFO_ENTRY to MT6620 as + * the channel list of being a STA to do scanning/searching AP or being an + * AP to choose an adequate channel if auto-channel is set. + */ + +/* Define mapping tables between country code and its channel set + */ +static const UINT_16 g_u2CountryGroup0[] = { COUNTRY_CODE_JP }; + +static const UINT_16 g_u2CountryGroup1[] = { + COUNTRY_CODE_AS, COUNTRY_CODE_AI, COUNTRY_CODE_BM, COUNTRY_CODE_KY, + COUNTRY_CODE_GU, COUNTRY_CODE_FM, COUNTRY_CODE_PR, COUNTRY_CODE_VI, + COUNTRY_CODE_AZ, COUNTRY_CODE_BW, COUNTRY_CODE_KH, COUNTRY_CODE_CX, + COUNTRY_CODE_CO, COUNTRY_CODE_CR, COUNTRY_CODE_GD, COUNTRY_CODE_GT, + COUNTRY_CODE_KI, COUNTRY_CODE_LB, COUNTRY_CODE_LR, COUNTRY_CODE_MN, + COUNTRY_CODE_AN, COUNTRY_CODE_NI, COUNTRY_CODE_PW, COUNTRY_CODE_WS, + COUNTRY_CODE_LK, COUNTRY_CODE_TT, COUNTRY_CODE_MM +}; + +static const UINT_16 g_u2CountryGroup2[] = { + COUNTRY_CODE_AW, COUNTRY_CODE_LA, COUNTRY_CODE_AE, COUNTRY_CODE_UG +}; + +static const UINT_16 g_u2CountryGroup3[] = { + COUNTRY_CODE_AR, COUNTRY_CODE_BR, COUNTRY_CODE_HK, COUNTRY_CODE_OM, + COUNTRY_CODE_PH, COUNTRY_CODE_SA, COUNTRY_CODE_SG, COUNTRY_CODE_ZA, + COUNTRY_CODE_VN, COUNTRY_CODE_BD, COUNTRY_CODE_DO, COUNTRY_CODE_FK, + COUNTRY_CODE_KZ, COUNTRY_CODE_MZ, COUNTRY_CODE_NA, COUNTRY_CODE_LC, + COUNTRY_CODE_VC, COUNTRY_CODE_UA, COUNTRY_CODE_UZ, COUNTRY_CODE_ZW, + COUNTRY_CODE_MP, COUNTRY_CODE_KR +}; + +static const UINT_16 g_u2CountryGroup4[] = { + COUNTRY_CODE_AT, COUNTRY_CODE_BE, COUNTRY_CODE_BG, COUNTRY_CODE_HR, + COUNTRY_CODE_CZ, COUNTRY_CODE_DK, COUNTRY_CODE_FI, COUNTRY_CODE_FR, + COUNTRY_CODE_GR, COUNTRY_CODE_HU, COUNTRY_CODE_IS, COUNTRY_CODE_IE, + COUNTRY_CODE_IT, COUNTRY_CODE_LU, COUNTRY_CODE_NL, COUNTRY_CODE_NO, + COUNTRY_CODE_PL, COUNTRY_CODE_PT, COUNTRY_CODE_RO, COUNTRY_CODE_SK, + COUNTRY_CODE_SI, COUNTRY_CODE_ES, COUNTRY_CODE_SE, COUNTRY_CODE_CH, + COUNTRY_CODE_GB, COUNTRY_CODE_AL, COUNTRY_CODE_AD, COUNTRY_CODE_BY, + COUNTRY_CODE_BA, COUNTRY_CODE_VG, COUNTRY_CODE_CV, COUNTRY_CODE_CY, + COUNTRY_CODE_EE, COUNTRY_CODE_ET, COUNTRY_CODE_GF, COUNTRY_CODE_PF, + COUNTRY_CODE_TF, COUNTRY_CODE_GE, COUNTRY_CODE_DE, COUNTRY_CODE_GH, + COUNTRY_CODE_GP, COUNTRY_CODE_IQ, COUNTRY_CODE_KE, COUNTRY_CODE_LV, + COUNTRY_CODE_LS, COUNTRY_CODE_LI, COUNTRY_CODE_LT, COUNTRY_CODE_MK, + COUNTRY_CODE_MT, COUNTRY_CODE_MQ, COUNTRY_CODE_MR, COUNTRY_CODE_MU, + COUNTRY_CODE_YT, COUNTRY_CODE_MD, COUNTRY_CODE_MC, COUNTRY_CODE_ME, + COUNTRY_CODE_MS, COUNTRY_CODE_RE, COUNTRY_CODE_MF, COUNTRY_CODE_SM, + COUNTRY_CODE_SN, COUNTRY_CODE_RS, COUNTRY_CODE_TR, COUNTRY_CODE_TC, + COUNTRY_CODE_VA, COUNTRY_CODE_EU, COUNTRY_CODE_DZ +}; + +static const UINT_16 g_u2CountryGroup5[] = { + COUNTRY_CODE_AU, COUNTRY_CODE_NZ, COUNTRY_CODE_EC, COUNTRY_CODE_PY, + COUNTRY_CODE_PE, COUNTRY_CODE_TH, COUNTRY_CODE_UY +}; + +static const UINT_16 g_u2CountryGroup6[] = { COUNTRY_CODE_RU }; + +static const UINT_16 g_u2CountryGroup7[] = { + COUNTRY_CODE_CL, COUNTRY_CODE_EG, COUNTRY_CODE_IN, COUNTRY_CODE_AG, + COUNTRY_CODE_BS, COUNTRY_CODE_BH, COUNTRY_CODE_BB, COUNTRY_CODE_BN, + COUNTRY_CODE_MV, COUNTRY_CODE_PA, COUNTRY_CODE_ZM, COUNTRY_CODE_CN +}; + +static const UINT_16 g_u2CountryGroup8[] = { COUNTRY_CODE_MY }; + +static const UINT_16 g_u2CountryGroup9[] = { COUNTRY_CODE_NP }; + +static const UINT_16 g_u2CountryGroup10[] = { + COUNTRY_CODE_IL, COUNTRY_CODE_AM, COUNTRY_CODE_KW, COUNTRY_CODE_MA, + COUNTRY_CODE_NE, COUNTRY_CODE_TN +}; + +static const UINT_16 g_u2CountryGroup11[] = { + COUNTRY_CODE_JO, COUNTRY_CODE_PG +}; + +static const UINT_16 g_u2CountryGroup12[] = { COUNTRY_CODE_AF }; + +static const UINT_16 g_u2CountryGroup13[] = { COUNTRY_CODE_NG }; + +static const UINT_16 g_u2CountryGroup14[] = { + COUNTRY_CODE_PK, COUNTRY_CODE_QA, COUNTRY_CODE_BF, COUNTRY_CODE_GY, + COUNTRY_CODE_HT, COUNTRY_CODE_JM, COUNTRY_CODE_MO, COUNTRY_CODE_MW, + COUNTRY_CODE_RW, COUNTRY_CODE_KN, COUNTRY_CODE_TZ +}; + +static const UINT_16 g_u2CountryGroup15[] = { COUNTRY_CODE_ID }; + +static const UINT_16 g_u2CountryGroup16[] = { + COUNTRY_CODE_AO, COUNTRY_CODE_BZ, COUNTRY_CODE_BJ, COUNTRY_CODE_BT, + COUNTRY_CODE_BO, COUNTRY_CODE_BI, COUNTRY_CODE_CM, COUNTRY_CODE_CF, + COUNTRY_CODE_TD, COUNTRY_CODE_KM, COUNTRY_CODE_CD, COUNTRY_CODE_CG, + COUNTRY_CODE_CI, COUNTRY_CODE_DJ, COUNTRY_CODE_GQ, COUNTRY_CODE_ER, + COUNTRY_CODE_FJ, COUNTRY_CODE_GA, COUNTRY_CODE_GM, COUNTRY_CODE_GN, + COUNTRY_CODE_GW, COUNTRY_CODE_RKS, COUNTRY_CODE_KG, COUNTRY_CODE_LY, + COUNTRY_CODE_MG, COUNTRY_CODE_ML, COUNTRY_CODE_NR, COUNTRY_CODE_NC, + COUNTRY_CODE_ST, COUNTRY_CODE_SC, COUNTRY_CODE_SL, COUNTRY_CODE_SB, + COUNTRY_CODE_SO, COUNTRY_CODE_SR, COUNTRY_CODE_SZ, COUNTRY_CODE_TJ, + COUNTRY_CODE_TG, COUNTRY_CODE_TO, COUNTRY_CODE_TM, COUNTRY_CODE_TV, + COUNTRY_CODE_VU, COUNTRY_CODE_YE +}; + +static const UINT_16 g_u2CountryGroup17[] = { + COUNTRY_CODE_US, COUNTRY_CODE_CA, COUNTRY_CODE_TW +}; + +static const UINT_16 g_u2CountryGroup18[] = { + COUNTRY_CODE_DM, COUNTRY_CODE_SV, COUNTRY_CODE_HN +}; + +static const UINT_16 g_u2CountryGroup19[] = { + COUNTRY_CODE_MX, COUNTRY_CODE_VE +}; + +static const UINT_16 g_u2CountryGroup20[] = { + COUNTRY_CODE_CK, COUNTRY_CODE_CU, COUNTRY_CODE_TL, COUNTRY_CODE_FO, + COUNTRY_CODE_GI, COUNTRY_CODE_GG, COUNTRY_CODE_IR, COUNTRY_CODE_IM, + COUNTRY_CODE_JE, COUNTRY_CODE_KP, COUNTRY_CODE_MH, COUNTRY_CODE_NU, + COUNTRY_CODE_NF, COUNTRY_CODE_PS, COUNTRY_CODE_PN, COUNTRY_CODE_PM, + COUNTRY_CODE_SS, COUNTRY_CODE_SD, COUNTRY_CODE_SY +}; + +DOMAIN_INFO_ENTRY arSupportedRegDomains[] = { + { + (PUINT_16) g_u2CountryGroup0, sizeof(g_u2CountryGroup0) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {82, BAND_2G4, CHNL_SPAN_5, 14, 1, FALSE} + , /* CH_SET_2G4_14_14 */ + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_NULL, 0, 0, 0, FALSE} + /* CH_SET_UNII_UPPER_NA */ + } + } + , + { + (PUINT_16) g_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, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup2, sizeof(g_u2CountryGroup2) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE} + , /* CH_SET_UNII_UPPER_149_161 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup3, sizeof(g_u2CountryGroup3) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup4, sizeof(g_u2CountryGroup4) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup5, sizeof(g_u2CountryGroup5) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 5, TRUE} + , /* CH_SET_UNII_WW_100_116 */ + {121, BAND_5G, CHNL_SPAN_20, 132, 3, TRUE} + , /* CH_SET_UNII_WW_132_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + /* CH_SET_UNII_UPPER_149_165 */ + + } + } + , + { + (PUINT_16) g_u2CountryGroup6, sizeof(g_u2CountryGroup6) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 132, 3, TRUE} + , /* CH_SET_UNII_WW_132_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_u2CountryGroup7, sizeof(g_u2CountryGroup7) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup8, sizeof(g_u2CountryGroup8) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 8, TRUE} + , /* 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} + } + } + , + { + (PUINT_16) g_u2CountryGroup9, sizeof(g_u2CountryGroup9) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE} + , /* CH_SET_UNII_UPPER_149_161 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup10, sizeof(g_u2CountryGroup10) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup11, sizeof(g_u2CountryGroup11) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_MID_NA */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup12, sizeof(g_u2CountryGroup12) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_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_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_LOW_NA */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup14, sizeof(g_u2CountryGroup14) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_LOW_NA */ + {118, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_MID_NA */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup15, sizeof(g_u2CountryGroup15) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_LOW_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_u2CountryGroup16, sizeof(g_u2CountryGroup16) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_LOW_NA */ + {118, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_MID_NA */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup17, sizeof(g_u2CountryGroup17) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 11, FALSE} + , /* CH_SET_2G4_1_11 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + /* CH_SET_UNII_UPPER_149_165 */ + } + } + , + { + (PUINT_16) g_u2CountryGroup18, sizeof(g_u2CountryGroup18) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 11, FALSE} + , /* CH_SET_2G4_1_11 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 5, TRUE} + , /* CH_SET_UNII_WW_100_116 */ + {121, BAND_5G, CHNL_SPAN_20, 132, 3, TRUE} + , /* CH_SET_UNII_WW_132_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + /* CH_SET_UNII_UPPER_149_165 */ + + } + } + , + { + (PUINT_16) g_u2CountryGroup19, sizeof(g_u2CountryGroup19) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 11, FALSE} + , /* CH_SET_2G4_1_11 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_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_u2CountryGroup20, sizeof(g_u2CountryGroup20) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + /* Note: Default group if no matched country code */ + NULL, 0, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } +}; + +static UINT_16 g_u2CountryGroup0_Passive[] = { + COUNTRY_CODE_UDF +}; + +/* + * Passive scan setting example + * +static UINT_16 g_u2CountryGroup1_Passive[] = { + COUNTRY_CODE_TW +}; +*/ + +DOMAIN_INFO_ENTRY arSupportedRegDomains_Passive[] = { + { + /* Default passive scan channel table is empty */ + NULL, 0, + { + {81, BAND_2G4, CHNL_SPAN_5, 11, 0, 0}, /* CH_SET_2G4_1_14 */ + {82, BAND_2G4, CHNL_SPAN_5, 5, 0, 0}, + + {115, BAND_5G, CHNL_SPAN_20, 36, 0, 0}, /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 0, 0}, /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 0, 0}, /* CH_SET_UNII_WW_100_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 0, 0}, /* CH_SET_UNII_UPPER_149_173 */ + } + }, +#ifdef CONFIG_MTK_TC1_FEATURE + { + /* 2.4GHz -> Ch1~11 : Set Active Scan, + * 2.4Ghz -> Ch12~14: Disabled. + * 5Ghz -> All channel : Set Passive Scan + */ + g_u2CountryGroup0_Passive, 0, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 0, 0}, /* CH_SET_2G4_1_11 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, 0}, /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, 0}, /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, 0}, /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 7, 0}, /* CH_SET_UNII_UPPER_149_173 */ + {0, BAND_NULL, 0, 0, 0, 0} + } + } +#else + { + /* User Defined passive scan channel table */ + g_u2CountryGroup0_Passive, 0, + { + {81, BAND_2G4, CHNL_SPAN_5, 12, 1, 0}, /* CH_SET_2G4_1_14 */ + {82, BAND_2G4, CHNL_SPAN_5, 5, 0, 0}, + + {115, BAND_5G, CHNL_SPAN_20, 36, 0, 0}, /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 0, 0}, /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 0, 0}, /* CH_SET_UNII_WW_100_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 0, 0}, /* CH_SET_UNII_UPPER_149_173 */ + } + }, + /* Passive scan setting example + * 1-11 active + * 12-14 passive + * 36-48 passive + * 52-64 passive + * 100-140 passive + * 146-165 active + *{ + * g_u2CountryGroup1_Passive, 1, + * { + * {81, BAND_2G4, CHNL_SPAN_5, 1, 0, 0}, + * {82, BAND_2G4, CHNL_SPAN_5, 12, 3, 0}, + * {115, BAND_5G, CHNL_SPAN_20, 36, 4, 0}, + * {118, BAND_5G, CHNL_SPAN_20, 52, 4, 0}, + * {121, BAND_5G, CHNL_SPAN_20, 100, 11, 0}, + * {125, BAND_5G, CHNL_SPAN_20, 149, 0, 0}, + * } + * }, + */ +#endif +}; + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY +SUBBAND_CHANNEL_T g_rRlmSubBand[] = { + + {BAND_2G4_LOWER_BOUND, BAND_2G4_UPPER_BOUND, 1, 0} + , /* 2.4G */ + {UNII1_LOWER_BOUND, UNII1_UPPER_BOUND, 2, 0} + , /* ch36,38,40,..,48 */ + {UNII2A_LOWER_BOUND, UNII2A_UPPER_BOUND, 2, 0} + , /* ch52,54,56,..,64 */ + {UNII2C_LOWER_BOUND, UNII2C_UPPER_BOUND, 2, 0} + , /* ch100,102,104,...,144 */ + {UNII3_LOWER_BOUND, UNII3_UPPER_BOUND, 2, 0} + /* ch149,151,153,....,173 */ +}; +#endif + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in/out] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +P_DOMAIN_INFO_ENTRY rlmDomainGetDomainInfo(P_ADAPTER_T prAdapter) +{ +#define REG_DOMAIN_GROUP_NUM \ + (sizeof(arSupportedRegDomains) / sizeof(DOMAIN_INFO_ENTRY)) +#define REG_DOMAIN_DEF_IDX (REG_DOMAIN_GROUP_NUM - 1) + + P_DOMAIN_INFO_ENTRY prDomainInfo; + P_REG_INFO_T prRegInfo; + UINT_16 u2TargetCountryCode; + UINT_16 i, j; + + ASSERT(prAdapter); + + if (prAdapter->prDomainInfo) + return prAdapter->prDomainInfo; + + prRegInfo = &prAdapter->prGlueInfo->rRegInfo; + + DBGLOG(RLM, TRACE, "eRegChannelListMap=%d, u2CountryCode=0x%04x\n", + prRegInfo->eRegChannelListMap, + prAdapter->rWifiVar.rConnSettings.u2CountryCode); + + /* + * Domain info can be specified by given idx of arSupportedRegDomains table, + * customized, or searched by country code, + * only one is set among these three methods in NVRAM. + */ + if (prRegInfo->eRegChannelListMap == REG_CH_MAP_TBL_IDX && + prRegInfo->ucRegChannelListIndex < REG_DOMAIN_GROUP_NUM) { + /* by given table idx */ + DBGLOG(RLM, TRACE, "ucRegChannelListIndex=%d\n", prRegInfo->ucRegChannelListIndex); + prDomainInfo = &arSupportedRegDomains[prRegInfo->ucRegChannelListIndex]; + } else if (prRegInfo->eRegChannelListMap == REG_CH_MAP_CUSTOMIZED) { + /* by customized */ + prDomainInfo = &prRegInfo->rDomainInfo; + } else { + /* by country code */ + u2TargetCountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode; + + for (i = 0; i < REG_DOMAIN_GROUP_NUM; i++) { + prDomainInfo = &arSupportedRegDomains[i]; + + if ((prDomainInfo->u4CountryNum && prDomainInfo->pu2CountryGroup) || + prDomainInfo->u4CountryNum == 0) { + for (j = 0; j < prDomainInfo->u4CountryNum; j++) { + if (prDomainInfo->pu2CountryGroup[j] == u2TargetCountryCode) + break; + } + if (j < prDomainInfo->u4CountryNum) + break; /* Found */ + } + } + + /* If no matched country code, use the default regulatory domain */ + if (i >= REG_DOMAIN_GROUP_NUM) { + DBGLOG(RLM, INFO, "No matched country code, use the default regulatory domain\n"); + prDomainInfo = &arSupportedRegDomains[REG_DOMAIN_DEF_IDX]; + } + } + + prAdapter->prDomainInfo = prDomainInfo; + return prDomainInfo; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Retrieve the supported channel list of specified band +* +* \param[in/out] eSpecificBand: BAND_2G4, BAND_5G or BAND_NULL (both 2.4G and 5G) +* fgNoDfs: whether to exculde DFS channels +* ucMaxChannelNum: max array size +* pucNumOfChannel: pointer to returned channel number +* paucChannelList: pointer to returned channel list array +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmDomainGetChnlList(P_ADAPTER_T prAdapter, + ENUM_BAND_T eSpecificBand, BOOLEAN fgNoDfs, + UINT_8 ucMaxChannelNum, PUINT_8 pucNumOfChannel, P_RF_CHANNEL_INFO_T paucChannelList) +{ + UINT_8 i, j, ucNum; + P_DOMAIN_SUBBAND_INFO prSubband; + P_DOMAIN_INFO_ENTRY prDomainInfo; + + ASSERT(prAdapter); + ASSERT(paucChannelList); + ASSERT(pucNumOfChannel); + + prDomainInfo = rlmDomainGetDomainInfo(prAdapter); + ASSERT(prDomainInfo); + + ucNum = 0; + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubband = &prDomainInfo->rSubBand[i]; + + if (prSubband->ucBand == BAND_NULL || prSubband->ucBand >= BAND_NUM || + (prSubband->ucBand == BAND_5G && !prAdapter->fgEnable5GBand)) + continue; + + if (fgNoDfs == TRUE && prSubband->fgDfs == TRUE) + continue; + + if (eSpecificBand == BAND_NULL || prSubband->ucBand == eSpecificBand) { + for (j = 0; j < prSubband->ucNumChannels; j++) { + if (ucNum >= ucMaxChannelNum) + break; + paucChannelList[ucNum].eBand = prSubband->ucBand; + paucChannelList[ucNum].ucChannelNum = + prSubband->ucFirstChannelNum + j * prSubband->ucChannelSpan; + paucChannelList[ucNum].eDFS = prSubband->fgDfs; + ucNum++; + } + } + } + + *pucNumOfChannel = ucNum; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Retrieve DFS channels from 5G band +* +* \param[in/out] ucMaxChannelNum: max array size +* pucNumOfChannel: pointer to returned channel number +* paucChannelList: pointer to returned channel list array +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmDomainGetDfsChnls(P_ADAPTER_T prAdapter, + UINT_8 ucMaxChannelNum, PUINT_8 pucNumOfChannel, P_RF_CHANNEL_INFO_T paucChannelList) +{ + UINT_8 i, j, ucNum; + P_DOMAIN_SUBBAND_INFO prSubband; + P_DOMAIN_INFO_ENTRY prDomainInfo; + + ASSERT(prAdapter); + ASSERT(paucChannelList); + ASSERT(pucNumOfChannel); + + prDomainInfo = rlmDomainGetDomainInfo(prAdapter); + ASSERT(prDomainInfo); + + ucNum = 0; + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubband = &prDomainInfo->rSubBand[i]; + + if (prSubband->ucBand == BAND_5G) { + if (!prAdapter->fgEnable5GBand) + continue; + + if (prSubband->fgDfs == TRUE) { + for (j = 0; j < prSubband->ucNumChannels; j++) { + if (ucNum >= ucMaxChannelNum) + break; + paucChannelList[ucNum].eBand = prSubband->ucBand; + paucChannelList[ucNum].ucChannelNum = + prSubband->ucFirstChannelNum + j * prSubband->ucChannelSpan; + ucNum++; + } + } + } + } + + *pucNumOfChannel = ucNum; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmDomainSendCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid) +{ + rlmDomainSendDomainInfoCmd(prAdapter, fgIsOid); +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + rlmDomainSendPwrLimitCmd(prAdapter); +#endif + rlmDomainSendPassiveScanInfoCmd(prAdapter, fgIsOid); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmDomainSendDomainInfoCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid) +{ + P_DOMAIN_INFO_ENTRY prDomainInfo; + P_CMD_SET_DOMAIN_INFO_T prCmd; + P_DOMAIN_SUBBAND_INFO prSubBand; + UINT_8 i; + + prDomainInfo = rlmDomainGetDomainInfo(prAdapter); + ASSERT(prDomainInfo); + + prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_SET_DOMAIN_INFO_T)); + if (!prCmd) { + DBGLOG(RLM, ERROR, "Alloc cmd buffer failed\n"); + return; + } + kalMemZero(prCmd, sizeof(CMD_SET_DOMAIN_INFO_T)); + + prCmd->u2CountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode; + prCmd->u2IsSetPassiveScan = 0; + prCmd->uc2G4Bandwidth = prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode; + prCmd->uc5GBandwidth = prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode; + prCmd->aucReserved[0] = 0; + prCmd->aucReserved[1] = 0; + + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubBand = &prDomainInfo->rSubBand[i]; + + prCmd->rSubBand[i].ucRegClass = prSubBand->ucRegClass; + prCmd->rSubBand[i].ucBand = prSubBand->ucBand; + + if (prSubBand->ucBand != BAND_NULL && prSubBand->ucBand < BAND_NUM) { + prCmd->rSubBand[i].ucChannelSpan = prSubBand->ucChannelSpan; + prCmd->rSubBand[i].ucFirstChannelNum = prSubBand->ucFirstChannelNum; + prCmd->rSubBand[i].ucNumChannels = prSubBand->ucNumChannels; + } + } + + /* Set domain info to chip */ + wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_DOMAIN_INFO, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + fgIsOid, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_SET_DOMAIN_INFO_T), /* u4SetQueryInfoLen */ + (PUINT_8)prCmd, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + cnmMemFree(prAdapter, prCmd); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmDomainSendPassiveScanInfoCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid) +{ +#define REG_DOMAIN_PASSIVE_DEF_IDX 0 +#define REG_DOMAIN_PASSIVE_UDF_IDX 1 +#define REG_DOMAIN_PASSIVE_GROUP_NUM \ + (sizeof(arSupportedRegDomains_Passive) / sizeof(DOMAIN_INFO_ENTRY)) + + P_DOMAIN_INFO_ENTRY prDomainInfo; + P_CMD_SET_DOMAIN_INFO_T prCmd; + P_DOMAIN_SUBBAND_INFO prSubBand; + UINT_16 u2TargetCountryCode; + UINT_8 i, j; + + prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_SET_DOMAIN_INFO_T)); + if (!prCmd) { + DBGLOG(RLM, ERROR, "Alloc cmd buffer failed\n"); + return; + } + kalMemZero(prCmd, sizeof(CMD_SET_DOMAIN_INFO_T)); + + prCmd->u2CountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode; + prCmd->u2IsSetPassiveScan = 1; + prCmd->uc2G4Bandwidth = prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode; + prCmd->uc5GBandwidth = prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode; + prCmd->aucReserved[0] = 0; + prCmd->aucReserved[1] = 0; + + DBGLOG(RLM, TRACE, "u2CountryCode=0x%04x\n", prAdapter->rWifiVar.rConnSettings.u2CountryCode); + + u2TargetCountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode; + for (i = 0; i < REG_DOMAIN_PASSIVE_GROUP_NUM; i++) { + prDomainInfo = &arSupportedRegDomains_Passive[i]; + + for (j = 0; j < prDomainInfo->u4CountryNum; j++) { + if (prDomainInfo->pu2CountryGroup[j] == u2TargetCountryCode) + break; + } + if (j < prDomainInfo->u4CountryNum) + break; /* Found */ + } + + if (i >= REG_DOMAIN_PASSIVE_GROUP_NUM) + prDomainInfo = &arSupportedRegDomains_Passive[REG_DOMAIN_PASSIVE_DEF_IDX]; + + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubBand = &prDomainInfo->rSubBand[i]; + + prCmd->rSubBand[i].ucRegClass = prSubBand->ucRegClass; + prCmd->rSubBand[i].ucBand = prSubBand->ucBand; + + if (prSubBand->ucBand != BAND_NULL && prSubBand->ucBand < BAND_NUM) { + prCmd->rSubBand[i].ucChannelSpan = prSubBand->ucChannelSpan; + prCmd->rSubBand[i].ucFirstChannelNum = prSubBand->ucFirstChannelNum; + prCmd->rSubBand[i].ucNumChannels = prSubBand->ucNumChannels; + } + } + + /* Set passive scan channel info to chip */ + wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_DOMAIN_INFO, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + fgIsOid, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_SET_DOMAIN_INFO_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmd, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + cnmMemFree(prAdapter, prCmd); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in/out] +* +* \return TRUE Legal channel +* FALSE Illegal channel for current regulatory domain +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rlmDomainIsLegalChannel(P_ADAPTER_T prAdapter, ENUM_BAND_T eBand, UINT_8 ucChannel) +{ + UINT_8 i, j; + P_DOMAIN_SUBBAND_INFO prSubband; + P_DOMAIN_INFO_ENTRY prDomainInfo; + + prDomainInfo = rlmDomainGetDomainInfo(prAdapter); + ASSERT(prDomainInfo); + + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubband = &prDomainInfo->rSubBand[i]; + + if (prSubband->ucBand == BAND_5G && !prAdapter->fgEnable5GBand) + continue; + + if (prSubband->ucBand == eBand) { + for (j = 0; j < prSubband->ucNumChannels; j++) { + if ((prSubband->ucFirstChannelNum + j * prSubband->ucChannelSpan) + == ucChannel) { + return TRUE; + } + } + } + } + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in/out] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ + +UINT_32 rlmDomainSupOperatingClassIeFill(PUINT_8 pBuf) +{ + /* + * The Country element should only be included for Status Code 0 (Successful). + */ + UINT_32 u4IeLen; + UINT_8 aucClass[12] = { 0x01, 0x02, 0x03, 0x05, 0x16, 0x17, 0x19, 0x1b, + 0x1c, 0x1e, 0x20, 0x21 + }; + + /* + * The Supported Operating Classes element is used by a STA to advertise the + * operating classes that it is capable of operating with in this country. + * + * The Country element (see 8.4.2.10) allows a STA to configure its PHY and MAC + * for operation when the operating triplet of Operating Extension Identifier, + * Operating Class, and Coverage Class fields is present. + */ + SUP_OPERATING_CLASS_IE(pBuf)->ucId = ELEM_ID_SUP_OPERATING_CLASS; + SUP_OPERATING_CLASS_IE(pBuf)->ucLength = 1 + sizeof(aucClass); + SUP_OPERATING_CLASS_IE(pBuf)->ucCur = 0x0c; /* 0x51 */ + kalMemCopy(SUP_OPERATING_CLASS_IE(pBuf)->ucSup, aucClass, sizeof(aucClass)); + u4IeLen = (SUP_OPERATING_CLASS_IE(pBuf)->ucLength + 2); + pBuf += u4IeLen; + + COUNTRY_IE(pBuf)->ucId = ELEM_ID_COUNTRY_INFO; + COUNTRY_IE(pBuf)->ucLength = 6; + COUNTRY_IE(pBuf)->aucCountryStr[0] = 0x55; + COUNTRY_IE(pBuf)->aucCountryStr[1] = 0x53; + COUNTRY_IE(pBuf)->aucCountryStr[2] = 0x20; + COUNTRY_IE(pBuf)->arCountryStr[0].ucFirstChnlNum = 1; + COUNTRY_IE(pBuf)->arCountryStr[0].ucNumOfChnl = 11; + COUNTRY_IE(pBuf)->arCountryStr[0].cMaxTxPwrLv = 0x1e; + u4IeLen += (COUNTRY_IE(pBuf)->ucLength + 2); + + return u4IeLen; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (fgValid) : 0 -> inValid, 1 -> Valid +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rlmDomainCheckChannelEntryValid(P_ADAPTER_T prAdapter, UINT_8 ucCentralCh) +{ + BOOLEAN fgValid = FALSE; + UINT_8 ucTemp = 0; + UINT_8 i; + /*Check Power limit table channel efficient or not */ + + for (i = POWER_LIMIT_2G4; i < POWER_LIMIT_SUBAND_NUM; i++) { + if ((ucCentralCh >= g_rRlmSubBand[i].ucStartCh) && (ucCentralCh <= g_rRlmSubBand[i].ucEndCh)) + ucTemp = (ucCentralCh - g_rRlmSubBand[i].ucStartCh) % g_rRlmSubBand[i].ucInterval; + } + +#if 0 + /*2.4G, ex 1, 2, 3 */ + if (ucCentralCh >= BAND_2G4_LOWER_BOUND && ucCentralCh <= BAND_2G4_UPPER_BOUND) + ucTemp = 0; + /*FCC- Spec : Band UNII-1, ex 36, 38, 40.... */ + else if (ucCentralCh >= UNII1_LOWER_BOUND && ucCentralCh <= UNII1_UPPER_BOUND) + ucTemp = (ucCentralCh - UNII1_LOWER_BOUND) % 2; + /*FCC- Spec : Band UNII-2A, ex 52, 54, 56.... */ + else if (ucCentralCh >= UNII2A_LOWER_BOUND && ucCentralCh <= UNII2A_UPPER_BOUND) + ucTemp = (ucCentralCh - UNII2A_LOWER_BOUND) % 2; + /*FCC- Spec : Band UNII-2C, ex 100, 102, 104.... */ + else if (ucCentralCh >= UNII2C_LOWER_BOUND && ucCentralCh <= UNII2C_UPPER_BOUND) + ucTemp = (ucCentralCh - UNII2C_LOWER_BOUND) % 2; + /*FCC- Spec : Band UNII-3, ex 149, 151, 153... */ + else if (ucCentralCh >= UNII3_LOWER_BOUND && ucCentralCh <= UNII3_UPPER_BOUND) + ucTemp = (ucCentralCh - UNII3_LOWER_BOUND) % 2; +#endif + if (ucTemp == 0) + fgValid = TRUE; + return fgValid; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 rlmDomainGetCenterChannel(ENUM_BAND_T eBand, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend) +{ + UINT_8 ucCenterChannel; + + if (eExtend == CHNL_EXT_SCA) + ucCenterChannel = ucPriChannel + 2; + else if (eExtend == CHNL_EXT_SCB) + ucCenterChannel = ucPriChannel - 2; + else + ucCenterChannel = ucPriChannel; + + return ucCenterChannel; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rlmDomainIsValidRfSetting(P_ADAPTER_T prAdapter, + ENUM_BAND_T eBand, + UINT_8 ucPriChannel, + ENUM_CHNL_EXT_T eExtend, + ENUM_CHANNEL_WIDTH_T eChannelWidth, UINT_8 ucChannelS1, UINT_8 ucChannelS2) +{ + UINT_8 ucCenterChannel; + BOOLEAN fgValidChannel = TRUE; + BOOLEAN fgValidBW = TRUE; + BOOLEAN fgValidRfSetting = TRUE; + UINT_32 u4PrimaryOffset; + + /*DBG msg for Channel InValid */ + if (eChannelWidth == CW_20_40MHZ) { + ucCenterChannel = rlmDomainGetCenterChannel(eBand, ucPriChannel, eExtend); + + /* Check Central Channel Valid or Not */ + fgValidChannel = rlmDomainCheckChannelEntryValid(prAdapter, ucCenterChannel); + if (fgValidChannel == FALSE) + DBGLOG(RLM, WARN, "Rf: CentralCh=%d\n", ucCenterChannel); + } else if (eChannelWidth == CW_80MHZ) { + ucCenterChannel = ucChannelS1; + + /* Check Central Channel Valid or Not */ + fgValidChannel = rlmDomainCheckChannelEntryValid(prAdapter, ucCenterChannel); + if (fgValidChannel == FALSE) + DBGLOG(RLM, WARN, "Rf: CentralCh=%d\n", ucCenterChannel); + } else if (eChannelWidth == CW_160MHZ) { + ucCenterChannel = ucChannelS2; + + /* Check Central Channel Valid or Not */ + /*TODo */ + } + + /* Check BW Setting Correct or Not */ + if (eBand == BAND_2G4) { + if (eChannelWidth != CW_20_40MHZ) { + fgValidBW = FALSE; + DBGLOG(RLM, WARN, "Rf: B=%d, W=%d\n", eBand, eChannelWidth); + } + } else { + if (eChannelWidth == CW_80MHZ) { + u4PrimaryOffset = CAL_CH_OFFSET_80M(ucPriChannel, ucCenterChannel); + if (u4PrimaryOffset > 4) { + fgValidBW = FALSE; + DBGLOG(RLM, WARN, "Rf: PriOffSet=%d, W=%d\n", u4PrimaryOffset, eChannelWidth); + } + } else if (eChannelWidth == CW_160MHZ) { + u4PrimaryOffset = CAL_CH_OFFSET_160M(ucPriChannel, ucCenterChannel); + if (u4PrimaryOffset > 8) { + fgValidBW = FALSE; + DBGLOG(RLM, WARN, "Rf: PriOffSet=%d, W=%d\n", u4PrimaryOffset, eChannelWidth); + } + } + } + + if ((fgValidBW == FALSE) || (fgValidChannel == FALSE)) + fgValidRfSetting = FALSE; + + return fgValidRfSetting; + +} + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (fgValid) : 0 -> inValid, 1 -> Valid +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rlmDomainCheckPowerLimitValid(P_ADAPTER_T prAdapter, + COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION rPowerLimitTableConfiguration, + UINT_8 ucPwrLimitNum) +{ + UINT_8 i; + BOOLEAN fgValid = TRUE; + PINT_8 prPwrLimit; + + prPwrLimit = &rPowerLimitTableConfiguration.aucPwrLimit[0]; + + for (i = 0; i < ucPwrLimitNum; i++, prPwrLimit++) { + if (*prPwrLimit > MAX_TX_POWER || *prPwrLimit < MIN_TX_POWER) { + fgValid = FALSE; + break; /*Find out Wrong Power limit */ + } + } + return fgValid; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmDomainCheckCountryPowerLimitTable(P_ADAPTER_T prAdapter) +{ + UINT_8 i, j; + UINT_16 u2CountryCodeTable, u2CountryCodeCheck; + BOOLEAN fgChannelValid = FALSE; + BOOLEAN fgPowerLimitValid = FALSE; + BOOLEAN fgEntryRepetetion = FALSE; + BOOLEAN fgTableValid = TRUE; + + /*Configuration Table Check */ + for (i = 0; i < sizeof(g_rRlmPowerLimitConfiguration) / sizeof(COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION); i++) { + /*Table Country Code */ + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitConfiguration[i].aucCountryCode[0], &u2CountryCodeTable); + + /*Repetition Entry Check */ + for (j = i + 1; + j < sizeof(g_rRlmPowerLimitConfiguration) / sizeof(COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION); + j++) { + + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitConfiguration[j].aucCountryCode[0], &u2CountryCodeCheck); + if (((g_rRlmPowerLimitConfiguration[i].ucCentralCh) == + g_rRlmPowerLimitConfiguration[j].ucCentralCh) + && (u2CountryCodeTable == u2CountryCodeCheck)) { + fgEntryRepetetion = TRUE; + DBGLOG(RLM, LOUD, "Domain: Configuration Repetition CC=%c%c, Ch=%d\n", + g_rRlmPowerLimitConfiguration[i].aucCountryCode[0], + g_rRlmPowerLimitConfiguration[i].aucCountryCode[1], + g_rRlmPowerLimitConfiguration[i].ucCentralCh); + } + } + + /*Channel Number Check */ + fgChannelValid = + rlmDomainCheckChannelEntryValid(prAdapter, g_rRlmPowerLimitConfiguration[i].ucCentralCh); + + /*Power Limit Check */ + fgPowerLimitValid = + rlmDomainCheckPowerLimitValid(prAdapter, g_rRlmPowerLimitConfiguration[i], PWR_LIMIT_NUM); + + if (fgChannelValid == FALSE || fgPowerLimitValid == FALSE) { + fgTableValid = FALSE; + DBGLOG(RLM, LOUD, "Domain: CC=%c%c, Ch=%d, Limit: %d,%d,%d,%d,%d\n", + g_rRlmPowerLimitConfiguration[i].aucCountryCode[0], + g_rRlmPowerLimitConfiguration[i].aucCountryCode[1], + g_rRlmPowerLimitConfiguration[i].ucCentralCh, + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_CCK], + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_20M], + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_40M], + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_80M], + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_160M]); + } + + if (u2CountryCodeTable == COUNTRY_CODE_NULL) { + DBGLOG(RLM, LOUD, "Domain: Full search down\n"); + break; /*End of country table entry */ + } + + } + + if (fgEntryRepetetion == FALSE) + DBGLOG(RLM, TRACE, "Domain: Configuration Table no Repetiton.\n"); + + /*Configuration Table no error */ + if (fgTableValid == TRUE) + prAdapter->fgIsPowerLimitTableValid = TRUE; + else + prAdapter->fgIsPowerLimitTableValid = FALSE; + + /*Default Table Check */ + fgEntryRepetetion = FALSE; + for (i = 0; i < sizeof(g_rRlmPowerLimitDefault) / sizeof(COUNTRY_POWER_LIMIT_TABLE_DEFAULT); i++) { + + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[i].aucCountryCode[0], &u2CountryCodeTable); + + for (j = i + 1; j < sizeof(g_rRlmPowerLimitDefault) / sizeof(COUNTRY_POWER_LIMIT_TABLE_DEFAULT); j++) { + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[j].aucCountryCode[0], &u2CountryCodeCheck); + if (u2CountryCodeTable == u2CountryCodeCheck) { + fgEntryRepetetion = TRUE; + DBGLOG(RLM, LOUD, + "Domain: Default Repetition CC=%c%c\n", + g_rRlmPowerLimitDefault[j].aucCountryCode[0], + g_rRlmPowerLimitDefault[j].aucCountryCode[1]); + } + } + } + if (fgEntryRepetetion == FALSE) + DBGLOG(RLM, TRACE, "Domain: Default Table no Repetiton.\n"); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (u2TableIndex) : if 0xFFFF -> No Table Match +*/ +/*----------------------------------------------------------------------------*/ +UINT_16 rlmDomainPwrLimitDefaultTableDecision(P_ADAPTER_T prAdapter, UINT_16 u2CountryCode) +{ + + UINT_16 i; + UINT_16 u2CountryCodeTable = COUNTRY_CODE_NULL; + UINT_16 u2TableIndex = POWER_LIMIT_TABLE_NULL; /* No Table Match */ + + /*Default Table Index */ + for (i = 0; i < sizeof(g_rRlmPowerLimitDefault) / sizeof(COUNTRY_POWER_LIMIT_TABLE_DEFAULT); i++) { + + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[i].aucCountryCode[0], &u2CountryCodeTable); + + if (u2CountryCodeTable == u2CountryCode) { + u2TableIndex = i; + break; /*match country code */ + } else if (u2CountryCodeTable == COUNTRY_CODE_NULL) { + u2TableIndex = i; + break; /*find last one country- Default */ + } + } + + DBGLOG(RLM, TRACE, "Domain: Default Table Index = %d\n", u2TableIndex); + + return u2TableIndex; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmDomainBuildCmdByDefaultTable(P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T prCmd, UINT_16 u2DefaultTableIndex) +{ + UINT_8 i, k; + P_COUNTRY_POWER_LIMIT_TABLE_DEFAULT prPwrLimitSubBand; + P_CMD_CHANNEL_POWER_LIMIT prCmdPwrLimit; + + prCmdPwrLimit = &prCmd->rChannelPowerLimit[0]; + prPwrLimitSubBand = &g_rRlmPowerLimitDefault[u2DefaultTableIndex]; + + /*Build power limit cmd by default table information */ + + for (i = POWER_LIMIT_2G4; i < POWER_LIMIT_SUBAND_NUM; i++) { + if (prPwrLimitSubBand->aucPwrLimitSubBand[i] < MAX_TX_POWER) { + for (k = g_rRlmSubBand[i].ucStartCh; k <= g_rRlmSubBand[i].ucEndCh; + k += g_rRlmSubBand[i].ucInterval) { + if ((prPwrLimitSubBand->ucPwrUnit & BIT(i)) == 0) { + prCmdPwrLimit->ucCentralCh = k; + prCmdPwrLimit->cPwrLimitCCK = + prPwrLimitSubBand->aucPwrLimitSubBand[i]; + prCmdPwrLimit->cPwrLimit20 = + prPwrLimitSubBand->aucPwrLimitSubBand[i]; + prCmdPwrLimit->cPwrLimit40 = + prPwrLimitSubBand->aucPwrLimitSubBand[i]; + prCmdPwrLimit->cPwrLimit80 = + prPwrLimitSubBand->aucPwrLimitSubBand[i]; + prCmdPwrLimit->cPwrLimit160 = + prPwrLimitSubBand->aucPwrLimitSubBand[i]; + prCmdPwrLimit++; + prCmd->ucNum++; + + } else { + /* + * ex: 40MHz power limit(mW\MHz) = 20MHz power limit(mW\MHz) * 2 + * ---> 40MHz power limit(dBm) = 20MHz power limit(dBm) + 6; + */ + prCmdPwrLimit->ucCentralCh = k; + prCmdPwrLimit->cPwrLimitCCK = prPwrLimitSubBand->aucPwrLimitSubBand[i]; + prCmdPwrLimit->cPwrLimit20 = prPwrLimitSubBand->aucPwrLimitSubBand[i]; + prCmdPwrLimit->cPwrLimit40 = prPwrLimitSubBand->aucPwrLimitSubBand[i] + 6; + if (prCmdPwrLimit->cPwrLimit40 > MAX_TX_POWER) + prCmdPwrLimit->cPwrLimit40 = MAX_TX_POWER; + prCmdPwrLimit->cPwrLimit80 = prPwrLimitSubBand->aucPwrLimitSubBand[i] + 12; + if (prCmdPwrLimit->cPwrLimit80 > MAX_TX_POWER) + prCmdPwrLimit->cPwrLimit80 = MAX_TX_POWER; + prCmdPwrLimit->cPwrLimit160 = prPwrLimitSubBand->aucPwrLimitSubBand[i] + 18; + if (prCmdPwrLimit->cPwrLimit160 > MAX_TX_POWER) + prCmdPwrLimit->cPwrLimit160 = MAX_TX_POWER; + prCmdPwrLimit++; + prCmd->ucNum++; + } + } + } + } + +#if 0 + if (prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_2G4] < MAX_TX_POWER) { + for (i = BAND_2G4_LOWER_BOUND; i <= BAND_2G4_UPPER_BOUND; i++) { + prCmdPwrLimit->ucCentralCh = i; + kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_2G4], + PWR_LIMIT_NUM); + prCmdPwrLimit++; + prCmd->ucNum++; + } + } + + if (prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII1] < MAX_TX_POWER) { + if (prCmd->u2CountryCode != COUNTRY_CODE_KR) { + for (i = UNII1_LOWER_BOUND; i <= UNII1_UPPER_BOUND; i += 2) { + prCmdPwrLimit->ucCentralCh = i; + kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, + prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII1], PWR_LIMIT_NUM); + prCmdPwrLimit++; + prCmd->ucNum++; + } + } else { + for (i = UNII1_LOWER_BOUND; i <= UNII1_UPPER_BOUND; i += 2) { + /* + * ex: 40MHz power limit(mW\MHz) = 20MHz power limit(mW\MHz) * 2 + * ---> 40MHz power limit(dBm) = 20MHz power limit(dBm) + 6; + */ + prCmdPwrLimit->ucCentralCh = i; + prCmdPwrLimit->cPwrLimitCCK = + g_rRlmPowerLimitDefault[u2DefaultTableIndex].cPwrLimitUnii1; + prCmdPwrLimit->cPwrLimit20 = + g_rRlmPowerLimitDefault[u2DefaultTableIndex].cPwrLimitUnii1; + prCmdPwrLimit->cPwrLimit40 = + g_rRlmPowerLimitDefault[u2DefaultTableIndex].cPwrLimitUnii1 + 6; + prCmdPwrLimit->cPwrLimit80 = + g_rRlmPowerLimitDefault[u2DefaultTableIndex].cPwrLimitUnii1 + 12; + prCmdPwrLimit->cPwrLimit160 = + g_rRlmPowerLimitDefault[u2DefaultTableIndex].cPwrLimitUnii1 + 18; + prCmdPwrLimit++; + prCmd->ucNum++; + } + } + } + + if (prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII2A] < MAX_TX_POWER) { + for (i = UNII2A_LOWER_BOUND; i <= UNII2A_UPPER_BOUND; i += 2) { + prCmdPwrLimit->ucCentralCh = i; + kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, + prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII2A], PWR_LIMIT_NUM); + prCmdPwrLimit++; + prCmd->ucNum++; + } + } + + if (prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII2C] < MAX_TX_POWER) { + for (i = UNII2C_LOWER_BOUND; i <= UNII2C_UPPER_BOUND; i += 2) { + prCmdPwrLimit->ucCentralCh = i; + kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, + prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII2C], PWR_LIMIT_NUM); + prCmdPwrLimit++; + prCmd->ucNum++; + } + } + if (prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII3] < MAX_TX_POWER) { + for (i = UNII3_LOWER_BOUND; i <= UNII3_UPPER_BOUND; i += 2) { + prCmdPwrLimit->ucCentralCh = i; + kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, + prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII3], PWR_LIMIT_NUM); + prCmdPwrLimit++; + prCmd->ucNum++; + } + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmDomainBuildCmdByConfigTable(P_ADAPTER_T prAdapter, P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T prCmd) +{ + UINT_8 i, k; + UINT_16 u2CountryCodeTable = COUNTRY_CODE_NULL; + P_CMD_CHANNEL_POWER_LIMIT prCmdPwrLimit; + BOOLEAN fgChannelValid; + + /* Build power limit cmd by configuration table information */ + + for (i = 0; i < sizeof(g_rRlmPowerLimitConfiguration) / sizeof(COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION); i++) { + + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitConfiguration[i].aucCountryCode[0], &u2CountryCodeTable); + + fgChannelValid = + rlmDomainCheckChannelEntryValid(prAdapter, g_rRlmPowerLimitConfiguration[i].ucCentralCh); + + if (u2CountryCodeTable == COUNTRY_CODE_NULL) { + DBGLOG(RLM, TRACE, "Domain: full search configuration table done.\n"); + break; /*end of configuration table */ + } else if ((u2CountryCodeTable == prCmd->u2CountryCode) && (fgChannelValid == TRUE)) { + + prCmdPwrLimit = &prCmd->rChannelPowerLimit[0]; + + if (prCmd->ucNum != 0) { + for (k = 0; k < prCmd->ucNum; k++) { + if (prCmdPwrLimit->ucCentralCh == + g_rRlmPowerLimitConfiguration[i].ucCentralCh) { + + /* + * Cmd setting (Default table information) and + * Configuration table has repetition channel entry, + * ex : Default table (ex: 2.4G, limit = 20dBm) --> + * ch1~14 limit =20dBm, + * Configuration table (ex: ch1, limit = 22dBm) --> ch 1 = 22 dBm + * Cmd final setting --> ch1 = 22dBm, ch12~14 = 20dBm + */ + prCmdPwrLimit->cPwrLimitCCK = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_CCK]; + prCmdPwrLimit->cPwrLimit20 = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_20M]; + prCmdPwrLimit->cPwrLimit40 = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_40M]; + prCmdPwrLimit->cPwrLimit80 = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_80M]; + prCmdPwrLimit->cPwrLimit160 = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_160M]; + + DBGLOG(RLM, LOUD, + "Domain: CC=%c%c,ConfigCh=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", + ((prCmd->u2CountryCode & 0xff00) >> 8), + (prCmd->u2CountryCode & 0x00ff), prCmdPwrLimit->ucCentralCh, + prCmdPwrLimit->cPwrLimitCCK, prCmdPwrLimit->cPwrLimit20, + prCmdPwrLimit->cPwrLimit40, prCmdPwrLimit->cPwrLimit80, + prCmdPwrLimit->cPwrLimit160, prCmdPwrLimit->ucFlag); + + break; + } + prCmdPwrLimit++; + } + if (k == prCmd->ucNum) { + + /* + * Full search cmd (Default table setting) no match channey, + * ex : Default table (ex: 2.4G, limit = 20dBm) --> ch1~14 limit =20dBm, + * Configuration table (ex: ch36, limit = 22dBm) --> ch 36 = 22 dBm + * Cmd final setting --> ch1~14 = 20dBm, ch36= 22dBm + */ + prCmdPwrLimit->cPwrLimitCCK = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_CCK]; + prCmdPwrLimit->cPwrLimit20 = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_20M]; + prCmdPwrLimit->cPwrLimit40 = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_40M]; + prCmdPwrLimit->cPwrLimit80 = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_80M]; + prCmdPwrLimit->cPwrLimit160 = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_160M]; + prCmd->ucNum++; + + DBGLOG(RLM, LOUD, + "Domain: Full CC=%c%c,ConfigCh=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", + ((prCmd->u2CountryCode & 0xff00) >> 8), (prCmd->u2CountryCode & 0x00ff), + prCmdPwrLimit->ucCentralCh, prCmdPwrLimit->cPwrLimitCCK, + prCmdPwrLimit->cPwrLimit20, prCmdPwrLimit->cPwrLimit40, + prCmdPwrLimit->cPwrLimit80, prCmdPwrLimit->cPwrLimit160, + prCmdPwrLimit->ucFlag); + + } + } else { + + /* + * Default table power limit value are 63--> cmd table no channel entry + * ex : Default table (ex: 2.4G, limit = 63Bm) --> no channel entry in cmd, + * Configuration table (ex: ch36, limit = 22dBm) --> ch 36 = 22 dBm + * Cmd final setting --> ch36= 22dBm + */ + prCmdPwrLimit->ucCentralCh = g_rRlmPowerLimitConfiguration[i].ucCentralCh; + prCmdPwrLimit->cPwrLimitCCK = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_CCK]; + prCmdPwrLimit->cPwrLimit20 = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_20M]; + prCmdPwrLimit->cPwrLimit40 = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_40M]; + prCmdPwrLimit->cPwrLimit80 = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_80M]; + prCmdPwrLimit->cPwrLimit160 = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_160M]; + prCmd->ucNum++; + + DBGLOG(RLM, LOUD, "Domain: Default table power limit value are 63.\n"); + DBGLOG(RLM, LOUD, "Domain: CC=%c%c,ConfigCh=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", + ((prCmd->u2CountryCode & 0xff00) >> 8), + (prCmd->u2CountryCode & 0x00ff), prCmdPwrLimit->ucCentralCh, + prCmdPwrLimit->cPwrLimitCCK, prCmdPwrLimit->cPwrLimit20, + prCmdPwrLimit->cPwrLimit40, prCmdPwrLimit->cPwrLimit80, + prCmdPwrLimit->cPwrLimit160, prCmdPwrLimit->ucFlag); + + } + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmDomainSendPwrLimitCmd(P_ADAPTER_T prAdapter) +{ + P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T prCmd; + UINT_8 i; + UINT_16 u2DefaultTableIndex; + UINT_32 u4SetCmdTableMaxSize; + UINT_32 u4SetQueryInfoLen; + P_CMD_CHANNEL_POWER_LIMIT prCmdPwrLimit; /* for print usage */ + + u4SetCmdTableMaxSize = + sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T) + + MAX_CMD_SUPPORT_CHANNEL_NUM * sizeof(CMD_CHANNEL_POWER_LIMIT); + + prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4SetCmdTableMaxSize); + + if (!prCmd) { + DBGLOG(RLM, ERROR, "Domain: no buf to send cmd\n"); + return; + } + kalMemZero(prCmd, u4SetCmdTableMaxSize); + + u2DefaultTableIndex = + rlmDomainPwrLimitDefaultTableDecision(prAdapter, prAdapter->rWifiVar.rConnSettings.u2CountryCode); + + if (u2DefaultTableIndex != POWER_LIMIT_TABLE_NULL) { + + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[u2DefaultTableIndex].aucCountryCode[0], + &prCmd->u2CountryCode); + + prCmd->ucNum = 0; + + if (prCmd->u2CountryCode != COUNTRY_CODE_NULL) { + /*Command - default table information */ + rlmDomainBuildCmdByDefaultTable(prCmd, u2DefaultTableIndex); + + /*Command - configuration table information */ + rlmDomainBuildCmdByConfigTable(prAdapter, prCmd); + } + } +#if 0 + u4SetCmdTableMaxSize = + sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T) + + MAX_CMD_SUPPORT_CHANNEL_NUM * sizeof(CMD_CHANNEL_POWER_LIMIT); + + prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4SetCmdTableMaxSize); + ASSERT(prCmd); + + /* To do: exception handle */ + if (!prCmd) { + DBGLOG(RLM, ERROR, "Domain: no buf to send cmd\n"); + return; + } + kalMemZero(prCmd, u4SetCmdTableMaxSize); /* TODO memzero */ + + if (u2TableIndex != POWER_LIMIT_TABLE_NULL && u2TableIndex < MAX_DEFAULT_TABLE_COUNTRY_NUM) { + + prCmd->u2CountryCode = (((UINT_16) g_rRlmCountryPowerLimitTable[u2TableIndex].aucCountryCode[0]) << 8) | + (((UINT_16) g_rRlmCountryPowerLimitTable[u2TableIndex].aucCountryCode[1]) & BITS(0, 7)); + prChPwrLimit = &g_rRlmCountryPowerLimitTable[u2TableIndex].rChannelPowerLimit[0]; + prCmdPwrLimit = &prCmd->rChannelPowerLimit[0]; + prCmd->ucNum = 0; + for (i = 0; i < MAX_CMD_SUPPORT_CHANNEL_NUM; i++) { + + if (prChPwrLimit->ucCentralCh != ENDCH) { + + /*Check Power limit table channel efficient or not */ + fgChannelValid = rlmDomainCheckChannelEntryValid(prAdapter, prChPwrLimit->ucCentralCh); + + /*Cmd set up */ + if (fgChannelValid) { + kalMemCopy(prCmdPwrLimit, prChPwrLimit, sizeof(CMD_CHANNEL_POWER_LIMIT)); + DBGLOG(RLM, INFO, + "Domain: ValidCh=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", + prCmdPwrLimit->ucCentralCh, prCmdPwrLimit->cPwrLimitCCK, + prCmdPwrLimit->cPwrLimit20, prCmdPwrLimit->cPwrLimit40, + prCmdPwrLimit->cPwrLimit80, prCmdPwrLimit->cPwrLimit160, + prCmdPwrLimit->ucFlag); + prCmd->ucNum++; + prCmdPwrLimit++; + } else { + DBGLOG(RLM, INFO, + "Domain: Non-Ch=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", + prChPwrLimit->ucCentralCh, prChPwrLimit->cPwrLimitCCK, + prChPwrLimit->cPwrLimit20, prChPwrLimit->cPwrLimit40, + prChPwrLimit->cPwrLimit80, prChPwrLimit->cPwrLimit160, + prChPwrLimit->ucFlag); + } + prChPwrLimit++; + } else { + /*End of the chanel entry */ + break; + } + }; + } +#endif + + if (prCmd->u2CountryCode != 0) { + DBGLOG(RLM, INFO, + "Domain: ValidCC =%c%c, ChNum=%d\n", ((prCmd->u2CountryCode & 0xff00) >> 8), + (prCmd->u2CountryCode & 0x00ff), prCmd->ucNum); + } else { + DBGLOG(RLM, INFO, "Domain: ValidCC =0x%04x, ucNum=%d\n", prCmd->u2CountryCode, prCmd->ucNum); + } + prCmdPwrLimit = &prCmd->rChannelPowerLimit[0]; + + for (i = 0; i < prCmd->ucNum; i++) { + DBGLOG(RLM, TRACE, "Domain: Ch=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", prCmdPwrLimit->ucCentralCh, + prCmdPwrLimit->cPwrLimitCCK, prCmdPwrLimit->cPwrLimit20, prCmdPwrLimit->cPwrLimit40, + prCmdPwrLimit->cPwrLimit80, prCmdPwrLimit->cPwrLimit160, prCmdPwrLimit->ucFlag); + prCmdPwrLimit++; + } + + u4SetQueryInfoLen = + (sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T) + (prCmd->ucNum) * sizeof(CMD_CHANNEL_POWER_LIMIT)); + + /* Update domain info to chip */ + if (prCmd->ucNum <= MAX_CMD_SUPPORT_CHANNEL_NUM) { + wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_COUNTRY_POWER_LIMIT, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + u4SetQueryInfoLen, /* u4SetQueryInfoLen */ + (PUINT_8) prCmd, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + } else + DBGLOG(RLM, ERROR, "Domain: illegal power limit table"); + + cnmMemFree(prAdapter, prCmd); + +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/rlm_obss.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/rlm_obss.c new file mode 100644 index 0000000000000..781a55a029a48 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/rlm_obss.c @@ -0,0 +1,315 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static VOID rlmObssScanTimeout(P_ADAPTER_T prAdapter, ULONG ulData); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmObssInit(P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prBssInfo; + UINT_8 ucNetIdx; + + RLM_NET_FOR_EACH(ucNetIdx) { + prBssInfo = &prAdapter->rWifiVar.arBssInfo[ucNetIdx]; + ASSERT(prBssInfo); + + cnmTimerInitTimer(prAdapter, &prBssInfo->rObssScanTimer, rlmObssScanTimeout, (ULONG) prBssInfo); + } /* end of RLM_NET_FOR_EACH */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rlmObssUpdateChnlLists(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) +{ + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmObssScanDone(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr) +{ + P_MSG_SCN_SCAN_DONE prScanDoneMsg; + P_BSS_INFO_T prBssInfo; + P_MSDU_INFO_T prMsduInfo; + P_ACTION_20_40_COEXIST_FRAME prTxFrame; + UINT_16 i, u2PayloadLen; + + ASSERT(prMsgHdr); + + prScanDoneMsg = (P_MSG_SCN_SCAN_DONE) prMsgHdr; + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prScanDoneMsg->ucNetTypeIndex]; + ASSERT(prBssInfo); + + DBGLOG(RLM, INFO, "OBSS Scan Done (NetIdx=%d, Mode=%d)\n", + prScanDoneMsg->ucNetTypeIndex, prBssInfo->eCurrentOPMode); + + cnmMemFree(prAdapter, prMsgHdr); + +#if CFG_ENABLE_WIFI_DIRECT + /* AP mode */ + if ((prAdapter->fgIsP2PRegistered) && + (IS_NET_ACTIVE(prAdapter, prBssInfo->ucNetTypeIndex)) && + (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { + return; + } +#endif + + /* STA mode */ + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE || + !RLM_NET_PARAM_VALID(prBssInfo) || prBssInfo->u2ObssScanInterval == 0) { + DBGLOG(RLM, WARN, "OBSS Scan Done (NetIdx=%d) -- Aborted!!\n", prBssInfo->ucNetTypeIndex); + return; + } + + /* To do: check 2.4G channel list to decide if obss mgmt should be + * sent to associated AP. Note: how to handle concurrent network? + * To do: invoke rlmObssChnlLevel() to decide if 20/40 BSS coexistence + * management frame is needed. + */ + prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + if ((prBssInfo->auc2G_20mReqChnlList[0] > 0 || prBssInfo->auc2G_NonHtChnlList[0] > 0) && prMsduInfo != NULL) { + DBGLOG(RLM, INFO, "Send 20/40 coexistence mgmt(20mReq=%d, NonHt=%d)\n", + prBssInfo->auc2G_20mReqChnlList[0], prBssInfo->auc2G_NonHtChnlList[0]); + + prTxFrame = (P_ACTION_20_40_COEXIST_FRAME) + ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + COPY_MAC_ADDR(prTxFrame->aucDestAddr, prBssInfo->aucBSSID); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); + + prTxFrame->ucCategory = CATEGORY_PUBLIC_ACTION; + prTxFrame->ucAction = ACTION_PUBLIC_20_40_COEXIST; + + /* To do: find correct algorithm */ + prTxFrame->rBssCoexist.ucId = ELEM_ID_20_40_BSS_COEXISTENCE; + prTxFrame->rBssCoexist.ucLength = 1; + prTxFrame->rBssCoexist.ucData = (prBssInfo->auc2G_20mReqChnlList[0] > 0) ? BSS_COEXIST_20M_REQ : 0; + + u2PayloadLen = 2 + 3; + + if (prBssInfo->auc2G_NonHtChnlList[0] > 0) { + ASSERT(prBssInfo->auc2G_NonHtChnlList[0] <= CHNL_LIST_SZ_2G); + + prTxFrame->rChnlReport.ucId = ELEM_ID_20_40_INTOLERANT_CHNL_REPORT; + prTxFrame->rChnlReport.ucLength = prBssInfo->auc2G_NonHtChnlList[0] + 1; + prTxFrame->rChnlReport.ucRegulatoryClass = 81; /* 2.4GHz, ch1~13 */ + for (i = 0; i < prBssInfo->auc2G_NonHtChnlList[0] && i < CHNL_LIST_SZ_2G; i++) + prTxFrame->rChnlReport.aucChannelList[i] = prBssInfo->auc2G_NonHtChnlList[i + 1]; + + u2PayloadLen += IE_SIZE(&prTxFrame->rChnlReport); + } + ASSERT((WLAN_MAC_HEADER_LEN + u2PayloadLen) <= PUBLIC_ACTION_MAX_LEN); + + /* Clear up channel lists in 2.4G band */ + prBssInfo->auc2G_20mReqChnlList[0] = 0; + prBssInfo->auc2G_NonHtChnlList[0] = 0; + + /* 4 Update information of MSDU_INFO_T */ + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; /* Management frame */ + prMsduInfo->ucStaRecIndex = prBssInfo->prStaRecOfAP->ucIndex; + prMsduInfo->ucNetworkType = prBssInfo->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->fgIsBasicRate = FALSE; + + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + } + /* end of prMsduInfo != NULL */ + if (prBssInfo->u2ObssScanInterval > 0) { + DBGLOG(RLM, INFO, "Set OBSS timer (NetIdx=%d, %d sec)\n", + prBssInfo->ucNetTypeIndex, prBssInfo->u2ObssScanInterval); + + cnmTimerStartTimer(prAdapter, &prBssInfo->rObssScanTimer, prBssInfo->u2ObssScanInterval * MSEC_PER_SEC); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static VOID rlmObssScanTimeout(P_ADAPTER_T prAdapter, ULONG ulData) +{ + P_BSS_INFO_T prBssInfo; + + prBssInfo = (P_BSS_INFO_T) ulData; + ASSERT(prBssInfo); + +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered && (IS_NET_ACTIVE(prAdapter, prBssInfo->ucNetTypeIndex))) { + + /* AP mode */ + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + + prBssInfo->fgObssActionForcedTo20M = FALSE; + + /* Check if Beacon content need to be updated */ + rlmUpdateParamsForAP(prAdapter, prBssInfo, FALSE); + + return; + } +#if CFG_SUPPORT_WFD + /* WFD streaming */ + else { + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = + &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings; + P_BSS_INFO_T prP2pBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; + + /* If WFD is enabled & connected */ + if (prWfdCfgSettings->ucWfdEnable && + (prWfdCfgSettings->u4WfdFlag & BIT(0)) && RLM_NET_PARAM_VALID(prP2pBssInfo)) { + + /* Skip OBSS scan */ + prBssInfo->u2ObssScanInterval = 0; + + DBGLOG(RLM, INFO, "WFD is running. Stop net[%u] OBSS scan.\n", + (UINT_32) prBssInfo->ucNetTypeIndex); + + return; + } + } +#endif + } +#endif /* end of CFG_ENABLE_WIFI_DIRECT */ + + /* STA mode */ + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE || + !RLM_NET_PARAM_VALID(prBssInfo) || prBssInfo->u2ObssScanInterval == 0) { + DBGLOG(RLM, WARN, "OBSS Scan timeout (NetIdx=%d) -- Aborted!!\n", prBssInfo->ucNetTypeIndex); + return; + } + + rlmObssTriggerScan(prAdapter, prBssInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmObssTriggerScan(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) +{ + P_MSG_SCN_SCAN_REQ prScanReqMsg; + + ASSERT(prBssInfo); + + prScanReqMsg = (P_MSG_SCN_SCAN_REQ) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_REQ)); + ASSERT(prScanReqMsg); + + if (!prScanReqMsg) { + DBGLOG(RLM, WARN, "No buf for OBSS scan (NetIdx=%d)!!\n", prBssInfo->ucNetTypeIndex); + + cnmTimerStartTimer(prAdapter, &prBssInfo->rObssScanTimer, prBssInfo->u2ObssScanInterval * MSEC_PER_SEC); + return; + } + + /* It is ok that ucSeqNum is set to fixed value because the same network + * OBSS scan interval is limited to OBSS_SCAN_MIN_INTERVAL (min 10 sec) + * and scan module don't care seqNum of OBSS scanning + */ + prScanReqMsg->rMsgHdr.eMsgId = MID_RLM_SCN_SCAN_REQ; + prScanReqMsg->ucSeqNum = 0x33; + prScanReqMsg->ucNetTypeIndex = prBssInfo->ucNetTypeIndex; + prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_WILDCARD; + prScanReqMsg->ucSSIDLength = 0; + prScanReqMsg->eScanChannel = SCAN_CHANNEL_2G4; + prScanReqMsg->u2IELen = 0; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanReqMsg, MSG_SEND_METHOD_BUF); + + DBGLOG(RLM, INFO, "Timeout to trigger OBSS scan (NetIdx=%d)!!\n", prBssInfo->ucNetTypeIndex); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/rlm_protection.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/rlm_protection.c new file mode 100644 index 0000000000000..a9db16b7c91d8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/rlm_protection.c @@ -0,0 +1,57 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/roaming_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/roaming_fsm.c new file mode 100644 index 0000000000000..56da0ddb069cc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/roaming_fsm.c @@ -0,0 +1,610 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E 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 +******************************************************************************** +*/ +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Initialize the value in ROAMING_FSM_INFO_T for ROAMING FSM operation +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID roamingFsmInit(IN P_ADAPTER_T prAdapter) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + + DBGLOG(ROAMING, LOUD, "->roamingFsmInit(): Current Time = %u\n", kalGetTimeTick()); + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* 4 <1> Initiate FSM */ + prRoamingFsmInfo->fgIsEnableRoaming = prConnSettings->fgIsEnableRoaming; + prRoamingFsmInfo->eCurrentState = ROAMING_STATE_IDLE; + prRoamingFsmInfo->rRoamingDiscoveryUpdateTime = 0; + prRoamingFsmInfo->DrvRoamingAllow = 1; + +} /* end of roamingFsmInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Uninitialize the value in AIS_FSM_INFO_T for AIS FSM operation +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID roamingFsmUninit(IN P_ADAPTER_T prAdapter) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + + DBGLOG(ROAMING, LOUD, "->roamingFsmUninit(): Current Time = %u\n", kalGetTimeTick()); + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + prRoamingFsmInfo->eCurrentState = ROAMING_STATE_IDLE; + +} /* end of roamingFsmUninit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Send commands to firmware +* +* @param [IN P_ADAPTER_T] prAdapter +* [IN P_ROAMING_PARAM_T] prParam +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID roamingFsmSendCmd(IN P_ADAPTER_T prAdapter, IN P_ROAMING_PARAM_T prParam) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + WLAN_STATUS rStatus; + + DBGLOG(ROAMING, LOUD, "->roamingFsmSendCmd(): Current Time = %u\n", kalGetTimeTick()); + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_ROAMING_TRANSIT, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(ROAMING_PARAM_T), /* u4SetQueryInfoLen */ + (PUINT_8) prParam, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); + +} /* end of roamingFsmSendCmd() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Update the recent time when ScanDone occurred +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID roamingFsmScanResultsUpdate(IN P_ADAPTER_T prAdapter) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + DBGLOG(ROAMING, LOUD, "->roamingFsmScanResultsUpdate(): Current Time = %u", kalGetTimeTick()); + + GET_CURRENT_SYSTIME(&prRoamingFsmInfo->rRoamingDiscoveryUpdateTime); + +} /* end of roamingFsmScanResultsUpdate() */ +#if !(CFG_SUPPORT_NCHO) +static BOOLEAN roamingFsmIsNeedScan(IN P_ADAPTER_T prAdapter) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prRoamBSSDescList; + P_ROAM_BSS_DESC_T prRoamBssDesc; + P_BSS_INFO_T prAisBssInfo; + P_BSS_DESC_T prBssDesc; + CMD_ID_SET_ROAMING_SKIP_T rCmdSwCtrl; + BOOLEAN fgIsNeedScan = FALSE; + BOOLEAN fgIsRoamingSSID = FALSE; + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prRoamBSSDescList = &prScanInfo->rRoamBSSDescList; + /* Count same BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prRoamBssDesc, prRoamBSSDescList, rLinkEntry, ROAM_BSS_DESC_T) { + if (EQUAL_SSID(prRoamBssDesc->aucSSID, + prRoamBssDesc->ucSSIDLen, + prAisBssInfo->aucSSID, prAisBssInfo->ucSSIDLen)) { + fgIsRoamingSSID = TRUE; + fgIsNeedScan = TRUE; + DBGLOG(INIT, INFO, "roamingFsmSteps: IsRoamingSSID:%d\n", fgIsRoamingSSID); + break; + } + } + + if (!fgIsRoamingSSID) { + prBssDesc = scanSearchBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); + if (prBssDesc) { + + rCmdSwCtrl.IsRoamingSkipOneAp = TRUE; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_ROAMING_SKIP, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_ID_SET_ROAMING_SKIP_T), + (PUINT_8)&rCmdSwCtrl, NULL, 0); + + DBGLOG(INIT, INFO, "roamingFsmSteps: RCPI:%d RoamSkipTimes:%d\n", + prBssDesc->ucRCPI, prAisBssInfo->ucRoamSkipTimes); + if (prBssDesc->ucRCPI > CFG_GOOG_RCPI_THRESHOLD) { + prAisBssInfo->ucRoamSkipTimes = CFG_GOOG_RCPI_SCAN_SKIP_TIMES; + prAisBssInfo->fgGoodRcpiArea = TRUE; + prAisBssInfo->fgPoorRcpiArea = FALSE; + } else { + if (prAisBssInfo->fgGoodRcpiArea) { + prAisBssInfo->ucRoamSkipTimes--; + } else if (prBssDesc->ucRCPI > CFG_POOR_RCPI_THRESHOLD) { + if (!prAisBssInfo->fgPoorRcpiArea) { + prAisBssInfo->ucRoamSkipTimes = CFG_POOR_RCPI_SCAN_SKIP_TIMES; + prAisBssInfo->fgPoorRcpiArea = TRUE; + prAisBssInfo->fgGoodRcpiArea = FALSE; + } else { + prAisBssInfo->ucRoamSkipTimes--; + } + } else { + prAisBssInfo->fgPoorRcpiArea = FALSE; + prAisBssInfo->fgGoodRcpiArea = FALSE; + prAisBssInfo->ucRoamSkipTimes--; + } + } + + if (prAisBssInfo->ucRoamSkipTimes == 0) { + prAisBssInfo->ucRoamSkipTimes = CFG_GOOG_RCPI_SCAN_SKIP_TIMES; + prAisBssInfo->fgPoorRcpiArea = FALSE; + prAisBssInfo->fgGoodRcpiArea = FALSE; + DBGLOG(INIT, INFO, "roamingFsmSteps: Need Scan\n"); + fgIsNeedScan = TRUE; + } + } + } + + return fgIsNeedScan; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! +* @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; +#if CFG_SUPPORT_NCHO + UINT32 u4ScnResultsTimeout = ROAMING_DISCOVERY_TIMEOUT_SEC; + UINT_32 u4ReqScan = FALSE; +#endif + + 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: + { +#if CFG_SUPPORT_NCHO + if (prAdapter->rNchoInfo.fgECHOEnabled == TRUE) { + u4ScnResultsTimeout = prAdapter->rNchoInfo.u4RoamScanPeriod; + DBGLOG(ROAMING, TRACE, "NCHO u4ScnResultsTimeout is %d\n", u4ScnResultsTimeout); + } + + if (CHECK_FOR_TIMEOUT(kalGetTimeTick(), prRoamingFsmInfo->rRoamingDiscoveryUpdateTime, + SEC_TO_SYSTIME(u4ScnResultsTimeout))) { + DBGLOG(ROAMING, LOUD, "DiscoveryUpdateTime Timeout"); + u4ReqScan = TRUE; + } else { + DBGLOG(ROAMING, LOUD, "DiscoveryUpdateTime Updated"); +#if CFG_SUPPORT_ROAMING_ENC + if (prAdapter->fgIsRoamingEncEnabled == TRUE) + u4ReqScan = TRUE; + else +#endif /* CFG_SUPPORT_ROAMING_ENC */ + u4ReqScan = FALSE; + } + aisFsmRunEventRoamingDiscovery(prAdapter, u4ReqScan); +#else + OS_SYSTIME rCurrentTime; + BOOLEAN fgIsNeedScan = FALSE; + + fgIsNeedScan = roamingFsmIsNeedScan(prAdapter); + + GET_CURRENT_SYSTIME(&rCurrentTime); + if (CHECK_FOR_TIMEOUT(rCurrentTime, prRoamingFsmInfo->rRoamingDiscoveryUpdateTime, + SEC_TO_SYSTIME(ROAMING_DISCOVERY_TIMEOUT_SEC)) && fgIsNeedScan) { + DBGLOG(ROAMING, LOUD, "roamingFsmSteps: DiscoveryUpdateTime Timeout"); + aisFsmRunEventRoamingDiscovery(prAdapter, TRUE); + } else { + DBGLOG(ROAMING, LOUD, "roamingFsmSteps: DiscoveryUpdateTime Updated"); +#if CFG_SUPPORT_ROAMING_ENC + if (prAdapter->fgIsRoamingEncEnabled == TRUE) + aisFsmRunEventRoamingDiscovery(prAdapter, TRUE); + else +#endif /* CFG_SUPPORT_ROAMING_ENC */ + aisFsmRunEventRoamingDiscovery(prAdapter, FALSE); + } +#endif + } + + break; + + case ROAMING_STATE_ROAM: + break; + + default: + ASSERT(0); /* Make sure we have handle all STATEs */ + } + } while (fgIsTransition); + + return; + +} /* end of roamingFsmSteps() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Transit to Decision state after join completion +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID roamingFsmRunEventStart(IN P_ADAPTER_T prAdapter) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + ENUM_ROAMING_STATE_T eNextState; + P_BSS_INFO_T prAisBssInfo; + ROAMING_PARAM_T rParam; + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + if (prAisBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + return; + + DBGLOG(ROAMING, EVENT, "EVENT-ROAMING START: Current Time = %u\n", kalGetTimeTick()); + + /* IDLE, ROAM -> DECISION */ + /* Errors as DECISION, DISCOVERY -> DECISION */ + if (!(prRoamingFsmInfo->eCurrentState == ROAMING_STATE_IDLE || + prRoamingFsmInfo->eCurrentState == ROAMING_STATE_ROAM)) + return; + + eNextState = ROAMING_STATE_DECISION; + if (eNextState != prRoamingFsmInfo->eCurrentState) { + rParam.u2Event = ROAMING_EVENT_START; + roamingFsmSendCmd(prAdapter, (P_ROAMING_PARAM_T) & rParam); + + /* Step to next state */ + roamingFsmSteps(prAdapter, eNextState); + } + +} /* end of roamingFsmRunEventStart() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Transit to Discovery state when deciding to find a candidate +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID roamingFsmRunEventDiscovery(IN P_ADAPTER_T prAdapter, IN P_ROAMING_PARAM_T prParam) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + ENUM_ROAMING_STATE_T eNextState; + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + DBGLOG(ROAMING, EVENT, "EVENT-ROAMING DISCOVERY: Current Time = %u Reason = %u\n", + kalGetTimeTick(), prParam->u2Reason); + + /* DECISION -> DISCOVERY */ + /* Errors as IDLE, DISCOVERY, ROAM -> DISCOVERY */ + if (prRoamingFsmInfo->eCurrentState != ROAMING_STATE_DECISION) + return; +#if CFG_SUPPORT_ROAMING_ENC + prRoamingFsmInfo->RoamingEntryTimeoutSkipCount = 0; +#endif + + eNextState = ROAMING_STATE_DISCOVERY; + /* DECISION -> DISCOVERY */ + if (eNextState != prRoamingFsmInfo->eCurrentState) { + P_BSS_INFO_T prAisBssInfo; + P_BSS_DESC_T prBssDesc; + PARAM_MAC_ADDRESS arBssid; + PARAM_SSID_T rSsid; + P_AIS_FSM_INFO_T prAisFsmInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + + kalMemZero(&rSsid, sizeof(PARAM_SSID_T)); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* sync. rcpi with firmware */ + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prBssDesc = prAisFsmInfo->prTargetBssDesc; + if (prBssDesc) { + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + COPY_MAC_ADDR(arBssid, prBssDesc->aucBSSID); + } else { + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); + COPY_MAC_ADDR(arBssid, prConnSettings->aucBSSID); + } + prBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, arBssid, TRUE, &rSsid); + if (prBssDesc) { + prBssDesc->ucRCPI = (UINT_8) (prParam->u2Data & 0xff); + DBGLOG(ROAMING, INFO, "RCPI %u\n", prBssDesc->ucRCPI); + } + + roamingFsmSteps(prAdapter, eNextState); + } + +} /* end of roamingFsmRunEventDiscovery() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Transit to Roam state after Scan Done +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID roamingFsmRunEventRoam(IN P_ADAPTER_T prAdapter) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + ENUM_ROAMING_STATE_T eNextState; + ROAMING_PARAM_T rParam; + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + DBGLOG(ROAMING, EVENT, "EVENT-ROAMING ROAM: Current Time = %u\n", kalGetTimeTick()); + + /* IDLE, ROAM -> DECISION */ + /* Errors as IDLE, DECISION, ROAM -> ROAM */ + if (prRoamingFsmInfo->eCurrentState != ROAMING_STATE_DISCOVERY) + return; + + eNextState = ROAMING_STATE_ROAM; + /* DISCOVERY -> ROAM */ + if (eNextState != prRoamingFsmInfo->eCurrentState) { + rParam.u2Event = ROAMING_EVENT_ROAM; + roamingFsmSendCmd(prAdapter, (P_ROAMING_PARAM_T) & rParam); + + /* Step to next state */ + roamingFsmSteps(prAdapter, eNextState); + } + +} /* end of roamingFsmRunEventRoam() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Transit to Decision state as being failed to find out any candidate +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID roamingFsmRunEventFail(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Param) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + ENUM_ROAMING_STATE_T eNextState; + ROAMING_PARAM_T rParam; + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + DBGLOG(ROAMING, EVENT, "EVENT-ROAMING FAIL: reason %x Current Time = %u\n", u4Param, kalGetTimeTick()); + + /* IDLE, ROAM -> DECISION */ + /* Errors as IDLE, DECISION, DISCOVERY -> DECISION */ + if (prRoamingFsmInfo->eCurrentState != ROAMING_STATE_ROAM) + return; + + eNextState = ROAMING_STATE_DECISION; + /* ROAM -> DECISION */ + if (eNextState != prRoamingFsmInfo->eCurrentState) { + rParam.u2Event = ROAMING_EVENT_FAIL; + rParam.u2Data = (UINT_16) (u4Param & 0xffff); + roamingFsmSendCmd(prAdapter, (P_ROAMING_PARAM_T) & rParam); + + /* Step to next state */ + roamingFsmSteps(prAdapter, eNextState); + } + +} /* end of roamingFsmRunEventFail() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Transit to Idle state as beging aborted by other moduels, AIS +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID roamingFsmRunEventAbort(IN P_ADAPTER_T prAdapter) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + ENUM_ROAMING_STATE_T eNextState; + ROAMING_PARAM_T rParam; + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + DBGLOG(ROAMING, EVENT, "EVENT-ROAMING ABORT: Current Time = %u\n", kalGetTimeTick()); + + eNextState = ROAMING_STATE_IDLE; + /* IDLE, DECISION, DISCOVERY, ROAM -> IDLE */ + if (eNextState != prRoamingFsmInfo->eCurrentState) { + rParam.u2Event = ROAMING_EVENT_ABORT; + roamingFsmSendCmd(prAdapter, (P_ROAMING_PARAM_T) & rParam); + + /* Step to next state */ + roamingFsmSteps(prAdapter, eNextState); + } + +} /* end of roamingFsmRunEventAbort() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process events from firmware +* +* @param [IN P_ADAPTER_T] prAdapter +* [IN P_ROAMING_PARAM_T] prParam +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS roamingFsmProcessEvent(IN P_ADAPTER_T prAdapter, IN P_ROAMING_PARAM_T prParam) +{ + DBGLOG(ROAMING, LOUD, "ROAMING Process Events: Current Time = %u\n", kalGetTimeTick()); + + if (prParam->u2Event == ROAMING_EVENT_DISCOVERY) + roamingFsmRunEventDiscovery(prAdapter, prParam); + + return WLAN_STATUS_SUCCESS; +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/rsn.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/rsn.c new file mode 100644 index 0000000000000..382a5fb9bcaab --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/rsn.c @@ -0,0 +1,3533 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* + * C O M P I L E 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; + uint16_t u2PmkidCount = 0; + 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); + cp += 2; + u4RemainRsnIeLen -= 2; + + if (u4RemainRsnIeLen == 0) + break; + + if (u4RemainRsnIeLen < 2) { + DBGLOG(RSN, TRACE, + "Fail to parse PMKID count in RSN iE\n"); + return FALSE; + } + + WLAN_GET_FIELD_16(cp, &u2PmkidCount); + cp += 2; + u4RemainRsnIeLen -= 2; + + if (u2PmkidCount > 4) { + DBGLOG(RSN, TRACE, + "Bad RSN IE due to PMKID count(%d)\n", + u2PmkidCount); + return FALSE; + } + + if (u2PmkidCount > 0 && u4RemainRsnIeLen < 16 * u2PmkidCount) { + DBGLOG(RSN, TRACE, + "Fail to parse PMKID in RSN iE, count: %d\n", + u2PmkidCount); + return FALSE; + } + } 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"); + + if ((prAdapter->rWifiVar.rConnSettings.rRsnInfo.u4GroupKeyCipherSuite + & 0x000000FF) != + GET_SELECTOR_TYPE(prBssRsnInfo->u4GroupKeyCipherSuite)) { + DBGLOG(RSN, WARN, "Break by GroupKeyCipherSuite\n"); + return FALSE; + } + + for (i = 0; i < prBssRsnInfo->u4PairwiseKeyCipherSuiteCount; + i++) { + if ((prAdapter->rWifiVar.rConnSettings. + rRsnInfo.au4PairwiseKeyCipherSuite[0] + & 0x000000FF) == + GET_SELECTOR_TYPE( + prBssRsnInfo->au4PairwiseKeyCipherSuite[i])) { + break; + } else if (i == + prBssRsnInfo->u4PairwiseKeyCipherSuiteCount - 1) { + DBGLOG(RSN, WARN, "Break by PairwiseKeyCipherSuite\n"); + return FALSE; + } + } + + if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA3_SAE) { + DBGLOG(RSN, WARN, "Don't check AuthKeyMgtSuite with SAE\n"); + return TRUE; + } + + for (i = 0; i < prBssRsnInfo->u4AuthKeyMgtSuiteCount; i++) { + if ((prAdapter->rWifiVar.rConnSettings. + rRsnInfo.au4AuthKeyMgtSuite[0] + & 0x000000FF) == + GET_SELECTOR_TYPE( + prBssRsnInfo->au4AuthKeyMgtSuite[i])) { + break; + } else if (i == prBssRsnInfo->u4AuthKeyMgtSuiteCount - 1) { + DBGLOG(RSN, WARN, "Break by AuthKeyMgtSuite\n"); + return FALSE; + } + } + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* +* \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 refer to wpa_supplicant wpa_key_mgmt_wpa + */ + +uint8_t rsnKeyMgmtWpa(IN P_ADAPTER_T prAdapter, + ENUM_PARAM_AUTH_MODE_T eAuthMode) +{ + uint32_t i; + + return eAuthMode == AUTH_MODE_WPA2 || + eAuthMode == AUTH_MODE_WPA2_PSK || + eAuthMode == AUTH_MODE_WPA2_FT_PSK || + eAuthMode == AUTH_MODE_WPA2_FT || + eAuthMode == AUTH_MODE_WPA3_SAE || + eAuthMode == AUTH_MODE_WPA3_OWE || + rsnSearchAKMSuite(prAdapter, RSN_CIPHER_SUITE_OWE, &i) || + rsnSearchAKMSuite(prAdapter, RSN_CIPHER_SUITE_SAE, &i); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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_PARAM_AUTH_MODE_T eAuthMode; + 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; + eAuthMode = prAdapter->rWifiVar.rConnSettings.eAuthMode; + +#if CFG_SUPPORT_WPS + fgIsWpsActive = kalWSCGetActiveState(prAdapter->prGlueInfo); + + /* CR1640, disable the AP select privacy check */ + if (fgIsWpsActive && + (eAuthMode < AUTH_MODE_WPA) && + (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_INFRA)) { + DBGLOG(RSN, TRACE, "-- Skip the Protected BSS check\n"); + return TRUE; + } +#endif + + /* Protection is not required in this BSS. */ + if ((prBss->u2CapInfo & CAP_INFO_PRIVACY) == 0) { + + if (secEnabledInAis(prAdapter) == FALSE) { + DBGLOG(RSN, TRACE, "-- No Protected BSS\n"); + return TRUE; + } + DBGLOG(RSN, WARN, "-- Protected BSS\n"); + return FALSE; + + } + + /* Protection is required in this BSS. */ + if ((prBss->u2CapInfo & CAP_INFO_PRIVACY) != 0) { + if (secEnabledInAis(prAdapter) == FALSE) { + DBGLOG(RSN, WARN, "-- Protected BSS\n"); + return FALSE; + } + } + + if (eAuthMode == AUTH_MODE_WPA || eAuthMode == AUTH_MODE_WPA_PSK || + eAuthMode == AUTH_MODE_WPA_NONE) { + + if (prBss->fgIEWPA) { + prBssRsnInfo = &prBss->rWPAInfo; + } else { + DBGLOG(RSN, WARN, "WPA Information Element does not exist.\n"); + return FALSE; + } + } else if (rsnKeyMgmtWpa(prAdapter, eAuthMode)) { + + if (prBss->fgIERSN) { + prBssRsnInfo = &prBss->rRSNInfo; + } else { + DBGLOG(RSN, WARN, "RSN Information Element does not exist.\n"); + return FALSE; + } +#if CFG_SUPPORT_HOTSPOT_2_0 + } else if (eAuthMode == AUTH_MODE_WPA_OSEN) { + /* OSEN is mutual exclusion with RSN, so we can reuse RSN's flag and variables */ + if (prBss->fgIEOsen) { + prBssRsnInfo = &prBss->rRSNInfo; + } else { + DBGLOG(RSN, WARN, "OSEN Information Element does not exist.\n"); + return FALSE; + } +#endif + } else if (prAdapter->rWifiVar.rConnSettings.eEncStatus != ENUM_ENCRYPTION1_ENABLED) { + /* If the driver is configured to use WEP only, ignore this BSS. */ + DBGLOG(RSN, WARN, "-- Not WEP-only legacy BSS %d\n", prAdapter->rWifiVar.rConnSettings.eEncStatus); + return FALSE; + } else if (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION1_ENABLED) { + /* If the driver is configured to use WEP only, use this BSS. */ + DBGLOG(RSN, TRACE, "-- WEP-only legacy BSS, fgIERSN %d, fgIEWPA %d\n", + prBss->fgIERSN, prBss->fgIEWPA); + /* if this BSS was configured to WPA/WPA2, don't select this AP */ + return (prBss->fgIERSN || prBss->fgIEWPA) ? FALSE : TRUE; + } + + if (!rsnIsSuitableBSS(prAdapter, prBssRsnInfo)) { + DBGLOG(RSN, WARN, "RSN info check no matched, RSN Score support[%d]\n", CFG_SUPPORT_RSN_SCORE); +#if CFG_SUPPORT_RSN_SCORE + prBss->fgIsRSNSuitableBss = FALSE; + } else + prBss->fgIsRSNSuitableBss = TRUE; +#else + return FALSE; + } +#endif + 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, WARN, "Inproper encryption status %d for group-key-only BSS\n", + prAdapter->rWifiVar.rConnSettings.eEncStatus); + } +#endif + } else { + fgSuiteSupported = FALSE; + + DBGLOG(RSN, TRACE, "eEncStatus %d %d 0x%x\n", prAdapter->rWifiVar.rConnSettings.eEncStatus, + (UINT_32) prBssRsnInfo->u4PairwiseKeyCipherSuiteCount, + (UINT_32) prBssRsnInfo->au4PairwiseKeyCipherSuite[0]); + /* Select pairwise/group ciphers */ + switch (prAdapter->rWifiVar.rConnSettings.eEncStatus) { + case ENUM_ENCRYPTION3_ENABLED: + for (i = 0; i < prBssRsnInfo->u4PairwiseKeyCipherSuiteCount; i++) { + if (GET_SELECTOR_TYPE(prBssRsnInfo->au4PairwiseKeyCipherSuite[i]) + == CIPHER_SUITE_CCMP) { + u4PairwiseCipher = prBssRsnInfo->au4PairwiseKeyCipherSuite[i]; + } + } + u4GroupCipher = prBssRsnInfo->u4GroupKeyCipherSuite; + break; + + case ENUM_ENCRYPTION2_ENABLED: + for (i = 0; i < prBssRsnInfo->u4PairwiseKeyCipherSuiteCount; i++) { + if (GET_SELECTOR_TYPE(prBssRsnInfo->au4PairwiseKeyCipherSuite[i]) + == CIPHER_SUITE_TKIP) { + u4PairwiseCipher = prBssRsnInfo->au4PairwiseKeyCipherSuite[i]; + } + } + if (GET_SELECTOR_TYPE(prBssRsnInfo->u4GroupKeyCipherSuite) == CIPHER_SUITE_CCMP) + DBGLOG(RSN, WARN, "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, WARN, "Cannot join CCMP/TKIP BSS\n"); + } else { + u4GroupCipher = prBssRsnInfo->u4GroupKeyCipherSuite; + } + break; + + default: + break; + } + } + + /* Exception handler */ + /* + * If we cannot find proper pairwise and group cipher suites to join the + * BSS, do not check the supported AKM suites. + */ + if (u4PairwiseCipher == 0 || u4GroupCipher == 0) { + DBGLOG(RSN, TRACE, "Failed to select pairwise/group cipher (0x%08x/0x%08x)\n", + u4PairwiseCipher, u4GroupCipher); + return FALSE; + } +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && (eNetwotkType == NETWORK_TYPE_P2P_INDEX)) { + if (u4PairwiseCipher != RSN_CIPHER_SUITE_CCMP || + u4GroupCipher != RSN_CIPHER_SUITE_CCMP || u4AkmSuite != RSN_AKM_SUITE_PSK) { + DBGLOG(RSN, TRACE, "Failed to select pairwise/group cipher for P2P network (0x%08x/0x%08x)\n", + u4PairwiseCipher, u4GroupCipher); + return FALSE; + } + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + if (eNetwotkType == NETWORK_TYPE_BOW_INDEX) { + if (u4PairwiseCipher != RSN_CIPHER_SUITE_CCMP || + u4GroupCipher != RSN_CIPHER_SUITE_CCMP || u4AkmSuite != RSN_AKM_SUITE_PSK) { + /* Do nothing */ + } + DBGLOG(RSN, TRACE, + "Failed to select pairwise/group cipher for BT over Wi-Fi network (0x%08x/0x%08x)\n", + u4PairwiseCipher, u4GroupCipher); + return FALSE; + } +#endif + + /* Verify if selected pairwisse cipher is supported */ + fgSuiteSupported = rsnSearchSupportedCipher(prAdapter, u4PairwiseCipher, &i); + + /* Verify if selected group cipher is supported */ + if (fgSuiteSupported) + fgSuiteSupported = rsnSearchSupportedCipher(prAdapter, u4GroupCipher, &i); + + if (!fgSuiteSupported) { + DBGLOG(RSN, TRACE, "Failed to support selected pairwise/group cipher (0x%08x/0x%08x)\n", + u4PairwiseCipher, u4GroupCipher); + return FALSE; + } + + /* Select AKM */ + /* + * If the driver cannot support any authentication suites advertised in + * the given BSS, we fail to perform RSNA policy selection. + */ + /* Attempt to find any overlapping supported AKM suite. */ + if (eAuthMode == AUTH_MODE_WPA2_FT_PSK && + rsnSearchAKMSuite(prAdapter, RSN_AKM_SUITE_FT_PSK, &j)) + u4AkmSuite = RSN_AKM_SUITE_FT_PSK; + else if (eAuthMode == AUTH_MODE_WPA2_FT && + rsnSearchAKMSuite(prAdapter, RSN_AKM_SUITE_FT_802_1X, &j)) + u4AkmSuite = RSN_AKM_SUITE_FT_802_1X; + else +#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, WARN, "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)) { + if (prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection == FALSE) { + DBGLOG(RSN, TRACE, "[MFP] Skip RSN IE, No MFP Required Capability\n"); + return FALSE; + } + } + } + DBGLOG(RSN, TRACE, "fgMgmtProtection = %d\n ", prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection); + +#endif + + if (GET_SELECTOR_TYPE(u4GroupCipher) == CIPHER_SUITE_CCMP) { + prBss->ucEncLevel = 3; + } else if (GET_SELECTOR_TYPE(u4GroupCipher) == CIPHER_SUITE_TKIP) { + prBss->ucEncLevel = 2; + } else if (GET_SELECTOR_TYPE(u4GroupCipher) == CIPHER_SUITE_WEP40 || + GET_SELECTOR_TYPE(u4GroupCipher) == CIPHER_SUITE_WEP104) { + prBss->ucEncLevel = 1; + } else { + ASSERT(FALSE); + } + prBss->u4RsnSelectedPairwiseCipher = u4PairwiseCipher; + prBss->u4RsnSelectedGroupCipher = u4GroupCipher; + prBss->u4RsnSelectedAKMSuite = u4AkmSuite; + + return TRUE; + +} /* rsnPerformPolicySelection */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to generate WPA IE for beacon frame. +* +* \param[in] pucIeStartAddr Pointer to put the generated WPA IE. +* +* \return The append WPA-None IE length +* \note +* Called by: JOIN module, compose beacon IE +*/ +/*----------------------------------------------------------------------------*/ +VOID rsnGenerateWpaNoneIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + UINT_32 i; + P_WPA_INFO_ELEM_T prWpaIE; + UINT_32 u4Suite; + UINT_16 u2SuiteCount; + PUINT_8 cp, cp2; + UINT_8 ucExpendedLen = 0; + PUINT_8 pucBuffer; + ENUM_NETWORK_TYPE_INDEX_T eNetworkId; + + DEBUGFUNC("rsnGenerateWpaNoneIE"); + + ASSERT(prMsduInfo); + + if (prAdapter->rWifiVar.rConnSettings.eAuthMode != AUTH_MODE_WPA_NONE) + return; + + eNetworkId = (ENUM_NETWORK_TYPE_INDEX_T) prMsduInfo->ucNetworkType; + + if (eNetworkId != NETWORK_TYPE_AIS_INDEX) + return; + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + + ASSERT(pucBuffer); + + prWpaIE = (P_WPA_INFO_ELEM_T) (pucBuffer); + + /* Start to construct a WPA IE. */ + /* Fill the Element ID field. */ + prWpaIE->ucElemId = ELEM_ID_WPA; + + /* Fill the OUI and OUI Type fields. */ + prWpaIE->aucOui[0] = 0x00; + prWpaIE->aucOui[1] = 0x50; + prWpaIE->aucOui[2] = 0xF2; + prWpaIE->ucOuiType = VENDOR_OUI_TYPE_WPA; + + /* Fill the Version field. */ + WLAN_SET_FIELD_16(&prWpaIE->u2Version, 1); /* version 1 */ + ucExpendedLen = 6; + + /* Fill the Pairwise Key Cipher Suite List field. */ + u2SuiteCount = 0; + cp = (PUINT_8) &prWpaIE->aucPairwiseKeyCipherSuite1[0]; + + if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_CCMP, &i)) + u4Suite = WPA_CIPHER_SUITE_CCMP; + else if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_TKIP, &i)) + u4Suite = WPA_CIPHER_SUITE_TKIP; + else if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_WEP104, &i)) + u4Suite = WPA_CIPHER_SUITE_WEP104; + else if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_WEP40, &i)) + u4Suite = WPA_CIPHER_SUITE_WEP40; + else + u4Suite = WPA_CIPHER_SUITE_TKIP; + + WLAN_SET_FIELD_32(cp, u4Suite); + u2SuiteCount++; + ucExpendedLen += 4; + cp += 4; + + /* Fill the Group Key Cipher Suite field as the same in pair-wise key. */ + WLAN_SET_FIELD_32(&prWpaIE->u4GroupKeyCipherSuite, u4Suite); + ucExpendedLen += 4; + + /* Fill the Pairwise Key Cipher Suite Count field. */ + WLAN_SET_FIELD_16(&prWpaIE->u2PairwiseKeyCipherSuiteCount, u2SuiteCount); + ucExpendedLen += 2; + + cp2 = cp; + + /* Fill the Authentication and Key Management Suite List field. */ + u2SuiteCount = 0; + cp += 2; + + if (rsnSearchAKMSuite(prAdapter, WPA_AKM_SUITE_802_1X, &i)) + u4Suite = WPA_AKM_SUITE_802_1X; + else if (rsnSearchAKMSuite(prAdapter, WPA_AKM_SUITE_PSK, &i)) + u4Suite = WPA_AKM_SUITE_PSK; + else + u4Suite = WPA_AKM_SUITE_NONE; + + /* This shall be the only available value for current implementation */ + ASSERT(u4Suite == WPA_AKM_SUITE_NONE); + + WLAN_SET_FIELD_32(cp, u4Suite); + u2SuiteCount++; + ucExpendedLen += 4; + cp += 4; + + /* Fill the Authentication and Key Management Suite Count field. */ + WLAN_SET_FIELD_16(cp2, u2SuiteCount); + ucExpendedLen += 2; + + /* Fill the Length field. */ + prWpaIE->ucLength = (UINT_8) ucExpendedLen; + + /* Increment the total IE length for the Element ID and Length fields. */ + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + +} /* rsnGenerateWpaNoneIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to generate WPA IE for +* associate request frame. +* +* \param[in] prCurrentBss The Selected BSS description +* +* \retval The append WPA IE length +* +* \note +* Called by: AIS module, Associate request +*/ +/*----------------------------------------------------------------------------*/ +VOID rsnGenerateWPAIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + PUCHAR cp; + PUINT_8 pucBuffer; + ENUM_NETWORK_TYPE_INDEX_T eNetworkId; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo; + + DEBUGFUNC("rsnGenerateWPAIE"); + + ASSERT(prMsduInfo); + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + + ASSERT(pucBuffer); + + eNetworkId = (ENUM_NETWORK_TYPE_INDEX_T) prMsduInfo->ucNetworkType; + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + /* if (eNetworkId != NETWORK_TYPE_AIS_INDEX) */ + /* return; */ + +#if CFG_ENABLE_WIFI_DIRECT + if ((1 /* prCurrentBss->fgIEWPA */ && + ((prAdapter->fgIsP2PRegistered) && + (eNetworkId == NETWORK_TYPE_P2P_INDEX) && + (kalP2PGetTkipCipher(prAdapter->prGlueInfo)))) || + ((prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA) || + (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA_PSK))) { +#else + if ((1 /* prCurrentBss->fgIEWPA */ && + ((prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA) || + (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA_PSK)))) { +#endif + if (prAdapter->fgIsP2PRegistered && prP2pSpecificBssInfo && prP2pSpecificBssInfo->u2WpaIeLen != 0) { + kalMemCopy(pucBuffer, prP2pSpecificBssInfo->aucWpaIeBuffer, prP2pSpecificBssInfo->u2WpaIeLen); + prMsduInfo->u2FrameLength += prP2pSpecificBssInfo->u2WpaIeLen; + return; + } + + /* Construct a WPA IE for association request frame. */ + WPA_IE(pucBuffer)->ucElemId = ELEM_ID_WPA; + WPA_IE(pucBuffer)->ucLength = ELEM_ID_WPA_LEN_FIXED; + WPA_IE(pucBuffer)->aucOui[0] = 0x00; + WPA_IE(pucBuffer)->aucOui[1] = 0x50; + WPA_IE(pucBuffer)->aucOui[2] = 0xF2; + WPA_IE(pucBuffer)->ucOuiType = VENDOR_OUI_TYPE_WPA; + WLAN_SET_FIELD_16(&WPA_IE(pucBuffer)->u2Version, 1); + +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered && eNetworkId == NETWORK_TYPE_P2P_INDEX) { + WLAN_SET_FIELD_32(&WPA_IE(pucBuffer)->u4GroupKeyCipherSuite, WPA_CIPHER_SUITE_TKIP); + } else +#endif + WLAN_SET_FIELD_32(&WPA_IE(pucBuffer)->u4GroupKeyCipherSuite, + prAdapter->rWifiVar. + arBssInfo[NETWORK_TYPE_AIS_INDEX].u4RsnSelectedGroupCipher); + + cp = (PUCHAR) &WPA_IE(pucBuffer)->aucPairwiseKeyCipherSuite1[0]; + + WLAN_SET_FIELD_16(&WPA_IE(pucBuffer)->u2PairwiseKeyCipherSuiteCount, 1); +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered && eNetworkId == NETWORK_TYPE_P2P_INDEX) { + WLAN_SET_FIELD_32(cp, WPA_CIPHER_SUITE_TKIP); + } else +#endif + WLAN_SET_FIELD_32(cp, + prAdapter->rWifiVar. + arBssInfo[NETWORK_TYPE_AIS_INDEX].u4RsnSelectedPairwiseCipher); + cp += 4; + + WLAN_SET_FIELD_16(cp, 1); + cp += 2; +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered && eNetworkId == NETWORK_TYPE_P2P_INDEX) { + WLAN_SET_FIELD_32(cp, WPA_AKM_SUITE_PSK); + } else +#endif + WLAN_SET_FIELD_32(cp, + prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].u4RsnSelectedAKMSuite); + cp += 4; + + WPA_IE(pucBuffer)->ucLength = ELEM_ID_WPA_LEN_FIXED; + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + } + +} /* rsnGenerateWPAIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to generate RSN IE for +* associate request frame. +* +* \param[in] prMsduInfo The Selected BSS description +* +* \retval The append RSN IE length +* +* \note +* Called by: AIS module, P2P module, BOW module Associate request +*/ +/*----------------------------------------------------------------------------*/ +VOID rsnGenerateRSNIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ +#if (CFG_REFACTORY_PMKSA == 0) + UINT_32 u4Entry; +#else + P_PMKID_ENTRY_T entry = NULL; +#endif + + PUCHAR cp; + BOOLEAN fgPmkidExist = FALSE; + PUINT_8 pucBuffer; + ENUM_PARAM_AUTH_MODE_T eAuthMode; + ENUM_NETWORK_TYPE_INDEX_T eNetworkId; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("rsnGenerateRSNIE"); + + ASSERT(prMsduInfo); + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + + ASSERT(pucBuffer); + + /* Todo:: network id */ + eNetworkId = (ENUM_NETWORK_TYPE_INDEX_T) prMsduInfo->ucNetworkType; + eAuthMode = prAdapter->rWifiVar.rConnSettings.eAuthMode; + + /* for Fast Bss Transition, we reuse the RSN Element composed in userspace */ + if ((eAuthMode == AUTH_MODE_WPA2_FT || + eAuthMode == AUTH_MODE_WPA2_FT_PSK) && + prAdapter->prGlueInfo->rFtIeForTx.prRsnIE) { + authAddRSNIE(prAdapter, prMsduInfo); + return; + } + + 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 */ && + rsnKeyMgmtWpa(prAdapter, eAuthMode))) { + /* 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; + + if ((eNetworkId == NETWORK_TYPE_P2P_INDEX) && + (prAdapter->rWifiVar.arBssInfo[eNetworkId].u4RsnSelectedAKMSuite + == RSN_AKM_SUITE_SAE)) { + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = + (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + + UINT_8 i = 0; + + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + /* AKM suite count */ + WLAN_SET_FIELD_16(cp, + prP2pSpecificBssInfo->u4KeyMgtSuiteCount); + cp += 2; + + /* AKM suite */ + for (i = 0; + i < prP2pSpecificBssInfo->u4KeyMgtSuiteCount; + i++) { + DBGLOG(RSN, TRACE, "KeyMgtSuite 0x%04x\n", + prP2pSpecificBssInfo->au4KeyMgtSuite[i]); + WLAN_SET_FIELD_32(cp, + prP2pSpecificBssInfo->au4KeyMgtSuite[i]); + cp += 4; + } + + RSN_IE(pucBuffer)->ucLength += + (prP2pSpecificBssInfo->u4KeyMgtSuiteCount - 1) * 4; + } else { + 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 (kalGetRsnIeMfpCap(prAdapter->prGlueInfo) == RSN_AUTH_MFP_REQUIRED) { + /* Both MFPC and MFPR need to be set if MFP required */ + WLAN_SET_FIELD_16(cp, ELEM_WPA_CAP_MFPC | ELEM_WPA_CAP_MFPR); /* Capabilities */ + } else if (kalGetRsnIeMfpCap(prAdapter->prGlueInfo) == RSN_AUTH_MFP_OPTIONAL) { + /* Only MFPC needs to be set if MFP optional */ + WLAN_SET_FIELD_16(cp, ELEM_WPA_CAP_MFPC); /* Capabilities */ + } + } +#endif + cp += 2; + + if (eNetworkId == NETWORK_TYPE_AIS_INDEX) { + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + if (!prStaRec) { + DBGLOG(RSN, TRACE, "rsnGenerateRSNIE: prStaRec is NULL\n"); + } +#if (CFG_REFACTORY_PMKSA == 0) + else if (rsnSearchPmkidEntry(prAdapter, prStaRec->aucMacAddr, &u4Entry) && + prAdapter->rWifiVar.rAisSpecificBssInfo.arPmkidCache[u4Entry].fgPmkidExist) { + fgPmkidExist = TRUE; + + RSN_IE(pucBuffer)->ucLength += 2; /* Length of PMKID count */ + + WLAN_SET_FIELD_16(cp, 1); /* PMKID count */ + cp += 2; + DBGLOG(RSN, TRACE, + "BSSID %pM ind=%d\n", prStaRec->aucMacAddr, (UINT_32) u4Entry); + DBGLOG(RSN, INFO, "use PMKID %pM\n", + (prAdapter->rWifiVar.rAisSpecificBssInfo. + arPmkidCache[u4Entry].rBssidInfo.arPMKID)); + + RSN_IE(pucBuffer)->ucLength += sizeof(PARAM_PMKID_VALUE); /* Length of PMKID */ + kalMemCopy(cp, + (PVOID) prAdapter->rWifiVar.rAisSpecificBssInfo. + arPmkidCache[u4Entry].rBssidInfo.arPMKID, sizeof(PARAM_PMKID_VALUE)); + cp += sizeof(PARAM_PMKID_VALUE); + } +#else + else + entry = rsnSearchPmkidEntry(prAdapter, prStaRec->aucMacAddr); + + /* Fill PMKID Count and List field */ + if (entry) { + uint8_t *pmk = entry->rBssidInfo.arPMKID; + + fgPmkidExist = TRUE; + + RSN_IE(pucBuffer)->ucLength += 2; + /* Fill PMKID Count field */ + WLAN_SET_FIELD_16(cp, 1); + cp += 2; + DBGLOG(RSN, INFO, "BSSID " MACSTR + "use PMKID " PMKSTR "\n", + MAC2STR(entry->rBssidInfo.arBSSID), + pmk[0], pmk[1], pmk[2], pmk[3], pmk[4], + pmk[5], pmk[6], pmk[7], pmk[8], pmk[9], + pmk[10], pmk[11], pmk[12] + pmk[13], + pmk[14], pmk[15]); + RSN_IE(pucBuffer)->ucLength += IW_PMKID_LEN; /* Length of PMKID */ + /* Fill PMKID List field */ + kalMemCopy(cp, entry->rBssidInfo.arPMKID, + IW_PMKID_LEN); + cp += IW_PMKID_LEN; + } +#endif +#if CFG_SUPPORT_802_11W + if (prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection) { + if (!fgPmkidExist) { + /* Empty PMKID Count */ + WLAN_SET_FIELD_16(cp, 0); /* PMKID count */ + cp += 2; + RSN_IE(pucBuffer)->ucLength += 2; + } + + /* Group Management Cipher Suite */ + 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, + P_STA_RECORD_T prStaRec, PUINT_16 pu2StatusCode) +{ + + RSN_INFO_T rRsnIe; + UINT_8 i; + UINT_16 statusCode; + + ASSERT(prAdapter); + ASSERT(prIe); + ASSERT(prStaRec); + 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) +#if CFG_SUPPORT_SOFTAP_WPA3 + && (rRsnIe.au4AuthKeyMgtSuite[0] != RSN_AKM_SUITE_SAE) +#endif + )) { + DBGLOG(RSN, WARN, "RSN with invalid AKMP\n"); + *pu2StatusCode = STATUS_CODE_INVALID_AKMP; + return; + } + + DBGLOG(RSN, TRACE, "RSN with CCMP-PSK\n"); + *pu2StatusCode = WLAN_STATUS_SUCCESS; + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + /* 1st check: if already PMF connection, reject assoc req: + * error 30 ASSOC_REJECTED_TEMPORARILY + */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + *pu2StatusCode = STATUS_CODE_ASSOC_REJECTED_TEMPORARILY; + return; + } + + /* if RSN capability not exist, just return */ + if (!rRsnIe.fgRsnCapPresent) { + *pu2StatusCode = WLAN_STATUS_SUCCESS; + return; + } + + prStaRec->rPmfCfg.fgMfpc = (rRsnIe.u2RsnCap & + ELEM_WPA_CAP_MFPC) ? 1 : 0; + prStaRec->rPmfCfg.fgMfpr = (rRsnIe.u2RsnCap & + ELEM_WPA_CAP_MFPR) ? 1 : 0; + + prStaRec->rPmfCfg.fgSaeRequireMfp = FALSE; + + for (i = 0; i < rRsnIe.u4AuthKeyMgtSuiteCount; i++) { + if ((rRsnIe.au4AuthKeyMgtSuite[i] == + RSN_AKM_SUITE_802_1X_SHA256) || + (rRsnIe.au4AuthKeyMgtSuite[i] == + RSN_AKM_SUITE_PSK_SHA256)) { + DBGLOG(RSN, INFO, "STA SHA256 support\n"); + prStaRec->rPmfCfg.fgSha256 = TRUE; + break; + } else if (rRsnIe.au4AuthKeyMgtSuite[i] == + RSN_AKM_SUITE_SAE) { + DBGLOG(RSN, INFO, "STA SAE support\n"); + prStaRec->rPmfCfg.fgSaeRequireMfp = TRUE; + break; + } + } + + DBGLOG(RSN, INFO, + "STA Assoc req mfpc:%d, mfpr:%d, sha256:%d, applyPmf:%d\n", + prStaRec->rPmfCfg.fgMfpc, prStaRec->rPmfCfg.fgMfpr, + prStaRec->rPmfCfg.fgSha256, + prStaRec->rPmfCfg.fgApplyPmf); + + /* if PMF validation fail, return success as legacy association + */ + statusCode = rsnPmfCapableValidation(prAdapter, + GET_BSS_INFO_BY_INDEX(prAdapter, NETWORK_TYPE_P2P_INDEX), + prStaRec); + *pu2StatusCode = statusCode; +#endif + } + +} +#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) +{ +#if (CFG_REFACTORY_PMKSA == 0) + 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)); +#else + struct PARAM_INDICATION_EVENT authEvent; + + DEBUGFUNC("rsnGenMicErrorEvent"); + + /* Status type: Authentication Event */ + authEvent.rStatus.eStatusType = ENUM_STATUS_TYPE_AUTHENTICATION; + + /* Authentication request */ + authEvent.rAuthReq.u4Length = sizeof(PARAM_AUTH_REQUEST_T); + COPY_MAC_ADDR(authEvent.rAuthReq.arBssid, + (PVOID) prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].aucBSSID); + if (fgFlags == TRUE) + authEvent.rAuthReq.u4Flags = PARAM_AUTH_REQUEST_GROUP_ERROR; + else + authEvent.rAuthReq.u4Flags = PARAM_AUTH_REQUEST_PAIRWISE_ERROR; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID)&authEvent, + sizeof(struct PARAM_INDICATION_EVENT)); +#endif + +} /* rsnGenMicErrorEvent */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to handle TKIP MIC failures. +* +* \param[in] adapter_p Pointer to the adapter object data area. +* \param[in] prSta Pointer to the STA which occur MIC Error +* \param[in] fgErrorKeyType type of error key +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID rsnTkipHandleMICFailure(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta, IN BOOLEAN fgErrorKeyType) +{ + /* UINT_32 u4RsnaCurrentMICFailTime; */ + /* P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; */ + + DEBUGFUNC("rsnTkipHandleMICFailure"); + + ASSERT(prAdapter); +#if 1 + rsnGenMicErrorEvent(prAdapter, /* prSta, */ fgErrorKeyType); + + nicConfigPowerSaveProfile(prAdapter, NETWORK_TYPE_AIS_INDEX, Param_PowerModeCAM, FALSE); + + /* Generate authentication request event. */ + DBGLOG(RSN, INFO, "Generate TKIP MIC error event (type: 0%d)\n", fgErrorKeyType); +#else + ASSERT(prSta); + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + /* Record the MIC error occur time. */ + GET_CURRENT_SYSTIME(&u4RsnaCurrentMICFailTime); + + /* Generate authentication request event. */ + DBGLOG(RSN, INFO, "Generate TKIP MIC error event (type: 0%d)\n", fgErrorKeyType); + + /* + * If less than 60 seconds have passed since a previous TKIP MIC failure, + * disassociate from the AP and wait for 60 seconds before (re)associating + * with the same AP. + */ + if (prAisSpecBssInfo->u4RsnaLastMICFailTime != 0 && + !CHECK_FOR_TIMEOUT(u4RsnaCurrentMICFailTime, + prAisSpecBssInfo->u4RsnaLastMICFailTime, SEC_TO_SYSTIME(TKIP_COUNTERMEASURE_SEC))) { + /* + * If less than 60 seconds expired since last MIC error, we have to + * block traffic. + */ + + DBGLOG(RSN, INFO, "Start blocking traffic!\n"); + rsnGenMicErrorEvent(prAdapter, /* prSta, */ fgErrorKeyType); + + secFsmEventStartCounterMeasure(prAdapter, prSta); + } else { + rsnGenMicErrorEvent(prAdapter, /* prSta, */ fgErrorKeyType); + DBGLOG(RSN, INFO, "First TKIP MIC error!\n"); + } + + COPY_SYSTIME(prAisSpecBssInfo->u4RsnaLastMICFailTime, u4RsnaCurrentMICFailTime); +#endif +} /* rsnTkipHandleMICFailure */ +#if (CFG_REFACTORY_PMKSA == 0) +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to select a list of BSSID from +* the scan results for PMKID candidate list. +* +* \param[in] prBssDesc the BSS Desc at scan result list +* \param[out] pu4CandidateCount Pointer to the number of selected candidates. +* It is set to zero if no BSSID matches our requirement. +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID rsnSelectPmkidCandidateList(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + P_AIS_BSS_INFO_T prAisBssInfo; + + DEBUGFUNC("rsnSelectPmkidCandidateList"); + + ASSERT(prBssDesc); + + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + prAisBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + + /* Search a BSS with the same SSID from the given BSS description set. */ + /* DBGLOG(RSN, TRACE, ("Check scan result [%pM]\n", */ + /* prBssDesc->aucBSSID)); */ + + if (UNEQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, + prConnSettings->aucSSID, prConnSettings->ucSSIDLen)) { + DBGLOG(RSN, TRACE, "-- SSID not matched\n"); + return; + } +#if 0 + if ((prBssDesc->u2BSSBasicRateSet & + ~(rPhyAttributes[prAisBssInfo->ePhyType].u2SupportedRateSet)) || prBssDesc->fgIsUnknownBssBasicRate) { + DBGLOG(RSN, TRACE, "-- Rate set not matched\n"); + return; + } + + if (prBssDesc->u4RsnSelectedPairwiseCipher != prAisBssInfo->u4RsnSelectedPairwiseCipher || + prBssDesc->u4RsnSelectedGroupCipher != prAisBssInfo->u4RsnSelectedGroupCipher || + prBssDesc->u4RsnSelectedAKMSuite != prAisBssInfo->u4RsnSelectedAKMSuite) { + DBGLOG(RSN, TRACE, "-- Encrypt status not matched for PMKID\n"); + return; + } +#endif + + rsnUpdatePmkidCandidateList(prAdapter, prBssDesc); + +} /* rsnSelectPmkidCandidateList */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to select a list of BSSID from +* the scan results for PMKID candidate list. +* +* \param[in] prBssDesc the BSS DESC at scan result list +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID rsnUpdatePmkidCandidateList(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) +{ + UINT_32 i; + P_CONNECTION_SETTINGS_T prConnSettings; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + DEBUGFUNC("rsnUpdatePmkidCandidateList"); + + ASSERT(prBssDesc); + + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + if (UNEQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, + prConnSettings->aucSSID, prConnSettings->ucSSIDLen)) { + DBGLOG(RSN, TRACE, "-- SSID not matched\n"); + return; + } + + for (i = 0; i < CFG_MAX_PMKID_CACHE; i++) { + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisSpecBssInfo->arPmkidCandicate[i].aucBssid)) + return; + } + + /* + * If the number of selected BSSID exceed MAX_NUM_PMKID_CACHE(16), + * then we only store MAX_NUM_PMKID_CACHE(16) in PMKID cache + */ + if ((prAisSpecBssInfo->u4PmkidCandicateCount + 1) > CFG_MAX_PMKID_CACHE) + prAisSpecBssInfo->u4PmkidCandicateCount--; + + i = prAisSpecBssInfo->u4PmkidCandicateCount; + + COPY_MAC_ADDR((PVOID) prAisSpecBssInfo->arPmkidCandicate[i].aucBssid, (PVOID) prBssDesc->aucBSSID); + + if (prBssDesc->u2RsnCap & MASK_RSNIE_CAP_PREAUTH) { + prAisSpecBssInfo->arPmkidCandicate[i].u4PreAuthFlags = 1; + DBGLOG(RSN, TRACE, "Add %pM with pre-auth to candidate list\n", + (prAisSpecBssInfo->arPmkidCandicate[i].aucBssid)); + } else { + prAisSpecBssInfo->arPmkidCandicate[i].u4PreAuthFlags = 0; + DBGLOG(RSN, TRACE, "Add %pM without pre-auth to candidate list\n", + (prAisSpecBssInfo->arPmkidCandicate[i].aucBssid)); + } + + prAisSpecBssInfo->u4PmkidCandicateCount++; + +} /* rsnUpdatePmkidCandidateList */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to search the desired entry in +* PMKID cache according to the BSSID +* +* \param[in] pucBssid Pointer to the BSSID +* \param[out] pu4EntryIndex Pointer to place the found entry index +* +* \retval TRUE, if found one entry for specified BSSID +* \retval FALSE, if not found +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rsnSearchPmkidEntry(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBssid, OUT PUINT_32 pu4EntryIndex) +{ + UINT_32 i; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + DEBUGFUNC("rsnSearchPmkidEntry"); + + ASSERT(pucBssid); + ASSERT(pu4EntryIndex); + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + if (prAisSpecBssInfo->u4PmkidCacheCount > CFG_MAX_PMKID_CACHE) + return FALSE; + + ASSERT(prAisSpecBssInfo->u4PmkidCacheCount <= CFG_MAX_PMKID_CACHE); + + /* Search for desired BSSID */ + for (i = 0; i < prAisSpecBssInfo->u4PmkidCacheCount; i++) { + if (!kalMemCmp(prAisSpecBssInfo->arPmkidCache[i].rBssidInfo.arBSSID, pucBssid, MAC_ADDR_LEN)) + break; + } + + /* If desired BSSID is found, then set the PMKID */ + if (i < prAisSpecBssInfo->u4PmkidCacheCount) { + *pu4EntryIndex = i; + + return TRUE; + } + + return FALSE; +} /* rsnSearchPmkidEntry */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to check if there is difference +* between PMKID candicate list and PMKID cache. If there +* is new candicate that no cache entry is available, then +* add a new entry for the new candicate in the PMKID cache +* and set the PMKID indication flag to TRUE. +* +* \retval TRUE, if new member in the PMKID candicate list +* \retval FALSe, if no new member in the PMKID candicate list +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rsnCheckPmkidCandicate(IN P_ADAPTER_T prAdapter) +{ + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + UINT_32 i; /* Index for PMKID candicate */ + UINT_32 j; /* Indix for PMKID cache */ + BOOLEAN status = FALSE; + + DEBUGFUNC("rsnCheckPmkidCandicate"); + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + /* Check for each candicate */ + for (i = 0; i < prAisSpecBssInfo->u4PmkidCandicateCount; i++) { + for (j = 0; j < prAisSpecBssInfo->u4PmkidCacheCount; j++) { + if (!kalMemCmp(prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arBSSID, + prAisSpecBssInfo->arPmkidCandicate[i].aucBssid, MAC_ADDR_LEN)) { + /* + * DBGLOG(RSN, TRACE, ("%pM at PMKID cache!!\n", + * (prAisSpecBssInfo->arPmkidCandicate[i].aucBssid))); + */ + break; + } + } + + /* No entry found in PMKID cache for the candicate, add new one */ + if (j == prAisSpecBssInfo->u4PmkidCacheCount + && prAisSpecBssInfo->u4PmkidCacheCount < CFG_MAX_PMKID_CACHE) { + DBGLOG(RSN, TRACE, + "Add %pM to PMKID cache!!\n", + (prAisSpecBssInfo->arPmkidCandicate[i].aucBssid)); + kalMemCopy((PVOID) prAisSpecBssInfo-> + arPmkidCache[prAisSpecBssInfo->u4PmkidCacheCount].rBssidInfo.arBSSID, + (PVOID) prAisSpecBssInfo->arPmkidCandicate[i].aucBssid, MAC_ADDR_LEN); + prAisSpecBssInfo->arPmkidCache[prAisSpecBssInfo->u4PmkidCacheCount].fgPmkidExist = FALSE; + prAisSpecBssInfo->u4PmkidCacheCount++; + + status = TRUE; + } + } + + return status; +} /* rsnCheckPmkidCandicate */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to wait a duration to indicate the pre-auth AP candicate +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rsnIndicatePmkidCand(IN P_ADAPTER_T prAdapter, IN ULONG ulParm) +{ + DBGLOG(RSN, EVENT, "Security - Time to indicate the PMKID cand.\n"); + + /* + * If the authentication mode is WPA2 and indication PMKID flag + * is available, then we indicate the PMKID candidate list to NDIS and + * clear the flag, indicatePMKID + */ + + if (prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].eConnectionState == PARAM_MEDIA_STATE_CONNECTED && + prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) { + rsnGeneratePmkidIndication(prAdapter); + } + +} /* end of rsnIndicatePmkidCand() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to check the BSS Desc at scan result +* with pre-auth cap at wpa2 mode. If there +* is candicate that no cache entry is available, then +* add a new entry for the new candicate in the PMKID cache +* and set the PMKID indication flag to TRUE. +* +* \param[in] prBss The BSS Desc at scan result +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rsnCheckPmkidCache(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBss) +{ + P_AIS_BSS_INFO_T prAisBssInfo; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + + DEBUGFUNC("rsnCheckPmkidCandicate"); + + ASSERT(prBss); + + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + prAisBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + if ((prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) && + (prConnSettings->eAuthMode == AUTH_MODE_WPA2)) { + rsnSelectPmkidCandidateList(prAdapter, prBss); + + /* + * Set indication flag of PMKID to TRUE, and then connHandleNetworkConnection() + * will indicate this later + */ + if (rsnCheckPmkidCandicate(prAdapter)) { + DBGLOG(RSN, TRACE, "Prepare a timer to indicate candidate PMKID Candidate\n"); + cnmTimerStopTimer(prAdapter, &prAisSpecBssInfo->rPreauthenticationTimer); + cnmTimerStartTimer(prAdapter, &prAisSpecBssInfo->rPreauthenticationTimer, + SEC_TO_MSEC(WAIT_TIME_IND_PMKID_CANDICATE_SEC)); + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to generate an PMKID candidate list +* indication to NDIS. +* +* \param[in] prAdapter Pointer to the adapter object data area. +* \param[in] u4Flags PMKID candidate list event: +* PARAM_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID rsnGeneratePmkidIndication(IN P_ADAPTER_T prAdapter) +{ + P_PARAM_STATUS_INDICATION_T prStatusEvent; + P_PARAM_PMKID_CANDIDATE_LIST_T prPmkidEvent; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecificBssInfo; + UINT_8 i, j = 0, count = 0; + UINT_32 u4LenOfUsedBuffer; + + DEBUGFUNC("rsnGeneratePmkidIndication"); + + ASSERT(prAdapter); + + prStatusEvent = (P_PARAM_STATUS_INDICATION_T) prAdapter->aucIndicationEventBuffer; + + /* Status type: PMKID Candidatelist Event */ + prStatusEvent->eStatusType = ENUM_STATUS_TYPE_CANDIDATE_LIST; + ASSERT(prStatusEvent); + + prPmkidEvent = (P_PARAM_PMKID_CANDIDATE_LIST_T) (&prStatusEvent->eStatusType + 1); + ASSERT(prPmkidEvent); + + prAisSpecificBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + ASSERT(prAisSpecificBssInfo); + + for (i = 0; i < prAisSpecificBssInfo->u4PmkidCandicateCount; i++) { + for (j = 0; j < prAisSpecificBssInfo->u4PmkidCacheCount; j++) { + if (EQUAL_MAC_ADDR(prAisSpecificBssInfo->arPmkidCache[j].rBssidInfo.arBSSID, + prAisSpecificBssInfo->arPmkidCandicate[i].aucBssid) && + (prAisSpecificBssInfo->arPmkidCache[j].fgPmkidExist == TRUE)) { + break; + } + } + if (count >= CFG_MAX_PMKID_CACHE) + break; + + if (j == prAisSpecificBssInfo->u4PmkidCacheCount) { + kalMemCopy((PVOID) prPmkidEvent->arCandidateList[count].arBSSID, + (PVOID) prAisSpecificBssInfo->arPmkidCandicate[i].aucBssid, PARAM_MAC_ADDR_LEN); + prPmkidEvent->arCandidateList[count].u4Flags = + prAisSpecificBssInfo->arPmkidCandicate[i].u4PreAuthFlags; + DBGLOG(RSN, TRACE, "%pM %d\n", (prPmkidEvent->arCandidateList[count].arBSSID), + (UINT_32) prPmkidEvent->arCandidateList[count].u4Flags); + count++; + } + } + + /* PMKID Candidate List */ + prPmkidEvent->u4Version = 1; + prPmkidEvent->u4NumCandidates = count; + DBGLOG(RSN, TRACE, "rsnGeneratePmkidIndication #%d\n", (UINT_32) prPmkidEvent->u4NumCandidates); + u4LenOfUsedBuffer = sizeof(ENUM_STATUS_TYPE_T) + (2 * sizeof(UINT_32)) + + (count * sizeof(PARAM_PMKID_CANDIDATE_T)); + /* dumpMemory8((PUINT_8)prAdapter->aucIndicationEventBuffer, u4LenOfUsedBuffer); */ + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID) prAdapter->aucIndicationEventBuffer, u4LenOfUsedBuffer); + +} /* rsnGeneratePmkidIndication */ +#else +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +P_PMKID_ENTRY_T rsnSearchPmkidEntry(IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBssid) +{ + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + P_PMKID_ENTRY_T entry; + P_LINK_T cache; + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + cache = &prAisSpecBssInfo->rPmkidCache; + + LINK_FOR_EACH_ENTRY(entry, cache, rLinkEntry, PMKID_ENTRY_T) { + if (EQUAL_MAC_ADDR(entry->rBssidInfo.arBSSID, pucBssid)) + return entry; + } + + return NULL; +} /* rsnSearchPmkidEntry */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to check the BSS Desc at scan result + * with pre-auth cap at wpa2 mode. If there is no cache entry, + * notify the PMKID indication. + * + * \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_BSS_INFO_T prAisBssInfo; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + + if (!prBss) + return; + + 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) && + EQUAL_SSID(prBss->aucSSID, prBss->ucSSIDLen, + prConnSettings->aucSSID, prConnSettings->ucSSIDLen) && + UNEQUAL_MAC_ADDR(prBss->aucBSSID, prAisBssInfo->aucBSSID) && + !rsnSearchPmkidEntry(prAdapter, prBss->aucBSSID)) { + PARAM_PMKID_CANDIDATE_T candidate; + + COPY_MAC_ADDR(candidate.arBSSID, prBss->aucBSSID); + candidate.u4Flags = prBss->u2RsnCap & MASK_RSNIE_CAP_PREAUTH; + rsnGeneratePmkidIndication(prAdapter, &candidate); + + DBGLOG(RSN, TRACE, "Generate " MACSTR + " with preauth %d to pmkid candidate list\n", + MAC2STR(prBss->aucBSSID), candidate.u4Flags); + } +} /* rsnCheckPmkidCache */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to add/update pmkid. + * + * \param[in] prPmkid The new pmkid + * + * \return status + */ +/*----------------------------------------------------------------------------*/ +uint32_t rsnSetPmkid(IN P_ADAPTER_T prAdapter, + IN P_PARAM_PMKID_T prPmkid) +{ + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + P_PMKID_ENTRY_T entry; + P_LINK_T cache; + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + cache = &prAisSpecBssInfo->rPmkidCache; + + entry = rsnSearchPmkidEntry(prAdapter, prPmkid->arBSSID); + if (!entry) { + entry = kalMemAlloc(sizeof(PMKID_ENTRY_T), VIR_MEM_TYPE); + if (!entry) + return -ENOMEM; + LINK_INSERT_TAIL(cache, &entry->rLinkEntry); + } + + DBGLOG(RSN, INFO, + "[%d] Set " MACSTR ", total %d, PMKID " PMKSTR "\n", + prPmkid->ucBssIdx, + MAC2STR(prPmkid->arBSSID), cache->u4NumElem, + prPmkid->arPMKID[0], prPmkid->arPMKID[1], prPmkid->arPMKID[2], + prPmkid->arPMKID[3], prPmkid->arPMKID[4], prPmkid->arPMKID[5], + prPmkid->arPMKID[6], prPmkid->arPMKID[7], prPmkid->arPMKID[8], + prPmkid->arPMKID[9], prPmkid->arPMKID[10], prPmkid->arPMKID[11], + prPmkid->arPMKID[12] + prPmkid->arPMKID[13], + prPmkid->arPMKID[14], prPmkid->arPMKID[15]); + + kalMemCopy(&entry->rBssidInfo, prPmkid, sizeof(PARAM_PMKID_T)); + return WLAN_STATUS_SUCCESS; +} /* rsnSetPmkid */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to del pmkid. + * + * \param[in] prPmkid pmkid should be deleted + * + * \return status + */ +/*----------------------------------------------------------------------------*/ +uint32_t rsnDelPmkid(IN P_ADAPTER_T prAdapter, + IN P_PARAM_PMKID_T prPmkid) +{ + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + P_PMKID_ENTRY_T entry; + P_LINK_T cache; + + if (!prPmkid) + return WLAN_STATUS_INVALID_DATA; + + DBGLOG(RSN, TRACE, "[%d] Del " MACSTR " pmkid\n", + prPmkid->ucBssIdx, + MAC2STR(prPmkid->arBSSID)); + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + cache = &prAisSpecBssInfo->rPmkidCache; + entry = rsnSearchPmkidEntry(prAdapter, prPmkid->arBSSID); + if (entry) { + if (kalMemCmp(prPmkid->arPMKID, + entry->rBssidInfo.arPMKID, IW_PMKID_LEN)) { + DBGLOG(RSN, WARN, "Del " MACSTR " pmkid but mismatch\n", + MAC2STR(prPmkid->arBSSID)); + } + LINK_REMOVE_KNOWN_ENTRY(cache, entry); + kalMemFree(entry, VIR_MEM_TYPE, sizeof(PMKID_ENTRY_T)); + } + + return WLAN_STATUS_SUCCESS; +} /* rsnDelPmkid */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to delete all pmkid. + * + * \return status + */ +/*----------------------------------------------------------------------------*/ +uint32_t rsnFlushPmkid(IN P_ADAPTER_T prAdapter) +{ + AIS_SPECIFIC_BSS_INFO_T *prAisSpecBssInfo; + P_PMKID_ENTRY_T entry; + P_LINK_T cache; + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + cache = &prAisSpecBssInfo->rPmkidCache; + + DBGLOG(RSN, INFO, "Flush Pmkid total:%d\n", + cache->u4NumElem); + + while (!LINK_IS_EMPTY(cache)) { + LINK_REMOVE_HEAD(cache, entry, P_PMKID_ENTRY_T); + kalMemFree(entry, VIR_MEM_TYPE, sizeof(PMKID_ENTRY_T)); + } + return WLAN_STATUS_SUCCESS; +} /* rsnDelPmkid */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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, + IN P_PARAM_PMKID_CANDIDATE_T prCandi) +{ + struct PARAM_INDICATION_EVENT pmkidEvent; + + DEBUGFUNC("rsnGeneratePmkidIndication"); + + /* Status type: PMKID Candidatelist Event */ + pmkidEvent.rStatus.eStatusType = ENUM_STATUS_TYPE_CANDIDATE_LIST; + kalMemCopy(&pmkidEvent.rCandi, prCandi, + sizeof(PARAM_PMKID_CANDIDATE_T)); + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (void *) &pmkidEvent, + sizeof(struct PARAM_INDICATION_EVENT)); +} /* rsnGeneratePmkidIndication */ +#endif +#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) +{ + /* caution: prStaRec might be null ! */ + if (prStaRec) { + P_BSS_INFO_T prBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, + NETWORK_TYPE_P2P_INDEX); + + if (prStaRec->ucNetTypeIndex == (UINT_8) NETWORK_TYPE_AIS_INDEX) { + return prAdapter->rWifiVar.rAisSpecificBssInfo.fgBipKeyInstalled; + } else if ((prStaRec->ucNetTypeIndex == + (UINT_8) NETWORK_TYPE_P2P_INDEX) && + prBssInfo && + (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { + if (prStaRec->rPmfCfg.fgApplyPmf) + DBGLOG(RSN, INFO, "AP-STA PMF capable\n"); + return prStaRec->rPmfCfg.fgApplyPmf; + } else { + return FALSE; + } + } 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))) { + DBGLOG(RSN, INFO, "association SA Query timed out\n"); + + prBssSpecInfo->ucSaQueryTimedOut = 1; + kalMemFree(prBssSpecInfo->pucSaQueryTransId, VIR_MEM_TYPE, + prBssSpecInfo->u4SaQueryCount * ACTION_SA_QUERY_TR_ID_LEN); + prBssSpecInfo->pucSaQueryTransId = NULL; + prBssSpecInfo->u4SaQueryCount = 0; + cnmTimerStopTimer(prAdapter, &prBssSpecInfo->rSaQueryTimer); + /* Re-connect */ + DBGLOG(RSN, INFO, "DisBy11w\n"); + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + + return 1; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to start the 802.11w sa query timer. +* +* +* \note +* Called by: AIS module, Handle Rx mgmt request +*/ +/*----------------------------------------------------------------------------*/ +void rsnStartSaQueryTimer(IN P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prBssInfo; + P_AIS_SPECIFIC_BSS_INFO_T prBssSpecInfo; + P_MSDU_INFO_T prMsduInfo; + P_ACTION_SA_QUERY_FRAME prTxFrame; + UINT_16 u2PayloadLen; + PUINT_8 pucTmp = NULL; + UINT_8 ucTransId[ACTION_SA_QUERY_TR_ID_LEN]; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + ASSERT(prBssInfo); + + prBssSpecInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + ASSERT(prBssSpecInfo); + + DBGLOG(RSN, INFO, "MFP: Start Sa Query\n"); + + if (prBssInfo->prStaRecOfAP == NULL) { + DBGLOG(RSN, INFO, "MFP: unassociated AP!\n"); + return; + } + + if (prBssSpecInfo->u4SaQueryCount > 0 && rsnCheckSaQueryTimeout(prAdapter)) { + DBGLOG(RSN, INFO, "MFP: u4SaQueryCount count =%d\n", prBssSpecInfo->u4SaQueryCount); + return; + } + + prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + prTxFrame = (P_ACTION_SA_QUERY_FRAME) + ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + prTxFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + + COPY_MAC_ADDR(prTxFrame->aucDestAddr, prBssInfo->aucBSSID); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); + + prTxFrame->ucCategory = CATEGORY_SA_QUERT_ACTION; + prTxFrame->ucAction = ACTION_SA_QUERY_REQUEST; + + if (prBssSpecInfo->u4SaQueryCount == 0) + GET_CURRENT_SYSTIME(&prBssSpecInfo->u4SaQueryStart); + + if (prBssSpecInfo->u4SaQueryCount) { + pucTmp = kalMemAlloc(prBssSpecInfo->u4SaQueryCount * ACTION_SA_QUERY_TR_ID_LEN, VIR_MEM_TYPE); + if (!pucTmp) { + DBGLOG(RSN, ERROR, "MFP: Fail to alloc tmp buffer for backup sa query id\n"); + return; + } + kalMemCopy(pucTmp, prBssSpecInfo->pucSaQueryTransId, + prBssSpecInfo->u4SaQueryCount * ACTION_SA_QUERY_TR_ID_LEN); + } + + kalMemFree(prBssSpecInfo->pucSaQueryTransId, VIR_MEM_TYPE, + prBssSpecInfo->u4SaQueryCount * ACTION_SA_QUERY_TR_ID_LEN); + + ucTransId[0] = (UINT_8) (kalRandomNumber() & 0xFF); + ucTransId[1] = (UINT_8) (kalRandomNumber() & 0xFF); + + kalMemCopy(prTxFrame->ucTransId, ucTransId, ACTION_SA_QUERY_TR_ID_LEN); + + prBssSpecInfo->u4SaQueryCount++; + + prBssSpecInfo->pucSaQueryTransId = + kalMemAlloc(prBssSpecInfo->u4SaQueryCount * ACTION_SA_QUERY_TR_ID_LEN, VIR_MEM_TYPE); + if (!prBssSpecInfo->pucSaQueryTransId) { + DBGLOG(RSN, ERROR, "MFP: Fail to alloc buffer for sa query id list\n"); + if (pucTmp) + kalMemFree(pucTmp, VIR_MEM_TYPE, + ..(prBssSpecInfo->u4SaQueryCount - 1) * ACTION_SA_QUERY_TR_ID_LEN); + 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); + if (!prStaRec) + return; + + DBGLOG(RSN, INFO, "IEEE 802.11: Received SA Query Request from %pM\n", prStaRec->aucMacAddr); + + DBGLOG_MEM8(RSN, TRACE, prRxFrame->ucTransId, ACTION_SA_QUERY_TR_ID_LEN); + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_DISCONNECTED) { + DBGLOG(RSN, TRACE, "IEEE 802.11: Ignore SA Query Request from unassociated STA %pM\n", + prStaRec->aucMacAddr); + return; + } + DBGLOG(RSN, INFO, "IEEE 802.11: Sending SA Query Response to %pM\n", prStaRec->aucMacAddr); + + prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + prTxFrame = (P_ACTION_SA_QUERY_FRAME) + ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + /* SA Query always with protected */ + prTxFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + + COPY_MAC_ADDR(prTxFrame->aucDestAddr, prBssInfo->aucBSSID); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); + + prTxFrame->ucCategory = CATEGORY_SA_QUERT_ACTION; + prTxFrame->ucAction = ACTION_SA_QUERY_RESPONSE; + + kalMemCopy(prTxFrame->ucTransId, prRxFrame->ucTransId, ACTION_SA_QUERY_TR_ID_LEN); + + u2PayloadLen = 2 + ACTION_SA_QUERY_TR_ID_LEN; + + /* 4 Update information of MSDU_INFO_T */ + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; /* Management frame */ + prMsduInfo->ucStaRecIndex = prBssInfo->prStaRecOfAP->ucIndex; + prMsduInfo->ucNetworkType = prBssInfo->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->fgIsBasicRate = FALSE; + + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to process the 802.11w sa query action frame. +* +* +* \note +* Called by: AIS module, Handle Rx mgmt request +*/ +/*----------------------------------------------------------------------------*/ +void rsnSaQueryAction(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_AIS_SPECIFIC_BSS_INFO_T prBssSpecInfo; + P_ACTION_SA_QUERY_FRAME prRxFrame; + P_STA_RECORD_T prStaRec; + UINT_32 i; + + prBssSpecInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + ASSERT(prBssSpecInfo); + + prRxFrame = (P_ACTION_SA_QUERY_FRAME) prSwRfb->pvHeader; + if (!prRxFrame) + return; + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (!prStaRec) + return; + + if (prSwRfb->u2PacketLen < ACTION_SA_QUERY_TR_ID_LEN) { + DBGLOG(RSN, WARN, "IEEE 802.11: Too short SA Query Action frame (len=%u)\n", + prSwRfb->u2PacketLen); + return; + } + + if (prRxFrame->ucAction == ACTION_SA_QUERY_REQUEST) { + rsnSaQueryRequest(prAdapter, prSwRfb); + return; + } + + if (prRxFrame->ucAction != ACTION_SA_QUERY_RESPONSE) { + DBGLOG(RSN, TRACE, "IEEE 802.11: Unexpected SA Query Action %d\n", prRxFrame->ucAction); + return; + } + + DBGLOG(RSN, INFO, "IEEE 802.11: Received SA Query Response from %pM\n", prStaRec->aucMacAddr); + + DBGLOG_MEM8(RSN, INFO, 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, INFO, "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; + P_STA_RECORD_T prStaRec; + + prHifRxHdr = prSwRfb->prHifRxHdr; + + if ((HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr) == NETWORK_TYPE_AIS_INDEX) && + prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection /* Use MFP */) { + P_WLAN_MAC_MGMT_HEADER_T prMgmtFrame = (P_WLAN_MAC_MGMT_HEADER_T) prSwRfb->pvHeader; + + if (prMgmtFrame->aucDestAddr[0] & BIT(0)) + fgUnicast = FALSE; + + if (prHifRxHdr->ucReserved & CONTROL_FLAG_UC_MGMT_NO_ENC) { + DBGLOG(RSN, INFO, "RX MGT: rsnCheckRxMgmt = %d 0x%x %ld ucSubtype=%x\n", + fgUnicast, + prHifRxHdr->ucReserved, + (prHifRxHdr->ucReserved & CONTROL_FLAG_UC_MGMT_NO_ENC), ucSubtype); + /* "Dropped unprotected Robust Action frame from an MFP STA" */ + /* exclude Public Action */ + if ((prMgmtFrame->u2FrameCtrl & MASK_FC_SUBTYPE) == MAC_FRAME_ACTION) { + UINT_8 ucAction = *prSwRfb->pucRecvBuff; + + if (ucAction != CATEGORY_PUBLIC_ACTION && ucAction != CATEGORY_HT_ACTION) { + DBGLOG(RSN, INFO, "RX MGT: UnProtected Robust Action frame = %d\n", ucAction); + fgRobustAction = TRUE; + return TRUE; + } + } + if (((prMgmtFrame->u2FrameCtrl & MASK_FC_SUBTYPE) == MAC_FRAME_DISASSOC) || + ((prMgmtFrame->u2FrameCtrl & MASK_FC_SUBTYPE) == MAC_FRAME_DEAUTH)) { + P_WLAN_DISASSOC_FRAME_T prDisassocFrame = (P_WLAN_DISASSOC_FRAME_T) prSwRfb->pvHeader; + + DBGLOG(RSN, INFO, "RX MGT: UnProtected deauth/disassoc frame, reason = %d\n", + prDisassocFrame->u2ReasonCode); + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if ((prStaRec != NULL) && + (prStaRec->ucStaState > STA_STATE_1) && + fgUnicast && + (prDisassocFrame->u2ReasonCode == REASON_CODE_CLASS_2_ERR || + prDisassocFrame->u2ReasonCode == REASON_CODE_CLASS_3_ERR)) { + /* MFP test plan 5.3.3.5 */ + DBGLOG(RSN, INFO, "RX MGT: rsnStartSaQuery\n"); + rsnStartSaQuery(prAdapter); + } + return TRUE; + } + } + } + return FALSE; +} +#endif + +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE +static BOOLEAN rsnCheckWpaRsnInfo(P_BSS_INFO_T prBss, P_RSN_INFO_T prWpaRsnInfo) +{ + UINT_32 i = 0; + + if (prWpaRsnInfo->u4GroupKeyCipherSuite != prBss->u4RsnSelectedGroupCipher) { + DBGLOG(RSN, INFO, "GroupCipherSuite change, old=0x%04x, new=0x%04x\n", + prBss->u4RsnSelectedGroupCipher, prWpaRsnInfo->u4GroupKeyCipherSuite); + return TRUE; + } + for (; i < prWpaRsnInfo->u4AuthKeyMgtSuiteCount; i++) + if (prBss->u4RsnSelectedAKMSuite == prWpaRsnInfo->au4AuthKeyMgtSuite[i]) + break; + if (i == prWpaRsnInfo->u4AuthKeyMgtSuiteCount) { + DBGLOG(RSN, INFO, "KeyMgmt change, not find 0x%04x in new beacon\n", prBss->u4RsnSelectedAKMSuite); + return TRUE; + } + + for (i = 0; i < prWpaRsnInfo->u4PairwiseKeyCipherSuiteCount; i++) + if (prBss->u4RsnSelectedPairwiseCipher == prWpaRsnInfo->au4PairwiseKeyCipherSuite[i]) + break; + if (i == prWpaRsnInfo->u4PairwiseKeyCipherSuiteCount) { + DBGLOG(RSN, INFO, "Pairwise Cipher change, not find 0x%04x in new beacon\n", + prBss->u4RsnSelectedPairwiseCipher); + return TRUE; + } + + return FALSE; +} + +BOOLEAN rsnCheckSecurityModeChanged(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_BSS_DESC_T prBssDesc) +{ + ENUM_PARAM_AUTH_MODE_T eAuthMode = prAdapter->rWifiVar.rConnSettings.eAuthMode; + + switch (eAuthMode) { + case AUTH_MODE_OPEN: /* original is open system */ + case AUTH_MODE_NON_RSN_FT: + if ((prBssDesc->u2CapInfo & CAP_INFO_PRIVACY) && !prAdapter->prGlueInfo->rWpaInfo.fgPrivacyInvoke) { + DBGLOG(RSN, INFO, "security change, open->privacy\n"); + return TRUE; + } + break; + case AUTH_MODE_SHARED: /* original is WEP */ + case AUTH_MODE_AUTO_SWITCH: + if ((prBssDesc->u2CapInfo & CAP_INFO_PRIVACY) == 0) { + DBGLOG(RSN, INFO, "security change, WEP->open\n"); + return TRUE; + } else if (prBssDesc->fgIERSN || prBssDesc->fgIEWPA) { + DBGLOG(RSN, INFO, "security change, WEP->WPA/WPA2\n"); + return TRUE; + } + break; + case AUTH_MODE_WPA: /*original is WPA */ + case AUTH_MODE_WPA_PSK: + case AUTH_MODE_WPA_NONE: + if (prBssDesc->fgIEWPA) + return rsnCheckWpaRsnInfo(prBssInfo, &prBssDesc->rWPAInfo); + DBGLOG(RSN, INFO, "security change, WPA->%s\n", + prBssDesc->fgIERSN ? "WPA2" : + (prBssDesc->u2CapInfo & CAP_INFO_PRIVACY ? "WEP" : "OPEN")); + return TRUE; + case AUTH_MODE_WPA2: /*original is WPA2 */ + case AUTH_MODE_WPA2_PSK: + case AUTH_MODE_WPA2_FT: + case AUTH_MODE_WPA2_FT_PSK: + case AUTH_MODE_WPA3_SAE: + if (prBssDesc->fgIERSN) + return rsnCheckWpaRsnInfo(prBssInfo, &prBssDesc->rRSNInfo); + DBGLOG(RSN, INFO, "security change, WPA2->%s\n", + prBssDesc->fgIEWPA ? "WPA" : + (prBssDesc->u2CapInfo & CAP_INFO_PRIVACY ? "WEP" : "OPEN")); + return TRUE; + default: + DBGLOG(RSN, WARN, "unknowned eAuthMode=%d\n", eAuthMode); + break; + } + /* + * DBGLOG(RSN, INFO, ("rsnCheckSecurityModeChanged, eAuthMode=%d, u2CapInfo=0x%02x, fgIEWPA=%d, fgIERSN=%d\n", + * eAuthMode, prBssDesc->u2CapInfo, prBssDesc->fgIEWPA, prBssDesc->fgIERSN)); + */ + return FALSE; +} +#endif + +#if CFG_SUPPORT_HOTSPOT_2_0 +BOOLEAN rsnParseOsenIE(P_ADAPTER_T prAdapter, struct IE_WFA_OSEN *prInfoElem, P_RSN_INFO_T prOsenInfo) +{ + UINT_32 i; + INT_32 u4RemainRsnIeLen; + UINT_16 u2Version = 0; + 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; + + ASSERT(prOsenInfo); + + cp = ((PUINT_8)prInfoElem) + 6; + u4RemainRsnIeLen = (INT_32) prInfoElem->ucLength - 4; + do { + if (u4RemainRsnIeLen == 0) + break; + + /* Parse the Group Key Cipher Suite field. */ + if (u4RemainRsnIeLen < 4) { + DBGLOG(RSN, WARN, "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, WARN, "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, WARN, + "Fail to parse RSN IE in pairwise cipher suite list (IE len: %d, Remain %u, Cnt %d GS %x)\n", + prInfoElem->ucLength, u4RemainRsnIeLen, u2PairSuiteCount, u4GroupSuite); + 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, WARN, "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, WARN, "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, WARN, "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. */ + prOsenInfo->ucElemId = ELEM_ID_VENDOR; + + prOsenInfo->u2Version = 0; + + prOsenInfo->u4GroupKeyCipherSuite = u4GroupSuite; + + DBGLOG(RSN, TRACE, "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; + + prOsenInfo->u4PairwiseKeyCipherSuiteCount = (UINT_32) u2PairSuiteCount; + + for (i = 0; i < (UINT_32) u2PairSuiteCount; i++) { + WLAN_GET_FIELD_32(pucPairSuite, &prOsenInfo->au4PairwiseKeyCipherSuite[i]); + pucPairSuite += 4; + + DBGLOG(RSN, TRACE, "RSN: pairwise key cipher suite [%d]: %02x-%02x-%02x-%02x\n", + (UINT_8) i, (UCHAR) (prOsenInfo->au4PairwiseKeyCipherSuite[i] & 0x000000FF), + (UCHAR) ((prOsenInfo->au4PairwiseKeyCipherSuite[i] >> 8) & 0x000000FF), + (UCHAR) ((prOsenInfo->au4PairwiseKeyCipherSuite[i] >> 16) & 0x000000FF), + (UCHAR) ((prOsenInfo->au4PairwiseKeyCipherSuite[i] >> 24) & 0x000000FF)); + } + } else { + /* The information about the pairwise key cipher suites is not present. + * Use the default chipher suite for RSN: CCMP + */ + + prOsenInfo->u4PairwiseKeyCipherSuiteCount = 1; + prOsenInfo->au4PairwiseKeyCipherSuite[0] = RSN_CIPHER_SUITE_CCMP; + + DBGLOG(RSN, WARN, "No Pairwise Cipher Suite found, using default (CCMP)\n"); + } + + 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; + + prOsenInfo->u4AuthKeyMgtSuiteCount = (UINT_32) u2AuthSuiteCount; + + for (i = 0; i < (UINT_32) u2AuthSuiteCount; i++) { + WLAN_GET_FIELD_32(pucAuthSuite, &prOsenInfo->au4AuthKeyMgtSuite[i]); + pucAuthSuite += 4; + + DBGLOG(RSN, TRACE, "RSN: AKM suite [%d]: %02x-%02x-%02x-%02x\n", + (UINT_8) i, (UCHAR) (prOsenInfo->au4AuthKeyMgtSuite[i] & 0x000000FF), + (UCHAR) ((prOsenInfo->au4AuthKeyMgtSuite[i] >> 8) & 0x000000FF), + (UCHAR) ((prOsenInfo->au4AuthKeyMgtSuite[i] >> 16) & 0x000000FF), + (UCHAR) ((prOsenInfo->au4AuthKeyMgtSuite[i] >> 24) & 0x000000FF)); + } + } else { + /* The information about the authentication and key management suites + * is not present. Use the default AKM suite for RSN. + */ + prOsenInfo->u4AuthKeyMgtSuiteCount = 1; + prOsenInfo->au4AuthKeyMgtSuite[0] = RSN_AKM_SUITE_802_1X; + + DBGLOG(RSN, WARN, "No AKM found, using default (802.1X)\n"); + } + + prOsenInfo->u2RsnCap = u2Cap; +#if CFG_SUPPORT_802_11W + prOsenInfo->fgRsnCapPresent = TRUE; +#endif + DBGLOG(RSN, TRACE, "RSN cap: 0x%04x\n", prOsenInfo->u2RsnCap); + + return TRUE; +} +#endif + +UINT_32 rsnCalculateFTIELen(P_ADAPTER_T prAdapter, + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, P_STA_RECORD_T prStaRec) +{ + ENUM_PARAM_AUTH_MODE_T eAuthMode = prAdapter->rWifiVar.rConnSettings.eAuthMode; + struct FT_IES *prFtIEs = &prAdapter->prGlueInfo->rFtIeForTx; + + if (!IS_BSS_INDEX_VALID(eNetTypeIndex) || !IS_BSS_AIS(GET_BSS_INFO_BY_INDEX(prAdapter, eNetTypeIndex)) || + !prFtIEs->prFTIE || (eAuthMode != AUTH_MODE_WPA2_FT && eAuthMode != AUTH_MODE_WPA2_FT_PSK)) + return 0; + return IE_SIZE(prFtIEs->prFTIE); +} + +VOID rsnGenerateFTIE(IN P_ADAPTER_T prAdapter, IN OUT P_MSDU_INFO_T prMsduInfo) +{ + ENUM_PARAM_AUTH_MODE_T eAuthMode = prAdapter->rWifiVar.rConnSettings.eAuthMode; + struct FT_IES *prFtIEs = &prAdapter->prGlueInfo->rFtIeForTx; + PUINT_8 pucBuffer = (PUINT_8)prMsduInfo->prPacket + prMsduInfo->u2FrameLength; + UINT_32 ucFtIeSize = 0; + UINT_8 ucBssIdx = prMsduInfo->ucNetworkType; + + if (!IS_BSS_INDEX_VALID(ucBssIdx) || !IS_BSS_AIS(GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx)) || + !prFtIEs->prFTIE || (eAuthMode != AUTH_MODE_WPA2_FT && eAuthMode != AUTH_MODE_WPA2_FT_PSK)) + return; + ucFtIeSize = IE_SIZE(prFtIEs->prFTIE); + prMsduInfo->u2FrameLength += ucFtIeSize; + kalMemCopy(pucBuffer, prFtIEs->prFTIE, ucFtIeSize); +} + +#if CFG_SUPPORT_802_11W +/* AP PMF */ +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to validate setting +* if PMF connection capable or not +* If AP MFPC=1, and STA MFPC=1, we let this as PMF connection +* +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +UINT_16 rsnPmfCapableValidation(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, IN P_STA_RECORD_T prStaRec) +{ + BOOLEAN selfMfpc, selfMfpr, peerMfpc, peerMfpr; + + selfMfpc = prBssInfo->rApPmfCfg.fgMfpc; + selfMfpr = prBssInfo->rApPmfCfg.fgMfpr; + peerMfpc = prStaRec->rPmfCfg.fgMfpc; + peerMfpr = prStaRec->rPmfCfg.fgMfpr; + + DBGLOG(RSN, INFO, "AP mfpc:%d, mfpr:%d / STA mfpc:%d, mfpr:%d\n", + selfMfpc, selfMfpr, peerMfpc, peerMfpr); + + if ((selfMfpc == TRUE) && (peerMfpc == FALSE)) { + if ((selfMfpr == TRUE) && (peerMfpr == FALSE)) { + DBGLOG(RSN, ERROR, "PMF policy violation for case 4\n"); + return STATUS_CODE_ROBUST_MGMT_FRAME_POLICY_VIOLATION; + } + + if (peerMfpr == TRUE) { + DBGLOG(RSN, ERROR, "PMF policy violation for case 7\n"); + return STATUS_CODE_ROBUST_MGMT_FRAME_POLICY_VIOLATION; + } + + if ((prBssInfo->u4RsnSelectedAKMSuite == + RSN_AKM_SUITE_SAE) && + prStaRec->rPmfCfg.fgSaeRequireMfp) { + DBGLOG(RSN, ERROR, + "PMF policy violation for case sae_require_mfp\n"); + return STATUS_CODE_ROBUST_MGMT_FRAME_POLICY_VIOLATION; + } + } + + if ((selfMfpc == TRUE) && (peerMfpc == TRUE)) { + DBGLOG(RSN, ERROR, "PMF Connection\n"); + prStaRec->rPmfCfg.fgApplyPmf = TRUE; + } + + return STATUS_CODE_SUCCESSFUL; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to generate TIMEOUT INTERVAL IE for +* association resp +* Add Timeout interval IE (56) when PMF invalid association +* +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rsnPmfGenerateTimeoutIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + IE_TIMEOUT_INTERVAL_T *prTimeout; + P_STA_RECORD_T prStaRec = NULL; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (!prStaRec) + return; + + prTimeout = (IE_TIMEOUT_INTERVAL_T *) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + + /* only when PMF connection, and association error code is 30 */ + if ((rsnCheckBipKeyInstalled(prAdapter, prStaRec) == TRUE) && + (prStaRec->u2StatusCode == STATUS_CODE_ASSOC_REJECTED_TEMPORARILY)) { + + DBGLOG(RSN, INFO, "rsnPmfGenerateTimeoutIE TRUE\n"); + prTimeout->ucId = ELEM_ID_TIMEOUT_INTERVAL; + prTimeout->ucLength = ELEM_MAX_LEN_TIMEOUT_IE; + prTimeout->ucType = IE_TIMEOUT_INTERVAL_TYPE_ASSOC_COMEBACK; + prTimeout->u4Value = 1<<10; + prMsduInfo->u2FrameLength += IE_SIZE(prTimeout); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to check the Sa query timeout. +* check if total retry time is greater than 1000ms +* +* \retval 1: retry max timeout. 0: not timeout +* \note +* Called by: AAA module, Handle by Sa Query timeout +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 rsnApCheckSaQueryTimeout(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + P_BSS_INFO_T prBssInfo; + UINT_32 now; + + GET_CURRENT_SYSTIME(&now); + + if (CHECK_FOR_TIMEOUT(now, prStaRec->rPmfCfg.u4SAQueryStart, + TU_TO_MSEC(1000))) { + DBGLOG(RSN, INFO, "association SA Query timed out\n"); + + /* XXX PMF TODO how to report STA REC disconnect?? */ + /* when SAQ retry count timeout, clear this STA */ + prStaRec->rPmfCfg.ucSAQueryTimedOut = 1; + prStaRec->rPmfCfg.u2TransactionID = 0; + prStaRec->rPmfCfg.u4SAQueryCount = 0; + cnmTimerStopTimer(prAdapter, &prStaRec->rPmfCfg.rSAQueryTimer); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, NETWORK_TYPE_P2P_INDEX); + + /* refer to p2pRoleFsmRunEventRxDeauthentication*/ + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + bssRemoveStaRecFromClientList(prAdapter, + prBssInfo, prStaRec); + /* Indicate disconnect to Host. */ + p2pFuncDisconnect(prAdapter, prStaRec, FALSE, 0); + /* Deactive BSS if PWR is IDLE and no peer */ + if (IS_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_P2P_INDEX) && + (prBssInfo->rStaRecOfClientList.u4NumElem == 0)) { + /* All Peer disconnected !! Stop BSS now!! */ + p2pFuncDeauthComplete(prAdapter, prBssInfo); + } + } + + return 1; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to start the 802.11w sa query timer. +* This routine is triggered every 201ms, and every time enter function, check +max timeout +* +* \note +* Called by: AAA module, Handle TX SAQ request +*/ +/*----------------------------------------------------------------------------*/ +void rsnApStartSaQueryTimer(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T + prStaRec, IN ULONG ulParamPtr) +{ + P_BSS_INFO_T prBssInfo; + P_MSDU_INFO_T prMsduInfo; + P_ACTION_SA_QUERY_FRAME prTxFrame; + UINT_16 u2PayloadLen; + + ASSERT(prStaRec); + + DBGLOG(RSN, INFO, "MFP: AP Start Sa Query timer\n"); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, NETWORK_TYPE_P2P_INDEX); + + if (prStaRec->rPmfCfg.u4SAQueryCount > 0 && + rsnApCheckSaQueryTimeout(prAdapter, prStaRec)) { + DBGLOG(RSN, INFO, "MFP: retry max timeout, u4SaQueryCount count =%u\n", + prStaRec->rPmfCfg.u4SAQueryCount); + return; + } + + prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, + MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + prTxFrame = (P_ACTION_SA_QUERY_FRAME) + ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) + prTxFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + COPY_MAC_ADDR(prTxFrame->aucDestAddr, prStaRec->aucMacAddr); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucBSSID); + COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); + + prTxFrame->ucCategory = CATEGORY_SA_QUERT_ACTION; + prTxFrame->ucAction = ACTION_SA_QUERY_REQUEST; + + if (prStaRec->rPmfCfg.u4SAQueryCount == 0) + GET_CURRENT_SYSTIME(&prStaRec->rPmfCfg.u4SAQueryStart); + + /* if retry, transcation id ++ */ + if (prStaRec->rPmfCfg.u4SAQueryCount) { + prStaRec->rPmfCfg.u2TransactionID++; + } else { + /* if first SAQ request, random pick transaction id */ + prStaRec->rPmfCfg.u2TransactionID = (UINT_16) (kalRandomNumber() & 0xFFFF); + } + + DBGLOG(RSN, INFO, "SAQ transaction id:%d\n", + prStaRec->rPmfCfg.u2TransactionID); + + /* trnsform U16 to U8 array */ + prTxFrame->ucTransId[0] = ((prStaRec->rPmfCfg.u2TransactionID & 0xff00) >> 8); + prTxFrame->ucTransId[1] = ((prStaRec->rPmfCfg.u2TransactionID & 0x00ff) >> 0); + + prStaRec->rPmfCfg.u4SAQueryCount++; + + u2PayloadLen = 2 + ACTION_SA_QUERY_TR_ID_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 = NULL; + prMsduInfo->fgIsBasicRate = TRUE; + + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(RSN, INFO, "SAQ Set MSDU_OPT_PROTECTED_FRAME\n"); + nicTxConfigPktOption(prMsduInfo, + MSDU_OPT_PROTECTED_FRAME, TRUE); + } + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + DBGLOG(RSN, INFO, "AP Set SA Query timer %u (%d Tu)\n", + prStaRec->rPmfCfg.u4SAQueryCount, 201); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rPmfCfg.rSAQueryTimer, TU_TO_MSEC(201)); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to start the 802.11w TX SA query. +* +* +* \note +* Called by: AAA module, Handle Tx action frame request +*/ +/*----------------------------------------------------------------------------*/ +void rsnApStartSaQuery(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + ASSERT(prStaRec); + + DBGLOG(RSN, INFO, "rsnApStartSaQuery\n"); + + if (prStaRec) { + cnmTimerStopTimer(prAdapter, &prStaRec->rPmfCfg.rSAQueryTimer); + cnmTimerInitTimer(prAdapter, &prStaRec->rPmfCfg.rSAQueryTimer, + (PFN_MGMT_TIMEOUT_FUNC)rsnApStartSaQueryTimer, (ULONG) prStaRec); + } + + if (prStaRec->rPmfCfg.u4SAQueryCount == 0) + rsnApStartSaQueryTimer(prAdapter, prStaRec, (ULONG) NULL); +} + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to stop the 802.11w SA query. +* +* +* \note +* Called by: AAA module, stop TX SAQ if receive correct SAQ response +*/ +/*----------------------------------------------------------------------------*/ +void rsnApStopSaQuery(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + ASSERT(prStaRec); + + cnmTimerStopTimer(prAdapter, &prStaRec->rPmfCfg.rSAQueryTimer); + prStaRec->rPmfCfg.u2TransactionID = 0; + prStaRec->rPmfCfg.u4SAQueryCount = 0; + prStaRec->rPmfCfg.ucSAQueryTimedOut = 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to process the 802.11w sa query action frame. +* +* +* \note +* Called by: AAA module, Handle Rx action request +*/ +/*----------------------------------------------------------------------------*/ +void rsnApSaQueryRequest(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; + + if (!prSwRfb) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (!prStaRec) /* Todo:: for not AIS check */ + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, NETWORK_TYPE_P2P_INDEX); + ASSERT(prBssInfo); + + prRxFrame = (P_ACTION_SA_QUERY_FRAME) prSwRfb->pvHeader; + if (!prRxFrame) + return; + + DBGLOG(RSN, INFO, + "IEEE 802.11: AP Received SA Query Request from " MACSTR "\n", + MAC2STR(prStaRec->aucMacAddr)); + + DBGLOG_MEM8(RSN, INFO, prRxFrame->ucTransId, ACTION_SA_QUERY_TR_ID_LEN); + + if (!rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(RSN, INFO, "IEEE 802.11: AP Ignore SA Query Request non-PMF STA " + MACSTR "\n", MAC2STR(prStaRec->aucMacAddr)); + return; + } + + DBGLOG(RSN, INFO, + "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; + + /* drop cipher mismatch */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + P_HIF_RX_HEADER_T prHifRxHdr = prSwRfb->prHifRxHdr; + + if (prHifRxHdr->ucReserved & CONTROL_FLAG_UC_MGMT_NO_ENC) { + /* if cipher mismatch, or incorrect encrypt, just drop */ + DBGLOG(RSN, ERROR, "drop SAQ req CM/CLM=1\n"); + return; + } + } + + prTxFrame = (P_ACTION_SA_QUERY_FRAME) + ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + prTxFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + DBGLOG(RSN, INFO, "AP SAQ resp set FC PF bit\n"); + } + COPY_MAC_ADDR(prTxFrame->aucDestAddr, prStaRec->aucMacAddr); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucBSSID); + 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 <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 = NULL; + prMsduInfo->fgIsBasicRate = TRUE; + + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(RSN, INFO, "AP SAQ resp set MSDU_OPT_PROTECTED_FRAME\n"); + nicTxConfigPktOption(prMsduInfo, + MSDU_OPT_PROTECTED_FRAME, TRUE); + } + + /* 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: AAA module, Handle Rx action request +*/ +/*----------------------------------------------------------------------------*/ +void rsnApSaQueryAction(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_ACTION_SA_QUERY_FRAME prRxFrame; + P_STA_RECORD_T prStaRec; + UINT_16 u2SwapTrID; + + prRxFrame = (P_ACTION_SA_QUERY_FRAME) prSwRfb->pvHeader; + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prStaRec == NULL) { + DBGLOG(RSN, INFO, "rsnApSaQueryAction: prStaRec is NULL"); + return; + } + + DBGLOG(RSN, TRACE, + "AP PMF SAQ action enter from " MACSTR "\n", + MAC2STR(prStaRec->aucMacAddr)); + if (prSwRfb->u2PacketLen < ACTION_SA_QUERY_TR_ID_LEN) { + DBGLOG(RSN, INFO, "IEEE 802.11: Too short SA Query Action frame (len=%lu)\n", + (unsigned long)prSwRfb->u2PacketLen); + return; + } + + if (prRxFrame->ucAction == ACTION_SA_QUERY_REQUEST) { + rsnApSaQueryRequest(prAdapter, prSwRfb); + return; + } + + if (prRxFrame->ucAction != ACTION_SA_QUERY_RESPONSE) { + DBGLOG(RSN, INFO, "IEEE 802.11: Unexpected SA Query Action %d\n", + prRxFrame->ucAction); + return; + } + + DBGLOG(RSN, INFO, + "IEEE 802.11: Received SA Query Response from " MACSTR "\n", + MAC2STR(prStaRec->aucMacAddr)); + + DBGLOG_MEM8(RSN, INFO, prRxFrame->ucTransId, ACTION_SA_QUERY_TR_ID_LEN); + + /* MLME-SAQuery.confirm */ + /* transform to network byte order */ + DBGLOG(RSN, TRACE, + "IEEE 802.11: prStaRec->rPmfCfg.u2TransactionID: %d\n", + prStaRec->rPmfCfg.u2TransactionID); + u2SwapTrID = htons(prStaRec->rPmfCfg.u2TransactionID); + DBGLOG(RSN, TRACE, + "IEEE 802.11: u2SwapTrID: %d\n", + u2SwapTrID); + if (kalMemCmp((UINT_8 *)&u2SwapTrID, prRxFrame->ucTransId, + ACTION_SA_QUERY_TR_ID_LEN) == 0) { + DBGLOG(RSN, INFO, "AP Reply to SA Query received\n"); + rsnApStopSaQuery(prAdapter, prStaRec); + } else { + DBGLOG(RSN, INFO, + "IEEE 802.11: AP No matching SA Query transaction identifier found\n"); + } + +} + +#endif /* CFG_SUPPORT_802_11W */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/saa_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/saa_fsm.c new file mode 100644 index 0000000000000..44d784a736b84 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/saa_fsm.c @@ -0,0 +1,1858 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E 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_EXTERNAL_AUTH"), + (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: + DBGLOG(SAA, TRACE, "authAlgNum %d, AuthTranNum %d\n", + prStaRec->ucAuthAlgNum, prStaRec->ucAuthTranNum); + if (prStaRec->ucAuthAlgNum == AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION && + prStaRec->ucAuthTranNum == AUTH_TRANSACTION_SEQ_2 && + prStaRec->ucStaState == STA_STATE_1) { + PARAM_STATUS_INDICATION_T rStatus = {.eStatusType = ENUM_STATUS_TYPE_FT_AUTH_STATUS}; + struct cfg80211_ft_event_params *prFtEvent = &prAdapter->prGlueInfo->rFtEventParam; + + prFtEvent->target_ap = prStaRec->aucMacAddr; + /* now, we don't support RIC first */ + prFtEvent->ric_ies = NULL; + prFtEvent->ric_ies_len = 0; + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, &rStatus, sizeof(rStatus)); + break; /* wait supplicant update ft ies and then continue to send assoc 1 */ + } + if (ePreviousState != prStaRec->eAuthAssocState) { /* Only trigger this event once */ + + if (prRetainedSwRfb) { + if (saaFsmSendEventJoinComplete(prAdapter, + WLAN_STATUS_SUCCESS, + prStaRec, + prRetainedSwRfb) == WLAN_STATUS_SUCCESS) { + /* Do nothing */ + } else { + eNextState = AA_STATE_RESOURCE; + fgIsTransition = TRUE; + } + } else { + if (saaFsmSendEventJoinComplete(prAdapter, + WLAN_STATUS_FAILURE, + prStaRec, + NULL) == WLAN_STATUS_RESOURCES) { + eNextState = AA_STATE_RESOURCE; + fgIsTransition = TRUE; + } + } + + } + + /* Free allocated TCM memory */ + if (prStaRec->prChallengeText) { + cnmMemFree(prAdapter, prStaRec->prChallengeText); + prStaRec->prChallengeText = (P_IE_CHALLENGE_TEXT_T) NULL; + } + break; + + case SAA_STATE_SEND_AUTH1: + { + /* Do tasks in INIT STATE */ + if (prStaRec->ucTxAuthAssocRetryCount >= prStaRec->ucTxAuthAssocRetryLimit) { + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_AUTH_TIMEOUT; + + eNextState = AA_STATE_IDLE; + fgIsTransition = TRUE; + } else { + prStaRec->ucTxAuthAssocRetryCount++; + prStaRec->ucAuthTranNum = AUTH_TRANSACTION_SEQ_1; + /* Update Station Record - Class 1 Flag */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + +#if !CFG_SUPPORT_AAA + if (authSendAuthFrame(prAdapter, + prStaRec, AUTH_TRANSACTION_SEQ_1) != WLAN_STATUS_SUCCESS) { +#else + if (authSendAuthFrame(prAdapter, + prStaRec, + prStaRec->ucNetTypeIndex, + NULL, + AUTH_TRANSACTION_SEQ_1, + STATUS_CODE_RESERVED) != WLAN_STATUS_SUCCESS) { +#endif /* CFG_SUPPORT_AAA */ + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC) saaFsmRunEventTxReqTimeOut, + (ULONG) prStaRec); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC(TX_AUTHENTICATION_RETRY_TIMEOUT_TU)); + } + } + } + break; + + case SAA_STATE_WAIT_AUTH2: + break; + + case SAA_STATE_SEND_AUTH3: + { + /* Do tasks in INIT STATE */ + if (prStaRec->ucTxAuthAssocRetryCount >= prStaRec->ucTxAuthAssocRetryLimit) { + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_AUTH_TIMEOUT; + + eNextState = AA_STATE_IDLE; + fgIsTransition = TRUE; + } else { + prStaRec->ucTxAuthAssocRetryCount++; + prStaRec->ucAuthTranNum = AUTH_TRANSACTION_SEQ_3; +#if !CFG_SUPPORT_AAA + if (authSendAuthFrame(prAdapter, + prStaRec, AUTH_TRANSACTION_SEQ_3) != WLAN_STATUS_SUCCESS) { +#else + if (authSendAuthFrame(prAdapter, + prStaRec, + prStaRec->ucNetTypeIndex, + NULL, + AUTH_TRANSACTION_SEQ_3, + STATUS_CODE_RESERVED) != WLAN_STATUS_SUCCESS) { +#endif /* CFG_SUPPORT_AAA */ + + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC) saaFsmRunEventTxReqTimeOut, + (ULONG) prStaRec); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC(TX_AUTHENTICATION_RETRY_TIMEOUT_TU)); + } + } + } + break; + + case SAA_STATE_WAIT_AUTH4: + break; + +#if CFG_SUPPORT_WPA3 + case SAA_STATE_EXTERNAL_AUTH: + kalExternalAuthRequest(prAdapter); + break; +#endif + + case SAA_STATE_SEND_ASSOC1: + /* Do tasks in INIT STATE */ + if (prStaRec->ucTxAuthAssocRetryCount >= prStaRec->ucTxAuthAssocRetryLimit) { + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_ASSOC_TIMEOUT; + + eNextState = AA_STATE_IDLE; + fgIsTransition = TRUE; + } else { + prStaRec->ucTxAuthAssocRetryCount++; + + if (assocSendReAssocReqFrame(prAdapter, prStaRec) != WLAN_STATUS_SUCCESS) { + + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC) saaFsmRunEventTxReqTimeOut, + (ULONG) prStaRec); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC(TX_ASSOCIATION_RETRY_TIMEOUT_TU)); + } + } + + break; + + case SAA_STATE_WAIT_ASSOC2: + break; + + case AA_STATE_RESOURCE: + /* TODO(Kevin) Can setup a timer and send message later */ + break; + + default: + DBGLOG(SAA, ERROR, "Unknown AA STATE\n"); + ASSERT(0); + break; + } + + } while (fgIsTransition); + + return; + +} /* end of saaFsmSteps() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send Event to AIS/BOW/P2P +* +* @param[in] rJoinStatus To indicate JOIN success or failure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] prSwRfb Pointer to the SW_RFB_T + +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +saaFsmSendEventJoinComplete(IN P_ADAPTER_T prAdapter, + IN WLAN_STATUS rJoinStatus, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb) +{ + P_BSS_INFO_T prBssInfo; + + ASSERT(prStaRec); + if (!prStaRec) + return WLAN_STATUS_INVALID_PACKET; + + /* Store limitation about 40Mhz bandwidth capability during association */ + if (prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM) { + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; + + if (rJoinStatus == WLAN_STATUS_SUCCESS) + prBssInfo->fg40mBwAllowed = prBssInfo->fgAssoc40mBwAllowed; + prBssInfo->fgAssoc40mBwAllowed = FALSE; + } + + if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { + P_MSG_SAA_FSM_COMP_T prSaaFsmCompMsg; + + prSaaFsmCompMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SAA_FSM_COMP_T)); + if (!prSaaFsmCompMsg) + return WLAN_STATUS_RESOURCES; + + if (rJoinStatus == WLAN_STATUS_SUCCESS) + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + + 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; + + if (rJoinStatus == WLAN_STATUS_SUCCESS) + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + + 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)) { + if (prStaRec) + DBGLOG(SAA, ERROR, "fgIsInUse = %d\n", prStaRec->fgIsInUse); + 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); + + if (prStaRec->ucAuthAlgNum == AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION && + prStaRec->ucAuthTranNum == AUTH_TRANSACTION_SEQ_2) { + DBGLOG(SAA, ERROR, "current is waiting FT auth, don't reentry\n"); + return; + } + /* 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_UNSPECIFIED_FAILURE; + + /* Update the record join time. */ + GET_CURRENT_SYSTIME(&prStaRec->rLastJoinTime); + + prStaRec->ucTxAuthAssocRetryCount = 0; + + if (prStaRec->prChallengeText) { + cnmMemFree(prAdapter, prStaRec->prChallengeText); + prStaRec->prChallengeText = (P_IE_CHALLENGE_TEXT_T) NULL; + } + + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + +#if CFG_PRIVACY_MIGRATION + /* 4 <4> Init the sec fsm */ + secFsmInit(prAdapter, prStaRec); +#endif + + /* 4 <5> Reset the STA STATE */ + /* Update Station Record - Class 1 Flag */ + /* NOTE(Kevin): Moved to AIS FSM for Reconnect issue - + * We won't deactivate the same STA_RECORD_T and then activate it again for the + * case of reconnection. + */ + /* cnmStaRecChangeState(prStaRec, STA_STATE_1); */ + + /* 4 <6> Decide if this BSS 20/40M bandwidth is allowed */ + if (prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM) { + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; + + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) + && (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) { + prBssInfo->fgAssoc40mBwAllowed = cnmBss40mBwPermitted(prAdapter, prBssInfo->ucNetTypeIndex); + } else { + prBssInfo->fgAssoc40mBwAllowed = FALSE; + } + DBGLOG(RLM, INFO, "STA 40mAllowed=%d\n", prBssInfo->fgAssoc40mBwAllowed); + } + /* 4 <7> Trigger SAA FSM */ + if (prStaRec->ucStaState == STA_STATE_1) { + if (prStaRec->ucAuthAlgNum == AUTH_ALGORITHM_NUM_SAE) + saaFsmSteps(prAdapter, prStaRec, + SAA_STATE_EXTERNAL_AUTH, + (P_SW_RFB_T) NULL); + else + saaFsmSteps(prAdapter, prStaRec, SAA_STATE_SEND_AUTH1, + (P_SW_RFB_T) NULL); + } else if (prStaRec->ucStaState == STA_STATE_2 || prStaRec->ucStaState == STA_STATE_3) + saaFsmSteps(prAdapter, prStaRec, SAA_STATE_SEND_ASSOC1, (P_SW_RFB_T) NULL); + +} /* end of saaFsmRunEventStart() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Continue Event to SAA FSM. +* +* @param[in] prMsgHdr Message of Join Request for a particular STA. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID saaFsmRunEventFTContinue(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + struct MSG_SAA_FT_CONTINUE *prSaaFsmMsg = NULL; + P_STA_RECORD_T prStaRec; + BOOLEAN fgFtRicRequest = FALSE; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prSaaFsmMsg = (struct MSG_SAA_FT_CONTINUE *)prMsgHdr; + prStaRec = prSaaFsmMsg->prStaRec; + fgFtRicRequest = prSaaFsmMsg->fgFTRicRequest; + cnmMemFree(prAdapter, prMsgHdr); + if ((!prStaRec) || (prStaRec->fgIsInUse == FALSE)) { + DBGLOG(SAA, ERROR, "No Sta Record or it is not in use\n"); + return; + } + if (prStaRec->eAuthAssocState != AA_STATE_IDLE) { + DBGLOG(SAA, ERROR, "Wrong SAA FSM state %d to continue auth/assoc\n", prStaRec->eAuthAssocState); + return; + } + DBGLOG(SAA, TRACE, "Continue to do auth/assoc\n"); + if (fgFtRicRequest) + saaFsmSteps(prAdapter, prStaRec, SAA_STATE_SEND_AUTH3, (P_SW_RFB_T) NULL); + else { + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + saaFsmSteps(prAdapter, prStaRec, SAA_STATE_SEND_ASSOC1, (P_SW_RFB_T) NULL); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle TxDone(Auth1/Auth3/AssocReq) Event of SAA FSM. +* +* @param[in] prMsduInfo Pointer to the MSDU_INFO_T. +* @param[in] rTxDoneStatus Return TX status of the Auth1/Auth3/AssocReq frame. +* +* @retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +saaFsmRunEventTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + + P_STA_RECORD_T prStaRec; + ENUM_AA_STATE_T eNextState; + + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (!prStaRec) { + DBGLOG(SAA, INFO, "EVENT-TX DONE: Status %d, Invalid StaRec\n", rTxDoneStatus); + return WLAN_STATUS_INVALID_PACKET; + } + + ASSERT(prStaRec); + + DBGLOG(SAA, INFO, "EVENT-TX DONE: Status: %d, eAuthAssocState: %d , SeqNO: %d ", + rTxDoneStatus, prStaRec->eAuthAssocState, + prMsduInfo->ucTxSeqNum); + + eNextState = prStaRec->eAuthAssocState; + + switch (prStaRec->eAuthAssocState) { + case SAA_STATE_SEND_AUTH1: + { + /* Strictly check the outgoing frame is matched with current AA STATE */ + if (authCheckTxAuthFrame(prAdapter, prMsduInfo, AUTH_TRANSACTION_SEQ_1) != WLAN_STATUS_SUCCESS) + break; + + if (rTxDoneStatus == TX_RESULT_SUCCESS) { + eNextState = SAA_STATE_WAIT_AUTH2; + + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC) saaFsmRunEventRxRespTimeOut, + (ULONG) prStaRec); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC(DOT11_AUTHENTICATION_RESPONSE_TIMEOUT_TU)); + } + + /* if TX was successful, change to next state. + * if TX was failed, do retry if possible. + */ + saaFsmSteps(prAdapter, prStaRec, eNextState, (P_SW_RFB_T) NULL); + } + break; + + case SAA_STATE_SEND_AUTH3: + { + /* Strictly check the outgoing frame is matched with current JOIN STATE */ + if (authCheckTxAuthFrame(prAdapter, prMsduInfo, AUTH_TRANSACTION_SEQ_3) != WLAN_STATUS_SUCCESS) + break; + + if (rTxDoneStatus == TX_RESULT_SUCCESS) { + eNextState = SAA_STATE_WAIT_AUTH4; + + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC) saaFsmRunEventRxRespTimeOut, + (ULONG) prStaRec); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC(DOT11_AUTHENTICATION_RESPONSE_TIMEOUT_TU)); + } + + /* if TX was successful, change to next state. + * if TX was failed, do retry if possible. + */ + saaFsmSteps(prAdapter, prStaRec, eNextState, (P_SW_RFB_T) NULL); + } + break; + + case SAA_STATE_SEND_ASSOC1: + { + /* Strictly check the outgoing frame is matched with current SAA STATE */ + if (assocCheckTxReAssocReqFrame(prAdapter, prMsduInfo) != WLAN_STATUS_SUCCESS) + break; + + if (rTxDoneStatus == TX_RESULT_SUCCESS) { + eNextState = SAA_STATE_WAIT_ASSOC2; + + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC) saaFsmRunEventRxRespTimeOut, + (ULONG) prStaRec); + + cnmTimerStartTimer(prAdapter, + &(prStaRec->rTxReqDoneOrRxRespTimer), + TU_TO_MSEC(DOT11_ASSOCIATION_RESPONSE_TIMEOUT_TU)); + } + /* if TX was successful, change to next state. + * if TX was failed, do retry if possible. + */ + saaFsmSteps(prAdapter, prStaRec, eNextState, (P_SW_RFB_T) NULL); + } + break; + + default: + break; /* Ignore other cases */ + } + + return WLAN_STATUS_SUCCESS; + +} /* end of saaFsmRunEventTxDone() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send Tx Request Timeout Event to SAA FSM. +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID saaFsmRunEventTxReqTimeOut(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + ASSERT(prStaRec); + if (!prStaRec) + return; + + DBGLOG(SAA, LOUD, "EVENT-TIMER: TX REQ TIMEOUT, Current Time = %u\n", kalGetTimeTick()); + + switch (prStaRec->eAuthAssocState) { + case SAA_STATE_SEND_AUTH1: + case SAA_STATE_SEND_AUTH3: + case SAA_STATE_SEND_ASSOC1: + saaFsmSteps(prAdapter, prStaRec, prStaRec->eAuthAssocState, (P_SW_RFB_T) NULL); + break; + + default: + return; + } + +} /* end of saaFsmRunEventTxReqTimeOut() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send Rx Response Timeout Event to SAA FSM. +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID saaFsmRunEventRxRespTimeOut(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + ENUM_AA_STATE_T eNextState; + + DBGLOG(SAA, LOUD, "EVENT-TIMER: RX RESP TIMEOUT, Current Time = %u\n", kalGetTimeTick()); + + ASSERT(prStaRec); + if (!prStaRec) + return; + + eNextState = prStaRec->eAuthAssocState; + + switch (prStaRec->eAuthAssocState) { + case SAA_STATE_WAIT_AUTH2: + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_AUTH_TIMEOUT; + + /* Pull back to earlier state to do retry */ + eNextState = SAA_STATE_SEND_AUTH1; + break; + + case SAA_STATE_WAIT_AUTH4: + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_AUTH_TIMEOUT; + + /* Pull back to earlier state to do retry */ + eNextState = SAA_STATE_SEND_AUTH3; + break; + + case SAA_STATE_WAIT_ASSOC2: + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_ASSOC_TIMEOUT; + + /* Pull back to earlier state to do retry */ + eNextState = SAA_STATE_SEND_ASSOC1; + break; + + default: + break; /* Ignore other cases */ + } + + if (eNextState != prStaRec->eAuthAssocState) + saaFsmSteps(prAdapter, prStaRec, eNextState, (P_SW_RFB_T) NULL); + +} /* end of saaFsmRunEventRxRespTimeOut() */ + +#if CFG_SUPPORT_RN +static BOOLEAN saaCheckOverLoadRN(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN ENUM_AA_STATE_T eFrmType) +{ + static UINT_32 u4OverLoadRN; + P_BSS_INFO_T prAisBssInfo; + PARAM_SSID_T rSsid; + P_CONNECTION_SETTINGS_T prConnSettings; + P_AIS_FSM_INFO_T prAisFsmInfo; + + kalMemZero(&rSsid, sizeof(PARAM_SSID_T)); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + if (prAisBssInfo->fgDisConnReassoc == TRUE) { + if (prStaRec->u2StatusCode == STATUS_CODE_ASSOC_DENIED_AP_OVERLOAD) { + DBGLOG(SAA, INFO, " eFrmType: %d, u4OverLoadRN times: %d\n", eFrmType, u4OverLoadRN); + if (u4OverLoadRN < JOIN_MAX_RETRY_OVERLOAD_RN) { + P_BSS_DESC_T prBssDesc; + + prBssDesc = prAisFsmInfo->prTargetBssDesc; + if (prBssDesc) + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + else + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, + prConnSettings->aucSSID, prConnSettings->ucSSIDLen); + + prBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, + prStaRec->aucMacAddr, TRUE, &rSsid); + if (prBssDesc) { + aisAddBlacklist(prAdapter, prBssDesc); + if (prBssDesc->prBlack) + prBssDesc->prBlack->u2AuthStatus = prStaRec->u2StatusCode; + } else + DBGLOG(SAA, INFO, " prBssDesc is NULL!\n"); + + u4OverLoadRN++; + aisFsmStateAbort(prAdapter, DISCONNECT_REASON_CODE_RADIO_LOST, TRUE); + return TRUE; + } + } + } else + u4OverLoadRN = 0; + + return FALSE; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will process the Rx Auth Response Frame and then +* trigger SAA FSM. +* +* @param[in] prSwRfb Pointer to the SW_RFB_T structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID saaFsmRunEventRxAuth(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_STA_RECORD_T prStaRec; + UINT_16 u2StatusCode; + ENUM_AA_STATE_T eNextState; + + ASSERT(prSwRfb); + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + /* We should have the corresponding Sta Record. */ + if (!prStaRec) { + /* Peter: we can handle the packet without station record */ + /* ASSERT(0); */ + return; + } + + if (!IS_AP_STA(prStaRec)) + return; + + switch (prStaRec->eAuthAssocState) { + case SAA_STATE_SEND_AUTH1: + case SAA_STATE_WAIT_AUTH2: + /* Check if the incoming frame is what we are waiting for */ + if (authCheckRxAuthFrameStatus(prAdapter, + prSwRfb, AUTH_TRANSACTION_SEQ_2, &u2StatusCode) == WLAN_STATUS_SUCCESS) { + + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = u2StatusCode; + + if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + + authProcessRxAuth2_Auth4Frame(prAdapter, prSwRfb); + prStaRec->ucAuthTranNum = AUTH_TRANSACTION_SEQ_2; + /* after received Auth2 for FT, should indicate to supplicant + * and wait response from supplicant + */ + if (prStaRec->ucAuthAlgNum == AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION) + eNextState = AA_STATE_IDLE; + else if (prStaRec->ucAuthAlgNum == (UINT_8) AUTH_ALGORITHM_NUM_SHARED_KEY) + eNextState = SAA_STATE_SEND_AUTH3; + else { + /* Update Station Record - Class 2 Flag */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + + eNextState = SAA_STATE_SEND_ASSOC1; + } + } else { + DBGLOG(SAA, INFO, "Auth Req was rejected by [ %pM ], Status Code = %d\n", + (prStaRec->aucMacAddr), u2StatusCode); + + eNextState = AA_STATE_IDLE; + } + + /* Reset Send Auth/(Re)Assoc Frame Count */ + prStaRec->ucTxAuthAssocRetryCount = 0; +#if CFG_SUPPORT_RN + if (saaCheckOverLoadRN(prAdapter, prStaRec, SAA_STATE_SEND_AUTH1)) + break; +#endif + 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) { + /* Add for 802.11r handling */ + WLAN_STATUS rStatus = authProcessRxAuth2_Auth4Frame(prAdapter, prSwRfb); + + prStaRec->ucAuthTranNum = AUTH_TRANSACTION_SEQ_4; + /* if Auth4 check is failed(check mic in Auth ack frame), should disconnect */ + if (prStaRec->ucAuthAlgNum == AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION && + rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(SAA, INFO, + "Check Rx Auth4 Frame failed, may be MIC error, %pM, status %d\n", + (prStaRec->aucMacAddr), u2StatusCode); + /* Reset Send Auth/(Re)Assoc Frame Count */ + prStaRec->ucTxAuthAssocRetryCount = 0; + saaFsmSteps(prAdapter, prStaRec, AA_STATE_IDLE, (P_SW_RFB_T) NULL); + break; + } + + /* Update Station Record - Class 2 Flag */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + + eNextState = SAA_STATE_SEND_ASSOC1; + } else { + DBGLOG(SAA, INFO, "Auth Req was rejected by [ %pM ], Status Code = %d\n", + (prStaRec->aucMacAddr), u2StatusCode); + + eNextState = AA_STATE_IDLE; + } + + /* Reset Send Auth/(Re)Assoc Frame Count */ + prStaRec->ucTxAuthAssocRetryCount = 0; + + saaFsmSteps(prAdapter, prStaRec, eNextState, (P_SW_RFB_T) NULL); + } + break; + + case SAA_STATE_EXTERNAL_AUTH: + kalIndicateRxMgmtFrame(prAdapter->prGlueInfo, prSwRfb); + break; + + default: + break; /* Ignore other cases */ + } + +} /* end of saaFsmRunEventRxAuth() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will process the Rx (Re)Association Response Frame and then +* trigger SAA FSM. +* +* @param[in] prSwRfb Pointer to the SW_RFB_T structure. +* +* @retval WLAN_STATUS_SUCCESS if the status code was not success +* @retval WLAN_STATUS_BUFFER_RETAINED if the status code was success +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS saaFsmRunEventRxAssoc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_STA_RECORD_T prStaRec; + UINT_16 u2StatusCode; + ENUM_AA_STATE_T eNextState; + P_SW_RFB_T prRetainedSwRfb = (P_SW_RFB_T) NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prSwRfb); + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + /* We should have the corresponding Sta Record. */ + if (!prStaRec) { + ASSERT(0); + return rStatus; + } + + if (!IS_AP_STA(prStaRec)) + return rStatus; + + switch (prStaRec->eAuthAssocState) { + case SAA_STATE_SEND_ASSOC1: + case SAA_STATE_WAIT_ASSOC2: + /* TRUE if the incoming frame is what we are waiting for */ + if (assocCheckRxReAssocRspFrameStatus(prAdapter, prSwRfb, &u2StatusCode) == WLAN_STATUS_SUCCESS) { + + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = u2StatusCode; + + if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + + /* Update Station Record - Class 3 Flag */ + /* NOTE(Kevin): Moved to AIS FSM for roaming issue - + * We should deactivate the STA_RECORD_T of previous AP before + * activate new one in Driver. + */ + /* cnmStaRecChangeState(prStaRec, STA_STATE_3); */ + + prStaRec->ucJoinFailureCount = 0; /* Clear history. */ + + prRetainedSwRfb = prSwRfb; + rStatus = WLAN_STATUS_PENDING; + } else { + DBGLOG(SAA, INFO, "Assoc Req was rejected by [ %pM ], Status Code = %d\n", + (prStaRec->aucMacAddr), u2StatusCode); + } + + /* Reset Send Auth/(Re)Assoc Frame Count */ + prStaRec->ucTxAuthAssocRetryCount = 0; + + /* update RCPI */ + prStaRec->ucRCPI = prSwRfb->prHifRxHdr->ucRcpi; + + eNextState = AA_STATE_IDLE; + +#if CFG_SUPPORT_RN + if (saaCheckOverLoadRN(prAdapter, prStaRec, SAA_STATE_SEND_ASSOC1)) + break; +#endif + saaFsmSteps(prAdapter, prStaRec, eNextState, prRetainedSwRfb); + } + break; + + default: + break; /* Ignore other cases */ + } + + return rStatus; + +} /* end of saaFsmRunEventRxAssoc() */ + +VOID +saaSendDisconnectMsgHandler(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_BSS_INFO_T prAisBssInfo, + IN ENUM_AA_FRM_TYPE_T eFrmType) +{ + do { + if (eFrmType == FRM_DEAUTH) { + if (prStaRec->ucStaState >= STA_STATE_2) { + 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 */ + } + } else { /* FRM_DISASSOC*/ + if (prStaRec->ucStaState >= STA_STATE_3) { + P_MSG_AIS_ABORT_T prAisAbortMsg; + /* NOTE(Chaozhong): Change state immediately to avoid starvation of + * MSG buffer because of too many disassoc frames before changing + * the STA state. + */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + + prAisAbortMsg = + (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(MSG_AIS_ABORT_T)); + if (!prAisAbortMsg) + break; + + prAisAbortMsg->rMsgHdr.eMsgId = MID_SAA_AIS_FSM_ABORT; + prAisAbortMsg->ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_DISASSOCIATED; + prAisAbortMsg->fgDelayIndication = FALSE; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); + } else { + + /* TODO(Kevin): Joining Abort */ + } + } + if (prAisBssInfo) + prAisBssInfo->u2DeauthReason = prStaRec->u2ReasonCode; + } while (0); +} + +#if CFG_SUPPORT_RN +static VOID saaAutoReConnect(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, + IN P_BSS_INFO_T prAisBssInfo, IN ENUM_AA_FRM_TYPE_T eFrmType) +{ + OS_SYSTIME rCurrentTime; + P_CONNECTION_SETTINGS_T prConnSettings; + P_AIS_FSM_INFO_T prAisFsmInfo; + PARAM_SSID_T rSsid; + + kalMemZero(&rSsid, sizeof(PARAM_SSID_T)); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + GET_CURRENT_SYSTIME(&rCurrentTime); + + /* + * TODO: maybe AP is in DFS channel, it wants to switch channels? + * Wait for beacon timeout? + * Need to do partial scan for the AP channel. + */ + + if (!CHECK_FOR_TIMEOUT(rCurrentTime, prAisBssInfo->rConnTime, + SEC_TO_SYSTIME(AIS_AUTORN_MIN_INTERVAL)) && + /* maybe some packets are queued in HW, we will get many de-auth */ + (prAisBssInfo->fgDisConnReassoc == FALSE)) { + DBGLOG(SAA, INFO, " AP deauth ok 0x%x %x %x rcpi:%d\n", + rCurrentTime, prAisBssInfo->rConnTime, SEC_TO_SYSTIME(AIS_AUTORN_MIN_INTERVAL), + dBm_TO_RCPI(prAdapter->rLinkQuality.cRssi)); + saaSendDisconnectMsgHandler(prAdapter, prStaRec, prAisBssInfo, eFrmType); + } else { + DBGLOG(SAA, INFO, " reassociate\n"); + + if (prAisBssInfo->fgDisConnReassoc == FALSE) { + P_BSS_DESC_T prBssDesc; + + /* during reassoc, FW send null then we maybe get deauth again */ + /* in the case, we will send deauth to supplicant, not here */ + + /* avoid re-scan */ + prAisBssInfo->fgDisConnReassoc = TRUE; + + prConnSettings->fgIsConnReqIssued = TRUE; + prConnSettings->fgIsDisconnectedByNonRequest = FALSE; + prAisBssInfo->u2DeauthReason = prStaRec->u2ReasonCode; + + prBssDesc = prAisFsmInfo->prTargetBssDesc; + if (prBssDesc) + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + else + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, + prConnSettings->aucSSID, prConnSettings->ucSSIDLen); + + prBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, prStaRec->aucMacAddr, TRUE, &rSsid); + if (prBssDesc) { + aisAddBlacklist(prAdapter, prBssDesc); + if (prStaRec->u2ReasonCode == REASON_CODE_DISASSOC_AP_OVERLOAD) { + struct AIS_BLACKLIST_ITEM *prBlackList = aisAddBlacklist(prAdapter, prBssDesc); + + if (prBlackList) + prBlackList->u2DeauthReason = prStaRec->u2ReasonCode; + } + prBssDesc->fgDeauthLastTime = TRUE; + prBssDesc->fgIsConnected = FALSE; + } else + DBGLOG(SAA, INFO, " prBssDesc is NULL!\n"); + aisFsmStateAbort(prAdapter, DISCONNECT_REASON_CODE_RADIO_LOST, TRUE); + } else if (!CHECK_FOR_TIMEOUT(rCurrentTime, prAisBssInfo->rConnTime, + SEC_TO_SYSTIME(AIS_AUTORN_MIN_INTERVAL - 10))) { + + DBGLOG(SAA, INFO, " AP deauth ok under reassoc 0x%x %x %x\n", + rCurrentTime, prAisBssInfo->rConnTime, SEC_TO_SYSTIME(AIS_AUTORN_MIN_INTERVAL - 10)); + + prAisBssInfo->fgDisConnReassoc = FALSE; + saaSendDisconnectMsgHandler(prAdapter, prStaRec, prAisBssInfo, eFrmType); + } + /* else, we are reassociating, skip the deauth */ + } +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will check the incoming Deauth Frame. +* +* @param[in] prSwRfb Pointer to the SW_RFB_T structure. +* +* @retval WLAN_STATUS_SUCCESS Always not retain deauthentication frames +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS saaFsmRunEventRxDeauth(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_STA_RECORD_T prStaRec; + P_WLAN_DEAUTH_FRAME_T prDeauthFrame; + + ASSERT(prSwRfb); + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (prStaRec == NULL) + return WLAN_STATUS_FAILURE; + + prDeauthFrame = (P_WLAN_DEAUTH_FRAME_T) prSwRfb->pvHeader; + DBGLOG(SAA, INFO, "Rx Deauth frame from BSSID=[ %pM ], reason: %d.\n", + prDeauthFrame->aucBSSID, prDeauthFrame->u2ReasonCode); + + do { + if (IS_STA_IN_AIS(prStaRec)) { + P_AIS_BSS_INFO_T prAisBssInfo; + + if (!IS_AP_STA(prStaRec)) + break; + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + if (prStaRec->ucStaState <= STA_STATE_1) + break; + + /* Check if this is the AP we are associated or associating with */ + if (authProcessRxDeauthFrame(prSwRfb, + prStaRec->aucMacAddr, + &prStaRec->u2ReasonCode) == WLAN_STATUS_SUCCESS && + prAdapter->prGlueInfo->eParamMediaStateIndicated == + PARAM_MEDIA_STATE_CONNECTED) { + + DBGLOG(SAA, INFO, "Deauth reason = %d\n", prStaRec->u2ReasonCode); +#if CFG_SUPPORT_RN + saaAutoReConnect(prAdapter, prStaRec, prAisBssInfo, FRM_DEAUTH); +#else + saaSendDisconnectMsgHandler(prAdapter, prStaRec, prAisBssInfo, FRM_DEAUTH); +#endif + } + + } +#if CFG_ENABLE_WIFI_DIRECT + else if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { + /* TODO(Kevin) */ + p2pFsmRunEventRxDeauthentication(prAdapter, prStaRec, prSwRfb); + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (IS_STA_IN_BOW(prStaRec)) + bowRunEventRxDeAuth(prAdapter, prStaRec, prSwRfb); +#endif + else + ASSERT(0); + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; +} /* end of saaFsmRunEventRxDeauth() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will check the incoming Disassociation Frame. +* +* @param[in] prSwRfb Pointer to the SW_RFB_T structure. +* +* @retval WLAN_STATUS_SUCCESS Always not retain disassociation frames +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS saaFsmRunEventRxDisassoc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_STA_RECORD_T prStaRec; + P_WLAN_DISASSOC_FRAME_T prDisassocFrame; + + ASSERT(prSwRfb); + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (prStaRec == NULL) + return WLAN_STATUS_FAILURE; + + prDisassocFrame = (P_WLAN_DISASSOC_FRAME_T) prSwRfb->pvHeader; + DBGLOG(SAA, INFO, "Rx Disassoc frame from BSSID=[ %pM ].\n", (prDisassocFrame->aucBSSID)); + + do { + if (IS_STA_IN_AIS(prStaRec)) { + P_AIS_BSS_INFO_T prAisBssInfo; + + if (!IS_AP_STA(prStaRec)) + break; + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + if (prStaRec->ucStaState <= STA_STATE_1) + break; + + /* Check if this is the AP we are associated or associating with */ + if (assocProcessRxDisassocFrame(prAdapter, + prSwRfb, + prStaRec->aucMacAddr, + &prStaRec->u2ReasonCode) == WLAN_STATUS_SUCCESS) { + + DBGLOG(SAA, INFO, "Disassoc reason = %d\n", prStaRec->u2ReasonCode); +#if CFG_SUPPORT_RN + saaAutoReConnect(prAdapter, prStaRec, prAisBssInfo, FRM_DISASSOC); +#else + saaSendDisconnectMsgHandler(prAdapter, prStaRec, prAisBssInfo, FRM_DISASSOC); +#endif + } + + } +#if CFG_ENABLE_WIFI_DIRECT + else if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { + /* TODO(Kevin) */ + p2pFsmRunEventRxDisassociation(prAdapter, prStaRec, prSwRfb); + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (IS_STA_IN_BOW(prStaRec)) { + /* Do nothing */ + /* TODO(Kevin) */ + } +#endif + else + ASSERT(0); + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; +} /* end of saaFsmRunEventRxDisassoc() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Abort Event to SAA FSM. +* +* @param[in] prMsgHdr Message of Abort Request for a particular STA. +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID saaFsmRunEventAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_SAA_FSM_ABORT_T prSaaFsmAbortMsg; + P_STA_RECORD_T prStaRec; + + ASSERT(prMsgHdr); + + prSaaFsmAbortMsg = (P_MSG_SAA_FSM_ABORT_T) prMsgHdr; + prStaRec = prSaaFsmAbortMsg->prStaRec; + + ASSERT(prStaRec); + if (!prStaRec) { + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + DBGLOG(SAA, LOUD, "EVENT-ABORT: Stop SAA FSM.\n"); + + cnmMemFree(prAdapter, prMsgHdr); + + /* Reset Send Auth/(Re)Assoc Frame Count */ + prStaRec->ucTxAuthAssocRetryCount = 0; + + /* Cancel JOIN relative Timer */ + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + + if (prStaRec->eAuthAssocState != AA_STATE_IDLE) { +#if DBG + DBGLOG(SAA, LOUD, "EVENT-ABORT: Previous Auth/Assoc State == %s.\n", + apucDebugAAState[prStaRec->eAuthAssocState]); +#else + DBGLOG(SAA, LOUD, "EVENT-ABORT: Previous Auth/Assoc State == %d.\n", prStaRec->eAuthAssocState); +#endif + } +#if 0 + /* For the Auth/Assoc State to IDLE */ + prStaRec->eAuthAssocState = AA_STATE_IDLE; +#else + /* Free this StaRec */ + cnmStaRecFree(prAdapter, prStaRec, FALSE); +#endif + +} /* end of saaFsmRunEventAbort() */ + +void saaFsmRunEventExternalAuthDone(IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr) +{ + struct MSG_SAA_EXTERNAL_AUTH_DONE *prSaaFsmMsg = NULL; + P_STA_RECORD_T prStaRec; + uint16_t status; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prSaaFsmMsg = (struct MSG_SAA_EXTERNAL_AUTH_DONE *)prMsgHdr; + prStaRec = prSaaFsmMsg->prStaRec; + status = prSaaFsmMsg->status; + + if (status != WLAN_STATUS_SUCCESS) + saaFsmSteps(prAdapter, prStaRec, AA_STATE_IDLE, + (P_SW_RFB_T)NULL); + else if (prStaRec->eAuthAssocState != SAA_STATE_EXTERNAL_AUTH) + DBGLOG(SAA, WARN, + "Receive External Auth DONE at wrong state\n"); + else + saaFsmSteps(prAdapter, prStaRec, SAA_STATE_SEND_ASSOC1, + (P_SW_RFB_T)NULL); +} /* end of saaFsmRunEventExternalAuthDone() */ + +/* TODO(Kevin): following code will be modified and move to AIS FSM */ +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will send Join Timeout Event to JOIN FSM. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \retval WLAN_STATUS_FAILURE Fail because of Join Timeout +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS joinFsmRunEventJoinTimeOut(IN P_ADAPTER_T prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("joinFsmRunEventJoinTimeOut"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + + DBGLOG(JOIN, EVENT, "JOIN EVENT: JOIN TIMEOUT\n"); + + /* Get a Station Record if possible, TA == BSSID for AP */ + prStaRec = staRecGetStaRecordByAddr(prAdapter, prJoinInfo->prBssDesc->aucBSSID); + + /* We have renew this Sta Record when in JOIN_STATE_INIT */ + ASSERT(prStaRec); + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_JOIN_TIMEOUT; + + /* Increase Failure Count */ + prStaRec->ucJoinFailureCount++; + + /* Reset Send Auth/(Re)Assoc Frame Count */ + prJoinInfo->ucTxAuthAssocRetryCount = 0; + + /* Cancel other JOIN relative Timer */ + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rTxRequestTimer); + + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rRxResponseTimer); + + /* Restore original setting from current BSS_INFO_T */ + if (prAdapter->eConnectionState == MEDIA_STATE_CONNECTED) + joinAdoptParametersFromCurrentBss(prAdapter); + + /* Pull back to IDLE */ + joinFsmSteps(prAdapter, JOIN_STATE_IDLE); + + return WLAN_STATUS_FAILURE; + +} /* end of joinFsmRunEventJoinTimeOut() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will adopt the parameters from Peer BSS. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID joinAdoptParametersFromPeerBss(IN P_ADAPTER_T prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + P_BSS_DESC_T prBssDesc; + + DEBUGFUNC("joinAdoptParametersFromPeerBss"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + prBssDesc = prJoinInfo->prBssDesc; + + /* 4 <1> Adopt Peer BSS' PHY TYPE */ + prAdapter->eCurrentPhyType = prBssDesc->ePhyType; + + DBGLOG(JOIN, INFO, "Target BSS[%s]'s PhyType = %s\n", + prBssDesc->aucSSID, (prBssDesc->ePhyType == PHY_TYPE_ERP_INDEX) ? "ERP" : "HR_DSSS"); + + /* 4 <2> Adopt Peer BSS' Frequency(Band/Channel) */ + DBGLOG(JOIN, INFO, "Target BSS's Channel = %d, Band = %d\n", prBssDesc->ucChannelNum, prBssDesc->eBand); + + nicSwitchChannel(prAdapter, prBssDesc->eBand, prBssDesc->ucChannelNum, 10); + + prJoinInfo->fgIsParameterAdopted = TRUE; + +} /* end of joinAdoptParametersFromPeerBss() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will adopt the parameters from current associated BSS. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID joinAdoptParametersFromCurrentBss(IN P_ADAPTER_T prAdapter) +{ + /* P_JOIN_INFO_T prJoinInfo = &prAdapter->rJoinInfo; */ + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + prBssInfo = &prAdapter->rBssInfo; + + /* 4 <1> Adopt current BSS' PHY TYPE */ + prAdapter->eCurrentPhyType = prBssInfo->ePhyType; + + /* 4 <2> Adopt current BSS' Frequency(Band/Channel) */ + DBGLOG(JOIN, INFO, "Current BSS's Channel = %d, Band = %d\n", prBssInfo->ucChnl, prBssInfo->eBand); + + nicSwitchChannel(prAdapter, prBssInfo->eBand, prBssInfo->ucChnl, 10); +} /* end of joinAdoptParametersFromCurrentBss() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will update all the SW variables and HW MCR registers after +* the association with target BSS. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID joinComplete(IN P_ADAPTER_T prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + P_BSS_DESC_T prBssDesc; + P_PEER_BSS_INFO_T prPeerBssInfo; + P_BSS_INFO_T prBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_STA_RECORD_T prStaRec; + P_TX_CTRL_T prTxCtrl; +#if CFG_SUPPORT_802_11D + P_IE_COUNTRY_T prIECountry; +#endif + + DEBUGFUNC("joinComplete"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + prBssDesc = prJoinInfo->prBssDesc; + prPeerBssInfo = &prAdapter->rPeerBssInfo; + prBssInfo = &prAdapter->rBssInfo; + prConnSettings = &prAdapter->rConnSettings; + prTxCtrl = &prAdapter->rTxCtrl; + +/* 4 <1> Update Connecting & Connected Flag of BSS_DESC_T. */ + /* Remove previous AP's Connection Flags if have */ + scanRemoveConnectionFlagOfBssDescByBssid(prAdapter, prBssInfo->aucBSSID); + + prBssDesc->fgIsConnected = TRUE; /* Mask as Connected */ + + if (prBssDesc->fgIsHiddenSSID) { + /* NOTE(Kevin): This is for the case of Passive Scan and the target BSS didn't + * broadcast SSID on its Beacon Frame. + */ + COPY_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, prAdapter->rConnSettings.aucSSID, prAdapter->rConnSettings.ucSSIDLen); + + if (prBssDesc->ucSSIDLen) + prBssDesc->fgIsHiddenSSID = FALSE; +#if DBG + else + ASSERT(0); +#endif /* DBG */ + + DBGLOG(JOIN, INFO, "Hidden SSID! - Update SSID : %s\n", prBssDesc->aucSSID); + } +/* 4 <2> Update BSS_INFO_T from BSS_DESC_T */ + /* 4 <2.A> PHY Type */ + prBssInfo->ePhyType = prBssDesc->ePhyType; + + /* 4 <2.B> BSS Type */ + prBssInfo->eBSSType = BSS_TYPE_INFRASTRUCTURE; + + /* 4 <2.C> BSSID */ + COPY_MAC_ADDR(prBssInfo->aucBSSID, prBssDesc->aucBSSID); + + DBGLOG(JOIN, INFO, "JOIN to BSSID: [%pM]\n", prBssDesc->aucBSSID); + + /* 4 <2.D> SSID */ + COPY_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + + /* 4 <2.E> Channel / Band information. */ + prBssInfo->eBand = prBssDesc->eBand; + prBssInfo->ucChnl = prBssDesc->ucChannelNum; + + /* 4 <2.F> RSN/WPA information. */ + secFsmRunEventStart(prAdapter); + prBssInfo->u4RsnSelectedPairwiseCipher = prBssDesc->u4RsnSelectedPairwiseCipher; + prBssInfo->u4RsnSelectedGroupCipher = prBssDesc->u4RsnSelectedGroupCipher; + prBssInfo->u4RsnSelectedAKMSuite = prBssDesc->u4RsnSelectedAKMSuite; + + if (secRsnKeyHandshakeEnabled()) + prBssInfo->fgIsWPAorWPA2Enabled = TRUE; + else + prBssInfo->fgIsWPAorWPA2Enabled = FALSE; + + /* 4 <2.G> Beacon interval. */ + prBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval; + + /* 4 <2.H> DTIM period. */ + prBssInfo->ucDtimPeriod = prBssDesc->ucDTIMPeriod; + + /* 4 <2.I> ERP Information */ + if ((prBssInfo->ePhyType == PHY_TYPE_ERP_INDEX) && /* Our BSS's PHY_TYPE is ERP now. */ + (prBssDesc->fgIsERPPresent)) { + + prBssInfo->fgIsERPPresent = TRUE; + prBssInfo->ucERP = prBssDesc->ucERP; /* Save the ERP for later check */ + } else { /* Some AP, may send ProbeResp without ERP IE. Thus prBssDesc->fgIsERPPresent is FALSE. */ + prBssInfo->fgIsERPPresent = FALSE; + prBssInfo->ucERP = 0; + } + +#if CFG_SUPPORT_802_11D + /* 4 <2.J> Country inforamtion of the associated AP */ + if (prConnSettings->fgMultiDomainCapabilityEnabled) { + DOMAIN_INFO_ENTRY rDomainInfo; + + if (domainGetDomainInfoByScanResult(prAdapter, &rDomainInfo)) { + if (prBssDesc->prIECountry) { + prIECountry = prBssDesc->prIECountry; + + domainParseCountryInfoElem(prIECountry, &prBssInfo->rDomainInfo); + + /* use the domain get from the BSS info */ + prBssInfo->fgIsCountryInfoPresent = TRUE; + nicSetupOpChnlList(prAdapter, prBssInfo->rDomainInfo.u2CountryCode, FALSE); + } else { + /* use the domain get from the scan result */ + prBssInfo->fgIsCountryInfoPresent = TRUE; + nicSetupOpChnlList(prAdapter, rDomainInfo.u2CountryCode, FALSE); + } + } + } +#endif + + /* 4 <2.K> Signal Power of the associated AP */ + prBssInfo->rRcpi = prBssDesc->rRcpi; + prBssInfo->rRssi = RCPI_TO_dBm(prBssInfo->rRcpi); + GET_CURRENT_SYSTIME(&prBssInfo->rRssiLastUpdateTime); + + /* 4 <2.L> Capability Field of the associated AP */ + prBssInfo->u2CapInfo = prBssDesc->u2CapInfo; + + DBGLOG(JOIN, INFO, "prBssInfo-> fgIsERPPresent = %d, ucERP = %02x, rRcpi = %d, rRssi = %ld\n", + prBssInfo->fgIsERPPresent, prBssInfo->ucERP, prBssInfo->rRcpi, prBssInfo->rRssi); + +/* 4 <3> Update BSS_INFO_T from PEER_BSS_INFO_T & NIC RATE FUNC */ + /* 4 <3.A> Association ID */ + prBssInfo->u2AssocId = prPeerBssInfo->u2AssocId; + + /* 4 <3.B> WMM Information */ + if (prAdapter->fgIsEnableWMM && (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_SUPPORT_WMM)) { + + prBssInfo->fgIsWmmAssoc = TRUE; + prTxCtrl->rTxQForVoipAccess = TXQ_AC3; + + qosWmmInfoInit(&prBssInfo->rWmmInfo, (prBssInfo->ePhyType == PHY_TYPE_HR_DSSS_INDEX) ? TRUE : FALSE); + + if (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_AC_PARAM_PRESENT) { + kalMemCopy(&prBssInfo->rWmmInfo, &prPeerBssInfo->rWmmInfo, sizeof(WMM_INFO_T)); + } else { + kalMemCopy(&prBssInfo->rWmmInfo, + &prPeerBssInfo->rWmmInfo, + sizeof(WMM_INFO_T) - sizeof(prPeerBssInfo->rWmmInfo.arWmmAcParams)); + } + } else { + prBssInfo->fgIsWmmAssoc = FALSE; + prTxCtrl->rTxQForVoipAccess = TXQ_AC1; + + kalMemZero(&prBssInfo->rWmmInfo, sizeof(WMM_INFO_T)); + } + + /* 4 <3.C> Operational Rate Set & BSS Basic Rate Set */ + prBssInfo->u2OperationalRateSet = prPeerBssInfo->u2OperationalRateSet; + prBssInfo->u2BSSBasicRateSet = prPeerBssInfo->u2BSSBasicRateSet; + + /* 4 <3.D> Short Preamble */ + if (prBssInfo->fgIsERPPresent) { + + /* NOTE(Kevin 2007/12/24): Truth Table. + * Short Preamble Bit in + * Final Driver Setting(Short) + * TRUE FALSE FALSE FALSE(shouldn't have such case, use the AssocResp) + * TRUE FALSE TRUE FALSE + * FALSE FALSE FALSE FALSE(shouldn't have such case, use the AssocResp) + * FALSE FALSE TRUE FALSE + * TRUE TRUE FALSE TRUE(follow ERP) + * TRUE TRUE TRUE FALSE(follow ERP) + * FALSE TRUE FALSE FALSE(shouldn't have such case, and we should set to FALSE) + * FALSE TRUE TRUE FALSE(we should set to FALSE) + */ + if ((prPeerBssInfo->fgIsShortPreambleAllowed) && + ((prConnSettings->ePreambleType == PREAMBLE_TYPE_SHORT) || + ((prConnSettings->ePreambleType == PREAMBLE_TYPE_AUTO) && + (prBssDesc->u2CapInfo & CAP_INFO_SHORT_PREAMBLE)))) { + + prBssInfo->fgIsShortPreambleAllowed = TRUE; + + if (prBssInfo->ucERP & ERP_INFO_BARKER_PREAMBLE_MODE) + prBssInfo->fgUseShortPreamble = FALSE; + else + prBssInfo->fgUseShortPreamble = TRUE; + } else { + prBssInfo->fgIsShortPreambleAllowed = FALSE; + prBssInfo->fgUseShortPreamble = FALSE; + } + } else { + /* NOTE(Kevin 2007/12/24): Truth Table. + * Short Preamble Bit in + * Final Driver Setting(Short) + * TRUE FALSE FALSE + * FALSE FALSE FALSE + * TRUE TRUE TRUE + * FALSE TRUE(status success) TRUE + * --> Honor the result of prPeerBssInfo. + */ + + prBssInfo->fgIsShortPreambleAllowed = prBssInfo->fgUseShortPreamble = + prPeerBssInfo->fgIsShortPreambleAllowed; + } + + DBGLOG(JOIN, INFO, "prBssInfo->fgIsShortPreambleAllowed = %d, prBssInfo->fgUseShortPreamble = %d\n", + prBssInfo->fgIsShortPreambleAllowed, prBssInfo->fgUseShortPreamble); + + /* 4 <3.E> Short Slot Time */ + prBssInfo->fgUseShortSlotTime = prPeerBssInfo->fgUseShortSlotTime; /* AP support Short Slot Time */ + + DBGLOG(JOIN, INFO, "prBssInfo->fgUseShortSlotTime = %d\n", prBssInfo->fgUseShortSlotTime); + + nicSetSlotTime(prAdapter, + prBssInfo->ePhyType, + ((prConnSettings->fgIsShortSlotTimeOptionEnable && + prBssInfo->fgUseShortSlotTime) ? TRUE : FALSE)); + + /* 4 <3.F> Update Tx Rate for Control Frame */ + bssUpdateTxRateForControlFrame(prAdapter); + + /* 4 <3.G> Save the available Auth Types during Roaming (Design for Fast BSS Transition). */ + /* if (prAdapter->fgIsEnableRoaming) */ /* NOTE(Kevin): Always prepare info for roaming */ + { + + if (prJoinInfo->ucCurrAuthAlgNum == AUTH_ALGORITHM_NUM_OPEN_SYSTEM) + prJoinInfo->ucRoamingAuthTypes |= AUTH_TYPE_OPEN_SYSTEM; + else if (prJoinInfo->ucCurrAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY) + prJoinInfo->ucRoamingAuthTypes |= AUTH_TYPE_SHARED_KEY; + + prBssInfo->ucRoamingAuthTypes = prJoinInfo->ucRoamingAuthTypes; + + /* Set the stable time of the associated BSS. We won't do roaming decision + * during the stable time. + */ + SET_EXPIRATION_TIME(prBssInfo->rRoamingStableExpirationTime, + SEC_TO_SYSTIME(ROAMING_STABLE_TIMEOUT_SEC)); + } + + /* 4 <3.H> Update Parameter for TX Fragmentation Threshold */ +#if CFG_TX_FRAGMENT + txFragInfoUpdate(prAdapter); +#endif /* CFG_TX_FRAGMENT */ + +/* 4 <4> Update STA_RECORD_T */ + /* Get a Station Record if possible */ + prStaRec = staRecGetStaRecordByAddr(prAdapter, prBssDesc->aucBSSID); + + if (prStaRec) { + UINT_16 u2OperationalRateSet, u2DesiredRateSet; + + /* 4 <4.A> Desired Rate Set */ + u2OperationalRateSet = (rPhyAttributes[prBssInfo->ePhyType].u2SupportedRateSet & + prBssInfo->u2OperationalRateSet); + + u2DesiredRateSet = (u2OperationalRateSet & prConnSettings->u2DesiredRateSet); + if (u2DesiredRateSet) { + prStaRec->u2DesiredRateSet = u2DesiredRateSet; + } else { + /* For Error Handling - The Desired Rate Set is not covered in Operational Rate Set. */ + prStaRec->u2DesiredRateSet = u2OperationalRateSet; + } + + /* Try to set the best initial rate for this entry */ + if (!rateGetBestInitialRateIndex(prStaRec->u2DesiredRateSet, + prStaRec->rRcpi, &prStaRec->ucCurrRate1Index)) { + + if (!rateGetLowestRateIndexFromRateSet(prStaRec->u2DesiredRateSet, &prStaRec->ucCurrRate1Index)) + ASSERT(0); + } + + DBGLOG(JOIN, INFO, "prStaRec->ucCurrRate1Index = %d\n", prStaRec->ucCurrRate1Index); + + /* 4 <4.B> Preamble Mode */ + prStaRec->fgIsShortPreambleOptionEnable = prBssInfo->fgUseShortPreamble; + + /* 4 <4.C> QoS Flag */ + prStaRec->fgIsQoS = prBssInfo->fgIsWmmAssoc; + } +#if DBG + else + ASSERT(0); +#endif /* DBG */ + +/* 4 <5> Update NIC */ + /* 4 <5.A> Update BSSID & Operation Mode */ + nicSetupBSS(prAdapter, prBssInfo); + + /* 4 <5.B> Update WLAN Table. */ + if (nicSetHwBySta(prAdapter, prStaRec) == FALSE) + ASSERT(FALSE); + /* 4 <5.C> Update Desired Rate Set for BT. */ +#if CFG_TX_FRAGMENT + if (prConnSettings->fgIsEnableTxAutoFragmentForBT) + txRateSetInitForBT(prAdapter, prStaRec); +#endif /* CFG_TX_FRAGMENT */ + + /* 4 <5.D> TX AC Parameter and TX/RX Queue Control */ + if (prBssInfo->fgIsWmmAssoc) { + +#if CFG_TX_AGGREGATE_HW_FIFO + nicTxAggregateTXQ(prAdapter, FALSE); +#endif /* CFG_TX_AGGREGATE_HW_FIFO */ + + qosUpdateWMMParametersAndAssignAllowedACI(prAdapter, &prBssInfo->rWmmInfo); + } else { + +#if CFG_TX_AGGREGATE_HW_FIFO + nicTxAggregateTXQ(prAdapter, TRUE); +#endif /* CFG_TX_AGGREGATE_HW_FIFO */ + + nicTxNonQoSAssignDefaultAdmittedTXQ(prAdapter); + + nicTxNonQoSUpdateTXQParameters(prAdapter, prBssInfo->ePhyType); + } + +#if CFG_TX_STOP_WRITE_TX_FIFO_UNTIL_JOIN + { + prTxCtrl->fgBlockTxDuringJoin = FALSE; + +#if !CFG_TX_AGGREGATE_HW_FIFO /* TX FIFO AGGREGATE already do flush once */ + nicTxFlushStopQueues(prAdapter, (UINT_8) TXQ_DATA_MASK, (UINT_8) NULL); +#endif /* CFG_TX_AGGREGATE_HW_FIFO */ + + nicTxRetransmitOfSendWaitQue(prAdapter); + + if (prTxCtrl->fgIsPacketInOsSendQueue) + nicTxRetransmitOfOsSendQue(prAdapter); +#if CFG_SDIO_TX_ENHANCE + halTxLeftClusteredMpdu(prAdapter); +#endif /* CFG_SDIO_TX_ENHANCE */ + + } +#endif /* CFG_TX_STOP_WRITE_TX_FIFO_UNTIL_JOIN */ + +/* 4 <6> Setup CONNECTION flag. */ + prAdapter->eConnectionState = MEDIA_STATE_CONNECTED; + prAdapter->eConnectionStateIndicated = MEDIA_STATE_CONNECTED; + + if (prJoinInfo->fgIsReAssoc) + prAdapter->fgBypassPortCtrlForRoaming = TRUE; + else + prAdapter->fgBypassPortCtrlForRoaming = FALSE; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_CONNECT, (PVOID) NULL, 0); + +} /* end of joinComplete() */ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/scan.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/scan.c new file mode 100644 index 0000000000000..d93b61fc2f3cd --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/scan.c @@ -0,0 +1,3956 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E 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) + +#define RSSI_HI_5GHZ (-60) +#define RSSI_MED_5GHZ (-70) +#define RSSI_LO_5GHZ (-80) + +#define PREF_HI_5GHZ (20) +#define PREF_MED_5GHZ (15) +#define PREF_LO_5GHZ (10) + +INT_32 rssiRangeHi = RSSI_HI_5GHZ; +INT_32 rssiRangeMed = RSSI_MED_5GHZ; +INT_32 rssiRangeLo = RSSI_LO_5GHZ; +UINT_8 pref5GhzHi = PREF_HI_5GHZ; +UINT_8 pref5GhzMed = PREF_MED_5GHZ; +UINT_8 pref5GhzLo = PREF_LO_5GHZ; + +/* +* definition for AP selection algrithm +*/ +#define BSS_FULL_SCORE 100 +#define CHNL_BSS_NUM_THRESOLD 100 +#define BSS_STA_CNT_THRESOLD 30 +#define SCORE_PER_AP 1 +#define ROAMING_NO_SWING_SCORE_STEP 100 +#define HARD_TO_CONNECT_RSSI_THRESOLD -80 +#define MINIMUM_RSSI_2G4 -94 /* Link speed 1Mbps need at least rssi -94dbm for 2.4G */ +#define MINIMUM_RSSI_5G -86 /* Link speed 6Mbps need at least rssi -86dbm for 5G */ +#define RSSI_DIFF_BETWEEN_BSS 10 /* dbm */ +#define LOW_RSSI_FOR_5G_BAND -70 /* dbm */ +#define HIGH_RSSI_FOR_5G_BAND -60 /* dbm */ + +#define WEIGHT_IDX_CHNL_UTIL 2 +#define WEIGHT_IDX_RSSI 2 +#define WEIGHT_IDX_SCN_MISS_CNT 2 +#define WEIGHT_IDX_PROBE_RSP 1 +#define WEIGHT_IDX_CLIENT_CNT 1 +#define WEIGHT_IDX_AP_NUM 2 +#define WEIGHT_IDX_5G_BAND 0 +#define WEIGHT_IDX_BAND_WIDTH 1 +#define WEIGHT_IDX_STBC 1 +#define WEIGHT_IDX_DEAUTH_LAST 4 +#define WEIGHT_IDX_BLACK_LIST 2 +#if CFG_SUPPORT_RSN_SCORE +#define WEIGHT_IDX_RSN 2 +#endif +#define WEIGHT_IDX_SAA 2 + +#define P2P_INDICATE_COMPLETE_BSS_INFO 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 +******************************************************************************** +*/ +struct REF_TSF { + UINT_32 au4Tsf[2]; + OS_SYSTIME rTime; +}; +static struct REF_TSF rTsf; +/******************************************************************************* +* M A 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 WLAN_STATUS + __scanProcessBeaconAndProbeResp(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); +/******************************************************************************* +* 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; + P_ROAM_BSS_DESC_T prRoamBSSDesc; + PUINT_8 pucBSSBuff; + PUINT_8 pucRoamBSSBuff; + UINT_32 i; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + pucBSSBuff = &prScanInfo->aucScanBuffer[0]; + pucRoamBSSBuff = &prScanInfo->aucScanRoamBuffer[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); + kalMemZero((PVOID) pucRoamBSSBuff, SCN_ROAM_MAX_BUFFER_SIZE); + + LINK_INITIALIZE(&prScanInfo->rFreeBSSDescList); + LINK_INITIALIZE(&prScanInfo->rBSSDescList); + LINK_INITIALIZE(&prScanInfo->rRoamFreeBSSDescList); + LINK_INITIALIZE(&prScanInfo->rRoamBSSDescList); + + for (i = 0; i < CFG_MAX_NUM_BSS_LIST; i++) { + + prBSSDesc = (P_BSS_DESC_T) pucBSSBuff; + + LINK_INSERT_TAIL(&prScanInfo->rFreeBSSDescList, &prBSSDesc->rLinkEntry); + + pucBSSBuff += ALIGN_4(sizeof(BSS_DESC_T)); + } + /* Check if the memory allocation consist with this initialization function */ + ASSERT(((ULONG) pucBSSBuff - (ULONG)&prScanInfo->aucScanBuffer[0]) == SCN_MAX_BUFFER_SIZE); + + for (i = 0; i < CFG_MAX_NUM_ROAM_BSS_LIST; i++) { + prRoamBSSDesc = (P_ROAM_BSS_DESC_T) pucRoamBSSBuff; + + LINK_INSERT_TAIL(&prScanInfo->rRoamFreeBSSDescList, &prRoamBSSDesc->rLinkEntry); + + pucRoamBSSBuff += ALIGN_4(sizeof(ROAM_BSS_DESC_T)); + } + ASSERT(((ULONG) pucRoamBSSBuff - (ULONG)&prScanInfo->aucScanRoamBuffer[0]) == SCN_ROAM_MAX_BUFFER_SIZE); + + /* reset freest channel information */ + prScanInfo->fgIsSparseChannelValid = FALSE; + + /* reset NLO state */ + prScanInfo->fgNloScanning = FALSE; + +#if CFG_SUPPORT_SCN_PSCN + prScanInfo->fgPscnOngoing = FALSE; + prScanInfo->fgGScnConfigSet = FALSE; + prScanInfo->fgGScnParamSet = FALSE; + + /* reset postpone Sched Scan Request*/ + prScanInfo->fgIsPostponeSchedScan = FALSE; + + prScanInfo->prPscnParam = kalMemAlloc(sizeof(CMD_SET_PSCAN_PARAM), VIR_MEM_TYPE); + if (!(prScanInfo->prPscnParam)) { + DBGLOG(SCN, ERROR, "Alloc memory for CMD_SET_PSCAN_PARAM fail\n"); + return; + } + kalMemZero(prScanInfo->prPscnParam, sizeof(CMD_SET_PSCAN_PARAM)); + + prScanInfo->eCurrentPSCNState = PSCN_IDLE; +#endif + +#if CFG_SUPPORT_GSCN + prScanInfo->prGscnFullResult = kalMemAlloc(offsetof(PARAM_WIFI_GSCAN_FULL_RESULT, ie_data) + + CFG_IE_BUFFER_SIZE, VIR_MEM_TYPE); + if (!(prScanInfo->prGscnFullResult)) { +#if CFG_SUPPORT_SCN_PSCN + kalMemFree(prScanInfo->prPscnParam, VIR_MEM_TYPE, sizeof(CMD_SET_PSCAN_PARAM)); +#endif + DBGLOG(SCN, ERROR, "Alloc memory for PARAM_WIFI_GSCAN_FULL_RESULT fail\n"); + return; + } + kalMemZero(prScanInfo->prGscnFullResult, + offsetof(PARAM_WIFI_GSCAN_FULL_RESULT, ie_data) + CFG_IE_BUFFER_SIZE); +#endif + + prScanInfo->u4ScanUpdateIdx = 0; +} /* 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); + LINK_INITIALIZE(&prScanInfo->rRoamFreeBSSDescList); + LINK_INITIALIZE(&prScanInfo->rRoamBSSDescList); +#if CFG_SUPPORT_SCN_PSCN + kalMemFree(prScanInfo->prPscnParam, VIR_MEM_TYPE, sizeof(CMD_SET_PSCAN_PARAM)); + + prScanInfo->eCurrentPSCNState = PSCN_IDLE; +#endif + +#if CFG_SUPPORT_GSCN + kalMemFree(prScanInfo->prGscnFullResult, VIR_MEM_TYPE, + offsetof(PARAM_WIFI_GSCAN_FULL_RESULT, ie_data) + CFG_IE_BUFFER_SIZE); +#endif + +} /* end of scnUninit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Find the corresponding BSS Descriptor according to given BSSID +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] aucBSSID Given BSSID. +* +* @return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T scanSearchBssDescByBssid(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]) +{ + return scanSearchBssDescByBssidAndSsid(prAdapter, aucBSSID, FALSE, NULL); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Find the corresponding BSS Descriptor according to given BSSID +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] aucBSSID Given BSSID. +* @param[in] fgCheckSsid Need to check SSID or not. (for multiple SSID with single BSSID cases) +* @param[in] prSsid Specified SSID +* +* @return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T +scanSearchBssDescByBssidAndSsid(IN P_ADAPTER_T prAdapter, + IN UINT_8 aucBSSID[], IN BOOLEAN fgCheckSsid, IN P_PARAM_SSID_T prSsid) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc; + P_BSS_DESC_T prDstBssDesc = (P_BSS_DESC_T) NULL; + + ASSERT(prAdapter); + ASSERT(aucBSSID); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prBSSDescList = &prScanInfo->rBSSDescList; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { + if (fgCheckSsid == FALSE || prSsid == NULL) + return prBssDesc; + + if (EQUAL_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, prSsid->aucSsid, prSsid->u4SsidLen)) { + return prBssDesc; + } else if (prDstBssDesc == NULL && prBssDesc->fgIsHiddenSSID == TRUE) { + prDstBssDesc = prBssDesc; + } else if (prBssDesc->eBSSType == BSS_TYPE_P2P_DEVICE) { + /* 20120206 frog: Equal BSSID but not SSID, SSID not hidden, + * SSID must be updated. + */ + /* 20160823:Permit the scan reusult which there are same BSSID + * but different SSID in what AIS STATE + */ + COPY_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, prSsid->aucSsid, prSsid->u4SsidLen); + return prBssDesc; + } + } + } + + return prDstBssDesc; + +} /* end of scanSearchBssDescByBssid() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Find the corresponding BSS Descriptor according to given Transmitter Address. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] aucSrcAddr Given Source Address(TA). +* +* @return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T scanSearchBssDescByTA(IN P_ADAPTER_T prAdapter, IN UINT_8 aucSrcAddr[]) +{ + return scanSearchBssDescByTAAndSsid(prAdapter, aucSrcAddr, FALSE, NULL); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Find the corresponding BSS Descriptor according to given Transmitter Address. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] aucSrcAddr Given Source Address(TA). +* @param[in] fgCheckSsid Need to check SSID or not. (for multiple SSID with single BSSID cases) +* @param[in] prSsid Specified SSID +* +* @return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T +scanSearchBssDescByTAAndSsid(IN P_ADAPTER_T prAdapter, + IN UINT_8 aucSrcAddr[], IN BOOLEAN fgCheckSsid, IN P_PARAM_SSID_T prSsid) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc; + P_BSS_DESC_T prDstBssDesc = (P_BSS_DESC_T) NULL; + + ASSERT(prAdapter); + ASSERT(aucSrcAddr); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prBSSDescList = &prScanInfo->rBSSDescList; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if (EQUAL_MAC_ADDR(prBssDesc->aucSrcAddr, aucSrcAddr)) { + if (fgCheckSsid == FALSE || prSsid == NULL) + return prBssDesc; + + if (EQUAL_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, prSsid->aucSsid, prSsid->u4SsidLen)) { + return prBssDesc; + } else if (prDstBssDesc == NULL && prBssDesc->fgIsHiddenSSID == TRUE) { + prDstBssDesc = prBssDesc; + } + + } + } + + return prDstBssDesc; + +} /* end of scanSearchBssDescByTA() */ + +#if CFG_SUPPORT_HOTSPOT_2_0 +/*----------------------------------------------------------------------------*/ +/*! +* @brief Find the corresponding BSS Descriptor according to given BSSID +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] aucBSSID Given BSSID. +* @param[in] fgCheckSsid Need to check SSID or not. (for multiple SSID with single BSSID cases) +* @param[in] prSsid Specified SSID +* +* @return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T scanSearchBssDescByBssidAndLatestUpdateTime(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc; + P_BSS_DESC_T prDstBssDesc = (P_BSS_DESC_T) NULL; + OS_SYSTIME rLatestUpdateTime = 0; + + ASSERT(prAdapter); + ASSERT(aucBSSID); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prBSSDescList = &prScanInfo->rBSSDescList; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { + if (!rLatestUpdateTime || CHECK_FOR_EXPIRATION(prBssDesc->rUpdateTime, rLatestUpdateTime)) { + prDstBssDesc = prBssDesc; + COPY_SYSTIME(rLatestUpdateTime, prBssDesc->rUpdateTime); + } + } + } + + return prDstBssDesc; + +} /* end of scanSearchBssDescByBssid() */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Find the corresponding BSS Descriptor according to +* given eBSSType, BSSID and Transmitter Address +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] eBSSType BSS Type of incoming Beacon/ProbeResp frame. +* @param[in] aucBSSID Given BSSID of Beacon/ProbeResp frame. +* @param[in] aucSrcAddr Given source address (TA) of Beacon/ProbeResp frame. +* +* @return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T +scanSearchExistingBssDesc(IN P_ADAPTER_T prAdapter, + IN ENUM_BSS_TYPE_T eBSSType, IN UINT_8 aucBSSID[], IN UINT_8 aucSrcAddr[]) +{ + return scanSearchExistingBssDescWithSsid(prAdapter, eBSSType, aucBSSID, aucSrcAddr, FALSE, NULL); +} + +VOID scanRemoveRoamBssDescsByTime(IN P_ADAPTER_T prAdapter, IN UINT_32 u4RemoveTime) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prRoamBSSDescList; + P_LINK_T prRoamFreeBSSDescList; + P_ROAM_BSS_DESC_T prRoamBssDesc; + P_ROAM_BSS_DESC_T prRoamBSSDescNext; + OS_SYSTIME rCurrentTime; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prRoamBSSDescList = &prScanInfo->rRoamBSSDescList; + prRoamFreeBSSDescList = &prScanInfo->rRoamFreeBSSDescList; + + GET_CURRENT_SYSTIME(&rCurrentTime); + + LINK_FOR_EACH_ENTRY_SAFE(prRoamBssDesc, prRoamBSSDescNext, prRoamBSSDescList, rLinkEntry, + ROAM_BSS_DESC_T) { + + if (CHECK_FOR_TIMEOUT(rCurrentTime, prRoamBssDesc->rUpdateTime, + SEC_TO_SYSTIME(u4RemoveTime))) { + + LINK_REMOVE_KNOWN_ENTRY(prRoamBSSDescList, prRoamBssDesc); + LINK_INSERT_TAIL(prRoamFreeBSSDescList, &prRoamBssDesc->rLinkEntry); + } + } +} + +P_ROAM_BSS_DESC_T +scanSearchRoamBssDescBySsid(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prRoamBSSDescList; + P_ROAM_BSS_DESC_T prRoamBssDesc; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prRoamBSSDescList = &prScanInfo->rRoamBSSDescList; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prRoamBssDesc, prRoamBSSDescList, rLinkEntry, ROAM_BSS_DESC_T) { + if (EQUAL_SSID(prRoamBssDesc->aucSSID, prRoamBssDesc->ucSSIDLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen)) { + return prRoamBssDesc; + } + } + + return NULL; +} + +P_ROAM_BSS_DESC_T scanAllocateRoamBssDesc(IN P_ADAPTER_T prAdapter) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prRoamFreeBSSDescList; + P_ROAM_BSS_DESC_T prRoamBssDesc = NULL; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prRoamFreeBSSDescList = &prScanInfo->rRoamFreeBSSDescList; + + LINK_REMOVE_HEAD(prRoamFreeBSSDescList, prRoamBssDesc, P_ROAM_BSS_DESC_T); + + if (prRoamBssDesc) { + P_LINK_T prRoamBSSDescList; + + kalMemZero(prRoamBssDesc, sizeof(ROAM_BSS_DESC_T)); + + prRoamBSSDescList = &prScanInfo->rRoamBSSDescList; + + LINK_INSERT_HEAD(prRoamBSSDescList, &prRoamBssDesc->rLinkEntry); + } + + return prRoamBssDesc; +} + +VOID scanAddToRoamBssDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) +{ + P_ROAM_BSS_DESC_T prRoamBssDesc; + + prRoamBssDesc = scanSearchRoamBssDescBySsid(prAdapter, prBssDesc); + + if (prRoamBssDesc == NULL) { + UINT_32 u4RemoveTime = REMOVE_TIMEOUT_TWO_DAY; + + do { + prRoamBssDesc = scanAllocateRoamBssDesc(prAdapter); + if (prRoamBssDesc) + break; + scanRemoveRoamBssDescsByTime(prAdapter, u4RemoveTime); + u4RemoveTime = u4RemoveTime / 2; + } while (u4RemoveTime > 0); + + if (prRoamBssDesc != NULL) { + COPY_SSID(prRoamBssDesc->aucSSID, prRoamBssDesc->ucSSIDLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + } + } + if (prRoamBssDesc != NULL) + GET_CURRENT_SYSTIME(&prRoamBssDesc->rUpdateTime); +} + +VOID scanSearchBssDescOfRoamSsid(IN P_ADAPTER_T prAdapter) +{ +#define SSID_ONLY_EXIST_ONE_AP 1 /* If only exist one same ssid AP, avoid unnecessary scan */ + + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc; + P_BSS_INFO_T prAisBssInfo; + UINT_32 u4SameSSIDCount = 0; + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + + if (prAisBssInfo->eConnectionState != PARAM_MEDIA_STATE_CONNECTED) + return; + + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + if (EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, + prAisBssInfo->aucSSID, prAisBssInfo->ucSSIDLen)) { + u4SameSSIDCount++; + if (u4SameSSIDCount > SSID_ONLY_EXIST_ONE_AP) { + scanAddToRoamBssDesc(prAdapter, prBssDesc); + break; + } + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Find the corresponding BSS Descriptor according to +* given eBSSType, BSSID and Transmitter Address +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] eBSSType BSS Type of incoming Beacon/ProbeResp frame. +* @param[in] aucBSSID Given BSSID of Beacon/ProbeResp frame. +* @param[in] aucSrcAddr Given source address (TA) of Beacon/ProbeResp frame. +* @param[in] fgCheckSsid Need to check SSID or not. (for multiple SSID with single BSSID cases) +* @param[in] prSsid Specified SSID +* +* @return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T +scanSearchExistingBssDescWithSsid(IN P_ADAPTER_T prAdapter, + IN ENUM_BSS_TYPE_T eBSSType, + IN UINT_8 aucBSSID[], + IN UINT_8 aucSrcAddr[], IN BOOLEAN fgCheckSsid, IN P_PARAM_SSID_T prSsid) +{ + P_SCAN_INFO_T prScanInfo; + P_BSS_DESC_T prBssDesc, prIBSSBssDesc; + P_LINK_T prBSSDescList; + P_LINK_T prFreeBSSDescList; + + + ASSERT(prAdapter); + ASSERT(aucSrcAddr); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + if ((eBSSType == BSS_TYPE_P2P_DEVICE) || (eBSSType == BSS_TYPE_INFRASTRUCTURE) || + (eBSSType == BSS_TYPE_BOW_DEVICE)) { + + if (eBSSType == BSS_TYPE_P2P_DEVICE) + fgCheckSsid = FALSE; + + if (eBSSType != BSS_TYPE_BOW_DEVICE) + scanSearchBssDescOfRoamSsid(prAdapter); + + prBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, aucBSSID, fgCheckSsid, prSsid); + + return prBssDesc; + + } else if (eBSSType == BSS_TYPE_IBSS) { + prIBSSBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, aucBSSID, fgCheckSsid, prSsid); + prBssDesc = scanSearchBssDescByTAAndSsid(prAdapter, aucSrcAddr, fgCheckSsid, prSsid); + + /* NOTE(Kevin): + * Rules to maintain the SCAN Result: + * For AdHoc - + * CASE I We have TA1(BSSID1), but it change its BSSID to BSSID2 + * -> Update TA1 entry's BSSID. + * CASE II We have TA1(BSSID1), and get TA1(BSSID1) again + * -> Update TA1 entry's contain. + * CASE III We have a SCAN result TA1(BSSID1), and TA2(BSSID2). Sooner or + * later, TA2 merge into TA1, we get TA2(BSSID1) + * -> Remove TA2 first and then replace TA1 entry's TA with TA2, + * Still have only one entry of BSSID. + * CASE IV We have a SCAN result TA1(BSSID1), and another TA2 also merge into BSSID1. + * -> Replace TA1 entry's TA with TA2, Still have only one entry. + * CASE V New IBSS + * -> Add this one to SCAN result. + */ + if (prBssDesc) { + if ((!prIBSSBssDesc) || /* CASE I */ + (prBssDesc == prIBSSBssDesc)) { /* CASE II */ + + return prBssDesc; + } /* CASE III */ + + prBSSDescList = &prScanInfo->rBSSDescList; + prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; + + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); + + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); + + return prIBSSBssDesc; + } + + if (prIBSSBssDesc) { /* CASE IV */ + return prIBSSBssDesc; + } + /* reture NULL CASE V */ + } + + 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; + P_LINK_T prEssList = &prAdapter->rWifiVar.rAisSpecificBssInfo.rCurEssLink; + + ASSERT(prAdapter); + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; + + /* DBGLOG(SCN, TRACE, ("Before Remove - Number Of SCAN Result = %ld\n", */ + /* prBSSDescList->u4NumElem)); */ + + if (u4RemovePolicy & SCN_RM_POLICY_TIMEOUT) { + P_BSS_DESC_T prBSSDescNext; + OS_SYSTIME rCurrentTime; + + GET_CURRENT_SYSTIME(&rCurrentTime); + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) && + (prBssDesc->fgIsConnected || prBssDesc->fgIsConnecting)) { + /* Don't remove the one currently we are connected. */ + continue; + } + + if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, + SEC_TO_SYSTIME(SCN_BSS_DESC_REMOVE_TIMEOUT_SEC))) { + + /* + * DBGLOG(SCN, TRACE, ("Remove TIMEOUT BSS DESC(%#x): + * MAC: %pM, Current Time = %08lx, Update Time = %08lx\n", + */ + /* prBssDesc, prBssDesc->aucBSSID, rCurrentTime, prBssDesc->rUpdateTime)); */ + if (!prBssDesc->prBlack) + aisQueryBlackList(prAdapter, prBssDesc); + if (prBssDesc->prBlack) + prBssDesc->prBlack->u4DisapperTime = (UINT_32)kalGetBootTime(); + + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); + /* Remove this BSS Desc from the Ess Desc List */ + if (LINK_ENTRY_IS_VALID(&prBssDesc->rLinkEntryEss)) + LINK_REMOVE_KNOWN_ENTRY(prEssList, &prBssDesc->rLinkEntryEss); + + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); + } + } + } else if (u4RemovePolicy & SCN_RM_POLICY_OLDEST_HIDDEN) { + P_BSS_DESC_T prBssDescOldest = (P_BSS_DESC_T) NULL; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) && + (prBssDesc->fgIsConnected || prBssDesc->fgIsConnecting)) { + /* Don't remove the one currently we are connected. */ + continue; + } + + if (!prBssDesc->fgIsHiddenSSID) + continue; + + if (!prBssDescOldest) { /* 1st element */ + prBssDescOldest = prBssDesc; + continue; + } + + if (TIME_BEFORE(prBssDesc->rUpdateTime, prBssDescOldest->rUpdateTime)) + prBssDescOldest = prBssDesc; + } + + if (prBssDescOldest) { + + /* + * DBGLOG(SCN, TRACE, ("Remove OLDEST HIDDEN BSS DESC(%#x): + * MAC: %pM, Update Time = %08lx\n", + */ + /* prBssDescOldest, prBssDescOldest->aucBSSID, prBssDescOldest->rUpdateTime)); */ + + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDescOldest); + + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDescOldest->rLinkEntry); + } + } else if (u4RemovePolicy & SCN_RM_POLICY_SMART_WEAKEST) { + P_BSS_DESC_T prBssDescWeakest = (P_BSS_DESC_T) NULL; + P_BSS_DESC_T prBssDescWeakestSameSSID = (P_BSS_DESC_T) NULL; + UINT_32 u4SameSSIDCount = 0; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) && + (prBssDesc->fgIsConnected || prBssDesc->fgIsConnecting)) { + /* Don't remove the one currently we are connected. */ + continue; + } + + if ((!prBssDesc->fgIsHiddenSSID) && + (EQUAL_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, prConnSettings->aucSSID, prConnSettings->ucSSIDLen))) { + u4SameSSIDCount++; + + if (!prBssDescWeakestSameSSID) + prBssDescWeakestSameSSID = prBssDesc; + else if (prBssDesc->ucRCPI < prBssDescWeakestSameSSID->ucRCPI) + prBssDescWeakestSameSSID = prBssDesc; + if (u4SameSSIDCount < SCN_BSS_DESC_SAME_SSID_THRESHOLD) + continue; + } + + if (!prBssDescWeakest) { /* 1st element */ + prBssDescWeakest = prBssDesc; + continue; + } + + if (prBssDesc->ucRCPI < prBssDescWeakest->ucRCPI) + prBssDescWeakest = prBssDesc; + + } + if ((u4SameSSIDCount >= SCN_BSS_DESC_SAME_SSID_THRESHOLD) && (prBssDescWeakestSameSSID)) + prBssDescWeakest = prBssDescWeakestSameSSID; + + if (prBssDescWeakest) { + + /* DBGLOG(SCN, TRACE, ("Remove WEAKEST BSS DESC(%#x): MAC: %pM, Update Time = %08lx\n", */ + /* prBssDescOldest, prBssDescOldest->aucBSSID, prBssDescOldest->rUpdateTime)); */ + if (!prBssDescWeakest->prBlack) + aisQueryBlackList(prAdapter, prBssDescWeakest); + if (prBssDescWeakest->prBlack) + prBssDescWeakest->prBlack->u4DisapperTime = (UINT_32)kalGetBootTime(); + + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDescWeakest); + /* Remove this BSS Desc from the Ess Desc List */ + if (LINK_ENTRY_IS_VALID(&prBssDescWeakest->rLinkEntryEss)) + LINK_REMOVE_KNOWN_ENTRY(prEssList, &prBssDescWeakest->rLinkEntryEss); + + /* 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; + UINT_32 u4Current = (UINT_32)kalGetBootTime(); + + 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 (!prBssDesc->prBlack) + aisQueryBlackList(prAdapter, prBssDesc); + if (prBssDesc->prBlack) + prBssDesc->prBlack->u4DisapperTime = u4Current; + + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); + /* Remove this BSS Desc from the Ess Desc List */ + if (LINK_ENTRY_IS_VALID(&prBssDesc->rLinkEntryEss)) + LINK_REMOVE_KNOWN_ENTRY(prEssList, &prBssDesc->rLinkEntryEss); + + /* 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; + P_LINK_T prEssList = NULL; + + ASSERT(prAdapter); + ASSERT(aucBSSID); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; + prEssList = &prAdapter->rWifiVar.rAisSpecificBssInfo.rCurEssLink; + + /* 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)) { + if (!prBssDesc->prBlack) + aisQueryBlackList(prAdapter, prBssDesc); + if (prBssDesc->prBlack) + prBssDesc->prBlack->u4DisapperTime = (UINT_32)kalGetBootTime(); + + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); + /* Remove this BSS Desc from the Ess Desc List */ + if (LINK_ENTRY_IS_VALID(&prBssDesc->rLinkEntryEss)) + LINK_REMOVE_KNOWN_ENTRY(prEssList, &prBssDesc->rLinkEntryEss); + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); + + /* BSSID is not unique, so need to traverse whols link-list */ + } + } + +} /* end of scanRemoveBssDescByBssid() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Delete BSS Descriptors from current list according to given band configuration +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] eBand Given band +* @param[in] eNetTypeIndex AIS - Remove IBSS/Infrastructure BSS +* BOW - Remove BOW BSS +* P2P - Remove P2P BSS +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +scanRemoveBssDescByBandAndNetwork(IN P_ADAPTER_T prAdapter, + IN ENUM_BAND_T eBand, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_LINK_T prFreeBSSDescList; + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; + P_BSS_DESC_T prBSSDescNext; + BOOLEAN fgToRemove; + + ASSERT(prAdapter); + ASSERT(eBand <= BAND_NUM); + ASSERT(eNetTypeIndex <= NETWORK_TYPE_INDEX_NUM); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; + + if (eBand == BAND_NULL) + return; /* no need to do anything, keep all scan result */ + + /* Check if such BSS Descriptor exists in a valid list */ + LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) { + fgToRemove = FALSE; + + if (prBssDesc->eBand == eBand) { + switch (eNetTypeIndex) { + case NETWORK_TYPE_AIS_INDEX: + if ((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) + || (prBssDesc->eBSSType == BSS_TYPE_IBSS)) { + fgToRemove = TRUE; + } + break; + + case NETWORK_TYPE_P2P_INDEX: + if (prBssDesc->eBSSType == BSS_TYPE_P2P_DEVICE) + fgToRemove = TRUE; + break; + + case NETWORK_TYPE_BOW_INDEX: + if (prBssDesc->eBSSType == BSS_TYPE_BOW_DEVICE) + fgToRemove = TRUE; + break; + + default: + ASSERT(0); + break; + } + } + + if (fgToRemove == TRUE) { + P_LINK_T prEssList = &prAdapter->rWifiVar.rAisSpecificBssInfo.rCurEssLink; + + if (!prBssDesc->prBlack) + aisQueryBlackList(prAdapter, prBssDesc); + if (prBssDesc->prBlack) + prBssDesc->prBlack->u4DisapperTime = (UINT_32)kalGetBootTime(); + + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); + /* Remove this BSS Desc from the Ess Desc List */ + if (LINK_ENTRY_IS_VALID(&prBssDesc->rLinkEntryEss)) + LINK_REMOVE_KNOWN_ENTRY(prEssList, &prBssDesc->rLinkEntryEss); + + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); + } + } + +} /* end of scanRemoveBssDescByBand() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Clear the CONNECTION FLAG of a specified BSS Descriptor. +* +* @param[in] aucBSSID Given BSSID. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID scanRemoveConnFlagOfBssDescByBssid(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; + + ASSERT(prAdapter); + ASSERT(aucBSSID); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { + prBssDesc->fgIsConnected = FALSE; + prBssDesc->fgIsConnecting = FALSE; + + /* BSSID is not unique, so need to traverse whols link-list */ + } + } + + return; + +} /* end of scanRemoveConnectionFlagOfBssDescByBssid() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Allocate new BSS_DESC_T +* +* @param[in] prAdapter Pointer to the Adapter structure. +* +* @return Pointer to BSS Descriptor, if has free space. NULL, if has no space. +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T scanAllocateBssDesc(IN P_ADAPTER_T prAdapter) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prFreeBSSDescList; + P_BSS_DESC_T prBssDesc; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; + + LINK_REMOVE_HEAD(prFreeBSSDescList, prBssDesc, P_BSS_DESC_T); + + if (prBssDesc) { + P_LINK_T prBSSDescList; + + kalMemZero(prBssDesc, sizeof(BSS_DESC_T)); + +#if CFG_ENABLE_WIFI_DIRECT + LINK_INITIALIZE(&(prBssDesc->rP2pDeviceList)); + prBssDesc->fgIsP2PPresent = FALSE; +#endif /* CFG_ENABLE_WIFI_DIRECT */ + + prBSSDescList = &prScanInfo->rBSSDescList; + + /* NOTE(Kevin): In current design, this new empty BSS_DESC_T will be + * inserted to BSSDescList immediately. + */ + LINK_INSERT_TAIL(prBSSDescList, &prBssDesc->rLinkEntry); + } + + return prBssDesc; + +} /* end of scanAllocateBssDesc() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This API parses Beacon/ProbeResp frame and insert extracted BSS_DESC_T +* with IEs into prAdapter->rWifiVar.rScanInfo.aucScanBuffer +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to the receiving frame buffer. +* +* @return Pointer to BSS Descriptor +* NULL if the Beacon/ProbeResp frame is invalid +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T scanAddToBssDesc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_BSS_DESC_T prBssDesc = NULL; + UINT_16 u2CapInfo; + ENUM_BSS_TYPE_T eBSSType = BSS_TYPE_INFRASTRUCTURE; + + PUINT_8 pucIE; + UINT_16 u2IELength; + UINT_16 u2Offset = 0; + + P_WLAN_BEACON_FRAME_T prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T) NULL; + P_IE_SSID_T prIeSsid = (P_IE_SSID_T) NULL; + P_IE_SUPPORTED_RATE_T prIeSupportedRate = (P_IE_SUPPORTED_RATE_T) NULL; + P_IE_EXT_SUPPORTED_RATE_T prIeExtSupportedRate = (P_IE_EXT_SUPPORTED_RATE_T) NULL; + P_HIF_RX_HEADER_T prHifRxHdr; + UINT_8 ucHwChannelNum = 0; + UINT_8 ucIeDsChannelNum = 0; + UINT_8 ucIeHtChannelNum = 0; + ENUM_CHNL_EXT_T eSco = CHNL_EXT_SCN; + BOOLEAN fgIsValidSsid = FALSE; + PARAM_SSID_T rSsid; + UINT_64 u8Timestamp; + BOOLEAN fgIsNewBssDesc = FALSE; + + UINT_32 i; + UINT_8 ucSSIDChar; + + UINT_8 ucOuiType; + UINT_16 u2SubTypeVersion; + UINT_8 ucPowerConstraint = 0; + P_IE_COUNTRY_T prCountryIE = NULL; + ENUM_BAND_T eHwBand = BAND_NULL; + BOOLEAN fgBandMismatch = FALSE; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + eHwBand = HIF_RX_HDR_GET_RF_BAND(prSwRfb->prHifRxHdr); + prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T) prSwRfb->pvHeader; + + WLAN_GET_FIELD_16(&prWlanBeaconFrame->u2CapInfo, &u2CapInfo); + WLAN_GET_FIELD_64(&prWlanBeaconFrame->au4Timestamp[0], &u8Timestamp); + + /* decide BSS type */ + switch (u2CapInfo & CAP_INFO_BSS_TYPE) { + case CAP_INFO_ESS: + /* It can also be Group Owner of P2P Group. */ + eBSSType = BSS_TYPE_INFRASTRUCTURE; + break; + + case CAP_INFO_IBSS: + eBSSType = BSS_TYPE_IBSS; + break; + case 0: + /* + * The P2P Device shall set the ESS bit of the Capabilities field + * in the Probe Response fame to 0 and IBSS bit to 0. (3.1.2.1.1) + */ + eBSSType = BSS_TYPE_P2P_DEVICE; + break; + +#if CFG_ENABLE_BT_OVER_WIFI + /* @TODO: add rule to identify BOW beacons */ +#endif + + default: + DBGLOG(SCN, ERROR, "wrong bss type %d\n", (INT_32)(u2CapInfo & CAP_INFO_BSS_TYPE)); + return NULL; + } + + /* 4 <1.1> Pre-parse SSID IE and channel info */ + pucIE = prWlanBeaconFrame->aucInfoElem; + u2IELength = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - + (UINT_16) OFFSET_OF(WLAN_BEACON_FRAME_BODY_T, aucInfoElem[0]); + + if (u2IELength > CFG_IE_BUFFER_SIZE) + u2IELength = CFG_IE_BUFFER_SIZE; + kalMemZero(&rSsid, sizeof(rSsid)); + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_SSID: + if (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID) { + ucSSIDChar = '\0'; + + /* D-Link DWL-900AP+ */ + if (IE_LEN(pucIE) == 0) + fgIsValidSsid = FALSE; + /* Cisco AP1230A - (IE_LEN(pucIE) == 1) && (SSID_IE(pucIE)->aucSSID[0] == '\0') */ + /* + * Linksys WRK54G/WL520g - (IE_LEN(pucIE) == n) && + * (SSID_IE(pucIE)->aucSSID[0~(n-1)] == '\0') + */ + else { + for (i = 0; i < IE_LEN(pucIE); i++) + ucSSIDChar |= SSID_IE(pucIE)->aucSSID[i]; + + if (ucSSIDChar) + fgIsValidSsid = TRUE; + } + + /* Update SSID to BSS Descriptor only if SSID is not hidden. */ + if (fgIsValidSsid == TRUE) { + COPY_SSID(rSsid.aucSsid, + rSsid.u4SsidLen, SSID_IE(pucIE)->aucSSID, SSID_IE(pucIE)->ucLength); + } + } + 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_HT_OP: + if (IE_LEN(pucIE) == (sizeof(IE_HT_OP_T) - 2)) + ucIeHtChannelNum = ((P_IE_HT_OP_T) pucIE)->ucPrimaryChannel; + break; + default: + break; + } + } + + /** + * Set band mismatch flag if we receive Beacon/ProbeResp in 2.4G band, + * but the channel num in IE info is 5G, and vice versa + * We can get channel num from different IE info, we select + * ELEM_ID_DS_PARAM_SET first, and then ELEM_ID_HT_OP + * If we don't have any channel info, we set it as HW channel, which is + * the channel we get this Beacon/ProbeResp from. + */ + if (ucIeDsChannelNum > 0) { + if (ucIeDsChannelNum <= HW_CHNL_NUM_MAX_2G4) + fgBandMismatch = (eHwBand != BAND_2G4); + else if (ucIeDsChannelNum < HW_CHNL_NUM_MAX_4G_5G) + fgBandMismatch = (eHwBand != BAND_5G); + } else if (ucIeHtChannelNum > 0) { + if (ucIeHtChannelNum <= HW_CHNL_NUM_MAX_2G4) + fgBandMismatch = (eHwBand != BAND_2G4); + else if (ucIeHtChannelNum < HW_CHNL_NUM_MAX_4G_5G) + fgBandMismatch = (eHwBand != BAND_5G); + } + + if (fgBandMismatch) { + DBGLOG(SCN, INFO, "%pM Band mismatch, HW band %d, DS chnl %d, HT chnl %d\n", + prWlanBeaconFrame->aucBSSID, eHwBand, ucIeDsChannelNum, ucIeHtChannelNum); + return NULL; + } + if (fgIsValidSsid) + DBGLOG(SCN, EVENT, "%s %pM channel %d\n", rSsid.aucSsid, prWlanBeaconFrame->aucBSSID, + HIF_RX_HDR_GET_CHNL_NUM(prSwRfb->prHifRxHdr)); + else + DBGLOG(SCN, EVENT, "hidden ssid, %pM channel %d\n", + HIDE(prWlanBeaconFrame->aucBSSID), + HIF_RX_HDR_GET_CHNL_NUM(prSwRfb->prHifRxHdr)); + /* 4 <1.2> Replace existing BSS_DESC_T or allocate a new one */ + prBssDesc = scanSearchExistingBssDescWithSsid(prAdapter, + eBSSType, + (PUINT_8) prWlanBeaconFrame->aucBSSID, + (PUINT_8) prWlanBeaconFrame->aucSrcAddr, + fgIsValidSsid, fgIsValidSsid == TRUE ? &rSsid : NULL); + + if (prBssDesc == (P_BSS_DESC_T) NULL) { + fgIsNewBssDesc = TRUE; + + do { + /* check if it is a beacon frame */ + if (((prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_BEACON) && + !fgIsValidSsid) { + DBGLOG(SCN, TRACE, "scanAddToBssDescssid is NULL Beacon, don't add hidden BSS(%pM)\n", + (PUINT_8)prWlanBeaconFrame->aucBSSID); + return NULL; + } + /* 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 | + SCN_RM_POLICY_TIMEOUT)); + + /* 4 <1.2.3> Second tail of allocation */ + prBssDesc = scanAllocateBssDesc(prAdapter); + if (prBssDesc) + break; + /* 4 <1.2.4> Remove the weakest one */ + /* If there are more than half of BSS which has the same ssid as connection + * setting, remove the weakest one from them. + * Else remove the weakest one. + */ + scanRemoveBssDescsByPolicy(prAdapter, + (SCN_RM_POLICY_EXCLUDE_CONNECTED | SCN_RM_POLICY_SMART_WEAKEST)); + + /* 4 <1.2.5> reallocation */ + prBssDesc = scanAllocateBssDesc(prAdapter); + if (prBssDesc) + break; + /* 4 <1.2.6> no space, should not happen */ + DBGLOG(SCN, ERROR, "no bss desc available after remove policy\n"); + return NULL; + + } while (FALSE); + + } else { + OS_SYSTIME rCurrentTime; + + /* WCXRP00000091 */ + /* if the received strength is much weaker than the original one, */ + /* ignore it due to it might be received on the folding frequency */ + + GET_CURRENT_SYSTIME(&rCurrentTime); + + if (prBssDesc->eBSSType != eBSSType) { + prBssDesc->eBSSType = eBSSType; + } else if (HIF_RX_HDR_GET_CHNL_NUM(prSwRfb->prHifRxHdr) != prBssDesc->ucChannelNum && + prBssDesc->ucRCPI > prSwRfb->prHifRxHdr->ucRcpi) { + /* for signal strength is too much weaker and previous beacon is not stale */ + if ((prBssDesc->ucRCPI - prSwRfb->prHifRxHdr->ucRcpi) >= REPLICATED_BEACON_STRENGTH_THRESHOLD && + (rCurrentTime - prBssDesc->rUpdateTime) <= REPLICATED_BEACON_FRESH_PERIOD) { + DBGLOG(SCN, EVENT, "rssi is too much weaker and previous one is fresh\n"); + return prBssDesc; + } + /* for received beacons too close in time domain */ + else if (rCurrentTime - prBssDesc->rUpdateTime <= REPLICATED_BEACON_TIME_THRESHOLD) { + DBGLOG(SCN, EVENT, "receive beacon/probe reponses too close\n"); + return prBssDesc; + } + } + + /* if Timestamp has been reset, re-generate BSS DESC 'cause AP should have reset itself */ + if (prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE && u8Timestamp < prBssDesc->u8TimeStamp.QuadPart) { + BOOLEAN fgIsConnected, fgIsConnecting; + + /* set flag for indicating this is a new BSS-DESC */ + fgIsNewBssDesc = TRUE; + + /* backup 2 flags for APs which reset timestamp unexpectedly */ + fgIsConnected = prBssDesc->fgIsConnected; + fgIsConnecting = prBssDesc->fgIsConnecting; + scanRemoveBssDescByBssid(prAdapter, prBssDesc->aucBSSID); + + prBssDesc = scanAllocateBssDesc(prAdapter); + if (!prBssDesc) + return NULL; + + /* restore */ + prBssDesc->fgIsConnected = fgIsConnected; + prBssDesc->fgIsConnecting = fgIsConnecting; + } + } + + prBssDesc->fgIsValidSSID = fgIsValidSsid; + + prBssDesc->u2RawLength = prSwRfb->u2PacketLen; + if (prBssDesc->u2RawLength > CFG_RAW_BUFFER_SIZE) + prBssDesc->u2RawLength = CFG_RAW_BUFFER_SIZE; + if (fgIsValidSsid || + ((prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_PROBE_RSP)) + kalMemCopy(prBssDesc->aucRawBuf, prWlanBeaconFrame, prBssDesc->u2RawLength); + + /* NOTE: Keep consistency of Scan Record during JOIN process */ + if ((fgIsNewBssDesc == FALSE) && prBssDesc->fgIsConnecting) { + DBGLOG(SCN, INFO, "we're connecting this BSS(%pM) now, don't update it\n", + prBssDesc->aucBSSID); + return prBssDesc; + } + /* 4 <2> Get information from Fixed Fields */ + prBssDesc->eBSSType = eBSSType; /* Update the latest BSS type information. */ + + COPY_MAC_ADDR(prBssDesc->aucSrcAddr, prWlanBeaconFrame->aucSrcAddr); + + COPY_MAC_ADDR(prBssDesc->aucBSSID, prWlanBeaconFrame->aucBSSID); + + prBssDesc->u8TimeStamp.QuadPart = u8Timestamp; + + WLAN_GET_FIELD_16(&prWlanBeaconFrame->u2BeaconInterval, &prBssDesc->u2BeaconInterval); + + prBssDesc->u2CapInfo = u2CapInfo; + + /* 4 <2.1> Retrieve IEs for later parsing */ + u2IELength = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - + (UINT_16) OFFSET_OF(WLAN_BEACON_FRAME_BODY_T, aucInfoElem[0]); + + if (u2IELength > CFG_IE_BUFFER_SIZE) { + u2IELength = CFG_IE_BUFFER_SIZE; + prBssDesc->fgIsIEOverflow = TRUE; + } else { + prBssDesc->fgIsIEOverflow = FALSE; + } + prBssDesc->u2IELength = u2IELength; + + if (fgIsValidSsid || + ((prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_PROBE_RSP)) + 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 +#if CFG_SUPPORT_DETECT_ATHEROS_AP + prBssDesc->fgIsAtherosAP = FALSE; +#endif + prBssDesc->fgExsitBssLoadIE = FALSE; + prBssDesc->fgMultiAnttenaAndSTBC = FALSE; +#if CFG_SUPPORT_ROAMING_RETRY + prBssDesc->fgIsRoamFail = FALSE; +#endif + /* 4 <3.1> Full IE parsing on SW_RFB_T */ + pucIE = prWlanBeaconFrame->aucInfoElem; + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + + switch (IE_ID(pucIE)) { + case ELEM_ID_SSID: + if ((!prIeSsid) && /* NOTE(Kevin): for Atheros IOT #1 */ + (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) { + BOOLEAN fgIsHiddenSSID = FALSE; + + ucSSIDChar = '\0'; + + prIeSsid = (P_IE_SSID_T) pucIE; + + /* D-Link DWL-900AP+ */ + if (IE_LEN(pucIE) == 0) + fgIsHiddenSSID = TRUE; + /* Cisco AP1230A - (IE_LEN(pucIE) == 1) && (SSID_IE(pucIE)->aucSSID[0] == '\0') */ + /* + * Linksys WRK54G/WL520g - (IE_LEN(pucIE) == n) && + * (SSID_IE(pucIE)->aucSSID[0~(n-1)] == '\0') + */ + else { + for (i = 0; i < IE_LEN(pucIE); i++) + ucSSIDChar |= SSID_IE(pucIE)->aucSSID[i]; + + if (!ucSSIDChar) + fgIsHiddenSSID = TRUE; + } + + /* Update SSID to BSS Descriptor only if SSID is not hidden. */ + if (!fgIsHiddenSSID) { + COPY_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, + SSID_IE(pucIE)->aucSSID, SSID_IE(pucIE)->ucLength); + } else if ((prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_PROBE_RSP) { + /* SSID should be updated if it is ProbeResp */ + kalMemZero(prBssDesc->aucSSID, sizeof(prBssDesc->aucSSID)); + prBssDesc->ucSSIDLen = 0; + } +#if 0 + /* + * After we connect to a hidden SSID, prBssDesc->aucSSID[] will + * not be empty and prBssDesc->ucSSIDLen will not be 0, + * so maybe we need to empty prBssDesc->aucSSID[] and set + * prBssDesc->ucSSIDLen to 0 in prBssDesc to avoid that + * UI still displays hidden SSID AP in scan list after + * we disconnect the hidden SSID AP. + */ + else { + prBssDesc->aucSSID[0] = '\0'; + prBssDesc->ucSSIDLen = 0; + } +#endif + + } + break; + + case ELEM_ID_SUP_RATES: + /* + * NOTE(Kevin): Buffalo WHR-G54S's supported rate set IE exceed 8. + * IE_LEN(pucIE) == 12, "1(B), 2(B), 5.5(B), 6(B), 9(B), 11(B), + * 12(B), 18(B), 24(B), 36(B), 48(B), 54(B)" + */ + /* TP-LINK will set extra and incorrect ie with ELEM_ID_SUP_RATES */ + if ((!prIeSupportedRate) && (IE_LEN(pucIE) <= RATE_NUM)) + prIeSupportedRate = SUP_RATES_IE(pucIE); + break; + + case ELEM_ID_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; + /* CFG_SUPPORT_802_11D */ + case ELEM_ID_COUNTRY_INFO: + prCountryIE = (P_IE_COUNTRY_T) pucIE; + break; + + 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 (CFG_REFACTORY_PMKSA == 0) + if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) +#endif + rsnCheckPmkidCache(prAdapter, prBssDesc); + } + break; +#endif + + case ELEM_ID_HT_CAP: + { + P_IE_HT_CAP_T prHtCap = (P_IE_HT_CAP_T)pucIE; + UINT_8 ucSpatial = 0; + UINT_8 i = 0; + + prBssDesc->fgIsHTPresent = TRUE; + if (prBssDesc->fgMultiAnttenaAndSTBC) + break; + for (; i < 4; i++) { + if (prHtCap->rSupMcsSet.aucRxMcsBitmask[i] > 0) + ucSpatial++; + } + prBssDesc->fgMultiAnttenaAndSTBC = + ((ucSpatial > 1) && (prHtCap->u2HtCapInfo & HT_CAP_INFO_TX_STBC)); + break; + } + case ELEM_ID_HT_OP: + if (IE_LEN(pucIE) != (sizeof(IE_HT_OP_T) - 2)) + break; + + eSco = (ENUM_CHNL_EXT_T) + (((P_IE_HT_OP_T) pucIE)->ucInfo1 & HT_OP_INFO1_SCO); + break; + +#if CFG_SUPPORT_WAPI + case ELEM_ID_WAPI: + if (wapiParseWapiIE(WAPI_IE(pucIE), &prBssDesc->rIEWAPI)) + prBssDesc->fgIEWAPI = TRUE; + break; +#endif + case ELEM_ID_BSS_LOAD: + { + struct IE_BSS_LOAD *prBssLoad = (struct IE_BSS_LOAD *)pucIE; + + prBssDesc->u2StaCnt = prBssLoad->u2StaCnt; + prBssDesc->ucChnlUtilization = prBssLoad->ucChnlUtilizaion; + prBssDesc->u2AvaliableAC = prBssLoad->u2AvailabeAC; + prBssDesc->fgExsitBssLoadIE = TRUE; + break; + } + case ELEM_ID_VENDOR: /* ELEM_ID_P2P, ELEM_ID_WMM */ +#if CFG_PRIVACY_MIGRATION + if (rsnParseCheckForWFAInfoElem(prAdapter, pucIE, &ucOuiType, &u2SubTypeVersion)) { + if ((ucOuiType == VENDOR_OUI_TYPE_WPA) && (u2SubTypeVersion == VERSION_WPA)) { + + if (rsnParseWpaIE(prAdapter, WPA_IE(pucIE), &prBssDesc->rWPAInfo)) + prBssDesc->fgIEWPA = TRUE; + } + } +#endif +#if CFG_SUPPORT_HOTSPOT_2_0 + /* since OSEN is mutual exclusion with RSN, so we reuse RSN here */ + if (pucIE[1] >= 10 && kalMemCmp(pucIE+2, "\x50\x6f\x9a\x12", 4) == 0 && + rsnParseOsenIE(prAdapter, (struct IE_WFA_OSEN *)pucIE, &prBssDesc->rRSNInfo)) + prBssDesc->fgIEOsen = 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 */ +#if CFG_SUPPORT_DETECT_ATHEROS_AP + if (IE_LEN(pucIE) <= ELEM_MIN_LEN_WFA_OUI_TYPE_SUBTYPE) + break; + else if (pucIE[2] == 0x00 && + pucIE[3] == 0x03 && pucIE[4] == 0x7F) + prBssDesc->fgIsAtherosAP = TRUE; +#endif + break; + case ELEM_ID_PWR_CONSTRAINT: + { + P_IE_POWER_CONSTRAINT_T prPwrConstraint = (P_IE_POWER_CONSTRAINT_T)pucIE; + + if (IE_LEN(pucIE) != 1) + break; + ucPowerConstraint = prPwrConstraint->ucLocalPowerConstraint; + 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 = eHwBand; + + /* 4 <4.2> Get channel and RCPI information */ + ucHwChannelNum = HIF_RX_HDR_GET_CHNL_NUM(prHifRxHdr); + + if (prBssDesc->eBand == BAND_2G4) { +#if (CFG_FORCE_USE_20BW == 0) + if (eSco != CHNL_EXT_RES) + prBssDesc->eSco = eSco; +#endif + /* 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 (eSco != CHNL_EXT_RES) + prBssDesc->eSco = eSco; + 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; + } + } + } + +#if CFG_SUPPORT_802_11K + if (prCountryIE) { + UINT_8 ucRemainLen = prCountryIE->ucLength - 3; + P_COUNTRY_INFO_SUBBAND_TRIPLET_T prSubBand = &prCountryIE->arCountryStr[0]; + const UINT_8 ucSubBandSize = (UINT_8)sizeof(COUNTRY_INFO_SUBBAND_TRIPLET_T); + INT_8 cNewPwrLimit = RLM_INVALID_POWER_LIMIT; + + /* Try to find a country subband base on our channel */ + while (ucRemainLen >= ucSubBandSize) { + if (prSubBand->ucFirstChnlNum < 201 && + prBssDesc->ucChannelNum >= prSubBand->ucFirstChnlNum && + prBssDesc->ucChannelNum <= (prSubBand->ucFirstChnlNum + prSubBand->ucNumOfChnl - 1)) + break; + ucRemainLen -= ucSubBandSize; + prSubBand++; + } + /* Found a right country band */ + if (ucRemainLen >= ucSubBandSize) { + cNewPwrLimit = prSubBand->cMaxTxPwrLv - ucPowerConstraint; + /* Limit Tx power changed */ + if (prBssDesc->cPowerLimit != cNewPwrLimit) { + prBssDesc->cPowerLimit = cNewPwrLimit; + DBGLOG(SCN, TRACE, "Old: TxPwrLimit %d,New: CountryMax %d, Constraint %d\n", + prBssDesc->cPowerLimit, prSubBand->cMaxTxPwrLv, ucPowerConstraint); + /* should tell firmware to restrict tx power if connected a BSS */ + if (prBssDesc->fgIsConnected) { + if (prBssDesc->cPowerLimit != RLM_INVALID_POWER_LIMIT) + rlmSetMaxTxPwrLimit(prAdapter, prBssDesc->cPowerLimit, 1); + else + rlmSetMaxTxPwrLimit(prAdapter, 0, 0); + } + } + } else if (prBssDesc->cPowerLimit != RLM_INVALID_POWER_LIMIT) { + prBssDesc->cPowerLimit = RLM_INVALID_POWER_LIMIT; + rlmSetMaxTxPwrLimit(prAdapter, 0, 0); + } + } else if (prBssDesc->cPowerLimit != RLM_INVALID_POWER_LIMIT) { + prBssDesc->cPowerLimit = RLM_INVALID_POWER_LIMIT; + rlmSetMaxTxPwrLimit(prAdapter, 0, 0); + } +#endif + + /* 4 <5> PHY type setting */ + prBssDesc->ucPhyTypeSet = 0; + + if (prBssDesc->eBand == BAND_2G4) { + /* 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)); + } + } + aisRemoveBeaconTimeoutEntry(prAdapter, prBssDesc); + /* update update-index and reset seen-probe-response */ + if (prBssDesc->u4UpdateIdx != prAdapter->rWifiVar.rScanInfo.u4ScanUpdateIdx) { + prBssDesc->fgSeenProbeResp = FALSE; + prBssDesc->u4UpdateIdx = prAdapter->rWifiVar.rScanInfo.u4ScanUpdateIdx; + } + /* check if it is a probe response frame */ + if ((prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_PROBE_RSP) + prBssDesc->fgSeenProbeResp = TRUE; + + /* 4 <6> Update BSS_DESC_T's Last Update TimeStamp. */ + if (fgIsValidSsid || + ((prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_PROBE_RSP)) + GET_CURRENT_SYSTIME(&prBssDesc->rUpdateTime); + + if (prBssDesc->fgIsConnected) { + rTsf.rTime = prBssDesc->rUpdateTime; + kalMemCopy(&rTsf.au4Tsf[0], &prBssDesc->u8TimeStamp, 8); + } + + return prBssDesc; +} + +/* clear all ESS scan result */ +VOID scanInitEssResult(P_ADAPTER_T prAdapter) +{ + prAdapter->rWlanInfo.u4ScanResultEssNum = 0; + prAdapter->rWlanInfo.u4ScanDbgTimes1 = 0; + prAdapter->rWlanInfo.u4ScanDbgTimes2 = 0; + prAdapter->rWlanInfo.u4ScanDbgTimes3 = 0; + prAdapter->rWlanInfo.u4ScanDbgTimes4 = 0; + kalMemZero(prAdapter->rWlanInfo.arScanResultEss, sizeof(prAdapter->rWlanInfo.arScanResultEss)); +} +/* print all ESS into log system once scan done */ +/* it is useful to log that, otherwise, we have no information to identify if hardware has seen a specific AP, */ +/* if user complained some AP were not found in scan result list */ +VOID scanLogEssResult(P_ADAPTER_T prAdapter) +{ +#define NUMBER_SSID_PER_LINE 16 + struct ESS_SCAN_RESULT_T *prEssResult = &prAdapter->rWlanInfo.arScanResultEss[0]; + UINT_32 u4ResultNum = prAdapter->rWlanInfo.u4ScanResultEssNum; + UINT_32 u4Index = 0; + + if (u4ResultNum == 0) { + DBGLOG(SCN, INFO, "0 Bss is found, %d, %d, %d, %d\n", + prAdapter->rWlanInfo.u4ScanDbgTimes1, prAdapter->rWlanInfo.u4ScanDbgTimes2, + prAdapter->rWlanInfo.u4ScanDbgTimes3, prAdapter->rWlanInfo.u4ScanDbgTimes4); + return; + } + + DBGLOG(SCN, INFO, + "Total:%u/%u; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s\n", + u4ResultNum, prAdapter->rWlanInfo.u4ScanResultNum, + prEssResult[0].aucSSID, prEssResult[1].aucSSID, prEssResult[2].aucSSID, + prEssResult[3].aucSSID, prEssResult[4].aucSSID, prEssResult[5].aucSSID, + prEssResult[6].aucSSID, prEssResult[7].aucSSID, prEssResult[8].aucSSID, + prEssResult[9].aucSSID, prEssResult[10].aucSSID, prEssResult[11].aucSSID, + prEssResult[12].aucSSID, prEssResult[13].aucSSID, prEssResult[14].aucSSID, + prEssResult[15].aucSSID); + if (u4ResultNum <= NUMBER_SSID_PER_LINE) + return; + u4ResultNum = (u4ResultNum + NUMBER_SSID_PER_LINE - 1) / NUMBER_SSID_PER_LINE; + for (u4Index = 1; u4Index < u4ResultNum; u4Index++) { + struct ESS_SCAN_RESULT_T *prEss = &prEssResult[NUMBER_SSID_PER_LINE*u4Index]; + + DBGLOG(SCN, INFO, + "%s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s\n", + prEss[0].aucSSID, + prEss[1].aucSSID, prEss[2].aucSSID, prEss[3].aucSSID, + prEss[4].aucSSID, prEss[5].aucSSID, prEss[6].aucSSID, + prEss[7].aucSSID, prEss[8].aucSSID, prEss[9].aucSSID, + prEss[10].aucSSID, prEss[11].aucSSID, prEss[12].aucSSID, + prEss[13].aucSSID, prEss[14].aucSSID, prEss[15].aucSSID); + } +} + +/* record all Scanned ESS, only one BSS was saved for each ESS, and AP who is hidden ssid was excluded. */ +/* maximum we only support record 64 ESSes */ +static VOID scanAddEssResult(P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) +{ + struct ESS_SCAN_RESULT_T *prEssResult = &prAdapter->rWlanInfo.arScanResultEss[0]; + UINT_32 u4Index = 0; + + if (prBssDesc->fgIsHiddenSSID) + return; + if (prAdapter->rWlanInfo.u4ScanResultEssNum >= CFG_MAX_NUM_BSS_LIST) + return; + for (; u4Index < prAdapter->rWlanInfo.u4ScanResultEssNum; u4Index++) { + if (EQUAL_SSID(prEssResult[u4Index].aucSSID, (UINT_8)prEssResult[u4Index].u2SSIDLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen)) + return; + } + + COPY_SSID(prEssResult[u4Index].aucSSID, prEssResult[u4Index].u2SSIDLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + COPY_MAC_ADDR(prEssResult[u4Index].aucBSSID, prBssDesc->aucBSSID); + prAdapter->rWlanInfo.u4ScanResultEssNum++; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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) */ + DBGLOG(SCN, INFO, "Bss Desc type is P2P\n"); + 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 < ARRAY_SIZE(aucRatesEx); i++) + aucRatesEx[i] = 0; + + switch (prBssDesc->eBSSType) { + case BSS_TYPE_IBSS: + eOpMode = NET_TYPE_IBSS; + break; + + case BSS_TYPE_INFRASTRUCTURE: + case BSS_TYPE_P2P_DEVICE: + case BSS_TYPE_BOW_DEVICE: + default: + eOpMode = NET_TYPE_INFRA; + break; + } + + DBGLOG(SCN, TRACE, "ind %s %d\n", prBssDesc->aucSSID, prBssDesc->ucChannelNum); + +#if (CFG_SUPPORT_TDLS == 1) + { + if (flgTdlsTestExtCapElm == TRUE) { + /* only for RALINK AP */ + UINT8 *pucElm = (UINT8 *) (prSwRfb->pvHeader + prSwRfb->u2PacketLen); + + kalMemCopy(pucElm - 9, aucTdlsTestExtCapElm, 7); + prSwRfb->u2PacketLen -= 2; +/* prSwRfb->u2PacketLen += 7; */ + + DBGLOG(TDLS, INFO, + " %s: append ext cap element to %pM\n", + __func__, prBssDesc->aucBSSID); + } + } +#endif /* CFG_SUPPORT_TDLS */ + + if (prAdapter->rWifiVar.rScanInfo.fgNloScanning && + test_bit(SUSPEND_FLAG_CLEAR_WHEN_RESUME, &prAdapter->ulSuspendFlag)) { + UINT_8 i = 0; + P_BSS_DESC_T *pprPendBssDesc = &prScanInfo->rNloParam.aprPendingBssDescToInd[0]; + + for (; i < SCN_SSID_MATCH_MAX_NUM; i++) { + if (pprPendBssDesc[i]) + continue; + DBGLOG(SCN, INFO, + "indicate bss[%pM] before wiphy resume, need to indicate again after wiphy resume\n", + prBssDesc->aucBSSID); + pprPendBssDesc[i] = prBssDesc; + break; + } + } + + scanAddEssResult(prAdapter, prBssDesc); + + if (prBssDesc->fgIsValidSSID) { + kalIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) prSwRfb->pvHeader, + prSwRfb->u2PacketLen, + prBssDesc->ucChannelNum, + RCPI_TO_dBm(prBssDesc->ucRCPI)); + } + + nicAddScanResult(prAdapter, + rMacAddr, + &rSsid, + prWlanBeaconFrame->u2CapInfo, + RCPI_TO_dBm(prBssDesc->ucRCPI), + eNetworkType, + &rConfiguration, + eOpMode, + aucRatesEx, + prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen, + (PUINT_8) ((ULONG) (prSwRfb->pvHeader) + WLAN_MAC_MGMT_HEADER_LEN)); + + return WLAN_STATUS_SUCCESS; + +} /* end of scanAddScanResult() */ + +BOOLEAN scanCheckBssIsLegal(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc) +{ + BOOLEAN fgAddToScanResult = FALSE; + ENUM_BAND_T eBand = 0; + UINT_8 ucChannel = 0; + + ASSERT(prAdapter); + /* check the channel is in the legal doamin */ + if (rlmDomainIsLegalChannel(prAdapter, prBssDesc->eBand, prBssDesc->ucChannelNum) == TRUE) { + /* check ucChannelNum/eBand for adjacement channel filtering */ + if (cnmAisInfraChannelFixed(prAdapter, &eBand, &ucChannel) == TRUE && + (eBand != prBssDesc->eBand || ucChannel != prBssDesc->ucChannelNum)) { + fgAddToScanResult = FALSE; + } else { + fgAddToScanResult = TRUE; + } + } + return fgAddToScanResult; + +} +VOID scanReportBss2Cfg80211(IN P_ADAPTER_T prAdapter, IN ENUM_BSS_TYPE_T eBSSType, IN P_BSS_DESC_T prSpecificBssDesc) +{ + P_LINK_T prBSSDescList = (P_LINK_T) NULL; + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; + RF_CHANNEL_INFO_T rChannelInfo; + + ASSERT(prAdapter); + + DBGLOG(SCN, TRACE, "eBSSType: %d\n", eBSSType); + + if (prSpecificBssDesc) { + + /* Check BSSID is legal channel */ + if (!scanCheckBssIsLegal(prAdapter, prSpecificBssDesc)) { + DBGLOG(SCN, TRACE, "Remove specific SSID[%s] on channel %d\n", + HIDE(prSpecificBssDesc->aucSSID), + prSpecificBssDesc->ucChannelNum); + return; + } + + DBGLOG(SCN, TRACE, "Report specific SSID[%s] ValidSSID[%d]\n", + HIDE(prSpecificBssDesc->aucSSID), + prSpecificBssDesc->fgIsValidSSID); + + if (eBSSType == BSS_TYPE_INFRASTRUCTURE) { + if (prSpecificBssDesc->fgIsValidSSID) + kalIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) prSpecificBssDesc->aucRawBuf, + prSpecificBssDesc->u2RawLength, + prSpecificBssDesc->ucChannelNum, + RCPI_TO_dBm(prSpecificBssDesc->ucRCPI)); + } else { + +#if P2P_INDICATE_COMPLETE_BSS_INFO + kalP2PIndicateCompleteBssInfo(prAdapter->prGlueInfo, prSpecificBssDesc); +#else + rChannelInfo.ucChannelNum = prSpecificBssDesc->ucChannelNum; + rChannelInfo.eBand = prSpecificBssDesc->eBand; + kalP2PIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) prSpecificBssDesc->aucRawBuf, + prSpecificBssDesc->u2RawLength, + &rChannelInfo, + RCPI_TO_dBm(prSpecificBssDesc->ucRCPI)); +#endif + } + +#if CFG_ENABLE_WIFI_DIRECT + prSpecificBssDesc->fgIsP2PReport = FALSE; +#endif + + } else { + /* Search BSS Desc from current SCAN result list. */ + prBSSDescList = &(prAdapter->rWifiVar.rScanInfo.rBSSDescList); + + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + /* Check BSSID is legal channel */ + if (!scanCheckBssIsLegal(prAdapter, prBssDesc)) { + DBGLOG(SCN, TRACE, "Remove SSID[%s] on channel %d\n", + prBssDesc->aucSSID, prBssDesc->ucChannelNum); + continue; + } + + if ((prBssDesc->eBSSType == eBSSType) +#if CFG_ENABLE_WIFI_DIRECT + || ((eBSSType == BSS_TYPE_P2P_DEVICE) && (prBssDesc->fgIsP2PReport == TRUE)) +#endif + ) { + + +#define TEMP_LOG_TEMPLATE "Report " MACSTR " SSID[%s %u] eBSSType[%d] " \ + "ValidSSID[%u] u2RawLength[%d] fgIsP2PReport[%d]\n" + DBGLOG(SCN, TRACE, TEMP_LOG_TEMPLATE, + MAC2STR(prBssDesc->aucBSSID), + HIDE(prBssDesc->aucSSID), + prBssDesc->ucChannelNum, + prBssDesc->eBSSType, + prBssDesc->fgIsValidSSID, + prBssDesc->u2RawLength, + prBssDesc->fgIsP2PReport); +#undef TEMP_LOG_TEMPLATE + + if (eBSSType == BSS_TYPE_INFRASTRUCTURE) { + if (prBssDesc->u2RawLength != 0 && + prBssDesc->fgIsValidSSID) { + kalIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) prBssDesc->aucRawBuf, + prBssDesc->u2RawLength, + prBssDesc->ucChannelNum, + RCPI_TO_dBm(prBssDesc->ucRCPI)); + } + kalMemZero(prBssDesc->aucRawBuf, CFG_RAW_BUFFER_SIZE); +#if CFG_ENABLE_WIFI_DIRECT + prBssDesc->fgIsP2PReport = FALSE; +#endif + prBssDesc->u2RawLength = 0; + + } else { +#if CFG_ENABLE_WIFI_DIRECT + if (prBssDesc->fgIsP2PReport == TRUE) { +#endif + rChannelInfo.ucChannelNum = prBssDesc->ucChannelNum; + rChannelInfo.eBand = prBssDesc->eBand; + kalP2PIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) prBssDesc->aucRawBuf, + prBssDesc->u2RawLength, + &rChannelInfo, + RCPI_TO_dBm(prBssDesc->ucRCPI)); + /* Do not clear it then we can pass the bss in Specific report */ + /* kalMemZero(prBssDesc->aucRawBuf,CFG_RAW_BUFFER_SIZE); */ + + /* The BSS entry will not be cleared after scan done. + * So if we dont receive the BSS in next scan, we cannot + * pass it. We use u2RawLength for the purpose. + */ + /* prBssDesc->u2RawLength=0; */ +#if CFG_ENABLE_WIFI_DIRECT + prBssDesc->fgIsP2PReport = FALSE; + } +#endif + } + } + } + } + wlanDebugScanTargetBSSDump(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Parse channel number to array index. +* +* @param[in] u4ChannelNum channel number. +* +* @retval index array index +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 nicChannelNum2Index(IN UINT_8 ucChannelNum) +{ + UINT_8 ucindex; + + /*Full2Partial*/ + if (ucChannelNum >= 1 && ucChannelNum <= 14) + /*1---14*/ + ucindex = ucChannelNum; + else if (ucChannelNum >= 36 && ucChannelNum <= 64) + /*15---22*/ + ucindex = 6 + (ucChannelNum >> 2); + else if (ucChannelNum >= 100 && ucChannelNum <= 144) + /*23---34*/ + ucindex = (ucChannelNum >> 2) - 2; + else if (ucChannelNum >= 149 && ucChannelNum <= 165) { + /*35---39*/ + ucChannelNum = ucChannelNum - 1; + ucindex = (ucChannelNum >> 2) - 2; + } else + ucindex = 0; + + return ucindex; +} + +static UINT_8 scanGetChannel(P_HIF_RX_HEADER_T prHifRxHdr, PUINT_8 pucIE, UINT_16 u2IELen) +{ + UINT_8 ucDsChannel = 0; + UINT_8 ucHtChannel = 0; + UINT_8 ucHwChannel = HIF_RX_HDR_GET_CHNL_NUM(prHifRxHdr); + UINT_16 u2Offset = 0; + ENUM_BAND_T eBand = HIF_RX_HDR_GET_RF_BAND(prHifRxHdr); + + IE_FOR_EACH(pucIE, u2IELen, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_DS_PARAM_SET: + if (IE_LEN(pucIE) == ELEM_MAX_LEN_DS_PARAMETER_SET) + ucDsChannel = DS_PARAM_IE(pucIE)->ucCurrChnl; + break; + case ELEM_ID_HT_OP: + if (IE_LEN(pucIE) == (sizeof(IE_HT_OP_T) - 2)) + ucHtChannel = ((P_IE_HT_OP_T) pucIE)->ucPrimaryChannel; + break; + } + } + DBGLOG(SCN, INFO, "band %d, hw channel %d, ds %d, ht %d\n", eBand, ucHwChannel, ucDsChannel, ucHtChannel); + if (eBand == BAND_2G4) { + if (ucDsChannel >= 1 && ucDsChannel <= 14) + return ucDsChannel; + return (ucHtChannel >= 1 && ucHtChannel <= 14) ? ucHtChannel:ucHwChannel; + } + return (ucHtChannel >= 1 && ucHtChannel < 200) ? ucHtChannel:ucHwChannel; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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) +{ + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq = &prAdapter->rWifiVar.rRmReqParams; + + /* if beacon request measurement is on-going, collect Beacon Report */ + if (prRmReq->rBcnRmParam.eState == RM_ON_GOING) { + struct RM_BEACON_REPORT_PARAMS rRepParams; + P_WLAN_BEACON_FRAME_T prWlanBeacon = (P_WLAN_BEACON_FRAME_T)prSwRfb->pvHeader; + P_WLAN_BEACON_FRAME_BODY_T prRepBeaconBody = (P_WLAN_BEACON_FRAME_BODY_T)&rRepParams.aucBcnFixedField; + UINT_16 u2IELen = prSwRfb->u2PacketLen - OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem); + + kalMemZero(&rRepParams, sizeof(rRepParams)); + if (u2IELen > CFG_IE_BUFFER_SIZE) + u2IELen = CFG_IE_BUFFER_SIZE; + + /* if this is a one antenna only device, the antenna id is always 1. 7.3.2.40 */ + rRepParams.ucAntennaID = 1; + rRepParams.ucChannel = scanGetChannel(prSwRfb->prHifRxHdr, prWlanBeacon->aucInfoElem, u2IELen); + rRepParams.ucRCPI = prSwRfb->prHifRxHdr->ucRcpi; + rRepParams.ucRSNI = 255; /* 255 means RSNI not available. see 7.3.2.41 */ + rRepParams.ucFrameInfo = 0; + kalMemCopy(prRepBeaconBody->au4Timestamp, prWlanBeacon->au4Timestamp, + sizeof(prWlanBeacon->au4Timestamp)); + prRepBeaconBody->u2BeaconInterval = prWlanBeacon->u2BeaconInterval; + prRepBeaconBody->u2CapInfo = prWlanBeacon->u2CapInfo; + + scanCollectBeaconReport(prAdapter, prWlanBeacon->aucInfoElem, u2IELen, + prWlanBeacon->aucBSSID, &rRepParams); + return WLAN_STATUS_SUCCESS; + } + return __scanProcessBeaconAndProbeResp(prAdapter, prSwRfb); +} + +/*static BOOLEAN +* scanBeaconReportCheckChannel(P_RM_BCN_REQ_T prBcnReq, UINT_8 ucBcnReqLen, UINT_8 ucChannel) +*{ +* PUINT_8 pucSubIE = &prBcnReq->aucSubElements[0]; +* +* if (prBcnReq->ucChannel == ucChannel) +* return TRUE; +* ucBcnReqLen -= OFFSET_OF(RM_BCN_REQ_T, aucSubElements); +* while (ucBcnReqLen > 0) { +* UINT_8 ucNumChannels = 0; +* UINT_8 ucIeSize = IE_SIZE(pucSubIE); +* +* if (pucSubIE[0] != ELEM_ID_AP_CHANNEL_REPORT) { +* ucBcnReqLen -= ucIeSize; +* pucSubIE += ucIeSize; +* continue; +* } +* ucNumChannels = ucIeSize - 1; +* while (ucNumChannels >= 3) { +* if (ucChannel == pucSubIE[ucNumChannels]) +* return TRUE; +* } +* ucBcnReqLen -= ucIeSize; +* pucSubIE += ucIeSize; +* } +* return FALSE; +*} +*/ +VOID scanCollectBeaconReport(IN P_ADAPTER_T prAdapter, PUINT_8 pucIEBuf, + UINT_16 u2IELength, PUINT_8 pucBssid, struct RM_BEACON_REPORT_PARAMS *prRepParams) +{ +#define BEACON_FIXED_FIELD_LENGTH 12 + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq = &prAdapter->rWifiVar.rRmReqParams; + struct RADIO_MEASUREMENT_REPORT_PARAMS *prRmRep = &prAdapter->rWifiVar.rRmRepParams; + P_RM_BCN_REQ_T prBcnReq = (P_RM_BCN_REQ_T)&prRmReq->prCurrMeasElem->aucRequestFields[0]; + P_IE_MEASUREMENT_REPORT_T prMeasReport = NULL; + /* Variables to process Beacon IE */ + PUINT_8 pucIE; + UINT_16 u2Offset = 0; + + /* Variables to collect report */ + UINT_8 ucRSSI = 0; + PUINT_8 pucSubIE = NULL; + UINT_8 ucCondition = 0; + UINT_8 ucRefValue = 0; + UINT_8 ucReportDetail = 0; + PUINT_8 pucReportIeIds = NULL; + UINT_8 ucReportIeIdsLen = 0; + struct RM_BCN_REPORT *prBcnReport = NULL; + UINT_8 ucBcnReportLen = 0; + struct RM_MEASURE_REPORT_ENTRY *prReportEntry = NULL; + UINT_16 u2RemainLen = 0; + BOOLEAN fgValidChannel = FALSE; + UINT_16 u2IeSize = 0; + + if (!EQUAL_MAC_ADDR(prBcnReq->aucBssid, "\xff\xff\xff\xff\xff\xff") && + !EQUAL_MAC_ADDR(prBcnReq->aucBssid, pucBssid)) { + DBGLOG(SCN, INFO, "bssid mismatch, req %pM, actual %pM\n", prBcnReq->aucBssid, pucBssid); + return; + } + + pucIE = pucIEBuf; + /* Step1: parsing Beacon Request sub element field to get Report controlling information */ + /* if match the channel that is in fixed field, no need to check AP channel report */ + if (prBcnReq->ucChannel == prRepParams->ucChannel) + fgValidChannel = TRUE; + + u2RemainLen = prRmReq->prCurrMeasElem->ucLength - 3 - OFFSET_OF(RM_BCN_REQ_T, aucSubElements); + pucSubIE = &prBcnReq->aucSubElements[0]; + while (u2RemainLen > 0) { + u2IeSize = IE_SIZE(pucSubIE); + if (u2IeSize > u2RemainLen) + break; + switch (pucSubIE[0]) { + case 0: /* checking if SSID is matched */ + /* length of sub-element ssid is 0 or first byte is 0, means wildcard ssid matching */ + if (!IE_LEN(pucSubIE) || !pucSubIE[2]) + break; + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (IE_ID(pucIE) == ELEM_ID_SSID) + break; + } + if (EQUAL_SSID(&pucIE[2], pucIE[1], &pucSubIE[2], pucSubIE[1])) + break; + { + UINT_8 aucReqSsid[33] = {0}; + UINT_8 aucBcnSsid[33] = {0}; + UINT_8 ucReqSsidLen = pucSubIE[1] <= 32 ? pucSubIE[1] : 32; + UINT_8 ucBcnSsidLen = pucIE[1] <= 32 ? pucIE[1] : 32; + + kalMemCopy(aucReqSsid, &pucSubIE[2], ucReqSsidLen); + kalMemCopy(aucBcnSsid, &pucIE[2], ucBcnSsidLen); + DBGLOG(SCN, TRACE, + "SSID mismatch, req(len %u, %s), bcn(id %u, len %u, %s)\n", + ucReqSsidLen, HIDE(aucReqSsid), + pucIE[0], ucBcnSsidLen, HIDE(aucBcnSsid)); + } + return; /* don't match SSID, don't report it */ + case 1: /* Beacon Reporting Information */ + ucCondition = pucSubIE[3]; + ucRefValue = pucSubIE[4]; + break; + case 2: /* Reporting Detail Element */ + ucReportDetail = pucSubIE[2]; + break; + case 10: /* Request Elements */ + { + struct IE_REQUEST_T *prIe = (struct IE_REQUEST_T *)pucSubIE; + + pucReportIeIds = prIe->aucReqIds; + ucReportIeIdsLen = prIe->ucLength; + break; + } + case 51: /* AP CHANNEL REPORT Element */ + { + UINT_8 ucNumChannels = 3; /* channel info is starting with the fourth byte */ + + if (fgValidChannel) + break; + /* try to match with AP channel report */ + while (ucNumChannels < u2IeSize) { + if (prRepParams->ucChannel == pucSubIE[ucNumChannels]) { + fgValidChannel = TRUE; + break; + } + ucNumChannels++; + } + } + } + u2RemainLen -= u2IeSize; + pucSubIE += u2IeSize; + } + if (!fgValidChannel && prBcnReq->ucChannel > 0 && prBcnReq->ucChannel < 255) { + DBGLOG(SCN, INFO, "channel %d, valid %d\n", prBcnReq->ucChannel, fgValidChannel); + return; + } + + /* Step2: check report condition */ + ucRSSI = RCPI_TO_dBm(prRepParams->ucRCPI); + switch (ucCondition) { + case 1: + if (ucRSSI <= ucRefValue/2) + return; + break; + case 2: + if (ucRSSI >= ucRefValue/2) + return; + break; + case 3: + break; + } + /* Step3: Compose Beacon Report in a temp buffer */ + /* search in saved reported link, check if we have saved a report for this AP */ + LINK_FOR_EACH_ENTRY(prReportEntry, &prRmRep->rReportLink, rLinkEntry, struct RM_MEASURE_REPORT_ENTRY) { + P_IE_MEASUREMENT_REPORT_T prReportElem = (P_IE_MEASUREMENT_REPORT_T)prReportEntry->aucMeasReport; + + prBcnReport = (struct RM_BCN_REPORT *)prReportElem->aucReportFields; + if (EQUAL_MAC_ADDR(prBcnReport->aucBSSID, pucBssid)) + break; + prBcnReport = NULL; + } + if (!prBcnReport) {/* not found a entry in collected report link */ + LINK_REMOVE_HEAD(&prRmRep->rFreeReportLink, prReportEntry, struct RM_MEASURE_REPORT_ENTRY *); + if (!prReportEntry) {/* not found a entry in free report link */ + prReportEntry = kalMemAlloc(sizeof(*prReportEntry), VIR_MEM_TYPE); + if (!prReportEntry)/* no memory to allocate in OS */ { + DBGLOG(SCN, ERROR, "Alloc Measurement Report Entry failed, No Memory\n"); + return; + } + } + DBGLOG(SCN, INFO, "allocate entry for Bss %pM, total entry %u\n", + pucBssid, prRmRep->rReportLink.u4NumElem); + LINK_INSERT_TAIL(&prRmRep->rReportLink, &prReportEntry->rLinkEntry); + } + kalMemZero(prReportEntry->aucMeasReport, sizeof(prReportEntry->aucMeasReport)); + prMeasReport = (P_IE_MEASUREMENT_REPORT_T)prReportEntry->aucMeasReport; + prBcnReport = (struct RM_BCN_REPORT *)prMeasReport->aucReportFields; + /* Fixed length field */ + prBcnReport->ucRegulatoryClass = prBcnReq->ucRegulatoryClass; + prBcnReport->ucChannel = prRepParams->ucChannel; + prBcnReport->u2Duration = prBcnReq->u2Duration; + /* ucReportInfo: Bit 0 is the type of frame, 0 means beacon/probe response, bit 1~7 means phy type */ + prBcnReport->ucReportInfo = prRepParams->ucFrameInfo; + prBcnReport->ucRCPI = ucRSSI; + prBcnReport->ucRSNI = prRepParams->ucRSNI;/* ToDo: no RSNI is supported now */ + COPY_MAC_ADDR(prBcnReport->aucBSSID, pucBssid); + prBcnReport->ucAntennaID = prRepParams->ucAntennaID; /* only one Antenna now */ + { + OS_SYSTIME rCurrent; + UINT_64 u8Tsf = *(PUINT_64)&rTsf.au4Tsf[0]; + + GET_CURRENT_SYSTIME(&rCurrent); + if (prRmReq->rStartTime >= rTsf.rTime) + u8Tsf += prRmReq->rStartTime - rTsf.rTime; + else + u8Tsf += rTsf.rTime - prRmReq->rStartTime; + kalMemCopy(prBcnReport->aucStartTime, &u8Tsf, 8); /* ToDo: start time is not supported now */ + u8Tsf = *(PUINT_64)&rTsf.au4Tsf[0] + rCurrent - rTsf.rTime; + kalMemCopy(prBcnReport->aucParentTSF, &u8Tsf, 4); /* low part of TSF */ + } + ucBcnReportLen = 0; + /* Optional Subelement Field */ + /* all fixed length fields and IEs in Request Sub Elements should be reported */ + if (ucReportDetail == 1 && ucReportIeIdsLen > 0) { + pucSubIE = &prBcnReport->aucOptElem[2]; + kalMemCopy(pucSubIE, prRepParams->aucBcnFixedField, BEACON_FIXED_FIELD_LENGTH); + pucSubIE += BEACON_FIXED_FIELD_LENGTH; + ucBcnReportLen += BEACON_FIXED_FIELD_LENGTH; + pucIE = pucIEBuf; + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + UINT_16 i = 0; + UINT_8 ucIncludedIESize = 0; + + for (; i < ucReportIeIdsLen; i++) + if (pucIE[0] == pucReportIeIds[i]) { + ucIncludedIESize = IE_SIZE(pucIE); + break; + } + /* the length of sub-element should less than 225, + ** and the included IE should be a complete one + */ + if (ucBcnReportLen + ucIncludedIESize > RM_BCN_REPORT_SUB_ELEM_MAX_LENGTH) + break; + if (ucIncludedIESize == 0) + continue; + ucBcnReportLen += ucIncludedIESize; + kalMemCopy(pucSubIE, pucIE, ucIncludedIESize); + pucSubIE += ucIncludedIESize; + } + prBcnReport->aucOptElem[0] = 1; /* sub-element id for reported frame body */ + prBcnReport->aucOptElem[1] = ucBcnReportLen; /* length of the sub-element */ + ucBcnReportLen += 2; + } else if (ucReportDetail == 2) {/* all fixed length fields and IEs should be reported */ + ucBcnReportLen += BEACON_FIXED_FIELD_LENGTH; + pucIE = pucIEBuf; + /* the length of sub-element should less than 225, and the included IE should be a complete one */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (ucBcnReportLen + IE_SIZE(pucIE) > RM_BCN_REPORT_SUB_ELEM_MAX_LENGTH) + break; + ucBcnReportLen += IE_SIZE(pucIE); + } + prBcnReport->aucOptElem[0] = 1; /* sub-element id for reported frame body */ + prBcnReport->aucOptElem[1] = ucBcnReportLen; /* length of the sub-element */ + pucIE = &prBcnReport->aucOptElem[2]; + kalMemCopy(pucIE, prRepParams->aucBcnFixedField, BEACON_FIXED_FIELD_LENGTH); + pucIE += BEACON_FIXED_FIELD_LENGTH; + kalMemCopy(pucIE, pucIEBuf, ucBcnReportLen - BEACON_FIXED_FIELD_LENGTH); + ucBcnReportLen += 2; + } + ucBcnReportLen += OFFSET_OF(struct RM_BCN_REPORT, aucOptElem); + /* Step4: fill in basic content of Measurement report IE */ + prMeasReport->ucId = ELEM_ID_MEASUREMENT_REPORT; + prMeasReport->ucToken = prRmReq->prCurrMeasElem->ucToken; + prMeasReport->ucMeasurementType = ELEM_RM_TYPE_BEACON_REPORT; + prMeasReport->ucReportMode = 0; + prMeasReport->ucLength = 3 + ucBcnReportLen; + DBGLOG(SCN, INFO, "Bss %pM, ReportDeail %d, IncludeIE Num %d, chnl %d\n", + pucBssid, ucReportDetail, ucReportIeIdsLen, prRepParams->ucChannel); +} + +static 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 + BOOLEAN fgAddToScanResult = FALSE; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + /* 4 <0> Ignore invalid Beacon Frame */ + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < + (TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN)) { + /* to debug beacon length too small issue */ + UINT_32 u4MailBox0; + + nicGetMailbox(prAdapter, 0, &u4MailBox0); + DBGLOG(SCN, WARN, "if conn sys also get less length (0x5a means yes) %x\n", (UINT_32) u4MailBox0); + DBGLOG(SCN, WARN, "u2PacketLen %d, u2HeaderLen %d, payloadLen %d\n", + prSwRfb->u2PacketLen, prSwRfb->u2HeaderLen, + prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen); + /* dumpMemory8(prSwRfb->pvHeader, prSwRfb->u2PacketLen); */ + + DBGLOG(SCN, ERROR, "Ignore invalid Beacon Frame\n"); + return rStatus; + } +#if CFG_SLT_SUPPORT + prSltInfo = &prAdapter->rWifiVar.rSltInfo; + + if (prSltInfo->fgIsDUT) { + DBGLOG(SCN, INFO, "\n\rBCN: RX\n"); + prSltInfo->u4BeaconReceiveCnt++; + return WLAN_STATUS_SUCCESS; + } else { + return WLAN_STATUS_SUCCESS; + } +#endif + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T) prSwRfb->pvHeader; + + /*ALPS01475157: don't show SSID on scan list for multicast MAC AP */ + if (IS_BMCAST_MAC_ADDR(prWlanBeaconFrame->aucSrcAddr)) { + DBGLOG(SCN, WARN, "received beacon/probe response from multicast AP\n"); + return rStatus; + } + + /* 4 <1> Parse and add into BSS_DESC_T */ + prBssDesc = scanAddToBssDesc(prAdapter, prSwRfb); + prAdapter->rWlanInfo.u4ScanDbgTimes1++; + + if (prBssDesc) { + /*Full2Partial at here, we should save channel info*/ + if (prAdapter->prGlueInfo->ucTrScanType == 1) { + UINT_8 ucindex; + + ucindex = nicChannelNum2Index(prBssDesc->ucChannelNum); + DBGLOG(SCN, TRACE, "Full2Partial ucChannelNum=%d, ucindex=%d\n", + prBssDesc->ucChannelNum, ucindex); + + /*prAdapter->prGlueInfo->ucChannelListNum++;*/ + prAdapter->prGlueInfo->ucChannelNum[ucindex] = 1; + } + + /* 4 <1.1> Beacon Change Detection for Connected BSS */ + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED && + ((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE && prConnSettings->eOPMode != NET_TYPE_IBSS) + || (prBssDesc->eBSSType == BSS_TYPE_IBSS && prConnSettings->eOPMode != NET_TYPE_INFRA)) && + EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID) && + EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, prAisBssInfo->aucSSID, + prAisBssInfo->ucSSIDLen)) { + BOOLEAN fgNeedDisconnect = FALSE; + +#if CFG_SUPPORT_BEACON_CHANGE_DETECTION + /* <1.1.2> check if supported rate differs */ + if (prAisBssInfo->u2OperationalRateSet != prBssDesc->u2OperationalRateSet) + fgNeedDisconnect = TRUE; +#endif +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE + if ( +#if CFG_SUPPORT_WAPI + (prAdapter->rWifiVar.rConnSettings.fgWapiMode == TRUE && + !wapiPerformPolicySelection(prAdapter, prBssDesc)) || +#endif + rsnCheckSecurityModeChanged(prAdapter, prAisBssInfo, prBssDesc)) { + DBGLOG(SCN, INFO, "Beacon security mode change detected\n"); + DBGLOG_MEM8(SCN, INFO, prSwRfb->pvHeader, prSwRfb->u2PacketLen); + fgNeedDisconnect = FALSE; + if (!prConnSettings->fgSecModeChangeStartTimer) { + cnmTimerStartTimer(prAdapter, + &prAdapter->rWifiVar.rAisFsmInfo.rSecModeChangeTimer, + SEC_TO_MSEC(3)); + prConnSettings->fgSecModeChangeStartTimer = TRUE; + } + } else { + if (prConnSettings->fgSecModeChangeStartTimer) { + cnmTimerStopTimer(prAdapter, + &prAdapter->rWifiVar.rAisFsmInfo.rSecModeChangeTimer); + prConnSettings->fgSecModeChangeStartTimer = FALSE; + } + } +#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 */ + /*dump beacon and probeRsp by connect setting SSID*/ + wlanDebugScanTargetBSSRecord(prAdapter, prBssDesc); + + } + + 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]))); + + prAdapter->rWlanInfo.u4ScanDbgTimes2++; + /* 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 */ + prAdapter->rWlanInfo.u4ScanDbgTimes3++; + + + if (prConnSettings->fgIsScanReqIssued || prAdapter->rWifiVar.rScanInfo.fgNloScanning +#if CFG_SUPPORT_SCN_PSCN + || prAdapter->rWifiVar.rScanInfo.fgPscnOngoing +#endif + ) { + fgAddToScanResult = scanCheckBssIsLegal(prAdapter, prBssDesc); + prAdapter->rWlanInfo.u4ScanDbgTimes4++; + + if (fgAddToScanResult == TRUE) + rStatus = scanAddScanResult(prAdapter, prBssDesc, prSwRfb); + } + if (fgAddToScanResult == FALSE) { + kalMemZero(prBssDesc->aucRawBuf, CFG_RAW_BUFFER_SIZE); + prBssDesc->u2RawLength = 0; + } + + } +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) + scanP2pProcessBeaconAndProbeResp(prAdapter, prSwRfb, &rStatus, prBssDesc, prWlanBeaconFrame); +#endif + } + + return rStatus; + +} /* end of scanProcessBeaconAndProbeResp() */ + +INT_32 scanResultsAdjust5GPref(P_BSS_DESC_T prBssDesc) +{ + INT_32 rssi = RCPI_TO_dBm(prBssDesc->ucRCPI); + INT_32 orgRssi = rssi; + + if (prBssDesc->eBand == BAND_5G) { + if (rssi >= rssiRangeHi) + rssi += pref5GhzHi; + else if (rssi >= rssiRangeMed) + rssi += pref5GhzMed; + else if (rssi >= rssiRangeLo) + rssi += pref5GhzLo; + } + /* Reduce chances of roam ping-pong */ + if (prBssDesc->fgIsConnected) + rssi += (ROAMING_NO_SWING_RCPI_STEP >> 1); + + if (prBssDesc->eBand == BAND_5G || prBssDesc->fgIsConnected) + DBGLOG(SCN, TRACE, "Adjust 5G band RSSI: " MACSTR " band=%d, orgRssi=%d afterRssi=%d\n", + MAC2STR(prBssDesc->aucBSSID), prBssDesc->eBand, orgRssi, rssi); + return rssi; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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; + BOOLEAN fgIsAbsentCandidateBss = TRUE; + ENUM_BAND_T eBand = 0; + UINT_8 ucChannel = 0; +#if CFG_SUPPORT_NCHO + UINT_8 ucRCPIStep = ROAMING_NO_SWING_RCPI_STEP; +#endif + ASSERT(prAdapter); + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); + + prAisSpecBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + + GET_CURRENT_SYSTIME(&rCurrentTime); + + /* check for fixed channel operation */ + if (eNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { +#if CFG_P2P_LEGACY_COEX_REVISE + fgIsFixedChannel = cnmAisDetectP2PChannel(prAdapter, &eBand, &ucChannel); +#else + fgIsFixedChannel = cnmAisInfraChannelFixed(prAdapter, &eBand, &ucChannel); +#endif + } else { + fgIsFixedChannel = FALSE; + } + +#if DBG + if (prConnSettings->ucSSIDLen < ELEM_MAX_LEN_SSID) + prConnSettings->aucSSID[prConnSettings->ucSSIDLen] = '\0'; +#endif + + DBGLOG(SCN, INFO, "SEARCH: Bss Num: %d, Look for SSID: %s, %pM Band=%d, channel=%d\n", + (UINT_32) prBSSDescList->u4NumElem, HIDE(prConnSettings->aucSSID), + (prConnSettings->aucBSSID), eBand, ucChannel); + + /* 4 <1> The outer loop to search for a candidate. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + /* TODO(Kevin): Update Minimum Channel Load Information here */ + + DBGLOG(SCN, TRACE, "SEARCH: [ %pM ], SSID:%s\n", + prBssDesc->aucBSSID, HIDE(prBssDesc->aucSSID)); + + /* 4 <2> Check PHY Type and attributes */ + /* 4 <2.1> Check Unsupported BSS PHY Type */ + if (!(prBssDesc->ucPhyTypeSet & (prAdapter->rWifiVar.ucAvailablePhyTypeSet))) { + DBGLOG(SCN, TRACE, "SEARCH: Ignore unsupported ucPhyTypeSet = %x\n", prBssDesc->ucPhyTypeSet); + continue; + } + /* 4 <2.2> Check if has unknown NonHT BSS Basic Rate Set. */ + if (prBssDesc->fgIsUnknownBssBasicRate) + continue; + /* 4 <2.3> Check if fixed operation cases should be aware */ + if (fgIsFixedChannel == TRUE && (prBssDesc->eBand != eBand || prBssDesc->ucChannelNum != ucChannel)) + continue; + /* 4 <2.4> Check if the channel is legal under regulatory domain */ + if (rlmDomainIsLegalChannel(prAdapter, prBssDesc->eBand, prBssDesc->ucChannelNum) == FALSE) + continue; + /* 4 <2.5> Check if this BSS_DESC_T is stale */ +#if CFG_SUPPORT_RN + if (prBssInfo->fgDisConnReassoc == FALSE) +#endif + if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, + SEC_TO_SYSTIME(SCN_BSS_DESC_REMOVE_TIMEOUT_SEC))) { + + BOOLEAN fgIsNeedToCheckTimeout = TRUE; + +#if CFG_SUPPORT_ROAMING + P_ROAMING_INFO_T prRoamingFsmInfo; + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + if ((prRoamingFsmInfo->eCurrentState == ROAMING_STATE_DISCOVERY) || + (prRoamingFsmInfo->eCurrentState == ROAMING_STATE_ROAM)) { + if (++prRoamingFsmInfo->RoamingEntryTimeoutSkipCount < + ROAMING_ENTRY_TIMEOUT_SKIP_COUNT_MAX) { + fgIsNeedToCheckTimeout = FALSE; + DBGLOG(SCN, INFO, "SEARCH: Romaing skip SCN_BSS_DESC_REMOVE_TIMEOUT_SEC\n"); + } + } +#endif + + if (fgIsNeedToCheckTimeout == TRUE) { + DBGLOG(SCN, TRACE, "Ignore stale bss %pM\n", prBssDesc->aucBSSID); + continue; + } + } + /* 4 <3> Check if reach the excessive join retry limit */ + /* NOTE(Kevin): STA_RECORD_T is recorded by TA. */ + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) eNetTypeIndex, prBssDesc->aucSrcAddr); + + if (prStaRec) { + /* NOTE(Kevin): + * The Status Code is the result of a Previous Connection Request, + * we use this as SCORE for choosing a proper + * candidate (Also used for compare see <6>) + * The Reason Code is an indication of the reason why AP reject us, + * we use this Code for "Reject" + * a SCAN result to become our candidate(Like a blacklist). + */ +#if 0 /* TODO(Kevin): */ + if (prStaRec->u2ReasonCode != REASON_CODE_RESERVED) { + DBGLOG(SCN, INFO, "SEARCH: Ignore BSS with previous Reason Code = %d\n", + prStaRec->u2ReasonCode); + continue; + } else +#endif + if (prStaRec->u2StatusCode != STATUS_CODE_SUCCESSFUL) { + /* NOTE(Kevin): greedy association - after timeout, we'll still + * try to associate to the AP whose STATUS of conection attempt + * was not success. + * We may also use (ucJoinFailureCount x JOIN_RETRY_INTERVAL_SEC) for + * time bound. + */ + if ((prStaRec->ucJoinFailureCount < JOIN_MAX_RETRY_FAILURE_COUNT) || + (CHECK_FOR_TIMEOUT(rCurrentTime, + prStaRec->rLastJoinTime, + SEC_TO_SYSTIME(JOIN_RETRY_INTERVAL_SEC)))) { + + /* NOTE(Kevin): Every JOIN_RETRY_INTERVAL_SEC interval, we can retry + * JOIN_MAX_RETRY_FAILURE_COUNT times. + */ + if (prStaRec->ucJoinFailureCount >= JOIN_MAX_RETRY_FAILURE_COUNT) + prStaRec->ucJoinFailureCount = 0; + DBGLOG(SCN, INFO, + "SEARCH: Try to join BSS again,Status Code=%d (Curr=%u/Last Join=%u)\n", + prStaRec->u2StatusCode, rCurrentTime, prStaRec->rLastJoinTime); + } else { + DBGLOG(SCN, INFO, + "SEARCH: Ignore BSS which reach maximum Join Retry Count = %d\n", + JOIN_MAX_RETRY_FAILURE_COUNT); + continue; + } + + } + } + /* 4 <4> Check for various NETWORK conditions */ + if (eNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { + + /* 4 <4.1> Check BSS Type for the corresponding Operation Mode in Connection Setting */ + /* NOTE(Kevin): For NET_TYPE_AUTO_SWITCH, we will always pass following check. */ + if (((prConnSettings->eOPMode == NET_TYPE_INFRA) && + (prBssDesc->eBSSType != BSS_TYPE_INFRASTRUCTURE)) +#if CFG_SUPPORT_ADHOC + || ((prConnSettings->eOPMode == NET_TYPE_IBSS + || prConnSettings->eOPMode == NET_TYPE_DEDICATED_IBSS) + && (prBssDesc->eBSSType != BSS_TYPE_IBSS)) +#endif + ) { + + DBGLOG(SCN, TRACE, "Cur OPMode %d, Ignore eBSSType = %d\n", + prConnSettings->eOPMode, prBssDesc->eBSSType); + continue; + } + /* 4 <4.2> Check AP's BSSID if OID_802_11_BSSID has been set. */ + if ((prConnSettings->fgIsConnByBssidIssued) && + (prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE)) { + + if (UNEQUAL_MAC_ADDR(prConnSettings->aucBSSID, prBssDesc->aucBSSID)) { + + DBGLOG(SCN, TRACE, "SEARCH: Ignore due to BSSID was not matched!\n"); + continue; + } + } +#if CFG_SUPPORT_ADHOC + /* 4 <4.3> Check for AdHoc Mode */ + if (prBssDesc->eBSSType == BSS_TYPE_IBSS) { + OS_SYSTIME rCurrentTime; + + /* 4 <4.3.1> Check if this SCAN record has been updated recently for IBSS. */ + /* NOTE(Kevin): Because some STA may change its BSSID frequently after it + * create the IBSS - e.g. IPN2220, so we need to make sure we get the new one. + * For BSS, if the old record was matched, however it won't be able to pass + * the Join Process later. + */ + GET_CURRENT_SYSTIME(&rCurrentTime); + if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, + SEC_TO_SYSTIME(SCN_ADHOC_BSS_DESC_TIMEOUT_SEC))) { + DBGLOG(SCN, LOUD, + "SEARCH: Skip old record of BSS Descriptor - BSSID:[%pM]\n\n", + prBssDesc->aucBSSID); + continue; + } + /* 4 <4.3.2> Check Peer's capability */ + if (ibssCheckCapabilityForAdHocMode(prAdapter, prBssDesc) == WLAN_STATUS_FAILURE) { + + if (prPrimaryBssDesc) + DBGLOG(SCN, INFO, + "SEARCH: BSS DESC MAC: %pM, not supported AdHoc Mode.\n", + prPrimaryBssDesc->aucBSSID); + + continue; + } + /* 4 <4.3.3> Compare TSF */ + if (prBssInfo->fgIsBeaconActivated && + UNEQUAL_MAC_ADDR(prBssInfo->aucBSSID, prBssDesc->aucBSSID)) { + + DBGLOG(SCN, LOUD, + "SEARCH: prBssDesc->fgIsLargerTSF = %d\n", prBssDesc->fgIsLargerTSF); + + if (!prBssDesc->fgIsLargerTSF) { + DBGLOG(SCN, INFO, + "SEARCH: Ignore BSS DESC MAC: [ %pM ], Smaller TSF\n", + prBssDesc->aucBSSID); + continue; + } + } + } +#endif /* CFG_SUPPORT_ADHOC */ + + } +#if 0 /* TODO(Kevin): For IBSS */ + /* 4 <2.c> Check if this SCAN record has been updated recently for IBSS. */ + /* NOTE(Kevin): Because some STA may change its BSSID frequently after it + * create the IBSS, so we need to make sure we get the new one. + * For BSS, if the old record was matched, however it won't be able to pass + * the Join Process later. + */ + if (prBssDesc->eBSSType == BSS_TYPE_IBSS) { + OS_SYSTIME rCurrentTime; + + GET_CURRENT_SYSTIME(&rCurrentTime); + if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, + SEC_TO_SYSTIME(BSS_DESC_TIMEOUT_SEC))) { + DBGLOG(SCAN, TRACE, "Skip old record of BSS Descriptor - BSSID:[%pM]\n\n", + prBssDesc->aucBSSID); + continue; + } + } + + if ((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) && + (prAdapter->eConnectionState == MEDIA_STATE_CONNECTED)) { + OS_SYSTIME rCurrentTime; + + GET_CURRENT_SYSTIME(&rCurrentTime); + if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, + SEC_TO_SYSTIME(BSS_DESC_TIMEOUT_SEC))) { + DBGLOG(SCAN, TRACE, "Skip old record of BSS Descriptor - BSSID:[%pM]\n\n", + (prBssDesc->aucBSSID)); + continue; + } + } + /* 4 <4B> Check for IBSS AdHoc Mode. */ + /* Skip if one or more BSS Basic Rate are not supported by current AdHocMode */ + if (prPrimaryBssDesc->eBSSType == BSS_TYPE_IBSS) { + /* 4 <4B.1> Check if match the Capability of current IBSS AdHoc Mode. */ + if (ibssCheckCapabilityForAdHocMode(prAdapter, prPrimaryBssDesc) == WLAN_STATUS_FAILURE) { + + DBGLOG(SCAN, TRACE, + "Ignore BSS DESC MAC: %pM, Capability not supported for AdHoc Mode.\n", + prPrimaryBssDesc->aucBSSID); + + continue; + } + /* 4 <4B.2> IBSS Merge Decision Flow for SEARCH STATE. */ + if (prAdapter->fgIsIBSSActive && + UNEQUAL_MAC_ADDR(prBssInfo->aucBSSID, prPrimaryBssDesc->aucBSSID)) { + + if (!fgIsLocalTSFRead) { + NIC_GET_CURRENT_TSF(prAdapter, &rCurrentTsf); + + DBGLOG(SCAN, TRACE, + "\n\nCurrent TSF : %08lx-%08lx\n\n", + rCurrentTsf.u.HighPart, rCurrentTsf.u.LowPart); + } + + if (rCurrentTsf.QuadPart > prPrimaryBssDesc->u8TimeStamp.QuadPart) { + DBGLOG(SCAN, TRACE, + "Ignore BSS DESC MAC: [%pM], Current BSSID: [%pM].\n", + prPrimaryBssDesc->aucBSSID, prBssInfo->aucBSSID); + + DBGLOG(SCAN, TRACE, + "\n\nBSS's TSF : %08lx-%08lx\n\n", + prPrimaryBssDesc->u8TimeStamp.u.HighPart, + prPrimaryBssDesc->u8TimeStamp.u.LowPart); + + prPrimaryBssDesc->fgIsLargerTSF = FALSE; + continue; + } else { + prPrimaryBssDesc->fgIsLargerTSF = TRUE; + } + + } + } + /* 4 <5> Check the Encryption Status. */ + if (rsnPerformPolicySelection(prPrimaryBssDesc)) { + + if (prPrimaryBssDesc->ucEncLevel > 0) { + fgIsFindBestEncryptionLevel = TRUE; + + fgIsFindFirst = FALSE; + } + } else { + /* Can't pass the Encryption Status Check, get next one */ + continue; + } + + /* + * For RSN Pre-authentication, update the PMKID canidate list for + * same SSID and encrypt status + */ + /* Update PMKID candicate list. */ + if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) { + rsnUpdatePmkidCandidateList(prPrimaryBssDesc); + if (prAdapter->rWifiVar.rAisBssInfo.u4PmkidCandicateCount) + prAdapter->rWifiVar.rAisBssInfo.fgIndicatePMKID = rsnCheckPmkidCandicate(); + } +#endif + + prPrimaryBssDesc = (P_BSS_DESC_T) NULL; + + /* 4 <6> Check current Connection Policy. */ + switch (prConnSettings->eConnectionPolicy) { + case CONNECT_BY_SSID_BEST_RSSI: + /* Choose Hidden SSID to join only if the `fgIsEnableJoin...` is TRUE */ + if (prAdapter->rWifiVar.fgEnableJoinToHiddenSSID && prBssDesc->fgIsHiddenSSID) { + /* NOTE(Kevin): following if () statement means that + * If Target is hidden, then we won't connect when user specify SSID_ANY policy. + */ + if (prConnSettings->ucSSIDLen) { + prPrimaryBssDesc = prBssDesc; + fgIsFindBestRSSI = TRUE; + } + + } else if (EQUAL_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, + prConnSettings->aucSSID, prConnSettings->ucSSIDLen)) { + prPrimaryBssDesc = prBssDesc; + fgIsFindBestRSSI = TRUE; + + DBGLOG(SCN, TRACE, "SEARCH: fgIsFindBestRSSI=TRUE, %d, prPrimaryBssDesc=[ %pM ]\n", + prBssDesc->ucRCPI, prPrimaryBssDesc->aucBSSID); + } + break; + + case CONNECT_BY_SSID_ANY: + /* NOTE(Kevin): In this policy, we don't know the desired + * SSID from user, so we should exclude the Hidden SSID from scan list. + * And because we refuse to connect to Hidden SSID node at the beginning, so + * when the JOIN Module deal with a BSS_DESC_T which has fgIsHiddenSSID == TRUE, + * then the Connection Settings must be valid without doubt. + */ + if (!prBssDesc->fgIsHiddenSSID) { + prPrimaryBssDesc = prBssDesc; + fgIsFindFirst = TRUE; + } + break; + + case CONNECT_BY_BSSID: + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prConnSettings->aucBSSID)) + prPrimaryBssDesc = prBssDesc; + break; + + default: + break; + } + + /* Primary Candidate was not found */ + if (prPrimaryBssDesc == NULL) + continue; + /* 4 <7> Check the Encryption Status. */ + if (prPrimaryBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) { +#if CFG_SUPPORT_WAPI + if (prAdapter->rWifiVar.rConnSettings.fgWapiMode) { + DBGLOG(SCN, TRACE, "SEARCH: fgWapiMode == 1\n"); + + if (wapiPerformPolicySelection(prAdapter, prPrimaryBssDesc)) { + fgIsFindFirst = TRUE; + } else { + /* Can't pass the Encryption Status Check, get next one */ + DBGLOG(SCN, TRACE, "SEARCH: Encryption check failure, prPrimaryBssDesc=[%pM]\n", + prPrimaryBssDesc->aucBSSID); + continue; + } + } else +#endif +#if CFG_RSN_MIGRATION + if (rsnPerformPolicySelection(prAdapter, prPrimaryBssDesc)) { + if (prAisSpecBssInfo->fgCounterMeasure) { + DBGLOG(RSN, INFO, "Skip while at counter measure period!!!\n"); + continue; + } + + if (prPrimaryBssDesc->ucEncLevel > 0) { + fgIsFindBestEncryptionLevel = TRUE; + fgIsFindFirst = FALSE; + } +#if 0 + /* Update PMKID candicate list. */ + if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) { + rsnUpdatePmkidCandidateList(prPrimaryBssDesc); + if (prAisSpecBssInfo->u4PmkidCandicateCount) { + if (rsnCheckPmkidCandicate()) { + DBGLOG(RSN, WARN, + "Prepare a timer to indicate candidate %pM\n", + (prAisSpecBssInfo->arPmkidCache + [prAisSpecBssInfo->u4PmkidCacheCount]. + rBssidInfo.aucBssid))); + cnmTimerStopTimer(&prAisSpecBssInfo->rPreauthenticationTimer); + cnmTimerStartTimer(&prAisSpecBssInfo->rPreauthenticationTimer, + SEC_TO_MSEC + (WAIT_TIME_IND_PMKID_CANDICATE_SEC)); + } + } + } +#endif + } else { + /* Can't pass the Encryption Status Check, get next one */ + DBGLOG(RSN, WARN, "Can't pass the Encryption Status Check, get next one\n"); + continue; + } +#endif + } else { + /* Todo:: P2P and BOW Policy Selection */ + } + + prPrimaryStaRec = prStaRec; + + /* 4 <8> Compare the Candidate and the Primary Scan Record. */ + if (!prCandidateBssDesc) { + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + + /* 4 <8.1> Condition - Get the first matched one. */ + if (fgIsFindFirst) + break; + } else { +#if 0 /* TODO(Kevin): For security(TBD) */ + /* 4 <6B> Condition - Choose the one with best Encryption Score. */ + if (fgIsFindBestEncryptionLevel) { + if (prCandidateBssDesc->ucEncLevel < prPrimaryBssDesc->ucEncLevel) { + + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } + + /* If reach here, that means they have the same Encryption Score. + */ + + /* 4 <6C> Condition - Give opportunity to the one we didn't connect before. */ + /* For roaming, only compare the candidates other than current associated BSSID. */ + if (!prCandidateBssDesc->fgIsConnected && !prPrimaryBssDesc->fgIsConnected) { + if ((prCandidateStaRec != (P_STA_RECORD_T) NULL) && + (prCandidateStaRec->u2StatusCode != STATUS_CODE_SUCCESSFUL)) { + + DBGLOG(SCAN, TRACE, + "So far -BSS DESC MAC: %pM has nonzero Status Code = %d\n", + prCandidateBssDesc->aucBSSID, + prCandidateStaRec->u2StatusCode); + + if (prPrimaryStaRec != (P_STA_RECORD_T) NULL) { + if (prPrimaryStaRec->u2StatusCode != STATUS_CODE_SUCCESSFUL) { + + /* Give opportunity to the one with smaller rLastJoinTime */ + if (TIME_BEFORE(prCandidateStaRec->rLastJoinTime, + prPrimaryStaRec->rLastJoinTime)) { + continue; + } + /* + * We've connect to CANDIDATE recently, + * let us try PRIMARY now + */ + else { + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } + /* PRIMARY's u2StatusCode = 0 */ + else { + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } + /* PRIMARY has no StaRec - We didn't connet to PRIMARY before */ + else { + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } else { + if ((prPrimaryStaRec != (P_STA_RECORD_T) NULL) && + (prPrimaryStaRec->u2StatusCode != STATUS_CODE_SUCCESSFUL)) { + continue; + } + } + } +#endif + + /* 4 <6D> Condition - Visible SSID win Hidden SSID. */ + if (prCandidateBssDesc->fgIsHiddenSSID) { + if (!prPrimaryBssDesc->fgIsHiddenSSID) { + prCandidateBssDesc = prPrimaryBssDesc; /* The non Hidden SSID win. */ + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } else { + if (prPrimaryBssDesc->fgIsHiddenSSID) + continue; + } + + /* 4 <6E> Condition - Choose the one with better RCPI(RSSI). */ + if (fgIsFindBestRSSI) { + /* TODO(Kevin): We shouldn't compare the actual value, we should + * allow some acceptable tolerance of some RSSI percentage here. + */ + INT_32 u4PrimAdjRssi = scanResultsAdjust5GPref(prPrimaryBssDesc); + INT_32 u4CandAdjRssi = scanResultsAdjust5GPref(prCandidateBssDesc); + + DBGLOG(SCN, TRACE, + "Candidate [" MACSTR "]: RCPI=%d, RSSI=%d, joinFailCnt=%d, Primary [" + MACSTR "]: RCPI=%d, RSSI=%d, joinFailCnt=%d\n", + MAC2STR(prCandidateBssDesc->aucBSSID), + prCandidateBssDesc->ucRCPI, u4CandAdjRssi, + prCandidateBssDesc->ucJoinFailureCount, + MAC2STR(prPrimaryBssDesc->aucBSSID), + prPrimaryBssDesc->ucRCPI, u4PrimAdjRssi, + prPrimaryBssDesc->ucJoinFailureCount); + + ASSERT(!(prCandidateBssDesc->fgIsConnected && prPrimaryBssDesc->fgIsConnected)); + if (prPrimaryBssDesc->ucJoinFailureCount >= SCN_BSS_JOIN_FAIL_THRESOLD) { + /* give a chance to do join if join fail before + * SCN_BSS_DECRASE_JOIN_FAIL_CNT_SEC seconds + */ + if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rJoinFailTime, + SEC_TO_SYSTIME(SCN_BSS_JOIN_FAIL_CNT_RESET_SEC))) { + prBssDesc->ucJoinFailureCount = SCN_BSS_JOIN_FAIL_THRESOLD - + SCN_BSS_JOIN_FAIL_RESET_STEP; + DBGLOG(SCN, INFO, + "decrease join fail count for Bss %pM to %u, timeout second %d\n", + prBssDesc->aucBSSID, prBssDesc->ucJoinFailureCount, + SCN_BSS_JOIN_FAIL_CNT_RESET_SEC); + } + } + /* + * NOTE: To prevent SWING, + * we do roaming only if target AP has at least 5dBm larger than us. + */ +#if CFG_SUPPORT_NCHO + if (prAdapter->rNchoInfo.fgECHOEnabled == TRUE) + ucRCPIStep = 2 * prAdapter->rNchoInfo.i4RoamDelta; +#endif + if (prCandidateBssDesc->fgIsConnected) { + if (u4CandAdjRssi < u4PrimAdjRssi && + prPrimaryBssDesc->ucJoinFailureCount < SCN_BSS_JOIN_FAIL_THRESOLD) { + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } else if (prPrimaryBssDesc->fgIsConnected) { + if (u4CandAdjRssi < u4PrimAdjRssi || + (prCandidateBssDesc->ucJoinFailureCount >= + SCN_BSS_JOIN_FAIL_THRESOLD)) { + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } else if (prPrimaryBssDesc->ucJoinFailureCount >= SCN_BSS_JOIN_FAIL_THRESOLD) + continue; + else if (prCandidateBssDesc->ucJoinFailureCount >= SCN_BSS_JOIN_FAIL_THRESOLD || + u4CandAdjRssi < u4PrimAdjRssi) { + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } +#if 0 + /* If reach here, that means they have the same Encryption Score, and + * both RSSI value are close too. + */ + /* 4 <6F> Seek the minimum Channel Load for less interference. */ + if (fgIsFindMinChannelLoad) { + /* Do nothing */ + /* TODO(Kevin): Check which one has minimum channel load in its channel */ + } +#endif + } + } + + if (prCandidateBssDesc != NULL) { + DBGLOG(SCN, INFO, + "SEARCH: Candidate BSS: %pM, RSSI = %d\n", prCandidateBssDesc->aucBSSID, + RCPI_TO_dBm(prCandidateBssDesc->ucRCPI)); + } else { + DBGLOG(SCN, WARN, "SEARCH: Candidate BSS is NULL\n"); + /* 4 <1> The outer loop to search for a candidate. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + if (EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, + prConnSettings->aucSSID, prConnSettings->ucSSIDLen)) { + fgIsAbsentCandidateBss = FALSE; + DBGLOG(SCN, INFO, "Find %s [%pM] in %d BSS!\n", prBssDesc->aucSSID + , prBssDesc->aucBSSID + , (UINT_32) prBSSDescList->u4NumElem); + } + } + if (fgIsAbsentCandidateBss == TRUE) + DBGLOG(SCN, WARN, "Driver can't find :%s in %d BSS list!\n", prConnSettings->aucSSID + , (UINT_32) prBSSDescList->u4NumElem); + } + + return prCandidateBssDesc; + +} /* end of scanSearchBssDescByPolicy() */ + +#if CFG_SUPPORT_AGPS_ASSIST +VOID scanReportScanResultToAgps(P_ADAPTER_T prAdapter) +{ + P_LINK_T prBSSDescList = &prAdapter->rWifiVar.rScanInfo.rBSSDescList; + P_BSS_DESC_T prBssDesc = NULL; + P_AGPS_AP_LIST_T prAgpsApList; + P_AGPS_AP_INFO_T prAgpsInfo; + P_SCAN_INFO_T prScanInfo = &prAdapter->rWifiVar.rScanInfo; + UINT_8 ucIndex = 0; + + prAgpsApList = kalMemAlloc(sizeof(AGPS_AP_LIST_T), VIR_MEM_TYPE); + if (!prAgpsApList) + return; + + prAgpsInfo = &prAgpsApList->arApInfo[0]; + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + if (prBssDesc->rUpdateTime < prScanInfo->rLastScanCompletedTime) + continue; + COPY_MAC_ADDR(prAgpsInfo->aucBSSID, prBssDesc->aucBSSID); + prAgpsInfo->ePhyType = AGPS_PHY_G; + prAgpsInfo->u2Channel = prBssDesc->ucChannelNum; + prAgpsInfo->i2ApRssi = RCPI_TO_dBm(prBssDesc->ucRCPI); + prAgpsInfo++; + ucIndex++; + if (ucIndex == 32) + break; + } + prAgpsApList->ucNum = ucIndex; + GET_CURRENT_SYSTIME(&prScanInfo->rLastScanCompletedTime); + /* DBGLOG(SCN, INFO, ("num of scan list:%d\n", ucIndex)); */ + kalIndicateAgpsNotify(prAdapter, AGPS_EVENT_WLAN_AP_LIST, (PUINT_8) prAgpsApList, sizeof(AGPS_AP_LIST_T)); + kalMemFree(prAgpsApList, VIR_MEM_TYPE, sizeof(AGPS_AP_LIST_T)); +} +#endif + +VOID scanGetCurrentEssChnlList(P_ADAPTER_T prAdapter) +{ + P_BSS_DESC_T prBssDesc = NULL; + P_LINK_T prBSSDescList = &prAdapter->rWifiVar.rScanInfo.rBSSDescList; + P_CONNECTION_SETTINGS_T prConnSettings = &prAdapter->rWifiVar.rConnSettings; + struct ESS_CHNL_INFO *prEssChnlInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo.arCurEssChnlInfo[0]; + P_LINK_T prCurEssLink = &prAdapter->rWifiVar.rAisSpecificBssInfo.rCurEssLink; + UINT_8 aucChnlBitMap[30] = {0,}; + UINT_8 aucChnlApNum[215] = {0,}; + UINT_8 aucChnlUtil[215] = {0,}; + UINT_8 ucByteNum = 0; + UINT_8 ucBitNum = 0; + UINT_8 ucChnlCount = 0; + UINT_8 j = 0; + /*UINT_8 i = 0;*/ + + if (prConnSettings->ucSSIDLen == 0) { + DBGLOG(SCN, INFO, "No Ess are expected to connect\n"); + return; + } + kalMemZero(prEssChnlInfo, CFG_MAX_NUM_OF_CHNL_INFO * sizeof(struct ESS_CHNL_INFO)); + while (!LINK_IS_EMPTY(prCurEssLink)) { + prBssDesc = LINK_PEEK_HEAD(prCurEssLink, BSS_DESC_T, rLinkEntryEss); + if (LINK_ENTRY_IS_VALID(&prBssDesc->rLinkEntryEss)) { + LINK_REMOVE_KNOWN_ENTRY(prCurEssLink, &prBssDesc->rLinkEntryEss); + } else { + DBGLOG(SCN, WARN, "scanGetCurrentEssChnlList: Invalid prPrev[%d] prNext[%d]\n", + ((((P_LINK_ENTRY_T)&prBssDesc->rLinkEntryEss)->prPrev == NULL) ? -1:0), + ((((P_LINK_ENTRY_T)&prBssDesc->rLinkEntryEss)->prNext == NULL) ? -1:0)); + LINK_INITIALIZE(prCurEssLink); + break; + } + } + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + if (prBssDesc->ucChannelNum > 214) + continue; + /* Statistic AP num for each channel */ + if (aucChnlApNum[prBssDesc->ucChannelNum] < 255) + aucChnlApNum[prBssDesc->ucChannelNum]++; + if (aucChnlUtil[prBssDesc->ucChannelNum] < prBssDesc->ucChnlUtilization) + aucChnlUtil[prBssDesc->ucChannelNum] = prBssDesc->ucChnlUtilization; + if (!EQUAL_SSID(prConnSettings->aucSSID, prConnSettings->ucSSIDLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen)) + continue; + /* Record same BSS list */ + LINK_INSERT_HEAD(prCurEssLink, &prBssDesc->rLinkEntryEss); + ucByteNum = prBssDesc->ucChannelNum / 8; + ucBitNum = prBssDesc->ucChannelNum % 8; + if (aucChnlBitMap[ucByteNum] & BIT(ucBitNum)) + continue; + aucChnlBitMap[ucByteNum] |= BIT(ucBitNum); + prEssChnlInfo[ucChnlCount].ucChannel = prBssDesc->ucChannelNum; + ucChnlCount++; + if (ucChnlCount >= CFG_MAX_NUM_OF_CHNL_INFO) + break; + } + prAdapter->rWifiVar.rAisSpecificBssInfo.ucCurEssChnlInfoNum = ucChnlCount; + for (j = 0; j < ucChnlCount; j++) { + UINT_8 ucChnl = prEssChnlInfo[j].ucChannel; + + prEssChnlInfo[j].ucApNum = aucChnlApNum[ucChnl]; + prEssChnlInfo[j].ucUtilization = aucChnlUtil[ucChnl]; + } +#if 0 + /* Sort according to AP number */ + for (j = 0; j < ucChnlCount; j++) { + for (i = j + 1; i < ucChnlCount; i++) + if (prEssChnlInfo[j].ucApNum > prEssChnlInfo[i].ucApNum) { + struct ESS_CHNL_INFO rTemp = prEssChnlInfo[j]; + + prEssChnlInfo[j] = prEssChnlInfo[i]; + prEssChnlInfo[i] = rTemp; + } + } +#endif + DBGLOG(SCN, INFO, "Find %s in %d BSSes, result %d\n", + prConnSettings->aucSSID, prBSSDescList->u4NumElem, prCurEssLink->u4NumElem); +} + +#define CALCULATE_SCORE_BY_PROBE_RSP(prBssDesc) \ + (WEIGHT_IDX_PROBE_RSP * (prBssDesc->fgSeenProbeResp ? BSS_FULL_SCORE : 0)) + +#define CALCULATE_SCORE_BY_MISS_CNT(prAdapter, prBssDesc) \ + (WEIGHT_IDX_SCN_MISS_CNT * \ + (prAdapter->rWifiVar.rScanInfo.u4ScanUpdateIdx - prBssDesc->u4UpdateIdx > 3 ? 0 : \ + (BSS_FULL_SCORE - (prAdapter->rWifiVar.rScanInfo.u4ScanUpdateIdx - prBssDesc->u4UpdateIdx) * 25))) + +#define CALCULATE_SCORE_BY_BAND(prAdapter, prBssDesc, cRssi) \ + (WEIGHT_IDX_5G_BAND * \ + ((prBssDesc->eBand == BAND_5G && prAdapter->fgEnable5GBand && cRssi > -70) ? BSS_FULL_SCORE : 0)) + +#define CALCULATE_SCORE_BY_STBC(prAdapter, prBssDesc) \ + (WEIGHT_IDX_STBC * \ + (prBssDesc->fgMultiAnttenaAndSTBC ? BSS_FULL_SCORE:0)) + +#define CALCULATE_SCORE_BY_DEAUTH(prBssDesc) \ + (WEIGHT_IDX_DEAUTH_LAST * (prBssDesc->fgDeauthLastTime ? 0:BSS_FULL_SCORE)) + +#if CFG_SUPPORT_RSN_SCORE +#define CALCULATE_SCORE_BY_RSN(prBssDesc) \ + (WEIGHT_IDX_RSN * (prBssDesc->fgIsRSNSuitableBss ? BSS_FULL_SCORE:0)) +#endif + +/* Channel Utilization: weight index will be */ +static UINT_16 scanCalculateScoreByChnlInfo( + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecificBssInfo, UINT_8 ucChannel) +{ + struct ESS_CHNL_INFO *prEssChnlInfo = &prAisSpecificBssInfo->arCurEssChnlInfo[0]; + UINT_8 i = 0; + UINT_16 u2Score = 0; + + for (; i < prAisSpecificBssInfo->ucCurEssChnlInfoNum; i++) { + if (ucChannel == prEssChnlInfo[i].ucChannel) { +#if 0 /* currently, we don't take channel utilization into account */ + /* the channel utilization max value is 255. great utilization means little weight value. + * the step of weight value is 2.6 + */ + u2Score = WEIGHT_IDX_CHNL_UTIL * + (BSS_FULL_SCORE - (prEssChnlInfo[i].ucUtilization * 10 / 26)); +#endif + /* if AP num on this channel is greater than 100, the weight will be 0. + * otherwise, the weight value decrease 1 if AP number increase 1 + */ + if (prEssChnlInfo[i].ucApNum <= CHNL_BSS_NUM_THRESOLD) + u2Score += WEIGHT_IDX_AP_NUM * + (BSS_FULL_SCORE - prEssChnlInfo[i].ucApNum * SCORE_PER_AP); + DBGLOG(SCN, TRACE, "channel %d, AP num %d\n", ucChannel, prEssChnlInfo[i].ucApNum); + break; + } + } + return u2Score; +} + +static UINT_16 scanCalculateScoreByBandwidth(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc) +{ + UINT_16 u2Score = 0; + if (prBssDesc->fgIsHTPresent) { + if (prBssDesc->eBand == BAND_2G4) { + u2Score = (prBssDesc->eSco == 0) ? 60:100; + } else if (prBssDesc->eBand == BAND_5G) { + u2Score = (prBssDesc->eSco == 0) ? 60:100; + } + } else if (prBssDesc->u2BSSBasicRateSet & RATE_SET_OFDM) + u2Score = 20; + else + u2Score = 10; + DBGLOG(SCN, TRACE, "ht %d, eband %d, esco %d, u2Score %d\n", + prBssDesc->fgIsHTPresent, prBssDesc->eBand, prBssDesc->eSco, u2Score); + + return u2Score * WEIGHT_IDX_BAND_WIDTH; +} + +static UINT_16 scanCalculateScoreByClientCnt(P_BSS_DESC_T prBssDesc) +{ + UINT_16 u2Score = 0; + + DBGLOG(SCN, TRACE, "Exist bss load %d, sta cnt %d\n", + prBssDesc->fgExsitBssLoadIE, prBssDesc->u2StaCnt); + + if (!prBssDesc->fgExsitBssLoadIE || prBssDesc->u2StaCnt > BSS_STA_CNT_THRESOLD) + return 0; + + u2Score = BSS_FULL_SCORE - prBssDesc->u2StaCnt * 3; + return u2Score * WEIGHT_IDX_CLIENT_CNT; +} + + +static BOOLEAN scanNeedReplaceCandidate(P_ADAPTER_T prAdapter, P_BSS_DESC_T prCandBss, P_BSS_DESC_T prCurrBss, + UINT_16 u2CandScore, UINT_16 u2CurrScore) +{ + UINT_32 u4UpdateIdx = prAdapter->rWifiVar.rScanInfo.u4ScanUpdateIdx; + UINT_16 u2CandMiss = u4UpdateIdx - prCandBss->u4UpdateIdx; + UINT_16 u2CurrMiss = u4UpdateIdx - prCurrBss->u4UpdateIdx; + INT_8 cCandRssi = RCPI_TO_dBm(prCandBss->ucRCPI); + INT_8 cCurrRssi = RCPI_TO_dBm(prCurrBss->ucRCPI); + + /* 1. No need check score case */ + /* 1.1 Scan missing count of CurrBss is too more, but Candidate is suitable, don't replace */ + if (u2CurrMiss > 2 && u2CurrMiss > u2CandMiss) { + DBGLOG(SCN, INFO, "Scan Miss count of CurrBss > 2, and Candidate <= 2\n"); + return FALSE; + } + /* 1.2 Scan missing count of Candidate is too more, but CurrBss is suitable, replace */ + if (u2CandMiss > 2 && u2CandMiss > u2CurrMiss) { + DBGLOG(SCN, INFO, "Scan Miss count of Candidate > 2, and CurrBss <= 2\n"); + return TRUE; + } + + /* 1.3 Hard connecting RSSI check */ + if ((prCurrBss->eBand == BAND_5G && cCurrRssi < MINIMUM_RSSI_5G) || + (prCurrBss->eBand == BAND_2G4 && cCurrRssi < MINIMUM_RSSI_2G4)) + return FALSE; + else if ((prCandBss->eBand == BAND_5G && cCandRssi < MINIMUM_RSSI_5G) || + (prCandBss->eBand == BAND_2G4 && cCandRssi < MINIMUM_RSSI_2G4)) + return TRUE; + + /* 1.4 prefer to select 5G Bss if Rssi of a 5G band BSS is >= -60dbm */ + if (prCandBss->eBand != prCurrBss->eBand) { + if (prCurrBss->eBand == BAND_5G) { + /* Current AP is 5G, replace candidate AP of current AP is good. */ + if (cCurrRssi >= HIGH_RSSI_FOR_5G_BAND || + (cCandRssi < HIGH_RSSI_FOR_5G_BAND && cCurrRssi > LOW_RSSI_FOR_5G_BAND)) + return TRUE; + else if (cCurrRssi < LOW_RSSI_FOR_5G_BAND && cCurrRssi < cCandRssi) + return FALSE; + } else { + /* Candidate AP is 5G, don't replace it if it's good enough. */ + if (cCandRssi >= HIGH_RSSI_FOR_5G_BAND || + (cCurrRssi < HIGH_RSSI_FOR_5G_BAND && cCandRssi > LOW_RSSI_FOR_5G_BAND)) + return FALSE; + else if (cCandRssi < LOW_RSSI_FOR_5G_BAND && cCandRssi < cCurrRssi) + return TRUE; + } + } + + /* 1.5 RSSI of Current Bss is lower than Candidate, don't replace + ** If the lower Rssi is greater than -59dbm, then no need check the difference + ** Otherwise, if difference is greater than 10dbm, select the good RSSI + */ + if (cCandRssi - cCurrRssi >= RSSI_DIFF_BETWEEN_BSS) + return FALSE; + /* RSSI of Candidate Bss is lower than Current, replace */ + if (cCurrRssi - cCandRssi >= RSSI_DIFF_BETWEEN_BSS) + return TRUE; + + /* 2. Check Score */ + /* 2.1 Cases that no need to replace candidate */ + if (prCandBss->fgIsConnected) { + if ((u2CandScore + ROAMING_NO_SWING_SCORE_STEP) >= u2CurrScore) + return FALSE; + } else if (prCurrBss->fgIsConnected) { + if (u2CandScore >= (u2CurrScore + ROAMING_NO_SWING_SCORE_STEP)) + return FALSE; + } else if (u2CandScore >= u2CurrScore) + return FALSE; + /* 2.2 other cases, replace candidate */ + return TRUE; +} +static BOOLEAN scanSanityCheckBssDesc(P_ADAPTER_T prAdapter, + P_BSS_DESC_T prBssDesc, ENUM_BAND_T eBand, UINT_8 ucChannel, BOOLEAN fgIsFixedChannel) +{ + if (!(prBssDesc->ucPhyTypeSet & (prAdapter->rWifiVar.ucAvailablePhyTypeSet))) { + DBGLOG(SCN, WARN, "SEARCH: Ignore unsupported ucPhyTypeSet = %x\n", + prBssDesc->ucPhyTypeSet); + return FALSE; + } + if (prBssDesc->fgIsUnknownBssBasicRate) + return FALSE; + if (fgIsFixedChannel && + (eBand != prBssDesc->eBand || ucChannel != prBssDesc->ucChannelNum)) { + DBGLOG(SCN, INFO, "Fix channel required band %d, channel %d\n", eBand, ucChannel); + return FALSE; + } + if (!rlmDomainIsLegalChannel(prAdapter, prBssDesc->eBand, prBssDesc->ucChannelNum)) { + DBGLOG(SCN, WARN, "Band %d channel %d is not legal\n", + prBssDesc->eBand, prBssDesc->ucChannelNum); + return FALSE; + } +#if CFG_SUPPORT_WAPI + if (prAdapter->rWifiVar.rConnSettings.fgWapiMode) { + if (!wapiPerformPolicySelection(prAdapter, prBssDesc)) + return FALSE; + } else +#endif + + if (!rsnPerformPolicySelection(prAdapter, prBssDesc)) + return FALSE; + + if (prAdapter->rWifiVar.rAisSpecificBssInfo.fgCounterMeasure) { + DBGLOG(SCN, WARN, "Skip while at counter measure period!!!\n"); + return FALSE; + } + return TRUE; +} +static UINT_16 scanCalculateScoreByRssi(P_BSS_DESC_T prBssDesc) +{ + UINT_16 u2Score = 0; + INT_8 cRssi = RCPI_TO_dBm(prBssDesc->ucRCPI); + + if (cRssi >= -20) + u2Score = BSS_FULL_SCORE; + else if (cRssi >= -55) + u2Score = 95; + else if (cRssi >= -65) + u2Score = 80; + else if (cRssi >= -70) + u2Score = 50; + else if (cRssi >= -77) + u2Score = 15; + else if (cRssi >= -88) + u2Score = 10; + else if (cRssi < -88 && cRssi > -100) + u2Score = 5; + else if (cRssi <= -100) + u2Score = 0; + + u2Score *= WEIGHT_IDX_RSSI; + + return u2Score; +} + +static UINT_16 scanCalculateScoreByBand(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc, INT_8 cRssi) +{ + UINT_16 u2Score = 0; + P_AIS_FSM_INFO_T prAisFsmInfo; + P_ROAMING_INFO_T prRoamingFsmInfo; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + if (prBssDesc->eBand == BAND_5G && prAdapter->fgEnable5GBand && cRssi > -60 + && prRoamingFsmInfo->eCurrentState == ROAMING_STATE_IDLE + && prAisFsmInfo->u4PostponeIndStartTime == 0) + u2Score = (WEIGHT_IDX_5G_BAND * BSS_FULL_SCORE); + + return u2Score; +} + +static UINT_16 scanCalculateScoreBySaa(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc) +{ + UINT_16 u2Score = 0; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + + prStaRec = cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_AIS_INDEX, prBssDesc->aucSrcAddr); + if (prStaRec) + u2Score = WEIGHT_IDX_SAA * (prStaRec->ucTxAuthAssocRetryCount ? 0 : BSS_FULL_SCORE); + else + u2Score = WEIGHT_IDX_SAA * BSS_FULL_SCORE; + + return u2Score; +} + +/***** +*Bss Characteristics to be taken into account when calculate Score: +*Channel Loading Group: +*1. Client Count (in BSS Load IE). +*2. AP number on the Channel. +* +*RF Group: +*1. Channel utilization. +*2. SNR. +*3. RSSI. +* +*Misc Group: +*1. Deauth Last time. +*2. Scan Missing Count. +*3. Has probe response in scan result. +* +*Capability Group: +*1. Prefer 5G band. +*2. Bandwidth. +*3. STBC and Multi Anttena. +*/ +P_BSS_DESC_T scanSearchBssDescByScoreForAis(P_ADAPTER_T prAdapter) +{ + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecificBssInfo = NULL; + P_LINK_T prEssLink = NULL; + P_CONNECTION_SETTINGS_T prConnSettings = NULL; + P_BSS_DESC_T prBssDesc = NULL; + P_BSS_DESC_T prCandBssDesc = NULL; + P_BSS_DESC_T prCandBssDescForLowRssi = NULL; + UINT_16 u2ScoreBand = 0; + UINT_16 u2ScoreChnlInfo = 0; + UINT_16 u2ScoreStaCnt = 0; + UINT_16 u2ScoreProbeRsp = 0; + UINT_16 u2ScoreScanMiss = 0; + UINT_16 u2ScoreBandwidth = 0; + UINT_16 u2ScoreSTBC = 0; + UINT_16 u2ScoreDeauth = 0; + UINT_16 u2ScoreSnrRssi = 0; + UINT_16 u2ScoreTotal = 0; + UINT_16 u2ScoreRSN = 0; + UINT_16 u2ScoreSaa = 0; + UINT_16 u2CandBssScore = 0; + UINT_16 u2CandBssScoreForLowRssi = 0; + UINT_16 u2BlackListScore = 0; + BOOLEAN fgSearchBlackList = FALSE; + BOOLEAN fgIsFixedChannel = FALSE; + ENUM_BAND_T eBand = BAND_2G4; + UINT_8 ucChannel = 0; + INT_8 cRssi = -128; + + if (!prAdapter) { + DBGLOG(SCN, ERROR, "prAdapter is NULL!\n"); + return NULL; + } + prAisSpecificBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prEssLink = &prAisSpecificBssInfo->rCurEssLink; + +#if CFG_SUPPORT_CHNL_CONFLICT_REVISE + fgIsFixedChannel = cnmAisDetectP2PChannel(prAdapter, &eBand, &ucChannel); +#else + fgIsFixedChannel = cnmAisInfraChannelFixed(prAdapter, &eBand, &ucChannel); +#endif + aisRemoveTimeoutBlacklist(prAdapter); + DBGLOG(SCN, INFO, "%s: ConnectionPolicy = %d\n", + __func__, + prConnSettings->eConnectionPolicy); + + +try_again: + LINK_FOR_EACH_ENTRY(prBssDesc, prEssLink, rLinkEntryEss, BSS_DESC_T) { + DBGLOG_MEM8_IE_ONE_LINE(SCN, TRACE, "BCN_IE", &prBssDesc->aucIEBuf[0], prBssDesc->u2IELength); + + if (prConnSettings->eConnectionPolicy == CONNECT_BY_BSSID && + EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prConnSettings->aucBSSID)) { + if (!scanSanityCheckBssDesc(prAdapter, prBssDesc, eBand, ucChannel, fgIsFixedChannel)) + continue; + + prCandBssDesc = prBssDesc; + break; + } +#if CFG_SUPPORT_ROAMING_RETRY + /*STA ingored the BSS which was fail on roamming.*/ + if (prBssDesc->fgIsRoamFail) { + DBGLOG(SCN, INFO, "Roamming fail before ingoring [%pM]!\n", prBssDesc->aucBSSID); + continue; + } +#endif + if (!fgSearchBlackList) { + prBssDesc->prBlack = aisQueryBlackList(prAdapter, prBssDesc); + if (prBssDesc->prBlack) { + if (prBssDesc->prBlack->fgIsInFWKBlacklist == TRUE) + DBGLOG(SCN, INFO, "%s(%pM) is in FWK blacklist, skip it\n", + prBssDesc->aucSSID, prBssDesc->aucBSSID); + continue; + } + } else if (!prBssDesc->prBlack) + continue; + else { + /* never search FWK blacklist even if we are trying blacklist */ + if (prBssDesc->prBlack->fgIsInFWKBlacklist == TRUE) { + DBGLOG(SCN, INFO, "Although trying blacklist, %s(%pM) is in FWK blacklist, skip it\n", + prBssDesc->aucSSID, prBssDesc->aucBSSID); + continue; + } + u2BlackListScore = WEIGHT_IDX_BLACK_LIST * + aisCalculateBlackListScore(prAdapter, prBssDesc); + } + + cRssi = RCPI_TO_dBm(prBssDesc->ucRCPI); + + if (!scanSanityCheckBssDesc(prAdapter, prBssDesc, eBand, ucChannel, fgIsFixedChannel)) + continue; + + u2ScoreBandwidth = scanCalculateScoreByBandwidth(prAdapter, prBssDesc); + u2ScoreStaCnt = scanCalculateScoreByClientCnt(prBssDesc); + u2ScoreSTBC = CALCULATE_SCORE_BY_STBC(prAdapter, prBssDesc); + u2ScoreChnlInfo = scanCalculateScoreByChnlInfo(prAisSpecificBssInfo, prBssDesc->ucChannelNum); + u2ScoreSnrRssi = scanCalculateScoreByRssi(prBssDesc); + u2ScoreDeauth = CALCULATE_SCORE_BY_DEAUTH(prBssDesc); + u2ScoreProbeRsp = CALCULATE_SCORE_BY_PROBE_RSP(prBssDesc); + u2ScoreScanMiss = CALCULATE_SCORE_BY_MISS_CNT(prAdapter, prBssDesc); + u2ScoreBand = scanCalculateScoreByBand(prAdapter, prBssDesc, cRssi); +#if CFG_SUPPORT_RSN_SCORE + u2ScoreRSN = CALCULATE_SCORE_BY_RSN(prBssDesc); +#endif + u2ScoreSaa = scanCalculateScoreBySaa(prAdapter, prBssDesc); + + u2ScoreTotal = u2ScoreBandwidth + u2ScoreChnlInfo + u2ScoreDeauth + u2ScoreProbeRsp + + u2ScoreScanMiss + u2ScoreSnrRssi + u2ScoreStaCnt + u2ScoreSTBC + u2ScoreBand + + u2BlackListScore + u2ScoreRSN + u2ScoreSaa; + + DBGLOG(SCN, INFO, + "%pM cRSSI[%d] 5G[%d] Score, Total %d ", + prBssDesc->aucBSSID, cRssi, (prBssDesc->eBand == BAND_5G ? 1 : 0), u2ScoreTotal); + + DBGLOG(SCN, INFO, + "DE[%d], PR[%d], SM[%d], SR[%d], BA[%d] RSN[%d], SAA[%d], BW[%d], CN[%d], ST[%d], CI[%d]\n", + u2ScoreDeauth, u2ScoreProbeRsp, u2ScoreScanMiss, u2ScoreSnrRssi, u2BlackListScore, + u2ScoreRSN, u2ScoreSaa, u2ScoreBandwidth, u2ScoreStaCnt, u2ScoreSTBC, u2ScoreChnlInfo); + + if (!prCandBssDesc || + scanNeedReplaceCandidate(prAdapter, prCandBssDesc, prBssDesc, u2CandBssScore, u2ScoreTotal)) { + prCandBssDesc = prBssDesc; + u2CandBssScore = u2ScoreTotal; + } + } + + if (prCandBssDesc) { + if (prCandBssDesc->fgIsConnected && !fgSearchBlackList && prEssLink->u4NumElem > 0) { + fgSearchBlackList = TRUE; + DBGLOG(SCN, INFO, "Can't roam out, try blacklist\n"); + goto try_again; + } + if (prConnSettings->eConnectionPolicy == CONNECT_BY_BSSID) + DBGLOG(SCN, INFO, + "Selected %pM (%d) base on bssid, when find %s, %pM in %d BSSes, fix channel %d.\n", + prCandBssDesc->aucBSSID, RCPI_TO_dBm(prCandBssDesc->ucRCPI), prConnSettings->aucSSID, + prConnSettings->aucBSSID, prEssLink->u4NumElem, ucChannel); + else + DBGLOG(SCN, INFO, + "Selected %pM, cRSSI[%d] 5G[%d] Score %d when find %s, %pM in %d BSSes, fix channel %d.\n", + prCandBssDesc->aucBSSID, cRssi = RCPI_TO_dBm(prCandBssDesc->ucRCPI), + (prCandBssDesc->eBand == BAND_5G ? 1 : 0), u2CandBssScore, + prConnSettings->aucSSID, prConnSettings->aucBSSID, prEssLink->u4NumElem, ucChannel); + return prCandBssDesc; + } else if (prCandBssDescForLowRssi) { + DBGLOG(SCN, INFO, "Selected %pM, Score %d when find %s, %pM in %d BSSes, fix channel %d.\n", + prCandBssDescForLowRssi->aucBSSID, u2CandBssScoreForLowRssi, + prConnSettings->aucSSID, prConnSettings->aucBSSID, prEssLink->u4NumElem, ucChannel); + return prCandBssDescForLowRssi; + } + + /* if No Candidate BSS is found, try BSSes which are in blacklist */ + if (!fgSearchBlackList && prEssLink->u4NumElem > 0) { + fgSearchBlackList = TRUE; + DBGLOG(SCN, INFO, "No Bss is found, Try blacklist\n"); + goto try_again; + } + + DBGLOG(SCN, INFO, "Selected None when find %s, %pM in %d BSSes, fix channel %d.\n", + prConnSettings->aucSSID, prConnSettings->aucBSSID, prEssLink->u4NumElem, ucChannel); + return NULL; +} + +VOID scanCollectNeighborBss(P_ADAPTER_T prAdapter) +{ + P_WIFI_VAR_T prWifiVar = &prAdapter->rWifiVar; + PUINT_8 pucNeighborBssBuf = &prWifiVar->rAisSpecificBssInfo.rBTMParam.aucOurNeighborBss[0]; + P_LINK_T prBSSDescList = &prWifiVar->rScanInfo.rBSSDescList; + P_BSS_DESC_T prConnectedBssDesc = prWifiVar->rAisFsmInfo.prTargetBssDesc; + P_BSS_DESC_T prBssDesc = NULL; + PUINT_8 pucConnectedSSID = NULL; + UINT_8 ucSSIDLen = 0; + struct IE_NEIGHBOR_REPORT_T *prReport = (struct IE_NEIGHBOR_REPORT_T *)pucNeighborBssBuf; + + if (prWifiVar->arBssInfo[NETWORK_TYPE_AIS_INDEX].eConnectionState != + PARAM_MEDIA_STATE_CONNECTED || !prConnectedBssDesc) + return; + pucConnectedSSID = &prConnectedBssDesc->aucSSID[0]; + ucSSIDLen = prConnectedBssDesc->ucSSIDLen; + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + if (!EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, pucConnectedSSID, ucSSIDLen)) + continue; + prReport->ucId = ELEM_ID_NEIGHBOR_REPORT; + COPY_MAC_ADDR(prReport->aucBSSID, prBssDesc->aucBSSID); + prReport->ucChnlNumber = prBssDesc->ucChannelNum; + prReport->ucPhyType = prBssDesc->ucPhyTypeSet; + } +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/scan_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/scan_fsm.c new file mode 100644 index 0000000000000..bbf675b8a7b5d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/scan_fsm.c @@ -0,0 +1,2460 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if DBG +/*lint -save -e64 Type mismatch */ +static PUINT_8 apucDebugScanState[SCAN_STATE_NUM] = { + (PUINT_8) DISP_STRING("SCAN_STATE_IDLE"), + (PUINT_8) DISP_STRING("SCAN_STATE_SCANNING"), +}; + +/*lint -restore */ +#endif /* DBG */ + +#define CURRENT_PSCN_VERSION 1 +#define RSSI_MARGIN_DEFAULT 5 +#define MAX_PERIOD 200000 + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnFsmSteps(IN P_ADAPTER_T prAdapter, IN ENUM_SCAN_STATE_T eNextState) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + P_MSG_HDR_T prMsgHdr; + + BOOLEAN fgIsTransition = (BOOLEAN) FALSE; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + do { + +#if DBG + DBGLOG(SCN, STATE, "TRANSITION: [%s] -> [%s]\n", + apucDebugScanState[prScanInfo->eCurrentState], apucDebugScanState[eNextState]); +#else + DBGLOG(SCN, STATE, "[%d] TRANSITION: [%d] -> [%d]\n", + DBG_SCN_IDX, prScanInfo->eCurrentState, eNextState); +#endif + + /* NOTE(Kevin): This is the only place to change the eCurrentState(except initial) */ + prScanInfo->eCurrentState = eNextState; + + fgIsTransition = (BOOLEAN) FALSE; + + switch (prScanInfo->eCurrentState) { + case SCAN_STATE_IDLE: + /* check for pending scanning requests */ + if (!cnmChUtilIsRunning(prAdapter) && !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: + prScanInfo->u4ScanUpdateIdx++; + if (prScanParam->fgIsScanV2 == FALSE) + scnSendScanReq(prAdapter); + else + scnSendScanReqV2(prAdapter); + break; + + default: + ASSERT(0); + break; + + } + } while (fgIsTransition); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Generate CMD_ID_SCAN_REQ command +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnSendScanReqExtCh(IN P_ADAPTER_T prAdapter) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + /*CMD_SCAN_REQ_EXT_CH rCmdScanReq;*/ + P_CMD_SCAN_REQ_EXT_CH prCmdScanReq; + UINT_32 i; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + prCmdScanReq = kalMemAlloc(sizeof(CMD_SCAN_REQ_EXT_CH), VIR_MEM_TYPE); + if (prCmdScanReq == NULL) { + DBGLOG(SCN, ERROR, "alloc CmdScanReq V1EXT fail"); + return; + } + + /* send command packet for scan */ + kalMemZero(prCmdScanReq, sizeof(CMD_SCAN_REQ_EXT_CH)); + + prCmdScanReq->ucSeqNum = prScanParam->ucSeqNum; + prCmdScanReq->ucNetworkType = (UINT_8) prScanParam->eNetTypeIndex; + prCmdScanReq->ucScanType = (UINT_8) prScanParam->eScanType; + prCmdScanReq->ucSSIDType = prScanParam->ucSSIDType; + + if (prScanParam->ucSSIDNum == 1) { + COPY_SSID(prCmdScanReq->aucSSID, + prCmdScanReq->ucSSIDLength, + prScanParam->aucSpecifiedSSID[0], prScanParam->ucSpecifiedSSIDLen[0]); + } + + prCmdScanReq->ucChannelType = (UINT_8) prScanParam->eScanChannel; + + if (prScanParam->eScanChannel == SCAN_CHANNEL_SPECIFIED) { + /* P2P would use: + * 1. Specified Listen Channel of passive scan for LISTEN state. + * 2. Specified Listen Channel of Target Device of active scan for SEARCH state. (Target != NULL) + */ + prCmdScanReq->ucChannelListNum = prScanParam->ucChannelListNum; + + for (i = 0; i < prCmdScanReq->ucChannelListNum; i++) { + prCmdScanReq->arChannelList[i].ucBand = (UINT_8) prScanParam->arChnlInfoList[i].eBand; + + prCmdScanReq->arChannelList[i].ucChannelNum = + (UINT_8) prScanParam->arChnlInfoList[i].ucChannelNum; + } + } +#if CFG_ENABLE_WIFI_DIRECT + if (prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + if (prP2pBssInfo == NULL) { + DBGLOG(P2P, ERROR, "scnSendScanReqExtCh prP2pBssInfo is NULL\n"); + return; + } +#if CFG_TC10_FEATURE + /* + * mtk supplicant will scan 4 channels for prograssive scan + * customer supplicant should have 3 channels when do social scan + */ + if (prScanParam->ucChannelListNum <= 4) { + DBGLOG(P2P, INFO, "scnSendScanReqExtCh Channel number %d for 70ms, OP_MODE[%d]\n", + prScanParam->ucChannelListNum, prP2pBssInfo->eCurrentOPMode); + prCmdScanReq->u2ChannelDwellTime = 70; + } else if (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + DBGLOG(P2P, INFO, "scnSendScanReqExtCh Channel number %d for 100ms, OP_MODE[%d]\n", + prScanParam->ucChannelListNum, prP2pBssInfo->eCurrentOPMode); + prCmdScanReq->u2ChannelDwellTime = 100; + } else + prCmdScanReq->u2ChannelDwellTime = 30; +#else + prCmdScanReq->u2ChannelDwellTime = prScanParam->u2PassiveListenInterval; +#endif + } +#endif + + if (prScanParam->u2IELen <= MAX_IE_LENGTH) + prCmdScanReq->u2IELen = prScanParam->u2IELen; + else + prCmdScanReq->u2IELen = MAX_IE_LENGTH; + + if (prScanParam->u2IELen) + kalMemCopy(prCmdScanReq->aucIE, prScanParam->aucIE, sizeof(UINT_8) * prCmdScanReq->u2IELen); + + DBGLOG(SCN, INFO, "ScanReqV1EXT: ScanType=%d, SSIDType=%d, Num=%d, ChannelType=%d, Num=%d", + prCmdScanReq->ucScanType, prCmdScanReq->ucSSIDType, prScanParam->ucSSIDNum, + prCmdScanReq->ucChannelType, prCmdScanReq->ucChannelListNum); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SCAN_REQ, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + OFFSET_OF(CMD_SCAN_REQ_EXT_CH, aucIE) + prCmdScanReq->u2IELen, + (PUINT_8) prCmdScanReq, NULL, 0); + /* sanity check for some scan parameters */ + if (prCmdScanReq->ucScanType >= SCAN_TYPE_NUM) + kalSendAeeWarning("wlan", "wrong scan type %d", prCmdScanReq->ucScanType); + else if (prCmdScanReq->ucChannelType >= SCAN_CHANNEL_NUM) + kalSendAeeWarning("wlan", "wrong channel type %d", prCmdScanReq->ucChannelType); + else if (prCmdScanReq->ucChannelType != SCAN_CHANNEL_SPECIFIED && + prCmdScanReq->ucChannelListNum != 0) + kalSendAeeWarning("wlan", + "channel list is not NULL but channel type is not specified"); + else if (prCmdScanReq->ucNetworkType >= NETWORK_TYPE_INDEX_NUM) + kalSendAeeWarning("wlan", "wrong network type %d", prCmdScanReq->ucNetworkType); + else if (prCmdScanReq->ucSSIDType >= BIT(4)) /* ssid type is wrong */ + kalSendAeeWarning("wlan", "wrong ssid type %d", prCmdScanReq->ucSSIDType); + else if (prCmdScanReq->ucSSIDLength > 32) + kalSendAeeWarning("wlan", "wrong ssid length %d", prCmdScanReq->ucSSIDLength); + + kalMemFree(prCmdScanReq, VIR_MEM_TYPE, sizeof(CMD_SCAN_REQ_EXT_CH)); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Generate CMD_ID_SCAN_REQ command +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnSendScanReq(IN P_ADAPTER_T prAdapter) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + /*CMD_SCAN_REQ rCmdScanReq;*/ + P_CMD_SCAN_REQ prCmdScanReq; + UINT_32 i; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + if (prScanParam->ucChannelListNum > 32) { + scnSendScanReqExtCh(prAdapter); + } else { + prCmdScanReq = kalMemAlloc(sizeof(CMD_SCAN_REQ), VIR_MEM_TYPE); + if (prCmdScanReq == NULL) { + DBGLOG(SCN, ERROR, "alloc CmdScanReq V1 fail"); + return; + } + /* send command packet for scan */ + kalMemZero(prCmdScanReq, sizeof(CMD_SCAN_REQ)); + prCmdScanReq->ucStructVersion = 1; + COPY_MAC_ADDR(prCmdScanReq->aucBSSID, prScanParam->aucBSSID); + if (!EQUAL_MAC_ADDR(prCmdScanReq->aucBSSID, "\xff\xff\xff\xff\xff\xff")) + DBGLOG(SCN, INFO, "Include BSSID %pM in probe request, NetIdx %d\n", + prCmdScanReq->aucBSSID, prScanParam->eNetTypeIndex); + prCmdScanReq->ucSeqNum = prScanParam->ucSeqNum; + prCmdScanReq->ucNetworkType = (UINT_8) prScanParam->eNetTypeIndex; + prCmdScanReq->ucScanType = (UINT_8) prScanParam->eScanType; + prCmdScanReq->ucSSIDType = prScanParam->ucSSIDType; + + if (prScanParam->ucSSIDNum == 1) { + COPY_SSID(prCmdScanReq->aucSSID, + prCmdScanReq->ucSSIDLength, + prScanParam->aucSpecifiedSSID[0], prScanParam->ucSpecifiedSSIDLen[0]); + } + + prCmdScanReq->ucChannelType = (UINT_8) prScanParam->eScanChannel; + + if (prScanParam->eScanChannel == SCAN_CHANNEL_SPECIFIED) { + /* P2P would use: + * 1. Specified Listen Channel of passive scan for LISTEN state. + * 2. Specified Listen Channel of Target Device of active scan for SEARCH state. + * (Target != NULL) + */ + prCmdScanReq->ucChannelListNum = prScanParam->ucChannelListNum; + + for (i = 0; i < prCmdScanReq->ucChannelListNum; i++) { + prCmdScanReq->arChannelList[i].ucBand = (UINT_8) prScanParam->arChnlInfoList[i].eBand; + + prCmdScanReq->arChannelList[i].ucChannelNum = + (UINT_8) prScanParam->arChnlInfoList[i].ucChannelNum; + } + } +#if CFG_ENABLE_WIFI_DIRECT + if (prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + if (prP2pBssInfo == NULL) { + DBGLOG(P2P, ERROR, "scnSendScanReq prP2pBssInfo is NULL\n"); + return; + } +#if CFG_TC10_FEATURE + /* + * mtk supplicant will scan 4 channels for prograssive scan + * customer supplicant should have 3 channels when do social scan + */ + if (prScanParam->ucChannelListNum <= 4) { + DBGLOG(P2P, INFO, "scnSendScanReq Channel number %d for 70ms, OP_MODE[%d]\n", + prScanParam->ucChannelListNum, prP2pBssInfo->eCurrentOPMode); + prCmdScanReq->u2ChannelDwellTime = 70; + } else if (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + DBGLOG(P2P, INFO, "scnSendScanReq Channel number %d for 100ms, OP_MODE[%d]\n", + prScanParam->ucChannelListNum, prP2pBssInfo->eCurrentOPMode); + prCmdScanReq->u2ChannelDwellTime = 100; + } else + prCmdScanReq->u2ChannelDwellTime = 30; +#else + prCmdScanReq->u2ChannelDwellTime = prScanParam->u2PassiveListenInterval; +#endif + } +#endif +#if CFG_ENABLE_FAST_SCAN + if (prScanParam->eNetTypeIndex == NETWORK_TYPE_AIS_INDEX) + prCmdScanReq->u2ChannelDwellTime = CFG_FAST_SCAN_DWELL_TIME; +#endif + if (prScanParam->eNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { + prCmdScanReq->u2ChannelDwellTime = prScanParam->u2ChannelDwellTime; + prCmdScanReq->u2ChannelMinDwellTime = prScanParam->u2MinChannelDwellTime; + } + + if (prScanParam->u2IELen <= MAX_IE_LENGTH) + prCmdScanReq->u2IELen = prScanParam->u2IELen; + else + prCmdScanReq->u2IELen = MAX_IE_LENGTH; + + if (prScanParam->u2IELen) + kalMemCopy(prCmdScanReq->aucIE, prScanParam->aucIE, sizeof(UINT_8) * prCmdScanReq->u2IELen); + + DBGLOG(SCN, INFO, "ScanReqV1: ScanType=%d, SSIDType=%d, Num=%d, ChannelType=%d, Num=%d", + prCmdScanReq->ucScanType, prCmdScanReq->ucSSIDType, prScanParam->ucSSIDNum, + prCmdScanReq->ucChannelType, prCmdScanReq->ucChannelListNum); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SCAN_REQ, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + OFFSET_OF(CMD_SCAN_REQ, aucIE) + prCmdScanReq->u2IELen, + (PUINT_8) prCmdScanReq, NULL, 0); + /* sanity check for some scan parameters */ + if (prCmdScanReq->ucScanType >= SCAN_TYPE_NUM) + kalSendAeeWarning("wlan", "wrong scan type %d", prCmdScanReq->ucScanType); + else if (prCmdScanReq->ucChannelType >= SCAN_CHANNEL_NUM) + kalSendAeeWarning("wlan", "wrong channel type %d", prCmdScanReq->ucChannelType); + else if (prCmdScanReq->ucChannelType != SCAN_CHANNEL_SPECIFIED && + prCmdScanReq->ucChannelListNum != 0) + kalSendAeeWarning("wlan", + "channel list is not NULL but channel type is not specified"); + else if (prCmdScanReq->ucNetworkType >= NETWORK_TYPE_INDEX_NUM) + kalSendAeeWarning("wlan", "wrong network type %d", prCmdScanReq->ucNetworkType); + else if (prCmdScanReq->ucSSIDType >= BIT(4)) /* ssid type is wrong */ + kalSendAeeWarning("wlan", "wrong ssid type %d", prCmdScanReq->ucSSIDType); + else if (prCmdScanReq->ucSSIDLength > 32) + kalSendAeeWarning("wlan", "wrong ssid length %d", prCmdScanReq->ucSSIDLength); + + kalMemFree(prCmdScanReq, VIR_MEM_TYPE, sizeof(CMD_SCAN_REQ)); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Generate CMD_ID_SCAN_REQ_V2 command +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnSendScanReqV2ExtCh(IN P_ADAPTER_T prAdapter) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + /*CMD_SCAN_REQ_V2_EXT_CH rCmdScanReq;*/ + P_CMD_SCAN_REQ_V2_EXT_CH prCmdScanReq; + UINT_32 i; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + prCmdScanReq = kalMemAlloc(sizeof(CMD_SCAN_REQ_V2_EXT_CH), VIR_MEM_TYPE); + if (prCmdScanReq == NULL) { + DBGLOG(SCN, ERROR, "alloc CmdScanReq V2EXT fail"); + return; + } + + /* send command packet for scan */ + kalMemZero(prCmdScanReq, sizeof(CMD_SCAN_REQ_V2_EXT_CH)); + + prCmdScanReq->ucSeqNum = prScanParam->ucSeqNum; + prCmdScanReq->ucNetworkType = (UINT_8) prScanParam->eNetTypeIndex; + prCmdScanReq->ucScanType = (UINT_8) prScanParam->eScanType; + prCmdScanReq->ucSSIDType = prScanParam->ucSSIDType; + + for (i = 0; i < prScanParam->ucSSIDNum; i++) { + COPY_SSID(prCmdScanReq->arSSID[i].aucSsid, + prCmdScanReq->arSSID[i].u4SsidLen, + prScanParam->aucSpecifiedSSID[i], prScanParam->ucSpecifiedSSIDLen[i]); + } + + prCmdScanReq->u2ProbeDelayTime = (UINT_8) prScanParam->u2ProbeDelayTime; + prCmdScanReq->ucChannelType = (UINT_8) prScanParam->eScanChannel; + + if (prScanParam->eScanChannel == SCAN_CHANNEL_SPECIFIED) { + /* P2P would use: + * 1. Specified Listen Channel of passive scan for LISTEN state. + * 2. Specified Listen Channel of Target Device of active scan for SEARCH state. (Target != NULL) + */ + prCmdScanReq->ucChannelListNum = prScanParam->ucChannelListNum; + + for (i = 0; i < prCmdScanReq->ucChannelListNum; i++) { + prCmdScanReq->arChannelList[i].ucBand = (UINT_8) prScanParam->arChnlInfoList[i].eBand; + + prCmdScanReq->arChannelList[i].ucChannelNum = + (UINT_8) prScanParam->arChnlInfoList[i].ucChannelNum; + } + } +#if CFG_ENABLE_WIFI_DIRECT + if (prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + if (prP2pBssInfo == NULL) { + DBGLOG(P2P, ERROR, "scnSendScanReqV2ExtCh prP2pBssInfo is NULL\n"); + return; + } +#if CFG_TC10_FEATURE + /* + * mtk supplicant will scan 4 channels for prograssive scan + * customer supplicant should have 3 channels when do social scan + */ + if (prScanParam->ucChannelListNum <= 4) { + DBGLOG(P2P, INFO, "scnSendScanReqV2ExtCh Channel number %d for 70ms, OP_MODE[%d]\n", + prScanParam->ucChannelListNum, prP2pBssInfo->eCurrentOPMode); + prCmdScanReq->u2ChannelDwellTime = 70; + } else if (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + DBGLOG(P2P, INFO, "scnSendScanReqV2ExtCh Channel number %d for 100ms, OP_MODE[%d]\n", + prScanParam->ucChannelListNum, prP2pBssInfo->eCurrentOPMode); + prCmdScanReq->u2ChannelDwellTime = 100; + } else + prCmdScanReq->u2ChannelDwellTime = 30; +#else + prCmdScanReq->u2ChannelDwellTime = prScanParam->u2PassiveListenInterval; +#endif + } +#endif + + if (prScanParam->u2IELen <= MAX_IE_LENGTH) + prCmdScanReq->u2IELen = prScanParam->u2IELen; + else + prCmdScanReq->u2IELen = MAX_IE_LENGTH; + + if (prScanParam->u2IELen) + kalMemCopy(prCmdScanReq->aucIE, prScanParam->aucIE, sizeof(UINT_8) * prCmdScanReq->u2IELen); + + DBGLOG(SCN, INFO, "ScanReqV2EXT: ScanType=%d, SSIDType=%d, Num=%d, ChannelType=%d, Num=%d", + prCmdScanReq->ucScanType, prCmdScanReq->ucSSIDType, prScanParam->ucSSIDNum, + prCmdScanReq->ucChannelType, prCmdScanReq->ucChannelListNum); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SCAN_REQ_V2, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + OFFSET_OF(CMD_SCAN_REQ_V2_EXT_CH, aucIE) + prCmdScanReq->u2IELen, + (PUINT_8) prCmdScanReq, NULL, 0); + /* sanity check for some scan parameters */ + if (prCmdScanReq->ucScanType >= SCAN_TYPE_NUM) + kalSendAeeWarning("wlan", "wrong scan type %d", prCmdScanReq->ucScanType); + else if (prCmdScanReq->ucChannelType >= SCAN_CHANNEL_NUM) + kalSendAeeWarning("wlan", "wrong channel type %d", prCmdScanReq->ucChannelType); + else if (prCmdScanReq->ucChannelType != SCAN_CHANNEL_SPECIFIED && + prCmdScanReq->ucChannelListNum != 0) + kalSendAeeWarning("wlan", + "channel list is not NULL but channel type is not specified"); + else if (prCmdScanReq->ucNetworkType >= NETWORK_TYPE_INDEX_NUM) + kalSendAeeWarning("wlan", "wrong network type %d", prCmdScanReq->ucNetworkType); + else if (prCmdScanReq->ucSSIDType >= BIT(4)) /* ssid type is wrong */ + kalSendAeeWarning("wlan", "wrong ssid type %d", prCmdScanReq->ucSSIDType); + + kalMemFree(prCmdScanReq, VIR_MEM_TYPE, sizeof(CMD_SCAN_REQ_V2_EXT_CH)); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Generate CMD_ID_SCAN_REQ_V3 command +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnSendScanReqV3ExtCh(IN P_ADAPTER_T prAdapter) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + /* P_CMD_SCAN_REQ_V3_EXT_CH prCmdScanReqV3; ScanReqV4 replace of ScanReqV3 for random MAC */ + struct CMD_SCAN_REQ_V4_EXT_CH *prCmdScanReqV4; + UINT_32 i; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + prCmdScanReqV4 = kalMemAlloc(sizeof(struct CMD_SCAN_REQ_V4_EXT_CH), VIR_MEM_TYPE); + if (prCmdScanReqV4 == NULL) { + DBGLOG(SCN, ERROR, "alloc CmdScanReq V4EXT fail"); + return; + } + /* send command packet for scan */ + kalMemZero(prCmdScanReqV4, sizeof(struct CMD_SCAN_REQ_V4_EXT_CH)); + + prCmdScanReqV4->ucSeqNum = prScanParam->ucSeqNum; + prCmdScanReqV4->ucNetworkType = (UINT_8) prScanParam->eNetTypeIndex; + prCmdScanReqV4->ucScanType = (UINT_8) prScanParam->eScanType; + prCmdScanReqV4->ucSSIDType = prScanParam->ucSSIDType; + + if (kalIsValidMacAddr(prScanParam->aucRandomMac)) { + prCmdScanReqV4->ucScnFuncMask |= ENUM_SCN_RANDOM_MAC_EN; + kalMemCopy(prCmdScanReqV4->aucRandomMac, + prScanParam->aucRandomMac, MAC_ADDR_LEN); + } + kalMemCopy(prCmdScanReqV4->arSSID[0].aucSsid, "CMD_SCAN_REQ_V4_T", strlen("CMD_SCAN_REQ_V4_T")); + prCmdScanReqV4->arSSID[0].u4SsidLen = 0; + for (i = 1; i <= prScanParam->ucSSIDNum; i++) { + COPY_SSID(prCmdScanReqV4->arSSID[i].aucSsid, + prCmdScanReqV4->arSSID[i].u4SsidLen, + prScanParam->aucSpecifiedSSID[i - 1], prScanParam->ucSpecifiedSSIDLen[i - 1]); + } + + prCmdScanReqV4->u2ProbeDelayTime = (UINT_8) prScanParam->u2ProbeDelayTime; + prCmdScanReqV4->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) + */ + prCmdScanReqV4->ucChannelListNum = prScanParam->ucChannelListNum; + + for (i = 0; i < prCmdScanReqV4->ucChannelListNum; i++) { + prCmdScanReqV4->arChannelList[i].ucBand = (UINT_8) prScanParam->arChnlInfoList[i].eBand; + + prCmdScanReqV4->arChannelList[i].ucChannelNum = + (UINT_8) prScanParam->arChnlInfoList[i].ucChannelNum; + } + } +#if CFG_ENABLE_WIFI_DIRECT + if (prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + if (prP2pBssInfo == NULL) { + DBGLOG(P2P, ERROR, "scnSendScanReqV4ExtCh prP2pBssInfo is NULL\n"); + return; + } +#if CFG_TC10_FEATURE + /* + * mtk supplicant will scan 4 channels for prograssive scan + * customer supplicant should have 3 channels when do social scan + */ + if (prScanParam->ucChannelListNum <= 4) { + DBGLOG(P2P, INFO, "scnSendScanReqV4ExtCh Channel number %d for 70ms, OP_MODE[%d]\n", + prScanParam->ucChannelListNum, prP2pBssInfo->eCurrentOPMode); + prCmdScanReqV4->u2ChannelDwellTime = 70; + } else if (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + DBGLOG(P2P, INFO, "scnSendScanReqV4ExtCh Channel number %d for 100ms, OP_MODE[%d]\n", + prScanParam->ucChannelListNum, prP2pBssInfo->eCurrentOPMode); + prCmdScanReqV4->u2ChannelDwellTime = 100; + } else + prCmdScanReqV4->u2ChannelDwellTime = 30; +#else + prCmdScanReqV4->u2ChannelDwellTime = prScanParam->u2PassiveListenInterval; +#endif + } +#endif + + if (prScanParam->u2IELen <= MAX_IE_LENGTH) + prCmdScanReqV4->u2IELen = prScanParam->u2IELen; + else + prCmdScanReqV4->u2IELen = MAX_IE_LENGTH; + + if (prScanParam->u2IELen) + kalMemCopy(prCmdScanReqV4->aucIE, prScanParam->aucIE, sizeof(UINT_8) * prCmdScanReqV4->u2IELen); + + DBGLOG(SCN, INFO, "ScanReqV4EXT: ScanType=%d, SSIDType=%d, Num=%d, ChannelType=%d, Num=%d, Mask=%d, Mac=" + MACSTR"\n", + prCmdScanReqV4->ucScanType, prCmdScanReqV4->ucSSIDType, prScanParam->ucSSIDNum, + prCmdScanReqV4->ucChannelType, prCmdScanReqV4->ucChannelListNum, + prCmdScanReqV4->ucScnFuncMask, MAC2STR(prCmdScanReqV4->aucRandomMac)); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SCAN_REQ_V2, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_SCAN_REQ_V4_EXT_CH), + (PUINT_8)prCmdScanReqV4, NULL, 0); + + kalMemFree(prCmdScanReqV4, VIR_MEM_TYPE, sizeof(struct CMD_SCAN_REQ_V4_EXT_CH)); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Generate CMD_ID_SCAN_REQ_V2 command +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnSendScanReqV2(IN P_ADAPTER_T prAdapter) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + /* P_CMD_SCAN_REQ_V2 prCmdScanReq; */ + /* P_CMD_SCAN_REQ_V3 prCmdScanReqV3; ScanReqV3 replace of ScanReqV2 for multi SSID feature */ + struct CMD_SCAN_REQ_V4 *prCmdScanReqV4; /* ScanReqV4 replace of ScanReqV3 for random MAC */ + UINT_32 i; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + if (prScanParam->ucChannelListNum > 32) { + scnSendScanReqV3ExtCh(prAdapter); + } else { + prCmdScanReqV4 = kalMemAlloc(sizeof(struct CMD_SCAN_REQ_V4), VIR_MEM_TYPE); + if (prCmdScanReqV4 == NULL) { + DBGLOG(SCN, ERROR, "alloc CmdScanReq V4 fail"); + return; + } + /* send command packet for scan */ + kalMemZero(prCmdScanReqV4, sizeof(struct CMD_SCAN_REQ_V4)); + + prCmdScanReqV4->ucSeqNum = prScanParam->ucSeqNum; + prCmdScanReqV4->ucNetworkType = (UINT_8) prScanParam->eNetTypeIndex; + prCmdScanReqV4->ucScanType = (UINT_8) prScanParam->eScanType; + prCmdScanReqV4->ucSSIDType = prScanParam->ucSSIDType; + if (kalIsValidMacAddr(prScanParam->aucRandomMac)) { + prCmdScanReqV4->ucScnFuncMask |= ENUM_SCN_RANDOM_MAC_EN; + kalMemCopy(prCmdScanReqV4->aucRandomMac, + prScanParam->aucRandomMac, MAC_ADDR_LEN); + } + + /* After android R, gen2 must support scan random MAC + * modify scan req from V3 to V4 to add random MAC related + * variables. FW will recognize "CMD_SCAN_REQ_V4_T" to decide + * use random MAC or not. + */ + kalMemCopy(prCmdScanReqV4->arSSID[0].aucSsid, "CMD_SCAN_REQ_V4_T", strlen("CMD_SCAN_REQ_V4_T")); + prCmdScanReqV4->arSSID[0].u4SsidLen = 0; + for (i = 1; i <= prScanParam->ucSSIDNum; i++) { + COPY_SSID(prCmdScanReqV4->arSSID[i].aucSsid, + prCmdScanReqV4->arSSID[i].u4SsidLen, + prScanParam->aucSpecifiedSSID[i - 1], + prScanParam->ucSpecifiedSSIDLen[i - 1]); + } + + prCmdScanReqV4->u2ProbeDelayTime = (UINT_8) prScanParam->u2ProbeDelayTime; + prCmdScanReqV4->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) + */ + prCmdScanReqV4->ucChannelListNum = prScanParam->ucChannelListNum; + + for (i = 0; i < prCmdScanReqV4->ucChannelListNum; i++) { + prCmdScanReqV4->arChannelList[i].ucBand = + (UINT_8) prScanParam->arChnlInfoList[i].eBand; + + prCmdScanReqV4->arChannelList[i].ucChannelNum = + (UINT_8) prScanParam->arChnlInfoList[i].ucChannelNum; + } + } +#if CFG_ENABLE_WIFI_DIRECT + if (prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + if (prP2pBssInfo == NULL) { + DBGLOG(P2P, ERROR, "scnSendScanReqV4 prP2pBssInfo is NULL\n"); + return; + } +#if CFG_TC10_FEATURE + /* + * mtk supplicant will scan 4 channels for prograssive scan + * customer supplicant should have 3 channels when do social scan + */ + if (prScanParam->ucChannelListNum <= 4) { + DBGLOG(P2P, INFO, "scnSendScanReqV4 Channel number %d for 70ms, OP_MODE[%d]\n", + prScanParam->ucChannelListNum, prP2pBssInfo->eCurrentOPMode); + prCmdScanReqV4->u2ChannelDwellTime = 70; + } else if (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + DBGLOG(P2P, INFO, "scnSendScanReqV4 Channel number %d for 100ms, OP_MODE[%d]\n", + prScanParam->ucChannelListNum, prP2pBssInfo->eCurrentOPMode); + prCmdScanReqV4->u2ChannelDwellTime = 100; + } else + prCmdScanReqV4->u2ChannelDwellTime = 30; +#else + prCmdScanReqV4->u2ChannelDwellTime = prScanParam->u2PassiveListenInterval; +#endif + } +#endif + if (prScanParam->u2IELen <= MAX_IE_LENGTH) + prCmdScanReqV4->u2IELen = prScanParam->u2IELen; + else + prCmdScanReqV4->u2IELen = MAX_IE_LENGTH; + + if (prScanParam->u2IELen) + kalMemCopy(prCmdScanReqV4->aucIE, prScanParam->aucIE, + sizeof(UINT_8) * prCmdScanReqV4->u2IELen); + + DBGLOG(SCN, INFO, "ScanReqV4: ScanType=%d, SSIDType=%d, Num=%d, ChannelType=%d, Num=%d, Mask=%d, Mac=" + MACSTR"\n", + prCmdScanReqV4->ucScanType, prCmdScanReqV4->ucSSIDType, prScanParam->ucSSIDNum, + prCmdScanReqV4->ucChannelType, prCmdScanReqV4->ucChannelListNum, + prCmdScanReqV4->ucScnFuncMask, MAC2STR(prCmdScanReqV4->aucRandomMac)); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SCAN_REQ_V2, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_SCAN_REQ_V4), + (PUINT_8) prCmdScanReqV4, NULL, 0); + + /* sanity check for some scan parameters */ + if (prCmdScanReqV4->ucScanType >= SCAN_TYPE_NUM) + kalSendAeeWarning("wlan", "wrong scan type %d", prCmdScanReqV4->ucScanType); + else if (prCmdScanReqV4->ucChannelType >= SCAN_CHANNEL_NUM) + kalSendAeeWarning("wlan", "wrong channel type %d", prCmdScanReqV4->ucChannelType); + else if (prCmdScanReqV4->ucChannelType != SCAN_CHANNEL_SPECIFIED && + prCmdScanReqV4->ucChannelListNum != 0) + kalSendAeeWarning("wlan", + "channel list is not NULL but channel type is not specified"); + else if (prCmdScanReqV4->ucNetworkType >= NETWORK_TYPE_INDEX_NUM) + kalSendAeeWarning("wlan", "wrong network type %d", prCmdScanReqV4->ucNetworkType); + else if (prCmdScanReqV4->ucSSIDType >= BIT(4)) /* ssid type is wrong */ + kalSendAeeWarning("wlan", "wrong ssid type %d", prCmdScanReqV4->ucSSIDType); + + kalMemFree(prCmdScanReqV4, VIR_MEM_TYPE, sizeof(struct CMD_SCAN_REQ_V4)); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 (prMsgHdr->eMsgId == MID_MNY_CNM_SCAN_CONTINUE) { + cnmMemFree(prAdapter, prMsgHdr); + scnFsmSteps(prAdapter, SCAN_STATE_IDLE); + } else if (prScanInfo->eCurrentState == SCAN_STATE_IDLE && !cnmChUtilIsRunning(prAdapter)) { + if (prMsgHdr->eMsgId == MID_AIS_SCN_SCAN_REQ + || prMsgHdr->eMsgId == MID_BOW_SCN_SCAN_REQ + || prMsgHdr->eMsgId == MID_P2P_SCN_SCAN_REQ || prMsgHdr->eMsgId == MID_RLM_SCN_SCAN_REQ) { + scnFsmHandleScanMsg(prAdapter, (P_MSG_SCN_SCAN_REQ) prMsgHdr); + } else if (prMsgHdr->eMsgId == MID_AIS_SCN_SCAN_REQ_V2 + || prMsgHdr->eMsgId == MID_BOW_SCN_SCAN_REQ_V2 + || prMsgHdr->eMsgId == MID_P2P_SCN_SCAN_REQ_V2 + || prMsgHdr->eMsgId == MID_RLM_SCN_SCAN_REQ_V2) { + scnFsmHandleScanMsgV2(prAdapter, (P_MSG_SCN_SCAN_REQ_V2) prMsgHdr); + } else { + /* should not deliver to this function */ + ASSERT(0); + } + + cnmMemFree(prAdapter, prMsgHdr); + scnFsmSteps(prAdapter, SCAN_STATE_SCANNING); + } else { + LINK_INSERT_TAIL(&prScanInfo->rPendingMsgList, &prMsgHdr->rLinkEntry); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnFsmMsgAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_SCN_SCAN_CANCEL prScanCancel; + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + CMD_SCAN_CANCEL rCmdScanCancel; + + ASSERT(prMsgHdr); + + prScanCancel = (P_MSG_SCN_SCAN_CANCEL) prMsgHdr; + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + if (prScanInfo->eCurrentState != SCAN_STATE_IDLE) { + if (prScanCancel->ucSeqNum == prScanParam->ucSeqNum && + prScanCancel->ucNetTypeIndex == (UINT_8) prScanParam->eNetTypeIndex) { + /* send cancel message to firmware domain */ + rCmdScanCancel.ucSeqNum = prScanParam->ucSeqNum; + +#if CFG_ENABLE_WIFI_DIRECT + if (prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) + rCmdScanCancel.ucIsExtChannel = (UINT_8) prScanCancel->fgIsChannelExt; + else + rCmdScanCancel.ucIsExtChannel = (UINT_8) FALSE; +#endif + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SCAN_CANCEL, + TRUE, + FALSE, + FALSE, + NULL, NULL, sizeof(CMD_SCAN_CANCEL), (PUINT_8) &rCmdScanCancel, NULL, 0); + + /* generate scan-done event for caller */ + scnFsmGenerateScanDoneMsg(prAdapter, + prScanParam->ucSeqNum, + (UINT_8) prScanParam->eNetTypeIndex, SCAN_STATUS_CANCELLED); + + /*Full2Partial at here, should stop save channel num*/ + if (prAdapter->prGlueInfo->ucTrScanType == 1) { + prAdapter->prGlueInfo->ucTrScanType = 0; + prAdapter->prGlueInfo->u4LastFullScanTime = 0; + DBGLOG(SCN, INFO, "Full2Partial scan cancel update ucTrScanType=%d\n", + prAdapter->prGlueInfo->ucTrScanType); + } + + /* switch to next pending scan */ + scnFsmSteps(prAdapter, SCAN_STATE_IDLE); + } else { + scnFsmRemovePendingMsg(prAdapter, prScanCancel->ucSeqNum, prScanCancel->ucNetTypeIndex); + } + } + + cnmMemFree(prAdapter, prMsgHdr); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Scan Message Parsing (Legacy) +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnFsmHandleScanMsg(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_SCAN_REQ prScanReqMsg) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + UINT_32 i; + + ASSERT(prAdapter); + ASSERT(prScanReqMsg); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + prScanParam->eScanType = prScanReqMsg->eScanType; + prScanParam->eNetTypeIndex = (ENUM_NETWORK_TYPE_INDEX_T) prScanReqMsg->ucNetTypeIndex; + prScanParam->ucSSIDType = prScanReqMsg->ucSSIDType; + kalMemCopy(prScanParam->aucBSSID, prScanReqMsg->aucBSSID, MAC_ADDR_LEN); + if (prScanParam->ucSSIDType & (SCAN_REQ_SSID_SPECIFIED | SCAN_REQ_SSID_P2P_WILDCARD | + SCAN_REQ_SSID_SPECIFIED_ONLY)) { + 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 + if (prScanParam->eNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { + prScanParam->u2ChannelDwellTime = prScanReqMsg->u2ChannelDwellTime; + prScanParam->u2MinChannelDwellTime = prScanReqMsg->u2MinChannelDwellTime; + } + prScanParam->ucSeqNum = prScanReqMsg->ucSeqNum; + + if (prScanReqMsg->rMsgHdr.eMsgId == MID_RLM_SCN_SCAN_REQ) + prScanParam->fgIsObssScan = TRUE; + else + prScanParam->fgIsObssScan = FALSE; + + prScanParam->fgIsScanV2 = FALSE; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Scan Message Parsing - V2 with multiple SSID support +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnFsmHandleScanMsgV2(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_SCAN_REQ_V2 prScanReqMsg) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + UINT_32 i; + + ASSERT(prAdapter); + ASSERT(prScanReqMsg); + ASSERT(prScanReqMsg->ucSSIDNum <= SCN_SSID_MAX_NUM); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + prScanParam->eScanType = prScanReqMsg->eScanType; + prScanParam->eNetTypeIndex = (ENUM_NETWORK_TYPE_INDEX_T) prScanReqMsg->ucNetTypeIndex; + prScanParam->ucSSIDType = prScanReqMsg->ucSSIDType; + prScanParam->ucSSIDNum = prScanReqMsg->ucSSIDNum; + kalMemCopy(prScanParam->aucRandomMac, prScanReqMsg->aucRandomMac, + MAC_ADDR_LEN); + + for (i = 0; i < prScanReqMsg->ucSSIDNum; i++) { + COPY_SSID(prScanParam->aucSpecifiedSSID[i], + prScanParam->ucSpecifiedSSIDLen[i], + prScanReqMsg->prSsid[i].aucSsid, (UINT_8) prScanReqMsg->prSsid[i].u4SsidLen); + } + + prScanParam->u2ProbeDelayTime = prScanReqMsg->u2ProbeDelay; + prScanParam->eScanChannel = prScanReqMsg->eScanChannel; + if (prScanParam->eScanChannel == SCAN_CHANNEL_SPECIFIED) { + if (prScanReqMsg->ucChannelListNum <= MAXIMUM_OPERATION_CHANNEL_LIST) + prScanParam->ucChannelListNum = prScanReqMsg->ucChannelListNum; + else + prScanParam->ucChannelListNum = MAXIMUM_OPERATION_CHANNEL_LIST; + + kalMemCopy(prScanParam->arChnlInfoList, + prScanReqMsg->arChnlInfoList, sizeof(RF_CHANNEL_INFO_T) * prScanParam->ucChannelListNum); + } + + if (prScanReqMsg->u2IELen <= MAX_IE_LENGTH) + prScanParam->u2IELen = prScanReqMsg->u2IELen; + else + prScanParam->u2IELen = MAX_IE_LENGTH; + + if (prScanParam->u2IELen) + kalMemCopy(prScanParam->aucIE, prScanReqMsg->aucIE, prScanParam->u2IELen); +#if CFG_ENABLE_WIFI_DIRECT + if (prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) + prScanParam->u2PassiveListenInterval = prScanReqMsg->u2ChannelDwellTime; +#endif + prScanParam->ucSeqNum = prScanReqMsg->ucSeqNum; + + if (prScanReqMsg->rMsgHdr.eMsgId == MID_RLM_SCN_SCAN_REQ) + prScanParam->fgIsObssScan = TRUE; + else + prScanParam->fgIsObssScan = FALSE; + + prScanParam->fgIsScanV2 = TRUE; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Remove pending scan request +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnFsmRemovePendingMsg(IN P_ADAPTER_T prAdapter, IN UINT_8 ucSeqNum, IN UINT_8 ucNetTypeIndex) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + P_MSG_HDR_T prPendingMsgHdr, prPendingMsgHdrNext, prRemoveMsgHdr = NULL; + P_LINK_ENTRY_T prRemoveLinkEntry = NULL; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + /* traverse through rPendingMsgList for removal */ + LINK_FOR_EACH_ENTRY_SAFE(prPendingMsgHdr, + prPendingMsgHdrNext, &(prScanInfo->rPendingMsgList), rLinkEntry, MSG_HDR_T) { + if (prPendingMsgHdr->eMsgId == MID_AIS_SCN_SCAN_REQ + || prPendingMsgHdr->eMsgId == MID_BOW_SCN_SCAN_REQ + || prPendingMsgHdr->eMsgId == MID_P2P_SCN_SCAN_REQ + || prPendingMsgHdr->eMsgId == MID_RLM_SCN_SCAN_REQ) { + P_MSG_SCN_SCAN_REQ prScanReqMsg = (P_MSG_SCN_SCAN_REQ) prPendingMsgHdr; + + if (ucSeqNum == prScanReqMsg->ucSeqNum && ucNetTypeIndex == prScanReqMsg->ucNetTypeIndex) { + prRemoveLinkEntry = &(prScanReqMsg->rMsgHdr.rLinkEntry); + prRemoveMsgHdr = prPendingMsgHdr; + } + } else if (prPendingMsgHdr->eMsgId == MID_AIS_SCN_SCAN_REQ_V2 + || prPendingMsgHdr->eMsgId == MID_BOW_SCN_SCAN_REQ_V2 + || prPendingMsgHdr->eMsgId == MID_P2P_SCN_SCAN_REQ_V2 + || prPendingMsgHdr->eMsgId == MID_RLM_SCN_SCAN_REQ_V2) { + P_MSG_SCN_SCAN_REQ_V2 prScanReqMsgV2 = (P_MSG_SCN_SCAN_REQ_V2) prPendingMsgHdr; + + if (ucSeqNum == prScanReqMsgV2->ucSeqNum && ucNetTypeIndex == prScanReqMsgV2->ucNetTypeIndex) { + prRemoveLinkEntry = &(prScanReqMsgV2->rMsgHdr.rLinkEntry); + prRemoveMsgHdr = prPendingMsgHdr; + } + } + + if (prRemoveLinkEntry) { + /* generate scan-done event for caller */ + scnFsmGenerateScanDoneMsg(prAdapter, ucSeqNum, ucNetTypeIndex, SCAN_STATUS_CANCELLED); + + /* remove from pending list */ + LINK_REMOVE_KNOWN_ENTRY(&(prScanInfo->rPendingMsgList), prRemoveLinkEntry); + cnmMemFree(prAdapter, prRemoveMsgHdr); + + break; + } + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnEventScanDone(IN P_ADAPTER_T prAdapter, IN P_EVENT_SCAN_DONE prScanDone) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + /* buffer empty channel information */ + if (prScanParam->eScanChannel == SCAN_CHANNEL_FULL || prScanParam->eScanChannel == SCAN_CHANNEL_2G4) { + if (prScanDone->ucSparseChannelValid) { + prScanInfo->fgIsSparseChannelValid = TRUE; + prScanInfo->rSparseChannel.eBand = (ENUM_BAND_T) prScanDone->rSparseChannel.ucBand; + prScanInfo->rSparseChannel.ucChannelNum = prScanDone->rSparseChannel.ucChannelNum; + } else { + prScanInfo->fgIsSparseChannelValid = FALSE; + } + } + + /*Full2Partial at here, should stop save channel num*/ + DBGLOG(SCN, TRACE, "Full2Partial scan done ucTrScanType=%d, eScanChannel=%d\n", + prAdapter->prGlueInfo->ucTrScanType, prScanParam->eScanChannel); + if ((prScanParam->eScanChannel == SCAN_CHANNEL_FULL) && + (prAdapter->prGlueInfo->ucTrScanType == 1)) { + prAdapter->prGlueInfo->ucTrScanType = 0; + DBGLOG(SCN, INFO, "Full2Partial scan done update ucTrScanType=%d\n", + prAdapter->prGlueInfo->ucTrScanType); + } + + if (prScanInfo->eCurrentState == SCAN_STATE_SCANNING && prScanDone->ucSeqNum == prScanParam->ucSeqNum) { + /* generate scan-done event for caller */ + scnFsmGenerateScanDoneMsg(prAdapter, + prScanParam->ucSeqNum, (UINT_8) prScanParam->eNetTypeIndex, SCAN_STATUS_DONE); + + /* switch to next pending scan */ + scnFsmSteps(prAdapter, SCAN_STATE_IDLE); + } else { + DBGLOG(SCN, WARN, "Unexpected SCAN-DONE event: SeqNum = %d, Current State = %d\n", + prScanDone->ucSeqNum, prScanInfo->eCurrentState); + } + +} /* end of scnEventScanDone */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +scnFsmGenerateScanDoneMsg(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucSeqNum, IN UINT_8 ucNetTypeIndex, IN ENUM_SCAN_STATUS eScanStatus) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + P_MSG_SCN_SCAN_DONE prScanDoneMsg; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + DBGLOG(SCN, INFO, + "Rcv Scan Done, NetIdx %d, Obss %d, Status %d, Seq %d ,STA MAC:[%pM] FwVer: 0x%x.%x DriVer:%s\n", + ucNetTypeIndex, prScanParam->fgIsObssScan, eScanStatus, ucSeqNum, + prAdapter->rWifiVar.aucMacAddress, + prAdapter->rVerInfo.u2FwOwnVersion, + prAdapter->rVerInfo.u2FwOwnVersionExtend, + WIFI_DRIVER_VERSION); + prScanDoneMsg = (P_MSG_SCN_SCAN_DONE) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_DONE)); + if (!prScanDoneMsg) { + ASSERT(0); /* Can't indicate SCAN FSM Complete */ + return; + } + + if (prScanParam->fgIsObssScan == TRUE) { + prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_RLM_SCAN_DONE; + } else { + switch ((ENUM_NETWORK_TYPE_INDEX_T) ucNetTypeIndex) { + case NETWORK_TYPE_AIS_INDEX: + prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_AIS_SCAN_DONE; + break; + +#if CFG_ENABLE_WIFI_DIRECT + case NETWORK_TYPE_P2P_INDEX: + prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_P2P_SCAN_DONE; + break; +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + case NETWORK_TYPE_BOW_INDEX: + prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_BOW_SCAN_DONE; + break; +#endif + + default: + ASSERT(0); + break; + } + } + + prScanDoneMsg->ucSeqNum = ucSeqNum; + prScanDoneMsg->ucNetTypeIndex = ucNetTypeIndex; + prScanDoneMsg->eScanStatus = eScanStatus; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanDoneMsg, MSG_SEND_METHOD_BUF); + +} /* end of scnFsmGenerateScanDoneMsg() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Query for most sparse channel +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnQuerySparseChannel(IN P_ADAPTER_T prAdapter, P_ENUM_BAND_T prSparseBand, PUINT_8 pucSparseChannel) +{ + P_SCAN_INFO_T prScanInfo; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + if (prScanInfo->fgIsSparseChannelValid == TRUE) { + if (prSparseBand) + *prSparseBand = prScanInfo->rSparseChannel.eBand; + + if (pucSparseChannel) + *pucSparseChannel = prScanInfo->rSparseChannel.ucChannelNum; + + return TRUE; + } else { + return FALSE; + } +} + +VOID scnFsmRunEventNloConReqTimeOut(IN P_ADAPTER_T prAdapter) +{ + P_SCAN_INFO_T prScanInfo; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanInfo->fgNloScanning = TRUE; + DBGLOG(SCN, INFO, "scnFsmNloConReqTimeOut\n"); + scnPSCNFsm(prAdapter, PSCN_RESET); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Event handler for NLO done event +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnEventNloDone(IN P_ADAPTER_T prAdapter, IN P_EVENT_NLO_DONE_T prNloDone) +{ + P_SCAN_INFO_T prScanInfo; + P_NLO_PARAM_T prNloParam; + P_SCAN_PARAM_T prScanParam; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prNloParam = &prScanInfo->rNloParam; + prScanParam = &prNloParam->rScanParam; + + if (prScanInfo->fgNloScanning == TRUE) { + DBGLOG(SCN, INFO, "scnEventNloDone Current State = %d\n", prScanInfo->eCurrentState); + + kalSchedScanResults(prAdapter->prGlueInfo); + + if (prNloParam->fgStopAfterIndication == TRUE) + prScanInfo->fgNloScanning = FALSE; + + kalMemZero(&prNloParam->aprPendingBssDescToInd[0], + CFG_SCAN_SSID_MATCH_MAX_NUM * sizeof(P_BSS_DESC_T)); + + cnmTimerStopTimer(prAdapter, &prAdapter->rScanNloTimeoutTimer); + + cnmTimerInitTimer(prAdapter, + &prAdapter->rScanNloTimeoutTimer, + (PFN_MGMT_TIMEOUT_FUNC) scnFsmRunEventNloConReqTimeOut, + (ULONG) NULL); + + cnmTimerStartTimer(prAdapter, + &prAdapter->rScanNloTimeoutTimer, + 5000); + + } else { + DBGLOG(SCN, INFO, "Unexpected NLO-DONE event\n"); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for starting scheduled scan +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +scnFsmSchedScanRequest(IN P_ADAPTER_T prAdapter) +{ + P_SCAN_INFO_T prScanInfo; + P_NLO_PARAM_T prNloParam; + P_SCAN_PARAM_T prScanParam; + P_CMD_NLO_REQ prCmdNloReq; + P_PARAM_SCHED_SCAN_REQUEST prSchedScanRequest; + UINT_32 i, j; + UINT_8 ucNetworkIndex; + BOOLEAN fgIsHiddenSSID; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prNloParam = &prScanInfo->rNloParam; + prScanParam = &prNloParam->rScanParam; + prSchedScanRequest = &prScanInfo->rSchedScanRequest; + ucNetworkIndex = 0; + fgIsHiddenSSID = FALSE; + + if (prScanInfo->fgNloScanning) { + DBGLOG(SCN, WARN, "prScanInfo->fgNloScanning == TRUE already scanning\n"); + return TRUE; + } + + /*check if normal scanning is true, driver start to postpone sched scan request*/ + prScanInfo->eCurrendSchedScanReq = SCHED_SCAN_POSTPONE_START; + + if (prScanInfo->eCurrentState != SCAN_STATE_IDLE) { + prScanInfo->fgIsPostponeSchedScan = TRUE; + DBGLOG(SCN, WARN, "already normal scanning ,driver postpones sched scan request!\n"); + return TRUE; + } + + prScanInfo->fgIsPostponeSchedScan = FALSE; + prScanInfo->fgNloScanning = TRUE; +#if CFG_NLO_MSP + scnSetMspParameterIntoPSCN(prAdapter, prScanInfo->prPscnParam); +#endif + + /* 1. load parameters */ + prScanParam->ucSeqNum++; + /* prScanParam->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; */ + + prNloParam->fgStopAfterIndication = FALSE; + prNloParam->ucFastScanIteration = 1; + + if (prSchedScanRequest->u2ScanInterval < SCAN_NLO_DEFAULT_INTERVAL) { + prSchedScanRequest->u2ScanInterval = SCAN_NLO_DEFAULT_INTERVAL; /* millisecond */ + DBGLOG(SCN, TRACE, "force interval to SCAN_NLO_DEFAULT_INTERVAL\n"); + } +#if !CFG_SUPPORT_SCN_PSCN +#if !CFG_SUPPORT_RLM_ACT_NETWORK + if (!IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX)) { + SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX); + + DBGLOG(SCN, INFO, "ACTIVATE AIS from INACTIVE to enable PNO\n"); + /* sync with firmware */ + nicActivateNetwork(prAdapter, NETWORK_TYPE_AIS_INDEX); + } +#else + rlmActivateNetwork(prAdapter, NETWORK_TYPE_AIS_INDEX, NET_ACTIVE_SRC_SCHED_SCAN); +#endif +#endif + prNloParam->u2FastScanPeriod = SCAN_NLO_MIN_INTERVAL; /* use second instead of millisecond for UINT_16*/ + prNloParam->u2SlowScanPeriod = SCAN_NLO_MAX_INTERVAL; + + if (prScanParam->ucSSIDNum > CFG_SCAN_SSID_MAX_NUM) + prScanParam->ucSSIDNum = CFG_SCAN_SSID_MAX_NUM; + else + prScanParam->ucSSIDNum = prSchedScanRequest->u4SsidNum; + + if (prNloParam->ucMatchSSIDNum > CFG_SCAN_SSID_MATCH_MAX_NUM) + prNloParam->ucMatchSSIDNum = CFG_SCAN_SSID_MATCH_MAX_NUM; + else +#if CFG_SUPPORT_SCHED_SCN_SSID_SETS + prNloParam->ucMatchSSIDNum = prSchedScanRequest->u4MatchSsidNum; +#else + prNloParam->ucMatchSSIDNum = prSchedScanRequest->u4SsidNum; +#endif + + kalMemZero(prNloParam->aucSSID, sizeof(prNloParam->aucSSID)); + kalMemZero(prNloParam->aucMatchSSID, sizeof(prNloParam->aucMatchSSID)); + +#if CFG_SUPPORT_SCHED_SCN_SSID_SETS + if (prNloParam->ucSSIDNum > CFG_SCAN_HIDDEN_SSID_MAX_NUM) + prNloParam->ucSSIDNum = CFG_SCAN_HIDDEN_SSID_MAX_NUM; + else + prNloParam->ucSSIDNum = prSchedScanRequest->u4SsidNum; + + for (i = 0; i < prNloParam->ucSSIDNum; i++) { + COPY_SSID(prNloParam->aucSSID[i], + prNloParam->ucSSIDLen[i], prSchedScanRequest->arSsid[i].aucSsid, + (UINT_8) prSchedScanRequest->arSsid[i].u4SsidLen); + } +#endif + for (i = 0; i < prNloParam->ucMatchSSIDNum; i++) { +#if CFG_SUPPORT_SCHED_SCN_SSID_SETS + + if (i < CFG_SCAN_SSID_MAX_NUM) { + COPY_SSID(prScanParam->aucSpecifiedSSID[i], + prScanParam->ucSpecifiedSSIDLen[i], prSchedScanRequest->arMatchSsid[i].aucSsid, + (UINT_8) prSchedScanRequest->arMatchSsid[i].u4SsidLen); + } + + COPY_SSID(prNloParam->aucMatchSSID[i], + prNloParam->ucMatchSSIDLen[i], prSchedScanRequest->arMatchSsid[i].aucSsid, + (UINT_8) prSchedScanRequest->arMatchSsid[i].u4SsidLen); +#else + if (i < CFG_SCAN_SSID_MAX_NUM) { + COPY_SSID(prScanParam->aucSpecifiedSSID[i], + prScanParam->ucSpecifiedSSIDLen[i], prSchedScanRequest->arSsid[i].aucSsid, + (UINT_8) prSchedScanRequest->arSsid[i].u4SsidLen); + } + + COPY_SSID(prNloParam->aucMatchSSID[i], + prNloParam->ucMatchSSIDLen[i], prSchedScanRequest->arSsid[i].aucSsid, + (UINT_8) prSchedScanRequest->arSsid[i].u4SsidLen); +#endif + prNloParam->aucCipherAlgo[i] = 0; + prNloParam->au2AuthAlgo[i] = 0; + + for (j = 0; j < SCN_NLO_NETWORK_CHANNEL_NUM; j++) + prNloParam->aucChannelHint[i][j] = 0; + } + + + /* 2. prepare command for sending */ + prCmdNloReq = (P_CMD_NLO_REQ) cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_NLO_REQ) + prScanParam->u2IELen); + + if (!prCmdNloReq) { + ASSERT(0); /* Can't initiate NLO operation */ + return FALSE; + } + + /* 3. send command packet for NLO operation */ + kalMemZero(prCmdNloReq, sizeof(CMD_NLO_REQ)); + + prCmdNloReq->ucSeqNum = prScanParam->ucSeqNum; + /* prCmdNloReq->ucBssIndex = prScanParam->ucBssIndex; */ + + prCmdNloReq->ucNetworkType = prScanParam->eNetTypeIndex; + /* prCmdNloReq->ucScanType = (UINT_8) prScanParam->eScanType; */ /* sync to firmware */ + + prCmdNloReq->fgStopAfterIndication = prNloParam->fgStopAfterIndication; + prCmdNloReq->ucFastScanIteration = prNloParam->ucFastScanIteration; + prCmdNloReq->u2FastScanPeriod = prNloParam->u2FastScanPeriod; + prCmdNloReq->u2SlowScanPeriod = prNloParam->u2SlowScanPeriod; + +#if CFG_SUPPORT_SCHED_SCN_SSID_SETS + for (i = 0 ; i < prNloParam->ucSSIDNum; i++) { + COPY_SSID(prCmdNloReq->arNetworkList[ucNetworkIndex].aucSSID, + prCmdNloReq->arNetworkList[ucNetworkIndex].ucSSIDLength, + prNloParam->aucSSID[i], prNloParam->ucSSIDLen[i]); + + DBGLOG(SCN, TRACE, "ssid set(%d) %s\n", + ucNetworkIndex, + HIDE(prCmdNloReq->arNetworkList[ucNetworkIndex].aucSSID)); + prCmdNloReq->arNetworkList[ucNetworkIndex].ucCipherAlgo + = prNloParam->aucCipherAlgo[ucNetworkIndex]; + prCmdNloReq->arNetworkList[ucNetworkIndex].u2AuthAlgo + = prNloParam->au2AuthAlgo[ucNetworkIndex]; + + for (j = 0; j < SCN_NLO_NETWORK_CHANNEL_NUM; j++) + prCmdNloReq->arNetworkList[ucNetworkIndex].ucNumChannelHint[j] + = prNloParam->aucChannelHint[ucNetworkIndex][j]; + + ucNetworkIndex++; + } + + + /*prSchedScanRequest->u4SsidNum +1 ~ prNloParam->ucMatchSSIDNum*/ + for (i = 0 ; i < prNloParam->ucMatchSSIDNum; i++) { + fgIsHiddenSSID = FALSE; + for (j = 0 ; j < prNloParam->ucSSIDNum; j++) { + if (EQUAL_SSID(prCmdNloReq->arNetworkList[j].aucSSID, + prCmdNloReq->arNetworkList[j].ucSSIDLength, + prNloParam->aucMatchSSID[i], prNloParam->ucMatchSSIDLen[i])) { + fgIsHiddenSSID = TRUE; + break; + } + } + if (ucNetworkIndex >= CFG_SCAN_SSID_MATCH_MAX_NUM) { + DBGLOG(SCN, TRACE, "ucNetworkIndex %d out of MAX num!\n", ucNetworkIndex); + break; + } + if (!fgIsHiddenSSID && prNloParam->ucMatchSSIDLen[i] != 0) { + COPY_SSID(prCmdNloReq->arNetworkList[ucNetworkIndex].aucSSID, + prCmdNloReq->arNetworkList[ucNetworkIndex].ucSSIDLength, + prNloParam->aucMatchSSID[i], prNloParam->ucMatchSSIDLen[i]); + + DBGLOG(SCN, TRACE, "Match set(%d) %s\n" + , i, prCmdNloReq->arNetworkList[ucNetworkIndex].aucSSID); + + prCmdNloReq->arNetworkList[ucNetworkIndex].ucCipherAlgo + = prNloParam->aucCipherAlgo[ucNetworkIndex]; + prCmdNloReq->arNetworkList[ucNetworkIndex].u2AuthAlgo + = prNloParam->au2AuthAlgo[ucNetworkIndex]; + + for (j = 0; j < SCN_NLO_NETWORK_CHANNEL_NUM; j++) + prCmdNloReq->arNetworkList[ucNetworkIndex].ucNumChannelHint[j] + = prNloParam->aucChannelHint[ucNetworkIndex][j]; + + ucNetworkIndex++; + } else + DBGLOG(SCN, TRACE, "ignore Match set(%d)%s,beacue it existed in NetworkList.\n" + , i, prNloParam->aucMatchSSID[i]); + + } + + /*Set uc Entry Num*/ + prCmdNloReq->ucEntryNum = ucNetworkIndex; + /*ucEntryNum[7] enable FW's support*/ + prCmdNloReq->ucReserved |= 0x80; + /*ucEntryNum[4:6]: set SSID sets */ + prCmdNloReq->ucReserved |= (prNloParam->ucSSIDNum & 0x07) << 4; + + DBGLOG(SCN, INFO, "ucEntryNum=%d,ucMatchSSIDNum=%d,ucSSIDNum=%d,ucReserved=0x%x,Iteration=%d,Period=%d\n" + , prCmdNloReq->ucEntryNum + , prNloParam->ucMatchSSIDNum + , prNloParam->ucSSIDNum + , prCmdNloReq->ucReserved + , prNloParam->ucFastScanIteration + , prNloParam->u2FastScanPeriod); +#else + + DBGLOG(SCN, INFO, "ucMatchSSIDNum %d, %s, Iteration=%d, FastScanPeriod=%d\n", + prNloParam->ucMatchSSIDNum, prNloParam->aucMatchSSID[0], + prNloParam->ucFastScanIteration, prNloParam->u2FastScanPeriod); + + prCmdNloReq->ucEntryNum = prNloParam->ucMatchSSIDNum; + for (i = 0; i < prNloParam->ucMatchSSIDNum; i++) { + COPY_SSID(prCmdNloReq->arNetworkList[i].aucSSID, + prCmdNloReq->arNetworkList[i].ucSSIDLength, + prNloParam->aucMatchSSID[i], prNloParam->ucMatchSSIDLen[i]); + + prCmdNloReq->arNetworkList[i].ucCipherAlgo = prNloParam->aucCipherAlgo[i]; + prCmdNloReq->arNetworkList[i].u2AuthAlgo = prNloParam->au2AuthAlgo[i]; + + for (j = 0; j < SCN_NLO_NETWORK_CHANNEL_NUM; j++) + prCmdNloReq->arNetworkList[i].ucNumChannelHint[j] = prNloParam->aucChannelHint[i][j]; + } +#endif + + if (prScanParam->u2IELen <= MAX_IE_LENGTH) + prCmdNloReq->u2IELen = prScanParam->u2IELen; + else + prCmdNloReq->u2IELen = MAX_IE_LENGTH; + + if (prScanParam->u2IELen) + kalMemCopy(prCmdNloReq->aucIE, prScanParam->aucIE, sizeof(UINT_8) * prCmdNloReq->u2IELen); + + prCmdNloReq->ucScnFuncMask |= prSchedScanRequest->ucScnFuncMask; + +#if !CFG_SUPPORT_SCN_PSCN + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_NLO_REQ, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_NLO_REQ) + prCmdNloReq->u2IELen, (PUINT_8) prCmdNloReq, NULL, 0); + +#else + scnCombineParamsIntoPSCN(prAdapter, prCmdNloReq, NULL, NULL, NULL, FALSE, FALSE, FALSE); + scnPSCNFsm(prAdapter, PSCN_RESET); +#endif + cnmMemFree(prAdapter, (PVOID) prCmdNloReq); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for stopping scheduled scan +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnFsmSchedScanStopRequest(IN P_ADAPTER_T prAdapter) +{ + P_SCAN_INFO_T prScanInfo; + P_NLO_PARAM_T prNloParam; + P_SCAN_PARAM_T prScanParam; + CMD_NLO_CANCEL rCmdNloCancel; + + ASSERT(prAdapter); + + /* stop Nlo timeout timer */ + cnmTimerStopTimer(prAdapter, &prAdapter->rScanNloTimeoutTimer); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prNloParam = &prScanInfo->rNloParam; + prScanParam = &prNloParam->rScanParam; + +#if !CFG_SUPPORT_SCN_PSCN +#if !CFG_SUPPORT_RLM_ACT_NETWORK + if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX)) { + UNSET_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX); + + DBGLOG(SCN, TRACE, "DEACTIVATE AIS to disable PNO\n"); + } +#else + rlmDeactivateNetwork(prAdapter, NETWORK_TYPE_AIS_INDEX, NET_ACTIVE_SRC_SCHED_SCAN); +#endif +#endif + + /*check if normal scanning is true, driver start to postpone sched scan stop request*/ + prScanInfo->eCurrendSchedScanReq = SCHED_SCAN_POSTPONE_STOP; + + if (prScanInfo->eCurrentState != SCAN_STATE_IDLE) { + prScanInfo->fgIsPostponeSchedScan = TRUE; + DBGLOG(SCN, WARN, "already normal scanning ,driver postpones sched scan stop request!\n"); + return TRUE; + } + prScanInfo->fgIsPostponeSchedScan = FALSE; + + /* send cancel message to firmware domain */ + rCmdNloCancel.ucSeqNum = prScanParam->ucSeqNum; + +#if !CFG_SUPPORT_SCN_PSCN + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_NLO_CANCEL, + TRUE, + FALSE, + FALSE, + nicCmdEventSetStopSchedScan, + nicOidCmdTimeoutCommon, sizeof(CMD_NLO_CANCEL), (PUINT_8)(&rCmdNloCancel), NULL, 0); +#else + scnCombineParamsIntoPSCN(prAdapter, NULL, NULL, NULL, NULL, TRUE, FALSE, FALSE); + if (prScanInfo->prPscnParam->fgGScnEnable + || prScanInfo->prPscnParam->fgBatchScnEnable) + scnPSCNFsm(prAdapter, PSCN_RESET); /* in case there is any PSCN */ + else + scnPSCNFsm(prAdapter, PSCN_IDLE); +#endif + + prScanInfo->fgNloScanning = FALSE; + + return TRUE; +} + +#if CFG_SUPPORT_SCN_PSCN +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for Set PSCN action +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnFsmPSCNAction(IN P_ADAPTER_T prAdapter, IN ENUM_PSCAN_ACT_T ucPscanAct) +{ + P_SCAN_INFO_T prScanInfo; + CMD_SET_PSCAN_ENABLE rCmdPscnAction; + + DBGLOG(SCN, INFO, "scnFsmPSCNAction Act = %d\n", ucPscanAct); + + kalMemZero(&rCmdPscnAction, sizeof(CMD_SET_PSCAN_ENABLE)); + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + if (ucPscanAct == PSCAN_ACT_ENABLE) { + prScanInfo->fgPscnOngoing = TRUE; + rCmdPscnAction.ucPscanAct = 0; + } else { + prScanInfo->fgPscnOngoing = FALSE; + rCmdPscnAction.ucPscanAct = 1; /* sync to firmware, 1 means disable, 0 means enable */ + } + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_PSCN_ENABLE, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_SET_PSCAN_ENABLE), (PUINT_8)&rCmdPscnAction, NULL, 0); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for Set PSCN param +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnFsmPSCNSetParam(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_PARAM prCmdPscnParam) +{ + P_SCAN_INFO_T prScanInfo; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + DBGLOG(SCN, INFO, "fgNLOScnEnable=%d %d %d, basePeriod=%d\n", + prCmdPscnParam->fgNLOScnEnable, prCmdPscnParam->fgBatchScnEnable, + prCmdPscnParam->fgGScnEnable, prCmdPscnParam->u4BasePeriod); + + if (1 /*prScanInfo->fgPscnOngoing == FALSE */) { + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_PSCAN_PARAM, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_SET_PSCAN_PARAM), (PUINT_8) prCmdPscnParam, NULL, 0); + + return TRUE; + } + return FALSE; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for Set hotlist +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnFsmPSCNSetHotlist(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_ADD_HOTLIST_BSSID prCmdPscnAddHotlist) +{ + CMD_SET_PSCAN_ADD_HOTLIST_BSSID rCmdPscnAddHotlist; + P_SCAN_INFO_T prScanInfo; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + memcpy(&rCmdPscnAddHotlist.aucMacAddr, &(prCmdPscnAddHotlist->aucMacAddr), sizeof(MAC_ADDR_LEN)); + + /* rCmdPscnAddHotlist.aucMacAddr = prCmdPscnAddHotlist->aucMacAddr; */ + rCmdPscnAddHotlist.ucFlags = prCmdPscnAddHotlist->ucFlags; + + if (prScanInfo->fgPscnOngoing && prScanInfo->prPscnParam->fgGScnEnable) { + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_PSCN_ADD_HOTLIST_BSSID, + TRUE, + FALSE, + FALSE, + NULL, + nicOidCmdTimeoutCommon, + sizeof(CMD_SET_PSCAN_ADD_HOTLIST_BSSID), (PUINT_8)&rCmdPscnAddHotlist, NULL, 0); + return TRUE; + } + /* debug msg, No PSCN, Sched SCAN no need to add the hotlist ??? */ + return FALSE; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for Set CMD_ID_SET_PSCN_ADD_SW_BSSID +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnFsmPSCNAddSWCBssId(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_ADD_SWC_BSSID prCmdPscnAddSWCBssId) +{ + CMD_SET_PSCAN_ADD_SWC_BSSID rCmdPscnAddSWCBssId; + P_SCAN_INFO_T prScanInfo; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + memcpy(&rCmdPscnAddSWCBssId.aucMacAddr, &(prCmdPscnAddSWCBssId->aucMacAddr), sizeof(MAC_ADDR_LEN)); + + /* rCmdPscnAddSWCBssId.aucMacAddr = prCmdPscnAddSWCBssId->aucMacAddr; */ + rCmdPscnAddSWCBssId.i4RssiHighThreshold = prCmdPscnAddSWCBssId->i4RssiHighThreshold; + rCmdPscnAddSWCBssId.i4RssiLowThreshold = prCmdPscnAddSWCBssId->i4RssiLowThreshold; + + if (prScanInfo->fgPscnOngoing && prScanInfo->prPscnParam->fgGScnEnable) { + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_PSCN_ADD_SW_BSSID, + TRUE, + FALSE, + FALSE, + NULL, + nicOidCmdTimeoutCommon, + sizeof(CMD_SET_PSCAN_ADD_SWC_BSSID), (PUINT_8)&rCmdPscnAddSWCBssId, NULL, 0); + return TRUE; + } + /* debug msg, No PSCN, Sched SCAN no need to add the hotlist ??? */ + return FALSE; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for Set CMD_ID_SET_PSCN_MAC_ADDR +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnFsmPSCNSetMacAddr(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_MAC_ADDR prCmdPscnSetMacAddr) +{ + CMD_SET_PSCAN_MAC_ADDR rCmdPscnSetMacAddr; + P_SCAN_INFO_T prScanInfo; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + /* rCmdPscnSetMacAddr.aucMacAddr = prCmdPscnSetMacAddr->aucMacAddr; */ + memcpy(&rCmdPscnSetMacAddr.aucMacAddr, &(prCmdPscnSetMacAddr->aucMacAddr), sizeof(MAC_ADDR_LEN)); + + rCmdPscnSetMacAddr.ucFlags = prCmdPscnSetMacAddr->ucFlags; + rCmdPscnSetMacAddr.ucVersion = prCmdPscnSetMacAddr->ucVersion; + + if (1 /* (prScanInfo->fgPscnOngoing == TRUE */) { + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_PSCN_MAC_ADDR, + TRUE, + FALSE, + FALSE, + NULL, + nicOidCmdTimeoutCommon, + sizeof(CMD_SET_PSCAN_MAC_ADDR), (PUINT_8)&rCmdPscnSetMacAddr, NULL, 0); + return TRUE; + } + /* debug msg, No PSCN, Sched SCAN no need to add the hotlist ??? */ + return FALSE; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for Combine PNO Scan params into PSCAN param +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +scnSubCombineNLOtoPSCN(IN P_ADAPTER_T prAdapter, IN P_CMD_NLO_REQ prNewCmdNloReq) +{ + P_SCAN_INFO_T prScanInfo; + P_CMD_SET_PSCAN_PARAM prCmdPscnParam; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prCmdPscnParam = (P_CMD_SET_PSCAN_PARAM) prScanInfo->prPscnParam; + + if (prNewCmdNloReq) { + prCmdPscnParam->fgNLOScnEnable = TRUE; + kalMemCopy(&(prCmdPscnParam->rCmdNloReq), prNewCmdNloReq, sizeof(CMD_NLO_REQ)); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for Combine Batch Scan params into PSCAN param +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +scnSubCombineBatchSCNtoPSCN(IN P_ADAPTER_T prAdapter, IN P_CMD_BATCH_REQ_T prNewCmdBatchReq) +{ + P_SCAN_INFO_T prScanInfo; + P_CMD_SET_PSCAN_PARAM prCmdPscnParam; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prCmdPscnParam = (P_CMD_SET_PSCAN_PARAM) prScanInfo->prPscnParam; + + if (prNewCmdBatchReq) { + prCmdPscnParam->fgBatchScnEnable = TRUE; + kalMemCopy(&(prCmdPscnParam->rCmdBatchReq), prNewCmdBatchReq, sizeof(CMD_BATCH_REQ_T)); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for Combine GSCN Scan params into PSCAN param +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +scnSubCombineGSCNtoPSCN(IN P_ADAPTER_T prAdapter, + IN P_CMD_GSCN_REQ_T prNewCmdGscnReq, IN P_CMD_GSCN_SCN_COFIG_T prNewCmdGscnConfig) +{ + P_SCAN_INFO_T prScanInfo; + P_CMD_SET_PSCAN_PARAM prCmdPscnParam; + UINT_32 ucPeriodMin = MAX_PERIOD; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prCmdPscnParam = (P_CMD_SET_PSCAN_PARAM) prScanInfo->prPscnParam; + prCmdPscnParam->fgGScnEnable = FALSE; + + DBGLOG(SCN, TRACE, "scnSubCombineGSCNtoPSCN fgGScnParamSet %d fgGScnConfigSet %d\n", + prScanInfo->fgGScnParamSet, prScanInfo->fgGScnConfigSet); + + if (prNewCmdGscnReq) { + DBGLOG(SCN, INFO, "setup prNewCmdGscnReq\n"); + prScanInfo->fgGScnParamSet = TRUE; + kalMemCopy(&(prCmdPscnParam->rCmdGscnReq), prNewCmdGscnReq, sizeof(CMD_GSCN_REQ_T)); + if (prNewCmdGscnReq->u4BasePeriod < ucPeriodMin) + prCmdPscnParam->u4BasePeriod = prNewCmdGscnReq->u4BasePeriod; + } else if (prScanInfo->fgGScnParamSet) { + DBGLOG(SCN, INFO, "no new prNewCmdGscnReq but there is an old one\n"); + } + + if (prNewCmdGscnConfig) { + DBGLOG(SCN, INFO, "setup prNewCmdGscnConfig\n"); + prScanInfo->fgGScnConfigSet = TRUE; + prCmdPscnParam->fgGScnEnable = TRUE; + prCmdPscnParam->rCmdGscnReq.u4MaxApPerScan = prNewCmdGscnConfig->ucNumApPerScn; + prCmdPscnParam->rCmdGscnReq.u4BufferThreshold = prNewCmdGscnConfig->u4BufferThreshold; + prCmdPscnParam->rCmdGscnReq.ucNumScnToCache = (UINT_8) prNewCmdGscnConfig->u4NumScnToCache; + } else if (prScanInfo->fgGScnConfigSet) { + DBGLOG(SCN, INFO, "no new prNewCmdGscnConfig but there is an old one\n"); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for Combine GSCN Scan params into PSCAN param +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +scnRemoveFromPSCN(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgRemoveNLOfromPSCN, + IN BOOLEAN fgRemoveBatchSCNfromPSCN, + IN BOOLEAN fgRemoveGSCNfromPSCN) +{ + P_SCAN_INFO_T prScanInfo; + P_CMD_SET_PSCAN_PARAM prCmdPscnParam; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prCmdPscnParam = (P_CMD_SET_PSCAN_PARAM) prScanInfo->prPscnParam; + + DBGLOG(SCN, INFO, "remove NLO or Batch or GSCN from PSCN--->NLO=%d, BSN=%d, GSN=%d\n", + fgRemoveNLOfromPSCN, fgRemoveBatchSCNfromPSCN, fgRemoveGSCNfromPSCN); + + if (fgRemoveNLOfromPSCN) { + prCmdPscnParam->fgNLOScnEnable = FALSE; + kalMemZero(&prCmdPscnParam->rCmdNloReq, sizeof(CMD_NLO_REQ)); + } + if (fgRemoveBatchSCNfromPSCN) { + prCmdPscnParam->fgBatchScnEnable = FALSE; + kalMemZero(&prCmdPscnParam->rCmdBatchReq, sizeof(CMD_BATCH_REQ_T)); + } + if (fgRemoveGSCNfromPSCN) { + prCmdPscnParam->fgGScnEnable = FALSE; + prScanInfo->fgGScnParamSet = FALSE; + prScanInfo->fgGScnConfigSet = FALSE; + prScanInfo->fgGScnAction = FALSE; + kalMemZero(&prCmdPscnParam->rCmdGscnReq, sizeof(CMD_GSCN_REQ_T)); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for Combine GSCN , Batch, PNO Scan params into PSCAN param +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +scnCombineParamsIntoPSCN(IN P_ADAPTER_T prAdapter, + IN P_CMD_NLO_REQ prNewCmdNloReq, + IN P_CMD_BATCH_REQ_T prNewCmdBatchReq, + IN P_CMD_GSCN_REQ_T prNewCmdGscnReq, + IN P_CMD_GSCN_SCN_COFIG_T prNewCmdGscnConfig, + IN BOOLEAN fgRemoveNLOfromPSCN, + IN BOOLEAN fgRemoveBatchSCNfromPSCN, IN BOOLEAN fgRemoveGSCNfromPSCN) +{ + P_SCAN_INFO_T prScanInfo; + P_CMD_SET_PSCAN_PARAM prCmdPscnParam; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prCmdPscnParam = (P_CMD_SET_PSCAN_PARAM) prScanInfo->prPscnParam; + + prCmdPscnParam->ucVersion = CURRENT_PSCN_VERSION; + + if (fgRemoveNLOfromPSCN || fgRemoveBatchSCNfromPSCN || fgRemoveGSCNfromPSCN) { + scnRemoveFromPSCN(prAdapter, + fgRemoveNLOfromPSCN, fgRemoveBatchSCNfromPSCN, fgRemoveGSCNfromPSCN); + } else { + DBGLOG(SCN, TRACE, "combine GSCN or Batch or NLO to PSCN --->\n"); + + scnSubCombineNLOtoPSCN(prAdapter, prNewCmdNloReq); + scnSubCombineBatchSCNtoPSCN(prAdapter, prNewCmdBatchReq); + scnSubCombineGSCNtoPSCN(prAdapter, prNewCmdGscnReq, prNewCmdGscnConfig); + } + + return TRUE; +} + +#if CFG_NLO_MSP + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for setting MSP parameter to PSCAN +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ + +VOID +scnSetMspParameterIntoPSCN(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_PARAM prCmdPscnParam) +{ + DBGLOG(SCN, TRACE, "--> %s()\n", __func__); + + ASSERT(prAdapter); + +#if 0 + prCmdPscnParam->rCmdNloReq.fgNLOMspEnable = 1; + prCmdPscnParam->rCmdNloReq.ucNLOMspEntryNum = 10; + prCmdPscnParam->rCmdNloReq.au2NLOMspList[0] = 120; + prCmdPscnParam->rCmdNloReq.au2NLOMspList[1] = 120; + prCmdPscnParam->rCmdNloReq.au2NLOMspList[2] = 240; + prCmdPscnParam->rCmdNloReq.au2NLOMspList[3] = 240; + prCmdPscnParam->rCmdNloReq.au2NLOMspList[4] = 480; + prCmdPscnParam->rCmdNloReq.au2NLOMspList[5] = 480; + prCmdPscnParam->rCmdNloReq.au2NLOMspList[6] = 960; + prCmdPscnParam->rCmdNloReq.au2NLOMspList[7] = 960; + prCmdPscnParam->rCmdNloReq.au2NLOMspList[8] = 960; + prCmdPscnParam->rCmdNloReq.au2NLOMspList[9] = 960; +#else + /* quick test configuration */ + prCmdPscnParam->rCmdNloReq.fgNLOMspEnable = 1; + prCmdPscnParam->rCmdNloReq.ucNLOMspEntryNum = 10; + prCmdPscnParam->rCmdNloReq.au2NLOMspList[0] = 10; + prCmdPscnParam->rCmdNloReq.au2NLOMspList[1] = 10; + prCmdPscnParam->rCmdNloReq.au2NLOMspList[2] = 10; + prCmdPscnParam->rCmdNloReq.au2NLOMspList[3] = 15; + prCmdPscnParam->rCmdNloReq.au2NLOMspList[4] = 15; + prCmdPscnParam->rCmdNloReq.au2NLOMspList[5] = 15; + prCmdPscnParam->rCmdNloReq.au2NLOMspList[6] = 20; + prCmdPscnParam->rCmdNloReq.au2NLOMspList[7] = 20; + prCmdPscnParam->rCmdNloReq.au2NLOMspList[8] = 20; + prCmdPscnParam->rCmdNloReq.au2NLOMspList[9] = 25; +#endif + +} + +#endif + + + +VOID scnPSCNFsm(IN P_ADAPTER_T prAdapter, IN ENUM_PSCAN_STATE_T eNextPSCNState) +{ + P_SCAN_INFO_T prScanInfo; + BOOLEAN fgTransitionState = FALSE; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + do { + fgTransitionState = FALSE; + + DBGLOG(SCN, STATE, "eCurrentPSCNState=%d, eNextPSCNState=%d\n", + prScanInfo->eCurrentPSCNState, eNextPSCNState); + + prScanInfo->eCurrentPSCNState = eNextPSCNState; + + switch (prScanInfo->eCurrentPSCNState) { + case PSCN_IDLE: + DBGLOG(SCN, TRACE, "PSCN_IDLE.... PSCAN_ACT_DISABLE\n"); +#if CFG_SUPPORT_RLM_ACT_NETWORK + rlmDeactivateNetwork(prAdapter, NETWORK_TYPE_AIS_INDEX, NET_ACTIVE_SRC_SCHED_SCAN); +#endif + scnFsmPSCNAction(prAdapter, PSCAN_ACT_DISABLE); + eNextPSCNState = PSCN_IDLE; + break; + + case PSCN_RESET: + DBGLOG(SCN, TRACE, "PSCN_RESET.... PSCAN_ACT_DISABLE\n"); +#if CFG_SUPPORT_RLM_ACT_NETWORK + rlmDeactivateNetwork(prAdapter, NETWORK_TYPE_AIS_INDEX, NET_ACTIVE_SRC_SCHED_SCAN); +#endif + scnFsmPSCNAction(prAdapter, PSCAN_ACT_DISABLE); + scnFsmPSCNSetParam(prAdapter, prScanInfo->prPscnParam); + + if (prScanInfo->prPscnParam->fgNLOScnEnable + || prScanInfo->prPscnParam->fgBatchScnEnable + || (prScanInfo->prPscnParam->fgGScnEnable && prScanInfo->fgGScnAction)) { + eNextPSCNState = PSCN_SCANNING; /* keep original operation if there is any PSCN */ + DBGLOG(SCN, TRACE, + "PSCN_RESET->PSCN_SCANNING....fgNLOScnEnable/fgBatchScnEnable/fgGScnEnable ENABLE\n"); + } else { + /* eNextPSCNState = PSCN_RESET; */ + DBGLOG(SCN, TRACE, + "PSCN_RESET->PSCN_RESET....fgNLOScnEnable/fgBatchScnEnable/fgGScnEnable DISABLE\n"); + } + break; + + case PSCN_SCANNING: + DBGLOG(SCN, TRACE, "PSCN_SCANNING.... PSCAN_ACT_ENABLE\n"); + if (prScanInfo->fgPscnOngoing) + break; +#if !CFG_SUPPORT_RLM_ACT_NETWORK + if (!IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX)) { + SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX); + DBGLOG(SCN, TRACE, "ACTIVATE AIS to enable PSCN\n"); + /* sync with firmware */ + nicActivateNetwork(prAdapter, NETWORK_TYPE_AIS_INDEX); + } +#else + rlmActivateNetwork(prAdapter, NETWORK_TYPE_AIS_INDEX, NET_ACTIVE_SRC_SCHED_SCAN); +#endif + + scnFsmPSCNAction(prAdapter, PSCAN_ACT_ENABLE); + prScanInfo->fgPscnOngoing = TRUE; + eNextPSCNState = PSCN_SCANNING; + break; + + default: + DBGLOG(SCN, WARN, "Unexpected state\n"); + ASSERT(0); + break; + } + + if (prScanInfo->eCurrentPSCNState != eNextPSCNState) + fgTransitionState = TRUE; + + } while (fgTransitionState); + +} +#endif + +#if CFG_SUPPORT_GSCN +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for Set GSCN param +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnSetGSCNParam(IN P_ADAPTER_T prAdapter, IN P_PARAM_WIFI_GSCAN_CMD_PARAMS prCmdGscnParam) +{ + P_CMD_GSCN_REQ_T prCmdGscnReq; + UINT_8 i = 0, j = 0; /*ucBucketIndex, ucChIndex*/ + + ASSERT(prAdapter); + prCmdGscnReq = kalMemAlloc(sizeof(CMD_GSCN_REQ_T), VIR_MEM_TYPE); + if (!prCmdGscnReq) { + DBGLOG(SCN, ERROR, "alloc prCmdGscnReq fail\n"); + return FALSE; + } + kalMemZero(prCmdGscnReq, sizeof(CMD_GSCN_REQ_T)); + prCmdGscnReq->u4NumBuckets = prCmdGscnParam->num_buckets; + prCmdGscnReq->u4BasePeriod = prCmdGscnParam->base_period; + DBGLOG(SCN, TRACE, "u4BasePeriod[%d], u4NumBuckets[%d]\n", + prCmdGscnReq->u4BasePeriod, prCmdGscnReq->u4NumBuckets); + + for (i = 0; i < prCmdGscnReq->u4NumBuckets; i++) { + prCmdGscnReq->arBucket[i].u2BucketIndex = + (UINT_16) prCmdGscnParam->buckets[i].bucket; + prCmdGscnReq->arBucket[i].eBand = prCmdGscnParam->buckets[i].band; + prCmdGscnReq->arBucket[i].ucBucketFreqMultiple = + (prCmdGscnParam->buckets[i].period / prCmdGscnParam->base_period); + prCmdGscnReq->arBucket[i].ucReportFlag = prCmdGscnParam->buckets[i].report_events; + prCmdGscnReq->arBucket[i].ucMaxBucketFreqMultiple = + (prCmdGscnParam->buckets[i].max_period / prCmdGscnParam->base_period); + prCmdGscnReq->arBucket[i].ucStepCount = (UINT_8)prCmdGscnParam->buckets[i].step_count; + + prCmdGscnReq->arBucket[i].ucNumChannels = + (UINT_8)prCmdGscnParam->buckets[i].num_channels; + DBGLOG(SCN, TRACE, "assign %d channels to bucket[%d]\n", + prCmdGscnReq->arBucket[i].ucNumChannels, i); + for (j = 0; j < prCmdGscnParam->buckets[i].num_channels; i++) { + prCmdGscnReq->arBucket[i].arChannelList[j].ucChannelNumber = + (UINT_8) nicFreq2ChannelNum(prCmdGscnParam->buckets[i].channels[j].channel * 1000); + prCmdGscnReq->arBucket[i].arChannelList[j].ucPassive = + (UINT_8) prCmdGscnParam->buckets[i].channels[j].passive; + prCmdGscnReq->arBucket[i].arChannelList[j].u4DwellTimeMs = + prCmdGscnParam->buckets[i].channels[j].dwellTimeMs; + + DBGLOG(SCN, TRACE, "[ucChannel %d, ucPassive %d, u4DwellTimeMs %d\n", + prCmdGscnReq->arBucket[i].arChannelList[j].ucChannelNumber, + prCmdGscnReq->arBucket[i].arChannelList[j].ucPassive, + prCmdGscnReq->arBucket[i].arChannelList[j].u4DwellTimeMs); + + } + + } + + scnCombineParamsIntoPSCN(prAdapter, NULL, NULL, prCmdGscnReq, NULL, FALSE, FALSE, FALSE); + scnPSCNFsm(prAdapter, PSCN_RESET); + + kalMemFree(prCmdGscnReq, VIR_MEM_TYPE, sizeof(CMD_GSCN_REQ_T)); + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for scnSetGSCNConfig +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnSetGSCNConfig(IN P_ADAPTER_T prAdapter, IN P_CMD_GSCN_SCN_COFIG_T prCmdGscnScnConfig) +{ + ASSERT(prAdapter); + ASSERT(prCmdGscnScnConfig); + + scnCombineParamsIntoPSCN(prAdapter, NULL, NULL, NULL, prCmdGscnScnConfig, FALSE, FALSE, FALSE); + scnPSCNFsm(prAdapter, PSCN_RESET); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for scnFsmGetGSCNResult +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnFsmGetGSCNResult(IN P_ADAPTER_T prAdapter, IN P_CMD_GET_GSCAN_RESULT_T prGetGscnResultCmd, + OUT PUINT_32 pu4SetInfoLen) +{ + CMD_GET_GSCAN_RESULT_T rGetGscnResultCmd; + P_SCAN_INFO_T prScanInfo; + P_PARAM_WIFI_GSCAN_RESULT_REPORT prGscnResult; + struct wiphy *wiphy; + UINT_32 u4SizeofGScanResults = 0; + UINT_8 ucBkt; + static UINT_8 scanId, numAp; + + ASSERT(prAdapter); + wiphy = priv_to_wiphy(prAdapter->prGlueInfo); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + kalMemCopy(&rGetGscnResultCmd, prGetGscnResultCmd, sizeof(CMD_GET_GSCAN_RESULT_T)); + DBGLOG(SCN, INFO, "rGetGscnResultCmd: ucGetNum[%d], fgFlush[%d]\n", + rGetGscnResultCmd.u4Num, rGetGscnResultCmd.ucFlush); + if ((rGetGscnResultCmd.u4Num == 0) || (rGetGscnResultCmd.u4Num > PSCAN_MAX_AP_CACHE_PER_SCAN)) + rGetGscnResultCmd.u4Num = PSCAN_MAX_AP_CACHE_PER_SCAN; + +#if 0 /* get GScan results from firmware */ + if (prScanInfo->fgPscnOngoing && prScanInfo->prPscnParam->fgGScnEnable) { + wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_GSCN_SCN_RESULT, + FALSE, + TRUE, + FALSE, + NULL, + nicOidCmdTimeoutCommon, + sizeof(CMD_GET_GSCAN_RESULT_T), (PUINT_8)&rGetGscnResultCmd, NULL, *pu4SetInfoLen); + return TRUE; + } +#else /* get GScan results from driver */ + scanId++; + u4SizeofGScanResults = sizeof(PARAM_WIFI_GSCAN_RESULT_REPORT) + + sizeof(PARAM_WIFI_GSCAN_RESULT) * (rGetGscnResultCmd.u4Num - 1); + prGscnResult = kalMemAlloc(u4SizeofGScanResults, VIR_MEM_TYPE); + if (!prGscnResult) { + DBGLOG(SCN, ERROR, "Can not alloc memory for PARAM_WIFI_GSCAN_RESULT_REPORT\n"); + return FALSE; + } + kalMemZero(prGscnResult, u4SizeofGScanResults); + + prGscnResult->u4ScanId = scanId; + prGscnResult->ucScanFlag = 3; + for (ucBkt = 0; ucBkt < GSCAN_MAX_BUCKETS; ucBkt++) + if (prScanInfo->prPscnParam->rCmdGscnReq.arBucket[ucBkt].ucReportFlag == REPORT_EVENTS_EACH_SCAN + || prScanInfo->prPscnParam->rCmdGscnReq.arBucket[ucBkt].ucReportFlag == REPORT_EVENTS_FULL_RESULTS) + prGscnResult->u4BucketMask |= (1 << ucBkt); + + /* copy scan results */ + { + P_PARAM_BSSID_EX_T prScanResults; + UINT_8 i = 0, remainAp = 0; + + if (numAp < prAdapter->rWlanInfo.u4ScanResultNum) + remainAp = prAdapter->rWlanInfo.u4ScanResultNum - numAp; + else { + kalMemFree(prGscnResult, VIR_MEM_TYPE, u4SizeofGScanResults); + return FALSE; + } + rGetGscnResultCmd.u4Num = + (rGetGscnResultCmd.u4Num <= remainAp) ? rGetGscnResultCmd.u4Num : remainAp; + + DBGLOG(SCN, TRACE, "u4Num=%d, numAp=%d\n", rGetGscnResultCmd.u4Num, numAp); + + for (i = 0; i < rGetGscnResultCmd.u4Num; i++) { + prScanResults = &(prAdapter->rWlanInfo.arScanResult[numAp]); + prGscnResult->rResult[i].ts = kalGetBootTime(); + if (prScanResults->rSsid.u4SsidLen <= ELEM_MAX_LEN_SSID) + kalMemCopy(prGscnResult->rResult[i].ssid, + prScanResults->rSsid.aucSsid, + prScanResults->rSsid.u4SsidLen); + kalMemCopy(prGscnResult->rResult[i].bssid, + prScanResults->arMacAddress, MAC_ADDR_LEN); + prGscnResult->rResult[i].channel = prScanResults->rConfiguration.u4DSConfig / 1000; + prGscnResult->rResult[i].rssi = prScanResults->rRssi; + prGscnResult->rResult[i].rtt = 0; + prGscnResult->rResult[i].rtt_sd = 0; + prGscnResult->rResult[i].beacon_period = prScanResults->rConfiguration.u4BeaconPeriod; + prGscnResult->rResult[i].capability = prScanResults->u2CapInfo; + prGscnResult->rResult[i].ie_length = prScanResults->u4IELength; + /* if (prScanResults->u4IELength <= CFG_RAW_BUFFER_SIZE) + * prGscnResult->rResult[i].ie_data = prAdapter->rWlanInfo.apucScanResultIEs[numAp]; + */ + + numAp++; + DBGLOG(SCN, TRACE, "Report GScan SSID[%s][%d][" MACSTR "] u4IELength=%d u2CapInfo=0x%x\n", + HIDE(prGscnResult->rResult[i].ssid), prGscnResult->rResult[i].channel, + MAC2STR(prGscnResult->rResult[i].bssid), prScanResults->u4IELength, + prScanResults->u2CapInfo); + } + if (numAp >= prAdapter->rWlanInfo.u4ScanResultNum) + numAp = 0; + } + + prGscnResult->u4NumOfResults = rGetGscnResultCmd.u4Num; + u4SizeofGScanResults += sizeof(struct nlattr) * 2; + DBGLOG(SCN, INFO, "scan_id=%d, scan_flag=0x%x, 0x%x, num=%d %d %d, u4SizeofGScanResults=%d\r\n", + prGscnResult->u4ScanId, + prGscnResult->ucScanFlag, + prGscnResult->u4BucketMask, numAp, + prGscnResult->u4NumOfResults, prAdapter->rWlanInfo.u4ScanResultNum, + u4SizeofGScanResults); + + if (numAp == rGetGscnResultCmd.u4Num) /* start transfer*/ + mtk_cfg80211_vendor_gscan_results(wiphy, prAdapter->prGlueInfo->prDevHandler->ieee80211_ptr, + prGscnResult, u4SizeofGScanResults, TRUE, FALSE); + mtk_cfg80211_vendor_gscan_results(wiphy, prAdapter->prGlueInfo->prDevHandler->ieee80211_ptr, + prGscnResult, u4SizeofGScanResults, FALSE, FALSE); + if (numAp == 0) /* end transfer */ + mtk_cfg80211_vendor_gscan_results(wiphy, prAdapter->prGlueInfo->prDevHandler->ieee80211_ptr, + prGscnResult, u4SizeofGScanResults, TRUE, TRUE); + + kalMemFree(prGscnResult, VIR_MEM_TYPE, u4SizeofGScanResults - sizeof(struct nlattr) * 2); + +#endif /* get GScan results from driver */ + + return TRUE; +} + +BOOLEAN scnFsmGSCNResults(IN P_ADAPTER_T prAdapter, IN P_EVENT_GSCAN_RESULT_T prEventBuffer) +{ + P_PARAM_WIFI_GSCAN_RESULT_REPORT prGscnResult; + struct wiphy *wiphy; + UINT_32 u4SizeofGScanResults = 0; + + prGscnResult = kalMemAlloc(sizeof(PARAM_WIFI_GSCAN_RESULT_REPORT), VIR_MEM_TYPE); + if (!prGscnResult) { + DBGLOG(SCN, ERROR, "Can not alloc memory for PARAM_WIFI_GSCAN_RESULT_REPORT\n"); + return FALSE; + } + + prGscnResult->u4ScanId = (UINT_32)prEventBuffer->u2ScanId; + prGscnResult->ucScanFlag = (UINT_8)prEventBuffer->u2ScanFlags; + prGscnResult->u4BucketMask = 1; + prGscnResult->u4NumOfResults = (UINT_32)prEventBuffer->u2NumOfResults; + + /* PARAM_WIFI_GSCAN_RESULT similar to WIFI_GSCAN_RESULT_T*/ + kalMemCopy(prGscnResult->rResult, prEventBuffer->rResult, + sizeof(PARAM_WIFI_GSCAN_RESULT) * (prGscnResult->u4NumOfResults)); + + u4SizeofGScanResults = sizeof(PARAM_WIFI_GSCAN_RESULT_REPORT) + sizeof(struct nlattr) * 2 + + sizeof(PARAM_WIFI_GSCAN_RESULT) * (prGscnResult->u4NumOfResults - 1); + DBGLOG(SCN, INFO, "scan_id=%d, scan_flag=0x%x, 0x%x, num=%d, u4SizeofGScanResults=%d\r\n", + prGscnResult->u4ScanId, + (UINT_32)prGscnResult->ucScanFlag, + prGscnResult->u4BucketMask, + prGscnResult->u4NumOfResults, + u4SizeofGScanResults); + + wiphy = priv_to_wiphy(prAdapter->prGlueInfo); + mtk_cfg80211_vendor_gscan_results(wiphy, prAdapter->prGlueInfo->prDevHandler->ieee80211_ptr, + prGscnResult, u4SizeofGScanResults, FALSE, FALSE); + + kalMemFree(prGscnResult, VIR_MEM_TYPE, sizeof(PARAM_WIFI_GSCAN_RESULT_REPORT)); + + return TRUE; +} +#endif + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/sec_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/sec_fsm.c new file mode 100644 index 0000000000000..5ac69e7b8aa5e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/sec_fsm.c @@ -0,0 +1,978 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +#if CFG_RSN_MIGRATION + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if DBG +/*lint -save -e64 Type mismatch */ +static PUINT_8 apucDebugSecState[SEC_STATE_NUM] = { + (PUINT_8) DISP_STRING("SEC_STATE_INIT"), + (PUINT_8) DISP_STRING("SEC_STATE_INITIATOR_PORT_BLOCKED"), + (PUINT_8) DISP_STRING("SEC_STATE_RESPONDER_PORT_BLOCKED"), + (PUINT_8) DISP_STRING("SEC_STATE_CHECK_OK"), + (PUINT_8) DISP_STRING("SEC_STATE_SEND_EAPOL"), + (PUINT_8) DISP_STRING("SEC_STATE_SEND_DEAUTH"), + (PUINT_8) DISP_STRING("SEC_STATE_COUNTERMEASURE"), +}; + +/*lint -restore */ +#endif /* DBG */ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do initialization of Security FSM and all variables in +* SEC_INFO_T. +* +* \param[in] prSta Pointer to the STA record +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID secFsmInit(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + P_SEC_INFO_T prSecInfo; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + ASSERT(prSta); + + prSecInfo = &prSta->rSecInfo; + +#if 1 /* MT6620 */ + /* At MT5921, is ok, but at MT6620, firmware base ASIC, the firmware */ + /* will lost these data, thus, driver have to keep the wep material and */ + /* setting to firmware while awake from D3. */ +#endif + + prSecInfo->eCurrentState = SEC_STATE_INIT; + + prSecInfo->fg2nd1xSend = FALSE; + prSecInfo->fgKeyStored = FALSE; + + if (IS_STA_IN_AIS(prSta)) { + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + prAisSpecBssInfo->u4RsnaLastMICFailTime = 0; + prAisSpecBssInfo->fgCheckEAPoLTxDone = FALSE; + + cnmTimerInitTimer(prAdapter, + &prAdapter->rWifiVar.rAisSpecificBssInfo.rRsnaEAPoLReportTimeoutTimer, + (PFN_MGMT_TIMEOUT_FUNC) secFsmEventEapolTxTimeout, (ULONG) prSta); + + cnmTimerInitTimer(prAdapter, + &prAdapter->rWifiVar.rAisSpecificBssInfo.rRsnaBlockTrafficTimer, + (PFN_MGMT_TIMEOUT_FUNC) secFsmEventEndOfCounterMeasure, (ULONG) prSta); + + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do uninitialization of Security FSM and all variables in +* SEC_INFO_T. +* +* \param[in] prSta Pointer to the STA record +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID /* whsu:Todo: */ +secFsmUnInit(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + P_SEC_INFO_T prSecInfo; + + ASSERT(prSta); + + prSecInfo = &prSta->rSecInfo; + + prSecInfo->fg2nd1xSend = FALSE; + prSecInfo->fgKeyStored = FALSE; + + /* nicPrivacyRemoveWlanTable(prSta->ucWTEntry); */ + + if (IS_STA_IN_AIS(prSta)) { + cnmTimerStopTimer(prAdapter, &prAdapter->rWifiVar.rAisSpecificBssInfo.rRsnaEAPoLReportTimeoutTimer); + cnmTimerStopTimer(prAdapter, &prAdapter->rWifiVar.rAisSpecificBssInfo.rRsnaBlockTrafficTimer); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* STANDBY to CHECK_OK. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - none +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID secFsmTrans_INIT_to_CHECK_OK(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + secSetPortBlocked(prAdapter, prSta, FALSE); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* INIT to INITIATOR_PORT_BLOCKED. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - none +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID secFsmTrans_INIT_to_INITIATOR_PORT_BLOCKED(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* INIT to RESPONDER_PORT_BLOCKED. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - none +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID secFsmTrans_INIT_to_RESPONDER_PORT_BLOCKED(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* INITIATOR_PORT_BLOCKED to CHECK_OK. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - none +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID secFsmTrans_INITIATOR_PORT_BLOCKED_to_CHECK_OK(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + secSetPortBlocked(prAdapter, prSta, FALSE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* RESPONDER_PORT_BLOCKED to CHECK_OK. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - none +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID secFsmTrans_RESPONDER_PORT_BLOCKED_to_CHECK_OK(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + secSetPortBlocked(prAdapter, prSta, FALSE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* CHECK_OK to SEND_EAPOL +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID secFsmTrans_CHECK_OK_to_SEND_EAPOL(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + + P_AIS_SPECIFIC_BSS_INFO_T prAisBssInfo; + + ASSERT(prAdapter); + + ASSERT(prSta); + + prAisBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + ASSERT(prAisBssInfo); + + if (!IS_STA_IN_AIS(prSta)) { + DBGLOG(RSN, INFO, "Counter Measure should occur at AIS network!!\n"); + /* ASSERT(0); */ + return; + } + + prAisBssInfo->fgCheckEAPoLTxDone = TRUE; + + /* cnmTimerStartTimer(prAdapter, */ + /* &prAisBssInfo->rRsnaEAPoLReportTimeoutTimer, */ + /* SEC_TO_MSEC(EAPOL_REPORT_SEND_TIMEOUT_INTERVAL_SEC)); */ + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* SEND_EAPOL to SEND_DEAUTH. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - none +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID secFsmTrans_SEND_EAPOL_to_SEND_DEAUTH(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + + if (!IS_STA_IN_AIS(prSta)) { + DBGLOG(RSN, INFO, "Counter Measure should occur at AIS network!!\n"); + /* ASSERT(0); */ + return; + } + + /* Compose deauth frame to AP, a call back function for tx done */ + if (authSendDeauthFrame(prAdapter, + prSta, + (P_SW_RFB_T) NULL, + REASON_CODE_MIC_FAILURE, + (PFN_TX_DONE_HANDLER) secFsmEventDeauthTxDone) != WLAN_STATUS_SUCCESS) { + ASSERT(FALSE); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* SEND_DEAUTH to COUNTERMEASURE. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID secFsmTrans_SEND_DEAUTH_to_COUNTERMEASURE(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + ASSERT(prAdapter); + ASSERT(prSta); + + if (!IS_STA_IN_AIS(prSta)) { + DBGLOG(RSN, INFO, "Counter Measure should occur at AIS network!!\n"); + /* ASSERT(0); */ + return; + } + /* Start the 60 sec timer */ + cnmTimerStartTimer(prAdapter, + &prAdapter->rWifiVar.rAisSpecificBssInfo.rRsnaBlockTrafficTimer, + SEC_TO_MSEC(COUNTER_MEASURE_TIMEOUT_INTERVAL_SEC)); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* SEND_DEAUTH to COUNTERMEASURE. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID secFsmTrans_COUNTERMEASURE_to_INIT(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + + /* Clear the counter measure flag */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The Core FSM engine of security module. +* +* \param[in] prSta Pointer to the Sta record +* \param[in] eNextState Enum value of next sec STATE +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +VOID secFsmSteps(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta, IN ENUM_SEC_STATE_T eNextState) +{ + P_SEC_INFO_T prSecInfo; + BOOLEAN fgIsTransition = (BOOLEAN) FALSE; + + ASSERT(prSta); + + prSecInfo = &prSta->rSecInfo; + ASSERT(prSecInfo); + + DEBUGFUNC("secFsmSteps"); + do { + /* Do entering Next State */ + prSecInfo->ePreviousState = prSecInfo->eCurrentState; + + /* Do entering Next State */ +#if DBG + DBGLOG(RSN, STATE, "%pM TRANSITION: [%s] -> [%s]\n", + prSta->aucMacAddr, + apucDebugSecState[prSecInfo->eCurrentState], apucDebugSecState[eNextState]); +#else + DBGLOG(RSN, STATE, "%pM [%d] TRANSITION: [%d] -> [%d]\n", + prSta->aucMacAddr, DBG_RSN_IDX, prSecInfo->eCurrentState, eNextState); +#endif + prSecInfo->eCurrentState = eNextState; + + fgIsTransition = (BOOLEAN) FALSE; +#if 0 + /* Do tasks of the State that we just entered */ + switch (prSecInfo->eCurrentState) { + case SEC_STATE_INIT: + break; + case SEC_STATE_INITIATOR_PORT_BLOCKED: + break; + case SEC_STATE_RESPONDER_PORT_BLOCKED: + break; + case SEC_STATE_CHECK_OK: + break; + case SEC_STATE_SEND_EAPOL: + break; + case SEC_STATE_SEND_DEAUTH: + break; + case SEC_STATE_COUNTERMEASURE: + break; + default: + ASSERT(0); /* Make sure we have handle all STATEs */ + break; + } +#endif + } while (fgIsTransition); + + return; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do initialization of Security FSM and all variables in +* SEC_INFO_T. +* +* \param[in] prSta Pointer to the Sta record +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID secFsmEventStart(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + P_SEC_INFO_T prSecInfo; + BOOLEAN fgIsTransition = (BOOLEAN) FALSE; + ENUM_SEC_STATE_T eNextState; + + DBGLOG(RSN, TRACE, "secFsmRunEventStart\n"); + + ASSERT(prSta); + + if (!prSta) + return; + + if (!IS_STA_IN_AIS(prSta)) + return; + + DBGLOG(RSN, TRACE, "secFsmRunEventStart for sta %pM network %d\n", + prSta->aucMacAddr, prSta->ucNetTypeIndex); + + prSecInfo = (P_SEC_INFO_T) &prSta->rSecInfo; + + eNextState = prSecInfo->eCurrentState; + + secSetPortBlocked(prAdapter, prSta, TRUE); + + /* prSta->fgTransmitKeyExist = FALSE; */ + /* whsu:: nicPrivacySetStaDefaultWTIdx(prSta); */ + +#if 1 /* Since the 1x and key can set to firmware in order, always enter the check ok state */ + SEC_STATE_TRANSITION(prAdapter, prSta, INIT, CHECK_OK); +#else + if (IS_STA_IN_AIS(prSta->eStaType)) { + if (secRsnKeyHandshakeEnabled(prAdapter) == TRUE +#if CFG_SUPPORT_WAPI + || (prAdapter->rWifiVar.rConnSettings.fgWapiMode) +#endif + ) { + prSta->fgTransmitKeyExist = FALSE; + /* nicPrivacyInitialize(prSta->ucNetTypeIndex); */ + SEC_STATE_TRANSITION(prAdapter, prSta, INIT, INITIATOR_PORT_BLOCKED); + } else { + SEC_STATE_TRANSITION(prAdapter, prSta, INIT, CHECK_OK); + } + } +#if CFG_ENABLE_WIFI_DIRECT || CFG_ENABLE_BT_OVER_WIFI +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_BT_OVER_WIFI + else if ((prSta->eStaType == STA_TYPE_BOW_CLIENT) || (prSta->eStaType == STA_TYPE_P2P_GC)) { +#elif CFG_ENABLE_WIFI_DIRECT + else if (prSta->eStaType == STA_TYPE_P2P_GC) { +#elif CFG_ENABLE_BT_OVER_WIFI + else if (prSta->eStaType == STA_TYPE_BOW_CLIENT) { +#endif + SEC_STATE_TRANSITION(prAdapter, prSta, INIT, RESPONDER_PORT_BLOCKED); + } +#endif + else + SEC_STATE_TRANSITION(prAdapter, prSta, INIT, INITIATOR_PORT_BLOCKED); +#endif + if (prSecInfo->eCurrentState != eNextState) + secFsmSteps(prAdapter, prSta, eNextState); + +} /* secFsmRunEventStart */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function called by reset procedure to force the sec fsm enter +* idle state +* +* \param[in] ucNetTypeIdx The Specific Network type index +* \param[in] prSta Pointer to the Sta record +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID secFsmEventAbort(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + P_SEC_INFO_T prSecInfo; + + DBGLOG(RSN, TRACE, "secFsmEventAbort for sta %pM network %d\n", + prSta->aucMacAddr, prSta->ucNetTypeIndex); + + ASSERT(prSta); + + if (!prSta) + return; + + if (!IS_STA_IN_AIS(prSta)) + return; + + prSecInfo = (P_SEC_INFO_T) &prSta->rSecInfo; + + prSta->fgTransmitKeyExist = FALSE; + + secSetPortBlocked(prAdapter, prSta, TRUE); + + if (prSecInfo == NULL) + return; + + if (IS_STA_IN_AIS(prSta)) { + + prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist = FALSE; + + if (prSecInfo->eCurrentState == SEC_STATE_SEND_EAPOL) { + if (prAdapter->rWifiVar.rAisSpecificBssInfo.fgCheckEAPoLTxDone == FALSE) { + DBGLOG(RSN, TRACE, "EAPOL STATE not match the flag\n"); + /* + * cnmTimerStopTimer(prAdapter, &prAdapter->rWifiVar. + * rAisSpecificBssInfo.rRsnaEAPoLReportTimeoutTimer); + */ + } + } + } + prSecInfo->eCurrentState = SEC_STATE_INIT; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will indicate an Event of "2nd EAPoL Tx is sending" to Sec FSM. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +VOID secFsmEvent2ndEapolTx(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + P_SEC_INFO_T prSecInfo; + ENUM_SEC_STATE_T eNextState; + /* BOOLEAN fgIsTransition = (BOOLEAN)FALSE; */ + + DEBUGFUNC("secFsmRunEvent2ndEapolTx"); + + ASSERT(prSta); + + prSecInfo = &prSta->rSecInfo; + eNextState = prSecInfo->eCurrentState; + +#if DBG + DBGLOG(RSN, TRACE, "%pM Sec state %s\n", prSta->aucMacAddr, + apucDebugSecState[prSecInfo->eCurrentState]); +#else + DBGLOG(RSN, TRACE, "%pM Sec state [%d]\n", prSta->aucMacAddr, prSecInfo->eCurrentState); +#endif + + switch (prSecInfo->eCurrentState) { + case SEC_STATE_INITIATOR_PORT_BLOCKED: + case SEC_STATE_CHECK_OK: + prSecInfo->fg2nd1xSend = TRUE; + break; + default: +#if DBG + DBGLOG(RSN, WARN, "Rcv 2nd EAPoL at %s\n", apucDebugSecState[prSecInfo->eCurrentState]); +#else + DBGLOG(RSN, WARN, "Rcv 2nd EAPoL at [%d]\n", prSecInfo->eCurrentState); +#endif + break; + } + + if (prSecInfo->eCurrentState != eNextState) + secFsmSteps(prAdapter, prSta, eNextState); + + return; + +} /* secFsmRunEvent2ndEapolTx */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will indicate an Event of "4th EAPoL Tx is Tx done" to Sec FSM. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +VOID secFsmEvent4ndEapolTxDone(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + P_SEC_INFO_T prSecInfo; + ENUM_SEC_STATE_T eNextState; + BOOLEAN fgIsTransition = (BOOLEAN) FALSE; + P_CMD_802_11_KEY prStoredKey; + + DEBUGFUNC("secFsmRunEvent4ndEapolTx"); + + ASSERT(prSta); + + prSecInfo = &prSta->rSecInfo; + eNextState = prSecInfo->eCurrentState; + +#if DBG + DBGLOG(RSN, TRACE, "%pM Sec state %s\n", prSta->aucMacAddr, + apucDebugSecState[prSecInfo->eCurrentState]); +#else + DBGLOG(RSN, TRACE, "%pM Sec state [%d]\n", prSta->aucMacAddr, prSecInfo->eCurrentState); +#endif + + switch (prSecInfo->eCurrentState) { + case SEC_STATE_INITIATOR_PORT_BLOCKED: + case SEC_STATE_CHECK_OK: + prSecInfo->fg2nd1xSend = FALSE; + if (prSecInfo->fgKeyStored) { + prStoredKey = (P_CMD_802_11_KEY) prSecInfo->aucStoredKey; + + /* prSta = rxmLookupStaRecIndexFromTA(prStoredKey->aucPeerAddr); */ + /* if (nicPrivacySetKeyEntry(prStoredKey, prSta->ucWTEntry) == FALSE) */ + /* DBGLOG(RSN, WARN, ("nicPrivacySetKeyEntry() fail,..\n")); */ + + /* key update */ + prSecInfo->fgKeyStored = FALSE; + prSta->fgTransmitKeyExist = TRUE; + } + if (prSecInfo->eCurrentState == SEC_STATE_INITIATOR_PORT_BLOCKED) + SEC_STATE_TRANSITION(prAdapter, prSta, INITIATOR_PORT_BLOCKED, CHECK_OK); + break; + default: + +#if DBG + DBGLOG(RSN, WARN, "Rcv thh EAPoL Tx done at %s\n", apucDebugSecState[prSecInfo->eCurrentState]); +#else + DBGLOG(RSN, WARN, "Rcv thh EAPoL Tx done at [%d]\n", prSecInfo->eCurrentState); +#endif + break; + } + + if (prSecInfo->eCurrentState != eNextState) + secFsmSteps(prAdapter, prSta, eNextState); + + return; + +} /* secFsmRunEvent4ndEapolTx */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will indicate an Event of "Pairwise key installed" to SEC FSM. +* +* \param[in] prSta Pointer to the Sta record +* +* \retval TRUE The key can be installed to HW +* \retval FALSE The kay conflict with the current key, abort it +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN secFsmEventPTKInstalled(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + P_SEC_INFO_T prSecInfo; + ENUM_SEC_STATE_T eNextState; + BOOLEAN fgStatus = TRUE; + BOOLEAN fgIsTransition = (BOOLEAN) FALSE; + + ASSERT(prSta); + + prSecInfo = &prSta->rSecInfo; + if (prSecInfo == NULL) + return TRUE; /* Not PTK */ + +#if DBG + DBGLOG(RSN, TRACE, "%pM Sec state %s\n", prSta->aucMacAdd), + apucDebugSecState[prSecInfo->eCurrentState]); +#else + DBGLOG(RSN, TRACE, "%pM Sec state [%d]\n", prSta->aucMacAddr, prSecInfo->eCurrentState); +#endif + + eNextState = prSecInfo->eCurrentState; + + switch (prSecInfo->eCurrentState) { + case SEC_STATE_INIT: + /* Legacy wep, wpa-none */ + break; + + case SEC_STATE_INITIATOR_PORT_BLOCKED: + if (prSecInfo->fg2nd1xSend) + ; + else + SEC_STATE_TRANSITION(prAdapter, prSta, INITIATOR_PORT_BLOCKED, CHECK_OK); + break; + + case SEC_STATE_RESPONDER_PORT_BLOCKED: + SEC_STATE_TRANSITION(prAdapter, prSta, RESPONDER_PORT_BLOCKED, CHECK_OK); + break; + + case SEC_STATE_CHECK_OK: + break; + + default: + fgStatus = FALSE; + break; + } + + if (prSecInfo->eCurrentState != eNextState) + secFsmSteps(prAdapter, prSta, eNextState); + + return fgStatus; + +} /* end of secFsmRunEventPTKInstalled() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will indicate an Event of "Counter Measure" to SEC FSM. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +VOID secFsmEventStartCounterMeasure(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + P_SEC_INFO_T prSecInfo; + ENUM_SEC_STATE_T eNextState; + BOOLEAN fgIsTransition = (BOOLEAN) FALSE; + + DEBUGFUNC("secFsmRunEventStartCounterMeasure"); + + ASSERT(prSta); + + if (!IS_STA_IN_AIS(prSta)) { + DBGLOG(RSN, INFO, "Counter Measure should occur at AIS network!!\n"); + /* ASSERT(0); */ + return; + } + + prSecInfo = &prSta->rSecInfo; + + eNextState = prSecInfo->eCurrentState; + +#if DBG + DBGLOG(RSN, TRACE, "%pM Sec state %s\n", prSta->aucMacAddr, + apucDebugSecState[prSecInfo->eCurrentState]); +#else + DBGLOG(RSN, TRACE, "%pM Sec state [%d]\n", prSta->aucMacAddr, prSecInfo->eCurrentState); +#endif + + prAdapter->rWifiVar.rAisSpecificBssInfo.u4RsnaLastMICFailTime = 0; + + switch (prSecInfo->eCurrentState) { + case SEC_STATE_CHECK_OK: + { + prAdapter->rWifiVar.rAisSpecificBssInfo.fgCounterMeasure = TRUE; + + /* dls port control */ + SEC_STATE_TRANSITION(prAdapter, prSta, CHECK_OK, SEND_EAPOL); + } + break; + + default: + break; + } + + /* Call arbFsmSteps() when we are going to change ARB STATE */ + if (prSecInfo->eCurrentState != eNextState) + secFsmSteps(prAdapter, prSta, eNextState); + + return; + +} /* secFsmRunEventStartCounterMeasure */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will indicate an Event of "802.1x EAPoL Tx Done" to Sec FSM. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +VOID +secFsmEventEapolTxDone(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + P_SEC_INFO_T prSecInfo; + ENUM_SEC_STATE_T eNextState; + BOOLEAN fgIsTransition = (BOOLEAN) FALSE; + P_AIS_SPECIFIC_BSS_INFO_T prAisBssInfo; + + DEBUGFUNC("secFsmRunEventEapolTxDone"); + + ASSERT(prStaRec); + + if (rTxDoneStatus != TX_RESULT_SUCCESS) { + DBGLOG(RSN, INFO, "Error EAPoL fram fail to send!!\n"); + /* ASSERT(0); */ + return; + } + + if (!IS_STA_IN_AIS(prStaRec)) { + DBGLOG(RSN, INFO, "Counter Measure should occur at AIS network!!\n"); + /* ASSERT(0); */ + return; + } + + prAisBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + ASSERT(prAisBssInfo); + + prSecInfo = &prStaRec->rSecInfo; + eNextState = prSecInfo->eCurrentState; + +#if DBG + DBGLOG(RSN, TRACE, "%pM Sec state %s\n", prStaRec->aucMacAddr, + apucDebugSecState[prSecInfo->eCurrentState]); +#else + DBGLOG(RSN, TRACE, "%pM Sec state [%d]\n", prStaRec->aucMacAddr, prSecInfo->eCurrentState); +#endif + + switch (prSecInfo->eCurrentState) { + case SEC_STATE_SEND_EAPOL: + if (prAisBssInfo->fgCheckEAPoLTxDone == FALSE) + ASSERT(0); + + prAisBssInfo->fgCheckEAPoLTxDone = FALSE; + /* cnmTimerStopTimer(prAdapter, &prAisBssInfo->rRsnaEAPoLReportTimeoutTimer); */ + + SEC_STATE_TRANSITION(prAdapter, prStaRec, SEND_EAPOL, SEND_DEAUTH); + break; + default: + break; + } + + if (prSecInfo->eCurrentState != eNextState) + secFsmSteps(prAdapter, prStaRec, eNextState); + + return; + +} /* secFsmRunEventEapolTxDone */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will indicate an Event of "Deauth frame Tx Done" to Sec FSM. +* +* \param[in] pMsduInfo Pointer to the Msdu Info +* \param[in] rStatus The Tx done status +* +* \return - +* +* \note after receive deauth frame, callback function call this +*/ +/*----------------------------------------------------------------------------*/ +VOID +secFsmEventDeauthTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + P_STA_RECORD_T prStaRec; + P_SEC_INFO_T prSecInfo; + ENUM_SEC_STATE_T eNextState; + BOOLEAN fgIsTransition = (BOOLEAN) FALSE; + + DEBUGFUNC("secFsmRunEventDeauthTxDone"); + + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + ASSERT(prStaRec); + + if (!prStaRec) + return; + + if (!IS_STA_IN_AIS(prStaRec)) { + DBGLOG(RSN, INFO, "Counter Measure should occur at AIS network!!\n"); + /* ASSERT(0); */ + return; + } + + prSecInfo = (P_SEC_INFO_T) &prStaRec->rSecInfo; + +#if DBG + DBGLOG(RSN, TRACE, "%pM Sec state %s\n", prStaRec->aucMacAddr, + apucDebugSecState[prSecInfo->eCurrentState]); +#else + DBGLOG(RSN, TRACE, "%pM Sec state [%d]\n", prStaRec->aucMacAddr, prSecInfo->eCurrentState); +#endif + + switch (prSecInfo->eCurrentState) { + case SEC_STATE_SEND_DEAUTH: + + DBGLOG(RSN, TRACE, "Set timer %d\n", COUNTER_MEASURE_TIMEOUT_INTERVAL_SEC); + + SEC_STATE_TRANSITION(prAdapter, prStaRec, SEND_DEAUTH, COUNTERMEASURE); + + break; + + default: + ASSERT(0); + break; + } + +} /* secFsmRunEventDeauthTxDone */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will check the eapol error frame fail to send issue. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +VOID secFsmEventEapolTxTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParm) +{ + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("secFsmRunEventEapolTxTimeout"); + + prStaRec = (P_STA_RECORD_T) ulParm; + + ASSERT(prStaRec); + + /* Todo:: How to handle the Eapol Error fail to send case? */ + ASSERT(0); + + return; + +} /* secFsmEventEapolTxTimeout */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will stop the counterMeasure duration. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +VOID secFsmEventEndOfCounterMeasure(IN P_ADAPTER_T prAdapter, ULONG ulParm) +{ + P_STA_RECORD_T prSta; + P_SEC_INFO_T prSecInfo; + ENUM_SEC_STATE_T eNextState; + BOOLEAN fgIsTransition = (BOOLEAN) FALSE; + + DEBUGFUNC("secFsmRunEventEndOfCounterMeasure"); + + prSta = (P_STA_RECORD_T) ulParm; + + ASSERT(prSta); + + if (!IS_STA_IN_AIS(prSta)) { + DBGLOG(RSN, INFO, "Counter Measure should occur at AIS network!!\n"); + /* ASSERT(0); */ + return; + } + + prSecInfo = &prSta->rSecInfo; + eNextState = prSecInfo->eCurrentState; + +#if DBG + DBGLOG(RSN, TRACE, "%pM Sec state %s\n", prSta->aucMacAddr, + apucDebugSecState[prSecInfo->eCurrentState]); +#else + DBGLOG(RSN, TRACE, "%pM Sec state [%d]\n", prSta->aucMacAddr, prSecInfo->eCurrentState); +#endif + + switch (prSecInfo->eCurrentState) { + case SEC_STATE_SEND_DEAUTH: + { + prAdapter->rWifiVar.rAisSpecificBssInfo.fgCounterMeasure = FALSE; + + SEC_STATE_TRANSITION(prAdapter, prSta, COUNTERMEASURE, INIT); + } + break; + + default: + ASSERT(0); + } + + /* Call arbFsmSteps() when we are going to change ARB STATE */ + if (prSecInfo->eCurrentState != eNextState) + secFsmSteps(prAdapter, prSta, eNextState); + +} /* end of secFsmRunEventEndOfCounterMeasure */ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/stats.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/stats.c new file mode 100644 index 0000000000000..2e2326616a374 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/stats.c @@ -0,0 +1,1451 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ +#include "precomp.h" + +enum EVENT_TYPE { + EVENT_RX, + EVENT_TX, + EVENT_TX_DONE +}; +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static void statsInfoEnvDisplay(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen); + +static WLAN_STATUS +statsInfoEnvRequest(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +UINT_64 u8DrvOwnStart, u8DrvOwnEnd; +UINT32 u4DrvOwnMax; +#define CFG_USER_LOAD 0 +#define ARP_TX_DONE_REQ_INTERVAL 500 +static UINT_16 su2TxDoneCfg = CFG_DHCP | CFG_ICMP | CFG_EAPOL | CFG_ARP; +static OS_SYSTIME srLastArpTxDoneReqTime; +/******************************************************************************* +* P R I V A T E F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to display all environment log. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +*/ +/*----------------------------------------------------------------------------*/ +static void statsInfoEnvDisplay(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen) +{ + P_ADAPTER_T prAdapter; + STA_RECORD_T *prStaRec; + UINT32 u4NumOfInfo, u4InfoId; + UINT32 u4RxErrBitmap; + STATS_INFO_ENV_T *prInfo; + UINT32 u4Total, u4RateId; +#if CFG_ENABLE_PER_STA_STATISTICS_LOG + UINT_32 u4LinkScore; +/* + * rQueryStaStatistics.u4TxFailCount + rQueryStaStatistics.u4TxLifeTimeoutCount; + */ + UINT_32 u4TotalError; + UINT_32 u4TxExceedThresholdCount; + UINT_32 u4TxTotalCount; +#endif +/* + * [wlan] statsInfoEnvRequest: (INIT INFO) statsInfoEnvRequest cmd ok. + * [wlan] statsEventHandle: (INIT INFO) statsEventHandle: Rcv a event + * [wlan] statsEventHandle: (INIT INFO) statsEventHandle: Rcv a event: 0 + * [wlan] statsInfoEnvDisplay: (INIT INFO) Display stats for [00:0c:43:31:35:97]: + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) TPAM(0x0) RTS(0 0) BA(0x1 0) OK(9 9 xxx) ERR(0 0 0 0 0 0 0) + * TPAM (bit0: enable 40M, bit1: enable 20 short GI, bit2: enable 40 short GI, + * bit3: use 40M TX, bit4: use short GI TX, bit5: use no ack) + * RTS (1st: current use RTS/CTS, 2nd: ever use RTS/CTS) + * BA (1st: TX session BA bitmap for TID0 ~ TID7, 2nd: peer receive maximum agg number) + * OK (1st: total number of tx packet from host, 2nd: total number of tx ok, system time last TX OK) + * ERR (1st: total number of tx err, 2nd ~ 7st: total number of + * WLAN_STATUS_BUFFER_RETAINED, WLAN_STATUS_PACKET_FLUSHED, WLAN_STATUS_PACKET_AGING_TIMEOUT, + * WLAN_STATUS_PACKET_MPDU_ERROR, WLAN_STATUS_PACKET_RTS_ERROR, WLAN_STATUS_PACKET_LIFETIME_ERROR) + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) TRATE (6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (0 0 0 0 0 0 0 3) + * TX rate count (1M 2 5.5 11 NA NA NA NA 48 24 12 6 54 36 18 9) (MCS0 ~ MCS7) + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) RX(148 1 0) BA(0x1 64) OK(2 2) ERR(0) + * RX (1st: latest RCPI, 2nd: chan num) + * BA (1st: RX session BA bitmap for TID0 ~ TID7, 2nd: our receive maximum agg number) + * OK (number of rx packets without error, number of rx packets to OS) + * ERR (number of rx packets with error) + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) RCCK (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + * CCK MODE (1 2 5.5 11M) + * [wlan] statsInfoEnvDisplay: (INIT INFO) ROFDM (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + * OFDM MODE (NA NA NA NA 6 9 12 18 24 36 48 54M) + * [wlan] statsInfoEnvDisplay: (INIT INFO) RHT (0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0) + * MIXED MODE (number of rx packets with MCS0 ~ MCS15) + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) StayIntH2M us (29 29 32) (0 0 0) (0 0 0) + * delay from HIF to MAC own bit=1 (min, avg, max for 500B) (min, avg, max for 1000B) (min, avg, max for others) + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) AirTime us (608 864 4480) (0 0 0) (0 0 0) + * delay from MAC start TX to MAC TX done + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) StayInt us (795 1052 4644_4504) (0 0 0_0) (0 0 0_0) + * delay from HIF to MAC TX done (min, avg, max_system time for 500B) + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) StayIntD2T us (795 1052 4644) (0 0 0) (0 0 0) + * delay from driver to MAC TX done (min, avg, max for 500B) + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) StayIntR_M2H us (37 40 58) (0 0 0) (0 0 0) + * delay from MAC to HIF (min, avg, max for 500B) + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) StayIntR_H2D us (0 0 0) (0 0 0) (0 0 0) + * delay from HIF to Driver OS (min, avg, max for 500B) + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) StayCntD2H unit:10ms (10 0 0 0) + * delay count from Driver to HIF (count in 0~10ms, 10~20ms, 20~30ms, others) + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) StayCnt unit:1ms (6 3 0 1) + * delay count from HIF to TX DONE (count in 0~1ms, 1~5ms, 5~10ms, others) + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) + * StayCnt (0~1161:7) (1161~2322:2) (2322~3483:0) (3483~4644:0) (4644~:1) + * delay count from HIF to TX DONE (count in 0~1161 ticks, 1161~2322, 2322~3483, 3483~4644, others) + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) OTHER (61877) (0) (38) (0) (0) (0ms) + * Channel idle time, scan count, channel change count, empty tx quota count, + * power save change count from active to PS, maximum delay from PS to active + */ + + /* init */ + prAdapter = prGlueInfo->prAdapter; + /* show pkt status */ + wlanPktStatusDebugDumpInfo(prAdapter); + /*prInfo = &rStatsInfoEnv;*/ + prInfo = kalMemAlloc(sizeof(STATS_INFO_ENV_T), VIR_MEM_TYPE); + if (prInfo == NULL) { + DBGLOG(RX, INFO, "prInfo alloc fail"); + return; + } + + kalMemZero(prInfo, sizeof(STATS_INFO_ENV_T)); + + if (u4InBufLen > sizeof(STATS_INFO_ENV_T)) + u4InBufLen = sizeof(STATS_INFO_ENV_T); + + /* parse */ + u4NumOfInfo = *(UINT32 *) prInBuf; + u4RxErrBitmap = *(UINT32 *) (prInBuf + 4); + + /* print */ + for (u4InfoId = 0; u4InfoId < u4NumOfInfo; u4InfoId++) { + /* + * use u4InBufLen, not sizeof(rStatsInfoEnv) + * because the firmware version maybe not equal to driver version + */ + kalMemCopy(prInfo, prInBuf + 8, u4InBufLen); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prInfo->ucStaRecIdx); + if (prStaRec == NULL) + continue; + + DBGLOG(RX, INFO, " Display stats for [%pM]: %uB\n", + prStaRec->aucMacAddr, (UINT32) sizeof(STATS_INFO_ENV_T)); + + if (prStaRec->ucStatsGenDisplayCnt++ > 10) { + /* display general statistics information every 10 * (5 or 10s) */ + DBGLOG(RX, INFO, " TBA(0x%x %u) RBA(0x%x %u)\n", + prInfo->ucTxAggBitmap, prInfo->ucTxPeerAggMaxSize, + prInfo->ucRxAggBitmap, prInfo->ucRxAggMaxSize); + prStaRec->ucStatsGenDisplayCnt = 0; + } + + if (prInfo->u4TxDataCntErr == 0) { + DBGLOG(RX, INFO, " TOS(%u) OK(%u %u) PendingPKT(%u) SE(%u) Num(%u %u %u %u)\n" + "TC resource(%d %d %d %d %d)\n", + (UINT32) prGlueInfo->rNetDevStats.tx_packets, + prInfo->u4TxDataCntAll, prInfo->u4TxDataCntOK, + prGlueInfo->i4TxPendingFrameNum, + prGlueInfo->i4TxPendingSecurityFrameNum, + prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][0], + prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][1], + prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][2], + prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][3], + prAdapter->rTxCtrl.rTc.aucFreeBufferCount[TC0_INDEX], + prAdapter->rTxCtrl.rTc.aucFreeBufferCount[TC1_INDEX], + prAdapter->rTxCtrl.rTc.aucFreeBufferCount[TC2_INDEX], + prAdapter->rTxCtrl.rTc.aucFreeBufferCount[TC3_INDEX], + prAdapter->rTxCtrl.rTc.aucFreeBufferCount[TC4_INDEX]); + } else { + DBGLOG(RX, INFO, " TOS(%u) OK(%u %u) ERR(%u) PendingPKT(%u) SE(%u) Num(%u %u %u %u)\n" + "TC resource(%d %d %d %d %d)\n", + (UINT32) prGlueInfo->rNetDevStats.tx_packets, + prInfo->u4TxDataCntAll, prInfo->u4TxDataCntOK, prInfo->u4TxDataCntErr, + prGlueInfo->i4TxPendingFrameNum, + prGlueInfo->i4TxPendingSecurityFrameNum, + prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][0], + prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][1], + prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][2], + prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][3], + prAdapter->rTxCtrl.rTc.aucFreeBufferCount[TC0_INDEX], + prAdapter->rTxCtrl.rTc.aucFreeBufferCount[TC1_INDEX], + prAdapter->rTxCtrl.rTc.aucFreeBufferCount[TC2_INDEX], + prAdapter->rTxCtrl.rTc.aucFreeBufferCount[TC3_INDEX], + prAdapter->rTxCtrl.rTc.aucFreeBufferCount[TC4_INDEX]); + DBGLOG(RX, INFO, " ERR type(%u %u %u %u %u %u)\n", + prInfo->u4TxDataCntErrType[0], prInfo->u4TxDataCntErrType[1], + prInfo->u4TxDataCntErrType[2], prInfo->u4TxDataCntErrType[3], + prInfo->u4TxDataCntErrType[4], prInfo->u4TxDataCntErrType[5]); + } + + for (u4RateId = 1, u4Total = 0; u4RateId < 16; u4RateId++) + u4Total += prInfo->u4TxRateCntNonHT[u4RateId]; + if (u4Total > 0) { + DBGLOG(RX, INFO, " non-HT TRATE (%u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u)\n", + prInfo->u4TxRateCntNonHT[0], prInfo->u4TxRateCntNonHT[1], + prInfo->u4TxRateCntNonHT[2], prInfo->u4TxRateCntNonHT[3], + prInfo->u4TxRateCntNonHT[4], prInfo->u4TxRateCntNonHT[5], + prInfo->u4TxRateCntNonHT[6], prInfo->u4TxRateCntNonHT[7], + prInfo->u4TxRateCntNonHT[8], prInfo->u4TxRateCntNonHT[9], + prInfo->u4TxRateCntNonHT[10], prInfo->u4TxRateCntNonHT[11], + prInfo->u4TxRateCntNonHT[12], prInfo->u4TxRateCntNonHT[13], + prInfo->u4TxRateCntNonHT[14], prInfo->u4TxRateCntNonHT[15]); + } + if (prInfo->u4TxRateCntNonHT[0] > 0) { + DBGLOG(RX, INFO, " HT TRATE (1M %u) (%u %u %u %u %u %u %u %u)\n", + prInfo->u4TxRateCntNonHT[0], + prInfo->u4TxRateCntHT[0], prInfo->u4TxRateCntHT[1], + prInfo->u4TxRateCntHT[2], prInfo->u4TxRateCntHT[3], + prInfo->u4TxRateCntHT[4], prInfo->u4TxRateCntHT[5], + prInfo->u4TxRateCntHT[6], prInfo->u4TxRateCntHT[7]); + } else { + DBGLOG(RX, INFO, " HT TRATE (%u %u %u %u %u %u %u %u)\n", + prInfo->u4TxRateCntHT[0], prInfo->u4TxRateCntHT[1], + prInfo->u4TxRateCntHT[2], prInfo->u4TxRateCntHT[3], + prInfo->u4TxRateCntHT[4], prInfo->u4TxRateCntHT[5], + prInfo->u4TxRateCntHT[6], prInfo->u4TxRateCntHT[7]); + } + + if ((prStaRec->u4RxReorderFallAheadCnt != 0) || (prStaRec->u4RxReorderFallBehindCnt != 0) || + (prStaRec->u4RxReorderHoleCnt != 0) || (prStaRec->u4RxReorderFallBehindNoDropCnt != 0)) { + DBGLOG(RX, INFO, " TREORDER (%u %u %u %u)\n", + prStaRec->u4RxReorderFallAheadCnt, prStaRec->u4RxReorderFallBehindCnt, + prStaRec->u4RxReorderHoleCnt, prStaRec->u4RxReorderFallBehindNoDropCnt); + } + + if (prInfo->u4RxDataCntErr == 0) { + DBGLOG(RX, INFO, " ROK(%u %u)\n", + prInfo->u4RxDataCntAll, prStaRec->u4StatsRxPassToOsCnt); + } else { + DBGLOG(RX, INFO, " ROK(%u %u) ERR(%u)\n", + prInfo->u4RxDataCntAll, prStaRec->u4StatsRxPassToOsCnt, + prInfo->u4RxDataCntErr); + } + + for (u4RateId = 1, u4Total = 0; u4RateId < 16; u4RateId++) + u4Total += prInfo->u4RxRateCnt[0][u4RateId] + prInfo->u4RxRateRetryCnt[0][u4RateId]; + if (u4Total > 0) { + for (u4RateId = 0, u4Total = 0; u4RateId < 16; u4RateId++) + u4Total += prInfo->u4RxRateRetryCnt[0][u4RateId]; + if (u4Total > 0) { + DBGLOG(RX, INFO, + " RCCK (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n" + "(%u %u)(%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n", + prInfo->u4RxRateCnt[0][0], prInfo->u4RxRateRetryCnt[0][0], + prInfo->u4RxRateCnt[0][1], prInfo->u4RxRateRetryCnt[0][1], + prInfo->u4RxRateCnt[0][2], prInfo->u4RxRateRetryCnt[0][2], + prInfo->u4RxRateCnt[0][3], prInfo->u4RxRateRetryCnt[0][3], + prInfo->u4RxRateCnt[0][4], prInfo->u4RxRateRetryCnt[0][4], + prInfo->u4RxRateCnt[0][5], prInfo->u4RxRateRetryCnt[0][5], + prInfo->u4RxRateCnt[0][6], prInfo->u4RxRateRetryCnt[0][6], + prInfo->u4RxRateCnt[0][7], prInfo->u4RxRateRetryCnt[0][7], + prInfo->u4RxRateCnt[0][8], prInfo->u4RxRateRetryCnt[0][8], + prInfo->u4RxRateCnt[0][9], prInfo->u4RxRateRetryCnt[0][9], + prInfo->u4RxRateCnt[0][10], prInfo->u4RxRateRetryCnt[0][10], + prInfo->u4RxRateCnt[0][11], prInfo->u4RxRateRetryCnt[0][11], + prInfo->u4RxRateCnt[0][12], prInfo->u4RxRateRetryCnt[0][12], + prInfo->u4RxRateCnt[0][13], prInfo->u4RxRateRetryCnt[0][13], + prInfo->u4RxRateCnt[0][14], prInfo->u4RxRateRetryCnt[0][14], + prInfo->u4RxRateCnt[0][15], prInfo->u4RxRateRetryCnt[0][15]); + } else { + DBGLOG(RX, INFO, " RCCK (%u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u)\n", + prInfo->u4RxRateCnt[0][0], + prInfo->u4RxRateCnt[0][1], + prInfo->u4RxRateCnt[0][2], + prInfo->u4RxRateCnt[0][3], + prInfo->u4RxRateCnt[0][4], + prInfo->u4RxRateCnt[0][5], + prInfo->u4RxRateCnt[0][6], + prInfo->u4RxRateCnt[0][7], + prInfo->u4RxRateCnt[0][8], + prInfo->u4RxRateCnt[0][9], + prInfo->u4RxRateCnt[0][10], + prInfo->u4RxRateCnt[0][11], + prInfo->u4RxRateCnt[0][12], + prInfo->u4RxRateCnt[0][13], + prInfo->u4RxRateCnt[0][14], prInfo->u4RxRateCnt[0][15]); + } + } else { + if ((prInfo->u4RxRateCnt[0][0] + prInfo->u4RxRateRetryCnt[0][0]) > 0) { + DBGLOG(RX, INFO, " RCCK (%u %u)\n", + prInfo->u4RxRateCnt[0][0], prInfo->u4RxRateRetryCnt[0][0]); + } + } + + for (u4RateId = 0, u4Total = 0; u4RateId < 16; u4RateId++) + u4Total += prInfo->u4RxRateCnt[1][u4RateId] + prInfo->u4RxRateRetryCnt[1][u4RateId]; + if (u4Total > 0) { + for (u4RateId = 0, u4Total = 0; u4RateId < 16; u4RateId++) + u4Total += prInfo->u4RxRateRetryCnt[1][u4RateId]; + if (u4Total > 0) { + DBGLOG(RX, INFO, + " ROFDM (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n" + "(%u %u)(%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n", + prInfo->u4RxRateCnt[1][0], prInfo->u4RxRateRetryCnt[1][0], + prInfo->u4RxRateCnt[1][1], prInfo->u4RxRateRetryCnt[1][1], + prInfo->u4RxRateCnt[1][2], prInfo->u4RxRateRetryCnt[1][2], + prInfo->u4RxRateCnt[1][3], prInfo->u4RxRateRetryCnt[1][3], + prInfo->u4RxRateCnt[1][4], prInfo->u4RxRateRetryCnt[1][4], + prInfo->u4RxRateCnt[1][5], prInfo->u4RxRateRetryCnt[1][5], + prInfo->u4RxRateCnt[1][6], prInfo->u4RxRateRetryCnt[1][6], + prInfo->u4RxRateCnt[1][7], prInfo->u4RxRateRetryCnt[1][7], + prInfo->u4RxRateCnt[1][8], prInfo->u4RxRateRetryCnt[1][8], + prInfo->u4RxRateCnt[1][9], prInfo->u4RxRateRetryCnt[1][9], + prInfo->u4RxRateCnt[1][10], prInfo->u4RxRateRetryCnt[1][10], + prInfo->u4RxRateCnt[1][11], prInfo->u4RxRateRetryCnt[1][11], + prInfo->u4RxRateCnt[1][12], prInfo->u4RxRateRetryCnt[1][12], + prInfo->u4RxRateCnt[1][13], prInfo->u4RxRateRetryCnt[1][13], + prInfo->u4RxRateCnt[1][14], prInfo->u4RxRateRetryCnt[1][14], + prInfo->u4RxRateCnt[1][15], prInfo->u4RxRateRetryCnt[1][15]); + } else { + DBGLOG(RX, INFO, " ROFDM (%u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u)\n", + prInfo->u4RxRateCnt[1][0], + prInfo->u4RxRateCnt[1][1], + prInfo->u4RxRateCnt[1][2], + prInfo->u4RxRateCnt[1][3], + prInfo->u4RxRateCnt[1][4], + prInfo->u4RxRateCnt[1][5], + prInfo->u4RxRateCnt[1][6], + prInfo->u4RxRateCnt[1][7], + prInfo->u4RxRateCnt[1][8], + prInfo->u4RxRateCnt[1][9], + prInfo->u4RxRateCnt[1][10], + prInfo->u4RxRateCnt[1][11], + prInfo->u4RxRateCnt[1][12], + prInfo->u4RxRateCnt[1][13], + prInfo->u4RxRateCnt[1][14], prInfo->u4RxRateCnt[1][15]); + } + } + + for (u4RateId = 0, u4Total = 0; u4RateId < 16; u4RateId++) + u4Total += prInfo->u4RxRateCnt[2][u4RateId] + prInfo->u4RxRateRetryCnt[2][u4RateId]; + if (u4Total > 0) { + for (u4RateId = 0, u4Total = 0; u4RateId < 16; u4RateId++) + u4Total += prInfo->u4RxRateRetryCnt[2][u4RateId]; + if (u4Total > 0) { + DBGLOG(RX, INFO, " RHT\n" + "(%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n", + prInfo->u4RxRateCnt[2][0], prInfo->u4RxRateRetryCnt[2][0], + prInfo->u4RxRateCnt[2][1], prInfo->u4RxRateRetryCnt[2][1], + prInfo->u4RxRateCnt[2][2], prInfo->u4RxRateRetryCnt[2][2], + prInfo->u4RxRateCnt[2][3], prInfo->u4RxRateRetryCnt[2][3], + prInfo->u4RxRateCnt[2][4], prInfo->u4RxRateRetryCnt[2][4], + prInfo->u4RxRateCnt[2][5], prInfo->u4RxRateRetryCnt[2][5], + prInfo->u4RxRateCnt[2][6], prInfo->u4RxRateRetryCnt[2][6], + prInfo->u4RxRateCnt[2][7], prInfo->u4RxRateRetryCnt[2][7]); + } else { + DBGLOG(RX, INFO, " RHT (%u %u %u %u %u %u %u %u)\n", + prInfo->u4RxRateCnt[2][0], + prInfo->u4RxRateCnt[2][1], + prInfo->u4RxRateCnt[2][2], + prInfo->u4RxRateCnt[2][3], + prInfo->u4RxRateCnt[2][4], + prInfo->u4RxRateCnt[2][5], + prInfo->u4RxRateCnt[2][6], prInfo->u4RxRateCnt[2][7]); + } + } + + /* RX drop counts */ + for (u4RateId = 0, u4Total = 0; u4RateId < 20; u4RateId++) + u4Total += prInfo->u4NumOfRxDrop[u4RateId]; + if (u4Total > 0) { + DBGLOG(RX, INFO, " RX Drop Count: (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u)\n" + " (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u)\n", + prInfo->u4NumOfRxDrop[0], prInfo->u4NumOfRxDrop[1], + prInfo->u4NumOfRxDrop[2], prInfo->u4NumOfRxDrop[3], + prInfo->u4NumOfRxDrop[4], prInfo->u4NumOfRxDrop[5], + prInfo->u4NumOfRxDrop[6], prInfo->u4NumOfRxDrop[7], + prInfo->u4NumOfRxDrop[8], prInfo->u4NumOfRxDrop[9], + prInfo->u4NumOfRxDrop[10], prInfo->u4NumOfRxDrop[11], + prInfo->u4NumOfRxDrop[12], prInfo->u4NumOfRxDrop[13], + prInfo->u4NumOfRxDrop[14], prInfo->u4NumOfRxDrop[15], + prInfo->u4NumOfRxDrop[16], prInfo->u4NumOfRxDrop[17], + prInfo->u4NumOfRxDrop[18], prInfo->u4NumOfRxDrop[19]); + } + + /* delay from HIF RX to HIF RX Done */ + if (((prInfo->u4StayIntMinHR2HRD[1] + prInfo->u4StayIntAvgHR2HRD[1] + + prInfo->u4StayIntMaxHR2HRD[1]) > 0) || + ((prInfo->u4StayIntMinHR2HRD[2] + prInfo->u4StayIntAvgHR2HRD[2] + + prInfo->u4StayIntMaxHR2HRD[2]) > 0)) { + DBGLOG(RX, INFO, " StayIntR_HR2HRD us (%u %u %u) (%u %u %u) (%u %u %u)\n", + prInfo->u4StayIntMinHR2HRD[0], prInfo->u4StayIntAvgHR2HRD[0], + prInfo->u4StayIntMaxHR2HRD[0], + prInfo->u4StayIntMinHR2HRD[1], prInfo->u4StayIntAvgHR2HRD[1], + prInfo->u4StayIntMaxHR2HRD[1], + prInfo->u4StayIntMinHR2HRD[2], prInfo->u4StayIntAvgHR2HRD[2], + prInfo->u4StayIntMaxHR2HRD[2]); + } else { + DBGLOG(RX, INFO, " StayIntR_HR2HRD us (%u %u %u)\n", + prInfo->u4StayIntMinHR2HRD[0], prInfo->u4StayIntAvgHR2HRD[0], + prInfo->u4StayIntMaxHR2HRD[0]); + } + + /* others */ + DBGLOG(RX, INFO, " OTHER (%u) (%u) (%u) (%x)\n", + prInfo->u4RxFifoFullCnt, prAdapter->ucScanTime, + prInfo->u4NumOfChanChange, prInfo->u4CurrChnlInfo); +#if CFG_SUPPORT_THERMO_THROTTLING + prAdapter->u4AirDelayTotal = (prInfo->u4AirDelayTotal << 5) / 400000; +#endif + +#if CFG_ENABLE_PER_STA_STATISTICS_LOG + /* rQueryStaStatistics.u4TxFailCount + rQueryStaStatistics.u4TxLifeTimeoutCount; */ + u4TotalError = prInfo->u4TxDataCntErr; + u4TxExceedThresholdCount = prStaRec->u4ThresholdCounter; + u4TxTotalCount = prStaRec->u4TotalTxPktsNumber; + + if (u4TxTotalCount) { + if (u4TxExceedThresholdCount <= u4TxTotalCount) + u4LinkScore = (90 - ((u4TxExceedThresholdCount * 90) / u4TxTotalCount)); + else + u4LinkScore = 0; + } else { + u4LinkScore = 90; + } + u4LinkScore += 10; + if (u4LinkScore == 10) { + if (u4TotalError <= u4TxTotalCount) + u4LinkScore = (10 - ((u4TotalError * 10) / u4TxTotalCount)); + else + u4LinkScore = 0; + } + if (u4LinkScore > 100) + u4LinkScore = 100; + + DBGLOG(RX, INFO, " link_score=%d for [%pM](%d)\n", + u4LinkScore, prStaRec->aucMacAddr, prStaRec->ucNetTypeIndex); + + /* Reset statistics */ + prStaRec->u4ThresholdCounter = 0; + prStaRec->u4TotalTxPktsNumber = 0; +#endif + + /* reset */ + kalMemZero(prStaRec->u4StayIntMinRx, sizeof(prStaRec->u4StayIntMinRx)); + kalMemZero(prStaRec->u4StayIntAvgRx, sizeof(prStaRec->u4StayIntAvgRx)); + kalMemZero(prStaRec->u4StayIntMaxRx, sizeof(prStaRec->u4StayIntMaxRx)); + prStaRec->u4StatsRxPassToOsCnt = 0; + prStaRec->u4RxReorderFallAheadCnt = 0; + prStaRec->u4RxReorderFallBehindCnt = 0; + prStaRec->u4RxReorderHoleCnt = 0; + prStaRec->u4RxReorderFallBehindNoDropCnt = 0; + } + + STATS_DRIVER_OWN_RESET(); + kalMemFree(prInfo, VIR_MEM_TYPE, sizeof(STATS_INFO_ENV_T)); +} + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to display all environment log. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +*/ +/*----------------------------------------------------------------------------*/ +static void statsInfoEnvDisplay(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen) +{ + P_ADAPTER_T prAdapter; + STA_RECORD_T *prStaRec; + UINT32 u4NumOfInfo, u4InfoId; + UINT32 u4RxErrBitmap; + STATS_INFO_ENV_T rStatsInfoEnv, *prInfo; + +/* + * [wlan] statsInfoEnvRequest: (INIT INFO) statsInfoEnvRequest cmd ok. + * [wlan] statsEventHandle: (INIT INFO) statsEventHandle: Rcv a event + * [wlan] statsEventHandle: (INIT INFO) statsEventHandle: Rcv a event: 0 + * [wlan] statsInfoEnvDisplay: (INIT INFO) Display stats for [00:0c:43:31:35:97]: + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) TPAM(0x0) RTS(0 0) BA(0x1 0) OK(9 9 xxx) ERR(0 0 0 0 0 0 0) + * TPAM (bit0: enable 40M, bit1: enable 20 short GI, bit2: enable 40 short GI, + bit3: use 40M TX, bit4: use short GI TX, bit5: use no ack) + * RTS (1st: current use RTS/CTS, 2nd: ever use RTS/CTS) + * BA (1st: TX session BA bitmap for TID0 ~ TID7, 2nd: peer receive maximum agg number) + * OK (1st: total number of tx packet from host, 2nd: total number of tx ok, system time last TX OK) + * ERR (1st: total number of tx err, 2nd ~ 7st: total number of + WLAN_STATUS_BUFFER_RETAINED, WLAN_STATUS_PACKET_FLUSHED, WLAN_STATUS_PACKET_AGING_TIMEOUT, + WLAN_STATUS_PACKET_MPDU_ERROR, WLAN_STATUS_PACKET_RTS_ERROR, WLAN_STATUS_PACKET_LIFETIME_ERROR) + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) TRATE (6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (0 0 0 0 0 0 0 3) + * TX rate count (1M 2 5.5 11 NA NA NA NA 48 24 12 6 54 36 18 9) (MCS0 ~ MCS7) + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) RX(148 1 0) BA(0x1 64) OK(2 2) ERR(0) + * RX (1st: latest RCPI, 2nd: chan num) + * BA (1st: RX session BA bitmap for TID0 ~ TID7, 2nd: our receive maximum agg number) + * OK (number of rx packets without error, number of rx packets to OS) + * ERR (number of rx packets with error) + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) RCCK (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + * CCK MODE (1 2 5.5 11M) + * [wlan] statsInfoEnvDisplay: (INIT INFO) ROFDM (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + * OFDM MODE (NA NA NA NA 6 9 12 18 24 36 48 54M) + * [wlan] statsInfoEnvDisplay: (INIT INFO) RHT (0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0) + * MIXED MODE (number of rx packets with MCS0 ~ MCS15) + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) StayIntH2M us (29 29 32) (0 0 0) (0 0 0) + * delay from HIF to MAC own bit=1 (min, avg, max for 500B) (min, avg, max for 1000B) (min, avg, max for others) + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) AirTime us (608 864 4480) (0 0 0) (0 0 0) + * delay from MAC start TX to MAC TX done + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) StayInt us (795 1052 4644_4504) (0 0 0_0) (0 0 0_0) + * delay from HIF to MAC TX done (min, avg, max_system time for 500B) + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) StayIntD2T us (795 1052 4644) (0 0 0) (0 0 0) + * delay from driver to MAC TX done (min, avg, max for 500B) + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) StayIntR_M2H us (37 40 58) (0 0 0) (0 0 0) + * delay from MAC to HIF (min, avg, max for 500B) + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) StayIntR_H2D us (0 0 0) (0 0 0) (0 0 0) + * delay from HIF to Driver OS (min, avg, max for 500B) + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) StayCntD2H unit:10ms (10 0 0 0) + * delay count from Driver to HIF (count in 0~10ms, 10~20ms, 20~30ms, others) + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) StayCnt unit:1ms (6 3 0 1) + * delay count from HIF to TX DONE (count in 0~1ms, 1~5ms, 5~10ms, others) + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) + * StayCnt (0~1161:7) (1161~2322:2) (2322~3483:0) (3483~4644:0) (4644~:1) + * delay count from HIF to TX DONE (count in 0~1161 ticks, 1161~2322, 2322~3483, 3483~4644, others) + * + * [wlan] statsInfoEnvDisplay: (INIT INFO) OTHER (61877) (0) (38) (0) (0) (0ms) + * Channel idle time, scan count, channel change count, empty tx quota count, + * power save change count from active to PS, maximum delay from PS to active + */ + + /* init */ + prAdapter = prGlueInfo->prAdapter; + prInfo = &rStatsInfoEnv; + kalMemZero(&rStatsInfoEnv, sizeof(rStatsInfoEnv)); + + if (u4InBufLen > sizeof(rStatsInfoEnv)) + u4InBufLen = sizeof(rStatsInfoEnv); + + /* parse */ + u4NumOfInfo = *(UINT32 *) prInBuf; + u4RxErrBitmap = *(UINT32 *) (prInBuf + 4); + + /* print */ + for (u4InfoId = 0; u4InfoId < u4NumOfInfo; u4InfoId++) { + /* + * use u4InBufLen, not sizeof(rStatsInfoEnv) + * because the firmware version maybe not equal to driver version + */ + kalMemCopy(&rStatsInfoEnv, prInBuf + 8, u4InBufLen); + + prStaRec = cnmGetStaRecByIndex(prAdapter, rStatsInfoEnv.ucStaRecIdx); + if (prStaRec == NULL) + continue; + + DBGLOG(RX, INFO, " Display stats V%d.%d for [%pM]: %uB %ums\n", + prInfo->ucFwVer[0], prInfo->ucFwVer[1], + (prStaRec->aucMacAddr), (UINT32) sizeof(STATS_INFO_ENV_T), + prInfo->u4ReportSysTime); + DBGLOG(RX, INFO, "TPAM(0x%x)RTS(%u %u)BA(0x%x %u)OS(%u)OK(%u %u)ERR(%u %u %u %u %u %u %u)\n", + prInfo->ucTxParam, + prInfo->fgTxIsRtsUsed, prInfo->fgTxIsRtsEverUsed, + prInfo->ucTxAggBitmap, prInfo->ucTxPeerAggMaxSize, + (UINT32) prGlueInfo->rNetDevStats.tx_packets, + prInfo->u4TxDataCntAll, prInfo->u4TxDataCntOK, + prInfo->u4TxDataCntErr, prInfo->u4TxDataCntErrType[0], + prInfo->u4TxDataCntErrType[1], prInfo->u4TxDataCntErrType[2], + prInfo->u4TxDataCntErrType[3], prInfo->u4TxDataCntErrType[4], + prInfo->u4TxDataCntErrType[5])); + + DBGLOG(RX, INFO, "TRATE(%u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u)\n", + prInfo->u4TxRateCntNonHT[0], prInfo->u4TxRateCntNonHT[1], + prInfo->u4TxRateCntNonHT[2], prInfo->u4TxRateCntNonHT[3], + prInfo->u4TxRateCntNonHT[4], prInfo->u4TxRateCntNonHT[5], + prInfo->u4TxRateCntNonHT[6], prInfo->u4TxRateCntNonHT[7], + prInfo->u4TxRateCntNonHT[8], prInfo->u4TxRateCntNonHT[9], + prInfo->u4TxRateCntNonHT[10], prInfo->u4TxRateCntNonHT[11], + prInfo->u4TxRateCntNonHT[12], prInfo->u4TxRateCntNonHT[13], + prInfo->u4TxRateCntNonHT[14], prInfo->u4TxRateCntNonHT[15], + prInfo->u4TxRateCntHT[0], prInfo->u4TxRateCntHT[1], + prInfo->u4TxRateCntHT[2], prInfo->u4TxRateCntHT[3], + prInfo->u4TxRateCntHT[4], prInfo->u4TxRateCntHT[5], + prInfo->u4TxRateCntHT[6], prInfo->u4TxRateCntHT[7])); + + DBGLOG(RX, INFO, " TREORDER (%u %u %u)\n", + prStaRec->u4RxReorderFallAheadCnt, + prStaRec->u4RxReorderFallBehindCnt, prStaRec->u4RxReorderHoleCnt); + + DBGLOG(RX, INFO, " RX(%u %u %u) BA(0x%x %u) OK(%u %u) ERR(%u)\n", + prInfo->ucRcvRcpi, prInfo->ucHwChanNum, prInfo->fgRxIsShortGI, + prInfo->ucRxAggBitmap, prInfo->ucRxAggMaxSize, + prInfo->u4RxDataCntAll, prStaRec->u4StatsRxPassToOsCnt, prInfo->u4RxDataCntErr); + + DBGLOG(RX, INFO, " RX Free MAC DESC(%u %u %u %u %u %u) Free HIF DESC(%u %u %u %u %u %u)\n", + prInfo->u4RxMacFreeDescCnt[0], prInfo->u4RxMacFreeDescCnt[1], + prInfo->u4RxMacFreeDescCnt[2], prInfo->u4RxMacFreeDescCnt[3], + prInfo->u4RxMacFreeDescCnt[4], prInfo->u4RxMacFreeDescCnt[5], + prInfo->u4RxHifFreeDescCnt[0], prInfo->u4RxHifFreeDescCnt[1], + prInfo->u4RxHifFreeDescCnt[2], prInfo->u4RxHifFreeDescCnt[3], + prInfo->u4RxHifFreeDescCnt[4], prInfo->u4RxHifFreeDescCnt[5])); + + DBGLOG(RX, INFO, " RCCK (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n" + "(%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n", + prInfo->u4RxRateCnt[0][0], prInfo->u4RxRateRetryCnt[0][0], + prInfo->u4RxRateCnt[0][1], prInfo->u4RxRateRetryCnt[0][1], + prInfo->u4RxRateCnt[0][2], prInfo->u4RxRateRetryCnt[0][2], + prInfo->u4RxRateCnt[0][3], prInfo->u4RxRateRetryCnt[0][3], + prInfo->u4RxRateCnt[0][4], prInfo->u4RxRateRetryCnt[0][4], + prInfo->u4RxRateCnt[0][5], prInfo->u4RxRateRetryCnt[0][5], + prInfo->u4RxRateCnt[0][6], prInfo->u4RxRateRetryCnt[0][6], + prInfo->u4RxRateCnt[0][7], prInfo->u4RxRateRetryCnt[0][7], + prInfo->u4RxRateCnt[0][8], prInfo->u4RxRateRetryCnt[0][8], + prInfo->u4RxRateCnt[0][9], prInfo->u4RxRateRetryCnt[0][9], + prInfo->u4RxRateCnt[0][10], prInfo->u4RxRateRetryCnt[0][10], + prInfo->u4RxRateCnt[0][11], prInfo->u4RxRateRetryCnt[0][11], + prInfo->u4RxRateCnt[0][12], prInfo->u4RxRateRetryCnt[0][12], + prInfo->u4RxRateCnt[0][13], prInfo->u4RxRateRetryCnt[0][13], + prInfo->u4RxRateCnt[0][14], prInfo->u4RxRateRetryCnt[0][14], + prInfo->u4RxRateCnt[0][15], prInfo->u4RxRateRetryCnt[0][15])); + DBGLOG(RX, INFO, " ROFDM (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n" + "(%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n", + prInfo->u4RxRateCnt[1][0], prInfo->u4RxRateRetryCnt[1][0], + prInfo->u4RxRateCnt[1][1], prInfo->u4RxRateRetryCnt[1][1], + prInfo->u4RxRateCnt[1][2], prInfo->u4RxRateRetryCnt[1][2], + prInfo->u4RxRateCnt[1][3], prInfo->u4RxRateRetryCnt[1][3], + prInfo->u4RxRateCnt[1][4], prInfo->u4RxRateRetryCnt[1][4], + prInfo->u4RxRateCnt[1][5], prInfo->u4RxRateRetryCnt[1][5], + prInfo->u4RxRateCnt[1][6], prInfo->u4RxRateRetryCnt[1][6], + prInfo->u4RxRateCnt[1][7], prInfo->u4RxRateRetryCnt[1][7], + prInfo->u4RxRateCnt[1][8], prInfo->u4RxRateRetryCnt[1][8], + prInfo->u4RxRateCnt[1][9], prInfo->u4RxRateRetryCnt[1][9], + prInfo->u4RxRateCnt[1][10], prInfo->u4RxRateRetryCnt[1][10], + prInfo->u4RxRateCnt[1][11], prInfo->u4RxRateRetryCnt[1][11], + prInfo->u4RxRateCnt[1][12], prInfo->u4RxRateRetryCnt[1][12], + prInfo->u4RxRateCnt[1][13], prInfo->u4RxRateRetryCnt[1][13], + prInfo->u4RxRateCnt[1][14], prInfo->u4RxRateRetryCnt[1][14], + prInfo->u4RxRateCnt[1][15], prInfo->u4RxRateRetryCnt[1][15])); + DBGLOG(RX, INFO, " RHT (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n" + "(%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n", + prInfo->u4RxRateCnt[2][0], prInfo->u4RxRateRetryCnt[2][0], + prInfo->u4RxRateCnt[2][1], prInfo->u4RxRateRetryCnt[2][1], + prInfo->u4RxRateCnt[2][2], prInfo->u4RxRateRetryCnt[2][2], + prInfo->u4RxRateCnt[2][3], prInfo->u4RxRateRetryCnt[2][3], + prInfo->u4RxRateCnt[2][4], prInfo->u4RxRateRetryCnt[2][4], + prInfo->u4RxRateCnt[2][5], prInfo->u4RxRateRetryCnt[2][5], + prInfo->u4RxRateCnt[2][6], prInfo->u4RxRateRetryCnt[2][6], + prInfo->u4RxRateCnt[2][7], prInfo->u4RxRateRetryCnt[2][7], + prInfo->u4RxRateCnt[2][8], prInfo->u4RxRateRetryCnt[2][8], + prInfo->u4RxRateCnt[2][9], prInfo->u4RxRateRetryCnt[2][9], + prInfo->u4RxRateCnt[2][10], prInfo->u4RxRateRetryCnt[2][10], + prInfo->u4RxRateCnt[2][11], prInfo->u4RxRateRetryCnt[2][11], + prInfo->u4RxRateCnt[2][12], prInfo->u4RxRateRetryCnt[2][12], + prInfo->u4RxRateCnt[2][13], prInfo->u4RxRateRetryCnt[2][13], + prInfo->u4RxRateCnt[2][14], prInfo->u4RxRateRetryCnt[2][14], + prInfo->u4RxRateCnt[2][15], prInfo->u4RxRateRetryCnt[2][15])); + + /* delay from HIF to MAC */ + DBGLOG(RX, INFO, " StayIntH2M us (%u %u %u) (%u %u %u) (%u %u %u)\n", + prInfo->u4StayIntMinH2M[0], prInfo->u4StayIntAvgH2M[0], + prInfo->u4StayIntMaxH2M[0], + prInfo->u4StayIntMinH2M[1], prInfo->u4StayIntAvgH2M[1], + prInfo->u4StayIntMaxH2M[1], + prInfo->u4StayIntMinH2M[2], prInfo->u4StayIntAvgH2M[2], + prInfo->u4StayIntMaxH2M[2])); + /* delay from MAC to TXDONE */ + DBGLOG(RX, INFO, " AirTime us (%u %u %u) (%u %u %u) (%u %u %u)\n", + prInfo->u4AirDelayMin[0] << 5, prInfo->u4AirDelayAvg[0] << 5, + prInfo->u4AirDelayMax[0] << 5, + prInfo->u4AirDelayMin[1] << 5, prInfo->u4AirDelayAvg[1] << 5, + prInfo->u4AirDelayMax[1] << 5, + prInfo->u4TxDataCntAll, (prInfo->u4AirDelayAvg[2] << 5) / (prInfo->u4TxDataCntAll), + (prInfo->u4AirDelayAvg[2] << 5) / 400000)); + prAdapter->u4AirDelayTotal = (prInfo->u4AirDelayTotal << 5) / 400000; + /* delay from HIF to TXDONE */ + DBGLOG(RX, INFO, " StayInt us (%u %u %u_%u) (%u %u %u_%u) (%u %u %u_%u)\n", + prInfo->u4StayIntMin[0], prInfo->u4StayIntAvg[0], + prInfo->u4StayIntMax[0], prInfo->u4StayIntMaxSysTime[0], + prInfo->u4StayIntMin[1], prInfo->u4StayIntAvg[1], + prInfo->u4StayIntMax[1], prInfo->u4StayIntMaxSysTime[1], + prInfo->u4StayIntMin[2], prInfo->u4StayIntAvg[2], + prInfo->u4StayIntMax[2], prInfo->u4StayIntMaxSysTime[2])); + /* delay from Driver to TXDONE */ + DBGLOG(RX, INFO, " StayIntD2T us (%u %u %u) (%u %u %u) (%u %u %u)\n", + prInfo->u4StayIntMinD2T[0], prInfo->u4StayIntAvgD2T[0], + prInfo->u4StayIntMaxD2T[0], + prInfo->u4StayIntMinD2T[1], prInfo->u4StayIntAvgD2T[1], + prInfo->u4StayIntMaxD2T[1], + prInfo->u4StayIntMinD2T[2], prInfo->u4StayIntAvgD2T[2], + prInfo->u4StayIntMaxD2T[2])); + + /* delay from RXDONE to HIF */ + DBGLOG(RX, INFO, " StayIntR_M2H us (%u %u %u) (%u %u %u) (%u %u %u)\n", + prInfo->u4StayIntMinRx[0], prInfo->u4StayIntAvgRx[0], + prInfo->u4StayIntMaxRx[0], + prInfo->u4StayIntMinRx[1], prInfo->u4StayIntAvgRx[1], + prInfo->u4StayIntMaxRx[1], + prInfo->u4StayIntMinRx[2], prInfo->u4StayIntAvgRx[2], prInfo->u4StayIntMaxRx[2])); + /* delay from HIF to OS */ + DBGLOG(RX, INFO, " StayIntR_H2D us (%u %u %u) (%u %u %u) (%u %u %u)\n", + prStaRec->u4StayIntMinRx[0], prStaRec->u4StayIntAvgRx[0], + prStaRec->u4StayIntMaxRx[0], + prStaRec->u4StayIntMinRx[1], prStaRec->u4StayIntAvgRx[1], + prStaRec->u4StayIntMaxRx[1], + prStaRec->u4StayIntMinRx[2], prStaRec->u4StayIntAvgRx[2], + prStaRec->u4StayIntMaxRx[2])); + + /* count based on delay from OS to HIF */ + DBGLOG(RX, INFO, " StayCntD2H unit:%dms (%d %d %d %d)\n", + STATS_STAY_INT_D2H_CONST, + prInfo->u4StayIntD2HByConst[0], prInfo->u4StayIntD2HByConst[1], + prInfo->u4StayIntD2HByConst[2], prInfo->u4StayIntD2HByConst[3]); + + /* count based on different delay from HIF to TX DONE */ + DBGLOG(RX, INFO, " StayCnt unit:%dms (%d %d %d %d)\n", + STATS_STAY_INT_CONST, + prInfo->u4StayIntByConst[0], prInfo->u4StayIntByConst[1], + prInfo->u4StayIntByConst[2], prInfo->u4StayIntByConst[3]); + DBGLOG(RX, INFO, " StayCnt (%d~%d:%d) (%d~%d:%d) (%d~%d:%d) (%d~%d:%d) (%d~:%d)\n", + 0, prInfo->u4StayIntMaxPast / 4, prInfo->u4StayIntCnt[0], + prInfo->u4StayIntMaxPast / 4, prInfo->u4StayIntMaxPast / 2, prInfo->u4StayIntCnt[1], + prInfo->u4StayIntMaxPast / 2, prInfo->u4StayIntMaxPast * 3 / 4, + prInfo->u4StayIntCnt[2], prInfo->u4StayIntMaxPast * 3 / 4, prInfo->u4StayIntMaxPast, + prInfo->u4StayIntCnt[3], prInfo->u4StayIntMaxPast, prInfo->u4StayIntCnt[4])); + + /* channel idle time */ + DBGLOG(RX, INFO, " Idle Time (slot): (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u)\n", + prInfo->au4ChanIdleCnt[0], prInfo->au4ChanIdleCnt[1], + prInfo->au4ChanIdleCnt[2], prInfo->au4ChanIdleCnt[3], + prInfo->au4ChanIdleCnt[4], prInfo->au4ChanIdleCnt[5], + prInfo->au4ChanIdleCnt[6], prInfo->au4ChanIdleCnt[7], + prInfo->au4ChanIdleCnt[8], prInfo->au4ChanIdleCnt[9])); + + /* BT coex */ + DBGLOG(RX, INFO, " BT coex (0x%x)\n", prInfo->u4BtContUseTime); + + /* others */ + DBGLOG(RX, INFO, " OTHER (%u) (%u) (%u) (%u) (%u) (%ums) (%uus)\n", + prInfo->u4RxFifoFullCnt, prAdapter->ucScanTime, + prInfo->u4NumOfChanChange, prStaRec->u4NumOfNoTxQuota, + prInfo->ucNumOfPsChange, prInfo->u4PsIntMax, u4DrvOwnMax / 1000); + + /* reset */ + kalMemZero(prStaRec->u4StayIntMinRx, sizeof(prStaRec->u4StayIntMinRx)); + kalMemZero(prStaRec->u4StayIntAvgRx, sizeof(prStaRec->u4StayIntAvgRx)); + kalMemZero(prStaRec->u4StayIntMaxRx, sizeof(prStaRec->u4StayIntMaxRx)); + prStaRec->u4StatsRxPassToOsCnt = 0; + prStaRec->u4RxReorderFallAheadCnt = 0; + prStaRec->u4RxReorderFallBehindCnt = 0; + prStaRec->u4RxReorderHoleCnt = 0; + prStaRec->u4RxReorderFallBehindNoDropCnt = 0; + } + + STATS_DRIVER_OWN_RESET(); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to request firmware to feedback statistics. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static WLAN_STATUS +statsInfoEnvRequest(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + STATS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* sanity check */ + if (fgIsUnderSuspend == true) { + DBGLOG(TX, INFO, "%s fgIsUnderSuspend = true.\n", __func__); + return WLAN_STATUS_SUCCESS; /* do not request stats after early suspend */ + } + + /* init command buffer */ + prCmdContent = (STATS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = STATS_CORE_CMD_ENV_REQUEST; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_STATS, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(STATS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(RX, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return WLAN_STATUS_RESOURCES; + } + + DBGLOG(RX, INFO, "%s cmd ok.\n", __func__); + return WLAN_STATUS_SUCCESS; +} + +/******************************************************************************* +* P U B L I C F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to handle any statistics event. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID statsEventHandle(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen) +{ + UINT32 u4EventId; + + /* sanity check */ +/* DBGLOG(RX, INFO, */ +/* (" %s: Rcv a event\n", __FUNCTION__)); */ + + if ((prGlueInfo == NULL) || (prInBuf == NULL)) + return; /* shall not be here */ + + /* handle */ + u4EventId = *(UINT32 *) prInBuf; + u4InBufLen -= 4; + +/* DBGLOG(RX, INFO, */ +/* (" %s: Rcv a event: %d\n", __FUNCTION__, u4EventId)); */ + + switch (u4EventId) { + case STATS_HOST_EVENT_ENV_REPORT: + statsInfoEnvDisplay(prGlueInfo, prInBuf + 4, u4InBufLen); + break; + + default: + break; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to detect if we can request firmware to feedback statistics. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] ucStaRecIndex The station index +* \param[out] None +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID statsEnvReportDetect(ADAPTER_T *prAdapter, UINT8 ucStaRecIndex) +{ + STA_RECORD_T *prStaRec; + OS_SYSTIME rCurTime; + STATS_CMD_CORE_T rCmd; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIndex); + + if (prStaRec == NULL) { + /* check station record but skip broadcast id: 0xFF */ + if (ucStaRecIndex != 0xFF) + DBGLOGLIMITED(TX, WARN, "%s : prStaRec[%d] is null!", __func__, ucStaRecIndex); + return; + } + + prStaRec->u4StatsEnvTxCnt++; + GET_CURRENT_SYSTIME(&rCurTime); + prAdapter->rStasEnvReportDetectTime = rCurTime; + + if (prStaRec->rStatsEnvTxPeriodLastTime == 0) { + DBGLOG(TX, WARN, "%s : rStatsEnvTxPeriodLastTime is 0!", __func__); + prStaRec->rStatsEnvTxLastTime = rCurTime; + prStaRec->rStatsEnvTxPeriodLastTime = rCurTime; + return; + } + + if (prStaRec->u4StatsEnvTxCnt > STATS_ENV_TX_CNT_REPORT_TRIGGER) { + if (CHECK_FOR_TIMEOUT(rCurTime, prStaRec->rStatsEnvTxLastTime, + SEC_TO_SYSTIME(STATS_ENV_TX_CNT_REPORT_TRIGGER_SEC))) { + rCmd.ucStaRecIdx = ucStaRecIndex; + statsInfoEnvRequest(prAdapter, &rCmd, 0, NULL); + + prStaRec->rStatsEnvTxLastTime = rCurTime; + prStaRec->rStatsEnvTxPeriodLastTime = rCurTime; + prStaRec->u4StatsEnvTxCnt = 0; + return; + } + } + + if (CHECK_FOR_TIMEOUT(rCurTime, prStaRec->rStatsEnvTxPeriodLastTime, SEC_TO_SYSTIME(STATS_ENV_TIMEOUT_SEC))) { + rCmd.ucStaRecIdx = ucStaRecIndex; + statsInfoEnvRequest(prAdapter, &rCmd, 0, NULL); + + prStaRec->rStatsEnvTxPeriodLastTime = rCurTime; + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to handle rx done. +* +* \param[in] prStaRec Pointer to the STA_RECORD_T structure +* \param[in] prSwRfb Pointer to the received packet +* \param[out] None +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID StatsEnvRxDone(STA_RECORD_T *prStaRec, SW_RFB_T *prSwRfb) +{ + UINT32 u4LenId; + UINT32 u4CurTime, u4DifTime; + + /* sanity check */ + if (prStaRec == NULL) + return; + + /* stats: rx done count */ + prStaRec->u4StatsRxPassToOsCnt++; + + /* get length partition ID */ + u4LenId = 0; + if (prSwRfb->u2PacketLen < STATS_STAY_INT_BYTE_THRESHOLD) { + u4LenId = 0; + } else { + if ((prSwRfb->u2PacketLen >= STATS_STAY_INT_BYTE_THRESHOLD) && + (prSwRfb->u2PacketLen < (STATS_STAY_INT_BYTE_THRESHOLD << 1))) { + u4LenId = 1; + } else + u4LenId = 2; + } + + /* stats: rx delay */ + u4CurTime = kalGetTimeTick(); + + if ((u4CurTime > prSwRfb->rRxTime) && (prSwRfb->rRxTime != 0)) { + u4DifTime = u4CurTime - prSwRfb->rRxTime; + + if (prStaRec->u4StayIntMinRx[u4LenId] == 0) /* impossible */ + prStaRec->u4StayIntMinRx[u4LenId] = 0xffffffff; + + if (u4DifTime > prStaRec->u4StayIntMaxRx[u4LenId]) + prStaRec->u4StayIntMaxRx[u4LenId] = u4DifTime; + else if (u4DifTime < prStaRec->u4StayIntMinRx[u4LenId]) + prStaRec->u4StayIntMinRx[u4LenId] = u4DifTime; + + prStaRec->u4StayIntAvgRx[u4LenId] += u4DifTime; + if (prStaRec->u4StayIntAvgRx[u4LenId] != u4DifTime) + prStaRec->u4StayIntAvgRx[u4LenId] >>= 1; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to handle rx done. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +UINT_64 StatsEnvTimeGet(VOID) +{ + /* TODO: use better API to get time to save time, jiffies unit is 10ms, too large */ + +/* struct timeval tv; */ + +/* do_gettimeofday(&tv); */ +/* return tv.tv_usec + tv.tv_sec * (UINT_64)1000000; */ + + UINT_64 u8Clk; +/* UINT32 *pClk = &u8Clk; */ + + u8Clk = sched_clock(); /* unit: naro seconds */ +/* printk(" sched_clock() = %x %x %u\n", pClk[0], pClk[1], sizeof(jiffies)); */ + + return (UINT_64) u8Clk; /* sched_clock *//* jiffies size = 4B */ +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to handle rx done. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID StatsEnvTxTime2Hif(MSDU_INFO_T *prMsduInfo, HIF_TX_HEADER_T *prHwTxHeader) +{ + UINT_64 u8SysTime, u8SysTimeIn; + UINT32 u4TimeDiff; + + u8SysTime = StatsEnvTimeGet(); + u8SysTimeIn = GLUE_GET_PKT_XTIME(prMsduInfo->prPacket); + u4TimeDiff = 0; + +/* printk(" hif: 0x%x %u %u %u\n", */ +/* prMsduInfo->prPacket, StatsEnvTimeGet(), u8SysTime, GLUE_GET_PKT_XTIME(prMsduInfo->prPacket)); */ + + if ((u8SysTimeIn > 0) && (u8SysTime > u8SysTimeIn)) { + u4TimeDiff = (UINT32) (u8SysTime - u8SysTimeIn); + u4TimeDiff = u4TimeDiff / 1000; /* ns to us */ + + /* pass the delay between OS to us and we to HIF */ + if (u4TimeDiff > 0xFFFF) + *(UINT16 *) prHwTxHeader->aucReserved = (UINT16) 0xFFFF; /* 65535 us */ + else + *(UINT16 *) prHwTxHeader->aucReserved = (UINT16) u4TimeDiff; + +/* printk(" u4TimeDiff: %u\n", u4TimeDiff); */ + } else { + prHwTxHeader->aucReserved[0] = 0; + prHwTxHeader->aucReserved[1] = 0; + } + + DBGLOG(TX, LOUD, "(%d)Tx 2 hif: 0x%p (%lld - %lld) =%u\n" + , prMsduInfo->u4DbgTxPktStatusIndex + , (PUINT_8)prMsduInfo->prPacket + , u8SysTime, GLUE_GET_PKT_XTIME(prMsduInfo->prPacket) + , u4TimeDiff); + + /*record the XmitTime and Write HIF time for each pkt*/ + wlanPktStausDebugUpdateProcessTime(prMsduInfo->u4DbgTxPktStatusIndex); + +} + +static VOID statsParsePktInfo(PUINT_8 pucPkt, UINT_8 status, UINT_8 eventType, P_MSDU_INFO_T prMsduInfo) +{ + /* get ethernet protocol */ + UINT_16 u2EtherType = (pucPkt[ETH_TYPE_LEN_OFFSET] << 8) | (pucPkt[ETH_TYPE_LEN_OFFSET + 1]); + PUINT_8 pucEthBody = &pucPkt[ETH_HLEN]; + + switch (u2EtherType) { + case ETH_P_ARP: + { + UINT_16 u2OpCode = (pucEthBody[6] << 8) | pucEthBody[7]; + + if (eventType == EVENT_TX) + prMsduInfo->fgIsBasicRate = TRUE; + + wlanPktDebugTraceInfoARP(status, eventType, u2OpCode); + wlanPktStatusDebugTraceInfoARP(status, eventType, u2OpCode, pucPkt, prMsduInfo); + + if ((su2TxDoneCfg & CFG_ARP) == 0) + break; + + switch (eventType) { + case EVENT_RX: + if (u2OpCode == ARP_PRO_REQ) + DBGLOG(RX, TRACE, " Arp Req From IP: %d.%d.%d.%d\n", + pucEthBody[14], pucEthBody[15], pucEthBody[16], pucEthBody[17]); + else if (u2OpCode == ARP_PRO_RSP) + DBGLOG(RX, TRACE, " Arp Rsp from IP: %d.%d.%d.%d\n", + pucEthBody[14], pucEthBody[15], pucEthBody[16], pucEthBody[17]); + break; + case EVENT_TX: + if (u2OpCode == ARP_PRO_REQ) { + DBGLOG(TX, TRACE, " Arp Req to IP: %d.%d.%d.%d\n", + pucEthBody[24], pucEthBody[25], pucEthBody[26], pucEthBody[27]); + if (srLastArpTxDoneReqTime && + kalGetTimeTick() - srLastArpTxDoneReqTime + < ARP_TX_DONE_REQ_INTERVAL) { + DBGLOGLIMITED(TX, INFO, + " Skip Tx done status for Arp Req to IP: %d.%d.%d.%d\n", + pucEthBody[24], pucEthBody[25], pucEthBody[26], pucEthBody[27]); + break; + } + srLastArpTxDoneReqTime = kalGetTimeTick(); + } else if (u2OpCode == ARP_PRO_RSP) + DBGLOG(TX, TRACE, " Arp Rsp to IP: %d.%d.%d.%d\n", + pucEthBody[24], pucEthBody[25], pucEthBody[26], pucEthBody[27]); + prMsduInfo->fgNeedTxDoneStatus = TRUE; + break; + case EVENT_TX_DONE: + if (u2OpCode == ARP_PRO_REQ) + DBGLOGLIMITED(TX, INFO, " Arp Req to IP: %d.%d.%d.%d\n", status, + pucEthBody[24], pucEthBody[25], pucEthBody[26], pucEthBody[27]); + else if (u2OpCode == ARP_PRO_RSP) + DBGLOG(TX, TRACE, " Arp Rsp to IP: %d.%d.%d.%d\n", status, + pucEthBody[24], pucEthBody[25], pucEthBody[26], pucEthBody[27]); + break; + } + break; + } + case ETH_P_IP: + { + UINT_8 ucIpProto = pucEthBody[9]; /* IP header without options */ + UINT_8 ucIpVersion = (pucEthBody[0] & IPVH_VERSION_MASK) >> IPVH_VERSION_OFFSET; + UINT_16 u2IpId = pucEthBody[4]<<8 | pucEthBody[5]; + + wlanPktDebugTraceInfoIP(status, eventType, ucIpProto, u2IpId); + wlanPktStatusDebugTraceInfoIP(status, eventType, ucIpProto, u2IpId, pucPkt, prMsduInfo); + + if (ucIpVersion != IPVERSION) + break; + + switch (ucIpProto) { + case IP_PRO_ICMP: + { + /* the number of ICMP packets is seldom so we print log here */ + UINT_8 ucIcmpType; + UINT_16 u2IcmpId, u2IcmpSeq; + PUINT_8 pucIcmp = &pucEthBody[20]; + + ucIcmpType = pucIcmp[0]; + /* don't log network unreachable packet */ + if (((su2TxDoneCfg & CFG_ICMP) == 0) || ucIcmpType == 3) + break; + u2IcmpId = *(UINT_16 *) &pucIcmp[4]; + u2IcmpSeq = *(UINT_16 *) &pucIcmp[6]; + switch (eventType) { + case EVENT_RX: + DBGLOG(RX, INFO, " ICMP: Type %d, Id BE 0x%04x, Seq BE 0x%04x\n", + ucIcmpType, u2IcmpId, u2IcmpSeq); + break; + case EVENT_TX: + DBGLOG(TX, TRACE, " ICMP: Type %d, Id 0x04%x, Seq BE 0x%04x\n", + ucIcmpType, u2IcmpId, u2IcmpSeq); + prMsduInfo->fgNeedTxDoneStatus = TRUE; + break; + case EVENT_TX_DONE: + DBGLOG(TX, INFO, " ICMP: Type %d, Id 0x%04x, Seq 0x%04x\n", + status, ucIcmpType, u2IcmpId, u2IcmpSeq); + break; + } + break; + } + case IP_PRO_UDP: + { + /* the number of DHCP packets is seldom so we print log here */ + PUINT_8 pucUdp = &pucEthBody[20]; + PUINT_8 pucUdpPayload = &pucUdp[8]; + UINT_16 u2UdpDstPort; + UINT_16 u2UdpSrcPort; + + u2UdpDstPort = (pucUdp[2] << 8) | pucUdp[3]; + u2UdpSrcPort = (pucUdp[0] << 8) | pucUdp[1]; + /* dhcp */ + if ((u2UdpDstPort == UDP_PORT_DHCPS) || (u2UdpDstPort == UDP_PORT_DHCPC)) { + UINT_32 u4TransID = pucUdpPayload[4]<<24 | pucUdpPayload[5]<<16 | + pucUdpPayload[6]<<8 | pucUdpPayload[7]; + + switch (eventType) { + case EVENT_RX: + DBGLOG(RX, INFO, " DHCP: IPID 0x%02x, MsgType 0x%x, TransID 0x%08x\n", + u2IpId, pucUdpPayload[0], u4TransID); + break; + case EVENT_TX: + DBGLOG(TX, INFO, " DHCP: IPID 0x%02x, MsgType 0x%x, TransID 0x%08x\n", + u2IpId, pucUdpPayload[0], u4TransID); + prMsduInfo->fgNeedTxDoneStatus = TRUE; + prMsduInfo->fgIsBasicRate = TRUE; + break; + case EVENT_TX_DONE: + DBGLOG(TX, INFO, + " DHCP: IPID 0x%02x, MsgType 0x%x, TransID 0x%08x\n", + status, u2IpId, pucUdpPayload[0], u4TransID); + break; + } + } else if (u2UdpDstPort == UDP_PORT_DNS) { /* tx dns */ + UINT_16 u2TransId = (pucUdpPayload[0] << 8) | pucUdpPayload[1]; + + if (eventType == EVENT_TX) + prMsduInfo->fgIsBasicRate = TRUE; + + if ((su2TxDoneCfg & CFG_DNS) == 0) + break; + if (eventType == EVENT_TX) { + DBGLOG(TX, INFO, " DNS: IPID 0x%02x, TransID 0x%04x\n", u2IpId, u2TransId); + prMsduInfo->fgNeedTxDoneStatus = TRUE; + } else if (eventType == EVENT_TX_DONE) + DBGLOG(TX, INFO, " DNS: IPID 0x%02x, TransID 0x%04x\n", + status, u2IpId, u2TransId); + } else if (u2UdpSrcPort == UDP_PORT_DNS && eventType == EVENT_RX) { /* rx dns */ + UINT_16 u2TransId = (pucUdpPayload[0] << 8) | pucUdpPayload[1]; + + if ((su2TxDoneCfg & CFG_DNS) == 0) + break; + DBGLOG(RX, INFO, " DNS: IPID 0x%02x, TransID 0x%04x\n", u2IpId, u2TransId); + } else if ((su2TxDoneCfg & CFG_UDP) != 0) { + switch (eventType) { + case EVENT_RX: + DBGLOG(RX, INFO, " UDP: IPID 0x%04x\n", u2IpId); + break; + case EVENT_TX: + DBGLOG(TX, INFO, " UDP: IPID 0x%04x\n", u2IpId); + prMsduInfo->fgNeedTxDoneStatus = TRUE; + break; + case EVENT_TX_DONE: + DBGLOG(TX, INFO, " UDP: IPID 0x%04x\n", status, u2IpId); + break; + } + } + break; + } + case IP_PRO_TCP: + if ((su2TxDoneCfg & CFG_TCP) == 0) + break; + + switch (eventType) { + case EVENT_RX: + DBGLOG(RX, INFO, " TCP: IPID 0x%04x\n", u2IpId); + break; + case EVENT_TX: + DBGLOG(TX, INFO, " TCP: IPID 0x%04x\n", u2IpId); + prMsduInfo->fgNeedTxDoneStatus = TRUE; + break; + case EVENT_TX_DONE: + DBGLOG(TX, INFO, " TCP: IPID 0x%04x\n", status, u2IpId); + break; + } + break; + } + break; + } + case ETH_P_PRE_1X: + DBGLOG(RX, INFO, "pre-1x\n"); + case ETH_P_1X: + { + PUINT_8 pucEapol = pucEthBody; + UINT_8 ucEapolType = pucEapol[1]; + + switch (ucEapolType) { + case 0: /* eap packet */ + switch (eventType) { + case EVENT_RX: + DBGLOG(RX, INFO, " EAP Packet: code %d, id %d, type %d\n", + pucEapol[4], pucEapol[5], pucEapol[7]); + break; + case EVENT_TX: + DBGLOG(TX, INFO, " EAP Packet: code %d, id %d, type %d\n", + pucEapol[4], pucEapol[5], pucEapol[7]); + break; + case EVENT_TX_DONE: + DBGLOG(TX, INFO, " EAP Packet: code %d, id %d, type %d\n", + status, pucEapol[4], pucEapol[5], pucEapol[7]); + break; + } + break; + case 1: /* eapol start */ + switch (eventType) { + case EVENT_RX: + DBGLOG(RX, INFO, " EAPOL: start\n"); + break; + case EVENT_TX: + DBGLOG(TX, INFO, " EAPOL: start\n"); + break; + case EVENT_TX_DONE: + DBGLOG(TX, INFO, " EAPOL: start\n", status); + break; + } + break; + case 3: /* key */ + { + UINT_16 u2KeyInfo = pucEapol[5]<<8 | pucEapol[6]; + + switch (eventType) { + case EVENT_RX: + DBGLOG(RX, INFO, + " EAPOL: key, KeyInfo 0x%04x, Nonce %02x%02x%02x%02x%02x%02x%02x%02x...\n", + u2KeyInfo, pucEapol[17], pucEapol[18], pucEapol[19], pucEapol[20], + pucEapol[21], pucEapol[22], pucEapol[23], pucEapol[24]); + break; + case EVENT_TX: + DBGLOG(TX, INFO, + " EAPOL: key, KeyInfo 0x%04x, Nonce %02x%02x%02x%02x%02x%02x%02x%02x...\n", + u2KeyInfo, + pucEapol[17], pucEapol[18], pucEapol[19], pucEapol[20], + pucEapol[21], pucEapol[22], pucEapol[23], pucEapol[24]); + break; + case EVENT_TX_DONE: + if (status != 0) { + DBGLOG(TX, INFO, + " EAPOL: key, KeyInfo 0x%04x, Nonce %02x%02x%02x%02x%02x%02x%02x%02x...\n", + status, u2KeyInfo, pucEapol[17], pucEapol[18], pucEapol[19], + pucEapol[20], pucEapol[21], pucEapol[22], pucEapol[23], pucEapol[24]); + } + break; + } + + break; + } + } + break; + } + case ETH_WPI_1X: + { + UINT_8 ucSubType = pucEthBody[3]; /* sub type filed*/ + UINT_16 u2Length = *(PUINT_16)&pucEthBody[6]; + UINT_16 u2Seq = *(PUINT_16)&pucEthBody[8]; + + switch (eventType) { + case EVENT_RX: + DBGLOG(RX, INFO, " WAPI: subType %d, Len %d, Seq %d\n", + ucSubType, u2Length, u2Seq); + break; + case EVENT_TX: + DBGLOG(TX, INFO, " WAPI: subType %d, Len %d, Seq %d\n", + ucSubType, u2Length, u2Seq); + break; + case EVENT_TX_DONE: + DBGLOG(TX, INFO, " WAPI: subType %d, Len %d, Seq %d\n", + status, ucSubType, u2Length, u2Seq); + break; + } + break; + } + } +} +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to display rx packet information. +* +* \param[in] pPkt Pointer to the packet +* \param[out] None +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID StatsRxPktInfoDisplay(UINT_8 *pPkt) +{ + statsParsePktInfo(pPkt, 0, EVENT_RX, NULL); +#if 0 /* carefully! too many ARP */ + if (pucIpHdr[0] == 0x00) { /* ARP */ + UINT_8 *pucDstIp = (UINT_8 *) pucIpHdr; + + if (pucDstIp[7] == ARP_PRO_REQ) { + DBGLOG(RX, TRACE, " OS rx a arp req from %d.%d.%d.%d\n", + pucDstIp[14], pucDstIp[15], pucDstIp[16], pucDstIp[17]); + } else if (pucDstIp[7] == ARP_PRO_RSP) { + DBGLOG(RX, TRACE, " OS rx a arp rsp from %d.%d.%d.%d\n", + pucDstIp[24], pucDstIp[25], pucDstIp[26], pucDstIp[27]); + } + } +#endif + +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to display tx packet information. +* +* \param[in] pPkt Pointer to the packet +* \param[out] None +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID StatsTxPktCallBack(UINT_8 *pPkt, P_MSDU_INFO_T prMsduInfo) +{ + UINT_16 u2EtherTypeLen; + + u2EtherTypeLen = (pPkt[ETH_TYPE_LEN_OFFSET] << 8) | (pPkt[ETH_TYPE_LEN_OFFSET + 1]); + statsParsePktInfo(pPkt, 0, EVENT_TX, prMsduInfo); + +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to handle display tx packet tx done information. +* +* \param[in] pPkt Pointer to the packet +* \param[out] None +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID StatsTxPktDoneInfoDisplay(ADAPTER_T *prAdapter, UINT_8 *pucEvtBuf) +{ + EVENT_TX_DONE_STATUS_T *prTxDone; + + prTxDone = (EVENT_TX_DONE_STATUS_T *) pucEvtBuf; + /* + * Why 65 Bytes: + * 8B + wlanheader(40B) + hif_tx_header(16B) + 6B + 6B(LLC) - 12B + */ + statsParsePktInfo(&prTxDone->aucPktBuf[64], prTxDone->ucStatus, EVENT_TX_DONE, NULL); +} + +VOID StatsSetCfgTxDone(UINT_16 u2Cfg, BOOLEAN fgSet) +{ + if (fgSet) + su2TxDoneCfg |= u2Cfg; + else + su2TxDoneCfg &= ~u2Cfg; +} + +UINT_16 StatsGetCfgTxDone(VOID) +{ + return su2TxDoneCfg; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/swcr.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/swcr.c new file mode 100644 index 0000000000000..14d73700fdeca --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/swcr.c @@ -0,0 +1,1079 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +#if CFG_SUPPORT_SWCR + +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wformat" +#endif +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +#if 0 +SWCR_MOD_MAP_ENTRY_T g_arSwCrAllMaps[] = { + {SWCR_MAP_NUM(g_arRlmArSwCrMap), g_arRlmArSwCrMap}, /* 0x00nn */ + {0, NULL} +}; +#endif + +UINT_32 g_au4SwCr[SWCR_CR_NUM]; /*: 0: command other: data */ + +/* JB mDNS Filter*/ +UINT_32 g_u4mDNSRXFilter; /* [31] 0: stop 1: start, [3] IPv6 [2] IPv4 */ + +static TIMER_T g_rSwcrDebugTimer; +static BOOLEAN g_fgSwcrDebugTimer = FALSE; +static UINT_32 g_u4SwcrDebugCheckTimeout; +static ENUM_SWCR_DBG_TYPE_T g_ucSwcrDebugCheckType; +static UINT_32 g_u4SwcrDebugFrameDumpType; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#define TEST_PS 1 + +static const PFN_CMD_RW_T g_arSwCtrlCmd[] = { + swCtrlCmdCategory0, + swCtrlCmdCategory1 +#if TEST_PS + , testPsCmdCategory0, testPsCmdCategory1 +#endif +#if CFG_SUPPORT_802_11V +#if (CFG_SUPPORT_802_11V_TIMING_MEASUREMENT == 1) && (WNM_UNIT_TEST == 1) + , testWNMCmdCategory0 +#endif +#endif +}; + +const PFN_SWCR_RW_T g_arSwCrModHandle[] = { + swCtrlSwCr, + NULL +}; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +enum { + SWCTRL_MAGIC, + SWCTRL_DEBUG, + SWCTRL_WIFI_VAR, + SWCTRL_ENABLE_INT, + SWCTRL_DISABLE_INT, + SWCTRL_TXM_INFO, + SWCTRL_RXM_INFO, + SWCTRL_DUMP_BSS, + SWCTRL_QM_INFO, + SWCTRL_DUMP_ALL_QUEUE_LEN, + SWCTRL_DUMP_MEM, + SWCTRL_TX_CTRL_INFO, + SWCTRL_DUMP_QUEUE, + SWCTRL_DUMP_QM_DBG_CNT, + SWCTRL_QM_DBG_CNT, + SWCTRL_RX_PKTS_DUMP, + SWCTRL_RX_MDNS_FILTER, + SWCTRL_CATA0_INDEX_NUM +}; + +enum { + SWCTRL_STA_INFO, + SWCTRL_DUMP_STA, + SWCTRL_STA_QUE_INFO, + SWCTRL_CATA1_INDEX_NUM +}; + +/* JB mDNS Filter*/ +#define RX_MDNS_FILTER_START (1<<31) +#define RX_MDNS_FILTER_IPV4 (1<<2) +#define RX_MDNS_FILTER_IPV6 (1<<3) +typedef enum _ENUM_SWCR_RX_MDNS_FILTER_CMD_T { + SWCR_RX_MDNS_FILTER_CMD_STOP = 0, + SWCR_RX_MDNS_FILTER_CMD_START, + SWCR_RX_MDNS_FILTER_CMD_ADD, + SWCR_RX_MDNS_FILTER_CMD_REMOVE, + SWCR_RX_MDNS_FILTER_NUM +} ENUM_SWCR_RX_MDNS_FILTER_CMD_T; + +#if TEST_PS +enum { + TEST_PS_MAGIC, + TEST_PS_SETUP_BSS, + TEST_PS_ENABLE_BEACON, + TEST_PS_TRIGGER_BMC, + TEST_PS_SEND_NULL, + TEST_PS_BUFFER_BMC, + TEST_PS_UPDATE_BEACON, + TEST_PS_CATA0_INDEX_NUM +}; + +enum { + TEST_PS_STA_PS, + TEST_PS_STA_ENTER_PS, + TEST_PS_STA_EXIT_PS, + TEST_PS_STA_TRIGGER_PSPOLL, + TEST_PS_STA_TRIGGER_FRAME, + TEST_PS_CATA1_INDEX_NUM +}; +#endif + +#if CFG_SUPPORT_802_11V +#if WNM_UNIT_TEST +enum { + TEST_WNM_TIMING_MEAS, + TEST_WNM_CATA0_INDEX_NUM +}; +#endif +#endif + +#define _SWCTRL_MAGIC 0x66201642 + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +void dumpQueue(P_ADAPTER_T prAdapter) +{ + + P_TX_CTRL_T prTxCtrl; + P_QUE_MGT_T prQM; + P_GLUE_INFO_T prGlueInfo; + UINT_32 i; + UINT_32 j; + + DEBUGFUNC("dumpQueue"); + + prTxCtrl = &prAdapter->rTxCtrl; + prQM = &prAdapter->rQM; + prGlueInfo = prAdapter->prGlueInfo; + + for (i = TC0_INDEX; i <= TC5_INDEX; i++) { + DBGLOG(SW4, INFO, "TC %u\n", i); + DBGLOG(SW4, INFO, "Max %u Free %u\n", + prTxCtrl->rTc.aucMaxNumOfBuffer[i], prTxCtrl->rTc.aucFreeBufferCount[i]); + + DBGLOG(SW4, INFO, "Average %u minReserved %u CurrentTcResource %u GuaranteedTcResource %u\n", + QM_GET_TX_QUEUE_LEN(prAdapter, i), + prQM->au4MinReservedTcResource[i], + prQM->au4CurrentTcResource[i], prQM->au4GuaranteedTcResource[i]); + + } + + for (i = 0; i < NUM_OF_PER_STA_TX_QUEUES; i++) { + DBGLOG(SW4, INFO, + "TC %u HeadStaIdx %u ForwardCount %u\n", i, prQM->au4HeadStaRecIndex[i], + prQM->au4ForwardCount[i]); + } + + DBGLOG(SW4, INFO, "BMC or unknown TxQueue Len %u\n", prQM->arTxQueue[0].u4NumElem); + DBGLOG(SW4, INFO, "Pending %d\n", prGlueInfo->i4TxPendingFrameNum); + DBGLOG(SW4, INFO, "Pending Security %d\n", prGlueInfo->i4TxPendingSecurityFrameNum); +#if defined(LINUX) + for (i = 0; i < 4; i++) { + for (j = 0; j < CFG_MAX_TXQ_NUM; j++) { + DBGLOG(SW4, INFO, + "Pending Q[%u][%u] %d\n", i, j, prGlueInfo->ai4TxPendingFrameNumPerQueue[i][j]); + } + } +#endif + + DBGLOG(SW4, INFO, " rFreeSwRfbList %u\n", prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem); + DBGLOG(SW4, INFO, " rReceivedRfbList %u\n", prAdapter->rRxCtrl.rReceivedRfbList.u4NumElem); + DBGLOG(SW4, INFO, " rIndicatedRfbList %u\n", prAdapter->rRxCtrl.rIndicatedRfbList.u4NumElem); + DBGLOG(SW4, INFO, " ucNumIndPacket %u\n", prAdapter->rRxCtrl.ucNumIndPacket); + DBGLOG(SW4, INFO, " ucNumRetainedPacket %u\n", prAdapter->rRxCtrl.ucNumRetainedPacket); +#if CFG_SUPPORT_MULTITHREAD + DBGLOG(SW4, INFO, " ucNumRxDataPacket %9u\n", prAdapter->rRxCtrl.rRxDataRfbList.u4NumElem); +#endif + +} + +void dumpSTA(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec) +{ + UINT_8 ucWTEntry; + UINT_32 i; + P_BSS_INFO_T prBssInfo; + + DEBUGFUNC("dumpSTA"); + + ASSERT(prStaRec); + ucWTEntry = prStaRec->ucWTEntry; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; + ASSERT(prBssInfo); + + DBGLOG(SW4, INFO, "Mac address: %pM Rcpi %u\n", prStaRec->aucMacAddr, prStaRec->ucRCPI); + + DBGLOG(SW4, INFO, "Idx %u Wtbl %u Used %u State %u Bss Phy 0x%x Sta DesiredPhy 0x%x\n", + prStaRec->ucIndex, ucWTEntry, + prStaRec->fgIsInUse, prStaRec->ucStaState, + prBssInfo->ucPhyTypeSet, prStaRec->ucDesiredPhyTypeSet); + + DBGLOG(SW4, INFO, "Sta Operation 0x%x DesiredNontHtRateSet 0x%x Mcs 0x%x u2HtCapInfo 0x%x\n", + prStaRec->u2OperationalRateSet, prStaRec->u2DesiredNonHTRateSet, prStaRec->ucMcsSet, + prStaRec->u2HtCapInfo); + + for (i = 0; i < NUM_OF_PER_STA_TX_QUEUES; i++) + DBGLOG(SW4, INFO, "TC %u Queue Len %u\n", i, prStaRec->arTxQueue[i].u4NumElem); + + DBGLOG(SW4, INFO, "BmpDeliveryAC %x\n", prStaRec->ucBmpDeliveryAC); + DBGLOG(SW4, INFO, "BmpTriggerAC %x\n", prStaRec->ucBmpTriggerAC); + DBGLOG(SW4, INFO, "UapsdSpSupproted %u\n", prStaRec->fgIsUapsdSupported); + DBGLOG(SW4, INFO, "IsQoS %u\n", prStaRec->fgIsQoS); + DBGLOG(SW4, INFO, "AssocId %u\n", prStaRec->u2AssocId); + + DBGLOG(SW4, INFO, "fgIsInPS %u\n", prStaRec->fgIsInPS); + DBGLOG(SW4, INFO, "ucFreeQuota %u\n", prStaRec->ucFreeQuota); + DBGLOG(SW4, INFO, "ucFreeQuotaForDelivery %u\n", prStaRec->ucFreeQuotaForDelivery); + DBGLOG(SW4, INFO, "ucFreeQuotaForNonDelivery %u\n", prStaRec->ucFreeQuotaForNonDelivery); + +#if 0 + DBGLOG(SW4, INFO, "IsQmmSup %u\n", prStaRec->fgIsWmmSupported); + DBGLOG(SW4, INFO, "IsUapsdSup %u\n", prStaRec->fgIsUapsdSupported); + DBGLOG(SW4, INFO, "AvailabaleDeliverPkts %u\n", prStaRec->ucAvailableDeliverPkts); + DBGLOG(SW4, INFO, "BmpDeliverPktsAC %u\n", prStaRec->u4BmpDeliverPktsAC); + DBGLOG(SW4, INFO, "BmpBufferAC %u\n", prStaRec->u4BmpBufferAC); + DBGLOG(SW4, INFO, "BmpNonDeliverPktsAC %u\n", prStaRec->u4BmpNonDeliverPktsAC); +#endif + + for (i = 0; i < CFG_RX_MAX_BA_TID_NUM; i++) { + if (prStaRec->aprRxReorderParamRefTbl[i]) { + DBGLOG(SW4, INFO, + "RxReorder fgIsValid: %u\n", prStaRec->aprRxReorderParamRefTbl[i]->fgIsValid); + DBGLOG(SW4, INFO, "RxReorder Tid: %u\n", prStaRec->aprRxReorderParamRefTbl[i]->ucTid); + DBGLOG(SW4, INFO, + "RxReorder rReOrderQue Len: %u\n", + prStaRec->aprRxReorderParamRefTbl[i]->rReOrderQue.u4NumElem); + DBGLOG(SW4, INFO, + "RxReorder WinStart: %u\n", prStaRec->aprRxReorderParamRefTbl[i]->u2WinStart); + DBGLOG(SW4, INFO, "RxReorder WinEnd: %u\n", prStaRec->aprRxReorderParamRefTbl[i]->u2WinEnd); + DBGLOG(SW4, INFO, "RxReorder WinSize: %u\n", prStaRec->aprRxReorderParamRefTbl[i]->u2WinSize); + } + } + +} + +VOID dumpBss(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) +{ + + DBGLOG(SW4, INFO, "SSID %s\n", HIDE(prBssInfo->aucSSID)); + DBGLOG(SW4, INFO, "OWN %pM\n", prBssInfo->aucOwnMacAddr); + DBGLOG(SW4, INFO, "BSSID %pM\n", prBssInfo->aucBSSID); + DBGLOG(SW4, INFO, "ucNetTypeIndex %u\n", prBssInfo->ucNetTypeIndex); + DBGLOG(SW4, INFO, "eConnectionState %u\n", prBssInfo->eConnectionState); + DBGLOG(SW4, INFO, "eCurrentOPMode %u\n", prBssInfo->eCurrentOPMode); + DBGLOG(SW4, INFO, "fgIsQBSS %u\n", prBssInfo->fgIsQBSS); + DBGLOG(SW4, INFO, "fgIsShortPreambleAllowed %u\n", prBssInfo->fgIsShortPreambleAllowed); + DBGLOG(SW4, INFO, "fgUseShortPreamble %u\n", prBssInfo->fgUseShortPreamble); + DBGLOG(SW4, INFO, "fgUseShortSlotTime %u\n", prBssInfo->fgUseShortSlotTime); + DBGLOG(SW4, INFO, "ucNonHTBasicPhyType %x\n", prBssInfo->ucNonHTBasicPhyType); + DBGLOG(SW4, INFO, "u2OperationalRateSet %x\n", prBssInfo->u2OperationalRateSet); + DBGLOG(SW4, INFO, "u2BSSBasicRateSet %x\n", prBssInfo->u2BSSBasicRateSet); + DBGLOG(SW4, INFO, "ucPhyTypeSet %x\n", prBssInfo->ucPhyTypeSet); + DBGLOG(SW4, INFO, "rStaRecOfClientList %d\n", prBssInfo->rStaRecOfClientList.u4NumElem); + DBGLOG(SW4, INFO, "u2CapInfo %x\n", prBssInfo->u2CapInfo); + DBGLOG(SW4, INFO, "u2ATIMWindow %x\n", prBssInfo->u2ATIMWindow); + DBGLOG(SW4, INFO, "u2AssocId %x\n", prBssInfo->u2AssocId); + DBGLOG(SW4, INFO, "ucDTIMPeriod %x\n", prBssInfo->ucDTIMPeriod); + DBGLOG(SW4, INFO, "ucDTIMCount %x\n", prBssInfo->ucDTIMCount); + DBGLOG(SW4, INFO, "fgIsNetAbsent %x\n", prBssInfo->fgIsNetAbsent); + DBGLOG(SW4, INFO, "eBand %d\n", prBssInfo->eBand); + DBGLOG(SW4, INFO, "ucPrimaryChannel %d\n", prBssInfo->ucPrimaryChannel); + DBGLOG(SW4, INFO, "ucHtOpInfo1 %d\n", prBssInfo->ucHtOpInfo1); + DBGLOG(SW4, INFO, "ucHtOpInfo2 %d\n", prBssInfo->u2HtOpInfo2); + DBGLOG(SW4, INFO, "ucHtOpInfo3 %d\n", prBssInfo->u2HtOpInfo3); + DBGLOG(SW4, INFO, "fgErpProtectMode %d\n", prBssInfo->fgErpProtectMode); + DBGLOG(SW4, INFO, "eHtProtectMode %d\n", prBssInfo->eHtProtectMode); + DBGLOG(SW4, INFO, "eGfOperationMode %d\n", prBssInfo->eGfOperationMode); + DBGLOG(SW4, INFO, "eRifsOperationMode %d\n", prBssInfo->eRifsOperationMode); + DBGLOG(SW4, INFO, "fgObssErpProtectMode %d\n", prBssInfo->fgObssErpProtectMode); + DBGLOG(SW4, INFO, "eObssHtProtectMode %d\n", prBssInfo->eObssHtProtectMode); + DBGLOG(SW4, INFO, "eObssGfProtectMode %d\n", prBssInfo->eObssGfOperationMode); + DBGLOG(SW4, INFO, "fgObssRifsOperationMode %d\n", prBssInfo->fgObssRifsOperationMode); + DBGLOG(SW4, INFO, "fgAssoc40mBwAllowed %d\n", prBssInfo->fgAssoc40mBwAllowed); + DBGLOG(SW4, INFO, "fg40mBwAllowed %d\n", prBssInfo->fg40mBwAllowed); + DBGLOG(SW4, INFO, "eBssSCO %d\n", prBssInfo->eBssSCO); + +} + +UINT_32 swCrGetDNSRxFilter(VOID) +{ + UINT_32 u2RetRxFilter = 0; + + if (g_u4mDNSRXFilter & RX_MDNS_FILTER_IPV4) + u2RetRxFilter |= PARAM_PACKET_FILTER_ALL_MULTICAST; + else + u2RetRxFilter |= PARAM_PACKET_FILTER_MULTICAST; + + DBGLOG(SW4, TRACE, "[MC debug]swCrGetDNSRxFilter %x\n", u2RetRxFilter); + + return u2RetRxFilter; +} + + +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: + 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 & ( + ~PARAM_PACKET_FILTER_MULTICAST | ~PARAM_PACKET_FILTER_ALL_MULTICAST); + fgUpdate = TRUE; + } else if (ucOpt0 == SWCR_RX_MDNS_FILTER_CMD_START) { + g_u4mDNSRXFilter |= (RX_MDNS_FILTER_START); + + u4rxfilter = prAdapter->u4OsPacketFilter | swCrGetDNSRxFilter(); + 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 = wlanoidSetPacketFilter(prAdapter, u4rxfilter, FALSE, NULL, 0); + } + break; + default: + break; + } + } else { + switch (ucIndex) { + case SWCTRL_DEBUG: + break; + case SWCTRL_MAGIC: + g_au4SwCr[1] = _SWCTRL_MAGIC; + /* DBGLOG(SW4, INFO, "BUILD TIME: %s %s\n", __DATE__, __TIME__); */ + break; + case SWCTRL_QM_INFO: + { + P_QUE_MGT_T prQM = &prAdapter->rQM; + + switch (ucOpt0) { + case 0: + g_au4SwCr[1] = (QM_GET_TX_QUEUE_LEN(prAdapter, ucOpt1)); + g_au4SwCr[2] = prQM->au4MinReservedTcResource[ucOpt1]; + g_au4SwCr[3] = prQM->au4CurrentTcResource[ucOpt1]; + g_au4SwCr[4] = prQM->au4GuaranteedTcResource[ucOpt1]; + break; + + case 1: + g_au4SwCr[1] = prQM->au4ForwardCount[ucOpt1]; + g_au4SwCr[2] = prQM->au4HeadStaRecIndex[ucOpt1]; + break; + + case 2: + g_au4SwCr[1] = prQM->arTxQueue[ucOpt1].u4NumElem; /* only one */ + + break; + } + + } + break; + case SWCTRL_TX_CTRL_INFO: + { + P_TX_CTRL_T prTxCtrl; + + prTxCtrl = &prAdapter->rTxCtrl; + switch (ucOpt0) { + case 0: + g_au4SwCr[1] = prAdapter->rTxCtrl.rTc.aucFreeBufferCount[ucOpt1]; + g_au4SwCr[2] = prAdapter->rTxCtrl.rTc.aucMaxNumOfBuffer[ucOpt1]; + break; + } + + } + break; + case SWCTRL_DUMP_QUEUE: + dumpQueue(prAdapter); + + break; +#if QM_DEBUG_COUNTER + case SWCTRL_DUMP_QM_DBG_CNT: + for (i = 0; i < QM_DBG_CNT_NUM; i++) + DBGLOG(SW4, INFO, "QM:DBG %u %u\n", i, prAdapter->rQM.au4QmDebugCounters[i]); + break; + + case SWCTRL_QM_DBG_CNT: + g_au4SwCr[1] = prAdapter->rQM.au4QmDebugCounters[ucOpt0]; + break; +#endif + case SWCTRL_DUMP_BSS: + { + dumpBss(prAdapter, &(prAdapter->rWifiVar.arBssInfo[ucOpt0])); + } + break; + + default: + break; + } + + } +} + +VOID swCtrlCmdCategory1(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1) +{ + UINT_8 ucIndex, ucRead; + UINT_8 ucWTEntry; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("swCtrlCmdCategory1"); + + SWCR_GET_RW_INDEX(ucAction, ucRead, ucIndex); + + if (ucOpt0 >= CFG_STA_REC_NUM) + return; + + /* prStaRec = cnmGetStaRecByIndex (prAdapter, ucOpt0); */ + prStaRec = &prAdapter->arStaRec[ucOpt0]; + ucWTEntry = prStaRec->ucWTEntry; + if (ucRead == SWCR_WRITE) { + /* Do nothing */ + } else { + /* Read */ + switch (ucIndex) { + case SWCTRL_STA_QUE_INFO: + { + g_au4SwCr[1] = prStaRec->arTxQueue[ucOpt1].u4NumElem; + } + break; + case SWCTRL_STA_INFO: + switch (ucOpt1) { + case 0: + g_au4SwCr[1] = prStaRec->fgIsInPS; + break; + } + + break; + + case SWCTRL_DUMP_STA: + { + dumpSTA(prAdapter, prStaRec); + } + break; + + default: + + break; + } + } + +} + +#if TEST_PS + +VOID +testPsSendQoSNullFrame(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN UINT_8 ucUP, + IN UINT_8 ucNetTypeIndex, + IN BOOLEAN fgBMC, + IN BOOLEAN fgIsBurstEnd, IN BOOLEAN ucPacketType, IN BOOLEAN ucPsSessionID, IN BOOLEAN fgSetEOSP) +{ + P_MSDU_INFO_T prMsduInfo; + UINT_16 u2EstimatedFrameLen; + P_WLAN_MAC_HEADER_QOS_T prQoSNullFrame; + + DEBUGFUNC("testPsSendQoSNullFrame"); + DBGLOG(SW4, LOUD, "\n"); + + /* 4 <1> Allocate a PKT_INFO_T for Null Frame */ + /* Init with MGMT Header Length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + WLAN_MAC_HEADER_QOS_LEN; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SW4, WARN, "No PKT_INFO_T for sending Null Frame.\n"); + return; + } + /* 4 <2> Compose Null frame in MSDU_INfO_T. */ + bssComposeQoSNullFrame(prAdapter, + (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + prStaRec, ucUP, fgSetEOSP); + + prMsduInfo->eSrc = TX_PACKET_MGMT; + /* prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_DATA; */ + prMsduInfo->ucPacketType = ucPacketType; + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucNetworkType = ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_HEADER_QOS_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_HEADER_QOS_LEN; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->fgIsBasicRate = TRUE; + prMsduInfo->fgIsBurstEnd = fgIsBurstEnd; + prMsduInfo->ucUserPriority = ucUP; + prMsduInfo->ucPsSessionID = ucPsSessionID /* 0~7 Test 7 means NOACK */; + + prQoSNullFrame = (P_WLAN_MAC_HEADER_QOS_T) (((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD)); + + if (fgBMC) + prQoSNullFrame->aucAddr1[0] = 0xfd; + else + prQoSNullFrame->aucAddr1[5] = 0xdd; + + /* 4 <4> Inform TXM to send this Null frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + +} + +VOID testPsSetupBss(IN P_ADAPTER_T prAdapter, IN UINT_8 ucNetworkTypeIndex) +{ + P_BSS_INFO_T prBssInfo; + UINT_8 _aucZeroMacAddr[] = NULL_MAC_ADDR; + + DEBUGFUNC("testPsSetupBss()"); + DBGLOG(SW4, INFO, "index %d\n", ucNetworkTypeIndex); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[ucNetworkTypeIndex]); + + /* 4 <1.2> Initiate PWR STATE */ + /* SET_NET_PWR_STATE_IDLE(prAdapter, ucNetworkTypeIndex); */ + + /* 4 <2> Initiate BSS_INFO_T - common part */ + BSS_INFO_INIT(prAdapter, ucNetworkTypeIndex); + + prBssInfo->eConnectionState = PARAM_MEDIA_STATE_DISCONNECTED; + prBssInfo->eConnectionStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; + prBssInfo->eCurrentOPMode = OP_MODE_ACCESS_POINT; + prBssInfo->fgIsNetActive = TRUE; + prBssInfo->ucNetTypeIndex = (ucNetworkTypeIndex); + prBssInfo->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_RESERVED; + + prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11BG; /* Depend on eBand */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->u2BSSBasicRateSet = RATE_SET_ERP; + prBssInfo->u2OperationalRateSet = RATE_SET_OFDM; + prBssInfo->fgErpProtectMode = FALSE; + prBssInfo->fgIsQBSS = TRUE; + + /* 4 <1.5> Setup MIB for current BSS */ + prBssInfo->u2BeaconInterval = 100; + prBssInfo->ucDTIMPeriod = DOT11_DTIM_PERIOD_DEFAULT; + prBssInfo->u2ATIMWindow = 0; + + prBssInfo->ucBeaconTimeoutCount = 0; + + bssInitForAP(prAdapter, prBssInfo, TRUE); + + COPY_MAC_ADDR(prBssInfo->aucBSSID, _aucZeroMacAddr); + LINK_INITIALIZE(&prBssInfo->rStaRecOfClientList); + prBssInfo->fgIsBeaconActivated = TRUE; + prBssInfo->ucHwDefaultFixedRateCode = RATE_CCK_1M_LONG; + + COPY_MAC_ADDR(prBssInfo->aucOwnMacAddr, prAdapter->rWifiVar.aucMacAddress); + + /* 4 <3> Initiate BSS_INFO_T - private part */ + /* TODO */ + prBssInfo->eBand = BAND_2G4; + prBssInfo->ucPrimaryChannel = 1; + prBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; + + /* prBssInfo->fgErpProtectMode = eErpProectMode; */ + /* prBssInfo->eHtProtectMode = eHtProtectMode; */ + /* prBssInfo->eGfOperationMode = eGfOperationMode; */ + + /* 4 <4> Allocate MSDU_INFO_T for Beacon */ + prBssInfo->prBeacon = cnmMgtPktAlloc(prAdapter, OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem[0]) + MAX_IE_LENGTH); + + if (prBssInfo->prBeacon) { + prBssInfo->prBeacon->eSrc = TX_PACKET_MGMT; + prBssInfo->prBeacon->ucNetworkType = ucNetworkTypeIndex; + } else { + DBGLOG(SW4, INFO, "prBeacon allocation fail\n"); + } + +#if 0 + prBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC = PM_UAPSD_ALL; + prBssInfo->rPmProfSetupInfo.ucBmpTriggerAC = PM_UAPSD_ALL; + prBssInfo->rPmProfSetupInfo.ucUapsdSp = WMM_MAX_SP_LENGTH_2; +#else + prBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC = (UINT_8) prAdapter->u4UapsdAcBmp; + prBssInfo->rPmProfSetupInfo.ucBmpTriggerAC = (UINT_8) prAdapter->u4UapsdAcBmp; + prBssInfo->rPmProfSetupInfo.ucUapsdSp = (UINT_8) prAdapter->u4MaxSpLen; +#endif + +#if 0 + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + + prBssInfo->arACQueParms[eAci].fgIsACMSet = FALSE; + prBssInfo->arACQueParms[eAci].u2Aifsn = (UINT_16) eAci; + prBssInfo->arACQueParms[eAci].u2CWmin = 7; + prBssInfo->arACQueParms[eAci].u2CWmax = 31; + prBssInfo->arACQueParms[eAci].u2TxopLimit = eAci + 1; + DBGLOG(SW4, INFO, "MQM: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", + eAci, prBssInfo->arACQueParms[eAci].fgIsACMSet, + prBssInfo->arACQueParms[eAci].u2Aifsn, + prBssInfo->arACQueParms[eAci].u2CWmin, + prBssInfo->arACQueParms[eAci].u2CWmax, prBssInfo->arACQueParms[eAci].u2TxopLimit)); + + } +#endif + + DBGLOG(SW4, INFO, "[2] ucBmpDeliveryAC:0x%x, ucBmpTriggerAC:0x%x, ucUapsdSp:0x%x", + prBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC, + prBssInfo->rPmProfSetupInfo.ucBmpTriggerAC, prBssInfo->rPmProfSetupInfo.ucUapsdSp); + +} + +VOID testPsCmdCategory0(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1) +{ + UINT_8 ucIndex, ucRead; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("testPsCmdCategory0"); + SWCR_GET_RW_INDEX(ucAction, ucRead, ucIndex); + + DBGLOG(SW4, LOUD, "Read %u Index %u\n", ucRead, ucIndex); + + prStaRec = cnmGetStaRecByIndex(prAdapter, 0); + + if (ucIndex >= TEST_PS_CATA0_INDEX_NUM) + return; + + if (ucRead == SWCR_WRITE) { + switch (ucIndex) { + case TEST_PS_SETUP_BSS: + testPsSetupBss(prAdapter, ucOpt0); + break; + + case TEST_PS_ENABLE_BEACON: + break; + + case TEST_PS_TRIGGER_BMC: + /* txmForwardQueuedBmcPkts (ucOpt0); */ + break; + case TEST_PS_SEND_NULL: + { + + testPsSendQoSNullFrame(prAdapter, prStaRec, (UINT_8) (g_au4SwCr[1] & 0xFF), /* UP */ + ucOpt0, (BOOLEAN) ((g_au4SwCr[1] >> 8) & 0xFF), /* BMC */ + (BOOLEAN) ((g_au4SwCr[1] >> 16) & 0xFF), /* BurstEnd */ + (BOOLEAN) ((g_au4SwCr[1] >> 24) & 0xFF), /* Packet type */ + (UINT_8) ((g_au4SwCr[2]) & 0xFF), /* PS sesson ID 7: NOACK */ + FALSE /* EOSP */ + ); + } + break; + case TEST_PS_BUFFER_BMC: + /* g_aprBssInfo[ucOpt0]->fgApToBufferBMC = (g_au4SwCr[1] & 0xFF); */ + break; + case TEST_PS_UPDATE_BEACON: + bssUpdateBeaconContent(prAdapter, ucOpt0 /*networktype */); + break; + + default: + break; + } + } else { + switch (ucIndex) { + + case TEST_PS_MAGIC: + g_au4SwCr[1] = 0x88660011; + break; + + } + } +} + +#endif /* TEST_PS */ + +#if TEST_PS + +VOID testPsCmdCategory1(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1) +{ + UINT_8 ucIndex, ucRead; + UINT_8 ucWTEntry; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("testPsCmdCategory1"); + + SWCR_GET_RW_INDEX(ucAction, ucRead, ucIndex); + + if (ucOpt0 >= CFG_STA_REC_NUM) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucOpt0); + if (!prStaRec) + return; + ucWTEntry = prStaRec->ucWTEntry; + if (ucRead == SWCR_WRITE) { + + switch (ucIndex) { + case TEST_PS_STA_PS: + prStaRec->fgIsInPS = (BOOLEAN) (g_au4SwCr[1] & 0x1); + prStaRec->fgIsQoS = (BOOLEAN) (g_au4SwCr[1] >> 8 & 0xFF); + prStaRec->fgIsUapsdSupported = (BOOLEAN) (g_au4SwCr[1] >> 16 & 0xFF); + prStaRec->ucBmpDeliveryAC = (BOOLEAN) (g_au4SwCr[1] >> 24 & 0xFF); + break; + + } + + } else { + /* Read */ + switch (ucIndex) { + default: + break; + } + } + +} + +#endif /* TEST_PS */ + +#if CFG_SUPPORT_802_11V +#if (CFG_SUPPORT_802_11V_TIMING_MEASUREMENT == 1) && (WNM_UNIT_TEST == 1) +VOID testWNMCmdCategory0(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1) +{ + UINT_8 ucIndex, ucRead; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("testWNMCmdCategory0"); + SWCR_GET_RW_INDEX(ucAction, ucRead, ucIndex); + + DBGLOG(SW4, INFO, "Read %u Index %u\n", ucRead, ucIndex); + + if (ucIndex >= TEST_WNM_CATA0_INDEX_NUM) + return; + + if (ucRead == SWCR_WRITE) { + switch (ucIndex) { + case TEST_WNM_TIMING_MEAS: + wnmTimingMeasUnitTest1(prAdapter, ucOpt0); + break; + + default: + break; + } + } +} +#endif /* TEST_WNM */ +#endif /* CFG_SUPPORT_802_11V */ + +VOID swCtrlSwCr(P_ADAPTER_T prAdapter, UINT_8 ucRead, UINT_16 u2Addr, UINT_32 *pu4Data) +{ + /* According other register STAIDX */ + UINT_8 ucOffset; + + ucOffset = (u2Addr >> 2) & 0x3F; + + if (ucOffset >= SWCR_CR_NUM) + return; + + if (ucRead == SWCR_WRITE) { + g_au4SwCr[ucOffset] = *pu4Data; + if (ucOffset == 0x0) { + /* Commmand [31:24]: Category */ + /* Commmand [23:23]: 1(W) 0(R) */ + /* Commmand [22:16]: Index */ + /* Commmand [15:08]: Option0 */ + /* Commmand [07:00]: Option1 */ + UINT_8 ucCate; + UINT_32 u4Cmd; + + u4Cmd = g_au4SwCr[0]; + ucCate = (UINT_8) (u4Cmd >> 24); + if (ucCate < ARRAY_SIZE(g_arSwCtrlCmd)) { + if (g_arSwCtrlCmd[ucCate] != NULL) { + g_arSwCtrlCmd[ucCate] (prAdapter, ucCate, (UINT_8) (u4Cmd >> 16 & 0xFF), + (UINT_8) ((u4Cmd >> 8) & 0xFF), (UINT_8) (u4Cmd & 0xFF)); + } + } + } + } else { + *pu4Data = g_au4SwCr[ucOffset]; + } +} + +VOID swCrReadWriteCmd(P_ADAPTER_T prAdapter, UINT_8 ucRead, UINT_16 u2Addr, UINT_32 *pu4Data) +{ + UINT_8 ucMod; + + ucMod = u2Addr >> 8; + /* Address [15:8] MOD ID */ + /* Address [7:0] OFFSET */ + + DEBUGFUNC("swCrReadWriteCmd"); + DBGLOG(SW4, TRACE, "%u addr 0x%x data 0x%x\n", ucRead, u2Addr, *pu4Data); + + if (ucMod < ARRAY_SIZE(g_arSwCrModHandle)) { + + if (g_arSwCrModHandle[ucMod] != NULL) + g_arSwCrModHandle[ucMod] (prAdapter, ucRead, u2Addr, pu4Data); + } /* ucMod */ +} + +/* Debug Support */ +VOID swCrFrameCheckEnable(P_ADAPTER_T prAdapter, UINT_32 u4DumpType) +{ + g_u4SwcrDebugFrameDumpType = u4DumpType; + prAdapter->rRxCtrl.u4RxPktsDumpTypeMask = u4DumpType; +} + +VOID swCrDebugInit(P_ADAPTER_T prAdapter) +{ + /* frame dump */ + if (g_u4SwcrDebugFrameDumpType) + swCrFrameCheckEnable(prAdapter, g_u4SwcrDebugFrameDumpType); + /* debug counter */ + g_fgSwcrDebugTimer = FALSE; + + cnmTimerInitTimer(prAdapter, &g_rSwcrDebugTimer, (PFN_MGMT_TIMEOUT_FUNC) swCrDebugCheckTimeout, (ULONG) NULL); + + if (g_u4SwcrDebugCheckTimeout) + swCrDebugCheckEnable(prAdapter, TRUE, g_ucSwcrDebugCheckType, g_u4SwcrDebugCheckTimeout); +} + +VOID swCrDebugUninit(P_ADAPTER_T prAdapter) +{ + cnmTimerStopTimer(prAdapter, &g_rSwcrDebugTimer); + + g_fgSwcrDebugTimer = FALSE; +} + +VOID swCrDebugCheckEnable(P_ADAPTER_T prAdapter, BOOLEAN fgIsEnable, UINT_8 ucType, UINT_32 u4Timeout) +{ + if (fgIsEnable) { + g_ucSwcrDebugCheckType = ucType; + g_u4SwcrDebugCheckTimeout = u4Timeout; + if (g_fgSwcrDebugTimer == FALSE) + swCrDebugCheckTimeout(prAdapter, 0); + } else { + cnmTimerStopTimer(prAdapter, &g_rSwcrDebugTimer); + g_u4SwcrDebugCheckTimeout = 0; + } + + g_fgSwcrDebugTimer = fgIsEnable; +} + +VOID swCrDebugCheck(P_ADAPTER_T prAdapter, P_CMD_SW_DBG_CTRL_T prCmdSwCtrl) +{ + P_RX_CTRL_T prRxCtrl; + P_TX_CTRL_T prTxCtrl; + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + + /* dump counters */ + if (prCmdSwCtrl) { + if (prCmdSwCtrl->u4Data == SWCR_DBG_TYPE_ALL) { + + /* TX Counter from fw */ + DBGLOG(SW4, INFO, "TX0\n" + "%08x %08x %08x %08x\n" + "%08x %08x %08x %08x\n", + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_BCN_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_FAILED_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_RETRY_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_AGING_TIMEOUT_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_PS_OVERFLOW_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_MGNT_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_ERROR_CNT]); +#if 1 + /* TX Counter from drv */ + DBGLOG(SW4, INFO, "TX1\n" + "%08x %08x %08x %08x\n", + (UINT_32) TX_GET_CNT(prTxCtrl, TX_INACTIVE_BSS_DROP), + (UINT_32) TX_GET_CNT(prTxCtrl, TX_INACTIVE_STA_DROP), + (UINT_32) TX_GET_CNT(prTxCtrl, TX_FORWARD_OVERFLOW_DROP), + (UINT_32) TX_GET_CNT(prTxCtrl, TX_AP_BORADCAST_DROP)); +#endif + + /* RX Counter */ + DBGLOG(SW4, INFO, "RX0\n" + "%08x %08x %08x %08x\n" + "%08x %08x %08x %08x\n" + "%08x %08x %08x %08x\n" + "%08x %08x %08x %08x\n", + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_DUP_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_TYPE_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_CLASS_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_AMPDU_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_STATUS_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_FORMAT_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_ICV_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_KEY_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_TKIP_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_MIC_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_BIP_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_FCSERR_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_FIFOFULL_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_PFDROP_CNT]); + + DBGLOG(SW4, INFO, "RX1\n" + "%08x %08x %08x %08x\n" + "%08x %08x %08x %08x\n", + (UINT_32) RX_GET_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT), + (UINT_32) RX_GET_CNT(prRxCtrl, RX_DATA_INDICATION_COUNT), + (UINT_32) RX_GET_CNT(prRxCtrl, RX_DATA_RETURNED_COUNT), + (UINT_32) RX_GET_CNT(prRxCtrl, RX_DATA_RETAINED_COUNT), + (UINT_32) RX_GET_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT), + (UINT_32) RX_GET_CNT(prRxCtrl, RX_TYPE_ERR_DROP_COUNT), + (UINT_32) RX_GET_CNT(prRxCtrl, RX_CLASS_ERR_DROP_COUNT), + (UINT_32) RX_GET_CNT(prRxCtrl, RX_DST_NULL_DROP_COUNT)); + + DBGLOG(SW4, INFO, "PWR\n" + "%08x %08x %08x %08x\n" + "%08x %08x %08x %08x\n", + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_PS_POLL_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_TRIGGER_NULL_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_BCN_IND_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_BCN_TIMEOUT_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_PM_STATE0], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_PM_STATE1], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_CUR_PS_PROF0], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_CUR_PS_PROF1]); + + DBGLOG(SW4, INFO, "ARM\n" + "%08x %08x %08x %08x\n" + "%08x %08x\n", + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_AR_STA0_RATE], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_AR_STA0_BWGI], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_AR_STA0_RX_RATE_RCPI], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_ROAMING_ENABLE], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_ROAMING_ROAM_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_ROAMING_INT_CNT]); + + DBGLOG(SW4, INFO, "BB\n" + "%08x %08x %08x %08x\n" + "%08x %08x %08x %08x\n", + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_RX_MDRDY_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_RX_FCSERR_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_CCK_PD_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_OFDM_PD_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_CCK_SFDERR_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_CCK_SIGERR_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_OFDM_TAGERR_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_OFDM_SIGERR_CNT]); + + } + } + /* start the next check */ + if (g_u4SwcrDebugCheckTimeout) + cnmTimerStartTimer(prAdapter, &g_rSwcrDebugTimer, g_u4SwcrDebugCheckTimeout * MSEC_PER_SEC); +} + +VOID swCrDebugCheckTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam) +{ + CMD_SW_DBG_CTRL_T rCmdSwCtrl; + WLAN_STATUS rStatus; + + rCmdSwCtrl.u4Id = (0xb000 << 16) + g_ucSwcrDebugCheckType; + rCmdSwCtrl.u4Data = 0; + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SW_DBG_CTRL, /* ucCID */ + FALSE, /* fgSetQuery */ + TRUE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + swCrDebugQuery, /* pfCmdDoneHandler */ + swCrDebugQueryTimeout, /* pfCmdTimeoutHandler */ + sizeof(CMD_SW_DBG_CTRL_T), /* u4SetQueryInfoLen */ + (PUINT_8)&rCmdSwCtrl, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); + +} + +VOID swCrDebugQuery(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + ASSERT(prAdapter); + + swCrDebugCheck(prAdapter, (P_CMD_SW_DBG_CTRL_T) (pucEventBuf)); +} + +VOID swCrDebugQueryTimeout(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + ASSERT(prAdapter); + + swCrDebugCheck(prAdapter, NULL); +} + +#endif /* CFG_SUPPORT_SWCR */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/tdls.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/tdls.c new file mode 100644 index 0000000000000..7e1e599332074 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/tdls.c @@ -0,0 +1,5667 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ +#include "precomp.h" + +#if (CFG_SUPPORT_TDLS == 1) +#include "gl_wext.h" +#include "tdls.h" +#include "gl_cfg80211.h" +#include +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static VOID TdlsCmdTestRxIndicatePkts(GLUE_INFO_T *prGlueInfo, struct sk_buff *prSkb); + +#if TDLS_CFG_CMD_TEST +static void TdlsCmdTestAddPeer(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestChSwProhibitedBitSet(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestChSwReqRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestChSwRspRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestChSwTimeoutSkip(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestDataContSend(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestDataRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestDataSend(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestDelay(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestDiscoveryReqRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestKeepAliveSkip(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestProhibitedBitSet(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestPtiReqRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestPtiRspRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestPtiTxDoneFail(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestRvFrame(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestSetupConfirmRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestSetupReqRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestSetupRspRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestScanCtrl(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestTearDownRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestTxFailSkip(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestTxTdlsFrame(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestTxFrame(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static TDLS_STATUS +TdlsCmdTestTxFmeSetupReqBufTranslate(UINT_8 *pCmdBuf, UINT_32 u4BufLen, PARAM_CUSTOM_TDLS_CMD_STRUCT_T *prCmd); + +static void TdlsCmdTestUpdatePeer(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestNullRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static VOID TdlsTimerTestDataContSend(ADAPTER_T *prAdapter, UINT_32 u4Param); + +static TDLS_STATUS +TdlsTestChStReqRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsTestChStRspRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsTestFrameSend(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsTestNullRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsTestPtiReqRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsTestPtiRspRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsTestTearDownRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsTestDataRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsTestPtiTxFail(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsTestTdlsFrameSend(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsTestTxFailSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsTestKeepAliveSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsTestChSwTimeoutSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsTestScanSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsChSwConf(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static void TdlsCmdChSwConf(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdInfoDisplay(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdKeyInfoDisplay(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdMibParamUpdate(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdSetupConf(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdUapsdConf(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static TDLS_STATUS +TdlsInfoDisplay(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsKeyInfoDisplay(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static VOID +TdlsLinkHistoryRecord(GLUE_INFO_T *prGlueInfo, + BOOLEAN fgIsTearDown, + UINT8 *pucPeerMac, BOOLEAN fgIsFromUs, UINT16 u2ReasonCode, VOID *prOthers); + +static VOID +TdlsLinkHistoryRecordUpdate(GLUE_INFO_T *prGlueInfo, + UINT8 *pucPeerMac, TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME eFmeStatus, VOID *pInfo); + +static TDLS_STATUS +TdlsMibParamUpdate(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsSetupConf(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsUapsdConf(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static void TdlsEventStatistics(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen); + +static void TdlsEventTearDown(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen); + +#endif /* TDLS_CFG_CMD_TEST */ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static BOOLEAN fgIsPtiTimeoutSkip = FALSE; + +/******************************************************************************* +* P R I V A T E F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to indicate packets to upper layer. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prSkb A pointer to the received packet +* +* \retval None +* +*/ +/*----------------------------------------------------------------------------*/ +static VOID TdlsCmdTestRxIndicatePkts(GLUE_INFO_T *prGlueInfo, struct sk_buff *prSkb) +{ + struct net_device *prNetDev; + + /* init */ + prNetDev = prGlueInfo->prDevHandler; + prGlueInfo->rNetDevStats.rx_bytes += prSkb->len; + prGlueInfo->rNetDevStats.rx_packets++; + + /* pass to upper layer */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) + prNetDev->last_rx = jiffies; +#endif + prSkb->protocol = eth_type_trans(prSkb, prNetDev); + prSkb->dev = prNetDev; + + if (!in_interrupt()) + netif_rx_ni(prSkb); /* only in non-interrupt context */ + else + netif_rx(prSkb); +} + +#if TDLS_CFG_CMD_TEST + +#define LR_TDLS_FME_FIELD_FILL(__Len) \ +do { \ + pPkt += __Len; \ + u4PktLen += __Len; \ +} while (0) + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to add a TDLS peer. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_2_[Responder MAC] + + iwpriv wlan0 set_str_cmd 0_2_00:11:22:33:44:01 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestAddPeer(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + PARAM_CUSTOM_TDLS_CMD_STRUCT_T rCmd; + struct wireless_dev *prWdev; + + /* reset */ + kalMemZero(&rCmd, sizeof(rCmd)); + + /* parse arguments */ + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.arRspAddr); + + /* init */ + rCmd.rPeerInfo.supported_rates = NULL; + rCmd.rPeerInfo.ht_capa = &rCmd.rHtCapa; + rCmd.rPeerInfo.vht_capa = &rCmd.rVhtCapa; /* LINUX_KERNEL_VERSION >= 3.10.0 */ + rCmd.rPeerInfo.sta_flags_set = BIT(NL80211_STA_FLAG_TDLS_PEER); + + /* send command to wifi task to handle */ + prWdev = prGlueInfo->prDevHandler->ieee80211_ptr; + mtk_cfg80211_add_station(prWdev->wiphy, (void *)0x1, rCmd.arRspAddr, &rCmd.rPeerInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to simulate to set the TDLS Prohibited bit. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_16_[Enable/Disable]_[Set/Clear] + + iwpriv wlan0 set_str_cmd 0_16_1_1 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestChSwProhibitedBitSet(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + TDLS_CMD_CORE_T rCmd; + + /* parse arguments */ + kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); + rCmd.Content.rCmdProhibit.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdProhibit.fgIsSet = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdProhibit.fgIsEnable); + + /* command to do this */ + flgTdlsTestExtCapElm = rCmd.Content.rCmdProhibit.fgIsEnable; + + aucTdlsTestExtCapElm[0] = ELEM_ID_EXTENDED_CAP; + aucTdlsTestExtCapElm[1] = 5; + aucTdlsTestExtCapElm[2] = 0; + aucTdlsTestExtCapElm[3] = 0; + aucTdlsTestExtCapElm[4] = 0; + aucTdlsTestExtCapElm[5] = 0; + aucTdlsTestExtCapElm[6] = (rCmd.Content.rCmdProhibit.fgIsSet << 7); /* bit39 */ +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a channel switch request from the peer. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_1_5_[TDLS Peer MAC]_[Chan]_[RegulatoryClass]_ + [SecondaryChannelOffset]_[SwitchTime]_[SwitchTimeout] + + iwpriv wlan0 set_str_cmd 0_1_5_00:11:22:33:44:01_1_255_0_15000_30000 + + RegulatoryClass: TODO (reference to Annex I of 802.11n spec.) + Secondary Channel Offset: 0 (SCN - no secondary channel) + 1 (SCA - secondary channel above) + 2 (SCB - secondary channel below) + SwitchTime: units of microseconds + +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestChSwReqRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac); + + rCmd.Content.rCmdChStReqRcv.u4Chan = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdChStReqRcv.u4RegClass = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdChStReqRcv.u4SecChanOff = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdChStReqRcv.u4SwitchTime = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdChStReqRcv.u4SwitchTimeout = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s:[%pM]u4Chan=%u u4RegClass=%u u4SecChanOff=%u u4SwitchTime=%u u4SwitchTimeout=%u\n", + __func__, rCmd.aucPeerMac, + (UINT32) rCmd.Content.rCmdChStReqRcv.u4Chan, + (UINT32) rCmd.Content.rCmdChStReqRcv.u4RegClass, + (UINT32) rCmd.Content.rCmdChStReqRcv.u4SecChanOff, + (UINT32) rCmd.Content.rCmdChStReqRcv.u4SwitchTime, + (UINT32) rCmd.Content.rCmdChStReqRcv.u4SwitchTimeout); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsTestChStReqRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a channel switch response from the peer. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_1_6_[TDLS Peer MAC]_[Chan]_ + [SwitchTime]_[SwitchTimeout]_[StatusCode] + + iwpriv wlan0 set_str_cmd 0_1_6_00:11:22:33:44:01_11_15000_30000_0 + + RegulatoryClass: TODO (reference to Annex I of 802.11n spec.) + Secondary Channel Offset: 0 (SCN - no secondary channel) + 1 (SCA - secondary channel above) + 2 (SCB - secondary channel below) + SwitchTime: units of microseconds + +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestChSwRspRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac); + + rCmd.Content.rCmdChStRspRcv.u4Chan = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdChStRspRcv.u4SwitchTime = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdChStRspRcv.u4SwitchTimeout = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdChStRspRcv.u4StatusCode = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s: [ %pM ] u4Chan=%u u4SwitchTime=%u u4SwitchTimeout=%u u4StatusCode=%u\n", + __func__, rCmd.aucPeerMac, + (UINT32) rCmd.Content.rCmdChStRspRcv.u4Chan, + (UINT32) rCmd.Content.rCmdChStRspRcv.u4SwitchTime, + (UINT32) rCmd.Content.rCmdChStRspRcv.u4SwitchTimeout, + (UINT32) rCmd.Content.rCmdChStRspRcv.u4StatusCode); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsTestChStRspRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to inform firmware to skip channel switch timeout function. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_11_[Enable/Disable] + + iwpriv wlan0 set_str_cmd 0_11_1 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestChSwTimeoutSkip(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); + rCmd.Content.rCmdKeepAliveSkip.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdKeepAliveSkip.fgIsEnable); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, + TdlsTestChSwTimeoutSkip, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to send a data frame to the peer periodically. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +*/ +/*----------------------------------------------------------------------------*/ +static TIMER_T rTdlsTimerTestDataSend; +static UINT_8 aucTdlsTestDataSPeerMac[6]; +static UINT_16 u2TdlsTestDataSInterval; + +static void TdlsCmdTestDataContSend(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + ADAPTER_T *prAdapter; + BOOLEAN fgIsEnabled; + + /* init */ + prAdapter = prGlueInfo->prAdapter; + + /* parse arguments */ + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucTdlsTestDataSPeerMac); + u2TdlsTestDataSInterval = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + fgIsEnabled = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + cnmTimerStopTimer(prAdapter, &rTdlsTimerTestDataSend); + + if (fgIsEnabled == FALSE) { + /* stop test timer */ + return; + } + + /* re-init test timer */ + cnmTimerInitTimer(prAdapter, + &rTdlsTimerTestDataSend, (PFN_MGMT_TIMEOUT_FUNC) TdlsTimerTestDataContSend, (ULONG) NULL); + + cnmTimerStartTimer(prAdapter, &rTdlsTimerTestDataSend, u2TdlsTestDataSInterval); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a data frame from the peer. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_0_x80_[TDLS Peer MAC]_[PM]_[UP]_[EOSP]_[IsNull] + + iwpriv wlan0 set_str_cmd 0_1_x80_00:11:22:33:44:01_0_0_0_0 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestDataRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac); + rCmd.Content.rCmdDatRcv.u4PM = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdDatRcv.u4UP = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdDatRcv.u4EOSP = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdDatRcv.u4IsNull = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, + " %s: [%pM] PM(%u) UP(%u) EOSP(%u) NULL(%u)\n", + __func__, rCmd.aucPeerMac, + (UINT32) rCmd.Content.rCmdDatRcv.u4PM, + (UINT32) rCmd.Content.rCmdDatRcv.u4UP, + (UINT32) rCmd.Content.rCmdDatRcv.u4EOSP, (UINT32) rCmd.Content.rCmdDatRcv.u4IsNull); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsTestDataRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to send a data frame to the peer. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_4_[Responder MAC]_[tx status] + + iwpriv wlan0 set_str_cmd 0_4_00:11:22:33:44:01_0 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestDataSend(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + P_ADAPTER_T prAdapter; + struct sk_buff *prMsduInfo; + UINT_8 *prPkt; + UINT_8 MAC[6] = {0}; + UINT_8 ucTxStatus; + + /* init */ + prAdapter = prGlueInfo->prAdapter; + + /* parse arguments */ + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, MAC); + ucTxStatus = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + /* allocate a data frame */ + prMsduInfo = kalPacketAlloc(prGlueInfo, 1000, &prPkt); + if (prMsduInfo == NULL) { + DBGLOG(TDLS, ERROR, " %s allocate pkt fail!\n", __func__); + return; + } + + /* init dev */ + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + DBGLOG(TDLS, ERROR, " %s prMsduInfo->dev == NULL!\n", __func__); + kalPacketFree(prGlueInfo, prMsduInfo); + return; + } + + /* init packet */ + prMsduInfo->len = 1000; + kalMemZero(prMsduInfo->data, 100); /* for QoS field */ + kalMemCopy(prMsduInfo->data, MAC, 6); + kalMemCopy(prMsduInfo->data + 6, prAdapter->rMyMacAddr, 6); + *(UINT_16 *) (prMsduInfo->data + 12) = 0x0800; + + /* simulate OS to send the packet */ + wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to simulate to set the TDLS Prohibited bit. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_16_[mili seconds] + + iwpriv wlan0 set_str_cmd 0_19_1000 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestDelay(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + UINT32 u4Delay; + + u4Delay = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + DBGLOG(TDLS, INFO, "%s: Delay = %d\n", __func__, u4Delay); + + kalMdelay(u4Delay); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a test discovery request frame command. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_1_10_[DialogToken]_[Peer MAC]_[BSSID] + + iwpriv wlan0 set_str_cmd 0_1_10_1_00:11:22:33:44:01 + iwpriv wlan0 set_str_cmd 0_1_10_1_00:11:22:33:44:01_00:22:33:44:11:22 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestDiscoveryReqRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + ADAPTER_T *prAdapter; + P_BSS_INFO_T prBssInfo; + struct sk_buff *prMsduInfo; + UINT_8 *pPkt; + UINT_32 u4PktLen, u4IeLen; + UINT_8 ucDialogToken, aucPeerMac[6] = {0}, aucBSSID[6], aucZeroMac[6]; + + /* parse arguments */ + ucDialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucPeerMac); + + kalMemZero(aucZeroMac, sizeof(aucZeroMac)); + kalMemZero(aucBSSID, sizeof(aucBSSID)); + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucBSSID); + + DBGLOG(TDLS, INFO, + " %s: DialogToken=%d from %pM\n", __func__, ucDialogToken, aucPeerMac); + + /* allocate/init packet */ + prAdapter = prGlueInfo->prAdapter; + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + u4PktLen = 0; + + prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); + if (prMsduInfo == NULL) { + DBGLOG(TDLS, ERROR, " %s: allocate pkt fail\n", __func__); + return; + } + + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + DBGLOG(TDLS, ERROR, " %s: MsduInfo->dev == NULL\n", __func__); + kalPacketFree(prGlueInfo, prMsduInfo); + return; + } + + /* make up frame content */ + /* 1. 802.3 header */ + kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(pPkt, aucPeerMac, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); + LR_TDLS_FME_FIELD_FILL(2); + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (1) Category */ + *pPkt = TDLS_FRM_CATEGORY; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (2) Action */ + *pPkt = TDLS_FRM_ACTION_DISCOVERY_REQ; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (3) Dialog token */ + *pPkt = ucDialogToken; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (16) Link identifier element */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; + + if (kalMemCmp(aucBSSID, aucZeroMac, 6) == 0) + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); + else + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, aucBSSID, 6); + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, aucPeerMac, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prAdapter->rMyMacAddr, 6); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 4. Update packet length */ + prMsduInfo->len = u4PktLen; + dumpMemory8(prMsduInfo->data, u4PktLen); + + /* pass to OS */ + TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to inform firmware to skip keep alive function. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_10_[Enable/Disable] + + iwpriv wlan0 set_str_cmd 0_10_1 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestKeepAliveSkip(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); + rCmd.Content.rCmdKeepAliveSkip.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdKeepAliveSkip.fgIsEnable); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, + TdlsTestKeepAliveSkip, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to simulate to set the TDLS Prohibited bit. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_11_[Enable/Disable]_[Set/Clear] + + iwpriv wlan0 set_str_cmd 0_13_1_1 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestProhibitedBitSet(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + TDLS_CMD_CORE_T rCmd; + + /* parse arguments */ + kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); + rCmd.Content.rCmdProhibit.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdProhibit.fgIsSet = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdProhibit.fgIsEnable); + + /* command to do this */ + flgTdlsTestExtCapElm = rCmd.Content.rCmdProhibit.fgIsEnable; + + aucTdlsTestExtCapElm[0] = ELEM_ID_EXTENDED_CAP; + aucTdlsTestExtCapElm[1] = 5; + aucTdlsTestExtCapElm[2] = 0; + aucTdlsTestExtCapElm[3] = 0; + aucTdlsTestExtCapElm[4] = 0; + aucTdlsTestExtCapElm[5] = 0; + aucTdlsTestExtCapElm[6] = (rCmd.Content.rCmdProhibit.fgIsSet << 6); /* bit38 */ +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a PTI request from the AP. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_1_4_[TDLS Peer MAC]_[Dialog Token] + + iwpriv wlan0 set_str_cmd 0_1_4_00:11:22:33:44:01_0 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestPtiReqRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac); + + rCmd.Content.rCmdPtiRspRcv.u4DialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s: [ %pM ] u4DialogToken = %u\n", + __func__, rCmd.aucPeerMac, (UINT32) rCmd.Content.rCmdPtiRspRcv.u4DialogToken); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsTestPtiReqRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a PTI response from the peer. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_1_9_[TDLS Peer MAC]_[Dialog Token]_[PM] + + iwpriv wlan0 set_str_cmd 0_1_9_00:11:22:33:44:01_0_1 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestPtiRspRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac); + + rCmd.Content.rCmdPtiRspRcv.u4DialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdPtiRspRcv.u4PM = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s: [%pM] u4DialogToken = %u %u\n", + __func__, rCmd.aucPeerMac, + (UINT32) rCmd.Content.rCmdPtiRspRcv.u4DialogToken, + (UINT32) rCmd.Content.rCmdPtiRspRcv.u4PM); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsTestPtiRspRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to inform firmware to simulate PTI tx done fail case. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_21_[Enable/Disable] + + iwpriv wlan0 set_str_cmd 0_21_1 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestPtiTxDoneFail(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); + rCmd.Content.rCmdPtiTxFail.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdPtiTxFail.fgIsEnable); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsTestPtiTxFail, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a test frame. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestRvFrame(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ +/* PARAM_CUSTOM_TDLS_CMD_STRUCT_T rCmd; */ +/* TDLS_STATUS u4Status; */ + UINT_32 u4Subcmd; +/* UINT_32 u4BufLen; */ + + /* parse sub-command */ + u4Subcmd = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + DBGLOG(TDLS, INFO, " test rv frame sub command = %u\n", (UINT32) u4Subcmd); + + /* parse command arguments */ + switch (u4Subcmd) { + case TDLS_FRM_ACTION_SETUP_REQ: + /* simulate to receive a setup request frame */ + TdlsCmdTestSetupReqRecv(prGlueInfo, prInBuf, u4InBufLen); + break; + + case TDLS_FRM_ACTION_SETUP_RSP: + /* simulate to receive a setup response frame */ + TdlsCmdTestSetupRspRecv(prGlueInfo, prInBuf, u4InBufLen); + break; + + case TDLS_FRM_ACTION_CONFIRM: + /* simulate to receive a setup confirm frame */ + TdlsCmdTestSetupConfirmRecv(prGlueInfo, prInBuf, u4InBufLen); + break; + + case TDLS_FRM_ACTION_TEARDOWN: + /* simulate to receive a tear down frame */ + TdlsCmdTestTearDownRecv(prGlueInfo, prInBuf, u4InBufLen); + break; + + case TDLS_FRM_ACTION_PTI: + /* simulate to receive a PTI request frame */ + TdlsCmdTestPtiReqRecv(prGlueInfo, prInBuf, u4InBufLen); + break; + + case TDLS_FRM_ACTION_PTI_RSP: + /* simulate to receive a PTI response frame */ + TdlsCmdTestPtiRspRecv(prGlueInfo, prInBuf, u4InBufLen); + break; + + case TDLS_FRM_DATA_TEST_DATA: + /* simulate to receive a DATA frame */ + TdlsCmdTestDataRecv(prGlueInfo, prInBuf, u4InBufLen); + break; + + case TDLS_FRM_ACTION_CHAN_SWITCH_REQ: + /* simulate to receive a channel switch request frame */ + TdlsCmdTestChSwReqRecv(prGlueInfo, prInBuf, u4InBufLen); + break; + + case TDLS_FRM_ACTION_CHAN_SWITCH_RSP: + /* simulate to receive a channel switch response frame */ + TdlsCmdTestChSwRspRecv(prGlueInfo, prInBuf, u4InBufLen); + break; + + case TDLS_FRM_ACTION_DISCOVERY_REQ: + /* simulate to receive a discovery request frame */ + TdlsCmdTestDiscoveryReqRecv(prGlueInfo, prInBuf, u4InBufLen); + break; + + default: + DBGLOG(TDLS, ERROR, " wrong test rv frame sub command\n"); + return; + } + +/* if (u4Status != TDLS_STATUS_SUCCESS) */ + { +/* DBGLOG(TDLS, ERROR, (" command parse fail\n")); */ +/* return; */ + } + + /* send command to wifi task to handle */ +#if 0 + kalIoctl(prGlueInfo, + TdlsTestFrameSend, + (PVOID)&rCmd, sizeof(PARAM_CUSTOM_TDLS_CMD_STRUCT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a test setup confirm frame command. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_1_2_[DialogToken]_[StatusCode]_[Peer MAC] + + iwpriv wlan0 set_str_cmd 0_1_2_1_0_00:11:22:33:44:01 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestSetupConfirmRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + ADAPTER_T *prAdapter; + P_BSS_INFO_T prBssInfo; + PM_PROFILE_SETUP_INFO_T *prPmProfSetupInfo; + struct sk_buff *prMsduInfo; + UINT_8 *pPkt; + UINT_32 u4PktLen, u4IeLen; + UINT_8 ucDialogToken, ucStatusCode, aucPeerMac[6] = {0}; + + /* parse arguments */ + ucDialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + ucStatusCode = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucPeerMac); + + DBGLOG(TDLS, INFO, + " %s: DialogToken=%d StatusCode=%d from %pM\n", + __func__, ucDialogToken, ucStatusCode, aucPeerMac); + + /* allocate/init packet */ + prAdapter = prGlueInfo->prAdapter; + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + + prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); + if (prMsduInfo == NULL) { + DBGLOG(TDLS, ERROR, " %s: allocate pkt fail\n", __func__); + return; + } + + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + DBGLOG(TDLS, ERROR, " %s: MsduInfo->dev == NULL\n", __func__); + kalPacketFree(prGlueInfo, prMsduInfo); + return; + } + + /* make up frame content */ + /* 1. 802.3 header */ + kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(pPkt, aucPeerMac, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); + LR_TDLS_FME_FIELD_FILL(2); + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (1) Category */ + *pPkt = TDLS_FRM_CATEGORY; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (2) Action */ + *pPkt = TDLS_FRM_ACTION_CONFIRM; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (3) Status Code */ + *pPkt = ucStatusCode; + *(pPkt + 1) = 0x00; + LR_TDLS_FME_FIELD_FILL(2); + + /* 3. Frame Formation - (4) Dialog token */ + *pPkt = ucDialogToken; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (17) WMM Information element */ + if (prAdapter->rWifiVar.fgSupportQoS) { + u4IeLen = mqmGenerateWmmParamIEByParam(prAdapter, prBssInfo, pPkt, OP_MODE_INFRASTRUCTURE); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } + + /* 3. Frame Formation - (16) Link identifier element */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = ELEM_LEN_LINK_IDENTIFIER; + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, aucPeerMac, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prAdapter->rMyMacAddr, 6); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 4. Update packet length */ + prMsduInfo->len = u4PktLen; + dumpMemory8(prMsduInfo->data, u4PktLen); + + /* pass to OS */ + TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a test setup request frame command. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_1_0_[DialogToken]_[Peer MAC]_[BSSID] + + iwpriv wlan0 set_str_cmd 0_1_0_1_00:11:22:33:44:01 + iwpriv wlan0 set_str_cmd 0_1_0_1_00:11:22:33:44:01_00:22:33:44:11:22 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestSetupReqRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + ADAPTER_T *prAdapter; + P_BSS_INFO_T prBssInfo; + struct sk_buff *prMsduInfo; + UINT_8 *pPkt; + UINT_32 u4PktLen, u4IeLen; + UINT_8 ucDialogToken, aucPeerMac[6] = {0}, aucBSSID[6], aucZeroMac[6]; + UINT_16 u2CapInfo; + + /* parse arguments */ + ucDialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucPeerMac); + + kalMemZero(aucZeroMac, sizeof(aucZeroMac)); + kalMemZero(aucBSSID, sizeof(aucBSSID)); + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucBSSID); + + DBGLOG(TDLS, INFO, + " %s: DialogToken=%d from %pM\n", __func__, ucDialogToken, aucPeerMac); + + /* allocate/init packet */ + prAdapter = prGlueInfo->prAdapter; + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + u4PktLen = 0; + + prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); + if (prMsduInfo == NULL) { + DBGLOG(TDLS, ERROR, " %s: allocate pkt fail\n", __func__); + return; + } + + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + DBGLOG(TDLS, ERROR, " %s: MsduInfo->dev == NULL\n", __func__); + kalPacketFree(prGlueInfo, prMsduInfo); + return; + } + + /* make up frame content */ + /* 1. 802.3 header */ + kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(pPkt, aucPeerMac, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); + LR_TDLS_FME_FIELD_FILL(2); + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (1) Category */ + *pPkt = TDLS_FRM_CATEGORY; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (2) Action */ + *pPkt = TDLS_FRM_ACTION_SETUP_REQ; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (3) Dialog token */ + *pPkt = ucDialogToken; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (4) Capability */ + u2CapInfo = assocBuildCapabilityInfo(prAdapter, NULL); + WLAN_SET_FIELD_16(pPkt, u2CapInfo); + LR_TDLS_FME_FIELD_FILL(2); + + /* 4. Append general IEs */ + u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, NULL, 0, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3. Frame Formation - (10) Extended capabilities element */ + EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP; + EXT_CAP_IE(pPkt)->ucLength = 5; + + EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */ + EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */ + EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */ + + /* TDLS_EX_CAP_PEER_UAPSD */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24)); + /* TDLS_EX_CAP_CHAN_SWITCH */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24)); + /* TDLS_EX_CAP_TDLS */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32)); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3. Frame Formation - (16) Link identifier element */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; + + if (kalMemCmp(aucBSSID, aucZeroMac, 6) == 0) + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); + else + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, aucBSSID, 6); + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, aucPeerMac, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prAdapter->rMyMacAddr, 6); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 4. Update packet length */ + prMsduInfo->len = u4PktLen; + dumpMemory8(prMsduInfo->data, u4PktLen); + + /* pass to OS */ + TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a test setup response frame command. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_1_1_[DialogToken]_[StatusCode]_[Peer MAC] + + iwpriv wlan0 set_str_cmd 0_1_1_1_0_00:11:22:33:44:01 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestSetupRspRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + ADAPTER_T *prAdapter; + P_BSS_INFO_T prBssInfo; + struct sk_buff *prMsduInfo; + UINT_8 *pPkt; + UINT_32 u4PktLen, u4IeLen; + UINT_8 ucDialogToken, ucStatusCode, aucPeerMac[6] = {0}; + UINT_16 u2CapInfo; + + /* parse arguments */ + ucDialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + ucStatusCode = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucPeerMac); + + DBGLOG(TDLS, INFO, + " %s: DialogToken=%d StatusCode=%d from %pM\n", + __func__, ucDialogToken, ucStatusCode, aucPeerMac); + + /* allocate/init packet */ + prAdapter = prGlueInfo->prAdapter; + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + u4PktLen = 0; + + prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); + if (prMsduInfo == NULL) { + DBGLOG(TDLS, ERROR, " %s: allocate pkt fail\n", __func__); + return; + } + + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + DBGLOG(TDLS, ERROR, " %s: MsduInfo->dev == NULL\n", __func__); + kalPacketFree(prGlueInfo, prMsduInfo); + return; + } + + /* make up frame content */ + /* 1. 802.3 header */ + kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(pPkt, aucPeerMac, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); + LR_TDLS_FME_FIELD_FILL(2); + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (1) Category */ + *pPkt = TDLS_FRM_CATEGORY; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (2) Action */ + *pPkt = TDLS_FRM_ACTION_SETUP_RSP; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (3) Status Code */ + *pPkt = ucStatusCode; + *(pPkt + 1) = 0x00; + LR_TDLS_FME_FIELD_FILL(2); + + /* 3. Frame Formation - (4) Dialog token */ + *pPkt = ucDialogToken; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (5) Capability */ + u2CapInfo = assocBuildCapabilityInfo(prAdapter, NULL); + WLAN_SET_FIELD_16(pPkt, u2CapInfo); + LR_TDLS_FME_FIELD_FILL(2); + + /* 4. Append general IEs */ + u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, NULL, 0, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3. Frame Formation - (10) Extended capabilities element */ + EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP; + EXT_CAP_IE(pPkt)->ucLength = 5; + + EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */ + EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */ + EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */ + + /* TDLS_EX_CAP_PEER_UAPSD */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24)); + /* TDLS_EX_CAP_CHAN_SWITCH */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24)); + /* TDLS_EX_CAP_TDLS */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32)); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3. Frame Formation - (16) Link identifier element */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = ELEM_LEN_LINK_IDENTIFIER; + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, prAdapter->rMyMacAddr, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, aucPeerMac, 6); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 4. Update packet length */ + prMsduInfo->len = u4PktLen; + dumpMemory8(prMsduInfo->data, u4PktLen); + + /* pass to OS */ + TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to inform firmware to skip channel switch timeout function. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_14_[Enable/Disable] + + iwpriv wlan0 set_str_cmd 0_14_0 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestScanCtrl(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); + rCmd.Content.rCmdScanSkip.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdScanSkip.fgIsEnable); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsTestScanSkip, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a test tear down frame command. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_1_3_[IsInitiator]_[ReasonCode]_[Peer MAC]_[Where] + + Where 0 (From driver) or 1 (From FW) + + iwpriv wlan0 set_str_cmd 0_1_3_1_26_00:11:22:33:44:01_0 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestTearDownRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + ADAPTER_T *prAdapter; + P_BSS_INFO_T prBssInfo; + struct sk_buff *prMsduInfo; + UINT_8 *pPkt; + UINT_32 u4PktLen, u4IeLen; + BOOLEAN fgIsInitiator; + UINT_8 ucReasonCode, aucPeerMac[6] = {0}; + BOOLEAN fgIsFromWhich; + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + fgIsInitiator = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + ucReasonCode = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucPeerMac); + fgIsFromWhich = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, + " %s: ReasonCode=%d from %pM %d\n", + __func__, ucReasonCode, aucPeerMac, fgIsFromWhich); + + if (fgIsFromWhich == 0) { + /* allocate/init packet */ + prAdapter = prGlueInfo->prAdapter; + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + u4PktLen = 0; + + prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); + if (prMsduInfo == NULL) { + DBGLOG(TDLS, ERROR, " %s: allocate pkt fail\n", __func__); + return; + } + + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + DBGLOG(TDLS, ERROR, " %s: MsduInfo->dev == NULL\n", __func__); + kalPacketFree(prGlueInfo, prMsduInfo); + return; + } + + /* make up frame content */ + /* 1. 802.3 header */ + kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(pPkt, aucPeerMac, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); + LR_TDLS_FME_FIELD_FILL(2); + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (1) Category */ + *pPkt = TDLS_FRM_CATEGORY; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (2) Action */ + *pPkt = TDLS_FRM_ACTION_TEARDOWN; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (3) Reason Code */ + *pPkt = ucReasonCode; + *(pPkt + 1) = 0x00; + LR_TDLS_FME_FIELD_FILL(2); + + /* 3. Frame Formation - (16) Link identifier element */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = ELEM_LEN_LINK_IDENTIFIER; + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); + if (fgIsInitiator == 1) { + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, aucPeerMac, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prAdapter->rMyMacAddr, 6); + } else { + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, prAdapter->rMyMacAddr, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, aucPeerMac, 6); + } + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 4. Update packet length */ + prMsduInfo->len = u4PktLen; + dumpMemory8(prMsduInfo->data, u4PktLen); + + /* pass to OS */ + TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo); + } else { + kalMemZero(&rCmd, sizeof(rCmd)); + kalMemCopy(rCmd.aucPeerMac, aucPeerMac, 6); + rCmd.Content.rCmdTearDownRcv.u4ReasonCode = (UINT32) ucReasonCode; + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, + TdlsTestTearDownRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to inform firmware to skip tx fail case. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_7_[Enable/Disable] + + iwpriv wlan0 set_str_cmd 0_7_1 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestTxFailSkip(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); + rCmd.Content.rCmdTxFailSkip.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdTxFailSkip.fgIsEnable); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsTestTxFailSkip, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to send a test frame command to wifi task. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_12_0_[FrameType]_[DialogToken]_[Peer MAC] + + iwpriv wlan0 set_str_cmd 0_12_0_0_1_00:11:22:33:44:01 +* +* EX: iwpriv wlan0 set_str_cmd 0_12_2_[FrameType]_[DialogToken]_[Peer MAC] + + iwpriv wlan0 set_str_cmd 0_12_2_0_1_00:11:22:33:44:01 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestTxTdlsFrame(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + PARAM_CUSTOM_TDLS_CMD_STRUCT_T rCmd; + UINT32 u4Subcmd; + UINT_32 u4BufLen = 0; + + /* parse sub-command */ + u4Subcmd = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + DBGLOG(TDLS, INFO, " test tx tdls frame sub command = %u\n", u4Subcmd); + + /* parse command arguments */ + rCmd.ucFmeType = CmdStringDecParse(prInBuf, &prInBuf, &u4BufLen); + + switch (u4Subcmd) { + case TDLS_FRM_ACTION_SETUP_REQ: + case TDLS_FRM_ACTION_SETUP_RSP: + case TDLS_FRM_ACTION_CONFIRM: + rCmd.ucToken = CmdStringDecParse(prInBuf, &prInBuf, &u4BufLen); + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.arRspAddr); + + DBGLOG(TDLS, INFO, " setup FmeType=%d Token=%d to [%pM]\n", + rCmd.ucFmeType, rCmd.ucToken, rCmd.arRspAddr); + break; + + default: + DBGLOG(TDLS, ERROR, " wrong test tx frame sub command\n"); + return; + } + + /* send command to wifi task to handle */ + kalIoctl(prGlueInfo, + TdlsTestTdlsFrameSend, + (PVOID)&rCmd, sizeof(PARAM_CUSTOM_TDLS_CMD_STRUCT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to send a test frame command to wifi task. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_0_0_[FrameType]_[DialogToken]_[Cap]_[ExCap]_ + [SupRate0]_[SupRate1]_[SupRate2]_[SupRate3]_ + [SupChan0]_[SupChan1]_[SupChan2]_[SupChan3]_ + [Timeout]_[Peer MAC] + + iwpriv wlan0 set_str_cmd 0_0_0_0_1_1_7_0_0_0_0_0_0_0_0_300_00:11:22:33:44:01 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestTxFrame(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + PARAM_CUSTOM_TDLS_CMD_STRUCT_T rCmd; + TDLS_STATUS u4Status; + UINT_32 u4Subcmd; + UINT_32 u4BufLen; + + /* parse sub-command */ + u4Subcmd = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + DBGLOG(TDLS, INFO, " test tx frame sub command = %u\n", (UINT32) u4Subcmd); + + /* parse command arguments */ + switch (u4Subcmd) { + case TDLS_FRM_ACTION_SETUP_REQ: + u4Status = TdlsCmdTestTxFmeSetupReqBufTranslate(prInBuf, u4InBufLen, &rCmd); + break; + + default: + DBGLOG(TDLS, ERROR, " wrong test tx frame sub command\n"); + return; + } + + if (u4Status != TDLS_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, " command parse fail\n"); + return; + } + + /* send command to wifi task to handle */ + kalIoctl(prGlueInfo, + TdlsTestFrameSend, + (PVOID)&rCmd, sizeof(PARAM_CUSTOM_TDLS_CMD_STRUCT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Parse the TDLS test frame command, setup request +* +* @param CmdBuf Pointer to the buffer. +* @param BufLen Record buffer length. +* @param CmdTspec Pointer to the structure. +* +* @retval WLAN_STATUS_SUCCESS: Translate OK. +* @retval WLAN_STATUS_FAILURE: Translate fail. +* @usage iwpriv wlan0 set_str_cmd [tdls]_[command] +* +* EX: iwpriv wlan0 set_str_cmd 0_0_0_[FrameType]_[DialogToken]_[Cap]_[ExCap]_ + [SupRate0]_[SupRate1]_[SupRate2]_[SupRate3]_ + [SupChan0]_[SupChan1]_[SupChan2]_[SupChan3]_ + [Timeout]_[Peer MAC] + + iwpriv wlan0 set_str_cmd 0_0_0_0_1_1_7_0_0_0_0_0_0_0_0_300_00:11:22:33:44:01 +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsCmdTestTxFmeSetupReqBufTranslate(UINT_8 *pCmdBuf, UINT_32 u4BufLen, PARAM_CUSTOM_TDLS_CMD_STRUCT_T *prCmd) +{ +/* dumpMemory8(ANDROID_LOG_INFO, pCmdBuf, u4BufLen); */ + + prCmd->ucFmeType = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); + prCmd->ucToken = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); + prCmd->u2Cap = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); + prCmd->ucExCap = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); + prCmd->arSupRate[0] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); + prCmd->arSupRate[1] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); + prCmd->arSupRate[2] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); + prCmd->arSupRate[3] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); + prCmd->arSupChan[0] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); + prCmd->arSupChan[1] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); + prCmd->arSupChan[2] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); + prCmd->arSupChan[3] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); + prCmd->u4Timeout = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); + CmdStringMacParse(pCmdBuf, &pCmdBuf, &u4BufLen, prCmd->arRspAddr); + + DBGLOG(TDLS, INFO, " command content =\n"); + DBGLOG(TDLS, INFO, "\tPeer MAC = %pM\n", (prCmd->arRspAddr)); + DBGLOG(TDLS, INFO, "\tToken = %u, Cap = 0x%x, ExCap = 0x%x, Timeout = %us FrameType = %u\n", + (UINT32) prCmd->ucToken, prCmd->u2Cap, prCmd->ucExCap, + (UINT32) prCmd->u4Timeout, (UINT32) prCmd->ucFmeType); + DBGLOG(TDLS, INFO, "\tSupRate = 0x%x %x %x %x\n", + prCmd->arSupRate[0], prCmd->arSupRate[1], prCmd->arSupRate[2], prCmd->arSupRate[3]); + DBGLOG(TDLS, INFO, "\tSupChan = %d %d %d %d\n", + prCmd->arSupChan[0], prCmd->arSupChan[1], prCmd->arSupChan[2], prCmd->arSupChan[3]); + + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to update a TDLS peer. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_3_[Responder MAC] + + iwpriv wlan0 set_str_cmd 0_3_00:11:22:33:44:01 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestUpdatePeer(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + PARAM_CUSTOM_TDLS_CMD_STRUCT_T rCmd; + struct wireless_dev *prWdev; + + /* reset */ + kalMemZero(&rCmd, sizeof(rCmd)); + + /* parse arguments */ + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.arRspAddr); + + /* init */ + rCmd.rPeerInfo.supported_rates = rCmd.arSupRate; + rCmd.rPeerInfo.ht_capa = &rCmd.rHtCapa; + rCmd.rPeerInfo.vht_capa = &rCmd.rVhtCapa; /* LINUX_KERNEL_VERSION >= 3.10.0 */ + rCmd.rPeerInfo.sta_flags_set = BIT(NL80211_STA_FLAG_TDLS_PEER); + rCmd.rPeerInfo.uapsd_queues = 0xf; /* all AC */ + rCmd.rPeerInfo.max_sp = 0; /* delivery all packets */ + + /* send command to wifi task to handle */ + prWdev = prGlueInfo->prDevHandler->ieee80211_ptr; + mtk_cfg80211_add_station(prWdev->wiphy, (void *)0x1, rCmd.arRspAddr, &rCmd.rPeerInfo); + + /* update */ + TdlsexCfg80211TdlsOper(prWdev->wiphy, (void *)0x1, rCmd.arRspAddr, NL80211_TDLS_ENABLE_LINK); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a Null frame from the peer. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +* EX: iwpriv wlan0 set_str_cmd 0_5_[Responder MAC]_[PM bit] + + iwpriv wlan0 set_str_cmd 0_5_00:11:22:33:44:01_1 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestNullRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac); + rCmd.Content.rCmdNullRcv.u4PM = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s: [%pM] u4PM = %u\n", + __func__, (rCmd.aucPeerMac), (UINT32) rCmd.Content.rCmdNullRcv.u4PM); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsTestNullRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to send a data frame to the peer periodically. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] u4Param no use +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_15_[Responder MAC]_[Interval: ms]_[Enable/Disable] + + iwpriv wlan0 set_str_cmd 0_15_00:11:22:33:44:01_5000_1 +*/ +/*----------------------------------------------------------------------------*/ +static VOID TdlsTimerTestDataContSend(ADAPTER_T *prAdapter, UINT_32 u4Param) +{ + GLUE_INFO_T *prGlueInfo; + struct sk_buff *prMsduInfo; + UINT_8 *prPkt; + + /* init */ + prGlueInfo = prAdapter->prGlueInfo; + + /* allocate a data frame */ + prMsduInfo = kalPacketAlloc(prGlueInfo, 1000, &prPkt); + if (prMsduInfo == NULL) { + DBGLOG(TDLS, ERROR, " %s allocate pkt fail!\n", __func__); + return; + } + + /* init dev */ + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + DBGLOG(TDLS, ERROR, " %s prMsduInfo->dev == NULL!\n", __func__); + kalPacketFree(prGlueInfo, prMsduInfo); + return; + } + + /* init packet */ + prMsduInfo->len = 1000; + kalMemCopy(prMsduInfo->data, aucTdlsTestDataSPeerMac, 6); + kalMemCopy(prMsduInfo->data + 6, prAdapter->rMyMacAddr, 6); + *(UINT_16 *) (prMsduInfo->data + 12) = 0x0800; + + DBGLOG(TDLS, INFO, " %s try to send a data frame to %pM\n", + __func__, aucTdlsTestDataSPeerMac); + + /* simulate OS to send the packet */ + wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); + + /* restart test timer */ + cnmTimerStartTimer(prAdapter, &rTdlsTimerTestDataSend, u2TdlsTestDataSInterval); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a Channel Switch Request frame. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestChStReqRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_TEST_CHSW_REQ; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a Channel Switch Response frame. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestChStRspRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_TEST_CHSW_RSP; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to send a test frame. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestFrameSend(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + GLUE_INFO_T *prGlueInfo; + PARAM_CUSTOM_TDLS_CMD_STRUCT_T *prCmd; + P_BSS_INFO_T prBssInfo; + struct sk_buff *prMsduInfo; + UINT_8 *pPkt; + UINT_32 u4PktLen, u4IeLen; + + /* sanity check */ + if (!prAdapter || !pvSetBuffer || !pu4SetInfoLen) + return TDLS_STATUS_FAILURE; + + DBGLOG(TDLS, INFO, " %s\n", __func__); + + if (u4SetBufferLen == 0) + return TDLS_STATUS_INVALID_LENGTH; + + /* allocate/init packet */ + prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; + prCmd = (PARAM_CUSTOM_TDLS_CMD_STRUCT_T *) pvSetBuffer; + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + *pu4SetInfoLen = u4SetBufferLen; + u4PktLen = 0; + + prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); + if (prMsduInfo == NULL) { + DBGLOG(TDLS, ERROR, " %s: allocate pkt fail\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + DBGLOG(TDLS, ERROR, " %s: MsduInfo->dev == NULL\n", __func__); + kalPacketFree(prGlueInfo, prMsduInfo); + return TDLS_STATUS_FAILURE; + } + + /* make up frame content */ + /* 1. 802.3 header */ + kalMemCopy(pPkt, prCmd->arRspAddr, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); + LR_TDLS_FME_FIELD_FILL(2); + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (1) Category */ + *pPkt = TDLS_FRM_CATEGORY; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (2) Action */ + *pPkt = prCmd->ucFmeType; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (3) Dialog token */ + *pPkt = prCmd->ucToken; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (4) Capability */ + WLAN_SET_FIELD_16(pPkt, prCmd->u2Cap); + LR_TDLS_FME_FIELD_FILL(2); + + /* 4. Append general IEs */ + u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, NULL, 0, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3. Frame Formation - (10) Extended capabilities element */ + EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP; + EXT_CAP_IE(pPkt)->ucLength = 5; + + EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */ + EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */ + EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */ + + if (prCmd->ucExCap & TDLS_EX_CAP_PEER_UAPSD) + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24)); + if (prCmd->ucExCap & TDLS_EX_CAP_CHAN_SWITCH) + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24)); + if (prCmd->ucExCap & TDLS_EX_CAP_TDLS) + EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32)); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3. Frame Formation - (12) Timeout interval element (TPK Key Lifetime) */ + TIMEOUT_INTERVAL_IE(pPkt)->ucId = ELEM_ID_TIMEOUT_INTERVAL; + TIMEOUT_INTERVAL_IE(pPkt)->ucLength = 5; + + TIMEOUT_INTERVAL_IE(pPkt)->ucType = IE_TIMEOUT_INTERVAL_TYPE_KEY_LIFETIME; + TIMEOUT_INTERVAL_IE(pPkt)->u4Value = htonl(prCmd->u4Timeout); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3. Frame Formation - (16) Link identifier element */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = ELEM_LEN_LINK_IDENTIFIER; + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, prAdapter->rMyMacAddr, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prCmd->arRspAddr, 6); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 4. Update packet length */ + prMsduInfo->len = u4PktLen; + dumpMemory8(prMsduInfo->data, u4PktLen); + + /* 5. send the data frame */ + wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a NULL frame. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestNullRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_TEST_NULL_RCV; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a PTI frame. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestPtiReqRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_TEST_PTI_REQ; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a PTI response frame. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestPtiRspRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_TEST_PTI_RSP; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a Tear Down frame. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestTearDownRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_TEST_TEAR_DOWN; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a data frame. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestDataRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_TEST_DATA_RCV; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to skip PTI tx fail status. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestPtiTxFail(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_TEST_PTI_TX_FAIL; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to send a TDLS action frame. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +* EX: iwpriv wlan0 set_str_cmd 0_12_0_[FrameType]_[DialogToken]_[Peer MAC] + + iwpriv wlan0 set_str_cmd 0_12_0_0_1_00:11:22:33:44:01 +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestTdlsFrameSend(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + GLUE_INFO_T *prGlueInfo; + PARAM_CUSTOM_TDLS_CMD_STRUCT_T *prCmd; + struct wireless_dev *prWdev; + + /* sanity check */ + if (!prAdapter || !pvSetBuffer || !pu4SetInfoLen) + return TDLS_STATUS_FAILURE; + + DBGLOG(TDLS, INFO, " %s\n", __func__); + + if (u4SetBufferLen == 0) + return TDLS_STATUS_INVALID_LENGTH; + + /* allocate/init packet */ + prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; + prCmd = (PARAM_CUSTOM_TDLS_CMD_STRUCT_T *) pvSetBuffer; + prWdev = (struct wireless_dev *)prGlueInfo->prDevHandler->ieee80211_ptr; + + TdlsexCfg80211TdlsMgmt(prWdev->wiphy, NULL, + prCmd->arRspAddr, prCmd->ucFmeType, 1, + 0, 0, /* open/none */ + FALSE, NULL, 0); + + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to skip tx fail status. So always success in tx done in firmware. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestTxFailSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_TEST_TX_FAIL_SKIP; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to skip to do keep alive function in firmware. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestKeepAliveSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_TEST_KEEP_ALIVE_SKIP; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to skip channel switch timeout. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestChSwTimeoutSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_TEST_CHSW_TIMEOUT_SKIP; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to skip scan request. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestScanSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_TEST_SCAN_SKIP; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +#endif /* TDLS_CFG_CMD_TEST */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to configure channel switch parameters. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsChSwConf(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_CHSW_CONF; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to update channel switch parameters. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_9_[TDLS Peer MAC]_ + [NetworkTypeIndex]_[1 (Enable) or (0) Disable]_[1 (Start) or 0 (Stop)]_ + [RegClass]_[Chan]_[SecChanOff]_[1 (Reqular) or (0) One Shot] + + RegulatoryClass: TODO (reference to Annex I of 802.11n spec.) + Secondary Channel Offset: 0 (SCN - no secondary channel) + 1 (SCA - secondary channel above) + 2 (SCB - secondary channel below) + SwitchTime: units of microseconds + + iwpriv wlan0 set_str_cmd 0_9_00:11:22:33:44:01_0_1_0_0_1_0_0 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdChSwConf(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac); + + rCmd.Content.rCmdChSwConf.ucNetTypeIndex = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdChSwConf.fgIsChSwEnabled = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdChSwConf.fgIsChSwStarted = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdChSwConf.ucRegClass = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdChSwConf.ucTargetChan = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdChSwConf.ucSecChanOff = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdChSwConf.fgIsChSwRegular = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s: %pM ucNetTypeIndex=%d, fgIsChSwEnabled=%d, fgIsChSwStarted=%d", + __func__, (rCmd.aucPeerMac), + rCmd.Content.rCmdChSwConf.ucNetTypeIndex, + rCmd.Content.rCmdChSwConf.fgIsChSwEnabled, + rCmd.Content.rCmdChSwConf.fgIsChSwStarted); + DBGLOG(TDLS, INFO, " RegClass=%d, TargetChan=%d, SecChanOff=%d, Regular=%d\n", + rCmd.Content.rCmdChSwConf.ucRegClass, + rCmd.Content.rCmdChSwConf.ucTargetChan, + rCmd.Content.rCmdChSwConf.ucSecChanOff, rCmd.Content.rCmdChSwConf.fgIsChSwRegular); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsChSwConf, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to display TDLS related information. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_18_[Peer MAC]_[Network Interface ID]_[IsClear] + + Network Interface ID: reference to ENUM_NETWORK_TYPE_INDEX_T + + typedef enum _ENUM_NETWORK_TYPE_INDEX_T { + NETWORK_TYPE_AIS_INDEX = 0, + NETWORK_TYPE_P2P_INDEX, + NETWORK_TYPE_BOW_INDEX, + NETWORK_TYPE_INDEX_NUM + } ENUM_NETWORK_TYPE_INDEX_T; + + iwpriv wlan0 set_str_cmd 0_18_00:00:00:00:00:00_0_0 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdInfoDisplay(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + kalMemZero(&rCmd, sizeof(rCmd)); + + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac); + rCmd.ucNetTypeIndex = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdInfoDisplay.fgIsToClearAllHistory = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, " %s: Command PeerMac=%pM in BSS%u\n", + __func__, (rCmd.aucPeerMac), rCmd.ucNetTypeIndex); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsInfoDisplay, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to display key related information. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_20 + + iwpriv wlan0 set_str_cmd 0_20 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdKeyInfoDisplay(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + kalMemZero(&rCmd, sizeof(rCmd)); + + DBGLOG(TDLS, INFO, " %s\n", __func__); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsKeyInfoDisplay, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to update MIB parameters. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_6_[TdlsEn]_[UapsdEn]_[PsmEn]_[PtiWin]_[CWCap]_ + [AckMisRetry]_[RspTimeout]_[CWPbDelay]_[DRWin]_[LowestAcInt] + + iwpriv wlan0 set_str_cmd 0_6_1_1_0_1_1_3_5_1000_2_1 + + reference to TDLS_CMD_CORE_MIB_PARAM_UPDATE_T +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdMibParamUpdate(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* reset */ + kalMemZero(&rCmd, sizeof(rCmd)); + + /* parse arguments */ + rCmd.Content.rCmdMibUpdate.Tdlsdot11TunneledDirectLinkSetupImplemented = + CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerUAPSDBufferSTAActivated = + CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerPSMActivated = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerUAPSDIndicationWindow = + CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSChannelSwitchingActivated = + CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerSTAMissingAckRetryLimit = + CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSResponseTimeout = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSProbeDelay = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSDiscoveryRequestWindow = + CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSACDeterminationInterval = + CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, " MIB param = %d %d %d %d %d %d %d %d %d %d\n", + rCmd.Content.rCmdMibUpdate.Tdlsdot11TunneledDirectLinkSetupImplemented, + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerUAPSDBufferSTAActivated, + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerPSMActivated, + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerUAPSDIndicationWindow, + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSChannelSwitchingActivated, + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerSTAMissingAckRetryLimit, + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSResponseTimeout, + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSProbeDelay, + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSDiscoveryRequestWindow, + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSACDeterminationInterval); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsMibParamUpdate, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to update setup parameters. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_17_[20/40 Support] + + iwpriv wlan0 set_str_cmd 0_17_1 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdSetupConf(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); + + rCmd.Content.rCmdSetupConf.fgIs2040Supported = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s: rCmdSetupConf=%d\n", __func__, rCmd.Content.rCmdSetupConf.fgIs2040Supported); + + /* command to do this */ + prGlueInfo->rTdlsLink.fgIs2040Sup = rCmd.Content.rCmdSetupConf.fgIs2040Supported; + + rStatus = kalIoctl(prGlueInfo, TdlsSetupConf, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to update UAPSD parameters. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_8_[SP timeout skip]_[PTI timeout skip] + + iwpriv wlan0 set_str_cmd 0_8_1_1 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdUapsdConf(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); + + /* UAPSD Service Period */ + rCmd.Content.rCmdUapsdConf.fgIsSpTimeoutSkip = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdUapsdConf.fgIsPtiTimeoutSkip = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + /* PTI Service Period */ + fgIsPtiTimeoutSkip = rCmd.Content.rCmdUapsdConf.fgIsPtiTimeoutSkip; + + DBGLOG(TDLS, INFO, "%s: fgIsSpTimeoutSkip=%d, fgIsPtiTimeoutSkip=%d\n", + __func__, rCmd.Content.rCmdUapsdConf.fgIsSpTimeoutSkip, fgIsPtiTimeoutSkip); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsUapsdConf, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to display TDLS all information. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +* iwpriv wlan0 set_str_cmd 0_18_00:00:00:00:00:00_0_0 +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsInfoDisplay(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + GLUE_INFO_T *prGlueInfo; + TDLS_CMD_CORE_T *prCmdContent; + STA_RECORD_T *prStaRec; + TDLS_INFO_LINK_T *prLink; + UINT32 u4StartIdx; + UINT32 u4PeerNum; + BOOLEAN fgIsListAll; + UINT8 ucMacZero[6]; + UINT32 u4HisIdx; + UINT8 ucNetTypeIndex; + + /* init */ + prGlueInfo = prAdapter->prGlueInfo; + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + u4StartIdx = 0; + u4PeerNum = 1; + fgIsListAll = TRUE; + kalMemZero(ucMacZero, sizeof(ucMacZero)); + ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + + /* display common information */ + DBGLOG(TDLS, TRACE, "TDLS common:\n"); + DBGLOG(TDLS, TRACE, "\t\trFreeSwRfbList=%u\n", (UINT32) prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem); + DBGLOG(TDLS, TRACE, "\t\tjiffies=%u %ums (HZ=%d)\n", (UINT32) jiffies, (UINT32) kalGetTimeTick(), HZ); + + /* display disconnection history information */ + DBGLOG(TDLS, TRACE, "TDLS link history: %d\n", prGlueInfo->rTdlsLink.u4LinkIdx); + + for (u4HisIdx = prGlueInfo->rTdlsLink.u4LinkIdx + 1; u4HisIdx < TDLS_LINK_HISTORY_MAX; u4HisIdx++) { + prLink = &prGlueInfo->rTdlsLink.rLinkHistory[u4HisIdx]; + + if (kalMemCmp(prLink->aucPeerMac, ucMacZero, 6) == 0) + continue; /* skip all zero */ + + DBGLOG(TDLS, TRACE, + "\t\t%d. %pM jiffies start(%lu %ums)end(%lu %ums)Reason(%u)fromUs(%u)Dup(%u)HT(%u)\n", + u4HisIdx, prLink->aucPeerMac, + prLink->jiffies_start, jiffies_to_msecs(prLink->jiffies_start), + prLink->jiffies_end, jiffies_to_msecs(prLink->jiffies_end), + prLink->ucReasonCode, + prLink->fgIsFromUs, prLink->ucDupCount, (prLink->ucHtCap & TDLS_INFO_LINK_HT_CAP_SUP)); + + if (prLink->ucHtCap & TDLS_INFO_LINK_HT_CAP_SUP) { + DBGLOG(TDLS, TRACE, + "\t\t\tBA (0x%x %x %x %x %x %x %x %x)\n", + prLink->ucHtBa[0], prLink->ucHtBa[1], + prLink->ucHtBa[2], prLink->ucHtBa[3], + prLink->ucHtBa[4], prLink->ucHtBa[5], prLink->ucHtBa[6], prLink->ucHtBa[7]); + } + } + for (u4HisIdx = 0; u4HisIdx <= prGlueInfo->rTdlsLink.u4LinkIdx; u4HisIdx++) { + prLink = &prGlueInfo->rTdlsLink.rLinkHistory[u4HisIdx]; + + if (kalMemCmp(prLink->aucPeerMac, ucMacZero, 6) == 0) + continue; /* skip all zero, use continue, not break */ + + DBGLOG(TDLS, TRACE, + "\t\t%d. %pM jiffies start(%lu %ums)end(%lu %ums)Reason(%u)fromUs(%u)Dup(%u)HT(%u)\n", + u4HisIdx, (prLink->aucPeerMac), + prLink->jiffies_start, jiffies_to_msecs(prLink->jiffies_start), + prLink->jiffies_end, jiffies_to_msecs(prLink->jiffies_end), + prLink->ucReasonCode, + prLink->fgIsFromUs, prLink->ucDupCount, (prLink->ucHtCap & TDLS_INFO_LINK_HT_CAP_SUP)); + + if (prLink->ucHtCap & TDLS_INFO_LINK_HT_CAP_SUP) { + DBGLOG(TDLS, TRACE, + "\t\t\tBA (0x%x %x %x %x %x %x %x %x)\n", + prLink->ucHtBa[0], prLink->ucHtBa[1], + prLink->ucHtBa[2], prLink->ucHtBa[3], + prLink->ucHtBa[4], prLink->ucHtBa[5], prLink->ucHtBa[6], prLink->ucHtBa[7]); + } + } + DBGLOG(TDLS, TRACE, "\n"); + + /* display link information */ + if (prCmdContent != NULL) { + if (kalMemCmp(prCmdContent->aucPeerMac, ucMacZero, 6) != 0) { + prStaRec = cnmGetStaRecByAddress(prAdapter, + prCmdContent->ucNetTypeIndex, prCmdContent->aucPeerMac); + if (prStaRec == NULL) + fgIsListAll = TRUE; + else + fgIsListAll = FALSE; + } + + ucNetTypeIndex = prCmdContent->ucNetTypeIndex; + } + + while (1) { + if (fgIsListAll == TRUE) { + /* list all TDLS peers */ + prStaRec = cnmStaTheTypeGet(prAdapter, ucNetTypeIndex, STA_TYPE_TDLS_PEER, &u4StartIdx); + if (prStaRec == NULL) + break; + } + + DBGLOG(TDLS, TRACE, "-------- TDLS %d: 0x %pM\n", u4PeerNum, (prStaRec->aucMacAddr)); + DBGLOG(TDLS, TRACE, "\t\t\t State %d, PM %d, Cap 0x%x\n", + prStaRec->ucStaState, prStaRec->fgIsInPS, prStaRec->u2CapInfo); + DBGLOG(TDLS, TRACE, "\t\t\t SetupDisable %d, ChSwDisable %d\n", + prStaRec->fgTdlsIsProhibited, prStaRec->fgTdlsIsChSwProhibited); + + if (fgIsListAll == FALSE) + break; /* only list one */ + } + + /* check if we need to clear all histories */ + if ((prCmdContent != NULL) && (prCmdContent->Content.rCmdInfoDisplay.fgIsToClearAllHistory == TRUE)) { + kalMemZero(&prGlueInfo->rTdlsLink, sizeof(prGlueInfo->rTdlsLink)); + prGlueInfo->rTdlsLink.u4LinkIdx = TDLS_LINK_HISTORY_MAX - 1; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to display key information. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsKeyInfoDisplay(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_KEY_INFO; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to record a disconnection event. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure +* \param[in] fgIsTearDown TRUE: the link is torn down +* \param[in] pucPeerMac Pointer to the MAC of the TDLS peer +* \param[in] fgIsFromUs TRUE: tear down is from us +* \param[in] u2ReasonCode Disconnection reason (TDLS_REASON_CODE) +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +static VOID +TdlsLinkHistoryRecord(GLUE_INFO_T *prGlueInfo, + BOOLEAN fgIsTearDown, + UINT8 *pucPeerMac, BOOLEAN fgIsFromUs, UINT16 u2ReasonCode, VOID *prOthers) +{ + TDLS_INFO_LINK_T *prLink; + + DBGLOG(TDLS, INFO, + " %s: record history for %pM %d %d %d %d\n", + __func__, pucPeerMac, prGlueInfo->rTdlsLink.u4LinkIdx, + fgIsTearDown, fgIsFromUs, u2ReasonCode); + + /* check duplicate one */ + if (prGlueInfo->rTdlsLink.u4LinkIdx >= TDLS_LINK_HISTORY_MAX) { + DBGLOG(TDLS, ERROR, " %s: u4LinkIdx >= TDLS_LINK_HISTORY_MAX\n", __func__); + + /* reset to 0 */ + prGlueInfo->rTdlsLink.u4LinkIdx = 0; + } + + prLink = &prGlueInfo->rTdlsLink.rLinkHistory[prGlueInfo->rTdlsLink.u4LinkIdx]; + + if (kalMemCmp(&prLink->aucPeerMac, pucPeerMac, 6) == 0) { + if ((prLink->ucReasonCode == u2ReasonCode) && (prLink->fgIsFromUs == fgIsFromUs)) { + /* same Peer MAC, Reason Code, Trigger source */ + if (fgIsTearDown == TRUE) { + if (prLink->jiffies_end != 0) { + /* already torn down */ + prLink->ucDupCount++; + return; + } + } else { + /* already built */ + prLink->ucDupCount++; + return; + } + } + } + + /* search old entry */ + if (fgIsTearDown == TRUE) { + /* TODO: need to search all entries to find it if we support multiple TDLS link design */ + if (kalMemCmp(&prLink->aucPeerMac, pucPeerMac, 6) != 0) { + /* error! can not find the link entry */ + DBGLOG(TDLS, INFO, " %s: cannot find the same entry!!!\n", __func__); + return; + } + + prLink->jiffies_end = jiffies; + prLink->ucReasonCode = (UINT8) u2ReasonCode; + prLink->fgIsFromUs = fgIsFromUs; + } else { + /* record new one */ + prGlueInfo->rTdlsLink.u4LinkIdx++; + if (prGlueInfo->rTdlsLink.u4LinkIdx >= TDLS_LINK_HISTORY_MAX) + prGlueInfo->rTdlsLink.u4LinkIdx = 0; + + prLink = &prGlueInfo->rTdlsLink.rLinkHistory[prGlueInfo->rTdlsLink.u4LinkIdx]; + + prLink->jiffies_start = jiffies; + prLink->jiffies_end = 0; + kalMemCopy(&prLink->aucPeerMac, pucPeerMac, 6); + prLink->ucReasonCode = 0; + prLink->fgIsFromUs = (UINT8) fgIsFromUs; + prLink->ucDupCount = 0; + + if (prOthers != NULL) { + /* record other parameters */ + TDLS_LINK_HIS_OTHERS_T *prHisOthers; + + prHisOthers = (TDLS_LINK_HIS_OTHERS_T *) prOthers; + if (prHisOthers->fgIsHt == TRUE) + prLink->ucHtCap |= TDLS_INFO_LINK_HT_CAP_SUP; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to update a disconnection event. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure +* \param[in] pucPeerMac Pointer to the MAC of the TDLS peer +* \param[in] eFmeStatus TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME +* \param[in] pInfo other information +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +static VOID +TdlsLinkHistoryRecordUpdate(GLUE_INFO_T *prGlueInfo, + UINT8 *pucPeerMac, TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME eFmeStatus, VOID *pInfo) +{ + TDLS_INFO_LINK_T *prLink; + UINT32 u4LinkIdx; + UINT32 u4Tid; + + /* sanity check */ + if ((eFmeStatus < TDLS_HOST_EVENT_SF_BA) || (eFmeStatus > TDLS_HOST_EVENT_SF_BA_RSP_DECLINE)) { + /* do not care these frames */ + return; + } + + DBGLOG(TDLS, INFO, + " %s: update history for %pM %d %d\n", + __func__, (pucPeerMac), prGlueInfo->rTdlsLink.u4LinkIdx, eFmeStatus); + + /* init */ + u4LinkIdx = prGlueInfo->rTdlsLink.u4LinkIdx; + prLink = &prGlueInfo->rTdlsLink.rLinkHistory[u4LinkIdx]; + + /* TODO: need to search all entries to find it if we support multiple TDLS link design */ + if (kalMemCmp(&prLink->aucPeerMac, pucPeerMac, 6) != 0) { + /* error! can not find the link entry */ + DBGLOG(TDLS, INFO, " %s: cannot find the same entry!!!\n", __func__); + return; + } + + /* update */ + u4Tid = *(UINT32 *) pInfo; + switch (eFmeStatus) { + case TDLS_HOST_EVENT_SF_BA: + prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_SETUP; + break; + + case TDLS_HOST_EVENT_SF_BA_OK: + prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_SETUP_OK; + break; + + case TDLS_HOST_EVENT_SF_BA_DECLINE: + prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_SETUP_DECLINE; + break; + + case TDLS_HOST_EVENT_SF_BA_PEER: + prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_PEER; + break; + + case TDLS_HOST_EVENT_SF_BA_RSP_OK: + prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_RSP_OK; + break; + + case TDLS_HOST_EVENT_SF_BA_RSP_DECLINE: + prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_RSP_DECLINE; + break; + } + + /* display TDLS link history */ + TdlsInfoDisplay(prGlueInfo->prAdapter, NULL, 0, NULL); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to configure TDLS MIB parameters. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsMibParamUpdate(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_MIB_UPDATE; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to configure TDLS SETUP parameters. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsSetupConf(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_SETUP_CONF; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +TDLS_STATUS +TdlsexEnableDisableLink(ADAPTER_T *prAdapter, + PUINT_8 pucPeerMacAddr, + BOOLEAN fgEnable, + ENUM_NETWORK_TYPE_INDEX_T eNetworkType) +{ + + STA_RECORD_T *prStaRec; + TDLS_LINK_HIS_OTHERS_T rHisOthers; + UINT_32 u4BufLen; /* no use */ + GLUE_INFO_T *prGlueInfo; + BSS_INFO_T *prBssInfo; + + if (!prAdapter || !prAdapter->prGlueInfo) + return TDLS_STATUS_FAILURE; + + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8)eNetworkType, pucPeerMacAddr); + + if (prStaRec == NULL) { + DBGLOG(TDLS, ERROR, "Cannot find the peer! %pM\n", pucPeerMacAddr); + return TDLS_STATUS_FAILURE; + } + + prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; + + DBGLOG(TDLS, INFO, "STA_INDEX: %d, %s\n", prStaRec->ucIndex, + fgEnable ? "NL80211_TDLS_ENABLE_LINK" : "NL80211_TDLS_DISABLE_LINK"); + + if (fgEnable) { + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + /* update key information after cnmStaRecChangeState(STA_STATE_3) */ + prStaRec->fgTdlsInSecurityMode = FALSE; + + if (prStaRec->rTdlsKeyTemp.u4Length <= 0) + DBGLOG(TDLS, INFO, "Empty Key, key length = 0\n"); + else { + DBGLOG_MEM8(TDLS, TRACE, prStaRec->rTdlsKeyTemp.aucKeyMaterial, + prStaRec->rTdlsKeyTemp.u4KeyLength); + + /* + * reminder the function that we are CIPHER_SUITE_CCMP, + * do not change cipher type to CIPHER_SUITE_WEP128 + */ + eNetworkType == NETWORK_TYPE_AIS_INDEX ? + _wlanoidSetAddKey(prAdapter, &prStaRec->rTdlsKeyTemp, + prStaRec->rTdlsKeyTemp.u4Length, FALSE, CIPHER_SUITE_CCMP, &u4BufLen) : + _wlanoidSetAddP2PTDLSKey(prAdapter, &prStaRec->rTdlsKeyTemp, + prStaRec->rTdlsKeyTemp.u4Length, &u4BufLen); + + /* clear the temp key */ + prStaRec->fgTdlsInSecurityMode = TRUE; + kalMemZero(&prStaRec->rTdlsKeyTemp, sizeof(prStaRec->rTdlsKeyTemp)); + } + + /* check if we need to disable channel switch function */ + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + if (prBssInfo->fgTdlsIsChSwProhibited == TRUE) { + TDLS_CMD_CORE_T rCmd; + + kalMemZero(&rCmd, sizeof(TDLS_CMD_CORE_T)); + rCmd.Content.rCmdChSwConf.ucNetTypeIndex = prStaRec->ucNetTypeIndex; + rCmd.Content.rCmdChSwConf.fgIsChSwEnabled = FALSE; + kalMemCopy(rCmd.aucPeerMac, prStaRec->aucMacAddr, 6); + TdlsChSwConf(prAdapter, &rCmd, 0, 0); + + DBGLOG(TDLS, INFO, " %s: disable channel switch\n", __func__); + } + + TDLS_LINK_INCREASE(prGlueInfo); + + /* record link */ + if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11N) + rHisOthers.fgIsHt = TRUE; + else + rHisOthers.fgIsHt = FALSE; + + TdlsLinkHistoryRecord(prAdapter->prGlueInfo, FALSE, + prStaRec->aucMacAddr, !prStaRec->flgTdlsIsInitiator, 0, &rHisOthers); + + return TDLS_STATUS_SUCCESS; + } + + /* Disable TDLS link */ + prGlueInfo->i4TdlsLastTx = -1; + prGlueInfo->eTdlsStatus = MTK_TDLS_LINK_DISABLE; + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + cnmStaRecFree(prAdapter, prStaRec, TRUE); /* release to other TDLS peers */ + + TDLS_LINK_DECREASE(prGlueInfo); + + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to configure UAPSD parameters. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsUapsdConf(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_UAPSD_CONF; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to update frame status. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsEventFmeStatus(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen) +{ + TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME eFmeStatus; + STA_RECORD_T *prStaRec; + UINT32 u4Tid; + + /* init */ + u4Tid = *(UINT32 *) prInBuf; + prInBuf += 4; /* skip u4EventSubId */ + + /* sanity check */ + prStaRec = cnmGetStaRecByIndex(prGlueInfo->prAdapter, *prInBuf); + if ((prStaRec == NULL) || (!IS_TDLS_STA(prStaRec))) + return; + prInBuf++; + + /* update status */ + eFmeStatus = *prInBuf; + TdlsLinkHistoryRecordUpdate(prGlueInfo, prStaRec->aucMacAddr, eFmeStatus, &u4Tid); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to collect TDLS statistics from firmware. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsEventStatistics(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen) +{ + STA_RECORD_T *prStaRec; + STAT_CNT_INFO_FW_T *prStat; + UINT32 u4RateId; + + /* init */ + prStaRec = cnmGetStaRecByIndex(prGlueInfo->prAdapter, *prInBuf); + if ((prStaRec == NULL) || (!IS_TDLS_STA(prStaRec))) + return; + + prInBuf += 4; /* skip prStaRec->ucIndex */ + + /* update statistics */ + kalMemCopy(&prStaRec->rTdlsStatistics.rFw, prInBuf, sizeof(prStaRec->rTdlsStatistics.rFw)); + + /* display statistics */ + prStat = &prStaRec->rTdlsStatistics.rFw; + + DBGLOG(TDLS, TRACE, " peer [%pM] statistics:\n", (prStaRec->aucMacAddr)); + DBGLOG(TDLS, TRACE, "\t\tT%d %d %d (P%d %d) (%dus) - E%d 0x%x - R%d (P%d)\n", + prStat->u4NumOfTx, prStat->u4NumOfTxOK, prStat->u4NumOfTxRetry, + prStat->u4NumOfPtiRspTxOk, prStat->u4NumOfPtiRspTxErr, + prStat->u4TxDoneAirTimeMax, + prStat->u4NumOfTxErr, prStat->u4TxErrBitmap, prStat->u4NumOfRx, prStat->u4NumOfPtiRspRx); + + DBGLOG(TDLS, TRACE, "\t\t"); + + for (u4RateId = prStat->u4TxRateOkHisId; u4RateId < STAT_CNT_INFO_MAX_TX_RATE_OK_HIS_NUM; u4RateId++) + DBGLOG(TDLS, TRACE, + "%d(%d) ", prStat->aucTxRateOkHis[u4RateId][0], prStat->aucTxRateOkHis[u4RateId][1]); + for (u4RateId = 0; u4RateId < prStat->u4TxRateOkHisId; u4RateId++) + DBGLOG(TDLS, TRACE, + "%d(%d) ", prStat->aucTxRateOkHis[u4RateId][0], prStat->aucTxRateOkHis[u4RateId][1]); + + DBGLOG(TDLS, TRACE, "\n\n"); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to do tear down. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsEventTearDown(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen) +{ + STA_RECORD_T *prStaRec; + UINT16 u2ReasonCode; + UINT32 u4TearDownSubId; + UINT8 *pMac, aucZeroMac[6]; + + /* init */ + u4TearDownSubId = *(UINT32 *) prInBuf; + kalMemZero(aucZeroMac, sizeof(aucZeroMac)); + pMac = aucZeroMac; + + prStaRec = cnmGetStaRecByIndex(prGlueInfo->prAdapter, *(prInBuf + 4)); + if (prStaRec != NULL) + pMac = prStaRec->aucMacAddr; + + /* handle */ + if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_TIMEOUT) { + DBGLOG(TDLS, WARN, " %s: peer [%pM] Reason=PTI timeout\n", + __func__, pMac); + } else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_AGE_TIMEOUT) { + DBGLOG(TDLS, WARN, " %s: peer [%pM] Reason=AGE timeout\n", + __func__, pMac); + } else { + DBGLOG(TDLS, WARN, " %s: peer [%pM] Reason=%d\n", + __func__, pMac, u4TearDownSubId); + } + + /* sanity check */ + if (prStaRec == NULL) + return; + + if (fgIsPtiTimeoutSkip == TRUE) { + /* skip PTI timeout event */ + if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_TIMEOUT) { + DBGLOG(TDLS, WARN, " %s: skip PTI timeout\n", __func__); + return; + } + } + + /* record history */ + if (u4TearDownSubId == TDLS_HOST_EVENT_TD_AGE_TIMEOUT) + u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_AGE_TIMEOUT; + else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_TIMEOUT) + u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_TIMEOUT; + else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_SEND_FAIL) + u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_SEND_FAIL; + else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_SEND_MAX_FAIL) + u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_SEND_MAX_FAIL; + else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_WRONG_NETWORK_IDX) + u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_WRONG_NETWORK_IDX; + else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_NON_STATE3) + u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_NON_STATE3; + else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_LOST_TEAR_DOWN) + u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_LOST_TEAR_DOWN; + else { + /* shall not be here */ + u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_UNKNOWN; + } + + TdlsLinkHistoryRecord(prGlueInfo, TRUE, prStaRec->aucMacAddr, TRUE, u2ReasonCode, NULL); + + /* correct correct reason code for PTI or AGE timeout to supplicant */ + if ((u2ReasonCode == TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_AGE_TIMEOUT) || + (u2ReasonCode == TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_TIMEOUT)) { + u2ReasonCode = TDLS_REASON_CODE_UNREACHABLE; + } + + /* 16 Nov 21:49 2012 http://permalink.gmane.org/gmane.linux.kernel.wireless.general/99712 */ + cfg80211_tdls_oper_request(prStaRec->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX ? + prGlueInfo->prDevHandler : + prGlueInfo->prP2PInfo->prDevHandler, + prStaRec->aucMacAddr, NL80211_TDLS_TEARDOWN, u2ReasonCode, GFP_ATOMIC); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to do tx down. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsEventTxDone(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen) +{ + UINT8 *pucFmeHdr; + UINT8 ucErrStatus; + UINT32 u4HeaderLen; + TDLS_FRAME_HEADER_T *prTdlsHdr; + WLAN_MAC_HEADER_QOS_T *prQosHdr; + + ucErrStatus = *(UINT32 *) prInBuf; + + /* frame hearder including Qos MAC and LLC header */ + pucFmeHdr = prInBuf + 4; /* skip ucErrStatus */ + + u4HeaderLen = sizeof(WLAN_MAC_HEADER_QOS_T) + sizeof(LLC_SNAP_HEADER_T); + + /* dumpMemory8(pucFmeHdr, u4InBufLen - 4); */ + DBGLOG_MEM8(TDLS, TRACE, pucFmeHdr, u4InBufLen - 4); + + if (u4InBufLen - 4 < u4HeaderLen) { + DBGLOG(TDLS, WARN, "Invalid Tdls frame length\n"); + return; + } + + prTdlsHdr = (TDLS_FRAME_HEADER_T *)(pucFmeHdr + u4HeaderLen); + + if (prTdlsHdr->ucPayLoadType != TDLS_FRM_PAYLOAD_TYPE || + prTdlsHdr->ucCategory != TDLS_FRM_CATEGORY) { + DBGLOG(TDLS, WARN, "Invalid frame type:category 0x%x:0x%x\n", + prTdlsHdr->ucPayLoadType, prTdlsHdr->ucCategory); + return; + } + + if (ucErrStatus == 0) + DBGLOG(TDLS, INFO, "OK to tx a TDLS action: %d\n", prTdlsHdr->ucAction); + else + DBGLOG(TDLS, INFO, "Failed to tx a TDLS action: %d (err=0x%x)\n", + ucErrStatus, prTdlsHdr->ucAction); + /* + * from DS = 0 + * to DS = 1 + * addr1 = BSSID + * addr2 = TA = SA + * addr3 = DA + */ + /* enable link and set key only when confirm TX done successfully */ + if (prTdlsHdr->ucAction == TDLS_FRM_ACTION_CONFIRM && !ucErrStatus) { + prQosHdr = (WLAN_MAC_HEADER_QOS_T *)pucFmeHdr; + TdlsexEnableDisableLink(prGlueInfo->prAdapter, + prQosHdr->aucAddr3, + TRUE, + prGlueInfo->eTdlsNetworkType); + } +} + +/******************************************************************************* +* P U B L I C F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to parse TDLS Extended Capabilities element. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID TdlsexBssExtCapParse(STA_RECORD_T *prStaRec, UINT_8 *pucIE) +{ + UINT_8 *pucIeExtCap; + + /* sanity check */ + if ((prStaRec == NULL) || (pucIE == NULL)) + return; + + if (IE_ID(pucIE) != ELEM_ID_EXTENDED_CAP) + return; + + /* + * from bit0 ~ + * + * bit 38: TDLS Prohibited + * The TDLS Prohibited subfield indicates whether the use of TDLS is prohibited. The + * field is set to 1 to indicate that TDLS is prohibited and to 0 to indicate that TDLS is + * allowed. + */ + if (IE_LEN(pucIE) < 5) + return; /* we need 39/8 = 5 bytes */ + + /* init */ + prStaRec->fgTdlsIsProhibited = FALSE; + prStaRec->fgTdlsIsChSwProhibited = FALSE; + + /* parse */ + pucIeExtCap = pucIE + 2; + pucIeExtCap += 4; /* shift to the byte we care about */ + + if ((*pucIeExtCap) & BIT(38 - 32)) + prStaRec->fgTdlsIsProhibited = TRUE; + if ((*pucIeExtCap) & BIT(39 - 32)) + prStaRec->fgTdlsIsChSwProhibited = TRUE; + + DBGLOG(TDLS, TRACE, + " %s: AP [%pM] tdls prohibit bit=%d %d\n", + __func__, + prStaRec->aucMacAddr, prStaRec->fgTdlsIsProhibited, prStaRec->fgTdlsIsChSwProhibited); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to transmit a TDLS data frame from nl80211. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] +* \param[in] +* \param[in] buf includes RSN IE + FT IE + Lifetimeout IE +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +int +TdlsexCfg80211TdlsMgmt(struct wiphy *wiphy, struct net_device *dev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, + bool initiator, const u8 *buf, size_t len) +{ + ADAPTER_T *prAdapter; + GLUE_INFO_T *prGlueInfo; + ENUM_NETWORK_TYPE_INDEX_T eNetworkType; + BSS_INFO_T *prBssInfo; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + TDLS_MGMT_TX_INFO *prMgmtTxInfo; + + /* + * Have correct behavior for STAUT receiving TDLS Setup Request after sending TDLS + * Set Request and before receiving TDLS Setup Response: + * -- Source Address of received Request is higher than own MAC address + * -- Source Address of received Request is lower than own MAC address + * + * ==> STA with larger MAC address will send the response frame. + * + * Supplicant will do this in wpa_tdls_process_tpk_m1(). + */ + + /* sanity check */ + if ((wiphy == NULL) || (peer == NULL)) { + DBGLOG(TDLS, ERROR, " %s: wrong 0x%p 0x%p!\n", __func__, wiphy, peer); + return -EINVAL; + } + + DBGLOG(TDLS, INFO, " %s: [%pM] %d %d %d 0x%p %u\n", + __func__, peer, action_code, dialog_token, status_code, buf, (UINT32) len); + + /* init */ + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(dev)); + if (prGlueInfo == NULL) { + DBGLOG(TDLS, ERROR, " %s: wrong prGlueInfo 0x%p!\n", __func__, prGlueInfo); + return -EINVAL; + } + + prAdapter = prGlueInfo->prAdapter; + if (prAdapter->fgTdlsIsSup == FALSE) { + DBGLOG(TDLS, ERROR, " %s: firmware TDLS is not supported!\n", __func__); + return -EBUSY; + } + + eNetworkType = dev == prGlueInfo->prDevHandler ? + NETWORK_TYPE_AIS_INDEX : NETWORK_TYPE_P2P_INDEX; + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkType]); + if (prBssInfo->fgTdlsIsProhibited == TRUE) { + /* do not send anything if TDLS is prohibited in the BSS */ + DBGLOG(TDLS, INFO, "BSS prohibit TDLS operations\n"); + return 0; + } + + prMgmtTxInfo = kalMemAlloc(sizeof(TDLS_MGMT_TX_INFO), VIR_MEM_TYPE); + if (prMgmtTxInfo == NULL) { + DBGLOG(TDLS, ERROR, " %s: allocate fail!\n", __func__); + return -ENOMEM; + } + + kalMemZero(prMgmtTxInfo, sizeof(TDLS_MGMT_TX_INFO)); + + if (peer != NULL) + kalMemCopy(prMgmtTxInfo->aucPeer, peer, 6); + prMgmtTxInfo->eNetworkType = eNetworkType; + prMgmtTxInfo->ucActionCode = action_code; + prMgmtTxInfo->ucDialogToken = dialog_token; + prMgmtTxInfo->u2StatusCode = status_code; + + if (buf != NULL) { + if (len > sizeof(prMgmtTxInfo->aucSecBuf)) { + kalMemFree(prMgmtTxInfo, VIR_MEM_TYPE, sizeof(TDLS_MGMT_TX_INFO)); + return -EINVAL; + } + prMgmtTxInfo->u4SecBufLen = len; + kalMemCopy(prMgmtTxInfo->aucSecBuf, buf, len); + } + + /* send the TDLS action data frame */ + rStatus = kalIoctl(prGlueInfo, + TdlsexMgmtCtrl, + prMgmtTxInfo, sizeof(TDLS_MGMT_TX_INFO), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + /* + * clear all content to avoid any bug if we dont yet execute TdlsexMgmtCtrl() + * then kalIoctl finishes + */ + kalMemZero(prMgmtTxInfo, sizeof(TDLS_MGMT_TX_INFO)); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s enable or disable link fail:%x\n", __func__, rStatus); + kalMemFree(prMgmtTxInfo, VIR_MEM_TYPE, sizeof(TDLS_MGMT_TX_INFO)); + return -EINVAL; + } + + kalMemFree(prMgmtTxInfo, VIR_MEM_TYPE, sizeof(TDLS_MGMT_TX_INFO)); + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to enable or disable TDLS link from upper layer. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] +* \param[in] +* \param[in] buf includes RSN IE + FT IE + Lifetimeout IE +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +int TdlsexCfg80211TdlsOper(struct wiphy *wiphy, struct net_device *dev, + const u8 *peer, enum nl80211_tdls_operation oper) +{ + ADAPTER_T *prAdapter; + GLUE_INFO_T *prGlueInfo; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + TDLS_CMD_LINK_T rCmdLink; + + /* sanity check */ + if (peer == NULL) { + DBGLOG(TDLS, ERROR, " %s: peer == NULL!\n", __func__); + return -EINVAL; + } + + DBGLOG(TDLS, INFO, " %s: [%pM] %d %d\n", + __func__, peer, oper, (wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)); + + if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) + return -ENOTSUPP; + + /* init */ + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(dev)); + if (prGlueInfo == NULL) { + DBGLOG(TDLS, ERROR, " %s: wrong prGlueInfo 0x%p!\n", __func__, prGlueInfo); + return -EINVAL; + } + prAdapter = prGlueInfo->prAdapter; + kalMemCopy(rCmdLink.aucPeerMac, peer, sizeof(rCmdLink.aucPeerMac)); + rCmdLink.fgIsEnabled = FALSE; + rCmdLink.eNetworkType = dev == prGlueInfo->prDevHandler ? + NETWORK_TYPE_AIS_INDEX : NETWORK_TYPE_P2P_INDEX; + + /* + * enum nl80211_tdls_operation { + * NL80211_TDLS_DISCOVERY_REQ, + * NL80211_TDLS_SETUP, + * NL80211_TDLS_TEARDOWN, + * NL80211_TDLS_ENABLE_LINK, + * NL80211_TDLS_DISABLE_LINK, + * }; + */ + + switch (oper) { + case NL80211_TDLS_ENABLE_LINK: + rCmdLink.fgIsEnabled = TRUE; + break; + + case NL80211_TDLS_DISABLE_LINK: + rCmdLink.fgIsEnabled = FALSE; + break; + + case NL80211_TDLS_TEARDOWN: + case NL80211_TDLS_SETUP: + case NL80211_TDLS_DISCOVERY_REQ: + /* we do not support setup/teardown/discovery from driver */ + return -ENOTSUPP; + + default: + return -ENOTSUPP; + } + + /* enable or disable TDLS link */ + rStatus = kalIoctl(prGlueInfo, + TdlsexLinkCtrl, &rCmdLink, sizeof(TDLS_CMD_LINK_T), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s enable or disable link fail:%x\n", __func__, rStatus); + return -EINVAL; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to send a command to TDLS module. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID TdlsexCmd(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + UINT_32 u4Subcmd; + static void (*TdlsCmdTestFunc)(P_GLUE_INFO_T, UINT_8 *, UINT_32); + + /* parse TDLS sub-command */ + u4Subcmd = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + DBGLOG(TDLS, INFO, " sub command = %u\n", (UINT32) u4Subcmd); + TdlsCmdTestFunc = NULL; + + /* handle different sub-command */ + switch (u4Subcmd) { +#if TDLS_CFG_CMD_TEST /* only for unit test */ + case TDLS_CMD_TEST_TX_FRAME: + /* simulate to send a TDLS frame */ + /* TdlsCmdTestTxFrame(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestTxFrame; + break; + + case TDLS_CMD_TEST_TX_TDLS_FRAME: + /* simulate to send a TDLS frame from supplicant */ + /* TdlsCmdTestTxTdlsFrame(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestTxTdlsFrame; + break; + + case TDLS_CMD_TEST_RCV_FRAME: + /* simulate to receive a TDLS frame */ + /* TdlsCmdTestRvFrame(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestRvFrame; + break; + + case TDLS_CMD_TEST_PEER_ADD: + /* simulate to add a TDLS peer */ + /* TdlsCmdTestAddPeer(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestAddPeer; + break; + + case TDLS_CMD_TEST_PEER_UPDATE: + /* simulate to update a TDLS peer */ + /* TdlsCmdTestUpdatePeer(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestUpdatePeer; + break; + + case TDLS_CMD_TEST_DATA_FRAME: + /* simulate to send a data frame to the peer */ + /* TdlsCmdTestDataSend(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestDataSend; + break; + + case TDLS_CMD_TEST_RCV_NULL: + /* simulate to receive a QoS null frame from the peer */ + /* TdlsCmdTestNullRecv(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestNullRecv; + break; + + case TDLS_CMD_TEST_SKIP_TX_FAIL: + /* command firmware to skip tx fail case */ + /* TdlsCmdTestTxFailSkip(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestTxFailSkip; + break; + + case TDLS_CMD_TEST_SKIP_KEEP_ALIVE: + /* command firmware to skip keep alive function */ + /* TdlsCmdTestKeepAliveSkip(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestKeepAliveSkip; + break; + + case TDLS_CMD_TEST_SKIP_CHSW_TIMEOUT: + /* command firmware to skip channel switch timeout function */ + /* TdlsCmdTestChSwTimeoutSkip(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestChSwTimeoutSkip; + break; + + case TDLS_CMD_TEST_PROHIBIT_SET_IN_AP: + /* simulate to set Prohibited Bit in AP */ + /* TdlsCmdTestProhibitedBitSet(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestProhibitedBitSet; + break; + + case TDLS_CMD_TEST_SCAN_DISABLE: + /* command to disable scan request to do channel switch */ + /* TdlsCmdTestScanCtrl(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestScanCtrl; + break; + + case TDLS_CMD_TEST_DATA_FRAME_CONT: + /* simulate to send a data frame to the peer periodically */ + /* TdlsCmdTestDataContSend(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestDataContSend; + break; + + case TDLS_CMD_TEST_CH_SW_PROHIBIT_SET_IN_AP: + /* simulate to set channel switch Prohibited Bit in AP */ + /* TdlsCmdTestChSwProhibitedBitSet(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestChSwProhibitedBitSet; + break; + + case TDLS_CMD_TEST_DELAY: + /* delay a where */ + /* TdlsCmdTestDelay(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestDelay; + break; + + case TDLS_CMD_TEST_PTI_TX_FAIL: + /* simulate the tx done fail for PTI */ + /* TdlsCmdTestPtiTxDoneFail(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestPtiTxDoneFail; + break; +#endif /* TDLS_CFG_CMD_TEST */ + + case TDLS_CMD_MIB_UPDATE: + /* update MIB parameters */ + /* TdlsCmdMibParamUpdate(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdMibParamUpdate; + break; + + case TDLS_CMD_UAPSD_CONF: + /* config UAPSD parameters */ + /* TdlsCmdUapsdConf(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdUapsdConf; + break; + + case TDLS_CMD_CH_SW_CONF: + /* enable or disable or start or stop channel switch function */ + /* TdlsCmdChSwConf(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdChSwConf; + break; + + case TDLS_CMD_SETUP_CONF: + /* config setup parameters */ + /* TdlsCmdSetupConf(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdSetupConf; + break; + + case TDLS_CMD_INFO: + /* display all TDLS information */ + /* TdlsCmdInfoDisplay(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdInfoDisplay; + break; + + case TDLS_CMD_KEY_INFO: + /* display key information */ + /* TdlsCmdKeyInfoDisplay(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdKeyInfoDisplay; + break; + + default: + break; + } + + if (TdlsCmdTestFunc != NULL) + TdlsCmdTestFunc(prGlueInfo, prInBuf, u4InBufLen); + +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to record a disconnection event. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure +* \param[in] fgIsTearDown TRUE: tear down +* \param[in] pucPeerMac Pointer to the MAC of the TDLS peer +* \param[in] fgIsFromUs TRUE: tear down is from us +* \param[in] u2ReasonCode Disconnection reason (TDLS_REASON_CODE) +* +* \retval none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID +TdlsexLinkHistoryRecord(GLUE_INFO_T *prGlueInfo, + BOOLEAN fgIsTearDown, UINT8 *pucPeerMac, BOOLEAN fgIsFromUs, UINT16 u2ReasonCode) +{ + /* sanity check */ + if ((prGlueInfo == NULL) || (pucPeerMac == NULL)) + return; + + DBGLOG(TDLS, INFO, + " %s: Rcv a inform from %pM %d %d\n", + __func__, pucPeerMac, fgIsFromUs, u2ReasonCode); + + /* record */ + TdlsLinkHistoryRecord(prGlueInfo, fgIsTearDown, pucPeerMac, fgIsFromUs, u2ReasonCode, NULL); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to send a command to TDLS module. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID TdlsexEventHandle(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen) +{ + UINT32 u4EventId; + + /* sanity check */ + if ((prGlueInfo == NULL) || (prInBuf == NULL)) + return; /* shall not be here */ + + /* handle */ + u4EventId = *(UINT32 *) prInBuf; + u4InBufLen -= 4; + + DBGLOG(TDLS, INFO, " %s: Rcv a event: %d\n", __func__, u4EventId); + + switch (u4EventId) { + case TDLS_HOST_EVENT_TEAR_DOWN: + TdlsEventTearDown(prGlueInfo, prInBuf + 4, u4InBufLen); + break; + + case TDLS_HOST_EVENT_TX_DONE: + TdlsEventTxDone(prGlueInfo, prInBuf + 4, u4InBufLen); + break; + + case TDLS_HOST_EVENT_FME_STATUS: + TdlsEventFmeStatus(prGlueInfo, prInBuf + 4, u4InBufLen); + break; + + case TDLS_HOST_EVENT_STATISTICS: + TdlsEventStatistics(prGlueInfo, prInBuf + 4, u4InBufLen); + break; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to initialize variables in TDLS. +* +* \param[in] prAdapter Pointer to the Adapter structure +* +* @return TDLS_STATUS_SUCCESS: do not set key and key infor. is queued + TDLS_STATUS_FAILURE: set key +*/ +/*----------------------------------------------------------------------------*/ +TDLS_STATUS TdlsexKeyHandle(ADAPTER_T *prAdapter, PARAM_KEY_T *prNewKey, ENUM_NETWORK_TYPE_INDEX_T eNetworkType) +{ + STA_RECORD_T *prStaRec; + + /* sanity check */ + if ((prAdapter == NULL) || (prNewKey == NULL)) + return TDLS_STATUS_FAILURE; + + /* + * supplicant will set key before updating station & enabling the link so we need to + * backup the key information and set key when link is enabled + */ + prStaRec = cnmGetStaRecByAddress(prAdapter, eNetworkType, prNewKey->arBSSID); + /* + * supplicant will add key when rx TDLS setup response: + * + * wpa_supplicant: nl80211: Drv Event 81 (NL80211_CMD_TDLS_OPER) received for p2p0 + * wpa_supplicant: nl80211: TDLS setup request for peer 02:08:22:88:b3:fb + * wpa_supplicant: TDLS: Sending TDLS Setup Request / TPK Handshake Message 1 (peer 02:08:22:88:b3:fb) + * wpa_supplicant: TDLS: Received TDLS Setup Response / TPK M2 (Peer 02:08:22:88:b3:fb) + * wpa_supplicant: TDLS: Sending TDLS Setup Confirm / TPK Handshake Message 3 + * wpa_supplicant: TDLS: Received TDLS Setup Response / TPK M2 (Peer 02:08:22:88:b3:fb) + * wpa_supplicant: TDLS: Sending TDLS Setup Confirm / TPK Handshake Message 3 + * wpa_supplicant: nl80211: Drv Event 81 (NL80211_CMD_TDLS_OPER) received for p2p0 + * wpa_supplicant: nl80211: TDLS teardown request for peer 02:08:22:88:b3:fb + * wpa_supplicant: TDLS: TDLS Teardown for 02:08:22:88:b3:fb + * + * tear down is needed as every TPK is differ due the different NONCE + */ + if ((prStaRec != NULL) && IS_TDLS_STA(prStaRec)) { + DBGLOG(TDLS, INFO, "[%pM] queue key (len=%d) until link is enabled\n", + prNewKey->arBSSID, (UINT32) prNewKey->u4KeyLength); + + if (prStaRec->ucStaState == STA_STATE_3) { + DBGLOG(TDLS, INFO, "[%pM] tear down the link due to STA_STATE_3\n", + prNewKey->arBSSID); + + /* re-key */ + TdlsLinkHistoryRecord(prAdapter->prGlueInfo, TRUE, + prStaRec->aucMacAddr, TRUE, + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_REKEY, NULL); + + /* 16 Nov 21:49 2012 http://permalink.gmane.org/gmane.linux.kernel.wireless.general/99712 */ + cfg80211_tdls_oper_request(eNetworkType == NETWORK_TYPE_AIS_INDEX ? + prAdapter->prGlueInfo->prDevHandler : + prAdapter->prGlueInfo->prP2PInfo->prDevHandler, + prStaRec->aucMacAddr, NL80211_TDLS_TEARDOWN, + TDLS_REASON_CODE_UNSPECIFIED, GFP_ATOMIC); + return TDLS_STATUS_SUCCESS; + } + + /* backup the key */ + kalMemCopy(&prStaRec->rTdlsKeyTemp, prNewKey, sizeof(prStaRec->rTdlsKeyTemp)); + return TDLS_STATUS_SUCCESS; + } + + return TDLS_STATUS_FAILURE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to initialize variables in TDLS. +* +* \param[in] prAdapter Pointer to the Adapter structure +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID TdlsexInit(ADAPTER_T *prAdapter) +{ + GLUE_INFO_T *prGlueInfo; + + /* init */ + prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; + + /* reset */ + kalMemZero(&prGlueInfo->rTdlsLink, sizeof(prGlueInfo->rTdlsLink)); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get any peer is in power save. +* +* \param[in] prAdapter Pointer to the Adapter structure +* +* \retval TRUE (at least one peer is in power save) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN TdlsexIsAnyPeerInPowerSave(ADAPTER_T *prAdapter) +{ + STA_RECORD_T *prStaRec; + UINT32 u4StaId, u4StartIdx; + + for (u4StaId = 0, u4StartIdx = 0; u4StaId < CFG_STA_REC_NUM; u4StaId++) { + /* list all TDLS peers */ + prStaRec = cnmStaTheTypeGet(prAdapter, NETWORK_TYPE_AIS_INDEX, STA_TYPE_TDLS_PEER, &u4StartIdx); + if (prStaRec == NULL) + break; + + if (prStaRec->fgIsInPS == TRUE) { + DBGLOG(TDLS, TRACE, " yes, at least one peer is in ps\n"); + return TRUE; + } + } + + return FALSE; +} + +static struct ksta_info * +MTKTdlsGetSta(P_GLUE_INFO_T prGlueInfo, const u8 *prSta) +{ + struct ksta_info *s; + + s = prGlueInfo->prStaHash[STA_HASH(prSta)]; + while (s && memcmp(s->aucAddr, prSta, 6)) + s = s->pNext; + return s; +} + +static void +MTKTdlsStaHashAdd(P_GLUE_INFO_T prGlueInfo, struct ksta_info *prSta) +{ + prSta->pNext = prGlueInfo->prStaHash[STA_HASH(prSta->aucAddr)]; + prGlueInfo->prStaHash[STA_HASH(prSta->aucAddr)] = prSta; +} + +struct ksta_info * +MTKTdlsStaAdd(P_GLUE_INFO_T prGlueInfo, const u8 *prAddr) +{ + struct ksta_info *prSta; + + prSta = kzalloc(sizeof(struct ksta_info), GFP_ATOMIC); + if (prSta == NULL) { + DBGLOG(TDLS, INFO, "Alloc ksta failed\n"); + return NULL; + } + + /* initialize STA info data */ + /* memcpy(sta->ucAddr, addr, ETH_ALEN); */ + ether_addr_copy(prSta->aucAddr, prAddr); + MTKTdlsStaHashAdd(prGlueInfo, prSta); + + return prSta; +} + +void +MTKTdlsCreateTarget(P_GLUE_INFO_T prGlueInfo, const u8 *prAddr, CHAR *prReason) +{ + struct ksta_info *prTdlsPeer; + + prTdlsPeer = MTKTdlsGetSta(prGlueInfo, prAddr); + + if (!prTdlsPeer) + prTdlsPeer = MTKTdlsStaAdd(prGlueInfo, prAddr); + if (!prTdlsPeer) + return; + + DBGLOG(TDLS, INFO, "Create TDLS peer[%pM] due to %s\n", + prTdlsPeer->aucAddr, prReason); + prGlueInfo->prStaHash[STA_HASH_SIZE] = prTdlsPeer; +} + +void +MTKTdlsApStaForEach(P_GLUE_INFO_T prGlueInfo, enum sta_op eOp, void *prArg, void **pprOut) +{ + int i4HashPos; + struct ksta_info *p, *r; + int i4Max_tp = 0; + + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prGlueInfo->prAdapter, SPIN_LOCK_STA_REC); + + for (i4HashPos = 0; i4HashPos < STA_HASH_SIZE; i4HashPos++) { + r = prGlueInfo->prStaHash[i4HashPos]; + while (r) { + p = r; + r = r->pNext; + switch (eOp) { + case STA_OP_FREE: + DBGLOG(TDLS, TRACE, "freeing sta %pM\n", p->aucAddr); + kfree(p); + if (!r) + prGlueInfo->prStaHash[i4HashPos] = NULL; + break; + case STA_OP_RESET: + DBGLOG(TDLS, TRACE, "Reset default\n"); + p->ulTxBytes = 0; + p->ulRxBytes = 0; + p->u4Throughput = 0; + prGlueInfo->ulLastUpdate = jiffies; + break; + case STA_OP_GET_MAX_TP: + p->u4Throughput = (p->ulTxBytes * HZ) / SAMPLING_UT; + + DBGLOG(TDLS, TRACE, "STA: %pM, TP: %d Bytes/s\n", + p->aucAddr, p->u4Throughput); + + /* + * exclude: + * BSSID, as we are direct link with BSSID + * broadcast / multicast + */ + if (p->u4Throughput >= i4Max_tp && + kalMemCmp(p->aucAddr, prArg, ETH_ALEN) && + IS_UCAST_MAC_ADDR(p->aucAddr)) { + DBGLOG(TDLS, TRACE, "MAX TP: %d\n", p->u4Throughput); + *pprOut = p; + i4Max_tp = p->u4Throughput; + } + break; + case STA_OP_UPDATE_TX: + default: + break; + } + } + } + KAL_RELEASE_SPIN_LOCK(prGlueInfo->prAdapter, SPIN_LOCK_STA_REC); +} + +VOID +MTKTdlsApStaUpdateTxRxStatus(P_GLUE_INFO_T prGlueInfo, unsigned long tx_bytes, unsigned long rx_bytes, const u8 *prAddr) +{ + struct ksta_info *sta; + + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prGlueInfo->prAdapter, SPIN_LOCK_STA_REC); + + sta = MTKTdlsGetSta(prGlueInfo, prAddr); + + if (!sta) + sta = MTKTdlsStaAdd(prGlueInfo, prAddr); + + if (!sta) { + KAL_RELEASE_SPIN_LOCK(prGlueInfo->prAdapter, SPIN_LOCK_STA_REC); + DBGLOG(TDLS, INFO, "Add sta info failed\n"); + return; + } + + if (tx_bytes) + sta->ulTxBytes += tx_bytes; + else + sta->ulRxBytes += rx_bytes; + + KAL_RELEASE_SPIN_LOCK(prGlueInfo->prAdapter, SPIN_LOCK_STA_REC); + + DBGLOG(TDLS, TRACE, "sta[%pM] %s bytes: %ld\n", prAddr, + tx_bytes ? "Tx" : "Rx", + tx_bytes ? tx_bytes : rx_bytes); +} + +/* check if it is OK for auto tdls setup over P2P */ +BOOLEAN MTKTdlsEnvP2P(P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prBssInfo; + + if (!prAdapter || !prAdapter->fgIsP2PRegistered) + return FALSE; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; + + return (prBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED && + prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) ? TRUE : FALSE; +} + +VOID +MTKTdlsSetup(P_GLUE_INFO_T prGlueInfo, struct ksta_info *prSta) +{ + DBGLOG(TDLS, INFO, "Build up tdls link with %pM\n", prSta->aucAddr); + cfg80211_tdls_oper_request(prGlueInfo->prP2PInfo->prDevHandler, + prSta->aucAddr, NL80211_TDLS_SETUP, 0, GFP_ATOMIC); + prSta->eTdlsStatus = MTK_TDLS_SETUP_INPROCESS; + prSta->eTdlsRole = MTK_TDLS_ROLE_INITOR; + /* the last sta hash used as target station */ + prGlueInfo->prStaHash[STA_HASH_SIZE] = prSta; + /* start TDLS status monitor */ + cnmTimerStartTimer(prGlueInfo->prAdapter, + &(prGlueInfo->prAdapter->rTdlsStateTimer), + SEC_TO_MSEC(TDLS_SETUP_TIMEOUT)); +} + +VOID +MTKTdlsTearDown(P_GLUE_INFO_T prGlueInfo, struct ksta_info *prSta, CHAR *reason) +{ + DBGLOG(TDLS, INFO, "TDLS teardown due to %s\n", reason); + + if (kalStrCmp(reason, "Disable Link")) + cfg80211_tdls_oper_request(prGlueInfo->prP2PInfo->prDevHandler, + prSta->aucAddr, NL80211_TDLS_TEARDOWN, 0, GFP_ATOMIC); + + prGlueInfo->prStaHash[STA_HASH_SIZE] = NULL; + prGlueInfo->i4TdlsLastRx = -1; + MTKTdlsApStaForEach(prGlueInfo, STA_OP_FREE, NULL, NULL); + + cnmTimerStopTimer(prGlueInfo->prAdapter, &(prGlueInfo->prAdapter->rTdlsStateTimer)); +} + +INT_32 +MTKAutoTdlsP2P(P_GLUE_INFO_T prGlueInfo, P_NATIVE_PACKET prPacket) +{ + UINT_32 u4PacketLen; + PUINT_8 pucData = NULL; + P_BSS_INFO_T prBssInfo = NULL; + struct ksta_info *target_sta = NULL; + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + + if (!prSkb || !prGlueInfo) + return -1; + + u4PacketLen = prSkb->len; + + if (u4PacketLen < ETH_HLEN) + return -1; + + prBssInfo = &(prGlueInfo->prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + pucData = prSkb->data; + + DBGLOG(TDLS, TRACE, "jiffies: %ld, timeout: %ld\n", + jiffies, prGlueInfo->ulLastUpdate + SAMPLING_UT); + + if (time_before(jiffies, prGlueInfo->ulLastUpdate + SAMPLING_UT)) { + MTKTdlsApStaUpdateTxRxStatus(prGlueInfo, u4PacketLen, 0, pucData); + return 0; + } + + if (!prGlueInfo->prStaHash[STA_HASH_SIZE]) { + MTKTdlsApStaForEach(prGlueInfo, STA_OP_GET_MAX_TP, + prBssInfo->aucBSSID, + (void **)&target_sta); + + if (target_sta && target_sta->u4Throughput > TDLS_SETUP_THD) { + switch (target_sta->eTdlsStatus) { + case MTK_TDLS_NOT_SETUP: + MTKTdlsSetup(prGlueInfo, target_sta); + return 1; + case MTK_TDLS_SETUP_INPROCESS: + DBGLOG(TDLS, INFO, "TDLS setup in Process\n"); + return 2; + default: + DBGLOG(TDLS, INFO, "TDLS setup state %d\n", + target_sta->eTdlsStatus); + return 3; + } + } + /* update one shot to avoid no sta available in sta list */ + MTKTdlsApStaUpdateTxRxStatus(prGlueInfo, u4PacketLen, 0, pucData); + goto reset; + } + + /* already has a tdls link */ + target_sta = prGlueInfo->prStaHash[STA_HASH_SIZE]; + + if (target_sta->eTdlsRole == MTK_TDLS_ROLE_RESPONDER) + return 6; + + target_sta->u4Throughput = (target_sta->ulTxBytes * HZ) / SAMPLING_UT; + + if (target_sta->u4Throughput < TDLS_TEARDOWN_THD) { + switch (target_sta->eTdlsStatus) { + case MTK_TDLS_LINK_ENABLE: + MTKTdlsTearDown(prGlueInfo, target_sta, "Low Tx Throughput"); + default: + return 4; + } + } +reset: + MTKTdlsApStaForEach(prGlueInfo, STA_OP_RESET, NULL, NULL); + return 5; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to enable or disable a TDLS link. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +*/ +/*----------------------------------------------------------------------------*/ +TDLS_STATUS TdlsexLinkCtrl(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + GLUE_INFO_T *prGlueInfo; + TDLS_CMD_LINK_T *prCmd; + STA_RECORD_T *prStaRec; + struct ksta_info *prKsta; + + /* sanity check */ + if ((prAdapter == NULL) || (pvSetBuffer == NULL) || (pu4SetInfoLen == NULL)) { + DBGLOG(TDLS, ERROR, " %s: sanity fail!\n", __func__); + return TDLS_STATUS_FAILURE; + } + + /* init */ + prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; + *pu4SetInfoLen = sizeof(TDLS_CMD_LINK_T); + prCmd = (TDLS_CMD_LINK_T *) pvSetBuffer; + + /* work-around link count */ + if ((TDLS_LINK_COUNT(prGlueInfo) < 0) || (TDLS_LINK_COUNT(prGlueInfo) > 1)) { + /* ERROR case: work-around to recount by searching all station records */ + UINT32 u4Idx; + + TDLS_LINK_COUNT_RESET(prGlueInfo); + + for (u4Idx = 0; u4Idx < CFG_STA_REC_NUM; u4Idx++) { + prStaRec = &prAdapter->arStaRec[u4Idx]; + + if (prStaRec->fgIsInUse && IS_TDLS_STA(prStaRec)) + TDLS_LINK_INCREASE(prGlueInfo); + } + + if (TDLS_LINK_COUNT(prGlueInfo) > 1) { + /* number of links is still > 1 */ + DBGLOG(TDLS, INFO, " %s: cTdlsLinkCnt %d > 1?\n", + __func__, TDLS_LINK_COUNT(prGlueInfo)); + + TDLS_LINK_COUNT_RESET(prGlueInfo); + + /* free all TDLS links */ + for (u4Idx = 0; u4Idx < CFG_STA_REC_NUM; u4Idx++) { + prStaRec = &prAdapter->arStaRec[u4Idx]; + + if (prStaRec->fgIsInUse && IS_TDLS_STA(prStaRec)) + cnmStaRecFree(prAdapter, prStaRec, TRUE); + } + + /* maybe inform supplicant ? */ + } + } + + /* for auto tdls */ + prKsta = MTKTdlsGetSta(prGlueInfo, prCmd->aucPeerMac); + + if (!prKsta) + prKsta = MTKTdlsStaAdd(prGlueInfo, prCmd->aucPeerMac); + if (!prKsta) + goto ret; + + if (prCmd->fgIsEnabled) { + prGlueInfo->prStaHash[STA_HASH_SIZE] = prKsta; + + prKsta->eTdlsStatus = MTK_TDLS_LINK_ENABLE; + /* + * special case: + * both tdls station want setup link at + * the same time. + * higher MAC addr driver will free sta and no role + * specified until enable link + */ + DBGLOG(TDLS, INFO, "Enable Link, LastRx:Role %d:%d\n", + prGlueInfo->i4TdlsLastRx, prKsta->eTdlsRole); + + switch (prGlueInfo->i4TdlsLastRx) { + /* Initor */ + case TDLS_FRM_ACTION_SETUP_RSP: + if (prKsta->eTdlsRole == MTK_TDLS_ROLE_IDLE) { + cnmTimerStartTimer(prGlueInfo->prAdapter, + &(prGlueInfo->prAdapter->rTdlsStateTimer), + SEC_TO_MSEC(TDLS_MONITOR_UT)); + prKsta->eTdlsRole = MTK_TDLS_ROLE_INITOR; + } + break; + case TDLS_FRM_ACTION_CONFIRM: + /* Responder */ + /* go through */ + default: + prKsta->eTdlsRole = MTK_TDLS_ROLE_RESPONDER; + + /* + * Supplicant will enable link after RX TDLS Confirm as responder + * It is very OK to enable link and install key when as responder + */ + if (TdlsexEnableDisableLink(prAdapter, prCmd->aucPeerMac, + prCmd->fgIsEnabled, prCmd->eNetworkType)) { + return TDLS_STATUS_FAILURE; + } + cnmTimerStartTimer(prGlueInfo->prAdapter, + &(prGlueInfo->prAdapter->rTdlsStateTimer), + SEC_TO_MSEC(TDLS_MONITOR_UT)); + break; + } + } else { + MTKTdlsTearDown(prAdapter->prGlueInfo, prKsta, "Disable Link"); + TdlsexEnableDisableLink(prAdapter, prCmd->aucPeerMac, + prCmd->fgIsEnabled, prCmd->eNetworkType); + } +ret: + /* display TDLS link history */ + TdlsInfoDisplay(prAdapter, NULL, 0, NULL); + + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to send a TDLS action data frame. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +*/ +/*----------------------------------------------------------------------------*/ +TDLS_STATUS TdlsexMgmtCtrl(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + GLUE_INFO_T *prGlueInfo; + TDLS_MGMT_TX_INFO *prMgmtTxInfo; + STA_RECORD_T *prStaRec; + + /* sanity check */ + if ((prAdapter == NULL) || (pvSetBuffer == NULL) || (pu4SetInfoLen == NULL)) { + DBGLOG(TDLS, ERROR, " %s: sanity fail!\n", __func__); + return TDLS_STATUS_FAILURE; + } + + /* init */ + prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; + *pu4SetInfoLen = sizeof(TDLS_MGMT_TX_INFO); + prMgmtTxInfo = (TDLS_MGMT_TX_INFO *) pvSetBuffer; + + switch (prMgmtTxInfo->ucActionCode) { + case TDLS_FRM_ACTION_DISCOVERY_RESPONSE: + case TDLS_FRM_ACTION_DISCOVERY_REQ: + prStaRec = NULL; + break; + + case TDLS_FRM_ACTION_SETUP_REQ: + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) prMgmtTxInfo->eNetworkType, prMgmtTxInfo->aucPeer); + if ((prStaRec != NULL) && (prStaRec->ucStaState == STA_STATE_3)) { + /* rekey? we reject re-setup link currently */ + /* TODO: Still can setup link during rekey */ + + /* + * return success to avoid supplicant clear TDLS entry; + * Or we cannot send out any TDLS tear down frame to the peer + */ + DBGLOG(TDLS, TRACE, " %s: skip new setup on the exist link!\n", __func__); + return TDLS_STATUS_SUCCESS; + } + + prStaRec = NULL; + break; + + case TDLS_FRM_ACTION_SETUP_RSP: + case TDLS_FRM_ACTION_CONFIRM: + case TDLS_FRM_ACTION_TEARDOWN: + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) prMgmtTxInfo->eNetworkType, prMgmtTxInfo->aucPeer); +#if 0 /* in some cases, the prStaRec is still NULL */ + /* + * EX: if a peer sends us a TDLS setup request with wrong BSSID, + * supplicant will not call TdlsexPeerAdd() to create prStaRec and + * supplicant will send a TDLS setup response with status code 7. + * + * So in the case, prStaRec will be NULL. + */ + if (prStaRec == NULL) { + DBGLOG(TDLS, ERROR, " %s: cannot find the peer!\n", __func__); + return -EINVAL; + } +#endif + break; + + /* + * TODO: Discovery response frame + * Note that the TDLS Discovery Response frame is not a TDLS frame but a 11 + * Public Action frame. + * In WiFi TDLS Tech Minutes June 8 2010.doc, + * a public action frame (i.e. it is no longer an encapsulated data frame) + */ + + default: + DBGLOG(TDLS, ERROR, + " %s: wrong action_code %d!\n", __func__, prMgmtTxInfo->ucActionCode); + return TDLS_STATUS_FAILURE; + } + + /* send the TDLS data frame */ + if (prStaRec != NULL) { + DBGLOG(TDLS, INFO, " %s: [%pM] ps=%d status=%d\n", + __func__, prStaRec->aucMacAddr, + prStaRec->fgIsInPS, prMgmtTxInfo->u2StatusCode); + + if (prMgmtTxInfo->ucActionCode == TDLS_FRM_ACTION_TEARDOWN) { + /* record disconnect history */ + TdlsLinkHistoryRecord(prGlueInfo, TRUE, prMgmtTxInfo->aucPeer, + TRUE, prMgmtTxInfo->u2StatusCode, NULL); + } + } + + return TdlsDataFrameSend(prAdapter, + prStaRec, + prMgmtTxInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to add a peer record. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +*/ +/*----------------------------------------------------------------------------*/ +TDLS_STATUS TdlsexPeerAdd(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + GLUE_INFO_T *prGlueInfo; + TDLS_CMD_PEER_ADD_T *prCmd; + BSS_INFO_T *prBssInfo; + STA_RECORD_T *prStaRec; + UINT_8 ucNonHTPhyTypeSet; + UINT32 u4StartIdx; + OS_SYSTIME rCurTime; + + /* sanity check */ + DBGLOG(TDLS, INFO, " %s\n", __func__); + + if ((prAdapter == NULL) || (pvSetBuffer == NULL) || (pu4SetInfoLen == NULL)) { + DBGLOG(TDLS, ERROR, " %s: sanity fail!\n", __func__); + return TDLS_STATUS_FAILURE; + } + + /* init */ + prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; + *pu4SetInfoLen = sizeof(TDLS_CMD_PEER_ADD_T); + prCmd = (TDLS_CMD_PEER_ADD_T *) pvSetBuffer; + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prCmd->eNetworkType]); + u4StartIdx = 0; + + /* search old entry */ + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) prCmd->eNetworkType, prCmd->aucPeerMac); + + /* check if any TDLS link exists because we only support one TDLS link currently */ + if (prStaRec == NULL) { + /* the MAC is new peer */ + prStaRec = cnmStaTheTypeGet(prAdapter, prCmd->eNetworkType, STA_TYPE_TDLS_PEER, &u4StartIdx); + + if (prStaRec != NULL) { + /* a building TDLS link exists */ + DBGLOG(TDLS, ERROR, + " %s: one TDLS link setup [%pM] is going...\n", + __func__, prStaRec->aucMacAddr); + + if (prStaRec->ucStaState != STA_STATE_3) { + /* check timeout */ + GET_CURRENT_SYSTIME(&rCurTime); + + if (CHECK_FOR_TIMEOUT(rCurTime, prStaRec->rTdlsSetupStartTime, + SEC_TO_SYSTIME(TDLS_SETUP_TIMEOUT_SEC))) { + /* free the StaRec */ + cnmStaRecFree(prAdapter, prStaRec, TRUE); + + DBGLOG(TDLS, ERROR, + " %s: free going TDLS link setup [%pM]\n", + __func__, (prStaRec->aucMacAddr)); + + /* handle new setup */ + prStaRec = NULL; + } else + return TDLS_STATUS_FAILURE; + } else { + /* the TDLS is built and works fine, reject new one */ + return TDLS_STATUS_FAILURE; + } + } + } else { + if (prStaRec->ucStaState == STA_STATE_3) { + /* the peer exists, maybe TPK lifetime expired, supplicant wants to renew key */ + TdlsLinkHistoryRecord(prAdapter->prGlueInfo, TRUE, + prStaRec->aucMacAddr, TRUE, + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_REKEY, NULL); + + /* 16 Nov 21:49 2012 http://permalink.gmane.org/gmane.linux.kernel.wireless.general/99712 */ + cfg80211_tdls_oper_request(prCmd->eNetworkType == NETWORK_TYPE_AIS_INDEX ? + prAdapter->prGlueInfo->prDevHandler : + prAdapter->prGlueInfo->prP2PInfo->prDevHandler, + prStaRec->aucMacAddr, NL80211_TDLS_TEARDOWN, + TDLS_REASON_CODE_UNSPECIFIED, GFP_ATOMIC); + + DBGLOG(TDLS, INFO, + " %s: re-setup link for [%pM] maybe re-key?\n", + __func__, (prStaRec->aucMacAddr)); + return TDLS_STATUS_FAILURE; + } + } + + /* + * create new entry if not exist + * + * 1. we are initiator + * (1) send TDLS setup request + * wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, NULL, 0); + * create a station record with STA_STATE_1. + * (2) got TDLS setup response and send TDLS setup confirm + * wpa_tdls_enable_link() + * update a station record with STA_STATE_3. + * + * 2. we are responder + * (1) got TDLS setup request + * wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, NULL, 0); + * create a station record with STA_STATE_1. + * (2) send TDLS setup response + * (3) got TDLS setup confirm + * wpa_tdls_enable_link() + * update a station record with STA_STATE_3. + */ + if (prStaRec == NULL) { + prStaRec = cnmStaRecAlloc(prAdapter, (UINT_8) prCmd->eNetworkType); + + if (prStaRec == NULL) { + /* shall not be here */ + DBGLOG(TDLS, ERROR, " %s: alloc prStaRec fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + /* init the prStaRec */ + /* prStaRec will be zero first in cnmStaRecAlloc() */ + COPY_MAC_ADDR(prStaRec->aucMacAddr, prCmd->aucPeerMac); + +/* cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); */ + } else { +#if 0 + if ((prStaRec->ucStaState > STA_STATE_1) && (IS_TDLS_STA(prStaRec))) { + /* + * test plan: The STAUT should locally tear down existing TDLS direct link and + * respond with Set up Response frame. + */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + } +#endif + } + + /* reference to bssCreateStaRecFromBssDesc() and use our best capability */ + /* reference to assocBuildReAssocReqFrameCommonIEs() to fill elements */ + + /* prStaRec->u2CapInfo */ + /* TODO: Need to parse elements from setup request frame */ + prStaRec->u2OperationalRateSet = prBssInfo->u2OperationalRateSet; + prStaRec->u2BSSBasicRateSet = prBssInfo->u2BSSBasicRateSet; + prStaRec->u2DesiredNonHTRateSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet; + prStaRec->ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + prStaRec->eStaType = STA_TYPE_TDLS_PEER; + + prStaRec->ucDesiredPhyTypeSet = /*prStaRec->ucPhyTypeSet & */ + prAdapter->rWifiVar.ucAvailablePhyTypeSet; + ucNonHTPhyTypeSet = prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11ABG; + + /* check for Target BSS's non HT Phy Types */ + if (ucNonHTPhyTypeSet) { + if (ucNonHTPhyTypeSet & PHY_TYPE_BIT_ERP) { + prStaRec->ucNonHTBasicPhyType = PHY_TYPE_ERP_INDEX; + } else if (ucNonHTPhyTypeSet & PHY_TYPE_BIT_OFDM) { + prStaRec->ucNonHTBasicPhyType = PHY_TYPE_OFDM_INDEX; + } else { /* if (ucNonHTPhyTypeSet & PHY_TYPE_HR_DSSS_INDEX) */ + + prStaRec->ucNonHTBasicPhyType = PHY_TYPE_HR_DSSS_INDEX; + } + + prStaRec->fgHasBasicPhyType = TRUE; + } else { + /* use mandatory for 11N only BSS */ + /* ASSERT(prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N); */ + + prStaRec->ucNonHTBasicPhyType = PHY_TYPE_HR_DSSS_INDEX; + prStaRec->fgHasBasicPhyType = FALSE; + } + + /* update non HT Desired Rate Set */ + { + P_CONNECTION_SETTINGS_T prConnSettings; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prStaRec->u2DesiredNonHTRateSet = + (prStaRec->u2OperationalRateSet & prConnSettings->u2DesiredNonHTRateSet); + } + +#if 0 /* TdlsexPeerAdd() will be called before we receive setup rsp in TdlsexRxFrameHandle() */ + /* check if the add is from the same peer in the 1st unhandled setup request frame */ + DBGLOG(TDLS, INFO, " %s: [%pM] [%pM]\n", + __func__, prGlueInfo->aucTdlsHtPeerMac, prCmd->aucPeerMac); + + if (kalMemCmp(prGlueInfo->aucTdlsHtPeerMac, prCmd->aucPeerMac, 6) == 0) { + /* copy the HT capability from its setup request */ + kalMemCopy(&prStaRec->rTdlsHtCap, &prGlueInfo->rTdlsHtCap, sizeof(IE_HT_CAP_T)); + + prStaRec->ucPhyTypeSet |= PHY_TYPE_SET_802_11N; + prStaRec->u2DesiredNonHTRateSet |= BIT(RATE_HT_PHY_INDEX); + + /* reset backup */ + kalMemZero(&prGlueInfo->rTdlsHtCap, sizeof(prStaRec->rTdlsHtCap)); + kalMemZero(prGlueInfo->aucTdlsHtPeerMac, sizeof(prGlueInfo->aucTdlsHtPeerMac)); + + DBGLOG(TDLS, INFO, " %s: peer is a HT device\n", __func__); + } +#endif + + /* update WMM: must support due to UAPSD in TDLS link */ + prStaRec->fgIsWmmSupported = TRUE; + prStaRec->fgIsUapsdSupported = TRUE; + + /* update station record to firmware */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + /* update time */ + GET_CURRENT_SYSTIME(&prStaRec->rTdlsSetupStartTime); + + DBGLOG(TDLS, INFO, "create a peer [%pM], sta rec: %d network index %d\n", + prStaRec->aucMacAddr, prStaRec->ucIndex, prStaRec->ucNetTypeIndex); + + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to update a peer record. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +*/ +/*----------------------------------------------------------------------------*/ +TDLS_STATUS TdlsexPeerUpdate(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + GLUE_INFO_T *prGlueInfo; + TDLS_CMD_PEER_UPDATE_T *prCmd; + BSS_INFO_T *prBssInfo; + STA_RECORD_T *prStaRec; + IE_HT_CAP_T *prHtCap; + + /* sanity check */ + DBGLOG(TDLS, TRACE, " %s\n", __func__); + + if ((prAdapter == NULL) || (pvSetBuffer == NULL) || (pu4SetInfoLen == NULL)) { + DBGLOG(TDLS, ERROR, " %s: sanity fail!\n", __func__); + return TDLS_STATUS_FAILURE; + } + + /* init */ + prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; + *pu4SetInfoLen = sizeof(TDLS_CMD_PEER_ADD_T); + prCmd = (TDLS_CMD_PEER_UPDATE_T *) pvSetBuffer; + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prCmd->eNetworkType]); + + /* search old entry */ + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) prCmd->eNetworkType, prCmd->aucPeerMac); + + /* + * create new entry if not exist + * + * 1. we are initiator + * (1) send TDLS setup request + * wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, NULL, 0); + * create a station record with STA_STATE_1. + * (2) got TDLS setup response and send TDLS setup confirm + * wpa_tdls_enable_link() + * update a station record with STA_STATE_3. + * + * 2. we are responder + * (1) got TDLS setup request + * wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, NULL, 0); + * create a station record with STA_STATE_1. + * (2) send TDLS setup response + * (3) got TDLS setup confirm + * wpa_tdls_enable_link() + * update a station record with STA_STATE_3. + */ + if ((prStaRec == NULL) || (prStaRec->fgIsInUse == 0)) { + DBGLOG(TDLS, ERROR, " %s: cannot find the peer!\n", __func__); + return TDLS_STATUS_FAILURE; + } + + DBGLOG(TDLS, INFO, " %s: update a peer [%pM] %d -> %d, 0x%x\n", + __func__, (prStaRec->aucMacAddr), + prStaRec->ucStaState, STA_STATE_3, prStaRec->eStaType); + + if (!IS_TDLS_STA(prStaRec)) { + DBGLOG(TDLS, ERROR, " %s: peer is not TDLS one!\n", __func__); + return TDLS_STATUS_FAILURE; + } + + /* check if the add is from the same peer in the 1st unhandled setup request frame */ + DBGLOG(TDLS, INFO, " %s: [%pM] [%pM]\n", + __func__, (prGlueInfo->aucTdlsHtPeerMac), (prCmd->aucPeerMac)); + + if (kalMemCmp(prGlueInfo->aucTdlsHtPeerMac, prCmd->aucPeerMac, 6) == 0) { + /* copy the HT capability from its setup request */ + kalMemCopy(&prStaRec->rTdlsHtCap, &prGlueInfo->rTdlsHtCap, sizeof(IE_HT_CAP_T)); + + prStaRec->ucPhyTypeSet |= PHY_TYPE_SET_802_11N; + prStaRec->u2DesiredNonHTRateSet |= BIT(RATE_HT_PHY_INDEX); + + /* reset backup */ + kalMemZero(&prGlueInfo->rTdlsHtCap, sizeof(prStaRec->rTdlsHtCap)); + kalMemZero(prGlueInfo->aucTdlsHtPeerMac, sizeof(prGlueInfo->aucTdlsHtPeerMac)); + + DBGLOG(TDLS, INFO, " %s: peer is a HT device\n", __func__); + } + + /* update the record join time. */ + GET_CURRENT_SYSTIME(&prStaRec->rUpdateTime); + + /* update Station Record - Status/Reason Code */ + prStaRec->u2StatusCode = prCmd->u2StatusCode; + + /* prStaRec->ucStaState shall be STA_STATE_1 */ + + prStaRec->u2CapInfo = prCmd->u2Capability; + /* prStaRec->u2OperationalRateSet */ + prStaRec->u2AssocId = 0; /* no use */ + prStaRec->u2ListenInterval = 0; /* unknown */ + /* prStaRec->ucDesiredPhyTypeSet */ + /* prStaRec->u2DesiredNonHTRateSet */ + /* prStaRec->u2BSSBasicRateSet */ + /* prStaRec->ucMcsSet */ + /* prStaRec->fgSupMcs32 */ + /* prStaRec->u2HtCapInfo */ + prStaRec->fgIsQoS = TRUE; + prStaRec->fgIsUapsdSupported = (prCmd->UapsdBitmap == 0) ? FALSE : TRUE; + /* prStaRec->ucAmpduParam */ + /* prStaRec->u2HtExtendedCap */ + prStaRec->u4TxBeamformingCap = 0; /* no use */ + prStaRec->ucAselCap = 0; /* no use */ + prStaRec->ucRCPI = 120; + prStaRec->ucBmpTriggerAC = prCmd->UapsdBitmap; + prStaRec->ucBmpDeliveryAC = prCmd->UapsdBitmap; + prStaRec->ucUapsdSp = prCmd->UapsdMaxSp; + + /* update HT */ +#if (TDLS_CFG_HT_SUP == 1) + if (prCmd->fgIsSupHt == FALSE) { + /* no HT IE is from supplicant so we use the backup */ + prHtCap = (IE_HT_CAP_T *) &prStaRec->rTdlsHtCap; + + DBGLOG(TDLS, INFO, " %s: [%pM] update ht ie 0x%x\n", + __func__, (prStaRec->aucMacAddr), prHtCap->ucId); + + if (prHtCap->ucId == ELEM_ID_HT_CAP) { + prStaRec->ucMcsSet = prHtCap->rSupMcsSet.aucRxMcsBitmask[0]; + prStaRec->fgSupMcs32 = (prHtCap->rSupMcsSet.aucRxMcsBitmask[32 / 8] & BIT(0)) ? TRUE : FALSE; + + prStaRec->u2HtCapInfo = prHtCap->u2HtCapInfo; + prStaRec->ucAmpduParam = prHtCap->ucAmpduParam; + prStaRec->u2HtExtendedCap = prHtCap->u2HtExtendedCap; + prStaRec->u4TxBeamformingCap = prHtCap->u4TxBeamformingCap; + prStaRec->ucAselCap = prHtCap->ucAselCap; + prStaRec->ucDesiredPhyTypeSet |= PHY_TYPE_SET_802_11N; + } + } else { + /* TODO: use the HT IE from supplicant */ + } +#endif /* TDLS_CFG_HT_SUP */ + + DBGLOG(TDLS, INFO, " %s: UAPSD 0x%x %d MCS=0x%x\n", + __func__, prCmd->UapsdBitmap, prCmd->UapsdMaxSp, prStaRec->ucMcsSet); + + /* cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); */ + + DBGLOG(TDLS, INFO, " %s: update a peer [%pM], index: %d\n", + __func__, (prStaRec->aucMacAddr), prStaRec->ucIndex); + + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to check if we need to drop a TDLS action frame. +* +* \param[in] *pPkt Pointer to the struct sk_buff->data. +* \param[in] +* \param[in] +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN TdlsexRxFrameDrop(GLUE_INFO_T *prGlueInfo, struct sk_buff *skb) +{ + ADAPTER_T *prAdapter; + UINT8 ucActionId; + UINT_8 *pPkt; + struct ksta_info *prTdlsPeer; + + pPkt = skb->data; + + /* sanity check */ + if ((pPkt == NULL) || (*(pPkt + 12) != 0x89) || (*(pPkt + 13) != 0x0d)) + return FALSE; /* not TDLS data frame htons(0x890d) */ + + ucActionId = *(pPkt + 12 + 2 + 2); /* skip dst, src MAC, type, payload type, category */ + + if (fgIsPtiTimeoutSkip == TRUE) { + /* also skip any tear down frame from the peer */ + if (ucActionId == TDLS_FRM_ACTION_TEARDOWN) + return TRUE; + } + + prAdapter = prGlueInfo->prAdapter; + DBGLOG(TDLS, INFO, "Rcv a TDLS peer [%pM] action frame %d (%u)\n", pPkt + 6, + ucActionId, (UINT32) prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem); + + if (ucActionId == TDLS_FRM_ACTION_TEARDOWN) { + DBGLOG(TDLS, WARN, "Rcv a TDLS tear down frame reason: %d, will DISABLE link\n", + *(pPkt + 13 + 4)); /* reason code */ + + /* record disconnect history */ + TdlsLinkHistoryRecord(prGlueInfo, TRUE, pPkt + 6, FALSE, *(pPkt + 13 + 4), NULL); + + /* inform tear down to supplicant only in OPEN/NONE mode */ + /* + * we need to tear down the link manually; or supplicant will display + * "No FTIE in TDLS Teardown" and it will not tear down the link + */ + cfg80211_tdls_oper_request(GLUE_GET_PKT_IS_P2P(skb) ? + prGlueInfo->prP2PInfo->prDevHandler : + prGlueInfo->prDevHandler, + pPkt + 6, NL80211_TDLS_TEARDOWN, *(pPkt + 13 + 4), GFP_ATOMIC); + /* + * do not indicate to host: + * rekey will fail because the peer created by rekey in initor will be freed + * by the teardown frame from responder + */ + return TRUE; + } + + /* + * used to decide TDLS role: + * only care setup request / response / confirm + * initor: last rx should be CONFIRM + * responder: last rx should be RESPONSE + */ + switch (ucActionId) { + case TDLS_FRM_ACTION_SETUP_REQ: + prTdlsPeer = prGlueInfo->prStaHash[STA_HASH_SIZE]; + /* we only support one TDLS link */ + if (prTdlsPeer && + TDLS_LINK_ENABLED(prTdlsPeer) && + UNEQUAL_MAC_ADDR(prTdlsPeer->aucAddr, pPkt + 6)) { + DBGLOG(TDLS, INFO, "Drop TDLS Setup Request as link already enabled\n"); + return TRUE; + } + + if (prTdlsPeer) + return FALSE; + + /* + * Special case: + * 1. we RX tdls setup request, send setup resp, rx setup confirme + * 2. At this point, TX throughput reach tdls setup THD + * 3. driver request to setup tdls link + * 4. supplicant will disable link + * + * results: + * if the data RX/TX has been triggerred, driver will drop data + * due to STATE_3 error check: + * authSendDeauthFrame:(SAA INFO)Sending Deauth, network: 1, seqNo 50 + * secCheckClassError:(RSN INFO)Send Deauth to [ 02:12:36:71:96:52 ] for Rx Class 3 Error. + * secCheckClassError:(RSN INFO)Host sends Deauth to [ 02:12:36:71:96:52 ] for Rx Class 3 fail. + * + * Solution: + * Stop the tdls setup request by create target peer. + */ + MTKTdlsCreateTarget(prGlueInfo, pPkt + 6, "Rx Setup Frame"); + return FALSE; + case TDLS_FRM_ACTION_CONFIRM: + case TDLS_FRM_ACTION_SETUP_RSP: + prGlueInfo->i4TdlsLastRx = ucActionId; + default: + return FALSE; + } +} + + +VOID TdlsexForwardFrameTag(struct sk_buff *skb, BOOLEAN fgDrop) +{ + /* make a NULL funciton for the use fo TDLS forward debug */ +} + + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to parse some IEs in the setup frame from the peer. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] pPkt Pointer to the ethernet packet +* +* \retval None +* +*/ +/*----------------------------------------------------------------------------*/ +VOID TdlsexRxFrameHandle(GLUE_INFO_T *prGlueInfo, struct sk_buff *skb) +{ + ADAPTER_T *prAdapter; + STA_RECORD_T *prStaRec; + UINT8 ucActionId; + UINT8 *pucPeerMac, ucElmId, ucElmLen; + INT16 s2FmeLen; + ENUM_NETWORK_TYPE_INDEX_T eNetworkType; + UINT_8 *pPkt; + UINT_16 u2PktLen; + + pPkt = skb->data; + u2PktLen = skb->len; + /* sanity check */ + if ((prGlueInfo == NULL) || (pPkt == NULL) || (*(pPkt + 12) != 0x89) || (*(pPkt + 13) != 0x0d)) + return; + + ucActionId = *(pPkt + 12 + 2 + 2); /* skip dst, src MAC, type, payload type, category */ + + if ((ucActionId != TDLS_FRM_ACTION_SETUP_REQ) && (ucActionId != TDLS_FRM_ACTION_SETUP_RSP)) + return; + + /* init */ + prAdapter = prGlueInfo->prAdapter; + pucPeerMac = pPkt + 6; + s2FmeLen = (INT16) u2PktLen; + + DBGLOG(TDLS, TRACE, + " %s: get a setup frame %d from %pM\n", + __func__, ucActionId, (pucPeerMac)); + + if (ucActionId == TDLS_FRM_ACTION_SETUP_REQ) + pPkt += 12 + 2 + 2 + 1 + 1 + 2; /* skip action, dialog token, capability */ + else + pPkt += 12 + 2 + 2 + 1 + 2 + 1 + 2; /* skip action, status code, dialog token, capability */ + + eNetworkType = GLUE_GET_PKT_IS_P2P(skb) ? NETWORK_TYPE_P2P_INDEX : NETWORK_TYPE_AIS_INDEX; + /* check station record */ + prStaRec = cnmGetStaRecByAddress(prGlueInfo->prAdapter, (UINT_8) eNetworkType, pucPeerMac); + + if (prStaRec == NULL) { + prStaRec = cnmStaRecAlloc(prAdapter, (UINT_8) eNetworkType); + + if (prStaRec == NULL) { + /* TODO: only one TDLS entry, need to free old one if timeout */ + DBGLOG(TDLS, ERROR, " %s: alloc prStaRec fail!\n", __func__); + return; + } + + /* init the prStaRec */ + /* prStaRec will be zero first in cnmStaRecAlloc() */ + COPY_MAC_ADDR(prStaRec->aucMacAddr, pucPeerMac); + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + } + + /* backup HT IE to station record */ + /* TODO: Maybe our TDLS only supports non-11n */ + while (s2FmeLen > 0) { + ucElmId = *pPkt++; + ucElmLen = *pPkt++; + + switch (ucElmId) { + case ELEM_ID_HT_CAP: /* 0x2d */ + /* backup the HT IE of 1st unhandled setup request frame */ + if (prGlueInfo->rTdlsHtCap.ucId == 0x00 && + ucElmLen <= sizeof(IE_HT_CAP_T) - 2) { + kalMemCopy(prGlueInfo->aucTdlsHtPeerMac, pucPeerMac, 6); + kalMemCopy(&prGlueInfo->rTdlsHtCap, pPkt - 2, ucElmLen + 2); + + /* + * cannot backup in prStaRec; or + * + * 1. we build a TDLS link + * 2. peer re-sends setup req + * 3. we backup HT cap element + * 4. supplicant disables the link + * 5. we clear the prStaRec + */ + + DBGLOG(TDLS, TRACE, + " %s: %pM: find a HT IE\n", + __func__, (pucPeerMac)); + } + return; + + case ELEM_ID_EXTENDED_CAP: + /* TODO: backup the extended capability IE */ + break; + } + + pPkt += ucElmLen; + s2FmeLen -= (2 + ucElmLen); + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to get the TDLS station record. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval TDLS_STATUS_SUCCESS: this is TDLS packet +* TDLS_STATUS_FAILURE: this is not TDLS packet +*/ +/*----------------------------------------------------------------------------*/ +TDLS_STATUS TdlsexStaRecIdxGet(ADAPTER_T *prAdapter, MSDU_INFO_T *prMsduInfo) +{ + BSS_INFO_T *prBssInfo; + STA_RECORD_T *prStaRec; + TDLS_STATUS Status; + + /* sanity check */ + if ((prAdapter == NULL) || (prMsduInfo == NULL)) + return TDLS_STATUS_FAILURE; + + if (prAdapter->prGlueInfo == NULL) + return TDLS_STATUS_FAILURE; + if (TDLS_IS_NO_LINK_GOING(prAdapter->prGlueInfo)) + return TDLS_STATUS_FAILURE; + + /* get record by ether dest */ + prStaRec = cnmGetStaRecByAddress(prAdapter, prMsduInfo->ucNetworkType, prMsduInfo->aucEthDestAddr); + /* + * Race condiation: + * driver has changed the STA_STATE to STATE_3 + * but firware has not complete the update STA_REC operation, + * which will make data to fimrware without firmware ready to + * TX. Key not paired with peer + */ + if (!prStaRec || !prStaRec->fgIsValid) + return TDLS_STATUS_FAILURE; + + /* init */ + prMsduInfo->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; + Status = TDLS_STATUS_SUCCESS; + + /* + * TDLS Setup Request frames, TDLS Setup Response frames and TDLS Setup Confirm + * frames shall be transmitted through the AP and shall not be transmitted to a group + * address. + * + * 1. In first time, prStaRec == NULL or prStaRec->ucStaState != STA_STATE_3, + * we will send them to AP; + * 2. When link is still on, if you command to send TDLS setup from supplicant, + * supplicant will DISABLE LINK first, prStaRec will be NULL then send TDLS + * setup frame to the peer. + */ + + do { + if ((prStaRec != NULL) && (prStaRec->ucStaState == STA_STATE_3) && (IS_TDLS_STA(prStaRec))) { + /* + * TDLS Test Case 5.3 Tear Down + * Automatically sends TDLS Teardown frame to STA 2 via AP + * + * 11.21.5 TDLS Direct Link Teardown + * The TDLS Teardown frame shall be sent over the direct path and the reason + * code shall be set to "TDLS 40 direct link teardown for unspecified reason", + * except when the TDLS peer STA is unreachable via the TDLS direct link, + * in which case, the TDLS Teardown frame shall be sent through the AP and + * the reason code shall be set to "TDLS direct link teardown due to TDLS peer + * STA unreachable via the TDLS direct link". + */ + /* if (prStaRec->fgIsInPS == TRUE) */ + /* + * check if the packet is tear down: + * we do not want to use PTI to indicate the tear down and + * we want to send the tear down to AP then AP help us to send it + */ + struct sk_buff *prSkb; + UINT8 *pEth; + UINT_16 u2EtherTypeLen; + + prSkb = (struct sk_buff *)prMsduInfo->prPacket; + if (prSkb != NULL) { + UINT8 ucActionCode, ucReasonCode; + + /* init */ + pEth = prSkb->data; + u2EtherTypeLen = (pEth[ETH_TYPE_LEN_OFFSET] << 8) | + (pEth[ETH_TYPE_LEN_OFFSET + 1]); + ucActionCode = pEth[ETH_TYPE_LEN_OFFSET + 1 + 3]; + ucReasonCode = pEth[ETH_TYPE_LEN_OFFSET + 1 + 4] | + (pEth[ETH_TYPE_LEN_OFFSET + 1 + 5] << 8); + + /* TDLS_REASON_CODE_UNREACHABLE: keep alive fail or PTI timeout */ + if ((u2EtherTypeLen == TDLS_FRM_PROT_TYPE) && + (ucActionCode == TDLS_FRM_ACTION_TEARDOWN) && + (ucReasonCode == TDLS_REASON_CODE_UNREACHABLE)) { + /* + * when we cannot reach the peer, + * we need AP's help to send the tear down frame + */ + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]); + prStaRec = prBssInfo->prStaRecOfAP; + if (prStaRec == NULL) { + Status = TDLS_STATUS_FAILURE; + break; + } +#if 0 + /* change status code */ + pEth[ETH_TYPE_LEN_OFFSET + 1 + 4] = TDLS_REASON_CODE_UNREACHABLE; +#endif + } + } + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + } else + Status = TDLS_STATUS_FAILURE; + } while (FALSE); + + DBGLOG(TDLS, TRACE, " %s: (Status=%x) [%pM] ucStaRecIndex = %d!\n", + __func__, (INT32) Status, (prMsduInfo->aucEthDestAddr), + prMsduInfo->ucStaRecIndex); + return Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to check if we suffer timeout for TX quota empty case. +* +* \param[in] prAdapter Pointer to the Adapter structure +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID TdlsexTxQuotaCheck(GLUE_INFO_T *prGlueInfo, STA_RECORD_T *prStaRec, UINT8 FreeQuota) +{ + OS_SYSTIME rCurTime; + + /* sanity check */ + if (!IS_TDLS_STA(prStaRec)) + return; + + if (FreeQuota != 0) { + /* reset timeout */ + prStaRec->rTdlsTxQuotaEmptyTime = 0; + return; + } + + if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + DBGLOG(TDLS, TRACE, "Skip quota check for p2p\n"); + return; + } + + /* work-around: check if the no free quota case is too long */ + GET_CURRENT_SYSTIME(&rCurTime); + + if (prStaRec->rTdlsTxQuotaEmptyTime == 0) { + prStaRec->rTdlsTxQuotaEmptyTime = rCurTime; + } else { + if (CHECK_FOR_TIMEOUT(rCurTime, prStaRec->rTdlsTxQuotaEmptyTime, + SEC_TO_SYSTIME(TDLS_TX_QUOTA_EMPTY_TIMEOUT))) { + /* tear down the link */ + DBGLOG(TDLS, WARN, + " %s: [%pM] TX quota empty timeout!\n", + __func__, (prStaRec->aucMacAddr)); + + /* record disconnect history */ + TdlsLinkHistoryRecord(prGlueInfo, TRUE, prStaRec->aucMacAddr, + TRUE, TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_TX_QUOTA_EMPTY, NULL); + + /* inform tear down to supplicant only in OPEN/NONE mode */ + /* + * we need to tear down the link manually; or supplicant will display + * "No FTIE in TDLS Teardown" and it will not tear down the link + */ + cfg80211_tdls_oper_request(prStaRec->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX ? + prGlueInfo->prDevHandler : + prGlueInfo->prP2PInfo->prDevHandler, + prStaRec->aucMacAddr, NL80211_TDLS_TEARDOWN, + TDLS_REASON_CODE_UNREACHABLE, GFP_ATOMIC); + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to un-initialize variables in TDLS. +* +* \param[in] prAdapter Pointer to the Adapter structure +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID TdlsexUninit(ADAPTER_T *prAdapter) +{ +#if TDLS_CFG_CMD_TEST + cnmTimerStopTimer(prAdapter, &rTdlsTimerTestDataSend); +#endif /* TDLS_CFG_CMD_TEST */ +} + +#endif /* CFG_SUPPORT_TDLS */ + +/* End of tdls.c */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/tdls_com.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/tdls_com.c new file mode 100644 index 0000000000000..2cbd6ae1e81b7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/tdls_com.c @@ -0,0 +1,764 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ + +#include "precomp.h" + +#if (CFG_SUPPORT_TDLS == 1) +#include "tdls.h" + + /******************************************************************************* + * C O N S T A N T S + ******************************************************************************** + */ + + /******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************** + */ + + /******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************** + */ + + /******************************************************************************* + * P R I V A T E F U N C T I O N S + ******************************************************************************** + */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to append general IEs. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] prStaRec Pointer to the STA_RECORD_T structure. +* \param[in] u2StatusCode Status code. +* \param[in] pPkt Pointer to the frame body +* +* \retval append length +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 TdlsFrameGeneralIeAppend(ADAPTER_T *prAdapter, STA_RECORD_T *prStaRec, UINT_16 u2StatusCode, UINT_8 *pPkt) +{ + GLUE_INFO_T *prGlueInfo; + BSS_INFO_T *prBssInfo; + PM_PROFILE_SETUP_INFO_T *prPmProfSetupInfo; + UINT_32 u4NonHTPhyType; + UINT_16 u2SupportedRateSet; + UINT_8 aucAllSupportedRates[RATE_NUM] = { 0 }; + UINT_8 ucAllSupportedRatesLen; + UINT_8 ucSupRatesLen; + UINT_8 ucExtSupRatesLen; + UINT_32 u4PktLen, u4IeLen; + BOOLEAN fg40mAllowed; + + /* reference to assocBuildReAssocReqFrameCommonIEs() */ + + /* init */ + prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + + /* 3. Frame Formation - (5) Supported Rates element */ + /* use all sup rate we can support */ + if (prStaRec != NULL) + u4NonHTPhyType = prStaRec->ucNonHTBasicPhyType; + else + u4NonHTPhyType = PHY_TYPE_ERP_INDEX; /* default */ + + u2SupportedRateSet = rNonHTPhyAttributes[u4NonHTPhyType].u2SupportedRateSet; + + if (prStaRec != NULL) { + u2SupportedRateSet &= prStaRec->u2OperationalRateSet; + + if (u2SupportedRateSet == 0) + u2SupportedRateSet = rNonHTPhyAttributes[u4NonHTPhyType].u2SupportedRateSet; + } + + rateGetDataRatesFromRateSet(u2SupportedRateSet, + prBssInfo->u2BSSBasicRateSet, aucAllSupportedRates, &ucAllSupportedRatesLen); + + ucSupRatesLen = ((ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) ? + ELEM_MAX_LEN_SUP_RATES : ucAllSupportedRatesLen); + + ucExtSupRatesLen = ucAllSupportedRatesLen - ucSupRatesLen; + + if (ucSupRatesLen) { + SUP_RATES_IE(pPkt)->ucId = ELEM_ID_SUP_RATES; + SUP_RATES_IE(pPkt)->ucLength = ucSupRatesLen; + kalMemCopy(SUP_RATES_IE(pPkt)->aucSupportedRates, aucAllSupportedRates, ucSupRatesLen); + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + } + + /* 3. Frame Formation - (7) Extended sup rates element */ + if (ucExtSupRatesLen) { + + EXT_SUP_RATES_IE(pPkt)->ucId = ELEM_ID_EXTENDED_SUP_RATES; + EXT_SUP_RATES_IE(pPkt)->ucLength = ucExtSupRatesLen; + + kalMemCopy(EXT_SUP_RATES_IE(pPkt)->aucExtSupportedRates, + &aucAllSupportedRates[ucSupRatesLen], ucExtSupRatesLen); + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + } + + /* 3. Frame Formation - (8) Supported channels element */ + /* + * The Supported channels element is included in Request frame and also in Response + * frame if Status Code 0 (successful). + */ + if (u2StatusCode == 0) { + SUPPORTED_CHANNELS_IE(pPkt)->ucId = ELEM_ID_SUP_CHS; + SUPPORTED_CHANNELS_IE(pPkt)->ucLength = 2; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[0] = 1; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[1] = 11; + +#if CFG_SUPPORT_DFS + if (prAdapter->fgEnable5GBand == TRUE) { + /* 5G support */ + SUPPORTED_CHANNELS_IE(pPkt)->ucLength = 10; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[2] = 36; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[3] = 4; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[4] = 52; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[5] = 4; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[6] = 149; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[7] = 4; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[8] = 165; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[9] = 4; + } +#endif /* CFG_SUPPORT_DFS */ + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + } + + /* 3. Frame Formation - (14) HT capabilities element */ + + /* no need to check AP capability */ + /* if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) && */ + + /* + * after we set ucPhyTypeSet to PHY_TYPE_SET_802_11N in TdlsexRxFrameHandle(), + * supplicant will disable link if exists and we will clear prStaRec. + * + * finally, prStaRec->ucPhyTypeSet will also be 0 + * + * so we have a fix in TdlsexPeerAdd(). + */ + if (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) { + /* TODO: prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode */ +#if 0 /* always support */ + if (prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode == CONFIG_BW_20M) + fg40mAllowed = FALSE; + else +#endif + fg40mAllowed = TRUE; + + u4IeLen = rlmFillHtCapIEByParams(fg40mAllowed, + prAdapter->rWifiVar.rConnSettings.fgRxShortGIDisabled, + prAdapter->rWifiVar.u8SupportRxSgi20, + prAdapter->rWifiVar.u8SupportRxSgi40, + prAdapter->rWifiVar.u8SupportRxGf, + prAdapter->rWifiVar.u8SupportRxSTBC, prBssInfo->eCurrentOPMode, pPkt); + + pPkt += u4IeLen; + u4PktLen += u4IeLen; + } + + /* 3. Frame Formation - (17) WMM Information element */ + + /* always support */ + /* if (prAdapter->rWifiVar.fgSupportQoS) */ + + { + /* force to support all UAPSD in TDLS link */ + u4IeLen = mqmGenerateWmmInfoIEByParam(TRUE /*prAdapter->rWifiVar.fgSupportUAPSD */, + 0xf /*prPmProfSetupInfo->ucBmpDeliveryAC */, + 0xf /*prPmProfSetupInfo->ucBmpTriggerAC */, + WMM_MAX_SP_LENGTH_ALL /*prPmProfSetupInfo->ucUapsdSp */, + pPkt); + + pPkt += u4IeLen; + u4PktLen += u4IeLen; + } + + return u4PktLen; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to transmit a TDLS data frame (setup req/rsp/confirm and tear down). +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] prStaRec Pointer to the STA_RECORD_T structure. +* \param[in] pPeerMac Pointer to the MAC of the TDLS peer +* \param[in] ucActionCode TDLS Action +* \param[in] ucDialogToken Dialog token +* \param[in] u2StatusCode Status code +* \param[in] pAppendIe Others IEs (here are security IEs from supplicant) +* \param[in] AppendIeLen IE length of others IEs +* +* \retval TDLS_STATUS_xx +*/ +/*----------------------------------------------------------------------------*/ +TDLS_STATUS +TdlsDataFrameSend(ADAPTER_T *prAdapter, + STA_RECORD_T *prStaRec, + TDLS_MGMT_TX_INFO *prMgmtTxInfo) +{ +#define LR_TDLS_FME_FIELD_FILL(__Len) \ +do { \ + pPkt += __Len; \ + u4PktLen += __Len; \ +} while (0) + + GLUE_INFO_T *prGlueInfo; + ENUM_NETWORK_TYPE_INDEX_T eNetworkType; + BSS_INFO_T *prBssInfo; + PM_PROFILE_SETUP_INFO_T *prPmProfSetupInfo; + struct sk_buff *prMsduInfo; + MSDU_INFO_T *prMsduInfoMgmt; + UINT8 *pPkt, *pucInitiator, *pucResponder; + UINT32 u4PktLen, u4IeLen; + UINT16 u2CapInfo; + /* UINT8 *pPktTemp; */ + + UINT_8 *pPeerMac; + UINT_8 ucActionCode; + UINT_8 ucDialogToken; + UINT_16 u2StatusCode; + UINT_8 *pAppendIe; + UINT_32 AppendIeLen; + + prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; + + DBGLOG(TDLS, TRACE, " %s: network type: %d 2040=%d\n", __func__, + prMgmtTxInfo->eNetworkType, + prGlueInfo->rTdlsLink.fgIs2040Sup); + + pPeerMac = prMgmtTxInfo->aucPeer; + ucActionCode = prMgmtTxInfo->ucActionCode; + ucDialogToken = prMgmtTxInfo->ucDialogToken; + u2StatusCode = prMgmtTxInfo->u2StatusCode; + pAppendIe = (UINT_8 *) prMgmtTxInfo->aucSecBuf; + AppendIeLen = prMgmtTxInfo->u4SecBufLen; + + eNetworkType = prMgmtTxInfo->eNetworkType; + /* sanity check */ + if (prStaRec != NULL) { + if (prStaRec->ucNetTypeIndex >= NETWORK_TYPE_INDEX_NUM) { + DBGLOG(TDLS, ERROR, + " %s: net index %d fail\n", __func__, prStaRec->ucNetTypeIndex); + return TDLS_STATUS_FAILURE; + } + + eNetworkType = prStaRec->ucNetTypeIndex; + } + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkType]); + + /* allocate/init packet */ + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + prMsduInfo = NULL; + prMsduInfoMgmt = NULL; + + /* make up frame content */ + if (ucActionCode != TDLS_FRM_ACTION_DISCOVERY_RESPONSE) { + /* + * The STAUT will not respond to a TDLS Discovery Request Frame with different BSSID. + * Supplicant will check this in wpa_tdls_process_discovery_request(). + */ + + /* TODO: reduce 1600 to correct size */ + prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); + if (prMsduInfo == NULL) { + DBGLOG(TDLS, ERROR, " %s: allocate pkt fail\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + if (eNetworkType == NETWORK_TYPE_AIS_INDEX) + prMsduInfo->dev = prGlueInfo->prDevHandler; + else + prMsduInfo->dev = prGlueInfo->prP2PInfo->prDevHandler; + + if (prMsduInfo->dev == NULL) { + DBGLOG(TDLS, ERROR, " %s: MsduInfo->dev == NULL\n", __func__); + kalPacketFree(prGlueInfo, prMsduInfo); + return TDLS_STATUS_FAILURE; + } + + /* 1. 802.3 header */ + /* pPktTemp = pPkt; */ + kalMemCopy(pPkt, pPeerMac, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(pPkt, prBssInfo->aucOwnMacAddr, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); + LR_TDLS_FME_FIELD_FILL(2); + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (1) Category */ + *pPkt = TDLS_FRM_CATEGORY; + LR_TDLS_FME_FIELD_FILL(1); + } else { + /* discovery response */ + WLAN_MAC_HEADER_T *prHdr; + + prMsduInfoMgmt = (MSDU_INFO_T *) + cnmMgtPktAlloc(prAdapter, PUBLIC_ACTION_MAX_LEN); + if (prMsduInfoMgmt == NULL) { + DBGLOG(TDLS, ERROR, " %s: allocate mgmt pkt fail\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + pPkt = (UINT8 *) prMsduInfoMgmt->prPacket; + prHdr = (WLAN_MAC_HEADER_T *) pPkt; + + /* 1. 802.11 header */ + prHdr->u2FrameCtrl = MAC_FRAME_ACTION; + prHdr->u2DurationID = 0; + kalMemCopy(prHdr->aucAddr1, pPeerMac, TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(prHdr->aucAddr2, prBssInfo->aucOwnMacAddr, TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(prHdr->aucAddr3, prBssInfo->aucBSSID, TDLS_FME_MAC_ADDR_LEN); + prHdr->u2SeqCtrl = 0; + LR_TDLS_FME_FIELD_FILL(sizeof(WLAN_MAC_HEADER_T)); + + /* Frame Formation - (1) Category */ + *pPkt = CATEGORY_PUBLIC_ACTION; + LR_TDLS_FME_FIELD_FILL(1); + } + + /* 3. Frame Formation - (2) Action */ + *pPkt = ucActionCode; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - Status Code */ + switch (ucActionCode) { + case TDLS_FRM_ACTION_SETUP_RSP: + case TDLS_FRM_ACTION_CONFIRM: + case TDLS_FRM_ACTION_TEARDOWN: + WLAN_SET_FIELD_16(pPkt, u2StatusCode); + LR_TDLS_FME_FIELD_FILL(2); + break; + } + + /* 3. Frame Formation - (3) Dialog token */ + if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { + *pPkt = ucDialogToken; + LR_TDLS_FME_FIELD_FILL(1); + } + + /* Fill elements */ + if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { + /* + * Capability + * + * Support Rates + * Extended Support Rates + * Supported Channels + * HT Capabilities + * WMM Information Element + * + * Extended Capabilities + * Link Identifier + * + * RSNIE + * FTIE + * Timeout Interval + */ + if (ucActionCode != TDLS_FRM_ACTION_CONFIRM) { + /* 3. Frame Formation - (4) Capability: 0x31 0x04, privacy bit will be set */ + u2CapInfo = assocBuildCapabilityInfo(prAdapter, prStaRec); + WLAN_SET_FIELD_16(pPkt, u2CapInfo); + LR_TDLS_FME_FIELD_FILL(2); + + /* 4. Append general IEs */ + /* + * TODO check HT: prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode + * must be CONFIG_BW_20_40M. + * + * TODO check HT: HT_CAP_INFO_40M_INTOLERANT must be clear if + * Tdls 20/40 is enabled. + */ + u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, prStaRec, u2StatusCode, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 5. Frame Formation - Extended capabilities element */ + EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP; + EXT_CAP_IE(pPkt)->ucLength = 5; + + EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */ + EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */ + EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */ + + /* if (prCmd->ucExCap & TDLS_EX_CAP_PEER_UAPSD) */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24)); + /* if (prCmd->ucExCap & TDLS_EX_CAP_CHAN_SWITCH) */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24)); + /* if (prCmd->ucExCap & TDLS_EX_CAP_TDLS) */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32)); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } else { + /* 5. Frame Formation - WMM Parameter element */ + if (prAdapter->rWifiVar.fgSupportQoS) { + u4IeLen = mqmGenerateWmmParamIEByParam(prAdapter, + prBssInfo, pPkt, OP_MODE_INFRASTRUCTURE); + + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } + } + } + + /* 6. Frame Formation - 20/40 BSS Coexistence */ + /* + * Follow WiFi test plan, add 20/40 element to request/response/confirm. + */ + /* if (prGlueInfo->rTdlsLink.fgIs2040Sup == TRUE) */ /* force to enable */ + if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { + /* + * bit0 = 1: The Information Request field is used to indicate that a + * transmitting STA is requesting the recipient to transmit a 20/40 BSS + * Coexistence Management frame with the transmitting STA as the + * recipient. + * + * bit1 = 0: The Forty MHz Intolerant field is set to 1 to prohibit an AP + * that receives this information or reports of this information from + * operating a 20/40 MHz BSS. + * + * bit2 = 0: The 20 MHz BSS Width Request field is set to 1 to prohibit + * a receiving AP from operating its BSS as a 20/40 MHz BSS. + */ + BSS_20_40_COEXIST_IE(pPkt)->ucId = ELEM_ID_20_40_BSS_COEXISTENCE; + BSS_20_40_COEXIST_IE(pPkt)->ucLength = 1; + BSS_20_40_COEXIST_IE(pPkt)->ucData = 0x01; + LR_TDLS_FME_FIELD_FILL(3); + } + + /* 6. Frame Formation - HT Operation element */ + /* u4IeLen = rlmFillHtOpIeBody(prBssInfo, pPkt); */ + /* LR_TDLS_FME_FIELD_FILL(u4IeLen); */ + + /* 7. Frame Formation - Link identifier element */ + /* Note1: Link ID sequence must be correct; Or the calculated MIC will be error */ + /* + * Note2: When we receive a setup request with link ID, Marvell will send setup response + * to the peer in link ID, not the SA in the WLAN header. + */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = ELEM_LEN_LINK_IDENTIFIER; + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); + + switch (ucActionCode) { + case TDLS_FRM_ACTION_SETUP_REQ: + case TDLS_FRM_ACTION_CONFIRM: + default: + /* we are initiator */ + pucInitiator = prBssInfo->aucOwnMacAddr; + pucResponder = pPeerMac; + + if (prStaRec != NULL) + prStaRec->flgTdlsIsInitiator = TRUE; + break; + + case TDLS_FRM_ACTION_SETUP_RSP: + case TDLS_FRM_ACTION_DISCOVERY_RESPONSE: + /* peer is initiator */ + pucInitiator = pPeerMac; + pucResponder = prBssInfo->aucOwnMacAddr; + + if (prStaRec != NULL) + prStaRec->flgTdlsIsInitiator = FALSE; + break; + + case TDLS_FRM_ACTION_TEARDOWN: + if (prStaRec != NULL) { + if (prStaRec->flgTdlsIsInitiator == TRUE) { + /* we are initiator */ + pucInitiator = prBssInfo->aucOwnMacAddr; + pucResponder = pPeerMac; + } else { + /* peer is initiator */ + pucInitiator = pPeerMac; + pucResponder = prBssInfo->aucOwnMacAddr; + } + } else { + /* peer is initiator */ + pucInitiator = pPeerMac; + pucResponder = prBssInfo->aucOwnMacAddr; + } + break; + } + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, pucInitiator, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, pucResponder, 6); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 8. Append security IEs */ + /* + * 11.21.5 TDLS Direct Link Teardown + * If the STA has security enabled on the link 37 with the AP, then the FTIE shall be + * included in the TDLS Teardown frame. + * + * For ralink station, it can accept our tear down without FTIE but marvell station. + */ + /* if ((ucActionCode != TDLS_FRM_ACTION_TEARDOWN) && (pAppendIe != NULL)) */ + if (pAppendIe != NULL) { + if ((ucActionCode != TDLS_FRM_ACTION_TEARDOWN) || + ((ucActionCode == TDLS_FRM_ACTION_TEARDOWN) && + (prStaRec != NULL) && (prStaRec->fgTdlsInSecurityMode == TRUE))) { + kalMemCopy(pPkt, pAppendIe, AppendIeLen); + LR_TDLS_FME_FIELD_FILL(AppendIeLen); + } + } + + /* 7. Append Supported Operating Classes IE */ + if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { + /* Note: if we do not put the IE, Marvell STA will decline our TDLS setup request */ + u4IeLen = rlmDomainSupOperatingClassIeFill(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } + + /* 11. send the data or management frame */ + if (ucActionCode != TDLS_FRM_ACTION_DISCOVERY_RESPONSE) { +#if 0 + /* + * Note1: remember to modify our MAC & AP MAC & peer MAC in LINK ID + * Note2: dialog token in rsp & confirm must be same as sender. + */ + +#if 1 + /* example for Ralink's and Broadcom's TDLS setup request frame in open/none */ + if (ucActionCode == TDLS_FRM_ACTION_SETUP_REQ) { +#if 0 + /* mediatek */ + char buffer[] = { 0x31, 0x04, + 0x01, 0x08, 0x02, 0x04, 0x0b, 0x16, 0xc, 0x12, 0x18, 0x24, + 0x32, 0x04, 0x30, 0x48, 0x60, 0x6c, + 0x24, 0x0a, 0x01, 0x0b, 0x24, 0x04, 0x34, 0x04, 0x95, 0x04, 0xa5, 0x01, + 0x2d, 0x1a, 0x72, 0x11, 0x03, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0xdd, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x0f, + 0x7f, 0x05, 0x00, 0x00, 0x00, 0x50, 0x20, + 0x48, 0x01, 0x01, + 0x65, 0x12, 0x00, 0x0c, 0x43, 0x31, 0x35, 0x97, 0x00, 0x11, 0x22, 0x33, + 0x44, 0x05, 0x00, 0x22, 0x58, 0x00, 0xcc, 0x0f, + 0x3b, 0x0d, 0x0c, 0x01, 0x02, 0x03, 0x05, 0x16, 0x17, 0x19, + 0x1b, 0x1c, 0x1e, 0x20, 0x21, + 0x07, 0x06, 0x55, 0x53, 0x20, 0x01, 0x0b, 0x1e + }; +#endif + +#if 1 + /* ralink *//* from capability */ + char buffer[] = { 0x21, 0x04, + 0x01, 0x08, 0x82, 0x84, 0x8b, 0x96, 0x12, 0x24, 0x48, 0x6c, + 0x07, 0x06, 0x55, 0x53, 0x20, 0xdd, 0x20, 0x00, + 0x32, 0x04, 0x0c, 0x18, 0x30, 0x60, + 0x24, 0x06, 0x01, 0x0b, 0x24, 0x08, 0x95, 0x04, + 0x7f, 0x05, 0x01, 0x00, 0x00, 0x50, 0x20, + 0x3b, 0x10, 0x20, 0x01, 0x02, 0x03, 0x04, 0x0c, 0x16, 0x17, 0x18, 0x19, + 0x1b, 0x1c, 0x1d, 0x1e, 0x20, 0x21, + 0x2d, 0x1a, 0x6e, 0x00, 0x17, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x48, 0x01, 0x01, + 0x65, 0x12, 0x00, 0x0c, 0x43, 0x44, 0x0b, 0x1a, 0x00, 0x11, 0x22, 0x33, + 0x44, 0x05, 0x00, 0x22, 0x58, 0x00, 0xcc, 0x0f, + 0xdd, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x0f + }; +#endif +#if 0 + /* 6630 */ + char buffer[] = { 0x01, 0x01, + 0x01, 0x04, 0x02, 0x04, 0x0b, 0x16, + 0x24, 0x02, 0x01, 0x0d, + 0x7f, 0x05, 0x00, 0x00, 0x00, 0x50, 0xff, + 0x2d, 0x1a, 0x61, 0x01, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x38, 0x05, 0x02, 0xc0, 0xa8, 0x00, 0x00, + 0x48, 0x01, 0x01, + 0x3b, 0x0d, 0x0c, 0x01, 0x02, 0x03, 0x05, 0x16, 0x17, 0x19, + 0x1b, 0x1c, 0x1d, 0x1e, 0x20, 0x21, + 0x07, 0x06, 0x55, 0x53, 0x20, 0x01, 0x0b, 0x1e, + 0x65, 0x12, 0x00, 0x0c, 0x43, 0x44, 0x0b, 0x1a, 0x00, 0x11, 0x22, 0x33, + 0x44, 0x05, 0x00, 0x22, 0x58, 0x00, 0xcc, 0x0f, + 0xdd, 0x18, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, + 0xbf, 0x0c, 0x30, 0x01, 0x80, 0x03, 0xfe, 0xff, 0x00, 0x00, 0xfe, 0xff, + 0x00, 0x00 + }; +#endif + + pPktTemp += 18; + memcpy(pPktTemp, buffer, sizeof(buffer)); + u4PktLen = 18 + sizeof(buffer); + } +#endif + +#if 1 + if (ucActionCode == TDLS_FRM_ACTION_CONFIRM) { + /* Note: dialog token must be same as request */ +#if 1 + /* ralink */ + char buffer[] = { 0x00, + 0x01, 0x2d, 0x1a, 0x6e, 0x00, 0x17, 0xff, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x65, 0x12, 0x00, 0x0c, 0x43, 0x44, 0x0b, 0x1a, 0x00, 0x11, 0x22, 0x33, + 0x44, 0x05, 0x00, 0x22, 0x58, 0x00, 0xcc, 0x0f, + 0xdd, 0x18, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x0f, 0x00, 0x03, + 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, 0x42, 0x43, 0x5e, 0x00, + 0x62, 0x32, 0x2f, 0x00 + }; +#endif + +#if 0 + /* 6630 */ + char buffer[] = { 0x00, + 0x01, + 0x38, 0x05, 0x02, 0xc0, 0xa8, 0x00, 0x00, + 0x48, 0x01, 0x01, + 0x3b, 0x0d, 0x0c, 0x01, 0x02, 0x03, 0x05, 0x16, 0x17, 0x19, + 0x1b, 0x1c, 0x1d, 0x1e, 0x20, 0x21, + 0x07, 0x06, 0x55, 0x53, 0x20, 0x01, 0x0b, 0x1e, + 0x65, 0x12, 0x00, 0x0c, 0x43, 0x44, 0x0b, 0x1a, 0x00, 0x11, 0x22, 0x33, + 0x44, 0x05, 0x00, 0x22, 0x58, 0x00, 0xcc, 0x0f, + 0xdd, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00, + 0xdd, 0x18, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x3f, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00 + }; +#endif + +#if 0 + /* A/D die */ + char buffer[] = { 0x00, + 0x01, + 0xdd, 0x18, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x0f, 0x6b, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00 0x65, 0x12, 0x00, 0x0c, 0x43, 0x31, 0x35, 0x97, 0x00, 0x11, 0x22, 0x33, + 0x44, 0x05, 0x00, 0x22, 0x58, 0x00, 0xcc, 0x0f, + 0x38, 0x0d, 0x0c, 0x01, 0x02, 0x03, 0x05, 0x16, 0x17, 0x19, 0x1b, + 0x1c, 0x1e, 0x20, 0x21, + 0x07, 0x06, 0x55, 0x53, 0x20, 0x01, 0x0b, 0x1e + }; +#endif + + pPktTemp += 18; + memcpy(pPktTemp, buffer, sizeof(buffer)); + u4PktLen = 18 + sizeof(buffer); + } +#endif + +#else + +#if 0 + /* for test in open/none */ + if (ucActionCode == TDLS_FRM_ACTION_SETUP_REQ) { + char buffer[] = { 0x01, 0x04, + 0x01, 0x08, 0x82, 0x84, 0x8b, 0x96, 0x12, 0x24, 0x48, 0x6c, + 0x07, 0x06, 0x55, 0x53, 0x20, 0xdd, 0x20, 0x00, + 0x32, 0x04, 0x30, 0x48, 0x60, 0x6c, + 0x24, 0x0a, 0x01, 0x0b, 0x24, 0x04, 0x34, 0x04, 0x95, 0x04, 0xa5, 0x01, + 0x2d, 0x1a, 0x72, 0x11, 0x03, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0xdd, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x0f, + 0x7f, 0x05, 0x00, 0x00, 0x00, 0x50, 0x20, + 0x48, 0x01, 0x01, + 0x65, 0x12, 0x00, 0x0c, 0x43, 0x44, 0x0b, 0x1a, 0x00, 0x11, 0x22, 0x33, + 0x44, 0x05, 0x00, 0x22, 0x58, 0x00, 0xcc, 0x0f, + 0x3b, 0x0d, 0x0c, 0x01, 0x02, 0x03, 0x05, 0x16, 0x17, 0x19, + 0x1b, 0x1c, 0x1e, 0x20, 0x21 + }; + + pPktTemp += 18; + memcpy(pPktTemp, buffer, sizeof(buffer)); + u4PktLen = 18 + sizeof(buffer); + } +#endif +#endif /* 0 */ + + /* 9. Update packet length */ + prMsduInfo->len = u4PktLen; + /* dumpMemory8(prMsduInfo->data, u4PktLen); */ + DBGLOG_MEM8(TDLS, TRACE, prMsduInfo->data, u4PktLen); + DBGLOG(TDLS, INFO, "Send TDLS action %d len %u by network %d\n", + ucActionCode, u4PktLen, eNetworkType); + prGlueInfo->i4TdlsLastTx = ucActionCode; + prGlueInfo->eTdlsNetworkType = eNetworkType; + if (eNetworkType == NETWORK_TYPE_AIS_INDEX) + wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); + else + p2pHardStartXmit(prMsduInfo, prMsduInfo->dev); + } else { + /* + * A TDLS capable STA that receives a TDLS Discovery Request frame is required to + * send the response "to the requesting STA, via the direct path." + * However, prior to establishment of the direct link, the responding STA may not + * know the rate capabilities of the requesting STA. In this case, the responding + * STA shall send the TDLS Discovery Response frame using a rate from the + * BSSBasicRateSet of the BSS to which the STA is currently associated. + */ + DBGLOG(TDLS, INFO, "Send TDLS Discovery Response by network %d\n", eNetworkType); + prMsduInfoMgmt->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfoMgmt->ucStaRecIndex = prBssInfo->prStaRecOfAP->ucIndex; + prMsduInfoMgmt->ucNetworkType = prBssInfo->ucNetTypeIndex; + prMsduInfoMgmt->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfoMgmt->fgIs802_1x = FALSE; + prMsduInfoMgmt->fgIs802_11 = TRUE; + prMsduInfoMgmt->u2FrameLength = u4PktLen; + prMsduInfoMgmt->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfoMgmt->pfTxDoneHandler = NULL; + prMsduInfoMgmt->fgIsBasicRate = TRUE; /* use basic rate */ + + /* Send them to HW queue */ + nicTxEnqueueMsdu(prAdapter, prMsduInfoMgmt); + } + + return TDLS_STATUS_SUCCESS; +} + +#endif /* CFG_SUPPORT_TDLS */ + + /* End of tdls_com.c */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/wapi.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/wapi.c new file mode 100644 index 0000000000000..f65fc31bdbbd8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/wapi.c @@ -0,0 +1,421 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E 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 parse WAPI IE. +* +* \param[in] prInfoElem Pointer to the RSN IE +* \param[out] prRsnInfo Pointer to the BSSDescription structure to store the +** WAPI information from the given WAPI IE +* +* \retval TRUE - Succeeded +* \retval FALSE - Failed +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wapiParseWapiIE(IN P_WAPI_INFO_ELEM_T prInfoElem, OUT P_WAPI_INFO_T prWapiInfo) +{ + UINT_32 i; + INT_32 u4RemainWapiIeLen; + UINT_16 u2Version; + UINT_16 u2Cap = 0; + UINT_32 u4GroupSuite = WAPI_CIPHER_SUITE_WPI; + UINT_16 u2PairSuiteCount = 0; + UINT_16 u2AuthSuiteCount = 0; + PUCHAR pucPairSuite = NULL; + PUCHAR pucAuthSuite = NULL; + PUCHAR cp; + + DEBUGFUNC("wapiParseWapiIE"); + + ASSERT(prInfoElem); + ASSERT(prWapiInfo); + + /* Verify the length of the WAPI IE. */ + if (prInfoElem->ucLength < 6) { + DBGLOG(SEC, TRACE, "WAPI IE length too short (length=%d)\n", prInfoElem->ucLength); + return FALSE; + } + + /* Check WAPI version: currently, we only support version 1. */ + WLAN_GET_FIELD_16(&prInfoElem->u2Version, &u2Version); + if (u2Version != 1) { + DBGLOG(SEC, TRACE, "Unsupported WAPI IE version: %d\n", u2Version); + return FALSE; + } + + cp = (PUCHAR) &prInfoElem->u2AuthKeyMgtSuiteCount; + u4RemainWapiIeLen = (INT_32) prInfoElem->ucLength - 2; + + do { + if (u4RemainWapiIeLen == 0) + break; + + /* + * AuthCount : 2 + * AuthSuite : 4 * authSuiteCount + * PairwiseCount: 2 + * PairwiseSuite: 4 * pairSuiteCount + * GroupSuite : 4 + * Cap : 2 + */ + + /* + * Parse the Authentication and Key Management Cipher Suite Count + * field. + */ + if (u4RemainWapiIeLen < 2) { + DBGLOG(SEC, TRACE, "Fail to parse WAPI IE in auth & key mgt suite count (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + WLAN_GET_FIELD_16(cp, &u2AuthSuiteCount); + cp += 2; + u4RemainWapiIeLen -= 2; + + /* + * Parse the Authentication and Key Management Cipher Suite List + * field. + */ + i = (UINT_32) u2AuthSuiteCount * 4; + if (u4RemainWapiIeLen < (INT_32) i) { + DBGLOG(SEC, TRACE, "Fail to parse WAPI IE in auth & key mgt suite list (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + pucAuthSuite = cp; + + cp += i; + u4RemainWapiIeLen -= (INT_32) i; + + if (u4RemainWapiIeLen == 0) + break; + + /* Parse the Pairwise Key Cipher Suite Count field. */ + if (u4RemainWapiIeLen < 2) { + DBGLOG(SEC, TRACE, "Fail to parse WAPI IE in pairwise cipher suite count (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + WLAN_GET_FIELD_16(cp, &u2PairSuiteCount); + cp += 2; + u4RemainWapiIeLen -= 2; + + /* Parse the Pairwise Key Cipher Suite List field. */ + i = (UINT_32) u2PairSuiteCount * 4; + if (u4RemainWapiIeLen < (INT_32) i) { + DBGLOG(SEC, TRACE, "Fail to parse WAPI IE in pairwise cipher suite list (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + pucPairSuite = cp; + + cp += i; + u4RemainWapiIeLen -= (INT_32) i; + + /* Parse the Group Key Cipher Suite field. */ + if (u4RemainWapiIeLen < 4) { + DBGLOG(SEC, TRACE, "Fail to parse WAPI IE in group cipher suite (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + WLAN_GET_FIELD_32(cp, &u4GroupSuite); + cp += 4; + u4RemainWapiIeLen -= 4; + + /* Parse the WAPI u2Capabilities field. */ + if (u4RemainWapiIeLen < 2) { + DBGLOG(SEC, TRACE, "Fail to parse WAPI IE in WAPI capabilities (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + WLAN_GET_FIELD_16(cp, &u2Cap); + u4RemainWapiIeLen -= 2; + + /* Todo:: BKID support */ + } while (FALSE); + + /* Save the WAPI information for the BSS. */ + + prWapiInfo->ucElemId = ELEM_ID_WAPI; + + prWapiInfo->u2Version = u2Version; + + prWapiInfo->u4GroupKeyCipherSuite = u4GroupSuite; + + DBGLOG(SEC, LOUD, "WAPI: version %d, group key cipher suite %02x-%02x-%02x-%02x\n", + u2Version, (UCHAR) (u4GroupSuite & 0x000000FF), + (UCHAR) ((u4GroupSuite >> 8) & 0x000000FF), + (UCHAR) ((u4GroupSuite >> 16) & 0x000000FF), (UCHAR) ((u4GroupSuite >> 24) & 0x000000FF)); + + if (pucPairSuite) { + /* The information about the pairwise key cipher suites is present. */ + if (u2PairSuiteCount > MAX_NUM_SUPPORTED_WAPI_CIPHER_SUITES) + u2PairSuiteCount = MAX_NUM_SUPPORTED_WAPI_CIPHER_SUITES; + + prWapiInfo->u4PairwiseKeyCipherSuiteCount = (UINT_32) u2PairSuiteCount; + + for (i = 0; i < (UINT_32) u2PairSuiteCount; i++) { + WLAN_GET_FIELD_32(pucPairSuite, &prWapiInfo->au4PairwiseKeyCipherSuite[i]); + pucPairSuite += 4; + + DBGLOG(SEC, LOUD, "WAPI: pairwise key cipher suite [%d]: %02x-%02x-%02x-%02x\n", + (UINT_8) i, (UCHAR) (prWapiInfo->au4PairwiseKeyCipherSuite[i] & 0x000000FF), + (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[i] >> 8) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[i] >> 16) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[i] >> 24) & 0x000000FF)); + } + } else { + /* + * The information about the pairwise key cipher suites is not present. + * Use the default chipher suite for WAPI: WPI. + */ + prWapiInfo->u4PairwiseKeyCipherSuiteCount = 1; + prWapiInfo->au4PairwiseKeyCipherSuite[0] = WAPI_CIPHER_SUITE_WPI; + + DBGLOG(SEC, LOUD, "WAPI: pairwise key cipher suite: %02x-%02x-%02x-%02x (default)\n", + (UCHAR) (prWapiInfo->au4PairwiseKeyCipherSuite[0] & 0x000000FF), + (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[0] >> 8) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[0] >> 16) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[0] >> 24) & 0x000000FF)); + } + + if (pucAuthSuite) { + /* + * The information about the authentication and key management suites + * is present. + */ + if (u2AuthSuiteCount > MAX_NUM_SUPPORTED_WAPI_AKM_SUITES) + u2AuthSuiteCount = MAX_NUM_SUPPORTED_WAPI_AKM_SUITES; + + prWapiInfo->u4AuthKeyMgtSuiteCount = (UINT_32) u2AuthSuiteCount; + + for (i = 0; i < (UINT_32) u2AuthSuiteCount; i++) { + WLAN_GET_FIELD_32(pucAuthSuite, &prWapiInfo->au4AuthKeyMgtSuite[i]); + pucAuthSuite += 4; + + DBGLOG(SEC, LOUD, "WAPI: AKM suite [%d]: %02x-%02x-%02x-%02x\n", + (UINT_8) i, (UCHAR) (prWapiInfo->au4AuthKeyMgtSuite[i] & 0x000000FF), + (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[i] >> 8) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[i] >> 16) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[i] >> 24) & 0x000000FF)); + } + } else { + /* + * The information about the authentication and key management suites + * is not present. Use the default AKM suite for WAPI. + */ + prWapiInfo->u4AuthKeyMgtSuiteCount = 1; + prWapiInfo->au4AuthKeyMgtSuite[0] = WAPI_AKM_SUITE_802_1X; + + DBGLOG(SEC, LOUD, "WAPI: AKM suite: %02x-%02x-%02x-%02x (default)\n", + (UCHAR) (prWapiInfo->au4AuthKeyMgtSuite[0] & 0x000000FF), + (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[0] >> 8) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[0] >> 16) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[0] >> 24) & 0x000000FF)); + } + + prWapiInfo->u2WapiCap = u2Cap; + DBGLOG(SEC, LOUD, "WAPI: cap: 0x%04x\n", prWapiInfo->u2WapiCap); + + return TRUE; +} /* wapiParseWapiIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to perform WAPI policy selection for a given BSS. +* +* \param[in] prAdapter Pointer to the adapter object data area. +* \param[in] prBss Pointer to the BSS description +* +* \retval TRUE - The WAPI policy selection for the given BSS is +* successful. The selected pairwise and group cipher suites +* are returned in the BSS description. +* \retval FALSE - The WAPI policy selection for the given BSS is failed. +* The driver shall not attempt to join the given BSS. +* +* \note The Encrypt status matched score will save to bss for final ap select. +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wapiPerformPolicySelection(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBss) +{ + UINT_32 i; + UINT_32 u4PairwiseCipher = 0; + UINT_32 u4GroupCipher = 0; + UINT_32 u4AkmSuite = 0; + P_WAPI_INFO_T prBssWapiInfo; + P_WLAN_INFO_T prWlanInfo; + + DEBUGFUNC("wapiPerformPolicySelection"); + + ASSERT(prBss); + + /* Notice!!!! WAPI AP not set the privacy bit for WAI and WAI-PSK at WZC configuration mode */ + prWlanInfo = &prAdapter->rWlanInfo; + + if (prBss->fgIEWAPI) { + prBssWapiInfo = &prBss->rIEWAPI; + } else { + if (prAdapter->rWifiVar.rConnSettings.fgWapiMode == FALSE) { + DBGLOG(SEC, TRACE, "-- No Protected BSS\n"); + return TRUE; + } + DBGLOG(SEC, TRACE, "WAPI Information Element does not exist.\n"); + return FALSE; + } + + /* Select pairwise/group ciphers */ + for (i = 0; i < prBssWapiInfo->u4PairwiseKeyCipherSuiteCount; i++) { + if (prBssWapiInfo->au4PairwiseKeyCipherSuite[i] == + prAdapter->rWifiVar.rConnSettings.u4WapiSelectedPairwiseCipher) { + u4PairwiseCipher = prBssWapiInfo->au4PairwiseKeyCipherSuite[i]; + } + } + if (prBssWapiInfo->u4GroupKeyCipherSuite == prAdapter->rWifiVar.rConnSettings.u4WapiSelectedGroupCipher) + u4GroupCipher = prBssWapiInfo->u4GroupKeyCipherSuite; + + /* Exception handler */ + /* + * If we cannot find proper pairwise and group cipher suites to join the + * BSS, do not check the supported AKM suites. + */ + if (u4PairwiseCipher == 0 || u4GroupCipher == 0) { + DBGLOG(SEC, TRACE, "Failed to select pairwise/group cipher (0x%08x/0x%08x)\n", + u4PairwiseCipher, u4GroupCipher); + return FALSE; + } + + /* Select AKM */ + /* + * If the driver cannot support any authentication suites advertised in + * the given BSS, we fail to perform RSNA policy selection. + */ + /* Attempt to find any overlapping supported AKM suite. */ + for (i = 0; i < prBssWapiInfo->u4AuthKeyMgtSuiteCount; i++) { + if (prBssWapiInfo->au4AuthKeyMgtSuite[i] == prAdapter->rWifiVar.rConnSettings.u4WapiSelectedAKMSuite) { + u4AkmSuite = prBssWapiInfo->au4AuthKeyMgtSuite[i]; + break; + } + } + + if (u4AkmSuite == 0) { + DBGLOG(SEC, TRACE, "Cannot support any AKM suites\n"); + return FALSE; + } + + DBGLOG(SEC, TRACE, "Selected pairwise/group cipher: %02x-%02x-%02x-%02x/%02x-%02x-%02x-%02x\n", + (UINT_8) (u4PairwiseCipher & 0x000000FF), + (UINT_8) ((u4PairwiseCipher >> 8) & 0x000000FF), + (UINT_8) ((u4PairwiseCipher >> 16) & 0x000000FF), + (UINT_8) ((u4PairwiseCipher >> 24) & 0x000000FF), + (UINT_8) (u4GroupCipher & 0x000000FF), + (UINT_8) ((u4GroupCipher >> 8) & 0x000000FF), + (UINT_8) ((u4GroupCipher >> 16) & 0x000000FF), + (UINT_8) ((u4GroupCipher >> 24) & 0x000000FF)); + + DBGLOG(SEC, TRACE, "Selected AKM suite: %02x-%02x-%02x-%02x\n", + (UINT_8) (u4AkmSuite & 0x000000FF), + (UINT_8) ((u4AkmSuite >> 8) & 0x000000FF), + (UINT_8) ((u4AkmSuite >> 16) & 0x000000FF), (UINT_8) ((u4AkmSuite >> 24) & 0x000000FF)); + + return TRUE; +} /* wapiPerformPolicySelection */ + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is use for wapi mode, to update the current wpi tx idx ? 0 :1 . +* +* \param[in] prStaRec Pointer to the Sta record +* \param[out] ucWlanIdx The Rx status->wlanidx field +* +* \retval TRUE - Succeeded +* \retval FALSE - Failed +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wapiUpdateTxKeyIdx(IN P_STA_RECORD_T prStaRec, IN UINT_8 ucWlanIdx) +{ + UINT_8 ucKeyId; + + if ((ucWlanIdx & BITS(0, 3)) == CIPHER_SUITE_WPI) { + + ucKeyId = ((ucWlanIdx & BITS(4, 5)) >> 4); + + if (ucKeyId != g_prWifiVar->rAisSpecificBssInfo.ucWpiActivedPWKey) { + DBGLOG(RSN, STATE, + "Change wapi key index from %d->%d\n", + g_prWifiVar->rAisSpecificBssInfo.ucWpiActivedPWKey, ucKeyId); + g_prWifiVar->rAisSpecificBssInfo.ucWpiActivedPWKey = ucKeyId; + + prStaRec->ucWTEntry = + (ucKeyId == + WTBL_AIS_BSSID_WAPI_IDX_0) ? WTBL_AIS_BSSID_WAPI_IDX_0 : WTBL_AIS_BSSID_WAPI_IDX_1; + } + } +} +#endif +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/wmm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/wmm.c new file mode 100644 index 0000000000000..8330d1d552c93 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/wmm.c @@ -0,0 +1,1203 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E 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 +******************************************************************************** +*/ +UINT_8 const aucUp2ACIMap[8] = {ACI_BE, ACI_BK, ACI_BK, ACI_BE, ACI_VI, ACI_VI, ACI_VO, ACI_VO}; + +/******************************************************************************* +* 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 +wmmTxTspecFrame(P_ADAPTER_T prAdapter, UINT_8 ucTid, enum TSPEC_OP_CODE eOpCode, + P_PARAM_QOS_TSPEC prTsParam); +static VOID wmmSyncAcParamWithFw( + P_ADAPTER_T prAdapter, UINT_8 ucAc, UINT_16 u2MediumTime, UINT_32 u4PhyRate); + +static void wmmGetTsmRptTimeout(P_ADAPTER_T prAdapter, ULONG ulParam); +static VOID wmmQueryTsmResult(P_ADAPTER_T prAdapter, ULONG ulParam); +static VOID +wmmRemoveTSM(P_ADAPTER_T prAdapter, struct ACTIVE_RM_TSM_REQ *prActiveTsm, BOOLEAN fgNeedStop); +static struct ACTIVE_RM_TSM_REQ * + wmmGetActiveTsmReq(P_ADAPTER_T prAdapter, UINT_8 ucTid, + BOOLEAN fgTriggered, BOOLEAN fgAllocIfNotExist); +static WLAN_STATUS +wmmRunEventActionTxDone(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo, + ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +static VOID wmmMayDoTsReplacement(P_ADAPTER_T prAdapter, UINT_8 ucNewTid); +#if 0 +static void DumpData(PUINT8 prAddr, UINT8 uLen, char *tag); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +VOID wmmInit(IN P_ADAPTER_T prAdapter) +{ + struct WMM_INFO *prWmmInfo = &prAdapter->rWifiVar.rWmmInfo; + struct TSPEC_INFO *prTspecInfo = &prWmmInfo->arTsInfo[0]; + UINT_8 ucTid = 0; + + for (ucTid = 0; ucTid < WMM_TSPEC_ID_NUM; ucTid++, prTspecInfo++) + cnmTimerInitTimer(prAdapter, &prTspecInfo->rAddTsTimer, + (PFN_MGMT_TIMEOUT_FUNC)wmmSetupTspecTimeOut, (ULONG)ucTid); + + LINK_INITIALIZE(&prWmmInfo->rActiveTsmReq); + prWmmInfo->rTriggeredTsmRptTime = 0; + DBGLOG(WMM, TRACE, "wmm init done\n"); +} + +VOID wmmUnInit(IN P_ADAPTER_T prAdapter) +{ + struct WMM_INFO *prWmmInfo = &prAdapter->rWifiVar.rWmmInfo; + struct TSPEC_INFO *prTspecInfo = &prWmmInfo->arTsInfo[0]; + UINT_8 ucTid = 0; + + for (ucTid = 0; ucTid < WMM_TSPEC_ID_NUM; ucTid++, prTspecInfo++) + cnmTimerStopTimer(prAdapter, &prTspecInfo->rAddTsTimer); + wmmRemoveAllTsmMeasurement(prAdapter, FALSE); + DBGLOG(WMM, TRACE, "wmm uninit done\n"); +} + +VOID +wmmFillTsinfo(P_PARAM_QOS_TSINFO prTsInfo, PUINT_8 pucTsInfo) +{ + UINT_32 u4TsInfoValue = 0; + /* | 0 |1-4 | 5-6 | 7-8 | 9 | 10 | 11-13 | 14-23 | + * Traffic Type|TSID| Dir |Access Policy|Reserved | PSB| UP |reserved| + */ + + u4TsInfoValue = prTsInfo->ucTrafficType & 0x1; + u4TsInfoValue |= (prTsInfo->ucTid & 0xf) << 1; + u4TsInfoValue |= (prTsInfo->ucDirection & 0x3) << 5; + u4TsInfoValue |= (prTsInfo->ucAccessPolicy & 0x3) << 7; + u4TsInfoValue |= (prTsInfo->ucApsd & 0x1) << 10; + u4TsInfoValue |= (prTsInfo->ucuserPriority) << 11; + u4TsInfoValue |= BIT(7); /* Fixed bit in spec */ + + pucTsInfo[0] = u4TsInfoValue & 0xFF; + pucTsInfo[1] = (u4TsInfoValue >> 8) & 0xff; + pucTsInfo[2] = (u4TsInfoValue >> 16) & 0xff; +} + +VOID +wmmComposeTspecIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, + P_PARAM_QOS_TSPEC prParamQosTspec) +{ + P_IE_WMM_TSPEC_T prIeWmmTspec = NULL; + UINT_8 *pucTemp = NULL; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + + prIeWmmTspec = (P_IE_WMM_TSPEC_T)((PUINT8)prMsduInfo->prPacket + prMsduInfo->u2FrameLength); + pucTemp = prIeWmmTspec->aucTspecBodyPart; + + /*fill WMM head*/ + prIeWmmTspec->ucId = ELEM_ID_VENDOR; + prIeWmmTspec->ucLength = ELEM_MAX_LEN_WMM_TSPEC; + kalMemCopy(prIeWmmTspec->aucOui, aucWfaOui, sizeof(aucWfaOui)); + prIeWmmTspec->ucOuiType = VENDOR_OUI_TYPE_WMM; + prIeWmmTspec->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_TSPEC; + prIeWmmTspec->ucVersion = VERSION_WMM; + + /*fill tsinfo*/ + wmmFillTsinfo(&prParamQosTspec->rTsInfo, prIeWmmTspec->aucTsInfo); + /*1.2 BODY*/ + /*nominal size*/ + /*DumpData(prParamQosTspec, sizeof(struct _PARAM_QOS_TSPEC), "QosTspc");*/ + WLAN_SET_FIELD_16(pucTemp, prParamQosTspec->u2NominalMSDUSize); + pucTemp += 2; + WLAN_SET_FIELD_16(pucTemp, prParamQosTspec->u2MaxMSDUsize); + pucTemp += 2; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4MinSvcIntv); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4MaxSvcIntv); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4InactIntv); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4SpsIntv); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4SvcStartTime); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4MinDataRate); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4MeanDataRate); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4PeakDataRate); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4MaxBurstSize); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4DelayBound); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4MinPHYRate); + pucTemp += 4; + WLAN_SET_FIELD_16(pucTemp, prParamQosTspec->u2Sba); + pucTemp += 2; + WLAN_SET_FIELD_16(pucTemp, prParamQosTspec->u2MediumTime); + /*DumpData(prIeWmmTspec->aucTsInfo, 55, "tspec ie");*/ + + prMsduInfo->u2FrameLength += IE_SIZE(prIeWmmTspec); +} + +static UINT_8 wmmNewDlgToken(VOID) +{ + static UINT_8 sWmmDlgToken; + + return sWmmDlgToken++; +} + +/* follow WMM spec, send add/del tspec request frame */ +static VOID +wmmTxTspecFrame(P_ADAPTER_T prAdapter, UINT_8 ucTid, enum TSPEC_OP_CODE eOpCode, + P_PARAM_QOS_TSPEC prTsParam) +{ + P_BSS_INFO_T prBssInfo = NULL; + UINT_16 u2PayLoadLen = WLAN_MAC_HEADER_LEN + 4; /*exclude TSPEC IE*/ + P_STA_RECORD_T prStaRec = prAdapter->rWifiVar.rAisFsmInfo.prTargetStaRec; + P_MSDU_INFO_T prMsduInfo = NULL; + struct WMM_ACTION_TSPEC_FRAME *prActionFrame = NULL; + UINT_16 u2FrameCtrl = MAC_FRAME_ACTION; + + if (!prStaRec || !prTsParam) { + DBGLOG(WMM, ERROR, "prStaRec NULL %d, prTsParam NULL %d\n", !prStaRec, !prTsParam); + return; + } + + /*build ADDTS for TID*/ + /*1 compose Action frame Fix field*/ + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + DBGLOG(WMM, INFO, "Tspec Action to AP="MACSTR"\n", MAC2STR(prStaRec->aucMacAddr)); + + prMsduInfo = cnmMgtPktAlloc(prAdapter, ACTION_ADDTS_REQ_FRAME_LEN); + + if (prMsduInfo == NULL) { + DBGLOG(WMM, ERROR, "prMsduInfo is null!"); + return; + } + 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 = u2PayLoadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = wmmRunEventActionTxDone; + prMsduInfo->fgIsBasicRate = TRUE; + kalMemZero(prMsduInfo->prPacket, ACTION_ADDTS_REQ_FRAME_LEN); + + prActionFrame = (struct WMM_ACTION_TSPEC_FRAME *)prMsduInfo->prPacket; + + /*********frame header**********************/ + WLAN_SET_FIELD_16(&prActionFrame->u2FrameCtrl, u2FrameCtrl); + COPY_MAC_ADDR(prActionFrame->aucDestAddr, prStaRec->aucMacAddr); + COPY_MAC_ADDR(prActionFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prActionFrame->aucBSSID, prStaRec->aucMacAddr); + prActionFrame->u2SeqCtrl = 0; + + /********Frame body*************/ + prActionFrame->ucCategory = CATEGORY_WME_MGT_NOTIFICATION; /*CATEGORY_QOS_ACTION;*/ + if (eOpCode == TX_ADDTS_REQ) { + prActionFrame->ucAction = ACTION_ADDTS_REQ; + prActionFrame->ucDlgToken = + (prTsParam->ucDialogToken == 0) ? wmmNewDlgToken():prTsParam->ucDialogToken; + } else if (eOpCode == TX_DELTS_REQ) { + prActionFrame->ucAction = ACTION_DELTS; + prActionFrame->ucDlgToken = 0; /* dialog token should be always 0 in delts frame */ + } + + prActionFrame->ucStatusCode = 0; /* this field only meanful in ADD TS response, otherwise set to 0 */ + + /*DumpData((P_UINT_8)prMsduInfo->prPacket,u2PayLoadLen, "ADDTS-FF");*/ + + /********Information Element *************/ + wmmComposeTspecIE(prAdapter, prMsduInfo, prTsParam); + + /******** Insert into Msdu Queue *************/ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + /*DumpData(((PUINT8)prMsduInfo->prPacket) + u2PayLoadLen, + * prMsduInfo->u2FrameLength - u2PayLoadLen, "TSPEC-IE"); + */ +} + +VOID wmmSetupTspecTimeOut(P_ADAPTER_T prAdapter, ULONG ulParam) +{ + struct TSPEC_INFO *prTsInfo = NULL; + UINT_8 ucTimeoutTid = (UINT_8)ulParam; + + if (ulParam >= WMM_TSPEC_ID_NUM) { + DBGLOG(WMM, INFO, "Wrong TS ID %d\n", ucTimeoutTid); + return; + } + prTsInfo = &prAdapter->rWifiVar.rWmmInfo.arTsInfo[ucTimeoutTid]; + switch (prTsInfo->eState) { + case QOS_TS_ACTIVE: + DBGLOG(WMM, INFO, "Update TS TIMEOUT for TID %d\n", ucTimeoutTid); + break; + case QOS_TS_SETUPING: + DBGLOG(WMM, INFO, "ADD TS TIMEOUT for TID %d\n", ucTimeoutTid); + prTsInfo->eState = QOS_TS_INACTIVE; + break; + default: + DBGLOG(WMM, INFO, "Shouldn't start this timer when Ts %d in state %d\n", + ucTimeoutTid, prTsInfo->eState); + break; + } +} +#if 0 +VOID +wmmSyncTXPwrLimitWithFw( + IN P_ADAPTER_T prAdapter, + IN BOOLEAN enable, + IN INT_8 cMaxPwr + ) +{ + CMD_MAX_TXPWR_LIMIT_T rCmdMaxTxPwrLimit; + UINT_8 ucLevel = 100; /*default 100 percent */ + /* <5mw 5mw 10mw 20mw 30mw 40mw 50mw + * <7dbm 7dbm 10dbm 13dbm 15dbm 16dbm 17dbm + * 5% 10% 20% 40% 60% 80% 100% + */ + if (cMaxPwr <= 2) { + ucLevel = 0; + cMaxPwr = 2; /* FW can accept the lowest power value: 2dbm */ + } else if (cMaxPwr < 7) + ucLevel = 5; + else if (cMaxPwr < 10) + ucLevel = 10; + else if (cMaxPwr < 13) + ucLevel = 20; + else if (cMaxPwr < 15) + ucLevel = 40; + else if (cMaxPwr == 15) + ucLevel = 60; + else if (cMaxPwr == 16) + ucLevel = 80; + else if (cMaxPwr >= 17) { + cMaxPwr = 17; + ucLevel = 100; + } + /* base on test plan, only the tx power limit is less than the one user set, we need use tpc limit */ + if (prAdapter->rWifiVar.rCCXInfo.ucTxPwrLevel < ucLevel) + return; + kalIndicateCcxNotify(prAdapter, CCX_EVENT_TX_PWR, &ucLevel, 1); + prAdapter->rWifiVar.rCCXInfo.ucTxPwrLevel = ucLevel; + rCmdMaxTxPwrLimit.ucMaxTxPwrLimitEnable = enable; + rCmdMaxTxPwrLimit.ucMaxTxPwr = (UINT_8)cMaxPwr * 2; /* in fw, he will devide this value */ + /* CMD_ID_SET_MAX_TXPWR_LIMIT: if tx power of some modulation which from nvram + * is less than this limit, he will use the value from nvram. otherwise, he will use this limit value + */ + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_MAX_TXPWR_LIMIT, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_MAX_TXPWR_LIMIT_T), + (PUINT8)&rCmdMaxTxPwrLimit, + NULL, + 0); +} +#endif + +UINT_8 wmmCalculateUapsdSetting(P_ADAPTER_T prAdapter) +{ + P_PM_PROFILE_SETUP_INFO_T prPmProf = + &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].rPmProfSetupInfo; + struct TSPEC_INFO *prCurTs = &prAdapter->rWifiVar.rWmmInfo.arTsInfo[0]; + UINT_8 ucTid = 0; + UINT_8 ucFinalSetting = 0; + + ucFinalSetting = (prPmProf->ucBmpDeliveryAC << 4) | prPmProf->ucBmpTriggerAC; + for (ucTid = 0; ucTid < WMM_TSPEC_ID_NUM; ucTid++, prCurTs++) { + UINT_8 ucPsd = 0; + + if (prCurTs->eState != QOS_TS_ACTIVE) + continue; + switch (prCurTs->eDir) { + case UPLINK_TS: + ucPsd = BIT(prCurTs->eAC); + break; + case DOWNLINK_TS: + ucPsd = BIT(prCurTs->eAC + 4); + break; + case BI_DIR_TS: + ucPsd = BIT(prCurTs->eAC) | BIT(prCurTs->eAC + 4); + break; + } + if (prCurTs->fgUapsd) + ucFinalSetting |= ucPsd; + else + ucFinalSetting &= ~ucPsd; + } + return ucFinalSetting; +} + +VOID wmmSyncAcParamWithFw( + P_ADAPTER_T prAdapter, UINT_8 ucAc, UINT_16 u2MediumTime, UINT_32 u4PhyRate) +{ + CMD_UPDATE_AC_PARAMS_T rCmdUpdateAcParam; + CMD_SET_WMM_PS_TEST_STRUCT_T rSetWmmPsTestParam; + + kalMemZero(&rCmdUpdateAcParam, sizeof(rCmdUpdateAcParam)); + rCmdUpdateAcParam.ucAcIndex = ucAc; + rCmdUpdateAcParam.ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + rCmdUpdateAcParam.u2MediumTime = u2MediumTime; + rCmdUpdateAcParam.u4PhyRate = u4PhyRate; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_UPDATE_AC_PARMS, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_UPDATE_AC_PARAMS_T), + (PUINT_8)&rCmdUpdateAcParam, + NULL, + 0); + + kalMemZero(&rSetWmmPsTestParam, sizeof(rSetWmmPsTestParam)); + rSetWmmPsTestParam.ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + rSetWmmPsTestParam.bmfgApsdEnAc = wmmCalculateUapsdSetting(prAdapter); + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_WMM_PS_TEST_PARMS, + TRUE, FALSE, FALSE, NULL, + NULL, sizeof(CMD_SET_WMM_PS_TEST_STRUCT_T), + (PUINT_8)&rSetWmmPsTestParam, NULL, 0); + + DBGLOG(WMM, INFO, "Ac=%d, MediumTime=%d PhyRate=%u Uapsd 0x%02x\n", + ucAc, u2MediumTime, u4PhyRate, rSetWmmPsTestParam.bmfgApsdEnAc); +} + +/* Return: AC List in bit map if this ac has active tspec */ +UINT_8 wmmHasActiveTspec(struct WMM_INFO *prWmmInfo) +{ + UINT_8 ucTid = 0; + UINT_8 ucACList = 0; + + /* if any tspec is active, it means */ + for (; ucTid < WMM_TSPEC_ID_NUM; ucTid++) + if (prWmmInfo->arTsInfo[ucTid].eState == QOS_TS_ACTIVE) + ucACList |= 1<arTsInfo[ucTid].eAC; + return ucACList; +} + +VOID +wmmRunEventTSOperate( + IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr + ) +{ + struct MSG_TS_OPERATE *prMsgTsOperate = (struct MSG_TS_OPERATE *)prMsgHdr; + + if (prMsgTsOperate == NULL) { + DBGLOG(WMM, INFO, "prMsgTsOperate = NULL, do nothing.\n"); + return; + } + + wmmTspecSteps(prAdapter, prMsgTsOperate->ucTid, + prMsgTsOperate->eOpCode, (VOID *)&prMsgTsOperate->rTspecParam); + + cnmMemFree(prAdapter, prMsgHdr); +} + +VOID +wmmTspecSteps(P_ADAPTER_T prAdapter, UINT_8 ucTid, enum TSPEC_OP_CODE eOpCode, + VOID *prStepParams) +{ + P_AIS_FSM_INFO_T prAisFsmInfo = &prAdapter->rWifiVar.rAisFsmInfo; + struct WMM_INFO *prWmmInfo = &prAdapter->rWifiVar.rWmmInfo; + struct TSPEC_INFO *prCurTs = NULL; + + if (prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].eConnectionState != + PARAM_MEDIA_STATE_CONNECTED || + prAisFsmInfo->eCurrentState == AIS_STATE_DISCONNECTING) { + DBGLOG(WMM, INFO, "ignore OP code %d when medium disconnected\n", eOpCode); + return; + } + + if (ucTid >= WMM_TSPEC_ID_NUM) { + DBGLOG(WMM, INFO, "Invalid TID %d\n", ucTid); + return; + } + + prCurTs = &prWmmInfo->arTsInfo[ucTid]; + DBGLOG(WMM, TRACE, "TID %d, State %d, Oper %d\n", ucTid, prCurTs->eState, eOpCode); + + switch (prCurTs->eState) { + case QOS_TS_INACTIVE: + { + P_PARAM_QOS_TSPEC prQosTspec = (P_PARAM_QOS_TSPEC)prStepParams; + + if (eOpCode != TX_ADDTS_REQ) + break; + + if (!prQosTspec) { + DBGLOG(WMM, INFO, "Lack of Tspec Param\n"); + break; + } + /*Send ADDTS req Frame*/ + wmmTxTspecFrame(prAdapter, ucTid, TX_ADDTS_REQ, prQosTspec); + + /*start ADDTS timer*/ + cnmTimerStartTimer(prAdapter, &prCurTs->rAddTsTimer, 1000); + prCurTs->eState = QOS_TS_SETUPING; + prCurTs->eAC = aucUp2ACIMap[prQosTspec->rTsInfo.ucuserPriority]; + prCurTs->ucToken = prQosTspec->ucDialogToken; + break; + } + case QOS_TS_SETUPING: + { + struct WMM_ADDTS_RSP_STEP_PARAM *prParam = + (struct WMM_ADDTS_RSP_STEP_PARAM *)prStepParams; + if (eOpCode == TX_DELTS_REQ || eOpCode == RX_DELTS_REQ || eOpCode == DISC_DELTS_REQ) { + cnmTimerStopTimer(prAdapter, &prCurTs->rAddTsTimer); + prCurTs->eState = QOS_TS_INACTIVE; + DBGLOG(WMM, INFO, "Del Ts %d in setuping state\n", ucTid); + break; + } else if (eOpCode != RX_ADDTS_RSP || prParam->ucDlgToken != prWmmInfo->arTsInfo[ucTid].ucToken) + break; + + cnmTimerStopTimer(prAdapter, &prCurTs->rAddTsTimer); + if (prParam->ucStatusCode == WMM_TS_STATUS_ADMISSION_ACCEPTED) { + struct ACTIVE_RM_TSM_REQ *prActiveTsmReq = NULL; + + prCurTs->eState = QOS_TS_ACTIVE; + prCurTs->eDir = prParam->eDir; + prCurTs->fgUapsd = !!prParam->ucApsd; + prCurTs->u2MediumTime = prParam->u2MediumTime; + prCurTs->u4PhyRate = prParam->u4PhyRate; + wmmSyncAcParamWithFw(prAdapter, prCurTs->eAC, prParam->u2MediumTime, + prParam->u4PhyRate); + wmmMayDoTsReplacement(prAdapter, ucTid); + /* start pending TSM if it was requested before admitted */ + prActiveTsmReq = wmmGetActiveTsmReq(prAdapter, ucTid, TRUE, FALSE); + if (prActiveTsmReq) + wmmStartTsmMeasurement(prAdapter, (ULONG)prActiveTsmReq->prTsmReq); + prActiveTsmReq = wmmGetActiveTsmReq(prAdapter, ucTid, FALSE, FALSE); + if (prActiveTsmReq) + wmmStartTsmMeasurement(prAdapter, (ULONG)prActiveTsmReq->prTsmReq); + } else { + prCurTs->eState = QOS_TS_INACTIVE; + DBGLOG(WMM, ERROR, "ADD TS is rejected, status=%d\n", prParam->ucStatusCode); + } + break; + } + case QOS_TS_ACTIVE: + { + struct ACTIVE_RM_TSM_REQ *prActiveTsm = NULL; + + switch (eOpCode) { + case TX_DELTS_REQ: + case RX_DELTS_REQ: + case DISC_DELTS_REQ: + prActiveTsm = wmmGetActiveTsmReq(prAdapter, ucTid, TRUE, FALSE); + if (prActiveTsm) + wmmRemoveTSM(prAdapter, prActiveTsm, TRUE); + prActiveTsm = wmmGetActiveTsmReq(prAdapter, ucTid, FALSE, FALSE); + if (prActiveTsm) + wmmRemoveTSM(prAdapter, prActiveTsm, TRUE); + prCurTs->eState = QOS_TS_INACTIVE; +#if 0 /* No need to change station tx queue, because test plan requires stop this UP 1s after delts was transmitted */ + qmHandleDelTspec(prAdapter, NETWORK_TYPE_AIS_INDEX, prAisFsmInfo->prTargetStaRec, prCurTs->eAC); +#endif + wmmSyncAcParamWithFw(prAdapter, prCurTs->eAC, 0, 0); + wmmDumpActiveTspecs(prAdapter, NULL, 0); + if (eOpCode == TX_DELTS_REQ) + wmmTxTspecFrame(prAdapter, ucTid, TX_DELTS_REQ, (P_PARAM_QOS_TSPEC)prStepParams); + break; + case TX_ADDTS_REQ: + /*Send ADDTS req Frame*/ + wmmTxTspecFrame(prAdapter, ucTid, TX_ADDTS_REQ, (P_PARAM_QOS_TSPEC)prStepParams); + prCurTs->eAC = aucUp2ACIMap[((P_PARAM_QOS_TSPEC)prStepParams)->rTsInfo.ucuserPriority]; + prCurTs->ucToken = ((P_PARAM_QOS_TSPEC)prStepParams)->ucDialogToken; + /*start ADDTS timer*/ + cnmTimerStartTimer(prAdapter, &prCurTs->rAddTsTimer, 1000); + break; + /* for case: TS of tid N has existed, then setup TS with this tid again. */ + case RX_ADDTS_RSP: + { + struct WMM_ADDTS_RSP_STEP_PARAM *prParam = (struct WMM_ADDTS_RSP_STEP_PARAM *)prStepParams; + + if (prParam->ucStatusCode != WMM_TS_STATUS_ADMISSION_ACCEPTED) { + DBGLOG(WMM, INFO, "Update TS %d request was rejected by BSS\n", ucTid); + break; + } + prCurTs->eDir = prParam->eDir; + prCurTs->fgUapsd = !!prParam->ucApsd; + prCurTs->u2MediumTime = prParam->u2MediumTime; + prCurTs->u4PhyRate = prParam->u4PhyRate; + wmmSyncAcParamWithFw(prAdapter, prCurTs->eAC, prParam->u2MediumTime, prParam->u4PhyRate); + wmmMayDoTsReplacement(prAdapter, ucTid); + break; + } + default: + break; + } + break; + } + default: + break; + } +} + +static WLAN_STATUS +wmmRunEventActionTxDone(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo, + ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + DBGLOG(WMM, INFO, "Status %d\n", rTxDoneStatus); + return WLAN_STATUS_SUCCESS; +} + +static char const charmap[16] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; +void DumpData(PUINT8 prAddr, UINT8 uLen, char *tag) +{ + UINT16 k = 0; + char buf[16*3+1]; + UINT16 loop = 0; + PUINT8 p = prAddr; + + uLen = (uLen > 128) ? 128 : uLen; + loop = uLen / 16; + if (tag) + DBGLOG(WMM, INFO, "++++++++ dump data \"%s\" p=%p len=%d\n", tag, prAddr, uLen); + else + DBGLOG(WMM, INFO, "++++++ dump data p=%p, len=%d\n", prAddr, uLen); + + while (loop) { + for (k = 0; k < 16; k++) { + buf[k*3] = charmap[((*(p + k) & 0xF0) >> 4)]; + buf[k*3 + 1] = charmap[(*(p + k) & 0x0F)]; + buf[k*3 + 2] = ' '; + } + buf[16*3] = 0; + DBGLOG(WMM, INFO, "%s\n", buf); + loop--; + p += 16; + } + uLen = uLen%16; + k = 0; + while (uLen) { + buf[k*3] = charmap[((*(p + k) & 0xF0) >> 4)]; + buf[k*3 + 1] = charmap[(*(p + k) & 0x0F)]; + buf[k*3 + 2] = ' '; + k++; + uLen--; + } + buf[k*3] = 0; + DBGLOG(WMM, INFO, "%s\n", buf); + DBGLOG(WMM, INFO, "====== end dump data\n"); +} +/* TSM related */ + +static VOID wmmQueryTsmResult(P_ADAPTER_T prAdapter, ULONG ulParam) +{ + struct RM_TSM_REQ *prTsmReq = ((struct ACTIVE_RM_TSM_REQ *)ulParam)->prTsmReq; + struct WMM_INFO *prWmmInfo = &prAdapter->rWifiVar.rWmmInfo; + CMD_GET_TSM_STATISTICS_T rGetTsmStatistics; + + DBGLOG(WMM, INFO, "Query TSM statistics, tid = %d\n", prTsmReq->ucTID); + DBGLOG(WMM, INFO, "%p , aci %d, duration %d\n", prTsmReq, prTsmReq->ucACI, prTsmReq->u2Duration); + rGetTsmStatistics.ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + rGetTsmStatistics.ucAcIndex = prTsmReq->ucACI; + rGetTsmStatistics.ucTid = prTsmReq->ucTID; + COPY_MAC_ADDR(rGetTsmStatistics.aucPeerAddr, prTsmReq->aucPeerAddr); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_TSM_STATISTICS, + FALSE, + TRUE, + FALSE, + wmmComposeTsmRpt, + NULL, + sizeof(CMD_GET_TSM_STATISTICS_T), + (PUINT_8)&rGetTsmStatistics, + NULL, + 0); + cnmTimerInitTimer(prAdapter, &prWmmInfo->rTsmTimer, wmmGetTsmRptTimeout, ulParam); + cnmTimerStartTimer(prAdapter, &prWmmInfo->rTsmTimer, 2000); +} + +static struct ACTIVE_RM_TSM_REQ * + wmmGetActiveTsmReq(P_ADAPTER_T prAdapter, UINT_8 ucTid, + BOOLEAN fgTriggered, BOOLEAN fgAllocIfNotExist) +{ + struct WMM_INFO *prWMMInfo = &prAdapter->rWifiVar.rWmmInfo; + struct ACTIVE_RM_TSM_REQ *prActiveReq = NULL; + BOOLEAN fgFound = FALSE; + + LINK_FOR_EACH_ENTRY(prActiveReq, &prWMMInfo->rActiveTsmReq, rLinkEntry, struct ACTIVE_RM_TSM_REQ) { + if ((!!prActiveReq->prTsmReq->u2Duration) == fgTriggered && + ucTid == prActiveReq->prTsmReq->ucTID) { + fgFound = TRUE; + break; + } + } + if (!fgFound && fgAllocIfNotExist) { + fgFound = TRUE; + prActiveReq = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(struct ACTIVE_RM_TSM_REQ)); + LINK_INSERT_TAIL(&prWMMInfo->rActiveTsmReq, &prActiveReq->rLinkEntry); + } + return fgFound ? prActiveReq:NULL; +} + +static VOID +wmmRemoveTSM(P_ADAPTER_T prAdapter, struct ACTIVE_RM_TSM_REQ *prActiveTsm, BOOLEAN fgNeedStop) +{ + struct WMM_INFO *prWMMInfo = &prAdapter->rWifiVar.rWmmInfo; + P_LINK_T prActiveTsmLink = &prWMMInfo->rActiveTsmReq; + + LINK_REMOVE_KNOWN_ENTRY(prActiveTsmLink, prActiveTsm); + if (fgNeedStop) { + CMD_SET_TSM_STATISTICS_REQUEST_T rTsmStatistics; + + rTsmStatistics.ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + rTsmStatistics.ucEnabled = FALSE; + rTsmStatistics.ucAcIndex = prActiveTsm->prTsmReq->ucACI; + rTsmStatistics.ucTid = prActiveTsm->prTsmReq->ucTID; + COPY_MAC_ADDR(rTsmStatistics.aucPeerAddr, prActiveTsm->prTsmReq->aucPeerAddr); + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_TSM_STATISTICS_REQUEST, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_SET_TSM_STATISTICS_REQUEST_T), + (PUINT_8)&rTsmStatistics, + NULL, + 0); + } + cnmMemFree(prAdapter, prActiveTsm->prTsmReq); + cnmMemFree(prAdapter, prActiveTsm); +} + +void +wmmStartTsmMeasurement(P_ADAPTER_T prAdapter, ULONG ulParam) +{ + struct WMM_INFO *prWMMInfo = &prAdapter->rWifiVar.rWmmInfo; + CMD_SET_TSM_STATISTICS_REQUEST_T rTsmStatistics; + struct RM_TSM_REQ *prTsmReq = (struct RM_TSM_REQ *)ulParam; + UINT_8 ucTid = prTsmReq->ucTID; + struct ACTIVE_RM_TSM_REQ *prActiveTsmReq = NULL; + P_STA_RECORD_T prStaRec = prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].prStaRecOfAP; + struct TSPEC_INFO *prCurTs = NULL; + + if (!prTsmReq->u2Duration && !(prTsmReq->rTriggerCond.ucCondition & TSM_TRIGGER_CONDITION_ALL)) { + DBGLOG(WMM, WARN, "Duration is %d, Trigger Condition %d\n", + prTsmReq->u2Duration, prTsmReq->rTriggerCond.ucCondition); + cnmMemFree(prAdapter, prTsmReq); + rlmScheduleNextRm(prAdapter); + return; + } + /* if current TID is not admitted, don't start measurement, only save this requirement */ + if (!prStaRec) { + DBGLOG(WMM, INFO, "No station record found for %pM\n", prTsmReq->aucPeerAddr); + cnmMemFree(prAdapter, prTsmReq); + rlmScheduleNextRm(prAdapter); + return; + } + /* if there's a active tspec, then TID means TS ID */ + prCurTs = &prWMMInfo->arTsInfo[ucTid]; + if (prCurTs->eState == QOS_TS_ACTIVE) + prTsmReq->ucACI = prCurTs->eAC; + else { /* otherwise TID means TC ID */ + UINT_8 ucTsAcs = wmmHasActiveTspec(prWMMInfo); + + prTsmReq->ucACI = aucUp2ACIMap[ucTid]; + /* if current TID is not admitted, don't start measurement, only save this requirement */ + if (prStaRec->afgAcmRequired[prTsmReq->ucACI] && !(ucTsAcs & BIT(prTsmReq->ucACI))) { + DBGLOG(WMM, INFO, "ACM is set for UP %d, but No tspec is setup\n", ucTid); + rlmScheduleNextRm(prAdapter); + return; + } + } + + kalMemZero(&rTsmStatistics, sizeof(rTsmStatistics)); + if (prTsmReq->u2Duration) { + /* If a non-AP QoS STa receives a Transmit Stream/Category Measurement Request for a TC, or + ** TS that is already being measured using a triggered transmit stream/category measurement, + ** the triggered traffic stream measurement shall be suspended for the duration of the requested + ** traffic stream measurement. When triggered measurement resumes, the traffic stream metrics + ** shall be reset. See end part of 802.11k 11.10.8.8 + **/ + LINK_FOR_EACH_ENTRY(prActiveTsmReq, &prWMMInfo->rActiveTsmReq, rLinkEntry, struct ACTIVE_RM_TSM_REQ) { + if (prActiveTsmReq->prTsmReq->u2Duration || prActiveTsmReq->prTsmReq->ucACI != prTsmReq->ucACI) + continue; + rTsmStatistics.ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + rTsmStatistics.ucEnabled = FALSE; + rTsmStatistics.ucAcIndex = prTsmReq->ucACI; + rTsmStatistics.ucTid = prActiveTsmReq->prTsmReq->ucTID; + COPY_MAC_ADDR(rTsmStatistics.aucPeerAddr, prActiveTsmReq->prTsmReq->aucPeerAddr); + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_TSM_STATISTICS_REQUEST, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_SET_TSM_STATISTICS_REQUEST_T), + (PUINT_8)&rTsmStatistics, + NULL, + 0); + } + prActiveTsmReq = wmmGetActiveTsmReq(prAdapter, ucTid, !!prTsmReq->u2Duration, TRUE); + /* if exist normal tsm on the same ts, replace it */ + if (prActiveTsmReq->prTsmReq) + cnmMemFree(prAdapter, prActiveTsmReq->prTsmReq); + DBGLOG(WMM, INFO, "%p tid %d, aci %d, duration %d\n", + prTsmReq, prTsmReq->ucTID, prTsmReq->ucACI, prTsmReq->u2Duration); + cnmTimerInitTimer(prAdapter, &prWMMInfo->rTsmTimer, wmmQueryTsmResult, (ULONG)prActiveTsmReq); + cnmTimerStartTimer(prAdapter, &prWMMInfo->rTsmTimer, TU_TO_MSEC(prTsmReq->u2Duration)); + } else { + prActiveTsmReq = wmmGetActiveTsmReq(prAdapter, ucTid, !prTsmReq->u2Duration, TRUE); + /* if exist triggered tsm on the same ts, replace it */ + if (prActiveTsmReq->prTsmReq) { + cnmTimerStopTimer(prAdapter, &prActiveTsmReq->rTsmTimer); + cnmMemFree(prAdapter, prActiveTsmReq->prTsmReq); + } + rTsmStatistics.ucTriggerCondition = prTsmReq->rTriggerCond.ucCondition; + rTsmStatistics.ucMeasureCount = prTsmReq->rTriggerCond.ucMeasureCount; + rTsmStatistics.ucTriggerTimeout = prTsmReq->rTriggerCond.ucTriggerTimeout; + rTsmStatistics.ucAvgErrThreshold = prTsmReq->rTriggerCond.ucAvgErrThreshold; + rTsmStatistics.ucConsecutiveErrThreshold = prTsmReq->rTriggerCond.ucConsecutiveErr; + rTsmStatistics.ucDelayThreshold = prTsmReq->rTriggerCond.ucDelayThreshold; + rTsmStatistics.ucBin0Range = prTsmReq->ucB0Range; + } + prActiveTsmReq->prTsmReq = prTsmReq; + rTsmStatistics.ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + rTsmStatistics.ucAcIndex = prTsmReq->ucACI; + rTsmStatistics.ucTid = prTsmReq->ucTID; + rTsmStatistics.ucEnabled = TRUE; + COPY_MAC_ADDR(rTsmStatistics.aucPeerAddr, prTsmReq->aucPeerAddr); + DBGLOG(WMM, INFO, "enabled=%d, tid=%d\n", rTsmStatistics.ucEnabled, ucTid); + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_TSM_STATISTICS_REQUEST, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_SET_TSM_STATISTICS_REQUEST_T), + (PUINT_8)&rTsmStatistics, + NULL, + 0); +} + +VOID wmmRemoveAllTsmMeasurement(P_ADAPTER_T prAdapter, BOOLEAN fgOnlyTriggered) +{ + P_LINK_T prActiveTsmLink = &prAdapter->rWifiVar.rWmmInfo.rActiveTsmReq; + struct ACTIVE_RM_TSM_REQ *prActiveTsm = NULL; + struct ACTIVE_RM_TSM_REQ *prHead = + LINK_PEEK_HEAD(prActiveTsmLink, struct ACTIVE_RM_TSM_REQ, rLinkEntry); + BOOLEAN fgFinished = FALSE; + + if (!fgOnlyTriggered) + cnmTimerStopTimer(prAdapter, &prAdapter->rWifiVar.rWmmInfo.rTsmTimer); + do { + prActiveTsm = LINK_PEEK_TAIL(prActiveTsmLink, struct ACTIVE_RM_TSM_REQ, rLinkEntry); + if (!prActiveTsm) + break; + if (prActiveTsm == prHead) + fgFinished = TRUE; + if (fgOnlyTriggered && prActiveTsm->prTsmReq->u2Duration) + continue; + wmmRemoveTSM(prAdapter, prActiveTsm, TRUE); + } while (!fgFinished); + prAdapter->rWifiVar.rWmmInfo.rTriggeredTsmRptTime = 0; +} + +BOOLEAN +wmmParseQosAction( + IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb + ) +{ + P_WLAN_ACTION_FRAME prWlanActionFrame = NULL; + P_UINT_8 pucIE = NULL; + PARAM_QOS_TSPEC rTspec; + UINT_16 u2Offset = 0; + UINT_16 u2IEsBufLen = 0; + UINT_8 ucTid = WMM_TSPEC_ID_NUM; + struct WMM_ADDTS_RSP_STEP_PARAM rStepParam; + BOOLEAN ret = FALSE; + + prWlanActionFrame = (P_WLAN_ACTION_FRAME)prSwRfb->pvHeader; + DBGLOG(WMM, INFO, "Action=%d\n", prWlanActionFrame->ucAction); + switch (prWlanActionFrame->ucAction) { + case ACTION_ADDTS_RSP: + { + kalMemZero(&rStepParam, sizeof(rStepParam)); + if (prWlanActionFrame->ucCategory == CATEGORY_WME_MGT_NOTIFICATION) { + struct WMM_ACTION_TSPEC_FRAME *prAddTsRsp = (struct WMM_ACTION_TSPEC_FRAME *)prWlanActionFrame; + + rStepParam.ucDlgToken = prAddTsRsp->ucDlgToken; + rStepParam.ucStatusCode = prAddTsRsp->ucStatusCode; + pucIE = (PUINT8)prAddTsRsp->aucInfoElem; + } else if (prWlanActionFrame->ucCategory == CATEGORY_QOS_ACTION) { + P_ACTION_ADDTS_RSP_FRAME prAddTsRsp = (P_ACTION_ADDTS_RSP_FRAME)prWlanActionFrame; + + rStepParam.ucDlgToken = prAddTsRsp->ucDialogToken; + rStepParam.ucStatusCode = prAddTsRsp->ucStatusCode; + pucIE = (PUINT8)prAddTsRsp->aucInfoElem; + } + /*for each IE*/ + u2IEsBufLen = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen - + (UINT_16)(OFFSET_OF(ACTION_ADDTS_RSP_FRAME, aucInfoElem) - WLAN_MAC_HEADER_LEN); + + if (pucIE == NULL) { + DBGLOG(WMM, INFO, "pueIE = NULL when Category=%d\n", prWlanActionFrame->ucCategory); + break; + } + + IE_FOR_EACH(pucIE, u2IEsBufLen, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_TSPEC: + case ELEM_ID_VENDOR: + if (wmmParseTspecIE(prAdapter, pucIE, &rTspec)) { + rStepParam.u2MediumTime = rTspec.u2MediumTime; + ucTid = rTspec.rTsInfo.ucTid; + rStepParam.eDir = rTspec.rTsInfo.ucDirection; + rStepParam.u4PhyRate = rTspec.u4MinPHYRate; + rStepParam.ucApsd = rTspec.rTsInfo.ucApsd; + } else { + DBGLOG(WMM, INFO, "can't parse Tspec IE?!\n"); + ASSERT(FALSE); + } + break; + default: + break; + } + } + wmmTspecSteps(prAdapter, ucTid, RX_ADDTS_RSP, &rStepParam); + ret = TRUE; + break; + } + case ACTION_DELTS: + { + if (prWlanActionFrame->ucCategory == CATEGORY_WME_MGT_NOTIFICATION) { + /* wmm Tspec */ + struct WMM_ACTION_TSPEC_FRAME *prDelTs = (struct WMM_ACTION_TSPEC_FRAME *)prWlanActionFrame; + + u2IEsBufLen = prSwRfb->u2PacketLen - + (UINT_16)OFFSET_OF(struct WMM_ACTION_TSPEC_FRAME, aucInfoElem); + u2Offset = 0; + pucIE = prDelTs->aucInfoElem; + IE_FOR_EACH(pucIE, u2IEsBufLen, u2Offset) { + if (!wmmParseTspecIE(prAdapter, pucIE, &rTspec)) + continue; + ucTid = rTspec.rTsInfo.ucTid; + break; + } + } else if (prWlanActionFrame->ucCategory == CATEGORY_QOS_ACTION) { + /* IEEE 802.11 Tspec */ + P_ACTION_DELTS_FRAME prDelTs = (P_ACTION_DELTS_FRAME)prWlanActionFrame; + + ucTid = WMM_TSINFO_TSID(prDelTs->aucTsInfo[0]); + } + + wmmTspecSteps(prAdapter, ucTid, RX_DELTS_REQ, NULL); + ret = TRUE; + break; + } + default: + break; + } + return ret; +} + +BOOLEAN +wmmParseTspecIE(P_ADAPTER_T prAdapter, PUINT_8 pucIE, P_PARAM_QOS_TSPEC prTspec) +{ + UINT_32 u4TsInfoValue = 0; + UINT_8 *pucTemp = NULL; + + if (IE_ID(pucIE) == ELEM_ID_TSPEC) { + DBGLOG(WMM, INFO, "found 802.11 Tspec Information Element\n"); + /* todo: implement 802.11 Tspec here, assign value to u4TsInfoValue and pucTemp */ + u4TsInfoValue = 0; + pucTemp = NULL; + return FALSE; /* we didn't support IEEE 802.11 Tspec now */ + } + { + P_IE_WMM_TSPEC_T prIeWmmTspec = (P_IE_WMM_TSPEC_T)pucIE; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + + if (prIeWmmTspec->ucId != ELEM_ID_VENDOR || + kalMemCmp(prIeWmmTspec->aucOui, aucWfaOui, sizeof(aucWfaOui)) || + prIeWmmTspec->ucOuiType != VENDOR_OUI_TYPE_WMM || + prIeWmmTspec->ucOuiSubtype != VENDOR_OUI_SUBTYPE_WMM_TSPEC) { + return FALSE; + } + u4TsInfoValue |= prIeWmmTspec->aucTsInfo[0]; + u4TsInfoValue |= (prIeWmmTspec->aucTsInfo[1] << 8); + u4TsInfoValue |= (prIeWmmTspec->aucTsInfo[2] << 16); + pucTemp = prIeWmmTspec->aucTspecBodyPart; + } + + prTspec->rTsInfo.ucTrafficType = WMM_TSINFO_TRAFFIC_TYPE(u4TsInfoValue); + prTspec->rTsInfo.ucTid = WMM_TSINFO_TSID(u4TsInfoValue); + prTspec->rTsInfo.ucDirection = WMM_TSINFO_DIR(u4TsInfoValue); + prTspec->rTsInfo.ucAccessPolicy = WMM_TSINFO_AC(u4TsInfoValue); + prTspec->rTsInfo.ucApsd = WMM_TSINFO_PSB(u4TsInfoValue); + prTspec->rTsInfo.ucuserPriority = WMM_TSINFO_UP(u4TsInfoValue); + + /* nominal size*/ + WLAN_GET_FIELD_16(pucTemp, &prTspec->u2NominalMSDUSize); + pucTemp += 2; + WLAN_GET_FIELD_16(pucTemp, &prTspec->u2MaxMSDUsize); + pucTemp += 2; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4MinSvcIntv); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4MaxSvcIntv); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4InactIntv); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4SpsIntv); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4SvcStartTime); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4MinDataRate); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4MeanDataRate); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4PeakDataRate); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4MaxBurstSize); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4DelayBound); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4MinPHYRate); + pucTemp += 4; + WLAN_GET_FIELD_16(pucTemp, &prTspec->u2Sba); + pucTemp += 2; + WLAN_GET_FIELD_16(pucTemp, &prTspec->u2MediumTime); + pucTemp += 2; + ASSERT((pucTemp == (IE_SIZE(pucIE) + pucIE))); + DBGLOG(WMM, INFO, "TsId=%d, TrafficType=%d, PSB=%d, MediumTime=%d\n", + prTspec->rTsInfo.ucTid, prTspec->rTsInfo.ucTrafficType, + prTspec->rTsInfo.ucApsd, prTspec->u2MediumTime); + return TRUE; +} + +static void wmmGetTsmRptTimeout(P_ADAPTER_T prAdapter, ULONG ulParam) +{ + DBGLOG(WMM, ERROR, "timeout to get Tsm Rpt from firmware\n"); + wlanReleasePendingCmdById(prAdapter, CMD_ID_GET_TSM_STATISTICS); + wmmRemoveTSM(prAdapter, (struct ACTIVE_RM_TSM_REQ *)ulParam, TRUE); + /* schedule next measurement after a duration based TSM done */ + rlmStartNextMeasurement(prAdapter, FALSE); +} + +void wmmComposeTsmRpt(P_ADAPTER_T prAdapter, P_CMD_INFO_T prCmdInfo, PUINT_8 pucEventBuf) +{ + struct RADIO_MEASUREMENT_REPORT_PARAMS *prRmRep = &prAdapter->rWifiVar.rRmRepParams; + P_IE_MEASUREMENT_REPORT_T prTsmRpt = NULL; + struct RM_TSM_REPORT *prTsmRptField = NULL; + P_CMD_GET_TSM_STATISTICS_T prTsmStatistic = (P_CMD_GET_TSM_STATISTICS_T)pucEventBuf; + UINT_16 u2IeSize = OFFSET_OF(IE_MEASUREMENT_REPORT_T, aucReportFields) + sizeof(*prTsmRptField); + struct ACTIVE_RM_TSM_REQ *prCurrentTsmReq = NULL; + struct WMM_INFO *prWMMInfo = &prAdapter->rWifiVar.rWmmInfo; + + prCurrentTsmReq = + wmmGetActiveTsmReq(prAdapter, prTsmStatistic->ucTid, !prTsmStatistic->ucReportReason, FALSE); + /* prCmdInfo is not NULL or report reason is 0 means it is a command reply, so we need to stop the timer */ + if (prCmdInfo || !prTsmStatistic->ucReportReason) + cnmTimerStopTimer(prAdapter, &prWMMInfo->rTsmTimer); + if (!prCurrentTsmReq) { + DBGLOG(WMM, ERROR, "unexpected Tsm statistic event, tid %d\n", prTsmStatistic->ucTid); + /* schedule next measurement after a duration based TSM done */ + rlmScheduleNextRm(prAdapter); + return; + } + + /* Put the report IE into report frame */ + if (u2IeSize + prRmRep->u2ReportFrameLen > RM_REPORT_FRAME_MAX_LENGTH) + rlmTxRadioMeasurementReport(prAdapter); + + DBGLOG(WMM, INFO, "tid %d, aci %d\n", prCurrentTsmReq->prTsmReq->ucTID, prCurrentTsmReq->prTsmReq->ucACI); + prTsmRpt = (P_IE_MEASUREMENT_REPORT_T)(prRmRep->pucReportFrameBuff + prRmRep->u2ReportFrameLen); + prTsmRpt->ucId = ELEM_ID_MEASUREMENT_REPORT; + prTsmRpt->ucToken = prCurrentTsmReq->prTsmReq->ucToken; + prTsmRpt->ucMeasurementType = ELEM_RM_TYPE_TSM_REPORT; + prTsmRpt->ucReportMode = 0; + prTsmRpt->ucLength = u2IeSize - 2; + prTsmRptField = (struct RM_TSM_REPORT *)&prTsmRpt->aucReportFields[0]; + prTsmRptField->u8ActualStartTime = prTsmStatistic->u8StartTime; + prTsmRptField->u2Duration = prCurrentTsmReq->prTsmReq->u2Duration; + COPY_MAC_ADDR(prTsmRptField->aucPeerAddress, prTsmStatistic->aucPeerAddr); + /* TID filed: bit0~bit3 reserved, bit4~bit7: real tid */ + prTsmRptField->ucTID = (prCurrentTsmReq->prTsmReq->ucTID & 0xf) << 4; + prTsmRptField->ucReason = prTsmStatistic->ucReportReason; + prTsmRptField->u4TransmittedMsduCnt = prTsmStatistic->u4PktTxDoneOK; + prTsmRptField->u4DiscardedMsduCnt = prTsmStatistic->u4PktDiscard; + prTsmRptField->u4FailedMsduCnt = prTsmStatistic->u4PktFail; + prTsmRptField->u4MultiRetryCnt = prTsmStatistic->u4PktRetryTxDoneOK; + prTsmRptField->u4CfPollLostCnt = prTsmStatistic->u4PktQosCfPollLost; + prTsmRptField->u4AvgQueDelay = prTsmStatistic->u4AvgPktQueueDelay; + prTsmRptField->u4AvgDelay = prTsmStatistic->u4AvgPktTxDelay; + prTsmRptField->ucBin0Range = prCurrentTsmReq->prTsmReq->ucB0Range; + kalMemCopy(&prTsmRptField->u4Bin[0], &prTsmStatistic->au4PktCntBin[0], sizeof(prTsmStatistic->au4PktCntBin)); + prRmRep->u2ReportFrameLen += u2IeSize; + /* For normal TSM, only once measurement */ + if (prCurrentTsmReq->prTsmReq->u2Duration) { + struct RM_TSM_REQ *prTsmReq = NULL; + CMD_SET_TSM_STATISTICS_REQUEST_T rTsmStatistics; + + wmmRemoveTSM(prAdapter, prCurrentTsmReq, FALSE); + /* Resume all triggered tsm whose TC is same with this normal tsm */ + LINK_FOR_EACH_ENTRY(prCurrentTsmReq, &prWMMInfo->rActiveTsmReq, rLinkEntry, struct ACTIVE_RM_TSM_REQ) { + prTsmReq = prCurrentTsmReq->prTsmReq; + if (prTsmReq->u2Duration || prTsmReq->ucACI != prTsmStatistic->ucAcIndex) + continue; + kalMemZero(&rTsmStatistics, sizeof(rTsmStatistics)); + rTsmStatistics.ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + rTsmStatistics.ucEnabled = TRUE; + rTsmStatistics.ucAcIndex = prTsmReq->ucACI; + rTsmStatistics.ucTid = prTsmReq->ucTID; + COPY_MAC_ADDR(rTsmStatistics.aucPeerAddr, prTsmReq->aucPeerAddr); + rTsmStatistics.ucTriggerCondition = prTsmReq->rTriggerCond.ucCondition; + rTsmStatistics.ucMeasureCount = prTsmReq->rTriggerCond.ucMeasureCount; + rTsmStatistics.ucTriggerTimeout = prTsmReq->rTriggerCond.ucTriggerTimeout; + rTsmStatistics.ucAvgErrThreshold = prTsmReq->rTriggerCond.ucAvgErrThreshold; + rTsmStatistics.ucConsecutiveErrThreshold = prTsmReq->rTriggerCond.ucConsecutiveErr; + rTsmStatistics.ucDelayThreshold = prTsmReq->rTriggerCond.ucDelayThreshold; + rTsmStatistics.ucBin0Range = prTsmReq->ucB0Range; + wlanSendSetQueryCmd(prAdapter, CMD_ID_SET_TSM_STATISTICS_REQUEST, TRUE, FALSE, FALSE, NULL, + NULL, sizeof(rTsmStatistics), + (PUINT_8)&rTsmStatistics, NULL, 0); + } + /* schedule next measurement after a duration based TSM done */ + rlmScheduleNextRm(prAdapter); + } else { + /* Triggered TSM, we should send TSM report to peer if the first report time to now more than 10 second */ + OS_SYSTIME rCurrent = kalGetTimeTick(); + + if (prWMMInfo->rTriggeredTsmRptTime == 0) + prWMMInfo->rTriggeredTsmRptTime = rCurrent; + else if (CHECK_FOR_TIMEOUT(rCurrent, prWMMInfo->rTriggeredTsmRptTime, 10000)) { + rlmTxRadioMeasurementReport(prAdapter); + prWMMInfo->rTriggeredTsmRptTime = 0; + } + } +} + +VOID wmmNotifyDisconnected(P_ADAPTER_T prAdapter) +{ + UINT_8 ucTid = 0; + + for (; ucTid < WMM_TSPEC_ID_NUM; ucTid++) + wmmTspecSteps(prAdapter, ucTid, DISC_DELTS_REQ, NULL); + wmmRemoveAllTsmMeasurement(prAdapter, FALSE); +} + +BOOLEAN wmmTsmIsOngoing(P_ADAPTER_T prAdapter) +{ + return !LINK_IS_EMPTY(&prAdapter->rWifiVar.rWmmInfo.rActiveTsmReq); +} + +/* This function implements TS replacement rule +** Replace case base on same AC: +** 1. old: Uni-dir; New: Bi-dir or same dir with old +** 2. old: Bi-dir; New: Bi-dir or Uni-dir +** 3. old: two diff Uni-dir; New: Bi-dir +** for detail, see WMM spec V1.2.0, section 3.5 +*/ +static VOID wmmMayDoTsReplacement(P_ADAPTER_T prAdapter, UINT_8 ucNewTid) +{ + struct TSPEC_INFO *prTspec = &prAdapter->rWifiVar.rWmmInfo.arTsInfo[0]; + UINT_8 ucTid = 0; + + for (; ucTid < WMM_TSPEC_ID_NUM; ucTid++) { + if (ucTid == ucNewTid) + continue; + if (prTspec[ucTid].eState != QOS_TS_ACTIVE || + prTspec[ucTid].eAC != prTspec[ucNewTid].eAC) + continue; + if (prTspec[ucNewTid].eDir != prTspec[ucTid].eDir && + prTspec[ucNewTid].eDir < BI_DIR_TS && + prTspec[ucTid].eDir < BI_DIR_TS) + continue; + prTspec[ucTid].eAC = ACI_NUM; + prTspec[ucTid].eState = QOS_TS_INACTIVE; + } + wmmDumpActiveTspecs(prAdapter, NULL, 0); +} + +UINT_32 wmmDumpActiveTspecs(P_ADAPTER_T prAdapter, PUINT_8 pucBuffer, UINT_16 u2BufferLen) +{ + UINT_8 ucTid = 0; + INT_32 i4BytesWritten = 0; + + struct TSPEC_INFO *prTspec = &prAdapter->rWifiVar.rWmmInfo.arTsInfo[0]; + + for (; ucTid < WMM_TSPEC_ID_NUM; ucTid++, prTspec++) { + if (prTspec->eState != QOS_TS_ACTIVE) + continue; + if (u2BufferLen > 0 && pucBuffer) { + i4BytesWritten += kalSnprintf(pucBuffer+i4BytesWritten, u2BufferLen, + "Tid %d, AC %d, Dir %d, Uapsd %d, MediumTime %d, PhyRate %u\n", + ucTid, prTspec->eAC, prTspec->eDir, prTspec->fgUapsd, + prTspec->u2MediumTime, prTspec->u4PhyRate); + if (i4BytesWritten <= 0) + break; + u2BufferLen -= (UINT_16)i4BytesWritten; + } else + DBGLOG(WMM, INFO, "Tid %d, AC %d, Dir %d, Uapsd %d, MediumTime %d, PhyRate %u\n", + ucTid, prTspec->eAC, prTspec->eDir, prTspec->fgUapsd, + prTspec->u2MediumTime, prTspec->u4PhyRate); + } + return (UINT_32)i4BytesWritten; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/wnm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/wnm.c new file mode 100644 index 0000000000000..e29b69c46634b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/mgmt/wnm.c @@ -0,0 +1,554 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E 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 || CFG_SUPPORT_PPR2) + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT +static UINT_8 ucTimingMeasToken; +#endif +static UINT_8 ucBtmMgtToken = 1; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to process the 802.11v wnm category action frame. +* +* +* \note +* Called by: Handle Rx mgmt request +*/ +/*----------------------------------------------------------------------------*/ +VOID wnmWNMAction(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_WLAN_ACTION_FRAME prRxFrame; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxFrame = (P_WLAN_ACTION_FRAME) prSwRfb->pvHeader; + + DBGLOG(WNM, TRACE, "WNM action frame: %d from %pM\n", prRxFrame->ucAction, prRxFrame->aucSrcAddr); + + switch (prRxFrame->ucAction) { +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT + case ACTION_WNM_TIMING_MEASUREMENT_REQUEST: + wnmTimingMeasRequest(prAdapter, prSwRfb); + return; +#endif +#if CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT + case ACTION_WNM_BSS_TRANSITION_MANAGEMENT_REQ: + wnmRecvBTMRequest(prAdapter, prSwRfb); + return; +#endif + case ACTION_WNM_NOTIFICATION_REQUEST: + default: + DBGLOG(INIT, INFO, "WNM action frame: %d, try to send to supplicant\n", prRxFrame->ucAction); + if (HIF_RX_HDR_GET_NETWORK_IDX(prSwRfb->prHifRxHdr) == NETWORK_TYPE_AIS_INDEX) + aisFuncValidateRxActionFrame(prAdapter, prSwRfb); + break; + } +} + +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to report timing measurement data. +* +*/ +/*----------------------------------------------------------------------------*/ +VOID wnmReportTimingMeas(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIndex, IN UINT_32 u4ToD, IN UINT_32 u4ToA) +{ + P_STA_RECORD_T prStaRec; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIndex); + + if ((!prStaRec) || (!prStaRec->fgIsInUse)) + return; + + DBGLOG(WNM, TRACE, "wnmReportTimingMeas: u4ToD %x u4ToA %x", u4ToD, u4ToA); + + if (!prStaRec->rWNMTimingMsmt.ucTrigger) + return; + + prStaRec->rWNMTimingMsmt.u4ToD = MICRO_TO_10NANO(u4ToD); + prStaRec->rWNMTimingMsmt.u4ToA = MICRO_TO_10NANO(u4ToA); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle TxDone(TimingMeasurement) Event. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prMsduInfo Pointer to the MSDU_INFO_T. +* @param[in] rTxDoneStatus Return TX status of the Timing Measurement frame. +* +* @retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wnmRunEventTimgingMeasTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + DBGLOG(WNM, LOUD, "EVENT-TX DONE: Current Time = %u\n", kalGetTimeTick()); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if ((!prStaRec) || (!prStaRec->fgIsInUse)) + return WLAN_STATUS_SUCCESS; /* For the case of replying ERROR STATUS CODE */ + + DBGLOG(WNM, TRACE, "wnmRunEventTimgingMeasTxDone: ucDialog %d ucFollowUp %d u4ToD %x u4ToA %x", + prStaRec->rWNMTimingMsmt.ucDialogToken, + prStaRec->rWNMTimingMsmt.ucFollowUpDialogToken, + prStaRec->rWNMTimingMsmt.u4ToD, prStaRec->rWNMTimingMsmt.u4ToA); + + prStaRec->rWNMTimingMsmt.ucFollowUpDialogToken = prStaRec->rWNMTimingMsmt.ucDialogToken; + prStaRec->rWNMTimingMsmt.ucDialogToken = ++ucTimingMeasToken; + + wnmComposeTimingMeasFrame(prAdapter, prStaRec, NULL); + + return WLAN_STATUS_SUCCESS; + +} /* end of wnmRunEventTimgingMeasTxDone() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the Timing Measurement frame. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +wnmComposeTimingMeasFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + P_MSDU_INFO_T prMsduInfo; + P_BSS_INFO_T prBssInfo; + P_ACTION_UNPROTECTED_WNM_TIMING_MEAS_FRAME prTxFrame; + UINT_16 u2PayloadLen; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; + ASSERT(prBssInfo); + + prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + prTxFrame = (P_ACTION_UNPROTECTED_WNM_TIMING_MEAS_FRAME) + ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + + COPY_MAC_ADDR(prTxFrame->aucDestAddr, prStaRec->aucMacAddr); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); + + prTxFrame->ucCategory = CATEGORY_UNPROTECTED_WNM_ACTION; + prTxFrame->ucAction = ACTION_UNPROTECTED_WNM_TIMING_MEASUREMENT; + + /* 3 Compose the frame body's frame. */ + prTxFrame->ucDialogToken = prStaRec->rWNMTimingMsmt.ucDialogToken; + prTxFrame->ucFollowUpDialogToken = prStaRec->rWNMTimingMsmt.ucFollowUpDialogToken; + prTxFrame->u4ToD = prStaRec->rWNMTimingMsmt.u4ToD; + prTxFrame->u4ToA = prStaRec->rWNMTimingMsmt.u4ToA; + prTxFrame->ucMaxToDErr = WNM_MAX_TOD_ERROR; + prTxFrame->ucMaxToAErr = WNM_MAX_TOA_ERROR; + + u2PayloadLen = 2 + ACTION_UNPROTECTED_WNM_TIMING_MEAS_LEN; + + /* 4 Update information of MSDU_INFO_T */ + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; /* Management frame */ + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; + prMsduInfo->fgIsBasicRate = FALSE; + + DBGLOG(WNM, TRACE, "wnmComposeTimingMeasFrame: ucDialogToken %d ucFollowUpDialogToken %d u4ToD %x u4ToA %x\n", + prTxFrame->ucDialogToken, prTxFrame->ucFollowUpDialogToken, + prTxFrame->u4ToD, prTxFrame->u4ToA); + + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return; + +} /* end of wnmComposeTimingMeasFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to process the 802.11v timing measurement request. +* +* +* \note +* Handle Rx mgmt request +*/ +/*----------------------------------------------------------------------------*/ +VOID wnmTimingMeasRequest(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_ACTION_WNM_TIMING_MEAS_REQ_FRAME prRxFrame = NULL; + P_STA_RECORD_T prStaRec; + + prRxFrame = (P_ACTION_WNM_TIMING_MEAS_REQ_FRAME) prSwRfb->pvHeader; + if (!prRxFrame) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if ((!prStaRec) || (!prStaRec->fgIsInUse)) + return; + + DBGLOG(WNM, TRACE, "IEEE 802.11: Received Timing Measuremen Request from %pM\n" + prStaRec->aucMacAdd); + + /* reset timing msmt */ + prStaRec->rWNMTimingMsmt.fgInitiator = TRUE; + prStaRec->rWNMTimingMsmt.ucTrigger = prRxFrame->ucTrigger; + if (!prRxFrame->ucTrigger) + return; + + prStaRec->rWNMTimingMsmt.ucDialogToken = ++ucTimingMeasToken; + prStaRec->rWNMTimingMsmt.ucFollowUpDialogToken = 0; + + wnmComposeTimingMeasFrame(prAdapter, prStaRec, wnmRunEventTimgingMeasTxDone); +} + +#if WNM_UNIT_TEST +VOID wnmTimingMeasUnitTest1(P_ADAPTER_T prAdapter, UINT_8 ucStaRecIndex) +{ + P_STA_RECORD_T prStaRec; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIndex); + if ((!prStaRec) || (!prStaRec->fgIsInUse)) + return; + + DBGLOG(WNM, INFO, "IEEE 802.11v: Test Timing Measuremen Request from %pM\n", + prStaRec->aucMacAddr); + + prStaRec->rWNMTimingMsmt.fgInitiator = TRUE; + prStaRec->rWNMTimingMsmt.ucTrigger = 1; + + prStaRec->rWNMTimingMsmt.ucDialogToken = ++ucTimingMeasToken; + prStaRec->rWNMTimingMsmt.ucFollowUpDialogToken = 0; + + wnmComposeTimingMeasFrame(prAdapter, prStaRec, wnmRunEventTimgingMeasTxDone); +} +#endif + +#endif /* CFG_SUPPORT_802_11V_TIMING_MEASUREMENT */ + +UINT_8 wnmGetBtmToken(VOID) +{ + return ucBtmMgtToken++; +} + +static WLAN_STATUS +wnmBTMQueryTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + DBGLOG(WNM, INFO, "Bss Transition Management Query Frame Tx Done\n"); + return WLAN_STATUS_SUCCESS; +} + +static WLAN_STATUS +wnmBTMResponseTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + DBGLOG(WNM, INFO, "Bss Transition Management Response Frame Tx Done\n"); + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the Bss Transition Management Response frame. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +wnmSendBTMResponseFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + P_MSDU_INFO_T prMsduInfo = NULL; + P_BSS_INFO_T prBssInfo = NULL; + struct ACTION_BTM_RSP_FRAME_T *prTxFrame = NULL; + UINT_16 u2PayloadLen = 0; + struct BSS_TRANSITION_MGT_PARAM_T *prBtmParam = + &prAdapter->rWifiVar.rAisSpecificBssInfo.rBTMParam; + PUINT_8 pucOptInfo = NULL; + + if (!prStaRec) { + DBGLOG(WNM, INFO, "No station record found\n"); + return; + } + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; + ASSERT(prBssInfo); + + /* 1 Allocate MSDU Info */ + prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + if (!prMsduInfo) + return; + prTxFrame = (struct ACTION_BTM_RSP_FRAME_T *) + ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + /* 2 Compose The Mac Header. */ + 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_WNM_ACTION; + prTxFrame->ucAction = ACTION_WNM_BSS_TRANSITION_MANAGEMENT_RSP; + + /* 3 Compose the frame body's frame. */ + prTxFrame->ucDialogToken = prBtmParam->ucDialogToken; + prBtmParam->ucDialogToken = 0; /* reset dialog token */ + prTxFrame->ucStatusCode = prBtmParam->ucStatusCode; + prTxFrame->ucBssTermDelay = prBtmParam->ucTermDelay; + pucOptInfo = &prTxFrame->aucOptInfo[0]; + if (prBtmParam->ucStatusCode == BSS_TRANSITION_MGT_STATUS_ACCEPT) { + COPY_MAC_ADDR(pucOptInfo, prBtmParam->aucTargetBssid); + pucOptInfo += MAC_ADDR_LEN; + u2PayloadLen += MAC_ADDR_LEN; + } + if (prBtmParam->u2OurNeighborBssLen > 0) { + kalMemCopy(pucOptInfo, prBtmParam->aucOurNeighborBss, prBtmParam->u2OurNeighborBssLen); + u2PayloadLen += prBtmParam->u2OurNeighborBssLen; + } + + /* 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 = OFFSET_OF(struct ACTION_BTM_RSP_FRAME_T, aucOptInfo) + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = wnmBTMResponseTxDone; + prMsduInfo->fgIsBasicRate = FALSE; + + /* 5 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); +} /* end of wnmComposeBTMResponseFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the Bss Transition Management Query frame. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +wnmSendBTMQueryFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + P_MSDU_INFO_T prMsduInfo = NULL; + P_BSS_INFO_T prBssInfo = NULL; + struct ACTION_BTM_QUERY_FRAME_T *prTxFrame = NULL; + struct BSS_TRANSITION_MGT_PARAM_T *prBtmParam = + &prAdapter->rWifiVar.rAisSpecificBssInfo.rBTMParam; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; + ASSERT(prBssInfo); + + /* 1 Allocate MSDU Info */ + prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + if (!prMsduInfo) + return; + prTxFrame = (struct ACTION_BTM_QUERY_FRAME_T *) + ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + /* 2 Compose The Mac Header. */ + 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_WNM_ACTION; + prTxFrame->ucAction = ACTION_WNM_BSS_TRANSITION_MANAGEMENT_QUERY; + + /* 3 Compose the frame body's frame. */ + prTxFrame->ucDialogToken = prBtmParam->ucDialogToken; + prTxFrame->ucQueryReason = prBtmParam->ucQueryReason; + if (prBtmParam->u2OurNeighborBssLen > 0) + kalMemCopy(prTxFrame->pucNeighborBss, prBtmParam->aucOurNeighborBss, prBtmParam->u2OurNeighborBssLen); + + /* 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 + 4 + prBtmParam->u2OurNeighborBssLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = wnmBTMQueryTxDone; + prMsduInfo->fgIsBasicRate = FALSE; + + /* 5 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); +} /* end of wnmComposeBTMQueryFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to process the 802.11v Bss Transition Management request. +* +* +* \note +* Handle Rx mgmt request +*/ +/*----------------------------------------------------------------------------*/ +VOID wnmRecvBTMRequest(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + struct ACTION_BTM_REQ_FRAME_T *prRxFrame = NULL; + struct BSS_TRANSITION_MGT_PARAM_T *prBtmParam = + &prAdapter->rWifiVar.rAisSpecificBssInfo.rBTMParam; + PUINT_8 pucOptInfo = NULL; + UINT_8 ucRequestMode = 0; + UINT_16 u2TmpLen = 0; + struct MSG_AIS_BSS_TRANSITION_T *prMsg = NULL; + enum WNM_AIS_BSS_TRANSITION eTransType = BSS_TRANSITION_NO_MORE_ACTION; + + prRxFrame = (struct ACTION_BTM_REQ_FRAME_T *) prSwRfb->pvHeader; + if (!prRxFrame) + return; + if (prSwRfb->u2PacketLen < OFFSET_OF(struct ACTION_BTM_REQ_FRAME_T, aucOptInfo)) { + DBGLOG(WNM, WARN, "BTM request frame length is less than a standard BTM frame\n"); + return; + } + prMsg = (struct MSG_AIS_BSS_TRANSITION_T *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(struct MSG_AIS_BSS_TRANSITION_T)); + if (!prMsg) { + DBGLOG(WNM, WARN, "Msg Hdr is NULL\n"); + return; + } + + prBtmParam->ucRequestMode = prRxFrame->ucRequestMode; + prBtmParam->ucValidityInterval = prRxFrame->ucValidityInterval; + prBtmParam->u2DisassocTimer = prRxFrame->u2DisassocTimer; + prBtmParam->ucDialogToken = prRxFrame->ucDialogToken; + pucOptInfo = &prRxFrame->aucOptInfo[0]; + if (!pucOptInfo) { + DBGLOG(WNM, WARN, "pucOptInfo == NULL\n"); + return; + } + ucRequestMode = prBtmParam->ucRequestMode; + u2TmpLen = OFFSET_OF(struct ACTION_BTM_REQ_FRAME_T, aucOptInfo); + if (ucRequestMode & BTM_REQ_MODE_BSS_TERM_INCLUDE) { + struct SUB_IE_BSS_TERM_DURATION_T *prBssTermDuration = + (struct SUB_IE_BSS_TERM_DURATION_T *)pucOptInfo; + + prBtmParam->u2TermDuration = prBssTermDuration->u2Duration; + kalMemCopy(prBtmParam->aucTermTsf, prBssTermDuration->aucTermTsf, 8); + pucOptInfo += sizeof(*prBssTermDuration); + u2TmpLen += sizeof(*prBssTermDuration); + } + if (ucRequestMode & BTM_REQ_MODE_ESS_DISC_IMM) { + kalMemCopy(prBtmParam->aucSessionURL, &pucOptInfo[1], pucOptInfo[0]); + prBtmParam->ucSessionURLLen = pucOptInfo[0]; + u2TmpLen += pucOptInfo[0]; + } + if (ucRequestMode & BTM_REQ_MODE_DISC_IMM) + eTransType = BSS_TRANSITION_DISASSOC; + + if (ucRequestMode & BTM_REQ_MODE_CAND_INCLUDED_BIT) { + if (prSwRfb->u2PacketLen > u2TmpLen) { + prBtmParam->u2PeerNeighborBssLen = prSwRfb->u2PacketLen - u2TmpLen; + prBtmParam->pucPeerNeighborBss = + kalMemAlloc(prBtmParam->u2PeerNeighborBssLen, VIR_MEM_TYPE); + } else + DBGLOG(WNM, WARN, "Candidate Include bit is set, but no candidate list\n"); + } + + DBGLOG(WNM, INFO, "BTM param: Req %d, VInt %d, DiscTimer %d, Token %d, TransType %d\n", + prBtmParam->ucRequestMode, prBtmParam->ucValidityInterval, prBtmParam->u2DisassocTimer, + prBtmParam->ucDialogToken, eTransType); + + prMsg->eTransitionType = eTransType; + prMsg->rMsgHdr.eMsgId = MID_WNM_AIS_BSS_TRANSITION; + /* if Bss Transition Mgmt Request is dest for broadcast, don't send Btm Response */ + if (kalMemCmp(prRxFrame->aucDestAddr, "\xff\xff\xff\xff\xff\xff", MAC_ADDR_LEN)) + prMsg->fgNeedResponse = TRUE; + else + prMsg->fgNeedResponse = FALSE; + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsg, MSG_SEND_METHOD_BUF); +} +#endif /* CFG_SUPPORT_802_11V */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/cmd_buf.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/cmd_buf.c new file mode 100644 index 0000000000000..f96970a80f9fe --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/cmd_buf.c @@ -0,0 +1,221 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static BOOLEAN fgCmdDumpIsDone = FALSE; +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to initial the MGMT memory pool for CMD Packet. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cmdBufInitialize(IN P_ADAPTER_T prAdapter) +{ + P_CMD_INFO_T prCmdInfo; + UINT_32 i; + + ASSERT(prAdapter); + + QUEUE_INITIALIZE(&prAdapter->rFreeCmdList); + + for (i = 0; i < CFG_TX_MAX_CMD_PKT_NUM; i++) { + prCmdInfo = &prAdapter->arHifCmdDesc[i]; + QUEUE_INSERT_TAIL(&prAdapter->rFreeCmdList, &prCmdInfo->rQueEntry); + } + fgCmdDumpIsDone = FALSE; +} /* end of cmdBufInitialize() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief dump CMD queue and print to trace, for debug use only +* @param[in] prQueue Pointer to the command Queue to be dumped +* @param[in] quename Name of the queue +*/ +/*----------------------------------------------------------------------------*/ +VOID cmdBufDumpCmdQueue(P_QUE_T prQueue, CHAR *queName) +{ + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T)QUEUE_GET_HEAD(prQueue); + + DBGLOG(NIC, INFO, "Dump CMD info for %s, Elem number:%u\n", queName, prQueue->u4NumElem); + while (prCmdInfo) { + P_CMD_INFO_T prCmdInfo1, prCmdInfo2, prCmdInfo3; + + prCmdInfo1 = (P_CMD_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prCmdInfo); + if (!prCmdInfo1) { + DBGLOG(NIC, INFO, "CID:%d SEQ:%d\n", prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + break; + } + prCmdInfo2 = (P_CMD_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prCmdInfo1); + if (!prCmdInfo2) { + DBGLOG(NIC, INFO, "CID:%d, SEQ:%d; CID:%d, SEQ:%d\n", prCmdInfo->ucCID, + prCmdInfo->ucCmdSeqNum, prCmdInfo1->ucCID, prCmdInfo1->ucCmdSeqNum); + break; + } + prCmdInfo3 = (P_CMD_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prCmdInfo2); + if (!prCmdInfo3) { + DBGLOG(NIC, INFO, "CID:%d, SEQ:%d; CID:%d, SEQ:%d; CID:%d, SEQ:%d\n", prCmdInfo->ucCID, + prCmdInfo->ucCmdSeqNum, prCmdInfo1->ucCID, prCmdInfo1->ucCmdSeqNum, + prCmdInfo2->ucCID, prCmdInfo2->ucCmdSeqNum); + break; + } + DBGLOG(NIC, INFO, "CID:%d, SEQ:%d; CID:%d, SEQ:%d; CID:%d, SEQ:%d; CID:%d, SEQ:%d\n", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum, prCmdInfo1->ucCID, + prCmdInfo1->ucCmdSeqNum, prCmdInfo2->ucCID, prCmdInfo2->ucCmdSeqNum, + prCmdInfo3->ucCID, prCmdInfo3->ucCmdSeqNum); + prCmdInfo = (P_CMD_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prCmdInfo3); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Allocate CMD_INFO_T from a free list and MGMT memory pool. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] u4Length Length of the frame buffer to allocate. +* +* @retval NULL Pointer to the valid CMD Packet handler +* @retval !NULL Fail to allocat CMD Packet +*/ +/*----------------------------------------------------------------------------*/ +P_CMD_INFO_T cmdBufAllocateCmdInfo(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Length) +{ + P_CMD_INFO_T prCmdInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("cmdBufAllocateCmdInfo"); + + ASSERT(prAdapter); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + QUEUE_REMOVE_HEAD(&prAdapter->rFreeCmdList, prCmdInfo, P_CMD_INFO_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + + if (prCmdInfo) { + /* Setup initial value in CMD_INFO_T */ + /* Start address of allocated memory */ + prCmdInfo->pucInfoBuffer = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4Length); + + if (prCmdInfo->pucInfoBuffer == NULL) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + QUEUE_INSERT_TAIL(&prAdapter->rFreeCmdList, &prCmdInfo->rQueEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + + prCmdInfo = NULL; + + DBGLOG(NIC, ERROR, "Allocate prCmdInfo->pucInfoBuffer fail!\n"); + } else { + prCmdInfo->u2InfoBufLen = 0; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->u4InqueTime = 0; + prCmdInfo->u4SendToFwTime = 0; + prCmdInfo->u4FwResponseTime = 0; + } + fgCmdDumpIsDone = FALSE; + } else if (!fgCmdDumpIsDone) { + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + P_QUE_T prCmdQue = &prGlueInfo->rCmdQueue; + P_QUE_T prPendingCmdQue = &prAdapter->rPendingCmdQueue; + P_TX_TCQ_STATUS_T prTc = &prAdapter->rTxCtrl.rTc; + + fgCmdDumpIsDone = TRUE; + cmdBufDumpCmdQueue(prCmdQue, "waiting Tx CMD queue"); + cmdBufDumpCmdQueue(prPendingCmdQue, "waiting response CMD queue"); + DBGLOG(NIC, INFO, "Tc4 number:%d\n", prTc->aucFreeBufferCount[TC4_INDEX]); + + } + + return prCmdInfo; + +} /* end of cmdBufAllocateCmdInfo() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to free the CMD Packet to the MGMT memory pool. +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo CMD Packet handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cmdBufFreeCmdInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("cmdBufFreeCmdInfo"); + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo) { + if (prCmdInfo->pucInfoBuffer) { + cnmMemFree(prAdapter, prCmdInfo->pucInfoBuffer); + prCmdInfo->pucInfoBuffer = NULL; + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + QUEUE_INSERT_TAIL(&prAdapter->rFreeCmdList, &prCmdInfo->rQueEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + } + + return; + +} /* end of cmdBufFreeCmdPacket() */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/nic.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/nic.c new file mode 100644 index 0000000000000..b97683711d8c6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/nic.c @@ -0,0 +1,3707 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E 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 +#define QUEUE_CMD_TIMEOUT_MS 10000 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +static INT_EVENT_MAP_T arIntEventMapTable[] = { + {WHISR_ABNORMAL_INT, INT_EVENT_ABNORMAL}, + {WHISR_D2H_SW_INT, INT_EVENT_SW_INT}, + {WHISR_TX_DONE_INT, INT_EVENT_TX}, + {(WHISR_RX0_DONE_INT | WHISR_RX1_DONE_INT), INT_EVENT_RX} +}; + +static const UINT_8 ucIntEventMapSize = (sizeof(arIntEventMapTable) / sizeof(INT_EVENT_MAP_T)); + +static IST_EVENT_FUNCTION apfnEventFuncTable[] = { + nicProcessAbnormalInterrupt, /*!< INT_EVENT_ABNORMAL */ + nicProcessSoftwareInterrupt, /*!< INT_EVENT_SW_INT */ + nicProcessTxInterrupt, /*!< INT_EVENT_TX */ + nicProcessRxInterrupt, /*!< INT_EVENT_RX */ +}; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/*! This macro is used to reduce coding errors inside nicAllocateAdapterMemory() + * and also enhance the readability. + */ +#define LOCAL_NIC_ALLOCATE_MEMORY(pucMem, u4Size, eMemType, pucComment) \ + { \ + DBGLOG(NIC, INFO, "Allocating %u bytes for %s.\n", u4Size, pucComment); \ + pucMem = (PUINT_8)kalMemAlloc(u4Size, eMemType); \ + if (pucMem == (PUINT_8)NULL) { \ + DBGLOG(NIC, ERROR, "Could not allocate %u bytes for %s.\n", u4Size, pucComment); \ + break; \ + } \ + ASSERT(((ULONG)pucMem % 4) == 0); \ + DBGLOG(NIC, TRACE, "Virtual Address = %p for %s.\n", pucMem, pucComment); \ + } + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +VOID HifDumpEnhanceModeData(P_ADAPTER_T prAdapter) +{ + dumpMemory32((PUINT_32)prAdapter->prSDIOCtrl, sizeof(ENHANCE_MODE_DATA_STRUCT_T)); +} + +VOID HifRegDump(P_ADAPTER_T prAdapter) +{ + UINT_32 i; + UINT_32 RegVal = 0; + + for (i = 0; i <= 0x58; i += 4) { + if ((i != MCR_WTDR0) && (i != MCR_WTDR1) && (i != MCR_WRDR0) && + (i != MCR_WRDR1) && (i != MCR_WSDIOCSR) && (i != MCR_WRPLR)) { + HAL_MCR_RD(prAdapter, i, &RegVal); + DBGLOG(NIC, WARN, "HIF Reg 0x%x = 0x%x\n", i, RegVal); + } + } + DBGLOG(NIC, WARN, "\n\n"); +} + +BOOLEAN HifIsFwOwn(P_ADAPTER_T prAdapter) +{ + return prAdapter->fgIsFwOwn; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This routine is responsible for the allocation of the data structures +* inside the Adapter structure, include: +* 1. SW_RFB_Ts +* 2. Common coalescing buffer for TX PATH. +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @retval WLAN_STATUS_SUCCESS - Has enough memory. +* @retval WLAN_STATUS_RESOURCES - Memory is not enough. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicAllocateAdapterMemory(IN P_ADAPTER_T prAdapter) +{ + WLAN_STATUS status = WLAN_STATUS_RESOURCES; + P_RX_CTRL_T prRxCtrl; + P_TX_CTRL_T prTxCtrl; + UINT_32 u4CbSize; + + DEBUGFUNC("nicAllocateAdapterMemory"); + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + prTxCtrl = &prAdapter->rTxCtrl; + + do { + /* 4 <0> Reset all Memory Handler */ +#if CFG_DBG_MGT_BUF + prAdapter->u4MemFreeDynamicCount = 0; + prAdapter->u4MemAllocDynamicCount = 0; +#endif + prAdapter->pucMgtBufCached = (PUINT_8) NULL; + prRxCtrl->pucRxCached = (PUINT_8) NULL; + prAdapter->prSDIOCtrl = (P_SDIO_CTRL_T) NULL; + + /* 4 <1> Memory for Management Memory Pool and CMD_INFO_T */ + /* Allocate memory for the CMD_INFO_T and its MGMT memory pool. */ + prAdapter->u4MgtBufCachedSize = MGT_BUFFER_SIZE; + + LOCAL_NIC_ALLOCATE_MEMORY(prAdapter->pucMgtBufCached, + prAdapter->u4MgtBufCachedSize, VIR_MEM_TYPE, "COMMON MGMT MEMORY POOL"); + + /* 4 <2> Memory for RX Descriptor */ + /* Initialize the number of rx buffers we will have in our queue. */ + /* We may setup ucRxPacketDescriptors by GLUE Layer, and using + * this variable directly. + */ + /* Allocate memory for the SW receive structures. */ + prRxCtrl->u4RxCachedSize = CFG_RX_MAX_PKT_NUM * ALIGN_4(sizeof(SW_RFB_T)); + + LOCAL_NIC_ALLOCATE_MEMORY(prRxCtrl->pucRxCached, prRxCtrl->u4RxCachedSize, VIR_MEM_TYPE, "SW_RFB_T"); + + /* 4 <3> Memory for TX DEscriptor */ + prTxCtrl->u4TxCachedSize = CFG_TX_MAX_PKT_NUM * ALIGN_4(sizeof(MSDU_INFO_T)); + + LOCAL_NIC_ALLOCATE_MEMORY(prTxCtrl->pucTxCached, prTxCtrl->u4TxCachedSize, VIR_MEM_TYPE, "MSDU_INFO_T"); + + /* 4 <4> Memory for Common Coalescing Buffer */ +#if CFG_COALESCING_BUFFER_SIZE || CFG_SDIO_RX_AGG + prAdapter->pucCoalescingBufCached = (PUINT_8) NULL; + + /* Allocate memory for the common coalescing buffer. */ + u4CbSize = CFG_COALESCING_BUFFER_SIZE; + +#if CFG_COALESCING_BUFFER_SIZE > CFG_RX_COALESCING_BUFFER_SIZE + prAdapter->u4CoalescingBufCachedSize = CFG_COALESCING_BUFFER_SIZE; +#else + prAdapter->u4CoalescingBufCachedSize = CFG_RX_COALESCING_BUFFER_SIZE; +#endif + + prAdapter->pucCoalescingBufCached = kalAllocateIOBuffer(prAdapter->u4CoalescingBufCachedSize); + + if (prAdapter->pucCoalescingBufCached == NULL) { + DBGLOG(NIC, ERROR, + "Could not allocate %u bytes for coalescing buffer.\n", + prAdapter->u4CoalescingBufCachedSize); + break; + } +#endif /* CFG_COALESCING_BUFFER_SIZE */ + + /* 4 <5> Memory for enhanced interrupt response */ + prAdapter->prSDIOCtrl = (P_SDIO_CTRL_T) + kalAllocateIOBuffer(sizeof(ENHANCE_MODE_DATA_STRUCT_T)); + + if (prAdapter->prSDIOCtrl == NULL) { + DBGLOG(NIC, ERROR, + "Could not allocate %zu bytes for interrupt response.\n", + sizeof(ENHANCE_MODE_DATA_STRUCT_T)); + break; + } + + status = WLAN_STATUS_SUCCESS; + + } while (FALSE); + + if (status != WLAN_STATUS_SUCCESS) + nicReleaseAdapterMemory(prAdapter); + + return status; + +} /* end of nicAllocateAdapterMemory() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This routine is responsible for releasing the allocated memory by +* nicAllocatedAdapterMemory(). +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicReleaseAdapterMemory(IN P_ADAPTER_T prAdapter) +{ + P_TX_CTRL_T prTxCtrl; + P_RX_CTRL_T prRxCtrl; +#if CFG_DBG_MGT_BUF + P_BUF_INFO_T prBufInfo; +#endif + + 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 */ + prBufInfo = &prAdapter->rMgtBufInfo; + DBGLOG(CNM, TRACE, "freeCnt:%d,AllocCnt:%d\n", prBufInfo->u4FreeCount, prBufInfo->u4AllocCount); + ASSERT(prAdapter->u4MemFreeDynamicCount == prAdapter->u4MemAllocDynamicCount); +#endif + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief disable global interrupt +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicDisableInterrupt(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_INT_EN_CLR); + + prAdapter->fgIsIntEnable = FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief enable global interrupt +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicEnableInterrupt(IN P_ADAPTER_T prAdapter) +{ + BOOLEAN fgIsIntEnableCache; + + ASSERT(prAdapter); + fgIsIntEnableCache = prAdapter->fgIsIntEnable; + + prAdapter->fgIsIntEnable = TRUE; /* NOTE(Kevin): It must be placed before MCR GINT write. */ + + /* If need enable INT and also set LPOwn at the same time. */ + if (prAdapter->fgIsIntEnableWithLPOwnSet) { + prAdapter->fgIsIntEnableWithLPOwnSet = FALSE; /* NOTE(Kevin): It's better to place it + * before MCR GINT write. + */ + /* If INT was enabled, only set LPOwn */ + if (fgIsIntEnableCache) { + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_SET); + prAdapter->fgIsFwOwn = TRUE; + } + /* If INT was not enabled, enable it and also set LPOwn now */ + else { + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_SET | WHLPCR_INT_EN_SET); + prAdapter->fgIsFwOwn = TRUE; + } + } + /* If INT was not enabled, enable it now */ + else if (!fgIsIntEnableCache) + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_INT_EN_SET); + +} /* end of nicEnableInterrupt() */ + +#if CFG_SDIO_INTR_ENHANCE +/*----------------------------------------------------------------------------*/ +/*! +* @brief For SDIO enhance mode, set the max rx len and tx status +* +* @param prAdapter a pointer to adapter private data structure. +* +* @return - none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicSDIOInit(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4Value = 0; + + ASSERT(prAdapter); + + /* 4 <1> Check STATUS Buffer is DW alignment. */ + ASSERT(IS_ALIGN_4((ULONG)&prAdapter->prSDIOCtrl->u4WHISR)); + + /* 4 <2> Setup STATUS count. */ + { + HAL_MCR_RD(prAdapter, MCR_WHCR, &u4Value); + + /* 4 <2.1> Setup the number of maximum RX length to be report */ + u4Value &= ~(WHCR_MAX_HIF_RX_LEN_NUM); + u4Value |= ((SDIO_MAXIMUM_RX_LEN_NUM << WHCR_OFFSET_MAX_HIF_RX_LEN_NUM)); + + /* 4 <2.2> Setup RX enhancement mode */ +#if CFG_SDIO_RX_ENHANCE + u4Value |= WHCR_RX_ENHANCE_MODE_EN; +#else + u4Value &= ~WHCR_RX_ENHANCE_MODE_EN; +#endif /* CFG_SDIO_RX_AGG */ + + HAL_MCR_WR(prAdapter, MCR_WHCR, u4Value); + } + + return; + +} /* end of nicSDIOInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read interrupt status from hardware +* +* @param prAdapter pointer to the Adapter handler +* @param the interrupts +* +* @return N/A +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicSDIOReadIntStatus(IN P_ADAPTER_T prAdapter, OUT PUINT_32 pu4IntStatus) +{ + P_SDIO_CTRL_T prSDIOCtrl; + + DEBUGFUNC("nicSDIOReadIntStatus"); + + ASSERT(prAdapter); + ASSERT(pu4IntStatus); + + /* + * prSDIOCtrl is from IO buffer. + * prAdapter->prSDIOCtrl = (P_SDIO_CTRL_T) + * kalAllocateIOBuffer(sizeof(ENHANCE_MODE_DATA_STRUCT_T)); + */ + prSDIOCtrl = prAdapter->prSDIOCtrl; + ASSERT(prSDIOCtrl); + + HAL_PORT_RD(prAdapter, + MCR_WHISR, + sizeof(ENHANCE_MODE_DATA_STRUCT_T), (PUINT_8) prSDIOCtrl, sizeof(ENHANCE_MODE_DATA_STRUCT_T)); + + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + *pu4IntStatus = 0; + return; + } + + /* workaround */ + if ((prSDIOCtrl->u4WHISR & WHISR_TX_DONE_INT) == 0 && + (prSDIOCtrl->rTxInfo.au4WTSR[0] | prSDIOCtrl->rTxInfo.au4WTSR[1])) { + prSDIOCtrl->u4WHISR |= WHISR_TX_DONE_INT; + } + + if ((prSDIOCtrl->u4WHISR & BIT(31)) == 0 && + HAL_GET_MAILBOX_READ_CLEAR(prAdapter) == TRUE && + (prSDIOCtrl->u4RcvMailbox0 != 0 || prSDIOCtrl->u4RcvMailbox1 != 0)) { + prSDIOCtrl->u4WHISR |= BIT(31); + } + + *pu4IntStatus = prSDIOCtrl->u4WHISR; + +} /* end of nicSDIOReadIntStatus() */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief The function used to read interrupt status and then invoking +* dispatching procedure for the appropriate functions +* corresponding to specific interrupt bits +* +* @param prAdapter pointer to the Adapter handler +* +* @retval WLAN_STATUS_SUCCESS +* @retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicProcessIST(IN P_ADAPTER_T prAdapter) +{ + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + UINT_32 u4IntStatus = 0; + UINT_32 i; + + DEBUGFUNC("nicProcessIST"); + /* DBGLOG(NIC, LOUD, ("\n")); */ + + ASSERT(prAdapter); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, "Fail in set nicProcessIST! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + if (prAdapter->fgIsClockGatingEnabled == TRUE) + nicDisableClockGating(prAdapter); +#endif + + for (i = 0; i < CFG_IST_LOOP_COUNT; i++) { /* CFG_IST_LOOP_COUNT = 1 */ + +#if CFG_SDIO_INTR_ENHANCE + nicSDIOReadIntStatus(prAdapter, &u4IntStatus); +#else + HAL_MCR_RD(prAdapter, MCR_WHISR, &u4IntStatus); +#endif /* CFG_SDIO_INTR_ENHANCE */ + +/* DBGLOG(NIC, TRACE, ("u4IntStatus: 0x%x\n", u4IntStatus)); */ + + if (u4IntStatus & ~(WHIER_DEFAULT | WHIER_FW_OWN_BACK_INT_EN)) { + DBGLOG(INTR, WARN, "Un-handled HISR %#x, HISR = %#x (HIER:0x%x)\n", + (UINT_32) (u4IntStatus & ~WHIER_DEFAULT), u4IntStatus, + (UINT_32) WHIER_DEFAULT); + u4IntStatus &= WHIER_DEFAULT; + } + + nicProcessIST_impl(prAdapter, u4IntStatus); + + if (u4IntStatus == 0) { + if (i == 0) + u4Status = WLAN_STATUS_NOT_INDICATING; + break; + } + } + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + if (prAdapter->fgIsClockGatingEnabled == FALSE) + nicEnableClockGating(prAdapter); +#endif + + return u4Status; +} /* end of nicProcessIST() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief The function used to dispatch the appropriate functions for specific +* interrupt bits +* +* @param prAdapter pointer to the Adapter handler +* u4IntStatus interrupt status bits +* +* @retval WLAN_STATUS_SUCCESS +* @retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicProcessIST_impl(IN P_ADAPTER_T prAdapter, IN UINT_32 u4IntStatus) +{ + UINT_32 u4IntCount = 0; + P_INT_EVENT_MAP_T prIntEventMap = NULL; + + ASSERT(prAdapter); + + prAdapter->u4IntStatus = u4IntStatus; + + /* Process each of the interrupt status consequently */ + prIntEventMap = &arIntEventMapTable[0]; + for (u4IntCount = 0; u4IntCount < ucIntEventMapSize; prIntEventMap++, u4IntCount++) { + if (prIntEventMap->u4Int & prAdapter->u4IntStatus) { + if (prIntEventMap->u4Event == INT_EVENT_RX && prAdapter->fgIsEnterD3ReqIssued == TRUE) { + /* ignore */ + } else if (apfnEventFuncTable[prIntEventMap->u4Event] != NULL) { + apfnEventFuncTable[prIntEventMap->u4Event] (prAdapter); + } else { + DBGLOG(INTR, WARN, + "Empty INTR handler! ISAR bit#: %u, event:%u, func: %p\n", + prIntEventMap->u4Int, prIntEventMap->u4Event, + apfnEventFuncTable[prIntEventMap->u4Event]); + + ASSERT(0); /* to trap any NULL interrupt handler */ + } + prAdapter->u4IntStatus &= ~prIntEventMap->u4Int; + } + } + + return WLAN_STATUS_SUCCESS; +} /* end of nicProcessIST_impl() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Verify the CHIP ID +* +* @param prAdapter a pointer to adapter private data structure. +* +* +* @retval TRUE CHIP ID is the same as the setting compiled +* @retval FALSE CHIP ID is different from the setting compiled +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN nicVerifyChipID(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4CIR = 0; + + ASSERT(prAdapter); + + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4CIR); + + DBGLOG(NIC, TRACE, "Chip ID: 0x%x\n", (UINT_32) (u4CIR & WCIR_CHIP_ID)); + DBGLOG(NIC, TRACE, "Revision ID: 0x%x\n", (UINT_32) ((u4CIR & WCIR_REVISION_ID) >> 16)); + +#if 0 + if (((u4CIR & WCIR_CHIP_ID) != MTK_CHIP_REV_72) && ((u4CIR & WCIR_CHIP_ID) != MTK_CHIP_REV_82)) + return FALSE; +#endif + + prAdapter->ucRevID = (UINT_8) (((u4CIR & WCIR_REVISION_ID) >> 16) & 0xF); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Initialize the MCR to the appropriate init value, and verify the init +* value +* +* @param prAdapter a pointer to adapter private data structure. +* +* @return - +*/ +/*----------------------------------------------------------------------------*/ +VOID nicMCRInit(IN P_ADAPTER_T prAdapter) +{ + + ASSERT(prAdapter); + + /* 4 <0> Initial value */ +} + +VOID nicHifInit(IN P_ADAPTER_T prAdapter) +{ + + ASSERT(prAdapter); +#if 0 + /* reset event */ + nicPutMailbox(prAdapter, 0, 0x52455345); /* RESE */ + nicPutMailbox(prAdapter, 1, 0x545F5746); /* T_WF */ + nicSetSwIntr(prAdapter, BIT(16)); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Initialize the Adapter soft variable +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicInitializeAdapter(IN P_ADAPTER_T prAdapter) +{ + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + + prAdapter->fgIsIntEnableWithLPOwnSet = FALSE; + + do { + if (!nicVerifyChipID(prAdapter)) { + u4Status = WLAN_STATUS_FAILURE; + break; + } + /* 4 <1> MCR init */ + nicMCRInit(prAdapter); + +#if CFG_SDIO_INTR_ENHANCE + nicSDIOInit(prAdapter); +#endif /* CFG_SDIO_INTR_ENHANCE */ + + HAL_MCR_WR(prAdapter, MCR_WHIER, WHIER_DEFAULT); + + /* 4 <2> init FW HIF */ + nicHifInit(prAdapter); + } while (FALSE); + + return u4Status; +} + +#if defined(_HIF_SPI) +/*----------------------------------------------------------------------------*/ +/*! +* \brief Restore the SPI Mode Select to default mode, +* this is important while driver is unload, and this must be last mcr +* since the operation will let the hif use 8bit mode access +* +* \param[in] prAdapter a pointer to adapter private data structure. +* \param[in] eGPIO2_Mode GPIO2 operation mode +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void nicRestoreSpiDefMode(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + HAL_MCR_WR(prAdapter, MCR_WCSR, SPICSR_8BIT_MODE_DATA); + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process rx interrupt. When the rx +* Interrupt is asserted, it means there are frames in queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicProcessAbnormalInterrupt(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4Value = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + + prGlueInfo = prAdapter->prGlueInfo; + prGlueInfo->IsrAbnormalCnt++; + HAL_MCR_RD(prAdapter, MCR_WASR, &u4Value); + DBGLOG(REQ, WARN, "MCR_WASR: 0x%x\n", u4Value); + + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief . +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicProcessFwOwnBackInterrupt(IN P_ADAPTER_T prAdapter) +{ + +} /* end of nicProcessFwOwnBackInterrupt() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief . +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicProcessSoftwareInterrupt(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4IntrBits; + + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + + u4IntrBits = prAdapter->u4IntStatus & BITS(8, 31); + + prGlueInfo->IsrSoftWareCnt++; + + if ((u4IntrBits & WHISR_D2H_SW_ASSERT_INFO_INT) != 0) { + nicPrintFirmwareAssertInfo(prAdapter); +#if CFG_CHIP_RESET_SUPPORT + glSendResetRequest(); +#endif + } +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + ASSERT((u4IntrBits & (ACK_GATING_ENABLE_D2H_INT | ACK_GATING_DISABLE_D2H_INT)) + != (ACK_GATING_ENABLE_D2H_INT | ACK_GATING_DISABLE_D2H_INT)); + + if (u4IntrBits & ACK_GATING_ENABLE_D2H_INT) + prAdapter->fgIsClockGatingEnabled = TRUE; + + if (u4IntrBits & ACK_GATING_DISABLE_D2H_INT) { + prAdapter->fgIsClockGatingEnabled = FALSE; + + /* Indicate Service Thread for TX */ + if (kalGetTxPendingCmdCount(prAdapter->prGlueInfo) > 0 || wlanGetTxPendingFrameCount(prAdapter) > 0) + kalSetEvent(prAdapter->prGlueInfo); + } +#endif + + DBGLOG(REQ, WARN, "u4IntrBits: 0x%x\n", u4IntrBits); +} /* end of nicProcessSoftwareInterrupt() */ + +VOID nicPutMailbox(IN P_ADAPTER_T prAdapter, IN UINT_32 u4MailboxNum, IN UINT_32 u4Data) +{ + if (u4MailboxNum == 0) { + /* HAL_MCR_WR */ + HAL_MCR_WR(prAdapter, MCR_H2DSM0R, u4Data); + } else if (u4MailboxNum == 1) { + /* HAL_MCR_WR */ + HAL_MCR_WR(prAdapter, MCR_H2DSM1R, u4Data); + } else { + ASSERT(0); + } +} + +VOID nicGetMailbox(IN P_ADAPTER_T prAdapter, IN UINT_32 u4MailboxNum, OUT PUINT_32 pu4Data) +{ + if (u4MailboxNum == 0) { + /* HAL_MCR_RD */ + HAL_MCR_RD(prAdapter, MCR_D2HRM0R, pu4Data); + } else if (u4MailboxNum == 1) { + /* HAL_MCR_RD */ + HAL_MCR_RD(prAdapter, MCR_D2HRM1R, pu4Data); + } else { + ASSERT(0); + } +} + +VOID nicSetSwIntr(IN P_ADAPTER_T prAdapter, IN UINT_32 u4SwIntrBitmap) +{ + /* NOTE: + * SW interrupt in HW bit 16 is mapping to SW bit 0 (shift 16bit in HW transparancy) + * SW interrupt valid from b0~b15 + */ + ASSERT((u4SwIntrBitmap & BITS(0, 15)) == 0); +/* DBGLOG(NIC, TRACE, ("u4SwIntrBitmap: 0x%08x\n", u4SwIntrBitmap)); */ + + HAL_MCR_WR(prAdapter, MCR_WSICR, u4SwIntrBitmap); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This procedure is used to dequeue from prAdapter->rPendingCmdQueue +* with specified sequential number +* +* @param prAdapter Pointer of ADAPTER_T +* ucSeqNum Sequential Number +* +* @retval - P_CMD_INFO_T +*/ +/*----------------------------------------------------------------------------*/ +P_CMD_INFO_T nicGetPendingCmdInfo(IN P_ADAPTER_T prAdapter, IN UINT_8 ucSeqNum) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; + UINT_32 u4CurrTick = 0; + + 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; + + u4CurrTick = kalGetTimeTick(); + if ((prCmdInfo->u4InqueTime != 0) && + (u4CurrTick - prCmdInfo->u4InqueTime) > QUEUE_CMD_TIMEOUT_MS) + DBGLOG(REQ, WARN, "CMD que is pending too long (%u)-(%u),CmdSeq=%d,ucSeq=%d\n" + , u4CurrTick, prCmdInfo->u4InqueTime, prCmdInfo->ucCmdSeqNum, ucSeqNum); + + if (prCmdInfo->ucCmdSeqNum == ucSeqNum) + break; + + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + + prCmdInfo = NULL; + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + QUEUE_CONCATENATE_QUEUES(prCmdQue, prTempCmdQue); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + + return prCmdInfo; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This procedure is used to dequeue from prAdapter->rTxCtrl.rTxMgmtTxingQueue +* with specified sequential number +* +* @param prAdapter Pointer of ADAPTER_T +* ucSeqNum Sequential Number +* +* @retval - P_MSDU_INFO_T +*/ +/*----------------------------------------------------------------------------*/ +P_MSDU_INFO_T nicGetPendingTxMsduInfo(IN P_ADAPTER_T prAdapter, IN UINT_8 ucSeqNum) +{ + P_QUE_T prTxingQue; + QUE_T rTempQue; + P_QUE_T prTempQue = &rTempQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_MSDU_INFO_T prMsduInfo = (P_MSDU_INFO_T) NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + prTxingQue = &(prAdapter->rTxCtrl.rTxMgmtTxingQueue); + QUEUE_MOVE_ALL(prTempQue, prTxingQue); + + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prMsduInfo = (P_MSDU_INFO_T) prQueueEntry; + + if (prMsduInfo->ucTxSeqNum == ucSeqNum) + break; + + QUEUE_INSERT_TAIL(prTxingQue, prQueueEntry); + + prMsduInfo = NULL; + + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); + } + QUEUE_CONCATENATE_QUEUES(prTxingQue, prTempQue); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + return prMsduInfo; +} + +P_MSDU_INFO_T nicGetPendingStaMMPDU(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIdx) +{ + P_MSDU_INFO_T prMsduInfoListHead = (P_MSDU_INFO_T) NULL; + P_QUE_T prTxingQue = (P_QUE_T) NULL; + QUE_T rTempQue; + P_QUE_T prTempQue = &rTempQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_MSDU_INFO_T prMsduInfo = (P_MSDU_INFO_T) NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + if (prAdapter == NULL) { + ASSERT(FALSE); + return NULL; + } + + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + do { + + prTxingQue = &(prAdapter->rTxCtrl.rTxMgmtTxingQueue); + QUEUE_MOVE_ALL(prTempQue, prTxingQue); + + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prMsduInfo = (P_MSDU_INFO_T) prQueueEntry; + + if ((prMsduInfo->ucStaRecIndex == ucStaRecIdx) && (prMsduInfo->pfTxDoneHandler != NULL)) { + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfo, prMsduInfoListHead); + prMsduInfoListHead = prMsduInfo; + } else { + QUEUE_INSERT_TAIL(prTxingQue, prQueueEntry); + + prMsduInfo = NULL; + } + + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); + } + + } while (FALSE); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + return prMsduInfoListHead; +} /* nicGetPendingStaMMPDU */ + +VOID nicFreePendingTxMsduInfoByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType) +{ + P_QUE_T prTxingQue; + QUE_T rTempQue; + P_QUE_T prTempQue = &rTempQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_MSDU_INFO_T prMsduInfoListHead = (P_MSDU_INFO_T) NULL; + P_MSDU_INFO_T prMsduInfoListTail = (P_MSDU_INFO_T) NULL; + P_MSDU_INFO_T prMsduInfo = (P_MSDU_INFO_T) NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + prTxingQue = &(prAdapter->rTxCtrl.rTxMgmtTxingQueue); + QUEUE_MOVE_ALL(prTempQue, prTxingQue); + + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prMsduInfo = (P_MSDU_INFO_T) prQueueEntry; + + if ((ENUM_NETWORK_TYPE_INDEX_T) (prMsduInfo->ucNetworkType) == eNetworkType) { + if (prMsduInfoListHead == NULL) { + prMsduInfoListHead = prMsduInfoListTail = prMsduInfo; + } else { + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, prMsduInfo); + prMsduInfoListTail = prMsduInfo; + } + } else { + QUEUE_INSERT_TAIL(prTxingQue, prQueueEntry); + + prMsduInfo = NULL; + } + + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); + } + QUEUE_CONCATENATE_QUEUES(prTxingQue, prTempQue); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + /* free */ + if (prMsduInfoListHead) + nicTxFreeMsduInfoPacket(prAdapter, prMsduInfoListHead); + + return; + +} /* end of nicFreePendingTxMsduInfoByNetwork() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This procedure is used to retrieve a CMD sequence number atomically +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval - UINT_8 +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 nicIncreaseCmdSeqNum(IN P_ADAPTER_T prAdapter) +{ + UINT_8 ucRetval; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_SEQ_NUM); + + prAdapter->ucCmdSeqNum++; + ucRetval = prAdapter->ucCmdSeqNum; + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_SEQ_NUM); + + return ucRetval; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This procedure is used to retrieve a TX sequence number atomically +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval - UINT_8 +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 nicIncreaseTxSeqNum(IN P_ADAPTER_T prAdapter) +{ + UINT_8 ucRetval; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_SEQ_NUM); + + prAdapter->ucTxSeqNum++; + ucRetval = prAdapter->ucTxSeqNum; + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_SEQ_NUM); + + return ucRetval; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to handle +* media state change event +* +* @param +* +* @retval +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicMediaStateChange(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType, IN P_EVENT_CONNECTION_STATUS prConnectionStatus) +{ + P_GLUE_INFO_T prGlueInfo; + P_AIS_FSM_INFO_T prAisFsmInfo; + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + switch (eNetworkType) { + case NETWORK_TYPE_AIS_INDEX: + if (prConnectionStatus->ucMediaStatus == PARAM_MEDIA_STATE_DISCONNECTED) { /* disconnected */ + if (kalGetMediaStateIndicated(prGlueInfo) != PARAM_MEDIA_STATE_DISCONNECTED || + prAisFsmInfo->eCurrentState == AIS_STATE_JOIN) { + P_BSS_INFO_T prAisBssInfo; + + DBGLOG(NIC, TRACE, "DisByMC\n"); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + if (prAisBssInfo->ucReasonOfDisconnect != DISCONNECT_REASON_CODE_NEW_CONNECTION) + 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 5720000: + return 144; + case 5745000: + return 149; + case 5765000: + return 153; + case 5785000: + return 157; + case 5805000: + return 161; + case 5825000: + return 165; + case 5845000: + return 169; + case 5865000: + return 173; + default: + return 0; + } +} + +/* firmware command wrapper */ +/* NETWORK (WIFISYS) */ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to activate WIFISYS for specified network +* +* @param prAdapter Pointer of ADAPTER_T +* eNetworkTypeIdx Index of network type +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicActivateNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) +{ + CMD_BSS_ACTIVATE_CTRL rCmdActivateCtrl; + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + + if (eNetworkTypeIdx >= NETWORK_TYPE_INDEX_NUM) { + DBGLOG(NIC, WARN, "eNetworkTypeIdx: %d\n", eNetworkTypeIdx); + return WLAN_STATUS_FAILURE; + } + + rCmdActivateCtrl.ucNetTypeIndex = (UINT_8) eNetworkTypeIdx; + rCmdActivateCtrl.ucActive = 1; + rCmdActivateCtrl.ucVersion = 1; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[eNetworkTypeIdx]; + COPY_MAC_ADDR(rCmdActivateCtrl.aucBssMacAddr, + prBssInfo->aucOwnMacAddr); + prBssInfo->fg40mBwAllowed = FALSE; + prBssInfo->fgAssoc40mBwAllowed = FALSE; + + DBGLOG(NIC, INFO, "OwnMac=" MACSTR " BSSID=" MACSTR " NetType=%d\n", + MAC2STR(prBssInfo->aucOwnMacAddr), + MAC2STR(prBssInfo->aucBSSID), eNetworkTypeIdx); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_BSS_ACTIVATE_CTRL, + TRUE, + FALSE, + FALSE, + NULL, NULL, sizeof(CMD_BSS_ACTIVATE_CTRL), (PUINT_8)&rCmdActivateCtrl, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to deactivate WIFISYS for specified network +* +* @param prAdapter Pointer of ADAPTER_T +* eNetworkTypeIdx Index of network type +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicDeactivateNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) +{ + WLAN_STATUS u4Status; + CMD_BSS_ACTIVATE_CTRL rCmdActivateCtrl; + + ASSERT(prAdapter); + ASSERT(eNetworkTypeIdx < NETWORK_TYPE_INDEX_NUM); + + rCmdActivateCtrl.ucNetTypeIndex = (UINT_8) eNetworkTypeIdx; + rCmdActivateCtrl.ucActive = 0; + + u4Status = wlanSendSetQueryCmd(prAdapter, + CMD_ID_BSS_ACTIVATE_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, sizeof(CMD_BSS_ACTIVATE_CTRL), (PUINT_8)&rCmdActivateCtrl, NULL, 0); + + /* free all correlated station records */ + cnmStaFreeAllStaByNetType(prAdapter, eNetworkTypeIdx, FALSE); + qmFreeAllByNetType(prAdapter, eNetworkTypeIdx); + nicFreePendingTxMsduInfoByNetwork(prAdapter, eNetworkTypeIdx); + kalClearSecurityFramesByNetType(prAdapter->prGlueInfo, eNetworkTypeIdx); + + return u4Status; +} + +/* BSS-INFO */ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to sync bss info with firmware +* when a new BSS has been connected or disconnected +* +* @param prAdapter Pointer of ADAPTER_T +* eNetworkTypeIdx Index of BSS-INFO type +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicUpdateBss(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) +{ + WLAN_STATUS u4Status; + P_BSS_INFO_T prBssInfo; + CMD_SET_BSS_INFO rCmdSetBssInfo; + + ASSERT(prAdapter); + ASSERT(eNetworkTypeIdx < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkTypeIdx]); + + kalMemZero(&rCmdSetBssInfo, sizeof(CMD_SET_BSS_INFO)); + + rCmdSetBssInfo.ucNetTypeIndex = (UINT_8) eNetworkTypeIdx; + rCmdSetBssInfo.ucConnectionState = (UINT_8) prBssInfo->eConnectionState; + rCmdSetBssInfo.ucCurrentOPMode = (UINT_8) prBssInfo->eCurrentOPMode; + rCmdSetBssInfo.ucSSIDLen = (UINT_8) prBssInfo->ucSSIDLen; + kalMemCopy(rCmdSetBssInfo.aucSSID, prBssInfo->aucSSID, prBssInfo->ucSSIDLen); + COPY_MAC_ADDR(rCmdSetBssInfo.aucBSSID, prBssInfo->aucBSSID); + rCmdSetBssInfo.ucIsQBSS = (UINT_8) prBssInfo->fgIsQBSS; + rCmdSetBssInfo.ucNonHTBasicPhyType = prBssInfo->ucNonHTBasicPhyType; + rCmdSetBssInfo.u2OperationalRateSet = prBssInfo->u2OperationalRateSet; + rCmdSetBssInfo.u2BSSBasicRateSet = prBssInfo->u2BSSBasicRateSet; + rCmdSetBssInfo.ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + rCmdSetBssInfo.fgHiddenSsidMode = prBssInfo->eHiddenSsidType; +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered + || prBssInfo->eCurrentOPMode == OP_MODE_P2P_DEVICE) + 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); +#if CFG_SUPPORT_HOTSPOT_2_0 + /* mapping OSEN to WPA2, due to firmware no need to know current is OSEN */ + if (prConnSettings->eAuthMode == AUTH_MODE_WPA_OSEN) + rCmdSetBssInfo.ucAuthMode = AUTH_MODE_WPA2; + else +#endif + 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 + } + /* Firmware didn't define AUTH_MODE_NON_RSN_FT, so AUTH_MODE_OPEN is zero in firmware, + ** but it is 1 in driver. so we need to minus 1 for all authmode except AUTH_MODE_NON_RSN_FT, + ** because AUTH_MODE_NON_RSN_FT will be same as AUTH_MODE_OPEN in firmware + **/ + if (rCmdSetBssInfo.ucAuthMode != AUTH_MODE_NON_RSN_FT) + rCmdSetBssInfo.ucAuthMode -= 1; + + 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; + + DBGLOG(NIC, INFO, + "nicUpdateBss eNetworkTypeIdx: %d, OwnMac=" MACSTR "\n", + eNetworkTypeIdx, + MAC2STR(prBssInfo->aucOwnMacAddr)); + + u4Status = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_BSS_INFO, + TRUE, + FALSE, + FALSE, + NULL, NULL, sizeof(CMD_SET_BSS_INFO), (PUINT_8)&rCmdSetBssInfo, NULL, 0); + + /* if BSS-INFO is going to be disconnected state, free all correlated station records */ + if (prBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { + /* clear client list */ + bssClearClientList(prAdapter, prBssInfo); + + /* free all correlated station records */ + cnmStaFreeAllStaByNetType(prAdapter, eNetworkTypeIdx, FALSE); + qmFreeAllByNetType(prAdapter, eNetworkTypeIdx); + kalClearSecurityFramesByNetType(prAdapter->prGlueInfo, eNetworkTypeIdx); +#if CFG_ENABLE_GTK_FRAME_FILTER + if (prBssInfo->prIpV4NetAddrList) + FREE_IPV4_NETWORK_ADDR_LIST(prBssInfo->prIpV4NetAddrList); +#endif + } + + return u4Status; +} + +/* BSS-INFO Indication (PM) */ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to indicate PM that +* a BSS has been created. (for AdHoc / P2P-GO) +* +* @param prAdapter Pointer of ADAPTER_T +* eNetworkTypeIdx Index of BSS-INFO +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicPmIndicateBssCreated(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) +{ + P_BSS_INFO_T prBssInfo; + CMD_INDICATE_PM_BSS_CREATED rCmdIndicatePmBssCreated; + + ASSERT(prAdapter); + ASSERT(eNetworkTypeIdx < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkTypeIdx]); + + rCmdIndicatePmBssCreated.ucNetTypeIndex = (UINT_8) eNetworkTypeIdx; + rCmdIndicatePmBssCreated.ucDtimPeriod = prBssInfo->ucDTIMPeriod; + rCmdIndicatePmBssCreated.u2BeaconInterval = prBssInfo->u2BeaconInterval; + rCmdIndicatePmBssCreated.u2AtimWindow = prBssInfo->u2ATIMWindow; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_INDICATE_PM_BSS_CREATED, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_INDICATE_PM_BSS_CREATED), (PUINT_8)&rCmdIndicatePmBssCreated, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to indicate PM that +* a BSS has been connected +* +* @param prAdapter Pointer of ADAPTER_T +* eNetworkTypeIdx Index of BSS-INFO +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicPmIndicateBssConnected(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) +{ + P_BSS_INFO_T prBssInfo; + CMD_INDICATE_PM_BSS_CONNECTED rCmdIndicatePmBssConnected; + + ASSERT(prAdapter); + ASSERT(eNetworkTypeIdx < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkTypeIdx]); + + rCmdIndicatePmBssConnected.ucNetTypeIndex = (UINT_8) eNetworkTypeIdx; + rCmdIndicatePmBssConnected.ucDtimPeriod = prBssInfo->ucDTIMPeriod; + rCmdIndicatePmBssConnected.u2AssocId = prBssInfo->u2AssocId; + rCmdIndicatePmBssConnected.u2BeaconInterval = prBssInfo->u2BeaconInterval; + rCmdIndicatePmBssConnected.u2AtimWindow = prBssInfo->u2ATIMWindow; + + rCmdIndicatePmBssConnected.ucBmpDeliveryAC = prBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC; + rCmdIndicatePmBssConnected.ucBmpTriggerAC = prBssInfo->rPmProfSetupInfo.ucBmpTriggerAC; + + /* DBGPRINTF("nicPmIndicateBssConnected: ucBmpDeliveryAC:0x%x, ucBmpTriggerAC:0x%x", */ + /* rCmdIndicatePmBssConnected.ucBmpDeliveryAC, */ + /* rCmdIndicatePmBssConnected.ucBmpTriggerAC); */ + + if ((eNetworkTypeIdx == NETWORK_TYPE_AIS_INDEX) +#if CFG_ENABLE_WIFI_DIRECT + || ((eNetworkTypeIdx == NETWORK_TYPE_P2P_INDEX) && (prAdapter->fgIsP2PRegistered)) +#endif + ) { + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE && prBssInfo->prStaRecOfAP) { + UINT_8 ucUapsd = wmmCalculateUapsdSetting(prAdapter); + + /* should sync Tspec uapsd settings */ + rCmdIndicatePmBssConnected.ucBmpDeliveryAC = (ucUapsd >> 4) & 0xf; + rCmdIndicatePmBssConnected.ucBmpTriggerAC = ucUapsd & 0xf; + 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; + + DBGLOG(NIC, INFO, "nicPmIndicateBssAbort eNetTypeIndex:%d\n", 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); +} + +#if CFG_SUPPORT_SET_CAM_BY_PROC +static BOOLEAN fgForceSetCAM = FALSE; +VOID nicForceSetCAM(BOOLEAN enabled) +{ + fgForceSetCAM = enabled; +} +#endif + +WLAN_STATUS +nicConfigPowerSaveProfile(IN P_ADAPTER_T prAdapter, + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, PARAM_POWER_MODE ePwrMode, BOOLEAN fgEnCmdEvent) +{ + DEBUGFUNC("nicConfigPowerSaveProfile"); + DBGLOG(NIC, TRACE, "eNetTypeIndex:%d, ePwrMode:%d, fgEnCmdEvent:%d\n", + eNetTypeIndex, ePwrMode, fgEnCmdEvent); + + ASSERT(prAdapter); + + if (eNetTypeIndex >= NETWORK_TYPE_INDEX_NUM) { + ASSERT(0); + return WLAN_STATUS_NOT_SUPPORTED; + } +/* prAdapter->rWlanInfo.ePowerSaveMode.ucNetTypeIndex = eNetTypeIndex; */ +/* prAdapter->rWlanInfo.ePowerSaveMode.ucPsProfile = (UINT_8)ePwrMode; */ + prAdapter->rWlanInfo.arPowerSaveMode[eNetTypeIndex].ucNetTypeIndex = eNetTypeIndex; + prAdapter->rWlanInfo.arPowerSaveMode[eNetTypeIndex].ucPsProfile = (UINT_8) ePwrMode; + +#if CFG_SUPPORT_SET_CAM_BY_PROC + if (fgForceSetCAM && (eNetTypeIndex == NETWORK_TYPE_AIS_INDEX)) + return WLAN_STATUS_SUCCESS; +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_POWER_SAVE_MODE, + TRUE, + FALSE, + (fgEnCmdEvent ? TRUE : FALSE), + (fgEnCmdEvent ? nicCmdEventSetCommon : NULL), + (fgEnCmdEvent ? nicOidCmdTimeoutCommon : NULL), + sizeof(CMD_PS_PROFILE_T), + (PUINT_8)&(prAdapter->rWlanInfo.arPowerSaveMode[eNetTypeIndex]), + NULL, sizeof(PARAM_POWER_MODE) + ); + +} /* end of wlanoidSetAcpiDevicePowerStateMode() */ + +WLAN_STATUS nicEnterCtiaMode(IN P_ADAPTER_T prAdapter, BOOLEAN fgEnterCtia, BOOLEAN fgEnCmdEvent) +{ + CMD_SW_DBG_CTRL_T rCmdSwCtrl; + CMD_ACCESS_REG rCmdAccessReg; + struct CMD_SET_CTIA_MODE rCmdSetCtiaMode; + WLAN_STATUS rWlanStatus; + + DEBUGFUNC("nicEnterCtiaMode"); + DBGLOG(NIC, INFO, "nicEnterCtiaMode: %d\n", fgEnterCtia); + + ASSERT(prAdapter); + + rWlanStatus = WLAN_STATUS_SUCCESS; + + kalMemZero(&rCmdSetCtiaMode, sizeof(rCmdSetCtiaMode)); + rCmdSetCtiaMode.ucCmdVersion = 0x01, + rCmdSetCtiaMode.ucCtiaModeEnable = fgEnterCtia; + + if (fgEnterCtia) { + /* 1. Disable On-Lin Scan */ + prAdapter->fgEnOnlineScan = FALSE; + + /* 3. Disable FIFO FULL no ack */ + rCmdAccessReg.u4Address = 0x60140028; + rCmdAccessReg.u4Data = 0x904; + wlanSendSetQueryCmd(prAdapter, CMD_ID_ACCESS_REG, TRUE, /* FALSE, */ + FALSE, /* TRUE, */ + FALSE, NULL, NULL, sizeof(CMD_ACCESS_REG), (PUINT_8)&rCmdAccessReg, NULL, 0); + + /* 4. Disable Roaming */ + rCmdSwCtrl.u4Id = 0x90000204; + rCmdSwCtrl.u4Data = 0x0; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); + + rCmdSwCtrl.u4Id = 0x90000200; + rCmdSwCtrl.u4Data = 0x820000; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); + + /* Disalbe auto tx power */ + rCmdSwCtrl.u4Id = 0xa0100003; + rCmdSwCtrl.u4Data = 0x0; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); + + /* 2. Keep at CAM mode */ + { + PARAM_POWER_MODE ePowerMode; + + prAdapter->u4CtiaPowerMode = 0; + prAdapter->fgEnCtiaPowerMode = TRUE; + + ePowerMode = Param_PowerModeCAM; + rWlanStatus = nicConfigPowerSaveProfile(prAdapter, + NETWORK_TYPE_AIS_INDEX, ePowerMode, fgEnCmdEvent); + } + + /* 5. Disable Beacon Timeout Detection */ + prAdapter->fgDisBcnLostDetection = TRUE; + } else { + /* 1. Enaable On-Lin Scan */ + prAdapter->fgEnOnlineScan = TRUE; + + /* 3. Enable FIFO FULL no ack */ + rCmdAccessReg.u4Address = 0x60140028; + rCmdAccessReg.u4Data = 0x905; + wlanSendSetQueryCmd(prAdapter, CMD_ID_ACCESS_REG, TRUE, /* FALSE, */ + FALSE, /* TRUE, */ + FALSE, NULL, NULL, sizeof(CMD_ACCESS_REG), (PUINT_8)&rCmdAccessReg, NULL, 0); + + /* 4. Enable Roaming */ + rCmdSwCtrl.u4Id = 0x90000204; + rCmdSwCtrl.u4Data = 0x1; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); + + rCmdSwCtrl.u4Id = 0x90000200; + rCmdSwCtrl.u4Data = 0x820000; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); + + /* Enable auto tx power */ + /* */ + + rCmdSwCtrl.u4Id = 0xa0100003; + rCmdSwCtrl.u4Data = 0x1; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); + + /* 2. Keep at Fast PS */ + { + PARAM_POWER_MODE ePowerMode; + + prAdapter->u4CtiaPowerMode = 2; + prAdapter->fgEnCtiaPowerMode = TRUE; + + ePowerMode = Param_PowerModeFast_PSP; + rWlanStatus = nicConfigPowerSaveProfile(prAdapter, + NETWORK_TYPE_AIS_INDEX, ePowerMode, fgEnCmdEvent); + } + + /* 5. Enable Beacon Timeout Detection */ + prAdapter->fgDisBcnLostDetection = FALSE; + + } + + /* 6. Sync to FW : enable/disable CTIA mode*/ + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_CTIA_MODE_STATUS, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(rCmdSetCtiaMode), (PUINT_8)&rCmdSetCtiaMode, NULL, 0); + + return rWlanStatus; +} /* end of nicEnterCtiaMode() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to indicate firmware domain +* for beacon generation parameters +* +* @param prAdapter Pointer of ADAPTER_T +* eIeUpdMethod, Update Method +* eNetTypeIndex Index of Network +* u2Capability Capability +* aucIe Pointer to buffer of IEs +* u2IELen Length of IEs +* +* @retval - WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +* WLAN_STATUS_PENDING +* WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicUpdateBeaconIETemplate(IN P_ADAPTER_T prAdapter, + IN ENUM_IE_UPD_METHOD_T eIeUpdMethod, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN UINT_16 u2Capability, IN PUINT_8 aucIe, IN UINT_16 u2IELen) +{ + P_CMD_BEACON_TEMPLATE_UPDATE prCmdBcnUpdate; + UINT_16 u2CmdBufLen = 0; + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_8 ucCmdSeqNum; + + DEBUGFUNC("wlanUpdateBeaconIETemplate"); + + DBGLOG(NIC, LOUD, "\nnicUpdateBeaconIETemplate\n"); + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + + if (u2IELen > MAX_IE_LENGTH) + return WLAN_STATUS_INVALID_DATA; + + if (eIeUpdMethod == IE_UPD_METHOD_UPDATE_RANDOM || eIeUpdMethod == IE_UPD_METHOD_UPDATE_ALL) + u2CmdBufLen = OFFSET_OF(CMD_BEACON_TEMPLATE_UPDATE, aucIE) + u2IELen; + else if (eIeUpdMethod == IE_UPD_METHOD_DELETE_ALL) + u2CmdBufLen = OFFSET_OF(CMD_BEACON_TEMPLATE_UPDATE, u2IELen); + +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP + else if (eIeUpdMethod == IE_UPD_METHOD_UPDATE_PROBE_RSP) { + DBGLOG(NIC, INFO, "update probe response temp for probe response offload to firmware\n"); + u2CmdBufLen = OFFSET_OF(CMD_BEACON_TEMPLATE_UPDATE, aucIE) + u2IELen; + } +#endif + else { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + /* prepare command info */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + u2CmdBufLen)); + if (!prCmdInfo) { + DBGLOG(NIC, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + DBGLOG(REQ, TRACE, "ucCmdSeqNum =%d\n", ucCmdSeqNum); + + /* Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->eNetworkType = eNetTypeIndex; + prCmdInfo->u2InfoBufLen = (UINT_16) (CMD_HDR_SIZE + u2CmdBufLen); + prCmdInfo->pfCmdDoneHandler = NULL; /* @FIXME */ + prCmdInfo->pfCmdTimeoutHandler = NULL; /* @FIXME */ + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_UPDATE_BEACON_CONTENT; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u2CmdBufLen; + prCmdInfo->pvInformationBuffer = NULL; + prCmdInfo->u4InformationBufferLength = 0; + + /* Setup WIFI_CMD_T (no payload) */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prCmdBcnUpdate = (P_CMD_BEACON_TEMPLATE_UPDATE) (prWifiCmd->aucBuffer); + + /* fill beacon updating command */ + prCmdBcnUpdate->ucUpdateMethod = (UINT_8) eIeUpdMethod; + prCmdBcnUpdate->ucNetTypeIndex = (UINT_8) eNetTypeIndex; + prCmdBcnUpdate->u2Capability = u2Capability; + prCmdBcnUpdate->u2IELen = u2IELen; + + DBGLOG(REQ, INFO, "CmdSeqNum =%d , UpdateMethod=%d ,Capability=0x%x, NetTypeIndex:%d\n" + , ucCmdSeqNum + , prCmdBcnUpdate->ucUpdateMethod + , prCmdBcnUpdate->u2Capability + , prCmdBcnUpdate->ucNetTypeIndex); + + if (u2IELen > 0) { + kalMemCopy(prCmdBcnUpdate->aucIE, aucIe, u2IELen); + DBGLOG_MEM8_IE_ONE_LINE(REQ, TRACE, "BCN_IE", prCmdBcnUpdate->aucIE, u2IELen); + } + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + return WLAN_STATUS_PENDING; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to initialization PHY related +* varaibles +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicSetAvailablePhyTypeSet(IN P_ADAPTER_T prAdapter) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + + ASSERT(prAdapter); + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + if (prConnSettings->eDesiredPhyConfig >= PHY_CONFIG_NUM) { + ASSERT(0); + return; + } + + prAdapter->rWifiVar.ucAvailablePhyTypeSet = aucPhyCfg2PhyTypeSet[prConnSettings->eDesiredPhyConfig]; + + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_BIT_ERP) + prAdapter->rWifiVar.eNonHTBasicPhyType2G4 = PHY_TYPE_ERP_INDEX; + /* NOTE(Kevin): Because we don't have N only mode, TBD */ + else { /* if (ucNonHTPhyTypeSet & PHY_TYPE_HR_DSSS_INDEX) */ + + prAdapter->rWifiVar.eNonHTBasicPhyType2G4 = PHY_TYPE_HR_DSSS_INDEX; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update WMM Parms +* +* @param prAdapter Pointer of ADAPTER_T +* eNetworkTypeIdx Index of BSS-INFO +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicQmUpdateWmmParms(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) +{ + P_BSS_INFO_T prBssInfo; + CMD_UPDATE_WMM_PARMS_T rCmdUpdateWmmParms; + + ASSERT(prAdapter); + ASSERT(eNetworkTypeIdx < NETWORK_TYPE_INDEX_NUM); + + DBGLOG(QM, EVENT, "sizeof(AC_QUE_PARMS_T): %zu\n", sizeof(AC_QUE_PARMS_T)); + DBGLOG(QM, EVENT, "sizeof(CMD_UPDATE_WMM_PARMS): %zu\n", sizeof(CMD_UPDATE_WMM_PARMS_T)); + DBGLOG(QM, EVENT, "sizeof(WIFI_CMD_T): %zu\n", sizeof(WIFI_CMD_T)); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkTypeIdx]); + rCmdUpdateWmmParms.ucNetTypeIndex = (UINT_8) eNetworkTypeIdx; + kalMemCopy(&rCmdUpdateWmmParms.arACQueParms[0], &prBssInfo->arACQueParms[0], (sizeof(AC_QUE_PARMS_T) * AC_NUM)); + + rCmdUpdateWmmParms.fgIsQBSS = prBssInfo->fgIsQBSS; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_UPDATE_WMM_PARMS, + TRUE, + FALSE, + FALSE, + NULL, NULL, sizeof(CMD_UPDATE_WMM_PARMS_T), (PUINT_8)&rCmdUpdateWmmParms, NULL, 0); +} + +WLAN_STATUS nicQmSetRxBASize(IN P_ADAPTER_T prAdapter, BOOLEAN enable, UINT32 size) +{ + CMD_SPECIFIC_RX_BA_WIN_SIZE_T rCmdRxBASize; + + ASSERT(prAdapter); + + rCmdRxBASize.fgEnabled = enable; + rCmdRxBASize.SpecificRxBAWinSize = size; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RX_BA_WIN_SIZE, + TRUE, + FALSE, + FALSE, + NULL, NULL, sizeof(CMD_SPECIFIC_RX_BA_WIN_SIZE_T), (PUINT_8)&rCmdRxBASize, NULL, 0); +} + +WLAN_STATUS nicSetUApsdParam(IN P_ADAPTER_T prAdapter, + IN PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T rUapsdParams, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) +{ + CMD_CUSTOM_UAPSD_PARAM_STRUCT_T rCmdUapsdParam; + P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo; + P_BSS_INFO_T prBssInfo; + WLAN_STATUS ret; + + DEBUGFUNC("nicSetUApsdParam"); + + ASSERT(prAdapter); + + if (eNetworkTypeIdx >= NETWORK_TYPE_INDEX_NUM) { + DBGLOG(NIC, ERROR, "nicSetUApsdParam Invalid eNetworkTypeIdx\n"); + return WLAN_STATUS_FAILURE; + } + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkTypeIdx]); + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + + kalMemZero(&rCmdUapsdParam, sizeof(CMD_CUSTOM_UAPSD_PARAM_STRUCT_T)); + + rCmdUapsdParam.fgEnAPSD = rUapsdParams.fgEnAPSD; + rCmdUapsdParam.fgEnAPSD_AcBe = rUapsdParams.fgEnAPSD_AcBe; + rCmdUapsdParam.fgEnAPSD_AcBk = rUapsdParams.fgEnAPSD_AcBk; + rCmdUapsdParam.fgEnAPSD_AcVo = rUapsdParams.fgEnAPSD_AcVo; + rCmdUapsdParam.fgEnAPSD_AcVi = rUapsdParams.fgEnAPSD_AcVi; + rCmdUapsdParam.ucMaxSpLen = rUapsdParams.ucMaxSpLen; + + /* Fill BmpDeliveryAC and BmpTriggerAC by UapsdParams */ + prPmProfSetupInfo->ucBmpDeliveryAC = + ((rUapsdParams.fgEnAPSD_AcBe << 0) | + (rUapsdParams.fgEnAPSD_AcBk << 1) | + (rUapsdParams.fgEnAPSD_AcVi << 2) | (rUapsdParams.fgEnAPSD_AcVo << 3)); + prPmProfSetupInfo->ucBmpTriggerAC = + ((rUapsdParams.fgEnAPSD_AcBe << 0) | + (rUapsdParams.fgEnAPSD_AcBk << 1) | + (rUapsdParams.fgEnAPSD_AcVi << 2) | (rUapsdParams.fgEnAPSD_AcVo << 3)); + prPmProfSetupInfo->ucUapsdSp = rUapsdParams.ucMaxSpLen; + + DBGLOG(NIC, INFO, "nicSetUApsdParam EnAPSD[%d] Be[%d] Bk[%d] Vo[%d] Vi[%d] SPLen[%d]\n", + rCmdUapsdParam.fgEnAPSD, rCmdUapsdParam.fgEnAPSD_AcBe, rCmdUapsdParam.fgEnAPSD_AcBk, + rCmdUapsdParam.fgEnAPSD_AcVo, rCmdUapsdParam.fgEnAPSD_AcVi, rCmdUapsdParam.ucMaxSpLen); + + switch (eNetworkTypeIdx) { + case NETWORK_TYPE_AIS_INDEX: + ret = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_UAPSD_PARAM, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_CUSTOM_UAPSD_PARAM_STRUCT_T), + (PUINT_8)&rCmdUapsdParam, NULL, 0); + break; + + case NETWORK_TYPE_P2P_INDEX: + ret = wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_UAPSD_PARAM, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_CUSTOM_UAPSD_PARAM_STRUCT_T), + (PUINT_8)&rCmdUapsdParam, NULL, 0); + break; + + default: + ret = WLAN_STATUS_FAILURE; + break; + } + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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); +} +#if CFG_SUPPORT_TX_POWER_BACK_OFF +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update TX power offset corresponding to +* each band/modulation/channel combination +* +* @param prAdapter Pointer of ADAPTER_T +* prTxPwrOffsetParam Pointer of TX power offset parameters +* +* @retval WLAN_STATUS_PENDING +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicUpdateTxPowerOffset(IN P_ADAPTER_T prAdapter, IN P_CMD_MITIGATED_PWR_OFFSET_T prTxPwrOffsetParam) +{ + DEBUGFUNC("nicUpdateTxPowerOffset"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_TX_PWR_OFFSET, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_MITIGATED_PWR_OFFSET_T), + (PUINT_8) prTxPwrOffsetParam, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update TX BackOff Start/Stop +* +* @param prAdapter Pointer of ADAPTER_T +* prTxPwrOffsetParam Pointer of TX power offset parameters +* +* @retval WLAN_STATUS_PENDING +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicTxPowerBackOff(IN P_ADAPTER_T prAdapter, IN UINT32 TxPowerBackOffParam) +{ + DEBUGFUNC("nicTxPowerBackOff"); + + ASSERT(prAdapter); + + DBGLOG(REQ, INFO, "%s: TxPowerBackOffParam = 0x%x\n", __func__, TxPowerBackOffParam); + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_TX_PWR_BACKOFF, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(UINT32), + (PUINT_8)&TxPowerBackOffParam, NULL, 0); +} +#endif +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to set auto tx power parameter +* +* @param prAdapter Pointer of ADAPTER_T +* prTxPwrParam Pointer of Auto TX power parameters +* +* @retval WLAN_STATUS_PENDING +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicSetAutoTxPower(IN P_ADAPTER_T prAdapter, IN P_CMD_AUTO_POWER_PARAM_T prAutoPwrParam) +{ + DEBUGFUNC("nicSetAutoTxPower"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_AUTOPWR_CTRL, + TRUE, + FALSE, + FALSE, + NULL, NULL, sizeof(CMD_AUTO_POWER_PARAM_T), (PUINT_8) prAutoPwrParam, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update TX power gain corresponding to +* each band/modulation combination +* +* @param prAdapter Pointer of ADAPTER_T +* prTxPwrParam Pointer of TX power parameters +* +* @retval WLAN_STATUS_PENDING +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicSetAutoTxPowerControl(IN P_ADAPTER_T prAdapter, IN P_CMD_TX_PWR_T prTxPwrParam) +{ + DEBUGFUNC("nicUpdateTxPower"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_TX_PWR, + TRUE, + FALSE, FALSE, NULL, NULL, sizeof(CMD_TX_PWR_T), (PUINT_8) prTxPwrParam, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update power offset around 5GHz band +* +* @param prAdapter Pointer of ADAPTER_T +* pr5GPwrOffset Pointer of 5GHz power offset parameter +* +* @retval WLAN_STATUS_PENDING +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicUpdate5GOffset(IN P_ADAPTER_T prAdapter, IN P_CMD_5G_PWR_OFFSET_T pr5GPwrOffset) +{ + DEBUGFUNC("nicUpdate5GOffset"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_5G_PWR_OFFSET, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_5G_PWR_OFFSET_T), (PUINT_8) pr5GPwrOffset, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update DPD calibration result +* +* @param prAdapter Pointer of ADAPTER_T +* pr5GPwrOffset Pointer of parameter for DPD calibration result +* +* @retval WLAN_STATUS_PENDING +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicUpdateDPD(IN P_ADAPTER_T prAdapter, IN P_CMD_PWR_PARAM_T prDpdCalResult) +{ + DEBUGFUNC("nicUpdateDPD"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_PWR_PARAM, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_PWR_PARAM_T), (PUINT_8) prDpdCalResult, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function starts system service such as timer and +* memory pools +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicInitSystemService(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + /* <1> Initialize MGMT Memory pool and STA_REC */ + cnmMemInit(prAdapter); + cnmStaRecInit(prAdapter); + cmdBufInitialize(prAdapter); + + /* <2> Mailbox Initialization */ + mboxInitialize(prAdapter); + + /* <3> Timer Initialization */ + cnmTimerInitialize(prAdapter); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function reset some specific system service, +* such as STA-REC +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicResetSystemService(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update WMM Parms +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicUninitSystemService(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + /* Timer Destruction */ + cnmTimerDestroy(prAdapter); + + /* Mailbox Destruction */ + mboxDestroy(prAdapter); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update WMM Parms +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicInitMGMT(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo) +{ + ASSERT(prAdapter); + + /* CNM Module - initialization */ + cnmInit(prAdapter); + + wmmInit(prAdapter); + + /* RLM Module - initialization */ + rlmFsmEventInit(prAdapter); + + /* SCN Module - initialization */ + scnInit(prAdapter); + + /* AIS Module - intiailization */ + aisInitializeConnectionSettings(prAdapter, prRegInfo); + aisFsmInit(prAdapter); + +#if CFG_SUPPORT_ROAMING + /* Roaming Module - intiailization */ + roamingFsmInit(prAdapter); +#endif /* CFG_SUPPORT_ROAMING */ + +#if CFG_SUPPORT_SWCR + swCrDebugInit(prAdapter); +#endif /* CFG_SUPPORT_SWCR */ + +#if (CFG_SUPPORT_TDLS == 1) + TdlsexInit(prAdapter); +#endif /* CFG_SUPPORT_TDLS */ + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update WMM Parms +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicUninitMGMT(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + +#if CFG_SUPPORT_SWCR + swCrDebugUninit(prAdapter); +#endif /* CFG_SUPPORT_SWCR */ + +#if CFG_SUPPORT_ROAMING + /* Roaming Module - unintiailization */ + roamingFsmUninit(prAdapter); +#endif /* CFG_SUPPORT_ROAMING */ + + /* AIS Module - unintiailization */ + aisFsmUninit(prAdapter); + + /* SCN Module - unintiailization */ + scnUninit(prAdapter); + + wmmUnInit(prAdapter); + + /* RLM Module - uninitialization */ + rlmFsmEventUninit(prAdapter); + + /* CNM Module - uninitialization */ + cnmUninit(prAdapter); + +#if (CFG_SUPPORT_TDLS == 1) + TdlsexUninit(prAdapter); +#endif /* CFG_SUPPORT_TDLS */ + +} + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is to inform firmware to enable MCU clock gating +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicEnableClockGating(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i, u4WHISR = 0; + + ASSERT(prAdapter); + + if (prAdapter->fgIsClockGatingEnabled == TRUE) + return WLAN_STATUS_SUCCESS; + + nicSetSwIntr(prAdapter, REQ_GATING_ENABLE_H2D_INT); + + i = 0; + while (i < GATING_CONTROL_POLL_LIMIT) { + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) + return WLAN_STATUS_FAILURE; + + HAL_READ_INTR_STATUS(prAdapter, sizeof(UINT_32), (PUINT_8)&u4WHISR); + + if (u4WHISR & ACK_GATING_ENABLE_D2H_INT) { + prAdapter->fgIsClockGatingEnabled = TRUE; + return WLAN_STATUS_SUCCESS; + } + } + + ASSERT(0); + return WLAN_STATUS_PENDING; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is to inform firmware to disable MCU clock gating +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicDisableClockGating(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i, u4WHISR = 0; + + ASSERT(prAdapter); + + if (prAdapter->fgIsClockGatingEnabled == FALSE) + return WLAN_STATUS_SUCCESS; + + nicSetSwIntr(prAdapter, REQ_GATING_DISABLE_H2D_INT); + + i = 0; + while (i < GATING_CONTROL_POLL_LIMIT) { + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) + return WLAN_STATUS_FAILURE; + + HAL_READ_INTR_STATUS(prAdapter, sizeof(UINT_32), (PUINT_8)&u4WHISR); + + if (u4WHISR & ACK_GATING_DISABLE_D2H_INT) { + prAdapter->fgIsClockGatingEnabled = FALSE; + return WLAN_STATUS_SUCCESS; + } + } + + ASSERT(0); + return WLAN_STATUS_PENDING; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is invoked to buffer scan result +* +* @param prAdapter Pointer to the Adapter structure. +* @param rMacAddr BSSID +* @param prSsid Pointer to SSID +* @param u4Privacy Privacy settings (0: Open / 1: WEP/WPA/WPA2 enabled) +* @param rRssi Received Strength (-10 ~ -200 dBm) +* @param eNetworkType Network Type (a/b/g) +* @param prConfiguration Network Parameter +* @param eOpMode Infra/Ad-Hoc +* @param rSupportedRates Supported basic rates +* @param u2IELength IE Length +* @param pucIEBuf Pointer to Information Elements(IEs) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +nicAddScanResult(IN P_ADAPTER_T prAdapter, + IN PARAM_MAC_ADDRESS rMacAddr, + IN P_PARAM_SSID_T prSsid, + IN UINT_16 u2CapInfo, + 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 = ARRAY_SIZE(prAdapter->rWlanInfo.aucScanIEBuf); + + 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].u2CapInfo = u2CapInfo; + prAdapter->rWlanInfo.arScanResult[i].u4Privacy = u2CapInfo & CAP_INFO_PRIVACY ? 1 : 0; + 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].u2CapInfo = u2CapInfo; + prAdapter->rWlanInfo.arScanResult[i].u4Privacy = u2CapInfo & CAP_INFO_PRIVACY ? 1 : 0; + 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].u2CapInfo = u2CapInfo; + prAdapter->rWlanInfo.arScanResult[i].u4Privacy = u2CapInfo & CAP_INFO_PRIVACY ? 1 : 0; + 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; + } + } + return i; + } + return i - 1; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is invoked to free IE buffer for dedicated scan result +* +* @param prAdapter Pointer to the Adapter structure. +* @param u4Idx Index of Scan Result +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicFreeScanResultIE(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Idx) +{ + UINT_32 i; + PUINT_8 pucPivot, pucMovePivot; + UINT_32 u4MoveSize, u4FreeSize, u4ReserveSize; + + ASSERT(prAdapter); + ASSERT(u4Idx < CFG_MAX_NUM_BSS_LIST); + + if (prAdapter->rWlanInfo.arScanResult[u4Idx].u4IELength == 0 + || prAdapter->rWlanInfo.apucScanResultIEs[u4Idx] == NULL) { + return; + } + + u4FreeSize = ALIGN_4(prAdapter->rWlanInfo.arScanResult[u4Idx].u4IELength); + + pucPivot = prAdapter->rWlanInfo.apucScanResultIEs[u4Idx]; + pucMovePivot = (PUINT_8) ((ULONG) (prAdapter->rWlanInfo.apucScanResultIEs[u4Idx]) + u4FreeSize); + + u4ReserveSize = ((ULONG) pucPivot) - (ULONG) (&(prAdapter->rWlanInfo.aucScanIEBuf[0])); + u4MoveSize = prAdapter->rWlanInfo.u4ScanIEBufferUsage - u4ReserveSize - u4FreeSize; + + /* 1. rest of buffer to move forward */ + kalMemCopy(pucPivot, pucMovePivot, u4MoveSize); + + /* 1.1 modify pointers */ + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + if (i != u4Idx) { + if (prAdapter->rWlanInfo.apucScanResultIEs[i] >= pucMovePivot) { + prAdapter->rWlanInfo.apucScanResultIEs[i] = + (PUINT_8) ((ULONG) (prAdapter->rWlanInfo.apucScanResultIEs[i]) - u4FreeSize); + } + } + } + + /* 1.2 reset the freed one */ + prAdapter->rWlanInfo.arScanResult[u4Idx].u4IELength = 0; + prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; + + /* 2. reduce IE buffer usage */ + prAdapter->rWlanInfo.u4ScanIEBufferUsage -= u4FreeSize; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to hack parameters for WLAN TABLE for +* fixed rate settings +* +* @param prAdapter Pointer to the Adapter structure. +* @param eRateSetting +* @param pu2DesiredNonHTRateSet, +* @param pu2BSSBasicRateSet, +* @param pucMcsSet +* @param pucSupMcs32 +* @param pu2HtCapInfo +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicUpdateRateParams(IN P_ADAPTER_T prAdapter, + IN ENUM_REGISTRY_FIXED_RATE_T eRateSetting, + IN PUINT_8 pucDesiredPhyTypeSet, + IN PUINT_16 pu2DesiredNonHTRateSet, + IN PUINT_16 pu2BSSBasicRateSet, + IN PUINT_8 pucMcsSet, IN PUINT_8 pucSupMcs32, IN PUINT_16 pu2HtCapInfo) +{ + ASSERT(prAdapter); + ASSERT(eRateSetting > FIXED_RATE_NONE && eRateSetting < FIXED_RATE_NUM); + + switch (prAdapter->rWifiVar.eRateSetting) { + case FIXED_RATE_1M: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HR_DSSS; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_1M; + *pu2BSSBasicRateSet = RATE_SET_BIT_1M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_2M: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HR_DSSS; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_2M; + *pu2BSSBasicRateSet = RATE_SET_BIT_2M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_5_5M: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HR_DSSS; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_5_5M; + *pu2BSSBasicRateSet = RATE_SET_BIT_5_5M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_11M: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HR_DSSS; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_11M; + *pu2BSSBasicRateSet = RATE_SET_BIT_11M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_6M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_6M; + *pu2BSSBasicRateSet = RATE_SET_BIT_6M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_9M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_9M; + *pu2BSSBasicRateSet = RATE_SET_BIT_9M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_12M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_12M; + *pu2BSSBasicRateSet = RATE_SET_BIT_12M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_18M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_18M; + *pu2BSSBasicRateSet = RATE_SET_BIT_18M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_24M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_24M; + *pu2BSSBasicRateSet = RATE_SET_BIT_24M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_36M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_36M; + *pu2BSSBasicRateSet = RATE_SET_BIT_36M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_48M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_48M; + *pu2BSSBasicRateSet = RATE_SET_BIT_48M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_54M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_54M; + *pu2BSSBasicRateSet = RATE_SET_BIT_54M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_MCS0_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS0_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS1_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS1_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS2_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS2_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS3_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS3_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS4_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS4_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS5_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS5_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS6_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS6_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS7_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS7_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS0_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS0_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS1_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS1_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS2_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS2_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS3_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS3_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS4_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS4_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS5_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS5_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS6_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS6_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS7_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS7_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS0_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS0_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS1_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS1_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS2_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS2_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS3_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS3_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS4_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS4_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS5_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS5_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS6_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS6_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS7_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS7_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS32_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS32_INDEX; + *pucSupMcs32 = 1; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS0_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS0_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS1_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS1_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS2_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS2_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS3_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS3_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS4_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS4_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS5_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS5_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS6_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS6_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS7_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS7_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS32_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS32_INDEX; + *pucSupMcs32 = 1; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + default: + ASSERT(0); + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to write the register +* +* @param u4Address Register address +* u4Value the value to be written +* +* @retval WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS nicWriteMcr(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Address, IN UINT_32 u4Value) +{ + CMD_ACCESS_REG rCmdAccessReg; + + rCmdAccessReg.u4Address = u4Address; + rCmdAccessReg.u4Data = u4Value; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_ACCESS_REG), (PUINT_8) &rCmdAccessReg, NULL, 0); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to modify the auto rate parameters +* +* @param u4ArSysParam0 see description below +* u4ArSysParam1 +* u4ArSysParam2 +* u4ArSysParam3 +* +* +* @retval WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +* +* @note +* ArSysParam0[0:3] -> auto rate version (0:disable 1:version1 2:version2) +* ArSysParam0[4:5]-> auto bw version (0:disable 1:version1 2:version2) +* ArSysParam0[6:7]-> auto gi version (0:disable 1:version1 2:version2) +* ArSysParam0[8:15]-> HT rate clear mask +* ArSysParam0[16:31]-> Legacy rate clear mask +* ArSysParam1[0:7]-> Auto Rate check weighting window +* ArSysParam1[8:15]-> Auto Rate v1 Force Rate down +* ArSysParam1[16:23]-> Auto Rate v1 PerH +* ArSysParam1[24:31]-> Auto Rate v1 PerL +* +* Examples +* ArSysParam0 = 1, +* Enable auto rate version 1 +* +* ArSysParam0 = 983041, +* Enable auto rate version 1 +* Remove CCK 1M, 2M, 5.5M, 11M +* +* ArSysParam0 = 786433 +* Enable auto rate version 1 +* Remove CCK 5.5M 11M +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS +nicRlmArUpdateParms(IN P_ADAPTER_T prAdapter, + IN UINT_32 u4ArSysParam0, + IN UINT_32 u4ArSysParam1, IN UINT_32 u4ArSysParam2, IN UINT_32 u4ArSysParam3) +{ + UINT_8 ucArVer, ucAbwVer, ucAgiVer; + UINT_16 u2HtClrMask; + UINT_16 u2LegacyClrMask; + UINT_8 ucArCheckWindow; + UINT_8 ucArPerL; + UINT_8 ucArPerH; + UINT_8 ucArPerForceRateDownPer; + + ucArVer = (UINT_8) (u4ArSysParam0 & BITS(0, 3)); + ucAbwVer = (UINT_8) ((u4ArSysParam0 & BITS(4, 5)) >> 4); + ucAgiVer = (UINT_8) ((u4ArSysParam0 & BITS(6, 7)) >> 6); + u2HtClrMask = (UINT_16) ((u4ArSysParam0 & BITS(8, 15)) >> 8); + u2LegacyClrMask = (UINT_16) ((u4ArSysParam0 & BITS(16, 31)) >> 16); + + ucArCheckWindow = (UINT_8) (u4ArSysParam1 & BITS(0, 7)); + ucArPerForceRateDownPer = (UINT_8) (((u4ArSysParam1 >> 8) & BITS(0, 7))); + ucArPerH = (UINT_8) (((u4ArSysParam1 >> 16) & BITS(0, 7))); + ucArPerL = (UINT_8) (((u4ArSysParam1 >> 24) & BITS(0, 7))); + + DBGLOG(NIC, INFO, "ArParam %u %u %u %u\n", u4ArSysParam0, u4ArSysParam1, u4ArSysParam2, u4ArSysParam3); + DBGLOG(NIC, INFO, "ArVer %u AbwVer %u AgiVer %u\n", ucArVer, ucAbwVer, ucAgiVer); + DBGLOG(NIC, INFO, "HtMask %x LegacyMask %x\n", u2HtClrMask, u2LegacyClrMask); + DBGLOG(NIC, INFO, + "CheckWin %u RateDownPer %u PerH %u PerL %u\n", ucArCheckWindow, ucArPerForceRateDownPer, ucArPerH, + ucArPerL); + +#define SWCR_DATA_ADDR(MOD, ADDR) (0x90000000+(MOD<<8)+(ADDR)) +#define SWCR_DATA_CMD(CATE, WRITE, INDEX, OPT0, OPT1) ((CATE<<24) | (WRITE<<23) | (INDEX<<16) | (OPT0 << 8) | OPT1) +#define SWCR_DATA0 0x0 +#define SWCR_DATA1 0x4 +#define SWCR_DATA2 0x8 +#define SWCR_DATA3 0xC +#define SWCR_DATA4 0x10 +#define SWCR_WRITE 1 +#define SWCR_READ 0 + + if (ucArVer > 0) { + /* dummy = WiFi.WriteMCR(&h90000104, &h00000001) */ + /* dummy = WiFi.WriteMCR(&h90000100, &h00850000) */ + + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), 1); + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 5, 0, 0)); + } else { + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), 0); + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 5, 0, 0)); + } + + /* ucArVer 0: none 1:PER 2:Rcpi */ + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), ucArVer); + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 7, 0, 0)); + + /* Candidate rate Ht mask */ + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), u2HtClrMask); + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 0x1c, 0, 0)); + + /* Candidate rate legacy mask */ + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), u2LegacyClrMask); + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 0x1d, 0, 0)); + +#if 0 + if (ucArCheckWindow != 0) { + /* TX DONE MCS INDEX CHECK STA RATE DOWN TH */ + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), ucArCheckWindow); + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 0x14, 0, 0)); + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), ucArCheckWindow); + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 0xc, 0, 0)); + } + + if (ucArPerForceRateDownPer != 0) { + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), ucArPerForceRateDownPer); + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 0x18, 0, 0)); + } + if (ucArPerH != 0) { + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), ucArPerH); + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 0x1, 0, 0)); + } + if (ucArPerL != 0) { + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), ucArPerL); + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 0x2, 0, 0)); + } +#endif + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to enable roaming +* +* @param u4EnableRoaming +* +* +* @retval WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +* +* @note +* u4EnableRoaming -> Enable Romaing +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicRoamingUpdateParams(IN P_ADAPTER_T prAdapter, IN UINT_32 u4EnableRoaming) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prConnSettings->fgIsEnableRoaming = ((u4EnableRoaming > 0) ? (TRUE) : (FALSE)); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief dump firmware Assert message +* +* \param[in] +* prAdapter +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +VOID nicPrintFirmwareAssertInfo(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4MailBox0, u4MailBox1; + UINT_32 line = 0; + UINT_8 aucAssertFile[7]; + UINT_32 u4ChipId; + +#if CFG_SDIO_INTR_ENHANCE + u4MailBox0 = prAdapter->prSDIOCtrl->u4RcvMailbox0; + u4MailBox1 = prAdapter->prSDIOCtrl->u4RcvMailbox1; +#else + nicGetMailbox(prAdapter, 0, &u4MailBox0); + nicGetMailbox(prAdapter, 1, &u4MailBox1); +#endif + + line = u4MailBox0 & 0x0000FFFF; + + u4MailBox0 = ((u4MailBox0 >> 16) & 0x0000FFFF); + + kalMemCopy(&aucAssertFile[0], &u4MailBox0, 2); + kalMemCopy(&aucAssertFile[2], &u4MailBox1, 4); + + aucAssertFile[6] = '\0'; + +#if defined(MT6620) + u4ChipId = 6620; +#elif defined(MT6628) + u4ChipId = 6582; +#endif + + kalPrint("\n[MT%u][wifi][Firmware] Assert at \"%s\" #%u\n\n", u4ChipId, aucAssertFile, line); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to update Link Quality information +* +* @param prAdapter Pointer of Adapter Data Structure +* eNetTypeIdx +* prEventLinkQuality +* cRssi +* cLinkQuality +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicUpdateLinkQuality(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN P_EVENT_LINK_QUALITY prEventLinkQuality) +{ + ASSERT(prAdapter); + ASSERT(eNetTypeIdx < NETWORK_TYPE_INDEX_NUM); + ASSERT(prEventLinkQuality); + + switch (eNetTypeIdx) { + case NETWORK_TYPE_AIS_INDEX: + if (prAdapter->rWifiVar.arBssInfo[eNetTypeIdx].eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + /* check is to prevent RSSI to be updated by incorrect initial RSSI from hardware */ + /* buffer statistics for further query */ + DBGLOG(NIC, INFO, "cRssi=%d, cLinkQuality=%d, u2LinkSpeed=%u", prEventLinkQuality->cRssi, + prEventLinkQuality->cLinkQuality, prEventLinkQuality->u2LinkSpeed); + if (prAdapter->fgIsLinkQualityValid == FALSE + || (kalGetTimeTick() - prAdapter->rLinkQualityUpdateTime) > CFG_LINK_QUALITY_VALID_PERIOD) { + nicUpdateRSSI(prAdapter, eNetTypeIdx, prEventLinkQuality->cRssi, + prEventLinkQuality->cLinkQuality); + } + + if (prAdapter->fgIsLinkRateValid == FALSE + || (kalGetTimeTick() - prAdapter->rLinkRateUpdateTime) > CFG_LINK_QUALITY_VALID_PERIOD) { + nicUpdateLinkSpeed(prAdapter, eNetTypeIdx, prEventLinkQuality->u2LinkSpeed); + } + } + break; +#if CFG_ENABLE_WIFI_DIRECT && CFG_SUPPORT_P2P_RSSI_QUERY + case NETWORK_TYPE_P2P_INDEX: + if (prAdapter->fgIsP2pLinkQualityValid == FALSE + || (kalGetTimeTick() - prAdapter->rP2pLinkQualityUpdateTime) > CFG_LINK_QUALITY_VALID_PERIOD) { + P_EVENT_LINK_QUALITY_EX prEventLQEx = (P_EVENT_LINK_QUALITY_EX) prEventLinkQuality; + + nicUpdateRSSI(prAdapter, NETWORK_TYPE_P2P_INDEX, prEventLQEx->cRssiP2P, + prEventLQEx->cLinkQualityP2P); + } + break; +#endif + default: + break; + + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to update RSSI and Link Quality information +* +* @param prAdapter Pointer of Adapter Data Structure +* eNetTypeIdx +* cRssi +* cLinkQuality +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicUpdateRSSI(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN INT_8 cRssi, IN INT_8 cLinkQuality) +{ + ASSERT(prAdapter); + ASSERT(eNetTypeIdx < NETWORK_TYPE_INDEX_NUM); + + switch (eNetTypeIdx) { + case NETWORK_TYPE_AIS_INDEX: + if (prAdapter->rWifiVar.arBssInfo[eNetTypeIdx].eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + prAdapter->fgIsLinkQualityValid = TRUE; + prAdapter->rLinkQualityUpdateTime = kalGetTimeTick(); + + prAdapter->rLinkQuality.cRssi = cRssi; + prAdapter->rLinkQuality.cLinkQuality = cLinkQuality; + + /* indicate to glue layer */ + kalUpdateRSSI(prAdapter->prGlueInfo, + KAL_NETWORK_TYPE_AIS_INDEX, + prAdapter->rLinkQuality.cRssi, prAdapter->rLinkQuality.cLinkQuality); + } + + break; +#if CFG_ENABLE_WIFI_DIRECT +#if CFG_SUPPORT_P2P_RSSI_QUERY + case NETWORK_TYPE_P2P_INDEX: + prAdapter->fgIsP2pLinkQualityValid = TRUE; + prAdapter->rP2pLinkQualityUpdateTime = kalGetTimeTick(); + + prAdapter->rP2pLinkQuality.cRssi = cRssi; + prAdapter->rP2pLinkQuality.cLinkQuality = cLinkQuality; + + kalUpdateRSSI(prAdapter->prGlueInfo, KAL_NETWORK_TYPE_P2P_INDEX, cRssi, cLinkQuality); + break; +#endif +#endif + default: + break; + + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to update Link Quality information +* +* @param prAdapter Pointer of Adapter Data Structure +* eNetTypeIdx +* prEventLinkQuality +* cRssi +* cLinkQuality +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicUpdateLinkSpeed(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN UINT_16 u2LinkSpeed) +{ + ASSERT(prAdapter); + ASSERT(eNetTypeIdx < NETWORK_TYPE_INDEX_NUM); + + switch (eNetTypeIdx) { + case NETWORK_TYPE_AIS_INDEX: + if (prAdapter->rWifiVar.arBssInfo[eNetTypeIdx].eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + /* buffer statistics for further query */ + prAdapter->fgIsLinkRateValid = TRUE; + prAdapter->rLinkRateUpdateTime = kalGetTimeTick(); + + prAdapter->rLinkQuality.u2LinkSpeed = u2LinkSpeed; + } + break; + + default: + break; + + } + +} + +#if CFG_SUPPORT_RDD_TEST_MODE +WLAN_STATUS nicUpdateRddTestMode(IN P_ADAPTER_T prAdapter, IN P_CMD_RDD_CH_T prRddChParam) +{ + DEBUGFUNC("nicUpdateRddTestMode.\n"); + + ASSERT(prAdapter); + +/* aisFsmScanRequest(prAdapter, NULL); */ + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RDD_CH, + TRUE, + FALSE, FALSE, NULL, NULL, sizeof(CMD_RDD_CH_T), (PUINT_8) prRddChParam, NULL, 0); +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/nic_cmd_event.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/nic_cmd_event.c new file mode 100644 index 0000000000000..3124321139273 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/nic_cmd_event.c @@ -0,0 +1,1349 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E 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" +#ifdef FW_CFG_SUPPORT +#include "fwcfg.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 +******************************************************************************** +*/ + +VOID nicCmdEventQueryMcrRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_PARAM_CUSTOM_MCR_RW_STRUCT_T prMcrRdInfo; + P_GLUE_INFO_T prGlueInfo; + P_CMD_ACCESS_REG prCmdAccessReg; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prCmdAccessReg = (P_CMD_ACCESS_REG) (pucEventBuf); + + u4QueryInfoLen = sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T); + + prMcrRdInfo = (P_PARAM_CUSTOM_MCR_RW_STRUCT_T) prCmdInfo->pvInformationBuffer; + prMcrRdInfo->u4McrOffset = prCmdAccessReg->u4Address; + prMcrRdInfo->u4McrData = prCmdAccessReg->u4Data; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + + return; + +} + +VOID nicCmdEventQuerySwCtrlRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_PARAM_CUSTOM_SW_CTRL_STRUCT_T prSwCtrlInfo; + P_GLUE_INFO_T prGlueInfo; + P_CMD_SW_DBG_CTRL_T prCmdSwCtrl; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prCmdSwCtrl = (P_CMD_SW_DBG_CTRL_T) (pucEventBuf); + + u4QueryInfoLen = sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T); + + prSwCtrlInfo = (P_PARAM_CUSTOM_SW_CTRL_STRUCT_T) prCmdInfo->pvInformationBuffer; + prSwCtrlInfo->u4Id = prCmdSwCtrl->u4Id; + prSwCtrlInfo->u4Data = prCmdSwCtrl->u4Data; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + + return; + +} + +VOID nicCmdEventSetCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4InformationBufferLength, WLAN_STATUS_SUCCESS); + } + +} + +VOID nicCmdEventSetDisassociate(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); + } + + DBGLOG(NIC, TRACE, "DisByCmdE\n"); + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + +#if !defined(LINUX) + prAdapter->fgIsRadioOff = TRUE; +#endif + +} + +VOID nicCmdEventSetIpAddress(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4Count; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + u4Count = (prCmdInfo->u4SetInfoLen - OFFSET_OF(CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress)) + / sizeof(IPV4_NETWORK_ADDRESS); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress) + u4Count * + (OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(PARAM_NETWORK_ADDRESS_IP)), + WLAN_STATUS_SUCCESS); + } + +} + +VOID nicCmdEventQueryRfTestATInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_TEST_STATUS prTestStatus, prQueryBuffer; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prTestStatus = (P_EVENT_TEST_STATUS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prQueryBuffer = (P_EVENT_TEST_STATUS) prCmdInfo->pvInformationBuffer; + + /*Memory copy length is depended on upper-layer*/ + kalMemCopy(prQueryBuffer, prTestStatus, prCmdInfo->u4InformationBufferLength); + + + u4QueryInfoLen = sizeof(EVENT_TEST_STATUS); + + /* Update Query Information Length */ + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} + +VOID nicCmdEventQueryLinkQuality(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + PARAM_RSSI rRssi, *prRssi; + P_EVENT_LINK_QUALITY prLinkQuality; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prLinkQuality = (P_EVENT_LINK_QUALITY) pucEventBuf; + + rRssi = (PARAM_RSSI) prLinkQuality->cRssi; /* ranged from (-128 ~ 30) in unit of dBm */ + DBGLOG(NIC, INFO, " %s: rRssi = %d\n", __func__, rRssi); + + if (prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + if (rRssi > PARAM_WHQL_RSSI_MAX_DBM) + rRssi = PARAM_WHQL_RSSI_MAX_DBM; + else if (rRssi < PARAM_WHQL_RSSI_MIN_DBM) + rRssi = PARAM_WHQL_RSSI_MIN_DBM; + } else { + rRssi = PARAM_WHQL_RSSI_MIN_DBM; + } + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prRssi = (PARAM_RSSI *) prCmdInfo->pvInformationBuffer; + + kalMemCopy(prRssi, &rRssi, sizeof(PARAM_RSSI)); + u4QueryInfoLen = sizeof(PARAM_RSSI); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This routine is in response of OID_GEN_LINK_SPEED query request +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the pending command info +* @param pucEventBuf +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicCmdEventQueryLinkSpeed(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_LINK_QUALITY prLinkQuality; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4LinkSpeed; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prLinkQuality = (P_EVENT_LINK_QUALITY) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + pu4LinkSpeed = (PUINT_32) (prCmdInfo->pvInformationBuffer); + + *pu4LinkSpeed = prLinkQuality->u2LinkSpeed * 5000; + + u4QueryInfoLen = sizeof(UINT_32); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +VOID nicCmdEventQueryStatistics(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_PARAM_802_11_STATISTICS_STRUCT_T prStatistics; + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + u4QueryInfoLen = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + prStatistics = (P_PARAM_802_11_STATISTICS_STRUCT_T) prCmdInfo->pvInformationBuffer; + + prStatistics->u4Length = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + prStatistics->rTransmittedFragmentCount = prEventStatistics->rTransmittedFragmentCount; + prStatistics->rMulticastTransmittedFrameCount = prEventStatistics->rMulticastTransmittedFrameCount; + prStatistics->rFailedCount = prEventStatistics->rFailedCount; + prStatistics->rRetryCount = prEventStatistics->rRetryCount; + prStatistics->rMultipleRetryCount = prEventStatistics->rMultipleRetryCount; + prStatistics->rRTSSuccessCount = prEventStatistics->rRTSSuccessCount; + prStatistics->rRTSFailureCount = prEventStatistics->rRTSFailureCount; + prStatistics->rACKFailureCount = prEventStatistics->rACKFailureCount; + prStatistics->rFrameDuplicateCount = prEventStatistics->rFrameDuplicateCount; + prStatistics->rReceivedFragmentCount = prEventStatistics->rReceivedFragmentCount; + prStatistics->rMulticastReceivedFrameCount = prEventStatistics->rMulticastReceivedFrameCount; + prStatistics->rFCSErrorCount = prEventStatistics->rFCSErrorCount; + prStatistics->rTKIPLocalMICFailures.QuadPart = 0; + prStatistics->rTKIPICVErrors.QuadPart = 0; + prStatistics->rTKIPCounterMeasuresInvoked.QuadPart = 0; + prStatistics->rTKIPReplays.QuadPart = 0; + prStatistics->rCCMPFormatErrors.QuadPart = 0; + prStatistics->rCCMPReplays.QuadPart = 0; + prStatistics->rCCMPDecryptErrors.QuadPart = 0; + prStatistics->rFourWayHandshakeFailures.QuadPart = 0; + prStatistics->rWEPUndecryptableCount.QuadPart = 0; + prStatistics->rWEPICVErrorCount.QuadPart = 0; + prStatistics->rDecryptSuccessCount.QuadPart = 0; + prStatistics->rDecryptFailureCount.QuadPart = 0; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +VOID nicCmdEventEnterRfTest(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ +#define WAIT_FW_READY_RETRY_CNT 200 + + UINT_32 u4WHISR = 0, u4Value = 0; + UINT_8 aucTxCount[8]; + UINT_16 u2RetryCnt = 0; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + /* [driver-land] */ + prAdapter->fgTestMode = TRUE; + + /* 0. always indicate disconnection */ + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_DISCONNECTED) + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + /* 1. Remove pending TX */ + nicTxRelease(prAdapter); + + /* 1.1 clear pending Security / Management Frames */ + kalClearSecurityFrames(prAdapter->prGlueInfo); + kalClearMgmtFrames(prAdapter->prGlueInfo); + + /* 1.2 clear pending TX packet queued in glue layer */ + kalFlushPendingTxPackets(prAdapter->prGlueInfo); + + /* 2. Reset driver-domain FSMs */ + nicUninitMGMT(prAdapter); + + nicResetSystemService(prAdapter); + nicInitMGMT(prAdapter, NULL); + + /* 3. Disable Interrupt */ + HAL_INTR_DISABLE(prAdapter); + + /* 4. Block til firmware completed entering into RF test mode */ + kalMsleep(500); + while (1) { + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4Value); + + if (u4Value & WCIR_WLAN_READY) { + break; + } else if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE || + kalIsResetting() || u2RetryCnt >= WAIT_FW_READY_RETRY_CNT) { + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4SetInfoLen, WLAN_STATUS_NOT_SUPPORTED); + + } + return; + } + kalMsleep(10); + u2RetryCnt++; + } + + /* 5. Clear Interrupt Status */ + HAL_READ_INTR_STATUS(prAdapter, 4, (PUINT_8)&u4WHISR); + if (HAL_IS_TX_DONE_INTR(u4WHISR)) + HAL_READ_TX_RELEASED_COUNT(prAdapter, aucTxCount); + /* 6. Reset TX Counter */ + nicTxResetResource(prAdapter); + + /* 7. Re-enable Interrupt */ + HAL_INTR_ENABLE(prAdapter); + + /* 8. completion indication */ + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, WLAN_STATUS_SUCCESS); + } +#if CFG_SUPPORT_NVRAM + /* 9. load manufacture data */ + wlanLoadManufactureData(prAdapter, kalGetConfiguration(prAdapter->prGlueInfo)); +#endif + +} + +VOID nicCmdEventLeaveRfTest(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ +#define WAIT_FW_READY_RETRY_CNT 200 + + UINT_32 u4WHISR = 0, u4Value = 0; + UINT_8 aucTxCount[8]; + UINT_16 u2RetryCnt = 0; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + /* 1. Disable Interrupt */ + HAL_INTR_DISABLE(prAdapter); + + /* 2. Block til firmware completed leaving from RF test mode */ + kalMsleep(500); + while (1) { + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4Value); + + if (u4Value & WCIR_WLAN_READY) { + break; + } else if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE || + kalIsResetting() || u2RetryCnt >= WAIT_FW_READY_RETRY_CNT) { + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4SetInfoLen, WLAN_STATUS_NOT_SUPPORTED); + + } + return; + } + kalMsleep(10); + u2RetryCnt++; + } + + /* 3. Clear Interrupt Status */ + HAL_READ_INTR_STATUS(prAdapter, 4, (PUINT_8)&u4WHISR); + if (HAL_IS_TX_DONE_INTR(u4WHISR)) + HAL_READ_TX_RELEASED_COUNT(prAdapter, aucTxCount); + /* 4. Reset TX Counter */ + nicTxResetResource(prAdapter); + + /* 5. Re-enable Interrupt */ + HAL_INTR_ENABLE(prAdapter); + + /* 6. set driver-land variable */ + prAdapter->fgTestMode = FALSE; + + /* 7. completion indication */ + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, WLAN_STATUS_SUCCESS); + } + + /* 8. Indicate as disconnected */ + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_DISCONNECTED) { + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + + prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); + } +#if CFG_SUPPORT_NVRAM + /* 9. load manufacture data */ + wlanLoadManufactureData(prAdapter, kalGetConfiguration(prAdapter->prGlueInfo)); +#endif + + /* 10. Override network address */ + wlanUpdateNetworkAddress(prAdapter); + +} + +VOID nicCmdEventQueryAddress(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_GLUE_INFO_T prGlueInfo; + P_EVENT_BASIC_CONFIG prEventBasicConfig; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + prEventBasicConfig = (P_EVENT_BASIC_CONFIG) (pucEventBuf); + + /* copy to adapter */ + kalMemCopy(&(prAdapter->rMyMacAddr), &(prEventBasicConfig->rMyMacAddr), MAC_ADDR_LEN); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + kalMemCopy(prCmdInfo->pvInformationBuffer, &(prEventBasicConfig->rMyMacAddr), MAC_ADDR_LEN); + u4QueryInfoLen = MAC_ADDR_LEN; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + /* 4 <3> Update new MAC address and all 3 networks */ + COPY_MAC_ADDR(prAdapter->rWifiVar.aucMacAddress, prAdapter->rMyMacAddr); + COPY_MAC_ADDR(prAdapter->rWifiVar.aucDeviceAddress, prAdapter->rMyMacAddr); + prAdapter->rWifiVar.aucDeviceAddress[0] ^= MAC_ADDR_LOCAL_ADMIN; + + COPY_MAC_ADDR(prAdapter->rWifiVar.aucInterfaceAddress, prAdapter->rMyMacAddr); + prAdapter->rWifiVar.aucInterfaceAddress[0] ^= MAC_ADDR_LOCAL_ADMIN; + + COPY_MAC_ADDR(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].aucOwnMacAddr, prAdapter->rMyMacAddr); + +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { + COPY_MAC_ADDR(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].aucOwnMacAddr, + prAdapter->rWifiVar.aucDeviceAddress); + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + COPY_MAC_ADDR(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX].aucOwnMacAddr, + prAdapter->rWifiVar.aucDeviceAddress); +#endif + +#if CFG_TEST_WIFI_DIRECT_GO + if (prAdapter->rWifiVar.prP2pFsmInfo->eCurrentState == P2P_STATE_IDLE) { + wlanEnableP2pFunction(prAdapter); + + wlanEnableATGO(prAdapter); + } +#endif + + kalUpdateMACAddress(prAdapter->prGlueInfo, prAdapter->rWifiVar.aucMacAddress); + +} + +VOID nicCmdEventQueryMcastAddr(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_GLUE_INFO_T prGlueInfo; + P_EVENT_MAC_MCAST_ADDR prEventMacMcastAddr; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventMacMcastAddr = (P_EVENT_MAC_MCAST_ADDR) (pucEventBuf); + + u4QueryInfoLen = prEventMacMcastAddr->u4NumOfGroupAddr * MAC_ADDR_LEN; + + /* buffer length check */ + if (prCmdInfo->u4InformationBufferLength < u4QueryInfoLen) { + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_BUFFER_TOO_SHORT); + } else { + kalMemCopy(prCmdInfo->pvInformationBuffer, + prEventMacMcastAddr->arAddress, + prEventMacMcastAddr->u4NumOfGroupAddr * MAC_ADDR_LEN); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + } +} + +VOID nicCmdEventQueryEepromRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T prEepromRdInfo; + P_GLUE_INFO_T prGlueInfo; + P_EVENT_ACCESS_EEPROM prEventAccessEeprom; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventAccessEeprom = (P_EVENT_ACCESS_EEPROM) (pucEventBuf); + + u4QueryInfoLen = sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T); + + prEepromRdInfo = (P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T) prCmdInfo->pvInformationBuffer; + prEepromRdInfo->ucEepromIndex = (UINT_8) (prEventAccessEeprom->u2Offset); + prEepromRdInfo->u2EepromData = prEventAccessEeprom->u2Data; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + + return; + +} + +VOID nicCmdEventSetMediaStreamMode(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + PARAM_MEDIA_STREAMING_INDICATION rParamMediaStreamIndication; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, WLAN_STATUS_SUCCESS); + } + + rParamMediaStreamIndication.rStatus.eStatusType = ENUM_STATUS_TYPE_MEDIA_STREAM_MODE; + rParamMediaStreamIndication.eMediaStreamMode = + prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode == 0 ? ENUM_MEDIA_STREAM_OFF : ENUM_MEDIA_STREAM_ON; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID)&rParamMediaStreamIndication, sizeof(PARAM_MEDIA_STREAMING_INDICATION)); +} + +VOID nicCmdEventSetStopSchedScan(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + /* + * DBGLOG(SCN, INFO, "--->nicCmdEventSetStopSchedScan\n" )); + */ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + /* + * DBGLOG(SCN, INFO, "<--kalSchedScanStopped\n" ); + */ + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4InformationBufferLength, WLAN_STATUS_SUCCESS); + } + + DBGLOG(SCN, INFO, "nicCmdEventSetStopSchedScan OID done, release lock and send event to uplayer\n"); + /*Due to dead lock issue, need to release the IO control before calling kernel APIs */ + kalSchedScanStopped(prAdapter->prGlueInfo); + +} + +/* Statistics responder */ +VOID nicCmdEventQueryXmitOk(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = (UINT_32) prEventStatistics->rTransmittedFragmentCount.QuadPart; + } else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = prEventStatistics->rTransmittedFragmentCount.QuadPart; + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +VOID nicCmdEventQueryRecvOk(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = (UINT_32) prEventStatistics->rReceivedFragmentCount.QuadPart; + } else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = prEventStatistics->rReceivedFragmentCount.QuadPart; + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +VOID nicCmdEventQueryXmitError(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = (UINT_32) prEventStatistics->rFailedCount.QuadPart; + } else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = (UINT_64) prEventStatistics->rFailedCount.QuadPart; + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +VOID nicCmdEventQueryRecvError(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = (UINT_32) prEventStatistics->rFCSErrorCount.QuadPart; + /* @FIXME, RX_ERROR_DROP_COUNT/RX_FIFO_FULL_DROP_COUNT is not calculated */ + } else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = prEventStatistics->rFCSErrorCount.QuadPart; + /* @FIXME, RX_ERROR_DROP_COUNT/RX_FIFO_FULL_DROP_COUNT is not calculated */ + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +VOID nicCmdEventQueryRecvNoBuffer(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = 0; /* @FIXME? */ + } else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = 0; /* @FIXME? */ + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +VOID nicCmdEventQueryRecvCrcError(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = (UINT_32) prEventStatistics->rFCSErrorCount.QuadPart; + } else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = prEventStatistics->rFCSErrorCount.QuadPart; + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +VOID nicCmdEventQueryRecvErrorAlignment(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = (UINT_32) 0; /* @FIXME */ + } else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = 0; /* @FIXME */ + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +VOID nicCmdEventQueryXmitOneCollision(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = + (UINT_32) (prEventStatistics->rMultipleRetryCount.QuadPart - + prEventStatistics->rRetryCount.QuadPart); + } else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = + (UINT_64) (prEventStatistics->rMultipleRetryCount.QuadPart - + prEventStatistics->rRetryCount.QuadPart); + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +VOID nicCmdEventQueryXmitMoreCollisions(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = (UINT_32) prEventStatistics->rMultipleRetryCount.QuadPart; + } else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = (UINT_64) prEventStatistics->rMultipleRetryCount.QuadPart; + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +VOID nicCmdEventQueryXmitMaxCollisions(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = (UINT_32) prEventStatistics->rFailedCount.QuadPart; + } else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = (UINT_64) prEventStatistics->rFailedCount.QuadPart; + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when command by OID/ioctl has been timeout +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* +* @return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +VOID nicOidCmdTimeoutCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + ASSERT(prAdapter); + + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_FAILURE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is a generic command timeout handler +* +* @param pfnOidHandler Pointer to the OID handler +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicCmdTimeoutCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + ASSERT(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when command for entering RF test has +* failed sending due to timeout (highly possibly by firmware crash) +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* +* @return none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicOidCmdEnterRFTestTimeout(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + ASSERT(prAdapter); + + /* 1. Remove pending TX frames */ + nicTxRelease(prAdapter); + + /* 1.1 clear pending Security / Management Frames */ + kalClearSecurityFrames(prAdapter->prGlueInfo); + kalClearMgmtFrames(prAdapter->prGlueInfo); + + /* 1.2 clear pending TX packet queued in glue layer */ + kalFlushPendingTxPackets(prAdapter->prGlueInfo); + + /* 2. indicate for OID failure */ + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_FAILURE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when command for memory dump has +* replied a event. +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* @param pucEventBuf Pointer to event buffer +* +* @return none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicCmdEventQueryMemDump(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T prMemDumpInfo; + P_GLUE_INFO_T prGlueInfo; + P_EVENT_DUMP_MEM_T prEventDumpMem; + static UINT_8 aucPath[256]; + static UINT_32 u4CurTimeTick; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventDumpMem = (P_EVENT_DUMP_MEM_T) (pucEventBuf); + + u4QueryInfoLen = sizeof(P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T); + + prMemDumpInfo = (P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T) prCmdInfo->pvInformationBuffer; + prMemDumpInfo->u4Address = prEventDumpMem->u4Address; + prMemDumpInfo->u4Length = prEventDumpMem->u4Length; + prMemDumpInfo->u4RemainLength = prEventDumpMem->u4RemainLength; + prMemDumpInfo->ucFragNum = prEventDumpMem->ucFragNum; + +#if 0 + do { + UINT_32 i = 0; + + DBGLOG(REQ, TRACE, "Rx dump address 0x%X, Length %d, FragNum %d, remain %d\n", + prEventDumpMem->u4Address, + prEventDumpMem->u4Length, prEventDumpMem->ucFragNum, prEventDumpMem->u4RemainLength); +#if 0 + for (i = 0; i < prEventDumpMem->u4Length; i++) { + DBGLOG(REQ, TRACE, "%02X ", prEventDumpMem->aucBuffer[i]); + if (i % 32 == 31) + DBGLOG(REQ, TRACE, "\n"); + } +#endif + } while (FALSE); +#endif + + if (prEventDumpMem->ucFragNum == 1) { + /* Store memory dump into sdcard, + * path /sdcard/dump___.hex + */ + u4CurTimeTick = kalGetTimeTick(); + sprintf(aucPath, "/sdcard/dump_%d_0x%08X_%d.hex", + u4CurTimeTick, + prEventDumpMem->u4Address, prEventDumpMem->u4Length + prEventDumpMem->u4RemainLength); + kalWriteToFile(aucPath, FALSE, &prEventDumpMem->aucBuffer[0], prEventDumpMem->u4Length); + } else { + /* Append current memory dump to the hex file */ + kalWriteToFile(aucPath, TRUE, &prEventDumpMem->aucBuffer[0], prEventDumpMem->u4Length); + } + + if (prEventDumpMem->u4RemainLength == 0 || prEventDumpMem->u4Address == 0xFFFFFFFF) { + /* The request is finished or firmware response a error */ + /* Reply time tick to iwpriv */ + *((PUINT_32) prCmdInfo->pvInformationBuffer) = u4CurTimeTick; + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } else { + /* The memory dump request is not finished, Send next command */ + wlanSendMemDumpCmd(prAdapter, + prCmdInfo->pvInformationBuffer, prCmdInfo->u4InformationBufferLength); + } + } + + return; + +} + +#if CFG_SUPPORT_BATCH_SCAN +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when event for SUPPORT_BATCH_SCAN +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* @param pucEventBuf Pointer to the event buffer +* +* @return none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicCmdEventBatchScanResult(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_EVENT_BATCH_RESULT_T prEventBatchResult; + P_GLUE_INFO_T prGlueInfo; + + DBGLOG(SCN, TRACE, "nicCmdEventBatchScanResult"); + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventBatchResult = (P_EVENT_BATCH_RESULT_T) pucEventBuf; + + u4QueryInfoLen = sizeof(EVENT_BATCH_RESULT_T); + kalMemCopy(prCmdInfo->pvInformationBuffer, prEventBatchResult, sizeof(EVENT_BATCH_RESULT_T)); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} +#endif + +#if CFG_SUPPORT_BUILD_DATE_CODE +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when event for build date code information +* has been retrieved +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* @param pucEventBuf Pointer to the event buffer +* +* @return none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicCmdEventBuildDateCode(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_EVENT_BUILD_DATE_CODE prEvent; + P_GLUE_INFO_T prGlueInfo; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEvent = (P_EVENT_BUILD_DATE_CODE) pucEventBuf; + + u4QueryInfoLen = sizeof(UINT_8) * 16; + kalMemCopy(prCmdInfo->pvInformationBuffer, prEvent->aucDateCode, sizeof(UINT_8) * 16); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when event for query STA link status +* has been retrieved +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* @param pucEventBuf Pointer to the event buffer +* +* @return none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicCmdEventQueryStaStatistics(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_EVENT_STA_STATISTICS_T prEvent; + P_GLUE_INFO_T prGlueInfo; + P_PARAM_GET_STA_STATISTICS prStaStatistics; + + if ((prAdapter == NULL) + || (prCmdInfo == NULL) + || (pucEventBuf == NULL) + || (prCmdInfo->pvInformationBuffer == NULL)) { + ASSERT(FALSE); + return; + } + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEvent = (P_EVENT_STA_STATISTICS_T) pucEventBuf; + prStaStatistics = (P_PARAM_GET_STA_STATISTICS) prCmdInfo->pvInformationBuffer; + + u4QueryInfoLen = sizeof(PARAM_GET_STA_STA_STATISTICS); + + /* Statistics from FW is valid */ + if (prEvent->u4Flags & BIT(0)) { + prStaStatistics->ucPer = prEvent->ucPer; + prStaStatistics->ucRcpi = prEvent->ucRcpi; + prStaStatistics->u4PhyMode = prEvent->u4PhyMode; + prStaStatistics->u2LinkSpeed = prEvent->u2LinkSpeed; + + prStaStatistics->u4TxFailCount = prEvent->u4TxFailCount; + prStaStatistics->u4TxLifeTimeoutCount = prEvent->u4TxLifeTimeoutCount; + + if (prEvent->u4TxCount) { + UINT_32 u4TxDoneAirTimeMs = USEC_TO_MSEC(prEvent->u4TxDoneAirTime * 32); + + prStaStatistics->u4TxAverageAirTime = (u4TxDoneAirTimeMs / prEvent->u4TxCount); + } else { + prStaStatistics->u4TxAverageAirTime = 0; + } + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when event for query LTE safe channels +* has been retrieved +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* @param pucEventBuf Pointer to the event buffer +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicCmdEventQueryLteSafeChn(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_LTE_SAFE_CHN_T prEvent; + PARAM_GET_CHN_INFO rLteSafeChnInfo; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + UINT_8 ucIdx = 0; + + if ((prAdapter == NULL) + || (prCmdInfo == NULL) + || (pucEventBuf == NULL) + || (prCmdInfo->pvInformationBuffer == NULL)) { + ASSERT(FALSE); + return; + } + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + prEvent = (P_EVENT_LTE_SAFE_CHN_T) pucEventBuf; /* FW responsed data */ + + if (!prP2pFsmInfo) { + DBGLOG(NIC, WARN, "NULL prP2pFsmInfo, p2p is removed?\n"); + return; + } + + /* Statistics from FW is valid */ + if (prEvent->u4Flags & BIT(0)) { + for (ucIdx = 0; ucIdx < 5; ucIdx++) { + rLteSafeChnInfo.rLteSafeChnList.au4SafeChannelBitmask[ucIdx] = + prEvent->rLteSafeChn.au4SafeChannelBitmask[ucIdx]; + } + DBGLOG(NIC, INFO, "[ACS]LTE safe channel bitmask: 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", + rLteSafeChnInfo.rLteSafeChnList.au4SafeChannelBitmask[0], + rLteSafeChnInfo.rLteSafeChnList.au4SafeChannelBitmask[1], + rLteSafeChnInfo.rLteSafeChnList.au4SafeChannelBitmask[2], + rLteSafeChnInfo.rLteSafeChnList.au4SafeChannelBitmask[3], + rLteSafeChnInfo.rLteSafeChnList.au4SafeChannelBitmask[4]); + } else { + DBGLOG(NIC, ERROR, "FW's event is NOT valid.\n"); + } + p2pFunProcessAcsReport(prAdapter, + &rLteSafeChnInfo, + &(prP2pFsmInfo->rAcsReqInfo)); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when event for query FW bss info +* has been retrieved +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* @param pucEventBuf Pointer to the event buffer +* +* @return none +* +*/ +/*----------------------------------------------------------------------------*/ + +VOID nicCmdEventGetBSSInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_EVENT_AIS_BSS_INFO_T prEvent; + P_GLUE_INFO_T prGlueInfo; + P_BSS_INFO_T prAisBssInfo; + + ASSERT(prAdapter); + + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEvent = (P_EVENT_AIS_BSS_INFO_T) pucEventBuf; + + u4QueryInfoLen = sizeof(EVENT_AIS_BSS_INFO_T); + kalMemCopy(prCmdInfo->pvInformationBuffer, prEvent, sizeof(EVENT_AIS_BSS_INFO_T)); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + if (prEvent->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + if (prEvent->eConnectionState != prAisBssInfo->eConnectionState) { + DBGLOG(NIC, ERROR, "driver[%d] & FW[%d] status didn't sync !!!\n", + prAisBssInfo->eConnectionState, prEvent->eCurrentOPMode); + aisFsmStateAbort(prAdapter, DISCONNECT_REASON_CODE_RADIO_LOST, FALSE); + } + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} +#ifdef FW_CFG_SUPPORT +VOID nicCmdEventQueryCfgRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + struct _CMD_HEADER_T *prInCfgHeader; + P_GLUE_INFO_T prGlueInfo; + struct _CMD_HEADER_T *prOutCfgHeader; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prInCfgHeader = (struct _CMD_HEADER_T *) pucEventBuf; + u4QueryInfoLen = sizeof(struct _CMD_HEADER_T); + prOutCfgHeader = (struct _CMD_HEADER_T *) prCmdInfo->pvInformationBuffer; + kalMemCopy(prOutCfgHeader, prInCfgHeader, sizeof(struct _CMD_HEADER_T)); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/nic_pwr_mgt.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/nic_pwr_mgt.c new file mode 100644 index 0000000000000..aaba86090293a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/nic_pwr_mgt.c @@ -0,0 +1,492 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to process the POWER ON procedure. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicpmSetFWOwn(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnableGlobalInt) +{ + UINT_32 u4RegValue = 0; + + ASSERT(prAdapter); + + if (prAdapter->fgIsFwOwn == TRUE) + return; + + if (nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) { + /* pending interrupts */ + return; + } + + if (fgEnableGlobalInt) { + prAdapter->fgIsIntEnableWithLPOwnSet = TRUE; + } else { + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_SET); + + HAL_MCR_RD(prAdapter, MCR_WHLPCR, &u4RegValue); + if (u4RegValue & WHLPCR_FW_OWN_REQ_SET) { + /* if set firmware own not successful (possibly pending interrupts), */ + /* indicate an own clear event */ + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_CLR); + + return; + } + + prAdapter->fgIsFwOwn = TRUE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to process the POWER OFF procedure. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ + + +UINT_32 u4OriRegValue; +BOOLEAN nicpmSetDriverOwn(IN P_ADAPTER_T prAdapter) +{ +#define LP_OWN_BACK_TOTAL_DELAY_MS 2000 /* exponential of 2 */ +#define LP_OWN_BACK_LOOP_DELAY_MS 1 /* exponential of 2 */ +#define LP_OWN_BACK_CLR_OWN_ITERATION 200 /* exponential of 2 */ + + BOOLEAN fgStatus = TRUE; + UINT_32 i, u4CurrTick, u4WriteTick, u4WriteTickTemp, u4TickDiff = 0; + UINT_32 u4RegValue = 0; + GL_HIF_INFO_T *HifInfo; + BOOLEAN fgWmtCoreDump = FALSE; + + ASSERT(prAdapter); + + if (prAdapter->fgIsFwOwn == FALSE) + return fgStatus; + + HifInfo = &prAdapter->prGlueInfo->rHifInfo; + + u4WriteTick = 0; + u4CurrTick = kalGetTimeTick(); + + STATS_DRIVER_OWN_START_RECORD(); + i = 0; + + while (1) { + HAL_MCR_RD(prAdapter, MCR_WHLPCR, &u4RegValue); + DBGLOG(NIC, TRACE, " MCR_WHLPCR = 0x%x\n", u4RegValue); + if (u4RegValue & WHLPCR_FW_OWN_REQ_SET) { + HAL_MCR_RD(prAdapter, MCR_D2HRM2R, &u4OriRegValue); + prAdapter->fgIsFwOwn = FALSE; + break; + } else if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE + || (u4TickDiff = (kalGetTimeTick() - u4CurrTick)) > LP_OWN_BACK_TOTAL_DELAY_MS + || fgIsResetting == TRUE) { + /* ERRORLOG(("LP cannot be own back (for %ld ms)", kalGetTimeTick() - u4CurrTick)); */ + fgStatus = FALSE; + if (fgIsResetting != TRUE) { + UINT_32 u4FwCnt; + static unsigned int u4OwnCnt; + /* MCR_D2HRM2R: low 4 bit means interrupt times, + * high 4 bit means firmware response times. + * ORI_MCR_D2HRM2R: the last successful value. + * for example: + * MCR_D2HRM2R = 0x44, ORI_MCR_D2HRM2R = 0x44 + * means firmware no receive interrupt form hardware. + * MCR_D2HRM2R = 0x45, ORI_MCR_D2HRM2R = 0x44 + * means firmware no send response. + * MCR_D2HRM2R = 0x55, ORI_MCR_D2HRM2R = 0x44 + * means firmware send response, but driver no receive. + */ + HAL_MCR_RD(prAdapter, MCR_D2HRM2R, &u4RegValue); + DBGLOG(NIC, WARN, " [1]MCR_D2HRM2R = 0x%x, ORI_MCR_D2HRM2R = 0x%x\n", + u4RegValue, u4OriRegValue); + + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_CLR); + HAL_MCR_RD(prAdapter, MCR_WHLPCR, &u4RegValue); + if (u4RegValue & WHLPCR_FW_OWN_REQ_SET) { + HAL_MCR_RD(prAdapter, MCR_D2HRM2R, &u4OriRegValue); + prAdapter->fgIsFwOwn = FALSE; + break; + } + HAL_MCR_RD(prAdapter, MCR_D2HRM2R, &u4RegValue); + DBGLOG(NIC, WARN, " [2]MCR_D2HRM2R = 0x%x, ORI_MCR_D2HRM2R = 0x%x\n", + u4RegValue, u4OriRegValue); + fgWmtCoreDump = glIsWmtCodeDump(); + DBGLOG(NIC, WARN, + " Fatal error! Driver own fail!!!! %d, fgIsBusAccessFailed: %d, OWN retry:%d, fgCoreDump:%d, u4TickDiff:%u\n", + u4OwnCnt++, fgIsBusAccessFailed, i, fgWmtCoreDump, u4TickDiff); + DBGLOG(NIC, WARN, "CONNSYS FW CPUINFO:\n"); + for (u4FwCnt = 0; u4FwCnt < 16; u4FwCnt++) + DBGLOG(NIC, WARN, "0x%08x ", MCU_REG_READL(HifInfo, CONN_MCU_CPUPCR)); + /* CONSYS_REG_READ(CONSYS_CPUPCR_REG) */ + if (fgWmtCoreDump == FALSE) { + kalSendAeeWarning("[Fatal error! Driver own fail!]", __func__); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_CHIP_RESET); + } else + DBGLOG(NIC, WARN, + "[Driver own fail!] WMT is code dumping !STOP AEE & chip reset\n"); + + } + break; + } + + u4WriteTickTemp = kalGetTimeTick(); + if (((u4WriteTickTemp - u4WriteTick) > LP_OWN_BACK_CLR_OWN_ITERATION) + || (i == 0)) { + /* Software get LP ownership - per LP_OWN_BACK_CLR_OWN_ITERATION*/ + DBGLOG(NIC, TRACE, "retry i=%d, write LP_OWN_REQ_CLR cur time %u - %u\n", + i, u4WriteTickTemp, u4WriteTick); + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_CLR); + u4WriteTick = u4WriteTickTemp; + } + + /* Delay for LP engine to complete its operation. */ + if (i <= 8) + kalMdelay(LP_OWN_BACK_LOOP_DELAY_MS); + else + kalMsleep(LP_OWN_BACK_LOOP_DELAY_MS); + i++; + } + + STATS_DRIVER_OWN_END_RECORD(); + STATS_DRIVER_OWN_STOP(); + + return fgStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to set ACPI power mode to D0. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN nicpmSetAcpiPowerD0(IN P_ADAPTER_T prAdapter) +{ + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + UINT_32 u4Value = 0, u4WHISR = 0; + UINT_8 aucTxCount[8]; + UINT_32 i; +#if CFG_ENABLE_FW_DOWNLOAD + UINT_32 u4FwImgLength, u4FwLoadAddr, u4ImgSecSize; + PVOID prFwMappingHandle; + PVOID pvFwImageMapFile = NULL; +#if CFG_ENABLE_FW_DIVIDED_DOWNLOAD + UINT_32 j; + P_FIRMWARE_DIVIDED_DOWNLOAD_T prFwHead; + BOOLEAN fgValidHead; + const UINT_32 u4CRCOffset = offsetof(FIRMWARE_DIVIDED_DOWNLOAD_T, u4NumOfEntries); +#endif +#endif + + DEBUGFUNC("nicpmSetAcpiPowerD0"); + ASSERT(prAdapter); + + do { + /* 0. Reset variables in ADAPTER_T */ + prAdapter->fgIsFwOwn = TRUE; + prAdapter->fgWiFiInSleepyState = FALSE; + prAdapter->rAcpiState = ACPI_STATE_D0; + prAdapter->fgIsEnterD3ReqIssued = FALSE; + + /* 1. Request Ownership to enter F/W download state */ + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); +#if !CFG_ENABLE_FULL_PM + nicpmSetDriverOwn(prAdapter); +#endif + + /* 2. Initialize the Adapter */ + u4Status = nicInitializeAdapter(prAdapter); + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(NIC, ERROR, "nicInitializeAdapter failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } + +#if CFG_ENABLE_FW_DOWNLOAD + prFwMappingHandle = kalFirmwareImageMapping(prAdapter->prGlueInfo, &pvFwImageMapFile, &u4FwImgLength); + if (!prFwMappingHandle) { + DBGLOG(NIC, ERROR, "Fail to load FW image from file!\n"); + pvFwImageMapFile = NULL; + } + + if (pvFwImageMapFile == NULL) { + u4Status = WLAN_STATUS_FAILURE; + break; + } + + /* 3.1 disable interrupt, download is done by polling mode only */ + nicDisableInterrupt(prAdapter); + + /* 3.2 Initialize Tx Resource to fw download state */ + nicTxInitResetResource(prAdapter); + + /* 3.3 FW download here */ + u4FwLoadAddr = kalGetFwLoadAddress(prAdapter->prGlueInfo); + +#if CFG_ENABLE_FW_DIVIDED_DOWNLOAD + /* 3a. parse file header for decision of divided firmware download or not */ + prFwHead = (P_FIRMWARE_DIVIDED_DOWNLOAD_T) pvFwImageMapFile; + + if (prFwHead->u4Signature == MTK_WIFI_SIGNATURE && + prFwHead->u4CRC == wlanCRC32((PUINT_8) pvFwImageMapFile + u4CRCOffset, + u4FwImgLength - u4CRCOffset)) { + fgValidHead = TRUE; + } else { + fgValidHead = FALSE; + } + + /* 3b. engage divided firmware downloading */ + if (fgValidHead == TRUE) { + for (i = 0; i < prFwHead->u4NumOfEntries; i++) { +#if CFG_ENABLE_FW_DOWNLOAD_AGGREGATION + if (wlanImageSectionDownloadAggregated(prAdapter, + prFwHead->arSection[i].u4DestAddr, + prFwHead->arSection[i].u4Length, + (PUINT_8) pvFwImageMapFile + + prFwHead->arSection[i].u4Offset) != + WLAN_STATUS_SUCCESS) { + DBGLOG(NIC, ERROR, "Firmware scatter download failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + } +#else + for (j = 0; j < prFwHead->arSection[i].u4Length; j += CMD_PKT_SIZE_FOR_IMAGE) { + if (j + CMD_PKT_SIZE_FOR_IMAGE < prFwHead->arSection[i].u4Length) + u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; + else + u4ImgSecSize = prFwHead->arSection[i].u4Length - j; + + if (wlanImageSectionDownload(prAdapter, + prFwHead->arSection[i].u4DestAddr + j, + u4ImgSecSize, + (PUINT_8) pvFwImageMapFile + + prFwHead->arSection[i].u4Offset + j) != WLAN_STATUS_SUCCESS) { + DBGLOG(NIC, ERROR, "Firmware scatter download failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } + } +#endif + /* escape from loop if any pending error occurs */ + if (u4Status == WLAN_STATUS_FAILURE) + break; + } + } else +#endif +#if CFG_ENABLE_FW_DOWNLOAD_AGGREGATION + if (wlanImageSectionDownloadAggregated(prAdapter, + u4FwLoadAddr, + u4FwImgLength, + (PUINT_8) pvFwImageMapFile) != WLAN_STATUS_SUCCESS) { + DBGLOG(NIC, ERROR, "Firmware scatter download failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + } +#else + for (i = 0; i < u4FwImgLength; i += CMD_PKT_SIZE_FOR_IMAGE) { + if (i + CMD_PKT_SIZE_FOR_IMAGE < u4FwImgLength) + u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; + else + u4ImgSecSize = u4FwImgLength - i; + + if (wlanImageSectionDownload(prAdapter, + u4FwLoadAddr + i, + u4ImgSecSize, + (PUINT_8) pvFwImageMapFile + i) != WLAN_STATUS_SUCCESS) { + DBGLOG(NIC, ERROR, "wlanImageSectionDownload failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } + } +#endif + + if (u4Status != WLAN_STATUS_SUCCESS) { + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, prFwMappingHandle, pvFwImageMapFile); + break; + } +#if !CFG_ENABLE_FW_DOWNLOAD_ACK + /* Send INIT_CMD_ID_QUERY_PENDING_ERROR command and wait for response */ + if (wlanImageQueryStatus(prAdapter) != WLAN_STATUS_SUCCESS) { + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, prFwMappingHandle, pvFwImageMapFile); + u4Status = WLAN_STATUS_FAILURE; + break; + } +#endif + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, prFwMappingHandle, pvFwImageMapFile); + + /* 4. send Wi-Fi Start command */ +#if CFG_OVERRIDE_FW_START_ADDRESS + wlanConfigWifiFunc(prAdapter, TRUE, kalGetFwStartAddress(prAdapter->prGlueInfo)); +#else + wlanConfigWifiFunc(prAdapter, FALSE, 0); +#endif +#endif /* if CFG_ENABLE_FW_DOWNLOAD */ + + /* 5. check Wi-Fi FW asserts ready bit */ + DBGLOG(NIC, TRACE, "wlanAdapterStart(): Waiting for Ready bit..\n"); + i = 0; + while (1) { + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4Value); + + if (u4Value & WCIR_WLAN_READY) { + DBGLOG(NIC, TRACE, "Ready bit asserted\n"); + break; + } else if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + break; + } else if (i >= CFG_RESPONSE_POLLING_TIMEOUT) { + DBGLOG(NIC, ERROR, "Waiting for Ready bit: Timeout\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } + i++; + kalMsleep(10); + } + + if (u4Status == WLAN_STATUS_SUCCESS) { + /* 6.1 reset interrupt status */ + HAL_READ_INTR_STATUS(prAdapter, 4, (PUINT_8)(&u4WHISR)); + if (HAL_IS_TX_DONE_INTR(u4WHISR)) + HAL_READ_TX_RELEASED_COUNT(prAdapter, aucTxCount); + + /* 6.2 reset TX Resource for normal operation */ + nicTxResetResource(prAdapter); + + /* 6.3 Enable interrupt */ + nicEnableInterrupt(prAdapter); + + /* 6.4 Override network address */ + wlanUpdateNetworkAddress(prAdapter); + + /* 6.5 indicate disconnection as default status */ + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + } + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + + /* MGMT Initialization */ + nicInitMGMT(prAdapter, NULL); + + } while (FALSE); + + if (u4Status != WLAN_STATUS_SUCCESS) + return FALSE; + else + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This routine is used to set ACPI power mode to D3. +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN nicpmSetAcpiPowerD3(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i; + + ASSERT(prAdapter); + + /* 1. MGMT - unitialization */ + nicUninitMGMT(prAdapter); + + /* 2. Disable Interrupt */ + nicDisableInterrupt(prAdapter); + + /* 3. emit CMD_NIC_POWER_CTRL command packet */ + wlanSendNicPowerCtrlCmd(prAdapter, 1); + + /* 4. Clear Interrupt Status */ + i = 0; + while (i < CFG_IST_LOOP_COUNT && nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) { + i++; + }; + + /* 5. Remove pending TX */ + nicTxRelease(prAdapter); + + /* 5.1 clear pending Security / Management Frames */ + kalClearSecurityFrames(prAdapter->prGlueInfo); + kalClearMgmtFrames(prAdapter->prGlueInfo); + + /* 5.2 clear pending TX packet queued in glue layer */ + kalFlushPendingTxPackets(prAdapter->prGlueInfo); + + /* 6. Set Onwership to F/W */ + nicpmSetFWOwn(prAdapter, FALSE); + + /* 7. Set variables */ + prAdapter->rAcpiState = ACPI_STATE_D3; + + return TRUE; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/nic_rx.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/nic_rx.c new file mode 100644 index 0000000000000..d82fd7a195dd9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/nic_rx.c @@ -0,0 +1,3284 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +#ifndef LINUX +#include +#else +#include +#endif + +#include "gl_os.h" +#include "debug.h" +#include "wlan_lib.h" +#include "gl_wext.h" + +#include +#include +#include +#include +#include "gl_cfg80211.h" +#include "gl_vendor.h" +#include "wnm.h" +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define RX_RESPONSE_TIMEOUT (1000) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +#if CFG_MGMT_FRAME_HANDLING +static PROCESS_RX_MGT_FUNCTION apfnProcessRxMgtFrame[MAX_NUM_OF_FC_SUBTYPES] = { +#if CFG_SUPPORT_AAA + aaaFsmRunEventRxAssoc, /* subtype 0000: Association request */ +#else + NULL, /* subtype 0000: Association request */ +#endif /* CFG_SUPPORT_AAA */ + saaFsmRunEventRxAssoc, /* subtype 0001: Association response */ +#if CFG_SUPPORT_AAA + aaaFsmRunEventRxAssoc, /* subtype 0010: Reassociation request */ +#else + NULL, /* subtype 0010: Reassociation request */ +#endif /* CFG_SUPPORT_AAA */ + saaFsmRunEventRxAssoc, /* subtype 0011: Reassociation response */ +#if (CFG_SUPPORT_ADHOC) || (CFG_SUPPORT_AAA) + bssProcessProbeRequest, /* subtype 0100: Probe request */ +#else + NULL, /* subtype 0100: Probe request */ +#endif /* CFG_SUPPORT_ADHOC */ + scanProcessBeaconAndProbeResp, /* subtype 0101: Probe response */ + NULL, /* subtype 0110: reserved */ + NULL, /* subtype 0111: reserved */ + scanProcessBeaconAndProbeResp, /* subtype 1000: Beacon */ + NULL, /* subtype 1001: ATIM */ + saaFsmRunEventRxDisassoc, /* subtype 1010: Disassociation */ + authCheckRxAuthFrameTransSeq, /* subtype 1011: Authentication */ + saaFsmRunEventRxDeauth, /* subtype 1100: Deauthentication */ + nicRxProcessActionFrame, /* subtype 1101: Action */ + NULL, /* subtype 1110: reserved */ + NULL /* subtype 1111: reserved */ +}; +#endif + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief Initialize the RFBs +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxInitialize(IN P_ADAPTER_T prAdapter) +{ + P_RX_CTRL_T prRxCtrl; + PUINT_8 pucMemHandle; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; + UINT_32 i; + UINT_16 failCounter = 0; + + 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); + QUEUE_INITIALIZE(&prRxCtrl->rUnInitializedRfbList); + +#if CFG_SUPPORT_MULTITHREAD + QUEUE_INITIALIZE(&prRxCtrl->rRxDataRfbList); +#endif + + pucMemHandle = prRxCtrl->pucRxCached; + for (i = CFG_RX_MAX_PKT_NUM; i != 0; i--) { + prSwRfb = (P_SW_RFB_T) pucMemHandle; + + /* TODO: have an error handling mechanism when failing packet allocate */ + if (nicRxSetupRFB(prAdapter, prSwRfb) != WLAN_STATUS_SUCCESS) + failCounter++; + nicRxReturnRFB(prAdapter, prSwRfb); + + pucMemHandle += ALIGN_4(sizeof(SW_RFB_T)); + } + if (failCounter > 0) + DBGLOG(RX, ERROR, "nicRxSetupRFB allocate (%d) packets failed\n", failCounter); + + ASSERT(prRxCtrl->rFreeSwRfbList.u4NumElem == CFG_RX_MAX_PKT_NUM); + /* Check if the memory allocation consist with this initialization function */ + ASSERT((ULONG) (pucMemHandle - prRxCtrl->pucRxCached) == prRxCtrl->u4RxCachedSize); + + /* 4 <2> Clear all RX counters */ + RX_RESET_ALL_CNTS(prRxCtrl); + +#if CFG_SDIO_RX_AGG + prRxCtrl->pucRxCoalescingBufPtr = prAdapter->pucCoalescingBufCached; + HAL_CFG_MAX_HIF_RX_LEN_NUM(prAdapter, CFG_SDIO_MAX_RX_AGG_NUM); +#else + HAL_CFG_MAX_HIF_RX_LEN_NUM(prAdapter, 1); +#endif + +#if CFG_HIF_STATISTICS + prRxCtrl->u4TotalRxAccessNum = 0; + prRxCtrl->u4TotalRxPacketNum = 0; +#endif + +#if CFG_HIF_RX_STARVATION_WARNING + prRxCtrl->u4QueuedCnt = 0; + prRxCtrl->u4DequeuedCnt = 0; +#endif + +} /* end of nicRxInitialize() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Uninitialize the RFBs +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxUninitialize(IN P_ADAPTER_T prAdapter) +{ + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + nicRxFlush(prAdapter); + + do { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rReceivedRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + if (prSwRfb) { + if (prSwRfb->pvPacket) + kalPacketFree(prAdapter->prGlueInfo, prSwRfb->pvPacket); + prSwRfb->pvPacket = NULL; + prSwRfb->pucRecvBuff = 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; + prSwRfb->pucRecvBuff = NULL; + } else { + break; + } + } while (TRUE); + + do { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rUnInitializedRfbList, 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; + prSwRfb->pucRecvBuff = NULL; + } else { + break; + } + } while (TRUE); + +#if CFG_SUPPORT_MULTITHREAD + do { + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rRxDataRfbList, 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; + prSwRfb->pucRecvBuff = NULL; + } else { + break; + } + } while (TRUE); +#endif + +} /* end of nicRxUninitialize() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Fill RFB +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb specify the RFB to receive rx data +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxFillRFB(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) +{ + P_HIF_RX_HEADER_T prHifRxHdr; + + UINT_32 u4PktLen = 0; + UINT_32 u4MacHeaderLen; + UINT_32 u4HeaderOffset; + + DEBUGFUNC("nicRxFillRFB"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prHifRxHdr = prSwRfb->prHifRxHdr; + ASSERT(prHifRxHdr); + + u4PktLen = prHifRxHdr->u2PacketLen; + + u4HeaderOffset = (UINT_32) (prHifRxHdr->ucHerderLenOffset & HIF_RX_HDR_HEADER_OFFSET_MASK); + u4MacHeaderLen = (UINT_32) (prHifRxHdr->ucHerderLenOffset & HIF_RX_HDR_HEADER_LEN) + >> HIF_RX_HDR_HEADER_LEN_OFFSET; + + /* DBGLOG(RX, TRACE, ("u4HeaderOffset = %d, u4MacHeaderLen = %d\n", */ + /* u4HeaderOffset, u4MacHeaderLen)); */ + + prSwRfb->u2HeaderLen = (UINT_16) u4MacHeaderLen; + prSwRfb->pvHeader = (PUINT_8) prHifRxHdr + HIF_RX_HDR_SIZE + u4HeaderOffset; + prSwRfb->u2PacketLen = (UINT_16) (u4PktLen - (HIF_RX_HDR_SIZE + u4HeaderOffset)); + + /* DBGLOG(RX, TRACE, ("Dump Rx packet, u2PacketLen = %d\n", prSwRfb->u2PacketLen)); */ + /* DBGLOG_MEM8(RX, TRACE, prSwRfb->pvHeader, prSwRfb->u2PacketLen); */ + +#if 0 + if (prHifRxHdr->ucReorder & HIF_RX_HDR_80211_HEADER_FORMAT) { + prSwRfb->u4HifRxHdrFlag |= HIF_RX_HDR_FLAG_802_11_FORMAT; + DBGLOG(RX, TRACE, "HIF_RX_HDR_FLAG_802_11_FORMAT\n"); + } + + if (prHifRxHdr->ucReorder & HIF_RX_HDR_DO_REORDER) { + prSwRfb->u4HifRxHdrFlag |= HIF_RX_HDR_FLAG_DO_REORDERING; + DBGLOG(RX, TRACE, "HIF_RX_HDR_FLAG_DO_REORDERING\n"); + + /* Get Seq. No and TID, Wlan Index info */ + if (prHifRxHdr->u2SeqNoTid & HIF_RX_HDR_BAR_FRAME) { + prSwRfb->u4HifRxHdrFlag |= HIF_RX_HDR_FLAG_BAR_FRAME; + DBGLOG(RX, TRACE, "HIF_RX_HDR_FLAG_BAR_FRAME\n"); + } + + prSwRfb->u2SSN = prHifRxHdr->u2SeqNoTid & HIF_RX_HDR_SEQ_NO_MASK; + prSwRfb->ucTid = (UINT_8) ((prHifRxHdr->u2SeqNoTid & HIF_RX_HDR_TID_MASK) + >> HIF_RX_HDR_TID_OFFSET); + DBGLOG(RX, TRACE, "u2SSN = %d, ucTid = %d\n", prSwRfb->u2SSN, prSwRfb->ucTid); + } + + if (prHifRxHdr->ucReorder & HIF_RX_HDR_WDS) { + prSwRfb->u4HifRxHdrFlag |= HIF_RX_HDR_FLAG_AMP_WDS; + DBGLOG(RX, TRACE, "HIF_RX_HDR_FLAG_AMP_WDS\n"); + } +#endif +} + +#if CFG_TCP_IP_CHKSUM_OFFLOAD || CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 +/*----------------------------------------------------------------------------*/ +/*! +* @brief Fill checksum status in RFB +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* @param u4TcpUdpIpCksStatus specify the Checksum status +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxFillChksumStatus(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb, IN UINT_32 u4TcpUdpIpCksStatus) +{ + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + if (prAdapter->u4CSUMFlags != CSUM_NOT_SUPPORTED) { + if (u4TcpUdpIpCksStatus & RX_CS_TYPE_IPv4) { /* IPv4 packet */ + prSwRfb->aeCSUM[CSUM_TYPE_IPV6] = CSUM_RES_NONE; + if (u4TcpUdpIpCksStatus & RX_CS_STATUS_IP) { /* IP packet csum failed */ + prSwRfb->aeCSUM[CSUM_TYPE_IPV4] = CSUM_RES_FAILED; + } else { + prSwRfb->aeCSUM[CSUM_TYPE_IPV4] = CSUM_RES_SUCCESS; + } + + if (u4TcpUdpIpCksStatus & RX_CS_TYPE_TCP) { /* TCP packet */ + prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_NONE; + if (u4TcpUdpIpCksStatus & RX_CS_STATUS_TCP) { /* TCP packet csum failed */ + prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_FAILED; + } else { + prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_SUCCESS; + } + } else if (u4TcpUdpIpCksStatus & RX_CS_TYPE_UDP) { /* UDP packet */ + prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_NONE; + if (u4TcpUdpIpCksStatus & RX_CS_STATUS_UDP) { /* UDP packet csum failed */ + prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_FAILED; + } else { + prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_SUCCESS; + } + } else { + prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_NONE; + prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_NONE; + } + } else if (u4TcpUdpIpCksStatus & RX_CS_TYPE_IPv6) { /* IPv6 packet */ + prSwRfb->aeCSUM[CSUM_TYPE_IPV4] = CSUM_RES_NONE; + prSwRfb->aeCSUM[CSUM_TYPE_IPV6] = CSUM_RES_SUCCESS; + + if (u4TcpUdpIpCksStatus & RX_CS_TYPE_TCP) { /* TCP packet */ + prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_NONE; + if (u4TcpUdpIpCksStatus & RX_CS_STATUS_TCP) { /* TCP packet csum failed */ + prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_FAILED; + } else { + prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_SUCCESS; + } + } else if (u4TcpUdpIpCksStatus & RX_CS_TYPE_UDP) { /* UDP packet */ + prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_NONE; + if (u4TcpUdpIpCksStatus & RX_CS_STATUS_UDP) { /* UDP packet csum failed */ + prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_FAILED; + } else { + prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_SUCCESS; + } + } else { + prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_NONE; + prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_NONE; + } + } else { + prSwRfb->aeCSUM[CSUM_TYPE_IPV4] = CSUM_RES_NONE; + prSwRfb->aeCSUM[CSUM_TYPE_IPV6] = CSUM_RES_NONE; + } + } + +} +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process packet doesn't need to do buffer reordering +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxProcessPktWithoutReorder(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_RX_CTRL_T prRxCtrl; + P_TX_CTRL_T prTxCtrl; + BOOLEAN fgIsRetained = FALSE; + UINT_32 u4CurrentRxBufferCount; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + BOOLEAN fgIsUninitRfb = FALSE; + + DEBUGFUNC("nicRxProcessPktWithoutReorder"); + /* DBGLOG(RX, TRACE, ("\n")); */ + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + u4CurrentRxBufferCount = prRxCtrl->rFreeSwRfbList.u4NumElem; + /* QM USED = $A, AVAILABLE COUNT = $B, INDICATED TO OS = $C + * TOTAL = $A + $B + $C + * + * Case #1 (Retain) + * ------------------------------------------------------- + * $A + $B < THRESHOLD := $A + $B + $C < THRESHOLD + $C := $TOTAL - THRESHOLD < $C + * => $C used too much, retain + * + * Case #2 (Non-Retain) + * ------------------------------------------------------- + * $A + $B > THRESHOLD := $A + $B + $C > THRESHOLD + $C := $TOTAL - THRESHOLD > $C + * => still available for $C to use + * + */ + fgIsRetained = (((u4CurrentRxBufferCount + + qmGetRxReorderQueuedBufferCount(prAdapter) + + prTxCtrl->i4PendingFwdFrameCount) < CFG_RX_RETAINED_PKT_THRESHOLD) ? TRUE : FALSE); + + /* DBGLOG(RX, INFO, ("fgIsRetained = %d\n", fgIsRetained)); */ + + if (kalProcessRxPacket(prAdapter->prGlueInfo, + prSwRfb->pvPacket, + prSwRfb->pvHeader, + (UINT_32) prSwRfb->u2PacketLen, fgIsRetained, prSwRfb->aeCSUM) != WLAN_STATUS_SUCCESS) { + DBGLOG(RX, ERROR, "kalProcessRxPacket return value != WLAN_STATUS_SUCCESS\n"); + ASSERT(0); + + nicRxReturnRFB(prAdapter, prSwRfb); + return; + } + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prStaRec) { +#if CFG_ENABLE_WIFI_DIRECT + if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX && prAdapter->fgIsP2PRegistered == TRUE) + GLUE_SET_PKT_FLAG_P2P(prSwRfb->pvPacket); +#endif +#if CFG_ENABLE_BT_OVER_WIFI + if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX) + GLUE_SET_PKT_FLAG_PAL(prSwRfb->pvPacket); +#endif + + /* record the count to pass to os */ + STATS_RX_PASS2OS_INC(prStaRec, prSwRfb); + } + prRxCtrl->apvIndPacket[prRxCtrl->ucNumIndPacket] = prSwRfb->pvPacket; + prRxCtrl->ucNumIndPacket++; + wlanPktStatusDebugTraceInfoSeq(prAdapter, prSwRfb->prHifRxHdr->u2SeqNoTid); + + if (fgIsRetained) { + prRxCtrl->apvRetainedPacket[prRxCtrl->ucNumRetainedPacket] = prSwRfb->pvPacket; + prRxCtrl->ucNumRetainedPacket++; + /* TODO : error handling of nicRxSetupRFB */ + if (nicRxSetupRFB(prAdapter, prSwRfb)) + fgIsUninitRfb = TRUE; + nicRxReturnRFBwithUninit(prAdapter, prSwRfb, fgIsUninitRfb); + } else { + prSwRfb->pvPacket = NULL; + prSwRfb->pucRecvBuff = NULL; + nicRxReturnRFBwithUninit(prAdapter, prSwRfb, fgIsUninitRfb); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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; + prSwRfb->pucRecvBuff = 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 */ +#if (CFG_SUPPORT_TDLS == 1) + TdlsexForwardFrameTag((struct sk_buff *)prMsduInfo->prPacket, TRUE); +#endif + nicTxFreeMsduInfoPacket(prAdapter, prRetMsduInfoList); + nicTxReturnMsduInfo(prAdapter, prRetMsduInfoList); + } +#if (CFG_SUPPORT_TDLS == 1) + else + TdlsexForwardFrameTag((struct sk_buff *)prMsduInfo->prPacket, FALSE); +#endif + /* indicate service thread for sending */ + if (prTxCtrl->i4PendingFwdFrameCount > 0) + kalSetEvent(prAdapter->prGlueInfo); + } else { /* no TX resource */ +#if (CFG_SUPPORT_TDLS == 1) + struct sk_buff *skb = (struct sk_buff *)prSwRfb->pvPacket; + + skb->data = prSwRfb->pvHeader; + TdlsexForwardFrameTag(skb, TRUE); +#endif + nicRxReturnRFB(prAdapter, prSwRfb); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process broadcast data packet for both host and forwarding +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxProcessGOBroadcastPkt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_SW_RFB_T prSwRfbDuplicated; + P_TX_CTRL_T prTxCtrl; + P_RX_CTRL_T prRxCtrl; + P_HIF_RX_HEADER_T prHifRxHdr; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxProcessGOBroadcastPkt"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prTxCtrl = &prAdapter->rTxCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + + prHifRxHdr = prSwRfb->prHifRxHdr; + ASSERT(prHifRxHdr); + + ASSERT(CFG_NUM_OF_QM_RX_PKT_NUM >= 16); + + if (prRxCtrl->rFreeSwRfbList.u4NumElem + >= (CFG_RX_MAX_PKT_NUM - (CFG_NUM_OF_QM_RX_PKT_NUM - 16 /* Reserved for others */))) { + + /* 1. Duplicate SW_RFB_T */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfbDuplicated, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + if (prSwRfbDuplicated) { + kalMemCopy(prSwRfbDuplicated->pucRecvBuff, + prSwRfb->pucRecvBuff, ALIGN_4(prHifRxHdr->u2PacketLen + HIF_RX_HW_APPENDED_LEN)); + + prSwRfbDuplicated->ucPacketType = HIF_RX_PKT_TYPE_DATA; + prSwRfbDuplicated->ucStaRecIdx = (UINT_8) (prHifRxHdr->ucStaRecIdx); + nicRxFillRFB(prAdapter, prSwRfbDuplicated); + + /* 2. Modify eDst */ + prSwRfbDuplicated->eDst = RX_PKT_DESTINATION_FORWARD; + + /* 4. Forward */ + nicRxProcessForwardPkt(prAdapter, prSwRfbDuplicated); + } + } else { + DBGLOG(RX, WARN, "Stop to forward BMC packet due to less free Sw Rfb %u\n", + prRxCtrl->rFreeSwRfbList.u4NumElem); + } + + /* 3. Indicate to host */ + prSwRfb->eDst = RX_PKT_DESTINATION_HOST; + nicRxProcessPktWithoutReorder(prAdapter, prSwRfb); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process HIF data packet +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxProcessDataPacket(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) +{ + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prRetSwRfb, prNextSwRfb; + P_HIF_RX_HEADER_T prHifRxHdr; + P_STA_RECORD_T prStaRec; + UINT_16 u2Etype = 0; + BOOLEAN fIsDummy = FALSE; + BOOLEAN fgIsSkipClass3Chk = FALSE; + + DEBUGFUNC("nicRxProcessDataPacket"); + /* DBGLOG(RX, TRACE, ("\n")); */ + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prHifRxHdr = prSwRfb->prHifRxHdr; + prRxCtrl = &prAdapter->rRxCtrl; + + fIsDummy = (prHifRxHdr->u2PacketLen >= 12) ? FALSE : TRUE; + + nicRxFillRFB(prAdapter, prSwRfb); + + if (prSwRfb->u2PacketLen > 14) { + PUINT_8 pc = (PUINT_8)prSwRfb->pvHeader; + + u2Etype = (pc[ETH_TYPE_LEN_OFFSET] << 8) | (pc[ETH_TYPE_LEN_OFFSET + 1]); + } + +#if CFG_TCP_IP_CHKSUM_OFFLOAD || CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 + { + UINT_32 u4TcpUdpIpCksStatus; + + u4TcpUdpIpCksStatus = *((PUINT_32) ((ULONG) prHifRxHdr + (UINT_32) (ALIGN_4(prHifRxHdr->u2PacketLen)))); + nicRxFillChksumStatus(prAdapter, prSwRfb, u4TcpUdpIpCksStatus); + + } +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + prStaRec = cnmGetStaRecByIndex(prAdapter, prHifRxHdr->ucStaRecIdx); + + if ((u2Etype == ETH_P_1X) || (u2Etype == ETH_P_PRE_1X)) { + if ((prStaRec != NULL) && (prStaRec->eAuthAssocState == SAA_STATE_WAIT_ASSOC2)) { + DBGLOG(RX, INFO, "skip class 3 error:Type=%d,Len=%d\n", u2Etype, prSwRfb->u2PacketLen); + fgIsSkipClass3Chk = TRUE; + } + } + + if ((fgIsSkipClass3Chk == TRUE) || + (secCheckClassError(prAdapter, prSwRfb, prStaRec) == TRUE && prAdapter->fgTestMode == FALSE)) { +#if CFG_HIF_RX_STARVATION_WARNING + prRxCtrl->u4QueuedCnt++; +#endif + prRetSwRfb = qmHandleRxPackets(prAdapter, prSwRfb); + if (prRetSwRfb != NULL) { + do { + /* save next first */ + prNextSwRfb = (P_SW_RFB_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prRetSwRfb); + if (fIsDummy == TRUE) { + nicRxReturnRFB(prAdapter, prRetSwRfb); + RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); + DBGLOG(RX, WARN, "Drop Dummy Packets"); + + } else { + switch (prRetSwRfb->eDst) { + case RX_PKT_DESTINATION_HOST: +#if ARP_MONITER_ENABLE + if (IS_STA_IN_AIS(prStaRec)) { + qmHandleRxArpPackets(prAdapter, prRetSwRfb); + qmHandleRxDhcpPackets(prAdapter, prRetSwRfb); + } +#endif + secHandleRxEapolPacket(prAdapter, prRetSwRfb, prStaRec); + 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); + } +} + +#if CFG_SUPPORT_GSCN +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process GSCAN event packet +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 nicRxProcessGSCNEvent(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) +{ + P_SCAN_INFO_T prScanInfo; + P_WIFI_EVENT_T prEvent; + P_GLUE_INFO_T prGlueInfo; + struct wiphy *wiphy; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prEvent = (P_WIFI_EVENT_T) prSwRfb->pucRecvBuff; + prGlueInfo = prAdapter->prGlueInfo; + /* Push the data to the skb */ + wiphy = priv_to_wiphy(prGlueInfo); + + /* Event Handling */ + switch (prEvent->ucEID) { + case EVENT_ID_GSCAN_SCAN_AVAILABLE: + { + P_EVENT_GSCAN_SCAN_AVAILABLE_T prEventGscnAvailable; + + DBGLOG(SCN, INFO, "EVENT_ID_GSCAN_SCAN_AVAILABLE\n"); + prEventGscnAvailable = (P_EVENT_GSCAN_SCAN_AVAILABLE_T) (prEvent->aucBuffer); + mtk_cfg80211_vendor_event_scan_results_available(wiphy, + prGlueInfo->prDevHandler->ieee80211_ptr, prEventGscnAvailable->u2Num); + } + break; + + case EVENT_ID_GSCAN_RESULT: + { + P_EVENT_GSCAN_RESULT_T prEventBuffer; + + DBGLOG(SCN, INFO, "EVENT_ID_GSCAN_RESULT 2\n"); + prEventBuffer = (P_EVENT_GSCAN_RESULT_T) (prEvent->aucBuffer); + /* scnFsmGSCNResults(prAdapter, prEventBuffer); */ + } + break; + + case EVENT_ID_GSCAN_CAPABILITY: + { + P_EVENT_GSCAN_CAPABILITY_T prEventGscnCapbiblity; + + DBGLOG(SCN, INFO, "EVENT_ID_GSCAN_CAPABILITY\n"); + prEventGscnCapbiblity = (P_EVENT_GSCAN_CAPABILITY_T) (prEvent->aucBuffer); + mtk_cfg80211_vendor_get_gscan_capabilities(wiphy, prGlueInfo->prDevHandler->ieee80211_ptr, + prEventGscnCapbiblity, sizeof(EVENT_GSCAN_CAPABILITY_T)); + } + break; + + case EVENT_ID_GSCAN_SCAN_COMPLETE: + { + P_EVENT_GSCAN_SCAN_COMPLETE_T prEventGscnScnDone; + + DBGLOG(SCN, INFO, "EVENT_ID_GSCAN_SCAN_COMPLETE\n"); + prEventGscnScnDone = (P_EVENT_GSCAN_SCAN_COMPLETE_T) (prEvent->aucBuffer); + mtk_cfg80211_vendor_event_complete_scan(wiphy, + prGlueInfo->prDevHandler->ieee80211_ptr, prEventGscnScnDone->ucScanState); + } + break; + + case EVENT_ID_GSCAN_FULL_RESULT: + { + UINT_32 ie_len = 0; + P_EVENT_GSCAN_FULL_RESULT_T prEventGscnFullResult; + /* P_PARAM_WIFI_GSCAN_FULL_RESULT prParamGscnFullResult; */ + + DBGLOG(SCN, TRACE, "EVENT_ID_GSCAN_FULL_RESULT\n"); + + prEventGscnFullResult = (P_EVENT_GSCAN_FULL_RESULT_T)(prEvent->aucBuffer); + ie_len = min(prEventGscnFullResult->u4IeLength, (UINT_32)CFG_IE_BUFFER_SIZE); + + DBGLOG(SCN, LOUD, "arSsid=%s, bssid="MACSTR", u4Channel=%d u4IeLength=%d\n", + prEventGscnFullResult->rResult.arSsid, + MAC2STR(prEventGscnFullResult->rResult.arMacAddr), + prEventGscnFullResult->rResult.u4Channel, prEventGscnFullResult->u4IeLength); + + kalMemZero(prScanInfo->prGscnFullResult, + offsetof(PARAM_WIFI_GSCAN_FULL_RESULT, ie_data) + CFG_IE_BUFFER_SIZE); + /* WIFI_GSCAN_RESULT_T similar to PARAM_WIFI_GSCAN_RESULT*/ + kalMemCopy(&prScanInfo->prGscnFullResult->fixed, &prEventGscnFullResult->rResult, + sizeof(WIFI_GSCAN_RESULT_T)); + prScanInfo->prGscnFullResult->u4BucketMask = prEventGscnFullResult->u4BucketMask; + prScanInfo->prGscnFullResult->ie_length = prEventGscnFullResult->u4IeLength; + kalMemCopy(prScanInfo->prGscnFullResult->ie_data, prEventGscnFullResult->ucIeData, ie_len); + + mtk_cfg80211_vendor_event_full_scan_results(wiphy, + prGlueInfo->prDevHandler->ieee80211_ptr, + prScanInfo->prGscnFullResult, + offsetof(PARAM_WIFI_GSCAN_FULL_RESULT, ie_data) + ie_len); + } + break; + + case EVENT_ID_GSCAN_SIGNIFICANT_CHANGE: + { + P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T prEventGscnSignificantChange; + + prEventGscnSignificantChange = (P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T) (prEvent->aucBuffer); + memcpy(prEventGscnSignificantChange, (P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T) (prEvent->aucBuffer), + sizeof(EVENT_GSCAN_SIGNIFICANT_CHANGE_T)); + } + break; + + case EVENT_ID_GSCAN_GEOFENCE_FOUND: + { + P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T prEventGscnGeofenceFound; + + prEventGscnGeofenceFound = (P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T) (prEvent->aucBuffer); + memcpy(prEventGscnGeofenceFound, (P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T) (prEvent->aucBuffer), + sizeof(EVENT_GSCAN_SIGNIFICANT_CHANGE_T)); + } + break; + + default: + DBGLOG(SCN, ERROR, "not a GSCN event\n"); + break; + } + + return 0; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @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; + struct wiphy *wiphy; + + DEBUGFUNC("nicRxProcessEventPacket"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prEvent = (P_WIFI_EVENT_T) prSwRfb->pucRecvBuff; + prGlueInfo = prAdapter->prGlueInfo; + wiphy = priv_to_wiphy(prGlueInfo); + + DBGLOG(RX, EVENT, "prEvent->ucEID = 0x%02x\n", prEvent->ucEID); + /* Event Handling */ + switch (prEvent->ucEID) { + case EVENT_ID_CMD_RESULT: + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + P_EVENT_CMD_RESULT prCmdResult; + + prCmdResult = (P_EVENT_CMD_RESULT) ((PUINT_8) prEvent + EVENT_HDR_SIZE); + + prCmdInfo->u4FwResponseTime = kalGetTimeTick(); + wlanDebugCommandRecodTime(prCmdInfo); + + /* 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); + } else + DBGLOG(RX, WARN, "prCmdInfo is null ,ucEID = 0x%02x ucSeqNum = 0x%02x\n" + , prEvent->ucEID, prEvent->ucSeqNum); + + break; + +#if 0 + case EVENT_ID_CONNECTION_STATUS: + /* OBSELETE */ + { + P_EVENT_CONNECTION_STATUS prConnectionStatus; + + prConnectionStatus = (P_EVENT_CONNECTION_STATUS) (prEvent->aucBuffer); + + DbgPrint("RX EVENT: EVENT_ID_CONNECTION_STATUS = %d\n", prConnectionStatus->ucMediaStatus); + if (prConnectionStatus->ucMediaStatus == PARAM_MEDIA_STATE_DISCONNECTED) { + /* disconnected */ + if (kalGetMediaStateIndicated(prGlueInfo) != PARAM_MEDIA_STATE_DISCONNECTED) { + + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + + prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); + } + } else if (prConnectionStatus->ucMediaStatus == PARAM_MEDIA_STATE_CONNECTED) { + /* connected */ + prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); + + /* fill information for association result */ + prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen = prConnectionStatus->ucSsidLen; + kalMemCopy(prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, + prConnectionStatus->aucSsid, prConnectionStatus->ucSsidLen); + + kalMemCopy(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, + prConnectionStatus->aucBssid, MAC_ADDR_LEN); + + /* @FIXME */ + prAdapter->rWlanInfo.rCurrBssId.u4Privacy = prConnectionStatus->ucEncryptStatus; + prAdapter->rWlanInfo.rCurrBssId.rRssi = 0; /* @FIXME */ + /* @FIXME */ + prAdapter->rWlanInfo.rCurrBssId.eNetworkTypeInUse = PARAM_NETWORK_TYPE_AUTOMODE; + prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4BeaconPeriod + = prConnectionStatus->u2BeaconPeriod; + prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4ATIMWindow + = prConnectionStatus->u2ATIMWindow; + prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4DSConfig + = prConnectionStatus->u4FreqInKHz; + prAdapter->rWlanInfo.ucNetworkType = prConnectionStatus->ucNetworkType; + + switch (prConnectionStatus->ucInfraMode) { + case 0: + prAdapter->rWlanInfo.rCurrBssId.eOpMode = NET_TYPE_IBSS; + break; + case 1: + prAdapter->rWlanInfo.rCurrBssId.eOpMode = NET_TYPE_INFRA; + break; + case 2: + default: + prAdapter->rWlanInfo.rCurrBssId.eOpMode = NET_TYPE_AUTO_SWITCH; + break; + } + /* always indicate to OS according to MSDN (re-association/roaming) */ + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_CONNECT, NULL, 0); + } + } + break; + + case EVENT_ID_SCAN_RESULT: + /* OBSELETE */ + break; +#endif + + case EVENT_ID_RX_ADDBA: + /* The FW indicates that an RX BA agreement will be established */ + qmHandleEventRxAddBa(prAdapter, prEvent); + break; + + case EVENT_ID_RX_DELBA: + /* The FW indicates that an RX BA agreement has been deleted */ + qmHandleEventRxDelBa(prAdapter, prEvent); + break; + +#if CFG_RX_BA_REORDERING_ENHANCEMENT + case EVENT_ID_BA_FW_DROP_SN: + qmHandleEventDropByFW(prAdapter, prEvent); + break; +#endif + + 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) { + prCmdInfo->u4FwResponseTime = kalGetTimeTick(); + wlanDebugCommandRecodTime(prCmdInfo); + if (prCmdInfo->pfCmdDoneHandler) + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); + else if (prCmdInfo->fgIsOid) + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } +#ifndef LINUX + if (prAdapter->rWlanInfo.eRssiTriggerType == ENUM_RSSI_TRIGGER_GREATER && + prAdapter->rWlanInfo.rRssiTriggerValue >= (PARAM_RSSI) (prAdapter->rLinkQuality.cRssi)) { + prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_TRIGGERED; + + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID)&(prAdapter->rWlanInfo.rRssiTriggerValue), + sizeof(PARAM_RSSI)); + } else if (prAdapter->rWlanInfo.eRssiTriggerType == ENUM_RSSI_TRIGGER_LESS + && prAdapter->rWlanInfo.rRssiTriggerValue <= (PARAM_RSSI) (prAdapter->rLinkQuality.cRssi)) { + prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_TRIGGERED; + + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID)&(prAdapter->rWlanInfo.rRssiTriggerValue), + sizeof(PARAM_RSSI)); + } +#endif + + break; + + case EVENT_ID_MIC_ERR_INFO: + { + P_EVENT_MIC_ERR_INFO prMicError; + /* P_PARAM_AUTH_EVENT_T prAuthEvent; */ + P_STA_RECORD_T prStaRec; + + DBGLOG(RSN, EVENT, "EVENT_ID_MIC_ERR_INFO\n"); + + prMicError = (P_EVENT_MIC_ERR_INFO) (prEvent->aucBuffer); + prStaRec = cnmGetStaRecByAddress(prAdapter, + (UINT_8) NETWORK_TYPE_AIS_INDEX, + prAdapter->rWlanInfo.rCurrBssId.arMacAddress); + ASSERT(prStaRec); + + if (prStaRec) + rsnTkipHandleMICFailure(prAdapter, prStaRec, (BOOLEAN) prMicError->u4Flags); + else + DBGLOG(RSN, WARN, "No STA rec!!\n"); +#if 0 + prAuthEvent = (P_PARAM_AUTH_EVENT_T) prAdapter->aucIndicationEventBuffer; + + /* Status type: Authentication Event */ + prAuthEvent->rStatus.eStatusType = ENUM_STATUS_TYPE_AUTHENTICATION; + + /* Authentication request */ + prAuthEvent->arRequest[0].u4Length = sizeof(PARAM_AUTH_REQUEST_T); + kalMemCopy((PVOID) prAuthEvent->arRequest[0].arBssid, + (PVOID) prAdapter->rWlanInfo.rCurrBssId.arMacAddress, + /* whsu:Todo? */PARAM_MAC_ADDR_LEN); + + if (prMicError->u4Flags != 0) + prAuthEvent->arRequest[0].u4Flags = PARAM_AUTH_REQUEST_GROUP_ERROR; + else + prAuthEvent->arRequest[0].u4Flags = PARAM_AUTH_REQUEST_PAIRWISE_ERROR; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID) prAuthEvent, + sizeof(PARAM_STATUS_INDICATION_T) + sizeof(PARAM_AUTH_REQUEST_T)); +#endif + } + break; + + case EVENT_ID_ASSOC_INFO: + { + P_EVENT_ASSOC_INFO prAssocInfo; + + prAssocInfo = (P_EVENT_ASSOC_INFO) (prEvent->aucBuffer); + + kalHandleAssocInfo(prAdapter->prGlueInfo, prAssocInfo); + } + break; +#if (CFG_REFACTORY_PMKSA == 0) + 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; +#endif + +#if 0 + case EVENT_ID_ACTIVATE_STA_REC_T: + { + P_EVENT_ACTIVATE_STA_REC_T prActivateStaRec; + + prActivateStaRec = (P_EVENT_ACTIVATE_STA_REC_T) (prEvent->aucBuffer); + + DbgPrint("RX EVENT: EVENT_ID_ACTIVATE_STA_REC_T Index:%d, MAC:[%pM]\n", + prActivateStaRec->ucStaRecIdx, prActivateStaRec->aucMacAddr); + + qmActivateStaRec(prAdapter, + (UINT_32) prActivateStaRec->ucStaRecIdx, + ((prActivateStaRec->fgIsQoS) ? TRUE : FALSE), + prActivateStaRec->ucNetworkTypeIndex, + ((prActivateStaRec->fgIsAP) ? TRUE : FALSE), prActivateStaRec->aucMacAddr); + + } + break; + + case EVENT_ID_DEACTIVATE_STA_REC_T: + { + P_EVENT_DEACTIVATE_STA_REC_T prDeactivateStaRec; + + prDeactivateStaRec = (P_EVENT_DEACTIVATE_STA_REC_T) (prEvent->aucBuffer); + + DbgPrint("RX EVENT: EVENT_ID_DEACTIVATE_STA_REC_T Index:%d, MAC:[%pM]\n", + prDeactivateStaRec->ucStaRecIdx, prActivateStaRec->aucMacAddr); + + qmDeactivateStaRec(prAdapter, prDeactivateStaRec->ucStaRecIdx); + } + break; +#endif + + case EVENT_ID_SCAN_DONE: + scnEventScanDone(prAdapter, (P_EVENT_SCAN_DONE) (prEvent->aucBuffer)); + break; + + case EVENT_ID_TX_DONE_STATUS: + { + secHandleTxStatus(prAdapter, prEvent->aucBuffer); + } + break; + + case EVENT_ID_TX_DONE: + { + P_EVENT_TX_DONE_T prTxDone; + + prTxDone = (P_EVENT_TX_DONE_T) (prEvent->aucBuffer); + + if (prTxDone->ucStatus) { + DBGLOG(RX, INFO, "EVENT_ID_TX_DONE PacketSeq:%u ucStatus: %u SN: %u\n", + prTxDone->ucPacketSeq, prTxDone->ucStatus, prTxDone->u2SequenceNumber); + if (prTxDone->ucStatus == TX_RESULT_FW_FLUSH) + prAdapter->ucFlushCount++; + } else + prAdapter->ucFlushCount = 0; + + /*when Fw flushed continusous packages, driver do whole chip reset !*/ + if (prAdapter->ucFlushCount >= RX_FW_FLUSH_PKT_THRESHOLD) { + DBGLOG(RX, ERROR, "FW flushed continusous packages :%d\n", prAdapter->ucFlushCount); + prAdapter->ucFlushCount = 0; +#if 0 + kalSendAeeWarning("[Fatal error! FW Flushed PKT too much!]", __func__); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_CHIP_RESET); +#endif + } + + /* call related TX Done Handler */ + prMsduInfo = nicGetPendingTxMsduInfo(prAdapter, prTxDone->ucPacketSeq); + +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT + DBGLOG(RX, TRACE, "EVENT_ID_TX_DONE u4TimeStamp = %x u2AirDelay = %x\n", + prTxDone->au4Reserved1, prTxDone->au4Reserved2); + + wnmReportTimingMeas(prAdapter, prMsduInfo->ucStaRecIndex, + prTxDone->au4Reserved1, prTxDone->au4Reserved1 + prTxDone->au4Reserved2); +#endif + + if (prMsduInfo) { + prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, + (ENUM_TX_RESULT_CODE_T) (prTxDone->ucStatus)); + + cnmMgtPktFree(prAdapter, prMsduInfo); + } + } + break; + case EVENT_ID_SLEEPY_NOTIFY: + { + P_EVENT_SLEEPY_NOTIFY prEventSleepyNotify; + + prEventSleepyNotify = (P_EVENT_SLEEPY_NOTIFY) (prEvent->aucBuffer); + + /* DBGLOG(RX, INFO, ("ucSleepyState = %d\n", prEventSleepyNotify->ucSleepyState)); */ + + prAdapter->fgWiFiInSleepyState = (BOOLEAN) (prEventSleepyNotify->ucSleepyState); + } + break; + case EVENT_ID_BT_OVER_WIFI: +#if CFG_ENABLE_BT_OVER_WIFI + { + UINT_8 aucTmp[sizeof(AMPC_EVENT) + sizeof(BOW_LINK_DISCONNECTED)]; + P_EVENT_BT_OVER_WIFI prEventBtOverWifi; + P_AMPC_EVENT prBowEvent; + P_BOW_LINK_CONNECTED prBowLinkConnected; + P_BOW_LINK_DISCONNECTED prBowLinkDisconnected; + + prEventBtOverWifi = (P_EVENT_BT_OVER_WIFI) (prEvent->aucBuffer); + + /* construct event header */ + prBowEvent = (P_AMPC_EVENT) aucTmp; + + if (prEventBtOverWifi->ucLinkStatus == 0) { + /* Connection */ + prBowEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_CONNECTED; + prBowEvent->rHeader.ucSeqNumber = 0; + prBowEvent->rHeader.u2PayloadLength = sizeof(BOW_LINK_CONNECTED); + + /* fill event body */ + prBowLinkConnected = (P_BOW_LINK_CONNECTED) (prBowEvent->aucPayload); + prBowLinkConnected->rChannel.ucChannelNum = prEventBtOverWifi->ucSelectedChannel; + kalMemZero(prBowLinkConnected->aucPeerAddress, MAC_ADDR_LEN); /* @FIXME */ + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prBowEvent); + } else { + /* Disconnection */ + prBowEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_DISCONNECTED; + prBowEvent->rHeader.ucSeqNumber = 0; + prBowEvent->rHeader.u2PayloadLength = sizeof(BOW_LINK_DISCONNECTED); + + /* fill event body */ + prBowLinkDisconnected = (P_BOW_LINK_DISCONNECTED) (prBowEvent->aucPayload); + prBowLinkDisconnected->ucReason = 0; /* @FIXME */ + kalMemZero(prBowLinkDisconnected->aucPeerAddress, MAC_ADDR_LEN); /* @FIXME */ + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prBowEvent); + } + } + break; +#endif + case EVENT_ID_STATISTICS: + /* buffer statistics for further query */ + prAdapter->fgIsStatValid = TRUE; + prAdapter->rStatUpdateTime = kalGetTimeTick(); + kalMemCopy(&prAdapter->rStatStruct, prEvent->aucBuffer, sizeof(EVENT_STATISTICS)); + + /* command response handling */ + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + prCmdInfo->u4FwResponseTime = kalGetTimeTick(); + wlanDebugCommandRecodTime(prCmdInfo); + if (prCmdInfo->pfCmdDoneHandler) + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); + else if (prCmdInfo->fgIsOid) + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + + break; + + case EVENT_ID_CH_PRIVILEGE: + cnmChMngrHandleChEvent(prAdapter, prEvent); + break; + + case EVENT_ID_BSS_ABSENCE_PRESENCE: + qmHandleEventBssAbsencePresence(prAdapter, prEvent); + break; + + case EVENT_ID_STA_CHANGE_PS_MODE: + qmHandleEventStaChangePsMode(prAdapter, prEvent); + break; +#if CFG_ENABLE_WIFI_DIRECT + case EVENT_ID_STA_UPDATE_FREE_QUOTA: + qmHandleEventStaUpdateFreeQuota(prAdapter, prEvent); + break; +#endif + case EVENT_ID_BSS_BEACON_TIMEOUT: + if (prAdapter->fgDisBcnLostDetection == FALSE) { + P_EVENT_BSS_BEACON_TIMEOUT_T prEventBssBeaconTimeout; + + prEventBssBeaconTimeout = (P_EVENT_BSS_BEACON_TIMEOUT_T) (prEvent->aucBuffer); + + DBGLOG(RX, INFO, "Beacon Timeout Reason = %u, update bad RSSI=-127 to upper layer\n", + prEventBssBeaconTimeout->ucReason); + + if (prEventBssBeaconTimeout->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { + /* Request stats report before beacon timeout */ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + if (prBssInfo) { + prStaRec = cnmGetStaRecByAddress(prAdapter, + NETWORK_TYPE_AIS_INDEX, + prBssInfo->aucBSSID); + if (prStaRec) + STATS_ENV_REPORT_DETECT(prAdapter, prStaRec->ucIndex); + } + + mtk_cfg80211_vendor_event_rssi_beyond_range(wiphy, + prAdapter->prGlueInfo->prDevHandler->ieee80211_ptr, + (INT_32)-127); + + aisBssBeaconTimeout(prAdapter); + aisRecordBeaconTimeout(prAdapter, prBssInfo); + } +#if CFG_ENABLE_WIFI_DIRECT + else if ((prAdapter->fgIsP2PRegistered) && + (prEventBssBeaconTimeout->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX)) + + p2pFsmRunEventBeaconTimeout(prAdapter); +#endif + else { + DBGLOG(RX, ERROR, "EVENT_ID_BSS_BEACON_TIMEOUT: (ucNetTypeIdx = %d)\n", + prEventBssBeaconTimeout->ucNetTypeIndex); + } + } + + break; + case EVENT_ID_UPDATE_NOA_PARAMS: +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { + P_EVENT_UPDATE_NOA_PARAMS_T prEventUpdateNoaParam; + + prEventUpdateNoaParam = (P_EVENT_UPDATE_NOA_PARAMS_T) (prEvent->aucBuffer); + + if (prEventUpdateNoaParam->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + p2pProcessEvent_UpdateNOAParam(prAdapter, + prEventUpdateNoaParam->ucNetTypeIndex, + prEventUpdateNoaParam); + } else { + ASSERT(0); + } + } +#else + ASSERT(0); +#endif + break; + + case EVENT_ID_STA_AGING_TIMEOUT: +#if CFG_ENABLE_WIFI_DIRECT + { + if (prAdapter->fgDisStaAgingTimeoutDetection == FALSE) { + P_EVENT_STA_AGING_TIMEOUT_T prEventStaAgingTimeout; + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; + + prEventStaAgingTimeout = (P_EVENT_STA_AGING_TIMEOUT_T) (prEvent->aucBuffer); + prStaRec = cnmGetStaRecByIndex(prAdapter, prEventStaAgingTimeout->ucStaRecIdx); + if (prStaRec == NULL) + break; + + DBGLOG(RX, INFO, "EVENT_ID_STA_AGING_TIMEOUT %u %pM\n", + prEventStaAgingTimeout->ucStaRecIdx, + prStaRec->aucMacAddr); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + bssRemoveStaRecFromClientList(prAdapter, prBssInfo, prStaRec); + + /* Call False Auth */ + if (prAdapter->fgIsP2PRegistered) + p2pFuncDisconnect(prAdapter, prStaRec, FALSE, REASON_CODE_DISASSOC_INACTIVITY); + + } + /* gDisStaAgingTimeoutDetection */ + } +#endif + break; + + case EVENT_ID_AP_OBSS_STATUS: +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) + rlmHandleObssStatusEventPkt(prAdapter, (P_EVENT_AP_OBSS_STATUS_T) prEvent->aucBuffer); +#endif + break; + + case EVENT_ID_ROAMING_STATUS: +#if CFG_SUPPORT_ROAMING + { + P_ROAMING_PARAM_T prParam; + + prParam = (P_ROAMING_PARAM_T) (prEvent->aucBuffer); + roamingFsmProcessEvent(prAdapter, prParam); + } +#endif /* CFG_SUPPORT_ROAMING */ + break; + case EVENT_ID_SEND_DEAUTH: + { + P_WLAN_MAC_HEADER_T prWlanMacHeader; + P_STA_RECORD_T prStaRec; + + prWlanMacHeader = (P_WLAN_MAC_HEADER_T) &prEvent->aucBuffer[0]; + DBGLOG(RSN, INFO, "nicRx: aucAddr1: %pM, nicRx: aucAddr2: %pM\n", + prWlanMacHeader->aucAddr1, prWlanMacHeader->aucAddr2); + prStaRec = cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_AIS_INDEX, prWlanMacHeader->aucAddr2); + if (prStaRec != NULL && prStaRec->ucStaState == STA_STATE_3) { + DBGLOG(RSN, WARN, "Ignore Deauth for Rx Class 3 error!\n"); + } else { + /* receive packets without StaRec */ + prSwRfb->pvHeader = (P_WLAN_MAC_HEADER_T) &prEvent->aucBuffer[0]; + if (authSendDeauthFrame(prAdapter, + NULL, + prSwRfb, + REASON_CODE_CLASS_3_ERR, + (PFN_TX_DONE_HANDLER) NULL) == WLAN_STATUS_SUCCESS) + DBGLOG(RSN, INFO, "Send Deauth for Rx Class3 Error\n"); + else + DBGLOG(RSN, WARN, "failed to send deauth for Rx class3 error\n"); + } + } + break; + +#if CFG_SUPPORT_RDD_TEST_MODE + case EVENT_ID_UPDATE_RDD_STATUS: + { + P_EVENT_RDD_STATUS_T prEventRddStatus; + + prEventRddStatus = (P_EVENT_RDD_STATUS_T) (prEvent->aucBuffer); + + prAdapter->ucRddStatus = prEventRddStatus->ucRddStatus; + } + + break; +#endif + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS + case EVENT_ID_UPDATE_BWCS_STATUS: + { + P_PTA_IPC_T prEventBwcsStatus; + + prEventBwcsStatus = (P_PTA_IPC_T) (prEvent->aucBuffer); + +#if CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(RSN, INFO, + "BCM BWCS Event: %02x%02x%02x%02x\n", + prEventBwcsStatus->u.aucBTPParams[0], prEventBwcsStatus->u.aucBTPParams[1], + prEventBwcsStatus->u.aucBTPParams[2], prEventBwcsStatus->u.aucBTPParams[3]); + + DBGLOG(RSN, INFO, + "BCM BWCS Event: BTPParams[0]:%02x, BTPParams[1]:%02x, BTPParams[2]:%02x, BTPParams[3]:%02x\n", + prEventBwcsStatus->u.aucBTPParams[0], prEventBwcsStatus->u.aucBTPParams[1], + prEventBwcsStatus->u.aucBTPParams[2], prEventBwcsStatus->u.aucBTPParams[3]); +#endif + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_BWCS_UPDATE, + (PVOID) prEventBwcsStatus, sizeof(PTA_IPC_T)); + } + + break; + + case EVENT_ID_UPDATE_BCM_DEBUG: + { + P_PTA_IPC_T prEventBwcsStatus; + + prEventBwcsStatus = (P_PTA_IPC_T) (prEvent->aucBuffer); + +#if CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(RSN, INFO, + "BCM FW status: %02x%02x%02x%02x\n", + prEventBwcsStatus->u.aucBTPParams[0], prEventBwcsStatus->u.aucBTPParams[1], + prEventBwcsStatus->u.aucBTPParams[2], prEventBwcsStatus->u.aucBTPParams[3]); + + DBGLOG(RSN, INFO, + "BCM FW status: BTPParams[0]:%02x, BTPParams[1]:%02x, BTPParams[2]:%02x, BTPParams[3]:%02x\n", + prEventBwcsStatus->u.aucBTPParams[0], prEventBwcsStatus->u.aucBTPParams[1], + prEventBwcsStatus->u.aucBTPParams[2], prEventBwcsStatus->u.aucBTPParams[3]; +#endif + } + + break; +#endif + + case EVENT_ID_DEBUG_CODE: /* only for debug */ + { + UINT_32 u4CodeId; + + DBGLOG(RSN, INFO, "[wlan-fw] function sequence: "); + for (u4CodeId = 0; u4CodeId < 1000; u4CodeId++) + DBGLOG(RSN, INFO, "%d ", prEvent->aucBuffer[u4CodeId]); + DBGLOG(RSN, INFO, "\n\n"); + } + break; + + case EVENT_ID_RFTEST_READY: + + /* command response handling */ + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + prCmdInfo->u4FwResponseTime = kalGetTimeTick(); + wlanDebugCommandRecodTime(prCmdInfo); + 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; + +#if CFG_SUPPORT_GSCN + case EVENT_ID_GSCAN_SCAN_AVAILABLE: + case EVENT_ID_GSCAN_CAPABILITY: + case EVENT_ID_GSCAN_SCAN_COMPLETE: + case EVENT_ID_GSCAN_FULL_RESULT: + case EVENT_ID_GSCAN_SIGNIFICANT_CHANGE: + case EVENT_ID_GSCAN_GEOFENCE_FOUND: + case EVENT_ID_GSCAN_RESULT: + nicRxProcessGSCNEvent(prAdapter, prSwRfb); + break; +#endif + + case EVENT_ID_NLO_DONE: +#if CFG_SUPPORT_SCN_PSCN + prAdapter->rWifiVar.rScanInfo.fgPscnOngoing = FALSE; +#endif + DBGLOG(INIT, INFO, "EVENT_ID_NLO_DONE\n"); + scnEventNloDone(prAdapter, (P_EVENT_NLO_DONE_T) (prEvent->aucBuffer)); + + break; + case EVENT_ID_RSP_CHNL_UTILIZATION: + cnmHandleChannelUtilization(prAdapter, (struct EVENT_RSP_CHNL_UTILIZATION *)prEvent->aucBuffer); + break; + +#if CFG_SUPPORT_BATCH_SCAN + case EVENT_ID_BATCH_RESULT: + DBGLOG(SCN, TRACE, "Got EVENT_ID_BATCH_RESULT"); + + /* command response handling */ + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + prCmdInfo->u4FwResponseTime = kalGetTimeTick(); + wlanDebugCommandRecodTime(prCmdInfo); + if (prCmdInfo->pfCmdDoneHandler) + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); + else if (prCmdInfo->fgIsOid) + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + + break; +#endif /* CFG_SUPPORT_BATCH_SCAN */ + + case EVENT_ID_RSSI_MONITOR: + { + INT_32 rssi = 0; + + kalMemCopy(&rssi, prEvent->aucBuffer, sizeof(INT_32)); + DBGLOG(RX, TRACE, "EVENT_ID_RSSI_MONITOR value=%d\n", rssi); + + mtk_cfg80211_vendor_event_rssi_beyond_range(wiphy, + prGlueInfo->prDevHandler->ieee80211_ptr, rssi); + } + break; + +#if (CFG_SUPPORT_TDLS == 1) + case EVENT_ID_TDLS: + TdlsexEventHandle(prAdapter->prGlueInfo, + (UINT8 *) prEvent->aucBuffer, (UINT32) (prEvent->u2PacketLen - 8)); + break; +#endif /* CFG_SUPPORT_TDLS */ + +#if (CFG_SUPPORT_STATISTICS == 1) + case EVENT_ID_STATS_ENV: + statsEventHandle(prAdapter->prGlueInfo, + (UINT8 *) prEvent->aucBuffer, (UINT32) (prEvent->u2PacketLen - 8)); + break; +#endif /* CFG_SUPPORT_STATISTICS */ + case EVENT_ID_CHECK_REORDER_BUBBLE: + qmHandleEventCheckReorderBubble(prAdapter, prEvent); + break; +#if (CFG_SUPPORT_EMI_DEBUG == 1) + case EVENT_ID_DRIVER_DUMP_LOG: + { + P_EVENT_DRIVER_DUMP_EMI_LOG_T prEventDriverDumpEmiLog; + + DBGLOG(RX, TRACE, "EVENT_ID_DRIVER_DUMP_LOG\n"); + prEventDriverDumpEmiLog = (P_EVENT_DRIVER_DUMP_EMI_LOG_T) (prEvent->aucBuffer); + wlanReadFwInfoFromEmi(&(prEventDriverDumpEmiLog->u4RequestDriverDumpAddr)); + break; + } +#endif + case EVENT_ID_FW_LOG_ENV: + { + P_EVENT_FW_LOG_T prEventLog; + + prEventLog = (P_EVENT_FW_LOG_T) (prEvent->aucBuffer); + prEventLog->log[MAX_FW_LOG_LENGTH - 1] = '\0'; + DBGLOG(RX, INFO, "[F-L]%s\n", prEventLog->log); + } + break; + case EVENT_ID_ADD_PKEY_DONE: + { + struct EVENT_ADD_KEY_DONE_INFO *prKeyDone = + (struct EVENT_ADD_KEY_DONE_INFO *)prEvent->aucBuffer; + P_STA_RECORD_T prStaRec = NULL; + UINT_8 ucKeyId; + + prStaRec = cnmGetStaRecByAddress(prAdapter, prKeyDone->ucNetworkType, prKeyDone->aucStaAddr); + + if (!prStaRec) { + ucKeyId = prAdapter->rWifiVar.rAisSpecificBssInfo.ucKeyAlgorithmId; + if ((ucKeyId == CIPHER_SUITE_WEP40) || (ucKeyId == CIPHER_SUITE_WEP104)) { + DBGLOG(RX, INFO, "WEP, ucKeyAlgorithmId= %d\n", ucKeyId); + prStaRec = cnmGetStaRecByAddress(prAdapter, prKeyDone->ucNetworkType, + prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].aucBSSID); + if (!prStaRec) { + DBGLOG(RX, INFO, "WEP, AddPKeyDone, Net %d, Addr %pM, StaRec is NULL\n", + prKeyDone->ucNetworkType, + prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].aucBSSID); + break; + } + } else { + DBGLOG(RX, INFO, "AddPKeyDone, Net %d, Addr %pM, StaRec is NULL\n", + prKeyDone->ucNetworkType, prKeyDone->aucStaAddr); + break; + } + } + prStaRec->fgIsTxKeyReady = TRUE; + if (prStaRec->fgIsValid) + prStaRec->fgIsTxAllowed = TRUE; + DBGLOG(RX, INFO, "AddPKeyDone, Net %d, Addr %pM, Tx Allowed %d\n", + prKeyDone->ucNetworkType, prKeyDone->aucStaAddr, prStaRec->fgIsTxAllowed); + break; + } +#if CFG_SUPPORT_P2P_ECSA + case EVENT_ID_ECSA_RESULT: + { + P_EVENT_ECSA_RESULT prEcsa = (P_EVENT_ECSA_RESULT) (prEvent->aucBuffer); + + DBGLOG(RX, INFO, "BssIndex:status:PrimaryChannel:Sco: %d:%d:%d:%d\n", + prEcsa->ucNetTypeIndex, + prEcsa->ucStatus, + prEcsa->ucPrimaryChannel, + prEcsa->ucRfSco); + kalP2pUpdateECSA(prAdapter, prEcsa); + } + break; +#endif + default: + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + prCmdInfo->u4FwResponseTime = kalGetTimeTick(); + wlanDebugCommandRecodTime(prCmdInfo); + 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); + } else if (prEvent->ucEID == EVENT_ID_GET_TSM_STATISTICS)/* in case of unsolicited event */ + wmmComposeTsmRpt(prAdapter, NULL, prEvent->aucBuffer); + + 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; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + nicRxFillRFB(prAdapter, prSwRfb); + + ucSubtype = (*(PUINT_8) (prSwRfb->pvHeader) & MASK_FC_SUBTYPE) >> OFFSET_OF_FC_SUBTYPE; + +#if 0 /* CFG_RX_PKTS_DUMP */ + { + P_HIF_RX_HEADER_T prHifRxHdr; + UINT_16 u2TxFrameCtrl; + + prHifRxHdr = prSwRfb->prHifRxHdr; + u2TxFrameCtrl = (*(PUINT_8) (prSwRfb->pvHeader) & MASK_FRAME_TYPE); + /* if (prAdapter->rRxCtrl.u4RxPktsDumpTypeMask & BIT(HIF_RX_PKT_TYPE_MANAGEMENT)) { */ + /* if (u2TxFrameCtrl == MAC_FRAME_BEACON || */ + /* u2TxFrameCtrl == MAC_FRAME_PROBE_RSP) { */ + + DBGLOG(RX, INFO, "QM RX MGT: net %u sta idx %u wlan idx %u ssn %u ptype %u subtype %u 11 %u\n", + (UINT_32) HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr), prHifRxHdr->ucStaRecIdx, + prSwRfb->ucWlanIdx, (UINT_32) HIF_RX_HDR_GET_SN(prHifRxHdr),/* The new SN of the frame */ + prSwRfb->ucPacketType, ucSubtype, HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)); + + /* DBGLOG_MEM8(SW4, TRACE, (PUINT_8)prSwRfb->pvHeader, prSwRfb->u2PacketLen); */ + /* } */ + /* } */ + } +#endif + + if ((prAdapter->fgTestMode == FALSE) && (prAdapter->prGlueInfo->fgIsRegistered == TRUE)) { +#if CFG_MGMT_FRAME_HANDLING +#if CFG_SUPPORT_802_11W + P_RX_CTRL_T prRxCtrl; + BOOLEAN fgMfgDrop = FALSE; + + fgMfgDrop = rsnCheckRxMgmt(prAdapter, prSwRfb, ucSubtype); + if (fgMfgDrop) { + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); +#if DBG + LOG_FUNC("QM RX MGT: Drop Unprotected Mgmt frame!!!\n"); +#endif + nicRxReturnRFB(prAdapter, prSwRfb); + RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); + return; + } +#endif + if (apfnProcessRxMgtFrame[ucSubtype]) { + switch (apfnProcessRxMgtFrame[ucSubtype] (prAdapter, prSwRfb)) { + case WLAN_STATUS_PENDING: + return; + case WLAN_STATUS_SUCCESS: + case WLAN_STATUS_FAILURE: + break; + + default: + DBGLOG(RX, WARN, + "Unexpected MMPDU(0x%02X) returned with abnormal status\n", ucSubtype); + break; + } + } +#endif + } + + nicRxReturnRFB(prAdapter, prSwRfb); +} + +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG +static VOID nicRxCheckWakeupReason(P_SW_RFB_T prSwRfb) +{ + PUINT_8 pvHeader = NULL; + P_HIF_RX_HEADER_T prHifRxHdr; + UINT_16 u2PktLen = 0; + UINT_32 u4HeaderOffset; + + if (!prSwRfb) + return; + prHifRxHdr = prSwRfb->prHifRxHdr; + if (!prHifRxHdr) + return; + + switch (prSwRfb->ucPacketType) { + case HIF_RX_PKT_TYPE_DATA: + { + UINT_16 u2Temp = 0; + + if (HIF_RX_HDR_GET_BAR_FLAG(prHifRxHdr)) { + DBGLOG(RX, INFO, "BAR frame[SSN:%d, TID:%d] wakeup host\n", + (UINT_16)HIF_RX_HDR_GET_SN(prHifRxHdr), (UINT_8)HIF_RX_HDR_GET_TID(prHifRxHdr)); + break; + } + u4HeaderOffset = (UINT_32)(prHifRxHdr->ucHerderLenOffset & HIF_RX_HDR_HEADER_OFFSET_MASK); + pvHeader = (PUINT_8)prHifRxHdr + HIF_RX_HDR_SIZE + u4HeaderOffset; + u2PktLen = (UINT_16)(prHifRxHdr->u2PacketLen - (HIF_RX_HDR_SIZE + u4HeaderOffset)); + if (!pvHeader) { + DBGLOG(RX, ERROR, "data packet but pvHeader is NULL!\n"); + break; + } + u2Temp = (pvHeader[ETH_TYPE_LEN_OFFSET] << 8) | (pvHeader[ETH_TYPE_LEN_OFFSET + 1]); + + switch (u2Temp) { + case ETH_P_IPV4: + u2Temp = *(UINT_16 *) &pvHeader[ETH_HLEN + 4]; + DBGLOG(RX, INFO, "IP Packet:%d.%d.%d.%d, to:%d.%d.%d.%d,ID 0x%04x wakeup host\n", + pvHeader[ETH_HLEN + 12], pvHeader[ETH_HLEN + 13], + pvHeader[ETH_HLEN + 14], pvHeader[ETH_HLEN + 15], + pvHeader[ETH_HLEN + 16], pvHeader[ETH_HLEN + 17], + pvHeader[ETH_HLEN + 18], pvHeader[ETH_HLEN + 19], + u2Temp); + break; + case ETH_P_ARP: + { + PUINT_8 pucEthBody = &pvHeader[ETH_HLEN]; + UINT_16 u2OpCode = (pucEthBody[6] << 8) | pucEthBody[7]; + + if (u2OpCode == ARP_PRO_REQ) + DBGLOG(RX, INFO, "Arp Req From IP: %d.%d.%d.%d wakeup host\n", + pucEthBody[14], pucEthBody[15], pucEthBody[16], pucEthBody[17]); + else if (u2OpCode == ARP_PRO_RSP) + DBGLOG(RX, INFO, "Arp Rsp from IP: %d.%d.%d.%d wakeup host\n", + pucEthBody[14], pucEthBody[15], pucEthBody[16], pucEthBody[17]); + break; + } + case ETH_P_1X: + /* Fall through */ + case ETH_P_PRE_1X: + /* Fall through */ +#if CFG_SUPPORT_WAPI + case ETH_WPI_1X: + /* Fall through */ +#endif + case ETH_P_AARP: + /* Fall through */ + case ETH_P_IPV6: + /* Fall through */ + case ETH_P_IPX: + /* Fall through */ + case 0x8100: /* VLAN */ + /* Fall through */ + case 0x890d: /* TDLS */ + DBGLOG(RX, INFO, "Data Packet, EthType 0x%04x wakeup host\n", u2Temp); + break; + default: + DBGLOG(RX, WARN, "maybe abnormal data packet, EthType 0x%04x wakeup host, dump it\n", + u2Temp); + DBGLOG_MEM8(RX, INFO, pvHeader, u2PktLen > 50 ? 50 : u2PktLen); + break; + } + break; + } + case HIF_RX_PKT_TYPE_EVENT: + { + P_WIFI_EVENT_T prEvent = (P_WIFI_EVENT_T) prSwRfb->pucRecvBuff; + + DBGLOG(RX, INFO, "Event 0x%02x wakeup host\n", prEvent->ucEID); + break; + } + case HIF_RX_PKT_TYPE_MANAGEMENT: + { + UINT_8 ucSubtype; + P_WLAN_MAC_MGMT_HEADER_T prWlanMgmtHeader; + + u4HeaderOffset = (UINT_32)(prHifRxHdr->ucHerderLenOffset & HIF_RX_HDR_HEADER_OFFSET_MASK); + pvHeader = (PUINT_8)prHifRxHdr + HIF_RX_HDR_SIZE + u4HeaderOffset; + if (!pvHeader) { + DBGLOG(RX, ERROR, "Mgmt Frame but pvHeader is NULL!\n"); + break; + } + prWlanMgmtHeader = (P_WLAN_MAC_MGMT_HEADER_T)pvHeader; + ucSubtype = (prWlanMgmtHeader->u2FrameCtrl & MASK_FC_SUBTYPE) >> + OFFSET_OF_FC_SUBTYPE; + DBGLOG(RX, INFO, "MGMT frame subtype: %d SeqCtrl %d wakeup host\n", + ucSubtype, prWlanMgmtHeader->u2SeqCtrl); + break; + } + default: + DBGLOG(RX, WARN, "Unknown Packet %d wakeup host\n", prSwRfb->ucPacketType); + break; + } +} +#endif +/*----------------------------------------------------------------------------*/ +/*! +* @brief nicProcessRFBs is used to process RFBs in the rReceivedRFBList queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxProcessRFBs(IN P_ADAPTER_T prAdapter) +{ + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + +#if CFG_SUPPORT_MULTITHREAD + QUE_T rTempRxDataQue; + P_QUE_T prTempRxDataQue = &rTempRxDataQue; + + QUEUE_INITIALIZE(prTempRxDataQue); +#endif + + DEBUGFUNC("nicRxProcessRFBs"); + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + +#if !(CFG_SUPPORT_MULTITHREAD) + prRxCtrl->ucNumIndPacket = 0; + prRxCtrl->ucNumRetainedPacket = 0; +#endif + do { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rReceivedRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + if (prSwRfb) { +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG + if (kalIsWakeupByWlan(prAdapter)) + nicRxCheckWakeupReason(prSwRfb); +#endif + switch (prSwRfb->ucPacketType) { + case HIF_RX_PKT_TYPE_DATA: +#if CFG_SUPPORT_MULTITHREAD + QUEUE_INSERT_TAIL(prTempRxDataQue, &prSwRfb->rQueEntry); +#else + nicRxProcessDataPacket(prAdapter, prSwRfb); +#endif + break; + + case HIF_RX_PKT_TYPE_EVENT: + nicRxProcessEventPacket(prAdapter, prSwRfb); + break; + + case HIF_RX_PKT_TYPE_TX_LOOPBACK: +#if (CONF_HIF_LOOPBACK_AUTO == 1) + { + kalDevLoopbkRxHandle(prAdapter, prSwRfb); + nicRxReturnRFB(prAdapter, prSwRfb); + } +#else + DBGLOG(RX, ERROR, "ucPacketType = %d\n", prSwRfb->ucPacketType); +#endif /* CONF_HIF_LOOPBACK_AUTO */ + break; + + case HIF_RX_PKT_TYPE_MANAGEMENT: + nicRxProcessMgmtPacket(prAdapter, prSwRfb); + break; + + default: + RX_INC_CNT(prRxCtrl, RX_TYPE_ERR_DROP_COUNT); + RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); + DBGLOG(RX, ERROR, "ucPacketType = %d\n", prSwRfb->ucPacketType); + nicRxReturnRFB(prAdapter, prSwRfb); /* need to free it */ + break; + } + } else { + break; + } + } while (TRUE); +#if CFG_SUPPORT_MULTITHREAD + if (QUEUE_IS_NOT_EMPTY(prTempRxDataQue)) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_DATA_QUE); + QUEUE_CONCATENATE_QUEUES(&prRxCtrl->rRxDataRfbList, prTempRxDataQue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_DATA_QUE); + kalWakeupRxThread(prAdapter->prGlueInfo); + } +#else + 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 + } +#endif +} /* end of nicRxProcessRFBs() */ + +#if !CFG_SDIO_INTR_ENHANCE +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read the rx data from data port and setup RFB +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* +* @retval WLAN_STATUS_SUCCESS: SUCCESS +* @retval WLAN_STATUS_FAILURE: FAILURE +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicRxReadBuffer(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) +{ + P_RX_CTRL_T prRxCtrl; + PUINT_8 pucBuf; + P_HIF_RX_HEADER_T prHifRxHdr; + UINT_32 u4PktLen = 0, u4ReadBytes; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + BOOLEAN fgResult = TRUE; + UINT_32 u4RegValue; + UINT_32 rxNum; + + DEBUGFUNC("nicRxReadBuffer"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + pucBuf = prSwRfb->pucRecvBuff; + prHifRxHdr = prSwRfb->prHifRxHdr; + ASSERT(pucBuf); + DBGLOG(RX, TRACE, "pucBuf= 0x%x, prHifRxHdr= 0x%x\n", pucBuf, prHifRxHdr); + + do { + /* Read the RFB DW length and packet length */ + HAL_MCR_RD(prAdapter, MCR_WRPLR, &u4RegValue); + if (!fgResult) { + DBGLOG(RX, ERROR, "Read RX Packet Lentgh Error\n"); + return WLAN_STATUS_FAILURE; + } + /* 20091021 move the line to get the HIF RX header (for RX0/1) */ + if (u4RegValue == 0) { + DBGLOG(RX, ERROR, "No RX packet\n"); + return WLAN_STATUS_FAILURE; + } + + u4PktLen = u4RegValue & BITS(0, 15); + if (u4PktLen != 0) { + rxNum = 0; + } else { + rxNum = 1; + u4PktLen = (u4RegValue & BITS(16, 31)) >> 16; + } + + DBGLOG(RX, TRACE, "RX%d: u4PktLen = %d\n", rxNum, u4PktLen); + + /* 4 <4> Read Entire RFB and packet, include HW appended DW (Checksum Status) */ + u4ReadBytes = ALIGN_4(u4PktLen) + 4; + HAL_READ_RX_PORT(prAdapter, rxNum, u4ReadBytes, pucBuf, CFG_RX_MAX_PKT_SIZE); + + /* 20091021 move the line to get the HIF RX header */ + /* u4PktLen = (UINT_32)prHifRxHdr->u2PacketLen; */ + if (u4PktLen != (UINT_32) prHifRxHdr->u2PacketLen) { + DBGLOG(RX, ERROR, "Read u4PktLen = %d, prHifRxHdr->u2PacketLen: %d\n", + u4PktLen, prHifRxHdr->u2PacketLen); +#if DBG + dumpMemory8((PUINT_8) prHifRxHdr, + (prHifRxHdr->u2PacketLen > 4096) ? 4096 : prHifRxHdr->u2PacketLen); +#endif + ASSERT(0); + } + /* u4PktLen is byte unit, not inlude HW appended DW */ + + prSwRfb->ucPacketType = (UINT_8) (prHifRxHdr->u2PacketType & HIF_RX_HDR_PACKET_TYPE_MASK); + DBGLOG(RX, TRACE, "ucPacketType = %d\n", prSwRfb->ucPacketType); + + prSwRfb->ucStaRecIdx = (UINT_8) (prHifRxHdr->ucStaRecIdx); + + /* fgResult will be updated in MACRO */ + if (!fgResult) + return WLAN_STATUS_FAILURE; + + DBGLOG(RX, TRACE, "Dump RX buffer, length = 0x%x\n", u4ReadBytes); + DBGLOG_MEM8(RX, TRACE, pucBuf, u4ReadBytes); + } while (FALSE); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read frames from the data port, fill RFB +* and put each frame into the rReceivedRFBList queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxReceiveRFBs(IN P_ADAPTER_T prAdapter) +{ + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; + P_HIF_RX_HEADER_T prHifRxHdr; + + UINT_32 u4HwAppendDW; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxReceiveRFBs"); + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + do { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + if (!prSwRfb) { + DBGLOG(RX, TRACE, "No More RFB\n"); + break; + } + /* need to consider */ + if (nicRxReadBuffer(prAdapter, prSwRfb) == WLAN_STATUS_FAILURE) { + DBGLOG(RX, TRACE, "halRxFillRFB failed\n"); + nicRxReturnRFB(prAdapter, prSwRfb); + break; + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_INSERT_TAIL(&prRxCtrl->rReceivedRfbList, &prSwRfb->rQueEntry); + RX_INC_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + prHifRxHdr = prSwRfb->prHifRxHdr; + u4HwAppendDW = *((PUINT_32) ((ULONG) prHifRxHdr + (UINT_32) (ALIGN_4(prHifRxHdr->u2PacketLen)))); + DBGLOG(RX, TRACE, "u4HwAppendDW = 0x%x\n", u4HwAppendDW); + DBGLOG(RX, TRACE, "u2PacketLen = 0x%x\n", prHifRxHdr->u2PacketLen); + } while (FALSE); /* while (RX_STATUS_TEST_MORE_FLAG(u4HwAppendDW)); */ + + return; + +} /* end of nicReceiveRFBs() */ + +#else +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read frames from the data port, fill RFB +* and put each frame into the rReceivedRFBList queue. +* +* @param prAdapter Pointer to the Adapter structure. +* @param u4DataPort Specify which port to read +* @param u2RxLength Specify to the the rx packet length in Byte. +* @param prSwRfb the RFB to receive rx data. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS +nicRxEnhanceReadBuffer(IN P_ADAPTER_T prAdapter, + IN UINT_32 u4DataPort, IN UINT_16 u2RxLength, IN OUT P_SW_RFB_T prSwRfb) +{ + P_RX_CTRL_T prRxCtrl; + PUINT_8 pucBuf; + P_HIF_RX_HEADER_T prHifRxHdr; + UINT_32 u4PktLen = 0; + WLAN_STATUS u4Status = WLAN_STATUS_FAILURE; + BOOLEAN fgResult = TRUE; + + DEBUGFUNC("nicRxEnhanceReadBuffer"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + pucBuf = prSwRfb->pucRecvBuff; + ASSERT(pucBuf); + + prHifRxHdr = prSwRfb->prHifRxHdr; + ASSERT(prHifRxHdr); + + /* DBGLOG(RX, TRACE, ("u2RxLength = %d\n", u2RxLength)); */ + + do { + /* 4 <1> Read RFB frame from MCR_WRDR0, include HW appended DW */ + HAL_READ_RX_PORT(prAdapter, + u4DataPort, ALIGN_4(u2RxLength + HIF_RX_HW_APPENDED_LEN), pucBuf, CFG_RX_MAX_PKT_SIZE); + + if (!fgResult) { + DBGLOG(RX, ERROR, "Read RX Packet Lentgh Error\n"); + break; + } + + u4PktLen = (UINT_32) (prHifRxHdr->u2PacketLen); + /* DBGLOG(RX, TRACE, ("u4PktLen = %d\n", u4PktLen)); */ + + prSwRfb->ucPacketType = (UINT_8) (prHifRxHdr->u2PacketType & HIF_RX_HDR_PACKET_TYPE_MASK); + /* DBGLOG(RX, TRACE, ("ucPacketType = %d\n", prSwRfb->ucPacketType)); */ + + prSwRfb->ucStaRecIdx = (UINT_8) (prHifRxHdr->ucStaRecIdx); + + /* 4 <2> if the RFB dw size or packet size is zero */ + if (u4PktLen == 0) { + DBGLOG(RX, ERROR, "Packet Length = %u\n", u4PktLen); + ASSERT(0); + break; + } + /* 4 <3> if the packet is too large or too small */ + if (u4PktLen > CFG_RX_MAX_PKT_SIZE) { + DBGLOG(RX, TRACE, "Read RX Packet Lentgh Error (%u)\n", u4PktLen); + ASSERT(0); + break; + } + + u4Status = WLAN_STATUS_SUCCESS; + } while (FALSE); + + DBGLOG_MEM8(RX, TRACE, pucBuf, ALIGN_4(u2RxLength + HIF_RX_HW_APPENDED_LEN)); + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read frames from the data port for SDIO +* I/F, fill RFB and put each frame into the rReceivedRFBList queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxSDIOReceiveRFBs(IN P_ADAPTER_T prAdapter) +{ + P_SDIO_CTRL_T prSDIOCtrl; + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; + UINT_32 i, rxNum; + UINT_16 u2RxPktNum, u2RxLength = 0, u2Tmp = 0; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxSDIOReceiveRFBs"); + + ASSERT(prAdapter); + + prSDIOCtrl = prAdapter->prSDIOCtrl; + ASSERT(prSDIOCtrl); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + for (rxNum = 0; rxNum < 2; rxNum++) { + u2RxPktNum = + (rxNum == 0 ? prSDIOCtrl->rRxInfo.u.u2NumValidRx0Len : prSDIOCtrl->rRxInfo.u.u2NumValidRx1Len); + + if (u2RxPktNum == 0) + continue; + + for (i = 0; i < u2RxPktNum; i++) { + if (rxNum == 0) { + /* HAL_READ_RX_LENGTH */ + HAL_READ_RX_LENGTH(prAdapter, &u2RxLength, &u2Tmp); + } else if (rxNum == 1) { + /* HAL_READ_RX_LENGTH */ + HAL_READ_RX_LENGTH(prAdapter, &u2Tmp, &u2RxLength); + } + + if (!u2RxLength) + break; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + if (!prSwRfb) { + DBGLOG(RX, TRACE, "No More RFB\n"); + break; + } + ASSERT(prSwRfb); + + if (nicRxEnhanceReadBuffer(prAdapter, rxNum, u2RxLength, prSwRfb) == WLAN_STATUS_FAILURE) { + DBGLOG(RX, TRACE, "nicRxEnhanceRxReadBuffer failed\n"); + nicRxReturnRFB(prAdapter, prSwRfb); + break; + } + /* prSDIOCtrl->au4RxLength[i] = 0; */ + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_INSERT_TAIL(&prRxCtrl->rReceivedRfbList, &prSwRfb->rQueEntry); + RX_INC_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + } + } + + prSDIOCtrl->rRxInfo.u.u2NumValidRx0Len = 0; + prSDIOCtrl->rRxInfo.u.u2NumValidRx1Len = 0; + +} /* end of nicRxSDIOReceiveRFBs() */ + +#endif /* CFG_SDIO_INTR_ENHANCE */ + +#if CFG_SDIO_RX_AGG +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read frames from the data port for SDIO with Rx aggregation enabled +* I/F, fill RFB and put each frame into the rReceivedRFBList queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxSDIOAggReceiveRFBs(IN P_ADAPTER_T prAdapter) +{ + P_ENHANCE_MODE_DATA_STRUCT_T prEnhDataStr; + P_RX_CTRL_T prRxCtrl; + P_SDIO_CTRL_T prSDIOCtrl; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; + UINT_32 u4RxLength; + UINT_32 i, rxNum; + UINT_32 u4RxAggCount = 0, u4RxAggLength = 0; + UINT_32 u4RxAvailAggLen, u4CurrAvailFreeRfbCnt; + PUINT_8 pucSrcAddr; + P_HIF_RX_HEADER_T prHifRxHdr; + BOOLEAN fgIsRxEnhanceMode; + UINT_16 u2RxPktNum; +#if CFG_SDIO_RX_ENHANCE + UINT_32 u4MaxLoopCount = CFG_MAX_RX_ENHANCE_LOOP_COUNT; +#endif + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxSDIOAggReceiveRFBs"); + + ASSERT(prAdapter); + prEnhDataStr = prAdapter->prSDIOCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + prSDIOCtrl = prAdapter->prSDIOCtrl; + +#if CFG_SDIO_RX_ENHANCE + fgIsRxEnhanceMode = TRUE; +#else + fgIsRxEnhanceMode = FALSE; +#endif + + + do { +#if CFG_SDIO_RX_ENHANCE + /* to limit maximum loop for RX */ + u4MaxLoopCount--; + if (u4MaxLoopCount == 0) + break; +#endif + + if (prEnhDataStr->rRxInfo.u.u2NumValidRx0Len == 0 && prEnhDataStr->rRxInfo.u.u2NumValidRx1Len == 0) + break; + + for (rxNum = 0; rxNum < 2; rxNum++) { + u2RxPktNum = + (rxNum == + 0 ? prEnhDataStr->rRxInfo.u.u2NumValidRx0Len : prEnhDataStr->rRxInfo.u.u2NumValidRx1Len); + + /* if this assertion happened, it is most likely a F/W bug */ + ASSERT(u2RxPktNum <= 16); + + if (u2RxPktNum > 16) + continue; + + if (u2RxPktNum == 0) + continue; + +#if CFG_HIF_STATISTICS + prRxCtrl->u4TotalRxAccessNum++; + prRxCtrl->u4TotalRxPacketNum += u2RxPktNum; +#endif + + u4CurrAvailFreeRfbCnt = prRxCtrl->rFreeSwRfbList.u4NumElem; + + /* if SwRfb is not enough, abort reading this time */ + if (u4CurrAvailFreeRfbCnt < u2RxPktNum) { +#if CFG_HIF_RX_STARVATION_WARNING + DbgPrint("FreeRfb is not enough: %d available, need %d\n", u4CurrAvailFreeRfbCnt, + u2RxPktNum); + DbgPrint("Queued Count: %d / Dequeud Count: %d\n", prRxCtrl->u4QueuedCnt, + prRxCtrl->u4DequeuedCnt); +#endif + continue; + } +#if CFG_SDIO_RX_ENHANCE + u4RxAvailAggLen = + CFG_RX_COALESCING_BUFFER_SIZE - (sizeof(ENHANCE_MODE_DATA_STRUCT_T) + + 4 /* extra HW padding */); +#else + u4RxAvailAggLen = CFG_RX_COALESCING_BUFFER_SIZE; +#endif + for (i = 0, u4RxAggCount = 0; i < u2RxPktNum; i++) { + PUINT_8 pucZeroArray = NULL; + +restart: + 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) { + u4RxAvailAggLen -= ALIGN_4(u4RxLength + HIF_RX_HW_APPENDED_LEN); + u4RxAggCount++; + continue; + } + + /* CFG_RX_COALESCING_BUFFER_SIZE is not large enough */ + DBGLOG(RX, ERROR, + "[%s] Request_len(%d) is greater than Available_len(%d)\n", + __func__, + (ALIGN_4(u4RxLength + HIF_RX_HW_APPENDED_LEN)), u4RxAvailAggLen); + u4RxLength += (CFG_RX_COALESCING_BUFFER_SIZE - u4RxAvailAggLen); + pucZeroArray = kalMemAlloc(1000, VIR_MEM_TYPE); + if (!pucZeroArray) + break; + kalMemZero(pucZeroArray, 1000); + HAL_READ_RX_PORT(prAdapter, rxNum, CFG_RX_COALESCING_BUFFER_SIZE, + prRxCtrl->pucRxCoalescingBufPtr, CFG_RX_COALESCING_BUFFER_SIZE); + /* dump RXD if total u4RxLength is greater than u4RxAvailAggLen */ + DBGLOG(RX, ERROR, + "RXD for the wrong packet is\n"); + DBGLOG_MEM32(RX, ERROR, prRxCtrl->pucRxCoalescingBufPtr+ + (CFG_RX_COALESCING_BUFFER_SIZE - u4RxAvailAggLen), + sizeof(HW_MAC_RX_DESC_T)); + u4RxLength -= CFG_RX_COALESCING_BUFFER_SIZE; + /* + * we should read out all pending data, otherwise, + * DE said the port will be in abnormal case + */ + while (u4RxLength > CFG_RX_COALESCING_BUFFER_SIZE) { + HAL_READ_RX_PORT(prAdapter, rxNum, CFG_RX_COALESCING_BUFFER_SIZE, + prRxCtrl->pucRxCoalescingBufPtr, CFG_RX_COALESCING_BUFFER_SIZE); + /* if continuous 1000 bytes were zeros, means there's no data in this port */ + if (!kalMemCmp(pucZeroArray, prRxCtrl->pucRxCoalescingBufPtr, 1000)) { + kalMemFree(pucZeroArray, VIR_MEM_TYPE, 1000); + goto restart; + } + } + if (u4RxLength > 0) { + HAL_READ_RX_PORT(prAdapter, rxNum, ALIGN_4(u4RxLength + HIF_RX_HW_APPENDED_LEN), + prRxCtrl->pucRxCoalescingBufPtr, CFG_RX_COALESCING_BUFFER_SIZE); + } + kalMemFree(pucZeroArray, VIR_MEM_TYPE, 1000); + goto restart; + } + + 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 (fgIsBusAccessFailed) { + DBGLOG(RX, ERROR, "Read RX Agg Packet Error\n"); + continue; + } + + pucSrcAddr = prRxCtrl->pucRxCoalescingBufPtr; + for (i = 0; i < u4RxAggCount; i++) { + UINT_16 u2PktLength; + UINT_16 u4HeaderOffset = (((P_HIF_RX_HEADER_T)pucSrcAddr)->ucHerderLenOffset + & HIF_RX_HDR_HEADER_OFFSET_MASK); + UINT_16 u4HeaderLen = HIF_RX_HDR_SIZE + u4HeaderOffset; + + u2PktLength = (rxNum == 0 ? + prEnhDataStr->rRxInfo.u.au2Rx0Len[i] : + prEnhDataStr->rRxInfo.u.au2Rx1Len[i]); + + if (((P_HIF_RX_HEADER_T)pucSrcAddr)->u2PacketLen < u4HeaderLen + && ((((P_HIF_RX_HEADER_T)pucSrcAddr)->u2PacketType + & HIF_RX_HDR_PACKET_TYPE_MASK) == HIF_RX_PKT_TYPE_DATA)) { + DBGLOG(RX, ERROR, "rxNum(%d), u2PacketLen(%d), headerLen(%d)\n", + rxNum, ((P_HIF_RX_HEADER_T)pucSrcAddr)->u2PacketLen, + u4HeaderLen); + DBGLOG(RX, ERROR, "Drop the unexpected packet...\n"); + DBGLOG_MEM8(RX, ERROR, pucSrcAddr, + ALIGN_4(u2PktLength + HIF_RX_HW_APPENDED_LEN)); + + pucSrcAddr += ALIGN_4(u2PktLength + HIF_RX_HW_APPENDED_LEN); + RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP | RST_FLAG_PREVENT_POWER_OFF); + continue; + } + + if (ALIGN_4(u2PktLength + HIF_RX_HW_APPENDED_LEN) > CFG_RX_MAX_PKT_SIZE + || ((P_HIF_RX_HEADER_T)pucSrcAddr)->u2PacketLen > CFG_RX_MAX_PKT_SIZE) { + DBGLOG(RX, ERROR, + "[%s] rxNum(%d), Request_len(%d), pkt_field_len(%d), MAX_PKT_SIZE(%d)...", + __func__, rxNum, (ALIGN_4(u2PktLength + HIF_RX_HW_APPENDED_LEN)), + ((P_HIF_RX_HEADER_T)pucSrcAddr)->u2PacketLen, + CFG_RX_MAX_PKT_SIZE); + DBGLOG(RX, ERROR, "Drop the unexpected packet...\n"); + DBGLOG_MEM8(RX, ERROR, pucSrcAddr, + ALIGN_4(u2PktLength + HIF_RX_HW_APPENDED_LEN)); + + pucSrcAddr += ALIGN_4(u2PktLength + HIF_RX_HW_APPENDED_LEN); + RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP | RST_FLAG_PREVENT_POWER_OFF); + continue; + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + ASSERT(prSwRfb); + kalMemCopy(prSwRfb->pucRecvBuff, pucSrcAddr, + ALIGN_4(u2PktLength + HIF_RX_HW_APPENDED_LEN)); + + /* record the rx time */ + STATS_RX_ARRIVE_TIME_RECORD(prSwRfb); /* ms */ + + prHifRxHdr = prSwRfb->prHifRxHdr; + ASSERT(prHifRxHdr); + + prSwRfb->ucPacketType = + (UINT_8) (prHifRxHdr->u2PacketType & HIF_RX_HDR_PACKET_TYPE_MASK); + /* DBGLOG(RX, TRACE, ("ucPacketType = %d\n", prSwRfb->ucPacketType)); */ + + prSwRfb->ucStaRecIdx = (UINT_8) (prHifRxHdr->ucStaRecIdx); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_INSERT_TAIL(&prRxCtrl->rReceivedRfbList, &prSwRfb->rQueEntry); + RX_INC_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + pucSrcAddr += ALIGN_4(u2PktLength + HIF_RX_HW_APPENDED_LEN); + /* prEnhDataStr->au4RxLength[i] = 0; */ + } + +#if CFG_SDIO_RX_ENHANCE + kalMemCopy(prAdapter->prSDIOCtrl, (pucSrcAddr + 4), sizeof(ENHANCE_MODE_DATA_STRUCT_T)); + + /* do the same thing what nicSDIOReadIntStatus() does */ + if ((prSDIOCtrl->u4WHISR & WHISR_TX_DONE_INT) == 0 && + (prSDIOCtrl->rTxInfo.au4WTSR[0] | prSDIOCtrl->rTxInfo.au4WTSR[1])) { + prSDIOCtrl->u4WHISR |= WHISR_TX_DONE_INT; + } + + if ((prSDIOCtrl->u4WHISR & BIT(31)) == 0 && + HAL_GET_MAILBOX_READ_CLEAR(prAdapter) == TRUE && + (prSDIOCtrl->u4RcvMailbox0 != 0 || prSDIOCtrl->u4RcvMailbox1 != 0)) { + prSDIOCtrl->u4WHISR |= BIT(31); + } + + /* dispatch to interrupt handler with RX bits masked */ + nicProcessIST_impl(prAdapter, + prSDIOCtrl->u4WHISR & (~(WHISR_RX0_DONE_INT | WHISR_RX1_DONE_INT))); +#endif + } + +#if !CFG_SDIO_RX_ENHANCE + prEnhDataStr->rRxInfo.u.u2NumValidRx0Len = 0; + prEnhDataStr->rRxInfo.u.u2NumValidRx1Len = 0; +#endif + } while ((prEnhDataStr->rRxInfo.u.u2NumValidRx0Len || prEnhDataStr->rRxInfo.u.u2NumValidRx1Len) + && fgIsRxEnhanceMode); + +} +#endif /* CFG_SDIO_RX_AGG */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Setup a RFB and allocate the os packet to the RFB +* +* @param prAdapter Pointer to the Adapter structure. +* @param prSwRfb Pointer to the RFB +* +* @retval WLAN_STATUS_SUCCESS +* @retval WLAN_STATUS_RESOURCES +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicRxSetupRFB(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + PVOID pvPacket; + PUINT_8 pucRecvBuff; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + if (!prSwRfb->pvPacket) { + kalMemZero(prSwRfb, sizeof(SW_RFB_T)); + pvPacket = kalPacketAlloc(prAdapter->prGlueInfo, CFG_RX_MAX_PKT_SIZE, &pucRecvBuff); + if (pvPacket == NULL) + return WLAN_STATUS_RESOURCES; + + prSwRfb->pvPacket = pvPacket; + prSwRfb->pucRecvBuff = (PVOID) pucRecvBuff; + } else { + kalMemZero(((PUINT_8) prSwRfb + OFFSET_OF(SW_RFB_T, prHifRxHdr)), + (sizeof(SW_RFB_T) - OFFSET_OF(SW_RFB_T, prHifRxHdr))); + } + + prSwRfb->prHifRxHdr = (P_HIF_RX_HEADER_T) (prSwRfb->pucRecvBuff); + + return WLAN_STATUS_SUCCESS; + +} /* end of nicRxSetupRFB() */ +VOID nicRxReturnRFBwithUninit(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb + , IN BOOLEAN fgIsUninitRfb) +{ + 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); + + if (fgIsUninitRfb) { + /* + * The processing on this RFB is uninitiated, so put it back on the tail of + * our list + */ + DBGLOGLIMITED(RX, WARN, + "wlanReturnPacket nicRxSetupRFB fail!\n"); + /* insert initialized SwRfb block */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_INSERT_TAIL(&prRxCtrl->rUnInitializedRfbList, prQueEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + } else { + nicRxReturnRFB(prAdapter, prSwRfb); + } + + + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This routine is called to put a RFB back onto the "RFB with Buffer" list +* or "RFB without buffer" list according to pvPacket. +* +* @param prAdapter Pointer to the Adapter structure. +* @param prSwRfb Pointer to the RFB +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxReturnRFB(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_RX_CTRL_T prRxCtrl; + P_QUE_ENTRY_T prQueEntry; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + prRxCtrl = &prAdapter->rRxCtrl; + prQueEntry = &prSwRfb->rQueEntry; + + ASSERT(prQueEntry); + + /* + * The processing on this RFB is done, so put it back on the tail of + * our list + */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + if (prSwRfb->pvPacket) { + /* QUEUE_INSERT_TAIL */ + QUEUE_INSERT_TAIL(&prRxCtrl->rFreeSwRfbList, prQueEntry); + } else { + /* QUEUE_INSERT_TAIL */ + prSwRfb->pucRecvBuff = NULL; + QUEUE_INSERT_TAIL(&prRxCtrl->rIndicatedRfbList, prQueEntry); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); +} /* end of nicRxReturnRFB() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process rx interrupt. When the rx +* Interrupt is asserted, it means there are frames in queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicProcessRxInterrupt(IN P_ADAPTER_T prAdapter) +{ + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + + prGlueInfo->IsrRxCnt++; +#if CFG_SDIO_INTR_ENHANCE +#if CFG_SDIO_RX_AGG + nicRxSDIOAggReceiveRFBs(prAdapter); +#else + nicRxSDIOReceiveRFBs(prAdapter); +#endif +#else + nicRxReceiveRFBs(prAdapter); +#endif /* CFG_SDIO_INTR_ENHANCE */ + + nicRxProcessRFBs(prAdapter); +} /* end of nicProcessRxInterrupt() */ + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +/*----------------------------------------------------------------------------*/ +/*! +* @brief Used to update IP/TCP/UDP checksum statistics of RX Module. +* +* @param prAdapter Pointer to the Adapter structure. +* @param aeCSUM The array of checksum result. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxUpdateCSUMStatistics(IN P_ADAPTER_T prAdapter, IN const ENUM_CSUM_RESULT_T aeCSUM[]) +{ + P_RX_CTRL_T prRxCtrl; + + ASSERT(prAdapter); + ASSERT(aeCSUM); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_SUCCESS) || + (aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_SUCCESS)) { + RX_INC_CNT(prRxCtrl, RX_CSUM_IP_SUCCESS_COUNT); + } else if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_FAILED) || (aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_FAILED)) { + RX_INC_CNT(prRxCtrl, RX_CSUM_IP_FAILED_COUNT); + } else if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_NONE) && (aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_NONE)) { + RX_INC_CNT(prRxCtrl, RX_CSUM_UNKNOWN_L3_PKT_COUNT); + } else { + ASSERT(0); + } + + if (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_SUCCESS) { + /* count success num */ + RX_INC_CNT(prRxCtrl, RX_CSUM_TCP_SUCCESS_COUNT); + } else if (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_FAILED) { + RX_INC_CNT(prRxCtrl, RX_CSUM_TCP_FAILED_COUNT); + } else if (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_SUCCESS) { + RX_INC_CNT(prRxCtrl, RX_CSUM_UDP_SUCCESS_COUNT); + } else if (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_FAILED) { + RX_INC_CNT(prRxCtrl, RX_CSUM_UDP_FAILED_COUNT); + } else if ((aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_NONE) && (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_NONE)) { + RX_INC_CNT(prRxCtrl, RX_CSUM_UNKNOWN_L4_PKT_COUNT); + } else { + ASSERT(0); + } + +} /* end of nicRxUpdateCSUMStatistics() */ +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to query current status of RX Module. +* +* @param prAdapter Pointer to the Adapter structure. +* @param pucBuffer Pointer to the message buffer. +* @param pu4Count Pointer to the buffer of message length count. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxQueryStatus(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuffer, OUT PUINT_32 pu4Count) +{ + P_RX_CTRL_T prRxCtrl; + PUINT_8 pucCurrBuf = pucBuffer; + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + /* if (pucBuffer) {} */ /* For Windows, we'll print directly instead of sprintf() */ + ASSERT(pu4Count); + + SPRINTF(pucCurrBuf, ("\n\nRX CTRL STATUS:")); + SPRINTF(pucCurrBuf, ("\n===============")); + SPRINTF(pucCurrBuf, ("\nFREE RFB w/i BUF LIST :%9u", prRxCtrl->rFreeSwRfbList.u4NumElem)); + SPRINTF(pucCurrBuf, ("\nFREE RFB w/o BUF LIST :%9u", prRxCtrl->rIndicatedRfbList.u4NumElem)); + SPRINTF(pucCurrBuf, ("\nRECEIVED RFB LIST :%9u", prRxCtrl->rReceivedRfbList.u4NumElem)); +#if CFG_SUPPORT_MULTITHREAD + SPRINTF(pucCurrBuf, ("\nRECEIVED DATA RFB LIST:%9u", prRxCtrl->rRxDataRfbList.u4NumElem)); +#endif + SPRINTF(pucCurrBuf, ("\n\n")); + + /* *pu4Count = (UINT_32)((UINT_32)pucCurrBuf - (UINT_32)pucBuffer); */ + +} /* end of nicRxQueryStatus() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Clear RX related counters +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return - (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxClearStatistics(IN P_ADAPTER_T prAdapter) +{ + P_RX_CTRL_T prRxCtrl; + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + RX_RESET_ALL_CNTS(prRxCtrl); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to query current statistics of RX Module. +* +* @param prAdapter Pointer to the Adapter structure. +* @param pucBuffer Pointer to the message buffer. +* @param pu4Count Pointer to the buffer of message length count. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxQueryStatistics(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuffer, OUT PUINT_32 pu4Count) +{ + P_RX_CTRL_T prRxCtrl; + PUINT_8 pucCurrBuf = pucBuffer; + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + /* if (pucBuffer) {} */ /* For Windows, we'll print directly instead of sprintf() */ + ASSERT(pu4Count); + +#define SPRINTF_RX_COUNTER(eCounter) \ + SPRINTF(pucCurrBuf, ("%-30s : %u\n", #eCounter, (UINT_32)prRxCtrl->au8Statistics[eCounter])) + + SPRINTF_RX_COUNTER(RX_MPDU_TOTAL_COUNT); + SPRINTF_RX_COUNTER(RX_SIZE_ERR_DROP_COUNT); + SPRINTF_RX_COUNTER(RX_DATA_INDICATION_COUNT); + SPRINTF_RX_COUNTER(RX_DATA_RETURNED_COUNT); + SPRINTF_RX_COUNTER(RX_DATA_RETAINED_COUNT); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD || CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 + SPRINTF_RX_COUNTER(RX_CSUM_TCP_FAILED_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_UDP_FAILED_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_IP_FAILED_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_TCP_SUCCESS_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_UDP_SUCCESS_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_IP_SUCCESS_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_UNKNOWN_L4_PKT_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_UNKNOWN_L3_PKT_COUNT); + SPRINTF_RX_COUNTER(RX_IP_V6_PKT_CCOUNT); +#endif + + /* *pu4Count = (UINT_32)(pucCurrBuf - pucBuffer); */ + + nicRxClearStatistics(prAdapter); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read the Response data from data port +* +* @param prAdapter pointer to the Adapter handler +* @param pucRspBuffer pointer to the Response buffer +* +* @retval WLAN_STATUS_SUCCESS: Response packet has been read +* @retval WLAN_STATUS_FAILURE: Read Response packet timeout or error occurred +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicRxWaitResponse(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucPortIdx, OUT PUINT_8 pucRspBuffer, IN UINT_32 u4MaxRespBufferLen, OUT PUINT_32 pu4Length) +{ + UINT_32 u4Value = 0, u4PktLen = 0; + UINT_32 i = 0; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + BOOLEAN fgResult = TRUE; + ktime_t rStartTime, rCurTime; + P_RX_CTRL_T prRxCtrl; + + DEBUGFUNC("nicRxWaitResponse"); + + ASSERT(prAdapter); + ASSERT(pucRspBuffer); + ASSERT(ucPortIdx < 2); + + rStartTime = ktime_get(); + prRxCtrl = &prAdapter->rRxCtrl; + + 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 */ + rCurTime = ktime_get(); + if (ktime_to_ms(ktime_sub(rCurTime, rStartTime)) > + RX_RESPONSE_TIMEOUT) { +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE + DBGLOG(RX, ERROR, + "RX_RESPONSE_TIMEOUT %u %u %lld %lld\n", + u4PktLen, i, rStartTime, + rCurTime); +#else + DBGLOG(RX, ERROR, + "RX_RESPONSE_TIMEOUT %u %u %lld %lld\n", + u4PktLen, i, rStartTime.tv64, + rCurTime.tv64); +#endif + return WLAN_STATUS_FAILURE; + } + + /* Response packet is not ready */ + kalUdelay(50); + + i++; + continue; + } + if (u4PktLen > u4MaxRespBufferLen) { + /* + * TO: buffer is not enough but we still need to read all data from HIF to avoid + * HIF crazy. + */ + DBGLOG(RX, ERROR, + "Not enough Event Buffer: required length = 0x%x, available buffer length = %d\n", + u4PktLen, u4MaxRespBufferLen); + DBGLOG(RX, ERROR, "i = %d, u4PktLen = %u\n", i, u4PktLen); + return WLAN_STATUS_FAILURE; + } + + wlanFWDLDebugAddRxStartTime(kalGetTimeTick()); + + HAL_PORT_RD(prAdapter, + ucPortIdx == 0 ? MCR_WRDR0 : MCR_WRDR1, u4PktLen, + prRxCtrl->pucRxCoalescingBufPtr, u4MaxRespBufferLen); + + wlanFWDLDebugAddRxDoneTime(kalGetTimeTick()); + + /* fgResult will be updated in MACRO */ + if (!fgResult) { + DBGLOG(RX, ERROR, "Read Response Packet Error\n"); + return WLAN_STATUS_FAILURE; + } + + kalMemCopy(pucRspBuffer, prRxCtrl->pucRxCoalescingBufPtr, u4PktLen); + DBGLOG(RX, TRACE, "Dump Response buffer, length = 0x%x\n", u4PktLen); + DBGLOG_MEM8(RX, TRACE, pucRspBuffer, u4PktLen); + + *pu4Length = u4PktLen; + break; + } while (TRUE); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Set filter to enable Promiscuous Mode +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxEnablePromiscuousMode(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + +} /* end of nicRxEnablePromiscuousMode() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Set filter to disable Promiscuous Mode +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxDisablePromiscuousMode(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + +} /* end of nicRxDisablePromiscuousMode() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief this function flushes all packets queued in reordering module +* +* @param prAdapter Pointer to the Adapter structure. +* +* @retval WLAN_STATUS_SUCCESS Flushed successfully +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicRxFlush(IN P_ADAPTER_T prAdapter) +{ + P_SW_RFB_T prSwRfb; + + ASSERT(prAdapter); + + prSwRfb = qmFlushRxQueues(prAdapter); + if (prSwRfb != NULL) { + do { + P_SW_RFB_T prNextSwRfb; + + /* save next first */ + prNextSwRfb = (P_SW_RFB_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prSwRfb); + + /* free */ + nicRxReturnRFB(prAdapter, prSwRfb); + + prSwRfb = prNextSwRfb; + } while (prSwRfb); + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param +* +* @retval +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicRxProcessActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_WLAN_ACTION_FRAME prActFrame; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + if (prSwRfb->u2PacketLen < sizeof(WLAN_ACTION_FRAME) - 1) + return WLAN_STATUS_INVALID_PACKET; + prActFrame = (P_WLAN_ACTION_FRAME) prSwRfb->pvHeader; + DBGLOG(RX, INFO, "Category %u, Action %u\n", prActFrame->ucCategory, prActFrame->ucAction); + + switch (prActFrame->ucCategory) { + case CATEGORY_QOS_ACTION: + case CATEGORY_WME_MGT_NOTIFICATION: + if (prActFrame->ucCategory == CATEGORY_QOS_ACTION) { + DBGLOG(RX, INFO, "received dscp action frame: %d\n", __LINE__); + handleQosMapConf(prAdapter, prSwRfb); + } + wmmParseQosAction(prAdapter, prSwRfb); + + break; + case CATEGORY_PUBLIC_ACTION: + if (prActFrame->ucAction == PUBLIC_ACTION_GAS_INITIAL_REQ) /* GAS Initial Request */ + DBGLOG(RX, INFO, "received GAS Initial Request frame\n"); + else if (prActFrame->ucAction == PUBLIC_ACTION_GAS_INITIAL_RESP) /* GAS Initial Response */ + DBGLOG(RX, INFO, "received GAS Initial Response frame\n"); + if (HIF_RX_HDR_GET_NETWORK_IDX(prSwRfb->prHifRxHdr) == NETWORK_TYPE_AIS_INDEX) + aisFuncValidateRxActionFrame(prAdapter, prSwRfb); +#if CFG_ENABLE_WIFI_DIRECT + else if (prAdapter->fgIsP2PRegistered) { + rlmProcessPublicAction(prAdapter, prSwRfb); + + p2pFuncValidateRxActionFrame(prAdapter, prSwRfb); + + } +#endif + break; + + case CATEGORY_HT_ACTION: +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) + rlmProcessHtAction(prAdapter, prSwRfb); +#endif + break; + case CATEGORY_VENDOR_SPECIFIC_ACTION: +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) + p2pFuncValidateRxActionFrame(prAdapter, prSwRfb); +#endif +#if CFG_SUPPORT_NCHO + if (HIF_RX_HDR_GET_NETWORK_IDX(prSwRfb->prHifRxHdr) == NETWORK_TYPE_AIS_INDEX) { + if (prAdapter->rNchoInfo.fgECHOEnabled == TRUE && prAdapter->rNchoInfo.u4WesMode == TRUE) { + aisFuncValidateRxActionFrame(prAdapter, prSwRfb); + DBGLOG(INIT, INFO, "NCHO CATEGORY_VENDOR_SPECIFIC_ACTION\n"); + } + } +#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)) { + DBGLOG(RSN, INFO, "Rx SA Query\n"); + /* MFP test plan 5.3.3.4 */ + rsnSaQueryAction(prAdapter, prSwRfb); + } else { + DBGLOG(RSN, WARN, "Un-Protected SA Query, do nothing\n"); + } + } else if (HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr) == + NETWORK_TYPE_P2P_INDEX) { + P_BSS_INFO_T prBssInfo = + &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + P_STA_RECORD_T prStaRec = + cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (prBssInfo && + prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT && + prStaRec) { + /* AP PMF */ + DBGLOG(RSN, INFO, "[Rx] nicRx AP PMF SAQ action\n"); + if (rsnCheckBipKeyInstalled(prAdapter, + prStaRec)) { + /* MFP test plan 4.3.3.4 */ + rsnApSaQueryAction(prAdapter, prSwRfb); + } + } + } + } + break; +#endif +#if (CFG_SUPPORT_802_11V || CFG_SUPPORT_PPR2) + case CATEGORY_WNM_ACTION: + { + if (HIF_RX_HDR_GET_NETWORK_IDX(prSwRfb->prHifRxHdr) == NETWORK_TYPE_AIS_INDEX) { + DBGLOG(RX, INFO, "WNM action frame: %d\n", __LINE__); + wnmWNMAction(prAdapter, prSwRfb); + } else + DBGLOG(RX, INFO, "WNM action frame: %d\n", __LINE__); + } + break; +#endif + +#if CFG_SUPPORT_DFS /* Add by Enlai */ + case CATEGORY_SPEC_MGT: + { + if (prAdapter->fgEnable5GBand == TRUE) + rlmProcessSpecMgtAction(prAdapter, prSwRfb); + } + break; +#endif + +#if CFG_SUPPORT_802_11K + case CATEGORY_RM_ACTION: + switch (prActFrame->ucAction) { + case RM_ACTION_RM_REQUEST: + rlmProcessRadioMeasurementRequest(prAdapter, prSwRfb); + break; + /*case RM_ACTION_LM_REQUEST: + * rlmProcessLinkMeasurementRequest(prAdapter, prActFrame); + * break;*/ /* Link Measurement is handled in Firmware + * rlmProcessLinkMeasurementRequest(prAdapter, prActFrame); + * break; + */ + /* Link Measurement is handled in Firmware */ + + case RM_ACTION_REIGHBOR_RESPONSE: + rlmProcessNeighborReportResonse(prAdapter, prActFrame, prSwRfb->u2PacketLen); + break; + } + break; +#endif + +#if (CFG_SUPPORT_TDLS == 1) + case 12: /* shall not be here */ + /* + * A received TDLS Action frame with the Type field set to Management shall + * be discarded. Note that the TDLS Discovery Response frame is not a TDLS + * frame but a Public Action frame. + */ + break; +#endif /* CFG_SUPPORT_TDLS */ + + default: + break; + } /* end of switch case */ + + return WLAN_STATUS_SUCCESS; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/nic_tx.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/nic_tx.c new file mode 100644 index 0000000000000..3509260533c0b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/nic_tx.c @@ -0,0 +1,2010 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E 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 "tdls.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will initial all variables in regard to SW TX Queues and +* all free lists of MSDU_INFO_T and SW_TFCB_T. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicTxInitialize(IN P_ADAPTER_T prAdapter) +{ + P_TX_CTRL_T prTxCtrl; + PUINT_8 pucMemHandle; + P_MSDU_INFO_T prMsduInfo; + UINT_32 i; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicTxInitialize"); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + /* 4 <1> Initialization of Traffic Class Queue Parameters */ + nicTxResetResource(prAdapter); + +#if CFG_SDIO_TX_AGG + prTxCtrl->pucTxCoalescingBufPtr = prAdapter->pucCoalescingBufCached; +#endif /* CFG_SDIO_TX_AGG */ + + /* allocate MSDU_INFO_T and link it into rFreeMsduInfoList */ + QUEUE_INITIALIZE(&prTxCtrl->rFreeMsduInfoList); + + pucMemHandle = prTxCtrl->pucTxCached; + for (i = 0; i < CFG_TX_MAX_PKT_NUM; i++) { + prMsduInfo = (P_MSDU_INFO_T) pucMemHandle; + kalMemZero(prMsduInfo, sizeof(MSDU_INFO_T)); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + QUEUE_INSERT_TAIL(&prTxCtrl->rFreeMsduInfoList, (P_QUE_ENTRY_T) prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + + pucMemHandle += ALIGN_4(sizeof(MSDU_INFO_T)); + } + + ASSERT(prTxCtrl->rFreeMsduInfoList.u4NumElem == CFG_TX_MAX_PKT_NUM); + /* Check if the memory allocation consist with this initialization function */ + ASSERT((UINT_32) (pucMemHandle - prTxCtrl->pucTxCached) == prTxCtrl->u4TxCachedSize); + + QUEUE_INITIALIZE(&prTxCtrl->rTxMgmtTxingQueue); + prTxCtrl->i4TxMgmtPendingNum = 0; + +#if CFG_HIF_STATISTICS + prTxCtrl->u4TotalTxAccessNum = 0; + prTxCtrl->u4TotalTxPacketNum = 0; +#endif + + prTxCtrl->i4PendingFwdFrameCount = 0; + + qmInit(prAdapter); + + TX_RESET_ALL_CNTS(prTxCtrl); + +} /* end of nicTxInitialize() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Driver maintain a variable that is synchronous with the usage of individual +* TC Buffer Count. This function will check if has enough TC Buffer for incoming +* packet and then update the value after promise to provide the resources. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] ucTC Specify the resource of TC +* +* \retval WLAN_STATUS_SUCCESS Resource is available and been assigned. +* \retval WLAN_STATUS_RESOURCES Resource is not available. +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 u4CurrTick; +WLAN_STATUS nicTxAcquireResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC, IN BOOLEAN pfgIsSecOrMgmt) +{ +#define TC4_NO_RESOURCE_DELAY_MS 5 /* exponential of 5s */ +#define TC4_NO_RESOURCE_DELAY_1S 1 /* exponential of 1s */ + + P_TX_CTRL_T prTxCtrl; + WLAN_STATUS u4Status = WLAN_STATUS_RESOURCES; + P_QUE_MGT_T prQM; + BOOLEAN fgWmtCoreDump = FALSE; + + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + prQM = &prAdapter->rQM; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + /* + * DbgPrint("nicTxAcquireResource prTxCtrl->rTc.aucFreeBufferCount[%d]=%d\n", + * ucTC, prTxCtrl->rTc.aucFreeBufferCount[ucTC]); + */ + do { + if (pfgIsSecOrMgmt && (ucTC == TC4_INDEX)) { + if (prTxCtrl->rTc.aucFreeBufferCount[ucTC] < 2) { + DBGLOG(TX, EVENT, " aucFreeBufferCount = %d\n", + prTxCtrl->rTc.aucFreeBufferCount[ucTC]); + + if (prTxCtrl->rTc.aucFreeBufferCount[ucTC]) + u4CurrTick = 0; + + break; + } + } + + if (prTxCtrl->rTc.aucFreeBufferCount[ucTC]) { + + if (ucTC == TC4_INDEX) + u4CurrTick = 0; + /* get a available TX entry */ + prTxCtrl->rTc.aucFreeBufferCount[ucTC]--; + + prQM->au4ResourceUsedCounter[ucTC]++; + + DBGLOG(TX, EVENT, "Acquire: TC = %d aucFreeBufferCount = %d\n", + ucTC, prTxCtrl->rTc.aucFreeBufferCount[ucTC]); + + u4Status = WLAN_STATUS_SUCCESS; + } + } while (FALSE); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + if (ucTC == TC4_INDEX) { + if (u4CurrTick == 0) + u4CurrTick = kalGetTimeTick(); + + if (CHECK_FOR_TIMEOUT(kalGetTimeTick(), u4CurrTick, + SEC_TO_SYSTIME(TC4_NO_RESOURCE_DELAY_1S))) + wlanDumpCommandFwStatus(); + + if (CHECK_FOR_TIMEOUT(kalGetTimeTick(), u4CurrTick, + SEC_TO_SYSTIME(TC4_NO_RESOURCE_DELAY_MS))) { + wlanDumpTcResAndTxedCmd(NULL, 0); + cmdBufDumpCmdQueue(&prAdapter->rPendingCmdQueue, "waiting response CMD queue"); + glDumpConnSysCpuInfo(prAdapter->prGlueInfo); + /* dump TC4[0] ~ TC4[3] TX_DESC */ + wlanDebugHifDescriptorDump(prAdapter, MTK_AMPDU_TX_DESC, DEBUG_TC4_INDEX); + + fgWmtCoreDump = glIsWmtCodeDump(); + if (fgWmtCoreDump == FALSE) { + DBGLOG(TX, WARN, + "[TC4 no resource delay 5s!] Trigger Coredump\n"); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP | RST_FLAG_PREVENT_POWER_OFF); + } else + DBGLOG(TX, WARN, + "[TC4 no resource delay 5s!] WMT is code dumping! STOP AEE & chip reset\n"); + + u4CurrTick = 0; + } + + } + return u4Status; + +} /* end of nicTxAcquireResourceAndTFCBs() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Driver maintain a variable that is synchronous with the usage of individual +* TC Buffer Count. This function will do polling if FW has return the resource. +* Used when driver start up before enable interrupt. +* +* @param prAdapter Pointer to the Adapter structure. +* @param ucTC Specify the resource of TC +* +* @retval WLAN_STATUS_SUCCESS Resource is available. +* @retval WLAN_STATUS_FAILURE Resource is not available. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicTxPollingResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC) +{ + P_TX_CTRL_T prTxCtrl; + WLAN_STATUS u4Status = WLAN_STATUS_FAILURE; + INT_32 i = NIC_TX_RESOURCE_POLLING_TIMEOUT; + UINT_32 au4WTSR[2]; + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + if (ucTC >= TC_NUM) + return WLAN_STATUS_FAILURE; + + if (prTxCtrl->rTc.aucFreeBufferCount[ucTC] > 0) + return WLAN_STATUS_SUCCESS; + + while (i-- > 0) { + HAL_READ_TX_RELEASED_COUNT(prAdapter, au4WTSR); + + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + break; + } else if (nicTxReleaseResource(prAdapter, (PUINT_8) au4WTSR)) { + if (prTxCtrl->rTc.aucFreeBufferCount[ucTC] > 0) { + u4Status = WLAN_STATUS_SUCCESS; + break; + } + kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC); + } else { + kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC); + } + if (i < NIC_TX_RESOURCE_POLLING_TIMEOUT - 30) { + wlanReadFwStatus(prAdapter); + wlanDumpCommandFwStatus(); + } + } + + if (i <= 0 && ucTC == TC4_INDEX) { + DBGLOG(TX, ERROR, "polling Tx resource for Tc4 timeout\n"); + wlanDumpTcResAndTxedCmd(NULL, 0); + glDumpConnSysCpuInfo(prAdapter->prGlueInfo); + } +#if DBG + { + INT_32 i4Times = NIC_TX_RESOURCE_POLLING_TIMEOUT - (i + 1); + + if (i4Times) { + DBGLOG(TX, TRACE, "Polling MCR_WTSR delay %d times, %d msec\n", + i4Times, (i4Times * NIC_TX_RESOURCE_POLLING_DELAY_MSEC)); + } + } +#endif /* DBG */ + + return u4Status; + +} /* end of nicTxPollingResource() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Driver maintain a variable that is synchronous with the usage of individual +* TC Buffer Count. This function will release TC Buffer count according to +* the given TX_STATUS COUNTER after TX Done. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] u4TxStatusCnt Value of TX STATUS +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN nicTxReleaseResource(IN P_ADAPTER_T prAdapter, IN unsigned char *aucTxRlsCnt) +{ + PUINT_32 pu4Tmp = (PUINT_32) aucTxRlsCnt; + P_TX_CTRL_T prTxCtrl; + BOOLEAN bStatus = FALSE; + UINT_32 i; + + KAL_SPIN_LOCK_DECLARATION(); + + P_QUE_MGT_T prQM = &prAdapter->rQM; + + prTxCtrl = &prAdapter->rTxCtrl; + + + if (pu4Tmp[0] | pu4Tmp[1]) { + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + for (i = 0; i < TC_NUM; i++) + prTxCtrl->rTc.aucFreeBufferCount[i] += aucTxRlsCnt[i]; + for (i = 0; i < TC_NUM; i++) + prQM->au4QmTcResourceBackCounter[i] += aucTxRlsCnt[i]; + if (aucTxRlsCnt[TC4_INDEX] != 0) + wlanTraceReleaseTcRes(prAdapter, aucTxRlsCnt, prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX]); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); +#if 0 + for (i = 0; i < TC_NUM; i++) { + DBGLOG(TX, TRACE, "aucFreeBufferCount[%d]: %d, aucMaxNumOfBuffer[%d]: %d\n", + i, prTxCtrl->rTc.aucFreeBufferCount[i], i, + prTxCtrl->rTc.aucMaxNumOfBuffer[i]); + } + DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[0]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[0]); + DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[1]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[1]); + DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[2]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[2]); + DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[3]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[3]); + DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[4]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[4]); + DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[5]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[5]); +#endif + ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC0_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC0_INDEX]); + ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC1_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC1_INDEX]); + ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC2_INDEX]); + ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC3_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC3_INDEX]); + ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC4_INDEX]); + ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC5_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC5_INDEX]); + bStatus = TRUE; + } + + return bStatus; +} /* end of nicTxReleaseResource() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Reset TC Buffer Count to initialized value +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicTxResetResource(IN P_ADAPTER_T prAdapter) +{ + P_TX_CTRL_T prTxCtrl; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicTxResetResource"); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC0_INDEX] = NIC_TX_BUFF_COUNT_TC0; + prTxCtrl->rTc.aucFreeBufferCount[TC0_INDEX] = NIC_TX_BUFF_COUNT_TC0; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC1_INDEX] = NIC_TX_BUFF_COUNT_TC1; + prTxCtrl->rTc.aucFreeBufferCount[TC1_INDEX] = NIC_TX_BUFF_COUNT_TC1; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC2_INDEX] = NIC_TX_BUFF_COUNT_TC2; + prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX] = NIC_TX_BUFF_COUNT_TC2; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC3_INDEX] = NIC_TX_BUFF_COUNT_TC3; + prTxCtrl->rTc.aucFreeBufferCount[TC3_INDEX] = NIC_TX_BUFF_COUNT_TC3; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC4_INDEX] = NIC_TX_BUFF_COUNT_TC4; + prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX] = NIC_TX_BUFF_COUNT_TC4; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC5_INDEX] = NIC_TX_BUFF_COUNT_TC5; + prTxCtrl->rTc.aucFreeBufferCount[TC5_INDEX] = NIC_TX_BUFF_COUNT_TC5; + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Driver maintain a variable that is synchronous with the usage of individual +* TC Buffer Count. This function will return the value for other component +* which needs this information for making decisions +* +* @param prAdapter Pointer to the Adapter structure. +* @param ucTC Specify the resource of TC +* +* @retval UINT_8 The number of corresponding TC number +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 nicTxGetResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC) +{ + P_TX_CTRL_T prTxCtrl; + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + ASSERT(prTxCtrl); + + if (ucTC >= TC_NUM) + return 0; + else + return prTxCtrl->rTc.aucFreeBufferCount[ucTC]; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief In this function, we'll aggregate frame(PACKET_INFO_T) +* corresponding to HIF TX port +* +* @param prAdapter Pointer to the Adapter structure. +* @param prMsduInfoListHead a link list of P_MSDU_INFO_T +* +* @retval WLAN_STATUS_SUCCESS Bus access ok. +* @retval WLAN_STATUS_FAILURE Bus access fail. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicTxMsduInfoList(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead) +{ + P_MSDU_INFO_T prMsduInfo, prNextMsduInfo; + QUE_T qDataPort0, qDataPort1; + WLAN_STATUS status; + BOOLEAN pfgIsSecOrMgmt = FALSE; + + ASSERT(prAdapter); + ASSERT(prMsduInfoListHead); + + prMsduInfo = prMsduInfoListHead; + + QUEUE_INITIALIZE(&qDataPort0); + QUEUE_INITIALIZE(&qDataPort1); + + /* Separate MSDU_INFO_T lists into 2 categories: for Port#0 & Port#1 */ + while (prMsduInfo) { + prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); +#if DBG && 0 + LOG_FUNC("nicTxMsduInfoList Acquire TC %d net %u mac len %u len %u Type %u 1x %u 11 %u\n", + prMsduInfo->ucTC, + prMsduInfo->ucNetworkType, + prMsduInfo->ucMacHeaderLength, + prMsduInfo->u2FrameLength, + prMsduInfo->ucPacketType, prMsduInfo->fgIs802_1x, prMsduInfo->fgIs802_11); + + LOG_FUNC("Dest Mac: %pM\n", prMsduInfo->aucEthDestAddr); +#endif + + /* double-check available TX resouce (need to sync with CONNSYS FW) */ + /* caller must guarantee that the TX resource is enough in the func; OR assert here */ + switch (prMsduInfo->ucTC) { + case TC0_INDEX: + case TC1_INDEX: + case TC2_INDEX: + case TC3_INDEX: + case TC5_INDEX: /* Broadcast/multicast data packets */ + QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo) = NULL; + QUEUE_INSERT_TAIL(&qDataPort0, (P_QUE_ENTRY_T) prMsduInfo); + status = nicTxAcquireResource(prAdapter, prMsduInfo->ucTC, FALSE); + ASSERT(status == WLAN_STATUS_SUCCESS) + + break; + + case TC4_INDEX: /* Command or 802.1x packets */ + QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo) = NULL; + QUEUE_INSERT_TAIL(&qDataPort1, (P_QUE_ENTRY_T) prMsduInfo); + + if ((prMsduInfo->fgIs802_1x == TRUE) || + (prMsduInfo->fgIs802_11 == TRUE)) + pfgIsSecOrMgmt = TRUE; + + status = nicTxAcquireResource(prAdapter, prMsduInfo->ucTC, pfgIsSecOrMgmt); + ASSERT(status == WLAN_STATUS_SUCCESS) + + break; + + default: + ASSERT(0); + break; + } + + prMsduInfo = prNextMsduInfo; + } + + /* send packets to HIF port0 or port1 here */ + if (qDataPort0.u4NumElem > 0) + nicTxMsduQueue(prAdapter, 0, &qDataPort0); + + if (qDataPort1.u4NumElem > 0) + nicTxMsduQueue(prAdapter, 1, &qDataPort1); + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + +#if CFG_PRINT_RTP_PROFILE +PKT_PROFILE_T rPrevRoundLastPkt; + +BOOLEAN +nicTxLifetimePrintCheckRTP(IN P_MSDU_INFO_T prPrevProfileMsduInfo, + IN P_PKT_PROFILE_T prPrevRoundLastPkt, + IN P_PKT_PROFILE_T prPktProfile, + IN OUT PBOOLEAN pfgGotFirst, IN UINT_32 u4MaxDeltaTime, IN UINT_8 ucSnToBePrinted) +{ + BOOLEAN fgPrintCurPkt = FALSE; + + if (u4MaxDeltaTime) { + /* 4 1. check delta between current round first pkt and prevous round last pkt */ + if (!*pfgGotFirst) { + *pfgGotFirst = TRUE; + + if (prPrevRoundLastPkt->fgIsValid) { + if (CHK_PROFILES_DELTA(prPktProfile, prPrevRoundLastPkt, u4MaxDeltaTime)) { + PRINT_PKT_PROFILE(prPrevRoundLastPkt, "PR"); + fgPrintCurPkt = TRUE; + } + } + } + /* 4 2. check delta between current pkt and previous pkt */ + if (prPrevProfileMsduInfo) { + if (CHK_PROFILES_DELTA(prPktProfile, &prPrevProfileMsduInfo->rPktProfile, u4MaxDeltaTime)) { + PRINT_PKT_PROFILE(&prPrevProfileMsduInfo->rPktProfile, "P"); + fgPrintCurPkt = TRUE; + } + } + /* 4 3. check delta of current pkt lifetime */ + if (CHK_PROFILE_DELTA(prPktProfile, u4MaxDeltaTime)) + fgPrintCurPkt = TRUE; + } + /* 4 4. print every X RTP packets */ +#if CFG_SUPPORT_WFD + if ((ucSnToBePrinted != 0) && (prPktProfile->u2RtpSn % ucSnToBePrinted) == 0) + fgPrintCurPkt = TRUE; +#endif + + return fgPrintCurPkt; +} + +BOOLEAN +nicTxLifetimePrintCheckSnOrder(IN P_MSDU_INFO_T prPrevProfileMsduInfo, + IN P_PKT_PROFILE_T prPrevRoundLastPkt, + IN P_PKT_PROFILE_T prPktProfile, IN OUT PBOOLEAN pfgGotFirst, IN UINT_8 ucLayer) +{ + BOOLEAN fgPrintCurPkt = FALSE; + P_PKT_PROFILE_T prTarPktProfile = NULL; + UINT_16 u2PredictSn = 0; + UINT_16 u2CurrentSn = 0; + UINT_8 aucNote[8]; + + /* 4 1. Get the target packet profile to compare */ + + /* 4 1.1 check SN between current round first pkt and prevous round last pkt */ + if ((!*pfgGotFirst) && (prPrevRoundLastPkt->fgIsValid)) { + *pfgGotFirst = TRUE; + prTarPktProfile = prPrevRoundLastPkt; + kalMemCopy(aucNote, "PR\0", 3); + } + /* 4 1.2 check SN between current pkt and previous pkt */ + else if (prPrevProfileMsduInfo) { + prTarPktProfile = &prPrevProfileMsduInfo->rPktProfile; + kalMemCopy(aucNote, "P\0", 2); + } + + if (!prTarPktProfile) + return FALSE; + /* 4 2. Check IP or RTP SN */ + switch (ucLayer) { + /* Check IP SN */ + case 0: + u2PredictSn = prTarPktProfile->u2IpSn + 1; + u2CurrentSn = prPktProfile->u2IpSn; + break; + /* Check RTP SN */ + case 1: + default: + u2PredictSn = prTarPktProfile->u2RtpSn + 1; + u2CurrentSn = prPktProfile->u2RtpSn; + break; + + } + /* 4 */ + /* 4 3. Compare SN */ + if (u2CurrentSn != u2PredictSn) { + PRINT_PKT_PROFILE(prTarPktProfile, aucNote); + fgPrintCurPkt = TRUE; + } + + return fgPrintCurPkt; +} +#endif + +VOID nicTxReturnMsduInfoProfiling(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead) +{ + P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead, prNextMsduInfo; + P_PKT_PROFILE_T prPktProfile; + UINT_16 u2MagicCode = 0; + + UINT_8 ucDebugtMode = 0; +#if CFG_PRINT_RTP_PROFILE + P_MSDU_INFO_T prPrevProfileMsduInfo = NULL; + P_PKT_PROFILE_T prPrevRoundLastPkt = &rPrevRoundLastPkt; + + BOOLEAN fgPrintCurPkt = FALSE; + BOOLEAN fgGotFirst = FALSE; + UINT_8 ucSnToBePrinted = 0; + + UINT_32 u4MaxDeltaTime = 50; /* in ms */ +#endif + +#if CFG_ENABLE_PER_STA_STATISTICS + UINT_32 u4PktPrintPeriod = 0; +#endif + +#if CFG_SUPPORT_WFD + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + + if (prAdapter->fgIsP2PRegistered) { + prWfdCfgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings; + u2MagicCode = prWfdCfgSettings->u2WfdMaximumTp; + ucDebugtMode = prAdapter->rWifiVar.prP2pFsmInfo->rWfdDebugSetting.ucWfdDebugMode; + /* if(prWfdCfgSettings->ucWfdEnable && (prWfdCfgSettings->u4WfdFlag & BIT(0))) { */ + /* u2MagicCode = 0xE040; */ + /* } */ + } +#endif + +#if CFG_PRINT_RTP_PROFILE + if ((u2MagicCode >= 0xF000)) { + ucSnToBePrinted = (UINT_8) (u2MagicCode & BITS(0, 7)); + u4MaxDeltaTime = (UINT_8) (((u2MagicCode & BITS(8, 11)) >> 8) * 10); + } else { + ucSnToBePrinted = 0; + u4MaxDeltaTime = 0; + } + +#endif + +#if CFG_ENABLE_PER_STA_STATISTICS + if ((u2MagicCode >= 0xE000) && (u2MagicCode < 0xF000)) + u4PktPrintPeriod = (UINT_32) ((u2MagicCode & BITS(0, 7)) * 32); + else + u4PktPrintPeriod = 0; +#endif + + while (prMsduInfo) { + prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); + prPktProfile = &prMsduInfo->rPktProfile; + + if (prPktProfile->fgIsValid) { + + prPktProfile->rHifTxDoneTimestamp = kalGetTimeTick(); + if (ucDebugtMode > 1) { + +#if CFG_PRINT_RTP_PROFILE +#if CFG_PRINT_RTP_SN_SKIP + fgPrintCurPkt = nicTxLifetimePrintCheckSnOrder(prPrevProfileMsduInfo, + prPrevRoundLastPkt, + prPktProfile, &fgGotFirst, 0); +#else + fgPrintCurPkt = nicTxLifetimePrintCheckRTP(prPrevProfileMsduInfo, + prPrevRoundLastPkt, + prPktProfile, + &fgGotFirst, + u4MaxDeltaTime, ucSnToBePrinted); +#endif + + /* Print current pkt profile */ + if (fgPrintCurPkt && ucDebugtMode > 1) + PRINT_PKT_PROFILE(prPktProfile, "C"); + + prPrevProfileMsduInfo = prMsduInfo; + fgPrintCurPkt = FALSE; +#endif + } +#if CFG_ENABLE_PER_STA_STATISTICS + { + P_STA_RECORD_T prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + UINT_32 u4DeltaTime; + UINT_32 u4DeltaHifTime; +#if 0 + P_QUE_MGT_T prQM = &prAdapter->rQM; +#endif + UINT_8 ucNetIndex; + + if (prStaRec) { + ucNetIndex = prStaRec->ucNetTypeIndex; + u4DeltaTime = (UINT_32) (prPktProfile->rHifTxDoneTimestamp - + prPktProfile->rHardXmitArrivalTimestamp); + u4DeltaHifTime = (UINT_32) (prPktProfile->rHifTxDoneTimestamp - + prPktProfile->rDequeueTimestamp); + prStaRec->u4TotalTxPktsNumber++; + + prStaRec->u4TotalTxPktsTime += u4DeltaTime; + prStaRec->u4TotalTxPktsHifTime += u4DeltaHifTime; + + if (u4DeltaTime > prStaRec->u4MaxTxPktsTime) + prStaRec->u4MaxTxPktsTime = u4DeltaTime; + + if (u4DeltaHifTime > prStaRec->u4MaxTxPktsHifTime) + prStaRec->u4MaxTxPktsHifTime = u4DeltaHifTime; + + + if (u4DeltaTime >= NIC_TX_TIME_THRESHOLD) + prStaRec->u4ThresholdCounter++; +#if 0 + if (u4PktPrintPeriod && (prStaRec->u4TotalTxPktsNumber >= u4PktPrintPeriod)) { + + DBGLOG(TX, TRACE, "[%u]N[%4u]A[%5u]M[%4u]T[%4u]E[%4u]\n", + prStaRec->ucIndex, + prStaRec->u4TotalTxPktsNumber, + prStaRec->u4TotalTxPktsTime / prStaRec->u4TotalTxPktsNumber, + prStaRec->u4MaxTxPktsTime, + prStaRec->u4ThresholdCounter, + prQM->au4QmTcResourceEmptyCounter[ucNetIndex][TC2_INDEX]); + + prStaRec->u4TotalTxPktsNumber = 0; + prStaRec->u4TotalTxPktsTime = 0; + prStaRec->u4MaxTxPktsTime = 0; + prStaRec->u4ThresholdCounter = 0; + prQM->au4QmTcResourceEmptyCounter[ucNetIndex][TC2_INDEX] = 0; + } +#endif + } + + } +#endif + } + + prMsduInfo = prNextMsduInfo; + }; + +#if CFG_PRINT_RTP_PROFILE + /* 4 4. record the lifetime of current round last pkt */ + if (prPrevProfileMsduInfo) { + prPktProfile = &prPrevProfileMsduInfo->rPktProfile; + prPrevRoundLastPkt->u2IpSn = prPktProfile->u2IpSn; + prPrevRoundLastPkt->u2RtpSn = prPktProfile->u2RtpSn; + prPrevRoundLastPkt->rHardXmitArrivalTimestamp = prPktProfile->rHardXmitArrivalTimestamp; + prPrevRoundLastPkt->rEnqueueTimestamp = prPktProfile->rEnqueueTimestamp; + prPrevRoundLastPkt->rDequeueTimestamp = prPktProfile->rDequeueTimestamp; + prPrevRoundLastPkt->rHifTxDoneTimestamp = prPktProfile->rHifTxDoneTimestamp; + prPrevRoundLastPkt->ucTcxFreeCount = prPktProfile->ucTcxFreeCount; + prPrevRoundLastPkt->fgIsPrinted = prPktProfile->fgIsPrinted; + prPrevRoundLastPkt->fgIsValid = TRUE; + } +#endif + + nicTxReturnMsduInfo(prAdapter, prMsduInfoListHead); + +} + +VOID nicTxLifetimeRecordEn(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN P_NATIVE_PACKET prPacket) +{ + P_PKT_PROFILE_T prPktProfile = &prMsduInfo->rPktProfile; + + /* Enable packet lifetime profiling */ + prPktProfile->fgIsValid = TRUE; + + /* Packet arrival time at kernel Hard Xmit */ + prPktProfile->rHardXmitArrivalTimestamp = GLUE_GET_PKT_ARRIVAL_TIME(prPacket); + + /* Packet enqueue time */ + prPktProfile->rEnqueueTimestamp = (OS_SYSTIME) kalGetTimeTick(); + +} + +#if CFG_PRINT_RTP_PROFILE +/* + * in: + * data RTP packet pointer + * size RTP size + * return + * 0:audio 1: video, -1:none + */ +UINT8 checkRtpAV(PUINT_8 data, UINT_32 size) +{ + PUINT_8 buf = data + 12; + + while (buf + 188 <= data + size) { + int pid = ((buf[1] << 8) & 0x1F00) | (buf[2] & 0xFF); + + if (pid == 0 || pid == 0x100 || pid == 0x1000) + buf += 188; + else if (pid == 0x1100) + return 0; + else if (pid == 0x1011) + return 1; + } + return -1; +} + +VOID +nicTxLifetimeCheckRTP(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN P_NATIVE_PACKET prPacket, IN UINT_32 u4PacketLen, IN UINT_8 ucNetworkType) +{ + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + UINT_16 u2EtherTypeLen; + PUINT_8 aucLookAheadBuf = NULL; + P_PKT_PROFILE_T prPktProfile = &prMsduInfo->rPktProfile; + + /* UINT_8 ucRtpHdrOffset = 28; */ + UINT_8 ucRtpSnOffset = 30; + /* UINT_32 u4RtpSrcPort = 15550; */ + P_TX_CTRL_T prTxCtrl; +#if CFG_SUPPORT_WFD + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + P_WFD_DBG_CFG_SETTINGS_T prWfdDbgSettings = (P_WFD_DBG_CFG_SETTINGS_T) NULL; + + BOOLEAN fgEnProfiling = FALSE; + + if (prAdapter->fgIsP2PRegistered) { + prWfdCfgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings; + prWfdDbgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdDebugSetting; +#if CFG_PRINT_RTP_SN_SKIP + if (ucNetworkType == NETWORK_TYPE_P2P_INDEX) { + fgEnProfiling = TRUE; + } else +#endif + if (((prWfdCfgSettings->u2WfdMaximumTp >= 0xF000) || + (prWfdDbgSettings->ucWfdDebugMode > 0)) && (ucNetworkType == NETWORK_TYPE_P2P_INDEX)) { + fgEnProfiling = TRUE; + } + } + + if (fgEnProfiling == FALSE) { + /* prPktProfile->fgIsValid = FALSE; */ + return; + } +#endif + + prTxCtrl = &prAdapter->rTxCtrl; + /* prPktProfile->fgIsValid = FALSE; */ + + aucLookAheadBuf = prSkb->data; + + u2EtherTypeLen = (aucLookAheadBuf[ETH_TYPE_LEN_OFFSET] << 8) | (aucLookAheadBuf[ETH_TYPE_LEN_OFFSET + 1]); + + if ((u2EtherTypeLen == ETH_P_IP) && (u4PacketLen >= LOOK_AHEAD_LEN)) { + PUINT_8 pucIpHdr = &aucLookAheadBuf[ETH_HLEN]; + UINT_16 u2tmpIpSN = 0; + UINT_8 ucIpVersion; + + ucIpVersion = (pucIpHdr[0] & IPVH_VERSION_MASK) >> IPVH_VERSION_OFFSET; + if (ucIpVersion == IPVERSION) { + if (pucIpHdr[IPV4_HDR_IP_PROTOCOL_OFFSET] == IP_PROTOCOL_UDP) { + + /* + * if(checkRtpAV(&pucIpHdr[ucRtpHdrOffset], + * (u4PacketLen - ETH_HLEN - ucRtpHdrOffset)) == 0) { + */ + + if (prPktProfile->fgIsValid == FALSE) + nicTxLifetimeRecordEn(prAdapter, prMsduInfo, prPacket); + + prPktProfile->fgIsPrinted = FALSE; + + prPktProfile->ucTcxFreeCount = prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX]; + + /* RTP SN */ + prPktProfile->u2RtpSn = pucIpHdr[ucRtpSnOffset] << 8 | pucIpHdr[ucRtpSnOffset + 1]; + + /* IP SN */ + prPktProfile->u2IpSn = pucIpHdr[IPV4_HDR_IP_IDENTIFICATION_OFFSET] << 8 | + pucIpHdr[IPV4_HDR_IP_IDENTIFICATION_OFFSET + 1]; + u2tmpIpSN = prPktProfile->u2IpSn; + if (prWfdDbgSettings->ucWfdDebugMode == 1) { + if ((u2tmpIpSN & (prWfdDbgSettings->u2WfdSNShowPeiroid)) == 0) + DBGLOG(TX, TRACE, + "RtpSn=%d IPId=%d j=%lu\n", prPktProfile->u2RtpSn, + prPktProfile->u2IpSn, jiffies); + } + /* } */ + } + } + } + +} +#endif +#if CFG_ENABLE_PER_STA_STATISTICS +VOID +nicTxLifetimeCheckByAC(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN P_NATIVE_PACKET prPacket, IN UINT_8 ucPriorityParam) +{ + switch (ucPriorityParam) { + /* BK */ + /* case 1: */ + /* case 2: */ + + /* BE */ + /* case 0: */ + /* case 3: */ + + /* VI */ + case 4: + case 5: + + /* VO */ + case 6: + case 7: + nicTxLifetimeRecordEn(prAdapter, prMsduInfo, prPacket); + break; + default: + break; + } +} + +#endif + +VOID +nicTxLifetimeCheck(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN P_NATIVE_PACKET prPacket, + IN UINT_8 ucPriorityParam, IN UINT_32 u4PacketLen, IN UINT_8 ucNetworkType) +{ + P_PKT_PROFILE_T prPktProfile = &prMsduInfo->rPktProfile; + + /* Reset packet profile */ + prPktProfile->fgIsValid = FALSE; + +#if CFG_ENABLE_PER_STA_STATISTICS + nicTxLifetimeCheckByAC(prAdapter, prMsduInfo, prPacket, ucPriorityParam); +#endif + +#if CFG_PRINT_RTP_PROFILE + nicTxLifetimeCheckRTP(prAdapter, prMsduInfo, prPacket, u4PacketLen, ucNetworkType); +#endif + +} + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief In this function, we'll write frame(PACKET_INFO_T) into HIF. +* +* @param prAdapter Pointer to the Adapter structure. +* @param ucPortIdx Port Number +* @param prQue a link list of P_MSDU_INFO_T +* +* @retval WLAN_STATUS_SUCCESS Bus access ok. +* @retval WLAN_STATUS_FAILURE Bus access fail. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicTxMsduQueue(IN P_ADAPTER_T prAdapter, UINT_8 ucPortIdx, P_QUE_T prQue) +{ + P_MSDU_INFO_T prMsduInfo, prNextMsduInfo; + HIF_TX_HEADER_T rHwTxHeader; + P_NATIVE_PACKET prNativePacket; + UINT_16 u2OverallBufferLength; + UINT_8 ucEtherTypeOffsetInWord; + PUINT_8 pucOutputBuf = (PUINT_8) NULL; /* Pointer to Transmit Data Structure Frame */ + UINT_32 u4TxHdrSize; + UINT_32 u4ValidBufSize; + UINT_32 u4TotalLength; + P_TX_CTRL_T prTxCtrl; + QUE_T rFreeQueue; +#if CFG_TCP_IP_CHKSUM_OFFLOAD + UINT_8 ucChksumFlag; +#endif + + ASSERT(prAdapter); + ASSERT(ucPortIdx < 2); + ASSERT(prQue); + + prTxCtrl = &prAdapter->rTxCtrl; + u4ValidBufSize = prAdapter->u4CoalescingBufCachedSize; + +#if CFG_HIF_STATISTICS + prTxCtrl->u4TotalTxAccessNum++; + prTxCtrl->u4TotalTxPacketNum += prQue->u4NumElem; +#endif + + QUEUE_INITIALIZE(&rFreeQueue); + + if (prQue->u4NumElem > 0) { + prMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_HEAD(prQue); + pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; + u4TotalLength = 0; + + while (prMsduInfo) { + +#if (CFG_SUPPORT_TDLS_DBG == 1) + { + struct sk_buff *prSkb = (struct sk_buff *)prMsduInfo->prPacket; + UINT8 *pkt = prSkb->data; + UINT16 u2Identifier; + + if ((*(pkt + 12) == 0x08) && (*(pkt + 13) == 0x00)) { + /* ip */ + u2Identifier = ((*(pkt + 18)) << 8) | (*(pkt + 19)); + DBGLOG(TX, TRACE, " %d\n", u2Identifier); + } + } +#endif +#if (CFG_SUPPORT_MET_PROFILING == 1) + kalMetProfilingFinish(prAdapter, prMsduInfo); +#endif + kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader)); + + prNativePacket = prMsduInfo->prPacket; + + ASSERT(prNativePacket); + + u4TxHdrSize = TX_HDR_SIZE; + + u2OverallBufferLength = ((prMsduInfo->u2FrameLength + TX_HDR_SIZE) & + (UINT_16) HIF_TX_HDR_TX_BYTE_COUNT_MASK); + + /* init TX header */ + rHwTxHeader.u2TxByteCount_UserPriority = u2OverallBufferLength; + rHwTxHeader.u2TxByteCount_UserPriority |= + ((UINT_16) prMsduInfo->ucUserPriority << HIF_TX_HDR_USER_PRIORITY_OFFSET); + + if (prMsduInfo->fgIs802_11) { + ucEtherTypeOffsetInWord = + (TX_HDR_SIZE + prMsduInfo->ucMacHeaderLength + prMsduInfo->ucLlcLength) >> 1; + } else { + ucEtherTypeOffsetInWord = ((ETHER_HEADER_LEN - ETHER_TYPE_LEN) + TX_HDR_SIZE) >> 1; + } + + rHwTxHeader.ucEtherTypeOffset = ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK; + + rHwTxHeader.ucResource_PktType_CSflags = (prMsduInfo->ucTC) << HIF_TX_HDR_RESOURCE_OFFSET; + rHwTxHeader.ucResource_PktType_CSflags |= + (UINT_8) (((prMsduInfo->ucPacketType) << HIF_TX_HDR_PACKET_TYPE_OFFSET) & + (HIF_TX_HDR_PACKET_TYPE_MASK)); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + if (prMsduInfo->eSrc == TX_PACKET_OS || prMsduInfo->eSrc == TX_PACKET_FORWARDING) { + if (prAdapter->u4CSUMFlags & + (CSUM_OFFLOAD_EN_TX_TCP | CSUM_OFFLOAD_EN_TX_UDP | CSUM_OFFLOAD_EN_TX_IP)) { + kalQueryTxChksumOffloadParam(prNativePacket, &ucChksumFlag); + + if (ucChksumFlag & TX_CS_IP_GEN) + rHwTxHeader.ucResource_PktType_CSflags |= (UINT_8) HIF_TX_HDR_IP_CSUM; + + if (ucChksumFlag & TX_CS_TCP_UDP_GEN) + rHwTxHeader.ucResource_PktType_CSflags |= (UINT_8) HIF_TX_HDR_TCP_CSUM; + } + } +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + rHwTxHeader.u2LLH = prMsduInfo->u2PalLLH; + rHwTxHeader.ucStaRecIdx = prMsduInfo->ucStaRecIndex; + rHwTxHeader.ucForwardingType_SessionID_Reserved = + (prMsduInfo->ucPsForwardingType) | ((prMsduInfo->ucPsSessionID) << + HIF_TX_HDR_PS_SESSION_ID_OFFSET) + | ((prMsduInfo->fgIsBurstEnd) ? HIF_TX_HDR_BURST_END_MASK : 0); + + rHwTxHeader.ucWlanHeaderLength = + (prMsduInfo->ucMacHeaderLength & HIF_TX_HDR_WLAN_HEADER_LEN_MASK); + rHwTxHeader.ucPktFormtId_Flags = (prMsduInfo->ucFormatID & HIF_TX_HDR_FORMAT_ID_MASK) + | ((prMsduInfo->ucNetworkType << HIF_TX_HDR_NETWORK_TYPE_OFFSET) & + HIF_TX_HDR_NETWORK_TYPE_MASK) + | ((prMsduInfo->fgIs802_1x << HIF_TX_HDR_FLAG_1X_FRAME_OFFSET) & + HIF_TX_HDR_FLAG_1X_FRAME_MASK) + | ((prMsduInfo->fgIs802_11 << HIF_TX_HDR_FLAG_802_11_FORMAT_OFFSET) & + HIF_TX_HDR_FLAG_802_11_FORMAT_MASK); + + rHwTxHeader.u2SeqNo = prMsduInfo->u2AclSN; + + if (prMsduInfo->pfTxDoneHandler) { + rHwTxHeader.ucPacketSeqNo = prMsduInfo->ucTxSeqNum; + rHwTxHeader.ucAck_BIP_BasicRate = HIF_TX_HDR_NEED_ACK; + } else { + rHwTxHeader.ucPacketSeqNo = 0; + rHwTxHeader.ucAck_BIP_BasicRate = 0; + } + + if (prMsduInfo->fgNeedTxDoneStatus == TRUE) + rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_NEED_TX_DONE_STATUS; + + if (prMsduInfo->fgIsBIP) + rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BIP; + + if (prMsduInfo->fgIsBasicRate) + rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BASIC_RATE; +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + if (prMsduInfo->rPktProfile.fgIsValid) + prMsduInfo->rPktProfile.rDequeueTimestamp = kalGetTimeTick(); +#endif + + /* record the queue time in driver */ + STATS_TX_TIME_TO_HIF(prMsduInfo, &rHwTxHeader); + wlanFillTimestamp(prAdapter, prMsduInfo->prPacket, PHASE_HIF_TX); +#if CFG_SDIO_TX_AGG + /* attach to coalescing buffer */ + kalMemCopy(pucOutputBuf + u4TotalLength, &rHwTxHeader, u4TxHdrSize); + u4TotalLength += u4TxHdrSize; + + if (prMsduInfo->eSrc == TX_PACKET_OS || prMsduInfo->eSrc == TX_PACKET_FORWARDING) + kalCopyFrame(prAdapter->prGlueInfo, prNativePacket, pucOutputBuf + u4TotalLength); + else if (prMsduInfo->eSrc == TX_PACKET_MGMT) + kalMemCopy(pucOutputBuf + u4TotalLength, prNativePacket, prMsduInfo->u2FrameLength); + else + ASSERT(0); + + u4TotalLength += ALIGN_4(prMsduInfo->u2FrameLength); + +#else + kalMemCopy(pucOutputBuf, &rHwTxHeader, u4TxHdrSize); + + /* Copy Frame Body */ + if (prMsduInfo->eSrc == TX_PACKET_OS || prMsduInfo->eSrc == TX_PACKET_FORWARDING) + kalCopyFrame(prAdapter->prGlueInfo, prNativePacket, pucOutputBuf + u4TxHdrSize); + else if (prMsduInfo->eSrc == TX_PACKET_MGMT) + kalMemCopy(pucOutputBuf + u4TxHdrSize, prNativePacket, prMsduInfo->u2FrameLength); + else + ASSERT(0); + + ASSERT(u2OverallBufferLength <= u4ValidBufSize); + + HAL_WRITE_TX_PORT(prAdapter, + ucPortIdx, + (UINT_32) u2OverallBufferLength, (PUINT_8) pucOutputBuf, u4ValidBufSize); + + /* send immediately */ +#endif + prNextMsduInfo = (P_MSDU_INFO_T) + QUEUE_GET_NEXT_ENTRY(&prMsduInfo->rQueEntry); + + if (prMsduInfo->eSrc == TX_PACKET_MGMT) { + GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum); + + if (prMsduInfo->pfTxDoneHandler == NULL) { + cnmMgtPktFree(prAdapter, prMsduInfo); + } else { + KAL_SPIN_LOCK_DECLARATION(); + DBGLOG(TX, TRACE, "Wait TxSeqNum:%d\n", prMsduInfo->ucTxSeqNum); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + QUEUE_INSERT_TAIL(&(prTxCtrl->rTxMgmtTxingQueue), (P_QUE_ENTRY_T) prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + } + } else { + /* only free MSDU when it is not a MGMT frame */ + QUEUE_INSERT_TAIL(&rFreeQueue, (P_QUE_ENTRY_T) prMsduInfo); + + if (prMsduInfo->eSrc == TX_PACKET_OS) + kalSendComplete(prAdapter->prGlueInfo, prNativePacket, WLAN_STATUS_SUCCESS); + else if (prMsduInfo->eSrc == TX_PACKET_FORWARDING) + GLUE_DEC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount); + } + + prMsduInfo = prNextMsduInfo; + } + +#if CFG_SDIO_TX_AGG + ASSERT(u4TotalLength <= u4ValidBufSize); + +#if CFG_DBG_GPIO_PINS + { + /* Start port write */ + mtk_wcn_stp_debug_gpio_assert(IDX_TX_PORT_WRITE, DBG_TIE_LOW); + kalUdelay(1); + mtk_wcn_stp_debug_gpio_assert(IDX_TX_PORT_WRITE, DBG_TIE_HIGH); + } +#endif + + /* send coalescing buffer */ + HAL_WRITE_TX_PORT(prAdapter, ucPortIdx, u4TotalLength, (PUINT_8) pucOutputBuf, u4ValidBufSize); +#endif + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE +#if CFG_SUPPORT_WFD && CFG_PRINT_RTP_PROFILE && !CFG_ENABLE_PER_STA_STATISTICS + do { + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + + prWfdCfgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings; + + if ((prWfdCfgSettings->u2WfdMaximumTp >= 0xF000)) { + /* Enable profiling */ + nicTxReturnMsduInfoProfiling(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(&rFreeQueue)); + } else { + /* Skip profiling */ + nicTxReturnMsduInfo(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(&rFreeQueue)); + } + } while (FALSE); +#else + nicTxReturnMsduInfoProfiling(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(&rFreeQueue)); +#endif +#else + /* return */ + nicTxReturnMsduInfo(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(&rFreeQueue)); +#endif + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief In this function, we'll write Command(CMD_INFO_T) into HIF. +* +* @param prAdapter Pointer to the Adapter structure. +* @param prPacketInfo Pointer of CMD_INFO_T +* @param ucTC Specify the resource of TC +* +* @retval WLAN_STATUS_SUCCESS Bus access ok. +* @retval WLAN_STATUS_FAILURE Bus access fail. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicTxCmd(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN UINT_8 ucTC) +{ + P_WIFI_CMD_T prWifiCmd; + UINT_16 u2OverallBufferLength; + PUINT_8 pucOutputBuf = (PUINT_8) NULL; /* Pointer to Transmit Data Structure Frame */ + UINT_8 ucPortIdx; + HIF_TX_HEADER_T rHwTxHeader; + P_NATIVE_PACKET prNativePacket; + UINT_8 ucEtherTypeOffsetInWord; + P_MSDU_INFO_T prMsduInfo; + P_TX_CTRL_T prTxCtrl; + BOOLEAN fgScanReqCmd = FALSE; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prTxCtrl = &prAdapter->rTxCtrl; + pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; + + /* <1> Assign Data Port */ + if (ucTC != TC4_INDEX) { + ucPortIdx = 0; + } else { + /* Broadcast/multicast data frames, 1x frames, command packets, MMPDU */ + ucPortIdx = 1; + } + wlanTraceTxCmd(prAdapter, prCmdInfo); + + if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) { + /* <2> Compose HIF_TX_HEADER */ + kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader)); + + prNativePacket = prCmdInfo->prPacket; + + ASSERT(prNativePacket); + + u2OverallBufferLength = TFCB_FRAME_PAD_TO_DW((prCmdInfo->u2InfoBufLen + TX_HDR_SIZE) + & (UINT_16) HIF_TX_HDR_TX_BYTE_COUNT_MASK); + + rHwTxHeader.u2TxByteCount_UserPriority = ((prCmdInfo->u2InfoBufLen + TX_HDR_SIZE) + & (UINT_16) HIF_TX_HDR_TX_BYTE_COUNT_MASK); + ucEtherTypeOffsetInWord = ((ETHER_HEADER_LEN - ETHER_TYPE_LEN) + TX_HDR_SIZE) >> 1; + + rHwTxHeader.ucEtherTypeOffset = ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK; + + rHwTxHeader.ucResource_PktType_CSflags = (ucTC << HIF_TX_HDR_RESOURCE_OFFSET); + + rHwTxHeader.ucStaRecIdx = prCmdInfo->ucStaRecIndex; + rHwTxHeader.ucForwardingType_SessionID_Reserved = HIF_TX_HDR_BURST_END_MASK; + + rHwTxHeader.ucWlanHeaderLength = (ETH_HLEN & HIF_TX_HDR_WLAN_HEADER_LEN_MASK); + rHwTxHeader.ucPktFormtId_Flags = + (((UINT_8) (prCmdInfo->eNetworkType) << HIF_TX_HDR_NETWORK_TYPE_OFFSET) & + HIF_TX_HDR_NETWORK_TYPE_MASK) + | ((1 << HIF_TX_HDR_FLAG_1X_FRAME_OFFSET) & HIF_TX_HDR_FLAG_1X_FRAME_MASK); + + rHwTxHeader.u2SeqNo = 0; + rHwTxHeader.ucPacketSeqNo = 0; + rHwTxHeader.ucAck_BIP_BasicRate = HIF_TX_HDR_NEED_TX_DONE_STATUS; + rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BASIC_RATE /* | HIF_TX_HDR_RTS */; + + /* <2.3> Copy HIF TX HEADER */ + kalMemCopy((PVOID)&pucOutputBuf[0], (PVOID)&rHwTxHeader, TX_HDR_SIZE); + + /* <3> Copy Frame Body Copy */ + kalCopyFrame(prAdapter->prGlueInfo, prNativePacket, pucOutputBuf + TX_HDR_SIZE); + } else if (prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) { + prMsduInfo = (P_MSDU_INFO_T) prCmdInfo->prPacket; + + ASSERT(prMsduInfo->fgIs802_11 == TRUE); + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + + /* <2> Compose HIF_TX_HEADER */ + kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader)); + + u2OverallBufferLength = ((prMsduInfo->u2FrameLength + TX_HDR_SIZE) & + (UINT_16) HIF_TX_HDR_TX_BYTE_COUNT_MASK); + + rHwTxHeader.u2TxByteCount_UserPriority = u2OverallBufferLength; + rHwTxHeader.u2TxByteCount_UserPriority |= + ((UINT_16) prMsduInfo->ucUserPriority << HIF_TX_HDR_USER_PRIORITY_OFFSET); + + ucEtherTypeOffsetInWord = (TX_HDR_SIZE + prMsduInfo->ucMacHeaderLength + prMsduInfo->ucLlcLength) >> 1; + + rHwTxHeader.ucEtherTypeOffset = ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK; + + rHwTxHeader.ucResource_PktType_CSflags = (prMsduInfo->ucTC) << HIF_TX_HDR_RESOURCE_OFFSET; + rHwTxHeader.ucResource_PktType_CSflags |= + (UINT_8) (((prMsduInfo->ucPacketType) << HIF_TX_HDR_PACKET_TYPE_OFFSET) & + (HIF_TX_HDR_PACKET_TYPE_MASK)); + + rHwTxHeader.u2LLH = prMsduInfo->u2PalLLH; + rHwTxHeader.ucStaRecIdx = prMsduInfo->ucStaRecIndex; + rHwTxHeader.ucForwardingType_SessionID_Reserved = + (prMsduInfo->ucPsForwardingType) | ((prMsduInfo->ucPsSessionID) << HIF_TX_HDR_PS_SESSION_ID_OFFSET) + | ((prMsduInfo->fgIsBurstEnd) ? HIF_TX_HDR_BURST_END_MASK : 0); + + rHwTxHeader.ucWlanHeaderLength = (prMsduInfo->ucMacHeaderLength & HIF_TX_HDR_WLAN_HEADER_LEN_MASK); + rHwTxHeader.ucPktFormtId_Flags = (prMsduInfo->ucFormatID & HIF_TX_HDR_FORMAT_ID_MASK) + | ((prMsduInfo->ucNetworkType << HIF_TX_HDR_NETWORK_TYPE_OFFSET) & HIF_TX_HDR_NETWORK_TYPE_MASK) + | ((prMsduInfo->fgIs802_1x << HIF_TX_HDR_FLAG_1X_FRAME_OFFSET) & HIF_TX_HDR_FLAG_1X_FRAME_MASK) + | ((prMsduInfo->fgIs802_11 << HIF_TX_HDR_FLAG_802_11_FORMAT_OFFSET) & + HIF_TX_HDR_FLAG_802_11_FORMAT_MASK); + + rHwTxHeader.u2SeqNo = prMsduInfo->u2AclSN; + + if (prMsduInfo->pfTxDoneHandler) { + rHwTxHeader.ucPacketSeqNo = prMsduInfo->ucTxSeqNum; + rHwTxHeader.ucAck_BIP_BasicRate = HIF_TX_HDR_NEED_ACK; + } else { + rHwTxHeader.ucPacketSeqNo = 0; + rHwTxHeader.ucAck_BIP_BasicRate = 0; + } + + if (prMsduInfo->fgIsBIP) + rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BIP; + + if (prMsduInfo->fgIsBasicRate) + rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BASIC_RATE; + /* <2.3> Copy HIF TX HEADER */ + kalMemCopy((PVOID)&pucOutputBuf[0], (PVOID)&rHwTxHeader, TX_HDR_SIZE); + + /* <3> Copy Frame Body */ + kalMemCopy(pucOutputBuf + TX_HDR_SIZE, prMsduInfo->prPacket, prMsduInfo->u2FrameLength); + + /* <4> Management Frame Post-Processing */ + GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum); + + if (prMsduInfo->pfTxDoneHandler == NULL) { + cnmMgtPktFree(prAdapter, prMsduInfo); + } else { + + DBGLOG(TX, TRACE, "Wait Cmd TxSeqNum:%d\n", prMsduInfo->ucTxSeqNum); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + QUEUE_INSERT_TAIL(&(prTxCtrl->rTxMgmtTxingQueue), (P_QUE_ENTRY_T) prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + } + } else { + prWifiCmd = (P_WIFI_CMD_T) prCmdInfo->pucInfoBuffer; + + /* <2> Compose the Header of Transmit Data Structure for CMD Packet */ + u2OverallBufferLength = + TFCB_FRAME_PAD_TO_DW((prCmdInfo->u2InfoBufLen) & (UINT_16) HIF_TX_HDR_TX_BYTE_COUNT_MASK); + + prWifiCmd->u2TxByteCount_UserPriority = u2OverallBufferLength; + prWifiCmd->ucEtherTypeOffset = 0; + prWifiCmd->ucResource_PktType_CSflags = (ucTC << HIF_TX_HDR_RESOURCE_OFFSET) + | (UINT_8) ((HIF_TX_PKT_TYPE_CMD << HIF_TX_HDR_PACKET_TYPE_OFFSET) & (HIF_TX_HDR_PACKET_TYPE_MASK)); + + /* <3> Copy CMD Header to command buffer (by using pucCoalescingBufCached) */ + kalMemCopy((PVOID)&pucOutputBuf[0], (PVOID) prCmdInfo->pucInfoBuffer, prCmdInfo->u2InfoBufLen); + + ASSERT(u2OverallBufferLength <= prAdapter->u4CoalescingBufCachedSize); + + if ((prCmdInfo->ucCID == CMD_ID_SCAN_REQ) || + (prCmdInfo->ucCID == CMD_ID_SCAN_CANCEL) || + (prCmdInfo->ucCID == CMD_ID_SCAN_REQ_V2)) { + DBGLOG(TX, INFO, "ucCmdSeqNum =%d, ucCID =%d\n", prCmdInfo->ucCmdSeqNum, prCmdInfo->ucCID); + /*record scan request tx_desciption*/ + wlanDebugScanRecord(prAdapter + , DBG_SCAN_WRITE_BEFORE); + fgScanReqCmd = TRUE; + + } + } + prCmdInfo->u4SendToFwTime = kalGetTimeTick(); + wlanDebugCommandRecodTime(prCmdInfo); + + /* <4> Write frame to data port */ + HAL_WRITE_TX_PORT(prAdapter, + ucPortIdx, + (UINT_32) u2OverallBufferLength, + (PUINT_8) pucOutputBuf, (UINT_32) prAdapter->u4CoalescingBufCachedSize); + if (fgScanReqCmd == TRUE) + /*record scan request tx_desciption*/ + wlanDebugScanRecord(prAdapter + , DBG_SCAN_WRITE_DONE); + + return WLAN_STATUS_SUCCESS; +} /* end of nicTxCmd() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will clean up all the pending frames in internal SW Queues +* by return the pending TX packet to the system. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicTxRelease(IN P_ADAPTER_T prAdapter) +{ + P_TX_CTRL_T prTxCtrl; + P_MSDU_INFO_T prMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + + nicTxFlush(prAdapter); + + /* free MSDU_INFO_T from rTxMgmtMsduInfoList */ + do { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + QUEUE_REMOVE_HEAD(&prTxCtrl->rTxMgmtTxingQueue, prMsduInfo, P_MSDU_INFO_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + if (prMsduInfo) { + /* the packet must be mgmt frame with tx done callback */ + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + + /* invoke done handler */ + prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_LIFE_TIMEOUT); + + cnmMgtPktFree(prAdapter, prMsduInfo); + } else { + break; + } + } while (TRUE); + +} /* end of nicTxRelease() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process the TX Done interrupt and pull in more pending frames in SW +* Queues for transmission. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicProcessTxInterrupt(IN P_ADAPTER_T prAdapter) +{ + P_TX_CTRL_T prTxCtrl; +#if CFG_SDIO_INTR_ENHANCE + P_SDIO_CTRL_T prSDIOCtrl; +#else + UINT_32 au4TxCount[2]; +#endif /* CFG_SDIO_INTR_ENHANCE */ + + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + prGlueInfo->IsrTxCnt++; + + /* Get the TX STATUS */ +#if CFG_SDIO_INTR_ENHANCE + + prSDIOCtrl = prAdapter->prSDIOCtrl; +#if DBG + /* dumpMemory8((PUINT_8)prSDIOCtrl, sizeof(SDIO_CTRL_T)); */ +#endif + + nicTxReleaseResource(prAdapter, (PUINT_8) &prSDIOCtrl->rTxInfo); + kalMemZero(&prSDIOCtrl->rTxInfo, sizeof(prSDIOCtrl->rTxInfo)); + +#else + + HAL_MCR_RD(prAdapter, MCR_WTSR0, &au4TxCount[0]); + HAL_MCR_RD(prAdapter, MCR_WTSR1, &au4TxCount[1]); + DBGLOG(EMU, TRACE, "MCR_WTSR0: 0x%x, MCR_WTSR1: 0x%x\n", au4TxCount[0], au4TxCount[1]); + + nicTxReleaseResource(prAdapter, (PUINT_8) au4TxCount); + +#endif /* CFG_SDIO_INTR_ENHANCE */ + + nicTxAdjustTcq(prAdapter); + + /* Indicate Service Thread */ + if (kalGetTxPendingCmdCount(prAdapter->prGlueInfo) > 0 || wlanGetTxPendingFrameCount(prAdapter) > 0) + kalSetEvent(prAdapter->prGlueInfo); + +} /* end of nicProcessTxInterrupt() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief this function frees packet of P_MSDU_INFO_T linked-list +* +* @param prAdapter Pointer to the Adapter structure. +* @param prMsduInfoList a link list of P_MSDU_INFO_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicTxFreeMsduInfoPacket(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead) +{ + P_NATIVE_PACKET prNativePacket; + P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead; + P_TX_CTRL_T prTxCtrl; + + ASSERT(prAdapter); + ASSERT(prMsduInfoListHead); + + prTxCtrl = &prAdapter->rTxCtrl; + + while (prMsduInfo) { + prNativePacket = prMsduInfo->prPacket; + + if (prMsduInfo->eSrc == TX_PACKET_OS) { + kalSendComplete(prAdapter->prGlueInfo, prNativePacket, WLAN_STATUS_FAILURE); + } else if (prMsduInfo->eSrc == TX_PACKET_MGMT) { + P_MSDU_INFO_T prTempMsduInfo = prMsduInfo; + + if (prMsduInfo->pfTxDoneHandler) + prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_DROPPED_IN_DRIVER); + prMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); + cnmMgtPktFree(prAdapter, prTempMsduInfo); + continue; + } else if (prMsduInfo->eSrc == TX_PACKET_FORWARDING) { + GLUE_DEC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount); + } + + prMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief this function returns P_MSDU_INFO_T of MsduInfoList to TxCtrl->rfreeMsduInfoList +* +* @param prAdapter Pointer to the Adapter structure. +* @param prMsduInfoList a link list of P_MSDU_INFO_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicTxReturnMsduInfo(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead) +{ + P_TX_CTRL_T prTxCtrl; + P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead, prNextMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + while (prMsduInfo) { + prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); + + switch (prMsduInfo->eSrc) { + case TX_PACKET_FORWARDING: + wlanReturnPacket(prAdapter, prMsduInfo->prPacket); + break; + case TX_PACKET_OS: + case TX_PACKET_OS_OID: + case TX_PACKET_MGMT: + default: + break; + } + + /* Reset MSDU_INFO fields */ + kalMemZero(prMsduInfo, sizeof(MSDU_INFO_T)); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + QUEUE_INSERT_TAIL(&prTxCtrl->rFreeMsduInfoList, (P_QUE_ENTRY_T) prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + prMsduInfo = prNextMsduInfo; + }; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief this function fills packet information to P_MSDU_INFO_T +* +* @param prAdapter Pointer to the Adapter structure. +* @param prMsduInfo P_MSDU_INFO_T +* @param prPacket P_NATIVE_PACKET +* +* @retval TRUE Success to extract information +* @retval FALSE Fail to extract correct information +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN nicTxFillMsduInfo(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN P_NATIVE_PACKET prPacket) +{ + P_GLUE_INFO_T prGlueInfo; + UINT_8 ucPriorityParam = 0; + UINT_8 ucMacHeaderLen; + UINT_8 aucEthDestAddr[PARAM_MAC_ADDR_LEN] = {0}; + BOOLEAN fgIs1x = FALSE; + BOOLEAN fgIsPAL = FALSE; + UINT_32 u4PacketLen = 0; + ULONG u4SysTime; + UINT_8 ucNetworkType = 0; + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + ASSERT(prGlueInfo); + + if (kalQoSFrameClassifierAndPacketInfo(prGlueInfo, + prPacket, + &ucPriorityParam, + &u4PacketLen, + aucEthDestAddr, + &fgIs1x, &fgIsPAL, &ucNetworkType, + NULL) == FALSE) { + DBGLOG(TX, WARN, "%s kalQoSFrameClassifierAndPacketInfo is false!\n", __func__); + return FALSE; + } +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + nicTxLifetimeCheck(prAdapter, prMsduInfo, prPacket, ucPriorityParam, u4PacketLen, ucNetworkType); +#endif + +#if (CFG_SUPPORT_TDLS == 1) + if (ucNetworkType == NETWORK_TYPE_P2P_INDEX && + MTKTdlsEnvP2P(prAdapter)) + MTKAutoTdlsP2P(prGlueInfo, prPacket); +#endif + /* Save the value of Priority Parameter */ + GLUE_SET_PKT_TID(prPacket, ucPriorityParam); + + if (fgIs1x) + GLUE_SET_PKT_FLAG_1X(prPacket); + + if (fgIsPAL) + GLUE_SET_PKT_FLAG_PAL(prPacket); + + ucMacHeaderLen = ETH_HLEN; + + /* Save the value of Header Length */ + GLUE_SET_PKT_HEADER_LEN(prPacket, ucMacHeaderLen); + + /* Save the value of Frame Length */ + GLUE_SET_PKT_FRAME_LEN(prPacket, (UINT_16) u4PacketLen); + + /* Save the value of Arrival Time */ + u4SysTime = (OS_SYSTIME) kalGetTimeTick(); + GLUE_SET_PKT_ARRIVAL_TIME(prPacket, u4SysTime); + + prMsduInfo->prPacket = prPacket; + prMsduInfo->fgIs802_1x = fgIs1x; + prMsduInfo->fgIs802_11 = FALSE; + prMsduInfo->ucNetworkType = ucNetworkType; + prMsduInfo->ucUserPriority = ucPriorityParam; + prMsduInfo->ucMacHeaderLength = ucMacHeaderLen; + prMsduInfo->u2FrameLength = (UINT_16) u4PacketLen; + COPY_MAC_ADDR(prMsduInfo->aucEthDestAddr, aucEthDestAddr); + + if (prSkb->len > ETH_HLEN) + STATS_TX_PKT_CALLBACK(prSkb->data, prMsduInfo); + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief this function update TCQ values by passing current status to txAdjustTcQuotas +* +* @param prAdapter Pointer to the Adapter structure. +* +* @retval WLAN_STATUS_SUCCESS Updated successfully +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicTxAdjustTcq(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4Num; + TX_TCQ_ADJUST_T rTcqAdjust; + P_TX_CTRL_T prTxCtrl; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + qmAdjustTcQuotas(prAdapter, &rTcqAdjust, &prTxCtrl->rTc); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + for (u4Num = 0; u4Num < TC_NUM; u4Num++) { + prTxCtrl->rTc.aucFreeBufferCount[u4Num] += rTcqAdjust.acVariation[u4Num]; + prTxCtrl->rTc.aucMaxNumOfBuffer[u4Num] += rTcqAdjust.acVariation[u4Num]; + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief this function flushes all packets queued in STA/AC queue +* +* @param prAdapter Pointer to the Adapter structure. +* +* @retval WLAN_STATUS_SUCCESS Flushed successfully +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS nicTxFlush(IN P_ADAPTER_T prAdapter) +{ + P_MSDU_INFO_T prMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + /* ask Per STA/AC queue to be fllushed and return all queued packets */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + prMsduInfo = qmFlushTxQueues(prAdapter); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + + if (prMsduInfo != NULL) { + nicTxFreeMsduInfoPacket(prAdapter, prMsduInfo); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_ENABLE_FW_DOWNLOAD +/*----------------------------------------------------------------------------*/ +/*! +* \brief In this function, we'll write Command(CMD_INFO_T) into HIF. +* However this function is used for INIT_CMD. +* +* In order to avoid further maintenance issues, these 2 functions are separated +* +* @param prAdapter Pointer to the Adapter structure. +* @param prPacketInfo Pointer of CMD_INFO_T +* @param ucTC Specify the resource of TC +* +* @retval WLAN_STATUS_SUCCESS Bus access ok. +* @retval WLAN_STATUS_FAILURE Bus access fail. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicTxInitCmd(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN UINT_8 ucTC) +{ + P_INIT_HIF_TX_HEADER_T prInitTxHeader; + UINT_16 u2OverallBufferLength; + PUINT_8 pucOutputBuf = (PUINT_8) NULL; /* Pointer to Transmit Data Structure Frame */ + UINT_32 ucPortIdx; + P_TX_CTRL_T prTxCtrl; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(ucTC == TC0_INDEX); + + prTxCtrl = &prAdapter->rTxCtrl; + pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; + prInitTxHeader = (P_INIT_HIF_TX_HEADER_T) prCmdInfo->pucInfoBuffer; + + /* <1> Compose the Header of Transmit Data Structure for CMD Packet */ + u2OverallBufferLength = + TFCB_FRAME_PAD_TO_DW((prCmdInfo->u2InfoBufLen) & (UINT_16) HIF_TX_HDR_TX_BYTE_COUNT_MASK); + + prInitTxHeader->u2TxByteCount = u2OverallBufferLength; + prInitTxHeader->ucEtherTypeOffset = 0; + prInitTxHeader->ucCSflags = 0; + + /* <2> Assign Data Port */ + if (ucTC != TC4_INDEX) { + ucPortIdx = 0; + } else { /* Broadcast/multicast data packets */ + ucPortIdx = 1; + } + + /* <3> Copy CMD Header to command buffer (by using pucCoalescingBufCached) */ + kalMemCopy((PVOID)&pucOutputBuf[0], (PVOID) prCmdInfo->pucInfoBuffer, prCmdInfo->u2InfoBufLen); + + ASSERT(u2OverallBufferLength <= prAdapter->u4CoalescingBufCachedSize); + + /* <4> Write frame to data port */ + HAL_WRITE_TX_PORT(prAdapter, + ucPortIdx, + (UINT_32) u2OverallBufferLength, + (PUINT_8) pucOutputBuf, (UINT_32) prAdapter->u4CoalescingBufCachedSize); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief In this function, we'll reset TX resource counter to initial value used +* in F/W download state +* +* @param prAdapter Pointer to the Adapter structure. +* +* @retval WLAN_STATUS_SUCCESS Reset is done successfully. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicTxInitResetResource(IN P_ADAPTER_T prAdapter) +{ + P_TX_CTRL_T prTxCtrl; + + DEBUGFUNC("nicTxInitResetResource"); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC0_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC0; + prTxCtrl->rTc.aucFreeBufferCount[TC0_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC0; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC1_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC1; + prTxCtrl->rTc.aucFreeBufferCount[TC1_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC1; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC2_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC2; + prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC2; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC3_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC3; + prTxCtrl->rTc.aucFreeBufferCount[TC3_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC3; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC4_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC4; + prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC4; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC5_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC5; + prTxCtrl->rTc.aucFreeBufferCount[TC5_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC5; + + return WLAN_STATUS_SUCCESS; + +} + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief this function enqueues MSDU_INFO_T into queue management, +* or command queue +* +* @param prAdapter Pointer to the Adapter structure. +* prMsduInfo Pointer to MSDU +* +* @retval WLAN_STATUS_SUCCESS Reset is done successfully. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicTxEnqueueMsdu(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_TX_CTRL_T prTxCtrl; + P_MSDU_INFO_T prNextMsduInfo, prRetMsduInfo, prMsduInfoHead; + QUE_T qDataPort0, qDataPort1; + P_CMD_INFO_T prCmdInfo; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + QUEUE_INITIALIZE(&qDataPort0); + QUEUE_INITIALIZE(&qDataPort1); + + /* check how many management frame are being queued */ + while (prMsduInfo) { + prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); + + QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo) = NULL; + + if (prMsduInfo->eSrc == TX_PACKET_MGMT) { + /* MMPDU: force stick to TC4 */ + prMsduInfo->ucTC = TC4_INDEX; + + QUEUE_INSERT_TAIL(&qDataPort1, (P_QUE_ENTRY_T) prMsduInfo); + } else { + QUEUE_INSERT_TAIL(&qDataPort0, (P_QUE_ENTRY_T) prMsduInfo); + } + + prMsduInfo = prNextMsduInfo; + } + + if (qDataPort0.u4NumElem) { + /* send to QM: queue the packet to different TX queue by policy */ + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + prRetMsduInfo = qmEnqueueTxPackets(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(&qDataPort0)); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + + /* post-process for "dropped" packets */ + if (prRetMsduInfo != NULL) { /* unable to enqueue */ + nicTxFreeMsduInfoPacket(prAdapter, prRetMsduInfo); + nicTxReturnMsduInfo(prAdapter, prRetMsduInfo); + } + } + + if (qDataPort1.u4NumElem) { + prMsduInfoHead = (P_MSDU_INFO_T) QUEUE_GET_HEAD(&qDataPort1); + + if (qDataPort1.u4NumElem > nicTxGetFreeCmdCount(prAdapter)) { + /* not enough descriptors for sending */ + u4Status = WLAN_STATUS_FAILURE; + + /* free all MSDUs */ + while (prMsduInfoHead) { + prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY(&prMsduInfoHead->rQueEntry); + + if (prMsduInfoHead->pfTxDoneHandler != NULL) { + prMsduInfoHead->pfTxDoneHandler(prAdapter, prMsduInfoHead, + TX_RESULT_DROPPED_IN_DRIVER); + } + + cnmMgtPktFree(prAdapter, prMsduInfoHead); + + prMsduInfoHead = prNextMsduInfo; + } + } else { + /* send to command queue */ + while (prMsduInfoHead) { + prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY(&prMsduInfoHead->rQueEntry); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + QUEUE_REMOVE_HEAD(&prAdapter->rFreeCmdList, prCmdInfo, P_CMD_INFO_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + + if (prCmdInfo) { + GLUE_INC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum); + + kalMemZero(prCmdInfo, sizeof(CMD_INFO_T)); + + prCmdInfo->eCmdType = COMMAND_TYPE_MANAGEMENT_FRAME; + prCmdInfo->u2InfoBufLen = prMsduInfoHead->u2FrameLength; + prCmdInfo->pucInfoBuffer = NULL; + prCmdInfo->prPacket = (P_NATIVE_PACKET) prMsduInfoHead; + prCmdInfo->ucStaRecIndex = prMsduInfoHead->ucStaRecIndex; + prCmdInfo->eNetworkType = prMsduInfoHead->ucNetworkType; + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->pfCmdTimeoutHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + + kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + } else { + /* Cmd free count is larger than expected, but allocation fail. */ + ASSERT(0); + + u4Status = WLAN_STATUS_FAILURE; + cnmMgtPktFree(prAdapter, prMsduInfoHead); + } + + prMsduInfoHead = prNextMsduInfo; + } + } + } + + /* indicate service thread for sending */ + if (prTxCtrl->i4TxMgmtPendingNum > 0 || kalGetTxPendingFrameCount(prAdapter->prGlueInfo) > 0) + kalSetEvent(prAdapter->prGlueInfo); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief this function returns available count in command queue +* +* @param prAdapter Pointer to the Adapter structure. +* +* @retval +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 nicTxGetFreeCmdCount(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + return prAdapter->rFreeCmdList.u4NumElem; +} + +VOID nicTxConfigPktOption(P_MSDU_INFO_T prMsduInfo, UINT_32 u4OptionMask, + BOOLEAN fgSetOption) +{ + /* + * prMsduInfo->fgIsBIP = fgSetOption; + * if (fgSetOption) + * prMsduInfo->u4Option |= u4OptionMask; + * else + * prMsduInfo->u4Option &= ~u4OptionMask; + */ +} + + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/p2p_nic.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/p2p_nic.c new file mode 100644 index 0000000000000..dd91db7e05930 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/p2p_nic.c @@ -0,0 +1,195 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief When Probe Rsp & Beacon frame is received and decide a P2P device, +* this function will be invoked to buffer scan result +* +* @param prAdapter Pointer to the Adapter structure. +* @param prEventScanResult Pointer of EVENT_SCAN_RESULT_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxAddP2pDevice(IN P_ADAPTER_T prAdapter, + IN P_EVENT_P2P_DEV_DISCOVER_RESULT_T prP2pResult, IN PUINT_8 pucRxIEBuf, IN UINT_16 u2RxIELength) +{ + P_P2P_INFO_T prP2pInfo = (P_P2P_INFO_T) NULL; + P_EVENT_P2P_DEV_DISCOVER_RESULT_T prTargetResult = (P_EVENT_P2P_DEV_DISCOVER_RESULT_T) NULL; + UINT_32 u4Idx = 0; + BOOLEAN bUpdate = FALSE; + + PUINT_8 pucIeBuf = (PUINT_8) NULL; + UINT_16 u2IELength = 0; + UINT_8 zeroMac[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; + + ASSERT(prAdapter); + + prP2pInfo = prAdapter->prP2pInfo; + + for (u4Idx = 0; u4Idx < prP2pInfo->u4DeviceNum; u4Idx++) { + prTargetResult = &prP2pInfo->arP2pDiscoverResult[u4Idx]; + + if (EQUAL_MAC_ADDR(prTargetResult->aucDeviceAddr, prP2pResult->aucDeviceAddr)) { + bUpdate = TRUE; + + /* Backup OLD buffer result. */ + pucIeBuf = prTargetResult->pucIeBuf; + u2IELength = prTargetResult->u2IELength; + + /* Update Device Info. */ + /* zero */ + kalMemZero(prTargetResult, sizeof(EVENT_P2P_DEV_DISCOVER_RESULT_T)); + + /* then buffer */ + kalMemCopy(prTargetResult, (PVOID) prP2pResult, sizeof(EVENT_P2P_DEV_DISCOVER_RESULT_T)); + + /* See if new IE length is longer or not. */ + if ((u2RxIELength > u2IELength) && (u2IELength != 0)) { + /* Buffer is not enough. */ + u2RxIELength = u2IELength; + } else if ((u2IELength == 0) && (u2RxIELength != 0)) { + /* RX new IE buf. */ + ASSERT(pucIeBuf == NULL); + pucIeBuf = prP2pInfo->pucCurrIePtr; + + if (((ULONG) prP2pInfo->pucCurrIePtr + (ULONG) u2RxIELength) > + (ULONG)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN]) { + /* Common Buffer is no enough. */ + u2RxIELength = + (UINT_16) ((ULONG)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN] - + (ULONG) prP2pInfo->pucCurrIePtr); + } + + /* Step to next buffer address. */ + prP2pInfo->pucCurrIePtr = + (PUINT_8) ((ULONG) prP2pInfo->pucCurrIePtr + (ULONG) u2RxIELength); + } + + /* Restore buffer pointer. */ + prTargetResult->pucIeBuf = pucIeBuf; + + if (pucRxIEBuf) { + /* If new received IE is available. + * Replace the old one & update new IE length. + */ + kalMemCopy(pucIeBuf, pucRxIEBuf, u2RxIELength); + prTargetResult->u2IELength = u2RxIELength; + } else { + /* There is no new IE information, keep the old one. */ + prTargetResult->u2IELength = u2IELength; + } + } + } + + if (!bUpdate) { + /* We would flush the whole scan result after each scan request is issued. + * If P2P device is too many, it may over the scan list. + */ + if ((u4Idx < CFG_MAX_NUM_BSS_LIST) && (UNEQUAL_MAC_ADDR(zeroMac, prP2pResult->aucDeviceAddr))) { + /* whsu:XXX */ + prTargetResult = &prP2pInfo->arP2pDiscoverResult[u4Idx]; + + /* zero */ + kalMemZero(prTargetResult, sizeof(EVENT_P2P_DEV_DISCOVER_RESULT_T)); + + /* then buffer */ + kalMemCopy(prTargetResult, (PVOID) prP2pResult, sizeof(EVENT_P2P_DEV_DISCOVER_RESULT_T)); + + /* + * printk("DVC FND %d %pM, %pM\n", + * prP2pInfo->u4DeviceNum, + * prP2pResult->aucDeviceAddr, + * prTargetResult->aucDeviceAddr); + */ + + if (u2RxIELength) { + prTargetResult->pucIeBuf = prP2pInfo->pucCurrIePtr; + + if (((ULONG) prP2pInfo->pucCurrIePtr + (ULONG) u2RxIELength) > + (ULONG)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN]) { + /* Common Buffer is no enough. */ + u2IELength = + (UINT_16) ((ULONG)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN] - + (ULONG) prP2pInfo->pucCurrIePtr); + } else { + u2IELength = u2RxIELength; + } + + prP2pInfo->pucCurrIePtr = + (PUINT_8) ((ULONG) prP2pInfo->pucCurrIePtr + (ULONG) u2IELength); + + kalMemCopy((PVOID) prTargetResult->pucIeBuf, (PVOID) pucRxIEBuf, (UINT_32) u2IELength); + prTargetResult->u2IELength = u2IELength; + } else { + prTargetResult->pucIeBuf = NULL; + prTargetResult->u2IELength = 0; + } + + prP2pInfo->u4DeviceNum++; + + } else { + /* TODO: Fixme to replace an old one. (?) */ + ASSERT(FALSE); + } + } +} /* nicRxAddP2pDevice */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/que_mgt.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/que_mgt.c new file mode 100644 index 0000000000000..1aa1f2d6b807b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/nic/que_mgt.c @@ -0,0 +1,5363 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +OS_SYSTIME g_arMissTimeout[CFG_STA_REC_NUM][CFG_RX_MAX_BA_TID_NUM]; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if ARP_MONITER_ENABLE +static UINT_16 arpMoniter; +static UINT_8 apIp[4]; +static UINT_8 gatewayIp[4]; +#endif +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static inline VOID qmDetermineStaRecIndex(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +static inline VOID +qmDequeueTxPacketsFromPerStaQueues(IN P_ADAPTER_T prAdapter, + OUT P_QUE_T prQue, + IN UINT_8 ucTC, IN UINT_8 ucCurrentAvailableQuota, IN UINT_8 ucTotalQuota); + +static inline VOID +qmDequeueTxPacketsFromPerTypeQueues(IN P_ADAPTER_T prAdapter, OUT P_QUE_T prQue, IN UINT_8 ucTC, IN UINT_8 ucMaxNum); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Init Queue Management for TX +* +* \param[in] (none) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmInit(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4QueArrayIdx; + UINT_32 i; + + P_QUE_MGT_T prQM = &prAdapter->rQM; + + /* DbgPrint("QM: Enter qmInit()\n"); */ +#if CFG_SUPPORT_QOS + prAdapter->rWifiVar.fgSupportQoS = TRUE; +#else + prAdapter->rWifiVar.fgSupportQoS = FALSE; +#endif + +#if CFG_SUPPORT_AMPDU_RX + prAdapter->rWifiVar.fgSupportAmpduRx = TRUE; +#else + prAdapter->rWifiVar.fgSupportAmpduRx = FALSE; +#endif + +#if CFG_SUPPORT_AMPDU_TX + prAdapter->rWifiVar.fgSupportAmpduTx = TRUE; +#else + prAdapter->rWifiVar.fgSupportAmpduTx = FALSE; +#endif + +#if CFG_SUPPORT_TSPEC + prAdapter->rWifiVar.fgSupportTspec = TRUE; +#else + prAdapter->rWifiVar.fgSupportTspec = FALSE; +#endif + +#if CFG_SUPPORT_UAPSD + prAdapter->rWifiVar.fgSupportUAPSD = TRUE; +#else + prAdapter->rWifiVar.fgSupportUAPSD = FALSE; +#endif + +#if CFG_SUPPORT_UL_PSMP + prAdapter->rWifiVar.fgSupportULPSMP = TRUE; +#else + prAdapter->rWifiVar.fgSupportULPSMP = FALSE; +#endif + +#if CFG_SUPPORT_RX_SGI + prAdapter->rWifiVar.u8SupportRxSgi20 = 0; + prAdapter->rWifiVar.u8SupportRxSgi40 = 0; +#else + prAdapter->rWifiVar.u8SupportRxSgi20 = 2; + prAdapter->rWifiVar.u8SupportRxSgi40 = 2; +#endif + +#if CFG_SUPPORT_RX_HT_GF + prAdapter->rWifiVar.u8SupportRxGf = 0; +#else + prAdapter->rWifiVar.u8SupportRxGf = 2; +#endif + + /* 4 <2> Initialize other TX queues (queues not in STA_RECs) */ + for (u4QueArrayIdx = 0; u4QueArrayIdx < NUM_OF_PER_TYPE_TX_QUEUES; u4QueArrayIdx++) + QUEUE_INITIALIZE(&(prQM->arTxQueue[u4QueArrayIdx])); + + /* 4 <3> Initialize the RX BA table and RX queues */ + /* Initialize the RX Reordering Parameters and Queues */ + for (u4QueArrayIdx = 0; u4QueArrayIdx < CFG_NUM_OF_RX_BA_AGREEMENTS; u4QueArrayIdx++) { + prQM->arRxBaTable[u4QueArrayIdx].fgIsValid = FALSE; + QUEUE_INITIALIZE(&(prQM->arRxBaTable[u4QueArrayIdx].rReOrderQue)); +#if CFG_RX_BA_REORDERING_ENHANCEMENT + QUEUE_INITIALIZE(&(prQM->arRxBaTable[u4QueArrayIdx].rNoNeedWaitQue)); +#endif + prQM->arRxBaTable[u4QueArrayIdx].u2WinStart = 0xFFFF; + prQM->arRxBaTable[u4QueArrayIdx].u2WinEnd = 0xFFFF; + + prQM->arRxBaTable[u4QueArrayIdx].fgIsWaitingForPktWithSsn = FALSE; + prQM->arRxBaTable[u4QueArrayIdx].fgHasBubble = FALSE; + cnmTimerInitTimer(prAdapter, + &(prQM->arRxBaTable[u4QueArrayIdx].rReorderBubbleTimer), + (PFN_MGMT_TIMEOUT_FUNC) qmHandleReorderBubbleTimeout, + (ULONG) (&prQM->arRxBaTable[u4QueArrayIdx])); + + } + prQM->ucRxBaCount = 0; + + kalMemSet(&g_arMissTimeout, 0, sizeof(g_arMissTimeout)); + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + /* 4 <4> Initialize TC resource control variables */ + for (i = 0; i < TC_NUM; i++) + prQM->au4AverageQueLen[i] = 0; + prQM->u4TimeToAdjustTcResource = QM_INIT_TIME_TO_ADJUST_TC_RSC; + prQM->u4TimeToUpdateQueLen = QM_INIT_TIME_TO_UPDATE_QUE_LEN; + prQM->u4TxNumOfVi = 0; + prQM->u4TxNumOfVo = 0; + +/* ASSERT(prQM->u4TimeToAdjust && prQM->u4TimeToUpdateQueLen); */ + + /* 1 20 1 1 4 1 */ + prQM->au4CurrentTcResource[TC0_INDEX] = NIC_TX_BUFF_COUNT_TC0; + prQM->au4CurrentTcResource[TC1_INDEX] = NIC_TX_BUFF_COUNT_TC1; + prQM->au4CurrentTcResource[TC2_INDEX] = NIC_TX_BUFF_COUNT_TC2; + prQM->au4CurrentTcResource[TC3_INDEX] = NIC_TX_BUFF_COUNT_TC3; + prQM->au4CurrentTcResource[TC4_INDEX] = NIC_TX_BUFF_COUNT_TC4; /* Not adjustable (TX port 1) */ + prQM->au4CurrentTcResource[TC5_INDEX] = NIC_TX_BUFF_COUNT_TC5; + DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC0 = %d\n", NIC_TX_BUFF_COUNT_TC0); + DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC1 = %d\n", NIC_TX_BUFF_COUNT_TC1); + DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC2 = %d\n", NIC_TX_BUFF_COUNT_TC2); + DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC3 = %d\n", NIC_TX_BUFF_COUNT_TC3); + DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC4 = %d\n", NIC_TX_BUFF_COUNT_TC4); + DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC5 = %d\n", NIC_TX_BUFF_COUNT_TC5); + + /* 1 1 1 1 2 1 */ + prQM->au4MinReservedTcResource[TC0_INDEX] = QM_MIN_RESERVED_TC0_RESOURCE; + prQM->au4MinReservedTcResource[TC1_INDEX] = QM_MIN_RESERVED_TC1_RESOURCE; + prQM->au4MinReservedTcResource[TC2_INDEX] = QM_MIN_RESERVED_TC2_RESOURCE; + prQM->au4MinReservedTcResource[TC3_INDEX] = QM_MIN_RESERVED_TC3_RESOURCE; + prQM->au4MinReservedTcResource[TC4_INDEX] = QM_MIN_RESERVED_TC4_RESOURCE; /* Not adjustable (TX port 1) */ + prQM->au4MinReservedTcResource[TC5_INDEX] = QM_MIN_RESERVED_TC5_RESOURCE; + + /* 4 4 6 6 2 4 */ + prQM->au4GuaranteedTcResource[TC0_INDEX] = QM_GUARANTEED_TC0_RESOURCE; + prQM->au4GuaranteedTcResource[TC1_INDEX] = QM_GUARANTEED_TC1_RESOURCE; + prQM->au4GuaranteedTcResource[TC2_INDEX] = QM_GUARANTEED_TC2_RESOURCE; + prQM->au4GuaranteedTcResource[TC3_INDEX] = QM_GUARANTEED_TC3_RESOURCE; + prQM->au4GuaranteedTcResource[TC4_INDEX] = QM_GUARANTEED_TC4_RESOURCE; + prQM->au4GuaranteedTcResource[TC5_INDEX] = QM_GUARANTEED_TC5_RESOURCE; + + prQM->fgTcResourcePostAnnealing = FALSE; + + ASSERT(QM_INITIAL_RESIDUAL_TC_RESOURCE < 64); +#endif + +#if QM_TEST_MODE + prQM->u4PktCount = 0; + +#if QM_TEST_FAIR_FORWARDING + + prQM->u4CurrentStaRecIndexToEnqueue = 0; + { + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + P_STA_RECORD_T prStaRec; + + /* Irrelevant in case this STA is an AIS AP (see qmDetermineStaRecIndex()) */ + aucMacAddr[0] = 0x11; + aucMacAddr[1] = 0x22; + aucMacAddr[2] = 0xAA; + aucMacAddr[3] = 0xBB; + aucMacAddr[4] = 0xCC; + aucMacAddr[5] = 0xDD; + + prStaRec = &prAdapter->arStaRec[1]; + ASSERT(prStaRec); + + prStaRec->fgIsValid = TRUE; + prStaRec->fgIsQoS = TRUE; + prStaRec->fgIsInPS = FALSE; + prStaRec->ucPsSessionID = 0xFF; + prStaRec->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + prStaRec->fgIsAp = TRUE; + COPY_MAC_ADDR((prStaRec)->aucMacAddr, aucMacAddr); + + } + +#endif + +#endif + +#if QM_FORWARDING_FAIRNESS + { + UINT_32 i; + + for (i = 0; i < NUM_OF_PER_STA_TX_QUEUES; i++) { + prQM->au4ForwardCount[i] = 0; + prQM->au4HeadStaRecIndex[i] = 0; + } + } +#endif + +#if QM_TC_RESOURCE_EMPTY_COUNTER + kalMemZero(prQM->au4QmTcResourceEmptyCounter, sizeof(prQM->au4QmTcResourceEmptyCounter)); +#endif + +} + +#if QM_TEST_MODE +VOID qmTestCases(IN P_ADAPTER_T prAdapter) +{ + P_QUE_MGT_T prQM = &prAdapter->rQM; + + DbgPrint("QM: ** TEST MODE **\n"); + + if (QM_TEST_STA_REC_DETERMINATION) { + if (prAdapter->arStaRec[0].fgIsValid) { + prAdapter->arStaRec[0].fgIsValid = FALSE; + DbgPrint("QM: (Test) Deactivate STA_REC[0]\n"); + } else { + prAdapter->arStaRec[0].fgIsValid = TRUE; + DbgPrint("QM: (Test) Activate STA_REC[0]\n"); + } + } + + if (QM_TEST_STA_REC_DEACTIVATION) { + /* Note that QM_STA_REC_HARD_CODING shall be set to 1 for this test */ + + if (prAdapter->arStaRec[0].fgIsValid) { + + DbgPrint("QM: (Test) Deactivate STA_REC[0]\n"); + qmDeactivateStaRec(prAdapter, 0); + } else { + + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + + /* Irrelevant in case this STA is an AIS AP (see qmDetermineStaRecIndex()) */ + aucMacAddr[0] = 0x11; + aucMacAddr[1] = 0x22; + aucMacAddr[2] = 0xAA; + aucMacAddr[3] = 0xBB; + aucMacAddr[4] = 0xCC; + aucMacAddr[5] = 0xDD; + + DbgPrint("QM: (Test) Activate STA_REC[0]\n"); + qmActivateStaRec(prAdapter, /* Adapter pointer */ + 0, /* STA_REC index from FW */ + TRUE, /* fgIsQoS */ + NETWORK_TYPE_AIS_INDEX, /* Network type */ + TRUE, /* fgIsAp */ + aucMacAddr /* MAC address */ + ); + } + } + + if (QM_TEST_FAIR_FORWARDING) { + if (prAdapter->arStaRec[1].fgIsValid) { + prQM->u4CurrentStaRecIndexToEnqueue++; + prQM->u4CurrentStaRecIndexToEnqueue %= 2; + DbgPrint("QM: (Test) Switch to STA_REC[%u]\n", prQM->u4CurrentStaRecIndexToEnqueue); + } + } + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Activate a STA_REC +* +* \param[in] prAdapter Pointer to the Adapter instance +* \param[in] u4StaRecIdx The index of the STA_REC +* \param[in] fgIsQoS Set to TRUE if this is a QoS STA +* \param[in] pucMacAddr The MAC address of the STA +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmActivateStaRec(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + + /* 4 <1> Deactivate first */ + ASSERT(prStaRec); + + if (prStaRec->fgIsValid) { /* The STA_REC has been activated */ + DBGLOG(QM, WARN, "QM: (WARNING) Activating a STA_REC which has been activated\n"); + DBGLOG(QM, WARN, "QM: (WARNING) Deactivating a STA_REC before re-activating\n"); + /* To flush TX/RX queues and del RX BA agreements */ + qmDeactivateStaRec(prAdapter, prStaRec->ucIndex); + } + /* 4 <2> Activate the STA_REC */ + /* Init the STA_REC */ + prStaRec->fgIsValid = TRUE; + prStaRec->fgIsInPS = FALSE; + prStaRec->ucPsSessionID = 0xFF; + prStaRec->fgIsAp = (IS_AP_STA(prStaRec)) ? TRUE : FALSE; + + if ((prStaRec->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) && secWpaEnabledInAis(prAdapter)) { + if (prStaRec->fgIsTxKeyReady) + prStaRec->fgIsTxAllowed = TRUE; + } else + prStaRec->fgIsTxAllowed = TRUE; + /* Done in qmInit() or qmDeactivateStaRec() */ +#if 0 + /* At the beginning, no RX BA agreements have been established */ + for (i = 0; i < CFG_RX_MAX_BA_TID_NUM; i++) + (prStaRec->aprRxReorderParamRefTbl)[i] = NULL; +#endif + + DBGLOG(QM, TRACE, "QM: +STA[%u]\n", (UINT_32) prStaRec->ucIndex); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Deactivate a STA_REC +* +* \param[in] prAdapter Pointer to the Adapter instance +* \param[in] u4StaRecIdx The index of the STA_REC +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmDeactivateStaRec(IN P_ADAPTER_T prAdapter, IN UINT_32 u4StaRecIdx) +{ + P_STA_RECORD_T prStaRec; + UINT_32 i; + P_MSDU_INFO_T prFlushedTxPacketList = NULL; + + ASSERT(u4StaRecIdx < CFG_NUM_OF_STA_RECORD); + + prStaRec = &prAdapter->arStaRec[u4StaRecIdx]; + ASSERT(prStaRec); + + /* 4<1> Flush TX queues */ + prFlushedTxPacketList = qmFlushStaTxQueues(prAdapter, u4StaRecIdx); + + if (prFlushedTxPacketList) + wlanProcessQueuedMsduInfo(prAdapter, prFlushedTxPacketList); + /* 4 <2> Flush RX queues and delete RX BA agreements */ + for (i = 0; i < CFG_RX_MAX_BA_TID_NUM; i++) { + /* Delete the RX BA entry with TID = i */ + qmDelRxBaEntry(prAdapter, (UINT_8) u4StaRecIdx, (UINT_8) i, FALSE); + } + + /* 4 <3> Deactivate the STA_REC */ + prStaRec->fgIsValid = FALSE; + prStaRec->fgIsInPS = FALSE; + prStaRec->fgIsTxAllowed = FALSE; + + /* To reduce printk for IOT sta to connect all the time, */ + /* DBGLOG(QM, INFO, ("QM: -STA[%ld]\n", u4StaRecIdx)); */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Deactivate a STA_REC +* +* \param[in] prAdapter Pointer to the Adapter instance +* \param[in] u4StaRecIdx The index of the network +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ + +VOID qmFreeAllByNetType(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) +{ + + P_QUE_MGT_T prQM; + P_QUE_T prQue; + QUE_T rNeedToFreeQue; + QUE_T rTempQue; + P_QUE_T prNeedToFreeQue; + P_QUE_T prTempQue; + P_MSDU_INFO_T prMsduInfo; + + prQM = &prAdapter->rQM; + prQue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST]; + + QUEUE_INITIALIZE(&rNeedToFreeQue); + QUEUE_INITIALIZE(&rTempQue); + + prNeedToFreeQue = &rNeedToFreeQue; + prTempQue = &rTempQue; + + QUEUE_MOVE_ALL(prTempQue, prQue); + + QUEUE_REMOVE_HEAD(prTempQue, prMsduInfo, P_MSDU_INFO_T); + while (prMsduInfo) { + + if (prMsduInfo->ucNetworkType == eNetworkTypeIdx) { + /* QUEUE_INSERT_TAIL */ + QUEUE_INSERT_TAIL(prNeedToFreeQue, (P_QUE_ENTRY_T) prMsduInfo); + } else { + /* QUEUE_INSERT_TAIL */ + QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prMsduInfo); + } + + QUEUE_REMOVE_HEAD(prTempQue, prMsduInfo, P_MSDU_INFO_T); + } + if (QUEUE_IS_NOT_EMPTY(prNeedToFreeQue)) + wlanProcessQueuedMsduInfo(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(prNeedToFreeQue)); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Flush all TX queues +* +* \param[in] (none) +* +* \return The flushed packets (in a list of MSDU_INFOs) +*/ +/*----------------------------------------------------------------------------*/ +P_MSDU_INFO_T qmFlushTxQueues(IN P_ADAPTER_T prAdapter) +{ + UINT_8 ucStaArrayIdx; + UINT_8 ucQueArrayIdx; + + P_MSDU_INFO_T prMsduInfoListHead; + P_MSDU_INFO_T prMsduInfoListTail; + + P_QUE_MGT_T prQM = &prAdapter->rQM; + + DBGLOG(QM, TRACE, "QM: Enter qmFlushTxQueues()\n"); + + prMsduInfoListHead = NULL; + prMsduInfoListTail = NULL; + + /* Concatenate all MSDU_INFOs in per-STA queues */ + for (ucStaArrayIdx = 0; ucStaArrayIdx < CFG_NUM_OF_STA_RECORD; ucStaArrayIdx++) { + + /* Always check each STA_REC when flushing packets no matter it is inactive or active */ +#if 0 + if (!prAdapter->arStaRec[ucStaArrayIdx].fgIsValid) + continue; /* Continue to check the next STA_REC */ +#endif + + for (ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_STA_TX_QUEUES; ucQueArrayIdx++) { + if (QUEUE_IS_EMPTY(&(prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]))) + continue; /* Continue to check the next TX queue of the same STA */ + + if (!prMsduInfoListHead) { + + /* The first MSDU_INFO is found */ + prMsduInfoListHead = (P_MSDU_INFO_T) + QUEUE_GET_HEAD(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]); + prMsduInfoListTail = (P_MSDU_INFO_T) + QUEUE_GET_TAIL(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]); + } else { + /* Concatenate the MSDU_INFO list with the existing list */ + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, + QUEUE_GET_HEAD(&prAdapter-> + arStaRec[ucStaArrayIdx].arTxQueue + [ucQueArrayIdx])); + + prMsduInfoListTail = (P_MSDU_INFO_T) + QUEUE_GET_TAIL(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]); + } + + QUEUE_INITIALIZE(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]); + } + } + + /* Flush per-Type queues */ + for (ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_TYPE_TX_QUEUES; ucQueArrayIdx++) { + + if (QUEUE_IS_EMPTY(&(prQM->arTxQueue[ucQueArrayIdx]))) + continue; /* Continue to check the next TX queue of the same STA */ + + if (!prMsduInfoListHead) { + + /* The first MSDU_INFO is found */ + prMsduInfoListHead = (P_MSDU_INFO_T) + QUEUE_GET_HEAD(&prQM->arTxQueue[ucQueArrayIdx]); + prMsduInfoListTail = (P_MSDU_INFO_T) + QUEUE_GET_TAIL(&prQM->arTxQueue[ucQueArrayIdx]); + } else { + /* Concatenate the MSDU_INFO list with the existing list */ + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, QUEUE_GET_HEAD(&prQM->arTxQueue[ucQueArrayIdx])); + + prMsduInfoListTail = (P_MSDU_INFO_T) + QUEUE_GET_TAIL(&prQM->arTxQueue[ucQueArrayIdx]); + } + + QUEUE_INITIALIZE(&prQM->arTxQueue[ucQueArrayIdx]); + + } + + if (prMsduInfoListTail) { + /* Terminate the MSDU_INFO list with a NULL pointer */ + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, NULL); + } + + return prMsduInfoListHead; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Flush TX packets for a particular STA +* +* \param[in] u4StaRecIdx STA_REC index +* +* \return The flushed packets (in a list of MSDU_INFOs) +*/ +/*----------------------------------------------------------------------------*/ +P_MSDU_INFO_T qmFlushStaTxQueues(IN P_ADAPTER_T prAdapter, IN UINT_32 u4StaRecIdx) +{ + UINT_8 ucQueArrayIdx; + P_MSDU_INFO_T prMsduInfoListHead; + P_MSDU_INFO_T prMsduInfoListTail; + P_STA_RECORD_T prStaRec; + + /* To reduce printk for IOT sta to connect all the time, */ + /* DBGLOG(QM, TRACE, ("QM: Enter qmFlushStaTxQueues(%ld)\n", u4StaRecIdx)); */ + + ASSERT(u4StaRecIdx < CFG_NUM_OF_STA_RECORD); + + prMsduInfoListHead = NULL; + prMsduInfoListTail = NULL; + + prStaRec = &prAdapter->arStaRec[u4StaRecIdx]; + ASSERT(prStaRec); + + /* No matter whether this is an activated STA_REC, do flush */ +#if 0 + if (!prStaRec->fgIsValid) + return NULL; +#endif + + /* Concatenate all MSDU_INFOs in TX queues of this STA_REC */ + for (ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_STA_TX_QUEUES; ucQueArrayIdx++) { + if (QUEUE_IS_EMPTY(&(prStaRec->arTxQueue[ucQueArrayIdx]))) + continue; + + if (!prMsduInfoListHead) { + /* The first MSDU_INFO is found */ + prMsduInfoListHead = (P_MSDU_INFO_T) + QUEUE_GET_HEAD(&prStaRec->arTxQueue[ucQueArrayIdx]); + prMsduInfoListTail = (P_MSDU_INFO_T) + QUEUE_GET_TAIL(&prStaRec->arTxQueue[ucQueArrayIdx]); + } else { + /* Concatenate the MSDU_INFO list with the existing list */ + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, + QUEUE_GET_HEAD(&prStaRec->arTxQueue[ucQueArrayIdx])); + + prMsduInfoListTail = (P_MSDU_INFO_T) QUEUE_GET_TAIL(&prStaRec->arTxQueue[ucQueArrayIdx]); + } + + QUEUE_INITIALIZE(&prStaRec->arTxQueue[ucQueArrayIdx]); + + } + +#if 0 + if (prMsduInfoListTail) { + /* Terminate the MSDU_INFO list with a NULL pointer */ + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, nicGetPendingStaMMPDU(prAdapter, (UINT_8) u4StaRecIdx)); + } else { + prMsduInfoListHead = nicGetPendingStaMMPDU(prAdapter, (UINT_8) u4StaRecIdx); + } +#endif + + return prMsduInfoListHead; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Flush RX packets +* +* \param[in] (none) +* +* \return The flushed packets (in a list of SW_RFBs) +*/ +/*----------------------------------------------------------------------------*/ +P_SW_RFB_T qmFlushRxQueues(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i; + P_SW_RFB_T prSwRfbListHead; + P_SW_RFB_T prSwRfbListTail; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + prSwRfbListHead = prSwRfbListTail = NULL; + + DBGLOG(QM, TRACE, "QM: Enter qmFlushRxQueues()\n"); + + for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) { + if (QUEUE_IS_NOT_EMPTY(&(prQM->arRxBaTable[i].rReOrderQue))) { + if (!prSwRfbListHead) { + + /* The first MSDU_INFO is found */ + prSwRfbListHead = (P_SW_RFB_T) + QUEUE_GET_HEAD(&(prQM->arRxBaTable[i].rReOrderQue)); + prSwRfbListTail = (P_SW_RFB_T) + QUEUE_GET_TAIL(&(prQM->arRxBaTable[i].rReOrderQue)); + } else { + /* Concatenate the MSDU_INFO list with the existing list */ + QM_TX_SET_NEXT_MSDU_INFO(prSwRfbListTail, + QUEUE_GET_HEAD(&(prQM->arRxBaTable[i].rReOrderQue))); + + prSwRfbListTail = (P_SW_RFB_T) + QUEUE_GET_TAIL(&(prQM->arRxBaTable[i].rReOrderQue)); + } + + QUEUE_INITIALIZE(&(prQM->arRxBaTable[i].rReOrderQue)); + + } else { + continue; + } + } + + if (prSwRfbListTail) { + /* Terminate the MSDU_INFO list with a NULL pointer */ + QM_TX_SET_NEXT_SW_RFB(prSwRfbListTail, NULL); + } + return prSwRfbListHead; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Flush RX packets with respect to a particular STA +* +* \param[in] u4StaRecIdx STA_REC index +* \param[in] u4Tid TID +* +* \return The flushed packets (in a list of SW_RFBs) +*/ +/*----------------------------------------------------------------------------*/ +P_SW_RFB_T qmFlushStaRxQueue(IN P_ADAPTER_T prAdapter, IN UINT_32 u4StaRecIdx, IN UINT_32 u4Tid) +{ + /* UINT_32 i; */ + P_SW_RFB_T prSwRfbListHead; + P_SW_RFB_T prSwRfbListTail; + P_RX_BA_ENTRY_T prReorderQueParm; + P_STA_RECORD_T prStaRec; + + DBGLOG(QM, TRACE, "QM: Enter qmFlushStaRxQueues(%u)\n", u4StaRecIdx); + + prSwRfbListHead = prSwRfbListTail = NULL; + + prStaRec = &prAdapter->arStaRec[u4StaRecIdx]; + ASSERT(prStaRec); + + /* No matter whether this is an activated STA_REC, do flush */ +#if 0 + if (!prStaRec->fgIsValid) + return NULL; +#endif + + /* Obtain the RX BA Entry pointer */ + prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[u4Tid]); + + /* Note: For each queued packet, prCurrSwRfb->eDst equals RX_PKT_DESTINATION_HOST */ + if (prReorderQueParm) { + + if (QUEUE_IS_NOT_EMPTY(&(prReorderQueParm->rReOrderQue))) { + + prSwRfbListHead = (P_SW_RFB_T) + QUEUE_GET_HEAD(&(prReorderQueParm->rReOrderQue)); + prSwRfbListTail = (P_SW_RFB_T) + QUEUE_GET_TAIL(&(prReorderQueParm->rReOrderQue)); + + QUEUE_INITIALIZE(&(prReorderQueParm->rReOrderQue)); + + } + } + + if (prSwRfbListTail) { + /* Terminate the MSDU_INFO list with a NULL pointer */ + QM_TX_SET_NEXT_SW_RFB(prSwRfbListTail, NULL); + } + return prSwRfbListHead; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Enqueue TX packets +* +* \param[in] prMsduInfoListHead Pointer to the list of TX packets +* +* \return The freed packets, which are not enqueued +*/ +/*----------------------------------------------------------------------------*/ +P_MSDU_INFO_T qmEnqueueTxPackets(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead) +{ + P_MSDU_INFO_T prMsduInfoReleaseList; + P_MSDU_INFO_T prCurrentMsduInfo; + P_MSDU_INFO_T prNextMsduInfo; + + P_STA_RECORD_T prStaRec; + QUE_T rNotEnqueuedQue; + P_QUE_T prTxQue = &rNotEnqueuedQue; + + UINT_8 ucPacketType; + UINT_8 ucTC; + P_QUE_MGT_T prQM = &prAdapter->rQM; + UINT_8 aucNextUP[WMM_AC_INDEX_NUM] = { 1 /* BEtoBK */, 1 /*na */, 0 /*VItoBE */, 4 /*VOtoVI */}; +#if QM_TC_RESOURCE_EMPTY_COUNTER + P_TX_CTRL_T prTxCtrl = NULL; +#endif + UINT_16 u2ActivedTspec = 0; + + DBGLOG(QM, LOUD, "Enter qmEnqueueTxPackets\n"); + + ASSERT(prMsduInfoListHead); + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + /* UINT_32 i; */ + /* 4 <0> Update TC resource control related variables */ + /* Keep track of the queue length */ + if (--prQM->u4TimeToUpdateQueLen == 0) { /* -- only here */ + prQM->u4TimeToUpdateQueLen = QM_INIT_TIME_TO_UPDATE_QUE_LEN; + qmUpdateAverageTxQueLen(prAdapter); + } +#endif + + /* Push TX packets into STA_REC (for UNICAST) or prAdapter->rQM (for BMCAST) */ + prStaRec = NULL; + prMsduInfoReleaseList = NULL; + prCurrentMsduInfo = NULL; + QUEUE_INITIALIZE(&rNotEnqueuedQue); + prNextMsduInfo = prMsduInfoListHead; + u2ActivedTspec = wmmHasActiveTspec(&prAdapter->rWifiVar.rWmmInfo); + + do { + P_BSS_INFO_T prBssInfo; + BOOLEAN fgCheckACMAgain; + ENUM_WMM_ACI_T eAci = WMM_AC_BE_INDEX; + + prCurrentMsduInfo = prNextMsduInfo; + prNextMsduInfo = QM_TX_GET_NEXT_MSDU_INFO(prCurrentMsduInfo); + ucTC = TC1_INDEX; + + /* 4 <1> Lookup the STA_REC index */ + /* The ucStaRecIndex will be set in this function */ + qmDetermineStaRecIndex(prAdapter, prCurrentMsduInfo); + ucPacketType = HIF_TX_PACKET_TYPE_DATA; + + STATS_ENV_REPORT_DETECT(prAdapter, prCurrentMsduInfo->ucStaRecIndex); + + DBGLOG(QM, LOUD, "***** ucStaRecIndex = %d *****\n", prCurrentMsduInfo->ucStaRecIndex); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prCurrentMsduInfo->ucNetworkType]); + +#if (CONF_HIF_LOOPBACK_AUTO == 0) + if (IS_NET_ACTIVE(prAdapter, prCurrentMsduInfo->ucNetworkType)) +#else + /* force to send the loopback test packet */ + SET_NET_ACTIVE(prAdapter, prCurrentMsduInfo->ucNetworkType); + prCurrentMsduInfo->ucStaRecIndex = STA_REC_INDEX_BMCAST; + ucPacketType = HIF_TX_PKT_TYPE_HIF_LOOPBACK; +#endif /* End of CONF_HIF_LOOPBACK_AUTO */ + { + switch (prCurrentMsduInfo->ucStaRecIndex) { + case STA_REC_INDEX_BMCAST: + prTxQue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST]; + ucTC = TC5_INDEX; +#if 0 + if (prCurrentMsduInfo->ucNetworkType == NETWORK_TYPE_P2P_INDEX + && prCurrentMsduInfo->eSrc != TX_PACKET_MGMT) { + if (LINK_IS_EMPTY + (&prAdapter->rWifiVar. + arBssInfo[NETWORK_TYPE_P2P_INDEX].rStaRecOfClientList)) { + prTxQue = &rNotEnqueuedQue; + TX_INC_CNT(&prAdapter->rTxCtrl, TX_AP_BORADCAST_DROP); + } + } +#endif + + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_23); + break; + + case STA_REC_INDEX_NOT_FOUND: + ucTC = TC5_INDEX; + + if (prCurrentMsduInfo->eSrc == TX_PACKET_FORWARDING) { + + /* if the packet is the forward type. the packet should be freed */ + DBGLOG(QM, TRACE, "Forwarding packet but Sta is STA_REC_INDEX_NOT_FOUND\n"); + /* prTxQue = &rNotEnqueuedQue; */ + } + prTxQue = &prQM->arTxQueue[TX_QUEUE_INDEX_NO_STA_REC]; + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_24); + + break; + + default: + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prCurrentMsduInfo->ucStaRecIndex); + + if (!prStaRec) { + DBGLOG(QM, ERROR, "prStaRec is NULL\n"); + break; + } + ASSERT(prStaRec->fgIsValid); + + if (prCurrentMsduInfo->ucUserPriority < 8) { + QM_DBG_CNT_INC(prQM, prCurrentMsduInfo->ucUserPriority + 15); + /* QM_DBG_CNT_15 *//* QM_DBG_CNT_16 *//* QM_DBG_CNT_17 *//* QM_DBG_CNT_18 */ + /* QM_DBG_CNT_19 *//* QM_DBG_CNT_20 *//* QM_DBG_CNT_21 *//* QM_DBG_CNT_22 */ + } + + eAci = WMM_AC_BE_INDEX; + do { + fgCheckACMAgain = FALSE; + if (!prStaRec->fgIsQoS) { + prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC1]; + ucTC = TC1_INDEX; + break; + } + + switch (prCurrentMsduInfo->ucUserPriority) { + case 1: + case 2: + prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC0]; + ucTC = TC0_INDEX; + eAci = WMM_AC_BK_INDEX; + break; + case 0: + case 3: + prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC1]; + ucTC = TC1_INDEX; + eAci = WMM_AC_BE_INDEX; + break; + case 4: + case 5: + prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC2]; + ucTC = TC2_INDEX; + eAci = WMM_AC_VI_INDEX; +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + prQM->u4TxNumOfVi++; +#endif + break; + case 6: + case 7: + prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC3]; + ucTC = TC3_INDEX; + eAci = WMM_AC_VO_INDEX; +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + prQM->u4TxNumOfVo++; +#endif + break; + default: + prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC1]; + ucTC = TC1_INDEX; + eAci = WMM_AC_BE_INDEX; + ASSERT(0); + break; + } + if (prBssInfo->arACQueParms[eAci].fgIsACMSet && + !(u2ActivedTspec & BIT(eAci)) && eAci != WMM_AC_BK_INDEX) { + prCurrentMsduInfo->ucUserPriority = aucNextUP[eAci]; + fgCheckACMAgain = TRUE; + } + } while (fgCheckACMAgain); + + /* LOG_FUNC ("QoS %u UP %u TC %u", */ + /* prStaRec->fgIsQoS,prCurrentMsduInfo->ucUserPriority, ucTC); */ + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + /* + * In TDLS or AP mode, peer maybe enter "sleep mode". + * + * If QM_INIT_TIME_TO_UPDATE_QUE_LEN = 60 when peer is in sleep mode, + * we need to wait 60 * u4TimeToAdjustTcResource = 180 packets + * u4TimeToAdjustTcResource = 3, + * then we will adjust TC resouce for VI or VO. + * + * But in TDLS test case, the throughput is very low, only 0.8Mbps in 5.7, + * we will to wait about 12 seconds to collect 180 packets. + * but the test time is only 20 seconds. + */ + if ((prQM->u4TxNumOfVi == 10) || (prQM->u4TxNumOfVo == 10)) { + /* force to do TC resouce update */ + prQM->u4TimeToUpdateQueLen = QM_INIT_TIME_TO_UPDATE_QUE_LEN_MIN; + prQM->u4TimeToAdjustTcResource = 1; + } +#endif +#if ARP_MONITER_ENABLE + if (IS_STA_IN_AIS(prStaRec) && prCurrentMsduInfo->eSrc == TX_PACKET_OS) + qmDetectArpNoResponse(prAdapter, prCurrentMsduInfo); +#endif + + break; /*default */ + } /* switch (prCurrentMsduInfo->ucStaRecIndex) */ +#if 0 /*TGn AP mode N-4.2.25 causes a large number of forwarding packets. + * Disable this drop mechanism to raise the throughput. + */ + + if (prCurrentMsduInfo->eSrc == TX_PACKET_FORWARDING) { + if (prTxQue->u4NumElem > 32) { + DBGLOG(QM, WARN, + "Drop the Packet for full Tx queue (forwarding) Bss %u\n", + prCurrentMsduInfo->ucNetworkType); + prTxQue = &rNotEnqueuedQue; + TX_INC_CNT(&prAdapter->rTxCtrl, TX_FORWARD_OVERFLOW_DROP); + } + } +#endif + } else { + + DBGLOGLIMITED(QM, WARN, "Drop the Packet for inactive Bss %u\n", + prCurrentMsduInfo->ucNetworkType); + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_31); + prTxQue = &rNotEnqueuedQue; + TX_INC_CNT(&prAdapter->rTxCtrl, TX_INACTIVE_BSS_DROP); + } + + /* 4 <3> Fill the MSDU_INFO for constructing HIF TX header */ + + /* TODO: Fill MSDU_INFO according to the network type, + * EtherType, and STA status (for PS forwarding control). + */ + + /* Note that the Network Type Index and STA_REC index are determined in + * qmDetermineStaRecIndex(prCurrentMsduInfo). + */ + QM_TX_SET_MSDU_INFO_FOR_DATA_PACKET(prCurrentMsduInfo, /* MSDU_INFO ptr */ + ucTC, /* TC tag */ + ucPacketType, /* Packet Type */ + 0, /* Format ID */ + prCurrentMsduInfo->fgIs802_1x, /* Flag 802.1x */ + prCurrentMsduInfo->fgIs802_11, /* Flag 802.11 */ + 0, /* PAL LLH */ + 0, /* ACL SN */ + PS_FORWARDING_TYPE_NON_PS, /* PS Forwarding Type */ + 0 /* PS Session ID */ + ); + + /* 4 <4> Enqueue the packet to different AC queue (max 5 AC queues) */ + QUEUE_INSERT_TAIL(prTxQue, (P_QUE_ENTRY_T) prCurrentMsduInfo); + wlanFillTimestamp(prAdapter, prCurrentMsduInfo->prPacket, PHASE_ENQ_QM); + + if (prTxQue != &rNotEnqueuedQue) { + prQM->u4EnqeueuCounter++; + prQM->au4ResourceWantedCounter[ucTC]++; + } + if (prStaRec) + prStaRec->u4EnqeueuCounter++; + +#if QM_TC_RESOURCE_EMPTY_COUNTER + prTxCtrl = &prAdapter->rTxCtrl; + + if (prTxCtrl->rTc.aucFreeBufferCount[ucTC] == 0) { + prQM->au4QmTcResourceEmptyCounter[prCurrentMsduInfo->ucNetworkType][ucTC]++; + /* + * DBGLOG(QM, TRACE, ("TC%d Q Empty Count: [%d]%ld\n", + * ucTC, + * prCurrentMsduInfo->ucNetworkType, + * prQM->au4QmTcResourceEmptyCounter[prCurrentMsduInfo->ucNetworkType][ucTC])); + */ + } +#endif + +#if QM_TEST_MODE + if (++prQM->u4PktCount == QM_TEST_TRIGGER_TX_COUNT) { + prQM->u4PktCount = 0; + qmTestCases(prAdapter); + } +#endif + + DBGLOG(QM, LOUD, "Current queue length = %u\n", prTxQue->u4NumElem); + } while (prNextMsduInfo); + + if (QUEUE_IS_NOT_EMPTY(&rNotEnqueuedQue)) { + QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T) QUEUE_GET_TAIL(&rNotEnqueuedQue), NULL); + prMsduInfoReleaseList = (P_MSDU_INFO_T) QUEUE_GET_HEAD(&rNotEnqueuedQue); + } + + return prMsduInfoReleaseList; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Determine the STA_REC index for a packet +* +* \param[in] prMsduInfo Pointer to the packet +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID qmDetermineStaRecIndex(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + UINT_32 i; + + P_STA_RECORD_T prTempStaRec; + /* P_QUE_MGT_T prQM = &prAdapter->rQM; */ + + prTempStaRec = NULL; + + ASSERT(prMsduInfo); + + /* 4 <1> DA = BMCAST */ + if (IS_BMCAST_MAC_ADDR(prMsduInfo->aucEthDestAddr)) { + /* + * For intrastructure mode and P2P (playing as a GC), BMCAST frames shall be sent to the AP. + * FW shall take care of this. The host driver is not able to distinguish these cases. + */ + prMsduInfo->ucStaRecIndex = STA_REC_INDEX_BMCAST; + DBGLOG(QM, LOUD, "TX with DA = BMCAST\n"); + return; + } +#if (CFG_SUPPORT_TDLS == 1) + /* Check if the peer is TDLS one */ + if (TdlsexStaRecIdxGet(prAdapter, prMsduInfo) == TDLS_STATUS_SUCCESS) + return; /* find a TDLS record */ +#endif /* CFG_SUPPORT_TDLS */ + + /* 4 <2> Check if an AP STA is present */ + for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++) { + prTempStaRec = &(prAdapter->arStaRec[i]); + + if ((prTempStaRec->ucNetTypeIndex == prMsduInfo->ucNetworkType) + && (prTempStaRec->fgIsAp) + && (prTempStaRec->fgIsValid)) { + prMsduInfo->ucStaRecIndex = prTempStaRec->ucIndex; + return; + } + } + + /* 4 <3> Not BMCAST, No AP --> Compare DA (i.e., to see whether this is a unicast frame to a client) */ + for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++) { + prTempStaRec = &(prAdapter->arStaRec[i]); + if (prTempStaRec->fgIsValid) { + if (EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, prMsduInfo->aucEthDestAddr)) { + prMsduInfo->ucStaRecIndex = prTempStaRec->ucIndex; + return; + } + } + } + + /* 4 <4> No STA found, Not BMCAST --> Indicate NOT_FOUND to FW */ + prMsduInfo->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; + DBGLOG(QM, LOUD, "QM: TX with STA_REC_INDEX_NOT_FOUND\n"); + +#if (QM_TEST_MODE && QM_TEST_FAIR_FORWARDING) + prMsduInfo->ucStaRecIndex = (UINT_8) prQM->u4CurrentStaRecIndexToEnqueue; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Dequeue TX packets from a STA_REC for a particular TC +* +* \param[out] prQue The queue to put the dequeued packets +* \param[in] ucTC The TC index (TC0_INDEX to TC5_INDEX) +* \param[in] ucMaxNum The maximum amount of dequeued packets +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID +qmDequeueTxPacketsFromPerStaQueues(IN P_ADAPTER_T prAdapter, + OUT P_QUE_T prQue, IN UINT_8 ucTC, IN UINT_8 ucCurrentQuota, IN UINT_8 ucTotalQuota) +{ + +#if QM_FORWARDING_FAIRNESS + UINT_32 i; /* Loop for */ + + PUINT_32 pu4HeadStaRecIndex; /* The Head STA index */ + PUINT_32 pu4HeadStaRecForwardCount; /* The total forwarded packets for the head STA */ + + P_STA_RECORD_T prStaRec; /* The current focused STA */ + P_BSS_INFO_T prBssInfo; /* The Bss for current focused STA */ + P_QUE_T prCurrQueue; /* The current TX queue to dequeue */ + P_MSDU_INFO_T prDequeuedPkt; /* The dequeued packet */ + + UINT_32 u4ForwardCount; /* To remember the total forwarded packets for a STA */ + UINT_32 u4MaxForwardCount; /* The maximum number of packets a STA can forward */ + UINT_32 u4Resource; /* The TX resource amount */ + + BOOLEAN fgChangeHeadSta; /* Whether a new head STA shall be determined at the end of the function */ + P_QUE_MGT_T prQM = &prAdapter->rQM; + + PUINT_8 pucFreeQuota = NULL; +#if CFG_ENABLE_WIFI_DIRECT + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = &prAdapter->rWifiVar.prP2pFsmInfo->rChnlReqInfo; + /*NFC Beam + Indication */ +#endif + DBGLOG(QM, LOUD, "Enter qmDequeueTxPacketsFromPerStaQueues (TC = %u)\n", ucTC); + + ASSERT(ucTC == TC0_INDEX || ucTC == TC1_INDEX || ucTC == TC2_INDEX || ucTC == TC3_INDEX || ucTC == TC4_INDEX); + + if (!ucCurrentQuota) { + prQM->au4DequeueNoTcResourceCounter[ucTC]++; + DBGLOG(TX, LOUD, "@@@@@ TC = %u ucCurrentQuota = %u @@@@@\n", ucTC, ucCurrentQuota); + return; + } + + u4Resource = ucCurrentQuota; + + /* 4 <1> Determine the head STA */ + /* The head STA shall be an active STA */ + + pu4HeadStaRecIndex = &(prQM->au4HeadStaRecIndex[ucTC]); + pu4HeadStaRecForwardCount = &(prQM->au4ForwardCount[ucTC]); + + DBGLOG(QM, LOUD, "(Fairness) TID = %u Init Head STA = %u Resource = %u\n", + ucTC, *pu4HeadStaRecIndex, u4Resource); + + /* From STA[x] to STA[x+1] to STA[x+2] to ... to STA[x] */ + for (i = 0; i < CFG_NUM_OF_STA_RECORD + 1; i++) { + prStaRec = &prAdapter->arStaRec[(*pu4HeadStaRecIndex)]; + ASSERT(prStaRec); + + /* Only Data frame (1x was not included) will be queued in */ + if (prStaRec->fgIsValid && prStaRec->fgIsTxAllowed) { + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + ASSERT(prBssInfo->ucNetTypeIndex == prStaRec->ucNetTypeIndex); + + /* Determine how many packets the head STA is allowed to send in a round */ + + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_25); + u4MaxForwardCount = ucTotalQuota; +#if CFG_ENABLE_WIFI_DIRECT + + pucFreeQuota = NULL; + if (prStaRec->fgIsInPS && (ucTC != TC4_INDEX)) { + /* TODO: Change the threshold in coorperation with the PS forwarding mechanism */ + /* u4MaxForwardCount = ucTotalQuota; */ + /* Per STA flow control when STA in PS mode */ + /* The PHASE 1: only update from ucFreeQuota (now) */ + /* XXX The PHASE 2: Decide by ucFreeQuota and ucBmpDeliveryAC (per queue ) */ + /* aucFreeQuotaPerQueue[] */ + /* NOTE: other method to set u4Resource */ + + if (prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported + /* + * && prAdapter->rWifiVar.fgSupportQoS + * && prAdapter->rWifiVar.fgSupportUAPSD + */) { + + if (prStaRec->ucBmpTriggerAC & BIT(ucTC)) { + u4MaxForwardCount = prStaRec->ucFreeQuotaForDelivery; + pucFreeQuota = &prStaRec->ucFreeQuotaForDelivery; + } else { + u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery; + pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery; + } + + } else { + ASSERT(prStaRec->ucFreeQuotaForDelivery == 0); + u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery; + pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery; + } + + } /* fgIsInPS */ +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +#if CFG_ENABLE_WIFI_DIRECT + + /*NFC Beam + Indication */ + + if (prBssInfo->fgIsNetAbsent && (ucTC != TC4_INDEX)) { + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + if ((prChnlReqInfo->NFC_BEAM != 1) && + (u4MaxForwardCount > prBssInfo->ucBssFreeQuota)) + u4MaxForwardCount = prBssInfo->ucBssFreeQuota; + } else { + if (u4MaxForwardCount > prBssInfo->ucBssFreeQuota) + u4MaxForwardCount = prBssInfo->ucBssFreeQuota; + } + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + + /* Determine whether the head STA can continue to forward packets in this round */ + if ((*pu4HeadStaRecForwardCount) < u4MaxForwardCount) + break; + + } /* prStaRec->fgIsValid */ + else { + /* The current Head STA has been deactivated, so search for a new head STA */ + prStaRec = NULL; + prBssInfo = NULL; + (*pu4HeadStaRecIndex)++; + (*pu4HeadStaRecIndex) %= CFG_NUM_OF_STA_RECORD; + + /* Reset the forwarding count before searching (since this is for a new selected STA) */ + (*pu4HeadStaRecForwardCount) = 0; + } + } /* i < CFG_NUM_OF_STA_RECORD + 1 */ + + /* All STA_RECs are inactive, so exit */ + if (!prStaRec) { + /* Under concurrent, it is possible that there is no candidcated STA. */ + /* DBGLOG(TX, EVENT, ("All STA_RECs are inactive\n")); */ + return; + } + + DBGLOG(QM, LOUD, "(Fairness) TID = %u Round Head STA = %u\n", ucTC, *pu4HeadStaRecIndex); + + /* 4 <2> Dequeue packets from the head STA */ + + prCurrQueue = &prStaRec->arTxQueue[ucTC]; + prDequeuedPkt = NULL; + fgChangeHeadSta = FALSE; + +#if (CFG_SUPPORT_TDLS == 1) + if (pucFreeQuota != NULL) + TdlsexTxQuotaCheck(prAdapter->prGlueInfo, prStaRec, *pucFreeQuota); +#endif /* CFG_SUPPORT_TDLS */ + + while (prCurrQueue) { + +#if QM_DEBUG_COUNTER + + if (ucTC <= TC4_INDEX) { + if (QUEUE_IS_EMPTY(prCurrQueue)) { + QM_DBG_CNT_INC(prQM, ucTC); + /* QM_DBG_CNT_00 *//* QM_DBG_CNT_01 *//* QM_DBG_CNT_02 */ + /* QM_DBG_CNT_03 *//* QM_DBG_CNT_04 */ + } + if (u4Resource == 0) { + QM_DBG_CNT_INC(prQM, ucTC + 5); + /* QM_DBG_CNT_05 *//* QM_DBG_CNT_06 *//* QM_DBG_CNT_07 */ + /* QM_DBG_CNT_08 *//* QM_DBG_CNT_09 */ + } + if (((*pu4HeadStaRecForwardCount) >= u4MaxForwardCount)) { + QM_DBG_CNT_INC(prQM, ucTC + 10); + /* QM_DBG_CNT_10 *//* QM_DBG_CNT_11 *//* QM_DBG_CNT_12 */ + /* QM_DBG_CNT_13 *//* QM_DBG_CNT_14 */ + } + } +#endif + + /* Three cases to break: (1) No resource (2) No packets (3) Fairness */ + if (QUEUE_IS_EMPTY(prCurrQueue) || ((*pu4HeadStaRecForwardCount) >= u4MaxForwardCount)) { + fgChangeHeadSta = TRUE; + break; + } else if (u4Resource == 0) { +#if (CFG_SUPPORT_STATISTICS == 1) + prStaRec->u4NumOfNoTxQuota++; +#endif /* CFG_SUPPORT_STATISTICS */ + break; + } + + QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T); + prStaRec->u4DeqeueuCounter++; + prQM->u4DequeueCounter++; + +#if (CFG_SUPPORT_TDLS_DBG == 1) + if (prDequeuedPkt != NULL) { + struct sk_buff *prSkb = (struct sk_buff *)prDequeuedPkt->prPacket; + UINT8 *pkt = prSkb->data; + UINT16 u2Identifier; + + if ((*(pkt + 12) == 0x08) && (*(pkt + 13) == 0x00)) { + /* ip */ + u2Identifier = ((*(pkt + 18)) << 8) | (*(pkt + 19)); + DBGLOG(QM, LOUD, " %d\n", u2Identifier); + } + } +#endif +#if DBG && 0 + LOG_FUNC("Deq0 TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n", + prDequeuedPkt->ucTC, + prCurrQueue->u4NumElem, + prDequeuedPkt->ucNetworkType, + prDequeuedPkt->ucMacHeaderLength, + prDequeuedPkt->u2FrameLength, + prDequeuedPkt->ucPacketType, prDequeuedPkt->fgIs802_1x, prDequeuedPkt->fgIs802_11); + + LOG_FUNC("Dest Mac: %pM\n", prDequeuedPkt->aucEthDestAddr); + +#if LINUX + { + struct sk_buff *prSkb = (struct sk_buff *)prDequeuedPkt->prPacket; + + dumpMemory8((PUINT_8) prSkb->data, prSkb->len); + } +#endif + +#endif + + ASSERT(prDequeuedPkt->ucTC == ucTC); + + if (!QUEUE_IS_EMPTY(prCurrQueue)) { + /* XXX: check all queues for STA */ + prDequeuedPkt->ucPsForwardingType = PS_FORWARDING_MORE_DATA_ENABLED; + } + + QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prDequeuedPkt); + u4Resource--; + (*pu4HeadStaRecForwardCount)++; + +#if CFG_ENABLE_WIFI_DIRECT + /* XXX The PHASE 2: decrease from aucFreeQuotaPerQueue[] */ + if (prStaRec->fgIsInPS && (ucTC != TC4_INDEX)) { + if ((pucFreeQuota) && (*pucFreeQuota > 0)) + *pucFreeQuota = *pucFreeQuota - 1; + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +#if CFG_ENABLE_WIFI_DIRECT + if (prBssInfo->fgIsNetAbsent && (ucTC != TC4_INDEX)) { + if (prBssInfo->ucBssFreeQuota > 0) + prBssInfo->ucBssFreeQuota--; + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + + } + + if (*pu4HeadStaRecForwardCount) { + DBGLOG(QM, LOUD, + "TC = %u Round Head STA = %u, u4HeadStaRecForwardCount = %u\n", ucTC, *pu4HeadStaRecIndex, + (*pu4HeadStaRecForwardCount)); + } +#if QM_BURST_END_INFO_ENABLED + /* Let FW know which packet is the last one dequeued from the STA */ + if (prDequeuedPkt) + prDequeuedPkt->fgIsBurstEnd = TRUE; +#endif + + /* 4 <3> Dequeue from the other STAs if there is residual TX resource */ + + /* Check all of the STAs to continue forwarding packets (including the head STA) */ + for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++) { + /* Break in case no reasource is available */ + if (u4Resource == 0) { + prQM->au4DequeueNoTcResourceCounter[ucTC]++; + break; + } + + /* The current head STA will be examined when i = CFG_NUM_OF_STA_RECORD-1 */ + prStaRec = &prAdapter->arStaRec[((*pu4HeadStaRecIndex) + i + 1) % CFG_NUM_OF_STA_RECORD]; + if (prStaRec == NULL) /* for coverity issue */ + break; + + if (prStaRec->fgIsValid && prStaRec->fgIsTxAllowed) { + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + ASSERT(prBssInfo->ucNetTypeIndex == prStaRec->ucNetTypeIndex); + + DBGLOG(QM, LOUD, "(Fairness) TID = %u Sharing STA = %u Resource = %u\n", + ucTC, prStaRec->ucIndex, u4Resource); + + prCurrQueue = &prStaRec->arTxQueue[ucTC]; + u4ForwardCount = 0; + u4MaxForwardCount = ucTotalQuota; + +#if CFG_ENABLE_WIFI_DIRECT + pucFreeQuota = NULL; + if (prStaRec->fgIsInPS && (ucTC != TC4_INDEX)) { + /* TODO: Change the threshold in coorperation with the PS forwarding mechanism */ + /* u4MaxForwardCount = ucTotalQuota; */ + /* Per STA flow control when STA in PS mode */ + /* The PHASE 1: only update from ucFreeQuota (now) */ + /* XXX The PHASE 2: Decide by ucFreeQuota and ucBmpDeliveryAC (per queue ) */ + /* aucFreeQuotaPerQueue[] */ + /* NOTE: other method to set u4Resource */ + if (prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported + /* + * && prAdapter->rWifiVar.fgSupportQoS + * && prAdapter->rWifiVar.fgSupportUAPSD + */) { + + if (prStaRec->ucBmpTriggerAC & BIT(ucTC)) { + u4MaxForwardCount = prStaRec->ucFreeQuotaForDelivery; + pucFreeQuota = &prStaRec->ucFreeQuotaForDelivery; + } else { + u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery; + pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery; + } + + } else { + ASSERT(prStaRec->ucFreeQuotaForDelivery == 0); + u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery; + pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery; + } + + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ +#if CFG_ENABLE_WIFI_DIRECT + if (prBssInfo->fgIsNetAbsent && (ucTC != TC4_INDEX)) { + if (u4MaxForwardCount > prBssInfo->ucBssFreeQuota) + u4MaxForwardCount = prBssInfo->ucBssFreeQuota; + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + } /* prStaRec->fgIsValid */ + else { + prBssInfo = NULL; + /* Invalid STA, so check the next STA */ + continue; + } + + while (prCurrQueue) { + /* Three cases to break: (1) No resource (2) No packets (3) Fairness */ + if ((u4Resource == 0) || QUEUE_IS_EMPTY(prCurrQueue) || (u4ForwardCount >= u4MaxForwardCount)) + break; + + + QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T); + +#if DBG && 0 + DBGLOG(QM, LOUD, "Deq0 TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n", + prDequeuedPkt->ucTC, + prCurrQueue->u4NumElem, + prDequeuedPkt->ucNetworkType, + prDequeuedPkt->ucMacHeaderLength, + prDequeuedPkt->u2FrameLength, + prDequeuedPkt->ucPacketType, + prDequeuedPkt->fgIs802_1x, prDequeuedPkt->fgIs802_11)); + + DBGLOG(QM, LOUD, "Dest Mac: %pM\n", prDequeuedPkt->aucEthDestAddr); + +#if LINUX + { + struct sk_buff *prSkb = (struct sk_buff *)prDequeuedPkt->prPacket; + + dumpMemory8((PUINT_8) prSkb->data, prSkb->len); + } +#endif + +#endif + + ASSERT(prDequeuedPkt->ucTC == ucTC); + + if (!QUEUE_IS_EMPTY(prCurrQueue)) + /* more data field ? */ + prDequeuedPkt->ucPsForwardingType = PS_FORWARDING_MORE_DATA_ENABLED; + + QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prDequeuedPkt); + if (prStaRec) + prStaRec->u4DeqeueuCounter++; + prQM->u4DequeueCounter++; + u4Resource--; + u4ForwardCount++; + +#if CFG_ENABLE_WIFI_DIRECT + /* XXX The PHASE 2: decrease from aucFreeQuotaPerQueue[] */ + if (prStaRec->fgIsInPS && (ucTC != TC4_INDEX)) { + if ((pucFreeQuota) && (*pucFreeQuota > 0)) + *pucFreeQuota = *pucFreeQuota - 1; + + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +#if CFG_ENABLE_WIFI_DIRECT + ASSERT(prBssInfo->ucNetTypeIndex == prStaRec->ucNetTypeIndex); + if (prBssInfo->fgIsNetAbsent && (ucTC != TC4_INDEX)) { + if (prBssInfo->ucBssFreeQuota > 0) + prBssInfo->ucBssFreeQuota--; + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + + } + +#if QM_BURST_END_INFO_ENABLED + /* Let FW know which packet is the last one dequeued from the STA */ + if (u4ForwardCount) + prDequeuedPkt->fgIsBurstEnd = TRUE; +#endif + } + + if (fgChangeHeadSta) { + (*pu4HeadStaRecIndex)++; + (*pu4HeadStaRecIndex) %= CFG_NUM_OF_STA_RECORD; + (*pu4HeadStaRecForwardCount) = 0; + DBGLOG(QM, LOUD, "(Fairness) TID = %u Scheduled Head STA = %u Left Resource = %u\n", + ucTC, (*pu4HeadStaRecIndex), u4Resource); + } + +/***************************************************************************************/ +#else + UINT_8 ucStaRecIndex; + P_STA_RECORD_T prStaRec; + P_QUE_T prCurrQueue; + UINT_8 ucPktCount; + P_MSDU_INFO_T prDequeuedPkt; + + DBGLOG(QM, LOUD, "Enter qmDequeueTxPacketsFromPerStaQueues (TC = %u)\n", ucTC); + + if (ucCurrentQuota == 0) + return; + /* 4 <1> Determine the queue index and the head STA */ + + /* The head STA */ + ucStaRecIndex = 0; /* TODO: Get the current head STA */ + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, ucStaRecIndex); + ASSERT(prStaRec); + + if (prStaRec == NULL) + return; + + /* The queue to pull out packets */ + ASSERT(ucTC == TC0_INDEX || ucTC == TC1_INDEX || ucTC == TC2_INDEX || ucTC == TC3_INDEX || ucTC == TC4_INDEX); + prCurrQueue = &prStaRec->arTxQueue[ucTC]; + + ucPktCount = ucCurrentQuota; + prDequeuedPkt = NULL; + + /* 4 <2> Dequeue packets for the head STA */ + while (TRUE) { + if (!(prStaRec->fgIsValid) || ucPktCount == 0 || QUEUE_IS_EMPTY(prCurrQueue)) { + break; + + } else { + + QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T); + /* DbgPrint("QM: Remove Queue Head, TC= %d\n", prDequeuedPkt->ucTC); */ + ASSERT(prDequeuedPkt->ucTC == ucTC); + + QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prDequeuedPkt); + ucPktCount--; + } + } + + /* DbgPrint("QM: Remaining number of queued packets = %d\n", prCurrQueue->u4NumElem); */ + +#if QM_BURST_END_INFO_ENABLED + if (prDequeuedPkt) + prDequeuedPkt->fgIsBurstEnd = TRUE; +#endif + + /* 4 <3> Update scheduling info */ + /* TODO */ + + /* 4 <4> Utilize the remainaing TX opportunities for non-head STAs */ + /* TODO */ +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Dequeue TX packets from a per-Type-based Queue for a particular TC +* +* \param[out] prQue The queue to put the dequeued packets +* \param[in] ucTC The TC index (Shall always be TC5_INDEX) +* \param[in] ucMaxNum The maximum amount of dequeued packets +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID +qmDequeueTxPacketsFromPerTypeQueues(IN P_ADAPTER_T prAdapter, OUT P_QUE_T prQue, IN UINT_8 ucTC, IN UINT_8 ucMaxNum) +{ + /* UINT_8 ucQueIndex; */ + /* UINT_8 ucStaRecIndex; */ + P_BSS_INFO_T prBssInfo; + P_BSS_INFO_T parBssInfo; + P_QUE_T prCurrQueue; + UINT_8 ucPktCount; + P_MSDU_INFO_T prDequeuedPkt; + P_MSDU_INFO_T prBurstEndPkt; + QUE_T rMergeQue; + P_QUE_T prMergeQue; + P_QUE_MGT_T prQM; + + DBGLOG(QM, LOUD, "Enter qmDequeueTxPacketsFromPerTypeQueues (TC = %d, Max = %d)\n", ucTC, ucMaxNum); + + /* TC5: Broadcast/Multicast data packets */ + ASSERT(ucTC == TC5_INDEX); + + if (ucMaxNum == 0) + return; + + prQM = &prAdapter->rQM; + /* 4 <1> Determine the queue */ + + prCurrQueue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST]; + ucPktCount = ucMaxNum; + prDequeuedPkt = NULL; + prBurstEndPkt = NULL; + + parBssInfo = prAdapter->rWifiVar.arBssInfo; + + QUEUE_INITIALIZE(&rMergeQue); + prMergeQue = &rMergeQue; + + /* 4 <2> Dequeue packets */ + while (TRUE) { + if (ucPktCount == 0 || QUEUE_IS_EMPTY(prCurrQueue)) + break; + + QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T); + ASSERT(prDequeuedPkt->ucTC == ucTC); + + ASSERT(prDequeuedPkt->ucNetworkType < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &parBssInfo[prDequeuedPkt->ucNetworkType]; + + if (IS_BSS_ACTIVE(prBssInfo)) { + if (!prBssInfo->fgIsNetAbsent) { + QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prDequeuedPkt); + prQM->u4DequeueCounter++; + prBurstEndPkt = prDequeuedPkt; + ucPktCount--; + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_26); +#if DBG && 0 + LOG_FUNC + ("DeqType TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n", + prDequeuedPkt->ucTC, prCurrQueue->u4NumElem, prDequeuedPkt->ucNetworkType, + prDequeuedPkt->ucMacHeaderLength, prDequeuedPkt->u2FrameLength, + prDequeuedPkt->ucPacketType, prDequeuedPkt->fgIs802_1x, + prDequeuedPkt->fgIs802_11); + + LOG_FUNC("Dest Mac: %pM\n", prDequeuedPkt->aucEthDestAddr); + +#if LINUX + { + struct sk_buff *prSkb = (struct sk_buff *)prDequeuedPkt->prPacket; + + dumpMemory8((PUINT_8) prSkb->data, prSkb->len); + } +#endif + +#endif + } else { + QUEUE_INSERT_TAIL(prMergeQue, (P_QUE_ENTRY_T) prDequeuedPkt); + } + } else { + QM_TX_SET_NEXT_MSDU_INFO(prDequeuedPkt, NULL); + wlanProcessQueuedMsduInfo(prAdapter, prDequeuedPkt); + } + } + + if (QUEUE_IS_NOT_EMPTY(prMergeQue)) { + QUEUE_CONCATENATE_QUEUES(prMergeQue, prCurrQueue); + QUEUE_MOVE_ALL(prCurrQueue, prMergeQue); + if (QUEUE_GET_TAIL(prCurrQueue)) + QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T) QUEUE_GET_TAIL(prCurrQueue), NULL); + } +#if QM_BURST_END_INFO_ENABLED + if (prBurstEndPkt) + prBurstEndPkt->fgIsBurstEnd = TRUE; +#endif +} /* qmDequeueTxPacketsFromPerTypeQueues */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Dequeue TX packets to send to HIF TX +* +* \param[in] prTcqStatus Info about the maximum amount of dequeued packets +* +* \return The list of dequeued TX packets +*/ +/*----------------------------------------------------------------------------*/ +P_MSDU_INFO_T qmDequeueTxPackets(IN P_ADAPTER_T prAdapter, IN P_TX_TCQ_STATUS_T prTcqStatus) +{ + + INT32 i; + P_MSDU_INFO_T prReturnedPacketListHead; + QUE_T rReturnedQue; + + DBGLOG(QM, LOUD, "Enter qmDequeueTxPackets\n"); + + QUEUE_INITIALIZE(&rReturnedQue); + + prReturnedPacketListHead = NULL; + + /* dequeue packets from different AC queue based on available aucFreeBufferCount */ + /* TC0 to TC4: AC0~AC3, 802.1x (commands packets are not handled by QM) */ + for (i = TC4_INDEX; i >= TC0_INDEX; i--) { + DBGLOG(QM, LOUD, "Dequeue packets from Per-STA queue[%d]\n", i); + + /* + * in the function, we will re-calculate the ucFreeQuota. + * If any packet with any priority for the station will be sent, ucFreeQuota -- + * + * Note1: ucFreeQuota will be decrease only when station is in power save mode. + * In active mode, we will sent the packet to the air directly. + * + * if(prStaRec->fgIsInPS && (ucTC!=TC4_INDEX)) { + * ASSERT(pucFreeQuota); + * ASSERT(*pucFreeQuota>0); + * if ((pucFreeQuota) && (*pucFreeQuota>0)) { + * *pucFreeQuota = *pucFreeQuota - 1; + * } + * } + * + * Note2: maximum queued number for a station is 10, TXM_MAX_BUFFER_PER_STA_DEF in fw + * i.e. default prStaRec->ucFreeQuota = 10 + * + * Note3: In qmUpdateFreeQuota(), we will adjust + * ucFreeQuotaForNonDelivery = ucFreeQuota>>1; + * ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery; + */ + qmDequeueTxPacketsFromPerStaQueues(prAdapter, + &rReturnedQue, + (UINT_8) i, + prTcqStatus->aucFreeBufferCount[i], /* maximum dequeue number */ + prTcqStatus->aucMaxNumOfBuffer[i]); + + /* The aggregate number of dequeued packets */ + DBGLOG(QM, LOUD, "DQA)[%u](%u)\n", i, rReturnedQue.u4NumElem); + } + + /* TC5 (BMCAST or STA-NOT-FOUND packets) */ + qmDequeueTxPacketsFromPerTypeQueues(prAdapter, + &rReturnedQue, TC5_INDEX, prTcqStatus->aucFreeBufferCount[TC5_INDEX] + ); + + DBGLOG(QM, LOUD, "Current total number of dequeued packets = %u\n", rReturnedQue.u4NumElem); + + if (QUEUE_IS_NOT_EMPTY(&rReturnedQue)) { + prReturnedPacketListHead = (P_MSDU_INFO_T) QUEUE_GET_HEAD(&rReturnedQue); + QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T) QUEUE_GET_TAIL(&rReturnedQue), NULL); + } + + return prReturnedPacketListHead; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Adjust the TC quotas according to traffic demands +* +* \param[out] prTcqAdjust The resulting adjustment +* \param[in] prTcqStatus Info about the current TC quotas and counters +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmAdjustTcQuotas(IN P_ADAPTER_T prAdapter, OUT P_TX_TCQ_ADJUST_T prTcqAdjust, IN P_TX_TCQ_STATUS_T prTcqStatus) +{ +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + UINT_32 i; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + /* Must reset */ + for (i = 0; i < TC_NUM; i++) + prTcqAdjust->acVariation[i] = 0; + + /* 4 <1> If TC resource is not just adjusted, exit directly */ + if (!prQM->fgTcResourcePostAnnealing) + return; + /* 4 <2> Adjust TcqStatus according to the updated prQM->au4CurrentTcResource */ + else { + INT_32 i4TotalExtraQuota = 0; + INT_32 ai4ExtraQuota[TC_NUM]; + BOOLEAN fgResourceRedistributed = TRUE; + + /* Obtain the free-to-distribute resource */ + for (i = 0; i < TC_NUM; i++) { + ai4ExtraQuota[i] = + (INT_32) prTcqStatus->aucMaxNumOfBuffer[i] - (INT_32) prQM->au4CurrentTcResource[i]; + + if (ai4ExtraQuota[i] > 0) { /* The resource shall be reallocated to other TCs */ + + if (ai4ExtraQuota[i] > prTcqStatus->aucFreeBufferCount[i]) { + /* + * we have residunt TC resources for the TC: + * EX: aucMaxNumOfBuffer[] = 20, au4CurrentTcResource[] = 5 + * ai4ExtraQuota[] = 15, aucFreeBufferCount[] = 10 + * + * so ai4ExtraQuota[] = aucFreeBufferCount[] = 10 + * because we available TC resources actually is 10, not 20 + */ + ai4ExtraQuota[i] = prTcqStatus->aucFreeBufferCount[i]; + + /* + * FALSE means we can re-do TC resource adjustment in tx done + * at next time, maybe more tx done is finished + */ + fgResourceRedistributed = FALSE; + } + + /* accumulate current all available TC resources */ + i4TotalExtraQuota += ai4ExtraQuota[i]; + + /* deduce unused TC resources for the TC */ + prTcqAdjust->acVariation[i] = (INT_8) (-ai4ExtraQuota[i]); + } + } + + /* Distribute quotas to TCs which need extra resource according to prQM->au4CurrentTcResource */ + for (i = 0; i < TC_NUM; i++) { + if (ai4ExtraQuota[i] < 0) { + + /* The TC needs extra resources */ + if ((-ai4ExtraQuota[i]) > i4TotalExtraQuota) { + /* the number of needed extra resources is larger than total available */ + ai4ExtraQuota[i] = (-i4TotalExtraQuota); + + /* wait for next tx done to do adjustment */ + fgResourceRedistributed = FALSE; + } + + /* decrease the total available */ + i4TotalExtraQuota += ai4ExtraQuota[i]; + + /* mark to increase TC resources for the TC */ + prTcqAdjust->acVariation[i] = (INT_8) (-ai4ExtraQuota[i]); + } + } + + /* In case some TC is waiting for TX Done, continue to adjust TC quotas upon TX Done */ + + /* + * if fgResourceRedistributed == TRUE, it means we will adjust at this time so + * we need to re-adjust TC resources (fgTcResourcePostAnnealing = FALSE). + */ + prQM->fgTcResourcePostAnnealing = (!fgResourceRedistributed); + +#if QM_PRINT_TC_RESOURCE_CTRL + DBGLOG(QM, LOUD, "QM: Curr Quota [0]=%u [1]=%u [2]=%u [3]=%u [4]=%u [5]=%u\n", + prTcqStatus->aucFreeBufferCount[0], + prTcqStatus->aucFreeBufferCount[1], + prTcqStatus->aucFreeBufferCount[2], + prTcqStatus->aucFreeBufferCount[3], + prTcqStatus->aucFreeBufferCount[4], prTcqStatus->aucFreeBufferCount[5] + )); +#endif + } + +#else + UINT_32 i; + + for (i = 0; i < TC_NUM; i++) + prTcqAdjust->acVariation[i] = 0; + +#endif +} + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL +/*----------------------------------------------------------------------------*/ +/*! +* \brief Update the average TX queue length for the TC resource control mechanism +* +* \param (none) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmUpdateAverageTxQueLen(IN P_ADAPTER_T prAdapter) +{ + INT_32 u4CurrQueLen, i, k; + P_STA_RECORD_T prStaRec; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + /* 4 <1> Update the queue lengths for TC0 to TC3 (skip TC4) and TC5 */ + /* use moving average algorithm to calculate au4AverageQueLen for every TC queue */ + for (i = 0; i < NUM_OF_PER_STA_TX_QUEUES - 1; i++) { + u4CurrQueLen = 0; + + for (k = 0; k < CFG_NUM_OF_STA_RECORD; k++) { + prStaRec = &prAdapter->arStaRec[k]; + ASSERT(prStaRec); + + /* If the STA is activated, get the queue length */ + if (prStaRec->fgIsValid && + (!prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex].fgIsNetAbsent) + ) { + + u4CurrQueLen += (prStaRec->arTxQueue[i].u4NumElem); + } + } + + if (prQM->au4AverageQueLen[i] == 0) { + prQM->au4AverageQueLen[i] = (u4CurrQueLen << QM_QUE_LEN_MOVING_AVE_FACTOR); /* *8 */ + } else { + /* len => len - len/8 = 7/8 * len + new len */ + prQM->au4AverageQueLen[i] -= (prQM->au4AverageQueLen[i] >> QM_QUE_LEN_MOVING_AVE_FACTOR); + prQM->au4AverageQueLen[i] += (u4CurrQueLen); + } + + } + + /* Update the queue length for TC5 (BMCAST) */ + u4CurrQueLen = prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST].u4NumElem; + + if (prQM->au4AverageQueLen[TC_NUM - 1] == 0) { + prQM->au4AverageQueLen[TC_NUM - 1] = (u4CurrQueLen << QM_QUE_LEN_MOVING_AVE_FACTOR); + } else { + prQM->au4AverageQueLen[TC_NUM - 1] -= + (prQM->au4AverageQueLen[TC_NUM - 1] >> QM_QUE_LEN_MOVING_AVE_FACTOR); + prQM->au4AverageQueLen[TC_NUM - 1] += (u4CurrQueLen); + } + + /* 4 <2> Adjust TC resource assignment every 3 times */ + /* Check whether it is time to adjust the TC resource assignment */ + if (--prQM->u4TimeToAdjustTcResource == 0) { /* u4TimeToAdjustTcResource = 3 */ + + /* The last assignment has not been completely applied */ + if (prQM->fgTcResourcePostAnnealing) { + /* Upon the next qmUpdateAverageTxQueLen function call, do this check again */ + + /* wait for next time to do qmReassignTcResource */ + prQM->u4TimeToAdjustTcResource = 1; + } else { /* The last assignment has been applied */ + prQM->u4TimeToAdjustTcResource = QM_INIT_TIME_TO_ADJUST_TC_RSC; + qmReassignTcResource(prAdapter); + } + } + + /* Debug */ +#if QM_PRINT_TC_RESOURCE_CTRL + for (i = 0; i < TC_NUM; i++) { + if (QM_GET_TX_QUEUE_LEN(prAdapter, i) >= 100) { + DBGLOG(QM, LOUD, "QM: QueLen [%u %u %u %u %u %u]\n", + QM_GET_TX_QUEUE_LEN(prAdapter, 0), + QM_GET_TX_QUEUE_LEN(prAdapter, 1), + QM_GET_TX_QUEUE_LEN(prAdapter, 2), + QM_GET_TX_QUEUE_LEN(prAdapter, 3), + QM_GET_TX_QUEUE_LEN(prAdapter, 4), QM_GET_TX_QUEUE_LEN(prAdapter, 5) + )); + break; + } + } +#endif + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Assign TX resource for each TC according to TX queue length and current assignment +* +* \param (none) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmReassignTcResource(IN P_ADAPTER_T prAdapter) +{ + INT_32 i4TotalResourceDemand = 0; + UINT_32 u4ResidualResource = 0; + UINT_32 i; + INT_32 ai4PerTcResourceDemand[TC_NUM]; + UINT_32 u4ShareCount = 0; + UINT_32 u4Share = 0; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + /* Note: After the new assignment is obtained, set prQM->fgTcResourcePostAnnealing to TRUE to + * start the TC-quota adjusting procedure, which will be invoked upon every TX Done + */ + /* + * tx done -> nicProcessTxInterrupt() -> nicTxAdjustTcq() + * -> qmAdjustTcQuotas() -> check fgTcResourcePostAnnealing + */ + + /* 4 <1> Determine the demands */ + /* Determine the amount of extra resource to fulfill all of the demands */ + for (i = 0; i < TC_NUM; i++) { + /* Skip TC4, which is not adjustable */ + if (i == TC4_INDEX) + continue; + + /* + * Define: extra_demand = average que_length (includes all station records) + + * min_reserved_quota - + * current available TC resources + * + * extra_demand means we need extra TC resources to transmit; other TCs can + * borrow their resources to us? + */ + ai4PerTcResourceDemand[i] = + ((UINT_32) (QM_GET_TX_QUEUE_LEN(prAdapter, i)) + + prQM->au4MinReservedTcResource[i] - prQM->au4CurrentTcResource[i]); + + /* If there are queued packets, allocate extra resource for the TC (for TCP consideration) */ + if (QM_GET_TX_QUEUE_LEN(prAdapter, i)) + ai4PerTcResourceDemand[i] += QM_EXTRA_RESERVED_RESOURCE_WHEN_BUSY; /* 0 */ + + /* + * accumulate all needed extra TC resources + * maybe someone need + resource, maybe someone need - resource + */ + i4TotalResourceDemand += ai4PerTcResourceDemand[i]; + } + + /* 4 <2> Case 1: Demand <= Total Resource */ + if (i4TotalResourceDemand <= 0) { + /* 4 <2.1> Satisfy every TC */ + /* total TC resources are enough, no extra TC resources is needed */ + + /* adjust used TC resources to average TC resources + min reserve TC resources */ + for (i = 0; i < TC_NUM; i++) { + /* Skip TC4 (not adjustable) */ + if (i == TC4_INDEX) + continue; + + /* + * the number of resources that one TC releases can be used for + * other TCs + * + * EX: TC0 au4CurrentTcResource[0] = 10 ai4PerTcResourceDemand[0] = -5 + * TC1 au4CurrentTcResource[1] = 5 ai4PerTcResourceDemand[0] = +5 + * => TC0 au4CurrentTcResource[0] = 10 + (-5) = 5 + * TC1 au4CurrentTcResource[1] = 5 + (+5) = 10 + */ + prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i]; + } + + /* 4 <2.2> Share the residual resource evenly */ + u4ShareCount = (TC_NUM - 1); /* 5, excluding TC4 */ + + /* + * EX: i4TotalResourceDemand = -10 + * means we have 10 available resources can be used. + */ + u4ResidualResource = (UINT_32) (-i4TotalResourceDemand); + u4Share = (u4ResidualResource / u4ShareCount); + + /* share available TC resources to all TCs averagely */ + for (i = 0; i < TC_NUM; i++) { + /* Skip TC4 (not adjustable) */ + if (i == TC4_INDEX) + continue; + + /* allocate residual average resources to the TC */ + prQM->au4CurrentTcResource[i] += u4Share; + + /* Every TC is fully satisfied so no need extra resources */ + ai4PerTcResourceDemand[i] = 0; + + /* decrease the allocated resources */ + u4ResidualResource -= u4Share; + } + + /* if still have available resources, we decide to give them to VO (TC3) queue */ + /* 4 <2.3> Allocate the left resource to TC3 (VO) */ + prQM->au4CurrentTcResource[TC3_INDEX] += (u4ResidualResource); + + } + /* 4 <3> Case 2: Demand > Total Resource --> Guarantee a minimum amount of resource for each TC */ + else { + /* + * u4ResidualResource means we at least need to keep + * QM_INITIAL_RESIDUAL_TC_RESOURCE available TC resources + * + * in 6628, u4ResidualResource = 26, max 28 + */ + u4ResidualResource = QM_INITIAL_RESIDUAL_TC_RESOURCE; + + /* 4 <3.1> Allocated resource amount = minimum of (guaranteed, total demand) */ + for (i = 0; i < TC_NUM; i++) { + + if (i == TC4_INDEX) + continue; /* Skip TC4 (not adjustable) */ + + /* The demand can be fulfilled with the guaranteed resource amount 4 4 6 6 2 4 */ + + /* + * ai4PerTcResourceDemand[i] = + * ((UINT_32)(QM_GET_TX_QUEUE_LEN(prAdapter, i)) + + * prQM->au4MinReservedTcResource[i] - + * prQM->au4CurrentTcResource[i]); + * + * so au4CurrentTcResource + ai4PerTcResourceDemand = + * + * ((UINT_32)(QM_GET_TX_QUEUE_LEN(prAdapter, i)) + + * prQM->au4MinReservedTcResource[i] = + * + * current average queue len + min TC resources + */ + if (prQM->au4CurrentTcResource[i] + ai4PerTcResourceDemand[i] < + prQM->au4GuaranteedTcResource[i]) { + + /* avg queue len + min reserve still smaller than guarantee so enough */ + prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i]; + + /* accumulate available TC resources from the TC */ + u4ResidualResource += + (prQM->au4GuaranteedTcResource[i] - prQM->au4CurrentTcResource[i]); + ai4PerTcResourceDemand[i] = 0; + } + + /* The demand can not be fulfilled with the guaranteed resource amount */ + else { + + /* means even we use all guarantee resources for the TC is still not enough */ + + /* + * guarantee number is always for the TC so extra resource number cannot + * include the guarantee number. + * + * EX: au4GuaranteedTcResource = 10, au4CurrentTcResource = 5 + * ai4PerTcResourceDemand = 6 + * + * ai4PerTcResourceDemand -= (10 - 5) ==> 1 + * only need extra 1 TC resouce is enough. + */ + ai4PerTcResourceDemand[i] -= + (prQM->au4GuaranteedTcResource[i] - prQM->au4CurrentTcResource[i]); + + /* update current avg TC resource to guarantee number */ + prQM->au4CurrentTcResource[i] = prQM->au4GuaranteedTcResource[i]; + + /* count how many TC queues need to get extra resources */ + u4ShareCount++; + } + } + + /* 4 <3.2> Allocate the residual resource */ + do { + /* If there is no resource left, exit directly */ + if (u4ResidualResource == 0) + break; + + /* This shall not happen */ + if (u4ShareCount == 0) { + prQM->au4CurrentTcResource[TC1_INDEX] += u4ResidualResource; + DBGLOG(QM, ERROR, "QM: (Error) u4ShareCount = 0\n"); + break; + } + + /* Share the residual resource evenly */ + u4Share = (u4ResidualResource / u4ShareCount); + + if (u4Share) { + for (i = 0; i < TC_NUM; i++) { + /* Skip TC4 (not adjustable) */ + if (i == TC4_INDEX) + continue; + + if (ai4PerTcResourceDemand[i] == 0) + continue; + + if (ai4PerTcResourceDemand[i] - u4Share) { + /* still not enough but we just can give it u4Share resources */ + prQM->au4CurrentTcResource[i] += u4Share; + u4ResidualResource -= u4Share; + ai4PerTcResourceDemand[i] -= u4Share; + } else { + /* enough */ + prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i]; + u4ResidualResource -= ai4PerTcResourceDemand[i]; + ai4PerTcResourceDemand[i] = 0; + } + } + } + + if (u4ResidualResource == 0) + break; + /* By priority, allocate the left resource that is not divisible by u4Share */ + + if (ai4PerTcResourceDemand[TC3_INDEX]) { /* VO */ + prQM->au4CurrentTcResource[TC3_INDEX]++; + if (--u4ResidualResource == 0) + break; + } + + if (ai4PerTcResourceDemand[TC2_INDEX]) { /* VI */ + prQM->au4CurrentTcResource[TC2_INDEX]++; + if (--u4ResidualResource == 0) + break; + } + + if (ai4PerTcResourceDemand[TC5_INDEX]) { /* BMCAST */ + prQM->au4CurrentTcResource[TC5_INDEX]++; + if (--u4ResidualResource == 0) + break; + } + + if (ai4PerTcResourceDemand[TC1_INDEX]) { /* BE */ + prQM->au4CurrentTcResource[TC1_INDEX]++; + if (--u4ResidualResource == 0) + break; + } + + if (ai4PerTcResourceDemand[TC0_INDEX]) { /* BK */ + prQM->au4CurrentTcResource[TC0_INDEX]++; + if (--u4ResidualResource == 0) + break; + } + + /* Allocate the left resource */ + prQM->au4CurrentTcResource[TC3_INDEX] += u4ResidualResource; + + } while (FALSE); + } + + /* mark the flag that we can start to do TC resource adjustment after TX done handle */ + prQM->fgTcResourcePostAnnealing = TRUE; + +#if QM_PRINT_TC_RESOURCE_CTRL + /* Debug print */ + DBGLOG(QM, LOUD, "QM: TC Rsc %u %u %u %u %u %u\n", + prQM->au4CurrentTcResource[0], + prQM->au4CurrentTcResource[1], + prQM->au4CurrentTcResource[2], + prQM->au4CurrentTcResource[3], + prQM->au4CurrentTcResource[4], + prQM->au4CurrentTcResource[5]); +#endif +} +#endif + +/*----------------------------------------------------------------------------*/ +/* RX-Related Queue Management */ +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +/*! +* \brief Init Queue Management for RX +* +* \param[in] (none) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmInitRxQueues(IN P_ADAPTER_T prAdapter) +{ + /* DbgPrint("QM: Enter qmInitRxQueues()\n"); */ + /* TODO */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Handle RX packets (buffer reordering) +* +* \param[in] prSwRfbListHead The list of RX packets +* +* \return The list of packets which are not buffered for reordering +*/ +/*----------------------------------------------------------------------------*/ +P_SW_RFB_T qmHandleRxPackets(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfbListHead) +{ + +#if CFG_RX_REORDERING_ENABLED + /* UINT_32 i; */ + P_SW_RFB_T prCurrSwRfb; + P_SW_RFB_T prNextSwRfb; + P_HIF_RX_HEADER_T prHifRxHdr; + QUE_T rReturnedQue; + PUINT_8 pucEthDestAddr; + BOOLEAN fgIsBMC; +#if CFG_RX_BA_REORDERING_ENHANCEMENT + BOOLEAN fgIsIndependentPkt; +#endif + + + /* 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); + +#if CFG_RX_BA_REORDERING_ENHANCEMENT + /* If it is indenpendant pkt, skip to reordering */ + if (prAdapter->rWifiVar.fgEnableReportIndependentPkt) + fgIsIndependentPkt = qmIsIndependentPkt(prCurrSwRfb); + else + fgIsIndependentPkt = FALSE; +#endif + prHifRxHdr = prCurrSwRfb->prHifRxHdr; /* TODO: (Tehuang) Use macro to obtain the pointer */ + + /* TODO: (Tehuang) Check if relaying */ + prCurrSwRfb->eDst = RX_PKT_DESTINATION_HOST; + + /* Decide the Destination */ +#if CFG_RX_PKTS_DUMP + if (prAdapter->rRxCtrl.u4RxPktsDumpTypeMask & BIT(HIF_RX_PKT_TYPE_DATA)) { + DBGLOG(SW4, INFO, "QM RX DATA: net %u sta idx %u wlan idx %u ssn %u tid %u ptype %u 11 %u\n", + (UINT_32) HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr), + prHifRxHdr->ucStaRecIdx, prCurrSwRfb->ucWlanIdx, + (UINT_32) HIF_RX_HDR_GET_SN(prHifRxHdr), /* The new SN of the frame */ + (UINT_32) HIF_RX_HDR_GET_TID(prHifRxHdr), + prCurrSwRfb->ucPacketType, + (UINT_32) HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)); + + DBGLOG_MEM8(SW4, TRACE, (PUINT_8) prCurrSwRfb->pvHeader, prCurrSwRfb->u2PacketLen); + } +#endif + + fgIsBMC = FALSE; + if (!HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)) { + + UINT_8 ucNetTypeIdx; + P_BSS_INFO_T prBssInfo; + + pucEthDestAddr = prCurrSwRfb->pvHeader; + ucNetTypeIdx = HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[ucNetTypeIdx]); + /* DBGLOG_MEM8(QM, TRACE,prCurrSwRfb->pvHeader, 16); */ + /* */ + + if (IS_BMCAST_MAC_ADDR(pucEthDestAddr) && (prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT)) + fgIsBMC = TRUE; + + if (prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem > + (CFG_RX_MAX_PKT_NUM - CFG_NUM_OF_QM_RX_PKT_NUM)) { + + if (!IS_BSS_ACTIVE(prBssInfo)) { + DBGLOG(QM, WARN, "Mark NULL the Packet for inactive Bss %u\n", ucNetTypeIdx); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + continue; + } + + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + if (IS_BMCAST_MAC_ADDR(pucEthDestAddr)) + prCurrSwRfb->eDst = RX_PKT_DESTINATION_HOST_WITH_FORWARD; + else if (UNEQUAL_MAC_ADDR(prBssInfo->aucOwnMacAddr, pucEthDestAddr) && + bssGetClientByAddress(prBssInfo, pucEthDestAddr)) + prCurrSwRfb->eDst = RX_PKT_DESTINATION_FORWARD; + /* TODO : need to check the dst mac is valid */ + /* If src mac is invalid, the packet will be freed in fw */ + } /* OP_MODE_ACCESS_POINT */ +#if CFG_SUPPORT_HOTSPOT_2_0 + else if (hs20IsFrameFilterEnabled(prAdapter, prBssInfo) && + hs20IsUnsecuredFrame(prAdapter, prBssInfo, prCurrSwRfb)) { + DBGLOG(QM, WARN, + "Mark NULL the Packet for Dropped Packet %u\n", ucNetTypeIdx); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + continue; + } +#endif + } else { + /* Dont not occupy other SW RFB */ + DBGLOG(QM, WARN, "Mark NULL the Packet for less Free Sw Rfb\n"); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + continue; + } + + } +#if CFG_SUPPORT_WAPI + if (prCurrSwRfb->u2PacketLen > ETHER_HEADER_LEN) { + PUINT_8 pc = (PUINT_8) prCurrSwRfb->pvHeader; + UINT_16 u2Etype = 0; + + u2Etype = (pc[ETH_TYPE_LEN_OFFSET] << 8) | (pc[ETH_TYPE_LEN_OFFSET + 1]); + + /* + * for wapi integrity test. WPI_1x packet should be always in non-encrypted mode. + * if we received any WPI(0x88b4) packet that is encrypted, drop here. + */ + if (u2Etype == ETH_WPI_1X && HIF_RX_HDR_GET_SEC_MODE(prHifRxHdr) != 0) { + DBGLOG(QM, INFO, "drop wpi packet with sec mode\n"); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + continue; + } + } +#endif + /* BAR frame */ + if (HIF_RX_HDR_GET_BAR_FLAG(prHifRxHdr)) { + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + qmProcessBarFrame(prAdapter, prCurrSwRfb, &rReturnedQue); + } + /* Reordering is not required for this packet, return it without buffering */ + else if (!HIF_RX_HDR_GET_REORDER_FLAG(prHifRxHdr) || fgIsBMC) { +#if 0 + if (!HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)) { + UINT_8 ucNetTypeIdx; + P_BSS_INFO_T prBssInfo; + + pucEthDestAddr = prCurrSwRfb->pvHeader; + ucNetTypeIdx = HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[ucNetTypeIdx]); + + if (IS_BMCAST_MAC_ADDR(pucEthDestAddr) && + (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { + 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. + */ +#if CFG_RX_BA_REORDERING_ENHANCEMENT + if (fgIsIndependentPkt) { + DBGLOG(QM, TRACE, "Insert independentPkt to returnedQue directly\n"); + QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + qmProcessIndepentReorderQueue(prAdapter, prCurrSwRfb); + } else + qmProcessPktWithReordering(prAdapter, prCurrSwRfb, &rReturnedQue); +#else + qmProcessPktWithReordering(prAdapter, prCurrSwRfb, &rReturnedQue); +#endif + } + } while (prNextSwRfb); + + /* RX_PKT_DESTINATION_HOST_WITH_FORWARD or RX_PKT_DESTINATION_FORWARD */ + /* The returned list of SW_RFBs must end with a NULL pointer */ + if (QUEUE_IS_NOT_EMPTY(&rReturnedQue)) + QM_TX_SET_NEXT_MSDU_INFO((P_SW_RFB_T) QUEUE_GET_TAIL(&rReturnedQue), NULL); + + return (P_SW_RFB_T) QUEUE_GET_HEAD(&rReturnedQue); + +#else + + /* DbgPrint("QM: Enter qmHandleRxPackets()\n"); */ + return prSwRfbListHead; + +#endif + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Reorder the received packet +* +* \param[in] prSwRfb The RX packet to process +* \param[out] prReturnedQue The queue for indicating packets +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmProcessPktWithReordering(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT P_QUE_T prReturnedQue) +{ + + P_STA_RECORD_T prStaRec; + P_HIF_RX_HEADER_T prHifRxHdr; + P_RX_BA_ENTRY_T prReorderQueParm; + + UINT_32 u4SeqNo; + UINT_32 u4WinStart; + UINT_32 u4WinEnd; + P_QUE_T prReorderQue; + /* P_SW_RFB_T prReorderedSwRfb; */ + BOOLEAN fgIsBaTimeout; + + DEBUGFUNC("qmProcessPktWithReordering"); + + if ((prSwRfb == NULL) || (prReturnedQue == NULL) || (prSwRfb->prHifRxHdr == NULL)) { + ASSERT(FALSE); + return; + } + + prHifRxHdr = prSwRfb->prHifRxHdr; + prSwRfb->ucStaRecIdx = prHifRxHdr->ucStaRecIdx; + prSwRfb->u2SSN = HIF_RX_HDR_GET_SN(prHifRxHdr); /* The new SN of the frame */ + prSwRfb->ucTid = (UINT_8) (HIF_RX_HDR_GET_TID(prHifRxHdr)); + /* prSwRfb->eDst = RX_PKT_DESTINATION_HOST; */ + + /* Incorrect STA_REC index */ + if (prSwRfb->ucStaRecIdx >= CFG_NUM_OF_STA_RECORD) { + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); + DBGLOG(QM, WARN, "Reordering for a NULL STA_REC, ucStaRecIdx = %d\n", prSwRfb->ucStaRecIdx); + /* ASSERT(0); */ + return; + } + + /* Check whether the STA_REC is activated */ + prStaRec = &(prAdapter->arStaRec[prSwRfb->ucStaRecIdx]); + ASSERT(prStaRec); + +#if 0 + if (!(prStaRec->fgIsValid)) { + /* TODO: (Tehuang) Handle the Host-FW sync issue. */ + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); + DBGLOG(QM, WARN, "Reordering for an invalid STA_REC\n"); + /* ASSERT(0); */ + return; + } +#endif + + /* Check whether the BA agreement exists */ + prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[prSwRfb->ucTid]); + if (!prReorderQueParm) { + /* TODO: (Tehuang) Handle the Host-FW sync issue. */ + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); + DBGLOG(QM, WARN, "Reordering for a NULL ReorderQueParm\n"); + /* ASSERT(0); */ + return; + } + + /* Start to reorder packets */ + u4SeqNo = (UINT_32) (prSwRfb->u2SSN); + prReorderQue = &(prReorderQueParm->rReOrderQue); + u4WinStart = (UINT_32) (prReorderQueParm->u2WinStart); + u4WinEnd = (UINT_32) (prReorderQueParm->u2WinEnd); + + /* Debug */ + /* DbgPrint("QM:(R)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); */ + + /* Case 1: Fall within */ + if /* 0 - start - sn - end - 4095 */ + (((u4WinStart <= u4SeqNo) && (u4SeqNo <= u4WinEnd)) + /* 0 - end - start - sn - 4095 */ + || ((u4WinEnd < u4WinStart) && (u4WinStart <= u4SeqNo)) + /* 0 - sn - end - start - 4095 */ + || ((u4SeqNo <= u4WinEnd) && (u4WinEnd < u4WinStart))) { + + qmInsertFallWithinReorderPkt(prSwRfb, prReorderQueParm, prReturnedQue); + +#if QM_RX_WIN_SSN_AUTO_ADVANCING + if (prReorderQueParm->fgIsWaitingForPktWithSsn) { + /* Let the first received packet pass the reorder check */ + DBGLOG(QM, LOUD, "QM:(A)[%d](%u){%u,%u}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); + + prReorderQueParm->u2WinStart = (UINT_16) u4SeqNo; + prReorderQueParm->u2WinEnd = + ((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT; + prReorderQueParm->fgIsWaitingForPktWithSsn = FALSE; + } +#endif + + if (qmPopOutDueToFallWithin(prAdapter, prReorderQueParm, prReturnedQue, &fgIsBaTimeout) == FALSE) + STATS_RX_REORDER_HOLE_INC(prStaRec); /* record hole count */ + STATS_RX_REORDER_HOLE_TIMEOUT_INC(prStaRec, fgIsBaTimeout); + } + /* Case 2: Fall ahead */ + else if + /* 0 - start - end - sn - (start+2048) - 4095 */ + (((u4WinStart < u4WinEnd) + && (u4WinEnd < u4SeqNo) + && (u4SeqNo < (u4WinStart + HALF_SEQ_NO_COUNT))) + /* 0 - sn - (start+2048) - start - end - 4095 */ + || ((u4SeqNo < u4WinStart) + && (u4WinStart < u4WinEnd) + && ((u4SeqNo + MAX_SEQ_NO_COUNT) < (u4WinStart + HALF_SEQ_NO_COUNT))) + /* 0 - end - sn - (start+2048) - start - 4095 */ + || ((u4WinEnd < u4SeqNo) + && (u4SeqNo < u4WinStart) + && ((u4SeqNo + MAX_SEQ_NO_COUNT) < (u4WinStart + HALF_SEQ_NO_COUNT)))) { + +#if QM_RX_WIN_SSN_AUTO_ADVANCING + if (prReorderQueParm->fgIsWaitingForPktWithSsn) + prReorderQueParm->fgIsWaitingForPktWithSsn = FALSE; +#endif + + qmInsertFallAheadReorderPkt(prSwRfb, prReorderQueParm, prReturnedQue); + + /* Advance the window after inserting a new tail */ + prReorderQueParm->u2WinEnd = (UINT_16) u4SeqNo; + prReorderQueParm->u2WinStart = + (((prReorderQueParm->u2WinEnd) - (prReorderQueParm->u2WinSize) + MAX_SEQ_NO_COUNT + 1) + % MAX_SEQ_NO_COUNT); + + qmPopOutDueToFallAhead(prAdapter, prReorderQueParm, prReturnedQue); + + STATS_RX_REORDER_FALL_AHEAD_INC(prStaRec); + + } + /* Case 3: Fall behind */ + else { +#if CFG_SUPPORT_GAMING_MODE || CFG_SUPPORT_OSHARE + BOOLEAN fgIsEnable = FALSE; +#if CFG_SUPPORT_GAMING_MODE + fgIsEnable |= prAdapter->fgEnGamingMode; +#endif +#if CFG_SUPPORT_OSHARE + fgIsEnable |= (prAdapter->fgEnOshareMode + && HIF_RX_HDR_GET_NETWORK_IDX(prSwRfb->prHifRxHdr) == NETWORK_TYPE_P2P_INDEX); +#endif + if (fgIsEnable) { + PUINT_8 pucData = (PUINT_8) prSwRfb->pvHeader; + UINT_16 u2Etype = (pucData[ETH_TYPE_LEN_OFFSET] << 8) | (pucData[ETH_TYPE_LEN_OFFSET + 1]); + + if (u2Etype == ETH_P_IP) { + PUINT_8 pucEthBody = &pucData[ETH_HLEN]; + UINT_8 ucIpProto = pucEthBody[IP_PROTO_HLEN]; + + if (ucIpProto == IP_PRO_UDP || ucIpProto == IP_PRO_TCP) { + DBGLOG(QM, LOUD, "QM: No drop packet:[%d](%d){%d,%d}\n", + prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); + STATS_RX_REORDER_FALL_BEHIND_NO_DROP_INC(prStaRec); + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); + return; + } + } + } +#endif /* CFG_SUPPORT_GAMING_MODE */ +#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); + return; + } +#endif +#endif + DBGLOG(QM, LOUD, "QM: drop packet:[%d](%d){%d,%d}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); + STATS_RX_REORDER_FALL_BEHIND_INC(prStaRec); + /* An erroneous packet */ + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); + return; + } + + return; + +} +VOID qmProcessBarFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT P_QUE_T prReturnedQue) +{ + + P_STA_RECORD_T prStaRec; + P_HIF_RX_HEADER_T prHifRxHdr; + P_RX_BA_ENTRY_T prReorderQueParm; + + UINT_32 u4SSN; + UINT_32 u4WinStart; + UINT_32 u4WinEnd; + P_QUE_T prReorderQue; + /* P_SW_RFB_T prReorderedSwRfb; */ + + if ((prSwRfb == NULL) || (prReturnedQue == NULL) || (prSwRfb->prHifRxHdr == NULL)) { + ASSERT(FALSE); + return; + } + + prHifRxHdr = prSwRfb->prHifRxHdr; + prSwRfb->ucStaRecIdx = prHifRxHdr->ucStaRecIdx; + prSwRfb->u2SSN = HIF_RX_HDR_GET_SN(prHifRxHdr); /* The new SSN */ + prSwRfb->ucTid = (UINT_8) (HIF_RX_HDR_GET_TID(prHifRxHdr)); + + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); + + /* Incorrect STA_REC index */ + if (prSwRfb->ucStaRecIdx >= CFG_NUM_OF_STA_RECORD) { + DBGLOG(QM, WARN, "QM: (Warning) BAR for a NULL STA_REC, ucStaRecIdx = %d\n", prSwRfb->ucStaRecIdx); + /* ASSERT(0); */ + return; + } + + /* Check whether the STA_REC is activated */ + prStaRec = &(prAdapter->arStaRec[prSwRfb->ucStaRecIdx]); + ASSERT(prStaRec); + +#if 0 + if (!(prStaRec->fgIsValid)) { + /* TODO: (Tehuang) Handle the Host-FW sync issue. */ + DbgPrint("QM: (Warning) BAR for an invalid STA_REC\n"); + /* ASSERT(0); */ + return; + } +#endif + + /* Check whether the BA agreement exists */ + prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[prSwRfb->ucTid]); + if (!prReorderQueParm) { + /* TODO: (Tehuang) Handle the Host-FW sync issue. */ + DBGLOG(QM, WARN, "QM: (Warning) BAR for a NULL ReorderQueParm\n"); + /* ASSERT(0); */ + return; + } + + u4SSN = (UINT_32) (prSwRfb->u2SSN); + prReorderQue = &(prReorderQueParm->rReOrderQue); + u4WinStart = (UINT_32) (prReorderQueParm->u2WinStart); + u4WinEnd = (UINT_32) (prReorderQueParm->u2WinEnd); + + if (qmCompareSnIsLessThan(u4WinStart, u4SSN)) { + prReorderQueParm->u2WinStart = (UINT_16) u4SSN; + prReorderQueParm->u2WinEnd = + ((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT; + DBGLOG(QM, TRACE, + "QM:(BAR)[%d](%u){%d,%d}\n", prSwRfb->ucTid, u4SSN, prReorderQueParm->u2WinStart, + prReorderQueParm->u2WinEnd); + qmPopOutDueToFallAhead(prAdapter, prReorderQueParm, prReturnedQue); + } else { + DBGLOG(QM, TRACE, "QM:(BAR)(%d)(%u){%u,%u}\n", prSwRfb->ucTid, u4SSN, u4WinStart, u4WinEnd); + } +} + +VOID qmInsertFallWithinReorderPkt(IN P_SW_RFB_T prSwRfb, IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue) +{ + P_SW_RFB_T prExaminedQueuedSwRfb; + P_QUE_T prReorderQue; + + ASSERT(prSwRfb); + ASSERT(prReorderQueParm); + ASSERT(prReturnedQue); + + prReorderQue = &(prReorderQueParm->rReOrderQue); + prExaminedQueuedSwRfb = (P_SW_RFB_T) QUEUE_GET_HEAD(prReorderQue); + + /* There are no packets queued in the Reorder Queue */ + if (prExaminedQueuedSwRfb == NULL) { + ((P_QUE_ENTRY_T) prSwRfb)->prPrev = NULL; + ((P_QUE_ENTRY_T) prSwRfb)->prNext = NULL; + prReorderQue->prHead = (P_QUE_ENTRY_T) prSwRfb; + prReorderQue->prTail = (P_QUE_ENTRY_T) prSwRfb; + prReorderQue->u4NumElem++; + } + + /* Determine the insert position */ + else { + do { + /* Case 1: Terminate. A duplicate packet */ + if ((prExaminedQueuedSwRfb->u2SSN) == (prSwRfb->u2SSN)) { + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); + return; + } + + /* Case 2: Terminate. The insert point is found */ + else if (qmCompareSnIsLessThan((prSwRfb->u2SSN), (prExaminedQueuedSwRfb->u2SSN))) + break; + + /* Case 3: Insert point not found. Check the next SW_RFB in the Reorder Queue */ + else + prExaminedQueuedSwRfb = (P_SW_RFB_T) (((P_QUE_ENTRY_T) prExaminedQueuedSwRfb)->prNext); + } while (prExaminedQueuedSwRfb); + + /* Update the Reorder Queue Parameters according to the found insert position */ + if (prExaminedQueuedSwRfb == NULL) { + /* The received packet shall be placed at the tail */ + ((P_QUE_ENTRY_T) prSwRfb)->prPrev = prReorderQue->prTail; + ((P_QUE_ENTRY_T) prSwRfb)->prNext = NULL; + (prReorderQue->prTail)->prNext = (P_QUE_ENTRY_T) (prSwRfb); + prReorderQue->prTail = (P_QUE_ENTRY_T) (prSwRfb); + } else { + ((P_QUE_ENTRY_T) prSwRfb)->prPrev = ((P_QUE_ENTRY_T) prExaminedQueuedSwRfb)->prPrev; + ((P_QUE_ENTRY_T) prSwRfb)->prNext = (P_QUE_ENTRY_T) prExaminedQueuedSwRfb; + if (((P_QUE_ENTRY_T) prExaminedQueuedSwRfb) == (prReorderQue->prHead)) { + /* The received packet will become the head */ + prReorderQue->prHead = (P_QUE_ENTRY_T) prSwRfb; + } else { + (((P_QUE_ENTRY_T) prExaminedQueuedSwRfb)->prPrev)->prNext = (P_QUE_ENTRY_T) prSwRfb; + } + ((P_QUE_ENTRY_T) prExaminedQueuedSwRfb)->prPrev = (P_QUE_ENTRY_T) prSwRfb; + } + + prReorderQue->u4NumElem++; + + } + DBGLOG(QM, TRACE, "qmInsertFallWithinReorderPkt SSN: %u\n", prSwRfb->u2SSN); +} + +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++; + DBGLOG(QM, TRACE, "qmInsertFallAheadReorderPkt SSN: %u\n", prSwRfb->u2SSN); +} + +BOOLEAN +qmPopOutDueToFallWithin(P_ADAPTER_T prAdapter, IN P_RX_BA_ENTRY_T prReorderQueParm, + OUT P_QUE_T prReturnedQue, OUT BOOLEAN *fgIsTimeout) +{ + P_SW_RFB_T prReorderedSwRfb; + P_QUE_T prReorderQue; + BOOLEAN fgDequeuHead, fgMissing; + OS_SYSTIME rCurrentTime, *prMissTimeout; + + prReorderQue = &(prReorderQueParm->rReOrderQue); + + *fgIsTimeout = FALSE; + fgMissing = FALSE; + rCurrentTime = 0; + prMissTimeout = &(g_arMissTimeout[prReorderQueParm->ucStaRecIdx][prReorderQueParm->ucTid]); + if ((*prMissTimeout)) { + fgMissing = TRUE; + GET_CURRENT_SYSTIME(&rCurrentTime); + } + + /* Check whether any packet can be indicated to the higher layer */ + while (TRUE) { + if (QUEUE_IS_EMPTY(prReorderQue)) + break; + + /* Always examine the head packet */ + prReorderedSwRfb = (P_SW_RFB_T) QUEUE_GET_HEAD(prReorderQue); + fgDequeuHead = FALSE; +#if CFG_RX_BA_REORDERING_ENHANCEMENT + qmHandleNoNeedWaitPktList(prReorderQueParm); +#endif + DBGLOG(QM, TRACE, "qmPopOutDueToFallWithin SSN: %u, WS: %u, WE: %u\n", + prReorderedSwRfb->u2SSN, prReorderQueParm->u2WinStart, prReorderQueParm->u2WinEnd); + + + /* 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 { + /* Start bubble timer */ + if (!prReorderQueParm->fgHasBubble) { + cnmTimerStartTimer(prAdapter, + &(prReorderQueParm->rReorderBubbleTimer), + prAdapter->u4QmRxBaMissTimeout); + prReorderQueParm->fgHasBubble = TRUE; + prReorderQueParm->u2FirstBubbleSn = prReorderQueParm->u2WinStart; + + DBGLOG(QM, TRACE, + "QM:Bub Timer STA[%u] TID[%u] BubSN[%u] Win{%d, %d}\n", + prReorderQueParm->ucStaRecIdx, prReorderedSwRfb->ucTid, + prReorderQueParm->u2FirstBubbleSn, + prReorderQueParm->u2WinStart, prReorderQueParm->u2WinEnd); + } + if ((fgMissing == TRUE) && + CHECK_FOR_TIMEOUT(rCurrentTime, (*prMissTimeout), + MSEC_TO_SYSTIME(prAdapter->u4QmRxBaMissTimeout))) { + DBGLOG(QM, TRACE, + "QM:RX BA Timout Next Tid %d SSN %d\n", prReorderQueParm->ucTid, + prReorderedSwRfb->u2SSN); + fgDequeuHead = TRUE; + prReorderQueParm->u2WinStart = (((prReorderedSwRfb->u2SSN) + 1) % MAX_SEQ_NO_COUNT); + + fgMissing = FALSE; + *fgIsTimeout = TRUE; + } else + break; + } + + /* Dequeue the head packet */ + if (fgDequeuHead) { + + if (((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext == NULL) { + prReorderQue->prHead = NULL; + prReorderQue->prTail = NULL; + } else { + prReorderQue->prHead = ((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext; + (((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext)->prPrev = NULL; + } + prReorderQue->u4NumElem--; + /* + * DbgPrint("QM: [%d] %d (%d)\n", + * prReorderQueParm->ucTid, + * prReorderedSwRfb->u2PacketLen, + * prReorderedSwRfb->u2SSN); + */ + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prReorderedSwRfb); + } + } + + if (QUEUE_IS_EMPTY(prReorderQue)) + *prMissTimeout = 0; + else { + if (fgMissing == FALSE) + GET_CURRENT_SYSTIME(prMissTimeout); + } + + /* After WinStart has been determined, update the WinEnd */ + prReorderQueParm->u2WinEnd = + (((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT); + return QUEUE_IS_EMPTY(prReorderQue); +} + +VOID qmPopOutDueToFallAhead(P_ADAPTER_T prAdapter, 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; +#if CFG_RX_BA_REORDERING_ENHANCEMENT + qmHandleNoNeedWaitPktList(prReorderQueParm); +#endif + DBGLOG(QM, TRACE, "qmPopOutDueToFallAhead SSN: %u, WS: %u, WE: %u\n", + prReorderedSwRfb->u2SSN, prReorderQueParm->u2WinStart, prReorderQueParm->u2WinEnd); + + /* 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 { + prReorderQueParm->fgHasBubbleInQue = TRUE; + /* Start bubble timer */ + if (!prReorderQueParm->fgHasBubble) { + cnmTimerStartTimer(prAdapter, + &(prReorderQueParm->rReorderBubbleTimer), + prAdapter->u4QmRxBaMissTimeout); + prReorderQueParm->fgHasBubble = TRUE; + prReorderQueParm->u2FirstBubbleSn = prReorderQueParm->u2WinStart; + + DBGLOG(QM, TRACE, + "QM:(Bub Timer) STA[%u] TID[%u] BubSN[%u] Win{%d, %d}\n", + prReorderQueParm->ucStaRecIdx, prReorderedSwRfb->ucTid, + prReorderQueParm->u2FirstBubbleSn, + prReorderQueParm->u2WinStart, prReorderQueParm->u2WinEnd); + } + break; + } + + /* Dequeue the head packet */ + if (fgDequeuHead) { + + if (((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext == NULL) { + prReorderQue->prHead = NULL; + prReorderQue->prTail = NULL; + } else { + prReorderQue->prHead = ((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext; + (((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext)->prPrev = NULL; + } + prReorderQue->u4NumElem--; + /* DbgPrint("QM: [%d] %d (%d)\n", */ + /* prReorderQueParm->ucTid, prReorderedSwRfb->u2PacketLen, prReorderedSwRfb->u2SSN); */ + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prReorderedSwRfb); + } + } + + /* After WinStart has been determined, update the WinEnd */ + prReorderQueParm->u2WinEnd = + (((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT); + +} + +BOOLEAN qmCompareSnIsLessThan(IN UINT_32 u4SnLess, IN UINT_32 u4SnGreater) +{ + /* 0 <---> SnLess <--(gap>2048)--> SnGreater : SnLess > SnGreater */ + if ((u4SnLess + HALF_SEQ_NO_COUNT) <= u4SnGreater) /* Shall be <= */ + return FALSE; + + /* 0 <---> SnGreater <--(gap>2048)--> SnLess : SnLess < SnGreater */ + else if ((u4SnGreater + HALF_SEQ_NO_COUNT) < u4SnLess) + return TRUE; + + /* 0 <---> SnGreater <--(gap<2048)--> SnLess : SnLess > SnGreater */ + /* 0 <---> SnLess <--(gap<2048)--> SnGreater : SnLess < SnGreater */ + else if (u4SnLess < u4SnGreater) + return TRUE; + else + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Handle Mailbox RX messages +* +* \param[in] prMailboxRxMsg The received Mailbox message from the FW +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmHandleMailboxRxMessage(IN MAILBOX_MSG_T prMailboxRxMsg) +{ + /* DbgPrint("QM: Enter qmHandleMailboxRxMessage()\n"); */ + /* TODO */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Handle ADD RX BA Event from the FW +* +* \param[in] prAdapter Adapter pointer +* \param[in] prEvent The event packet from the FW +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmHandleEventRxAddBa(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_EVENT_RX_ADDBA_T prEventRxAddBa; + P_STA_RECORD_T prStaRec; + UINT_32 u4Tid; + UINT_32 u4WinSize; + + DBGLOG(QM, INFO, "QM:Event +RxBa\n"); + + prEventRxAddBa = (P_EVENT_RX_ADDBA_T) prEvent; + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventRxAddBa->ucStaRecIdx); + + if (!prStaRec) { + /* Invalid STA_REC index, discard the event packet */ + /* ASSERT(0); */ + DBGLOG(QM, WARN, "QM: (Warning) RX ADDBA Event for a NULL STA_REC\n"); + return; + } +#if 0 + if (!(prStaRec->fgIsValid)) { + /* TODO: (Tehuang) Handle the Host-FW synchronization issue */ + DBGLOG(QM, WARN, "QM: (Warning) RX ADDBA Event for an invalid STA_REC\n"); + /* ASSERT(0); */ + /* return; */ + } +#endif + + u4Tid = (((prEventRxAddBa->u2BAParameterSet) & BA_PARAM_SET_TID_MASK) + >> BA_PARAM_SET_TID_MASK_OFFSET); + + u4WinSize = (((prEventRxAddBa->u2BAParameterSet) & BA_PARAM_SET_BUFFER_SIZE_MASK) + >> BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET); + + if (!qmAddRxBaEntry(prAdapter, + prStaRec->ucIndex, + (UINT_8) u4Tid, + (prEventRxAddBa->u2BAStartSeqCtrl >> OFFSET_BAR_SSC_SN), (UINT_16) u4WinSize)) { + + /* FW shall ensure the availabiilty of the free-to-use BA entry */ + DBGLOG(QM, ERROR, "QM: (Error) qmAddRxBaEntry() failure\n"); + ASSERT(0); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Handle DEL RX BA Event from the FW +* +* \param[in] prAdapter Adapter pointer +* \param[in] prEvent The event packet from the FW +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmHandleEventRxDelBa(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_EVENT_RX_DELBA_T prEventRxDelBa; + P_STA_RECORD_T prStaRec; + + /* DbgPrint("QM:Event -RxBa\n"); */ + + prEventRxDelBa = (P_EVENT_RX_DELBA_T) prEvent; + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventRxDelBa->ucStaRecIdx); + + if (!prStaRec) + /* Invalid STA_REC index, discard the event packet */ + /* ASSERT(0); */ + return; +#if 0 + if (!(prStaRec->fgIsValid)) + /* TODO: (Tehuang) Handle the Host-FW synchronization issue */ + /* ASSERT(0); */ + return; +#endif + + qmDelRxBaEntry(prAdapter, prStaRec->ucIndex, prEventRxDelBa->ucTid, TRUE); + +} + +P_RX_BA_ENTRY_T qmLookupRxBaEntry(IN P_ADAPTER_T prAdapter, UINT_8 ucStaRecIdx, UINT_8 ucTid) +{ + int i; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + /* DbgPrint("QM: Enter qmLookupRxBaEntry()\n"); */ + + for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) { + if (prQM->arRxBaTable[i].fgIsValid) { + if ((prQM->arRxBaTable[i].ucStaRecIdx == ucStaRecIdx) && (prQM->arRxBaTable[i].ucTid == ucTid)) + return &prQM->arRxBaTable[i]; + } + } + return NULL; +} + +BOOLEAN +qmAddRxBaEntry(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucStaRecIdx, IN UINT_8 ucTid, IN UINT_16 u2WinStart, IN UINT_16 u2WinSize) +{ + int i; + P_RX_BA_ENTRY_T prRxBaEntry = NULL; + P_STA_RECORD_T prStaRec; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + ASSERT(ucStaRecIdx < CFG_NUM_OF_STA_RECORD); + + if (ucStaRecIdx >= CFG_NUM_OF_STA_RECORD) { + /* Invalid STA_REC index, discard the event packet */ + DBGLOG(QM, WARN, "QM: (WARNING) RX ADDBA Event for a invalid ucStaRecIdx = %d\n", ucStaRecIdx); + return FALSE; + } + + prStaRec = &prAdapter->arStaRec[ucStaRecIdx]; + ASSERT(prStaRec); + + /* if(!(prStaRec->fgIsValid)){ */ + /* DbgPrint("QM: (WARNING) Invalid STA when adding an RX BA\n"); */ + /* return FALSE; */ + /* } */ + + /* 4 <1> Delete before adding */ + /* Remove the BA entry for the same (STA, TID) tuple if it exists */ + if (qmLookupRxBaEntry(prAdapter, ucStaRecIdx, ucTid)) + qmDelRxBaEntry(prAdapter, ucStaRecIdx, ucTid, TRUE); /* prQM->ucRxBaCount-- */ + /* 4 <2> Add a new BA entry */ + /* No available entry to store the BA agreement info. Retrun FALSE. */ + if (prQM->ucRxBaCount >= CFG_NUM_OF_RX_BA_AGREEMENTS) { + DBGLOG(QM, ERROR, "QM: **failure** (limited resource, ucRxBaCount=%d)\n", prQM->ucRxBaCount); + return FALSE; + } + /* Find the free-to-use BA entry */ + for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) { + if (!prQM->arRxBaTable[i].fgIsValid) { + prRxBaEntry = &(prQM->arRxBaTable[i]); + prQM->ucRxBaCount++; + DBGLOG(QM, LOUD, "QM: ucRxBaCount=%d\n", prQM->ucRxBaCount); + break; + } + } + /* If a free-to-use entry is found, configure it and associate it with the STA_REC */ + u2WinSize += CFG_RX_BA_INC_SIZE; + if (prRxBaEntry) { + prRxBaEntry->ucStaRecIdx = ucStaRecIdx; + prRxBaEntry->ucTid = ucTid; + prRxBaEntry->u2WinStart = u2WinStart; + prRxBaEntry->u2WinSize = u2WinSize; + prRxBaEntry->u2WinEnd = ((u2WinStart + u2WinSize - 1) % MAX_SEQ_NO_COUNT); + prRxBaEntry->fgIsValid = TRUE; + prRxBaEntry->fgIsWaitingForPktWithSsn = TRUE; + prRxBaEntry->fgHasBubble = FALSE; + + 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 (prRxBaEntry->fgHasBubble) { + DBGLOG(QM, TRACE, "QM:(Bub Check Cancel) STA[%u] TID[%u], DELBA\n", + prRxBaEntry->ucStaRecIdx, prRxBaEntry->ucTid); + + cnmTimerStopTimer(prAdapter, &prRxBaEntry->rReorderBubbleTimer); + prRxBaEntry->fgHasBubble = FALSE; + } +#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 +} + +#if CFG_RX_BA_REORDERING_ENHANCEMENT +VOID qmInsertNoNeedWaitPkt(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, IN ENUM_NO_NEED_WATIT_DROP_REASON_T eDropReason) +{ + P_STA_RECORD_T prStaRec; + P_RX_BA_ENTRY_T prRxBaEntry; + P_NO_NEED_WAIT_PKT_T prNoNeedWaitPkt; + + /* Check whether the STA_REC is activated */ + prStaRec = &(prAdapter->arStaRec[prSwRfb->ucStaRecIdx]); + ASSERT(prStaRec); + + prRxBaEntry = ((prStaRec->aprRxReorderParamRefTbl)[prSwRfb->ucTid]); + + if (!(prRxBaEntry) || !(prRxBaEntry->fgIsValid)) { + DBGLOG(QM, WARN, "qmInsertNoNeedWaitPkt for a NULL ReorderQueParm, SSN:[%u], DropReason:(%d)\n", + prSwRfb->u2SSN, eDropReason); + return; + } + + prNoNeedWaitPkt = (P_NO_NEED_WAIT_PKT_T) kalMemAlloc(sizeof(NO_NEED_WAIT_PKT_T), VIR_MEM_TYPE); + + if (prNoNeedWaitPkt == NULL) { + DBGLOG(QM, ERROR, "qmInsertNoNeedWaitPkt alloc error SSN:[%u], DropReason:(%d)\n", + prSwRfb->u2SSN, eDropReason); + return; + } + + prNoNeedWaitPkt->u2SSN = prSwRfb->u2SSN; + prNoNeedWaitPkt->eDropReason = eDropReason; + if (eDropReason == PACKET_DROP_BY_FW) + DBGLOG(QM, INFO, "qmInsertNoNeedWaitPkt SSN:[%u], DropReason:(%d)\n", prSwRfb->u2SSN, eDropReason); + else + DBGLOG(QM, TRACE, "qmInsertNoNeedWaitPkt SSN:[%u], DropReason:(%d)\n", prSwRfb->u2SSN, eDropReason); + QUEUE_INSERT_TAIL(&(prRxBaEntry->rNoNeedWaitQue), (P_QUE_ENTRY_T) prNoNeedWaitPkt); +} + +VOID qmHandleEventDropByFW(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_EVENT_PACKET_DROP_BY_FW_T prDropSSNEvt = (P_EVENT_PACKET_DROP_BY_FW_T) prEvent; + P_RX_BA_ENTRY_T prRxBaEntry; + UINT_16 u2StartSSN; + UINT_8 u1BitmapSSN; + UINT_8 u1SetCount, u1Count; + UINT_16 u2OfCount; + SW_RFB_T rSwRfb; + + u2StartSSN = QM_GET_DROP_BY_FW_SSN(prDropSSNEvt->u2StartSSN); + + /* Get target Rx BA entry */ + prRxBaEntry = qmLookupRxBaEntry(prAdapter, prDropSSNEvt->ucStaRecIdx, prDropSSNEvt->ucTid); + rSwRfb.ucTid = prDropSSNEvt->ucTid; + rSwRfb.ucStaRecIdx = prDropSSNEvt->ucStaRecIdx; + + /* Sanity Check */ + if (!prRxBaEntry) { + DBGLOG(QM, ERROR, "qmHandleEventDropByFW STA[%u] TID[%u], No Rx BA entry\n", + prDropSSNEvt->ucStaRecIdx, prDropSSNEvt->ucTid); + return; + } + + u2OfCount = 0; + + for (u1SetCount = 0; u1SetCount < QM_RX_MAX_FW_DROP_SSN_SIZE; u1SetCount++) { + u1BitmapSSN = prDropSSNEvt->au1BitmapSSN[u1SetCount]; + + for (u1Count = 0; u1Count < 8; u1Count++) { + if ((u1BitmapSSN & BIT(0)) == 1) { + rSwRfb.u2SSN = u2StartSSN + u2OfCount; + qmInsertNoNeedWaitPkt(prAdapter, &rSwRfb, PACKET_DROP_BY_FW); + } + u1BitmapSSN >>= 1; + u2OfCount++; + } + } +} + +VOID qmHandleNoNeedWaitPktList(IN P_RX_BA_ENTRY_T prReorderQueParm) +{ + P_QUE_T prNoNeedWaitQue; + P_NO_NEED_WAIT_PKT_T prNoNeedWaitPkt; + P_NO_NEED_WAIT_PKT_T prNoNeedWaitNextPkt; + UINT_16 u2SSN, u2WinStart, u2WinEnd, u2AheadPoint; + + if (prReorderQueParm == NULL) { + DBGLOG(QM, ERROR, "qmHandleNoNeedWaitPktList for a NULL prReorderQueParm\n"); + return; + } + + prNoNeedWaitQue = &(prReorderQueParm->rNoNeedWaitQue); + + if (QUEUE_IS_NOT_EMPTY(prNoNeedWaitQue)) { + prNoNeedWaitPkt = (P_NO_NEED_WAIT_PKT_T) QUEUE_GET_HEAD(prNoNeedWaitQue); + + u2SSN = prNoNeedWaitPkt->u2SSN; + u2WinStart = prReorderQueParm->u2WinStart; + u2WinEnd = prReorderQueParm->u2WinEnd; + + /* Remove all packets that SSN is less than WinStart */ + do { + u2SSN = prNoNeedWaitPkt->u2SSN; + prNoNeedWaitNextPkt = + (P_NO_NEED_WAIT_PKT_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prNoNeedWaitPkt); + + u2AheadPoint = u2WinStart + HALF_SEQ_NO_COUNT; + if (u2AheadPoint >= MAX_SEQ_NO_COUNT) + u2AheadPoint -= MAX_SEQ_NO_COUNT; + + if /*0: End - AheadPoint - SSN - Start :4095*/ + (((u2SSN < u2WinStart) + && (u2AheadPoint < u2SSN) + && (u2WinEnd < u2AheadPoint)) + /*0: Start - End - AheadPoint - SSN :4095*/ + || ((u2AheadPoint < u2SSN) + && (u2WinEnd < u2AheadPoint) + && (u2WinStart < u2WinEnd)) + /*0: SSN - Start - End - AheadPhoint :4095*/ + || ((u2WinEnd < u2AheadPoint) + && (u2WinStart < u2WinEnd) + && (u2SSN < u2WinStart)) + /*0: AheadPoint - SSN - Start - End :4095*/ + || ((u2WinStart < u2WinEnd) + && (u2SSN < u2WinStart) + && (u2AheadPoint < u2SSN))) { + + QUEUE_REMOVE_HEAD(prNoNeedWaitQue, prNoNeedWaitPkt, P_NO_NEED_WAIT_PKT_T); + kalMemFree(prNoNeedWaitPkt, VIR_MEM_TYPE, sizeof(NO_NEED_WAIT_PKT_T)); + + DBGLOG(QM, TRACE, "qmHandleNoNeedWaitPktList Remove SSN:[%u], WS:%u, WE:%u\n", + u2SSN, u2WinStart, u2WinEnd); + } + + + prNoNeedWaitPkt = prNoNeedWaitNextPkt; + } while (prNoNeedWaitPkt); + + /* Adjust WinStart if current WinStart is contain in NoNeedWaitQue */ + while ((prNoNeedWaitPkt = + qmSearchNoNeedWaitPktBySSN(prReorderQueParm, prReorderQueParm->u2WinStart)) != NULL) { + prReorderQueParm->u2WinStart = (((prNoNeedWaitPkt->u2SSN) + 1) % MAX_SEQ_NO_COUNT); + prReorderQueParm->u2WinEnd = + (((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT); + QUEUE_REMOVE_HEAD(prNoNeedWaitQue, prNoNeedWaitPkt, P_NO_NEED_WAIT_PKT_T); + kalMemFree(prNoNeedWaitPkt, VIR_MEM_TYPE, sizeof(NO_NEED_WAIT_PKT_T)); + } + } +} + +VOID qmHandleNoNeedWaitStopBubTimer(IN P_ADAPTER_T prAdapter, IN P_RX_BA_ENTRY_T prReorderQueParm) +{ + QUE_T rReturnedQue; + P_QUE_T prReturnedQue = &rReturnedQue; + P_SW_RFB_T prSwRfb; + + QUEUE_INITIALIZE(prReturnedQue); + prReorderQueParm->fgHasBubbleInQue = FALSE; + + qmPopOutDueToFallAhead(prAdapter, prReorderQueParm, prReturnedQue); + + DBGLOG(QM, INFO, "qmHandleNoNeedWaitStopBubTimer BubInQue[%d] STA[%u] TID[%u] BubSN[%u] Win{%d, %d}\n", + prReorderQueParm->fgHasBubbleInQue, + prReorderQueParm->ucStaRecIdx, + prReorderQueParm->ucTid, + prReorderQueParm->u2FirstBubbleSn, + prReorderQueParm->u2WinStart, prReorderQueParm->u2WinEnd); + + if (prReorderQueParm->fgHasBubbleInQue == FALSE) { + /* Stop bubble timer if there are no bubbles in reorder queue. */ + cnmTimerStopTimer(prAdapter, &(prReorderQueParm->rReorderBubbleTimer)); + + prReorderQueParm->fgHasBubble = FALSE; + + if (QUEUE_IS_NOT_EMPTY(prReturnedQue)) { + QM_TX_SET_NEXT_MSDU_INFO((P_SW_RFB_T) QUEUE_GET_TAIL(prReturnedQue), NULL); + + prSwRfb = (P_SW_RFB_T) QUEUE_GET_HEAD(prReturnedQue); + while (prSwRfb) { + DBGLOG(QM, TRACE, + "qmHandleNoNeedWaitStopBubTimer Flush STA[%u] TID[%u] Pop Out SN[%u]\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid, prSwRfb->u2SSN); + + prSwRfb = (P_SW_RFB_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prSwRfb); + } + + wlanProcessQueuedSwRfb(prAdapter, (P_SW_RFB_T) QUEUE_GET_HEAD(prReturnedQue)); + } else { + DBGLOG(QM, TRACE, "qmHandleNoNeedWaitStopBubTimer Flush STA[%u] TID[%u] Pop Out 0 packet\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + } + } + + qmHandleMissTimeout(prReorderQueParm); +} + +P_NO_NEED_WAIT_PKT_T qmSearchNoNeedWaitPktBySSN(IN P_RX_BA_ENTRY_T prReorderQueParm, IN UINT_32 u2SSN) +{ + P_QUE_T prNoNeedWaitQue = NULL; + P_NO_NEED_WAIT_PKT_T prNoNeedWaitPkt = NULL; + + prNoNeedWaitQue = &(prReorderQueParm->rNoNeedWaitQue); + + if (QUEUE_IS_NOT_EMPTY(prNoNeedWaitQue)) { + prNoNeedWaitPkt = (P_NO_NEED_WAIT_PKT_T) QUEUE_GET_HEAD(prNoNeedWaitQue); + + do { + if (prNoNeedWaitPkt->u2SSN == u2SSN) + return prNoNeedWaitPkt; + + prNoNeedWaitPkt = (P_NO_NEED_WAIT_PKT_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prNoNeedWaitPkt); + } while (prNoNeedWaitPkt); + } + + return NULL; +} + +VOID qmRemoveAllNoNeedWaitPkt(IN P_RX_BA_ENTRY_T prReorderQueParm) +{ + P_QUE_T prNoNeedWaitQue; + P_NO_NEED_WAIT_PKT_T prNoNeedWaitPkt; + P_NO_NEED_WAIT_PKT_T prNoNeedWaitNextPkt; + + prNoNeedWaitQue = &(prReorderQueParm->rNoNeedWaitQue); + + if (QUEUE_IS_NOT_EMPTY(prNoNeedWaitQue)) { + prNoNeedWaitPkt = (P_NO_NEED_WAIT_PKT_T) QUEUE_GET_HEAD(prNoNeedWaitQue); + + do { + prNoNeedWaitNextPkt = + (P_NO_NEED_WAIT_PKT_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prNoNeedWaitPkt); + QUEUE_REMOVE_HEAD(prNoNeedWaitQue, prNoNeedWaitPkt, P_NO_NEED_WAIT_PKT_T); + kalMemFree(prNoNeedWaitPkt, VIR_MEM_TYPE, sizeof(NO_NEED_WAIT_PKT_T)); + prNoNeedWaitPkt = prNoNeedWaitNextPkt; + } while (prNoNeedWaitNextPkt); + } +} + +VOID qmDumpNoNeedWaitPkt(IN P_RX_BA_ENTRY_T prReorderQueParm) +{ + P_QUE_T prNoNeedWaitQue; + P_NO_NEED_WAIT_PKT_T prNoNeedWaitPkt; + + prNoNeedWaitQue = &(prReorderQueParm->rNoNeedWaitQue); + + if (QUEUE_IS_NOT_EMPTY(prNoNeedWaitQue)) { + prNoNeedWaitPkt = (P_NO_NEED_WAIT_PKT_T) QUEUE_GET_HEAD(prNoNeedWaitQue); + + do { + DBGLOG(QM, INFO, "qmDumpNoNeedWaitPkt > SSN:[%u] DropReason:(%d)\n", + prNoNeedWaitPkt->u2SSN, prNoNeedWaitPkt->eDropReason); + prNoNeedWaitPkt = (P_NO_NEED_WAIT_PKT_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prNoNeedWaitPkt); + } while (prNoNeedWaitPkt); + } else + DBGLOG(QM, INFO, "qmDumpNoNeedWaitPkt > QUEUE EMPTY\n"); +} + +BOOLEAN qmIsIndependentPkt(IN P_SW_RFB_T prSwRfb) +{ + PUINT_8 pucPkt = prSwRfb->pvHeader; + UINT_16 u2EtherType = kalGetPktEtherType(pucPkt); + BOOLEAN fgIsIndependent = FALSE; + + switch (u2EtherType) { + case ENUM_PKT_ARP: + case ENUM_PKT_ICMP: + case ENUM_PKT_DHCP: + case ENUM_PKT_DNS: + fgIsIndependent = TRUE; + break; + default: + break; + } + + DBGLOG(QM, TRACE, "qmIsIndependentPkt type:%d,fgIsIndependent %d\n", u2EtherType, fgIsIndependent); + + return fgIsIndependent; + +} +VOID qmProcessIndepentReorderQueue(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_RX_BA_ENTRY_T prRxBaEntry; + + if ((prSwRfb == NULL) || (prSwRfb->prHifRxHdr == NULL)) { + ASSERT(FALSE); + return; + } + + prSwRfb->u2SSN = HIF_RX_HDR_GET_SN(prSwRfb->prHifRxHdr); + prSwRfb->ucTid = (UINT_8) (HIF_RX_HDR_GET_TID(prSwRfb->prHifRxHdr)); + + /* Insert to NoNeedWaitPkt queue */ + qmInsertNoNeedWaitPkt(prAdapter, prSwRfb, PACKET_DROP_BY_INDEPENDENT_PKT); + + /* handle NoNeedWaitPkt queue*/ + prRxBaEntry = qmLookupRxBaEntry(prAdapter, prSwRfb->ucStaRecIdx, prSwRfb->ucTid); + + if (!(prRxBaEntry) || !(prRxBaEntry->fgIsValid)) { + DBGLOG(QM, ERROR, "qmProcessIndepentReorderQueue for a NULL prRxBaEntry\n"); + return; + } + qmHandleNoNeedWaitPktList(prRxBaEntry); + +} + +#endif + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To process WMM related IEs in ASSOC_RSP +* +* \param[in] prAdapter Adapter pointer +* \param[in] prSwRfb The received frame +* \param[in] pucIE The pointer to the first IE in the frame +* \param[in] u2IELength The total length of IEs in the frame +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mqmProcessAssocReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength) +{ + P_STA_RECORD_T prStaRec; + UINT_16 u2Offset; + PUINT_8 pucIEStart; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + P_IE_WMM_INFO_T prIeWmmInfo; + UINT_8 ucQosInfo; + UINT_8 ucQosInfoAC; + UINT_8 ucBmpAC; + + DEBUGFUNC("mqmProcessAssocReq"); + + ASSERT(prSwRfb); + ASSERT(pucIE); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ASSERT(prStaRec); + + if (prStaRec == NULL) + return; + + prStaRec->fgIsQoS = FALSE; + prStaRec->fgIsWmmSupported = prStaRec->fgIsUapsdSupported = FALSE; + + pucIEStart = pucIE; + + /* If the device does not support QoS or if WMM is not supported by the peer, exit. */ + if (!prAdapter->rWifiVar.fgSupportQoS) + return; + + /* Determine whether QoS is enabled with the association */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_WMM: + + if ((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) && + (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) { + switch (WMM_IE_OUI_SUBTYPE(pucIE)) { + case VENDOR_OUI_SUBTYPE_WMM_INFO: + if (IE_LEN(pucIE) != 7) + break; /* WMM Info IE with a wrong length */ + prStaRec->fgIsQoS = TRUE; + prStaRec->fgIsWmmSupported = TRUE; + + prIeWmmInfo = (P_IE_WMM_INFO_T) pucIE; + ucQosInfo = prIeWmmInfo->ucQosInfo; + ucQosInfoAC = ucQosInfo & BITS(0, 3); + + prStaRec->fgIsUapsdSupported = ((ucQosInfoAC) ? TRUE : FALSE) & + prAdapter->rWifiVar.fgSupportUAPSD; + + ucBmpAC = 0; + + if (ucQosInfoAC & WMM_QOS_INFO_VO_UAPSD) + ucBmpAC |= BIT(ACI_VO); + if (ucQosInfoAC & WMM_QOS_INFO_VI_UAPSD) + ucBmpAC |= BIT(ACI_VI); + if (ucQosInfoAC & WMM_QOS_INFO_BE_UAPSD) + ucBmpAC |= BIT(ACI_BE); + if (ucQosInfoAC & WMM_QOS_INFO_BK_UAPSD) + ucBmpAC |= BIT(ACI_BK); + + prStaRec->ucBmpTriggerAC = prStaRec->ucBmpDeliveryAC = ucBmpAC; + + prStaRec->ucUapsdSp = + (ucQosInfo & WMM_QOS_INFO_MAX_SP_LEN_MASK) >> 5; + break; + default: + /* Other WMM QoS IEs. Ignore any */ + break; + } + } + /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS */ + + break; + + case ELEM_ID_HT_CAP: + /* Some client won't put the WMM IE if client is 802.11n */ + if (IE_LEN(pucIE) == (sizeof(IE_HT_CAP_T) - 2)) + prStaRec->fgIsQoS = TRUE; + break; + default: + break; + } + } + + DBGLOG(QM, TRACE, "MQM: Assoc_Req Parsing (QoS Enabled=%d)\n", prStaRec->fgIsQoS); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To process WMM related IEs in ASSOC_RSP +* +* \param[in] prAdapter Adapter pointer +* \param[in] prSwRfb The received frame +* \param[in] pucIE The pointer to the first IE in the frame +* \param[in] u2IELength The total length of IEs in the frame +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mqmProcessAssocRsp(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength) +{ + P_STA_RECORD_T prStaRec; + UINT_16 u2Offset; + PUINT_8 pucIEStart; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + + + DEBUGFUNC("mqmProcessAssocRsp"); + + ASSERT(prSwRfb); + ASSERT(pucIE); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ASSERT(prStaRec); + + if (prStaRec == NULL) + return; + + prStaRec->fgIsQoS = FALSE; + + pucIEStart = pucIE; + + DBGLOG(QM, TRACE, "QM: (fgIsWmmSupported=%d, fgSupportQoS=%d)\n", + prStaRec->fgIsWmmSupported, prAdapter->rWifiVar.fgSupportQoS); + + /* If the device does not support QoS or if WMM is not supported by the peer, exit. */ + /* if((!prAdapter->rWifiVar.fgSupportQoS) || (!prStaRec->fgIsWmmSupported)) */ + if ((!prAdapter->rWifiVar.fgSupportQoS)) + return; + + /* Determine whether QoS is enabled with the association */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_WMM: + if ((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) && + (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) { + + switch (WMM_IE_OUI_SUBTYPE(pucIE)) { + case VENDOR_OUI_SUBTYPE_WMM_PARAM: + if (IE_LEN(pucIE) != 24) + break; /* WMM Info IE with a wrong length */ + prStaRec->fgIsQoS = TRUE; + break; + + case VENDOR_OUI_SUBTYPE_WMM_INFO: + if (IE_LEN(pucIE) != 7) + break; /* WMM Info IE with a wrong length */ + prStaRec->fgIsQoS = TRUE; + break; + + default: + /* Other WMM QoS IEs. Ignore any */ + break; + } + } + /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS */ + break; + + case ELEM_ID_HT_CAP: + /* Some AP won't put the WMM IE if client is 802.11n */ + if (IE_LEN(pucIE) == (sizeof(IE_HT_CAP_T) - 2)) + prStaRec->fgIsQoS = TRUE; + break; + case ELEM_ID_QOS_MAP_SET: + DBGLOG(QM, WARN, "QM: received assoc resp qosmapset ie\n"); + qosParseQosMapSet(prAdapter, prStaRec, pucIE); + default: + break; + } + } + + /* Parse AC parameters and write to HW CRs */ + if (prStaRec->fgIsQoS) { + mqmParseEdcaParameters(prAdapter, prSwRfb, pucIEStart, u2IELength, TRUE); +#if ARP_MONITER_ENABLE + qmResetArpDetect(); +#endif + } + + DBGLOG(QM, TRACE, "MQM: Assoc_Rsp Parsing (QoS Enabled=%d)\n", prStaRec->fgIsQoS); + if (prStaRec->fgIsWmmSupported) + nicQmUpdateWmmParms(prAdapter, prStaRec->ucNetTypeIndex); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To parse WMM Parameter IE (in BCN or Assoc_Rsp) +* +* \param[in] prAdapter Adapter pointer +* \param[in] prSwRfb The received frame +* \param[in] pucIE The pointer to the first IE in the frame +* \param[in] u2IELength The total length of IEs in the frame +* \param[in] fgForceOverride TRUE: If EDCA parameters are found, always set to HW CRs. +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +mqmParseEdcaParameters(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength, IN BOOLEAN fgForceOverride) +{ + P_STA_RECORD_T prStaRec; + UINT_16 u2Offset; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + P_BSS_INFO_T prBssInfo; + P_AC_QUE_PARMS_T prAcQueParams; + P_IE_WMM_PARAM_T prIeWmmParam; + ENUM_WMM_ACI_T eAci; + PUINT_8 pucWmmParamSetCount; + + DEBUGFUNC("mqmParseEdcaParameters"); + + ASSERT(prSwRfb); + ASSERT(pucIE); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ASSERT(prStaRec); + if (prStaRec == NULL) + return; + + DBGLOG(QM, TRACE, "QM: (fgIsWmmSupported=%d, fgIsQoS=%d)\n", prStaRec->fgIsWmmSupported, prStaRec->fgIsQoS); + + if ((!prAdapter->rWifiVar.fgSupportQoS) || (!prStaRec->fgIsWmmSupported) || (!prStaRec->fgIsQoS)) + return; + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + /* Goal: Obtain the EDCA parameters */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_WMM: + if ((WMM_IE_OUI_TYPE(pucIE) != VENDOR_OUI_TYPE_WMM) || + (kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) + break; + + switch (WMM_IE_OUI_SUBTYPE(pucIE)) { + case VENDOR_OUI_SUBTYPE_WMM_PARAM: + if (IE_LEN(pucIE) != 24) + break; /* WMM Param IE with a wrong length */ + + pucWmmParamSetCount = &(prBssInfo->ucWmmParamSetCount); + prIeWmmParam = (P_IE_WMM_PARAM_T) pucIE; + + /* Check the Parameter Set Count to determine whether EDCA parameters */ + /* have been changed */ + if (!fgForceOverride && (*pucWmmParamSetCount + == (prIeWmmParam->ucQosInfo & WMM_QOS_INFO_PARAM_SET_CNT))) + break; /* Ignore the IE without updating HW CRs */ + + /* Update Parameter Set Count */ + *pucWmmParamSetCount = + (prIeWmmParam->ucQosInfo & WMM_QOS_INFO_PARAM_SET_CNT); + + /* Update EDCA parameters */ + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + + prAcQueParams = &prBssInfo->arACQueParms[eAci]; + mqmFillAcQueParam(prIeWmmParam, eAci, prAcQueParams); + + prAcQueParams->fgIsACMSet = + (prAcQueParams->u2Aifsn & WMM_ACIAIFSN_ACM) ? TRUE : FALSE; + prAcQueParams->u2Aifsn &= WMM_ACIAIFSN_AIFSN; + + DBGLOG(QM, LOUD, + "eAci:%d, ACM:%d, Aifsn:%d, CWmin:%d, CWmax:%d, TxopLmt:%d\n", + eAci, prAcQueParams->fgIsACMSet, prAcQueParams->u2Aifsn, + prAcQueParams->u2CWmin, prAcQueParams->u2CWmax, + prAcQueParams->u2TxopLimit); + } + break; + default: + /* Other WMM QoS IEs. Ignore */ + break; + } + + /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS, ... (not cared) */ + break; + default: + break; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used for parsing EDCA parameters specified in the WMM Parameter IE +* +* \param[in] prAdapter Adapter pointer +* \param[in] prIeWmmParam The pointer to the WMM Parameter IE +* \param[in] u4AcOffset The offset specifying the AC queue for parsing +* \param[in] prHwAcParams The parameter structure used to configure the HW CRs +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mqmFillAcQueParam(IN P_IE_WMM_PARAM_T prIeWmmParam, IN UINT_32 u4AcOffset, OUT P_AC_QUE_PARMS_T prAcQueParams) +{ + prAcQueParams->u2Aifsn = *((PUINT_8) (&(prIeWmmParam->ucAciAifsn_BE)) + (u4AcOffset * 4)); + + prAcQueParams->u2CWmax = BIT(((*((PUINT_8) (&(prIeWmmParam->ucEcw_BE)) + (u4AcOffset * 4))) & WMM_ECW_WMAX_MASK) + >> WMM_ECW_WMAX_OFFSET) - 1; + + prAcQueParams->u2CWmin = + BIT((*((PUINT_8) (&(prIeWmmParam->ucEcw_BE)) + (u4AcOffset * 4))) & WMM_ECW_WMIN_MASK) - 1; + + WLAN_GET_FIELD_16(((PUINT_8) (&(prIeWmmParam->aucTxopLimit_BE)) + (u4AcOffset * 4)), + &(prAcQueParams->u2TxopLimit)); + + prAcQueParams->ucGuradTime = TXM_DEFAULT_FLUSH_QUEUE_GUARD_TIME; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To parse WMM/11n related IEs in scan results (only for AP peers) +* +* \param[in] prAdapter Adapter pointer +* \param[in] prScanResult The scan result which shall be parsed to obtain needed info +* \param[out] prStaRec The obtained info is stored in the STA_REC +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +#if (CFG_SUPPORT_TDLS == 1) /* for test purpose */ +BOOLEAN flgTdlsTestExtCapElm = FALSE; +UINT8 aucTdlsTestExtCapElm[7]; +#endif /* CFG_SUPPORT_TDLS */ +VOID mqmProcessScanResult(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prScanResult, OUT P_STA_RECORD_T prStaRec) +{ + PUINT_8 pucIE; + UINT_16 u2IELength; + UINT_16 u2Offset; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + + DEBUGFUNC("mqmProcessScanResult"); + + ASSERT(prScanResult); + ASSERT(prStaRec); + + /* Reset the flag before parsing */ + prStaRec->fgIsWmmSupported = prStaRec->fgIsUapsdSupported = FALSE; + + if (!prAdapter->rWifiVar.fgSupportQoS) + return; + + u2IELength = prScanResult->u2IELength; + pucIE = prScanResult->aucIEBuf; + +#if (CFG_SUPPORT_TDLS == 1) + /* TDLS test purpose */ + if (flgTdlsTestExtCapElm == TRUE) + TdlsexBssExtCapParse(prStaRec, aucTdlsTestExtCapElm); +#endif /* CFG_SUPPORT_TDLS */ + + /* Goal: Determine whether the peer supports WMM/QoS and UAPSDU */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_EXTENDED_CAP: +#if (CFG_SUPPORT_TDLS == 1) + TdlsexBssExtCapParse(prStaRec, pucIE); +#endif /* CFG_SUPPORT_TDLS */ +#if CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT + prStaRec->fgSupportBTM = !!((*(PUINT_32)(pucIE+2)) & BIT(ELEM_EXT_CAP_BSS_TRANSITION_BIT)); +#endif + break; + + case ELEM_ID_WMM: + if ((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) && + (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) { + + switch (WMM_IE_OUI_SUBTYPE(pucIE)) { + case VENDOR_OUI_SUBTYPE_WMM_PARAM: + if (IE_LEN(pucIE) != 24) + break; /* WMM Param IE with a wrong length */ + + prStaRec->fgIsWmmSupported = TRUE; + prStaRec->fgIsUapsdSupported = + (((((P_IE_WMM_PARAM_T) pucIE)->ucQosInfo) & WMM_QOS_INFO_UAPSD) ? + TRUE : FALSE); + + prStaRec->afgAcmRequired[ACI_BE] = + (((P_IE_WMM_PARAM_T)pucIE)->ucAciAifsn_BE & WMM_ACIAIFSN_ACM) ? + TRUE : FALSE; + prStaRec->afgAcmRequired[ACI_BK] = + (((P_IE_WMM_PARAM_T)pucIE)->ucAciAifsn_BG & WMM_ACIAIFSN_ACM) ? + TRUE : FALSE; + prStaRec->afgAcmRequired[ACI_VI] = + (((P_IE_WMM_PARAM_T)pucIE)->ucAciAifsn_VI & WMM_ACIAIFSN_ACM) ? + TRUE : FALSE; + prStaRec->afgAcmRequired[ACI_VO] = + (((P_IE_WMM_PARAM_T)pucIE)->ucAciAifsn_VO & WMM_ACIAIFSN_ACM) ? + TRUE : FALSE; + DBGLOG(WMM, INFO, "WMM: "MACSTR "ACM BK=%d BE=%d VI=%d VO=%d\n", + MAC2STR(prStaRec->aucMacAddr), + prStaRec->afgAcmRequired[ACI_BK], + prStaRec->afgAcmRequired[ACI_BE], + prStaRec->afgAcmRequired[ACI_VI], + prStaRec->afgAcmRequired[ACI_VO]); + break; + + case VENDOR_OUI_SUBTYPE_WMM_INFO: + if (IE_LEN(pucIE) != 7) + break; /* WMM Info IE with a wrong length */ + + prStaRec->fgIsWmmSupported = TRUE; + prStaRec->fgIsUapsdSupported = + (((((P_IE_WMM_INFO_T) pucIE)->ucQosInfo) & WMM_QOS_INFO_UAPSD) ? + TRUE : FALSE); + break; + + default: + /* A WMM QoS IE that doesn't matter. Ignore it. */ + break; + } + } + /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS, ... (not cared) */ + + break; + + default: + /* A WMM IE that doesn't matter. Ignore it. */ + break; + } + } + DBGLOG(QM, LOUD, "MQM: Scan Result Parsing (WMM=%d, UAPSD=%d)\n", + prStaRec->fgIsWmmSupported, prStaRec->fgIsUapsdSupported); + +} + +UINT_8 qmGetStaRecIdx(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEthDestAddr, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType) +{ + UINT_32 i; + P_STA_RECORD_T prTempStaRec; + + prTempStaRec = NULL; + + ASSERT(prAdapter); + + /* 4 <1> DA = BMCAST */ + if (IS_BMCAST_MAC_ADDR(pucEthDestAddr)) + return STA_REC_INDEX_BMCAST; + /* 4 <2> Check if an AP STA is present */ + for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++) { + prTempStaRec = &(prAdapter->arStaRec[i]); + if ((prTempStaRec->ucNetTypeIndex == eNetworkType) + && (prTempStaRec->fgIsAp) + && (prTempStaRec->fgIsValid)) { + return prTempStaRec->ucIndex; + } + } + + /* 4 <3> Not BMCAST, No AP --> Compare DA (i.e., to see whether this is a unicast frame to a client) */ + for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++) { + prTempStaRec = &(prAdapter->arStaRec[i]); + if (prTempStaRec->fgIsValid) { + if (EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, pucEthDestAddr)) + return prTempStaRec->ucIndex; + } + } + + /* 4 <4> No STA found, Not BMCAST --> Indicate NOT_FOUND to FW */ + return STA_REC_INDEX_NOT_FOUND; +} + +UINT_32 +mqmGenerateWmmInfoIEByParam(BOOLEAN fgSupportUAPSD, + UINT_8 ucBmpDeliveryAC, UINT_8 ucBmpTriggerAC, UINT_8 ucUapsdSp, UINT_8 *pOutBuf) +{ + P_IE_WMM_INFO_T prIeWmmInfo; + UINT_32 ucUapsd[] = { + WMM_QOS_INFO_BE_UAPSD, + WMM_QOS_INFO_BK_UAPSD, + WMM_QOS_INFO_VI_UAPSD, + WMM_QOS_INFO_VO_UAPSD + }; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + + ASSERT(pOutBuf); + + prIeWmmInfo = (P_IE_WMM_INFO_T) pOutBuf; + + prIeWmmInfo->ucId = ELEM_ID_WMM; + prIeWmmInfo->ucLength = ELEM_MAX_LEN_WMM_INFO; + + /* WMM-2.2.1 WMM Information Element Field Values */ + prIeWmmInfo->aucOui[0] = aucWfaOui[0]; + prIeWmmInfo->aucOui[1] = aucWfaOui[1]; + prIeWmmInfo->aucOui[2] = aucWfaOui[2]; + prIeWmmInfo->ucOuiType = VENDOR_OUI_TYPE_WMM; + prIeWmmInfo->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_INFO; + + prIeWmmInfo->ucVersion = VERSION_WMM; + prIeWmmInfo->ucQosInfo = 0; + + /* UAPSD initial queue configurations (delivery and trigger enabled) */ + if (fgSupportUAPSD) { + + UINT_8 ucQosInfo = 0; + UINT_8 i; + + /* Static U-APSD setting */ + for (i = ACI_BE; i <= ACI_VO; i++) { + if (ucBmpDeliveryAC & ucBmpTriggerAC & BIT(i)) + ucQosInfo |= (UINT_8) ucUapsd[i]; + } + + if (ucBmpDeliveryAC & ucBmpTriggerAC) { + switch (ucUapsdSp) { + case WMM_MAX_SP_LENGTH_ALL: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_ALL; + break; + + case WMM_MAX_SP_LENGTH_2: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_2; + break; + + case WMM_MAX_SP_LENGTH_4: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_4; + break; + + case WMM_MAX_SP_LENGTH_6: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_6; + break; + + default: + DBGLOG(QM, WARN, "MQM: Incorrect SP length\n"); + ucQosInfo |= WMM_QOS_INFO_MAX_SP_2; + break; + } + } + prIeWmmInfo->ucQosInfo = ucQosInfo; + + } + + /* Increment the total IE length for the Element ID and Length fields. */ + return IE_SIZE(prIeWmmInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Generate the WMM Info IE +* +* \param[in] prAdapter Adapter pointer +* @param prMsduInfo The TX MMPDU +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID mqmGenerateWmmInfoIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_IE_WMM_INFO_T prIeWmmInfo; + P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo; + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("mqmGenerateWmmInfoIE"); + + ASSERT(prMsduInfo); + + /* In case QoS is not turned off, exit directly */ + if (!prAdapter->rWifiVar.fgSupportQoS) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + if (prStaRec == NULL) + return; + + if (!prStaRec->fgIsWmmSupported) + return; + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + + prIeWmmInfo = (P_IE_WMM_INFO_T) + ((PUINT_8) prMsduInfo->prPacket + prMsduInfo->u2FrameLength); + +#if 0 + prIeWmmInfo->ucId = ELEM_ID_WMM; + prIeWmmInfo->ucLength = ELEM_MAX_LEN_WMM_INFO; + + /* WMM-2.2.1 WMM Information Element Field Values */ + prIeWmmInfo->aucOui[0] = aucWfaOui[0]; + prIeWmmInfo->aucOui[1] = aucWfaOui[1]; + prIeWmmInfo->aucOui[2] = aucWfaOui[2]; + prIeWmmInfo->ucOuiType = VENDOR_OUI_TYPE_WMM; + prIeWmmInfo->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_INFO; + + prIeWmmInfo->ucVersion = VERSION_WMM; + prIeWmmInfo->ucQosInfo = 0; + + /* UAPSD initial queue configurations (delivery and trigger enabled) */ + /* if (prAdapter->rWifiVar.fgSupportUAPSD) { */ + if (prAdapter->rWifiVar.fgSupportUAPSD && prStaRec->fgIsUapsdSupported) { + + UINT_8 ucQosInfo = 0; + UINT_8 i; + + /* Static U-APSD setting */ + for (i = ACI_BE; i <= ACI_VO; i++) { + if (prPmProfSetupInfo->ucBmpDeliveryAC & prPmProfSetupInfo->ucBmpTriggerAC & BIT(i)) + ucQosInfo |= (UINT_8) ucUapsd[i]; + } + + if (prPmProfSetupInfo->ucBmpDeliveryAC & prPmProfSetupInfo->ucBmpTriggerAC) { + switch (prPmProfSetupInfo->ucUapsdSp) { + case WMM_MAX_SP_LENGTH_ALL: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_ALL; + break; + + case WMM_MAX_SP_LENGTH_2: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_2; + break; + + case WMM_MAX_SP_LENGTH_4: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_4; + break; + + case WMM_MAX_SP_LENGTH_6: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_6; + break; + + default: + DBGLOG(QM, INFO, "MQM: Incorrect SP length\n"); + ucQosInfo |= WMM_QOS_INFO_MAX_SP_2; + break; + } + } + prIeWmmInfo->ucQosInfo = ucQosInfo; + + } + + /* Increment the total IE length for the Element ID and Length fields. */ + prMsduInfo->u2FrameLength += IE_SIZE(prIeWmmInfo); +#else + + prMsduInfo->u2FrameLength += mqmGenerateWmmInfoIEByParam((prAdapter->rWifiVar.fgSupportUAPSD + && prStaRec->fgIsUapsdSupported), + prPmProfSetupInfo->ucBmpDeliveryAC, + prPmProfSetupInfo->ucBmpTriggerAC, + prPmProfSetupInfo->ucUapsdSp, (UINT_8 *) prIeWmmInfo); +#endif +} + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* @brief log2 calculation for CW +* +* @param[in] val value +* +* @return log2(val) +*/ +/*----------------------------------------------------------------------------*/ + +UINT_32 cwlog2(UINT_32 val) +{ + + UINT_32 n; + + n = 0; + + while (val >= 512) { + n += 9; + val = val >> 9; + } + while (val >= 16) { + n += 4; + val >>= 4; + } + while (val >= 2) { + n += 1; + val >>= 1; + } + return n; +} +#endif + +UINT_32 mqmGenerateWmmParamIEByParam(P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, UINT_8 *pOutBuf, ENUM_OP_MODE_T ucOpMode) +{ + P_IE_WMM_PARAM_T prIeWmmParam; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + UINT_8 aucACI[] = { + WMM_ACI_AC_BE, + WMM_ACI_AC_BK, + WMM_ACI_AC_VI, + WMM_ACI_AC_VO + }; + ENUM_WMM_ACI_T eAci; + UCHAR *pucAciAifsn, *pucEcw, *pucTxopLimit; + + ASSERT(pOutBuf); + + prIeWmmParam = (P_IE_WMM_PARAM_T) pOutBuf; + + prIeWmmParam->ucId = ELEM_ID_WMM; + prIeWmmParam->ucLength = ELEM_MAX_LEN_WMM_PARAM; + + /* WMM-2.2.1 WMM Information Element Field Values */ + prIeWmmParam->aucOui[0] = aucWfaOui[0]; + prIeWmmParam->aucOui[1] = aucWfaOui[1]; + prIeWmmParam->aucOui[2] = aucWfaOui[2]; + prIeWmmParam->ucOuiType = VENDOR_OUI_TYPE_WMM; + prIeWmmParam->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_PARAM; + + prIeWmmParam->ucVersion = VERSION_WMM; + prIeWmmParam->ucQosInfo = (prBssInfo->ucWmmParamSetCount & WMM_QOS_INFO_PARAM_SET_CNT); + + /* UAPSD initial queue configurations (delivery and trigger enabled) */ + if (prAdapter->rWifiVar.fgSupportUAPSD) { + if (ucOpMode == OP_MODE_INFRASTRUCTURE) + prIeWmmParam->ucQosInfo = 0xf; + else + prIeWmmParam->ucQosInfo |= WMM_QOS_INFO_UAPSD; + } + + /* EDCA parameter */ + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + + /* DBGLOG(QM, LOUD, */ + /* ("MQM: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", */ + /* eAci,prBssInfo->arACQueParmsForBcast[eAci].fgIsACMSet , */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn, */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmin, */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmax, */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit)); */ + +#if 0 + *(((PUINT_8) (&prIeWmmParam->ucAciAifsn_BE)) + + (eAci << 2)) = (UINT_8) (aucACI[eAci] | + (prBssInfo->arACQueParmsForBcast[eAci].fgIsACMSet ? + WMM_ACIAIFSN_ACM : 0) | + (prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn & + (WMM_ACIAIFSN_AIFSN))); +#else + /* avoid compile warnings in Klockwork tool */ + if (eAci == WMM_AC_BE_INDEX) { + pucAciAifsn = &prIeWmmParam->ucAciAifsn_BE; + pucEcw = &prIeWmmParam->ucEcw_BE; + pucTxopLimit = prIeWmmParam->aucTxopLimit_BE; + } else if (eAci == WMM_AC_BK_INDEX) { + pucAciAifsn = &prIeWmmParam->ucAciAifsn_BG; + pucEcw = &prIeWmmParam->ucEcw_BG; + pucTxopLimit = prIeWmmParam->aucTxopLimit_BG; + } else if (eAci == WMM_AC_VI_INDEX) { + pucAciAifsn = &prIeWmmParam->ucAciAifsn_VI; + pucEcw = &prIeWmmParam->ucEcw_VI; + pucTxopLimit = prIeWmmParam->aucTxopLimit_VI; + } else if (eAci == WMM_AC_VO_INDEX) { + pucAciAifsn = &prIeWmmParam->ucAciAifsn_VO; + pucEcw = &prIeWmmParam->ucEcw_VO; + pucTxopLimit = prIeWmmParam->aucTxopLimit_VO; + } + + *pucAciAifsn = (UINT_8) (aucACI[eAci] + | (prBssInfo->arACQueParmsForBcast[eAci].fgIsACMSet ? WMM_ACIAIFSN_ACM : 0) + | (prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn & (WMM_ACIAIFSN_AIFSN))); +#endif + +#if 1 +/* *( ((PUINT_8)(&prIeWmmParam->ucEcw_BE)) + (eAci <<2) ) = (UINT_8) (0 */ + *pucEcw = (UINT_8) (0 | (((prBssInfo->aucCWminLog2ForBcast[eAci])) & WMM_ECW_WMIN_MASK) + | ((((prBssInfo->aucCWmaxLog2ForBcast[eAci])) << WMM_ECW_WMAX_OFFSET) & + WMM_ECW_WMAX_MASK) + ); +#else + *(((PUINT_8) (&prIeWmmParam->ucEcw_BE)) + + (eAci << 2)) = (UINT_8) (0 | + (cwlog2((prBssInfo->arACQueParmsForBcast[eAci].u2CWmin + + 1)) & WMM_ECW_WMIN_MASK) | + ((cwlog2 + ((prBssInfo->arACQueParmsForBcast[eAci].u2CWmax + + 1)) << WMM_ECW_WMAX_OFFSET) & + WMM_ECW_WMAX_MASK) + ); +#endif + +#if 0 + WLAN_SET_FIELD_16(((PUINT_8) (prIeWmmParam->aucTxopLimit_BE)) + (eAci << 2) + , prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit); +#else + WLAN_SET_FIELD_16(pucTxopLimit, prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit); +#endif + } + + /* Increment the total IE length for the Element ID and Length fields. */ + return IE_SIZE(prIeWmmParam); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Generate the WMM Param IE +* +* \param[in] prAdapter Adapter pointer +* @param prMsduInfo The TX MMPDU +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID mqmGenerateWmmParamIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_IE_WMM_PARAM_T prIeWmmParam; + +#if 0 + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + + UINT_8 aucACI[] = { + WMM_ACI_AC_BE, + WMM_ACI_AC_BK, + WMM_ACI_AC_VI, + WMM_ACI_AC_VO + }; + ENUM_WMM_ACI_T eAci; +#endif + + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("mqmGenerateWmmParamIE"); + DBGLOG(QM, LOUD, "\n"); + + ASSERT(prMsduInfo); + + /* In case QoS is not turned off, exit directly */ + if (!prAdapter->rWifiVar.fgSupportQoS) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (prStaRec) { + if (!prStaRec->fgIsQoS) + return; + } + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]); + + if (!prBssInfo->fgIsQBSS) + return; +/* 20120220 frog: update beacon content & change OP mode is a separate event for P2P network. */ +#if 0 + if (prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT && prBssInfo->eCurrentOPMode != OP_MODE_BOW) + return; +#endif + + prIeWmmParam = (P_IE_WMM_PARAM_T) + ((PUINT_8) prMsduInfo->prPacket + prMsduInfo->u2FrameLength); + +#if 0 + prIeWmmParam->ucId = ELEM_ID_WMM; + prIeWmmParam->ucLength = ELEM_MAX_LEN_WMM_PARAM; + + /* WMM-2.2.1 WMM Information Element Field Values */ + prIeWmmParam->aucOui[0] = aucWfaOui[0]; + prIeWmmParam->aucOui[1] = aucWfaOui[1]; + prIeWmmParam->aucOui[2] = aucWfaOui[2]; + prIeWmmParam->ucOuiType = VENDOR_OUI_TYPE_WMM; + prIeWmmParam->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_PARAM; + + prIeWmmParam->ucVersion = VERSION_WMM; + prIeWmmParam->ucQosInfo = (prBssInfo->ucWmmParamSetCount & WMM_QOS_INFO_PARAM_SET_CNT); + + /* UAPSD initial queue configurations (delivery and trigger enabled) */ + if (prAdapter->rWifiVar.fgSupportUAPSD) + prIeWmmParam->ucQosInfo |= WMM_QOS_INFO_UAPSD; + + /* EDCA parameter */ + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + + /* DBGLOG(QM, LOUD, */ + /* ("MQM: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", */ + /* eAci,prBssInfo->arACQueParmsForBcast[eAci].fgIsACMSet , */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn, */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmin, */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmax, */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit)); */ + + *(((PUINT_8) (&prIeWmmParam->ucAciAifsn_BE)) + + (eAci << 2)) = (UINT_8) (aucACI[eAci] | + (prBssInfo->arACQueParmsForBcast[eAci].fgIsACMSet ? + WMM_ACIAIFSN_ACM : 0) | + (prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn & + (WMM_ACIAIFSN_AIFSN))); +#if 1 + *(((PUINT_8) (&prIeWmmParam->ucEcw_BE)) + + (eAci << 2)) = (UINT_8) (0 | + (((prBssInfo->aucCWminLog2ForBcast[eAci])) & WMM_ECW_WMIN_MASK) | + ((((prBssInfo->aucCWmaxLog2ForBcast[eAci])) << WMM_ECW_WMAX_OFFSET) & + WMM_ECW_WMAX_MASK)); +#else + *(((PUINT_8) (&prIeWmmParam->ucEcw_BE)) + + (eAci << 2)) = (UINT_8) (0 | + (cwlog2((prBssInfo->arACQueParmsForBcast[eAci].u2CWmin + + 1)) & WMM_ECW_WMIN_MASK) | + ((cwlog2((prBssInfo->arACQueParmsForBcast[eAci].u2CWmax + 1)) + << WMM_ECW_WMAX_OFFSET) & WMM_ECW_WMAX_MASK)); +#endif + + WLAN_SET_FIELD_16(((PUINT_8) (prIeWmmParam->aucTxopLimit_BE)) + (eAci << 2) + , prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit); + + } + + /* Increment the total IE length for the Element ID and Length fields. */ + prMsduInfo->u2FrameLength += IE_SIZE(prIeWmmParam); +#else + + prMsduInfo->u2FrameLength += mqmGenerateWmmParamIEByParam(prAdapter, + prBssInfo, (UINT_8 *) prIeWmmParam, OP_MODE_ACCESS_POINT); +#endif +} + +ENUM_FRAME_ACTION_T +qmGetFrameAction(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType, + IN UINT_8 ucStaRecIdx, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_FRAME_TYPE_IN_CMD_Q_T eFrameType) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + P_WLAN_MAC_HEADER_T prWlanFrame; + UINT_16 u2TxFrameCtrl; + + DEBUGFUNC("qmGetFrameAction"); + +#if (NIC_TX_BUFF_COUNT_TC4 > 2) +#define QM_MGMT_QUUEUD_THRESHOLD 2 +#else +#define QM_MGMT_QUUEUD_THRESHOLD 1 +#endif + + DATA_STRUCT_INSPECTING_ASSERT(QM_MGMT_QUUEUD_THRESHOLD <= (NIC_TX_BUFF_COUNT_TC4)); + DATA_STRUCT_INSPECTING_ASSERT(QM_MGMT_QUUEUD_THRESHOLD > 0); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkType]); + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, ucStaRecIdx); + + /* XXX Check BOW P2P AIS time ot set active */ + if (!IS_BSS_ACTIVE(prBssInfo)) { + if (eFrameType == FRAME_TYPE_MMPDU) { + prWlanFrame = (P_WLAN_MAC_HEADER_T) prMsduInfo->prPacket; + u2TxFrameCtrl = (prWlanFrame->u2FrameCtrl) & MASK_FRAME_TYPE; /* Optimized for ARM */ + if (((u2TxFrameCtrl == MAC_FRAME_DEAUTH) + && (prMsduInfo->pfTxDoneHandler == NULL)) + || (u2TxFrameCtrl == MAC_FRAME_ACTION)) /* whsu */ + return FRAME_ACTION_TX_PKT; + } + + DBGLOG(QM, WARN, "Drop packets Action, eFrameType: %d (Bss Index %u).\n", + eFrameType, prBssInfo->ucNetTypeIndex); + TX_INC_CNT(&prAdapter->rTxCtrl, TX_INACTIVE_BSS_DROP); + return FRAME_ACTION_DROP_PKT; + } + + /* TODO Handle disconnect issue */ + + /* P2P probe Request frame */ + do { + if (eFrameType == FRAME_TYPE_MMPDU) { + prWlanFrame = (P_WLAN_MAC_HEADER_T) prMsduInfo->prPacket; + u2TxFrameCtrl = (prWlanFrame->u2FrameCtrl) & MASK_FRAME_TYPE; /* Optimized for ARM */ + + if (u2TxFrameCtrl == MAC_FRAME_BEACON) { + if (prBssInfo->fgIsNetAbsent) + return FRAME_ACTION_DROP_PKT; + } else if (u2TxFrameCtrl == MAC_FRAME_PROBE_RSP) { + if (prBssInfo->fgIsNetAbsent) + return FRAME_ACTION_DROP_PKT; + } else if (u2TxFrameCtrl == MAC_FRAME_DEAUTH) { + if (prBssInfo->fgIsNetAbsent) + break; + DBGLOG(P2P, LOUD, "Sending DEAUTH Frame\n"); + return FRAME_ACTION_TX_PKT; + } + /* MMPDU with prStaRec && fgIsInUse not check fgIsNetActive */ + else if (u2TxFrameCtrl == MAC_FRAME_ASSOC_REQ + || u2TxFrameCtrl == MAC_FRAME_AUTH + || u2TxFrameCtrl == MAC_FRAME_REASSOC_REQ + || u2TxFrameCtrl == MAC_FRAME_PROBE_REQ || u2TxFrameCtrl == MAC_FRAME_ACTION) { + + if ((prStaRec) && (prStaRec->fgIsInPS)) { + if (nicTxGetResource(prAdapter, TC4_INDEX) >= QM_MGMT_QUUEUD_THRESHOLD) + return FRAME_ACTION_TX_PKT; + else + return FRAME_ACTION_QUEUE_PKT; + } + return FRAME_ACTION_TX_PKT; + } + + if (!prStaRec) + return FRAME_ACTION_TX_PKT; + + if (!prStaRec->fgIsInUse) + return FRAME_ACTION_DROP_PKT; + + /* FRAME_TYPE_MMPDU */ + } else if (eFrameType == FRAME_TYPE_802_1X) { + + if (!prStaRec) + return FRAME_ACTION_TX_PKT; + + if (!prStaRec->fgIsInUse) + return FRAME_ACTION_DROP_PKT; + if (prStaRec->fgIsInPS) { + if (nicTxGetResource(prAdapter, TC4_INDEX) >= QM_MGMT_QUUEUD_THRESHOLD) + return FRAME_ACTION_TX_PKT; + else + return FRAME_ACTION_QUEUE_PKT; + } + + /* FRAME_TYPE_802_1X */ + } else if ((!IS_BSS_ACTIVE(prBssInfo)) + || (!prStaRec) + || (!prStaRec->fgIsInUse)) { + return FRAME_ACTION_DROP_PKT; + } + } while (0); + + if (prBssInfo->fgIsNetAbsent) { + DBGLOG(QM, LOUD, "Queue packets (Absent %u).\n", prBssInfo->ucNetTypeIndex); + return FRAME_ACTION_QUEUE_PKT; + } + + if (prStaRec && prStaRec->fgIsInPS) { + DBGLOG(QM, LOUD, "Queue packets (PS %u).\n", prStaRec->fgIsInPS); + return FRAME_ACTION_QUEUE_PKT; + } + switch (eFrameType) { + case FRAME_TYPE_802_1X: + if (!prStaRec->fgIsValid) + return FRAME_ACTION_QUEUE_PKT; + break; + + case FRAME_TYPE_MMPDU: + break; + + default: + ASSERT(0); + } + + return FRAME_ACTION_TX_PKT; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Handle BSS change operation Event from the FW +* +* \param[in] prAdapter Adapter pointer +* \param[in] prEvent The event packet from the FW +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmHandleEventBssAbsencePresence(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_EVENT_BSS_ABSENCE_PRESENCE_T prEventBssStatus; + P_BSS_INFO_T prBssInfo; + BOOLEAN fgIsNetAbsentOld; + + prEventBssStatus = (P_EVENT_BSS_ABSENCE_PRESENCE_T) prEvent; + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prEventBssStatus->ucNetTypeIdx]); + fgIsNetAbsentOld = prBssInfo->fgIsNetAbsent; + prBssInfo->fgIsNetAbsent = prEventBssStatus->fgIsAbsent; + prBssInfo->ucBssFreeQuota = prEventBssStatus->ucBssFreeQuota; + + /* DBGLOG(QM, TRACE, ("qmHandleEventBssAbsencePresence (ucNetTypeIdx=%d, fgIsAbsent=%d, FreeQuota=%d)\n", */ + /* prEventBssStatus->ucNetTypeIdx, prBssInfo->fgIsNetAbsent, prBssInfo->ucBssFreeQuota)); */ + + DBGLOGLIMITED(QM, INFO, "NAF=%d,%d,%d\n", + prEventBssStatus->ucNetTypeIdx, prBssInfo->fgIsNetAbsent, prBssInfo->ucBssFreeQuota); + + if (!prBssInfo->fgIsNetAbsent) { + /* QM_DBG_CNT_27 */ + QM_DBG_CNT_INC(&(prAdapter->rQM), QM_DBG_CNT_27); + } else { + /* QM_DBG_CNT_28 */ + QM_DBG_CNT_INC(&(prAdapter->rQM), QM_DBG_CNT_28); + } + /* From Absent to Present */ + if ((fgIsNetAbsentOld) && (!prBssInfo->fgIsNetAbsent)) + kalSetEvent(prAdapter->prGlueInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Handle STA change PS mode Event from the FW +* +* \param[in] prAdapter Adapter pointer +* \param[in] prEvent The event packet from the FW +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmHandleEventStaChangePsMode(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_EVENT_STA_CHANGE_PS_MODE_T prEventStaChangePsMode; + P_STA_RECORD_T prStaRec; + BOOLEAN fgIsInPSOld; + + /* DbgPrint("QM:Event -RxBa\n"); */ + + prEventStaChangePsMode = (P_EVENT_STA_CHANGE_PS_MODE_T) prEvent; + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventStaChangePsMode->ucStaRecIdx); + ASSERT(prStaRec); + + if (prStaRec) { + + fgIsInPSOld = prStaRec->fgIsInPS; + prStaRec->fgIsInPS = prEventStaChangePsMode->fgIsInPs; + + qmUpdateFreeQuota(prAdapter, + prStaRec, + prEventStaChangePsMode->ucUpdateMode, prEventStaChangePsMode->ucFreeQuota, 0); + + /* DBGLOG(QM, TRACE, ("qmHandleEventStaChangePsMode (ucStaRecIdx=%d, fgIsInPs=%d)\n", */ + /* prEventStaChangePsMode->ucStaRecIdx, prStaRec->fgIsInPS)); */ + + DBGLOG(QM, TRACE, "PS=%d,%d\n", prEventStaChangePsMode->ucStaRecIdx, prStaRec->fgIsInPS); + + /* From PS to Awake */ + if ((fgIsInPSOld) && (!prStaRec->fgIsInPS)) + kalSetEvent(prAdapter->prGlueInfo); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Update STA free quota Event from FW +* +* \param[in] prAdapter Adapter pointer +* \param[in] prEvent The event packet from the FW +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmHandleEventStaUpdateFreeQuota(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_EVENT_STA_UPDATE_FREE_QUOTA_T prEventStaUpdateFreeQuota; + P_STA_RECORD_T prStaRec; + + prEventStaUpdateFreeQuota = (P_EVENT_STA_UPDATE_FREE_QUOTA_T) prEvent; + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventStaUpdateFreeQuota->ucStaRecIdx); + ASSERT(prStaRec); + + if (prStaRec) { + if (prStaRec->fgIsInPS) { + qmUpdateFreeQuota(prAdapter, + prStaRec, + prEventStaUpdateFreeQuota->ucUpdateMode, + prEventStaUpdateFreeQuota->ucFreeQuota, + prEventStaUpdateFreeQuota->aucReserved[0]); + + kalSetEvent(prAdapter->prGlueInfo); + } +#if 0 + DBGLOG(QM, TRACE, + "qmHandleEventStaUpdateFreeQuota (ucStaRecIdx=%d, ucUpdateMode=%d, ucFreeQuota=%d)\n", + prEventStaUpdateFreeQuota->ucStaRecIdx, prEventStaUpdateFreeQuota->ucUpdateMode, + prEventStaUpdateFreeQuota->ucFreeQuota); +#endif + + DBGLOG(QM, TRACE, "UFQ=%d,%d,%d\n", + prEventStaUpdateFreeQuota->ucStaRecIdx, + prEventStaUpdateFreeQuota->ucUpdateMode, prEventStaUpdateFreeQuota->ucFreeQuota); + + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Update STA free quota +* +* \param[in] prStaRec the STA +* \param[in] ucUpdateMode the method to update free quota +* \param[in] ucFreeQuota the value for update +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +qmUpdateFreeQuota(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, IN UINT_8 ucUpdateMode, IN UINT_8 ucFreeQuota, IN UINT_8 ucNumOfTxDone) +{ + + UINT_8 ucFreeQuotaForNonDelivery; + UINT_8 ucFreeQuotaForDelivery; + BOOLEAN flgIsUpdateForcedToDelivery; + + ASSERT(prStaRec); + DBGLOG(QM, LOUD, "qmUpdateFreeQuota orig ucFreeQuota=%d Mode %u New %u\n", + prStaRec->ucFreeQuota, ucUpdateMode, ucFreeQuota); + + if (!prStaRec->fgIsInPS) + return; + + flgIsUpdateForcedToDelivery = FALSE; + + if (ucNumOfTxDone > 0) { + /* + * update free quota by + * num of tx done + resident free quota (delivery + non-delivery) + */ + UINT_8 ucAvailQuota; + + ucAvailQuota = ucNumOfTxDone + prStaRec->ucFreeQuotaForDelivery + prStaRec->ucFreeQuotaForNonDelivery; + if (ucAvailQuota > ucFreeQuota) /* sanity check */ + ucAvailQuota = ucFreeQuota; + + /* update current free quota */ + ucFreeQuota = ucAvailQuota; + + /* check if the update is from last packet */ + if (ucFreeQuota == (prStaRec->ucFreeQuota + 1)) { + /* just add the extra quota to delivery queue */ + + /* + * EX: + * 1. TDLS peer enters power save + * 2. When the last 2 VI packets are tx done, we will receive 2 update events + * 3. 1st update event: ucFreeQuota = 9 + * 4. We will correct new quota for delivey and non-delivery to 7:2 + * 5. 2rd update event: ucFreeQuota = 10 + * 6. We will re-correct new quota for delivery and non-delivery to 5:5 + * + * But non-delivery queue is not busy. + * So in the case, we will have wrong decision, i.e. higher queue always quota 5 + * + * Solution: skip the 2rd update event and just add the extra quota to delivery. + */ + + flgIsUpdateForcedToDelivery = TRUE; + } + } + + switch (ucUpdateMode) { + case FREE_QUOTA_UPDATE_MODE_INIT: + case FREE_QUOTA_UPDATE_MODE_OVERWRITE: + prStaRec->ucFreeQuota = ucFreeQuota; + break; + case FREE_QUOTA_UPDATE_MODE_INCREASE: + prStaRec->ucFreeQuota += ucFreeQuota; + break; + case FREE_QUOTA_UPDATE_MODE_DECREASE: + prStaRec->ucFreeQuota -= ucFreeQuota; + break; + default: + ASSERT(0); + } + + DBGLOG(QM, LOUD, "qmUpdateFreeQuota new ucFreeQuota=%d)\n", prStaRec->ucFreeQuota); + + ucFreeQuota = prStaRec->ucFreeQuota; + + ucFreeQuotaForNonDelivery = 0; + ucFreeQuotaForDelivery = 0; + + if (ucFreeQuota > 0) { + if (prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported + /* + * && prAdapter->rWifiVar.fgSupportQoS + * && prAdapter->rWifiVar.fgSupportUAPSD + */) { + /* XXX We should assign quota to aucFreeQuotaPerQueue[NUM_OF_PER_STA_TX_QUEUES] */ + + if (flgIsUpdateForcedToDelivery == FALSE) { + if (prStaRec->ucFreeQuotaForNonDelivery > 0 && prStaRec->ucFreeQuotaForDelivery > 0) { + ucFreeQuotaForNonDelivery = ucFreeQuota >> 1; + ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery; + } else if (prStaRec->ucFreeQuotaForNonDelivery == 0 + && prStaRec->ucFreeQuotaForDelivery == 0) { + ucFreeQuotaForNonDelivery = ucFreeQuota >> 1; + ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery; + } else if (prStaRec->ucFreeQuotaForNonDelivery > 0) { + /* NonDelivery is not busy */ + if (ucFreeQuota >= 3) { + ucFreeQuotaForNonDelivery = 2; + ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery; + } else { + ucFreeQuotaForDelivery = ucFreeQuota; + ucFreeQuotaForNonDelivery = 0; + } + } else if (prStaRec->ucFreeQuotaForDelivery > 0) { + /* Delivery is not busy */ + if (ucFreeQuota >= 3) { + ucFreeQuotaForDelivery = 2; + ucFreeQuotaForNonDelivery = ucFreeQuota - ucFreeQuotaForDelivery; + } else { + ucFreeQuotaForNonDelivery = ucFreeQuota; + ucFreeQuotaForDelivery = 0; + } + } + } else { + ucFreeQuotaForNonDelivery = 2; + ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery; + } + } else { + /* no use ? */ + /* !prStaRec->fgIsUapsdSupported */ + ucFreeQuotaForNonDelivery = ucFreeQuota; + ucFreeQuotaForDelivery = 0; + } + } + /* ucFreeQuota > 0 */ + prStaRec->ucFreeQuotaForDelivery = ucFreeQuotaForDelivery; + prStaRec->ucFreeQuotaForNonDelivery = ucFreeQuotaForNonDelivery; + +#if (CFG_SUPPORT_TDLS_DBG == 1) + if (IS_TDLS_STA(prStaRec)) + DBGLOG(QM, LOUD, " quota %d %d %d\n", + ucFreeQuota, ucFreeQuotaForDelivery, ucFreeQuotaForNonDelivery); +#endif + + DBGLOG(QM, LOUD, "new QuotaForDelivery = %d QuotaForNonDelivery = %d\n", + prStaRec->ucFreeQuotaForDelivery, prStaRec->ucFreeQuotaForNonDelivery); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Return the reorder queued RX packets +* +* \param[in] (none) +* +* \return The number of queued RX packets +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 qmGetRxReorderQueuedBufferCount(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i, u4Total; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + u4Total = 0; + /* XXX The summation may impact the performance */ + for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) { + u4Total += prQM->arRxBaTable[i].rReOrderQue.u4NumElem; +#if DBG && 0 + if (QUEUE_IS_EMPTY(&(prQM->arRxBaTable[i].rReOrderQue))) + ASSERT(prQM->arRxBaTable[i].rReOrderQue == 0); +#endif + } + ASSERT(u4Total <= (CFG_NUM_OF_QM_RX_PKT_NUM * 2)); + return u4Total; +} + +#if ARP_MONITER_ENABLE +VOID qmDetectArpNoResponse(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + struct sk_buff *prSkb = NULL; + PUINT_8 pucData = NULL; + UINT_16 u2EtherType = 0; + int arpOpCode = 0; + + prSkb = (struct sk_buff *)prMsduInfo->prPacket; + + if (!prSkb || (prSkb->len <= ETHER_HEADER_LEN)) + return; + + pucData = prSkb->data; + if (!pucData) + return; + u2EtherType = (pucData[ETH_TYPE_LEN_OFFSET] << 8) | (pucData[ETH_TYPE_LEN_OFFSET + 1]); + + if (u2EtherType != ETH_P_ARP) + return; + + if (kalMemCmp(apIp, &pucData[ETH_TYPE_LEN_OFFSET + 26], sizeof(apIp)) && + kalMemCmp(gatewayIp, &pucData[ETH_TYPE_LEN_OFFSET + 26], sizeof(gatewayIp))) /* dest ip address */ + return; + + arpOpCode = (pucData[ETH_TYPE_LEN_OFFSET + 8] << 8) | (pucData[ETH_TYPE_LEN_OFFSET + 8 + 1]); + if (arpOpCode == ARP_PRO_REQ) { + arpMoniter++; + if (arpMoniter > 20) { + DBGLOG(INIT, WARN, "IOT Critical issue, arp no resp, check AP!\n"); + aisBssBeaconTimeout(prAdapter); + arpMoniter = 0; + kalMemZero(apIp, sizeof(apIp)); + } + } +} + +VOID qmHandleRxArpPackets(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) +{ + PUINT_8 pucData = NULL; + UINT_16 u2EtherType = 0; + int arpOpCode = 0; + P_BSS_INFO_T prBssInfo = NULL; + + if (prSwRfb->u2PacketLen <= ETHER_HEADER_LEN) + return; + + pucData = (PUINT_8)prSwRfb->pvHeader; + if (!pucData) + return; + u2EtherType = (pucData[ETH_TYPE_LEN_OFFSET] << 8) | (pucData[ETH_TYPE_LEN_OFFSET + 1]); + + if (u2EtherType != ETH_P_ARP) + return; + + arpOpCode = (pucData[ETH_TYPE_LEN_OFFSET + 8] << 8) | (pucData[ETH_TYPE_LEN_OFFSET + 8 + 1]); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + if (arpOpCode == ARP_PRO_RSP) { + arpMoniter = 0; + if (prBssInfo && prBssInfo->prStaRecOfAP) { + if (EQUAL_MAC_ADDR(&(pucData[ETH_TYPE_LEN_OFFSET + 10]), /* source hardware address */ + prBssInfo->prStaRecOfAP->aucMacAddr)) { + kalMemCopy(apIp, &(pucData[ETH_TYPE_LEN_OFFSET + 16]), sizeof(apIp)); + DBGLOG(INIT, TRACE, "get arp response from AP %d.%d.%d.%d\n", + apIp[0], apIp[1], apIp[2], apIp[3]); + } + } + } +} + +VOID qmHandleRxDhcpPackets(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) +{ + PUINT_8 pucData = NULL; + PUINT_8 pucEthBody = NULL; + PUINT_8 pucUdpBody = NULL; + UINT_32 udpLength = 0; + UINT_32 i = 0; + P_BOOTP_PROTOCOL_T prBootp = NULL; + UINT_32 u4DhcpMagicCode = 0; + UINT_8 dhcpTypeGot = 0; + UINT_8 dhcpGatewayGot = 0; + + if (prSwRfb->u2PacketLen <= ETHER_HEADER_LEN) + return; + + pucData = (PUINT_8)prSwRfb->pvHeader; + if (!pucData) + return; + if (((pucData[ETH_TYPE_LEN_OFFSET] << 8) | pucData[ETH_TYPE_LEN_OFFSET + 1]) != ETH_P_IPV4) + return; + + pucEthBody = &pucData[ETH_HLEN]; + if (((pucEthBody[0] & IPVH_VERSION_MASK) >> IPVH_VERSION_OFFSET) != IPVERSION) + return; + if (pucEthBody[9] != IP_PRO_UDP) + return; + + pucUdpBody = &pucEthBody[(pucEthBody[0] & 0x0F) * 4]; + if ((pucUdpBody[0] << 8 | pucUdpBody[1]) != UDP_PORT_DHCPS || + (pucUdpBody[2] << 8 | pucUdpBody[3]) != UDP_PORT_DHCPC) + return; + + udpLength = pucUdpBody[4] << 8 | pucUdpBody[5]; + + prBootp = (P_BOOTP_PROTOCOL_T) &pucUdpBody[8]; + + WLAN_GET_FIELD_BE32(&prBootp->aucOptions[0], &u4DhcpMagicCode); + if (u4DhcpMagicCode != DHCP_MAGIC_NUMBER) { + DBGLOG(INIT, WARN, "dhcp wrong magic number, magic code: %d\n", u4DhcpMagicCode); + return; + } + + /* 1. 248 is from udp header to the beginning of dhcp option + * 2. not sure the dhcp option always usd 255 as a end mark? if so, while condition should be removed? + */ + while (i < udpLength - 248) { + /* bcz of the strange P_BOOTP_PROTOCOL_T, the dhcp magic code was count in dhcp options + * so need to [i + 4] to skip it + */ + switch (prBootp->aucOptions[i + 4]) { + case 3: + /* both dhcp ack and offer will update it */ + if (prBootp->aucOptions[i + 6] || + prBootp->aucOptions[i + 7] || + prBootp->aucOptions[i + 8] || + prBootp->aucOptions[i + 9]) { + gatewayIp[0] = prBootp->aucOptions[i + 6]; + gatewayIp[1] = prBootp->aucOptions[i + 7]; + gatewayIp[2] = prBootp->aucOptions[i + 8]; + gatewayIp[3] = prBootp->aucOptions[i + 9]; + + DBGLOG(INIT, TRACE, "Gateway ip: %d.%d.%d.%d\n", + gatewayIp[0], + gatewayIp[1], + gatewayIp[2], + gatewayIp[3]); + }; + dhcpGatewayGot = 1; + break; + case 53: + if (prBootp->aucOptions[i + 6] != 0x02 && prBootp->aucOptions[i + 6] != 0x05) { + DBGLOG(INIT, WARN, "wrong dhcp message type, type: %d\n", prBootp->aucOptions[i + 6]); + if (dhcpGatewayGot) + kalMemZero(gatewayIp, sizeof(gatewayIp)); + return; + } + dhcpTypeGot = 1; + break; + case 255: + return; + + default: + break; + } + if (dhcpGatewayGot && dhcpTypeGot) + return; + + i += prBootp->aucOptions[i + 5] + 2; + } + DBGLOG(INIT, WARN, "can't find the dhcp option 255?, need to check the net log\n"); +} + +VOID qmResetArpDetect(VOID) +{ + arpMoniter = 0; + kalMemZero(apIp, sizeof(apIp)); + kalMemZero(gatewayIp, sizeof(gatewayIp)); +} +#endif + + +VOID qmHandleReorderBubbleTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr) +{ + P_RX_BA_ENTRY_T prReorderQueParm = (P_RX_BA_ENTRY_T) ulParamPtr; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; + P_EVENT_CHECK_REORDER_BUBBLE_T prCheckReorderEvent; + + if (!prReorderQueParm->fgIsValid) { + DBGLOG(QM, TRACE, "QM:Bub Check Cancel STA[%u] TID[%u], No Rx BA entry\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + return; + } + + if (!prReorderQueParm->fgHasBubble) { + DBGLOG(QM, TRACE, + "QM:Bub Check Cancel STA[%u] TID[%u], Bubble has been filled\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + return; + } + + DBGLOG(QM, TRACE, "QM:Bub Timeout STA[%u] TID[%u] BubSN[%u]\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid, prReorderQueParm->u2FirstBubbleSn); + + /* Generate a self-inited event to Rx path */ + QUEUE_REMOVE_HEAD(&prAdapter->rRxCtrl.rFreeSwRfbList, prSwRfb, P_SW_RFB_T); + + if (prSwRfb) { + prCheckReorderEvent = (P_EVENT_CHECK_REORDER_BUBBLE_T) prSwRfb->pucRecvBuff; + + prSwRfb->ucPacketType = HIF_RX_PKT_TYPE_EVENT; + + prCheckReorderEvent->ucEID = EVENT_ID_CHECK_REORDER_BUBBLE; + prCheckReorderEvent->ucSeqNum = 0; + + prCheckReorderEvent->ucStaRecIdx = prReorderQueParm->ucStaRecIdx; + prCheckReorderEvent->ucTid = prReorderQueParm->ucTid; + prCheckReorderEvent->u2Length = sizeof(EVENT_CHECK_REORDER_BUBBLE_T); + + QUEUE_INSERT_TAIL(&prAdapter->rRxCtrl.rReceivedRfbList, &prSwRfb->rQueEntry); + RX_INC_CNT(&prAdapter->rRxCtrl, RX_MPDU_TOTAL_COUNT); + + DBGLOG(QM, LOUD, "QM:Bub Check Event Sent STA[%u] TID[%u]\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + + nicRxProcessRFBs(prAdapter); + + DBGLOG(QM, LOUD, "QM:Bub Check Event Handled STA[%u] TID[%u]\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + } else { + DBGLOG(QM, TRACE, + "QM:Bub Check Cancel STA[%u] TID[%u], Bub check event alloc failed\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + + cnmTimerStartTimer(prAdapter, &(prReorderQueParm->rReorderBubbleTimer), prAdapter->u4QmRxBaMissTimeout); + + DBGLOG(QM, TRACE, "QM:Bub Timer Restart STA[%u] TID[%u] BubSN[%u] Win{%d, %d}\n", + prReorderQueParm->ucStaRecIdx, + prReorderQueParm->ucTid, + prReorderQueParm->u2FirstBubbleSn, + prReorderQueParm->u2WinStart, prReorderQueParm->u2WinEnd); + } +} + +VOID qmHandleEventCheckReorderBubble(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_EVENT_CHECK_REORDER_BUBBLE_T prCheckReorderEvent = (P_EVENT_CHECK_REORDER_BUBBLE_T) prEvent; + P_RX_BA_ENTRY_T prReorderQueParm; + P_QUE_T prReorderQue; + QUE_T rReturnedQue; + P_QUE_T prReturnedQue = &rReturnedQue; + P_SW_RFB_T prReorderedSwRfb, prSwRfb; + + QUEUE_INITIALIZE(prReturnedQue); + + /* Get target Rx BA entry */ + prReorderQueParm = qmLookupRxBaEntry(prAdapter, prCheckReorderEvent->ucStaRecIdx, prCheckReorderEvent->ucTid); + + /* Sanity Check */ + if (!prReorderQueParm || !prReorderQueParm->fgIsValid || !prReorderQueParm->fgHasBubble) { + if (!prReorderQueParm) { + DBGLOG(QM, WARN, "QM:Bub Check Cancel STA[%u] TID[%u]. QueParm is NULL.", + prCheckReorderEvent->ucStaRecIdx, prCheckReorderEvent->ucTid); + } else { + DBGLOG(QM, WARN, "QM:Bub Check Cancel STA[%u] TID[%u]. QueParm %p valid %d has bubble %d\n", + prCheckReorderEvent->ucStaRecIdx, + prCheckReorderEvent->ucTid, prReorderQueParm, + prReorderQueParm->fgIsValid, prReorderQueParm->fgHasBubble); + } + return; + } + + prReorderQue = &(prReorderQueParm->rReOrderQue); + + if (QUEUE_IS_EMPTY(prReorderQue)) { + prReorderQueParm->fgHasBubble = FALSE; + + DBGLOG(QM, WARN, + "QM:Bub Check Cancel STA[%u] TID[%u], Bubble has been filled\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + + return; + } + + DBGLOG(QM, TRACE, "QM:Bub Check Event Got STA[%u] TID[%u]\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + + /* Expected bubble timeout => pop out packets before win_end */ + if (prReorderQueParm->u2FirstBubbleSn == prReorderQueParm->u2WinStart) { + + prReorderedSwRfb = (P_SW_RFB_T) QUEUE_GET_TAIL(prReorderQue); + + prReorderQueParm->u2WinStart = prReorderedSwRfb->u2SSN + 1; + prReorderQueParm->u2WinEnd = + ((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT; + + qmPopOutDueToFallAhead(prAdapter, prReorderQueParm, prReturnedQue); + + DBGLOG(QM, TRACE, "QM:Bub Flush) STA[%u] TID[%u] BubSN[%u] Win{%d, %d}\n", + prReorderQueParm->ucStaRecIdx, + prReorderQueParm->ucTid, + prReorderQueParm->u2FirstBubbleSn, + prReorderQueParm->u2WinStart, prReorderQueParm->u2WinEnd); + + if (QUEUE_IS_NOT_EMPTY(prReturnedQue)) { + QM_TX_SET_NEXT_MSDU_INFO((P_SW_RFB_T) QUEUE_GET_TAIL(prReturnedQue), NULL); + + prSwRfb = (P_SW_RFB_T) QUEUE_GET_HEAD(prReturnedQue); + while (prSwRfb) { + DBGLOG(QM, TRACE, + "QM:Bub Flush STA[%u] TID[%u] Pop Out SN[%u]\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid, prSwRfb->u2SSN); + + prSwRfb = (P_SW_RFB_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prSwRfb); + } + + wlanProcessQueuedSwRfb(prAdapter, (P_SW_RFB_T) QUEUE_GET_HEAD(prReturnedQue)); + } else { + DBGLOG(QM, TRACE, "QM:Bub Flush STA[%u] TID[%u] Pop Out 0 packet\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + } + + prReorderQueParm->fgHasBubble = FALSE; + } + /* First bubble has been filled but others exist */ + else { + prReorderQueParm->u2FirstBubbleSn = prReorderQueParm->u2WinStart; + cnmTimerStartTimer(prAdapter, &(prReorderQueParm->rReorderBubbleTimer), prAdapter->u4QmRxBaMissTimeout); + + DBGLOG(QM, TRACE, "QM:Bub Timer STA[%u] TID[%u] BubSN[%u] Win{%d, %d}\n", + prReorderQueParm->ucStaRecIdx, + prReorderQueParm->ucTid, + prReorderQueParm->u2FirstBubbleSn, + prReorderQueParm->u2WinStart, prReorderQueParm->u2WinEnd); + } + + qmHandleMissTimeout(prReorderQueParm); + +} + +VOID qmHandleMissTimeout(IN P_RX_BA_ENTRY_T prReorderQueParm) +{ + P_QUE_T prReorderQue; + OS_SYSTIME *prMissTimeout; + + prReorderQue = &(prReorderQueParm->rReOrderQue); + + prMissTimeout = &g_arMissTimeout[prReorderQueParm->ucStaRecIdx][prReorderQueParm->ucTid]; + if (QUEUE_IS_EMPTY(prReorderQue)) { + DBGLOG(QM, TRACE, "QM:(Bub Check) Reset prMissTimeout to zero\n"); + *prMissTimeout = 0; + } else { + DBGLOG(QM, TRACE, "QM:(Bub Check) Reset prMissTimeout to current time\n"); + GET_CURRENT_SYSTIME(prMissTimeout); + } +} + +VOID qmMoveStaTxQueue(P_STA_RECORD_T prSrcStaRec, P_STA_RECORD_T prDstStaRec) +{ + UINT_8 ucQueArrayIdx; + P_QUE_T prSrcQue = NULL; + P_QUE_T prDstQue = NULL; + P_MSDU_INFO_T prMsduInfo = NULL; + UINT_8 ucDstStaIndex = 0; + + ASSERT(prSrcStaRec); + ASSERT(prDstStaRec); + + prSrcQue = &prSrcStaRec->arTxQueue[0]; + prDstQue = &prDstStaRec->arTxQueue[0]; + ucDstStaIndex = prDstStaRec->ucIndex; + + DBGLOG(QM, INFO, "Pending MSDUs for TC 0~3, %u %u %u %u\n", prSrcQue[TC0_INDEX].u4NumElem, + prSrcQue[TC1_INDEX].u4NumElem, prSrcQue[TC2_INDEX].u4NumElem, prSrcQue[TC3_INDEX].u4NumElem); + /* Concatenate all MSDU_INFOs in TX queues of this STA_REC */ + for (ucQueArrayIdx = 0; ucQueArrayIdx < TC4_INDEX; ucQueArrayIdx++) { + prMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_HEAD(&prSrcQue[ucQueArrayIdx]); + while (prMsduInfo) { + prMsduInfo->ucStaRecIndex = ucDstStaIndex; + prMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY(&prMsduInfo->rQueEntry); + } + QUEUE_CONCATENATE_QUEUES((&prDstQue[ucQueArrayIdx]), (&prSrcQue[ucQueArrayIdx])); + } +} + +VOID qmHandleDelTspec(P_ADAPTER_T prAdapter, ENUM_NETWORK_TYPE_INDEX_T eNetType, + P_STA_RECORD_T prStaRec, ENUM_ACI_T eAci) +{ + UINT_8 aucNextUP[ACI_NUM] = {1/* BEtoBK */, 1/*na */, 0/*VItoBE */, 4/*VOtoVI */}; + ENUM_ACI_T aeNextAci[ACI_NUM] = {ACI_BK, ACI_BK, ACI_BE, ACI_VI}; + UINT_16 u2ActivedTspec = 0; + UINT_8 ucNewUp = 0; + P_QUE_T prSrcQue = NULL; + P_QUE_T prDstQue = NULL; + P_MSDU_INFO_T prMsduInfo = NULL; + P_AC_QUE_PARMS_T prAcQueParam = NULL; + + if (!prStaRec || eAci == ACI_NUM || eAci == ACI_BK) { + DBGLOG(QM, ERROR, "prSta NULL %d, eAci %d, prAdapter NULL %d\n", !prStaRec, eAci, !prAdapter); + return; + } + prSrcQue = &prStaRec->arTxQueue[eAci]; + prAcQueParam = &(prAdapter->rWifiVar.arBssInfo[eNetType].arACQueParms[0]); + u2ActivedTspec = wmmHasActiveTspec(&prAdapter->rWifiVar.rWmmInfo); + + while (prAcQueParam[eAci].fgIsACMSet && + (u2ActivedTspec & BIT(eAci)) && eAci != ACI_BK) { + eAci = aeNextAci[eAci]; + ucNewUp = aucNextUP[eAci]; + } + + prDstQue = &prStaRec->arTxQueue[eAci]; + prMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_HEAD(prSrcQue); + while (prMsduInfo) { + prMsduInfo->ucUserPriority = ucNewUp; + prMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY(&prMsduInfo->rQueEntry); + } + QUEUE_CONCATENATE_QUEUES(prDstQue, prSrcQue); +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_bow.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_bow.c new file mode 100644 index 0000000000000..dd2e79ced765d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_bow.c @@ -0,0 +1,1006 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "debug.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "precomp.h" +#include +#include "bss.h" + +#if CFG_ENABLE_BT_OVER_WIFI + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* @FIXME if there is command/event with payload length > 28 */ +#define MAX_BUFFER_SIZE (64) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +#if CFG_BOW_TEST +UINT_32 g_u4PrevSysTime; +UINT_32 g_u4CurrentSysTime; +UINT_32 g_arBowRevPalPacketTime[11]; +#endif + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/* forward declarations */ +static ssize_t mt6620_ampc_read(IN struct file *filp, IN char __user *buf, IN size_t size, IN OUT loff_t *ppos); + +static ssize_t +mt6620_ampc_write(IN struct file *filp, OUT const char __user *buf, IN size_t size, IN OUT loff_t *ppos); + +static long mt6620_ampc_ioctl(IN struct file *filp, IN unsigned int cmd, IN OUT unsigned long arg); + +static unsigned int mt6620_ampc_poll(IN struct file *filp, IN poll_table * wait); + +static int mt6620_ampc_open(IN struct inode *inodep, IN struct file *filp); + +static int mt6620_ampc_release(IN struct inode *inodep, IN struct file *filp); + +/* character file operations */ +static const struct file_operations mt6620_ampc_fops = { + /* .owner = THIS_MODULE, */ + .read = mt6620_ampc_read, + .write = mt6620_ampc_write, + .unlocked_ioctl = mt6620_ampc_ioctl, + .poll = mt6620_ampc_poll, + .open = mt6620_ampc_open, + .release = mt6620_ampc_release, +}; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Register for character device to communicate with 802.11 PAL +* +* \param[in] prGlueInfo Pointer to glue info +* +* \return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN glRegisterAmpc(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + if (prGlueInfo->rBowInfo.fgIsRegistered == TRUE) + return FALSE; + +#if 0 + /* 1. allocate major number dynamically */ + + if (alloc_chrdev_region(&(prGlueInfo->rBowInfo.u4DeviceNumber), 0, /* first minor number */ + 1, /* number */ + GLUE_BOW_DEVICE_NAME) != 0) + + return FALSE; +#endif + +#if 1 + +#if defined(CONFIG_AMPC_CDEV_NUM) + prGlueInfo->rBowInfo.u4DeviceNumber = MKDEV(CONFIG_AMPC_CDEV_NUM, 0); +#else + prGlueInfo->rBowInfo.u4DeviceNumber = MKDEV(226, 0); +#endif + + if (register_chrdev_region(prGlueInfo->rBowInfo.u4DeviceNumber, 1, /* number */ + GLUE_BOW_DEVICE_NAME) != 0) + + return FALSE; +#endif + + /* 2. spin-lock initialization */ + /* spin_lock_init(&(prGlueInfo->rBowInfo.rSpinLock)); */ + + /* 3. initialize kfifo */ + /* + * prGlueInfo->rBowInfo.prKfifo = kfifo_alloc(GLUE_BOW_KFIFO_DEPTH, + * GFP_KERNEL, + * &(prGlueInfo->rBowInfo.rSpinLock)); + */ + if ((kfifo_alloc((struct kfifo *)&(prGlueInfo->rBowInfo.rKfifo), GLUE_BOW_KFIFO_DEPTH, GFP_KERNEL))) + goto fail_kfifo_alloc; + + /* if(prGlueInfo->rBowInfo.prKfifo == NULL) */ + if (&(prGlueInfo->rBowInfo.rKfifo) == NULL) + goto fail_kfifo_alloc; + + /* 4. initialize cdev */ + cdev_init(&(prGlueInfo->rBowInfo.cdev), &mt6620_ampc_fops); + /* prGlueInfo->rBowInfo.cdev.owner = THIS_MODULE; */ + prGlueInfo->rBowInfo.cdev.ops = &mt6620_ampc_fops; + + /* 5. add character device */ + if (cdev_add(&(prGlueInfo->rBowInfo.cdev), prGlueInfo->rBowInfo.u4DeviceNumber, 1)) + goto fail_cdev_add; + + /* 6. in queue initialization */ + init_waitqueue_head(&(prGlueInfo->rBowInfo.outq)); + + /* 7. finish */ + prGlueInfo->rBowInfo.fgIsRegistered = TRUE; + return TRUE; + +fail_cdev_add: + kfifo_free(&(prGlueInfo->rBowInfo.rKfifo)); +/* kfifo_free(prGlueInfo->rBowInfo.prKfifo); */ +fail_kfifo_alloc: + unregister_chrdev_region(prGlueInfo->rBowInfo.u4DeviceNumber, 1); + return FALSE; +} /* end of glRegisterAmpc */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Unregister character device for communicating with 802.11 PAL +* +* \param[in] prGlueInfo Pointer to glue info +* +* \return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN glUnregisterAmpc(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + if (prGlueInfo->rBowInfo.fgIsRegistered == FALSE) + return FALSE; + + prGlueInfo->rBowInfo.fgIsRegistered = FALSE; + + /* 1. free netdev if necessary */ +#if CFG_BOW_SEPARATE_DATA_PATH + kalUninitBowDevice(prGlueInfo); +#endif + + /* 2. removal of character device */ + cdev_del(&(prGlueInfo->rBowInfo.cdev)); + + /* 3. free kfifo */ +/* kfifo_free(prGlueInfo->rBowInfo.prKfifo); */ + kfifo_free(&(prGlueInfo->rBowInfo.rKfifo)); +/* prGlueInfo->rBowInfo.prKfifo = NULL; */ +/* prGlueInfo->rBowInfo.rKfifo = NULL; */ + + /* 4. free device number */ + unregister_chrdev_region(prGlueInfo->rBowInfo.u4DeviceNumber, 1); + + return TRUE; +} /* end of glUnregisterAmpc */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief read handler for character device to communicate with 802.11 PAL +* +* \param[in] +* \return +* Follows Linux Character Device Interface +* +*/ +/*----------------------------------------------------------------------------*/ +static ssize_t mt6620_ampc_read(IN struct file *filp, IN char __user *buf, IN size_t size, IN OUT loff_t *ppos) +{ + UINT_8 aucBuffer[MAX_BUFFER_SIZE]; + ssize_t retval; + P_GLUE_INFO_T prGlueInfo; + + prGlueInfo = (P_GLUE_INFO_T) (filp->private_data); + + ASSERT(prGlueInfo); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return -EFAULT; + /* size check */ +/* if(kfifo_len(prGlueInfo->rBowInfo.prKfifo) >= size) */ + if (kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)) >= size) + retval = size; + else + retval = kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)); +/* retval = kfifo_len(prGlueInfo->rBowInfo.prKfifo); */ + +/* kfifo_get(prGlueInfo->rBowInfo.prKfifo, aucBuffer, retval); */ +/* kfifo_out(prGlueInfo->rBowInfo.prKfifo, aucBuffer, retval); */ + if (!(kfifo_out(&(prGlueInfo->rBowInfo.rKfifo), aucBuffer, retval))) { + retval = -EIO; + return retval; + } + + if (copy_to_user(buf, aucBuffer, retval)) + retval = -EIO; + + return retval; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief write handler for character device to communicate with 802.11 PAL +* +* \param[in] +* \return +* Follows Linux Character Device Interface +* +*/ +/*----------------------------------------------------------------------------*/ +static ssize_t +mt6620_ampc_write(IN struct file *filp, OUT const char __user *buf, IN size_t size, IN OUT loff_t *ppos) +{ +#if CFG_BOW_TEST + UINT_8 i; +#endif + + UINT_8 aucBuffer[MAX_BUFFER_SIZE]; + P_AMPC_COMMAND prCmd; + P_GLUE_INFO_T prGlueInfo; + + prGlueInfo = (P_GLUE_INFO_T) (filp->private_data); + ASSERT(prGlueInfo); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return -EFAULT; + + if (size > MAX_BUFFER_SIZE) + return -EINVAL; + else if (copy_from_user(aucBuffer, buf, size)) + return -EIO; + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "AMP driver CMD buffer size : %d.\n", size); + + for (i = 0; i < MAX_BUFFER_SIZE; i++) + DBGLOG(BOW, EVENT, "AMP write content : 0x%x.\n", aucBuffer[i]); + + DBGLOG(BOW, EVENT, "BoW CMD write.\n"); +#endif + + prCmd = (P_AMPC_COMMAND) aucBuffer; + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "AMP write content payload length : %d.\n", prCmd->rHeader.u2PayloadLength); + + DBGLOG(BOW, EVENT, "AMP write content header length : %d.\n", sizeof(AMPC_COMMAND_HEADER_T)); +#endif + + /* size check */ + if (prCmd->rHeader.u2PayloadLength + sizeof(AMPC_COMMAND_HEADER_T) != size) { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "Wrong CMD total length.\n"); +#endif + + return -EINVAL; + } + + if (wlanbowHandleCommand(prGlueInfo->prAdapter, prCmd) == WLAN_STATUS_SUCCESS) + return size; + else + return -EINVAL; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief ioctl handler for character device to communicate with 802.11 PAL +* +* \param[in] +* \return +* Follows Linux Character Device Interface +* +*/ +/*----------------------------------------------------------------------------*/ +static long mt6620_ampc_ioctl(IN struct file *filp, IN unsigned int cmd, IN OUT unsigned long arg) +{ + int err = 0; + P_GLUE_INFO_T prGlueInfo; + + prGlueInfo = (P_GLUE_INFO_T) (filp->private_data); + + ASSERT(prGlueInfo); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return -EFAULT; + /* permission check */ + if (_IOC_DIR(cmd) & _IOC_READ) + err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)); + else if (_IOC_DIR(cmd) & _IOC_WRITE) + err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)); + if (err) + return -EFAULT; + + /* no ioctl is implemented yet */ + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief ioctl handler for character device to communicate with 802.11 PAL +* +* \param[in] +* \return +* Follows Linux Character Device Interface +* +*/ +/*----------------------------------------------------------------------------*/ +static unsigned int mt6620_ampc_poll(IN struct file *filp, IN poll_table * wait) +{ + unsigned int retval; + P_GLUE_INFO_T prGlueInfo; + + prGlueInfo = (P_GLUE_INFO_T) (filp->private_data); + + ASSERT(prGlueInfo); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return -EFAULT; + + poll_wait(filp, &prGlueInfo->rBowInfo.outq, wait); + + retval = (POLLOUT | POLLWRNORM); /* always accepts incoming command packets */ + +/* DBGLOG(BOW, EVENT, ("mt6620_ampc_pol, POLLOUT | POLLWRNORM, %x\n", retval)); */ + +/* if(kfifo_len(prGlueInfo->rBowInfo.prKfifo) > 0) */ + if (kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)) > 0) { + retval |= (POLLIN | POLLRDNORM); + +/* DBGLOG(BOW, EVENT, ("mt6620_ampc_pol, POLLIN | POLLRDNORM, %x\n", retval)); */ + + } + + return retval; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief open handler for character device to communicate with 802.11 PAL +* +* \param[in] +* \return +* Follows Linux Character Device Interface +* +*/ +/*----------------------------------------------------------------------------*/ +static int mt6620_ampc_open(IN struct inode *inodep, IN struct file *filp) +{ + P_GLUE_INFO_T prGlueInfo; + P_GL_BOW_INFO prBowInfo; + + prBowInfo = container_of(inodep->i_cdev, GL_BOW_INFO, cdev); + ASSERT(prBowInfo); + + prGlueInfo = container_of(prBowInfo, GLUE_INFO_T, rBowInfo); + ASSERT(prGlueInfo); + + /* set-up private data */ + filp->private_data = prGlueInfo; + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief close handler for character device to communicate with 802.11 PAL +* +* \param[in] +* \return +* Follows Linux Character Device Interface +* +*/ +/*----------------------------------------------------------------------------*/ +static int mt6620_ampc_release(IN struct inode *inodep, IN struct file *filp) +{ + P_GLUE_INFO_T prGlueInfo; + + prGlueInfo = (P_GLUE_INFO_T) (filp->private_data); + + ASSERT(prGlueInfo); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to indicate event for Bluetooth over Wi-Fi +* +* \param[in] +* prGlueInfo +* prEvent +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalIndicateBOWEvent(IN P_GLUE_INFO_T prGlueInfo, IN P_AMPC_EVENT prEvent) +{ + size_t u4AvailSize, u4EventSize; + + ASSERT(prGlueInfo); + ASSERT(prEvent); + + /* check device */ + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return; + + /* + * u4AvailSize = + * GLUE_BOW_KFIFO_DEPTH - kfifo_len(prGlueInfo->rBowInfo.prKfifo); + */ + + u4AvailSize = GLUE_BOW_KFIFO_DEPTH - kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)); + + u4EventSize = prEvent->rHeader.u2PayloadLength + sizeof(AMPC_EVENT_HEADER_T); + + /* check kfifo availability */ + if (u4AvailSize < u4EventSize) { + DBGLOG(BOW, EVENT, "[bow] no space for event: %zu/%zu\n", u4EventSize, u4AvailSize); + return; + } + /* queue into kfifo */ + /* kfifo_put(prGlueInfo->rBowInfo.prKfifo, (PUINT_8)prEvent, u4EventSize); */ + /* kfifo_in(prGlueInfo->rBowInfo.prKfifo, (PUINT_8)prEvent, u4EventSize); */ + kfifo_in(&(prGlueInfo->rBowInfo.rKfifo), (PUINT_8) prEvent, u4EventSize); + wake_up_interruptible(&(prGlueInfo->rBowInfo.outq)); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Bluetooth-over-Wi-Fi state from glue layer +* +* \param[in] +* prGlueInfo +* rPeerAddr +* \return +* ENUM_BOW_DEVICE_STATE +*/ +/*----------------------------------------------------------------------------*/ +ENUM_BOW_DEVICE_STATE kalGetBowState(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 aucPeerAddress[6]) +{ + UINT_8 i; + + ASSERT(prGlueInfo); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "kalGetBowState.\n"); +#endif + + for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { + if (EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr, aucPeerAddress) == 0) { + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "kalGetBowState, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", i, + aucPeerAddress[0], + aucPeerAddress[1], + aucPeerAddress[2], + aucPeerAddress[3], aucPeerAddress[4], aucPeerAddress[5])); + + DBGLOG(BOW, EVENT, + "kalGetBowState, prGlueInfo->rBowInfo.aeState %x, %x.\n", i, + prGlueInfo->rBowInfo.aeState[i]); + +#endif + + return prGlueInfo->rBowInfo.aeState[i]; + } + } + + return BOW_DEVICE_STATE_DISCONNECTED; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to set Bluetooth-over-Wi-Fi state in glue layer +* +* \param[in] +* prGlueInfo +* eBowState +* rPeerAddr +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalSetBowState(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_BOW_DEVICE_STATE eBowState, IN UINT_8 aucPeerAddress[6]) +{ + UINT_8 i; + + ASSERT(prGlueInfo); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "kalSetBowState.\n"); + + DBGLOG(BOW, EVENT, "kalSetBowState, prGlueInfo->rBowInfo.arPeerAddr, %x:%x:%x:%x:%x:%x.\n", + prGlueInfo->rBowInfo.arPeerAddr[0], + prGlueInfo->rBowInfo.arPeerAddr[1], + prGlueInfo->rBowInfo.arPeerAddr[2], + prGlueInfo->rBowInfo.arPeerAddr[3], + prGlueInfo->rBowInfo.arPeerAddr[4], prGlueInfo->rBowInfo.arPeerAddr[5])); + + DBGLOG(BOW, EVENT, "kalSetBowState, aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + aucPeerAddress[0], + aucPeerAddress[1], + aucPeerAddress[2], aucPeerAddress[3], aucPeerAddress[4], aucPeerAddress[5]); +#endif + + for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { + if (EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr, aucPeerAddress) == 0) { + prGlueInfo->rBowInfo.aeState[i] = eBowState; + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "kalSetBowState, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", i, + aucPeerAddress[0], + aucPeerAddress[1], + aucPeerAddress[2], + aucPeerAddress[3], aucPeerAddress[4], aucPeerAddress[5])); + + DBGLOG(BOW, EVENT, + "kalSetBowState, prGlueInfo->rBowInfo.aeState %x, %x.\n", i, + prGlueInfo->rBowInfo.aeState[i]); +#endif + + return TRUE; + } + } + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Bluetooth-over-Wi-Fi global state +* +* \param[in] +* prGlueInfo +* +* \return +* BOW_DEVICE_STATE_DISCONNECTED +* in case there is no BoW connection or +* BoW connection under initialization +* +* BOW_DEVICE_STATE_STARTING +* in case there is no BoW connection but +* some BoW connection under initialization +* +* BOW_DEVICE_STATE_CONNECTED +* in case there is any BoW connection available +*/ +/*----------------------------------------------------------------------------*/ +ENUM_BOW_DEVICE_STATE kalGetBowGlobalState(IN P_GLUE_INFO_T prGlueInfo) +{ + UINT_32 i; + + ASSERT(prGlueInfo); + +/* Henry, can reduce this logic to indentify state change */ + + for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { + if (prGlueInfo->rBowInfo.aeState[i] == BOW_DEVICE_STATE_CONNECTED) + return BOW_DEVICE_STATE_CONNECTED; + } + + for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { + if (prGlueInfo->rBowInfo.aeState[i] == BOW_DEVICE_STATE_STARTING) + return BOW_DEVICE_STATE_STARTING; + } + + return BOW_DEVICE_STATE_DISCONNECTED; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Bluetooth-over-Wi-Fi operating frequency +* +* \param[in] +* prGlueInfo +* +* \return +* in unit of KHz +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 kalGetBowFreqInKHz(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->rBowInfo.u4FreqInKHz; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Bluetooth-over-Wi-Fi role +* +* \param[in] +* prGlueInfo +* +* \return +* 0: Responder +* 1: Initiator +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 kalGetBowRole(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rPeerAddr) +{ + UINT_32 i; + + ASSERT(prGlueInfo); + + for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { + if (EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr[i], rPeerAddr) == 0) + return prGlueInfo->rBowInfo.aucRole[i]; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to set Bluetooth-over-Wi-Fi role +* +* \param[in] +* prGlueInfo +* ucRole +* 0: Responder +* 1: Initiator +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalSetBowRole(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRole, IN PARAM_MAC_ADDRESS rPeerAddr) +{ + UINT_32 i; + + ASSERT(prGlueInfo); + ASSERT(ucRole <= 1); + + for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { + if (EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr[i], rPeerAddr) == 0) + prGlueInfo->rBowInfo.aucRole[i] = ucRole; /* Henry, 0 : Responder, 1 : Initiator */ + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to get available Bluetooth-over-Wi-Fi physical link number +* +* \param[in] +* prGlueInfo +* \return +* UINT_32 +* how many physical links are aviailable +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 kalGetBowAvailablePhysicalLinkCount(IN P_GLUE_INFO_T prGlueInfo) +{ + UINT_8 i; + UINT_8 ucLinkCount = 0; + + ASSERT(prGlueInfo); + + for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { + if (prGlueInfo->rBowInfo.aeState[i] == BOW_DEVICE_STATE_DISCONNECTED) + ucLinkCount++; + } + +#if 0 /* CFG_BOW_TEST */ + DBGLOG(BOW, EVENT, "kalGetBowAvailablePhysicalLinkCount, ucLinkCount, %c.\n", ucLinkCount); +#endif + + return ucLinkCount; +} + +#if CFG_BOW_SEPARATE_DATA_PATH + +/* Net Device Hooks */ +/*----------------------------------------------------------------------------*/ +/*! + * \brief A function for net_device open (ifup) + * + * \param[in] prDev Pointer to struct net_device. + * + * \retval 0 The execution succeeds. + * \retval < 0 The execution failed. + */ +/*----------------------------------------------------------------------------*/ +static int bowOpen(IN struct net_device *prDev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + /* 2. carrier on & start TX queue */ + netif_carrier_on(prDev); + netif_tx_start_all_queues(prDev); + + return 0; /* success */ +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief A function for net_device stop (ifdown) + * + * \param[in] prDev Pointer to struct net_device. + * + * \retval 0 The execution succeeds. + * \retval < 0 The execution failed. + */ +/*----------------------------------------------------------------------------*/ +static int bowStop(IN struct net_device *prDev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + /* 1. stop TX queue */ + netif_tx_stop_all_queues(prDev); + + /* 2. turn of carrier */ + if (netif_carrier_ok(prDev)) + netif_carrier_off(prDev); + + return 0; +}; + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is TX entry point of NET DEVICE. + * + * \param[in] prSkb Pointer of the sk_buff to be sent + * \param[in] prDev Pointer to struct net_device + * + * \retval NETDEV_TX_OK - on success. + * \retval NETDEV_TX_BUSY - on failure, packet will be discarded by upper layer. + */ +/*----------------------------------------------------------------------------*/ +static int bowHardStartXmit(IN struct sk_buff *prSkb, IN struct net_device *prDev) +{ + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + + P_QUE_ENTRY_T prQueueEntry = NULL; + P_QUE_T prTxQueue = NULL; + UINT_16 u2QueueIdx = 0; + UINT_8 ucDSAP, ucSSAP, ucControl; + UINT_8 aucOUI[3]; + PUINT_8 aucLookAheadBuf = NULL; + +#if CFG_BOW_TEST + UINT_32 i; +#endif + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prSkb); + ASSERT(prDev); + ASSERT(prGlueInfo); + + aucLookAheadBuf = prSkb->data; + + ucDSAP = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET]; + ucSSAP = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET + 1]; + ucControl = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET + 2]; + aucOUI[0] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET]; + aucOUI[1] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET + 1]; + aucOUI[2] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET + 2]; + prGlueInfo->u8SkbToDriver++; + + if (!(ucDSAP == ETH_LLC_DSAP_SNAP && + ucSSAP == ETH_LLC_SSAP_SNAP && + ucControl == ETH_LLC_CONTROL_UNNUMBERED_INFORMATION && + aucOUI[0] == ETH_SNAP_BT_SIG_OUI_0 && + aucOUI[1] == ETH_SNAP_BT_SIG_OUI_1 && aucOUI[2] == ETH_SNAP_BT_SIG_OUI_2) || (prSkb->len > 1514)) { + +#if CFG_BOW_TEST + DBGLOG(BOW, TRACE, "Invalid BOW packet, skip tx\n"); +#endif + + dev_kfree_skb(prSkb); + prGlueInfo->u8SkbFreed++; + return NETDEV_TX_OK; + } + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(BOW, TRACE, "GLUE_FLAG_HALT skip tx\n"); + dev_kfree_skb(prSkb); + prGlueInfo->u8SkbFreed++; + return NETDEV_TX_OK; + } + + prQueueEntry = (P_QUE_ENTRY_T) GLUE_GET_PKT_QUEUE_ENTRY(prSkb); + prTxQueue = &prGlueInfo->rTxQueue; + +#if CFG_BOW_TEST + DBGLOG(BOW, TRACE, "Tx sk_buff->len: %d\n", prSkb->len); + DBGLOG(BOW, TRACE, "Tx sk_buff->data_len: %d\n", prSkb->data_len); + DBGLOG(BOW, TRACE, "Tx sk_buff->data:\n"); + + for (i = 0; i < prSkb->len; i++) { + DBGLOG(BOW, TRACE, "%4x", prSkb->data[i]); + + if ((i + 1) % 16 == 0) + DBGLOG(BOW, TRACE, "\n"); + } + + DBGLOG(BOW, TRACE, "\n"; +#endif +#if CFG_BOW_TEST +/* g_u4CurrentSysTime = (OS_SYSTIME)kalGetTimeTick(; */ + g_u4CurrentSysTime = (OS_SYSTIME) jiffies_to_usecs(jiffies); + i = g_u4CurrentSysTime - g_u4PrevSysTime; + if ((i >> 10) > 0) + i = 10; + else + i = i >> 7; + g_arBowRevPalPacketTime[i]++; + g_u4PrevSysTime = g_u4CurrentSysTime; +#endif + if (wlanProcessSecurityFrame(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb) == FALSE) { + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_INSERT_TAIL(prTxQueue, prQueueEntry); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingFrameNum); + GLUE_INC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_BOW_INDEX][u2QueueIdx]); + if (prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_BOW_INDEX][u2QueueIdx] >= + CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD) + DBGLOG(TX, INFO, "netif_stop_subqueue for BOW, Queue len: %d\n", + prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_BOW_INDEX][u2QueueIdx]); + + netif_stop_subqueue(prDev, u2QueueIdx); + } else { + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum); + } + + kalSetEvent(prGlueInfo); + /* For Linux, we'll always return OK FLAG, because we'll free this skb by ourself */ + return NETDEV_TX_OK; +} + +/* callbacks for netdevice */ +static const struct net_device_ops bow_netdev_ops = { + .ndo_open = bowOpen, .ndo_stop = bowStop, .ndo_start_xmit = bowHardStartXmit,}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief initialize net device for Bluetooth-over-Wi-Fi +* +* \param[in] +* prGlueInfo +* prDevName +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalInitBowDevice(IN P_GLUE_INFO_T prGlueInfo, IN const char *prDevName) +{ + P_ADAPTER_T prAdapter; + P_GL_HIF_INFO_T prHif; + PARAM_MAC_ADDRESS rMacAddr; + + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->rBowInfo.fgIsRegistered == TRUE); + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + prHif = &prGlueInfo->rHifInfo; + ASSERT(prHif); + if (prGlueInfo->rBowInfo.fgIsNetRegistered == FALSE) { + prGlueInfo->rBowInfo.prDevHandler = + alloc_netdev_mq(sizeof(P_GLUE_INFO_T), prDevName, NET_NAME_PREDICTABLE, ether_setup, CFG_MAX_TXQ_NUM); + if (!prGlueInfo->rBowInfo.prDevHandler) + return FALSE; + + /* 1. setup netdev */ + /* 1.1 Point to shared glue structure */ + *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->rBowInfo.prDevHandler)) = prGlueInfo; + /* 1.2 fill hardware address */ + COPY_MAC_ADDR(rMacAddr, prAdapter->rMyMacAddr); + rMacAddr[0] |= 0x2; + /* change to local administrated address */ + ether_addr_copy(prGlueInfo->rBowInfo.prDevHandler->dev_addr, rMacAddr); + ether_addr_copy(prGlueInfo->rBowInfo.prDevHandler->perm_addr, + prGlueInfo->rBowInfo.prDevHandler->dev_addr); + /* 1.3 register callback functions */ + prGlueInfo->rBowInfo.prDevHandler->netdev_ops = &bow_netdev_ops; +#if (MTK_WCN_HIF_SDIO == 0) + SET_NETDEV_DEV(prGlueInfo->rBowInfo.prDevHandler, prHif->Dev); +#endif + register_netdev(prGlueInfo->rBowInfo.prDevHandler); + /* 2. net device initialize */ + netif_carrier_off(prGlueInfo->rBowInfo.prDevHandler); + netif_tx_stop_all_queues(prGlueInfo->rBowInfo.prDevHandler); + /* 3. finish */ + prGlueInfo->rBowInfo.fgIsNetRegistered = TRUE; + } + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief uninitialize net device for Bluetooth-over-Wi-Fi +* +* \param[in] +* prGlueInfo +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalUninitBowDevice(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + /* ASSERT(prGlueInfo->rBowInfo.fgIsRegistered == TRUE); */ + if (prGlueInfo->rBowInfo.fgIsNetRegistered == TRUE) { + prGlueInfo->rBowInfo.fgIsNetRegistered = FALSE; + if (netif_carrier_ok(prGlueInfo->rBowInfo.prDevHandler)) + netif_carrier_off(prGlueInfo->rBowInfo.prDevHandler); + + netif_tx_stop_all_queues(prGlueInfo->rBowInfo.prDevHandler); + /* netdevice unregistration & free */ + unregister_netdev(prGlueInfo->rBowInfo.prDevHandler); + free_netdev(prGlueInfo->rBowInfo.prDevHandler); + prGlueInfo->rBowInfo.prDevHandler = NULL; + return TRUE; + } else { + return FALSE; + } +} +#endif /* CFG_BOW_SEPARATE_DATA_PATH */ +#endif /* CFG_ENABLE_BT_OVER_WIFI */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_cfg80211.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_cfg80211.c new file mode 100644 index 0000000000000..60fbb26cc2252 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_cfg80211.c @@ -0,0 +1,3661 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ +#include "gl_os.h" +#include "debug.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "precomp.h" +#include +#include +#include +#include "gl_cfg80211.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/* + * workaround for some ANR CRs. if suppliant is blocked longer than 10s, wifi hal will tell wifiMonitor + * to teminate. for the case which can block supplicant 10s is to del key more than 5 times. the root cause + * is that there is no resource in TC4, so del key command was not able to set, and then oid + * timeout was happed. if we found the root cause why fw couldn't release TC resouce, we will remove this + * workaround + */ +static UINT_8 gucKeyIndex = 255; + +/******************************************************************************* +* P 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 + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +int +mtk_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, enum nl80211_iftype type, struct vif_params *params) +#else +int +mtk_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, enum nl80211_iftype type, u32 *flags, struct vif_params *params) +#endif +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + ENUM_PARAM_OP_MODE_T eOpMode; + UINT_32 u4BufLen; + + DBGLOG(REQ, INFO, "--> %s()\n", __func__); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + if (type == NL80211_IFTYPE_STATION) + eOpMode = NET_TYPE_INFRA; + else if (type == NL80211_IFTYPE_ADHOC) + eOpMode = NET_TYPE_IBSS; + else + return -EINVAL; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetInfrastructureMode, + &eOpMode, sizeof(eOpMode), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "set infrastructure mode error:%x\n", rStatus); + + /* reset wpa info */ + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + prGlueInfo->rWpaInfo.u4KeyMgmt = 0; + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; +#if CFG_SUPPORT_802_11W + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; +#endif + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for adding key + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_add_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, bool pairwise, const u8 *mac_addr, struct key_params *params) +{ + PARAM_KEY_T rKey; + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + INT_32 i4Rslt = -EINVAL; + UINT_32 u4BufLen = 0; + UINT_8 tmp1[8]; + UINT_8 tmp2[8]; + + DBGLOG(REQ, INFO, "--> %s()\n", __func__); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + kalMemZero(&rKey, sizeof(PARAM_KEY_T)); + + rKey.u4KeyIndex = key_index; + + if (params->cipher) { + switch (params->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + rKey.ucCipher = CIPHER_SUITE_WEP40; + break; + case WLAN_CIPHER_SUITE_WEP104: + rKey.ucCipher = CIPHER_SUITE_WEP104; + break; + case WLAN_CIPHER_SUITE_TKIP: + rKey.ucCipher = CIPHER_SUITE_TKIP; + break; + case WLAN_CIPHER_SUITE_CCMP: + rKey.ucCipher = CIPHER_SUITE_CCMP; + break; + case WLAN_CIPHER_SUITE_SMS4: + rKey.ucCipher = CIPHER_SUITE_WPI; + break; + case WLAN_CIPHER_SUITE_AES_CMAC: + rKey.ucCipher = CIPHER_SUITE_BIP; + break; + default: + ASSERT(FALSE); + } + } + + if (mac_addr) { + COPY_MAC_ADDR(rKey.arBSSID, mac_addr); + if ((rKey.arBSSID[0] == 0x00) && (rKey.arBSSID[1] == 0x00) && (rKey.arBSSID[2] == 0x00) && + (rKey.arBSSID[3] == 0x00) && (rKey.arBSSID[4] == 0x00) && (rKey.arBSSID[5] == 0x00)) { + rKey.arBSSID[0] = 0xff; + rKey.arBSSID[1] = 0xff; + rKey.arBSSID[2] = 0xff; + rKey.arBSSID[3] = 0xff; + rKey.arBSSID[4] = 0xff; + rKey.arBSSID[5] = 0xff; + } + if (rKey.arBSSID[0] != 0xFF) { + rKey.u4KeyIndex |= BIT(31); + if ((rKey.arBSSID[0] != 0x00) || (rKey.arBSSID[1] != 0x00) || (rKey.arBSSID[2] != 0x00) || + (rKey.arBSSID[3] != 0x00) || (rKey.arBSSID[4] != 0x00) || (rKey.arBSSID[5] != 0x00)) + rKey.u4KeyIndex |= BIT(30); + } + } else { + rKey.arBSSID[0] = 0xff; + rKey.arBSSID[1] = 0xff; + rKey.arBSSID[2] = 0xff; + rKey.arBSSID[3] = 0xff; + rKey.arBSSID[4] = 0xff; + rKey.arBSSID[5] = 0xff; + /* rKey.u4KeyIndex |= BIT(31);//Enable BIT 31 will make tx use bc key id,should use pairwise key id 0 */ + } + + if (params->key) { + /* rKey.aucKeyMaterial[0] = kalMemAlloc(params->key_len, VIR_MEM_TYPE); */ + kalMemCopy(rKey.aucKeyMaterial, params->key, params->key_len); + if (params->key_len == 32) { + kalMemCopy(tmp1, ¶ms->key[16], 8); + kalMemCopy(tmp2, ¶ms->key[24], 8); + kalMemCopy(&rKey.aucKeyMaterial[16], tmp2, 8); + kalMemCopy(&rKey.aucKeyMaterial[24], tmp1, 8); + } + } + + rKey.u4KeyLength = params->key_len; + rKey.u4Length = ((ULONG)&(((P_PARAM_KEY_T) 0)->aucKeyMaterial)) + rKey.u4KeyLength; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetAddKey, &rKey, rKey.u4Length, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus == WLAN_STATUS_SUCCESS) + i4Rslt = 0; + + return i4Rslt; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for getting key for specified STA + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_get_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, + bool pairwise, + const u8 *mac_addr, void *cookie, void (*callback) (void *cookie, struct key_params *)) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, TRACE, "--> %s()\n", __func__); + + /* not implemented */ + + return -EINVAL; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for removing key for specified STA + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_index, bool pairwise, const u8 *mac_addr) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + PARAM_REMOVE_KEY_T rRemoveKey; + UINT_32 u4BufLen = 0; + INT_32 i4Rslt = -EINVAL; + + DBGLOG(REQ, INFO, "--> %s()\n", __func__); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + kalMemZero(&rRemoveKey, sizeof(PARAM_REMOVE_KEY_T)); + if (mac_addr) + COPY_MAC_ADDR(rRemoveKey.arBSSID, mac_addr); + else if (key_index <= gucKeyIndex) { /* new operation, reset gucKeyIndex */ + gucKeyIndex = 255; + } else { /* bypass the next remove key operation */ + gucKeyIndex = key_index; + return -EBUSY; + } + rRemoveKey.u4KeyIndex = key_index; + rRemoveKey.u4Length = sizeof(PARAM_REMOVE_KEY_T); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRemoveKey, &rRemoveKey, rRemoveKey.u4Length, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "remove key error:%x\n", rStatus); + if (rStatus == WLAN_STATUS_FAILURE && mac_addr) { + i4Rslt = -EBUSY; + gucKeyIndex = key_index; + } + } else { + gucKeyIndex = 255; + i4Rslt = 0; + } + + return i4Rslt; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for setting default key on an interface + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_index, bool unicast, bool multicast) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, TRACE, "--> %s()\n", __func__); + + /* not implemented */ + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for setting set_default_mgmt_ke on an interface + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_set_default_mgmt_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index) +{ + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for getting station information such as RSSI + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, const u8 *mac, struct station_info *sinfo) +{ +#define LINKSPEED_MAX_RANGE_11BGN 3000 + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + PARAM_MAC_ADDRESS arBssid; + UINT_32 u4BufLen; + UINT_32 u4Rate = 0; + UINT_32 u8diffTxBad, u8diffRetry; + INT_32 i4Rssi = 0; + PARAM_802_11_STATISTICS_STRUCT_T rStatistics; + + DBGLOG(REQ, TRACE, "--> %s()\n", __func__); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + kalMemZero(arBssid, MAC_ADDR_LEN); + wlanQueryInformation(prGlueInfo->prAdapter, wlanoidQueryBssid, &arBssid[0], sizeof(arBssid), &u4BufLen); + + /* 1. check BSSID */ + if (UNEQUAL_MAC_ADDR(arBssid, mac)) { + /* wrong MAC address */ + DBGLOG(REQ, WARN, "incorrect BSSID: [ %pM ] currently connected BSSID[ %pM ]\n", + mac, arBssid); + /* wificond will bring the mac address of the device itself */ + /* return -ENOENT; */ + } + + /* 2. fill TX rate */ + if (prGlueInfo->eParamMediaStateIndicated != PARAM_MEDIA_STATE_CONNECTED) { + /* not connected */ + DBGLOG(REQ, WARN, "not yet connected\n"); + } else { + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryLinkSpeed, &u4Rate, sizeof(u4Rate), TRUE, FALSE, FALSE, FALSE, &u4BufLen); + if ((rStatus != WLAN_STATUS_SUCCESS) || (u4Rate == 0)) { + /* DBGLOG(REQ, WARN, "unable to retrieve link speed\n")); */ + goto put_cache_info; + } else { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); +#else + sinfo->filled |= STATION_INFO_TX_BITRATE; +#endif + sinfo->txrate.legacy = u4Rate / 1000; /* convert from 100bps to 100kbps */ + prGlueInfo->u4LinkSpeedCache = u4Rate / 1000; + } + } + + /* 3. fill RSSI */ + if (prGlueInfo->eParamMediaStateIndicated != PARAM_MEDIA_STATE_CONNECTED) { + /* not connected */ + DBGLOG(REQ, WARN, "not yet connected\n"); + } else { + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryRssi, &i4Rssi, sizeof(i4Rssi), TRUE, FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS || (i4Rssi == PARAM_WHQL_RSSI_MIN_DBM) + || (i4Rssi == PARAM_WHQL_RSSI_MAX_DBM)) { + /* DBGLOG(REQ, WARN, "unable to retrieve link speed\n"); */ + goto put_cache_info; + } else { + /* in the cfg80211 layer, the signal is a signed char variable. */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); +#else + sinfo->filled |= STATION_INFO_SIGNAL; +#endif + sinfo->signal = i4Rssi; /* dBm */ + prGlueInfo->i4RssiCache = i4Rssi; + } + + /* 4. Fill Tx OK and Tx Bad */ + { + WLAN_STATUS rStatus; + + kalMemZero(&rStatistics, sizeof(rStatistics)); + /* Get Tx OK/Fail cnt from AIS statistic counter */ + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStatisticsPL, + &rStatistics, sizeof(rStatistics), TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + /* DBGLOG(REQ, WARN, "unable to retrieive statistic\n"); */ + goto put_cache_info; + } else { + INT_32 i4RssiThreshold = -85; /* set rssi threshold -85dBm */ + UINT_32 u4LinkspeedThreshold = 55; /* set link speed threshold 5.5Mbps */ + BOOLEAN fgWeighted = 0; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS); + sinfo->filled |= BIT(NL80211_STA_INFO_TX_FAILED); + sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES); + sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS); + sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES); +#else + sinfo->filled |= STATION_INFO_TX_PACKETS; + sinfo->filled |= STATION_INFO_TX_FAILED; + sinfo->filled |= STATION_INFO_TX_BYTES; + sinfo->filled |= STATION_INFO_RX_PACKETS; + sinfo->filled |= STATION_INFO_RX_BYTES; +#endif + + /* calculate difference */ + u8diffTxBad = rStatistics.rFailedCount.QuadPart - prGlueInfo->u8Statistic[0]; + u8diffRetry = rStatistics.rRetryCount.QuadPart - prGlueInfo->u8Statistic[1]; + /* restore counters */ + prGlueInfo->u8Statistic[0] = rStatistics.rFailedCount.QuadPart; + prGlueInfo->u8Statistic[1] = rStatistics.rRetryCount.QuadPart; + + /* check threshold is valid */ + if (prGlueInfo->fgPoorlinkValid) { + if (prGlueInfo->i4RssiThreshold) + i4RssiThreshold = prGlueInfo->i4RssiThreshold; + if (prGlueInfo->u4LinkspeedThreshold) + u4LinkspeedThreshold = prGlueInfo->u4LinkspeedThreshold; + } + /* add weighted to fail counter */ + if (sinfo->txrate.legacy < u4LinkspeedThreshold || sinfo->signal < i4RssiThreshold) { + prGlueInfo->u8TotalFailCnt += (u8diffTxBad * 16 + u8diffRetry); + fgWeighted = 1; + } else { + prGlueInfo->u8TotalFailCnt += u8diffTxBad; + } + /* report counters */ + /* prGlueInfo->rNetDevStats.tx_packets = + * rStatistics.rTransmittedFragmentCount.QuadPart; + */ + prGlueInfo->rNetDevStats.tx_errors = prGlueInfo->u8TotalFailCnt; + sinfo->tx_packets = prGlueInfo->rNetDevStats.tx_packets; + sinfo->tx_failed = prGlueInfo->rNetDevStats.tx_errors; + sinfo->tx_bytes = prGlueInfo->rNetDevStats.tx_bytes; + sinfo->rx_packets = prGlueInfo->rNetDevStats.rx_packets; + sinfo->rx_bytes = prGlueInfo->rNetDevStats.rx_bytes; + /* Good Fail Bad Difference retry difference Linkspeed Rate Weighted */ + DBGLOG(REQ, TRACE, + "Poorlink State TxOK:%lld %u RxOK:%u TxFail:%d Bad:%d Retry:%d TxBytes:%llu Rx:%llu", + rStatistics.rTransmittedFragmentCount.QuadPart, + sinfo->tx_packets, sinfo->rx_packets, + sinfo->tx_failed, + (int)u8diffTxBad, + (int)u8diffRetry, + sinfo->tx_bytes, sinfo->rx_bytes); + DBGLOG(REQ, TRACE, + "Rate(%d) Signal(%d) Weight(%d) QuadPart(%d)\n", + sinfo->txrate.legacy, + sinfo->signal, + (int)fgWeighted, + (int)rStatistics.rMultipleRetryCount.QuadPart); + } + } + } + return 0; + +put_cache_info: +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + if (!(BIT(NL80211_STA_INFO_TX_BITRATE) & sinfo->filled)) { +#else + if (!(STATION_INFO_TX_BITRATE & sinfo->filled)) { +#endif + DBGLOG(REQ, WARN, "last link speed, status=%d, rate=%d\n", rStatus, u4Rate); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); +#else + sinfo->filled |= STATION_INFO_TX_BITRATE; +#endif + sinfo->txrate.legacy = prGlueInfo->u4LinkSpeedCache; + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + if (!(BIT(NL80211_STA_INFO_SIGNAL) & sinfo->filled)) { +#else + if (!(STATION_INFO_SIGNAL & sinfo->filled)) { +#endif + DBGLOG(REQ, WARN, "last rssi\n"); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); +#else + sinfo->filled |= STATION_INFO_SIGNAL; +#endif + sinfo->signal = prGlueInfo->i4RssiCache; + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + if (!(BIT(NL80211_STA_INFO_TX_PACKETS) & sinfo->filled)) { +#else + if (!(STATION_INFO_TX_PACKETS & sinfo->filled)) { +#endif + DBGLOG(REQ, WARN, "last statistic\n"); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS); + sinfo->filled |= BIT(NL80211_STA_INFO_TX_FAILED); + sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES); + sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS); + sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES); +#else + sinfo->filled |= STATION_INFO_TX_PACKETS; + sinfo->filled |= STATION_INFO_TX_FAILED; + sinfo->filled |= STATION_INFO_TX_BYTES; + sinfo->filled |= STATION_INFO_RX_PACKETS; + sinfo->filled |= STATION_INFO_RX_BYTES; +#endif + sinfo->tx_packets = prGlueInfo->rNetDevStats.tx_packets; + sinfo->tx_failed = prGlueInfo->rNetDevStats.tx_errors; + sinfo->tx_bytes = prGlueInfo->rNetDevStats.tx_bytes; + sinfo->rx_packets = prGlueInfo->rNetDevStats.rx_packets; + sinfo->rx_bytes = prGlueInfo->rNetDevStats.rx_bytes; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for adding a station information + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_change_station(struct wiphy *wiphy, struct net_device *ndev, + const u8 *mac, struct station_parameters *params) +{ +#if (CFG_SUPPORT_TDLS == 1) + /* + * EX: In supplicant, + * (Supplicant) wpa_tdls_process_tpk_m3() -> + * (Supplicant) wpa_tdls_enable_link() -> + * (Supplicant) wpa_sm_tdls_peer_addset() -> + * (Supplicant) ..tdls_peer_addset() -> + * (Supplicant) wpa_supplicant_tdls_peer_addset() -> + * (Supplicant) wpa_drv_sta_add() -> + * (Supplicant) ..sta_add() -> + * (Supplicant) wpa_driver_nl80211_sta_add() -> + * (NL80211) nl80211_set_station() -> + * (Driver) mtk_cfg80211_change_station() + * + * if nl80211_set_station fails, supplicant will tear down the link. + */ + P_GLUE_INFO_T prGlueInfo; + TDLS_CMD_PEER_UPDATE_T rCmdUpdate; + WLAN_STATUS rStatus; + UINT_32 u4BufLen, u4Temp; + + /* sanity check */ + if ((wiphy == NULL) || (mac == NULL) || (params == NULL)) + return -EINVAL; + + DBGLOG(TDLS, INFO, "%s: 0x%p 0x%x\n", __func__, params->supported_rates, params->sta_flags_set); + + if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) + return -EOPNOTSUPP; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(ndev)); + if (prGlueInfo == NULL) + return -EINVAL; + + /* TODO: check if we are station mode, not AP mode */ + + /* init */ + kalMemZero(&rCmdUpdate, sizeof(rCmdUpdate)); + kalMemCopy(rCmdUpdate.aucPeerMac, mac, 6); + + if (ndev == prGlueInfo->prDevHandler) { + DBGLOG(TDLS, INFO, "AIS network\n"); + rCmdUpdate.eNetworkType = NETWORK_TYPE_AIS_INDEX; + } else { + DBGLOG(TDLS, INFO, "P2P network\n"); + rCmdUpdate.eNetworkType = NETWORK_TYPE_P2P_INDEX; + } + + if (params->supported_rates != NULL) { + u4Temp = params->supported_rates_len; + if (u4Temp > TDLS_CMD_PEER_UPDATE_SUP_RATE_MAX) { + u4Temp = TDLS_CMD_PEER_UPDATE_SUP_RATE_MAX; + DBGLOG(TDLS, ERROR, "%s sup rate too long: %d\n", __func__, params->supported_rates_len); + } + kalMemCopy(rCmdUpdate.aucSupRate, params->supported_rates, u4Temp); + rCmdUpdate.u2SupRateLen = u4Temp; + } + + /* + * In supplicant, only recognize WLAN_EID_QOS 46, not 0xDD WMM + * So force to support UAPSD here. + */ + rCmdUpdate.UapsdBitmap = 0x0F; /*params->uapsd_queues; */ + rCmdUpdate.UapsdMaxSp = 0; /*params->max_sp; */ + + DBGLOG(TDLS, INFO, "%s: UapsdBitmap=0x%x UapsdMaxSp=%d\n", + __func__, rCmdUpdate.UapsdBitmap, rCmdUpdate.UapsdMaxSp); + + rCmdUpdate.u2Capability = params->capability; + + if (params->ext_capab != NULL) { + u4Temp = params->ext_capab_len; + if (u4Temp > TDLS_CMD_PEER_UPDATE_EXT_CAP_MAXLEN) { + u4Temp = TDLS_CMD_PEER_UPDATE_EXT_CAP_MAXLEN; + DBGLOG(TDLS, ERROR, "%s ext_capab too long: %d\n", __func__, params->ext_capab_len); + } + kalMemCopy(rCmdUpdate.aucExtCap, params->ext_capab, u4Temp); + rCmdUpdate.u2ExtCapLen = u4Temp; + } + + if (params->ht_capa != NULL) { + DBGLOG(TDLS, INFO, "%s: peer is 11n device\n", __func__); + + rCmdUpdate.rHtCap.u2CapInfo = params->ht_capa->cap_info; + rCmdUpdate.rHtCap.ucAmpduParamsInfo = params->ht_capa->ampdu_params_info; + rCmdUpdate.rHtCap.u2ExtHtCapInfo = params->ht_capa->extended_ht_cap_info; + rCmdUpdate.rHtCap.u4TxBfCapInfo = params->ht_capa->tx_BF_cap_info; + rCmdUpdate.rHtCap.ucAntennaSelInfo = params->ht_capa->antenna_selection_info; + kalMemCopy(rCmdUpdate.rHtCap.rMCS.arRxMask, + params->ht_capa->mcs.rx_mask, sizeof(rCmdUpdate.rHtCap.rMCS.arRxMask)); + rCmdUpdate.rHtCap.rMCS.u2RxHighest = params->ht_capa->mcs.rx_highest; + rCmdUpdate.rHtCap.rMCS.ucTxParams = params->ht_capa->mcs.tx_params; + /* use ht info in TDLS setup frames */ + rCmdUpdate.fgIsSupHt = FALSE; + } + + /* update a TDLS peer record */ + rStatus = kalIoctl(prGlueInfo, + TdlsexPeerUpdate, + &rCmdUpdate, sizeof(TDLS_CMD_PEER_UPDATE_T), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s update error:%x\n", __func__, rStatus); + return -EINVAL; + } +#endif /* CFG_SUPPORT_TDLS */ + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for adding a station information + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_add_station(struct wiphy *wiphy, struct net_device *ndev, + const u8 *mac, struct station_parameters *params) +{ +#if (CFG_SUPPORT_TDLS == 1) + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + P_GLUE_INFO_T prGlueInfo; + TDLS_CMD_PEER_ADD_T rCmdCreate; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + + if ((wiphy == NULL) || (mac == NULL) || (params == NULL)) + return -EINVAL; + + /* + * wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, + * NULL, 0); + * + * wpa_sm_tdls_peer_addset(struct wpa_sm *sm, const u8 *addr, int add, + * u16 aid, u16 capability, const u8 *supp_rates, + * size_t supp_rates_len, + * const struct ieee80211_ht_capabilities *ht_capab, + * const struct ieee80211_vht_capabilities *vht_capab, + * u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len) + * + * Only MAC address of the peer is valid. + */ + + DBGLOG(TDLS, INFO, "%s: 0x%p %d\n", __func__, params->supported_rates, params->supported_rates_len); + + /* sanity check */ + if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) + return -EOPNOTSUPP; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(ndev)); + + if (prGlueInfo == NULL) + return -EINVAL; + + /* TODO: check if we are station mode, not AP mode */ + + /* init */ + kalMemZero(&rCmdCreate, sizeof(rCmdCreate)); + kalMemCopy(rCmdCreate.aucPeerMac, mac, 6); + + if (ndev == prGlueInfo->prDevHandler) { + DBGLOG(TDLS, INFO, "AIS network\n"); + rCmdCreate.eNetworkType = NETWORK_TYPE_AIS_INDEX; + } else { + DBGLOG(TDLS, INFO, "P2P network\n"); + rCmdCreate.eNetworkType = NETWORK_TYPE_P2P_INDEX; + } +#if 0 + rCmdCreate.eNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + + rCmdCreate.u2CapInfo = params->capability; + + DBGLOG(TDLS, INFO, " %s: capability = 0x%x\n", __func__, rCmdCreate.u2CapInfo); + + if ((params->supported_rates != NULL) && (params->supported_rates_len != 0)) { + UINT32 u4Idx; + + DBGLOG(TDLS, INFO, " %s: sup rate = 0x", __func__); + + rIeSup.ucId = ELEM_ID_SUP_RATES; + rIeSup.ucLength = params->supported_rates_len; + for (u4Idx = 0; u4Idx < rIeSup.ucLength; u4Idx++) { + rIeSup.aucSupportedRates[u4Idx] = params->supported_rates[u4Idx]; + DBGLOG(TDLS, INFO, "%x ", rIeSup.aucSupportedRates[u4Idx]); + } + DBGLOG(TDLS, INFO, "\n"); + + rateGetRateSetFromIEs(&rIeSup, + NULL, + &rCmdCreate.u2OperationalRateSet, + &rCmdCreate.u2BSSBasicRateSet, &rCmdCreate.fgIsUnknownBssBasicRate); + } + + /* phy type */ +#endif + + /* create a TDLS peer record */ + rStatus = kalIoctl(prGlueInfo, + TdlsexPeerAdd, + &rCmdCreate, sizeof(TDLS_CMD_PEER_ADD_T), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s create error:%x\n", __func__, rStatus); + return -EINVAL; + } +#endif /* CFG_SUPPORT_TDLS */ + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for deleting a station information + * + * @param + * + * @retval 0: successful + * others: failure + * + * @other + * must implement if you have add_station(). + */ +/*----------------------------------------------------------------------------*/ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +int mtk_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, struct station_del_parameters *params) +#else +int mtk_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, const u8 *mac) +#endif +{ + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to do a scan + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +#if CFG_MULTI_SSID_SCAN +static PARAM_SCAN_REQUEST_ADV_T rScanRequest; +#else +static PARAM_SCAN_REQUEST_EXT_T rScanRequest; +#endif +int mtk_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_BSS_INFO_T prBssInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + UINT_32 num_ssid = 0; + UINT_32 old_num_ssid = 0; + UINT_32 wildcard_flag = 0; +#if CFG_MULTI_SSID_SCAN + UINT_32 i, u4ValidIdx; +#endif +/* PARAM_SCAN_REQUEST_EXT_T rScanRequest; */ + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + prBssInfo = &(prGlueInfo->prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + if ((!prGlueInfo->prAdapter->fgEnCfg80211Scan) && + (kalGetMediaStateIndicated(prGlueInfo) == + PARAM_MEDIA_STATE_CONNECTED)) { + DBGLOG(SCN, WARN, "Disable cfg80211 scan.\n"); + return -EBUSY; + } + +#if CFG_MULTI_SSID_SCAN + kalMemZero(&rScanRequest, sizeof(PARAM_SCAN_REQUEST_ADV_T)); + /* check if there is any pending scan not yet finished */ + if (prGlueInfo->prScanRequest != NULL) { + DBGLOG(REQ, ERROR, "prGlueInfo->prScanRequest != NULL\n"); + return -EBUSY; + } + + old_num_ssid = num_ssid = (UINT_32)request->n_ssids; + DBGLOG(REQ, TRACE, "request->n_ssids=%d\n", request->n_ssids); + + if (request->n_ssids == 0) + rScanRequest.u4SsidNum = 0; + else if (request->n_ssids <= (SCN_SSID_MAX_NUM + 1)) { + u4ValidIdx = 0; + for (i = 0; i < request->n_ssids; i++) { + if ((request->ssids[i].ssid[0] == 0) + || (request->ssids[i].ssid_len == 0)) { + num_ssid--; /* remove if this is a wildcard scan*/ + wildcard_flag |= (1 << i); + DBGLOG(REQ, TRACE, "i=%d, num_ssid-- for wildcard scan\n", i); + continue; + } + COPY_SSID(rScanRequest.rSsid[u4ValidIdx].aucSsid, + rScanRequest.rSsid[u4ValidIdx].u4SsidLen, + request->ssids[i].ssid, request->ssids[i].ssid_len); + DBGLOG(REQ, INFO, "i=%d, u4ValidIdx=%d, aucSsid=%s, u4SsidLen=%d\n", + i, u4ValidIdx, + rScanRequest.rSsid[u4ValidIdx].aucSsid, rScanRequest.rSsid[u4ValidIdx].u4SsidLen); + + u4ValidIdx++; + if (u4ValidIdx == SCN_SSID_MAX_NUM) { + DBGLOG(REQ, INFO, "i=%d, u4ValidIdx is SCN_SSID_MAX_NUM\n", i); + break; + } + } + rScanRequest.u4SsidNum = u4ValidIdx; /* real SSID number to firmware */ + } else { + DBGLOG(REQ, ERROR, "request->n_ssids:%d\n", request->n_ssids); + return -EINVAL; + } +#else + kalMemZero(&rScanRequest, sizeof(PARAM_SCAN_REQUEST_EXT_T)); + + /* check if there is any pending scan not yet finished */ + if (prGlueInfo->prScanRequest != NULL) { + DBGLOG(REQ, ERROR, "prGlueInfo->prScanRequest != NULL\n"); + return -EBUSY; + } + + if (request->n_ssids == 0) { + rScanRequest.rSsid.u4SsidLen = 0; + } else if (request->n_ssids == 1) { + /*wildcard ssid*/ + COPY_SSID(rScanRequest.rSsid.aucSsid, rScanRequest.rSsid.u4SsidLen, request->ssids[0].ssid, + request->ssids[0].ssid_len); + } else if (request->n_ssids == 2) { + DBGLOG(REQ, INFO, "mtk_cfg80211_scan,[0]ssid:%s, [0]ssid_len:%d [1]ssid:%s, [1]ssid_len:%d" + , HIDE(request->ssids[0].ssid), request->ssids[0].ssid_len + , HIDE(request->ssids[1].ssid), request->ssids[1].ssid_len); + /*ssids[0]: specific ssid*/ + /*ssids[1]: wildcard ssid*/ + + request->n_ssids--; + COPY_SSID(rScanRequest.rSsid.aucSsid, rScanRequest.rSsid.u4SsidLen, request->ssids[0].ssid, + request->ssids[0].ssid_len); + } else { + DBGLOG(REQ, ERROR, "request to find %d SSIDs, but only support %d\n" + , request->n_ssids, GL_CFG80211_SCAN_SSID_MAX_NUM); + return -EINVAL; + } +#endif + DBGLOG(REQ, INFO, "mtk_cfg80211_scan(), n_ssids=%d, num_ssid=(%u=>%u), wildcard=0x%X\n" + , request->n_ssids, old_num_ssid, num_ssid, wildcard_flag); + + kalScanParseRandomMac(prBssInfo, request, rScanRequest.aucRandomMac); + + if (request->ie_len > 0) { + rScanRequest.u4IELength = request->ie_len; + rScanRequest.pucIE = (PUINT_8) (request->ie); + } else { + rScanRequest.u4IELength = 0; + } +#if 0 + prGlueInfo->prScanRequest = request; + rStatus = kalIoctl(prGlueInfo, + wlanoidSetBssidListScanExt, + &rScanRequest, sizeof(PARAM_SCAN_REQUEST_EXT_T), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "scan error:%x\n", rStatus); + prGlueInfo->prScanRequest = NULL; + return -EINVAL; + } + + /*prGlueInfo->prScanRequest = request;*/ +#endif + /* temp save request ieee80211_channel info */ + rScanRequest.puPartialScanReq = (PUINT_8)request; + DBGLOG(REQ, TRACE, "mtk_cfg80211_scan request=%p\n", rScanRequest.puPartialScanReq); + + prGlueInfo->prScanRequest = request; + +#if CFG_MULTI_SSID_SCAN + rStatus = kalIoctl(prGlueInfo, + wlanoidSetBssidListScanAdv, + &rScanRequest, sizeof(PARAM_SCAN_REQUEST_ADV_T), FALSE, FALSE, FALSE, FALSE, &u4BufLen); +#else + rStatus = kalIoctl(prGlueInfo, + wlanoidSetBssidListScanExt, + &rScanRequest, sizeof(PARAM_SCAN_REQUEST_EXT_T), FALSE, FALSE, FALSE, FALSE, &u4BufLen); +#endif + + if (rStatus != WLAN_STATUS_SUCCESS) { + prGlueInfo->prScanRequest = NULL; + rScanRequest.puPartialScanReq = NULL; + DBGLOG(REQ, ERROR, "scan error:%x\n", rStatus); + return -EINVAL; + } + + return 0; +} +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for abort an ongoing scan. The driver shall + * indicate the status of the scan through cfg80211_scan_done() + * + * @param wiphy - pointer of wireless hardware description + * wdev - pointer of wireless device state + * + */ +/*----------------------------------------------------------------------------*/ +void mtk_cfg80211_abort_scan(struct wiphy *wiphy, struct wireless_dev *wdev) +{ + UINT_32 u4SetInfoLen = 0; + WLAN_STATUS rStatus; + P_GLUE_INFO_T prGlueInfo = NULL; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidAbortScan, + NULL, 1, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, ERROR, "wlanoidAbortScan fail 0x%x\n", rStatus); +} + +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; +#if (CFG_REFACTORY_PMKSA == 0) +#if CFG_SUPPORT_OKC + UINT_16 u2PmkIdCnt = 0; +#endif +#endif + UINT_32 u4BufLen; + ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus; + ENUM_PARAM_AUTH_MODE_T eAuthMode; + UINT_32 cipher, u4AkmSuite = 0; + PARAM_CONNECT_T rNewSsid; + ENUM_PARAM_OP_MODE_T eOpMode; + P_CONNECTION_SETTINGS_T prConnSettings = NULL; + struct wireless_dev *wdev = NULL; + P_DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY prEntry; + P_IEEE_802_11_MIB_T prMib; + int i; + + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + if (ndev == NULL) { + DBGLOG(REQ, ERROR, "ndev is NULL\n"); + return -EINVAL; + } + wdev = ndev->ieee80211_ptr; + + /* Supplicant requests connecting during driver do disconnecting, + * it will cause to install key fail, error is -67(link has been + * servered). + * Beacaus driver disconnected is done, but cfg80211 is disconnecting. + * Reject this request.Supplicant will issue the connecting request again. + */ + if (wdev->current_bss && + kalGetMediaStateIndicated(prGlueInfo) == PARAM_MEDIA_STATE_DISCONNECTED) { + DBGLOG(REQ, WARN, "Reject this connecting request\n"); + return -EALREADY; + } + + DBGLOG(REQ, INFO, "[wlan] mtk_cfg80211_connect %p %zu\n", sme->ie, sme->ie_len); + prConnSettings = &prGlueInfo->prAdapter->rWifiVar.rConnSettings; + + if (prGlueInfo->prAdapter->rWifiVar.rConnSettings.eOPMode > NET_TYPE_AUTO_SWITCH) + eOpMode = NET_TYPE_AUTO_SWITCH; + else + eOpMode = prGlueInfo->prAdapter->rWifiVar.rConnSettings.eOPMode; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetInfrastructureMode, + &eOpMode, sizeof(eOpMode), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "wlanoidSetInfrastructureMode fail 0x%x\n", rStatus); + return -EFAULT; + } + + /* after set operation mode, key table are cleared */ + + /* reset wpa info */ + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + prGlueInfo->rWpaInfo.u4KeyMgmt = 0; + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; +#if CFG_SUPPORT_802_11W + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; + prGlueInfo->rWpaInfo.ucRSNMfpCap = RSN_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; +#if CFG_SUPPORT_802_11R + case NL80211_AUTHTYPE_FT: + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_FT; + break; +#endif + case NL80211_AUTHTYPE_SAE: + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_SAE; + break; + default: + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM | IW_AUTH_ALG_SHARED_KEY; + break; + } + + if (sme->crypto.n_ciphers_pairwise) { + DBGLOG(RSN, INFO, "cipher pairwise (%x)\n", sme->crypto.ciphers_pairwise[0]); + 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) { + DBGLOG(RSN, INFO, "cipher group (%x)\n", 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; + case WLAN_CIPHER_SUITE_NO_GROUP_ADDR: + 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; + u4AkmSuite = WPA_AKM_SUITE_802_1X; + break; + case WLAN_AKM_SUITE_PSK: + eAuthMode = AUTH_MODE_WPA_PSK; + u4AkmSuite = WPA_AKM_SUITE_PSK; + break; + default: + DBGLOG(REQ, WARN, "invalid auth mode (%d)\n", sme->crypto.akm_suites[0]); + 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; + u4AkmSuite = RSN_AKM_SUITE_802_1X; + break; + case WLAN_AKM_SUITE_PSK: + eAuthMode = AUTH_MODE_WPA2_PSK; + u4AkmSuite = RSN_AKM_SUITE_PSK; + break; +#if CFG_SUPPORT_802_11W + case WLAN_AKM_SUITE_8021X_SHA256: + eAuthMode = AUTH_MODE_WPA2; + u4AkmSuite = RSN_AKM_SUITE_802_1X_SHA256; + break; + case WLAN_AKM_SUITE_PSK_SHA256: + eAuthMode = AUTH_MODE_WPA2_PSK; + u4AkmSuite = RSN_AKM_SUITE_PSK_SHA256; + break; +#endif +#if CFG_SUPPORT_HOTSPOT_2_0 + case WLAN_AKM_SUITE_OSEN: + eAuthMode = AUTH_MODE_WPA_OSEN; + u4AkmSuite = WFA_AKM_SUITE_OSEN; + break; +#endif +#if CFG_SUPPORT_802_11R + case WLAN_AKM_SUITE_FT_8021X: + eAuthMode = AUTH_MODE_WPA2_FT; + u4AkmSuite = RSN_AKM_SUITE_FT_802_1X; + break; + case WLAN_AKM_SUITE_FT_PSK: + eAuthMode = AUTH_MODE_WPA2_FT_PSK; + u4AkmSuite = RSN_AKM_SUITE_FT_PSK; + break; +#endif + case WLAN_AKM_SUITE_SAE: + if (sme->auth_type == NL80211_AUTHTYPE_SAE) + eAuthMode = AUTH_MODE_WPA3_SAE; + else + eAuthMode = AUTH_MODE_OPEN; + u4AkmSuite = RSN_CIPHER_SUITE_SAE; + break; + + case WLAN_AKM_SUITE_OWE: + eAuthMode = AUTH_MODE_WPA3_OWE; + u4AkmSuite = RSN_CIPHER_SUITE_OWE; + break; + default: + DBGLOG(REQ, WARN, "invalid auth mode (%d)\n", sme->crypto.akm_suites[0]); + return -EINVAL; + } +#if CFG_SUPPORT_HOTSPOT_2_0 + } else if (prGlueInfo->rWpaInfo.u4WpaVersion + == IW_AUTH_WPA_VERSION_DISABLED && + sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_OSEN) { + eAuthMode = AUTH_MODE_WPA_OSEN; + u4AkmSuite = WFA_AKM_SUITE_OSEN; +#endif + } + } + + if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_DISABLED && eAuthMode != AUTH_MODE_WPA_OSEN) { + switch (prGlueInfo->rWpaInfo.u4AuthAlg) { + case IW_AUTH_ALG_OPEN_SYSTEM: + eAuthMode = AUTH_MODE_OPEN; + break; +#if CFG_SUPPORT_802_11R + case IW_AUTH_ALG_FT: + eAuthMode = AUTH_MODE_NON_RSN_FT; + break; +#endif + default: + eAuthMode = AUTH_MODE_AUTO_SWITCH; + break; + } + } + + prGlueInfo->rWpaInfo.fgPrivacyInvoke = sme->privacy; + + prGlueInfo->fgWpsActive = FALSE; +#if CFG_SUPPORT_HOTSPOT_2_0 + prGlueInfo->fgConnectHS20AP = FALSE; +#endif +#if (CFG_REFACTORY_PMKSA == 0) + prConnSettings->fgOkcEnabled = FALSE; + prConnSettings->fgOkcPmksaReady = FALSE; +#endif + if (sme->ie && sme->ie_len > 0) { + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + PUINT_8 prDesiredIE = NULL; + PUINT_8 pucIEStart = (PUINT_8)sme->ie; + +#if CFG_SUPPORT_WPS2 + prDesiredIE = (PUINT_8) kalFindIeMatchMask(ELEM_ID_VENDOR, + pucIEStart, sme->ie_len, NULL, 0, 0, NULL); + /* If it's vendor IE, check if it's WPS IE. */ + if (prDesiredIE && prDesiredIE[1] >= 4) { + if (memcmp(&prDesiredIE[2], "\x00\x50\xf2\x04", 4) == 0) + prGlueInfo->fgWpsActive = TRUE; + } +#endif +#if CFG_SUPPORT_WAPI + if (wextSrchDesiredWAPIIE(pucIEStart, sme->ie_len, (PUINT_8 *) &prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetWapiAssocInfo, + prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(SEC, WARN, "[wapi] set wapi assoc info error:%x\n", rStatus); + } +#endif + + DBGLOG(REQ, TRACE, "[wlan] wlanoidSetWapiAssocInfo: .fgWapiMode = %d\n", + prGlueInfo->prAdapter->rWifiVar.rConnSettings.fgWapiMode); + +#if CFG_SUPPORT_HOTSPOT_2_0 + if (wextSrchDesiredHS20IE(pucIEStart, sme->ie_len, (PUINT_8 *) &prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetHS20Info, + prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + /* Do nothing */ + /* printk(KERN_INFO "[HS20] set HS20 assoc info error:%lx\n", rStatus); */ + } + } else if (wextSrchDesiredOsenIE(pucIEStart, sme->ie_len, (PUINT_8 *) &prDesiredIE)) { + /* we can reuse aucHS20AssocInfoIE because hs20 indication IE is not present when OSEN exist */ + kalMemCopy(prGlueInfo->aucHS20AssocInfoIE, prDesiredIE, IE_SIZE(prDesiredIE)); + prGlueInfo->u2HS20AssocInfoIELen = (UINT_16)IE_SIZE(prDesiredIE); + } +#endif + if (wextSrchDesiredWPAIE(pucIEStart, sme->ie_len, 0x30, + (uint8_t **) &prDesiredIE)) { + RSN_INFO_T rRsnInfo; + + if (rsnParseRsnIE(prGlueInfo->prAdapter, + (P_RSN_INFO_ELEM_T)prDesiredIE, &rRsnInfo)) { +#if CFG_SUPPORT_802_11W + if (rRsnInfo.u2RsnCap & ELEM_WPA_CAP_MFPC) { + prGlueInfo->rWpaInfo.ucRSNMfpCap = RSN_AUTH_MFP_OPTIONAL; + if (rRsnInfo.u2RsnCap & ELEM_WPA_CAP_MFPR) + prGlueInfo->rWpaInfo.ucRSNMfpCap = RSN_AUTH_MFP_REQUIRED; + } else + prGlueInfo->rWpaInfo.ucRSNMfpCap = RSN_AUTH_MFP_DISABLED; +#endif + } + } +#if (CFG_REFACTORY_PMKSA == 0) +#if CFG_SUPPORT_OKC + wextSrchOkcAndPMKID(pucIEStart, sme->ie_len, (PUINT_8 *)&prDesiredIE, &prConnSettings->fgOkcEnabled); + + if (prDesiredIE) + u2PmkIdCnt = *(PUINT_16)prDesiredIE; + DBGLOG(REQ, INFO, "u2PmkIdCnt %d\n", u2PmkIdCnt); + + if (u2PmkIdCnt != 0 && sme->bssid && !EQUAL_MAC_ADDR("\x0\x0\x0\x0\x0\x0", sme->bssid) && + IS_UCAST_MAC_ADDR(sme->bssid)) { + PARAM_PMKID_T rPmkid; + + rPmkid.u4Length = (UINT_32)(sizeof(rPmkid) | (1 << 31)); + rPmkid.u4BSSIDInfoCount = 1; + kalMemCopy(rPmkid.arBSSIDInfo[0].arBSSID, sme->bssid, MAC_ADDR_LEN); + kalMemCopy(rPmkid.arBSSIDInfo[0].arPMKID, prDesiredIE+2, IW_PMKID_LEN); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetPmkid, + (PVOID)&rPmkid, rPmkid.u4Length, FALSE, FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "failed to add OKC PMKID\n"); + } +#endif +#endif + } + + /* Fill WPA info - mfp setting */ + /* Must put after paring RSNE from upper layer + * for prWpaInfo->ucRSNMfpCap assignment + */ +#if CFG_SUPPORT_802_11W + switch (sme->mfp) { + case NL80211_MFP_NO: + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; + /* Change Mfp parameter from DISABLED to OPTIONAL + * if upper layer set MFPC = 1 in RSNE + * since upper layer can't bring MFP OPTIONAL information + * to driver by sme->mfp + */ + if (prGlueInfo->rWpaInfo.ucRSNMfpCap == RSN_AUTH_MFP_OPTIONAL) + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_OPTIONAL; + else if (prGlueInfo->rWpaInfo.ucRSNMfpCap == + RSN_AUTH_MFP_REQUIRED) + DBGLOG(REQ, WARN, + "mfp parameter(DISABLED) conflict with mfp cap(REQUIRED)\n"); + break; + case NL80211_MFP_REQUIRED: + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_REQUIRED; + break; + default: + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; + break; + } + DBGLOG(REQ, INFO, "MFP=%d\n", prGlueInfo->rWpaInfo.u4Mfp); +#endif + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAuthMode, &eAuthMode, sizeof(eAuthMode), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "set auth mode error:%x\n", rStatus); + + prMib = &prGlueInfo->prAdapter->rMib; + /* Enable the specific AKM suite only. */ + for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) { + prEntry = &prMib-> + dot11RSNAConfigAuthenticationSuitesTable[i]; + if (prEntry->dot11RSNAConfigAuthenticationSuite == + u4AkmSuite) + prEntry->dot11RSNAConfigAuthenticationSuiteEnabled = + TRUE; + else + prEntry->dot11RSNAConfigAuthenticationSuiteEnabled = + FALSE; + } + + cipher = prGlueInfo->rWpaInfo.u4CipherGroup | prGlueInfo->rWpaInfo.u4CipherPairwise; + + if (prGlueInfo->rWpaInfo.fgPrivacyInvoke) { + if (cipher & IW_AUTH_CIPHER_CCMP) { + eEncStatus = ENUM_ENCRYPTION3_ENABLED; + } else if (cipher & IW_AUTH_CIPHER_TKIP) { + eEncStatus = ENUM_ENCRYPTION2_ENABLED; + } else if (cipher & (IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40)) { + eEncStatus = ENUM_ENCRYPTION1_ENABLED; + } else if (cipher & IW_AUTH_CIPHER_NONE) { + if (prGlueInfo->rWpaInfo.fgPrivacyInvoke) + eEncStatus = ENUM_ENCRYPTION1_ENABLED; + else + eEncStatus = ENUM_ENCRYPTION_DISABLED; + } else { + eEncStatus = ENUM_ENCRYPTION_DISABLED; + } + } else { + eEncStatus = ENUM_ENCRYPTION_DISABLED; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEncryptionStatus, + &eEncStatus, sizeof(eEncStatus), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "set encryption mode error:%x\n", rStatus); + + if (sme->key_len != 0 && prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_DISABLED) { + P_PARAM_WEP_T prWepKey = (P_PARAM_WEP_T) wepBuf; + + prWepKey->u4Length = 12 + sme->key_len; + prWepKey->u4KeyLength = (UINT_32) sme->key_len; + prWepKey->u4KeyIndex = (UINT_32) sme->key_idx; + prWepKey->u4KeyIndex |= BIT(31); + if (prWepKey->u4KeyLength > 32) { + DBGLOG(REQ, ERROR, "Too long key length (%u)\n", prWepKey->u4KeyLength); + return -EINVAL; + } + kalMemCopy(prWepKey->aucKeyMaterial, sme->key, prWepKey->u4KeyLength); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAddWep, + prWepKey, prWepKey->u4Length, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "wlanoidSetAddWep fail 0x%x\n", rStatus); + return -EFAULT; + } + } + + if (sme->channel) + rNewSsid.u4CenterFreq = sme->channel->center_freq; + else + rNewSsid.u4CenterFreq = 0; + rNewSsid.pucBssid = (UINT_8 *)sme->bssid; + rNewSsid.pucSsid = (UINT_8 *)sme->ssid; + rNewSsid.u4SsidLen = sme->ssid_len; + /* Check former assocIE to prevent memory leakage in situations like + * upper layer requests connection without disconnecting first, ... + */ + if (prConnSettings->assocIeLen > 0) { + kalMemFree(prConnSettings->pucAssocIEs, VIR_MEM_TYPE, + prConnSettings->assocIeLen); + prConnSettings->assocIeLen = 0; + } + + if (sme->ie_len > 0) { + prConnSettings->pucAssocIEs = + kalMemAlloc(sme->ie_len, VIR_MEM_TYPE); + if (prConnSettings->pucAssocIEs) { + prConnSettings->assocIeLen = sme->ie_len; + kalMemCopy(prConnSettings->pucAssocIEs, + sme->ie, prConnSettings->assocIeLen); + } else { + DBGLOG(INIT, INFO, + "allocate memory for prConnSettings->pucAssocIEs failed!\n"); + return -ENOMEM; + } + } + rStatus = kalIoctl(prGlueInfo, + wlanoidSetConnect, + (PVOID)(&rNewSsid), sizeof(PARAM_CONNECT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "set SSID:%x\n", rStatus); + return -EINVAL; + } + + return 0; +} + +#if CFG_SUPPORT_WPA3 +int mtk_cfg80211_external_auth(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_external_auth_params *params) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_FAILURE; + uint32_t u4BufLen; + struct PARAM_EXTERNAL_AUTH auth; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + if (!prGlueInfo) + DBGLOG(REQ, WARN, + "SAE-confirm failed with invalid prGlueInfo\n"); + + COPY_MAC_ADDR(auth.bssid, params->bssid); + auth.status = params->status; + auth.ucBssIdx = (uint8_t)NETWORK_TYPE_AIS_INDEX; + rStatus = kalIoctl(prGlueInfo, wlanoidExternalAuthDone, (void *)&auth, + sizeof(auth), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(OID, INFO, "SAE-confirm failed with: %d\n", rStatus); + + return 0; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @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; + + DBGLOG(REQ, INFO, "--> %s()\n", __func__); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, NULL, 0, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "disassociate error:%x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to join an IBSS group + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_ibss_params *params) +{ + PARAM_SSID_T rNewSsid; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4ChnlFreq; /* Store channel or frequency information */ + UINT_32 u4BufLen = 0; + WLAN_STATUS rStatus; + struct ieee80211_channel *channel = NULL; + + DBGLOG(REQ, INFO, "--> %s()\n", __func__); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + /* set channel */ + if (params->chandef.chan) + channel = params->chandef.chan; + if (channel) { + u4ChnlFreq = nicChannelNum2Freq(channel->hw_value); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetFrequency, + &u4ChnlFreq, sizeof(u4ChnlFreq), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + /* set SSID */ + kalMemCopy(rNewSsid.aucSsid, params->ssid, params->ssid_len); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetSsid, + (PVOID)(&rNewSsid), sizeof(PARAM_SSID_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set SSID:%x\n", rStatus); + return -EFAULT; + } + + return 0; + + return -EINVAL; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to leave from IBSS group + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + + DBGLOG(REQ, INFO, "--> %s()\n", __func__); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, NULL, 0, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "disassociate error:%x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to configure + * WLAN power managemenet + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, bool enabled, int timeout) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + PARAM_POWER_MODE ePowerMode; + + DBGLOG(REQ, TRACE, "--> %s()\n", __func__); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if CFG_SUPPORT_DBG_POWERMODE + if (prGlueInfo->prAdapter->fgEnDbgPowerMode) { + DBGLOG(REQ, WARN, "Force power mode enabled, ignore this enable command: %d\n", enabled); + return 0; + } +#endif + if (enabled) { + if (timeout == -1) + ePowerMode = Param_PowerModeFast_PSP; + else + ePowerMode = Param_PowerModeMAX_PSP; + } else { + ePowerMode = Param_PowerModeCAM; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &ePowerMode, sizeof(ePowerMode), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set_power_mgmt error:%x\n", rStatus); + return -EFAULT; + } + + return 0; +} +#if (CFG_REFACTORY_PMKSA == 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; + + DBGLOG(REQ, INFO, "--> %s()\n", __func__); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + prPmkid = (P_PARAM_PMKID_T) kalMemAlloc(8 + sizeof(PARAM_BSSID_INFO_T), VIR_MEM_TYPE); + if (!prPmkid) { + DBGLOG(REQ, ERROR, "Can not alloc memory for IW_PMKSA_ADD\n"); + return -ENOMEM; + } + + prPmkid->u4Length = 8 + sizeof(PARAM_BSSID_INFO_T); + prPmkid->u4BSSIDInfoCount = 1; + kalMemCopy(prPmkid->arBSSIDInfo->arBSSID, pmksa->bssid, 6); + kalMemCopy(prPmkid->arBSSIDInfo->arPMKID, pmksa->pmkid, IW_PMKID_LEN); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetPmkid, prPmkid, sizeof(PARAM_PMKID_T), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "add pmkid error:%x\n", rStatus); + kalMemFree(prPmkid, VIR_MEM_TYPE, 8 + sizeof(PARAM_BSSID_INFO_T)); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to remove + * a cached PMKID for a BSSID + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_pmksa *pmksa) +{ + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to flush + * all cached PMKID + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + P_PARAM_PMKID_T prPmkid; + + DBGLOG(REQ, INFO, "--> %s()\n", __func__); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + prPmkid = (P_PARAM_PMKID_T) kalMemAlloc(8, VIR_MEM_TYPE); + if (!prPmkid) { + DBGLOG(REQ, ERROR, "Can not alloc memory for IW_PMKSA_FLUSH\n"); + return -ENOMEM; + } + + prPmkid->u4Length = 8; + prPmkid->u4BSSIDInfoCount = 0; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetPmkid, prPmkid, sizeof(PARAM_PMKID_T), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "flush pmkid error:%x\n", rStatus); + kalMemFree(prPmkid, VIR_MEM_TYPE, 8); + + return 0; +} +#else +/*----------------------------------------------------------------------------*/ +/*! + * @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; + PARAM_PMKID_T pmkid; + UINT_8 ucBssIndex = 0; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, TRACE, "mtk_cfg80211_set_pmksa " MACSTR " pmk\n", + MAC2STR(pmksa->bssid)); + + COPY_MAC_ADDR(pmkid.arBSSID, pmksa->bssid); + kalMemCopy(pmkid.arPMKID, pmksa->pmkid, IW_PMKID_LEN); + pmkid.ucBssIdx = ucBssIndex; + rStatus = kalIoctl(prGlueInfo, wlanoidSetPmkid, &pmkid, + sizeof(PARAM_PMKID_T), + FALSE, FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "add pmkid error:%x\n", rStatus); + + 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) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + PARAM_PMKID_T pmkid; + UINT_8 ucBssIndex = 0; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, TRACE, "mtk_cfg80211_del_pmksa " MACSTR "\n", + MAC2STR(pmksa->bssid)); + + COPY_MAC_ADDR(pmkid.arBSSID, pmksa->bssid); + kalMemCopy(pmkid.arPMKID, pmksa->pmkid, IW_PMKID_LEN); + pmkid.ucBssIdx = ucBssIndex; + rStatus = kalIoctl(prGlueInfo, wlanoidDelPmkid, &pmkid, + sizeof(PARAM_PMKID_T), + FALSE, FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "add pmkid error:%x\n", rStatus); + + 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; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, wlanoidFlushPmkid, NULL, 0, + FALSE, FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "flush pmkid error:%x\n", rStatus); + + return 0; +} +#endif + +void mtk_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, + IN struct wireless_dev *wdev, + IN u16 frame_type, IN bool reg) +{ +#if 0 + P_MSG_P2P_MGMT_FRAME_REGISTER_T prMgmtFrameRegister = (P_MSG_P2P_MGMT_FRAME_REGISTER_T) NULL; +#endif + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + + do { + + DBGLOG(REQ, LOUD, "mtk_cfg80211_mgmt_frame_register\n"); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + switch (frame_type) { + case MAC_FRAME_PROBE_REQ: + if (reg) { + prGlueInfo->u4OsMgmtFrameFilter |= PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(REQ, LOUD, "Open packet filer probe request\n"); + } else { + prGlueInfo->u4OsMgmtFrameFilter &= ~PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(REQ, LOUD, "Close packet filer probe request\n"); + } + break; + case MAC_FRAME_ACTION: + if (reg) { + prGlueInfo->u4OsMgmtFrameFilter |= PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(REQ, LOUD, "Open packet filer action frame.\n"); + } else { + prGlueInfo->u4OsMgmtFrameFilter &= ~PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(REQ, LOUD, "Close packet filer action frame.\n"); + } + break; + default: + DBGLOG(REQ, TRACE, "Ask frog to add code for mgmt:%x\n", frame_type); + break; + } + + if (prGlueInfo->prAdapter != NULL) { + /* prGlueInfo->ulFlag |= GLUE_FLAG_FRAME_FILTER_AIS; */ + set_bit(GLUE_FLAG_FRAME_FILTER_AIS_BIT, &prGlueInfo->ulFlag); + + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + + if (in_interrupt()) + DBGLOG(REQ, TRACE, "It is in interrupt level\n"); + } +#if 0 + + prMgmtFrameRegister = (P_MSG_P2P_MGMT_FRAME_REGISTER_T) cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + sizeof + (MSG_P2P_MGMT_FRAME_REGISTER_T)); + + if (prMgmtFrameRegister == NULL) { + ASSERT(FALSE); + break; + } + + prMgmtFrameRegister->rMsgHdr.eMsgId = MID_MNY_P2P_MGMT_FRAME_REGISTER; + + prMgmtFrameRegister->u2FrameType = frame_type; + prMgmtFrameRegister->fgIsRegister = reg; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMgmtFrameRegister, MSG_SEND_METHOD_BUF); + +#endif + + } while (FALSE); + +} /* mtk_cfg80211_mgmt_frame_register */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to stay on a + * specified channel + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, + unsigned int duration, u64 *cookie) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_REMAIN_ON_CHANNEL_T prMsgChnlReq = (P_MSG_REMAIN_ON_CHANNEL_T) NULL; + + do { + if ((wiphy == NULL) || (wdev == NULL) || (chan == NULL) || (cookie == NULL)) + break; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if 1 + DBGLOG(REQ, INFO, "--> %s()\n", __func__); +#endif + + *cookie = prGlueInfo->u8Cookie++; + + prMsgChnlReq = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_REMAIN_ON_CHANNEL_T)); + + if (prMsgChnlReq == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + kalMemZero(prMsgChnlReq, sizeof(MSG_REMAIN_ON_CHANNEL_T)); + + prMsgChnlReq->rMsgHdr.eMsgId = MID_MNY_AIS_REMAIN_ON_CHANNEL; + prMsgChnlReq->u8Cookie = *cookie; + prMsgChnlReq->u4DurationMs = duration; + + prMsgChnlReq->ucChannelNum = nicFreq2ChannelNum(chan->center_freq * 1000); + + switch (chan->band) { + case IEEE80211_BAND_2GHZ: + prMsgChnlReq->eBand = BAND_2G4; + break; + case IEEE80211_BAND_5GHZ: + prMsgChnlReq->eBand = BAND_5G; + break; + default: + prMsgChnlReq->eBand = BAND_2G4; + break; + } + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChnlReq, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to cancel staying + * on a specified channel + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_CANCEL_REMAIN_ON_CHANNEL_T prMsgChnlAbort = (P_MSG_CANCEL_REMAIN_ON_CHANNEL_T) NULL; + + do { + if ((wiphy == NULL) || (wdev == NULL)) + break; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if 1 + DBGLOG(REQ, INFO, "--> %s()\n", __func__); +#endif + + prMsgChnlAbort = + cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_CANCEL_REMAIN_ON_CHANNEL_T)); + + if (prMsgChnlAbort == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgChnlAbort->rMsgHdr.eMsgId = MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL; + prMsgChnlAbort->u8Cookie = cookie; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChnlAbort, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to send a management frame + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_MGMT_TX_REQUEST_T prMsgTxReq = (P_MSG_MGMT_TX_REQUEST_T) NULL; + P_MSDU_INFO_T prMgmtFrame = (P_MSDU_INFO_T) NULL; + PUINT_8 pucFrameBuf = (PUINT_8) NULL; + + do { +#if 1 + DBGLOG(REQ, INFO, "--> %s()\n", __func__); +#endif + + if ((wiphy == NULL) || (wdev == NULL) || (params == 0) || (cookie == NULL)) + break; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + *cookie = prGlueInfo->u8Cookie++; + + /* Channel & Channel Type & Wait time are ignored. */ + prMsgTxReq = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_MGMT_TX_REQUEST_T)); + + if (prMsgTxReq == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgTxReq->fgNoneCckRate = FALSE; + prMsgTxReq->fgIsWaitRsp = TRUE; + + prMgmtFrame = cnmMgtPktAlloc(prGlueInfo->prAdapter, (UINT_32) (params->len + MAC_TX_RESERVED_FIELD)); + prMsgTxReq->prMgmtMsduInfo = prMgmtFrame; + if (prMsgTxReq->prMgmtMsduInfo == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgTxReq->u8Cookie = *cookie; + prMsgTxReq->rMsgHdr.eMsgId = MID_MNY_AIS_MGMT_TX; + + pucFrameBuf = (PUINT_8) ((ULONG) prMgmtFrame->prPacket + MAC_TX_RESERVED_FIELD); + + kalMemCopy(pucFrameBuf, params->buf, params->len); + + prMgmtFrame->u2FrameLength = params->len; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgTxReq, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + if ((i4Rslt != 0) && (prMsgTxReq != NULL)) { + if (prMsgTxReq->prMgmtMsduInfo != NULL) + cnmMgtPktFree(prGlueInfo->prAdapter, prMsgTxReq->prMgmtMsduInfo); + + cnmMemFree(prGlueInfo->prAdapter, prMsgTxReq); + } + + return i4Rslt; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to cancel the wait time + * from transmitting a management frame on another channel + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, TRACE, "--> %s()\n", __func__); + + /* not implemented */ + + return -EINVAL; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for handling sched_scan start/stop request + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ + +int +mtk_cfg80211_sched_scan_start(IN struct wiphy *wiphy, + IN struct net_device *ndev, IN struct cfg80211_sched_scan_request *request) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_BSS_INFO_T prBssInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 i, u4BufLen; + P_PARAM_SCHED_SCAN_REQUEST prSchedScanRequest; +#if CFG_SUPPORT_SCHED_SCN_SSID_SETS + UINT_32 num = 0; +#endif + + DBGLOG(REQ, INFO, "--> %s() n_ssid:%d , match_set:%d\n", __func__, request->n_ssids, request->n_match_sets); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + prBssInfo = &(prGlueInfo->prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + if ((!prGlueInfo->prAdapter->fgEnCfg80211Scan) && + (kalGetMediaStateIndicated(prGlueInfo) == + PARAM_MEDIA_STATE_CONNECTED)) { + DBGLOG(SCN, WARN, "Disable cfg80211 sched scan.\n"); + return -EBUSY; + } + + /* check if there is any pending scan/sched_scan not yet finished */ + if (prGlueInfo->prScanRequest != NULL || prGlueInfo->prSchedScanRequest != NULL) { + DBGLOG(SCN, ERROR, "(prGlueInfo->prScanRequest != NULL || prGlueInfo->prSchedScanRequest != NULL)\n"); + return -EBUSY; + } else if (request == NULL || request->n_match_sets > CFG_SCAN_SSID_MATCH_MAX_NUM) { + DBGLOG(SCN, ERROR, "(request == NULL || request->n_match_sets > CFG_SCAN_SSID_MATCH_MAX_NUM)\n"); + /* invalid scheduled scan request */ + return -EINVAL; + } else if (/* !request->n_ssids || */!request->n_match_sets) { + /* invalid scheduled scan request */ + return -EINVAL; + } +#if CFG_SUPPORT_SCHED_SCN_SSID_SETS + else if (!request->n_ssids || request->n_ssids > CFG_SCAN_HIDDEN_SSID_MAX_NUM) { + /* invalid scheduled scan request */ + return -EINVAL; + } +#endif + + prSchedScanRequest = (P_PARAM_SCHED_SCAN_REQUEST) kalMemAlloc(sizeof(PARAM_SCHED_SCAN_REQUEST), VIR_MEM_TYPE); + if (prSchedScanRequest == NULL) { + DBGLOG(SCN, ERROR, "(prSchedScanRequest == NULL) kalMemAlloc fail\n"); + return -ENOMEM; + } + + kalMemZero(prSchedScanRequest, sizeof(PARAM_SCHED_SCAN_REQUEST)); + +#if CFG_SUPPORT_SCHED_SCN_SSID_SETS + /*passed in the probe_reqs in active scans*/ + for (i = 0; i < request->n_ssids; i++) { + if (request->ssids && (&(request->ssids[i]))) { + DBGLOG(SCN, TRACE, "ssids : (%d)[%s]\n", i, HIDE(request->ssids[i].ssid)); + /*driver ingored the null ssid*/ + if (request->ssids[i].ssid_len == 0) + DBGLOG(SCN, WARN, "ignore the null ssid, index:%d\n", i); + else { + COPY_SSID(prSchedScanRequest->arSsid[num].aucSsid, + prSchedScanRequest->arSsid[num].u4SsidLen, + request->ssids[i].ssid, request->ssids[i].ssid_len); + num++; + } + } + } + prSchedScanRequest->u4SsidNum = num; + num = 0; + + + if (kalSchedScanParseRandomMac(prBssInfo, request, + prSchedScanRequest->aucRandomMac, prSchedScanRequest->aucRandomMacMask)) { + prSchedScanRequest->ucScnFuncMask |= ENUM_SCN_RANDOM_MAC_EN; + } + + + for (i = 0; i < request->n_match_sets; i++) { + if (request->match_sets && (&(request->match_sets[i]))) { + DBGLOG(SCN, TRACE, "match : (%d)[%s]\n", i, + HIDE(request->match_sets[i].ssid.ssid)); + /*driver ingored the null ssid*/ + if (request->match_sets[i].ssid.ssid_len == 0) + DBGLOG(SCN, WARN, "ignore the null ssid, index:%d\n", i); + else { + COPY_SSID(prSchedScanRequest->arMatchSsid[num].aucSsid, + prSchedScanRequest->arMatchSsid[num].u4SsidLen, + request->match_sets[i].ssid.ssid, request->match_sets[i].ssid.ssid_len); + num++; + } + } + } + prSchedScanRequest->u4MatchSsidNum = num; +#else + prSchedScanRequest->u4SsidNum = request->n_match_sets; + for (i = 0; i < request->n_match_sets; i++) { + if (request->match_sets == NULL || &(request->match_sets[i]) == NULL) { + prSchedScanRequest->arSsid[i].u4SsidLen = 0; + } else { + COPY_SSID(prSchedScanRequest->arSsid[i].aucSsid, + prSchedScanRequest->arSsid[i].u4SsidLen, + request->match_sets[i].ssid.ssid, request->match_sets[i].ssid.ssid_len); + } + } +#endif + prSchedScanRequest->u4IELength = request->ie_len; + if (request->ie_len > 0) + prSchedScanRequest->pucIE = (PUINT_8) (request->ie); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + prSchedScanRequest->u2ScanInterval = (UINT_16) (request->scan_plans[0].interval); +#else + prSchedScanRequest->u2ScanInterval = (UINT_16) (request->interval); +#endif + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetStartSchedScan, + prSchedScanRequest, sizeof(PARAM_SCHED_SCAN_REQUEST), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + kalMemFree(prSchedScanRequest, VIR_MEM_TYPE, sizeof(PARAM_SCHED_SCAN_REQUEST)); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(SCN, ERROR, "scheduled scan error:%x\n", rStatus); + return -EINVAL; + } + + prGlueInfo->prSchedScanRequest = request; + + return 0; +} + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_sched_scan_stop(IN struct wiphy *wiphy, + IN struct net_device *ndev, + IN u64 reqid) +#else +int mtk_cfg80211_sched_scan_stop(IN struct wiphy *wiphy, IN struct net_device *ndev) +#endif +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + + DBGLOG(REQ, INFO, "--> %s()\n", __func__); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + /* check if there is any pending scan/sched_scan not yet finished */ + if (prGlueInfo->prSchedScanRequest == NULL) { + DBGLOG(SCN, ERROR, "prGlueInfo->prSchedScanRequest == NULL\n"); + return -EBUSY; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidSetStopSchedScan, NULL, 0, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(SCN, ERROR, "scheduled scan error, rStatus: %d\n", rStatus); + return -EINVAL; + } + + /* 1. reset first for newly incoming request */ + /* GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); */ + if (prGlueInfo->prSchedScanRequest != NULL) + prGlueInfo->prSchedScanRequest = NULL; + /* GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); */ + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for handling association request + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_assoc(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_assoc_request *req) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MAC_ADDRESS arBssid; +#if CFG_SUPPORT_HOTSPOT_2_0 + PUINT_8 prDesiredIE = NULL; +#endif + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + + DBGLOG(REQ, INFO, "--> %s()\n", __func__); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + kalMemZero(arBssid, MAC_ADDR_LEN); + wlanQueryInformation(prGlueInfo->prAdapter, wlanoidQueryBssid, &arBssid[0], sizeof(arBssid), &u4BufLen); + + /* 1. check BSSID */ + if (UNEQUAL_MAC_ADDR(arBssid, req->bss->bssid)) { + /* wrong MAC address */ + DBGLOG(REQ, WARN, "incorrect BSSID: [ %pM ] currently connected BSSID[ %pM ]\n", + req->bss->bssid, arBssid); + return -ENOENT; + } + + if (req->ie && req->ie_len > 0) { +#if CFG_SUPPORT_HOTSPOT_2_0 + if (wextSrchDesiredHS20IE((PUINT_8) req->ie, req->ie_len, (PUINT_8 *) &prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetHS20Info, + prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + /* Do nothing */ + /* printk(KERN_INFO "[HS20] set HS20 assoc info error:%lx\n", rStatus); */ + } + } +#endif + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetBssid, + (PVOID) req->bss->bssid, MAC_ADDR_LEN, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set BSSID:%x\n", rStatus); + return -EINVAL; + } + + return 0; +} + +#if CONFIG_NL80211_TESTMODE +/* + * #define NLA_PUT(skb, attrtype, attrlen, data) \ + * do { \ + * if (unlikely(nla_put(skb, attrtype, attrlen, data) < 0)) \ + * goto nla_put_failure; \ + * } while (0) + * + * #define NLA_PUT_TYPE(skb, type, attrtype, value) \ + * do { \ + * type __tmp = value; \ + * NLA_PUT(skb, attrtype, sizeof(type), &__tmp); \ + * } while (0) + * + * #define NLA_PUT_U8(skb, attrtype, value) \ + * NLA_PUT_TYPE(skb, u8, attrtype, value) + * + * #define NLA_PUT_U16(skb, attrtype, value) \ + * NLA_PUT_TYPE(skb, u16, attrtype, value) + * + * #define NLA_PUT_U32(skb, attrtype, value) \ + * NLA_PUT_TYPE(skb, u32, attrtype, value) + * + * #define NLA_PUT_U64(skb, attrtype, value) \ + * NLA_PUT_TYPE(skb, u64, attrtype, value) + */ +#if CFG_SUPPORT_WAPI +int mtk_cfg80211_testmode_set_key_ext(IN struct wiphy *wiphy, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_SET_KEY_EXTS prParams = (P_NL80211_DRIVER_SET_KEY_EXTS) NULL; + struct iw_encode_exts *prIWEncExt = (struct iw_encode_exts *)NULL; + WLAN_STATUS rstatus = WLAN_STATUS_SUCCESS; + int fgIsValid = 0; + UINT_32 u4BufLen = 0; + + P_PARAM_WPI_KEY_T prWpiKey = (P_PARAM_WPI_KEY_T) keyStructBuf; + + memset(keyStructBuf, 0, sizeof(keyStructBuf)); + + ASSERT(wiphy); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + DBGLOG(REQ, INFO, "--> %s()\n", __func__); + + if (data && len) { + prParams = (P_NL80211_DRIVER_SET_KEY_EXTS) data; + } else { + DBGLOG(REQ, ERROR, "mtk_cfg80211_testmode_set_key_ext, data is NULL\n"); + return -EINVAL; + } + + if (prParams) + prIWEncExt = (struct iw_encode_exts *)&prParams->ext; + + if (prIWEncExt->alg == IW_ENCODE_ALG_SMS4) { + /* KeyID */ + prWpiKey->ucKeyID = prParams->key_index; + prWpiKey->ucKeyID--; + if (prWpiKey->ucKeyID > 1) { + /* key id is out of range */ + /* printk(KERN_INFO "[wapi] add key error: key_id invalid %d\n", prWpiKey->ucKeyID); */ + return -EINVAL; + } + + if (prIWEncExt->key_len != 32) { + /* key length not valid */ + /* printk(KERN_INFO "[wapi] add key error: key_len invalid %d\n", prIWEncExt->key_len); */ + return -EINVAL; + } + /* printk(KERN_INFO "[wapi] %d ext_flags %d\n", prEnc->flags, prIWEncExt->ext_flags); */ + + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + prWpiKey->eKeyType = ENUM_WPI_GROUP_KEY; + prWpiKey->eDirection = ENUM_WPI_RX; + } else if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { + prWpiKey->eKeyType = ENUM_WPI_PAIRWISE_KEY; + prWpiKey->eDirection = ENUM_WPI_RX_TX; + } +/* #if CFG_SUPPORT_WAPI */ + /* handle_sec_msg_final(prIWEncExt->key, 32, prIWEncExt->key, NULL); */ +/* #endif */ + /* PN */ + memcpy(prWpiKey->aucPN, prIWEncExt->tx_seq, IW_ENCODE_SEQ_MAX_SIZE); + memcpy(prWpiKey->aucPN + IW_ENCODE_SEQ_MAX_SIZE, prIWEncExt->rx_seq, IW_ENCODE_SEQ_MAX_SIZE); + + + /* BSSID */ + memcpy(prWpiKey->aucAddrIndex, prIWEncExt->addr, 6); + + memcpy(prWpiKey->aucWPIEK, prIWEncExt->key, 16); + prWpiKey->u4LenWPIEK = 16; + + memcpy(prWpiKey->aucWPICK, &prIWEncExt->key[16], 16); + prWpiKey->u4LenWPICK = 16; + + rstatus = kalIoctl(prGlueInfo, + wlanoidSetWapiKey, + prWpiKey, sizeof(PARAM_WPI_KEY_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rstatus != WLAN_STATUS_SUCCESS) { + /* printk(KERN_INFO "[wapi] add key error:%lx\n", rStatus); */ + fgIsValid = -EFAULT; + } + + } + return fgIsValid; +} +#endif + +int +mtk_cfg80211_testmode_get_sta_statistics(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + INT_32 i4Status = -EINVAL; + UINT_32 u4BufLen; + UINT_32 u4LinkScore; + UINT_32 u4TotalError; + UINT_32 u4TxExceedThresholdCount; + UINT_32 u4TxTotalCount; + + P_NL80211_DRIVER_GET_STA_STATISTICS_PARAMS prParams = NULL; + PARAM_GET_STA_STA_STATISTICS rQueryStaStatistics; + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(QM, INFO, "--> %s()\n", __func__); + + if (data && len) { + prParams = (P_NL80211_DRIVER_GET_STA_STATISTICS_PARAMS) data; + } else { + DBGLOG(QM, ERROR, "mtk_cfg80211_testmode_get_sta_statistics, data is NULL\n"); + return -EINVAL; + } + /* + * if (!prParams->aucMacAddr) { + * DBGLOG(QM, INFO, "%s MAC Address is NULL\n", __func__); + * return -EINVAL; + * } + */ + skb = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(PARAM_GET_STA_STA_STATISTICS) + 1); + + if (!skb) { + DBGLOG(QM, ERROR, "%s allocate skb failed:%x\n", __func__, rStatus); + return -ENOMEM; + } + + DBGLOG(QM, TRACE, "Get [ %pM ] STA statistics\n", prParams->aucMacAddr); + + kalMemZero(&rQueryStaStatistics, sizeof(rQueryStaStatistics)); + COPY_MAC_ADDR(rQueryStaStatistics.aucMacAddr, prParams->aucMacAddr); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStaStatistics, + &rQueryStaStatistics, sizeof(rQueryStaStatistics), TRUE, FALSE, TRUE, TRUE, &u4BufLen); + + /* Calcute Link Score */ + u4TxExceedThresholdCount = rQueryStaStatistics.u4TxExceedThresholdCount; + u4TxTotalCount = rQueryStaStatistics.u4TxTotalCount; + u4TotalError = rQueryStaStatistics.u4TxFailCount + rQueryStaStatistics.u4TxLifeTimeoutCount; + + /* u4LinkScore 10~100 , ExceedThreshold ratio 0~90 only */ + /* u4LinkScore 0~9 , Drop packet ratio 0~9 and all packets exceed threshold */ + if (u4TxTotalCount) { + if (u4TxExceedThresholdCount <= u4TxTotalCount) + u4LinkScore = (90 - ((u4TxExceedThresholdCount * 90) / u4TxTotalCount)); + else + u4LinkScore = 0; + } else { + u4LinkScore = 90; + } + + u4LinkScore += 10; + + if (u4LinkScore == 10) { + + if (u4TotalError <= u4TxTotalCount) + u4LinkScore = (10 - ((u4TotalError * 10) / u4TxTotalCount)); + else + u4LinkScore = 0; + + } + + if (u4LinkScore > 100) + u4LinkScore = 100; + + /*NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_INVALID, 0);*/ + { + unsigned char __tmp = 0; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_INVALID, sizeof(unsigned char), &__tmp) < 0)) + goto nla_put_failure; + } + + /*NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_VERSION, NL80211_DRIVER_TESTMODE_VERSION);*/ + { + unsigned char __tmp = NL80211_DRIVER_TESTMODE_VERSION; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_VERSION, sizeof(unsigned char), &__tmp) < 0)) + goto nla_put_failure; + } + + /* NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE, u4LinkScore); */ + { + unsigned int __tmp = u4LinkScore; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + /*NLA_PUT(skb, NL80211_TESTMODE_STA_STATISTICS_MAC, MAC_ADDR_LEN, prParams->aucMacAddr);*/ + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_MAC, MAC_ADDR_LEN, &prParams->aucMacAddr) < 0)) + goto nla_put_failure; + + /*NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_FLAG, rQueryStaStatistics.u4Flag);*/ + { + unsigned int __tmp = rQueryStaStatistics.u4Flag; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_FLAG, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + + /* FW part STA link status */ + /*NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_PER, rQueryStaStatistics.ucPer);*/ + { + unsigned char __tmp = rQueryStaStatistics.ucPer; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_PER, sizeof(unsigned char), &__tmp) < 0)) + goto nla_put_failure; + } + + /*NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_RSSI, rQueryStaStatistics.ucRcpi);*/ + { + unsigned char __tmp = rQueryStaStatistics.ucRcpi; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_RSSI, sizeof(unsigned char), &__tmp) < 0)) + goto nla_put_failure; + } + + /*NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_PHY_MODE, rQueryStaStatistics.u4PhyMode);*/ + { + unsigned int __tmp = rQueryStaStatistics.u4PhyMode; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_PHY_MODE, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + /*NLA_PUT_U16(skb, NL80211_TESTMODE_STA_STATISTICS_TX_RATE, rQueryStaStatistics.u2LinkSpeed);*/ + { + unsigned short __tmp = rQueryStaStatistics.u2LinkSpeed; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TX_RATE, + sizeof(unsigned short), &__tmp) < 0)) + goto nla_put_failure; + } + /*NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT, rQueryStaStatistics.u4TxFailCount);*/ + { + unsigned int __tmp = rQueryStaStatistics.u4TxFailCount; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + /*NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT, rQueryStaStatistics.u4TxLifeTimeoutCount);*/ + { + unsigned int __tmp = rQueryStaStatistics.u4TxLifeTimeoutCount; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + /*NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME, rQueryStaStatistics.u4TxAverageAirTime);*/ + { + unsigned int __tmp = rQueryStaStatistics.u4TxAverageAirTime; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + /* Driver part link status */ + /*NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT, rQueryStaStatistics.u4TxTotalCount);*/ + { + unsigned int __tmp = rQueryStaStatistics.u4TxTotalCount; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + /* + * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT, + * rQueryStaStatistics.u4TxExceedThresholdCount); + */ + { + unsigned int __tmp = rQueryStaStatistics.u4TxExceedThresholdCount; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + /* + * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME, + * rQueryStaStatistics.u4TxAverageProcessTime); + */ + { + unsigned int __tmp = rQueryStaStatistics.u4TxAverageProcessTime; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + { + unsigned int __tmp = rQueryStaStatistics.u4TxMaxTime; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_MAX_PROCESS_TIME, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + + { + unsigned int __tmp = rQueryStaStatistics.u4TxAverageHifTime; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_AVG_HIF_PROCESS_TIME, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + { + unsigned int __tmp = rQueryStaStatistics.u4TxMaxHifTime; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_MAX_HIF_PROCESS_TIME, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + /* + * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_ENQUEUE, rQueryStaStatistics.u4EnqueueCounter); + */ + { + unsigned int __tmp = rQueryStaStatistics.u4EnqueueCounter; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_ENQUEUE, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + /* + * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_DEQUEUE, rQueryStaStatistics.u4DequeueCounter); + */ + { + unsigned int __tmp = rQueryStaStatistics.u4DequeueCounter; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_DEQUEUE, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + /* + * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_STA_ENQUEUE, rQueryStaStatistics.u4EnqueueStaCounter); + */ + { + unsigned int __tmp = rQueryStaStatistics.u4EnqueueStaCounter; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_STA_ENQUEUE, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + /* + * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_STA_DEQUEUE, rQueryStaStatistics.u4DequeueStaCounter); + */ + { + unsigned int __tmp = rQueryStaStatistics.u4DequeueStaCounter; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_STA_DEQUEUE, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + /* + * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_CNT, rQueryStaStatistics.IsrCnt); + */ + { + unsigned int __tmp = rQueryStaStatistics.IsrCnt; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_CNT, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + /* + * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_PASS_CNT, rQueryStaStatistics.IsrPassCnt); + */ + { + unsigned int __tmp = rQueryStaStatistics.IsrPassCnt; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_PASS_CNT, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + /* + * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_TASK_CNT, rQueryStaStatistics.TaskIsrCnt); + */ + { + unsigned int __tmp = rQueryStaStatistics.TaskIsrCnt; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_TASK_CNT, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + /* + * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_AB_CNT, rQueryStaStatistics.IsrAbnormalCnt); + */ + { + unsigned int __tmp = rQueryStaStatistics.IsrAbnormalCnt; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_AB_CNT, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + /* + * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_SW_CNT, rQueryStaStatistics.IsrSoftWareCnt); + */ + { + unsigned int __tmp = rQueryStaStatistics.IsrSoftWareCnt; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_SW_CNT, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + /* + * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_TX_CNT, rQueryStaStatistics.IsrTxCnt); + */ + { + unsigned int __tmp = rQueryStaStatistics.IsrTxCnt; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_TX_CNT, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + /* + *NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_RX_CNT, rQueryStaStatistics.IsrRxCnt); + */ + { + unsigned int __tmp = rQueryStaStatistics.IsrRxCnt; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_RX_CNT, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + /* Network counter */ + /* + * NLA_PUT(skb, + * NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY, + * sizeof(rQueryStaStatistics.au4TcResourceEmptyCount), rQueryStaStatistics.au4TcResourceEmptyCount); + */ + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY, + sizeof(rQueryStaStatistics.au4TcResourceEmptyCount), &rQueryStaStatistics.au4TcResourceEmptyCount) < 0)) + goto nla_put_failure; + /* + * NLA_PUT(skb, + * NL80211_TESTMODE_STA_STATISTICS_NO_TC_ARRAY, + * sizeof(rQueryStaStatistics.au4DequeueNoTcResource), rQueryStaStatistics.au4DequeueNoTcResource); + */ + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_NO_TC_ARRAY, + sizeof(rQueryStaStatistics.au4DequeueNoTcResource), &rQueryStaStatistics.au4DequeueNoTcResource) < 0)) + goto nla_put_failure; + /* + * NLA_PUT(skb, + * NL80211_TESTMODE_STA_STATISTICS_RB_ARRAY, + * sizeof(rQueryStaStatistics.au4TcResourceBackCount), rQueryStaStatistics.au4TcResourceBackCount); + */ + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_RB_ARRAY, + sizeof(rQueryStaStatistics.au4TcResourceBackCount), &rQueryStaStatistics.au4TcResourceBackCount) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_USED_BFCT_ARRAY, + sizeof(rQueryStaStatistics.au4TcResourceUsedCount), &rQueryStaStatistics.au4TcResourceUsedCount) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_WANTED_BFCT_ARRAY, + sizeof(rQueryStaStatistics.au4TcResourceWantedCount), + &rQueryStaStatistics.au4TcResourceWantedCount) < 0)) + goto nla_put_failure; + + /* Sta queue length */ + /* + * NLA_PUT(skb, + * NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY, + * sizeof(rQueryStaStatistics.au4TcQueLen), rQueryStaStatistics.au4TcQueLen); + */ + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY, + sizeof(rQueryStaStatistics.au4TcQueLen), &rQueryStaStatistics.au4TcQueLen) < 0)) + goto nla_put_failure; + + + /* Global QM counter */ + /* + * NLA_PUT(skb, + * NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY, + * sizeof(rQueryStaStatistics.au4TcAverageQueLen), rQueryStaStatistics.au4TcAverageQueLen); + */ + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY, + sizeof(rQueryStaStatistics.au4TcAverageQueLen), &rQueryStaStatistics.au4TcAverageQueLen) < 0)) + goto nla_put_failure; + + /* + * NLA_PUT(skb, + * NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY, + * sizeof(rQueryStaStatistics.au4TcCurrentQueLen), rQueryStaStatistics.au4TcCurrentQueLen); + */ + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY, + sizeof(rQueryStaStatistics.au4TcCurrentQueLen), &rQueryStaStatistics.au4TcCurrentQueLen) < 0)) + goto nla_put_failure; + + + /* Reserved field */ + /* + * NLA_PUT(skb, + * NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY, + * sizeof(rQueryStaStatistics.au4Reserved), rQueryStaStatistics.au4Reserved); + */ + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY, + sizeof(rQueryStaStatistics.au4Reserved), &rQueryStaStatistics.au4Reserved) < 0)) + goto nla_put_failure; + + i4Status = cfg80211_testmode_reply(skb); + skb = NULL; + +nla_put_failure: + if (skb != NULL) + kfree_skb(skb); + return i4Status; +} + +int +mtk_cfg80211_testmode_set_packet_filter(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + INT_32 i4Status = rStatus; + UINT_32 u4BufLen = 0; + P_NL80211_DRIVER_RXFILTER_PARAMS prParams = NULL; + + PACKET_DROP_T cmdBuf; + P_PACKET_DROP_T pCmdHeader = NULL; + P_PACKET_DROP_SETTING_V1_T pCmdData = NULL; + UINT_64 u64Filter = 0; + + ASSERT(wiphy); + ASSERT(prGlueInfo); + + if (data && len) + prParams = (P_NL80211_DRIVER_RXFILTER_PARAMS)data; + else { + DBGLOG(QM, ERROR, "mtk_cfg80211_testmode_set_packet_filter, data is NULL or len is 0\n"); + return -EINVAL; + } + + + kalMemZero(&cmdBuf, sizeof(cmdBuf)); + + pCmdHeader = &cmdBuf; + pCmdHeader->cmdVersion = 0; + pCmdHeader->cmdType = 0; + pCmdHeader->magicCode = 0x72; + pCmdHeader->cmdBufferLen = MAX_PACKET_DROP_LENGTH; + + pCmdData = (P_PACKET_DROP_SETTING_V1_T)&(pCmdHeader->buffer[0]); + + u64Filter = prParams->Ipv4FilterHigh; + u64Filter = u64Filter<<32; + u64Filter &= 0xffffffff00000000; + pCmdData->Drop_IPv4.bytes = u64Filter|prParams->Ipv4FilterLow; + + /*bit0~bit8 + * + *pCmdData->Drop_IPv4.bytes |= 0xFE; + *struct { + * UINT_64 all:1; + * UINT_64 MDNS:1; + * UINT_64 LLMNR:1; + * UINT_64 BROWSER:1; + * UINT_64 CAPWAP:1; + * UINT_64 DNS:1; + * UINT_64 NBNS:1; + * UINT_64 SSDP:1; + * UINT_64 others:1; + * } UDPbits; + */ + + u64Filter = prParams->Ipv6FilterHigh; + u64Filter = u64Filter<<32; + u64Filter &= 0xffffffff00000000; + pCmdData->Drop_IPv6.bytes = u64Filter|prParams->Ipv6FilterLow; + + /* bit0 only + *pCmdData->Drop_IPv6.bytes |= 0x01; + *struct { + * UINT_64 all:1; + * } bits; + */ + + u64Filter = prParams->SnapFilterHigh; + u64Filter = u64Filter<<32; + u64Filter &= 0xffffffff00000000; + pCmdData->Drop_SNAP.bytes = u64Filter|prParams->SnapFilterLow; + + /*bit0~bit4 + *pCmdData->Drop_SNAP.bytes |= 0x0E; + * struct { + * UINT_64 all:1; + * UINT_64 CDP:1; + * UINT_64 STP:1; + * UINT_64 XID:1; + * UINT_64 others:1; + * } bits; + */ + pr_info("wlan_gen2: mtk_cfg80211_testmode_set_packet_filter\n Drop_IPv4(%02llx)\nDrop_IPv6(%02llx)\nDrop_SNAP(%02llx)\n", + pCmdData->Drop_IPv4.bytes, pCmdData->Drop_IPv6.bytes, pCmdData->Drop_SNAP.bytes); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRxPacketFilterPriv, + &cmdBuf, + sizeof(PACKET_DROP_T), + FALSE, + FALSE, + TRUE, + FALSE, + &u4BufLen); + + /*printk("rStatus = %08x\n",rStatus);*/ + + if (rStatus != WLAN_STATUS_SUCCESS) + i4Status = -EFAULT; + + return i4Status; +} + +int +mtk_cfg80211_testmode_get_link_detection(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo) +{ + + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + INT_32 i4Status = -EINVAL; + UINT_32 u4BufLen; + + PARAM_802_11_STATISTICS_STRUCT_T rStatistics; + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(QM, INFO, "--> %s()\n", __func__); + + skb = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(PARAM_GET_STA_STA_STATISTICS) + 1); + + if (!skb) { + DBGLOG(QM, TRACE, "%s allocate skb failed:%x\n", __func__, rStatus); + return -ENOMEM; + } + + kalMemZero(&rStatistics, sizeof(rStatistics)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStatistics, + &rStatistics, sizeof(rStatistics), TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + /* NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_INVALID, 0); */ + { + unsigned char __tmp = 0; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_INVALID, sizeof(unsigned char), &__tmp) < 0)) + goto nla_put_failure; + } + + /* NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_TX_FAIL_CNT, rStatistics.rFailedCount.QuadPart); */ + { + u64 __tmp = rStatistics.rFailedCount.QuadPart; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_LINK_TX_FAIL_CNT, + sizeof(u64), &__tmp) < 0)) + goto nla_put_failure; + } + + /* NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_TX_RETRY_CNT, rStatistics.rRetryCount.QuadPart); */ + { + u64 __tmp = rStatistics.rFailedCount.QuadPart; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_LINK_TX_RETRY_CNT, + sizeof(u64), &__tmp) < 0)) + goto nla_put_failure; + } + + /* NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_TX_MULTI_RETRY_CNT, rStatistics.rMultipleRetryCount.QuadPart); */ + { + u64 __tmp = rStatistics.rMultipleRetryCount.QuadPart; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_LINK_TX_MULTI_RETRY_CNT, + sizeof(u64), &__tmp) < 0)) + goto nla_put_failure; + } + + /* NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_ACK_FAIL_CNT, rStatistics.rACKFailureCount.QuadPart); */ + { + u64 __tmp = rStatistics.rACKFailureCount.QuadPart; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_LINK_ACK_FAIL_CNT, + sizeof(u64), &__tmp) < 0)) + goto nla_put_failure; + } + + /* NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_FCS_ERR_CNT, rStatistics.rFCSErrorCount.QuadPart); */ + { + u64 __tmp = rStatistics.rFCSErrorCount.QuadPart; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_LINK_FCS_ERR_CNT, + sizeof(u64), &__tmp) < 0)) + goto nla_put_failure; + } + + + i4Status = cfg80211_testmode_reply(skb); + skb = NULL; + +nla_put_failure: + if (skb != NULL) + kfree_skb(skb); + return i4Status; +} + +int mtk_cfg80211_testmode_sw_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_SW_CMD_PARAMS prParams = (P_NL80211_DRIVER_SW_CMD_PARAMS) NULL; + WLAN_STATUS rstatus = WLAN_STATUS_SUCCESS; + int fgIsValid = 0; + UINT_32 u4SetInfoLen = 0; + + ASSERT(wiphy); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + DBGLOG(REQ, TRACE, "--> %s()\n", __func__); + + if (data && len) + prParams = (P_NL80211_DRIVER_SW_CMD_PARAMS) data; + + if (prParams) { + if (prParams->set == 1) { + rstatus = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC) wlanoidSetSwCtrlWrite, + &prParams->adr, (UINT_32) 8, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + } + } + + if (rstatus != WLAN_STATUS_SUCCESS) + fgIsValid = -EFAULT; + + return fgIsValid; +} + +#if CFG_SUPPORT_HOTSPOT_2_0 +int mtk_cfg80211_testmode_hs20_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + struct wpa_driver_hs20_data_s *prParams = NULL; + WLAN_STATUS rstatus = WLAN_STATUS_SUCCESS; + int fgIsValid = 0; + UINT_32 u4SetInfoLen = 0; + + ASSERT(wiphy); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + DBGLOG(REQ, INFO, "--> %s()\n", __func__); + + if (data && len) { + prParams = (struct wpa_driver_hs20_data_s *)data; + + DBGLOG(REQ, TRACE, "[%s] Cmd Type (%d)\n", __func__, prParams->CmdType); + } + + if (prParams) { + int i; + + switch (prParams->CmdType) { + case HS20_CMD_ID_SET_BSSID_POOL: + DBGLOG(REQ, TRACE, "fgBssidPoolIsEnable=%d, ucNumBssidPool=%d\n", + prParams->hs20_set_bssid_pool.fgBssidPoolIsEnable, + prParams->hs20_set_bssid_pool.ucNumBssidPool); + for (i = 0; i < prParams->hs20_set_bssid_pool.ucNumBssidPool; i++) { + DBGLOG(REQ, TRACE, "[%d][ %pM ]\n", i, + (prParams->hs20_set_bssid_pool.arBssidPool[i])); + } + rstatus = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC) wlanoidSetHS20BssidPool, + &prParams->hs20_set_bssid_pool, + sizeof(struct param_hs20_set_bssid_pool), + FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + break; + default: + DBGLOG(REQ, TRACE, "[%s] Unknown Cmd Type (%d)\n", __func__, prParams->CmdType); + rstatus = WLAN_STATUS_FAILURE; + + } + + } + + if (rstatus != WLAN_STATUS_SUCCESS) + fgIsValid = -EFAULT; + + return fgIsValid; +} +#endif + +int mtk_cfg80211_testmode_set_poorlink_param(IN struct wiphy *wiphy, IN void *data, IN int len, + IN P_GLUE_INFO_T prGlueInfo) +{ + int fgIsValid = 0; + P_NL80211_DRIVER_POORLINK_PARAMS prParams = NULL; + + ASSERT(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, INFO, "--> %s()\n", __func__); + + if (data && len) { + prParams = (P_NL80211_DRIVER_POORLINK_PARAMS) data; + } else { + DBGLOG(REQ, ERROR, "mtk_cfg80211_testmode_set_poorlink_param, data is NULL\n"); + return -EINVAL; + } + if (prParams->ucLinkSpeed) + prGlueInfo->u4LinkspeedThreshold = prParams->ucLinkSpeed * 10; + if (prParams->cRssi) + prGlueInfo->i4RssiThreshold = prParams->cRssi; + if (!prGlueInfo->fgPoorlinkValid) + prGlueInfo->fgPoorlinkValid = 1; +#if 0 + DBGLOG(REQ, TRACE, "poorlink set param valid(%d)rssi(%d)linkspeed(%d)\n", + prGlueInfo->fgPoorlinkValid, prGlueInfo->i4RssiThreshold, prGlueInfo->u4LinkspeedThreshold); +#endif + + return fgIsValid; + +} + +int mtk_cfg80211_testmode_cmd(IN struct wiphy *wiphy, IN struct wireless_dev *wdev, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_TEST_MODE_PARAMS prParams = NULL; + INT_32 i4Status = -EINVAL; + + + ASSERT(wiphy); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + if (data && len) { + prParams = (P_NL80211_DRIVER_TEST_MODE_PARAMS) data; + } else { + DBGLOG(REQ, ERROR, "data is NULL\n"); + return i4Status; + } + + /* Clear the version byte */ + prParams->index = prParams->index & ~BITS(24, 31); + + switch (prParams->index) { + case TESTMODE_CMD_ID_SW_CMD: /* SW cmd */ + i4Status = mtk_cfg80211_testmode_sw_cmd(wiphy, data, len); + break; +#if CFG_SUPPORT_WAPI + case TESTMODE_CMD_ID_WAPI: /* WAPI */ + i4Status = mtk_cfg80211_testmode_set_key_ext(wiphy, data, len); + break; +#endif + case TESTMODE_CMD_ID_SUSPEND: + { + P_NL80211_DRIVER_SUSPEND_PARAMS prParams = (P_NL80211_DRIVER_SUSPEND_PARAMS) data; + + if (prParams->suspend == 1) { + wlanHandleSystemSuspend(); + if (prGlueInfo->prAdapter->fgIsP2PRegistered) + p2pHandleSystemSuspend(); + i4Status = 0; + } else if (prParams->suspend == 0) { + wlanHandleSystemResume(); + if (prGlueInfo->prAdapter->fgIsP2PRegistered) + p2pHandleSystemResume(); + i4Status = 0; + } + break; + } + case TESTMODE_CMD_ID_RXFILTER: + i4Status = mtk_cfg80211_testmode_set_packet_filter(wiphy, data, len, prGlueInfo); + break; + case TESTMODE_CMD_ID_STATISTICS: + i4Status = mtk_cfg80211_testmode_get_sta_statistics(wiphy, data, len, prGlueInfo); + break; + case TESTMODE_CMD_ID_LINK_DETECT: + i4Status = mtk_cfg80211_testmode_get_link_detection(wiphy, data, len, prGlueInfo); + break; + case TESTMODE_CMD_ID_POORLINK: + i4Status = mtk_cfg80211_testmode_set_poorlink_param(wiphy, data, len, prGlueInfo); + break; + +#if CFG_SUPPORT_HOTSPOT_2_0 + case TESTMODE_CMD_ID_HS20: + i4Status = mtk_cfg80211_testmode_hs20_cmd(wiphy, data, len); + break; +#endif + case TESTMODE_CMD_ID_STR_CMD: + i4Status = mtk_cfg80211_process_str_cmd(prGlueInfo, + (PUINT_8)(prParams+1), len - sizeof(*prParams)); + break; + + default: + i4Status = -EINVAL; + break; + } + + if (i4Status != 0) + DBGLOG(REQ, INFO, "--> %s() prParams->index=%d, status=%d\n" + , __func__, prParams->index, i4Status); + + return i4Status; +} + +int mtk_cfg80211_testmode_get_scan_done(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo) +{ +#define NL80211_TESTMODE_P2P_SCANDONE_INVALID 0 +#define NL80211_TESTMODE_P2P_SCANDONE_STATUS 1 + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + INT_32 i4Status = -EINVAL, READY_TO_BEAM = 0; + + /* P_NL80211_DRIVER_GET_STA_STATISTICS_PARAMS prParams = NULL; */ + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(QM, INFO, "--> %s()\n", __func__); + + skb = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(UINT_32)); + READY_TO_BEAM = + (UINT_32) (prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo. + fgIsGOInitialDone) & + (!prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsScanRequest); + DBGLOG(QM, TRACE, + "NFC:GOInitialDone[%d] and P2PScanning[%d]\n", + prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsGOInitialDone, + prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsScanRequest); + + if (!skb) { + DBGLOG(QM, TRACE, "%s allocate skb failed:%x\n", __func__, rStatus); + return -ENOMEM; + } + + /* NLA_PUT_U8(skb, NL80211_TESTMODE_P2P_SCANDONE_INVALID, 0); */ + { + unsigned char __tmp = 0; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_P2P_SCANDONE_INVALID, sizeof(unsigned char), &__tmp) < 0)) + goto nla_put_failure; + } + /* NLA_PUT_U32(skb, NL80211_TESTMODE_P2P_SCANDONE_STATUS, READY_TO_BEAM); */ + { + unsigned int __tmp = READY_TO_BEAM; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_P2P_SCANDONE_STATUS, sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + + i4Status = cfg80211_testmode_reply(skb); + skb = NULL; + +nla_put_failure: + if (skb != NULL) + kfree_skb(skb); + return i4Status; +} + +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @brief cfg80211 suspend callback, will be invoked in wiphy_suspend + * + * @param wiphy: pointer to wiphy + * wow: pointer to cfg80211_wowlan + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + DBGLOG(REQ, TRACE, "--> %s()\n", __func__); + + if (kalHaltTryLock()) + return 0; + + if (kalIsHalted() || !wiphy) + goto end; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + set_bit(SUSPEND_FLAG_FOR_WAKEUP_REASON, &prGlueInfo->prAdapter->ulSuspendFlag); + set_bit(SUSPEND_FLAG_CLEAR_WHEN_RESUME, &prGlueInfo->prAdapter->ulSuspendFlag); +end: + kalHaltUnlock(); + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief cfg80211 resume callback, will be invoked in wiphy_resume. + * + * @param wiphy: pointer to wiphy + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_resume(struct wiphy *wiphy) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_BSS_DESC_T *pprBssDesc = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_8 i = 0; + + DBGLOG(SCN, TRACE, "--> %s()\n", __func__); + + if (kalHaltTryLock()) + return 0; + + if (kalIsHalted() || !wiphy) + goto end; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + prAdapter = prGlueInfo->prAdapter; + clear_bit(SUSPEND_FLAG_CLEAR_WHEN_RESUME, &prAdapter->ulSuspendFlag); + pprBssDesc = &prAdapter->rWifiVar.rScanInfo.rNloParam.aprPendingBssDescToInd[0]; + for (; i < SCN_SSID_MATCH_MAX_NUM; i++) { + if (pprBssDesc[i] == NULL) + break; + if (pprBssDesc[i]->u2RawLength == 0) + continue; + kalIndicateBssInfo(prGlueInfo, + (PUINT_8) pprBssDesc[i]->aucRawBuf, + pprBssDesc[i]->u2RawLength, + pprBssDesc[i]->ucChannelNum, + RCPI_TO_dBm(pprBssDesc[i]->ucRCPI)); + } + + if (i > 0) { + DBGLOG(SCN, INFO, "pending %d sched scan results\n", i); + kalMemZero(&pprBssDesc[0], i * sizeof(P_BSS_DESC_T)); + } +end: + kalHaltUnlock(); + return 0; +} + +int mtk_cfg80211_update_ft_ies(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_update_ft_ies_params *ftie) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4InfoBufLen = 0; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + +#if !CFG_SUPPORT_802_11R + DBGLOG(OID, INFO, "802.11R is not enabled\n"); + return 0; +#endif + if (!wiphy) + return -1; + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + rStatus = kalIoctl(prGlueInfo, wlanoidUpdateFtIes, (PVOID)ftie, sizeof(*ftie), FALSE, + FALSE, FALSE, FALSE, &u4InfoBufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(OID, INFO, "update Ft IE failed\n"); + return 0; +} + +INT_32 mtk_cfg80211_process_str_cmd(P_GLUE_INFO_T prGlueInfo, PUINT_8 cmd, INT_32 len) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4SetInfoLen = 0; + + DBGLOG(REQ, INFO, "--> %s()\n", __func__); + + if (kalStrniCmp(cmd, "tdls-ps ", 8) == 0) { +#if CFG_SUPPORT_TDLS + DBGLOG(TDLS, INFO, "disable tdls-ps\n"); + rStatus = kalIoctl(prGlueInfo, + wlanoidDisableTdlsPs, + (PVOID)(cmd+8), 1, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); +#else + DBGLOG(REQ, WARN, "not support tdls\n"); + return -EOPNOTSUPP; +#endif + } else if (kalStrniCmp(cmd, "SETALWAYSSCANSTATE ", 19) == 0) { + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAlwaysScan, + (PVOID)(cmd+19), + sizeof(UINT_8), + FALSE, + FALSE, + TRUE, + FALSE, + &u4SetInfoLen); + } else if (kalStrniCmp(cmd, "OSHAREMOD ", 10) == 0) { +#if CFG_SUPPORT_OSHARE + struct OSHARE_MODE_T cmdBuf; + struct OSHARE_MODE_T *pCmdHeader = NULL; + struct OSHARE_MODE_SETTING_V1_T *pCmdData = NULL; + + kalMemZero(&cmdBuf, sizeof(cmdBuf)); + + pCmdHeader = &cmdBuf; + pCmdHeader->cmdVersion = OSHARE_MODE_CMD_V1; + pCmdHeader->cmdType = 1; /*1-set 0-query*/ + pCmdHeader->magicCode = OSHARE_MODE_MAGIC_CODE; + pCmdHeader->cmdBufferLen = MAX_OSHARE_MODE_LENGTH; + + pCmdData = (struct OSHARE_MODE_SETTING_V1_T *)&(pCmdHeader->buffer[0]); + pCmdData->osharemode = *(PUINT_8)(cmd + 10) - '0'; + + DBGLOG(REQ, INFO, "cmd=%s, osharemode=%u\n", cmd, pCmdData->osharemode); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetOshareMode, + &cmdBuf, + sizeof(struct OSHARE_MODE_T), + FALSE, + FALSE, + TRUE, + FALSE, + &u4SetInfoLen); + if (rStatus == WLAN_STATUS_SUCCESS && prGlueInfo) { + P_ADAPTER_T prAdapter = prGlueInfo->prAdapter; + + if (prAdapter) { + prAdapter->fgEnOshareMode = pCmdData->osharemode; + DBGLOG(REQ, INFO, "Set osharemode=%u\n", prAdapter->fgEnOshareMode); + } + } +#else + DBGLOG(REQ, WARN, "not support OSHAREMOD\n"); + return -EOPNOTSUPP; +#endif + } else if (kalStrniCmp(cmd, "NEIGHBOR-REQUEST", 16) == 0) { + PUINT_8 pucSSID = NULL; + UINT_32 u4SSIDLen = 0; + + if (len > 16 && (kalStrniCmp(cmd+16, " SSID=", 6) == 0)) { + pucSSID = cmd + 22; + u4SSIDLen = len - 22; + DBGLOG(REQ, INFO, "cmd=%s, ssid len %u, ssid=%s\n", cmd, u4SSIDLen, HIDE(pucSSID)); + } + rStatus = kalIoctl(prGlueInfo, wlanoidSendNeighborRequest, + (PVOID)pucSSID, u4SSIDLen, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + } else if (kalStrniCmp(cmd, "BSS-TRANSITION-QUERY", 20) == 0) { + PUINT_8 pucReason = NULL; + + if (len > 20 && (kalStrniCmp(cmd+20, " reason=", 8) == 0)) + pucReason = cmd + 28; + rStatus = kalIoctl(prGlueInfo, + wlanoidSendBTMQuery, + (PVOID)pucReason, 1, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + } else + return -EOPNOTSUPP; + + if (rStatus == WLAN_STATUS_SUCCESS) + return 0; + + return -EINVAL; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_init.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_init.c new file mode 100644 index 0000000000000..45e98c5580d19 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_init.c @@ -0,0 +1,3668 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ +#include "gl_os.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "gl_cfg80211.h" +#include "precomp.h" +#if CFG_SUPPORT_AGPS_ASSIST +#include "gl_kal.h" +#endif +#if CFG_TC1_FEATURE +#include +#endif +#include "gl_vendor.h" + +#ifdef FW_CFG_SUPPORT +#include "fwcfg.h" +#endif +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* #define MAX_IOREQ_NUM 10 */ + +BOOLEAN fgIsUnderSuspend; +BOOLEAN fgNvramAvailable; +UINT_8 g_aucNvram[CFG_FILE_WIFI_REC_SIZE]; + +#if CFG_ENABLE_WIFI_DIRECT +spinlock_t g_p2p_lock; +int g_u4P2PEnding; +int g_u4P2POnOffing; +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Tasklet mechanism is like buttom-half in Linux. We just want to + * send a signal to OS for interrupt defer processing. All resources + * are NOT allowed reentry, so txPacket, ISR-DPC and ioctl must avoid preempty. + */ +typedef struct _WLANDEV_INFO_T { + struct net_device *prDev; +} WLANDEV_INFO_T, *P_WLANDEV_INFO_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +#define CHAN2G(_channel, _freq, _flags) \ +{ \ + .band = 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 = (((_channel >= 182) && (_channel <= 196)) ? \ + (4000 + (5 * (_channel))) : (5000 + (5 * (_channel)))), \ + .hw_value = (_channel), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} + +static struct ieee80211_channel mtk_5ghz_channels[] = { + /* UNII-1 */ + CHAN5G(34, 0), CHAN5G(36, 0), + CHAN5G(38, 0), CHAN5G(40, 0), + CHAN5G(42, 0), CHAN5G(44, 0), + CHAN5G(46, 0), CHAN5G(48, 0), + /* UNII-2 */ + CHAN5G(52, IEEE80211_CHAN_RADAR), + CHAN5G(56, IEEE80211_CHAN_RADAR), + CHAN5G(60, IEEE80211_CHAN_RADAR), + CHAN5G(64, IEEE80211_CHAN_RADAR), + /* UNII-2e */ + CHAN5G(100, IEEE80211_CHAN_RADAR), + CHAN5G(104, IEEE80211_CHAN_RADAR), + CHAN5G(108, IEEE80211_CHAN_RADAR), + CHAN5G(112, IEEE80211_CHAN_RADAR), + CHAN5G(116, IEEE80211_CHAN_RADAR), + CHAN5G(120, IEEE80211_CHAN_RADAR), + CHAN5G(124, IEEE80211_CHAN_RADAR), + CHAN5G(128, IEEE80211_CHAN_RADAR), + CHAN5G(132, IEEE80211_CHAN_RADAR), + CHAN5G(136, IEEE80211_CHAN_RADAR), + CHAN5G(140, IEEE80211_CHAN_RADAR), + CHAN5G(144, IEEE80211_CHAN_RADAR), + /* UNII-3 */ + CHAN5G(149, 0), + CHAN5G(153, 0), CHAN5G(157, 0), + CHAN5G(161, 0), CHAN5G(165, 0), + CHAN5G(169, 0), CHAN5G(173, 0), + CHAN5G(184, 0), CHAN5G(188, 0), + CHAN5G(192, 0), CHAN5G(196, 0), + CHAN5G(200, 0), CHAN5G(204, 0), + CHAN5G(208, 0), CHAN5G(212, 0), + CHAN5G(216, 0), +}; + +#define RATETAB_ENT(_rate, _rateid, _flags) \ +{ \ + .bitrate = (_rate), \ + .hw_value = (_rateid), \ + .flags = (_flags), \ +} + +/* for cfg80211 - rate table */ +static struct ieee80211_rate mtk_rates[] = { + RATETAB_ENT(10, 0x1000, 0), + RATETAB_ENT(20, 0x1001, 0), + RATETAB_ENT(55, 0x1002, 0), + RATETAB_ENT(110, 0x1003, 0), /* 802.11b */ + RATETAB_ENT(60, 0x2000, 0), + RATETAB_ENT(90, 0x2001, 0), + RATETAB_ENT(120, 0x2002, 0), + RATETAB_ENT(180, 0x2003, 0), + RATETAB_ENT(240, 0x2004, 0), + RATETAB_ENT(360, 0x2005, 0), + RATETAB_ENT(480, 0x2006, 0), + RATETAB_ENT(540, 0x2007, 0), /* 802.11a/g */ +}; + +#define mtk_a_rates (mtk_rates + 4) +#define mtk_a_rates_size (ARRAY_SIZE(mtk_rates) - 4) +#define mtk_g_rates (mtk_rates + 0) +#define mtk_g_rates_size (ARRAY_SIZE(mtk_rates) - 0) + +#define WLAN_MCS_INFO \ +{ \ + .rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0},\ + .rx_highest = 0, \ + .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ +} + +#define WLAN_HT_CAP \ +{ \ + .ht_supported = true, \ + .cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 \ + | IEEE80211_HT_CAP_SM_PS \ + | IEEE80211_HT_CAP_GRN_FLD \ + | IEEE80211_HT_CAP_SGI_20 \ + | IEEE80211_HT_CAP_SGI_40, \ + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, \ + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE, \ + .mcs = WLAN_MCS_INFO, \ +} + +/********************************************************** +* Public for both legacy Wi-Fi and P2P to access +**********************************************************/ +struct ieee80211_supported_band mtk_band_2ghz = { + .band = 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 = WLAN_HT_CAP, +}; + +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 = WLAN_HT_CAP, +}; + +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, + WLAN_CIPHER_SUITE_NO_GROUP_ADDR +}; + +/*********************************************************/ + +/* NIC interface name */ +#define NIC_INF_NAME "wlan%d" /* interface name */ +/* support to change debug module info dynamically */ +UINT_8 aucDebugModule[DBG_MODULE_NUM]; + +UINT_32 u4DriverLogLevel = ENUM_WIFI_LOG_LEVEL_OFF; +UINT_32 u4FwLogLevel = ENUM_WIFI_LOG_LEVEL_OFF; + +/* 4 2007/06/26, mikewu, now we don't use this, we just fix the number of wlan device to 1 */ +static WLANDEV_INFO_T arWlanDevInfo[CFG_MAX_WLAN_DEVICES] = { {0} }; + +static UINT_32 u4WlanDevNum; /* How many NICs coexist now */ + +/**20150205 added work queue for sched_scan to avoid cfg80211 stop schedule scan dead loack**/ +struct delayed_work sched_workq; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if CFG_ENABLE_WIFI_DIRECT +static SUB_MODULE_HANDLER rSubModHandler[SUB_MODULE_NUM] = { {NULL} }; +#endif + +static struct cfg80211_ops mtk_wlan_ops = { + .suspend = mtk_cfg80211_suspend, + .resume = mtk_cfg80211_resume, + .change_virtual_intf = mtk_cfg80211_change_iface, + .add_key = mtk_cfg80211_add_key, + .get_key = mtk_cfg80211_get_key, + .del_key = mtk_cfg80211_del_key, + .set_default_key = mtk_cfg80211_set_default_key, + .set_default_mgmt_key = mtk_cfg80211_set_default_mgmt_key, + .get_station = mtk_cfg80211_get_station, + .change_station = mtk_cfg80211_change_station, + .add_station = mtk_cfg80211_add_station, + .del_station = mtk_cfg80211_del_station, + .scan = mtk_cfg80211_scan, + .abort_scan = mtk_cfg80211_abort_scan, + .connect = mtk_cfg80211_connect, + .disconnect = mtk_cfg80211_disconnect, + .join_ibss = mtk_cfg80211_join_ibss, + .leave_ibss = mtk_cfg80211_leave_ibss, + .set_power_mgmt = mtk_cfg80211_set_power_mgmt, + .set_pmksa = mtk_cfg80211_set_pmksa, + .del_pmksa = mtk_cfg80211_del_pmksa, + .flush_pmksa = mtk_cfg80211_flush_pmksa, + .assoc = mtk_cfg80211_assoc, + /* Action Frame TX/RX */ + .remain_on_channel = mtk_cfg80211_remain_on_channel, + .cancel_remain_on_channel = mtk_cfg80211_cancel_remain_on_channel, + .mgmt_tx = mtk_cfg80211_mgmt_tx, +/* .mgmt_tx_cancel_wait = mtk_cfg80211_mgmt_tx_cancel_wait, */ + .mgmt_frame_register = mtk_cfg80211_mgmt_frame_register, +#ifdef CONFIG_NL80211_TESTMODE + .testmode_cmd = mtk_cfg80211_testmode_cmd, +#endif +#if (CFG_SUPPORT_TDLS == 1) + .tdls_mgmt = TdlsexCfg80211TdlsMgmt, + .tdls_oper = TdlsexCfg80211TdlsOper, +#endif /* CFG_SUPPORT_TDLS */ +#if 1 /* Remove schedule_scan because we need more verification for NLO */ + .sched_scan_start = mtk_cfg80211_sched_scan_start, + .sched_scan_stop = mtk_cfg80211_sched_scan_stop, +#endif + .update_ft_ies = mtk_cfg80211_update_ft_ies, +#if CFG_SUPPORT_WPA3 + .external_auth = mtk_cfg80211_external_auth, +#endif +}; + + +static const struct wiphy_vendor_command mtk_wlan_vendor_ops[] = { + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_GET_CHANNEL_LIST + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_channel_list + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_SET_COUNTRY_CODE + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_country_code + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV + | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_scan_mac_oui + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_GET_ROAMING_CAPABILITIES + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_roaming_capabilities + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_CONFIG_ROAMING + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_config_roaming + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_ENABLE_ROAMING + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_enable_roaming + }, + /* GSCAN */ +#if CFG_SUPPORT_GSCN + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_SUBCMD_GET_CAPABILITIES + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_gscan_capabilities + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_SUBCMD_SET_CONFIG + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_config + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_SUBCMD_SET_SCAN_CONFIG + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_scan_config + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_SUBCMD_ENABLE_GSCAN + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_enable_scan + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_enable_full_scan_results + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_SUBCMD_GET_SCAN_RESULTS + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_gscan_result + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_significant_change + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_SUBCMD_SET_HOTLIST + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_hotlist + }, +#endif + /* RTT */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = RTT_SUBCMD_GETCAPABILITY + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_rtt_capabilities + }, + /* Link Layer Statistics */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = LSTATS_SUBCMD_GET_INFO + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_llstats_get_info + }, + /* RSSI Monitoring */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_SET_RSSI_MONITOR + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_rssi_monitoring + }, + /* Packet Keep Alive */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_OFFLOAD_START_MKEEP_ALIVE + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_packet_keep_alive_start + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_OFFLOAD_STOP_MKEEP_ALIVE + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_packet_keep_alive_stop + }, + /* Get Driver Version or Firmware Version */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = LOGGER_GET_VER + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_version + }, + { + { + .vendor_id = OUI_QCA, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_band + }, + { + { + .vendor_id = OUI_QCA, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_roaming_policy + }, + /* Get Supported Feature Set */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_GET_FEATURE_SET + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_supported_feature_set + }, + /* Set Tx Power Scenario */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_SELECT_TX_POWER_SCENARIO + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_tx_power_scenario + }, +}; + +static const struct nl80211_vendor_cmd_info mtk_wlan_vendor_events[] = { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_HOTLIST_RESULTS_FOUND + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_SCAN_RESULTS_AVAILABLE + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_FULL_SCAN_RESULTS + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = RTT_EVENT_COMPLETE + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_COMPLETE_SCAN + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_HOTLIST_RESULTS_LOST + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_EVENT_RSSI_MONITOR + }, +}; + +/* There isn't a lot of sense in it, but you can transmit anything you like */ +static const struct ieee80211_txrx_stypes + mtk_cfg80211_ais_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { + [NL80211_IFTYPE_ADHOC] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) + }, + [NL80211_IFTYPE_STATION] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) + }, + [NL80211_IFTYPE_AP] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | BIT(IEEE80211_STYPE_ACTION >> 4) + }, + [NL80211_IFTYPE_AP_VLAN] = { + /* copy AP */ + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) | BIT(IEEE80211_STYPE_ACTION >> 4) + }, + [NL80211_IFTYPE_P2P_CLIENT] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + }, + [NL80211_IFTYPE_P2P_GO] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | BIT(IEEE80211_STYPE_ACTION >> 4) + } +}; + +#ifdef CONFIG_PM +static const struct wiphy_wowlan_support mtk_wlan_wowlan_support = { + .flags = WIPHY_WOWLAN_DISCONNECT | WIPHY_WOWLAN_ANY, +}; +#endif + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Override the implementation of select queue +* +* \param[in] dev Pointer to struct net_device +* \param[in] skb Pointer to struct skb_buff +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +unsigned int _cfg80211_classify8021d(struct sk_buff *skb) +{ + unsigned int dscp = 0; + + /* skb->priority values from 256->263 are magic values + * directly indicate a specific 802.1d priority. This is + * to allow 802.1d priority to be passed directly in from + * tags + */ + + if (skb->priority >= 256 && skb->priority <= 263) + return skb->priority - 256; + switch (skb->protocol) { + case htons(ETH_P_IP): + dscp = ip_hdr(skb)->tos & 0xfc; + break; + } + return dscp >> 5; +} + +static const UINT_16 au16Wlan1dToQueueIdx[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; + +#if KERNEL_VERSION(4, 19, 0) <= CFG80211_VERSION_CODE +static UINT_16 wlanSelectQueue(struct net_device *dev, struct sk_buff *skb, + struct net_device *sb_dev, select_queue_fallback_t fallback) +#else +static UINT_16 wlanSelectQueue(struct net_device *dev, struct sk_buff *skb, + void *accel_priv, select_queue_fallback_t fallback) +#endif +{ + skb->priority = _cfg80211_classify8021d(skb); + + return au16Wlan1dToQueueIdx[skb->priority]; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Load NVRAM data and translate it into REG_INFO_T +* +* \param[in] prGlueInfo Pointer to struct GLUE_INFO_T +* \param[out] prRegInfo Pointer to struct REG_INFO_T +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static void glLoadNvram(IN P_GLUE_INFO_T prGlueInfo, OUT P_REG_INFO_T prRegInfo) +{ + UINT_32 i, j, len, startAddr; + UINT_8 aucTmp[2]; + PUINT_8 pucDest; + + ASSERT(prGlueInfo); + ASSERT(prRegInfo); + + if ((!prGlueInfo) || (!prRegInfo)) + return; + + DBGLOG(INIT, INFO, "fgNvramAvailable = %u\n", fgNvramAvailable); + prGlueInfo->fgNvramAvailable = fgNvramAvailable; + if (!prGlueInfo->fgNvramAvailable) { + DBGLOG(INIT, WARN, "Nvram not available\n"); + return; + } + + /* load MAC Address */ +#if CFG_TC1_FEATURE + TC1_FAC_NAME(FacReadWifiMacAddr) ((unsigned char *)prRegInfo->aucMacAddr); + +#else + for (i = 0; i < PARAM_MAC_ADDR_LEN; i += sizeof(UINT_16)) { + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucMacAddress) + i, + (PUINT_16) (((PUINT_8) prRegInfo->aucMacAddr) + i)); + } +#endif + + /* load country code */ + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucCountryCode[0]), (PUINT_16) aucTmp); + + /* cast to wide characters */ + prRegInfo->au2CountryCode[0] = (UINT_16) aucTmp[0]; + prRegInfo->au2CountryCode[1] = (UINT_16) aucTmp[1]; + + /* load default normal TX power */ + for (i = 0; i < sizeof(TX_PWR_PARAM_T); i += sizeof(UINT_16)) { + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, rTxPwr) + i, + (PUINT_16) (((PUINT_8)&(prRegInfo->rTxPwr)) + i)); + } + + /* load feature flags */ + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, ucTxPwrValid), (PUINT_16) aucTmp); + prRegInfo->ucTxPwrValid = aucTmp[0]; + prRegInfo->ucSupport5GBand = aucTmp[1]; + + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, uc2G4BwFixed20M), (PUINT_16) aucTmp); + prRegInfo->uc2G4BwFixed20M = aucTmp[0]; + prRegInfo->uc5GBwFixed20M = aucTmp[1]; + + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, ucEnable5GBand), (PUINT_16) aucTmp); + prRegInfo->ucEnable5GBand = aucTmp[0]; + + /* load EFUSE overriding part */ + for (i = 0; i < sizeof(prRegInfo->aucEFUSE); i += sizeof(UINT_16)) { + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucEFUSE) + i, + (PUINT_16) (((PUINT_8)&(prRegInfo->aucEFUSE)) + i)); + } + + /* load band edge tx power control */ + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, fg2G4BandEdgePwrUsed), (PUINT_16) aucTmp); + prRegInfo->fg2G4BandEdgePwrUsed = (BOOLEAN) aucTmp[0]; + if (aucTmp[0]) { + prRegInfo->cBandEdgeMaxPwrCCK = (INT_8) aucTmp[1]; + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, cBandEdgeMaxPwrOFDM20), (PUINT_16) aucTmp); + prRegInfo->cBandEdgeMaxPwrOFDM20 = (INT_8) aucTmp[0]; + prRegInfo->cBandEdgeMaxPwrOFDM40 = (INT_8) aucTmp[1]; + } + + /* load regulation subbands */ + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, ucRegChannelListMap), (PUINT_16) aucTmp); + prRegInfo->eRegChannelListMap = (ENUM_REG_CH_MAP_T) aucTmp[0]; + prRegInfo->ucRegChannelListIndex = aucTmp[1]; + + if (prRegInfo->eRegChannelListMap == REG_CH_MAP_CUSTOMIZED) { + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + pucDest = (PUINT_8)&prRegInfo->rDomainInfo.rSubBand[i]; + for (j = 0; j < 6; j += sizeof(UINT_16)) { + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucRegSubbandInfo) + + (i * 6 + j), (PUINT_16) aucTmp); + + *pucDest++ = aucTmp[0]; + *pucDest++ = aucTmp[1]; + } + } + } + /* load RSSI compensation */ + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, uc2GRssiCompensation), (PUINT_16) aucTmp); + prRegInfo->uc2GRssiCompensation = aucTmp[0]; + prRegInfo->uc5GRssiCompensation = aucTmp[1]; + + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, fgRssiCompensationValidbit), (PUINT_16) aucTmp); + prRegInfo->fgRssiCompensationValidbit = aucTmp[0]; + prRegInfo->ucRxAntennanumber = aucTmp[1]; + +#if CFG_SUPPORT_TX_POWER_BACK_OFF + kalCfgDataRead(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, fgRlmMitigatedPwrByChByMode), + sizeof(UINT_8), + (PUINT_16) aucTmp); + prRegInfo->fgRlmMitigatedPwrByChByMode = aucTmp[0]; + + /* load Tx Power offset perchannel per mode 40 : MAXNUM_MITIGATED_PWR_BY_CH_BY_MODE */ + kalCfgDataRead(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, arRlmMitigatedPwrByChByMode), + sizeof(MITIGATED_PWR_BY_CH_BY_MODE)*40, + (PUINT_16) prRegInfo->arRlmMitigatedPwrByChByMode); + + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, + bTxPowerLimitEnable2G), (PUINT_16) aucTmp); + prRegInfo->bTxPowerLimitEnable2G = (BOOLEAN)aucTmp[0]; + prRegInfo->cTxBackOffMaxPower2G = aucTmp[1]; + + /* load TxPower for 5G Band from nvram */ + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, + bTxPowerLimitEnable5G), (PUINT_16) aucTmp); + prRegInfo->bTxPowerLimitEnable5G = (BOOLEAN)aucTmp[0]; + prRegInfo->cTxBackOffMaxPower5G = aucTmp[1]; + + +#endif +#if CFG_SUPPORT_FCC_POWER_BACK_OFF + /* load FCC cert. parameters */ + kalCfgDataRead(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, rFccTxPwrAdjust), + sizeof(FCC_TX_PWR_ADJUST), + (PUINT_16)&prRegInfo->rFccTxPwrAdjust); + + /* load FCC Channel Band Edge */ + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucChannelBandEdge[0]), (PUINT_16) aucTmp); + prRegInfo->aucChannelBandEdge[0] = (UINT_8) aucTmp[0]; + prRegInfo->aucChannelBandEdge[1] = (UINT_8) aucTmp[1]; + + DBGLOG(INIT, TRACE, "rFccTxPwrAdjust offset:%ld, value:%d, %d, %d, %d, [%d, %d], [%d, %d], [%d, %d]\n", + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, rFccTxPwrAdjust), + prRegInfo->rFccTxPwrAdjust.fgFccTxPwrAdjust, + prRegInfo->rFccTxPwrAdjust.uOffsetCCK, + prRegInfo->rFccTxPwrAdjust.uOffsetHT20, + prRegInfo->rFccTxPwrAdjust.uOffsetHT40, + prRegInfo->rFccTxPwrAdjust.aucChannelCCK[0], + prRegInfo->rFccTxPwrAdjust.aucChannelCCK[1], + prRegInfo->rFccTxPwrAdjust.aucChannelHT20[0], + prRegInfo->rFccTxPwrAdjust.aucChannelHT20[1], + prRegInfo->rFccTxPwrAdjust.aucChannelHT40[0], + prRegInfo->rFccTxPwrAdjust.aucChannelHT40[1]); + + DBGLOG(INIT, TRACE, "FCC Tx power channel band edge [%d, %d]\n", + prRegInfo->aucChannelBandEdge[0], prRegInfo->aucChannelBandEdge[1]); +#endif + startAddr = OFFSET_OF(REG_INFO_T, aucMacAddr); + len = sizeof(REG_INFO_T); + DBGLOG_MEM8_IE_ONE_LINE(INIT, INFO, "RegInfo", (PUINT_8)prRegInfo + startAddr, len); +} + +#if CFG_ENABLE_WIFI_DIRECT +/*----------------------------------------------------------------------------*/ +/*! +* \brief called by txthread, run sub module init function +* +* \param[in] prGlueInfo Pointer to struct GLUE_INFO_T +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanSubModRunInit(P_GLUE_INFO_T prGlueInfo) +{ + /*now, we only have p2p module */ + if (rSubModHandler[P2P_MODULE].fgIsInited == FALSE) { + rSubModHandler[P2P_MODULE].subModInit(prGlueInfo); + rSubModHandler[P2P_MODULE].fgIsInited = TRUE; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief called by txthread, run sub module exit function +* +* \param[in] prGlueInfo Pointer to struct GLUE_INFO_T +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanSubModRunExit(P_GLUE_INFO_T prGlueInfo) +{ + /*now, we only have p2p module */ + if (rSubModHandler[P2P_MODULE].fgIsInited == TRUE) { + rSubModHandler[P2P_MODULE].subModExit(prGlueInfo); + rSubModHandler[P2P_MODULE].fgIsInited = FALSE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief set sub module init flag, force TxThread to run sub modle init +* +* \param[in] prGlueInfo Pointer to struct GLUE_INFO_T +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanSubModInit(P_GLUE_INFO_T prGlueInfo) +{ + /* 4 Mark HALT, notify main thread to finish current job */ + prGlueInfo->ulFlag |= GLUE_FLAG_SUB_MOD_INIT; + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + /* wait main thread finish sub module INIT */ + wait_for_completion_interruptible(&prGlueInfo->rSubModComp); + +#if 0 + if (prGlueInfo->prAdapter->fgIsP2PRegistered) + p2pNetRegister(prGlueInfo); +#endif + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief set sub module exit flag, force TxThread to run sub modle exit +* +* \param[in] prGlueInfo Pointer to struct GLUE_INFO_T +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanSubModExit(P_GLUE_INFO_T prGlueInfo) +{ +#if 0 + if (prGlueInfo->prAdapter->fgIsP2PRegistered) + p2pNetUnregister(prGlueInfo); +#endif + + /* 4 Mark HALT, notify main thread to finish current job */ + prGlueInfo->ulFlag |= GLUE_FLAG_SUB_MOD_EXIT; + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + /* wait main thread finish sub module EXIT */ + wait_for_completion_interruptible(&prGlueInfo->rSubModComp); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief set by sub module, indicate sub module is already inserted +* +* \param[in] rSubModInit, function pointer point to sub module init function +* \param[in] rSubModExit, function pointer point to sub module exit function +* \param[in] eSubModIdx, sub module index +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanSubModRegisterInitExit(SUB_MODULE_INIT rSubModInit, SUB_MODULE_EXIT rSubModExit, ENUM_SUB_MODULE_IDX_T eSubModIdx) +{ + rSubModHandler[eSubModIdx].subModInit = rSubModInit; + rSubModHandler[eSubModIdx].subModExit = rSubModExit; + rSubModHandler[eSubModIdx].fgIsInited = FALSE; +} + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief check wlan is launched or not +* +* \param[in] (none) +* +* \return TRUE, wlan is already started +* FALSE, wlan is not started yet +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanIsLaunched(VOID) +{ + struct net_device *prDev = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + + /* 4 <0> Sanity check */ + ASSERT(u4WlanDevNum <= CFG_MAX_WLAN_DEVICES); + if (u4WlanDevNum == 0) + return FALSE; + + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + + ASSERT(prDev); + if (prDev == NULL) + return FALSE; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + if (prGlueInfo == NULL) + 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 (u4WlanDevNum == 0) + return FALSE; + + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + if (prDev == NULL) + return FALSE; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + if (prGlueInfo == NULL) + return FALSE; + + if (prGlueInfo->prAdapter->fgIsWlanLaunched == FALSE) + return FALSE; + + *prGlueInfoExpAddr = prGlueInfo; + return TRUE; +} + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Release prDev from wlandev_array and free tasklet object related to it. +* +* \param[in] prDev Pointer to struct net_device +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static void wlanClearDevIdx(struct net_device *prDev) +{ + int i; + + ASSERT(prDev); + + for (i = 0; i < CFG_MAX_WLAN_DEVICES; i++) { + if (arWlanDevInfo[i].prDev == prDev) { + arWlanDevInfo[i].prDev = NULL; + u4WlanDevNum--; + } + } + +} /* end of wlanClearDevIdx() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Allocate an unique interface index, net_device::ifindex member for this +* wlan device. Store the net_device in wlandev_array, and initialize +* tasklet object related to it. +* +* \param[in] prDev Pointer to struct net_device +* +* \retval >= 0 The device number. +* \retval -1 Fail to get index. +*/ +/*----------------------------------------------------------------------------*/ +static int wlanGetDevIdx(struct net_device *prDev) +{ + int i; + + ASSERT(prDev); + + for (i = 0; i < CFG_MAX_WLAN_DEVICES; i++) { + if (arWlanDevInfo[i].prDev == (struct net_device *)NULL) { + /* Reserve 2 bytes space to store one digit of + * device number and NULL terminator. + */ + arWlanDevInfo[i].prDev = prDev; + u4WlanDevNum++; + return i; + } + } + + return -1; +} /* end of wlanGetDevIdx() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A method of struct net_device, a primary SOCKET interface to configure +* the interface lively. Handle an ioctl call on one of our devices. +* Everything Linux ioctl specific is done here. Then we pass the contents +* of the ifr->data to the request message handler. +* +* \param[in] prDev Linux kernel netdevice +* +* \param[in] prIfReq Our private ioctl request structure, typed for the generic +* struct ifreq so we can use ptr to function +* +* \param[in] cmd Command ID +* +* \retval 0 The IOCTL command is executed successfully. +* \retval <0 The execution of IOCTL command is failed. +*/ +/*----------------------------------------------------------------------------*/ +int wlanDoIOCTL(struct net_device *prDev, struct ifreq *prIfReq, int i4Cmd) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + int ret = 0; + + DBGLOG(INIT, INFO, "wlanDoIOCTL Cmd= 0x%04x\n", i4Cmd); + /* Verify input parameters for the following functions */ + ASSERT(prDev && prIfReq); + if (!prDev || !prIfReq) { + DBGLOG(INIT, ERROR, "Invalid input data\n"); + return -EINVAL; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + if (!prGlueInfo) { + DBGLOG(INIT, ERROR, "prGlueInfo is NULL\n"); + return -EFAULT; + } + + if (prGlueInfo->u4ReadyFlag == 0) { + DBGLOG(INIT, ERROR, "Adapter is not ready\n"); + return -EINVAL; + } + + if ((i4Cmd >= SIOCIWFIRST) && (i4Cmd < SIOCIWFIRSTPRIV)) { + /* 0x8B00 ~ 0x8BDF, wireless extension region */ + ret = wext_support_ioctl(prDev, prIfReq, i4Cmd); + } else if ((i4Cmd >= SIOCIWFIRSTPRIV) && (i4Cmd < SIOCIWLASTPRIV)) { + /* 0x8BE0 ~ 0x8BFF, private ioctl region */ + ret = priv_support_ioctl(prDev, prIfReq, i4Cmd); + } else if (i4Cmd == SIOCDEVPRIVATE + 1) { + ret = priv_support_driver_cmd(prDev, prIfReq, i4Cmd); + } else { + DBGLOG(INIT, WARN, "Unexpected ioctl command: 0x%04x\n", i4Cmd); + ret = -EOPNOTSUPP; + } + if (ret != 0) + DBGLOG(INIT, WARN, "wlanDoIOCTL Ret err: %d\n", ret); + + 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; +struct net_device *gPrDev; +static BOOLEAN fgIsWorkMcStart = FALSE; +static BOOLEAN fgIsWorkMcEverInit = FALSE; +static struct wireless_dev *gprWdev; + +static UINT_8 wlanNvramBufHandler(PVOID ctx, const CHAR *buf, UINT_16 length) +{ + DBGLOG(INIT, INFO, "buf = %p, length = %u\n", buf, length); + if (buf == NULL || length <= 0 || length > sizeof(g_aucNvram)) + return -EFAULT; + + if (copy_from_user(g_aucNvram, buf, length)) { + DBGLOG(INIT, ERROR, "copy nvram fail\n"); + fgNvramAvailable = FALSE; + return -EINVAL; + } + + fgNvramAvailable = TRUE; + return 0; +} + +static void createWirelessDevice(void) +{ + struct wiphy *prWiphy = NULL; + struct wireless_dev *prWdev = NULL; +#if CFG_SUPPORT_PERSIST_NETDEV + struct net_device *prNetDev = NULL; +#endif + + /* <1.1> Create wireless_dev */ + prWdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (!prWdev) { + DBGLOG(INIT, ERROR, "Allocating memory to wireless_dev context failed\n"); + return; + } + + + /* <1.2> Create wiphy */ + prWiphy = wiphy_new(&mtk_wlan_ops, sizeof(GLUE_INFO_T)); + if (!prWiphy) { + DBGLOG(INIT, ERROR, "Allocating memory to wiphy device failed\n"); + goto free_wdev; + } + + /* <1.3> configure wireless_dev & wiphy */ + prWdev->iftype = NL80211_IFTYPE_STATION; +#if CFG_MULTI_SSID_SCAN + prWiphy->max_scan_ssids = SCN_SSID_MAX_NUM + 1; +#else + prWiphy->max_scan_ssids = 1; +#endif + prWiphy->max_scan_ie_len = 512; +#if CFG_SUPPORT_SCHED_SCN_SSID_SETS + prWiphy->max_sched_scan_ssids = CFG_SCAN_HIDDEN_SSID_MAX_NUM; +#else + prWiphy->max_sched_scan_ssids = CFG_SCAN_SSID_MAX_NUM; +#endif + prWiphy->max_match_sets = CFG_SCAN_SSID_MATCH_MAX_NUM; + prWiphy->max_sched_scan_ie_len = CFG_CFG80211_IE_BUF_LEN; + + /* prWiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); */ + prWiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | + BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO); + + prWiphy->iface_combinations = p_mtk_sta_iface_combos; + prWiphy->n_iface_combinations = mtk_sta_iface_combos_num; + + prWiphy->bands[IEEE80211_BAND_2GHZ] = &mtk_band_2ghz; + /* + * always assign 5Ghz bands here, if the chip is not support 5Ghz, + * bands[IEEE80211_BAND_5GHZ] will be assign to NULL + */ + prWiphy->bands[IEEE80211_BAND_5GHZ] = &mtk_band_5ghz; + prWiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + prWiphy->cipher_suites = mtk_cipher_suites; + prWiphy->n_cipher_suites = ARRAY_SIZE(mtk_cipher_suites); +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE + prWiphy->flags = WIPHY_FLAG_SUPPORTS_FW_ROAM + | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; + /* In kernel 4.12 or newer, + * this is obsoletes - WIPHY_FLAG_SUPPORTS_SCHED_SCAN + */ + prWiphy->max_sched_scan_reqs = 1; +#else + prWiphy->flags = WIPHY_FLAG_SUPPORTS_FW_ROAM + | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL + | WIPHY_FLAG_SUPPORTS_SCHED_SCAN; +#endif +#if CFG_SUPPORT_AAA && CFG_SUPPORT_WPA3 + prWiphy->flags |= WIPHY_FLAG_HAVE_AP_SME; +#endif + prWiphy->regulatory_flags = REGULATORY_CUSTOM_REG; +#if CFG_SUPPORT_TDLS + TDLSEX_WIPHY_FLAGS_INIT(prWiphy->flags); +#endif /* CFG_SUPPORT_TDLS */ + prWiphy->max_remain_on_channel_duration = 500; + prWiphy->mgmt_stypes = mtk_cfg80211_ais_default_mgmt_stypes; +#if CFG_SUPPORT_WPA3 + prWiphy->features |= NL80211_FEATURE_SAE; +#endif + +#if (CFG_SUPPORT_SCAN_RANDOM_MAC && \ + (KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE)) + prWiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; + prWiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR; +#endif + + prWiphy->vendor_commands = mtk_wlan_vendor_ops; + prWiphy->n_vendor_commands = sizeof(mtk_wlan_vendor_ops) / sizeof(struct wiphy_vendor_command); + prWiphy->vendor_events = mtk_wlan_vendor_events; + prWiphy->n_vendor_events = ARRAY_SIZE(mtk_wlan_vendor_events); + + /* <1.4> wowlan support */ +#ifdef CONFIG_PM + prWiphy->wowlan = &mtk_wlan_wowlan_support; +#endif +#ifdef CONFIG_CFG80211_WEXT + /* <1.5> Use wireless extension to replace IOCTL */ + prWiphy->wext = &wext_handler_def; +#endif + + if (wiphy_register(prWiphy) < 0) { + DBGLOG(INIT, ERROR, "wiphy_register error\n"); + goto free_wiphy; + } + prWdev->wiphy = prWiphy; + +#if CFG_SUPPORT_PERSIST_NETDEV + /* <2> allocate and register net_device */ + prNetDev = alloc_netdev_mq(sizeof(P_GLUE_INFO_T), NIC_INF_NAME, NET_NAME_PREDICTABLE, + ether_setup, CFG_MAX_TXQ_NUM); + if (!prNetDev) { + DBGLOG(INIT, ERROR, "Allocating memory to net_device context failed\n"); + goto unregister_wiphy; + } + + *((P_GLUE_INFO_T *) netdev_priv(prNetDev)) = (P_GLUE_INFO_T) wiphy_priv(prWiphy); + + prNetDev->netdev_ops = &wlan_netdev_ops; +#ifdef CONFIG_WIRELESS_EXT + prNetDev->wireless_handlers = &wext_handler_def; +#endif + netif_carrier_off(prNetDev); + netif_tx_stop_all_queues(prNetDev); + + /* <2.1> co-relate with wireless_dev bi-directionally */ + prNetDev->ieee80211_ptr = prWdev; + prWdev->netdev = prNetDev; +#if CFG_TCP_IP_CHKSUM_OFFLOAD + prNetDev->features = NETIF_F_HW_CSUM; +#endif + + /* <2.2> co-relate net device & device tree */ + SET_NETDEV_DEV(prNetDev, wiphy_dev(prWiphy)); + + /* <2.3> register net_device */ + if (register_netdev(prWdev->netdev) < 0) { + DBGLOG(INIT, ERROR, "Register net_device failed\n"); + goto unregister_wiphy; + } +#endif /* CFG_SUPPORT_PERSIST_NETDEV */ + + register_file_buf_handler(wlanNvramBufHandler, (PVOID)NULL, ENUM_BUF_TYPE_NVRAM); + gprWdev = prWdev; + DBGLOG(INIT, INFO, "Create wireless device success\n"); + return; + +#if CFG_SUPPORT_PERSIST_NETDEV +unregister_wiphy: + wiphy_unregister(prWiphy); +#endif +free_wiphy: + wiphy_free(prWiphy); +free_wdev: + kfree(prWdev); +} + +static void destroyWirelessDevice(void) +{ +#if CFG_SUPPORT_PERSIST_NETDEV + unregister_netdev(gprWdev->netdev); + free_netdev(gprWdev->netdev); +#endif + wiphy_unregister(gprWdev->wiphy); + wiphy_free(gprWdev->wiphy); + kfree(gprWdev); + gprWdev = NULL; +} + +static void wlanSetMulticastList(struct net_device *prDev) +{ + gPrDev = prDev; + schedule_delayed_work(&workq, 0); +} + +/* + * FIXME: Since we cannot sleep in the wlanSetMulticastList, we arrange + * another workqueue for sleeping. We don't want to block + * tx_thread, so we can't let tx_thread to do this + */ + +static void wlanSetMulticastListWorkQueue(struct work_struct *work) +{ + + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4PacketFilter = 0; + UINT_32 u4SetInfoLen; + struct net_device *prDev = gPrDev; + + fgIsWorkMcStart = TRUE; + + DBGLOG(INIT, TRACE, "wlanSetMulticastListWorkQueue\n"); + + if (kalHaltLock(KAL_HALT_LOCK_TIMEOUT_NORMAL_CASE)) + return; + if (kalIsHalted()) { + fgIsWorkMcStart = FALSE; + kalHaltUnlock(); + return; + } + + prGlueInfo = (prDev != NULL) ? *((P_GLUE_INFO_T *) netdev_priv(prDev)) : NULL; + ASSERT(prDev); + ASSERT(prGlueInfo); + if (!prDev || !prGlueInfo) { + DBGLOG(INIT, WARN, "abnormal dev or skb: prDev(0x%p), prGlueInfo(0x%p)\n", prDev, prGlueInfo); + fgIsWorkMcStart = FALSE; + kalHaltUnlock(); + return; + } + + if (prDev->flags & IFF_PROMISC) + u4PacketFilter |= PARAM_PACKET_FILTER_PROMISCUOUS; + + if (prDev->flags & IFF_BROADCAST) + u4PacketFilter |= PARAM_PACKET_FILTER_BROADCAST; + + if (prDev->flags & IFF_MULTICAST) { + if ((prDev->flags & IFF_ALLMULTI) || + (netdev_mc_count(prDev) > MAX_NUM_GROUP_ADDR)) { + + u4PacketFilter |= PARAM_PACKET_FILTER_ALL_MULTICAST; + } else { + u4PacketFilter |= PARAM_PACKET_FILTER_MULTICAST; + } + } + + kalHaltUnlock(); + + if (kalIoctl(prGlueInfo, + wlanoidSetCurrentPacketFilter, + &u4PacketFilter, + sizeof(u4PacketFilter), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen) != WLAN_STATUS_SUCCESS) { + fgIsWorkMcStart = FALSE; + DBGLOG(INIT, ERROR, "wlanSetMulticastListWorkQueue kalIoctl u4PacketFilter=%d\n", u4PacketFilter); + return; + } + + if (u4PacketFilter & PARAM_PACKET_FILTER_MULTICAST) { + /* Prepare multicast address list */ + struct netdev_hw_addr *ha; + PUINT_8 prMCAddrList = NULL; + UINT_32 i = 0; + + if (kalHaltLock(KAL_HALT_LOCK_TIMEOUT_NORMAL_CASE)) + return; + if (kalIsHalted()) { + fgIsWorkMcStart = FALSE; + kalHaltUnlock(); + /*DBGLOG(INIT, WARN, "wlanSetMulticastListWorkQueue g_u4HaltFlag=%d\n", g_u4HaltFlag);*/ + return; + } + + prMCAddrList = kalMemAlloc(MAX_NUM_GROUP_ADDR * ETH_ALEN, VIR_MEM_TYPE); + + /* Avoid race condition with kernel net subsystem */ + netif_addr_lock_bh(prDev); + + netdev_for_each_mc_addr(ha, prDev) { + if ((i < MAX_NUM_GROUP_ADDR) && (ha != NULL)) { + memcpy((prMCAddrList + i * ETH_ALEN), ha->addr, ETH_ALEN); + i++; + } + } + + netif_addr_unlock_bh(prDev); + + kalHaltUnlock(); + + kalIoctl(prGlueInfo, + wlanoidSetMulticastList, + prMCAddrList, (i * ETH_ALEN), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + kalMemFree(prMCAddrList, VIR_MEM_TYPE, MAX_NUM_GROUP_ADDR * ETH_ALEN); + } + + fgIsWorkMcStart = FALSE; + +} /* end of wlanSetMulticastList() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate scheduled scan has been stopped +* +* \param[in] +* prGlueInfo +* +* \return +* None +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanSchedScanStoppedWorkQueue(struct work_struct *work) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + struct net_device *prDev = gPrDev; + + prGlueInfo = (prDev != NULL) ? *((P_GLUE_INFO_T *) netdev_priv(prDev)) : NULL; + if (!prGlueInfo) { + DBGLOG(SCN, ERROR, "prGlueInfo == NULL unexpected\n"); + return; + } + + /* 2. indication to cfg80211 */ + /* 20150205 change cfg80211_sched_scan_stopped to work queue due to sched_scan_mtx dead lock issue */ +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE + cfg80211_sched_scan_stopped(priv_to_wiphy(prGlueInfo), 0); +#else + cfg80211_sched_scan_stopped(priv_to_wiphy(prGlueInfo)); +#endif + DBGLOG(SCN, INFO, + "cfg80211_sched_scan_stopped event send done\n"); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is TX entry point of NET DEVICE. +* +* \param[in] prSkb Pointer of the sk_buff to be sent +* \param[in] prDev Pointer to struct net_device +* +* \retval NETDEV_TX_OK - on success. +* \retval NETDEV_TX_BUSY - on failure, packet will be discarded by upper layer. +*/ +/*----------------------------------------------------------------------------*/ +#define STATS_ENV_TX_DETECT_TIMEOUT_SEC 20 + +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; + OS_SYSTIME rCurTime; + UINT_32 u4NumPending; + UINT_32 u4SkbLen = 0; +#if (CFG_SUPPORT_TDLS_DBG == 1) + UINT16 u2Identifier = 0; +#endif + +#if CFG_BOW_TEST + UINT_32 i; +#endif + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prSkb); + ASSERT(prDev); + ASSERT(prGlueInfo); + prGlueInfo->u8SkbToDriver++; + +#if (CFG_SUPPORT_TDLS_DBG == 1) + { + UINT8 *pkt = prSkb->data; + + if ((*(pkt + 12) == 0x08) && (*(pkt + 13) == 0x00)) { + /* ip */ + u2Identifier = ((*(pkt + 18)) << 8) | (*(pkt + 19)); + /* u2TdlsTxSeq[u4TdlsTxSeqId ++] = u2Identifier; */ + DBGLOG(INIT, INFO, " %d\n", u2Identifier); + } + } +#endif + /* check if WiFi is halt */ + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(INIT, INFO, "GLUE_FLAG_HALT skip tx\n"); + dev_kfree_skb(prSkb); + prGlueInfo->u8SkbFreed++; + return NETDEV_TX_OK; + } +#if CFG_SUPPORT_HOTSPOT_2_0 + if (prGlueInfo->fgIsDad) { + /* kalPrint("[Passpoint R2] Due to ipv4_dad...TX is forbidden\n"); */ + dev_kfree_skb(prSkb); + prGlueInfo->u8SkbFreed++; + return NETDEV_TX_OK; + } + if (prGlueInfo->fgIs6Dad) { + /* kalPrint("[Passpoint R2] Due to ipv6_dad...TX is forbidden\n"); */ + dev_kfree_skb(prSkb); + prGlueInfo->u8SkbFreed++; + return NETDEV_TX_OK; + } +#endif + + STATS_TX_TIME_ARRIVE(prSkb); + prQueueEntry = (P_QUE_ENTRY_T) GLUE_GET_PKT_QUEUE_ENTRY(prSkb); + prTxQueue = &prGlueInfo->rTxQueue; + +#if CFG_BOW_TEST + DBGLOG(BOW, TRACE, "sk_buff->len: %d\n", prSkb->len); + DBGLOG(BOW, TRACE, "sk_buff->data_len: %d\n", prSkb->data_len); + DBGLOG(BOW, TRACE, "sk_buff->data:\n"); + + for (i = 0; i < prSkb->len; i++) { + DBGLOG(BOW, TRACE, "%4x", prSkb->data[i]); + + if ((i + 1) % 16 == 0) + DBGLOG(BOW, TRACE, "\n"); + } + + DBGLOG(BOW, TRACE, "\n"); +#endif + + u4SkbLen = prSkb->len; + + if (wlanProcessSecurityFrame(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb) == FALSE) { + + /* non-1x packets */ + +#if CFG_DBG_GPIO_PINS + { + /* TX request from OS */ + mtk_wcn_stp_debug_gpio_assert(IDX_TX_REQ, DBG_TIE_LOW); + kalUdelay(1); + mtk_wcn_stp_debug_gpio_assert(IDX_TX_REQ, DBG_TIE_HIGH); + } +#endif + + u2QueueIdx = skb_get_queue_mapping(prSkb); + ASSERT(u2QueueIdx < CFG_MAX_TXQ_NUM); + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + GLUE_SET_PKT_ARRIVAL_TIME(prSkb, kalGetTimeTick()); +#endif + wlanFillTimestamp(prGlueInfo->prAdapter, (PVOID)prSkb, PHASE_XMIT_RCV); + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingFrameNum); + if (u2QueueIdx < CFG_MAX_TXQ_NUM) + GLUE_INC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][u2QueueIdx]); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_INSERT_TAIL(prTxQueue, prQueueEntry); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); +/* GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingFrameNum); */ +/* GLUE_INC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][u2QueueIdx]); */ + + if (u2QueueIdx < CFG_MAX_TXQ_NUM) { + if (prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][u2QueueIdx] >= + CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD) { + DBGLOG(TX, INFO, "netif_stop_subqueue for wlan0, Queue len: %d\n", + prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][u2QueueIdx]); + + netif_stop_subqueue(prDev, u2QueueIdx); + +#if (CONF_HIF_LOOPBACK_AUTO == 1) + prGlueInfo->rHifInfo.HifLoopbkFlg |= 0x01; +#endif /* CONF_HIF_LOOPBACK_AUTO */ + } + } + } else { + /* printk("is security frame\n"); */ + + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum); + } + + DBGLOG(TX, EVENT, "\n+++++ pending frame %d len = %d +++++\n", prGlueInfo->i4TxPendingFrameNum, u4SkbLen); + prGlueInfo->rNetDevStats.tx_bytes += u4SkbLen; + prGlueInfo->rNetDevStats.tx_packets++; + if (netif_carrier_ok(prDev)) + kalPerMonStart(prGlueInfo); + + /* set GLUE_FLAG_TXREQ_BIT */ + + /* pr->u4Flag |= GLUE_FLAG_TXREQ; */ + /* wake_up_interruptible(&prGlueInfo->waitq); */ + kalSetEvent(prGlueInfo); + + /* Maybe the Packet is pending on queue and on TC resource */ + u4NumPending = prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][0] + + prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][1] + + prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][2] + + prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][3]; + + GET_CURRENT_SYSTIME(&rCurTime); + if (CHECK_FOR_TIMEOUT(rCurTime, prGlueInfo->prAdapter->rStasEnvReportDetectTime, + SEC_TO_SYSTIME(STATS_ENV_TX_DETECT_TIMEOUT_SEC)) && u4NumPending > 0) { + DBGLOG(TX, WARN, "%s rCurTime=%u PendingPKT Num(%u %u %u %u)TC4 resource (%d %d %d %d %d)\n", + __func__, rCurTime, + prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][0], + prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][1], + prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][2], + prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][3], + prGlueInfo->prAdapter->rTxCtrl.rTc.aucFreeBufferCount[TC0_INDEX], + prGlueInfo->prAdapter->rTxCtrl.rTc.aucFreeBufferCount[TC1_INDEX], + prGlueInfo->prAdapter->rTxCtrl.rTc.aucFreeBufferCount[TC2_INDEX], + prGlueInfo->prAdapter->rTxCtrl.rTc.aucFreeBufferCount[TC3_INDEX], + prGlueInfo->prAdapter->rTxCtrl.rTc.aucFreeBufferCount[TC4_INDEX]); + } + + /* For Linux, we'll always return OK FLAG, because we'll free this skb by ourself */ + return NETDEV_TX_OK; +} /* end of wlanHardStartXmit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A method of struct net_device, to get the network interface statistical +* information. +* +* Whenever an application needs to get statistics for the interface, this method +* is called. This happens, for example, when ifconfig or netstat -i is run. +* +* \param[in] prDev Pointer to struct net_device. +* +* \return net_device_stats buffer pointer. +*/ +/*----------------------------------------------------------------------------*/ +struct net_device_stats *wlanGetStats(IN struct net_device *prDev) +{ + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + +#if 0 + WLAN_STATUS rStatus; + UINT_32 u4XmitError = 0; + UINT_32 u4XmitOk = 0; + UINT_32 u4RecvError = 0; + UINT_32 u4RecvOk = 0; + UINT_32 u4BufLen; + + ASSERT(prDev); + + /* @FIX ME: need a more clear way to do this */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryXmitError, &u4XmitError, sizeof(UINT_32), TRUE, TRUE, TRUE, &u4BufLen); + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryXmitOk, &u4XmitOk, sizeof(UINT_32), TRUE, TRUE, TRUE, &u4BufLen); + rStatus = kalIoctl(prGlueInfo, wlanoidQueryRcvOk, &u4RecvOk, sizeof(UINT_32), TRUE, TRUE, TRUE, &u4BufLen); + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryRcvError, &u4RecvError, sizeof(UINT_32), TRUE, TRUE, TRUE, &u4BufLen); + prGlueInfo->rNetDevStats.rx_packets = u4RecvOk; + prGlueInfo->rNetDevStats.tx_packets = u4XmitOk; + prGlueInfo->rNetDevStats.tx_errors = u4XmitError; + prGlueInfo->rNetDevStats.rx_errors = u4RecvError; + /* prGlueInfo->rNetDevStats.rx_bytes = rCustomNetDevStats.u4RxBytes; */ + /* prGlueInfo->rNetDevStats.tx_bytes = rCustomNetDevStats.u4TxBytes; */ + /* prGlueInfo->rNetDevStats.rx_errors = rCustomNetDevStats.u4RxErrors; */ + /* prGlueInfo->rNetDevStats.multicast = rCustomNetDevStats.u4Multicast; */ +#endif + /* prGlueInfo->rNetDevStats.rx_packets = 0; */ + /* prGlueInfo->rNetDevStats.tx_packets = 0; */ + prGlueInfo->rNetDevStats.tx_errors = 0; + prGlueInfo->rNetDevStats.rx_errors = 0; + /* prGlueInfo->rNetDevStats.rx_bytes = 0; */ + /* prGlueInfo->rNetDevStats.tx_bytes = 0; */ + prGlueInfo->rNetDevStats.rx_errors = 0; + prGlueInfo->rNetDevStats.multicast = 0; + + return &prGlueInfo->rNetDevStats; + +} /* end of wlanGetStats() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A function for prDev->init +* +* \param[in] prDev Pointer to struct net_device. +* +* \retval 0 The execution of wlanInit succeeds. +* \retval -ENXIO No such device. +*/ +/*----------------------------------------------------------------------------*/ +static int wlanInit(struct net_device *prDev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + if (fgIsWorkMcEverInit == FALSE) { + if (!prDev) + return -ENXIO; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + INIT_DELAYED_WORK(&workq, wlanSetMulticastListWorkQueue); + + /* 20150205 work queue for sched_scan */ + INIT_DELAYED_WORK(&sched_workq, wlanSchedScanStoppedWorkQueue); + + fgIsWorkMcEverInit = TRUE; + } + + return 0; /* success */ +} /* end of wlanInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A function for prDev->uninit +* +* \param[in] prDev Pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static void wlanUninit(struct net_device *prDev) +{ + +} /* end of wlanUninit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A function for prDev->open +* +* \param[in] prDev Pointer to struct net_device. +* +* \retval 0 The execution of wlanOpen succeeds. +* \retval < 0 The execution of wlanOpen failed. +*/ +/*----------------------------------------------------------------------------*/ +static int wlanOpen(struct net_device *prDev) +{ + ASSERT(prDev); + + netif_tx_start_all_queues(prDev); + + return 0; /* success */ +} /* end of wlanOpen() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A function for prDev->stop +* +* \param[in] prDev Pointer to struct net_device. +* +* \retval 0 The execution of wlanStop succeeds. +* \retval < 0 The execution of wlanStop failed. +*/ +/*----------------------------------------------------------------------------*/ +static int wlanStop(struct net_device *prDev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + 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) { + kalCfg80211ScanDone(prGlueInfo->prScanRequest, TRUE); + prGlueInfo->prScanRequest = NULL; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + netif_tx_stop_all_queues(prDev); + + return 0; /* success */ +} /* end of wlanStop() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Update channel table for cfg80211 based on current country domain + * + * \param[in] prGlueInfo Pointer to glue info + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +VOID wlanUpdateChannelTable(P_GLUE_INFO_T prGlueInfo) +{ + UINT_8 i, j; + UINT_8 ucNumOfChannel; + RF_CHANNEL_INFO_T aucChannelList[ARRAY_SIZE(mtk_2ghz_channels) + ARRAY_SIZE(mtk_5ghz_channels)]; + + /* 1. Disable all channels */ + for (i = 0; i < ARRAY_SIZE(mtk_2ghz_channels); i++) { + mtk_2ghz_channels[i].flags |= IEEE80211_CHAN_DISABLED; + mtk_2ghz_channels[i].orig_flags |= IEEE80211_CHAN_DISABLED; + } + + for (i = 0; i < ARRAY_SIZE(mtk_5ghz_channels); i++) { + mtk_5ghz_channels[i].flags |= IEEE80211_CHAN_DISABLED; + mtk_5ghz_channels[i].orig_flags |= IEEE80211_CHAN_DISABLED; + } + + /* 2. Get current domain channel list */ + rlmDomainGetChnlList(prGlueInfo->prAdapter, + BAND_NULL, FALSE, + ARRAY_SIZE(mtk_2ghz_channels) + ARRAY_SIZE(mtk_5ghz_channels), + &ucNumOfChannel, aucChannelList); + + /* 3. Enable specific channel based on domain channel list */ + for (i = 0; i < ucNumOfChannel; i++) { + switch (aucChannelList[i].eBand) { + case BAND_2G4: + for (j = 0; j < ARRAY_SIZE(mtk_2ghz_channels); j++) { + if (mtk_2ghz_channels[j].hw_value == aucChannelList[i].ucChannelNum) { + mtk_2ghz_channels[j].flags &= ~IEEE80211_CHAN_DISABLED; + mtk_2ghz_channels[j].orig_flags &= ~IEEE80211_CHAN_DISABLED; + break; + } + } + break; + + case BAND_5G: + for (j = 0; j < ARRAY_SIZE(mtk_5ghz_channels); j++) { + if (mtk_5ghz_channels[j].hw_value == aucChannelList[i].ucChannelNum) { + mtk_5ghz_channels[j].flags &= ~IEEE80211_CHAN_DISABLED; + mtk_5ghz_channels[j].orig_flags &= ~IEEE80211_CHAN_DISABLED; + mtk_5ghz_channels[j].dfs_state = + (aucChannelList[i].eDFS) ? + NL80211_DFS_USABLE : + NL80211_DFS_UNAVAILABLE; + break; + } + } + break; + + default: + DBGLOG(INIT, WARN, "Unknown band %d\n", aucChannelList[i].eBand); + break; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Register the device to the kernel and return the index. +* +* \param[in] prDev Pointer to struct net_device. +* +* \retval 0 The execution of wlanNetRegister succeeds. +* \retval < 0 The execution of wlanNetRegister failed. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 wlanNetRegister(struct wireless_dev *prWdev) +{ + P_GLUE_INFO_T prGlueInfo; + INT_32 i4DevIdx = -1; + int ret = 0; + + ASSERT(prWdev); + + do { + if (!prWdev) + break; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); + i4DevIdx = wlanGetDevIdx(prWdev->netdev); + if (i4DevIdx < 0) { + DBGLOG(INIT, ERROR, "net_device number exceed!\n"); + break; + } + +#if !CFG_SUPPORT_PERSIST_NETDEV + ret = register_netdev(prWdev->netdev); + if (ret < 0) { + DBGLOG(INIT, ERROR, "Register net_device failed, ret = %d\n", ret); + + wlanClearDevIdx(prWdev->netdev); + i4DevIdx = -1; + } +#endif + if (i4DevIdx != -1) + prGlueInfo->fgIsRegistered = TRUE; + + } while (FALSE); + + return i4DevIdx; /* success */ +} /* end of wlanNetRegister() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief A method of struct net_device, to set the randomized mac address + * + * This method is called before Wifi Framework requests a new conenction with + * enabled feature "Connected Random Mac". + * + * \param[in] ndev Pointer to struct net_device. + * \param[in] addr Randomized Mac address passed from WIFI framework. + * + * \return int. + */ +/*----------------------------------------------------------------------------*/ +static int wlanSetMacAddress(struct net_device *ndev, void *addr) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + P_BSS_INFO_T prAisBssInfo = NULL; + struct sockaddr *sa = NULL; + + /********************************************************************** + * Check if kernel passes valid data to us * + ********************************************************************** + */ + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(ndev)); + if (!ndev || !addr || !prGlueInfo) { + DBGLOG(INIT, ERROR, + "Set macaddr with ndev(%d), glue(%d) and addr(%d)\n", + (ndev == NULL) ? 0 : 1, (prGlueInfo == NULL) ? 0 : 1, + (addr == NULL) ? 0 : 1); + return WLAN_STATUS_INVALID_DATA; + } + prAdapter = prGlueInfo->prAdapter; + if (!prAdapter) { + DBGLOG(INIT, ERROR, "Invalid prAdapter\n"); + return WLAN_STATUS_INVALID_DATA; + } + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + if (!prAdapter) { + DBGLOG(INIT, ERROR, "Invalid prAisBssInfo\n"); + return WLAN_STATUS_INVALID_DATA; + } + + /********************************************************************** + * 1. Change OwnMacAddr which will be updated to FW through * + * rlmActivateNetwork later. * + * 2. Change dev_addr stored in kernel to notify framework that the * + * mac addr has been changed and what the new value is. * + ********************************************************************** + */ + sa = (struct sockaddr *)addr; + + COPY_MAC_ADDR(prAisBssInfo->aucOwnMacAddr, sa->sa_data); + COPY_MAC_ADDR(prGlueInfo->prDevHandler->dev_addr, sa->sa_data); + DBGLOG(INIT, INFO, "Set connect random macaddr to " MACSTR ".\n", + MAC2STR(prAisBssInfo->aucOwnMacAddr)); + + return WLAN_STATUS_SUCCESS; +} /* end of wlanSetMacAddr() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Unregister the device from the kernel +* +* \param[in] prWdev Pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID wlanNetUnregister(struct wireless_dev *prWdev) +{ + P_GLUE_INFO_T prGlueInfo; + + if (!prWdev) { + DBGLOG(INIT, ERROR, "wlanNetUnregister: The device context is NULL\n"); + return; + } + DBGLOG(INIT, TRACE, "unregister net_dev(0x%p)\n", prWdev->netdev); + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); + wlanClearDevIdx(prWdev->netdev); +#if !CFG_SUPPORT_PERSIST_NETDEV + unregister_netdev(prWdev->netdev); +#endif + prGlueInfo->fgIsRegistered = FALSE; + + DBGLOG(INIT, INFO, "unregister wireless_dev(0x%p), ifindex=%d\n", prWdev, prWdev->netdev->ifindex); + +} /* end of wlanNetUnregister() */ + +static const struct net_device_ops wlan_netdev_ops = { + .ndo_open = wlanOpen, + .ndo_stop = wlanStop, + .ndo_set_rx_mode = wlanSetMulticastList, + .ndo_get_stats = wlanGetStats, + .ndo_do_ioctl = wlanDoIOCTL, + .ndo_start_xmit = wlanHardStartXmit, + .ndo_init = wlanInit, + .ndo_uninit = wlanUninit, + .ndo_select_queue = wlanSelectQueue, + .ndo_set_mac_address = wlanSetMacAddress, +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A method for creating Linux NET4 struct net_device object and the +* private data(prGlueInfo and prAdapter). Setup the IO address to the HIF. +* Assign the function pointer to the net_device object +* +* \param[in] pvData Memory address for the device +* +* \retval Not null The wireless_dev object. +* \retval NULL Fail to create wireless_dev object +*/ +/*----------------------------------------------------------------------------*/ +static struct lock_class_key rSpinKey[SPIN_LOCK_NUM]; +static struct wireless_dev *wlanNetCreate(PVOID pvData) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + struct wireless_dev *prWdev = gprWdev; + UINT_32 i; + struct device *prDev; + + if (!prWdev) { + DBGLOG(INIT, ERROR, "Allocating memory to wireless_dev context failed\n"); + return NULL; + } + /* 4 <1> co-relate wiphy & prDev */ +#if MTK_WCN_HIF_SDIO + mtk_wcn_hif_sdio_get_dev(*((MTK_WCN_HIF_SDIO_CLTCTX *) pvData), &prDev); +#else + /* prDev = &((struct sdio_func *) pvData)->dev; //samp */ + prDev = pvData; /* samp */ +#endif + if (!prDev) + DBGLOG(INIT, WARN, "unable to get struct dev for wlan\n"); + /* + * don't set prDev as parent of wiphy->dev, because we have done device_add + * in driver init. if we set parent here, parent will be not able to know this child, + * and may occurs a KE in device_shutdown, to free wiphy->dev, because his parent + * has been freed. + */ + /*set_wiphy_dev(prWdev->wiphy, prDev);*/ + +#if !CFG_SUPPORT_PERSIST_NETDEV + /* 4 <3> Initialize Glue structure */ + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); + kalMemZero(prGlueInfo, sizeof(GLUE_INFO_T)); + /* 4 <3.1> Create net device */ + prGlueInfo->prDevHandler = alloc_netdev_mq(sizeof(P_GLUE_INFO_T), NIC_INF_NAME, + NET_NAME_PREDICTABLE, ether_setup, CFG_MAX_TXQ_NUM); + + /* Device can help us to save at most 3000 packets, after we stopped queue */ + if (prGlueInfo->prDevHandler != NULL) + prGlueInfo->prDevHandler->tx_queue_len = 3000; + if (!prGlueInfo->prDevHandler) { + DBGLOG(INIT, ERROR, "Allocating memory to net_device context failed\n"); + return NULL; + } + DBGLOG(INIT, INFO, "net_device prDev(0x%p) allocated ifindex=%d\n", + prGlueInfo->prDevHandler, prGlueInfo->prDevHandler->ifindex); + + /* 4 <3.1.1> Initialize net device variables */ + *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->prDevHandler)) = prGlueInfo; + + prGlueInfo->prDevHandler->netdev_ops = &wlan_netdev_ops; +#ifdef CONFIG_WIRELESS_EXT + prGlueInfo->prDevHandler->wireless_handlers = &wext_handler_def; +#endif + netif_carrier_off(prGlueInfo->prDevHandler); + netif_tx_stop_all_queues(prGlueInfo->prDevHandler); + + /* 4 <3.1.2> co-relate with wiphy bi-directionally */ + prGlueInfo->prDevHandler->ieee80211_ptr = prWdev; +#if CFG_TCP_IP_CHKSUM_OFFLOAD + prGlueInfo->prDevHandler->features = NETIF_F_HW_CSUM; +#endif + prWdev->netdev = prGlueInfo->prDevHandler; + + /* 4 <3.1.3> co-relate net device & prDev */ + /*SET_NETDEV_DEV(prGlueInfo->prDevHandler, wiphy_dev(prWdev->wiphy));*/ + SET_NETDEV_DEV(prGlueInfo->prDevHandler, prDev); +#else /* CFG_SUPPORT_PERSIST_NETDEV */ + prGlueInfo->prDevHandler = gprWdev->netdev; +#endif /* CFG_SUPPORT_PERSIST_NETDEV */ + + /* 4 <3.2> Initialize Glue variables */ + prGlueInfo->eParamMediaStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; + prGlueInfo->fgIsMacAddrOverride = FALSE; + prGlueInfo->fgIsRegistered = FALSE; + prGlueInfo->prScanRequest = NULL; + prGlueInfo->puScanChannel = NULL; + + /*Full2Partial*/ + /*init update full scan to partial scan varable*/ + prGlueInfo->u4LastFullScanTime = 0; + prGlueInfo->ucTrScanType = 0; + kalMemSet(prGlueInfo->ucChannelNum, 0, FULL_SCAN_MAX_CHANNEL_NUM); + prGlueInfo->puFullScan2PartialChannel = NULL; + +#if CFG_SUPPORT_HOTSPOT_2_0 + /* Init DAD */ + prGlueInfo->fgIsDad = FALSE; + prGlueInfo->fgIs6Dad = FALSE; + kalMemZero(prGlueInfo->aucDADipv4, 4); + kalMemZero(prGlueInfo->aucDADipv6, 16); +#endif + + init_completion(&prGlueInfo->rScanComp); + init_completion(&prGlueInfo->rHaltComp); + init_completion(&prGlueInfo->rPendComp); +#if CFG_SUPPORT_MULTITHREAD + init_completion(&prGlueInfo->rRxHaltComp); +#endif +#if CFG_ENABLE_WIFI_DIRECT + init_completion(&prGlueInfo->rP2pReq); + init_completion(&prGlueInfo->rSubModComp); +#endif +#if CFG_SUPPORT_NCHO + init_completion(&prGlueInfo->rAisChGrntComp); +#endif + + /* initialize timer for OID timeout checker */ + kalOsTimerInitialize(prGlueInfo, kalTimeoutHandler); + + for (i = 0; i < SPIN_LOCK_NUM; i++) { + spin_lock_init(&prGlueInfo->rSpinLock[i]); + lockdep_set_class(&prGlueInfo->rSpinLock[i], &rSpinKey[i]); + } + + /* initialize semaphore for ioctl */ + sema_init(&prGlueInfo->ioctl_sem, 1); + + glSetHifInfo(prGlueInfo, (ULONG) pvData); + + /* 4 <8> Init Queues */ + init_waitqueue_head(&prGlueInfo->waitq); +#if CFG_SUPPORT_MULTITHREAD + init_waitqueue_head(&prGlueInfo->waitq_rx); +#endif + QUEUE_INITIALIZE(&prGlueInfo->rCmdQueue); + QUEUE_INITIALIZE(&prGlueInfo->rTxQueue); + + /* 4 <4> Create Adapter structure */ + prGlueInfo->prAdapter = (P_ADAPTER_T) wlanAdapterCreate(prGlueInfo); + + if (!prGlueInfo->prAdapter) { + DBGLOG(INIT, ERROR, "Allocating memory to adapter failed\n"); + return NULL; + } + KAL_WAKE_LOCK_INIT(prAdapter, prGlueInfo->rAhbIsrWakeLock, "WLAN AHB ISR"); + +#if CFG_SUPPORT_MULTITHREAD + /*Check wake_lock is available, maybe wake_lock was un-released before using it.*/ + if (KAL_WAKE_LOCK_ACTIVE(prAdapter, &prGlueInfo->rTimeoutWakeLock) != 0) + DBGLOG(INIT, ERROR, "rTimeoutWakeLock = %d is invalid.\n" + , KAL_WAKE_LOCK_ACTIVE(prAdapter, &prGlueInfo->rTimeoutWakeLock)); + + KAL_WAKE_LOCK_INIT(prAdapter, prGlueInfo->rTimeoutWakeLock, "Wlan Timeout"); + DBGLOG(INIT, INFO, "rTimeoutWakeLock init addr=%p\n", &prGlueInfo->rTimeoutWakeLock); +#endif +#if CFG_SUPPORT_PERSIST_NETDEV + dev_open(prGlueInfo->prDevHandler); + netif_carrier_off(prGlueInfo->prDevHandler); + netif_tx_stop_all_queues(prGlueInfo->prDevHandler); +#endif + + return prWdev; +} /* end of wlanNetCreate() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Destroying the struct net_device object and the private data. +* +* \param[in] prWdev Pointer to struct wireless_dev. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID wlanNetDestroy(struct wireless_dev *prWdev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prWdev); + + if (!prWdev) { + DBGLOG(INIT, ERROR, "wlanNetDestroy: The device context is NULL\n"); + return; + } + + /* prGlueInfo is allocated with net_device */ + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); + ASSERT(prGlueInfo); + + /* destroy kal OS timer */ + kalCancelTimer(prGlueInfo); + + glClearHifInfo(prGlueInfo); + + wlanAdapterDestroy(prGlueInfo->prAdapter); + prGlueInfo->prAdapter = NULL; + +#if CFG_SUPPORT_PERSIST_NETDEV + /* take the net_device to down state */ + dev_close(prGlueInfo->prDevHandler); +#else + /* Free net_device and private data prGlueInfo, which are allocated by alloc_netdev(). */ + free_netdev(prWdev->netdev); +#endif + + /* gPrDev is assigned by prGlueInfo->prDevHandler, + * set NULL to this global variable. + */ + gPrDev = NULL; +} /* end of wlanNetDestroy() */ + +#ifndef CONFIG_X86 +UINT_8 g_aucBufIpAddr[32] = { 0 }; +static void wlanNotifyFwSuspend(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgSuspend) +{ + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_32 u4SetInfoLen; + + rStatus = kalIoctl(prGlueInfo, + wlanoidNotifyFwSuspend, + (PVOID)&fgSuspend, + sizeof(fgSuspend), + FALSE, + FALSE, + TRUE, + FALSE, + &u4SetInfoLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "wlanNotifyFwSuspend fail\n"); +} + +void wlanHandleSystemSuspend(void) +{ + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + struct net_device *prDev = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_8 ip[4] = { 0 }; + UINT_32 u4NumIPv4 = 0; +#ifdef CONFIG_IPV6 + UINT_8 ip6[16] = { 0 }; /* FIX ME: avoid to allocate large memory in stack */ + UINT_32 u4NumIPv6 = 0; +#endif + UINT_32 i; + P_PARAM_NETWORK_ADDRESS_IP prParamIpAddr; +#if CFG_SUPPORT_DROP_MC_PACKET + UINT_32 u4PacketFilter = 0; + UINT_32 u4SetInfoLen = 0; +#endif + DBGLOG(INIT, INFO, "******wlan System Suspend*******.\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; + + fgIsUnderSuspend = true; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + +#if CFG_SUPPORT_DROP_MC_PACKET + /* new filter should not include p2p mask */ +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + u4PacketFilter = prGlueInfo->prAdapter->u4OsPacketFilter & (~PARAM_PACKET_FILTER_P2P_MASK); +#endif + if (kalIoctl(prGlueInfo, + wlanoidSetCurrentPacketFilter, + &u4PacketFilter, + sizeof(u4PacketFilter), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "set packet filter failed.\n"); + } +#endif + 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 available.\n"); + goto notify_suspend; + } + kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip)); + + /* todo: traverse between list to find whole sets of IPv4 addresses */ + if (!((ip[0] == 0) && (ip[1] == 0) && (ip[2] == 0) && (ip[3] == 0))) + u4NumIPv4++; +#ifdef CONFIG_IPV6 + if (!prDev || !(prDev->ip6_ptr) || + !((struct in_device *)(prDev->ip6_ptr))->ifa_list || + !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))) { + DBGLOG(INIT, INFO, "ipv6 is not available.\n"); + goto notify_suspend; + } + kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6)); + DBGLOG(INIT, INFO, "ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n", + ip6[0], ip6[1], ip6[2], ip6[3], + ip6[4], ip6[5], ip6[6], ip6[7], + ip6[8], ip6[9], ip6[10], ip6[11], ip6[12], ip6[13], ip6[14], ip6[15] + ); + + /* todo: traverse between list to find whole sets of IPv6 addresses */ + if (!((ip6[0] == 0) && (ip6[1] == 0) && (ip6[2] == 0) && (ip6[3] == 0) && (ip6[4] == 0) && (ip6[5] == 0))) { + /* Do nothing */ + /* u4NumIPv6++; */ + } +#endif + + /* <7> set up the ARP filter */ + { + UINT_32 u4SetInfoLen = 0; + UINT_32 u4Len = OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress); + P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST) g_aucBufIpAddr; + P_PARAM_NETWORK_ADDRESS prParamNetAddr = prParamNetAddrList->arAddress; + + kalMemZero(g_aucBufIpAddr, sizeof(g_aucBufIpAddr)); + + prParamNetAddrList->u4AddressCount = u4NumIPv4; +#ifdef CONFIG_IPV6 + prParamNetAddrList->u4AddressCount += u4NumIPv6; +#endif + prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + for (i = 0; i < u4NumIPv4; i++) { + prParamNetAddr->u2AddressLength = sizeof(PARAM_NETWORK_ADDRESS_IP); /* 4;; */ + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + prParamIpAddr = (P_PARAM_NETWORK_ADDRESS_IP) prParamNetAddr->aucAddress; + kalMemCopy(&prParamIpAddr->in_addr, ip, sizeof(ip)); + prParamNetAddr = + (P_PARAM_NETWORK_ADDRESS) ((ULONG) prParamNetAddr + sizeof(PARAM_NETWORK_ADDRESS)); + u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(PARAM_NETWORK_ADDRESS); + } +/* u4NumIPv6 never accumulate + * #ifdef CONFIG_IPV6 + * for (i = 0; i < u4NumIPv6; i++) { + * prParamNetAddr->u2AddressLength = 6; + * prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + * kalMemCopy(prParamNetAddr->aucAddress, ip6, sizeof(ip6)); + * prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prParamNetAddr + sizeof(ip6)); + * u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip6); + * } + * #endif + */ + ASSERT(u4Len <= sizeof(g_aucBufIpAddr)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNetworkAddress, + (PVOID) prParamNetAddrList, u4Len, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + } + +notify_suspend: + DBGLOG(INIT, INFO, "IP: %d.%d.%d.%d, rStatus: %u\n", ip[0], ip[1], ip[2], ip[3], rStatus); + wlanNotifyFwSuspend(prGlueInfo, TRUE); +} + +void wlanHandleSystemResume(void) +{ + struct net_device *prDev = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_8 ip[4] = { 0 }; +#ifdef CONFIG_IPV6 + UINT_8 ip6[16] = { 0 }; /* FIX ME: avoid to allocate large memory in stack */ +#endif + EVENT_AIS_BSS_INFO_T rParam; + UINT_32 u4BufLen = 0; +#if CFG_SUPPORT_DROP_MC_PACKET + UINT_32 u4PacketFilter = 0; + UINT_32 u4SetInfoLen = 0; +#endif + DBGLOG(INIT, INFO, "************wlan System Resume.\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); */ + + fgIsUnderSuspend = false; + + if (!prDev) { + DBGLOG(INIT, INFO, "prDev == NULL!!!\n"); + return; + } + /* <3> acquire the prGlueInfo */ + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + +#if CFG_SUPPORT_DROP_MC_PACKET + /* new filter should not include p2p mask */ +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + u4PacketFilter = prGlueInfo->prAdapter->u4OsPacketFilter & (~PARAM_PACKET_FILTER_P2P_MASK); +#endif + if (kalIoctl(prGlueInfo, + wlanoidSetCurrentPacketFilter, + &u4PacketFilter, + sizeof(u4PacketFilter), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "set packet filter failed.\n"); + } +#endif + /* + * We will receive the event in rx, we will check if the status is the same in driver + * and FW, if not the same, trigger disconnetion procedure. + */ + + kalMemZero(&rParam, sizeof(EVENT_AIS_BSS_INFO_T)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryBSSInfo, + &rParam, sizeof(EVENT_AIS_BSS_INFO_T), TRUE, TRUE, TRUE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, ERROR, "Query BSSinfo fail 0x%x!!\n", rStatus); + + /* <2> get the IPv4 address */ + if (!(prDev->ip_ptr) || + !((struct in_device *)(prDev->ip_ptr))->ifa_list || + !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))) { + DBGLOG(INIT, INFO, "ip is not avalible.\n"); + + rStatus = WLAN_STATUS_FAILURE; + + goto notify_resume; + } + /* <4> copy the IPv4 address */ + kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip)); + +#ifdef CONFIG_IPV6 + /* <5> get the IPv6 address */ + if (!prDev || !(prDev->ip6_ptr) || + !((struct in_device *)(prDev->ip6_ptr))->ifa_list || + !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))) { + DBGLOG(INIT, INFO, "ipv6 is not avalible.\n"); + + rStatus = WLAN_STATUS_FAILURE; + + goto notify_resume; + } + /* <6> copy the IPv6 address */ + kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6)); + DBGLOG(INIT, INFO, "ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n", + ip6[0], ip6[1], ip6[2], ip6[3], + ip6[4], ip6[5], ip6[6], ip6[7], + ip6[8], ip6[9], ip6[10], ip6[11], ip6[12], ip6[13], ip6[14], ip6[15] + ); +#endif + /* <7> clear the ARP filter */ + { + UINT_32 u4SetInfoLen = 0; +/* UINT_8 aucBuf[32] = {0}; */ + UINT_32 u4Len = sizeof(PARAM_NETWORK_ADDRESS_LIST); + P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST) g_aucBufIpAddr; + /* aucBuf; */ + + kalMemZero(g_aucBufIpAddr, sizeof(g_aucBufIpAddr)); + + prParamNetAddrList->u4AddressCount = 0; + prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + + ASSERT(u4Len <= sizeof(g_aucBufIpAddr /*aucBuf */)); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNetworkAddress, + (PVOID) prParamNetAddrList, u4Len, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + } + +notify_resume: + DBGLOG(INIT, INFO, "Query BSS result: %d %d %d, IP: %d.%d.%d.%d, rStatus: %u\n", + rParam.eConnectionState, rParam.eCurrentOPMode, rParam.fgIsNetActive, + ip[0], ip[1], ip[2], ip[3], rStatus); + + wlanNotifyFwSuspend(prGlueInfo, FALSE); +} +#endif /* ! CONFIG_X86 */ + +void reset_p2p_mode(P_GLUE_INFO_T prGlueInfo) +{ + PARAM_CUSTOM_P2P_SET_STRUCT_T rSetP2P; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + if (!prGlueInfo) + return; + + rSetP2P.u4Enable = 0; + rSetP2P.u4Mode = 0; + + p2pNetUnregister(prGlueInfo, FALSE); + + rWlanStatus = kalIoctl(prGlueInfo, wlanoidSetP2pMode, (PVOID)&rSetP2P, + sizeof(PARAM_CUSTOM_P2P_SET_STRUCT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rWlanStatus != WLAN_STATUS_SUCCESS) + prGlueInfo->prAdapter->fgIsP2PRegistered = FALSE; + + DBGLOG(INIT, INFO, + "ret = 0x%08x\n", (uint32_t) rWlanStatus); +} + +int set_p2p_mode_handler(struct net_device *netdev, PARAM_CUSTOM_P2P_SET_STRUCT_T p2pmode) +{ +#if 0 + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(netdev)); + PARAM_CUSTOM_P2P_SET_STRUCT_T rSetP2P; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + rSetP2P.u4Enable = p2pmode.u4Enable; + rSetP2P.u4Mode = p2pmode.u4Mode; + + if (!rSetP2P.u4Enable) + p2pNetUnregister(prGlueInfo, TRUE); + + rWlanStatus = kalIoctl(prGlueInfo, + wlanoidSetP2pMode, + (PVOID) &rSetP2P, + sizeof(PARAM_CUSTOM_P2P_SET_STRUCT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + DBGLOG(INIT, INFO, "ret = %d\n", rWlanStatus); + if (rSetP2P.u4Enable) + p2pNetRegister(prGlueInfo, TRUE); + + return 0; + +#else + + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(netdev)); + PARAM_CUSTOM_P2P_SET_STRUCT_T rSetP2P; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + BOOLEAN fgIsP2PEnding; + UINT_32 u4BufLen = 0; + + GLUE_SPIN_LOCK_DECLARATION(); + + if (!prGlueInfo) + return -1; + + if (prGlueInfo->u4ReadyFlag == 0) { + DBGLOG(INIT, ERROR, "adapter is not ready\n"); + return -1; + } + + DBGLOG(INIT, INFO, "%u %u\n", (UINT_32) p2pmode.u4Enable, (UINT_32) p2pmode.u4Mode); + + /* avoid remove & p2p off command simultaneously */ + GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); + fgIsP2PEnding = g_u4P2PEnding; + g_u4P2POnOffing = 1; + GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); + + if (fgIsP2PEnding == 1) { + /* skip the command if we are removing */ + GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); + g_u4P2POnOffing = 0; + GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); + return 0; + } + + /* Resetting p2p mode if registered to avoid launch KE */ + if (p2pmode.u4Enable + && prGlueInfo->prAdapter->fgIsP2PRegistered + && !kalIsResetting()) { + DBGLOG(INIT, WARN, "Resetting p2p mode\n"); + reset_p2p_mode(prGlueInfo); + } + + rSetP2P.u4Enable = p2pmode.u4Enable; + rSetP2P.u4Mode = p2pmode.u4Mode; + +#if !CFG_SUPPORT_PERSIST_NETDEV + if ((!rSetP2P.u4Enable) && (fgIsResetting == FALSE)) + p2pNetUnregister(prGlueInfo, TRUE); +#endif + /* move out to caller to avoid kalIoctrl & suspend/resume deadlock problem ALPS00844864 */ + /* + * Scenario: + * 1. System enters suspend/resume but not yet enter wlanearlysuspend() + * or wlanlateresume(); + * + * 2. System switches to do PRIV_CMD_P2P_MODE and execute kalIoctl() + * and get g_halt_sem then do glRegisterEarlySuspend() or + * glUnregisterEarlySuspend(); + * + * But system suspend/resume procedure is not yet finished so we + * suspend; + * + * 3. System switches back to do suspend/resume procedure and execute + * kalIoctl(). But driver does not yet release g_halt_sem so system + * suspend in wlanearlysuspend() or wlanlateresume(); + * + * ==> deadlock occurs. + */ + + rWlanStatus = kalIoctl(prGlueInfo, wlanoidSetP2pMode, (PVOID) &rSetP2P,/* pu4IntBuf[0]is used as input SubCmd */ + sizeof(PARAM_CUSTOM_P2P_SET_STRUCT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); +#if !CFG_SUPPORT_PERSIST_NETDEV + /* + * Need to check fgIsP2PRegistered, in case of whole chip reset. + * in this case, kalIOCTL return success always, + * and prGlueInfo->prP2pInfo may be NULL + */ + if ((rSetP2P.u4Enable) && (prGlueInfo->prAdapter->fgIsP2PRegistered) && (fgIsResetting == FALSE)) + p2pNetRegister(prGlueInfo, TRUE); +#endif + GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); + g_u4P2POnOffing = 0; + GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); + return 0; +#endif +} + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + +#define FW_LOG_CMD_ON_OFF 0 +#define FW_LOG_CMD_SET_LEVEL 1 +static uint32_t u4LogOnOffCache = -1; + +static void consys_log_event_notification(int cmd, int value) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + struct net_device *prDev = gPrDev; +#if 0 /* gen2? */ + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + struct _CMD_HEADER_T rCmdV1Header; + struct _CMD_FORMAT_V1_T rCmd_v1; +#endif + + DBGLOG(INIT, INFO, "gPrDev=%p, cmd=%d, value=%d\n", + gPrDev, cmd, value); + + if (kalIsHalted()) { /* power-off */ + u4LogOnOffCache = value; + DBGLOG(INIT, INFO, + "Power off return, u4LogOnOffCache=%d\n", + u4LogOnOffCache); + return; + } + + prGlueInfo = (prDev != NULL) ? + *((P_GLUE_INFO_T *) netdev_priv(prDev)) : NULL; + DBGLOG(INIT, TRACE, "prGlueInfo=%p\n", prGlueInfo); + if (!prGlueInfo) { + u4LogOnOffCache = value; + DBGLOG(INIT, INFO, + "prGlueInfo == NULL return, u4LogOnOffCache=%d\n", + u4LogOnOffCache); + return; + } + prAdapter = prGlueInfo->prAdapter; + DBGLOG(INIT, TRACE, "prAdapter=%p\n", prAdapter); + if (!prAdapter) { + u4LogOnOffCache = value; + DBGLOG(INIT, INFO, + "prAdapter == NULL return, u4LogOnOffCache=%d\n", u4LogOnOffCache); + return; + } + + if (cmd == FW_LOG_CMD_ON_OFF) { +#if 0 /* gen2? */ + uint8_t onoff[1] = {'0'}; +#endif + DBGLOG(INIT, TRACE, "FW_LOG_CMD_ON_OFF\n"); +#if 0 /* gen2? */ + rCmdV1Header.cmdType = CMD_TYPE_SET; + rCmdV1Header.cmdVersion = CMD_VER_1; + rCmdV1Header.cmdBufferLen = 0; + rCmdV1Header.itemNum = 0; + + kalMemSet(rCmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); + kalMemSet(&rCmd_v1, 0, sizeof(struct _CMD_FORMAT_V1)); + + rCmd_v1.itemType = ITEM_TYPE_STR; + + /*send string format to firmware */ + rCmd_v1.itemStringLength = kalStrLen("EnableDbgLog"); + kalMemZero(rCmd_v1.itemString, MAX_CMD_NAME_MAX_LENGTH); + kalMemCopy(rCmd_v1.itemString, "EnableDbgLog", + rCmd_v1.itemStringLength); + + if (value == 1) /* other cases, send 'OFF=0' */ + onoff[0] = '1'; + rCmd_v1.itemValueLength = 1; + kalMemZero(rCmd_v1.itemValue, MAX_CMD_VALUE_MAX_LENGTH); + kalMemCopy(rCmd_v1.itemValue, &onoff, 1); + + DBGLOG(INIT, WARN, "Send key word (%s) WITH (%s) to firmware\n", + rCmd_v1.itemString, rCmd_v1.itemValue); + + kalMemCopy(((struct _CMD_FORMAT_V1_T *)rCmdV1Header.buffer), + &rCmd_v1, sizeof(struct _CMD_FORMAT_V1_T)); + + rCmdV1Header.cmdBufferLen += sizeof(struct _CMD_FORMAT_V1_T); + rCmdV1Header.itemNum = 1; + + rStatus = wlanSendSetQueryCmd( + prAdapter, /* prAdapter */ + CMD_ID_GET_SET_CUSTOMER_CFG, /* 0x70 */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler*/ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct _CMD_HEADER_T), /* u4SetQueryInfoLen */ + (PUINT_8)&rCmdV1Header, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus == WLAN_STATUS_FAILURE) + DBGLOG(INIT, INFO, + "[Fail]kalIoctl wifiSefCFG fail 0x%x\n", + rStatus); +#endif + /* keep in cache */ + u4LogOnOffCache = value; + } else if (cmd == FW_LOG_CMD_SET_LEVEL) { + /*ENG_LOAD_OFFSET 1*/ + /*USERDEBUG_LOAD_OFFSET 2 */ + /*USER_LOAD_OFFSET 3 */ + DBGLOG(INIT, INFO, "FW_LOG_CMD_SET_LEVEL\n"); + } else { + DBGLOG(INIT, INFO, "command can not parse\n"); + } +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Wlan probe function. This function probes and initializes the device. +* +* \param[in] pvData data passed by bus driver init function +* _HIF_EHPI: NULL +* _HIF_SDIO: sdio bus driver handle +* +* \retval 0 Success +* \retval negative value Failed +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 wlanProbe(PVOID pvData) +{ + struct wireless_dev *prWdev = NULL; + enum probe_fail_reason { + BUS_INIT_FAIL, + NET_CREATE_FAIL, + BUS_SET_IRQ_FAIL, + ADAPTER_START_FAIL, + NET_REGISTER_FAIL, + PROC_INIT_FAIL, + FAIL_REASON_NUM + } eFailReason; + P_WLANDEV_INFO_T prWlandevInfo = NULL; + INT_32 i4DevIdx = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + INT_32 i4Status = 0; + BOOLEAN bRet = FALSE; + + eFailReason = FAIL_REASON_NUM; + do { + /* 4 <1> Initialize the IO port of the interface */ + /* GeorgeKuo: pData has different meaning for _HIF_XXX: + * _HIF_EHPI: pointer to memory base variable, which will be + * initialized by glBusInit(). + * _HIF_SDIO: bus driver handle + */ + bRet = glBusInit(pvData); + wlanDebugInit(); + /* Cannot get IO address from interface */ + if (bRet == FALSE) { + DBGLOG(INIT, ERROR, KERN_ALERT "wlanProbe: glBusInit() fail\n"); + i4Status = -EIO; + eFailReason = BUS_INIT_FAIL; + break; + } + /* 4 <2> Create network device, Adapter, KalInfo, prDevHandler(netdev) */ + prWdev = wlanNetCreate(pvData); + if (prWdev == NULL) { + DBGLOG(INIT, ERROR, "wlanProbe: No memory for dev and its private\n"); + i4Status = -ENOMEM; + eFailReason = NET_CREATE_FAIL; + break; + } + /* 4 <2.5> Set the ioaddr to HIF Info */ + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); + gPrDev = prGlueInfo->prDevHandler; + + /* 4 <4> Setup IRQ */ + prWlandevInfo = &arWlanDevInfo[i4DevIdx]; + + i4Status = glBusSetIrq(prWdev->netdev, NULL, *((P_GLUE_INFO_T *) netdev_priv(prWdev->netdev))); + + if (i4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "wlanProbe: Set IRQ error\n"); + eFailReason = BUS_SET_IRQ_FAIL; + break; + } + + prGlueInfo->i4DevIdx = i4DevIdx; + + prAdapter = prGlueInfo->prAdapter; + + prGlueInfo->u4ReadyFlag = 0; + + /* default set the FW roaming enable state to 'on' */ + prGlueInfo->u4FWRoamingEnable = 1; + + /*Check the build variant*/ +#if defined(WLAN_ENG_LOAD) + prGlueInfo->rBuildVarint = MTK_BUILD_VAR_ENG; +#elif defined(WLAN_USERDEBUG_LOAD) + prGlueInfo->rBuildVarint = MTK_BUILD_VAR_USERDEUB; +#elif defined(WLAN_USER_LOAD) + prGlueInfo->rBuildVarint = MTK_BUILD_VAR_USER; +#else + prGlueInfo->rBuildVarint = 0; +#endif + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + prAdapter->u4CSUMFlags = (CSUM_OFFLOAD_EN_TX_TCP | CSUM_OFFLOAD_EN_TX_UDP | CSUM_OFFLOAD_EN_TX_IP); +#endif +#if CFG_SUPPORT_CFG_FILE + wlanCfgInit(prAdapter, NULL, 0, 0); +#ifdef ENABLED_IN_ENGUSERDEBUG + { + PUINT_8 pucConfigBuf; + UINT_32 u4ConfigReadLen; + + pucConfigBuf = (PUINT_8) kalMemAlloc(WLAN_CFG_FILE_BUF_SIZE, VIR_MEM_TYPE); + u4ConfigReadLen = 0; + DBGLOG(INIT, LOUD, "CFG_FILE: Read File...\n"); + if (pucConfigBuf) { + kalMemZero(pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE); + if (kalReadToFile("/data/misc/wifi.cfg", + pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE, &u4ConfigReadLen) == 0) { + DBGLOG(INIT, LOUD, "CFG_FILE: Read /data/misc/wifi.cfg\n"); + + } else if (kalReadToFile("/data/misc/wifi/wifi.cfg", + pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE, &u4ConfigReadLen) == 0) { + DBGLOG(INIT, LOUD, "CFG_FILE: Read /data/misc/wifi/wifi.cfg\n"); + } else if (kalReadToFile("/etc/firmware/wifi.cfg", + pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE, &u4ConfigReadLen) == 0) { + DBGLOG(INIT, LOUD, "CFG_FILE: Read /etc/firmware/wifi.cfg\n"); + } + + if (pucConfigBuf[0] != '\0' && u4ConfigReadLen > 0) + wlanCfgInit(prAdapter, pucConfigBuf, u4ConfigReadLen, 0); + kalMemFree(pucConfigBuf, VIR_MEM_TYPE, WLAN_CFG_FILE_BUF_SIZE); + } /* pucConfigBuf */ + } +#endif +#endif + /* 4 <5> Start Device */ + /* */ +#if CFG_ENABLE_FW_DOWNLOAD + DBGLOG(INIT, TRACE, "start to download firmware...\n"); + + /* before start adapter, we need to open and load firmware */ + { + UINT_32 u4FwSize = 0; + PVOID prFwBuffer = NULL; + P_REG_INFO_T prRegInfo = &prGlueInfo->rRegInfo; + + /* P_REG_INFO_T prRegInfo = (P_REG_INFO_T) kmalloc(sizeof(REG_INFO_T), GFP_KERNEL); */ + kalMemSet(prRegInfo, 0, sizeof(REG_INFO_T)); + prRegInfo->u4StartAddress = CFG_FW_START_ADDRESS; + prRegInfo->u4LoadAddress = CFG_FW_LOAD_ADDRESS; + /* Load NVRAM content to REG_INFO_T */ + glLoadNvram(prGlueInfo, prRegInfo); +#if CFG_TC10_FEATURE + if (sysMacAddrOverride(prGlueInfo->rRegInfo.aucMacAddr)) + DBGLOG(INIT, ERROR, "Read MAC addr failed from /efs/\n"); + else + DBGLOG(INIT, INFO, " MAC addr %pM\n", + prGlueInfo->rRegInfo.aucMacAddr); +#endif +#if CFG_SUPPORT_CFG_FILE +#ifdef ENABLED_IN_ENGUSERDEBUG + wlanCfgApply(prAdapter); +#endif +#endif + + /* kalMemCopy(&prGlueInfo->rRegInfo, prRegInfo, sizeof(REG_INFO_T)); */ + + prRegInfo->u4PowerMode = CFG_INIT_POWER_SAVE_PROF; + prRegInfo->fgEnArpFilter = TRUE; + + if (kalFirmwareImageMapping(prGlueInfo, &prFwBuffer, &u4FwSize) == NULL) { + i4Status = -EIO; + DBGLOG(INIT, ERROR, "kalFirmwareImageMapping fail!\n"); + goto bailout; + } else { + + if (wlanAdapterStart(prAdapter, prRegInfo, prFwBuffer, + u4FwSize) != WLAN_STATUS_SUCCESS) { + i4Status = -EIO; + } + } + + kalFirmwareImageUnmapping(prGlueInfo, NULL, prFwBuffer); + +bailout: + /* kfree(prRegInfo); */ + + DBGLOG(INIT, TRACE, "download firmware status = %d\n", i4Status); + + if (i4Status < 0) { + GL_HIF_INFO_T *HifInfo; + UINT_32 u4FwCnt; + + DBGLOG(INIT, WARN, "CONNSYS FW CPUINFO:\n"); + HifInfo = &prAdapter->prGlueInfo->rHifInfo; + for (u4FwCnt = 0; u4FwCnt < 16; u4FwCnt++) + DBGLOG(INIT, WARN, "0x%08x ", MCU_REG_READL(HifInfo, CONN_MCU_CPUPCR)); + /* CONSYS_REG_READ(CONSYS_CPUPCR_REG) */ + + /* dump HIF/DMA registers, if fgIsBusAccessFailed is FALSE, otherwise, */ + /* dump HIF register may be hung */ + if (!fgIsBusAccessFailed) + HifRegDump(prGlueInfo->prAdapter); +/* if (prGlueInfo->rHifInfo.DmaOps->DmaRegDump != NULL) */ +/* prGlueInfo->rHifInfo.DmaOps->DmaRegDump(&prGlueInfo->rHifInfo); */ + eFailReason = ADAPTER_START_FAIL; + break; + } + } +#else + /* P_REG_INFO_T prRegInfo = (P_REG_INFO_T) kmalloc(sizeof(REG_INFO_T), GFP_KERNEL); */ + kalMemSet(&prGlueInfo->rRegInfo, 0, sizeof(REG_INFO_T)); + P_REG_INFO_T prRegInfo = &prGlueInfo->rRegInfo; + + /* Load NVRAM content to REG_INFO_T */ + glLoadNvram(prGlueInfo, prRegInfo); + + prRegInfo->u4PowerMode = CFG_INIT_POWER_SAVE_PROF; + + if (wlanAdapterStart(prAdapter, prRegInfo, NULL, 0) != WLAN_STATUS_SUCCESS) { + i4Status = -EIO; + eFailReason = ADAPTER_START_FAIL; + break; + } +#endif + if (prAdapter->fgEnable5GBand == FALSE) + prWdev->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; + else + prWdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &mtk_band_5ghz; + + prGlueInfo->main_thread = kthread_run(tx_thread, prGlueInfo->prDevHandler, "tx_thread"); +#if CFG_SUPPORT_MULTITHREAD + prGlueInfo->rx_thread = kthread_run(rx_thread, prGlueInfo->prDevHandler, "rx_thread"); +#endif + kalChangeSchedParams(prGlueInfo, TRUE); + kalSetHalted(FALSE); +#if CFG_SUPPORT_ROAMING_ENC + /* adjust roaming threshold */ + { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + CMD_ROAMING_INFO_T rRoamingInfo; + UINT_32 u4SetInfoLen = 0; + + prAdapter->fgIsRoamingEncEnabled = TRUE; + + /* suggestion from Tsaiyuan.Hsu */ + kalMemZero(&rRoamingInfo, sizeof(CMD_ROAMING_INFO_T)); + rRoamingInfo.fgIsFastRoamingApplied = TRUE; + + DBGLOG(INIT, TRACE, "Enable roaming enhance function\n"); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRoamingInfo, + &rRoamingInfo, sizeof(rRoamingInfo), TRUE, TRUE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, ERROR, "set roaming advance info fail 0x%x\n", rStatus); + } +#endif /* CFG_SUPPORT_ROAMING_ENC */ + +#if (CFG_SUPPORT_TXR_ENC == 1) + /* adjust tx rate switch threshold */ + rlmTxRateEnhanceConfig(prGlueInfo->prAdapter); +#endif /* CFG_SUPPORT_TXR_ENC */ + + /* set MAC address */ + { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + struct sockaddr MacAddr; + UINT_32 u4SetInfoLen = 0; + + kalMemZero(MacAddr.sa_data, sizeof(MacAddr.sa_data)); + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryCurrentAddr, + &MacAddr.sa_data, + PARAM_MAC_ADDR_LEN, TRUE, TRUE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, WARN, "set MAC addr fail 0x%x\n", rStatus); + prGlueInfo->u4ReadyFlag = 0; + } else { + ether_addr_copy(prGlueInfo->prDevHandler->dev_addr, (const u8 *)&(MacAddr.sa_data)); + ether_addr_copy(prGlueInfo->prDevHandler->perm_addr, + prGlueInfo->prDevHandler->dev_addr); + + /* card is ready */ + prGlueInfo->u4ReadyFlag = 1; +#if CFG_SHOW_MACADDR_SOURCE + DBGLOG(INIT, INFO, "MAC address: %pM ", (&MacAddr.sa_data)); +#endif + } + } +#ifdef FW_CFG_SUPPORT + { + if (wlanFwArrayCfg(prAdapter) != WLAN_STATUS_FAILURE) + DBGLOG(INIT, INFO, "FW Array Cfg done!"); + } +#ifdef ENABLED_IN_ENGUSERDEBUG + { + if (wlanFwFileCfg(prAdapter) != WLAN_STATUS_FAILURE) + DBGLOG(INIT, INFO, "FW File Cfg done!"); + } +#endif +#endif + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + /* set HW checksum offload */ + { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_32 u4CSUMFlags = CSUM_OFFLOAD_EN_ALL; + UINT_32 u4SetInfoLen = 0; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetCSUMOffload, + (PVOID) &u4CSUMFlags, + sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, WARN, "set HW checksum offload fail 0x%x\n", rStatus); + } +#endif + +#if CFG_SUPPORT_EMI_DEBUG + { + /* set Driver Read EMI */ + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + CMD_DRIVER_DUMP_EMI_LOG_T rDriverDumpEmiLog; + UINT_32 u4SetInfoLen = 0; + + /*ENG_LOAD_OFFSET 1*/ + /*USERDEBUG_LOAD_OFFSET 2 */ + /*USER_LOAD_OFFSET 3 */ + + kalMemZero(&rDriverDumpEmiLog, sizeof(CMD_DRIVER_DUMP_EMI_LOG_T)); + rDriverDumpEmiLog.fgIsDriverDumpEmiLogEnable = TRUE | (1 << prGlueInfo->rBuildVarint); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEnableDumpEMILog, + (PVOID)&rDriverDumpEmiLog, + sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, WARN, "set Driver read EMI address fail 0x%x\n", rStatus); + } +#endif +#if CFG_SUPPORT_802_11K + { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_32 u4SetInfoLen = 0; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSync11kCapbilities, + NULL, + 0, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, WARN, "set 11k Capabilities fail 0x%x\n", rStatus); + } +#endif + /* 4 <3> Register the card */ + DBGLOG(INIT, TRACE, "wlanNetRegister...\n"); + i4DevIdx = wlanNetRegister(prWdev); + if (i4DevIdx < 0) { + i4Status = -ENXIO; + DBGLOG(INIT, ERROR, "wlanProbe: Cannot register the net_device context to the kernel\n"); + eFailReason = NET_REGISTER_FAIL; + break; + } + + wlanRegisterNotifier(); + /* 4 <6> Initialize /proc filesystem */ +#ifdef WLAN_INCLUDE_PROC + DBGLOG(INIT, TRACE, "init procfs...\n"); + i4Status = procCreateFsEntry(prGlueInfo); + if (i4Status < 0) { + DBGLOG(INIT, ERROR, "wlanProbe: init procfs failed\n"); + eFailReason = PROC_INIT_FAIL; + break; + } +#endif /* WLAN_INCLUDE_PROC */ + +#if WLAN_INCLUDE_SYS + i4Status = sysCreateFsEntry(prGlueInfo); + if (i4Status < 0) { + DBGLOG(INIT, ERROR, "wlanProbe: init sysfs failed\n"); + eFailReason = PROC_INIT_FAIL; + break; + } +#endif /* WLAN_INCLUDE_SYS */ + +#ifdef FW_CFG_SUPPORT + i4Status = cfgCreateProcEntry(prGlueInfo); + if (i4Status < 0) { + DBGLOG(INIT, ERROR, "fw cfg proc failed\n"); + break; + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + prGlueInfo->rBowInfo.fgIsNetRegistered = FALSE; + prGlueInfo->rBowInfo.fgIsRegistered = FALSE; + glRegisterAmpc(prGlueInfo); +#endif + +#if CFG_ENABLE_WIFI_DIRECT + DBGLOG(INIT, TRACE, "wlanSubModInit...\n"); + + /* wlan is launched */ + prGlueInfo->prAdapter->fgIsWlanLaunched = TRUE; + /* if p2p module is inserted, notify tx_thread to init p2p network */ + if (rSubModHandler[P2P_MODULE].subModInit) + wlanSubModInit(prGlueInfo); + /* register set_p2p_mode handler to mtk_wmt_wifi */ + register_set_p2p_mode_handler(set_p2p_mode_handler); +#endif +#if CFG_SPM_WORKAROUND_FOR_HOTSPOT + if (glIsChipNeedWakelock(prGlueInfo)) + KAL_WAKE_LOCK_INIT(prGlueInfo->prAdapter, prGlueInfo->prAdapter->rApWakeLock, "WLAN AP"); +#endif + kalMemZero(&prGlueInfo->rFtIeForTx, sizeof(prGlueInfo->rFtIeForTx)); + } while (FALSE); + + if (i4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "%s eFailReasone:%d\n", __func__, eFailReason); + switch (eFailReason) { + case PROC_INIT_FAIL: + wlanNetUnregister(prWdev); + set_bit(GLUE_FLAG_HALT_BIT, &prGlueInfo->ulFlag); + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + /* wait main thread stops */ + wait_for_completion_interruptible(&prGlueInfo->rHaltComp); + KAL_WAKE_LOCK_DESTROY(prAdapter, prAdapter->rTxThreadWakeLock); + wlanAdapterStop(prAdapter); + glBusFreeIrq(prWdev->netdev, *((P_GLUE_INFO_T *) netdev_priv(prWdev->netdev))); + KAL_WAKE_LOCK_DESTROY(prAdapter, prGlueInfo->rAhbIsrWakeLock); +#if CFG_SUPPORT_MULTITHREAD + KAL_WAKE_LOCK_DESTROY(prAdapter, prGlueInfo->rTimeoutWakeLock); +#endif + wlanNetDestroy(prWdev); + /* prGlueInfo->prAdapter is released in wlanNetDestroy */ + /* Set NULL value for local prAdapter as well */ + prAdapter = NULL; + break; + case NET_REGISTER_FAIL: + set_bit(GLUE_FLAG_HALT_BIT, &prGlueInfo->ulFlag); + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + /* wait main thread stops */ + wait_for_completion_interruptible(&prGlueInfo->rHaltComp); + KAL_WAKE_LOCK_DESTROY(prAdapter, prAdapter->rTxThreadWakeLock); + wlanAdapterStop(prAdapter); + glBusFreeIrq(prWdev->netdev, *((P_GLUE_INFO_T *) netdev_priv(prWdev->netdev))); + KAL_WAKE_LOCK_DESTROY(prAdapter, prGlueInfo->rAhbIsrWakeLock); +#if CFG_SUPPORT_MULTITHREAD + KAL_WAKE_LOCK_DESTROY(prAdapter, prGlueInfo->rTimeoutWakeLock); +#endif + wlanNetDestroy(prWdev); + /* prGlueInfo->prAdapter is released in wlanNetDestroy */ + /* Set NULL value for local prAdapter as well */ + prAdapter = NULL; + break; + case ADAPTER_START_FAIL: + glBusFreeIrq(prWdev->netdev, *((P_GLUE_INFO_T *) netdev_priv(prWdev->netdev))); + KAL_WAKE_LOCK_DESTROY(prAdapter, prGlueInfo->rAhbIsrWakeLock); +#if CFG_SUPPORT_MULTITHREAD + KAL_WAKE_LOCK_DESTROY(prAdapter, prGlueInfo->rTimeoutWakeLock); +#endif + wlanNetDestroy(prWdev); + /* prGlueInfo->prAdapter is released in wlanNetDestroy */ + /* Set NULL value for local prAdapter as well */ + prAdapter = NULL; + break; + case BUS_SET_IRQ_FAIL: + KAL_WAKE_LOCK_DESTROY(prAdapter, prGlueInfo->rAhbIsrWakeLock); +#if CFG_SUPPORT_MULTITHREAD + KAL_WAKE_LOCK_DESTROY(prAdapter, prGlueInfo->rTimeoutWakeLock); +#endif + wlanNetDestroy(prWdev); + /* prGlueInfo->prAdapter is released in wlanNetDestroy */ + /* Set NULL value for local prAdapter as well */ + prAdapter = NULL; + break; + case NET_CREATE_FAIL: + break; + case BUS_INIT_FAIL: + break; + default: + break; + } + } +#if CFG_ENABLE_WIFI_DIRECT + { + GLUE_SPIN_LOCK_DECLARATION(); + + GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); + g_u4P2PEnding = 0; + GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); + } +#endif +#if CFG_SUPPORT_AGPS_ASSIST + if (i4Status == WLAN_STATUS_SUCCESS) + kalIndicateAgpsNotify(prAdapter, AGPS_EVENT_WLAN_ON, NULL, 0); +#endif +#if (CFG_SUPPORT_MET_PROFILING == 1) + { + int iMetInitRet = WLAN_STATUS_FAILURE; + + if (i4Status == WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, TRACE, "init MET procfs...\n"); + iMetInitRet = kalMetInitProcfs(prGlueInfo); + if (iMetInitRet < 0) + DBGLOG(INIT, ERROR, "wlanProbe: init MET procfs failed\n"); + } + } +#endif + if (i4Status == WLAN_STATUS_SUCCESS) { + /*Init performance monitor structure */ + kalPerMonInit(prGlueInfo); + /* probe ok */ + DBGLOG(INIT, TRACE, "wlanProbe ok\n"); + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + /* sync log status with firmware */ + if (u4LogOnOffCache != -1) /* -1: connsysD does not set */ + consys_log_event_notification((int)FW_LOG_CMD_ON_OFF, + u4LogOnOffCache); +#endif + + update_driver_loaded_status(TRUE); + } else { + /* + * we don't care the return value of mtk_wcn_set_connsys_power_off_flag, + * because even this function returns + * error, we can also call core dump but only core dump failed. + */ + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP); + /* probe failed */ + DBGLOG(INIT, ERROR, "wlanProbe failed\n"); + } + + if (u4FwLogLevel > ENUM_WIFI_LOG_LEVEL_OFF) { + if (prAdapter) + wlanDbgSetLogLevelImpl(prAdapter, ENUM_WIFI_LOG_LEVEL_VERSION_V1, + ENUM_WIFI_LOG_MODULE_FW, u4FwLogLevel); + } + + return i4Status; +} /* end of wlanProbe() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A method to stop driver operation and release all resources. Following +* this call, no frame should go up or down through this interface. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID wlanRemove(VOID) +{ +#define KAL_WLAN_REMOVE_TIMEOUT_MSEC 3000 + struct net_device *prDev = NULL; + P_WLANDEV_INFO_T prWlandevInfo = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + P_CONNECTION_SETTINGS_T prConnSettings; + + DBGLOG(INIT, LOUD, "Remove wlan!\n"); + + /* 4 <0> Sanity check */ + ASSERT(u4WlanDevNum <= CFG_MAX_WLAN_DEVICES); + if (u4WlanDevNum == 0) { + DBGLOG(INIT, ERROR, "0 == u4WlanDevNum\n"); + return; + } + /* unregister set_p2p_mode handler to mtk_wmt_wifi */ + register_set_p2p_mode_handler(NULL); + + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + prWlandevInfo = &arWlanDevInfo[u4WlanDevNum - 1]; + + ASSERT(prDev); + if (prDev == NULL) { + DBGLOG(INIT, ERROR, "NULL == prDev\n"); + return; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + if (prGlueInfo == NULL) { + DBGLOG(INIT, ERROR, "NULL == prGlueInfo\n"); + free_netdev(prDev); + return; + } + + kalPerMonDestroy(prGlueInfo); + /* 4 <3> Remove /proc filesystem. */ +#ifdef FW_CFG_SUPPORT + cfgRemoveProcEntry(); +#endif +#ifdef WLAN_INCLUDE_PROC + procRemoveProcfs(); +#endif /* WLAN_INCLUDE_PROC */ +#if WLAN_INCLUDE_SYS + sysRemoveSysfs(); +#endif /* WLAN_INCLUDE_SYS */ + +#if CFG_ENABLE_WIFI_DIRECT + /* avoid remove & p2p off command simultaneously */ + { + BOOLEAN fgIsP2POnOffing; + + GLUE_SPIN_LOCK_DECLARATION(); + + GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); + g_u4P2PEnding = 1; + fgIsP2POnOffing = g_u4P2POnOffing; + GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); + + DBGLOG(INIT, TRACE, "waiting for fgIsP2POnOffing...\n"); + + /* History: cannot use down() here, sometimes we cannot come back here */ + /* waiting for p2p off command finishes, we cannot skip the remove */ + while (1) { + if (fgIsP2POnOffing == 0) + break; + GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); + fgIsP2POnOffing = g_u4P2POnOffing; + GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); + } + } + if (prGlueInfo->prAdapter->fgIsP2PRegistered) { + DBGLOG(INIT, INFO, "p2pNetUnregister...\n"); +#if !CFG_SUPPORT_PERSIST_NETDEV + /* Release rtnl_lock() */ + complete(&prGlueInfo->rP2pReq); + p2pNetUnregister(prGlueInfo, FALSE); +#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 */ + DBGLOG(INIT, TRACE, "free IRQ...\n"); + glBusFreeIrq(prDev, *((P_GLUE_INFO_T *) netdev_priv(prDev))); + + kalSetHalted(TRUE); /* before flush_delayed_work() */ + if (fgIsWorkMcStart == TRUE) { + DBGLOG(INIT, TRACE, "flush_delayed_work...\n"); + flush_delayed_work(&workq); /* flush_delayed_work_sync is deprecated */ + } + + /* Prevent memory leakage */ + prConnSettings = &prGlueInfo->prAdapter->rWifiVar.rConnSettings; + if (prConnSettings && prConnSettings->assocIeLen > 0) { + kalMemFree(prConnSettings->pucAssocIEs, VIR_MEM_TYPE, + prConnSettings->assocIeLen); + prConnSettings->assocIeLen = 0; + } + flush_delayed_work(&sched_workq); + + DBGLOG(INIT, INFO, "down g_halt_sem...\n"); + kalHaltLock(KAL_WLAN_REMOVE_TIMEOUT_MSEC); +#if CFG_SPM_WORKAROUND_FOR_HOTSPOT + if (glIsChipNeedWakelock(prGlueInfo)) + KAL_WAKE_LOCK_DESTROY(prGlueInfo->prAdapter, prGlueInfo->prAdapter->rApWakeLock); +#endif + +/* flush_delayed_work_sync(&workq); */ +/* flush_delayed_work(&workq); */ /* flush_delayed_work_sync is deprecated */ + + /* 4 <2> Mark HALT, notify main thread to stop, and clean up queued requests */ +/* prGlueInfo->u4Flag |= GLUE_FLAG_HALT; */ + set_bit(GLUE_FLAG_HALT_BIT, &prGlueInfo->ulFlag); +#if CFG_SUPPORT_MULTITHREAD + DBGLOG(INIT, TRACE, "waiting for rx_thread stop...\n"); + wake_up_interruptible(&prGlueInfo->waitq_rx); + wait_for_completion_interruptible(&prGlueInfo->rRxHaltComp); +#endif + + DBGLOG(INIT, TRACE, "waiting for tx_thread stop...\n"); + + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + + DBGLOG(INIT, TRACE, "wait_for_completion_interruptible\n"); + + /* wait main thread stops */ + wait_for_completion(&prGlueInfo->rHaltComp); + + DBGLOG(INIT, TRACE, "wlan thread(s) stopped\n"); + + KAL_WAKE_LOCK_DESTROY(prGlueInfo->prAdapter, prGlueInfo->prAdapter->rTxThreadWakeLock); + KAL_WAKE_LOCK_DESTROY(prGlueInfo->prAdapter, prGlueInfo->rAhbIsrWakeLock); +#if CFG_SUPPORT_MULTITHREAD + KAL_WAKE_LOCK_DESTROY(prGlueInfo->prAdapter, prGlueInfo->rTimeoutWakeLock); + DBGLOG(INIT, INFO, "remove rTimeoutWakeLock = %p\n", &prGlueInfo->rTimeoutWakeLock); + +#endif + + kalMemSet(&(prGlueInfo->prAdapter->rWlanInfo), 0, sizeof(WLAN_INFO_T)); + + /* prGlueInfo->rHifInfo.main_thread = NULL; */ + prGlueInfo->main_thread = NULL; +#if CFG_SUPPORT_MULTITHREAD + prGlueInfo->rx_thread = NULL; +#endif +#if CFG_ENABLE_BT_OVER_WIFI + if (prGlueInfo->rBowInfo.fgIsRegistered) + glUnregisterAmpc(prGlueInfo); +#endif + +#if (CFG_SUPPORT_MET_PROFILING == 1) + kalMetRemoveProcfs(); +#endif + + /* Force to do DMA reset */ + DBGLOG(INIT, TRACE, "glResetHif\n"); + glResetHif(prGlueInfo); + + /* 4 <4> wlanAdapterStop */ + prAdapter = prGlueInfo->prAdapter; +#if CFG_SUPPORT_AGPS_ASSIST + kalIndicateAgpsNotify(prAdapter, AGPS_EVENT_WLAN_OFF, NULL, 0); +#endif + + wlanAdapterStop(prAdapter); + DBGLOG(INIT, TRACE, "Number of Stalled Packets = %d\n", prGlueInfo->i4TxPendingFrameNum); + +#if CFG_ENABLE_WIFI_DIRECT + prGlueInfo->prAdapter->fgIsWlanLaunched = FALSE; + if (prGlueInfo->prAdapter->fgIsP2PRegistered) { + DBGLOG(INIT, INFO, "p2pRemove...\n"); + p2pRemove(prGlueInfo); + } +#endif + + /* 4 <5> Release the Bus */ + glBusRelease(prDev); + + kalHaltUnlock(); + wlanDebugUninit(); + /* 4 <6> Unregister the card */ + wlanNetUnregister(prDev->ieee80211_ptr); + + /* 4 <7> Destroy the device */ + wlanNetDestroy(prDev->ieee80211_ptr); + prDev = NULL; + + DBGLOG(INIT, LOUD, "wlanUnregisterNotifier...\n"); + wlanUnregisterNotifier(); + + update_driver_loaded_status(FALSE); + + DBGLOG(INIT, INFO, "wlanRemove ok\n"); +} /* end of wlanRemove() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Driver entry point when the driver is configured as a Linux Module, and +* is called once at module load time, by the user-level modutils +* application: insmod or modprobe. +* +* \retval 0 Success +*/ +/*----------------------------------------------------------------------------*/ +/* 1 Module Entry Point */ +static int initWlan(void) +{ + int ret = 0, i; + + /* Set the initial debug level of each module */ +#if DBG + for (i = 0; i < DBG_MODULE_NUM; i++) + aucDebugModule[i] = DBG_CLASS_MASK; /* enable all */ +#else + for (i = 0; i < DBG_MODULE_NUM; i++) + aucDebugModule[i] = DBG_CLASS_ERROR | DBG_CLASS_WARN | DBG_CLASS_INFO | DBG_CLASS_STATE; +#endif /* DBG */ + + DBGLOG(INIT, INFO, "initWlan\n"); + + spin_lock_init(&g_p2p_lock); + + fgNvramAvailable = FALSE; + /* memory pre-allocation */ + kalInitIOBuffer(); + procInitFs(); +#if WLAN_INCLUDE_SYS + sysInitFs(); +#endif + createWirelessDevice(); + if (gprWdev) + glP2pCreateWirelessDevice((P_GLUE_INFO_T) wiphy_priv(gprWdev->wiphy)); + gPrDev = NULL; + + ret = ((glRegisterBus(wlanProbe, wlanRemove) == WLAN_STATUS_SUCCESS) ? 0 : -EIO); + + if (ret == -EIO) { + kalUninitIOBuffer(); + return ret; + } +#if (CFG_CHIP_RESET_SUPPORT) + glResetInit(); +#endif + + /* Register framebuffer notifier client */ + if (gprWdev) + kalFbNotifierReg((P_GLUE_INFO_T) wiphy_priv(gprWdev->wiphy)); + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + wifi_fwlog_event_func_register(consys_log_event_notification); +#endif + + /* Set the initial DEBUG CLASS of each module */ + return ret; +} /* end of initWlan() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Driver exit point when the driver as a Linux Module is removed. Called +* at module unload time, by the user level modutils application: rmmod. +* This is our last chance to clean up after ourselves. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +/* 1 Module Leave Point */ +static VOID exitWlan(void) +{ + DBGLOG(INIT, INFO, "exitWlan\n"); + + /* Unregister framebuffer notifier client*/ + kalFbNotifierUnReg(); + +#if CFG_CHIP_RESET_SUPPORT + glResetUninit(); +#endif + destroyWirelessDevice(); + glP2pDestroyWirelessDevice(); + + glUnregisterBus(wlanRemove); + + /* free pre-allocated memory */ + kalUninitIOBuffer(); + + DBGLOG(INIT, INFO, "exitWlan\n"); + procUninitProcFs(); +#if WLAN_INCLUDE_SYS + sysUninitSysFs(); +#endif + +} /* end of exitWlan() */ + +#if CFG_SUPPORT_SET_CAM_BY_PROC +VOID nicConfigProcSetCamCfgWrite(BOOLEAN enabled) +{ + struct net_device *prDev = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + PARAM_POWER_MODE ePowerMode; + BOOLEAN fgEnCmdEvent; + UINT_8 ucBssIndex; + CMD_PS_PROFILE_T arPowerSaveMode[NETWORK_TYPE_INDEX_NUM]; + + /* 4 <1> Sanity Check */ + ASSERT(u4WlanDevNum <= CFG_MAX_WLAN_DEVICES); + if (u4WlanDevNum == 0) { + DBGLOG(INIT, ERROR, "wlanLateResume u4WlanDevNum invalid!!\n"); + return; + } + + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + if (!prDev) + return; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + if (!prGlueInfo) + return; + + prAdapter = prGlueInfo->prAdapter; + if ((!prAdapter) || (!&(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]))) + return; + + fgEnCmdEvent = FALSE; + ucBssIndex = NETWORK_TYPE_AIS_INDEX; + arPowerSaveMode[ucBssIndex].ucNetTypeIndex = ucBssIndex; + + if (enabled) { + nicForceSetCAM(TRUE); + ePowerMode = Param_PowerModeCAM; + arPowerSaveMode[ucBssIndex].ucPsProfile = (UINT_8) ePowerMode; + DBGLOG(INIT, INFO, "Enable CAM BssIndex:%d, PowerMode:%d\n", + ucBssIndex, arPowerSaveMode[ucBssIndex].ucPsProfile); + } else { + nicForceSetCAM(FALSE); + arPowerSaveMode[ucBssIndex].ucPsProfile = + prAdapter->rWlanInfo.arPowerSaveMode[ucBssIndex].ucPsProfile; + DBGLOG(INIT, INFO, "Disable CAM BssIndex:%d, PowerMode:%d\n", + ucBssIndex, arPowerSaveMode[ucBssIndex].ucPsProfile); + } + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_POWER_SAVE_MODE, + TRUE, + FALSE, + (fgEnCmdEvent ? TRUE : FALSE), + (fgEnCmdEvent ? nicCmdEventSetCommon : NULL), + (fgEnCmdEvent ? nicOidCmdTimeoutCommon : NULL), + sizeof(CMD_PS_PROFILE_T), + (PUINT_8)&(arPowerSaveMode[ucBssIndex]), + NULL, sizeof(PARAM_POWER_MODE)); +} +#endif + +#ifdef MTK_WCN_BUILT_IN_DRIVER + +int mtk_wcn_wlan_gen2_init(void) +{ + return initWlan(); +} +EXPORT_SYMBOL(mtk_wcn_wlan_gen2_init); + +void mtk_wcn_wlan_gen2_exit(void) +{ + return exitWlan(); +} +EXPORT_SYMBOL(mtk_wcn_wlan_gen2_exit); + +#else + +module_init(initWlan); +module_exit(exitWlan); + +#endif + +MODULE_AUTHOR(NIC_AUTHOR); +MODULE_DESCRIPTION(NIC_DESC); +MODULE_SUPPORTED_DEVICE(NIC_NAME); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_kal.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_kal.c new file mode 100644 index 0000000000000..dc8040e219942 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_kal.c @@ -0,0 +1,5198 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E 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 "gl_kal.h" +#include "precomp.h" +#if CFG_TC1_FEATURE +#include +#endif +#if CFG_SUPPORT_AGPS_ASSIST +#include +#endif +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +#include +#else +#include +#endif +#endif +#include "connectivity_build_in_adapter.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + + +#define OPEN_FIRMWARE_BY_REQUEST 1 +#define ENHANCE_AP_MODE_THROUGHPUT 1 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +#if DBG +int allocatedMemSize; +#endif + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/* #define MTK_DMA_BUF_MEMCPY_SUP */ + +static PVOID pvIoBuffer; + +#ifdef MTK_DMA_BUF_MEMCPY_SUP +static PVOID pvIoPhyBuf; +static PVOID pvDmaBuffer; +static PVOID pvDmaPhyBuf; +#endif /* MTK_DMA_BUF_MEMCPY_SUP */ + +static UINT_32 pvIoBufferSize; +static UINT_32 pvIoBufferUsage; +static struct KAL_HALT_CTRL_T rHaltCtrl = { + .lock = __SEMAPHORE_INITIALIZER(rHaltCtrl.lock, 1), + .owner = NULL, + .fgHalt = TRUE, + .fgHeldByKalIoctl = FALSE, + .u4HoldStart = 0, +}; + +/* framebuffer callback related variable and status flag */ +static struct notifier_block wlan_fb_notifier; +void *wlan_fb_notifier_priv_data; +BOOLEAN wlan_fb_power_down = FALSE; +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +#if defined(MT6620) && CFG_MULTI_ECOVER_SUPPORT +typedef enum _ENUM_WMTHWVER_TYPE_T { + WMTHWVER_MT6620_E1 = 0x0, + WMTHWVER_MT6620_E2 = 0x1, + WMTHWVER_MT6620_E3 = 0x2, + WMTHWVER_MT6620_E4 = 0x3, + WMTHWVER_MT6620_E5 = 0x4, + WMTHWVER_MT6620_E6 = 0x5, + WMTHWVER_MT6620_MAX, + WMTHWVER_INVALID = 0xff +} ENUM_WMTHWVER_TYPE_T, *P_ENUM_WMTHWVER_TYPE_T; +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +VOID kalHifAhbKalWakeLockTimeout(IN P_GLUE_INFO_T prGlueInfo) +{ + KAL_WAKE_LOCK_TIMEOUT(prGlueInfo->prAdapter, (prGlueInfo->rAhbIsrWakeLock), (HZ / 10)); /* 100ms */ +} + +#if CFG_ENABLE_FW_DOWNLOAD + +#if OPEN_FIRMWARE_BY_REQUEST +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ + GL_HIF_INFO_T *prHifInfo = &prGlueInfo->rHifInfo; + INT_32 i4Ret = 0; + UINT_8 aucFilePath[32]; + + DEBUGFUNC("kalFirmwareImageMapping"); + + ASSERT(prGlueInfo); + ASSERT(ppvMapFileBuf); + ASSERT(pu4FileLength); + + prGlueInfo->prFw = NULL; + kalMemZero(aucFilePath, sizeof(aucFilePath)); + +#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: + kalMemCopy(aucFilePath, CFG_FW_FILENAME, + strlen(CFG_FW_FILENAME)); + break; + case WMTHWVER_MT6620_E6: + default: + kalMemCopy(aucFilePath, CFG_FW_FILENAME "_E6", + strlen(CFG_FW_FILENAME "_E6")); + break; + } +#elif defined(MT6628) +#if 0 /* new wifi ram code mechanism, waiting firmware ready, then we can enable these code */ + kalMemCopy(aucFilePath, CFG_FW_FILENAME "_AD", + strlen(CFG_FW_FILENAME "_AD")); +#endif + kalMemCopy(aucFilePath, CFG_FW_FILENAME "_", + strlen(CFG_FW_FILENAME "_")); + glGetChipInfo(prGlueInfo, &aucFilePath[strlen(CFG_FW_FILENAME "_")]); +#else + kalMemCopy(aucFilePath, CFG_FW_FILENAME, + strlen(CFG_FW_FILENAME)); +#endif + + /* <1> Open firmware */ + do { + i4Ret = request_firmware(&prGlueInfo->prFw, aucFilePath, prHifInfo->Dev); + } while (i4Ret == -EAGAIN); /* By programming guide */ + + if (i4Ret == WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "FW %s: request done [%d]\n", aucFilePath, i4Ret); + } else { + DBGLOG(INIT, ERROR, "FW %s: request failed [%d]\n", aucFilePath, i4Ret); + return NULL; + } + + *pu4FileLength = prGlueInfo->prFw->size; + *ppvMapFileBuf = ((u8 *) prGlueInfo->prFw->data); + + return ((u8 *) prGlueInfo->prFw->data); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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); + +} + +#else + +static struct file *filp; +static uid_t orgfsuid; +static gid_t orgfsgid; +static mm_segment_t orgfs; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to +* open firmware image in kernel space +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* +* \retval WLAN_STATUS_SUCCESS. +* \retval WLAN_STATUS_FAILURE. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS kalFirmwareOpen(IN P_GLUE_INFO_T prGlueInfo) +{ + UINT_8 aucFilePath[50]; + + /* FIX ME: since we don't have hotplug script in the filesystem, + * so the request_firmware() KAPI can not work properly + */ + + /* + * save uid and gid used for filesystem access. + * set user and group to 0(root) + */ + struct cred *cred = (struct cred *)get_current_cred(); + + orgfsuid = cred->fsuid.val; + orgfsgid = cred->fsgid.val; + cred->fsuid.val = cred->fsgid.val = 0; + + ASSERT(prGlueInfo); + + orgfs = get_fs(); + set_fs(get_ds()); + + /* open the fw file */ +#if defined(MT6620) & CFG_MULTI_ECOVER_SUPPORT + switch (mtk_wcn_wmt_hwver_get()) { + case WMTHWVER_MT6620_E1: + case WMTHWVER_MT6620_E2: + case WMTHWVER_MT6620_E3: + case WMTHWVER_MT6620_E4: + case WMTHWVER_MT6620_E5: + filp = filp_open("/vendor/firmware/" CFG_FW_FILENAME, O_RDONLY, 0); + break; + + case WMTHWVER_MT6620_E6: + default: + filp = filp_open("/vendor/firmware/" CFG_FW_FILENAME "_E6", O_RDONLY, 0); + break; + } +#elif defined(MT6628) +/* filp = filp_open("/vendor/firmware/"CFG_FW_FILENAME"_MT6628", O_RDONLY, 0); */ +/* filp = filp_open("/vendor/firmware/"CFG_FW_FILENAME"_MT6582", O_RDONLY, 0); */ +#if 0 /* new wifi ram code mechanism, waiting firmware ready, then we can enable these code */ + kalMemZero(aucFilePath, sizeof(aucFilePath)); + kalMemCopy(aucFilePath, "/vendor/firmware/" CFG_FW_FILENAME "_AD", + sizeof("/vendor/firmware/" CFG_FW_FILENAME "_AD")); + filp = filp_open(aucFilePath, O_RDONLY, 0); + if (!IS_ERR(filp)) + goto open_success; +#endif + kalMemZero(aucFilePath, sizeof(aucFilePath)); + kalMemCopy(aucFilePath, "/vendor/firmware/" CFG_FW_FILENAME "_", + strlen("/vendor/firmware/" CFG_FW_FILENAME "_")); + glGetChipInfo(prGlueInfo, &aucFilePath[strlen("/vendor/firmware/" CFG_FW_FILENAME "_")]); + + DBGLOG(INIT, INFO, "open file: %s\n", aucFilePath); + + filp = filp_open(aucFilePath, O_RDONLY, 0); +#else + filp = filp_open("/vendor/firmware/" CFG_FW_FILENAME, O_RDONLY, 0); +#endif + if (IS_ERR(filp)) { + DBGLOG(INIT, ERROR, "Open FW image: %s failed\n", CFG_FW_FILENAME); + goto error_open; + } +#if 0 +open_success: +#endif + DBGLOG(INIT, TRACE, "Open FW image: %s done\n", CFG_FW_FILENAME); + return WLAN_STATUS_SUCCESS; + +error_open: + /* restore */ + set_fs(orgfs); + cred->fsuid.val = orgfsuid; + cred->fsgid.val = orgfsgid; + put_cred(cred); + return WLAN_STATUS_FAILURE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to +* release firmware image in kernel space +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* +* \retval WLAN_STATUS_SUCCESS. +* \retval WLAN_STATUS_FAILURE. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS kalFirmwareClose(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + if ((filp != NULL) && !IS_ERR(filp)) { + /* close firmware file */ + filp_close(filp, NULL); + + /* restore */ + set_fs(orgfs); + { + struct cred *cred = (struct cred *)get_current_cred(); + + cred->fsuid.val = orgfsuid; + cred->fsgid.val = orgfsgid; + put_cred(cred); + } + filp = NULL; + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to +* load firmware image in kernel space +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* +* \retval WLAN_STATUS_SUCCESS. +* \retval WLAN_STATUS_FAILURE. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS kalFirmwareLoad(IN P_GLUE_INFO_T prGlueInfo, OUT PVOID prBuf, IN UINT_32 u4Offset, OUT PUINT_32 pu4Size) +{ + ASSERT(prGlueInfo); + ASSERT(pu4Size); + ASSERT(prBuf); + + /* l = filp->f_path.dentry->d_inode->i_size; */ + + /* the object must have a read method */ + if ((filp == NULL) || IS_ERR(filp) || (filp->f_op == NULL)) { + goto error_read; + } else { + filp->f_pos = u4Offset; + DBGLOG(INIT, INFO, "kalFirmwareLoad read start!\n"); + *pu4Size = __vfs_read(filp, (__force void __user *)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); + + *pu4Size = filp->f_path.dentry->d_inode->i_size; + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to load firmware image +* +* \param pvGlueInfo Pointer of GLUE Data Structure +* \param ppvMapFileBuf Pointer of pointer to memory-mapped firmware image +* \param pu4FileLength File length and memory mapped length as well + +* \retval Map File Handle, used for unammping +*/ +/*----------------------------------------------------------------------------*/ + +PVOID kalFirmwareImageMapping(IN P_GLUE_INFO_T prGlueInfo, OUT PPVOID ppvMapFileBuf, OUT PUINT_32 pu4FileLength) +{ + UINT_32 u4FwSize = 0; + PVOID prFwBuffer = NULL; + + DEBUGFUNC("kalFirmwareImageMapping"); + + ASSERT(prGlueInfo); + ASSERT(ppvMapFileBuf); + ASSERT(pu4FileLength); + + do { + /* <1> Open firmware */ + if (kalFirmwareOpen(prGlueInfo) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, TRACE, "kalFirmwareOpen fail!\n"); + break; + } + + /* <2> Query firmare size */ + kalFirmwareSize(prGlueInfo, &u4FwSize); + /* <3> Use vmalloc for allocating large memory trunk */ + prFwBuffer = vmalloc(ALIGN_4(u4FwSize)); + /* <4> Load image binary into buffer */ + if (kalFirmwareLoad(prGlueInfo, prFwBuffer, 0, &u4FwSize) != WLAN_STATUS_SUCCESS) { + vfree(prFwBuffer); + kalFirmwareClose(prGlueInfo); + DBGLOG(INIT, TRACE, "kalFirmwareLoad fail!\n"); + break; + } + /* <5> write back info */ + *pu4FileLength = u4FwSize; + *ppvMapFileBuf = prFwBuffer; + + return prFwBuffer; + + } while (FALSE); + + return NULL; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to unload firmware image mapped memory +* +* \param pvGlueInfo Pointer of GLUE Data Structure +* \param pvFwHandle Pointer to mapping handle +* \param pvMapFileBuf Pointer to memory-mapped firmware image +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ + +VOID kalFirmwareImageUnmapping(IN P_GLUE_INFO_T prGlueInfo, IN PVOID prFwHandle, IN PVOID pvMapFileBuf) +{ + DEBUGFUNC("kalFirmwareImageUnmapping"); + + ASSERT(prGlueInfo); + + /* pvMapFileBuf might be NULL when file doesn't exist */ + if (pvMapFileBuf) + vfree(pvMapFileBuf); + + kalFirmwareClose(prGlueInfo); +} + +#endif /* OPEN_FIRMWARE_BY_REQUEST */ + +#endif /* CFG_ENABLE_FW_DOWNLOAD */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to acquire +* OS SPIN_LOCK. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] rLockCategory Specify which SPIN_LOCK +* \param[out] pu4Flags Pointer of a variable for saving IRQ flags +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalAcquireSpinLock(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, OUT unsigned long *pu4Flags) +{ + unsigned long u4Flags = 0; + + ASSERT(prGlueInfo); + ASSERT(pu4Flags); + + if (rLockCategory < SPIN_LOCK_NUM) { + +#if CFG_USE_SPIN_LOCK_BOTTOM_HALF + spin_lock_bh(&prGlueInfo->rSpinLock[rLockCategory]); +#else /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + spin_lock_irqsave(&prGlueInfo->rSpinLock[rLockCategory], u4Flags); +#endif /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + + *pu4Flags = u4Flags; +/* DBGLOG(INIT, TRACE, ("A+%d\n", rLockCategory)); */ + } + +} /* end of kalAcquireSpinLock() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to release +* OS SPIN_LOCK. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] rLockCategory Specify which SPIN_LOCK +* \param[in] u4Flags Saved IRQ flags +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID kalReleaseSpinLock(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, IN UINT_32 u4Flags) +{ + ASSERT(prGlueInfo); + + if (rLockCategory < SPIN_LOCK_NUM) { + /* DBGLOG(INIT, TRACE, ("A-%d %d %d\n", rLockCategory, u4MemAllocCnt, u4MemFreeCnt)); */ +#if CFG_USE_SPIN_LOCK_BOTTOM_HALF + spin_unlock_bh(&prGlueInfo->rSpinLock[rLockCategory]); +#else /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + spin_unlock_irqrestore(&prGlueInfo->rSpinLock[rLockCategory], u4Flags); +#endif /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + + } + +} /* end of kalReleaseSpinLock() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to update +* current MAC address. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pucMacAddr Pointer of current MAC address +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID kalUpdateMACAddress(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucMacAddr) +{ + ASSERT(prGlueInfo); + ASSERT(pucMacAddr); + + if (UNEQUAL_MAC_ADDR(prGlueInfo->prDevHandler->dev_addr, pucMacAddr)) + memcpy(prGlueInfo->prDevHandler->dev_addr, pucMacAddr, PARAM_MAC_ADDR_LEN); + +} + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +/*----------------------------------------------------------------------------*/ +/*! +* \brief To query the packet information for offload related parameters. +* +* \param[in] pvPacket Pointer to the packet descriptor. +* \param[in] pucFlag Points to the offload related parameter. +* +* \return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID kalQueryTxChksumOffloadParam(IN PVOID pvPacket, OUT PUINT_8 pucFlag) +{ + struct sk_buff *skb = (struct sk_buff *)pvPacket; + UINT_8 ucFlag = 0; + + ASSERT(pvPacket); + ASSERT(pucFlag); + + + if (skb->ip_summed == CHECKSUM_PARTIAL) { +#if DBG + /* Kevin: do double check, we can remove this part in Normal Driver. + * Because we register NIC feature with NETIF_F_IP_CSUM for MT5912B MAC, so + * we'll process IP packet only. + */ + if (skb->protocol != htons(ETH_P_IP)) { + /* printk("Wrong skb->protocol( = %08x) for TX Checksum Offload.\n", skb->protocol); */ + } else +#endif + ucFlag |= (TX_CS_IP_GEN | TX_CS_TCP_UDP_GEN); + } + + *pucFlag = ucFlag; + +} /* kalQueryChksumOffloadParam */ + +/* 4 2007/10/8, mikewu, this is rewritten by Mike */ +/*----------------------------------------------------------------------------*/ +/*! +* \brief To update the checksum offload status to the packet to be indicated to OS. +* +* \param[in] pvPacket Pointer to the packet descriptor. +* \param[in] pucFlag Points to the offload related parameter. +* +* \return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID kalUpdateRxCSUMOffloadParam(IN PVOID pvPacket, IN ENUM_CSUM_RESULT_T aeCSUM[]) +{ + struct sk_buff *skb = (struct sk_buff *)pvPacket; + + ASSERT(pvPacket); + + if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_SUCCESS || aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_SUCCESS) && + ((aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_SUCCESS) || (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_SUCCESS))) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + } else { + skb->ip_summed = CHECKSUM_NONE; +#if DBG + if (aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_NONE && aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_NONE) + DBGLOG(RX, TRACE, "RX: \"non-IPv4/IPv6\" Packet\n"); + else if (aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_FAILED) + DBGLOG(RX, TRACE, "RX: \"bad IP Checksum\" Packet\n"); + else if (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_FAILED) + DBGLOG(RX, TRACE, "RX: \"bad TCP Checksum\" Packet\n"); + else if (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_FAILED) + DBGLOG(RX, TRACE, "RX: \"bad UDP Checksum\" Packet\n"); + else + /* Do nothing */ +#endif + } + +} /* kalUpdateRxCSUMOffloadParam */ +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to free packet allocated from kalPacketAlloc. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pvPacket Pointer of the packet descriptor +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID kalPacketFree(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket) +{ + dev_kfree_skb((struct sk_buff *)pvPacket); + if (prGlueInfo) + prGlueInfo->u8SkbFreed++; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Only handles driver own creating packet (coalescing buffer). +* +* \param prGlueInfo Pointer of GLUE Data Structure +* \param u4Size Pointer of Packet Handle +* \param ppucData Status Code for OS upper layer +* +* \return NULL: Failed to allocate skb, Not NULL get skb +*/ +/*----------------------------------------------------------------------------*/ +PVOID kalPacketAlloc(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Size, OUT PPUINT_8 ppucData) +{ + struct sk_buff *prSkb = dev_alloc_skb(u4Size); + + if (prSkb) + *ppucData = (PUINT_8) (prSkb->data); +#if DBG + { + PUINT_32 pu4Head = (PUINT_32) &prSkb->cb[0]; + *pu4Head = (UINT_32) prSkb->head; + DBGLOG(RX, TRACE, "prSkb->head = %#x, prSkb->cb = %#x\n", (UINT_32) prSkb->head, *pu4Head); + } +#endif + return (PVOID) prSkb; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Process the received packet for indicating to OS. +* +* \param[in] prGlueInfo Pointer to the Adapter structure. +* \param[in] pvPacket Pointer of the packet descriptor +* \param[in] pucPacketStart The starting address of the buffer of Rx packet. +* \param[in] u4PacketLen The packet length. +* \param[in] pfgIsRetain Is the packet to be retained. +* \param[in] aerCSUM The result of TCP/ IP checksum offload. +* +* \retval WLAN_STATUS_SUCCESS. +* \retval WLAN_STATUS_FAILURE. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +kalProcessRxPacket(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket, IN PUINT_8 pucPacketStart, IN UINT_32 u4PacketLen, + /* IN PBOOLEAN pfgIsRetain, */ + IN BOOLEAN fgIsRetain, IN ENUM_CSUM_RESULT_T aerCSUM[]) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + if (pvPacket == NULL) { + DBGLOG(INIT, WARN, "%s: pvPacket is a null value\n", __func__); + rStatus = WLAN_STATUS_FAILURE; + } else { + + struct sk_buff *skb = (struct sk_buff *)pvPacket; + + skb->data = pucPacketStart; + /* reset tail pointer first, for 64bit kernel,we should call linux kernel API */ + skb_reset_tail_pointer(skb); + /* only if skb->len > len, then skb_trim has effect */ + skb_trim(skb, 0); + /* shift tail and skb->len to correct value */ + skb_put(skb, u4PacketLen); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + kalUpdateRxCSUMOffloadParam(skb, aerCSUM); +#endif + } + + return rStatus; +} + +#if (CONF_HIF_LOOPBACK_AUTO == 1) +/*----------------------------------------------------------------------------*/ +/*! +* \brief Do HIF loopback test. +* +* \param[in] GlueInfo Pointer to the GLUE_INFO_T structure. +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +unsigned int testmode; +unsigned int testlen = 64; + +void kalDevLoopbkAuto(IN P_GLUE_INFO_T GlueInfo) +{ +#define HIF_LOOPBK_AUTO_TEST_LEN 1600 +/* GL_HIF_INFO_T *HifInfo; */ + static unsigned int txcnt; + struct sk_buff *MsduInfo; + UINT_8 *Pkt; + UINT_32 RegVal; + UINT_32 PktLen = 16; + + /* Init */ + if (testmode != 0) { + PktLen = kalRandomNumber() % 1520; + if (PktLen < 64) + PktLen = 64; + } else { + PktLen = testlen++; + if (PktLen > 1520) { + testmode = 1; + PktLen = 64; + } + } + +/* PktLen = 100; */ + DBGLOG(INIT, INFO, "kalDevLoopbkAuto> Send a packet to HIF (len = %d) (total = %d)...\n", PktLen, ++txcnt); +/* HifInfo = &GlueInfo->rHifInfo; */ + + /* Allocate a MSDU_INFO_T */ + MsduInfo = kalPacketAlloc(GlueInfo, HIF_LOOPBK_AUTO_TEST_LEN, &Pkt); + if (MsduInfo == NULL) { + DBGLOG(INIT, WARN, "No PKT_INFO_T for sending loopback packet!\n"); + return; + } + + /* Init the packet */ + MsduInfo->dev = GlueInfo->prDevHandler; + if (MsduInfo->dev == NULL) { + DBGLOG(INIT, WARN, "MsduInfo->dev == NULL!!\n"); + kalPacketFree(GlueInfo, MsduInfo); + return; + } + + MsduInfo->len = PktLen; + kalMemSet(MsduInfo->data, 0xff, 6); + kalMemSet(MsduInfo->data + 6, 0x5a, PktLen - 6); + + /* Simulate OS to send the packet */ + wlanHardStartXmit(MsduInfo, MsduInfo->dev); + +#if 0 + PktLen += 4; + if (PktLen >= 1600) + PktLen = 16; +#endif + + /* Note: in FPGA, clock is not accuracy so 3000 here, not 10000 */ +/* HifInfo->HifTmrLoopbkFn.expires = jiffies + MSEC_TO_SYSTIME(1000); */ +/* add_timer(&(HifInfo->HifTmrLoopbkFn)); */ +} + +int kalDevLoopbkThread(IN void *data) +{ + struct net_device *dev = data; + P_GLUE_INFO_T GlueInfo = *((P_GLUE_INFO_T *) netdev_priv(dev)); + GL_HIF_INFO_T *HifInfo = &GlueInfo->rHifInfo; + int ret; + static int test; + + while (TRUE) { + ret = wait_event_interruptible(HifInfo->HifWaitq, (HifInfo->HifLoopbkFlg != 0)); + + if (HifInfo->HifLoopbkFlg == 0xFFFFFFFF) + break; + + while (TRUE) { + /* if ((HifInfo->HifLoopbkFlg & 0x01) == 0) */ + if (GlueInfo->i4TxPendingFrameNum < 64) { + DBGLOG(INIT, INFO, "GlueInfo->i4TxPendingFrameNum = %d\n", + GlueInfo->i4TxPendingFrameNum); + kalDevLoopbkAuto(GlueInfo); + + if (testmode == 0) + kalMsleep(3000); + } else + kalMsleep(1); + } + } +} + +void kalDevLoopbkRxHandle(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) +{ + static unsigned int rxcnt; + UINT_32 i; + UINT_8 *Buf = prSwRfb->pucRecvBuff + sizeof(HIF_TX_HEADER_T); + P_HIF_RX_HEADER_T prHifRxHdr = prSwRfb->prHifRxHdr; + UINT_32 len = prHifRxHdr->u2PacketLen - sizeof(HIF_TX_HEADER_T); + + if (len > 1600) { + while (1) + DBGLOG(INIT, ERROR, "HIF> Loopback len > 1600!!! error!!!\n"); + } + + for (i = 0; i < 6; i++) { + if (Buf[i] != 0xff) { + while (1) { + DBGLOG(INIT, ERROR, "HIF> Loopbk dst addr error (len = %d)!\n", len); + dumpMemory8(prSwRfb->pucRecvBuff, prHifRxHdr->u2PacketLen); + } + } + } + + for (i = 6; i < len; i++) { + if (Buf[i] != 0x5a) { + while (1) { + DBGLOG(INIT, ERROR, "HIF> Loopbk error (len = %d)!\n", len); + dumpMemory8(prSwRfb->pucRecvBuff, prHifRxHdr->u2PacketLen); + } + } + } + + DBGLOG(INIT, INFO, "HIF> Loopbk OK (len = %d) (total = %d)!\n", len, ++rxcnt); +} +#endif /* CONF_HIF_LOOPBACK_AUTO */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate an array of received packets is available for higher +* level protocol uses. +* +* \param[in] prGlueInfo Pointer to the Adapter structure. +* \param[in] apvPkts The packet array to be indicated +* \param[in] ucPktNum The number of packets to be indicated +* +* \retval TRUE Success. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS kalRxIndicatePkts(IN P_GLUE_INFO_T prGlueInfo, IN PVOID apvPkts[], IN UINT_8 ucPktNum) +{ + UINT_8 ucIdx = 0; + struct net_device *prNetDev = prGlueInfo->prDevHandler; + struct sk_buff *prSkb = NULL; + + ASSERT(prGlueInfo); + ASSERT(apvPkts); + +#if CFG_BOW_TEST + UINT_32 i; +#endif + + for (ucIdx = 0; ucIdx < ucPktNum; ucIdx++) { + prSkb = apvPkts[ucIdx]; +#if DBG + do { + PUINT_8 pu4Head = (PUINT_8) &prSkb->cb[0]; + UINT_32 u4HeadValue = 0; + + kalMemCopy(&u4HeadValue, pu4Head, sizeof(u4HeadValue)); + DBGLOG(RX, TRACE, "prSkb->head = %p, prSkb->cb = 0x%x\n", pu4Head, u4HeadValue); + } while (0); +#endif + + if (GLUE_GET_PKT_IS_P2P(prSkb)) { + /* P2P */ +#if CFG_ENABLE_WIFI_DIRECT + if (prGlueInfo->prAdapter->fgIsP2PRegistered) + prNetDev = kalP2PGetDevHdlr(prGlueInfo); + /* prNetDev->stats.rx_bytes += prSkb->len; */ + /* prNetDev->stats.rx_packets++; */ + prGlueInfo->prP2PInfo->rNetDevStats.rx_bytes += prSkb->len; + prGlueInfo->prP2PInfo->rNetDevStats.rx_packets++; +#if (CFG_SUPPORT_TDLS == 1) + MTKTdlsApStaUpdateTxRxStatus(prGlueInfo, 0, prSkb->len, prSkb->data + 6); +#endif +#else + prNetDev = prGlueInfo->prDevHandler; +#endif + } else if (GLUE_GET_PKT_IS_PAL(prSkb)) { + /* BOW */ +#if CFG_ENABLE_BT_OVER_WIFI && CFG_BOW_SEPARATE_DATA_PATH + if (prGlueInfo->rBowInfo.fgIsNetRegistered) + prNetDev = prGlueInfo->rBowInfo.prDevHandler; +#else + prNetDev = prGlueInfo->prDevHandler; +#endif + } else { + /* AIS */ + prNetDev = prGlueInfo->prDevHandler; + prGlueInfo->rNetDevStats.rx_bytes += prSkb->len; + prGlueInfo->rNetDevStats.rx_packets++; + + } + + /* check if the "unicast" packet is from us */ + if (kalMemCmp(prSkb->data, prSkb->data + 6, 6) == 0) { + /* we will filter broadcast/multicast packet sent from us in hardware */ + /* source address = destination address ? */ + DBGLOG(RX, EVENT, + "kalRxIndicatePkts got from us!!! Drop it! ([ %pM ] len %d)\n", + prSkb->data, prSkb->len); + wlanReturnPacket(prGlueInfo->prAdapter, prSkb); + continue; + } +#if (CFG_SUPPORT_TDLS == 1) + if (TdlsexRxFrameDrop(prGlueInfo, prSkb) == TRUE) { + /* drop the received TDLS action frame */ + DBGLOG(TDLS, WARN, + " %s: drop a received packet from %pM %u\n", + __func__, prSkb->data, + (UINT32) ((P_ADAPTER_T) (prGlueInfo->prAdapter))->rRxCtrl.rFreeSwRfbList.u4NumElem); + wlanReturnPacket(prGlueInfo->prAdapter, prSkb); + continue; + } + + /* + * get a TDLS request/response/confirm, we need to parse the HT IE + * because older supplicant does not pass HT IE to us + */ + TdlsexRxFrameHandle(prGlueInfo, prSkb); +#endif /* CFG_SUPPORT_TDLS */ + + STATS_RX_PKT_INFO_DISPLAY(prSkb->data); + +#if KERNEL_VERSION(4, 11, 0) <= CFG80211_VERSION_CODE + /* ToDo jiffies assignment */ +#else + prNetDev->last_rx = jiffies; +#endif + prSkb->protocol = eth_type_trans(prSkb, prNetDev); + prSkb->dev = prNetDev; + /* DBGLOG_MEM32(RX, TRACE, (PUINT_32)prSkb->data, prSkb->len); */ + DBGLOG(RX, TRACE, "kalRxIndicatePkts len = %d\n", prSkb->len); + +#if CFG_BOW_TEST + DBGLOG(BOW, TRACE, "Rx sk_buff->len: %d\n", prSkb->len); + DBGLOG(BOW, TRACE, "Rx sk_buff->data_len: %d\n", prSkb->data_len); + DBGLOG(BOW, TRACE, "Rx sk_buff->data:\n"); + + for (i = 0; i < prSkb->len; i++) { + DBGLOG(BOW, TRACE, "%4x", prSkb->data[i]); + + if ((i + 1) % 16 == 0) + DBGLOG(BOW, TRACE, "\n"); + } + + DBGLOG(BOW, TRACE, "\n"); +#endif + + if (!in_interrupt()) + netif_rx_ni(prSkb); /* only in non-interrupt context */ + else + netif_rx(prSkb); + + wlanReturnPacket(prGlueInfo->prAdapter, NULL); + } + + if (netif_carrier_ok(prNetDev)) + kalPerMonStart(prGlueInfo); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Called by driver to indicate event to upper layer, for example, the wpa +* supplicant or wireless tools. +* +* \param[in] pvAdapter Pointer to the adapter descriptor. +* \param[in] eStatus Indicated status. +* \param[in] pvBuf Indicated message buffer. +* \param[in] u4BufLen Indicated message buffer size. +* +* \return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 ScanCnt = 0, ScanDoneFailCnt = 0; +VOID +kalIndicateStatusAndComplete(IN P_GLUE_INFO_T prGlueInfo, IN WLAN_STATUS eStatus, IN PVOID pvBuf, IN UINT_32 u4BufLen) +{ + UINT_32 bufLen; + P_PARAM_STATUS_INDICATION_T pStatus = (P_PARAM_STATUS_INDICATION_T) pvBuf; +#if (CFG_REFACTORY_PMKSA == 0) + 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); +#else + struct PARAM_INDICATION_EVENT *prEvent = (struct PARAM_INDICATION_EVENT *) pvBuf; +#endif + + PARAM_MAC_ADDRESS arBssid; + PARAM_SSID_T ssid; + struct ieee80211_channel *prChannel = NULL; + struct cfg80211_bss *bss; + UINT_8 ucChannelNum; + P_BSS_DESC_T prBssDesc = NULL; + UINT_16 u2StatusCode = WLAN_STATUS_AUTH_TIMEOUT; + OS_SYSTIME rCurrentTime; + BOOLEAN fgIsNeedUpdateBss = FALSE; + P_CONNECTION_SETTINGS_T prConnSettings; + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE + struct cfg80211_roam_info rRoamInfo = { 0 }; +#endif + + GLUE_SPIN_LOCK_DECLARATION(); + + kalMemZero(arBssid, MAC_ADDR_LEN); + GET_CURRENT_SYSTIME(&rCurrentTime); + + ASSERT(prGlueInfo); + + switch (eStatus) { + case WLAN_STATUS_ROAM_OUT_FIND_BEST: + case WLAN_STATUS_MEDIA_CONNECT: + + prGlueInfo->eParamMediaStateIndicated = PARAM_MEDIA_STATE_CONNECTED; + + /* indicate assoc event */ + wlanQueryInformation(prGlueInfo->prAdapter, wlanoidQueryBssid, &arBssid[0], sizeof(arBssid), &bufLen); + wext_indicate_wext_event(prGlueInfo, SIOCGIWAP, arBssid, bufLen); + + /* switch netif on */ + netif_carrier_on(prGlueInfo->prDevHandler); + + do { + /* print message on console */ + wlanQueryInformation(prGlueInfo->prAdapter, wlanoidQuerySsid, &ssid, sizeof(ssid), &bufLen); + + ssid.aucSsid[(ssid.u4SsidLen >= PARAM_MAX_LEN_SSID) ? + (PARAM_MAX_LEN_SSID - 1) : ssid.u4SsidLen] = '\0'; + DBGLOG(AIS, INFO, " %s netif_carrier_on [ssid:%s %pM ], status=%u\n", + prGlueInfo->prDevHandler->name, + HIDE(ssid.aucSsid), arBssid, eStatus); + } while (0); + + if (prGlueInfo->fgIsRegistered == TRUE) { + struct cfg80211_bss *bss_others = NULL; + UINT_8 ucLoopCnt = 15; /* only loop 15 times to avoid dead loop */ + + /* retrieve channel */ + ucChannelNum = wlanGetChannelNumberByNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_AIS_INDEX); + if (ucChannelNum <= 14) { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, + IEEE80211_BAND_2GHZ)); + } else { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, + IEEE80211_BAND_5GHZ)); + } + + if (!prChannel) + DBGLOG(SCN, ERROR, "prChannel is NULL and ucChannelNum is %d\n", ucChannelNum); + + /* ensure BSS exists */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + bss = cfg80211_get_bss(priv_to_wiphy(prGlueInfo), prChannel, arBssid, + ssid.aucSsid, ssid.u4SsidLen, IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY); +#else + bss = cfg80211_get_bss(priv_to_wiphy(prGlueInfo), prChannel, arBssid, + ssid.aucSsid, ssid.u4SsidLen, 0, 0); +#endif + if (!bss) + DBGLOG(SCN, INFO, "cfg80211_get_bss failed: channel(%d)\n", ucChannelNum); + + prBssDesc = + wlanGetTargetBssDescByNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_AIS_INDEX); + + if (prBssDesc != NULL) { + /* + * cfg80211 bss expire time is 7s. if bss in driver older then 5s, + * update to cfg80211 again. + */ + if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, SEC_TO_SYSTIME(5))) { + fgIsNeedUpdateBss = TRUE; + DBGLOG(SCN, INFO, " Bss age > 5s, update bss to cfg80211.\n"); + } + } + if (bss == NULL || fgIsNeedUpdateBss == TRUE) { + /* create BSS on-the-fly */ + if ((prBssDesc != NULL) && (prChannel != NULL)) { + bss = cfg80211_inform_bss(priv_to_wiphy(prGlueInfo), prChannel, + CFG80211_BSS_FTYPE_UNKNOWN, + 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); + if (!bss) { + DBGLOG(SCN, WARN, + "inform_bss failed, BSSID[%pM/%pM] SSID[%s] Chnl[%d/%d] RCPI[%d] IELng[%d] Bcn[%d]\n", + prBssDesc->aucBSSID, arBssid, HIDE(prBssDesc->aucSSID), + prBssDesc->ucChannelNum, ucChannelNum, + RCPI_TO_dBm(prBssDesc->ucRCPI), + prBssDesc->u2IELength, prBssDesc->u2BeaconInterval); + DBGLOG_MEM8_IE_ONE_LINE(SCN, WARN, + "kalIndicateStatusAndComplete:inform_bss", + prBssDesc->aucIEBuf, prBssDesc->u2IELength); + } else { + DBGLOG(SCN, INFO, + "inform_bss, BSSID[%pM/%pM] SSID[%s] Chnl[%d/%d] RCPI[%d] IELng[%d] Bcn[%d]\n", + prBssDesc->aucBSSID, arBssid, HIDE(prBssDesc->aucSSID), + prBssDesc->ucChannelNum, ucChannelNum, + RCPI_TO_dBm(prBssDesc->ucRCPI), + prBssDesc->u2IELength, prBssDesc->u2BeaconInterval); + } + } else { + DBGLOG(SCN, WARN, "prBssDesc(%d) prChannel(%d)", + (prBssDesc) ? 1 : 0, (prChannel) ? 1 : 0); + } + } + /* + * remove all bsses that before and only channel different with the current connected one + * if without this patch, UI will show channel A is connected even if AP has change channel + * from A to B + */ + while (ucLoopCnt--) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + bss_others = cfg80211_get_bss(priv_to_wiphy(prGlueInfo), NULL, arBssid, + ssid.aucSsid, ssid.u4SsidLen, IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY); +#else + bss_others = cfg80211_get_bss(priv_to_wiphy(prGlueInfo), NULL, arBssid, + ssid.aucSsid, ssid.u4SsidLen, 0, 0); +#endif + if (bss && bss_others && bss_others != bss) { + DBGLOG(SCN, INFO, "remove BSSes that only channel different\n"); + cfg80211_unlink_bss(priv_to_wiphy(prGlueInfo), bss_others); + } else + break; + } + + /* CFG80211 Indication */ + if (eStatus == WLAN_STATUS_ROAM_OUT_FIND_BEST) { +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE + rRoamInfo.bss = bss; + rRoamInfo.req_ie = prGlueInfo->aucReqIe; + rRoamInfo.req_ie_len = + prGlueInfo->u4ReqIeLength; + rRoamInfo.resp_ie = prGlueInfo->aucRspIe; + rRoamInfo.resp_ie_len = + prGlueInfo->u4RspIeLength; + + cfg80211_roamed(prGlueInfo->prDevHandler, + &rRoamInfo, GFP_KERNEL); +#else + cfg80211_roamed_bss(prGlueInfo->prDevHandler, + bss, + prGlueInfo->aucReqIe, + prGlueInfo->u4ReqIeLength, + prGlueInfo->aucRspIe, prGlueInfo->u4RspIeLength, GFP_KERNEL); +#endif + } else { + /* + * to support user space roaming, cfg80211 will change the sme_state to connecting + * before reassociate + */ + cfg80211_connect_result(prGlueInfo->prDevHandler, + arBssid, + prGlueInfo->aucReqIe, + prGlueInfo->u4ReqIeLength, + prGlueInfo->aucRspIe, + prGlueInfo->u4RspIeLength, WLAN_STATUS_SUCCESS, GFP_KERNEL); + } + } + + break; + + case WLAN_STATUS_MEDIA_DISCONNECT: + case WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY: + /* indicate disassoc event */ + wext_indicate_wext_event(prGlueInfo, SIOCGIWAP, NULL, 0); + /* + * For CR 90 and CR99, While supplicant do reassociate, driver will do netif_carrier_off first, + * after associated success, at joinComplete(), do netif_carier_on, + * but for unknown reason, the supplicant 1x pkt will not called the driver + * hardStartXmit, for template workaround these bugs, add this compiling flag + */ + /* switch netif off */ + + DBGLOG(AIS, INFO, "[wifi] %s netif_carrier_off\n", + prGlueInfo->prDevHandler->name); + + netif_carrier_off(prGlueInfo->prDevHandler); + + /*Full2Partial*/ + /*at here, should init u4LastFullScanTime, ucTrScanType, ucChannelListNum, ucChannelNum*/ + DBGLOG(INIT, TRACE, "Full2Partial disconenct reset value\n"); + prGlueInfo->u4LastFullScanTime = 0; + prGlueInfo->ucTrScanType = 0; + kalMemSet(prGlueInfo->ucChannelNum, 0, FULL_SCAN_MAX_CHANNEL_NUM); + if (prGlueInfo->puFullScan2PartialChannel != NULL) { + kalMemFree(prGlueInfo->puFullScan2PartialChannel, + VIR_MEM_TYPE, sizeof(PARTIAL_SCAN_INFO)); + prGlueInfo->puFullScan2PartialChannel = NULL; + } + + if (prGlueInfo->fgIsRegistered == TRUE) { + P_WIFI_VAR_T prWifiVar = &prGlueInfo->prAdapter->rWifiVar; + UINT_16 u2DeauthReason = prWifiVar->arBssInfo[NETWORK_TYPE_AIS_INDEX].u2DeauthReason; + /* CFG80211 Indication */ + DBGLOG(AIS, INFO, "[wifi] %s cfg80211_disconnected: Reason=%d\n", + prGlueInfo->prDevHandler->name, u2DeauthReason); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + cfg80211_disconnected(prGlueInfo->prDevHandler, u2DeauthReason, NULL, 0, + eStatus == WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY ? true : false, GFP_KERNEL); +#else + cfg80211_disconnected(prGlueInfo->prDevHandler, u2DeauthReason, NULL, 0, GFP_KERNEL); +#endif + } + prConnSettings = &prGlueInfo->prAdapter->rWifiVar.rConnSettings; + if (prConnSettings && prConnSettings->assocIeLen > 0) { + kalMemFree(prConnSettings->pucAssocIEs, VIR_MEM_TYPE, + prConnSettings->assocIeLen); + prConnSettings->assocIeLen = 0; + } + kalMemFree(prGlueInfo->rFtIeForTx.pucIEBuf, VIR_MEM_TYPE, prGlueInfo->rFtIeForTx.u4IeLength); + kalMemZero(&prGlueInfo->rFtIeForTx, sizeof(prGlueInfo->rFtIeForTx)); + 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 */ + DBGLOG(SCN, TRACE, "[ais] scan complete %p %d %d\n", + prGlueInfo->prScanRequest, ScanCnt, ScanDoneFailCnt); + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if (prGlueInfo->prScanRequest != NULL) { + kalCfg80211ScanDone(prGlueInfo->prScanRequest, FALSE); + prGlueInfo->prScanRequest = NULL; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + break; + + case WLAN_STATUS_JOIN_FAILURE: + if (pvBuf) + u2StatusCode = *(UINT_16 *)pvBuf; + + prBssDesc = prGlueInfo->prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc; + + DBGLOG(INIT, INFO, "JOIN Failure: u2StatusCode=%d", u2StatusCode); + if (prBssDesc) + COPY_MAC_ADDR(arBssid, prBssDesc->aucBSSID); + else + COPY_MAC_ADDR(arBssid, prGlueInfo->prAdapter->rWifiVar.rConnSettings.aucBSSID); + + /* indicate AIS Jion fail event + *if (prGlueInfo->prDevHandler->ieee80211_ptr->sme_state == CFG80211_SME_CONNECTING) + */ + if (prBssDesc && u2StatusCode + && u2StatusCode != STATUS_CODE_AUTH_TIMEOUT + && u2StatusCode != STATUS_CODE_ASSOC_TIMEOUT) + cfg80211_connect_result(prGlueInfo->prDevHandler, + arBssid, + prGlueInfo->aucReqIe, + prGlueInfo->u4ReqIeLength, + prGlueInfo->aucRspIe, + prGlueInfo->u4RspIeLength, + u2StatusCode, GFP_KERNEL); + else + cfg80211_connect_result(prGlueInfo->prDevHandler, + arBssid, + prGlueInfo->aucReqIe, + prGlueInfo->u4ReqIeLength, + prGlueInfo->aucRspIe, + prGlueInfo->u4RspIeLength, + STATUS_CODE_AUTH_TIMEOUT, GFP_KERNEL); + prGlueInfo->eParamMediaStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; + break; + +#if 0 + case WLAN_STATUS_MSDU_OK: + if (netif_running(prGlueInfo->prDevHandler)) + netif_wake_queue(prGlueInfo->prDevHandler); + break; +#endif + + case WLAN_STATUS_MEDIA_SPECIFIC_INDICATION: + if (pStatus) { + switch (pStatus->eStatusType) { + case ENUM_STATUS_TYPE_AUTHENTICATION: + /* + * printk(KERN_NOTICE "ENUM_STATUS_TYPE_AUTHENTICATION: L(%ld) [ %pM ] F:%lx\n", + * pAuth->Request[0].Length, + * pAuth->Request[0].Bssid, + * pAuth->Request[0].Flags); + */ + /* indicate (UC/GC) MIC ERROR event only */ +#if (CFG_REFACTORY_PMKSA == 0) + 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); + } +#else + if ((prEvent->rAuthReq.u4Flags == + PARAM_AUTH_REQUEST_PAIRWISE_ERROR) || + (prEvent->rAuthReq.u4Flags == PARAM_AUTH_REQUEST_GROUP_ERROR)) { + cfg80211_michael_mic_failure( + prGlueInfo->prDevHandler, NULL, + (prEvent->rAuthReq.u4Flags == + PARAM_AUTH_REQUEST_PAIRWISE_ERROR) + ? NL80211_KEYTYPE_PAIRWISE : + NL80211_KEYTYPE_GROUP, + 0, NULL, GFP_KERNEL); + wext_indicate_wext_event(prGlueInfo, + IWEVMICHAELMICFAILURE, + (unsigned char *) + &prEvent->rAuthReq, + prEvent->rAuthReq.u4Length); + } +#endif + + break; + + case ENUM_STATUS_TYPE_CANDIDATE_LIST: + /* + * printk(KERN_NOTICE "Param_StatusType_PMKID_CandidateList: Ver(%ld) Num(%ld)\n", + * pPmkid->u2Version, + * pPmkid->u4NumCandidates); + * if (pPmkid->u4NumCandidates > 0) { + * printk(KERN_NOTICE "candidate[ %pM ] preAuth Flag:%lx\n", + * pPmkid->arCandidateList[0].rBSSID, + * pPmkid->arCandidateList[0].fgFlags); + * } + */ + { +#if (CFG_REFACTORY_PMKSA == 0) + UINT_32 i = 0; + /*struct net_device *prDev = prGlueInfo->prDevHandler; */ + P_PARAM_PMKID_CANDIDATE_T prCand = NULL; + /* + * indicate pmk candidate via cfg80211 to supplicant, + * the second parameter is 1000 for + * cfg80211_pmksa_candidate_notify, because wpa_supplicant defined it. + */ + for (i = 0; i < pPmkid->u4NumCandidates; i++) { + prCand = &pPmkid->arCandidateList[i]; + cfg80211_pmksa_candidate_notify(prGlueInfo->prDevHandler, 1000, + prCand->arBSSID, prCand->u4Flags, + GFP_KERNEL); + + wext_indicate_wext_event(prGlueInfo, + IWEVPMKIDCAND, + (unsigned char *)prCand, + pPmkid->u4NumCandidates); + } +#else + cfg80211_pmksa_candidate_notify( + prGlueInfo->prDevHandler, + 1000, + prEvent->rCandi.arBSSID, + prEvent->rCandi.u4Flags, + GFP_KERNEL); + + wext_indicate_wext_event( + prGlueInfo, + IWEVPMKIDCAND, + (unsigned char *) &prEvent->rCandi, + sizeof(PARAM_PMKID_CANDIDATE_T)); +#endif + } + break; + case ENUM_STATUS_TYPE_FT_AUTH_STATUS: + cfg80211_ft_event(prGlueInfo->prDevHandler, &prGlueInfo->rFtEventParam); + break; + default: + /* case ENUM_STATUS_TYPE_MEDIA_STREAM_MODE */ + /* + * printk(KERN_NOTICE "unknown media specific indication type:%x\n", + * pStatus->StatusType); + */ + break; + } + } else { + /* + * printk(KERN_WARNING "media specific indication buffer NULL\n"); + */ + } + break; + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS + case WLAN_STATUS_BWCS_UPDATE: + { + wext_indicate_wext_event(prGlueInfo, IWEVCUSTOM, pvBuf, sizeof(PTA_IPC_T)); + } + + break; + +#endif + + default: + /* + * printk(KERN_WARNING "unknown indication:%lx\n", eStatus); + */ + break; + } +} /* kalIndicateStatusAndComplete */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to update the (re)association request + * information to the structure used to query and set + * OID_802_11_ASSOCIATION_INFORMATION. + * + * \param[in] prGlueInfo Pointer to the Glue structure. + * \param[in] pucFrameBody Pointer to the frame body of the last (Re)Association + * Request frame from the AP. + * \param[in] u4FrameBodyLen The length of the frame body of the last + * (Re)Association Request frame. + * \param[in] fgReassocRequest TRUE, if it is a Reassociation Request frame. + * + * \return (none) + * + */ +/*----------------------------------------------------------------------------*/ +VOID +kalUpdateReAssocReqInfo(IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBody, IN UINT_32 u4FrameBodyLen, IN BOOLEAN fgReassocRequest) +{ + PUINT_8 cp; + + ASSERT(prGlueInfo); + + /* reset */ + prGlueInfo->u4ReqIeLength = 0; + + if (fgReassocRequest) { + if (u4FrameBodyLen < 15) { + /* + * printk(KERN_WARNING "frameBodyLen too short:%ld\n", frameBodyLen); + */ + return; + } + } else { + if (u4FrameBodyLen < 9) { + /* + * printk(KERN_WARNING "frameBodyLen too short:%ld\n", frameBodyLen); + */ + return; + } + } + + cp = pucFrameBody; + + if (fgReassocRequest) { + /* Capability information field 2 */ + /* Listen interval field 2 */ + /* Current AP address 6 */ + cp += 10; + u4FrameBodyLen -= 10; + } else { + /* Capability information field 2 */ + /* Listen interval field 2 */ + cp += 4; + u4FrameBodyLen -= 4; + } + + wext_indicate_wext_event(prGlueInfo, IWEVASSOCREQIE, cp, u4FrameBodyLen); + + if (u4FrameBodyLen <= CFG_CFG80211_IE_BUF_LEN) { + prGlueInfo->u4ReqIeLength = u4FrameBodyLen; + kalMemCopy(prGlueInfo->aucReqIe, cp, u4FrameBodyLen); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is called to update the (re)association + * response information to the structure used to reply with + * cfg80211_connect_result + * + * @param prGlueInfo Pointer to adapter descriptor + * @param pucFrameBody Pointer to the frame body of the last (Re)Association + * Response frame from the AP + * @param u4FrameBodyLen The length of the frame body of the last + * (Re)Association Response frame + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +VOID kalUpdateReAssocRspInfo(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucFrameBody, IN UINT_32 u4FrameBodyLen) +{ + UINT_32 u4IEOffset = 6; /* cap_info, status_code & assoc_id */ + UINT_32 u4IELength = u4FrameBodyLen - u4IEOffset; + + ASSERT(prGlueInfo); + + /* reset */ + prGlueInfo->u4RspIeLength = 0; + + if (u4IELength <= CFG_CFG80211_IE_BUF_LEN) { + prGlueInfo->u4RspIeLength = u4IELength; + kalMemCopy(prGlueInfo->aucRspIe, pucFrameBody + u4IEOffset, u4IELength); + } + +} /* kalUpdateReAssocRspInfo */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Notify OS with SendComplete event of the specific packet. Linux should + * free packets here. + * + * \param[in] prGlueInfo Pointer of GLUE Data Structure + * \param[in] pvPacket Pointer of Packet Handle + * \param[in] status Status Code for OS upper layer + * + * \return - + */ +/*----------------------------------------------------------------------------*/ +VOID kalSendCompleteAndAwakeQueue(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket) +{ + + struct net_device *prDev = NULL; + struct sk_buff *prSkb = NULL; + UINT_16 u2QueueIdx = 0; + UINT_8 ucNetworkType = 0; + BOOLEAN fgIsValidDevice = TRUE; + + ASSERT(pvPacket); + ASSERT(prGlueInfo->i4TxPendingFrameNum); + + prSkb = (struct sk_buff *)pvPacket; + u2QueueIdx = skb_get_queue_mapping(prSkb); + ASSERT(u2QueueIdx < CFG_MAX_TXQ_NUM); + + if (GLUE_GET_PKT_IS_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 if (GLUE_GET_PKT_IS_PAL(prSkb)) { + ucNetworkType = NETWORK_TYPE_BOW_INDEX; + } else { + ucNetworkType = NETWORK_TYPE_AIS_INDEX; + } + + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingFrameNum); + if (u2QueueIdx < CFG_MAX_TXQ_NUM) + GLUE_DEC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[ucNetworkType][u2QueueIdx]); + prDev = prSkb->dev; + + ASSERT(prDev); + + if ((fgIsValidDevice == TRUE) && (u2QueueIdx < CFG_MAX_TXQ_NUM)) { + if (netif_subqueue_stopped(prDev, prSkb) && + prGlueInfo->ai4TxPendingFrameNumPerQueue[ucNetworkType][u2QueueIdx] <= + CFG_TX_START_NETIF_PER_QUEUE_THRESHOLD) { + DBGLOG(TX, INFO, "netif_wake_subqueue for bss: %d. Queue len: %d\n", + ucNetworkType, + prGlueInfo->ai4TxPendingFrameNumPerQueue[ucNetworkType][u2QueueIdx]); + netif_wake_subqueue(prDev, u2QueueIdx); + +#if (CONF_HIF_LOOPBACK_AUTO == 1) + prGlueInfo->rHifInfo.HifLoopbkFlg &= ~0x01; +#endif /* CONF_HIF_LOOPBACK_AUTO */ + } + } + + dev_kfree_skb((struct sk_buff *)pvPacket); + prGlueInfo->u8SkbFreed++; + + DBGLOG(TX, EVENT, "----- pending frame %d -----\n", prGlueInfo->i4TxPendingFrameNum); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Copy Mac Address setting from registry. It's All Zeros in Linux. + * + * \param[in] prAdapter Pointer to the Adapter structure + * + * \param[out] paucMacAddr Pointer to the Mac Address buffer + * + * \retval WLAN_STATUS_SUCCESS + * + * \note + */ +/*----------------------------------------------------------------------------*/ +VOID kalQueryRegistryMacAddr(IN P_GLUE_INFO_T prGlueInfo, OUT PUINT_8 paucMacAddr) +{ + UINT_8 aucZeroMac[MAC_ADDR_LEN] = { 0, 0, 0, 0, 0, 0 } + + DEBUGFUNC("kalQueryRegistryMacAddr"); + + ASSERT(prGlueInfo); + ASSERT(paucMacAddr); + + kalMemCopy((PVOID) paucMacAddr, (PVOID) aucZeroMac, MAC_ADDR_LEN); + +} /* end of kalQueryRegistryMacAddr() */ + +#if CFG_SUPPORT_EXT_CONFIG +/*----------------------------------------------------------------------------*/ +/*! + * \brief Read external configuration, ex. NVRAM or file + * + * \param[in] prGlueInfo Pointer of GLUE Data Structure + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +UINT_32 kalReadExtCfg(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + /* + * External data is given from user space by ioctl or /proc, not read by + * driver. + */ + if (prGlueInfo->u4ExtCfgLength != 0) + DBGLOG(INIT, TRACE, "Read external configuration data -- OK\n"); + else + DBGLOG(INIT, TRACE, "Read external configuration data -- fail\n"); + + return prGlueInfo->u4ExtCfgLength; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * @brief This inline function is to extract some packet information, including + * user priority, packet length, destination address, 802.1x and BT over Wi-Fi + * or not. + * + * @param prGlueInfo Pointer to the glue structure + * @param prNdisPacket Packet descriptor + * @param pucPriorityParam User priority + * @param pu4PacketLen Packet length + * @param pucEthDestAddr Destination address + * @param pfgIs1X 802.1x packet or not + * @param pfgIsPAL BT over Wi-Fi packet or not + * @prGenUse General used param + * + * @retval TRUE Success to extract information + * @retval FALSE Fail to extract correct information + */ +/*----------------------------------------------------------------------------*/ + +BOOLEAN +kalQoSFrameClassifierAndPacketInfo(IN P_GLUE_INFO_T prGlueInfo, + IN P_NATIVE_PACKET prPacket, + OUT PUINT_8 pucPriorityParam, + OUT PUINT_32 pu4PacketLen, + OUT PUINT_8 pucEthDestAddr, + OUT PBOOLEAN pfgIs1X, + OUT PBOOLEAN pfgIsPAL, OUT PUINT_8 pucNetworkType, + OUT PVOID prGenUse) +{ + + UINT_32 u4PacketLen; + + UINT_8 ucUserPriority = USER_PRIORITY_DEFAULT; /* Default */ + UINT_8 ucEtherType; + UINT_16 u2EtherTypeLen; + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + PUINT_8 aucLookAheadBuf = NULL; + + DEBUGFUNC("kalQoSFrameClassifierAndPacketInfo"); + + u4PacketLen = prSkb->len; + + if (u4PacketLen < ETH_HLEN) { + DBGLOG(TX, WARN, "Invalid Ether packet length: %u\n", (UINT_32) u4PacketLen); + return FALSE; + } + + aucLookAheadBuf = prSkb->data; + + *pfgIs1X = FALSE; + *pfgIsPAL = FALSE; + + /* 4 <3> Obtain the User Priority for WMM */ + ucEtherType = kalGetPktEtherType(aucLookAheadBuf); + u2EtherTypeLen = (aucLookAheadBuf[ETH_TYPE_LEN_OFFSET] << 8) | (aucLookAheadBuf[ETH_TYPE_LEN_OFFSET + 1]); + + /* <4> 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; + } + } + + if ((u2EtherTypeLen == ETH_P_IP) && (u4PacketLen >= LOOK_AHEAD_LEN)) { + PUINT_8 pucIpHdr = &aucLookAheadBuf[ETH_HLEN]; + UINT_8 ucIpVersion; + PUINT_8 pucIpPayload = pucIpHdr + 20; + + ucIpVersion = (pucIpHdr[0] & IPVH_VERSION_MASK) >> IPVH_VERSION_OFFSET; + if (ucIpVersion == IPVERSION) { + UINT_8 ucIpTos; + + ucIpTos = pucIpHdr[1]; + /* Get the DSCP value from the header of IP packet. */ + ucUserPriority = getUpFromDscp(prGlueInfo, *pucNetworkType, (ucIpTos >> 2) & 0x3F); + +#if (1 || defined(PPR2_TEST)) + /* DBGLOG(TX, TRACE, "setUP ucIpTos: %d, ucUP: %d\n", ucIpTos, ucUserPriority);*/ + if (pucIpHdr[9] == IP_PRO_ICMP && pucIpPayload[0] == 0x08) { + DBGLOG(TX, INFO, "PING ipid: %d ucIpTos: %d, ucUP: %d\n", + (pucIpHdr[5] << 8 | pucIpHdr[4]), + ucIpTos, ucUserPriority); + } +#endif + if (ucUserPriority == 0xFF) + ucUserPriority = ((ucIpTos & IPTOS_PREC_MASK) >> IPTOS_PREC_OFFSET); + + + } + + /* TODO(Kevin): Add TSPEC classifier here */ + } else if (u2EtherTypeLen == ETH_P_IPV6) { + PUINT_8 pucIpHdr = &aucLookAheadBuf[ETH_HLEN]; + UINT_16 u2Tmp; + UINT_8 ucIpTos; + + WLAN_GET_FIELD_BE16(pucIpHdr, &u2Tmp); + ucIpTos = u2Tmp >> 4; + + /* Get the DSCP value from the header of IP packet. */ + ucUserPriority = getUpFromDscp(prGlueInfo, *pucNetworkType, (ucIpTos >> 2) & 0x3F); + + if (ucUserPriority == 0xFF) + ucUserPriority = ((ucIpTos & IPTOS_PREC_MASK) >> IPTOS_PREC_OFFSET); + } else if (u2EtherTypeLen == ETH_P_1X || u2EtherTypeLen == ETH_P_PRE_1X) { /* For Port Control */ + PUINT_8 pucEapol = &aucLookAheadBuf[ETH_HLEN]; + UINT_8 ucEapolType = pucEapol[1]; + UINT_16 u2KeyInfo = pucEapol[5]<<8 | pucEapol[6]; + /* + * generate a seq number used to trace security frame TX + */ + if (prGenUse) + *(UINT_8 *)prGenUse = nicIncreaseCmdSeqNum(prGlueInfo->prAdapter); + + switch (ucEapolType) { + case 0: /* eap packet */ + DBGLOG(TX, INFO, " EAP Packet: code %d, id %d, type %d, seqNo %d\n", + pucEapol[4], pucEapol[5], pucEapol[7], + prGenUse ? *(UINT_8 *)prGenUse : 0); + break; + case 1: /* eapol start */ + DBGLOG(TX, INFO, " EAPOL: start, seqNo %d\n", + prGenUse ? *(UINT_8 *)prGenUse : 0); + break; + case 3: /* key */ + DBGLOG(TX, INFO, + " EAPOL: key, KeyInfo 0x%04x, Nonce %02x%02x%02x%02x%02x%02x%02x%02x... seqNo %d\n", + u2KeyInfo, pucEapol[17], pucEapol[18], pucEapol[19], pucEapol[20], + pucEapol[21], pucEapol[22], pucEapol[23], pucEapol[24], + prGenUse ? *(UINT_8 *)prGenUse : 0); + break; + } + *pfgIs1X = TRUE; + } +#if CFG_SUPPORT_WAPI + else if (u2EtherTypeLen == ETH_WPI_1X) { + PUINT_8 pucEthBody = &aucLookAheadBuf[ETH_HLEN]; + UINT_8 ucSubType = pucEthBody[3]; /* sub type filed*/ + UINT_16 u2Length = *(PUINT_16)&pucEthBody[6]; + UINT_16 u2Seq = *(PUINT_16)&pucEthBody[8]; + + DBGLOG(TX, INFO, " WAPI: subType %d, Len %d, Seq %d\n", + ucSubType, u2Length, u2Seq); + *pfgIs1X = TRUE; + } +#endif +#if (CFG_SUPPORT_TDLS == 1) + else if (u2EtherTypeLen == TDLS_FRM_PROT_TYPE) { + /* TDLS case */ + TDLSEX_UP_ASSIGN(ucUserPriority); + } +#endif /* CFG_SUPPORT_TDLS */ + else if (u2EtherTypeLen <= 1500) { /* 802.3 Frame */ + UINT_8 ucDSAP, ucSSAP, ucControl; + UINT_8 aucOUI[3]; + + ucDSAP = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET]; + ucSSAP = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET + 1]; + ucControl = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET + 2]; + + aucOUI[0] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET]; + aucOUI[1] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET + 1]; + aucOUI[2] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET + 2]; + + if (ucDSAP == ETH_LLC_DSAP_SNAP && + ucSSAP == ETH_LLC_SSAP_SNAP && + ucControl == ETH_LLC_CONTROL_UNNUMBERED_INFORMATION && + aucOUI[0] == ETH_SNAP_BT_SIG_OUI_0 && + aucOUI[1] == ETH_SNAP_BT_SIG_OUI_1 && aucOUI[2] == ETH_SNAP_BT_SIG_OUI_2) { + + UINT_16 tmp = + ((aucLookAheadBuf[ETH_SNAP_OFFSET + 3] << 8) | aucLookAheadBuf[ETH_SNAP_OFFSET + 4]); + + *pfgIsPAL = TRUE; + ucUserPriority = (UINT_8) prSkb->priority; + + if (tmp == BOW_PROTOCOL_ID_SECURITY_FRAME) { + PUINT_8 pucEapol = &aucLookAheadBuf[ETH_SNAP_OFFSET + 5]; + UINT_8 ucEapolType = pucEapol[1]; + UINT_16 u2KeyInfo = pucEapol[5]<<8 | pucEapol[6]; + + if (prGenUse) + *(UINT_8 *)prGenUse = nicIncreaseCmdSeqNum(prGlueInfo->prAdapter); + + switch (ucEapolType) { + case 0: /* eap packet */ + DBGLOG(TX, INFO, " EAP Packet: code %d, id %d, type %d, seqNo %d\n", + pucEapol[4], pucEapol[5], pucEapol[7], + prGenUse ? *(UINT_8 *)prGenUse : 0); + break; + case 1: /* eapol start */ + DBGLOG(TX, INFO, " EAPOL: start, seqNo %d\n", + prGenUse ? *(UINT_8 *)prGenUse : 0); + break; + case 3: /* key */ + DBGLOG(TX, INFO, + " EAPOL: key, KeyInfo 0x%04x, Nonce %02x%02x%02x%02x%02x%02x%02x%02x seqNo %d\n", + u2KeyInfo, pucEapol[17], pucEapol[18], pucEapol[19], pucEapol[20], + pucEapol[21], pucEapol[22], pucEapol[23], pucEapol[24], + prGenUse ? *(UINT_8 *)prGenUse : 0); + break; + } + *pfgIs1X = TRUE; + } + } + } + /* 4 <5> Check ethernet type and return the value of Priority Parameter. */ + if (ucEtherType == ENUM_PKT_DHCP || ucEtherType == ENUM_PKT_ARP) { + ucUserPriority = 6; /* use VO priority */ + DBGLOG(TX, TRACE, "change UserPriority = %d\n", ucUserPriority); + } + *pucPriorityParam = ucUserPriority; + + /* 4 <6> Retrieve Packet Information - DA */ + /* Packet Length/ Destination Address */ + *pu4PacketLen = u4PacketLen; + + kalMemCopy(pucEthDestAddr, aucLookAheadBuf, PARAM_MAC_ADDR_LEN); + + return TRUE; +} /* end of kalQoSFrameClassifier() */ + +VOID +kalOidComplete(IN P_GLUE_INFO_T prGlueInfo, + IN BOOLEAN fgSetQuery, IN UINT_32 u4SetQueryInfoLen, IN WLAN_STATUS rOidStatus) +{ + + ASSERT(prGlueInfo); + /* remove timeout check timer */ + wlanoidClearTimeoutCheck(prGlueInfo->prAdapter); + + /* if (prGlueInfo->u4TimeoutFlag != 1) { */ + prGlueInfo->rPendStatus = rOidStatus; + DBGLOG(OID, TEMP, "kalOidComplete, caller: %p\n", __builtin_return_address(0)); + + /* complete ONLY if there are waiters */ + if (!completion_done(&prGlueInfo->rPendComp)) + complete(&prGlueInfo->rPendComp); + else + DBGLOG(INIT, WARN, "SKIP multiple OID complete!\n"); + + prGlueInfo->u4OidCompleteFlag = 1; + /* } */ + /* else let it timeout on kalIoctl entry */ +} + +VOID kalOidClearance(IN P_GLUE_INFO_T prGlueInfo) +{ + /* if (prGlueInfo->u4TimeoutFlag != 1) { */ + /* clear_bit(GLUE_FLAG_OID_BIT, &prGlueInfo->u4Flag); */ + if (prGlueInfo->u4OidCompleteFlag != 1) { + DBGLOG(OID, TEMP, "kalOidClearance, caller: %p\n", __builtin_return_address(0)); + /* complete ONLY if there are waiters */ + if (!completion_done(&prGlueInfo->rPendComp)) + complete(&prGlueInfo->rPendComp); + else + DBGLOG(INIT, WARN, "SKIP multiple OID complete!\n"); + + } + /* } */ +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is used to transfer linux ioctl to OID, and we + * need to specify the behavior of the OID by ourself + * + * @param prGlueInfo Pointer to the glue structure + * @param pvInfoBuf Data buffer + * @param u4InfoBufLen Data buffer length + * @param fgRead Is this a read OID + * @param fgWaitResp does this OID need to wait for values + * @param fgCmd does this OID compose command packet + * @param pu4QryInfoLen The data length of the return values + * + * @retval TRUE Success to extract information + * @retval FALSE Fail to extract correct information + */ +/*----------------------------------------------------------------------------*/ + +/* todo: enqueue the i/o requests for multiple processes access */ +/* */ +/* currently, return -1 */ +/* */ + +/* static GL_IO_REQ_T OidEntry; */ + +WLAN_STATUS +kalIoctl(IN P_GLUE_INFO_T prGlueInfo, + IN PFN_OID_HANDLER_FUNC pfnOidHandler, + IN PVOID pvInfoBuf, + IN UINT_32 u4InfoBufLen, + IN BOOLEAN fgRead, IN BOOLEAN fgWaitResp, IN BOOLEAN fgCmd, IN BOOLEAN fgIsP2pOid, OUT PUINT_32 pu4QryInfoLen) +{ + P_GL_IO_REQ_T prIoReq = NULL; + WLAN_STATUS ret = WLAN_STATUS_SUCCESS; + P_ADAPTER_T prAdapter = NULL; + + if (fgIsResetting == TRUE) + return WLAN_STATUS_SUCCESS; + + /* GLUE_SPIN_LOCK_DECLARATION(); */ + ASSERT(prGlueInfo); + if (prGlueInfo == NULL) { + DBGLOG(OID, WARN, "kalIoctl: prGlueInfo is NULL.\n"); + return WLAN_STATUS_FAILURE; + } + + prAdapter = prGlueInfo->prAdapter; + + ASSERT(prAdapter); + + /* <1> Check if driver is halt */ + /* if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) { */ + /* return WLAN_STATUS_ADAPTER_NOT_READY; */ + /* } */ + + /* + * if wait longer than double OID timeout timer, then will show backtrace who held halt lock. + * at this case, we will return kalIoctl failure because tx_thread may be hung + */ + + if (kalHaltLock(2 * WLAN_OID_TIMEOUT_THRESHOLD)) { + DBGLOG(OID, WARN, "kalIoctl: WLAN_STATUS_FAILURE\n"); + prIoReq = &(prGlueInfo->OidEntry); + ASSERT(prIoReq); + DBGLOG(OID, WARN, "OidHandler 0x%p pvInfoBuf 0x%p,Buflen =%d,InfoLen=%p fgRead=%d,fgWaitRsp=%d\n" + , prIoReq->pfnOidHandler + , prIoReq->pvInfoBuf + , prIoReq->u4InfoBufLen + , prIoReq->pu4QryInfoLen + , prIoReq->fgRead + , prIoReq->fgWaitResp); + return WLAN_STATUS_FAILURE; + } + + if (kalIsHalted()) { + kalHaltUnlock(); + DBGLOG(OID, WARN, "kalIoctl: WLAN_STATUS_ADAPTER_NOT_READY\n"); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + if (down_interruptible(&prGlueInfo->ioctl_sem)) { + kalHaltUnlock(); + DBGLOG(OID, WARN, "kalIoctl: WLAN_STATUS_FAILURE\n"); + return WLAN_STATUS_FAILURE; + } + rHaltCtrl.fgHeldByKalIoctl = TRUE; + + /* <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 */ + reinit_completion(&prGlueInfo->rPendComp); + set_bit(GLUE_FLAG_OID_BIT, &prGlueInfo->ulFlag); + + /* <8> Wake up tx thread to handle kick start the I/O request */ + wake_up_interruptible(&prGlueInfo->waitq); + + /* <9> Block and wait for event or timeout, current the timeout is 30 secs */ + if (wait_for_completion_timeout(&prGlueInfo->rPendComp, 30 * KAL_HZ)) { + /* if (!wait_for_completion_interruptible(&prGlueInfo->rPendComp)) { */ + DBGLOG(OID, TEMP, "kalIoctl: before wait, caller: %p\n", __builtin_return_address(0)); + /*wait_for_completion(&prGlueInfo->rPendComp); {*/ + /* Case 1: No timeout. */ + /* if return WLAN_STATUS_PENDING, the status of cmd is stored in prGlueInfo */ + if (prIoReq->rStatus == WLAN_STATUS_PENDING) + ret = prGlueInfo->rPendStatus; + else + ret = prIoReq->rStatus; + if (ret != WLAN_STATUS_SUCCESS) + DBGLOG(OID, WARN, "kalIoctl: ret ErrCode: %x\n", ret); + } else { + /* Case 2: timeout */ + /* clear pending OID's cmd in CMD queue */ + DBGLOG(OID, WARN, "kalIoctl: wait_for_completion_timeout occurred!\n"); + DBGLOG(OID, WARN + , "OidHandler 0x%p pvInfoBuf 0x%p,Buflen =%d,InfoLen=%p fgRead=%d,fgWaitRsp=%d,now[%u]\n" + , pfnOidHandler + , pvInfoBuf + , u4InfoBufLen + , pu4QryInfoLen + , fgRead + , fgWaitResp + , kalGetTimeTick()); + wlanDebugCommandRecodDump(); + wlanDumpTcResAndTxedCmd(NULL, 0); + cmdBufDumpCmdQueue(&prAdapter->rPendingCmdQueue, "waiting response CMD queue"); + wlanDumpCommandFwStatus(); +#if 0 + if (fgCmd) { + prGlueInfo->u4TimeoutFlag = 1; + wlanReleasePendingOid(prGlueInfo->prAdapter, 0); + } +#endif + ret = WLAN_STATUS_FAILURE; + } + + DBGLOG(OID, TEMP, "kalIoctl: done\n"); + up(&prGlueInfo->ioctl_sem); + rHaltCtrl.fgHeldByKalIoctl = FALSE; + kalHaltUnlock(); + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to clear all pending security frames + * + * \param prGlueInfo Pointer of GLUE Data Structure + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +VOID kalClearSecurityFrames(IN P_GLUE_INFO_T prGlueInfo) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + /* Clear pending security frames in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) { + prCmdInfo->pfCmdTimeoutHandler(prGlueInfo->prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + } else { + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + QUEUE_CONCATENATE_QUEUES(prCmdQue, prTempCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to clear pending security frames + * belongs to dedicated network type + * + * \param prGlueInfo Pointer of GLUE Data Structure + * \param eNetworkTypeIdx Network Type Index + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +VOID kalClearSecurityFramesByNetType(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + /* Clear pending security frames in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME && prCmdInfo->eNetworkType == eNetworkTypeIdx) { + prCmdInfo->pfCmdTimeoutHandler(prGlueInfo->prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + } else { + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + QUEUE_CONCATENATE_QUEUES(prCmdQue, prTempCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to clear all pending management frames + * + * \param prGlueInfo Pointer of GLUE Data Structure + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +VOID kalClearMgmtFrames(IN P_GLUE_INFO_T prGlueInfo) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + /* Clear pending management frames in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) { + wlanReleaseCommand(prGlueInfo->prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + } else { + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + QUEUE_CONCATENATE_QUEUES(prCmdQue, prTempCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to clear all pending management frames + * belongs to dedicated network type + * \param prGlueInfo Pointer of GLUE Data Structure + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +VOID kalClearMgmtFramesByNetType(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + /* Clear pending management frames in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME && + prCmdInfo->eNetworkType == eNetworkTypeIdx) { + wlanReleaseCommand(prGlueInfo->prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + } else { + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + QUEUE_CONCATENATE_QUEUES(prCmdQue, prTempCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); +} /* kalClearMgmtFramesByNetType */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is a kernel thread function for handling command packets + * Tx requests and interrupt events + * + * @param data data pointer to private data of tx_thread + * + * @retval If the function succeeds, the return value is 0. + * Otherwise, an error code is returned. + * + */ +/*----------------------------------------------------------------------------*/ + +int tx_thread(void *data) +{ + struct net_device *dev = data; + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(dev)); + + P_QUE_ENTRY_T prQueueEntry = NULL; + P_GL_IO_REQ_T prIoReq = NULL; + P_QUE_T prTxQueue = NULL; + P_QUE_T prCmdQue = NULL; + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = NULL; + int i, u4UninitRfbNum = 0; + int ret = 0; + + BOOLEAN fgNeedHwAccess = FALSE; + BOOLEAN fgAllowOidHandle = FALSE; + BOOLEAN fgIsUninitRfb = FALSE; + + struct sk_buff *prSkb = NULL; + + /* for spin lock acquire and release */ + GLUE_SPIN_LOCK_DECLARATION(); + + prTxQueue = &prGlueInfo->rTxQueue; + prCmdQue = &prGlueInfo->rCmdQueue; + prRxCtrl = &prGlueInfo->prAdapter->rRxCtrl; + + current->flags |= PF_NOFREEZE; + + DBGLOG(INIT, TRACE, "1. policy: %d, static_prio: %d", + current->policy, current->static_prio); + + if (current->policy == SCHED_NORMAL) { + /* set main_thread to highest normal priority */ + set_user_nice(current, PRIO_TO_NICE(DEFAULT_PRIO - 19)); + } + DBGLOG(INIT, INFO, "tx_thread starts running...\n"); + + DBGLOG(INIT, TRACE, "2. policy: %d, static_prio: %d", + current->policy, current->static_prio); + + while (TRUE) { + +#if CFG_ENABLE_WIFI_DIRECT + /*run p2p multicast list work. */ + if (test_and_clear_bit(GLUE_FLAG_SUB_MOD_MULTICAST_BIT, &prGlueInfo->ulFlag)) + p2pSetMulticastListWorkQueueWrapper(prGlueInfo); +#endif + + if (test_and_clear_bit(GLUE_FLAG_FRAME_FILTER_AIS_BIT, &prGlueInfo->ulFlag)) { + P_AIS_FSM_INFO_T prAisFsmInfo = (P_AIS_FSM_INFO_T) NULL; + /* printk("prGlueInfo->u4OsMgmtFrameFilter = %x", prGlueInfo->u4OsMgmtFrameFilter); */ + prAisFsmInfo = &(prGlueInfo->prAdapter->rWifiVar.rAisFsmInfo); + prAisFsmInfo->u4AisPacketFilter = prGlueInfo->u4OsMgmtFrameFilter; + } + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, (prGlueInfo->prAdapter)->rTxThreadWakeLock); + DBGLOG(INIT, INFO, "tx_thread should stop now...\n"); + break; + } + + /* + * sleep on waitqueue if no events occurred. Event contain (1) GLUE_FLAG_INT + * (2) GLUE_FLAG_OID (3) GLUE_FLAG_TXREQ (4) GLUE_FLAG_HALT + * + */ + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, (prGlueInfo->prAdapter)->rTxThreadWakeLock); + + ret = wait_event_interruptible(prGlueInfo->waitq, (prGlueInfo->ulFlag != 0)); + + KAL_WAKE_LOCK(prGlueInfo->prAdapter, (prGlueInfo->prAdapter)->rTxThreadWakeLock); + +/* #if (CONF_HIF_LOOPBACK_AUTO == 1) */ +/* if (test_and_clear_bit(GLUE_FLAG_HIF_LOOPBK_AUTO_BIT, &prGlueInfo->u4Flag)) { */ +/* kalDevLoopbkAuto(prGlueInfo); */ +/* } */ +/* #endif */ /* CONF_HIF_LOOPBACK_AUTO */ + +#if CFG_DBG_GPIO_PINS + /* TX thread Wake up */ + mtk_wcn_stp_debug_gpio_assert(IDX_TX_THREAD, DBG_TIE_LOW); +#endif +#if CFG_ENABLE_WIFI_DIRECT + /*run p2p multicast list work. */ + if (test_and_clear_bit(GLUE_FLAG_SUB_MOD_MULTICAST_BIT, &prGlueInfo->ulFlag)) + p2pSetMulticastListWorkQueueWrapper(prGlueInfo); + + if (test_and_clear_bit(GLUE_FLAG_FRAME_FILTER_BIT, &prGlueInfo->ulFlag) && + prGlueInfo->prP2PInfo) { + p2pFuncUpdateMgmtFrameRegister(prGlueInfo->prAdapter, + prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter); + } +#endif + if (test_and_clear_bit(GLUE_FLAG_FRAME_FILTER_AIS_BIT, &prGlueInfo->ulFlag)) { + P_AIS_FSM_INFO_T prAisFsmInfo = (P_AIS_FSM_INFO_T) NULL; + /* printk("prGlueInfo->u4OsMgmtFrameFilter = %x", prGlueInfo->u4OsMgmtFrameFilter); */ + prAisFsmInfo = &(prGlueInfo->prAdapter->rWifiVar.rAisFsmInfo); + prAisFsmInfo->u4AisPacketFilter = prGlueInfo->u4OsMgmtFrameFilter; + } + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, (prGlueInfo->prAdapter)->rTxThreadWakeLock); + DBGLOG(INIT, INFO, "<1>tx_thread should stop now...\n"); + break; + } + + fgNeedHwAccess = FALSE; + + /* Handle Interrupt */ + if (test_and_clear_bit(GLUE_FLAG_INT_BIT, &prGlueInfo->ulFlag)) { + if (fgNeedHwAccess == FALSE) { + fgNeedHwAccess = TRUE; + + wlanAcquirePowerControl(prGlueInfo->prAdapter); + } + + /* + * the Wi-Fi interrupt is already disabled in mmc thread, + * so we set the flag only to enable the interrupt later + */ + prGlueInfo->prAdapter->fgIsIntEnable = FALSE; + /* wlanISR(prGlueInfo->prAdapter, TRUE); */ + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + /* Should stop now... skip pending interrupt */ + DBGLOG(INIT, INFO, "ignore pending interrupt\n"); + } else { + prGlueInfo->TaskIsrCnt++; + wlanIST(prGlueInfo->prAdapter); + } + } + + /* transfer ioctl to OID request */ +#if 0 + if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) { + DBGLOG(INIT, INFO, "<2>tx_thread should stop now...\n"); + break; + } +#endif + + do { + if (test_and_clear_bit(GLUE_FLAG_OID_BIT, &prGlueInfo->ulFlag)) { + /* get current prIoReq */ + prGlueInfo->u4OidCompleteFlag = 0; + + prIoReq = &(prGlueInfo->OidEntry); +#if CFG_ENABLE_WIFI_DIRECT + if (prGlueInfo->prAdapter->fgIsP2PRegistered == FALSE && prIoReq->fgIsP2pOid == TRUE) { + /* + * if this Oid belongs to p2p and p2p module is removed + * do nothing, + */ + } else +#endif + { + if (!completion_done(&prGlueInfo->rPendComp)) + fgAllowOidHandle = TRUE; + else + fgAllowOidHandle = FALSE; + if (fgAllowOidHandle && (prIoReq->fgRead == FALSE)) { + prIoReq->rStatus = wlanSetInformation(prIoReq->prAdapter, + prIoReq->pfnOidHandler, + prIoReq->pvInfoBuf, + prIoReq->u4InfoBufLen, + prIoReq->pu4QryInfoLen); + } else if (fgAllowOidHandle) { + prIoReq->rStatus = wlanQueryInformation(prIoReq->prAdapter, + prIoReq->pfnOidHandler, + prIoReq->pvInfoBuf, + prIoReq->u4InfoBufLen, + prIoReq->pu4QryInfoLen); + } else + DBGLOG(OID, WARN, "completion_done = true, do nothing\n"); + + if (prIoReq->rStatus != WLAN_STATUS_PENDING) { + DBGLOG(OID, TEMP, "tx_thread, complete\n"); + complete(&prGlueInfo->rPendComp); + } else { + wlanoidTimeoutCheck(prGlueInfo->prAdapter, prIoReq->pfnOidHandler); + } + } + } + + } while (FALSE); + + /* + * + * if TX request, clear the TXREQ flag. TXREQ set by kalSetEvent/GlueSetEvent + * indicates the following requests occur + * + */ +#if 0 + if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) { + DBGLOG(INIT, INFO, "<3>tx_thread should stop now...\n"); + break; + } +#endif + + if (test_and_clear_bit(GLUE_FLAG_TXREQ_BIT, &prGlueInfo->ulFlag)) { + /* Process Mailbox Messages */ + wlanProcessMboxMessage(prGlueInfo->prAdapter); + + /* Process CMD request */ + do { + if (prCmdQue->u4NumElem > 0) { + if (fgNeedHwAccess == FALSE) { + fgNeedHwAccess = TRUE; + + wlanAcquirePowerControl(prGlueInfo->prAdapter); + } + wlanProcessCommandQueue(prGlueInfo->prAdapter, prCmdQue); + } + } while (FALSE); + + /* Handle Packet Tx */ + { + while (QUEUE_IS_NOT_EMPTY(prTxQueue)) { + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_REMOVE_HEAD(prTxQueue, prQueueEntry, P_QUE_ENTRY_T); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + + ASSERT(prQueueEntry); + if (prQueueEntry == NULL) + break; + + prSkb = (struct sk_buff *)GLUE_GET_PKT_DESCRIPTOR(prQueueEntry); + ASSERT(prSkb); + if (prSkb == NULL) { + DBGLOG(INIT, ERROR, "prSkb == NULL!\n"); + continue; + } +#if (CFG_SUPPORT_TDLS_DBG == 1) + UINT8 *pkt = prSkb->data; + UINT16 u2Identifier; + + if ((*(pkt + 12) == 0x08) && (*(pkt + 13) == 0x00)) { + /* ip */ + u2Identifier = ((*(pkt + 18)) << 8) | (*(pkt + 19)); + DBGLOG(INIT, LOUD, " %d\n", u2Identifier); + } +#endif + if (wlanEnqueueTxPacket(prGlueInfo->prAdapter, + (P_NATIVE_PACKET) prSkb) == WLAN_STATUS_RESOURCES) { + /* no available entry in rFreeMsduInfoList */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_INSERT_HEAD(prTxQueue, prQueueEntry); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + + break; + } + } + + if (wlanGetTxPendingFrameCount(prGlueInfo->prAdapter) > 0) { + /* send packets to HIF here */ + wlanTxPendingPackets(prGlueInfo->prAdapter, &fgNeedHwAccess); + } + } + + } + /* Process unInitialized Rfb*/ + if (prRxCtrl->rUnInitializedRfbList.u4NumElem > 0) { + u4UninitRfbNum = prRxCtrl->rUnInitializedRfbList.u4NumElem; + DBGLOG(INIT, INFO, "tx_thread :process uninitialziation RFB num=%d\n", u4UninitRfbNum); + for (i = 0; i < u4UninitRfbNum; i++) { + fgIsUninitRfb = FALSE; + KAL_ACQUIRE_SPIN_LOCK(prGlueInfo->prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rUnInitializedRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prGlueInfo->prAdapter, SPIN_LOCK_RX_QUE); + if (prSwRfb) { + if (nicRxSetupRFB(prGlueInfo->prAdapter, prSwRfb)) { + DBGLOGLIMITED(INIT, ERROR, "Setup RFB Fail! insert uninit List!\n"); + fgIsUninitRfb = TRUE; + } + nicRxReturnRFBwithUninit(prGlueInfo->prAdapter, prSwRfb, fgIsUninitRfb); + } else { + DBGLOG(INIT, ERROR, "prSwRfb is NULL!\n"); + } + } + } + + /* Process RX, In linux, we don't need to free sk_buff by ourself */ + + /* In linux, we don't need to free sk_buff by ourself */ + + /* In linux, we don't do reset */ + if (fgNeedHwAccess == TRUE) + wlanReleasePowerControl(prGlueInfo->prAdapter); + + /* handle cnmTimer time out */ + if (test_and_clear_bit(GLUE_FLAG_TIMEOUT_BIT, &prGlueInfo->ulFlag)) + wlanTimerTimeoutCheck(prGlueInfo->prAdapter); +#if CFG_DBG_GPIO_PINS + /* TX thread go to sleep */ + if (!prGlueInfo->ulFlag) + mtk_wcn_stp_debug_gpio_assert(IDX_TX_THREAD, DBG_TIE_HIGH); +#endif + } + +#if 0 + if (fgNeedHwAccess == TRUE) + wlanReleasePowerControl(prGlueInfo->prAdapter); +#endif + + /* exit while loop, tx thread is closed so we flush all pending packets */ + /* flush the pending TX packets */ + if (prGlueInfo->i4TxPendingFrameNum > 0) + kalFlushPendingTxPackets(prGlueInfo); + + /* flush pending security frames */ + if (prGlueInfo->i4TxPendingSecurityFrameNum > 0) + kalClearSecurityFrames(prGlueInfo); + + /* remove pending oid */ + wlanReleasePendingOid(prGlueInfo->prAdapter, 0); + + /* In linux, we don't need to free sk_buff by ourself */ + + DBGLOG(INIT, INFO, "mtk_sdiod stops\n"); + complete(&prGlueInfo->rHaltComp); + + return 0; + +} +#if CFG_SUPPORT_MULTITHREAD +VOID kalWakeupRxThread(P_GLUE_INFO_T prGlueInfo) +{ + set_bit(GLUE_FLAG_RX_BIT, &(prGlueInfo->ulFlag)); + wake_up_interruptible(&(prGlueInfo->waitq_rx)); +} +int rx_thread(void *data) +{ + struct net_device *dev = data; + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(dev)); + P_ADAPTER_T prAdapter; + int ret = 0; + P_RX_CTRL_T prRxCtrl = &prGlueInfo->prAdapter->rRxCtrl; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + KAL_WAKELOCK_DECLARE(rRxThreadWakeLock); + + prAdapter = prGlueInfo->prAdapter; + KAL_WAKE_LOCK_INIT(prAdapter, rRxThreadWakeLock, "WLAN rx_thread"); + KAL_WAKE_LOCK(prAdapter, rRxThreadWakeLock); + + if (current->policy == SCHED_NORMAL) + current->static_prio = DEFAULT_PRIO - 19; + + DBGLOG(INIT, INFO, "rx_thread starts running...\n"); + + while (TRUE) { + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(INIT, INFO, "rx_thread should stop now...\n"); + break; + } + /* Unlock wakelock if rx_thread going to idle */ + if (!(prGlueInfo->ulFlag & GLUE_FLAG_RX_PROCESS)) + KAL_WAKE_UNLOCK(prAdapter, rRxThreadWakeLock); + /* + * sleep on waitqueue if no events occurred. + */ + do { + ret = wait_event_interruptible(prGlueInfo->waitq_rx, + ((prGlueInfo->ulFlag & GLUE_FLAG_RX_PROCESS) != 0)); + } while (ret); + if (!KAL_WAKE_LOCK_ACTIVE(prAdapter, &rRxThreadWakeLock)) + KAL_WAKE_LOCK(prAdapter, rRxThreadWakeLock); + if (test_and_clear_bit(GLUE_FLAG_RX_BIT, &prGlueInfo->ulFlag)) { + prRxCtrl->ucNumIndPacket = 0; + prRxCtrl->ucNumRetainedPacket = 0; + do { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_DATA_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rRxDataRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_DATA_QUE); + + if (prSwRfb) { + switch (prSwRfb->ucPacketType) { + case HIF_RX_PKT_TYPE_DATA: + nicRxProcessDataPacket(prAdapter, prSwRfb); + break; + + default: + /* This case should never happen */ + RX_INC_CNT(prRxCtrl, RX_TYPE_ERR_DROP_COUNT); + RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); + DBGLOG(RX, ERROR, "ucPacketType = %d\n", prSwRfb->ucPacketType); + nicRxReturnRFB(prAdapter, prSwRfb); /* need to free it */ + break; + } + } else { + break; + } + } while (TRUE); + if (prRxCtrl->ucNumIndPacket > 0) { + RX_ADD_CNT(prRxCtrl, RX_DATA_INDICATION_COUNT, prRxCtrl->ucNumIndPacket); + RX_ADD_CNT(prRxCtrl, RX_DATA_RETAINED_COUNT, prRxCtrl->ucNumRetainedPacket); + + /* DBGLOG(RX, INFO, ("%d packets indicated, Retained cnt = %d\n", */ + /* prRxCtrl->ucNumIndPacket, prRxCtrl->ucNumRetainedPacket)); */ + #if CFG_NATIVE_802_11 + kalRxIndicatePkts(prAdapter->prGlueInfo, + (UINT_32) prRxCtrl->ucNumIndPacket, + (UINT_32) prRxCtrl->ucNumRetainedPacket); + #else + kalRxIndicatePkts(prAdapter->prGlueInfo, + prRxCtrl->apvIndPacket, + (UINT_32) prRxCtrl->ucNumIndPacket); + #endif + } + KAL_WAKE_LOCK_TIMEOUT(prAdapter, prGlueInfo->rTimeoutWakeLock, + MSEC_TO_JIFFIES(WAKE_LOCK_RX_TIMEOUT)); + } + } + complete(&prGlueInfo->rRxHaltComp); + if (KAL_WAKE_LOCK_ACTIVE(prAdapter, &rRxThreadWakeLock)) + KAL_WAKE_UNLOCK(prAdapter, rRxThreadWakeLock); + KAL_WAKE_LOCK_DESTROY(prAdapter, rRxThreadWakeLock); + return 0; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * \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, PARAM_MAC_ADDRESS *prMacAddr) +{ + ASSERT(prGlueInfo); + + if (prGlueInfo->fgIsMacAddrOverride == FALSE) { +#if !defined(CONFIG_X86) + +#if !(CFG_TC1_FEATURE || CFG_TC10_FEATURE) + UINT_32 i; +#endif + BOOLEAN fgIsReadError = FALSE; + +#if CFG_TC1_FEATURE + TC1_FAC_NAME(FacReadWifiMacAddr) ((unsigned char *)prMacAddr); +#elif CFG_TC10_FEATURE + COPY_MAC_ADDR(prMacAddr, prGlueInfo->rRegInfo.aucMacAddr); +#else + if (!EQUAL_MAC_ADDR(&prGlueInfo->rRegInfo.aucMacAddr, "\x00\x00\x00\x00\x00\x00")) { + COPY_MAC_ADDR(prMacAddr, &prGlueInfo->rRegInfo.aucMacAddr); + return TRUE; + } + 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; + } + } + +#endif + + if (fgIsReadError == TRUE) + return FALSE; + else + return TRUE; +#else + /* x86 Linux doesn't need to override network address so far */ + return FALSE; +#endif + } else { + COPY_MAC_ADDR(prMacAddr, prGlueInfo->rMacAddrOverride); + + return TRUE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to flush pending TX packets in glue layer + * + * \param pvGlueInfo Pointer of GLUE Data Structure + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +VOID kalFlushPendingTxPackets(IN P_GLUE_INFO_T prGlueInfo) +{ + P_QUE_T prTxQue; + P_QUE_ENTRY_T prQueueEntry; + PVOID prPacket; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + prTxQue = &(prGlueInfo->rTxQueue); + + if (prGlueInfo->i4TxPendingFrameNum) { + while (TRUE) { + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_REMOVE_HEAD(prTxQue, prQueueEntry, P_QUE_ENTRY_T); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + + if (prQueueEntry == NULL) + break; + + prPacket = GLUE_GET_PKT_DESCRIPTOR(prQueueEntry); + kalSendComplete(prGlueInfo, prPacket, WLAN_STATUS_NOT_ACCEPTED); + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is get indicated media state + * + * \param pvGlueInfo Pointer of GLUE Data Structure + * + * \retval + */ +/*----------------------------------------------------------------------------*/ +ENUM_PARAM_MEDIA_STATE_T kalGetMediaStateIndicated(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->eParamMediaStateIndicated; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to set indicated media state + * + * \param pvGlueInfo Pointer of GLUE Data Structure + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +VOID kalSetMediaStateIndicated(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_PARAM_MEDIA_STATE_T eParamMediaStateIndicate) +{ + ASSERT(prGlueInfo); + + prGlueInfo->eParamMediaStateIndicated = eParamMediaStateIndicate; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to clear pending OID staying in command queue + * + * \param prGlueInfo Pointer of GLUE Data Structure + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +VOID kalOidCmdClearance(IN P_GLUE_INFO_T prGlueInfo) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + + if (((P_CMD_INFO_T) prQueueEntry)->fgIsOid) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + break; + } + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + QUEUE_CONCATENATE_QUEUES(prCmdQue, prTempCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + if (prCmdInfo) { + if (prCmdInfo->pfCmdTimeoutHandler) + prCmdInfo->pfCmdTimeoutHandler(prGlueInfo->prAdapter, prCmdInfo); + else + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_NOT_ACCEPTED); + + prGlueInfo->u4OidCompleteFlag = 1; + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to insert command into prCmdQueue + * + * \param prGlueInfo Pointer of GLUE Data Structure + * prQueueEntry Pointer of queue entry to be inserted + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +VOID kalEnqueueCommand(IN P_GLUE_INFO_T prGlueInfo, IN P_QUE_ENTRY_T prQueueEntry) +{ + P_QUE_T prCmdQue; + P_CMD_INFO_T prCmdInfo; + P_MSDU_INFO_T prMsduInfo; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + ASSERT(prQueueEntry); + + prCmdQue = &prGlueInfo->rCmdQueue; + + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + if (prCmdInfo->prPacket && prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) { + prMsduInfo = (P_MSDU_INFO_T) (prCmdInfo->prPacket); + prMsduInfo->eCmdType = prCmdInfo->eCmdType; + prMsduInfo->ucCID = prCmdInfo->ucCID; + prMsduInfo->u4InqueTime = kalGetTimeTick(); + } + prCmdInfo->u4InqueTime = kalGetTimeTick(); + wlanDebugCommandRecodTime(prCmdInfo); + + 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 */ +} +#if CFG_SUPPORT_EMI_DEBUG +/*----------------------------------------------------------------------------*/ +/*! +* @brief This routine is used to get EMI address +* +* @param settion +* @param offset +* @param buff +* @param len +* @return PINT +*/ +/*----------------------------------------------------------------------------*/ +PINT8 kalGetFwInfoFormEmi(UINT8 section, UINT32 offset, PUINT8 buff, UINT32 len) +{ + return wmt_lib_get_fwinfor_from_emi(section, offset, buff, len); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to get firmware load address from registry + * + * \param prGlueInfo Pointer of GLUE Data Structure + * + * \retval + */ +/*----------------------------------------------------------------------------*/ +UINT_32 kalGetFwLoadAddress(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->rRegInfo.u4LoadAddress; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to get firmware start address from registry + * + * \param prGlueInfo Pointer of GLUE Data Structure + * + * \retval + */ +/*----------------------------------------------------------------------------*/ +UINT_32 kalGetFwStartAddress(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->rRegInfo.u4StartAddress; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Notify OS with SendComplete event of the specific packet. Linux should + * free packets here. + * + * @param pvGlueInfo Pointer of GLUE Data Structure + * @param pvPacket Pointer of Packet Handle + * @param status Status Code for OS upper layer + * + * @return none + */ +/*----------------------------------------------------------------------------*/ + +/* / Todo */ +VOID kalSecurityFrameSendComplete(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket, IN WLAN_STATUS rStatus) +{ + ASSERT(pvPacket); + + dev_kfree_skb((struct sk_buff *)pvPacket); + if (prGlueInfo) { + prGlueInfo->u8SkbFreed++; + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum); + } +} + +UINT_32 kalGetTxPendingFrameCount(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return (UINT_32) (prGlueInfo->i4TxPendingFrameNum); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to retrieve the number of pending commands + * (including MMPDU, 802.1X and command packets) + * + * \param prGlueInfo Pointer of GLUE Data Structure + * + * \retval + */ +/*----------------------------------------------------------------------------*/ +UINT_32 kalGetTxPendingCmdCount(IN P_GLUE_INFO_T prGlueInfo) +{ + P_QUE_T prCmdQue; + + ASSERT(prGlueInfo); + prCmdQue = &prGlueInfo->rCmdQueue; + + return prCmdQue->u4NumElem; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Timer Initialization Procedure + * + * \param[in] prGlueInfo Pointer to GLUE Data Structure + * \param[in] prTimerHandler Pointer to timer handling function, whose only + * argument is "prAdapter" + * + * \retval none + * + */ +/*----------------------------------------------------------------------------*/ + +/* static struct timer_list tickfn; */ + +VOID kalOsTimerInitialize(IN P_GLUE_INFO_T prGlueInfo, IN PVOID prTimerHandler) +{ + + ASSERT(prGlueInfo); +#if KERNEL_VERSION(4, 15, 0) <= CFG80211_VERSION_CODE + timer_setup(&prGlueInfo->tickfn, prTimerHandler, 0); +#else + init_timer(&(prGlueInfo->tickfn)); + prGlueInfo->tickfn.function = prTimerHandler; + prGlueInfo->tickfn.data = (ULONG) prGlueInfo; +#endif +} + +/* Todo */ +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set the time to do the time out check. + * + * \param[in] prGlueInfo Pointer to GLUE Data Structure + * \param[in] rInterval Time out interval from current time. + * + * \retval TRUE Success. + */ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalSetTimer(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Interval) +{ + ASSERT(prGlueInfo); + del_timer_sync(&(prGlueInfo->tickfn)); + + prGlueInfo->tickfn.expires = jiffies + u4Interval * HZ / MSEC_PER_SEC; + add_timer(&(prGlueInfo->tickfn)); + + return TRUE; /* success */ +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to cancel + * + * \param[in] prGlueInfo Pointer to GLUE Data Structure + * + * \retval TRUE : Timer has been canceled + * FALAE : Timer doens't exist + */ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalCancelTimer(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + clear_bit(GLUE_FLAG_TIMEOUT_BIT, &prGlueInfo->ulFlag); + + if (del_timer_sync(&(prGlueInfo->tickfn)) >= 0) + return TRUE; + else + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is a callback function for scanning done + * + * \param[in] prGlueInfo Pointer to GLUE Data Structure + * + * \retval none + * + */ +/*----------------------------------------------------------------------------*/ +VOID kalScanDone(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_KAL_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN WLAN_STATUS status) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + + ASSERT(prGlueInfo); + + prAisFsmInfo = &(prGlueInfo->prAdapter->rWifiVar.rAisFsmInfo); + /* report all queued beacon/probe response frames to upper layer */ +#if CFG_SUPPORT_ADD_CONN_AP + wlanCheckConnectedAP(prGlueInfo->prAdapter); +#endif + scanLogEssResult(prGlueInfo->prAdapter); + + scanReportBss2Cfg80211(prGlueInfo->prAdapter, BSS_TYPE_INFRASTRUCTURE, NULL); + cnmTimerStopTimer(prGlueInfo->prAdapter, &prAisFsmInfo->rScanDoneTimer); + + /* check for system configuration for generating error message on scan list */ + wlanCheckSystemConfiguration(prGlueInfo->prAdapter); + + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_SCAN_COMPLETE, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to generate a random number + * + * \param none + * + * \retval UINT_32 + */ +/*----------------------------------------------------------------------------*/ +UINT_32 kalRandomNumber(VOID) +{ + UINT_32 number = 0; + + get_random_bytes(&number, 4); + + return number; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief command timeout call-back function + * + * \param[in] prGlueInfo Pointer to the GLUE data structure. + * + * \retval (none) + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(4, 15, 0) <= CFG80211_VERSION_CODE +VOID kalTimeoutHandler(struct timer_list *timer) +#else +VOID kalTimeoutHandler(ULONG arg) +#endif +{ +#if KERNEL_VERSION(4, 15, 0) <= CFG80211_VERSION_CODE + P_GLUE_INFO_T prGlueInfo = + from_timer(prGlueInfo, timer, tickfn); +#else + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) arg; +#endif + ASSERT(prGlueInfo); + + /* Notify tx thread for timeout event */ + set_bit(GLUE_FLAG_TIMEOUT_BIT, &prGlueInfo->ulFlag); + wake_up_interruptible(&prGlueInfo->waitq); + +} + +VOID kalSetEvent(P_GLUE_INFO_T pr) +{ + set_bit(GLUE_FLAG_TXREQ_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief to check if configuration file (NVRAM/Registry) exists + * + * \param[in] + * prGlueInfo + * + * \return + * TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalIsConfigurationExist(IN P_GLUE_INFO_T prGlueInfo) +{ +#if !defined(CONFIG_X86) + ASSERT(prGlueInfo); + + return prGlueInfo->fgNvramAvailable; +#else + /* there is no configuration data for x86-linux */ + return FALSE; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief to retrieve Registry information + * + * \param[in] + * prGlueInfo + * + * \return + * Pointer of REG_INFO_T + */ +/*----------------------------------------------------------------------------*/ +P_REG_INFO_T kalGetConfiguration(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return &(prGlueInfo->rRegInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief to retrieve version information of corresponding configuration file + * + * \param[in] + * prGlueInfo + * + * \param[out] + * pu2Part1CfgOwnVersion + * pu2Part1CfgPeerVersion + * pu2Part2CfgOwnVersion + * pu2Part2CfgPeerVersion + * + * \return + * NONE + */ +/*----------------------------------------------------------------------------*/ +VOID +kalGetConfigurationVersion(IN P_GLUE_INFO_T prGlueInfo, + OUT PUINT_16 pu2Part1CfgOwnVersion, + OUT PUINT_16 pu2Part1CfgPeerVersion, + OUT PUINT_16 pu2Part2CfgOwnVersion, OUT PUINT_16 pu2Part2CfgPeerVersion) +{ + ASSERT(prGlueInfo); + + ASSERT(pu2Part1CfgOwnVersion); + ASSERT(pu2Part1CfgPeerVersion); + ASSERT(pu2Part2CfgOwnVersion); + ASSERT(pu2Part2CfgPeerVersion); + + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part1OwnVersion), pu2Part1CfgOwnVersion); + + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part1PeerVersion), pu2Part1CfgPeerVersion); + + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part2OwnVersion), pu2Part2CfgOwnVersion); + + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part2PeerVersion), pu2Part2CfgPeerVersion); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief to check if the WPS is active or not + * + * \param[in] + * prGlueInfo + * + * \return + * TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalWSCGetActiveState(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->fgWpsActive; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief update RSSI and LinkQuality to GLUE layer + * + * \param[in] + * prGlueInfo + * eNetTypeIdx + * cRssi + * cLinkQuality + * + * \return + * None + */ +/*----------------------------------------------------------------------------*/ +VOID +kalUpdateRSSI(IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_KAL_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN INT_8 cRssi, IN INT_8 cLinkQuality) +{ + struct iw_statistics *pStats = (struct iw_statistics *)NULL; + + ASSERT(prGlueInfo); + + switch (eNetTypeIdx) { + case KAL_NETWORK_TYPE_AIS_INDEX: + pStats = (struct iw_statistics *)(&(prGlueInfo->rIwStats)); + break; +#if CFG_ENABLE_WIFI_DIRECT +#if CFG_SUPPORT_P2P_RSSI_QUERY + case KAL_NETWORK_TYPE_P2P_INDEX: + pStats = (struct iw_statistics *)(&(prGlueInfo->rP2pIwStats)); + break; +#endif +#endif + default: + break; + + } + + if (pStats) { + pStats->qual.qual = cLinkQuality; + pStats->qual.noise = 0; + pStats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_NOISE_UPDATED | IW_QUAL_DBM; + pStats->qual.level = 0x100 + cRssi; + pStats->qual.updated |= IW_QUAL_LEVEL_UPDATED; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Pre-allocate I/O buffer + * + * \param[in] + * none + * + * \return + * TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalInitIOBuffer(VOID) +{ + UINT_32 u4Size; + + if (CFG_COALESCING_BUFFER_SIZE >= CFG_RX_COALESCING_BUFFER_SIZE) + u4Size = CFG_COALESCING_BUFFER_SIZE + sizeof(ENHANCE_MODE_DATA_STRUCT_T); + else + u4Size = CFG_RX_COALESCING_BUFFER_SIZE + sizeof(ENHANCE_MODE_DATA_STRUCT_T); + + pvIoBuffer = kmalloc(u4Size, GFP_KERNEL); + /* pvIoBuffer = dma_alloc_coherent(NULL, u4Size, &pvIoPhyBuf, GFP_KERNEL); */ + if (pvIoBuffer) { + pvIoBufferSize = u4Size; + pvIoBufferUsage = 0; + + return TRUE; + } + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Free pre-allocated I/O buffer + * + * \param[in] + * none + * + * \return + * none + */ +/*----------------------------------------------------------------------------*/ +VOID kalUninitIOBuffer(VOID) +{ + kfree(pvIoBuffer); +#ifdef MTK_DMA_BUF_MEMCPY_SUP + dma_free_coherent(NULL, CFG_RX_COALESCING_BUFFER_SIZE, pvDmaBuffer, pvDmaPhyBuf); +#endif /* MTK_DMA_BUF_MEMCPY_SUP */ + /* dma_free_coherent(NULL, pvIoBufferSize, pvIoBuffer, pvIoPhyBuf); */ + + pvIoBuffer = (PVOID) NULL; + pvIoBufferSize = 0; + pvIoBufferUsage = 0; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Dispatch pre-allocated I/O buffer + * + * \param[in] + * u4AllocSize + * + * \return + * PVOID for pointer of pre-allocated I/O buffer + */ +/*----------------------------------------------------------------------------*/ +PVOID kalAllocateIOBuffer(IN UINT_32 u4AllocSize) +{ + PVOID ret = (PVOID) NULL; + + if (pvIoBuffer) { + if (u4AllocSize <= (pvIoBufferSize - pvIoBufferUsage)) { + ret = (PVOID) &(((PUINT_8) (pvIoBuffer))[pvIoBufferUsage]); + pvIoBufferUsage += u4AllocSize; + } + } else { + /* fault tolerance */ + ret = (PVOID) kalMemAlloc(u4AllocSize, PHY_MEM_TYPE); + } + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Release all dispatched I/O buffer + * + * \param[in] + * none + * + * \return + * none + */ +/*----------------------------------------------------------------------------*/ +VOID kalReleaseIOBuffer(IN PVOID pvAddr, IN UINT_32 u4Size) +{ + if (pvIoBuffer) { + pvIoBufferUsage -= u4Size; + } else { + /* fault tolerance */ + kalMemFree(pvAddr, PHY_MEM_TYPE, u4Size); + } +} +/*----------------------------------------------------------------------------*/ +/*! +* \brief decode ethernet type from package head +* +* \param[in] +* none +* +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ + +UINT_8 kalGetPktEtherType(IN PUINT_8 pucPkt) +{ + UINT_16 u2EtherType; + PUINT_8 pucEthBody; + UINT_8 ucResult = ENUM_PKT_FLAG_NUM; + + if (pucPkt == NULL) { + DBGLOG(INIT, WARN, "kalGetPktEtherType pucPkt is null!\n"); + return ucResult; + } + + u2EtherType = (pucPkt[ETH_TYPE_LEN_OFFSET] << 8) | (pucPkt[ETH_TYPE_LEN_OFFSET + 1]); + pucEthBody = &pucPkt[ETH_HLEN]; + + switch (u2EtherType) { + case ETH_P_ARP: + { + DBGLOG(INIT, LOUD, "kalGetPktEtherType : ARP\n"); + ucResult = ENUM_PKT_ARP; + break; + } + case ETH_P_IP: + { + UINT_8 ucIpProto = pucEthBody[9]; /* IP header without options */ + + switch (ucIpProto) { + case IP_PRO_ICMP: + { + DBGLOG(INIT, LOUD, "kalGetPktEtherType : ICMP\n"); + ucResult = ENUM_PKT_ICMP; + break; + } + case IP_PRO_UDP: + { + PUINT_8 pucUdp = &pucEthBody[20]; + UINT_16 u2UdpSrcPort; + UINT_16 u2UdpDstPort; + + u2UdpDstPort = (pucUdp[2] << 8) | pucUdp[3]; + u2UdpSrcPort = (pucUdp[0] << 8) | pucUdp[1]; + + if ((u2UdpDstPort == UDP_PORT_DHCPS) || (u2UdpDstPort == UDP_PORT_DHCPC)) { + DBGLOG(INIT, LOUD, "kalGetPktEtherType : DHCP\n"); + ucResult = ENUM_PKT_DHCP; + break; + } else if (u2UdpSrcPort == UDP_PORT_DNS) { + DBGLOG(INIT, LOUD, "kalGetPktEtherType : DNS\n"); + ucResult = ENUM_PKT_DNS; + break; + } + } + } + break; + } + case ETH_P_PRE_1X: + { + ucResult = ENUM_PKT_PROTECTED_1X; + break; + } + case ETH_P_1X: + { + ucResult = ENUM_PKT_1X; + break; + } + case TDLS_FRM_PROT_TYPE: + { + ucResult = ENUM_PKT_TDLS; + break; + } + case ETH_WPI_1X: + { + ucResult = ENUM_PKT_WPI_1X; + break; + + } + default: + DBGLOG(INIT, LOUD, "unSupport pkt type:u2EtherType:0x%x\n" + , u2EtherType); + break; + } + + return ucResult; +} +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] prAdapter Pointer of ADAPTER_T + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +VOID +kalGetChannelList(IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_BAND_T eSpecificBand, + IN UINT_8 ucMaxChannelNum, IN PUINT_8 pucNumOfChannel, IN P_RF_CHANNEL_INFO_T paucChannelList) +{ + rlmDomainGetChnlList(prGlueInfo->prAdapter, eSpecificBand, FALSE, ucMaxChannelNum, + pucNumOfChannel, paucChannelList); +} +/*----------------------------------------------------------------------------*/ +/*! +* \brief : get APMCU Mem buffer +* +* \param[in] type +* \param[in] index +* \param[in] pucBuffer +* \param[in] u4BufferLen + +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ + +VOID kalGetAPMCUMen(IN P_GLUE_INFO_T prGlueInfo, IN UINT32 u4StartAddr + , IN UINT32 u4Offset, IN UINT32 index, OUT PUINT_8 pucBuffer, IN UINT_32 u4BufferLen) +{ + + PUINT8 descBaseAddr; + + DBGLOG(INIT, TRACE, "TC start addr:0x%x, index:%d, offset:0x%x len:%d" + , u4StartAddr, index, u4Offset, u4BufferLen); + + descBaseAddr = (prGlueInfo->rHifInfo.APMcuRegBaseAddr + u4StartAddr + +(u4Offset * index)); + + if ((descBaseAddr != NULL) && (pucBuffer != NULL)) + kalMemCopy(pucBuffer, descBaseAddr, u4BufferLen); + +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] prAdapter Pointer of ADAPTER_T + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalIsAPmode(IN P_GLUE_INFO_T prGlueInfo) +{ +#if CFG_ENABLE_WIFI_DIRECT + if (IS_NET_ACTIVE(prGlueInfo->prAdapter, NETWORK_TYPE_P2P_INDEX) && + p2pFuncIsAPMode(prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo)) + return TRUE; +#endif + + return FALSE; +} + +#ifdef MTK_DMA_BUF_MEMCPY_SUP +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function gets the physical address for Pre-allocate I/O buffer. + * + * \param[in] prGlueInfo Pointer of GLUE Data Structure + * \param[in] rLockCategory Specify which SPIN_LOCK + * \param[out] pu4Flags Pointer of a variable for saving IRQ flags + * + * \return physical addr + */ +/*----------------------------------------------------------------------------*/ +ULONG kalIOPhyAddrGet(IN ULONG VirtAddr) +{ + ULONG PhyAddr; + + if ((VirtAddr >= (ULONG) pvIoBuffer) && (VirtAddr <= ((ULONG) (pvIoBuffer) + pvIoBufferSize))) { + PhyAddr = (ULONG) pvIoPhyBuf; + PhyAddr += (VirtAddr - (ULONG) (pvIoBuffer)); + return PhyAddr; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function gets the physical address for Pre-allocate I/O buffer. + * + * \param[in] prGlueInfo Pointer of GLUE Data Structure + * \param[in] rLockCategory Specify which SPIN_LOCK + * \param[out] pu4Flags Pointer of a variable for saving IRQ flags + * + * \return physical addr + */ +/*----------------------------------------------------------------------------*/ +VOID kalDmaBufGet(IN VOID *dev, OUT VOID **VirtAddr, OUT VOID **PhyAddr) +{ + if (pvDmaBuffer == NULL) { + dma_addr_t rAddr; + + pvDmaBuffer = dma_alloc_coherent(dev, CFG_RX_COALESCING_BUFFER_SIZE, &rAddr, GFP_KERNEL); + pvDmaPhyBuf = (PVOID) rAddr; + if (pvDmaBuffer == NULL) + DBGLOG(INIT, ERROR, "pvDmaBuffer is still NULL.\n"); + } + + *VirtAddr = pvDmaBuffer; + *PhyAddr = pvDmaPhyBuf; +} +#endif /* MTK_DMA_BUF_MEMCPY_SUP */ + +#if CFG_SUPPORT_802_11W +/*----------------------------------------------------------------------------*/ +/*! + * \brief to check if the MFP is active or not + * + * \param[in] + * prGlueInfo + * + * \return + * TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +UINT_32 kalGetMfpSetting(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->rWpaInfo.u4Mfp; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief to check if the RSN IE CAP setting from supplicant + * + * \param[in] + * prGlueInfo + * + * \return + * TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +UINT_8 kalGetRsnIeMfpCap(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->rWpaInfo.ucRSNMfpCap; +} + +#endif + +struct file *kalFileOpen(const char *path, int flags, int rights) +{ + struct file *filp = NULL; + mm_segment_t oldfs; + int err = 0; + + oldfs = get_fs(); + set_fs(get_ds()); + filp = filp_open(path, flags, rights); + set_fs(oldfs); + if (IS_ERR(filp)) { + err = PTR_ERR(filp); + return NULL; + } + return filp; +} + +VOID kalFileClose(struct file *file) +{ + filp_close(file, NULL); +} + +UINT_32 kalFileRead(struct file *file, UINT_64 offset, UINT_8 *data, UINT_32 size) +{ + mm_segment_t oldfs; + INT_32 ret; + + oldfs = get_fs(); + set_fs(get_ds()); +#if KERNEL_VERSION(4, 13, 0) <= CFG80211_VERSION_CODE + ret = kernel_read(file, data, size, &offset); +#else + ret = vfs_read(file, data, size, &offset); +#endif + set_fs(oldfs); + return ret; +} + +UINT_32 kalFileWrite(struct file *file, UINT_64 offset, UINT_8 *data, UINT_32 size) +{ + mm_segment_t oldfs; + INT_32 ret; + + oldfs = get_fs(); + set_fs(get_ds()); +#if KERNEL_VERSION(4, 13, 0) <= CFG80211_VERSION_CODE + ret = kernel_write(file, data, size, &offset); +#else + ret = vfs_write(file, data, size, &offset); +#endif + + set_fs(oldfs); + return ret; +} + +UINT_32 kalWriteToFile(const PUINT_8 pucPath, BOOLEAN fgDoAppend, PUINT_8 pucData, UINT_32 u4Size) +{ + struct file *file = NULL; + UINT_32 ret = -1; + UINT_32 u4Flags = 0; + + if (fgDoAppend) + u4Flags = O_APPEND; + + file = kalFileOpen(pucPath, O_WRONLY | O_CREAT | u4Flags, S_IRWXU); + if (file) { + ret = kalFileWrite(file, 0, pucData, u4Size); + kalFileClose(file); + } + + return ret; +} + +INT_32 kalReadToFile(const PUINT_8 pucPath, PUINT_8 pucData, UINT_32 u4Size, PUINT_32 pu4ReadSize) +{ + struct file *file = NULL; + INT_32 ret = -1; + UINT_32 u4ReadSize = 0; + + DBGLOG(INIT, LOUD, "kalReadToFile() path %s\n", pucPath); + + file = kalFileOpen(pucPath, O_RDONLY, 0); + + if ((file != NULL) && !IS_ERR(file)) { + u4ReadSize = kalFileRead(file, 0, pucData, u4Size); + kalFileClose(file); + if (pu4ReadSize) + *pu4ReadSize = u4ReadSize; + ret = 0; + } + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To indicate BSS-INFO to NL80211 as scanning result + * + * \param[in] + * prGlueInfo + * pucBeaconProbeResp + * u4FrameLen + * + * + * + * \return + * none + */ +/*----------------------------------------------------------------------------*/ +VOID +kalIndicateBssInfo(IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucBeaconProbeResp, + IN UINT_32 u4FrameLen, IN UINT_8 ucChannelNum, IN INT_32 i4SignalStrength) +{ + struct wiphy *wiphy; + struct ieee80211_channel *prChannel = NULL; + + ASSERT(prGlueInfo); + wiphy = priv_to_wiphy(prGlueInfo); + + /* search through channel entries */ + if (ucChannelNum <= 14) { + prChannel = + ieee80211_get_channel(wiphy, ieee80211_channel_to_frequency(ucChannelNum, IEEE80211_BAND_2GHZ)); + } else { + prChannel = + ieee80211_get_channel(wiphy, ieee80211_channel_to_frequency(ucChannelNum, IEEE80211_BAND_5GHZ)); + } + + if (prChannel != NULL && prGlueInfo->fgIsRegistered == TRUE) { + struct cfg80211_bss *bss; +#if CFG_SUPPORT_TSF_USING_BOOTTIME + struct ieee80211_mgmt *prMgmtFrame = (struct ieee80211_mgmt *)pucBeaconProbeResp; + + prMgmtFrame->u.beacon.timestamp = kalGetBootTime(); +#endif + ScanCnt++; + + /* indicate to NL80211 subsystem */ + bss = cfg80211_inform_bss_frame(wiphy, + prChannel, + (struct ieee80211_mgmt *)pucBeaconProbeResp, + u4FrameLen, i4SignalStrength * 100, GFP_KERNEL); + + if (!bss) { + ScanDoneFailCnt++; + DBGLOG(SCN, WARN, "inform bss to cfg80211 failed, bss channel %d, rssi %d\n", + ucChannelNum, i4SignalStrength); + } else { + cfg80211_put_bss(wiphy, bss); + DBGLOG(SCN, TRACE, "inform bss to cfg80211, bss channel %d, rssi %d\n", + ucChannelNum, i4SignalStrength); + } + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief abstraction of cfg80211_scan_done + * Since linux-4.8.y the 2nd parameter is changed from bool to + * struct cfg80211_scan_info, but we don't use all fields yet. + * + * @request: the corresponding scan request (sanity checked by callers!) + * @aborted: set to true if the scan was aborted for any reason, + * userspace will be notified of that + * + * \return + * none + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(4, 8, 0) <= LINUX_VERSION_CODE +void kalCfg80211ScanDone(struct cfg80211_scan_request *request, bool aborted) +{ + struct cfg80211_scan_info info = { .aborted = aborted }; + + cfg80211_scan_done(request, &info); +} +#else +void kalCfg80211ScanDone(struct cfg80211_scan_request *request, bool aborted) +{ + cfg80211_scan_done(request, aborted); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To indicate channel ready + * + * \param[in] + * prGlueInfo + * + * \return + * none + */ +/*----------------------------------------------------------------------------*/ +VOID +kalReadyOnChannel(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, + IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_8 ucChannelNum, IN UINT_32 u4DurationMs) +{ + struct ieee80211_channel *prChannel = NULL; + enum nl80211_channel_type rChannelType; + + /* ucChannelNum = wlanGetChannelNumberByNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_AIS_INDEX); */ + + if (prGlueInfo->fgIsRegistered == TRUE) { + if (ucChannelNum <= 14) { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, IEEE80211_BAND_2GHZ)); + } else { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, IEEE80211_BAND_5GHZ)); + } + + switch (eSco) { + case CHNL_EXT_SCN: + rChannelType = NL80211_CHAN_NO_HT; + break; + + case CHNL_EXT_SCA: + rChannelType = NL80211_CHAN_HT40MINUS; + break; + + case CHNL_EXT_SCB: + rChannelType = NL80211_CHAN_HT40PLUS; + break; + + case CHNL_EXT_RES: + default: + rChannelType = NL80211_CHAN_HT20; + break; + } + + cfg80211_ready_on_channel(prGlueInfo->prDevHandler->ieee80211_ptr, u8Cookie, prChannel, u4DurationMs, + GFP_KERNEL); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To indicate channel expiration + * + * \param[in] + * prGlueInfo + * + * \return + * none + */ +/*----------------------------------------------------------------------------*/ +VOID +kalRemainOnChannelExpired(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_8 ucChannelNum) +{ + struct ieee80211_channel *prChannel = NULL; + enum nl80211_channel_type rChannelType; + + ucChannelNum = wlanGetChannelNumberByNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_AIS_INDEX); + + if (prGlueInfo->fgIsRegistered == TRUE) { + if (ucChannelNum <= 14) { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, IEEE80211_BAND_2GHZ)); + } else { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, IEEE80211_BAND_5GHZ)); + } + + switch (eSco) { + case CHNL_EXT_SCN: + rChannelType = NL80211_CHAN_NO_HT; + break; + + case CHNL_EXT_SCA: + rChannelType = NL80211_CHAN_HT40MINUS; + break; + + case CHNL_EXT_SCB: + rChannelType = NL80211_CHAN_HT40PLUS; + break; + + case CHNL_EXT_RES: + default: + rChannelType = NL80211_CHAN_HT20; + break; + } + + cfg80211_remain_on_channel_expired(prGlueInfo->prDevHandler->ieee80211_ptr, u8Cookie, prChannel, + GFP_KERNEL); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To indicate Mgmt tx status + * + * \param[in] + * prGlueInfo + * + * \return + * none + */ +/*----------------------------------------------------------------------------*/ +VOID +kalIndicateMgmtTxStatus(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, IN BOOLEAN fgIsAck, IN PUINT_8 pucFrameBuf, IN UINT_32 u4FrameLen) +{ + + do { + if ((prGlueInfo == NULL) || (pucFrameBuf == NULL) || (u4FrameLen == 0)) { + DBGLOG(AIS, TRACE, "Unexpected pointer PARAM. %p, %p, %u.", + prGlueInfo, pucFrameBuf, u4FrameLen); + ASSERT(FALSE); + break; + } + + cfg80211_mgmt_tx_status(prGlueInfo->prDevHandler->ieee80211_ptr, + u8Cookie, pucFrameBuf, u4FrameLen, fgIsAck, GFP_KERNEL); + } while (FALSE); + +} /* kalIndicateMgmtTxStatus */ + +VOID kalIndicateRxMgmtFrame(IN P_GLUE_INFO_T prGlueInfo, IN P_SW_RFB_T prSwRfb) +{ +#define DBG_MGMT_FRAME_INDICATION 1 + INT_32 i4Freq = 0; + UINT_8 ucChnlNum = 0; +#if DBG_MGMT_FRAME_INDICATION + P_WLAN_MAC_HEADER_T prWlanHeader = (P_WLAN_MAC_HEADER_T) NULL; +#endif + + do { + if ((prGlueInfo == NULL) || (prSwRfb == NULL)) { + ASSERT(FALSE); + break; + } + + ucChnlNum = prSwRfb->prHifRxHdr->ucHwChannelNum; + +#if DBG_MGMT_FRAME_INDICATION + prWlanHeader = (P_WLAN_MAC_HEADER_T) prSwRfb->pvHeader; + + switch (prWlanHeader->u2FrameCtrl) { + case MAC_FRAME_PROBE_REQ: + DBGLOG(AIS, TRACE, "RX Probe Req at channel %d ", ucChnlNum); + break; + case MAC_FRAME_PROBE_RSP: + DBGLOG(AIS, TRACE, "RX Probe Rsp at channel %d ", ucChnlNum); + break; + case MAC_FRAME_ACTION: + DBGLOG(AIS, TRACE, "RX Action frame at channel %d ", ucChnlNum); + break; + default: + DBGLOG(AIS, INFO, "RX Packet:%d at channel %d ", prWlanHeader->u2FrameCtrl, ucChnlNum); + break; + } + +#endif + i4Freq = nicChannelNum2Freq(ucChnlNum) / 1000; + + cfg80211_rx_mgmt(prGlueInfo->prDevHandler->ieee80211_ptr, /* struct net_device * dev, */ + i4Freq, + RCPI_TO_dBm(prSwRfb->prHifRxHdr->ucRcpi), + prSwRfb->pvHeader, prSwRfb->u2PacketLen, GFP_KERNEL); + } while (FALSE); + +} /* kalIndicateRxMgmtFrame */ + +#if CFG_SUPPORT_AGPS_ASSIST +BOOLEAN kalIndicateAgpsNotify(P_ADAPTER_T prAdapter, UINT_8 cmd, PUINT_8 data, UINT_16 dataLen) +{ + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + + struct sk_buff *skb = cfg80211_testmode_alloc_event_skb(priv_to_wiphy(prGlueInfo), + dataLen, GFP_KERNEL); + if (!skb) { + DBGLOG(AIS, ERROR, "kalIndicateAgpsNotify: alloc skb failed\n"); + return FALSE; + } + + /* DBGLOG(CCX, INFO, ("WLAN_STATUS_AGPS_NOTIFY, cmd=%d\n", cmd)); */ + if (unlikely(nla_put(skb, MTK_ATTR_AGPS_CMD, sizeof(cmd), &cmd) < 0)) + goto nla_put_failure; + if (dataLen > 0 && data && unlikely(nla_put(skb, MTK_ATTR_AGPS_DATA, dataLen, data) < 0)) + goto nla_put_failure; + if (unlikely(nla_put(skb, MTK_ATTR_AGPS_IFINDEX, sizeof(UINT_32), &prGlueInfo->prDevHandler->ifindex) < 0)) + goto nla_put_failure; + /* currently, the ifname maybe wlan0, p2p0, so the maximum name length will be 5 bytes */ + if (unlikely(nla_put(skb, MTK_ATTR_AGPS_IFNAME, 5, prGlueInfo->prDevHandler->name) < 0)) + goto nla_put_failure; + cfg80211_testmode_event(skb, GFP_KERNEL); + return TRUE; + +nla_put_failure: + kfree_skb(skb); + return FALSE; +} +#endif + +#if (CFG_SUPPORT_MET_PROFILING == 1) +#define PROC_MET_PROF_CTRL "met_ctrl" +#define PROC_MET_PROF_PORT "met_port" + +struct proc_dir_entry *pMetProcDir; +void *pMetGlobalData; + +#if 0 +static unsigned long __read_mostly tracing_mark_write_addr; +#endif + +static inline void __mt_update_tracing_mark_write_addr(void) +{ +#if 0 + if (unlikely(tracing_mark_write_addr == 0)) + tracing_mark_write_addr = kallsyms_lookup_name("tracing_mark_write"); +#endif +} + + +VOID kalMetProfilingStart(IN P_GLUE_INFO_T prGlueInfo, IN struct sk_buff *prSkb) +{ + UINT_8 ucIpVersion; + UINT_16 u2UdpSrcPort; + UINT_16 u2RtpSn; + PUINT_8 pucEthHdr = prSkb->data; + PUINT_8 pucIpHdr, pucUdpHdr, pucRtpHdr; + + /* | Ethernet(14) | IP(20) | UDP(8)| RTP(12) | */ + /* UDP==> |SRC_PORT(2)|DST_PORT(2)|LEN(2)|CHKSUM(2)| */ + /* RTP==> |CTRL(2)|SEQ(2)|TimeStamp(4)|... */ + /* printk("MET_PROF: MET enable=%d(HardXmit)\n", prGlueInfo->u8MetProfEnable); */ + if (prGlueInfo->u8MetProfEnable == 1) { + u2UdpSrcPort = prGlueInfo->u16MetUdpPort; + if ((*(pucEthHdr + 12) == 0x08) && (*(pucEthHdr + 13) == 0x00)) { + /* IP */ + pucIpHdr = pucEthHdr + ETH_HLEN; + ucIpVersion = (*pucIpHdr & IPVH_VERSION_MASK) >> IPVH_VERSION_OFFSET; + if ((ucIpVersion == IPVERSION) && (pucIpHdr[IPV4_HDR_IP_PROTOCOL_OFFSET] == IP_PROTOCOL_UDP)) { + /* UDP */ + pucUdpHdr = pucIpHdr + IP_HEADER_LEN; + /* check UDP port number */ + if (((UINT_16) pucUdpHdr[0] << 8 | (UINT_16) pucUdpHdr[1]) == u2UdpSrcPort) { + /* RTP */ + pucRtpHdr = pucUdpHdr + 8; + u2RtpSn = (UINT_16) pucRtpHdr[2] << 8 | pucRtpHdr[3]; + /* + * trace_printk("S|%d|%s|%d\n", current->tgid, "WIFI-CHIP", u2RtpSn); + * //frm_sequence); + */ +#if 0 + __mt_update_tracing_mark_write_addr(); + if (tracing_mark_write_addr != 0) { + KERNEL_event_trace_printk(tracing_mark_write_addr, "S|%d|%s|%d\n", + current->tgid, "WIFI-CHIP", u2RtpSn); + } +#endif + } + } + } + } +} + +VOID kalMetProfilingFinish(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + UINT_8 ucIpVersion; + UINT_16 u2UdpSrcPort; + UINT_16 u2RtpSn; + struct sk_buff *prSkb = (struct sk_buff *)prMsduInfo->prPacket; + PUINT_8 pucEthHdr = prSkb->data; + PUINT_8 pucIpHdr, pucUdpHdr, pucRtpHdr; + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + + /* | Ethernet(14) | IP(20) | UDP(8)| RTP(12) | */ + /* UDP==> |SRC_PORT(2)|DST_PORT(2)|LEN(2)|CHKSUM(2)| */ + /* RTP==> |CTRL(2)|SEQ(2)|TimeStamp(4)|... */ + /* printk("MET_PROF: MET enable=%d(TxMsdu)\n", prGlueInfo->u8MetProfEnable); */ + if (prGlueInfo->u8MetProfEnable == 1) { + u2UdpSrcPort = prGlueInfo->u16MetUdpPort; + if ((*(pucEthHdr + 12) == 0x08) && (*(pucEthHdr + 13) == 0x00)) { + /* IP */ + pucIpHdr = pucEthHdr + ETH_HLEN; + ucIpVersion = (*pucIpHdr & IPVH_VERSION_MASK) >> IPVH_VERSION_OFFSET; + if ((ucIpVersion == IPVERSION) && (pucIpHdr[IPV4_HDR_IP_PROTOCOL_OFFSET] == IP_PROTOCOL_UDP)) { + /* UDP */ + pucUdpHdr = pucIpHdr + IP_HEADER_LEN; + /* check UDP port number */ + if (((UINT_16) pucUdpHdr[0] << 8 | (UINT_16) pucUdpHdr[1]) == u2UdpSrcPort) { + /* RTP */ + pucRtpHdr = pucUdpHdr + 8; + u2RtpSn = (UINT_16) pucRtpHdr[2] << 8 | pucRtpHdr[3]; + /* + * trace_printk("F|%d|%s|%d\n", current->tgid, "WIFI-CHIP", u2RtpSn); + * //frm_sequence); + */ +#if 0 + __mt_update_tracing_mark_write_addr(); + if (tracing_mark_write_addr != 0) { + KERNEL_event_trace_printk(tracing_mark_write_addr, "F|%d|%s|%d\n", + current->tgid, "WIFI-CHIP", u2RtpSn); + } +#endif + } + } + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief The PROC function for adjusting Debug Level to turn on/off debugging message. + * + * \param[in] file pointer to file. + * \param[in] buffer Buffer from user space. + * \param[in] count Number of characters to write + * \param[in] data Pointer to the private data structure. + * + * \return number of characters write from User Space. + */ +/*----------------------------------------------------------------------------*/ +static ssize_t kalMetCtrlWriteProcfs(struct file *file, const char __user *buffer, size_t count, loff_t *off) +{ + char acBuf[128 + 1]; /* + 1 for "\0" */ + UINT_32 u4CopySize; + int u8MetProfEnable; + + IN P_GLUE_INFO_T prGlueInfo; + + u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + if (copy_from_user(acBuf, buffer, u4CopySize)) + return -1; + acBuf[u4CopySize] = '\0'; + + if (sscanf(acBuf, " %d", &u8MetProfEnable) == 1) + DBGLOG(INIT, INFO, "MET_PROF: Write MET PROC Enable=%d\n", u8MetProfEnable); + if (pMetGlobalData != NULL) { + prGlueInfo = (P_GLUE_INFO_T) pMetGlobalData; + prGlueInfo->u8MetProfEnable = (UINT_8) u8MetProfEnable; + } + return count; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief The PROC function for adjusting Debug Level to turn on/off debugging message. + * + * \param[in] file pointer to file. + * \param[in] buffer Buffer from user space. + * \param[in] count Number of characters to write + * \param[in] data Pointer to the private data structure. + * + * \return number of characters write from User Space. + */ +/*----------------------------------------------------------------------------*/ +static ssize_t kalMetPortWriteProcfs(struct file *file, const char __user *buffer, size_t count, loff_t *off) +{ + char acBuf[128 + 1]; /* + 1 for "\0" */ + UINT_32 u4CopySize; + int u16MetUdpPort; + + IN P_GLUE_INFO_T prGlueInfo; + + u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + if (copy_from_user(acBuf, buffer, u4CopySize)) + return -1; + acBuf[u4CopySize] = '\0'; + + if (sscanf(acBuf, " %d", &u16MetUdpPort) == 1) + DBGLOG(INIT, INFO, "MET_PROF: Write MET PROC UDP_PORT=%d\n", u16MetUdpPort); + if (pMetGlobalData != NULL) { + prGlueInfo = (P_GLUE_INFO_T) pMetGlobalData; + prGlueInfo->u16MetUdpPort = (UINT_16) u16MetUdpPort; + } + return count; +} + +const struct file_operations rMetProcCtrlFops = { + .write = kalMetCtrlWriteProcfs +}; + +const struct file_operations rMetProcPortFops = { + .write = kalMetPortWriteProcfs +}; + +int kalMetInitProcfs(IN P_GLUE_INFO_T prGlueInfo) +{ + /* struct proc_dir_entry *pMetProcDir; */ + if (init_net.proc_net == (struct proc_dir_entry *)NULL) { + DBGLOG(INIT, INFO, "init proc fs fail: proc_net == NULL\n"); + return -ENOENT; + } + /* + * Directory: Root (/proc/net/wlan0) + */ + pMetProcDir = proc_mkdir("wlan0", init_net.proc_net); + if (pMetProcDir == NULL) + return -ENOENT; + /* + * /proc/net/wlan0 + * |-- met_ctrl (PROC_MET_PROF_CTRL) + * |-- met_port (PROC_MET_PROF_PORT) + */ + /* proc_create(PROC_MET_PROF_CTRL, 0x0644, pMetProcDir, &rMetProcFops); */ + proc_create(PROC_MET_PROF_CTRL, 0, pMetProcDir, &rMetProcCtrlFops); + proc_create(PROC_MET_PROF_PORT, 0, pMetProcDir, &rMetProcPortFops); + + pMetGlobalData = (void *)prGlueInfo; + + return 0; +} + +int kalMetRemoveProcfs(void) +{ + + if (init_net.proc_net == (struct proc_dir_entry *)NULL) { + DBGLOG(INIT, WARN, "remove proc fs fail: proc_net == NULL\n"); + return -ENOENT; + } + remove_proc_entry(PROC_MET_PROF_CTRL, pMetProcDir); + remove_proc_entry(PROC_MET_PROF_PORT, pMetProcDir); + /* remove root directory (proc/net/wlan0) */ + remove_proc_entry("wlan0", init_net.proc_net); + /* clear MetGlobalData */ + pMetGlobalData = NULL; + + return 0; +} +#endif +UINT_64 kalGetBootTime(void) +{ + struct timespec ts; + UINT_64 bootTime = 0; + + get_monotonic_boottime(&ts); + /* + * we assign ts.tv_sec to bootTime first, then multiply USEC_PER_SEC + * this will prevent multiply result turn to a negative value on 32bit system + */ + bootTime = ts.tv_sec; + bootTime *= USEC_PER_SEC; + bootTime += ts.tv_nsec / NSEC_PER_USEC; + return bootTime; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To indicate scheduled scan results are avilable + * + * \param[in] + * prGlueInfo + * + * \return + * None + */ +/*----------------------------------------------------------------------------*/ +VOID kalSchedScanResults(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE + cfg80211_sched_scan_results(priv_to_wiphy(prGlueInfo), 0); +#else + cfg80211_sched_scan_results(priv_to_wiphy(prGlueInfo)); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate scheduled scan has been stopped +* +* \param[in] +* prGlueInfo +* +* \return +* None +*/ +/*----------------------------------------------------------------------------*/ +VOID kalSchedScanStopped(IN P_GLUE_INFO_T prGlueInfo) +{ + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + /* 1. reset first for newly incoming request */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if (prGlueInfo->prSchedScanRequest != NULL) + prGlueInfo->prSchedScanRequest = NULL; + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + DBGLOG(SCN, INFO, "cfg80211_sched_scan_stopped send event\n"); + + /* 2. indication to cfg80211 */ + /* + * 20150205 change cfg80211_sched_scan_stopped to work queue to use K thread to send event instead of Tx thread + * due to sched_scan_mtx dead lock issue by Tx thread serves oid cmds and send event in the same time + */ + DBGLOG(SCN, TRACE, "start work queue to send event\n"); + schedule_delayed_work(&sched_workq, 0); + DBGLOG(SCN, TRACE, "tx_thread return from kalSchedScanStoppped\n"); + +} + +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To check if device if wake up by wlan + * + * \param[in] + * prAdapter + * + * \return + * TRUE: wake up by wlan; otherwise, FALSE + */ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalIsWakeupByWlan(P_ADAPTER_T prAdapter) +{ + /* + * SUSPEND_FLAG_FOR_WAKEUP_REASON is set means system has suspended, but may be failed + * duo to some driver suspend failed. so we need help of function slp_get_wake_reason + */ + if (test_and_clear_bit(SUSPEND_FLAG_FOR_WAKEUP_REASON, &prAdapter->ulSuspendFlag) == 0) + return FALSE; + /* + * if slp_get_wake_reason or spm_get_last_wakeup_src is NULL, it means SPM module didn't implement + * it. then we should return FALSE always. otherwise, if slp_get_wake_reason returns WR_WAKE_SRC, + * then it means the host is suspend successfully. + */ + if (KERNEL_slp_get_wake_reason() != WR_WAKE_SRC) + return FALSE; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + /* + * spm_get_last_wakeup_src will returns the last wakeup source, + * WAKE_SRC_R12_CONN2AP_SPM_WAKEUP_B is connsys + */ + return !!(KERNEL_spm_get_last_wakeup_src() & + WAKE_SRC_R12_CONN2AP_SPM_WAKEUP_B); +#else + /* + * spm_get_last_wakeup_src will returns the last wakeup source, + * WAKE_SRC_CONN2AP is connsys + */ + return !!(KERNEL_spm_get_last_wakeup_src() & WAKE_SRC_CONN2AP); +#endif +} +#endif +VOID kalShowStackEachTask(IN P_GLUE_INFO_T prGlueInfo) +{ + if (prGlueInfo) { + DBGLOG(INIT, ERROR, "***** show [main thread] *****\n"); + connectivity_export_show_stack(prGlueInfo->main_thread, NULL); + } + + DBGLOG(INIT, ERROR, "***** show [rHaltCtrl.owner] *****\n"); + connectivity_export_show_stack(rHaltCtrl.owner, NULL); + + DBGLOG(INIT, ERROR, "***** show [Current] *****\n"); + connectivity_export_show_stack(current, NULL); +} +INT_32 kalHaltLock(UINT_32 waitMs) +{ + INT_32 i4Ret = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_GL_IO_REQ_T prIoReq = NULL; + + if (waitMs) { + i4Ret = down_timeout(&rHaltCtrl.lock, MSEC_TO_JIFFIES(waitMs)); + if (!i4Ret) + goto success; + if (i4Ret != -ETIME) + return i4Ret; + if (rHaltCtrl.fgHeldByKalIoctl) { + wlanExportGlueInfo(&prGlueInfo); + prIoReq = &(prGlueInfo->OidEntry); + ASSERT(prIoReq); + DBGLOG(OID, WARN + , "OidHandler 0x%p pvInfoBuf 0x%p,Buflen =%d,InfoLen=%p fgRead=%d,fgWaitRsp=%d,now[%u]\n" + , prIoReq->pfnOidHandler + , prIoReq->pvInfoBuf + , prIoReq->u4InfoBufLen + , prIoReq->pu4QryInfoLen + , prIoReq->fgRead + , prIoReq->fgWaitResp, kalGetTimeTick()); + wlanDebugCommandRecodDump(); + wlanDumpCommandFwStatus(); + wlanDumpTcResAndTxedCmd(NULL, 0); + cmdBufDumpCmdQueue(&prGlueInfo->prAdapter->rPendingCmdQueue, "waiting response CMD queue"); + + } else { + DBGLOG(INIT, ERROR, "halt lock held by %s pid %d longer than %u ms!\n", + rHaltCtrl.owner->comm, rHaltCtrl.owner->pid, + kalGetTimeTick() - rHaltCtrl.u4HoldStart); + } + kalShowStackEachTask(prGlueInfo); + + + return i4Ret; + } + down(&rHaltCtrl.lock); +success: + rHaltCtrl.owner = current; + rHaltCtrl.u4HoldStart = kalGetTimeTick(); + return 0; +} + +INT_32 kalHaltTryLock(VOID) +{ + INT_32 i4Ret = 0; + + i4Ret = down_trylock(&rHaltCtrl.lock); + if (i4Ret) + return i4Ret; + rHaltCtrl.owner = current; + rHaltCtrl.u4HoldStart = kalGetTimeTick(); + return 0; +} + +VOID kalHaltUnlock(VOID) +{ + if (kalGetTimeTick() - rHaltCtrl.u4HoldStart > WLAN_OID_TIMEOUT_THRESHOLD * 2 && + rHaltCtrl.owner) + DBGLOG(INIT, ERROR, "process %s pid %d hold halt lock longer than 4s!\n", + rHaltCtrl.owner->comm, rHaltCtrl.owner->pid); + rHaltCtrl.owner = NULL; + up(&rHaltCtrl.lock); +} + +VOID kalSetHalted(BOOLEAN fgHalt) +{ + rHaltCtrl.fgHalt = fgHalt; +} + +BOOLEAN kalIsHalted(VOID) +{ + return rHaltCtrl.fgHalt; +} + +VOID kalPerMonDump(IN P_GLUE_INFO_T prGlueInfo) +{ + struct PERF_MONITOR_T *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + DBGLOG(SW4, WARN, "ulPerfMonFlag:0x%lx\n", prPerMonitor->ulPerfMonFlag); + DBGLOG(SW4, WARN, "ulLastTxBytes:%ld\n", prPerMonitor->ulLastTxBytes); + DBGLOG(SW4, WARN, "ulLastRxBytes:%ld\n", prPerMonitor->ulLastRxBytes); + DBGLOG(SW4, WARN, "ulP2PLastTxBytes:%ld\n", prPerMonitor->ulP2PLastTxBytes); + DBGLOG(SW4, WARN, "ulP2PLastRxBytes:%ld\n", prPerMonitor->ulP2PLastRxBytes); + DBGLOG(SW4, WARN, "ulThroughput:%ld\n", prPerMonitor->ulThroughput); + DBGLOG(SW4, WARN, "u4UpdatePeriod:%d\n", prPerMonitor->u4UpdatePeriod); + DBGLOG(SW4, WARN, "u4TarPerfLevel:%d\n", prPerMonitor->u4TarPerfLevel); + DBGLOG(SW4, WARN, "u4CurrPerfLevel:%d\n", prPerMonitor->u4CurrPerfLevel); + DBGLOG(SW4, WARN, "netStats tx_bytes:%ld\n", prGlueInfo->rNetDevStats.tx_bytes); + DBGLOG(SW4, WARN, "netStats tx_bytes:%ld\n", prGlueInfo->rNetDevStats.rx_bytes); + DBGLOG(SW4, WARN, "p2p netStats tx_bytes:%ld\n", prGlueInfo->prP2PInfo->rNetDevStats.tx_bytes); + DBGLOG(SW4, WARN, "p2p netStats tx_bytes:%ld\n", prGlueInfo->prP2PInfo->rNetDevStats.rx_bytes); +} + +inline INT_32 kalPerMonInit(IN P_GLUE_INFO_T prGlueInfo) +{ + struct PERF_MONITOR_T *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + DBGLOG(SW4, TRACE, "enter %s\n", __func__); + if (KAL_TEST_BIT(PERF_MON_RUNNING_BIT, prPerMonitor->ulPerfMonFlag)) + DBGLOG(SW4, WARN, "abnormal, perf monitory already running\n"); + KAL_CLR_BIT(PERF_MON_RUNNING_BIT, prPerMonitor->ulPerfMonFlag); + KAL_CLR_BIT(PERF_MON_DISABLE_BIT, prPerMonitor->ulPerfMonFlag); + KAL_SET_BIT(PERF_MON_STOP_BIT, prPerMonitor->ulPerfMonFlag); + prPerMonitor->u4UpdatePeriod = 1000; + cnmTimerInitTimer(prGlueInfo->prAdapter, + &prPerMonitor->rPerfMonTimer, + (PFN_MGMT_TIMEOUT_FUNC) kalPerMonHandler, (ULONG) NULL); + DBGLOG(SW4, TRACE, "exit %s\n", __func__); + return 0; +} + +inline INT_32 kalPerMonDisable(IN P_GLUE_INFO_T prGlueInfo) +{ + struct PERF_MONITOR_T *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + + DBGLOG(SW4, TRACE, "enter %s\n", __func__); + if (KAL_TEST_BIT(PERF_MON_RUNNING_BIT, prPerMonitor->ulPerfMonFlag)) { + DBGLOG(SW4, TRACE, "need to stop before disable\n"); + kalPerMonStop(prGlueInfo); + } + KAL_SET_BIT(PERF_MON_DISABLE_BIT, prPerMonitor->ulPerfMonFlag); + DBGLOG(SW4, TRACE, "exit %s\n", __func__); + return 0; +} + +inline INT_32 kalPerMonEnable(IN P_GLUE_INFO_T prGlueInfo) +{ + struct PERF_MONITOR_T *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + + DBGLOG(SW4, INFO, "enter %s\n", __func__); + KAL_CLR_BIT(PERF_MON_DISABLE_BIT, prPerMonitor->ulPerfMonFlag); + DBGLOG(SW4, TRACE, "exit %s\n", __func__); + return 0; +} + +inline INT_32 kalPerMonStart(IN P_GLUE_INFO_T prGlueInfo) +{ + struct PERF_MONITOR_T *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + DBGLOG(SW4, TRACE, "enter %s\n", __func__); + + if ((wlan_fb_power_down || fgIsUnderSuspend) && + !KAL_TEST_BIT(PERF_MON_DISABLE_BIT, prPerMonitor->ulPerfMonFlag)) { + /* + * Remove this to prevent KE, kalPerMonStart might be called in soft irq + * kalBoostCpu might call flush_work which will use wait_for_completion + * then KE will happen in this case + * Simply don't start performance monitor here + */ + /*kalPerMonDisable(prGlueInfo);*/ + return 0; + } + if (KAL_TEST_BIT(PERF_MON_DISABLE_BIT, prPerMonitor->ulPerfMonFlag) || + KAL_TEST_BIT(PERF_MON_RUNNING_BIT, prPerMonitor->ulPerfMonFlag)) + return 0; + + prPerMonitor->ulLastRxBytes = 0; + prPerMonitor->ulLastTxBytes = 0; + prPerMonitor->ulP2PLastRxBytes = 0; + prPerMonitor->ulP2PLastTxBytes = 0; + prPerMonitor->ulThroughput = 0; + prPerMonitor->u4CurrPerfLevel = 0; + prPerMonitor->u4TarPerfLevel = 0; + prPerMonitor->u1ShutdownCoreCount = 0; + + cnmTimerStartTimer(prGlueInfo->prAdapter, &prPerMonitor->rPerfMonTimer, prPerMonitor->u4UpdatePeriod); + KAL_SET_BIT(PERF_MON_RUNNING_BIT, prPerMonitor->ulPerfMonFlag); + KAL_CLR_BIT(PERF_MON_STOP_BIT, prPerMonitor->ulPerfMonFlag); + DBGLOG(SW4, INFO, "perf monitor started\n"); + return 0; +} + +inline INT_32 kalPerMonStop(IN P_GLUE_INFO_T prGlueInfo) +{ + struct PERF_MONITOR_T *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + DBGLOG(SW4, TRACE, "enter %s\n", __func__); + + if (KAL_TEST_BIT(PERF_MON_DISABLE_BIT, prPerMonitor->ulPerfMonFlag)) { + DBGLOG(SW4, TRACE, "perf monitory disabled\n"); + return 0; + } + + if (KAL_TEST_BIT(PERF_MON_STOP_BIT, prPerMonitor->ulPerfMonFlag)) { + DBGLOG(SW4, TRACE, "perf monitory already stopped\n"); + return 0; + } + + KAL_SET_BIT(PERF_MON_STOP_BIT, prPerMonitor->ulPerfMonFlag); + if (KAL_TEST_BIT(PERF_MON_RUNNING_BIT, prPerMonitor->ulPerfMonFlag)) { + cnmTimerStopTimer(prGlueInfo->prAdapter, &prPerMonitor->rPerfMonTimer); + KAL_CLR_BIT(PERF_MON_RUNNING_BIT, prPerMonitor->ulPerfMonFlag); + prPerMonitor->ulLastRxBytes = 0; + prPerMonitor->ulLastTxBytes = 0; + prPerMonitor->ulP2PLastRxBytes = 0; + prPerMonitor->ulP2PLastTxBytes = 0; + prPerMonitor->ulThroughput = 0; + prPerMonitor->u4CurrPerfLevel = 0; + prPerMonitor->u4TarPerfLevel = 0; + prPerMonitor->u1ShutdownCoreCount = 0; + + /*Cancel CPU performance mode request*/ + kalBoostCpu(prGlueInfo, 0); + } + DBGLOG(SW4, TRACE, "exit %s\n", __func__); + return 0; +} + +inline INT_32 kalPerMonDestroy(IN P_GLUE_INFO_T prGlueInfo) +{ + kalPerMonDisable(prGlueInfo); + return 0; +} + +VOID kalPerMonHandler(IN P_ADAPTER_T prAdapter, ULONG ulParam) +{ + /* Calculate current throughput */ + struct PERF_MONITOR_T *prPerMonitor; + struct net_device *prNetDev = NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + LONG latestTxBytes, latestRxBytes, txDiffBytes, rxDiffBytes; + LONG p2pLatestTxBytes, p2pLatestRxBytes, p2pTxDiffBytes, p2pRxDiffBytes; + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + BOOLEAN needBoostCpu = TRUE; +#ifdef ENHANCE_AP_MODE_THROUGHPUT + BOOLEAN fgIsPureAp = FALSE; +#endif + + if ((prGlueInfo->ulFlag & GLUE_FLAG_HALT) || (!prAdapter->fgIsP2PRegistered)) + return; + + prNetDev = prGlueInfo->prDevHandler; + prP2pBssInfo = &prGlueInfo->prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; + prPerMonitor = &prAdapter->rPerMonitor; + DBGLOG(SW4, TRACE, "enter kalPerMonHandler\n"); + +#ifdef ENHANCE_AP_MODE_THROUGHPUT + /* Distinguish AP mode from STA mode requirement */ + fgIsPureAp = prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->fgIsApMode; +#endif + + latestTxBytes = prGlueInfo->rNetDevStats.tx_bytes; + latestRxBytes = prGlueInfo->rNetDevStats.rx_bytes; + p2pLatestTxBytes = prGlueInfo->prP2PInfo->rNetDevStats.tx_bytes; + p2pLatestRxBytes = prGlueInfo->prP2PInfo->rNetDevStats.rx_bytes; + if (prPerMonitor->ulLastRxBytes == 0 && + prPerMonitor->ulLastTxBytes == 0 && + prPerMonitor->ulP2PLastRxBytes == 0 && + prPerMonitor->ulP2PLastTxBytes == 0) { + prPerMonitor->ulThroughput = 0; + } else { + txDiffBytes = latestTxBytes - prPerMonitor->ulLastTxBytes; + rxDiffBytes = latestRxBytes - prPerMonitor->ulLastRxBytes; + if (txDiffBytes < 0) + txDiffBytes = -(txDiffBytes); + if (rxDiffBytes < 0) + rxDiffBytes = -(rxDiffBytes); + p2pTxDiffBytes = p2pLatestTxBytes - prPerMonitor->ulP2PLastTxBytes; + p2pRxDiffBytes = p2pLatestRxBytes - prPerMonitor->ulP2PLastRxBytes; + if (p2pTxDiffBytes < 0) + p2pTxDiffBytes = -(p2pTxDiffBytes); + if (p2pRxDiffBytes < 0) + p2pRxDiffBytes = -(p2pRxDiffBytes); + + prPerMonitor->ulThroughput = txDiffBytes + rxDiffBytes + p2pTxDiffBytes + p2pRxDiffBytes; + prPerMonitor->ulThroughput *= (prPerMonitor->u4UpdatePeriod/1000); + prPerMonitor->ulThroughput <<= 3; + + /* AIS: [Bytes TX][Bytes RX] [Packet TX][Packet RX], P2P: [Bytes TX][Bytes RX] [Packet TX][Packet RX] */ + DBGLOG(SW4, INFO, + "kalPerMonHandler > Tput: %ld > AIS:[%ld][%ld] [%ld][%ld], P2P:[%ld][%ld] [%ld][%ld]\n", + prPerMonitor->ulThroughput, + txDiffBytes, rxDiffBytes, + prGlueInfo->rNetDevStats.tx_packets, prGlueInfo->rNetDevStats.rx_packets, + p2pTxDiffBytes, p2pRxDiffBytes, + prGlueInfo->prP2PInfo->rNetDevStats.tx_packets, prGlueInfo->prP2PInfo->rNetDevStats.rx_packets); + } + prPerMonitor->ulLastTxBytes = latestTxBytes; + prPerMonitor->ulLastRxBytes = latestRxBytes; + prPerMonitor->ulP2PLastTxBytes = p2pLatestTxBytes; + prPerMonitor->ulP2PLastRxBytes = p2pLatestRxBytes; + +#ifdef ENHANCE_AP_MODE_THROUGHPUT + if (fgIsPureAp) { + if (prPerMonitor->ulThroughput < THROUGHPUT_AP_L1_THRESHOLD) + prPerMonitor->u4TarPerfLevel = 0; +#if 0 + else if (prPerMonitor->ulThroughput < THROUGHPUT_AP_L2_THRESHOLD) + prPerMonitor->u4TarPerfLevel = 1; + else if (prPerMonitor->ulThroughput < THROUGHPUT_AP_L3_THRESHOLD) + prPerMonitor->u4TarPerfLevel = 2; + else if (prPerMonitor->ulThroughput < THROUGHPUT_AP_L4_THRESHOLD) + prPerMonitor->u4TarPerfLevel = 3; +#endif + else + prPerMonitor->u4TarPerfLevel = 4; + } else +#endif + { + if (prPerMonitor->ulThroughput < THROUGHPUT_L1_THRESHOLD) { + if (prPerMonitor->u4CurrPerfLevel != 0 && + prPerMonitor->u1ShutdownCoreCount < THROUGHPUT_SHUTDOWN_CORE_COUNT) { + prPerMonitor->u1ShutdownCoreCount++; + DBGLOG(SW4, INFO, "kalPerMonHandler > u1ShutdownCoreCount: %d\n", + prPerMonitor->u1ShutdownCoreCount); + needBoostCpu = FALSE; + } + prPerMonitor->u4TarPerfLevel = 0; + } else if (prPerMonitor->ulThroughput < THROUGHPUT_L2_THRESHOLD) + prPerMonitor->u4TarPerfLevel = 1; + else if (prPerMonitor->ulThroughput < THROUGHPUT_L3_THRESHOLD) + prPerMonitor->u4TarPerfLevel = 2; + else if (prPerMonitor->ulThroughput < THROUGHPUT_L4_THRESHOLD) + prPerMonitor->u4TarPerfLevel = 3; + else + prPerMonitor->u4TarPerfLevel = 4; + + if (prPerMonitor->u4TarPerfLevel != 0) + prPerMonitor->u1ShutdownCoreCount = 0; + } + +#ifdef ENHANCE_AP_MODE_THROUGHPUT + if (((fgIsUnderSuspend || wlan_fb_power_down) && !fgIsPureAp) || + !(netif_carrier_ok(prNetDev) || + (prP2pBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) || + (prP2pBssInfo->rStaRecOfClientList.u4NumElem > 0))) +#else + if (fgIsUnderSuspend || wlan_fb_power_down || + !(netif_carrier_ok(prNetDev) || + (prP2pBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) || + (prP2pBssInfo->rStaRecOfClientList.u4NumElem > 0))) +#endif + kalPerMonStop(prGlueInfo); + else { + DBGLOG(SW4, TRACE, "throughput:%ld bps\n", prPerMonitor->ulThroughput); + if (needBoostCpu && (prPerMonitor->u4TarPerfLevel != prPerMonitor->u4CurrPerfLevel)) { + /* if tar level = 0; core_number=prPerMonitor->u4TarPerfLevel+1*/ + if (prPerMonitor->u4TarPerfLevel) + kalBoostCpu(prGlueInfo, prPerMonitor->u4TarPerfLevel); + else + kalBoostCpu(prGlueInfo, 0); + + prPerMonitor->u4CurrPerfLevel = prPerMonitor->u4TarPerfLevel; + } + cnmTimerStartTimer(prGlueInfo->prAdapter, &prPerMonitor->rPerfMonTimer, prPerMonitor->u4UpdatePeriod); + } + + DBGLOG(SW4, TRACE, "exit kalPerMonHandler\n"); +} + +INT32 __weak kalBoostCpu(P_GLUE_INFO_T prGlueInfo, UINT_32 core_num) +{ + DBGLOG(SW4, WARN, "enter weak kalBoostCpu, core_num:%d\n", core_num); + return 0; +} + +INT32 __weak kalSetCpuNumFreq(UINT_32 core_num, UINT_32 freq) +{ + DBGLOG(SW4, WARN, "enter weak kalSetCpuNumFreq, core_num:%d\n", core_num); + return 0; +} + +static int wlan_fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data) +{ + struct fb_event *evdata = data; + INT_32 blank; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)wlan_fb_notifier_priv_data; + +#ifdef ENHANCE_AP_MODE_THROUGHPUT + BOOLEAN fgIsPureAp = FALSE; +#endif + + /* If we aren't interested in this event, skip it immediately ... */ + if (event != FB_EVENT_BLANK) + return 0; + + if (prGlueInfo == NULL || prGlueInfo->prAdapter == NULL) + return 0; + + if (kalHaltTryLock()) + return 0; + + blank = *(INT_32 *)evdata->data; + + switch (blank) { + case FB_BLANK_UNBLANK: + if (!kalIsHalted()) + kalPerMonEnable(prGlueInfo); + wlan_fb_power_down = FALSE; + break; + case FB_BLANK_POWERDOWN: + wlan_fb_power_down = TRUE; + if (!kalIsHalted()) { +#ifdef ENHANCE_AP_MODE_THROUGHPUT + /* Distinguish AP mode from STA mode requirement */ + if (prGlueInfo && prGlueInfo->prAdapter && prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo) + fgIsPureAp = prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->fgIsApMode; + if (!fgIsPureAp) + kalPerMonDisable(prGlueInfo); +#else + kalPerMonDisable(prGlueInfo); +#endif + } + break; + default: + break; + } + + kalHaltUnlock(); + return 0; +} + +INT_32 kalFbNotifierReg(IN P_GLUE_INFO_T prGlueInfo) +{ + INT_32 i4Ret; + + wlan_fb_notifier_priv_data = prGlueInfo; + wlan_fb_notifier.notifier_call = wlan_fb_notifier_callback; + i4Ret = fb_register_client(&wlan_fb_notifier); + if (i4Ret) + DBGLOG(SW4, WARN, "Register wlan_fb_notifier failed:%d\n", i4Ret); + else + DBGLOG(SW4, TRACE, "Register wlan_fb_notifier succeed\n"); + + return i4Ret; +} + +VOID kalFbNotifierUnReg(VOID) +{ + fb_unregister_client(&wlan_fb_notifier); + wlan_fb_notifier_priv_data = NULL; +} +/* +** change scheduler parameters, like schedule policy(RT thread or normal thread) and priority +** fgNormalThread: true means normal thread, false means RT thread +*/ +VOID kalChangeSchedParams(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgNormalThread) +{ + struct sched_param param = {.sched_priority = 0}; + + /* For RT thread */ + if (!fgNormalThread && prGlueInfo->i4Priority != 0) { + param.sched_priority = prGlueInfo->i4Priority; + DBGLOG(INIT, INFO, "RT priority %d\n", param.sched_priority); + if (prGlueInfo->main_thread && prGlueInfo->main_thread->policy != SCHED_FIFO) + sched_setscheduler(prGlueInfo->main_thread, SCHED_FIFO, ¶m); +#if CFG_SUPPORT_MULTITHREAD + if (prGlueInfo->rx_thread && prGlueInfo->rx_thread->policy != SCHED_FIFO) + sched_setscheduler(prGlueInfo->rx_thread, SCHED_FIFO, ¶m); +#endif + return; + } + /* For normal thread */ + if (prGlueInfo->main_thread && prGlueInfo->main_thread->policy != SCHED_NORMAL) { + sched_setscheduler(prGlueInfo->main_thread, SCHED_NORMAL, ¶m); + /* set main_thread to highest normal priority */ + set_user_nice(prGlueInfo->main_thread, PRIO_TO_NICE(DEFAULT_PRIO - 19)); + } +#if CFG_SUPPORT_MULTITHREAD + if (prGlueInfo->rx_thread && prGlueInfo->rx_thread->policy != SCHED_NORMAL) { + sched_setscheduler(prGlueInfo->rx_thread, SCHED_NORMAL, ¶m); + /* set rx_thread to highest normal priority */ + set_user_nice(prGlueInfo->rx_thread, PRIO_TO_NICE(DEFAULT_PRIO - 19)); + } +#endif +} + +#if CFG_SUPPORT_WPA3 +int kalExternalAuthRequest(IN P_ADAPTER_T prAdapter) +{ + struct cfg80211_external_auth_params params; + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_DESC_T prBssDesc; + struct net_device *ndev = NULL; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + if (!prAisFsmInfo) { + DBGLOG(SAA, WARN, + "SAE auth failed with NULL prAisFsmInfo\n"); + return WLAN_STATUS_INVALID_DATA; + } + + prBssDesc = prAisFsmInfo->prTargetBssDesc; + if (!prBssDesc) { + DBGLOG(SAA, WARN, + "SAE auth failed without prTargetBssDesc\n"); + return WLAN_STATUS_INVALID_DATA; + } + + ndev = prAdapter->prGlueInfo->prDevHandler; + params.action = NL80211_EXTERNAL_AUTH_START; + COPY_MAC_ADDR(params.bssid, prBssDesc->aucBSSID); + COPY_SSID(params.ssid.ssid, params.ssid.ssid_len, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + params.key_mgmt_suite = RSN_CIPHER_SUITE_SAE; + DBGLOG(AIS, INFO, "[WPA3] "MACSTR" %s %d %d %02x-%02x-%02x-%02x", + params.bssid, params.ssid.ssid, + params.ssid.ssid_len, params.action, + (uint8_t) (params.key_mgmt_suite & 0x000000FF), + (uint8_t) ((params.key_mgmt_suite >> 8) & 0x000000FF), + (uint8_t) ((params.key_mgmt_suite >> 16) & 0x000000FF), + (uint8_t) ((params.key_mgmt_suite >> 24) & 0x000000FF)); + return cfg80211_external_auth_request(ndev, ¶ms, GFP_KERNEL); +} +#endif + +int kalMaskMemCmp(const void *cs, const void *ct, + const void *mask, size_t count) +{ + const uint8_t *su1, *su2, *su3; + int res = 0; + + for (su1 = cs, su2 = ct, su3 = mask; + count > 0; ++su1, ++su2, ++su3, count--) { + if (mask != NULL) + res = ((*su1)&(*su3)) - ((*su2)&(*su3)); + else + res = (*su1) - (*su2); + if (res != 0) + break; + } + return res; +} + +const uint8_t *kalFindIeMatchMask(uint8_t eid, + const uint8_t *ies, int len, + const uint8_t *match, + int match_len, int match_offset, + const uint8_t *match_mask) +{ + /* match_offset can't be smaller than 2, unless match_len is + * zero, in which case match_offset must be zero as well. + */ + if (WARN_ON((match_len && match_offset < 2) || + (!match_len && match_offset))) + return NULL; + while (len >= 2 && len >= ies[1] + 2) { + if ((ies[0] == eid) && + (ies[1] + 2 >= match_offset + match_len) && + !kalMaskMemCmp(ies + match_offset, + match, match_mask, match_len)) + return ies; + len -= ies[1] + 2; + ies += ies[1] + 2; + } + return NULL; +} + +u_int8_t kalIsValidMacAddr(IN const uint8_t *addr) +{ + return (addr != NULL) && is_valid_ether_addr(addr); +} + +#if (KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE) +void kalParseRandomMac( + P_BSS_INFO_T prBssInfo, IN uint8_t *pucMacAddr, + IN uint8_t *pucMacAddrMask, OUT uint8_t *pucRandomMac) +{ + uint8_t ucMacAddr[MAC_ADDR_LEN]; + uint8_t ucMacAddrMask[MAC_ADDR_LEN]; + + if (!prBssInfo) { + DBGLOG(SCN, ERROR, "Invalid BssInfo\n"); + return; + } + + ASSERT(pucMacAddr); + ASSERT(pucRandomMac); + + if (pucMacAddr) + COPY_MAC_ADDR(ucMacAddr, pucMacAddr); + else + eth_zero_addr(ucMacAddr); + + /* Set all 6bytes MAC to be random*/ + get_random_mask_addr(pucRandomMac, ucMacAddr, pucMacAddrMask); + + + DBGLOG(SCN, INFO, "random mac=" MACSTR " mac_addr=" MACSTR + ", mac_addr_mask=%pM\n", MAC2STR(pucRandomMac), + MAC2STR(ucMacAddr), ucMacAddrMask); +} + +void kalScanParseRandomMac( + P_BSS_INFO_T prBssInfo, + const struct cfg80211_scan_request *request, + uint8_t *pucRandomMac) +{ + uint8_t ucMacAddr[MAC_ADDR_LEN]; + uint8_t ucMacAddrMask[MAC_ADDR_LEN]; + + ASSERT(request); + ASSERT(pucRandomMac); + + if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) { + DBGLOG(SCN, TRACE, "Scan random mac is not set\n"); + return; + } + +#if KERNEL_VERSION(4, 10, 0) <= CFG80211_VERSION_CODE + { + if (kalIsValidMacAddr(request->bssid)) { + COPY_MAC_ADDR(pucRandomMac, request->bssid); + DBGLOG(SCN, INFO, "random mac=" MACSTR "\n", + pucRandomMac); + return; + } + } +#endif + COPY_MAC_ADDR(ucMacAddr, request->mac_addr); + COPY_MAC_ADDR(ucMacAddrMask, request->mac_addr_mask); + + kalParseRandomMac(prBssInfo, ucMacAddr, ucMacAddrMask, pucRandomMac); +} + +BOOLEAN kalSchedScanParseRandomMac( + P_BSS_INFO_T prBssInfo, + const struct cfg80211_sched_scan_request *request, + uint8_t *pucRandomMac, uint8_t *pucRandomMacMask) +{ + uint8_t ucMacAddr[MAC_ADDR_LEN]; + + ASSERT(request); + ASSERT(pucRandomMac); + + if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) { + DBGLOG(SCN, TRACE, "Scan random mac is not set\n"); + return FALSE; + } + COPY_MAC_ADDR(ucMacAddr, request->mac_addr); + COPY_MAC_ADDR(pucRandomMacMask, request->mac_addr_mask); + + kalParseRandomMac(prBssInfo, ucMacAddr, pucRandomMacMask, + pucRandomMac); + return TRUE; +} + +#else /* if (KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE) */ +void kalScanParseRandomMac(P_BSS_INFO_T prBssInfo, + const struct cfg80211_scan_request *request, uint8_t *pucRandomMac) +{ + /* Do nothing */ +} + +BOOLEAN kalSchedScanParseRandomMac(const struct net_device *ndev, + const struct cfg80211_sched_scan_request *request, + uint8_t *pucRandomMac, uint8_t *pucRandomMacMask) +{ + return FALSE; +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_p2p.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_p2p.c new file mode 100644 index 0000000000000..c7e5f1502ddc3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_p2p.c @@ -0,0 +1,4343 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include + +#include "gl_os.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "gl_p2p_os.h" +#include "gl_p2p_ioctl.h" +#include "gl_vendor.h" + +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define ARGV_MAX_NUM (4) + +/*For CFG80211 - wiphy parameters*/ +#define MAX_SCAN_LIST_NUM (1) +#define MAX_SCAN_IE_LEN (512) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +static struct cfg80211_ops mtk_p2p_ops = { + .change_virtual_intf = mtk_p2p_cfg80211_change_iface, /* 1st */ + .change_bss = mtk_p2p_cfg80211_change_bss, + .scan = mtk_p2p_cfg80211_scan, + .abort_scan = mtk_p2p_cfg80211_abort_scan, + .remain_on_channel = mtk_p2p_cfg80211_remain_on_channel, + .cancel_remain_on_channel = mtk_p2p_cfg80211_cancel_remain_on_channel, + .mgmt_tx = mtk_p2p_cfg80211_mgmt_tx, + .connect = mtk_p2p_cfg80211_connect, + .disconnect = mtk_p2p_cfg80211_disconnect, + .deauth = mtk_p2p_cfg80211_deauth, + .disassoc = mtk_p2p_cfg80211_disassoc, + .start_ap = mtk_p2p_cfg80211_start_ap, + .change_beacon = mtk_p2p_cfg80211_change_beacon, + .stop_ap = mtk_p2p_cfg80211_stop_ap, + .set_wiphy_params = mtk_p2p_cfg80211_set_wiphy_params, +#if (CFG_SUPPORT_TDLS == 1) + .change_station = mtk_cfg80211_change_station, + .add_station = mtk_cfg80211_add_station, +#endif + .del_station = mtk_p2p_cfg80211_del_station, + .set_monitor_channel = mtk_p2p_cfg80211_set_channel, + .set_bitrate_mask = mtk_p2p_cfg80211_set_bitrate_mask, + .mgmt_frame_register = mtk_p2p_cfg80211_mgmt_frame_register, + .get_station = mtk_p2p_cfg80211_get_station, + .add_key = mtk_p2p_cfg80211_add_key, + .get_key = mtk_p2p_cfg80211_get_key, + .del_key = mtk_p2p_cfg80211_del_key, + .set_default_key = mtk_p2p_cfg80211_set_default_key, + .set_default_mgmt_key = mtk_p2p_cfg80211_set_mgmt_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 +#if (CFG_SUPPORT_TDLS == 1) + .tdls_mgmt = TdlsexCfg80211TdlsMgmt, + .tdls_oper = TdlsexCfg80211TdlsOper, +#endif /* CFG_SUPPORT_TDLS */ + +}; + +static const struct wiphy_vendor_command mtk_p2p_vendor_ops[] = { + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_GET_CHANNEL_LIST + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_channel_list + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_SET_COUNTRY_CODE + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_country_code + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_GET_ROAMING_CAPABILITIES + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_roaming_capabilities + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_CONFIG_ROAMING + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_config_roaming + }, +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + { + { + .vendor_id = OUI_QCA, + .subcmd = NL80211_VENDOR_SUBCMD_ACS + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV + | WIPHY_VENDOR_CMD_NEED_NETDEV + | WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = mtk_cfg80211_vendor_acs + }, +#endif + { + { + .vendor_id = OUI_QCA, + .subcmd = NL80211_VENDOR_SUBCMD_GET_FEATURES + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV + | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_features + }, +}; + +static const struct nl80211_vendor_cmd_info mtk_p2p_vendor_events[] = { + { + .vendor_id = OUI_QCA, + .subcmd = NL80211_VENDOR_SUBCMD_ACS + }, +}; + +/* 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) +#if CFG_SUPPORT_SOFTAP_WPA3 + | BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) +#endif + }, + [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) + } +}; + +static const struct ieee80211_iface_limit mtk_p2p_iface_limits[] = { + { + .max = 1, + .types = BIT(NL80211_IFTYPE_STATION) + }, + { + .max = 1, + .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | + BIT(NL80211_IFTYPE_P2P_GO) + }, +}; + +static const struct ieee80211_iface_combination mtk_sta_iface_combos[] = { + { + .max_interfaces = 2, + .num_different_channels = 2, + .n_limits = ARRAY_SIZE(mtk_p2p_iface_limits), + .limits = mtk_p2p_iface_limits + } +}; +const struct ieee80211_iface_combination *p_mtk_sta_iface_combos = mtk_sta_iface_combos; +const INT_32 mtk_sta_iface_combos_num = ARRAY_SIZE(mtk_sta_iface_combos); + +static const struct ieee80211_iface_combination mtk_p2p_iface_combos[] = { + { + .max_interfaces = 2, + .num_different_channels = 2, + .n_limits = ARRAY_SIZE(mtk_p2p_iface_limits), + .limits = mtk_p2p_iface_limits + } +}; +#endif + +/* the legacy wireless extension stuff */ +static const iw_handler rP2PIwStandardHandler[] = { + [SIOCGIWPRIV - SIOCIWFIRST] = mtk_p2p_wext_get_priv, + [SIOCGIWSCAN - SIOCIWFIRST] = mtk_p2p_wext_discovery_results, + [SIOCSIWESSID - SIOCIWFIRST] = mtk_p2p_wext_reconnect, + [SIOCSIWAUTH - SIOCIWFIRST] = mtk_p2p_wext_set_auth, + [SIOCSIWENCODEEXT - SIOCIWFIRST] = mtk_p2p_wext_set_key, + [SIOCSIWPOWER - SIOCIWFIRST] = mtk_p2p_wext_set_powermode, + [SIOCGIWPOWER - SIOCIWFIRST] = mtk_p2p_wext_get_powermode, + [SIOCSIWTXPOW - SIOCIWFIRST] = mtk_p2p_wext_set_txpow, +#if CFG_SUPPORT_P2P_RSSI_QUERY + [SIOCGIWSTATS - SIOCIWFIRST] = mtk_p2p_wext_get_rssi, +#endif + [SIOCSIWMLME - SIOCIWFIRST] = mtk_p2p_wext_mlme_handler, +}; + +static const iw_handler rP2PIwPrivHandler[] = { + [IOC_P2P_CFG_DEVICE - SIOCIWFIRSTPRIV] = mtk_p2p_wext_set_local_dev_info, + [IOC_P2P_PROVISION_COMPLETE - SIOCIWFIRSTPRIV] = mtk_p2p_wext_set_provision_complete, + [IOC_P2P_START_STOP_DISCOVERY - SIOCIWFIRSTPRIV] = mtk_p2p_wext_start_stop_discovery, + [IOC_P2P_DISCOVERY_RESULTS - SIOCIWFIRSTPRIV] = mtk_p2p_wext_discovery_results, + [IOC_P2P_WSC_BEACON_PROBE_RSP_IE - SIOCIWFIRSTPRIV] = mtk_p2p_wext_wsc_ie, + [IOC_P2P_CONNECT_DISCONNECT - SIOCIWFIRSTPRIV] = mtk_p2p_wext_connect_disconnect, + [IOC_P2P_PASSWORD_READY - SIOCIWFIRSTPRIV] = mtk_p2p_wext_password_ready, +/* [IOC_P2P_SET_PWR_MGMT_PARAM - SIOCIWFIRSTPRIV] = mtk_p2p_wext_set_pm_param, */ + [IOC_P2P_SET_INT - SIOCIWFIRSTPRIV] = mtk_p2p_wext_set_int, + [IOC_P2P_GET_STRUCT - SIOCIWFIRSTPRIV] = mtk_p2p_wext_get_struct, + [IOC_P2P_SET_STRUCT - SIOCIWFIRSTPRIV] = mtk_p2p_wext_set_struct, + [IOC_P2P_GET_REQ_DEVICE_INFO - SIOCIWFIRSTPRIV] = mtk_p2p_wext_request_dev_info, +}; + +static const struct iw_priv_args rP2PIwPrivTable[] = { + { + .cmd = IOC_P2P_CFG_DEVICE, + .set_args = IW_PRIV_TYPE_BYTE | (__u16) sizeof(IW_P2P_CFG_DEVICE_TYPE), + .get_args = IW_PRIV_TYPE_NONE, + .name = "P2P_CFG_DEVICE"} + , + { + .cmd = IOC_P2P_START_STOP_DISCOVERY, + .set_args = IW_PRIV_TYPE_BYTE | (__u16) sizeof(IW_P2P_REQ_DEVICE_TYPE), + .get_args = IW_PRIV_TYPE_NONE, + .name = "P2P_DISCOVERY"} + , + { + .cmd = IOC_P2P_DISCOVERY_RESULTS, + .set_args = IW_PRIV_TYPE_NONE, + .get_args = IW_PRIV_TYPE_NONE, + .name = "P2P_RESULT"} + , + { + .cmd = IOC_P2P_WSC_BEACON_PROBE_RSP_IE, + .set_args = IW_PRIV_TYPE_BYTE | (__u16) sizeof(IW_P2P_HOSTAPD_PARAM), + .get_args = IW_PRIV_TYPE_NONE, + .name = "P2P_WSC_IE"} + , + { + .cmd = IOC_P2P_CONNECT_DISCONNECT, + .set_args = IW_PRIV_TYPE_BYTE | (__u16) sizeof(IW_P2P_CONNECT_DEVICE), + .get_args = IW_PRIV_TYPE_NONE, + .name = "P2P_CONNECT"} + , + { + .cmd = IOC_P2P_PASSWORD_READY, + .set_args = IW_PRIV_TYPE_BYTE | (__u16) sizeof(IW_P2P_PASSWORD_READY), + .get_args = IW_PRIV_TYPE_NONE, + .name = "P2P_PASSWD_RDY"} + , + { + .cmd = IOC_P2P_GET_STRUCT, + .set_args = IW_PRIV_TYPE_NONE, + .get_args = 256, + .name = "P2P_GET_STRUCT"} + , + { + .cmd = IOC_P2P_SET_STRUCT, + .set_args = 256, + .get_args = IW_PRIV_TYPE_NONE, + .name = "P2P_SET_STRUCT"} + , + { + .cmd = IOC_P2P_GET_REQ_DEVICE_INFO, + .set_args = IW_PRIV_TYPE_NONE, + .get_args = IW_PRIV_TYPE_BYTE | (__u16) sizeof(IW_P2P_DEVICE_REQ), + .name = "P2P_GET_REQDEV"} + , + { + /* SET STRUCT sub-ioctls commands */ + .cmd = PRIV_CMD_OID, + .set_args = 256, + .get_args = IW_PRIV_TYPE_NONE, + .name = "set_oid"} + , + { + /* GET STRUCT sub-ioctls commands */ + .cmd = PRIV_CMD_OID, + .set_args = IW_PRIV_TYPE_NONE, + .get_args = 256, + .name = "get_oid"} +}; + +const struct iw_handler_def mtk_p2p_wext_handler_def = { + .num_standard = (__u16) sizeof(rP2PIwStandardHandler) / sizeof(iw_handler), + .num_private = (__u16) sizeof(rP2PIwPrivHandler) / sizeof(iw_handler), + .num_private_args = (__u16) sizeof(rP2PIwPrivTable) / sizeof(struct iw_priv_args), + .standard = rP2PIwStandardHandler, + .private = rP2PIwPrivHandler, + .private_args = rP2PIwPrivTable, +#if CFG_SUPPORT_P2P_RSSI_QUERY + .get_wireless_stats = mtk_p2p_wext_get_wireless_stats, +#else + .get_wireless_stats = NULL, +#endif +}; + +#ifdef CONFIG_PM +static const struct wiphy_wowlan_support p2p_wowlan_support = { + .flags = WIPHY_WOWLAN_DISCONNECT | WIPHY_WOWLAN_ANY, +}; +#endif + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/* for IE Searching */ +extern BOOLEAN +wextSrchDesiredWPAIE(IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT PPUINT_8 ppucDesiredIE); + +#if CFG_SUPPORT_WPS +extern BOOLEAN +wextSrchDesiredWPSIE(IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT PPUINT_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 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 }; + +#if KERNEL_VERSION(4, 19, 0) <= CFG80211_VERSION_CODE +static UINT_16 p2pSelectQueue(struct net_device *dev, struct sk_buff *skb, + struct net_device *sb_dev, select_queue_fallback_t fallback) +#else +static UINT_16 p2pSelectQueue(struct net_device *dev, struct sk_buff *skb, + void *accel_priv, select_queue_fallback_t fallback) +#endif +{ + skb->priority = _p2p_cfg80211_classify8021d(skb); + + return au16Wlan1dToQueueIdx[skb->priority]; +} + +struct net_device *g_P2pPrDev; +static struct wireless_dev *gprP2pWdev; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A function for prDev->init +* +* \param[in] prDev Pointer to struct net_device. +* +* \retval 0 The execution of wlanInit succeeds. +* \retval -ENXIO No such device. +*/ +/*----------------------------------------------------------------------------*/ +static int p2pInit(struct net_device *prDev) +{ +/* P_GLUE_INFO_T prGlueInfo; */ + if (!prDev) + return -ENXIO; + + DBGLOG(P2P, INFO, "dev name=%s\n", prDev->name); + return 0; /* success */ +} /* end of p2pInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A function for prDev->uninit +* +* \param[in] prDev Pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static void p2pUninit(IN struct net_device *prDev) +{ + +} /* end of p2pUninit() */ + +static const struct net_device_ops p2p_netdev_ops = { + .ndo_open = p2pOpen, + .ndo_stop = p2pStop, + .ndo_set_mac_address = p2pSetMACAddress, + .ndo_set_rx_mode = p2pSetMulticastList, + .ndo_get_stats = p2pGetStats, + .ndo_do_ioctl = p2pDoIOCTL, + .ndo_start_xmit = p2pHardStartXmit, + .ndo_select_queue = p2pSelectQueue, + .ndo_init = p2pInit, + .ndo_uninit = p2pUninit, +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Allocate memory for P2P_INFO, GL_P2P_INFO, P2P_CONNECTION_SETTINGS +* P2P_SPECIFIC_BSS_INFO, P2P_FSM_INFO +* +* \param[in] prGlueInfo Pointer to glue info +* +* \return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2PAllocInfo(IN P_GLUE_INFO_T prGlueInfo) +{ + P_ADAPTER_T prAdapter = NULL; + P_WIFI_VAR_T prWifiVar = NULL; + + if ((!prGlueInfo) || (!prGlueInfo->prAdapter)) { + ASSERT(FALSE); + return FALSE; + } + + prAdapter = prGlueInfo->prAdapter; + prWifiVar = &(prAdapter->rWifiVar); + + if (!prWifiVar) { + ASSERT(FALSE); + return FALSE; + } + + do { + if (prGlueInfo->prP2PInfo == NULL) { + /*alloc memory for p2p info */ + prGlueInfo->prP2PInfo = kalMemAlloc(sizeof(GL_P2P_INFO_T), VIR_MEM_TYPE); + prAdapter->prP2pInfo = kalMemAlloc(sizeof(P2P_INFO_T), VIR_MEM_TYPE); + prWifiVar->prP2PConnSettings = kalMemAlloc(sizeof(P2P_CONNECTION_SETTINGS_T), VIR_MEM_TYPE); + prWifiVar->prP2pFsmInfo = kalMemAlloc(sizeof(P2P_FSM_INFO_T), VIR_MEM_TYPE); + prWifiVar->prP2pSpecificBssInfo = kalMemAlloc(sizeof(P2P_SPECIFIC_BSS_INFO_T), VIR_MEM_TYPE); + } else { + ASSERT(prAdapter->prP2pInfo != NULL); + ASSERT(prWifiVar->prP2PConnSettings != NULL); + ASSERT(prWifiVar->prP2pFsmInfo != NULL); + ASSERT(prWifiVar->prP2pSpecificBssInfo != NULL); + } + /*MUST set memory to 0 */ + if (prGlueInfo->prP2PInfo) + kalMemZero(prGlueInfo->prP2PInfo, sizeof(GL_P2P_INFO_T)); + if (prAdapter->prP2pInfo) + kalMemZero(prAdapter->prP2pInfo, sizeof(P2P_INFO_T)); + if (prWifiVar->prP2PConnSettings) + kalMemZero(prWifiVar->prP2PConnSettings, sizeof(P2P_CONNECTION_SETTINGS_T)); + if (prWifiVar->prP2pFsmInfo) + kalMemZero(prWifiVar->prP2pFsmInfo, sizeof(P2P_FSM_INFO_T)); + if (prWifiVar->prP2pSpecificBssInfo) + kalMemZero(prWifiVar->prP2pSpecificBssInfo, sizeof(P2P_SPECIFIC_BSS_INFO_T)); + + } while (FALSE); + + /* chk if alloc successful or not */ + if (prGlueInfo->prP2PInfo && + prAdapter->prP2pInfo && + prWifiVar->prP2PConnSettings && prWifiVar->prP2pFsmInfo && prWifiVar->prP2pSpecificBssInfo) { + return TRUE; + } + + if (prWifiVar->prP2pSpecificBssInfo) { + kalMemFree(prWifiVar->prP2pSpecificBssInfo, VIR_MEM_TYPE, sizeof(P2P_SPECIFIC_BSS_INFO_T)); + + prWifiVar->prP2pSpecificBssInfo = NULL; + } + if (prWifiVar->prP2pFsmInfo) { + kalMemFree(prWifiVar->prP2pFsmInfo, VIR_MEM_TYPE, sizeof(P2P_FSM_INFO_T)); + + prWifiVar->prP2pFsmInfo = NULL; + } + if (prWifiVar->prP2PConnSettings) { + kalMemFree(prWifiVar->prP2PConnSettings, VIR_MEM_TYPE, sizeof(P2P_CONNECTION_SETTINGS_T)); + + prWifiVar->prP2PConnSettings = NULL; + } + if (prGlueInfo->prP2PInfo) { + kalMemFree(prGlueInfo->prP2PInfo, VIR_MEM_TYPE, sizeof(GL_P2P_INFO_T)); + + prGlueInfo->prP2PInfo = NULL; + } + if (prAdapter->prP2pInfo) { + kalMemFree(prAdapter->prP2pInfo, VIR_MEM_TYPE, sizeof(P2P_INFO_T)); + + prAdapter->prP2pInfo = NULL; + } + return FALSE; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Free memory for P2P_INFO, GL_P2P_INFO, P2P_CONNECTION_SETTINGS +* P2P_SPECIFIC_BSS_INFO, P2P_FSM_INFO +* +* \param[in] prGlueInfo Pointer to glue info +* +* \return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2PFreeInfo(P_GLUE_INFO_T prGlueInfo) +{ + + if ((!prGlueInfo) || (!prGlueInfo->prAdapter)) { + ASSERT(FALSE); + return FALSE; + } + + /* free memory after p2p module is ALREADY unregistered */ + if (prGlueInfo->prAdapter->fgIsP2PRegistered == FALSE) { + + kalMemFree(prGlueInfo->prAdapter->prP2pInfo, VIR_MEM_TYPE, sizeof(P2P_INFO_T)); + kalMemFree(prGlueInfo->prP2PInfo, VIR_MEM_TYPE, sizeof(GL_P2P_INFO_T)); + kalMemFree(prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings, VIR_MEM_TYPE, + sizeof(P2P_CONNECTION_SETTINGS_T)); + kalMemFree(prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo, VIR_MEM_TYPE, sizeof(P2P_FSM_INFO_T)); + kalMemFree(prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo, VIR_MEM_TYPE, + sizeof(P2P_SPECIFIC_BSS_INFO_T)); + + /*Reomve p2p bss scan list */ + scanRemoveAllP2pBssDesc(prGlueInfo->prAdapter); + + /*reset all pointer to NULL */ + prGlueInfo->prP2PInfo = NULL; + prGlueInfo->prAdapter->prP2pInfo = NULL; + prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings = NULL; + prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo = NULL; + prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo = NULL; + + return TRUE; + } else { + return FALSE; + } + +} + +#if !CFG_SUPPORT_PERSIST_NETDEV +BOOLEAN p2pNetRegister(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgIsRtnlLockAcquired) +{ + BOOLEAN fgDoRegister = FALSE; +/* BOOLEAN fgRollbackRtnlLock = FALSE; */ + BOOLEAN ret; + + GLUE_SPIN_LOCK_DECLARATION(); + + if ((!prGlueInfo) || (!prGlueInfo->prAdapter)) { + ASSERT(FALSE); + return FALSE; + } + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if (prGlueInfo->prAdapter->rP2PNetRegState == ENUM_NET_REG_STATE_UNREGISTERED) { + prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_REGISTERING; + fgDoRegister = TRUE; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + if (!fgDoRegister) + return TRUE; + + /* net device initialize */ + netif_carrier_off(prGlueInfo->prP2PInfo->prDevHandler); + netif_tx_stop_all_queues(prGlueInfo->prP2PInfo->prDevHandler); + + /* register for net device */ + if (register_netdev(prGlueInfo->prP2PInfo->prDevHandler) < 0) { + DBGLOG(P2P, WARN, "unable to register netdevice for p2p\n"); + /* free dev in glUnregisterP2P() */ + /* free_netdev(prGlueInfo->prP2PInfo->prDevHandler); */ + + ret = FALSE; + } else { + prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_REGISTERED; + ret = TRUE; + } + return ret; +} + +BOOLEAN p2pNetUnregister(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgIsRtnlLockAcquired) +{ + BOOLEAN fgDoUnregister = FALSE; +/* BOOLEAN fgRollbackRtnlLock = FALSE; */ + GLUE_SPIN_LOCK_DECLARATION(); + + if ((!prGlueInfo) || (!prGlueInfo->prAdapter)) { + ASSERT(FALSE); + return FALSE; + } + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if (prGlueInfo->prAdapter->rP2PNetRegState == ENUM_NET_REG_STATE_REGISTERED) { + prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_UNREGISTERING; + fgDoUnregister = TRUE; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + if (!fgDoUnregister) + return TRUE; + + /* prepare for removal */ + if (netif_carrier_ok(prGlueInfo->prP2PInfo->prDevHandler)) + netif_carrier_off(prGlueInfo->prP2PInfo->prDevHandler); + + netif_tx_stop_all_queues(prGlueInfo->prP2PInfo->prDevHandler); + DBGLOG(P2P, INFO, "P2P unregister_netdev 0x%p\n", prGlueInfo->prP2PInfo->prDevHandler); + unregister_netdev(prGlueInfo->prP2PInfo->prDevHandler); + + prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_UNREGISTERED; + + return TRUE; +} +#endif + +BOOLEAN glP2pCreateWirelessDevice(P_GLUE_INFO_T prGlueInfo) +{ + struct wiphy *prWiphy = NULL; + struct wireless_dev *prWdev = NULL; +#if CFG_SUPPORT_PERSIST_NETDEV + struct net_device *prNetDev = NULL; +#endif +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + prWdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (!prWdev) { + DBGLOG(P2P, ERROR, "allocate p2p wireless device fail, no memory\n"); + return FALSE; + } + /* 1. allocate WIPHY */ + prWiphy = wiphy_new(&mtk_p2p_ops, sizeof(P_GLUE_INFO_T)); + if (!prWiphy) { + DBGLOG(P2P, ERROR, "unable to allocate wiphy for p2p\n"); + goto free_wdev; + } + + prWiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_P2P_CLIENT) | + BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_STATION); + + prWiphy->iface_combinations = mtk_p2p_iface_combos; + prWiphy->n_iface_combinations = ARRAY_SIZE(mtk_p2p_iface_combos); + + prWiphy->bands[IEEE80211_BAND_2GHZ] = &mtk_band_2ghz; + prWiphy->bands[IEEE80211_BAND_5GHZ] = &mtk_band_5ghz; + + prWiphy->mgmt_stypes = mtk_cfg80211_default_mgmt_stypes; +#if CFG_SUPPORT_SOFTAP_WPA3 + prWiphy->features |= NL80211_FEATURE_SAE; +#endif + prWiphy->max_remain_on_channel_duration = 500; + prWiphy->cipher_suites = mtk_cipher_suites; + prWiphy->n_cipher_suites = ARRAY_SIZE(mtk_cipher_suites); + prWiphy->flags = WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | WIPHY_FLAG_HAVE_AP_SME; +#if (CFG_SUPPORT_TDLS == 1) + TDLSEX_WIPHY_FLAGS_INIT(prWiphy->flags); +#endif /* CFG_SUPPORT_TDLS */ + prWiphy->regulatory_flags = REGULATORY_CUSTOM_REG; + prWiphy->ap_sme_capa = 1; + + prWiphy->max_scan_ssids = MAX_SCAN_LIST_NUM; + prWiphy->max_scan_ie_len = MAX_SCAN_IE_LEN; + prWiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + prWiphy->vendor_commands = mtk_p2p_vendor_ops; + prWiphy->n_vendor_commands = sizeof(mtk_p2p_vendor_ops) / sizeof(struct wiphy_vendor_command); + prWiphy->vendor_events = mtk_p2p_vendor_events; + prWiphy->n_vendor_events = ARRAY_SIZE(mtk_p2p_vendor_events); + +#ifdef CONFIG_PM + prWiphy->wowlan = &p2p_wowlan_support; +#endif + +#if KERNEL_VERSION(3, 14, 0) < LINUX_VERSION_CODE + prWiphy->max_ap_assoc_sta = P2P_MAXIMUM_CLIENT_COUNT; +#endif + + /* 2.1 set priv as pointer to glue structure */ + *((P_GLUE_INFO_T *) wiphy_priv(prWiphy)) = prGlueInfo; + if (wiphy_register(prWiphy) < 0) { + DBGLOG(P2P, ERROR, "fail to register wiphy for p2p\n"); + goto free_wiphy; + } + prWdev->wiphy = prWiphy; +#if CFG_SUPPORT_PERSIST_NETDEV + /* 3. allocate netdev */ + prNetDev = alloc_netdev_mq(sizeof(P_GLUE_INFO_T), P2P_INF_NAME, NET_NAME_PREDICTABLE, + ether_setup, CFG_MAX_TXQ_NUM); + if (!prNetDev) { + DBGLOG(P2P, ERROR, "unable to allocate netdevice for p2p\n"); + goto unregister_wiphy; + } + + /* 4. setup netdev */ + /* 4.1 Point to shared glue structure */ + *((P_GLUE_INFO_T *) netdev_priv(prNetDev)) = prGlueInfo; + + /* 4.2 fill hardware address */ + /* + * COPY_MAC_ADDR(rMacAddr, prAdapter->rMyMacAddr); + * rMacAddr[0] ^= 0x2; // change to local administrated address + * memcpy(prGlueInfo->prP2PInfo->prDevHandler->dev_addr, rMacAddr, ETH_ALEN); + * memcpy(prGlueInfo->prP2PInfo->prDevHandler->perm_addr, + * prGlueInfo->prP2PInfo->prDevHandler->dev_addr, ETH_ALEN); + */ + + /* 4.3 register callback functions */ + prNetDev->netdev_ops = &p2p_netdev_ops; + /* prGlueInfo->prP2PInfo->prDevHandler->wireless_handlers = &mtk_p2p_wext_handler_def;*/ + + prNetDev->ieee80211_ptr = prWdev; + prWdev->netdev = prNetDev; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + prNetDev->features = NETIF_F_IP_CSUM; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + /* net device initialize */ + netif_carrier_off(prNetDev); + netif_tx_stop_all_queues(prNetDev); + + /* 5. register for net device */ + if (register_netdev(prNetDev) < 0) { + DBGLOG(P2P, ERROR, "unable to register netdevice for p2p\n"); + free_netdev(prNetDev); + goto unregister_wiphy; + } +#endif + gprP2pWdev = prWdev; + return TRUE; + +#if CFG_SUPPORT_PERSIST_NETDEV +unregister_wiphy: + wiphy_unregister(prWiphy); +#endif +free_wiphy: + wiphy_free(prWiphy); +free_wdev: + kfree(prWdev); +#endif + return FALSE; +} + +void glP2pDestroyWirelessDevice(VOID) +{ +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#if CFG_SUPPORT_PERSIST_NETDEV + unregister_netdev(gprP2pWdev->netdev); + free_netdev(gprP2pWdev->netdev); +#endif + wiphy_unregister(gprP2pWdev->wiphy); + wiphy_free(gprP2pWdev->wiphy); + kfree(gprP2pWdev); + gprP2pWdev = NULL; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Register for cfg80211 for Wi-Fi Direct +* +* \param[in] prGlueInfo Pointer to glue info +* +* \return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN glRegisterP2P(P_GLUE_INFO_T prGlueInfo, const char *prDevName, BOOLEAN fgIsApMode) +{ + P_ADAPTER_T prAdapter = NULL; + P_GL_HIF_INFO_T prHif = NULL; + PARAM_MAC_ADDRESS rMacAddr; + struct net_device *prDevHandler = NULL; +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + struct device *prDev; +#endif + + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prHif = &prGlueInfo->rHifInfo; + ASSERT(prHif); + + DBGLOG(P2P, TRACE, "glRegisterP2P\n"); +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + if (!gprP2pWdev) { + DBGLOG(P2P, ERROR, "gl_p2p, wireless device is not exist\n"); + return FALSE; + } +#endif + /* 0. allocate p2pinfo */ + if (!p2PAllocInfo(prGlueInfo)) { + DBGLOG(P2P, ERROR, "Allocate memory for p2p FAILED\n"); + ASSERT(0); + return FALSE; + } +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + prGlueInfo->prP2PInfo->prWdev = gprP2pWdev; + /* 1. fill wiphy parameters */ +#if MTK_WCN_HIF_SDIO + mtk_wcn_hif_sdio_get_dev(prHif->cltCtx, &prDev); + if (!prDev) + DBGLOG(P2P, WARN, "unable to get struct dev for p2p\n"); +#else + prDev = prHif->Dev; +#endif + /*set_wiphy_dev(gprP2pWdev->wiphy, prDev);*/ + if (!prGlueInfo->prAdapter->fgEnable5GBand) + gprP2pWdev->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; + + /* 2. set priv as pointer to glue structure */ + *(P_GLUE_INFO_T *) wiphy_priv(gprP2pWdev->wiphy) = prGlueInfo; + + if (fgIsApMode) { + gprP2pWdev->iftype = NL80211_IFTYPE_AP; +#if CFG_SUPPORT_PERSIST_NETDEV + if (kalStrnCmp(gprP2pWdev->netdev->name, AP_INF_NAME, 2)) { + rtnl_lock(); + dev_change_name(gprP2pWdev->netdev->name, AP_INF_NAME); + rtnl_unlock(); + } +#endif + } else { + gprP2pWdev->iftype = NL80211_IFTYPE_P2P_CLIENT; +#if CFG_SUPPORT_PERSIST_NETDEV + if (kalStrnCmp(gprP2pWdev->netdev->name, P2P_INF_NAME, 3)) { + rtnl_lock(); + dev_change_name(gprP2pWdev->netdev->name, P2P_INF_NAME); + rtnl_unlock(); + } +#endif + } +#endif /* CFG_ENABLE_WIFI_DIRECT_CFG_80211 */ + +#if CFG_SUPPORT_PERSIST_NETDEV + prP2PInfo->prDevHandler = gprP2pWdev->netdev; +#else /* CFG_SUPPORT_PERSIST_NETDEV */ + /* 3. allocate netdev */ + prDevHandler = alloc_netdev_mq(sizeof(P_GLUE_INFO_T), prDevName, NET_NAME_PREDICTABLE, + ether_setup, CFG_MAX_TXQ_NUM); + if (!prDevHandler) { + DBGLOG(P2P, ERROR, "unable to allocate netdevice for p2p\n"); + return FALSE; + } + prGlueInfo->prP2PInfo->prDevHandler = prDevHandler; + /* 4. setup netdev */ + /* 4.1 Point to shared glue structure */ + *((P_GLUE_INFO_T *) netdev_priv(prDevHandler)) = prGlueInfo; + + /* 4.2 fill hardware address */ + COPY_MAC_ADDR(rMacAddr, prAdapter->rMyMacAddr); + rMacAddr[0] ^= 0x2; /* change to local administrated address */ + ether_addr_copy(prDevHandler->dev_addr, rMacAddr); + ether_addr_copy(prDevHandler->perm_addr, prDevHandler->dev_addr); + + /* 4.3 register callback functions */ + prDevHandler->netdev_ops = &p2p_netdev_ops; + /* prGlueInfo->prP2PInfo->prDevHandler->wireless_handlers = &mtk_p2p_wext_handler_def; */ + +#if (MTK_WCN_HIF_SDIO == 0) + SET_NETDEV_DEV(prDevHandler, prHif->Dev); +#endif + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + prDevHandler->ieee80211_ptr = gprP2pWdev; + gprP2pWdev->netdev = prDevHandler; +#endif + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + prDevHandler->features = NETIF_F_IP_CSUM; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ +#endif /* CFG_SUPPORT_PERSIST_NETDEV */ + + /* 5. set p2p net device register state */ + prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_UNREGISTERED; + + /* 6. setup running mode */ + prAdapter->rWifiVar.prP2pFsmInfo->fgIsApMode = fgIsApMode; + + /* 7. finish */ + p2pFsmInit(prAdapter); + + p2pFuncInitConnectionSettings(prAdapter, prAdapter->rWifiVar.prP2PConnSettings); + + /* Active network too early would cause HW not able to sleep. + * Defer the network active time. + */ +/* nicActivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); */ + + return TRUE; +} /* end of glRegisterP2P() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Unregister Net Device for Wi-Fi Direct +* +* \param[in] prGlueInfo Pointer to glue info +* +* \return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN glUnregisterP2P(P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + /* + * normal flow: this func will called first before wlanRemove, and it can do fsmUninit/deactivateNetwork + * gracefully. + */ + /* + * when reset: because tx_thread with fw has stopped, so it can't do these job and the recovery will be + * dependent on chip system reset. + */ + /* + * if so, just skip it by flag GLUE_FLAG_HALT(warning: when tx_thread was stop, this flag was not cleared, + * and NEED TO KEEP IT NOT CLEARED!). + */ + if (!(prGlueInfo->ulFlag & GLUE_FLAG_HALT)) { + p2pFsmUninit(prGlueInfo->prAdapter); + nicDeactivateNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_P2P_INDEX); + } +#if CFG_SUPPORT_PERSIST_NETDEV + dev_close(prGlueInfo->prP2PInfo->prDevHandler); +#else + if (prGlueInfo->prP2PInfo->prDevHandler != NULL) + free_netdev(prGlueInfo->prP2PInfo->prDevHandler); + prGlueInfo->prP2PInfo->prDevHandler = NULL; +#endif + /* Free p2p memory */ + if (!p2PFreeInfo(prGlueInfo)) { + DBGLOG(P2P, ERROR, "Free memory for p2p FAILED\n"); + ASSERT(0); + return FALSE; + } + return TRUE; +} /* end of glUnregisterP2P() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief A function for stop p2p fsm immediate + * + * \param[in] prGlueInfo Pointer to struct P_GLUE_INFO_T. + * + * \retval TRUE The execution succeeds. + * \retval FALSE The execution failed. + */ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2pStopImmediate(P_GLUE_INFO_T prGlueInfo) +{ +/* P_ADAPTER_T prAdapter = NULL; */ +/* P_MSG_P2P_FUNCTION_SWITCH_T prFuncSwitch; */ + + ASSERT(prGlueInfo); + +/* prAdapter = prGlueInfo->prAdapter; */ +/* ASSERT(prAdapter); */ + + /* 1. stop TX queue */ + netif_tx_stop_all_queues(prGlueInfo->prP2PInfo->prDevHandler); + +#if 0 + /* 2. switch P2P-FSM off */ + /* 2.1 allocate for message */ + prFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(MSG_P2P_FUNCTION_SWITCH_T)); + + if (!prFuncSwitch) { + ASSERT(0); /* Can't trigger P2P FSM */ + DBGLOG(P2P, ERROR, "Allocate for p2p mesasage FAILED\n"); + /* return -ENOMEM; */ + } + + /* 2.2 fill message */ + prFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; + prFuncSwitch->fgIsFuncOn = FALSE; + + /* 2.3 send message */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prFuncSwitch, MSG_SEND_METHOD_UNBUF); + +#endif + + /* 3. stop queue and turn off carrier */ + prGlueInfo->prP2PInfo->eState = PARAM_MEDIA_STATE_DISCONNECTED; + + return TRUE; +} /* end of p2pStop() */ + +/* Net Device Hooks */ +/*----------------------------------------------------------------------------*/ +/*! + * \brief A function for net_device open (ifup) + * + * \param[in] prDev Pointer to struct net_device. + * + * \retval 0 The execution succeeds. + * \retval < 0 The execution failed. + */ +/*----------------------------------------------------------------------------*/ +static int p2pOpen(IN struct net_device *prDev) +{ +/* P_GLUE_INFO_T prGlueInfo = NULL; */ +/* P_ADAPTER_T prAdapter = NULL; */ +/* P_MSG_P2P_FUNCTION_SWITCH_T prFuncSwitch; */ + + ASSERT(prDev); + +#if 0 /* Move after device name set. (mtk_p2p_set_local_dev_info) */ + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + /* 1. switch P2P-FSM on */ + /* 1.1 allocate for message */ + prFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(MSG_P2P_FUNCTION_SWITCH_T)); + + if (!prFuncSwitch) { + ASSERT(0); /* Can't trigger P2P FSM */ + return -ENOMEM; + } + + /* 1.2 fill message */ + prFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; + prFuncSwitch->fgIsFuncOn = TRUE; + + /* 1.3 send message */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prFuncSwitch, MSG_SEND_METHOD_BUF); +#endif + + /* 2. carrier on & start TX queue */ + /* netif_carrier_on(prDev); */ + netif_tx_start_all_queues(prDev); + + return 0; /* success */ +} /* end of p2pOpen() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief A function for net_device stop (ifdown) + * + * \param[in] prDev Pointer to struct net_device. + * + * \retval 0 The execution succeeds. + * \retval < 0 The execution failed. + */ +/*----------------------------------------------------------------------------*/ +static int p2pStop(IN struct net_device *prDev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + /* P_ADAPTER_T prAdapter = NULL; */ +/* P_MSG_P2P_FUNCTION_SWITCH_T prFuncSwitch; */ + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + + struct cfg80211_scan_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) + kalCfg80211ScanDone(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 CFG_SUPPORT_PERSIST_NETDEV + /* @FIXME */ + /* prDev->stats.rx_packets = 0; */ + /* prDev->stats.tx_packets = 0; */ + prDev->stats.tx_errors = 0; + prDev->stats.rx_errors = 0; + /* prDev->stats.rx_bytes = 0; */ + /* prDev->stats.tx_bytes = 0; */ + prDev->stats.multicast = 0; + + return &prDev->stats; + +#else + /* prGlueInfo->prP2PInfo->rNetDevStats.rx_packets = 0; */ + /* prGlueInfo->prP2PInfo->rNetDevStats.tx_packets = 0; */ + prGlueInfo->prP2PInfo->rNetDevStats.tx_errors = 0; + prGlueInfo->prP2PInfo->rNetDevStats.rx_errors = 0; + /* prGlueInfo->prP2PInfo->rNetDevStats.rx_bytes = 0; */ + /* prGlueInfo->prP2PInfo->rNetDevStats.tx_bytes = 0; */ + /* prGlueInfo->prP2PInfo->rNetDevStats.rx_errors = 0; */ + prGlueInfo->prP2PInfo->rNetDevStats.multicast = 0; + + return &prGlueInfo->prP2PInfo->rNetDevStats; +#endif +} /* end of p2pGetStats() */ + +static void p2pSetMulticastList(IN struct net_device *prDev) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + + prGlueInfo = (prDev != NULL) ? *((P_GLUE_INFO_T *) netdev_priv(prDev)) : NULL; + + ASSERT(prDev); + ASSERT(prGlueInfo); + if (!prDev || !prGlueInfo) { + DBGLOG(P2P, WARN, "abnormal dev or skb: prDev(0x%p), prGlueInfo(0x%p)\n", prDev, prGlueInfo); + return; + } + + g_P2pPrDev = prDev; + + /* 4 Mark HALT, notify main thread to finish current job */ + /* prGlueInfo->u4Flag |= GLUE_FLAG_SUB_MOD_MULTICAST; */ + set_bit(GLUE_FLAG_SUB_MOD_MULTICAST_BIT, &prGlueInfo->ulFlag); + + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + +} /* p2pSetMulticastList */ + +/* + * FIXME: Since we cannot sleep in the wlanSetMulticastList, we arrange + * another workqueue for sleeping. We don't want to block + * tx_thread, so we can't let tx_thread to do this + */ + +void p2pSetMulticastListWorkQueueWrapper(P_GLUE_INFO_T prGlueInfo) +{ + if (!prGlueInfo) { + DBGLOG(INIT, ERROR, "prGlueInfo is NULL\n"); + return; + } +#if CFG_ENABLE_WIFI_DIRECT + if (prGlueInfo->prAdapter->fgIsP2PRegistered) + mtk_p2p_wext_set_Multicastlist(prGlueInfo); +#endif +} /* end of p2pSetMulticastListWorkQueueWrapper() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is to set multicast list and set rx mode. + * + * \param[in] prDev Pointer to struct net_device + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void mtk_p2p_wext_set_Multicastlist(P_GLUE_INFO_T prGlueInfo) +{ + UINT_32 u4SetInfoLen = 0; + struct net_device *prDev = g_P2pPrDev; + + prGlueInfo = (prDev != NULL) ? *((P_GLUE_INFO_T *) netdev_priv(prDev)) : NULL; + + ASSERT(prDev); + ASSERT(prGlueInfo); + if (!prDev || !prGlueInfo) { + DBGLOG(P2P, WARN, "abnormal dev or skb: prDev(0x%p), prGlueInfo(0x%p)\n", prDev, prGlueInfo); + return; + } + + if (prDev->flags & IFF_PROMISC) + prGlueInfo->prP2PInfo->u4PacketFilter |= PARAM_PACKET_FILTER_PROMISCUOUS; + + if (prDev->flags & IFF_BROADCAST) + prGlueInfo->prP2PInfo->u4PacketFilter |= PARAM_PACKET_FILTER_BROADCAST; + + if (prDev->flags & IFF_MULTICAST) { + if ((prDev->flags & IFF_ALLMULTI) || + (netdev_mc_count(prDev) > MAX_NUM_GROUP_ADDR)) { + prGlueInfo->prP2PInfo->u4PacketFilter |= PARAM_PACKET_FILTER_ALL_MULTICAST; + } else { + prGlueInfo->prP2PInfo->u4PacketFilter |= PARAM_PACKET_FILTER_MULTICAST; + } + } + + if (prGlueInfo->prP2PInfo->u4PacketFilter & PARAM_PACKET_FILTER_MULTICAST) { + /* Prepare multicast address list */ + struct netdev_hw_addr *ha; + UINT_32 i = 0; + + /* Avoid race condition with kernel net subsystem */ + netif_addr_lock_bh(prDev); + + netdev_for_each_mc_addr(ha, prDev) { + if ((i < MAX_NUM_GROUP_ADDR) && (ha != NULL)) { + COPY_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucMCAddrList[i]), ha->addr); + i++; + } + } + + netif_addr_unlock_bh(prDev); + + DBGLOG(P2P, TRACE, "SEt Multicast Address List\n"); + + if (i >= MAX_NUM_GROUP_ADDR) + return; + wlanoidSetP2PMulticastList(prGlueInfo->prAdapter, + &(prGlueInfo->prP2PInfo->aucMCAddrList[0]), (i * ETH_ALEN), &u4SetInfoLen); + + } + +} /* end of mtk_p2p_wext_set_Multicastlist */ + +/*----------------------------------------------------------------------------*/ +/* + * \brief This function is TX entry point of NET DEVICE. + * + * \param[in] prSkb Pointer of the sk_buff to be sent + * \param[in] prDev Pointer to struct net_device + * + * \retval NETDEV_TX_OK - on success. + * \retval NETDEV_TX_BUSY - on failure, packet will be discarded by upper layer. + */ +/*----------------------------------------------------------------------------*/ +int p2pHardStartXmit(IN struct sk_buff *prSkb, IN struct net_device *prDev) +{ + P_QUE_ENTRY_T prQueueEntry = NULL; + P_QUE_T prTxQueue = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_16 u2QueueIdx = 0; + P_BSS_INFO_T prP2pBssInfo = NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prSkb); + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + prGlueInfo->u8SkbToDriver++; + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(P2P, ERROR, "GLUE_FLAG_HALT skip tx\n"); + prGlueInfo->u8SkbFreed++; + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } +#if (CFG_SUPPORT_MET_PROFILING == 1) + kalMetProfilingStart(prGlueInfo, prSkb); +#endif + + /* mark as P2P packets */ + GLUE_SET_PKT_FLAG_P2P(prSkb); +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + GLUE_SET_PKT_ARRIVAL_TIME(prSkb, kalGetTimeTick()); +#endif + + STATS_TX_TIME_ARRIVE(prSkb); + prQueueEntry = (P_QUE_ENTRY_T) GLUE_GET_PKT_QUEUE_ENTRY(prSkb); + prTxQueue = &prGlueInfo->rTxQueue; + + /* Statistic usage. */ + prGlueInfo->prP2PInfo->rNetDevStats.tx_bytes += prSkb->len; + prGlueInfo->prP2PInfo->rNetDevStats.tx_packets++; + /* prDev->stats.tx_packets++; */ + + if (wlanProcessSecurityFrame(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb) == FALSE) { + + u2QueueIdx = skb_get_queue_mapping(prSkb); + ASSERT(u2QueueIdx < CFG_MAX_TXQ_NUM); + + if (u2QueueIdx >= CFG_MAX_TXQ_NUM) { + DBGLOG(P2P, ERROR, "Incorrect queue index, skip this frame\n"); + prGlueInfo->u8SkbFreed++; + prGlueInfo->prP2PInfo->rNetDevStats.tx_bytes -= prSkb->len; + prGlueInfo->prP2PInfo->rNetDevStats.tx_packets--; + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_INSERT_TAIL(prTxQueue, prQueueEntry); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingFrameNum); + GLUE_INC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_P2P_INDEX][u2QueueIdx]); + + if (prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_P2P_INDEX][u2QueueIdx] >= + CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD) { + DBGLOG(TX, INFO, "netif_stop_subqueue for p2p0, Queue len: %d\n", + prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_P2P_INDEX][u2QueueIdx]); + netif_stop_subqueue(prDev, u2QueueIdx); + } + } else { + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum); + } + + kalSetEvent(prGlueInfo); + + prP2pBssInfo = &prGlueInfo->prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; + if ((prP2pBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) || + (prP2pBssInfo->rStaRecOfClientList.u4NumElem > 0)) + kalPerMonStart(prGlueInfo); + + return NETDEV_TX_OK; +} /* end of p2pHardStartXmit() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief A method of struct net_device, a primary SOCKET interface to configure + * the interface lively. Handle an ioctl call on one of our devices. + * Everything Linux ioctl specific is done here. Then we pass the contents + * of the ifr->data to the request message handler. + * + * \param[in] prDev Linux kernel netdevice + * + * \param[in] prIfReq Our private ioctl request structure, typed for the generic + * struct ifreq so we can use ptr to function + * + * \param[in] cmd Command ID + * + * \retval 0 The IOCTL command is executed successfully. + * \retval <0 The execution of IOCTL command is failed. + */ +/*----------------------------------------------------------------------------*/ +int p2pDoIOCTL(struct net_device *prDev, struct ifreq *prIfReq, int i4Cmd) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + int ret = 0; + char *prExtraBuf = NULL; + UINT_32 u4ExtraSize = 0; + struct iwreq *prIwReq = (struct iwreq *)prIfReq; + struct iw_request_info rIwReqInfo; + + ASSERT(prDev && prIfReq); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + if (!prGlueInfo) { + DBGLOG(P2P, ERROR, "prGlueInfo is NULL\n"); + return -EFAULT; + } + + if (prGlueInfo->u4ReadyFlag == 0) { + DBGLOG(P2P, ERROR, "Adapter is not ready\n"); + return -EINVAL; + } + + rIwReqInfo.cmd = (__u16) i4Cmd; + rIwReqInfo.flags = 0; + + switch (i4Cmd) { + case SIOCSIWENCODEEXT: + /* Set Encryption Material after 4-way handshaking is done */ + if (prIwReq->u.encoding.pointer) { + u4ExtraSize = prIwReq->u.encoding.length; + if (u4ExtraSize > sizeof(struct iw_encode_ext)) { + ret = -EINVAL; + break; + } + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, prIwReq->u.encoding.pointer, u4ExtraSize)) + ret = -EFAULT; + } else if (prIwReq->u.encoding.length != 0) { + ret = -EINVAL; + break; + } + + if (ret == 0) + ret = mtk_p2p_wext_set_key(prDev, &rIwReqInfo, &(prIwReq->u), prExtraBuf); + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); + prExtraBuf = NULL; + break; + + case SIOCSIWMLME: + /* IW_MLME_DISASSOC used for disconnection */ + if (prIwReq->u.data.length != sizeof(struct iw_mlme)) { + DBGLOG(P2P, WARN, "MLME buffer strange:%d\n", prIwReq->u.data.length); + ret = -EINVAL; + break; + } + + if (!prIwReq->u.data.pointer) { + ret = -EINVAL; + break; + } + + prExtraBuf = kalMemAlloc(sizeof(struct iw_mlme), VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, prIwReq->u.data.pointer, sizeof(struct iw_mlme))) + ret = -EFAULT; + else + ret = mtk_p2p_wext_mlme_handler(prDev, &rIwReqInfo, &(prIwReq->u), prExtraBuf); + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, sizeof(struct iw_mlme)); + prExtraBuf = NULL; + break; + + case SIOCGIWPRIV: + /* This ioctl is used to list all IW privilege ioctls */ + ret = mtk_p2p_wext_get_priv(prDev, &rIwReqInfo, &(prIwReq->u), NULL); + break; + + case SIOCGIWSCAN: + ret = mtk_p2p_wext_discovery_results(prDev, &rIwReqInfo, &(prIwReq->u), NULL); + break; + + case SIOCSIWAUTH: + ret = mtk_p2p_wext_set_auth(prDev, &rIwReqInfo, &(prIwReq->u), NULL); + break; + + case IOC_P2P_CFG_DEVICE: + case IOC_P2P_PROVISION_COMPLETE: + case IOC_P2P_START_STOP_DISCOVERY: + case IOC_P2P_DISCOVERY_RESULTS: + case IOC_P2P_WSC_BEACON_PROBE_RSP_IE: + case IOC_P2P_CONNECT_DISCONNECT: + case IOC_P2P_PASSWORD_READY: + case IOC_P2P_GET_STRUCT: + case IOC_P2P_SET_STRUCT: + case IOC_P2P_GET_REQ_DEVICE_INFO: + ret = + rP2PIwPrivHandler[i4Cmd - SIOCIWFIRSTPRIV] (prDev, &rIwReqInfo, &(prIwReq->u), + (char *)&(prIwReq->u)); + break; +#if CFG_SUPPORT_P2P_RSSI_QUERY + case SIOCGIWSTATS: + ret = mtk_p2p_wext_get_rssi(prDev, &rIwReqInfo, &(prIwReq->u), NULL); + break; +#endif + case IOC_GET_PRIVATE_IOCTL_CMD: + ret = priv_support_driver_cmd(prDev, prIfReq, i4Cmd); + + break; + default: + ret = -ENOTTY; + } + + return ret; +} /* end of p2pDoIOCTL() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To report the iw private args table to user space. + * + * \param[in] prDev Net device requested. + * \param[in] info Pointer to iw_request_info. + * \param[inout] wrqu Pointer to iwreq_data. + * \param[inout] extra + * + * \retval 0 For success. + * \retval -E2BIG For user's buffer size is too small. + * \retval -EFAULT For fail. + * + */ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_get_priv(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + struct iw_point *prData = (struct iw_point *)&wrqu->data; + UINT_16 u2BufferSize = prData->length; + + /* Update our private args table size */ + prData->length = (__u16)sizeof(rP2PIwPrivTable); + if (u2BufferSize < prData->length) + return -E2BIG; + + if (prData->length) { + if (copy_to_user(prData->pointer, rP2PIwPrivTable, sizeof(rP2PIwPrivTable))) + return -EFAULT; + } + + return 0; +} /* end of mtk_p2p_wext_get_priv() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To indicate P2P-FSM for re-associate to the connecting device + * + * \param[in] prDev Net device requested. + * \param[inout] wrqu Pointer to iwreq_data + * + * \retval 0 For success. + * \retval -EFAULT For fail. + * + */ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_reconnect(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ +#if 0 + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_MSG_HDR_T prMsgHdr; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prMsgHdr = (P_MSG_HDR_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_HDR_T)); + if (!prMsgHdr) { + ASSERT(0); /* Can't trigger P2P FSM */ + return -ENOMEM; + } + + /* 1.2 fill message */ + + DBGLOG(P2P, TRACE, "mtk_p2p_wext_reconnect: P2P Reconnect\n"); + + /* 1.3 send message */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgHdr, MSG_SEND_METHOD_BUF); +#endif + return 0; +} /* end of mtk_p2p_wext_reconnect() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief MLME command handler +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_mlme_handler(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ +#if 0 + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + struct iw_mlme *mlme = (struct iw_mlme *)extra; + P_MSG_P2P_CONNECTION_ABORT_T prMsgP2PConnAbt = (P_MSG_P2P_CONNECTION_ABORT_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + DBGLOG(P2P, TRACE, "mtk_p2p_wext_mlme_handler:\n"); + + switch (mlme->cmd) { + case IW_MLME_DISASSOC: + prMsgP2PConnAbt = + (P_MSG_HDR_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_CONNECTION_ABORT_T)); + if (!prMsgP2PConnAbt) { + ASSERT(0); /* Can't trigger P2P FSM */ + return -ENOMEM; + } + + COPY_MAC_ADDR(prMsgP2PConnAbt->aucTargetID, mlme->addr.sa_data); + + prMsgP2PConnAbt->u2ReasonCode = mlme->reason_code; + + if (EQUAL_MAC_ADDR(prMsgP2PConnAbt->aucTargetID, prP2pBssInfo->aucOwnMacAddr)) { + DBGLOG(P2P, TRACE, "P2P Connection Abort:\n"); + + /* 1.2 fill message */ + prMsgP2PConnAbt->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT; + } else { + DBGLOG(P2P, TRACE, "P2P Connection Pause:\n"); + + /* 1.2 fill message */ + } + + /* 1.3 send message */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgP2PConnAbt, MSG_SEND_METHOD_BUF); + + break; + + default: + return -EOPNOTSUPP; + } +#endif + return 0; +} /* end of mtk_p2p_wext_mlme_handler() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_PROVISION_COMPLETE) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_provision_complete(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ +#if 0 + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + struct iw_point *prData = (struct iw_point *)&wrqu->data; + P_MSG_HDR_T prMsgHdr; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + switch (prData->flags) { + case P2P_PROVISIONING_SUCCESS: + prMsgHdr = (P_MSG_HDR_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_HDR_T)); + if (!prMsgHdr) { + ASSERT(0); /* Can't trigger P2P FSM */ + return -ENOMEM; + } + + /* 1.2 fill message */ + + prGlueInfo->prP2PInfo->u4CipherPairwise = IW_AUTH_CIPHER_CCMP; + + /* 1.3 send message */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgHdr, MSG_SEND_METHOD_BUF); + + break; + + case P2P_PROVISIONING_FAIL: + + break; + + default: + return -EOPNOTSUPP; + } +#endif + + return 0; +} /* end of mtk_p2p_wext_set_provision_complete() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_START_STOP_DISCOVERY) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_start_stop_discovery(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ +#if 0 + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + struct iw_point *prData = (struct iw_point *)&wrqu->data; + P_IW_P2P_REQ_DEVICE_TYPE prReqDeviceType = (P_IW_P2P_REQ_DEVICE_TYPE) extra; + UINT_8 au4IeBuf[MAX_IE_LENGTH]; + P_MSG_HDR_T prMsgHdr; + P_MSG_P2P_DEVICE_DISCOVER_T prDiscoverMsg; + P_P2P_CONNECTION_SETTINGS_T prConnSettings; + UINT_8 aucNullAddr[] = NULL_MAC_ADDR; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + if (prData->flags == P2P_STOP_DISCOVERY) { + prMsgHdr = (P_MSG_HDR_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_HDR_T)); + + if (!prMsgHdr) { + ASSERT(0); /* Can't trigger P2P FSM */ + return -ENOMEM; + } + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgHdr, MSG_SEND_METHOD_BUF); + } else if (prData->flags == P2P_START_DISCOVERY) { + + /* retrieve IE for Probe Response */ + if (prReqDeviceType->probe_rsp_len > 0) { + if (prReqDeviceType->probe_rsp_len <= MAX_IE_LENGTH) { + if (copy_from_user + (prGlueInfo->prP2PInfo->aucWSCIE[2], prReqDeviceType->probe_rsp_ie, + prReqDeviceType->probe_rsp_len)) { + return -EFAULT; + } + prGlueInfo->prP2PInfo->u2WSCIELen[2] = prReqDeviceType->probe_rsp_len; + } else { + return -E2BIG; + } + } + + /* retrieve IE for Probe Request */ + if (prReqDeviceType->probe_req_len > 0) { + if (prReqDeviceType->probe_req_len <= MAX_IE_LENGTH) { + if (copy_from_user + (prGlueInfo->prP2PInfo->aucWSCIE[1], prReqDeviceType->probe_req_ie, + prReqDeviceType->probe_req_len)) { + return -EFAULT; + } + prGlueInfo->prP2PInfo->u2WSCIELen[1] = prReqDeviceType->probe_req_len; + } else { + return -E2BIG; + } + } + /* update IE for Probe Request */ + + if (prReqDeviceType->scan_type == P2P_LISTEN) { + /* update listening parameter */ + + /* @TODO: update prConnSettings for Probe Response IE */ + } else { + /* indicate P2P-FSM with MID_MNY_P2P_DEVICE_DISCOVERY */ + prDiscoverMsg = (P_MSG_P2P_DEVICE_DISCOVER_T) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(MSG_P2P_DEVICE_DISCOVER_T)); + + if (!prDiscoverMsg) { + ASSERT(0); /* Can't trigger P2P FSM */ + return -ENOMEM; + } + + prDiscoverMsg->rMsgHdr.eMsgId = MID_MNY_P2P_DEVICE_DISCOVERY; + prDiscoverMsg->u4DevDiscoverTime = 0; /* unlimited */ + prDiscoverMsg->fgIsSpecificType = TRUE; + prDiscoverMsg->rTargetDeviceType.u2CategoryID = + *(PUINT_16) (&(prReqDeviceType->pri_device_type[0])); + prDiscoverMsg->rTargetDeviceType.u2SubCategoryID = + *(PUINT_16) (&(prReqDeviceType->pri_device_type[6])); + COPY_MAC_ADDR(prDiscoverMsg->aucTargetDeviceID, aucNullAddr); + + /* @FIXME: parameter to be refined, where to pass IE buffer ? */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prDiscoverMsg, MSG_SEND_METHOD_BUF); + } + } else { + return -EINVAL; + } +#endif + + return 0; +} /* end of mtk_p2p_wext_start_stop_discovery() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_SET_INT) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Setting parameters not support. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_invitation_request(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + int i4Status = 0; +#if 0 + P_ADAPTER_T prAdapter = (P_ADAPTER_T) NULL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + struct iw_point *prData = (struct iw_point *)&wrqu->data; + P_IW_P2P_IOCTL_INVITATION_STRUCT prIoctlInvitation = (P_IW_P2P_IOCTL_INVITATION_STRUCT) NULL; + + do { + if ((prDev == NULL) || (extra == NULL)) { + ASSERT(FALSE); + i4Status = -EINVAL; + break; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + prIoctlInvitation = (P_IW_P2P_IOCTL_INVITATION_STRUCT) extra; + + if (prGlueInfo == NULL) { + i4Status = -EINVAL; + break; + } + + prAdapter = prGlueInfo->prAdapter; + + if (prAdapter == NULL) { + i4Status = -EINVAL; + break; + } + + if (prIoctlInvitation->ucReinvoke == 1) { + /* TODO: Set Group ID */ + p2pFuncSetGroupID(prAdapter, prIoctlInvitation->aucGroupID, prIoctlInvitation->aucSsid, + prIoctlInvitation->u4SsidLen); + } + + else { + P_MSG_P2P_INVITATION_REQUEST_T prMsgP2PInvitationReq = (P_MSG_P2P_INVITATION_REQUEST_T) NULL; + + /* TODO: Do Invitation. */ + prMsgP2PInvitationReq = + (P_MSG_P2P_INVITATION_REQUEST_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(MSG_P2P_INVITATION_REQUEST_T)); + if (!prMsgP2PInvitationReq) { + ASSERT(0); /* Can't trigger P2P FSM */ + i4Status = -ENOMEM; + break; + } + + /* 1.2 fill message */ + kalMemCopy(prMsgP2PInvitationReq->aucDeviceID, prIoctlInvitation->aucDeviceID, MAC_ADDR_LEN); + + DBGLOG(P2P, TRACE, "mtk_p2p_wext_invitation_request: P2P Invitation Req\n"); + + /* 1.3 send message */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgP2PInvitationReq, MSG_SEND_METHOD_BUF); + + } + + } while (FALSE); +#endif + + return i4Status; + +} + +/* mtk_p2p_wext_invitation_request */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_SET_INT) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Setting parameters not support. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_invitation_abort(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + int i4Status = 0; +#if 0 + P_ADAPTER_T prAdapter = (P_ADAPTER_T) NULL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + struct iw_point *prData = (struct iw_point *)&wrqu->data; + P_IW_P2P_IOCTL_ABORT_INVITATION prIoctlInvitationAbort = (P_IW_P2P_IOCTL_ABORT_INVITATION) NULL; + + UINT_8 bssid[MAC_ADDR_LEN]; + + do { + if ((prDev == NULL) || (extra == NULL)) { + ASSERT(FALSE); + i4Status = -EINVAL; + break; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + prIoctlInvitationAbort = (P_IW_P2P_IOCTL_ABORT_INVITATION) extra; + + if (prGlueInfo == NULL) { + i4Status = -EINVAL; + break; + } + + prAdapter = prGlueInfo->prAdapter; + + if (prAdapter == NULL) { + i4Status = -EINVAL; + break; + } + P_MSG_P2P_INVITATION_REQUEST_T prMsgP2PInvitationAbort = (P_MSG_P2P_INVITATION_REQUEST_T) NULL; + + prMsgP2PInvitationAbort = + (P_MSG_P2P_INVITATION_REQUEST_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(MSG_P2P_INVITATION_REQUEST_T)); + + if (!prMsgP2PInvitationAbort) { + ASSERT(0); /* Can't trigger P2P FSM */ + i4Status = -ENOMEM; + break; + } + + /* 1.2 fill message */ + kalMemCopy(prMsgP2PInvitationAbort->aucDeviceID, prIoctlInvitationAbort->dev_addr, + MAC_ADDR_LEN); + + DBGLOG(P2P, TRACE, "mtk_p2p_wext_invitation_request: P2P Invitation Req\n"); + + /* 1.3 send message */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgP2PInvitationAbort, MSG_SEND_METHOD_BUF); + + + } while (FALSE); +#endif + + return i4Status; + +} + +/* mtk_p2p_wext_invitation_abort */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To override p2p interface address + * + * \param[in] prDev Net device requested. + * \param[in] addr Pointer to address + * + * \retval 0 For success. + * \retval -E2BIG For user's buffer size is too small. + * \retval -EFAULT For fail. + * + */ +/*----------------------------------------------------------------------------*/ +int p2pSetMACAddress(IN struct net_device *prDev, void *addr) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_BSS_INFO_T prBssInfo = NULL; + struct sockaddr *sa = NULL; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + if (!prDev || !addr) { + DBGLOG(INIT, ERROR, "Set macaddr with ndev(%d) and addr(%d)\n", + (prDev == NULL) ? 0 : 1, (addr == NULL) ? 0 : 1); + return WLAN_STATUS_INVALID_DATA; + } + + prBssInfo + = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + if (!prBssInfo) { + DBGLOG(INIT, ERROR, "bss is not active\n"); + return WLAN_STATUS_INVALID_DATA; + } + + sa = (struct sockaddr *)addr; + + COPY_MAC_ADDR(prBssInfo->aucOwnMacAddr, sa->sa_data); + COPY_MAC_ADDR(prDev->dev_addr, sa->sa_data); + + COPY_MAC_ADDR(prAdapter->rWifiVar.aucDeviceAddress, + sa->sa_data); + COPY_MAC_ADDR(prAdapter->rWifiVar.aucInterfaceAddress, + sa->sa_data); + + /* Unset p2p net to update OwnMacAddr in FSM */ + UNSET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); + + DBGLOG(INIT, INFO, + "Set random macaddr to " MACSTR ".\n", + MAC2STR(prBssInfo->aucOwnMacAddr)); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 (GLUE_CHK_PR2(prDev, prAuth) == FALSE) + 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; + if (u4ExtraSize > sizeof(struct iw_encode_ext)) { + ret = -EINVAL; + break; + } + + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + /* here should set prExtraBuf default value */ + memset(prExtraBuf, 0, u4ExtraSize); + if (copy_from_user(prExtraBuf, wrqu->encoding.pointer, u4ExtraSize)) { + 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) { + ret = -EINVAL; + break; + } + + memset(keyStructBuf, 0, sizeof(keyStructBuf)); + + if ((prEnc->flags & IW_ENCODE_MODE) == IW_ENCODE_DISABLED) { /* Key Removal */ + prRemoveKey->u4Length = sizeof(*prRemoveKey); + memcpy(prRemoveKey->arBSSID, prIWEncExt->addr.sa_data, 6); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRemoveP2PKey, + prRemoveKey, + prRemoveKey->u4Length, FALSE, FALSE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + ret = -EFAULT; + } else { + if (prIWEncExt->alg == IW_ENCODE_ALG_CCMP) { + /* KeyID */ + prKey->u4KeyIndex = (prEnc->flags & IW_ENCODE_INDEX) ? + ((prEnc->flags & IW_ENCODE_INDEX) - 1) : 0; + if (prKey->u4KeyIndex <= 3) { + /* bit(31) and bit(30) are shared by pKey and pRemoveKey */ + /* Tx Key Bit(31) */ + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + prKey->u4KeyIndex |= 0x1UL << 31; + + /* Pairwise Key Bit(30) */ + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + /* group key */ + } else { + /* pairwise key */ + prKey->u4KeyIndex |= 0x1UL << 30; + } + + /* Rx SC Bit(29) */ + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { + prKey->u4KeyIndex |= 0x1UL << 29; + memcpy(&prKey->rKeyRSC, prIWEncExt->rx_seq, + IW_ENCODE_SEQ_MAX_SIZE); + } + + /* BSSID */ + memcpy(prKey->arBSSID, prIWEncExt->addr.sa_data, 6); + if (prIWEncExt->key_len >= 32) { + ret = -EINVAL; + break; + } + memcpy(prKey->aucKeyMaterial, prIWEncExt->key, prIWEncExt->key_len); + + prKey->u4KeyLength = prIWEncExt->key_len; + prKey->u4Length = + ((ULONG)&(((P_PARAM_KEY_T) 0)->aucKeyMaterial)) + + prKey->u4KeyLength; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAddP2PKey, + prKey, + prKey->u4Length, + FALSE, FALSE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + ret = -EFAULT; + } else { + ret = -EINVAL; + } + } else { + ret = -EINVAL; + } + } + + } while (FALSE); + + if (prExtraBuf) { + kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); + prExtraBuf = NULL; + } + + return ret; +} /* end of mtk_p2p_wext_set_key() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief set the p2p gc power mode +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_powermode(IN struct net_device *prNetDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + /* printk("set_powermode = %d, value = %d\n", wrqu->power.disabled, wrqu->power.value); */ + struct iw_param *prPower = (struct iw_param *)&wrqu->power; +#if 1 + PARAM_POWER_MODE ePowerMode; + INT_32 i4PowerValue; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prPower); + if (GLUE_CHK_PR2(prNetDev, prPower) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* printk(KERN_INFO "wext_set_power value(%d) disabled(%d) flag(0x%x)\n", */ + /* prPower->value, prPower->disabled, prPower->flags); */ + + if (prPower->disabled) { + ePowerMode = Param_PowerModeCAM; + } else { + i4PowerValue = prPower->value; +#if WIRELESS_EXT < 21 + i4PowerValue /= 1000000; +#endif + if (i4PowerValue == 0) { + ePowerMode = Param_PowerModeCAM; + } else if (i4PowerValue == 1) { + ePowerMode = Param_PowerModeMAX_PSP; + } else if (i4PowerValue == 2) { + ePowerMode = Param_PowerModeFast_PSP; + } else { + DBGLOG(P2P, ERROR, "%s(): unsupported power management mode value = %d.\n", + __func__, prPower->value); + + return -EINVAL; + } + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetP2pPowerSaveProfile, + &ePowerMode, sizeof(ePowerMode), FALSE, FALSE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + /* printk(KERN_INFO DRV_NAME"wlanoidSet802dot11PowerSaveProfile fail 0x%lx\n", rStatus); */ + return -EFAULT; + } +#endif + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief get the p2p gc power mode +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_get_powermode(IN struct net_device *prNetDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + /* printk("mtk_p2p_wext_get_powermode\n"); */ + /* wrqu->power.disabled = 0; */ + /* wrqu->power.value = 1; */ + + struct iw_param *prPower = (struct iw_param *)&wrqu->power; + PARAM_POWER_MODE ePowerMode = Param_PowerModeMax; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prPower); + if (GLUE_CHK_PR2(prNetDev, prPower) == FALSE) + 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="); + if (iwe.u.data.length > 40) + iwe.u.data.length = 40; + + snprintf(data, iwe.u.data.length, "p2p_cap=%02x%02x%02x%02x%c", + prTargetResult->ucDeviceCapabilityBitmap, prTargetResult->ucGroupCapabilityBitmap, + (UINT_8) prTargetResult->u2ConfigMethod, + (UINT_8) (prTargetResult->u2ConfigMethod >> 8), '\0'); + current_ev = + iwe_stream_add_point(info, current_ev, extra + IW_SCAN_MAX_DATA, &iwe, (char *)data); + + /* printk("%s\n", data); */ + kalMemZero(data, 40); + + iwe.cmd = IWEVCUSTOM; + iwe.u.data.flags = 0; + iwe.u.data.length = 12 + sizeof("p2p_dev_type="); + if (iwe.u.data.length > 40) + iwe.u.data.length = 40; + + snprintf(data, iwe.u.data.length, "p2p_dev_type=%02x%02x%02x%02x%02x%02x%c", + (UINT_8) prTargetResult->rPriDevType.u2CategoryID, + (UINT_8) prTargetResult->rPriDevType.u2SubCategoryID, + (UINT_8) prTargetResult->arSecDevType[0].u2CategoryID, + (UINT_8) prTargetResult->arSecDevType[0].u2SubCategoryID, + (UINT_8) prTargetResult->arSecDevType[1].u2CategoryID, + (UINT_8) prTargetResult->arSecDevType[1].u2SubCategoryID, '\0'); + current_ev = + iwe_stream_add_point(info, current_ev, extra + IW_SCAN_MAX_DATA, &iwe, (char *)data); + /* printk("%s\n", data); */ + + kalMemZero(data, 40); + + iwe.cmd = IWEVCUSTOM; + iwe.u.data.flags = 0; + iwe.u.data.length = 17 + sizeof("p2p_grp_bssid="); + if (iwe.u.data.length > 40) + iwe.u.data.length = 40; + + snprintf(data, iwe.u.data.length, "p2p_grp_bssid= %pM %c", + prTargetResult->aucBSSID, '\0'); + current_ev = iwe_stream_add_point(info, current_ev, + extra + IW_SCAN_MAX_DATA, &iwe, (char *)data); + /* printk("%s\n", data); */ + + } +#endif + } + + /* Length of data */ + wrqu->data.length = (current_ev - extra); + wrqu->data.flags = 0; + + return 0; +} /* end of mtk_p2p_wext_discovery_results() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_WSC_BEACON_PROBE_RSP_IE) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_wsc_ie(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_IW_P2P_HOSTAPD_PARAM prHostapdParam = (P_IW_P2P_HOSTAPD_PARAM) extra; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + if (prHostapdParam->len > 0) { + if (prHostapdParam->len <= MAX_WSC_IE_LENGTH) { + if (copy_from_user + (prGlueInfo->prP2PInfo->aucWSCIE[0], prHostapdParam->data, prHostapdParam->len)) { + return -EFAULT; + } + if (copy_from_user + (prGlueInfo->prP2PInfo->aucWSCIE[2], prHostapdParam->data, prHostapdParam->len)) { + return -EFAULT; + } + } else { + return -E2BIG; + } + } + + prGlueInfo->prP2PInfo->u2WSCIELen[0] = prHostapdParam->len; + prGlueInfo->prP2PInfo->u2WSCIELen[2] = prHostapdParam->len; + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_P2P_INDEX); + + /* @TODO: send message to P2P-FSM */ + + return 0; +} /* end of mtk_p2p_wext_wsc_ie() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_CONNECT_DISCONNECT) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_connect_disconnect(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + struct iw_point *prData = (struct iw_point *)&wrqu->data; +/* P_IW_P2P_CONNECT_DEVICE prConnectDevice = (P_IW_P2P_CONNECT_DEVICE)extra; */ +/* P_MSG_HDR_T prMsgHdr; */ +/* P_MSG_P2P_CONNECTION_REQUEST_T prMsgP2PConnReq; */ +/* P_MSG_P2P_CONNECTION_ABORT_T prMsgP2PConnAbt; */ +/* UINT_8 aucBCAddr[] = BC_MAC_ADDR; */ + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + if (prData->flags == P2P_CONNECT) { +#if 0 + /* indicate P2P-FSM with MID_MNY_P2P_CONNECTION_REQ */ + prMsgP2PConnReq = (P_MSG_P2P_CONNECTION_REQUEST_T) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(MSG_P2P_CONNECTION_REQUEST_T)); + + if (!prMsgP2PConnReq) { + ASSERT(0); /* Can't trigger P2P FSM */ + return -ENOMEM; + } + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgP2PConnReq, MSG_SEND_METHOD_BUF); +#endif + } else if (prData->flags == P2P_DISCONNECT) { +#if 0 + /* indicate P2P-FSM with MID_MNY_P2P_CONNECTION_ABORT */ + prMsgP2PConnAbt = (P_MSG_HDR_T) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(MSG_P2P_CONNECTION_ABORT_T)); + + if (!prMsgP2PConnAbt) { + ASSERT(0); /* Can't trigger P2P FSM */ + return -ENOMEM; + } + + COPY_MAC_ADDR(prMsgP2PConnAbt->aucTargetID, prConnectDevice->sta_addr); + + prMsgP2PConnAbt->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgP2PConnAbt, MSG_SEND_METHOD_BUF); +#endif + } else { + return -EINVAL; + } + + return 0; +} /* end of mtk_p2p_wext_connect_disconnect() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_PASSWORD_READY) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_password_ready(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_IW_P2P_PASSWORD_READY prPasswordReady = (P_IW_P2P_PASSWORD_READY) extra; + P_P2P_CONNECTION_SETTINGS_T prConnSettings; + UINT_16 u2CmdLen = 0; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + u2CmdLen = prPasswordReady->probe_req_len; + + /* retrieve IE for Probe Request */ + if (u2CmdLen > 0) { + if (u2CmdLen <= MAX_WSC_IE_LENGTH) { + if (copy_from_user + (prGlueInfo->prP2PInfo->aucWSCIE[1], prPasswordReady->probe_req_ie, + u2CmdLen)) { + return -EFAULT; + } + } else { + return -E2BIG; + } + } + + prGlueInfo->prP2PInfo->u2WSCIELen[1] = u2CmdLen; + + /* retrieve IE for Probe Response */ + u2CmdLen = prPasswordReady->probe_rsp_len; + if (u2CmdLen > 0) { + if (u2CmdLen <= MAX_WSC_IE_LENGTH) { + if (copy_from_user + (prGlueInfo->prP2PInfo->aucWSCIE[2], prPasswordReady->probe_rsp_ie, u2CmdLen)) { + return -EFAULT; + } + } else { + return -E2BIG; + } + } + + prGlueInfo->prP2PInfo->u2WSCIELen[2] = u2CmdLen; + + 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 (GLUE_CHK_PR2(prDev, wrqu) == FALSE) + return -EINVAL; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prP2pSpecificBssInfo = prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo; + prP2pConnSettings = prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings; + prP2pFsmInfo = prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo; + + u4SubCmd = (UINT_32) wrqu->mode; + index = pu4IntBuf[1]; + value = pu4IntBuf[2]; + + DBGLOG(P2P, INFO, "set parameter, u4SubCmd=%d idx=%d value=%d\n", (INT_16) u4SubCmd, (INT_16) index, value); + + switch (u4SubCmd) { + case PRIV_CMD_INT_P2P_SET: + switch (index) { + case 0: /* Listen CH */ + { + UINT_8 ucSuggestChnl = 0; + + prP2pConnSettings->ucListenChnl = value; + + /* 20110920 - frog: User configurations are placed in ConnSettings. */ + if (rlmFuncFindAvailableChannel + (prGlueInfo->prAdapter, value, &ucSuggestChnl, TRUE, TRUE)) { + prP2pSpecificBssInfo->ucListenChannel = value; + } else { + prP2pSpecificBssInfo->ucListenChannel = ucSuggestChnl; + } + + break; + } + case 1: /* P2p mode */ + break; + case 4: /* Noa duration */ + prP2pSpecificBssInfo->rNoaParam.u4NoaDurationMs = value; + /* only to apply setting when setting NOA count */ + /* + * status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, + * (char *)&prP2pSpecificBssInfo->rNoaParam); + */ + break; + case 5: /* Noa interval */ + prP2pSpecificBssInfo->rNoaParam.u4NoaIntervalMs = value; + /* only to apply setting when setting NOA count */ + /* + * status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, + * (char *)&prP2pSpecificBssInfo->rNoaParam); + */ + break; + case 6: /* Noa count */ + prP2pSpecificBssInfo->rNoaParam.u4NoaCount = value; + status = + mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); + break; + case 100: /* Oper CH */ + /* 20110920 - frog: User configurations are placed in ConnSettings. */ + prP2pConnSettings->ucOperatingChnl = value; + break; + case 101: /* Local config Method, for P2P SDK */ + /* prP2pConnSettings->u2LocalConfigMethod; */ + break; + case 102: /* Sigma P2p reset */ + kalMemZero(prP2pConnSettings->aucTargetDevAddr, MAC_ADDR_LEN); + /* prP2pConnSettings->eConnectionPolicy = ENUM_P2P_CONNECTION_POLICY_AUTO; */ + break; + case 103: /* WPS MODE */ + kalP2PSetWscMode(prGlueInfo, value); + break; + case 104: /* P2p send persence, duration */ + break; + case 105: /* P2p send persence, interval */ + break; + case 106: /* P2P set sleep */ + value = 1; + kalIoctl(prGlueInfo, + wlanoidSetP2pPowerSaveProfile, + &value, sizeof(value), FALSE, FALSE, TRUE, TRUE, &u4Leng); + break; + case 107: /* P2P set opps, CTWindowl */ + prP2pSpecificBssInfo->rOppPsParam.u4CTwindowMs = value; + status = + mtk_p2p_wext_set_oppps_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rOppPsParam); + break; + case 108: /* p2p_set_power_save */ + kalIoctl(prGlueInfo, + wlanoidSetP2pPowerSaveProfile, + &value, sizeof(value), FALSE, FALSE, TRUE, TRUE, &u4Leng); + + break; + + default: + break; + } + break; + default: + break; + } + + return status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_SET_STRUCT) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_struct(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + int status = 0; + UINT_32 u4SubCmd = 0; + UINT_32 u4CmdLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = NULL; + + ASSERT(prDev); + ASSERT(wrqu); + + if (GLUE_CHK_PR2(prDev, wrqu) == FALSE) + return -EINVAL; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + u4SubCmd = (UINT_32) wrqu->data.flags; + u4CmdLen = (UINT_32) wrqu->data.length; + + kalMemZero(&prGlueInfo->prP2PInfo->aucOidBuf[0], sizeof(prGlueInfo->prP2PInfo->aucOidBuf)); + + switch (u4SubCmd) { + case PRIV_CMD_OID: + if (u4CmdLen > OID_SET_GET_STRUCT_LENGTH) { + DBGLOG(P2P, ERROR, "input data length invalid %u\n", u4CmdLen); + status = -EINVAL; + break; + } + + if (copy_from_user(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), wrqu->data.pointer, u4CmdLen)) { + status = -EFAULT; + break; + } + + if (!kalMemCmp(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), extra, u4CmdLen)) + DBGLOG(P2P, INFO, "extra buffer is valid\n"); + else + DBGLOG(P2P, INFO, "extra 0x%p\n", extra); + + prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucOidBuf[0])); + switch (prP2PReq->u4CmdId) { + case P2P_CMD_ID_SEND_SD_RESPONSE: + status = mtk_p2p_wext_send_service_discovery_response(prDev, info, wrqu, (char *)prP2PReq); + break; + + case P2P_CMD_ID_SEND_SD_REQUEST: + status = mtk_p2p_wext_send_service_discovery_request(prDev, info, wrqu, (char *)prP2PReq); + break; + + case P2P_CMD_ID_TERMINATE_SD_PHASE: + status = mtk_p2p_wext_terminate_service_discovery_phase(prDev, info, wrqu, (char *)prP2PReq); + break; + + case P2P_CMD_ID_INVITATION: + if (prP2PReq->inBufferLength == sizeof(IW_P2P_IOCTL_INVITATION_STRUCT)) { + /* Do nothing */ + /* + * status = mtk_p2p_wext_invitation_request(prDev, info, wrqu, + * (char *)(prP2PReq->aucBuffer)); + */ + } + break; + + case P2P_CMD_ID_INVITATION_ABORT: + if (prP2PReq->inBufferLength == sizeof(IW_P2P_IOCTL_ABORT_INVITATION)) { + /* Do nothing */ + /* + * status = mtk_p2p_wext_invitation_abort(prDev, info, wrqu, + * (char *)(prP2PReq->aucBuffer)); + */ + } + break; + + case P2P_CMD_ID_START_FORMATION: + if (prP2PReq->inBufferLength == sizeof(IW_P2P_IOCTL_START_FORMATION)) + status = mtk_p2p_wext_start_formation(prDev, info, wrqu, (char *)(prP2PReq->aucBuffer)); + break; + default: + status = -EOPNOTSUPP; + } + + break; +#if CFG_SUPPORT_ANTI_PIRACY + case PRIV_SEC_CHECK_OID: + if (u4CmdLen > 256) { + status = -EOPNOTSUPP; + break; + } + if (copy_from_user(&(prGlueInfo->prP2PInfo->aucSecCheck[0]), wrqu->data.pointer, u4CmdLen)) { + status = -EFAULT; + break; + } + + if (!kalMemCmp(&(prGlueInfo->prP2PInfo->aucSecCheck[0]), extra, u4CmdLen)) + DBGLOG(P2P, INFO, "extra buffer is valid\n"); + else + DBGLOG(P2P, INFO, "extra 0x%p\n", extra); + prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucSecCheck[0])); + + switch (prP2PReq->u4CmdId) { + case P2P_CMD_ID_SEC_CHECK: + status = mtk_p2p_wext_set_sec_check_request(prDev, info, wrqu, (char *)prP2PReq); + break; + default: + status = -EOPNOTSUPP; + } + break; +#endif + case PRIV_CMD_P2P_VERSION: + if (u4CmdLen > OID_SET_GET_STRUCT_LENGTH) { + DBGLOG(P2P, ERROR, "input data length invalid %u\n", u4CmdLen); + status = -EINVAL; + break; + } + + if (copy_from_user(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), wrqu->data.pointer, u4CmdLen)) { + status = -EFAULT; + break; + } + + if (!kalMemCmp(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), extra, u4CmdLen)) + DBGLOG(P2P, INFO, "extra buffer is valid\n"); + else + DBGLOG(P2P, INFO, "extra 0x%p\n", extra); + + prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucOidBuf[0])); + switch (prP2PReq->u4CmdId) { + case P2P_CMD_ID_P2P_VERSION: + status = mtk_p2p_wext_set_p2p_version(prDev, info, wrqu, (char *)prP2PReq); + break; + default: + status = -EOPNOTSUPP; + break; + } + break; + default: + status = -EOPNOTSUPP; + break; + } + + return status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_GET_STRUCT) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_get_struct(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + int status = 0; + UINT_32 u4SubCmd = 0; + UINT_32 u4CmdLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = NULL; + + ASSERT(prDev); + ASSERT(wrqu); + + if (!prDev || !wrqu) { + DBGLOG(P2P, WARN, "%s(): invalid param(0x%p, 0x%p)\n", __func__, prDev, wrqu); + return -EINVAL; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + u4SubCmd = (UINT_32) wrqu->data.flags; + u4CmdLen = (UINT_32) wrqu->data.length; + + kalMemZero(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), sizeof(prGlueInfo->prP2PInfo->aucOidBuf)); + + switch (u4SubCmd) { + case PRIV_CMD_OID: + if (u4CmdLen > sizeof(IW_P2P_TRANSPORT_STRUCT)) { + DBGLOG(P2P, ERROR, "input data length invalid %u\n", u4CmdLen); + status = -EINVAL; + break; + } + + if (copy_from_user(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), + wrqu->data.pointer, sizeof(IW_P2P_TRANSPORT_STRUCT))) { + DBGLOG(P2P, ERROR, "%s() copy_from_user oidBuf fail\n", __func__); + return -EFAULT; + } + + prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucOidBuf[0])); + + switch (prP2PReq->u4CmdId) { + case P2P_CMD_ID_GET_SD_REQUEST: + status = mtk_p2p_wext_get_service_discovery_request(prDev, info, wrqu, (char *)prP2PReq); + break; + + case P2P_CMD_ID_GET_SD_RESPONSE: + status = mtk_p2p_wext_get_service_discovery_response(prDev, info, wrqu, (char *)prP2PReq); + break; + + case P2P_CMD_ID_INVITATION_INDICATE: + { + status = + mtk_p2p_wext_invitation_indicate(prDev, info, wrqu, (char *)(prP2PReq->aucBuffer)); + prP2PReq->outBufferLength = wrqu->data.length; + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + wrqu->data.length + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); + return -EIO; + } else { + return 0; + } + break; + } + case P2P_CMD_ID_INVITATION_STATUS: + { + status = + mtk_p2p_wext_invitation_status(prDev, info, wrqu, (char *)(prP2PReq->aucBuffer)); + prP2PReq->outBufferLength = wrqu->data.length; + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + wrqu->data.length + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); + return -EIO; + } else { + return 0; + } + break; + } + case P2P_CMD_ID_GET_CH_LIST: + { + UINT_16 i; + UINT_8 NumOfChannel = 50; + RF_CHANNEL_INFO_T aucChannelList[50]; + UINT_8 ucMaxChannelNum = 50; + PUINT_8 pucChnlList = (PUINT_8) prP2PReq->aucBuffer; + + kalGetChnlList(prGlueInfo, BAND_NULL, ucMaxChannelNum, &NumOfChannel, aucChannelList); + /* here must confirm NumOfChannel < 16, for prP2PReq->aucBuffer 16 byte */ + if (NumOfChannel > 15) { + /* DBGLOG(P2P, ERROR, "channel num > 15\n", __func__); */ + NumOfChannel = 15; + } + 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))) { + DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); + return -EIO; + } else { + return 0; + } + break; + } + + case P2P_CMD_ID_GET_OP_CH: + { + UINT_32 u4QueryInfoLen = 0; + + prP2PReq->inBufferLength = 4; + + status = wlanoidQueryP2pOpChannel(prGlueInfo->prAdapter, + prP2PReq->aucBuffer, + prP2PReq->inBufferLength, &u4QueryInfoLen); + prP2PReq->outBufferLength = u4QueryInfoLen; + if (status == 0) { /* WLAN_STATUS_SUCCESS */ + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + u4QueryInfoLen + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, + aucBuffer))) { + DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); + return -EIO; + } + } else { + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); + return -EIO; + } + } + break; + } + + default: + status = -EOPNOTSUPP; + } + + break; +#if CFG_SUPPORT_ANTI_PIRACY + case PRIV_SEC_CHECK_OID: + if (u4CmdLen > sizeof(IW_P2P_TRANSPORT_STRUCT)) { + status = -EINVAL; + break; + } + + if (copy_from_user(&(prGlueInfo->prP2PInfo->aucSecCheck[0]), + wrqu->data.pointer, sizeof(IW_P2P_TRANSPORT_STRUCT))) { + DBGLOG(P2P, ERROR, "%s() copy_from_user oidBuf fail\n", __func__); + return -EFAULT; + } + + prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucSecCheck[0])); + + switch (prP2PReq->u4CmdId) { + case P2P_CMD_ID_SEC_CHECK: + status = mtk_p2p_wext_get_sec_check_response(prDev, info, wrqu, (char *)prP2PReq); + break; + default: + status = -EOPNOTSUPP; + } + break; +#endif +#if 0 + case PRIV_CMD_P2P_VERSION: + if (u4CmdLen > sizeof(IW_P2P_TRANSPORT_STRUCT)) { + status = -EINVAL; + break; + } + + if (copy_from_user(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), + wrqu->data.pointer, sizeof(IW_P2P_TRANSPORT_STRUCT))) { + DBGLOG(P2P, ERROR, "%s() copy_from_user oidBuf fail\n", __func__); + return -EFAULT; + } + + prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucOidBuf[0])); + + switch (prP2PReq->u4CmdId) { + case P2P_CMD_ID_P2P_VERSION: + status = mtk_p2p_wext_get_p2p_version(prDev, info, wrqu, (char *)prP2PReq); + break; + default: + status = -EOPNOTSUPP; + break; + } + + /* Copy queried data to user. */ + if (status == 0) { /* WLAN_STATUS_SUCCESS */ + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + prP2PReq->outBufferLength + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); + return -EIO; + } + } + + else { + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); + return -EIO; + } + } + + break; +#endif + default: + DBGLOG(P2P, ERROR, "Unknown sub cmd: 0x%x\n", u4SubCmd); + return -EOPNOTSUPP; + } + + return status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* getting service discovery request frame from driver +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_get_service_discovery_request(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4QueryInfoLen = 0; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidGetP2PSDRequest, + prP2PReq->aucBuffer, prP2PReq->outBufferLength, TRUE, FALSE, TRUE, TRUE, &u4QueryInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + prP2PReq->outBufferLength = u4QueryInfoLen; + + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + u4QueryInfoLen + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); + return -EIO; + } else { + return 0; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* getting service discovery response frame from driver +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_get_service_discovery_response(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4QueryInfoLen = 0; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidGetP2PSDResponse, + prP2PReq->aucBuffer, prP2PReq->outBufferLength, TRUE, FALSE, TRUE, TRUE, &u4QueryInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + prP2PReq->outBufferLength = u4QueryInfoLen; + + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + u4QueryInfoLen + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); + return -EIO; + } + return 0; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* sending service discovery request frame +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_send_service_discovery_request(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4SetInfoLen; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSendP2PSDRequest, + prP2PReq->aucBuffer, prP2PReq->inBufferLength, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + else + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* sending service discovery response frame +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_send_service_discovery_response(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4SetInfoLen; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSendP2PSDResponse, + prP2PReq->aucBuffer, prP2PReq->inBufferLength, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + else + return 0; +} + +#if CFG_SUPPORT_ANTI_PIRACY +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_sec_check_request(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4SetInfoLen; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetSecCheckRequest, + prP2PReq->aucBuffer, prP2PReq->inBufferLength, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + else + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_get_sec_check_response(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4QueryInfoLen = 0; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + DBGLOG(P2P, INFO, "mtk_p2p_wext_get_sec_check_response\n"); + rStatus = kalIoctl(prGlueInfo, + wlanoidGetSecCheckResponse, + prP2PReq->aucBuffer, prP2PReq->outBufferLength, TRUE, FALSE, TRUE, TRUE, &u4QueryInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + prP2PReq->outBufferLength = u4QueryInfoLen; + + if (copy_to_user(wrqu->data.pointer, + prP2PReq->aucBuffer, u4QueryInfoLen + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); + return -EIO; + } + return 0; + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* terminating service discovery phase +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_terminate_service_discovery_phase(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4SetInfoLen; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetP2PTerminateSDPhase, + prP2PReq->aucBuffer, prP2PReq->inBufferLength, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + else + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_noa_param(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4SetInfoLen; + /* P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT)extra; */ + P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T prNoaParam = (P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T) extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + DBGLOG(P2P, INFO, "mtk_p2p_wext_set_noa_param\n"); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetNoaParam, prNoaParam, /* prP2PReq->aucBuffer, */ + sizeof(PARAM_CUSTOM_NOA_PARAM_STRUCT_T), /* prP2PReq->inBufferLength, */ + FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + else + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_oppps_param(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4SetInfoLen; +/* P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT)extra; */ + P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T prOppPsParam = (P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T) extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + DBGLOG(P2P, INFO, "mtk_p2p_wext_set_oppps_param\n"); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetOppPsParam, prOppPsParam, /* prP2PReq->aucBuffer, */ + sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T), /* prP2PReq->inBufferLength, */ + FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + else + return 0; +} + +int +mtk_p2p_wext_set_p2p_version(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; + UINT_32 u4SetInfoLen; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetP2pSupplicantVersion, + prP2PReq->aucBuffer, prP2PReq->inBufferLength, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + else + return rStatus; + +} + +/* mtk_p2p_wext_set_p2p_version */ + +int +mtk_p2p_wext_get_p2p_version(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4QueryInfoLen; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryP2pVersion, + prP2PReq->aucBuffer, prP2PReq->outBufferLength, TRUE, FALSE, TRUE, TRUE, &u4QueryInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + else + return rStatus; + +} /* mtk_p2p_wext_get_p2p_version */ + +#if CFG_SUPPORT_P2P_RSSI_QUERY + +int +mtk_p2p_wext_get_rssi(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4QueryInfoLen; + struct iw_point *prData = (struct iw_point *)&wrqu->data; + UINT_16 u2BufferSize = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Rssi; + struct iw_statistics *pStats = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + if (!prGlueInfo) { + rStatus = WLAN_STATUS_FAILURE; + goto stat_out; + } + + pStats = (struct iw_statistics *)(&(prGlueInfo->rP2pIwStats)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryP2pRssi, &i4Rssi, sizeof(i4Rssi), TRUE, TRUE, TRUE, TRUE, &u4QueryInfoLen); + + u2BufferSize = prData->length; + + if (u2BufferSize < sizeof(struct iw_statistics)) + return -E2BIG; + + if (copy_to_user(prData->pointer, pStats, sizeof(struct iw_statistics))) + rStatus = WLAN_STATUS_FAILURE; + +stat_out: + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + else + return rStatus; + +} /* mtk_p2p_wext_get_rssi */ + +struct iw_statistics *mtk_p2p_wext_get_wireless_stats(struct net_device *prDev) +{ + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + P_GLUE_INFO_T prGlueInfo = NULL; + struct iw_statistics *pStats = NULL; + INT_32 i4Rssi; + UINT_32 bufLen = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) + goto stat_out; + + pStats = (struct iw_statistics *)(&(prGlueInfo->rP2pIwStats)); + + if (!prDev || !netif_carrier_ok(prDev)) { + /* network not connected */ + goto stat_out; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryP2pRssi, &i4Rssi, sizeof(i4Rssi), TRUE, TRUE, TRUE, TRUE, &bufLen); + +stat_out: + return pStats; +} /* mtk_p2p_wext_get_wireless_stats */ + +#endif /* CFG_SUPPORT_P2P_RSSI_QUERY */ + +int +mtk_p2p_wext_set_txpow(IN struct net_device *prDev, + IN struct iw_request_info *prIwrInfo, IN OUT union iwreq_data *prTxPow, IN char *pcExtra) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + P_ADAPTER_T prAdapter = (P_ADAPTER_T) NULL; +#if 0 + P_MSG_P2P_FUNCTION_SWITCH_T prMsgFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) NULL; +#endif + int i4Ret = 0; + + ASSERT(prDev); + ASSERT(prTxPow); + + do { + if ((!prDev) || (!prTxPow)) { + i4Ret = -EINVAL; + break; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + + if (!prGlueInfo) { + i4Ret = -EINVAL; + break; + } + + prAdapter = prGlueInfo->prAdapter; +#if 0 + prMsgFuncSwitch = + (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(MSG_P2P_FUNCTION_SWITCH_T)); + if (!prMsgFuncSwitch) { + ASSERT(0); + return -ENOMEM; + } + + prMsgFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; + + if (prTxPow->disabled) { + /* Dissolve. */ + prMsgFuncSwitch->fgIsFuncOn = FALSE; + } else { + + /* Re-enable function. */ + prMsgFuncSwitch->fgIsFuncOn = TRUE; + } + + /* 1.3 send message */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgFuncSwitch, MSG_SEND_METHOD_BUF); +#endif + + } while (FALSE); + + return i4Ret; +} /* mtk_p2p_wext_set_txpow */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_p2p_cfg80211.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_p2p_cfg80211.c new file mode 100644 index 0000000000000..f52845f0de29b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_p2p_cfg80211.c @@ -0,0 +1,2084 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "config.h" + +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#include +#include +#include +#include +#include +#include +#include + +#include "precomp.h" +#include "gl_cfg80211.h" +#include "gl_p2p_ioctl.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wformat" +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +static BOOLEAN __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) +{ + if (channel == NULL) + return FALSE; + + DBGLOG(P2P, INFO, "channel band: %d, freq: %d\n", channel->band, channel->center_freq); + + 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: + *prChnlSco = CHNL_EXT_SCN; + break; + } + } + + return TRUE; +} + +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; + PARAM_KEY_T rKey; + const UINT_8 aucBCAddr[] = BC_MAC_ADDR; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + DBGLOG(RSN, TRACE, "mtk_p2p_cfg80211_add_key\n"); + + if (mac_addr) { + DBGLOG(RSN, TRACE, + "keyIdx = %d pairwise = %d mac = " MACSTR "\n", key_index, pairwise, + MAC2STR(mac_addr)); + } else { + DBGLOG(RSN, TRACE, "keyIdx = %d pairwise = %d null mac\n", key_index, + pairwise); + } + DBGLOG(RSN, TRACE, "Cipher = %x\n", params->cipher); + DBGLOG_MEM8(RSN, TRACE, params->key, params->key_len); + + if (params->key_len > 32) { + DBGLOG(RSN, WARN, "key_len [%d] is invalid!\n", + params->key_len); + return -EINVAL; + } + + kalMemZero(&rKey, sizeof(PARAM_KEY_T)); + + rKey.u4KeyIndex = key_index; + + if (params->cipher) { + switch (params->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + rKey.ucCipher = CIPHER_SUITE_WEP40; + break; + case WLAN_CIPHER_SUITE_WEP104: + rKey.ucCipher = CIPHER_SUITE_WEP104; + break; +#if 0 + case WLAN_CIPHER_SUITE_WEP128: + rKey.ucCipher = CIPHER_SUITE_WEP128; + break; +#endif + case WLAN_CIPHER_SUITE_TKIP: + rKey.ucCipher = CIPHER_SUITE_TKIP; + break; + case WLAN_CIPHER_SUITE_CCMP: + rKey.ucCipher = CIPHER_SUITE_CCMP; + break; +#if 0 + case WLAN_CIPHER_SUITE_GCMP: + rKey.ucCipher = CIPHER_SUITE_GCMP; + break; + case WLAN_CIPHER_SUITE_CCMP_256: + rKey.ucCipher = CIPHER_SUITE_CCMP256; + break; +#endif + case WLAN_CIPHER_SUITE_SMS4: + rKey.ucCipher = CIPHER_SUITE_WPI; + break; + + case WLAN_CIPHER_SUITE_AES_CMAC: + rKey.ucCipher = CIPHER_SUITE_BIP; + break; + default: + ASSERT(FALSE); + } + } + + + /* For BC addr case: ex: AP mode, + * driver_nl80211 will not have mac_addr + */ + if (pairwise) { + rKey.u4KeyIndex |= BIT(31); /* Tx */ + rKey.u4KeyIndex |= BIT(30); /* Pairwise */ + COPY_MAC_ADDR(rKey.arBSSID, mac_addr); + } else { + COPY_MAC_ADDR(rKey.arBSSID, aucBCAddr); + } + + /* Check if add key under AP mode */ + if (kalP2PGetRole(prGlueInfo) == 2) + rKey.u4KeyIndex |= BIT(28); /* authenticator */ + + if (params->key) { + /* rKey.aucKeyMaterial[0] = kalMemAlloc(params->key_len, VIR_MEM_TYPE); */ + kalMemCopy(rKey.aucKeyMaterial, params->key, params->key_len); + } + rKey.u4KeyLength = params->key_len; + rKey.u4Length = ((ULONG)&(((P_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)); + + DBGLOG(P2P, INFO, "--> %s()\n", __func__); + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + i4Rslt = 0; + return i4Rslt; + } + + kalMemZero(&prRemoveKey, sizeof(PARAM_REMOVE_KEY_T)); + if (mac_addr) + memcpy(prRemoveKey.arBSSID, mac_addr, PARAM_MAC_ADDR_LEN); + prRemoveKey.u4KeyIndex = key_index; + prRemoveKey.u4Length = sizeof(PARAM_REMOVE_KEY_T); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRemoveP2PKey, + &prRemoveKey, prRemoveKey.u4Length, FALSE, FALSE, TRUE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_SUCCESS) + i4Rslt = 0; + + return i4Rslt; +} + +int +mtk_p2p_cfg80211_set_default_key(struct wiphy *wiphy, + struct net_device *netdev, u8 key_index, bool unicast, bool multicast) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* not implemented yet */ + + return WLAN_STATUS_SUCCESS; +} + +int mtk_p2p_cfg80211_set_mgmt_key(struct wiphy *wiphy, struct net_device *dev +, u8 key_index) +{ + DBGLOG(RSN, INFO, "mtk_p2p_cfg80211_set_mgmt_key, kid:%d\n", key_index); + + return 0; +} + +int mtk_p2p_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, + const u8 *mac, struct station_info *sinfo) +{ + INT_32 i4RetRslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + P_GL_P2P_INFO_T prP2pGlueInfo = (P_GL_P2P_INFO_T) NULL; + P2P_STATION_INFO_T rP2pStaInfo; + + ASSERT(wiphy); + + do { + if ((wiphy == NULL) || (ndev == NULL) || (sinfo == NULL) || (mac == NULL)) + break; + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_get_station\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + prP2pGlueInfo = prGlueInfo->prP2PInfo; + + sinfo->filled = 0; + + /* Get station information. */ + /* 1. Inactive time? */ + p2pFuncGetStationInfo(prGlueInfo->prAdapter, (PUINT_8)mac, &rP2pStaInfo); + + /* Inactive time. */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME); +#else + sinfo->filled |= STATION_INFO_INACTIVE_TIME; +#endif + sinfo->inactive_time = rP2pStaInfo.u4InactiveTime; + sinfo->generation = prP2pGlueInfo->i4Generation; + + i4RetRslt = 0; + } while (FALSE); + + return i4RetRslt; +} + +int mtk_p2p_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + P_GL_P2P_INFO_T prP2pGlueInfo = (P_GL_P2P_INFO_T) NULL; + P_MSG_P2P_SCAN_REQUEST_T prMsgScanRequest = (P_MSG_P2P_SCAN_REQUEST_T) NULL; + UINT_32 u4MsgSize = 0, u4Idx = 0; + INT_32 i4RetRslt = -EINVAL; + P_RF_CHANNEL_INFO_T prRfChannelInfo = (P_RF_CHANNEL_INFO_T) NULL; + P_P2P_SSID_STRUCT_T prSsidStruct = (P_P2P_SSID_STRUCT_T) NULL; + struct ieee80211_channel *prChannel = NULL; + struct cfg80211_ssid *prSsid = NULL; + + /* [---------Channel---------] [---------SSID---------][---------IE---------] */ + + 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, INFO, "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) { + DBGLOG(P2P, TRACE, "Allocate MsgScanRequest failed\n"); + prP2pGlueInfo->prScanRequest = NULL; + i4RetRslt = -ENOMEM; + break; + } + + DBGLOG(P2P, TRACE, "Generating scan request message.\n"); + + prMsgScanRequest->rMsgHdr.eMsgId = MID_MNY_P2P_DEVICE_DISCOVERY; + + DBGLOG(P2P, INFO, "Requesting channel number:%d.\n", request->n_channels); + + for (u4Idx = 0; u4Idx < request->n_channels; u4Idx++) { + /* Translate Freq from MHz to channel number. */ + prRfChannelInfo = &(prMsgScanRequest->arChannelListInfo[u4Idx]); + prChannel = request->channels[u4Idx]; + + prRfChannelInfo->ucChannelNum = nicFreq2ChannelNum(prChannel->center_freq * 1000); + DBGLOG(P2P, TRACE, "Scanning Channel: %d, freq: %d\n", + prRfChannelInfo->ucChannelNum, prChannel->center_freq); + switch (prChannel->band) { + case 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 (prSsidStruct) { + if (request->n_ssids) { + ASSERT((ULONG) prSsidStruct == (ULONG)&(prMsgScanRequest->arChannelListInfo[u4Idx])); + prMsgScanRequest->prSSID = prSsidStruct; + } + + for (u4Idx = 0; u4Idx < request->n_ssids; u4Idx++) { + COPY_SSID(prSsidStruct->aucSsid, + prSsidStruct->ucSsidLen, request->ssids->ssid, request->ssids->ssid_len); + + prSsidStruct++; + prSsid++; + } + + prMsgScanRequest->i4SsidNum = request->n_ssids; + + DBGLOG(P2P, TRACE, "Finish SSID list:%d.\n", request->n_ssids); + + /* IE BUFFERS */ + prMsgScanRequest->pucIEBuf = (PUINT_8) prSsidStruct; + if (request->ie_len) { + kalMemCopy(prMsgScanRequest->pucIEBuf, request->ie, request->ie_len); + prMsgScanRequest->u4IELen = request->ie_len; + } + } + + DBGLOG(P2P, TRACE, "Finish IE Buffer.\n"); + + 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 */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for abort an ongoing scan. The driver shall + * indicate the status of the scan through cfg80211_scan_done() + * + * @param wiphy - pointer of wireless hardware description + * wdev - pointer of wireless device state + * + */ +/*----------------------------------------------------------------------------*/ +void mtk_p2p_cfg80211_abort_scan(struct wiphy *wiphy, struct wireless_dev *wdev) +{ + UINT_32 u4SetInfoLen = 0; + WLAN_STATUS rStatus; + P_GLUE_INFO_T prGlueInfo = NULL; + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_abort_scan\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidAbortP2pScan, + NULL, 1, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, ERROR, "mtk_p2p_cfg80211_abort_scan fail 0x%x\n", rStatus); +} + +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, INFO, "mtk_p2p_cfg80211_set_wiphy_params\n"); + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (changed & WIPHY_PARAM_RETRY_SHORT) { + /* TODO: */ + DBGLOG(P2P, TRACE, "The RETRY short param is changed.\n"); + } + + if (changed & WIPHY_PARAM_RETRY_LONG) { + /* TODO: */ + DBGLOG(P2P, TRACE, "The RETRY long param is changed.\n"); + } + + if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { + /* TODO: */ + DBGLOG(P2P, TRACE, "The RETRY fragmentation threshold is changed.\n"); + } + + if (changed & WIPHY_PARAM_RTS_THRESHOLD) { + /* TODO: */ + DBGLOG(P2P, TRACE, "The RETRY RTS threshold is changed.\n"); + } + + if (changed & WIPHY_PARAM_COVERAGE_CLASS) { + /* TODO: */ + DBGLOG(P2P, TRACE, "The coverage class is changed???\n"); + } + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_set_wiphy_params */ + +int mtk_p2p_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ibss_params *params) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* not implemented yet */ + + return -EINVAL; +} + +int mtk_p2p_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* not implemented yet */ + + return -EINVAL; +} + +int mtk_p2p_cfg80211_set_txpower(struct wiphy *wiphy, + struct wireless_dev *wdev, + enum nl80211_tx_power_setting type, int mbm) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* not implemented yet */ + + return -EINVAL; +} + +int mtk_p2p_cfg80211_get_txpower(struct wiphy *wiphy, + struct wireless_dev *wdev, + int *dbm) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* not implemented yet */ + + return -EINVAL; +} + +int mtk_p2p_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, bool enabled, int timeout) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 value; + UINT_32 u4Leng; + + ASSERT(wiphy); + + if (enabled) + value = 2; + else + value = 0; + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_set_power_mgmt ps=%d.\n", enabled); + + /* p2p_set_power_save */ + kalIoctl(prGlueInfo, wlanoidSetP2pPowerSaveProfile, &value, sizeof(value), FALSE, FALSE, TRUE, TRUE, &u4Leng); + return 0; +} + +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; + + do { + if ((wiphy == NULL) || (settings == NULL)) + break; + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_start_ap.\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* switch netif on */ + netif_carrier_on(dev); + + mtk_p2p_cfg80211_set_channel(wiphy, &settings->chandef); + + 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 = pucBuffer + settings->beacon.head_len; + } else { + prP2pBcnUpdateMsg->u4BcnHdrLen = 0; + + prP2pBcnUpdateMsg->pucBcnHdr = NULL; + } + + if (settings->beacon.tail_len != 0) { + kalMemCopy(pucBuffer, settings->beacon.tail, settings->beacon.tail_len); + + prP2pBcnUpdateMsg->u4BcnBodyLen = settings->beacon.tail_len; + + prP2pBcnUpdateMsg->pucBcnBody = pucBuffer; + } 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->u4BcnInterval = settings->beacon_interval; + + prP2pStartAPMsg->u4DtimPeriod = settings->dtim_period; + + COPY_SSID(prP2pStartAPMsg->aucSsid, prP2pStartAPMsg->u2SsidLen, settings->ssid, settings->ssid_len); + + prP2pStartAPMsg->ucHiddenSsidType = settings->hidden_ssid; + + prP2pStartAPMsg->fgIsPrivacy = settings->privacy; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prP2pStartAPMsg, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + +#if CFG_SPM_WORKAROUND_FOR_HOTSPOT + if (glIsChipNeedWakelock(prGlueInfo)) + KAL_WAKE_LOCK(prGlueInfo->prAdapter, prGlueInfo->prAdapter->rApWakeLock); +#endif + + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_start_ap */ + +int mtk_p2p_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_beacon_data *beacon) +{ + 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) || (beacon == NULL)) + break; + + DBGLOG(P2P, INFO, "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) + + beacon->head_len + beacon->tail_len)); + + if (prP2pBcnUpdateMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prP2pBcnUpdateMsg->rMsgHdr.eMsgId = MID_MNY_P2P_BEACON_UPDATE; + pucBuffer = prP2pBcnUpdateMsg->aucBuffer; + + if (beacon->head_len != 0) { + kalMemCopy(pucBuffer, beacon->head, beacon->head_len); + + prP2pBcnUpdateMsg->u4BcnHdrLen = beacon->head_len; + + prP2pBcnUpdateMsg->pucBcnHdr = pucBuffer; + + pucBuffer = pucBuffer + beacon->head_len; + } else { + prP2pBcnUpdateMsg->u4BcnHdrLen = 0; + + prP2pBcnUpdateMsg->pucBcnHdr = NULL; + } + + if (beacon->tail_len != 0) { + kalMemCopy(pucBuffer, beacon->tail, beacon->tail_len); + + prP2pBcnUpdateMsg->u4BcnBodyLen = beacon->tail_len; + + prP2pBcnUpdateMsg->pucBcnBody = pucBuffer; + } else { + prP2pBcnUpdateMsg->u4BcnBodyLen = 0; + + prP2pBcnUpdateMsg->pucBcnBody = NULL; + } +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP + if (beacon->proberesp_ies) { + prP2pBcnUpdateMsg->pucProbeRsp = kalMemAlloc(beacon->proberesp_ies_len, VIR_MEM_TYPE); + if (!prP2pBcnUpdateMsg->pucProbeRsp) + return -ENOMEM; + prP2pBcnUpdateMsg->u4ProbeRsp_len = beacon->proberesp_ies_len; + kalMemCopy(prP2pBcnUpdateMsg->pucProbeRsp, beacon->proberesp_ies, beacon->proberesp_ies_len); + } +#endif + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prP2pBcnUpdateMsg, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_change_beacon */ + +UINT_32 +mtk_oid_stop_ap_role(P_ADAPTER_T prAdapter, void *pvSetBuffer, + UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + unsigned char u4Idx = 0; + + if ((prAdapter == NULL) || (pvSetBuffer == NULL) + || (pu4SetInfoLen == NULL)) + return WLAN_STATUS_FAILURE; + + *pu4SetInfoLen = sizeof(unsigned char); + if (u4SetBufferLen < sizeof(unsigned char)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + u4Idx = *(unsigned char *) pvSetBuffer; + + DBGLOG(INIT, TRACE, "ucRoleIdx = %d\n", u4Idx); + + p2pFsmRunEventStopAP(prAdapter, NULL); + + DBGLOG(INIT, INFO, "done, ucRoleIdx = %d\n", u4Idx); + + return 0; + +} + +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; + + unsigned char u4Idx = 0; + UINT_32 rStatus; + UINT_32 u4BufLen; + + do { + if (wiphy == NULL) + break; + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_stop_ap.\n"); + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + if (prGlueInfo == NULL) + break; + + rStatus = kalIoctl(prGlueInfo, + mtk_oid_stop_ap_role, &u4Idx, + sizeof(unsigned char), + FALSE, FALSE, TRUE, TRUE, + &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, ERROR, "stop ap fail 0x%x\n", rStatus); + + i4Rslt = 0; +#if CFG_SPM_WORKAROUND_FOR_HOTSPOT + if (glIsChipNeedWakelock(prGlueInfo)) + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, prGlueInfo->prAdapter->rApWakeLock); +#endif + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_stop_ap */ + +/* TODO: */ +int mtk_p2p_cfg80211_deauth(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_deauth_request *req) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* not implemented yet */ + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_deauth.\n"); + + return -EINVAL; +} /* mtk_p2p_cfg80211_deauth */ + +/* TODO: */ +int mtk_p2p_cfg80211_disassoc(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_disassoc_request *req) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_disassoc.\n"); + + /* not implemented yet */ + + return -EINVAL; +} /* mtk_p2p_cfg80211_disassoc */ + +int mtk_p2p_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, + unsigned int duration, u64 *cookie) +{ + INT_32 i4Rslt = -EINVAL; + ULONG timeout = 0; + 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 prChnlReqMsg = (P_MSG_P2P_CHNL_REQUEST_T) NULL; + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T)NULL; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + + do { + if ((wiphy == NULL) || (wdev == NULL) || (chan == NULL) || (cookie == NULL)) + break; + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + prGlueP2pInfo = prGlueInfo->prP2PInfo; + prP2pFsmInfo = prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo; + prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); + + *cookie = prGlueP2pInfo->u8Cookie++; + + prChnlReqMsg = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_CHNL_REQUEST_T)); + + if (prChnlReqMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_remain_on_channel, cookie: 0x%llx\n", *cookie); + + prChnlReqMsg->rMsgHdr.eMsgId = MID_MNY_P2P_CHNL_REQ; + prChnlReqMsg->u8Cookie = *cookie; + prChnlReqMsg->u4Duration = duration; + + __channel_format_switch(chan, NL80211_CHAN_HT20, /* 4 KH Need Check */ + &prChnlReqMsg->rChannelInfo, &prChnlReqMsg->eChnlSco); + reinit_completion(&prGlueInfo->rP2pReq); + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prChnlReqMsg, MSG_SEND_METHOD_BUF); + + /* + * Need wait until firmare grant channel to sync with supplicant, + * wait 2HZ to avoid grant channel takes too long or failed + */ + timeout = wait_for_completion_timeout(&prGlueInfo->rP2pReq, msecs_to_jiffies(2000)); + if (timeout == 0) { + DBGLOG(P2P, INFO, "Request channel timeout(2HZ)\n"); + /* + * Throw out remain/cancel on request channel to + * simulate this channel request has been success + */ + kalP2PIndicateChannelReady(prGlueInfo, + prChnlReqInfo->u8Cookie, + prChnlReqInfo->ucReqChnlNum, + prChnlReqInfo->eBand, + prChnlReqInfo->eChnlSco, + prChnlReqInfo->u4MaxInterval); + /* Indicate channel return. */ + kalP2PIndicateChannelExpired(prGlueInfo, &prP2pFsmInfo->rChnlReqInfo); + + /* Return Channel */ + p2pFuncReleaseCh(prGlueInfo->prAdapter, &(prP2pFsmInfo->rChnlReqInfo)); + } + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} + +/* mtk_p2p_cfg80211_remain_on_channel */ +int mtk_p2p_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie) +{ + INT_32 i4Rslt = -EINVAL; + ULONG timeout = 0; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + P_MSG_P2P_CHNL_ABORT_T prMsgChnlAbort = (P_MSG_P2P_CHNL_ABORT_T) NULL; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)NULL; + + do { + if ((wiphy == NULL) || (wdev == NULL)) + break; + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + prP2pFsmInfo = prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo; + + prMsgChnlAbort = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_CHNL_ABORT_T)); + + if (prMsgChnlAbort == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_cancel_remain_on_channel, cookie: 0x%llx\n", cookie); + + prMsgChnlAbort->rMsgHdr.eMsgId = MID_MNY_P2P_CHNL_ABORT; + prMsgChnlAbort->u8Cookie = cookie; + reinit_completion(&prGlueInfo->rP2pReq); + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChnlAbort, MSG_SEND_METHOD_BUF); + timeout = wait_for_completion_timeout(&prGlueInfo->rP2pReq, msecs_to_jiffies(2000)); + if (timeout == 0) { + DBGLOG(P2P, INFO, "Cancel remain on channel timeout(2HZ)\n"); + /* Indicate channel return. */ + kalP2PIndicateChannelExpired(prGlueInfo, &prP2pFsmInfo->rChnlReqInfo); + + /* Return Channel */ + p2pFuncReleaseCh(prGlueInfo->prAdapter, &(prP2pFsmInfo->rChnlReqInfo)); + } + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_cancel_remain_on_channel */ + +int mtk_p2p_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + INT_32 i4Rslt = -EINVAL; + struct _MSG_P2P_EXTEND_LISTEN_INTERVAL_T *prMsgExtListenReq = NULL; + ULONG timeout = 0; + 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; + UINT_32 u4OriRegValue = 0; + UINT_32 u4NextRegValue = 0; + + DBGLOG(P2P, TRACE, "--> %s() ext list,wait :%d\n" + , __func__, params->wait); + + do { + if ((wiphy == NULL) || (wdev == NULL) || (params == 0) || (cookie == NULL)) + break; + /* DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_mgmt_tx\n")); */ + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + *cookie = prGlueP2pInfo->u8Cookie++; + + /* Channel & Channel Type & Wait time are ignored. */ + prMsgTxReq = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_MGMT_TX_REQUEST_T)); + + if (prMsgTxReq == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + /* Here need to extend the listen interval */ + prMsgExtListenReq = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct _MSG_P2P_EXTEND_LISTEN_INTERVAL_T)); + if (prMsgExtListenReq) { + prMsgExtListenReq->rMsgHdr.eMsgId = MID_MNY_P2P_EXTEND_LISTEN_INTERVAL; + prMsgExtListenReq->wait = params->wait; + DBGLOG(P2P, TRACE, "ext listen, wait: %d\n", prMsgExtListenReq->wait); + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T)prMsgExtListenReq, + MSG_SEND_METHOD_BUF); + } + + prMsgTxReq->fgNoneCckRate = FALSE; + prMsgTxReq->fgIsWaitRsp = TRUE; + + prMgmtFrame = cnmMgtPktAlloc(prGlueInfo->prAdapter, (UINT_32) (params->len + MAC_TX_RESERVED_FIELD)); + + prMsgTxReq->prMgmtMsduInfo = prMgmtFrame; + if (prMsgTxReq->prMgmtMsduInfo == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMgmtFrame->u8Cookie = *cookie; + prMsgTxReq->rMsgHdr.eMsgId = MID_MNY_P2P_MGMT_TX; + + pucFrameBuf = (PUINT_8) ((ULONG) prMgmtFrame->prPacket + MAC_TX_RESERVED_FIELD); + + kalMemCopy(pucFrameBuf, params->buf, params->len); + + prMgmtFrame->u2FrameLength = params->len; + reinit_completion(&prGlueInfo->rP2pReq); + + /*record MailBox2*/ + HAL_MCR_RD(prGlueInfo->prAdapter, MCR_D2HRM2R, &u4OriRegValue); + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgTxReq, MSG_SEND_METHOD_BUF); + + timeout = wait_for_completion_timeout(&prGlueInfo->rP2pReq, msecs_to_jiffies(2000)); + if (timeout == 0) { + DBGLOG(P2P, INFO, "wait mgmt tx done timeout cookie 0x%llx and mgmt_tx status: false\n", + *cookie); + + /* Indicate mgmt_tx status return. */ + if (prMgmtFrame != NULL) { + if (prMgmtFrame->prPacket != NULL) { + kalP2PIndicateMgmtTxStatus(prGlueInfo, + *cookie, + false, + prMgmtFrame->prPacket, + (UINT_32) prMgmtFrame->u2FrameLength); + } + } + /*dump mailbox info from FW*/ + HAL_MCR_RD(prGlueInfo->prAdapter, MCR_D2HRM2R, &u4NextRegValue); + + DBGLOG(P2P, WARN, " MCR_D2HRM2R = 0x%x, ORI_MCR_D2HRM2R = 0x%x\n", + u4NextRegValue, u4OriRegValue); + } + + 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)); + + DBGLOG(P2P, INFO, "--> %s() CTS:%d,ShortPramble:%d\n" + , __func__, params->use_cts_prot, params->use_short_preamble); + + 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 */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, struct station_del_parameters *params) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_P2P_CONNECTION_ABORT_T prDisconnectMsg = (P_MSG_P2P_CONNECTION_ABORT_T) NULL; + UINT_8 aucBcMac[] = BC_MAC_ADDR; + const UINT_8 *mac = NULL; + + do { + if ((wiphy == NULL) || (dev == NULL)) + break; + + if (params->mac == NULL) + mac = aucBcMac; + else + mac = params->mac; + + 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); + if (params->reason_code == 0) + prDisconnectMsg->u2ReasonCode = REASON_CODE_DEAUTH_LEAVING_BSS; + else + prDisconnectMsg->u2ReasonCode = params->reason_code; + prDisconnectMsg->fgSendDeauth = TRUE; + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_del_station ReasonCode = %d\n", prDisconnectMsg->u2ReasonCode); + + 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 */ +#else +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, const u8 *mac) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_P2P_CONNECTION_ABORT_T prDisconnectMsg = (P_MSG_P2P_CONNECTION_ABORT_T) NULL; + UINT_8 aucBcMac[] = BC_MAC_ADDR; + + do { + if ((wiphy == NULL) || (dev == NULL)) + break; + + if (mac == NULL) + mac = aucBcMac; + + 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); +#if CFG_TC10_FEATURE + prDisconnectMsg->u2ReasonCode = REASON_CODE_DEAUTH_LEAVING_BSS; +#else + prDisconnectMsg->u2ReasonCode = REASON_CODE_UNSPECIFIED; +#endif + prDisconnectMsg->fgSendDeauth = TRUE; + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_del_station ReasonCode = %d\n", prDisconnectMsg->u2ReasonCode); + + 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 */ +#endif + +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, INFO, "mtk_p2p_cfg80211_connect.\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + prConnReqMsg = + (P_MSG_P2P_CONNECTION_REQUEST_T) cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + (sizeof(MSG_P2P_CONNECTION_REQUEST_T) + sme->ie_len)); + + if (prConnReqMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prConnReqMsg->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_REQ; + + COPY_SSID(prConnReqMsg->rSsid.aucSsid, prConnReqMsg->rSsid.ucSsidLen, sme->ssid, sme->ssid_len); + + COPY_MAC_ADDR(prConnReqMsg->aucBssid, sme->bssid); + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_connect to %pM, IE len: %zu\n", + prConnReqMsg->aucBssid, sme->ie_len); + + DBGLOG(P2P, TRACE, "Assoc Req IE Buffer Length:%zu\n", sme->ie_len); + kalMemCopy(prConnReqMsg->aucIEBuf, sme->ie, sme->ie_len); + prConnReqMsg->u4IELen = sme->ie_len; + + __channel_format_switch(sme->channel, NL80211_CHAN_NO_HT, + &prConnReqMsg->rChannelInfo, &prConnReqMsg->eChnlSco); + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prConnReqMsg, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_connect */ + +int mtk_p2p_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code) +{ + INT_32 i4Rslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_MSG_P2P_CONNECTION_ABORT_T prDisconnMsg = (P_MSG_P2P_CONNECTION_ABORT_T) NULL; + UINT_8 aucBCAddr[] = BC_MAC_ADDR; + + do { + if ((wiphy == NULL) || (dev == NULL)) + break; + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_disconnect.\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + +/* prDisconnMsg = (P_MSG_P2P_CONNECTION_ABORT_T)kalMemAlloc(sizeof(P_MSG_P2P_CONNECTION_ABORT_T), VIR_MEM_TYPE); */ + prDisconnMsg = + (P_MSG_P2P_CONNECTION_ABORT_T) cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(MSG_P2P_CONNECTION_ABORT_T)); + + if (prDisconnMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_disconnect.Allocate Memory Failed.\n"); + break; + } + + prDisconnMsg->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT; + prDisconnMsg->u2ReasonCode = reason_code; + prDisconnMsg->fgSendDeauth = TRUE; + COPY_MAC_ADDR(prDisconnMsg->aucTargetID, aucBCAddr); + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prDisconnMsg, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_disconnect */ +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_change_iface(IN struct wiphy *wiphy, + IN struct net_device *ndev, + IN enum nl80211_iftype type, IN struct vif_params *params) +#else +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) +#endif +{ + 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, INFO, "mtk_p2p_cfg80211_change_iface. type: %d\n", type); + + 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"); + prSwitchModeMsg->eIftype = IFTYPE_P2P_CLIENT; + /* This case need to fall through */ + case NL80211_IFTYPE_STATION: + if (type == NL80211_IFTYPE_STATION) { + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_STATION.\n"); + prSwitchModeMsg->eIftype = IFTYPE_STATION; + } + prSwitchModeMsg->eOpMode = OP_MODE_INFRASTRUCTURE; + break; + case NL80211_IFTYPE_AP: + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_AP.\n"); + prSwitchModeMsg->eIftype = IFTYPE_AP; + /* This case need to fall through */ + case NL80211_IFTYPE_P2P_GO: + if (type == NL80211_IFTYPE_P2P_GO) { + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_P2P_GO not AP.\n"); + prSwitchModeMsg->eIftype = IFTYPE_P2P_GO; + } + prSwitchModeMsg->eOpMode = OP_MODE_ACCESS_POINT; + break; + default: + DBGLOG(P2P, TRACE, "Other type :%d .\n", type); + prSwitchModeMsg->eOpMode = OP_MODE_P2P_DEVICE; + prSwitchModeMsg->eIftype = IFTYPE_P2P_DEVICE; + break; + } + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prSwitchModeMsg, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_change_iface */ + +int mtk_p2p_cfg80211_set_channel(IN struct wiphy *wiphy, struct cfg80211_chan_def *chandef) +{ + INT_32 i4Rslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + RF_CHANNEL_INFO_T rRfChnlInfo = {0, 0}; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = NULL; + + do { + if (wiphy == NULL) + break; + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_set_channel.\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + __channel_format_switch(chandef->chan, 0, &rRfChnlInfo, NULL); + + prP2pConnSettings = prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings; + prP2pConnSettings->ucOperatingChnl = rRfChnlInfo.ucChannelNum; + prP2pConnSettings->eBand = rRfChnlInfo.eBand; + + 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, INFO, "mtk_p2p_cfg80211_set_bitrate_mask\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* TODO: Set bitrate mask of the peer? */ + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_set_bitrate_mask */ + +void mtk_p2p_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, + struct wireless_dev *wdev, + IN u16 frame_type, IN bool reg) +{ +#if 0 + P_MSG_P2P_MGMT_FRAME_REGISTER_T prMgmtFrameRegister = (P_MSG_P2P_MGMT_FRAME_REGISTER_T) NULL; +#endif + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + + do { + if ((wiphy == NULL) || (wdev == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_mgmt_frame_register\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + switch (frame_type) { + case MAC_FRAME_PROBE_REQ: + if (reg) { + prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter |= PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(P2P, TRACE, "Open packet filer probe request\n"); + } else { + prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter &= ~PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(P2P, TRACE, "Close packet filer probe request\n"); + } + break; + case MAC_FRAME_ACTION: + if (reg) { + prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter |= PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(P2P, TRACE, "Open packet filer action frame.\n"); + } else { + prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter &= ~PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(P2P, TRACE, "Close packet filer action frame.\n"); + } + break; +#if CFG_SUPPORT_SOFTAP_WPA3 + case MAC_FRAME_AUTH: + if (reg) { + prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter + |= PARAM_PACKET_FILTER_AUTH; + DBGLOG(P2P, TRACE, "Open packet filer auth request\n"); + } else { + prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter + &= ~PARAM_PACKET_FILTER_AUTH; + DBGLOG(P2P, TRACE, "Close packet filer auth request\n"); + } + break; + case MAC_FRAME_ASSOC_REQ: + if (reg) { + prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter + |= PARAM_PACKET_FILTER_ASSOC_REQ; + DBGLOG(P2P, TRACE, "Open packet filer assoc request\n"); + } else { + prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter + &= ~PARAM_PACKET_FILTER_ASSOC_REQ; + DBGLOG(P2P, TRACE, "Close packet filer assoc request\n"); + } + break; +#endif + default: + DBGLOG(P2P, ERROR, "Ask frog to add code for mgmt:%x\n", frame_type); + break; + } + + if ((prGlueInfo->prAdapter != NULL) && (prGlueInfo->prAdapter->fgIsP2PRegistered == TRUE)) { + + /* prGlueInfo->u4Flag |= GLUE_FLAG_FRAME_FILTER; */ + set_bit(GLUE_FLAG_FRAME_FILTER_BIT, &prGlueInfo->ulFlag); + + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + + if (in_interrupt()) + DBGLOG(P2P, TRACE, "It is in interrupt level\n"); + } +#if 0 + + prMgmtFrameRegister = (P_MSG_P2P_MGMT_FRAME_REGISTER_T) cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + sizeof + (MSG_P2P_MGMT_FRAME_REGISTER_T)); + + if (prMgmtFrameRegister == NULL) { + ASSERT(FALSE); + break; + } + + prMgmtFrameRegister->rMsgHdr.eMsgId = MID_MNY_P2P_MGMT_FRAME_REGISTER; + + prMgmtFrameRegister->u2FrameType = frame_type; + prMgmtFrameRegister->fgIsRegister = reg; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMgmtFrameRegister, MSG_SEND_METHOD_BUF); + +#endif + + } while (FALSE); + +} /* mtk_p2p_cfg80211_mgmt_frame_register */ + +#if CONFIG_NL80211_TESTMODE +int mtk_p2p_cfg80211_testmode_cmd(IN struct wiphy *wiphy, IN struct wireless_dev *wdev, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_TEST_PARAMS prParams = NULL; + INT_32 i4Status = -EINVAL; + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + DBGLOG(P2P, INFO, "--> %s()\n", __func__); + + if (data && len) { + prParams = (P_NL80211_DRIVER_TEST_PARAMS) data; + } else { + DBGLOG(P2P, ERROR, "data is NULL\n"); + return i4Status; + } + + if (prParams->index >> 24 == 0x01) { + /* New version */ + prParams->index = prParams->index & ~BITS(24, 31); + } else { + /* Old version */ + i4Status = mtk_p2p_cfg80211_testmode_p2p_sigma_pre_cmd(wiphy, data, len); + return i4Status; + } + + switch (prParams->index) { + case 1: /* P2P Simga */ +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION + { + P_NL80211_DRIVER_SW_CMD_PARAMS prParamsCmd; + + prParamsCmd = (P_NL80211_DRIVER_SW_CMD_PARAMS) data; + + if ((prParamsCmd->adr & 0xffff0000) == 0xffff0000) { + i4Status = mtk_p2p_cfg80211_testmode_sw_cmd(wiphy, data, len); + break; + } + } +#endif + i4Status = mtk_p2p_cfg80211_testmode_p2p_sigma_cmd(wiphy, data, len); + break; +#if CFG_SUPPORT_WFD + case 2: /* WFD */ + i4Status = mtk_p2p_cfg80211_testmode_wfd_update_cmd(wiphy, data, len); + break; +#endif + case 3: /* Hotspot Client Management */ + i4Status = mtk_p2p_cfg80211_testmode_hotspot_block_cmd(wiphy, data, len); + break; + case 0x10: + i4Status = mtk_cfg80211_testmode_get_sta_statistics(wiphy, data, len, prGlueInfo); + break; + case 0x11: /*NFC Beam + Indication */ + prChnlReqInfo = &prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rChnlReqInfo; + if (data && len) { + P_NL80211_DRIVER_SET_NFC_PARAMS prParams = (P_NL80211_DRIVER_SET_NFC_PARAMS) data; + + prChnlReqInfo->NFC_BEAM = prParams->NFC_Enable; + DBGLOG(P2P, INFO, "NFC: BEAM[%d]\n", prChnlReqInfo->NFC_BEAM); + } + break; + case 0x12: /*NFC Beam + Indication */ + DBGLOG(P2P, INFO, "NFC: Polling\n"); + i4Status = mtk_cfg80211_testmode_get_scan_done(wiphy, data, len, prGlueInfo); + break; + case TESTMODE_CMD_ID_STR_CMD: + i4Status = mtk_cfg80211_process_str_cmd(prGlueInfo, (PUINT_8)(prParams + 1), + len - sizeof(*prParams)); + break; + case TESTMODE_CMD_ID_HS_CONFIG: + i4Status = mtk_p2p_cfg80211_testmode_hotspot_config_cmd(wiphy, data, len); + break; + default: + i4Status = -EINVAL; + break; + } + + DBGLOG(P2P, TRACE, "prParams->index=%d, status=%d\n", prParams->index, i4Status); + + return i4Status; +} + +int mtk_p2p_cfg80211_testmode_hotspot_config_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + struct NL80211_DRIVER_HOTSPOT_CONFIG_PARAMS *prParams = (struct NL80211_DRIVER_HOTSPOT_CONFIG_PARAMS *) NULL; + UINT_32 index; + UINT_32 value; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (data && len) { + prParams = (struct NL80211_DRIVER_HOTSPOT_CONFIG_PARAMS *) data; + } else { + DBGLOG(P2P, ERROR, "data is NULL or len is 0\n"); + return -EINVAL; + } + + index = prParams->idx; + value = prParams->value; + + DBGLOG(P2P, INFO, "NL80211_ATTR_TESTDATA, idx=%d value=%d\n", + (UINT_32) prParams->idx, (UINT_32) prParams->value); + + switch (index) { + case 1: /* Max Clients */ + kalP2PSetMaxClients(prGlueInfo, value); + break; + default: + break; + } + + return 0; +} + +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, INFO, "mtk_p2p_cfg80211_testmode_p2p_sigma_pre_cmd\n"); + + if (data && len) + memcpy(&rParams, data, len); + + DBGLOG(P2P, TRACE, "NL80211_ATTR_TESTDATA,idx_mode=%d idx=%d value=%u\n", + (INT_16) rParams.idx_mode, (INT_16) rParams.idx, rParams.value); + + index_mode = rParams.idx_mode; + index = rParams.idx; + value = rParams.value; + + switch (index) { + case 0: /* Listen CH */ + break; + case 1: /* P2p mode */ + break; + case 4: /* Noa duration */ + prP2pSpecificBssInfo->rNoaParam.u4NoaDurationMs = value; + /* only to apply setting when setting NOA count */ + /* status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); */ + break; + case 5: /* Noa interval */ + prP2pSpecificBssInfo->rNoaParam.u4NoaIntervalMs = value; + /* only to apply setting when setting NOA count */ + /* status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); */ + break; + case 6: /* Noa count */ + prP2pSpecificBssInfo->rNoaParam.u4NoaCount = value; + /* status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); */ + break; + case 100: /* Oper CH */ + /* 20110920 - frog: User configurations are placed in ConnSettings. */ + /* prP2pConnSettings->ucOperatingChnl = value; */ + break; + case 101: /* Local config Method, for P2P SDK */ + prP2pConnSettings->u2LocalConfigMethod = value; + break; + case 102: /* Sigma P2p reset */ + /* kalMemZero(prP2pConnSettings->aucTargetDevAddr, MAC_ADDR_LEN); */ + /* prP2pConnSettings->eConnectionPolicy = ENUM_P2P_CONNECTION_POLICY_AUTO; */ + p2pFsmUninit(prGlueInfo->prAdapter); + p2pFsmInit(prGlueInfo->prAdapter); + break; + case 103: /* WPS MODE */ + kalP2PSetWscMode(prGlueInfo, value); + break; + case 104: /* P2p send persence, duration */ + break; + case 105: /* P2p send persence, interval */ + break; + case 106: /* P2P set sleep */ + value = 1; + kalIoctl(prGlueInfo, + wlanoidSetP2pPowerSaveProfile, &value, sizeof(value), FALSE, FALSE, TRUE, TRUE, &u4Leng); + break; + case 107: /* P2P set opps, CTWindowl */ + prP2pSpecificBssInfo->rOppPsParam.u4CTwindowMs = value; + /* status = mtk_p2p_wext_set_oppps_param(prDev,info,wrqu,(char *)&prP2pSpecificBssInfo->rOppPsParam); */ + break; + case 108: /* p2p_set_power_save */ + kalIoctl(prGlueInfo, + wlanoidSetP2pPowerSaveProfile, &value, sizeof(value), FALSE, FALSE, TRUE, TRUE, &u4Leng); + + break; + default: + break; + } + + return status; + +} + +int mtk_p2p_cfg80211_testmode_p2p_sigma_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_P2P_SIGMA_PARAMS prParams = (P_NL80211_DRIVER_P2P_SIGMA_PARAMS) NULL; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; + UINT_32 index; + INT_32 value; + int status = 0; + UINT_32 u4Leng; + struct NL80211_DRIVER_P2P_NOA_PARAMS { + NL80211_DRIVER_TEST_PARAMS hdr; + UINT_32 idx; + UINT_32 value; /* should not be used in this case */ + UINT_32 count; + UINT_32 interval; + UINT_32 duration; + }; + struct NL80211_DRIVER_P2P_NOA_PARAMS *prNoaParams = NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + prP2pSpecificBssInfo = prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo; + prP2pConnSettings = prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings; + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_testmode_p2p_sigma_cmd\n"); + + if (data && len) { + prParams = (P_NL80211_DRIVER_P2P_SIGMA_PARAMS) data; + } else { + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_testmode_p2p_sigma_cmd, data is NULL or len is 0\n"); + return -EINVAL; + } + + index = (INT_32) prParams->idx; + value = (INT_32) prParams->value; + + DBGLOG(P2P, TRACE, "NL80211_ATTR_TESTDATA, idx=%d value=%d\n", + (INT_32) prParams->idx, (INT_32) prParams->value); + + switch (index) { + case 0: /* Listen CH */ + break; + case 1: /* P2p mode */ + break; + case 4: /* Noa duration */ + prNoaParams = data; + prP2pSpecificBssInfo->rNoaParam.u4NoaCount = prNoaParams->count; + prP2pSpecificBssInfo->rNoaParam.u4NoaIntervalMs = prNoaParams->interval; + prP2pSpecificBssInfo->rNoaParam.u4NoaDurationMs = prNoaParams->duration; + DBGLOG(P2P, INFO, "SET NOA: %d %d %d\n", + prNoaParams->count, prNoaParams->interval, prNoaParams->duration); + + /* only to apply setting when setting NOA count */ + kalIoctl(prGlueInfo, wlanoidSetNoaParam, &prP2pSpecificBssInfo->rNoaParam, + sizeof(PARAM_CUSTOM_NOA_PARAM_STRUCT_T), + FALSE, FALSE, TRUE, TRUE, &u4Leng); + 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; + + DBGLOG(P2P, INFO, "SET OPPS: %d\n", value); + kalIoctl(prGlueInfo, wlanoidSetOppPsParam, &prP2pSpecificBssInfo->rOppPsParam, + sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T), + FALSE, FALSE, TRUE, TRUE, &u4Leng); + break; + case 108: /* p2p_set_power_save */ + kalIoctl(prGlueInfo, + wlanoidSetP2pPowerSaveProfile, &value, sizeof(value), FALSE, FALSE, TRUE, TRUE, &u4Leng); + + break; + case 109: /* Max Clients */ + kalP2PSetMaxClients(prGlueInfo, value); + break; + case 110: /* Hotspot WPS mode */ + kalIoctl(prGlueInfo, wlanoidSetP2pWPSmode, &value, sizeof(value), FALSE, FALSE, TRUE, TRUE, &u4Leng); + break; + default: + break; + } + + return status; + +} + +#if CFG_SUPPORT_WFD +int mtk_p2p_cfg80211_testmode_wfd_update_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) +{ + static UINT_8 prevWfdEnable; + + 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"); + + /* to reduce log, print when state changed */ + if (prevWfdEnable != prParams->WfdEnable) { + prevWfdEnable = prParams->WfdEnable; + DBGLOG(P2P, INFO, "WFD Enable:%x\n", prParams->WfdEnable); + DBGLOG(P2P, INFO, "WFD Session Available:%x\n", prParams->WfdSessionAvailable); + DBGLOG(P2P, INFO, "WFD Couple Sink Status:%x\n", prParams->WfdCoupleSinkStatus); + /* aucReserved0[2] */ + DBGLOG(P2P, INFO, "WFD Device Info:%x\n", prParams->WfdDevInfo); + DBGLOG(P2P, INFO, "WFD Control Port:%x\n", prParams->WfdControlPort); + DBGLOG(P2P, INFO, "WFD Maximum Throughput:%x\n", prParams->WfdMaximumTp); + DBGLOG(P2P, INFO, "WFD Extend Capability:%x\n", prParams->WfdExtendCap); + DBGLOG(P2P, INFO, "WFD Couple Sink Addr %pM\n", prParams->WfdCoupleSinkAddress); + DBGLOG(P2P, INFO, "WFD Associated BSSID %pM\n", prParams->WfdAssociatedBssid); + /* UINT_8 aucVideolp[4]; */ + /* UINT_8 aucAudiolp[4]; */ + DBGLOG(P2P, INFO, "WFD Video Port:%x\n", prParams->WfdVideoPort); + DBGLOG(P2P, INFO, "WFD Audio Port:%x\n", prParams->WfdAudioPort); + DBGLOG(P2P, INFO, "WFD Flag:%x\n", prParams->WfdFlag); + DBGLOG(P2P, INFO, "WFD Policy:%x\n", prParams->WfdPolicy); + DBGLOG(P2P, INFO, "WFD State:%x\n", prParams->WfdState); + /* UINT_8 aucWfdSessionInformationIE[24*8]; */ + DBGLOG(P2P, INFO, "WFD Session Info Length:%x\n", prParams->WfdSessionInformationIELen); + /* UINT_8 aucReserved1[2]; */ + DBGLOG(P2P, INFO, "WFD Primary Sink Addr %pM\n", prParams->aucWfdPrimarySinkMac); + DBGLOG(P2P, INFO, "WFD Secondary Sink Addr %pM\n", prParams->aucWfdSecondarySinkMac); + DBGLOG(P2P, INFO, "WFD Advanced Flag:%x\n", prParams->WfdAdvanceFlag); + DBGLOG(P2P, INFO, "WFD Sigma mode:%x\n", prParams->WfdSigmaMode); + /* UINT_8 aucReserved2[64]; */ + /* UINT_8 aucReserved3[64]; */ + /* UINT_8 aucReserved4[64]; */ + } + + prWfdCfgSettings = &(prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + + kalMemCopy(&prWfdCfgSettings->u4WfdCmdType, &prParams->WfdCmdType, sizeof(WFD_CFG_SETTINGS_T)); + + prMsgWfdCfgUpdate = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_WFD_CONFIG_SETTINGS_CHANGED_T)); + + if (prMsgWfdCfgUpdate == NULL) { + ASSERT(FALSE); + return status; + } + + prMsgWfdCfgUpdate->rMsgHdr.eMsgId = MID_MNY_P2P_WFD_CFG_UPDATE; + prMsgWfdCfgUpdate->prWfdCfgSettings = prWfdCfgSettings; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgWfdCfgUpdate, MSG_SEND_METHOD_BUF); +#if 0 /* Test Only */ +/* prWfdCfgSettings->ucWfdEnable = 1; */ +/* prWfdCfgSettings->u4WfdFlag |= WFD_FLAGS_DEV_INFO_VALID; */ + prWfdCfgSettings->u4WfdFlag |= WFD_FLAGS_DEV_INFO_VALID; + prWfdCfgSettings->u2WfdDevInfo = 123; + prWfdCfgSettings->u2WfdControlPort = 456; + prWfdCfgSettings->u2WfdMaximumTp = 789; + + prWfdCfgSettings->u4WfdFlag |= WFD_FLAGS_SINK_INFO_VALID; + prWfdCfgSettings->ucWfdCoupleSinkStatus = 0xAB; + { + UINT_8 aucTestAddr[MAC_ADDR_LEN] = { 0x77, 0x66, 0x55, 0x44, 0x33, 0x22 }; + + COPY_MAC_ADDR(prWfdCfgSettings->aucWfdCoupleSinkAddress, aucTestAddr); + } + + prWfdCfgSettings->u4WfdFlag |= WFD_FLAGS_EXT_CAPABILITY_VALID; + prWfdCfgSettings->u2WfdExtendCap = 0xCDE; + +#endif + + return status; + +} +#endif /* CFG_SUPPORT_WFD */ + +int mtk_p2p_cfg80211_testmode_hotspot_block_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_HOTSPOT_BLOCK_PARAMS prParams = (P_NL80211_DRIVER_HOTSPOT_BLOCK_PARAMS) NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + DBGLOG(P2P, INFO, "--> %s()\n", __func__); + + if (data && len) { + prParams = (P_NL80211_DRIVER_HOTSPOT_BLOCK_PARAMS) data; + } else { + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_testmode_hotspot_block_cmd, data is NULL or len is 0\n"); + return -EINVAL; + } + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_testmode_hotspot_block_cmd\n"); + + return kalP2PSetBlackList(prGlueInfo, prParams->aucBssid, prParams->ucblocked); +} + +int mtk_p2p_cfg80211_testmode_sw_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_SW_CMD_PARAMS prParams = (P_NL80211_DRIVER_SW_CMD_PARAMS) NULL; + WLAN_STATUS rstatus = WLAN_STATUS_SUCCESS; + int fgIsValid = 0; + UINT_32 u4SetInfoLen = 0; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + +#if 1 + DBGLOG(P2P, TRACE, "--> %s()\n", __func__); +#endif + + if (data && len) + prParams = (P_NL80211_DRIVER_SW_CMD_PARAMS) data; + + if (prParams) { + if (prParams->set == 1) { + rstatus = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC) wlanoidSetSwCtrlWrite, + &prParams->adr, (UINT_32) 8, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + } + } + + if (rstatus != WLAN_STATUS_SUCCESS) + fgIsValid = -EFAULT; + + return fgIsValid; +} + +#endif /* CONFIG_NL80211_TESTMODE */ + +#endif /* CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_WIFI_DIRECT_CFG_80211 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_p2p_init.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_p2p_init.c new file mode 100644 index 0000000000000..5798749fc36ef --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_p2p_init.c @@ -0,0 +1,325 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E 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_INF_NAME "p2p%d" +#if CFG_TC10_FEATURE +#define AP_INF_NAME "swlan%d" +#else +#define AP_INF_NAME "ap%d" +#endif + +#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 +******************************************************************************** +*/ +static PUCHAR ifname = P2P_INF_NAME; +static UINT_16 mode = RUNNING_P2P_MODE; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +void p2pHandleSystemSuspend(void) +{ + struct net_device *prDev = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_8 ip[4] = { 0 }; + UINT_32 u4NumIPv4 = 0; +#ifdef CONFIG_IPV6 + UINT_8 ip6[16] = { 0 }; /* FIX ME: avoid to allocate large memory in stack */ + UINT_32 u4NumIPv6 = 0; +#endif + UINT_32 i; + P_PARAM_NETWORK_ADDRESS_IP prParamIpAddr; + + + if (!wlanExportGlueInfo(&prGlueInfo)) { + DBGLOG(P2P, INFO, "No glue info\n"); + return; + } + + ASSERT(prGlueInfo); + /* <1> Sanity check and acquire the net_device */ + prDev = prGlueInfo->prP2PInfo->prDevHandler; + ASSERT(prDev); + + /* <3> get the IPv4 address */ + if (!prDev || !(prDev->ip_ptr) || + !((struct in_device *)(prDev->ip_ptr))->ifa_list || + !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))) { + DBGLOG(P2P, INFO, "ip is not available.\n"); + return; + } + /* <4> copy the IPv4 address */ + kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip)); + + /* todo: traverse between list to find whole sets of IPv4 addresses */ + if (!((ip[0] == 0) && (ip[1] == 0) && (ip[2] == 0) && (ip[3] == 0))) + u4NumIPv4++; +#ifdef CONFIG_IPV6 + /* <5> get the IPv6 address */ + if (!prDev || !(prDev->ip6_ptr) || + !((struct in_device *)(prDev->ip6_ptr))->ifa_list || + !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))) { + DBGLOG(P2P, INFO, "ipv6 is not available.\n"); + return; + } + /* <6> copy the IPv6 address */ + kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6)); + DBGLOG(P2P, INFO, "ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n", + ip6[0], ip6[1], ip6[2], ip6[3], + ip6[4], ip6[5], ip6[6], ip6[7], ip6[8], ip6[9], ip6[10], ip6[11], ip6[12], ip6[13], ip6[14], ip6[15]); + /* todo: traverse between list to find whole sets of IPv6 addresses */ + + if (!((ip6[0] == 0) && (ip6[1] == 0) && (ip6[2] == 0) && (ip6[3] == 0) && (ip6[4] == 0) && (ip6[5] == 0))) + ; /* Do nothing */ +#endif + /* <7> set up the ARP filter */ + { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_32 u4SetInfoLen = 0; +/* UINT_8 aucBuf[32] = {0}; */ + UINT_32 u4Len = OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress); + P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST) g_aucBufIpAddr; + /* aucBuf; */ + P_PARAM_NETWORK_ADDRESS prParamNetAddr = prParamNetAddrList->arAddress; + + kalMemZero(g_aucBufIpAddr, sizeof(g_aucBufIpAddr)); + + prParamNetAddrList->u4AddressCount = u4NumIPv4; +#ifdef CONFIG_IPV6 + prParamNetAddrList->u4AddressCount += u4NumIPv6; +#endif + + prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + for (i = 0; i < u4NumIPv4; i++) { + prParamNetAddr->u2AddressLength = sizeof(PARAM_NETWORK_ADDRESS_IP); /* 4;; */ + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; +#if 0 + kalMemCopy(prParamNetAddr->aucAddress, ip, sizeof(ip)); + prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((UINT_32) prParamNetAddr + sizeof(ip)); + u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip); +#else + prParamIpAddr = (P_PARAM_NETWORK_ADDRESS_IP) prParamNetAddr->aucAddress; + kalMemCopy(&prParamIpAddr->in_addr, ip, sizeof(ip)); + + /* + * prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + + * sizeof(PARAM_NETWORK_ADDRESS)); + * frog. The pointer is not right. + */ + + prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prParamNetAddr + + (ULONG) (prParamNetAddr->u2AddressLength + + OFFSET_OF(PARAM_NETWORK_ADDRESS, + aucAddress))); + + u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(PARAM_NETWORK_ADDRESS_IP); +#endif + } +#if 0 +#ifdef CONFIG_IPV6 + for (i = 0; i < u4NumIPv6; i++) { + prParamNetAddr->u2AddressLength = 6; + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + kalMemCopy(prParamNetAddr->aucAddress, ip6, sizeof(ip6)); + /* prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(ip6)); */ + + prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prParamNetAddr + + (ULONG) (prParamNetAddr->u2AddressLength + + OFFSET_OF(PARAM_NETWORK_ADDRESS, + aucAddress))); + + u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip6); + } +#endif +#endif + ASSERT(u4Len <= sizeof(g_aucBufIpAddr /*aucBuf */)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetP2pSetNetworkAddress, + (PVOID) prParamNetAddrList, u4Len, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); + + DBGLOG(INIT, INFO, "IP: %d.%d.%d.%d, rStatus: %u\n", ip[0], ip[1], ip[2], ip[3], rStatus); + } +} + +void p2pHandleSystemResume(void) +{ + struct net_device *prDev = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_8 ip[4] = { 0 }; +#ifdef CONFIG_IPV6 + UINT_8 ip6[16] = { 0 }; /* FIX ME: avoid to allocate large memory in stack */ +#endif + + if (!wlanExportGlueInfo(&prGlueInfo)) { + DBGLOG(P2P, WARN, "no glue info\n"); + return; + } + + ASSERT(prGlueInfo); + /* <1> Sanity check and acquire the net_device */ + prDev = prGlueInfo->prP2PInfo->prDevHandler; + ASSERT(prDev); + + /* <3> get the IPv4 address */ + if (!prDev || !(prDev->ip_ptr) || + !((struct in_device *)(prDev->ip_ptr))->ifa_list || + !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))) { + DBGLOG(P2P, INFO, "ip is not available.\n"); + return; + } + /* <4> copy the IPv4 address */ + kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip)); + +#ifdef CONFIG_IPV6 + /* <5> get the IPv6 address */ + if (!prDev || !(prDev->ip6_ptr) || + !((struct in_device *)(prDev->ip6_ptr))->ifa_list || + !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))) { + DBGLOG(P2P, INFO, "ipv6 is not available.\n"); + return; + } + /* <6> copy the IPv6 address */ + kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6)); + DBGLOG(P2P, INFO, "ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n", + ip6[0], ip6[1], ip6[2], ip6[3], + ip6[4], ip6[5], ip6[6], ip6[7], ip6[8], ip6[9], ip6[10], ip6[11], ip6[12], ip6[13], ip6[14], ip6[15]); +#endif + /* <7> clear the ARP filter */ + { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_32 u4SetInfoLen = 0; +/* UINT_8 aucBuf[32] = {0}; */ + UINT_32 u4Len = sizeof(PARAM_NETWORK_ADDRESS_LIST); + P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST) g_aucBufIpAddr; + /* aucBuf; */ + + kalMemZero(g_aucBufIpAddr, sizeof(g_aucBufIpAddr)); + + prParamNetAddrList->u4AddressCount = 0; + prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + + ASSERT(u4Len <= sizeof(g_aucBufIpAddr /*aucBuf */)); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetP2pSetNetworkAddress, + (PVOID) prParamNetAddrList, u4Len, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); + + DBGLOG(INIT, INFO, "IP: %d.%d.%d.%d, rStatus: %u\n", ip[0], ip[1], ip[2], ip[3], rStatus); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* run p2p init procedure, glue register p2p and set p2p registered flag +* +* \retval 1 Success +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2pLaunch(P_GLUE_INFO_T prGlueInfo) +{ + + DBGLOG(P2P, TRACE, "p2pLaunch\n"); + + if (prGlueInfo->prAdapter->fgIsP2PRegistered == TRUE) { + DBGLOG(P2P, INFO, "p2p is already registered\n"); + return FALSE; + } + + if (!glRegisterP2P(prGlueInfo, ifname, (BOOLEAN) mode)) { + DBGLOG(P2P, ERROR, "Launch failed\n"); + return FALSE; + } + + prGlueInfo->prAdapter->fgIsP2PRegistered = TRUE; + DBGLOG(P2P, TRACE, "Launch success, fgIsP2PRegistered TRUE\n"); + return TRUE; +} + +VOID p2pSetMode(IN BOOLEAN fgIsAPMode) +{ + if (fgIsAPMode) { + mode = RUNNING_AP_MODE; + ifname = AP_INF_NAME; + } else { + mode = RUNNING_P2P_MODE; + ifname = P2P_INF_NAME; + } + +} /* p2pSetMode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* run p2p exit procedure, glue unregister p2p and set p2p registered flag +* +* \retval 1 Success +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2pRemove(P_GLUE_INFO_T prGlueInfo) +{ + if (prGlueInfo->prAdapter->fgIsP2PRegistered == FALSE) { + DBGLOG(P2P, INFO, "p2p is not registered\n"); + return FALSE; + } + /* Check P2P FSM is stop or not. If not then stop now */ + if (IS_P2P_ACTIVE(prGlueInfo->prAdapter)) + p2pStopImmediate(prGlueInfo); + + prGlueInfo->prAdapter->fgIsP2PRegistered = FALSE; + glUnregisterP2P(prGlueInfo); + return TRUE; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_p2p_kal.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_p2p_kal.c new file mode 100644 index 0000000000000..95c19c22f5335 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_p2p_kal.c @@ -0,0 +1,1729 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "net/cfg80211.h" +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Wi-Fi Direct state from glue layer +* +* \param[in] +* prGlueInfo +* rPeerAddr +* \return +* ENUM_BOW_DEVICE_STATE +*/ +/*----------------------------------------------------------------------------*/ +ENUM_PARAM_MEDIA_STATE_T kalP2PGetState(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->prP2PInfo->eState; +} /* end of kalP2PGetState() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to update the assoc req to p2p +* +* \param[in] +* prGlueInfo +* pucFrameBody +* u4FrameBodyLen +* fgReassocRequest +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalP2PUpdateAssocInfo(IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBody, IN UINT_32 u4FrameBodyLen, IN BOOLEAN fgReassocRequest) +{ + union iwreq_data wrqu; + unsigned char *pucExtraInfo = NULL; + unsigned char *pucDesiredIE = NULL; +/* unsigned char aucExtraInfoBuf[200]; */ + PUINT_8 cp; + + memset(&wrqu, 0, sizeof(wrqu)); + + if (fgReassocRequest) { + if (u4FrameBodyLen < 15) { + /* + * printk(KERN_WARNING "frameBodyLen too short:%ld\n", frameBodyLen); + */ + return; + } + } else { + if (u4FrameBodyLen < 9) { + /* + * printk(KERN_WARNING "frameBodyLen too short:%ld\n", frameBodyLen); + */ + return; + } + } + + cp = pucFrameBody; + + if (fgReassocRequest) { + /* Capability information field 2 */ + /* Listen interval field 2 */ + /* Current AP address 6 */ + cp += 10; + u4FrameBodyLen -= 10; + } else { + /* Capability information field 2 */ + /* Listen interval field 2 */ + cp += 4; + u4FrameBodyLen -= 4; + } + + /* do supplicant a favor, parse to the start of WPA/RSN IE */ + if (wextSrchDesiredWPSIE(cp, u4FrameBodyLen, 0xDD, &pucDesiredIE)) { + /* printk("wextSrchDesiredWPSIE!!\n"); */ + /* WPS IE found */ + } else if (wextSrchDesiredWPAIE(cp, u4FrameBodyLen, 0x30, &pucDesiredIE)) { + /* printk("wextSrchDesiredWPAIE!!\n"); */ + /* RSN IE found */ + } else if (wextSrchDesiredWPAIE(cp, u4FrameBodyLen, 0xDD, &pucDesiredIE)) { + /* printk("wextSrchDesiredWPAIE!!\n"); */ + /* WPA IE found */ + } else { + /* no WPA/RSN IE found, skip this event */ + goto skip_indicate_event; + } + + /* IWEVASSOCREQIE, indicate binary string */ + pucExtraInfo = pucDesiredIE; + wrqu.data.length = pucDesiredIE[1] + 2; + + /* Send event to user space */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVASSOCREQIE, &wrqu, pucExtraInfo); + +skip_indicate_event: + return; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to set Wi-Fi Direct state in glue layer +* +* \param[in] +* prGlueInfo +* eBowState +* rPeerAddr +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalP2PSetState(IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_PARAM_MEDIA_STATE_T eState, IN PARAM_MAC_ADDRESS rPeerAddr, IN UINT_8 ucRole) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + + if (eState == PARAM_MEDIA_STATE_CONNECTED) { + prGlueInfo->prP2PInfo->eState = PARAM_MEDIA_STATE_CONNECTED; + + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_STA_CONNECT=%pM ", rPeerAddr); + evt.data.length = strlen(aucBuffer); + + /* indicate in IWECUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + + } else if (eState == PARAM_MEDIA_STATE_DISCONNECTED) { + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_STA_DISCONNECT=%pM ", rPeerAddr); + evt.data.length = strlen(aucBuffer); + + /* indicate in IWECUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + } else { + ASSERT(0); + } + +} /* end of kalP2PSetState() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Wi-Fi Direct operating frequency +* +* \param[in] +* prGlueInfo +* +* \return +* in unit of KHz +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 kalP2PGetFreqInKHz(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->prP2PInfo->u4FreqInKHz; +} /* end of kalP2PGetFreqInKHz() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Bluetooth-over-Wi-Fi role +* +* \param[in] +* prGlueInfo +* +* \return +* 0: P2P Device +* 1: Group Client +* 2: Group Owner +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 kalP2PGetRole(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->prP2PInfo->ucRole; +} /* end of kalP2PGetRole() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to set Wi-Fi Direct role +* +* \param[in] +* prGlueInfo +* ucResult +* 0: successful +* 1: error +* ucRole +* 0: P2P Device +* 1: Group Client +* 2: Group Owner +* +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalP2PSetRole(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucResult, IN PUINT_8 pucSSID, IN UINT_8 ucSSIDLen, IN UINT_8 ucRole) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + ASSERT(ucRole <= 2); + + memset(&evt, 0, sizeof(evt)); + + if (ucResult == 0) + prGlueInfo->prP2PInfo->ucRole = ucRole; + + if (pucSSID) + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_FORMATION_RST=%d%d%d%c%c", ucResult, ucRole, + 1 /* persistence or not */, pucSSID[7], pucSSID[8]); + else + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_FORMATION_RST=%d%d%d%c%c", ucResult, ucRole, + 1 /* persistence or not */, '0', '0'); + + evt.data.length = strlen(aucBuffer); + + /* if (pucSSID) */ + /* printk("P2P GO SSID DIRECT-%c%c\n", pucSSID[7], pucSSID[8]); */ + + /* indicate in IWECUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PSetRole() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to set the cipher for p2p +* +* \param[in] +* prGlueInfo +* u4Cipher +* +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalP2PSetCipher(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Cipher) +{ + if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { + ASSERT(FALSE); + return; + } + + prGlueInfo->prP2PInfo->u4CipherPairwise = u4Cipher; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to get the cipher, return for cipher is ccmp +* +* \param[in] +* prGlueInfo +* +* \return +* TRUE: cipher is ccmp +* FALSE: cipher is none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalP2PGetCipher(IN P_GLUE_INFO_T prGlueInfo) +{ + if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { + ASSERT(FALSE); + return FALSE; + } + + if (prGlueInfo->prP2PInfo->u4CipherPairwise == IW_AUTH_CIPHER_CCMP) + return TRUE; + + if (prGlueInfo->prP2PInfo->u4CipherPairwise == IW_AUTH_CIPHER_TKIP) + return TRUE; + + return FALSE; +} + +BOOLEAN kalP2PGetCcmpCipher(IN P_GLUE_INFO_T prGlueInfo) +{ + if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { + ASSERT(FALSE); + return FALSE; + } + + if (prGlueInfo->prP2PInfo->u4CipherPairwise == IW_AUTH_CIPHER_CCMP) + return TRUE; + + if (prGlueInfo->prP2PInfo->u4CipherPairwise == IW_AUTH_CIPHER_TKIP) + return FALSE; + + return FALSE; +} + +BOOLEAN kalP2PGetTkipCipher(IN P_GLUE_INFO_T prGlueInfo) +{ + if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { + ASSERT(FALSE); + return FALSE; + } + + if (prGlueInfo->prP2PInfo->u4CipherPairwise == IW_AUTH_CIPHER_CCMP) + return FALSE; + + if (prGlueInfo->prP2PInfo->u4CipherPairwise == IW_AUTH_CIPHER_TKIP) + return TRUE; + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to set the status of WSC +* +* \param[in] +* prGlueInfo +* +* \return +*/ +/*----------------------------------------------------------------------------*/ +VOID kalP2PSetWscMode(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucWscMode) +{ + if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { + ASSERT(FALSE); + return; + } + + prGlueInfo->prP2PInfo->ucWSCRunning = ucWscMode; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to get the status of WSC +* +* \param[in] +* prGlueInfo +* +* \return +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 kalP2PGetWscMode(IN P_GLUE_INFO_T prGlueInfo) +{ + if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { + ASSERT(FALSE); + return 0; + } + + return prGlueInfo->prP2PInfo->ucWSCRunning; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to get the wsc ie length +* +* \param[in] +* prGlueInfo +* ucType : 0 for beacon, 1 for probe req, 2 for probe resp +* +* \return +* The WSC IE length +*/ +/*----------------------------------------------------------------------------*/ +UINT_16 kalP2PCalWSC_IELen(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucType) +{ + ASSERT(prGlueInfo); + + ASSERT(ucType < 3); + + return prGlueInfo->prP2PInfo->u2WSCIELen[ucType]; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to get the p2p ie length +* +* \param[in] +* prGlueInfo +* +* +* \return +* The P2P IE length +*/ +/*----------------------------------------------------------------------------*/ +UINT_16 kalP2PCalP2P_IELen(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucIndex) +{ + ASSERT(prGlueInfo); + + ASSERT(ucIndex < MAX_P2P_IE_SIZE); + + return prGlueInfo->prP2PInfo->u2P2PIELen[ucIndex]; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to copy the wsc ie setting from p2p supplicant +* +* \param[in] +* prGlueInfo +* +* \return +* The WPS IE length +*/ +/*----------------------------------------------------------------------------*/ +VOID kalP2PGenWSC_IE(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucType, IN PUINT_8 pucBuffer) +{ + P_GL_P2P_INFO_T prGlP2pInfo = (P_GL_P2P_INFO_T) NULL; + + do { + if ((prGlueInfo == NULL) || (ucType >= 3) || (pucBuffer == NULL)) + break; + + prGlP2pInfo = prGlueInfo->prP2PInfo; + + kalMemCopy(pucBuffer, prGlP2pInfo->aucWSCIE[ucType], prGlP2pInfo->u2WSCIELen[ucType]); + + } while (FALSE); + +} + +VOID kalP2PUpdateWSC_IE(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucType, IN PUINT_8 pucBuffer, IN UINT_16 u2BufferLength) +{ + P_GL_P2P_INFO_T prGlP2pInfo = (P_GL_P2P_INFO_T) NULL; + + do { + if ((prGlueInfo == NULL) || (ucType >= 3) || ((u2BufferLength > 0) && (pucBuffer == NULL))) + break; + + if (u2BufferLength > 400) { + DBGLOG(P2P, ERROR, + "Buffer length is not enough, GLUE only 400 bytes but %d received\n", u2BufferLength); + ASSERT(FALSE); + break; + } + + prGlP2pInfo = prGlueInfo->prP2PInfo; + + kalMemCopy(prGlP2pInfo->aucWSCIE[ucType], pucBuffer, u2BufferLength); + + prGlP2pInfo->u2WSCIELen[ucType] = u2BufferLength; + + } while (FALSE); + +} /* kalP2PUpdateWSC_IE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to copy the p2p ie setting from p2p supplicant +* +* \param[in] +* prGlueInfo +* +* \return +* +*/ +/*----------------------------------------------------------------------------*/ +VOID kalP2PGenP2P_IE(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucIndex, IN PUINT_8 pucBuffer) +{ + P_GL_P2P_INFO_T prGlP2pInfo = (P_GL_P2P_INFO_T) NULL; + + do { + if ((prGlueInfo == NULL) || (ucIndex >= MAX_P2P_IE_SIZE) || (pucBuffer == NULL)) + break; + + prGlP2pInfo = prGlueInfo->prP2PInfo; + + kalMemCopy(pucBuffer, prGlP2pInfo->aucP2PIE[ucIndex], prGlP2pInfo->u2P2PIELen[ucIndex]); + + } while (FALSE); + +} + +VOID kalP2PUpdateP2P_IE(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucIndex, IN PUINT_8 pucBuffer, IN UINT_16 u2BufferLength) +{ + P_GL_P2P_INFO_T prGlP2pInfo = (P_GL_P2P_INFO_T) NULL; + + do { + if ((prGlueInfo == NULL) || + (ucIndex >= MAX_P2P_IE_SIZE) || + ((u2BufferLength > 0) && (pucBuffer == NULL))) + break; + + if (u2BufferLength > 400) { + DBGLOG(P2P, ERROR, + "kalP2PUpdateP2P_IE > Buffer length is not enough, GLUE only 400 bytes but %d received\n", + u2BufferLength); + ASSERT(FALSE); + break; + } + + prGlP2pInfo = prGlueInfo->prP2PInfo; + + kalMemCopy(prGlP2pInfo->aucP2PIE[ucIndex], pucBuffer, u2BufferLength); + + prGlP2pInfo->u2P2PIELen[ucIndex] = u2BufferLength; + + } while (FALSE); + +} /* kalP2PUpdateWSC_IE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief indicate an event to supplicant for device connection request +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalP2PIndicateConnReq(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucDevName, IN INT_32 u4NameLength, + IN PARAM_MAC_ADDRESS rPeerAddr, IN UINT_8 ucDevType, /* 0: P2P Device / 1: GC / 2: GO */ + IN INT_32 i4ConfigMethod, IN INT_32 i4ActiveConfigMethod) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + /* buffer peer information for later IOC_P2P_GET_REQ_DEVICE_INFO access */ + prGlueInfo->prP2PInfo->u4ConnReqNameLength = u4NameLength > 32 ? 32 : u4NameLength; + kalMemCopy(prGlueInfo->prP2PInfo->aucConnReqDevName, pucDevName, prGlueInfo->prP2PInfo->u4ConnReqNameLength); + COPY_MAC_ADDR(prGlueInfo->prP2PInfo->rConnReqPeerAddr, rPeerAddr); + prGlueInfo->prP2PInfo->ucConnReqDevType = ucDevType; + prGlueInfo->prP2PInfo->i4ConnReqConfigMethod = i4ConfigMethod; + prGlueInfo->prP2PInfo->i4ConnReqActiveConfigMethod = i4ActiveConfigMethod; + + /* prepare event structure */ + memset(&evt, 0, sizeof(evt)); + + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_DVC_REQ"); + evt.data.length = strlen(aucBuffer); + + /* indicate in IWEVCUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PIndicateConnReq() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Indicate an event to supplicant for device connection request from other device. +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* \param[in] pucGroupBssid Only valid when invitation Type equals to 0. +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalP2PInvitationIndication(IN P_GLUE_INFO_T prGlueInfo, + IN P_P2P_DEVICE_DESC_T prP2pDevDesc, + IN PUINT_8 pucSsid, + IN UINT_8 ucSsidLen, + IN UINT_8 ucOperatingChnl, IN UINT_8 ucInvitationType, IN PUINT_8 pucGroupBssid) +{ +#if 1 + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + /* buffer peer information for later IOC_P2P_GET_STRUCT access */ + prGlueInfo->prP2PInfo->u4ConnReqNameLength = + (UINT_32) ((prP2pDevDesc->u2NameLength > 32) ? 32 : prP2pDevDesc->u2NameLength); + kalMemCopy(prGlueInfo->prP2PInfo->aucConnReqDevName, prP2pDevDesc->aucName, + prGlueInfo->prP2PInfo->u4ConnReqNameLength); + COPY_MAC_ADDR(prGlueInfo->prP2PInfo->rConnReqPeerAddr, prP2pDevDesc->aucDeviceAddr); + COPY_MAC_ADDR(prGlueInfo->prP2PInfo->rConnReqGroupAddr, pucGroupBssid); + prGlueInfo->prP2PInfo->i4ConnReqConfigMethod = (INT_32) (prP2pDevDesc->u2ConfigMethod); + prGlueInfo->prP2PInfo->ucOperatingChnl = ucOperatingChnl; + prGlueInfo->prP2PInfo->ucInvitationType = ucInvitationType; + + /* prepare event structure */ + memset(&evt, 0, sizeof(evt)); + + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_INV_INDICATE"); + evt.data.length = strlen(aucBuffer); + + /* indicate in IWEVCUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + return; + +#else + P_MSG_P2P_CONNECTION_REQUEST_T prP2pConnReq = (P_MSG_P2P_CONNECTION_REQUEST_T) NULL; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; + + do { + ASSERT_BREAK((prGlueInfo != NULL) && (prP2pDevDesc != NULL)); + + /* Not a real solution */ + + prP2pSpecificBssInfo = prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo; + prP2pConnSettings = prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings; + + prP2pConnReq = (P_MSG_P2P_CONNECTION_REQUEST_T) cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + sizeof(MSG_P2P_CONNECTION_REQUEST_T)); + + if (prP2pConnReq == NULL) + break; + + kalMemZero(prP2pConnReq, sizeof(MSG_P2P_CONNECTION_REQUEST_T)); + + prP2pConnReq->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_REQ; + + prP2pConnReq->eFormationPolicy = ENUM_P2P_FORMATION_POLICY_AUTO; + + COPY_MAC_ADDR(prP2pConnReq->aucDeviceID, prP2pDevDesc->aucDeviceAddr); + + prP2pConnReq->u2ConfigMethod = prP2pDevDesc->u2ConfigMethod; + + if (ucInvitationType == P2P_INVITATION_TYPE_INVITATION) { + prP2pConnReq->fgIsPersistentGroup = FALSE; + prP2pConnReq->fgIsTobeGO = FALSE; + + } + + else if (ucInvitationType == P2P_INVITATION_TYPE_REINVOKE) { + DBGLOG(P2P, TRACE, "Re-invoke Persistent Group\n"); + prP2pConnReq->fgIsPersistentGroup = TRUE; + prP2pConnReq->fgIsTobeGO = (prGlueInfo->prP2PInfo->ucRole == 2) ? TRUE : FALSE; + + } + + p2pFsmRunEventDeviceDiscoveryAbort(prGlueInfo->prAdapter, NULL); + + if (ucOperatingChnl != 0) + prP2pSpecificBssInfo->ucPreferredChannel = ucOperatingChnl; + + if ((ucSsidLen < 32) && (pucSsid != NULL)) + COPY_SSID(prP2pConnSettings->aucSSID, prP2pConnSettings->ucSSIDLen, pucSsid, ucSsidLen); + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prP2pConnReq, MSG_SEND_METHOD_BUF); + + } while (FALSE); + + /* frog add. */ + /* TODO: Invitation Indication */ + + return; +#endif + +} /* kalP2PInvitationIndication */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Indicate an status to supplicant for device invitation status. +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalP2PInvitationStatus(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4InvStatus) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + /* buffer peer information for later IOC_P2P_GET_STRUCT access */ + prGlueInfo->prP2PInfo->u4InvStatus = u4InvStatus; + + /* prepare event structure */ + memset(&evt, 0, sizeof(evt)); + + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_INV_STATUS"); + evt.data.length = strlen(aucBuffer); + + /* indicate in IWEVCUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + +} /* kalP2PInvitationStatus */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Indicate an event to supplicant for Service Discovery request from other device. +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalP2PIndicateSDRequest(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rPeerAddr, IN UINT_8 ucSeqNum) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_SD_REQ %d", ucSeqNum); + evt.data.length = strlen(aucBuffer); + + /* indicate IWEVP2PSDREQ event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PIndicateSDRequest() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Indicate an event to supplicant for Service Discovery response +* from other device. +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +void kalP2PIndicateSDResponse(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rPeerAddr, IN UINT_8 ucSeqNum) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_SD_RESP %d", ucSeqNum); + evt.data.length = strlen(aucBuffer); + + /* indicate IWEVP2PSDREQ event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PIndicateSDResponse() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Indicate an event to supplicant for Service Discovery TX Done +* from other device. +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* \param[in] ucSeqNum Sequence number of the frame +* \param[in] ucStatus Status code for TX +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalP2PIndicateTXDone(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucSeqNum, IN UINT_8 ucStatus) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_SD_XMITTED: %d %d", ucSeqNum, ucStatus); + evt.data.length = strlen(aucBuffer); + + /* indicate IWEVP2PSDREQ event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PIndicateSDResponse() */ + +struct net_device *kalP2PGetDevHdlr(P_GLUE_INFO_T prGlueInfo) +{ + if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { + ASSERT(FALSE); + return NULL; + } + + return prGlueInfo->prP2PInfo->prDevHandler; +} + +#if CFG_SUPPORT_ANTI_PIRACY +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalP2PIndicateSecCheckRsp(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucRsp, IN UINT_16 u2RspLen) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_SEC_CHECK_RSP="); + + kalMemCopy(prGlueInfo->prP2PInfo->aucSecCheckRsp, pucRsp, u2RspLen); + evt.data.length = strlen(aucBuffer); + +#if DBG + DBGLOG_MEM8(SEC, LOUD, prGlueInfo->prP2PInfo->aucSecCheckRsp, u2RspLen); +#endif + /* indicate in IWECUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); +} /* p2pFsmRunEventRxDisassociation */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalGetChnlList(IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_BAND_T eSpecificBand, + IN UINT_8 ucMaxChannelNum, IN PUINT_8 pucNumOfChannel, IN P_RF_CHANNEL_INFO_T paucChannelList) +{ + rlmDomainGetChnlList(prGlueInfo->prAdapter, eSpecificBand, FALSE, ucMaxChannelNum, + pucNumOfChannel, paucChannelList); +} /* kalGetChnlList */ + +/* ////////////////////////////////////ICS SUPPORT////////////////////////////////////// */ + +VOID +kalP2PIndicateChannelReady(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8SeqNum, + IN UINT_32 u4ChannelNum, + IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_32 u4Duration) +{ + struct ieee80211_channel *prIEEE80211ChnlStruct = (struct ieee80211_channel *)NULL; + RF_CHANNEL_INFO_T rChannelInfo; + enum nl80211_channel_type eChnlType = NL80211_CHAN_NO_HT; + + do { + if (prGlueInfo == NULL) + break; + + kalMemZero(&rChannelInfo, sizeof(RF_CHANNEL_INFO_T)); + + rChannelInfo.ucChannelNum = u4ChannelNum; + rChannelInfo.eBand = eBand; + + prIEEE80211ChnlStruct = kalP2pFuncGetChannelEntry(prGlueInfo->prP2PInfo, &rChannelInfo); + + kalP2pFuncGetChannelType(eSco, &eChnlType); + + if (!prIEEE80211ChnlStruct) { + DBGLOG(P2P, WARN, "prIEEE80211ChnlStruct is NULL\n"); + break; + } + cfg80211_ready_on_channel(prGlueInfo->prP2PInfo->prWdev, /* struct wireless_dev, */ + u8SeqNum, /* u64 cookie, */ + prIEEE80211ChnlStruct, /* struct ieee80211_channel * chan, */ + u4Duration, /* unsigned int duration, */ + GFP_KERNEL); /* gfp_t gfp */ /* allocation flags */ + } while (FALSE); + +} /* kalP2PIndicateChannelReady */ + +VOID kalP2PIndicateChannelExpired(IN P_GLUE_INFO_T prGlueInfo, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo) +{ + + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + struct ieee80211_channel *prIEEE80211ChnlStruct = (struct ieee80211_channel *)NULL; + enum nl80211_channel_type eChnlType = NL80211_CHAN_NO_HT; + RF_CHANNEL_INFO_T rRfChannelInfo; + + do { + if ((prGlueInfo == NULL) || (prChnlReqInfo == NULL)) { + + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + if (prGlueP2pInfo == NULL) { + ASSERT(FALSE); + break; + } + + DBGLOG(P2P, TRACE, "kalP2PIndicateChannelExpired\n"); + + rRfChannelInfo.eBand = prChnlReqInfo->eBand; + rRfChannelInfo.ucChannelNum = prChnlReqInfo->ucReqChnlNum; + + prIEEE80211ChnlStruct = kalP2pFuncGetChannelEntry(prGlueP2pInfo, &rRfChannelInfo); + + kalP2pFuncGetChannelType(prChnlReqInfo->eChnlSco, &eChnlType); + + if (!prIEEE80211ChnlStruct) { + DBGLOG(P2P, WARN, "prIEEE80211ChnlStruct is NULL\n"); + break; + } + cfg80211_remain_on_channel_expired(prGlueP2pInfo->prWdev, /* struct wireless_dev, */ + prChnlReqInfo->u8Cookie, prIEEE80211ChnlStruct, GFP_KERNEL); + } while (FALSE); + +} /* kalP2PIndicateChannelExpired */ + +VOID kalP2PIndicateScanDone(IN P_GLUE_INFO_T prGlueInfo, IN BOOLEAN fgIsAbort) +{ + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + struct cfg80211_scan_request *prScanRequest = NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + do { + if (prGlueInfo == NULL) { + + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + if (prGlueP2pInfo == NULL) { + ASSERT(FALSE); + break; + } + + DBGLOG(INIT, TRACE, "[p2p] scan complete %p\n", prGlueP2pInfo->prScanRequest); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if (prGlueP2pInfo->prScanRequest != NULL) { + prScanRequest = prGlueP2pInfo->prScanRequest; + prGlueP2pInfo->prScanRequest = NULL; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + /* 2. then CFG80211 Indication */ + + if (prScanRequest != NULL) { + + /* report all queued beacon/probe response frames to upper layer */ + scanReportBss2Cfg80211(prGlueInfo->prAdapter, BSS_TYPE_P2P_DEVICE, NULL); + + DBGLOG(INIT, TRACE, "DBG:p2p_cfg_scan_done\n"); + kalCfg80211ScanDone(prScanRequest, fgIsAbort); + } + + } while (FALSE); + +} /* kalP2PIndicateScanDone */ + +VOID +kalP2PIndicateBssInfo(IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBuf, + IN UINT_32 u4BufLen, IN P_RF_CHANNEL_INFO_T prChannelInfo, IN INT_32 i4SignalStrength) +{ + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + struct ieee80211_channel *prChannelEntry = (struct ieee80211_channel *)NULL; + struct ieee80211_mgmt *prBcnProbeRspFrame = (struct ieee80211_mgmt *)pucFrameBuf; + struct cfg80211_bss *prCfg80211Bss = (struct cfg80211_bss *)NULL; + + do { + if ((prGlueInfo == NULL) || (pucFrameBuf == NULL) || (prChannelInfo == NULL)) { + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + if (prGlueP2pInfo == NULL) { + ASSERT(FALSE); + break; + } + + prChannelEntry = kalP2pFuncGetChannelEntry(prGlueP2pInfo, prChannelInfo); + + if (prChannelEntry == NULL) { + DBGLOG(P2P, WARN, "Unknown channel info\n"); + break; + } + /* rChannelInfo.center_freq = nicChannelNum2Freq((UINT_32)prChannelInfo->ucChannelNum) / 1000; */ + + if (u4BufLen > 0) { + prCfg80211Bss = cfg80211_inform_bss_frame( + /* struct wiphy * wiphy, */ + prGlueP2pInfo->prWdev->wiphy, + prChannelEntry, + prBcnProbeRspFrame, + u4BufLen, i4SignalStrength, GFP_KERNEL); + } + + /* Return this structure. */ + if (!prCfg80211Bss) { + DBGLOG(P2P, WARN, + "inform bss[%pM]: to cfg80211 failed, bss channel %d, rcpi %d, len %d\n", + prBcnProbeRspFrame->bssid, + prChannelInfo->ucChannelNum, i4SignalStrength, u4BufLen); + } else { + cfg80211_put_bss(prGlueP2pInfo->prWdev->wiphy, prCfg80211Bss); + DBGLOG(P2P, TRACE, "inform bss to cfg80211, bss channel %d, rcpi %d\n", + prChannelInfo->ucChannelNum, i4SignalStrength); + } + } while (FALSE); + +} /* kalP2PIndicateBssInfo */ + +VOID +kalP2PIndicateCompleteBssInfo(IN P_GLUE_INFO_T prGlueInfo, IN P_BSS_DESC_T prSpecificBssDesc) +{ + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + struct ieee80211_channel *prChannelEntry = (struct ieee80211_channel *)NULL; + struct cfg80211_bss *prCfg80211Bss = (struct cfg80211_bss *)NULL; + RF_CHANNEL_INFO_T rChannelInfo; + + if ((prGlueInfo == NULL) || (prSpecificBssDesc == NULL)) { + ASSERT(FALSE); + return; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + if (prGlueP2pInfo == NULL) { + DBGLOG(P2P, WARN, "kalP2PIndicateCompleteBssInfo: prGlueP2pInfo is NULL\n"); + ASSERT(FALSE); + return; + } + + rChannelInfo.ucChannelNum = prSpecificBssDesc->ucChannelNum; + rChannelInfo.eBand = prSpecificBssDesc->eBand; + prChannelEntry = kalP2pFuncGetChannelEntry(prGlueP2pInfo, &rChannelInfo); + + if (prChannelEntry == NULL) { + DBGLOG(P2P, WARN, "kalP2PIndicateCompleteBssInfo: Unknown channel info\n"); + return; + } + + prCfg80211Bss = cfg80211_inform_bss(prGlueP2pInfo->prWdev->wiphy, prChannelEntry, + ((prSpecificBssDesc->fgSeenProbeResp == TRUE) ? + CFG80211_BSS_FTYPE_PRESP : CFG80211_BSS_FTYPE_BEACON), + prSpecificBssDesc->aucBSSID, 0, /* TSF */ + prSpecificBssDesc->u2CapInfo, + prSpecificBssDesc->u2BeaconInterval, /* beacon interval */ + prSpecificBssDesc->aucIEBuf, /* IE */ + prSpecificBssDesc->u2IELength, /* IE Length */ + RCPI_TO_dBm(prSpecificBssDesc->ucRCPI) * 100, /* MBM */ + GFP_KERNEL); + + if (!prCfg80211Bss) { + DBGLOG(P2P, WARN, + "kalP2PIndicateCompleteBssInfo fail, BSSID[%pM] SSID[%s] Chnl[%d] RCPI[%d] IELng[%d] Bcn[%d]\n", + prSpecificBssDesc->aucBSSID, + HIDE(prSpecificBssDesc->aucSSID), + prSpecificBssDesc->ucChannelNum, + RCPI_TO_dBm(prSpecificBssDesc->ucRCPI), + prSpecificBssDesc->u2IELength, + prSpecificBssDesc->u2BeaconInterval); + dumpMemory8IEOneLine(prSpecificBssDesc->aucBSSID, + prSpecificBssDesc->aucIEBuf, prSpecificBssDesc->u2IELength); + } else + DBGLOG(P2P, TRACE, + "kalP2PIndicateCompleteBssInfo, BSS[%p] BSSID[%pM] SSID[%s] Chnl[%d] RCPI[%d] IELng[%d] Bcn[%d]\n", + prCfg80211Bss, + prSpecificBssDesc->aucBSSID, + HIDE(prSpecificBssDesc->aucSSID), + prSpecificBssDesc->ucChannelNum, + RCPI_TO_dBm(prSpecificBssDesc->ucRCPI), + prSpecificBssDesc->u2IELength, + prSpecificBssDesc->u2BeaconInterval); +} + + +VOID +kalP2PIndicateMgmtTxStatus(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, IN BOOLEAN fgIsAck, IN PUINT_8 pucFrameBuf, IN UINT_32 u4FrameLen) +{ + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + + do { + if ((prGlueInfo == NULL) || (pucFrameBuf == NULL) || (u4FrameLen == 0)) { + DBGLOG(P2P, TRACE, "Unexpected pointer PARAM. %p, %p, %u.", + prGlueInfo, pucFrameBuf, u4FrameLen); + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + cfg80211_mgmt_tx_status(prGlueP2pInfo->prWdev, /* struct net_device * dev, */ + u8Cookie, pucFrameBuf, u4FrameLen, fgIsAck, GFP_KERNEL); + + } while (FALSE); + +} /* kalP2PIndicateMgmtTxStatus */ + +VOID kalP2PIndicateRxMgmtFrame(IN P_GLUE_INFO_T prGlueInfo, IN P_SW_RFB_T prSwRfb) +{ +#define DBG_P2P_MGMT_FRAME_INDICATION 0 + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + INT_32 i4Freq = 0; + UINT_8 ucChnlNum = 0; +#if DBG_P2P_MGMT_FRAME_INDICATION + P_WLAN_MAC_HEADER_T prWlanHeader = (P_WLAN_MAC_HEADER_T) NULL; +#endif + + do { + if ((prGlueInfo == NULL) || (prSwRfb == NULL)) { + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + ucChnlNum = prSwRfb->prHifRxHdr->ucHwChannelNum; + +#if DBG_P2P_MGMT_FRAME_INDICATION + + prWlanHeader = (P_WLAN_MAC_HEADER_T) prSwRfb->pvHeader; + + switch (prWlanHeader->u2FrameCtrl) { + case MAC_FRAME_PROBE_REQ: + DBGLOG(P2P, TRACE, "RX Probe Req at channel %d ", ucChnlNum); + break; + case MAC_FRAME_PROBE_RSP: + DBGLOG(P2P, TRACE, "RX Probe Rsp at channel %d ", ucChnlNum); + break; + case MAC_FRAME_ACTION: + DBGLOG(P2P, TRACE, "RX Action frame at channel %d ", ucChnlNum); + break; + default: + DBGLOG(P2P, TRACE, "RX Packet:%d at channel %d ", prWlanHeader->u2FrameCtrl, ucChnlNum); + break; + } + + DBGLOG(P2P, TRACE, "from: %pM\n", prWlanHeader->aucAddr2); +#endif + i4Freq = nicChannelNum2Freq(ucChnlNum) / 1000; + + cfg80211_rx_mgmt(prGlueP2pInfo->prWdev, /* struct net_device * dev, */ + i4Freq, + RCPI_TO_dBm(prSwRfb->prHifRxHdr->ucRcpi), + prSwRfb->pvHeader, prSwRfb->u2PacketLen, GFP_ATOMIC); + } while (FALSE); + +} /* kalP2PIndicateRxMgmtFrame */ + +VOID +kalP2PGCIndicateConnectionStatus(IN P_GLUE_INFO_T prGlueInfo, + IN P_P2P_CONNECTION_REQ_INFO_T prP2pConnInfo, + IN PUINT_8 pucRxIEBuf, IN UINT_16 u2RxIELen, IN UINT_16 u2StatusReason, + IN WLAN_STATUS eStatus) +{ + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + + do { + if (prGlueInfo == NULL) { + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + DBGLOG(P2P, INFO, "%s: Reason code: %d eStatus=0x%x\n", __func__, u2StatusReason, eStatus); + + if (prP2pConnInfo) { + /* switch netif on */ + netif_carrier_on(prGlueP2pInfo->prDevHandler); + + 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? */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + cfg80211_disconnected(prGlueP2pInfo->prDevHandler, /* struct net_device * dev, */ + u2StatusReason, pucRxIEBuf, u2RxIELen, + eStatus == WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY ? true : false, + GFP_KERNEL); +#else + cfg80211_disconnected(prGlueP2pInfo->prDevHandler, /* struct net_device * dev, */ + u2StatusReason, pucRxIEBuf, u2RxIELen, GFP_KERNEL); +#endif + } + + } 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; + + do { + if ((prGlueInfo == NULL) || (prCliStaRec == NULL)) + break; + + prP2pGlueInfo = prGlueInfo->prP2PInfo; + + if (fgIsNew) { + struct station_info rStationInfo; + + kalMemZero(&rStationInfo, sizeof(rStationInfo)); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)) + rStationInfo.filled = STATION_INFO_ASSOC_REQ_IES; +#endif + rStationInfo.generation = ++prP2pGlueInfo->i4Generation; + + rStationInfo.assoc_req_ies = prCliStaRec->pucAssocReqIe; + rStationInfo.assoc_req_ies_len = prCliStaRec->u2AssocReqIeLen; + + 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: +#if CFG_SUPPORT_P2P_ECSA + *channel_type = NL80211_CHAN_HT20; +#else + *channel_type = NL80211_CHAN_NO_HT; +#endif + break; + case CHNL_EXT_SCA: + *channel_type = NL80211_CHAN_HT40MINUS; + break; + case CHNL_EXT_SCB: + *channel_type = NL80211_CHAN_HT40PLUS; + break; + default: + ASSERT(FALSE); + *channel_type = NL80211_CHAN_NO_HT; + break; + } + + } + + fgIsValid = TRUE; + } while (FALSE); + + return fgIsValid; +} /* kalP2pFuncGetChannelType */ + +struct ieee80211_channel *kalP2pFuncGetChannelEntry(IN P_GL_P2P_INFO_T prP2pInfo, IN P_RF_CHANNEL_INFO_T prChannelInfo) +{ + struct ieee80211_channel *prTargetChannelEntry = (struct ieee80211_channel *)NULL; + UINT_32 u4TblSize = 0, u4Idx = 0; + struct ieee80211_supported_band **bands; + + do { + if ((prP2pInfo == NULL) || (prChannelInfo == NULL)) + break; + bands = &prP2pInfo->prWdev->wiphy->bands[0]; + switch (prChannelInfo->eBand) { + case BAND_2G4: + if (bands[IEEE80211_BAND_2GHZ] == NULL) + DBGLOG(P2P, ERROR, "kalP2pFuncGetChannelEntry 2.4G NULL Bands!!\n"); + else { + prTargetChannelEntry = bands[IEEE80211_BAND_2GHZ]->channels; + u4TblSize = bands[IEEE80211_BAND_2GHZ]->n_channels; + } + break; + case BAND_5G: + if (bands[IEEE80211_BAND_5GHZ] == NULL) + DBGLOG(P2P, ERROR, "kalP2pFuncGetChannelEntry 5G NULL Bands!!\n"); + else { + prTargetChannelEntry = bands[IEEE80211_BAND_5GHZ]->channels; + u4TblSize = 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 */ +#if CFG_SUPPORT_P2P_ECSA +VOID kalP2pUpdateECSA(IN P_ADAPTER_T prAdapter, IN P_EVENT_ECSA_RESULT prECSA) +{ + P_BSS_INFO_T prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prECSA->ucNetTypeIndex]); + UINT_32 u4Freq = 0; + struct cfg80211_chan_def chandef; + RF_CHANNEL_INFO_T rChannelInfo; + enum nl80211_channel_type chantype; + struct ieee80211_channel *channel; + + + if (prECSA == NULL) { + DBGLOG(P2P, ERROR, "ECSA_RESULT is null!\n"); + return; + } + + if (prECSA->ucStatus == ECSA_EVENT_STATUS_UPDATE_BEACON) { + DBGLOG(P2P, INFO, "ECSA FW upeate beacon success!\n"); + return; + } + + u4Freq = nicChannelNum2Freq(prECSA->ucPrimaryChannel); + + if (!u4Freq) { + DBGLOG(P2P, ERROR, "channel number invalid: %d\n", prECSA->ucPrimaryChannel); + return; + } + + rChannelInfo.ucChannelNum = prECSA->ucPrimaryChannel; + rChannelInfo.eBand = prECSA->ucPrimaryChannel > 14 ? BAND_5G : BAND_2G4; + + channel = kalP2pFuncGetChannelEntry(prAdapter->prGlueInfo->prP2PInfo, &rChannelInfo); + if (!channel) { + DBGLOG(P2P, ERROR, "invalid channel:band %d:%d\n", + rChannelInfo.ucChannelNum, + rChannelInfo.eBand); + return; + } + kalP2pFuncGetChannelType(prECSA->ucRfSco, &chantype); + prBssInfo->ucPrimaryChannel = prECSA->ucPrimaryChannel; + prBssInfo->eBssSCO = prECSA->ucRfSco; + prBssInfo->eBand = prBssInfo->ucPrimaryChannel > 14 ? BAND_5G : BAND_2G4; + prBssInfo->fgChanSwitching = FALSE; + + /* sync with firmware */ + nicUpdateBss(prAdapter, prECSA->ucNetTypeIndex); + + /* only indicate to host when we AP/GO */ + if (prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) { + DBGLOG(P2P, INFO, "Do not indicate to host\n"); + return; + } + + if (prBssInfo->ucPrimaryChannel == 14) + chantype = NL80211_CHAN_NO_HT; + + cfg80211_chandef_create(&chandef, channel, chantype); + /* indicate to host */ + cfg80211_ch_switch_notify(prAdapter->prGlueInfo->prP2PInfo->prDevHandler, + &chandef); +} +#endif +/*----------------------------------------------------------------------------*/ +/*! +* \brief to set/clear the MAC address to/from the black list of Hotspot +* +* \param[in] +* prGlueInfo +* +* \return +*/ +/*----------------------------------------------------------------------------*/ +INT_32 kalP2PSetBlackList(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS bssid, IN BOOLEAN block) +{ + UINT_8 aucNullAddr[] = NULL_MAC_ADDR; + UINT_32 i; + + if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { + ASSERT(FALSE); + return -EFAULT; + } + + if (EQUAL_MAC_ADDR(bssid, aucNullAddr)) + return -EINVAL; + + if (block) { + /* Set the bssid to the black list to block the STA */ + for (i = 0; i < P2P_MAXIMUM_CLIENT_COUNT; i++) { + if (EQUAL_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucBlackMACList[i]), bssid)) + break; + } + if (i >= P2P_MAXIMUM_CLIENT_COUNT) { + for (i = 0; i < P2P_MAXIMUM_CLIENT_COUNT; i++) { + if (EQUAL_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucBlackMACList[i]), aucNullAddr)) { + COPY_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucBlackMACList[i]), bssid); + break; + } + } + if (i >= P2P_MAXIMUM_CLIENT_COUNT) { + DBGLOG(P2P, ERROR, "AP black list full, cannot block more STA!!\n"); + return -ENOBUFS; + } + } else + DBGLOG(P2P, WARN, MACSTR " already in black list\n", MAC2STR(bssid)); + + } else { + /* Clear the bssid from the black list to unblock the STA */ + for (i = 0; i < P2P_MAXIMUM_CLIENT_COUNT; i++) { + if (EQUAL_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucBlackMACList[i]), bssid)) { + COPY_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucBlackMACList[i]), aucNullAddr); + break; + } + } + if (i >= P2P_MAXIMUM_CLIENT_COUNT) + DBGLOG(P2P, ERROR, MACSTR " is not found in black list!!\n", MAC2STR(bssid)); + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to compare and check whether the MAC address is in the black list of Hotspot +* +* \param[in] +* prGlueInfo +* +* \return +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalP2PCmpBlackList(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS bssid) +{ + UINT_8 aucNullAddr[] = NULL_MAC_ADDR; + UINT_32 i; + + if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) + return FALSE; + + if (EQUAL_MAC_ADDR(bssid, aucNullAddr)) + return FALSE; + + for (i = 0; i < P2P_MAXIMUM_CLIENT_COUNT; i++) { + if (EQUAL_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucBlackMACList[i]), bssid)) + return TRUE; + } + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to set the max clients of Hotspot or P2P GO +* +* \param[in] +* prGlueInfo +* +* \return +*/ +/*----------------------------------------------------------------------------*/ +VOID kalP2PSetMaxClients(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4MaxClient) +{ + if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { + ASSERT(FALSE); + return; + } + + if (u4MaxClient == 0 || u4MaxClient >= P2P_MAXIMUM_CLIENT_COUNT) + prGlueInfo->prP2PInfo->ucMaxClients = P2P_MAXIMUM_CLIENT_COUNT; + else + prGlueInfo->prP2PInfo->ucMaxClients = (UINT_8)u4MaxClient; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to check whether reaches the max clients of Hotspot or P2P GO +* +* \param[in] +* prGlueInfo +* +* \return +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalP2PReachMaxClients(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4NumClient) +{ + if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { + ASSERT(FALSE); + return FALSE; + } + + if (prGlueInfo->prP2PInfo->ucMaxClients) { + if ((UINT_8)u4NumClient >= prGlueInfo->prP2PInfo->ucMaxClients) + return TRUE; + else + return FALSE; + } + + return FALSE; +} + +VOID kalP2pUnlinkBss(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 aucBSSID[]) +{ + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + struct cfg80211_bss *bss = NULL; + + ASSERT(prGlueInfo); + ASSERT(aucBSSID); + + DBGLOG(P2P, INFO, "bssid: " MACSTR "\n", MAC2STR(aucBSSID)); + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + if (prGlueP2pInfo == NULL) + return; + +#if (KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE) + bss = cfg80211_get_bss(prGlueP2pInfo->prWdev->wiphy, + NULL, /* channel */ + aucBSSID, + NULL, /* ssid */ + 0, /* ssid length */ + IEEE80211_BSS_TYPE_ESS, + IEEE80211_PRIVACY_ANY); +#else + bss = cfg80211_get_bss(prGlueP2pInfo->prWdev->wiphy, + NULL, /* channel */ + aucBSSID, + NULL, /* ssid */ + 0, /* ssid length */ + WLAN_CAPABILITY_ESS, + WLAN_CAPABILITY_ESS); +#endif + + if (bss != NULL) { + cfg80211_unlink_bss(prGlueP2pInfo->prWdev->wiphy, bss); + cfg80211_put_bss(prGlueP2pInfo->prWdev->wiphy, bss); + } + + if (scanSearchBssDescByBssidAndSsid(prGlueInfo->prAdapter, + aucBSSID, FALSE, NULL) != NULL) + scanRemoveBssDescByBssid(prGlueInfo->prAdapter, aucBSSID); +} + +void kalP2pIndicateQueuedMgmtFrame(IN P_GLUE_INFO_T prGlueInfo, + IN struct P2P_QUEUED_ACTION_FRAME *prFrame) +{ + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + + if ((prGlueInfo == NULL) || (prFrame == NULL)) + return; + + if (prFrame->prHeader == NULL || prFrame->u2Length == 0) { + DBGLOG(P2P, WARN, "Frame pointer is null or length is 0.\n"); + return; + } + + DBGLOG(P2P, INFO, "Indicate queued p2p action frame.\n"); + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + cfg80211_rx_mgmt( + /* struct net_device * dev, */ + prGlueP2pInfo->prWdev, + prFrame->u4Freq, + 0, + prFrame->prHeader, + prFrame->u2Length, + GFP_ATOMIC); +} + +void kalP2pIndicateAcsResult(IN P_GLUE_INFO_T prGlueInfo, + IN uint8_t ucPrimaryCh, + IN uint8_t ucSecondCh, + IN uint8_t ucSeg0Ch, + IN uint8_t ucSeg1Ch, + IN enum ENUM_MAX_BANDWIDTH_SETTING eChnlBw) +{ + struct sk_buff *vendor_event = NULL; + uint16_t ch_width = MAX_BW_20MHZ; + + switch (eChnlBw) { + case MAX_BW_20MHZ: + ch_width = 20; + break; + case MAX_BW_40MHZ: + ch_width = 40; + break; + default: + DBGLOG(P2P, ERROR, "unsupport width: %d.\n", ch_width); + break; + } + + DBGLOG(P2P, INFO, "pri: %d, sec: %d, seg0: %d, seg1: %d, ch_width: %d\n", + ucPrimaryCh, + ucSecondCh, + ucSeg0Ch, + ucSeg1Ch, + ch_width); + +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE + vendor_event = cfg80211_vendor_event_alloc( + prGlueInfo->prP2PInfo->prWdev->wiphy, +#if KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE + prGlueInfo->prP2PInfo->prWdev, +#endif + 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN, + WIFI_EVENT_ACS, + GFP_KERNEL); +#endif + + if (!vendor_event) { + DBGLOG(P2P, ERROR, "allocate vendor event fail.\n"); + goto nla_put_failure; + } + + if (unlikely(nla_put_u8(vendor_event, + WIFI_VENDOR_ATTR_ACS_PRIMARY_CHANNEL, + ucPrimaryCh) < 0)) { + DBGLOG(P2P, ERROR, "put primary channel fail.\n"); + goto nla_put_failure; + } + + if (unlikely(nla_put_u8(vendor_event, + WIFI_VENDOR_ATTR_ACS_SECONDARY_CHANNEL, + ucSecondCh) < 0)) { + DBGLOG(P2P, ERROR, "put secondary channel fail.\n"); + goto nla_put_failure; + } + + if (unlikely(nla_put_u8(vendor_event, + WIFI_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL, + ucSeg0Ch) < 0)) { + DBGLOG(P2P, ERROR, "put vht seg0 fail.\n"); + goto nla_put_failure; + } + + if (unlikely(nla_put_u8(vendor_event, + WIFI_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL, + ucSeg1Ch) < 0)) { + DBGLOG(P2P, ERROR, "put vht seg1 fail.\n"); + goto nla_put_failure; + } + + if (unlikely(nla_put_u16(vendor_event, + WIFI_VENDOR_ATTR_ACS_CHWIDTH, + ch_width) < 0)) { + DBGLOG(P2P, ERROR, "put ch width fail.\n"); + goto nla_put_failure; + } + + if (unlikely(nla_put_u8(vendor_event, + WIFI_VENDOR_ATTR_ACS_HW_MODE, + ucPrimaryCh > 14 ? + P2P_VENDOR_ACS_HW_MODE_11A : + P2P_VENDOR_ACS_HW_MODE_11G) < 0)) { + DBGLOG(P2P, ERROR, "put hw mode fail.\n"); + goto nla_put_failure; + } +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE + cfg80211_vendor_event(vendor_event, GFP_KERNEL); +#endif + return; + +nla_put_failure: + if (vendor_event) + kfree_skb(vendor_event); +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_proc.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_proc.c new file mode 100644 index 0000000000000..c81d1e6716373 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_proc.c @@ -0,0 +1,1313 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E 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" + +#ifdef FW_CFG_SUPPORT +#include "fwcfg.h" +#endif +/* #include "wlan_lib.h" */ +/* #include "debug.h" */ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define PROC_WLAN_THERMO "wlanThermo" +#define PROC_COUNTRY "country" +#define PROC_DRV_STATUS "status" +#define PROC_RX_STATISTICS "rx_statistics" +#define PROC_TX_STATISTICS "tx_statistics" +#define PROC_DBG_LEVEL_NAME "dbgLevel" +#define PROC_NEED_TX_DONE "TxDoneCfg" +#define PROC_AUTO_PERF_CFG "autoPerfCfg" +#define PROC_ROOT_NAME "wlan" +#define PROC_CMD_DEBUG_NAME "cmdDebug" +#define PROC_CFG_NAME "cfg" +#if CFG_SUPPORT_SET_CAM_BY_PROC +#define PROC_SET_CAM "setCAM" +#endif + +#define PROC_MCR_ACCESS_MAX_USER_INPUT_LEN 20 +#define PROC_RX_STATISTICS_MAX_USER_INPUT_LEN 10 +#define PROC_TX_STATISTICS_MAX_USER_INPUT_LEN 10 +#define PROC_DBG_LEVEL_MAX_USER_INPUT_LEN (20*10) +#define PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN 8 + +#define PROC_UID_SHELL 2000 +#define PROC_GID_WIFI 1010 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +/* static UINT_32 u4McrOffset; */ +#if CFG_SUPPORT_THERMO_THROTTLING +static P_GLUE_INFO_T g_prGlueInfo_proc; +#endif +#if FW_CFG_SUPPORT +static P_GLUE_INFO_T gprGlueInfo; +#endif + +struct proc_dir_entry *prEntry; +typedef struct _PROC_CFG_ENTRY { + struct proc_dir_entry *prEntryWlanThermo; + struct proc_dir_entry *prEntryCountry; + struct proc_dir_entry *prEntryStatus; + struct proc_dir_entry *prEntryRxStatis; + struct proc_dir_entry *prEntryTxStatis; + struct proc_dir_entry *prEntryDbgLevel; + struct proc_dir_entry *prEntryTxDoneCfg; + struct proc_dir_entry *prEntryAutoPerCfg; + struct proc_dir_entry *prEntryCmdDbg; + struct proc_dir_entry *prEntryCfg; +#if CFG_SUPPORT_SET_CAM_BY_PROC + struct proc_dir_entry *prEntrySetCAM; +#endif +} PROC_CFG_ENTRY, *P_PROC_CFG_ENTRY; +static P_PROC_CFG_ENTRY gprProcCfgEntry; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* \brief The PROC function for reading MCR register to User Space, the offset of +* the MCR is specified in u4McrOffset. +* +* \param[in] page Buffer provided by kernel. +* \param[in out] start Start Address to read(3 methods). +* \param[in] off Offset. +* \param[in] count Allowable number to read. +* \param[out] eof End of File indication. +* \param[in] data Pointer to the private data structure. +* +* \return number of characters print to the buffer from User Space. +*/ +/*----------------------------------------------------------------------------*/ +#if 0 +static int procMCRRead(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + P_GLUE_INFO_T prGlueInfo; + PARAM_CUSTOM_MCR_RW_STRUCT_T rMcrInfo; + UINT_32 u4BufLen; + char *p = page; + UINT_32 u4Count; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + ASSERT(data); + + /* Kevin: Apply PROC read method 1. */ + if (off != 0) + return 0; /* To indicate end of file. */ + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv((struct net_device *)data)); + + rMcrInfo.u4McrOffset = u4McrOffset; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryMcrRead, + (PVOID)&rMcrInfo, sizeof(rMcrInfo), TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + /* SPRINTF(p, ("MCR (0x%08lxh): 0x%08lx\n", */ + /* rMcrInfo.u4McrOffset, rMcrInfo.u4McrData)); */ + + u4Count = (UINT_32) (p - page); + + *eof = 1; + + return (int)u4Count; + +} /* end of procMCRRead() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The PROC function for writing MCR register to HW or update u4McrOffset +* for reading MCR later. +* +* \param[in] file pointer to file. +* \param[in] buffer Buffer from user space. +* \param[in] count Number of characters to write +* \param[in] data Pointer to the private data structure. +* +* \return number of characters write from User Space. +*/ +/*----------------------------------------------------------------------------*/ +static int procMCRWrite(struct file *file, const char *buffer, unsigned long count, void *data) +{ + P_GLUE_INFO_T prGlueInfo; + char acBuf[PROC_MCR_ACCESS_MAX_USER_INPUT_LEN + 1]; /* + 1 for "\0" */ + int i4CopySize; + PARAM_CUSTOM_MCR_RW_STRUCT_T rMcrInfo; + UINT_32 u4BufLen; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + ASSERT(data); + + i4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + if (copy_from_user(acBuf, buffer, i4CopySize)) + return 0; + acBuf[i4CopySize] = '\0'; + + if (sscanf(acBuf, "0x%lx 0x%lx", &rMcrInfo.u4McrOffset, &rMcrInfo.u4McrData) == 2) { + /* NOTE: Sometimes we want to test if bus will still be ok, after accessing + * the MCR which is not align to DW boundary. + */ + /* if (IS_ALIGN_4(rMcrInfo.u4McrOffset)) */ + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv((struct net_device *)data)); + + u4McrOffset = rMcrInfo.u4McrOffset; + + /* printk("Write 0x%lx to MCR 0x%04lx\n", */ + /* rMcrInfo.u4McrOffset, rMcrInfo.u4McrData); */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetMcrWrite, + (PVOID)&rMcrInfo, sizeof(rMcrInfo), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + } + + if (sscanf(acBuf, "0x%lx 0x%lx", &rMcrInfo.u4McrOffset, &rMcrInfo.u4McrData) == 1) { + /* if (IS_ALIGN_4(rMcrInfo.u4McrOffset)) */ + u4McrOffset = rMcrInfo.u4McrOffset; + } + + return count; + +} /* end of procMCRWrite() */ +#endif + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief The PROC function for reading Driver Status to User Space. +* +* \param[in] page Buffer provided by kernel. +* \param[in out] start Start Address to read(3 methods). +* \param[in] off Offset. +* \param[in] count Allowable number to read. +* \param[out] eof End of File indication. +* \param[in] data Pointer to the private data structure. +* +* \return number of characters print to the buffer from User Space. +*/ +/*----------------------------------------------------------------------------*/ +static int procDrvStatusRead(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + P_GLUE_INFO_T prGlueInfo = ((struct net_device *)data)->priv; + char *p = page; + UINT_32 u4Count; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(data); + + /* Kevin: Apply PROC read method 1. */ + if (off != 0) + return 0; /* To indicate end of file. */ + + SPRINTF(p, ("GLUE LAYER STATUS:")); + SPRINTF(p, ("\n==================")); + + SPRINTF(p, ("\n* Number of Pending Frames: %ld\n", prGlueInfo->u4TxPendingFrameNum)); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + wlanoidQueryDrvStatusForLinuxProc(prGlueInfo->prAdapter, p, &u4Count); + + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + u4Count += (UINT_32) (p - page); + + *eof = 1; + + return (int)u4Count; + +} /* end of procDrvStatusRead() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The PROC function for reading Driver RX Statistic Counters to User Space. +* +* \param[in] page Buffer provided by kernel. +* \param[in out] start Start Address to read(3 methods). +* \param[in] off Offset. +* \param[in] count Allowable number to read. +* \param[out] eof End of File indication. +* \param[in] data Pointer to the private data structure. +* +* \return number of characters print to the buffer from User Space. +*/ +/*----------------------------------------------------------------------------*/ +static int procRxStatisticsRead(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + P_GLUE_INFO_T prGlueInfo = ((struct net_device *)data)->priv; + char *p = page; + UINT_32 u4Count; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(data); + + /* Kevin: Apply PROC read method 1. */ + if (off != 0) + return 0; /* To indicate end of file. */ + + SPRINTF(p, ("RX STATISTICS (Write 1 to clear):")); + SPRINTF(p, ("\n=================================\n")); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + wlanoidQueryRxStatisticsForLinuxProc(prGlueInfo->prAdapter, p, &u4Count); + + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + u4Count += (UINT_32) (p - page); + + *eof = 1; + + return (int)u4Count; + +} /* end of procRxStatisticsRead() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The PROC function for reset Driver RX Statistic Counters. +* +* \param[in] file pointer to file. +* \param[in] buffer Buffer from user space. +* \param[in] count Number of characters to write +* \param[in] data Pointer to the private data structure. +* +* \return number of characters write from User Space. +*/ +/*----------------------------------------------------------------------------*/ +static int procRxStatisticsWrite(struct file *file, const char *buffer, unsigned long count, void *data) +{ + P_GLUE_INFO_T prGlueInfo = ((struct net_device *)data)->priv; + char acBuf[PROC_RX_STATISTICS_MAX_USER_INPUT_LEN + 1]; /* + 1 for "\0" */ + UINT_32 u4CopySize; + UINT_32 u4ClearCounter; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(data); + + u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + copy_from_user(acBuf, buffer, u4CopySize); + acBuf[u4CopySize] = '\0'; + + if (kstrtoint(acBuf, 10, &u4ClearCounter) == 1) { + if (u4ClearCounter == 1) { + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + wlanoidSetRxStatisticsForLinuxProc(prGlueInfo->prAdapter); + + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + } + } + + return count; + +} /* end of procRxStatisticsWrite() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The PROC function for reading Driver TX Statistic Counters to User Space. +* +* \param[in] page Buffer provided by kernel. +* \param[in out] start Start Address to read(3 methods). +* \param[in] off Offset. +* \param[in] count Allowable number to read. +* \param[out] eof End of File indication. +* \param[in] data Pointer to the private data structure. +* +* \return number of characters print to the buffer from User Space. +*/ +/*----------------------------------------------------------------------------*/ +static int procTxStatisticsRead(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + P_GLUE_INFO_T prGlueInfo = ((struct net_device *)data)->priv; + char *p = page; + UINT_32 u4Count; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(data); + + /* Kevin: Apply PROC read method 1. */ + if (off != 0) + return 0; /* To indicate end of file. */ + + SPRINTF(p, ("TX STATISTICS (Write 1 to clear):")); + SPRINTF(p, ("\n=================================\n")); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + wlanoidQueryTxStatisticsForLinuxProc(prGlueInfo->prAdapter, p, &u4Count); + + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + u4Count += (UINT_32) (p - page); + + *eof = 1; + + return (int)u4Count; + +} /* end of procTxStatisticsRead() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The PROC function for reset Driver TX Statistic Counters. +* +* \param[in] file pointer to file. +* \param[in] buffer Buffer from user space. +* \param[in] count Number of characters to write +* \param[in] data Pointer to the private data structure. +* +* \return number of characters write from User Space. +*/ +/*----------------------------------------------------------------------------*/ +static int procTxStatisticsWrite(struct file *file, const char *buffer, unsigned long count, void *data) +{ + P_GLUE_INFO_T prGlueInfo = ((struct net_device *)data)->priv; + char acBuf[PROC_RX_STATISTICS_MAX_USER_INPUT_LEN + 1]; /* + 1 for "\0" */ + UINT_32 u4CopySize; + UINT_32 u4ClearCounter; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(data); + + u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + copy_from_user(acBuf, buffer, u4CopySize); + acBuf[u4CopySize] = '\0'; + + if (kstrtoint(acBuf, 10, &u4ClearCounter) == 1) { + if (u4ClearCounter == 1) { + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + wlanoidSetTxStatisticsForLinuxProc(prGlueInfo->prAdapter); + + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + } + } + + return count; + +} /* end of procTxStatisticsWrite() */ +#endif +static struct proc_dir_entry *gprProcRoot; +static UINT_8 aucDbModuleName[][PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN] = { + "INIT", "HAL", "INTR", "REQ", "TX", "RX", "RFTEST", "EMU", "SW1", "SW2", + "SW3", "SW4", "HEM", "AIS", "RLM", "MEM", "CNM", "RSN", "BSS", "SCN", + "SAA", "AAA", "P2P", "QM", "SEC", "BOW", "WAPI", "ROAMING", "TDLS", "OID", + "NIC", "WNM", "WMM" +}; +static UINT_8 aucProcBuf[1536]; +static ssize_t procDbgLevelRead(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + UINT_8 *temp = &aucProcBuf[0]; + UINT_32 u4CopySize = 0; + UINT_16 i; + UINT_16 u2ModuleNum = 0; + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0) + return 0; + + kalStrCpy(temp, "\nTEMP |LOUD |INFO |TRACE|EVENT|STATE|WARN |ERROR\n" + "bit7 |bit6 |bit5 |bit4 |bit3 |bit2 |bit1 |bit0\n\n" + "Debug Module\tIndex\tLevel\tDebug Module\tIndex\tLevel\n\n"); + temp += kalStrLen(temp); + + u2ModuleNum = (sizeof(aucDbModuleName) / PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN) & 0xfe; + for (i = 0; i < u2ModuleNum; i += 2) + SPRINTF(temp, ("DBG_%s_IDX\t(0x%02x):\t0x%02x\tDBG_%s_IDX\t(0x%02x):\t0x%02x\n", + &aucDbModuleName[i][0], i, aucDebugModule[i], + &aucDbModuleName[i+1][0], i+1, aucDebugModule[i+1])); + + if ((sizeof(aucDbModuleName) / PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN) & 0x1) + SPRINTF(temp, ("DBG_%s_IDX\t(0x%02x):\t0x%02x\n", + &aucDbModuleName[u2ModuleNum][0], u2ModuleNum, aucDebugModule[u2ModuleNum])); + + u4CopySize = kalStrLen(aucProcBuf); + if (u4CopySize > count) + u4CopySize = count; + if (copy_to_user(buf, aucProcBuf, u4CopySize)) { + kalPrint("copy to user failed\n"); + return -EFAULT; + } + + *f_pos += u4CopySize; + return (ssize_t)u4CopySize; +} + +static ssize_t procDbgLevelWrite(struct file *file, const char *buffer, size_t count, loff_t *data) +{ + UINT_32 u4NewDbgModule, u4NewDbgLevel; + UINT_8 i = 0; + UINT_32 u4CopySize = sizeof(aucProcBuf); + UINT_8 *temp = &aucProcBuf[0]; + + kalMemSet(aucProcBuf, 0, u4CopySize); + u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1); + + if (copy_from_user(aucProcBuf, buffer, u4CopySize)) { + kalPrint("error of copy from user\n"); + return -EFAULT; + } + aucProcBuf[u4CopySize] = '\0'; + + while (temp) { + if (sscanf(temp, "0x%x:0x%x", &u4NewDbgModule, &u4NewDbgLevel) != 2) { + kalPrint("debug module and debug level should be one byte in length\n"); + break; + } + if (u4NewDbgModule == 0xFF) { + for (i = 0; i < DBG_MODULE_NUM; i++) + aucDebugModule[i] = u4NewDbgLevel & DBG_CLASS_MASK; + + break; + } else if (u4NewDbgModule >= DBG_MODULE_NUM) { + kalPrint("debug module index should less than %d\n", DBG_MODULE_NUM); + break; + } + aucDebugModule[u4NewDbgModule] = u4NewDbgLevel & DBG_CLASS_MASK; + temp = kalStrChr(temp, ','); + if (!temp) + break; + temp++; /* skip ',' */ + } + wlanDbgLevelSync(); + return count; +} + + +static const struct file_operations dbglevel_ops = { + .owner = THIS_MODULE, + .read = procDbgLevelRead, + .write = procDbgLevelWrite, +}; + +static ssize_t procTxDoneCfgRead(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + UINT_8 *temp = &aucProcBuf[0]; + UINT_32 u4CopySize = 0; + UINT_16 u2TxDoneCfg = 0; + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0) + return 0; + + u2TxDoneCfg = StatsGetCfgTxDone(); + SPRINTF(temp, ("Tx Done Configure:\nARP %d\tDNS %d\nTCP %d\tUDP %d\nEAPOL %d\tDHCP %d\nICMP %d\n", + !!(u2TxDoneCfg & CFG_ARP), !!(u2TxDoneCfg & CFG_DNS), !!(u2TxDoneCfg & CFG_TCP), + !!(u2TxDoneCfg & CFG_UDP), !!(u2TxDoneCfg & CFG_EAPOL), !!(u2TxDoneCfg & CFG_DHCP), + !!(u2TxDoneCfg & CFG_ICMP))); + + u4CopySize = kalStrLen(aucProcBuf); + if (u4CopySize > count) + u4CopySize = count; + if (copy_to_user(buf, aucProcBuf, u4CopySize)) { + kalPrint("copy to user failed\n"); + return -EFAULT; + } + + *f_pos += u4CopySize; + return (ssize_t)u4CopySize; +} + +static ssize_t procTxDoneCfgWrite(struct file *file, const char *buffer, size_t count, loff_t *data) +{ +#define MODULE_NAME_LENGTH 6 + + UINT_8 i = 0; + UINT_32 u4CopySize = sizeof(aucProcBuf); + UINT_8 *temp = &aucProcBuf[0]; + UINT_16 u2SetTxDoneCfg = 0; + UINT_16 u2ClsTxDoneCfg = 0; + UINT_8 aucModule[MODULE_NAME_LENGTH]; + UINT_32 u4Enabled; + UINT_8 aucModuleArray[][MODULE_NAME_LENGTH] = {"ARP", "DNS", "TCP", "UDP", "EAPOL", "DHCP", "ICMP"}; + + kalMemSet(aucProcBuf, 0, u4CopySize); + u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1); + + if (copy_from_user(aucProcBuf, buffer, u4CopySize)) { + kalPrint("error of copy from user\n"); + return -EFAULT; + } + aucProcBuf[u4CopySize] = '\0'; + temp = &aucProcBuf[0]; + while (temp) { + kalMemSet(aucModule, 0, MODULE_NAME_LENGTH); + + /* pick up a string and teminated after meet : */ + if (sscanf(temp, "%5s %d", aucModule, &u4Enabled) != 2) { + kalPrint("read param fail, aucModule=%s\n", aucModule); + break; + } + for (i = 0; i < sizeof(aucModuleArray)/MODULE_NAME_LENGTH; i++) { + if (kalStrniCmp(aucModule, aucModuleArray[i], MODULE_NAME_LENGTH) == 0) { + if (u4Enabled) + u2SetTxDoneCfg |= 1 << i; + else + u2ClsTxDoneCfg |= 1 << i; + break; + } + } + temp = kalStrChr(temp, ','); + if (!temp) + break; + temp++; /* skip ',' */ + } + if (u2SetTxDoneCfg) + StatsSetCfgTxDone(u2SetTxDoneCfg, TRUE); + + if (u2ClsTxDoneCfg) + StatsSetCfgTxDone(u2ClsTxDoneCfg, FALSE); + return count; +} + +static const struct file_operations proc_txdone_ops = { + .owner = THIS_MODULE, + .read = procTxDoneCfgRead, + .write = procTxDoneCfgWrite, +}; + +static ssize_t procAutoPerfCfgRead(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + UINT_8 *temp = &aucProcBuf[0]; + UINT_32 u4CopySize = 0; + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0) + return 0; + + SPRINTF(temp, ("Auto Performance Configure:\ncore_num:frequence\n")); + + u4CopySize = kalStrLen(aucProcBuf); + if (u4CopySize > count) + u4CopySize = count; + if (copy_to_user(buf, aucProcBuf, u4CopySize)) { + kalPrint("copy to user failed\n"); + return -EFAULT; + } + + *f_pos += u4CopySize; + return (ssize_t)u4CopySize; +} + +static ssize_t procAutoPerfCfgWrite(struct file *file, const char *buffer, size_t count, loff_t *data) +{ + UINT_32 u4CoreNum = 0; + UINT_32 u4CoreFreq = 0; + UINT_8 *temp = &aucProcBuf[0]; + UINT_32 u4CopySize = count; + + DBGLOG(INIT, WARN, "%s\n", __func__); + + if (u4CopySize >= sizeof(aucProcBuf)) + u4CopySize = sizeof(aucProcBuf) - 1; + + kalMemSet(aucProcBuf, 0, u4CopySize); + + if (copy_from_user(aucProcBuf, buffer, u4CopySize)) { + kalPrint("error of copy from user\n"); + return -EFAULT; + } + + aucProcBuf[u4CopySize] = '\0'; + + if (sscanf(temp, "%d:%d", &u4CoreNum, &u4CoreFreq) != 2) { + DBGLOG(INIT, WARN, "parameter format should be u4CoreNum:u4CoreFreq\n"); + return -EFAULT; + } + DBGLOG(INIT, WARN, "u4CoreNum:%d, u4CoreFreq:%d\n", u4CoreNum, u4CoreFreq); + + kalSetCpuNumFreq(u4CoreNum, u4CoreFreq); + + return u4CopySize; +} + +static const struct file_operations auto_perf_ops = { + .owner = THIS_MODULE, + .read = procAutoPerfCfgRead, + .write = procAutoPerfCfgWrite, +}; + + +static ssize_t procCmdDebug(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + UINT_32 u4CopySize = 0; + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0) + return 0; + + wlanDumpTcResAndTxedCmd(aucProcBuf, sizeof(aucProcBuf)); + + u4CopySize = kalStrLen(aucProcBuf); + if (u4CopySize > count) + u4CopySize = count; + if (copy_to_user(buf, aucProcBuf, u4CopySize)) { + kalPrint("copy to user failed\n"); + return -EFAULT; + } + + *f_pos += u4CopySize; + return (ssize_t)u4CopySize; +} + +static const struct file_operations proc_CmdDebug_ops = { + .owner = THIS_MODULE, + .read = procCmdDebug, +}; + +static ssize_t procCountryRead(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + UINT_32 u4CopySize; + UINT_16 u2CountryCode = 0; + + /* if *f_pos > 0, it means has read successed last time, don't try again */ + if (*f_pos > 0) + return 0; + + if (g_prGlueInfo_proc && g_prGlueInfo_proc->prAdapter) + u2CountryCode = g_prGlueInfo_proc->prAdapter->rWifiVar.rConnSettings.u2CountryCode; + + if (u2CountryCode) + kalSprintf(aucProcBuf, "Current Country Code: %c%c\n", (u2CountryCode>>8) & 0xff, u2CountryCode & 0xff); + else + kalStrnCpy(aucProcBuf, "Current Country Code: NULL\n", strlen("Current Country Code: NULL\n") + 1); + + u4CopySize = kalStrLen(aucProcBuf); + if (copy_to_user(buf, aucProcBuf, u4CopySize)) { + pr_info("copy to user failed\n"); + return -EFAULT; + } + *f_pos += u4CopySize; + + return (INT_32)u4CopySize; +} + +static ssize_t procCountryWrite(struct file *file, const char __user *buffer, size_t count, loff_t *data) +{ + UINT_32 u4BufLen = 0; + WLAN_STATUS rStatus; + UINT_32 u4CopySize = sizeof(aucProcBuf); + + kalMemSet(aucProcBuf, 0, u4CopySize); + u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1); + + if (copy_from_user(aucProcBuf, buffer, u4CopySize)) { + pr_info("error of copy from user\n"); + return -EFAULT; + } + + aucProcBuf[u4CopySize] = '\0'; + rStatus = kalIoctl(g_prGlueInfo_proc, + wlanoidSetCountryCode, &aucProcBuf[0], 2, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "failed set country code: %s\n", aucProcBuf); + return -EINVAL; + } + return count; +} + +static const struct file_operations country_ops = { + .owner = THIS_MODULE, + .read = procCountryRead, + .write = procCountryWrite, +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function create a PROC fs in linux /proc/net subdirectory. +* +* \param[in] prDev Pointer to the struct net_device. +* \param[in] pucDevName Pointer to the name of net_device. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ + +#if CFG_SUPPORT_THERMO_THROTTLING + +/** + * This function is called then the /proc file is read + * + */ +typedef struct _COEX_BUF1 { + UINT8 buffer[128]; + INT32 availSize; +} COEX_BUF1, *P_COEX_BUF1; + +COEX_BUF1 gCoexBuf1; + +static ssize_t procfile_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + + INT32 retval = 0; + INT32 i_ret = 0; + CHAR *warn_msg = "no data available, please run echo 15 xx > /proc/driver/wmt_psm first\n"; + + if (*f_pos > 0) { + retval = 0; + } else { + /*len = sprintf(page, "%d\n", g_psm_enable); */ + if (gCoexBuf1.availSize <= 0) { + DBGLOG(INIT, WARN, "no data available\n"); + retval = strlen(warn_msg) + 1; + if (count < retval) + retval = count; + i_ret = copy_to_user(buf, warn_msg, retval); + if (i_ret) { + DBGLOG(INIT, ERROR, "copy to buffer failed, ret:%d\n", retval); + retval = -EFAULT; + goto err_exit; + } + *f_pos += retval; + } else { + INT32 i = 0; + INT32 len = 0; + CHAR msg_info[128]; + INT32 max_num = 0; + /* + * we do not check page buffer, because there are only 100 bytes in g_coex_buf, no reason page + * buffer is not enough, a bomb is placed here on unexpected condition + */ + + DBGLOG(INIT, TRACE, "%d bytes available\n", gCoexBuf1.availSize); + max_num = ((sizeof(msg_info) > count ? sizeof(msg_info) : count) - 1) / 5; + + if (max_num > gCoexBuf1.availSize) + max_num = gCoexBuf1.availSize; + else + DBGLOG(INIT, TRACE, + "round to %d bytes due to local buffer size limitation\n", max_num); + + for (i = 0; i < max_num; i++) + len += sprintf(msg_info + len, "%d", gCoexBuf1.buffer[i]); + + len += sprintf(msg_info + len, "\n"); + retval = len; + + i_ret = copy_to_user(buf, msg_info, retval); + if (i_ret) { + DBGLOG(INIT, ERROR, "copy to buffer failed, ret:%d\n", retval); + retval = -EFAULT; + goto err_exit; + } + *f_pos += retval; + } + } + gCoexBuf1.availSize = 0; +err_exit: + + return retval; +} + +typedef INT32 (*WLAN_DEV_DBG_FUNC)(void); +static INT32 wlan_get_thermo_power(void); +static INT32 wlan_get_link_mode(void); + +static const WLAN_DEV_DBG_FUNC wlan_dev_dbg_func[] = { + [0] = wlan_get_thermo_power, + [1] = wlan_get_link_mode, + +}; + +INT32 wlan_get_thermo_power(void) +{ + P_ADAPTER_T prAdapter; + + prAdapter = g_prGlueInfo_proc->prAdapter; + + if (prAdapter->u4AirDelayTotal > 100) + gCoexBuf1.buffer[0] = 100; + else + gCoexBuf1.buffer[0] = prAdapter->u4AirDelayTotal; + gCoexBuf1.availSize = 1; + DBGLOG(RLM, TRACE, "PROC %s thrmo_power(%d)\n", __func__, gCoexBuf1.buffer[0]); + + return 0; +} + +INT32 wlan_get_link_mode(void) +{ + UINT_8 ucLinkMode = 0; + P_ADAPTER_T prAdapter; + BOOLEAN fgIsAPmode; + + prAdapter = g_prGlueInfo_proc->prAdapter; + fgIsAPmode = p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo); + + DBGLOG(RLM, TRACE, "PROC %s AIS(%d)P2P(%d)AP(%d)\n", + __func__, + prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].eConnectionState, + prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].eConnectionState, fgIsAPmode); + + + if (prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].eConnectionState == PARAM_MEDIA_STATE_CONNECTED) + ucLinkMode |= BIT(0); + if (prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].eConnectionState == PARAM_MEDIA_STATE_CONNECTED) + ucLinkMode |= BIT(1); + if (fgIsAPmode) + ucLinkMode |= BIT(2); + + gCoexBuf1.buffer[0] = ucLinkMode; + gCoexBuf1.availSize = 1; + + return 0; +} + +static ssize_t procfile_write(struct file *filp, const char __user *buffer, + size_t count, loff_t *f_pos) +{ + char buf[256]; + char *pBuf; + ULONG len = count; + unsigned int x = 0; + char *pToken = NULL; + char *pDelimiter = " \t"; + INT32 i4Ret = -1; + + DBGLOG(INIT, TRACE, "write parameter len = %d\n\r", (INT32) len); + if (len >= sizeof(buf)) { + DBGLOG(INIT, ERROR, "input handling fail!\n"); + return -1; + } + + if (copy_from_user(buf, buffer, len)) + return -EFAULT; + + buf[len] = '\0'; + DBGLOG(INIT, TRACE, "write parameter data = %s\n\r", buf); + pBuf = buf; + pToken = strsep(&pBuf, pDelimiter); + if (pToken) { + i4Ret = kalkStrtou32(pToken, 16, &x); + if (!i4Ret) + DBGLOG(INIT, TRACE, " x(0x%08x)\n\r", x); + } + + if ((!i4Ret) && (ARRAY_SIZE(wlan_dev_dbg_func) > x) && + (NULL != wlan_dev_dbg_func[x])) + (*wlan_dev_dbg_func[x]) (); + else + DBGLOG(INIT, ERROR, + "no handler defined for command id(0x%08x), pToken=%p, i4Ret=%d\n\r", + x, pToken, i4Ret); + + return len; +} + +static const struct file_operations proc_fops = { + .owner = THIS_MODULE, + .read = procfile_read, + .write = procfile_write, +}; +#endif + +#if CFG_SUPPORT_SET_CAM_BY_PROC +static ssize_t procSetCamCfgWrite(struct file *file, const char *buffer, size_t count, loff_t *data) +{ +#define MODULE_NAME_LEN_1 5 + + UINT_32 u4CopySize = sizeof(aucProcBuf); + UINT_8 *temp = &aucProcBuf[0]; + BOOLEAN fgSetCamCfg = FALSE; + UINT_8 aucModule[MODULE_NAME_LEN_1]; + UINT_32 u4Enabled; + UINT_8 aucModuleArray[MODULE_NAME_LEN_1] = "CAM"; + + kalMemSet(aucProcBuf, 0, u4CopySize); + u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1); + + if (copy_from_user(aucProcBuf, buffer, u4CopySize)) { + pr_info("error of copy from user\n"); + return -EFAULT; + } + aucProcBuf[u4CopySize] = '\0'; + temp = &aucProcBuf[0]; + while (temp) { + kalMemSet(aucModule, 0, MODULE_NAME_LEN_1); + + /* pick up a string and teminated after meet : */ + if (sscanf(temp, "%4s %d", aucModule, &u4Enabled) != 2) { + pr_info("read param fail, aucModule=%s\n", aucModule); + break; + } + + if (kalStrnCmp(aucModule, aucModuleArray, MODULE_NAME_LEN_1) == 0) { + if (u4Enabled) + fgSetCamCfg = TRUE; + else + fgSetCamCfg = FALSE; + break; + } + temp = kalStrChr(temp, ','); + if (!temp) + break; + temp++; /* skip ',' */ + } + + nicConfigProcSetCamCfgWrite(fgSetCamCfg); + + return count; +} + +static const struct file_operations proc_set_cam_ops = { + .owner = THIS_MODULE, + .write = procSetCamCfgWrite, +}; +#endif + +INT_32 procInitFs(VOID) +{ + if (init_net.proc_net == (struct proc_dir_entry *)NULL) { + DBGLOG(INIT, ERROR, "init proc fs fail: proc_net == NULL\n"); + return -ENOENT; + } + + /* + * Directory: Root (/proc/net/wlan0) + */ + + gprProcRoot = proc_mkdir(PROC_ROOT_NAME, init_net.proc_net); + if (!gprProcRoot) { + DBGLOG(INIT, ERROR, "gprProcRoot == NULL\n"); + return -ENOENT; + } + proc_set_user(gprProcRoot, KUIDT_INIT(PROC_UID_SHELL), KGIDT_INIT(PROC_GID_WIFI)); + + gprProcCfgEntry = kalMemAlloc(sizeof(PROC_CFG_ENTRY), PHY_MEM_TYPE); + kalMemZero(gprProcCfgEntry, sizeof(PROC_CFG_ENTRY)); + + gprProcCfgEntry->prEntryDbgLevel = proc_create(PROC_DBG_LEVEL_NAME, 0664, gprProcRoot, &dbglevel_ops); + + if (gprProcCfgEntry->prEntryDbgLevel == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry %s/n", PROC_DBG_LEVEL_NAME); + return -1; + } + proc_set_user(gprProcCfgEntry->prEntryDbgLevel, KUIDT_INIT(PROC_UID_SHELL), KGIDT_INIT(PROC_GID_WIFI)); + + gprProcCfgEntry->prEntryTxDoneCfg = proc_create(PROC_NEED_TX_DONE, 0664, gprProcRoot, &proc_txdone_ops); + if (gprProcCfgEntry->prEntryTxDoneCfg == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry %s/n", PROC_NEED_TX_DONE); + return -1; + } + proc_set_user(gprProcCfgEntry->prEntryTxDoneCfg, KUIDT_INIT(PROC_UID_SHELL), KGIDT_INIT(PROC_GID_WIFI)); + + gprProcCfgEntry->prEntryAutoPerCfg = proc_create(PROC_AUTO_PERF_CFG, 0664, gprProcRoot, &auto_perf_ops); + if (gprProcCfgEntry->prEntryAutoPerCfg == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry %s/n", PROC_AUTO_PERF_CFG); + return -1; + } + proc_set_user(gprProcCfgEntry->prEntryAutoPerCfg, KUIDT_INIT(PROC_UID_SHELL), KGIDT_INIT(PROC_GID_WIFI)); + + gprProcCfgEntry->prEntryCountry = proc_create(PROC_COUNTRY, 0664, gprProcRoot, &country_ops); + if (gprProcCfgEntry->prEntryCountry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry %s/n", PROC_COUNTRY); + return -1; + } + + return 0; +} /* end of procInitProcfs() */ + +INT_32 procUninitProcFs(VOID) +{ + if (gprProcRoot) { + if (gprProcCfgEntry->prEntryDbgLevel) + remove_proc_entry(PROC_DBG_LEVEL_NAME, gprProcRoot); + else + DBGLOG(INIT, ERROR, "%s PROC_DBG_LEVEL_NAME is null/n", __func__); + + if (gprProcCfgEntry->prEntryAutoPerCfg) + remove_proc_entry(PROC_AUTO_PERF_CFG, gprProcRoot); + else + DBGLOG(INIT, ERROR, "%s PROC_AUTO_PERF_CFG is null/n", __func__); + + if (gprProcCfgEntry->prEntryCountry) + remove_proc_entry(PROC_COUNTRY, gprProcRoot); + else + DBGLOG(INIT, ERROR, "%s PROC_COUNTRY is null/n", __func__); + + remove_proc_subtree(PROC_ROOT_NAME, init_net.proc_net); + + if (gprProcCfgEntry) + kalMemFree(gprProcCfgEntry, sizeof(PROC_CFG_ENTRY), PHY_MEM_TYPE); + + } else { + DBGLOG(INIT, ERROR, "%s gprProcRoot ist null/n", __func__); + } + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function clean up a PROC fs created by procInitProcfs(). +* +* \param[in] prDev Pointer to the struct net_device. +* \param[in] pucDevName Pointer to the name of net_device. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +INT_32 procRemoveProcfs(VOID) +{ + /* remove root directory (proc/net/wlan0) */ + /* remove_proc_entry(pucDevName, init_net.proc_net); */ + if (gprProcCfgEntry->prEntryWlanThermo) { + remove_proc_entry(PROC_WLAN_THERMO, gprProcRoot); + gprProcCfgEntry->prEntryWlanThermo = NULL; + } else + DBGLOG(INIT, ERROR, "%s PROC_WLAN_THERMO is null\n", __func__); + + if (gprProcCfgEntry->prEntryCmdDbg) { + remove_proc_entry(PROC_CMD_DEBUG_NAME, gprProcRoot); + gprProcCfgEntry->prEntryCmdDbg = NULL; + } else + DBGLOG(INIT, ERROR, "%s PROC_CMD_DEBUG_NAME is null\n", __func__); + +#if CFG_SUPPORT_SET_CAM_BY_PROC + if (gprProcCfgEntry->prEntrySetCAM) { + remove_proc_entry(PROC_SET_CAM, gprProcRoot); + gprProcCfgEntry->prEntrySetCAM = NULL; + } else + DBGLOG(INIT, ERROR, "%s PROC_SET_CAM is null\n", __func__); +#endif + +#if CFG_SUPPORT_THERMO_THROTTLING + g_prGlueInfo_proc = NULL; +#endif + return 0; +} /* end of procRemoveProcfs() */ + +INT_32 procCreateFsEntry(P_GLUE_INFO_T prGlueInfo) +{ + + DBGLOG(INIT, TRACE, "[%s]\n", __func__); + +#if CFG_SUPPORT_THERMO_THROTTLING + g_prGlueInfo_proc = prGlueInfo; +#endif + + prGlueInfo->pProcRoot = gprProcRoot; + if (gprProcCfgEntry->prEntryWlanThermo) + DBGLOG(INIT, WARN, "proc entry %s is exist\n", PROC_WLAN_THERMO); + + gprProcCfgEntry->prEntryWlanThermo = proc_create(PROC_WLAN_THERMO, 0664, gprProcRoot, &proc_fops); + if (gprProcCfgEntry->prEntryWlanThermo == NULL) { + DBGLOG(INIT, WARN, "Unable to create /proc entry %s\n", PROC_WLAN_THERMO); + return -1; + } + + if (gprProcCfgEntry->prEntryCmdDbg) + DBGLOG(INIT, WARN, "proc entry %s is exist\n", PROC_CMD_DEBUG_NAME); + + gprProcCfgEntry->prEntryCmdDbg = proc_create(PROC_CMD_DEBUG_NAME, 0444, gprProcRoot, &proc_CmdDebug_ops); + if (gprProcCfgEntry->prEntryCmdDbg == NULL) { + DBGLOG(INIT, WARN, "Unable to create /proc entry %s\n", PROC_CMD_DEBUG_NAME); + return -1; + } + proc_set_user(gprProcCfgEntry->prEntryCmdDbg, KUIDT_INIT(PROC_UID_SHELL), KGIDT_INIT(PROC_GID_WIFI)); + +#if CFG_SUPPORT_SET_CAM_BY_PROC + if (gprProcCfgEntry->prEntrySetCAM) + DBGLOG(INIT, WARN, "proc entry %s is exist\n", PROC_SET_CAM); + + gprProcCfgEntry->prEntrySetCAM = proc_create(PROC_SET_CAM, 0664, gprProcRoot, &proc_set_cam_ops); + if (gprProcCfgEntry->prEntrySetCAM == NULL) { + DBGLOG(INIT, WARN, "Unable to create /proc entry %s\n", PROC_SET_CAM); + return -1; + } + proc_set_user(gprProcCfgEntry->prEntrySetCAM, KUIDT_INIT(PROC_UID_SHELL), KGIDT_INIT(PROC_GID_WIFI)); +#endif + + return 0; +} + +#ifdef FW_CFG_SUPPORT +#define MAX_CFG_OUTPUT_BUF_LENGTH 1024 +static UINT_8 aucCfgBuf[CMD_FORMAT_V1_LENGTH]; +static UINT_8 aucCfgQueryKey[MAX_CMD_NAME_MAX_LENGTH]; +static UINT_8 aucCfgOutputBuf[MAX_CFG_OUTPUT_BUF_LENGTH]; + +static ssize_t cfgRead(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_8 *temp = &aucCfgOutputBuf[0]; + UINT_32 u4CopySize = 0; + UINT_32 u4Offset = 0; + PCHAR pHeadOutputString = "\nprocCfgRead() "; + struct _CMD_HEADER_T cmdV1Header; + struct _CMD_FORMAT_V1_T *pr_cmd_v1 = (struct _CMD_FORMAT_V1_T *) cmdV1Header.buffer; + + /* if *f_pos > 0, we should return 0 to make cat command exit */ + if (*f_pos > 0 || gprGlueInfo == NULL) + return 0; + + kalMemSet(aucCfgOutputBuf, '\0', MAX_CFG_OUTPUT_BUF_LENGTH); + + u4Offset += kalSnprintf(temp + u4Offset, MAX_CFG_OUTPUT_BUF_LENGTH - u4Offset, "%s", + pHeadOutputString); + + u4Offset += kalSnprintf(temp + u4Offset, MAX_CFG_OUTPUT_BUF_LENGTH - u4Offset, "%s:\n", + aucCfgQueryKey); + + /* send to FW */ + cmdV1Header.cmdVersion = CMD_VER_1; + cmdV1Header.cmdType = CMD_TYPE_QUERY; + cmdV1Header.itemNum = 1; + cmdV1Header.cmdBufferLen = sizeof(struct _CMD_FORMAT_V1_T); + kalMemSet(cmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); + + pr_cmd_v1->itemStringLength = kalStrLen(aucCfgQueryKey); + kalMemCopy(pr_cmd_v1->itemString, aucCfgQueryKey, kalStrLen(aucCfgQueryKey)); + + rStatus = kalIoctl(gprGlueInfo, + wlanoidQueryCfgRead, + (PVOID)&cmdV1Header, + sizeof(cmdV1Header), + TRUE, + TRUE, + TRUE, + FALSE, + &u4CopySize); + if (rStatus == WLAN_STATUS_FAILURE) + DBGLOG(INIT, ERROR, "prCmdV1Header kalIoctl wlanoidQueryCfgRead fail 0x%x\n", rStatus); + + u4Offset += kalSnprintf(temp + u4Offset, MAX_CFG_OUTPUT_BUF_LENGTH - u4Offset, "%s\n", + cmdV1Header.buffer); + + u4CopySize = kalStrLen(aucCfgOutputBuf); + DBGLOG(INIT, INFO, "cfgRead: count:%zu u4CopySize:%d,[%s]\n", count, u4CopySize, aucCfgOutputBuf); + if (u4CopySize > count) + u4CopySize = count; + + if (copy_to_user(buf, aucCfgOutputBuf, u4CopySize)) + DBGLOG(INIT, ERROR, "copy to user failed\n"); + + *f_pos += u4CopySize; + return (ssize_t)u4CopySize; +} + +static ssize_t cfgWrite(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) +{ + /* echo xxx xxx > /proc/net/wlan/cfg */ + UINT_8 i = 0; + UINT_32 u4CopySize = sizeof(aucCfgBuf); + UINT_8 token_num = 1; + + kalMemSet(aucCfgBuf, '\0', u4CopySize); + u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1); + + if (copy_from_user(aucCfgBuf, buf, u4CopySize)) { + DBGLOG(INIT, ERROR, "copy from user failed\n"); + return -EFAULT; + } + + if (u4CopySize > 0) + aucCfgBuf[u4CopySize - 1] = '\0'; + + for (; i < u4CopySize; i++) { + if (aucCfgBuf[i] == ' ') { + token_num++; + break; + } + } + + DBGLOG(INIT, INFO, "procCfgWrite :%s token_num:%d input_size :%zu\n" + , aucCfgBuf, token_num, count); + + if (token_num == 1) { + kalMemSet(aucCfgQueryKey, 0, sizeof(aucCfgQueryKey)); + u4CopySize = ((u4CopySize > sizeof(aucCfgQueryKey)) ? sizeof(aucCfgQueryKey) : u4CopySize); + memcpy(aucCfgQueryKey, aucCfgBuf, u4CopySize); + /*replace Carriage Return (0x0a) to string end of terminal */ + if ((u4CopySize > 0) && (aucCfgQueryKey[u4CopySize - 1] == 0x0a)) + aucCfgQueryKey[u4CopySize - 1] = '\0'; + } else { + if (u4CopySize) + wlanFwCfgParse(gprGlueInfo->prAdapter, aucCfgBuf); + } + + return count; +} + +static const struct file_operations cfg_ops = { + .owner = THIS_MODULE, + .read = cfgRead, + .write = cfgWrite, +}; + +INT_32 cfgRemoveProcEntry(void) +{ + if (gprProcCfgEntry->prEntryCfg) { + remove_proc_entry(PROC_CFG_NAME, gprProcRoot); + gprProcCfgEntry->prEntryCfg = NULL; + } else + DBGLOG(INIT, ERROR, "%s PROC_CFG_NAME is null\n", __func__); + return 0; +} + +INT_32 cfgCreateProcEntry(P_GLUE_INFO_T prGlueInfo) +{ + prGlueInfo->pProcRoot = gprProcRoot; + gprGlueInfo = prGlueInfo; + + gprProcCfgEntry->prEntryCfg = proc_create(PROC_CFG_NAME, 0664, gprProcRoot, &cfg_ops); + + if (gprProcCfgEntry->prEntryCfg == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry cfg\n\r"); + return -1; + } + proc_set_user(gprProcCfgEntry->prEntryCfg, KUIDT_INIT(PROC_UID_SHELL), KGIDT_INIT(PROC_GID_WIFI)); + + return 0; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_rst.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_rst.c new file mode 100644 index 0000000000000..f3abc41ef6451 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_rst.c @@ -0,0 +1,282 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include + +#include "precomp.h" +#include "gl_rst.h" + +#if CFG_CHIP_RESET_SUPPORT + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +static BOOLEAN fgResetTriggered = FALSE; +BOOLEAN fgIsResetting = FALSE; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static RESET_STRUCT_T wifi_rst; + +static void mtk_wifi_reset(struct work_struct *work); +static void mtk_wifi_trigger_reset(struct work_struct *work); + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static void *glResetCallback(ENUM_WMTDRV_TYPE_T eSrcType, + ENUM_WMTDRV_TYPE_T eDstType, + ENUM_WMTMSG_TYPE_T eMsgType, void *prMsgBody, unsigned int u4MsgLength); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*0= f/w assert flag is not set, others=f/w assert flag is set */ +BOOLEAN glIsWmtCodeDump(VOID) +{ + if (mtk_wcn_stp_coredump_start_get() == 0) + return FALSE; + else + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for + * 1. register wifi reset callback + * 2. initialize wifi reset work + * + * @param none + * + * @retval none + */ +/*----------------------------------------------------------------------------*/ +VOID glResetInit(VOID) +{ +#if (MTK_WCN_SINGLE_MODULE == 0) + /* 1. Register reset callback */ + mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_WIFI, (PF_WMT_CB) glResetCallback); +#endif /* MTK_WCN_SINGLE_MODULE */ + + /* 2. Initialize reset work */ + INIT_WORK(&(wifi_rst.rst_work), mtk_wifi_reset); + INIT_WORK(&(wifi_rst.rst_trigger_work), mtk_wifi_trigger_reset); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for + * 1. deregister wifi reset callback + * + * @param none + * + * @retval none + */ +/*----------------------------------------------------------------------------*/ +VOID glResetUninit(VOID) +{ +#if (MTK_WCN_SINGLE_MODULE == 0) + /* 1. Deregister reset callback */ + mtk_wcn_wmt_msgcb_unreg(WMTDRV_TYPE_WIFI); +#endif /* MTK_WCN_SINGLE_MODULE */ + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is invoked when there is reset messages indicated + * + * @param eSrcType + * eDstType + * eMsgType + * prMsgBody + * u4MsgLength + * + * @retval + */ +/*----------------------------------------------------------------------------*/ +static void *glResetCallback(ENUM_WMTDRV_TYPE_T eSrcType, + ENUM_WMTDRV_TYPE_T eDstType, + ENUM_WMTMSG_TYPE_T eMsgType, void *prMsgBody, unsigned int u4MsgLength) +{ + switch (eMsgType) { + case WMTMSG_TYPE_RESET: + if (u4MsgLength == sizeof(ENUM_WMTRSTMSG_TYPE_T)) { + P_ENUM_WMTRSTMSG_TYPE_T prRstMsg = (P_ENUM_WMTRSTMSG_TYPE_T) prMsgBody; + + switch (*prRstMsg) { + case WMTRSTMSG_RESET_START: + DBGLOG(INIT, WARN, "Whole chip reset start!\n"); + fgResetTriggered = FALSE; + fgIsResetting = TRUE; + wifi_reset_start(); + break; + + case WMTRSTMSG_RESET_END: + DBGLOG(INIT, WARN, "Whole chip reset end!\n"); + fgIsResetting = FALSE; + wifi_rst.rst_data = RESET_SUCCESS; + schedule_work(&(wifi_rst.rst_work)); + break; + + case WMTRSTMSG_RESET_END_FAIL: + DBGLOG(INIT, WARN, "Whole chip reset fail!\n"); + fgIsResetting = FALSE; + wifi_rst.rst_data = RESET_FAIL; + schedule_work(&(wifi_rst.rst_work)); + break; + + default: + break; + } + } + break; + + default: + break; + } + + return NULL; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is called for wifi reset + * + * @param skb + * info + * + * @retval 0 + * nonzero + */ +/*----------------------------------------------------------------------------*/ +static void mtk_wifi_reset(struct work_struct *work) +{ + RESET_STRUCT_T *rst = container_of(work, RESET_STRUCT_T, rst_work); + + wifi_reset_end(rst->rst_data); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is called for generating reset request to WMT + * + * @param None + * + * @retval None + */ +/*----------------------------------------------------------------------------*/ +VOID glSendResetRequest(VOID) +{ + /* WMT thread would trigger whole chip reset itself */ +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is called for checking if connectivity chip is resetting + * + * @param None + * + * @retval TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalIsResetting(VOID) +{ + return fgIsResetting; +} + +static void mtk_wifi_trigger_reset(struct work_struct *work) +{ + BOOLEAN fgResult = FALSE; + RESET_STRUCT_T *rst = container_of(work, RESET_STRUCT_T, rst_trigger_work); + + fgResetTriggered = TRUE; + /* Set the power off flag to FALSE in WMT to prevent chip power off after + ** wlanProbe return failure, because we need to do core dump afterward. + */ + if (rst->rst_trigger_flag & RST_FLAG_PREVENT_POWER_OFF) + mtk_wcn_set_connsys_power_off_flag(FALSE); + + fgResult = mtk_wcn_wmt_assert_timeout(WMTDRV_TYPE_WIFI, 40, 0); + DBGLOG(INIT, INFO, "reset result %d, trigger flag 0x%x\n", fgResult, rst->rst_trigger_flag); +} + +BOOLEAN glResetTrigger(P_ADAPTER_T prAdapter, UINT_32 u4RstFlag, const PUINT_8 pucFile, UINT_32 u4Line) +{ + BOOLEAN fgResult = TRUE; + + if (kalIsResetting() || fgResetTriggered) { + if (prAdapter) { + DBGLOG(INIT, ERROR, + "Skip trigger whole-chip reset in %s line %d, during resetting! Chip[%04X E%u]\n", + pucFile, u4Line, + ((P_GL_HIF_INFO_T) & (prAdapter->prGlueInfo->rHifInfo))->ChipID, + wlanGetEcoVersion(prAdapter)); + DBGLOG(INIT, ERROR, + "FW Ver DEC[%u.%lu] HEX[%x.%lx], Driver Ver[%u.%lu]\n", + (prAdapter->rVerInfo.u2FwOwnVersion >> 8), + (prAdapter->rVerInfo.u2FwOwnVersion & BITS(0, 7)), + (prAdapter->rVerInfo.u2FwOwnVersion >> 8), + (prAdapter->rVerInfo.u2FwOwnVersion & BITS(0, 7)), + (prAdapter->rVerInfo.u2FwPeerVersion >> 8), + (prAdapter->rVerInfo.u2FwPeerVersion & BITS(0, 7))); + } else { + DBGLOG(INIT, ERROR, "Skip trigger whole-chip reset in %s line %d\n", + pucFile, u4Line); + } + + fgResult = TRUE; + } else { + if (prAdapter) { + DBGLOG(INIT, ERROR, + "Trigger chip reset in %s line %d, Chip[%04X E%u] ", + pucFile, u4Line, + ((P_GL_HIF_INFO_T) & (prAdapter->prGlueInfo->rHifInfo))->ChipID, + wlanGetEcoVersion(prAdapter)); + DBGLOG(INIT, ERROR, "FW Ver DEC[%u.%lu] HEX[%x.%lx], Driver Ver[%u.%lu]\n", + (prAdapter->rVerInfo.u2FwOwnVersion >> 8), + (prAdapter->rVerInfo.u2FwOwnVersion & BITS(0, 7)), + (prAdapter->rVerInfo.u2FwOwnVersion >> 8), + (prAdapter->rVerInfo.u2FwOwnVersion & BITS(0, 7)), + (prAdapter->rVerInfo.u2FwPeerVersion >> 8), + (prAdapter->rVerInfo.u2FwPeerVersion & BITS(0, 7))); + } else { + DBGLOG(INIT, ERROR, "Trigger chip reset in %s line %d\n", + pucFile, u4Line); + } + + wifi_rst.rst_trigger_flag = u4RstFlag; + schedule_work(&(wifi_rst.rst_trigger_work)); + } + + return fgResult; +} + +#endif /* CFG_CHIP_RESET_SUPPORT */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_sys.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_sys.c new file mode 100644 index 0000000000000..d5ea21b14c47f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_sys.c @@ -0,0 +1,606 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +/* + ** Id: /os/linux/gl_sys.c + */ + +/*! \file "gl_sys.c" + * \brief This file defines the interface which can interact with users + * in /sys fs. + * + * Detail description. + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" +#include "gl_os.h" +#include "gl_kal.h" +#include "debug.h" +#include "wlan_lib.h" +#include "debug.h" +#include "wlan_oid.h" +#include +#include +#include +#include +#include +#include + +#if WLAN_INCLUDE_SYS + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define MTK_INFO_MAX_SIZE 128 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +static P_GLUE_INFO_T g_prGlueInfo; +static struct kobject *wifi_kobj; +static uint8_t aucMacAddrOverride[] = "FF:FF:FF:FF:FF:FF"; +static uint8_t aucDefaultFWVersion[] = "Unknown"; +static u_int8_t fgIsMacAddrOverride = FALSE; +static int32_t g_i4PM = -1; +static char acVerInfo[MTK_INFO_MAX_SIZE]; +static char acSoftAPInfo[MTK_INFO_MAX_SIZE]; + +#if BUILD_QA_DBG +static uint32_t g_u4Memdump = 3; +#else +static uint32_t g_u4Memdump = 2; +#endif + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +static ssize_t pm_show( + struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + return snprintf(buf, + sizeof(g_i4PM), + "%d", g_i4PM); +} + +static void pm_EnterCtiaMode(void) +{ + if (!g_prGlueInfo) + DBGLOG(INIT, ERROR, "g_prGlueInfo is null\n"); + else if (g_i4PM == -1) + DBGLOG(INIT, TRACE, "keep default\n"); + else { + g_prGlueInfo->prAdapter->fgEnDbgPowerMode = !g_i4PM; + nicEnterCtiaMode(g_prGlueInfo->prAdapter, + !g_i4PM, + FALSE); + } +} + +static ssize_t pm_store( + struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, + size_t count) +{ + int32_t i4Ret = 0; + + i4Ret = kstrtoint(buf, 10, &g_i4PM); + + if (i4Ret) + DBGLOG(INIT, ERROR, "sscanf pm fail u4Ret=%d\n", i4Ret); + else { + DBGLOG(INIT, INFO, + "Set PM to %d.\n", + g_i4PM); + + pm_EnterCtiaMode(); + } + + return (i4Ret == 0) ? count : 0; +} + +static ssize_t macaddr_show( + struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + return snprintf(buf, + sizeof(aucMacAddrOverride), + "%s", aucMacAddrOverride); +} + +static ssize_t macaddr_store( + struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, + size_t count) +{ + int32_t i4Ret = 0; + + i4Ret = sscanf(buf, "%18s", (uint8_t *)&aucMacAddrOverride); + + if (!i4Ret) + DBGLOG(INIT, ERROR, "sscanf mac format fail u4Ret=%d\n", i4Ret); + else { + DBGLOG(INIT, INFO, + "Set macaddr to %s.\n", + aucMacAddrOverride); + } + + fgIsMacAddrOverride = TRUE; + + return (i4Ret > 0) ? count : 0; +} + +static ssize_t wifiver_show( + struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + return snprintf(buf, + sizeof(acVerInfo), "%s", + acVerInfo); +} + +static ssize_t softap_show( + struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + return snprintf(buf, sizeof(acSoftAPInfo), "%s", acSoftAPInfo); +} + +static ssize_t memdump_show( + struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + return snprintf(buf, + sizeof(g_u4Memdump), + "%d", g_u4Memdump); +} + +static ssize_t memdump_store( + struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, + size_t count) +{ + int32_t i4Ret = 0; + + i4Ret = kstrtouint(buf, 10, &g_u4Memdump); + + if (i4Ret) + DBGLOG(INIT, ERROR, "sscanf memdump fail u4Ret=%d\n", i4Ret); + else { + DBGLOG(INIT, INFO, + "Set memdump to %d.\n", + g_u4Memdump); + } + + return (i4Ret == 0) ? count : 0; +} + + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +static struct kobj_attribute macaddr_attr + = __ATTR(mac_addr, 0664, macaddr_show, macaddr_store); + +static struct kobj_attribute wifiver_attr + = __ATTR(wifiver, 0664, wifiver_show, NULL); + +static struct kobj_attribute softap_attr + = __ATTR(softap, 0664, softap_show, NULL); + +static struct kobj_attribute pm_attr + = __ATTR(pm, 0664, pm_show, pm_store); + +static struct kobj_attribute memdump_attr + = __ATTR(memdump, 0664, memdump_show, memdump_store); + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +void sysCreateMacAddr(void) +{ + if (g_prGlueInfo) { + uint8_t rMacAddr[MAC_ADDR_LEN]; + + COPY_MAC_ADDR(rMacAddr, + g_prGlueInfo->prAdapter->rWifiVar.aucMacAddress); + + kalSnprintf(aucMacAddrOverride, + sizeof(aucMacAddrOverride), + "%pM", + MAC2STR(rMacAddr)); + + DBGLOG(INIT, TRACE, + "Init macaddr to " MACSTR ".\n", + MAC2STR(rMacAddr)); + } +} + +void sysInitMacAddr(void) +{ + int32_t i4Ret = 0; + + if (!wifi_kobj) { + DBGLOG(INIT, ERROR, "wifi_kobj is null\n"); + return; + } + + i4Ret = sysfs_create_file(wifi_kobj, &macaddr_attr.attr); + if (i4Ret) + DBGLOG(INIT, ERROR, "Unable to create macaddr entry\n"); +} + +void sysUninitMacAddr(void) +{ + if (!wifi_kobj) { + DBGLOG(INIT, ERROR, "wifi_kobj is null\n"); + return; + } + + sysfs_remove_file(wifi_kobj, &macaddr_attr.attr); +} + +void sysInitPM(void) +{ + int32_t i4Ret = 0; + + if (!wifi_kobj) { + DBGLOG(INIT, ERROR, "wifi_kobj is null\n"); + return; + } + + i4Ret = sysfs_create_file(wifi_kobj, &pm_attr.attr); + if (i4Ret) + DBGLOG(INIT, ERROR, "Unable to create macaddr entry\n"); +} + +void sysUninitPM(void) +{ + if (!wifi_kobj) { + DBGLOG(INIT, ERROR, "wifi_kobj is null\n"); + return; + } + + sysfs_remove_file(wifi_kobj, &pm_attr.attr); +} + +void sysCreateWifiVer(void) +{ +#define STR_HELPER(x) #x +#define STR(x) STR_HELPER(x) + + char aucDriverVersionStr[] = STR(NIC_DRIVER_MAJOR_VERSION) "_" + STR(NIC_DRIVER_MINOR_VERSION) "_" + STR(NIC_DRIVER_SERIAL_VERSION) "-" + DRIVER_BUILD_DATE; + uint16_t u2NvramVer = 0; + uint8_t ucOffset = 0; + + kalMemZero(acVerInfo, sizeof(acVerInfo)); + + ucOffset += kalSnprintf(acVerInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "%s\n", "Mediatek"); + + ucOffset += kalSnprintf(acVerInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "DRIVER_VER: %s\n", aucDriverVersionStr); + + if (g_prGlueInfo) + ucOffset += kalSnprintf(acVerInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "FW_VER: 0x%x.%x\n" + , g_prGlueInfo->prAdapter->rVerInfo.u2FwOwnVersion + , g_prGlueInfo->prAdapter->rVerInfo.u2FwOwnVersionExtend); + else { + ucOffset += kalSnprintf(acVerInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "FW_VER: %s\n" + , aucDefaultFWVersion); + } + + if (g_prGlueInfo) { + kalCfgDataRead16(g_prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, + u2Part1OwnVersion), &u2NvramVer); + ucOffset += kalSnprintf(acVerInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "NVRAM: 0x%x\n", u2NvramVer); + } else { + ucOffset += kalSnprintf(acVerInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "NVRAM: %s\n", "Unknown"); + } +} + +void sysInitWifiVer(void) +{ + int32_t i4Ret = 0; + + if (!wifi_kobj) { + DBGLOG(INIT, ERROR, "wifi_kobj is null\n"); + return; + } + + i4Ret = sysfs_create_file(wifi_kobj, &wifiver_attr.attr); + if (i4Ret) + DBGLOG(INIT, ERROR, "Unable to create wifiver entry\n"); + + sysCreateWifiVer(); +} + +void sysUninitWifiVer(void) +{ + if (!wifi_kobj) { + DBGLOG(INIT, ERROR, "wifi_kobj is null\n"); + return; + } + + sysfs_remove_file(wifi_kobj, &wifiver_attr.attr); +} + +void sysCreateSoftap(void) +{ + REG_INFO_T *prRegInfo = NULL; + + uint8_t ucOffset = 0; + u_int8_t fgDbDcModeEn = FALSE; + + /* Log SoftAP/hotspot information into .softap.info + * #Support wifi and hotspot at the same time? + * DualBandConcurrency=no + * # Supporting 5Ghz + * 5G=check NVRAM ucEnable5GBand + * # Max support client count + * maxClient=P2P_MAXIMUM_CLIENT_COUNT + * #Supporting android_net_wifi_set_Country_Code_Hal + * HalFn_setCountryCodeHal=yes , + * call mtk_cfg80211_vendor_set_country_code + * #Supporting android_net_wifi_getValidChannels + * HalFn_getValidChannels=yes, + * call mtk_cfg80211_vendor_get_channel_list + */ + + if (g_prGlueInfo) { + prRegInfo = &g_prGlueInfo->rRegInfo; +#if CFG_SUPPORT_DBDC + fgDbDcModeEn = g_prGlueInfo->prAdapter->rWifiVar.fgDbDcModeEn; +#endif + } + + kalMemZero(acSoftAPInfo, sizeof(acSoftAPInfo)); + + ucOffset = 0; + + if (g_prGlueInfo) { + ucOffset += kalSnprintf(acSoftAPInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "DualBandConcurrency=%s\n" + , fgDbDcModeEn ? "yes" : "no"); + } else + ucOffset += kalSnprintf(acSoftAPInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "DualBandConcurrency=%s\n", "no"); + + if (prRegInfo) + ucOffset += kalSnprintf(acSoftAPInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "5G=%s\n", prRegInfo->ucEnable5GBand ? "yes" : "no"); + else + ucOffset += kalSnprintf(acSoftAPInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "5G=%s\n", "yes"); + + ucOffset += kalSnprintf(acSoftAPInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "maxClient=%d\n", P2P_MAXIMUM_CLIENT_COUNT); + + ucOffset += kalSnprintf(acSoftAPInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "HalFn_setCountryCodeHal=%s\n", "yes"); + + ucOffset += kalSnprintf(acSoftAPInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "HalFn_getValidChannels=%s\n", "yes"); + + ucOffset += kalSnprintf(acSoftAPInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "DualInterface=%s\n", "yes"); +} + +void sysInitSoftap(void) +{ + int32_t i4Ret = 0; + + if (!wifi_kobj) { + DBGLOG(INIT, ERROR, "wifi_kobj is null\n"); + return; + } + + i4Ret = sysfs_create_file(wifi_kobj, &softap_attr.attr); + if (i4Ret) + DBGLOG(INIT, ERROR, "Unable to create softap entry\n"); + + sysCreateSoftap(); +} + +void sysUninitSoftap(void) +{ + if (!wifi_kobj) { + DBGLOG(INIT, ERROR, "wifi_kobj is null\n"); + return; + } + + sysfs_remove_file(wifi_kobj, &softap_attr.attr); +} + +void sysInitMemdump(void) +{ + int32_t i4Ret = 0; + + if (!wifi_kobj) { + DBGLOG(INIT, ERROR, "wifi_kobj is null\n"); + return; + } + + i4Ret = sysfs_create_file(wifi_kobj, &memdump_attr.attr); + if (i4Ret) + DBGLOG(INIT, ERROR, "Unable to create softap entry\n"); +} + +void sysUninitMemdump(void) +{ + if (!wifi_kobj) { + DBGLOG(INIT, ERROR, "wifi_kobj is null\n"); + return; + } + + sysfs_remove_file(wifi_kobj, &memdump_attr.attr); +} + +int32_t sysCreateFsEntry(P_GLUE_INFO_T prGlueInfo) +{ + DBGLOG(INIT, TRACE, "[%s]\n", __func__); + + g_prGlueInfo = prGlueInfo; + + sysCreateMacAddr(); + pm_EnterCtiaMode(); + sysCreateWifiVer(); + sysCreateSoftap(); + + return 0; +} + +int32_t sysRemoveSysfs(void) +{ + g_prGlueInfo = NULL; + + return 0; +} + +int32_t sysInitFs(void) +{ + DBGLOG(INIT, TRACE, "[%s]\n", __func__); + + wifi_kobj = kobject_create_and_add("wifi", NULL); + kobject_get(wifi_kobj); + kobject_uevent(wifi_kobj, KOBJ_ADD); + + sysInitMacAddr(); + sysInitWifiVer(); + sysInitSoftap(); + sysInitPM(); + sysInitMemdump(); + + return 0; +} + +int32_t sysUninitSysFs(void) +{ + DBGLOG(INIT, TRACE, "[%s]\n", __func__); + + sysUninitMemdump(); + sysUninitPM(); + sysUninitSoftap(); + sysUninitWifiVer(); + sysUninitMacAddr(); + + kobject_put(wifi_kobj); + kobject_uevent(wifi_kobj, KOBJ_REMOVE); + wifi_kobj = NULL; + + return 0; +} + +int32_t sysHexToNum(int8_t c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; +} + +int32_t sysHwAddrToBin(int8_t *txt, uint8_t *addr) +{ + int32_t i; + int8_t *pos = txt; + + for (i = 0; i < 6; i++) { + int32_t a, b; + + while (*pos == ':' || *pos == '.' || *pos == '-') + pos++; + + a = sysHexToNum(*pos++); + if (a < 0) + return -1; + b = sysHexToNum(*pos++); + if (b < 0) + return -1; + *addr++ = (a << 4) | b; + } + + return pos - txt; +} + +int32_t sysMacAddrOverride(uint8_t *prMacAddr) +{ + DBGLOG(INIT, TRACE, + "Override=%d\n", fgIsMacAddrOverride); + + if (!fgIsMacAddrOverride) + return -1; + + sysHwAddrToBin( + aucMacAddrOverride, + prMacAddr); + + DBGLOG(INIT, TRACE, + "Init macaddr to " MACSTR ".\n", + MAC2STR(prMacAddr)); + + return 0; +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_vendor.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_vendor.c new file mode 100644 index 0000000000000..b07c24547839b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_vendor.c @@ -0,0 +1,2269 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include + +#include "gl_os.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "precomp.h" +#include "gl_cfg80211.h" +#include "gl_vendor.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* These values must sync from Wifi HAL + * /hardware/libhardware_legacy/include/hardware_legacy/wifi_hal.h + */ +/* Basic infrastructure mode */ +#define WIFI_FEATURE_INFRA (0x0001) +/* Support for 5 GHz Band */ +#define WIFI_FEATURE_INFRA_5G (0x0002) +/* Support for GAS/ANQP */ +#define WIFI_FEATURE_HOTSPOT (0x0004) +/* Wifi-Direct */ +#define WIFI_FEATURE_P2P (0x0008) +/* Soft AP */ +#define WIFI_FEATURE_SOFT_AP (0x0010) +/* Google-Scan APIs */ +#define WIFI_FEATURE_GSCAN (0x0020) +/* Neighbor Awareness Networking */ +#define WIFI_FEATURE_NAN (0x0040) +/* Device-to-device RTT */ +#define WIFI_FEATURE_D2D_RTT (0x0080) +/* Device-to-AP RTT */ +#define WIFI_FEATURE_D2AP_RTT (0x0100) +/* Batched Scan (legacy) */ +#define WIFI_FEATURE_BATCH_SCAN (0x0200) +/* Preferred network offload */ +#define WIFI_FEATURE_PNO (0x0400) +/* Support for two STAs */ +#define WIFI_FEATURE_ADDITIONAL_STA (0x0800) +/* Tunnel directed link setup */ +#define WIFI_FEATURE_TDLS (0x1000) +/* Support for TDLS off channel */ +#define WIFI_FEATURE_TDLS_OFFCHANNEL (0x2000) +/* Enhanced power reporting */ +#define WIFI_FEATURE_EPR (0x4000) +/* Support for AP STA Concurrency */ +#define WIFI_FEATURE_AP_STA (0x8000) +/* Link layer stats collection */ +#define WIFI_FEATURE_LINK_LAYER_STATS (0x10000) +/* WiFi Logger */ +#define WIFI_FEATURE_LOGGER (0x20000) +/* WiFi PNO enhanced */ +#define WIFI_FEATURE_HAL_EPNO (0x40000) +/* RSSI Monitor */ +#define WIFI_FEATURE_RSSI_MONITOR (0x80000) +/* WiFi mkeep_alive */ +#define WIFI_FEATURE_MKEEP_ALIVE (0x100000) +/* ND offload configure */ +#define WIFI_FEATURE_CONFIG_NDO (0x200000) +/* Capture Tx transmit power levels */ +#define WIFI_FEATURE_TX_TRANSMIT_POWER (0x400000) +/* Enable/Disable firmware roaming */ +#define WIFI_FEATURE_CONTROL_ROAMING (0x800000) +/* Support Probe IE white listing */ +#define WIFI_FEATURE_IE_WHITELIST (0x1000000) +/* Support MAC & Probe Sequence Number randomization */ +#define WIFI_FEATURE_SCAN_RAND (0x2000000) +/* Support Tx Power Limit setting */ +#define WIFI_FEATURE_SET_TX_POWER_LIMIT (0x4000000) +/* Support Using Body/Head Proximity for SAR */ +#define WIFI_FEATURE_USE_BODY_HEAD_SAR (0x8000000) + +/* note: WIFI_FEATURE_GSCAN be enabled just for ACTS test item: scanner */ +#define WIFI_HAL_FEATURE_SET ((WIFI_FEATURE_P2P) |\ + (WIFI_FEATURE_SOFT_AP) |\ + (WIFI_FEATURE_PNO) |\ + (WIFI_FEATURE_TDLS) |\ + (WIFI_FEATURE_RSSI_MONITOR) |\ + (WIFI_FEATURE_CONTROL_ROAMING) |\ + (WIFI_FEATURE_SET_TX_POWER_LIMIT)\ + ) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +static struct nla_policy nla_parse_wifi_policy[WIFI_ATTRIBUTE_ROAMING_STATE + 1] = { + [WIFI_ATTRIBUTE_BAND] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_NUM_CHANNELS] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_CHANNEL_LIST] = {.type = NLA_UNSPEC}, + + [WIFI_ATTRIBUTE_NUM_FEATURE_SET] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_FEATURE_SET] = {.type = NLA_UNSPEC}, + [WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI] = {.type = NLA_UNSPEC}, + [WIFI_ATTRIBUTE_NODFS_VALUE] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_COUNTRY_CODE] = {.type = NLA_STRING}, + + [WIFI_ATTRIBUTE_MAX_RSSI] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_MIN_RSSI] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_RSSI_MONITOR_START] = {.type = NLA_U32}, + + [WIFI_ATTRIBUTE_ROAMING_CAPABILITIES] = {.type = NLA_UNSPEC}, + [WIFI_ATTRIBUTE_ROAMING_BLACKLIST_NUM] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_ROAMING_BLACKLIST_BSSID] = {.type = NLA_UNSPEC}, + [WIFI_ATTRIBUTE_ROAMING_WHITELIST_NUM] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_ROAMING_WHITELIST_SSID] = {.type = NLA_UNSPEC}, + [WIFI_ATTRIBUTE_ROAMING_STATE] = {.type = NLA_U32}, +}; + +#if CFG_SUPPORT_GSCN +static struct nla_policy nla_parse_gscan_policy[GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1] = { + [GSCAN_ATTRIBUTE_NUM_BUCKETS] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BASE_PERIOD] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BUCKETS_BAND] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BUCKET_ID] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BUCKET_PERIOD] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BUCKET_CHANNELS] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_REPORT_THRESHOLD] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_REPORT_EVENTS] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BSSID] = {.type = NLA_UNSPEC}, + [GSCAN_ATTRIBUTE_RSSI_LOW] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_RSSI_HIGH] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE] = {.type = NLA_U16}, + [GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_MIN_BREACHING] = {.type = NLA_U16}, + [GSCAN_ATTRIBUTE_NUM_AP] = {.type = NLA_U16}, + [GSCAN_ATTRIBUTE_HOTLIST_FLUSH] = {.type = NLA_U8}, + [GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH] = {.type = NLA_U8}, +}; +#endif + +static struct nla_policy nla_parse_offloading_policy[MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC + 1] = { + [MKEEP_ALIVE_ATTRIBUTE_ID] = {.type = NLA_U8}, + [MKEEP_ALIVE_ATTRIBUTE_IP_PKT] = {.type = NLA_UNSPEC}, + [MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN] = {.type = NLA_U16}, + [MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR] = {.type = NLA_UNSPEC}, + [MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR] = {.type = NLA_UNSPEC}, + [MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC] = {.type = NLA_U32}, +}; + +static const struct nla_policy nla_get_acs_policy[ + WIFI_VENDOR_ATTR_ACS_MAX + 1] = { + [WIFI_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 }, + [WIFI_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG }, + [WIFI_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG }, + [WIFI_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG }, + [WIFI_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 }, + [WIFI_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_UNSPEC }, + [WIFI_VENDOR_ATTR_ACS_FREQ_LIST] = { .type = NLA_UNSPEC }, +}; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +int mtk_cfg80211_vendor_get_channel_list(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo; + struct nlattr *attr; + UINT_32 band = 0; + UINT_8 ucNumOfChannel, i, j; + RF_CHANNEL_INFO_T aucChannelList[64]; + UINT_32 num_channels; + wifi_channel channels[64]; + struct sk_buff *skb; + + ASSERT(wiphy && wdev); + if ((data == NULL) || !data_len) + return -EINVAL; + + attr = (struct nlattr *)data; + if (attr->nla_type == WIFI_ATTRIBUTE_BAND) + band = nla_get_u32(attr); + + if (wdev->iftype == NL80211_IFTYPE_AP) + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + else + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + if (!prGlueInfo) + return -EFAULT; + + switch (band) { + case 1: /* 2.4G band */ + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_2G4, TRUE, + 64, &ucNumOfChannel, aucChannelList); + break; + case 2: /* 5G band without DFS channels */ + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_5G, TRUE, + 64, &ucNumOfChannel, aucChannelList); + break; + case 4: /* 5G band DFS channels only */ + rlmDomainGetDfsChnls(prGlueInfo->prAdapter, 64, &ucNumOfChannel, aucChannelList); + break; + default: + ucNumOfChannel = 0; + break; + } + + kalMemZero(channels, sizeof(channels)); + for (i = 0, j = 0; i < ucNumOfChannel; i++) { + /* We need to report frequency list to HAL */ + channels[j] = nicChannelNum2Freq(aucChannelList[i].ucChannelNum) / 1000; + if (channels[j] == 0) + continue; + else { + DBGLOG(REQ, TRACE, "channels[%d] = %d\n", j, channels[j]); + j++; + } + } + num_channels = j; + DBGLOG(REQ, INFO, "Get channel list for band: %d, num_channels=%d\n", band, num_channels); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(channels)); + if (!skb) { + DBGLOG(REQ, ERROR, "Allocate skb failed\n"); + return -ENOMEM; + } + + if (unlikely(nla_put_u32(skb, WIFI_ATTRIBUTE_NUM_CHANNELS, num_channels) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put(skb, WIFI_ATTRIBUTE_CHANNEL_LIST, + (sizeof(wifi_channel) * num_channels), channels) < 0)) + goto nla_put_failure; + + return cfg80211_vendor_cmd_reply(skb); + +nla_put_failure: + kfree_skb(skb); + return -EFAULT; +} + +int mtk_cfg80211_vendor_set_country_code(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + struct nlattr *attr; + UINT_8 country[2] = {0, 0}; + + ASSERT(wiphy && wdev); + if ((data == NULL) || (data_len == 0)) + return -EINVAL; + + attr = (struct nlattr *)data; + if (attr->nla_type == WIFI_ATTRIBUTE_COUNTRY_CODE) { + country[0] = *((PUINT_8)nla_data(attr)); + country[1] = *((PUINT_8)nla_data(attr) + 1); + } + + DBGLOG(REQ, INFO, "Set country code: %c%c, iftype=%d\n", country[0], country[1], wdev->iftype); + + if (wdev->iftype == NL80211_IFTYPE_AP) + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + else + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + if (!prGlueInfo) + return -EFAULT; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetCountryCode, country, 2, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "Set country code error: %x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +int mtk_cfg80211_vendor_set_scan_mac_oui(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct nlattr *attr; + uint32_t i = 0; + uint8_t ucMacOui[MAC_OUI_LEN]; + + uint32_t u4BufLen = 0; + + ASSERT(wiphy); + ASSERT(wdev); + + if (data == NULL || data_len <= 0) { + DBGLOG(REQ, ERROR, "data error(len=%d)\n", data_len); + return -EINVAL; + } + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + if (!prGlueInfo) { + DBGLOG(REQ, ERROR, "Invalid glue info\n"); + return -EFAULT; + } + + attr = (struct nlattr *)data; + kalMemZero(ucMacOui, MAC_OUI_LEN); + if (nla_type(attr) != WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI) { + DBGLOG(REQ, ERROR, "Set MAC oui type error(%u)\n", + nla_type(attr)); + return -EINVAL; + } + + if (nla_len(attr) != MAC_OUI_LEN) { + DBGLOG(REQ, ERROR, "Set MAC oui length error(%u), %u needed\n", + nla_len(attr), MAC_OUI_LEN); + return -EINVAL; + } + + for (i = 0; i < MAC_OUI_LEN; i++) + ucMacOui[i] = *((uint8_t *)nla_data(attr) + i); + + DBGLOG(REQ, INFO, "Set MAC oui: %02x-%02x-%02x\n", + ucMacOui[0], ucMacOui[1], ucMacOui[2]); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetScanMacOui, + ucMacOui, MAC_OUI_LEN, + FALSE, FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "Set MAC oui error: 0x%X\n", rStatus); + return -EFAULT; + } + + return 0; +} + +int mtk_cfg80211_vendor_get_roaming_capabilities(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + uint32_t maxNumOfList[2] = { MAX_FW_ROAMING_BLACKLIST_SIZE, + MAX_FW_ROAMING_WHITELIST_SIZE }; + struct sk_buff *skb; + + ASSERT(wiphy); + + DBGLOG(REQ, INFO, + "Get roaming capabilities: max black/whitelist=%d/%d", + maxNumOfList[0], maxNumOfList[1]); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(uint32_t) * 2); + if (!skb) { + DBGLOG(REQ, ERROR, "Allocate skb failed\n"); + return -ENOMEM; + } + + if (unlikely(nla_put(skb, WIFI_ATTRIBUTE_ROAMING_CAPABILITIES, + sizeof(uint32_t), &maxNumOfList[0]) < 0)) + goto nla_put_failure; + if (unlikely(nla_put(skb, WIFI_ATTRIBUTE_ROAMING_CAPABILITIES, + sizeof(uint32_t), &maxNumOfList[1]) < 0)) + goto nla_put_failure; + + return cfg80211_vendor_cmd_reply(skb); + +nla_put_failure: + kfree_skb(skb); + return -EFAULT; +} + +int mtk_cfg80211_vendor_config_roaming(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4ResultLen = 0; + WLAN_STATUS rStatus; + + DBGLOG(REQ, INFO, "Receives roaming blacklist & whitelist with data_len=%d\n", data_len); + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || (data_len == 0)) + return -EINVAL; + + if (wdev->iftype == NL80211_IFTYPE_AP) + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + else + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + if (!prGlueInfo) + return -EINVAL; + + if (prGlueInfo->u4FWRoamingEnable == 0) { + DBGLOG(REQ, INFO, "FWRoaming is disabled (FWRoamingEnable=%d)\n", prGlueInfo->u4FWRoamingEnable); + return WLAN_STATUS_SUCCESS; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidConfigRoaming, (PVOID)data, data_len, + FALSE, FALSE, FALSE, FALSE, &u4ResultLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "%s config roaming error:%x\n", __func__, rStatus); + return -EINVAL; + } + + return WLAN_STATUS_SUCCESS; +} + +int mtk_cfg80211_vendor_enable_roaming(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + struct nlattr *attr; + + ASSERT(wiphy); /* change to if (wiphy == NULL) then return? */ + ASSERT(wdev); /* change to if (wiphy == NULL) then return? */ + + if (wdev->iftype == NL80211_IFTYPE_AP) + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + else + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + if (!prGlueInfo) + return -EFAULT; + + attr = (struct nlattr *)data; + if (attr->nla_type == WIFI_ATTRIBUTE_ROAMING_STATE) + prGlueInfo->u4FWRoamingEnable = nla_get_u32(attr); + + DBGLOG(REQ, INFO, "FWK set FWRoamingEnable = %d\n", prGlueInfo->u4FWRoamingEnable); + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_SUPPORT_GSCN +int mtk_cfg80211_vendor_get_gscan_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Status = -EINVAL; + PARAM_WIFI_GSCAN_CAPABILITIES_STRUCT_T rGscanCapabilities; + struct sk_buff *skb; + + DBGLOG(REQ, TRACE, "vendor command: data_len=%d\r\n", data_len); + + ASSERT(wiphy); + ASSERT(wdev); + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(rGscanCapabilities)); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed:%x\n", __func__, i4Status); + return -ENOMEM; + } + + kalMemZero(&rGscanCapabilities, sizeof(rGscanCapabilities)); + + /* GSCN capabilities return from driver not firmware */ + rGscanCapabilities.max_scan_cache_size = PSCAN_MAX_SCAN_CACHE_SIZE; + rGscanCapabilities.max_scan_buckets = GSCAN_MAX_BUCKETS; + rGscanCapabilities.max_ap_cache_per_scan = PSCAN_MAX_AP_CACHE_PER_SCAN; + rGscanCapabilities.max_rssi_sample_size = 10; + rGscanCapabilities.max_scan_reporting_threshold = GSCAN_MAX_REPORT_THRESHOLD; + rGscanCapabilities.max_hotlist_bssids = MAX_HOTLIST_BSSIDS; + rGscanCapabilities.max_hotlist_ssids = MAX_HOTLIST_SSIDS; + rGscanCapabilities.max_significant_wifi_change_aps = MAX_SIGNIFICANT_CHANGE_APS; + rGscanCapabilities.max_bssid_history_entries = PSCAN_MAX_AP_CACHE_PER_SCAN * PSCAN_MAX_SCAN_CACHE_SIZE; + rGscanCapabilities.max_number_epno_networks = 0; + rGscanCapabilities.max_number_epno_networks_by_ssid = 0; + rGscanCapabilities.max_number_of_white_listed_ssid = 0; + + /* NLA_PUT_U32(skb, NL80211_ATTR_VENDOR_ID, GOOGLE_OUI); */ + /* NLA_PUT_U32(skb, NL80211_ATTR_VENDOR_SUBCMD, GSCAN_SUBCMD_GET_CAPABILITIES); */ + /* NLA_PUT(skb, GSCAN_ATTRIBUTE_CAPABILITIES, sizeof(rGscanCapabilities), &rGscanCapabilities); */ + if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_CAPABILITIES, + sizeof(rGscanCapabilities), &rGscanCapabilities) < 0)) + goto nla_put_failure; + + i4Status = cfg80211_vendor_cmd_reply(skb); + return i4Status; + +nla_put_failure: + kfree_skb(skb); + return i4Status; +} + +int mtk_cfg80211_vendor_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + /* CMD_GSCN_REQ_T rCmdGscnParam; */ + + /* INT_32 i4Status = -EINVAL; */ + P_PARAM_WIFI_GSCAN_CMD_PARAMS prWifiScanCmd = NULL; + struct nlattr *attr[GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD + 1]; + struct nlattr *pbucket, *pchannel; + UINT_32 len_basic, len_bucket, len_channel; + int i, j, k; + uint_32 u4ArySize; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + + prWifiScanCmd = (P_PARAM_WIFI_GSCAN_CMD_PARAMS) kalMemAlloc(sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS), VIR_MEM_TYPE); + if (!prWifiScanCmd) { + DBGLOG(REQ, ERROR, "Can not alloc memory for PARAM_WIFI_GSCAN_CMD_PARAMS\n"); + return -ENOMEM; + } + + DBGLOG(REQ, TRACE, "vendor command: data_len=%d\r\n", data_len); + kalMemZero(prWifiScanCmd, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); + kalMemZero(attr, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD + 1)); + + NLA_PARSE_NESTED(attr, GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD, (struct nlattr *)(data - NLA_HDRLEN), + nla_parse_gscan_policy); + len_basic = 0; + for (k = GSCAN_ATTRIBUTE_NUM_BUCKETS; k <= GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD; k++) { + if (attr[k]) { + switch (k) { + case GSCAN_ATTRIBUTE_BASE_PERIOD: + prWifiScanCmd->base_period = nla_get_u32(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_NUM_BUCKETS: + u4ArySize = nla_get_u32(attr[k]); + prWifiScanCmd->num_buckets = + (u4ArySize <= GSCAN_MAX_BUCKETS) + ? u4ArySize : GSCAN_MAX_BUCKETS; + len_basic += NLA_ALIGN(attr[k]->nla_len); + DBGLOG(REQ, TRACE, "attr=0x%x, num_buckets=%d nla_len=%d,\r\n", + *(UINT_32 *) attr[k], prWifiScanCmd->num_buckets, attr[k]->nla_len); + break; + } + } + } + pbucket = (struct nlattr *)((UINT_8 *) data + len_basic); + DBGLOG(REQ, TRACE, "+++basic attribute size=%d pbucket=%p\r\n", len_basic, pbucket); + + for (i = 0; i < prWifiScanCmd->num_buckets; i++) { + if (NLA_PARSE_NESTED(attr, GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD, (struct nlattr *)pbucket, + nla_parse_gscan_policy) < 0) + goto nla_put_failure; + len_bucket = 0; + for (k = GSCAN_ATTRIBUTE_NUM_BUCKETS; k <= GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD; k++) { + if (attr[k] == NULL) + continue; + switch (k) { + case GSCAN_ATTRIBUTE_BUCKETS_BAND: + prWifiScanCmd->buckets[i].band = nla_get_u32(attr[k]); + len_bucket += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_BUCKET_ID: + prWifiScanCmd->buckets[i].bucket = nla_get_u32(attr[k]); + len_bucket += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_BUCKET_PERIOD: + prWifiScanCmd->buckets[i].period = nla_get_u32(attr[k]); + len_bucket += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT: + prWifiScanCmd->buckets[i].step_count = nla_get_u32(attr[k]); + len_bucket += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD: + prWifiScanCmd->buckets[i].max_period = nla_get_u32(attr[k]); + len_bucket += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_REPORT_EVENTS: + prWifiScanCmd->buckets[i].report_events = nla_get_u32(attr[k]); + /* parameter validity check */ + if (((prWifiScanCmd->buckets[i].report_events & REPORT_EVENTS_EACH_SCAN) + != REPORT_EVENTS_EACH_SCAN) + && ((prWifiScanCmd->buckets[i].report_events & REPORT_EVENTS_FULL_RESULTS) + != REPORT_EVENTS_FULL_RESULTS) + && ((prWifiScanCmd->buckets[i].report_events & REPORT_EVENTS_NO_BATCH) + != REPORT_EVENTS_NO_BATCH)) + prWifiScanCmd->buckets[i].report_events = REPORT_EVENTS_EACH_SCAN; + len_bucket += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS: + prWifiScanCmd->buckets[i].num_channels = nla_get_u32(attr[k]); + len_bucket += NLA_ALIGN(attr[k]->nla_len); + DBGLOG(REQ, TRACE, "bucket%d: attr=0x%x, num_channels=%d nla_len=%d,\r\n", + i, *(UINT_32 *) attr[k], nla_get_u32(attr[k]), attr[k]->nla_len); + break; + } + } + pbucket = (struct nlattr *)((UINT_8 *) pbucket + NLA_HDRLEN); + /* request.attr_start(i) as nested attribute */ + DBGLOG(REQ, TRACE, "+++pure bucket size=%d pbucket=%p\r\n", len_bucket, pbucket); + pbucket = (struct nlattr *)((UINT_8 *) pbucket + len_bucket); + /* pure bucket payload, not include channels */ + + /*don't need to use nla_parse_nested to parse channels */ + /* the header of channel in bucket i */ + pchannel = (struct nlattr *)((UINT_8 *) pbucket + NLA_HDRLEN); + for (j = 0; j < prWifiScanCmd->buckets[i].num_channels; j++) { + prWifiScanCmd->buckets[i].channels[j].channel = nla_get_u32(pchannel); + len_channel = NLA_ALIGN(pchannel->nla_len); + DBGLOG(REQ, TRACE, + "attr=0x%x, channel=%d,\r\n", *(UINT_32 *) pchannel, nla_get_u32(pchannel)); + + pchannel = (struct nlattr *)((UINT_8 *) pchannel + len_channel); + } + pbucket = pchannel; + } + + DBGLOG(REQ, INFO, "base_period=%d, num_buckets=%d, bucket0: %d %d %d %d %d %d\n", + prWifiScanCmd->base_period, prWifiScanCmd->num_buckets, + prWifiScanCmd->buckets[0].bucket, prWifiScanCmd->buckets[0].band, + prWifiScanCmd->buckets[0].period, prWifiScanCmd->buckets[0].max_period, + prWifiScanCmd->buckets[0].num_channels, prWifiScanCmd->buckets[0].report_events); + + DBGLOG(REQ, TRACE, "bucket0: num_channels=%d, %d, %d; bucket1: num_channels=%d, %d, %d\n", + prWifiScanCmd->buckets[0].num_channels, + prWifiScanCmd->buckets[0].channels[0].channel, prWifiScanCmd->buckets[0].channels[1].channel, + prWifiScanCmd->buckets[1].num_channels, + prWifiScanCmd->buckets[1].channels[0].channel, prWifiScanCmd->buckets[1].channels[1].channel); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetGSCNParam, + prWifiScanCmd, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + kalMemFree(prWifiScanCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); + return 0; + +nla_put_failure: + if (prWifiScanCmd != NULL) + kalMemFree(prWifiScanCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); + return -ENOMEM; +} + +int mtk_cfg80211_vendor_set_scan_config(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + + INT_32 i4Status = -ENOMEM; + /*PARAM_WIFI_GSCAN_CMD_PARAMS rWifiScanCmd;*/ + P_PARAM_WIFI_GSCAN_CMD_PARAMS prWifiScanCmd = NULL; + struct nlattr *attr[GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE + 1]; + /* UINT_32 num_scans = 0; */ /* another attribute */ + int k; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + DBGLOG(REQ, TRACE, "vendor command: data_len=%d\r\n", data_len); + /*kalMemZero(&rWifiScanCmd, sizeof(rWifiScanCmd));*/ + prWifiScanCmd = kalMemAlloc(sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS), VIR_MEM_TYPE); + if (prWifiScanCmd == NULL) + goto nla_put_failure; + kalMemZero(prWifiScanCmd, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); + kalMemZero(attr, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE + 1)); + + if (NLA_PARSE_NESTED(attr, GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, + (struct nlattr *)(data - NLA_HDRLEN), nla_parse_gscan_policy) < 0) + goto nla_put_failure; + for (k = GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN; k <= GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE; k++) { + if (attr[k]) { + switch (k) { + case GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN: + prWifiScanCmd->max_ap_per_scan = nla_get_u32(attr[k]); + break; + case GSCAN_ATTRIBUTE_REPORT_THRESHOLD: + prWifiScanCmd->report_threshold_percent = nla_get_u32(attr[k]); + break; + case GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE: + prWifiScanCmd->report_threshold_num_scans = nla_get_u32(attr[k]); + break; + } + } + } + /* parameter validity check */ + if (prWifiScanCmd->report_threshold_percent > 100) + prWifiScanCmd->report_threshold_percent = 100; + DBGLOG(REQ, TRACE, "attr=0x%x, attr2=0x%x ", *(UINT_32 *) attr[GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN], + *(UINT_32 *) attr[GSCAN_ATTRIBUTE_REPORT_THRESHOLD]); + + DBGLOG(REQ, INFO, "max_ap_per_scan=%d, report_threshold=%d num_scans=%d\r\n", + prWifiScanCmd->max_ap_per_scan, prWifiScanCmd->report_threshold_percent, + prWifiScanCmd->report_threshold_num_scans); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetGSCNConfig, + prWifiScanCmd, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + kalMemFree(prWifiScanCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); + return 0; + +nla_put_failure: + if (prWifiScanCmd != NULL) + kalMemFree(prWifiScanCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); + return i4Status; +} + +int mtk_cfg80211_vendor_set_significant_change(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + INT_32 i4Status = -EINVAL; + P_PARAM_WIFI_SIGNIFICANT_CHANGE prWifiChangeCmd = NULL; + UINT_8 flush = 0; + /* struct nlattr *attr[GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1]; */ + struct nlattr **attr = NULL; + struct nlattr *paplist; + int i, k; + UINT_32 len_basic, len_aplist; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + DBGLOG(REQ, TRACE, "vendor command: data_len=%d\r\n", data_len); + for (i = 0; i < 6; i++) + DBGLOG(REQ, LOUD, "0x%x 0x%x 0x%x 0x%x\r\n", + *((UINT_32 *) data + i * 4), *((UINT_32 *) data + i * 4 + 1), + *((UINT_32 *) data + i * 4 + 2), *((UINT_32 *) data + i * 4 + 3)); + prWifiChangeCmd = kalMemAlloc(sizeof(PARAM_WIFI_SIGNIFICANT_CHANGE), VIR_MEM_TYPE); + if (prWifiChangeCmd == NULL) + goto nla_put_failure; + kalMemZero(prWifiChangeCmd, sizeof(PARAM_WIFI_SIGNIFICANT_CHANGE)); + attr = kalMemAlloc(sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1), VIR_MEM_TYPE); + if (attr == NULL) + goto nla_put_failure; + kalMemZero(attr, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1)); + + if (NLA_PARSE_NESTED(attr, GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, + (struct nlattr *)(data - NLA_HDRLEN), nla_parse_gscan_policy) < 0) + goto nla_put_failure; + len_basic = 0; + for (k = GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE; k <= GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH; k++) { + if (attr[k]) { + switch (k) { + case GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE: + prWifiChangeCmd->rssi_sample_size = nla_get_u16(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE: + prWifiChangeCmd->lost_ap_sample_size = nla_get_u16(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_MIN_BREACHING: + prWifiChangeCmd->min_breaching = nla_get_u16(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_NUM_AP: + prWifiChangeCmd->num_ap = nla_get_u16(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + DBGLOG(REQ, TRACE, "attr=0x%x, num_ap=%d nla_len=%d,\r\n", + *(UINT_32 *) attr[k], prWifiChangeCmd->num_ap, attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH: + flush = nla_get_u8(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + } + } + } + paplist = (struct nlattr *)((UINT_8 *) data + len_basic); + DBGLOG(REQ, TRACE, "+++basic attribute size=%d flush=%d\r\n", len_basic, flush); + + if (paplist->nla_type == GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS) + paplist = (struct nlattr *)((UINT_8 *) paplist + NLA_HDRLEN); + + for (i = 0; i < prWifiChangeCmd->num_ap; i++) { + if (NLA_PARSE_NESTED(attr, GSCAN_ATTRIBUTE_RSSI_HIGH, (struct nlattr *)paplist, + nla_parse_gscan_policy) < 0) + goto nla_put_failure; + paplist = (struct nlattr *)((UINT_8 *) paplist + NLA_HDRLEN); + /* request.attr_start(i) as nested attribute */ + len_aplist = 0; + for (k = GSCAN_ATTRIBUTE_BSSID; k <= GSCAN_ATTRIBUTE_RSSI_HIGH; k++) { + if (attr[k]) { + switch (k) { + case GSCAN_ATTRIBUTE_BSSID: + kalMemCopy(prWifiChangeCmd->ap[i].bssid, nla_data(attr[k]), sizeof(mac_addr)); + len_aplist += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_RSSI_LOW: + prWifiChangeCmd->ap[i].low = nla_get_u32(attr[k]); + len_aplist += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_RSSI_HIGH: + prWifiChangeCmd->ap[i].high = nla_get_u32(attr[k]); + len_aplist += NLA_ALIGN(attr[k]->nla_len); + break; + } + } + } + if (((i + 1) % 4 == 0) || (i == prWifiChangeCmd->num_ap - 1)) + DBGLOG(REQ, TRACE, "ap[%d], len_aplist=%d\n", i, len_aplist); + else + DBGLOG(REQ, TRACE, "ap[%d], len_aplist=%d\t", i, len_aplist); + paplist = (struct nlattr *)((UINT_8 *) paplist + len_aplist); + } + + DBGLOG(REQ, TRACE, + "flush=%d, rssi_sample_size=%d lost_ap_sample_size=%d min_breaching=%d", + flush, prWifiChangeCmd->rssi_sample_size, prWifiChangeCmd->lost_ap_sample_size, + prWifiChangeCmd->min_breaching); + DBGLOG(REQ, TRACE, + "ap[0].channel=%d low=%d high=%d, ap[1].channel=%d low=%d high=%d", + prWifiChangeCmd->ap[0].channel, prWifiChangeCmd->ap[0].low, prWifiChangeCmd->ap[0].high, + prWifiChangeCmd->ap[1].channel, prWifiChangeCmd->ap[1].low, prWifiChangeCmd->ap[1].high); + kalMemFree(prWifiChangeCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_SIGNIFICANT_CHANGE)); + kalMemFree(attr, VIR_MEM_TYPE, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1)); + return 0; + +nla_put_failure: + if (prWifiChangeCmd) + kalMemFree(prWifiChangeCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_SIGNIFICANT_CHANGE)); + if (attr) + kalMemFree(attr, VIR_MEM_TYPE, + sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1)); + return i4Status; +} + +int mtk_cfg80211_vendor_set_hotlist(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + CMD_SET_PSCAN_ADD_HOTLIST_BSSID rCmdPscnAddHotlist; + + INT_32 i4Status = -EINVAL; + P_PARAM_WIFI_BSSID_HOTLIST prWifiHotlistCmd = NULL; + UINT_8 flush = 0; + /* struct nlattr *attr[GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1]; */ + struct nlattr **attr = NULL; + struct nlattr *paplist; + int i, k; + UINT_32 len_basic, len_aplist; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + DBGLOG(REQ, TRACE, "vendor command: data_len=%d\r\n", data_len); + for (i = 0; i < 5; i++) + DBGLOG(REQ, LOUD, "0x%x 0x%x 0x%x 0x%x\r\n", + *((UINT_32 *) data + i * 4), *((UINT_32 *) data + i * 4 + 1), + *((UINT_32 *) data + i * 4 + 2), *((UINT_32 *) data + i * 4 + 3)); + prWifiHotlistCmd = kalMemAlloc(sizeof(PARAM_WIFI_BSSID_HOTLIST), VIR_MEM_TYPE); + if (prWifiHotlistCmd == NULL) + goto nla_put_failure; + kalMemZero(prWifiHotlistCmd, sizeof(PARAM_WIFI_BSSID_HOTLIST)); + attr = kalMemAlloc(sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1), VIR_MEM_TYPE); + if (attr == NULL) + goto nla_put_failure; + kalMemZero(attr, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1)); + + if (NLA_PARSE_NESTED(attr, GSCAN_ATTRIBUTE_NUM_AP, (struct nlattr *)(data - NLA_HDRLEN), + nla_parse_gscan_policy) < 0) + goto nla_put_failure; + len_basic = 0; + for (k = GSCAN_ATTRIBUTE_HOTLIST_FLUSH; k <= GSCAN_ATTRIBUTE_NUM_AP; k++) { + if (attr[k]) { + switch (k) { + case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE: + prWifiHotlistCmd->lost_ap_sample_size = nla_get_u32(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_NUM_AP: + prWifiHotlistCmd->num_ap = nla_get_u16(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + DBGLOG(REQ, TRACE, "attr=0x%x, num_ap=%d nla_len=%d,\r\n", + *(UINT_32 *) attr[k], prWifiHotlistCmd->num_ap, attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_HOTLIST_FLUSH: + flush = nla_get_u8(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + } + } + } + paplist = (struct nlattr *)((UINT_8 *) data + len_basic); + DBGLOG(REQ, INFO, "+++basic attribute size=%d flush=%d\r\n", len_basic, flush); + + if (paplist->nla_type == GSCAN_ATTRIBUTE_HOTLIST_BSSIDS) + paplist = (struct nlattr *)((UINT_8 *) paplist + NLA_HDRLEN); + + for (i = 0; i < prWifiHotlistCmd->num_ap; i++) { + if (NLA_PARSE_NESTED(attr, GSCAN_ATTRIBUTE_RSSI_HIGH, (struct nlattr *)paplist, + nla_parse_gscan_policy) < 0) + goto nla_put_failure; + paplist = (struct nlattr *)((UINT_8 *) paplist + NLA_HDRLEN); + /* request.attr_start(i) as nested attribute */ + len_aplist = 0; + for (k = GSCAN_ATTRIBUTE_BSSID; k <= GSCAN_ATTRIBUTE_RSSI_HIGH; k++) { + if (attr[k]) { + switch (k) { + case GSCAN_ATTRIBUTE_BSSID: + kalMemCopy(prWifiHotlistCmd->ap[i].bssid, nla_data(attr[k]), sizeof(mac_addr)); + len_aplist += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_RSSI_LOW: + prWifiHotlistCmd->ap[i].low = nla_get_u32(attr[k]); + len_aplist += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_RSSI_HIGH: + prWifiHotlistCmd->ap[i].high = nla_get_u32(attr[k]); + len_aplist += NLA_ALIGN(attr[k]->nla_len); + break; + } + } + } + if (((i + 1) % 4 == 0) || (i == prWifiHotlistCmd->num_ap - 1)) + DBGLOG(REQ, TRACE, "ap[%d], len_aplist=%d\n", i, len_aplist); + else + DBGLOG(REQ, TRACE, "ap[%d], len_aplist=%d\t", i, len_aplist); + paplist = (struct nlattr *)((UINT_8 *) paplist + len_aplist); + } + + DBGLOG(REQ, INFO, + "flush=%d, lost_ap_sample_size=%d, Hotlist:ap[0].channel=%d low=%d high=%d, ap[1].channel=%d low=%d high=%d", + flush, prWifiHotlistCmd->lost_ap_sample_size, + prWifiHotlistCmd->ap[0].channel, prWifiHotlistCmd->ap[0].low, prWifiHotlistCmd->ap[0].high, + prWifiHotlistCmd->ap[1].channel, prWifiHotlistCmd->ap[1].low, prWifiHotlistCmd->ap[1].high); + + memcpy(&(rCmdPscnAddHotlist.aucMacAddr), &(prWifiHotlistCmd->ap[0].bssid), 6 * sizeof(UINT_8)); + rCmdPscnAddHotlist.ucFlags = (UINT_8) TRUE; + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + kalMemFree(prWifiHotlistCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_BSSID_HOTLIST)); + kalMemFree(attr, VIR_MEM_TYPE, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1)); + return 0; + +nla_put_failure: + if (prWifiHotlistCmd) + kalMemFree(prWifiHotlistCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_BSSID_HOTLIST)); + if (attr) + kalMemFree(attr, VIR_MEM_TYPE, + sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1)); + return i4Status; +} + +int mtk_cfg80211_vendor_enable_scan(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_WIFI_GSCAN_ACTION_CMD_PARAMS rWifiScanActionCmd; + + INT_32 i4Status = -EINVAL; + struct nlattr *attr; + UINT_8 gGScanEn = 0; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + DBGLOG(REQ, TRACE, "vendor command: data_len=%d, data=0x%x 0x%x\r\n", + data_len, *((UINT_32 *) data), *((UINT_32 *) data + 1)); + + attr = (struct nlattr *)data; + if (attr->nla_type == GSCAN_ATTRIBUTE_ENABLE_FEATURE) + gGScanEn = nla_get_u32(attr); + DBGLOG(REQ, INFO, "gGScanEn=%d\r\n", gGScanEn); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + if (gGScanEn == TRUE) + rWifiScanActionCmd.ucPscanAct = PSCAN_ACT_ENABLE; + else + rWifiScanActionCmd.ucPscanAct = PSCAN_ACT_DISABLE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetGSCNAction, + &rWifiScanActionCmd, + sizeof(PARAM_WIFI_GSCAN_ACTION_CMD_PARAMS), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + return 0; + +nla_put_failure: + return i4Status; +} + +int mtk_cfg80211_vendor_enable_full_scan_results(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + INT_32 i4Status = -EINVAL; + struct nlattr *attr; + UINT_8 gFullScanResultsEn = 0; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + DBGLOG(REQ, TRACE, "vendor command: data_len=%d, data=0x%x 0x%x\r\n", + data_len, *((UINT_32 *) data), *((UINT_32 *) data + 1)); + + attr = (struct nlattr *)data; + if (attr->nla_type == GSCAN_ENABLE_FULL_SCAN_RESULTS) + gFullScanResultsEn = nla_get_u32(attr); + DBGLOG(REQ, INFO, "gFullScanResultsEn=%d\r\n", gFullScanResultsEn); + + return 0; + +nla_put_failure: + return i4Status; +} + +int mtk_cfg80211_vendor_get_gscan_result(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + /*WLAN_STATUS rStatus;*/ + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_WIFI_GSCAN_GET_RESULT_PARAMS rGScanResultParm; + + INT_32 i4Status = -EINVAL; + struct nlattr *attr; + UINT_32 get_num = 0, real_num = 0; + UINT_8 flush = 0; + /* + * PARAM_WIFI_GSCAN_RESULT result[4], *pResult; + * struct sk_buff *skb; + */ + int i; /*int j;*/ + /*UINT_32 scan_id;*/ + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + DBGLOG(REQ, TRACE, "vendor command: data_len=%d\r\n", data_len); + for (i = 0; i < 2; i++) + DBGLOG(REQ, LOUD, "0x%x 0x%x 0x%x 0x%x\r\n", *((UINT_32 *) data + i * 4), + *((UINT_32 *) data + i * 4 + 1), *((UINT_32 *) data + i * 4 + 2), + *((UINT_32 *) data + i * 4 + 3)); + + attr = (struct nlattr *)data; + if (attr->nla_type == GSCAN_ATTRIBUTE_NUM_OF_RESULTS) { + get_num = nla_get_u32(attr); + attr = (struct nlattr *)((UINT_8 *) attr + attr->nla_len); + } + if (attr->nla_type == GSCAN_ATTRIBUTE_FLUSH_RESULTS) { + flush = nla_get_u8(attr); + attr = (struct nlattr *)((UINT_8 *) attr + attr->nla_len); + } + DBGLOG(REQ, TRACE, "number=%d, flush=%d\r\n", get_num, flush); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + /* parameter validity check */ + real_num = (get_num < PSCAN_MAX_AP_CACHE_PER_SCAN) ? get_num : PSCAN_MAX_AP_CACHE_PER_SCAN; + get_num = real_num; + + if (flush) + flush = TRUE; + + rGScanResultParm.get_num = get_num; + rGScanResultParm.flush = flush; + { + kalIoctl(prGlueInfo, + wlanoidGetGSCNResult, + &rGScanResultParm, + sizeof(PARAM_WIFI_GSCAN_GET_RESULT_PARAMS), TRUE, TRUE, TRUE, FALSE, &u4BufLen); + } + DBGLOG(REQ, LOUD, "u4BufLen=%d\r\n", u4BufLen); + return 0; + +nla_put_failure: + return i4Status; +} + +int mtk_cfg80211_vendor_gscan_results(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len, BOOLEAN complete, BOOLEAN compValue) +{ + P_PARAM_WIFI_GSCAN_RESULT_REPORT prGscnResult = NULL; + UINT_32 u4SizeofGScanResults; + P_PARAM_WIFI_GSCAN_RESULT prResults = NULL; /* similar to WIFI_GSCAN_RESULT_T*/ + UINT_32 scan_id = 0; + UINT_8 scan_flag = 0; + UINT_32 real_num = 0; + UINT_32 ch_bucket_mask = 0; + INT_32 i4Status = -EINVAL; + struct sk_buff *skb; + struct nlattr *attr1, *attr2; + + ASSERT(data); + prGscnResult = (P_PARAM_WIFI_GSCAN_RESULT_REPORT)data; + u4SizeofGScanResults = data_len; + + if (prGscnResult) { + scan_id = prGscnResult->u4ScanId; + scan_flag = prGscnResult->ucScanFlag; + ch_bucket_mask = prGscnResult->u4BucketMask; + real_num = prGscnResult->u4NumOfResults; + } + if (complete) + DBGLOG(SCN, INFO, "complete=%d, compValue=%d", complete, compValue); + else + DBGLOG(SCN, TRACE, "scan_id=%d 0x%x, bkt=0x%x, num=%d, u4SizeofGScanResults=%d\r\n", + scan_id, scan_flag, ch_bucket_mask, real_num, u4SizeofGScanResults); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, u4SizeofGScanResults); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed:%x\n", __func__, i4Status); + return -ENOMEM; + } + + attr1 = nla_nest_start(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS); + + if (complete == TRUE) { + /* NLA_PUT_U8(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, 1); */ + { + unsigned char __tmp = compValue; + + if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + } else { + attr2 = nla_nest_start(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS); + + /*NLA_PUT_U32(skb, GSCAN_ATTRIBUTE_SCAN_ID, scan_id);*/ + { + unsigned int __tmp = scan_id; + + if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_SCAN_ID, sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + /*NLA_PUT_U8(skb, GSCAN_ATTRIBUTE_SCAN_FLAGS, 1);*/ + { + unsigned char __tmp = scan_flag; + + if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_SCAN_FLAGS, sizeof(u8), &__tmp) < 0)) + goto nla_put_failure; + } + /*NLA_PUT_U32(skb, GSCAN_ATTRIBUTE_NUM_OF_RESULTS, real_num);*/ + { + unsigned int __tmp = real_num; + + if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_NUM_OF_RESULTS, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + { + unsigned int __tmp = ch_bucket_mask; + + if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + if (prGscnResult) + prResults = (P_PARAM_WIFI_GSCAN_RESULT) prGscnResult->rResult; + if (prResults) { + /*NLA_PUT(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS, sizeof(PARAM_WIFI_GSCAN_RESULT) * real_num, + * prResults); + */ + if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS, + sizeof(PARAM_WIFI_GSCAN_RESULT)*real_num, prResults) < 0)) + goto nla_put_failure; + } + + if (attr2) + nla_nest_end(skb, attr2); + } + + if (attr1) + nla_nest_end(skb, attr1); + + i4Status = cfg80211_vendor_cmd_reply(skb); + if (i4Status) + DBGLOG(REQ, ERROR, "i4Status=%d real_num=%d\n", i4Status, real_num); + return real_num; + +nla_put_failure: + kfree_skb(skb); + DBGLOG(REQ, ERROR, "nla_put_failure\n"); + return -ENOMEM; +} +#endif + +int mtk_cfg80211_vendor_get_rtt_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Status = -EINVAL; + PARAM_WIFI_RTT_CAPABILITIES rRttCapabilities; + struct sk_buff *skb; + + DBGLOG(REQ, TRACE, "vendor command\r\n"); + + ASSERT(wiphy); + ASSERT(wdev); + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(rRttCapabilities)); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed:%x\n", __func__, i4Status); + return -ENOMEM; + } + + kalMemZero(&rRttCapabilities, sizeof(rRttCapabilities)); + + /* RTT Capabilities return from driver not firmware */ + rRttCapabilities.rtt_one_sided_supported = 0; + rRttCapabilities.rtt_ftm_supported = 0; + rRttCapabilities.lci_support = 0; + rRttCapabilities.lcr_support = 0; + rRttCapabilities.preamble_support = 0; + rRttCapabilities.bw_support = 0; + + if (unlikely(nla_put(skb, RTT_ATTRIBUTE_CAPABILITIES, + sizeof(rRttCapabilities), &rRttCapabilities) < 0)) + goto nla_put_failure; + + i4Status = cfg80211_vendor_cmd_reply(skb); + return i4Status; + +nla_put_failure: + kfree_skb(skb); + return i4Status; +} + +int mtk_cfg80211_vendor_llstats_get_info(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + INT_32 i4Status = -EINVAL; + WIFI_RADIO_STAT *pRadioStat; + struct sk_buff *skb; + UINT_32 u4BufLen = 0; + + ASSERT(wiphy); + ASSERT(wdev); + + u4BufLen = sizeof(WIFI_RADIO_STAT) + sizeof(WIFI_IFACE_STAT); + pRadioStat = kalMemAlloc(u4BufLen, VIR_MEM_TYPE); + if (!pRadioStat) { + DBGLOG(REQ, ERROR, "%s kalMemAlloc pRadioStat failed\n", __func__); + return -ENOMEM; + } + kalMemZero(pRadioStat, u4BufLen); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, u4BufLen); + if (!skb) { + DBGLOG(REQ, TRACE, "%s allocate skb failed:%x\n", __func__, i4Status); + return -ENOMEM; + } + + /* + * rStatus = kalIoctl(prGlueInfo, + * wlanoidQueryStatistics, + * &rRadioStat, + * sizeof(rRadioStat), + * TRUE, + * TRUE, + * TRUE, + * FALSE, + * &u4BufLen); + */ + /* only for test */ + pRadioStat->radio = 10; + pRadioStat->on_time = 11; + pRadioStat->tx_time = 12; + pRadioStat->num_channels = 4; + + /*NLA_PUT(skb, LSTATS_ATTRIBUTE_STATS, u4BufLen, pRadioStat);*/ + if (unlikely(nla_put(skb, LSTATS_ATTRIBUTE_STATS, u4BufLen, pRadioStat) < 0)) + goto nla_put_failure; + + i4Status = cfg80211_vendor_cmd_reply(skb); + kalMemFree(pRadioStat, VIR_MEM_TYPE, u4BufLen); + return -1; /* not support LLS now*/ + /* return i4Status; */ + +nla_put_failure: + kfree_skb(skb); + return i4Status; +} + +int mtk_cfg80211_vendor_set_rssi_monitoring(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + + INT_32 i4Status = -EINVAL; + PARAM_RSSI_MONITOR_T rRSSIMonitor; + struct nlattr *attr[WIFI_ATTRIBUTE_RSSI_MONITOR_START + 1]; + UINT_32 i = 0; + + ASSERT(wiphy); + ASSERT(wdev); + + DBGLOG(REQ, TRACE, "vendor command: data_len=%d\r\n", data_len); + kalMemZero(&rRSSIMonitor, sizeof(PARAM_RSSI_MONITOR_T)); + if ((data == NULL) || !data_len) + goto nla_put_failure; + kalMemZero(attr, sizeof(struct nlattr *) * (WIFI_ATTRIBUTE_RSSI_MONITOR_START + 1)); + + if (NLA_PARSE_NESTED(attr, WIFI_ATTRIBUTE_RSSI_MONITOR_START, + (struct nlattr *)(data - NLA_HDRLEN), nla_parse_wifi_policy) < 0) { + DBGLOG(REQ, ERROR, "%s nla_parse_nested failed\n", __func__); + goto nla_put_failure; + } + + for (i = WIFI_ATTRIBUTE_MAX_RSSI; i <= WIFI_ATTRIBUTE_RSSI_MONITOR_START; i++) { + if (attr[i]) { + switch (i) { + case WIFI_ATTRIBUTE_MAX_RSSI: + rRSSIMonitor.max_rssi_value = nla_get_u32(attr[i]); + break; + case WIFI_ATTRIBUTE_MIN_RSSI: + rRSSIMonitor.min_rssi_value = nla_get_u32(attr[i]); + break; + case WIFI_ATTRIBUTE_RSSI_MONITOR_START: + rRSSIMonitor.enable = nla_get_u32(attr[i]); + break; + } + } + } + + DBGLOG(REQ, INFO, "mMax_rssi=%d, mMin_rssi=%d enable=%d\r\n", + rRSSIMonitor.max_rssi_value, rRSSIMonitor.min_rssi_value, rRSSIMonitor.enable); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidRssiMonitor, + &rRSSIMonitor, sizeof(PARAM_RSSI_MONITOR_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + return rStatus; + +nla_put_failure: + return i4Status; +} + +int mtk_cfg80211_vendor_packet_keep_alive_start(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_16 u2IpPktLen = 0; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + + INT_32 i4Status = -EINVAL; + P_PARAM_PACKET_KEEPALIVE_T prPkt = NULL; + struct nlattr *attr[MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC + 1]; + UINT_32 i = 0; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + + DBGLOG(REQ, TRACE, "vendor command: data_len=%d\r\n", data_len); + prPkt = (P_PARAM_PACKET_KEEPALIVE_T) kalMemAlloc(sizeof(PARAM_PACKET_KEEPALIVE_T), VIR_MEM_TYPE); + if (!prPkt) { + DBGLOG(REQ, ERROR, "Can not alloc memory for PARAM_PACKET_KEEPALIVE_T\n"); + return -ENOMEM; + } + kalMemZero(prPkt, sizeof(PARAM_PACKET_KEEPALIVE_T)); + kalMemZero(attr, sizeof(struct nlattr *) * (MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC + 1)); + + prPkt->enable = TRUE; /*start packet keep alive*/ + if (NLA_PARSE_NESTED(attr, MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC, + (struct nlattr *)(data - NLA_HDRLEN), nla_parse_offloading_policy) < 0) { + DBGLOG(REQ, ERROR, "%s nla_parse_nested failed\n", __func__); + goto nla_put_failure; + } + + for (i = MKEEP_ALIVE_ATTRIBUTE_ID; i <= MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC; i++) { + if (attr[i]) { + switch (i) { + case MKEEP_ALIVE_ATTRIBUTE_ID: + prPkt->index = nla_get_u8(attr[i]); + break; + case MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN: + prPkt->u2IpPktLen = nla_get_u16(attr[i]); + break; + case MKEEP_ALIVE_ATTRIBUTE_IP_PKT: + u2IpPktLen = prPkt->u2IpPktLen <= 256 ? prPkt->u2IpPktLen : 256; + kalMemCopy(prPkt->pIpPkt, nla_data(attr[i]), u2IpPktLen); + break; + case MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR: + kalMemCopy(prPkt->ucSrcMacAddr, nla_data(attr[i]), sizeof(mac_addr)); + break; + case MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR: + kalMemCopy(prPkt->ucDstMacAddr, nla_data(attr[i]), sizeof(mac_addr)); + break; + case MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC: + prPkt->u4PeriodMsec = nla_get_u32(attr[i]); + break; + } + } + } + + DBGLOG(REQ, INFO, "enable=%d, index=%d, u2IpPktLen=%d u4PeriodMsec=%d\n", + prPkt->enable, prPkt->index, prPkt->u2IpPktLen, prPkt->u4PeriodMsec); + DBGLOG(REQ, TRACE, "prPkt->pIpPkt=0x%02x%02x%02x%02x, %02x%02x%02x%02x, %02x%02x%02x%02x, %02x%02x%02x%02x", + prPkt->pIpPkt[0], prPkt->pIpPkt[1], prPkt->pIpPkt[2], prPkt->pIpPkt[3], + prPkt->pIpPkt[4], prPkt->pIpPkt[5], prPkt->pIpPkt[6], prPkt->pIpPkt[7], + prPkt->pIpPkt[8], prPkt->pIpPkt[9], prPkt->pIpPkt[10], prPkt->pIpPkt[11], + prPkt->pIpPkt[12], prPkt->pIpPkt[13], prPkt->pIpPkt[14], prPkt->pIpPkt[15]); + DBGLOG(REQ, TRACE, "prPkt->srcMAC=%02x:%02x:%02x:%02x:%02x:%02x, dstMAC=%02x:%02x:%02x:%02x:%02x:%02x\n", + prPkt->ucSrcMacAddr[0], prPkt->ucSrcMacAddr[1], prPkt->ucSrcMacAddr[2], prPkt->ucSrcMacAddr[3], + prPkt->ucSrcMacAddr[4], prPkt->ucSrcMacAddr[5], + prPkt->ucDstMacAddr[0], prPkt->ucDstMacAddr[1], prPkt->ucDstMacAddr[2], prPkt->ucDstMacAddr[3], + prPkt->ucDstMacAddr[4], prPkt->ucDstMacAddr[5]); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidPacketKeepAlive, + prPkt, sizeof(PARAM_PACKET_KEEPALIVE_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + kalMemFree(prPkt, VIR_MEM_TYPE, sizeof(PARAM_PACKET_KEEPALIVE_T)); + return rStatus; + +nla_put_failure: + if (prPkt != NULL) + kalMemFree(prPkt, VIR_MEM_TYPE, sizeof(PARAM_PACKET_KEEPALIVE_T)); + return i4Status; +} + +int mtk_cfg80211_vendor_packet_keep_alive_stop(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + + INT_32 i4Status = -EINVAL; + P_PARAM_PACKET_KEEPALIVE_T prPkt = NULL; + struct nlattr *attr; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + + DBGLOG(REQ, TRACE, "vendor command: data_len=%d\r\n", data_len); + prPkt = (P_PARAM_PACKET_KEEPALIVE_T) kalMemAlloc(sizeof(PARAM_PACKET_KEEPALIVE_T), VIR_MEM_TYPE); + if (!prPkt) { + DBGLOG(REQ, ERROR, "Can not alloc memory for PARAM_PACKET_KEEPALIVE_T\n"); + return -ENOMEM; + } + kalMemZero(prPkt, sizeof(PARAM_PACKET_KEEPALIVE_T)); + + prPkt->enable = FALSE; /*stop packet keep alive*/ + attr = (struct nlattr *)data; + if (attr->nla_type == MKEEP_ALIVE_ATTRIBUTE_ID) + prPkt->index = nla_get_u8(attr); + + DBGLOG(REQ, INFO, "enable=%d, index=%d\r\n", prPkt->enable, prPkt->index); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidPacketKeepAlive, + prPkt, sizeof(PARAM_PACKET_KEEPALIVE_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + kalMemFree(prPkt, VIR_MEM_TYPE, sizeof(PARAM_PACKET_KEEPALIVE_T)); + return rStatus; + +nla_put_failure: + if (prPkt != NULL) + kalMemFree(prPkt, VIR_MEM_TYPE, sizeof(PARAM_PACKET_KEEPALIVE_T)); + return i4Status; +} + +int mtk_cfg80211_vendor_get_version(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + struct sk_buff *skb; + struct nlattr *attrlist; + char verInfoBuf[64]; + UINT_32 u4CopySize = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(wiphy); + ASSERT(wdev); + + if ((data == NULL) || !data_len) + return -ENOMEM; + + kalMemZero(verInfoBuf, 64); + attrlist = (struct nlattr *)((UINT_8 *) data); + if (attrlist->nla_type == LOGGER_ATTRIBUTE_DRIVER_VER) { + char wifiDriverVersionStr[] = WIFI_MODULE "_" ANDROID_VER "_" RELEASE_DATE "_" SERIAL_NUMBER; + UINT_32 u4StrSize = strlen(wifiDriverVersionStr); + + u4CopySize = (u4StrSize >= 64) ? 63 : u4StrSize; + strncpy(verInfoBuf, wifiDriverVersionStr, u4CopySize); + } else if (attrlist->nla_type == LOGGER_ATTRIBUTE_FW_VER) { + WIFI_VER_INFO_T *prVerInfo; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + prVerInfo = &(prGlueInfo->prAdapter->rVerInfo); + sprintf(verInfoBuf, "%x.%x.%x", (prVerInfo->u2FwOwnVersion >> 8), + (prVerInfo->u2FwOwnVersion & 0xff), (prVerInfo->u2FwOwnVersionExtend)); + u4CopySize = strlen(verInfoBuf); + } + + if (u4CopySize <= 0) + return -EFAULT; + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, u4CopySize); + if (!skb) { + DBGLOG(REQ, ERROR, "Allocate skb failed\n"); + return -ENOMEM; + } + + if (unlikely(nla_put_nohdr(skb, u4CopySize, &verInfoBuf[0]) < 0)) + goto nla_put_failure; + + return cfg80211_vendor_cmd_reply(skb); + +nla_put_failure: + kfree_skb(skb); + return -EFAULT; +} + +#if CFG_SUPPORT_GSCN +int mtk_cfg80211_vendor_event_complete_scan(struct wiphy *wiphy, struct wireless_dev *wdev, WIFI_SCAN_EVENT complete) +{ + struct sk_buff *skb; + WIFI_SCAN_EVENT complete_scan; + + ASSERT(wiphy); + ASSERT(wdev); + + DBGLOG(REQ, INFO, "vendor command complete=%d\r\n", complete); + + skb = cfg80211_vendor_event_alloc(wiphy, wdev, sizeof(complete), GSCAN_EVENT_COMPLETE_SCAN, GFP_KERNEL); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + complete_scan = WIFI_SCAN_RESULTS_AVAILABLE; + /*NLA_PUT_U32(skb, GSCAN_EVENT_COMPLETE_SCAN, complete);*/ + { + unsigned int __tmp = complete; + + if (unlikely(nla_put(skb, GSCAN_EVENT_COMPLETE_SCAN, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -ENOMEM; +} + +int mtk_cfg80211_vendor_event_scan_results_available(struct wiphy *wiphy, struct wireless_dev *wdev, UINT_32 num) +{ + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(wdev); + /* UINT_32 scan_result; */ + + DBGLOG(REQ, INFO, "vendor command num=%d\r\n", num); + + skb = cfg80211_vendor_event_alloc(wiphy, wdev, sizeof(num), GSCAN_EVENT_SCAN_RESULTS_AVAILABLE, GFP_KERNEL); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + /* scan_result = 2; */ + /*NLA_PUT_U32(skb, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE, num);*/ + { + unsigned int __tmp = num; + + if (unlikely(nla_put(skb, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -ENOMEM; +} + +int mtk_cfg80211_vendor_event_full_scan_results(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_GSCAN_FULL_RESULT pdata, UINT_32 data_len) +{ + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(wdev); + ASSERT(pdata); + DBGLOG(REQ, TRACE, "ssid=%s, bssid="MACSTR", rssi=%d, %d, capa=0x%x, ie_length=%d\n", + HIDE(pdata->fixed.ssid), + MAC2STR(pdata->fixed.bssid), + pdata->fixed.rssi, + pdata->fixed.channel, + pdata->fixed.capability, + pdata->ie_length); + + skb = cfg80211_vendor_event_alloc(wiphy, wdev, data_len, GSCAN_EVENT_FULL_SCAN_RESULTS, GFP_KERNEL); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + /* kalMemCopy(&full_result, pdata, sizeof(PARAM_WIFI_GSCAN_FULL_RESULT); */ + /*NLA_PUT(skb, GSCAN_EVENT_FULL_SCAN_RESULTS, sizeof(full_result), &full_result);*/ + if (unlikely(nla_put(skb, GSCAN_EVENT_FULL_SCAN_RESULTS, + data_len, pdata) < 0)) + goto nla_put_failure; + + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -ENOMEM; +} +#endif + +int mtk_cfg80211_vendor_event_significant_change_results(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_CHANGE_RESULT pdata, UINT_32 data_len) +{ + struct sk_buff *skb; + PARAM_WIFI_CHANGE_RESULT result[2], *presult; + + ASSERT(wiphy); + ASSERT(wdev); + DBGLOG(REQ, TRACE, "vendor command\r\n"); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + skb = cfg80211_vendor_event_alloc(wiphy, wdev, sizeof(PARAM_WIFI_CHANGE_RESULT), + GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS, GFP_KERNEL); +#else + skb = cfg80211_vendor_event_alloc(wiphy, sizeof(PARAM_WIFI_CHANGE_RESULT), + GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS, GFP_KERNEL); +#endif + + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + presult = result; + kalMemZero(presult, (sizeof(PARAM_WIFI_CHANGE_RESULT) * 2)); + /* only for test */ + kalMemCopy(presult->bssid, "213123", sizeof(mac_addr)); + presult->channel = 2437; + presult->rssi[0] = -45; + presult->rssi[1] = -46; + presult++; + presult->channel = 2439; + presult->rssi[0] = -47; + presult->rssi[1] = -48; + /*NLA_PUT(skb, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS, (sizeof(PARAM_WIFI_CHANGE_RESULT) * 2), result);*/ + if (unlikely(nla_put(skb, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS, + (sizeof(PARAM_WIFI_CHANGE_RESULT) * 2), result) < 0)) + goto nla_put_failure; + + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -ENOMEM; +} + +int mtk_cfg80211_vendor_event_hotlist_ap_found(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_GSCAN_RESULT pdata, UINT_32 data_len) +{ + struct sk_buff *skb; + PARAM_WIFI_GSCAN_RESULT result[2], *presult; + + ASSERT(wiphy); + ASSERT(wdev); + DBGLOG(REQ, TRACE, "vendor command\r\n"); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + skb = cfg80211_vendor_event_alloc(wiphy, wdev, sizeof(PARAM_WIFI_GSCAN_RESULT), + GSCAN_EVENT_HOTLIST_RESULTS_FOUND, GFP_KERNEL); +#else + skb = cfg80211_vendor_event_alloc(wiphy, sizeof(PARAM_WIFI_GSCAN_RESULT), + GSCAN_EVENT_HOTLIST_RESULTS_FOUND, GFP_KERNEL); +#endif + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + presult = result; + kalMemZero(presult, (sizeof(PARAM_WIFI_GSCAN_RESULT) * 2)); + /* only for test */ + kalMemCopy(presult->bssid, "123123", sizeof(mac_addr)); + presult->channel = 2441; + presult->rssi = -45; + presult++; + presult->channel = 2443; + presult->rssi = -47; + /*NLA_PUT(skb, GSCAN_EVENT_HOTLIST_RESULTS_FOUND, (sizeof(PARAM_WIFI_GSCAN_RESULT) * 2), result);*/ + if (unlikely(nla_put(skb, GSCAN_EVENT_HOTLIST_RESULTS_FOUND, + (sizeof(PARAM_WIFI_GSCAN_RESULT) * 2), result) < 0)) + goto nla_put_failure; + + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -ENOMEM; +} + +int mtk_cfg80211_vendor_event_hotlist_ap_lost(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_GSCAN_RESULT pdata, UINT_32 data_len) +{ + struct sk_buff *skb; + PARAM_WIFI_GSCAN_RESULT result[2], *presult; + + ASSERT(wiphy); + ASSERT(wdev); + DBGLOG(REQ, TRACE, "vendor command\r\n"); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + skb = cfg80211_vendor_event_alloc(wiphy, wdev, sizeof(PARAM_WIFI_GSCAN_RESULT), + GSCAN_EVENT_HOTLIST_RESULTS_LOST, GFP_KERNEL); +#else + skb = cfg80211_vendor_event_alloc(wiphy, sizeof(PARAM_WIFI_GSCAN_RESULT), + GSCAN_EVENT_HOTLIST_RESULTS_LOST, GFP_KERNEL); +#endif + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + presult = result; + kalMemZero(presult, (sizeof(PARAM_WIFI_GSCAN_RESULT) * 2)); + /* only for test */ + kalMemCopy(presult->bssid, "321321", sizeof(mac_addr)); + presult->channel = 2445; + presult->rssi = -46; + presult++; + presult->channel = 2447; + presult->rssi = -48; + /*NLA_PUT(skb, GSCAN_EVENT_HOTLIST_RESULTS_LOST, (sizeof(PARAM_WIFI_GSCAN_RESULT) * 2), result);*/ + if (unlikely(nla_put(skb, GSCAN_EVENT_HOTLIST_RESULTS_LOST, + (sizeof(PARAM_WIFI_GSCAN_RESULT) * 2), result) < 0)) + goto nla_put_failure; + + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -ENOMEM; +} + +int mtk_cfg80211_vendor_event_rssi_beyond_range(struct wiphy *wiphy, struct wireless_dev *wdev, INT_32 rssi) +{ + struct sk_buff *skb; + PARAM_RSSI_MONITOR_EVENT rRSSIEvt; + P_BSS_INFO_T prAisBssInfo; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(wiphy); + ASSERT(wdev); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, TRACE, "vendor command rssi=%d\r\n", rssi); + kalMemZero(&rRSSIEvt, sizeof(PARAM_RSSI_MONITOR_EVENT)); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + skb = cfg80211_vendor_event_alloc(wiphy, wdev, sizeof(PARAM_RSSI_MONITOR_EVENT), + WIFI_EVENT_RSSI_MONITOR, GFP_KERNEL); +#else + skb = cfg80211_vendor_event_alloc(wiphy, sizeof(PARAM_RSSI_MONITOR_EVENT), + WIFI_EVENT_RSSI_MONITOR, GFP_KERNEL); +#endif + + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + prAisBssInfo = &(prGlueInfo->prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + kalMemCopy(rRSSIEvt.BSSID, prAisBssInfo->aucBSSID, sizeof(UINT_8) * MAC_ADDR_LEN); + + rRSSIEvt.version = 1; /* RSSI_MONITOR_EVT_VERSION = 1 */ + if (rssi > PARAM_WHQL_RSSI_MAX_DBM) + rssi = PARAM_WHQL_RSSI_MAX_DBM; + else if (rssi < -127) + rssi = -127; + rRSSIEvt.rssi = (INT_8)rssi; + DBGLOG(REQ, INFO, "RSSI Event: version=%d, rssi=%d, BSSID=" MACSTR "\r\n", + rRSSIEvt.version, rRSSIEvt.rssi, MAC2STR(rRSSIEvt.BSSID)); + + /*NLA_PUT_U32(skb, GOOGLE_RSSI_MONITOR_EVENT, rssi);*/ + { + /* unsigned int __tmp = rssi; */ + + if (unlikely(nla_put(skb, WIFI_EVENT_RSSI_MONITOR, + sizeof(PARAM_RSSI_MONITOR_EVENT), &rRSSIEvt) < 0)) + goto nla_put_failure; + } + + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -ENOMEM; +} + +int mtk_cfg80211_vendor_set_band(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + struct nlattr *attr; + UINT_8 setBand = 0; + ENUM_BAND_T band; + + ASSERT(wiphy); + ASSERT(wdev); + + DBGLOG(REQ, TRACE, "%s()\n", __func__); + + if ((data == NULL) || !data_len) + goto nla_put_failure; + + DBGLOG(REQ, TRACE, "vendor command: data_len=%d, data=0x%x 0x%x\r\n", + data_len, *((UINT_32 *) data), *((UINT_32 *) data + 1)); + + attr = (struct nlattr *)data; + setBand = nla_get_u32(attr); + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, INFO, "Vendor Set Band value=%d\r\n", setBand); + + if (setBand == QCA_SETBAND_5G) + band = BAND_5G; + else if (setBand == QCA_SETBAND_2G) + band = BAND_2G4; + else + band = BAND_NULL; + + prGlueInfo->prAdapter->aeSetBand[NETWORK_TYPE_AIS_INDEX] = band; + return 0; + +nla_put_failure: + return -1; + +} + +int mtk_cfg80211_vendor_set_roaming_policy(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + struct nlattr *attr; + UINT_32 setRoaming = 0; + UINT_32 u4BufLen = 0; + + ASSERT(wiphy); + ASSERT(wdev); + + DBGLOG(REQ, TRACE, "%s()\n", __func__); + + if ((data == NULL) || !data_len) + goto nla_put_failure; + + attr = (struct nlattr *)data; + setRoaming = nla_get_u32(attr); + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, INFO, "vendor command: data_len=%d, data=0x%x 0x%x, policy = %d\n", + data_len, *((UINT_32 *) data), *((UINT_32 *) data + 1), setRoaming); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetDrvRoamingPolicy, + &setRoaming, sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + return 0; + +nla_put_failure: + return -1; + +} + +int mtk_cfg80211_vendor_get_supported_feature_set(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + uint32_t u4FeatureSet = WIFI_HAL_FEATURE_SET; + P_GLUE_INFO_T prGlueInfo; + P_REG_INFO_T prRegInfo; + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(wdev); + if (wdev->iftype == NL80211_IFTYPE_AP) + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + else + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + if (!prGlueInfo) + return -EFAULT; + prRegInfo = &prGlueInfo->rRegInfo; + if (!prRegInfo) + return -EFAULT; + + if (prRegInfo->ucSupport5GBand) + u4FeatureSet |= WIFI_FEATURE_INFRA_5G; + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u4FeatureSet)); + if (!skb) { + DBGLOG(REQ, ERROR, "Allocate skb failed\n"); + return -ENOMEM; + } + + if (unlikely( + nla_put_nohdr(skb, sizeof(u4FeatureSet), &u4FeatureSet) < 0)) { + DBGLOG(REQ, ERROR, "nla_put_nohdr failed\n"); + goto nla_put_failure; + } + + DBGLOG(REQ, INFO, "supported feature set=0x%x\n", u4FeatureSet); + + return cfg80211_vendor_cmd_reply(skb); + +nla_put_failure: + kfree_skb(skb); + return -EFAULT; +} + +int mtk_cfg80211_vendor_set_tx_power_scenario(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo; + struct PARAM_TX_POWER_LIMIT rTxPwrLimit; + struct nlattr *attr; + uint32_t u4Scenario; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(wdev); + if (wdev->iftype == NL80211_IFTYPE_AP) + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + else + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + if (!prGlueInfo) + return -EFAULT; + + attr = (struct nlattr *)data; + if (attr->nla_type == WIFI_ATTRIBUTE_TX_POWER_SCENARIO) + u4Scenario = nla_get_u32(attr); + else + return -EINVAL; + + kalMemZero(&rTxPwrLimit, sizeof(struct PARAM_TX_POWER_LIMIT)); + rTxPwrLimit.iScenario = (u4Scenario == UINT_MAX) ? + -1 : (int32_t)u4Scenario; + + DBGLOG(REQ, INFO, + "iScenario=%d, u4Scenario=%u, UINT_MAX=%u, iftype=%d\n", + rTxPwrLimit.iScenario, u4Scenario, UINT_MAX, + wdev->iftype); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetTxPowerLimit, + (PVOID)&rTxPwrLimit, + sizeof(struct PARAM_TX_POWER_LIMIT), + FALSE, FALSE, TRUE, FALSE, NULL); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(rStatus)); + if (!skb) { + DBGLOG(REQ, ERROR, "Allocate skb failed\n"); + return -ENOMEM; + } + + if (unlikely( + nla_put_nohdr(skb, sizeof(rStatus), &rStatus) < 0)) { + DBGLOG(REQ, ERROR, "nla_put_nohdr failed\n"); + goto errHandleLabel; + } + + DBGLOG(REQ, INFO, "rStatus=0x%x\n", rStatus); + + return cfg80211_vendor_cmd_reply(skb); + +errHandleLabel: + kfree_skb(skb); + return -EFAULT; +} + +int mtk_cfg80211_vendor_acs(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo; + struct nlattr *tb[WIFI_VENDOR_ATTR_ACS_MAX + 1] = { 0 }; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + bool ht_enabled, ht40_enabled, vht_enabled; + uint8_t ch_width = 0; + enum P2P_VENDOR_ACS_HW_MODE hw_mode; + uint8_t *ch_list = NULL; + uint8_t ch_list_count = 0; + uint8_t i; + uint32_t msg_size; + struct MSG_P2P_ACS_REQUEST *prMsgAcsRequest; + P_RF_CHANNEL_INFO_T prRfChannelInfo; + struct sk_buff *reply_skb; + + if (!wiphy || !wdev || !data || !data_len) { + DBGLOG(REQ, ERROR, "input data null.\n"); + rStatus = -EINVAL; + goto exit; + } + + if (wdev->iftype == NL80211_IFTYPE_AP) + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + else + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + if (!prGlueInfo) { + DBGLOG(REQ, ERROR, "get glue structure fail.\n"); + rStatus = -EFAULT; + goto exit; + } + + if (NLA_PARSE(tb, WIFI_VENDOR_ATTR_ACS_MAX, data, data_len, + nla_get_acs_policy)) { + DBGLOG(REQ, ERROR, "parse acs attr fail.\n"); + rStatus = -EINVAL; + goto exit; + } + + if (!tb[WIFI_VENDOR_ATTR_ACS_HW_MODE]) { + DBGLOG(REQ, ERROR, "attr hw_mode failed.\n"); + rStatus = -EINVAL; + goto exit; + } + hw_mode = nla_get_u8(tb[WIFI_VENDOR_ATTR_ACS_HW_MODE]); + + if (tb[WIFI_VENDOR_ATTR_ACS_HT_ENABLED]) + ht_enabled = + nla_get_flag(tb[WIFI_VENDOR_ATTR_ACS_HT_ENABLED]); + else + ht_enabled = 0; + + if (tb[WIFI_VENDOR_ATTR_ACS_HT40_ENABLED]) + ht40_enabled = + nla_get_flag(tb[WIFI_VENDOR_ATTR_ACS_HT40_ENABLED]); + else + ht40_enabled = 0; + + if (tb[WIFI_VENDOR_ATTR_ACS_VHT_ENABLED]) + vht_enabled = + nla_get_flag(tb[WIFI_VENDOR_ATTR_ACS_VHT_ENABLED]); + else + vht_enabled = 0; + + if (tb[WIFI_VENDOR_ATTR_ACS_CHWIDTH]) + ch_width = nla_get_u16(tb[WIFI_VENDOR_ATTR_ACS_CHWIDTH]); + + if (tb[WIFI_VENDOR_ATTR_ACS_CH_LIST]) { + char *tmp = nla_data(tb[WIFI_VENDOR_ATTR_ACS_CH_LIST]); + + ch_list_count = nla_len(tb[WIFI_VENDOR_ATTR_ACS_CH_LIST]); + if (ch_list_count) { + ch_list = kalMemAlloc(sizeof(uint8_t) * ch_list_count, + VIR_MEM_TYPE); + if (ch_list == NULL) { + DBGLOG(REQ, ERROR, "allocate ch_list fail.\n"); + rStatus = -ENOMEM; + goto exit; + } + + kalMemCopy(ch_list, tmp, ch_list_count); + } + } else if (tb[WIFI_VENDOR_ATTR_ACS_FREQ_LIST]) { + uint32_t *freq = + nla_data(tb[WIFI_VENDOR_ATTR_ACS_FREQ_LIST]); + + ch_list_count = nla_len(tb[WIFI_VENDOR_ATTR_ACS_FREQ_LIST]) / + sizeof(uint32_t); + if (ch_list_count) { + ch_list = kalMemAlloc(sizeof(uint8_t) * ch_list_count, + VIR_MEM_TYPE); + if (ch_list == NULL) { + DBGLOG(REQ, ERROR, "allocate ch_list fail.\n"); + rStatus = -ENOMEM; + goto exit; + } + + for (i = 0; i < ch_list_count; i++) + ch_list[i] = + ieee80211_frequency_to_channel(freq[i]); + } + } + + if (!ch_list_count) { + DBGLOG(REQ, ERROR, "channel list count can NOT be 0\n"); + rStatus = -EINVAL; + goto exit; + } + + msg_size = sizeof(struct MSG_P2P_ACS_REQUEST) + + (ch_list_count * sizeof(RF_CHANNEL_INFO_T)); + + prMsgAcsRequest = cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, msg_size); + + if (prMsgAcsRequest == NULL) { + DBGLOG(REQ, ERROR, "allocate msg acs req. fail.\n"); + rStatus = -ENOMEM; + goto exit; + } + + kalMemSet(prMsgAcsRequest, 0, msg_size); + prMsgAcsRequest->rMsgHdr.eMsgId = MID_MNY_P2P_ACS; + prMsgAcsRequest->fgIsHtEnable = ht_enabled; + prMsgAcsRequest->fgIsHt40Enable = ht40_enabled; + prMsgAcsRequest->fgIsVhtEnable = vht_enabled; + switch (ch_width) { + case 20: + prMsgAcsRequest->eChnlBw = MAX_BW_20MHZ; + break; + case 40: + prMsgAcsRequest->eChnlBw = MAX_BW_40MHZ; + break; + case 80: + prMsgAcsRequest->eChnlBw = MAX_BW_80MHZ; + break; + case 160: + prMsgAcsRequest->eChnlBw = MAX_BW_160MHZ; + break; + default: + DBGLOG(REQ, ERROR, "unsupport width: %d.\n", ch_width); + prMsgAcsRequest->eChnlBw = MAX_BW_UNKNOWN; + break; + } + prMsgAcsRequest->eHwMode = hw_mode; + prMsgAcsRequest->u4NumChannel = ch_list_count; + + for (i = 0; i < ch_list_count; i++) { + /* Translate Freq from MHz to channel number. */ + prRfChannelInfo = + &(prMsgAcsRequest->arChannelListInfo[i]); + + prRfChannelInfo->ucChannelNum = ch_list[i]; + + if (prRfChannelInfo->ucChannelNum <= 14) + prRfChannelInfo->eBand = BAND_2G4; + else + prRfChannelInfo->eBand = BAND_5G; + + /* Iteration. */ + prRfChannelInfo++; + } + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prMsgAcsRequest, + MSG_SEND_METHOD_BUF); + +exit: + if (ch_list) + kalMemFree(ch_list, VIR_MEM_TYPE, + sizeof(uint8_t) * ch_list_count); + if (rStatus == WLAN_STATUS_SUCCESS) { + reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, + NLMSG_HDRLEN); + if (reply_skb != NULL) + return cfg80211_vendor_cmd_reply(reply_skb); + } + return rStatus; +} + +int mtk_cfg80211_vendor_get_features(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + struct sk_buff *reply_skb; + uint8_t feature_flags[(NUM_VENDOR_FEATURES + 7) / 8] = {0}; + uint8_t i; + + if (!wiphy || !wdev) { + DBGLOG(REQ, ERROR, "input data null.\n"); + return -EINVAL; + } + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + feature_flags[(VENDOR_FEATURE_SUPPORT_HW_MODE_ANY / 8)] |= + (1 << (VENDOR_FEATURE_SUPPORT_HW_MODE_ANY % 8)); +#endif + + for (i = 0; i < ((NUM_VENDOR_FEATURES + 7) / 8); i++) { + DBGLOG(REQ, INFO, "Dump feature flags[%d]=0x%x.\n", i, + feature_flags[i]); + } + + reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, + sizeof(feature_flags) + NLMSG_HDRLEN); + + if (!reply_skb) + goto nla_put_failure; + + if (nla_put(reply_skb, WIFI_VENDOR_ATTR_FEATURE_FLAGS, + sizeof(feature_flags), feature_flags)) + goto nla_put_failure; + + return cfg80211_vendor_cmd_reply(reply_skb); + +nla_put_failure: + kfree_skb(reply_skb); + return -EINVAL; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_wext.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_wext.c new file mode 100644 index 0000000000000..ddb48a51a1975 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_wext.c @@ -0,0 +1,4359 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ + +#include "gl_os.h" + +#include "config.h" +#include "wlan_oid.h" + +#include "gl_wext.h" +#include "gl_wext_priv.h" + +#include "precomp.h" + +#if CFG_SUPPORT_WAPI +#include "gl_sec.h" +#endif + +/* compatibility to wireless extensions */ +#ifdef WIRELESS_EXT + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +const long channel_freq[] = { + 2412, 2417, 2422, 2427, 2432, 2437, 2442, + 2447, 2452, 2457, 2462, 2467, 2472, 2484 +}; + +#define NUM_CHANNELS (ARRAY_SIZE(channel_freq)) + +#define MAX_SSID_LEN 32 +#define COUNTRY_CODE_LEN 10 /* country code length */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************** + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************** + */ +/* NOTE: name in iwpriv_args only have 16 bytes */ +static const struct iw_priv_args rIwPrivTable[] = { + {IOCTL_SET_INT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, ""}, + {IOCTL_GET_INT, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, ""}, + {IOCTL_SET_INT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, ""}, + {IOCTL_GET_INT, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, ""}, + {IOCTL_SET_INT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, ""}, + + {IOCTL_GET_INT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, ""}, + {IOCTL_GET_INT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, ""}, + + {IOCTL_SET_INTS, IW_PRIV_TYPE_INT | 4, 0, ""}, + {IOCTL_GET_INT, 0, IW_PRIV_TYPE_INT | 50, ""}, + {IOCTL_GET_INT, 0, IW_PRIV_TYPE_CHAR | 16, ""}, + + {IOCTL_SET_STRING, IW_PRIV_TYPE_CHAR | 512, 0, ""}, + + {IOCTL_GET_STRING, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | 512, ""}, + + /* added for set_oid and get_oid */ + {IOCTL_SET_STRUCT, 256, 0, ""}, + {IOCTL_GET_STRUCT, 0, 256, ""}, + + {IOCTL_GET_DRIVER, IW_PRIV_TYPE_CHAR | 2000, IW_PRIV_TYPE_CHAR | + 2000, "driver"}, + + /* sub-ioctl definitions */ +#if 0 + {PRIV_CMD_REG_DOMAIN, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_reg_domain"}, + {PRIV_CMD_REG_DOMAIN, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_reg_domain"}, +#endif + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + {PRIV_CMD_CSUM_OFFLOAD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_tcp_csum"}, +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + {PRIV_CMD_POWER_MODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_power_mode"}, + {PRIV_CMD_POWER_MODE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_power_mode"}, + + {PRIV_CMD_WMM_PS, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "set_wmm_ps"}, + + {PRIV_CMD_TEST_MODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_test_mode"}, + {PRIV_CMD_TEST_CMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_test_cmd"}, + {PRIV_CMD_TEST_CMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_test_result"}, +#if CFG_SUPPORT_PRIV_MCR_RW + {PRIV_CMD_ACCESS_MCR, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_mcr"}, + {PRIV_CMD_ACCESS_MCR, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_mcr"}, +#endif + {PRIV_CMD_SW_CTRL, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_sw_ctrl"}, + {PRIV_CMD_SW_CTRL, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_sw_ctrl"}, + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS + {PRIV_CUSTOM_BWCS_CMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_bwcs"}, + /* GET STRUCT sub-ioctls commands */ + {PRIV_CUSTOM_BWCS_CMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_bwcs"}, +#endif + + /* SET STRUCT sub-ioctls commands */ + {PRIV_CMD_OID, 256, 0, "set_oid"}, + /* GET STRUCT sub-ioctls commands */ + {PRIV_CMD_OID, 0, 256, "get_oid"}, + + {PRIV_CMD_BAND_CONFIG, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_band"}, + {PRIV_CMD_BAND_CONFIG, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_band"}, + + {PRIV_CMD_SET_TX_POWER, IW_PRIV_TYPE_INT | 4, 0, "set_txpower"}, + {PRIV_CMD_GET_CH_LIST, 0, IW_PRIV_TYPE_INT | 50, "get_ch_list"}, + {PRIV_CMD_DUMP_MEM, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_mem"}, + +#if CFG_ENABLE_WIFI_DIRECT + {PRIV_CMD_P2P_MODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_p2p_mode"}, +#endif + {PRIV_CMD_GET_BUILD_DATE_CODE, 0, IW_PRIV_TYPE_CHAR | 16, "get_date_code"}, + {PRIV_CMD_GET_DEBUG_CODE, 0, IW_PRIV_TYPE_CHAR | 16, "get_dbg_code"}, + /* handle any command with many input parameters */ + {PRIV_CMD_OTHER, IW_PRIV_TYPE_CHAR | 512, 0, "set_str_cmd"}, + + {PRIV_CMD_DUMP_DRIVER, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | 512, "dump_driver"}, + + {PRIV_CMD_WFD_DEBUG_CODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_wfd_dbg_code"}, +}; + +static const iw_handler rIwPrivHandler[] = { + [IOCTL_SET_INT - SIOCIWFIRSTPRIV] = priv_set_int, + [IOCTL_GET_INT - SIOCIWFIRSTPRIV] = priv_get_int, + [IOCTL_SET_ADDRESS - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_GET_ADDRESS - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_SET_STR - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_GET_STR - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_SET_KEY - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_GET_KEY - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_SET_STRUCT - SIOCIWFIRSTPRIV] = priv_set_struct, + [IOCTL_GET_STRUCT - SIOCIWFIRSTPRIV] = priv_get_struct, + [IOCTL_SET_STRUCT_FOR_EM - SIOCIWFIRSTPRIV] = priv_set_struct, + [IOCTL_SET_INTS - SIOCIWFIRSTPRIV] = priv_set_ints, + [IOCTL_GET_INTS - SIOCIWFIRSTPRIV] = priv_get_ints, + [IOCTL_SET_STRING - SIOCIWFIRSTPRIV] = priv_set_string, + [IOCTL_GET_STRING - SIOCIWFIRSTPRIV] = priv_get_string, + [IOCTL_GET_DRIVER - SIOCIWFIRSTPRIV] = priv_set_driver, +}; + +/* standard ioctls */ +static int std_get_name(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_freq(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_freq(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_mode(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_mode(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_ap(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_ap(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_rate(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_rts(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_rts(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_frag(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_txpow(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_txpow(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_power(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_power(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_range(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_priv(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_priv(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_mlme(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_scan(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_scan(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_essid(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_essid(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_encode(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_encode(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_auth(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_encode_ext(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static const iw_handler mtk_std_handler[] = { + IW_HANDLER(SIOCGIWNAME, std_get_name), /* factory mode used */ + IW_HANDLER(SIOCSIWFREQ, std_set_freq), + IW_HANDLER(SIOCGIWFREQ, std_get_freq), /* factory mode used */ + IW_HANDLER(SIOCSIWMODE, std_set_mode), /* factory mode used */ + IW_HANDLER(SIOCGIWMODE, std_get_mode), /* factory mode used */ + IW_HANDLER(SIOCGIWRANGE, std_get_range), /* factory mode used */ + IW_HANDLER(SIOCSIWPRIV, std_set_priv), + IW_HANDLER(SIOCGIWPRIV, std_get_priv), + IW_HANDLER(SIOCSIWAP, std_set_ap), + IW_HANDLER(SIOCGIWAP, std_get_ap), /* factory mode used */ + IW_HANDLER(SIOCSIWMLME, std_set_mlme), + IW_HANDLER(SIOCSIWSCAN, std_set_scan), /* factory mode used */ + IW_HANDLER(SIOCGIWSCAN, std_get_scan), /* factory mode used */ + IW_HANDLER(SIOCSIWESSID, std_set_essid), /* factory mode used */ + IW_HANDLER(SIOCGIWESSID, std_get_essid), /* factory mode used */ + IW_HANDLER(SIOCGIWRATE, std_get_rate), /* factory mode used */ + IW_HANDLER(SIOCSIWRTS, std_set_rts), + IW_HANDLER(SIOCGIWRTS, std_get_rts), /* factory mode used */ + IW_HANDLER(SIOCGIWFRAG, std_get_frag), /* factory mode used */ + IW_HANDLER(SIOCSIWTXPOW, std_set_txpow), + IW_HANDLER(SIOCGIWTXPOW, std_get_txpow), /* factory mode used */ + IW_HANDLER(SIOCSIWENCODE, std_set_encode), + IW_HANDLER(SIOCGIWENCODE, std_get_encode),/* factory mode used */ + IW_HANDLER(SIOCSIWPOWER, std_set_power), + IW_HANDLER(SIOCGIWPOWER, std_get_power), /* factory mode used */ + IW_HANDLER(SIOCSIWAUTH, std_set_auth), + IW_HANDLER(SIOCSIWENCODEEXT, std_set_encode_ext), +}; + +const struct iw_handler_def wext_handler_def = { + .num_standard = (__u16) sizeof(mtk_std_handler) / sizeof(iw_handler), + .num_private = (__u16) sizeof(rIwPrivHandler) / sizeof(iw_handler), + .num_private_args = (__u16) sizeof(rIwPrivTable) / sizeof(struct iw_priv_args), + .standard = (iw_handler *) mtk_std_handler, + .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 PPUINT_8 ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ucDesiredElemId && i4InfoElemLen <= i4TotalIeLen) { + if (ucDesiredElemId != 0xDD) { + /* Non 0xDD, OK! */ + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + /* EID == 0xDD, check WPA IE */ + if (pucIEStart[1] >= 4) { + if (memcmp(&pucIEStart[2], "\x00\x50\xf2\x01", 4) == 0) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + } /* check WPA IE length */ + /* check EID == 0xDD */ + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* parseSearchDesiredWPAIE */ + +#if CFG_SUPPORT_WAPI +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired WAPI Information Element . +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextSrchDesiredWAPIIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PPUINT_8 ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ELEM_ID_WAPI && i4InfoElemLen <= i4TotalIeLen) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* wextSrchDesiredWAPIIE */ +#endif + +#if CFG_SUPPORT_HOTSPOT_2_0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief Check if exist the desired HS2.0 Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextIsDesiredHS20IE(IN PUINT_8 pucCurIE, IN INT_32 i4TotalIeLen) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucCurIE); + + i4InfoElemLen = (INT_32) pucCurIE[1] + 2; + + if (pucCurIE[0] == ELEM_ID_VENDOR && i4InfoElemLen <= i4TotalIeLen) { + if (pucCurIE[1] >= ELEM_MIN_LEN_HS20_INDICATION) { + if (memcmp(&pucCurIE[2], "\x50\x6f\x9a\x10", 4) == 0) + return TRUE; + } + } + /* check desired EID */ + return FALSE; +} /* wextIsDesiredHS20IE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Check if exist the desired interworking Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextIsDesiredInterworkingIE(IN PUINT_8 pucCurIE, IN INT_32 i4TotalIeLen) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucCurIE); + + i4InfoElemLen = (INT_32) pucCurIE[1] + 2; + + if (pucCurIE[0] == ELEM_ID_INTERWORKING && i4InfoElemLen <= i4TotalIeLen) { + switch (pucCurIE[1]) { + case IW_IE_LENGTH_ANO: + case IW_IE_LENGTH_ANO_HESSID: + case IW_IE_LENGTH_ANO_VENUE: + case IW_IE_LENGTH_ANO_VENUE_HESSID: + return TRUE; + + default: + break; + } + + } + /* check desired EID */ + return FALSE; +} /* wextIsDesiredInterworkingIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Check if exist the desired Adv Protocol Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextIsDesiredAdvProtocolIE(IN PUINT_8 pucCurIE, IN INT_32 i4TotalIeLen) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucCurIE); + + i4InfoElemLen = (INT_32) pucCurIE[1] + 2; + + if (pucCurIE[0] == ELEM_ID_ADVERTISEMENT_PROTOCOL && i4InfoElemLen <= i4TotalIeLen) + return TRUE; + /* check desired EID */ + return FALSE; +} /* wextIsDesiredAdvProtocolIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Check if exist the desired Roaming Consortium Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextIsDesiredRoamingConsortiumIE(IN PUINT_8 pucCurIE, IN INT_32 i4TotalIeLen) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucCurIE); + + i4InfoElemLen = (INT_32) pucCurIE[1] + 2; + + if (pucCurIE[0] == ELEM_ID_ROAMING_CONSORTIUM && i4InfoElemLen <= i4TotalIeLen) + return TRUE; + /* check desired EID */ + return FALSE; +} /* wextIsDesiredRoamingConsortiumIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired HS2.0 Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextSrchDesiredHS20IE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PPUINT_8 ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ELEM_ID_VENDOR && i4InfoElemLen <= i4TotalIeLen) { + if (pucIEStart[1] >= ELEM_MIN_LEN_HS20_INDICATION) { + if (memcmp(&pucIEStart[2], "\x50\x6f\x9a\x10", 4) == 0) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + } + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* wextSrchDesiredHS20IE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired HS2.0 Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextSrchDesiredOsenIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PPUINT_8 ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + if (pucIEStart[0] == ELEM_ID_VENDOR && i4InfoElemLen <= i4TotalIeLen) { + if (pucIEStart[1] >= 4) { + if (memcmp(&pucIEStart[2], "\x50\x6f\x9a\x12", 4) == 0) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + } + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired Adv Protocol Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextSrchDesiredAdvProtocolIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PPUINT_8 ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ELEM_ID_ADVERTISEMENT_PROTOCOL && i4InfoElemLen <= i4TotalIeLen) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* wextSrchDesiredAdvProtocolIE */ +#endif +#if (CFG_REFACTORY_PMKSA == 0) +BOOLEAN wextSrchOkcAndPMKID(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PPUINT_8 ppucPMKID, OUT PUINT_8 okc) +{ + INT_32 i4InfoElemLen; + UINT_8 ucDone = 0; + + ASSERT(pucIEStart); + ASSERT(ppucPMKID); + ASSERT(okc); + *okc = 0; + *ppucPMKID = NULL; + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + if (i4InfoElemLen > i4TotalIeLen) + break; + if (pucIEStart[0] == ELEM_ID_VENDOR) { + if (pucIEStart[1] != 4 || pucIEStart[2] != 0 || pucIEStart[3] != 0x8 || pucIEStart[4] != 0x22) + goto check_next; + *okc = pucIEStart[5]; + ucDone |= 1; + } else if (pucIEStart[0] == ELEM_ID_RSN) { + /* + * RSN IE: + * EID(1), Len(1), Version(2), GrpCipher(4), PairCipherCnt(2), PairCipherList(PairCipherCnt * 4) + * AKMCnt(2), AkmList(4*AkmCnt), RSNCap(2), PMKIDCnt(2), PMKIDList(16*PMKIDCnt), GrpMgtCipher(4) + */ + UINT_16 u2CipherCnt = 0; + UINT_16 u2AkmCnt = 0; + INT_32 i4LenToCheck = 8; + + /* if no Pairwise Cipher Count field, bypass */ + if (i4InfoElemLen < i4LenToCheck + 2) + goto check_next; + u2CipherCnt = *(PUINT_16)&pucIEStart[i4LenToCheck]; + i4LenToCheck += 2; /* include length of Pairwise Cipher Count field */ + i4LenToCheck += u2CipherCnt * 4; /* include cipher list field */ + /* if no AKM Count, bypass */ + if (i4InfoElemLen < i4LenToCheck + 2) + goto check_next; + u2AkmCnt = *(PUINT_16)&pucIEStart[i4LenToCheck]; + i4LenToCheck += 2; /* include length of AKM Count */ + i4LenToCheck += u2AkmCnt * 4 + 2; /* include akm list field */ + /* + * if IE length is 10 + u2CipherCnt * 4 + 2 + u2AkmCnt * 4 + 2 + 6, + * means PMKID count field is zero, and Group Mgmt Cipher may be exist + */ + if (i4InfoElemLen <= i4LenToCheck + 6) + goto check_next; + *ppucPMKID = pucIEStart + i4LenToCheck; /* return PMKID field and started at PMKID count */ + ucDone |= 2; + } + if (ucDone == 3) + return TRUE; + /* check desired EID */ + /* Select next information element. */ +check_next: + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + return FALSE; +} +#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 PPUINT_8 ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ucDesiredElemId && i4InfoElemLen <= i4TotalIeLen) { + if (ucDesiredElemId != 0xDD) { + /* Non 0xDD, OK! */ + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + /* EID == 0xDD, check WPS IE */ + if (pucIEStart[1] >= 4) { + if (memcmp(&pucIEStart[2], "\x00\x50\xf2\x04", 4) == 0) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + } /* check WPS IE length */ + /* check EID == 0xDD */ + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* parseSearchDesiredWPSIE */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Get the name of the protocol used on the air. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] pcName Buffer to store protocol name string +* \param[in] pcExtra NULL. +* +* \retval 0 For success. +* +* \note If netif_carrier_ok, protocol name is returned; +* otherwise, "disconnected" is returned. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_name(IN struct net_device *prNetDev, IN struct iw_request_info *prIwrInfo, + OUT char *pcName, IN UINT_32 pcNameSize, IN char *pcExtra) +{ + ENUM_PARAM_NETWORK_TYPE_T eNetWorkType = PARAM_NETWORK_TYPE_NUM; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(pcName); + if (FALSE == GLUE_CHK_PR2(prNetDev, pcName)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (netif_carrier_ok(prNetDev)) { + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryNetworkTypeInUse, + &eNetWorkType, sizeof(eNetWorkType), TRUE, FALSE, FALSE, FALSE, &u4BufLen); + + switch (eNetWorkType) { + case PARAM_NETWORK_TYPE_DS: + strncpy(pcName, "IEEE 802.11b", pcNameSize); + break; + case PARAM_NETWORK_TYPE_OFDM24: + strncpy(pcName, "IEEE 802.11bgn", pcNameSize); + break; + case PARAM_NETWORK_TYPE_AUTOMODE: + case PARAM_NETWORK_TYPE_OFDM5: + strncpy(pcName, "IEEE 802.11abgn", pcNameSize); + break; + case PARAM_NETWORK_TYPE_FH: + default: + strncpy(pcName, "IEEE 802.11", pcNameSize); + break; + } + } else { + strncpy(pcName, "Disconnected", pcNameSize); + } + + pcName[pcNameSize - 1] = '\0'; + + 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 (GLUE_CHK_PR2(prNetDev, prIwFreq) == FALSE) + 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 (rStatus != WLAN_STATUS_SUCCESS) + return -EINVAL; + } + /* Setting by channel number */ + else if ((prIwFreq->m > KILO) || (prIwFreq->e > 0)) + return -EOPNOTSUPP; + + /* Change to channel number format */ + u4ChnlFreq = (UINT_32) prIwFreq->m; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetChannel, &u4ChnlFreq, sizeof(u4ChnlFreq), FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + 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 (GLUE_CHK_PR2(prNetDev, prIwFreq) == FALSE) + 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 (GLUE_CHK_PR2(prNetDev, pu4Mode) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + switch (*pu4Mode) { + case IW_MODE_AUTO: + eOpMode = NET_TYPE_AUTO_SWITCH; + break; + + case IW_MODE_ADHOC: + eOpMode = NET_TYPE_IBSS; + break; + + case IW_MODE_INFRA: + eOpMode = NET_TYPE_INFRA; + break; + + default: + DBGLOG(REQ, ERROR, "%s(): Set UNSUPPORTED Mode = %d.\n", __func__, *pu4Mode); + return -EOPNOTSUPP; + } + + /* printk("%s(): Set Mode = %d\n", __FUNCTION__, *pu4Mode); */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetInfrastructureMode, + &eOpMode, sizeof(eOpMode), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + /* after set operation mode, key table are cleared */ + + /* reset wpa info */ + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + prGlueInfo->rWpaInfo.u4KeyMgmt = 0; + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; +#if CFG_SUPPORT_802_11W + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; +#endif + + return 0; +} /* wext_set_mode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get operating mode. +* +* \param[in] prNetDev Net device requested. +* \param[in] prIwReqInfo NULL. +* \param[out] pu4Mode Buffer to store operating mode information. +* \param[in] pcExtra NULL. +* +* \retval 0 If data is valid. +* \retval -EINVAL Otherwise. +* +* \note If netif_carrier_ok, operating mode information is stored in pu4Mode. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_mode(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, OUT unsigned int *pu4Mode, IN char *pcExtra) +{ + ENUM_PARAM_OP_MODE_T eOpMode = NET_TYPE_NUM; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(pu4Mode); + if (GLUE_CHK_PR2(prNetDev, pu4Mode) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryInfrastructureMode, + &eOpMode, sizeof(eOpMode), TRUE, FALSE, FALSE, FALSE, &u4BufLen); + + switch (eOpMode) { + case NET_TYPE_IBSS: + *pu4Mode = IW_MODE_ADHOC; + break; + + case NET_TYPE_INFRA: + *pu4Mode = IW_MODE_INFRA; + break; + + case NET_TYPE_AUTO_SWITCH: + *pu4Mode = IW_MODE_AUTO; + break; + + default: + DBGLOG(REQ, ERROR, "%s(): Get UNKNOWN Mode.\n", __func__); + return -EINVAL; + } + + return 0; +} /* wext_get_mode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get the valid range for each configurable STA setting value. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prData Pointer to iw_point structure, not used. +* \param[out] pcExtra Pointer to buffer which is allocated by caller of this +* function, wext_support_ioctl() or ioctl_standard_call() in +* wireless.c. +* +* \retval 0 If data is valid. +* +* \note The extra buffer (pcExtra) is filled with information from driver. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_range(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, IN struct iw_point *prData, OUT char *pcExtra) +{ + struct iw_range *prRange = NULL; + PARAM_RATES_EX aucSuppRate = { 0 }; /* data buffers */ + int i = 0; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(pcExtra); + if (GLUE_CHK_PR2(prNetDev, pcExtra) == FALSE) + 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 (GLUE_CHK_PR2(prNetDev, prAddr) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* if (!netif_carrier_ok(prNetDev)) { */ + /* return -ENOTCONN; */ + /* } */ + + if (prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_DISCONNECTED) { + /* memset(prAddr, 0, 6); */ + memset(prAddr, 0, sizeof(struct sockaddr)); + return 0; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryBssid, prAddr->sa_data, ETH_ALEN, TRUE, FALSE, FALSE, FALSE, &u4BufLen); + + return 0; +} /* wext_get_ap */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set mlme operation request. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prData Pointer of iw_point header. +* \param[in] pcExtra Pointer to iw_mlme structure mlme request information. +* +* \retval 0 For success. +* \retval -EOPNOTSUPP unsupported IW_MLME_ command. +* \retval -EINVAL Set MLME Fail, different bssid. +* +* \note Driver will start mlme operation if valid. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_set_mlme(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, IN struct iw_point *prData, IN char *pcExtra) +{ + struct iw_mlme *prMlme = NULL; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(pcExtra); + if (GLUE_CHK_PR2(prNetDev, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + prMlme = (struct iw_mlme *)pcExtra; + if (prMlme->cmd == IW_MLME_DEAUTH || prMlme->cmd == IW_MLME_DISASSOC) { + if (!netif_carrier_ok(prNetDev)) { + DBGLOG(REQ, WARN, "[wifi] Set MLME Deauth/Disassoc, but netif_carrier_off\n"); + return 0; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, NULL, 0, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + return 0; + } + DBGLOG(REQ, WARN, "[wifi] unsupported IW_MLME_ command :%d\n", prMlme->cmd); + return -EOPNOTSUPP; + +} /* wext_set_mlme */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To issue scan request. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prData NULL. +* \param[in] pcExtra NULL. +* +* \retval 0 For success. +* \retval -EFAULT Tx power is off. +* +* \note Device will start scanning. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_set_scan(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, IN struct iw_scan_req *prIwScanReq, 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 (GLUE_CHK_DEV(prNetDev) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + +#if WIRELESS_EXT > 17 + /* retrieve SSID */ + if (prIwScanReq) + essid_len = prIwScanReq->essid_len; +#endif + DBGLOG(REQ, INFO, "[wifi]essid_len=%d\n", essid_len); + + 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 (GLUE_CHK_PR3(prNetDev, prData, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* Initialize local variables */ + pcCur = pcExtra; + pcValidEntryEnd = pcExtra; + pcEnd = pcExtra + prData->length; /* end of extra buffer */ + + /* Allocate another query buffer with the same size of extra buffer */ + u4AllocBufLen = prData->length; + prList = kalMemAlloc(u4AllocBufLen, VIR_MEM_TYPE); + if (prList == NULL) { + DBGLOG(REQ, ERROR, "[wifi] no memory for scan list:%d\n", prData->length); + ret = -ENOMEM; + goto error; + } + prList->u4NumberOfItems = 0; + + /* wait scan done */ + /* printk ("wait for scan results\n"); */ + /* wait_for_completion_interruptible_timeout(&prGlueInfo->rScanComp, 4 * KAL_HZ); */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryBssidList, prList, u4AllocBufLen, TRUE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus == WLAN_STATUS_INVALID_LENGTH) { + /* Buffer length is not large enough. */ + /* printk(KERN_INFO "[wifi] buf:%d result:%ld\n", pData->length, u4BufLen); */ + +#if WIRELESS_EXT >= 17 + /* + * This feature is supported in WE-17 or above, limited by iwlist. + * Return -E2BIG and iwlist will request again with a larger buffer. + */ + ret = -E2BIG; + /* Update length to give application a hint on result length */ + prData->length = (__u16) u4BufLen; + goto error; +#else + /* + * Realloc a larger query buffer here, but don't write too much to extra + * buffer when filling it later. + */ + kalMemFree(prList, VIR_MEM_TYPE, u4AllocBufLen); + + u4AllocBufLen = u4BufLen; + prList = kalMemAlloc(u4AllocBufLen, VIR_MEM_TYPE); + if (prList == NULL) { + DBGLOG(REQ, ERROR, "[wifi] no memory for larger scan list :%u\n", u4BufLen); + ret = -ENOMEM; + goto error; + } + prList->NumberOfItems = 0; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryBssidList, prList, u4AllocBufLen, TRUE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus == WLAN_STATUS_INVALID_LENGTH) { + DBGLOG(REQ, ERROR, "[wifi] larger buf:%u result:%u\n", u4AllocBufLen, u4BufLen); + ret = -E2BIG; + prData->length = (__u16) u4BufLen; + goto error; + } +#endif /* WIRELESS_EXT >= 17 */ + + } + + if (prList->u4NumberOfItems > CFG_MAX_NUM_BSS_LIST) { + DBGLOG(REQ, WARN, "[wifi] strange scan result count:%u\n", prList->u4NumberOfItems); + goto error; + } + + /* Copy required data from pList to pcExtra */ + prBss = &prList->arBssid[0]; /* set to the first entry */ + for (i = 0; i < prList->u4NumberOfItems; ++i) { + /* BSSID */ + iwEvent.cmd = SIOCGIWAP; + iwEvent.len = IW_EV_ADDR_LEN; + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.ap_addr.sa_family = ARPHRD_ETHER; + ether_addr_copy(iwEvent.u.ap_addr.sa_data, prBss->arMacAddress); + memcpy(pcCur, &iwEvent, IW_EV_ADDR_LEN); + pcCur += IW_EV_ADDR_LEN; + + /* SSID */ + iwEvent.cmd = SIOCGIWESSID; + /* Modification to user space pointer(essid.pointer) is not needed. */ + iwEvent.u.essid.length = (__u16) prBss->rSsid.u4SsidLen; + iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.essid.length; + + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.essid.flags = 1; + iwEvent.u.essid.pointer = NULL; + +#if WIRELESS_EXT <= 18 + memcpy(pcCur, &iwEvent, iwEvent.len); +#else + memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); + memcpy(pcCur + IW_EV_LCP_LEN, &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF); +#endif + memcpy(pcCur + IW_EV_POINT_LEN, prBss->rSsid.aucSsid, iwEvent.u.essid.length); + pcCur += iwEvent.len; + /* Frequency */ + iwEvent.cmd = SIOCGIWFREQ; + iwEvent.len = IW_EV_FREQ_LEN; + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.freq.m = prBss->rConfiguration.u4DSConfig; + iwEvent.u.freq.e = 3; /* (in KHz) */ + iwEvent.u.freq.i = 0; + memcpy(pcCur, &iwEvent, IW_EV_FREQ_LEN); + pcCur += IW_EV_FREQ_LEN; + + /* Operation Mode */ + iwEvent.cmd = SIOCGIWMODE; + iwEvent.len = IW_EV_UINT_LEN; + if ((pcCur + iwEvent.len) > pcEnd) + break; + if (prBss->eOpMode == NET_TYPE_IBSS) + iwEvent.u.mode = IW_MODE_ADHOC; + else if (prBss->eOpMode == NET_TYPE_INFRA) + iwEvent.u.mode = IW_MODE_INFRA; + else + iwEvent.u.mode = IW_MODE_AUTO; + memcpy(pcCur, &iwEvent, IW_EV_UINT_LEN); + pcCur += IW_EV_UINT_LEN; + + /* Quality */ + iwEvent.cmd = IWEVQUAL; + iwEvent.len = IW_EV_QUAL_LEN; + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.qual.qual = 0; /* Quality not available now */ + /* -100 < Rssi < -10, normalized by adding 0x100 */ + iwEvent.u.qual.level = 0x100 + prBss->rRssi; + iwEvent.u.qual.noise = 0; /* Noise not available now */ + iwEvent.u.qual.updated = IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID; + memcpy(pcCur, &iwEvent, IW_EV_QUAL_LEN); + pcCur += IW_EV_QUAL_LEN; + + /* Security Mode */ + iwEvent.cmd = SIOCGIWENCODE; + iwEvent.len = IW_EV_POINT_LEN; + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.data.pointer = NULL; + iwEvent.u.data.flags = 0; + iwEvent.u.data.length = 0; + if (!prBss->u4Privacy) + iwEvent.u.data.flags |= IW_ENCODE_DISABLED; +#if WIRELESS_EXT <= 18 + memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN); +#else + memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); + memcpy(pcCur + IW_EV_LCP_LEN, &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF); +#endif + pcCur += IW_EV_POINT_LEN; + + /* rearrange rate information */ + u4BufIndex = sprintf(aucRatesBuf, "Rates (Mb/s):"); + u4HighestRate = 0; + for (j = 0; j < PARAM_MAX_LEN_RATES_EX; ++j) { + UINT_8 curRate = prBss->rSupportedRates[j] & 0x7F; + + if (curRate == 0) + break; + + if (curRate > u4HighestRate) + u4HighestRate = curRate; + + if (curRate == RATE_5_5M) + u4BufIndex += sprintf(aucRatesBuf + u4BufIndex, " 5.5"); + else + u4BufIndex += sprintf(aucRatesBuf + u4BufIndex, " %d", curRate / 2); +#if DBG + if (u4BufIndex > sizeof(aucRatesBuf)) { + /* printk("rate info too long\n"); */ + break; + } +#endif + } + /* Report Highest Rates */ + iwEvent.cmd = SIOCGIWRATE; + iwEvent.len = IW_EV_PARAM_LEN; + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.bitrate.value = u4HighestRate * 500000; + iwEvent.u.bitrate.fixed = 0; + iwEvent.u.bitrate.disabled = 0; + iwEvent.u.bitrate.flags = 0; + memcpy(pcCur, &iwEvent, iwEvent.len); + pcCur += iwEvent.len; + +#if WIRELESS_EXT >= 15 /* IWEVCUSTOM is available in WE-15 or above */ + /* Report Residual Rates */ + iwEvent.cmd = IWEVCUSTOM; + iwEvent.u.data.length = u4BufIndex; + iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length; + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.data.flags = 0; +#if WIRELESS_EXT <= 18 + memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN); +#else + memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); + memcpy(pcCur + IW_EV_LCP_LEN, &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF); +#endif + memcpy(pcCur + IW_EV_POINT_LEN, aucRatesBuf, u4BufIndex); + pcCur += iwEvent.len; +#endif /* WIRELESS_EXT >= 15 */ + + if (wextSrchDesiredWPAIE(&prBss->aucIEs[sizeof(PARAM_FIXED_IEs)], + prBss->u4IELength - sizeof(PARAM_FIXED_IEs), + 0xDD, (PUINT_8 *) &prDesiredIE)) { + iwEvent.cmd = IWEVGENIE; + iwEvent.u.data.flags = 1; + iwEvent.u.data.length = 2 + (__u16) prDesiredIE->ucLength; + iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length; + if ((pcCur + iwEvent.len) > pcEnd) + break; +#if WIRELESS_EXT <= 18 + memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN); +#else + memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); + memcpy(pcCur + IW_EV_LCP_LEN, + &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF); +#endif + memcpy(pcCur + IW_EV_POINT_LEN, prDesiredIE, 2 + prDesiredIE->ucLength); + pcCur += iwEvent.len; + } +#if CFG_SUPPORT_WPS /* search WPS IE (0xDD, 221, OUI: 0x0050f204 ) */ + if (wextSrchDesiredWPSIE(&prBss->aucIEs[sizeof(PARAM_FIXED_IEs)], + prBss->u4IELength - sizeof(PARAM_FIXED_IEs), + 0xDD, (PUINT_8 *) &prDesiredIE)) { + iwEvent.cmd = IWEVGENIE; + iwEvent.u.data.flags = 1; + iwEvent.u.data.length = 2 + (__u16) prDesiredIE->ucLength; + iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length; + if ((pcCur + iwEvent.len) > pcEnd) + break; +#if WIRELESS_EXT <= 18 + memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN); +#else + memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); + memcpy(pcCur + IW_EV_LCP_LEN, + &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF); +#endif + memcpy(pcCur + IW_EV_POINT_LEN, prDesiredIE, 2 + prDesiredIE->ucLength); + pcCur += iwEvent.len; + } +#endif + + /* Search RSN IE (0x30, 48). pBss->IEs starts from timestamp. */ + /* pBss->IEs starts from timestamp */ + if (wextSrchDesiredWPAIE(&prBss->aucIEs[sizeof(PARAM_FIXED_IEs)], + prBss->u4IELength - sizeof(PARAM_FIXED_IEs), + 0x30, (PUINT_8 *) &prDesiredIE)) { + + iwEvent.cmd = IWEVGENIE; + iwEvent.u.data.flags = 1; + iwEvent.u.data.length = 2 + (__u16) prDesiredIE->ucLength; + iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length; + if ((pcCur + iwEvent.len) > pcEnd) + break; +#if WIRELESS_EXT <= 18 + memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN); +#else + memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); + memcpy(pcCur + IW_EV_LCP_LEN, + &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF); +#endif + memcpy(pcCur + IW_EV_POINT_LEN, prDesiredIE, 2 + prDesiredIE->ucLength); + pcCur += iwEvent.len; + } +#if CFG_SUPPORT_WAPI /* Android+ */ + if (wextSrchDesiredWAPIIE(&prBss->aucIEs[sizeof(PARAM_FIXED_IEs)], + prBss->u4IELength - sizeof(PARAM_FIXED_IEs), (PUINT_8 *) &prDesiredIE)) { + +#if 0 + iwEvent.cmd = IWEVGENIE; + iwEvent.u.data.flags = 1; + iwEvent.u.data.length = 2 + (__u16) prDesiredIE->ucLength; + iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length; + if ((pcCur + iwEvent.len) > pcEnd) + break; +#if WIRELESS_EXT <= 18 + memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN); +#else + memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); + memcpy(pcCur + IW_EV_LCP_LEN, + &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF); +#endif + memcpy(pcCur + IW_EV_POINT_LEN, prDesiredIE, 2 + prDesiredIE->ucLength); + pcCur += iwEvent.len; +#else + iwEvent.cmd = IWEVCUSTOM; + iwEvent.u.data.length = (2 + prDesiredIE->ucLength) * 2 + 8 /* wapi_ie= */; + iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length; + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.data.flags = 1; + + memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); + memcpy(pcCur + IW_EV_LCP_LEN, + &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF); + + pcCur += (IW_EV_POINT_LEN); + + pcCur += sprintf(pcCur, "wapi_ie="); + + snprintf_hex(pcCur, pcEnd - pcCur, (UINT_8 *) prDesiredIE, prDesiredIE->ucLength + 2); + + pcCur += (2 + prDesiredIE->ucLength) * 2 /* iwEvent.len */; +#endif + } +#endif + /* Complete an entry. Update end of valid entry */ + pcValidEntryEnd = pcCur; + /* Extract next bss */ + prBss = (P_PARAM_BSSID_EX_T) ((char *)prBss + prBss->u4Length); + } + + /* + * Update valid data length for caller function and upper layer + * applications. + */ + prData->length = (pcValidEntryEnd - pcExtra); + /* printk(KERN_INFO "[wifi] buf:%d result:%ld\n", pData->length, u4BufLen); */ + + /* kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_SCAN_COMPLETE, NULL, 0); */ + +error: + /* free local query buffer */ + if (prList) + kalMemFree(prList, VIR_MEM_TYPE, u4AllocBufLen); + + return ret; +} /* wext_get_scan */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set desired network name ESSID. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prEssid Pointer of iw_point header. +* \param[in] pcExtra Pointer to buffer srtoring essid string. +* +* \retval 0 If netif_carrier_ok. +* \retval -E2BIG Essid string length is too big. +* \retval -EINVAL pcExtra is null pointer. +* \retval -EFAULT Driver fail to set new essid. +* +* \note If string length is ok, device will try connecting to the new network. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_set_essid(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, IN struct iw_point *prEssid, IN char *pcExtra) +{ + PARAM_SSID_T rNewSsid; + UINT_32 cipher; + ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus; + ENUM_PARAM_AUTH_MODE_T eAuthMode; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prEssid); + ASSERT(pcExtra); + if (GLUE_CHK_PR3(prNetDev, prEssid, pcExtra) == FALSE) + 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); + + kalMemZero(&rNewSsid, sizeof(PARAM_SSID_T)); +#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 + + kalMemSet(rNewSsid.aucSsid, '\0', sizeof(rNewSsid.aucSsid)); + if (rNewSsid.u4SsidLen > sizeof(rNewSsid.aucSsid) - 1) + rNewSsid.u4SsidLen = sizeof(rNewSsid.aucSsid) - 1; + + kalMemCopy(rNewSsid.aucSsid, pcExtra, rNewSsid.u4SsidLen); + + DBGLOG(REQ, INFO, "wlan set essid: %s, u4SsidLen=%d\n", rNewSsid.aucSsid, rNewSsid.u4SsidLen); + + 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 (GLUE_CHK_PR3(prNetDev, prEssid, pcExtra) == FALSE) + 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 rStatus; +} /* 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 (GLUE_CHK_PR2(prNetDev, prRate) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* + * printk("value = %d, fixed = %d, disable = %d, flags = %d\n", + * prRate->value, prRate->fixed, prRate->disabled, prRate->flags); + */ + + rStatus = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQuerySupportedRates, &aucSuppRate, sizeof(aucSuppRate), &u4BufLen); + + /* Case: AUTO */ + if (prRate->value < 0) { + if (prRate->fixed == 0) { + /* iwconfig wlan0 rate auto */ + + /* set full supported rate to device */ + /* printk("wlanoidQuerySupportedRates():u4BufLen = %ld\n", u4BufLen); */ + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetDesiredRates, + &aucSuppRate, sizeof(aucSuppRate), &u4BufLen); + return 0; + } + /* iwconfig wlan0 rate fixed */ + + /* fix rate to what? DO NOTHING */ + return -EINVAL; + } + + aucNewRate[0] = prRate->value / 500000; /* In unit of 500k */ + + for (i = 0; i < PARAM_MAX_LEN_RATES_EX; i++) { + /* check the given value is supported */ + if (aucSuppRate[i] == 0) + break; + + if (aucNewRate[0] == aucSuppRate[i]) { + u4NewRateLen = 1; + break; + } + } + + if (u4NewRateLen == 0) { + /* the given value is not supported */ + /* return error or use given rate as upper bound? */ + return -EINVAL; + } + + if (prRate->fixed == 0) { + /* add all rates lower than desired rate */ + for (i = 0; i < PARAM_MAX_LEN_RATES_EX; ++i) { + if (aucSuppRate[i] == 0) + break; + + if (aucSuppRate[i] < aucNewRate[0]) + aucNewRate[u4NewRateLen++] = aucSuppRate[i]; + } + } + + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetDesiredRates, &aucNewRate, sizeof(aucNewRate), &u4BufLen); + return 0; +} /* wext_set_rate */ + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get current tx bit rate. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] prRate Pointer to iw_param structure to store current tx rate. +* \param[in] pcExtra NULL. +* +* \retval 0 If netif_carrier_ok. +* \retval -ENOTCONN Otherwise. +* +* \note If netif_carrier_ok, current tx rate is stored in pRate. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_rate(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, OUT struct iw_param *prRate, IN char *pcExtra) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + UINT_32 u4Rate = 0; + + ASSERT(prNetDev); + ASSERT(prRate); + if (GLUE_CHK_PR2(prNetDev, prRate) == FALSE) + 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 (GLUE_CHK_PR2(prNetDev, prRts) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (prRts->disabled == 1) + u4RtsThresh = 2347; + else if (prRts->value < 0 || prRts->value > 2347) + return -EINVAL; + + u4RtsThresh = (PARAM_RTS_THRESHOLD) prRts->value; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRtsThreshold, + &u4RtsThresh, sizeof(u4RtsThresh), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + prRts->value = (typeof(prRts->value)) u4RtsThresh; + prRts->disabled = (prRts->value > 2347) ? 1 : 0; + prRts->fixed = 1; + + return 0; +} /* wext_set_rts */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get RTS/CTS theshold. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] prRts Pointer to iw_param structure containing rts threshold. +* \param[in] pcExtra NULL. +* +* \retval 0 Success. +* +* \note RTS threshold is stored in pRts. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_rts(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, OUT struct iw_param *prRts, IN char *pcExtra) +{ + PARAM_RTS_THRESHOLD u4RtsThresh = 0; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prRts); + if (GLUE_CHK_PR2(prNetDev, prRts) == FALSE) + 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 (GLUE_CHK_PR2(prNetDev, prTxPow) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (prTxPow->disabled) { + /* <1> disconnect */ + rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, NULL, 0, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, ERROR, "######set disassoc failed\n"); + else + DBGLOG(REQ, TRACE, "######set assoc ok\n"); + /* <2> mark to power state flag */ + ePowerState = ACPI_STATE_D0; + DBGLOG(REQ, INFO, "set to acpi d3(0)\n"); + wlanSetAcpiState(prGlueInfo->prAdapter, ePowerState); + + } else { + ePowerState = ACPI_STATE_D0; + DBGLOG(REQ, INFO, "set to acpi d0\n"); + wlanSetAcpiState(prGlueInfo->prAdapter, ePowerState); + } + + 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 (GLUE_CHK_PR2(prNetDev, prTxPow) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* + * GeorgeKuo: wlanoidQueryAcpiDevicePowerState() reports capability, not + * current state. Use GLUE_INFO_T to store state. + */ + /* ePowerState = prGlueInfo->ePowerState; */ + + /* TxPow parameters: Fixed at relative 100% */ +#if WIRELESS_EXT < 17 + prTxPow->flags = 0x0002; /* IW_TXPOW_RELATIVE */ +#else + prTxPow->flags = IW_TXPOW_RELATIVE; +#endif + prTxPow->value = 100; + prTxPow->fixed = 1; + /* prTxPow->disabled = (ePowerState != ParamDeviceStateD3) ? FALSE : TRUE; */ + prTxPow->disabled = TRUE; + + return 0; +} /* wext_get_txpow */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get encryption cipher and key. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] prEnc Pointer to iw_point structure containing securiry information. +* \param[in] pcExtra Buffer to store key content. +* +* \retval 0 Success. +* +* \note Securiry information is stored in pEnc except key content. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_encode(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, OUT struct iw_point *prEnc, IN char *pcExtra) +{ +#if 1 + /* ENUM_ENCRYPTION_STATUS_T eEncMode; */ + ENUM_PARAM_ENCRYPTION_STATUS_T eEncMode = ENUM_WEP_ENABLED; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prEnc); + if (GLUE_CHK_PR2(prNetDev, prEnc) == FALSE) + 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 (GLUE_CHK_PR3(prNetDev, prEnc, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* reset to default mode */ + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + prGlueInfo->rWpaInfo.u4KeyMgmt = 0; + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; +#if CFG_SUPPORT_802_11W + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; +#endif + + /* iwconfig wlan0 key off */ + if ((prEnc->flags & IW_ENCODE_MODE) == IW_ENCODE_DISABLED) { + eAuthMode = AUTH_MODE_OPEN; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAuthMode, + &eAuthMode, sizeof(eAuthMode), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + eEncStatus = ENUM_ENCRYPTION_DISABLED; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEncryptionStatus, + &eEncStatus, sizeof(eEncStatus), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + return 0; + } + + /* iwconfig wlan0 key 0123456789 */ + /* iwconfig wlan0 key s:abcde */ + /* iwconfig wlan0 key 0123456789 [1] */ + /* iwconfig wlan0 key 01234567890123456789012345 [1] */ + /* check key size for WEP */ + if (prEnc->length == 5 || prEnc->length == 13 || prEnc->length == 16) { + /* prepare PARAM_WEP key structure */ + prWepKey->u4KeyIndex = (prEnc->flags & IW_ENCODE_INDEX) ? (prEnc->flags & IW_ENCODE_INDEX) - 1 : 0; + if (prWepKey->u4KeyIndex > 3) { + /* key id is out of range */ + return -EINVAL; + } + prWepKey->u4KeyIndex |= 0x80000000; + prWepKey->u4Length = 12 + prEnc->length; + prWepKey->u4KeyLength = prEnc->length; + kalMemCopy(prWepKey->aucKeyMaterial, pcExtra, prEnc->length); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAddWep, + prWepKey, prWepKey->u4Length, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "wlanoidSetAddWep fail 0x%x\n", rStatus); + return -EFAULT; + } + + /* change to auto switch */ + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_SHARED_KEY | IW_AUTH_ALG_OPEN_SYSTEM; + eAuthMode = AUTH_MODE_AUTO_SWITCH; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAuthMode, + &eAuthMode, sizeof(eAuthMode), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + /* printk(KERN_INFO DRV_NAME"wlanoidSetAuthMode fail 0x%lx\n", rStatus); */ + return -EFAULT; + } + + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40; + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40; + + eEncStatus = ENUM_WEP_ENABLED; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEncryptionStatus, + &eEncStatus, + sizeof(ENUM_PARAM_ENCRYPTION_STATUS_T), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + /* printk(KERN_INFO DRV_NAME"wlanoidSetEncryptionStatus fail 0x%lx\n", rStatus); */ + return -EFAULT; + } + + return 0; + } +#endif + return -EOPNOTSUPP; +} /* wext_set_encode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set power management. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prPower Pointer to iw_param structure containing tx power setting. +* \param[in] pcExtra NULL. +* +* \retval 0 Success. +* +* \note New Power Management Mode is set to driver. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_set_power(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, IN struct iw_param *prPower, IN char *pcExtra) +{ +#if 1 + + PARAM_POWER_MODE ePowerMode; + INT_32 i4PowerValue; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prPower); + if (GLUE_CHK_PR2(prNetDev, prPower) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* printk(KERN_INFO "wext_set_power value(%d) disabled(%d) flag(0x%x)\n", */ + /* prPower->value, prPower->disabled, prPower->flags); */ + + if (prPower->disabled) { + ePowerMode = Param_PowerModeCAM; + } else { + i4PowerValue = prPower->value; +#if WIRELESS_EXT < 21 + i4PowerValue /= 1000000; +#endif + if (i4PowerValue == 0) { + ePowerMode = Param_PowerModeCAM; + } else if (i4PowerValue == 1) { + ePowerMode = Param_PowerModeMAX_PSP; + } else if (i4PowerValue == 2) { + ePowerMode = Param_PowerModeFast_PSP; + } else { + DBGLOG(REQ, ERROR, "%s(): unsupported power management mode value = %d.\n", + __func__, prPower->value); + + return -EINVAL; + } + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &ePowerMode, sizeof(ePowerMode), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + /* printk(KERN_INFO DRV_NAME"wlanoidSet802dot11PowerSaveProfile fail 0x%lx\n", rStatus); */ + return -EFAULT; + } +#endif + return 0; +} /* wext_set_power */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get power management. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] prPower Pointer to iw_param structure containing tx power setting. +* \param[in] pcExtra NULL. +* +* \retval 0 Success. +* +* \note Power management mode is stored in pTxPow->value. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_power(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, OUT struct iw_param *prPower, IN char *pcExtra) +{ + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + PARAM_POWER_MODE ePowerMode = Param_PowerModeCAM; + + ASSERT(prNetDev); + ASSERT(prPower); + if (GLUE_CHK_PR2(prNetDev, prPower) == FALSE) + 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 (GLUE_CHK_PR2(prNetDev, prAuth) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* Save information to glue info and process later when ssid is set. */ + switch (prAuth->flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: +#if CFG_SUPPORT_WAPI + if (wlanQueryWapiMode(prGlueInfo->prAdapter)) { + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; + } else { + prGlueInfo->rWpaInfo.u4WpaVersion = prAuth->value; + } +#else + prGlueInfo->rWpaInfo.u4WpaVersion = prAuth->value; +#endif + break; + + case IW_AUTH_CIPHER_PAIRWISE: + prGlueInfo->rWpaInfo.u4CipherPairwise = prAuth->value; + break; + + case IW_AUTH_CIPHER_GROUP: + prGlueInfo->rWpaInfo.u4CipherGroup = prAuth->value; + break; + + case IW_AUTH_KEY_MGMT: + prGlueInfo->rWpaInfo.u4KeyMgmt = prAuth->value; +#if CFG_SUPPORT_WAPI + if (prGlueInfo->rWpaInfo.u4KeyMgmt == IW_AUTH_KEY_MGMT_WAPI_PSK || + prGlueInfo->rWpaInfo.u4KeyMgmt == IW_AUTH_KEY_MGMT_WAPI_CERT) { + UINT_32 u4BufLen; + WLAN_STATUS rStatus; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetWapiMode, + &prAuth->value, sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + DBGLOG(REQ, INFO, "IW_AUTH_WAPI_ENABLED :%d\n", prAuth->value); + } +#endif + if (prGlueInfo->rWpaInfo.u4KeyMgmt == IW_AUTH_KEY_MGMT_WPS) + prGlueInfo->fgWpsActive = TRUE; + else + prGlueInfo->fgWpsActive = FALSE; + break; + + case IW_AUTH_80211_AUTH_ALG: + prGlueInfo->rWpaInfo.u4AuthAlg = prAuth->value; + break; + + case IW_AUTH_PRIVACY_INVOKED: + prGlueInfo->rWpaInfo.fgPrivacyInvoke = prAuth->value; + break; +#if CFG_SUPPORT_802_11W + case IW_AUTH_MFP: + /* printk("wext_set_auth IW_AUTH_MFP=%d\n", prAuth->value); */ + prGlueInfo->rWpaInfo.u4Mfp = prAuth->value; + break; +#endif +#if CFG_SUPPORT_WAPI + case IW_AUTH_WAPI_ENABLED: + { + UINT_32 u4BufLen; + WLAN_STATUS rStatus; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetWapiMode, + &prAuth->value, sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + } + DBGLOG(REQ, INFO, "IW_AUTH_WAPI_ENABLED :%d\n", prAuth->value); + break; +#endif + default: + /* + * printk(KERN_INFO "[wifi] unsupported IW_AUTH_INDEX :%d\n", prAuth->flags); + */ + break; + } + return 0; +} /* wext_set_auth */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set encryption cipher and key. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prEnc Pointer to iw_point structure containing securiry information. +* \param[in] pcExtra Pointer to key string buffer. +* +* \retval 0 Success. +* \retval -EINVAL Key ID error for WEP. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note Securiry information is stored in pEnc. +*/ +/*----------------------------------------------------------------------------*/ +#if CFG_SUPPORT_WAPI +UINT_8 keyStructBuf[320]; /* add/remove key shared buffer */ +#else +UINT_8 keyStructBuf[100]; /* add/remove key shared buffer */ +#endif + +static int +wext_set_encode_ext(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, IN struct iw_point *prEnc, IN char *pcExtra) +{ + P_PARAM_REMOVE_KEY_T prRemoveKey = (P_PARAM_REMOVE_KEY_T) keyStructBuf; + P_PARAM_KEY_T prKey = (P_PARAM_KEY_T) keyStructBuf; + + P_PARAM_WEP_T prWepKey = (P_PARAM_WEP_T) wepBuf; + + struct iw_encode_ext *prIWEncExt = (struct iw_encode_ext *)pcExtra; + + ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus; + ENUM_PARAM_AUTH_MODE_T eAuthMode; + /* ENUM_PARAM_OP_MODE_T eOpMode = NET_TYPE_AUTO_SWITCH; */ + +#if CFG_SUPPORT_WAPI + P_PARAM_WPI_KEY_T prWpiKey = (P_PARAM_WPI_KEY_T) keyStructBuf; +#endif + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prEnc); + if (GLUE_CHK_PR3(prNetDev, prEnc, pcExtra) == FALSE) + return -EINVAL; + + if (prIWEncExt == NULL) { + DBGLOG(REQ, ERROR, "prIWEncExt is NULL!\n"); + return -EINVAL; + } + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memset(keyStructBuf, 0, sizeof(keyStructBuf)); + +#if CFG_SUPPORT_WAPI + if (prIWEncExt->alg == IW_ENCODE_ALG_SMS4) { + if (prEnc->flags & IW_ENCODE_DISABLED) { + /* printk(KERN_INFO "[wapi] IW_ENCODE_DISABLED\n"); */ + return 0; + } + /* KeyID */ + prWpiKey->ucKeyID = (prEnc->flags & IW_ENCODE_INDEX); + prWpiKey->ucKeyID--; + if (prWpiKey->ucKeyID > 1) { + /* key id is out of range */ + /* printk(KERN_INFO "[wapi] add key error: key_id invalid %d\n", prWpiKey->ucKeyID); */ + return -EINVAL; + } + + if (prIWEncExt->key_len != 32) { + /* key length not valid */ + /* printk(KERN_INFO "[wapi] add key error: key_len invalid %d\n", prIWEncExt->key_len); */ + return -EINVAL; + } + /* printk(KERN_INFO "[wapi] %d ext_flags %d\n", prEnc->flags, prIWEncExt->ext_flags); */ + + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + prWpiKey->eKeyType = ENUM_WPI_GROUP_KEY; + prWpiKey->eDirection = ENUM_WPI_RX; + } else if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { + prWpiKey->eKeyType = ENUM_WPI_PAIRWISE_KEY; + prWpiKey->eDirection = ENUM_WPI_RX_TX; + } + + /* PN */ + { + UINT_32 i; + + for (i = 0; i < IW_ENCODE_SEQ_MAX_SIZE; i++) + prWpiKey->aucPN[i] = prIWEncExt->tx_seq[i]; + for (i = 0; i < IW_ENCODE_SEQ_MAX_SIZE; i++) + prWpiKey->aucPN[IW_ENCODE_SEQ_MAX_SIZE + i] = prIWEncExt->rx_seq[i]; + } + + /* BSSID */ + memcpy(prWpiKey->aucAddrIndex, prIWEncExt->addr.sa_data, 6); + + memcpy(prWpiKey->aucWPIEK, prIWEncExt->key, 16); + prWpiKey->u4LenWPIEK = 16; + + memcpy(prWpiKey->aucWPICK, &prIWEncExt->key[16], 16); + prWpiKey->u4LenWPICK = 16; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetWapiKey, + prWpiKey, sizeof(PARAM_WPI_KEY_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + /* Do nothing */ + /* printk(KERN_INFO "[wapi] add key error:%lx\n", rStatus); */ + } + } else +#endif + { + + if ((prEnc->flags & IW_ENCODE_MODE) == IW_ENCODE_DISABLED) { + prRemoveKey->u4Length = sizeof(*prRemoveKey); + memcpy(prRemoveKey->arBSSID, prIWEncExt->addr.sa_data, 6); + /* + * printk("IW_ENCODE_DISABLED: ID:%d, Addr:[ %pM ]\n", + * prRemoveKey->KeyIndex, prRemoveKey->BSSID); + */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRemoveKey, + prRemoveKey, prRemoveKey->u4Length, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, INFO, "remove key error:%x\n", rStatus); + return 0; + } + /* return 0; */ + /* printk ("alg %x\n", prIWEncExt->alg); */ + + switch (prIWEncExt->alg) { + case IW_ENCODE_ALG_NONE: + break; + case IW_ENCODE_ALG_WEP: + /* iwconfig wlan0 key 0123456789 */ + /* iwconfig wlan0 key s:abcde */ + /* iwconfig wlan0 key 0123456789 [1] */ + /* iwconfig wlan0 key 01234567890123456789012345 [1] */ + /* check key size for WEP */ + if (prIWEncExt->key_len == 5 || prIWEncExt->key_len == 13 || prIWEncExt->key_len == 16) { + /* prepare PARAM_WEP key structure */ + prWepKey->u4KeyIndex = (prEnc->flags & IW_ENCODE_INDEX) ? + (prEnc->flags & IW_ENCODE_INDEX) - 1 : 0; + if (prWepKey->u4KeyIndex > 3) { + /* key id is out of range */ + return -EINVAL; + } + prWepKey->u4KeyIndex |= 0x80000000; + prWepKey->u4Length = 12 + prIWEncExt->key_len; + prWepKey->u4KeyLength = prIWEncExt->key_len; + /* kalMemCopy(prWepKey->aucKeyMaterial, pcExtra, prIWEncExt->key_len); */ + kalMemCopy(prWepKey->aucKeyMaterial, prIWEncExt->key, prIWEncExt->key_len); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAddWep, + prWepKey, prWepKey->u4Length, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "wlanoidSetAddWep fail 0x%x\n", rStatus); + return -EFAULT; + } + + /* change to auto switch */ + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_SHARED_KEY | IW_AUTH_ALG_OPEN_SYSTEM; + eAuthMode = AUTH_MODE_AUTO_SWITCH; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAuthMode, + &eAuthMode, + sizeof(eAuthMode), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "wlanoidSetAuthMode fail 0x%x\n", rStatus); + return -EFAULT; + } + + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40; + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40; + + eEncStatus = ENUM_WEP_ENABLED; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEncryptionStatus, + &eEncStatus, + sizeof(ENUM_PARAM_ENCRYPTION_STATUS_T), + FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "wlanoidSetEncryptionStatus fail 0x%x\n", rStatus); + return -EFAULT; + } + + } else { + DBGLOG(REQ, INFO, "key length %x\n", prIWEncExt->key_len); + DBGLOG(REQ, INFO, "key error\n"); + } + + break; + case IW_ENCODE_ALG_TKIP: + case IW_ENCODE_ALG_CCMP: +#if CFG_SUPPORT_802_11W + case IW_ENCODE_ALG_AES_CMAC: +#endif + { + + /* KeyID */ + prKey->u4KeyIndex = (prEnc->flags & IW_ENCODE_INDEX) ? + (prEnc->flags & IW_ENCODE_INDEX) - 1 : 0; +#if CFG_SUPPORT_802_11W + if (prKey->u4KeyIndex > 5) { +#else + if (prKey->u4KeyIndex > 3) { +#endif + DBGLOG(REQ, ERROR, "key index error:0x%x\n", prKey->u4KeyIndex); + /* key id is out of range */ + return -EINVAL; + } + + /* bit(31) and bit(30) are shared by pKey and pRemoveKey */ + /* Tx Key Bit(31) */ + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { + prKey->u4KeyIndex |= 0x1UL << 31; + /* Code style */ + } + /* Pairwise Key Bit(30) */ + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + /* Do nothing */ + /* group key */ + } else { + /* pairwise key */ + prKey->u4KeyIndex |= 0x1UL << 30; + } + } + /* Rx SC Bit(29) */ + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { + prKey->u4KeyIndex |= 0x1UL << 29; + memcpy(&prKey->rKeyRSC, prIWEncExt->rx_seq, IW_ENCODE_SEQ_MAX_SIZE); + } + + /* BSSID */ + memcpy(prKey->arBSSID, prIWEncExt->addr.sa_data, 6); + + /* switch tx/rx MIC key for sta */ + if (prIWEncExt->alg == IW_ENCODE_ALG_TKIP && prIWEncExt->key_len == 32) { + memcpy(prKey->aucKeyMaterial, prIWEncExt->key, 16); + memcpy(((PUINT_8) prKey->aucKeyMaterial) + 16, prIWEncExt->key + 24, 8); + memcpy((prKey->aucKeyMaterial) + 24, prIWEncExt->key + 16, 8); + } else { + if (prIWEncExt->key_len > sizeof(prKey->aucKeyMaterial)) { + DBGLOG(REQ, ERROR, "prIWEncExt->key_len: %u is too long!\n", + prIWEncExt->key_len); + return -EINVAL; + } + memcpy(prKey->aucKeyMaterial, prIWEncExt->key, prIWEncExt->key_len); + } + + prKey->u4KeyLength = prIWEncExt->key_len; + prKey->u4Length = ((ULONG)&(((P_PARAM_KEY_T) 0)->aucKeyMaterial)) + prKey->u4KeyLength; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAddKey, + prKey, prKey->u4Length, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "add key error:%x\n", rStatus); + return -EFAULT; + } + break; + } + } + + return 0; +} /* wext_set_encode_ext */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set country code +* +* \param[in] prNetDev Net device requested. +* \param[in] prData iwreq.u.data carries country code value. +* +* \retval 0 For success. +* \retval -EEFAULT For fail. +* +* \note Country code is stored and channel list is updated based on current country domain. +*/ +/*----------------------------------------------------------------------------*/ +static int wext_set_country(IN struct net_device *prNetDev, IN struct iw_point *prData) +{ + P_GLUE_INFO_T prGlueInfo; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + UINT_8 aucCountry[COUNTRY_CODE_LEN]; + + ASSERT(prNetDev); + + /* + * prData->pointer should be like "COUNTRY US", "COUNTRY EU" + * and "COUNTRY JP" + */ + if (GLUE_CHK_PR2(prNetDev, prData) == FALSE || !prData->pointer || prData->length < COUNTRY_CODE_LEN) + return -EINVAL; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (copy_from_user(aucCountry, prData->pointer, COUNTRY_CODE_LEN)) + return -EFAULT; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetCountryCode, + &aucCountry[COUNTRY_CODE_LEN - 2], 2, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "Set country code error: %x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +#if CFG_TC1_FEATURE /* for Passive Scan */ +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set passive scan +* +* \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_passive_scan(IN struct net_device *prNetDev, IN struct iw_point *prData) +{ + P_GLUE_INFO_T prGlueInfo; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + UINT_8 passivescan; + + ASSERT(prNetDev); + + /* prData->pointer should be like SCAN-PASSIVE or SCAN-ACTIVE*/ + if ((GLUE_CHK_PR2(prNetDev, prData) == FALSE) || + (!prData->pointer) || (prData->length < 11)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + passivescan = prData->flags; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetPassiveScan, &passivescan, 1, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + return 0; +} +#endif /* CONFIG_MTK_TC1_FEATURE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To report the iw private args table to user space. +* +* \param[in] prNetDev Net device requested. +* \param[out] prData iwreq.u.data to carry the private args table. +* +* \retval 0 For success. +* \retval -E2BIG For user's buffer size is too small. +* \retval -EFAULT For fail. +* +*/ +/*----------------------------------------------------------------------------*/ +static int wext_get_priv(IN struct net_device *prNetDev, OUT struct iw_point *prData) +{ + UINT_16 u2BufferSize = prData->length; + + /* Update our private args table size */ + prData->length = (__u16)sizeof(rIwPrivTable); + if (u2BufferSize < prData->length) + return -E2BIG; + + if (prData->length) { + if (copy_to_user(prData->pointer, rIwPrivTable, sizeof(rIwPrivTable))) + return -EFAULT; + } + + return 0; +} /* wext_get_priv */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief ioctl() (Linux Wireless Extensions) routines +* +* \param[in] prDev Net device requested. +* \param[in] ifr The ifreq structure for seeting the wireless extension. +* \param[in] i4Cmd The wireless extension ioctl command. +* +* \retval zero On success. +* \retval -EOPNOTSUPP If the cmd is not supported. +* \retval -EFAULT If copy_to_user goes wrong. +* \retval -EINVAL If any value's out of range. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int wext_support_ioctl(IN struct net_device *prDev, IN struct ifreq *prIfReq, IN int i4Cmd) +{ + struct iwreq *iwr = (struct iwreq *)prIfReq; + struct iw_request_info rIwReqInfo; + int ret = 0; + char *prExtraBuf = NULL; + UINT_32 u4ExtraSize = 0; + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + WLAN_STATUS rStatus; + UINT_32 u4BufLen; +#if (CFG_REFACTORY_PMKSA == 0) + P_PARAM_PMKID_T prPmkid; +#else + PARAM_PMKID_T pmkid; +#endif + struct iw_scan_req *prIwScanReq = NULL; + + /* printk("%d CMD:0x%x\n", jiffies_to_msecs(jiffies), i4Cmd); */ + + rIwReqInfo.cmd = (__u16) i4Cmd; + rIwReqInfo.flags = 0; + + switch (i4Cmd) { + case SIOCGIWNAME: /* 0x8B01, get wireless protocol name */ + ret = wext_get_name(prDev, &rIwReqInfo, (char *)&iwr->u.name, sizeof(iwr->u.name), NULL); + break; + + /* case SIOCSIWNWID: 0x8B02, deprecated */ + /* case SIOCGIWNWID: 0x8B03, deprecated */ + + case SIOCSIWFREQ: /* 0x8B04, set channel */ + ret = wext_set_freq(prDev, NULL, &iwr->u.freq, NULL); + break; + + case SIOCGIWFREQ: /* 0x8B05, get channel */ + ret = wext_get_freq(prDev, NULL, &iwr->u.freq, NULL); + break; + + case SIOCSIWMODE: /* 0x8B06, set operation mode */ + ret = wext_set_mode(prDev, NULL, &iwr->u.mode, NULL); + /* ret = 0; */ + break; + + case SIOCGIWMODE: /* 0x8B07, get operation mode */ + ret = wext_get_mode(prDev, NULL, &iwr->u.mode, NULL); + break; + + /* case SIOCSIWSENS: 0x8B08, unsupported */ + /* case SIOCGIWSENS: 0x8B09, unsupported */ + + /* case SIOCSIWRANGE: 0x8B0A, unused */ + case SIOCGIWRANGE: /* 0x8B0B, get range of parameters */ + if (iwr->u.data.pointer != NULL) { + /* Buffer size should be large enough */ + if (iwr->u.data.length < sizeof(struct iw_range)) { + ret = -E2BIG; + break; + } + + prExtraBuf = kalMemAlloc(sizeof(struct iw_range), VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + /* reset all fields */ + memset(prExtraBuf, 0, sizeof(struct iw_range)); + iwr->u.data.length = sizeof(struct iw_range); + + ret = wext_get_range(prDev, NULL, &iwr->u.data, prExtraBuf); + /* Push up to the caller */ + if (copy_to_user(iwr->u.data.pointer, prExtraBuf, iwr->u.data.length)) + ret = -EFAULT; + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, sizeof(struct iw_range)); + prExtraBuf = NULL; + } else { + ret = -EINVAL; + } + break; +#if CFG_TC1_FEATURE /* for Passive Scan */ + case SIOCSIWPRIV: /* 0x8B0C, flags 1 : Country, flag2 : passive scan */ + if (iwr->u.data.flags == 0x0001 || iwr->u.data.flags == 0x0000) + ret = wext_set_country(prDev, &iwr->u.data); + else if (iwr->u.data.flags == 0x0002) + ret = wext_set_passive_scan(prDev, &iwr->u.data); + else if (iwr->u.data.flags == 0x0003) + ret = wext_set_passive_scan(prDev, &iwr->u.data); + break; +#else + case SIOCSIWPRIV: /* 0x8B0C, set country code */ + ret = wext_set_country(prDev, &iwr->u.data); + break; +#endif + case SIOCGIWPRIV: /* 0x8B0D, get private args table */ + ret = wext_get_priv(prDev, &iwr->u.data); + break; + + /* case SIOCSIWSTATS: 0x8B0E, unused */ + /* + * case SIOCGIWSTATS: + * get statistics, intercepted by wireless_process_ioctl() in wireless.c, + * redirected to dev_iwstats(), dev->get_wireless_stats(). + */ + /* case SIOCSIWSPY: 0x8B10, unsupported */ + /* case SIOCGIWSPY: 0x8B11, unsupported */ + /* case SIOCSIWTHRSPY: 0x8B12, unsupported */ + /* case SIOCGIWTHRSPY: 0x8B13, unsupported */ + + case SIOCSIWAP: /* 0x8B14, set access point MAC addresses (BSSID) */ + if (iwr->u.ap_addr.sa_data[0] == 0 && + iwr->u.ap_addr.sa_data[1] == 0 && + iwr->u.ap_addr.sa_data[2] == 0 && + iwr->u.ap_addr.sa_data[3] == 0 && + iwr->u.ap_addr.sa_data[4] == 0 && iwr->u.ap_addr.sa_data[5] == 0) { + /* + * WPA Supplicant will set 000000000000 in + * wpa_driver_wext_deinit(), do nothing here or disassoc again? + */ + ret = 0; + break; + } + ret = wext_set_ap(prDev, NULL, &iwr->u.ap_addr, NULL); + + break; + + case SIOCGIWAP: /* 0x8B15, get access point MAC addresses (BSSID) */ + ret = wext_get_ap(prDev, NULL, &iwr->u.ap_addr, NULL); + break; + + case SIOCSIWMLME: /* 0x8B16, request MLME operation */ + /* Fixed length structure */ + if (iwr->u.data.length != sizeof(struct iw_mlme)) { + DBGLOG(REQ, ERROR, "MLME buffer strange:%d\n", iwr->u.data.length); + ret = -EINVAL; + break; + } + + if (!iwr->u.data.pointer) { + ret = -EINVAL; + break; + } + + prExtraBuf = kalMemAlloc(sizeof(struct iw_mlme), VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, iwr->u.data.pointer, sizeof(struct iw_mlme))) + ret = -EFAULT; + else + ret = wext_set_mlme(prDev, NULL, &(iwr->u.data), prExtraBuf); + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, sizeof(struct iw_mlme)); + prExtraBuf = NULL; + break; + + /* case SIOCGIWAPLIST: 0x8B17, deprecated */ + case SIOCSIWSCAN: /* 0x8B18, scan request */ + if (iwr->u.data.pointer == NULL) + ret = wext_set_scan(prDev, NULL, NULL, NULL); +#if WIRELESS_EXT > 17 + else if (iwr->u.data.length == sizeof(struct iw_scan_req)) { + prIwScanReq = kalMemAlloc(sizeof(struct iw_scan_req), VIR_MEM_TYPE); + if (!prIwScanReq) { + ret = -ENOMEM; + break; + } + if (copy_from_user(prIwScanReq, iwr->u.data.pointer, sizeof(struct iw_scan_req))) + ret = -EFAULT; + else { + if (prIwScanReq->essid_len > IW_ESSID_MAX_SIZE) + prIwScanReq->essid_len = IW_ESSID_MAX_SIZE; + ret = wext_set_scan(prDev, NULL, prIwScanReq, &(prIwScanReq->essid[0])); + } + + kalMemFree(prIwScanReq, VIR_MEM_TYPE, sizeof(struct iw_scan_req)); + prIwScanReq = NULL; + } +#endif + else + ret = -EINVAL; + break; +#if 1 + case SIOCGIWSCAN: /* 0x8B19, get scan results */ + if (!iwr->u.data.pointer || !iwr->u.essid.pointer) { + ret = -EINVAL; + break; + } + + u4ExtraSize = iwr->u.data.length; + /* allocate the same size of kernel buffer to store scan results. */ + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + /* iwr->u.data.length may be updated by wext_get_scan() */ + ret = wext_get_scan(prDev, NULL, &iwr->u.data, prExtraBuf); + if (ret != 0) { + if (ret == -E2BIG) + DBGLOG(REQ, WARN, "[wifi] wext_get_scan -E2BIG\n"); + } else { + /* check updated length is valid */ + ASSERT(iwr->u.data.length <= u4ExtraSize); + if (iwr->u.data.length > u4ExtraSize) { + DBGLOG(REQ, INFO, "Updated result length is larger than allocated (%d > %u)\n", + iwr->u.data.length, u4ExtraSize); + iwr->u.data.length = u4ExtraSize; + } + + if (copy_to_user(iwr->u.data.pointer, prExtraBuf, iwr->u.data.length)) + ret = -EFAULT; + } + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); + prExtraBuf = NULL; + + break; + +#endif + +#if 1 + case SIOCSIWESSID: /* 0x8B1A, set SSID (network name) */ + u4ExtraSize = iwr->u.essid.length; + if (u4ExtraSize > 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, u4ExtraSize)) { + 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 */ + u4ExtraSize = iwr->u.essid.length; + if (!iwr->u.essid.pointer) { + ret = -EINVAL; + break; + } + + if (u4ExtraSize != IW_ESSID_MAX_SIZE && u4ExtraSize != IW_ESSID_MAX_SIZE + 1) { + DBGLOG(REQ, ERROR, "[wifi] iwr->u.essid.length:%d too small\n", u4ExtraSize); + ret = -E2BIG; /* let caller try larger buffer */ + break; + } + + prExtraBuf = kalMemAlloc(IW_ESSID_MAX_SIZE + 1, 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 + 1); + 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 */ + u4ExtraSize = iwr->u.encoding.length; + if (iwr->u.encoding.pointer) { + if (u4ExtraSize > 16) { + ret = -E2BIG; + break; + } + + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, iwr->u.encoding.pointer, u4ExtraSize)) + ret = -EFAULT; + + if (ret == 0) + ret = wext_set_encode(prDev, NULL, &iwr->u.encoding, prExtraBuf); + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); + prExtraBuf = NULL; + + } else if (u4ExtraSize != 0) + ret = -EINVAL; + + break; + + case SIOCGIWENCODE: /* 0x8B2B, get encoding token & mode */ + /* check pointer */ + ret = wext_get_encode(prDev, NULL, &iwr->u.encoding, NULL); + break; + + case SIOCSIWPOWER: /* 0x8B2C, set power management */ + ret = wext_set_power(prDev, NULL, &iwr->u.power, NULL); + break; + + case SIOCGIWPOWER: /* 0x8B2D, get power management */ + ret = wext_get_power(prDev, NULL, &iwr->u.power, NULL); + break; + +#if WIRELESS_EXT > 17 + case SIOCSIWGENIE: /* 0x8B30, set gen ie */ + if (iwr->u.data.pointer == NULL) + break; + + if (0 /* wlanQueryWapiMode(prGlueInfo->prAdapter) */) + break; + + /* Fixed length structure */ + u4ExtraSize = iwr->u.data.length; + +#if CFG_SUPPORT_WAPI + if (u4ExtraSize > 42 /* The max wapi ie buffer */) { + ret = -EINVAL; + break; + } +#endif + if (u4ExtraSize == 0) + break; + + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + if (copy_from_user(prExtraBuf, iwr->u.data.pointer, u4ExtraSize)) { + ret = -EFAULT; + } else { +#if CFG_SUPPORT_WAPI + rStatus = kalIoctl(prGlueInfo, + wlanoidSetWapiAssocInfo, + prExtraBuf, + u4ExtraSize, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + /* + * printk(KERN_INFO "[wapi] set wapi assoc info error:%lx\n", + * rStatus); + */ +#endif +#if CFG_SUPPORT_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; + if (u4ExtraSize > sizeof(struct iw_encode_ext)) { + ret = -EINVAL; + break; + } + + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, iwr->u.encoding.pointer, u4ExtraSize)) + ret = -EFAULT; + } else if (iwr->u.encoding.length != 0) { + ret = -EINVAL; + break; + } + + if (ret == 0) + ret = wext_set_encode_ext(prDev, NULL, &iwr->u.encoding, prExtraBuf); + + if (prExtraBuf) { + kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); + prExtraBuf = NULL; + } + break; + + /* case SIOCGIWENCODEEXT: 0x8B35, unused? */ + + case SIOCSIWPMKSA: /* 0x8B36, pmksa cache operation */ +#if 1 + if (iwr->u.data.pointer) { + /* Fixed length structure */ + if (iwr->u.data.length != sizeof(struct iw_pmksa)) { + ret = -EINVAL; + break; + } + + u4ExtraSize = sizeof(struct iw_pmksa); + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, iwr->u.data.pointer, sizeof(struct iw_pmksa))) { + ret = -EFAULT; + } else { + switch (((struct iw_pmksa *)prExtraBuf)->cmd) { + case IW_PMKSA_ADD: + /* + * printk(KERN_INFO "IW_PMKSA_ADD [ %pM ]\n", + * (((struct iw_pmksa *)pExtraBuf)->bssid.sa_data)); + */ +#if (CFG_REFACTORY_PMKSA == 0) + prPmkid = + (P_PARAM_PMKID_T) kalMemAlloc(8 + sizeof(PARAM_BSSID_INFO_T), + VIR_MEM_TYPE); + if (!prPmkid) { + DBGLOG(REQ, ERROR, "Can not alloc memory for IW_PMKSA_ADD\n"); + ret = -ENOMEM; + break; + } + + prPmkid->u4Length = 8 + sizeof(PARAM_BSSID_INFO_T); + prPmkid->u4BSSIDInfoCount = 1; + kalMemCopy(prPmkid->arBSSIDInfo->arBSSID, + ((struct iw_pmksa *)prExtraBuf)->bssid.sa_data, 6); + kalMemCopy(prPmkid->arBSSIDInfo->arPMKID, + ((struct iw_pmksa *)prExtraBuf)->pmkid, IW_PMKID_LEN); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetPmkid, + prPmkid, + sizeof(PARAM_PMKID_T), + FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, ERROR, "add pmkid error:%x\n", rStatus); + kalMemFree(prPmkid, VIR_MEM_TYPE, 8 + sizeof(PARAM_BSSID_INFO_T)); +#else + kalMemCopy(pmkid.arBSSID, + ((struct iw_pmksa *)prExtraBuf)->bssid.sa_data, + PARAM_MAC_ADDR_LEN); + kalMemCopy(pmkid.arPMKID, + ((struct iw_pmksa *)prExtraBuf)->pmkid, IW_PMKID_LEN); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetPmkid, &pmkid, + sizeof(PARAM_PMKID_T), + FALSE, FALSE, TRUE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "add pmkid error:%x\n", rStatus); +#endif + + break; + case IW_PMKSA_REMOVE: + /* + * printk(KERN_INFO "IW_PMKSA_REMOVE [ %pM ]\n", + * (((struct iw_pmksa *)buf)->bssid.sa_data)); + */ + break; + case IW_PMKSA_FLUSH: + /* + * printk(KERN_INFO "IW_PMKSA_FLUSH\n"); + */ +#if (CFG_REFACTORY_PMKSA == 0) + prPmkid = (P_PARAM_PMKID_T) kalMemAlloc(8, VIR_MEM_TYPE); + if (!prPmkid) { + DBGLOG(REQ, ERROR, + "Can not alloc memory for IW_PMKSA_FLUSH\n"); + ret = -ENOMEM; + break; + } + + prPmkid->u4Length = 8; + prPmkid->u4BSSIDInfoCount = 0; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetPmkid, + prPmkid, + sizeof(PARAM_PMKID_T), + FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, ERROR, "flush pmkid error:%x\n", rStatus); + kalMemFree(prPmkid, VIR_MEM_TYPE, 8); +#else + rStatus = kalIoctl(prGlueInfo, wlanoidFlushPmkid, NULL, 0, + FALSE, FALSE, TRUE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "flush pmkid error:%x\n", rStatus); +#endif + + break; + default: + DBGLOG(REQ, WARN, "UNKNOWN iw_pmksa command:%d\n", + ((struct iw_pmksa *)prExtraBuf)->cmd); + ret = -EFAULT; + break; + } + } + + if (prExtraBuf) { + kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); + prExtraBuf = NULL; + } + } else if (iwr->u.data.length != 0) { + ret = -EINVAL; + break; + } +#endif + break; + +#endif + + default: + /* printk(KERN_NOTICE "unsupported IOCTL: 0x%x\n", i4Cmd); */ + ret = -EOPNOTSUPP; + break; + } + + /* printk("%ld CMD:0x%x ret:%d\n", jiffies_to_msecs(jiffies), i4Cmd, ret); */ + + return ret; +} /* wext_support_ioctl */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To send an event (RAW socket pacekt) to user process actively. +* +* \param[in] prGlueInfo Glue layer info. +* \param[in] u4cmd Which event command we want to indicate to user process. +* \param[in] pData Data buffer to be indicated. +* \param[in] dataLen Available data size in pData. +* +* \return (none) +* +* \note Event is indicated to upper layer if cmd is supported and data is valid. +* Using of kernel symbol wireless_send_event(), which is defined in +* after WE-14 (2.4.20). +*/ +/*----------------------------------------------------------------------------*/ +void +wext_indicate_wext_event(IN P_GLUE_INFO_T prGlueInfo, + IN unsigned int u4Cmd, IN unsigned char *pucData, IN unsigned int u4dataLen) +{ + union iwreq_data wrqu; + unsigned char *pucExtraInfo = NULL; +#if WIRELESS_EXT >= 15 + unsigned char *pucDesiredIE = NULL; + unsigned char aucExtraInfoBuf[200]; +#endif +#if WIRELESS_EXT < 18 + int i; +#endif + + memset(&wrqu, 0, sizeof(wrqu)); + + switch (u4Cmd) { + case SIOCGIWTXPOW: + memcpy(&wrqu.power, pucData, u4dataLen); + break; + case SIOCGIWSCAN: + complete_all(&prGlueInfo->rScanComp); + break; + + case SIOCGIWAP: + if (pucData) + ether_addr_copy((u8 *)&(wrqu.ap_addr.sa_data), pucData); + /* memcpy(&wrqu.ap_addr.sa_data, pucData, ETH_ALEN); */ + else + /* memset(&wrqu.ap_addr.sa_data, 0, ETH_ALEN); */ + eth_zero_addr((u8 *)&wrqu.ap_addr.sa_data); + break; + + case IWEVASSOCREQIE: +#if WIRELESS_EXT < 15 + /* under WE-15, no suitable Event can be used */ + goto skip_indicate_event; +#else + /* do supplicant a favor, parse to the start of WPA/RSN IE */ + if (wextSrchDesiredWPAIE(pucData, u4dataLen, 0x30, &pucDesiredIE)) { + /* RSN IE found */ + /* Do nothing */ +#if 0 + } else if (wextSrchDesiredWPSIE(pucData, u4dataLen, 0xDD, &pucDesiredIE)) { + /* WPS IE found */ + /* Do nothing */ +#endif + } else if (wextSrchDesiredWPAIE(pucData, u4dataLen, 0xDD, &pucDesiredIE)) { + /* WPA IE found */ + /* Do nothing*/ +#if CFG_SUPPORT_WAPI /* Android+ */ + } else if (wextSrchDesiredWAPIIE(pucData, u4dataLen, &pucDesiredIE)) { + /* WAPI IE found */ + /* printk("wextSrchDesiredWAPIIE!!\n"); */ +#endif + } else { + /* no WPA/RSN IE found, skip this event */ + goto skip_indicate_event; + } +#if WIRELESS_EXT < 18 + /* under WE-18, only IWEVCUSTOM can be used */ + u4Cmd = IWEVCUSTOM; + pucExtraInfo = aucExtraInfoBuf; + pucExtraInfo += sprintf(pucExtraInfo, "ASSOCINFO(ReqIEs="); + /* printk(KERN_DEBUG "assoc info buffer size needed:%d\n", infoElemLen * 2 + 17); */ + /* translate binary string to hex string, requirement of IWEVCUSTOM */ + for (i = 0; i < pucDesiredIE[1] + 2; ++i) + pucExtraInfo += sprintf(pucExtraInfo, "%02x", pucDesiredIE[i]); + pucExtraInfo = aucExtraInfoBuf; + wrqu.data.length = 17 + (pucDesiredIE[1] + 2) * 2; +#else + /* IWEVASSOCREQIE, indicate binary string */ + pucExtraInfo = pucDesiredIE; + wrqu.data.length = pucDesiredIE[1] + 2; +#endif +#endif /* WIRELESS_EXT < 15 */ + break; + + case IWEVMICHAELMICFAILURE: +#if WIRELESS_EXT < 15 + /* under WE-15, no suitable Event can be used */ + goto skip_indicate_event; +#else + if (pucData) { + P_PARAM_AUTH_REQUEST_T pAuthReq = (P_PARAM_AUTH_REQUEST_T) pucData; + /* under WE-18, only IWEVCUSTOM can be used */ + u4Cmd = IWEVCUSTOM; + pucExtraInfo = aucExtraInfoBuf; + pucExtraInfo += sprintf(pucExtraInfo, "MLME-MICHAELMICFAILURE.indication "); + pucExtraInfo += snprintf(pucExtraInfo, + 10, + "%s", + (pAuthReq->u4Flags == PARAM_AUTH_REQUEST_GROUP_ERROR) ? + "groupcast " : "unicast "); + + wrqu.data.length = pucExtraInfo - aucExtraInfoBuf; + pucExtraInfo = aucExtraInfoBuf; + } +#endif /* WIRELESS_EXT < 15 */ + break; + + case IWEVPMKIDCAND: + if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA2 && + prGlueInfo->rWpaInfo.u4KeyMgmt == IW_AUTH_KEY_MGMT_802_1X) { + + /* only used in WPA2 */ +#if WIRELESS_EXT >= 18 + P_PARAM_PMKID_CANDIDATE_T prPmkidCand = (P_PARAM_PMKID_CANDIDATE_T) pucData; + + struct iw_pmkid_cand rPmkidCand; + + pucExtraInfo = aucExtraInfoBuf; + + rPmkidCand.flags = prPmkidCand->u4Flags; + rPmkidCand.index = 0; + rPmkidCand.bssid.sa_family = 0; + kalMemCopy(rPmkidCand.bssid.sa_data, prPmkidCand->arBSSID, 6); + + kalMemCopy(pucExtraInfo, (PUINT_8) &rPmkidCand, sizeof(struct iw_pmkid_cand)); + wrqu.data.length = sizeof(struct iw_pmkid_cand); + + /* pmkid canadidate list is supported after WE-18 */ + /* indicate struct iw_pmkid_cand */ +#else + /* printk(KERN_INFO "IWEVPMKIDCAND event skipped, WE < 18\n"); */ + goto skip_indicate_event; +#endif + } else { + /* printk(KERN_INFO "IWEVPMKIDCAND event skipped, NOT WPA2\n"); */ + goto skip_indicate_event; + } + break; + + case IWEVCUSTOM: + u4Cmd = IWEVCUSTOM; + pucExtraInfo = aucExtraInfoBuf; + kalMemCopy(pucExtraInfo, pucData, sizeof(PTA_IPC_T)); + wrqu.data.length = sizeof(PTA_IPC_T); + break; + + default: + /* printk(KERN_INFO "Unsupported wext event:%x\n", cmd); */ + goto skip_indicate_event; + } + + /* Send event to user space */ + wireless_send_event(prGlueInfo->prDevHandler, u4Cmd, &wrqu, pucExtraInfo); + +skip_indicate_event: + return; +} /* wext_indicate_wext_event */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A method of struct net_device, to get the network interface statistical +* information. +* +* Whenever an application needs to get statistics for the interface, this method +* is called. This happens, for example, when ifconfig or netstat -i is run. +* +* \param[in] pDev Pointer to struct net_device. +* +* \return net_device_stats buffer pointer. +* +*/ +/*----------------------------------------------------------------------------*/ +struct iw_statistics *wext_get_wireless_stats(struct net_device *prDev) +{ + + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + P_GLUE_INFO_T prGlueInfo = NULL; + struct iw_statistics *pStats = NULL; + INT_32 i4Rssi; + UINT_32 bufLen = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) + goto stat_out; + + pStats = (struct iw_statistics *)(&(prGlueInfo->rIwStats)); + + if (!prDev || !netif_carrier_ok(prDev)) { + /* network not connected */ + goto stat_out; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryRssi, &i4Rssi, sizeof(i4Rssi), TRUE, TRUE, TRUE, FALSE, &bufLen); + +stat_out: + return pStats; +} /* wlan_get_wireless_stats */ + + +/* Standard call implementations */ +static int std_get_name(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_name(prDev, NULL, (char *)(&(prData->name)), + sizeof(prData->name), NULL); +} + +static int std_set_freq(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_freq(prDev, NULL, &(prData->freq), NULL); +} + +static int std_get_freq(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_freq(prDev, NULL, &(prData->freq), NULL); +} + +static int std_set_mode(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_mode(prDev, NULL, &prData->mode, NULL); +} + +static int std_get_mode(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_mode(prDev, NULL, &prData->mode, NULL); +} + +static int std_set_ap(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + int ret = 0; + + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + + if (prData->ap_addr.sa_data[0] == 0 && + prData->ap_addr.sa_data[1] == 0 && + prData->ap_addr.sa_data[2] == 0 && + prData->ap_addr.sa_data[3] == 0 && + prData->ap_addr.sa_data[4] == 0 + && prData->ap_addr.sa_data[5] == 0) { + /* WPA Supplicant will set 000000000000 in + * wpa_driver_wext_deinit(), do nothing here or + * disassoc again? + */ + ret = 0; + } else { + ret = wext_set_ap(prDev, NULL, &(prData->ap_addr), NULL); + } + return ret; +} + +static int std_get_ap(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_ap(prDev, NULL, &(prData->ap_addr), NULL); +} + +static int std_get_rate(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_rate(prDev, NULL, &prData->bitrate, NULL); +} + +static int std_set_rts(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_rts(prDev, NULL, &(prData->rts), NULL); +} + +static int std_get_rts(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_rts(prDev, NULL, &prData->rts, NULL); +} + +static int std_get_frag(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_frag(prDev, NULL, &prData->frag, NULL); +} + +static int std_set_txpow(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_txpow(prDev, NULL, &(prData->txpower), NULL); +} + +static int std_get_txpow(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_txpow(prDev, NULL, &prData->txpower, NULL); +} + +static int std_set_power(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_power(prDev, NULL, &prData->power, NULL); +} + +static int std_get_power(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_power(prDev, NULL, &prData->power, NULL); +} + +static int std_get_range(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_range(prDev, NULL, &(prData->data), + pcExtra); +} + +static int std_set_priv(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_country(prDev, &(prData->data)); +} + +static int std_get_priv(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_priv(prDev, &(prData->data)); +} + +static int std_set_scan(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_scan(prDev, NULL, NULL, NULL); +} + +static int std_set_mlme(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_mlme(prDev, NULL, &(prData->data), pcExtra); +} + +static int std_get_scan(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_scan(prDev, NULL, &(prData->data), pcExtra); +} + +static int std_set_essid(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_essid(prDev, NULL, &(prData->essid), pcExtra); +} + +static int std_get_essid(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_essid(prDev, NULL, &(prData->essid), pcExtra); +} + +static int std_set_encode(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_encode(prDev, NULL, + &(prData->encoding), + pcExtra); +} + +static int std_get_encode(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_encode(prDev, NULL, &(prData->encoding), NULL); +} + +static int std_set_auth(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_auth(prDev, NULL, &(prData->param), NULL); +} + +static int std_set_encode_ext(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_encode_ext(prDev, NULL, &(prData->encoding), + pcExtra); +} + +#endif /* WIRELESS_EXT */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_wext_priv.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_wext_priv.c new file mode 100644 index 0000000000000..df0c63a6f793e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/gl_wext_priv.c @@ -0,0 +1,5338 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ +#include "precomp.h" + +#include "gl_os.h" +#include "gl_wext_priv.h" +#if CFG_SUPPORT_WAPI +#include "gl_sec.h" +#endif +#if CFG_ENABLE_WIFI_DIRECT +#include "gl_p2p_os.h" +#endif +#ifdef FW_CFG_SUPPORT +#include "fwcfg.h" +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define NUM_SUPPORTED_OIDS (sizeof(arWlanOidReqTable) / sizeof(WLAN_REQ_ENTRY)) +#define CMD_START "START" +#define CMD_STOP "STOP" +#define CMD_SCAN_ACTIVE "SCAN-ACTIVE" +#define CMD_SCAN_PASSIVE "SCAN-PASSIVE" +#define CMD_RSSI "RSSI" +#define CMD_LINKSPEED "LINKSPEED" +#define CMD_RXFILTER_START "RXFILTER-START" +#define CMD_RXFILTER_STOP "RXFILTER-STOP" +#define CMD_RXFILTER_ADD "RXFILTER-ADD" +#define CMD_RXFILTER_REMOVE "RXFILTER-REMOVE" +#define CMD_BTCOEXSCAN_START "BTCOEXSCAN-START" +#define CMD_BTCOEXSCAN_STOP "BTCOEXSCAN-STOP" +#define CMD_BTCOEXMODE "BTCOEXMODE" +#define CMD_SETSUSPENDOPT "SETSUSPENDOPT" +#define CMD_SETSUSPENDMODE "SETSUSPENDMODE" +#define CMD_P2P_DEV_ADDR "P2P_DEV_ADDR" +#define CMD_SETFWPATH "SETFWPATH" +#define CMD_SETBAND "SETBAND" +#define CMD_GETBAND "GETBAND" +#define CMD_COUNTRY "COUNTRY" +#define CMD_P2P_SET_NOA "P2P_SET_NOA" +#define CMD_P2P_GET_NOA "P2P_GET_NOA" +#define CMD_P2P_SET_PS "P2P_SET_PS" +#define CMD_SET_AP_WPS_P2P_IE "SET_AP_WPS_P2P_IE" +#define CMD_SETROAMMODE "SETROAMMODE" +#define CMD_MIRACAST "MIRACAST" + +#define CMD_ECSA "P2P_ECSA" +#define CMD_PNOSSIDCLR_SET "PNOSSIDCLR" +#define CMD_PNOSETUP_SET "PNOSETUP " +#define CMD_PNOENABLE_SET "PNOFORCE" +#define CMD_PNODEBUG_SET "PNODEBUG" +#define CMD_WLS_BATCHING "WLS_BATCHING" + +#define CMD_OKC_SET_PMK "SET_PMK" +#define CMD_OKC_ENABLE "OKC_ENABLE" + +#define CMD_ADD_TS "addts" +#define CMD_DELETE_TS "delts" +#define CMD_FW_PARAM "set_fw_param " + +/* miracast related definition */ +#define MIRACAST_MODE_OFF 0 +#define MIRACAST_MODE_SOURCE 1 +#define MIRACAST_MODE_SINK 2 + +#ifndef MIRACAST_AMPDU_SIZE +#define MIRACAST_AMPDU_SIZE 8 +#endif + +#ifndef MIRACAST_MCHAN_ALGO +#define MIRACAST_MCHAN_ALGO 1 +#endif + +#ifndef MIRACAST_MCHAN_BW +#define MIRACAST_MCHAN_BW 25 +#endif + +#define CMD_BAND_AUTO 0 +#define CMD_BAND_5G 1 +#define CMD_BAND_2G 2 +#define CMD_BAND_ALL 3 +#define CMD_OID_BUF_LENGTH 4096 + +/* Mediatek private command */ + +#define CMD_SET_SW_CTRL "SET_SW_CTRL" +#define CMD_GET_SW_CTRL "GET_SW_CTRL" +#define CMD_SET_CFG "SET_CFG" +#define CMD_GET_CFG "GET_CFG" +#define CMD_SET_CHIP "SET_CHIP" +#define CMD_GET_CHIP "GET_CHIP" +#define CMD_SET_DBG_LEVEL "SET_DBG_LEVEL" +#define CMD_GET_DBG_LEVEL "GET_DBG_LEVEL" +#define CMD_SET_FCC_CERT "SET_FCC_CHANNEL" +#define CMD_GET_WIFI_TYPE "GET_WIFI_TYPE" +#define PRIV_CMD_SIZE 512 + +static UINT_32 g_ucMiracastMode = MIRACAST_MODE_OFF; + +typedef struct cmd_tlv { + char prefix; + char version; + char subver; + char reserved; +} cmd_tlv_t; + +typedef struct priv_driver_cmd_s { + char buf[PRIV_CMD_SIZE]; + int used_len; + int total_len; +} priv_driver_cmd_t; + +#if CFG_SUPPORT_BATCH_SCAN +#define CMD_BATCH_SET "WLS_BATCHING SET" +#define CMD_BATCH_GET "WLS_BATCHING GET" +#define CMD_BATCH_STOP "WLS_BATCHING STOP" +#endif + +#if CFG_SUPPORT_NCHO +/* NCHO related command definition. Setting by supplicant */ +#define CMD_NCHO_ROAM_TRIGGER_GET "GETROAMTRIGGER" +#define CMD_NCHO_ROAM_TRIGGER_SET "SETROAMTRIGGER" +#define CMD_NCHO_ROAM_DELTA_GET "GETROAMDELTA" +#define CMD_NCHO_ROAM_DELTA_SET "SETROAMDELTA" +#define CMD_NCHO_ROAM_SCAN_PERIOD_GET "GETROAMSCANPERIOD" +#define CMD_NCHO_ROAM_SCAN_PERIOD_SET "SETROAMSCANPERIOD" +#define CMD_NCHO_ROAM_SCAN_CHANNELS_GET "GETROAMSCANCHANNELS" +#define CMD_NCHO_ROAM_SCAN_CHANNELS_SET "SETROAMSCANCHANNELS" +#define CMD_NCHO_ROAM_SCAN_CONTROL_GET "GETROAMSCANCONTROL" +#define CMD_NCHO_ROAM_SCAN_CONTROL_SET "SETROAMSCANCONTROL" +#define CMD_NCHO_SCAN_CHANNEL_TIME_GET "GETSCANCHANNELTIME" +#define CMD_NCHO_SCAN_CHANNEL_TIME_SET "SETSCANCHANNELTIME" +#define CMD_NCHO_SCAN_HOME_TIME_GET "GETSCANHOMETIME" +#define CMD_NCHO_SCAN_HOME_TIME_SET "SETSCANHOMETIME" +#define CMD_NCHO_SCAN_HOME_AWAY_TIME_GET "GETSCANHOMEAWAYTIME" +#define CMD_NCHO_SCAN_HOME_AWAY_TIME_SET "SETSCANHOMEAWAYTIME" +#define CMD_NCHO_SCAN_NPROBES_GET "GETSCANNPROBES" +#define CMD_NCHO_SCAN_NPROBES_SET "SETSCANNPROBES" +#define CMD_NCHO_REASSOC_SEND "REASSOC" +#define CMD_NCHO_ACTION_FRAME_SEND "SENDACTIONFRAME" +#define CMD_NCHO_WES_MODE_GET "GETWESMODE" +#define CMD_NCHO_WES_MODE_SET "SETWESMODE" +#define CMD_NCHO_BAND_GET "GETBAND" +#define CMD_NCHO_BAND_SET "SETBAND" +#define CMD_NCHO_DFS_SCAN_MODE_GET "GETDFSSCANMODE" +#define CMD_NCHO_DFS_SCAN_MODE_SET "SETDFSSCANMODE" +#define CMD_NCHO_DFS_SCAN_MODE_GET "GETDFSSCANMODE" +#define CMD_NCHO_DFS_SCAN_MODE_SET "SETDFSSCANMODE" +#define CMD_NCHO_ENABLE "NCHOENABLE" +#define CMD_NCHO_DISABLE "NCHODISABLE" +static int +priv_driver_enable_ncho(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen); +static int +priv_driver_disable_ncho(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen); + +int +priv_driver_set_ncho_roam_trigger(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Param = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 i4Ret = -1; + UINT_32 u4SetInfoLen = 0; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, apcArgv[1]); + i4Ret = kalkStrtos32(apcArgv[1], 0, &i4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", i4Ret); + return -1; + } + + DBGLOG(INIT, TRACE, "NCHO set roam trigger cmd %d\n", i4Param); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNchoRoamTrigger, + &i4Param, sizeof(INT_32), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO set roam trigger fail 0x%x\n", rStatus); + i4Ret = -1; + } else { + DBGLOG(INIT, TRACE, "NCHO set roam trigger successed\n"); + i4Ret = 0; + } + + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4Ret; +} + +int +priv_driver_get_ncho_roam_trigger(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4BytesWritten = -1; + INT_32 i4Param = 0; + UINT_32 u4BufLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + struct _CMD_HEADER_T cmdV1Header; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4BytesWritten; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return i4BytesWritten; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryNchoRoamTrigger, + &cmdV1Header, + sizeof(cmdV1Header), TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO wlanoidQueryNchoRoamTrigger fail 0x%x\n", rStatus); + return i4BytesWritten; + } + + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %s\n", cmdV1Header.buffer); + i4BytesWritten = kalkStrtou32(cmdV1Header.buffer, 0, &i4Param); + if (i4BytesWritten) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d!\n", i4BytesWritten); + i4BytesWritten = -1; + } else { + i4Param = RCPI_TO_dBm(i4Param); /* RCPI to DB */ + DBGLOG(INIT, TRACE, "NCHO query RoamTrigger is %d\n", i4Param); + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%d", i4Param); + } + + return i4BytesWritten; +} + +int priv_driver_set_ncho_roam_delta(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Param = 0; + UINT_32 u4SetInfoLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 i4Ret = -1; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, apcArgv[1]); + i4Ret = kalkStrtos32(apcArgv[1], 0, &i4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", i4Ret); + return -1; + } + + DBGLOG(INIT, TRACE, "NCHO set roam delta cmd %d\n", i4Param); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNchoRoamDelta, + &i4Param, sizeof(INT_32), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO set roam delta fail 0x%x\n", rStatus); + i4Ret = -1; + } else { + DBGLOG(INIT, TRACE, "NCHO set roam delta successed\n"); + i4Ret = 0; + } + + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4Ret; +} +int priv_driver_get_ncho_roam_delta(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4BytesWritten = -1; + INT_32 i4Param = 0; + UINT_32 u4BufLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4BytesWritten; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return i4BytesWritten; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryNchoRoamDelta, + &i4Param, + sizeof(INT_32), TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO wlanoidQueryNchoRoamDelta fail 0x%x\n", rStatus); + } else { + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %d\n", i4Param); + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%d", i4Param); + } + return i4BytesWritten; +} + +int priv_driver_set_ncho_roam_scn_period(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4Param = 0; + UINT_32 u4SetInfoLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 i4Ret = -1; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, apcArgv[1]); + i4Ret = kalkStrtou32(apcArgv[1], 0, &u4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", i4Ret); + return -1; + } + + DBGLOG(INIT, TRACE, "NCHO set roam period cmd %d\n", u4Param); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNchoRoamScnPeriod, + &u4Param, sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO set roam period fail 0x%x\n", rStatus); + i4Ret = -1; + } else { + DBGLOG(INIT, TRACE, "NCHO set roam period successed\n"); + i4Ret = 0; + } + + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4Ret; +} +int priv_driver_get_ncho_roam_scn_period(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4BytesWritten = -1; + UINT_32 u4Param = 0; + UINT_32 u4BufLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4BytesWritten; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return i4BytesWritten; + } + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryNchoRoamScnPeriod, + &u4Param, + sizeof(UINT_32), TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO wlanoidQueryNchoRoamScnPeriod fail 0x%x\n", rStatus); + } else { + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %d\n", u4Param); + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%u", u4Param); + } + return i4BytesWritten; +} +int priv_driver_set_ncho_roam_scn_chnl(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4ChnlInfo = 0; + UINT_8 i = 1; + UINT_8 t = 0; + UINT_32 u4SetInfoLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 i4Ret = -1; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + CFG_NCHO_SCAN_CHNL_T rRoamScnChnl; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, cmd is %s\n", i4Argc, apcArgv[1]); + i4Ret = kalkStrtou32(apcArgv[1], 0, &u4ChnlInfo); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", i4Ret); + return -1; + } + + rRoamScnChnl.ucChannelListNum = u4ChnlInfo; + DBGLOG(REQ, ERROR, "NCHO ChannelListNum is %d\n", u4ChnlInfo); + if (i4Argc != u4ChnlInfo + 2) { + DBGLOG(REQ, ERROR, "NCHO param mismatch %d\n", u4ChnlInfo); + return -1; + } + for (i = 2; i < i4Argc; i++) { + i4Ret = kalkStrtou32(apcArgv[i], 0, &u4ChnlInfo); + if (i4Ret) { + while (i != 2) { + rRoamScnChnl.arChnlInfoList[i].ucChannelNum = 0; + i--; + } + DBGLOG(REQ, ERROR, "NCHO parse chnl num error %d\n", i4Ret); + return -1; + } + if (u4ChnlInfo != 0) { + DBGLOG(INIT, TRACE, "NCHO t = %d, channel value=%d\n", t, u4ChnlInfo); + if ((u4ChnlInfo >= 1) && (u4ChnlInfo <= 14)) + rRoamScnChnl.arChnlInfoList[t].eBand = BAND_2G4; + else + rRoamScnChnl.arChnlInfoList[t].eBand = BAND_5G; + + rRoamScnChnl.arChnlInfoList[t].ucChannelNum = u4ChnlInfo; + t++; + } + + } + + DBGLOG(INIT, TRACE, "NCHO set roam scan channel cmd\n"); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNchoRoamScnChnl, + &rRoamScnChnl, + sizeof(CFG_NCHO_SCAN_CHNL_T), + FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO set roam scan channel fail 0x%x\n", rStatus); + i4Ret = -1; + } else { + DBGLOG(INIT, TRACE, "NCHO set roam scan channel successed\n"); + i4Ret = 0; + } + + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4Ret; +} + +int priv_driver_get_ncho_roam_scn_chnl(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_8 i = 0; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = -1; + INT_32 i4Argc = 0; + UINT_32 u4ChnlInfo = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + CFG_NCHO_SCAN_CHNL_T rRoamScnChnl; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4BytesWritten; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return i4BytesWritten; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryNchoRoamScnChnl, + &rRoamScnChnl, + sizeof(CFG_NCHO_SCAN_CHNL_T), TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO wlanoidQueryNchoRoamScnChnl fail 0x%x\n", rStatus); + } else { + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %d\n", rRoamScnChnl.ucChannelListNum); + u4ChnlInfo = rRoamScnChnl.ucChannelListNum; + i4BytesWritten = 0; + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, "%u", u4ChnlInfo); + for (i = 0; i < rRoamScnChnl.ucChannelListNum; i++) { + u4ChnlInfo = rRoamScnChnl.arChnlInfoList[i].ucChannelNum; + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, " %u", u4ChnlInfo); + } + } + + DBGLOG(REQ, TRACE, "NCHO i4BytesWritten is %d and channel list is %s\n", i4BytesWritten, pcCommand); + return i4BytesWritten; +} + +int priv_driver_set_ncho_roam_scn_ctrl(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4Param = 0; + UINT_32 u4SetInfoLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 i4Ret = -1; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, apcArgv[1]); + i4Ret = kalkStrtou32(apcArgv[1], 0, &u4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", i4Ret); + return -1; + } + + DBGLOG(INIT, TRACE, "NCHO set roam scan control cmd %d\n", u4Param); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNchoRoamScnCtrl, + &u4Param, sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO set roam scan control fail 0x%x\n", rStatus); + i4Ret = -1; + } else { + DBGLOG(INIT, TRACE, "NCHO set roam scan control successed\n"); + i4Ret = 0; + } + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4Ret; +} +int priv_driver_get_ncho_roam_scn_ctrl(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4BytesWritten = -1; + UINT_32 u4Param = 0; + UINT_32 u4BufLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4BytesWritten; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return i4BytesWritten; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryNchoRoamScnCtrl, + &u4Param, + sizeof(UINT_32), TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO wlanoidQueryNchoRoamScnCtrl fail 0x%x\n", rStatus); + } else { + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %d\n", u4Param); + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%u", u4Param); + } + return i4BytesWritten; +} + +int priv_driver_set_ncho_scn_chnl_time(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4Param = 0; + UINT_32 u4SetInfoLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 i4Ret = -1; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, apcArgv[1]); + i4Ret = kalkStrtou32(apcArgv[1], 0, &u4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", i4Ret); + return -1; + } + + DBGLOG(INIT, TRACE, "NCHO set scan channel time cmd %d\n", u4Param); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNchoScnChnlTime, + &u4Param, sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO set scan channel time fail 0x%x\n", rStatus); + i4Ret = -1; + } else { + DBGLOG(INIT, TRACE, "NCHO set scan channel time successed\n"); + i4Ret = 0; + } + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4Ret; +} +int priv_driver_get_ncho_scn_chnl_time(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4BytesWritten = -1; + UINT_32 u4Param = 0; + UINT_32 u4BufLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + struct _CMD_HEADER_T cmdV1Header; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4BytesWritten; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return i4BytesWritten; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryNchoScnChnlTime, + &cmdV1Header, + sizeof(cmdV1Header), TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO wlanoidQueryNchoScnChnlTime fail 0x%x\n", rStatus); + } else { + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %s\n", cmdV1Header.buffer); + i4BytesWritten = kalkStrtou32(cmdV1Header.buffer, 0, &u4Param); + if (i4BytesWritten) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d!\n", i4BytesWritten); + i4BytesWritten = -1; + } else { + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%u", u4Param); + } + } + return i4BytesWritten; +} + +int priv_driver_set_ncho_scn_home_time(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4Param = 0; + UINT_32 u4SetInfoLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 i4Ret = -1; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, apcArgv[1]); + i4Ret = kalkStrtou32(apcArgv[1], 0, &u4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", i4Ret); + return -1; + } + + DBGLOG(INIT, TRACE, "NCHO set scan home time cmd %d\n", u4Param); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNchoScnHomeTime, + &u4Param, sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO set scan home time fail 0x%x\n", rStatus); + i4Ret = -1; + } else { + DBGLOG(INIT, TRACE, "NCHO set scan home time successed\n"); + i4Ret = 0; + } + + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4Ret; +} +int priv_driver_get_ncho_scn_home_time(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4BytesWritten = -1; + UINT_32 u4Param = 0; + UINT_32 u4BufLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + struct _CMD_HEADER_T cmdV1Header; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4BytesWritten; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return i4BytesWritten; + } + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryNchoScnHomeTime, + &cmdV1Header, + sizeof(cmdV1Header), TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO wlanoidQueryNchoScnChnlTime fail 0x%x\n", rStatus); + } else { + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %s\n", cmdV1Header.buffer); + i4BytesWritten = kalkStrtou32(cmdV1Header.buffer, 0, &u4Param); + if (i4BytesWritten) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d!\n", i4BytesWritten); + i4BytesWritten = -1; + } else { + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%u", u4Param); + } + } + return i4BytesWritten; +} + +int priv_driver_set_ncho_scn_home_away_time(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4Param = 0; + UINT_32 u4SetInfoLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 i4Ret = -1; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, apcArgv[1]); + i4Ret = kalkStrtou32(apcArgv[1], 0, &u4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", i4Ret); + return -1; + } + + DBGLOG(INIT, TRACE, "NCHO set scan home away time cmd %d\n", u4Param); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNchoScnHomeAwayTime, + &u4Param, sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO set scan home away time fail 0x%x\n", rStatus); + i4Ret = -1; + } else { + DBGLOG(INIT, TRACE, "NCHO set scan home away time successed\n"); + i4Ret = 0; + } + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4Ret; +} +int priv_driver_get_ncho_scn_home_away_time(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4BytesWritten = -1; + UINT_32 u4Param = 0; + UINT_32 u4BufLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + struct _CMD_HEADER_T cmdV1Header; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4BytesWritten; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return i4BytesWritten; + } + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryNchoScnHomeAwayTime, + &cmdV1Header, + sizeof(cmdV1Header), TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO wlanoidQueryNchoScnHomeAwayTime fail 0x%x\n", rStatus); + return i4BytesWritten; + } + + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %s\n", cmdV1Header.buffer); + i4BytesWritten = kalkStrtou32(cmdV1Header.buffer, 0, &u4Param); + if (i4BytesWritten) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d!\n", i4BytesWritten); + i4BytesWritten = -1; + } else { + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%u", u4Param); + } + + return i4BytesWritten; +} + +int priv_driver_set_ncho_scn_nprobes(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4Param = 0; + UINT_32 u4SetInfoLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 i4Ret = -1; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, apcArgv[1]); + + i4Ret = kalkStrtou32(apcArgv[1], 0, &u4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", i4Ret); + return -1; + } + + DBGLOG(INIT, TRACE, "NCHO set scan nprobes cmd %d\n", u4Param); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNchoScnNprobes, + &u4Param, sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO set scan nprobes fail 0x%x\n", rStatus); + i4Ret = -1; + } else { + DBGLOG(INIT, TRACE, "NCHO set scan nprobes successed\n"); + i4Ret = 0; + } + + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4Ret; +} + +int priv_driver_get_ncho_scn_nprobes(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4BytesWritten = -1; + UINT_32 u4Param = 0; + UINT_32 u4BufLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + struct _CMD_HEADER_T cmdV1Header; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4BytesWritten; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return i4BytesWritten; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryNchoScnNprobes, + &cmdV1Header, + sizeof(cmdV1Header), TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO wlanoidQueryNchoScnNprobes fail 0x%x\n", rStatus); + return i4BytesWritten; + } + + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %s\n", cmdV1Header.buffer); + i4BytesWritten = kalkStrtou32(cmdV1Header.buffer, 0, &u4Param); + if (i4BytesWritten) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d!\n", i4BytesWritten); + i4BytesWritten = -1; + } else { + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%u", u4Param); + } + + return i4BytesWritten; +} + +/* handle this command as framework roaming */ +int priv_driver_send_ncho_reassoc(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Ret = -1; + UINT_32 u4Param = 0; + UINT_32 u4SetInfoLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + CFG_NCHO_RE_ASSOC_T rReAssoc; + PARAM_CONNECT_T rParamConn; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc == 3) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s %s\n", i4Argc, apcArgv[1], apcArgv[2]); + + i4Ret = kalkStrtou32(apcArgv[2], 0, &u4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", i4Ret); + return -1; + } + DBGLOG(INIT, TRACE, "NCHO send reassoc cmd %d\n", u4Param); + kalMemZero(&rReAssoc, sizeof(CFG_NCHO_RE_ASSOC_T)); + rReAssoc.u4CenterFreq = nicChannelNum2Freq(u4Param); + CmdStringMacParse(apcArgv[1], (UINT_8 **)&apcArgv[1], &u4SetInfoLen, rReAssoc.aucBssid); + DBGLOG(INIT, TRACE, "NCHO Bssid %pM to roam\n", rReAssoc.aucBssid); + rParamConn.pucBssid = (UINT_8 *)rReAssoc.aucBssid; + rParamConn.pucSsid = (UINT_8 *)rReAssoc.aucSsid; + rParamConn.u4SsidLen = rReAssoc.u4SsidLen; + rParamConn.u4CenterFreq = rReAssoc.u4CenterFreq; + + rStatus = kalIoctl(prGlueInfo, + wlanoidGetNchoReassocInfo, + &rParamConn, + sizeof(PARAM_CONNECT_T), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO get reassoc information fail 0x%x\n", rStatus); + return -1; + } + DBGLOG(INIT, TRACE, "NCHO ssid %s to roam\n", HIDE(rParamConn.pucSsid)); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetConnect, + &rParamConn, + sizeof(PARAM_CONNECT_T), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO send reassoc fail 0x%x\n", rStatus); + i4Ret = -1; + } else { + DBGLOG(INIT, TRACE, "NCHO send reassoc successed\n"); + i4Ret = 0; + } + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4Ret; +} + +int +nchoRemainOnChannel(IN P_ADAPTER_T prAdapter, IN UINT_8 ucChannelNum, IN UINT_32 u4DewellTime) +{ + INT_32 i4Ret = -1; + P_MSG_REMAIN_ON_CHANNEL_T prMsgChnlReq = (P_MSG_REMAIN_ON_CHANNEL_T) NULL; + + do { + if (!prAdapter) + break; + + prMsgChnlReq = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_REMAIN_ON_CHANNEL_T)); + + if (prMsgChnlReq == NULL) { + ASSERT(FALSE); + DBGLOG(REQ, ERROR, "NCHO there is no memory for message channel req\n"); + return i4Ret; + } + kalMemZero(prMsgChnlReq, sizeof(MSG_REMAIN_ON_CHANNEL_T)); + + prMsgChnlReq->rMsgHdr.eMsgId = MID_MNY_AIS_REMAIN_ON_CHANNEL; + prMsgChnlReq->u4DurationMs = u4DewellTime; + prMsgChnlReq->u8Cookie = 0; + prMsgChnlReq->ucChannelNum = ucChannelNum; + + if ((ucChannelNum >= 1) && (ucChannelNum <= 14)) + prMsgChnlReq->eBand = BAND_2G4; + else + prMsgChnlReq->eBand = BAND_5G; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChnlReq, MSG_SEND_METHOD_BUF); + + i4Ret = 0; + } while (FALSE); + + return i4Ret; +} + +int +nchoSendActionFrame(IN P_ADAPTER_T prAdapter, P_NCHO_ACTION_FRAME_PARAMS prParamActionFrame) +{ + INT_32 i4Ret = -1; + P_MSG_MGMT_TX_REQUEST_T prMsgTxReq = (P_MSG_MGMT_TX_REQUEST_T) NULL; + + if (!prAdapter || !prParamActionFrame) + return i4Ret; + + do { + /* Channel & Channel Type & Wait time are ignored. */ + prMsgTxReq = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_MGMT_TX_REQUEST_T)); + + if (prMsgTxReq == NULL) { + ASSERT(FALSE); + DBGLOG(REQ, ERROR, "NCHO there is no memory for message tx req\n"); + return i4Ret; + } + + prMsgTxReq->fgNoneCckRate = FALSE; + prMsgTxReq->fgIsWaitRsp = TRUE; + + prMsgTxReq->u8Cookie = 0; + prMsgTxReq->rMsgHdr.eMsgId = MID_MNY_AIS_NCHO_ACTION_FRAME; + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgTxReq, MSG_SEND_METHOD_BUF); + + i4Ret = 0; + } while (FALSE); + + if ((i4Ret != 0) && (prMsgTxReq != NULL)) { + if (prMsgTxReq->prMgmtMsduInfo != NULL) + cnmMgtPktFree(prAdapter, prMsgTxReq->prMgmtMsduInfo); + + cnmMemFree(prAdapter, prMsgTxReq); + } + + return i4Ret; +} + +WLAN_STATUS nchoParseActionFrame(IN P_NCHO_ACTION_FRAME_PARAMS prParamActionFrame, IN char *pcCommand) +{ + UINT_32 u4SetInfoLen = 0; + UINT_32 u4Num = 0; + P_NCHO_AF_INFO prAfInfo = NULL; + + if (!prParamActionFrame || !pcCommand) + return WLAN_STATUS_FAILURE; + + prAfInfo = (P_NCHO_AF_INFO)(pcCommand + kalStrLen(CMD_NCHO_ACTION_FRAME_SEND) + 1); + if (prAfInfo->i4len > CMD_NCHO_AF_DATA_LENGTH) { + DBGLOG(INIT, ERROR, "NCHO AF data length is %d\n", prAfInfo->i4len); + return WLAN_STATUS_FAILURE; + } + + prParamActionFrame->i4len = prAfInfo->i4len; + prParamActionFrame->i4channel = prAfInfo->i4channel; + prParamActionFrame->i4DwellTime = prAfInfo->i4DwellTime; + kalMemZero(prParamActionFrame->aucData, CMD_NCHO_AF_DATA_LENGTH/2); + u4SetInfoLen = prAfInfo->i4len; + while (u4SetInfoLen > 0 && u4Num < CMD_NCHO_AF_DATA_LENGTH/2) { + *(prParamActionFrame->aucData + u4Num) = + CmdString2HexParse(prAfInfo->pucData, + (UINT_8 **)&prAfInfo->pucData, + (UINT_8 *)&u4SetInfoLen); + u4Num++; + } + DBGLOG(INIT, TRACE, "NCHO MAC str is %s\n", prAfInfo->aucBssid); + CmdStringMacParse(prAfInfo->aucBssid, + (UINT_8 **)&prAfInfo->aucBssid, + &u4SetInfoLen, + prParamActionFrame->aucBssid); + return WLAN_STATUS_SUCCESS; +} + +int +priv_driver_send_ncho_action_frame(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + NCHO_ACTION_FRAME_PARAMS rParamActionFrame; + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Ret = -1; + UINT_32 u4SetInfoLen = 0; + ULONG ulTimer = 0; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = nchoParseActionFrame(&rParamActionFrame, pcCommand); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO action frame parse error\n"); + return -1; + } + + DBGLOG(INIT, TRACE, "NCHO MAC is %pM\n", rParamActionFrame.aucBssid); + rStatus = kalIoctl(prGlueInfo, + wlanoidSendNchoActionFrameStart, + &rParamActionFrame, + sizeof(NCHO_ACTION_FRAME_PARAMS), + FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO send action fail 0x%x\n", rStatus); + return -1; + } + + reinit_completion(&prGlueInfo->rAisChGrntComp); + i4Ret = nchoRemainOnChannel(prGlueInfo->prAdapter, + rParamActionFrame.i4channel, + rParamActionFrame.i4DwellTime); + + ulTimer = wait_for_completion_timeout(&prGlueInfo->rAisChGrntComp, + msecs_to_jiffies(CMD_NCHO_COMP_TIMEOUT)); + if (ulTimer) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSendNchoActionFrameEnd, + NULL, 0, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO send action fail 0x%x\n", rStatus); + return -1; + } + i4Ret = nchoSendActionFrame(prGlueInfo->prAdapter, &rParamActionFrame); + } else { + i4Ret = -1; + DBGLOG(INIT, ERROR, "NCHO req channel timeout\n"); + } + + return i4Ret; +} + +int +priv_driver_set_ncho_wes_mode(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4Param = 0; + UINT_32 u4SetInfoLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 i4Ret = -1; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_8 puCommondBuf[WLAN_CFG_ARGV_MAX]; + + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, apcArgv[1]); + i4Ret = kalkStrtou32(apcArgv[1], 0, &u4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", i4Ret); + return -1; + } + /*If WES mode is 1, enable NCHO*/ + /*If WES mode is 0, disable NCHO*/ + if (u4Param == TRUE && prGlueInfo->prAdapter->rNchoInfo.fgECHOEnabled == FALSE) { + kalSnprintf(puCommondBuf, WLAN_CFG_ARGV_MAX, "%s %d", CMD_NCHO_ENABLE, 1); + priv_driver_enable_ncho(prNetDev, puCommondBuf, sizeof(puCommondBuf)); + } else if (u4Param == FALSE && prGlueInfo->prAdapter->rNchoInfo.fgECHOEnabled == TRUE) { + kalSnprintf(puCommondBuf, WLAN_CFG_ARGV_MAX, "%s", CMD_NCHO_DISABLE); + priv_driver_disable_ncho(prNetDev, puCommondBuf, sizeof(puCommondBuf)); + } + + DBGLOG(INIT, INFO, "NCHO set WES mode cmd %d\n", u4Param); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNchoWesMode, + &u4Param, sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO set WES mode fail 0x%x\n", rStatus); + i4Ret = -1; + } else { + DBGLOG(INIT, TRACE, "NCHO set WES mode successed\n"); + i4Ret = 0; + } + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4Ret; +} + +int priv_driver_get_ncho_wes_mode(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4BytesWritten = -1; + UINT_32 u4Param = 0; + UINT_32 u4BufLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -WLAN_STATUS_FAILURE; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return i4BytesWritten; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryNchoWesMode, + &u4Param, + sizeof(UINT_32), TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO wlanoidQueryNchoWesMode fail 0x%x\n", rStatus); + } else { + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %d\n", u4Param); + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%u", u4Param); + } + DBGLOG(REQ, TRACE, "NCHO get result is %s\n", pcCommand); + return i4BytesWritten; +} + +int priv_driver_set_ncho_band(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4Param = 0; + UINT_32 u4SetInfoLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 i4Ret = -1; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, apcArgv[1]); + i4Ret = kalkStrtou32(apcArgv[1], 0, &u4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", i4Ret); + return -1; + } + + DBGLOG(INIT, TRACE, "NCHO set band cmd %d\n", u4Param); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNchoBand, + &u4Param, sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO set band fail 0x%x\n", rStatus); + i4Ret = -1; + } else { + DBGLOG(INIT, TRACE, "NCHO set band successed\n"); + i4Ret = 0; + } + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4Ret; +} +int priv_driver_get_ncho_band(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4BytesWritten = -1; + UINT_32 u4Param = 0; + UINT_32 u4BufLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4BytesWritten; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return i4BytesWritten; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryNchoBand, + &u4Param, + sizeof(UINT_32), TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO wlanoidQueryNchoBand fail 0x%x\n", rStatus); + } else { + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %d\n", u4Param); + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%u", u4Param); + } + return i4BytesWritten; +} + +int priv_driver_set_ncho_dfs_scn_mode(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4Param = 0; + UINT_32 u4SetInfoLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 i4Ret = -1; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, apcArgv[1]); + i4Ret = kalkStrtou32(apcArgv[1], 0, &u4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", i4Ret); + return -1; + } + + DBGLOG(INIT, TRACE, "NCHO set DFS scan cmd %d\n", u4Param); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNchoDfsScnMode, + &u4Param, sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO set DFS scan fail 0x%x\n", rStatus); + i4Ret = -1; + } else { + DBGLOG(INIT, TRACE, "NCHO set DFS scan successed\n"); + i4Ret = 0; + } + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4Ret; +} +int +priv_driver_get_ncho_dfs_scn_mode(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4BytesWritten = -1; + UINT_32 u4Param = 0; + UINT_32 u4BufLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + struct _CMD_HEADER_T cmdV1Header; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4BytesWritten; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO Error input parameter %d\n", i4Argc); + return i4BytesWritten; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryNchoDfsScnMode, + &cmdV1Header, + sizeof(struct _CMD_HEADER_T), TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO wlanoidQueryNchoDfsScnMode fail 0x%x\n", rStatus); + return i4BytesWritten; + } + + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %s\n", cmdV1Header.buffer); + i4BytesWritten = kalkStrtou32(cmdV1Header.buffer, 0, &u4Param); + if (i4BytesWritten) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d!\n", i4BytesWritten); + i4BytesWritten = -1; + } else { + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%u", u4Param); + } + + return i4BytesWritten; +} + +int +priv_driver_enable_ncho(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4Param = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 i4BytesWritten = -1; + UINT_32 u4SetInfoLen = 0; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4BytesWritten; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, apcArgv[1]); + i4BytesWritten = kalkStrtou32(apcArgv[1], 0, &u4Param); + if (i4BytesWritten) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", i4BytesWritten); + i4BytesWritten = -1; + } else { + DBGLOG(INIT, TRACE, "NCHO set enable cmd %d\n", u4Param); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNchoEnable, + &u4Param, sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO set enable fail 0x%x\n", rStatus); + i4BytesWritten = -1; + } else { + DBGLOG(INIT, TRACE, "NCHO set enable successed\n"); + i4BytesWritten = 0; + } + } + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4BytesWritten; +} + +int +priv_driver_disable_ncho(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4BytesWritten = -1; + UINT_32 u4Param = 0; + UINT_32 u4BufLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + struct _CMD_HEADER_T cmdV1Header; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4BytesWritten; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return i4BytesWritten; + } + /*<1> Set NCHO Disable to FW*/ + u4Param = FALSE; + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNchoEnable, + &u4Param, sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO wlanoidSetNchoEnable :%d fail 0x%x\n", u4Param, rStatus); + return i4BytesWritten; + } + + /*<2> Query NCHOEnable Satus*/ + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryNchoEnable, + &cmdV1Header, + sizeof(cmdV1Header), TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO wlanoidQueryNchoEnable fail 0x%x\n", rStatus); + return i4BytesWritten; + } + + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %s\n", cmdV1Header.buffer); + + + i4BytesWritten = kalkStrtou32(cmdV1Header.buffer, 0, &u4Param); + if (i4BytesWritten) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d!\n", i4BytesWritten); + i4BytesWritten = -1; + } else { + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%u", u4Param); + } + + return i4BytesWritten; +} +/*Check NCHO is enable or not.*/ +BOOLEAN +priv_driver_auto_enable_ncho(IN struct net_device *prNetDev) +{ + UINT_8 puCommondBuf[WLAN_CFG_ARGV_MAX]; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + + kalSnprintf(puCommondBuf, WLAN_CFG_ARGV_MAX, "%s %d", CMD_NCHO_ENABLE, 1); +#if CFG_SUPPORT_NCHO_AUTO_ENABLE + if (prGlueInfo->prAdapter->rNchoInfo.fgECHOEnabled == FALSE) { + DBGLOG(INIT, INFO, "NCHO is unavailable now! Start to NCHO Enable CMD\n"); + priv_driver_enable_ncho(prNetDev, puCommondBuf, sizeof(puCommondBuf)); + + } +#endif + return TRUE; +} + +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static int +priv_get_ndis(IN struct net_device *prNetDev, IN NDIS_TRANSPORT_STRUCT * prNdisReq, OUT PUINT_32 pu4OutputLen); + +static int +priv_set_ndis(IN struct net_device *prNetDev, IN NDIS_TRANSPORT_STRUCT * prNdisReq, OUT PUINT_32 pu4OutputLen); + +#if 0 /* CFG_SUPPORT_WPS */ +static int +priv_set_appie(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, OUT char *pcExtra); + +static int +priv_set_filter(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, OUT char *pcExtra); +#endif /* CFG_SUPPORT_WPS */ + +static BOOLEAN reqSearchSupportedOidEntry(IN UINT_32 rOid, OUT P_WLAN_REQ_ENTRY * ppWlanReqEntry); + +#if 0 +static WLAN_STATUS +reqExtQueryConfiguration(IN P_GLUE_INFO_T prGlueInfo, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +static WLAN_STATUS +reqExtSetConfiguration(IN P_GLUE_INFO_T prGlueInfo, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +static WLAN_STATUS +reqExtSetAcpiDevicePowerState(IN P_GLUE_INFO_T prGlueInfo, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static UINT_8 aucOidBuf[CMD_OID_BUF_LENGTH] = { 0 }; + +/* OID processing table */ +/* + * Order is important here because the OIDs should be in order of + * increasing value for binary searching. + */ +static WLAN_REQ_ENTRY arWlanOidReqTable[] = { + /* + * {(NDIS_OID)rOid, + * (PUINT_8)pucOidName, + * fgQryBufLenChecking, fgSetBufLenChecking, fgIsHandleInGlueLayerOnly, u4InfoBufLen, + * pfOidQueryHandler, + * pfOidSetHandler} + */ + /* General Operational Characteristics */ + + /* Ethernet Operational Characteristics */ + {OID_802_3_CURRENT_ADDRESS, + DISP_STRING("OID_802_3_CURRENT_ADDRESS"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 6, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryCurrentAddr, + NULL}, + + /* OID_802_3_MULTICAST_LIST */ + /* OID_802_3_MAXIMUM_LIST_SIZE */ + /* Ethernet Statistics */ + + /* NDIS 802.11 Wireless LAN OIDs */ + {OID_802_11_SUPPORTED_RATES, + DISP_STRING("OID_802_11_SUPPORTED_RATES"), + TRUE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_RATES_EX), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQuerySupportedRates, + NULL} + , + /* + * {OID_802_11_CONFIGURATION, + * DISP_STRING("OID_802_11_CONFIGURATION"), + * TRUE, TRUE, ENUM_OID_GLUE_EXTENSION, sizeof(PARAM_802_11_CONFIG_T), + * (PFN_OID_HANDLER_FUNC_REQ)reqExtQueryConfiguration, + * (PFN_OID_HANDLER_FUNC_REQ)reqExtSetConfiguration}, + */ + {OID_PNP_SET_POWER, + DISP_STRING("OID_PNP_SET_POWER"), + TRUE, FALSE, ENUM_OID_GLUE_EXTENSION, sizeof(PARAM_DEVICE_POWER_STATE), + NULL, + (PFN_OID_HANDLER_FUNC_REQ) reqExtSetAcpiDevicePowerState} + , + + /* Custom OIDs */ + {OID_CUSTOM_OID_INTERFACE_VERSION, + DISP_STRING("OID_CUSTOM_OID_INTERFACE_VERSION"), + TRUE, FALSE, ENUM_OID_DRIVER_CORE, 4, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryOidInterfaceVersion, + NULL} + , + + /* + * #if PTA_ENABLED + * {OID_CUSTOM_BT_COEXIST_CTRL, + * DISP_STRING("OID_CUSTOM_BT_COEXIST_CTRL"), + * FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_BT_COEXIST_T), + * NULL, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetBtCoexistCtrl}, + * #endif + */ + + /* + * {OID_CUSTOM_POWER_MANAGEMENT_PROFILE, + * DISP_STRING("OID_CUSTOM_POWER_MANAGEMENT_PROFILE"), + * FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryPwrMgmtProfParam, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetPwrMgmtProfParam}, + * {OID_CUSTOM_PATTERN_CONFIG, + * DISP_STRING("OID_CUSTOM_PATTERN_CONFIG"), + * TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_PATTERN_SEARCH_CONFIG_STRUCT_T), + * NULL, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetPatternConfig}, + * {OID_CUSTOM_BG_SSID_SEARCH_CONFIG, + * DISP_STRING("OID_CUSTOM_BG_SSID_SEARCH_CONFIG"), + * FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + * NULL, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetBgSsidParam}, + * {OID_CUSTOM_VOIP_SETUP, + * DISP_STRING("OID_CUSTOM_VOIP_SETUP"), + * TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryVoipConnectionStatus, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetVoipConnectionStatus}, + * {OID_CUSTOM_ADD_TS, + * DISP_STRING("OID_CUSTOM_ADD_TS"), + * TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + * NULL, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidAddTS}, + * {OID_CUSTOM_DEL_TS, + * DISP_STRING("OID_CUSTOM_DEL_TS"), + * TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + * NULL, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidDelTS}, + */ + + /* + * #if CFG_LP_PATTERN_SEARCH_SLT + * {OID_CUSTOM_SLT, + * DISP_STRING("OID_CUSTOM_SLT"), + * FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidQuerySltResult, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetSltMode}, + * #endif + * + * {OID_CUSTOM_ROAMING_EN, + * DISP_STRING("OID_CUSTOM_ROAMING_EN"), + * TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryRoamingFunction, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetRoamingFunction}, + * {OID_CUSTOM_WMM_PS_TEST, + * DISP_STRING("OID_CUSTOM_WMM_PS_TEST"), + * TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + * NULL, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetWiFiWmmPsTest}, + * {OID_CUSTOM_COUNTRY_STRING, + * DISP_STRING("OID_CUSTOM_COUNTRY_STRING"), + * FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryCurrentCountry, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetCurrentCountry}, + * + * #if CFG_SUPPORT_802_11D + * {OID_CUSTOM_MULTI_DOMAIN_CAPABILITY, + * DISP_STRING("OID_CUSTOM_MULTI_DOMAIN_CAPABILITY"), + * FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryMultiDomainCap, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetMultiDomainCap}, + * #endif + * + * {OID_CUSTOM_GPIO2_MODE, + * DISP_STRING("OID_CUSTOM_GPIO2_MODE"), + * FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(ENUM_PARAM_GPIO2_MODE_T), + * NULL, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetGPIO2Mode}, + * {OID_CUSTOM_CONTINUOUS_POLL, + * DISP_STRING("OID_CUSTOM_CONTINUOUS_POLL"), + * FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CONTINUOUS_POLL_T), + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryContinuousPollInterval, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetContinuousPollProfile}, + * {OID_CUSTOM_DISABLE_BEACON_DETECTION, + * DISP_STRING("OID_CUSTOM_DISABLE_BEACON_DETECTION"), + * FALSE, TRUE, ENUM_OID_DRIVER_CORE, 4, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryDisableBeaconDetectionFunc, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetDisableBeaconDetectionFunc}, + */ + + /* WPS */ + /* + * {OID_CUSTOM_DISABLE_PRIVACY_CHECK, + * DISP_STRING("OID_CUSTOM_DISABLE_PRIVACY_CHECK"), + * FALSE, TRUE, ENUM_OID_DRIVER_CORE, 4, + * NULL, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetDisablePriavcyCheck}, + */ + + {OID_CUSTOM_MCR_RW, + DISP_STRING("OID_CUSTOM_MCR_RW"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryMcrRead, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetMcrWrite} + , + + {OID_CUSTOM_EEPROM_RW, + DISP_STRING("OID_CUSTOM_EEPROM_RW"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryEepromRead, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetEepromWrite} + , + + {OID_CUSTOM_SW_CTRL, + DISP_STRING("OID_CUSTOM_SW_CTRL"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQuerySwCtrlRead, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetSwCtrlWrite} + , + + {OID_CUSTOM_MEM_DUMP, + DISP_STRING("OID_CUSTOM_MEM_DUMP"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_MEM_DUMP_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryMemDump, + NULL} + , + + {OID_CUSTOM_TEST_MODE, + DISP_STRING("OID_CUSTOM_TEST_MODE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + NULL, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestSetTestMode} + , + + /* + * {OID_CUSTOM_TEST_RX_STATUS, + * DISP_STRING("OID_CUSTOM_TEST_RX_STATUS"), + * FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T), + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryRfTestRxStatus, + * NULL}, + * {OID_CUSTOM_TEST_TX_STATUS, + * DISP_STRING("OID_CUSTOM_TEST_TX_STATUS"), + * FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T), + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryRfTestTxStatus, + * NULL}, + */ + {OID_CUSTOM_ABORT_TEST_MODE, + DISP_STRING("OID_CUSTOM_ABORT_TEST_MODE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + NULL, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestSetAbortTestMode} + , + {OID_CUSTOM_MTK_WIFI_TEST, + DISP_STRING("OID_CUSTOM_MTK_WIFI_TEST"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_MTK_WIFI_TEST_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestQueryAutoTest, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestSetAutoTest} + , + + /* OID_CUSTOM_EMULATION_VERSION_CONTROL */ + + /* BWCS */ +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS + {OID_CUSTOM_BWCS_CMD, + DISP_STRING("OID_CUSTOM_BWCS_CMD"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(PTA_IPC_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryBT, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetBT} + , +#endif + + /* + * {OID_CUSTOM_SINGLE_ANTENNA, + * DISP_STRING("OID_CUSTOM_SINGLE_ANTENNA"), + * FALSE, FALSE, ENUM_OID_DRIVER_CORE, 4, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryBtSingleAntenna, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetBtSingleAntenna}, + * {OID_CUSTOM_SET_PTA, + * DISP_STRING("OID_CUSTOM_SET_PTA"), + * FALSE, FALSE, ENUM_OID_DRIVER_CORE, 4, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryPta, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetPta}, + */ + + {OID_CUSTOM_MTK_NVRAM_RW, + DISP_STRING("OID_CUSTOM_MTK_NVRAM_RW"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_NVRAM_RW_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryNvramRead, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetNvramWrite} + , + + {OID_CUSTOM_CFG_SRC_TYPE, + DISP_STRING("OID_CUSTOM_CFG_SRC_TYPE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(ENUM_CFG_SRC_TYPE_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryCfgSrcType, + NULL} + , + + {OID_CUSTOM_EEPROM_TYPE, + DISP_STRING("OID_CUSTOM_EEPROM_TYPE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(ENUM_EEPROM_TYPE_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryEepromType, + NULL} + , + +#if CFG_SUPPORT_WAPI + {OID_802_11_WAPI_MODE, + DISP_STRING("OID_802_11_WAPI_MODE"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, 4, + NULL, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetWapiMode} + , + {OID_802_11_WAPI_ASSOC_INFO, + DISP_STRING("OID_802_11_WAPI_ASSOC_INFO"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + NULL, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetWapiAssocInfo} + , + {OID_802_11_SET_WAPI_KEY, + DISP_STRING("OID_802_11_SET_WAPI_KEY"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_WPI_KEY_T), + NULL, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetWapiKey} + , +#endif + +#if CFG_SUPPORT_GAMING_MODE + {OID_CUSTOM_GAMING_MODE, + DISP_STRING("OID_CUSTOM_GAMING_MODE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(UINT_32), + NULL, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetGamingMode} + , +#endif + + {OID_IPC_WIFI_LOG_UI, + DISP_STRING("OID_IPC_WIFI_LOG_UI"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(struct PARAM_WIFI_LOG_LEVEL_UI), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryWifiLogLevelSupport, + NULL} + , + + {OID_IPC_WIFI_LOG_LEVEL, + DISP_STRING("OID_IPC_WIFI_LOG_LEVEL"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(struct PARAM_WIFI_LOG_LEVEL), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryWifiLogLevel, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetWifiLogLevel} + , + +}; + +/******************************************************************************* +* 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; + + if ((i4Cmd == IOCTL_SET_STRUCT_FOR_EM) && !capable(CAP_NET_ADMIN)) + return -EPERM; + + switch (i4Cmd) { + case IOCTL_SET_INT: + /* NOTE(Kevin): 1/3 INT Type <= IFNAMSIZ, so we don't need copy_from/to_user() */ + return priv_set_int(prNetDev, &rIwReqInfo, &(prIwReq->u), (char *)&(prIwReq->u)); + + case IOCTL_GET_INT: + /* NOTE(Kevin): 1/3 INT Type <= IFNAMSIZ, so we don't need copy_from/to_user() */ + return priv_get_int(prNetDev, &rIwReqInfo, &(prIwReq->u), (char *)&(prIwReq->u)); + + case IOCTL_SET_STRUCT: + case IOCTL_SET_STRUCT_FOR_EM: + return priv_set_struct(prNetDev, &rIwReqInfo, &prIwReq->u, (char *)&(prIwReq->u)); + + case IOCTL_GET_STRUCT: + return priv_get_struct(prNetDev, &rIwReqInfo, &prIwReq->u, (char *)&(prIwReq->u)); + + default: + return -EOPNOTSUPP; + + } /* end of switch */ + +} /* priv_support_ioctl */ + +#if CFG_SUPPORT_BATCH_SCAN + +EVENT_BATCH_RESULT_T g_rEventBatchResult[CFG_BATCH_MAX_MSCAN]; + +UINT_32 batchChannelNum2Freq(UINT_32 u4ChannelNum) +{ + UINT_32 u4ChannelInMHz; + + if (u4ChannelNum >= 1 && u4ChannelNum <= 13) + u4ChannelInMHz = 2412 + (u4ChannelNum - 1) * 5; + else if (u4ChannelNum == 14) + u4ChannelInMHz = 2484; + else if (u4ChannelNum == 133) + u4ChannelInMHz = 3665; /* 802.11y */ + else if (u4ChannelNum == 137) + u4ChannelInMHz = 3685; /* 802.11y */ + else if (u4ChannelNum >= 34 && u4ChannelNum <= 165) + u4ChannelInMHz = 5000 + u4ChannelNum * 5; + else if (u4ChannelNum >= 183 && u4ChannelNum <= 196) + u4ChannelInMHz = 4000 + u4ChannelNum * 5; + else + u4ChannelInMHz = 0; + + return u4ChannelInMHz; +} + +#define TMP_TEXT_LEN_S 40 +#define TMP_TEXT_LEN_L 60 +static UCHAR text1[TMP_TEXT_LEN_S], text2[TMP_TEXT_LEN_L], text3[TMP_TEXT_LEN_L]; /* A safe len */ + +WLAN_STATUS +batchConvertResult(IN P_EVENT_BATCH_RESULT_T prEventBatchResult, + OUT PVOID pvBuffer, IN UINT_32 u4MaxBufferLen, OUT PUINT_32 pu4RetLen) +{ + CHAR *p = pvBuffer; + CHAR ssid[ELEM_MAX_LEN_SSID + 1]; + INT_32 nsize = 0, nsize1, nsize2, nsize3, scancount; + INT_32 i, j, nleft; + UINT_32 freq; + + P_EVENT_BATCH_RESULT_ENTRY_T prEntry; + P_EVENT_BATCH_RESULT_T pBr; + + nleft = u4MaxBufferLen - 5; /* -5 for "----\n" */ + + pBr = prEventBatchResult; + scancount = 0; + for (j = 0; j < CFG_BATCH_MAX_MSCAN; j++) { + scancount += pBr->ucScanCount; + pBr++; + } + + nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "scancount=%x\nnextcount=%x\n", scancount, scancount); + if (nsize1 < nleft) { + p += nsize1 = kalSprintf(p, "%s", text1); + nleft -= nsize1; + } else + goto short_buf; + + pBr = prEventBatchResult; + for (j = 0; j < CFG_BATCH_MAX_MSCAN; j++) { + DBGLOG(SCN, TRACE, "convert mscan = %d, apcount=%d, nleft=%d\n", j, pBr->ucScanCount, nleft); + + if (pBr->ucScanCount == 0) { + pBr++; + continue; + } + + nleft -= 5; /* -5 for "####\n" */ + + /* We only support one round scan result now. */ + nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "apcount=%d\n", pBr->ucScanCount); + if (nsize1 < nleft) { + p += nsize1 = kalSprintf(p, "%s", text1); + nleft -= nsize1; + } else + goto short_buf; + + for (i = 0; i < pBr->ucScanCount; i++) { + prEntry = &pBr->arBatchResult[i]; + + nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "bssid=" MACSTR "\n", + prEntry->aucBssid[0], + prEntry->aucBssid[1], + prEntry->aucBssid[2], + prEntry->aucBssid[3], + prEntry->aucBssid[4], prEntry->aucBssid[5]); + + kalMemCopy(ssid, + prEntry->aucSSID, + (prEntry->ucSSIDLen < ELEM_MAX_LEN_SSID ? prEntry->ucSSIDLen : ELEM_MAX_LEN_SSID)); + ssid[(prEntry->ucSSIDLen < + (ELEM_MAX_LEN_SSID - 1) ? prEntry->ucSSIDLen : (ELEM_MAX_LEN_SSID - 1))] = '\0'; + nsize2 = kalSnprintf(text2, TMP_TEXT_LEN_L, "ssid=%s\n", ssid); + + freq = batchChannelNum2Freq(prEntry->ucFreq); + nsize3 = + kalSnprintf(text3, TMP_TEXT_LEN_L, + "freq=%u\nlevel=%d\ndist=%u\ndistSd=%u\n====\n", freq, + prEntry->cRssi, prEntry->u4Dist, prEntry->u4Distsd); + + nsize = nsize1 + nsize2 + nsize3; + if (nsize < nleft) { + + kalStrnCpy(p, text1, TMP_TEXT_LEN_S); + p += nsize1; + + kalStrnCpy(p, text2, TMP_TEXT_LEN_L); + p += nsize2; + + kalStrnCpy(p, text3, TMP_TEXT_LEN_L); + p += nsize3; + + nleft -= nsize; + } else { + DBGLOG(SCN, TRACE, "Warning: Early break! (%d)\n", i); + break; /* discard following entries, TODO: apcount? */ + } + } + + nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "%s", "####\n"); + p += kalSprintf(p, "%s", text1); + + pBr++; + } + + nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "%s", "----\n"); + kalSprintf(p, "%s", text1); + + *pu4RetLen = u4MaxBufferLen - nleft; + DBGLOG(SCN, TRACE, "total len = %d (max len = %d)\n", *pu4RetLen, u4MaxBufferLen); + + return WLAN_STATUS_SUCCESS; + +short_buf: + DBGLOG(SCN, TRACE, + "Short buffer issue! %d > %d, %s\n", u4MaxBufferLen + (nsize - nleft), + u4MaxBufferLen, (char *)pvBuffer); + return WLAN_STATUS_INVALID_LENGTH; +} +#endif + +#if CFG_SUPPORT_GET_CH_ENV +WLAN_STATUS +scanEnvResult(P_GLUE_INFO_T prGlueInfo, OUT PVOID pvBuffer, IN UINT_32 u4MaxBufferLen, OUT PUINT_32 pu4RetLen) +{ + P_ADAPTER_T prAdapter = NULL; + CHAR *p = pvBuffer; + INT_32 nsize; + INT_32 i, nleft; + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc; + CH_ENV_T chEnvInfo[54]; /* 54: from FW define; TODO: sync MAXIMUM_OPERATION_CHANNEL_LIST */ + UINT_32 i4GetCh = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + UINT_8 ucTextLen = 40; + UCHAR text[ucTextLen]; + INT_32 u4Ret; + + prAdapter = prGlueInfo->prAdapter; + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + + kalMemZero(chEnvInfo, sizeof(chEnvInfo)); + + DBGLOG(SCN, TRACE, "pvBuffer:%s, pu4RetLen:%d\n", (char *)pvBuffer, *pu4RetLen); + + wlanCfgParseArgument(pvBuffer, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= 2) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &i4GetCh); + if (u4Ret) + DBGLOG(SCN, TRACE, "parse pvBuffer error u4Ret=%d\n", u4Ret); + /* i4GetCh = kalStrtoul(apcArgv[1], NULL, 0); */ + } + + nleft = u4MaxBufferLen - 5; /* -5 for "----\n" */ + + nsize = kalSnprintf(text, ucTextLen, "%s", "scanEnvResult\nResult:1\n");/* Always return 1 for alpha version. */ + + if (nsize < nleft) { + p += nsize = kalSnprintf(p, ucTextLen, "%s", text); + nleft -= nsize; + } else + goto short_buf; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + if (prBssDesc->ucChannelNum > 0) { + if (prBssDesc->ucChannelNum <= 14) { /* 1~14 */ + chEnvInfo[prBssDesc->ucChannelNum - 1].ucChNum = prBssDesc->ucChannelNum; + chEnvInfo[prBssDesc->ucChannelNum - 1].ucApNum++; + } else if (prBssDesc->ucChannelNum <= 64) { /* 15~22 */ + chEnvInfo[prBssDesc->ucChannelNum / 4 + 5].ucChNum = prBssDesc->ucChannelNum; + chEnvInfo[prBssDesc->ucChannelNum / 4 + 5].ucApNum++; + } else if (prBssDesc->ucChannelNum <= 116) { /* 23~27 */ + chEnvInfo[prBssDesc->ucChannelNum / 4 - 3].ucChNum = prBssDesc->ucChannelNum; + chEnvInfo[prBssDesc->ucChannelNum / 4 - 3].ucApNum++; + } else if (prBssDesc->ucChannelNum <= 140) { /* 28~30 */ + chEnvInfo[prBssDesc->ucChannelNum / 4 - 6].ucChNum = prBssDesc->ucChannelNum; + chEnvInfo[prBssDesc->ucChannelNum / 4 - 6].ucApNum++; + } else if (prBssDesc->ucChannelNum <= 165) { /* 31~35 */ + chEnvInfo[(prBssDesc->ucChannelNum - 1) / 4 - 7].ucChNum = prBssDesc->ucChannelNum; + chEnvInfo[(prBssDesc->ucChannelNum - 1) / 4 - 7].ucApNum++; + } + } + } + + for (i = 0; i < 54; i++) { + if (chEnvInfo[i].ucChNum != 0) { + if (i4GetCh == 0 || (chEnvInfo[i].ucChNum == (UINT_8)i4GetCh)) { + DBGLOG(SCN, TRACE, "chNum=%d,apNum=%d\n", chEnvInfo[i].ucChNum, chEnvInfo[i].ucApNum); + p += nsize = + kalSnprintf(p, ucTextLen, "chNum=%d,apNum=%d\n", chEnvInfo[i].ucChNum, + chEnvInfo[i].ucApNum); + nleft -= nsize; + } + } + } + + p += nsize = kalSnprintf(p, ucTextLen, "%s", "----\n"); + nleft -= nsize; + + *pu4RetLen = u4MaxBufferLen - nleft; + DBGLOG(SCN, TRACE, "total len = %d (max len = %d)\n", *pu4RetLen, u4MaxBufferLen); + + return WLAN_STATUS_SUCCESS; + +short_buf: + DBGLOG(SCN, TRACE, "Short buffer issue! %d > %d, %s\n", u4MaxBufferLen + (nsize - nleft), u4MaxBufferLen, p); + return WLAN_STATUS_INVALID_LENGTH; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Private ioctl set int handler. +* +* \param[in] prNetDev Net device requested. +* \param[in] prIwReqInfo Pointer to iwreq structure. +* \param[in] prIwReqData The ioctl data structure, use the field of sub-command. +* \param[in] pcExtra The buffer with input value +* +* \retval 0 For success. +* \retval -EOPNOTSUPP If cmd is not supported. +* \retval -EINVAL If a value is out of range. +* +*/ +/*----------------------------------------------------------------------------*/ +static int +_priv_set_int(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) +{ + UINT_32 u4SubCmd; + PUINT_32 pu4IntBuf; + P_NDIS_TRANSPORT_STRUCT prNdisReq; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4BufLen = 0; + int status = 0; + P_PTA_IPC_T prPtaIpc; + + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + + if (GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + u4SubCmd = (UINT_32) prIwReqData->mode; + pu4IntBuf = (PUINT_32) pcExtra; + + switch (u4SubCmd) { + case PRIV_CMD_TEST_MODE: + /* printk("TestMode=%ld\n", pu4IntBuf[1]); */ + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + if (pu4IntBuf[1] == PRIV_CMD_TEST_MAGIC_KEY) { + prNdisReq->ndisOidCmd = OID_CUSTOM_TEST_MODE; + } else if (pu4IntBuf[1] == 0) { + prNdisReq->ndisOidCmd = OID_CUSTOM_ABORT_TEST_MODE; + } else { + status = 0; + break; + } + prNdisReq->inNdisOidlength = 0; + prNdisReq->outNdisOidLength = 0; + + /* Execute this OID */ + status = priv_set_ndis(prNetDev, prNdisReq, &u4BufLen); + break; + + case PRIV_CMD_TEST_CMD: + /* printk("CMD=0x%08lx, data=0x%08lx\n", pu4IntBuf[1], pu4IntBuf[2]); */ + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); + + prNdisReq->ndisOidCmd = OID_CUSTOM_MTK_WIFI_TEST; + prNdisReq->inNdisOidlength = 8; + prNdisReq->outNdisOidLength = 8; + + /* Execute this OID */ + status = priv_set_ndis(prNetDev, prNdisReq, &u4BufLen); + break; + +#if CFG_SUPPORT_PRIV_MCR_RW + case PRIV_CMD_ACCESS_MCR: + /* printk("addr=0x%08lx, data=0x%08lx\n", pu4IntBuf[1], pu4IntBuf[2]); */ + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + if (!prGlueInfo->fgMcrAccessAllowed) { + if (pu4IntBuf[1] == PRIV_CMD_TEST_MAGIC_KEY && pu4IntBuf[2] == PRIV_CMD_TEST_MAGIC_KEY) + prGlueInfo->fgMcrAccessAllowed = TRUE; + status = 0; + break; + } + + kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); + + prNdisReq->ndisOidCmd = OID_CUSTOM_MCR_RW; + prNdisReq->inNdisOidlength = 8; + prNdisReq->outNdisOidLength = 8; + + /* Execute this OID */ + status = priv_set_ndis(prNetDev, prNdisReq, &u4BufLen); + break; +#endif + + case PRIV_CMD_SW_CTRL: + /* printk("addr=0x%08lx, data=0x%08lx\n", pu4IntBuf[1], pu4IntBuf[2]); */ + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); + + prNdisReq->ndisOidCmd = OID_CUSTOM_SW_CTRL; + prNdisReq->inNdisOidlength = 8; + prNdisReq->outNdisOidLength = 8; + + /* Execute this OID */ + status = priv_set_ndis(prNetDev, prNdisReq, &u4BufLen); + break; + +#if 0 + case PRIV_CMD_BEACON_PERIOD: + rStatus = wlanSetInformation(prGlueInfo->prAdapter, wlanoidSetBeaconInterval, + (PVOID)&pu4IntBuf[1],/* pu4IntBuf[0] is used as input SubCmd */ + sizeof(UINT_32), &u4BufLen); + break; +#endif + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + case PRIV_CMD_CSUM_OFFLOAD: + { + UINT_32 u4CSUMFlags; + + if (pu4IntBuf[1] == 1) + u4CSUMFlags = CSUM_OFFLOAD_EN_ALL; + else if (pu4IntBuf[1] == 0) + u4CSUMFlags = 0; + else + return -EINVAL; + + if (kalIoctl(prGlueInfo, + wlanoidSetCSUMOffload, + (PVOID)&u4CSUMFlags, + sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4BufLen) == WLAN_STATUS_SUCCESS) { + if (pu4IntBuf[1] == 1) + prNetDev->features |= NETIF_F_HW_CSUM; + else if (pu4IntBuf[1] == 0) + prNetDev->features &= ~NETIF_F_HW_CSUM; + } + } + break; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + case PRIV_CMD_POWER_MODE: + kalIoctl(prGlueInfo, wlanoidSet802dot11PowerSaveProfile, + (PVOID)&pu4IntBuf[1], /* pu4IntBuf[0] is used as input SubCmd */ + sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + break; + + case PRIV_CMD_WMM_PS: + { + PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T rWmmPsTest; + + rWmmPsTest.bmfgApsdEnAc = (UINT_8) pu4IntBuf[1]; + rWmmPsTest.ucIsEnterPsAtOnce = (UINT_8) pu4IntBuf[2]; + rWmmPsTest.ucIsDisableUcTrigger = (UINT_8) pu4IntBuf[3]; + rWmmPsTest.reserved = 0; + + kalIoctl(prGlueInfo, + wlanoidSetWiFiWmmPsTest, + (PVOID)&rWmmPsTest, + sizeof(PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + } + break; + +#if 0 + case PRIV_CMD_ADHOC_MODE: + rStatus = wlanSetInformation(prGlueInfo->prAdapter, wlanoidSetAdHocMode, + (PVOID)&pu4IntBuf[1], /* pu4IntBuf[0] is used as input SubCmd */ + sizeof(UINT_32), &u4BufLen); + break; +#endif + + case PRIV_CUSTOM_BWCS_CMD: + + DBGLOG(REQ, INFO, "pu4IntBuf[1] = %x, size of PTA_IPC_T = %zu.\n", + pu4IntBuf[1], sizeof(PARAM_PTA_IPC_T)); + + prPtaIpc = (P_PTA_IPC_T) aucOidBuf; + prPtaIpc->u.aucBTPParams[0] = (UINT_8) (pu4IntBuf[1] >> 24); + prPtaIpc->u.aucBTPParams[1] = (UINT_8) (pu4IntBuf[1] >> 16); + prPtaIpc->u.aucBTPParams[2] = (UINT_8) (pu4IntBuf[1] >> 8); + prPtaIpc->u.aucBTPParams[3] = (UINT_8) (pu4IntBuf[1]); + + DBGLOG(REQ, INFO, + "BCM BWCS CMD : BTPParams[0]=%02x, BTPParams[1]=%02x, BTPParams[2]=%02x, BTPParams[3]=%02x.\n", + prPtaIpc->u.aucBTPParams[0], prPtaIpc->u.aucBTPParams[1], prPtaIpc->u.aucBTPParams[2], + prPtaIpc->u.aucBTPParams[3]); + +#if 0 + status = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetBT, (PVOID)&aucOidBuf[0], u4CmdLen, &u4BufLen); +#endif + + status = wlanoidSetBT(prGlueInfo->prAdapter, + (PVOID)&aucOidBuf[0], sizeof(PARAM_PTA_IPC_T), &u4BufLen); + + if (status != WLAN_STATUS_SUCCESS) + status = -EFAULT; + + break; + + case PRIV_CMD_BAND_CONFIG: + { + DBGLOG(REQ, INFO, "CMD set_band=%u\n", (UINT_32) pu4IntBuf[1]); + } + break; + +#if CFG_ENABLE_WIFI_DIRECT + case PRIV_CMD_P2P_MODE: + { + /* no use, move to set_p2p_mode_handler() */ + PARAM_CUSTOM_P2P_SET_STRUCT_T p2pmode; + + p2pmode.u4Enable = pu4IntBuf[1]; + p2pmode.u4Mode = pu4IntBuf[2]; + set_p2p_mode_handler(prNetDev, p2pmode); +#if 0 + PARAM_CUSTOM_P2P_SET_STRUCT_T rSetP2P; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + BOOLEAN fgIsP2PEnding; + + GLUE_SPIN_LOCK_DECLARATION(); + + /* avoid remove & p2p off command simultaneously */ + GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); + fgIsP2PEnding = g_u4P2PEnding; + g_u4P2POnOffing = 1; + GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); + + if (fgIsP2PEnding == 1) { + /* skip the command if we are removing */ + GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); + g_u4P2POnOffing = 0; + GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); + break; + } + rSetP2P.u4Enable = pu4IntBuf[1]; + rSetP2P.u4Mode = pu4IntBuf[2]; + + if (!rSetP2P.u4Enable) + p2pNetUnregister(prGlueInfo, TRUE); + + /* move out to caller to avoid kalIoctrl & suspend/resume deadlock problem ALPS00844864 */ + /* + * Scenario: + * 1. System enters suspend/resume but not yet enter wlanearlysuspend() + * or wlanlateresume(); + * + * 2. System switches to do PRIV_CMD_P2P_MODE and execute kalIoctl() + * and get g_halt_sem then do glRegisterEarlySuspend() or + * glUnregisterEarlySuspend(); + * + * But system suspend/resume procedure is not yet finished so we + * suspend; + * + * 3. System switches back to do suspend/resume procedure and execute + * kalIoctl(). But driver does not yet release g_halt_sem so system + * suspend in wlanearlysuspend() or wlanlateresume(); + * + * ==> deadlock occurs. + */ + if ((!rSetP2P.u4Enable) && (g_u4HaltFlag == 0) && (fgIsResetting == FALSE)) { + /* fgIsP2PRegistered == TRUE means P2P is enabled */ + DBGLOG(P2P, INFO, "p2pEalySuspendReg\n"); + p2pEalySuspendReg(prGlueInfo, rSetP2P.u4Enable); /* p2p remove */ + } + + DBGLOG(P2P, INFO, + "wlanoidSetP2pMode 0x%p %d %d\n", &rSetP2P, rSetP2P.u4Enable, rSetP2P.u4Mode); + rWlanStatus = kalIoctl(prGlueInfo, wlanoidSetP2pMode, + (PVOID)&rSetP2P, /* pu4IntBuf[0] is used as input SubCmd */ + sizeof(PARAM_CUSTOM_P2P_SET_STRUCT_T), + FALSE, FALSE, TRUE, FALSE, &u4BufLen); + DBGLOG(P2P, INFO, "wlanoidSetP2pMode ok\n"); + + /* move out to caller to avoid kalIoctrl & suspend/resume deadlock problem ALPS00844864 */ + if ((rSetP2P.u4Enable) && (g_u4HaltFlag == 0) && (fgIsResetting == FALSE)) { + /* fgIsP2PRegistered == TRUE means P2P on successfully */ + p2pEalySuspendReg(prGlueInfo, rSetP2P.u4Enable); /* p2p on */ + } + + if (rSetP2P.u4Enable) + p2pNetRegister(prGlueInfo, TRUE); + + GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); + g_u4P2POnOffing = 0; + GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); +#endif + } + break; +#endif + +#if (CFG_SUPPORT_MET_PROFILING == 1) + case PRIV_CMD_MET_PROFILING: + { + /* PARAM_CUSTOM_WFD_DEBUG_STRUCT_T rWfdDebugModeInfo; */ + /* rWfdDebugModeInfo.ucWFDDebugMode=(UINT_8)pu4IntBuf[1]; */ + /* rWfdDebugModeInfo.u2SNPeriod=(UINT_16)pu4IntBuf[2]; */ + /* DBGLOG(REQ, INFO,("WFD Debug Mode:%d Period:%d\n", */ + /* rWfdDebugModeInfo.ucWFDDebugMode,rWfdDebugModeInfo.u2SNPeriod)); */ + prGlueInfo->u8MetProfEnable = (UINT_8) pu4IntBuf[1]; + prGlueInfo->u16MetUdpPort = (UINT_16) pu4IntBuf[2]; + DBGLOG(REQ, INFO, "MET_PROF: Enable=%d UDP_PORT=%d\n", prGlueInfo->u8MetProfEnable, + prGlueInfo->u16MetUdpPort); + + } + break; + +#endif + case PRIV_CMD_WFD_DEBUG_CODE: + { + PARAM_CUSTOM_WFD_DEBUG_STRUCT_T rWfdDebugModeInfo; + + rWfdDebugModeInfo.ucWFDDebugMode = (UINT_8) pu4IntBuf[1]; + rWfdDebugModeInfo.u2SNPeriod = (UINT_16) pu4IntBuf[2]; + DBGLOG(REQ, INFO, "WFD Debug Mode:%d Period:%d\n", rWfdDebugModeInfo.ucWFDDebugMode, + rWfdDebugModeInfo.u2SNPeriod); + kalIoctl(prGlueInfo, wlanoidSetWfdDebugMode, (PVOID)&rWfdDebugModeInfo, + sizeof(PARAM_CUSTOM_WFD_DEBUG_STRUCT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + } + break; + default: + return -EOPNOTSUPP; + } + + return status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Private ioctl get int handler. +* +* \param[in] pDev Net device requested. +* \param[out] pIwReq Pointer to iwreq structure. +* \param[in] prIwReqData The ioctl req structure, use the field of sub-command. +* \param[out] pcExtra The buffer with put the return value +* +* \retval 0 For success. +* \retval -EOPNOTSUPP If cmd is not supported. +* \retval -EFAULT For fail. +* +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 gucBufDbgCode[1000]; + +static int +_priv_get_int(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + UINT_32 u4SubCmd; + PUINT_32 pu4IntBuf; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4BufLen = 0; + int status = 0; + P_NDIS_TRANSPORT_STRUCT prNdisReq; + + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + if (GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + u4SubCmd = (UINT_32) prIwReqData->mode; + pu4IntBuf = (PUINT_32) pcExtra; + + switch (u4SubCmd) { + case PRIV_CMD_TEST_CMD: + /* printk("CMD=0x%08lx, data=0x%08lx\n", pu4IntBuf[1], pu4IntBuf[2]); */ + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); + + prNdisReq->ndisOidCmd = OID_CUSTOM_MTK_WIFI_TEST; + prNdisReq->inNdisOidlength = 8; + prNdisReq->outNdisOidLength = 8; + + status = priv_get_ndis(prNetDev, prNdisReq, &u4BufLen); + if (status == 0) { + /* printk("Result=%ld\n", *(PUINT_32)&prNdisReq->ndisOidContent[4]); */ + prIwReqData->mode = *(PUINT_32) &prNdisReq->ndisOidContent[4]; + /* + * if (copy_to_user(prIwReqData->data.pointer, + * &prNdisReq->ndisOidContent[4], 4)) { + * printk(KERN_NOTICE "priv_get_int() copy_to_user oidBuf fail(3)\n"); + * return -EFAULT; + * } + */ + } + return status; + +#if CFG_SUPPORT_PRIV_MCR_RW + case PRIV_CMD_ACCESS_MCR: + /* printk("addr=0x%08lx\n", pu4IntBuf[1]); */ + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + if (!prGlueInfo->fgMcrAccessAllowed) { + status = 0; + return status; + } + + kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); + + prNdisReq->ndisOidCmd = OID_CUSTOM_MCR_RW; + prNdisReq->inNdisOidlength = 8; + prNdisReq->outNdisOidLength = 8; + + status = priv_get_ndis(prNetDev, prNdisReq, &u4BufLen); + if (status == 0) { + /* printk("Result=%ld\n", *(PUINT_32)&prNdisReq->ndisOidContent[4]); */ + prIwReqData->mode = *(PUINT_32) &prNdisReq->ndisOidContent[4]; + } + return status; +#endif + + case PRIV_CMD_DUMP_MEM: + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + +#if 1 + if (!prGlueInfo->fgMcrAccessAllowed) { + status = 0; + return status; + } +#endif + kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); + + prNdisReq->ndisOidCmd = OID_CUSTOM_MEM_DUMP; + prNdisReq->inNdisOidlength = 8; + prNdisReq->outNdisOidLength = 8; + + status = priv_get_ndis(prNetDev, prNdisReq, &u4BufLen); + if (status == 0) + prIwReqData->mode = *(PUINT_32) &prNdisReq->ndisOidContent[0]; + return status; + + case PRIV_CMD_SW_CTRL: + /* printk(" addr=0x%08lx\n", pu4IntBuf[1]); */ + + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); + + prNdisReq->ndisOidCmd = OID_CUSTOM_SW_CTRL; + prNdisReq->inNdisOidlength = 8; + prNdisReq->outNdisOidLength = 8; + + status = priv_get_ndis(prNetDev, prNdisReq, &u4BufLen); + if (status == 0) { + /* printk("Result=%ld\n", *(PUINT_32)&prNdisReq->ndisOidContent[4]); */ + prIwReqData->mode = *(PUINT_32) &prNdisReq->ndisOidContent[4]; + } + return status; + +#if 0 + case PRIV_CMD_BEACON_PERIOD: + status = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryBeaconInterval, + (PVOID) pu4IntBuf, sizeof(UINT_32), &u4BufLen); + return status; + + case PRIV_CMD_POWER_MODE: + status = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQuery802dot11PowerSaveProfile, + (PVOID) pu4IntBuf, sizeof(UINT_32), &u4BufLen); + return status; + + case PRIV_CMD_ADHOC_MODE: + status = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryAdHocMode, (PVOID) pu4IntBuf, sizeof(UINT_32), &u4BufLen); + return status; +#endif + + case PRIV_CMD_BAND_CONFIG: + DBGLOG(REQ, INFO, "CMD get_band=\n"); + prIwReqData->mode = 0; + return status; + + default: + break; + } + + u4SubCmd = (UINT_32) prIwReqData->data.flags; + + switch (u4SubCmd) { + case PRIV_CMD_GET_CH_LIST: + { + UINT_16 i, j = 0; + UINT_8 NumOfChannel = 50; + UINT_8 ucMaxChannelNum = 50; + INT_32 ch[50]; + /* RF_CHANNEL_INFO_T aucChannelList[50]; */ + P_RF_CHANNEL_INFO_T paucChannelList; + P_RF_CHANNEL_INFO_T ChannelList_t; + + paucChannelList = kalMemAlloc(sizeof(RF_CHANNEL_INFO_T) * 50, VIR_MEM_TYPE); + if (paucChannelList == NULL) { + DBGLOG(REQ, INFO, "alloc ChannelList fail\n"); + return -EFAULT; + } + kalMemZero(paucChannelList, sizeof(RF_CHANNEL_INFO_T) * 50); + kalGetChannelList(prGlueInfo, BAND_NULL, ucMaxChannelNum, &NumOfChannel, paucChannelList); + if (NumOfChannel > 50) { + ASSERT(0); + NumOfChannel = 50; + } + + ChannelList_t = paucChannelList; + if (kalIsAPmode(prGlueInfo)) { + for (i = 0; i < NumOfChannel; i++) { + if ((ChannelList_t->ucChannelNum <= 13) + || (ChannelList_t->ucChannelNum == 36 + || ChannelList_t->ucChannelNum == 40 + || ChannelList_t->ucChannelNum == 44 + || ChannelList_t->ucChannelNum == 48)) { + ch[j] = (INT_32) ChannelList_t->ucChannelNum; + ChannelList_t++; + j++; + } + } + } else { + for (j = 0; j < NumOfChannel; j++) { + ch[j] = (INT_32) ChannelList_t->ucChannelNum; + ChannelList_t++; + } + } + + kalMemFree(paucChannelList, VIR_MEM_TYPE, sizeof(RF_CHANNEL_INFO_T) * 50); + + prIwReqData->data.length = j; + if (copy_to_user(prIwReqData->data.pointer, ch, NumOfChannel * sizeof(INT_32))) + return -EFAULT; + else + return status; + } + + case PRIV_CMD_GET_BUILD_DATE_CODE: + { + UINT_8 aucBuffer[16]; + + if (kalIoctl(prGlueInfo, + wlanoidQueryBuildDateCode, + (PVOID) aucBuffer, + sizeof(UINT_8) * 16, TRUE, TRUE, TRUE, FALSE, &u4BufLen) == WLAN_STATUS_SUCCESS) { + prIwReqData->data.length = sizeof(UINT_8) * 16; + + if (copy_to_user(prIwReqData->data.pointer, aucBuffer, prIwReqData->data.length)) + return -EFAULT; + else + return status; + } else { + return -EFAULT; + } + } + + case PRIV_CMD_GET_DEBUG_CODE: + { + wlanQueryDebugCode(prGlueInfo->prAdapter); + + kalMemSet(gucBufDbgCode, '.', sizeof(gucBufDbgCode)); + u4BufLen = prIwReqData->data.length; + if (u4BufLen > sizeof(gucBufDbgCode)) + u4BufLen = sizeof(gucBufDbgCode); + if (copy_to_user(prIwReqData->data.pointer, gucBufDbgCode, u4BufLen)) + return -EFAULT; + else + return status; + } + + default: + return -EOPNOTSUPP; + } + + return status; +} /* priv_get_int */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Private ioctl set int array handler. +* +* \param[in] prNetDev Net device requested. +* \param[in] prIwReqInfo Pointer to iwreq structure. +* \param[in] prIwReqData The ioctl data structure, use the field of sub-command. +* \param[in] pcExtra The buffer with input value +* +* \retval 0 For success. +* \retval -EOPNOTSUPP If cmd is not supported. +* \retval -EINVAL If a value is out of range. +* +*/ +/*----------------------------------------------------------------------------*/ +static int +_priv_set_ints(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) +{ + UINT_32 u4SubCmd, u4BufLen, u4CmdLen; + 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 (GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + u4SubCmd = (UINT_32) prIwReqData->data.flags; + u4CmdLen = (UINT_32) prIwReqData->data.length; + + switch (u4SubCmd) { + case PRIV_CMD_SET_TX_POWER: + { + UINT_16 i, j; + INT_32 setting[4] = {0}; + + if (u4CmdLen > 4) + return -EINVAL; + if (copy_from_user(setting, prIwReqData->data.pointer, u4CmdLen)) + return -EFAULT; +#if !(CFG_SUPPORT_TX_POWER_BACK_OFF) + 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; +#else + +#if 0 + DBGLOG(REQ, INFO, "Tx power num = %d\n", prIwReqData->data.length); + + DBGLOG(REQ, INFO, "Tx power setting = %d %d %d %d\n", + setting[0], setting[1], setting[2], setting[3]); +#endif + prTxpwr = &prGlueInfo->rTxPwr; + if (setting[0] == 0 && prIwReqData->data.length == 4 /* argc num */) { + /* 0 (All networks), 1 (legacy STA), 2 (Hotspot AP), 3 (P2P), 4 (BT over Wi-Fi) */ + if (setting[1] == 1 || setting[1] == 0) { + if (setting[2] == 0 || setting[2] == 1) + prTxpwr->c2GLegacyStaPwrOffset = setting[3]; + if (setting[2] == 0 || setting[2] == 2) + prTxpwr->c5GLegacyStaPwrOffset = setting[3]; + } + if (setting[1] == 2 || setting[1] == 0) { + if (setting[2] == 0 || setting[2] == 1) + prTxpwr->c2GHotspotPwrOffset = setting[3]; + if (setting[2] == 0 || setting[2] == 2) + prTxpwr->c5GHotspotPwrOffset = setting[3]; + } + if (setting[1] == 3 || setting[1] == 0) { + if (setting[2] == 0 || setting[2] == 1) + prTxpwr->c2GP2pPwrOffset = setting[3]; + if (setting[2] == 0 || setting[2] == 2) + prTxpwr->c5GP2pPwrOffset = setting[3]; + } + if (setting[1] == 4 || setting[1] == 0) { + if (setting[2] == 0 || setting[2] == 1) + prTxpwr->c2GBowPwrOffset = setting[3]; + if (setting[2] == 0 || setting[2] == 2) + prTxpwr->c5GBowPwrOffset = setting[3]; + } + } else if (setting[0] == 1 && prIwReqData->data.length == 2) { + prTxpwr->ucConcurrencePolicy = setting[1]; + } else if (setting[0] == 2 && prIwReqData->data.length == 3) { + if (setting[1] == 0) { + for (i = 0; i < 14; i++) + prTxpwr->acTxPwrLimit2G[i] = setting[2]; + } else if (setting[1] <= 14) + prTxpwr->acTxPwrLimit2G[setting[1] - 1] = setting[2]; + } else if (setting[0] == 3 && prIwReqData->data.length == 3) { + if (setting[1] == 0) { + for (i = 0; i < 4; i++) + prTxpwr->acTxPwrLimit5G[i] = setting[2]; + } else if (setting[1] <= 4) + prTxpwr->acTxPwrLimit5G[setting[1] - 1] = setting[2]; + } else if (setting[0] == 4 && prIwReqData->data.length == 2) { + if (setting[1] == 0) + wlanDefTxPowerCfg(prGlueInfo->prAdapter); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetTxPower, + prTxpwr, + sizeof(SET_TXPWR_CTRL_T), TRUE, FALSE, FALSE, FALSE, &u4BufLen); + } else if (setting[0] == 5 && prIwReqData->data.length == 4) { + UINT_8 ch = setting[1]; + UINT_8 modulation = setting[2]; + INT_8 offset = setting[3]; + P_MITIGATED_PWR_BY_CH_BY_MODE pOffsetEntry; + + j = 0; + do { + pOffsetEntry = &(prTxpwr->arRlmMitigatedPwrByChByMode[j++]); + if (ch == 0) + break; + + if (ch == pOffsetEntry->channel) { + switch (modulation) { + case 0: + pOffsetEntry->mitigatedCckDsss = offset; + pOffsetEntry->mitigatedOfdm = offset; + pOffsetEntry->mitigatedHt20 = offset; + pOffsetEntry->mitigatedHt40 = offset; + break; + case 1: + pOffsetEntry->mitigatedCckDsss = offset; + break; + case 2: + pOffsetEntry->mitigatedOfdm = offset; + break; + case 3: + pOffsetEntry->mitigatedHt20 = offset; + break; + case 4: + pOffsetEntry->mitigatedHt40 = offset; + break; + default: + return -EFAULT; + } + } + } while (j < 40); + } else + return -EFAULT; +#endif + } + + return status; + default: + break; + } + + return status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Private ioctl get int array handler. +* +* \param[in] pDev Net device requested. +* \param[out] pIwReq Pointer to iwreq structure. +* \param[in] prIwReqData The ioctl req structure, use the field of sub-command. +* \param[out] pcExtra The buffer with put the return value +* +* \retval 0 For success. +* \retval -EOPNOTSUPP If cmd is not supported. +* \retval -EFAULT For fail. +* +*/ +/*----------------------------------------------------------------------------*/ +static int +_priv_get_ints(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + UINT_32 u4SubCmd; + P_GLUE_INFO_T prGlueInfo; + int status = 0; + INT_32 ch[50]; + + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + if (GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + u4SubCmd = (UINT_32) prIwReqData->data.flags; + + switch (u4SubCmd) { + case PRIV_CMD_GET_CH_LIST: + { + UINT_16 i; + UINT_8 NumOfChannel = 50; + UINT_8 ucMaxChannelNum = 50; + /*RF_CHANNEL_INFO_T aucChannelList[50];*/ + P_RF_CHANNEL_INFO_T paucChannelList; + P_RF_CHANNEL_INFO_T ChannelList_t; + + paucChannelList = kalMemAlloc(sizeof(RF_CHANNEL_INFO_T) * 50, VIR_MEM_TYPE); + if (paucChannelList == NULL) { + DBGLOG(REQ, INFO, "alloc fail\n"); + return -EINVAL; + } + kalMemZero(paucChannelList, sizeof(RF_CHANNEL_INFO_T) * 50); + + kalGetChannelList(prGlueInfo, BAND_NULL, ucMaxChannelNum, &NumOfChannel, paucChannelList); + if (NumOfChannel > 50) + NumOfChannel = 50; + + ChannelList_t = paucChannelList; + for (i = 0; i < NumOfChannel; i++) { + ch[i] = (INT_32) ChannelList_t->ucChannelNum; + ChannelList_t++; + } + + kalMemFree(paucChannelList, VIR_MEM_TYPE, sizeof(RF_CHANNEL_INFO_T) * 50); + prIwReqData->data.length = NumOfChannel; + if (copy_to_user(prIwReqData->data.pointer, ch, NumOfChannel * sizeof(INT_32))) + return -EFAULT; + else + return status; + } + default: + break; + } + + return status; +} /* priv_get_int */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Private ioctl set structure handler. +* +* \param[in] pDev Net device requested. +* \param[in] prIwReqData Pointer to iwreq_data structure. +* +* \retval 0 For success. +* \retval -EOPNOTSUPP If cmd is not supported. +* \retval -EINVAL If a value is out of range. +* +*/ +/*----------------------------------------------------------------------------*/ +static int +_priv_set_struct(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) +{ + UINT_32 u4SubCmd = 0; + int status = 0; + /* WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; */ + UINT_32 u4CmdLen = 0; + P_NDIS_TRANSPORT_STRUCT prNdisReq; +#if CFG_SUPPORT_TX_POWER_BACK_OFF + P_PARAM_MTK_WIFI_TEST_STRUCT_T prTestStruct; +#endif + + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + /* ASSERT(prIwReqInfo); */ + ASSERT(prIwReqData); + /* ASSERT(pcExtra); */ + + kalMemZero(&aucOidBuf[0], sizeof(aucOidBuf)); + + if (GLUE_CHK_PR2(prNetDev, prIwReqData) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + u4SubCmd = (UINT_32) prIwReqData->data.flags; + +#if 0 + DBGLOG(REQ, INFO, "priv_set_struct(): prIwReqInfo->cmd(0x%X), u4SubCmd(%ld)\n", + prIwReqInfo->cmd, u4SubCmd); +#endif + + switch (u4SubCmd) { +#if 0 /* PTA_ENABLED */ + case PRIV_CMD_BT_COEXIST: + u4CmdLen = prIwReqData->data.length * sizeof(UINT_32); + ASSERT(sizeof(PARAM_CUSTOM_BT_COEXIST_T) >= u4CmdLen); + if (sizeof(PARAM_CUSTOM_BT_COEXIST_T) < u4CmdLen) + return -EFAULT; + + if (copy_from_user(&aucOidBuf[0], prIwReqData->data.pointer, u4CmdLen)) { + status = -EFAULT; /* return -EFAULT; */ + break; + } + + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetBtCoexistCtrl, (PVOID)&aucOidBuf[0], u4CmdLen, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + status = -EFAULT; + break; +#endif + + case PRIV_CUSTOM_BWCS_CMD: + u4CmdLen = prIwReqData->data.length * sizeof(UINT_32); + ASSERT(sizeof(PARAM_PTA_IPC_T) >= u4CmdLen); + if (sizeof(PARAM_PTA_IPC_T) < u4CmdLen) + return -EFAULT; +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS && CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(REQ, INFO, + "ucCmdLen = %d, size of PTA_IPC_T = %d, prIwReqData->data = 0x%x.\n", u4CmdLen, + sizeof(PARAM_PTA_IPC_T), prIwReqData->data); + + DBGLOG(REQ, INFO, "priv_set_struct(): prIwReqInfo->cmd(0x%X), u4SubCmd(%u)\n", + prIwReqInfo->cmd, u4SubCmd); + + DBGLOG(REQ, INFO, "*pcExtra = 0x%x\n", *pcExtra); +#endif + + if (copy_from_user(&aucOidBuf[0], prIwReqData->data.pointer, u4CmdLen)) { + status = -EFAULT; /* return -EFAULT; */ + break; + } +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS && CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(REQ, INFO, "priv_set_struct(): BWCS CMD = %02x%02x%02x%02x\n", + aucOidBuf[2], aucOidBuf[3], aucOidBuf[4], aucOidBuf[5]); +#endif + +#if 0 + status = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetBT, (PVOID)&aucOidBuf[0], u4CmdLen, &u4BufLen); +#endif + +#if 1 + status = wlanoidSetBT(prGlueInfo->prAdapter, (PVOID)&aucOidBuf[0], u4CmdLen, &u4BufLen); +#endif + + if (status != WLAN_STATUS_SUCCESS) + status = -EFAULT; + + break; + +#if CFG_SUPPORT_WPS2 + case PRIV_CMD_WSC_PROBE_REQ: + { + /* retrieve IE for Probe Request */ + u4CmdLen = prIwReqData->data.length; + if (u4CmdLen > GLUE_INFO_WSCIE_LENGTH) { + DBGLOG(REQ, ERROR, "Input data length is invalid %u\n", u4CmdLen); + return -EINVAL; + } + + if (u4CmdLen > 0) { + if (copy_from_user(prGlueInfo->aucWSCIE, prIwReqData->data.pointer, u4CmdLen)) { + DBGLOG(REQ, ERROR, "Copy from user failed\n"); + status = -EFAULT; + break; + } + prGlueInfo->u2WSCIELen = u4CmdLen; + } else { + prGlueInfo->u2WSCIELen = 0; + } + } + break; +#endif + case PRIV_CMD_OID: + u4CmdLen = prIwReqData->data.length; + if (u4CmdLen > CMD_OID_BUF_LENGTH) { + DBGLOG(REQ, ERROR, "Input data length is invalid %u\n", u4CmdLen); + return -EINVAL; + } + + if (copy_from_user(&aucOidBuf[0], prIwReqData->data.pointer, u4CmdLen)) { + status = -EFAULT; + break; + } + if (!kalMemCmp(&aucOidBuf[0], pcExtra, u4CmdLen)) + 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: + u4CmdLen = prIwReqData->data.length; + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + if (u4CmdLen > sizeof(prNdisReq->ndisOidContent)) { + DBGLOG(REQ, ERROR, "Input data length is invalid %u\n", u4CmdLen); + return -EINVAL; + } + + if (copy_from_user(&prNdisReq->ndisOidContent[0], prIwReqData->data.pointer, u4CmdLen)) { + 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; + +#if CFG_SUPPORT_TX_POWER_BACK_OFF + case PRIV_CMD_SET_TX_POWER: + { + P_REG_INFO_T prRegInfo = &prGlueInfo->rRegInfo; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT8 cStartTxBackOff = 0; + BOOLEAN bFgForceExecution = FALSE; + /* TxPwrBackOffParam's 0th byte contains enable/disable TxPowerBackOff for 2G */ + /* TxPwrBackOffParam's 1st byte contains default TxPowerBackOff value for 2G */ + /* TxPwrBackOffParam's 2nd byte contains enable/disable TxPowerBackOff for 5G */ + /* TxPwrBackOffParam's 3rd byte contains default TxPowerBackOff value for 5G */ + + ULONG TxPwrBackOffParam = 0; + + u4CmdLen = prIwReqData->data.length; + prTestStruct = (P_PARAM_MTK_WIFI_TEST_STRUCT_T)&aucOidBuf[0]; + + if (u4CmdLen > sizeof(aucOidBuf)) { + DBGLOG(REQ, ERROR, "SET_TX_POWER: Input data length is invalid %u\n", u4CmdLen); + return -EINVAL; + } + if (copy_from_user(prTestStruct, prIwReqData->data.pointer, u4CmdLen)) { + DBGLOG(REQ, INFO, "SET_TX_POWER: copy from user failed\n"); + return -EFAULT; + } + + DBGLOG(REQ, INFO, "%s: SET_TX_POWER FuncIndex:%u\n", + __func__, prTestStruct->u4FuncIndex); + DBGLOG(REQ, INFO, "FuncData:%u[0x%x], FuncData2:%u[0x%x]\n", + prTestStruct->u4FuncData, + prTestStruct->u4FuncData, + prTestStruct->u4FuncData2, + prTestStruct->u4FuncData2); + DBGLOG(REQ, INFO, "Enable2G:%d, MaxPower2G:%u\n", + prRegInfo->bTxPowerLimitEnable2G, + prRegInfo->cTxBackOffMaxPower2G); + DBGLOG(REQ, INFO, "Enable5G:%d, MaxPower5G:%u\n", + prRegInfo->bTxPowerLimitEnable5G, + prRegInfo->cTxBackOffMaxPower5G); + + /* u4FuncData: start or stop */ + cStartTxBackOff = prTestStruct->u4FuncData; + + /* + * u4FuncData2: used in dynamiclly set back off from ioctl + * with a specific power value. + * if u4FuncData2 is not 0, driver will force to send cmd to firmware. + */ + if (prTestStruct->u4FuncData2 != 0) + bFgForceExecution = TRUE; + + if ((prRegInfo->bTxPowerLimitEnable2G == TRUE) + || (prRegInfo->bTxPowerLimitEnable5G == TRUE) + || bFgForceExecution) { + if (cStartTxBackOff == TRUE) { + UINT_8 ucTxBackOffMaxPower = prTestStruct->u4FuncData2 * 2; + + if (ucTxBackOffMaxPower != 0) { + prRegInfo->cTxBackOffMaxPower2G = ucTxBackOffMaxPower; + prRegInfo->bTxPowerLimitEnable2G = 1; + } + TxPwrBackOffParam |= prRegInfo->bTxPowerLimitEnable2G; + TxPwrBackOffParam |= (prRegInfo->cTxBackOffMaxPower2G) << 8; + if (ucTxBackOffMaxPower != 0) { + prRegInfo->cTxBackOffMaxPower5G = ucTxBackOffMaxPower; + prRegInfo->bTxPowerLimitEnable5G = 1; + } + TxPwrBackOffParam |= prRegInfo->bTxPowerLimitEnable5G << 16; + TxPwrBackOffParam |= (ULONG)(prRegInfo->cTxBackOffMaxPower5G) << 24; + DBGLOG(REQ, INFO, + "Start BackOff: TxPwrBackOffParam=0x%lx\n", + TxPwrBackOffParam); + } else { + TxPwrBackOffParam = 0; /* First byte is start/stop */ + DBGLOG(REQ, INFO, + "Stop BackOff: TxPwrBackOffParam=0x%lx\n", + TxPwrBackOffParam); + } + rStatus = nicTxPowerBackOff(prGlueInfo->prAdapter, TxPwrBackOffParam); + if (rStatus == WLAN_STATUS_PENDING) + status = 0; + else + status = -EINVAL; + } + } + break; +#endif + + case PRIV_CMD_GET_WIFI_TYPE: + { + int32_t i4ResultLen; + + u4CmdLen = prIwReqData->data.length; + if (u4CmdLen >= CMD_OID_BUF_LENGTH) { + DBGLOG(REQ, ERROR, + "u4CmdLen:%u >= CMD_OID_BUF_LENGTH:%d\n", + u4CmdLen, CMD_OID_BUF_LENGTH); + return -EINVAL; + } + + if (copy_from_user(&aucOidBuf[0], + prIwReqData->data.pointer, + u4CmdLen)) { + DBGLOG(REQ, ERROR, "copy_from_user fail\n"); + return -EFAULT; + } + + aucOidBuf[u4CmdLen] = 0; + i4ResultLen = priv_driver_cmds(prNetDev, aucOidBuf, + u4CmdLen); + if (i4ResultLen > 1) { + if (copy_to_user(prIwReqData->data.pointer, + &aucOidBuf[0], i4ResultLen)) { + DBGLOG(REQ, ERROR, + "copy_to_user fail\n"); + return -EFAULT; + } + prIwReqData->data.length = i4ResultLen; + } else { + DBGLOG(REQ, ERROR, + "i4ResultLen:%d <= 1\n", i4ResultLen); + return -EFAULT; + } + + } + break; + + default: + return -EOPNOTSUPP; + } + + return status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Private ioctl get struct handler. +* +* \param[in] pDev Net device requested. +* \param[out] pIwReq Pointer to iwreq structure. +* \param[in] cmd Private sub-command. +* +* \retval 0 For success. +* \retval -EFAULT If copy from user space buffer fail. +* \retval -EOPNOTSUPP Parameter "cmd" not recognized. +* +*/ +/*----------------------------------------------------------------------------*/ +static int +_priv_get_struct(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + UINT_32 u4SubCmd = 0; + P_NDIS_TRANSPORT_STRUCT prNdisReq = NULL; + + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4BufLen = 0; + int status = 0; + + kalMemZero(&aucOidBuf[0], sizeof(aucOidBuf)); + + ASSERT(prNetDev); + ASSERT(prIwReqData); + if (!prNetDev || !prIwReqData) { + DBGLOG(REQ, INFO, "priv_get_struct(): invalid param(0x%p, 0x%p)\n", prNetDev, prIwReqData); + return -EINVAL; + } + + u4SubCmd = (UINT_32) prIwReqData->data.flags; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, "priv_get_struct(): invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, *((P_GLUE_INFO_T *) netdev_priv(prNetDev))); + return -EINVAL; + } +#if 0 + DBGLOG(REQ, INFO, "priv_get_struct(): prIwReqInfo->cmd(0x%X), u4SubCmd(%ld)\n", + prIwReqInfo->cmd, u4SubCmd); +#endif + memset(aucOidBuf, 0, sizeof(aucOidBuf)); + + switch (u4SubCmd) { + case PRIV_CMD_OID: + if (copy_from_user(&aucOidBuf[0], prIwReqData->data.pointer, sizeof(NDIS_TRANSPORT_STRUCT))) { + DBGLOG(REQ, INFO, "priv_get_struct() copy_from_user oidBuf fail\n"); + return -EFAULT; + } + + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; +#if 0 + DBGLOG(REQ, INFO, "\n priv_get_struct cmd 0x%02x len:%d OID:0x%08x OID Len:%d\n", + cmd, pIwReq->u.data.length, ndisReq->ndisOidCmd, ndisReq->inNdisOidlength); +#endif + if (priv_get_ndis(prNetDev, prNdisReq, &u4BufLen) == 0) { + prNdisReq->outNdisOidLength = u4BufLen; + if (copy_to_user(prIwReqData->data.pointer, + &aucOidBuf[0], + u4BufLen + sizeof(NDIS_TRANSPORT_STRUCT) - + sizeof(prNdisReq->ndisOidContent))) { + DBGLOG(REQ, INFO, "priv_get_struct() copy_to_user oidBuf fail(1)\n"); + return -EFAULT; + } + return 0; + } + prNdisReq->outNdisOidLength = u4BufLen; + if (copy_to_user(prIwReqData->data.pointer, + &aucOidBuf[0], OFFSET_OF(NDIS_TRANSPORT_STRUCT, ndisOidContent))) { + DBGLOG(REQ, INFO, "priv_get_struct() copy_to_user oidBuf fail(2)\n"); + } + return -EFAULT; + + case PRIV_CMD_SW_CTRL: + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + if (prIwReqData->data.length > sizeof(prNdisReq->ndisOidContent)) { + DBGLOG(REQ, INFO, "priv_get_struct() exceeds length limit\n"); + return -EFAULT; + } + + if (copy_from_user(&prNdisReq->ndisOidContent[0], + prIwReqData->data.pointer, + prIwReqData->data.length)) { + DBGLOG(REQ, INFO, "priv_get_struct() copy_from_user oidBuf fail\n"); + return -EFAULT; + } + + prNdisReq->ndisOidCmd = OID_CUSTOM_SW_CTRL; + prNdisReq->inNdisOidlength = 8; + prNdisReq->outNdisOidLength = 8; + + status = priv_get_ndis(prNetDev, prNdisReq, &u4BufLen); + if (status == 0) { + prNdisReq->outNdisOidLength = u4BufLen; + /* printk("len=%d Result=%08lx\n", u4BufLen, *(PUINT_32)&prNdisReq->ndisOidContent[4]); */ + + if (copy_to_user(prIwReqData->data.pointer, + &prNdisReq->ndisOidContent[4], + 4 /* OFFSET_OF(NDIS_TRANSPORT_STRUCT, ndisOidContent) */)) { + DBGLOG(REQ, INFO, "priv_get_struct() copy_to_user oidBuf fail(2)\n"); + } + } + return 0; + + default: + DBGLOG(REQ, WARN, "get struct cmd:0x%x\n", u4SubCmd); + return -EOPNOTSUPP; + } +} /* priv_get_struct */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The routine handles a set operation for a single OID. +* +* \param[in] pDev Net device requested. +* \param[in] ndisReq Ndis request OID information copy from user. +* \param[out] outputLen_p If the call is successful, returns the number of +* bytes written into the query buffer. If the +* call failed due to invalid length of the query +* buffer, returns the amount of storage needed.. +* +* \retval 0 On success. +* \retval -EOPNOTSUPP If cmd is not supported. +* +*/ +/*----------------------------------------------------------------------------*/ +static int +priv_set_ndis(IN struct net_device *prNetDev, IN NDIS_TRANSPORT_STRUCT * prNdisReq, OUT PUINT_32 pu4OutputLen) +{ + P_WLAN_REQ_ENTRY prWlanReqEntry = NULL; + WLAN_STATUS status = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4SetInfoLen = 0; + + ASSERT(prNetDev); + ASSERT(prNdisReq); + ASSERT(pu4OutputLen); + + if (!prNetDev || !prNdisReq || !pu4OutputLen) { + DBGLOG(REQ, INFO, "priv_set_ndis(): invalid param(0x%p, 0x%p, 0x%p)\n", + prNetDev, prNdisReq, pu4OutputLen); + return -EINVAL; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, "priv_set_ndis(): invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, *((P_GLUE_INFO_T *) netdev_priv(prNetDev))); + return -EINVAL; + } +#if 0 + DBGLOG(REQ, INFO, "priv_set_ndis(): prNdisReq->ndisOidCmd(0x%lX)\n", prNdisReq->ndisOidCmd); +#endif + + if (reqSearchSupportedOidEntry(prNdisReq->ndisOidCmd, &prWlanReqEntry) == FALSE) { + DBGLOG(REQ, WARN, "Unknown oid: %d\n", prNdisReq->ndisOidCmd); + /* WARNLOG(("Set OID: 0x%08lx (unknown)\n", prNdisReq->ndisOidCmd)); */ + return -EOPNOTSUPP; + } + + if (prWlanReqEntry->pfOidSetHandler == NULL) { + DBGLOG(REQ, WARN, "No oid handler for %d\n", prNdisReq->ndisOidCmd); + /* WARNLOG(("Set %s: Null set handler\n", prWlanReqEntry->pucOidName)); */ + return -EOPNOTSUPP; + } +#if 0 + DBGLOG(REQ, INFO, "priv_set_ndis(): %s\n", prWlanReqEntry->pucOidName); +#endif + + if (prWlanReqEntry->fgSetBufLenChecking) { + if (prNdisReq->inNdisOidlength != prWlanReqEntry->u4InfoBufLen) { + DBGLOG(REQ, WARN, "Set %s: Invalid length (current=%u, needed=%u)\n", + prWlanReqEntry->pucOidName, + prNdisReq->inNdisOidlength, prWlanReqEntry->u4InfoBufLen); + + *pu4OutputLen = prWlanReqEntry->u4InfoBufLen; + return -EINVAL; + } + } + + if (prWlanReqEntry->eOidMethod == ENUM_OID_GLUE_ONLY) { + /* GLUE sw info only */ + status = prWlanReqEntry->pfOidSetHandler(prGlueInfo, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, &u4SetInfoLen); + } else if (prWlanReqEntry->eOidMethod == ENUM_OID_GLUE_EXTENSION) { + /* multiple sw operations */ + status = prWlanReqEntry->pfOidSetHandler(prGlueInfo, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, &u4SetInfoLen); + } else if (prWlanReqEntry->eOidMethod == ENUM_OID_DRIVER_CORE) { + /* driver core */ + + status = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC) prWlanReqEntry->pfOidSetHandler, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + } else { + DBGLOG(REQ, INFO, "priv_set_ndis(): unsupported OID method:0x%x\n", prWlanReqEntry->eOidMethod); + return -EOPNOTSUPP; + } + + *pu4OutputLen = u4SetInfoLen; + + switch (status) { + case WLAN_STATUS_SUCCESS: + break; + + case WLAN_STATUS_INVALID_LENGTH: + /* WARNLOG(("Set %s: Invalid length (current=%ld, needed=%ld)\n", */ + /* prWlanReqEntry->pucOidName, */ + /* prNdisReq->inNdisOidlength, */ + /* u4SetInfoLen)); */ + break; + } + + if (status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return 0; +} /* priv_set_ndis */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The routine handles a query operation for a single OID. Basically we +* return information about the current state of the OID in question. +* +* \param[in] pDev Net device requested. +* \param[in] ndisReq Ndis request OID information copy from user. +* \param[out] outputLen_p If the call is successful, returns the number of +* bytes written into the query buffer. If the +* call failed due to invalid length of the query +* buffer, returns the amount of storage needed.. +* +* \retval 0 On success. +* \retval -EOPNOTSUPP If cmd is not supported. +* \retval -EINVAL invalid input parameters +* +*/ +/*----------------------------------------------------------------------------*/ +static int +priv_get_ndis(IN struct net_device *prNetDev, IN NDIS_TRANSPORT_STRUCT * prNdisReq, OUT PUINT_32 pu4OutputLen) +{ + P_WLAN_REQ_ENTRY prWlanReqEntry = NULL; + UINT_32 u4BufLen = 0; + WLAN_STATUS status = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prNetDev); + ASSERT(prNdisReq); + ASSERT(pu4OutputLen); + + if (!prNetDev || !prNdisReq || !pu4OutputLen) { + DBGLOG(REQ, INFO, "priv_get_ndis(): invalid param(0x%p, 0x%p, 0x%p)\n", + prNetDev, prNdisReq, pu4OutputLen); + return -EINVAL; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, "priv_get_ndis(): invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, *((P_GLUE_INFO_T *) netdev_priv(prNetDev))); + return -EINVAL; + } +#if 0 + DBGLOG(REQ, INFO, "priv_get_ndis(): prNdisReq->ndisOidCmd(0x%lX)\n", prNdisReq->ndisOidCmd); +#endif + + if (reqSearchSupportedOidEntry(prNdisReq->ndisOidCmd, &prWlanReqEntry) == FALSE) { + DBGLOG(REQ, WARN, "Unknown oid: %d\n", prNdisReq->ndisOidCmd); + /* WARNLOG(("Query OID: 0x%08lx (unknown)\n", prNdisReq->ndisOidCmd)); */ + return -EOPNOTSUPP; + } + + if (prWlanReqEntry->pfOidQueryHandler == NULL) { + DBGLOG(REQ, WARN, "No oid handler for %d\n", prNdisReq->ndisOidCmd); + /* WARNLOG(("Query %s: Null query handler\n", prWlanReqEntry->pucOidName)); */ + return -EOPNOTSUPP; + } +#if 0 + DBGLOG(REQ, INFO, "priv_get_ndis(): %s\n", prWlanReqEntry->pucOidName); +#endif + + if (prWlanReqEntry->fgQryBufLenChecking) { + if (prNdisReq->inNdisOidlength < prWlanReqEntry->u4InfoBufLen) { + /* Not enough room in InformationBuffer. Punt */ + /* WARNLOG(("Query %s: Buffer too short (current=%ld, needed=%ld)\n", */ + /* prWlanReqEntry->pucOidName, */ + /* prNdisReq->inNdisOidlength, */ + /* prWlanReqEntry->u4InfoBufLen)); */ + + *pu4OutputLen = prWlanReqEntry->u4InfoBufLen; + + status = WLAN_STATUS_INVALID_LENGTH; + return -EINVAL; + } + } + + if (prWlanReqEntry->eOidMethod == ENUM_OID_GLUE_ONLY) { + /* GLUE sw info only */ + status = prWlanReqEntry->pfOidQueryHandler(prGlueInfo, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, &u4BufLen); + } else if (prWlanReqEntry->eOidMethod == ENUM_OID_GLUE_EXTENSION) { + /* multiple sw operations */ + status = prWlanReqEntry->pfOidQueryHandler(prGlueInfo, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, &u4BufLen); + } else if (prWlanReqEntry->eOidMethod == ENUM_OID_DRIVER_CORE) { + /* driver core */ + + status = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC) prWlanReqEntry->pfOidQueryHandler, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, TRUE, TRUE, TRUE, FALSE, &u4BufLen); + } else { + DBGLOG(REQ, INFO, "priv_get_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 (status != WLAN_STATUS_SUCCESS) + return -EOPNOTSUPP; + + return 0; +} /* priv_get_ndis */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Parse command value in a string. +* +* @param InStr Pointer to the string buffer. +* @param OutStr Pointer to the next command value. +* @param OutLen Record the resident buffer length. +* +* @retval Command value. +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 CmdStringDecParse(IN UINT_8 *InStr, OUT UINT_8 **OutStr, OUT UINT_32 *OutLen) +{ + unsigned char Charc, *Buf; + unsigned int Num; + int Maxloop; + int ReadId; + int TotalLen; + + /* init */ + Num = 0; + Maxloop = 0; + ReadId = 0; + Buf = (unsigned char *)InStr; + TotalLen = *OutLen; + *OutStr = Buf; + + /* sanity check */ + if (Buf[0] == 0x00) + return 0; + + /* check the value is decimal or hex */ + if ((Buf[ReadId] == 'x') || ((Buf[ReadId] == '0') && (Buf[ReadId + 1] == 'x'))) { + /* skip x or 0x */ + if (Buf[ReadId] == 'x') + ReadId++; + else + ReadId += 2; + + /* translate the hex number */ + while (Maxloop++ < 10) { + Charc = Buf[ReadId]; + if ((Charc >= 0x30) && (Charc <= 0x39)) + Charc -= 0x30; + else if ((Charc >= 'a') && (Charc <= 'f')) + Charc -= 'a'; + else if ((Charc >= 'A') && (Charc <= 'F')) + Charc -= 'A'; + else + break; /* exit the parsing */ + Num = Num * 16 + Charc + 10; + ReadId++; + TotalLen--; + } + } else { + /* translate the decimal number */ + while (Maxloop++ < 10) { + Charc = Buf[ReadId]; + if ((Charc < 0x30) || (Charc > 0x39)) + break; /* exit the parsing */ + Charc -= 0x30; + Num = Num * 10 + Charc; + ReadId++; + TotalLen--; + } + } + + if (Buf[ReadId] == 0x00) + *OutStr = &Buf[ReadId]; + else + *OutStr = &Buf[ReadId + 1]; /* skip the character: _ */ + + *OutLen = TotalLen - 1; /* skip the character: _ */ + return Num; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Parse command MAC address in a string. +* +* @param InStr Pointer to the string buffer. +* @param OutStr Pointer to the next command value. +* @param OutLen Record the resident buffer length. +* +* @retval Command value. +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 CmdStringMacParse(IN UINT_8 *InStr, OUT UINT_8 **OutStr, OUT UINT_32 *OutLen, OUT UINT_8 *OutMac) +{ + unsigned char Charc, *Buf; + unsigned int Num; + int Maxloop; + int ReadId; + int TotalLen; + + /* init */ + Num = 0; + Maxloop = 0; + ReadId = 0; + Buf = (unsigned char *)InStr; + TotalLen = *OutLen; + *OutStr = Buf; + + /* sanity check */ + if (Buf[0] == 0x00) + return 0; + + /* parse MAC */ + while (Maxloop < 6) { + Charc = Buf[ReadId]; + if ((Charc >= 0x30) && (Charc <= 0x39)) + Charc -= 0x30; + else if ((Charc >= 'a') && (Charc <= 'f')) + Charc = Charc - 'a' + 10; + else if ((Charc >= 'A') && (Charc <= 'F')) + Charc = Charc - 'A' + 10; + else + return -1; /* error, exit the parsing */ + + Num = Charc; + ReadId++; + TotalLen--; + + Charc = Buf[ReadId]; + if ((Charc >= 0x30) && (Charc <= 0x39)) + Charc -= 0x30; + else if ((Charc >= 'a') && (Charc <= 'f')) + Charc = Charc - 'a' + 10; + else if ((Charc >= 'A') && (Charc <= 'F')) + Charc = Charc - 'A' + 10; + else + return -1; /* error, exit the parsing */ + + Num = Num * 16 + Charc; + ReadId += 2; /* skip the character and ':' */ + TotalLen -= 2; + + OutMac[Maxloop] = Num; + Maxloop++; + } + + *OutStr = &Buf[ReadId]; /* skip the character: _ */ + *OutLen = TotalLen; /* skip the character: _ */ + return Num; +} +#if CFG_SUPPORT_NCHO +/* do not include 0x or x, string to Hexadecimal */ +UINT_8 CmdString2HexParse(IN UINT_8 *InStr, OUT UINT_8 **OutStr, OUT UINT_8 *OutLen) +{ + unsigned char Charc, *Buf; + unsigned char ucNum; + int Maxloop; + int ReadId; + int TotalLen; + + /* init */ + ucNum = 0; + Maxloop = 0; + ReadId = 0; + Buf = (unsigned char *)InStr; + TotalLen = *OutLen; + *OutStr = Buf; + + /* sanity check */ + if (TotalLen <= 0) + return 0; + if (Buf[0] == 0x00) + return 0; + { + while (Maxloop++ < 2) { + Charc = Buf[ReadId]; + if ((Charc >= 0x30) && (Charc <= 0x39)) { + Charc -= 0x30; + } else if ((Charc >= 'a') && (Charc <= 'f')) { + Charc -= 'a'; + Charc += 10; + } else if ((Charc >= 'A') && (Charc <= 'F')) { + Charc -= 'A'; + Charc += 10; + } else { + break; /* exit the parsing */ + } + ucNum = ucNum * 16 + Charc; + ReadId++; + TotalLen--; + } + } + + *OutStr = &Buf[ReadId]; + *OutLen = TotalLen; + return ucNum; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The routine handles a set operation for a single OID. +* +* \param[in] pDev Net device requested. +* \param[in] ndisReq Ndis request OID information copy from user. +* \param[out] outputLen_p If the call is successful, returns the number of +* bytes written into the query buffer. If the +* call failed due to invalid length of the query +* buffer, returns the amount of storage needed.. +* +* \retval 0 On success. +* \retval -EOPNOTSUPP If cmd is not supported. +* +*/ +/*----------------------------------------------------------------------------*/ +static int +_priv_set_string(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) +{ + P_GLUE_INFO_T GlueInfo; + INT_32 status = 0; + UINT_32 subcmd; + UINT_8 *pucInBuf = aucOidBuf; + UINT_32 u4BufLen; + + /* sanity check */ + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + + + if (GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra) == FALSE) + return -EINVAL; + + u4BufLen = prIwReqData->data.length; + GlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (u4BufLen > CMD_OID_BUF_LENGTH) { + DBGLOG(REQ, ERROR, "Input data length is invalid %u\n", u4BufLen); + return -EINVAL; + } + + if (copy_from_user(pucInBuf, prIwReqData->data.pointer, u4BufLen)) + return -EFAULT; + + DBGLOG(REQ, INFO, "orig str cmd %s, %u\n", pucInBuf, u4BufLen); + + subcmd = CmdStringDecParse(pucInBuf, &pucInBuf, &u4BufLen); + DBGLOG(REQ, INFO, "priv_set_string> command = %u\n", (UINT32) subcmd); + + /* handle the command */ + switch (subcmd) { +#if (CFG_SUPPORT_TDLS == 1) + case PRIV_CMD_OTHER_TDLS: + TdlsexCmd(GlueInfo, pucInBuf, u4BufLen); + break; +#endif /* CFG_SUPPORT_TDLS */ + +#if (CFG_SUPPORT_TXR_ENC == 1) + case PRIV_CMD_OTHER_TAR: + { + rlmCmd(GlueInfo, pucInBuf, u4BufLen); + break; + } +#endif /* CFG_SUPPORT_TXR_ENC */ + case PRIV_CMD_OTHER: + { + INT_32 i4BytesWritten; + + if (!kalStrniCmp(pucInBuf, "addts", 5) || !kalStrniCmp(pucInBuf, "delts", 5)) + kalIoctl(GlueInfo, wlanoidTspecOperation, (PVOID)pucInBuf, + u4BufLen, FALSE, FALSE, FALSE, FALSE, &i4BytesWritten); + else if (!kalStrniCmp(pucInBuf, "RM-IT", 5)) + kalIoctl(GlueInfo, wlanoidRadioMeasurementIT, (PVOID)(pucInBuf+6), + u4BufLen, FALSE, FALSE, FALSE, FALSE, &i4BytesWritten); + break; + } + default: + break; + } + + return status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The routine handles a get 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_get_string(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) +{ + UINT_32 u4SubCmd = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + int status = 0; + + if (!prNetDev || !prIwReqData || !pcExtra) { + 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)); + 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 (copy_from_user(pcExtra, prIwReqData->data.pointer, prIwReqData->data.length)) { + DBGLOG(REQ, INFO, "copy from user failed\n"); + return -EFAULT; + } + switch (u4SubCmd) { + case PRIV_CMD_DUMP_DRIVER: + { + INT_32 i4BytesWritten = 0; + + if (!kalStrniCmp(pcExtra, "dumpts", 6)) + kalIoctl(prGlueInfo, wlanoidTspecOperation, (PVOID)pcExtra, + 512, FALSE, FALSE, FALSE, FALSE, &i4BytesWritten); + else if (!kalStrniCmp(pcExtra, "dumpuapsd", 9)) + kalIoctl(prGlueInfo, wlanoidDumpUapsdSetting, (PVOID)pcExtra, + 512, FALSE, FALSE, FALSE, FALSE, &i4BytesWritten); + prIwReqData->data.length = i4BytesWritten; + DBGLOG(REQ, INFO, "returned Bytes %d\n", i4BytesWritten); + break; + } + default: + DBGLOG(REQ, WARN, "Unknown SubCmd %u with param %s\n", u4SubCmd, pcExtra); + break; + } + return status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to search desired OID. +* +* \param rOid[in] Desired NDIS_OID +* \param ppWlanReqEntry[out] Found registered OID entry +* +* \retval TRUE: Matched OID is found +* \retval FALSE: No matched OID is found +*/ +/*----------------------------------------------------------------------------*/ +static BOOLEAN reqSearchSupportedOidEntry(IN UINT_32 rOid, OUT P_WLAN_REQ_ENTRY *ppWlanReqEntry) +{ + INT_32 i, j, k; + + i = 0; + j = NUM_SUPPORTED_OIDS - 1; + + while (i <= j) { + k = (i + j) / 2; + + if (rOid == arWlanOidReqTable[k].rOid) { + *ppWlanReqEntry = &arWlanOidReqTable[k]; + return TRUE; + } else if (rOid < arWlanOidReqTable[k].rOid) { + j = k - 1; + } else { + i = k + 1; + } + } + + return FALSE; +} /* reqSearchSupportedOidEntry */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Private ioctl driver 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_set_driver(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + uint32_t u4SubCmd = 0; + uint16_t u2Cmd = 0; + + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + + ASSERT(prNetDev); + ASSERT(prIwReqData); + if (!prNetDev || !prIwReqData) { + DBGLOG(REQ, INFO, + "priv_set_driver(): invalid param(0x%p, 0x%p)\n", + prNetDev, prIwReqData); + return -EINVAL; + } + + u2Cmd = prIwReqInfo->cmd; + DBGLOG(REQ, INFO, "prIwReqInfo->cmd %u\n", u2Cmd); + + u4SubCmd = (uint32_t) prIwReqData->data.flags; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, + "priv_set_driver(): invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, + *((struct GLUE_INFO **) netdev_priv(prNetDev))); + return -EINVAL; + } + + /* trick,hack in ./net/wireless/wext-priv.c ioctl_private_iw_point */ + /* because the cmd number is odd (get), the input string will not be + * copy_to_user + */ + + DBGLOG(REQ, INFO, "prIwReqData->data.length %u\n", + prIwReqData->data.length); + + /* Use GET type becauase large data by iwpriv. */ + + ASSERT(IW_IS_GET(u2Cmd)); + if (prIwReqData->data.length != 0) { + if (!access_ok(VERIFY_READ, prIwReqData->data.pointer, + prIwReqData->data.length)) { + DBGLOG(REQ, INFO, + "%s access_ok Read fail written = %d\n", + __func__, i4BytesWritten); + return -EFAULT; + } + if (copy_from_user(pcExtra, prIwReqData->data.pointer, + prIwReqData->data.length)) { + DBGLOG(REQ, INFO, + "%s copy_form_user fail written = %d\n", + __func__, prIwReqData->data.length); + return -EFAULT; + } + /* prIwReqData->data.length include the terminate '\0' */ + pcExtra[prIwReqData->data.length - 1] = 0; + } + + if (pcExtra) { + DBGLOG(REQ, INFO, "pcExtra %s\n", pcExtra); + /* Please check max length in rIwPrivTable */ + DBGLOG(REQ, INFO, "%s prIwReqData->data.length = %d\n", + __func__, prIwReqData->data.length); + + i4BytesWritten = priv_driver_cmds(prNetDev, pcExtra, + 2000 /*prIwReqData->data.length */); + DBGLOG(REQ, INFO, "%s i4BytesWritten = %d\n", __func__, + i4BytesWritten); + } + + DBGLOG(REQ, INFO, "pcExtra done\n"); + + if (i4BytesWritten > 0) { + if (i4BytesWritten > 2000) + i4BytesWritten = 2000; + prIwReqData->data.length = + i4BytesWritten; /* the iwpriv will use the length */ + } else if (i4BytesWritten == 0) { + prIwReqData->data.length = i4BytesWritten; + } +#if 0 + /* trick,hack in ./net/wireless/wext-priv.c ioctl_private_iw_point */ + /* because the cmd number is even (set), the return string will not be + * copy_to_user + */ + ASSERT(IW_IS_SET(u2Cmd)); + if (!access_ok(VERIFY_WRITE, prIwReqData->data.pointer, + i4BytesWritten)) { + DBGLOG(REQ, INFO, "%s access_ok Write fail written = %d\n", + __func__, i4BytesWritten); + return -EFAULT; + } + if (copy_to_user(prIwReqData->data.pointer, pcExtra, + i4BytesWritten)) { + DBGLOG(REQ, INFO, "%s copy_to_user fail written = %d\n", + __func__, i4BytesWritten); + return -EFAULT; + } + DBGLOG(RSN, INFO, "%s copy_to_user written = %d\n", + __func__, i4BytesWritten); +#endif + return 0; + +} /* priv_set_driver */ + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the radio configuration used in IBSS +* mode and RF test mode. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[out] pvQueryBuffer Pointer to the buffer that holds the result of the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +static WLAN_STATUS +reqExtQueryConfiguration(IN P_GLUE_INFO_T prGlueInfo, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_802_11_CONFIG_T prQueryConfig = (P_PARAM_802_11_CONFIG_T) pvQueryBuffer; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4QueryInfoLen = 0; + + DEBUGFUNC("wlanoidQueryConfiguration"); + + ASSERT(prGlueInfo); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(PARAM_802_11_CONFIG_T); + if (u4QueryBufferLen < sizeof(PARAM_802_11_CONFIG_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvQueryBuffer); + + kalMemZero(prQueryConfig, sizeof(PARAM_802_11_CONFIG_T)); + + /* Update the current radio configuration. */ + prQueryConfig->u4Length = sizeof(PARAM_802_11_CONFIG_T); + +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidSetBeaconInterval, + &prQueryConfig->u4BeaconPeriod, sizeof(UINT_32), TRUE, TRUE, &u4QueryInfoLen); +#else + rStatus = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryBeaconInterval, + &prQueryConfig->u4BeaconPeriod, sizeof(UINT_32), &u4QueryInfoLen); +#endif + if (rStatus != WLAN_STATUS_SUCCESS) + return rStatus; +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidQueryAtimWindow, + &prQueryConfig->u4ATIMWindow, sizeof(UINT_32), TRUE, TRUE, &u4QueryInfoLen); +#else + rStatus = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryAtimWindow, + &prQueryConfig->u4ATIMWindow, sizeof(UINT_32), &u4QueryInfoLen); +#endif + if (rStatus != WLAN_STATUS_SUCCESS) + return rStatus; +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidQueryFrequency, + &prQueryConfig->u4DSConfig, sizeof(UINT_32), TRUE, TRUE, &u4QueryInfoLen); +#else + rStatus = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryFrequency, + &prQueryConfig->u4DSConfig, sizeof(UINT_32), &u4QueryInfoLen); +#endif + if (rStatus != WLAN_STATUS_SUCCESS) + return rStatus; + + prQueryConfig->rFHConfig.u4Length = sizeof(PARAM_802_11_CONFIG_FH_T); + + return rStatus; + +} /* end of reqExtQueryConfiguration() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the radio configuration used in IBSS +* mode. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_NOT_ACCEPTED +*/ +/*----------------------------------------------------------------------------*/ +static WLAN_STATUS +reqExtSetConfiguration(IN P_GLUE_INFO_T prGlueInfo, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_PARAM_802_11_CONFIG_T prNewConfig = (P_PARAM_802_11_CONFIG_T) pvSetBuffer; + UINT_32 u4SetInfoLen = 0; + + DEBUGFUNC("wlanoidSetConfiguration"); + + ASSERT(prGlueInfo); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_802_11_CONFIG_T); + + if (u4SetBufferLen < *pu4SetInfoLen) + return WLAN_STATUS_INVALID_LENGTH; + + /* OID_802_11_CONFIGURATION. If associated, NOT_ACCEPTED shall be returned. */ + if (prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_CONNECTED) + return WLAN_STATUS_NOT_ACCEPTED; + + ASSERT(pvSetBuffer); + +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidSetBeaconInterval, + &prNewConfig->u4BeaconPeriod, sizeof(UINT_32), FALSE, TRUE, &u4SetInfoLen); +#else + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetBeaconInterval, + &prNewConfig->u4BeaconPeriod, sizeof(UINT_32), &u4SetInfoLen); +#endif + if (rStatus != WLAN_STATUS_SUCCESS) + return rStatus; +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidSetAtimWindow, + &prNewConfig->u4ATIMWindow, sizeof(UINT_32), FALSE, TRUE, &u4SetInfoLen); +#else + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetAtimWindow, &prNewConfig->u4ATIMWindow, sizeof(UINT_32), &u4SetInfoLen); +#endif + if (rStatus != WLAN_STATUS_SUCCESS) + return rStatus; +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidSetFrequency, + &prNewConfig->u4DSConfig, sizeof(UINT_32), FALSE, TRUE, &u4SetInfoLen); +#else + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetFrequency, &prNewConfig->u4DSConfig, sizeof(UINT_32), &u4SetInfoLen); +#endif + + if (rStatus != WLAN_STATUS_SUCCESS) + return rStatus; + + return rStatus; + +} /* end of reqExtSetConfiguration() */ + +#endif +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set beacon detection function enable/disable state +* This is mainly designed for usage under BT inquiry state (disable function). +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. +* \retval WLAN_STATUS_INVALID_LENGTH +* +*/ +/*----------------------------------------------------------------------------*/ +static WLAN_STATUS +reqExtSetAcpiDevicePowerState(IN P_GLUE_INFO_T prGlueInfo, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prGlueInfo); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + /* WIFI is enabled, when ACPI is D0 (ParamDeviceStateD0 = 1). And vice versa */ + + /* rStatus = wlanSetInformation(prGlueInfo->prAdapter, */ + /* wlanoidSetAcpiDevicePowerState, */ + /* pvSetBuffer, */ + /* u4SetBufferLen, */ + /* pu4SetInfoLen); */ + return rStatus; +} + +int priv_driver_set_chip_config(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + UINT_32 u4CmdLen = 0; + UINT_32 u4PrefixLen = 0; + /* INT_32 i4Argc = 0; */ + /* PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = {0}; */ + + PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T rChipConfigInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + DBGLOG(REQ, INFO, "priv_driver_set_chip_config command is %s\n", pcCommand); + /* wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); */ + /* DBGLOG(REQ, LOUD,("argc is %i\n",i4Argc)); */ + /* */ + u4CmdLen = kalStrnLen(pcCommand, i4TotalLen); + u4PrefixLen = kalStrLen(CMD_SET_CHIP) + 1 /*space */; + + kalMemZero(&rChipConfigInfo, sizeof(rChipConfigInfo)); + + /* if(i4Argc >= 2) { */ + if (u4CmdLen > u4PrefixLen) { + + rChipConfigInfo.ucType = CHIP_CONFIG_TYPE_WO_RESPONSE; + /* rChipConfigInfo.u2MsgSize = kalStrnLen(apcArgv[1],CHIP_CONFIG_RESP_SIZE); */ + rChipConfigInfo.u2MsgSize = u4CmdLen - u4PrefixLen; + /* kalStrnCpy(rChipConfigInfo.aucCmd,apcArgv[1],CHIP_CONFIG_RESP_SIZE); */ + if (u4PrefixLen <= CHIP_CONFIG_RESP_SIZE) { + kalStrnCpy(rChipConfigInfo.aucCmd, pcCommand + u4PrefixLen, + CHIP_CONFIG_RESP_SIZE - u4PrefixLen); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetChipConfig, + &rChipConfigInfo, + sizeof(rChipConfigInfo), FALSE, FALSE, TRUE, TRUE, &u4BufLen); + } else { + + DBGLOG(REQ, INFO, "%s: kalIoctl Command Len > %d\n", __func__, CHIP_CONFIG_RESP_SIZE); + rStatus = WLAN_STATUS_FAILURE; + } + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, INFO, "%s: kalIoctl ret=%d\n", __func__, rStatus); + i4BytesWritten = -1; + } + } + + return i4BytesWritten; + +} + +int priv_driver_set_miracast(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 i4BytesWritten = 0; + /* WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; */ + /* UINT_32 u4BufLen = 0; */ + INT_32 i4Argc = 0; + UINT_32 ucMode = 0; + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T prMsgWfdCfgUpdate = (P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T) NULL; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + INT_32 u4Ret; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + prAdapter = prGlueInfo->prAdapter; + if (i4Argc >= 2) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &ucMode); /* ucMode = kalStrtoul(apcArgv[1], NULL, 0); */ + if (u4Ret) + DBGLOG(REQ, LOUD, "parse pcCommand error u4Ret=%d\n", u4Ret); + + if (g_ucMiracastMode == ucMode) + ; + /* XXX: continue or skip */ + + g_ucMiracastMode = ucMode; + prMsgWfdCfgUpdate = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_WFD_CONFIG_SETTINGS_CHANGED_T)); + + if (prMsgWfdCfgUpdate != NULL) { + + prWfdCfgSettings = &(prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + prMsgWfdCfgUpdate->rMsgHdr.eMsgId = MID_MNY_P2P_WFD_CFG_UPDATE; + prMsgWfdCfgUpdate->prWfdCfgSettings = prWfdCfgSettings; + + if (ucMode == MIRACAST_MODE_OFF) { + prWfdCfgSettings->ucWfdEnable = 0; + snprintf(pcCommand, i4TotalLen, CMD_SET_CHIP " mira 0"); + } else if (ucMode == MIRACAST_MODE_SOURCE) { + prWfdCfgSettings->ucWfdEnable = 1; + snprintf(pcCommand, i4TotalLen, CMD_SET_CHIP " mira 1"); + } else if (ucMode == MIRACAST_MODE_SINK) { + prWfdCfgSettings->ucWfdEnable = 2; + snprintf(pcCommand, i4TotalLen, CMD_SET_CHIP " mira 2"); + } else { + prWfdCfgSettings->ucWfdEnable = 0; + snprintf(pcCommand, i4TotalLen, CMD_SET_CHIP " mira 0"); + } + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgWfdCfgUpdate, MSG_SEND_METHOD_BUF); + + priv_driver_set_chip_config(prNetDev, pcCommand, i4TotalLen); + + } /* prMsgWfdCfgUpdate */ + else { + ASSERT(FALSE); + i4BytesWritten = -1; + } + } + + /* i4Argc */ + return i4BytesWritten; +} +#if CFG_SUPPORT_P2P_ECSA +int priv_driver_set_cs_config(IN struct net_device *prNetDev, + IN UINT_8 mode, + IN UINT_8 channel, + IN UINT_8 op_class, + IN UINT_8 count, + IN UINT_8 sco) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4BufLen = 0; + PARAM_ECSA_CONFIG_STRUCT_T rECSAConfig; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + kalMemZero(&rECSAConfig, sizeof(rECSAConfig)); + + rECSAConfig.channel = channel; + rECSAConfig.count = count; + rECSAConfig.mode = mode; + rECSAConfig.op_class = op_class; + rECSAConfig.sco = sco; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetECSAConfig, + &rECSAConfig, + sizeof(rECSAConfig), FALSE, FALSE, TRUE, TRUE, &u4BufLen); + DBGLOG(REQ, INFO, "%s status: %d\n", __func__, rStatus); + rStatus = p2pUpdateBeaconEcsaIE(prGlueInfo->prAdapter, NETWORK_TYPE_P2P_INDEX); + DBGLOG(REQ, INFO, "%s update beacon status: %d\n", __func__, rStatus); + return rStatus; +} + +int priv_driver_ecsa(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + UINT_32 channel; + UINT_8 op_class; + UINT_32 bandwidth; + UINT_32 u4Freq; + INT_32 sec_channel = 0; + UINT_8 ucPreferedChnl; + ENUM_BAND_T eBand; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + + P_MSG_P2P_ECSA_T prMsgECSA = NULL; + P_MSG_P2P_ECSA_T prMsgCSA = NULL; + + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + ENUM_CHNL_EXT_T eSco = CHNL_EXT_SCN; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, INFO, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc != 3) { + /* + * cmd format: P2P_ECSA channel bandwidth + * argc should be 3 + */ + DBGLOG(REQ, WARN, "cmd format invalid. argc: %d\n", i4Argc); + return -1; + } + /* + * apcArgv[0] = "P2P_ECSA + * apcArgv[1] = channel + * apcArgv[2] = bandwidth + */ + if (kalkStrtou32(apcArgv[1], 0, &channel) || + kalkStrtou32(apcArgv[2], 0, &bandwidth)) { + DBGLOG(REQ, INFO, "kalkstrtou32 failed\n"); + return -1; + } + DBGLOG(REQ, INFO, "ECSA: channel:bandwidth %d:%d\n", channel, bandwidth); + u4Freq = nicChannelNum2Freq(channel); + prMsgCSA = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_ECSA_T)); + + prMsgECSA = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_ECSA_T)); + if (!prMsgECSA || !prMsgCSA) { + if (prMsgECSA) + cnmMemFree(prAdapter, prMsgECSA); + if (prMsgCSA) + cnmMemFree(prAdapter, prMsgCSA); + + DBGLOG(REQ, ERROR, "Msg alloc failed\n"); + return -1; + } + + if (bandwidth == 20) { + /* no need to get sco */ + } else if (bandwidth == 40) { + /* need get sco */ + if (cnmPreferredChannel(prAdapter, + &eBand, + &ucPreferedChnl, + &eSco) == FALSE) { + eSco = rlmDecideSco(prAdapter, channel, channel > 14 ? BAND_2G4 : BAND_5G); + } + + } else { + /* failed, we not support 80/160 yet */ + DBGLOG(REQ, ERROR, "band width %d not support\n", bandwidth); + return -2; + } + + if (eSco == CHNL_EXT_SCN) { + DBGLOG(REQ, INFO, "SCO: No Sco\n"); + sec_channel = 0; + } else if (eSco == CHNL_EXT_SCA) { + DBGLOG(REQ, INFO, "SCO: above Sco\n"); + sec_channel = 1; + } else if (eSco == CHNL_EXT_SCB) { + DBGLOG(REQ, INFO, "SCO: above Sco\n"); + sec_channel = -1; + } + rlmFreqToChannelExt(u4Freq / 1000, sec_channel, &op_class, (PUINT_8)&channel); + + prMsgCSA->rMsgHdr.eMsgId = MID_MNY_P2P_CSA; + prMsgCSA->rP2pECSA.channel = channel; + prMsgCSA->rP2pECSA.count = 50; /* 50 TBTTs */ + prMsgCSA->rP2pECSA.mode = 0; /* not reserve transimit */ + prMsgCSA->rP2pECSA.op_class = op_class; + prMsgCSA->rP2pECSA.sco = eSco; + + DBGLOG(REQ, INFO, "freq:channel:mode:count:op_class:sco %d:%d:%d:%d:%d:%d", + u4Freq, + channel, prMsgCSA->rP2pECSA.mode, + prMsgCSA->rP2pECSA.count, + prMsgCSA->rP2pECSA.op_class, + prMsgCSA->rP2pECSA.sco); + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgCSA, MSG_SEND_METHOD_BUF); + + prMsgECSA->rMsgHdr.eMsgId = MID_MNY_P2P_ECSA; + prMsgECSA->rP2pECSA.channel = channel; + prMsgECSA->rP2pECSA.count = 50; /* 50 TBTTs */ + prMsgECSA->rP2pECSA.mode = 0; /* not reserve transimit */ + prMsgECSA->rP2pECSA.op_class = op_class; + prMsgECSA->rP2pECSA.sco = eSco; + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgECSA, MSG_SEND_METHOD_BUF); + + priv_driver_set_cs_config(prNetDev, 0, channel, op_class, 50, eSco); + return 0; +} +#endif + +int priv_support_driver_cmd(IN struct net_device *prNetDev, IN OUT struct ifreq *prReq, IN int i4Cmd) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + int ret = 0; + char *pcCommand = NULL; + priv_driver_cmd_t *priv_cmd = NULL; + int i4BytesWritten = 0; + int i4TotalLen = 0; + + if (!prReq->ifr_data) { + ret = -EINVAL; + goto exit; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (!prGlueInfo) { + DBGLOG(REQ, WARN, "No glue info\n"); + ret = -EFAULT; + goto exit; + } + if (prGlueInfo->u4ReadyFlag == 0) { + ret = -EINVAL; + goto exit; + } + + priv_cmd = kzalloc(sizeof(priv_driver_cmd_t), GFP_KERNEL); + if (!priv_cmd) { + DBGLOG(REQ, WARN, "%s, alloc mem failed\n", __func__); + return -ENOMEM; + } + + if (copy_from_user(priv_cmd, prReq->ifr_data, sizeof(priv_driver_cmd_t))) { + DBGLOG(REQ, INFO, "%s: copy_from_user fail\n", __func__); + ret = -EFAULT; + goto exit; + } + + i4TotalLen = priv_cmd->total_len; + + if (i4TotalLen <= 0 || i4TotalLen > PRIV_CMD_SIZE) { + ret = -EINVAL; + DBGLOG(REQ, INFO, "%s: i4TotalLen invalid\n", __func__); + goto exit; + } + + pcCommand = priv_cmd->buf; + + DBGLOG(REQ, INFO, "%s: driver cmd \"%s\" on %s\n", __func__, pcCommand, prReq->ifr_name); + + i4BytesWritten = priv_driver_cmds(prNetDev, pcCommand, i4TotalLen); + + if (i4BytesWritten < 0) { + DBGLOG(REQ, INFO, "%s: command %s failed; Written is %d\n", + __func__, pcCommand, i4BytesWritten); + ret = -EFAULT; + } + +exit: + kfree(priv_cmd); + + return ret; +} + +static int priv_driver_get_wifi_type(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct PARAM_GET_WIFI_TYPE rParamGetWifiType; + P_GLUE_INFO_T prGlueInfo = NULL; + uint32_t rStatus; + uint32_t u4BytesWritten = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) { + DBGLOG(REQ, ERROR, "GLUE_CHK_PR2 fail\n"); + return -1; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rParamGetWifiType.prNetDev = prNetDev; + + rStatus = kalIoctl(prGlueInfo, + wlanoidGetWifiType, + (void *)&rParamGetWifiType, + sizeof(void *), + FALSE, + FALSE, + FALSE, + FALSE, + &u4BytesWritten); + if (rStatus == WLAN_STATUS_SUCCESS) { + if (u4BytesWritten > 0) { + if (u4BytesWritten > i4TotalLen) + u4BytesWritten = i4TotalLen; + kalMemCopy(pcCommand, rParamGetWifiType.arWifiTypeName, + u4BytesWritten); + } + } else { + DBGLOG(REQ, ERROR, "rStatus=%x\n", rStatus); + u4BytesWritten = 0; + } + + return (int)u4BytesWritten; +} + +#if CFG_SUPPORT_BATCH_SCAN +#define CMD_BATCH_SET "WLS_BATCHING SET" +#define CMD_BATCH_GET "WLS_BATCHING GET" +#define CMD_BATCH_STOP "WLS_BATCHING STOP" +#endif + +#if CFG_SUPPORT_GET_CH_ENV +#define CMD_CH_ENV_GET "CH_ENV_GET" +#endif + +INT_32 priv_driver_cmds(IN struct net_device *prNetDev, IN PCHAR pcCommand, IN INT_32 i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4BytesWritten = 0; + INT_32 i4CmdFound = 0; + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (i4CmdFound == 0) { + i4CmdFound = 1; + + if (strncasecmp(pcCommand, CMD_MIRACAST, strlen(CMD_MIRACAST)) == 0) + i4BytesWritten = priv_driver_set_miracast(prNetDev, pcCommand, i4TotalLen); +#if CFG_SUPPORT_P2P_ECSA + else if (kalStrniCmp(pcCommand, CMD_ECSA, strlen(CMD_ECSA)) == 0) + i4BytesWritten = priv_driver_ecsa(prNetDev, pcCommand, i4TotalLen); +#endif +#if CFG_SUPPORT_BATCH_SCAN + else if (strncasecmp(pcCommand, CMD_BATCH_SET, strlen(CMD_BATCH_SET)) == 0) { + kalIoctl(prGlueInfo, + wlanoidSetBatchScanReq, + (PVOID) pcCommand, i4TotalLen, FALSE, FALSE, TRUE, FALSE, &i4BytesWritten); + } else if (strncasecmp(pcCommand, CMD_BATCH_GET, strlen(CMD_BATCH_GET)) == 0) { + /* strcpy(pcCommand, "BATCH SCAN DATA FROM FIRMWARE"); */ + /* i4BytesWritten = strlen("BATCH SCAN DATA FROM FIRMWARE") + 1; */ + /* i4BytesWritten = priv_driver_get_linkspeed (prNetDev, pcCommand, i4TotalLen); */ + + UINT_32 u4BufLen; + int i; + /* int rlen=0; */ + + for (i = 0; i < CFG_BATCH_MAX_MSCAN; i++) { + g_rEventBatchResult[i].ucScanCount = i + 1; /* for get which mscan */ + kalIoctl(prGlueInfo, + wlanoidQueryBatchScanResult, + (PVOID)&g_rEventBatchResult[i], + sizeof(EVENT_BATCH_RESULT_T), TRUE, TRUE, TRUE, FALSE, &u4BufLen); + } + +#if 0 + DBGLOG(SCN, INFO, "Batch Scan Results, scan count = %u\n", g_rEventBatchResult.ucScanCount); + for (i = 0; i < g_rEventBatchResult.ucScanCount; i++) { + prEntry = &g_rEventBatchResult.arBatchResult[i]; + DBGLOG(SCN, INFO, "Entry %u\n", i); + DBGLOG(SCN, INFO, " BSSID = %pM\n", prEntry->aucBssid); + DBGLOG(SCN, INFO, " SSID = %s\n", prEntry->aucSSID); + DBGLOG(SCN, INFO, " SSID len = %u\n", prEntry->ucSSIDLen); + DBGLOG(SCN, INFO, " RSSI = %d\n", prEntry->cRssi); + DBGLOG(SCN, INFO, " Freq = %u\n", prEntry->ucFreq); + } +#endif + + batchConvertResult(&g_rEventBatchResult[0], pcCommand, i4TotalLen, &i4BytesWritten); + + /* Dump for debug */ + /* + * print_hex_dump(KERN_INFO, "BATCH", DUMP_PREFIX_ADDRESS, 16, 1, pcCommand, + * i4BytesWritten, TRUE); + */ + + } else if (strncasecmp(pcCommand, CMD_BATCH_STOP, strlen(CMD_BATCH_STOP)) == 0) { + kalIoctl(prGlueInfo, + wlanoidSetBatchScanReq, + (PVOID) pcCommand, i4TotalLen, FALSE, FALSE, TRUE, FALSE, &i4BytesWritten); + } +#endif +#if CFG_SUPPORT_GET_CH_ENV + else if (strncasecmp(pcCommand, CMD_CH_ENV_GET, strlen(CMD_CH_ENV_GET)) == 0) + scanEnvResult(prGlueInfo, pcCommand, i4TotalLen, &i4BytesWritten); +#endif + else if (kalStrniCmp(pcCommand, CMD_ADD_TS, strlen(CMD_ADD_TS)) == 0 || + kalStrniCmp(pcCommand, CMD_DELETE_TS, strlen(CMD_DELETE_TS)) == 0) { + kalIoctl(prGlueInfo, wlanoidTspecOperation, (PVOID)pcCommand, + i4TotalLen, FALSE, FALSE, FALSE, FALSE, &i4BytesWritten); + } +#if CFG_SUPPORT_FCC_POWER_BACK_OFF + else if (kalStrniCmp(pcCommand, CMD_SET_FCC_CERT, strlen(CMD_SET_FCC_CERT)) == 0) { + CMD_FCC_TX_PWR_ADJUST rFccTxPwrAdjust; + P_FCC_TX_PWR_ADJUST pFccTxPwrAdjust = &prGlueInfo->rRegInfo.rFccTxPwrAdjust; + WLAN_STATUS rWlanStatus = WLAN_STATUS_FAILURE; + + if (pFccTxPwrAdjust->fgFccTxPwrAdjust == 0) + DBGLOG(RLM, WARN, + "FCC cert control(%d) is disabled in NVRAM\n", + pFccTxPwrAdjust->fgFccTxPwrAdjust); + else { + pcCommand += (strlen(CMD_SET_FCC_CERT) + 1); + if (kalStrniCmp(pcCommand, "-1", strlen("-1")) != 0 && *pcCommand != '0') + DBGLOG(RLM, WARN, "control parameter(%s) is not correct(0 or -1)\n", + pcCommand); + else { + kalMemSet(&rFccTxPwrAdjust, 0, sizeof(rFccTxPwrAdjust)); +#if 0 + rFccTxPwrAdjust.Offset_CCK = 14; /* drop 7dB */ + rFccTxPwrAdjust.Offset_HT20 = 16; /* drop 8dB */ + rFccTxPwrAdjust.Offset_HT40 = 14; /* drop 7dB */ + rFccTxPwrAdjust.Channel_CCK[0] = 12; /* start channel */ + rFccTxPwrAdjust.Channel_CCK[1] = 13; /* end channel */ + rFccTxPwrAdjust.Channel_HT20[0] = 12; /* start channel */ + rFccTxPwrAdjust.Channel_HT20[1] = 13; /* end channel */ + /* start channel, primiary channel 12, HT40, center channel (10) -2 */ + rFccTxPwrAdjust.Channel_HT40[0] = 8; + /* end channel, primiary channel 12, HT40, center channel (11) -2 */ + rFccTxPwrAdjust.Channel_HT40[1] = 9; + /* set special bandedge*/ + rFccTxPwrAdjust.Channel_Bandedge[0] = 11; + rFccTxPwrAdjust.Channel_Bandedge[1] = 13; +#else + kalMemCopy(&rFccTxPwrAdjust, pFccTxPwrAdjust, sizeof(FCC_TX_PWR_ADJUST)); + /* set special channel band edge */ + kalMemCopy(&rFccTxPwrAdjust.Channel_Bandedge, + &prGlueInfo->rRegInfo.aucChannelBandEdge, sizeof(UINT_8)*2); +#endif + rFccTxPwrAdjust.fgFccTxPwrAdjust = *pcCommand == '0' ? 1 : 0; + + DBGLOG(RLM, INFO, "FCC Cert Control (%d)\n", rFccTxPwrAdjust.fgFccTxPwrAdjust); + + rWlanStatus = kalIoctl(prGlueInfo, + wlanoidSetFccCert, + (PVOID)&rFccTxPwrAdjust, + sizeof(CMD_FCC_TX_PWR_ADJUST), + FALSE, + FALSE, + TRUE, + FALSE, + NULL); + if (rWlanStatus == WLAN_STATUS_SUCCESS) + i4BytesWritten = i4TotalLen; + } + } + } +#endif +#if 0 + + else if (strncasecmp(pcCommand, CMD_RSSI, strlen(CMD_RSSI)) == 0) { + /* i4BytesWritten = wl_android_get_rssi(net, command, i4TotalLen); */ + } else if (strncasecmp(pcCommand, CMD_LINKSPEED, strlen(CMD_LINKSPEED)) == 0) { + i4BytesWritten = priv_driver_get_linkspeed(prNetDev, pcCommand, i4TotalLen); + } else if (strncasecmp(pcCommand, CMD_PNOSSIDCLR_SET, strlen(CMD_PNOSSIDCLR_SET)) == 0) { + /* Do nothing */ + } else if (strncasecmp(pcCommand, CMD_PNOSETUP_SET, strlen(CMD_PNOSETUP_SET)) == 0) { + /* Do nothing */ + } else if (strncasecmp(pcCommand, CMD_PNOENABLE_SET, strlen(CMD_PNOENABLE_SET)) == 0) { + /* Do nothing */ + } else if (strncasecmp(pcCommand, CMD_SETSUSPENDOPT, strlen(CMD_SETSUSPENDOPT)) == 0) { + /* i4BytesWritten = wl_android_set_suspendopt(net, pcCommand, i4TotalLen); */ + } else if (strncasecmp(pcCommand, CMD_SETSUSPENDMODE, strlen(CMD_SETSUSPENDMODE)) == 0) { + i4BytesWritten = priv_driver_set_suspend_mode(prNetDev, pcCommand, i4TotalLen); + } else if (strncasecmp(pcCommand, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) { + i4BytesWritten = priv_driver_set_band(prNetDev, pcCommand, i4TotalLen); + } else if (strncasecmp(pcCommand, CMD_GETBAND, strlen(CMD_GETBAND)) == 0) { + /* i4BytesWritten = wl_android_get_band(net, pcCommand, i4TotalLen); */ + } else if (strncasecmp(pcCommand, CMD_COUNTRY, strlen(CMD_COUNTRY)) == 0) { + i4BytesWritten = priv_driver_set_country(prNetDev, pcCommand, i4TotalLen); + } + /* Mediatek private command */ + else if (strncasecmp(pcCommand, CMD_SET_SW_CTRL, strlen(CMD_SET_SW_CTRL)) == 0) { + i4BytesWritten = priv_driver_set_sw_ctrl(prNetDev, pcCommand, i4TotalLen); + } else if (strncasecmp(pcCommand, CMD_GET_SW_CTRL, strlen(CMD_GET_SW_CTRL)) == 0) { + i4BytesWritten = priv_driver_get_sw_ctrl(prNetDev, pcCommand, i4TotalLen); + } else if (strncasecmp(pcCommand, CMD_SET_CFG, strlen(CMD_SET_CFG)) == 0) { + i4BytesWritten = priv_driver_set_cfg(prNetDev, pcCommand, i4TotalLen); + } else if (strncasecmp(pcCommand, CMD_GET_CFG, strlen(CMD_GET_CFG)) == 0) { + i4BytesWritten = priv_driver_get_cfg(prNetDev, pcCommand, i4TotalLen); + } else if (strncasecmp(pcCommand, CMD_SET_CHIP, strlen(CMD_SET_CHIP)) == 0) { + i4BytesWritten = priv_driver_set_chip_config(prNetDev, pcCommand, i4TotalLen); + } else if (strncasecmp(pcCommand, CMD_GET_CHIP, strlen(CMD_GET_CHIP)) == 0) { + i4BytesWritten = priv_driver_get_chip_config(prNetDev, pcCommand, i4TotalLen); + } else if (strncasecmp(pcCommand, CMD_SET_DBG_LEVEL, strlen(CMD_SET_DBG_LEVEL)) == 0) { + i4BytesWritten = priv_driver_set_dbg_level(prNetDev, pcCommand, i4TotalLen); + } else if (strncasecmp(pcCommand, CMD_GET_DBG_LEVEL, strlen(CMD_GET_DBG_LEVEL)) == 0) { + i4BytesWritten = priv_driver_get_dbg_level(prNetDev, pcCommand, i4TotalLen); + } +#if CFG_SUPPORT_BATCH_SCAN + else if (strncasecmp(pcCommand, CMD_BATCH_SET, strlen(CMD_BATCH_SET)) == 0) { + kalIoctl(prGlueInfo, + wlanoidSetBatchScanReq, + (PVOID) pcCommand, i4TotalLen, FALSE, FALSE, TRUE, &i4BytesWritten); + } else if (strncasecmp(pcCommand, CMD_BATCH_GET, strlen(CMD_BATCH_GET)) == 0) { + /* strcpy(pcCommand, "BATCH SCAN DATA FROM FIRMWARE"); */ + /* i4BytesWritten = strlen("BATCH SCAN DATA FROM FIRMWARE") + 1; */ + /* i4BytesWritten = priv_driver_get_linkspeed (prNetDev, pcCommand, i4TotalLen); */ + + UINT_32 u4BufLen; + int i; + /* int rlen=0; */ + + for (i = 0; i < CFG_BATCH_MAX_MSCAN; i++) { + g_rEventBatchResult[i].ucScanCount = i + 1; /* for get which mscan */ + kalIoctl(prGlueInfo, + wlanoidQueryBatchScanResult, + (PVOID)&g_rEventBatchResult[i], + sizeof(EVENT_BATCH_RESULT_T), TRUE, TRUE, TRUE, &u4BufLen); + } + +#if 0 + DBGLOG(SCN, INFO, "Batch Scan Results, scan count = %u\n", g_rEventBatchResult.ucScanCount); + for (i = 0; i < g_rEventBatchResult.ucScanCount; i++) { + prEntry = &g_rEventBatchResult.arBatchResult[i]; + DBGLOG(SCN, INFO, "Entry %u\n", i); + DBGLOG(SCN, INFO, " BSSID = %pM\n", prEntry->aucBssid); + DBGLOG(SCN, INFO, " SSID = %s\n", prEntry->aucSSID); + DBGLOG(SCN, INFO, " SSID len = %u\n", prEntry->ucSSIDLen); + DBGLOG(SCN, INFO, " RSSI = %d\n", prEntry->cRssi); + DBGLOG(SCN, INFO, " Freq = %u\n", prEntry->ucFreq); + } +#endif + + batchConvertResult(&g_rEventBatchResult[0], pcCommand, i4TotalLen, &i4BytesWritten); + + /* Dump for debug */ + /* + * print_hex_dump(KERN_INFO, "BATCH", DUMP_PREFIX_ADDRESS, 16, 1, pcCommand, i4BytesWritten, + * TRUE); + */ + + } else if (strncasecmp(pcCommand, CMD_BATCH_STOP, strlen(CMD_BATCH_STOP)) == 0) { + kalIoctl(prGlueInfo, + wlanoidSetBatchScanReq, + (PVOID) pcCommand, i4TotalLen, FALSE, FALSE, TRUE, &i4BytesWritten); + } +#endif + +#endif + +#if CFG_SUPPORT_NCHO + else if (kalStrniCmp(pcCommand, + CMD_NCHO_ROAM_TRIGGER_SET, + strlen(CMD_NCHO_ROAM_TRIGGER_SET)) == 0) { + i4BytesWritten = priv_driver_set_ncho_roam_trigger(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_ROAM_TRIGGER_GET, + strlen(CMD_NCHO_ROAM_TRIGGER_GET)) == 0) { + i4BytesWritten = priv_driver_get_ncho_roam_trigger(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_ROAM_DELTA_SET, + strlen(CMD_NCHO_ROAM_DELTA_SET)) == 0) { + i4BytesWritten = priv_driver_set_ncho_roam_delta(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_ROAM_DELTA_GET, + strlen(CMD_NCHO_ROAM_DELTA_GET)) == 0) { + i4BytesWritten = priv_driver_get_ncho_roam_delta(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_ROAM_SCAN_PERIOD_SET, + strlen(CMD_NCHO_ROAM_SCAN_PERIOD_SET)) == 0) { + i4BytesWritten = priv_driver_set_ncho_roam_scn_period(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_ROAM_SCAN_PERIOD_GET, + strlen(CMD_NCHO_ROAM_SCAN_PERIOD_GET)) == 0) { + i4BytesWritten = priv_driver_get_ncho_roam_scn_period(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_ROAM_SCAN_CHANNELS_SET, + strlen(CMD_NCHO_ROAM_SCAN_CHANNELS_SET)) == 0) { + i4BytesWritten = priv_driver_set_ncho_roam_scn_chnl(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_ROAM_SCAN_CHANNELS_GET, + strlen(CMD_NCHO_ROAM_SCAN_CHANNELS_GET)) == 0) { + i4BytesWritten = priv_driver_get_ncho_roam_scn_chnl(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_ROAM_SCAN_CONTROL_SET, + strlen(CMD_NCHO_ROAM_SCAN_CONTROL_SET)) == 0) { + i4BytesWritten = priv_driver_set_ncho_roam_scn_ctrl(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_ROAM_SCAN_CONTROL_GET, + strlen(CMD_NCHO_ROAM_SCAN_CONTROL_GET)) == 0) { + i4BytesWritten = priv_driver_get_ncho_roam_scn_ctrl(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_SCAN_CHANNEL_TIME_SET, + strlen(CMD_NCHO_SCAN_CHANNEL_TIME_SET)) == 0) { + i4BytesWritten = priv_driver_set_ncho_scn_chnl_time(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_SCAN_CHANNEL_TIME_GET, + strlen(CMD_NCHO_SCAN_CHANNEL_TIME_GET)) == 0) { + i4BytesWritten = priv_driver_get_ncho_scn_chnl_time(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_SCAN_HOME_TIME_SET, + strlen(CMD_NCHO_SCAN_HOME_TIME_SET)) == 0) { + i4BytesWritten = priv_driver_set_ncho_scn_home_time(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_SCAN_HOME_TIME_GET, + strlen(CMD_NCHO_SCAN_HOME_TIME_GET)) == 0) { + i4BytesWritten = priv_driver_get_ncho_scn_home_time(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_SCAN_HOME_AWAY_TIME_SET, + strlen(CMD_NCHO_SCAN_HOME_AWAY_TIME_SET)) == 0) { + i4BytesWritten = priv_driver_set_ncho_scn_home_away_time(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_SCAN_HOME_AWAY_TIME_GET, + strlen(CMD_NCHO_SCAN_HOME_AWAY_TIME_GET)) == 0) { + i4BytesWritten = priv_driver_get_ncho_scn_home_away_time(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_SCAN_NPROBES_SET, + strlen(CMD_NCHO_SCAN_NPROBES_SET)) == 0) { + i4BytesWritten = priv_driver_set_ncho_scn_nprobes(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_SCAN_NPROBES_GET, + strlen(CMD_NCHO_SCAN_NPROBES_GET)) == 0) { + i4BytesWritten = priv_driver_get_ncho_scn_nprobes(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_REASSOC_SEND, + strlen(CMD_NCHO_REASSOC_SEND)) == 0) { + i4BytesWritten = priv_driver_send_ncho_reassoc(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_ACTION_FRAME_SEND, + strlen(CMD_NCHO_ACTION_FRAME_SEND)) == 0) { + i4BytesWritten = priv_driver_send_ncho_action_frame(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_WES_MODE_SET, + strlen(CMD_NCHO_WES_MODE_SET)) == 0) { + i4BytesWritten = priv_driver_set_ncho_wes_mode(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_WES_MODE_GET, strlen(CMD_NCHO_WES_MODE_GET)) == 0) { + i4BytesWritten = priv_driver_get_ncho_wes_mode(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_BAND_SET, + strlen(CMD_NCHO_BAND_SET)) == 0) { + i4BytesWritten = priv_driver_set_ncho_band(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_BAND_GET, + strlen(CMD_NCHO_BAND_GET)) == 0) { + i4BytesWritten = priv_driver_get_ncho_band(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_DFS_SCAN_MODE_SET, + strlen(CMD_NCHO_DFS_SCAN_MODE_SET)) == 0) { + i4BytesWritten = priv_driver_set_ncho_dfs_scn_mode(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_DFS_SCAN_MODE_GET, + strlen(CMD_NCHO_DFS_SCAN_MODE_GET)) == 0) { + i4BytesWritten = priv_driver_get_ncho_dfs_scn_mode(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_ENABLE, + strlen(CMD_NCHO_ENABLE)) == 0) { + i4BytesWritten = priv_driver_enable_ncho(prNetDev, pcCommand, i4TotalLen); + } else if (kalStrniCmp(pcCommand, + CMD_NCHO_DISABLE, + strlen(CMD_NCHO_DISABLE)) == 0) { + i4BytesWritten = priv_driver_disable_ncho(prNetDev, pcCommand, i4TotalLen); + } +#endif + else if (!strncasecmp(pcCommand, CMD_FW_PARAM, strlen(CMD_FW_PARAM))) + kalIoctl(prGlueInfo, wlanoidSetFwParam, (PVOID)(pcCommand + 13), + i4TotalLen - 13, FALSE, FALSE, FALSE, FALSE, &i4BytesWritten); + else if (!strncasecmp(pcCommand, CMD_GET_WIFI_TYPE, strlen(CMD_GET_WIFI_TYPE))) + i4BytesWritten = priv_driver_get_wifi_type(prNetDev, pcCommand, i4TotalLen); + else + i4CmdFound = 0; + } + + /* i4CmdFound */ + if (i4CmdFound == 0) + DBGLOG(REQ, INFO, "Unknown driver command %s - ignored\n", pcCommand); + + if (i4BytesWritten >= 0) { + if ((i4BytesWritten == 0) && (i4TotalLen > 0)) { + /* reset the command buffer */ + pcCommand[0] = '\0'; + } + + if (i4BytesWritten >= i4TotalLen) { + DBGLOG(REQ, INFO, + "%s: i4BytesWritten %d > i4TotalLen < %d\n", __func__, i4BytesWritten, i4TotalLen); + i4BytesWritten = i4TotalLen; + } else { + pcCommand[i4BytesWritten] = '\0'; + i4BytesWritten++; + } + } + + return i4BytesWritten; + +} + +static int compat_priv(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra, + int (*priv_func)(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra)) +{ + struct iw_point *prIwp; + int ret = 0; +#ifdef CONFIG_COMPAT + struct compat_iw_point *iwp_compat = NULL; + struct iw_point iwp; +#endif + + if (!prIwReqData) + return -EINVAL; + +#ifdef CONFIG_COMPAT + if (prIwReqInfo->flags & IW_REQUEST_FLAG_COMPAT) { + iwp_compat = (struct compat_iw_point *) &prIwReqData->data; + iwp.pointer = compat_ptr(iwp_compat->pointer); + iwp.length = iwp_compat->length; + iwp.flags = iwp_compat->flags; + prIwp = &iwp; + } else +#endif + prIwp = &prIwReqData->data; + + + ret = priv_func(prNetDev, prIwReqInfo, (union iwreq_data *)prIwp, pcExtra); + +#ifdef CONFIG_COMPAT + if (prIwReqInfo->flags & IW_REQUEST_FLAG_COMPAT) { + iwp_compat->pointer = ptr_to_compat(iwp.pointer); + iwp_compat->length = iwp.length; + iwp_compat->flags = iwp.flags; + } +#endif + return ret; +} + +int +priv_set_int(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) +{ + return compat_priv(prNetDev, prIwReqInfo, prIwReqData, pcExtra, _priv_set_int); +} + +int +priv_get_int(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + return compat_priv(prNetDev, prIwReqInfo, prIwReqData, pcExtra, _priv_get_int); +} + +int +priv_set_ints(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) +{ + return compat_priv(prNetDev, prIwReqInfo, prIwReqData, pcExtra, _priv_set_ints); +} + +int +priv_get_ints(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + return compat_priv(prNetDev, prIwReqInfo, prIwReqData, pcExtra, _priv_get_ints); +} + +int +priv_set_struct(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) +{ + return compat_priv(prNetDev, prIwReqInfo, prIwReqData, pcExtra, _priv_set_struct); +} + +int +priv_get_struct(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + return compat_priv(prNetDev, prIwReqInfo, prIwReqData, pcExtra, _priv_get_struct); +} + +int +priv_set_string(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) +{ + return _priv_set_string(prNetDev, prIwReqInfo, prIwReqData, pcExtra); + /*return compat_priv(prNetDev, prIwReqInfo, prIwReqData, pcExtra, _priv_set_string);*/ +} + +int +priv_get_string(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) +{ + return _priv_get_string(prNetDev, prIwReqInfo, prIwReqData, pcExtra); + /*return compat_priv(prNetDev, prIwReqInfo, prIwReqData, pcExtra, _priv_get_string);*/ +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/hif/ahb/ahb.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/hif/ahb/ahb.c new file mode 100644 index 0000000000000..556497f0f29d3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/hif/ahb/ahb.c @@ -0,0 +1,1696 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +/* #include */ +#include +/* #include */ +#include +/* #include */ +/* #include */ +/* #include */ + +#include +#ifndef CONFIG_X86 +#include +#endif + +#ifdef CONFIG_OF +#include +#include +#include +#else + +#endif + +/* + * #include + * #include + */ + +#include "gl_os.h" + +#if defined(MT6620) +#include "mt6620_reg.h" +#elif defined(MT6628) +#include "mtreg.h" +#endif + +#if !defined(CONFIG_MTK_CLKMGR) +#include +#endif + +/* #define MTK_DMA_BUF_MEMCPY_SUP */ /* no virt_to_phys() use */ + +/* #define HIF_DEBUG_SUP */ +/* #define HIF_DEBUG_SUP_TX */ + +#ifdef HIF_DEBUG_SUP +#define HIF_DBG(msg) (printk msg) +#else +#define HIF_DBG(msg) +#endif /* HIF_DEBUG_SUP */ + +#ifdef HIF_DEBUG_SUP_TX +#define HIF_DBG_TX(msg) (printk msg) +#else +#define HIF_DBG_TX(msg) +#endif /* HIF_DEBUG_SUP */ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static UINT_32 HifAhbDmaEnhanceModeConf(GLUE_INFO_T *GlueInfo, UINT_32 BurstLen, UINT_32 PortId, UINT_32 TransByte); + +static irqreturn_t HifAhbISR(IN int Irq, IN void *Arg); + +static int HifAhbProbe(VOID); + +static int HifAhbRemove(VOID); + +#if (MTK_WCN_SINGLE_MODULE == 0) +static int HifAhbBusCntGet(VOID); + +static int HifAhbBusCntClr(VOID); + +static int HifTxCnt; +#endif /* MTK_WCN_SINGLE_MODULE */ + +#if (CONF_HIF_DEV_MISC == 1) +static ssize_t HifAhbMiscRead(IN struct file *Filp, OUT char __user *DstBuf, IN size_t Size, IN loff_t *Ppos); + +static ssize_t HifAhbMiscWrite(IN struct file *Filp, IN const char __user *SrcBuf, IN size_t Size, IN loff_t *Ppos); + +static int HifAhbMiscIoctl(IN struct file *Filp, IN unsigned int Cmd, IN unsigned long arg); + +static int HifAhbMiscOpen(IN struct inode *Inodep, IN struct file *Filp); + +static int HifAhbMiscClose(IN struct inode *Inodep, IN struct file *Filp); +#else + +static int HifAhbPltmProbe(IN struct platform_device *PDev); + +static int __exit HifAhbPltmRemove(IN struct platform_device *PDev); + +#ifdef CONFIG_PM +static int HifAhbPltmSuspend(IN struct platform_device *PDev, pm_message_t Message); + +static int HifAhbPltmResume(IN struct platform_device *PDev); +#endif /* CONFIG_PM */ + +#endif /* CONF_HIF_DEV_MISC */ + +#if (CONF_HIF_LOOPBACK_AUTO == 1) /* only for development test */ +#if KERNEL_VERSION(4, 15, 0) <= CFG80211_VERSION_CODE +static VOID HifAhbLoopbkAuto(struct timer_list *timer); +#else +static VOID HifAhbLoopbkAuto(IN unsigned long arg); +#endif +#endif /* CONF_HIF_LOOPBACK_AUTO */ + +#if (CONF_HIF_DMA_INT == 1) +static irqreturn_t HifDmaISR(IN int Irq, IN void *Arg); +#endif /* CONF_HIF_DMA_INT */ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/* initialiation function from other module */ +static probe_card pfWlanProbe; + +/* release function from other module */ +static remove_card pfWlanRemove; + +static BOOLEAN WlanDmaFatalErr; + +#if (CONF_HIF_DEV_MISC == 1) +static const struct file_operations MtkAhbOps = { + .owner = THIS_MODULE, + .read = HifAhbMiscRead, + .write = HifAhbMiscWrite, + .unlocked_ioctl = HifAhbMiscIoctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = HifAhbMiscIoctl, +#endif + .open = HifAhbMiscOpen, + .release = HifAhbMiscClose, +}; + +static struct miscdevice MtkAhbDriver = { + .minor = MISC_DYNAMIC_MINOR, /* any minor number */ + .name = HIF_MOD_NAME, + .fops = &MtkAhbOps, +}; +#else + +#ifdef CONFIG_OF +static const struct of_device_id apwifi_of_ids[] = { + {.compatible = "mediatek,wifi", .data = (void *)0}, + {.compatible = "mediatek,mt7623-wifi", .data = (void *)0x7623}, + {} +}; +#endif + +struct platform_driver __refdata MtkPltmAhbDriver = { + .driver = { + .name = "mt-wifi", + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = apwifi_of_ids, +#endif + }, + .probe = HifAhbPltmProbe, +#ifdef CONFIG_PM + .suspend = HifAhbPltmSuspend, + .resume = HifAhbPltmResume, +#else + .suspend = NULL, + .resume = NULL, +#endif /* CONFIG_PM */ + .remove = __exit_p(HifAhbPltmRemove), +}; + +static struct platform_device *HifAhbPDev; + +#endif /* CONF_HIF_DEV_MISC */ + +/******************************************************************************* +* P U B L I C F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will register sdio bus to the os +* +* \param[in] pfProbe Function pointer to detect card +* \param[in] pfRemove Function pointer to remove card +* +* \return The result of registering HIF driver (WLAN_STATUS_SUCCESS = 0) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS glRegisterBus(probe_card pfProbe, remove_card pfRemove) +{ + WLAN_STATUS Ret; + + ASSERT(pfProbe); + ASSERT(pfRemove); + + pfWlanProbe = pfProbe; /* wlan card initialization in other modules = wlanProbe() */ + pfWlanRemove = pfRemove; + +#if (CONF_HIF_DEV_MISC == 1) + Ret = misc_register(&MtkAhbDriver); + if (Ret != 0) + return Ret; + HifAhbProbe(); +#else + Ret = platform_driver_register(&MtkPltmAhbDriver); +#endif /* CONF_HIF_DEV_MISC */ + + return Ret; + +} /* end of glRegisterBus() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will unregister sdio bus to the os +* +* \param[in] pfRemove Function pointer to remove card +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glUnregisterBus(remove_card pfRemove) +{ + ASSERT(pfRemove); + + if (pfRemove) + pfRemove(); + +#if (CONF_HIF_DEV_MISC == 1) + HifAhbRemove(); + + if ((misc_deregister(&MtkAhbDriver)) != 0) + ; +#else + + platform_driver_unregister(&MtkPltmAhbDriver); +#endif /* CONF_HIF_DEV_MISC */ + + return; + +} /* end of glUnregisterBus() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will inform us whole chip reset start event. +* +* \param[in] GlueInfo Pointer to glue info structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glResetHif(GLUE_INFO_T *GlueInfo) +{ + GL_HIF_INFO_T *HifInfo; + + ASSERT(GlueInfo); + + if (GlueInfo) { + HifInfo = &GlueInfo->rHifInfo; + if (HifInfo->DmaOps) + HifInfo->DmaOps->DmaReset(HifInfo); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function stores hif related info, which is initialized before. +* +* \param[in] GlueInfo Pointer to glue info structure +* \param[in] u4Cookie Pointer to UINT_32 memory base variable for _HIF_HPI +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glSetHifInfo(GLUE_INFO_T *GlueInfo, ULONG ulCookie) +{ + GL_HIF_INFO_T *HifInfo; + const struct of_device_id *of_id; + + /* Init HIF */ + ASSERT(GlueInfo); + + if (GlueInfo == NULL) { + DBGLOG(INIT, ERROR, "GlueInfo is NULL."); + return; + } + + HifInfo = &GlueInfo->rHifInfo; +#if (CONF_HIF_DEV_MISC == 1) + HifInfo->Dev = MtkAhbDriver.this_device; +#else + HifInfo->Dev = &HifAhbPDev->dev; +#endif /* CONF_HIF_DEV_MISC */ + SET_NETDEV_DEV(GlueInfo->prDevHandler, HifInfo->Dev); + + if (HifInfo->HifRegBaseAddr == NULL) + HifInfo->HifRegBaseAddr = ioremap(HIF_DRV_BASE, HIF_DRV_LENGTH); + + if (HifInfo->McuRegBaseAddr == NULL) + HifInfo->McuRegBaseAddr = ioremap(CONN_MCU_DRV_BASE, CONN_MCU_REG_LENGTH); + + if (HifInfo->APMcuRegBaseAddr == NULL) + HifInfo->APMcuRegBaseAddr = ioremap(AP_MCU_DRV_BASE, AP_MCU_TX_RX_LENGTH); + + /* default disable DMA */ + HifInfo->fgDmaEnable = FALSE; + HifInfo->DmaRegBaseAddr = 0; + HifInfo->DmaOps = NULL; + of_id = of_match_node(apwifi_of_ids, HifAhbPDev->dev.of_node); + if (of_id && of_id->data) { + HifInfo->ChipID = (UINT_32)(unsigned long)of_id->data; + } else { + /* read chip ID */ + HifInfo->ChipID = HIF_REG_READL(HifInfo, MCR_WCIR) & 0xFFFF; + switch (HifInfo->ChipID) { + case 0x0321: + case 0x0335: + case 0x0337: + HifInfo->ChipID = 0x6735; + break; + case 0x0326: + case 0x0551: + case 0x0690: + case 0x0699: + HifInfo->ChipID = 0x6755; + break; + case 0x0633: + HifInfo->ChipID = 0x6570; + break; + } + } + + DBGLOG(INIT, INFO, "[WiFi/HIF] ChipID=0x%x, HifInfo->HifRegBaseAddr=0x%p, HifInfo->McuRegBaseAddr=0x%p\n", + HifInfo->ChipID, HifInfo->HifRegBaseAddr, HifInfo->McuRegBaseAddr); + +#ifdef CONFIG_OF +#if !defined(CONFIG_MTK_CLKMGR) + HifInfo->clk_wifi_dma = devm_clk_get(&HifAhbPDev->dev, "wifi-dma"); + if (IS_ERR(HifInfo->clk_wifi_dma)) + DBGLOG(INIT, ERROR, "[WiFi/HIF][CCF]cannot get HIF clk_wifi_dma clock.\n"); + DBGLOG(INIT, TRACE, "[WiFi/HIF][CCF]HIF clk_wifi_dma=0x%p\n", HifInfo->clk_wifi_dma); +#endif +#endif + + /* Init DMA */ + WlanDmaFatalErr = 0; /* reset error flag */ + +#if (CONF_MTK_AHB_DMA == 1) + spin_lock_init(&HifInfo->DdmaLock); + + HifPdmaInit(HifInfo); +#endif /* CONF_MTK_AHB_DMA */ + + /* Start loopback test after 10 seconds */ +#if (CONF_HIF_LOOPBACK_AUTO == 1) /* only for development test */ + { +#if KERNEL_VERSION(4, 15, 0) <= CFG80211_VERSION_CODE + timer_setup(&HifInfo->HifTmrLoopbkFn, HifAhbLoopbkAuto, 0); +#else + init_timer(&(HifInfo->HifTmrLoopbkFn)); + HifInfo->HifTmrLoopbkFn.function = HifAhbLoopbkAuto; + HifInfo->HifTmrLoopbkFn.data = (unsigned long)GlueInfo; +#endif + init_waitqueue_head(&HifInfo->HifWaitq); + HifInfo->HifTaskLoopbkFn = kthread_run(kalDevLoopbkThread, GlueInfo->prDevHandler, "LoopbkThread"); + HifInfo->HifLoopbkFlg = 0; + + /* Note: in FPGA, clock is not accuracy so 3000 here, not 10000 */ + HifInfo->HifTmrLoopbkFn.expires = jiffies + MSEC_TO_SYSTIME(30000); + add_timer(&(HifInfo->HifTmrLoopbkFn)); + + HIF_DBG(("[WiFi/HIF] Start loopback test after 10 seconds (jiffies = %u)...\n", jiffies)); + } +#endif /* CONF_HIF_LOOPBACK_AUTO */ + +#if (CONF_HIF_DMA_INT == 1) + init_waitqueue_head(&HifInfo->HifDmaWaitq); + HifInfo->HifDmaWaitFlg = 0; +#endif /* CONF_HIF_DMA_INT */ + + /* Default set DMA usleep enable for CPU optimization*/ + HifInfo->fgDmaUsleepEnable = TRUE; + +} /* end of glSetHifInfo() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function clears hif related info. +* +* \param[in] GlueInfo Pointer to glue info structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glClearHifInfo(GLUE_INFO_T *GlueInfo) +{ + iounmap(GlueInfo->rHifInfo.HifRegBaseAddr); + iounmap(GlueInfo->rHifInfo.DmaRegBaseAddr); + iounmap(GlueInfo->rHifInfo.McuRegBaseAddr); + iounmap(GlueInfo->rHifInfo.APMcuRegBaseAddr); + GlueInfo->rHifInfo.HifRegBaseAddr = NULL; + GlueInfo->rHifInfo.DmaRegBaseAddr = NULL; + GlueInfo->rHifInfo.McuRegBaseAddr = NULL; + GlueInfo->rHifInfo.APMcuRegBaseAddr = NULL; + return; + +} /* end of glClearHifInfo() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function clears hif related info. +* +* \param[in] GlueInfo Pointer to glue info structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glGetChipInfo(GLUE_INFO_T *GlueInfo, UINT_8 *pucChipBuf) +{ + GL_HIF_INFO_T *HifInfo; + + HifInfo = &GlueInfo->rHifInfo; + DBGLOG(INIT, TRACE, "glGetChipInfo ChipID = 0x%x\n", HifInfo->ChipID); + switch (HifInfo->ChipID) { + case MTK_CHIP_ID_6571: + case MTK_CHIP_ID_8127: + case MTK_CHIP_ID_6752: + case MTK_CHIP_ID_8163: + case MTK_CHIP_ID_8167: + case MTK_CHIP_ID_6735: + case MTK_CHIP_ID_6570: + case MTK_CHIP_ID_6580: + case MTK_CHIP_ID_6755: + case MTK_CHIP_ID_7623: + kalSprintf(pucChipBuf, "%04x", HifInfo->ChipID); + break; + default: + kalMemCopy(pucChipBuf, "SOC", strlen("SOC")); + } +} /* end of glGetChipInfo() */ + +#if CFG_SPM_WORKAROUND_FOR_HOTSPOT +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function to check if we need wakelock under Hotspot mode. +* +* \param[in] GlueInfo Pointer to glue info structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN glIsChipNeedWakelock(GLUE_INFO_T *GlueInfo) +{ + GL_HIF_INFO_T *HifInfo; + + HifInfo = &GlueInfo->rHifInfo; + if (HifInfo->ChipID == MTK_CHIP_ID_6572 || HifInfo->ChipID == MTK_CHIP_ID_6582) + return TRUE; + else + return FALSE; +} /* end of glIsChipNeedWakelock() */ +#endif /* CFG_SPM_WORKAROUND_FOR_HOTSPOT */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Initialize bus operation and hif related information, request resources. +* +* \param[out] pvData A pointer to HIF-specific data type buffer. +* For eHPI, pvData is a pointer to UINT_32 type and stores a +* mapped base address. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN glBusInit(PVOID pvData) +{ + return TRUE; +} /* end of glBusInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus operation and release resources. +* +* \param[in] pvData A pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glBusRelease(PVOID pvData) +{ +} /* end of glBusRelease() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setup bus interrupt operation and interrupt handler for os. +* +* \param[in] pvData A pointer to struct net_device. +* \param[in] pfnIsr A pointer to interrupt handler function. +* \param[in] pvCookie Private data for pfnIsr function. +* +* \retval WLAN_STATUS_SUCCESS if success +* NEGATIVE_VALUE if fail +*/ +/*----------------------------------------------------------------------------*/ +#ifdef CONFIG_OF +INT_32 glBusSetIrq(PVOID pvData, PVOID pfnIsr, PVOID pvCookie) +{ + struct device_node *node = NULL; + unsigned int irq_info[3] = { 0, 0, 0 }; + /* unsigned int phy_base; */ + unsigned int irq_id = 0; + unsigned int irq_flags = 0; + + struct net_device *prNetDevice; + + ASSERT(pvData); + if (!pvData) + return -1; + prNetDevice = (struct net_device *)pvData; + + node = of_find_compatible_node(NULL, NULL, "mediatek,wifi"); + if (node) { + irq_id = irq_of_parse_and_map(node, 0); + DBGLOG(INIT, INFO, "WIFI-OF: get wifi irq(%d)\n", irq_id); + } else { + DBGLOG(INIT, ERROR, "WIFI-OF: get wifi device node fail\n"); + } + + /* get the interrupt line behaviour */ + if (of_property_read_u32_array(node, "interrupts", irq_info, ARRAY_SIZE(irq_info))) { + DBGLOG(INIT, ERROR, "WIFI-OF: get interrupt flag from DTS fail\n"); + } else { + irq_flags = irq_info[2]; + DBGLOG(INIT, LOUD, "WIFI-OF: get interrupt flag(0x%x)\n", irq_flags); + } + + /* Register AHB IRQ */ + if (request_irq(irq_id, HifAhbISR, irq_flags, HIF_MOD_NAME, prNetDevice)) { + DBGLOG(INIT, ERROR, "WIFI-OF: request irq %d fail!\n", irq_id); + return -1; + } + + return 0; +} + +VOID glBusFreeIrq(PVOID pvData, PVOID pvCookie) +{ + struct device_node *node = NULL; + unsigned int irq_info[3] = { 0, 0, 0 }; + /* unsigned int phy_base; */ + unsigned int irq_id = 0; + unsigned int irq_flags = 0; + + struct net_device *prNetDevice; + + /* Init */ + ASSERT(pvData); + if (!pvData) + return; + prNetDevice = (struct net_device *)pvData; + + node = of_find_compatible_node(NULL, NULL, "mediatek,wifi"); + if (node) { + irq_id = irq_of_parse_and_map(node, 0); + DBGLOG(INIT, INFO, "WIFI-OF: get wifi irq(%d)\n", irq_id); + } else { + DBGLOG(INIT, ERROR, "WIFI-OF: get wifi device node fail\n"); + } + + /* get the interrupt line behaviour */ + if (of_property_read_u32_array(node, "interrupts", irq_info, ARRAY_SIZE(irq_info))) { + DBGLOG(INIT, ERROR, "WIFI-OF: get interrupt flag from DTS fail\n"); + } else { + irq_flags = irq_info[2]; + DBGLOG(INIT, LOUD, "WIFI-OF: get interrupt flag(0x%x)\n", irq_flags); + } + + /* Free the IRQ */ + free_irq(irq_id, prNetDevice); + return; + +} +#else +/* the name is different in 72 and 82 */ +#ifndef MT_WF_HIF_IRQ_ID /* for MT6572/82/92 */ +#define MT_WF_HIF_IRQ_ID WF_HIF_IRQ_ID +#endif /* MT_WF_HIF_IRQ_ID */ + +INT_32 glBusSetIrq(PVOID pvData, PVOID pfnIsr, PVOID pvCookie) +{ + int ret = 0; + struct net_device *prNetDevice; + GLUE_INFO_T *GlueInfo; + GL_HIF_INFO_T *HifInfo; + + /* Init */ + ASSERT(pvData); + if (!pvData) + return -1; + + prNetDevice = (struct net_device *)pvData; + GlueInfo = (GLUE_INFO_T *) pvCookie; + ASSERT(GlueInfo); + if (!GlueInfo) { + DBGLOG(INIT, ERROR, "GlueInfo == NULL!\n"); + return -1; + } + + HifInfo = &GlueInfo->rHifInfo; + + /* Register AHB IRQ */ + if (request_irq(MT_WF_HIF_IRQ_ID, HifAhbISR, IRQF_TRIGGER_LOW, HIF_MOD_NAME, prNetDevice)) { + DBGLOG(INIT, ERROR, "request irq %d fail!\n", MT_WF_HIF_IRQ_ID); + return -1; + } +#if (CONF_HIF_DMA_INT == 1) + if (request_irq(MT_GDMA2_IRQ_ID, HifDmaISR, IRQF_TRIGGER_LOW, "AHB_DMA", prNetDevice)) { + DBGLOG(INIT, ERROR, "request irq %d fail!\n", MT_GDMA2_IRQ_ID); + free_irq(MT_WF_HIF_IRQ_ID, prNetDevice); + return -1; + } +#endif /* CONF_HIF_DMA_INT */ + + return ret; + +} /* end of glBusSetIrq() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus interrupt operation and disable interrupt handling for os. +* +* \param[in] pvData A pointer to struct net_device. +* \param[in] pvCookie Private data for pfnIsr function. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glBusFreeIrq(PVOID pvData, PVOID pvCookie) +{ + struct net_device *prNetDevice; + GLUE_INFO_T *GlueInfo; + GL_HIF_INFO_T *HifInfo; + + /* Init */ + ASSERT(pvData); + if (!pvData) + return; + + prNetDevice = (struct net_device *)pvData; + GlueInfo = (GLUE_INFO_T *) pvCookie; + ASSERT(GlueInfo); + if (!GlueInfo) + return; + + HifInfo = &GlueInfo->rHifInfo; + + /* Free the IRQ */ + free_irq(MT_WF_HIF_IRQ_ID, prNetDevice); + return; + +} /* end of glBusreeIrq() */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Read a 32-bit device register +* +* \param[in] GlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] RegOffset Register offset +* \param[in] pu4Value Pointer to variable used to store read value +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalDevRegRead(IN GLUE_INFO_T *GlueInfo, IN UINT_32 RegOffset, OUT UINT_32 *pu4Value) +{ + GL_HIF_INFO_T *HifInfo; + + /* sanity check and init */ + ASSERT(GlueInfo); + ASSERT(pu4Value); + + if (GlueInfo == NULL || pu4Value == NULL) { + DBGLOG(HAL, ERROR, "Passing NULL pointer."); + return FALSE; + } + + HifInfo = &GlueInfo->rHifInfo; + + /* use PIO mode to read register */ + if (WlanDmaFatalErr && RegOffset != MCR_WCIR && RegOffset != MCR_WHLPCR) + return FALSE; + *pu4Value = HIF_REG_READL(HifInfo, RegOffset); + + if ((RegOffset == MCR_WRDR0) || (RegOffset == MCR_WRDR1)) + HIF_DBG(("[WiFi/HIF] kalDevRegRead from Data Port 0 or 1\n")); + + return TRUE; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write a 32-bit device register +* +* \param[in] GlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] RegOffset Register offset +* \param[in] RegValue RegValue to be written +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalDevRegWrite(IN GLUE_INFO_T *GlueInfo, IN UINT_32 RegOffset, IN UINT_32 RegValue) +{ + GL_HIF_INFO_T *HifInfo; + + /* sanity check and init */ + ASSERT(GlueInfo); + + if (GlueInfo == NULL) { + DBGLOG(INIT, ERROR, "GlueInfo is NULL."); + return FALSE; + } + + + HifInfo = &GlueInfo->rHifInfo; + + /* use PIO mode to write register */ + if (WlanDmaFatalErr && RegOffset != MCR_WCIR && RegOffset != MCR_WHLPCR) + return FALSE; + HIF_REG_WRITEL(HifInfo, RegOffset, RegValue); + + if ((RegOffset == MCR_WTDR0) || (RegOffset == MCR_WTDR1)) + HIF_DBG(("[WiFi/HIF] kalDevRegWrite to Data Port 0 or 1\n")); + + return TRUE; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Read device I/O port +* +* \param[in] GlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] Port I/O port offset +* \param[in] Size Length to be read +* \param[out] Buf Pointer to read buffer +* \param[in] MaxBufSize Length of the buffer valid to be accessed +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalDevPortRead(IN P_GLUE_INFO_T GlueInfo, IN UINT_16 Port, IN UINT_32 Size, OUT PUINT_8 Buf, IN UINT_32 MaxBufSize) +{ + GL_HIF_INFO_T *HifInfo; + UINT_32 u4HSTCRValue = 0; + UINT_32 RegWHLPCR = 0; + UINT_32 u4PortReadCntStart = 0; + UINT_32 u4PortReadCntEnd = 0; + + /* sanity check */ + if ((WlanDmaFatalErr == 1) || (fgIsResetting == TRUE) || (HifIsFwOwn(GlueInfo->prAdapter) == TRUE)) { + DBGLOG(RX, ERROR, "WlanDmaFatalErr: %d, fgIsResetting: %d, HifIsFwOwn: %d\n", + WlanDmaFatalErr, fgIsResetting, HifIsFwOwn(GlueInfo->prAdapter)); + return FALSE; + } + /* Init */ + ASSERT(GlueInfo); + HifInfo = &GlueInfo->rHifInfo; + + ASSERT(Buf); + ASSERT(Size <= MaxBufSize); + + /* Note: burst length should be equal to the one used in DMA */ + if (Port == MCR_WRDR0) + u4HSTCRValue = HifAhbDmaEnhanceModeConf(GlueInfo, HIF_BURST_4DW, HIF_TARGET_RXD0, Size); + else if (Port == MCR_WRDR1) + u4HSTCRValue = HifAhbDmaEnhanceModeConf(GlueInfo, HIF_BURST_4DW, HIF_TARGET_RXD1, Size); + else if (Port == MCR_WHISR) + u4HSTCRValue = HifAhbDmaEnhanceModeConf(GlueInfo, HIF_BURST_4DW, HIF_TARGET_WHISR, Size); + + RegWHLPCR = HIF_REG_READL(HifInfo, MCR_WHLPCR); + if ((RegWHLPCR & WHLPCR_INT_EN_SET) == 1) + HIF_REG_WRITEL(HifInfo, MCR_WHLPCR, WHLPCR_INT_EN_CLR); + + /* Read */ +#if (CONF_MTK_AHB_DMA == 1) + if ((HifInfo->fgDmaEnable == TRUE) && (HifInfo->DmaOps != NULL) + && ((Port == MCR_WRDR0) || (Port == MCR_WRDR1))) { + /* only for data port */ +#ifdef MTK_DMA_BUF_MEMCPY_SUP + VOID *DmaVBuf = NULL, *DmaPBuf = NULL; +#endif /* MTK_DMA_BUF_MEMCPY_SUP */ + GL_HIF_DMA_OPS_T *prDmaOps = HifInfo->DmaOps; + MTK_WCN_HIF_DMA_CONF DmaConf; + UINT_32 LoopCnt; + unsigned long PollTimeout; + INT_32 DmaErrorCode = 0; +#if (CONF_HIF_DMA_INT == 1) + INT_32 RtnVal = 0; +#endif + /* config DMA, Port = MCR_WRDR0 or MCR_WRDR1 */ + DmaConf.Count = Size; + DmaConf.Dir = HIF_DMA_DIR_RX; + DmaConf.Src = HIF_DRV_BASE + Port; /* must be physical addr */ + +#ifdef MTK_DMA_BUF_MEMCPY_SUP + DmaConf.Dst = kalIOPhyAddrGet(Buf); /* must be physical addr */ + + /* TODO: use virt_to_phys() */ + if (DmaConf.Dst == NULL) { + HIF_DBG(("[WiFi/HIF] Use Dma Buffer to RX packet (%d %d)...\n", Size, CFG_RX_MAX_PKT_SIZE)); + /* ASSERT(Size <= CFG_RX_MAX_PKT_SIZE); */ + + kalDmaBufGet(HifInfo->Dev, &DmaVBuf, &DmaPBuf); + DmaConf.Dst = (ULONG) DmaPBuf; + } +#else + /* + * http://kernelnewbies.org/KernelMemoryAllocation + * Since the cache-coherent mapping may be expensive, also a streaming allocation exists. + * + * This is a buffer for one-way communication, which means coherency is limited to + * flushing the data from the cache after a write finishes. The buffer has to be + * pre-allocated (e.g. using kmalloc()). DMA for it is set up with dma_map_single(). + * + * When the DMA is finished (e.g. when the device has sent an interrupt signaling end of + * DMA), call dma_unmap_single(). Between map and unmap, the device is in control of the + * buffer: if you write to the device, do it before dma_map_single(), if you read from + * it, do it after dma_unmap_single(). + */ + /* DMA_FROM_DEVICE invalidated (without writeback) the cache */ + /* TODO: if dst_off was not cacheline aligned */ + DmaConf.Dst = dma_map_single(HifInfo->Dev, Buf, Size, DMA_FROM_DEVICE); + DmaErrorCode = dma_mapping_error(HifInfo->Dev, DmaConf.Dst); + if (DmaErrorCode != 0) + DBGLOG(RX, INFO, "DMA mapping error: %d\n", DmaErrorCode); +#endif /* MTK_DMA_BUF_MEMCPY_SUP */ + + /* start to read data */ + AP_DMA_HIF_LOCK(HifInfo); /* lock to avoid other codes config GDMA */ + + prDmaOps->DmaClockCtrl(TRUE); + prDmaOps->DmaConfig(HifInfo, &DmaConf); + prDmaOps->DmaStart(HifInfo); + +#if (CONF_HIF_DMA_INT == 1) + RtnVal = wait_event_interruptible_timeout(HifInfo->HifDmaWaitq, (HifInfo->HifDmaWaitFlg != 0), 1000); + if (RtnVal <= 0) + DBGLOG(RX, ERROR, "fatal error1! reset DMA!\n"); + HifInfo->HifDmaWaitFlg = 0; +#else + PollTimeout = jiffies + HZ * 5; + + if (HifInfo->fgDmaUsleepEnable && GlueInfo->fgIsFwDlDone) { + /* usleep while polling to reduce CPUusage */ + do { + if (time_before(jiffies, PollTimeout)) { + u4PortReadCntStart++; + kalUsleepRange(1, 1); + continue; + } + DBGLOG(RX, INFO, "RX DMA Timeout, HSTCR: 0x%08x, and dump WHISR EnhanceMode data\n", + u4HSTCRValue); + HifDumpEnhanceModeData(GlueInfo->prAdapter); + if (prDmaOps->DmaRegDump != NULL) + prDmaOps->DmaRegDump(HifInfo); + WlanDmaFatalErr = 1; + /* we still need complete dma progress even dma timeout */ + break; + } while (!prDmaOps->DmaPollIntr(HifInfo)); + } else { + do { + if (time_before(jiffies, PollTimeout)) + continue; + DBGLOG(RX, INFO, "RX DMA Timeout, HSTCR: 0x%08x, and dump WHISR EnhanceMode data\n", + u4HSTCRValue); + HifDumpEnhanceModeData(GlueInfo->prAdapter); + if (prDmaOps->DmaRegDump != NULL) + prDmaOps->DmaRegDump(HifInfo); + WlanDmaFatalErr = 1; + /* we still need complete dma progress even dma timeout */ + break; + } while (!prDmaOps->DmaPollIntr(HifInfo)); + } + +#endif /* CONF_HIF_DMA_INT */ + /* + * we should disable dma interrupt then clear dma interrupt, otherwise, + * for dma timeout case, interrupt may be set after we clear it + */ + prDmaOps->DmaStop(HifInfo); + prDmaOps->DmaAckIntr(HifInfo); + + LoopCnt = 0; + if (HifInfo->fgDmaUsleepEnable && GlueInfo->fgIsFwDlDone) { + /* usleep while polling to reduce CPU usage */ + do { + if (LoopCnt++ > 100000) { + /* TODO: impossible! reset DMA */ + DBGLOG(RX, ERROR, "fatal error2! reset DMA!\n"); + break; + } + u4PortReadCntEnd++; + kalUsleepRange(1, 1); + } while (prDmaOps->DmaPollStart(HifInfo) != 0); + } else { + do { + if (LoopCnt++ > 100000) { + /* TODO: impossible! reset DMA */ + DBGLOG(RX, ERROR, "fatal error2! reset DMA!\n"); + break; + } + } while (prDmaOps->DmaPollStart(HifInfo) != 0); + } + + prDmaOps->DmaClockCtrl(FALSE); + + AP_DMA_HIF_UNLOCK(HifInfo); + +#ifdef MTK_DMA_BUF_MEMCPY_SUP + if (DmaVBuf != NULL) + kalMemCopy(Buf, DmaVBuf, Size); +#else + dma_unmap_single(HifInfo->Dev, DmaConf.Dst, Size, DMA_FROM_DEVICE); +#endif /* MTK_DMA_BUF_MEMCPY_SUP */ + + if ((RegWHLPCR & WHLPCR_INT_EN_SET) == 1) + HIF_REG_WRITEL(HifInfo, MCR_WHLPCR, WHLPCR_INT_EN_SET); + + if (WlanDmaFatalErr) { + if (!fgIsResetting) + GL_RESET_TRIGGER(GlueInfo->prAdapter, RST_FLAG_CHIP_RESET); + return FALSE; + } + HIF_DBG(("[WiFi/HIF] DMA RX OK!\n")); + DBGLOG(TX, LOUD, "u4PortReadCntStart,%d,u4PortReadCntEnd,%d\n", + u4PortReadCntStart, u4PortReadCntEnd); + } else +#endif /* CONF_MTK_AHB_DMA */ + { + UINT_32 IdLoop, MaxLoop; + UINT_32 *LoopBuf; + + /* default PIO mode */ + MaxLoop = Size >> 2; + if (Size & 0x3) + MaxLoop++; + LoopBuf = (UINT_32 *) Buf; + + if (LoopBuf != NULL) { + for (IdLoop = 0; + IdLoop < MaxLoop; IdLoop++) { + + *LoopBuf = HIF_REG_READL(HifInfo, Port); + LoopBuf++; + } + + if ((RegWHLPCR & WHLPCR_INT_EN_SET) == 1) + HIF_REG_WRITEL(HifInfo, MCR_WHLPCR, WHLPCR_INT_EN_SET); + } + } + + return TRUE; + +} /* end of kalDevPortRead() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write device I/O port +* +* \param[in] GlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] Port I/O port offset +* \param[in] Size Length to be write +* \param[in] Buf Pointer to write buffer +* \param[in] MaxBufSize Length of the buffer valid to be accessed +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalDevPortWrite(IN P_GLUE_INFO_T GlueInfo, IN UINT_16 Port, IN UINT_32 Size, IN PUINT_8 Buf, IN UINT_32 MaxBufSize) +{ + GL_HIF_INFO_T *HifInfo; + UINT_32 u4HSTCRValue = 0; + UINT_32 RegWHLPCR = 0; + UINT_32 u4PortWriteCntStart = 0; + UINT_32 u4PortWriteCntEnd = 0; + + /* sanity check */ + if ((WlanDmaFatalErr == 1) || (fgIsResetting == TRUE) || (HifIsFwOwn(GlueInfo->prAdapter) == TRUE)) { + DBGLOG(RX, ERROR, "WlanDmaFatalErr: %d, fgIsResetting: %d, HifIsFwOwn: %d\n", + WlanDmaFatalErr, fgIsResetting, HifIsFwOwn(GlueInfo->prAdapter)); + return FALSE; + } + + /* Init */ + ASSERT(GlueInfo); + HifInfo = &GlueInfo->rHifInfo; + + ASSERT(Buf); + ASSERT(Size <= MaxBufSize); + + HifTxCnt++; + + /* Note: burst length should be equal to the one used in DMA */ + if (Port == MCR_WTDR0) + u4HSTCRValue = HifAhbDmaEnhanceModeConf(GlueInfo, HIF_BURST_4DW, HIF_TARGET_TXD0, Size); + else if (Port == MCR_WTDR1) + u4HSTCRValue = HifAhbDmaEnhanceModeConf(GlueInfo, HIF_BURST_4DW, HIF_TARGET_TXD1, Size); + /* else other non-data port */ + + RegWHLPCR = HIF_REG_READL(HifInfo, MCR_WHLPCR); + if ((RegWHLPCR & WHLPCR_INT_EN_SET) == 1) + HIF_REG_WRITEL(HifInfo, MCR_WHLPCR, WHLPCR_INT_EN_CLR); + + /* Write */ +#if (CONF_MTK_AHB_DMA == 1) + if ((HifInfo->fgDmaEnable == TRUE) && (HifInfo->DmaOps != NULL) && ((Port == MCR_WTDR0) || + (Port == MCR_WTDR1))) { + /* only for data port */ +#ifdef MTK_DMA_BUF_MEMCPY_SUP + VOID *DmaVBuf = NULL, *DmaPBuf = NULL; +#endif /* MTK_DMA_BUF_MEMCPY_SUP */ + GL_HIF_DMA_OPS_T *prDmaOps = HifInfo->DmaOps; + MTK_WCN_HIF_DMA_CONF DmaConf; + UINT_32 LoopCnt; + unsigned long PollTimeout; + INT_32 DmaErrorCode = 0; +#if (CONF_HIF_DMA_INT == 1) + INT_32 RtnVal = 0; +#endif + + kalMemSet(&DmaConf, 0, sizeof(MTK_WCN_HIF_DMA_CONF)); + /* config GDMA */ + HIF_DBG_TX(("[WiFi/HIF/DMA] Prepare to send data...\n")); + DmaConf.Count = Size; + DmaConf.Dir = HIF_DMA_DIR_TX; + DmaConf.Dst = HIF_DRV_BASE + Port; /* must be physical addr */ + +#ifdef MTK_DMA_BUF_MEMCPY_SUP + DmaConf.Src = kalIOPhyAddrGet(Buf); /* must be physical addr */ + + /* TODO: use virt_to_phys() */ + if (DmaConf.Src == NULL) { + HIF_DBG_TX(("[WiFi/HIF] Use Dma Buffer to TX packet (%d %d)...\n", Size, CFG_RX_MAX_PKT_SIZE)); + /* ASSERT(Size <= CFG_RX_MAX_PKT_SIZE); */ + + kalDmaBufGet(HifInfo->Dev, &DmaVBuf, &DmaPBuf); + DmaConf.Src = (ULONG) DmaPBuf; + + kalMemCopy(DmaVBuf, Buf, Size); + } +#else + + /* DMA_TO_DEVICE writeback the cache */ + DmaConf.Src = dma_map_single(HifInfo->Dev, Buf, Size, DMA_TO_DEVICE); + DmaErrorCode = dma_mapping_error(HifInfo->Dev, DmaConf.Src); + if (DmaErrorCode != 0) + DBGLOG(TX, INFO, "DMA mapping error: %d\n", DmaErrorCode); +#endif /* MTK_DMA_BUF_MEMCPY_SUP */ + + /* start to write */ + AP_DMA_HIF_LOCK(HifInfo); + + prDmaOps->DmaClockCtrl(TRUE); + prDmaOps->DmaConfig(HifInfo, &DmaConf); + prDmaOps->DmaStart(HifInfo); + +#if (CONF_HIF_DMA_INT == 1) + RtnVal = wait_event_interruptible_timeout(HifInfo->HifDmaWaitq, (HifInfo->HifDmaWaitFlg != 0), 1000); + if (RtnVal <= 0) + DBGLOG(TX, ERROR, "fatal error1! reset DMA!\n"); + HifInfo->HifDmaWaitFlg = 0; +#else + + LoopCnt = 0; + PollTimeout = jiffies + HZ * 5; + + if (HifInfo->fgDmaUsleepEnable && GlueInfo->fgIsFwDlDone) { + /* usleep while polling to reduce CPU usage */ + do { + if (time_before(jiffies, PollTimeout)) { + u4PortWriteCntStart++; + kalUsleepRange(1, 1); + continue; + } + DBGLOG(TX, INFO, "TX DMA Timeout, HSTCR: 0x%08x\n", u4HSTCRValue); + if (prDmaOps->DmaRegDump != NULL) + prDmaOps->DmaRegDump(HifInfo); + WlanDmaFatalErr = 1; + /* we still need complete dma progress even dma timeout */ + break; + } while (!prDmaOps->DmaPollIntr(HifInfo)); + } else { + do { + if (time_before(jiffies, PollTimeout)) + continue; + DBGLOG(TX, INFO, "TX DMA Timeout, HSTCR: 0x%08x\n", u4HSTCRValue); + if (prDmaOps->DmaRegDump != NULL) + prDmaOps->DmaRegDump(HifInfo); + WlanDmaFatalErr = 1; + /* we still need complete dma progress even dma timeout */ + break; + } while (!prDmaOps->DmaPollIntr(HifInfo)); + } + +#endif /* CONF_HIF_DMA_INT */ + /* + * we should disable dma interrupt then clear dma interrupt, otherwise, + * for dma timeout case, interrupt may be set after we clear it + */ + prDmaOps->DmaStop(HifInfo); + prDmaOps->DmaAckIntr(HifInfo); + + LoopCnt = 0; + if (HifInfo->fgDmaUsleepEnable && GlueInfo->fgIsFwDlDone) { + /* usleep while polling to reduce CPU usage */ + do { + if (LoopCnt++ > 100000) { + DBGLOG(TX, ERROR, "fatal error2! reset DMA!\n"); + break; + } + u4PortWriteCntEnd++; + kalUsleepRange(1, 1); + } while (prDmaOps->DmaPollStart(HifInfo) != 0); + } else { + do { + if (LoopCnt++ > 100000) { + DBGLOG(TX, ERROR, "fatal error2! reset DMA!\n"); + break; + } + } while (prDmaOps->DmaPollStart(HifInfo) != 0); + } + + prDmaOps->DmaClockCtrl(FALSE); + + AP_DMA_HIF_UNLOCK(HifInfo); + +#ifndef MTK_DMA_BUF_MEMCPY_SUP + dma_unmap_single(HifInfo->Dev, DmaConf.Src, Size, DMA_TO_DEVICE); +#endif /* MTK_DMA_BUF_MEMCPY_SUP */ + + if ((RegWHLPCR & WHLPCR_INT_EN_SET) == 1) + HIF_REG_WRITEL(HifInfo, MCR_WHLPCR, WHLPCR_INT_EN_SET); + + if (WlanDmaFatalErr) { + if (!fgIsResetting) + GL_RESET_TRIGGER(GlueInfo->prAdapter, RST_FLAG_CHIP_RESET); + return FALSE; + } + HIF_DBG_TX(("[WiFi/HIF] DMA TX OK!\n")); + DBGLOG(TX, LOUD, "u4PortWriteCntStart,%d,u4PortWriteCntEnd,%d\n", + u4PortWriteCntStart, u4PortWriteCntEnd); + } else +#endif /* CONF_MTK_AHB_DMA */ + { + UINT_32 IdLoop, MaxLoop; + UINT_32 *LoopBuf; + + /* PIO mode */ + MaxLoop = Size >> 2; + LoopBuf = (UINT_32 *) Buf; + + if (LoopBuf != NULL) { + HIF_DBG_TX(("[WiFi/HIF/PIO] Prepare to send data (%d 0x%p-0x%p)...\n", + Size, LoopBuf, (((UINT8 *) LoopBuf) + (Size & (~0x03))))); + + if (Size & 0x3) + MaxLoop++; + + for (IdLoop = 0; + IdLoop < MaxLoop; IdLoop++) { + HIF_REG_WRITEL(HifInfo, Port, *LoopBuf); + LoopBuf++; + } + + if ((RegWHLPCR & WHLPCR_INT_EN_SET) == 1) + HIF_REG_WRITEL(HifInfo, MCR_WHLPCR, WHLPCR_INT_EN_SET); + + HIF_DBG_TX(("\n\n")); + } + } + + return TRUE; + +} /* end of kalDevPortWrite() */ + +/******************************************************************************* +* P R I V A T E F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a SDIO interrupt callback function +* +* \param[in] func pointer to SDIO handle +* +* \return void +*/ +/*----------------------------------------------------------------------------*/ +static irqreturn_t HifAhbISR(IN int Irq, IN void *Arg) +{ + struct net_device *prNetDevice = (struct net_device *)Arg; + GLUE_INFO_T *GlueInfo; + GL_HIF_INFO_T *HifInfo; + + /* Init */ + IsrCnt++; + ASSERT(prNetDevice); + + if (!prNetDevice) + return IRQ_HANDLED; + + GlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDevice)); + ASSERT(GlueInfo); + + if (!GlueInfo) + return IRQ_HANDLED; + + HifInfo = &GlueInfo->rHifInfo; + + GlueInfo->IsrCnt++; + + if (GlueInfo->ulFlag & GLUE_FLAG_HALT) { + HIF_REG_WRITEL(HifInfo, MCR_WHLPCR, WHLPCR_INT_EN_CLR); + return IRQ_HANDLED; + } + + HIF_REG_WRITEL(HifInfo, MCR_WHLPCR, WHLPCR_INT_EN_CLR); + + /* lock 100ms to avoid suspend */ + kalHifAhbKalWakeLockTimeout(GlueInfo); + + /* Wake up main thread */ + set_bit(GLUE_FLAG_INT_BIT, &GlueInfo->ulFlag); + + /* when we got sdio interrupt, we wake up the tx servie thread */ + wake_up_interruptible(&GlueInfo->waitq); + + IsrPassCnt++; + GlueInfo->IsrPassCnt++; + return IRQ_HANDLED; + +} + +#if (CONF_HIF_DMA_INT == 1) +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a SDIO interrupt callback function +* +* \param[in] func pointer to SDIO handle +* +* \return void +*/ +/*----------------------------------------------------------------------------*/ + +static irqreturn_t HifDmaISR(IN int Irq, IN void *Arg) +{ + struct net_device *prNetDevice = (struct net_device *)Arg; + GLUE_INFO_T *GlueInfo; + GL_HIF_INFO_T *HifInfo; + + /* Init */ + ASSERT(prNetDevice); + GlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDevice)); + ASSERT(GlueInfo); + + if (!GlueInfo) + return IRQ_HANDLED; + HifInfo = &GlueInfo->rHifInfo; + + /* disable interrupt */ + HifInfo->DmaOps->DmaAckIntr(HifInfo); + + /* Wake up main thread */ + set_bit(1, &HifInfo->HifDmaWaitFlg); + + /* when we got sdio interrupt, we wake up the tx servie thread */ + wake_up_interruptible(&HifInfo->HifDmaWaitq); + + return IRQ_HANDLED; + +} +#endif /* CONF_HIF_DMA_INT */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a SDIO probe function +* +* \param[in] func pointer to SDIO handle +* \param[in] id pointer to SDIO device id table +* +* \return void +*/ +/*----------------------------------------------------------------------------*/ +#if defined(CONFIG_MTK_CLKMGR) +#if defined(MTK_EXTERNAL_LDO) || defined(MTK_ALPS_BOX_SUPPORT) +#include +#endif +#endif + +static int HifAhbProbe(VOID) +{ + int Ret = 0; + + DBGLOG(INIT, INFO, "HifAhbProbe()\n"); + + /* power on WiFi TX PA 3.3V and HIF GDMA clock */ + { +#ifdef CONFIG_MTK_PMIC_MT6397 +#if defined(CONFIG_MTK_CLKMGR) +#ifdef MTK_EXTERNAL_LDO + /* for 8127 tablet */ + mt_set_gpio_mode(GPIO51, GPIO_MODE_04); + mt_set_gpio_dir(GPIO51, GPIO_DIR_OUT); + mt_set_gpio_pull_enable(GPIO51, GPIO_PULL_ENABLE); + mt_set_gpio_pull_select(GPIO51, GPIO_PULL_UP); +#elif defined(MTK_ALPS_BOX_SUPPORT) + /* for 8127 box */ + mt_set_gpio_mode(GPIO89, GPIO_MODE_04); + mt_set_gpio_dir(GPIO89, GPIO_DIR_OUT); + mt_set_gpio_pull_enable(GPIO89, GPIO_PULL_ENABLE); + mt_set_gpio_pull_select(GPIO89, GPIO_PULL_UP); +#else + hwPowerOn(MT65XX_POWER_LDO_VGP4, VOL_3300, "WLAN"); +#endif +#endif +#else +#ifdef CONFIG_OF /*for MT6752 */ + mtk_wcn_consys_hw_wifi_paldo_ctrl(1); /* switch to HW mode */ +#else /*for MT6572/82/92 */ + hwPowerOn(MT6323_POWER_LDO_VCN33_WIFI, VOL_3300, "WLAN"); + upmu_set_vcn33_on_ctrl_wifi(1); /* switch to HW mode */ +#endif +#endif + + } + +#if (CONF_HIF_DEV_MISC == 1) + if (pfWlanProbe((PVOID) &MtkAhbDriver.this_device) != WLAN_STATUS_SUCCESS) { +#else + if (pfWlanProbe((PVOID) &HifAhbPDev->dev) != WLAN_STATUS_SUCCESS) { +#endif /* CONF_HIF_DEV_MISC */ + + pfWlanRemove(); + Ret = -1; + } + + return Ret; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do module remove. +* +* \param[in] None +* +* \return The result of remove (WLAN_STATUS_SUCCESS = 0) +*/ +/*----------------------------------------------------------------------------*/ +static int HifAhbRemove(VOID) +{ + DBGLOG(INIT, INFO, "HifAhbRemove()\n"); + + pfWlanRemove(); + + { +#ifdef CONFIG_MTK_PMIC_MT6397 +#if defined(CONFIG_MTK_CLKMGR) +#ifdef MTK_EXTERNAL_LDO + /* for 8127 tablet */ + mt_set_gpio_mode(GPIO51, GPIO_MODE_04); + mt_set_gpio_dir(GPIO51, GPIO_DIR_OUT); + mt_set_gpio_pull_enable(GPIO51, GPIO_PULL_ENABLE); + mt_set_gpio_pull_select(GPIO51, GPIO_PULL_DOWN); +#elif defined(MTK_ALPS_BOX_SUPPORT) + /* for 8127 box */ + mt_set_gpio_mode(GPIO89, GPIO_MODE_04); + mt_set_gpio_dir(GPIO89, GPIO_DIR_OUT); + mt_set_gpio_pull_enable(GPIO89, GPIO_PULL_ENABLE); + mt_set_gpio_pull_select(GPIO89, GPIO_PULL_DOWN); +#else + hwPowerDown(MT65XX_POWER_LDO_VGP4, "WLAN"); +#endif +#endif +#else +#ifdef CONFIG_OF /*for MT6752 */ + mtk_wcn_consys_hw_wifi_paldo_ctrl(0); /* switch to SW mode */ +#else /*for MT6572/82/92 */ + upmu_set_vcn33_on_ctrl_wifi(0); /* switch to SW mode */ + hwPowerDown(MT6323_POWER_LDO_VCN33_WIFI, "WLAN"); +#endif +#endif + + } + + return 0; +} + +#if (MTK_WCN_SINGLE_MODULE == 0) +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function gets the TX count pass through HIF AHB bus. +* +* \param[in] None +* +* \return TX count +*/ +/*----------------------------------------------------------------------------*/ +static int HifAhbBusCntGet(VOID) +{ + return HifTxCnt; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function resets the TX count pass through HIF AHB bus. +* +* \param[in] None +* +* \return 0 +*/ +/*----------------------------------------------------------------------------*/ +static int HifAhbBusCntClr(VOID) +{ + HifTxCnt = 0; + return 0; +} + +int __weak HifAhbSetMpuProtect(bool enable) +{ + return 0; +} +#endif /* MTK_WCN_SINGLE_MODULE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function configs the DMA TX/RX settings before any real TX/RX. +* +* \param[in] GlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] BurstLen 0(1DW), 1(4DW), 2(8DW), Others(Reserved) +* \param[in] PortId 0(TXD0), 1(TXD1), 2(RXD0), 3(RXD1), 4(WHISR enhance) +* \param[in] TransByte Should be 4-byte align. +* +* \return void +*/ +/*----------------------------------------------------------------------------*/ +static UINT_32 HifAhbDmaEnhanceModeConf(GLUE_INFO_T *GlueInfo, UINT_32 BurstLen, UINT_32 PortId, UINT_32 TransByte) +{ + GL_HIF_INFO_T *HifInfo; + UINT_32 RegHSTCR; + + ASSERT(GlueInfo); + + if (GlueInfo == NULL) { + DBGLOG(INIT, ERROR, "GlueInfo is NULL."); + return 0; + } + + HifInfo = &GlueInfo->rHifInfo; + + RegHSTCR = HIF_REG_READL(HifInfo, MCR_WHIER); + + RegHSTCR = HIF_REG_READL(HifInfo, MCR_HSTCR); + RegHSTCR = + ((BurstLen << HSTCR_AFF_BURST_LEN_OFFSET) & HSTCR_AFF_BURST_LEN) | + ((PortId << HSTCR_TRANS_TARGET_OFFSET) & HSTCR_TRANS_TARGET) | + (((TransByte & 0x3) == 0) ? (TransByte & HSTCR_HSIF_TRANS_CNT) : ((TransByte + 4) & HSTCR_HSIF_TRANS_CNT)); + HIF_REG_WRITEL(HifInfo, MCR_HSTCR, RegHSTCR); + return RegHSTCR; +} + +VOID glSetPowerState(IN GLUE_INFO_T *GlueInfo, IN UINT_32 ePowerMode) +{ + +} + +#if (CONF_HIF_DEV_MISC == 1) +/* no use */ +static ssize_t HifAhbMiscRead(IN struct file *Filp, OUT char __user *DstBuf, IN size_t Size, IN loff_t *Ppos) +{ + return 0; +} + +static ssize_t HifAhbMiscWrite(IN struct file *Filp, IN const char __user *SrcBuf, IN size_t Size, IN loff_t *Ppos) +{ + return 0; +} + +static int HifAhbMiscIoctl(IN struct file *Filp, IN unsigned int Cmd, IN unsigned long arg) +{ + return 0; +} + +static int HifAhbMiscOpen(IN struct inode *Inodep, IN struct file *Filp) +{ + return 0; +} + +static int HifAhbMiscClose(IN struct inode *Inodep, IN struct file *Filp) +{ + return 0; +} +#else + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called by OS platform device module. +* +* \param[in] PDev Pointer to the platform device structure. +* +* \return 0 +*/ +/*----------------------------------------------------------------------------*/ +static int HifAhbPltmProbe(IN struct platform_device *PDev) +{ + HifAhbPDev = PDev; + + DBGLOG(INIT, INFO, "HifAhbPltmProbe\n"); + +#if (CONF_HIF_PMIC_TEST == 1) + wmt_set_jtag_for_mcu(); + wmt_set_jtag_for_gps(); + +#endif /* CONF_HIF_PMIC_TEST */ + +#if (MTK_WCN_SINGLE_MODULE == 1) + HifAhbProbe(); /* only for test purpose without WMT module */ + +#else + + /* register WiFi function to WMT */ + DBGLOG(INIT, INFO, "mtk_wcn_wmt_wlan_reg\n"); + { + MTK_WCN_WMT_WLAN_CB_INFO WmtCb; + + kalMemZero(&WmtCb, sizeof(MTK_WCN_WMT_WLAN_CB_INFO)); + WmtCb.wlan_probe_cb = HifAhbProbe; + WmtCb.wlan_remove_cb = HifAhbRemove; + WmtCb.wlan_bus_cnt_get_cb = HifAhbBusCntGet; + WmtCb.wlan_bus_cnt_clr_cb = HifAhbBusCntClr; + WmtCb.wlan_emi_mpu_set_protection_cb = HifAhbSetMpuProtect; + mtk_wcn_wmt_wlan_reg(&WmtCb); + } +#endif /* MTK_WCN_SINGLE_MODULE */ + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called by OS platform device module. +* +* \param[in] PDev Pointer to the platform device structure. +* +* \return 0 +*/ +/*----------------------------------------------------------------------------*/ +static int __exit HifAhbPltmRemove(IN struct platform_device *PDev) +{ +#if (MTK_WCN_SINGLE_MODULE == 0) + mtk_wcn_wmt_wlan_unreg(); +#endif /* MTK_WCN_SINGLE_MODULE */ + return 0; +} + +#ifdef CONFIG_PM +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called by OS platform device module. +* +* \param[in] PDev Pointer to the platform device structure. +* \param[in] Message +* +* \return 0 +*/ +/*----------------------------------------------------------------------------*/ +static int HifAhbPltmSuspend(IN struct platform_device *PDev, pm_message_t Message) +{ + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called by OS platform device module. +* +* \param[in] PDev Pointer to the platform device structure. +* +* \return 0 +*/ +/*----------------------------------------------------------------------------*/ +static int HifAhbPltmResume(IN struct platform_device *PDev) +{ + return 0; +} +#endif /* CONFIG_PM */ + +#endif /* CONF_HIF_DEV_MISC */ + +#if (CONF_HIF_LOOPBACK_AUTO == 1) +/*----------------------------------------------------------------------------*/ +/*! +* \brief Trigger to do HIF loopback test. +* +* \param[in] arg Pointer to the GLUE_INFO_T structure. +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(4, 15, 0) <= CFG80211_VERSION_CODE +static VOID HifAhbLoopbkAuto(struct timer_list *timer) +#else +static VOID HifAhbLoopbkAuto(IN unsigned long arg) +#endif +{ +#if KERNEL_VERSION(4, 15, 0) <= CFG80211_VERSION_CODE + GL_HIF_INFO_T *HifInfo = from_timer(HifInfo, timer, HifTmrLoopbkFn); +#else + P_GLUE_INFO_T GlueInfo = (P_GLUE_INFO_T) arg; + GL_HIF_INFO_T *HifInfo = &GlueInfo->rHifInfo; +#endif + ASSERT(GlueInfo); + + HIF_DBG(("[WiFi/HIF] Trigger to do loopback test...\n")); + + set_bit(GLUE_FLAG_HIF_LOOPBK_AUTO_BIT, &HifInfo->HifLoopbkFlg); + wake_up_interruptible(&HifInfo->HifWaitq); + +} +#endif /* CONF_HIF_LOOPBACK_AUTO */ + +VOID glDumpConnSysCpuInfo(P_GLUE_INFO_T prGlueInfo) +{ + GL_HIF_INFO_T *prHifInfo = &prGlueInfo->rHifInfo; + unsigned short j; + + for (j = 0; j < 512; j++) { + DBGLOG(INIT, WARN, "0x%08x ", MCU_REG_READL(prHifInfo, CONN_MCU_CPUPCR)); + if ((j + 1) % 16 == 0) + DBGLOG(INIT, WARN, "\n"); + } +} + +/* End of ahb.c */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/hif/ahb/arm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/hif/ahb/arm.c new file mode 100644 index 0000000000000..52afe9cca31c3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/hif/ahb/arm.c @@ -0,0 +1,12 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/hif/ahb/include/hif.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/hif/ahb/include/hif.h new file mode 100644 index 0000000000000..672e4d92bed74 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/hif/ahb/include/hif.h @@ -0,0 +1,316 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _HIF_H +#define _HIF_H + +#include "gl_typedef.h" +#include "mtk_porting.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#define CONF_MTK_AHB_DMA 1 /* PIO mode is default mode if DMA is disabled */ + +#define CONF_HIF_DEV_MISC 0 /* register as misc device */ +#define CONF_HIF_LOOPBACK_AUTO 0 /* hif loopback test triggered by open() */ + /* only for development test */ + +#define CONF_HIF_PMIC_TEST 0 /* test purpose: power on CONNSYS */ + +#define CONF_HIF_DMA_INT 0 /* DMA interrupt mode */ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +extern phys_addr_t gConEmiPhyBase; +extern BOOLEAN fgIsResetting; +extern UINT_32 IsrCnt, IsrPassCnt; +extern int kalDevLoopbkThread(IN void *data); + +#ifdef CONFIG_MTK_PMIC_MT6397 +#else +#ifdef CONFIG_OF /*for MT6752 */ +extern INT_32 mtk_wcn_consys_hw_wifi_paldo_ctrl(UINT_32 enable); +#else /*for MT6572/82/92 */ +extern void upmu_set_vcn33_on_ctrl_wifi(UINT_32 val); +#endif +#endif + +#if (CONF_HIF_DEV_MISC == 1) +#else +/* extern INT32 mtk_wcn_consys_hw_reg_ctrl(UINT32 on, UINT32 co_clock_en); */ +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#ifndef CONN_MCU_CONFIG_BASE +#define CONN_MCU_CONFIG_BASE 0xF8070000 /* MT6572 */ +#endif /* CONN_MCU_CONFIG_BASE */ + +#define CONSYS_CPUPCR_REG (CONN_MCU_CONFIG_BASE + 0x00000160) +#define CONSYS_REG_READ(addr) (*((volatile unsigned int *)(addr))) + +#define CONN_MCU_DRV_BASE 0x18070000 +#define CONN_MCU_CHIPID 0x0008 + +#define CONN_MCU_REG_LENGTH 0x0200 +#define CONN_MCU_CPUPCR 0x0160 + +#define AP_MCU_DRV_BASE 0x18090000 +#define AP_MCU_TX_RX_LENGTH 0x10100 +#define AP_MCU_TX_DESC_ADDR 0x0000 +#define AP_MCU_RX_DESC_ADDR 0x8080 +#define AP_MCU_BANK_OFFSET 0x1010 + +#if (CFG_SRAM_SIZE_OPTION == 0) +#define AP_MCU_TC_INDEX_4_ADDR 0x1E50 +#elif (CFG_SRAM_SIZE_OPTION == 1) +#define AP_MCU_TC_INDEX_4_ADDR 0x2848 +#elif (CFG_SRAM_SIZE_OPTION == 2) +#define AP_MCU_TC_INDEX_4_ADDR 0x2F28 +#endif +#define AP_MCU_TC_INDEX_4_OFFSET 0x0018 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/* host interface's private data structure, which is attached to os glue +** layer info structure. + */ +typedef struct _GL_HIF_DMA_OPS_T { /* DMA Operators */ + void (*DmaConfig)(IN PVOID HifInfo, IN PVOID Conf); + + void (*DmaStart)(IN PVOID HifInfo); + + void (*DmaStop)(IN PVOID HifInfo); + + INT32 (*DmaPollStart)(IN PVOID HifInfo); + + INT32 (*DmaPollIntr)(IN PVOID HifInfo); + + void (*DmaAckIntr)(IN PVOID HifInfo); + + void (*DmaClockCtrl)(IN UINT_32 FlgIsEnabled); + + void (*DmaRegDump)(IN PVOID HifInfo); + + void (*DmaReset)(IN PVOID HifInfo); + +} GL_HIF_DMA_OPS_T; + +typedef struct _GL_HIF_INFO_T { + + /* General */ + VOID *Dev; /* struct device */ + +#define MTK_CHIP_ID_6571 0x6571 +#define MTK_CHIP_ID_6572 0x6572 +#define MTK_CHIP_ID_6582 0x6582 +#define MTK_CHIP_ID_8127 0x8127 +#define MTK_CHIP_ID_6752 0x6752 +#define MTK_CHIP_ID_8163 0x8163 +#define MTK_CHIP_ID_8167 0x8167 +#define MTK_CHIP_ID_6735 0x6735 +#define MTK_CHIP_ID_6570 0x6570 +#define MTK_CHIP_ID_6580 0x6580 +#define MTK_CHIP_ID_6755 0x6755 +#define MTK_CHIP_ID_7623 0x7623 + + UINT_32 ChipID; + + /* Control flag */ + BOOLEAN fgIntReadClear; + BOOLEAN fgMbxReadClear; + BOOLEAN fgDmaEnable; /* TRUE: DMA mode is used (default) */ + BOOLEAN fgDmaUsleepEnable; /* TRUE: While DMA pooling, usleep is used (default) */ + + /* HIF related */ + UINT_8 *HifRegBaseAddr; /* HIF register base */ + UINT_8 *McuRegBaseAddr; /* CONN MCU register base */ + UINT_8 *APMcuRegBaseAddr; /* APMcu register base */ + +#if (CONF_HIF_LOOPBACK_AUTO == 1) + struct timer_list HifTmrLoopbkFn; /* HIF loopback test trigger timer */ + wait_queue_head_t HifWaitq; + UINT_32 HifLoopbkFlg; + struct task_struct *HifTaskLoopbkFn; /* HIF loopback test task */ +#endif /* CONF_HIF_LOOPBACK_AUTO */ + +#if (CONF_HIF_DMA_INT == 1) + wait_queue_head_t HifDmaWaitq; + UINT_32 HifDmaWaitFlg; +#endif /* CONF_HIF_DMA_INT */ + + /* DMA related */ +#define AP_DMA_HIF_LOCK(_lock) /* spin_lock_bh(&(_lock)->DdmaLock) */ +#define AP_DMA_HIF_UNLOCK(_lock) /* spin_unlock_bh(&(_lock)->DdmaLock) */ + spinlock_t DdmaLock; /* protect DMA access */ + + UINT_8 *DmaRegBaseAddr; /* DMA register base */ + GL_HIF_DMA_OPS_T *DmaOps; /* DMA Operators */ + +#if !defined(CONFIG_MTK_CLKMGR) + struct clk *clk_wifi_dma; +#endif +} GL_HIF_INFO_T, *P_GL_HIF_INFO_T; + +#define HIF_MOD_NAME "AHB_SLAVE_HIF" + +#define HIF_DRV_BASE 0x180F0000 +#define HIF_DRV_LENGTH 0x005c + +typedef enum _MTK_WCN_HIF_BURST_LEN { + HIF_BURST_1DW = 0, + HIF_BURST_4DW, + HIF_BURST_8DW +} MTK_WCN_HIF_BURST_LEN; + +typedef enum _MTK_WCN_HIF_TXRX_TARGET { + HIF_TARGET_TXD0 = 0, + HIF_TARGET_TXD1, + HIF_TARGET_RXD0, + HIF_TARGET_RXD1, + HIF_TARGET_WHISR +} MTK_WCN_HIF_TXRX_TARGET; + +typedef enum _MTK_WCN_HIF_DMA_DIR { + HIF_DMA_DIR_TX = 0, + HIF_DMA_DIR_RX +} MTK_WCN_HIF_DMA_DIR; + +typedef struct _MTK_WCN_HIF_DMA_CONF { + UINT_32 Count; + MTK_WCN_HIF_DMA_DIR Dir; + UINT_32 Burst; + UINT_32 Wsize; + UINT_32 Ratio; + UINT_32 Connect; + UINT_32 Fix_en; + ULONG Src; + ULONG Dst; +} MTK_WCN_HIF_DMA_CONF; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define MCU_REG_READL(_hif, _addr) \ + readl((volatile UINT_32 *)((_hif)->McuRegBaseAddr + _addr)) + +/* PIO mode HIF register read/write */ +#define HIF_REG_READL(_hif, _addr) \ + readl((volatile UINT_32 *)((_hif)->HifRegBaseAddr + _addr)) + +#define HIF_REG_WRITEL(_hif, _addr, _val) \ + writel(_val, ((volatile UINT_32 *)((_hif)->HifRegBaseAddr + _addr))) + +#define HIF_REG_WRITEB(_hif, _addr, _val) \ + writeb(_val, ((volatile UINT_32 *)((_hif)->HifRegBaseAddr + _addr))) + +/* PIO mode DMA register read/write */ +#define HIF_DMAR_READL(_hif, _addr) \ + readl((volatile UINT_32 *)((_hif)->DmaRegBaseAddr + _addr)) + +#define HIF_DMAR_WRITEL(_hif, _addr, _val) \ + writel(_val, ((volatile UINT_32 *)((_hif)->DmaRegBaseAddr + _addr))) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#ifndef MODULE_AHB_DMA +VOID HifDumpEnhanceModeData(P_ADAPTER_T prAdapter); + +VOID HifRegDump(P_ADAPTER_T prAdapter); + +BOOLEAN HifIsFwOwn(P_ADAPTER_T prAdapter); + +WLAN_STATUS glRegisterBus(probe_card pfProbe, remove_card pfRemove); + +VOID glUnregisterBus(remove_card pfRemove); + +VOID glResetHif(GLUE_INFO_T *GlueInfo); + +VOID glSetHifInfo(P_GLUE_INFO_T prGlueInfo, ULONG ulCookie); + +VOID glClearHifInfo(P_GLUE_INFO_T prGlueInfo); + +VOID glGetChipInfo(GLUE_INFO_T *GlueInfo, UINT_8 *pucChipBuf); + +#if CFG_SPM_WORKAROUND_FOR_HOTSPOT +BOOLEAN glIsChipNeedWakelock(GLUE_INFO_T *GlueInfo); +#endif + +BOOLEAN glBusInit(PVOID pvData); + +VOID glBusRelease(PVOID pData); + +INT_32 glBusSetIrq(PVOID pvData, PVOID pfnIsr, PVOID pvCookie); + +VOID glBusFreeIrq(PVOID pvData, PVOID pvCookie); + +VOID glSetPowerState(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 ePowerMode); + +VOID glDumpConnSysCpuInfo(P_GLUE_INFO_T prGlueInfo); + +#endif /* MODULE_AHB_DMA */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Config GDMA TX/RX. +* +* \param[in] DmaRegBaseAddr Pointer to the IO register base. +* \param[in] Conf Pointer to the DMA operator. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +VOID HifGdmaInit(GL_HIF_INFO_T *HifInfo); + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Config PDMA TX/RX. +* +* \param[in] DmaRegBaseAddr Pointer to the IO register base. +* \param[in] Conf Pointer to the DMA operator. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +VOID HifPdmaInit(GL_HIF_INFO_T *HifInfo); + +int HifAhbSetMpuProtect(bool enable); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _HIF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/hif/ahb/include/hif_gdma.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/hif/ahb/include/hif_gdma.h new file mode 100644 index 0000000000000..3fa41e9dcd1ac --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/hif/ahb/include/hif_gdma.h @@ -0,0 +1,148 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _HIF_GDMA_H +#define _HIF_GDMA_H + +#include "mtk_porting.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef enum _MTK_WCN_HIF_GDMA_BURST_LEN { + HIF_GDMA_BURST_1_8 = 0, + HIF_GDMA_BURST_2_8, + HIF_GDMA_BURST_3_8, + HIF_GDMA_BURST_4_8, + HIF_GDMA_BURST_5_8, + HIF_GDMA_BURST_6_8, + HIF_GDMA_BURST_7_8, + HIF_GDMA_BURST_8_8 /* same as HIF_GDMA_BURST_7_8 */ +} MTK_WCN_HIF_GDMA_BURST_LEN; + +typedef enum _MTK_WCN_HIF_GDMA_WRITE_LEN { + HIF_GDMA_WRITE_0 = 0, /* transaction size is 1 byte */ + HIF_GDMA_WRITE_1, /* transaction size is 2 byte */ + HIF_GDMA_WRITE_2, /* transaction size is 4 byte */ + HIF_GDMA_WRITE_3 /* transaction size is 1 byte */ +} MTK_WCN_HIF_GDMA_WRITE_LEN; + +typedef enum _MTK_WCN_HIF_GDMA_RATIO { + HIF_GDMA_RATIO_0 = 0, /* 1/2 */ + HIF_GDMA_RATIO_1 /* 1/1 */ +} MTK_WCN_HIF_GDMA_RATIO; + +typedef enum _MTK_WCN_HIF_GDMA_CONNECT { + HIF_GDMA_CONNECT_NO = 0, /* no connect */ + HIF_GDMA_CONNECT_SET1, /* connect set1 (req/ack) */ + HIF_GDMA_CONNECT_SET2, /* connect set2 (req/ack) */ + HIF_GDMA_CONNECT_SET3 /* connect set3 (req/ack) */ +} MTK_WCN_HIF_GDMA_CONNECT; + +/* reference to MT6572_AP_P_DMA_Spec.doc */ +#define AP_DMA_HIF_BASE 0x11000100 + +#define AP_P_DMA_G_DMA_2_INT_FLAG (0x0000) +#define AP_P_DMA_G_DMA_2_CON (0x0018) +#define AP_P_DMA_G_DMA_2_CONNECT (0x0034) +#define AP_P_DMA_G_DMA_2_LEN1 (0x0024) +#define AP_P_DMA_G_DMA_2_SRC_ADDR (0x001C) +#define AP_P_DMA_G_DMA_2_DST_ADDR (0x0020) +#define AP_P_DMA_G_DMA_2_INT_EN (0x0004) +#define AP_P_DMA_G_DMA_2_EN (0x0008) +#define AP_P_DMA_G_DMA_2_RST (0x000C) +#define AP_P_DMA_G_DMA_2_STOP (0x0010) + +#define AP_DMA_HIF_0_LENGTH 0x0038 + +/* AP_DMA_HIF_0_INT_FLAG */ +#define ADH_CR_FLAG_0 BIT(0) + +/* AP_DMA_HIF_0_INT_EN */ +#define ADH_CR_INTEN_FLAG_0 BIT(0) + +/* AP_DMA_HIF_0_EN */ +#define ADH_CR_EN BIT(0) +#define ADH_CR_CONN_BUR_EN BIT(1) + +/* AP_DMA_HIF_0_STOP */ +#define ADH_CR_PAUSE BIT(1) +#define ADH_CR_STOP BIT(0) + +/* AP_P_DMA_G_DMA_2_CON */ +#define ADH_CR_FLAG_FINISH BIT(30) +#define ADH_CR_RSIZE BITS(28, 29) +#define ADH_CR_RSIZE_OFFSET 28 +#define ADH_CR_WSIZE BITS(24, 25) +#define ADH_CR_WSIZE_OFFSET 24 +#define ADH_CR_BURST_LEN BITS(16, 18) +#define ADH_CR_BURST_LEN_OFFSET 16 +#define ADH_CR_WADDR_FIX_EN BIT(3) +#define ADH_CR_WADDR_FIX_EN_OFFSET 3 +#define ADH_CR_RADDR_FIX_EN BIT(4) +#define ADH_CR_RADDR_FIX_EN_OFFSET 4 + +/* AP_P_DMA_G_DMA_2_CONNECT */ +#define ADH_CR_RATIO BIT(3) +#define ADH_CR_RATIO_OFFSET 3 +#define ADH_CR_DIR BIT(2) +#define ADH_CR_DIR_OFFSET 2 +#define ADH_CR_CONNECT BITS(0, 1) + +/* AP_DMA_HIF_0_LEN */ +#define ADH_CR_LEN BITS(0, 19) + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _HIF_GDMA_H */ + +/* End of hif_gdma.h */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/hif/ahb/include/hif_pdma.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/hif/ahb/include/hif_pdma.h new file mode 100644 index 0000000000000..137b7a42cff95 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/hif/ahb/include/hif_pdma.h @@ -0,0 +1,141 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _HIF_PDMA_H +#define _HIF_PDMA_H + +#include "mtk_porting.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef enum _MTK_WCN_HIF_PDMA_BURST_LEN { + HIF_PDMA_BURST_1_4 = 0, + HIF_PDMA_BURST_2_4, + HIF_PDMA_BURST_3_4, + HIF_PDMA_BURST_4_4 +} MTK_WCN_HIF_PDMA_BURST_LEN; + +/* reference to MT6572_AP_P_DMA_Spec.doc */ +#ifdef CONFIG_OF +/*for MT6752*/ +#define AP_DMA_HIF_BASE 0x11000080 +#else +/*for MT6572/82/92*/ +#define AP_DMA_HIF_BASE 0x11000180 +#endif + +#define AP_DMA_HIF_0_INT_FLAG (0x0000) +#define AP_DMA_HIF_0_INT_EN (0x0004) +#define AP_DMA_HIF_0_EN (0x0008) +#define AP_DMA_HIF_0_RST (0x000C) +#define AP_DMA_HIF_0_STOP (0x0010) +#define AP_DMA_HIF_0_FLUSH (0x0014) +#define AP_DMA_HIF_0_CON (0x0018) +#define AP_DMA_HIF_0_SRC_ADDR (0x001C) +#define AP_DMA_HIF_0_DST_ADDR (0x0020) +#define AP_DMA_HIF_0_LEN (0x0024) +#define AP_DMA_HIF_0_INT_BUF_SIZE (0x0038) +#define AP_DMA_HIF_0_DEBUG_STATUS (0x0050) +#define AP_DMA_HIF_0_SRC_ADDR2 (0x0054) +#define AP_DMA_HIF_0_DST_ADDR2 (0x0058) + +#define AP_DMA_HIF_0_LENGTH 0x0080 + +/* AP_DMA_HIF_0_INT_FLAG */ +#define ADH_CR_FLAG_0 BIT(0) + +/* AP_DMA_HIF_0_INT_EN */ +#define ADH_CR_INTEN_FLAG_0 BIT(0) + +/* AP_DMA_HIF_0_EN */ +#define ADH_CR_EN BIT(0) + +/* AP_DMA_HIF_0_RST */ +#define ADH_CR_HARD_RST BIT(1) +#define ADH_CR_WARM_RST BIT(0) + +/* AP_DMA_HIF_0_STOP */ +#define ADH_CR_PAUSE BIT(1) +#define ADH_CR_STOP BIT(0) + +/* AP_DMA_HIF_0_FLUSH */ +#define ADH_CR_FLUSH BIT(0) + +/* AP_DMA_HIF_0_CON */ +#define ADH_CR_BURST_LEN BITS(16, 17) +#define ADH_CR_BURST_LEN_OFFSET 16 +#define ADH_CR_SLOW_CNT BITS(5, 14) +#define ADH_CR_SLOW_EN BIT(2) +#define ADH_CR_FIX_EN BIT(1) +#define ADH_CR_FIX_EN_OFFSET 1 +#define ADH_CR_DIR BIT(0) +#define ADH_CR_INTA_INCR BIT(31) + +/* AP_DMA_HIF_0_LEN */ +#define ADH_CR_LEN BITS(0, 19) + +/* AP_DMA_HIF_0_SRC_ADDR2 */ +#define ADH_CR_SRC_ADDR2 BIT(0) +/* AP_DMA_HIF_0_DST_ADDR2 */ +#define ADH_CR_DST_ADDR2 BIT(0) + +/* AP_DMA_HIF_0_SRC_ADDR2, BIT 0~3 to support 6G DRAM */ +#define ADH_CR_SRC_ADDR2_6G BITS(0, 3) +/* AP_DMA_HIF_0_DST_ADDR2, BIT 0~3 to support 6G DRAM */ +#define ADH_CR_DST_ADDR2_6G BITS(0, 3) + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _HIF_PDMA_H */ + +/* End of hif_gdma.h */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/hif/ahb/include/mtk_porting.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/hif/ahb/include/mtk_porting.h new file mode 100644 index 0000000000000..1944772cf3415 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/hif/ahb/include/mtk_porting.h @@ -0,0 +1,103 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/* porting layer */ +/* Android */ + +#ifndef _MTK_PORTING_H_ +#define _MTK_PORTING_H_ + +#include /* include stddef.h for NULL */ + +#define CONF_MTK_AHB_DMA 1 + +/* Type definition for signed integers */ +/* + * typedef signed char INT8, *PINT8; + * typedef signed short INT16, *PINT16; + * typedef signed int INT_32, *PINT32; + */ + +/* Type definition for unsigned integers */ +/* + * typedef unsigned char UINT8, *PUINT8; + * typedef unsigned short UINT16, *PUINT16; + * typedef unsigned int UINT32, *PUINT32; + */ + +#ifndef VOID +/*typedef void VOID, *PVOID;*/ +#endif + +#ifndef IN +#define IN +#endif + +#ifndef OUT +#define OUT +#endif + +#ifndef INTOUT +#define INOUT +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef BIT +#define BIT(n) ((UINT_32) 1U << (n)) +#endif /* BIT */ + +#ifndef BITS +/* bits range: for example BITS(16,23) = 0xFF0000 + * ==> (BIT(m)-1) = 0x0000FFFF ~(BIT(m)-1) => 0xFFFF0000 + * ==> (BIT(n+1)-1) = 0x00FFFFFF + */ +#define BITS(m, n) (~(BIT(m)-1) & ((BIT(n) - 1) | BIT(n))) +#endif /* BIT */ + +#ifndef MTK_WCN_BOOL_TRUE +#define MTK_WCN_BOOL_FALSE ((MTK_WCN_BOOL) 0) +#define MTK_WCN_BOOL_TRUE ((MTK_WCN_BOOL) 1) +#endif + +typedef int MTK_WCN_MUTEX; + +typedef int MTK_WCN_TIMER; + +/* system APIs */ +/* mutex */ +typedef MTK_WCN_MUTEX(*MUTEX_CREATE) (const char *const name); +typedef INT_32(*MUTEX_DESTROY) (MTK_WCN_MUTEX mtx); +typedef INT_32(*MUTEX_LOCK) (MTK_WCN_MUTEX mtx); +typedef INT_32(*MUTEX_UNLOCK) (MTK_WCN_MUTEX mtx, unsigned long flags); +/* debug */ +typedef INT_32(*DBG_PRINT) (const char *str, ...); +typedef INT_32(*DBG_ASSERT) (INT_32 expr, const char *file, INT_32 line); +/* timer */ +typedef void (*MTK_WCN_TIMER_CB) (void); +typedef MTK_WCN_TIMER(*TIMER_CREATE) (const char *const name); +typedef INT_32(*TIMER_DESTROY) (MTK_WCN_TIMER tmr); +typedef INT_32(*TIMER_START) (MTK_WCN_TIMER tmr, UINT_32 timeout, MTK_WCN_TIMER_CB tmr_cb, void *param); +typedef INT_32(*TIMER_STOP) (MTK_WCN_TIMER tmr); +/* kernel lib */ +typedef void *(*SYS_MEMCPY) (void *dest, const void *src, UINT_32 n); +typedef void *(*SYS_MEMSET) (void *s, INT_32 c, UINT_32 n); +typedef INT_32(*SYS_SPRINTF) (char *str, const char *format, ...); + +#endif /* _MTK_PORTING_H_ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_cfg80211.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_cfg80211.h new file mode 100644 index 0000000000000..06dff8f68f347 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_cfg80211.h @@ -0,0 +1,333 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _GL_CFG80211_H +#define _GL_CFG80211_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#include +#include + +#include "gl_os.h" +extern void wlanHandleSystemResume(void); +extern void wlanHandleSystemSuspend(void); +extern void p2pHandleSystemResume(void); +extern void p2pHandleSystemSuspend(void); + +#if CFG_SUPPORT_WAPI +extern UINT_8 keyStructBuf[1024]; /* add/remove key shared buffer */ +#else +extern UINT_8 keyStructBuf[100]; /* add/remove key shared buffer */ +#endif + +extern struct delayed_work sched_workq; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#if CONFIG_NL80211_TESTMODE +#define NL80211_DRIVER_TESTMODE_VERSION 2 +#endif + +#define GL_CFG80211_SCAN_SSID_MAX_NUM 2 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +#if CONFIG_NL80211_TESTMODE + +typedef struct _NL80211_DRIVER_GET_STA_STATISTICS_PARAMS { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + UINT_32 u4Version; + UINT_32 u4Flag; + UINT_8 aucMacAddr[MAC_ADDR_LEN]; +} NL80211_DRIVER_GET_STA_STATISTICS_PARAMS, *P_NL80211_DRIVER_GET_STA_STATISTICS_PARAMS; + +typedef struct _NL80211_DRIVER_POORLINK_PARAMS { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + INT_8 cRssi; /* cRssi=0 means it is a invalid value. */ + UINT_8 ucLinkSpeed; /* ucLinkSpeed=0 means it is a invalid value */ + UINT_16 u2Reserved; +} NL80211_DRIVER_POORLINK_PARAMS, *P_NL80211_DRIVER_POORLINK_PARAMS; + +typedef enum _ENUM_TESTMODE_STA_STATISTICS_ATTR { + NL80211_TESTMODE_STA_STATISTICS_INVALID = 0, + NL80211_TESTMODE_STA_STATISTICS_VERSION, + NL80211_TESTMODE_STA_STATISTICS_MAC, + NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE, + NL80211_TESTMODE_STA_STATISTICS_FLAG, + + NL80211_TESTMODE_STA_STATISTICS_PER, + NL80211_TESTMODE_STA_STATISTICS_RSSI, + NL80211_TESTMODE_STA_STATISTICS_PHY_MODE, + NL80211_TESTMODE_STA_STATISTICS_TX_RATE, + + NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT, + NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT, + + NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME, + NL80211_TESTMODE_STA_STATISTICS_MAX_PROCESS_TIME, + NL80211_TESTMODE_STA_STATISTICS_AVG_HIF_PROCESS_TIME, + NL80211_TESTMODE_STA_STATISTICS_MAX_HIF_PROCESS_TIME, + + NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT, + NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT, + NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME, + + NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY, + + /* + * how many packages TX during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_ENQUEUE, + + /* + * how many packages this TX during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_STA_ENQUEUE, + + /* + * how many packages dequeue during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_DEQUEUE, + + /* + * how many packages this sta dequeue during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_STA_DEQUEUE, + + /* + * how many TC[0-3] resource back from firmware during + * statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_RB_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_NO_TC_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_USED_BFCT_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_WANTED_BFCT_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_PASS_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_TASK_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_AB_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_SW_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_TX_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_RX_CNT, + + NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_NUM +} ENUM_TESTMODE_STA_STATISTICS_ATTR; + +typedef struct _NL80211_DRIVER_SET_NFC_PARAMS { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + UINT_32 NFC_Enable; +} NL80211_DRIVER_SET_NFC_PARAMS, *P_NL80211_DRIVER_SET_NFC_PARAMS; + +typedef struct _NL80211_DRIVER_GET_SCANDONE_PARAMS { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + UINT_32 u4ScanDone; +} NL80211_DRIVER_GET_SCANDONE_PARAMS, *P_NL80211_DRIVER_GET_SCANDONE_PARAMS; + +typedef enum _ENUM_TESTMODE_LINK_DETECTION_ATTR { + NL80211_TESTMODE_LINK_INVALID = 0, + NL80211_TESTMODE_LINK_TX_FAIL_CNT, + NL80211_TESTMODE_LINK_TX_RETRY_CNT, + NL80211_TESTMODE_LINK_TX_MULTI_RETRY_CNT, + NL80211_TESTMODE_LINK_ACK_FAIL_CNT, + NL80211_TESTMODE_LINK_FCS_ERR_CNT, + + NL80211_TESTMODE_LINK_DETECT_NUM, +} ENUM_TESTMODE_LINK_DETECTION_ATTR; + +#endif +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/* cfg80211 hooks */ +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +int +mtk_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, enum nl80211_iftype type, struct vif_params *params); +#else +int +mtk_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, enum nl80211_iftype type, u32 *flags, struct vif_params *params); +#endif +int +mtk_cfg80211_add_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, bool pairwise, const u8 *mac_addr, struct key_params *params); + +int +mtk_cfg80211_get_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, + bool pairwise, + const u8 *mac_addr, void *cookie, void (*callback) (void *cookie, struct key_params *) +); + +int +mtk_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_index, bool pairwise, const u8 *mac_addr); + +int +mtk_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_index, bool unicast, bool multicast); + +int mtk_cfg80211_set_default_mgmt_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index); + +int mtk_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, const u8 *mac, struct station_info *sinfo); + +int mtk_cfg80211_add_station(struct wiphy *wiphy, struct net_device *ndev, + const u8 *mac, struct station_parameters *params); + +int mtk_cfg80211_change_station(struct wiphy *wiphy, struct net_device *ndev, + const u8 *mac, struct station_parameters *params); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +int mtk_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, struct station_del_parameters *params); +#else +int mtk_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, const u8 *mac); +#endif + +int mtk_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request); + +void mtk_cfg80211_abort_scan(struct wiphy *wiphy, struct wireless_dev *wdev); + +int mtk_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_connect_params *sme); + +int mtk_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, u16 reason_code); + +int mtk_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_ibss_params *params); + +int mtk_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev); + +int mtk_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, bool enabled, int timeout); + +int mtk_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_pmksa *pmksa); + +int mtk_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_pmksa *pmksa); + +int mtk_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev); + +int mtk_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, + unsigned int duration, u64 *cookie); + +int mtk_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie); + +int +mtk_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie); + +void mtk_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, + IN struct wireless_dev *wdev, + IN u16 frame_type, IN bool reg); + +int mtk_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie); + +int mtk_cfg80211_assoc(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_assoc_request *req); + +int +mtk_cfg80211_sched_scan_start(IN struct wiphy *wiphy, + IN struct net_device *ndev, IN struct cfg80211_sched_scan_request *request); + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_sched_scan_stop(IN struct wiphy *wiphy, + IN struct net_device *ndev, + IN u64 reqid); +#else +int mtk_cfg80211_sched_scan_stop(IN struct wiphy *wiphy, IN struct net_device *ndev); +#endif + +#if CONFIG_NL80211_TESTMODE +int +mtk_cfg80211_testmode_get_sta_statistics(IN struct wiphy *wiphy, + IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo); + +int mtk_cfg80211_testmode_get_scan_done(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo); + +int mtk_cfg80211_testmode_cmd(IN struct wiphy *wiphy, IN struct wireless_dev *wdev, IN void *data, IN int len); + +int mtk_cfg80211_testmode_sw_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); + +#if CFG_SUPPORT_WAPI +int mtk_cfg80211_testmode_set_key_ext(IN struct wiphy *wiphy, IN void *data, IN int len); +#endif + +#if CFG_SUPPORT_HOTSPOT_2_0 +int mtk_cfg80211_testmode_hs20_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); +#endif + +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_WIFI_DIRECT_CFG_80211 +int mtk_p2p_cfg80211_testmode_sw_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); +#endif +#else +#error "Please ENABLE kernel config (CONFIG_NL80211_TESTMODE)" +#endif + +int mtk_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow); + +int mtk_cfg80211_resume(struct wiphy *wiphy); + +int mtk_cfg80211_update_ft_ies(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_update_ft_ies_params *ftie); + +INT_32 mtk_cfg80211_process_str_cmd(P_GLUE_INFO_T prGlueInfo, PUINT_8 cmd, INT_32 len); + +#if CFG_SUPPORT_WPA3 +int mtk_cfg80211_external_auth(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_external_auth_params *params); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _GL_CFG80211_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_kal.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_kal.h new file mode 100644 index 0000000000000..e5f5047d1772c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_kal.h @@ -0,0 +1,952 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _GL_KAL_H +#define _GL_KAL_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "config.h" +#include "gl_typedef.h" +#include "gl_os.h" +#include "link.h" +#include "nic/mac.h" +#include "nic/wlan_def.h" +#include "wlan_lib.h" +#include "wlan_oid.h" +#include "gl_wext_priv.h" +#include + +#if CFG_ENABLE_BT_OVER_WIFI +#include "nic/bow.h" +#endif + +#if KERNEL_VERSION(4, 11, 0) <= CFG80211_VERSION_CODE +#include "linux/sched/types.h" +#endif + +#if DBG +extern int allocatedMemSize; +#endif + +#if CFG_SUPPORT_MET_PROFILING +#include "linux/kallsyms.h" +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +#include +#else +#include +#endif +#endif + +extern BOOLEAN fgIsUnderSuspend; +extern UINT_32 TaskIsrCnt; +extern BOOLEAN fgIsResetting; +extern int wlanHardStartXmit(struct sk_buff *prSkb, struct net_device *prDev); +extern UINT_32 u4MemAllocCnt, u4MemFreeCnt; + + +extern struct delayed_work sched_workq; + +#if defined(MT6620) && CFG_MULTI_ECOVER_SUPPORT +extern ENUM_WMTHWVER_TYPE_T mtk_wcn_wmt_hwver_get(VOID); +#endif +extern PUINT8 wmt_lib_get_fwinfor_from_emi(UINT8 section, UINT32 offset, PUINT8 buff, UINT32 len); +extern PUINT8 mtk_wcn_consys_emi_virt_addr_get(UINT32 ctrl_state_offset); + +extern BOOLEAN fgIsUnderSuspend; + +/* for built-in WMT */ +extern void connectivity_export_show_stack(struct task_struct *tsk, unsigned long *sp); +extern void connectivity_export_tracing_record_cmdline(struct task_struct *tsk); +/******************************************************************************* +* 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, + 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, + +#if CFG_SUPPORT_MULTITHREAD + SPIN_LOCK_RX_DATA_QUE, +#endif + SPIN_LOCK_NUM +} ENUM_SPIN_LOCK_CATEGORY_E; + +/* event for assoc information update */ +typedef struct _EVENT_ASSOC_INFO { + UINT_8 ucAssocReq; /* 1 for assoc req, 0 for assoc rsp */ + UINT_8 ucReassoc; /* 0 for assoc, 1 for reassoc */ + UINT_16 u2Length; + PUINT_8 pucIe; +} EVENT_ASSOC_INFO, *P_EVENT_ASSOC_INFO; + +typedef enum _ENUM_KAL_NETWORK_TYPE_INDEX_T { + KAL_NETWORK_TYPE_AIS_INDEX = 0, +#if CFG_ENABLE_WIFI_DIRECT + KAL_NETWORK_TYPE_P2P_INDEX, +#endif +#if CFG_ENABLE_BT_OVER_WIFI + KAL_NETWORK_TYPE_BOW_INDEX, +#endif + KAL_NETWORK_TYPE_INDEX_NUM +} ENUM_KAL_NETWORK_TYPE_INDEX_T; + +typedef enum _ENUM_PKT_TYPE_T { + ENUM_PKT_802_11, /* 802.11 or non-802.11 */ + ENUM_PKT_802_3, /* 802.3 or ethernetII */ + ENUM_PKT_1X, /* 1x frame or not */ + ENUM_PKT_PROTECTED_1X, /* prtected 1x frame */ + ENUM_PKT_WPI_1X, /* WAPI */ + ENUM_PKT_VLAN_EXIST, /* VLAN tag exist */ + ENUM_PKT_DHCP, /* DHCP frame */ + ENUM_PKT_ARP, /* ARP */ + ENUM_PKT_ICMP, /* ICMP */ + ENUM_PKT_TDLS, /* TDLS */ + ENUM_PKT_DNS, /* DNS */ + + ENUM_PKT_FLAG_NUM +} ENUM_PKT_TYPE_T; + + +typedef enum _ENUM_AMPDU_TYPE_E { + MTK_AMPDU_TX_DESC, + MTK_AMPDU_RX_DESC, + MTK_AMPDU_NUM +} ENUM_AMPDU_TYPE; + +typedef enum _ENUM_KAL_MEM_ALLOCATION_TYPE_E { + PHY_MEM_TYPE, /* physically continuous */ + VIR_MEM_TYPE, /* virtually continuous */ + MEM_TYPE_NUM +} ENUM_KAL_MEM_ALLOCATION_TYPE; + +enum ENUM_BUILD_VARIANT_E { + MTK_BUILD_VAR_ENG = 1, /*eng load*/ + MTK_BUILD_VAR_USERDEUB = 2, /*userdebug load*/ + MTK_BUILD_VAR_USER = 3 /*user load*/ +}; + +#if CONFIG_ANDROID /* Defined in Android kernel source */ +#if (KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE) +typedef struct wakeup_source KAL_WAKE_LOCK_T, *P_KAL_WAKE_LOCK_T; +#else +typedef struct wake_lock KAL_WAKE_LOCK_T, *P_KAL_WAKE_LOCK_T; +#endif +#else +typedef UINT_32 KAL_WAKE_LOCK_T, *P_KAL_WAKE_LOCK_T; +#endif + +#if CFG_SUPPORT_AGPS_ASSIST +typedef enum _ENUM_MTK_AGPS_ATTR { + MTK_ATTR_AGPS_INVALID, + MTK_ATTR_AGPS_CMD, + MTK_ATTR_AGPS_DATA, + MTK_ATTR_AGPS_IFINDEX, + MTK_ATTR_AGPS_IFNAME, + MTK_ATTR_AGPS_MAX +} ENUM_MTK_CCX_ATTR; + +typedef enum _ENUM_AGPS_EVENT { + AGPS_EVENT_WLAN_ON, + AGPS_EVENT_WLAN_OFF, + AGPS_EVENT_WLAN_AP_LIST, + WIFI_EVENT_CHIP_RESET, +} ENUM_CCX_EVENT; +BOOLEAN kalIndicateAgpsNotify(P_ADAPTER_T prAdapter, UINT_8 cmd, PUINT_8 data, UINT_16 dataLen); +#endif + +struct KAL_HALT_CTRL_T { + struct semaphore lock; + struct task_struct *owner; + BOOLEAN fgHalt; + BOOLEAN fgHeldByKalIoctl; + OS_SYSTIME u4HoldStart; +}; +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/* Macros of bit operation */ +/*----------------------------------------------------------------------------*/ +#define KAL_SET_BIT(bitOffset, value) set_bit(bitOffset, &value) +#define KAL_CLR_BIT(bitOffset, value) clear_bit(bitOffset, &value) +#define KAL_TEST_AND_CLEAR_BIT(bitOffset, value) test_and_clear_bit(bitOffset, &value) +#define KAL_TEST_BIT(bitOffset, value) test_bit(bitOffset, &value) + +/*----------------------------------------------------------------------------*/ +/* Macros of SPIN LOCK operations for using in Driver Layer */ +/*----------------------------------------------------------------------------*/ +#define KAL_SPIN_LOCK_DECLARATION() unsigned long __u4Flags + +#define KAL_ACQUIRE_SPIN_LOCK(_prAdapter, _rLockCategory) \ + kalAcquireSpinLock(((P_ADAPTER_T)_prAdapter)->prGlueInfo, _rLockCategory, &__u4Flags) + +#define KAL_RELEASE_SPIN_LOCK(_prAdapter, _rLockCategory) \ + kalReleaseSpinLock(((P_ADAPTER_T)_prAdapter)->prGlueInfo, _rLockCategory, __u4Flags) + +/*----------------------------------------------------------------------------*/ +/* Macros for accessing Reserved Fields of native packet */ +/*----------------------------------------------------------------------------*/ +#define KAL_GET_PKT_QUEUE_ENTRY(_p) GLUE_GET_PKT_QUEUE_ENTRY(_p) +#define KAL_GET_PKT_DESCRIPTOR(_prQueueEntry) GLUE_GET_PKT_DESCRIPTOR(_prQueueEntry) +#define KAL_GET_PKT_TID(_p) GLUE_GET_PKT_TID(_p) +#define KAL_GET_PKT_IS1X(_p) GLUE_GET_PKT_IS1X(_p) +#define KAL_GET_PKT_HEADER_LEN(_p) GLUE_GET_PKT_HEADER_LEN(_p) +#define KAL_GET_PKT_PAYLOAD_LEN(_p) GLUE_GET_PKT_PAYLOAD_LEN(_p) +#define KAL_GET_PKT_ARRIVAL_TIME(_p) GLUE_GET_PKT_ARRIVAL_TIME(_p) + +/*----------------------------------------------------------------------------*/ +/* Macros of wake_lock operations for using in Driver Layer */ +/*----------------------------------------------------------------------------*/ +#if CONFIG_ANDROID /* Defined in Android kernel source */ +#if (KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE) +#if (KERNEL_VERSION(4, 14, 149) <= LINUX_VERSION_CODE) +#define KAL_WAKE_LOCK_INIT(_prAdapter, _prWakeLock, _pcName) \ + _prWakeLock = wakeup_source_register(NULL, _pcName); +#define KAL_WAKE_LOCK_DESTROY(_prAdapter, _prWakeLock) \ +{ \ + wakeup_source_unregister(_prWakeLock); \ + _prWakeLock = NULL; \ +} +#else +#define KAL_WAKE_LOCK_INIT(_prAdapter, _prWakeLock, _pcName) \ +{ \ + _prWakeLock = kalMemAlloc(sizeof(KAL_WAKE_LOCK_T), \ + VIR_MEM_TYPE); \ + if (!_prWakeLock) { \ + DBGLOG(HAL, ERROR, \ + "KAL_WAKE_LOCK_INIT init fail!\n"); \ + } \ + else { \ + wakeup_source_init(_prWakeLock, _pcName); \ + } \ +} +#define KAL_WAKE_LOCK_DESTROY(_prAdapter, _prWakeLock) \ +{ \ + if (!_prWakeLock) { \ + wakeup_source_trash(_prWakeLock); \ + _prWakeLock = NULL; \ + } \ +} +#endif +#define KAL_WAKE_LOCK(_prAdapter, _prWakeLock) \ + __pm_stay_awake(_prWakeLock) +#define KAL_WAKE_LOCK_TIMEOUT(_prAdapter, _prWakeLock, _u4Timeout) \ + __pm_wakeup_event(_prWakeLock, JIFFIES_TO_MSEC(_u4Timeout)) +#define KAL_WAKE_UNLOCK(_prAdapter, _prWakeLock) \ + __pm_relax(_prWakeLock) +#define KAL_WAKE_LOCK_ACTIVE(_prAdapter, _prWakeLock) \ + ((_prWakeLock)->active) +#else +#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) + +#define KAL_WAKE_LOCK_ACTIVE(_prAdapter, _prWakeLock) \ + wake_lock_active(_prWakeLock) + typedef struct wake_lock KAL_WAKE_LOCK_T, *P_KAL_WAKE_LOCK_T; +#define KAL_WAKELOCK_DECLARE(_lock) \ + struct wake_lock _lock +#endif + +#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) +typedef UINT_32 KAL_WAKE_LOCK_T, *P_KAL_WAKE_LOCK_T; +#define KAL_WAKELOCK_DECLARE(_lock) +#define KAL_WAKE_LOCK_ACTIVE(_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 { \ + if (u4Size > PAGE_SIZE) \ + pvAddr = vmalloc(u4Size); \ + else \ + pvAddr = kmalloc(u4Size, GFP_KERNEL); \ + } \ + if (pvAddr) { \ + allocatedMemSize += u4Size; \ + DBGLOG(INIT, INFO, "%p(%u) allocated (%s:%s)\n", \ + pvAddr, (UINT_32)u4Size, __FILE__, __func__); \ + } \ + pvAddr; \ +}) +#else +#define kalMemAlloc(u4Size, eMemType) ({ \ + void *pvAddr; \ + if (eMemType == PHY_MEM_TYPE) { \ + pvAddr = kmalloc(u4Size, GFP_KERNEL); \ + } \ + else { \ + if (u4Size > PAGE_SIZE) \ + pvAddr = vmalloc(u4Size); \ + else \ + pvAddr = kmalloc(u4Size, GFP_KERNEL); \ + } \ + pvAddr; \ +}) +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Free allocated cache memory +* +* \param[in] pvAddr Required memory size. +* \param[in] eMemType Memory allocation type +* \param[in] u4Size Allocated memory size. +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +#if DBG +#define kalMemFree(pvAddr, eMemType, u4Size) \ +{ \ + if (pvAddr) { \ + allocatedMemSize -= u4Size; \ + DBGLOG(INIT, INFO, "%p(%u) freed (%s:%s)\n", \ + pvAddr, (UINT_32)u4Size, __FILE__, __func__); \ + } \ + kvfree(pvAddr); \ +} +#else +#define kalMemFree(pvAddr, eMemType, u4Size) \ +{ \ + kvfree(pvAddr); \ +} +#endif + +#define kalUdelay(u4USec) udelay(u4USec) + +#define kalMdelay(u4MSec) mdelay(u4MSec) +#define kalMsleep(u4MSec) msleep(u4MSec) +#define kalUsleepRange(u4StarUSec, u4EndUSec) usleep_range(u4StarUSec, u4EndUSec) + +/* Copy memory from user space to kernel space */ +#define kalMemCopyFromUser(_pvTo, _pvFrom, _u4N) copy_from_user(_pvTo, _pvFrom, _u4N) + +/* Copy memory from kernel space to user space */ +#define kalMemCopyToUser(_pvTo, _pvFrom, _u4N) copy_to_user(_pvTo, _pvFrom, _u4N) + +/* Copy memory block with specific size */ +#define kalMemCopy(pvDst, pvSrc, u4Size) memcpy(pvDst, pvSrc, u4Size) + +/* Set memory block with specific pattern */ +#define kalMemSet(pvAddr, ucPattern, u4Size) memset(pvAddr, ucPattern, u4Size) + +/* Compare two memory block with specific length. + * Return zero if they are the same. + */ +#define kalMemCmp(pvAddr1, pvAddr2, u4Size) memcmp(pvAddr1, pvAddr2, u4Size) + +/* Zero specific memory block */ +#define kalMemZero(pvAddr, u4Size) memset(pvAddr, 0, u4Size) + +/* string operation */ +#define kalStrCpy(dest, src) strcpy(dest, src) +#define kalStrnCpy(dest, src, n) strncpy(dest, src, n) +#define kalStrCmp(ct, cs) strcmp(ct, cs) +#define kalStrnCmp(ct, cs, n) strncmp(ct, cs, n) +#define kalStrChr(s, c) strchr(s, c) +#define kalStrrChr(s, c) strrchr(s, c) +#define kalStrnChr(s, n, c) strnchr(s, n, c) +#define kalStrLen(s) strlen(s) +#define kalStrnLen(s, b) strnlen(s, b) +#define kalStrniCmp(s1, s2, n) strncasecmp(s1, s2, n) +/* + * #define kalStrtoul(cp, endp, base) simple_strtoul(cp, endp, base) + * #define kalStrtol(cp, endp, base) simple_strtol(cp, endp, base) + */ +#define kalkStrtou32(cp, base, resp) kstrtou32(cp, base, resp) +#define kalkStrtos32(cp, base, resp) kstrtos32(cp, base, resp) +#define kalSnprintf(buf, size, fmt, ...) snprintf(buf, size, fmt, __VA_ARGS__) +#define kalSprintf(buf, fmt, ...) sprintf(buf, fmt, __VA_ARGS__) +/* remove for AOSP */ +/* #define kalSScanf(buf, fmt, ...) sscanf(buf, fmt, __VA_ARGS__) */ +#define kalStrStr(ct, cs) strstr(ct, cs) +#define kalStrSep(s, ct) strsep(s, ct) +#define kalStrCat(dest, src) strcat(dest, src) + +/* defined for wince sdio driver only */ +#if defined(_HIF_SDIO) +#define kalDevSetPowerState(prGlueInfo, ePowerMode) glSetPowerState(prGlueInfo, ePowerMode) +#else +#define kalDevSetPowerState(prGlueInfo, ePowerMode) +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Notify OS with SendComplete event of the specific packet. Linux should +* free packets here. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pvPacket Pointer of Packet Handle +* \param[in] status Status Code for OS upper layer +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +#define kalSendComplete(prGlueInfo, pvPacket, status) \ + kalSendCompleteAndAwakeQueue(prGlueInfo, pvPacket) + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to locate the starting address of incoming ethernet +* frame for skb. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pvPacket Pointer of Packet Handle +* +* \return starting address of ethernet frame buffer. +*/ +/*----------------------------------------------------------------------------*/ +#define kalQueryBufferPointer(prGlueInfo, pvPacket) \ + ((PUINT_8)((struct sk_buff *)pvPacket)->data) + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to query the length of valid buffer which is accessible during +* port read/write. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pvPacket Pointer of Packet Handle +* +* \return starting address of ethernet frame buffer. +*/ +/*----------------------------------------------------------------------------*/ +#define kalQueryValidBufferLength(prGlueInfo, pvPacket) \ + ((UINT_32)((struct sk_buff *)pvPacket)->end - \ + (UINT_32)((struct sk_buff *)pvPacket)->data) + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to copy the entire frame from skb to the destination +* address in the input parameter. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pvPacket Pointer of Packet Handle +* \param[in] pucDestBuffer Destination Address +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +#define kalCopyFrame(prGlueInfo, pvPacket, pucDestBuffer) \ + do {struct sk_buff *skb = (struct sk_buff *)pvPacket; \ + memcpy(pucDestBuffer, skb->data, skb->len); } while (0) + +#define kalGetTimeTick() jiffies_to_msecs(jiffies) + +#define WLAN_TAG "[wlan]" +#define kalPrint(_Fmt...) pr_info(WLAN_TAG _Fmt) +#define kalPrintLimited(_Fmt...) pr_info_ratelimited(WLAN_TAG _Fmt) + +#define kalBreakPoint() \ +do { \ + WARN_ON(1); \ + panic("Oops"); \ +} while (0) + +#if CFG_ENABLE_AEE_MSG +#define kalSendAeeException aee_kernel_exception +#define kalSendAeeWarning aee_kernel_warning +#define kalSendAeeReminding aee_kernel_reminding +#else +#define kalSendAeeException(_module, _desc, ...) +#define kalSendAeeWarning(_module, _desc, ...) +#define kalSendAeeReminding(_module, _desc, ...) +#endif + +#define PRINTF_ARG(...) __VA_ARGS__ +#define SPRINTF(buf, arg) {buf += sprintf((char *)(buf), PRINTF_ARG arg); } + +#define USEC_TO_SYSTIME(_usec) ((_usec) / USEC_PER_MSEC) +#define MSEC_TO_SYSTIME(_msec) (_msec) + +#define MSEC_TO_JIFFIES(_msec) msecs_to_jiffies(_msec) +#define JIFFIES_TO_MSEC(_jiffie) jiffies_to_msecs(_jiffie) + +#define KAL_HALT_LOCK_TIMEOUT_NORMAL_CASE 3000 /* 3s */ + +/****************************************************************** + * + ******************************************************************/ +#if KERNEL_VERSION(4, 19, 0) > CFG80211_VERSION_CODE +#define KERNEL_event_trace_printk(ip, fmt, args...) \ +do { \ + __trace_printk_check_format(fmt, ##args); \ + connectivity_export_tracing_record_cmdline(current); \ + if (__builtin_constant_p(fmt)) { \ + static const char *trace_printk_fmt \ + __attribute__((section("__trace_printk_fmt"))) = \ + __builtin_constant_p(fmt) ? fmt : NULL; \ + \ + __trace_bprintk(ip, trace_printk_fmt, ##args); \ + } else \ + __trace_printk(ip, fmt, ##args); \ +} while (0) +#endif +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Routines in gl_kal.c */ +/*----------------------------------------------------------------------------*/ +VOID +kalAcquireSpinLock(IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, OUT unsigned long *pu4Flags); + +VOID kalReleaseSpinLock(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, IN UINT_32 u4Flags); + +VOID kalUpdateMACAddress(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucMacAddr); + +VOID kalPacketFree(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket); + +PVOID kalPacketAlloc(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Size, OUT PPUINT_8 ppucData); + +VOID kalOsTimerInitialize(IN P_GLUE_INFO_T prGlueInfo, IN PVOID prTimerHandler); + +BOOLEAN kalSetTimer(IN P_GLUE_INFO_T prGlueInfo, IN OS_SYSTIME rInterval); + +WLAN_STATUS +kalProcessRxPacket(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket, IN PUINT_8 pucPacketStart, IN UINT_32 u4PacketLen, + /* IN PBOOLEAN pfgIsRetain, */ + IN BOOLEAN fgIsRetain, IN ENUM_CSUM_RESULT_T aeCSUM[] +); + +WLAN_STATUS kalRxIndicatePkts(IN P_GLUE_INFO_T prGlueInfo, IN PVOID apvPkts[], IN UINT_8 ucPktNum); + +VOID +kalIndicateStatusAndComplete(IN P_GLUE_INFO_T prGlueInfo, IN WLAN_STATUS eStatus, IN PVOID pvBuf, IN UINT_32 u4BufLen); + +VOID +kalUpdateReAssocReqInfo(IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBody, IN UINT_32 u4FrameBodyLen, IN BOOLEAN fgReassocRequest); + +VOID kalUpdateReAssocRspInfo(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucFrameBody, IN UINT_32 u4FrameBodyLen); + +#if CFG_TX_FRAGMENT +BOOLEAN +kalQueryTxPacketHeader(IN P_GLUE_INFO_T prGlueInfo, + IN PVOID pvPacket, OUT PUINT_16 pu2EtherTypeLen, OUT PUINT_8 pucEthDestAddr); +#endif /* CFG_TX_FRAGMENT */ + +VOID kalSendCompleteAndAwakeQueue(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +VOID kalQueryTxChksumOffloadParam(IN PVOID pvPacket, OUT PUINT_8 pucFlag); + +VOID kalUpdateRxCSUMOffloadParam(IN PVOID pvPacket, IN ENUM_CSUM_RESULT_T eCSUM[]); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +BOOLEAN kalRetrieveNetworkAddress(IN P_GLUE_INFO_T prGlueInfo, PARAM_MAC_ADDRESS *prMacAddr); + +VOID +kalReadyOnChannel(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, + IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_8 ucChannelNum, IN UINT_32 u4DurationMs); + +VOID +kalRemainOnChannelExpired(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_8 ucChannelNum); + +VOID +kalIndicateMgmtTxStatus(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, IN BOOLEAN fgIsAck, IN PUINT_8 pucFrameBuf, IN UINT_32 u4FrameLen); + +VOID kalIndicateRxMgmtFrame(IN P_GLUE_INFO_T prGlueInfo, IN P_SW_RFB_T prSwRfb); + +/*----------------------------------------------------------------------------*/ +/* Routines in interface - ehpi/sdio.c */ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalDevRegRead(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Register, OUT PUINT_32 pu4Value); + +BOOLEAN kalDevRegWrite(P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Register, IN UINT_32 u4Value); + +BOOLEAN +kalDevPortRead(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_16 u2Port, IN UINT_32 u2Len, OUT PUINT_8 pucBuf, IN UINT_32 u2ValidOutBufSize); + +BOOLEAN +kalDevPortWrite(P_GLUE_INFO_T prGlueInfo, + IN UINT_16 u2Port, IN UINT_32 u2Len, IN PUINT_8 pucBuf, IN UINT_32 u2ValidInBufSize); + +BOOLEAN kalDevWriteWithSdioCmd52(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Addr, IN UINT_8 ucData); + +void kalDevLoopbkAuto(IN P_GLUE_INFO_T GlueInfo); + +#if CFG_SUPPORT_EXT_CONFIG +UINT_32 kalReadExtCfg(IN P_GLUE_INFO_T prGlueInfo); +#endif + +UINT_8 kalGetPktEtherType(IN PUINT_8 pucPkt); + +BOOLEAN +kalQoSFrameClassifierAndPacketInfo(IN P_GLUE_INFO_T prGlueInfo, + IN P_NATIVE_PACKET prPacket, + OUT PUINT_8 pucPriorityParam, + OUT PUINT_32 pu4PacketLen, + OUT PUINT_8 pucEthDestAddr, + OUT PBOOLEAN pfgIs1X, + OUT PBOOLEAN pfgIsPAL, OUT PUINT_8 pucNetworkType, + OUT PVOID prGenUse); + +VOID +kalOidComplete(IN P_GLUE_INFO_T prGlueInfo, + IN BOOLEAN fgSetQuery, IN UINT_32 u4SetQueryInfoLen, IN WLAN_STATUS rOidStatus); + +WLAN_STATUS +kalIoctl(IN P_GLUE_INFO_T prGlueInfo, + IN PFN_OID_HANDLER_FUNC pfnOidHandler, + IN PVOID pvInfoBuf, + IN UINT_32 u4InfoBufLen, + IN BOOLEAN fgRead, IN BOOLEAN fgWaitResp, IN BOOLEAN fgCmd, IN BOOLEAN fgIsP2pOid, OUT PUINT_32 pu4QryInfoLen); + +VOID kalHandleAssocInfo(IN P_GLUE_INFO_T prGlueInfo, IN P_EVENT_ASSOC_INFO prAssocInfo); + +#if CFG_ENABLE_FW_DOWNLOAD + +PVOID kalFirmwareImageMapping(IN P_GLUE_INFO_T prGlueInfo, OUT PPVOID ppvMapFileBuf, OUT PUINT_32 pu4FileLength); + +VOID kalFirmwareImageUnmapping(IN P_GLUE_INFO_T prGlueInfo, IN PVOID prFwHandle, IN PVOID pvMapFileBuf); +#endif + +/*----------------------------------------------------------------------------*/ +/* Card Removal Check */ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalIsCardRemoved(IN P_GLUE_INFO_T prGlueInfo); + +/*----------------------------------------------------------------------------*/ +/* TX */ +/*----------------------------------------------------------------------------*/ +VOID kalFlushPendingTxPackets(IN P_GLUE_INFO_T prGlueInfo); + +/*----------------------------------------------------------------------------*/ +/* Media State Indication */ +/*----------------------------------------------------------------------------*/ +ENUM_PARAM_MEDIA_STATE_T kalGetMediaStateIndicated(IN P_GLUE_INFO_T prGlueInfo); + +VOID kalSetMediaStateIndicated(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_PARAM_MEDIA_STATE_T eParamMediaStateIndicate); + +/*----------------------------------------------------------------------------*/ +/* OID handling */ +/*----------------------------------------------------------------------------*/ +VOID kalOidCmdClearance(IN P_GLUE_INFO_T prGlueInfo); + +VOID kalOidClearance(IN P_GLUE_INFO_T prGlueInfo); + +VOID kalEnqueueCommand(IN P_GLUE_INFO_T prGlueInfo, IN P_QUE_ENTRY_T prQueueEntry); + +#if CFG_ENABLE_BT_OVER_WIFI +/*----------------------------------------------------------------------------*/ +/* Bluetooth over Wi-Fi handling */ +/*----------------------------------------------------------------------------*/ +VOID kalIndicateBOWEvent(IN P_GLUE_INFO_T prGlueInfo, IN P_AMPC_EVENT prEvent); + +ENUM_BOW_DEVICE_STATE kalGetBowState(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rPeerAddr); + +BOOLEAN kalSetBowState(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_BOW_DEVICE_STATE eBowState, PARAM_MAC_ADDRESS rPeerAddr); + +ENUM_BOW_DEVICE_STATE kalGetBowGlobalState(IN P_GLUE_INFO_T prGlueInfo); + +UINT_32 kalGetBowFreqInKHz(IN P_GLUE_INFO_T prGlueInfo); + +UINT_8 kalGetBowRole(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rPeerAddr); + +VOID kalSetBowRole(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRole, IN PARAM_MAC_ADDRESS rPeerAddr); + +UINT_8 kalGetBowAvailablePhysicalLinkCount(IN P_GLUE_INFO_T prGlueInfo); + +#if CFG_BOW_SEPARATE_DATA_PATH +/*----------------------------------------------------------------------------*/ +/* Bluetooth over Wi-Fi Net Device Init/Uninit */ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalInitBowDevice(IN P_GLUE_INFO_T prGlueInfo, IN const char *prDevName); + +BOOLEAN kalUninitBowDevice(IN P_GLUE_INFO_T prGlueInfo); +#endif /* CFG_BOW_SEPARATE_DATA_PATH */ +#endif /* CFG_ENABLE_BT_OVER_WIFI */ + +/*----------------------------------------------------------------------------*/ +/* Firmware Download Handling */ +/*----------------------------------------------------------------------------*/ +UINT_32 kalGetFwStartAddress(IN P_GLUE_INFO_T prGlueInfo); + +UINT_32 kalGetFwLoadAddress(IN P_GLUE_INFO_T prGlueInfo); + +/*----------------------------------------------------------------------------*/ +/* Security Frame Clearance */ +/*----------------------------------------------------------------------------*/ +VOID kalClearSecurityFrames(IN P_GLUE_INFO_T prGlueInfo); + +VOID kalClearSecurityFramesByNetType(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); + +VOID kalSecurityFrameSendComplete(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket, IN WLAN_STATUS rStatus); + +/*----------------------------------------------------------------------------*/ +/* Management Frame Clearance */ +/*----------------------------------------------------------------------------*/ +VOID kalClearMgmtFrames(IN P_GLUE_INFO_T prGlueInfo); + +VOID kalClearMgmtFramesByNetType(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); + +UINT_32 kalGetTxPendingFrameCount(IN P_GLUE_INFO_T prGlueInfo); + +UINT_32 kalGetTxPendingCmdCount(IN P_GLUE_INFO_T prGlueInfo); + +BOOLEAN kalSetTimer(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Interval); + +BOOLEAN kalCancelTimer(IN P_GLUE_INFO_T prGlueInfo); + +VOID kalScanDone(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_KAL_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN WLAN_STATUS status); + +UINT_32 kalRandomNumber(VOID); + +#if KERNEL_VERSION(4, 15, 0) <= CFG80211_VERSION_CODE +VOID kalTimeoutHandler(struct timer_list *timer); +#else +VOID kalTimeoutHandler(ULONG arg); +#endif + +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 kalCfgDataRead(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Offset, + IN UINT_32 u4Len, OUT PUINT_16 pu2Data); + +BOOLEAN kalCfgDataRead16(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Offset, OUT PUINT_16 pu2Data); + +BOOLEAN kalCfgDataWrite16(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Offset, IN UINT_16 u2Data); + +/*----------------------------------------------------------------------------*/ +/* WSC Connection */ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalWSCGetActiveState(IN P_GLUE_INFO_T prGlueInfo); + +/*----------------------------------------------------------------------------*/ +/* RSSI Updating */ +/*----------------------------------------------------------------------------*/ +VOID +kalUpdateRSSI(IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_KAL_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN INT_8 cRssi, IN INT_8 cLinkQuality); + +/*----------------------------------------------------------------------------*/ +/* I/O Buffer Pre-allocation */ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalInitIOBuffer(VOID); + +VOID kalUninitIOBuffer(VOID); + +PVOID kalAllocateIOBuffer(IN UINT_32 u4AllocSize); + +VOID kalReleaseIOBuffer(IN PVOID pvAddr, IN UINT_32 u4Size); + +VOID +kalGetChannelList(IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_BAND_T eSpecificBand, + IN UINT_8 ucMaxChannelNum, IN PUINT_8 pucNumOfChannel, IN P_RF_CHANNEL_INFO_T paucChannelList); + +BOOLEAN kalIsAPmode(IN P_GLUE_INFO_T prGlueInfo); + +ULONG kalIOPhyAddrGet(IN ULONG VirtAddr); + +VOID kalDmaBufGet(IN VOID *dev, OUT VOID **VirtAddr, OUT VOID **PhyAddr); + +#if CFG_SUPPORT_802_11W +/*----------------------------------------------------------------------------*/ +/* 802.11W */ +/*----------------------------------------------------------------------------*/ +UINT_32 kalGetMfpSetting(IN P_GLUE_INFO_T prGlueInfo); +UINT_8 kalGetRsnIeMfpCap(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); + +void kalCfg80211ScanDone(struct cfg80211_scan_request *request, bool aborted); + +/*----------------------------------------------------------------------------*/ +/* PNO Support */ +/*----------------------------------------------------------------------------*/ +VOID kalSchedScanResults(IN P_GLUE_INFO_T prGlueInfo); + +VOID kalSchedScanStopped(IN P_GLUE_INFO_T prGlueInfo); + +#if CFG_SUPPORT_EMI_DEBUG +/*----------------------------------------------------------------------------*/ +/* WMT Support */ +/*----------------------------------------------------------------------------*/ +PINT8 kalGetFwInfoFormEmi(UINT8 section, UINT32 offset, PUINT8 buff, UINT32 len); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +int tx_thread(void *data); +int rx_thread(void *data); +VOID kalWakeupRxThread(P_GLUE_INFO_T prGlueInfo); + +VOID kalHifAhbKalWakeLockTimeout(IN P_GLUE_INFO_T prGlueInfo); +VOID kalMetProfilingStart(IN P_GLUE_INFO_T prGlueInfo, IN struct sk_buff *prSkb); +VOID kalMetProfilingFinish(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); +int kalMetInitProcfs(IN P_GLUE_INFO_T prGlueInfo); +int kalMetRemoveProcfs(void); + +UINT_64 kalGetBootTime(void); + +INT_32 kalReadToFile(const PUINT_8 pucPath, PUINT_8 pucData, UINT_32 u4Size, PUINT_32 pu4ReadSize); +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG +BOOLEAN kalIsWakeupByWlan(P_ADAPTER_T prAdapter); +#endif +INT_32 kalHaltLock(UINT_32 waitMs); +INT_32 kalHaltTryLock(VOID); +VOID kalHaltUnlock(VOID); +VOID kalSetHalted(BOOLEAN fgHalt); +BOOLEAN kalIsHalted(VOID); +VOID kalGetAPMCUMen(IN P_GLUE_INFO_T prGlueInfo, IN UINT32 u4StartAddr + , IN UINT32 u4Offset, IN UINT32 index, OUT PUINT_8 pucBuffer, IN UINT_32 u4BufferLen); + +INT_32 kalPerMonInit(IN P_GLUE_INFO_T prGlueInfo); +INT_32 kalPerMonDisable(IN P_GLUE_INFO_T prGlueInfo); +INT_32 kalPerMonEnable(IN P_GLUE_INFO_T prGlueInfo); +INT_32 kalPerMonStart(IN P_GLUE_INFO_T prGlueInfo); +INT_32 kalPerMonStop(IN P_GLUE_INFO_T prGlueInfo); +INT_32 kalPerMonDestroy(IN P_GLUE_INFO_T prGlueInfo); +VOID kalPerMonHandler(IN P_ADAPTER_T prAdapter, ULONG ulParam); +INT_32 kalBoostCpu(IN P_GLUE_INFO_T prGlueInfo, UINT_32 core_num); +INT32 kalSetCpuNumFreq(UINT_32 core_num, UINT_32 freq); +INT_32 kalFbNotifierReg(IN P_GLUE_INFO_T prGlueInfo); +VOID kalFbNotifierUnReg(VOID); +#if CFG_SUPPORT_SET_CAM_BY_PROC +VOID nicConfigProcSetCamCfgWrite(BOOLEAN enabled); +#endif +VOID kalChangeSchedParams(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgNormalThread); +#if CFG_SUPPORT_WPA3 +int kalExternalAuthRequest(IN P_ADAPTER_T prAdapter); +#endif + +u_int8_t kalIsValidMacAddr(IN const uint8_t *addr); + +void kalScanParseRandomMac( + P_BSS_INFO_T prBssInfo, + const struct cfg80211_scan_request *request, + uint8_t *pucRandomMac); + +BOOLEAN kalSchedScanParseRandomMac( + P_BSS_INFO_T prBssInfo, + const struct cfg80211_sched_scan_request *request, + uint8_t *pucRandomMac, uint8_t *pucRandomMacMask); +#endif /* _GL_KAL_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_os.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_os.h new file mode 100644 index 0000000000000..3ef86ca24e334 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_os.h @@ -0,0 +1,997 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _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 (CFG_TX_MAX_PKT_NUM / 2) +#define CFG_TX_START_NETIF_PER_QUEUE_THRESHOLD (CFG_TX_MAX_PKT_NUM / 8) + +#define ETH_P_1X 0x888E +#define IPTOS_PREC_OFFSET 5 +#define USER_PRIORITY_DEFAULT 0 + +#define ETH_WPI_1X 0x88B4 + +#define ETH_HLEN 14 +#define ETH_TYPE_LEN_OFFSET 12 +#define ETH_P_IP 0x0800 +#define ETH_P_1X 0x888E +#define ETH_P_PRE_1X 0x88C7 +#define ETH_P_ARP 0x0806 + +#define ARP_PRO_REQ 1 +#define ARP_PRO_RSP 2 + +#define IPVERSION 4 +#define IP_HEADER_LEN 20 +#define IP_PROTO_HLEN 9 + +#define IP_PRO_ICMP 0x01 +#define IP_PRO_UDP 0x11 +#define IP_PRO_TCP 0x06 + +#define UDP_PORT_DHCPS 0x43 +#define UDP_PORT_DHCPC 0x44 +#define UDP_PORT_DNS 0x35 + +#define IPVH_VERSION_OFFSET 4 /* For Little-Endian */ +#define IPVH_VERSION_MASK 0xF0 +#define IPTOS_PREC_OFFSET 5 +#define IPTOS_PREC_MASK 0xE0 + +#define SOURCE_PORT_LEN 2 +/* NOTE(Kevin): Without IP Option Length */ +#define LOOK_AHEAD_LEN (ETH_HLEN + IP_HEADER_LEN + SOURCE_PORT_LEN) + +/* 802.2 LLC/SNAP */ +#define ETH_LLC_OFFSET (ETH_HLEN) +#define ETH_LLC_LEN 3 +#define ETH_LLC_DSAP_SNAP 0xAA +#define ETH_LLC_SSAP_SNAP 0xAA +#define ETH_LLC_CONTROL_UNNUMBERED_INFORMATION 0x03 + +/* Bluetooth SNAP */ +#define ETH_SNAP_OFFSET (ETH_HLEN + ETH_LLC_LEN) +#define ETH_SNAP_LEN 5 +#define ETH_SNAP_BT_SIG_OUI_0 0x00 +#define ETH_SNAP_BT_SIG_OUI_1 0x19 +#define ETH_SNAP_BT_SIG_OUI_2 0x58 + +#define BOW_PROTOCOL_ID_SECURITY_FRAME 0x0003 + +#if defined(MT6620) +#define CHIP_NAME "MT6620" +#elif defined(MT6628) +#define CHIP_NAME "MT6582" +#endif + +#define DRV_NAME "["CHIP_NAME"]: " + +/* Define 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) +#define GLUE_INFO_WSCIE_LENGTH 500 + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include /* constant of kernel version */ + +#include /* bitops.h */ + +#include /* struct timer_list */ +#include /* jiffies */ +#include /* udelay and mdelay macro */ + +#if CONFIG_ANDROID +#if (KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE) +#include +#include +#else +#include +#endif +#endif + +#include /* IRQT_FALLING */ + +#include /* struct net_device, struct net_device_stats */ +#include /* for eth_type_trans() function */ +#include /* struct iw_statistics */ +#include +#include /* struct in_device */ + +#include /* struct iphdr */ + +#include /* for memcpy()/memset() function */ +#include /* for offsetof() macro */ + +#include /* The proc filesystem constants/structures */ + +#include /* for rtnl_lock() and rtnl_unlock() */ +#include /* kthread_should_stop(), kthread_run() */ +#include /* for copy_from_user() */ +#include /* for firmware download */ +#include + +#include /* for kfifo interface */ +#include /* for cdev interface */ + +#include /* for firmware download */ +#include + +#if defined(_HIF_SDIO) +#include +#include +#endif + +#include + +#include +#include + +#include /* readw and writew */ + +#if WIRELESS_EXT > 12 +#include +#endif + +#ifdef CFG_CFG80211_VERSION +#define CFG80211_VERSION_CODE CFG_CFG80211_VERSION +#else +#define CFG80211_VERSION_CODE LINUX_VERSION_CODE +#endif + +#include "version.h" +#include "config.h" + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#include +#include +#endif + +#include + +#if CFG_SUPPORT_HOTSPOT_2_0 +#include +#endif + +#include "gl_typedef.h" +#include "typedef.h" +#include "queue.h" +#include "gl_kal.h" +#include "hif.h" +#if CFG_CHIP_RESET_SUPPORT +#include "gl_rst.h" +#endif + +#if (CFG_SUPPORT_TDLS == 1) +#include "tdls_extr.h" +#include "tdls.h" +#endif +#include "debug.h" + +#include "wlan_lib.h" +#include "wlan_oid.h" + +#if CFG_ENABLE_AEE_MSG +#include +#endif + +extern BOOLEAN fgIsBusAccessFailed; +extern const struct ieee80211_iface_combination *p_mtk_sta_iface_combos; +extern const INT_32 mtk_sta_iface_combos_num; +extern UINT_8 g_aucNvram[]; + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH +typedef void (*wifi_fwlog_event_func_cb)(int, int); +/* adaptor ko */ +extern int wifi_fwlog_onoff_status(void); +extern void wifi_fwlog_event_func_register(wifi_fwlog_event_func_cb pfFwlog); +#endif + +extern struct net_device *gPrDev; +extern void update_driver_loaded_status(uint8_t loaded); + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define GLUE_FLAG_HALT BIT(0) +#define GLUE_FLAG_INT BIT(1) +#define GLUE_FLAG_OID BIT(2) +#define GLUE_FLAG_TIMEOUT BIT(3) +#define GLUE_FLAG_TXREQ BIT(4) +#define GLUE_FLAG_SUB_MOD_INIT BIT(5) +#define GLUE_FLAG_SUB_MOD_EXIT BIT(6) +#define GLUE_FLAG_SUB_MOD_MULTICAST BIT(7) +#define GLUE_FLAG_FRAME_FILTER BIT(8) +#define GLUE_FLAG_FRAME_FILTER_AIS BIT(9) +#define GLUE_FLAG_HIF_LOOPBK_AUTO BIT(10) +#define GLUE_FLAG_HALT_BIT (0) +#define GLUE_FLAG_INT_BIT (1) +#define GLUE_FLAG_OID_BIT (2) +#define GLUE_FLAG_TIMEOUT_BIT (3) +#define GLUE_FLAG_TXREQ_BIT (4) +#define GLUE_FLAG_SUB_MOD_INIT_BIT (5) +#define GLUE_FLAG_SUB_MOD_EXIT_BIT (6) +#define GLUE_FLAG_SUB_MOD_MULTICAST_BIT (7) +#define GLUE_FLAG_FRAME_FILTER_BIT (8) +#define GLUE_FLAG_FRAME_FILTER_AIS_BIT (9) +#define GLUE_FLAG_HIF_LOOPBK_AUTO_BIT (10) +#define GLUE_FLAG_RX_BIT (11) +#define GLUE_FLAG_RX BIT(GLUE_FLAG_RX_BIT) +#define GLUE_FLAG_RX_PROCESS (GLUE_FLAG_HALT | GLUE_FLAG_RX) + +#define GLUE_BOW_KFIFO_DEPTH (1024) +/* #define GLUE_BOW_DEVICE_NAME "MT6620 802.11 AMP" */ +#define GLUE_BOW_DEVICE_NAME "ampc0" + +/*Full2Partial*/ +#define UPDATE_FULL_TO_PARTIAL_SCAN_TIMEOUT 60 /* s */ + +#define FULL_SCAN_MAX_CHANNEL_NUM 40 + +#define WAKE_LOCK_RX_TIMEOUT 300 /* ms */ + +/******************************************************************************* +* 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; + UINT_8 ucRSNMfpCap; +#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; + +enum ENUM_WLAN_DRV_BUF_TYPE_T { + ENUM_BUF_TYPE_NVRAM, + ENUM_BUF_TYPE_DRV_CFG, + ENUM_BUF_TYPE_FW_CFG, + ENUM_BUF_TYPE_NUM +}; + +#endif + +typedef struct _GL_IO_REQ_T { + QUE_ENTRY_T rQueEntry; + /* wait_queue_head_t cmdwait_q; */ + BOOLEAN fgRead; + BOOLEAN fgWaitResp; +#if CFG_ENABLE_WIFI_DIRECT + BOOLEAN fgIsP2pOid; +#endif + P_ADAPTER_T prAdapter; + PFN_OID_HANDLER_FUNC pfnOidHandler; + PVOID pvInfoBuf; + UINT_32 u4InfoBufLen; + PUINT_32 pu4QryInfoLen; + WLAN_STATUS rStatus; + UINT_32 u4Flag; +} GL_IO_REQ_T, *P_GL_IO_REQ_T; + +#if CFG_ENABLE_BT_OVER_WIFI +typedef struct _GL_BOW_INFO { + BOOLEAN fgIsRegistered; + dev_t u4DeviceNumber; /* dynamic device number */ +/* struct kfifo *prKfifo; */ /* for buffering indicated events */ + struct kfifo rKfifo; /* for buffering indicated events */ + spinlock_t rSpinLock; /* spin lock for kfifo */ + struct cdev cdev; + UINT_32 u4FreqInKHz; /* frequency */ + + UINT_8 aucRole[CFG_BOW_PHYSICAL_LINK_NUM]; /* 0: Responder, 1: Initiator */ + ENUM_BOW_DEVICE_STATE aeState[CFG_BOW_PHYSICAL_LINK_NUM]; + PARAM_MAC_ADDRESS arPeerAddr[CFG_BOW_PHYSICAL_LINK_NUM]; + + wait_queue_head_t outq; + +#if CFG_BOW_SEPARATE_DATA_PATH + /* Device handle */ + struct net_device *prDevHandler; + BOOLEAN fgIsNetRegistered; +#endif + +} GL_BOW_INFO, *P_GL_BOW_INFO; +#endif + +#if (CFG_SUPPORT_TDLS == 1) +typedef struct _TDLS_INFO_LINK_T { + /* start time when link is built, end time when link is broken */ + unsigned long jiffies_start, jiffies_end; + + /* the peer MAC */ + UINT8 aucPeerMac[6]; + + /* broken reason */ + UINT8 ucReasonCode; + + /* TRUE: torn down is triggerred by us */ + UINT8 fgIsFromUs; + + /* duplicate count; same reason */ + UINT8 ucDupCount; + + /* HT capability */ +#define TDLS_INFO_LINK_HT_CAP_SUP 0x01 + UINT8 ucHtCap; +#define TDLS_INFO_LINK_HT_BA_SETUP 0x01 +#define TDLS_INFO_LINK_HT_BA_SETUP_OK 0x02 +#define TDLS_INFO_LINK_HT_BA_SETUP_DECLINE 0x04 +#define TDLS_INFO_LINK_HT_BA_PEER 0x10 +#define TDLS_INFO_LINK_HT_BA_RSP_OK 0x20 +#define TDLS_INFO_LINK_HT_BA_RSP_DECLINE 0x40 + UINT8 ucHtBa[8]; /* TID0 ~ TID7 */ +} TDLS_INFO_LINK_T; + +typedef struct _TDLS_INFO_T { + /* link history */ +#define TDLS_LINK_HISTORY_MAX 30 + TDLS_INFO_LINK_T rLinkHistory[TDLS_LINK_HISTORY_MAX]; + UINT32 u4LinkIdx; + + /* TRUE: support 20/40 bandwidth in TDLS link */ + BOOLEAN fgIs2040Sup; + + /* total TDLS link count */ + INT8 cLinkCnt; +} TDLS_INFO_T; +#endif /* CFG_SUPPORT_TDLS */ + +struct FT_IES { + UINT_16 u2MDID; + struct IE_MOBILITY_DOMAIN_T *prMDIE; + struct IE_FAST_TRANSITION_T *prFTIE; + IE_TIMEOUT_INTERVAL_T *prTIE; + P_RSN_INFO_ELEM_T prRsnIE; + PUINT_8 pucIEBuf; + UINT_32 u4IeLength; +}; + +/* +* type definition of pointer to p2p structure +*/ +typedef struct _GL_P2P_INFO_T GL_P2P_INFO_T, *P_GL_P2P_INFO_T; + +struct _GLUE_INFO_T { + /* Device handle */ + struct net_device *prDevHandler; + + /* Device Index(index of arWlanDevInfo[]) */ + INT_32 i4DevIdx; + + /* Device statistics */ + struct net_device_stats rNetDevStats; + + /* Wireless statistics struct net_device */ + struct iw_statistics rIwStats; + + /* spinlock to sync power save mechanism */ + spinlock_t rSpinLock[SPIN_LOCK_NUM]; + + /* semaphore for ioctl */ + struct semaphore ioctl_sem; + + UINT_64 u8Cookie; + + ULONG ulFlag; /* GLUE_FLAG_XXX */ + UINT_32 u4PendFlag; + /* UINT_32 u4TimeoutFlag; */ + UINT_32 u4OidCompleteFlag; + UINT_32 u4ReadyFlag; /* check if card is ready */ + + UINT_32 u4OsMgmtFrameFilter; + + /* Number of pending frames, also used for debuging if any frame is + * missing during the process of unloading Driver. + * + * NOTE(Kevin): In Linux, we also use this variable as the threshold + * for manipulating the netif_stop(wake)_queue() func. + */ + INT_32 ai4TxPendingFrameNumPerQueue[4][CFG_MAX_TXQ_NUM]; + INT_32 i4TxPendingFrameNum; + INT_32 i4TxPendingSecurityFrameNum; + + /* current IO request for kalIoctl */ + GL_IO_REQ_T OidEntry; + + /* registry info */ + REG_INFO_T rRegInfo; + + /* firmware */ + const 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; + + struct completion rScanComp; /* indicate scan complete */ + struct completion rHaltComp; /* indicate main thread halt complete */ + struct completion rRxHaltComp; /* indicate hif_thread halt complete */ + struct completion rPendComp; /* indicate main thread halt complete */ + struct completion rP2pReq; /* indicate p2p request(request channel/frame tx) + * complete + */ +#if CFG_SUPPORT_NCHO + struct completion rAisChGrntComp; /* indicate Ais channel grant complete */ +#endif +#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; + wait_queue_head_t waitq_rx; + struct task_struct *rx_thread; + KAL_WAKE_LOCK_T *rTimeoutWakeLock; + + 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[GLUE_INFO_WSCIE_LENGTH]; /*for probe req */ + UINT_16 u2WSCIELen; + UINT_8 aucWSCAssocInfoIE[200]; /*for Assoc req */ + UINT_16 u2WSCAssocInfoIELen; + +#if CFG_SUPPORT_HOTSPOT_2_0 + UINT_8 aucHS20AssocInfoIE[200]; /*for Assoc req */ + UINT_16 u2HS20AssocInfoIELen; + UINT_8 ucHotspotConfig; + BOOLEAN fgConnectHS20AP; +#endif + + /* NVRAM availability */ + BOOLEAN fgNvramAvailable; + + BOOLEAN fgMcrAccessAllowed; + + /* MAC Address Overridden by IOCTL */ + BOOLEAN fgIsMacAddrOverride; + PARAM_MAC_ADDRESS rMacAddrOverride; + + SET_TXPWR_CTRL_T rTxPwr; + + /* for cfg80211 scan done indication */ + struct cfg80211_scan_request *prScanRequest; + + /* for cfg80211 scheduled scan */ + struct cfg80211_sched_scan_request *prSchedScanRequest; + + /* to indicate registered or not */ + BOOLEAN fgIsRegistered; + + /* for cfg80211 connected indication */ + UINT_32 u4RspIeLength; + UINT_8 aucRspIe[CFG_CFG80211_IE_BUF_LEN]; + + UINT_32 u4ReqIeLength; + UINT_8 aucReqIe[CFG_CFG80211_IE_BUF_LEN]; + + KAL_WAKE_LOCK_T *rAhbIsrWakeLock; + +#if CFG_SUPPORT_HOTSPOT_2_0 + BOOLEAN fgIsDad; + UINT_8 aucDADipv4[4]; + BOOLEAN fgIs6Dad; + UINT_8 aucDADipv6[16]; +#endif +#if (CFG_SUPPORT_MET_PROFILING == 1) + UINT_8 u8MetProfEnable; + INT_16 u16MetUdpPort; +#endif + BOOLEAN fgPoorlinkValid; + UINT_64 u8Statistic[2]; + UINT_64 u8TotalFailCnt; + UINT_32 u4LinkspeedThreshold; + INT_32 i4RssiThreshold; + INT_32 i4RssiCache; + UINT_32 u4LinkSpeedCache; + +#if (CFG_SUPPORT_TDLS == 1) + /* record TX rate used to be a reference for TDLS setup */ + ULONG ulLastUpdate; + /* The last one of STA_HASH_SIZE is used as target sta */ + struct ksta_info *prStaHash[STA_HASH_SIZE + 1]; + INT_32 i4TdlsLastRx; + INT_32 i4TdlsLastTx; + enum MTK_TDLS_STATUS eTdlsStatus; + ENUM_NETWORK_TYPE_INDEX_T eTdlsNetworkType; + + TDLS_INFO_T rTdlsLink; + + UINT8 aucTdlsHtPeerMac[6]; + IE_HT_CAP_T rTdlsHtCap; /* temp to queue HT capability element */ + + /* + * [0~7]: jiffies + * [8~13]: Peer MAC + * [14]: Reason Code + * [15]: From us or peer + * [16]: Duplicate Count + */ + /* UINT8 aucTdlsDisconHistory[TDLS_DISCON_HISTORY_MAX][20]; */ + /* UINT32 u4TdlsDisconIdx; */ +#endif /* CFG_SUPPORT_TDLS */ + UINT_32 IsrCnt; + UINT_32 IsrPassCnt; + UINT_32 TaskIsrCnt; + + UINT_32 IsrPreCnt; + UINT_32 IsrPrePassCnt; + UINT_32 TaskPreIsrCnt; + + UINT_32 IsrAbnormalCnt; + UINT_32 IsrSoftWareCnt; + UINT_32 IsrTxCnt; + UINT_32 IsrRxCnt; + /* save partial scan channel information */ + PUINT_8 puScanChannel; + UINT_64 u8SkbToDriver; + UINT_64 u8SkbFreed; + + /*Full2Partial*/ + /*save update full scan to partial scan information*/ + /*last full scan time during AIS_STATE_NORMAL_TR state*/ + OS_SYSTIME u4LastFullScanTime; + /*full scan or partial scan*/ + UINT_8 ucTrScanType; + /*channel number, last full scan find AP*/ + /*UINT_8 ucChannelListNum;*/ + /*channel list, last full scan find AP*/ + UINT_8 ucChannelNum[FULL_SCAN_MAX_CHANNEL_NUM]; + /**/ + PUINT_8 puFullScan2PartialChannel; + + struct FT_IES rFtIeForTx; + struct cfg80211_ft_event_params rFtEventParam; + UINT_32 i4Priority; + + enum ENUM_BUILD_VARIANT_E rBuildVarint; + + /* FW Roaming */ + /* store the FW roaming enable state which FWK determines */ + /* if it's = 0, ignore the black/whitelists settings from FWK */ + UINT_32 u4FWRoamingEnable; + + BOOLEAN fgIsFwDlDone; +}; + +typedef irqreturn_t(*PFN_WLANISR) (int irq, void *dev_id, struct pt_regs *regs); + +typedef void (*PFN_LINUX_TIMER_FUNC) (unsigned long); + +/* + * generic sub module init/exit handler + * now, we only have one sub module, p2p + */ +#if CFG_ENABLE_WIFI_DIRECT +typedef BOOLEAN(*SUB_MODULE_INIT) (P_GLUE_INFO_T prGlueInfo); +typedef BOOLEAN(*SUB_MODULE_EXIT) (P_GLUE_INFO_T prGlueInfo); + +typedef struct _SUB_MODULE_HANDLER { + SUB_MODULE_INIT subModInit; + SUB_MODULE_EXIT subModExit; + BOOLEAN fgIsInited; +} SUB_MODULE_HANDLER, *P_SUB_MODULE_HANDLER; + +#endif + +#if CONFIG_NL80211_TESTMODE +enum TestModeCmdType { + /* old test mode command id, compatible with exist testmode command */ + TESTMODE_CMD_ID_SW_CMD = 1, + TESTMODE_CMD_ID_WAPI = 2, + TESTMODE_CMD_ID_HS20 = 3, + TESTMODE_CMD_ID_POORLINK = 4, + TESTMODE_CMD_ID_STATISTICS = 0x10, + TESTMODE_CMD_ID_LINK_DETECT = 0x20, + /* old test mode command id, compatible with exist testmode command */ + + /* Hotspot managerment testmode command */ + TESTMODE_CMD_ID_HS_CONFIG = 51, + + /* all new added test mode command should great than TESTMODE_CMD_ID_NEW_BEGIN */ + TESTMODE_CMD_ID_NEW_BEGIN = 100, + TESTMODE_CMD_ID_SUSPEND = 101, + TESTMODE_CMD_ID_STR_CMD = 102, + TESTMODE_CMD_ID_RXFILTER = 103, +}; +#if CFG_SUPPORT_HOTSPOT_2_0 +enum Hs20CmdType { + HS20_CMD_ID_SET_BSSID_POOL = 0, + NUM_OF_HS20_CMD_ID +}; +#endif + +typedef struct _NL80211_DRIVER_TEST_MODE_PARAMS { + UINT_32 index; + UINT_32 buflen; +} NL80211_DRIVER_TEST_MODE_PARAMS, *P_NL80211_DRIVER_TEST_MODE_PARAMS; + +/*SW CMD */ +typedef struct _NL80211_DRIVER_SW_CMD_PARAMS { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + UINT_8 set; + UINT_32 adr; + UINT_32 data; +} NL80211_DRIVER_SW_CMD_PARAMS, *P_NL80211_DRIVER_SW_CMD_PARAMS; + +typedef struct _NL80211_DRIVER_SUSPEND_PARAMS { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + UINT_8 suspend; +} NL80211_DRIVER_SUSPEND_PARAMS, *P_NL80211_DRIVER_SUSPEND_PARAMS; + +typedef struct _NL80211_DRIVER_RXFILTER_PARAMS { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + UINT_32 Ipv4FilterHigh; + UINT_32 Ipv4FilterLow; + UINT_32 Ipv6FilterHigh; + UINT_32 Ipv6FilterLow; + UINT_32 SnapFilterHigh; + UINT_32 SnapFilterLow; +} NL80211_DRIVER_RXFILTER_PARAMS, *P_NL80211_DRIVER_RXFILTER_PARAMS; + +struct iw_encode_exts { + __u32 ext_flags; /*!< IW_ENCODE_EXT_* */ + __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /*!< LSB first */ + __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /*!< LSB first */ + __u8 addr[MAC_ADDR_LEN]; /* + * !< ff:ff:ff:ff:ff:ff for broadcast/multicast + * (group) keys or unicast address for + * individual keys + */ + __u16 alg; /*!< IW_ENCODE_ALG_* */ + __u16 key_len; + __u8 key[32]; +}; + +/*SET KEY EXT */ +typedef struct _NL80211_DRIVER_SET_KEY_EXTS { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + UINT_8 key_index; + UINT_8 key_len; + struct iw_encode_exts ext; +} NL80211_DRIVER_SET_KEY_EXTS, *P_NL80211_DRIVER_SET_KEY_EXTS; + +#if CFG_SUPPORT_HOTSPOT_2_0 + +struct param_hs20_set_bssid_pool { + u8 fgBssidPoolIsEnable; + u8 ucNumBssidPool; + u8 arBssidPool[8][ETH_ALEN]; +}; + +struct wpa_driver_hs20_data_s { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + enum Hs20CmdType CmdType; + struct param_hs20_set_bssid_pool hs20_set_bssid_pool; +}; + +#endif /* CFG_SUPPORT_HOTSPOT_2_0 */ + +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Macros of SPIN LOCK operations for using in Glue Layer */ +/*----------------------------------------------------------------------------*/ +#if CFG_USE_SPIN_LOCK_BOTTOM_HALF +#define GLUE_SPIN_LOCK_DECLARATION() +#define GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, rLockCategory) \ + { \ + if (rLockCategory < SPIN_LOCK_NUM) \ + spin_lock_bh(&(prGlueInfo->rSpinLock[rLockCategory])); \ + } +#define GLUE_RELEASE_SPIN_LOCK(prGlueInfo, rLockCategory) \ + { \ + if (rLockCategory < SPIN_LOCK_NUM) \ + spin_unlock_bh(&(prGlueInfo->rSpinLock[rLockCategory])); \ + } +#define GLUE_ACQUIRE_THE_SPIN_LOCK(prLock) \ + spin_lock_bh(prLock) +#define GLUE_RELEASE_THE_SPIN_LOCK(prLock) \ + spin_unlock_bh(prLock) + +#else /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ +#define GLUE_SPIN_LOCK_DECLARATION() unsigned long __u4Flags = 0 +#define GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, rLockCategory) \ + { \ + if (rLockCategory < SPIN_LOCK_NUM) \ + spin_lock_irqsave(&(prGlueInfo)->rSpinLock[rLockCategory], __u4Flags); \ + } +#define GLUE_RELEASE_SPIN_LOCK(prGlueInfo, rLockCategory) \ + { \ + if (rLockCategory < SPIN_LOCK_NUM) \ + spin_unlock_irqrestore(&(prGlueInfo->rSpinLock[rLockCategory]), __u4Flags); \ + } +#define GLUE_ACQUIRE_THE_SPIN_LOCK(prLock) \ + spin_lock_irqsave(prLock, __u4Flags) +#define GLUE_RELEASE_THE_SPIN_LOCK(prLock) \ + spin_unlock_irqrestore(prLock, __u4Flags) +#endif /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + +/*----------------------------------------------------------------------------*/ +/* Macros for accessing Reserved Fields of native packet */ +/*----------------------------------------------------------------------------*/ +#define GLUE_CB_OFFSET 4 /* + * For 64-bit platform, avoiding that the cb + * isoverwrited by "(prQueueEntry)->prNext = + * (P_QUE_ENTRY_T)NULL;" in QUEUE_INSERT_TAIL + */ +#define GLUE_GET_PKT_QUEUE_ENTRY(_p) \ + (&(((struct sk_buff *)(_p))->cb[0])) + +#define GLUE_GET_PKT_DESCRIPTOR(_prQueueEntry) \ + ((P_NATIVE_PACKET) ((ULONG)_prQueueEntry - offsetof(struct sk_buff, cb[0]))) + +#define GLUE_SET_PKT_FLAG_802_11(_p) \ + (*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4])) |= BIT(7)) + +#define GLUE_SET_PKT_FLAG_1X(_p) \ + (*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4])) |= BIT(6)) + +#define GLUE_SET_PKT_FLAG_PAL(_p) \ + (*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4])) |= BIT(5)) + +#define GLUE_SET_PKT_FLAG_P2P(_p) \ + (*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4])) |= BIT(4)) + +#define GLUE_SET_PKT_TID(_p, _tid) \ + (*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4])) |= (((UINT_8)((_tid) & (BITS(0, 3)))))) + +#define GLUE_SET_PKT_FRAME_LEN(_p, _u2PayloadLen) \ + (*((PUINT_16)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+6])) = (UINT_16)(_u2PayloadLen)) + +#define GLUE_GET_PKT_FRAME_LEN(_p) \ + (*((PUINT_16)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+6]))) + +#define GLUE_GET_PKT_IS_802_11(_p) \ + ((*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4]))) & (BIT(7))) + +#define GLUE_GET_PKT_IS_1X(_p) \ + ((*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4]))) & (BIT(6))) + +#define GLUE_GET_PKT_TID(_p) \ + ((*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4]))) & (BITS(0, 3))) + +#define GLUE_GET_PKT_IS_PAL(_p) \ + ((*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4]))) & (BIT(5))) + +#define GLUE_GET_PKT_IS_P2P(_p) \ + ((*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4]))) & (BIT(4))) + +#define GLUE_SET_PKT_HEADER_LEN(_p, _ucMacHeaderLen) \ + (*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+5])) = (UINT_8)(_ucMacHeaderLen)) + +#define GLUE_GET_PKT_HEADER_LEN(_p) \ + (*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+5]))) + +#define GLUE_SET_PKT_ARRIVAL_TIME(_p, _rSysTime) \ + (*((POS_SYSTIME)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+8])) = (OS_SYSTIME)(_rSysTime)) + +#define GLUE_GET_PKT_ARRIVAL_TIME(_p) \ + (*((POS_SYSTIME)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+8]))) + +#define GLUE_SET_PKT_XTIME(_p, _rSysTime) \ + (*((UINT_64 *)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+16])) = (UINT_64)(_rSysTime)) + +#define GLUE_GET_PKT_XTIME(_p) \ + (*((UINT_64 *)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+16]))) + +/* Check validity of prDev, private data, and pointers */ +#define GLUE_CHK_DEV(prDev) \ + ((prDev && *((P_GLUE_INFO_T *) netdev_priv(prDev))) ? TRUE : FALSE) + +#define GLUE_CHK_PR2(prDev, pr2) \ + ((GLUE_CHK_DEV(prDev) && pr2) ? TRUE : FALSE) + +#define GLUE_CHK_PR3(prDev, pr2, pr3) \ + ((GLUE_CHK_PR2(prDev, pr2) && pr3) ? TRUE : FALSE) + +#define GLUE_CHK_PR4(prDev, pr2, pr3, pr4) \ + ((GLUE_CHK_PR3(prDev, pr2, pr3) && pr4) ? TRUE : FALSE) + +#define GLUE_SET_EVENT(pr) \ + kalSetEvent(pr) + +#define GLUE_INC_REF_CNT(_refCount) atomic_inc((atomic_t *)&(_refCount)) +#define GLUE_DEC_REF_CNT(_refCount) atomic_dec((atomic_t *)&(_refCount)) + +#define DbgPrint(...) +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +#ifdef WLAN_INCLUDE_PROC +INT_32 procRemoveProcfs(VOID); + +INT_32 procCreateFsEntry(P_GLUE_INFO_T prGlueInfo); +INT_32 procInitFs(VOID); +INT_32 procUninitProcFs(VOID); + +#endif /* WLAN_INCLUDE_PROC */ + +#if WLAN_INCLUDE_SYS +int32_t sysCreateFsEntry(P_GLUE_INFO_T prGlueInfo); +int32_t sysRemoveSysfs(void); +int32_t sysInitFs(void); +int32_t sysUninitSysFs(void); +int32_t sysMacAddrOverride(uint8_t *prMacAddr); +#endif /* WLAN_INCLUDE_SYS */ + +#if CFG_ENABLE_BT_OVER_WIFI +BOOLEAN glRegisterAmpc(P_GLUE_INFO_T prGlueInfo); + +BOOLEAN glUnregisterAmpc(P_GLUE_INFO_T prGlueInfo); +#endif + +#if CFG_ENABLE_WIFI_DIRECT + +VOID wlanSubModRunInit(P_GLUE_INFO_T prGlueInfo); + +VOID wlanSubModRunExit(P_GLUE_INFO_T prGlueInfo); + +BOOLEAN wlanSubModInit(P_GLUE_INFO_T prGlueInfo); + +BOOLEAN wlanSubModExit(P_GLUE_INFO_T prGlueInfo); + +VOID +wlanSubModRegisterInitExit(SUB_MODULE_INIT rSubModInit, SUB_MODULE_EXIT rSubModExit, ENUM_SUB_MODULE_IDX_T eSubModIdx); + +BOOLEAN wlanExportGlueInfo(P_GLUE_INFO_T *prGlueInfoExpAddr); + +BOOLEAN wlanIsLaunched(VOID); + +VOID wlanUpdateChannelTable(P_GLUE_INFO_T prGlueInfo); + +#endif + +#ifdef FW_CFG_SUPPORT +INT_32 cfgCreateProcEntry(P_GLUE_INFO_T prGlueInfo); +INT_32 cfgRemoveProcEntry(void); +#endif + +typedef UINT_8 (*file_buf_handler) (PVOID ctx, const CHAR __user *buf, UINT_16 length); +extern VOID register_file_buf_handler(file_buf_handler handler, PVOID ctx, UINT_8 ucType); +extern const uint8_t *kalFindIeMatchMask(uint8_t eid, + const uint8_t *ies, int len, + const uint8_t *match, + int match_len, int match_offset, + const uint8_t *match_mask); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _GL_OS_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_p2p_ioctl.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_p2p_ioctl.h new file mode 100644 index 0000000000000..b9b25787c134b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_p2p_ioctl.h @@ -0,0 +1,581 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _GL_P2P_IOCTL_H +#define _GL_P2P_IOCTL_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#include +#include +#endif + +#include "wlan_oid.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* Device private ioctl calls */ +/* #define SIOCDEVPRIVATE 0x89F0*/ +#define IOC_GET_PRIVATE_IOCTL_CMD (SIOCDEVPRIVATE+1) + +/* (WirelessExtension) Private I/O Controls */ +#define IOC_P2P_CFG_DEVICE (SIOCIWFIRSTPRIV+0) +#define IOC_P2P_PROVISION_COMPLETE (SIOCIWFIRSTPRIV+2) +#define IOC_P2P_START_STOP_DISCOVERY (SIOCIWFIRSTPRIV+4) +#define IOC_P2P_DISCOVERY_RESULTS (SIOCIWFIRSTPRIV+5) +#define IOC_P2P_WSC_BEACON_PROBE_RSP_IE (SIOCIWFIRSTPRIV+6) +#define IOC_P2P_GO_WSC_IE IOC_P2P_WSC_BEACON_PROBE_RSP_IE +#define IOC_P2P_CONNECT_DISCONNECT (SIOCIWFIRSTPRIV+8) +#define IOC_P2P_PASSWORD_READY (SIOCIWFIRSTPRIV+10) +/* #define IOC_P2P_SET_PWR_MGMT_PARAM (SIOCIWFIRSTPRIV+12) */ +#define IOC_P2P_SET_INT (SIOCIWFIRSTPRIV+12) +#define IOC_P2P_GET_STRUCT (SIOCIWFIRSTPRIV+13) +#define IOC_P2P_SET_STRUCT (SIOCIWFIRSTPRIV+14) +#define IOC_P2P_GET_REQ_DEVICE_INFO (SIOCIWFIRSTPRIV+15) + +#define PRIV_CMD_INT_P2P_SET 0 + +/* IOC_P2P_PROVISION_COMPLETE (iw_point . flags) */ +#define P2P_PROVISIONING_SUCCESS 0 +#define P2P_PROVISIONING_FAIL 1 + +/* IOC_P2P_START_STOP_DISCOVERY (iw_point . flags) */ +#define P2P_STOP_DISCOVERY 0 +#define P2P_START_DISCOVERY 1 + +/* IOC_P2P_CONNECT_DISCONNECT (iw_point . flags) */ +#define P2P_CONNECT 0 +#define P2P_DISCONNECT 1 + +/* IOC_P2P_START_STOP_DISCOVERY (scan_type) */ +#define P2P_SCAN_FULL_AND_FIND 0 +#define P2P_SCAN_FULL 1 +#define P2P_SCAN_SEARCH_AND_LISTEN 2 +#define P2P_LISTEN 3 + +/* IOC_P2P_GET_STRUCT/IOC_P2P_SET_STRUCT */ +#define P2P_SEND_SD_RESPONSE 0 +#define P2P_GET_SD_REQUEST 1 +#define P2P_SEND_SD_REQUEST 2 +#define P2P_GET_SD_RESPONSE 3 +#define P2P_TERMINATE_SD_PHASE 4 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Wireless Extension: Private I/O Control */ +/*----------------------------------------------------------------------------*/ +typedef struct iw_p2p_cfg_device_type { + void __user *ssid; + UINT_8 ssid_len; + UINT_8 pri_device_type[8]; + UINT_8 snd_device_type[8]; + void __user *device_name; + UINT_8 device_name_len; + UINT_8 intend; + UINT_8 persistence; + UINT_8 sec_mode; + UINT_8 ch; + UINT_8 ch_width; /* 0: 20 Mhz 1:20/40 Mhz auto */ + UINT_8 max_scb; +} IW_P2P_CFG_DEVICE_TYPE, *P_IW_P2P_CFG_DEVICE_TYPE; + +typedef struct iw_p2p_hostapd_param { + UINT_8 cmd; + UINT_8 rsv[3]; + UINT_8 sta_addr[6]; + void __user *data; + UINT_16 len; +} IW_P2P_HOSTAPD_PARAM, *P_IW_P2P_HOSTAPD_PARAM; + +typedef struct iw_p2p_req_device_type { + UINT_8 scan_type; /* 0: Full scan + Find + * 1: Full scan + * 2: Scan (Search +Listen) + * 3: Listen + * other : reserved + */ + UINT_8 pri_device_type[8]; + void __user *probe_req_ie; + UINT_16 probe_req_len; + void __user *probe_rsp_ie; + UINT_16 probe_rsp_len; +} IW_P2P_REQ_DEVICE_TYPE, *P_IW_P2P_REQ_DEVICE_TYPE; + +typedef struct iw_p2p_connect_device { + UINT_8 sta_addr[6]; + UINT_8 p2pRole; /* 0: P2P Device, 1:GC, 2: GO */ + UINT_8 needProvision; /* 0: Don't needed provision, 1: doing the wsc provision first */ + UINT_8 authPeer; /* 1: auth peer invitation request */ + UINT_8 intend_config_method; /* Request Peer Device used config method */ +} IW_P2P_CONNECT_DEVICE, *P_IW_P2P_CONNECT_DEVICE; + +typedef struct iw_p2p_password_ready { + UINT_8 active_config_method; + void __user *probe_req_ie; + UINT_16 probe_req_len; + void __user *probe_rsp_ie; + UINT_16 probe_rsp_len; +} IW_P2P_PASSWORD_READY, *P_IW_P2P_PASSWORD_READY; + +typedef struct iw_p2p_device_req { + UINT_8 name[33]; + UINT_32 name_len; + UINT_8 device_addr[6]; + UINT_8 device_type; + INT_32 config_method; + INT_32 active_config_method; +} IW_P2P_DEVICE_REQ, *P_IW_P2P_DEVICE_REQ; + +typedef struct iw_p2p_transport_struct { + UINT_32 u4CmdId; + UINT_32 inBufferLength; + UINT_32 outBufferLength; + UINT_8 aucBuffer[16]; +} IW_P2P_TRANSPORT_STRUCT, *P_IW_P2P_TRANSPORT_STRUCT; + +/* For Invitation */ +typedef struct iw_p2p_ioctl_invitation_struct { + UINT_8 aucDeviceID[6]; + UINT_8 aucGroupID[6]; /* BSSID */ + UINT_8 aucSsid[32]; + UINT_32 u4SsidLen; + UINT_8 ucReinvoke; +} IW_P2P_IOCTL_INVITATION_STRUCT, *P_IW_P2P_IOCTL_INVITATION_STRUCT; + +typedef struct iw_p2p_ioctl_abort_invitation { + UINT_8 dev_addr[6]; +} IW_P2P_IOCTL_ABORT_INVITATION, *P_IW_P2P_IOCTL_ABORT_INVITATION; + +typedef struct iw_p2p_ioctl_invitation_indicate { + UINT_8 dev_addr[6]; + UINT_8 group_bssid[6]; + INT_32 config_method; /* peer device supported config method */ + UINT_8 dev_name[32]; /* for reinvoke */ + UINT_32 name_len; + UINT_8 operating_channel; /* for re-invoke, target operating channel */ + UINT_8 invitation_type; /* invitation or re-invoke */ +} IW_P2P_IOCTL_INVITATION_INDICATE, *P_IW_P2P_IOCTL_INVITATION_INDICATE; + +typedef struct iw_p2p_ioctl_invitation_status { + UINT_32 status_code; +} IW_P2P_IOCTL_INVITATION_STATUS, *P_IW_P2P_IOCTL_INVITATION_STATUS; + +/* For Formation */ +typedef struct iw_p2p_ioctl_start_formation { + UINT_8 dev_addr[6]; /* bssid */ + UINT_8 role; /* 0: P2P Device, 1:GC, 2: GO */ + UINT_8 needProvision; /* 0: Don't needed provision, 1: doing the wsc provision first */ + UINT_8 auth; /* 1: auth peer invitation request */ + UINT_8 config_method; /* Request Peer Device used config method */ +} IW_P2P_IOCTL_START_FORMATION, *P_IW_P2P_IOCTL_START_FORMATION; + +/* SET_STRUCT / GET_STRUCT */ +typedef enum _ENUM_P2P_CMD_ID_T { + P2P_CMD_ID_SEND_SD_RESPONSE = 0, /* 0x00 (Set) */ + P2P_CMD_ID_GET_SD_REQUEST, /* 0x01 (Get) */ + P2P_CMD_ID_SEND_SD_REQUEST, /* 0x02 (Set) */ + P2P_CMD_ID_GET_SD_RESPONSE, /* 0x03 (Get) */ + P2P_CMD_ID_TERMINATE_SD_PHASE, /* 0x04 (Set) */ +#if 1 /* CFG_SUPPORT_ANTI_PIRACY */ + P2P_CMD_ID_SEC_CHECK, /* 0x05(Set) */ +#endif + P2P_CMD_ID_INVITATION, /* 0x06 (Set) */ + P2P_CMD_ID_INVITATION_INDICATE, /* 0x07 (Get) */ + P2P_CMD_ID_INVITATION_STATUS, /* 0x08 (Get) */ + P2P_CMD_ID_INVITATION_ABORT, /* 0x09 (Set) */ + P2P_CMD_ID_START_FORMATION, /* 0x0A (Set) */ + P2P_CMD_ID_P2P_VERSION, /* 0x0B (Set/Get) */ + P2P_CMD_ID_GET_CH_LIST = 12, /* 0x0C (Get) */ + P2P_CMD_ID_GET_OP_CH = 14 /* 0x0E (Get) */ +} ENUM_P2P_CMD_ID_T, *P_ENUM_P2P_CMD_ID_T; + +/* Service Discovery */ +typedef struct iw_p2p_cmd_send_sd_response { + PARAM_MAC_ADDRESS rReceiverAddr; + UINT_8 fgNeedTxDoneIndication; + UINT_8 ucSeqNum; + UINT_16 u2PacketLength; + UINT_8 aucPacketContent[0]; /*native 802.11 */ +} IW_P2P_CMD_SEND_SD_RESPONSE, *P_IW_P2P_CMD_SEND_SD_RESPONSE; + +typedef struct iw_p2p_cmd_get_sd_request { + PARAM_MAC_ADDRESS rTransmitterAddr; + UINT_16 u2PacketLength; + UINT_8 aucPacketContent[0]; /*native 802.11 */ +} IW_P2P_CMD_GET_SD_REQUEST, *P_IW_P2P_CMD_GET_SD_REQUEST; + +typedef struct iw_p2p_cmd_send_service_discovery_request { + PARAM_MAC_ADDRESS rReceiverAddr; + UINT_8 fgNeedTxDoneIndication; + UINT_8 ucSeqNum; + UINT_16 u2PacketLength; + UINT_8 aucPacketContent[0]; /*native 802.11 */ +} IW_P2P_CMD_SEND_SD_REQUEST, *P_IW_P2P_CMD_SEND_SD_REQUEST; + +typedef struct iw_p2p_cmd_get_sd_response { + PARAM_MAC_ADDRESS rTransmitterAddr; + UINT_16 u2PacketLength; + UINT_8 aucPacketContent[0]; /*native 802.11 */ +} IW_P2P_CMD_GET_SD_RESPONSE, *P_IW_P2P_CMD_GET_SD_RESPONSE; + +typedef struct iw_p2p_cmd_terminate_sd_phase { + PARAM_MAC_ADDRESS rPeerAddr; +} IW_P2P_CMD_TERMINATE_SD_PHASE, *P_IW_P2P_CMD_TERMINATE_SD_PHASE; + +typedef struct iw_p2p_version { + UINT_32 u4Version; +} IW_P2P_VERSION, *P_IW_P2P_VERSION; + +typedef enum _ENUM_TESTMODE_AVAILABLE_CHAN_ATTR { + __NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_INVALID, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_2G_BASE_1, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_36, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_52, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_100, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_149, + __NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_AFTER_LAST, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_MAX = __NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_AFTER_LAST - 1 +} ENUM_TESTMODE_AVAILABLE_CHAN_ATTR; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +extern struct ieee80211_supported_band mtk_band_2ghz; +extern struct ieee80211_supported_band mtk_band_5ghz; +extern const UINT_32 mtk_cipher_suites[6]; +#endif + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type, struct vif_params *params); +#else +int mtk_p2p_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type, u32 *flags, struct vif_params *params); +#endif +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_cfg80211_add_station(struct wiphy *wiphy, struct net_device *ndev, + const u8 *mac, struct station_parameters *params); + +int mtk_cfg80211_change_station(struct wiphy *wiphy, struct net_device *ndev, + const u8 *mac, struct station_parameters *params); + +int mtk_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_set_mgmt_key(struct wiphy *wiphy, struct net_device *dev, u8 key_index); + +int mtk_p2p_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, + const u8 *mac, struct station_info *sinfo); + +int mtk_p2p_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed); + +int mtk_p2p_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_connect_params *sme); + +int mtk_p2p_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code); + +int mtk_p2p_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ibss_params *params); + +int mtk_p2p_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev); + +int mtk_p2p_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, bool enabled, int timeout); + +int mtk_p2p_cfg80211_change_bss(struct wiphy *wiphy, struct net_device *dev, struct bss_parameters *params); + +int mtk_p2p_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, unsigned int duration, u64 *cookie); + +int mtk_p2p_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request); + +void mtk_p2p_cfg80211_abort_scan(struct wiphy *wiphy, struct wireless_dev *wdev); + +int mtk_p2p_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie); + +int mtk_p2p_cfg80211_set_txpower(struct wiphy *wiphy, + struct wireless_dev *wdev, enum nl80211_tx_power_setting type, int mbm); + +int mtk_p2p_cfg80211_get_txpower(struct wiphy *wiphy, struct wireless_dev *wdev, int *dbm); + +int mtk_p2p_cfg80211_deauth(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_deauth_request *req); + +int mtk_p2p_cfg80211_disassoc(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_disassoc_request *req); + +int mtk_p2p_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ap_settings *settings); + +int mtk_p2p_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_beacon_data *info); + +int mtk_p2p_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie); + +int mtk_p2p_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, struct station_del_parameters *params); +#else +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, const u8 *mac); +#endif + +int mtk_p2p_cfg80211_set_channel(struct wiphy *wiphy, struct cfg80211_chan_def *chandef); + +void mtk_p2p_cfg80211_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev, u16 frame_type, bool reg); + +int +mtk_p2p_cfg80211_set_bitrate_mask(IN struct wiphy *wiphy, + IN struct net_device *dev, + IN const u8 *peer, IN const struct cfg80211_bitrate_mask *mask); + +#if CONFIG_NL80211_TESTMODE + +int mtk_p2p_cfg80211_testmode_cmd(IN struct wiphy *wiphy, IN struct wireless_dev *wdev, IN void *data, IN int len); + +int mtk_cfg80211_process_str_cmd(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 cmd, IN INT_32 len); + +int mtk_p2p_cfg80211_testmode_p2p_sigma_pre_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); + +int mtk_p2p_cfg80211_testmode_p2p_sigma_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); + +#if CFG_SUPPORT_WFD +int mtk_p2p_cfg80211_testmode_wfd_update_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); +#endif + +int mtk_p2p_cfg80211_testmode_hotspot_block_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); + +int mtk_p2p_cfg80211_testmode_hotspot_config_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); + +#else +#error "Please ENABLE kernel config (CONFIG_NL80211_TESTMODE)" +#endif + +#endif + +/* I/O control handlers */ + +int +mtk_p2p_wext_get_priv(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_reconnect(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_auth(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_key(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_mlme_handler(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_powermode(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_get_powermode(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +/* Private Wireless I/O Controls takes use of iw_handler */ +int +mtk_p2p_wext_set_local_dev_info(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_provision_complete(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_start_stop_discovery(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_discovery_results(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_wsc_ie(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_connect_disconnect(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_password_ready(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_request_dev_info(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_invitation_indicate(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_invitation_status(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_pm_param(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_ps_profile(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_network_address(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_int(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +/* Private Wireless I/O Controls for IOC_SET_STRUCT/IOC_GET_STRUCT */ +int +mtk_p2p_wext_set_struct(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_get_struct(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +/* IOC_SET_STRUCT/IOC_GET_STRUCT: Service Discovery */ +int +mtk_p2p_wext_get_service_discovery_request(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_get_service_discovery_response(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_send_service_discovery_request(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_send_service_discovery_response(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_terminate_service_discovery_phase(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +#if CFG_SUPPORT_ANTI_PIRACY +int +mtk_p2p_wext_set_sec_check_request(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_get_sec_check_response(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); +#endif + +int +mtk_p2p_wext_set_noa_param(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_oppps_param(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_p2p_version(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_get_p2p_version(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +void mtk_p2p_wext_set_Multicastlist(IN P_GLUE_INFO_T prGlueInfo); + +#if CFG_SUPPORT_P2P_RSSI_QUERY +int +mtk_p2p_wext_get_rssi(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +struct iw_statistics *mtk_p2p_wext_get_wireless_stats(struct net_device *prDev); + +#endif + +int +mtk_p2p_wext_set_txpow(IN struct net_device *prDev, + IN struct iw_request_info *prIwrInfo, IN OUT union iwreq_data *prTxPow, IN char *pcExtra); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _GL_P2P_IOCTL_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_p2p_kal.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_p2p_kal.h new file mode 100644 index 0000000000000..dbd89bee5b922 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_p2p_kal.h @@ -0,0 +1,223 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _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 + +extern BOOLEAN +wextSrchDesiredWPAIE(IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT unsigned char **ppucDesiredIE); + +#if CFG_SUPPORT_WPS +extern BOOLEAN +wextSrchDesiredWPSIE(IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT unsigned char **ppucDesiredIE); +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +BOOLEAN kalP2pFuncGetChannelType(IN ENUM_CHNL_EXT_T rChnlSco, OUT enum nl80211_channel_type *channel_type); +struct ieee80211_channel *kalP2pFuncGetChannelEntry(IN P_GL_P2P_INFO_T prP2pInfo, IN P_RF_CHANNEL_INFO_T prChannelInfo); + +#if CFG_SUPPORT_P2P_ECSA +VOID kalP2pUpdateECSA(IN P_ADAPTER_T prAdapter, IN P_EVENT_ECSA_RESULT prECSA); +#endif + +/* 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); + +UINT_16 kalP2PCalP2P_IELen(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucIndex); + +VOID kalP2PGenP2P_IE(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucIndex, IN PUINT_8 pucBuffer); + +VOID kalP2PUpdateP2P_IE(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucIndex, 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 +kalP2PIndicateCompleteBssInfo(IN P_GLUE_INFO_T prGlueInfo, IN P_BSS_DESC_T prSpecificBssDesc); + +VOID kalP2PIndicateRxMgmtFrame(IN P_GLUE_INFO_T prGlueInfo, IN P_SW_RFB_T prSwRfb); + +VOID +kalP2PIndicateMgmtTxStatus(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, IN BOOLEAN fgIsAck, IN PUINT_8 pucFrameBuf, IN UINT_32 u4FrameLen); + +VOID kalP2PIndicateChannelExpired(IN P_GLUE_INFO_T prGlueInfo, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo); + +VOID +kalP2PGCIndicateConnectionStatus(IN P_GLUE_INFO_T prGlueInfo, + IN P_P2P_CONNECTION_REQ_INFO_T prP2pConnInfo, + IN PUINT_8 pucRxIEBuf, IN UINT_16 u2RxIELen, IN UINT_16 u2StatusReason, + IN WLAN_STATUS eStatus); + +VOID kalP2PGOStationUpdate(IN P_GLUE_INFO_T prGlueInfo, IN P_STA_RECORD_T prCliStaRec, IN BOOLEAN fgIsNew); + +INT_32 kalP2PSetBlackList(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS bssid, IN BOOLEAN block); + +BOOLEAN kalP2PCmpBlackList(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS bssid); + +VOID kalP2PSetMaxClients(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4MaxClient); + +BOOLEAN kalP2PReachMaxClients(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4NumClient); + +VOID kalP2pUnlinkBss(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 aucBSSID[]); + +void kalP2pIndicateQueuedMgmtFrame(IN P_GLUE_INFO_T prGlueInfo, + IN struct P2P_QUEUED_ACTION_FRAME *prFrame); + +void kalP2pIndicateAcsResult(IN P_GLUE_INFO_T prGlueInfo, + IN uint8_t ucPrimaryCh, + IN uint8_t ucSecondCh, + IN uint8_t ucSeg0Ch, + IN uint8_t ucSeg1Ch, + IN enum ENUM_MAX_BANDWIDTH_SETTING eChnlBw); + +#endif /* _GL_P2P_KAL_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_p2p_os.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_p2p_os.h new file mode 100644 index 0000000000000..e2e31b3ba4b6f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_p2p_os.h @@ -0,0 +1,264 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _GL_P2P_OS_H +#define _GL_P2P_OS_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#include +#endif + +#include "wlan_oid.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define OID_SET_GET_STRUCT_LENGTH 4096 /* For SET_STRUCT/GET_STRUCT */ + +#define MAX_P2P_IE_SIZE 5 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +extern struct net_device *g_P2pPrDev; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +struct _GL_P2P_INFO_T { + + /* Device handle */ + struct net_device *prDevHandler; + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + /* cfg80211 */ + struct wireless_dev *prWdev; + + struct cfg80211_scan_request *prScanRequest; + + UINT_64 u8Cookie; + + /* Generation for station list update. */ + INT_32 i4Generation; + + UINT_32 u4OsMgmtFrameFilter; + +#endif + + /* Device statistics */ + struct net_device_stats rNetDevStats; + + /* glue layer variables */ + UINT_32 u4FreqInKHz; /* frequency */ + UINT_8 ucRole; /* 0: P2P Device, 1: Group Client, 2: Group Owner */ + UINT_8 ucIntent; /* range: 0-15 */ + UINT_8 ucScanMode; /* 0: Search & Listen, 1: Scan without probe response */ + + ENUM_PARAM_MEDIA_STATE_T eState; + UINT_32 u4PacketFilter; + PARAM_MAC_ADDRESS aucMCAddrList[MAX_NUM_GROUP_ADDR]; + + /* connection-requested peer information */ + UINT_8 aucConnReqDevName[32]; + INT_32 u4ConnReqNameLength; + PARAM_MAC_ADDRESS rConnReqPeerAddr; + PARAM_MAC_ADDRESS rConnReqGroupAddr; /* For invitation group. */ + UINT_8 ucConnReqDevType; + INT_32 i4ConnReqConfigMethod; + INT_32 i4ConnReqActiveConfigMethod; + + UINT_32 u4CipherPairwise; + UINT_8 ucWSCRunning; + + UINT_8 aucWSCIE[3][400]; /* 0 for beacon, 1 for probe req, 2 for probe response */ + UINT_16 u2WSCIELen[3]; + + UINT_8 aucP2PIE[MAX_P2P_IE_SIZE][400]; + UINT_16 u2P2PIELen[MAX_P2P_IE_SIZE]; + +#if CFG_SUPPORT_WFD + UINT_8 aucWFDIE[400]; + UINT_16 u2WFDIELen; + 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[OID_SET_GET_STRUCT_LENGTH]; + +#if 1 /* CFG_SUPPORT_ANTI_PIRACY */ + UINT_8 aucSecCheck[256]; + UINT_8 aucSecCheckRsp[256]; +#endif + + /* + * Hotspot Client Management + */ + /* TODO: It is better to maintain the black MAC address with a linked list. */ + PARAM_MAC_ADDRESS aucBlackMACList[10]; + UINT_8 ucMaxClients; + +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION + UINT_32 u4PsLevel; +#endif +}; + +#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; + +/* Hotspot Management set config */ +struct NL80211_DRIVER_HOTSPOT_CONFIG_PARAMS { + NL80211_DRIVER_TEST_PARAMS hdr; + UINT_32 idx; + UINT_32 value; +}; + +#if CFG_SUPPORT_WFD +typedef struct _NL80211_DRIVER_WFD_PARAMS { + NL80211_DRIVER_TEST_PARAMS hdr; + UINT_32 WfdCmdType; + UINT_8 WfdEnable; + UINT_8 WfdCoupleSinkStatus; + UINT_8 WfdSessionAvailable; + UINT_8 WfdSigmaMode; + UINT_16 WfdDevInfo; + UINT_16 WfdControlPort; + UINT_16 WfdMaximumTp; + UINT_16 WfdExtendCap; + UINT_8 WfdCoupleSinkAddress[MAC_ADDR_LEN]; + UINT_8 WfdAssociatedBssid[MAC_ADDR_LEN]; + UINT_8 WfdVideoIp[4]; + UINT_8 WfdAudioIp[4]; + UINT_16 WfdVideoPort; + UINT_16 WfdAudioPort; + UINT_32 WfdFlag; + UINT_32 WfdPolicy; + UINT_32 WfdState; + UINT_8 WfdSessionInformationIE[24 * 8]; /* Include Subelement ID, length */ + UINT_16 WfdSessionInformationIELen; + UINT_8 aucReserved1[2]; + UINT_8 aucWfdPrimarySinkMac[MAC_ADDR_LEN]; + UINT_8 aucWfdSecondarySinkMac[MAC_ADDR_LEN]; + UINT_32 WfdAdvanceFlag; + /* Group 1 64 bytes */ + UINT_8 aucWfdLocalIp[4]; + UINT_16 WfdLifetimeAc2; /* Unit is 2 TU */ + UINT_16 WfdLifetimeAc3; /* Unit is 2 TU */ + UINT_16 WfdCounterThreshold; /* Unit is ms */ + UINT_8 aucReserved2[54]; + /* Group 3 64 bytes */ + UINT_8 aucReserved3[64]; + /* Group 3 64 bytes */ + UINT_8 aucReserved4[64]; +} NL80211_DRIVER_WFD_PARAMS, *P_NL80211_DRIVER_WFD_PARAMS; +#endif +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +BOOLEAN p2pLaunch(P_GLUE_INFO_T prGlueInfo); + +BOOLEAN p2pRemove(P_GLUE_INFO_T prGlueInfo); + +VOID p2pSetMode(IN BOOLEAN fgIsAPMode); + +BOOLEAN glRegisterP2P(P_GLUE_INFO_T prGlueInfo, const char *prDevName, BOOLEAN fgIsApMode); + +VOID p2pEalySuspendReg(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgIsEnable); + +BOOLEAN glUnregisterP2P(P_GLUE_INFO_T prGlueInfo); + +BOOLEAN p2pNetRegister(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgIsRtnlLockAcquired); + +BOOLEAN p2pNetUnregister(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgIsRtnlLockAcquired); + +BOOLEAN p2pStopImmediate(P_GLUE_INFO_T prGlueInfo); + +BOOLEAN p2PFreeInfo(P_GLUE_INFO_T prGlueInfo); + +BOOLEAN glP2pCreateWirelessDevice(P_GLUE_INFO_T prGlueInfo); + + +VOID glP2pDestroyWirelessDevice(VOID); + +VOID p2pSetMulticastListWorkQueueWrapper(P_GLUE_INFO_T prGlueInfo); + + +int p2pHardStartXmit(IN struct sk_buff *prSkb, IN struct net_device *prDev); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_rst.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_rst.h new file mode 100644 index 0000000000000..c0adaff8dcfdb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_rst.h @@ -0,0 +1,111 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _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" + +#if (KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE) +typedef unsigned int CMB_STUB_AIF_X; +typedef unsigned int CMB_STUB_AIF_CTRL; +#endif + +#include "wmt_exp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define RST_FLAG_CHIP_RESET 0 +#define RST_FLAG_DO_CORE_DUMP BIT(0) +#define RST_FLAG_PREVENT_POWER_OFF BIT(1) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef enum _ENUM_RESET_STATUS_T { + RESET_FAIL, + RESET_SUCCESS +} ENUM_RESET_STATUS_T; + +typedef struct _RESET_STRUCT_T { + ENUM_RESET_STATUS_T rst_data; + struct work_struct rst_work; + struct work_struct rst_trigger_work; + UINT_32 rst_trigger_flag; +} RESET_STRUCT_T; +/******************************************************************************* +* E X T E R N A L F U N C T I O N S +******************************************************************************** +*/ +#if CFG_CHIP_RESET_SUPPORT +extern int wifi_reset_start(void); +extern int wifi_reset_end(ENUM_RESET_STATUS_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 +******************************************************************************** +*/ +#if CFG_CHIP_RESET_SUPPORT +#define GL_RESET_TRIGGER(_prAdapter, _u4Flags) \ + glResetTrigger(_prAdapter, (_u4Flags), (const PUINT_8)__FILE__, __LINE__) +#else + DBGLOG(INIT, INFO, "DO NOT support chip reset\n") +#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 +******************************************************************************** +*/ + +VOID glResetInit(VOID); + +VOID glResetUninit(VOID); + +VOID glSendResetRequest(VOID); + +BOOLEAN kalIsResetting(VOID); + +BOOLEAN glIsWmtCodeDump(VOID); + +BOOLEAN glResetTrigger(P_ADAPTER_T prAdapter, UINT_32 u4RstFlag, const PUINT_8 pucFile, UINT_32 u4Line); + +#endif /* _GL_RST_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_sec.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_sec.h new file mode 100644 index 0000000000000..541811b3c1413 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_sec.h @@ -0,0 +1,24 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _GL_SEC_H +#define _GL_SEC_H + +extern void handle_sec_msg_1(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_2(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_3(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_4(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_5(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_final(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); + +#endif /* _GL_SEC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_typedef.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_typedef.h new file mode 100644 index 0000000000000..d6d6d79d06bf6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_typedef.h @@ -0,0 +1,227 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _GL_TYPEDEF_H +#define _GL_TYPEDEF_H +#include "linux/version.h" +#include "osal_typedef.h" + +#if (KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE) +#define IEEE80211_BAND_2GHZ NL80211_BAND_2GHZ +#define IEEE80211_BAND_5GHZ NL80211_BAND_5GHZ +#define IEEE80211_BAND_60GHZ NL80211_BAND_60GHZ +#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 ((BOOLEAN) 0) +#define TRUE ((BOOLEAN) 1) +#endif /* FALSE */ + +#ifndef NULL +#if defined(__cplusplus) +#define NULL 0 +#else +#define NULL ((void *) 0) +#endif +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Type definition for void */ +/*mach/mt_typedefs.h define _TYPEDEFS_H, to avoid compile error*/ +/* Type definition for Boolean */ +typedef unsigned char BOOLEAN, *PBOOLEAN; + +/* Type definition for signed integers */ +typedef signed char CHAR, *PCHAR, **PPCHAR; +typedef signed char INT_8, *PINT_8, **PPINT_8; +typedef signed short INT_16, *PINT_16, **PPINT_16; +typedef signed int INT_32, *PINT_32, **PPINT_32; +typedef signed long long INT_64, *PINT_64, **PPINT_64; + +/* Type definition for unsigned integers */ +typedef unsigned char UCHAR, *PUCHAR, **PPUCHAR; +typedef unsigned char UINT_8, *PUINT_8, **PPUINT_8, *P_UINT_8; +typedef unsigned short UINT_16, *PUINT_16, **PPUINT_16; +typedef unsigned int UINT_32, *PUINT_32, **PPUINT_32; +typedef unsigned long long UINT_64, *PUINT_64, **PPUINT_64; + +typedef unsigned int 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. + * : 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_ATTRIB_PACKED__ __attribute__((__packed__)) +#define __KAL_ATTRIB_ALIGN_4__ __aligned(4) + +#ifndef BIT +#define BIT(n) ((UINT_32) 1U << (n)) +#endif /* BIT */ + +#ifndef BITS +/* bits range: for example BITS(16,23) = 0xFF0000 + * ==> (BIT(m)-1) = 0x0000FFFF ~(BIT(m)-1) => 0xFFFF0000 + * ==> (BIT(n+1)-1) = 0x00FFFFFF + */ +#define BITS(m, n) (~(BIT(m)-1) & ((BIT(n) - 1) | BIT(n))) +#endif /* BIT */ + +/* + * This macro returns the byte offset of a named field in a known structure + * type. + * _type - structure name, + * _field - field name of the structure + */ +#ifndef OFFSET_OF +#define OFFSET_OF(_type, _field) ((ULONG)&(((_type *)0)->_field)) +#endif /* OFFSET_OF */ + +/* This macro returns the base address of an instance of a structure + * given the type of the structure and the address of a field within the + * containing structure. + * _addrOfField - address of current field of the structure, + * _type - structure name, + * _field - field name of the structure + */ +#ifndef ENTRY_OF +#define ENTRY_OF(_addrOfField, _type, _field) \ + ((_type *)((PINT_8)(_addrOfField) - (PINT_8)OFFSET_OF(_type, _field))) +#endif /* ENTRY_OF */ + +/* This macro align the input value to the DW boundary. + * _value - value need to check + */ +#ifndef ALIGN_4 +#define ALIGN_4(_value) (((_value) + 3) & ~3u) +#endif /* ALIGN_4 */ + +/* This macro check the DW alignment of the input value. + * _value - value of address need to check + */ +#ifndef IS_ALIGN_4 +#define IS_ALIGN_4(_value) (((_value) & 0x3) ? FALSE : TRUE) +#endif /* IS_ALIGN_4 */ + +#ifndef IS_NOT_ALIGN_4 +#define IS_NOT_ALIGN_4(_value) (((_value) & 0x3) ? TRUE : FALSE) +#endif /* IS_NOT_ALIGN_4 */ + +/* This macro evaluate the input length in unit of Double Word(4 Bytes). + * _value - value in unit of Byte, output will round up to DW boundary. + */ +#ifndef BYTE_TO_DWORD +#define BYTE_TO_DWORD(_value) ((_value + 3) >> 2) +#endif /* BYTE_TO_DWORD */ + +/* This macro evaluate the input length in unit of Byte. + * _value - value in unit of DW, output is in unit of Byte. + */ +#ifndef DWORD_TO_BYTE +#define DWORD_TO_BYTE(_value) ((_value) << 2) +#endif /* DWORD_TO_BYTE */ + +#if 1 /* Little-Endian */ +#define CONST_NTOHS(_x) ntohs(_x) + +#define CONST_HTONS(_x) htons(_x) + +#define NTOHS(_x) ntohs(_x) + +#define HTONS(_x) htons(_x) + +#define NTOHL(_x) ntohl(_x) + +#define HTONL(_x) htonl(_x) + +#else /* Big-Endian */ + +#define CONST_NTOHS(_x) + +#define CONST_HTONS(_x) + +#define NTOHS(_x) + +#define HTONS(_x) + +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _GL_TYPEDEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_vendor.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_vendor.h new file mode 100644 index 0000000000000..5ec980eed400c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_vendor.h @@ -0,0 +1,878 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _GL_VENDOR_H +#define _GL_VENDOR_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#include +#include +#include +#include + +#include "gl_os.h" + +#include "wlan_lib.h" +#include "gl_wext.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define GOOGLE_OUI 0x001A11 +#define OUI_QCA 0x001374 + +#define QCA_NL80211_VENDOR_SUBCMD_ROAMING 9 +#define QCA_NL80211_VENDOR_SUBCMD_SETBAND 105 +#define NL80211_VENDOR_SUBCMD_ACS 54 +#define NL80211_VENDOR_SUBCMD_GET_FEATURES 55 + +#define WIFI_VENDOR_ATTR_FEATURE_FLAGS 7 + + +typedef enum { + /* Don't use 0 as a valid subcommand */ + ANDROID_NL80211_SUBCMD_UNSPECIFIED, + + /* Define all vendor startup commands between 0x0 and 0x0FFF */ + ANDROID_NL80211_SUBCMD_WIFI_RANGE_START = 0x0001, + ANDROID_NL80211_SUBCMD_WIFI_RANGE_END = 0x0FFF, + + /* Define all GScan related commands between 0x1000 and 0x10FF */ + ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START = 0x1000, + ANDROID_NL80211_SUBCMD_GSCAN_RANGE_END = 0x10FF, + + /* Define all RTT related commands between 0x1100 and 0x11FF */ + ANDROID_NL80211_SUBCMD_RTT_RANGE_START = 0x1100, + ANDROID_NL80211_SUBCMD_RTT_RANGE_END = 0x11FF, + + ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START = 0x1200, + ANDROID_NL80211_SUBCMD_LSTATS_RANGE_END = 0x12FF, + + /* Define all Logger related commands between 0x1400 and 0x14FF */ + ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START = 0x1400, + ANDROID_NL80211_SUBCMD_DEBUG_RANGE_END = 0x14FF, + + /* Define all wifi offload related commands between 0x1600 and 0x16FF */ + ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START = 0x1600, + ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_END = 0x16FF, + + /* This is reserved for future usage */ + +} ANDROID_VENDOR_SUB_COMMAND; + +typedef enum { + WIFI_SUBCMD_GET_CHANNEL_LIST = ANDROID_NL80211_SUBCMD_WIFI_RANGE_START, + + WIFI_SUBCMD_GET_FEATURE_SET, /* 0x0002 */ + WIFI_SUBCMD_GET_FEATURE_SET_MATRIX, /* 0x0003 */ + WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI, /* 0x0004 */ + WIFI_SUBCMD_NODFS_SET, /* 0x0005 */ + WIFI_SUBCMD_SET_COUNTRY_CODE, /* 0x0006 */ + WIFI_SUBCMD_SET_RSSI_MONITOR, /* 0x0007 */ + + /* Add more sub commands here */ + WIFI_SUBCMD_GET_ROAMING_CAPABILITIES, /* 0x0008 */ + /* skip 0x0009 for diver set_roaming_policy */ + WIFI_SUBCMD_CONFIG_ROAMING = 0x000a, /* 0x000a */ + WIFI_SUBCMD_ENABLE_ROAMING, /* 0x000b */ + + WIFI_SUBCMD_SELECT_TX_POWER_SCENARIO, /* 0x000c */ + +} WIFI_SUB_COMMAND; + +typedef enum { + GSCAN_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START, + + GSCAN_SUBCMD_SET_CONFIG, /* 0x1001 */ + GSCAN_SUBCMD_SET_SCAN_CONFIG, /* 0x1002 */ + GSCAN_SUBCMD_ENABLE_GSCAN, /* 0x1003 */ + GSCAN_SUBCMD_GET_SCAN_RESULTS, /* 0x1004 */ + GSCAN_SUBCMD_SCAN_RESULTS, /* 0x1005 */ + + GSCAN_SUBCMD_SET_HOTLIST, /* 0x1006 */ + + GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG, /* 0x1007 */ + GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, /* 0x1008 */ + /* Add more sub commands here */ + +} GSCAN_SUB_COMMAND; + +typedef enum { + RTT_SUBCMD_SET_CONFIG = ANDROID_NL80211_SUBCMD_RTT_RANGE_START, + RTT_SUBCMD_CANCEL_CONFIG, + RTT_SUBCMD_GETCAPABILITY, +} RTT_SUB_COMMAND; + +typedef enum { + LSTATS_SUBCMD_GET_INFO = ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START, +} LSTATS_SUB_COMMAND; + +/* moved from wifi_logger.cpp */ +enum DEBUG_SUB_COMMAND { + LOGGER_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START, + LOGGER_GET_VER +}; + +typedef enum { + WIFI_OFFLOAD_START_MKEEP_ALIVE = ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START, + WIFI_OFFLOAD_STOP_MKEEP_ALIVE, +} WIFI_OFFLOAD_SUB_COMMAND; + +typedef enum { + GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS, + GSCAN_EVENT_HOTLIST_RESULTS_FOUND, + GSCAN_EVENT_SCAN_RESULTS_AVAILABLE, + GSCAN_EVENT_FULL_SCAN_RESULTS, + RTT_EVENT_COMPLETE, + GSCAN_EVENT_COMPLETE_SCAN, + GSCAN_EVENT_HOTLIST_RESULTS_LOST, + WIFI_EVENT_RSSI_MONITOR +} WIFI_VENDOR_EVENT; + +enum WIFI_P2P_VENDOR_EVENT { + WIFI_EVENT_ACS, +}; + +typedef enum { + WIFI_ATTRIBUTE_BAND = 1, + WIFI_ATTRIBUTE_NUM_CHANNELS, + WIFI_ATTRIBUTE_CHANNEL_LIST, + + WIFI_ATTRIBUTE_NUM_FEATURE_SET, + WIFI_ATTRIBUTE_FEATURE_SET, + WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, + WIFI_ATTRIBUTE_NODFS_VALUE, + WIFI_ATTRIBUTE_COUNTRY_CODE, + + WIFI_ATTRIBUTE_MAX_RSSI, + WIFI_ATTRIBUTE_MIN_RSSI, + WIFI_ATTRIBUTE_RSSI_MONITOR_START, + + WIFI_ATTRIBUTE_ROAMING_CAPABILITIES, + WIFI_ATTRIBUTE_ROAMING_BLACKLIST_NUM, + WIFI_ATTRIBUTE_ROAMING_BLACKLIST_BSSID, + WIFI_ATTRIBUTE_ROAMING_WHITELIST_NUM, + WIFI_ATTRIBUTE_ROAMING_WHITELIST_SSID, + WIFI_ATTRIBUTE_ROAMING_STATE, + + WIFI_ATTRIBUTE_TX_POWER_SCENARIO, + +} WIFI_ATTRIBUTE; + +/* moved from wifi_logger.cpp */ +enum LOGGER_ATTRIBUTE { + LOGGER_ATTRIBUTE_DRIVER_VER, + LOGGER_ATTRIBUTE_FW_VER +}; + +typedef enum { + GSCAN_ATTRIBUTE_CAPABILITIES = 1, + + GSCAN_ATTRIBUTE_NUM_BUCKETS = 10, + GSCAN_ATTRIBUTE_BASE_PERIOD, + GSCAN_ATTRIBUTE_BUCKETS_BAND, + GSCAN_ATTRIBUTE_BUCKET_ID, + GSCAN_ATTRIBUTE_BUCKET_PERIOD, + GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS, + GSCAN_ATTRIBUTE_BUCKET_CHANNELS, + GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, + GSCAN_ATTRIBUTE_REPORT_THRESHOLD, + GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, + + GSCAN_ATTRIBUTE_ENABLE_FEATURE = 20, + GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, /* indicates no more results */ + GSCAN_ATTRIBUTE_FLUSH_FEATURE, /* Flush all the configs */ + GSCAN_ENABLE_FULL_SCAN_RESULTS, + GSCAN_ATTRIBUTE_REPORT_EVENTS, + /* Adaptive scan attributes */ + GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT, + GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD, + + GSCAN_ATTRIBUTE_NUM_OF_RESULTS = 30, + GSCAN_ATTRIBUTE_FLUSH_RESULTS, + GSCAN_ATTRIBUTE_SCAN_RESULTS, /* flat array of wifi_scan_result */ + GSCAN_ATTRIBUTE_SCAN_ID, /* indicates scan number */ + GSCAN_ATTRIBUTE_SCAN_FLAGS, /* indicates if scan was aborted */ + GSCAN_ATTRIBUTE_AP_FLAGS, /* flags on significant change event */ + GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK, + + GSCAN_ATTRIBUTE_SSID = 40, + GSCAN_ATTRIBUTE_BSSID, + GSCAN_ATTRIBUTE_CHANNEL, + GSCAN_ATTRIBUTE_RSSI, + GSCAN_ATTRIBUTE_TIMESTAMP, + GSCAN_ATTRIBUTE_RTT, + GSCAN_ATTRIBUTE_RTTSD, + + GSCAN_ATTRIBUTE_HOTLIST_BSSIDS = 50, + GSCAN_ATTRIBUTE_RSSI_LOW, + GSCAN_ATTRIBUTE_RSSI_HIGH, + GSCAN_ATTRIBUTE_HOTLIST_ELEM, + GSCAN_ATTRIBUTE_HOTLIST_FLUSH, + + GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE = 60, + GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, + GSCAN_ATTRIBUTE_MIN_BREACHING, + GSCAN_ATTRIBUTE_NUM_AP, + GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS, + GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + +} GSCAN_ATTRIBUTE; + +typedef enum { + RTT_ATTRIBUTE_CAPABILITIES = 1, + + RTT_ATTRIBUTE_TARGET_CNT = 10, + RTT_ATTRIBUTE_TARGET_INFO, + RTT_ATTRIBUTE_TARGET_MAC, + RTT_ATTRIBUTE_TARGET_TYPE, + RTT_ATTRIBUTE_TARGET_PEER, + RTT_ATTRIBUTE_TARGET_CHAN, + RTT_ATTRIBUTE_TARGET_PERIOD, + RTT_ATTRIBUTE_TARGET_NUM_BURST, + RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST, + RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM, + RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR, + RTT_ATTRIBUTE_TARGET_LCI, + RTT_ATTRIBUTE_TARGET_LCR, + RTT_ATTRIBUTE_TARGET_BURST_DURATION, + RTT_ATTRIBUTE_TARGET_PREAMBLE, + RTT_ATTRIBUTE_TARGET_BW, + RTT_ATTRIBUTE_RESULTS_COMPLETE = 30, + RTT_ATTRIBUTE_RESULTS_PER_TARGET, + RTT_ATTRIBUTE_RESULT_CNT, + RTT_ATTRIBUTE_RESULT +} RTT_ATTRIBUTE; + +typedef enum { + LSTATS_ATTRIBUTE_STATS = 2, +} LSTATS_ATTRIBUTE; + +typedef enum { + MKEEP_ALIVE_ATTRIBUTE_ID = 1, + MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN, + MKEEP_ALIVE_ATTRIBUTE_IP_PKT, + MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR, + MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR, + MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC +} WIFI_MKEEP_ALIVE_ATTRIBUTE; + +typedef enum { + WIFI_BAND_UNSPECIFIED, + WIFI_BAND_BG = 1, /* 2.4 GHz */ + WIFI_BAND_A = 2, /* 5 GHz without DFS */ + WIFI_BAND_A_DFS = 4, /* 5 GHz DFS only */ + WIFI_BAND_A_WITH_DFS = 6, /* 5 GHz with DFS */ + WIFI_BAND_ABG = 3, /* 2.4 GHz + 5 GHz; no DFS */ + WIFI_BAND_ABG_WITH_DFS = 7, /* 2.4 GHz + 5 GHz with DFS */ +} WIFI_BAND; + +typedef enum { + WIFI_SCAN_RESULTS_AVAILABLE, /* reported when REPORT_EVENTS_EACH_SCAN is set and a scan + * completes. WIFI_SCAN_THRESHOLD_NUM_SCANS or + * WIFI_SCAN_THRESHOLD_PERCENT can be reported instead if the + * reason for the event is available; however, at most one of + * these events should be reported per scan. If there are + * multiple buckets that were scanned this period and one has the + * EACH_SCAN flag set then this event should be preferred. + */ + WIFI_SCAN_THRESHOLD_NUM_SCANS, /* can be reported when REPORT_EVENTS_EACH_SCAN is not set and + * report_threshold_num_scans is reached. + */ + WIFI_SCAN_THRESHOLD_PERCENT, /* can be reported when REPORT_EVENTS_EACH_SCAN is not set and + * report_threshold_percent is reached. + */ + WIFI_SCAN_FAILED /* reported when currently executing gscans have failed. + * start_gscan will need to be called again in order to continue + * scanning. This is intended to indicate abnormal scan + * terminations (not those as a result of stop_gscan). + */ +} WIFI_SCAN_EVENT; + +/* QCA Vender CMD */ +typedef enum { + QCA_SETBAND_AUTO, + QCA_SETBAND_5G, + QCA_SETBAND_2G, +} QCA_SET_BAND; + +#define REPORT_EVENTS_EACH_SCAN (1 << 0) +#define REPORT_EVENTS_FULL_RESULTS (1 << 1) +#define REPORT_EVENTS_NO_BATCH (1 << 2) + +#define GSCAN_MAX_REPORT_THRESHOLD 1024000 +#define GSCAN_MAX_CHANNELS 8 +#define GSCAN_MAX_BUCKETS 8 +#define MAX_HOTLIST_BSSIDS 16 +#define MAX_HOTLIST_SSIDS 16 +#define MAX_SIGNIFICANT_CHANGE_APS 16 +#define PSCAN_MAX_SCAN_CACHE_SIZE 16 +#define PSCAN_MAX_AP_CACHE_PER_SCAN 16 +#define PSCAN_VERSION 1 + +#define MAX_BUFFERED_GSCN_RESULTS 5 + +#define MAX_FW_ROAMING_BLACKLIST_SIZE 16 +#define MAX_FW_ROAMING_WHITELIST_SIZE 8 + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +#define NLA_PARSE_NESTED(nlattr, maxtype, nla, policy) \ + nla_parse_nested(nlattr, maxtype, nla, policy, NULL) +#define NLA_PARSE(tb, maxtype, head, len, policy) \ + nla_parse(tb, maxtype, head, len, policy, NULL) +#else +#define NLA_PARSE_NESTED(nlattr, maxtype, nla, policy) \ + nla_parse_nested(nlattr, maxtype, nla, policy) +#define NLA_PARSE(tb, maxtype, head, len, policy) \ + nla_parse(tb, maxtype, head, len, policy) +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef UINT_64 wifi_timestamp; /* In microseconds (us) */ +typedef UINT_64 wifi_timespan; /* In nanoseconds (ns) */ + +typedef UINT_8 mac_addr[6]; +typedef UINT_32 wifi_channel; /* Indicates channel frequency in MHz */ +typedef INT_32 wifi_rssi; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +typedef struct _PARAM_WIFI_GSCAN_GET_RESULT_PARAMS { + UINT_32 get_num; + UINT_8 flush; +} PARAM_WIFI_GSCAN_GET_RESULT_PARAMS, *P_PARAM_WIFI_GSCAN_GET_RESULT_PARAMS; + +typedef struct _PARAM_WIFI_GSCAN_ACTION_CMD_PARAMS { + UINT_8 ucPscanAct; + UINT_8 aucReserved[3]; +} PARAM_WIFI_GSCAN_ACTION_CMD_PARAMS, *P_PARAM_WIFI_GSCAN_ACTION_CMD_PARAMS; + +typedef struct _PARAM_WIFI_GSCAN_CAPABILITIES_STRUCT_T { + UINT_32 max_scan_cache_size; /* total space allocated for scan (in bytes) */ + UINT_32 max_scan_buckets; /* maximum number of channel buckets */ + UINT_32 max_ap_cache_per_scan; /* maximum number of APs that can be stored per scan */ + UINT_32 max_rssi_sample_size; /* number of RSSI samples used for averaging RSSI */ + UINT_32 max_scan_reporting_threshold; /* max possible report_threshold as described */ + /* in wifi_scan_cmd_params */ + UINT_32 max_hotlist_bssids; /* maximum number of entries for hotlist BSSIDs */ + UINT_32 max_hotlist_ssids; /* maximum number of entries for hotlist SSIDs */ + UINT_32 max_significant_wifi_change_aps; /* maximum number of entries for */ + /* significant wifi change APs */ + UINT_32 max_bssid_history_entries; /* number of BSSID/RSSI entries that device can hold */ + UINT_32 max_number_epno_networks; /* max number of epno entries */ + UINT_32 max_number_epno_networks_by_ssid; /* max number of epno entries if ssid is specified */ + UINT_32 max_number_of_white_listed_ssid; /* max number of white listed SSIDs, M target is 2 to 4 */ +} PARAM_WIFI_GSCAN_CAPABILITIES_STRUCT_T, *P_PARAM_WIFI_GSCAN_CAPABILITIES_STRUCT_T; + +typedef struct _PARAM_WIFI_GSCAN_CHANNEL_SPEC { + UINT_32 channel; /* frequency */ + UINT_32 dwellTimeMs; /* dwell time hint */ + UINT_32 passive; /* 0 => active, 1 => passive scan; ignored for DFS */ + /* Add channel class */ +} PARAM_WIFI_GSCAN_CHANNEL_SPEC, *P_PARAM_WIFI_GSCAN_CHANNEL_SPEC; + +typedef struct _PARAM_WIFI_GSCAN_BUCKET_SPEC { + UINT_32 bucket; /* bucket index, 0 based */ + WIFI_BAND band; /* when UNSPECIFIED, use channel list */ + UINT_32 period; /* desired period, in millisecond; if this is too */ + /* low, the firmware should choose to generate results as */ + /* fast as it can instead of failing the command */ + /* report_events semantics - + * This is a bit field; which defines following bits - + * REPORT_EVENTS_EACH_SCAN => report a scan completion event after scan. If this is not set + * then scan completion events should be reported if + * report_threshold_percent or report_threshold_num_scans is + * reached. + * REPORT_EVENTS_FULL_RESULTS => forward scan results (beacons/probe responses + IEs) + * in real time to HAL, in addition to completion events + * Note: To keep backward compatibility, fire completion + * events regardless of REPORT_EVENTS_EACH_SCAN. + * REPORT_EVENTS_NO_BATCH => controls if scans for this bucket should be placed in the + * history buffer + */ + UINT_8 report_events; + UINT_32 max_period; /* if max_period is non zero or different than period, then this bucket is + * an exponential backoff bucket and the scan period will grow exponentially + * as per formula: actual_period(N) = period * (base ^ (N/step_count)) + * to a maximum period of max_period + */ + UINT_32 step_count; /* for exponential back off bucket, number of scans to perform for a given period */ + + UINT_32 num_channels; + /* channels to scan; these may include DFS channels + * Note that a given channel may appear in multiple buckets + */ + PARAM_WIFI_GSCAN_CHANNEL_SPEC channels[GSCAN_MAX_CHANNELS]; +} PARAM_WIFI_GSCAN_BUCKET_SPEC, *P_PARAM_WIFI_GSCAN_BUCKET_SPEC; + +typedef struct _PARAM_WIFI_GSCAN_CMD_PARAMS { + UINT_32 base_period; /* base timer period in ms */ + UINT_32 max_ap_per_scan; /* number of APs to store in each scan in the */ + /* BSSID/RSSI history buffer (keep the highest RSSI APs) */ + UINT_32 report_threshold_percent; /* in %, when scan buffer is this much full, wake up AP */ + UINT_32 report_threshold_num_scans; + UINT_32 num_buckets; + PARAM_WIFI_GSCAN_BUCKET_SPEC buckets[GSCAN_MAX_BUCKETS]; +} PARAM_WIFI_GSCAN_CMD_PARAMS, *P_PARAM_WIFI_GSCAN_CMD_PARAMS; + +typedef struct _PARAM_WIFI_GSCAN_RESULT { + wifi_timestamp ts; /* time since boot (in microsecond) when the result was */ + /* retrieved */ + UINT_8 ssid[32 + 1]; /* null terminated */ + mac_addr bssid; + wifi_channel channel; /* channel frequency in MHz */ + wifi_rssi rssi; /* in db */ + wifi_timespan rtt; /* in nanoseconds */ + wifi_timespan rtt_sd; /* standard deviation in rtt */ + UINT_16 beacon_period; /* period advertised in the beacon */ + UINT_16 capability; /* capabilities advertised in the beacon */ + UINT_32 ie_length; /* size of the ie_data blob */ + UINT_8 ie_data[1]; /* blob of all the information elements found in the */ + /* beacon; this data should be a packed list of */ + /* wifi_information_element objects, one after the other. */ + /* other fields */ +} PARAM_WIFI_GSCAN_RESULT, *P_PARAM_WIFI_GSCAN_RESULT; + +typedef struct _PARAM_WIFI_GSCAN_RESULT_REPORT { + UINT_32 u4ScanId; + UINT_8 ucScanFlag; + UINT_8 ucReserved[3]; + UINT_32 u4BucketMask; + UINT_32 u4NumOfResults; + PARAM_WIFI_GSCAN_RESULT rResult[1]; +} PARAM_WIFI_GSCAN_RESULT_REPORT, *P_PARAM_WIFI_GSCAN_RESULT_REPORT; + +typedef struct _PARAM_WIFI_GSCAN_FULL_RESULT { + PARAM_WIFI_GSCAN_RESULT fixed; + UINT_32 u4BucketMask; /* scan chbucket bitmask */ + UINT_32 ie_length; /* byte length of Information Elements */ + UINT_8 ie_data[1]; /* IE data to follow */ +} PARAM_WIFI_GSCAN_FULL_RESULT, *P_PARAM_WIFI_GSCAN_FULL_RESULT; + +/* Significant wifi change*/ +/* + * typedef struct _PARAM_WIFI_CHANGE_RESULT{ + * mac_addr bssid; // BSSID + * wifi_channel channel; // channel frequency in MHz + * UINT_32 num_rssi; // number of rssi samples + * wifi_rssi rssi[8]; // RSSI history in db + * } PARAM_WIFI_CHANGE_RESULT, *P_PARAM_WIFI_CHANGE_RESULT; + */ + +typedef struct _PARAM_WIFI_CHANGE_RESULT { + UINT_16 flags; + UINT_16 channel; + mac_addr bssid; /* BSSID */ + INT_8 rssi[8]; /* RSSI history in db */ +} PARAM_WIFI_CHANGE_RESULT, *P_PARAM_WIFI_CHANGE_RESULT; + +typedef struct _PARAM_AP_THRESHOLD { + mac_addr bssid; /* AP BSSID */ + wifi_rssi low; /* low threshold */ + wifi_rssi high; /* high threshold */ + wifi_channel channel; /* channel hint */ +} PARAM_AP_THRESHOLD, *P_PARAM_AP_THRESHOLD; + +typedef struct _PARAM_WIFI_BSSID_HOTLIST { + UINT_32 lost_ap_sample_size; + UINT_32 num_ap; /* number of hotlist APs */ + PARAM_AP_THRESHOLD ap[MAX_HOTLIST_BSSIDS]; /* hotlist APs */ +} PARAM_WIFI_BSSID_HOTLIST, *P_PARAM_WIFI_BSSID_HOTLIST; + +typedef struct _PARAM_WIFI_SIGNIFICANT_CHANGE { + UINT_16 rssi_sample_size; /* number of samples for averaging RSSI */ + UINT_16 lost_ap_sample_size; /* number of samples to confirm AP loss */ + UINT_16 min_breaching; /* number of APs breaching threshold */ + UINT_16 num_ap; /* max 64 */ + PARAM_AP_THRESHOLD ap[MAX_SIGNIFICANT_CHANGE_APS]; +} PARAM_WIFI_SIGNIFICANT_CHANGE, *P_PARAM_WIFI_SIGNIFICANT_CHANGE; + +/* RTT Capabilities */ +typedef struct _PARAM_WIFI_RTT_CAPABILITIES { + UINT_8 rtt_one_sided_supported; /* if 1-sided rtt data collection is supported */ + UINT_8 rtt_ftm_supported; /* if ftm rtt data collection is supported */ + UINT_8 lci_support; /* if initiator supports LCI request. Applies to 2-sided RTT */ + UINT_8 lcr_support; /* if initiator supports LCR request. Applies to 2-sided RTT */ + UINT_8 preamble_support; /* bit mask indicates what preamble is supported by initiator */ + UINT_8 bw_support; /* bit mask indicates what BW is supported by initiator */ +} PARAM_WIFI_RTT_CAPABILITIES, *P_PARAM_WIFI_RTT_CAPABILITIES; + +/* channel operating width */ +typedef enum { + WIFI_CHAN_WIDTH_20 = 0, + WIFI_CHAN_WIDTH_40 = 1, + WIFI_CHAN_WIDTH_80 = 2, + WIFI_CHAN_WIDTH_160 = 3, + WIFI_CHAN_WIDTH_80P80 = 4, + WIFI_CHAN_WIDTH_5 = 5, + WIFI_CHAN_WIDTH_10 = 6, + WIFI_CHAN_WIDTH_INVALID = -1 +} WIFI_CHANNEL_WIDTH; + +/* channel information */ +typedef struct { + WIFI_CHANNEL_WIDTH width; /* channel width (20, 40, 80, 80+80, 160) */ + UINT_32 center_freq; /* primary 20 MHz channel */ + UINT_32 center_freq0; /* center frequency (MHz) first segment */ + UINT_32 center_freq1; /* center frequency (MHz) second segment */ +} WIFI_CHANNEL_INFO; + +/* channel statistics */ +typedef struct { + WIFI_CHANNEL_INFO channel; /* channel */ + UINT_32 on_time; /* msecs the radio is awake (32 bits number accruing over time) */ + UINT_32 cca_busy_time; /* msecs the CCA register is busy (32 bits number accruing over time) */ +} WIFI_CHANNEL_STAT; + +/* radio statistics */ +typedef struct { + UINT_32 radio; /* wifi radio (if multiple radio supported) */ + UINT_32 on_time; /* msecs the radio is awake (32 bits number accruing over time) */ + UINT_32 tx_time; /* msecs the radio is transmitting (32 bits number accruing over time) */ + UINT_32 rx_time; /* msecs the radio is in active receive (32 bits number accruing over time) */ + UINT_32 on_time_scan; /* msecs the radio is awake due to all scan (32 bits number accruing over time) */ + UINT_32 on_time_nbd; /* msecs the radio is awake due to NAN (32 bits number accruing over time) */ + UINT_32 on_time_gscan; /* msecs the radio is awake due to G?scan (32 bits number accruing over time) */ + UINT_32 on_time_roam_scan; /* + * msecs the radio is awake due to roam?scan + * (32 bits number accruing over time) + */ + UINT_32 on_time_pno_scan; /* + * msecs the radio is awake due to PNO scan + * (32 bits number accruing over time) + */ + UINT_32 on_time_hs20; /* + * msecs the radio is awake due to HS2.0 scans and GAS exchange + * 32 bits number accruing over time) + */ + UINT_32 num_channels; /* number of channels */ + WIFI_CHANNEL_STAT channels[]; /* channel statistics */ +} WIFI_RADIO_STAT; + +/* wifi rate */ +typedef struct { + UINT_32 preamble:3; /* 0: OFDM, 1:CCK, 2:HT 3:VHT 4..7 reserved */ + UINT_32 nss:2; /* 0:1x1, 1:2x2, 3:3x3, 4:4x4 */ + UINT_32 bw:3; /* 0:20MHz, 1:40Mhz, 2:80Mhz, 3:160Mhz */ + UINT_32 rateMcsIdx:8; /* OFDM/CCK rate code would be as per ieee std in the units of 0.5mbps */ + /* HT/VHT it would be mcs index */ + UINT_32 reserved:16; /* reserved */ + UINT_32 bitrate; /* units of 100 Kbps */ +} WIFI_RATE; + +/* per rate statistics */ +typedef struct { + WIFI_RATE rate; /* rate information */ + UINT_32 tx_mpdu; /* number of successfully transmitted data pkts (ACK rcvd) */ + UINT_32 rx_mpdu; /* number of received data pkts */ + UINT_32 mpdu_lost; /* number of data packet losses (no ACK) */ + UINT_32 retries; /* total number of data pkt retries */ + UINT_32 retries_short; /* number of short data pkt retries */ + UINT_32 retries_long; /* number of long data pkt retries */ +} WIFI_RATE_STAT; + +/*wifi_interface_link_layer_info*/ +typedef enum { + WIFI_DISCONNECTED = 0, + WIFI_AUTHENTICATING = 1, + WIFI_ASSOCIATING = 2, + WIFI_ASSOCIATED = 3, + WIFI_EAPOL_STARTED = 4, /* if done by firmware/driver */ + WIFI_EAPOL_COMPLETED = 5, /* if done by firmware/driver */ +} WIFI_CONNECTION_STATE; + +typedef enum { + WIFI_ROAMING_IDLE = 0, + WIFI_ROAMING_ACTIVE = 1, +} WIFI_ROAM_STATE; + +typedef enum { + WIFI_INTERFACE_STA = 0, + WIFI_INTERFACE_SOFTAP = 1, + WIFI_INTERFACE_IBSS = 2, + WIFI_INTERFACE_P2P_CLIENT = 3, + WIFI_INTERFACE_P2P_GO = 4, + WIFI_INTERFACE_NAN = 5, + WIFI_INTERFACE_MESH = 6, + WIFI_INTERFACE_UNKNOWN = -1 +} WIFI_INTERFACE_MODE; + +typedef struct { + WIFI_INTERFACE_MODE mode; /* interface mode */ + u8 mac_addr[6]; /* interface mac address (self) */ + WIFI_CONNECTION_STATE state; /* connection state (valid for STA, CLI only) */ + WIFI_ROAM_STATE roaming; /* roaming state */ + u32 capabilities; /* WIFI_CAPABILITY_XXX (self) */ + u8 ssid[33]; /* null terminated SSID */ + u8 bssid[6]; /* bssid */ + u8 ap_country_str[3]; /* country string advertised by AP */ + u8 country_str[3]; /* country string for this association */ +} WIFI_INTERFACE_LINK_LAYER_INFO; + +/* access categories */ +typedef enum { + WIFI_AC_VO = 0, + WIFI_AC_VI = 1, + WIFI_AC_BE = 2, + WIFI_AC_BK = 3, + WIFI_AC_MAX = 4, +} WIFI_TRAFFIC_AC; + +/* wifi peer type */ +typedef enum { + WIFI_PEER_STA, + WIFI_PEER_AP, + WIFI_PEER_P2P_GO, + WIFI_PEER_P2P_CLIENT, + WIFI_PEER_NAN, + WIFI_PEER_TDLS, + WIFI_PEER_INVALID, +} WIFI_PEER_TYPE; + +/* per peer statistics */ +typedef struct { + WIFI_PEER_TYPE type; /* peer type (AP, TDLS, GO etc.) */ + UINT_8 peer_mac_address[6]; /* mac address */ + UINT_32 capabilities; /* peer WIFI_CAPABILITY_XXX */ + UINT_32 num_rate; /* number of rates */ + WIFI_RATE_STAT rate_stats[]; /* per rate statistics, number of entries = num_rate */ +} WIFI_PEER_INFO; + +/* per access category statistics */ +typedef struct { + WIFI_TRAFFIC_AC ac; /* access category (VI, VO, BE, BK) */ + UINT_32 tx_mpdu; /* number of successfully transmitted unicast data pkts (ACK rcvd) */ + UINT_32 rx_mpdu; /* number of received unicast mpdus */ + UINT_32 tx_mcast; /* number of successfully transmitted multicast data packets */ + /* STA case: implies ACK received from AP for the unicast packet in which mcast pkt was sent */ + UINT_32 rx_mcast; /* number of received multicast data packets */ + UINT_32 rx_ampdu; /* number of received unicast a-mpdus */ + UINT_32 tx_ampdu; /* number of transmitted unicast a-mpdus */ + UINT_32 mpdu_lost; /* number of data pkt losses (no ACK) */ + UINT_32 retries; /* total number of data pkt retries */ + UINT_32 retries_short; /* number of short data pkt retries */ + UINT_32 retries_long; /* number of long data pkt retries */ + UINT_32 contention_time_min; /* data pkt min contention time (usecs) */ + UINT_32 contention_time_max; /* data pkt max contention time (usecs) */ + UINT_32 contention_time_avg; /* data pkt avg contention time (usecs) */ + UINT_32 contention_num_samples; /* num of data pkts used for contention statistics */ +} WIFI_WMM_AC_STAT; + +/* interface statistics */ +typedef struct { + /* wifi_interface_handle iface; // wifi interface */ + WIFI_INTERFACE_LINK_LAYER_INFO info; /* current state of the interface */ + UINT_32 beacon_rx; /* access point beacon received count from connected AP */ + UINT_32 mgmt_rx; /* access point mgmt frames received count from connected AP (including Beacon) */ + UINT_32 mgmt_action_rx; /* action frames received count */ + UINT_32 mgmt_action_tx; /* action frames transmit count */ + wifi_rssi rssi_mgmt; /* access Point Beacon and Management frames RSSI (averaged) */ + wifi_rssi rssi_data; /* access Point Data Frames RSSI (averaged) from connected AP */ + wifi_rssi rssi_ack; /* access Point ACK RSSI (averaged) from connected AP */ + WIFI_WMM_AC_STAT ac[WIFI_AC_MAX]; /* per ac data packet statistics */ + UINT_32 num_peers; /* number of peers */ + WIFI_PEER_INFO peer_info[]; /* per peer statistics */ +} WIFI_IFACE_STAT; + +/* RSSI Monitoring */ +typedef struct _PARAM_RSSI_MONITOR_T { + BOOLEAN enable; /* 1=Start, 0=Stop*/ + INT_8 max_rssi_value; + INT_8 min_rssi_value; + UINT_8 reserved[1]; +} PARAM_RSSI_MONITOR_T, *P_PARAM_RSSI_MONITOR_T; + +typedef struct { + UINT_8 version; + INT_8 rssi; + mac_addr BSSID; +} PARAM_RSSI_MONITOR_EVENT; + +/* Packet Keep Alive */ +typedef struct _PARAM_PACKET_KEEPALIVE_T { + BOOLEAN enable; /* 1=Start, 0=Stop*/ + UINT_8 index; + UINT_16 u2IpPktLen; + UINT_8 pIpPkt[256]; + mac_addr ucSrcMacAddr; + mac_addr ucDstMacAddr; + UINT_32 u4PeriodMsec; +} PARAM_PACKET_KEEPALIVE_T, *P_PARAM_PACKET_KEEPALIVE_T; + +enum WIFI_VENDOR_ATTR_ACS { + WIFI_VENDOR_ATTR_ACS_CHANNEL_INVALID = 0, + WIFI_VENDOR_ATTR_ACS_PRIMARY_CHANNEL, + WIFI_VENDOR_ATTR_ACS_SECONDARY_CHANNEL, + WIFI_VENDOR_ATTR_ACS_HW_MODE, + WIFI_VENDOR_ATTR_ACS_HT_ENABLED, + WIFI_VENDOR_ATTR_ACS_HT40_ENABLED, + WIFI_VENDOR_ATTR_ACS_VHT_ENABLED, + WIFI_VENDOR_ATTR_ACS_CHWIDTH, + WIFI_VENDOR_ATTR_ACS_CH_LIST, + WIFI_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL, + WIFI_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL, + WIFI_VENDOR_ATTR_ACS_FREQ_LIST, + WIFI_VENDOR_ATTR_ACS_AFTER_LAST, + WIFI_VENDOR_ATTR_ACS_MAX = + WIFI_VENDOR_ATTR_ACS_AFTER_LAST - 1 +}; + +enum NL80211_VENDOR_FEATURES { + VENDOR_FEATURE_KEY_MGMT_OFFLOAD = 0, + VENDOR_FEATURE_SUPPORT_HW_MODE_ANY = 1, + VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS = 2, + VENDOR_FEATURE_P2P_LISTEN_OFFLOAD = 3, + VENDOR_FEATURE_OCE_STA = 4, + VENDOR_FEATURE_OCE_AP = 5, + VENDOR_FEATURE_OCE_STA_CFON = 6, + NUM_VENDOR_FEATURES /* keep last */ +}; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +int mtk_cfg80211_vendor_get_channel_list(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_country_code(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +#if CFG_SUPPORT_GSCN +int mtk_cfg80211_vendor_get_gscan_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_scan_config(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_significant_change(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_hotlist(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_enable_scan(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_enable_full_scan_results(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_get_gscan_result(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_gscan_results(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len, BOOLEAN complete, BOOLEAN compValue); +#endif + +int mtk_cfg80211_vendor_get_rtt_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_llstats_get_info(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_rssi_monitoring(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_packet_keep_alive_start(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_packet_keep_alive_stop(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_get_version(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_event_complete_scan(struct wiphy *wiphy, struct wireless_dev *wdev, + WIFI_SCAN_EVENT complete); + +int mtk_cfg80211_vendor_event_scan_results_available(struct wiphy *wiphy, struct wireless_dev *wdev, UINT_32 num); + +int mtk_cfg80211_vendor_event_full_scan_results(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_GSCAN_FULL_RESULT pdata, UINT_32 data_len); + +int mtk_cfg80211_vendor_event_significant_change_results(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_CHANGE_RESULT pdata, UINT_32 data_len); + +int mtk_cfg80211_vendor_event_hotlist_ap_found(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_GSCAN_RESULT pdata, UINT_32 data_len); + +int mtk_cfg80211_vendor_event_hotlist_ap_lost(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_GSCAN_RESULT pdata, UINT_32 data_len); + +int mtk_cfg80211_vendor_event_rssi_beyond_range(struct wiphy *wiphy, struct wireless_dev *wdev, INT_32 rssi); + +int mtk_cfg80211_vendor_set_band(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_scan_mac_oui(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_roaming_policy(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_get_roaming_capabilities(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); + +int mtk_cfg80211_vendor_config_roaming(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); + +int mtk_cfg80211_vendor_enable_roaming(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); + +int mtk_cfg80211_vendor_get_supported_feature_set( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_tx_power_scenario( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_acs(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); + +int mtk_cfg80211_vendor_get_features(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); + +#endif /* _GL_VENDOR_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_wext.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_wext.h new file mode 100644 index 0000000000000..fb4fd190b1f11 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_wext.h @@ -0,0 +1,312 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _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 + +#define IW_AUTH_ALG_FT 0x00000008 +#define IW_AUTH_ALG_SAE 0x00000010 +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +extern const struct iw_handler_def wext_handler_def; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/* wireless extensions' ioctls */ +int wext_support_ioctl(IN struct net_device *prDev, IN struct ifreq *prIfReq, IN int i4Cmd); + +int +wext_set_rate(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN struct iw_param *prRate, IN char *pcExtra); + +void +wext_indicate_wext_event(IN P_GLUE_INFO_T prGlueInfo, + IN unsigned int u4Cmd, IN unsigned char *pucData, IN unsigned int u4DataLen); + +struct iw_statistics *wext_get_wireless_stats(struct net_device *prDev); + +BOOLEAN +wextSrchDesiredWPAIE(IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT PPUINT_8 ppucDesiredIE); + +#if CFG_SUPPORT_WPS +BOOLEAN +wextSrchDesiredWPSIE(IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT PPUINT_8 ppucDesiredIE); +#endif + +#if CFG_SUPPORT_HOTSPOT_2_0 +BOOLEAN wextSrchDesiredHS20IE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PPUINT_8 ppucDesiredIE); + +BOOLEAN wextSrchDesiredAdvProtocolIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PPUINT_8 ppucDesiredIE); + +BOOLEAN wextSrchDesiredOsenIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PPUINT_8 ppucDesiredIE); +#endif + +#if CFG_SUPPORT_WAPI +BOOLEAN wextSrchDesiredWAPIIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PPUINT_8 ppucDesiredIE); +#endif + +BOOLEAN wextSrchOkcAndPMKID(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PPUINT_8 ppucPMKID, OUT PUINT_8 okc); +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* WIRELESS_EXT */ + +#endif /* _GL_WEXT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_wext_priv.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_wext_priv.h new file mode 100644 index 0000000000000..7bbde0bc0a950 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/include/gl_wext_priv.h @@ -0,0 +1,329 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _GL_WEXT_PRIV_H +#define _GL_WEXT_PRIV_H +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +/* If it is set to 1, iwpriv will support register read/write */ +#define CFG_SUPPORT_PRIV_MCR_RW 1 + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#if CFG_ENABLE_WIFI_DIRECT +extern int set_p2p_mode_handler(struct net_device *netdev, PARAM_CUSTOM_P2P_SET_STRUCT_T p2pmode); +#if 0 +extern BOOLEAN fgIsResetting; +extern BOOLEAN g_u4HaltFlag; +extern spinlock_t g_p2p_lock; +extern int g_u4P2PEnding; +extern int g_u4P2POnOffing; +#endif +#endif + + +#if (CFG_SUPPORT_TXR_ENC == 1) +extern VOID rlmCmd(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); +#endif /* CFG_SUPPORT_TXR_ENC */ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* New wireless extensions API - SET/GET convention (even ioctl numbers are + * root only) + */ +#define IOCTL_SET_INT (SIOCIWFIRSTPRIV + 0) +#define IOCTL_GET_INT (SIOCIWFIRSTPRIV + 1) + +#define IOCTL_SET_ADDRESS (SIOCIWFIRSTPRIV + 2) +#define IOCTL_GET_ADDRESS (SIOCIWFIRSTPRIV + 3) +#define IOCTL_SET_STR (SIOCIWFIRSTPRIV + 4) +#define IOCTL_GET_STR (SIOCIWFIRSTPRIV + 5) +#define IOCTL_SET_KEY (SIOCIWFIRSTPRIV + 6) +#define IOCTL_GET_KEY (SIOCIWFIRSTPRIV + 7) +#define IOCTL_SET_STRUCT (SIOCIWFIRSTPRIV + 8) +#define IOCTL_GET_STRUCT (SIOCIWFIRSTPRIV + 9) +#define IOCTL_SET_STRUCT_FOR_EM (SIOCIWFIRSTPRIV + 11) +#define IOCTL_SET_INTS (SIOCIWFIRSTPRIV + 12) +#define IOCTL_GET_INTS (SIOCIWFIRSTPRIV + 13) +#define IOCTL_SET_STRING (SIOCIWFIRSTPRIV + 14) +#define IOCTL_GET_STRING (SIOCIWFIRSTPRIV + 15) +#define IOCTL_GET_DRIVER (SIOCIWFIRSTPRIV + 17) + +#define PRIV_CMD_REG_DOMAIN 0 +#define PRIV_CMD_BEACON_PERIOD 1 +#define PRIV_CMD_ADHOC_MODE 2 + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +#define PRIV_CMD_CSUM_OFFLOAD 3 +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +#define PRIV_CMD_ROAMING 4 +#define PRIV_CMD_VOIP_DELAY 5 +#define PRIV_CMD_POWER_MODE 6 + +#define PRIV_CMD_WMM_PS 7 +#define PRIV_CMD_BT_COEXIST 8 +#define PRIV_GPIO2_MODE 9 + +#define PRIV_CUSTOM_SET_PTA 10 +#define PRIV_CUSTOM_CONTINUOUS_POLL 11 +#define PRIV_CUSTOM_SINGLE_ANTENNA 12 +#define PRIV_CUSTOM_BWCS_CMD 13 +#define PRIV_CUSTOM_DISABLE_BEACON_DETECTION 14 /* later */ +#define PRIV_CMD_OID 15 +#define PRIV_SEC_MSG_OID 16 + +#define PRIV_CMD_TEST_MODE 17 +#define PRIV_CMD_TEST_CMD 18 +#define PRIV_CMD_ACCESS_MCR 19 +#define PRIV_CMD_SW_CTRL 20 + +#if 1 /* ANTI_PRIVCY */ +#define PRIV_SEC_CHECK_OID 21 +#endif + +#define PRIV_CMD_WSC_PROBE_REQ 22 + +#define PRIV_CMD_P2P_VERSION 23 + +#define PRIV_CMD_GET_CH_LIST 24 + +#define PRIV_CMD_SET_TX_POWER 25 + +#define PRIV_CMD_BAND_CONFIG 26 + +#define PRIV_CMD_DUMP_MEM 27 + +#define PRIV_CMD_P2P_MODE 28 + +#define PRIV_CMD_GET_BUILD_DATE_CODE 29 + +#define PRIV_CMD_GET_DEBUG_CODE 30 + +#define PRIV_CMD_OTHER 31 + +#define PRIV_CMD_WFD_DEBUG_CODE 32 + +#define PRIV_CMD_MET_PROFILING 33 + +#define PRIV_CMD_DUMP_DRIVER 34 + +/* wifi type: 11g, 11n, ... */ +#define PRIV_CMD_GET_WIFI_TYPE 41 + +/* other string command ID */ +#define PRIV_CMD_OTHER_TDLS 0x00 +#define PRIV_CMD_OTHER_TAR 0x01 /* TX auto rate */ + +/* 802.3 Objects (Ethernet) */ +#define OID_802_3_CURRENT_ADDRESS 0x01010102 + +/* IEEE 802.11 OIDs */ +#define OID_802_11_SUPPORTED_RATES 0x0D01020E +#define OID_802_11_CONFIGURATION 0x0D010211 + +/* PnP and PM OIDs, NDIS default OIDS */ +#define OID_PNP_SET_POWER 0xFD010101 + +#define OID_CUSTOM_OID_INTERFACE_VERSION 0xFFA0C000 + +/* MT5921 specific OIDs */ +#define OID_CUSTOM_BT_COEXIST_CTRL 0xFFA0C580 +#define OID_CUSTOM_POWER_MANAGEMENT_PROFILE 0xFFA0C581 +#define OID_CUSTOM_PATTERN_CONFIG 0xFFA0C582 +#define OID_CUSTOM_BG_SSID_SEARCH_CONFIG 0xFFA0C583 +#define OID_CUSTOM_VOIP_SETUP 0xFFA0C584 +#define OID_CUSTOM_ADD_TS 0xFFA0C585 +#define OID_CUSTOM_DEL_TS 0xFFA0C586 +#define OID_CUSTOM_SLT 0xFFA0C587 +#define OID_CUSTOM_ROAMING_EN 0xFFA0C588 +#define OID_CUSTOM_WMM_PS_TEST 0xFFA0C589 +#define OID_CUSTOM_COUNTRY_STRING 0xFFA0C58A +#define OID_CUSTOM_MULTI_DOMAIN_CAPABILITY 0xFFA0C58B +#define OID_CUSTOM_GPIO2_MODE 0xFFA0C58C +#define OID_CUSTOM_CONTINUOUS_POLL 0xFFA0C58D +#define OID_CUSTOM_DISABLE_BEACON_DETECTION 0xFFA0C58E + +/* CR1460, WPS privacy bit check disable */ +#define OID_CUSTOM_DISABLE_PRIVACY_CHECK 0xFFA0C600 + +/* Precedent OIDs */ +#define OID_CUSTOM_MCR_RW 0xFFA0C801 +#define OID_CUSTOM_EEPROM_RW 0xFFA0C803 +#define OID_CUSTOM_SW_CTRL 0xFFA0C805 +#define OID_CUSTOM_MEM_DUMP 0xFFA0C807 + +/* RF Test specific OIDs */ +#define OID_CUSTOM_TEST_MODE 0xFFA0C901 +#define OID_CUSTOM_TEST_RX_STATUS 0xFFA0C903 +#define OID_CUSTOM_TEST_TX_STATUS 0xFFA0C905 +#define OID_CUSTOM_ABORT_TEST_MODE 0xFFA0C906 +#define OID_CUSTOM_MTK_WIFI_TEST 0xFFA0C911 + +/* BWCS */ +#define OID_CUSTOM_BWCS_CMD 0xFFA0C931 +#define OID_CUSTOM_SINGLE_ANTENNA 0xFFA0C932 +#define OID_CUSTOM_SET_PTA 0xFFA0C933 + +/* NVRAM */ +#define OID_CUSTOM_MTK_NVRAM_RW 0xFFA0C941 +#define OID_CUSTOM_CFG_SRC_TYPE 0xFFA0C942 +#define OID_CUSTOM_EEPROM_TYPE 0xFFA0C943 + +#if CFG_SUPPORT_WAPI +#define OID_802_11_WAPI_MODE 0xFFA0CA00 +#define OID_802_11_WAPI_ASSOC_INFO 0xFFA0CA01 +#define OID_802_11_SET_WAPI_KEY 0xFFA0CA02 +#endif + +#if CFG_SUPPORT_WPS2 +#define OID_802_11_WSC_ASSOC_INFO 0xFFA0CB00 +#endif + +#if CFG_SUPPORT_GAMING_MODE +#define OID_CUSTOM_GAMING_MODE 0xFFA0CC00 +#endif + +#if CFG_SUPPORT_NCHO +#define CMD_NCHO_COMP_TIMEOUT 1500 /* ms */ +#define CMD_NCHO_AF_DATA_LENGTH 1040 +#endif +/* Define magic key of test mode (Don't change it for future compatibity) */ +#define PRIV_CMD_TEST_MAGIC_KEY 2011 + +#define OID_IPC_WIFI_LOG_UI 0xFFA0CC01 +#define OID_IPC_WIFI_LOG_LEVEL 0xFFA0CC02 + +/******************************************************************************* +* 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_set_driver(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, + IN OUT char *pcExtra); + +UINT_32 CmdStringDecParse(IN UINT_8 *InStr, OUT UINT_8 **OutStr, OUT UINT_32 *OutLen); + +UINT_32 CmdStringMacParse(IN UINT_8 *InStr, OUT UINT_8 **OutStr, OUT UINT_32 *OutLen, OUT UINT_8 *OutMac); + +#if CFG_SUPPORT_NCHO +UINT_8 CmdString2HexParse(IN UINT_8 *InStr, OUT UINT_8 **OutStr, OUT UINT_8 *OutLen); +#endif + +int +priv_set_string(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra); + +int +priv_get_string(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra); + +int priv_support_ioctl(IN struct net_device *prDev, IN OUT struct ifreq *prReq, IN int i4Cmd); + +int priv_support_driver_cmd(IN struct net_device *prDev, IN OUT struct ifreq *prReq, IN int i4Cmd); + +INT_32 priv_driver_cmds(IN struct net_device *prNetDev, IN PCHAR pcCommand, IN INT_32 i4TotalLen); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _GL_WEXT_PRIV_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/platform.c b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/platform.c new file mode 100644 index 0000000000000..25b078a5b17b3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/linux/platform.c @@ -0,0 +1,636 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#include +#include + +#include + +#include "gl_os.h" + +#ifndef CONFIG_X86 +#if defined(CONFIG_HAS_EARLY_SUSPEND) +#include +#endif +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#if CFG_TC10_FEATURE +#define WIFI_NVRAM_FILE_NAME "/vendor/firmware/WIFI" +#else +#define WIFI_NVRAM_FILE_NAME "/mnt/vendor/nvdata/APCFG/APRDEB/WIFI" +#endif +#define WIFI_NVRAM_CUSTOM_NAME "/mnt/vendor/nvdata/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, ERROR, "netdev_event: device is empty.\n"); + return NOTIFY_DONE; + } + DBGLOG(REQ, INFO, "netdev_event, addr=%x, notification=%lx, dev_name=%s\n", + ifa->ifa_address, notification, prDev->name); + if (!fgIsUnderSuspend) + return NOTIFY_DONE; + if ((strncmp(prDev->name, "p2p", 3) != 0) && (strncmp(prDev->name, "wlan", 4) != 0)) { + DBGLOG(REQ, WARN, "netdev_event: not our device\n"); + return NOTIFY_DONE; + } +#if 0 /* CFG_SUPPORT_HOTSPOT_2_0 */ + { + /* printk(KERN_INFO "[netdev_event] IPV4_DAD is unlock now!!\n"); */ + prGlueInfo->fgIsDad = FALSE; + } +#endif + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + + if (prGlueInfo == NULL) { + DBGLOG(REQ, ERROR, "netdev_event: prGlueInfo is empty.\n"); + return NOTIFY_DONE; + } + ASSERT(prGlueInfo); + + /* <3> get the IPv4 address */ + if (!prDev || !(prDev->ip_ptr) || + !((struct in_device *)(prDev->ip_ptr))->ifa_list || + !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))) { + DBGLOG(REQ, INFO, "ip is not available.\n"); + return NOTIFY_DONE; + } + + kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip)); + DBGLOG(REQ, INFO, "ip is %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); + + /* todo: traverse between list to find whole sets of IPv4 addresses */ + if (!((ip[0] == 0) && (ip[1] == 0) && (ip[2] == 0) && (ip[3] == 0))) + u4NumIPv4++; +/* #ifdef CONFIG_IPV6 */ +#if 0 + if (!prDev || !(prDev->ip6_ptr) || + !((struct in_device *)(prDev->ip6_ptr))->ifa_list || + !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))) { + DBGLOG(REQ, INFO, "ipv6 is not available.\n"); + return NOTIFY_DONE; + } + + kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6)); + DBGLOG(REQ, INFO, "ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n", + ip6[0], ip6[1], ip6[2], ip6[3], + ip6[4], ip6[5], ip6[6], ip6[7], ip6[8], ip6[9], ip6[10], ip6[11], ip6[12], ip6[13], ip6[14], ip6[15]); + + /* todo: traverse between list to find whole sets of IPv6 addresses */ + if (!((ip6[0] == 0) && (ip6[1] == 0) && (ip6[2] == 0) && (ip6[3] == 0) && (ip6[4] == 0) && (ip6[5] == 0))) + /* u4NumIPv6++; */ +#endif + + /* here we can compare the dev with other network's netdev to */ + /* set the proper arp filter */ + /* */ + /* IMPORTANT: please make sure if the context can sleep, if the context can't sleep */ + /* we should schedule a kernel thread to do this for us */ + + /* <7> set up the ARP filter */ + { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_32 u4SetInfoLen = 0; + UINT_8 aucBuf[32] = { 0 }; + UINT_32 u4Len = OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress); + P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST) aucBuf; + P_PARAM_NETWORK_ADDRESS prParamNetAddr = prParamNetAddrList->arAddress; + +/* #ifdef CONFIG_IPV6 */ +#if 0 + prParamNetAddrList->u4AddressCount = u4NumIPv4 + u4NumIPv6; +#else + prParamNetAddrList->u4AddressCount = u4NumIPv4; +#endif + prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + for (i = 0; i < u4NumIPv4; i++) { + prParamNetAddr->u2AddressLength = sizeof(PARAM_NETWORK_ADDRESS_IP); /* 4;; */ + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; +#if 0 + kalMemCopy(prParamNetAddr->aucAddress, ip, sizeof(ip)); + prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((PUINT_8) prParamNetAddr + sizeof(ip)); + u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip); +#else + prParamIpAddr = (P_PARAM_NETWORK_ADDRESS_IP) prParamNetAddr->aucAddress; + kalMemCopy(&prParamIpAddr->in_addr, ip, sizeof(ip)); + prParamNetAddr = + (P_PARAM_NETWORK_ADDRESS) ((PUINT_8) prParamNetAddr + sizeof(PARAM_NETWORK_ADDRESS)); + u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(PARAM_NETWORK_ADDRESS); +#endif + } +/* #ifdef CONFIG_IPV6 */ +#if 0 + for (i = 0; i < u4NumIPv6; i++) { + prParamNetAddr->u2AddressLength = 6; + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + kalMemCopy(prParamNetAddr->aucAddress, ip6, sizeof(ip6)); + prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((PUINT_8) prParamNetAddr + sizeof(ip6)); + u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip6); + } +#endif + ASSERT(u4Len <= sizeof(aucBuf)); + + DBGLOG(REQ, INFO, "kalIoctl (0x%p, 0x%p)\n", prGlueInfo, prParamNetAddrList); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNetworkAddress, + (PVOID) prParamNetAddrList, u4Len, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, ERROR, "set HW pattern filter fail 0x%x\n", rStatus); + } + + return NOTIFY_DONE; + +} + +/* #if CFG_SUPPORT_HOTSPOT_2_0 */ +#if 0 +static int net6dev_event(struct notifier_block *nb, unsigned long notification, void *ptr) +{ + struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr; + struct net_device *prDev = ifa->idev->dev; + P_GLUE_INFO_T prGlueInfo = NULL; + + if (prDev == NULL) { + DBGLOG(REQ, INFO, "net6dev_event: device is empty.\n"); + return NOTIFY_DONE; + } + + if ((strncmp(prDev->name, "p2p", 3) != 0) && (strncmp(prDev->name, "wlan", 4) != 0)) { + DBGLOG(REQ, INFO, "net6dev_event: xxx\n"); + return NOTIFY_DONE; + } + + if (strncmp(prDev->name, "p2p", 3) == 0) { + /* because we store the address of prGlueInfo in p2p's private date of net device */ + /* *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->prP2PInfo->prDevHandler)) = prGlueInfo; */ + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + } else { /* wlan0 */ + prGlueInfo = (P_GLUE_INFO_T) netdev_priv(prDev); + } + + if (prGlueInfo == NULL) { + DBGLOG(REQ, INFO, "netdev_event: prGlueInfo is empty.\n"); + return NOTIFY_DONE; + } + /* printk(KERN_INFO "[net6dev_event] IPV6_DAD is unlock now!!\n"); */ + prGlueInfo->fgIs6Dad = FALSE; + + return NOTIFY_DONE; +} +#endif + +static struct notifier_block inetaddr_notifier = { + .notifier_call = netdev_event, +}; + +#if 0 /* CFG_SUPPORT_HOTSPOT_2_0 */ +static struct notifier_block inet6addr_notifier = { + .notifier_call = net6dev_event, +}; +#endif + +void wlanRegisterNotifier(void) +{ + register_inetaddr_notifier(&inetaddr_notifier); + +#if CFG_SUPPORT_HOTSPOT_2_0 + /* register_inet6addr_notifier(&inet6addr_notifier); */ +#endif +} + +/* EXPORT_SYMBOL(wlanRegisterNotifier); */ + +void wlanUnregisterNotifier(void) +{ + unregister_inetaddr_notifier(&inetaddr_notifier); + +#if CFG_SUPPORT_HOTSPOT_2_0 + /* unregister_inetaddr_notifier(&inet6addr_notifier); */ +#endif +} + +/* EXPORT_SYMBOL(wlanUnregisterNotifier); */ + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +/* (Wayne) TODO: merge these two functions into one. */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +static int nvram_read(char *filename, char *buf, ssize_t len, int offset) +{ +#if CFG_SUPPORT_NVRAM + struct file *fd; + int retLen = -1; + loff_t pos; + char __user *p; + + 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) { + DBGLOG(INIT, INFO, "[MT6620][nvram_read] : f_op is NULL!!\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; + } + } + + p = (__force char __user *)buf; + pos = (loff_t)offset; + retLen = __vfs_read(fd, p, len, &pos); + if (retLen < 0) + DBGLOG(INIT, ERROR, "[MT6620][nvram_read] : read failed!! Error code: %d\n", retLen); + + } while (FALSE); + + filp_close(fd, NULL); + + set_fs(old_fs); + + return retLen; + +#else /* !CFG_SUPPORT_NVRAM */ + + return -EIO; + +#endif +} +#else +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"); + set_fs(old_fs); + 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 +} +#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 +*/ +/*----------------------------------------------------------------------------*/ +/* (Wayne) TODO: merge these two functions into one. */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +static int nvram_write(char *filename, char *buf, ssize_t len, int offset) +{ +#if CFG_SUPPORT_NVRAM + struct file *fd; + int retLen = -1; + loff_t pos; + char __user *p; + + 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) { + DBGLOG(INIT, INFO, "[MT6620][nvram_write] : f_op is NULL!!\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; + } + } + + p = (__force char __user *)buf; + pos = (loff_t)offset; + + retLen = __vfs_write(fd, p, len, &pos); + if (retLen < 0) + DBGLOG(INIT, ERROR, "[MT6620][nvram_write] : write failed!! Error code: %d\n", retLen); + + } while (FALSE); + + filp_close(fd, NULL); + + set_fs(old_fs); + + return retLen; + +#else /* !CFG_SUPPORT_NVRAMS */ + + return -EIO; + +#endif +} +#else +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"); + set_fs(old_fs); + 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 +} +#endif +#endif /* #if 0 */ +/*----------------------------------------------------------------------------*/ +/*! +* \brief API for reading data on NVRAM +* +* \param[in] +* prGlueInfo +* u4Offset +* \param[out] +* pu2Data +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalCfgDataRead(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Offset, + IN UINT_32 u4Len, OUT PUINT_16 pu2Data) +{ + if (pu2Data == NULL) + return FALSE; + + if (u4Offset + u4Len > CFG_FILE_WIFI_REC_SIZE) + return FALSE; + + kalMemCopy(pu2Data, &g_aucNvram[u4Offset], u4Len); + return TRUE; +#if 0 + if (nvram_read(WIFI_NVRAM_FILE_NAME, + (char *)pu2Data, u4Len, u4Offset) != u4Len) { + return FALSE; + } else { + return TRUE; + } +#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 (u4Offset + sizeof(unsigned short) > CFG_FILE_WIFI_REC_SIZE) + return FALSE; + + kalMemCopy(pu2Data, &g_aucNvram[u4Offset], sizeof(unsigned short)); + return TRUE; +#if 0 + if (nvram_read(WIFI_NVRAM_FILE_NAME, + (char *)pu2Data, sizeof(unsigned short), u4Offset) != sizeof(unsigned short)) { + return FALSE; + } else { + return TRUE; + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 (u4Offset + sizeof(unsigned short) > CFG_FILE_WIFI_REC_SIZE) + return FALSE; + + kalMemCopy(&g_aucNvram[u4Offset], &u2Data, sizeof(unsigned short)); + return TRUE; +#if 0 + if (nvram_write(WIFI_NVRAM_FILE_NAME, + (char *)&u2Data, sizeof(unsigned short), u4Offset) != sizeof(unsigned short)) { + return FALSE; + } else { + return TRUE; + } +#endif +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/version.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/version.h new file mode 100644 index 0000000000000..43cc4205b9b27 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/os/version.h @@ -0,0 +1,100 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _VERSION_H +#define _VERSION_H +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#ifndef NIC_AUTHOR +#define NIC_AUTHOR "NIC_AUTHOR" +#endif +#ifndef NIC_DESC +#define NIC_DESC "NIC_DESC" +#endif + +#ifndef NIC_NAME +#if defined(MT6620) +#define NIC_NAME "MT6620" +#define NIC_DEVICE_ID "MT6620" +#define NIC_DEVICE_ID_LOW "mt6620" +#elif defined(MT6628) +#define NIC_NAME "MT6582" +#define NIC_DEVICE_ID "MT6582" +#define NIC_DEVICE_ID_LOW "mt6582" +#endif +#endif + +/* NIC driver information */ +#define NIC_VENDOR "MediaTek Inc." +#define NIC_VENDOR_OUI {0x00, 0x0C, 0xE7} + +#if defined(MT6620) +#define NIC_PRODUCT_NAME "MediaTek Inc. MT6620 Wireless LAN Adapter" +#define NIC_DRIVER_NAME "MediaTek Inc. MT6620 Wireless LAN Adapter Driver" +#elif defined(MT6628) +/* #define NIC_PRODUCT_NAME "MediaTek Inc. MT6628 Wireless LAN Adapter" */ +/* #define NIC_DRIVER_NAME "MediaTek Inc. MT6628 Wireless LAN Adapter Driver" */ +#define NIC_PRODUCT_NAME "MediaTek Inc. MT6582 Wireless LAN Adapter" +#define NIC_DRIVER_NAME "MediaTek Inc. MT6582 Wireless LAN Adapter Driver" +#endif + +/* Define our driver version */ +#define NIC_DRIVER_MAJOR_VERSION 2 +#define NIC_DRIVER_MINOR_VERSION 0 +#define NIC_DRIVER_SERIAL_VERSION 1 +#define NIC_DRIVER_VERSION_STRING "201607271200" + +/******************************************************************************* +* 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 */ From 7aceb09ffcf51db93fd0c511c8636080cda70085 Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 21:55:50 +0800 Subject: [PATCH 15/32] Add files via upload --- .../wlan/core/gen2/include/CFG_Wifi_File.h | 215 ++ .../wlan/core/gen2/include/config.h | 974 ++++++ .../wlan/core/gen2/include/debug.h | 508 +++ .../wlan/core/gen2/include/fwcfg.h | 129 + .../wlan/core/gen2/include/link.h | 373 +++ .../wlan/core/gen2/include/mgmt/aa_fsm.h | 148 + .../wlan/core/gen2/include/mgmt/ais_fsm.h | 473 +++ .../wlan/core/gen2/include/mgmt/assoc.h | 93 + .../wlan/core/gen2/include/mgmt/auth.h | 115 + .../wlan/core/gen2/include/mgmt/bow_fsm.h | 159 + .../wlan/core/gen2/include/mgmt/bss.h | 162 + .../wlan/core/gen2/include/mgmt/cnm.h | 200 ++ .../wlan/core/gen2/include/mgmt/cnm_mem.h | 777 +++++ .../wlan/core/gen2/include/mgmt/cnm_scan.h | 115 + .../wlan/core/gen2/include/mgmt/cnm_timer.h | 177 ++ .../wlan/core/gen2/include/mgmt/hem_mbox.h | 278 ++ .../wlan/core/gen2/include/mgmt/hs20.h | 142 + .../wlan/core/gen2/include/mgmt/mib.h | 129 + .../wlan/core/gen2/include/mgmt/p2p_assoc.h | 59 + .../wlan/core/gen2/include/mgmt/p2p_bss.h | 59 + .../wlan/core/gen2/include/mgmt/p2p_fsm.h | 1871 +++++++++++ .../wlan/core/gen2/include/mgmt/p2p_func.h | 194 ++ .../wlan/core/gen2/include/mgmt/p2p_ie.h | 171 + .../wlan/core/gen2/include/mgmt/p2p_rlm.h | 79 + .../core/gen2/include/mgmt/p2p_rlm_obss.h | 69 + .../wlan/core/gen2/include/mgmt/p2p_scan.h | 85 + .../wlan/core/gen2/include/mgmt/p2p_state.h | 56 + .../wlan/core/gen2/include/mgmt/privacy.h | 190 ++ .../wlan/core/gen2/include/mgmt/qosmap.h | 72 + .../wlan/core/gen2/include/mgmt/rate.h | 78 + .../wlan/core/gen2/include/mgmt/rlm.h | 404 +++ .../wlan/core/gen2/include/mgmt/rlm_domain.h | 532 ++++ .../wlan/core/gen2/include/mgmt/rlm_obss.h | 98 + .../core/gen2/include/mgmt/rlm_protection.h | 95 + .../core/gen2/include/mgmt/rlm_txpwr_init.h | 1213 ++++++++ .../wlan/core/gen2/include/mgmt/roaming_fsm.h | 138 + .../wlan/core/gen2/include/mgmt/rsn.h | 244 ++ .../wlan/core/gen2/include/mgmt/scan.h | 839 +++++ .../wlan/core/gen2/include/mgmt/sec_fsm.h | 117 + .../wlan/core/gen2/include/mgmt/stats.h | 372 +++ .../wlan/core/gen2/include/mgmt/swcr.h | 189 ++ .../wlan/core/gen2/include/mgmt/tdls.h | 322 ++ .../wlan/core/gen2/include/mgmt/wapi.h | 81 + .../core/gen2/include/mgmt/wlan_typedef.h | 86 + .../wlan/core/gen2/include/mgmt/wmm.h | 212 ++ .../wlan/core/gen2/include/mgmt/wnm.h | 137 + .../wlan/core/gen2/include/nic/adapter.h | 1140 +++++++ .../wlan/core/gen2/include/nic/bow.h | 224 ++ .../wlan/core/gen2/include/nic/cmd_buf.h | 128 + .../wlan/core/gen2/include/nic/hal.h | 555 ++++ .../wlan/core/gen2/include/nic/hif_rx.h | 175 ++ .../wlan/core/gen2/include/nic/hif_tx.h | 168 + .../wlan/core/gen2/include/nic/mac.h | 2737 +++++++++++++++++ .../wlan/core/gen2/include/nic/mtreg.h | 258 ++ .../wlan/core/gen2/include/nic/nic.h | 306 ++ .../wlan/core/gen2/include/nic/nic_rx.h | 280 ++ .../wlan/core/gen2/include/nic/nic_tx.h | 417 +++ .../wlan/core/gen2/include/nic/p2p.h | 165 + .../wlan/core/gen2/include/nic/p2p_cmd_buf.h | 71 + .../wlan/core/gen2/include/nic/p2p_mac.h | 210 ++ .../wlan/core/gen2/include/nic/p2p_nic.h | 65 + .../core/gen2/include/nic/p2p_nic_cmd_event.h | 75 + .../wlan/core/gen2/include/nic/que_mgt.h | 909 ++++++ .../wlan/core/gen2/include/nic/wlan_def.h | 873 ++++++ .../wlan/core/gen2/include/nic_cmd_event.h | 1958 ++++++++++++ .../core/gen2/include/nic_init_cmd_event.h | 149 + .../wlan/core/gen2/include/p2p_precomp.h | 205 ++ .../wlan/core/gen2/include/p2p_typedef.h | 167 + .../wlan/core/gen2/include/precomp.h | 239 ++ .../wlan/core/gen2/include/pwr_mgt.h | 100 + .../wlan/core/gen2/include/queue.h | 170 + .../wlan/core/gen2/include/rftest.h | 260 ++ .../wlan/core/gen2/include/tdls_extr.h | 424 +++ .../wlan/core/gen2/include/typedef.h | 155 + .../wlan/core/gen2/include/wlan_bow.h | 250 ++ .../wlan/core/gen2/include/wlan_lib.h | 697 +++++ .../wlan/core/gen2/include/wlan_oid.h | 2034 ++++++++++++ .../wlan/core/gen2/include/wlan_p2p.h | 221 ++ 78 files changed, 29014 insertions(+) create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/CFG_Wifi_File.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/config.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/debug.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/fwcfg.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/link.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/aa_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/ais_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/assoc.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/auth.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/bow_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/bss.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/cnm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/cnm_mem.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/cnm_scan.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/cnm_timer.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/hem_mbox.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/hs20.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/mib.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_assoc.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_bss.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_func.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_ie.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_rlm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_rlm_obss.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_scan.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_state.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/privacy.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/qosmap.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rate.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rlm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rlm_domain.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rlm_obss.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rlm_protection.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rlm_txpwr_init.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/roaming_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rsn.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/scan.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/sec_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/stats.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/swcr.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/tdls.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/wapi.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/wlan_typedef.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/wmm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/wnm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/adapter.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/bow.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/cmd_buf.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/hal.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/hif_rx.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/hif_tx.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/mac.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/mtreg.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/nic.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/nic_rx.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/nic_tx.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/p2p.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/p2p_cmd_buf.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/p2p_mac.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/p2p_nic.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/p2p_nic_cmd_event.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/que_mgt.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/wlan_def.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic_cmd_event.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic_init_cmd_event.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/p2p_precomp.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/p2p_typedef.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/precomp.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/pwr_mgt.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/queue.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/rftest.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/tdls_extr.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/typedef.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/wlan_bow.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/wlan_lib.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/wlan_oid.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen2/include/wlan_p2p.h diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/CFG_Wifi_File.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/CFG_Wifi_File.h new file mode 100644 index 0000000000000..dda49fabb9f92 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/CFG_Wifi_File.h @@ -0,0 +1,215 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _CFG_WIFI_FILE_H +#define _CFG_WIFI_FILE_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_typedef.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +/* duplicated from nic_cmd_event.h to avoid header dependency */ +typedef struct _TX_PWR_PARAM_T { + INT_8 cTxPwr2G4Cck; /* signed, in unit of 0.5dBm */ + INT_8 acReserved[3]; /* form MT6628 acReserved[0]=cTxPwr2G4Dsss */ + INT_8 cTxPwr2G4OFDM_BPSK; + INT_8 cTxPwr2G4OFDM_QPSK; + INT_8 cTxPwr2G4OFDM_16QAM; + INT_8 cTxPwr2G4OFDM_Reserved; + INT_8 cTxPwr2G4OFDM_48Mbps; + INT_8 cTxPwr2G4OFDM_54Mbps; + + INT_8 cTxPwr2G4HT20_BPSK; + INT_8 cTxPwr2G4HT20_QPSK; + INT_8 cTxPwr2G4HT20_16QAM; + INT_8 cTxPwr2G4HT20_MCS5; + INT_8 cTxPwr2G4HT20_MCS6; + INT_8 cTxPwr2G4HT20_MCS7; + + INT_8 cTxPwr2G4HT40_BPSK; + INT_8 cTxPwr2G4HT40_QPSK; + INT_8 cTxPwr2G4HT40_16QAM; + INT_8 cTxPwr2G4HT40_MCS5; + INT_8 cTxPwr2G4HT40_MCS6; + INT_8 cTxPwr2G4HT40_MCS7; + + INT_8 cTxPwr5GOFDM_BPSK; + INT_8 cTxPwr5GOFDM_QPSK; + INT_8 cTxPwr5GOFDM_16QAM; + INT_8 cTxPwr5GOFDM_Reserved; + INT_8 cTxPwr5GOFDM_48Mbps; + INT_8 cTxPwr5GOFDM_54Mbps; + + INT_8 cTxPwr5GHT20_BPSK; + INT_8 cTxPwr5GHT20_QPSK; + INT_8 cTxPwr5GHT20_16QAM; + INT_8 cTxPwr5GHT20_MCS5; + INT_8 cTxPwr5GHT20_MCS6; + INT_8 cTxPwr5GHT20_MCS7; + + INT_8 cTxPwr5GHT40_BPSK; + INT_8 cTxPwr5GHT40_QPSK; + INT_8 cTxPwr5GHT40_16QAM; + INT_8 cTxPwr5GHT40_MCS5; + INT_8 cTxPwr5GHT40_MCS6; + INT_8 cTxPwr5GHT40_MCS7; +} TX_PWR_PARAM_T, *P_TX_PWR_PARAM_T; + +typedef struct _PWR_5G_OFFSET_T { + INT_8 cOffsetBand0; /* 4.915-4.980G */ + INT_8 cOffsetBand1; /* 5.000-5.080G */ + INT_8 cOffsetBand2; /* 5.160-5.180G */ + INT_8 cOffsetBand3; /* 5.200-5.280G */ + INT_8 cOffsetBand4; /* 5.300-5.340G */ + INT_8 cOffsetBand5; /* 5.500-5.580G */ + INT_8 cOffsetBand6; /* 5.600-5.680G */ + INT_8 cOffsetBand7; /* 5.700-5.825G */ +} PWR_5G_OFFSET_T, *P_PWR_5G_OFFSET_T; + +typedef struct _PWR_PARAM_T { + UINT_32 au4Data[28]; + UINT_32 u4RefValue1; + UINT_32 u4RefValue2; +} PWR_PARAM_T, *P_PWR_PARAM_T; + +typedef struct _MITIGATED_PWR_BY_CH_BY_MODE { + UINT_8 channel; + INT_8 mitigatedCckDsss; + INT_8 mitigatedOfdm; + INT_8 mitigatedHt20; + INT_8 mitigatedHt40; +} MITIGATED_PWR_BY_CH_BY_MODE, *P_MITIGATED_PWR_BY_CH_BY_MODE; + +typedef struct _FCC_TX_PWR_ADJUST_T { + UINT_8 fgFccTxPwrAdjust; + UINT_8 uOffsetCCK; + UINT_8 uOffsetHT20; + UINT_8 uOffsetHT40; + UINT_8 aucChannelCCK[2]; + UINT_8 aucChannelHT20[2]; + UINT_8 aucChannelHT40[2]; +} FCC_TX_PWR_ADJUST, *P_FCC_TX_PWR_ADJUST; + +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-248]; + UINT_8 aucChannelBandEdge[2]; + UINT_16 u2SizeOfNvram; + INT_8 bTxPowerLimitEnable2G; + INT_8 cTxBackOffMaxPower2G; + INT_8 bTxPowerLimitEnable5G; + INT_8 cTxBackOffMaxPower5G; + + /* 256 bytes of function data */ + UINT_16 u2Part2OwnVersion; + UINT_16 u2Part2PeerVersion; + UINT_8 uc2G4BwFixed20M; + UINT_8 uc5GBwFixed20M; + UINT_8 ucEnable5GBand; + UINT_8 aucPreTailReserved; + UINT_8 uc2GRssiCompensation; + UINT_8 uc5GRssiCompensation; + UINT_8 fgRssiCompensationValidbit; + UINT_8 ucRxAntennanumber; + /*support tx power back off [start]*/ + MITIGATED_PWR_BY_CH_BY_MODE arRlmMitigatedPwrByChByMode[40]; + UINT_8 fgRlmMitigatedPwrByChByMode; + FCC_TX_PWR_ADJUST rFccTxPwrAdjust; + /*support tx power back off [end]*/ + UINT_8 aucTailReserved[768 - 12 - 211]; +} MT6620_CFG_PARAM_STRUCT, *P_MT6620_CFG_PARAM_STRUCT, WIFI_CFG_PARAM_STRUCT, *P_WIFI_CFG_PARAM_STRUCT; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifndef DATA_STRUCT_INSPECTING_ASSERT +#define DATA_STRUCT_INSPECTING_ASSERT(expr) \ +{ \ + switch (0) {case 0: case (expr): default:; } \ +} +#endif + +#define CFG_FILE_WIFI_REC_SIZE sizeof(WIFI_CFG_PARAM_STRUCT) +#define EXTEND_NVRAM_SIZE 1024 + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#ifndef _lint +/* We don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + * We'll need this to guarantee the same member order in different structures + * to simply handling effort in some functions. + */ +static inline VOID nvramOffsetCheck(VOID) +{ + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part2OwnVersion) == 256); + + DATA_STRUCT_INSPECTING_ASSERT(sizeof(WIFI_CFG_PARAM_STRUCT) == EXTEND_NVRAM_SIZE); + + DATA_STRUCT_INSPECTING_ASSERT((OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucEFUSE) & 0x0001) == 0); + + DATA_STRUCT_INSPECTING_ASSERT((OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucRegSubbandInfo) & 0x0001) == 0); +} +#endif + +#endif /* _CFG_WIFI_FILE_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/config.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/config.h new file mode 100644 index 0000000000000..6fa3a23a54e81 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/config.h @@ -0,0 +1,974 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#ifdef MT6620 +#undef MT6620 +#endif + +#ifndef MT6628 +#define MT6628 +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* 2 Flags for OS capability */ + +#define MTK_WCN_SINGLE_MODULE 0 /* 1: without WMT */ + +#ifdef LINUX +#ifdef CONFIG_X86 +#define MTK_WCN_HIF_SDIO 0 +#else +#define MTK_WCN_HIF_SDIO 0 /* samp */ +#endif +#else +#define MTK_WCN_HIF_SDIO 0 +#endif + +#if (CFG_SUPPORT_AEE == 1) +#define CFG_ENABLE_AEE_MSG 1 +#else +#define CFG_ENABLE_AEE_MSG 0 +#endif + +#if CFG_ENABLE_AEE_MSG +#include +#endif + +/* 2 Flags for Driver Features */ +#define CFG_TX_FRAGMENT 1 /* + * !< 1: Enable TX fragmentation + * 0: Disable + */ +#define CFG_SUPPORT_PERFORMANCE_TEST 0 /*Only for performance Test */ + +#define CFG_COUNTRY_CODE NULL /* "US" */ + +#ifndef LINUX +#define CFG_FW_FILENAME L"WIFI_RAM_CODE" +#define CFG_FW_FILENAME_E6 L"WIFI_RAM_CODE_E6" +#else +#define CFG_FW_FILENAME "WIFI_RAM_CODE" +#endif +#ifndef LINUX +#define CFG_SUPPORT_CFG_FILE 0 +#else +#define CFG_SUPPORT_CFG_FILE 1 +#endif + +#define CFG_SUPPORT_FCC_DYNAMIC_TX_PWR_ADJUST 0 /* Support FCC/CE Dynamic Tx Power Adjust */ + +#define CFG_SUPPORT_CE_FCC_TXPWR_LIMIT 0 /* Support CE FCC Tx Power limit */ + +#define CFG_SUPPORT_802_11D 1 /* + * !< 1(default): Enable 802.11d + * 0: Disable + */ + +#define CFG_SUPPORT_RRM 0 /* Radio Reasource Measurement (802.11k) */ +#define CFG_SUPPORT_DFS 1 /* DFS (802.11h) */ + +#if (CFG_SUPPORT_DFS == 1) /* Add by Enlai */ +#define CFG_SUPPORT_QUIET 1 /* Quiet (802.11h) */ +#define CFG_SUPPORT_SPEC_MGMT 1 /* Spectrum Management (802.11h): TPC and DFS */ +#else +#define CFG_SUPPORT_QUIET 0 /* Quiet (802.11h) */ +#define CFG_SUPPORT_SPEC_MGMT 0 /* Spectrum Management (802.11h): TPC and DFS */ +#endif + +#define CFG_SUPPORT_RX_RDG 0 /* 11n feature. RX RDG capability */ +#define CFG_SUPPORT_MFB 0 /* 802.11n MCS Feedback responder */ +#define CFG_SUPPORT_RX_STBC 1 /* 802.11n RX STBC (1SS) */ +#define CFG_SUPPORT_RX_SGI 1 /* 802.11n RX short GI for both 20M and 40M BW */ +#define CFG_SUPPORT_RX_HT_GF 1 /* 802.11n RX HT green-field capability */ + +#define CFG_SUPPORT_ROAMING_ENC 0 /* enahnced roaming */ +#define CFG_SUPPORT_ROAMING_RETRY 1 /* enahnced roaming */ + +#define CFG_SUPPORT_TDLS 1 /* IEEE802.11z TDLS */ +#define CFG_SUPPORT_TDLS_DBG 0 /* TDLS debug */ +#define CFG_SUPPORT_STATISTICS 1 +#define CFG_SUPPORT_DBG_POWERMODE 1 /* for debugging power always active mode */ + +#define CFG_SUPPORT_TXR_ENC 0 /* enhanced tx rate switch */ + +#define CFG_SUPPORT_PERSIST_NETDEV 0 /* create NETDEV when system bootup */ + +#define CFG_FORCE_USE_20BW 1 + +#define CFG_SUPPORT_RN 1 + +#define CFG_SUPPORT_SET_CAM_BY_PROC 1 + +#define CFG_SUPPORT_RSN_SCORE 0 + +#define CFG_SUPPORT_GAMING_MODE 1 + +#define CFG_SUPPORT_OSHARE 1 + +#define CFG_SUPPORT_WAPI 1 + +/*------------------------------------------------------------------------------ + * Flags of WPA3 support + *------------------------------------------------------------------------------ + */ + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0) +#define CFG_SUPPORT_WPA3 0 +#else +#define CFG_SUPPORT_WPA3 1 +#endif + +#if (CFG_SUPPORT_WPA3 == 1) +#define CFG_REFACTORY_PMKSA 1 +#else +#define CFG_REFACTORY_PMKSA 0 +#endif + +/*------------------------------------------------------------------------------ + * Flags of Random MAC support + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_SCAN_RANDOM_MAC 1 + +/*------------------------------------------------------------------------------ + * 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_NATIVE_802_11 0 +#define CFG_TX_MAX_PKT_SIZE 1600 +#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 + +#endif + +/* 2 Flags for Driver Parameters */ +/*------------------------------------------------------------------------------ + * Flags for EHPI Interface in Colibri Platform + *------------------------------------------------------------------------------ + */ +#define CFG_EHPI_FASTER_BUS_TIMING 0 /* + * !< 1: Do workaround for faster bus timing + * 0(default): Disable + */ + +/*------------------------------------------------------------------------------ + * Flags for HIFSYS Interface + *------------------------------------------------------------------------------ + */ +#ifdef _lint +#define _HIF_SDIO 0 /* samp */ +#endif + +#define CFG_SDIO_INTR_ENHANCE 1 /* + * !< 1(default): Enable SDIO ISR & TX/RX status enhance mode + * 0: Disable + */ +#define CFG_SDIO_RX_ENHANCE 0 /* + * !< 1(default): Enable SDIO ISR & TX/RX status enhance mode + * 0: Disable + */ +#define CFG_SDIO_TX_AGG 1 /* + * !< 1: Enable SDIO TX enhance + * mode(Multiple frames in single BLOCK CMD) + * 0(default): Disable + */ + +#define CFG_SDIO_RX_AGG 1 /* + * !< 1: Enable SDIO RX enhance + * mode(Multiple frames in single BLOCK CMD) + * 0(default): Disable + */ + +#if (CFG_SDIO_RX_AGG == 1) && (CFG_SDIO_INTR_ENHANCE == 0) +#error "CFG_SDIO_INTR_ENHANCE should be 1 once CFG_SDIO_RX_AGG equals to 1" +#elif (CFG_SDIO_INTR_ENHANCE == 1 || CFG_SDIO_RX_ENHANCE == 1) && (CFG_SDIO_RX_AGG == 0) +#error "CFG_SDIO_RX_AGG should be 1 once CFG_SDIO_INTR_ENHANCE and/or CFG_SDIO_RX_ENHANCE equals to 1" +#endif + +#define CFG_SDIO_MAX_RX_AGG_NUM 0 /* + * !< 1: Setting the maximum RX aggregation number + * 0(default): no limited + */ + +#ifdef WINDOWS_CE +#define CFG_SDIO_PATHRU_MODE 1 /* + * !< 1: Support pass through (PATHRU) mode + * 0: Disable + */ +#else +#define CFG_SDIO_PATHRU_MODE 0 /*!< 0: Always disable if WINDOWS_CE is not defined */ +#endif + +#define CFG_MAX_RX_ENHANCE_LOOP_COUNT 3 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Integration + *------------------------------------------------------------------------------ + */ +#if defined(MT6620) +#define MT6620_FPGA_BWCS 0 +#define MT6620_FPGA_V5 0 + +#if (MT6620_FPGA_BWCS == 1) && (MT6620_FPGA_V5 == 1) +#error +#endif + +#if (MTK_WCN_HIF_SDIO == 1) +#define CFG_MULTI_ECOVER_SUPPORT 1 +#elif !defined(LINUX) +#define CFG_MULTI_ECOVER_SUPPORT 1 +#else +#define CFG_MULTI_ECOVER_SUPPORT 0 +#endif + +#define CFG_ENABLE_CAL_LOG 0 +#define CFG_REPORT_RFBB_VERSION 0 + +#elif defined(MT6628) + +#define CFG_MULTI_ECOVER_SUPPORT 0 + +#define CFG_ENABLE_CAL_LOG 1 +#define CFG_REPORT_RFBB_VERSION 1 + +#endif + +#define CFG_CHIP_RESET_SUPPORT 1 + +#if defined(MT6628) +#define CFG_EMBED_FIRMWARE_BUILD_DATE_CODE 1 +#endif + +/*------------------------------------------------------------------------------ + * Flags for workaround + *------------------------------------------------------------------------------ + */ +#if defined(MT6620) && (MT6620_FPGA_BWCS == 0) && (MT6620_FPGA_V5 == 0) +#define MT6620_E1_ASIC_HIFSYS_WORKAROUND 0 +#else +#define MT6620_E1_ASIC_HIFSYS_WORKAROUND 0 +#endif + +/* SPM issue: suspend current is higher than deep idle */ +#define CFG_SPM_WORKAROUND_FOR_HOTSPOT 1 + +/*------------------------------------------------------------------------------ + * Flags for driver version + *------------------------------------------------------------------------------ + */ +#define CFG_DRV_OWN_VERSION \ + ((UINT_16)((NIC_DRIVER_MAJOR_VERSION << 8) | (NIC_DRIVER_MINOR_VERSION))) +#define CFG_DRV_PEER_VERSION ((UINT_16)0x0000) + +/*------------------------------------------------------------------------------ + * Flags for TX path which are OS dependent + *------------------------------------------------------------------------------ + */ +/*! NOTE(Kevin): If the Network buffer is non-scatter-gather like structure(without + * NETIF_F_FRAGLIST in LINUX), then we can set CFG_TX_BUFFER_IS_SCATTER_LIST to "0" + * for zero copy TX packets. + * For scatter-gather like structure, we set "1", driver will do copy frame to + * internal coalescing buffer before write it to FIFO. + */ +#if defined(LINUX) +#define CFG_TX_BUFFER_IS_SCATTER_LIST 1 /* + * !< 1: Do frame copy before write to TX FIFO. + * Used when Network buffer is scatter-gather. + * 0(default): Do not copy frame + */ +#else /* WINDOWS/WINCE */ +#define CFG_TX_BUFFER_IS_SCATTER_LIST 1 +#endif /* LINUX */ + +#if CFG_SDIO_TX_AGG || CFG_TX_BUFFER_IS_SCATTER_LIST +#define CFG_COALESCING_BUFFER_SIZE (CFG_TX_MAX_PKT_SIZE * NIC_TX_BUFF_SUM) +#else +#define CFG_COALESCING_BUFFER_SIZE (CFG_TX_MAX_PKT_SIZE) +#endif /* CFG_SDIO_TX_AGG || CFG_TX_BUFFER_IS_SCATTER_LIST */ + +/*------------------------------------------------------------------------------ + * Flags and Parameters for TX path + *------------------------------------------------------------------------------ + */ + +/*! Maximum number of SW TX packet queue */ +#define CFG_TX_MAX_PKT_NUM 4096 /* + * 256 must >= CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD * 2; + * or wmm will fail when queue is full + */ + +/*! Maximum number of SW TX CMD packet buffer */ +#define CFG_TX_MAX_CMD_PKT_NUM 32 + +/*! Maximum number of associated STAs */ +#define CFG_NUM_OF_STA_RECORD 20 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for RX path + *------------------------------------------------------------------------------ + */ + +/*! Max. descriptor number - sync. with firmware */ +#if CFG_SLT_SUPPORT +#define CFG_NUM_OF_RX0_HIF_DESC 42 +#else +#define CFG_NUM_OF_RX0_HIF_DESC 16 +#endif +#define CFG_NUM_OF_RX1_HIF_DESC 2 + +/*! Max. buffer hold by QM */ +#define CFG_NUM_OF_QM_RX_PKT_NUM 4096 + +/*! 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 +#define CFG_RX_BA_REORDERING_ENHANCEMENT 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 128 + +#define CFG_MAX_NUM_ROAM_BSS_LIST 64 + +#define CFG_MAX_COMMON_IE_BUF_LEN ((1500 * CFG_MAX_NUM_BSS_LIST) / 3) + +/*! Maximum size of Header buffer of each SCAN record */ +#define CFG_RAW_BUFFER_SIZE 1024 + +/*! Maximum size of IE buffer of each SCAN record */ +#define CFG_IE_BUFFER_SIZE 512 + +/*! Maximum number of STA records */ +#define CFG_MAX_NUM_STA_RECORD 32 + +#define CFG_GOOG_RCPI_THRESHOLD 90 +#define CFG_POOR_RCPI_THRESHOLD 67 +#define CFG_GOOG_RCPI_SCAN_SKIP_TIMES 3 +#define CFG_POOR_RCPI_SCAN_SKIP_TIMES 2 +/*------------------------------------------------------------------------------ + * Flags and Parameters for Power management + *------------------------------------------------------------------------------ + */ +#define CFG_ENABLE_FULL_PM 1 +#define CFG_ENABLE_WAKEUP_ON_LAN 0 +#if defined(CONFIG_ARCH_MT6755) || defined(CONFIG_ARCH_MT6735) || defined(CONFIG_ARCH_MT6735M) || \ + defined(CONFIG_ARCH_MT6753) || defined(CONFIG_ARCH_MT6580) +#define CFG_SUPPORT_WAKEUP_REASON_DEBUG 1 /* debug which packet wake up host */ +#else +#define CFG_SUPPORT_WAKEUP_REASON_DEBUG 0 /* debug which packet wake up host */ +#endif +#define CFG_INIT_POWER_SAVE_PROF ENUM_PSP_FAST_SWITCH + +#define CFG_INIT_ENABLE_PATTERN_FILTER_ARP 0 + +#define CFG_INIT_UAPSD_AC_BMP 0 /* (BIT(3) | BIT(2) | BIT(1) | BIT(0)) */ + +/* #define CFG_SUPPORT_WAPI 0 */ +#define CFG_SUPPORT_WPS 1 +#define CFG_SUPPORT_WPS2 1 + +#if (CFG_REFACTORY_PMKSA == 0) +/*------------------------------------------------------------------------------ + * 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 + */ +#endif +/*------------------------------------------------------------------------------ + * Auto Channel Selection maximun channel number + *------------------------------------------------------------------------------ + */ +#define MAX_CHN_NUM 39 /* CH1~CH14, CH36~CH48, CH52~CH64, CH100~CH144, CH149~CH165 */ +#define MAX_2G_BAND_CHN_NUM 14 + +/*------------------------------------------------------------------------------ + * FAST SCAN + *------------------------------------------------------------------------------ + */ +#define CFG_ENABLE_FAST_SCAN 0 +#define CFG_CN_SUPPORT_CLASS121 0 /* Add Class 121, 5470-5725MHz, support for China domain */ +#if CFG_ENABLE_FAST_SCAN + #define CFG_FAST_SCAN_DWELL_TIME 40 + #define CFG_FAST_SCAN_REG_DOMAIN_DEF_IDX 10 +#endif +/*------------------------------------------------------------------------------ + * Flags and Parameters for Ad-Hoc + *------------------------------------------------------------------------------ + */ +#define CFG_INIT_ADHOC_FREQ (2462000) +#define CFG_INIT_ADHOC_MODE AD_HOC_MODE_MIXED_11BG +#define CFG_INIT_ADHOC_BEACON_INTERVAL (100) +#define CFG_INIT_ADHOC_ATIM_WINDOW (0) + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Maximum Scan SSID number + *------------------------------------------------------------------------------ + */ +#define CFG_MULTI_SSID_SCAN 1 +#if CFG_TC1_FEATURE +#define CFG_NLO_MSP 1 /* NLO/PNO Multiple Scan Plan */ +#else +#define CFG_NLO_MSP 0 +#endif +#define CFG_SUPPORT_SCHED_SCN_SSID_SETS 1 /*Sched-scan support hidden SSID*/ +#define CFG_SCAN_SSID_MAX_NUM (10) + + +#if CFG_SUPPORT_SCHED_SCN_SSID_SETS +#define CFG_SCAN_HIDDEN_SSID_MAX_NUM (7) +#endif +#define CFG_SCAN_SSID_MATCH_MAX_NUM (16) + +#define CFG_SUPPORT_DETECT_ATHEROS_AP 0 + +#define CFG_SCAN_ABORT_HANDLE 1 +/*------------------------------------------------------------------------------ + * Flags and Parameters for Support EMI DEBUG + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_EMI_DEBUG 1 + + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Load Setup Default + *------------------------------------------------------------------------------ + */ + +/*------------------------------------------------------------------------------ + * Flags for enable 802.11A Band setting + *------------------------------------------------------------------------------ + */ + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Interrupt Process + *------------------------------------------------------------------------------ + */ +#if defined(_HIF_SDIO) && defined(WINDOWS_CE) +#define CFG_IST_LOOP_COUNT 8 +#else +#define CFG_IST_LOOP_COUNT 8 +#endif /* _HIF_SDIO */ + +#define CFG_INT_WRITE_CLEAR 0 + +#if defined(LINUX) +#define CFG_DBG_GPIO_PINS 0 /* if 1, use MT6516 GPIO pin to log TX behavior */ +#endif + +/* 2 Flags for Driver Debug Options */ +/*------------------------------------------------------------------------------ + * Flags of TX Debug Option. NOTE(Kevin): Confirm with SA before modifying following flags. + *------------------------------------------------------------------------------ + */ +#define CFG_DBG_MGT_BUF 1 /* + * !< 1: Debug statistics usage of MGMT Buffer + * 0: Disable + */ + +#define CFG_HIF_STATISTICS 0 + +#define CFG_HIF_RX_STARVATION_WARNING 0 + +#define CFG_STARTUP_DEBUG 0 + +#define CFG_RX_PKTS_DUMP 1 + +/*------------------------------------------------------------------------------ + * Flags of Firmware Download Option. + *------------------------------------------------------------------------------ + */ +#define CFG_ENABLE_FW_DOWNLOAD 1 + +#define CFG_ENABLE_FW_DOWNLOAD_ACK 1 +#define CFG_ENABLE_FW_ENCRYPTION 1 + +#if defined(MT6628) +#define CFG_ENABLE_FW_DOWNLOAD_AGGREGATION 0 +#define CFG_ENABLE_FW_DIVIDED_DOWNLOAD 1 +#endif + +#if defined(MT6620) +#if MT6620_FPGA_BWCS +#define CFG_FW_LOAD_ADDRESS 0x10014000 +#define CFG_OVERRIDE_FW_START_ADDRESS 0 +#define CFG_FW_START_ADDRESS 0x10014001 +#elif MT6620_FPGA_V5 +#define CFG_FW_LOAD_ADDRESS 0x10008000 +#define CFG_OVERRIDE_FW_START_ADDRESS 0 +#define CFG_FW_START_ADDRESS 0x10008001 +#else +#define CFG_FW_LOAD_ADDRESS 0x10008000 +#define CFG_OVERRIDE_FW_START_ADDRESS 0 +#define CFG_FW_START_ADDRESS 0x10008001 +#endif +#elif defined(MT6628) +#define CFG_FW_LOAD_ADDRESS 0x00060000 +#define CFG_OVERRIDE_FW_START_ADDRESS 1 +#define CFG_FW_START_ADDRESS 0x00060000 +#define CFG_START_ADDRESS_IS_1ST_SECTION_ADDR 1 +#endif + +/*------------------------------------------------------------------------------ + * Flags of Bluetooth-over-WiFi (BT 3.0 + HS) support + *------------------------------------------------------------------------------ + */ + +#ifdef LINUX +#ifdef CONFIG_X86 +#define CFG_ENABLE_BT_OVER_WIFI 0 +#else +#define CFG_ENABLE_BT_OVER_WIFI 1 +#endif +#else +#define CFG_ENABLE_BT_OVER_WIFI 0 +#endif + +#define CFG_BOW_SEPARATE_DATA_PATH 1 + +#define CFG_BOW_PHYSICAL_LINK_NUM 4 + +#define CFG_BOW_TEST 0 + +#define CFG_BOW_LIMIT_AIS_CHNL 1 + +#define CFG_BOW_SUPPORT_11N 0 + +#define CFG_BOW_RATE_LIMITATION 1 + +/*------------------------------------------------------------------------------ + * Flags of Wi-Fi Direct support + *------------------------------------------------------------------------------ + */ +#ifdef LINUX +#ifdef CONFIG_X86 +#define CFG_ENABLE_WIFI_DIRECT 0 +#define CFG_SUPPORT_802_11W 1 +#else +#define CFG_ENABLE_WIFI_DIRECT 1 +#define CFG_SUPPORT_802_11W 1 +#endif +#else +#define CFG_ENABLE_WIFI_DIRECT 0 +#define CFG_SUPPORT_802_11W 0 /* Not support at WinXP */ +#endif + +#define CFG_SUPPORT_PERSISTENT_GROUP 0 + +#define CFG_TEST_WIFI_DIRECT_GO 0 + +#define CFG_TEST_ANDROID_DIRECT_GO 0 + +#define CFG_UNITEST_P2P 0 + +/* + * Enable cfg80211 option after Android 2.2(Froyo) is suggested, + * cfg80211 on linux 2.6.29 is not mature yet + */ +#define CFG_ENABLE_WIFI_DIRECT_CFG_80211 1 + +#define CFG_SUPPORT_HOTSPOT_OPTIMIZATION 1 +#define CFG_HOTSPOT_OPTIMIZATION_BEACON_INTERVAL 300 +#define CFG_HOTSPOT_OPTIMIZATION_DTIM 1 + +#define CFG_AUTO_CHANNEL_SEL_SUPPORT 1 + +#define CFG_SUPPORT_SOFTAP_WPA3 1 + +#define CFG_SET_BCN_CAPINFO_BY_DRIVER 0 + + +/*------------------------------------------------------------------------------ + * 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 1000 + +/*------------------------------------------------------------------------------ + * Migration Option + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_ADHOC 0 +#define CFG_SUPPORT_AAA 1 + +#define CFG_SUPPORT_BCM 0 +#define CFG_SUPPORT_BCM_BWCS 0 +#define CFG_SUPPORT_BCM_BWCS_DEBUG 0 + +#define CFG_SUPPORT_RDD_TEST_MODE 0 + +#define CFG_SUPPORT_PWR_MGT 1 + +#define CFG_RSN_MIGRATION 1 + +#define CFG_PRIVACY_MIGRATION 1 + +#define CFG_ENABLE_HOTSPOT_PRIVACY_CHECK 1 + +#define CFG_MGMT_FRAME_HANDLING 1 + +#define CFG_MGMT_HW_ACCESS_REPLACEMENT 0 + +#if CFG_SUPPORT_PERFORMANCE_TEST + +#else + +#endif + +#define CFG_SUPPORT_AIS_5GHZ 1 +#define CFG_SUPPORT_BEACON_CHANGE_DETECTION 0 + +/*------------------------------------------------------------------------------ + * Option for NVRAM and Version Checking + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_NVRAM 1 +#define CFG_NVRAM_EXISTENCE_CHECK 1 +#define CFG_SW_NVRAM_VERSION_CHECK 1 +#define CFG_SUPPORT_NIC_CAPABILITY 1 + +/*------------------------------------------------------------------------------ + * CONFIG_TITLE : Stress Test Option + * OWNER : Puff Wen + * Description : For stress test only. DO NOT enable it while normal operation + *------------------------------------------------------------------------------ + */ +#define CFG_STRESS_TEST_SUPPORT 0 + +/*------------------------------------------------------------------------------ + * Flags for LINT + *------------------------------------------------------------------------------ + */ +#define LINT_SAVE_AND_DISABLE /*lint -save -e* */ + +#define LINT_RESTORE /*lint -restore */ + +#define LINT_EXT_HEADER_BEGIN LINT_SAVE_AND_DISABLE + +#define LINT_EXT_HEADER_END LINT_RESTORE + +/*------------------------------------------------------------------------------ + * Flags of Features + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_MULTITHREAD 0 + +#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_DYNAMIC_ROAM 0 +#define CFG_SUPPORT_SWCR 1 + +#define CFG_SUPPORT_ANTI_PIRACY 1 + +#define CFG_SUPPORT_OSC_SETTING 1 + +#define CFG_SUPPORT_P2P_RSSI_QUERY 0 + +#define CFG_SUPPORT_CHNL_CONFLICT_REVISE 0 + +#define CFG_SHOW_MACADDR_SOURCE 1 +#define CFG_BSS_DISAPPEAR_THRESOLD 20 /*unit: sec */ +#define CFG_NEIGHBOR_AP_CHANNEL_NUM 50 +#define CFG_MAX_NUM_OF_CHNL_INFO 50 +#define CFG_SELECT_BSS_BASE_ON_MULTI_PARAM 1 +#define CFG_SUPPORT_VO_ENTERPRISE 1 +#define CFG_NEIGHBOR_AP_CHANNEL_NUM 50 +#define CFG_SUPPORT_WMM_AC 1 + +#if CFG_SUPPORT_VO_ENTERPRISE +#define CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT 1 +#define CFG_SUPPORT_802_11R 1 +#define CFG_SUPPORT_802_11V 1 +#define CFG_SUPPORT_802_11K 1 +#else +#define CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT 0 +#define CFG_SUPPORT_802_11R 0 +#define CFG_SUPPORT_802_11V 0 +#define CFG_SUPPORT_802_11K 0 +#endif + +#define CFG_SUPPORT_802_11V_TIMING_MEASUREMENT 0 +#define CFG_SUPPORT_OKC 1 + +#if (CFG_SUPPORT_802_11V_TIMING_MEASUREMENT == 1) || CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT == 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 + +#define WNM_UNIT_TEST 0 + +#define CFG_SUPPORT_PPR2 1 +#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 + +#define CFG_SUPPORT_CPU_BOOST 0 + + +#define CFG_SUPPORT_TX_POWER_BACK_OFF 1 + +#define CFG_SUPPORT_FCC_POWER_BACK_OFF 0 + + +#define CFG_SUPPORT_P2P_ECSA 0 + +#define CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP 0 + +#define CFG_SUPPORT_RLM_ACT_NETWORK 1 + +#define CFG_SUPPORT_P2P_EAP_FAIL_WORKAROUND 1 + +/*------------------------------------------------------------------------------ + * Flags of Packet Lifetime Profiling Mechanism + *------------------------------------------------------------------------------ + */ +#define CFG_ENABLE_PKT_LIFETIME_PROFILE 1 + +#define CFG_ENABLE_PER_STA_STATISTICS 1 +#define CFG_ENABLE_PER_STA_STATISTICS_LOG 1 + +#define CFG_PRINT_RTP_PROFILE 0 /* If want to enable WFD Debug, please change it to 1. */ +#define CFG_PRINT_RTP_SN_SKIP 0 + +#define CFG_SUPPORT_PWR_LIMIT_COUNTRY 1 +#define CFG_SUPPORT_MTK_SYNERGY 1 +/*------------------------------------------------------------------------------ + * Flags of bus error tolerance + *------------------------------------------------------------------------------ + */ +#define CFG_FORCE_RESET_UNDER_BUS_ERROR 0 + +/*------------------------------------------------------------------------------ + * Build Date Code Integration + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_BUILD_DATE_CODE 1 + +/*------------------------------------------------------------------------------ + * Flags for prepare the FW compile flag + *------------------------------------------------------------------------------ + */ +#define COMPILE_FLAG0_GET_STA_LINK_STATUS (1 << 0) +#define COMPILE_FLAG0_WFD_ENHANCEMENT_PROTECT (1 << 1) + +/*------------------------------------------------------------------------------ + * Flags of Batch Scan SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_BATCH_SCAN 0 +#define CFG_BATCH_MAX_MSCAN 2 + +/*------------------------------------------------------------------------------ + * Flags of G-Scan SUPPORT and P-SCN SUPPORT, GSCN is one type of PSCN + *------------------------------------------------------------------------------ + */ + +#define CFG_SUPPORT_SCN_PSCN 1 +#if CFG_SUPPORT_SCN_PSCN +#define CFG_SUPPORT_GSCN 0 /* GSCN can be disabled here */ +#else +#define CFG_SUPPORT_GSCN 0 +#endif + +/*------------------------------------------------------------------------------ + * Flags of Channel Environment SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_GET_CH_ENV 1 + +/*------------------------------------------------------------------------------ + * Flags of THERMO_THROTTLING SUPPORT + *------------------------------------------------------------------------------ + */ + +#define CFG_SUPPORT_THERMO_THROTTLING 1 +#define WLAN_INCLUDE_PROC 1 + +#if CFG_TC10_FEATURE +#define WLAN_INCLUDE_SYS 1 +#else +#define WLAN_INCLUDE_SYS 0 +#endif + +#define CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE 1 +#define CFG_IGNORE_INVALID_AUTH_TSN 0 +/*------------------------------------------------------------------------------ + * Flags of drop multicast packet when device suspend + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_DROP_MC_PACKET 0 + +/*------------------------------------------------------------------------------ + * Flags of NCHO SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_NCHO 0 +#define CFG_SUPPORT_NCHO_AUTO_ENABLE 0 + +#define CFG_SUPPORT_ADD_CONN_AP 1 + + +/*------------------------------------------------------------------------------ + * Flags of Key Word Exception Mechanism + *------------------------------------------------------------------------------ + */ +#define CFG_ENABLE_KEYWORD_EXCEPTION_MECHANISM 1 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + + +/*Driver naming rule: Mdoule_AndroidVersion_Branch_Date_SerialNum*/ +/*Module: Gen2(0x01)/Gen3(0x02) | kernel-3.10(x00)/3.18(0x10),kernel-4.4(0x20)*/ +/*AndroidVersion:7.0->70*/ +/*Branch: 00 for Trunk, 01->mp1,02->mp2*/ +/*Date: relase date*/ +/*Serial Number :start form 1*/ +#define WIFI_MODULE "11" +#define ANDROID_VER "70" +#define RELEASE_DATE "20170324" +#define SERIAL_NUMBER "1" +#define SP_BRANCH "TC10" +#define WIFI_DRIVER_VERSION WIFI_MODULE "_" ANDROID_VER "_" RELEASE_DATE "_" SERIAL_NUMBER "_" SP_BRANCH + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _CONFIG_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/debug.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/debug.h new file mode 100644 index 0000000000000..174f260edab8c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/debug.h @@ -0,0 +1,508 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _DEBUG_H +#define _DEBUG_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#ifndef BUILD_QA_DBG +#define BUILD_QA_DBG 0 +#endif + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_typedef.h" + +extern UINT_8 aucDebugModule[]; + +extern UINT_32 u4DriverLogLevel; +extern UINT_32 u4FwLogLevel; + +extern void set_logtoomuch_enable(int value); +extern int get_logtoomuch_enable(void); + +/******************************************************************************* +* 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) + +#define DBG_LOG_LEVEL_OFF (DBG_CLASS_ERROR | DBG_CLASS_WARN | DBG_CLASS_INFO | DBG_CLASS_STATE) +#define DBG_LOG_LEVEL_DEFAULT (DBG_LOG_LEVEL_OFF | DBG_CLASS_EVENT | DBG_CLASS_TRACE) +#define DBG_LOG_LEVEL_EXTREME (DBG_LOG_LEVEL_DEFAULT | DBG_CLASS_LOUD | DBG_CLASS_TEMP) + +enum PKT_PHASE { + PHASE_XMIT_RCV, + PHASE_ENQ_QM, + PHASE_HIF_TX, +}; +#if defined(LINUX) +#define DBG_PRINTF_64BIT_DEC "lld" + +#else /* Windows */ +#define DBG_PRINTF_64BIT_DEC "I64d" + +#endif +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Define debug module index */ +typedef enum _ENUM_DBG_MODULE_T { + DBG_INIT_IDX = 0, /* For driver initial */ + DBG_HAL_IDX, /* For HAL(HW) Layer */ + DBG_INTR_IDX, /* For Interrupt */ + DBG_REQ_IDX, + DBG_TX_IDX, + DBG_RX_IDX, + DBG_RFTEST_IDX, /* For RF test mode */ + DBG_EMU_IDX, /* Developer specific */ + + DBG_SW1_IDX, /* Developer specific */ + DBG_SW2_IDX, /* Developer specific */ + DBG_SW3_IDX, /* Developer specific */ + DBG_SW4_IDX, /* Developer specific */ + + DBG_HEM_IDX, /* HEM */ + DBG_AIS_IDX, /* AIS */ + DBG_RLM_IDX, /* RLM */ + DBG_MEM_IDX, /* RLM */ + DBG_CNM_IDX, /* CNM */ + DBG_RSN_IDX, /* RSN */ + DBG_BSS_IDX, /* BSS */ + DBG_SCN_IDX, /* SCN */ + DBG_SAA_IDX, /* SAA */ + DBG_AAA_IDX, /* AAA */ + DBG_P2P_IDX, /* P2P */ + DBG_QM_IDX, /* QUE_MGT */ + DBG_SEC_IDX, /* SEC */ + DBG_BOW_IDX, /* BOW */ + DBG_WAPI_IDX, /* WAPI */ + DBG_ROAMING_IDX, /* ROAMING */ + DBG_TDLS_IDX, /* TDLS *//* CFG_SUPPORT_TDLS */ + DBG_OID_IDX, + DBG_NIC_IDX, + DBG_WNM_IDX, + DBG_WMM_IDX, + + DBG_MODULE_NUM /* Notice the XLOG check */ +} ENUM_DBG_MODULE_T; +enum PKT_TYPE { + PKT_RX, + PKT_TX, + PKT_TX_DONE +}; + +typedef enum _ENUM_DBG_SCAN_T { + DBG_SCAN_WRITE_BEFORE, /*Start send ScanRequest*/ + DBG_SCAN_WRITE_DONE, /*hal write success and ScanRequest done*/ +} ENUM_DBG_SCAN_T; + +struct WLAN_DEBUG_INFO { + BOOLEAN fgVoE5_7Test:1; + BOOLEAN fgReserved:7; +}; + +/* Define debug TRAFFIC_CLASS index */ + +typedef enum _ENUM_DEBUG_TRAFFIC_CLASS_INDEX_T { + DEBUG_TC0_INDEX = 0, /* HIF TX0: AC0 packets */ + DEBUG_TC1_INDEX, /* HIF TX0: AC1 packets & non-QoS packets */ + DEBUG_TC2_INDEX, /* HIF TX0: AC2 packets */ + DEBUG_TC3_INDEX, /* HIF TX0: AC3 packets */ + DEBUG_TC4_INDEX, /* HIF TX1: Command packets or 802.1x packets */ + DEBUG_TC5_INDEX, /* HIF TX0: BMCAST packets */ + DEBUG_TC_NUM /* Maximum number of Traffic Classes. */ +} ENUM_DEBUG_TRAFFIC_CLASS_INDEX_T; + +/* XLOG */ +/* #define XLOG_DBG_MODULE_IDX 28 */ /* DBG_MODULE_NUM */ +/* #if (XLOG_DBG_MODULE_IDX != XLOG_DBG_MODULE_IDX) */ +/* #error "Please modify the DBG_MODULE_NUM and make sure this include at XLOG" */ +/* #endif */ + +/* Define who owns developer specific index */ +#define DBG_YARCO_IDX DBG_SW1_IDX +#define DBG_KEVIN_IDX DBG_SW2_IDX +#define DBG_CMC_IDX DBG_SW3_IDX +#define DBG_GEORGE_IDX DBG_SW4_IDX + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/* Debug print format string for the OS system time */ +#define OS_SYSTIME_DBG_FORMAT "0x%08x" + +/* Debug print argument for the OS system time */ +#define OS_SYSTIME_DBG_ARGUMENT(systime) (systime) + +/* Debug print format string for the MAC Address */ +#define MACSTR "%pM" +/* "%02x:%02x:%02x:%02x:%02x:%02x" */ + +/* Debug print argument for the MAC Address */ +#define MAC2STR(a) a +/* ((PUINT_8)a)[0], ((PUINT_8)a)[1], ((PUINT_8)a)[2], ((PUINT_8)a)[3], ((PUINT_8)a)[4], ((PUINT_8)a)[5] */ + +#if (CFG_REFACTORY_PMKSA == 1) +#define PMKSTR "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%03x%02x%02x" +#endif + +/* The pre-defined format to dump the value of a varaible with its name shown. */ +#define DUMPVAR(variable, format) (#variable " = " format "\n", variable) + +/* The pre-defined format to dump the MAC type value with its name shown. */ +#define DUMPMACADDR(addr) (#addr " = %pM\n", (addr)) + +/* for HIDE some information for user load */ +#ifdef BUILD_QA_DBG +#define HIDE(_str) _str +#else +#define HIDE(_str) "***" +#endif + +/* 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 kalPrint +#define LOG_FUNC_LIMITED kalPrintLimited + +#if defined(LINUX) +#define DBGLOG(_Module, _Class, _Fmt, ...) \ + do { \ + if ((aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) == 0) \ + break; \ + LOG_FUNC("%s:(" #_Module " " #_Class ") " _Fmt, __func__, ##__VA_ARGS__); \ + } while (0) + +#define DBGLOGLIMITED(_Module, _Class, _Fmt, ...) \ + do { \ + if ((aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) == 0) \ + break; \ + LOG_FUNC_LIMITED("%s:(" #_Module " " #_Class ") " _Fmt, __func__, ##__VA_ARGS__); \ + } while (0) +#else +#define DBGLOG(_Module, _Class, _Fmt) +#define DBGLOGLIMITED(_Module, _Class, _Fmt) +#endif + +#if DBG + +#define TMP_BUF_LEN 256 +#define TMP_WBUF_LEN (TMP_BUF_LEN * 2) + +extern PINT_16 g_wbuf_p; +extern PINT_8 g_buf_p; + +/* If __FUNCTION__ is already defined by compiler, we just use it. */ +#if defined(__func__) +#define DEBUGFUNC(_Func) +#else +#define DEBUGFUNC(_Func) \ + static const char __func__[] = _Func +#endif + +#define DBGLOG_MEM8(_Module, _Class, _StartAddr, _Length) \ + { \ + if (aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) { \ + LOG_FUNC("%s:(" #_Module " " #_Class ")\n", __func__); \ + dumpMemory8((PUINT_8) (_StartAddr), (UINT_32) (_Length)); \ + } \ + } + +#define DBGLOG_MEM32(_Module, _Class, _StartAddr, _Length) \ + { \ + if (aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) { \ + LOG_FUNC("%s:(" #_Module " " #_Class ")\n", __func__); \ + dumpMemory32((PUINT_32) (_StartAddr), (UINT_32) (_Length)); \ + } \ + } + +#undef ASSERT + +#ifdef _lint +#define ASSERT(_exp) \ + { \ + if (!(_exp)) { \ + do {} while (1); \ + } \ + } +#else +#define ASSERT(_exp) \ + { \ + if (!(_exp)) { \ + LOG_FUNC("Assertion failed: %s:%d %s\n", __FILE__, __LINE__, #_exp); \ + kalBreakPoint(); \ + } \ + } +#endif /* _lint */ + +#define ASSERT_REPORT(_exp, _fmt) \ + { \ + if (!(_exp)) { \ + LOG_FUNC("Assertion failed: %s:%d %s\n", __FILE__, __LINE__, #_exp); \ + LOG_FUNC _fmt; \ + kalBreakPoint(); \ + } \ + } + +#define DISP_STRING(_str) _str + +#else /* !DBG */ + +#define DEBUGFUNC(_Func) +#define INITLOG(_Fmt) +#define ERRORLOG(_Fmt) +#define WARNLOG(_Fmt) + +#define DBGLOG_MEM8(_Module, _Class, _StartAddr, _Length) \ + { \ + if (aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) { \ + LOG_FUNC("%s: (" #_Module " " #_Class ")\n", __func__); \ + dumpMemory8((PUINT_8) (_StartAddr), (UINT_32) (_Length)); \ + } \ + } + +#define DBGLOG_MEM32(_Module, _Class, _StartAddr, _Length) + +#undef ASSERT + +#if BUILD_QA_DBG +#if defined(LINUX) /* For debugging in Linux w/o GDB */ +#define ASSERT(_exp) \ + { \ + if (!(_exp)) { \ + LOG_FUNC("Assertion failed: %s:%d (%s)\n", __FILE__, __LINE__, #_exp); \ + kalBreakPoint(); \ + } \ + } + +#define ASSERT_REPORT(_exp, _fmt) \ + { \ + if (!(_exp)) { \ + 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)) { \ + 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)) { \ + 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)) { \ + kalBreakPoint(); \ + } \ + } + +#define ASSERT_REPORT(_exp, _fmt) \ + { \ + if (!(_exp)) { \ + kalBreakPoint(); \ + } \ + } +#endif /* WINDOWS_CE */ +#endif /* LINUX */ +#else +#define ASSERT(_exp) \ + { \ + if (!(_exp)) { \ + LOG_FUNC("Warning at %s:%d (%s)\n", __func__, __LINE__, #_exp); \ + } \ + } + +#define ASSERT_REPORT(_exp, _fmt) \ + { \ + if (!(_exp)) { \ + LOG_FUNC("Warning at %s:%d (%s)\n", __func__, __LINE__, #_exp); \ + LOG_FUNC _fmt; \ + } \ + } +#endif /* BUILD_QA_DBG */ + +#define DISP_STRING(_str) "" + +#endif /* DBG */ + +#if CFG_STARTUP_DEBUG +#if defined(LINUX) +#define DBGPRINTF kalPrint +#else +#define DBGPRINTF DbgPrint +#endif +#else +#define DBGPRINTF(...) +#endif + +/* The following macro is used for debugging packed structures. */ +#ifndef DATA_STRUCT_INSPECTING_ASSERT +#define DATA_STRUCT_INSPECTING_ASSERT(expr) \ +{ \ + switch (0) {case 0: case (expr): default:; } \ +} +#endif +#define DBGLOG_MEM8_IE_ONE_LINE(_Module, _Class, _String, _StartAddr, _Length) \ + { \ + if (aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) { \ + dumpMemory8IEOneLine((PUINT_8) (_String), (PUINT_8) (_StartAddr), (UINT_32) (_Length)); \ + } \ + } + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID dumpMemory8IEOneLine(IN PUINT_8 aucBSSID, IN PUINT_8 pucStartAddr, IN UINT_32 u4Length); + +VOID dumpMemory8(IN PUINT_8 pucStartAddr, IN UINT_32 u4Length); + +VOID dumpMemory32(IN PUINT_32 pu4StartAddr, IN UINT_32 u4Length); + +VOID wlanDebugInit(VOID); + +VOID wlanDebugUninit(VOID); + +VOID wlanTraceReleaseTcRes(P_ADAPTER_T prAdapter, PUINT_8 aucTxRlsCnt, UINT_8 ucAvailable); + +VOID wlanTraceTxCmd(P_ADAPTER_T prAdapter, P_CMD_INFO_T prCmd); + +VOID wlanReadFwStatus(P_ADAPTER_T prAdapter); + +VOID wlanDumpTxReleaseCount(P_ADAPTER_T prAdapter); + +VOID wlanDumpTcResAndTxedCmd(PUINT_8 pucBuf, UINT_32 maxLen); + +VOID wlanDumpCommandFwStatus(VOID); + +VOID wlanDebugScanTargetBSSRecord(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc); + +VOID wlanDebugScanTargetBSSDump(P_ADAPTER_T prAdapter); + +VOID wlanPktDebugDumpInfo(P_ADAPTER_T prAdapter); +VOID wlanPktDebugTraceInfoIP(UINT_8 status, UINT_8 eventType, UINT_8 ucIpProto, UINT_16 u2IpId); +VOID wlanPktDebugTraceInfoARP(UINT_8 status, UINT_8 eventType, UINT_16 u2ArpOpCode); +VOID wlanPktDebugTraceInfo(UINT_8 status, UINT_8 eventType + , UINT_16 u2EtherType, UINT_8 ucIpProto, UINT_16 u2IpId, UINT_16 u2ArpOpCode); +VOID wlanDebugHifDescriptorDump(P_ADAPTER_T prAdapter, ENUM_AMPDU_TYPE type + , ENUM_DEBUG_TRAFFIC_CLASS_INDEX_T tcIndex); +VOID wlanDebugScanRecord(P_ADAPTER_T prAdapter, ENUM_DBG_SCAN_T recordType); +VOID wlanDebugScanDump(P_ADAPTER_T prAdapter); + + +VOID wlanFWDLDebugInit(VOID); + +VOID wlanFWDLDebugStartSectionPacketInfo(UINT_32 u4Section, UINT_32 u4DownloadSize, + UINT_32 u4ResponseTime); + +VOID wlanFWDLDebugAddTxStartTime(UINT_32 u4TxStartTime); + +VOID wlanFWDLDebugAddTxDoneTime(UINT_32 u4TxDoneTime); + +VOID wlanFWDLDebugAddRxStartTime(UINT_32 u4RxStartTime); + +VOID wlanFWDLDebugAddRxDoneTime(UINT_32 u4RxDoneTime); + +VOID wlanFWDLDebugDumpInfo(VOID); + +VOID wlanFWDLDebugUninit(VOID); + +UINT_32 wlanFWDLDebugGetPktCnt(VOID); + +VOID wlanDumpMcuChipId(P_ADAPTER_T prAdapter); + +VOID wlanPktStausDebugUpdateProcessTime(UINT_32 u4DbgTxPktStatusIndex); +VOID wlanPktStatusDebugDumpInfo(P_ADAPTER_T prAdapter); + + + +VOID wlanPktStatusDebugTraceInfoSeq(P_ADAPTER_T prAdapter, UINT_16 u2NoSeq); +VOID wlanPktStatusDebugTraceInfoARP(UINT_8 status, UINT_8 eventType, UINT_16 u2ArpOpCode, PUINT_8 pucPkt + , P_MSDU_INFO_T prMsduInfo); +VOID wlanPktStatusDebugTraceInfoIP(UINT_8 status, UINT_8 eventType, UINT_8 ucIpProto, UINT_16 u2IpId + , PUINT_8 pucPkt, P_MSDU_INFO_T prMsduInfo); +VOID wlanPktStatusDebugTraceInfo(UINT_8 status, UINT_8 eventType, UINT_16 u2EtherType + , UINT_8 ucIpProto, UINT_16 u2IpId, UINT_16 u2ArpOpCode, PUINT_8 pucPkt, P_MSDU_INFO_T prMsduInfo); +VOID wlanDebugCommandRecodTime(P_CMD_INFO_T prCmdInfo); +VOID wlanDebugCommandRecodDump(VOID); +#if CFG_SUPPORT_EMI_DEBUG +VOID wlanReadFwInfoFromEmi(IN PUINT_32 pAddr); + +VOID wlanFillTimestamp(P_ADAPTER_T prAdapter, PVOID pvPacket, UINT_8 ucPhase); +#endif + +VOID wlanDbgLogLevelInit(VOID); +VOID wlanDbgLogLevelUninit(VOID); +UINT_32 wlanDbgLevelUiSupport(IN P_ADAPTER_T prAdapter, UINT_32 u4Version, UINT_32 ucModule); +UINT_32 wlanDbgGetLogLevelImpl(IN P_ADAPTER_T prAdapter, UINT_32 u4Version, UINT_32 ucModule); +VOID wlanDbgSetLogLevelImpl(IN P_ADAPTER_T prAdapter, UINT_32 u4Version, + UINT_32 u4Module, UINT_32 u4level); +VOID wlanDbgLevelSync(VOID); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _DEBUG_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/fwcfg.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/fwcfg.h new file mode 100644 index 0000000000000..26e6de008266d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/fwcfg.h @@ -0,0 +1,129 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _FWCFG_H +#define _FWCFG_H +#include "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 +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#ifdef FW_CFG_SUPPORT +#define MAX_CMD_ITEM_MAX 4 +#define MAX_CMD_NAME_MAX_LENGTH 32 +#define MAX_CMD_VALUE_MAX_LENGTH 32 + +#define MAX_CMD_TYPE_LENGTH 1 +#define MAX_CMD_RESERVE_LENGTH 1 +#define MAX_CMD_STRING_LENGTH 1 +#define MAX_CMD_VALUE_LENGTH 1 + +#define CMD_FORMAT_V1_LENGTH (MAX_CMD_NAME_MAX_LENGTH + \ + MAX_CMD_VALUE_MAX_LENGTH + MAX_CMD_TYPE_LENGTH + \ + MAX_CMD_STRING_LENGTH + MAX_CMD_VALUE_LENGTH + MAX_CMD_RESERVE_LENGTH) + +#define MAX_CMD_BUFFER_LENGTH (CMD_FORMAT_V1_LENGTH * MAX_CMD_ITEM_MAX) + +#define FW_CFG_FILE_1 "/etc/firmware/wifi_fw.cfg" +#define FW_CFG_FILE_2 "/vendor/firmware/wifi_fw.cfg" +#define FW_CFG_FILE_3 "/data/misc/wifi/wifi_fw.cfg" + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +enum _CMD_VER_T { + CMD_VER_1, + CMD_VER_1_EXT +}; + +enum _CMD_TYPE_T { + CMD_TYPE_QUERY, + CMD_TYPE_SET +}; + +struct _CMD_FORMAT_V1_T { + UINT_8 itemType; + UINT_8 itemStringLength; + UINT_8 itemValueLength; + UINT_8 Reserved; + UINT_8 itemString[MAX_CMD_NAME_MAX_LENGTH]; + UINT_8 itemValue[MAX_CMD_VALUE_MAX_LENGTH]; +}; + +struct _CMD_HEADER_T { + enum _CMD_VER_T cmdVersion; + enum _CMD_TYPE_T cmdType; + UINT_8 itemNum; + UINT_16 cmdBufferLen; + UINT_8 buffer[MAX_CMD_BUFFER_LENGTH]; +}; + +struct WLAN_CFG_PARSE_STATE_S { + CHAR *ptr; + CHAR *text; + INT_32 nexttoken; + UINT_32 maxSize; +}; + +struct _FW_CFG { + PUINT_8 key; + PUINT_8 value; +}; +/******************************************************************************* +* P U B 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_32 getFwCfgItemNum(void); + +PUINT_8 getFwCfgItemKey(UINT_8 i); + +PUINT_8 getFwCfgItemValue(UINT_8 i); + +void wlanCfgFwSetParam(PUINT_8 fwBuffer, PCHAR cmdStr, PCHAR value, int num, int type); + +WLAN_STATUS wlanCfgSetGetFw(IN P_ADAPTER_T prAdapter, const PCHAR fwBuffer, int cmdNum, enum _CMD_TYPE_T cmdType); + +WLAN_STATUS wlanFwCfgParse(IN P_ADAPTER_T prAdapter, PUINT_8 pucConfigBuf); + +WLAN_STATUS wlanFwArrayCfg(IN P_ADAPTER_T prAdpter); + +WLAN_STATUS wlanFwFileCfg(IN P_ADAPTER_T prAdpter); +#endif +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/link.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/link.h new file mode 100644 index 0000000000000..c4cbe90714a46 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/link.h @@ -0,0 +1,373 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _LINK_H +#define _LINK_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_typedef.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* May cause page fault & unalignment issue (data abort) */ +#define INVALID_LINK_POISON1 ((VOID *) 0x00100101) +/* Used to verify that nonbody uses non-initialized link entries. */ +#define INVALID_LINK_POISON2 ((VOID *) 0x00100201) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Simple Doubly Linked List Structures - Entry Part */ +typedef struct _LINK_ENTRY_T { + struct _LINK_ENTRY_T *prNext, *prPrev; +} LINK_ENTRY_T, *P_LINK_ENTRY_T; + +/* Simple Doubly Linked List Structures - List Part */ +typedef struct _LINK_T { + P_LINK_ENTRY_T prNext; + P_LINK_ENTRY_T prPrev; + UINT_32 u4NumElem; +} LINK_T, *P_LINK_T; + +struct LINK_MGMT { + LINK_T rUsingLink; + LINK_T rFreeLink; +}; + +/******************************************************************************* +* P U B 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_MGMT_INIT(prLinkMgmt) \ + do { \ + LINK_INITIALIZE(&((struct LINK_MGMT *)prLinkMgmt)->rUsingLink); \ + LINK_INITIALIZE(&((struct LINK_MGMT *)prLinkMgmt)->rFreeLink); \ + } while (0) + +#define LINK_MGMT_GET_ENTRY(prLinkMgmt, prEntry, EntryType, memType) \ + do { \ + LINK_REMOVE_HEAD(&((struct LINK_MGMT *)prLinkMgmt)->rFreeLink, \ + prEntry, EntryType*); \ + if (!prEntry) \ + prEntry = kalMemAlloc(sizeof(EntryType), memType); \ + } while (0) + +#define LINK_MGMT_UNINIT(prLinkMgmt, EntryType, memType) \ + do { \ + EntryType *prEntry = NULL; \ + P_LINK_T prFreeList = &((struct LINK_MGMT *)prLinkMgmt)->rFreeLink; \ + P_LINK_T prUsingList = &((struct LINK_MGMT *)prLinkMgmt)->rUsingLink; \ + LINK_REMOVE_HEAD(prFreeList, prEntry, EntryType *); \ + while (prEntry) { \ + kalMemFree(prEntry, memType, sizeof(EntryType)); \ + LINK_REMOVE_HEAD(prFreeList, prEntry, EntryType *); \ + } \ + LINK_REMOVE_HEAD(prUsingList, prEntry, EntryType *); \ + while (prEntry) { \ + kalMemFree(prEntry, memType, sizeof(EntryType)); \ + LINK_REMOVE_HEAD(prUsingList, prEntry, EntryType *); \ + } \ + } 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_ENTRY_IS_VALID(prEntry) \ + (((P_LINK_ENTRY_T)(prEntry))->prNext != (P_LINK_ENTRY_T)NULL && \ + ((P_LINK_ENTRY_T)(prEntry))->prNext != (P_LINK_ENTRY_T)INVALID_LINK_POISON1 && \ + ((P_LINK_ENTRY_T)(prEntry))->prPrev != (P_LINK_ENTRY_T)NULL && \ + ((P_LINK_ENTRY_T)(prEntry))->prPrev != (P_LINK_ENTRY_T)INVALID_LINK_POISON2) + +#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) ? \ + (_type *)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) ? \ + (_type *)NULL : LINK_ENTRY((prLink)->prPrev, _type, _member) \ + ) + +/* Get first entry from a link list */ +/* NOTE: We assume the link entry located at the beginning of "prEntry Type", + * so that we can cast the link entry to other data type without doubts. + * And this macro also decrease the total entry count at the same time. + */ +#define LINK_REMOVE_HEAD(prLink, prEntry, _P_TYPE) \ + { \ + ASSERT(prLink); \ + if (LINK_IS_EMPTY(prLink)) { \ + prEntry = (_P_TYPE)NULL; \ + } \ + else { \ + prEntry = (_P_TYPE)(((P_LINK_T)(prLink))->prNext); \ + linkDel((P_LINK_ENTRY_T)prEntry); \ + ((prLink)->u4NumElem)--; \ + } \ + } + +/* Assume the link entry located at the beginning of prEntry Type. + * And also decrease the total entry count. + */ +#define LINK_REMOVE_KNOWN_ENTRY(prLink, prEntry) \ + { \ + ASSERT(prLink); \ + ASSERT(prEntry); \ + linkDel((P_LINK_ENTRY_T)prEntry); \ + ((prLink)->u4NumElem)--; \ + } + +/* Iterate over a link list */ +#define LINK_FOR_EACH(prEntry, prLink) \ + for (prEntry = (prLink)->prNext; \ + prEntry != (P_LINK_ENTRY_T)(prLink); \ + prEntry = (P_LINK_ENTRY_T)prEntry->prNext) + +/* Iterate over a link list backwards */ +#define LINK_FOR_EACH_PREV(prEntry, prLink) \ + for (prEntry = (prLink)->prPrev; \ + prEntry != (P_LINK_ENTRY_T)(prLink); \ + prEntry = (P_LINK_ENTRY_T)prEntry->prPrev) + +/* Iterate over a link list safe against removal of link entry */ +#define LINK_FOR_EACH_SAFE(prEntry, prNextEntry, prLink) \ + for (prEntry = (prLink)->prNext, prNextEntry = prEntry->prNext; \ + prEntry != (P_LINK_ENTRY_T)(prLink); \ + prEntry = prNextEntry, prNextEntry = prEntry->prNext) + +/* Iterate over a link list of given type */ +#define LINK_FOR_EACH_ENTRY(prObj, prLink, rMember, _TYPE) \ + for (prObj = LINK_ENTRY((prLink)->prNext, _TYPE, rMember); \ + &prObj->rMember != (P_LINK_ENTRY_T)(prLink); \ + prObj = LINK_ENTRY(prObj->rMember.prNext, _TYPE, rMember)) + +/* Iterate backwards over a link list of given type */ +#define LINK_FOR_EACH_ENTRY_PREV(prObj, prLink, rMember, _TYPE) \ + for (prObj = LINK_ENTRY((prLink)->prPrev, _TYPE, rMember); \ + &prObj->rMember != (P_LINK_ENTRY_T)(prLink); \ + prObj = LINK_ENTRY(prObj->rMember.prPrev, _TYPE, rMember)) + +/* Iterate over a link list of given type safe against removal of link entry */ +#define LINK_FOR_EACH_ENTRY_SAFE(prObj, prNextObj, prLink, rMember, _TYPE) \ + for (prObj = LINK_ENTRY((prLink)->prNext, _TYPE, rMember), \ + prNextObj = LINK_ENTRY(prObj->rMember.prNext, _TYPE, rMember); \ + &prObj->rMember != (P_LINK_ENTRY_T)(prLink); \ + prObj = prNextObj, \ + prNextObj = LINK_ENTRY(prNextObj->rMember.prNext, _TYPE, rMember)) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is only for internal link list manipulation. +* +* \param[in] prNew Pointer of new link head +* \param[in] prPrev Pointer of previous link head +* \param[in] prNext Pointer of next link head +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID __linkAdd(IN P_LINK_ENTRY_T prNew, IN P_LINK_ENTRY_T prPrev, IN P_LINK_ENTRY_T prNext) +{ + prNext->prPrev = prNew; + prNew->prNext = prNext; + prNew->prPrev = prPrev; + prPrev->prNext = prNew; + +} /* end of __linkAdd() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will add a new entry after the specified link head. +* +* \param[in] prNew New entry to be added +* \param[in] prHead Specified link head to add it after +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID linkAdd(IN P_LINK_ENTRY_T prNew, IN P_LINK_T prLink) +{ + __linkAdd(prNew, (P_LINK_ENTRY_T) prLink, prLink->prNext); + +} /* end of linkAdd() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will add a new entry before the specified link head. +* +* \param[in] prNew New entry to be added +* \param[in] prHead Specified link head to add it before +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID linkAddTail(IN P_LINK_ENTRY_T prNew, IN P_LINK_T prLink) +{ + __linkAdd(prNew, prLink->prPrev, (P_LINK_ENTRY_T) prLink); + +} /* end of linkAddTail() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is only for internal link list manipulation. +* +* \param[in] prPrev Pointer of previous link head +* \param[in] prNext Pointer of next link head +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID __linkDel(IN P_LINK_ENTRY_T prPrev, IN P_LINK_ENTRY_T prNext) +{ + prNext->prPrev = prPrev; + prPrev->prNext = prNext; + +} /* end of __linkDel() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will delete a specified entry from link list. +* NOTE: the entry is in an initial state. +* +* \param prEntry Specified link head(entry) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID linkDel(IN P_LINK_ENTRY_T prEntry) +{ + __linkDel(prEntry->prPrev, prEntry->prNext); + + LINK_ENTRY_INITIALIZE(prEntry); + +} /* end of linkDel() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will delete a specified entry from link list and then add it +* after the specified link head. +* +* \param[in] prEntry Specified link head(entry) +* \param[in] prOtherHead Another link head to add it after +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID linkMove(IN P_LINK_ENTRY_T prEntry, IN P_LINK_T prLink) +{ + __linkDel(prEntry->prPrev, prEntry->prNext); + linkAdd(prEntry, prLink); + +} /* end of linkMove() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will delete a specified entry from link list and then add it +* before the specified link head. +* +* \param[in] prEntry Specified link head(entry) +* \param[in] prOtherHead Another link head to add it before +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID linkMoveTail(IN P_LINK_ENTRY_T prEntry, IN P_LINK_T prLink) +{ + __linkDel(prEntry->prPrev, prEntry->prNext); + linkAddTail(prEntry, prLink); + +} /* end of linkMoveTail() */ + +#endif /* _LINK_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/aa_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/aa_fsm.h new file mode 100644 index 0000000000000..0044dd9950973 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/aa_fsm.h @@ -0,0 +1,148 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _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 */ + +#define JOIN_MAX_RETRY_OVERLOAD_RN 1 /* 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_EXTERNAL_AUTH, + 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; + +typedef enum _ENUM_AA_FRM_TYPE_T { + FRM_DISASSOC = 0, + FRM_DEAUTH +} ENUM_AA_FRM_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 +******************************************************************************** +*/ + +/******************************************************************************* +* 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); + +VOID saaSendDisconnectMsgHandler(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, + IN P_BSS_INFO_T prAisBssInfo, IN ENUM_AA_FRM_TYPE_T eFrmType); + +VOID saaFsmRunEventFTContinue(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +void saaFsmRunEventExternalAuthDone(IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr); +/*----------------------------------------------------------------------------*/ +/* Routines in aaa_fsm.c */ +/*----------------------------------------------------------------------------*/ +VOID aaaFsmRunEventRxAuth(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +WLAN_STATUS aaaFsmRunEventRxAssoc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +WLAN_STATUS +aaaFsmRunEventTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _AA_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/ais_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/ais_fsm.h new file mode 100644 index 0000000000000..65378ece64e01 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/ais_fsm.h @@ -0,0 +1,473 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _AIS_FSM_H +#define _AIS_FSM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define AIS_BG_SCAN_INTERVAL_MIN_SEC 2 /* 30 // exponential to 960 */ +#define AIS_BG_SCAN_INTERVAL_MAX_SEC 2 /* 960 // 16min */ + +#define AIS_DELAY_TIME_OF_DISC_SEC_ONLY_2G4 2 /* 2.4G scan need about 0.5s, so delay 2s to reconnect is enough */ +#define AIS_DELAY_TIME_OF_DISC_SEC_DUALBAND 5 /* 2.4G scan need about 3.3s, so delay 5s to reconnect is enough */ + +#define AIS_IBSS_ALONE_TIMEOUT_SEC 20 /* seconds */ + +#define AIS_BEACON_TIMEOUT_COUNT_ADHOC 30 +#define AIS_BEACON_TIMEOUT_COUNT_INFRA 10 +#define AIS_BEACON_TIMEOUT_GUARD_TIME_SEC 1 /* Second */ + +#define AIS_BEACON_MAX_TIMEOUT_TU 100 +#define AIS_BEACON_MIN_TIMEOUT_TU 5 +#define AIS_BEACON_MAX_TIMEOUT_VALID TRUE +#define AIS_BEACON_MIN_TIMEOUT_VALID TRUE + +#define AIS_BMC_MAX_TIMEOUT_TU 100 +#define AIS_BMC_MIN_TIMEOUT_TU 5 +#define AIS_BMC_MAX_TIMEOUT_VALID TRUE +#define AIS_BMC_MIN_TIMEOUT_VALID TRUE + +#define AIS_JOIN_CH_GRANT_THRESHOLD 10 +#define AIS_JOIN_CH_REQUEST_INTERVAL 4000 + +#define AIS_SCN_DONE_TIMEOUT_SEC 25 /* 25 for 2.4G + 5G */ /* 5 */ + + +#define AIS_AUTORN_MIN_INTERVAL 20 +#define AIS_BLACKLIST_TIMEOUT 15 /* seconds */ + +#define AIS_WAIT_OKC_PMKID_SEC 1000 /* unit: ms */ +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_AIS_STATE_T { + AIS_STATE_IDLE = 0, + AIS_STATE_SEARCH, + AIS_STATE_SCAN, + AIS_STATE_ONLINE_SCAN, + AIS_STATE_LOOKING_FOR, + AIS_STATE_WAIT_FOR_NEXT_SCAN, + AIS_STATE_REQ_CHANNEL_JOIN, + AIS_STATE_JOIN, + AIS_STATE_IBSS_ALONE, + AIS_STATE_IBSS_MERGE, + AIS_STATE_NORMAL_TR, + AIS_STATE_DISCONNECTING, + AIS_STATE_REQ_REMAIN_ON_CHANNEL, + AIS_STATE_REMAIN_ON_CHANNEL, + AIS_STATE_COLLECT_ESS_INFO, + AIS_STATE_NUM +} ENUM_AIS_STATE_T; + +/* reconnect level for determining if we should reconnect */ +typedef enum _ENUM_RECONNECT_LEVEL_T { + RECONNECT_LEVEL_MIN = 0, + RECONNECT_LEVEL_ROAMING_FAIL, /* roaming failed */ + RECONNECT_LEVEL_BEACON_TIMEOUT, /* driver beacon timeout */ + RECONNECT_LEVEL_USER_SET, /* user set connect or disassociate */ + RECONNECT_LEVEL_MAX +} ENUM_RECONNECT_LEVEL_T; + +typedef struct _MSG_AIS_ABORT_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucReasonOfDisconnect; + BOOLEAN fgDelayIndication; +} MSG_AIS_ABORT_T, *P_MSG_AIS_ABORT_T; + +typedef struct _MSG_AIS_IBSS_PEER_FOUND_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucNetTypeIndex; + BOOLEAN fgIsMergeIn; /* TRUE: Merge In, FALSE: Merge Out */ + P_STA_RECORD_T prStaRec; +} MSG_AIS_IBSS_PEER_FOUND_T, *P_MSG_AIS_IBSS_PEER_FOUND_T; + +typedef enum _ENUM_AIS_REQUEST_TYPE_T { + AIS_REQUEST_SCAN, + AIS_REQUEST_RECONNECT, + AIS_REQUEST_ROAMING_SEARCH, + AIS_REQUEST_ROAMING_CONNECT, + AIS_REQUEST_REMAIN_ON_CHANNEL, + AIS_REQUEST_NUM +} ENUM_AIS_REQUEST_TYPE_T; + +typedef struct _AIS_REQ_HDR_T { + LINK_ENTRY_T rLinkEntry; + ENUM_AIS_REQUEST_TYPE_T eReqType; + /* temp save partial scan channel info */ + PUINT_8 pu8ChannelInfo; +} AIS_REQ_HDR_T, *P_AIS_REQ_HDR_T; + +typedef struct _AIS_REQ_CHNL_INFO { + ENUM_BAND_T eBand; + ENUM_CHNL_EXT_T eSco; + UINT_8 ucChannelNum; + UINT_32 u4DurationMs; + UINT_64 u8Cookie; +} AIS_REQ_CHNL_INFO, *P_AIS_REQ_CHNL_INFO; + +typedef struct _AIS_MGMT_TX_REQ_INFO_T { + BOOLEAN fgIsMgmtTxRequested; + P_MSDU_INFO_T prMgmtTxMsdu; + UINT_64 u8Cookie; +} AIS_MGMT_TX_REQ_INFO_T, *P_AIS_MGMT_TX_REQ_INFO_T; + +struct AIS_BLACKLIST_ITEM { + LINK_ENTRY_T rLinkEntry; + + UINT_8 aucBSSID[MAC_ADDR_LEN]; + UINT_16 u2DeauthReason; + UINT_16 u2AuthStatus; + UINT_8 ucCount; + UINT_8 ucSSIDLen; + UINT_8 aucSSID[32]; + OS_SYSTIME rAddTime; + UINT_32 u4DisapperTime; + BOOLEAN fgIsInFWKBlacklist; +}; + +struct AIS_BEACON_TIMEOUT_BSS { + LINK_ENTRY_T rLinkEntry; + + UINT_64 u8Tsf; + UINT_64 u8AddTime; + UINT_8 ucReserved; + UINT_8 aucBSSID[MAC_ADDR_LEN]; + UINT_8 ucSSIDLen; + UINT_8 aucSSID[32]; +}; + +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; + + UINT_32 u4PostponeIndStartTime; + + TIMER_T rJoinTimeoutTimer; + + TIMER_T rChannelTimeoutTimer; + + TIMER_T rScanDoneTimer; + + TIMER_T rDeauthDoneTimer; + + TIMER_T rWaitOkcPMKTimer; + +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE + TIMER_T rSecModeChangeTimer; +#endif + UINT_8 ucSeqNumOfReqMsg; + UINT_8 ucSeqNumOfChReq; + UINT_8 ucSeqNumOfScanReq; + + UINT_32 u4ChGrantedInterval; + + UINT_8 ucConnTrialCount; +#if CFG_MULTI_SSID_SCAN + UINT_8 ucScanSSIDNum; + PARAM_SSID_T arScanSSID[SCN_SSID_MAX_NUM]; +#endif + + 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; +#if CFG_MULTI_SSID_SCAN + /* for roaming target */ + PARAM_SSID_T rRoamingSSID;/* MULTI SSID */ +#endif + + /* Join Request Timestamp */ + OS_SYSTIME rJoinReqTime; + + /* for cfg80211 REMAIN_ON_CHANNEL support */ + AIS_REQ_CHNL_INFO rChReqInfo; + + /* Mgmt tx related. */ + AIS_MGMT_TX_REQ_INFO_T rMgmtTxInfo; + + /* Packet filter for AIS module. */ + UINT_32 u4AisPacketFilter; + + struct LINK_MGMT rBcnTimeout; + UINT_8 ucJoinFailCntAfterScan; + UINT_8 aucRandomMac[MAC_ADDR_LEN]; + + UINT_8 aucNeighborAPChnl[CFG_NEIGHBOR_AP_CHANNEL_NUM]; +#if CFG_SUPPORT_DYNAMIC_ROAM + INT_8 cRoamTriggerThreshold; +#endif +#if CFG_SCAN_ABORT_HANDLE + BOOLEAN fgIsAbortEvnetDuringScan; +#endif + BOOLEAN fgTargetChnlScanIssued; +} AIS_FSM_INFO_T, *P_AIS_FSM_INFO_T; + +enum WNM_AIS_BSS_TRANSITION { + BSS_TRANSITION_NO_MORE_ACTION, + BSS_TRANSITION_REQ_ROAMING, + BSS_TRANSITION_DISASSOC, + BSS_TRANSITION_MAX_NUM +}; +struct MSG_AIS_BSS_TRANSITION_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + BOOLEAN fgNeedResponse; + enum WNM_AIS_BSS_TRANSITION eTransitionType; +}; +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define aisChangeMediaState(_prAdapter, _eNewMediaState) \ + (_prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].eConnectionState = (_eNewMediaState)) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID aisInitializeConnectionSettings(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo); + +VOID aisFsmInit(IN P_ADAPTER_T prAdapter); + +VOID aisFsmUninit(IN P_ADAPTER_T prAdapter); + +VOID aisFsmStateInit_JOIN(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc); + +BOOLEAN aisFsmStateInit_RetryJOIN(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +VOID aisFsmStateInit_IBSS_ALONE(IN P_ADAPTER_T prAdapter); + +VOID aisFsmStateInit_IBSS_MERGE(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc); + +VOID aisFsmStateAbort(IN P_ADAPTER_T prAdapter, UINT_8 ucReasonOfDisconnect, BOOLEAN fgDelayIndication); + +VOID aisFsmStateAbort_JOIN(IN P_ADAPTER_T prAdapter); + +VOID aisFsmStateAbort_SCAN(IN P_ADAPTER_T prAdapter); + +VOID aisFsmStateAbort_NORMAL_TR(IN P_ADAPTER_T prAdapter); + +VOID aisFsmStateAbort_IBSS(IN P_ADAPTER_T prAdapter); +#if 0 +VOID aisFsmSetChannelInfo(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_SCAN_REQ ScanReqMsg, IN ENUM_AIS_STATE_T CurrentState); +#endif +VOID aisFsmSteps(IN P_ADAPTER_T prAdapter, ENUM_AIS_STATE_T eNextState); + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Handling */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID aisFsmRunEventAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID aisFsmRunEventJoinComplete(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID aisFsmRunEventFoundIBSSPeer(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID aisFsmRunEventRemainOnChannel(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID aisFsmRunEventCancelRemainOnChannel(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +/*----------------------------------------------------------------------------*/ +/* Handling for Ad-Hoc Network */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmCreateIBSS(IN P_ADAPTER_T prAdapter); + +VOID aisFsmMergeIBSS(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +/*----------------------------------------------------------------------------*/ +/* Handling of Incoming Mailbox Message from CNM */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventChGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +/*----------------------------------------------------------------------------*/ +/* Generating Outgoing Mailbox Message to CNM */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmReleaseCh(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* Event Indication */ +/*----------------------------------------------------------------------------*/ +VOID +aisIndicationOfMediaStateToHost(IN P_ADAPTER_T prAdapter, + ENUM_PARAM_MEDIA_STATE_T eConnectionState, BOOLEAN fgDelayIndication); + +VOID aisPostponedEventOfSchedScanReq(IN P_ADAPTER_T prAdapter, P_AIS_FSM_INFO_T prAisFsmInfo); + +VOID aisPostponedEventOfDisconnTimeout(IN P_ADAPTER_T prAdapter, P_AIS_FSM_INFO_T prAisFsmInfo); + +VOID aisUpdateBssInfoForJOIN(IN P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, P_SW_RFB_T prAssocRspSwRfb); + +VOID aisUpdateBssInfoForCreateIBSS(IN P_ADAPTER_T prAdapter); + +VOID aisUpdateBssInfoForMergeIBSS(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +BOOLEAN aisValidateProbeReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_32 pu4ControlFlags); + +WLAN_STATUS +aisFsmRunEventMgmtFrameTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +/*----------------------------------------------------------------------------*/ +/* Disconnection Handling */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmDisconnect(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgDelayIndication); + +/*----------------------------------------------------------------------------*/ +/* Event Handling */ +/*----------------------------------------------------------------------------*/ +VOID aisBssBeaconTimeout(IN P_ADAPTER_T prAdapter); + +VOID aisBssSecurityChanged(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS +aisDeauthXmitComplete(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +#if CFG_SUPPORT_ROAMING +VOID aisFsmRunEventRoamingDiscovery(IN P_ADAPTER_T prAdapter, UINT_32 u4ReqScan); + +ENUM_AIS_STATE_T aisFsmRoamingScanResultsUpdate(IN P_ADAPTER_T prAdapter); + +VOID aisFsmRoamingDisconnectPrevAP(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prTargetStaRec); + +VOID aisUpdateBssInfoForRoamingAP(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prAssocRspSwRfb); +#endif /*CFG_SUPPORT_ROAMING */ + +/*----------------------------------------------------------------------------*/ +/* Timeout Handling */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventBGSleepTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParam); + +VOID aisFsmRunEventIbssAloneTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParam); + +VOID aisFsmRunEventJoinTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam); + +VOID aisFsmRunEventChannelTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam); + +VOID aisFsmRunEventScanDoneTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParam); + +VOID aisFsmRunEventDeauthTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam); +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE +VOID aisFsmRunEventSecModeChangeTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr); +#endif + +/*----------------------------------------------------------------------------*/ +/* OID/IOCTL Handling */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmScanRequest(IN P_ADAPTER_T prAdapter, IN P_PARAM_SSID_T prSsid, IN PUINT_8 pucIe, IN UINT_32 u4IeLength); + +#if 1 /* MULTI SSID */ +VOID aisFsmScanRequestAdv(IN P_ADAPTER_T prAdapter, IN UINT_8 ucSsidNum, IN P_PARAM_SSID_T prSsid, + IN PUINT_8 pucIe, IN UINT_32 u4IeLength, IN PUINT_8 paucRandomMac); +#endif +/*----------------------------------------------------------------------------*/ +/* Internal State Checking */ +/*----------------------------------------------------------------------------*/ +BOOLEAN aisFsmIsRequestPending(IN P_ADAPTER_T prAdapter, IN ENUM_AIS_REQUEST_TYPE_T eReqType, IN BOOLEAN bRemove); + +P_AIS_REQ_HDR_T aisFsmGetNextRequest(IN P_ADAPTER_T prAdapter); + +BOOLEAN aisFsmInsertRequest(IN P_ADAPTER_T prAdapter, IN ENUM_AIS_REQUEST_TYPE_T eReqType); + +VOID aisFsmFlushRequest(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS +aisFuncTxMgmtFrame(IN P_ADAPTER_T prAdapter, + IN P_AIS_MGMT_TX_REQ_INFO_T prMgmtTxReqInfo, IN P_MSDU_INFO_T prMgmtTxMsdu, IN UINT_64 u8Cookie); + +VOID aisFsmRunEventMgmtFrameTx(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); +#if CFG_SUPPORT_NCHO +VOID aisFsmRunEventNchoActionFrameTx(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); +#endif + +VOID aisFuncValidateRxActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +#if (CFG_REFACTORY_PMKSA == 0) +VOID aisFsmRunEventSetOkcPmk(IN P_ADAPTER_T prAdapter); +#endif + +VOID aisFsmRunEventBssTransition(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID aisCollectNeighborAPChannel(P_ADAPTER_T prAdapter, struct IE_NEIGHBOR_REPORT_T *prNeiRep, UINT_16 u2Length); + +#if defined(CFG_TEST_MGMT_FSM) && (CFG_TEST_MGMT_FSM != 0) +VOID aisTest(VOID); +#endif /* CFG_TEST_MGMT_FSM */ + +VOID aisRefreshFWKBlacklist(P_ADAPTER_T prAdapter); +struct AIS_BLACKLIST_ITEM *aisAddBlacklist(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc); +VOID aisRemoveBlackList(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc); +VOID aisRemoveTimeoutBlacklist(P_ADAPTER_T prAdapter); +struct AIS_BLACKLIST_ITEM *aisQueryBlackList(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc); +VOID aisRecordBeaconTimeout(P_ADAPTER_T prAdapter, P_BSS_INFO_T prAisBssInfo); +VOID aisRemoveBeaconTimeoutEntry(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc); +UINT_16 aisCalculateBlackListScore(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc); +VOID aisCollectNeighborAPChannel(P_ADAPTER_T prAdapter, + struct IE_NEIGHBOR_REPORT_T *prNeiRep, UINT_16 u2Length); +VOID aisRunEventChnlUtilRsp(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _AIS_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/assoc.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/assoc.h new file mode 100644 index 0000000000000..e097eba3e61fc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/assoc.h @@ -0,0 +1,93 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _ASSOC_H +#define _ASSOC_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Routines in assoc.c */ +/*----------------------------------------------------------------------------*/ +UINT_16 assocBuildCapabilityInfo(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +WLAN_STATUS assocSendReAssocReqFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +WLAN_STATUS assocCheckTxReAssocReqFrame(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +WLAN_STATUS assocCheckTxReAssocRespFrame(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +WLAN_STATUS +assocCheckRxReAssocRspFrameStatus(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu2StatusCode); + +WLAN_STATUS assocSendDisAssocFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN UINT_16 u2ReasonCode); + +WLAN_STATUS +assocProcessRxDisassocFrame(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, IN UINT_8 aucBSSID[], OUT PUINT_16 pu2ReasonCode); + +WLAN_STATUS assocProcessRxAssocReqFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu2StatusCode); + +WLAN_STATUS assocSendReAssocRespFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +VOID assocGenerateMDIE(IN P_ADAPTER_T prAdapter, IN OUT P_MSDU_INFO_T prMsduInfo); + +UINT_32 assocCalculateConnIELen(IN P_ADAPTER_T prAdapter, + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec); + +VOID assocGenerateConnIE(IN P_ADAPTER_T prAdapter, + IN OUT P_MSDU_INFO_T prMsduInfo); +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _ASSOC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/auth.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/auth.h new file mode 100644 index 0000000000000..9525dba71978a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/auth.h @@ -0,0 +1,115 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _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); + +WLAN_STATUS +authProcessRxAuthFrame(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN P_BSS_INFO_T prBssInfo, + OUT PUINT_16 pu2ReturnStatusCode); + +VOID authAddMDIE(IN P_ADAPTER_T prAdapter, IN OUT P_MSDU_INFO_T prMsduInfo); + +UINT_32 authCalculateRSNIELen(P_ADAPTER_T prAdapter, ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, P_STA_RECORD_T prStaRec); + +VOID authAddRSNIE(IN P_ADAPTER_T prAdapter, IN OUT P_MSDU_INFO_T prMsduInfo); + +VOID authHandleFtIEs(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, P_IE_HDR_T prIEHdr); +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _AUTH_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/bow_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/bow_fsm.h new file mode 100644 index 0000000000000..d01488e91c0c5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/bow_fsm.h @@ -0,0 +1,159 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _BOW_FSM_H +#define _BOW_FSM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define BOW_BG_SCAN_INTERVAL_MIN_SEC 2 /* 30 // exponential to 960 */ +#define BOW_BG_SCAN_INTERVAL_MAX_SEC 2 /* 960 // 16min */ + +#define BOW_DELAY_TIME_OF_DISCONNECT_SEC 10 + +#define BOW_BEACON_TIMEOUT_COUNT_STARTING 10 +#define BOW_BEACON_TIMEOUT_GUARD_TIME_SEC 1 /* Second */ + +#define BOW_BEACON_MAX_TIMEOUT_TU 100 +#define BOW_BEACON_MIN_TIMEOUT_TU 5 +#define BOW_BEACON_MAX_TIMEOUT_VALID TRUE +#define BOW_BEACON_MIN_TIMEOUT_VALID TRUE + +#define BOW_BMC_MAX_TIMEOUT_TU 100 +#define BOW_BMC_MIN_TIMEOUT_TU 5 +#define BOW_BMC_MAX_TIMEOUT_VALID TRUE +#define BOW_BMC_MIN_TIMEOUT_VALID TRUE + +#define BOW_JOIN_CH_GRANT_THRESHOLD 10 +#define BOW_JOIN_CH_REQUEST_INTERVAL 2000 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef enum _ENUM_BOW_STATE_T { + BOW_STATE_IDLE = 0, + BOW_STATE_SEARCH, + BOW_STATE_SCAN, + BOW_STATE_ONLINE_SCAN, + BOW_STATE_LOOKING_FOR, + BOW_STATE_WAIT_FOR_NEXT_SCAN, + BOW_STATE_REQ_CHANNEL_JOIN, + BOW_STATE_REQ_CHANNEL_ALONE, + BOW_STATE_REQ_CHANNEL_MERGE, + BOW_STATE_JOIN, + BOW_STATE_IBSS_ALONE, + BOW_STATE_IBSS_MERGE, + BOW_STATE_NORMAL_TR, + BOW_STATE_NUM +} ENUM_BOW_STATE_T; + +typedef struct _BOW_FSM_INFO_T { + ENUM_BOW_STATE_T ePreviousState; + ENUM_BOW_STATE_T eCurrentState; + + BOOLEAN fgTryScan; + + /* Channel Privilege */ + + BOOLEAN fgIsInfraChannelFinished; + BOOLEAN fgIsChannelRequested; + BOOLEAN fgIsChannelGranted; + BOOLEAN fgIsScanPending; + UINT_32 u4ChGrantedInterval; + + UINT_8 ucPrimaryChannel; + ENUM_BAND_T eBand; + UINT_16 u2BeaconInterval; + + ENUM_BOW_STATE_T eReturnState; /* Return state after current activity finished or abort. */ + ENUM_BOW_STATE_T eForwardState; /* Step to next state if ACTION frame is TX successfully. */ + + P_BSS_DESC_T prTargetBss; /* BSS of target P2P Device. For Connection/Service Discovery */ + + P_STA_RECORD_T prTargetStaRec; + P_BSS_DESC_T prTargetBssDesc; /* For destination */ + + UINT_8 aucPeerAddress[6]; + + UINT_8 ucRole; + + BOOLEAN fgSupportQoS; + + BOOLEAN fgIsRsponseProbe; /* Indicate if BOW can response probe request frame. */ + + /* Sequence number of requested message. */ + UINT_8 ucSeqNumOfChReq; + UINT_8 ucSeqNumOfReqMsg; + UINT_8 ucSeqNumOfScnMsg; + UINT_8 ucSeqNumOfScanReq; + + UINT_8 ucSeqNumOfCancelMsg; + + UINT_8 ucDialogToken; + + /* Timer */ + TIMER_T rStartingBeaconTimer; /* For device discovery time of each discovery request from user. */ + TIMER_T rStartingDiscoveryTimer; + TIMER_T rOperationListenTimer; /* For Find phase under operational state. */ + TIMER_T rFSMTimer; /* A timer used for Action frame timeout usage. */ + TIMER_T rIndicationOfDisconnectTimer; + TIMER_T rChGrantedTimer; + + UINT_8 ucAvailableAuthTypes; /* Used for AUTH_MODE_AUTO_SWITCH */ + +} BOW_FSM_INFO_T, *P_BOW_FSM_INFO_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define bowChangeMediaState(_prAdapter, _eNewMediaState) \ + (_prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX].eConnectionState = (_eNewMediaState)) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/bss.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/bss.h new file mode 100644 index 0000000000000..079f94534b305 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/bss.h @@ -0,0 +1,162 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _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 IS_BSS_INDEX_VALID(_ucBssIndex) ((_ucBssIndex) < NETWORK_TYPE_INDEX_NUM) + + +#define GET_BSS_INFO_BY_INDEX(_prAdapter, _ucBssIndex) \ + (&((_prAdapter)->rWifiVar.arBssInfo[(_ucBssIndex)])) + + +#define bssAssignAssocID(_prStaRec) ((_prStaRec)->ucIndex + 1) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Routines for all Operation Modes */ +/*----------------------------------------------------------------------------*/ +P_STA_RECORD_T +bssCreateStaRecFromBssDesc(IN P_ADAPTER_T prAdapter, + IN ENUM_STA_TYPE_T eStaType, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_BSS_DESC_T prBssDesc); + +VOID bssComposeNullFrame(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuffer, IN P_STA_RECORD_T prStaRec); + +VOID +bssComposeQoSNullFrame(IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBuffer, IN P_STA_RECORD_T prStaRec, IN UINT_8 ucUP, IN BOOLEAN fgSetEOSP); + +WLAN_STATUS +bssSendNullFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN PFN_TX_DONE_HANDLER pfTxDoneHandler); + +WLAN_STATUS +bssSendQoSNullFrame(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, IN UINT_8 ucUP, IN PFN_TX_DONE_HANDLER pfTxDoneHandler); + +/*----------------------------------------------------------------------------*/ +/* Routines for both IBSS(AdHoc) and BSS(AP) */ +/*----------------------------------------------------------------------------*/ +VOID bssGenerateExtSuppRate_IE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +VOID +bssBuildBeaconProbeRespFrameCommonIEs(IN P_MSDU_INFO_T prMsduInfo, IN P_BSS_INFO_T prBssInfo, IN PUINT_8 pucDestAddr); + +VOID +bssComposeBeaconProbeRespFrameHeaderAndFF(IN PUINT_8 pucBuffer, + IN PUINT_8 pucDestAddr, + IN PUINT_8 pucOwnMACAddress, + IN PUINT_8 pucBSSID, IN UINT_16 u2BeaconInterval, IN UINT_16 u2CapInfo); + +WLAN_STATUS +bssSendBeaconProbeResponse(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN PUINT_8 pucDestAddr, IN UINT_32 u4ControlFlags); + +WLAN_STATUS bssProcessProbeRequest(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID bssClearClientList(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo); + +VOID bssAddStaRecToClientList(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_STA_RECORD_T prStaRec); + +VOID bssRemoveStaRecFromClientList(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_STA_RECORD_T prStaRec); + +/*----------------------------------------------------------------------------*/ +/* Routines for IBSS(AdHoc) only */ +/*----------------------------------------------------------------------------*/ +VOID +ibssProcessMatchedBeacon(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, IN P_BSS_DESC_T prBssDesc, IN UINT_8 ucRCPI); + +WLAN_STATUS ibssCheckCapabilityForAdHocMode(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); + +VOID ibssInitForAdHoc(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo); + +WLAN_STATUS bssUpdateBeaconContent(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); + +/*----------------------------------------------------------------------------*/ +/* Routines for BSS(AP) only */ +/*----------------------------------------------------------------------------*/ +VOID bssInitForAP(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN BOOLEAN fgIsRateUpdate); + +VOID bssUpdateDTIMCount(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); + +VOID bssSetTIMBitmap(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN UINT_16 u2AssocId); + +P_STA_RECORD_T bssGetClientByAddress(IN P_BSS_INFO_T prBssInfo, PUINT_8 pucMacAddr); + +/*link function to p2p module for txBcnIETable*/ + +/* WMM-2.2.2 WMM ACI to AC coding */ +typedef enum _ENUM_ACI_T { + ACI_BE = 0, + ACI_BK = 1, + ACI_VI = 2, + ACI_VO = 3, + ACI_NUM +} ENUM_ACI_T, *P_ENUM_ACI_T; + +typedef enum _ENUM_AC_PRIORITY_T { + AC_BK_PRIORITY = 0, + AC_BE_PRIORITY, + AC_VI_PRIORITY, + AC_VO_PRIORITY +} ENUM_AC_PRIORITY_T, *P_ENUM_AC_PRIORITY_T; + +#endif /* _BSS_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/cnm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/cnm.h new file mode 100644 index 0000000000000..343d4a348fe25 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/cnm.h @@ -0,0 +1,200 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _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; + +struct MSG_REQ_CH_UTIL { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_16 u2Duration; + UINT_16 u2ReturnMID; + UINT_8 ucChnlNum; + UINT_8 aucChnlList[100]; +}; + +struct MSG_CH_UTIL_RSP { + MSG_HDR_T rMsgHdr; + UINT_8 ucChnlNum; + UINT_8 aucChnlList[100]; + UINT_8 aucChUtil[100]; +}; + +typedef struct _CNM_INFO_T { + UINT_32 u4Reserved; + + UINT_16 u2ReturnMID; + TIMER_T rReqChnlUtilTimer; +} CNM_INFO_T, *P_CNM_INFO_T; + +#if CFG_ENABLE_WIFI_DIRECT +/* Moved from p2p_fsm.h */ +typedef struct _DEVICE_TYPE_T { + UINT_16 u2CategoryId; /* Category ID */ + UINT_8 aucOui[4]; /* OUI */ + UINT_16 u2SubCategoryId; /* Sub Category ID */ +} __KAL_ATTRIB_PACKED__ DEVICE_TYPE_T, *P_DEVICE_TYPE_T; +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID cnmInit(P_ADAPTER_T prAdapter); + +VOID cnmUninit(P_ADAPTER_T prAdapter); + +VOID cnmChMngrRequestPrivilege(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr); + +VOID cnmChMngrAbortPrivilege(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr); + +VOID cnmChMngrHandleChEvent(P_ADAPTER_T prAdapter, P_WIFI_EVENT_T prEvent); + +BOOLEAN +cnmPreferredChannel(P_ADAPTER_T prAdapter, P_ENUM_BAND_T prBand, PUINT_8 pucPrimaryChannel, P_ENUM_CHNL_EXT_T prBssSCO); + +BOOLEAN cnmAisInfraChannelFixed(P_ADAPTER_T prAdapter, P_ENUM_BAND_T prBand, PUINT_8 pucPrimaryChannel); + +VOID cnmAisInfraConnectNotify(P_ADAPTER_T prAdapter); + +BOOLEAN cnmAisIbssIsPermitted(P_ADAPTER_T prAdapter); + +BOOLEAN cnmP2PIsPermitted(P_ADAPTER_T prAdapter); + +BOOLEAN cnmBowIsPermitted(P_ADAPTER_T prAdapter); + +BOOLEAN cnmBss40mBwPermitted(P_ADAPTER_T prAdapter, ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx); +#if CFG_P2P_LEGACY_COEX_REVISE +BOOLEAN cnmAisDetectP2PChannel(P_ADAPTER_T prAdapter, P_ENUM_BAND_T prBand, PUINT_8 pucPrimaryChannel); +#endif +VOID cnmRunEventReqChnlUtilTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr); +VOID cnmHandleChannelUtilization(P_ADAPTER_T prAdapter, + struct EVENT_RSP_CHNL_UTILIZATION *prChnlUtil); +VOID cnmRequestChannelUtilization(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr); +BOOLEAN cnmChUtilIsRunning(P_ADAPTER_T prAdapter); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#ifndef _lint +/* We don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + * We'll need this to guarantee the same member order in different structures + * to simply handling effort in some functions. + */ +static inline VOID cnmMsgDataTypeCheck(VOID) +{ + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, rMsgHdr) == 0); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, rMsgHdr) == OFFSET_OF(MSG_CH_RECOVER_T, rMsgHdr)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, ucNetTypeIndex) == + OFFSET_OF(MSG_CH_RECOVER_T, ucNetTypeIndex)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, ucTokenID) == OFFSET_OF(MSG_CH_RECOVER_T, ucTokenID)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, ucPrimaryChannel) == + OFFSET_OF(MSG_CH_RECOVER_T, ucPrimaryChannel)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, eRfSco) == OFFSET_OF(MSG_CH_RECOVER_T, eRfSco)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, eRfBand) == OFFSET_OF(MSG_CH_RECOVER_T, eRfBand)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, eReqType) == OFFSET_OF(MSG_CH_RECOVER_T, eReqType)); + +} +#endif /* _lint */ + +#endif /* _CNM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/cnm_mem.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/cnm_mem.h new file mode 100644 index 0000000000000..e47cc5f5207d6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/cnm_mem.h @@ -0,0 +1,777 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _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 +******************************************************************************** +*/ +#include "qosmap.h" +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#ifndef POWER_OF_2 +#define POWER_OF_2(n) BIT(n) +#endif + +/* Size of a basic management buffer block in power of 2 */ +#define MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2 7 /* 7 to the power of 2 = 128 */ +#define MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2 5 /* 5 to the power of 2 = 32 */ + +/* Size of a basic management buffer block */ +#define MGT_BUF_BLOCK_SIZE POWER_OF_2(MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2) +#define MSG_BUF_BLOCK_SIZE POWER_OF_2(MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2) + +/* Total size of (n) basic management buffer blocks */ +#define MGT_BUF_BLOCKS_SIZE(n) ((UINT_32)(n) << MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2) +#define MSG_BUF_BLOCKS_SIZE(n) ((UINT_32)(n) << MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2) + +/* Number of management buffer block */ +#define MAX_NUM_OF_BUF_BLOCKS 32 /* Range: 1~32 */ + +/* Size of overall management frame buffer */ +#define MGT_BUFFER_SIZE (MAX_NUM_OF_BUF_BLOCKS * MGT_BUF_BLOCK_SIZE) +#define MSG_BUFFER_SIZE (MAX_NUM_OF_BUF_BLOCKS * MSG_BUF_BLOCK_SIZE) + +/* STA_REC related definitions */ +#define STA_REC_INDEX_BMCAST 0xFF +#define STA_REC_INDEX_NOT_FOUND 0xFE +#define STA_WAIT_QUEUE_NUM 5 /* Number of SW queues in each STA_REC: AC0~AC4 */ +#define SC_CACHE_INDEX_NUM 5 /* Number of SC caches in each STA_REC: AC0~AC4 */ + +/* P2P related definitions */ +#ifdef CFG_ENABLE_WIFI_DIRECT +/* Moved from p2p_fsm.h */ +#define WPS_ATTRI_MAX_LEN_DEVICE_NAME 32 /* 0x1011 */ +#define P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT 8 /* NOTE(Kevin): Shall <= 16 */ +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +#if ((MAX_NUM_OF_BUF_BLOCKS > 32) || (MAX_NUM_OF_BUF_BLOCKS <= 0)) +#error > #define MAX_NUM_OF_MGT_BUF_BLOCKS : Out of boundary ! +#elif MAX_NUM_OF_BUF_BLOCKS > 16 +typedef UINT_32 BUF_BITMAP; +#elif MAX_NUM_OF_BUF_BLOCKS > 8 +typedef UINT_16 BUF_BITMAP; +#else +typedef UINT_8 BUF_BITMAP; +#endif /* MAX_NUM_OF_MGT_BUF_BLOCKS */ + +/* Control variable of TX management memory pool */ +typedef struct _BUF_INFO_T { + PUINT_8 pucBuf; + +#if CFG_DBG_MGT_BUF + UINT_32 u4AllocCount; + UINT_32 u4FreeCount; + UINT_32 u4AllocNullCount; +#endif /* CFG_DBG_MGT_BUF */ + + BUF_BITMAP rFreeBlocksBitmap; + UINT_8 aucAllocatedBlockNum[MAX_NUM_OF_BUF_BLOCKS]; +} BUF_INFO_T, *P_BUF_INFO_T; + +/* Wi-Fi divides RAM into three types + * MSG: Mailbox message (Small size) + * BUF: HW DMA buffers (HIF/MAC) + */ +typedef enum _ENUM_RAM_TYPE_T { + RAM_TYPE_MSG = 0, + RAM_TYPE_BUF +} ENUM_RAM_TYPE_T, P_ENUM_RAM_TYPE_T; + +typedef enum _ENUM_BUFFER_SOURCE_T { + BUFFER_SOURCE_HIF_TX0 = 0, + BUFFER_SOURCE_HIF_TX1, + BUFFER_SOURCE_MAC_RX, + BUFFER_SOURCE_MNG, + BUFFER_SOURCE_BCN, + BUFFER_SOURCE_NUM +} ENUM_BUFFER_SOURCE_T, *P_ENUM_BUFFER_SOURCE_T; + +typedef enum _ENUM_SEC_STATE_T { + SEC_STATE_INIT, + SEC_STATE_INITIATOR_PORT_BLOCKED, + SEC_STATE_RESPONDER_PORT_BLOCKED, + SEC_STATE_CHECK_OK, + SEC_STATE_SEND_EAPOL, + SEC_STATE_SEND_DEAUTH, + SEC_STATE_COUNTERMEASURE, + SEC_STATE_NUM +} ENUM_SEC_STATE_T; + +typedef struct _TSPEC_ENTRY_T { + UINT_8 ucStatus; + UINT_8 ucToken; /* Dialog Token in ADDTS_REQ or ADDTS_RSP */ + UINT_16 u2MediumTime; + UINT_32 u4TsInfo; + /* PARAM_QOS_TS_INFO rParamTsInfo; */ + /* Add other retained QoS parameters below */ +} TSPEC_ENTRY_T, *P_TSPEC_ENTRY_T, TSPEC_TABLE_ENTRY_T, *P_TSPEC_TABLE_ENTRY_T; + +typedef struct _SEC_INFO_T { + + ENUM_SEC_STATE_T ePreviousState; + ENUM_SEC_STATE_T eCurrentState; + + BOOLEAN fg2nd1xSend; + BOOLEAN fgKeyStored; + + UINT_8 aucStoredKey[64]; + + BOOLEAN fgAllowOnly1x; +} SEC_INFO_T, *P_SEC_INFO_T; + +#define MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS 3 + +#define UPDATE_BSS_RSSI_INTERVAL_SEC 3 /* Seconds */ + +/* Fragment information structure */ +typedef struct _FRAG_INFO_T { + UINT_16 u2NextFragSeqCtrl; + PUINT_8 pucNextFragStart; + P_SW_RFB_T pr1stFrag; + OS_SYSTIME rReceiveLifetimeLimit; /* The receive time of 1st fragment */ +} FRAG_INFO_T, *P_FRAG_INFO_T; + +typedef struct _STAT_CNT_INFO_FW_T { + UINT32 u4NumOfTx; /* number of packets sent from host */ + UINT32 u4NumOfTxOK; /* number of packets sent to air OK */ + UINT32 u4NumOfTxRetry; /* number of packets sent to air RETRY */ + UINT32 u4TxDoneAirTimeMax; /* maximum tx done air time */ + + UINT32 u4NumOfPtiRspTxOk; /* number of PTI RSP sent to air OK */ + UINT32 u4NumOfPtiRspTxErr; /* number of PTI RSP sent to air ERROR */ + + UINT32 u4NumOfTxErr; /* number of packets sent to air ERROR */ + + UINT32 u4NumOfRx; /* number of received packets */ + UINT32 u4NumOfPtiRspRx; /* number of PTI RSP rcv */ + +#define STAT_CNT_INFO_TX_ERR_FLUSHED 0x00000001 +#define STAT_CNT_INFO_TX_ERR_AGE_TIMEOUT 0x00000002 +#define STAT_CNT_INFO_TX_ERR_MPDU 0x00000004 +#define STAT_CNT_INFO_TX_ERR_RTS 0x00000010 +#define STAT_CNT_INFO_TX_ERR_LIFETIME 0x00000020 +#define STAT_CNT_INFO_TX_ERR_UNKNOWN 0x80000000 + UINT32 u4TxErrBitmap; /* TX error type */ + +#define STAT_CNT_INFO_MAX_TX_RATE_OK_HIS_NUM 10 /* TX OK history */ + UINT8 aucTxRateOkHis[STAT_CNT_INFO_MAX_TX_RATE_OK_HIS_NUM][2]; + UINT32 u4TxRateOkHisId; + +#define STAT_CNT_INFO_MAX_RATE_ID (32) /* MCS0 ~ MCS31 */ + UINT32 aucTxRateMap[STAT_CNT_INFO_MAX_RATE_ID]; + UINT32 aucRxRateMap[STAT_CNT_INFO_MAX_RATE_ID]; + + UINT8 aucStateHis[100][3]; /* State history */ + UINT32 u4StateHisId; /* history ID */ +} STAT_CNT_INFO_FW_T; + +typedef struct _STAT_CNT_INFO_DRV_T { + + UINT32 u4NumOfTxFromOs; /* number of packets sent from OS */ + UINT32 u4NumOfTxQueFull; /* number of packets dropped due to queue full */ + UINT32 u4NumOfTxToFw; /* number of packets sent to firmware */ + + STAT_CNT_INFO_FW_T rFw; +} STAT_CNT_INFO_DRV_T; + + +#if CFG_SUPPORT_802_11W +/* AP PMF */ +struct AP_PMF_CFG { + BOOLEAN fgMfpc; + BOOLEAN fgMfpr; + BOOLEAN fgSha256; + BOOLEAN fgAPApplyPmfReq; + BOOLEAN fgBipKeyInstalled; +}; + +struct STA_PMF_CFG { + BOOLEAN fgMfpc; + BOOLEAN fgMfpr; + BOOLEAN fgSha256; + BOOLEAN fgSaeRequireMfp; + BOOLEAN fgApplyPmf; + BOOLEAN fgBipKeyInstalled; + + /* for certification 4.3.3.1, 4.3.3.2 TX unprotected deauth */ + BOOLEAN fgRxDeauthResp; + + /* For PMF SA query TX request retry a timer */ + /* record the start time of 1st SAQ request */ + UINT_32 u4SAQueryStart; + UINT_32 u4SAQueryCount; + UINT_8 ucSAQueryTimedOut; /* retry more than 1000ms */ + TIMER_T rSAQueryTimer; + UINT_16 u2TransactionID; +}; +#endif + +/* Define STA record structure */ +struct _STA_RECORD_T { + LINK_ENTRY_T rLinkEntry; + UINT_8 ucIndex; /* Not modify it except initializing */ + + BOOLEAN fgIsInUse; /* Indicate if this entry is in use or not */ + UINT_8 aucMacAddr[MAC_ADDR_LEN]; /* MAC address */ + + /* SAA/AAA */ + ENUM_AA_STATE_T eAuthAssocState; /* Store STATE Value used in SAA/AAA */ + UINT_8 ucAuthAssocReqSeqNum; + + ENUM_STA_TYPE_T eStaType; /* Indicate the role of this STA in + * the network (for example, P2P GO) + */ + + UINT_8 ucNetTypeIndex; /* ENUM_NETWORK_TYPE_INDEX_T */ + + UINT_8 ucStaState; /* STATE_1,2,3 */ + + UINT_8 ucPhyTypeSet; /* Available PHY Type Set of this peer + * (may deduced from received BSS_DESC_T) + */ + UINT_8 ucDesiredPhyTypeSet; /* The match result by AND operation of peer's + * PhyTypeSet and ours. + */ + BOOLEAN fgHasBasicPhyType; /* A flag to indicate a Basic Phy Type which + * is used to generate some Phy Attribute IE + * (e.g. capability, MIB) during association. + */ + UINT_8 ucNonHTBasicPhyType; /* The Basic Phy Type chosen among the + * ucDesiredPhyTypeSet. + */ + + UINT_16 u2CapInfo; /* For Infra Mode, to store Capability Info. from Association Resp(SAA). + * For AP Mode, to store Capability Info. from Association Req(AAA). + */ + UINT_16 u2AssocId; /* For Infra Mode, to store AID from Association Resp(SAA). + * For AP Mode, to store the Assigned AID(AAA). + */ + + UINT_16 u2ListenInterval; /* Listen Interval from STA(AAA) */ + + UINT_16 u2DesiredNonHTRateSet; /* Our Current Desired Rate Set after + * match with STA's Operational Rate Set + */ + + UINT_16 u2OperationalRateSet; /* Operational Rate Set of peer BSS */ + UINT_16 u2BSSBasicRateSet; /* Basic Rate Set of peer BSS */ + + BOOLEAN fgIsMerging; /* For IBSS Mode, to indicate that Merge is ongoing */ + + BOOLEAN fgDiagnoseConnection; /* + * For Infra/AP Mode, to diagnose the Connection with + * this peer by sending ProbeReq/Null frame + */ + + /*------------------------------------------------------------------------------------------*/ + /* 802.11n HT capabilities when (prStaRec->ucPhyTypeSet & PHY_TYPE_BIT_HT) is true */ + /* They have the same definition with fields of information element */ + /*------------------------------------------------------------------------------------------*/ + UINT_8 ucMcsSet; /* MCS0~7 rate set of peer BSS */ + BOOLEAN fgSupMcs32; /* MCS32 is supported by peer BSS */ + UINT_16 u2HtCapInfo; /* HT cap info field by HT cap IE */ + UINT_8 ucAmpduParam; /* Field A-MPDU Parameters in HT cap IE */ + UINT_16 u2HtExtendedCap; /* HT extended cap field by HT cap IE */ + UINT_32 u4TxBeamformingCap; /* TX beamforming cap field by HT cap IE */ + UINT_8 ucAselCap; /* ASEL cap field by HT cap IE */ + + UINT_8 ucRCPI; /* RCPI of peer */ + + UINT_8 ucDTIMPeriod; /* Target BSS's DTIM Period, we use this + * value for setup Listen Interval + * TODO(Kevin): TBD + */ + UINT_8 ucAuthAlgNum; /* For Infra/AP Mode, the Auth Algorithm Num used in Authentication(SAA/AAA) */ + UINT_8 ucAuthTranNum; /* For Infra/AP Mode, the Auth Transaction Number */ + 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) */ + BOOLEAN afgAcmRequired[ACI_NUM]; + + /*------------------------------------------------------------------------------------------*/ + /* P2P related fields */ + /*------------------------------------------------------------------------------------------*/ +#if CFG_ENABLE_WIFI_DIRECT + UINT_8 u2DevNameLen; + UINT_8 aucDevName[WPS_ATTRI_MAX_LEN_DEVICE_NAME]; + + UINT_8 aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ + + UINT_16 u2ConfigMethods; + + UINT_8 ucDeviceCap; + + UINT_8 ucSecondaryDevTypeCount; + + DEVICE_TYPE_T rPrimaryDevTypeBE; + + DEVICE_TYPE_T arSecondaryDevTypeBE[P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT]; +#endif /* CFG_SUPPORT_P2P */ + + /*------------------------------------------------------------------------------------------*/ + /* QM related fields */ + /*------------------------------------------------------------------------------------------*/ + + UINT_8 ucFreeQuota; /* + * Per Sta flow controal. Valid when fgIsInPS is TRUE. + * Change it for per Queue flow control + */ + /* UINT_8 aucFreeQuotaPerQueue[NUM_OF_PER_STA_TX_QUEUES]; */ /* used in future */ + UINT_8 ucFreeQuotaForDelivery; + UINT_8 ucFreeQuotaForNonDelivery; +#if CFG_ENABLE_PKT_LIFETIME_PROFILE && CFG_ENABLE_PER_STA_STATISTICS + UINT_32 u4TotalTxPktsNumber; + UINT_32 u4TotalTxPktsTime; + UINT_32 u4TotalTxPktsHifTime; + + UINT_32 u4MaxTxPktsTime; + UINT_32 u4MaxTxPktsHifTime; + + UINT_32 u4ThresholdCounter; + UINT_32 u4EnqeueuCounter; + UINT_32 u4DeqeueuCounter; + UINT_32 u4PrevIntCount; + UINT_32 u4ThisIntCount; + UINT_32 u4NoTcResource; +#endif + +#if 1 + /*------------------------------------------------------------------------------------------*/ + /* To be removed, this is to make que_mgt compilation success only */ + /*------------------------------------------------------------------------------------------*/ + /* When this STA_REC is in use, set to TRUE. */ + BOOLEAN fgIsValid; + + BOOLEAN fgIsTxAllowed; + BOOLEAN fgIsTxKeyReady; + + /* Per-STA Queues: [0] AC0, [1] AC1, [2] AC2, [3] AC3, [4] 802.1x */ + QUE_T arTxQueue[NUM_OF_PER_STA_TX_QUEUES]; + + /* When this STA is in PS Mode, set to TRUE. */ + /* BOOLEAN fgIsPS; */ + + /* When this STA enters Power-Saving, FW will notify the driver with a Session ID */ + UINT_8 ucPsSessionID; + + BOOLEAN fgIsAp; + + /* Reorder Parameter reference table */ + P_RX_BA_ENTRY_T aprRxReorderParamRefTbl[CFG_RX_MAX_BA_TID_NUM]; +#endif + +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT + TIMINGMSMT_PARAM_T rWNMTimingMsmt; +#endif + +#if (CFG_SUPPORT_TDLS == 1) + BOOLEAN fgTdlsIsProhibited; /* TRUE: AP prohibits TDLS links */ + BOOLEAN fgTdlsIsChSwProhibited; /* TRUE: AP prohibits TDLS chan switch */ + + BOOLEAN flgTdlsIsInitiator; /* TRUE: the peer is the initiator */ + IE_HT_CAP_T rTdlsHtCap; /* temp to queue HT capability element */ + BOOLEAN fgTdlsInSecurityMode; /* TRUE: security mode */ + PARAM_KEY_T rTdlsKeyTemp; /* temp to queue the key information */ + +#define TDLS_SETUP_TIMEOUT_SEC 5 /* unit: second */ + OS_SYSTIME rTdlsSetupStartTime; /* time when link setup is started */ + + OS_SYSTIME rTdlsTxQuotaEmptyTime; /* time when TX quota is 0 */ + + STAT_CNT_INFO_DRV_T rTdlsStatistics; +#endif /* CFG_SUPPORT_TDLS */ + +#if (CFG_SUPPORT_STATISTICS == 1) +#define STATS_ENV_TIMEOUT_SEC 10 /* unit: second */ + OS_SYSTIME rStatsEnvTxPeriodLastTime; + +#define STATS_ENV_TX_CNT_REPORT_TRIGGER 2500 /* 6Mbps */ +#define STATS_ENV_TX_CNT_REPORT_TRIGGER_SEC 5 /* unit: second */ + OS_SYSTIME rStatsEnvTxLastTime; + UINT32 u4StatsEnvTxCnt; + + UINT32 u4NumOfNoTxQuota; + + UINT32 u4RxReorderFallAheadCnt; + UINT32 u4RxReorderFallBehindCnt; + UINT32 u4RxReorderFallBehindNoDropCnt; + UINT32 u4RxReorderHoleCnt; + UINT32 u4RxReorderHoleTimeoutCnt; + + UINT32 u4StatsRxPassToOsCnt; + + /* delay from HIF to pass to OS: us */ +#define STATS_STAY_INT_BYTE_THRESHOLD 500 + UINT32 u4StayIntMaxRx[3], u4StayIntMinRx[3], u4StayIntAvgRx[3]; + + UINT8 ucStatsGenDisplayCnt; +#endif /* CFG_SUPPORT_STATISTICS */ +#if DSCP_SUPPORT + UINT_8 qosMapSet[64]; +#endif + UINT_16 u2MaxIdlePeriod; + UINT_8 ucIdleOption; + BOOLEAN fgSupportBTM; /* flag to indicate Capbility for Bss Transition Management */ + + /* For Infra/GC Mode, a timer used to avoid the Deauth frame not be sent */ + TIMER_T rDeauthTxDoneTimer; +#if CFG_SUPPORT_802_11W + /* AP PMF */ + struct STA_PMF_CFG rPmfCfg; +#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 required for this packet */ + BOOLEAN fgBIP; /* Set to true if BIP is used for this packet */ + UINT_8 ucFragTotalCount; + UINT_8 ucFragFinishedCount; + UINT_16 u2FragThreshold; /* Fragmentation threshold without WLAN Header & FCS */ + BOOLEAN fgFixedRate; /* If a fixed rate is used, set to TRUE. */ + UINT_8 ucFixedRateCode; /* The rate code copied to MAC TX Desc */ + UINT_8 ucFixedRateRetryLimit; /* The retry limit when a fixed rate is used */ + BOOLEAN fgIsBmcQueueEnd; /* Set to true if this packet is the end of BMC */ + + /* TXM: For flushing ACL frames */ + UINT_16 u2PalLLH; /* 802.11 PAL LLH */ + /* UINT_16 u2LLH; */ + UINT_16 u2ACLSeq; /* u2LLH+u2ACLSeq for AM HCI flush ACL frame */ + + /* TXM for retransmitting a flushed packet */ + BOOLEAN fgIsSnAssigned; + UINT_16 u2SequenceNumber; /* To remember the Sequence Control field of this MPDU */ + +} MSDU_INFO_T, *P_MSDU_INFO_T; +#endif + +#if 0 +/* nic_rx.h */ +typedef struct _SW_RFB_T { + + /* 4 ----------------MSDU_INFO and SW_RFB Common Fields------------------ */ + + LINK_ENTRY_T rLinkEntry; + PUINT_8 pucBuffer; /* Pointer to the associated buffer */ + + UINT_8 ucBufferSource; /* HIF TX0, HIF TX1, MAC RX, or MNG Pool */ + UINT_8 ucNetworkTypeIndex; /* Network type index that this TX packet is assocaited with */ + UINT_8 ucTC; /* 0 to 5 (used by HIF TX to increment the corresponding TC counter) */ + UINT_8 ucTID; /* Traffic Identification */ + + BOOLEAN fgIs802_11Frame; /* Set to TRUE for 802.11 frame */ + UINT_8 ucMacHeaderLength; + UINT_16 u2PayloadLength; + PUINT_8 pucMacHeader; /* 802.11 header */ + PUINT_8 pucPayload; /* 802.11 payload */ + + OS_SYSTIME rArrivalTime; /* System Timestamp (4) */ + P_STA_RECORD_T prStaRec; + +#if CFG_PROFILE_BUFFER_TRACING + ENUM_BUFFER_ACTIVITY_TYPE_T eActivity[2]; + UINT_32 rActivityTime[2]; +#endif +#if DBG && CFG_BUFFER_FREE_CHK + BOOLEAN fgBufferInSource; +#endif + + UINT_8 ucControlFlag; /* For specify some Control Flags, e.g. Basic Rate */ + + /* 4 -----------------------Non-Common ------------------------- */ + + /* For composing the HIF RX Header (TODO: move flags to ucControlFlag) */ + PUINT_8 pucHifRxPacket; /* Pointer to the Response packet to HIF RX0 or RX1 */ + UINT_16 u2HifRxPacketLength; + UINT_8 ucHeaderOffset; + UINT_8 ucHifRxPortIndex; + + UINT_16 u2SequenceControl; + BOOLEAN fgIsA4Frame; /* (For MAC RX packet parsing) set to TRUE if 4 addresses are present */ + BOOLEAN fgIsBAR; + BOOLEAN fgIsQoSData; + BOOLEAN fgIsAmsduSubframe; /* Set to TRUE for A-MSDU Subframe */ + + /* For HIF RX DMA Desc */ + BOOLEAN fgTUChecksumCheckRequired; + BOOLEAN fgIPChecksumCheckRequired; + UINT_8 ucEtherTypeOffset; + +} SW_RFB_T, *P_SW_RFB_T; +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +P_MSDU_INFO_T cnmMgtPktAlloc(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Length); + +VOID cnmMgtPktFree(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +VOID cnmMemInit(IN P_ADAPTER_T prAdapter); + +PVOID cnmMemAlloc(IN P_ADAPTER_T prAdapter, IN ENUM_RAM_TYPE_T eRamType, IN UINT_32 u4Length); + +VOID cnmMemFree(IN P_ADAPTER_T prAdapter, IN PVOID pvMemory); + +VOID cnmStaRecInit(IN P_ADAPTER_T prAdapter); + +VOID cnmStaRecUninit(IN P_ADAPTER_T prAdapter); + +P_STA_RECORD_T cnmStaRecAlloc(IN P_ADAPTER_T prAdapter, IN UINT_8 ucNetTypeIndex); + +VOID cnmStaRecFree(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN BOOLEAN fgSyncToChip); + +VOID cnmStaFreeAllStaByNetType(P_ADAPTER_T prAdapter, ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, BOOLEAN fgSyncToChip); + +P_STA_RECORD_T cnmGetStaRecByIndex(IN P_ADAPTER_T prAdapter, IN UINT_8 ucIndex); + +P_STA_RECORD_T cnmGetStaRecByAddress(IN P_ADAPTER_T prAdapter, IN UINT_8 ucNetTypeIndex, IN UINT_8 aucPeerMACAddress[]); + +VOID cnmStaRecResetStatus(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); + +VOID cnmStaRecChangeState(IN P_ADAPTER_T prAdapter, IN OUT P_STA_RECORD_T prStaRec, IN UINT_8 ucNewState); + +P_STA_RECORD_T +cnmStaTheTypeGet(P_ADAPTER_T prAdapter, + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, ENUM_STA_TYPE_T eStaType, UINT32 *pu4StartIdx); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#ifndef _lint +/* Kevin: we don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + * We'll need this for porting driver to different RTOS. + */ +static inline VOID cnmMemDataTypeCheck(VOID) +{ +#if 0 + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, rLinkEntry) == 0); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, rLinkEntry) == OFFSET_OF(SW_RFB_T, rLinkEntry)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, pucBuffer) == OFFSET_OF(SW_RFB_T, pucBuffer)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucBufferSource) == OFFSET_OF(SW_RFB_T, ucBufferSource)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, pucMacHeader) == OFFSET_OF(SW_RFB_T, pucMacHeader)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucMacHeaderLength) == + OFFSET_OF(SW_RFB_T, ucMacHeaderLength)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, pucPayload) == OFFSET_OF(SW_RFB_T, pucPayload)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, u2PayloadLength) == OFFSET_OF(SW_RFB_T, u2PayloadLength)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, prStaRec) == OFFSET_OF(SW_RFB_T, prStaRec)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucNetworkTypeIndex) == + OFFSET_OF(SW_RFB_T, ucNetworkTypeIndex)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucTID) == OFFSET_OF(SW_RFB_T, ucTID)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, fgIs802_11Frame) == OFFSET_OF(SW_RFB_T, fgIs802_11Frame)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucControlFlag) == OFFSET_OF(SW_RFB_T, ucControlFlag)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, rArrivalTime) == OFFSET_OF(SW_RFB_T, rArrivalTime)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucTC) == OFFSET_OF(SW_RFB_T, ucTC)); + +#if CFG_PROFILE_BUFFER_TRACING + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, eActivity[0]) == OFFSET_OF(SW_RFB_T, eActivity[0])); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, rActivityTime[0]) == + OFFSET_OF(SW_RFB_T, rActivityTime[0])); +#endif + +#if DBG && CFG_BUFFER_FREE_CHK + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, fgBufferInSource) == + OFFSET_OF(SW_RFB_T, fgBufferInSource)); +#endif + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(STA_RECORD_T, rLinkEntry) == 0); + + return; +#endif +} +#endif /* _lint */ + +#endif /* _CNM_MEM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/cnm_scan.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/cnm_scan.h new file mode 100644 index 0000000000000..d8cb437810002 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/cnm_scan.h @@ -0,0 +1,115 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _CNM_SCAN_H +#define _CNM_SCAN_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define SCN_CHANNEL_DWELL_TIME_MIN_MSEC 12 +#define SCN_CHANNEL_DWELL_TIME_EXT_MSEC 98 + +#define SCN_TOTAL_PROBEREQ_NUM_FOR_FULL 3 +#define SCN_SPECIFIC_PROBEREQ_NUM_FOR_FULL 1 + +#define SCN_TOTAL_PROBEREQ_NUM_FOR_PARTIAL 2 +#define SCN_SPECIFIC_PROBEREQ_NUM_FOR_PARTIAL 1 + +#define SCN_INTERLACED_CHANNEL_GROUPS_NUM 3 /* Used by partial scan */ + +#define SCN_PARTIAL_SCAN_NUM 3 + +#define SCN_PARTIAL_SCAN_IDLE_MSEC 100 + +#define MAXIMUM_OPERATION_CHANNEL_LIST 46 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* The type of Scan Source */ +typedef enum _ENUM_SCN_REQ_SOURCE_T { + SCN_REQ_SOURCE_HEM = 0, + SCN_REQ_SOURCE_NET_FSM, + SCN_REQ_SOURCE_ROAMING, /* ROAMING Module is independent of AIS FSM */ + SCN_REQ_SOURCE_OBSS, /* 2.4G OBSS scan */ + SCN_REQ_SOURCE_NUM +} ENUM_SCN_REQ_SOURCE_T, *P_ENUM_SCN_REQ_SOURCE_T; + +typedef enum _ENUM_SCAN_PROFILE_T { + SCAN_PROFILE_FULL = 0, + SCAN_PROFILE_PARTIAL, + SCAN_PROFILE_VOIP, + SCAN_PROFILE_FULL_2G4, + SCAN_PROFILE_NUM +} ENUM_SCAN_PROFILE_T, *P_ENUM_SCAN_PROFILE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#if 0 +VOID cnmScanInit(VOID); + +VOID cnmScanRunEventScanRequest(IN P_MSG_HDR_T prMsgHdr); + +BOOLEAN cnmScanRunEventScanAbort(IN P_MSG_HDR_T prMsgHdr); + +VOID cnmScanProfileSelection(VOID); + +VOID cnmScanProcessStart(VOID); + +VOID cnmScanProcessStop(VOID); + +VOID cnmScanRunEventReqAISAbsDone(IN P_MSG_HDR_T prMsgHdr); + +VOID cnmScanRunEventCancelAISAbsDone(IN P_MSG_HDR_T prMsgHdr); + +VOID cnmScanPartialScanTimeout(UINT_32 u4Param); + +VOID cnmScanRunEventScnFsmComplete(IN P_MSG_HDR_T prMsgHdr); +#endif + +#endif /* _CNM_SCAN_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/cnm_timer.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/cnm_timer.h new file mode 100644 index 0000000000000..28c963075d95f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/cnm_timer.h @@ -0,0 +1,177 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _CNM_TIMER_H +#define _CNM_TIMER_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#undef MSEC_PER_SEC +#define MSEC_PER_SEC 1000 +#undef USEC_PER_MSEC +#define USEC_PER_MSEC 1000 +#define USEC_PER_TU 1024 /* microsecond */ + +#define MSEC_PER_MIN (60 * MSEC_PER_SEC) + +#define MGMT_MAX_TIMEOUT_INTERVAL ((UINT_32)0x7fffffff) + +#define WAKE_LOCK_MAX_TIME 5 /* Unit: sec */ + +/* If WAKE_LOCK_MAX_TIME is too large, the whole system may always keep awake + * because of periodic timer of OBSS scanning + */ +#if (WAKE_LOCK_MAX_TIME >= OBSS_SCAN_MIN_INTERVAL) +#error WAKE_LOCK_MAX_TIME is too large +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef VOID(*PFN_MGMT_TIMEOUT_FUNC) (P_ADAPTER_T, ULONG); + +typedef struct _TIMER_T { + LINK_ENTRY_T rLinkEntry; + OS_SYSTIME rExpiredSysTime; + UINT_16 u2Minutes; + UINT_16 u2Reserved; + ULONG ulData; + PFN_MGMT_TIMEOUT_FUNC pfMgmtTimeOutFunc; +} TIMER_T, *P_TIMER_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/* Check if time "a" is before time "b" */ +/* In 32-bit variable, 0x00000001~0x7fffffff -> positive number, + * 0x80000000~0xffffffff -> negative number + */ +#define TIME_BEFORE_64bit(a, b) (a < b) + +#define TIME_BEFORE(a, b) ((UINT_32)((UINT_32)(a) - (UINT_32)(b)) > 0x7fffffff) + +/* #define TIME_BEFORE(a,b) ((INT_32)((INT_32)(b) - (INT_32)(a)) > 0) + * may cause UNexpect result between Free build and Check build for WinCE + */ + +#define TIME_AFTER(a, b) TIME_BEFORE(b, a) + +#define SYSTIME_TO_SEC(_systime) ((_systime) / KAL_HZ) +#define SEC_TO_SYSTIME(_sec) ((_sec) * KAL_HZ) + +/* The macros to convert second & millisecond */ +#define MSEC_TO_SEC(_msec) ((_msec) / MSEC_PER_SEC) +#define SEC_TO_MSEC(_sec) ((UINT_32)(_sec) * MSEC_PER_SEC) + +/* The macros to convert millisecond & microsecond */ +#define USEC_TO_MSEC(_usec) ((_usec) / USEC_PER_MSEC) +#define MSEC_TO_USEC(_msec) ((UINT_32)(_msec) * USEC_PER_MSEC) + +/* The macros to convert TU & microsecond, TU & millisecond */ +#define TU_TO_USEC(_tu) ((_tu) * USEC_PER_TU) +#define TU_TO_MSEC(_tu) USEC_TO_MSEC(TU_TO_USEC(_tu)) + +/* The macros to convert TU & & OS system time, round up by 0.5 */ +#define TU_TO_SYSTIME(_tu) MSEC_TO_SYSTIME(TU_TO_MSEC(_tu)) +#define SYSTIME_TO_TU(_systime) \ + ((SYSTIME_TO_USEC(_systime) + ((USEC_PER_TU / 2) - 1)) / USEC_PER_TU) + +/* The macros to convert OS system time & microsecond */ +#define SYSTIME_TO_USEC(_systime) (SYSTIME_TO_MSEC(_systime) * USEC_PER_MSEC) + +/* The macro to get the current OS system time */ +#define GET_CURRENT_SYSTIME(_systime_p) {*(_systime_p) = kalGetTimeTick(); } + +/* The macro to copy the system time */ +#define COPY_SYSTIME(_destTime, _srcTime) {(_destTime) = (_srcTime); } + +/* The macro to get the system time difference between t1 and t2 (t1 - t2) */ +/* + * #define GET_SYSTIME_DIFFERENCE(_time1, _time2, _diffTime) \ + * (_diffTime) = (_time1) - (_time2) + */ + +/* The macro to check for the expiration, if TRUE means _currentTime >= _expirationTime */ +#define CHECK_FOR_EXPIRATION(_currentTime, _expirationTime) \ + (((UINT_32)(_currentTime) - (UINT_32)(_expirationTime)) <= 0x7fffffffUL) + +/* The macro to check for the timeout */ +#define CHECK_FOR_TIMEOUT(_currentTime, _timeoutStartingTime, _timeout) \ + CHECK_FOR_EXPIRATION((_currentTime), ((_timeoutStartingTime) + (_timeout))) + +/* The macro to set the expiration time with a specified timeout *//* Watch out for round up. */ +#define SET_EXPIRATION_TIME(_expirationTime, _timeout) \ + { \ + GET_CURRENT_SYSTIME(&(_expirationTime)); \ + (_expirationTime) += (OS_SYSTIME)(_timeout); \ + } + +#define timerRenewTimer(adapter, tmr, interval) \ + timerStartTimer(adapter, tmr, interval, (tmr)->function, (tmr)->data) + +#define MGMT_INIT_TIMER(_adapter_p, _timer, _callbackFunc) \ + timerInitTimer(_adapter_p, &(_timer), (ULONG)(_callbackFunc)) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID cnmTimerInitialize(IN P_ADAPTER_T prAdapter); + +VOID cnmTimerDestroy(IN P_ADAPTER_T prAdapter); + +VOID +cnmTimerInitTimer(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer, IN PFN_MGMT_TIMEOUT_FUNC pfFunc, IN ULONG ulData); + +VOID cnmTimerStopTimer(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer); + +VOID cnmTimerStartTimer(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer, IN UINT_32 u4TimeoutMs); + +VOID cnmTimerDoTimeOutCheck(IN P_ADAPTER_T prAdapter); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +static inline INT_32 timerPendingTimer(IN P_TIMER_T prTimer) +{ + ASSERT(prTimer); + + return prTimer->rLinkEntry.prNext != NULL; +} + +#endif /* _CNM_TIMER_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/hem_mbox.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/hem_mbox.h new file mode 100644 index 0000000000000..df1e8f08041f2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/hem_mbox.h @@ -0,0 +1,278 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _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_OID_SAA_FSM_CONTINUE, /* OID notify SAA to continue to do authentication/association fsm for FT */ + MID_OID_SAA_FSM_EXTERNAL_AUTH, /* OID notify SAA to continue SAE authentication/association fsm */ + MID_AIS_SAA_FSM_ABORT, /* AIS notify SAA for Aborting authentication/association fsm */ + MID_SAA_AIS_JOIN_COMPLETE, /* SAA notify AIS for indicating join complete */ + +#if CFG_ENABLE_BT_OVER_WIFI + /*--------------------------------------------------*/ + /* BOW Module Mailbox Messages */ + /*--------------------------------------------------*/ + MID_BOW_SAA_FSM_START, /* BOW notify SAA for Starting authentication/association fsm */ + MID_BOW_SAA_FSM_ABORT, /* BOW notify SAA for Aborting authentication/association fsm */ + MID_SAA_BOW_JOIN_COMPLETE, /* SAA notify BOW for indicating join complete */ +#endif + +#if CFG_ENABLE_WIFI_DIRECT + /*--------------------------------------------------*/ + /* P2P Module Mailbox Messages */ + /*--------------------------------------------------*/ + MID_P2P_SAA_FSM_START, /* P2P notify SAA for Starting authentication/association fsm */ + MID_P2P_SAA_FSM_ABORT, /* P2P notify SAA for Aborting authentication/association fsm */ + MID_SAA_P2P_JOIN_COMPLETE, /* SAA notify P2P for indicating join complete */ + + MID_MNY_P2P_FUN_SWITCH, /* Enable P2P FSM. */ + MID_MNY_P2P_DEVICE_DISCOVERY, /* Start device discovery. */ + MID_MNY_P2P_CONNECTION_REQ, /* Connection request. */ + MID_MNY_P2P_CONNECTION_ABORT, /* Abort connection request, P2P FSM return to IDLE. */ + MID_MNY_P2P_BEACON_UPDATE, + MID_MNY_P2P_STOP_AP, + MID_MNY_P2P_CHNL_REQ, + MID_MNY_P2P_CHNL_ABORT, + MID_MNY_P2P_MGMT_TX, + MID_MNY_P2P_GROUP_DISSOLVE, + MID_MNY_P2P_MGMT_FRAME_REGISTER, + MID_MNY_P2P_NET_DEV_REGISTER, + MID_MNY_P2P_START_AP, + MID_MNY_P2P_MGMT_FRAME_UPDATE, + MID_MNY_P2P_EXTEND_LISTEN_INTERVAL, +#if CFG_SUPPORT_P2P_ECSA + MID_MNY_P2P_CSA, + MID_MNY_P2P_ECSA, +#endif +#if CFG_SUPPORT_WFD + MID_MNY_P2P_WFD_CFG_UPDATE, +#endif +#endif + +#if CFG_SUPPORT_ADHOC + MID_SCN_AIS_FOUND_IBSS, /* SCN notify AIS that an IBSS Peer has been found and can merge into */ +#endif /* CFG_SUPPORT_ADHOC */ + + MID_SAA_AIS_FSM_ABORT, /* SAA notify AIS for indicating deauthentication/disassociation */ + + /*--------------------------------------------------*/ + /* AIS MGMT-TX Support */ + /*--------------------------------------------------*/ + MID_MNY_AIS_REMAIN_ON_CHANNEL, + MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL, + MID_MNY_AIS_MGMT_TX, + MID_MNY_CNM_REQ_CH_UTIL, + MID_CNM_AIS_RSP_CH_UTIL, + MID_MNY_CNM_SCAN_CONTINUE, + MID_WNM_AIS_BSS_TRANSITION, + MID_OID_WMM_TSPEC_OPERATE, + MID_RLM_RM_SCHEDULE, +#if CFG_SUPPORT_NCHO + MID_MNY_AIS_NCHO_ACTION_FRAME, +#endif + MID_MNY_P2P_ACS, + MID_TOTAL_NUM +} ENUM_MSG_ID_T, *P_ENUM_MSG_ID_T; + +/* Message header of inter-components */ +struct _MSG_HDR_T { + LINK_ENTRY_T rLinkEntry; + ENUM_MSG_ID_T eMsgId; +}; + +typedef VOID(*PFN_MSG_HNDL_FUNC) (P_ADAPTER_T, P_MSG_HDR_T); + +typedef struct _MSG_HNDL_ENTRY { + ENUM_MSG_ID_T eMsgId; + PFN_MSG_HNDL_FUNC pfMsgHndl; +} MSG_HNDL_ENTRY_T, *P_MSG_HNDL_ENTRY_T; + +typedef enum _EUNM_MSG_SEND_METHOD_T { + MSG_SEND_METHOD_BUF = 0, /* + * Message is put in the queue and will be + * executed when mailbox is checked. + */ + MSG_SEND_METHOD_UNBUF /* + * The handler function is called immediately + * in the same context of the sender + */ +} EUNM_MSG_SEND_METHOD_T, *P_EUNM_MSG_SEND_METHOD_T; + +typedef enum _ENUM_MBOX_ID_T { + MBOX_ID_0 = 0, + MBOX_ID_TOTAL_NUM +} ENUM_MBOX_ID_T, *P_ENUM_MBOX_ID_T; + +/* Define Mailbox structure */ +typedef struct _MBOX_T { + LINK_T rLinkHead; +} MBOX_T, *P_MBOX_T; + +typedef struct _MSG_SAA_FSM_START_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + P_STA_RECORD_T prStaRec; +} MSG_SAA_FSM_START_T, *P_MSG_SAA_FSM_START_T; + +typedef struct _MSG_SAA_FSM_COMP_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + WLAN_STATUS rJoinStatus; + P_STA_RECORD_T prStaRec; + P_SW_RFB_T prSwRfb; +} MSG_SAA_FSM_COMP_T, *P_MSG_SAA_FSM_COMP_T; + +typedef struct _MSG_SAA_FSM_ABORT_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + P_STA_RECORD_T prStaRec; +} MSG_SAA_FSM_ABORT_T, *P_MSG_SAA_FSM_ABORT_T; + +typedef struct _MSG_CONNECTION_ABORT_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucNetTypeIndex; +} MSG_CONNECTION_ABORT_T, *P_MSG_CONNECTION_ABORT_T; + +typedef struct _MSG_REMAIN_ON_CHANNEL_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + ENUM_BAND_T eBand; + ENUM_CHNL_EXT_T eSco; + UINT_8 ucChannelNum; + UINT_32 u4DurationMs; + UINT_64 u8Cookie; +} MSG_REMAIN_ON_CHANNEL_T, *P_MSG_REMAIN_ON_CHANNEL_T; + +typedef struct _MSG_CANCEL_REMAIN_ON_CHANNEL_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_64 u8Cookie; +} MSG_CANCEL_REMAIN_ON_CHANNEL_T, *P_MSG_CANCEL_REMAIN_ON_CHANNEL_T; + +typedef struct _MSG_MGMT_TX_REQUEST_T { + MSG_HDR_T rMsgHdr; + P_MSDU_INFO_T prMgmtMsduInfo; + UINT_64 u8Cookie; /* For indication. */ + BOOLEAN fgNoneCckRate; + BOOLEAN fgIsWaitRsp; +} MSG_MGMT_TX_REQUEST_T, *P_MSG_MGMT_TX_REQUEST_T; + +struct MSG_SAA_FT_CONTINUE { + MSG_HDR_T rMsgHdr; + P_STA_RECORD_T prStaRec; + BOOLEAN fgFTRicRequest; /* if fgFTRicRequest is TRUE, then will do FT Resource Request Protocol */ +}; + +struct MSG_SAA_EXTERNAL_AUTH_DONE { + MSG_HDR_T rMsgHdr; + P_STA_RECORD_T prStaRec; + uint16_t status; +}; + +/* specific message data types */ +typedef MSG_SAA_FSM_START_T MSG_JOIN_REQ_T, *P_MSG_JOIN_REQ_T; +typedef MSG_SAA_FSM_COMP_T MSG_JOIN_COMP_T, *P_MSG_JOIN_COMP_T; +typedef MSG_SAA_FSM_ABORT_T MSG_JOIN_ABORT_T, *P_MSG_JOIN_ABORT_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID mboxSetup(IN P_ADAPTER_T prAdapter, IN ENUM_MBOX_ID_T eMboxId); + +VOID +mboxSendMsg(IN P_ADAPTER_T prAdapter, + IN ENUM_MBOX_ID_T eMboxId, IN P_MSG_HDR_T prMsg, IN EUNM_MSG_SEND_METHOD_T eMethod); + +VOID mboxRcvAllMsg(IN P_ADAPTER_T prAdapter, IN ENUM_MBOX_ID_T eMboxId); + +VOID mboxInitialize(IN P_ADAPTER_T prAdapter); + +VOID mboxDestroy(IN P_ADAPTER_T prAdapter); + +VOID mboxDummy(IN P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _HEM_MBOX_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/hs20.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/hs20.h new file mode 100644 index 0000000000000..5ed221a0386d7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/hs20.h @@ -0,0 +1,142 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _HS20_H +#define _HS20_H + +#if CFG_SUPPORT_HOTSPOT_2_0 +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define BSSID_POOL_MAX_SIZE 8 +#define HS20_SIGMA_SCAN_RESULT_TIMEOUT 30 /* sec */ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +#if CFG_ENABLE_GTK_FRAME_FILTER +/*For GTK Frame Filter*/ +typedef struct _IPV4_NETWORK_ADDRESS_LIST { + UINT_8 ucAddrCount; + IPV4_NETWORK_ADDRESS arNetAddr[1]; +} IPV4_NETWORK_ADDRESS_LIST, *P_IPV4_NETWORK_ADDRESS_LIST; +#endif + +/* Entry of BSSID Pool - For SIGMA Test */ +typedef struct _BSSID_ENTRY_T { + UINT_8 aucBSSID[MAC_ADDR_LEN]; +} BSSID_ENTRY_T, P_HS20_BSSID_POOL_ENTRY_T; + +struct _HS20_INFO_T { + + /*Hotspot 2.0 Information */ + UINT_8 aucHESSID[MAC_ADDR_LEN]; + UINT_8 ucAccessNetworkOptions; + UINT_8 ucVenueGroup; /* VenueInfo - Group */ + UINT_8 ucVenueType; + UINT_8 ucHotspotConfig; + + /*Roaming Consortium Information */ + /* PARAM_HS20_ROAMING_CONSORTIUM_INFO rRCInfo; */ + + /*Hotspot 2.0 dummy AP Info */ + + /*Time Advertisement Information */ + /* UINT_32 u4UTCOffsetTime; */ + /* UINT_8 aucTimeZone[ELEM_MAX_LEN_TIME_ZONE]; */ + /* UINT_8 ucLenTimeZone; */ + + /* For SIGMA Test */ + /* BSSID Pool */ + BSSID_ENTRY_T arBssidPool[BSSID_POOL_MAX_SIZE]; + UINT_8 ucNumBssidPoolEntry; + BOOLEAN fgIsHS2SigmaMode; + +}; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/*For GTK Frame Filter*/ +#if DBG +#define FREE_IPV4_NETWORK_ADDR_LIST(_prAddrList) \ + { \ + UINT_32 u4Size = OFFSET_OF(IPV4_NETWORK_ADDRESS_LIST, arNetAddr) + \ + (((_prAddrList)->ucAddrCount) * sizeof(IPV4_NETWORK_ADDRESS)); \ + kalMemFree((_prAddrList), VIR_MEM_TYPE, u4Size); \ + (_prAddrList) = NULL; \ + } +#else +#define FREE_IPV4_NETWORK_ADDR_LIST(_prAddrList) \ + { \ + kalMemFree((_prAddrList), VIR_MEM_TYPE, 0); \ + (_prAddrList) = NULL; \ + } +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +VOID hs20FillExtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo); + +VOID hs20FillProreqExtCapIE(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucIE); + +VOID hs20FillHS20IE(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucIE); + +UINT_32 hs20CalculateHS20RelatedIEForProbeReq(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucTargetBSSID); + +WLAN_STATUS hs20GenerateHS20RelatedIEForProbeReq(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucTargetBSSID, OUT PUINT_8 prIE); + +BOOLEAN hs20IsGratuitousArp(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prCurrSwRfb); + +BOOLEAN hs20IsUnsolicitedNeighborAdv(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prCurrSwRfb); + +#if CFG_ENABLE_GTK_FRAME_FILTER +BOOLEAN hs20IsForgedGTKFrame(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_SW_RFB_T prCurrSwRfb); +#endif + +BOOLEAN hs20IsUnsecuredFrame(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_SW_RFB_T prCurrSwRfb); + +BOOLEAN hs20IsFrameFilterEnabled(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo); + +WLAN_STATUS hs20SetBssidPool(IN P_ADAPTER_T prAdapter, IN PVOID pvBuffer, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx); + +#endif +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/mib.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/mib.h new file mode 100644 index 0000000000000..ade7bea2ed845 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/mib.h @@ -0,0 +1,129 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _MIB_H +#define _MIB_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Entry in SMT AuthenticationAlgorithms Table: dot11AuthenticationAlgorithmsEntry */ +typedef struct _DOT11_AUTHENTICATION_ALGORITHMS_ENTRY { + BOOLEAN dot11AuthenticationAlgorithmsEnable; /* dot11AuthenticationAlgorithmsEntry 3 */ +} DOT11_AUTHENTICATION_ALGORITHMS_ENTRY, *P_DOT11_AUTHENTICATION_ALGORITHMS_ENTRY; + +/* Entry in SMT dot11RSNAConfigPairwiseCiphersTalbe Table: dot11RSNAConfigPairwiseCiphersEntry */ +typedef struct _DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY { + UINT_32 dot11RSNAConfigPairwiseCipher; /* dot11RSNAConfigPairwiseCiphersEntry 2 */ + BOOLEAN dot11RSNAConfigPairwiseCipherEnabled; /* dot11RSNAConfigPairwiseCiphersEntry 3 */ +} DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY, *P_DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY; + +/* Entry in SMT dot11RSNAConfigAuthenticationSuitesTalbe Table: dot11RSNAConfigAuthenticationSuitesEntry */ +typedef struct _DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY { + UINT_32 dot11RSNAConfigAuthenticationSuite; /* dot11RSNAConfigAuthenticationSuitesEntry 2 */ + BOOLEAN dot11RSNAConfigAuthenticationSuiteEnabled; /* dot11RSNAConfigAuthenticationSuitesEntry 3 */ +} DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY, *P_DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY; + +/* ----- IEEE 802.11 MIB Major sections ----- */ +typedef struct _IEEE_802_11_MIB_T { + /* dot11PrivacyTable (dot11smt 5) */ + UINT_8 dot11WEPDefaultKeyID; /* dot11PrivacyEntry 2 */ + BOOLEAN dot11TranmitKeyAvailable; + UINT_32 dot11WEPICVErrorCount; /* dot11PrivacyEntry 5 */ + UINT_32 dot11WEPExcludedCount; /* dot11PrivacyEntry 6 */ + + /* dot11RSNAConfigTable (dot11smt 8) */ + UINT_32 dot11RSNAConfigGroupCipher; /* dot11RSNAConfigEntry 4 */ + + /* dot11RSNAConfigPairwiseCiphersTable (dot11smt 9) */ + DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY dot11RSNAConfigPairwiseCiphersTable[MAX_NUM_SUPPORTED_CIPHER_SUITES]; + + /* dot11RSNAConfigAuthenticationSuitesTable (dot11smt 10) */ + DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY + dot11RSNAConfigAuthenticationSuitesTable[MAX_NUM_SUPPORTED_AKM_SUITES]; + +#if 0 /* SUPPORT_WAPI */ + BOOLEAN fgWapiKeyInstalled; + PARAM_WPI_KEY_T rWapiPairwiseKey[2]; + BOOLEAN fgPairwiseKeyUsed[2]; + UINT_8 ucWpiActivedPWKey; /* Must be 0 or 1, by wapi spec */ + PARAM_WPI_KEY_T rWapiGroupKey[2]; + BOOLEAN fgGroupKeyUsed[2]; +#endif +} IEEE_802_11_MIB_T, *P_IEEE_802_11_MIB_T; + +/* ------------------ IEEE 802.11 non HT PHY characteristics ---------------- */ +typedef const struct _NON_HT_PHY_ATTRIBUTE_T { + UINT_16 u2SupportedRateSet; + + BOOLEAN fgIsShortPreambleOptionImplemented; + + BOOLEAN fgIsShortSlotTimeOptionImplemented; + +} NON_HT_PHY_ATTRIBUTE_T, *P_NON_HT_PHY_ATTRIBUTE_T; + +typedef const struct _NON_HT_ADHOC_MODE_ATTRIBUTE_T { + + ENUM_PHY_TYPE_INDEX_T ePhyTypeIndex; + + UINT_16 u2BSSBasicRateSet; + +} NON_HT_ADHOC_MODE_ATTRIBUTE_T, *P_NON_HT_ADHOC_MODE_ATTRIBUTE_T; + +typedef NON_HT_ADHOC_MODE_ATTRIBUTE_T NON_HT_AP_MODE_ATTRIBUTE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +extern NON_HT_PHY_ATTRIBUTE_T rNonHTPhyAttributes[]; +extern NON_HT_ADHOC_MODE_ATTRIBUTE_T rNonHTAdHocModeAttributes[]; +extern NON_HT_AP_MODE_ATTRIBUTE_T rNonHTApModeAttributes[]; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _MIB_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_assoc.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_assoc.h new file mode 100644 index 0000000000000..360fee42d5258 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_assoc.h @@ -0,0 +1,59 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _P2P_ASSOC_H +#define _P2P_ASSOC_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +PUINT_8 p2pBuildReAssocReqFrameCommonIEs(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN PUINT_8 pucBuffer); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_bss.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_bss.h new file mode 100644 index 0000000000000..8213f7d1e34fb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_bss.h @@ -0,0 +1,59 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _P2P_BSS_H +#define _P2P_BSS_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +UINT_32 p2pGetTxProbRspIeTableSize(VOID); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_fsm.h new file mode 100644 index 0000000000000..ff06afe446993 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_fsm.h @@ -0,0 +1,1871 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _P2P_FSM_H +#define _P2P_FSM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#define CID52_53_54 0 + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_P2P_STATE_T { + P2P_STATE_IDLE = 0, + P2P_STATE_SCAN, + P2P_STATE_AP_CHANNEL_DETECT, + P2P_STATE_REQING_CHANNEL, + P2P_STATE_CHNL_ON_HAND, /* Requesting Channel to Send Specific Frame. */ + P2P_STATE_GC_JOIN, /* Sending Specific Frame. May extending channel by other event. */ + P2P_STATE_NUM +} ENUM_P2P_STATE_T, *P_ENUM_P2P_STATE_T; + + +enum _ENUM_P2P_DEV_EXT_LISTEN_T { + P2P_DEV_NOT_EXT_LISTEN, + P2P_DEV_EXT_LISTEN_ING, + P2P_DEV_EXT_LISTEN_WAITFOR_TIMEOUT, + P2P_DEV_EXT_LISTEN_NUM +}; +typedef enum _ENUM_P2P_CONNECT_STATE_T { + P2P_CNN_NORMAL = 0, + P2P_CNN_GO_NEG_REQ, + P2P_CNN_GO_NEG_RESP, + P2P_CNN_GO_NEG_CONF, + P2P_CNN_INVITATION_REQ, + P2P_CNN_INVITATION_RESP, + P2P_CNN_DEV_DISC_REQ, + P2P_CNN_DEV_DISC_RESP, + P2P_CNN_PROV_DISC_REQ, + P2P_CNN_PROV_DISC_RES +} ENUM_P2P_CNN_STATE_T, *P_ENUM_P2P_CNN_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_ZERO_LEN, + ENUM_HIDDEN_SSID_ZERO_CONTENT, + ENUM_HIDDEN_SSID_NUM +} ENUM_HIDDEN_SSID_TYPE_T, *P_ENUM_HIDDEN_SSID_TYPE_T; + +typedef struct _P2P_SSID_STRUCT_T { + UINT_8 aucSsid[32]; + UINT_8 ucSsidLen; +} P2P_SSID_STRUCT_T, *P_P2P_SSID_STRUCT_T; + +typedef struct _P2P_STATION_INFO_T { + UINT_32 u4InactiveTime; + UINT_32 u4RxBytes; /* TODO: */ + UINT_32 u4TxBytes; /* TODO: */ + UINT_32 u4RxPackets; /* TODO: */ + UINT_32 u4TxPackets; /* TODO: */ + /* TODO: Add more for requirement. */ +} P2P_STATION_INFO_T, *P_P2P_STATION_INFO_T; + +typedef struct _AP_CRYPTO_SETTINGS_T { + UINT_32 u4WpaVersion; + UINT_32 u4CipherGroup; + INT_32 i4NumOfCiphers; + UINT_32 aucCiphersPairwise[5]; + INT_32 i4NumOfAkmSuites; + UINT_32 aucAkmSuites[2]; + BOOLEAN fgIsControlPort; + UINT_16 u2ControlPortBE; + BOOLEAN fgIsControlPortEncrypt; +} AP_CRYPTO_SETTINGS_T, *P_AP_CRYPTO_SETTINGS_T; + +/*-------------------- P2P FSM ACTION STRUCT ---------------------*/ +typedef struct _P2P_CHNL_REQ_INFO_T { + BOOLEAN fgIsChannelRequested; + UINT_8 ucSeqNumOfChReq; + UINT_64 u8Cookie; + UINT_8 ucReqChnlNum; + ENUM_BAND_T eBand; + ENUM_CHNL_EXT_T eChnlSco; + UINT_32 u4MaxInterval; + ENUM_CHANNEL_REQ_TYPE_T eChannelReqType; + + UINT_8 ucOriChnlNum; + ENUM_BAND_T eOriBand; + ENUM_CHNL_EXT_T eOriChnlSco; + UINT_32 NFC_BEAM; /*NFC Beam + Indication */ +} P2P_CHNL_REQ_INFO_T, *P_P2P_CHNL_REQ_INFO_T; + +typedef struct _P2P_SCAN_REQ_INFO_T { + ENUM_SCAN_TYPE_T eScanType; + ENUM_SCAN_CHANNEL eChannelSet; + UINT_16 u2PassiveDewellTime; + UINT_8 ucSeqNumOfScnMsg; + BOOLEAN fgIsAbort; + BOOLEAN fgIsScanRequest; + UINT_8 ucNumChannelList; + RF_CHANNEL_INFO_T arScanChannelList[MAXIMUM_OPERATION_CHANNEL_LIST]; + UINT_32 u4BufLength; + UINT_8 aucIEBuf[MAX_IE_LENGTH]; + P2P_SSID_STRUCT_T rSsidStruct; /* Currently we can only take one SSID scan request */ + BOOLEAN fgIsGOInitialDone; + u_int8_t fgIsAcsReq; +} 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_GC_DISCONNECTION_REQ_INFO_T { + P_STA_RECORD_T prTargetStaRec; + UINT_32 u4RetryCount; + UINT_16 u2ReasonCode; + BOOLEAN fgSendDeauth; +} P2P_GC_DISCONNECTION_REQ_INFO_T, *P_P2P_GC_DISCONNECTION_REQ_INFO_T; + +typedef struct _P2P_MGMT_TX_REQ_INFO_T { + BOOLEAN fgIsMgmtTxRequested; + P_MSDU_INFO_T prMgmtTxMsdu; + UINT_64 u8Cookie; +} P2P_MGMT_TX_REQ_INFO_T, *P_P2P_MGMT_TX_REQ_INFO_T; + +struct _MSG_P2P_EXTEND_LISTEN_INTERVAL_T { + MSG_HDR_T rMsgHdr; + UINT_32 wait; /* interval supplicant expected to stay in listen interval */ +}; + +typedef struct _P2P_BEACON_UPDATE_INFO_T { + PUINT_8 pucBcnHdr; + UINT_32 u4BcnHdrLen; + PUINT_8 pucBcnBody; + UINT_32 u4BcnBodyLen; +} P2P_BEACON_UPDATE_INFO_T, *P_P2P_BEACON_UPDATE_INFO_T; + +typedef struct _P2P_PROBE_RSP_UPDATE_INFO_T { + P_MSDU_INFO_T prProbeRspMsduTemplate; +} P2P_PROBE_RSP_UPDATE_INFO_T, *P_P2P_PROBE_RSP_UPDATE_INFO_T; + +typedef struct _P2P_ASSOC_RSP_UPDATE_INFO_T { + PUINT_8 pucAssocRspExtIE; + UINT_16 u2AssocIELen; +} P2P_ASSOC_RSP_UPDATE_INFO_T, *P_P2P_ASSOC_RSP_UPDATE_INFO_T; + +typedef struct _P2P_JOIN_INFO_T { + UINT_32 ucSeqNumOfReqMsg; + UINT_8 ucAvailableAuthTypes; + P_STA_RECORD_T prTargetStaRec; + P2P_SSID_STRUCT_T rSsidStruct; + BOOLEAN fgIsJoinComplete; + /* For ASSOC Rsp. */ + UINT_32 u4BufLength; + UINT_8 aucIEBuf[MAX_IE_LENGTH]; +} P2P_JOIN_INFO_T, *P_P2P_JOIN_INFO_T; + +#if CFG_SUPPORT_WFD + +#define WFD_FLAGS_DEV_INFO_VALID BIT(0) /* 1. WFD_DEV_INFO, 2. WFD_CTRL_PORT, 3. WFD_MAT_TP. */ +#define WFD_FLAGS_SINK_INFO_VALID BIT(1) /* 1. WFD_SINK_STATUS, 2. WFD_SINK_MAC. */ +#define WFD_FLAGS_ASSOC_MAC_VALID BIT(2) /* 1. WFD_ASSOC_MAC. */ +#define WFD_FLAGS_EXT_CAPABILITY_VALID BIT(3) /* 1. WFD_EXTEND_CAPABILITY. */ + +struct _WFD_CFG_SETTINGS_T { + UINT_32 u4WfdCmdType; + UINT_8 ucWfdEnable; + UINT_8 ucWfdCoupleSinkStatus; + UINT_8 ucWfdSessionAvailable; /* 0: NA 1:Set 2:Clear */ + UINT_8 ucWfdSigmaMode; + UINT_16 u2WfdDevInfo; + UINT_16 u2WfdControlPort; + UINT_16 u2WfdMaximumTp; + UINT_16 u2WfdExtendCap; + UINT_8 aucWfdCoupleSinkAddress[MAC_ADDR_LEN]; + UINT_8 aucWfdAssociatedBssid[MAC_ADDR_LEN]; + UINT_8 aucWfdVideoIp[4]; + UINT_8 aucWfdAudioIp[4]; + UINT_16 u2WfdVideoPort; + UINT_16 u2WfdAudioPort; + UINT_32 u4WfdFlag; + UINT_32 u4WfdPolicy; + UINT_32 u4WfdState; + UINT_8 aucWfdSessionInformationIE[24 * 8]; + UINT_16 u2WfdSessionInformationIELen; + UINT_8 aucReserved1[2]; + UINT_8 aucWfdPrimarySinkMac[MAC_ADDR_LEN]; + UINT_8 aucWfdSecondarySinkMac[MAC_ADDR_LEN]; + UINT_32 u4WfdAdvancedFlag; + /* Group 1 64 bytes */ + UINT_8 aucWfdLocalIp[4]; + UINT_16 u2WfdLifetimeAc2; /* Unit is 2 TU */ + UINT_16 u2WfdLifetimeAc3; /* Unit is 2 TU */ + UINT_16 u2WfdCounterThreshold; /* Unit is ms */ + UINT_8 aucReverved2[54]; + /* Group 2 64 bytes */ + UINT_8 aucReverved3[64]; + /* Group 3 64 bytes */ + UINT_8 aucReverved4[64]; + +}; + +struct _WFD_DBG_CFG_SETTINGS_T { + UINT_8 ucWfdDebugMode; + UINT_16 u2WfdSNShowPeiroid; + UINT_8 Reserved; + +}; + +#endif + +enum P2P_VENDOR_ACS_HW_MODE { + P2P_VENDOR_ACS_HW_MODE_11B, + P2P_VENDOR_ACS_HW_MODE_11G, + P2P_VENDOR_ACS_HW_MODE_11A, + P2P_VENDOR_ACS_HW_MODE_11AD, + P2P_VENDOR_ACS_HW_MODE_11ANY +}; + +struct P2P_ACS_REQ_INFO { + u_int8_t fgIsProcessing; + u_int8_t fgIsHtEnable; + u_int8_t fgIsHt40Enable; + u_int8_t fgIsVhtEnable; + enum ENUM_MAX_BANDWIDTH_SETTING eChnlBw; + enum P2P_VENDOR_ACS_HW_MODE eHwMode; + uint32_t u4LteSafeChnMask_2G; + uint32_t u4LteSafeChnMask_5G_1; + uint32_t u4LteSafeChnMask_5G_2; + + /* output only */ + uint8_t ucPrimaryCh; + uint8_t ucSecondCh; + uint8_t ucCenterFreqS1; + uint8_t ucCenterFreqS2; +}; + +struct _P2P_FSM_INFO_T { + /* State related. */ + ENUM_P2P_STATE_T ePreviousState; + ENUM_P2P_STATE_T eCurrentState; + ENUM_P2P_CNN_STATE_T eCNNState; + + /* Channel related. */ + P2P_CHNL_REQ_INFO_T rChnlReqInfo; + + /* Scan related. */ + P2P_SCAN_REQ_INFO_T rScanReqInfo; + + /* Connection related. */ + P2P_CONNECTION_REQ_INFO_T rConnReqInfo; + + /* Disconnection related. */ + P2P_GC_DISCONNECTION_REQ_INFO_T rGcDisConnReqInfo; + + /* Mgmt tx related. */ + P2P_MGMT_TX_REQ_INFO_T rMgmtTxInfo; + + /* Auto channel selection related. */ + struct P2P_ACS_REQ_INFO rAcsReqInfo; + + /* Beacon related. */ + P2P_BEACON_UPDATE_INFO_T rBcnContentInfo; + + /* Probe Response related. */ + P2P_PROBE_RSP_UPDATE_INFO_T rProbeRspContentInfo; + + /* Assoc Rsp related. */ + P2P_ASSOC_RSP_UPDATE_INFO_T rAssocRspContentInfo; + + /* GC Join related. */ + P2P_JOIN_INFO_T rJoinInfo; + + /* FSM Timer */ +/* TIMER_T rP2pFsmTimeoutTimer; */ + + /* GC Target BSS. */ + P_BSS_DESC_T prTargetBss; + + /* GC Connection Request. */ + BOOLEAN fgIsConnectionRequested; + + BOOLEAN fgIsApMode; + + /* Channel grant interval. */ + UINT_32 u4GrantInterval; + + /* Packet filter for P2P module. */ + UINT_32 u4P2pPacketFilter; + + /* vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv Prepare for use vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv */ + /* Msg event queue. */ + LINK_T rMsgEventQueue; + +#if CFG_SUPPORT_WFD + WFD_CFG_SETTINGS_T rWfdConfigureSettings; + WFD_DBG_CFG_SETTINGS_T rWfdDebugSetting; +#endif + + BOOLEAN fgIsWPSMode; + + enum _ENUM_P2P_DEV_EXT_LISTEN_T eListenExted; + + BOOLEAN fgIsChannelExtended; + + /* Queued p2p action frame */ + struct P2P_QUEUED_ACTION_FRAME rQueuedActionFrame; +}; + +/*---------------- 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; + u_int8_t fgIsAcsReq; + 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; +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP + PUINT_8 pucProbeRsp; + UINT_32 u4ProbeRsp_len; +#endif + 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; + enum ENUM_IFTYPE eIftype; +} 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; + +typedef struct _P2P_ECSA_SETTING_T { + u8 mode; + u8 channel; + u8 sco; + u8 op_class; + u8 count; +} P2P_ECSA_SETTING_T, *P_P2P_ECSA_SETTING_T; + +typedef struct _MSG_P2P_ECSA_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + P2P_ECSA_SETTING_T rP2pECSA; +} MSG_P2P_ECSA_T, *P_MSG_P2P_ECSA_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 + +struct MSG_P2P_ACS_REQUEST { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + BOOLEAN fgIsHtEnable; + BOOLEAN fgIsHt40Enable; + BOOLEAN fgIsVhtEnable; + enum ENUM_MAX_BANDWIDTH_SETTING eChnlBw; + enum P2P_VENDOR_ACS_HW_MODE eHwMode; + UINT_32 u4NumChannel; + RF_CHANNEL_INFO_T arChannelListInfo[1]; +}; + +/******************************************************************************* +* 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 p2pFsmRunEventScanAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventMgmtFrameTx(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventStartAP(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventNetDeviceRegister(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventUpdateMgmtFrame(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventExtendListen(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventBeaconUpdate(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventStopAP(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventChannelRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventChannelAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventDissolve(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventSwitchOPMode(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +WLAN_STATUS +p2pFsmRunEventMgmtFrameTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +VOID p2pFsmRunEventMgmtFrameRegister(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +#if CFG_SUPPORT_WFD +VOID p2pFsmRunEventWfdSettingUpdate(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); +#endif + +VOID p2pFsmRunEventSendCSA(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); +VOID p2pFsmRunEventSendECSA(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +#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 10 +#define P2P_MAXIMUM_NOA_COUNT 8 + +#define P2P_MAXIMUM_ATTRIBUTE_LEN 251 + +#define P2P_CTWINDOW_DEFAULT 25 /* in TU=(1024usec) */ + +#define P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE 768 + +/* P2P 3.1.2.1.3 - Find Phase */ +#define P2P_MAX_DISCOVERABLE_INTERVAL 8 /* 3 */ +#define P2P_MIN_DISCOVERABLE_INTERVAL 5 /* 1 */ + +#define P2P_LISTEN_SCAN_UNIT 100 /* MS */ + +/* FSM Time Related constrain. */ +#define P2P_SERACH_STATE_PERIOD_MS 1000 /* Deprecated. */ + +#define P2P_GO_CHANNEL_STAY_INTERVAL 1000 + +#define P2P_GO_NEGO_TIMEOUT_MS 500 +#define P2P_CONNECTION_TIMEOUT_SEC 120 + +#define P2P_INVITAION_TIMEOUT_MS 500 /* Timeout Wait Invitation Resonse. */ +#define P2P_PROVISION_DISCOVERY_TIMEOUT_MS 500 /* Timeout Wait Provision Discovery Resonse. */ + +/* 3 --------------- WFA P2P IE --------------- */ +/* P2P 4.1.1 - P2P IE format */ +#define P2P_OUI_TYPE_LEN 4 +#define P2P_IE_OUI_HDR (ELEM_HDR_LEN + P2P_OUI_TYPE_LEN) /* + * == OFFSET_OF(IE_P2P_T, + * aucP2PAttributes[0]) + */ + +/* P2P 4.1.1 - General P2P Attribute */ +#define P2P_ATTRI_HDR_LEN 3 /* ID(1 octet) + Length(2 octets) */ +#define P2P_ATTRI_LEN_NOTICE_OF_ABSENCE (P2P_ATTRI_HDR_LEN + 2) /* 5 */ + +/* P2P 4.1.1 - P2P Attribute ID definitions */ +#define P2P_ATTRI_ID_STATUS 0 +#define P2P_ATTRI_ID_REASON_CODE 1 +#define P2P_ATTRI_ID_P2P_CAPABILITY 2 +#define P2P_ATTRI_ID_P2P_DEV_ID 3 +#define P2P_ATTRI_ID_GO_INTENT 4 +#define P2P_ATTRI_ID_CFG_TIMEOUT 5 +#define P2P_ATTRI_ID_LISTEN_CHANNEL 6 +#define P2P_ATTRI_ID_P2P_GROUP_BSSID 7 +#define P2P_ATTRI_ID_EXT_LISTEN_TIMING 8 +#define P2P_ATTRI_ID_INTENDED_P2P_IF_ADDR 9 +#define P2P_ATTRI_ID_P2P_MANAGEABILITY 10 +#define P2P_ATTRI_ID_CHANNEL_LIST 11 +#define P2P_ATTRI_ID_NOTICE_OF_ABSENCE 12 +#define P2P_ATTRI_ID_P2P_DEV_INFO 13 +#define P2P_ATTRI_ID_P2P_GROUP_INFO 14 +#define P2P_ATTRI_ID_P2P_GROUP_ID 15 +#define P2P_ATTRI_ID_P2P_INTERFACE 16 +#define P2P_ATTRI_ID_OPERATING_CHANNEL 17 +#define P2P_ATTRI_ID_INVITATION_FLAG 18 +#define P2P_ATTRI_ID_VENDOR_SPECIFIC 221 + +/* Maximum Length of P2P Attributes */ +#define P2P_ATTRI_MAX_LEN_STATUS 1 /* 0 */ +#define P2P_ATTRI_MAX_LEN_REASON_CODE 1 /* 1 */ +#define P2P_ATTRI_MAX_LEN_P2P_CAPABILITY 2 /* 2 */ +#define P2P_ATTRI_MAX_LEN_P2P_DEV_ID 6 /* 3 */ +#define P2P_ATTRI_MAX_LEN_GO_INTENT 1 /* 4 */ +#define P2P_ATTRI_MAX_LEN_CFG_TIMEOUT 2 /* 5 */ +#if CID52_53_54 +#define P2P_ATTRI_MAX_LEN_LISTEN_CHANNEL 5 /* 6 */ +#else +#define P2P_ATTRI_MAX_LEN_LISTEN_CHANNEL 5 /* 6 */ +#endif +#define P2P_ATTRI_MAX_LEN_P2P_GROUP_BSSID 6 /* 7 */ +#define P2P_ATTRI_MAX_LEN_EXT_LISTEN_TIMING 4 /* 8 */ +#define P2P_ATTRI_MAX_LEN_INTENDED_P2P_IF_ADDR 6 /* 9 */ +#define P2P_ATTRI_MAX_LEN_P2P_MANAGEABILITY 1 /* 10 */ +/* #define P2P_ATTRI_MAX_LEN_CHANNEL_LIST 3 + (n* (2 + num_of_ch)) */ /* 11 */ +#define P2P_ATTRI_LEN_CHANNEL_LIST 3 /* 11 */ +#define P2P_ATTRI_LEN_CHANNEL_ENTRY 2 /* 11 */ + +/* #define P2P_ATTRI_MAX_LEN_NOTICE_OF_ABSENCE 2 + (n* (13)) */ /* 12 */ +#define P2P_ATTRI_MAX_LEN_NOTICE_OF_ABSENCE (2 + (P2P_MAXIMUM_NOA_COUNT*(13))) /* 12 */ + +#define P2P_ATTRI_MAX_LEN_P2P_DEV_INFO (17 + (8 * (8)) + 36) /* 13 */ +/* #define P2P_ATTRI_MAX_LEN_P2P_GROUP_INFO n* (25 + (m* (8)) + 32) */ /* 14 */ +#define P2P_ATTRI_MAX_LEN_P2P_GROUP_ID 38 /* 15 */ +#define P2P_ATTRI_MAX_LEN_P2P_INTERFACE 253 /* 7 + 6* [0~41] */ /* 16 */ +#if CID52_53_54 +#define P2P_ATTRI_MAX_LEN_OPERATING_CHANNEL 5 /* 17 */ +#else +#define P2P_ATTRI_MAX_LEN_OPERATING_CHANNEL 5 /* 17 */ +#endif +#define P2P_ATTRI_MAX_LEN_INVITATION_FLAGS 1 /* 18 */ + +/* P2P 4.1.2 - P2P Status definitions */ +#define P2P_STATUS_SUCCESS 0 +#define P2P_STATUS_FAIL_INFO_IS_CURRENTLY_UNAVAILABLE 1 +#define P2P_STATUS_FAIL_INCOMPATIBLE_PARAM 2 +#define P2P_STATUS_FAIL_LIMIT_REACHED 3 +#define P2P_STATUS_FAIL_INVALID_PARAM 4 +#define P2P_STATUS_FAIL_UNABLE_ACCOMMODATE_REQ 5 +#define P2P_STATUS_FAIL_PREVIOUS_PROTOCOL_ERR 6 +#define P2P_STATUS_FAIL_NO_COMMON_CHANNELS 7 +#define P2P_STATUS_FAIL_UNKNOWN_P2P_GROUP 8 +#define P2P_STATUS_FAIL_SAME_INTENT_VALUE_15 9 +#define P2P_STATUS_FAIL_INCOMPATIBLE_PROVISION_METHOD 10 +#define P2P_STATUS_FAIL_REJECTED_BY_USER 11 + +/* P2P 4.1.3 - P2P Minor Reason Code definitions */ +#define P2P_REASON_SUCCESS 0 +#define P2P_REASON_DISASSOCIATED_DUE_CROSS_CONNECTION 1 +#define P2P_REASON_DISASSOCIATED_DUE_UNMANAGEABLE 2 +#define P2P_REASON_DISASSOCIATED_DUE_NO_P2P_COEXIST_PARAM 3 +#define P2P_REASON_DISASSOCIATED_DUE_MANAGEABLE 4 + +/* P2P 4.1.4 - Device Capability Bitmap definitions */ +#define P2P_DEV_CAPABILITY_SERVICE_DISCOVERY BIT(0) +#define P2P_DEV_CAPABILITY_CLIENT_DISCOVERABILITY BIT(1) +#define P2P_DEV_CAPABILITY_CONCURRENT_OPERATION BIT(2) +#define P2P_DEV_CAPABILITY_P2P_INFRA_MANAGED BIT(3) +#define P2P_DEV_CAPABILITY_P2P_DEVICE_LIMIT BIT(4) +#define P2P_DEV_CAPABILITY_P2P_INVITATION_PROCEDURE BIT(5) + +/* P2P 4.1.4 - Group Capability Bitmap definitions */ +#define P2P_GROUP_CAPABILITY_P2P_GROUP_OWNER BIT(0) +#define P2P_GROUP_CAPABILITY_PERSISTENT_P2P_GROUP BIT(1) +#define P2P_GROUP_CAPABILITY_P2P_GROUP_LIMIT BIT(2) +#define P2P_GROUP_CAPABILITY_INTRA_BSS_DISTRIBUTION BIT(3) +#define P2P_GROUP_CAPABILITY_CROSS_CONNECTION BIT(4) +#define P2P_GROUP_CAPABILITY_PERSISTENT_RECONNECT BIT(5) +#define P2P_GROUP_CAPABILITY_GROUP_FORMATION BIT(6) + +/* P2P 4.1.6 - GO Intent field definitions */ +#define P2P_GO_INTENT_TIE_BREAKER_FIELD BIT(0) +#define P2P_GO_INTENT_VALUE_MASK BITS(1, 7) +#define P2P_GO_INTENT_VALUE_OFFSET 1 + +/* P2P 4.1.12 - Manageability Bitmap definitions */ +#define P2P_DEVICE_MANAGEMENT BIT(0) + +/* P2P 4.1.14 - CTWindow and OppPS Parameters definitions */ +#define P2P_CTW_OPPPS_PARAM_OPPPS_FIELD BIT(7) +#define P2P_CTW_OPPPS_PARAM_CTWINDOW_MASK BITS(0, 6) + +#define ELEM_MAX_LEN_P2P_FOR_PROBE_REQ \ + (P2P_OUI_TYPE_LEN + \ + (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_P2P_CAPABILITY) + \ + (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_P2P_DEV_ID) + \ + (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_LISTEN_CHANNEL) + \ + (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_OPERATING_CHANNEL)) + +#define ELEM_MAX_LEN_P2P_FOR_ASSOC_REQ \ + (P2P_OUI_TYPE_LEN + \ + (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_P2P_CAPABILITY) + \ + (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_EXT_LISTEN_TIMING) + \ + (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_P2P_DEV_INFO)) + +/* P2P 4.1.16 - P2P Client Infor Descriptor */ +#define P2P_CLIENT_INFO_DESC_HDR_LEN 1 /* Length(1 octets) */ + +/* P2P 4.1.20 - P2P Invitation Flags Attribute*/ +#define P2P_INVITATION_FLAGS_INVITATION_TYPE BIT(0) +#define P2P_INVITATION_TYPE_INVITATION 0 +#define P2P_INVITATION_TYPE_REINVOKE 1 +/* 3 --------------- WPS Data Element Definitions --------------- */ +/* P2P 4.2.2 - General WSC Attribute */ +#define WSC_ATTRI_HDR_LEN 4 /* ID(2 octet) + Length(2 octets) */ +#define WSC_ATTRI_MAX_LEN_VERSION 1 +#define WSC_ATTRI_MAX_LEN_DEVICE_PASSWORD_ID 2 +#define WSC_ATTRI_LEN_CONFIG_METHOD 2 + +/* WPS 11 - Data Element Definitions */ +#define WPS_ATTRI_ID_VERSION 0x104A +#define WPS_ATTRI_ID_CONFIGURATION_METHODS 0x1008 +#define WPS_ATTRI_ID_DEVICE_PASSWORD 0x1012 +#define WPS_ATTRI_ID_DEVICE_NAME 0x1011 +#define WPS_ATTRI_ID_PRI_DEVICE_TYPE 0x1054 +#define WPS_ATTRI_ID_SEC_DEVICE_TYPE 0x1055 + +#define WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE 300 + +#define WPS_ATTRI_MAX_LEN_DEVICE_NAME 32 /* 0x1011 */ + +#define WPS_ATTRI_CFG_METHOD_USBA BIT(0) +#define WPS_ATTRI_CFG_METHOD_ETHERNET BIT(1) +#define WPS_ATTRI_CFG_METHOD_LABEL BIT(2) +#define WPS_ATTRI_CFG_METHOD_DISPLAY BIT(3) +#define WPS_ATTRI_CFG_METHOD_EXT_NFC BIT(4) +#define WPS_ATTRI_CFG_METHOD_INT_NFC BIT(5) +#define WPS_ATTRI_CFG_METHOD_NFC_IF BIT(6) +#define WPS_ATTRI_CFG_METHOD_PUSH_BUTTON BIT(7) +#define WPS_ATTRI_CFG_METHOD_KEYPAD BIT(8) + +#define P2P_FLAGS_PROVISION_COMPLETE 0x00000001 +#define P2P_FLAGS_PROVISION_DISCOVERY_COMPLETE 0x00000002 +#define P2P_FLAGS_PROVISION_DISCOVERY_WAIT_RESPONSE 0x00000004 +#define P2P_FLAGS_PROVISION_DISCOVERY_RESPONSE_WAIT 0x00000008 +#define P2P_FLAGS_MASK_PROVISION 0x00000017 +#define P2P_FLAGS_MASK_PROVISION_COMPLETE 0x00000015 +#define P2P_FLAGS_PROVISION_DISCOVERY_INDICATED 0x00000010 +#define P2P_FLAGS_INVITATION_TOBE_GO 0x00000100 +#define P2P_FLAGS_INVITATION_TOBE_GC 0x00000200 +#define P2P_FLAGS_INVITATION_SUCCESS 0x00000400 +#define P2P_FLAGS_INVITATION_WAITING_TARGET 0x00000800 +#define P2P_FLAGS_MASK_INVITATION 0x00000F00 +#define P2P_FLAGS_FORMATION_ON_GOING 0x00010000 +#define P2P_FLAGS_FORMATION_LOCAL_PWID_RDY 0x00020000 +#define P2P_FLAGS_FORMATION_TARGET_PWID_RDY 0x00040000 +#define P2P_FLAGS_FORMATION_COMPLETE 0x00080000 +#define P2P_FLAGS_MASK_FORMATION 0x000F0000 +#define P2P_FLAGS_DEVICE_DISCOVER_REQ 0x00100000 +#define P2P_FLAGS_DEVICE_DISCOVER_DONE 0x00200000 +#define P2P_FLAGS_DEVICE_INVITATION_WAIT 0x00400000 +#define P2P_FLAGS_DEVICE_SERVICE_DISCOVER_WAIT 0x00800000 +#define P2P_FLAGS_MASK_DEVICE_DISCOVER 0x00F00000 + +#define P2P_FLAGS_DEVICE_FORMATION_REQUEST 0x01000000 + +/* MACRO for flag operation */ +#define SET_FLAGS(_FlagsVar, _BitsToSet) \ + {(_FlagsVar) = ((_FlagsVar) | (_BitsToSet))} + +#define TEST_FLAGS(_FlagsVar, _BitsToCheck) \ + (((_FlagsVar) & (_BitsToCheck)) == (_BitsToCheck)) + +#define CLEAR_FLAGS(_FlagsVar, _BitsToClear) \ + {(_FlagsVar) &= ~(_BitsToClear)} + +#define CFG_DISABLE_WIFI_DIRECT_ENHANCEMENT_I 0 + +#define CFG_DISABLE_WIFI_DIRECT_ENHANCEMENT_II 0 + +#define CFG_DISABLE_WIFI_DIRECT_ENHANCEMENT_III 0 + +#define CFG_DISABLE_WIFI_DIRECT_ENHANCEMENT_IV 0 + +#define CFG_DISABLE_DELAY_PROVISION_DISCOVERY 0 + +#define CFG_CONNECTION_POLICY_2_0 0 + +/* Device Password ID */ +enum wps_dev_password_id { + DEV_PW_DEFAULT = 0x0000, + DEV_PW_USER_SPECIFIED = 0x0001, + DEV_PW_MACHINE_SPECIFIED = 0x0002, + DEV_PW_REKEY = 0x0003, + DEV_PW_PUSHBUTTON = 0x0004, + DEV_PW_REGISTRAR_SPECIFIED = 0x0005 +}; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +#if defined(WINDOWS_DDK) || defined(WINDOWS_CE) +#pragma pack(1) +#endif + +/* 3 --------------- WFA P2P IE and Attributes --------------- */ + +/* P2P 4.1.1 - P2P Information Element */ +typedef struct _IE_P2P_T { + UINT_8 ucId; /* Element ID */ + UINT_8 ucLength; /* Length */ + UINT_8 aucOui[3]; /* OUI */ + UINT_8 ucOuiType; /* OUI Type */ + UINT_8 aucP2PAttributes[1]; /* P2P Attributes */ +} __KAL_ATTRIB_PACKED__ IE_P2P_T, *P_IE_P2P_T; + +/* P2P 4.1.1 - General P2P Attribute */ +typedef struct _P2P_ATTRIBUTE_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucBody[1]; /* Body field */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRIBUTE_T, ATTRIBUTE_HDR_T, *P_P2P_ATTRIBUTE_T, *P_ATTRIBUTE_HDR_T; + +/* P2P 4.1.2 - P2P Status Attribute */ +typedef struct _P2P_ATTRI_STATUS_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucStatusCode; /* Status Code */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_STATUS_T, *P_P2P_ATTRI_STATUS_T; + +/* P2P 4.1.3 - P2P Minor Reason Code Attribute */ +typedef struct _P2P_ATTRI_REASON_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucMinorReasonCode; /* Minor Reason Code */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_REASON_T, *P_P2P_ATTRI_REASON_T; + +/* P2P 4.1.4 - P2P Capability Attribute */ +typedef struct _P2P_ATTRI_CAPABILITY_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucDeviceCap; /* Device Capability Bitmap */ + UINT_8 ucGroupCap; /* Group Capability Bitmap */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_CAPABILITY_T, *P_P2P_ATTRI_CAPABILITY_T; + +/* P2P 4.1.5 - P2P Device ID Attribute */ +typedef struct _P2P_ATTRI_DEV_ID_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_DEV_ID_T, *P_P2P_ATTRI_DEV_ID_T; + +/* P2P 4.1.6 - Group Owner Intent Attribute */ +typedef struct _P2P_ATTRI_GO_INTENT_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucGOIntent; /* Group Owner Intent */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_GO_INTENT_T, *P_P2P_ATTRI_GO_INTENT_T; + +/* P2P 4.1.7 - Configuration Timeout Attribute */ +typedef struct _P2P_ATTRI_CFG_TIMEOUT_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucGOCfgTimeout; /* GO Configuration Timeout */ + UINT_8 ucClientCfgTimeout; /* Client Configuration Timeout */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_CFG_TIMEOUT_T, *P_P2P_ATTRI_CFG_TIMEOUT_T; + +/* P2P 4.1.8 - Listen Channel Attribute */ +typedef struct _P2P_ATTRI_LISTEN_CHANNEL_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucCountryString[3]; /* Country String */ + UINT_8 ucOperatingClass; /* Operating Class from 802.11 Annex J/P802.11 REVmb 3.0 */ + UINT_8 ucChannelNumber; /* Channel Number */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_LISTEN_CHANNEL_T, *P_P2P_ATTRI_LISTEN_CHANNEL_T; + +/* P2P 4.1.9 - P2P Group BSSID Attribute */ +typedef struct _P2P_ATTRI_GROUP_BSSID_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucBssid[MAC_ADDR_LEN]; /* P2P Group BSSID */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_GROUP_BSSID_T, *P_P2P_ATTRI_GROUP_BSSID_T; + +/* P2P 4.1.10 - Extended Listen Timing Attribute */ +typedef struct _P2P_ATTRI_EXT_LISTEN_TIMING_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_16 u2AvailPeriod; /* Availability Period */ + UINT_16 u2AvailInterval; /* Availability Interval */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_EXT_LISTEN_TIMING_T, *P_P2P_ATTRI_EXT_LISTEN_TIMING_T; + +/* P2P 4.1.11 - Intended P2P Interface Address Attribute */ +typedef struct _P2P_ATTRI_INTENDED_IF_ADDR_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucIfAddr[MAC_ADDR_LEN]; /* P2P Interface Address */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_INTENDED_IF_ADDR_T, *P_P2P_ATTRI_INTENDED_IF_ADDR_T; + +/* P2P 4.1.12 - P2P Manageability Attribute */ +typedef struct _P2P_ATTRI_MANAGEABILITY_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucManageability; /* P2P Manageability Bitmap */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_MANAGEABILITY_T, *P_P2P_ATTRI_MANAGEABILITY_T; + +/* P2P 4.1.13 - Channel List Attribute */ +typedef struct _P2P_ATTRI_CHANNEL_LIST_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucCountryString[3]; /* Country String */ + UINT_8 aucChannelEntry[1]; /* Channel Entry List */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_CHANNEL_T, *P_P2P_ATTRI_CHANNEL_T; + +typedef struct _CHANNEL_ENTRY_FIELD_T { + UINT_8 ucRegulatoryClass; /* Regulatory Class */ + UINT_8 ucNumberOfChannels; /* Number Of Channels */ + UINT_8 aucChannelList[1]; /* Channel List */ +} __KAL_ATTRIB_PACKED__ CHANNEL_ENTRY_FIELD_T, *P_CHANNEL_ENTRY_FIELD_T; + +/* P2P 4.1.14 - Notice of Absence Attribute */ +typedef struct _P2P_ATTRI_NOA_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucIndex; /* Index */ + UINT_8 ucCTWOppPSParam; /* CTWindow and OppPS Parameters */ + UINT_8 aucNoADesc[1]; /* NoA Descriptor */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_NOA_T, *P_P2P_ATTRI_NOA_T; + +typedef struct _NOA_DESCRIPTOR_T { + UINT_8 ucCountType; /* Count/Type */ + UINT_32 u4Duration; /* Duration */ + UINT_32 u4Interval; /* Interval */ + UINT_32 u4StartTime; /* Start Time */ +} __KAL_ATTRIB_PACKED__ NOA_DESCRIPTOR_T, *P_NOA_DESCRIPTOR_T; + +typedef struct _P2P_ATTRI_DEV_INFO_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ + UINT_16 u2ConfigMethodsBE; /* Config Method */ + DEVICE_TYPE_T rPrimaryDevTypeBE; /* Primary Device Type */ + UINT_8 ucNumOfSecondaryDevType; /* Number of Secondary Device Types */ + DEVICE_TYPE_T arSecondaryDevTypeListBE[1]; /* Secondary Device Type List */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_DEV_INFO_T, *P_P2P_ATTRI_DEV_INFO_T; + +/* WPS 7.1 & 11 WPS TLV Data Format - Device Name */ +typedef struct _DEVICE_NAME_TLV_T { + UINT_16 u2Id; /* WPS Attribute Type */ + UINT_16 u2Length; /* Data Length */ + UINT_8 aucName[32]; /* Device Name */ /* TODO: Fixme */ +} __KAL_ATTRIB_PACKED__ DEVICE_NAME_TLV_T, *P_DEVICE_NAME_TLV_T; + +/* P2P 4.1.16 - P2P Group Info Attribute */ +typedef struct _P2P_CLIENT_INFO_DESC_T { + UINT_8 ucLength; /* Length */ + UINT_8 aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ + UINT_8 aucIfAddr[MAC_ADDR_LEN]; /* P2P Interface Address */ + UINT_8 ucDeviceCap; /* Device Capability Bitmap */ + UINT_16 u2ConfigMethodsBE; /* Config Method */ + DEVICE_TYPE_T rPrimaryDevTypeBE; /* Primary Device Type */ + UINT_8 ucNumOfSecondaryDevType; /* Number of Secondary Device Types */ + DEVICE_TYPE_T arSecondaryDevTypeListBE[1]; /* Secondary Device Type List */ +} __KAL_ATTRIB_PACKED__ P2P_CLIENT_INFO_DESC_T, *P_P2P_CLIENT_INFO_DESC_T; + +typedef struct _P2P_ATTRI_GROUP_INFO_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + P2P_CLIENT_INFO_DESC_T arClientDesc[1]; /* P2P Client Info Descriptors */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_GROUP_INFO_T, *P_P2P_ATTRI_GROUP_INFO_T; + +/* P2P 4.1.17 - P2P Group ID Attribute */ +typedef struct _P2P_ATTRI_GROUP_ID_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ + UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; /* SSID */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_GROUP_ID_T, *P_P2P_ATTRI_GROUP_ID_T; + +/* P2P 4.1.18 - P2P Interface Attribute */ +typedef struct _P2P_ATTRI_INTERFACE_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ + UINT_8 ucIfAddrCount; /* P2P Interface Address Count */ + UINT_8 aucIfAddrList[MAC_ADDR_LEN]; /* P2P Interface Address List */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_INTERFACE_T, *P_P2P_ATTRI_INTERFACE_T; + +/* P2P 4.1.19 - Operating Channel Attribute */ +typedef struct _P2P_ATTRI_OPERATING_CHANNEL_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucCountryString[3]; /* Country String */ + UINT_8 ucOperatingClass; /* Operating Class from 802.11 Annex J/P802.11 REVmb 3.0 */ + UINT_8 ucChannelNumber; /* Channel Number */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_OPERATING_CHANNEL_T, *P_P2P_ATTRI_OPERATING_CHANNEL_T; + +/* P2P 4.1.20 - Invitation Flags Attribute */ +typedef struct _P2P_ATTRI_INVITATION_FLAG_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucInviteFlagsBitmap; /* Invitation Flags Bitmap */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_INVITATION_FLAG_T, *P_P2P_ATTRI_INVITATION_FLAG_T; + +/* P2P 4.1.1 - General WSC Attribute */ +typedef struct _WSC_ATTRIBUTE_T { + UINT_16 u2Id; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucBody[1]; /* Body field */ +} __KAL_ATTRIB_PACKED__ WSC_ATTRIBUTE_T, *P_WSC_ATTRIBUTE_T; + +/* WSC 1.0 Table 28 */ +typedef struct _WSC_ATTRI_VERSION_T { + UINT_16 u2Id; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucVersion; /* Version 1.0 or 1.1 */ +} __KAL_ATTRIB_PACKED__ WSC_ATTRI_VERSION_T, *P_WSC_ATTRI_VERSION_T; + +typedef struct _WSC_ATTRI_DEVICE_PASSWORD_ID_T { + UINT_16 u2Id; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_16 u2DevPasswordId; /* Device Password ID */ +} __KAL_ATTRIB_PACKED__ WSC_ATTRI_DEVICE_PASSWORD_ID_T, *P_WSC_ATTRI_DEVICE_PASSWORD_ID_T; + +typedef struct _WSC_ATTRI_CONFIGURATION_METHOD_T { + UINT_16 u2Id; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_16 u2ConfigMethods; /* Configure Methods */ +} __KAL_ATTRIB_PACKED__ WSC_ATTRI_CONFIGURATION_METHOD_T, *P_WSC_ATTRI_CONFIGURATION_METHOD_T; + +#if defined(WINDOWS_DDK) || defined(WINDOWS_CE) +#pragma pack() +#endif + +/* 3 --------------- WFA P2P Attributes Handler prototype --------------- */ +typedef UINT_32(*PFN_APPEND_ATTRI_FUNC) (P_ADAPTER_T, BOOLEAN, PUINT_16, PUINT_8, UINT_16); + +typedef VOID(*PFN_HANDLE_ATTRI_FUNC) (P_SW_RFB_T, P_P2P_ATTRIBUTE_T); + +typedef VOID(*PFN_VERIFY_ATTRI_FUNC) (P_SW_RFB_T, P_P2P_ATTRIBUTE_T, PUINT_16); + +typedef UINT_32(*PFN_CALCULATE_VAR_ATTRI_LEN_FUNC) (P_ADAPTER_T, P_STA_RECORD_T); + +typedef struct _APPEND_VAR_ATTRI_ENTRY_T { + UINT_16 u2EstimatedFixedAttriLen; /* For fixed length */ + PFN_CALCULATE_VAR_ATTRI_LEN_FUNC pfnCalculateVariableAttriLen; + PFN_APPEND_ATTRI_FUNC pfnAppendAttri; +} APPEND_VAR_ATTRI_ENTRY_T, *P_APPEND_VAR_ATTRI_ENTRY_T; + +typedef enum _ENUM_CONFIG_METHOD_SEL { + ENUM_CONFIG_METHOD_SEL_AUTO, + ENUM_CONFIG_METHOD_SEL_USER, + ENUM_CONFIG_METHOD_SEL_NUM +} ENUM_CONFIG_METHOD_SEL, *P_ENUM_CONFIG_METHOD_SEL; + +typedef enum _ENUM_P2P_FORMATION_POLICY { + ENUM_P2P_FORMATION_POLICY_AUTO = 0, + ENUM_P2P_FORMATION_POLICY_PASSIVE, /* Device would wait GO NEGO REQ instead of sending it actively. */ + ENUM_P2P_FORMATION_POLICY_NUM +} ENUM_P2P_FORMATION_POLICY, P_ENUM_P2P_FORMATION_POLICY; + +typedef enum _ENUM_P2P_INVITATION_POLICY { + ENUM_P2P_INVITATION_POLICY_USER = 0, + ENUM_P2P_INVITATION_POLICY_ACCEPT_FIRST, + ENUM_P2P_INVITATION_POLICY_DENY_ALL, + ENUM_P2P_INVITATION_POLICY_NUM +} ENUM_P2P_INVITATION_POLICY, P_ENUM_P2P_INVITATION_POLICY; + +/* 3 --------------- Data Structure for P2P Operation --------------- */ +/* 3 Session for CONNECTION SETTINGS of P2P */ +struct _P2P_CONNECTION_SETTINGS_T { + UINT_8 ucDevNameLen; + UINT_8 aucDevName[WPS_ATTRI_MAX_LEN_DEVICE_NAME]; + + DEVICE_TYPE_T rPrimaryDevTypeBE; + + ENUM_P2P_FORMATION_POLICY eFormationPolicy; /* Formation Policy. */ + + /*------------WSC Related Param---------------*/ + UINT_16 u2ConfigMethodsSupport; /* Preferred configure method. + * Some device may not have keypad. + */ + ENUM_CONFIG_METHOD_SEL eConfigMethodSelType; + UINT_16 u2TargetConfigMethod; /* Configure method selected by user or auto. */ + UINT_16 u2LocalConfigMethod; /* Configure method of target. */ + BOOLEAN fgIsPasswordIDRdy; + /*------------WSC Related Param---------------*/ + + UINT_8 ucClientConfigTimeout; + UINT_8 ucGoConfigTimeout; + + UINT_8 ucSecondaryDevTypeCount; +#if P2P_MAX_SUPPORTED_SEC_DEV_TYPE_COUNT + DEVICE_TYPE_T arSecondaryDevTypeBE[P2P_MAX_SUPPORTED_SEC_DEV_TYPE_COUNT]; +#endif + +#if 0 + UINT_8 ucRfChannelListCount; +#if P2P_MAX_SUPPORTED_CHANNEL_LIST_COUNT + UINT_8 aucChannelList[P2P_MAX_SUPPORTED_CHANNEL_LIST_COUNT]; /* + * Channel Numbering + * depends on 802.11mb Annex J. + */ + +#endif +#else + UINT_8 ucRfChannelListSize; +#if P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE + UINT_8 aucChannelEntriesField[P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE]; +#endif +#endif + + /* Go Intent */ + UINT_8 ucTieBreaker; + UINT_8 ucGoIntent; + + /* For Device Capability */ + BOOLEAN fgSupportServiceDiscovery; + BOOLEAN fgSupportClientDiscoverability; + BOOLEAN fgSupportConcurrentOperation; + BOOLEAN fgSupportInfraManaged; + BOOLEAN fgSupportInvitationProcedure; + + /* For Group Capability */ + BOOLEAN fgSupportPersistentP2PGroup; + BOOLEAN fgSupportIntraBSSDistribution; + BOOLEAN fgSupportCrossConnection; + BOOLEAN fgSupportPersistentReconnect; + + BOOLEAN fgP2pGroupLimit; + + BOOLEAN fgSupportOppPS; + UINT_16 u2CTWindow; + + BOOLEAN fgIsScanReqIssued; + BOOLEAN fgIsServiceDiscoverIssued; + + /*============ Target Device Connection Settings ============*/ + + /* Discover Target Device Info. */ + BOOLEAN fgIsDevId; + BOOLEAN fgIsDevType; + + /* Encryption mode of Target Device */ + ENUM_PARAM_AUTH_MODE_T eAuthMode; + + /* SSID + * 1. AP Mode, this is the desired SSID user specified. + * 2. Client Mode, this is the target SSID to be connected to. + */ + UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; + UINT_8 ucSSIDLen; + + /* Operating channel requested. */ + UINT_8 ucOperatingChnl; + ENUM_BAND_T eBand; + + /* Linten channel requested. */ + UINT_8 ucListenChnl; + + /* For device discover address/type. */ + UINT_8 aucTargetDevAddr[MAC_ADDR_LEN]; /* P2P Device Address, for P2P Device Discovery & P2P Connection. */ + +#if CFG_ENABLE_WIFI_DIRECT + P_P2P_DEVICE_DESC_T prTargetP2pDesc; +#endif + + UINT_8 ucLastStatus; /* P2P FSM would append status attribute according to this field. */ + +#if !CFG_DISABLE_DELAY_PROVISION_DISCOVERY + UINT_8 ucLastDialogToken; + UINT_8 aucIndicateDevAddr[MAC_ADDR_LEN]; +#endif + +#if 0 + UINT_8 ucTargetRfChannelListCount; +#if P2P_MAX_SUPPORTED_CHANNEL_LIST_COUNT + UINT_8 aucTargetChannelList[P2P_MAX_SUPPORTED_CHANNEL_LIST_COUNT]; /* + * Channel Numbering + * depends on 802.11mb Annex J. + */ +#endif +#endif + +}; + +typedef struct _NOA_TIMING_T { + BOOLEAN fgIsInUse; /* Indicate if this entry is in use or not */ + UINT_8 ucCount; /* Count */ + + UINT_8 aucReserved[2]; + + UINT_32 u4Duration; /* Duration */ + UINT_32 u4Interval; /* Interval */ + UINT_32 u4StartTime; /* Start Time */ +} NOA_TIMING_T, *P_NOA_TIMING_T; + +typedef enum _ENUM_P2P_IOCTL_T { + P2P_IOCTL_IDLE = 0, + P2P_IOCTL_DEV_DISCOVER, + P2P_IOCTL_INVITATION_REQ, + P2P_IOCTL_SERV_DISCOVER, + P2P_IOCTL_WAITING, + P2P_IOCTL_NUM +} ENUM_P2P_IOCTL_T; + +/*---------------- Service Discovery Related -------------------*/ +typedef enum _ENUM_SERVICE_TX_TYPE_T { + ENUM_SERVICE_TX_TYPE_BY_DA, + ENUM_SERVICE_TX_TYPE_BY_CHNL, + ENUM_SERVICE_TX_TYPE_NUM +} ENUM_SERVICE_TX_TYPE_T; + +typedef struct _SERVICE_DISCOVERY_FRAME_DATA_T { + QUE_ENTRY_T rQueueEntry; + P_MSDU_INFO_T prSDFrame; + ENUM_SERVICE_TX_TYPE_T eServiceType; + UINT_8 ucSeqNum; + union { + + UINT_8 ucChannelNum; + UINT_8 aucPeerAddr[MAC_ADDR_LEN]; + } uTypeData; + BOOLEAN fgIsTxDoneIndicate; +} SERVICE_DISCOVERY_FRAME_DATA_T, *P_SERVICE_DISCOVERY_FRAME_DATA_T; + +struct _P2P_FSM_INFO_T_DEPRECATED { + /* P2P FSM State */ + ENUM_P2P_STATE_T eCurrentState; + + /* Channel */ + BOOLEAN fgIsChannelRequested; + + ENUM_P2P_STATE_T ePreviousState; + + ENUM_P2P_STATE_T eReturnState; /* Return state after current activity finished or abort. */ + + UINT_8 aucTargetIfAddr[PARAM_MAC_ADDR_LEN]; + P_BSS_DESC_T prTargetBss; /* BSS of target P2P Device. For Connection/Service Discovery */ + + P_STA_RECORD_T prTargetStaRec; + + BOOLEAN fgIsRsponseProbe; /* Indicate if P2P FSM can response probe request frame. */ + + /* Sequence number of requested message. */ + UINT_8 ucSeqNumOfReqMsg; /* Used for SAA FSM request message. */ + + /* Channel Privilege */ + UINT_8 ucSeqNumOfChReq; /* Used for Channel Request message. */ + + UINT_8 ucSeqNumOfScnMsg; /* Used for SCAN FSM request message. */ + UINT_8 ucSeqNumOfCancelMsg; + + UINT_8 ucDialogToken; + UINT_8 ucRxDialogToken; + + /* Timer */ + TIMER_T rDeviceDiscoverTimer; /* For device discovery time of each discovery request from user. */ + TIMER_T rOperationListenTimer; /* For Find phase under operational state. */ + TIMER_T rFSMTimer; /* A timer used for Action frame timeout usage. */ + + TIMER_T rRejoinTimer; /* A timer used for Action frame timeout usage. */ + + /* Flag to indicate Provisioning */ + BOOLEAN fgIsConnectionRequested; + + /* Current IOCTL. */ + ENUM_P2P_IOCTL_T eP2pIOCTL; + + UINT_8 ucAvailableAuthTypes; /* Used for AUTH_MODE_AUTO_SWITCH */ + + /*--------SERVICE DISCOVERY--------*/ + QUE_T rQueueGASRx; /* Input Request/Response. */ + QUE_T rQueueGASTx; /* Output Response. */ + P_SERVICE_DISCOVERY_FRAME_DATA_T prSDRequest; + UINT_8 ucVersionNum; /* GAS packet sequence number for...Action Frame? */ + UINT_8 ucGlobalSeqNum; /* Sequence Number of RX SD packet. */ + /*--------Service DISCOVERY--------*/ + + /*--------DEVICE DISCOVERY---------*/ + UINT_8 aucTargetGroupID[PARAM_MAC_ADDR_LEN]; + UINT_16 u2TargetGroupSsidLen; + UINT_8 aucTargetSsid[32]; + UINT_8 aucSearchingP2pDevice[PARAM_MAC_ADDR_LEN]; + UINT_8 ucDLToken; + /*----------------------------------*/ + + /* Indicating Peer Status. */ + UINT_32 u4Flags; + + /*Indicating current running mode. */ + BOOLEAN fgIsApMode; + + /*------------INVITATION------------*/ + ENUM_P2P_INVITATION_POLICY eInvitationRspPolicy; + /*----------------------------------*/ + +}; + +struct _P2P_SPECIFIC_BSS_INFO_T { + /* For GO(AP) Mode - Compose TIM IE */ + UINT_16 u2SmallestAID; + UINT_16 u2LargestAID; + UINT_8 ucBitmapCtrl; + /* UINT_8 aucPartialVirtualBitmap[MAX_LEN_TIM_PARTIAL_BMP]; */ + + /* For GC/GO OppPS */ + BOOLEAN fgEnableOppPS; + UINT_16 u2CTWindow; + + /* For GC/GO NOA */ + UINT_8 ucNoAIndex; + UINT_8 ucNoATimingCount; /* Number of NoA Timing */ + NOA_TIMING_T arNoATiming[P2P_MAXIMUM_NOA_COUNT]; + + BOOLEAN fgIsNoaAttrExisted; + + /* For P2P Device */ + UINT_8 ucRegClass; /* Regulatory Class for channel. */ + UINT_8 ucListenChannel; /* Linten Channel only on channels 1, 6 and 11 in the 2.4 GHz. */ + + UINT_8 ucPreferredChannel; /* + * Operating Channel, should be one of channel list + * in p2p connection settings. + */ + ENUM_CHNL_EXT_T eRfSco; + ENUM_BAND_T eRfBand; + + /* Extended Listen Timing. */ + UINT_16 u2AvailabilityPeriod; + UINT_16 u2AvailabilityInterval; + +#if 0 /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */ + UINT_16 u2IELenForBCN; + UINT_8 aucBeaconIECache[P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE + WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; + + /* UINT_16 u2IELenForProbeRsp; */ + /* UINT_8 aucProbeRspIECache[P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE + WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; */ + + UINT_16 u2IELenForAssocRsp; + UINT_8 aucAssocRspIECache[P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE + WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; + +#else + UINT_16 u2AttributeLen; + UINT_8 aucAttributesCache[P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; + + UINT_16 u2WscAttributeLen; + UINT_8 aucWscAttributesCache[WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; +#endif + UINT_8 aucGroupID[MAC_ADDR_LEN]; + UINT_16 u2GroupSsidLen; + UINT_8 aucGroupSsid[ELEM_MAX_LEN_SSID]; + + PARAM_CUSTOM_NOA_PARAM_STRUCT_T rNoaParam; + PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T rOppPsParam; + + uint32_t u4KeyMgtSuiteCount; + uint32_t au4KeyMgtSuite[P2P_MAX_AKM_SUITES]; + + UINT_16 u2WpaIeLen; + UINT_8 aucWpaIeBuffer[ELEM_HDR_LEN + ELEM_MAX_LEN_WPA]; +}; + +typedef struct _MSG_P2P_DEVICE_DISCOVER_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_32 u4DevDiscoverTime; /* 0: Infinite, 1~X: in unit of MS. */ + BOOLEAN fgIsSpecificType; +#if CFG_ENABLE_WIFI_DIRECT + P2P_DEVICE_TYPE_T rTargetDeviceType; +#endif + UINT_8 aucTargetDeviceID[MAC_ADDR_LEN]; +} MSG_P2P_DEVICE_DISCOVER_T, *P_MSG_P2P_DEVICE_DISCOVER_T; + +typedef struct _MSG_P2P_INVITATION_REQUEST_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 aucDeviceID[MAC_ADDR_LEN]; /* Target Device ID to be invited. */ +} MSG_P2P_INVITATION_REQUEST_T, *P_MSG_P2P_INVITATION_REQUEST_T; + +typedef struct _MSG_P2P_FUNCTION_SWITCH_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + BOOLEAN fgIsFuncOn; +} MSG_P2P_FUNCTION_SWITCH_T, *P_MSG_P2P_FUNCTION_SWITCH_T; + +typedef struct _MSG_P2P_SERVICE_DISCOVERY_REQUEST_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 aucDeviceID[MAC_ADDR_LEN]; + BOOLEAN fgNeedTxDoneIndicate; + UINT_8 ucSeqNum; +} MSG_P2P_SERVICE_DISCOVERY_REQUEST_T, *P_MSG_P2P_SERVICE_DISCOVERY_REQUEST_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define p2pChangeMediaState(_prAdapter, _eNewMediaState) \ +do { \ + (_prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].eConnectionState = (_eNewMediaState));\ + wfdChangeMediaState((_prAdapter), NETWORK_TYPE_P2P_INDEX, (_eNewMediaState)); \ +} while (0) + +#define ATTRI_ID(_fp) (((P_P2P_ATTRIBUTE_T) _fp)->ucId) +#define ATTRI_LEN(_fp) \ + (((UINT_16) ((PUINT_8)&((P_P2P_ATTRIBUTE_T) _fp)->u2Length)[0]) | \ + ((UINT_16) ((PUINT_8)&((P_P2P_ATTRIBUTE_T) _fp)->u2Length)[1] << 8)) + +#define ATTRI_SIZE(_fp) (P2P_ATTRI_HDR_LEN + ATTRI_LEN(_fp)) + +#define P2P_ATTRI_FOR_EACH(_pucAttriBuf, _u2AttriBufLen, _u2Offset) \ + for ((_u2Offset) = 0; ((_u2Offset) < (_u2AttriBufLen)); \ + (_u2Offset) += ATTRI_SIZE(_pucAttriBuf), ((_pucAttriBuf) += ATTRI_SIZE(_pucAttriBuf))) + +#define P2P_IE(_fp) ((P_IE_P2P_T) _fp) + +#define WSC_ATTRI_ID(_fp) \ + (((UINT_16) ((PUINT_8)&((P_WSC_ATTRIBUTE_T) _fp)->u2Id)[0] << 8) | \ + ((UINT_16) ((PUINT_8)&((P_WSC_ATTRIBUTE_T) _fp)->u2Id)[1])) + +#define WSC_ATTRI_LEN(_fp) \ + (((UINT_16) ((PUINT_8)&((P_WSC_ATTRIBUTE_T) _fp)->u2Length)[0] << 8) | \ + ((UINT_16) ((PUINT_8)&((P_WSC_ATTRIBUTE_T) _fp)->u2Length)[1])) + +#define WSC_ATTRI_SIZE(_fp) (WSC_ATTRI_HDR_LEN + WSC_ATTRI_LEN(_fp)) + +#define WSC_ATTRI_FOR_EACH(_pucAttriBuf, _u2AttriBufLen, _u2Offset) \ + for ((_u2Offset) = 0; ((_u2Offset) < (_u2AttriBufLen)); \ + (_u2Offset) += WSC_ATTRI_SIZE(_pucAttriBuf), ((_pucAttriBuf) += WSC_ATTRI_SIZE(_pucAttriBuf))) + +#define WSC_IE(_fp) ((P_IE_P2P_T) _fp) + +#define WFD_ATTRI_ID(_fp) (((P_WFD_ATTRIBUTE_T) _fp)->ucElemID) + +#define WFD_ATTRI_LEN(_fp) \ + (((UINT_16) ((PUINT_8)&((P_WFD_ATTRIBUTE_T) _fp)->u2Length)[0] << 8) | \ + ((UINT_16) ((PUINT_8)&((P_WFD_ATTRIBUTE_T) _fp)->u2Length)[1])) + +#define WFD_ATTRI_SIZE(_fp) (WFD_ATTRI_HDR_LEN + WFD_ATTRI_LEN(_fp)) + +#define WFD_ATTRI_FOR_EACH(_pucAttriBuf, _u2AttriBufLen, _u2Offset) \ + for ((_u2Offset) = 0; ((_u2Offset) < (_u2AttriBufLen)); \ + (_u2Offset) += WFD_ATTRI_SIZE(_pucAttriBuf), ((_pucAttriBuf) += WFD_ATTRI_SIZE(_pucAttriBuf))) + +#if DBG +#define ASSERT_BREAK(_exp) \ + { \ + if (!(_exp)) { \ + ASSERT(FALSE); \ + break; \ + } \ + } + +#else +#define ASSERT_BREAK(_exp) +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/*======P2P State======*/ +VOID +p2pStateInit_LISTEN(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_P2P_SPECIFIC_BSS_INFO_T prSP2pBssInfo, IN UINT_8 ucListenChannel); + +VOID p2pStateAbort_LISTEN(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsChannelExtenstion); + +VOID p2pStateAbort_SEARCH_SCAN(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsChannelExtenstion); + +VOID p2pStateAbort_GO_OPERATION(IN P_ADAPTER_T prAdapter); + +VOID p2pStateAbort_GC_OPERATION(IN P_ADAPTER_T prAdapter); + +VOID +p2pStateInit_CONFIGURATION(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_BSS_INFO_T prP2pBssInfo, IN P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecBssInfo); + +VOID p2pStateAbort_CONFIGURATION(IN P_ADAPTER_T prAdapter); + +VOID p2pStateInit_JOIN(IN P_ADAPTER_T prAdapter); + +VOID p2pStateAbort_JOIN(IN P_ADAPTER_T prAdapter); + +/*====== P2P Functions ======*/ + +VOID p2pFuncInitGO(IN P_ADAPTER_T prAdapter); + +VOID +p2pFuncDisconnect(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, IN BOOLEAN fgSendDeauth, IN UINT_16 u2ReasonCode); + +VOID +p2pFuncSwitchOPMode(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, IN ENUM_OP_MODE_T eOpMode, IN BOOLEAN fgSyncToFW); + +VOID p2pFuncRunEventProvisioningComplete(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +WLAN_STATUS p2pFuncSetGroupID(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucGroupID, IN PUINT_8 pucSsid, IN UINT_8 ucSsidLen); + +WLAN_STATUS +p2pFuncSendDeviceDiscoverabilityReqFrame(IN P_ADAPTER_T prAdapter, IN UINT_8 aucDestAddr[], IN UINT_8 ucDialogToken); + +WLAN_STATUS +p2pFuncSendDeviceDiscoverabilityRspFrame(IN P_ADAPTER_T prAdapter, IN UINT_8 aucDestAddr[], IN UINT_8 ucDialogToken); + +UINT_8 p2pFuncGetVersionNumOfSD(IN P_ADAPTER_T prAdapter); + +/*====== P2P FSM ======*/ +VOID p2pFsmRunEventConnectionRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventDeviceDiscoveryRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventDeviceDiscoveryAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventRxGroupNegotiationReqFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +WLAN_STATUS +p2pFsmRunEventGroupNegotiationRequestTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +WLAN_STATUS +p2pFsmRunEventGroupNegotiationResponseTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +WLAN_STATUS +p2pFsmRunEventGroupNegotiationConfirmTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +WLAN_STATUS +p2pFsmRunEventProvisionDiscoveryRequestTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +WLAN_STATUS +p2pFsmRunEventProvisionDiscoveryResponseTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +WLAN_STATUS +p2pFsmRunEventInvitationRequestTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +VOID p2pFsmRunEventRxDeauthentication(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb); + +VOID p2pFsmRunEventRxDisassociation(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb); + +VOID p2pFsmRunEventBeaconTimeout(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS +p2pFsmRunEventDeauthTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + + +/*======Mail Box Event Message=====*/ + +VOID p2pFsmRunEventConnectionAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventConnectionTrigger(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventP2PFunctionSwitch(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventChGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventJoinComplete(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventConnectionPause(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID +p2pIndicationOfMediaStateToHost(IN P_ADAPTER_T prAdapter, + IN ENUM_PARAM_MEDIA_STATE_T eConnectionState, IN UINT_8 aucTargetAddr[]); + +VOID p2pUpdateBssInfoForJOIN(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prAssocRspSwRfb); + +/*======Mail Box Event Message=====*/ + +VOID p2pFsmInit(IN P_ADAPTER_T prAdapter); + +VOID p2pFsmUninit(IN P_ADAPTER_T prAdapter); + +VOID p2pFsmSteps(IN P_ADAPTER_T prAdapter, IN ENUM_P2P_STATE_T eNextState); + +VOID p2pStartGO(IN P_ADAPTER_T prAdapter); + +VOID p2pAssignSsid(IN PUINT_8 pucSsid, IN PUINT_8 pucSsidLen); + +VOID p2pFsmRunEventScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventIOReqTimeout(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Param); + +VOID p2pFsmRunEventSearchPeriodTimeout(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Param); + +VOID p2pFsmRunEventFsmTimeout(IN P_ADAPTER_T prAdapter, IN ULONG u4Param); + +VOID p2pFsmRunEventRejoinTimeout(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Parm); + +VOID p2pFsmRunEventDeauthTimeout(IN P_ADAPTER_T prAdapter, IN ULONG u4Param); + +/*=============== 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); + +WLAN_STATUS p2pUpdateBeaconEcsaIE(IN P_ADAPTER_T prAdapter, IN UINT_8 ucNetTypeIndex); + +VOID p2pFuncCompleteIOCTL(IN P_ADAPTER_T prAdapter, IN WLAN_STATUS rWlanStatus); +VOID p2pFsmRunEventTdlsTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParam); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#ifndef _lint +/* Kevin: we don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + * We'll need this for porting driver to different RTOS. + */ +static inline VOID p2pDataTypeCheck(VOID) +{ + DATA_STRUCT_INSPECTING_ASSERT(sizeof(IE_P2P_T) == (2 + 4 + 1)); /* all UINT_8 */ + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRIBUTE_T) == (3 + 1)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_STATUS_T) == (3 + 1)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_REASON_T) == (3 + 1)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_CAPABILITY_T) == (3 + 2)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_DEV_ID_T) == (3 + 6)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_GO_INTENT_T) == (3 + 1)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_CFG_TIMEOUT_T) == (3 + 2)); +#if CID52_53_54 + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_LISTEN_CHANNEL_T) == (3 + 5)); +#else + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_LISTEN_CHANNEL_T) == (3 + 5)); +#endif + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_GROUP_BSSID_T) == (3 + 6)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_EXT_LISTEN_TIMING_T) == (3 + 4)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_INTENDED_IF_ADDR_T) == (3 + 6)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_MANAGEABILITY_T) == (3 + 1)); + + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_CHANNEL_T) == (3 + 4)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(CHANNEL_ENTRY_FIELD_T) == 3); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_NOA_T) == (3 + 3)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(NOA_DESCRIPTOR_T) == 13); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(DEVICE_TYPE_T) == 8); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_DEV_INFO_T) == (3 + 6 + 2 + 8 + 1 + 8)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(DEVICE_NAME_TLV_T) == (4 + 32)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_CLIENT_INFO_DESC_T) == (1 + 6 + 6 + 1 + 2 + 8 + 1 + 8)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_GROUP_INFO_T) == (3 + (1 + 6 + 6 + 1 + 2 + 8 + 1 + 8))); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_GROUP_ID_T) == (3 + 38)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_INTERFACE_T) == (3 + 13)); +#if CID52_53_54 + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_OPERATING_CHANNEL_T) == (3 + 5)); +#else + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_OPERATING_CHANNEL_T) == (3 + 5)); +#endif + +} +#endif /* _lint */ + +VOID p2pFsmNotifyTxStatus(IN P_ADAPTER_T prAdapter, UINT_8 *pucEvtBuf); + +VOID p2pFsmNotifyRxP2pActionFrame(IN P_ADAPTER_T prAdapter, + IN enum P2P_ACTION_FRAME_TYPE eP2pFrameType, + OUT u_int8_t *prFgBufferFrame); + +void p2pFsmRunEventAcs(IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr); + +#endif /* _P2P_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_func.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_func.h new file mode 100644 index 0000000000000..633c73089955c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_func.h @@ -0,0 +1,194 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _P2P_FUNC_H +#define _P2P_FUNC_H + +#define P2P_EXT_LISTEN_TIME_MS 600 +#define P2P_OFF_CHNL_TX_DEFAULT_TIME_MS 1000 + +VOID p2pFuncRequestScan(IN P_ADAPTER_T prAdapter, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo); + +VOID p2pFuncCancelScan(IN P_ADAPTER_T prAdapter, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo); + +VOID p2pFuncStartGO(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, + IN 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); + +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 p2pFuncProcessBeacon(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); + +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP +WLAN_STATUS p2pFuncUpdateProbeRspIEs(IN P_ADAPTER_T prAdapter, IN P_MSG_P2P_BEACON_UPDATE_T prIETemp, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); +#endif + +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 p2pFuncParseBeaconIEs(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, IN PUINT_8 pucIEInfo, IN UINT_32 u4IELen); + +P_BSS_DESC_T +p2pFuncKeepOnConnection(IN P_ADAPTER_T prAdapter, + IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo); + +VOID p2pFuncStoreAssocRspIEBuffer(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID +p2pFuncMgmtFrameRegister(IN P_ADAPTER_T prAdapter, + IN UINT_16 u2FrameType, IN BOOLEAN fgIsRegistered, OUT PUINT_32 pu4P2pPacketFilter); + +VOID p2pFuncUpdateMgmtFrameRegister(IN P_ADAPTER_T prAdapter, IN UINT_32 u4OsFilter); + +VOID p2pFuncGetStationInfo(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucMacAddr, OUT P_P2P_STATION_INFO_T prStaInfo); + +BOOLEAN +p2pFuncGetAttriList(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucOuiType, + IN PUINT_8 pucIE, IN UINT_16 u2IELength, OUT PPUINT_8 ppucAttriList, OUT PUINT_16 pu2AttriListLen); + +P_MSDU_INFO_T p2pFuncProcessP2pProbeRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMgmtTxMsdu); + +#if 0 /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */ +UINT_32 +p2pFuncCalculateExtra_IELenForBeacon(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); + +VOID p2pFuncGenerateExtra_IEForBeacon(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +#else +UINT_32 +p2pFuncCalculateP2p_IELenForBeacon(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); + +VOID p2pFuncGenerateP2p_IEForBeacon(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +UINT_32 +p2pFuncCalculateWSC_IELenForBeacon(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); + +VOID p2pFuncGenerateWSC_IEForBeacon(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); +#endif +UINT_32 +p2pFuncCalculateP2p_IELenForAssocRsp(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); + +VOID p2pFuncGenerateP2p_IEForAssocRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +UINT_32 +p2pFuncCalculateWSC_IELenForAssocRsp(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); + +VOID p2pFuncGenerateWSC_IEForAssocRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +UINT_32 +p2pFuncCalculateP2P_IELen(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec, + IN APPEND_VAR_ATTRI_ENTRY_T arAppendAttriTable[], IN UINT_32 u4AttriTableSize); + +VOID +p2pFuncGenerateP2P_IE(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize, + IN APPEND_VAR_ATTRI_ENTRY_T arAppendAttriTable[], IN UINT_32 u4AttriTableSize); + +UINT_32 +p2pFuncAppendAttriStatusForAssocRsp(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pFuncAppendAttriExtListenTiming(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +VOID +p2pFuncDissolve(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, IN BOOLEAN fgSendDeauth, IN UINT_16 u2ReasonCode); + +P_IE_HDR_T +p2pFuncGetSpecIE(IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucIEBuf, IN UINT_16 u2BufferLen, IN UINT_8 ucElemID, IN PBOOLEAN pfgIsMore); + +P_ATTRIBUTE_HDR_T +p2pFuncGetSpecAttri(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucOuiType, IN PUINT_8 pucIEBuf, IN UINT_16 u2BufferLen, IN UINT_16 u2AttriID); + +WLAN_STATUS wfdChangeMediaState(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx, + IN ENUM_PARAM_MEDIA_STATE_T eConnectionState); +#if CFG_SUPPORT_P2P_EAP_FAIL_WORKAROUND +VOID p2pFuncEAPfailureWorkaround(IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucEvtBuf); +#endif +#endif + +BOOLEAN p2pFuncValidateProbeResp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMgmtTxMsdu); + +BOOLEAN p2pFuncRetryGcDeauth(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_STA_RECORD_T prStaRec, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +VOID p2pFuncClearGcDeauthRetry(IN P_ADAPTER_T prAdapter); + +VOID p2pFuncDeauthComplete(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo); + +void p2pFunCleanQueuedMgmtFrame(IN P_ADAPTER_T prAdapter, + IN struct P2P_QUEUED_ACTION_FRAME *prFrame); + +void p2pFunProcessAcsReport(IN P_ADAPTER_T prAdapter, + IN P_PARAM_GET_CHN_INFO prLteSafeChnInfo, + IN struct P2P_ACS_REQ_INFO *prAcsReqInfo); + +void p2pFunIndicateAcsResult(IN P_GLUE_INFO_T prGlueInfo, + IN struct P2P_ACS_REQ_INFO *prAcsReqInfo); + +void p2pFunCalAcsChnScores(IN P_ADAPTER_T prAdapter, + IN ENUM_BAND_T eBand); + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_ie.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_ie.h new file mode 100644 index 0000000000000..9f53894737c46 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_ie.h @@ -0,0 +1,171 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _P2P_IE_H +#define _P2P_IE_H + +#if CFG_SUPPORT_WFD + +#define ELEM_MAX_LEN_WFD 62 /* TODO: Move to appropriate place */ + +/*---------------- WFD Data Element Definitions ----------------*/ +/* WFD 4.1.1 - WFD IE format */ +#define WFD_OUI_TYPE_LEN 4 +#define WFD_IE_OUI_HDR (ELEM_HDR_LEN + WFD_OUI_TYPE_LEN) /* + * == OFFSET_OF(IE_P2P_T, + * aucP2PAttributes[0]) + */ + +/* WFD 4.1.1 - General WFD Attribute */ +#define WFD_ATTRI_HDR_LEN 3 /* ID(1 octet) + Length(2 octets) */ + +/* WFD Attribute Code */ +#define WFD_ATTRI_ID_DEV_INFO 0 +#define WFD_ATTRI_ID_ASSOC_BSSID 1 +#define WFD_ATTRI_ID_COUPLED_SINK_INFO 6 +#define WFD_ATTRI_ID_EXT_CAPABILITY 7 +#define WFD_ATTRI_ID_SESSION_INFO 9 +#define WFD_ATTRI_ID_ALTER_MAC_ADDRESS 10 + +/* Maximum Length of WFD Attributes */ +#define WFD_ATTRI_MAX_LEN_DEV_INFO 6 /* 0 */ +#define WFD_ATTRI_MAX_LEN_ASSOC_BSSID 6 /* 1 */ +#define WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO 7 /* 6 */ +#define WFD_ATTRI_MAX_LEN_EXT_CAPABILITY 2 /* 7 */ +#define WFD_ATTRI_MAX_LEN_SESSION_INFO 0 /* 9 */ /* 24 * #Clients */ +#define WFD_ATTRI_MAX_LEN_ALTER_MAC_ADDRESS 6 /* 10 */ + +/* WFD 1.10 5.1.1 */ +typedef struct _IE_WFD_T { + UINT_8 ucId; /* Element ID */ + UINT_8 ucLength; /* Length */ + UINT_8 aucOui[3]; /* OUI */ + UINT_8 ucOuiType; /* OUI Type */ + UINT_8 aucWFDAttributes[1]; /* WFD Subelement */ +} __KAL_ATTRIB_PACKED__ IE_WFD_T, *P_IE_WFD_T; + +typedef struct _WFD_ATTRIBUTE_T { + UINT_8 ucElemID; /* Subelement ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucBody[1]; /* Body field */ +} __KAL_ATTRIB_PACKED__ WFD_ATTRIBUTE_T, *P_WFD_ATTRIBUTE_T; + +typedef struct _WFD_DEVICE_INFORMATION_IE_T { + UINT_8 ucElemID; + UINT_16 u2Length; + UINT_16 u2WfdDevInfo; + UINT_16 u2SessionMgmtCtrlPort; + UINT_16 u2WfdDevMaxSpeed; +} __KAL_ATTRIB_PACKED__ WFD_DEVICE_INFORMATION_IE_T, *P_WFD_DEVICE_INFORMATION_IE_T; + +typedef struct _WFD_ASSOCIATED_BSSID_IE_T { + UINT_8 ucElemID; + UINT_16 u2Length; + UINT_8 aucAssocBssid[MAC_ADDR_LEN]; +} __KAL_ATTRIB_PACKED__ WFD_ASSOCIATED_BSSID_IE_T, *P_WFD_ASSOCIATED_BSSID_IE_T; + +typedef struct _WFD_COUPLE_SINK_INFORMATION_IE_T { + UINT_8 ucElemID; + UINT_16 u2Length; + UINT_8 ucCoupleSinkStatusBp; + UINT_8 aucCoupleSinkMac[MAC_ADDR_LEN]; +} __KAL_ATTRIB_PACKED__ WFD_COUPLE_SINK_INFORMATION_IE_T, *P_WFD_COUPLE_SINK_INFORMATION_IE_T; + +typedef struct _WFD_EXTENDED_CAPABILITY_IE_T { + UINT_8 ucElemID; + UINT_16 u2Length; + UINT_16 u2WfdExtCapabilityBp; +} __KAL_ATTRIB_PACKED__ WFD_EXTENDED_CAPABILITY_IE_T, *P_WFD_EXTENDED_CAPABILITY_IE_T; + +typedef struct _WFD_SESSION_INFORMATION_IE_T { + UINT_8 ucElemID; + UINT_16 u2Length; + PUINT_8 pucWfdDevInfoDesc[1]; +} __KAL_ATTRIB_PACKED__ WFD_SESSION_INFORMATION_IE_T, *P_WFD_SESSION_INFORMATION_IE_T; + +typedef struct _WFD_DEVICE_INFORMATION_DESCRIPTOR_T { + UINT_8 ucLength; + UINT_8 aucDevAddr[MAC_ADDR_LEN]; + UINT_8 aucAssocBssid[MAC_ADDR_LEN]; + UINT_16 u2WfdDevInfo; + UINT_16 u2WfdDevMaxSpeed; + UINT_8 ucCoupleSinkStatusBp; + UINT_8 aucCoupleSinkMac[MAC_ADDR_LEN]; +} __KAL_ATTRIB_PACKED__ WFD_DEVICE_INFORMATION_DESCRIPTOR_T, *P_WFD_DEVICE_INFORMATION_DESCRIPTOR_T; + +#endif + +UINT_32 +p2pCalculate_IEForAssocReq(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); + +VOID p2pGenerate_IEForAssocReq(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +#if CFG_SUPPORT_WFD + +UINT_32 +wfdFuncAppendAttriDevInfo(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +wfdFuncAppendAttriAssocBssid(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +wfdFuncAppendAttriCoupledSinkInfo(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +wfdFuncAppendAttriExtCapability(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 wfdFuncCalculateAttriLenSessionInfo(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +UINT_32 +wfdFuncAppendAttriSessionInfo(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +wfdFuncCalculateWfdIELenForProbeResp(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); + +VOID wfdFuncGenerateWfdIEForProbeResp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +UINT_32 +wfdFuncCalculateWfdIELenForAssocReq(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); + +VOID wfdFuncGenerateWfdIEForAssocReq(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +UINT_32 +wfdFuncCalculateWfdIELenForAssocRsp(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); + +VOID wfdFuncGenerateWfdIEForAssocRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +UINT_32 +wfdFuncCalculateWfdIELenForBeacon(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); + +VOID wfdFuncGenerateWfdIEForBeacon(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +#endif + +UINT_32 p2pFuncCalculateP2P_IE_NoA(IN P_ADAPTER_T prAdapter, IN UINT_32 ucBssIdx, IN P_STA_RECORD_T prStaRec); + +VOID p2pFuncGenerateP2P_IE_NoA(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_rlm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_rlm.h new file mode 100644 index 0000000000000..1a4a4bd74b080 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_rlm.h @@ -0,0 +1,79 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _P2P_RLM_H +#define _P2P_RLM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +extern VOID rlmSyncOperationParams(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +VOID rlmBssInitForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); + +BOOLEAN rlmUpdateBwByChListForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); + +VOID rlmUpdateParamsForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, BOOLEAN fgUpdateBeacon); + +VOID rlmFuncInitialChannelList(IN P_ADAPTER_T prAdapter); + +VOID +rlmFuncCommonChannelList(IN P_ADAPTER_T prAdapter, + IN P_CHANNEL_ENTRY_FIELD_T prChannelEntryII, IN UINT_8 ucChannelListSize); + +UINT_8 rlmFuncFindOperatingClass(IN P_ADAPTER_T prAdapter, IN UINT_8 ucChannelNum); + +BOOLEAN +rlmFuncFindAvailableChannel(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucCheckChnl, + IN PUINT_8 pucSuggestChannel, IN BOOLEAN fgIsSocialChannel, IN BOOLEAN fgIsDefaultChannel); + +ENUM_CHNL_EXT_T rlmDecideScoForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); +ENUM_CHNL_EXT_T rlmDecideSco(P_ADAPTER_T prAdapter, UINT_8 ucPrimaryChannel, ENUM_BAND_T eBand); +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_rlm_obss.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_rlm_obss.h new file mode 100644 index 0000000000000..699251a230e13 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_rlm_obss.h @@ -0,0 +1,69 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _P2P_RLM_OBSS_H +#define _P2P_RLM_OBSS_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +VOID rlmRspGenerateObssScanIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + +VOID rlmProcessPublicAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); + +VOID rlmProcessHtAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); + +VOID rlmHandleObssStatusEventPkt(P_ADAPTER_T prAdapter, P_EVENT_AP_OBSS_STATUS_T prObssStatus); + +UINT_8 rlmObssChnlLevel(P_BSS_INFO_T prBssInfo, ENUM_BAND_T eBand, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend); + +VOID rlmObssScanExemptionRsp(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_SW_RFB_T prSwRfb); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_scan.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_scan.h new file mode 100644 index 0000000000000..1e7e8e7316064 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_scan.h @@ -0,0 +1,85 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _P2P_SCAN_H +#define _P2P_SCAN_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +WLAN_STATUS scanSendDeviceDiscoverEvent(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc, IN P_SW_RFB_T prSwRfb); + +P_P2P_DEVICE_DESC_T +scanSearchTargetP2pDesc(IN P_ADAPTER_T prAdapter, IN UINT_8 aucDeviceID[], IN PP_BSS_DESC_T pprBssDesc); + +P_P2P_DEVICE_DESC_T +scanFindP2pDeviceDesc(IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc, + IN UINT_8 aucMacAddr[], IN BOOLEAN fgIsDeviceAddr, IN BOOLEAN fgAddIfNoFound); + +P_P2P_DEVICE_DESC_T scanGetP2pDeviceDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); + +VOID scnEventReturnChannel(IN P_ADAPTER_T prAdapter, IN UINT_8 ucScnSeqNum); + +BOOLEAN scanUpdateP2pDeviceDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); + +VOID +scanP2pProcessBeaconAndProbeResp(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN P_WLAN_STATUS prStatus, + IN P_BSS_DESC_T prBssDesc, IN P_WLAN_BEACON_FRAME_T prWlanBeaconFrame); + +VOID scanRemoveAllP2pBssDesc(P_ADAPTER_T prAdapter); + +VOID scanRemoveP2pBssDesc(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc); + +P_BSS_DESC_T +scanP2pSearchDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo, IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_state.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_state.h new file mode 100644 index 0000000000000..43173e7aa971a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/p2p_state.h @@ -0,0 +1,56 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _P2P_STATE_H +#define _P2P_STATE_H + +BOOLEAN +p2pStateInit_IDLE(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN P_BSS_INFO_T prP2pBssInfo, OUT P_ENUM_P2P_STATE_T peNextState); + +VOID p2pStateAbort_IDLE(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN ENUM_P2P_STATE_T eNextState); + +VOID p2pStateInit_SCAN(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo); + +VOID p2pStateAbort_SCAN(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN ENUM_P2P_STATE_T eNextState); + +VOID p2pStateInit_AP_CHANNEL_DETECT(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo); + +VOID +p2pStateAbort_AP_CHANNEL_DETECT(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo, IN ENUM_P2P_STATE_T eNextState); + +VOID +p2pStateInit_CHNL_ON_HAND(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo, IN P_P2P_FSM_INFO_T prP2pFsmInfo); + +VOID +p2pStateAbort_CHNL_ON_HAND(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_BSS_INFO_T prP2pBssInfo, IN ENUM_P2P_STATE_T eNextState); + +VOID +p2pStateAbort_REQING_CHANNEL(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN ENUM_P2P_STATE_T eNextState); + +VOID +p2pStateInit_GC_JOIN(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_BSS_INFO_T prP2pBssInfo, IN P_P2P_JOIN_INFO_T prJoinInfo, IN P_BSS_DESC_T prBssDesc); + +VOID +p2pStateAbort_GC_JOIN(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_P2P_JOIN_INFO_T prJoinInfo, IN ENUM_P2P_STATE_T eNextState); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/privacy.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/privacy.h new file mode 100644 index 0000000000000..d0d0240ece219 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/privacy.h @@ -0,0 +1,190 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _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 + +enum ENUM_EAPOL_KEY_TYPE_T { + EAPOL_KEY_NOT_KEY = 0, + EAPOL_KEY_1_OF_4 = 1, + EAPOL_KEY_2_OF_4 = 2, + EAPOL_KEY_3_OF_4 = 3, + EAPOL_KEY_4_OF_4 = 4, + EAPOL_KEY_1_OF_2 = 5, + EAPOL_KEY_2_OF_2 = 6, +}; + +enum ENUM_KEY_ACTION_TYPE_T { + SEC_DROP_KEY_COMMAND = 0, + SEC_QUEUE_KEY_COMMAND = 1, + SEC_TX_KEY_COMMAND = 2, + SEC_ACTION_KEY_NUM +}; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +VOID secInit(IN P_ADAPTER_T prAdapter, IN UINT_8 ucNetTypeIdx); + +VOID secSetPortBlocked(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta, IN BOOLEAN fgPort); + +BOOLEAN secCheckClassError(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN P_STA_RECORD_T prStaRec); + +BOOLEAN secTxPortControlCheck(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN P_STA_RECORD_T prStaRec); + +BOOLEAN secRxPortControlCheck(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSWRfb); + +VOID secSetCipherSuite(IN P_ADAPTER_T prAdapter, IN UINT_32 u4CipherSuitesFlags); + +BOOLEAN +secProcessEAPOL(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN P_STA_RECORD_T prStaRec, IN PUINT_8 pucPayload, IN UINT_16 u2PayloadLen); + +VOID +secHandleTxDoneCallback(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T pMsduInfo, IN P_STA_RECORD_T prStaRec, IN WLAN_STATUS rStatus); + +BOOLEAN secIsProtectedFrame(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsdu, IN P_STA_RECORD_T prStaRec); + +#if (CFG_REFACTORY_PMKSA == 0) +VOID secClearPmkid(IN P_ADAPTER_T prAdapter); +#endif + +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); + +BOOLEAN secWpaEnabledInAis(IN P_ADAPTER_T prAdapter); + +enum ENUM_EAPOL_KEY_TYPE_T secGetEapolKeyType(PUINT_8 pucPacket); + +VOID secHandleTxStatus(ADAPTER_T *prAdapter, UINT_8 *pucEvtBuf); + +VOID secHandleRxEapolPacket(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prRetSwRfb, + IN P_STA_RECORD_T prStaRec); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _PRIVACY_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/qosmap.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/qosmap.h new file mode 100644 index 0000000000000..6a2794c5ea37e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/qosmap.h @@ -0,0 +1,72 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _QOSMAP_H +#define _QOSMAP_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 +******************************************************************************** +*/ +#define DSCP_SUPPORT 1 +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID handleQosMapConf(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +int qosHandleQosMapConfigure(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID qosMapSetInit(IN P_STA_RECORD_T prStaRec); + +VOID qosParseQosMapSet(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN PUINT_8 qosMapSet); + +UINT_8 getUpFromDscp(IN P_GLUE_INFO_T prGlueInfo, IN int type, IN int dscp); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _QOSMAP_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rate.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rate.h new file mode 100644 index 0000000000000..d9a080ff0a046 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rate.h @@ -0,0 +1,78 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _RATE_H +#define _RATE_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Routines in rate.c */ +/*----------------------------------------------------------------------------*/ +VOID +rateGetRateSetFromIEs(IN P_IE_SUPPORTED_RATE_T prIeSupportedRate, + IN P_IE_EXT_SUPPORTED_RATE_T prIeExtSupportedRate, + OUT PUINT_16 pu2OperationalRateSet, + OUT PUINT_16 pu2BSSBasicRateSet, OUT PBOOLEAN pfgIsUnknownBSSBasicRate); + +VOID +rateGetDataRatesFromRateSet(IN UINT_16 u2OperationalRateSet, + IN UINT_16 u2BSSBasicRateSet, OUT PUINT_8 pucDataRates, OUT PUINT_8 pucDataRatesLen); + +BOOLEAN rateGetHighestRateIndexFromRateSet(IN UINT_16 u2RateSet, OUT PUINT_8 pucHighestRateIndex); + +BOOLEAN rateGetLowestRateIndexFromRateSet(IN UINT_16 u2RateSet, OUT PUINT_8 pucLowestRateIndex); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _RATE_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rlm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rlm.h new file mode 100644 index 0000000000000..fcf4ef440cda8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rlm.h @@ -0,0 +1,404 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _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 */ + +/* Radio Measurement Request Mode definition */ +#define RM_REQ_MODE_PARALLEL_BIT BIT(0) +#define RM_REQ_MODE_ENABLE_BIT BIT(1) +#define RM_REQ_MODE_REQUEST_BIT BIT(2) +#define RM_REQ_MODE_REPORT_BIT BIT(3) +#define RM_REQ_MODE_DURATION_MANDATORY_BIT BIT(4) +#define RM_REP_MODE_LATE BIT(0) +#define RM_REP_MODE_INCAPABLE BIT(1) +#define RM_REP_MODE_REFUSED BIT(2) + +/* Radio Measurement Report Frame Max Length */ +#define RM_REPORT_FRAME_MAX_LENGTH 1600 +#define RM_BCN_REPORT_SUB_ELEM_MAX_LENGTH 224 + +/* beacon request mode definition */ +#define RM_BCN_REQ_PASSIVE_MODE 0 +#define RM_BCN_REQ_ACTIVE_MODE 1 +#define RM_BCN_REQ_TABLE_MODE 2 + +#define RLM_INVALID_POWER_LIMIT -127 /* dbm */ +#define RLM_MAX_TX_PWR 20 /* dbm */ +#define RLM_MIN_TX_PWR 8 /* dbm */ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +struct SUB_ELEMENT_LIST { + struct SUB_ELEMENT_LIST *prNext; + struct SUB_ELEMENT_T rSubIE; +}; + +enum BCN_RM_STATE { + RM_NO_REQUEST, + RM_ON_GOING, + RM_WAITING, /*waiting normal scan done */ +}; + +enum RM_REQ_PRIORITY { + RM_PRI_BROADCAST, + RM_PRI_MULTICAST, + RM_PRI_UNICAST +}; + +struct NORMAL_SCAN_PARAMS { + PARAM_SSID_T arSSID[SCN_SSID_MAX_NUM]; + UINT_8 aucScanIEBuf[MAX_IE_LENGTH]; + UINT_32 u4IELen; + UINT_8 ucSsidNum; + BOOLEAN fgExist; + BOOLEAN fgFull2Partial; + UINT_8 aucRandomMac[MAC_ADDR_LEN]; +}; + +/* Beacon RM related parameters */ +struct BCN_RM_PARAMS { + BOOLEAN fgExistBcnReq; + enum BCN_RM_STATE eState; + struct NORMAL_SCAN_PARAMS rNormalScan; +}; + +struct RADIO_MEASUREMENT_REQ_PARAMS { + /* Remain Request Elements Length, started at prMeasElem. if it is 0, means RM is done */ + UINT_16 u2RemainReqLen; + UINT_16 u2ReqIeBufLen; + P_IE_MEASUREMENT_REQ_T prCurrMeasElem; + OS_SYSTIME rStartTime; + UINT_16 u2Repetitions; + PUINT_8 pucReqIeBuf; + enum RM_REQ_PRIORITY ePriority; + BOOLEAN fgRmIsOngoing; + BOOLEAN fgInitialLoop; + + struct BCN_RM_PARAMS rBcnRmParam; +}; + +struct RADIO_MEASUREMENT_REPORT_PARAMS { + UINT_16 u2ReportFrameLen; /* the total length of Measurement Report elements */ + PUINT_8 pucReportFrameBuff; + /* Variables to collect report */ + LINK_T rReportLink; /* a link to save received report entry */ + LINK_T rFreeReportLink; +}; + +typedef enum _ENUM_NET_ACTIVE_SRC_T { + NET_ACTIVE_SRC_NONE = 0, + NET_ACTIVE_SRC_CONNECT = 1, + NET_ACTIVE_SRC_SCAN = 2, + NET_ACTIVE_SRC_SCHED_SCAN = 4, + NET_ACTIVE_SRC_NUM +} ENUM_NET_ACTIVE_SRC_T, *P_ENUM_NET_ACTIVE_SRC_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 RM_EXIST_REPORT(_prRmReportParam) \ + (((struct RADIO_MEASUREMENT_REPORT_PARAMS *)_prRmReportParam)->u2ReportFrameLen == \ + OFFSET_OF(ACTION_RM_REPORT_FRAME, aucInfoElem)) + +/* 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 rlmGenerateMTKOuiIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + +VOID rlmProcessBcn(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength); + +VOID rlmProcessAssocRsp(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength); + +VOID rlmFillSyncCmdParam(P_CMD_SET_BSS_RLM_PARAM_T prCmdBody, P_BSS_INFO_T prBssInfo); + +VOID rlmSyncOperationParams(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); + +VOID rlmBssInitForAPandIbss(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); + +VOID rlmProcessAssocReq(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength); + +VOID rlmBssAborted(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); + +UINT32 +rlmFillHtCapIEByParams(BOOLEAN fg40mAllowed, + BOOLEAN fgShortGIDisabled, + UINT_8 u8SupportRxSgi20, + UINT_8 u8SupportRxSgi40, + UINT_8 u8SupportRxGf, UINT_8 u8SupportRxSTBC, ENUM_OP_MODE_T eCurrentOPMode, UINT_8 *pOutBuf); + +UINT32 rlmFillHtOpIeBody(P_BSS_INFO_T prBssInfo, UINT_8 *pFme); + +#if CFG_SUPPORT_DFS /* Add by Enlai */ +VOID rlmProcessSpecMgtAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); + +VOID rlmProcessChannelSwitchIE(P_ADAPTER_T prAdapter, P_IE_CHANNEL_SWITCH_T prChannelSwitchIE); +#endif + +VOID +rlmTxRateEnhanceConfig( + P_ADAPTER_T prAdapter + ); + +VOID +rlmCmd( + P_GLUE_INFO_T prGlueInfo, + UINT_8 *prInBuf, + UINT_32 u4InBufLen + ); +VOID rlmProcessNeighborReportResonse( + P_ADAPTER_T prAdapter, P_WLAN_ACTION_FRAME prAction, UINT_16 u2PacketLen); +VOID rlmTxNeighborReportRequest(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, + struct SUB_ELEMENT_LIST *prSubIEs); + +VOID rlmGernerateRRMEnabledCapIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +VOID rlmGerneratePowerCapIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +VOID rlmProcessRadioMeasurementRequest(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); + +VOID rlmProcessLinkMeasurementRequest(P_ADAPTER_T prAdapter, P_WLAN_ACTION_FRAME prAction); + +VOID rlmProcessNeighborReportResonse(P_ADAPTER_T prAdapter, P_WLAN_ACTION_FRAME prAction, UINT_16 u2PacketLen); + +VOID rlmFillRrmCapa(PUINT_8 pucCapa); + +VOID rlmSetMaxTxPwrLimit(IN P_ADAPTER_T prAdapter, INT_8 cLimit, UINT_8 ucEnable); + +VOID rlmStartNextMeasurement(P_ADAPTER_T prAdapter, BOOLEAN fgNewStarted); + +BOOLEAN rlmBcnRmRunning(P_ADAPTER_T prAdapter); + +BOOLEAN rlmFillScanMsg(P_ADAPTER_T prAdapter, P_MSG_SCN_SCAN_REQ prMsg); + +VOID rlmDoBeaconMeasurement(P_ADAPTER_T prAdapter, ULONG ulParam); + +VOID rlmTxNeighborReportRequest(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, struct SUB_ELEMENT_LIST *prSubIEs); + +VOID rlmTxRadioMeasurementReport(P_ADAPTER_T prAdapter); + +VOID rlmCancelRadioMeasurement(P_ADAPTER_T prAdapter); + +enum RM_REQ_PRIORITY rlmGetRmRequestPriority(PUINT_8 pucDestAddr); + +VOID rlmRunEventProcessNextRm(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr); + +VOID rlmScheduleNextRm(P_ADAPTER_T prAdapter); +#if CFG_SUPPORT_P2P_ECSA +void rlmGenActionCSHdr(u8 *buf, + u8 *da, u8 *sa, u8 *bssid, + u8 category, u8 action); + +void rlmGenActionCSA(u8 *buf, + u8 mode, + u8 channel, + u8 count, + u8 sco); + +void rlmGenActionECSA(u8 *buf, + u8 mode, + u8 channel, + u8 count, + u8 op_class); +VOID rlmGenerateCSAIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); +VOID rlmGenerateECSAIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); +VOID rlmFreqToChannelExt(unsigned int freq, + int sec_channel, + u8 *op_class, u8 *channel); +#endif + +#if CFG_SUPPORT_RLM_ACT_NETWORK +VOID rlmActivateNetwork(P_ADAPTER_T prAdapter, ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx, + ENUM_NET_ACTIVE_SRC_T eNetActiveSrcIdx); + +VOID rlmDeactivateNetwork(P_ADAPTER_T prAdapter, ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx, + ENUM_NET_ACTIVE_SRC_T eNetActiveSrcIdx); +#endif +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#ifndef _lint +static inline VOID rlmDataTypeCheck(VOID) +{ +#if CFG_ENABLE_BT_OVER_WIFI + DATA_STRUCT_INSPECTING_ASSERT(NETWORK_TYPE_AIS_INDEX < NETWORK_TYPE_BOW_INDEX); + +#if CFG_ENABLE_WIFI_DIRECT + DATA_STRUCT_INSPECTING_ASSERT(NETWORK_TYPE_P2P_INDEX < NETWORK_TYPE_BOW_INDEX); +#endif +#endif + +} +#endif /* _lint */ + +#endif /* _RLM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rlm_domain.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rlm_domain.h new file mode 100644 index 0000000000000..b8bfd648c0b62 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rlm_domain.h @@ -0,0 +1,532 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _RLM_DOMAIN_H +#define _RLM_DOMAIN_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define MAX_SUBBAND_NUM 6 +#define MAX_SUBBAND_NUM_5G 8 + +#define COUNTRY_CODE_NULL ((UINT_16)0x0) + +/* ISO/IEC 3166-1 two-character country codes */ + +#define COUNTRY_CODE_AD (((UINT_16) 'A' << 8) | (UINT_16) 'D') /* Andorra */ +#define COUNTRY_CODE_AE (((UINT_16) 'A' << 8) | (UINT_16) 'E') /* UAE */ +#define COUNTRY_CODE_AF (((UINT_16) 'A' << 8) | (UINT_16) 'F') /* Afghanistan */ +#define COUNTRY_CODE_AG (((UINT_16) 'A' << 8) | (UINT_16) 'G') /* Antigua & Barbuda */ +#define COUNTRY_CODE_AI (((UINT_16) 'A' << 8) | (UINT_16) 'I') /* Anguilla */ +#define COUNTRY_CODE_AL (((UINT_16) 'A' << 8) | (UINT_16) 'L') /* Albania */ +#define COUNTRY_CODE_AM (((UINT_16) 'A' << 8) | (UINT_16) 'M') /* Armenia */ +#define COUNTRY_CODE_AN (((UINT_16) 'A' << 8) | (UINT_16) 'N') /* Netherlands Antilles */ +#define COUNTRY_CODE_AO (((UINT_16) 'A' << 8) | (UINT_16) 'O') /* Angola */ +#define COUNTRY_CODE_AR (((UINT_16) 'A' << 8) | (UINT_16) 'R') /* Argentina */ +#define COUNTRY_CODE_AS (((UINT_16) 'A' << 8) | (UINT_16) 'S') /* American Samoa (USA) */ +#define COUNTRY_CODE_AT (((UINT_16) 'A' << 8) | (UINT_16) 'T') /* Austria */ +#define COUNTRY_CODE_AU (((UINT_16) 'A' << 8) | (UINT_16) 'U') /* Australia */ +#define COUNTRY_CODE_AW (((UINT_16) 'A' << 8) | (UINT_16) 'W') /* Aruba */ +#define COUNTRY_CODE_AZ (((UINT_16) 'A' << 8) | (UINT_16) 'Z') /* Azerbaijan */ +#define COUNTRY_CODE_BA (((UINT_16) 'B' << 8) | (UINT_16) 'A') /* Bosnia and Herzegovina */ +#define COUNTRY_CODE_BB (((UINT_16) 'B' << 8) | (UINT_16) 'B') /* Barbados */ +#define COUNTRY_CODE_BD (((UINT_16) 'B' << 8) | (UINT_16) 'D') /* Bangladesh */ +#define COUNTRY_CODE_BE (((UINT_16) 'B' << 8) | (UINT_16) 'E') /* Belgium */ +#define COUNTRY_CODE_BF (((UINT_16) 'B' << 8) | (UINT_16) 'F') /* Burkina Faso */ +#define COUNTRY_CODE_BG (((UINT_16) 'B' << 8) | (UINT_16) 'G') /* Bulgaria */ +#define COUNTRY_CODE_BH (((UINT_16) 'B' << 8) | (UINT_16) 'H') /* Bahrain */ +#define COUNTRY_CODE_BI (((UINT_16) 'B' << 8) | (UINT_16) 'I') /* Burundi */ +#define COUNTRY_CODE_BJ (((UINT_16) 'B' << 8) | (UINT_16) 'J') /* Benin */ +#define COUNTRY_CODE_BM (((UINT_16) 'B' << 8) | (UINT_16) 'M') /* Bermuda */ +#define COUNTRY_CODE_BN (((UINT_16) 'B' << 8) | (UINT_16) 'N') /* Brunei */ +#define COUNTRY_CODE_BO (((UINT_16) 'B' << 8) | (UINT_16) 'O') /* Bolivia */ +#define COUNTRY_CODE_BR (((UINT_16) 'B' << 8) | (UINT_16) 'R') /* Brazil */ +#define COUNTRY_CODE_BS (((UINT_16) 'B' << 8) | (UINT_16) 'S') /* Bahamas */ +#define COUNTRY_CODE_BT (((UINT_16) 'B' << 8) | (UINT_16) 'T') /* Bhutan */ +#define COUNTRY_CODE_BW (((UINT_16) 'B' << 8) | (UINT_16) 'W') /* Botswana */ +#define COUNTRY_CODE_BY (((UINT_16) 'B' << 8) | (UINT_16) 'Y') /* Belarus */ +#define COUNTRY_CODE_BZ (((UINT_16) 'B' << 8) | (UINT_16) 'Z') /* Belize */ +#define COUNTRY_CODE_CA (((UINT_16) 'C' << 8) | (UINT_16) 'A') /* Canada */ +#define COUNTRY_CODE_CD (((UINT_16) 'C' << 8) | (UINT_16) 'D') /* Congo. Democratic Republic of the */ +#define COUNTRY_CODE_CF (((UINT_16) 'C' << 8) | (UINT_16) 'F') /* Central African Republic */ +#define COUNTRY_CODE_CG (((UINT_16) 'C' << 8) | (UINT_16) 'G') /* Congo. Republic of the */ +#define COUNTRY_CODE_CH (((UINT_16) 'C' << 8) | (UINT_16) 'H') /* Switzerland */ +#define COUNTRY_CODE_CI (((UINT_16) 'C' << 8) | (UINT_16) 'I') /* Cote d'lvoire */ +#define COUNTRY_CODE_CK (((UINT_16) 'C' << 8) | (UINT_16) 'K') /* Cook Island */ +#define COUNTRY_CODE_CL (((UINT_16) 'C' << 8) | (UINT_16) 'L') /* Chile */ +#define COUNTRY_CODE_CM (((UINT_16) 'C' << 8) | (UINT_16) 'M') /* Cameroon */ +#define COUNTRY_CODE_CN (((UINT_16) 'C' << 8) | (UINT_16) 'N') /* China */ +#define COUNTRY_CODE_CO (((UINT_16) 'C' << 8) | (UINT_16) 'O') /* Columbia */ +#define COUNTRY_CODE_CR (((UINT_16) 'C' << 8) | (UINT_16) 'R') /* Costa Rica */ +#define COUNTRY_CODE_CU (((UINT_16) 'C' << 8) | (UINT_16) 'U') /* Cuba */ +#define COUNTRY_CODE_CV (((UINT_16) 'C' << 8) | (UINT_16) 'V') /* Cape Verde */ +#define COUNTRY_CODE_CX (((UINT_16) 'C' << 8) | (UINT_16) 'X') /* "Christmas Island(Australia) */ +#define COUNTRY_CODE_CY (((UINT_16) 'C' << 8) | (UINT_16) 'Y') /* Cyprus */ +#define COUNTRY_CODE_CZ (((UINT_16) 'C' << 8) | (UINT_16) 'Z') /* Czech */ +#define COUNTRY_CODE_DE (((UINT_16) 'D' << 8) | (UINT_16) 'E') /* Germany */ +#define COUNTRY_CODE_DJ (((UINT_16) 'D' << 8) | (UINT_16) 'J') /* Djibouti */ +#define COUNTRY_CODE_DK (((UINT_16) 'D' << 8) | (UINT_16) 'K') /* Denmark */ +#define COUNTRY_CODE_DM (((UINT_16) 'D' << 8) | (UINT_16) 'M') /* Dominica */ +#define COUNTRY_CODE_DO (((UINT_16) 'D' << 8) | (UINT_16) 'O') /* Dominican Republic */ +#define COUNTRY_CODE_DZ (((UINT_16) 'D' << 8) | (UINT_16) 'Z') /* Algeria */ +#define COUNTRY_CODE_EC (((UINT_16) 'E' << 8) | (UINT_16) 'C') /* Ecuador */ +#define COUNTRY_CODE_EE (((UINT_16) 'E' << 8) | (UINT_16) 'E') /* Estonia */ +#define COUNTRY_CODE_EG (((UINT_16) 'E' << 8) | (UINT_16) 'G') /* Egypt */ +#define COUNTRY_CODE_EH (((UINT_16) 'E' << 8) | (UINT_16) 'H') /* Western Sahara (Morocco) */ +#define COUNTRY_CODE_ER (((UINT_16) 'E' << 8) | (UINT_16) 'R') /* Eritrea */ +#define COUNTRY_CODE_ES (((UINT_16) 'E' << 8) | (UINT_16) 'S') /* Spain */ +#define COUNTRY_CODE_ET (((UINT_16) 'E' << 8) | (UINT_16) 'T') /* Ethiopia */ +#define COUNTRY_CODE_EU (((UINT_16) 'E' << 8) | (UINT_16) 'U') /* Europe */ +#define COUNTRY_CODE_FI (((UINT_16) 'F' << 8) | (UINT_16) 'I') /* Finland */ +#define COUNTRY_CODE_FJ (((UINT_16) 'F' << 8) | (UINT_16) 'J') /* Fiji */ +#define COUNTRY_CODE_FK (((UINT_16) 'F' << 8) | (UINT_16) 'K') /* Falkland Island */ +#define COUNTRY_CODE_FM (((UINT_16) 'F' << 8) | (UINT_16) 'M') /* Micronesia */ +#define COUNTRY_CODE_FO (((UINT_16) 'F' << 8) | (UINT_16) 'O') /* Faroe Island */ +#define COUNTRY_CODE_FR (((UINT_16) 'F' << 8) | (UINT_16) 'R') /* France */ +#define COUNTRY_CODE_FR (((UINT_16) 'F' << 8) | (UINT_16) 'R') /* Wallis and Futuna (France) */ +#define COUNTRY_CODE_GA (((UINT_16) 'G' << 8) | (UINT_16) 'A') /* Gabon */ +#define COUNTRY_CODE_GB (((UINT_16) 'G' << 8) | (UINT_16) 'B') /* United Kingdom */ +#define COUNTRY_CODE_GD (((UINT_16) 'G' << 8) | (UINT_16) 'D') /* Grenada */ +#define COUNTRY_CODE_GE (((UINT_16) 'G' << 8) | (UINT_16) 'E') /* Georgia */ +#define COUNTRY_CODE_GF (((UINT_16) 'G' << 8) | (UINT_16) 'F') /* French Guiana */ +#define COUNTRY_CODE_GG (((UINT_16) 'G' << 8) | (UINT_16) 'G') /* Guernsey */ +#define COUNTRY_CODE_GH (((UINT_16) 'G' << 8) | (UINT_16) 'H') /* Ghana */ +#define COUNTRY_CODE_GI (((UINT_16) 'G' << 8) | (UINT_16) 'I') /* Gibraltar */ +#define COUNTRY_CODE_GM (((UINT_16) 'G' << 8) | (UINT_16) 'M') /* Gambia */ +#define COUNTRY_CODE_GN (((UINT_16) 'G' << 8) | (UINT_16) 'N') /* Guinea */ +#define COUNTRY_CODE_GP (((UINT_16) 'G' << 8) | (UINT_16) 'P') /* Guadeloupe */ +#define COUNTRY_CODE_GQ (((UINT_16) 'G' << 8) | (UINT_16) 'Q') /* Equatorial Guinea */ +#define COUNTRY_CODE_GR (((UINT_16) 'G' << 8) | (UINT_16) 'R') /* Greece */ +#define COUNTRY_CODE_GT (((UINT_16) 'G' << 8) | (UINT_16) 'T') /* Guatemala */ +#define COUNTRY_CODE_GU (((UINT_16) 'G' << 8) | (UINT_16) 'U') /* Guam */ +#define COUNTRY_CODE_GW (((UINT_16) 'G' << 8) | (UINT_16) 'W') /* Guinea-Bissau */ +#define COUNTRY_CODE_GY (((UINT_16) 'G' << 8) | (UINT_16) 'Y') /* Guyana */ +#define COUNTRY_CODE_HK (((UINT_16) 'H' << 8) | (UINT_16) 'K') /* Hong Kong */ +#define COUNTRY_CODE_HN (((UINT_16) 'H' << 8) | (UINT_16) 'N') /* Honduras */ +#define COUNTRY_CODE_HR (((UINT_16) 'H' << 8) | (UINT_16) 'R') /* Croatia */ +#define COUNTRY_CODE_HT (((UINT_16) 'H' << 8) | (UINT_16) 'T') /* Haiti */ +#define COUNTRY_CODE_HU (((UINT_16) 'H' << 8) | (UINT_16) 'U') /* Hungary */ +#define COUNTRY_CODE_ID (((UINT_16) 'I' << 8) | (UINT_16) 'D') /* Indonesia */ +#define COUNTRY_CODE_IE (((UINT_16) 'I' << 8) | (UINT_16) 'E') /* Ireland */ +#define COUNTRY_CODE_IL (((UINT_16) 'I' << 8) | (UINT_16) 'L') /* Israel */ +#define COUNTRY_CODE_IM (((UINT_16) 'I' << 8) | (UINT_16) 'M') /* Isle of Man */ +#define COUNTRY_CODE_IN (((UINT_16) 'I' << 8) | (UINT_16) 'N') /* India */ +#define COUNTRY_CODE_IQ (((UINT_16) 'I' << 8) | (UINT_16) 'Q') /* Iraq */ +#define COUNTRY_CODE_IR (((UINT_16) 'I' << 8) | (UINT_16) 'R') /* Iran */ +#define COUNTRY_CODE_IS (((UINT_16) 'I' << 8) | (UINT_16) 'S') /* Iceland */ +#define COUNTRY_CODE_IT (((UINT_16) 'I' << 8) | (UINT_16) 'T') /* Italy */ +#define COUNTRY_CODE_JE (((UINT_16) 'J' << 8) | (UINT_16) 'E') /* Jersey */ +#define COUNTRY_CODE_JM (((UINT_16) 'J' << 8) | (UINT_16) 'M') /* Jameica */ +#define COUNTRY_CODE_JO (((UINT_16) 'J' << 8) | (UINT_16) 'O') /* Jordan */ +#define COUNTRY_CODE_JP (((UINT_16) 'J' << 8) | (UINT_16) 'P') /* Japan */ +#define COUNTRY_CODE_KE (((UINT_16) 'K' << 8) | (UINT_16) 'E') /* Kenya */ +#define COUNTRY_CODE_KG (((UINT_16) 'K' << 8) | (UINT_16) 'G') /* Kyrgyzstan */ +#define COUNTRY_CODE_KH (((UINT_16) 'K' << 8) | (UINT_16) 'H') /* Cambodia */ +#define COUNTRY_CODE_KI (((UINT_16) 'K' << 8) | (UINT_16) 'I') /* Kiribati */ +#define COUNTRY_CODE_KM (((UINT_16) 'K' << 8) | (UINT_16) 'M') /* Comoros */ +#define COUNTRY_CODE_KN (((UINT_16) 'K' << 8) | (UINT_16) 'N') /* Saint Kitts and Nevis */ +#define COUNTRY_CODE_KP (((UINT_16) 'K' << 8) | (UINT_16) 'P') /* North Korea */ +#define COUNTRY_CODE_KR (((UINT_16) 'K' << 8) | (UINT_16) 'R') /* South Korea */ +#define COUNTRY_CODE_KW (((UINT_16) 'K' << 8) | (UINT_16) 'W') /* Kuwait */ +#define COUNTRY_CODE_KY (((UINT_16) 'K' << 8) | (UINT_16) 'Y') /* Cayman Islands */ +#define COUNTRY_CODE_KZ (((UINT_16) 'K' << 8) | (UINT_16) 'Z') /* Kazakhstan */ +#define COUNTRY_CODE_LA (((UINT_16) 'L' << 8) | (UINT_16) 'A') /* Laos */ +#define COUNTRY_CODE_LB (((UINT_16) 'L' << 8) | (UINT_16) 'B') /* Lebanon */ +#define COUNTRY_CODE_LC (((UINT_16) 'L' << 8) | (UINT_16) 'C') /* Saint Lucia */ +#define COUNTRY_CODE_LI (((UINT_16) 'L' << 8) | (UINT_16) 'I') /* Liechtenstein */ +#define COUNTRY_CODE_LK (((UINT_16) 'L' << 8) | (UINT_16) 'K') /* Sri Lanka */ +#define COUNTRY_CODE_LR (((UINT_16) 'L' << 8) | (UINT_16) 'R') /* Liberia */ +#define COUNTRY_CODE_LS (((UINT_16) 'L' << 8) | (UINT_16) 'S') /* Lesotho */ +#define COUNTRY_CODE_LT (((UINT_16) 'L' << 8) | (UINT_16) 'T') /* Lithuania */ +#define COUNTRY_CODE_LU (((UINT_16) 'L' << 8) | (UINT_16) 'U') /* Luxemburg */ +#define COUNTRY_CODE_LV (((UINT_16) 'L' << 8) | (UINT_16) 'V') /* Latvia */ +#define COUNTRY_CODE_LY (((UINT_16) 'L' << 8) | (UINT_16) 'Y') /* Libya */ +#define COUNTRY_CODE_MA (((UINT_16) 'M' << 8) | (UINT_16) 'A') /* Morocco */ +#define COUNTRY_CODE_MC (((UINT_16) 'M' << 8) | (UINT_16) 'C') /* Monaco */ +#define COUNTRY_CODE_MD (((UINT_16) 'M' << 8) | (UINT_16) 'D') /* Moldova */ +#define COUNTRY_CODE_ME (((UINT_16) 'M' << 8) | (UINT_16) 'E') /* Montenegro */ +#define COUNTRY_CODE_MF (((UINT_16) 'M' << 8) | (UINT_16) 'F') /* + * Saint Martin / Sint Marteen + * (Added on window's list) + */ +#define COUNTRY_CODE_MG (((UINT_16) 'M' << 8) | (UINT_16) 'G') /* Madagascar */ +#define COUNTRY_CODE_MH (((UINT_16) 'M' << 8) | (UINT_16) 'H') /* Marshall Islands */ +#define COUNTRY_CODE_MK (((UINT_16) 'M' << 8) | (UINT_16) 'K') /* Macedonia */ +#define COUNTRY_CODE_ML (((UINT_16) 'M' << 8) | (UINT_16) 'L') /* Mali */ +#define COUNTRY_CODE_MM (((UINT_16) 'M' << 8) | (UINT_16) 'M') /* Myanmar */ +#define COUNTRY_CODE_MN (((UINT_16) 'M' << 8) | (UINT_16) 'N') /* Mongolia */ +#define COUNTRY_CODE_MO (((UINT_16) 'M' << 8) | (UINT_16) 'O') /* Macao */ +#define COUNTRY_CODE_MP (((UINT_16) 'M' << 8) | (UINT_16) 'P') /* + * Northern Mariana Islands (Rota Island. + * Saipan and Tinian Island) + */ +#define COUNTRY_CODE_MQ (((UINT_16) 'M' << 8) | (UINT_16) 'Q') /* Martinique (France) */ +#define COUNTRY_CODE_MR (((UINT_16) 'M' << 8) | (UINT_16) 'R') /* Mauritania */ +#define COUNTRY_CODE_MS (((UINT_16) 'M' << 8) | (UINT_16) 'S') /* Montserrat (UK) */ +#define COUNTRY_CODE_MT (((UINT_16) 'M' << 8) | (UINT_16) 'T') /* Malta */ +#define COUNTRY_CODE_MU (((UINT_16) 'M' << 8) | (UINT_16) 'U') /* Mauritius */ +#define COUNTRY_CODE_MV (((UINT_16) 'M' << 8) | (UINT_16) 'V') /* Maldives */ +#define COUNTRY_CODE_MW (((UINT_16) 'M' << 8) | (UINT_16) 'W') /* Malawi */ +#define COUNTRY_CODE_MX (((UINT_16) 'M' << 8) | (UINT_16) 'X') /* Mexico */ +#define COUNTRY_CODE_MY (((UINT_16) 'M' << 8) | (UINT_16) 'Y') /* Malaysia */ +#define COUNTRY_CODE_MZ (((UINT_16) 'M' << 8) | (UINT_16) 'Z') /* Mozambique */ +#define COUNTRY_CODE_NA (((UINT_16) 'N' << 8) | (UINT_16) 'A') /* Namibia */ +#define COUNTRY_CODE_NC (((UINT_16) 'N' << 8) | (UINT_16) 'C') /* New Caledonia */ +#define COUNTRY_CODE_NE (((UINT_16) 'N' << 8) | (UINT_16) 'E') /* Niger */ +#define COUNTRY_CODE_NF (((UINT_16) 'N' << 8) | (UINT_16) 'F') /* Norfolk Island */ +#define COUNTRY_CODE_NG (((UINT_16) 'N' << 8) | (UINT_16) 'G') /* Nigeria */ +#define COUNTRY_CODE_NI (((UINT_16) 'N' << 8) | (UINT_16) 'I') /* Nicaragua */ +#define COUNTRY_CODE_NL (((UINT_16) 'N' << 8) | (UINT_16) 'L') /* Netherlands */ +#define COUNTRY_CODE_NO (((UINT_16) 'N' << 8) | (UINT_16) 'O') /* Norway */ +#define COUNTRY_CODE_NP (((UINT_16) 'N' << 8) | (UINT_16) 'P') /* Nepal */ +#define COUNTRY_CODE_NR (((UINT_16) 'N' << 8) | (UINT_16) 'R') /* Nauru */ +#define COUNTRY_CODE_NU (((UINT_16) 'N' << 8) | (UINT_16) 'U') /* Niue */ +#define COUNTRY_CODE_NZ (((UINT_16) 'N' << 8) | (UINT_16) 'Z') /* New Zealand */ +#define COUNTRY_CODE_OM (((UINT_16) 'O' << 8) | (UINT_16) 'M') /* Oman */ +#define COUNTRY_CODE_PA (((UINT_16) 'P' << 8) | (UINT_16) 'A') /* Panama */ +#define COUNTRY_CODE_PE (((UINT_16) 'P' << 8) | (UINT_16) 'E') /* Peru */ +#define COUNTRY_CODE_PF (((UINT_16) 'P' << 8) | (UINT_16) 'F') /* "French Polynesia */ +#define COUNTRY_CODE_PG (((UINT_16) 'P' << 8) | (UINT_16) 'G') /* Papua New Guinea */ +#define COUNTRY_CODE_PH (((UINT_16) 'P' << 8) | (UINT_16) 'H') /* Philippines */ +#define COUNTRY_CODE_PK (((UINT_16) 'P' << 8) | (UINT_16) 'K') /* Pakistan */ +#define COUNTRY_CODE_PL (((UINT_16) 'P' << 8) | (UINT_16) 'L') /* Poland */ +#define COUNTRY_CODE_PM (((UINT_16) 'P' << 8) | (UINT_16) 'M') /* Saint Pierre and Miquelon */ +#define COUNTRY_CODE_PN (((UINT_16) 'P' << 8) | (UINT_16) 'N') /* Pitcairn Islands */ +#define COUNTRY_CODE_PR (((UINT_16) 'P' << 8) | (UINT_16) 'R') /* Puerto Rico (USA) */ +#define COUNTRY_CODE_PS (((UINT_16) 'P' << 8) | (UINT_16) 'S') /* Palestinian Authority */ +#define COUNTRY_CODE_PT (((UINT_16) 'P' << 8) | (UINT_16) 'T') /* Portugal */ +#define COUNTRY_CODE_PW (((UINT_16) 'P' << 8) | (UINT_16) 'W') /* Palau */ +#define COUNTRY_CODE_PY (((UINT_16) 'P' << 8) | (UINT_16) 'Y') /* Paraguay */ +#define COUNTRY_CODE_QA (((UINT_16) 'Q' << 8) | (UINT_16) 'A') /* Qatar */ +#define COUNTRY_CODE_RE (((UINT_16) 'R' << 8) | (UINT_16) 'E') /* Reunion (France) */ +#define COUNTRY_CODE_RKS (((UINT_16) 'R' << 8) | (UINT_16) 'K') /* Kosvo (Added on window's list) */ +#define COUNTRY_CODE_RO (((UINT_16) 'R' << 8) | (UINT_16) 'O') /* Romania */ +#define COUNTRY_CODE_RS (((UINT_16) 'R' << 8) | (UINT_16) 'S') /* Serbia */ +#define COUNTRY_CODE_RU (((UINT_16) 'R' << 8) | (UINT_16) 'U') /* Russia */ +#define COUNTRY_CODE_RW (((UINT_16) 'R' << 8) | (UINT_16) 'W') /* Rwanda */ +#define COUNTRY_CODE_SA (((UINT_16) 'S' << 8) | (UINT_16) 'A') /* Saudi Arabia */ +#define COUNTRY_CODE_SB (((UINT_16) 'S' << 8) | (UINT_16) 'B') /* Solomon Islands */ +#define COUNTRY_CODE_SC (((UINT_16) 'S' << 8) | (UINT_16) 'C') /* Seychelles */ +#define COUNTRY_CODE_SD (((UINT_16) 'S' << 8) | (UINT_16) 'D') /* Sudan */ +#define COUNTRY_CODE_SE (((UINT_16) 'S' << 8) | (UINT_16) 'E') /* Sweden */ +#define COUNTRY_CODE_SG (((UINT_16) 'S' << 8) | (UINT_16) 'G') /* Singapole */ +#define COUNTRY_CODE_SI (((UINT_16) 'S' << 8) | (UINT_16) 'I') /* Slovenia */ +#define COUNTRY_CODE_SK (((UINT_16) 'S' << 8) | (UINT_16) 'K') /* Slovakia */ +#define COUNTRY_CODE_SL (((UINT_16) 'S' << 8) | (UINT_16) 'L') /* Sierra Leone */ +#define COUNTRY_CODE_SM (((UINT_16) 'S' << 8) | (UINT_16) 'M') /* San Marino */ +#define COUNTRY_CODE_SN (((UINT_16) 'S' << 8) | (UINT_16) 'N') /* Senegal */ +#define COUNTRY_CODE_SO (((UINT_16) 'S' << 8) | (UINT_16) 'O') /* Somalia */ +#define COUNTRY_CODE_SR (((UINT_16) 'S' << 8) | (UINT_16) 'R') /* Suriname */ +#define COUNTRY_CODE_SS (((UINT_16) 'S' << 8) | (UINT_16) 'S') /* South_Sudan */ +#define COUNTRY_CODE_ST (((UINT_16) 'S' << 8) | (UINT_16) 'T') /* Sao Tome and Principe */ +#define COUNTRY_CODE_SV (((UINT_16) 'S' << 8) | (UINT_16) 'V') /* El Salvador */ +#define COUNTRY_CODE_SY (((UINT_16) 'S' << 8) | (UINT_16) 'Y') /* Syria */ +#define COUNTRY_CODE_SZ (((UINT_16) 'S' << 8) | (UINT_16) 'Z') /* Swaziland */ +#define COUNTRY_CODE_TC (((UINT_16) 'T' << 8) | (UINT_16) 'C') /* Turks and Caicos Islands (UK) */ +#define COUNTRY_CODE_TD (((UINT_16) 'T' << 8) | (UINT_16) 'D') /* Chad */ +#define COUNTRY_CODE_TF (((UINT_16) 'T' << 8) | (UINT_16) 'F') /* French Southern and Antarctic Lands */ +#define COUNTRY_CODE_TG (((UINT_16) 'T' << 8) | (UINT_16) 'G') /* Togo */ +#define COUNTRY_CODE_TH (((UINT_16) 'T' << 8) | (UINT_16) 'H') /* Thailand */ +#define COUNTRY_CODE_TJ (((UINT_16) 'T' << 8) | (UINT_16) 'J') /* Tajikistan */ +#define COUNTRY_CODE_TL (((UINT_16) 'T' << 8) | (UINT_16) 'L') /* East Timor */ +#define COUNTRY_CODE_TM (((UINT_16) 'T' << 8) | (UINT_16) 'M') /* Turkmenistan */ +#define COUNTRY_CODE_TN (((UINT_16) 'T' << 8) | (UINT_16) 'N') /* Tunisia */ +#define COUNTRY_CODE_TO (((UINT_16) 'T' << 8) | (UINT_16) 'O') /* Tonga */ +#define COUNTRY_CODE_TR (((UINT_16) 'T' << 8) | (UINT_16) 'R') /* Turkey */ +#define COUNTRY_CODE_TT (((UINT_16) 'T' << 8) | (UINT_16) 'T') /* Trinidad and Tobago */ +#define COUNTRY_CODE_TV (((UINT_16) 'T' << 8) | (UINT_16) 'V') /* Tuvalu */ +#define COUNTRY_CODE_TW (((UINT_16) 'T' << 8) | (UINT_16) 'W') /* Taiwan */ +#define COUNTRY_CODE_TZ (((UINT_16) 'T' << 8) | (UINT_16) 'Z') /* Tanzania */ +#define COUNTRY_CODE_UA (((UINT_16) 'U' << 8) | (UINT_16) 'A') /* Ukraine */ +#define COUNTRY_CODE_UG (((UINT_16) 'U' << 8) | (UINT_16) 'G') /* Ugnada */ +#define COUNTRY_CODE_US (((UINT_16) 'U' << 8) | (UINT_16) 'S') /* US */ +#define COUNTRY_CODE_UY (((UINT_16) 'U' << 8) | (UINT_16) 'Y') /* Uruguay */ +#define COUNTRY_CODE_UZ (((UINT_16) 'U' << 8) | (UINT_16) 'Z') /* Uzbekistan */ +#define COUNTRY_CODE_VA (((UINT_16) 'V' << 8) | (UINT_16) 'A') /* Vatican (Holy See) */ +#define COUNTRY_CODE_VC (((UINT_16) 'V' << 8) | (UINT_16) 'C') /* Saint Vincent and the Grenadines */ +#define COUNTRY_CODE_VE (((UINT_16) 'V' << 8) | (UINT_16) 'E') /* Venezuela */ +#define COUNTRY_CODE_VG (((UINT_16) 'V' << 8) | (UINT_16) 'G') /* British Virgin Islands */ +#define COUNTRY_CODE_VI (((UINT_16) 'V' << 8) | (UINT_16) 'I') /* US Virgin Islands */ +#define COUNTRY_CODE_VN (((UINT_16) 'V' << 8) | (UINT_16) 'N') /* Vietnam */ +#define COUNTRY_CODE_VU (((UINT_16) 'V' << 8) | (UINT_16) 'U') /* Vanuatu */ +#define COUNTRY_CODE_WS (((UINT_16) 'W' << 8) | (UINT_16) 'S') /* Samoa */ +#define COUNTRY_CODE_YE (((UINT_16) 'Y' << 8) | (UINT_16) 'E') /* Yemen */ +#define COUNTRY_CODE_YT (((UINT_16) 'Y' << 8) | (UINT_16) 'T') /* Mayotte (France) */ +#define COUNTRY_CODE_ZA (((UINT_16) 'Z' << 8) | (UINT_16) 'A') /* South Africa */ +#define COUNTRY_CODE_ZM (((UINT_16) 'Z' << 8) | (UINT_16) 'M') /* Zambia */ +#define COUNTRY_CODE_ZW (((UINT_16) 'Z' << 8) | (UINT_16) 'W') /* Zimbabwe */ + +#define COUNTRY_CODE_DF (((UINT_16) 'D' << 8) | (UINT_16) 'F') /* Default country domain */ + +#ifdef CONFIG_MTK_TC1_FEATURE +#define COUNTRY_CODE_UDF (((UINT_16) 'D' << 8) | (UINT_16) 'C') /* + * Default Country Code, for User + * Defined channel list and passive scan channel list + */ +#else +#define COUNTRY_CODE_UDF (((UINT_16) 'U' << 8) | (UINT_16) 'D') /* + * User defined supported channel list + * and passive scan channel list + */ +#endif +#define COUNTRY_CODE_FF (((UINT_16) 'F' << 8) | (UINT_16) 'F') /* enable open for all channel for Certification */ +#define COUNTRY_CODE_FE (((UINT_16) 'F' << 8) | (UINT_16) 'E') /* disable open for all channel for Certification */ + +/* dot11RegDomainsSupportValue */ +#define MIB_REG_DOMAIN_FCC 0x10 /* FCC (US) */ +#define MIB_REG_DOMAIN_IC 0x20 /* IC or DOC (Canada) */ +#define MIB_REG_DOMAIN_ETSI 0x30 /* ETSI (Europe) */ +#define MIB_REG_DOMAIN_SPAIN 0x31 /* Spain */ +#define MIB_REG_DOMAIN_FRANCE 0x32 /* France */ +#define MIB_REG_DOMAIN_JAPAN 0x40 /* MPHPT (Japan) */ +#define MIB_REG_DOMAIN_OTHER 0x00 /* other */ + +/*2.4G*/ +#define BAND_2G4_LOWER_BOUND 1 +#define BAND_2G4_UPPER_BOUND 14 +/*5G SubBand FCC spec*/ +#define UNII1_LOWER_BOUND 36 +#define UNII1_UPPER_BOUND 48 +#define UNII2A_LOWER_BOUND 52 +#define UNII2A_UPPER_BOUND 64 +#define UNII2C_LOWER_BOUND 100 +#define UNII2C_UPPER_BOUND 144 +#define UNII3_LOWER_BOUND 149 +#define UNII3_UPPER_BOUND 173 + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +#define POWER_LIMIT_TABLE_NULL 0xFFFF +#define MAX_TX_POWER 63 +#define MIN_TX_POWER -64 +#define MAX_CMD_SUPPORT_CHANNEL_NUM 64 + +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +typedef enum _ENUM_POWER_LIMIT_T { + PWR_LIMIT_CCK, + PWR_LIMIT_20M, + PWR_LIMIT_40M, + PWR_LIMIT_80M, + PWR_LIMIT_160M, + PWR_LIMIT_NUM +} ENUM_POWER_LIMIT_T, *P_ENUM_POWER_LIMIT_T; + +#endif + +typedef enum _ENUM_POWER_LIMIT_SUBBAND_T { + POWER_LIMIT_2G4, + POWER_LIMIT_UNII1, + POWER_LIMIT_UNII2A, + POWER_LIMIT_UNII2C, + POWER_LIMIT_UNII3, + POWER_LIMIT_SUBAND_NUM +} ENUM_POWER_LIMIT_SUBBAND_T, *P_ENUM_POWER_LIMIT_SUBBAND_T; + +/* Define channel offset in unit of 5MHz bandwidth */ +typedef enum _ENUM_CHNL_SPAN_T { + CHNL_SPAN_5 = 1, + CHNL_SPAN_10 = 2, + CHNL_SPAN_20 = 4, + CHNL_SPAN_40 = 8 +} ENUM_CHNL_SPAN_T, *P_ENUM_CHNL_SPAN_T; + +/* Define BSS operating bandwidth */ +typedef enum _ENUM_CHNL_BW_T { + CHNL_BW_20, + CHNL_BW_20_40, + CHNL_BW_10, + CHNL_BW_5 +} ENUM_CHNL_BW_T, *P_ENUM_CHNL_BW_T; + +/* In all bands, the first channel will be SCA and the second channel is SCB, + * then iteratively. + * Note the final channel will not be SCA. + */ +typedef struct _DOMAIN_SUBBAND_INFO { + /* Note1: regulation class depends on operation bandwidth and RF band. + * For example: 2.4GHz, 1~13, 20MHz ==> regulation class = 81 + * 2.4GHz, 1~13, SCA ==> regulation class = 83 + * 2.4GHz, 1~13, SCB ==> regulation class = 84 + * Note2: TX power limit is not specified here because path loss is unknown + */ + UINT_8 ucRegClass; /* Regulation class for 20MHz */ + UINT_8 ucBand; /* Type: ENUM_BAND_T */ + UINT_8 ucChannelSpan; /* Type: ENUM_CHNL_SPAN_T */ + UINT_8 ucFirstChannelNum; + UINT_8 ucNumChannels; + UINT_8 fgDfs; /* Type: BOOLEAN */ +} DOMAIN_SUBBAND_INFO, *P_DOMAIN_SUBBAND_INFO; + +/* Use it as all available channel list for STA */ +typedef struct _DOMAIN_INFO_ENTRY { + PUINT_16 pu2CountryGroup; + UINT_32 u4CountryNum; + + /* If different attributes, put them into different rSubBands. + * For example, DFS shall be used or not. + */ + DOMAIN_SUBBAND_INFO rSubBand[MAX_SUBBAND_NUM]; +} DOMAIN_INFO_ENTRY, *P_DOMAIN_INFO_ENTRY; + + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +typedef struct _CHANNEL_POWER_LIMIT { + UINT_8 ucCentralCh; + INT_8 cPwrLimitCCK; + INT_8 cPwrLimit20; + INT_8 cPwrLimit40; + INT_8 cPwrLimit80; + INT_8 cPwrLimit160; + UINT_8 ucFlag; + UINT_8 aucReserved[1]; +} CHANNEL_POWER_LIMIT, *P_CHANNEL_POWER_LIMIT; + +typedef struct _COUNTRY_CHANNEL_POWER_LIMIT { + UINT_8 aucCountryCode[2]; + UINT_8 ucCountryFlag; + UINT_8 ucChannelNum; + UINT_8 aucReserved[4]; + CHANNEL_POWER_LIMIT rChannelPowerLimit[80]; +} COUNTRY_CHANNEL_POWER_LIMIT, *P_COUNTRY_CHANNEL_POWER_LIMIT; + +#define CHANNEL_PWR_LIMIT(_channel, _pwrLimit_cck, _pwrLimit_bw20, \ + _pwrLimit_bw40, _pwrLimit_bw80, _pwrLimit_bw160, _ucFlag) \ + { \ + .ucCentralCh = (_channel), \ + .cPwrLimitCCK = (_pwrLimit_cck), \ + .cPwrLimit20 = (_pwrLimit_bw20), \ + .cPwrLimit40 = (_pwrLimit_bw40), \ + .cPwrLimit80 = (_pwrLimit_bw80), \ + .cPwrLimit160 = (_pwrLimit_bw160), \ + .ucFlag = (_ucFlag), \ + .aucReserved = {0} \ +} + +typedef struct _COUNTRY_POWER_LIMIT_TABLE_DEFAULT { + UINT_8 aucCountryCode[2]; + /* 0: ch 1 ~14 , 1: ch 36 ~48, 2: ch 52 ~64, 3: ch 100 ~144, 4: ch 149 ~165 */ + INT_8 aucPwrLimitSubBand[POWER_LIMIT_SUBAND_NUM]; + /* + * bit0: cPwrLimit2G4, bit1: cPwrLimitUnii1; bit2: cPwrLimitUnii2A; + * bit3: cPwrLimitUnii2C; bit4: cPwrLimitUnii3; mW: 0, mW\MHz : 1 + */ + UINT_8 ucPwrUnit; +} COUNTRY_POWER_LIMIT_TABLE_DEFAULT, *P_COUNTRY_POWER_LIMIT_TABLE_DEFAULT; + +typedef struct _COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION { + UINT_8 aucCountryCode[2]; + UINT_8 ucCentralCh; + INT_8 aucPwrLimit[PWR_LIMIT_NUM]; +} COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION, *P_COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION; + +typedef struct _SUBBAND_CHANNEL_T { + UINT_8 ucStartCh; + UINT_8 ucEndCh; + UINT_8 ucInterval; + UINT_8 ucReserved; +} SUBBAND_CHANNEL_T, *P_SUBBAND_CHANNEL_T; + +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define CAL_CH_OFFSET_80M(_PRIMARY_CH, _CENTRAL_CH) \ + (((_PRIMARY_CH - _CENTRAL_CH) + 6) >> 2) + +#define CAL_CH_OFFSET_160M(_PRIMARY_CH, _CENTRAL_CH) \ + (((_PRIMARY_CH - _CENTRAL_CH) + 14) >> 2) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +P_DOMAIN_INFO_ENTRY rlmDomainGetDomainInfo(P_ADAPTER_T prAdapter); + +VOID rlmDomainGetChnlList(P_ADAPTER_T prAdapter, + ENUM_BAND_T eSpecificBand, BOOLEAN fgNoDfs, + UINT_8 ucMaxChannelNum, PUINT_8 pucNumOfChannel, P_RF_CHANNEL_INFO_T paucChannelList); + +VOID rlmDomainGetDfsChnls(P_ADAPTER_T prAdapter, + UINT_8 ucMaxChannelNum, PUINT_8 pucNumOfChannel, P_RF_CHANNEL_INFO_T paucChannelList); + +VOID rlmDomainSendCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid); + +VOID rlmDomainSendDomainInfoCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid); + +VOID rlmDomainSendPassiveScanInfoCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid); + +BOOLEAN rlmDomainIsLegalChannel(P_ADAPTER_T prAdapter, ENUM_BAND_T eBand, UINT_8 ucChannel); + +UINT_32 rlmDomainSupOperatingClassIeFill(PUINT_8 pBuf); + +BOOLEAN rlmDomainCheckChannelEntryValid(P_ADAPTER_T prAdapter, UINT_8 ucCentralCh); + +UINT_8 rlmDomainGetCenterChannel(ENUM_BAND_T eBand, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend); + +BOOLEAN rlmDomainIsValidRfSetting(P_ADAPTER_T prAdapter, ENUM_BAND_T eBand, + UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend, + ENUM_CHANNEL_WIDTH_T eChannelWidth, UINT_8 ucChannelS1, UINT_8 ucChannelS2); + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +BOOLEAN +rlmDomainCheckPowerLimitValid(P_ADAPTER_T prAdapter, + COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION rPowerLimitTableConfiguration, + UINT_8 ucPwrLimitNum); + +VOID rlmDomainCheckCountryPowerLimitTable(P_ADAPTER_T prAdapter); + +UINT_16 rlmDomainPwrLimitDefaultTableDecision(P_ADAPTER_T prAdapter, UINT_16 u2CountryCode); + +VOID rlmDomainSendPwrLimitCmd(P_ADAPTER_T prAdapter); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _RLM_DOMAIN_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rlm_obss.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rlm_obss.h new file mode 100644 index 0000000000000..2fc70b7af0f56 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rlm_obss.h @@ -0,0 +1,98 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _RLM_OBSS_H +#define _RLM_OBSS_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define CHNL_LIST_SZ_2G 14 +#define CHNL_LIST_SZ_5G 14 + +#define CHNL_LEVEL0 0 +#define CHNL_LEVEL1 1 +#define CHNL_LEVEL2 2 + +#define AFFECTED_CHNL_OFFSET 5 + +#define OBSS_SCAN_MIN_INTERVAL 10 /* In unit of sec */ + +#define PUBLIC_ACTION_MAX_LEN 200 /* In unit of byte */ + +/* P2P GO only */ +/* Define default OBSS Scan parameters (from MIB in spec.) */ +#define dot11OBSSScanPassiveDwell 20 +#define dot11OBSSScanActiveDwell 10 +#define dot11OBSSScanPassiveTotalPerChannel 200 +#define dot11OBSSScanActiveTotalPerChannel 20 +#define dot11BSSWidthTriggerScanInterval 300 /* Unit: sec */ +#define dot11BSSWidthChannelTransitionDelayFactor 5 +#define dot11OBSSScanActivityThreshold 25 + +#define OBSS_20_40M_TIMEOUT (dot11BSSWidthTriggerScanInterval + 10) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/* Control MAC PCO function */ +typedef enum _ENUM_SYS_PCO_PHASE_T { + SYS_PCO_PHASE_DISABLED = 0, + SYS_PCO_PHASE_20M, + SYS_PCO_PHASE_40M +} ENUM_SYS_PCO_PHASE_T, *P_ENUM_SYS_PCO_PHASE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID rlmObssInit(P_ADAPTER_T prAdapter); + +VOID rlmObssScanDone(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr); + +VOID rlmObssTriggerScan(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _RLM_OBSS_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rlm_protection.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rlm_protection.h new file mode 100644 index 0000000000000..a3965a5a0dd38 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rlm_protection.h @@ -0,0 +1,95 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _RLM_PROTECTION_H +#define _RLM_PROTECTION_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_SYS_PROTECT_MODE_T { + SYS_PROTECT_MODE_NONE = 0, /* Mode 0 */ + SYS_PROTECT_MODE_ERP, /* Mode 1 */ + SYS_PROTECT_MODE_NON_HT, /* Mode 2 */ + SYS_PROTECT_MODE_20M, /* Mode 3 */ + + SYS_PROTECT_MODE_NUM +} ENUM_SYS_PROTECT_MODE_T, *P_ENUM_SYS_PROTECT_MODE_T; + +/* This definition follows HT Protection field of HT Operation IE */ +typedef enum _ENUM_HT_PROTECT_MODE_T { + HT_PROTECT_MODE_NONE = 0, + HT_PROTECT_MODE_NON_MEMBER, + HT_PROTECT_MODE_20M, + HT_PROTECT_MODE_NON_HT, + + HT_PROTECT_MODE_NUM +} ENUM_HT_PROTECT_MODE_T, *P_ENUM_HT_PROTECT_MODE_T; + +typedef enum _ENUM_GF_MODE_T { + GF_MODE_NORMAL = 0, + GF_MODE_PROTECT, + GF_MODE_DISALLOWED, + + GF_MODE_NUM +} ENUM_GF_MODE_T, *P_ENUM_GF_MODE_T; + +typedef enum _ENUM_RIFS_MODE_T { + RIFS_MODE_NORMAL = 0, + RIFS_MODE_DISALLOWED, + + RIFS_MODE_NUM +} ENUM_RIFS_MODE_T, *P_ENUM_RIFS_MODE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _RLM_PROTECTION_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rlm_txpwr_init.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rlm_txpwr_init.h new file mode 100644 index 0000000000000..7037c9774ad56 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rlm_txpwr_init.h @@ -0,0 +1,1213 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _RLM_TXPWR_INIT_H +#define _RLM_TXPWR_INIT_H + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/*Support Tx Power Range : 63~ -64 (unit : 0.5dBm)*/ + +#define PWR_LIMIT_2G4_IN_MW_MHZ BIT(0) +#define PWR_LIMIT_UNII1_IN_MW_MHZ BIT(1) +#define PWR_LIMIT_UNII2A_IN_MW_MHZ BIT(2) +#define PWR_LIMIT_UNII2C_IN_MW_MHZ BIT(3) +#define PWR_LIMIT_UNII3_IN_MW_MHZ BIT(4) + +#if CFG_SUPPORT_CE_FCC_TXPWR_LIMIT +#define CE_FCC_TXPWR_LIMIT_CCK 30 /* 15 dBm */ +#define CE_FCC_TXPWR_LIMIT_OFDM 20 /* 10 dBm */ +#define CE_FCC_TXPWR_LIMIT_HT40 18 /* 9 dBm */ +#endif + + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +COUNTRY_POWER_LIMIT_TABLE_DEFAULT g_rRlmPowerLimitDefault[] = { + + {{'A', 'O'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'B', 'Z'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'B', 'J'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'B', 'T'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'B', 'O'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'B', 'I'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'C', 'M'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'C', 'F'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'T', 'D'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'K', 'M'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'C', 'D'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'C', 'G'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'C', 'I'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'D', 'J'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'G', 'Q'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'E', 'R'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'F', 'J'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'G', 'A'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'G', 'M'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'G', 'N'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'G', 'W'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'R', 'K'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'K', 'G'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'L', 'Y'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'M', 'G'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'M', 'L'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'N', 'R'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'N', 'C'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'T'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'C'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'L'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'B'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'O'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'R'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'Z'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'T', 'J'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'T', 'G'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'T', 'O'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'T', 'M'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'T', 'V'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'V', 'U'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'Y', 'E'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'A', 'S'} + , {60, 34, 46, 48, 60} + , 0} + , + {{'A', 'I'} + , {60, 34, 48, 60, 60} + , 0} + , + {{'B', 'M'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'C', 'A'} + , {60, 46, 48, 48, 60} + , 0} + , + {{'K', 'Y'} + , {60, 34, 48, 60, 60} + , 0} + , + {{'G', 'U'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'F', 'M'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'P', 'R'} + , {60, 34, 46, 48, 60} + , 0} + , + {{'U', 'S'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'V', 'I'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'A', 'R'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'A', 'U'} + , {63, 46, 46, 60, 63} + , 0} + , + {{'A', 'Z'} + , {40, 34, 48, 60, 60} + , 0} + , + {{'B', 'W'} + , {40, 46, 46, 60, 60} + , 0} + , + {{'K', 'H'} + , {40, 46, 46, 48, 60} + , 0} + , + {{'C', 'X'} + , {63, 46, 46, 60, 63} + , 0} + , + {{'C', 'O'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'C', 'R'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'E', 'C'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'G', 'D'} + , {40, 46, 46, 60, 60} + , 0} + , + {{'G', 'T'} + , {40, 34, 48, 48, 60} + , 0} + , + {{'H', 'K'} + , {63, 46, 46, 60, 63} + , 0} + , + {{'K', 'I'} + , {63, 46, 46, 60, 63} + , 0} + , + {{'L', 'B'} + , {40, 46, 46, 46, 46} + , 0} + , + {{'L', 'R'} + , {60, 46, 60, 63, 63} + , 0} + , + {{'M', 'N'} + , {46, 32, 46, 46, 58} + , 0} + , + {{'A', 'N'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'N', 'Z'} + , {63, 46, 60, 48, 63} + , 0} + , + {{'N', 'I'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'P', 'W'} + , {60, 60, 60, 60, 60} + , 0} + , + {{'P', 'Y'} + , {60, 46, 46, 48, 60} + , 0} + , + {{'P', 'E'} + , {54, 46, 48, 42, 48} + , 0} + , + {{'P', 'H'} + , {40, 46, 46, 48, 48} + , 0} + , + {{'W', 'S'} + , {40, 40, 40, 40, 60} + , 0} + , + {{'S', 'G'} + , {46, 46, 46, 60, 60} + , 0} + , + {{'L', 'K'} + , {46, 46, 46, 46, 46} + , 0} + , + {{'T', 'H'} + , {40, 46, 46, 60, 60} + , 0} + , + {{'T', 'T'} + , {60, 46, 46, 60, 60} + , 0} + , + {{'U', 'Y'} + , {63, 46, 46, 46, 46} + , 0} + , + {{'V', 'N'} + , {46, 46, 46, 60, 60} + , 0} + , + {{'A', 'W'} + , {60, 46, 60, 60, 63} + , 0} + , + {{'L', 'A'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'S', 'A'} + , {40, 46, 46, 60, 60} + , 0} + , + {{'A', 'E'} + , {40, 46, 46, 60, 46} + , 0} + , + {{'U', 'G'} + , {40, 46, 46, 48, 60} + , 0} + , + {{'M', 'M'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'A', 'L'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'D', 'Z'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'A', 'D'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'A', 'T'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'B', 'Y'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'B', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'B', 'A'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'V', 'G'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'B', 'G'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'C', 'V'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'H', 'R'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'C', 'Y'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'C', 'Z'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'D', 'K'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'E', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'E', 'T'} + , {40, 40, 40, 40, 63} + , 0} + , + {{'F', 'I'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'F', 'R'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'G', 'F'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'P', 'F'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'T', 'F'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'G', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'D', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'G', 'H'} + , {40, 34, 48, 60, 63} + , 0} + , + {{'G', 'R'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'G', 'P'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'H', 'U'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'I', 'S'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'I', 'Q'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'I', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'I', 'T'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'K', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'L', 'V'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'L', 'S'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'L', 'I'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'L', 'T'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'L', 'U'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'K'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'T'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'Q'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'R'} + , {40, 46, 46, 46, 63} + , 0} + , + {{'M', 'U'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'Y', 'T'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'D'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'C'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'S'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'N', 'L'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'N', 'O'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'O', 'M'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'P', 'L'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'P', 'T'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'R', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'R', 'O'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'F'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'S', 'M'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'S', 'N'} + , {40, 40, 40, 60, 63} + , 0} + , + {{'R', 'S'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'S', 'K'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'S', 'I'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'Z', 'A'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'E', 'S'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'S', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'C', 'H'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'T', 'R'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'T', 'C'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'G', 'B'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'V', 'A'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'A', 'M'} + , {40, 40, 40, 63, 63} + , 0} + , + {{'I', 'L'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'K', 'W'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'M', 'A'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'N', 'E'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'T', 'N'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'E', 'H'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'N', 'P'} + , {60, 46, 46, 63, 60} + , 0} + , + {{'A', 'F'} + , {40, 46, 63, 63, 63} + , 0} + , + {{'A', 'G'} + , {40, 46, 48, 63, 54} + , 0} + , + {{'B', 'S'} + , {63, 46, 60, 63, 63} + , 0} + , + {{'B', 'H'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'B', 'B'} + , {40, 46, 48, 63, 54} + , 0} + , + {{'B', 'N'} + , {46, 46, 46, 63, 60} + , 0} + , + {{'C', 'L'} + , {40, 44, 44, 63, 44} + , 0} + , + {{'C', 'N'} + , {40, 46, 46, 63, 54} + , 0} + , + {{'E', 'G'} + , {40, 46, 46, 63, 46} + , 0} + , + {{'S', 'V'} + , {60, 34, 48, 63, 60} + , 0} + , + {{'I', 'N'} + , {60, 46, 46, 63, 60} + , 0} + , + {{'M', 'Y'} + , {54, 60, 60, 63, 60} + , 0} + , + {{'M', 'V'} + , {40, 46, 46, 63, 40} + , 0} + , + {{'P', 'A'} + , {60, 34, 48, 63, 60} + , 0} + , + {{'V', 'E'} + , {60, 46, 46, 63, 60} + , 0} + , + {{'Z', 'M'} + , {60, 46, 46, 63, 60} + , 0} + , + {{'J', 'O'} + , {40, 46, 63, 63, 46} + , 0} + , + {{'P', 'G'} + , {40, 46, 63, 63, 60} + , 0} + , + {{'B', 'F'} + , {40, 63, 63, 63, 60} + , 0} + , + {{'G', 'Y'} + , {60, 63, 63, 63, 60} + , 0} + , + {{'H', 'T'} + , {40, 63, 63, 63, 60} + , 0} + , + {{'H', 'N'} + , {60, 63, 63, 63, 60} + , 0} + , + {{'J', 'M'} + , {54, 63, 63, 63, 57} + , 0} + , + {{'M', 'O'} + , {40, 63, 63, 63, 40} + , 0} + , + {{'M', 'W'} + , {60, 63, 63, 63, 60} + , 0} + , + {{'P', 'K'} + , {40, 63, 63, 63, 40} + , 0} + , + {{'Q', 'A'} + , {40, 63, 63, 63, 40} + , 0} + , + {{'R', 'W'} + , {40, 63, 63, 63, 60} + , 0} + , + {{'K', 'N'} + , {40, 63, 63, 63, 60} + , 0} + , + {{'T', 'Z'} + , {40, 63, 63, 63, 40} + , 0} + , + {{'I', 'D'} + , {46, 63, 63, 63, 60} + , 0} + , + {{'N', 'G'} + , {40, 63, 46, 63, 60} + , 0} + , + {{'B', 'D'} + , {40, 46, 46, 60, 28} + , 0} + , + {{'B', 'R'} + , {52, 46, 46, 60, 60} + , 0} + , + {{'D', 'M'} + , {60, 34, 46, 48, 60} + , 0} + , + {{'D', 'O'} + , {63, 46, 46, 60, 63} + , 0} + , + {{'F', 'K'} + , {40, 46, 46, 60, 28} + , 0} + , + {{'K', 'Z'} + , {40, 34, 48, 60, 60} + , 0} + , + {{'M', 'X'} + , {60, 34, 48, 60, 63} + , 0} + , + {{'M', 'Z'} + , {40, 34, 46, 48, 60} + , 0} + , + {{'N', 'A'} + , {40, 34, 46, 48, 60} + , 0} + , + {{'R', 'U'} + , {40, 34, 48, 60, 60} + , 0} + , + {{'L', 'C'} + , {40, 34, 48, 48, 60} + , 0} + , + {{'V', 'C'} + , {40, 34, 46, 48, 60} + , 0} + , + {{'U', 'A'} + , {40, 46, 46, 46, 48} + , 0} + , + {{'U', 'Z'} + , {40, 48, 48, 48, 60} + , 0} + , + {{'Z', 'W'} + , {40, 34, 46, 48, 60} + , 0} + , + {{'M', 'P'} + , {60, 34, 46, 48, 60} + , 0} + , + {{'T', 'W'} + , {60, 63, 34, 48, 60} + , 0} + , + {{'C', 'K'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'C', 'U'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'T', 'L'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'F', 'O'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'G', 'I'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'G', 'G'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'I', 'R'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'I', 'M'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'J', 'E'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'K', 'P'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'M', 'H'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'N', 'U'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'N', 'F'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'P', 'S'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'P', 'N'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'P', 'M'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'S', 'S'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'S', 'D'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'S', 'Y'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'J', 'P'} + , {46, 46, 46, 60, 63} + , 0} + , + {{'K', 'R'} + , {46, 34, 46, 46, 46} + , PWR_LIMIT_UNII1_IN_MW_MHZ} + , + +/*Default*/ + {{0, 0} + , {63, 63, 63, 63, 63} + , 0} +}; + +COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION g_rRlmPowerLimitConfiguration[] = { + + {{'A', 'I'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'A', 'Z'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'B', 'W'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'G', 'D'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'L', 'B'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'L', 'R'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'W', 'S'} + , 165, {40, 40, 40, 40, 40} + } + , + {{'V', 'N'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'U', 'S'} + , 1, {38, 30, 60, 60, 60} + } + , + {{'U', 'S'} + , 3, {60, 60, 26, 60, 60} + } + , + {{'U', 'S'} + , 9, {60, 60, 26, 60, 60} + } + , + {{'U', 'S'} + , 11, {38, 30, 60, 60, 60} + } + , + {{'U', 'S'} + , 36, {34, 34, 34, 34, 34} + } + , + {{'U', 'S'} + , 38, {34, 34, 34, 34, 34} + } + , + {{'U', 'S'} + , 42, {34, 34, 34, 31, 34} + } + , + {{'U', 'S'} + , 58, {48, 48, 48, 31, 48} + } + , + {{'U', 'S'} + , 62, {48, 48, 34, 48, 48} + } + , + {{'U', 'S'} + , 64, {37, 37, 48, 48, 48} + } + , + {{'U', 'S'} + , 100, {37, 37, 48, 48, 48} + } + , + {{'U', 'S'} + , 102, {48, 48, 34, 48, 48} + } + , + {{'U', 'S'} + , 106, {48, 48, 48, 31, 48} + } + , + {{'U', 'S'} + , 155, {60, 60, 60, 31, 60} + } + , + {{'U', 'S'} + , 159, {60, 60, 34, 60, 60} + } + , + {{'U', 'S'} + , 165, {37, 37, 60, 60, 60} + } + , + +/*Default*/ + {{0, 0} + , 165, {63, 63, 63, 63, 63} + } +}; + +#if 0 +COUNTRY_CHANNEL_POWER_LIMIT g_rRlmCountryPowerLimitTable[] = { + { + {'A', 'O'} + , 0, 0, {0, 0, 0, 0} + , + { + CHANNEL_PWR_LIMIT(1, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(2, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(3, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(4, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(5, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(6, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(7, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(8, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(9, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(10, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(11, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(12, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(13, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(14, 40, 40, 40, 40, 40, 0), + + CHANNEL_PWR_LIMIT(36, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(38, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(40, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(42, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(44, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(46, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(48, 63, 63, 63, 63, 63, 0), + + CHANNEL_PWR_LIMIT(52, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(54, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(56, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(58, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(60, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(62, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(64, 63, 63, 63, 63, 63, 0), + + CHANNEL_PWR_LIMIT(100, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(102, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(104, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(106, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(108, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(110, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(112, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(114, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(116, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(118, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(120, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(122, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(124, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(126, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(128, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(130, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(132, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(134, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(136, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(138, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(140, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(142, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(144, 63, 63, 63, 63, 63, 0), + + CHANNEL_PWR_LIMIT(149, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(151, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(153, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(155, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(157, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(159, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(161, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(163, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(165, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(167, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(169, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(171, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(173, 63, 63, 63, 63, 63, 0) + } + } + , + { + /*Used to check the end of country entry */ + {0, 0} + , 0, 0, {0, 0, 0, 0} + , + { + /*Used to check the end of channel power limit */ + CHANNEL_PWR_LIMIT(ENDCH, 0, 0, 0, 0, 0, 0) + } + } /*end of CountryTable */ +}; +#endif +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#endif /* _RLM_TXPWR_INIT_H */ + + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/roaming_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/roaming_fsm.h new file mode 100644 index 0000000000000..aa740ff36172e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/roaming_fsm.h @@ -0,0 +1,138 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _ROAMING_FSM_H +#define _ROAMING_FSM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* Roaming Discovery interval, SCAN result need to be updated */ +#define ROAMING_DISCOVERY_TIMEOUT_SEC 5 /* Seconds. */ + +/* #define ROAMING_NO_SWING_RCPI_STEP 5 //rcpi */ +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_ROAMING_FAIL_REASON_T { + ROAMING_FAIL_REASON_CONNLIMIT = 0, + ROAMING_FAIL_REASON_NOCANDIDATE, + ROAMING_FAIL_REASON_NUM +} ENUM_ROAMING_FAIL_REASON_T; + +/* events of roaming between driver and firmware */ +typedef enum _ENUM_ROAMING_EVENT_T { + ROAMING_EVENT_START = 0, + ROAMING_EVENT_DISCOVERY, + ROAMING_EVENT_ROAM, + ROAMING_EVENT_FAIL, + ROAMING_EVENT_ABORT, + ROAMING_EVENT_NUM +} ENUM_ROAMING_EVENT_T; + +#define ROAMING_EVENT_REASON_TX_ERR BIT(0) +#define ROAMING_EVENT_REASON_RCPI BIT(1) + +typedef struct _ROAMING_PARAM_T { + UINT_16 u2Event; + UINT_16 u2Data; + UINT_16 u2Reason; +} ROAMING_PARAM_T, *P_ROAMING_PARAM_T; + + /**/ typedef enum _ENUM_ROAMING_STATE_T { + ROAMING_STATE_IDLE = 0, + ROAMING_STATE_DECISION, + ROAMING_STATE_DISCOVERY, + ROAMING_STATE_ROAM, + ROAMING_STATE_NUM +} ENUM_ROAMING_STATE_T; + +typedef struct _ROAMING_INFO_T { + BOOLEAN fgIsEnableRoaming; + + ENUM_ROAMING_STATE_T eCurrentState; + + OS_SYSTIME rRoamingDiscoveryUpdateTime; + +#define ROAMING_ENTRY_TIMEOUT_SKIP_COUNT_MAX 2 + UINT_32 RoamingEntryTimeoutSkipCount; + + UINT_32 DrvRoamingAllow; +} ROAMING_INFO_T, *P_ROAMING_INFO_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#if CFG_SUPPORT_ROAMING +#define IS_ROAMING_ACTIVE(prAdapter) \ + (prAdapter->rWifiVar.rRoamingInfo.eCurrentState == ROAMING_STATE_ROAM) +#else +#define IS_ROAMING_ACTIVE(prAdapter) FALSE +#endif /* CFG_SUPPORT_ROAMING */ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID roamingFsmInit(IN P_ADAPTER_T prAdapter); + +VOID roamingFsmUninit(IN P_ADAPTER_T prAdapter); + +VOID roamingFsmSendCmd(IN P_ADAPTER_T prAdapter, IN P_ROAMING_PARAM_T prParam); + +VOID roamingFsmScanResultsUpdate(IN P_ADAPTER_T prAdapter); + +VOID roamingFsmSteps(IN P_ADAPTER_T prAdapter, IN ENUM_ROAMING_STATE_T eNextState); + +VOID roamingFsmRunEventStart(IN P_ADAPTER_T prAdapter); + +VOID roamingFsmRunEventDiscovery(IN P_ADAPTER_T prAdapter, IN P_ROAMING_PARAM_T prParam); + +VOID roamingFsmRunEventRoam(IN P_ADAPTER_T prAdapter); + +VOID roamingFsmRunEventFail(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Reason); + +VOID roamingFsmRunEventAbort(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS roamingFsmProcessEvent(IN P_ADAPTER_T prAdapter, IN P_ROAMING_PARAM_T prParam); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _ROAMING_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rsn.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rsn.h new file mode 100644 index 0000000000000..d0cefb9c802a4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/rsn.h @@ -0,0 +1,244 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _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 RSN_CIPHER_SUITE_GROUP_NOT_USED 0x07AC0F00 +#define RSN_CIPHER_SUITE_SAE 0x08AC0F00 +#define RSN_CIPHER_SUITE_OWE 0x12AC0F00 + +#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 +#define RSN_AKM_SUITE_FT_802_1X 0x03AC0F00 +#define RSN_AKM_SUITE_FT_PSK 0x04AC0F00 +#if KERNEL_VERSION(4, 12, 0) > CFG80211_VERSION_CODE +#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03 +#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04 +#endif +/* Add AKM SUITE for OWE since kernel haven't defined it. */ +#define WLAN_AKM_SUITE_OWE 0x000FAC12 +#if CFG_SUPPORT_802_11W +#define RSN_AKM_SUITE_802_1X_SHA256 0x05AC0F00 +#define RSN_AKM_SUITE_PSK_SHA256 0x06AC0F00 +#endif +#define RSN_AKM_SUITE_SAE 0x08AC0F00 +#define RSN_AKM_SUITE_8021X_SUITE_B 0x0BAC0F00 +#define RSN_AKM_SUITE_8021X_SUITE_B_192 0x0CAC0F00 +#define RSN_AKM_SUITE_OWE 0x12AC0F00 + +#define WPA_AKM_SUITE_NONE 0x00F25000 +#define WPA_AKM_SUITE_802_1X 0x01F25000 +#define WPA_AKM_SUITE_PSK 0x02F25000 + +#define WFA_AKM_SUITE_OSEN 0x019A6F50 +/* this define should be in ieee80211.h, but kernel didn't update it. so we define here temporary */ +#define WLAN_AKM_SUITE_OSEN 0x506f9a01 +#define WLAN_CIPHER_SUITE_NO_GROUP_ADDR 0x000fac07 + +#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 */ +#if (CFG_REFACTORY_PMKSA == 0) +#define WAIT_TIME_IND_PMKID_CANDICATE_SEC 6 /* seconds */ +#endif +#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(6) + +/******************************************************************************* +* P U B 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) + +#define ELEM_MAX_LEN_TIMEOUT_IE (5) + +/******************************************************************************* +* 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, + P_STA_RECORD_T prStaRec, PUINT_16 pu2StatusCode); +#endif + +VOID rsnTkipHandleMICFailure(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta, IN BOOLEAN fgErrorKeyType); + +#if (CFG_REFACTORY_PMKSA == 0) +VOID rsnSelectPmkidCandidateList(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); + +VOID rsnUpdatePmkidCandidateList(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); + +BOOLEAN rsnSearchPmkidEntry(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBssid, OUT PUINT_32 pu4EntryIndex); + +BOOLEAN rsnCheckPmkidCandicate(IN P_ADAPTER_T prAdapter); + +VOID rsnCheckPmkidCache(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBss); + +VOID rsnGeneratePmkidIndication(IN P_ADAPTER_T prAdapter); + +VOID rsnIndicatePmkidCand(IN P_ADAPTER_T prAdapter, IN ULONG ulParm); +#else +P_PMKID_ENTRY_T rsnSearchPmkidEntry(IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBssid); + +void rsnCheckPmkidCache(IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBss); + +void rsnGeneratePmkidIndication(IN P_ADAPTER_T prAdapter, + IN P_PARAM_PMKID_CANDIDATE_T prCandi); + +WLAN_STATUS rsnSetPmkid(IN P_ADAPTER_T prAdapter, + IN P_PARAM_PMKID_T prPmkid); + +WLAN_STATUS rsnDelPmkid(IN P_ADAPTER_T prAdapter, + IN P_PARAM_PMKID_T prPmkid); + +WLAN_STATUS rsnFlushPmkid(IN P_ADAPTER_T prAdapter); +#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); + +UINT_16 rsnPmfCapableValidation(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, IN P_STA_RECORD_T prStaRec); + +VOID rsnPmfGenerateTimeoutIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + +void rsnApStartSaQuery(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +void rsnApSaQueryAction(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); +#endif /* CFG_SUPPORT_802_11W */ + +BOOLEAN rsnCheckSecurityModeChanged(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_BSS_DESC_T prBssDesc); +BOOLEAN rsnParseOsenIE(P_ADAPTER_T prAdapter, struct IE_WFA_OSEN *prInfoElem, P_RSN_INFO_T prOsenInfo); + +UINT_32 +rsnCalculateFTIELen(P_ADAPTER_T prAdapter, ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, P_STA_RECORD_T prStaRec); + +VOID rsnGenerateFTIE(IN P_ADAPTER_T prAdapter, IN OUT P_MSDU_INFO_T prMsduInfo); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _RSN_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/scan.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/scan.h new file mode 100644 index 0000000000000..7baf90758d3be --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/scan.h @@ -0,0 +1,839 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _SCAN_H +#define _SCAN_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "gl_vendor.h" + +/* TDLS test purpose */ +extern BOOLEAN flgTdlsTestExtCapElm; +extern UINT8 aucTdlsTestExtCapElm[]; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/*! Maximum buffer size of SCAN list */ +#define SCN_MAX_BUFFER_SIZE (CFG_MAX_NUM_BSS_LIST * ALIGN_4(sizeof(BSS_DESC_T))) +#define SCN_ROAM_MAX_BUFFER_SIZE (CFG_MAX_NUM_ROAM_BSS_LIST * ALIGN_4(sizeof(ROAM_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 20 /* This is used by POLICY SMART WEAKEST, + * If exceed this value, remove weakest BSS_DESC_T + * with same SSID first in large network. + */ + +/* the scan time in WFD mode + 2.4G/5G is about 9s so we need to enlarge the value */ +#define SCN_BSS_DESC_REMOVE_TIMEOUT_SEC 15 /* Second. */ + /* This is used by POLICY TIMEOUT, + * If exceed this value, remove timeout BSS_DESC_T. + */ + +#define SCN_PROBE_DELAY_MSEC 0 + +#define SCN_ADHOC_BSS_DESC_TIMEOUT_SEC 15 /* Second. */ + +#define SCN_NLO_NETWORK_CHANNEL_NUM (4) + +#define REMOVE_TIMEOUT_TWO_DAY (60*60*24*2) + +/*----------------------------------------------------------------------------*/ +/* 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) /* two probe req will be sent, wildcard and specified */ +#define SCAN_REQ_SSID_SPECIFIED_ONLY BIT(3) /* only a specified ssid probe request will be sent */ +/*----------------------------------------------------------------------------*/ +/* Support Multiple SSID SCAN */ +/*----------------------------------------------------------------------------*/ +#define SCN_SSID_MAX_NUM CFG_SCAN_SSID_MAX_NUM +#define SCN_SSID_MATCH_MAX_NUM CFG_SCAN_SSID_MATCH_MAX_NUM + +#define SWC_NUM_BSSID_THRESHOLD_DEFAULT 8 +#define SWC_RSSI_WINDSIZE_DEFAULT 8 +#define LOST_AP_WINDOW 16 +#define MAX_CHANNEL_NUM_PER_BUCKETS 8 + +#define SCN_BSS_JOIN_FAIL_THRESOLD 4 +#define SCN_BSS_JOIN_FAIL_CNT_RESET_SEC 15 +#define SCN_BSS_JOIN_FAIL_RESET_STEP 2 + +#if CFG_SUPPORT_BATCH_SCAN +/*----------------------------------------------------------------------------*/ +/* SCAN_BATCH_REQ */ +/*----------------------------------------------------------------------------*/ +#define SCAN_BATCH_REQ_START BIT(0) +#define SCAN_BATCH_REQ_STOP BIT(1) +#define SCAN_BATCH_REQ_RESULT BIT(2) +#endif + +#define SCAN_NLO_DEFAULT_INTERVAL 30000 +/* PNO min period 30s, max period 300s */ +#define SCAN_NLO_MIN_INTERVAL 30 +#define SCAN_NLO_MAX_INTERVAL 300 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_SCAN_TYPE_T { + SCAN_TYPE_PASSIVE_SCAN = 0, + SCAN_TYPE_ACTIVE_SCAN, + SCAN_TYPE_NUM +} ENUM_SCAN_TYPE_T, *P_ENUM_SCAN_TYPE_T; + +typedef enum _ENUM_SCAN_STATE_T { + SCAN_STATE_IDLE = 0, + SCAN_STATE_SCANNING, + SCAN_STATE_NUM +} ENUM_SCAN_STATE_T; + +typedef enum _ENUM_SCAN_CHANNEL_T { + SCAN_CHANNEL_FULL = 0, + SCAN_CHANNEL_2G4, + SCAN_CHANNEL_5G, + SCAN_CHANNEL_P2P_SOCIAL, + SCAN_CHANNEL_SPECIFIED, + SCAN_CHANNEL_NUM +} ENUM_SCAN_CHANNEL, *P_ENUM_SCAN_CHANNEL; + +typedef struct _MSG_SCN_FSM_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_32 u4Dummy; +} MSG_SCN_FSM_T, *P_MSG_SCN_FSM_T; + +typedef enum _ENUM_POSTPONE_SCHED_SCAN_REQUEST_T { + SCHED_SCAN_POSTPONE_START = 0, + SCHED_SCAN_POSTPONE_STOP, + SCHED_SCAN_POSTPONE_NUM +} ENUM_POSTPONE_SCHED_SCAN_REQUEST_T; + + +typedef enum _ENUM_PSCAN_STATE_T { + PSCN_IDLE = 0, + PSCN_RESET, + PSCN_SCANNING, + PSCAN_STATE_T_NUM +} ENUM_PSCAN_STATE_T; + +/*----------------------------------------------------------------------------*/ +/* BSS Descriptors */ +/*----------------------------------------------------------------------------*/ +struct _BSS_DESC_T { + LINK_ENTRY_T rLinkEntry; + LINK_ENTRY_T rLinkEntryEss; + + 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 fgIsValidSSID; /* This flag is TRUE if the SSID is not hidden */ + BOOLEAN fgIsHiddenSSID; /* When this flag is TRUE, means the SSID + * of this BSS is not known yet. + */ + UINT_8 ucSSIDLen; + UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; + + OS_SYSTIME rUpdateTime; + + ENUM_BSS_TYPE_T eBSSType; + + UINT_16 u2CapInfo; + + UINT_16 u2BeaconInterval; + UINT_16 u2ATIMWindow; + + UINT_16 u2OperationalRateSet; + UINT_16 u2BSSBasicRateSet; + BOOLEAN fgIsUnknownBssBasicRate; + + BOOLEAN fgIsERPPresent; + BOOLEAN fgIsHTPresent; + + UINT_8 ucPhyTypeSet; /* Available PHY Type Set of this BSS */ + + UINT_8 ucChannelNum; + + ENUM_CHNL_EXT_T eSco; /* + * Record bandwidth for association process + * Some AP will send association resp by 40MHz BW + */ + ENUM_BAND_T eBand; + + UINT_8 ucDTIMPeriod; + + BOOLEAN fgIsLargerTSF; /* This BSS's TimeStamp is larger than us(TCL == 1 in RX_STATUS_T) */ + + UINT_8 ucRCPI; + + UINT_8 ucWmmFlag; /* A flag to indicate this BSS's WMM capability */ + + /* + * \brief The srbiter Search State will matched the scan result, + * and saved the selected cipher and akm, and report the score, + * for arbiter join state, join module will carry this target BSS + * to rsn generate ie function, for gen wpa/rsn ie + */ + UINT_32 u4RsnSelectedGroupCipher; + UINT_32 u4RsnSelectedPairwiseCipher; + UINT_32 u4RsnSelectedAKMSuite; + + UINT_16 u2RsnCap; + + RSN_INFO_T rRSNInfo; + RSN_INFO_T rWPAInfo; +#if 1 /* CFG_SUPPORT_WAPI */ + WAPI_INFO_T rIEWAPI; + BOOLEAN fgIEWAPI; +#endif + BOOLEAN fgIERSN; + BOOLEAN fgIEWPA; + BOOLEAN fgIEOsen; + +#if CFG_SUPPORT_DETECT_ATHEROS_AP + BOOLEAN fgIsAtherosAP; +#endif + + /*! \brief RSN parameters selected for connection */ + /* + * ! \brief The Select score for final AP selection, + * 0, no sec, 1,2,3 group cipher is WEP, TKIP, CCMP + */ + UINT_8 ucEncLevel; + +#if CFG_ENABLE_WIFI_DIRECT + BOOLEAN fgIsP2PPresent; + BOOLEAN fgIsP2PReport; /* TRUE: report to upper layer */ + P_P2P_DEVICE_DESC_T prP2pDesc; + + UINT_8 aucIntendIfAddr[MAC_ADDR_LEN]; /* For IBSS, the SrcAddr is different from BSSID */ + /* UINT_8 ucDevCapabilityBitmap; */ /* Device Capability Attribute. (P2P_DEV_CAPABILITY_XXXX) */ + /* UINT_8 ucGroupCapabilityBitmap; */ /* Group Capability Attribute. (P2P_GROUP_CAPABILITY_XXXX) */ + + LINK_T rP2pDeviceList; + + /* P_LINK_T prP2pDeviceList; */ + + /* For + * 1. P2P Capability. + * 2. P2P Device ID. ( in aucSrcAddr[] ) + * 3. NOA (TODO:) + * 4. Extend Listen Timing. (Probe Rsp) (TODO:) + * 5. P2P Device Info. (Probe Rsp) + * 6. P2P Group Info. (Probe Rsp) + */ +#endif + + BOOLEAN fgIsIEOverflow; /* The received IE length exceed the maximum IE buffer size */ + UINT_16 u2RawLength; /* The byte count of aucRawBuf[] */ + UINT_16 u2IELength; /* The byte count of aucIEBuf[] */ + + ULARGE_INTEGER u8TimeStamp; /* Place u8TimeStamp before aucIEBuf[1] to force DW align */ + UINT_8 aucRawBuf[CFG_RAW_BUFFER_SIZE]; + UINT_8 aucIEBuf[CFG_IE_BUFFER_SIZE]; + UINT_8 ucJoinFailureCount; + OS_SYSTIME rJoinFailTime; + struct AIS_BLACKLIST_ITEM *prBlack; + UINT_16 u2StaCnt; + UINT_16 u2AvaliableAC; /* Available Admission Capacity */ + UINT_8 ucChnlUtilization; + UINT_8 ucSNR; + BOOLEAN fgSeenProbeResp; + BOOLEAN fgExsitBssLoadIE; + BOOLEAN fgMultiAnttenaAndSTBC; + BOOLEAN fgDeauthLastTime; + UINT_32 u4UpdateIdx; +#if CFG_SUPPORT_ROAMING_RETRY + BOOLEAN fgIsRoamFail; +#endif + INT_8 cPowerLimit; +#if CFG_SUPPORT_RSN_SCORE + BOOLEAN fgIsRSNSuitableBss; +#endif +}; + +struct _ROAM_BSS_DESC_T { + LINK_ENTRY_T rLinkEntry; + UINT_8 ucSSIDLen; + UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; + OS_SYSTIME rUpdateTime; +}; + +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 */ + UINT_16 u2ChannelDwellTime; + UINT_16 u2MinChannelDwellTime; + UINT_8 aucBSSID[MAC_ADDR_LEN]; + 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]; + UINT_8 aucRandomMac[MAC_ADDR_LEN]; +} SCAN_PARAM_T, *P_SCAN_PARAM_T; + +typedef struct _NLO_PARAM_T { /* Used by SCAN FSM */ + SCAN_PARAM_T rScanParam; + + /* NLO */ + BOOLEAN fgStopAfterIndication; + UINT_8 ucFastScanIteration; + UINT_16 u2FastScanPeriod; + UINT_16 u2SlowScanPeriod; + + /* Match SSID */ + UINT_8 ucMatchSSIDNum; + UINT_8 ucMatchSSIDLen[SCN_SSID_MATCH_MAX_NUM]; + UINT_8 aucMatchSSID[SCN_SSID_MATCH_MAX_NUM][ELEM_MAX_LEN_SSID]; + +#if CFG_SUPPORT_SCHED_SCN_SSID_SETS + /* SSID set*/ + UINT_8 ucSSIDNum; + UINT_8 ucSSIDLen[CFG_SCAN_HIDDEN_SSID_MAX_NUM]; + UINT_8 aucSSID[CFG_SCAN_HIDDEN_SSID_MAX_NUM][ELEM_MAX_LEN_SSID]; +#endif + + UINT_8 aucCipherAlgo[SCN_SSID_MATCH_MAX_NUM]; + UINT_16 au2AuthAlgo[SCN_SSID_MATCH_MAX_NUM]; + UINT_8 aucChannelHint[SCN_SSID_MATCH_MAX_NUM][SCN_NLO_NETWORK_CHANNEL_NUM]; + P_BSS_DESC_T aprPendingBssDescToInd[SCN_SSID_MATCH_MAX_NUM]; +} NLO_PARAM_T, *P_NLO_PARAM_T; + +#if 1 + +typedef struct _GSCN_CHANNEL_INFO_T { + UINT_8 ucBand; + UINT_8 ucChannelNumber; /* Channel Number */ + UINT_8 ucPassive; /* 0 => active, 1 => passive scan; ignored for DFS */ + UINT_8 aucReserved[1]; + + UINT_32 u4DwellTimeMs; /* dwell time hint */ + /* Add channel class */ +} GSCN_CHANNEL_INFO_T, *P_GSCN_CHANNEL_INFO_T; + +typedef struct _GSCAN_BUCKET_T { + UINT_16 u2BucketIndex; /* bucket index, 0 based */ + UINT_8 ucBucketFreqMultiple; /* + * desired period, in millisecond; + * if this is too low, the firmware should choose to generate + * results as fast as it can instead of failing the command + */ + UINT_8 ucReportFlag; + UINT_8 ucMaxBucketFreqMultiple; /* max_period / base_period */ + UINT_8 ucStepCount; + UINT_8 ucNumChannels; + UINT_8 aucReserved[1]; + WIFI_BAND eBand; /* when UNSPECIFIED, use channel list */ + GSCN_CHANNEL_INFO_T arChannelList[GSCAN_MAX_CHANNELS]; /* channels to scan; these may include DFS channels */ +} GSCAN_BUCKET_T, *P_GSCAN_BUCKET_T; + +typedef struct _CMD_GSCN_REQ_T { + UINT_8 ucFlags; + UINT_8 ucNumScnToCache; + UINT_8 aucReserved[2]; + UINT_32 u4BufferThreshold; + UINT_32 u4BasePeriod; /* base timer period in ms */ + UINT_32 u4NumBuckets; + UINT_32 u4MaxApPerScan; /* number of APs to store in each scan in the */ + /* BSSID/RSSI history buffer (keep the highest RSSI APs) */ + + GSCAN_BUCKET_T arBucket[GSCAN_MAX_BUCKETS]; +} CMD_GSCN_REQ_T, *P_CMD_GSCN_REQ_T; + +#endif + +typedef struct _CMD_GSCN_SCN_COFIG_T { + UINT_8 ucNumApPerScn; /* GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN */ + UINT_32 u4BufferThreshold; /* GSCAN_ATTRIBUTE_REPORT_THRESHOLD */ + UINT_32 u4NumScnToCache; /* GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE */ +} CMD_GSCN_SCN_COFIG_T, *P_CMD_GSCN_SCN_COFIG_T; + +typedef struct _CMD_GET_GSCAN_RESULT { + UINT_8 ucVersion; + UINT_8 aucReserved[2]; + UINT_8 ucFlush; + UINT_32 u4Num; +} CMD_GET_GSCAN_RESULT_T, *P_CMD_GET_GSCAN_RESULT_T; + +typedef struct _CMD_BATCH_REQ_T { + UINT_8 ucSeqNum; + UINT_8 ucNetTypeIndex; + UINT_8 ucCmd; /* Start/ Stop */ + UINT_8 ucMScan; /* an integer number of scans per batch */ + UINT_8 ucBestn; /* an integer number of the max AP to remember per scan */ + UINT_8 ucRtt; /* + * an integer number of highest-strength AP for which we'd like + * approximate distance reported + */ + UINT_8 ucChannel; /* channels */ + UINT_8 ucChannelType; + UINT_8 ucChannelListNum; + UINT_8 aucReserved[3]; + UINT_32 u4Scanfreq; /* an integer number of seconds between scans */ + CHANNEL_INFO_T arChannelList[32]; /* channels */ +} CMD_BATCH_REQ_T, *P_CMD_BATCH_REQ_T; + +typedef struct _CMD_SET_PSCAN_PARAM { + UINT_8 ucVersion; + CMD_NLO_REQ rCmdNloReq; + CMD_BATCH_REQ_T rCmdBatchReq; + CMD_GSCN_REQ_T rCmdGscnReq; + BOOLEAN fgNLOScnEnable; + BOOLEAN fgBatchScnEnable; + BOOLEAN fgGScnEnable; + UINT_32 u4BasePeriod; /* GSCAN_ATTRIBUTE_BASE_PERIOD */ +} CMD_SET_PSCAN_PARAM, *P_CMD_SET_PSCAN_PARAM; + +typedef struct _SCAN_INFO_T { + ENUM_SCAN_STATE_T eCurrentState; /* Store the STATE variable of SCAN FSM */ + + OS_SYSTIME rLastScanCompletedTime; + + SCAN_PARAM_T rScanParam; + NLO_PARAM_T rNloParam; + + UINT_32 u4NumOfBssDesc; + + UINT_8 aucScanBuffer[SCN_MAX_BUFFER_SIZE]; + + LINK_T rBSSDescList; + + LINK_T rFreeBSSDescList; + + LINK_T rPendingMsgList; + + UINT_8 aucScanRoamBuffer[SCN_ROAM_MAX_BUFFER_SIZE]; + LINK_T rRoamFreeBSSDescList; + LINK_T rRoamBSSDescList; + + /* Sparse Channel Detection */ + BOOLEAN fgIsSparseChannelValid; + RF_CHANNEL_INFO_T rSparseChannel; + + /* NLO scanning state tracking */ + BOOLEAN fgNloScanning; +#if CFG_SUPPORT_SCN_PSCN + BOOLEAN fgPscnOngoing; + BOOLEAN fgGScnConfigSet; + BOOLEAN fgGScnParamSet; + BOOLEAN fgGScnAction; + P_CMD_SET_PSCAN_PARAM prPscnParam; + BOOLEAN fgIsPostponeSchedScan; + ENUM_POSTPONE_SCHED_SCAN_REQUEST_T eCurrendSchedScanReq; + PARAM_SCHED_SCAN_REQUEST rSchedScanRequest; + ENUM_PSCAN_STATE_T eCurrentPSCNState; +#endif +#if CFG_SUPPORT_GSCN + P_PARAM_WIFI_GSCAN_FULL_RESULT prGscnFullResult; +#endif + + UINT_32 u4ScanUpdateIdx; +} SCAN_INFO_T, *P_SCAN_INFO_T; + +/* use to save partial scan channel information */ +typedef struct _PARTIAL_SCAN_INFO_T { + UINT_8 ucChannelListNum; + RF_CHANNEL_INFO_T arChnlInfoList[MAXIMUM_OPERATION_CHANNEL_LIST]; +} PARTIAL_SCAN_INFO, *P_PARTIAL_SCAN_INFO; + +/* 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]; + UINT_16 u2ChannelDwellTime; /* In TU. 1024us. */ + + UINT_16 u2TimeoutValue; /* ms unit */ /* MULTI SSID */ + UINT_16 u2MinChannelDwellTime; /* In TU. 1024us. */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; + + 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. */ +#if CFG_MULTI_SSID_SCAN + UINT_16 u2TimeoutValue; /* ms unit */ +#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]; + UINT_8 aucRandomMac[MAC_ADDR_LEN]; +} MSG_SCN_SCAN_REQ_V2, *P_MSG_SCN_SCAN_REQ_V2; + +typedef struct _MSG_SCN_SCAN_CANCEL_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + UINT_8 ucNetTypeIndex; +#if CFG_ENABLE_WIFI_DIRECT + BOOLEAN fgIsChannelExt; +#endif +} MSG_SCN_SCAN_CANCEL, *P_MSG_SCN_SCAN_CANCEL; + +/* Outgoing Mailbox Messages */ +typedef enum _ENUM_SCAN_STATUS_T { + SCAN_STATUS_DONE = 0, + SCAN_STATUS_CANCELLED, + SCAN_STATUS_FAIL, + SCAN_STATUS_BUSY, + SCAN_STATUS_NUM +} ENUM_SCAN_STATUS, *P_ENUM_SCAN_STATUS; + +typedef struct _MSG_SCN_SCAN_DONE_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + UINT_8 ucNetTypeIndex; + ENUM_SCAN_STATUS eScanStatus; +} MSG_SCN_SCAN_DONE, *P_MSG_SCN_SCAN_DONE; + +#if CFG_SUPPORT_AGPS_ASSIST +typedef enum { + AGPS_PHY_A, + AGPS_PHY_B, + AGPS_PHY_G, +} AP_PHY_TYPE; + +typedef struct _AGPS_AP_INFO_T { + UINT_8 aucBSSID[6]; + INT_16 i2ApRssi; /* -127..128 */ + UINT_16 u2Channel; /* 0..256 */ + AP_PHY_TYPE ePhyType; +} AGPS_AP_INFO_T, *P_AGPS_AP_INFO_T; + +typedef struct _AGPS_AP_LIST_T { + UINT_8 ucNum; + AGPS_AP_INFO_T arApInfo[32]; +} AGPS_AP_LIST_T, *P_AGPS_AP_LIST_T; +#endif + +typedef struct _CMD_SET_PSCAN_ADD_HOTLIST_BSSID { + UINT_8 aucMacAddr[6]; + UINT_8 ucFlags; + UINT_8 aucReserved[5]; +} CMD_SET_PSCAN_ADD_HOTLIST_BSSID, *P_CMD_SET_PSCAN_ADD_HOTLIST_BSSID; + +typedef struct _CMD_SET_PSCAN_ADD_SWC_BSSID { + INT_32 i4RssiLowThreshold; + INT_32 i4RssiHighThreshold; + UINT_8 aucMacAddr[6]; + UINT_8 aucReserved[6]; +} CMD_SET_PSCAN_ADD_SWC_BSSID, *P_CMD_SET_PSCAN_ADD_SWC_BSSID; + +typedef struct _CMD_SET_PSCAN_MAC_ADDR { + UINT_8 ucVersion; + UINT_8 ucFlags; + UINT_8 aucMacAddr[6]; + UINT_8 aucReserved[8]; +} CMD_SET_PSCAN_MAC_ADDR, *P_CMD_SET_PSCAN_MAC_ADDR; + +struct RM_BEACON_REPORT_PARAMS { + UINT_8 ucChannel; + UINT_8 ucRCPI; + UINT_8 ucRSNI; + UINT_8 ucAntennaID; + UINT_8 ucFrameInfo; + UINT_8 aucBcnFixedField[12]; +}; + +struct RM_MEASURE_REPORT_ENTRY { + LINK_ENTRY_T rLinkEntry; + /* should greater than sizeof(struct RM_BCN_REPORT) + + ** sizeof(IE_MEASUREMENT_REPORT_T) + RM_BCN_REPORT_SUB_ELEM_MAX_LENGTH + */ + UINT_8 aucMeasReport[260]; +}; +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Routines in scan.c */ +/*----------------------------------------------------------------------------*/ +VOID scnInit(IN P_ADAPTER_T prAdapter); + +VOID scnUninit(IN P_ADAPTER_T prAdapter); + +/* BSS-DESC Search */ +P_BSS_DESC_T scanSearchBssDescByBssid(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]); + +P_BSS_DESC_T +scanSearchBssDescByBssidAndSsid(IN P_ADAPTER_T prAdapter, + IN UINT_8 aucBSSID[], IN BOOLEAN fgCheckSsid, IN P_PARAM_SSID_T prSsid); + +P_BSS_DESC_T scanSearchBssDescByTA(IN P_ADAPTER_T prAdapter, IN UINT_8 aucSrcAddr[]); + +P_BSS_DESC_T +scanSearchBssDescByTAAndSsid(IN P_ADAPTER_T prAdapter, + IN UINT_8 aucSrcAddr[], IN BOOLEAN fgCheckSsid, IN P_PARAM_SSID_T prSsid); + +#if CFG_SUPPORT_HOTSPOT_2_0 +P_BSS_DESC_T scanSearchBssDescByBssidAndLatestUpdateTime(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]); +#endif + +/* BSS-DESC Search - Alternative */ +P_BSS_DESC_T +scanSearchExistingBssDesc(IN P_ADAPTER_T prAdapter, + IN ENUM_BSS_TYPE_T eBSSType, IN UINT_8 aucBSSID[], IN UINT_8 aucSrcAddr[]); + +P_BSS_DESC_T +scanSearchExistingBssDescWithSsid(IN P_ADAPTER_T prAdapter, + IN ENUM_BSS_TYPE_T eBSSType, + IN UINT_8 aucBSSID[], + IN UINT_8 aucSrcAddr[], IN BOOLEAN fgCheckSsid, IN P_PARAM_SSID_T prSsid); + +/* BSS-DESC Allocation */ +P_BSS_DESC_T scanAllocateBssDesc(IN P_ADAPTER_T prAdapter); + +/* BSS-DESC Removal */ +VOID scanRemoveBssDescsByPolicy(IN P_ADAPTER_T prAdapter, IN UINT_32 u4RemovePolicy); + +VOID scanRemoveBssDescByBssid(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]); + +VOID +scanRemoveBssDescByBandAndNetwork(IN P_ADAPTER_T prAdapter, + IN ENUM_BAND_T eBand, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); + +/* BSS-DESC State Change */ +VOID scanRemoveConnFlagOfBssDescByBssid(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]); + +#if 0 +/* BSS-DESC Insertion */ +P_BSS_DESC_T scanAddToInternalScanResult(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSWRfb, IN P_BSS_DESC_T prBssDesc); +#endif + +/* BSS-DESC Insertion - ALTERNATIVE */ +P_BSS_DESC_T scanAddToBssDesc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +WLAN_STATUS scanProcessBeaconAndProbeResp(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSWRfb); + +VOID +scanBuildProbeReqFrameCommonIEs(IN P_MSDU_INFO_T prMsduInfo, + IN PUINT_8 pucDesiredSsid, IN UINT_32 u4DesiredSsidLen, IN UINT_16 u2SupportedRateSet); + +WLAN_STATUS scanSendProbeReqFrames(IN P_ADAPTER_T prAdapter, IN P_SCAN_PARAM_T prScanParam); + +VOID scanUpdateBssDescForSearch(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); + +P_BSS_DESC_T scanSearchBssDescByPolicy(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); + +WLAN_STATUS scanAddScanResult(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc, IN P_SW_RFB_T prSwRfb); + +BOOLEAN scanCheckBssIsLegal(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc); + +VOID scanReportBss2Cfg80211(IN P_ADAPTER_T prAdapter, IN ENUM_BSS_TYPE_T eBSSType, IN P_BSS_DESC_T SpecificprBssDesc); + +P_ROAM_BSS_DESC_T scanSearchRoamBssDescBySsid(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); +P_ROAM_BSS_DESC_T scanAllocateRoamBssDesc(IN P_ADAPTER_T prAdapter); +VOID scanAddToRoamBssDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); +VOID scanSearchBssDescOfRoamSsid(IN P_ADAPTER_T prAdapter); +VOID scanRemoveRoamBssDescsByTime(IN P_ADAPTER_T prAdapter, IN UINT_32 u4RemoveTime); +/*----------------------------------------------------------------------------*/ +/* Routines in scan_fsm.c */ +/*----------------------------------------------------------------------------*/ +VOID scnFsmSteps(IN P_ADAPTER_T prAdapter, IN ENUM_SCAN_STATE_T eNextState); + +/*----------------------------------------------------------------------------*/ +/* Command Routines */ +/*----------------------------------------------------------------------------*/ +VOID scnSendScanReqExtCh(IN P_ADAPTER_T prAdapter); + +VOID scnSendScanReq(IN P_ADAPTER_T prAdapter); + +VOID scnSendScanReqV2ExtCh(IN P_ADAPTER_T prAdapter); + +VOID scnSendScanReqV2(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* RX Event Handling */ +/*----------------------------------------------------------------------------*/ +VOID scnEventScanDone(IN P_ADAPTER_T prAdapter, IN P_EVENT_SCAN_DONE prScanDone); + +VOID scnEventNloDone(IN P_ADAPTER_T prAdapter, IN P_EVENT_NLO_DONE_T prNloDone); + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Handling */ +/*----------------------------------------------------------------------------*/ +VOID scnFsmMsgStart(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID scnFsmMsgAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID scnFsmHandleScanMsg(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_SCAN_REQ prScanReqMsg); + +VOID scnFsmHandleScanMsgV2(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_SCAN_REQ_V2 prScanReqMsg); + +VOID scnFsmRemovePendingMsg(IN P_ADAPTER_T prAdapter, IN UINT_8 ucSeqNum, IN UINT_8 ucNetTypeIndex); + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Generation */ +/*----------------------------------------------------------------------------*/ +VOID +scnFsmGenerateScanDoneMsg(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucSeqNum, IN UINT_8 ucNetTypeIndex, IN ENUM_SCAN_STATUS eScanStatus); + +/*----------------------------------------------------------------------------*/ +/* Query for sparse channel */ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnQuerySparseChannel(IN P_ADAPTER_T prAdapter, P_ENUM_BAND_T prSparseBand, PUINT_8 pucSparseChannel); + +/*----------------------------------------------------------------------------*/ +/* OID/IOCTL Handling */ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnFsmSchedScanRequest(IN P_ADAPTER_T prAdapter); + +BOOLEAN scnFsmSchedScanStopRequest(IN P_ADAPTER_T prAdapter); + +#if CFG_SUPPORT_SCN_PSCN +BOOLEAN scnFsmPSCNAction(IN P_ADAPTER_T prAdapter, IN ENUM_PSCAN_ACT_T ucPscanAct); + +BOOLEAN scnFsmPSCNSetParam(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_PARAM prCmdPscnParam); + +BOOLEAN scnFsmGSCNSetHotlist(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_PARAM prCmdPscnParam); + +BOOLEAN scnFsmPSCNAddSWCBssId(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_ADD_SWC_BSSID prCmdPscnAddSWCBssId); + +BOOLEAN scnFsmPSCNSetMacAddr(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_MAC_ADDR prCmdPscnSetMacAddr); + +BOOLEAN scnCombineParamsIntoPSCN(IN P_ADAPTER_T prAdapter, + IN P_CMD_NLO_REQ prCmdNloReq, + IN P_CMD_BATCH_REQ_T prCmdBatchReq, + IN P_CMD_GSCN_REQ_T prCmdGscnReq, + IN P_CMD_GSCN_SCN_COFIG_T prNewCmdGscnConfig, + IN BOOLEAN fgRemoveNLOfromPSCN, + IN BOOLEAN fgRemoveBatchSCNfromPSCN, IN BOOLEAN fgRemoveGSCNfromPSCN); + +VOID scnPSCNFsm(IN P_ADAPTER_T prAdapter, IN ENUM_PSCAN_STATE_T eNextPSCNState); +#endif +#if CFG_NLO_MSP +VOID scnSetMspParameterIntoPSCN(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_PARAM prCmdPscnParam); +#endif +#if CFG_SUPPORT_GSCN +BOOLEAN scnSetGSCNParam(IN P_ADAPTER_T prAdapter, IN P_PARAM_WIFI_GSCAN_CMD_PARAMS prCmdGscnParam); + +BOOLEAN scnSetGSCNConfig(IN P_ADAPTER_T prAdapter, IN P_CMD_GSCN_SCN_COFIG_T prCmdGscnScnConfig); + +BOOLEAN scnFsmGetGSCNResult(IN P_ADAPTER_T prAdapter, + IN P_CMD_GET_GSCAN_RESULT_T prGetGscnResultCmd, OUT PUINT_32 pu4SetInfoLen); + +BOOLEAN scnFsmGSCNResults(IN P_ADAPTER_T prAdapter, IN P_EVENT_GSCAN_RESULT_T prEventBuffer); +#endif + +#if CFG_SUPPORT_AGPS_ASSIST +VOID scanReportScanResultToAgps(P_ADAPTER_T prAdapter); +#endif +P_BSS_DESC_T scanSearchBssDescByScoreForAis(P_ADAPTER_T prAdapter); +VOID scanGetCurrentEssChnlList(P_ADAPTER_T prAdapter); + +VOID scanLogEssResult(P_ADAPTER_T prAdapter); +VOID scanInitEssResult(P_ADAPTER_T prAdapter); + +#endif /* _SCAN_H */ + +VOID scanCollectBeaconReport(IN P_ADAPTER_T prAdapter, PUINT_8 pucIEBuf, + UINT_16 u2Length, PUINT_8 pucBssid, struct RM_BEACON_REPORT_PARAMS *prRepParams); diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/sec_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/sec_fsm.h new file mode 100644 index 0000000000000..83f2f386635cc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/sec_fsm.h @@ -0,0 +1,117 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _SEC_FSM_H +#define _SEC_FSM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/* TKIP CounterMeasure interval for Rejoin to Network. */ +#define COUNTER_MEASURE_TIMEOUT_INTERVAL_SEC 60 + +/* Timeout to wait the EAPoL Error Report frame Send out. */ +#define EAPOL_REPORT_SEND_TIMEOUT_INTERVAL_SEC 1 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef UINT_32 SEC_STATUS, *P_SEC_STATUS; + +#if 0 +/* WPA2 PMKID candicate structure */ +typedef struct _PMKID_CANDICATE_T { + UINT_8 aucBssid[MAC_ADDR_LEN]; /* MAC address */ + UINT_32 u4PreAuthFlags; +} PMKID_CANDICATE_T, *P_PMKID_CANDICATE_T; +#endif + +typedef SEC_STATUS(*PFN_SEC_FSM_STATE_HANDLER) (VOID); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define SEC_STATE_TRANSITION_FLAG fgIsTransition +#define SEC_NEXT_STATE_VAR eNextState + +#define SEC_STATE_TRANSITION(prAdapter, prSta, eFromState, eToState) \ + { secFsmTrans_ ## eFromState ## _to_ ## eToState(prAdapter, prSta); \ + SEC_NEXT_STATE_VAR = SEC_STATE_ ## eToState; \ + SEC_STATE_TRANSITION_FLAG = (BOOLEAN)TRUE; \ + } + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/*--------------------------------------------------------------*/ +/* Routines to handle the sec check */ +/*--------------------------------------------------------------*/ +/***** Routines in sec_fsm.c *****/ +VOID secFsmInit(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +VOID secFsmEventInit(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +VOID secFsmEventStart(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +VOID secFsmEventAbort(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +BOOLEAN secFsmEventPTKInstalled(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +VOID secFsmEvent2ndEapolTx(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +VOID secFsmEvent4ndEapolTxDone(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +VOID +secFsmEventEapolTxDone(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +VOID secFsmEventEapolTxTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParm); + +VOID +secFsmEventDeauthTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +VOID secFsmEventStartCounterMeasure(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +VOID secFsmEventEndOfCounterMeasure(IN P_ADAPTER_T prAdapter, IN ULONG ulParm); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _SEC_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/stats.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/stats.h new file mode 100644 index 0000000000000..2d990531b0484 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/stats.h @@ -0,0 +1,372 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ +extern UINT_64 u8DrvOwnStart, u8DrvOwnEnd; +extern UINT32 u4DrvOwnMax; +extern BOOLEAN fgIsUnderSuspend; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/* Command to TDLS core module */ +typedef enum _STATS_CMD_CORE_ID { + STATS_CORE_CMD_ENV_REQUEST = 0x00 +} STATS_CMD_CORE_ID; + +typedef enum _STATS_EVENT_HOST_ID { + STATS_HOST_EVENT_ENV_REPORT = 0x00, + STATS_HOST_EVENT_RX_DROP +} STATS_EVENT_HOST_ID; + +#define CFG_ARP BIT(0) +#define CFG_DNS BIT(1) +#define CFG_TCP BIT(2) +#define CFG_UDP BIT(3) +#define CFG_EAPOL BIT(4) +#define CFG_DHCP BIT(5) +#define CFG_ICMP BIT(6) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef struct _STATS_CMD_CORE_T { + + UINT32 u4Command; /* STATS_CMD_CORE_ID */ + + UINT8 ucStaRecIdx; + UINT8 ucReserved[3]; + + UINT32 u4Reserved[4]; + +#define STATS_CMD_CORE_RESERVED_SIZE 50 + union { + UINT8 Reserved[STATS_CMD_CORE_RESERVED_SIZE]; + } Content; + +} STATS_CMD_CORE_T; + +typedef struct _STATS_INFO_ENV_T { + + BOOLEAN fgIsUsed; /* TRUE: used */ + + /* ------------------- TX ------------------- */ + BOOLEAN fgTxIsRtsUsed; /* TRUE: we use RTS/CTS currently */ + BOOLEAN fgTxIsRtsEverUsed; /* TRUE: we ever use RTS/CTS */ + BOOLEAN fgTxIsCtsSelfUsed; /* TRUE: we use CTS-self */ + +#define STATS_INFO_TX_PARAM_HW_BW40_OFFSET 0 +#define STATS_INFO_TX_PARAM_HW_SHORT_GI20_OFFSET 1 +#define STATS_INFO_TX_PARAM_HW_SHORT_GI40_OFFSET 2 +#define STATS_INFO_TX_PARAM_USE_BW40_OFFSET 3 +#define STATS_INFO_TX_PARAM_USE_SHORT_GI_OFFSET 4 +#define STATS_INFO_TX_PARAM_NO_ACK_OFFSET 5 + UINT_8 ucTxParam; + + UINT_8 ucStaRecIdx; + UINT_8 ucReserved1[2]; + + UINT32 u4TxDataCntAll; /* total tx count from host */ + UINT32 u4TxDataCntOK; /* total tx ok count to air */ + UINT32 u4TxDataCntErr; /* total tx err count to air */ + + /* WLAN_STATUS_BUFFER_RETAINED ~ WLAN_STATUS_PACKET_LIFETIME_ERROR */ + UINT32 u4TxDataCntErrType[6]; /* total tx err count for different type to air */ + + UINT_8 ucTxRate1NonHTMax; + UINT_8 ucTxRate1HTMax; + UINT32 u4TxRateCntNonHT[16]; /* tx done rate */ + UINT32 u4TxRateCntHT[16]; /* tx done rate */ + + UINT_8 ucTxAggBitmap; /* TX BA sessions TID0 ~ TID7 */ + UINT_8 ucTxPeerAggMaxSize; + + /* ------------------- RX ------------------- */ + BOOLEAN fgRxIsRtsUsed; /* TRUE: peer uses RTS/CTS currently */ + BOOLEAN fgRxIsRtsEverUsed; /* TRUE: peer ever uses RTS/CTS */ + + UINT_8 ucRcvRcpi; + UINT_8 ucHwChanNum; + BOOLEAN fgRxIsShortGI; + UINT_8 ucReserved2[1]; + + UINT32 u4RxDataCntAll; /* total rx count from peer */ + UINT32 u4RxDataCntErr; /* total rx err count */ + UINT32 u4RxRateCnt[3][16]; /* [0]:CCK, [1]:OFDM, [2]:MIXED (skip green mode) */ + + UINT_8 ucRxAggBitmap; /* RX BA sessions TID0 ~ TID7 */ + UINT_8 ucRxAggMaxSize; + +#define STATS_INFO_PHY_MODE_CCK 0 +#define STATS_INFO_PHY_MODE_OFDM 1 +#define STATS_INFO_PHY_MODE_HT 2 +#define STATS_INFO_PHY_MODE_VHT 3 + UINT_8 ucBssSupPhyMode; /* CCK, OFDM, HT, or VHT BSS */ + + UINT_8 ucVersion; /* the version of statistics info environment */ + + /* ------------------- Delay ------------------- */ +#define STATS_AIR_DELAY_INT 500 /* 500 byte */ + + /* delay in firmware from host to MAC */ + /* unit: us, for 500B, 1000B, max */ + UINT32 u4StayIntMaxH2M[3], u4StayIntMinH2M[3], u4StayIntAvgH2M[3]; + + /* delay in firmware from MAC to TX done */ + /* unit: 32us, for 500B, 1000B, max */ + UINT32 u4AirDelayMax[3], u4AirDelayMin[3], u4AirDelayAvg[3]; + + /* delay in firmware from host to TX done */ + /* unit: us, for 500B, 1000B, max */ + UINT32 u4StayIntMax[3], u4StayIntMin[3], u4StayIntAvg[3]; + UINT32 u4StayIntMaxSysTime[3]; + + /* delay in firmware from driver to TX done */ + /* unit: us, for 500B, 1000B, max */ + UINT32 u4StayIntMaxD2T[3], u4StayIntMinD2T[3], u4StayIntAvgD2T[3]; + + /* delay count in firmware from host to TX done */ + /* u4StayIntByConst: divide 4 fix partitions to count each delay in firmware */ +#define STATS_STAY_INT_CONST 1 /* 1ms */ +#define STATS_STAY_INT_CONST_2 5 +#define STATS_STAY_INT_CONST_3 10 +#define STATS_STAY_INT_CONST_4 15 +#define STATS_STAY_INT_CONST_NUM 4 + UINT32 u4StayIntByConst[STATS_STAY_INT_CONST_NUM]; + + /* + * u4StayIntMaxPast: past maximum delay in firmware + * u4StayIntCnt[]: divide 4 partitions to count each delay in firmware + */ +#define STATS_STAY_INT_NUM 4 + UINT32 u4StayIntMaxPast; + UINT32 u4StayIntCnt[STATS_STAY_INT_NUM + 1]; + + /* delay count in firmware from driver to HIF */ + /* u4StayIntD2HByConst: divide 4 fix partitions to count each delay in firmware */ +#define STATS_STAY_INT_D2H_CONST 10 /* 10ms */ +#define STATS_STAY_INT_D2H_CONST_2 20 +#define STATS_STAY_INT_D2H_CONST_3 30 +#define STATS_STAY_INT_D2H_CONST_4 40 +#define STATS_STAY_INT_D2H_CONST_NUM 4 + UINT32 u4StayIntD2HByConst[STATS_STAY_INT_D2H_CONST_NUM]; + + /* unit: us, for 500B, 1000B, max */ + UINT32 u4StayIntMaxRx[3], u4StayIntMinRx[3], u4StayIntAvgRx[3]; + + /* ------------------- Others ------------------- */ + UINT32 u4NumOfChanChange; /* total channel change count */ + UINT32 u4NumOfRetryCnt; /* total TX retry count */ + UINT32 u4RxFifoFullCnt; /* + * counter of the number of the packets which + * pass RFCR but are dropped due to FIFO full. + */ + UINT32 u4PsIntMax; /* maximum time from ps to active */ + UINT_8 ucNumOfPsChange; /* peer power save change count */ + UINT_8 ucReserved3[3]; + + UINT32 u4ReportSysTime; /* firmware system time */ + UINT32 u4RxDataCntOk; /* total rx count to hif */ + + /* V4 */ + UINT32 u4RxRateRetryCnt[3][16]; /* [0]:CCK, [1]:OFDM, [2]:MIXED (skip green mode) */ + UINT32 au4ChanIdleCnt[10]; /* past Channel idle count in unit of slot */ + + /* V5 */ + UINT32 u4BtContUseTime; /* the air time that BT continuous occypy */ + + /* V6 */ + UINT32 u4LastTxOkTime; /* last time we tx ok to the station */ + + /* V7 */ + UINT_8 ucBtWfCoexGrantCnt[8]; /* [0]:WF Rx Grant Cnt[1]: WF Tx Grant Cnt[2]: WF Grant with Priority1 */ + /* [4]:BT Rx Grant Cnt[5]: BT Tx Grant Cnt[6]: BT Grant with Priority1 */ + + /* V8 */ + UINT_32 u4RxMacFreeDescCnt[6]; + UINT_32 u4RxHifFreeDescCnt[6]; + + /* V9 */ +#define STATS_MAX_RX_DROP_TYPE 20 + UINT32 u4NumOfRxDrop[STATS_MAX_RX_DROP_TYPE]; + + /* V10 */ + UINT_32 u4NumOfTxDone; /* number of all packets (data/man/ctrl) tx done */ + UINT_32 u4NumOfTxDoneFixRate; /* number of done rate = 0 */ + UINT_32 u4NumOfTxDoneErrRate; /* number of error done rate */ + UINT_32 u4NumOfNullTxDone; /* number of null tx done */ + UINT_32 u4NumOfQoSNullTxDone; /* number of QoS-null tx done */ + + /* V11 */ + /* delay in firmware from HIF RX to HIF RX Done */ + /* unit: us, for 500B, 1000B, max */ + UINT32 u4StayIntMaxHR2HRD[3], u4StayIntMinHR2HRD[3], u4StayIntAvgHR2HRD[3]; + + /* V12 */ + UINT32 u4AirDelayTotal; /* agg all the air delay */ + + /* V13 */ + UINT32 u4CurrChnlInfo; /* add current channel information */ + + UINT_8 ucReserved_rate[4]; /* the field must be the last one */ +} STATS_INFO_ENV_T; + +/******************************************************************************* +* M A C R O D E C L A R A T I O N S +******************************************************************************** +*/ +#if (CFG_SUPPORT_STATISTICS == 1) + +#define STATS_ENV_REPORT_DETECT statsEnvReportDetect + +#define STATS_RX_REORDER_FALL_AHEAD_INC(__StaRec__) \ +{ \ + (__StaRec__)->u4RxReorderFallAheadCnt++; \ +} + +#define STATS_RX_REORDER_FALL_BEHIND_INC(__StaRec__) \ +{ \ + (__StaRec__)->u4RxReorderFallBehindCnt++; \ +} + +#define STATS_RX_REORDER_FALL_BEHIND_NO_DROP_INC(__StaRec__) \ +{ \ + (__StaRec__)->u4RxReorderFallBehindNoDropCnt++; \ +} + +#define STATS_RX_REORDER_HOLE_INC(__StaRec__) \ +{ \ + (__StaRec__)->u4RxReorderHoleCnt++; \ +} + +#define STATS_RX_REORDER_HOLE_TIMEOUT_INC(__StaRec__, __IsTimeout__) \ +{ \ + if ((__IsTimeout__) == TRUE) \ + (__StaRec__)->u4RxReorderHoleTimeoutCnt++; \ +} + +#define STATS_RX_ARRIVE_TIME_RECORD(__SwRfb__) \ +{ \ + (__SwRfb__)->rRxTime = StatsEnvTimeGet(); \ +} + +#define STATS_RX_PASS2OS_INC StatsEnvRxDone + +#define STATS_RX_PKT_INFO_DISPLAY StatsRxPktInfoDisplay + +#define STATS_TX_TIME_ARRIVE(__Skb__) \ +do { \ + UINT_64 __SysTime; \ + __SysTime = StatsEnvTimeGet(); /* us */ \ + GLUE_SET_PKT_XTIME(__Skb__, __SysTime); \ +} while (FALSE) + +#define STATS_TX_TIME_TO_HIF StatsEnvTxTime2Hif + +#define STATS_TX_PKT_CALLBACK StatsTxPktCallBack +#define STATS_TX_PKT_DONE_INFO_DISPLAY StatsTxPktDoneInfoDisplay + +#define STATS_DRIVER_OWN_RESET() \ +{ \ + u4DrvOwnMax = 0; \ +} +#define STATS_DRIVER_OWN_START_RECORD() \ +{ \ + u8DrvOwnStart = StatsEnvTimeGet(); \ +} +#define STATS_DRIVER_OWN_END_RECORD() \ +{ \ + u8DrvOwnEnd = StatsEnvTimeGet(); \ +} +#define STATS_DRIVER_OWN_STOP() \ +do { \ + UINT32 __Diff; \ + __Diff = (UINT32)(u8DrvOwnEnd - u8DrvOwnStart); \ + if (__Diff > u4DrvOwnMax) \ + u4DrvOwnMax = __Diff; \ +} while (FALSE) + +#else + +#define STATS_ENV_REPORT_DETECT(__Adapter__, __StaRecIndex__) + +#define STATS_RX_REORDER_FALL_AHEAD_INC(__StaRec__) +#define STATS_RX_REORDER_FALL_BEHIND_INC(__StaRec__) +#define STATS_RX_REORDER_HOLE_INC(__StaRec__) +#define STATS_RX_REORDER_HOLE_TIMEOUT_INC(__StaRec__, __IsTimeout__) +#define STATS_RX_PASS2OS_INC(__StaRec__, __SwRfb__) +#define STATS_RX_PKT_INFO_DISPLAY(__Pkt__) + +#define STATS_TX_TIME_ARRIVE(__Skb__) +#define STATS_TX_TIME_TO_HIF(__MsduInfo__, __HwTxHeader__) +#define STATS_TX_PKT_CALLBACK(__Pkt__, __fgIsNeedAck__) +#define STATS_TX_PKT_DONE_INFO_DISPLAY(__Adapter__, __Event__) + +#define STATS_DRIVER_OWN_RESET() +#define STATS_DRIVER_OWN_START_RECORD() +#define STATS_DRIVER_OWN_END_RECORD() +#define STATS_DRIVER_OWN_STOP() +#endif /* CFG_SUPPORT_STATISTICS */ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E F U N C T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C F U N C T I O N S +******************************************************************************** +*/ + +VOID statsEnvReportDetect(ADAPTER_T *prAdapter, UINT8 ucStaRecIndex); + +VOID StatsEnvRxDone(STA_RECORD_T *prStaRec, SW_RFB_T *prSwRfb); + +UINT_64 StatsEnvTimeGet(VOID); + +VOID StatsEnvTxTime2Hif(MSDU_INFO_T *prMsduInfo, HIF_TX_HEADER_T *prHwTxHeader); + +VOID statsEventHandle(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen); + +VOID StatsRxPktInfoDisplay(UINT_8 *pPkt); + +VOID StatsTxPktCallBack(UINT_8 *pPkt, P_MSDU_INFO_T prMsduInfo); + +VOID StatsTxPktDoneInfoDisplay(ADAPTER_T *prAdapter, UINT_8 *pucEvtBuf); + +VOID StatsSetCfgTxDone(UINT_16 u2Cfg, BOOLEAN fgSet); + +UINT_16 StatsGetCfgTxDone(VOID); + +/* End of stats.h */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/swcr.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/swcr.h new file mode 100644 index 0000000000000..b7c18571b263f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/swcr.h @@ -0,0 +1,189 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _SWCR_H +#define _SWCR_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "nic_cmd_event.h" + +#if 0 +extern SWCR_MAP_ENTRY_T g_arRlmArSwCrMap[]; +#endif +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define SWCR_VAR(x) ((VOID *)&x) +#define SWCR_FUNC(x) ((VOID *)x) + +#define SWCR_T_FUNC BIT(7) + +#define SWCR_L_32 3 +#define SWCR_L_16 2 +#define SWCR_L_8 1 + +#define SWCR_READ 0 +#define SWCR_WRITE 1 + +#define SWCR_MAP_NUM(x) (ARRAY_SIZE(x)) + +#define SWCR_CR_NUM 7 + +#define SWCR_GET_RW_INDEX(action, rw, index) \ +do { \ + index = action & 0x7F; \ + rw = action >> 7; \ +} while (0) + +extern UINT_32 g_au4SwCr[]; /*: 0: command other: data */ + +typedef VOID(*PFN_SWCR_RW_T) (P_ADAPTER_T prAdapter, UINT_8 ucRead, UINT_16 u2Addr, UINT_32 *pu4Data); +typedef VOID(*PFN_CMD_RW_T) (P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1); + +typedef struct _SWCR_MAP_ENTRY_T { + UINT_16 u2Type; + PVOID u4Addr; +} SWCR_MAP_ENTRY_T, *P_SWCR_MAP_ENTRY_T; + +typedef struct _SWCR_MOD_MAP_ENTRY_T { + UINT_8 ucMapNum; + P_SWCR_MAP_ENTRY_T prSwCrMap; +} SWCR_MOD_MAP_ENTRY_T, *P_SWCR_MOD_MAP_ENTRY_T; + +typedef enum _ENUM_SWCR_DBG_TYPE_T { + SWCR_DBG_TYPE_ALL = 0, + SWCR_DBG_TYPE_TXRX, + SWCR_DBG_TYPE_RX_RATES, + SWCR_DBG_TYPE_PS, + SWCR_DBG_TYPE_NUM +} ENUM_SWCR_DBG_TYPE_T; + +typedef enum _ENUM_SWCR_DBG_ALL_T { + SWCR_DBG_ALL_TX_CNT = 0, + SWCR_DBG_ALL_TX_BCN_CNT, + SWCR_DBG_ALL_TX_FAILED_CNT, + SWCR_DBG_ALL_TX_RETRY_CNT, + SWCR_DBG_ALL_TX_AGING_TIMEOUT_CNT, + SWCR_DBG_ALL_TX_PS_OVERFLOW_CNT, + SWCR_DBG_ALL_TX_MGNT_DROP_CNT, + SWCR_DBG_ALL_TX_ERROR_CNT, + + SWCR_DBG_ALL_RX_CNT, + SWCR_DBG_ALL_RX_DROP_CNT, + SWCR_DBG_ALL_RX_DUP_DROP_CNT, + SWCR_DBG_ALL_RX_TYPE_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_CLASS_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_AMPDU_ERROR_DROP_CNT, + + SWCR_DBG_ALL_RX_STATUS_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_FORMAT_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_ICV_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_KEY_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_TKIP_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_MIC_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_BIP_ERROR_DROP_CNT, + + SWCR_DBG_ALL_RX_FCSERR_CNT, + SWCR_DBG_ALL_RX_FIFOFULL_CNT, + SWCR_DBG_ALL_RX_PFDROP_CNT, + + SWCR_DBG_ALL_PWR_PS_POLL_CNT, + SWCR_DBG_ALL_PWR_TRIGGER_NULL_CNT, + SWCR_DBG_ALL_PWR_BCN_IND_CNT, + SWCR_DBG_ALL_PWR_BCN_TIMEOUT_CNT, + SWCR_DBG_ALL_PWR_PM_STATE0, + SWCR_DBG_ALL_PWR_PM_STATE1, + SWCR_DBG_ALL_PWR_CUR_PS_PROF0, + SWCR_DBG_ALL_PWR_CUR_PS_PROF1, + + SWCR_DBG_ALL_AR_STA0_RATE, + SWCR_DBG_ALL_AR_STA0_BWGI, + SWCR_DBG_ALL_AR_STA0_RX_RATE_RCPI, + + SWCR_DBG_ALL_ROAMING_ENABLE, + SWCR_DBG_ALL_ROAMING_ROAM_CNT, + SWCR_DBG_ALL_ROAMING_INT_CNT, + + SWCR_DBG_ALL_BB_RX_MDRDY_CNT, + SWCR_DBG_ALL_BB_RX_FCSERR_CNT, + SWCR_DBG_ALL_BB_CCK_PD_CNT, + SWCR_DBG_ALL_BB_OFDM_PD_CNT, + SWCR_DBG_ALL_BB_CCK_SFDERR_CNT, + SWCR_DBG_ALL_BB_CCK_SIGERR_CNT, + SWCR_DBG_ALL_BB_OFDM_TAGERR_CNT, + SWCR_DBG_ALL_BB_OFDM_SIGERR_CNT, + + SWCR_DBG_ALL_NUM +} ENUM_SWCR_DBG_ALL_T; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID swCtrlCmdCategory0(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1); +VOID swCtrlCmdCategory1(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1); +VOID testPsCmdCategory0(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1); +VOID testPsCmdCategory1(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1); +void testWNMCmdCategory0(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1); +VOID swCtrlSwCr(P_ADAPTER_T prAdapter, UINT_8 ucRead, UINT_16 u2Addr, UINT_32 *pu4Data); +UINT_32 swCrGetDNSRxFilter(VOID); + +/* Support Debug */ +VOID swCrDebugCheck(P_ADAPTER_T prAdapter, P_CMD_SW_DBG_CTRL_T prCmdSwCtrl); +VOID swCrDebugCheckTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam); +VOID swCrDebugQuery(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +VOID swCrDebugQueryTimeout(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +VOID swCrReadWriteCmd(P_ADAPTER_T prAdapter, UINT_8 ucRead, UINT_16 u2Addr, UINT_32 *pu4Data); + +/* Debug Support */ +VOID swCrFrameCheckEnable(P_ADAPTER_T prAdapter, UINT_32 u4DumpType); +VOID swCrDebugInit(P_ADAPTER_T prAdapter); +VOID swCrDebugCheckEnable(P_ADAPTER_T prAdapter, BOOLEAN fgIsEnable, UINT_8 ucType, UINT_32 u4Timeout); +VOID swCrDebugUninit(P_ADAPTER_T prAdapter); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/tdls.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/tdls.h new file mode 100644 index 0000000000000..445fbad02f3c8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/tdls.h @@ -0,0 +1,322 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _TDLS_H +#define _TDLS_H + +#if (CFG_SUPPORT_TDLS == 1) + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#define TDLS_CFG_CMD_TEST 1 +#define TDLS_CFG_HT_SUP 1 + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +extern int wlanHardStartXmit(struct sk_buff *prSkb, struct net_device *prDev); +extern int p2pHardStartXmit(struct sk_buff *prSkb, struct net_device *prDev); +extern BOOLEAN flgTdlsTestExtCapElm; +extern UINT8 aucTdlsTestExtCapElm[]; +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +typedef struct _TDLS_LINK_HIS_OTHERS_T { + BOOLEAN fgIsHt; /* TRUE: HT device */ + +} TDLS_LINK_HIS_OTHERS_T; + +/* command */ +typedef enum _TDLS_CMD_ID { + TDLS_CMD_TEST_TX_FRAME = 0x00, + TDLS_CMD_TEST_RCV_FRAME = 0x01, + TDLS_CMD_TEST_PEER_ADD = 0x02, + TDLS_CMD_TEST_PEER_UPDATE = 0x03, + TDLS_CMD_TEST_DATA_FRAME = 0x04, + TDLS_CMD_TEST_RCV_NULL = 0x05, + TDLS_CMD_MIB_UPDATE = 0x06, + TDLS_CMD_TEST_SKIP_TX_FAIL = 0x07, + TDLS_CMD_UAPSD_CONF = 0x08, + TDLS_CMD_CH_SW_CONF = 0x09, + TDLS_CMD_TEST_SKIP_KEEP_ALIVE = 0x0a, + TDLS_CMD_TEST_SKIP_CHSW_TIMEOUT = 0x0b, + TDLS_CMD_TEST_TX_TDLS_FRAME = 0x0c, + TDLS_CMD_TEST_PROHIBIT_SET_IN_AP = 0x0d, + TDLS_CMD_TEST_SCAN_DISABLE = 0x0e, + TDLS_CMD_TEST_DATA_FRAME_CONT = 0x0f, + TDLS_CMD_TEST_CH_SW_PROHIBIT_SET_IN_AP = 0x10, + TDLS_CMD_SETUP_CONF = 0x11, + TDLS_CMD_INFO = 0x12, + TDLS_CMD_TEST_DELAY = 0x13, + TDLS_CMD_KEY_INFO = 0x14, + TDLS_CMD_TEST_PTI_TX_FAIL = 0x15 +} TDLS_CMD_ID; + +typedef enum _TDLS_EVENT_HOST_ID { + TDLS_HOST_EVENT_TEAR_DOWN = 0x00, /* TDLS_EVENT_HOST_SUBID_TEAR_DOWN */ + TDLS_HOST_EVENT_TX_DONE, + TDLS_HOST_EVENT_FME_STATUS, /* TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME */ + TDLS_HOST_EVENT_STATISTICS +} TDLS_EVENT_HOST_ID; + +typedef enum _TDLS_EVENT_HOST_SUBID_TEAR_DOWN { + TDLS_HOST_EVENT_TD_PTI_TIMEOUT = 0x00, + TDLS_HOST_EVENT_TD_AGE_TIMEOUT, + TDLS_HOST_EVENT_TD_PTI_SEND_FAIL, + TDLS_HOST_EVENT_TD_PTI_SEND_MAX_FAIL, + TDLS_HOST_EVENT_TD_WRONG_NETWORK_IDX, + TDLS_HOST_EVENT_TD_NON_STATE3, + TDLS_HOST_EVENT_TD_LOST_TEAR_DOWN +} TDLS_EVENT_HOST_SUBID_TEAR_DOWN; + +typedef enum _TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME { + TDLS_HOST_EVENT_SF_BA, + TDLS_HOST_EVENT_SF_BA_OK, + TDLS_HOST_EVENT_SF_BA_DECLINE, + TDLS_HOST_EVENT_SF_BA_PEER, + TDLS_HOST_EVENT_SF_BA_RSP_OK, + TDLS_HOST_EVENT_SF_BA_RSP_DECLINE +} TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME; + +/* payload specific type in the LLC/SNAP header */ +#define TDLS_FRM_PAYLOAD_TYPE 2 + +#define TDLS_FRM_CATEGORY 12 + +typedef enum _TDLS_FRM_ACTION_ID { + TDLS_FRM_ACTION_SETUP_REQ = 0x00, + TDLS_FRM_ACTION_SETUP_RSP, + TDLS_FRM_ACTION_CONFIRM, + TDLS_FRM_ACTION_TEARDOWN, + TDLS_FRM_ACTION_PTI, + TDLS_FRM_ACTION_CHAN_SWITCH_REQ, + TDLS_FRM_ACTION_CHAN_SWITCH_RSP, + TDLS_FRM_ACTION_PEER_PSM_REQ, + TDLS_FRM_ACTION_PEER_PSM_RSP, + TDLS_FRM_ACTION_PTI_RSP, /* 0x09 */ + TDLS_FRM_ACTION_DISCOVERY_REQ, + + TDLS_FRM_ACTION_EVENT_TEAR_DOWN_TO_SUPPLICANT = 0x30, + + TDLS_FRM_DATA_TEST_DATA = 0x80 +} TDLS_FRM_ACTION_ID; + +#define TDLS_FRM_ACTION_DISCOVERY_RESPONSE 14 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* 7.3.2.62 Link Identifier element */ +#define ELEM_ID_LINK_IDENTIFIER 101 +#define ELEM_LEN_LINK_IDENTIFIER 18 + +typedef struct _IE_LINK_IDENTIFIER_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aBSSID[6]; + UINT_8 aInitiator[6]; + UINT_8 aResponder[6]; +} __KAL_ATTRIB_PACKED__ IE_LINK_IDENTIFIER_T; + +typedef struct _TDLS_FRAME_HEADER { + UINT_8 ucPayLoadType; + UINT_8 ucCategory; + UINT_8 ucAction; +} __KAL_ATTRIB_PACKED__ TDLS_FRAME_HEADER_T; + + +#define TDLS_LINK_IDENTIFIER_IE(__ie__) ((IE_LINK_IDENTIFIER_T *)(__ie__)) + +/* test command use */ +typedef struct _PARAM_CUSTOM_TDLS_CMD_STRUCT_T { + + UINT_8 ucFmeType; /* TDLS_FRM_ACTION_ID */ + + UINT_8 ucToken; + UINT_16 u2Cap; + + /* bit0: TDLS, bit1: Peer U-APSD Buffer, bit2: Channel Switching */ +#define TDLS_EX_CAP_PEER_UAPSD BIT(0) +#define TDLS_EX_CAP_CHAN_SWITCH BIT(1) +#define TDLS_EX_CAP_TDLS BIT(2) + UINT_8 ucExCap; + + UINT_8 arSupRate[4]; + UINT_8 arSupChan[4]; + + UINT_32 u4Timeout; + +#define TDLS_FME_MAC_ADDR_LEN 6 + UINT_8 arRspAddr[TDLS_FME_MAC_ADDR_LEN]; + UINT_8 arBssid[TDLS_FME_MAC_ADDR_LEN]; + +/* + * Linux Kernel-3.10 + * struct station_parameters { + * const u8 *supported_rates; + * struct net_device *vlan; + * u32 sta_flags_mask, sta_flags_set; + * u32 sta_modify_mask; + * int listen_interval; + * u16 aid; + * u8 supported_rates_len; + * u8 plink_action; + * u8 plink_state; + * const struct ieee80211_ht_cap *ht_capa; + * const struct ieee80211_vht_cap *vht_capa; + * u8 uapsd_queues; + * u8 max_sp; + * enum nl80211_mesh_power_mode local_pm; + * u16 capability; + * const u8 *ext_capab; + * u8 ext_capab_len; + * }; + */ + struct ieee80211_ht_cap rHtCapa; + struct ieee80211_vht_cap rVhtCapa; /* LINUX_KERNEL_VERSION >= 3.10.0 */ + struct station_parameters rPeerInfo; + +} PARAM_CUSTOM_TDLS_CMD_STRUCT_T; + +typedef struct _TDLS_MGMT_TX_INFO { + ENUM_NETWORK_TYPE_INDEX_T eNetworkType; + UINT8 aucPeer[6]; + UINT8 ucActionCode; + UINT8 ucDialogToken; + UINT16 u2StatusCode; + UINT32 u4SecBufLen; + UINT8 aucSecBuf[1000]; +} TDLS_MGMT_TX_INFO; + +enum MTK_TDLS_STATUS { + MTK_TDLS_NOT_SETUP, + MTK_TDLS_SETUP_INPROCESS, + MTK_TDLS_SETUP_COMPLETE, + MTK_TDLS_SETUP_TEARDOWN, + MTK_TDLS_LINK_ENABLE, + MTK_TDLS_LINK_DOWN, + MTK_TDLS_LINK_DISABLE, + MTK_TDLS_SETUP_NUM +}; + +enum MTK_TDLS_ROLE { + MTK_TDLS_ROLE_IDLE, + MTK_TDLS_ROLE_RESPONDER, + MTK_TDLS_ROLE_INITOR, + MTK_TDLS_ROLE_NUM +}; + +struct ksta_info { + struct ksta_info *pNext; /* next entry in sta list */ + UCHAR aucAddr[6]; + ENUM_NETWORK_TYPE_INDEX_T ucNetworkType; + UINT_32 u4Throughput; + UINT_32 u4RxThroughput; + ULONG ulTxBytes; + ULONG ulRxBytes; + enum MTK_TDLS_STATUS eTdlsStatus; + UINT32 u4SetupFailCount; + enum MTK_TDLS_ROLE eTdlsRole; +}; + +#define SAMPLING_UT (2 * HZ) +#define TDLS_SETUP_TIMEOUT (4) +#define TDLS_MONITOR_UT (2) +/* TDLS setup threshold if TX throughput > the THD */ +#define TDLS_SETUP_THD (1000) +#define TDLS_SETUP_COUNT (4) +#define TDLS_TEARDOWN_THD (500) +#define TDLS_TEARDOWN_RX_THD (100) +#define TDLS_LINK_ENABLED(prSta) (prSta->eTdlsStatus == MTK_TDLS_LINK_ENABLE) + +enum sta_op { + STA_OP_FREE, + STA_OP_RESET, + STA_OP_GET_MAX_TP, + STA_OP_UPDATE_TX, + STA_OP_NUM +}; + + +#define STA_HASH_SIZE 256 +#define STA_HASH(prSta) (prSta[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 +******************************************************************************** +*/ + +/* check any TDLS link */ +#define TDLS_IS_NO_LINK_GOING(__GlueInfo__) \ + ((__GlueInfo__)->rTdlsLink.cLinkCnt == 0) + +/* increase TDLS link count */ +#define TDLS_LINK_INCREASE(__GlueInfo__) \ + ((__GlueInfo__)->rTdlsLink.cLinkCnt++) + +/* decrease TDLS link count */ +#define TDLS_LINK_DECREASE(__GlueInfo__) \ +do { \ + if ((__GlueInfo__)->rTdlsLink.cLinkCnt > 0) \ + (__GlueInfo__)->rTdlsLink.cLinkCnt--; \ +} while (0) + +/* get TDLS link count */ +#define TDLS_LINK_COUNT(__GlueInfo__) \ + ((__GlueInfo__)->rTdlsLink.cLinkCnt) + +/* reset TDLS link count */ +#define TDLS_LINK_COUNT_RESET(__GlueInfo__) \ + ((__GlueInfo__)->rTdlsLink.cLinkCnt = 0) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/* Note: these functions are used only in tdls module, not other modules */ +UINT_32 TdlsFrameGeneralIeAppend(ADAPTER_T *prAdapter, STA_RECORD_T *prStaRec, UINT_16 u2StatusCode, UINT_8 *pPkt); + +TDLS_STATUS +TdlsDataFrameSend(ADAPTER_T *prAdapter, + STA_RECORD_T *prStaRec, + TDLS_MGMT_TX_INFO *prMsduInfo); +INT_32 MTKAutoTdlsP2P(P_GLUE_INFO_T prGlueInfo, P_NATIVE_PACKET prPacket); +BOOLEAN MTKTdlsEnvP2P(P_ADAPTER_T prAdapter); +VOID MTKTdlsSetup(P_GLUE_INFO_T prGlueInfo, struct ksta_info *prSta); +VOID MTKTdlsTearDown(P_GLUE_INFO_T prGlueInfo, struct ksta_info *prSta, CHAR *reason); +VOID MTKTdlsApStaUpdateTxRxStatus(P_GLUE_INFO_T prGlueInfo, unsigned long tx_bytes, + unsigned long rx_bytes, const u8 *addr); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* CFG_SUPPORT_TDLS */ + +#endif /* _TDLS_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/wapi.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/wapi.h new file mode 100644 index 0000000000000..b1b8ab52ee180 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/wapi.h @@ -0,0 +1,81 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _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 +******************************************************************************** +*/ + +BOOLEAN wapiParseWapiIE(IN P_WAPI_INFO_ELEM_T prInfoElem, OUT P_WAPI_INFO_T prWapiInfo); + +BOOLEAN wapiPerformPolicySelection(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBss); + +/* BOOLEAN */ +/* wapiUpdateTxKeyIdx ( */ +/* IN P_STA_RECORD_T prStaRec, */ +/* IN UINT_8 ucWlanIdx */ +/* ); */ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif +#endif /* _WAPI_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/wlan_typedef.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/wlan_typedef.h new file mode 100644 index 0000000000000..7ae489cd30289 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/wlan_typedef.h @@ -0,0 +1,86 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _WLAN_TYPEDEF_H +#define _WLAN_TYPEDEF_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Type definition for BSS_INFO_T structure, to describe the attributes used in a + * common BSS. + */ +typedef struct _BSS_INFO_T BSS_INFO_T, *P_BSS_INFO_T; + +typedef BSS_INFO_T AIS_BSS_INFO_T, *P_AIS_BSS_INFO_T; +typedef BSS_INFO_T P2P_BSS_INFO_T, *P_P2P_BSS_INFO_T; +typedef BSS_INFO_T BOW_BSS_INFO_T, *P_BOW_BSS_INFO_T; + +typedef struct _AIS_SPECIFIC_BSS_INFO_T AIS_SPECIFIC_BSS_INFO_T, *P_AIS_SPECIFIC_BSS_INFO_T; +typedef struct _P2P_SPECIFIC_BSS_INFO_T P2P_SPECIFIC_BSS_INFO_T, *P_P2P_SPECIFIC_BSS_INFO_T; +typedef struct _BOW_SPECIFIC_BSS_INFO_T BOW_SPECIFIC_BSS_INFO_T, *P_BOW_SPECIFIC_BSS_INFO_T; +/* CFG_SUPPORT_WFD */ +typedef struct _WFD_CFG_SETTINGS_T WFD_CFG_SETTINGS_T, *P_WFD_CFG_SETTINGS_T; + +typedef struct _WFD_DBG_CFG_SETTINGS_T WFD_DBG_CFG_SETTINGS_T, *P_WFD_DBG_CFG_SETTINGS_T; + +/* BSS related structures */ +/* Type definition for BSS_DESC_T structure, to describe parameter sets of a particular BSS */ +typedef struct _BSS_DESC_T BSS_DESC_T, *P_BSS_DESC_T, **PP_BSS_DESC_T; +typedef struct _ROAM_BSS_DESC_T ROAM_BSS_DESC_T, *P_ROAM_BSS_DESC_T, **PP_ROAM_BSS_DESC_T; + +#if CFG_SUPPORT_HOTSPOT_2_0 +typedef struct _HS20_INFO_T HS20_INFO_T, *P_HS20_INFO_T; +#endif /* CFG_SUPPORT_HOTSPOT_2_0 */ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _WLAN_TYPEDEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/wmm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/wmm.h new file mode 100644 index 0000000000000..f70d96b2fd193 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/wmm.h @@ -0,0 +1,212 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef WMM_HDR_H +#define WMM_HDR_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 VENDOR_OUI_TYPE_TSRS 8 +#define VENDOR_OUI_TYPE_TSM 7 +#define VENDOR_OUI_TYPE_EDCALIFE 9 +#define WLAN_MAC_ACTION_ADDTS_LEN (WLAN_MAC_MGMT_HEADER_HTC_LEN + 66) +#define WLAN_MAC_ACTION_DELTS_LEN (WLAN_MAC_MGMT_HEADER_HTC_LEN + 7) +#define TSPEC_POLICY_CHECK_INTERVAL 2500 /* unit ms */ + +#define WMM_TS_STATUS_ADMISSION_ACCEPTED 0 +#define WMM_TS_STATUS_ADDTS_INVALID_PARAM 1 +#define WMM_TS_STATUS_ADDTS_REFUSED 3 +#define WMM_TS_STATUS_ASSOC_QOS_FAILED 0xc8 +#define WMM_TS_STATUS_POLICY_CONFIG_REFUSED 0xc9 +#define WMM_TS_STATUS_ASSOC_INSUFFICIENT_BANDWIDTH 0xca +#define WMM_TS_STATUS_ASSOC_INVALID_PARAM 0xcb + +/* +** In WMM, TSs are identified with TIDs values 0 through 7. Any TID may map onto any +** UP and thus onto any AC, however for each AC used between an RA and TA, only the +** following combinations are valid: +** No TS, One uplink TS, one Download link TS, one uplink and one uplink TS, one +** bi-directional TS. +** so maximum 8 TSs are allowed in a RA & TA context. +*/ +#define WMM_TSPEC_ID_NUM 8 + +/*WMM-2.2.11 WMM TSPEC IE*/ +#define ELEM_MAX_LEN_WMM_TSPEC 61 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +enum WMM_ADDTS_STATUS { + ADDTS_ACCEPTED = 0, + ADDTS_INVALID_PARAMS = 1, + ADDTS_REFUSED = 2 +}; + +enum TSPEC_OP_CODE { + TX_ADDTS_REQ, + RX_ADDTS_RSP, + TX_DELTS_REQ, + RX_DELTS_REQ, + DISC_DELTS_REQ, + UPDATE_TS_REQ +}; + +enum QOS_TS_STATE { + QOS_TS_INACTIVE, + QOS_TS_ACTIVE, + QOS_TS_SETUPING, + QOS_TS_STATE_MAX +}; + +enum TSPEC_DIR { + UPLINK_TS = 0, + DOWNLINK_TS = 1, + BI_DIR_TS = 3 +}; + +struct TSPEC_INFO { + TIMER_T rAddTsTimer; + UINT_8 ucToken; + BOOLEAN fgUapsd; + ENUM_ACI_T eAC:8; + enum TSPEC_DIR eDir:8; + enum QOS_TS_STATE eState:8; + /* debug information */ + UINT_16 u2MediumTime; + UINT_32 u4PhyRate; +}; + +struct TSM_TRIGGER_COND { + UINT_8 ucCondition; + UINT_8 ucAvgErrThreshold; + UINT_8 ucConsecutiveErr; + UINT_8 ucDelayThreshold; + UINT_8 ucMeasureCount; + /* In this time frame, for one condition, only once report is allowed */ + UINT_8 ucTriggerTimeout; +}; + +struct RM_TSM_REQ { + UINT_16 u2Duration; /* unit: TUs */ + UINT_8 aucPeerAddr[MAC_ADDR_LEN]; + UINT_8 ucToken; + UINT_8 ucTID; + UINT_8 ucACI; + UINT_8 ucB0Range; /* 2^(i-1)*ucB0Range =< delay < 2^i * ucB0Range */ + struct TSM_TRIGGER_COND rTriggerCond; +}; + +struct ACTIVE_RM_TSM_REQ { + LINK_ENTRY_T rLinkEntry; + struct RM_TSM_REQ *prTsmReq; + TIMER_T rTsmTimer; +}; + +struct WMM_INFO { + /* A TS is identified uniquely by its TID value within the context of the RA and TA + ** the index is TID for this array + */ + struct TSPEC_INFO arTsInfo[WMM_TSPEC_ID_NUM]; + LINK_T rActiveTsmReq; + OS_SYSTIME rTriggeredTsmRptTime; + TIMER_T rTsmTimer; +}; + +struct WMM_ADDTS_RSP_STEP_PARAM { + UINT_8 ucDlgToken; + UINT_8 ucStatusCode; + UINT_8 ucApsd; + enum TSPEC_DIR eDir:8; + UINT_16 u2EdcaLifeTime; + UINT_16 u2MediumTime; + UINT_32 u4PhyRate; +}; + +struct MSG_TS_OPERATE { + MSG_HDR_T rMsgHdr; + enum TSPEC_OP_CODE eOpCode; + UINT_8 ucTid; + PARAM_QOS_TSPEC rTspecParam; +}; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +extern UINT_8 const aucUp2ACIMap[8]; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define WMM_TSINFO_TRAFFIC_TYPE(tsinfo) (tsinfo & BIT(0)) +#define WMM_TSINFO_TSID(tsinfo) ((tsinfo & BITS(1, 4)) >> 1) +#define WMM_TSINFO_DIR(tsinfo) ((tsinfo & BITS(5, 6)) >> 5) +#define WMM_TSINFO_AC(tsinfo) ((tsinfo & BITS(7, 8)) >> 7) +#define WMM_TSINFO_PSB(tsinfo) ((tsinfo & BIT(10)) >> 10) +#define WMM_TSINFO_UP(tsinfo) ((tsinfo & BITS(11, 13)) >> 11) + +#define TSM_TRIGGER_CONDITION_ALL BITS(0, 2) +#define TSM_TRIGGER_AVG BIT(0) +#define TSM_TRIGGER_CONSECUTIVE BIT(1) +#define TSM_TIRGGER_DELAY BIT(2) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +VOID wmmFillTsinfo(P_PARAM_QOS_TSINFO prTsInfo, P_UINT_8 pucTsInfo); +VOID wmmSetupTspecTimeOut(P_ADAPTER_T prAdapter, ULONG ulParam); +void wmmStartTsmMeasurement(P_ADAPTER_T prAdapter, ULONG ulParam); +VOID wmmRunEventTSOperate(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr); +BOOLEAN wmmParseQosAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); +BOOLEAN +wmmParseTspecIE(P_ADAPTER_T prAdapter, PUINT_8 pucIE, P_PARAM_QOS_TSPEC prTspec); +VOID +wmmTspecSteps(P_ADAPTER_T prAdapter, UINT_8 ucTid, + enum TSPEC_OP_CODE eOpCode, VOID *prStepParams); +UINT_8 wmmHasActiveTspec(struct WMM_INFO *prWmmInfo); +VOID wmmNotifyDisconnected(P_ADAPTER_T prAdapter); +void wmmComposeTsmRpt(P_ADAPTER_T prAdapter, P_CMD_INFO_T prCmdInfo, PUINT_8 pucEventBuf); +VOID wmmInit(IN P_ADAPTER_T prAdapter); +VOID wmmUnInit(IN P_ADAPTER_T prAdapter); +BOOLEAN wmmTsmIsOngoing(P_ADAPTER_T prAdapter); +VOID wmmNotifyDisconnected(P_ADAPTER_T prAdapter); +VOID wmmRemoveAllTsmMeasurement(P_ADAPTER_T prAdapter, BOOLEAN fgOnlyTriggered); +UINT_8 wmmCalculateUapsdSetting(P_ADAPTER_T prAdapter); +UINT_32 wmmDumpActiveTspecs(P_ADAPTER_T prAdapter, PUINT_8 pucBuffer, UINT_16 u2BufferLen); +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/wnm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/wnm.h new file mode 100644 index 0000000000000..8429936e699c9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/mgmt/wnm.h @@ -0,0 +1,137 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _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; + +struct BSS_TRANSITION_MGT_PARAM_T { + /* for Query */ + UINT_8 ucDialogToken; + UINT_8 ucQueryReason; + /* for Request */ + UINT_8 ucRequestMode; + UINT_8 ucValidityInterval; + UINT_16 u2DisassocTimer; + UINT_16 u2TermDuration; + UINT_8 aucTermTsf[8]; + UINT_8 ucSessionURLLen; + UINT_8 aucSessionURL[255]; + /* for Respone */ + UINT_8 ucStatusCode; + UINT_8 ucTermDelay; + UINT_8 aucTargetBssid[MAC_ADDR_LEN]; + UINT_8 aucOurNeighborBss[CFG_MAX_NUM_BSS_LIST]; + PUINT_8 pucPeerNeighborBss; + UINT_16 u2OurNeighborBssLen; + UINT_16 u2PeerNeighborBssLen; +}; +/******************************************************************************* +* P U B 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 BTM_REQ_MODE_CAND_INCLUDED_BIT BIT(0) +#define BTM_REQ_MODE_ABRIDGED BIT(1) +#define BTM_REQ_MODE_DISC_IMM BIT(2) +#define BTM_REQ_MODE_BSS_TERM_INCLUDE BIT(3) +#define BTM_REQ_MODE_ESS_DISC_IMM BIT(4) + +#define BSS_TRANSITION_MGT_STATUS_ACCEPT 0 +#define BSS_TRANSITION_MGT_STATUS_UNSPECIFIED 1 +#define BSS_TRANSITION_MGT_STATUS_NEED_SCAN 2 +#define BSS_TRANSITION_MGT_STATUS_CAND_NO_CAPACITY 3 +#define BSS_TRANSITION_MGT_STATUS_TERM_UNDESIRED 4 +#define BSS_TRANSITION_MGT_STATUS_TERM_DELAY_REQUESTED 5 +#define BSS_TRANSITION_MGT_STATUS_CAND_LIST_PROVIDED 6 +#define BSS_TRANSITION_MGT_STATUS_CAND_NO_CANDIDATES 7 +#define BSS_TRANSITION_MGT_STATUS_LEAVING_ESS 8 + +/* 802.11v: define Transtion and Transition Query reasons */ +#define BSS_TRANSITION_BETTER_AP_FOUND 6 +#define BSS_TRANSITION_LOW_RSSI 16 +#define BSS_TRANSITION_INCLUDE_PREFER_CAND_LIST 19 +#define BSS_TRANSITION_LEAVING_ESS 20 + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +WLAN_STATUS +wnmRunEventTimgingMeasTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +VOID +wnmComposeTimingMeasFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN PFN_TX_DONE_HANDLER pfTxDoneHandler); + +VOID wnmTimingMeasRequest(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID wnmWNMAction(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID wnmReportTimingMeas(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIndex, IN UINT_32 u4ToD, IN UINT_32 u4ToA); + +VOID wnmRecvBTMRequest(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID wnmSendBTMQueryFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +VOID wnmSendBTMResponseFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +UINT_8 wnmGetBtmToken(VOID); + +#if WNM_UNIT_TEST +VOID wnmTimingMeasUnitTest1(P_ADAPTER_T prAdapter, UINT_8 ucStaRecIndex); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _WNM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/adapter.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/adapter.h new file mode 100644 index 0000000000000..3880b02b8b850 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/adapter.h @@ -0,0 +1,1140 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _ADAPTER_H +#define _ADAPTER_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#if CFG_SUPPORT_HOTSPOT_2_0 +#include "hs20.h" +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef struct _ENHANCE_MODE_DATA_STRUCT_T SDIO_CTRL_T, *P_SDIO_CTRL_T; + +struct ESS_SCAN_RESULT_T { + UINT_8 aucBSSID[MAC_ADDR_LEN]; + UINT_16 u2SSIDLen; + UINT_8 aucSSID[32]; +}; + +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; + + struct ESS_SCAN_RESULT_T arScanResultEss[CFG_MAX_NUM_BSS_LIST]; + UINT_32 u4ScanResultEssNum; + UINT_32 u4ScanDbgTimes1; + UINT_32 u4ScanDbgTimes2; + UINT_32 u4ScanDbgTimes3; + UINT_32 u4ScanDbgTimes4; + + /* 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; + ENUM_RECONNECT_LEVEL_T eReConnectLevel; + + 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; +#if (CFG_REFACTORY_PMKSA == 0) + /* Indicates if OKC feature is enabled in wpa_supplicant for this ESS */ + BOOLEAN fgOkcEnabled; + /* Indicates that there's a PMKSA associated with this ESS + ** in supplicant to generate PMKID for each BSS + */ + BOOLEAN fgOkcPmksaReady; +#endif + ENUM_PARAM_PHY_CONFIG_T eDesiredPhyConfig; + + /* Used for AP mode for desired channel and bandwidth */ + UINT_16 u2CountryCode; + UINT_16 u2CountryCodeBakup; + UINT_8 uc2G4BandwidthMode; /* 20/40M or 20M only */ + UINT_8 uc5GBandwidthMode; /* 20/40M or 20M only */ + + BOOLEAN fgTxShortGIDisabled; + BOOLEAN fgRxShortGIDisabled; + +#if CFG_SUPPORT_802_11D + BOOLEAN fgMultiDomainCapabilityEnabled; +#endif /* CFG_SUPPORT_802_11D */ + +#if 1 /* CFG_SUPPORT_WAPI */ + BOOLEAN fgWapiMode; + UINT_32 u4WapiSelectedGroupCipher; + UINT_32 u4WapiSelectedPairwiseCipher; + UINT_32 u4WapiSelectedAKMSuite; +#endif + + /* CR1486, CR1640 */ + /* for WPS, disable the privacy check for AP selection policy */ + BOOLEAN fgPrivacyCheckDisable; + + /* b0~3: trigger-en AC0~3. b4~7: delivery-en AC0~3 */ + UINT_8 bmfgApsdEnAc; + + /* for RSN info store, when upper layer set rsn info */ + RSN_INFO_T rRsnInfo; + +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE + BOOLEAN fgSecModeChangeStartTimer; +#endif + struct LINK_MGMT rBlackList; + uint8_t *pucAssocIEs; + size_t assocIeLen; +} 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 */ + +#if CFG_SUPPORT_RLM_ACT_NETWORK + UINT_8 ucNetActiveSrc; /* Trigger source: connect/scan/pno */ +#endif + + 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; + + enum ENUM_KEY_ACTION_TYPE_T eKeyAction; + + /*------------------------------------------------------------------------*/ + /* 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; +#if CFG_SUPPORT_P2P_ECSA + UINT_8 ucEcsaChannel; + UINT_8 ucOpClass; + UINT_8 ucSwitchCount; + UINT_8 ucSwitchMode; + BOOLEAN fgChanSwitching; +#endif + 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 */ + + /* Set scanning MAC OUI */ + UINT_8 fgIsScanOuiSet; + UINT_8 ucScanOui[MAC_OUI_LEN]; + + BOOLEAN fgObssActionForcedTo20M; /* GO only */ + BOOLEAN fgObssBeaconForcedTo20M; /* GO only */ + + /*------------------------------------------------------------------------*/ + /* HW Related Fields (Kevin) */ + /*------------------------------------------------------------------------*/ + UINT_8 ucHwDefaultFixedRateCode; /* The default rate code copied to MAC TX Desc */ + UINT_16 u2HwLPWakeupGuardTimeUsec; + + UINT_8 ucBssFreeQuota; /* The value is updated from FW */ +#if CFG_ENABLE_GTK_FRAME_FILTER + P_IPV4_NETWORK_ADDRESS_LIST prIpV4NetAddrList; +#endif + UINT_16 u2DeauthReason; + +#if (CFG_SUPPORT_TDLS == 1) + BOOLEAN fgTdlsIsProhibited; /* TRUE: AP prohibits TDLS links */ + BOOLEAN fgTdlsIsChSwProhibited; /* TRUE: AP prohibits TDLS chan switch */ +#endif /* CFG_SUPPORT_TDLS */ + +#if CFG_SUPPORT_RN + OS_SYSTIME rConnTime; + BOOLEAN fgDisConnReassoc; +#endif + + UINT_8 ucRoamSkipTimes; + BOOLEAN fgGoodRcpiArea; + BOOLEAN fgPoorRcpiArea; +#if CFG_SUPPORT_P2P_EAP_FAIL_WORKAROUND + BOOLEAN fgP2PPendingDeauth; + UINT_32 u4P2PEapTxDoneTime; +#endif + + BOOLEAN fgIsDelayIndication; + enum ENUM_IFTYPE eIftype; + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + struct AP_PMF_CFG rApPmfCfg; +#endif +}; + +struct ESS_CHNL_INFO { + UINT_8 ucChannel; + UINT_8 ucUtilization; + UINT_8 ucApNum; +}; + +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; +#if (CFG_REFACTORY_PMKSA == 0) + /* Stored the current bss wpa rsn cap filed, used for roaming policy */ + /* UINT_16 u2RsnCap; */ + TIMER_T rPreauthenticationTimer; +#endif + /* + * 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]; + +#if (CFG_REFACTORY_PMKSA == 0) + /* 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; +#else + LINK_T rPmkidCache; +#endif +#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 ESS_CHNL_INFO arCurEssChnlInfo[CFG_MAX_NUM_OF_CHNL_INFO]; + UINT_8 ucCurEssChnlInfoNum; + LINK_T rCurEssLink; + struct BSS_TRANSITION_MGT_PARAM_T rBTMParam; + UINT_8 ucKeyAlgorithmId; +}; + +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; + UINT_8 ucWithPhyTypeSpecificIE; + + ENUM_PHY_TYPE_INDEX_T eNonHTBasicPhyType2G4; /* Basic Phy Type used by SCN according + * to the set of Available PHY Types + */ + + ENUM_PARAM_PREAMBLE_TYPE_T ePreambleType; + ENUM_REGISTRY_FIXED_RATE_T eRateSetting; + + BOOLEAN fgIsShortSlotTimeOptionEnable; + /* User desired setting, but will honor the capability of AP */ + + BOOLEAN fgEnableJoinToHiddenSSID; + BOOLEAN fgSupportWZCDisassociation; + + BOOLEAN fgSupportQoS; + BOOLEAN fgSupportAmpduTx; + BOOLEAN fgSupportAmpduRx; + BOOLEAN fgSupportTspec; + BOOLEAN fgSupportUAPSD; + BOOLEAN fgSupportULPSMP; + UINT_8 u8SupportRxSgi20; /* 0: default 1: enable 2:disble */ + UINT_8 u8SupportRxSgi40; + UINT_8 u8SupportRxGf; + UINT_8 u8SupportRxSTBC; +#if CFG_SUPPORT_CFG_FILE + UINT_8 ucApWpsMode; + UINT_8 ucCert11nMode; + UINT_8 ucApChannel; +#endif +#if CFG_SUPPORT_CE_FCC_TXPWR_LIMIT + UINT_8 ucCeFccTxPwrLimit; + UINT_8 ucCeFccTxPwrLimitCck; + UINT_8 ucCeFccTxPwrLimitOfdmHt20; + UINT_8 ucCeFccTxPwrLimitHt40; +#endif +#if CFG_SLT_SUPPORT + SLT_INFO_T rSltInfo; +#endif +#if CFG_SUPPORT_HOTSPOT_2_0 + HS20_INFO_T rHS20Info; +#endif + + PARAM_GET_CHN_INFO rChnLoadInfo; + +#if CFG_RX_BA_REORDERING_ENHANCEMENT + BOOLEAN fgEnableReportIndependentPkt; +#endif +#if CFG_SUPPORT_MTK_SYNERGY + UINT_8 ucMtkOui; + UINT_32 u4MtkOuiCap; + UINT_8 aucMtkFeature[4]; +#endif + struct RADIO_MEASUREMENT_REQ_PARAMS rRmReqParams; + struct RADIO_MEASUREMENT_REPORT_PARAMS rRmRepParams; + + struct WMM_INFO rWmmInfo; + + UINT_8 aucAifsN[WMM_AC_INDEX_NUM]; + UINT_8 aucCwMin[WMM_AC_INDEX_NUM]; + UINT_16 au2CwMax[WMM_AC_INDEX_NUM]; + UINT_16 au2TxOp[WMM_AC_INDEX_NUM]; +} 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; + UINT_16 u2FwOwnVersionExtend; /*support version extended*/ +} 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 + + +#if CFG_SUPPORT_NCHO +typedef enum _ENUM_NCHO_ITEM_SET_TYPE_T { + ITEM_SET_TYPE_NUM, + ITEM_SET_TYPE_STR +} ENUM_NCHO_ITEM_SET_TYPE, *P_ENUM_NCHO_ITEM_SET_TYPE; + +typedef enum _ENUM_NCHO_BAND_T { + NCHO_BAND_AUTO = 0, + NCHO_BAND_5G, + NCHO_BAND_2G4, + NCHO_BAND_NUM +} ENUM_NCHO_BAND, *P_ENUM_NCHO_BAND; + +typedef enum _ENUM_NCHO_DFS_SCN_MODE_T { + NCHO_DFS_SCN_DISABLE = 0, + NCHO_DFS_SCN_ENABLE1, + NCHO_DFS_SCN_ENABLE2, + NCHO_DFS_SCN_NUM +} ENUM_NCHO_DFS_SCN_MODE, *P_ENUM_NCHO_DFS_SCN_MODE; + +typedef struct _CFG_NCHO_RE_ASSOC_T { + UINT_32 u4SsidLen; /*!< SSID length in bytes. Zero length is broadcast(any) SSID */ + UINT_8 aucSsid[ELEM_MAX_LEN_SSID]; + UINT_8 aucBssid[MAC_ADDR_LEN]; + UINT_32 u4CenterFreq; +} CFG_NCHO_RE_ASSOC_T, *PCFG_NCHO_RE_ASSOC_T; + +typedef struct _CFG_NCHO_SCAN_CHNL_T { + UINT_8 ucChannelListNum; + RF_CHANNEL_INFO_T arChnlInfoList[MAXIMUM_OPERATION_CHANNEL_LIST]; +} CFG_NCHO_SCAN_CHNL_T, *PCFG_NCHO_SCAN_CHNL_T; + +typedef struct _NCHO_ACTION_FRAME_PARAMS_T { + UCHAR aucBssid[MAC_ADDR_LEN]; + INT32 i4channel; + INT32 i4DwellTime; + INT32 i4len; + UCHAR aucData[520]; +} NCHO_ACTION_FRAME_PARAMS, *P_NCHO_ACTION_FRAME_PARAMS; + +typedef struct _NCHO_AF_INFO_T { + PUCHAR aucBssid; + INT32 i4channel; + INT32 i4DwellTime; + INT32 i4len; + PUCHAR pucData; +} NCHO_AF_INFO, *P_NCHO_AF_INFO; + +typedef struct _NCHO_INFO_T { + BOOLEAN fgECHOEnabled; + BOOLEAN fgChGranted; + BOOLEAN fgIsSendingAF; + INT32 i4RoamTrigger; /* db */ + INT32 i4RoamDelta; /* db */ + UINT32 u4RoamScanPeriod; /* ms */ + UINT32 u4ScanChannelTime; /* ms */ + UINT32 u4ScanHomeTime; /* ms */ + UINT32 u4ScanHomeawayTime; /* ms */ + UINT32 u4ScanNProbes; + UINT32 u4WesMode; + ENUM_NCHO_BAND eBand; + ENUM_NCHO_DFS_SCN_MODE eDFSScnMode; + UINT32 u4RoamScanControl; + CFG_NCHO_SCAN_CHNL_T rRoamScnChnl; + NCHO_ACTION_FRAME_PARAMS rParamActionFrame; +} NCHO_INFO, *P_NCHO_INFO; +#endif + +/* + * State Machine: + * --> STOP: No Tx/Rx traffic + * -----> clear RUNNING + * --> DISABLE: Screen is off + * --> ENABLE: Screen is on && Tx/Rx traffic is active + * -----> clear DISABLE + * --> RUNNING: Screen was on && Tx/Rx was ongoing + */ +struct PERF_MONITOR_T { + TIMER_T rPerfMonTimer; + ULONG ulPerfMonFlag; + ULONG ulLastTxBytes; + ULONG ulLastRxBytes; + ULONG ulP2PLastTxBytes; + ULONG ulP2PLastRxBytes; + ULONG ulThroughput; /* in bps */ + UINT32 u4UpdatePeriod; /* in ms */ + UINT32 u4TarPerfLevel; + UINT32 u4CurrPerfLevel; + UINT8 u1ShutdownCoreCount; +}; + +/* + * 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]; + + ENUM_BAND_T aeSetBand[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 + +#if (CFG_REFACTORY_PMKSA == 0) + /* Buffer for Authentication Event */ + /* Move to glue layer and refine the kal function */ + /* Reference to rsnGeneratePmkidIndication function at rsn.c */ + UINT_8 aucIndicationEventBuffer[(CFG_MAX_PMKID_CACHE * 20) + 8]; +#endif + UINT_32 u4IntStatus; + + ENUM_ACPI_STATE_T rAcpiState; + + BOOLEAN fgIsIntEnable; + BOOLEAN fgIsIntEnableWithLPOwnSet; + + BOOLEAN fgIsFwOwn; + BOOLEAN fgWiFiInSleepyState; + + UINT_32 u4PwrCtrlBlockCnt; + + QUE_T rPendingCmdQueue; + + P_GLUE_INFO_T prGlueInfo; + + UINT_8 ucCmdSeqNum; + UINT_8 ucTxSeqNum; + +#if 1 /* CFG_SUPPORT_WAPI */ + BOOLEAN fgUseWapi; +#endif + + /* RF Test flags */ + BOOLEAN fgTestMode; + + /* WLAN Info for DRIVER_CORE OID query */ + WLAN_INFO_T rWlanInfo; + +#if CFG_ENABLE_WIFI_DIRECT + BOOLEAN fgIsP2PRegistered; + ENUM_NET_REG_STATE_T rP2PNetRegState; + BOOLEAN fgIsWlanLaunched; + P_P2P_INFO_T prP2pInfo; +#if CFG_SUPPORT_P2P_RSSI_QUERY + OS_SYSTIME rP2pLinkQualityUpdateTime; + BOOLEAN fgIsP2pLinkQualityValid; + EVENT_LINK_QUALITY rP2pLinkQuality; +#endif + + /* FSM Timer */ + TIMER_T rP2pFsmTimeoutTimer; +#endif + + TIMER_T rTdlsStateTimer; + + /* Online Scan Option */ + BOOLEAN fgEnOnlineScan; + + /* Online Scan Option */ + BOOLEAN fgDisBcnLostDetection; + + /* MAC address */ + PARAM_MAC_ADDRESS rMyMacAddr; + + /* Wake-up Event for WOL */ + UINT_32 u4WakeupEventEnable; + + /* Event Buffering */ + EVENT_STATISTICS rStatStruct; + OS_SYSTIME rStatUpdateTime; + BOOLEAN fgIsStatValid; + + EVENT_LINK_QUALITY rLinkQuality; + OS_SYSTIME rLinkQualityUpdateTime; + BOOLEAN fgIsLinkQualityValid; + OS_SYSTIME rLinkRateUpdateTime; + BOOLEAN fgIsLinkRateValid; + + /* WIFI_VAR_T */ + WIFI_VAR_T rWifiVar; + + /* MTK WLAN NIC driver IEEE 802.11 MIB */ + IEEE_802_11_MIB_T rMib; + + /* Mailboxs for inter-module communication */ + MBOX_T arMbox[MBOX_ID_TOTAL_NUM]; + + /* Timers for OID Pending Handling */ + TIMER_T rOidTimeoutTimer; + + TIMER_T rReturnIndicatedRfbListTimer; + + /* Root Timer for cnm_timer module */ + ROOT_TIMER rRootTimer; + + /* RLM maintenance */ + ENUM_CHNL_EXT_T eRfSco; + ENUM_SYS_PROTECT_MODE_T eSysProtectMode; + ENUM_GF_MODE_T eSysHtGfMode; + ENUM_RIFS_MODE_T eSysTxRifsMode; + ENUM_SYS_PCO_PHASE_T eSysPcoPhase; + + P_DOMAIN_INFO_ENTRY prDomainInfo; + + /* QM */ + QUE_MGT_T rQM; + + CNM_INFO_T rCnmInfo; + + UINT_32 u4PowerMode; + + UINT_32 u4CtiaPowerMode; + BOOLEAN fgEnCtiaPowerMode; + + UINT_32 fgEnArpFilter; + + UINT_32 u4UapsdAcBmp; + + UINT_32 u4MaxSpLen; + + UINT_32 u4PsCurrentMeasureEn; + + /* Version Information */ + WIFI_VER_INFO_T rVerInfo; + + /* 5GHz support (from F/W) */ + BOOLEAN fgIsHw5GBandDisabled; + BOOLEAN fgEnable5GBand; + BOOLEAN fgIsEepromUsed; + BOOLEAN fgIsEfuseValid; + BOOLEAN fgIsEmbbededMacAddrValid; + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + BOOLEAN fgIsPowerLimitTableValid; +#endif + + /* Packet Forwarding Tracking */ + INT_32 i4PendingFwdFrameCount; + +#if CFG_SUPPORT_RDD_TEST_MODE + UINT_8 ucRddStatus; +#endif + + BOOLEAN fgDisStaAgingTimeoutDetection; +#if CFG_SUPPORT_CFG_FILE + P_WLAN_CFG_T prWlanCfg; + WLAN_CFG_T rWlanCfg; +#endif +#if CFG_SPM_WORKAROUND_FOR_HOTSPOT + KAL_WAKE_LOCK_T *rApWakeLock; +#endif + UINT_32 u4FwCompileFlag0; + UINT_32 u4FwCompileFlag1; + KAL_WAKE_LOCK_T *rTxThreadWakeLock; + KAL_WAKE_LOCK_T *rAhbIsrWakeLock; + +#if CFG_SUPPORT_ROAMING_ENC + BOOLEAN fgIsRoamingEncEnabled; +#endif /* CFG_SUPPORT_ROAMING_ENC */ + +#if (CFG_SUPPORT_TDLS == 1) + BOOLEAN fgTdlsIsSup; +#endif /* CFG_SUPPORT_TDLS */ + + UINT_8 ucScanTime; + +#if CFG_SUPPORT_DBG_POWERMODE + BOOLEAN fgEnDbgPowerMode; /* dbg privilege power mode, always keep in active */ +#endif +#if CFG_SUPPORT_NCHO /* NCHO information */ + NCHO_INFO rNchoInfo; +#endif + UINT_32 u4AirDelayTotal; /* dbg privilege power mode, always keep in active */ + ULONG ulSuspendFlag; + UINT_8 ucFlushCount; /*FW flush packet count*/ + struct PERF_MONITOR_T rPerMonitor; + +#ifdef CFG_TC1_FEATURE /* for Passive Scan */ + UINT_8 ucScanType; +#endif + + /* NLO Timer */ + TIMER_T rScanNloTimeoutTimer; + + struct WLAN_DEBUG_INFO rDebugInfo; + + OS_SYSTIME rStasEnvReportDetectTime; + + UINT_32 u4QmRxBaMissTimeout; + BOOLEAN fgEnCfg80211Scan; + +#if CFG_SUPPORT_GAMING_MODE + BOOLEAN fgEnGamingMode; +#endif +#if CFG_SUPPORT_OSHARE + BOOLEAN fgEnOshareMode; +#endif +}; /* end of _ADAPTER_T */ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define SUSPEND_FLAG_FOR_WAKEUP_REASON (0) +#define SUSPEND_FLAG_CLEAR_WHEN_RESUME (1) + +/*----------------------------------------------------------------------------*/ +/* Macros for BSS_INFO_T - Flag of Net Active */ +/*----------------------------------------------------------------------------*/ +#define IS_NET_ACTIVE(_prAdapter, _NetTypeIndex) \ + (_prAdapter->rWifiVar.arBssInfo[(_NetTypeIndex)].fgIsNetActive) +#define IS_BSS_ACTIVE(_prBssInfo) ((_prBssInfo)->fgIsNetActive) + +#define IS_BSS_AIS(_prBssInfo) \ + ((_prBssInfo)->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) + +#define IS_AIS_ACTIVE(_prAdapter) IS_NET_ACTIVE(_prAdapter, NETWORK_TYPE_AIS_INDEX) +#define IS_P2P_ACTIVE(_prAdapter) IS_NET_ACTIVE(_prAdapter, NETWORK_TYPE_P2P_INDEX) +#define IS_BOW_ACTIVE(_prAdapter) IS_NET_ACTIVE(_prAdapter, NETWORK_TYPE_BOW_INDEX) + +#define SET_NET_ACTIVE(_prAdapter, _NetTypeIndex) \ + {_prAdapter->rWifiVar.arBssInfo[(_NetTypeIndex)].fgIsNetActive = TRUE; } + +#define UNSET_NET_ACTIVE(_prAdapter, _NetTypeIndex) \ + {_prAdapter->rWifiVar.arBssInfo[(_NetTypeIndex)].fgIsNetActive = FALSE; } + +#define BSS_INFO_INIT(_prAdapter, _NetTypeIndex) \ + { UINT_8 _aucZeroMacAddr[] = NULL_MAC_ADDR; \ + P_BSS_INFO_T _prBssInfo = &(_prAdapter->rWifiVar.arBssInfo[(_NetTypeIndex)]); \ + \ + _prBssInfo->eConnectionState = PARAM_MEDIA_STATE_DISCONNECTED; \ + _prBssInfo->eConnectionStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; \ + _prBssInfo->eCurrentOPMode = OP_MODE_INFRASTRUCTURE; \ + _prBssInfo->fgIsNetActive = FALSE; \ + _prBssInfo->ucNetTypeIndex = (_NetTypeIndex); \ + _prBssInfo->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_RESERVED; \ + COPY_MAC_ADDR(_prBssInfo->aucBSSID, _aucZeroMacAddr); \ + LINK_INITIALIZE(&_prBssInfo->rStaRecOfClientList); \ + _prBssInfo->fgIsBeaconActivated = FALSE; \ + _prBssInfo->ucHwDefaultFixedRateCode = RATE_CCK_1M_LONG; \ + _prBssInfo->fgIsNetAbsent = FALSE; \ + } + +#if CFG_ENABLE_BT_OVER_WIFI +#define BOW_BSS_INFO_INIT(_prAdapter, _NetTypeIndex) \ + { \ + P_BSS_INFO_T _prBssInfo = &(_prAdapter->rWifiVar.arBssInfo[(_NetTypeIndex)]); \ + \ + _prBssInfo->eConnectionState = PARAM_MEDIA_STATE_DISCONNECTED; \ + _prBssInfo->eConnectionStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; \ + _prBssInfo->eCurrentOPMode = OP_MODE_BOW; \ + _prBssInfo->ucNetTypeIndex = (_NetTypeIndex); \ + _prBssInfo->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_RESERVED; \ + LINK_INITIALIZE(&_prBssInfo->rStaRecOfClientList); \ + _prBssInfo->fgIsBeaconActivated = TRUE; \ + _prBssInfo->ucHwDefaultFixedRateCode = RATE_CCK_1M_LONG; \ + _prBssInfo->fgIsNetAbsent = FALSE; \ + } +#endif + +#define PERF_MON_DISABLE_BIT (0) +#define PERF_MON_STOP_BIT (1) +#define PERF_MON_RUNNING_BIT (2) + +#define THROUGHPUT_L1_THRESHOLD (20*1024*1024) +#define THROUGHPUT_L2_THRESHOLD (40*1024*1024) +#define THROUGHPUT_L3_THRESHOLD (60*1024*1024) +#define THROUGHPUT_L4_THRESHOLD (135*1024*1024) + +#define THROUGHPUT_AP_L1_THRESHOLD (5*1024*1024) +#define THROUGHPUT_AP_L2_THRESHOLD (10*1024*1024) +#define THROUGHPUT_AP_L3_THRESHOLD (60*1024*1024) +#define THROUGHPUT_AP_L4_THRESHOLD (135*1024*1024) + + +#define THROUGHPUT_SHUTDOWN_CORE_COUNT 5 + +/*----------------------------------------------------------------------------*/ +/* Macros for Power State */ +/*----------------------------------------------------------------------------*/ +#define SET_NET_PWR_STATE_IDLE(_prAdapter, _NetTypeIndex) \ + {_prAdapter->rWifiVar.aePwrState[(_NetTypeIndex)] = PWR_STATE_IDLE; } + +#define SET_NET_PWR_STATE_ACTIVE(_prAdapter, _NetTypeIndex) \ + {_prAdapter->rWifiVar.aePwrState[(_NetTypeIndex)] = PWR_STATE_ACTIVE; } + +#define SET_NET_PWR_STATE_PS(_prAdapter, _NetTypeIndex) \ + {_prAdapter->rWifiVar.aePwrState[(_NetTypeIndex)] = PWR_STATE_PS; } + +#define IS_NET_PWR_STATE_ACTIVE(_prAdapter, _NetTypeIndex) \ + (_prAdapter->rWifiVar.aePwrState[(_NetTypeIndex)] == PWR_STATE_ACTIVE) + +#define IS_NET_PWR_STATE_IDLE(_prAdapter, _NetTypeIndex) \ + (_prAdapter->rWifiVar.aePwrState[(_NetTypeIndex)] == PWR_STATE_IDLE) + +#define IS_SCN_PWR_STATE_ACTIVE(_prAdapter) \ + (_prAdapter->rWifiVar.rScanInfo.eScanPwrState == SCAN_PWR_STATE_ACTIVE) + +#define IS_SCN_PWR_STATE_IDLE(_prAdapter) \ + (_prAdapter->rWifiVar.rScanInfo.eScanPwrState == SCAN_PWR_STATE_IDLE) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _ADAPTER_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/bow.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/bow.h new file mode 100644 index 0000000000000..3d515943d7a04 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/bow.h @@ -0,0 +1,224 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _BOW_H_ +#define _BOW_H_ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define BOWDEVNAME "bow0" + +#define MAX_BOW_NUMBER_OF_CHANNEL_2G4 14 +#define MAX_BOW_NUMBER_OF_CHANNEL_5G 4 +/* (MAX_BOW_NUMBER_OF_CHANNEL_2G4 + MAX_BOW_NUMBER_OF_CHANNEL_5G) */ +#define MAX_BOW_NUMBER_OF_CHANNEL 18 + +#define MAX_ACTIVITY_REPORT 2 +#define MAX_ACTIVITY_REPROT_TIME 660 + +#define ACTIVITY_REPORT_STATUS_SUCCESS 0 +#define ACTIVITY_REPORT_STATUS_FAILURE 1 +#define ACTIVITY_REPORT_STATUS_TIME_INVALID 2 +#define ACTIVITY_REPORT_STATUS_OTHERS 3 + +#define ACTIVITY_REPORT_SCHEDULE_UNKNOWN 0 /* Does not know the schedule of the interference */ +#define ACTIVITY_REPORT_SCHEDULE_KNOWN 1 + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef struct _BT_OVER_WIFI_COMMAND_HEADER_T { + UINT_8 ucCommandId; + UINT_8 ucSeqNumber; + UINT_16 u2PayloadLength; +} AMPC_COMMAND_HEADER_T, *P_AMPC_COMMAND_HEADER_T; + +typedef struct _BT_OVER_WIFI_COMMAND { + AMPC_COMMAND_HEADER_T rHeader; + UINT_8 aucPayload[0]; +} AMPC_COMMAND, *P_AMPC_COMMAND; + +typedef struct _BT_OVER_WIFI_EVENT_HEADER_T { + UINT_8 ucEventId; + UINT_8 ucSeqNumber; + UINT_16 u2PayloadLength; +} AMPC_EVENT_HEADER_T, *P_AMPC_EVENT_HEADER_T; + +typedef struct _BT_OVER_WIFI_EVENT { + AMPC_EVENT_HEADER_T rHeader; + UINT_8 aucPayload[0]; +} AMPC_EVENT, *P_AMPC_EVENT; + +typedef struct _CHANNEL_DESC_T { + UINT_8 ucChannelBand; + UINT_8 ucChannelNum; +} CHANNEL_DESC, P_CHANNEL_DESC; + +/* Command Structures */ +typedef struct _BOW_SETUP_CONNECTION { +/* Fixed to 2.4G */ + UINT_8 ucChannelNum; + UINT_8 ucReserved1; + UINT_8 aucPeerAddress[6]; + UINT_16 u2BeaconInterval; + UINT_8 ucTimeoutDiscovery; + UINT_8 ucTimeoutInactivity; + UINT_8 ucRole; + UINT_8 ucPAL_Capabilities; + INT_8 cMaxTxPower; + UINT_8 ucReserved2; + +/* Pending, for future BOW 5G supporting. */ +/* + * UINT_8 aucPeerAddress[6]; + * UINT_16 u2BeaconInterval; + * UINT_8 ucTimeoutDiscovery; + * UINT_8 ucTimeoutInactivity; + * UINT_8 ucRole; + * UINT_8 ucPAL_Capabilities; + * INT_8 cMaxTxPower; + * UINT_8 ucChannelListNum; + * CHANNEL_DESC arChannelList[1]; + */ +} BOW_SETUP_CONNECTION, *P_BOW_SETUP_CONNECTION; + +typedef struct _BOW_DESTROY_CONNECTION { + UINT_8 aucPeerAddress[6]; + UINT_8 aucReserved[2]; +} BOW_DESTROY_CONNECTION, *P_BOW_DESTROY_CONNECTION; + +typedef struct _BOW_SET_PTK { + UINT_8 aucPeerAddress[6]; + UINT_8 aucReserved[2]; + UINT_8 aucTemporalKey[16]; +} BOW_SET_PTK, *P_BOW_SET_PTK; + +typedef struct _BOW_READ_RSSI { + UINT_8 aucPeerAddress[6]; + UINT_8 aucReserved[2]; +} BOW_READ_RSSI, *P_BOW_READ_RSSI; + +typedef struct _BOW_READ_LINK_QUALITY { + UINT_8 aucPeerAddress[6]; + UINT_8 aucReserved[2]; +} BOW_READ_LINK_QUALITY, *P_BOW_READ_LINK_QUALITY; + +typedef struct _BOW_SHORT_RANGE_MODE { + UINT_8 aucPeerAddress[6]; + INT_8 cTxPower; + UINT_8 ucReserved; +} BOW_SHORT_RANGE_MODE, *P_BOW_SHORT_RANGE_MODE; + +/* Event Structures */ +typedef struct _BOW_COMMAND_STATUS { + UINT_8 ucStatus; + UINT_8 ucReserved[3]; +} BOW_COMMAND_STATUS, *P_BOW_COMMAND_STATUS; + +typedef struct _BOW_MAC_STATUS { + UINT_8 aucMacAddr[6]; + UINT_8 ucAvailability; + UINT_8 ucNumOfChannel; + CHANNEL_DESC arChannelList[MAX_BOW_NUMBER_OF_CHANNEL]; +} BOW_MAC_STATUS, *P_BOW_MAC_STATUS; + +typedef struct _BOW_LINK_CONNECTED { + CHANNEL_DESC rChannel; + UINT_8 aucReserved; + UINT_8 aucPeerAddress[6]; +} BOW_LINK_CONNECTED, *P_BOW_LINK_CONNECTED; + +typedef struct _BOW_LINK_DISCONNECTED { + UINT_8 ucReason; + UINT_8 aucReserved; + UINT_8 aucPeerAddress[6]; +} BOW_LINK_DISCONNECTED, *P_BOW_LINK_DISCONNECTED; + +typedef struct _BOW_RSSI { + INT_8 cRssi; + UINT_8 aucReserved[3]; +} BOW_RSSI, *P_BOW_RSSI; + +typedef struct _BOW_LINK_QUALITY { + UINT_8 ucLinkQuality; + UINT_8 aucReserved[3]; +} BOW_LINK_QUALITY, *P_BOW_LINK_QUALITY; + +typedef enum _ENUM_BOW_CMD_ID_T { + BOW_CMD_ID_GET_MAC_STATUS = 1, + BOW_CMD_ID_SETUP_CONNECTION, + BOW_CMD_ID_DESTROY_CONNECTION, + BOW_CMD_ID_SET_PTK, + BOW_CMD_ID_READ_RSSI, + BOW_CMD_ID_READ_LINK_QUALITY, + BOW_CMD_ID_SHORT_RANGE_MODE, + BOW_CMD_ID_GET_CHANNEL_LIST, +} ENUM_BOW_CMD_ID_T, *P_ENUM_BOW_CMD_ID_T; + +typedef enum _ENUM_BOW_EVENT_ID_T { + BOW_EVENT_ID_COMMAND_STATUS = 1, + BOW_EVENT_ID_MAC_STATUS, + BOW_EVENT_ID_LINK_CONNECTED, + BOW_EVENT_ID_LINK_DISCONNECTED, + BOW_EVENT_ID_RSSI, + BOW_EVENT_ID_LINK_QUALITY, + BOW_EVENT_ID_CHANNEL_LIST, + BOW_EVENT_ID_CHANNEL_SELECTED, +} ENUM_BOW_EVENT_ID_T, *P_ENUM_BOW_EVENT_ID_T; + +typedef enum _ENUM_BOW_DEVICE_STATE { + BOW_DEVICE_STATE_DISCONNECTED = 0, + BOW_DEVICE_STATE_DISCONNECTING, + BOW_DEVICE_STATE_ACQUIRING_CHANNEL, + BOW_DEVICE_STATE_STARTING, + BOW_DEVICE_STATE_SCANNING, + BOW_DEVICE_STATE_CONNECTING, + BOW_DEVICE_STATE_CONNECTED, + BOW_DEVICE_STATE_NUM +} ENUM_BOW_DEVICE_STATE, *P_ENUM_BOW_DEVICE_STATE; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#endif /*_BOW_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/cmd_buf.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/cmd_buf.h new file mode 100644 index 0000000000000..bf4b666fcdbda --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/cmd_buf.h @@ -0,0 +1,128 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _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_KEY_IOCTL, + 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; + UINT_32 u4InqueTime; + UINT_32 u4SendToFwTime; + UINT_32 u4FwResponseTime; +}; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID cmdBufInitialize(IN P_ADAPTER_T prAdapter); + +P_CMD_INFO_T cmdBufAllocateCmdInfo(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Length); + +VOID cmdBufFreeCmdInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +/*----------------------------------------------------------------------------*/ +/* Routines for CMDs */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanSendSetQueryCmd(IN P_ADAPTER_T prAdapter, + UINT_8 ucCID, + BOOLEAN fgSetQuery, + BOOLEAN fgNeedResp, + BOOLEAN fgIsOid, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + UINT_32 u4SetQueryInfoLen, + PUINT_8 pucInfoBuffer, OUT PVOID pvSetQueryBuffer, IN UINT_32 u4SetQueryBufferLen); +VOID cmdBufDumpCmdQueue(P_QUE_T prQueue, CHAR *queName); +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _CMD_BUF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/hal.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/hal.h new file mode 100644 index 0000000000000..76f456978ba5b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/hal.h @@ -0,0 +1,555 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _HAL_H +#define _HAL_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/* Macros for flag operations for the Adapter structure */ +#define HAL_SET_FLAG(_M, _F) ((_M)->u4HwFlags |= (_F)) +#define HAL_CLEAR_FLAG(_M, _F) ((_M)->u4HwFlags &= ~(_F)) +#define HAL_TEST_FLAG(_M, _F) ((_M)->u4HwFlags & (_F)) +#define HAL_TEST_FLAGS(_M, _F) (((_M)->u4HwFlags & (_F)) == (_F)) + +#if defined(_HIF_SDIO) +#define HAL_MCR_RD(_prAdapter, _u4Offset, _pu4Value) \ +do { \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (kalDevRegRead(_prAdapter->prGlueInfo, _u4Offset, _pu4Value) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + /* DBGLOG(HAL, ERROR, ("HAL_MCR_RD access fail! 0x%x: 0x%x\n", */ \ + /* (UINT32)_u4Offset, (UINT32)*_pu4Value)); */ \ + } \ + } else { \ + /* DBGLOG(HAL, WARN, ("ignore HAL_MCR_RD access! 0x%x\n", (UINT32)_u4Offset)); */ \ + } \ +} while (0) + +#define HAL_MCR_WR(_prAdapter, _u4Offset, _u4Value) \ +do { \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (kalDevRegWrite(_prAdapter->prGlueInfo, _u4Offset, _u4Value) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + /* DBGLOG(HAL, ERROR, ("HAL_MCR_WR access fail! 0x%x: 0x%x\n", */ \ + /* (UINT32)_u4Offset, (UINT32)_u4Value)); */ \ + } \ + } else { \ + /* DBGLOG(HAL, WARN, ("ignore HAL_MCR_WR access! 0x%x: 0x%x\n", */ \ + /* (UINT32)_u4Offset, (UINT32)_u4Value)); */ \ + } \ +} while (0) + +#define HAL_PORT_RD(_prAdapter, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ +{ \ + /*fgResult = FALSE; */\ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (kalDevPortRead(_prAdapter->prGlueInfo, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ + == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, "HAL_PORT_RD access fail! 0x%x\n", _u4Port); \ + GL_RESET_TRIGGER(_prAdapter, RST_FLAG_CHIP_RESET); \ + } \ + 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); \ + GL_RESET_TRIGGER(_prAdapter, RST_FLAG_CHIP_RESET); \ + } \ + else { \ + /*fgResult = TRUE;*/ } \ + } else { \ + DBGLOG(HAL, WARN, "ignore HAL_PORT_WR access! 0x%x\n", _u4Port); \ + } \ +} + +#if 0 /* only for SDIO */ +#define HAL_BYTE_WR(_prAdapter, _u4Port, _ucBuf) \ +{ \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (kalDevWriteWithSdioCmd52(_prAdapter->prGlueInfo, _u4Port, _ucBuf) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, "HAL_BYTE_WR access fail! 0x%x\n", _u4Port); \ + } \ + else { \ + /* Todo:: Nothing*/ \ + } \ + } \ + else { \ + DBGLOG(HAL, WARN, "ignore HAL_BYTE_WR access! 0x%x\n", _u4Port); \ + } \ +} +#endif + +#define HAL_DRIVER_OWN_BY_SDIO_CMD52(_prAdapter, _pfgDriverIsOwnReady) \ +{ \ + UINT_8 ucBuf = BIT(1); \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (kalDevReadAfterWriteWithSdioCmd52(_prAdapter->prGlueInfo, MCR_WHLPCR_BYTE1, &ucBuf, 1) \ + == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, "kalDevReadAfterWriteWithSdioCmd52 access fail!\n"); \ + } \ + else { \ + *_pfgDriverIsOwnReady = (ucBuf & BIT(0)) ? TRUE : FALSE; \ + } \ + } else { \ + DBGLOG(HAL, WARN, "ignore HAL_DRIVER_OWN_BY_SDIO_CMD52 access!\n"); \ + } \ +} + +#else /* #if defined(_HIF_SDIO) */ +#define HAL_MCR_RD(_prAdapter, _u4Offset, _pu4Value) \ +{ \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (kalDevRegRead(_prAdapter->prGlueInfo, _u4Offset, _pu4Value) \ + == FALSE) \ + fgIsBusAccessFailed = TRUE; \ +} + +#define HAL_MCR_WR(_prAdapter, _u4Offset, _u4Value) \ +{ \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (kalDevRegWrite(_prAdapter->prGlueInfo, _u4Offset, _u4Value) \ + == FALSE) \ + fgIsBusAccessFailed = TRUE; \ +} + +#define HAL_PORT_RD(_prAdapter, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ +{ \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (kalDevPortRead(_prAdapter->prGlueInfo, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ + == FALSE) \ + fgIsBusAccessFailed = TRUE; \ +} + +#define HAL_PORT_WR(_prAdapter, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ +{ \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (kalDevPortWrite(_prAdapter->prGlueInfo, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ + == FALSE) \ + fgIsBusAccessFailed = TRUE; \ +} + +#if 0 /* only for SDIO */ +#define HAL_BYTE_WR(_prAdapter, _u4Port, _ucBuf) \ +{ \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ +kalDevWriteWithSdioCmd52(_prAdapter->prGlueInfo, _u4Port, _ucBuf); \ +} +#endif + +#endif /* #if defined(_HIF_SDIO) */ + +#define HAL_READ_RX_PORT(prAdapter, u4PortId, u4Len, pvBuf, _u4ValidBufSize) \ +{ \ + ASSERT(u4PortId < 2); \ + HAL_PORT_RD(prAdapter, \ + ((u4PortId == 0) ? MCR_WRDR0 : MCR_WRDR1), \ + u4Len, \ + pvBuf, \ + _u4ValidBufSize/*temp!!*//*4Kbyte*/); \ +} + +#define HAL_WRITE_TX_PORT(_prAdapter, _ucTxPortIdx, _u4Len, _pucBuf, _u4ValidBufSize) \ +{ \ + ASSERT(_ucTxPortIdx < 2); \ + if ((_u4ValidBufSize - _u4Len) >= sizeof(UINT_32)) { \ + /* fill with single dword of zero as TX-aggregation termination */ \ + *(PUINT_32) (&((_pucBuf)[ALIGN_4(_u4Len)])) = 0; \ + } \ + HAL_PORT_WR(_prAdapter, \ + (_ucTxPortIdx == 0) ? MCR_WTDR0 : MCR_WTDR1, \ + _u4Len, \ + _pucBuf, \ + _u4ValidBufSize/*temp!!*//*4KByte*/); \ +} + +/* + * The macro to read the given MCR several times to check if the wait + * condition come true. + */ +#define HAL_MCR_RD_AND_WAIT(_pAdapter, _offset, _pReadValue, _waitCondition, _waitDelay, _waitCount, _status) \ +{ \ + UINT_32 count; \ + (_status) = FALSE; \ + for (count = 0; count < (_waitCount); count++) { \ + HAL_MCR_RD((_pAdapter), (_offset), (_pReadValue)); \ + if ((_waitCondition)) { \ + (_status) = TRUE; \ + break; \ + } \ + kalUdelay((_waitDelay)); \ + } \ +} + +/* + * The macro to write 1 to a R/S bit and read it several times to check if the + * command is done + */ +#define HAL_MCR_WR_AND_WAIT(_pAdapter, _offset, _writeValue, _busyMask, _waitDelay, _waitCount, _status) \ +{ \ + UINT_32 u4Temp; \ + UINT_32 u4Count = _waitCount; \ + (_status) = FALSE; \ + HAL_MCR_WR((_pAdapter), (_offset), (_writeValue)); \ + do { \ + kalUdelay((_waitDelay)); \ + HAL_MCR_RD((_pAdapter), (_offset), &u4Temp); \ + if (!(u4Temp & (_busyMask))) { \ + (_status) = TRUE; \ + break; \ + } \ + u4Count--; \ + } while (u4Count); \ +} + +#define HAL_GET_CHIP_ID_VER(_prAdapter, pu2ChipId, pu2Version) \ +{ \ + UINT_32 u4Value; \ + HAL_MCR_RD(_prAdapter, \ + MCR_WCIR, \ + &u4Value); \ + *pu2ChipId = (UINT_16)(u4Value & WCIR_CHIP_ID); \ + *pu2Version = (UINT_16)(u4Value & WCIR_REVISION_ID) >> 16; \ +} + +#define HAL_WAIT_WIFI_FUNC_READY(_prAdapter) \ +{ \ + UINT_32 u4Value; \ + UINT_32 i; \ + for (i = 0; i < 100; i++) { \ + HAL_MCR_RD(_prAdapter, \ + MCR_WCIR, \ + &u4Value); \ + if (u4Value & WCIR_WLAN_READY) { \ + break; \ + } \ + NdisMSleep(10); \ + } \ +} + +#define HAL_INTR_DISABLE(_prAdapter) \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHLPCR, \ + WHLPCR_INT_EN_CLR) + +#define HAL_INTR_ENABLE(_prAdapter) \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHLPCR, \ + WHLPCR_INT_EN_SET) + +#define HAL_INTR_ENABLE_AND_LP_OWN_SET(_prAdapter) \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHLPCR, \ + (WHLPCR_INT_EN_SET | WHLPCR_FW_OWN_REQ_SET)) + +#define HAL_LP_OWN_SET(_prAdapter) \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHLPCR, \ + WHLPCR_FW_OWN_REQ_SET) + +#define HAL_LP_OWN_CLR_OK(_prAdapter, _pfgResult) \ +{ \ + UINT_32 i; \ + UINT_32 u4RegValue; \ + UINT_32 u4LoopCnt = 2048 / 8; \ + *_pfgResult = TRUE; \ + /* Software get LP ownership */ \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHLPCR, \ + WHLPCR_FW_OWN_REQ_CLR) \ + for (i = 0; i < u4LoopCnt; i++) { \ + HAL_MCR_RD(_prAdapter, MCR_WHLPCR, &u4RegValue); \ + if (u4RegValue & WHLPCR_IS_DRIVER_OWN) { \ + break; \ + } \ + else { \ + kalUdelay(8); \ + } \ + } \ + if (i == u4LoopCnt) { \ + *_pfgResult = FALSE; \ + /*ERRORLOG(("LP cannot be own back (%ld)", u4LoopCnt));*/ \ + /* check the time of LP instructions need to perform from Sleep to On */ \ + /*ASSERT(0); */ \ + } \ +} + +#define HAL_GET_ABNORMAL_INTERRUPT_REASON_CODE(_prAdapter, pu4AbnormalReason) \ +{ \ + HAL_MCR_RD(_prAdapter, \ + MCR_WASR, \ + pu4AbnormalReason); \ +} + +#define HAL_DISABLE_RX_ENHANCE_MODE(_prAdapter) \ +{ \ + UINT_32 u4Value; \ + HAL_MCR_RD(_prAdapter, \ + MCR_WHCR, \ + &u4Value); \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHCR, \ + u4Value & ~WHCR_RX_ENHANCE_MODE_EN); \ +} + +#define HAL_ENABLE_RX_ENHANCE_MODE(_prAdapter) \ +{ \ + UINT_32 u4Value; \ + HAL_MCR_RD(_prAdapter, \ + MCR_WHCR, \ + &u4Value); \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHCR, \ + u4Value | WHCR_RX_ENHANCE_MODE_EN); \ +} + +#define HAL_CFG_MAX_HIF_RX_LEN_NUM(_prAdapter, _ucNumOfRxLen) \ +{ \ + UINT_32 u4Value, ucNum; \ + ucNum = ((_ucNumOfRxLen >= 16) ? 0 : _ucNumOfRxLen); \ + u4Value = 0; \ + HAL_MCR_RD(_prAdapter, \ + MCR_WHCR, \ + &u4Value); \ + u4Value &= ~WHCR_MAX_HIF_RX_LEN_NUM; \ + u4Value |= ((((UINT_32)ucNum) << 4) & WHCR_MAX_HIF_RX_LEN_NUM); \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHCR, \ + u4Value); \ +} + +#define HAL_SET_INTR_STATUS_READ_CLEAR(prAdapter) \ +{ \ + UINT_32 u4Value; \ + HAL_MCR_RD(prAdapter, \ + MCR_WHCR, \ + &u4Value); \ + HAL_MCR_WR(prAdapter, \ + MCR_WHCR, \ + u4Value & ~WHCR_W_INT_CLR_CTRL); \ + prAdapter->prGlueInfo->rHifInfo.fgIntReadClear = TRUE;\ +} + +#define HAL_SET_INTR_STATUS_WRITE_1_CLEAR(prAdapter) \ +{ \ + UINT_32 u4Value; \ + HAL_MCR_RD(prAdapter, \ + MCR_WHCR, \ + &u4Value); \ + HAL_MCR_WR(prAdapter, \ + MCR_WHCR, \ + u4Value | WHCR_W_INT_CLR_CTRL); \ + prAdapter->prGlueInfo->rHifInfo.fgIntReadClear = FALSE;\ +} + +/* + * Note: enhance mode structure may also carried inside the buffer, + * if the length of the buffer is long enough + */ +#define HAL_READ_INTR_STATUS(prAdapter, length, pvBuf) \ + HAL_PORT_RD(prAdapter, \ + MCR_WHISR, \ + length, \ + pvBuf, \ + length) + +#define HAL_READ_TX_RELEASED_COUNT(_prAdapter, aucTxReleaseCount) \ +{ \ + PUINT_32 pu4Value = (PUINT_32)aucTxReleaseCount; \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTSR0, \ + &pu4Value[0]); \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTSR1, \ + &pu4Value[1]); \ +} + +#define HAL_READ_RX_LENGTH(prAdapter, pu2Rx0Len, pu2Rx1Len) \ +{ \ + UINT_32 u4Value; \ + u4Value = 0; \ + HAL_MCR_RD(prAdapter, \ + MCR_WRPLR, \ + &u4Value); \ + *pu2Rx0Len = (UINT_16)u4Value; \ + *pu2Rx1Len = (UINT_16)(u4Value >> 16); \ +} +#define HAL_GET_APMCU_MEM(_prAdapter, _addr, _Offset, _index, _buf, _len) \ +{ \ + kalGetAPMCUMen(_prAdapter->prGlueInfo, _addr, _Offset, _index, _buf, _len); \ +} + +#define HAL_GET_INTR_STATUS_FROM_ENHANCE_MODE_STRUCT(pvBuf, u2Len, pu4Status) \ +{ \ + PUINT_32 pu4Buf = (PUINT_32)pvBuf; \ + *pu4Status = pu4Buf[0]; \ +} + +#define HAL_GET_TX_STATUS_FROM_ENHANCE_MODE_STRUCT(pvInBuf, pu4BufOut, u4LenBufOut) \ +{ \ + PUINT_32 pu4Buf = (PUINT_32)pvInBuf; \ + ASSERT(u4LenBufOut >= 8); \ + pu4BufOut[0] = pu4Buf[1]; \ + pu4BufOut[1] = pu4Buf[2]; \ +} + +#define HAL_GET_RX_LENGTH_FROM_ENHANCE_MODE_STRUCT(pvInBuf, pu2Rx0Num, au2Rx0Len, pu2Rx1Num, au2Rx1Len) \ +{ \ + PUINT_32 pu4Buf = (PUINT_32)pvInBuf; \ + ASSERT((sizeof(au2Rx0Len) / sizeof(UINT_16)) >= 16); \ + ASSERT((sizeof(au2Rx1Len) / sizeof(UINT_16)) >= 16); \ + *pu2Rx0Num = (UINT_16)pu4Buf[3]; \ + *pu2Rx1Num = (UINT_16)(pu4Buf[3] >> 16); \ + kalMemCopy(au2Rx0Len, &pu4Buf[4], 8); \ + kalMemCopy(au2Rx1Len, &pu4Buf[12], 8); \ +} + +#define HAL_GET_MAILBOX_FROM_ENHANCE_MODE_STRUCT(pvInBuf, pu4Mailbox0, pu4Mailbox1) \ +{ \ + PUINT_32 pu4Buf = (PUINT_32)pvInBuf; \ + *pu4Mailbox0 = (UINT_16)pu4Buf[21]; \ + *pu4Mailbox1 = (UINT_16)pu4Buf[22]; \ +} + +#define HAL_IS_TX_DONE_INTR(u4IntrStatus) \ + ((u4IntrStatus & WHISR_TX_DONE_INT) ? TRUE : FALSE) + +#define HAL_IS_RX_DONE_INTR(u4IntrStatus) \ + ((u4IntrStatus & (WHISR_RX0_DONE_INT | WHISR_RX1_DONE_INT)) ? TRUE : FALSE) + +#define HAL_IS_ABNORMAL_INTR(u4IntrStatus) \ + ((u4IntrStatus & WHISR_ABNORMAL_INT) ? TRUE : FALSE) + +#define HAL_IS_FW_OWNBACK_INTR(u4IntrStatus) \ + ((u4IntrStatus & WHISR_FW_OWN_BACK_INT) ? TRUE : FALSE) + +#define HAL_PUT_MAILBOX(prAdapter, u4MboxId, u4Data) \ +{ \ + ASSERT(u4MboxId < 2); \ + HAL_MCR_WR(prAdapter, \ + ((u4MboxId == 0) ? MCR_H2DSM0R : MCR_H2DSM1R), \ + u4Data); \ +} + +#define HAL_GET_MAILBOX(prAdapter, u4MboxId, pu4Data) \ +{ \ + ASSERT(u4MboxId < 2); \ + HAL_MCR_RD(prAdapter, \ + ((u4MboxId == 0) ? MCR_D2HRM0R : MCR_D2HRM1R), \ + pu4Data); \ +} + +#define HAL_SET_MAILBOX_READ_CLEAR(prAdapter, fgEnableReadClear) \ +{ \ + UINT_32 u4Value; \ + HAL_MCR_RD(prAdapter, MCR_WHCR, &u4Value);\ + HAL_MCR_WR(prAdapter, MCR_WHCR, \ + (fgEnableReadClear) ? \ + (u4Value | WHCR_W_MAILBOX_RD_CLR_EN) : \ + (u4Value & ~WHCR_W_MAILBOX_RD_CLR_EN)); \ + prAdapter->prGlueInfo->rHifInfo.fgMbxReadClear = fgEnableReadClear;\ +} + +#define HAL_GET_MAILBOX_READ_CLEAR(prAdapter) (prAdapter->prGlueInfo->rHifInfo.fgMbxReadClear) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _HAL_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/hif_rx.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/hif_rx.h new file mode 100644 index 0000000000000..25041d513936c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/hif_rx.h @@ -0,0 +1,175 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _HIF_RX_H +#define _HIF_RX_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/*! HIF_RX_HEADER_T */ +/* DW 0, Byte 1 */ +#define HIF_RX_HDR_PACKET_TYPE_MASK BITS(0, 1) +#define HIF_RX_HDR_SEC_MODE_MASK BITS(2, 5) +#define HIF_RX_HDR_SEC_MODE_OFFSET 2 + +/* DW 1, Byte 0 */ +#define HIF_RX_HDR_HEADER_LEN BITS(2, 7) +#define HIF_RX_HDR_HEADER_LEN_OFFSET 2 +#define HIF_RX_HDR_HEADER_OFFSET_MASK BITS(0, 1) + +/* DW 1, Byte 1 */ +#define HIF_RX_HDR_80211_HEADER_FORMAT BIT(0) +#define HIF_RX_HDR_DO_REORDER BIT(1) +#define HIF_RX_HDR_PAL BIT(2) +#define HIF_RX_HDR_TCL BIT(3) +#define HIF_RX_HDR_NETWORK_IDX_MASK BITS(4, 7) +#define HIF_RX_HDR_NETWORK_IDX_OFFSET 4 + +/* DW 1, Byte 2, 3 */ +#define HIF_RX_HDR_SEQ_NO_MASK BITS(0, 11) +#define HIF_RX_HDR_TID_MASK BITS(12, 14) +#define HIF_RX_HDR_TID_OFFSET 12 +#define HIF_RX_HDR_BAR_FRAME BIT(15) + +#define HIF_RX_HDR_FLAG_AMP_WDS BIT(0) +#define HIF_RX_HDR_FLAG_802_11_FORMAT BIT(1) +#define HIF_RX_HDR_FLAG_BAR_FRAME BIT(2) +#define HIF_RX_HDR_FLAG_DO_REORDERING BIT(3) +#define HIF_RX_HDR_FLAG_CTRL_WARPPER_FRAME BIT(4) + +#define HIF_RX_HW_APPENDED_LEN 4 + +/* For DW 2, Byte 3 - ucHwChannelNum */ +#define HW_CHNL_NUM_MAX_2G4 (14) +#define HW_CHNL_NUM_MAX_4G_5G (255 - HW_CHNL_NUM_MAX_2G4) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef struct _HIF_RX_HEADER_T { + UINT_16 u2PacketLen; + UINT_16 u2PacketType; + UINT_8 ucHerderLenOffset; + UINT_8 uc80211_Reorder_PAL_TCL; + UINT_16 u2SeqNoTid; + UINT_8 ucStaRecIdx; + UINT_8 ucRcpi; + UINT_8 ucHwChannelNum; + UINT_8 ucReserved; +} HIF_RX_HEADER_T, *P_HIF_RX_HEADER_T; + +typedef struct _HIF_RX_DESC_T { + UINT_8 ucOwn; + UINT_8 ucDescChksum; + UINT_8 ucEtherTypeOffset; + UINT_8 ucChkSumInfo; + UINT_32 u4NextDesc; + UINT_32 u4BufStartAddr; + UINT_16 u2RxBufLen; + UINT_16 u2Rsrv1; +} HIF_RX_DESC_T, *P_HIF_RX_DESC_T; + + +typedef enum _ENUM_HIF_RX_PKT_TYPE_T { + HIF_RX_PKT_TYPE_DATA = 0, + HIF_RX_PKT_TYPE_EVENT, + HIF_RX_PKT_TYPE_TX_LOOPBACK, + HIF_RX_PKT_TYPE_MANAGEMENT, + HIF_RX_PKT_TYPE_NUM +} ENUM_HIF_RX_PKT_TYPE_T, *P_ENUM_HIF_RX_PKT_TYPE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define HIF_RX_HDR_SIZE sizeof(HIF_RX_HEADER_T) + +#define HIF_RX_HDR_GET_80211_FLAG(_prHifRxHdr) \ + (((((_prHifRxHdr)->uc80211_Reorder_PAL_TCL) & HIF_RX_HDR_80211_HEADER_FORMAT) ? TRUE : FALSE)) +#define HIF_RX_HDR_GET_REORDER_FLAG(_prHifRxHdr) \ + (((((_prHifRxHdr)->uc80211_Reorder_PAL_TCL) & HIF_RX_HDR_DO_REORDER) ? TRUE : FALSE)) +#define HIF_RX_HDR_GET_PAL_FLAG(_prHifRxHdr) \ + (((((_prHifRxHdr)->uc80211_Reorder_PAL_TCL) & HIF_RX_HDR_PAL) ? TRUE : FALSE)) +#define HIF_RX_HDR_GET_TCL_FLAG(_prHifRxHdr) \ + (((((_prHifRxHdr)->uc80211_Reorder_PAL_TCL) & HIF_RX_HDR_TCL) ? TRUE : FALSE)) +#define HIF_RX_HDR_GET_NETWORK_IDX(_prHifRxHdr) \ + ((((_prHifRxHdr)->uc80211_Reorder_PAL_TCL) & HIF_RX_HDR_NETWORK_IDX_MASK)\ + >> HIF_RX_HDR_NETWORK_IDX_OFFSET) + +#define HIF_RX_HDR_GET_SEC_MODE(_prHifRxHdr) \ + ((((_prHifRxHdr)->u2PacketType) & HIF_RX_HDR_SEC_MODE_MASK) >> HIF_RX_HDR_SEC_MODE_OFFSET) + +#define HIF_RX_HDR_GET_TID(_prHifRxHdr) \ + ((((_prHifRxHdr)->u2SeqNoTid) & HIF_RX_HDR_TID_MASK)\ + >> HIF_RX_HDR_TID_OFFSET) +#define HIF_RX_HDR_GET_SN(_prHifRxHdr) \ + (((_prHifRxHdr)->u2SeqNoTid) & HIF_RX_HDR_SEQ_NO_MASK) +#define HIF_RX_HDR_GET_BAR_FLAG(_prHifRxHdr) \ + (((((_prHifRxHdr)->u2SeqNoTid) & HIF_RX_HDR_BAR_FRAME) ? TRUE : FALSE)) + +#define HIF_RX_HDR_GET_CHNL_NUM(_prHifRxHdr) \ + ((((_prHifRxHdr)->ucHwChannelNum) > HW_CHNL_NUM_MAX_4G_5G) ? \ + (((_prHifRxHdr)->ucHwChannelNum) - HW_CHNL_NUM_MAX_4G_5G) : \ + ((_prHifRxHdr)->ucHwChannelNum)) + +/* To do: support more bands other than 2.4G and 5G */ +#define HIF_RX_HDR_GET_RF_BAND(_prHifRxHdr) \ + ((((_prHifRxHdr)->ucHwChannelNum) <= HW_CHNL_NUM_MAX_2G4) ? \ + BAND_2G4 : BAND_5G) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static inline VOID hifDataTypeCheck(VOID); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/* Kevin: we don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + * We'll need this for porting driver to different RTOS. + */ +static inline VOID hifDataTypeCheck(VOID) +{ + DATA_STRUCT_INSPECTING_ASSERT(sizeof(HIF_RX_HEADER_T) == 12); + +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/hif_tx.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/hif_tx.h new file mode 100644 index 0000000000000..76f1069dc9b6b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/hif_tx.h @@ -0,0 +1,168 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _HIF_TX_H +#define _HIF_TX_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* Maximum buffer size for individual HIF TCQ Buffer */ +#define HIF_TX_BUFF_MAX_SIZE 1552 /* Reserved field was not included */ + +/* Maximum buffer count for individual HIF TCQ */ +#define HIF_TX_BUFF_COUNT_TC0 3 +#define HIF_TX_BUFF_COUNT_TC1 3 +#define HIF_TX_BUFF_COUNT_TC2 3 +#define HIF_TX_BUFF_COUNT_TC3 3 +#define HIF_TX_BUFF_COUNT_TC4 2 + +#define TX_HDR_SIZE sizeof(HIF_TX_HEADER_T) + +#define CMD_HDR_SIZE sizeof(WIFI_CMD_T) + +#define CMD_PKT_SIZE_FOR_IMAGE 2048 /* !< 2048 Bytes CMD payload buffer */ + +/*! NIC_HIF_TX_HEADER_T */ +/* DW 0, Byte 0,1 */ +#define HIF_TX_HDR_TX_BYTE_COUNT_MASK BITS(0, 11) +#define HIF_TX_HDR_USER_PRIORITY_OFFSET 12 + +/* DW 0, Byte 2 */ +#define HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK BITS(0, 7) + +/* DW 0, Byte 3 */ +#define HIF_TX_HDR_IP_CSUM BIT(0) +#define HIF_TX_HDR_TCP_CSUM BIT(1) +#define HIF_TX_HDR_RESOURCE_MASK BITS(2, 5) +#define HIF_TX_HDR_RESOURCE_OFFSET 2 +#define HIF_TX_HDR_PACKET_TYPE_MASK BITS(6, 7) +#define HIF_TX_HDR_PACKET_TYPE_OFFSET 6 + +/* DW 1, Byte 0 */ +#define HIF_TX_HDR_WLAN_HEADER_LEN_MASK BITS(0, 5) + +/* DW 1, Byte 1 */ +#define HIF_TX_HDR_FORMAT_ID_MASK BITS(0, 2) +#define HIF_TX_HDR_NETWORK_TYPE_MASK BITS(4, 5) +#define HIF_TX_HDR_NETWORK_TYPE_OFFSET 4 +#define HIF_TX_HDR_FLAG_1X_FRAME_MASK BIT(6) +#define HIF_TX_HDR_FLAG_1X_FRAME_OFFSET 6 +#define HIF_TX_HDR_FLAG_802_11_FORMAT_MASK BIT(7) +#define HIF_TX_HDR_FLAG_802_11_FORMAT_OFFSET 7 + +/* DW2, Byte 3 */ +#define HIF_TX_HDR_PS_FORWARDING_TYPE_MASK BITS(0, 1) +#define HIF_TX_HDR_PS_SESSION_ID_MASK BITS(2, 4) +#define HIF_TX_HDR_PS_SESSION_ID_OFFSET 2 +#define HIF_TX_HDR_BURST_END_MASK BIT(5) +#define HIF_TX_HDR_BURST_END_OFFSET 5 + +/* DW3, Byte 1 */ +#define HIF_TX_HDR_NEED_ACK BIT(0) +#define HIF_TX_HDR_BIP BIT(1) +#define HIF_TX_HDR_BASIC_RATE BIT(2) +#define HIF_TX_HDR_NEED_TX_DONE_STATUS BIT(3) +#define HIF_TX_HDR_RTS BIT(4) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef struct _HIF_HW_TX_HEADER_T { + UINT_16 u2TxByteCount; + UINT_8 ucEtherTypeOffset; + UINT_8 ucCSflags; + UINT_8 aucBuffer[0]; +} HIF_HW_TX_HEADER_T, *P_HIF_HW_TX_HEADER_T; + +typedef struct _HIF_TX_HEADER_T { + UINT_16 u2TxByteCount_UserPriority; + UINT_8 ucEtherTypeOffset; + UINT_8 ucResource_PktType_CSflags; + UINT_8 ucWlanHeaderLength; + UINT_8 ucPktFormtId_Flags; + UINT_16 u2LLH; /* for BOW */ + UINT_16 u2SeqNo; /* for BOW */ + UINT_8 ucStaRecIdx; + UINT_8 ucForwardingType_SessionID_Reserved; + UINT_8 ucPacketSeqNo; + UINT_8 ucAck_BIP_BasicRate; + UINT_8 aucReserved[2]; +} HIF_TX_HEADER_T, *P_HIF_TX_HEADER_T; + +typedef struct _HIF_TX_DESC_T { + UINT_8 ucOwn; + UINT_8 ucDescChksum; + UINT_16 u2Rsrv1; + UINT_32 u4NextDesc; + UINT_32 u4BufStartAddr; + UINT_32 u4Rsrv2; +} HIF_TX_DESC_T, *P_HIF_TX_DESC_T; + +typedef enum _ENUM_HIF_TX_PKT_TYPE_T { + HIF_TX_PKT_TYPE_DATA = 0, + HIF_TX_PKT_TYPE_CMD, + HIF_TX_PKT_TYPE_HIF_LOOPBACK, + HIF_TX_PKT_TYPE_MANAGEMENT, + HIF_TX_PKT_TYPE_NUM +} ENUM_HIF_TX_PKT_TYPE_T, *P_ENUM_HIF_TX_PKT_TYPE_T; + +typedef enum _ENUM_HIF_OOB_CTRL_PKT_TYPE_T { + HIF_OOB_CTRL_PKT_TYPE_LOOPBACK = 1, + HIF_OOB_CTRL_PKT_TYP_NUM +} ENUM_HIF_OOB_CTRL_PKT_TYPE_T, *P_ENUM_HIF_OOB_CTRL_PKT_TYPE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define TFCB_FRAME_PAD_TO_DW(u2Length) ALIGN_4(u2Length) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/* Kevin: we don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + */ +static inline VOID hif_txDataTypeCheck(VOID); + +static inline VOID hif_txDataTypeCheck(VOID) +{ + DATA_STRUCT_INSPECTING_ASSERT(sizeof(HIF_TX_HEADER_T) == 16); + +} + +#endif /*_HIF_TX_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/mac.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/mac.h new file mode 100644 index 0000000000000..204b9cc02c11e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/mac.h @@ -0,0 +1,2737 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _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_OUI_LEN 3 + +#define MAC_ADDR_LOCAL_ADMIN BIT(1) + +#define ETH_P_IPV4 0x0800 +#define ETH_P_IPX 0x8137 /* Novell IPX */ +#define ETH_P_AARP 0x80F3 /* AppleTalk Address Resolution Protocol (AARP) */ +#define ETH_P_IPV6 0x86DD + +#define IP_VERSION_4 4 +#define IP_VERSION_6 6 + +#define IP_PROTOCOL_TCP 6 +#define IP_PROTOCOL_UDP 17 + +#define IPV4_HDR_IP_IDENTIFICATION_OFFSET 4 +#define IPV4_HDR_IP_PROTOCOL_OFFSET 9 +#define IPV4_HDR_IP_CSUM_OFFSET 10 +#define IPV4_HDR_IP_SRC_ADDR_OFFSET 12 +#define IPV4_HDR_IP_DST_ADDR_OFFSET 16 + +#define IPV6_HDR_IP_PROTOCOL_OFFSET 6 +#define IPV6_HDR_IP_SRC_ADDR_OFFSET 8 +#define IPV6_HDR_IP_DST_ADDR_OFFSET 24 +#define IPV6_HDR_IP_DST_ADDR_MAC_HIGH_OFFSET 32 +#define IPV6_HDR_IP_DST_ADDR_MAC_LOW_OFFSET 37 +#define IPV6_PROTOCOL_ICMPV6 0x3A +#define IPV6_ADDR_LEN 16 +#define IPV6_HDR_LEN 40 + +#define ARP_OPERATION_OFFSET 6 +#define ARP_SNEDER_MAC_OFFSET 8 +#define ARP_SENDER_IP_OFFSET 14 +#define ARP_TARGET_MAC_OFFSET 18 +#define ARP_TARGET_IP_OFFSET 24 +#define ARP_OPERATION_REQUEST 0x0001 +#define ARP_OPERATION_RESPONSE 0x0002 + +#define ICMPV6_TYPE_OFFSET 0 +#define ICMPV6_FLAG_OFFSET 4 +#define ICMPV6_TARGET_ADDR_OFFSET 8 +#define ICMPV6_TARGET_LL_ADDR_TYPE_OFFSET 24 +#define ICMPV6_TARGET_LL_ADDR_LEN_OFFSET 25 +#define ICMPV6_TARGET_LL_ADDR_TA_OFFSET 26 + +#define ICMPV6_FLAG_ROUTER_BIT BIT(7) +#define ICMPV6_FLAG_SOLICITED_BIT BIT(6) +#define ICMPV6_FLAG_OVERWRITE_BIT BIT(5) +#define ICMPV6_TYPE_NEIGHBOR_SOLICITATION 0x87 +#define ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT 0x88 + +#define TCP_HDR_TCP_CSUM_OFFSET 16 +#define UDP_HDR_UDP_CSUM_OFFSET 6 + +#define DHCP_MAGIC_NUMBER 0x63825363 + +#define LLC_LEN 8 /* LLC(3) + SNAP(3) + EtherType(2) */ + +#define NULL_MAC_ADDR {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} +#define BC_MAC_ADDR {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} + +/* Ethernet Frame Field Size, in byte */ +#define ETHER_HEADER_LEN 14 +#define ETHER_TYPE_LEN 2 +#define ETHER_MIN_PKT_SZ 60 +#define ETHER_MAX_PKT_SZ 1514 + +/* IEEE 802.11 WLAN Frame Field Size, in byte */ +#define WLAN_MAC_HEADER_LEN 24 /* Address 4 excluded */ +#define WLAN_MAC_HEADER_A4_LEN 30 /* Address 4 included */ +#define WLAN_MAC_HEADER_QOS_LEN 26 /* QoS Control included */ +#define WLAN_MAC_HEADER_QOS_HTC_LEN 30 /* QoS Control and HTC included */ +#define WLAN_MAC_HEADER_A4_QOS_LEN 32 /* Address 4 and QoS Control included */ +#define WLAN_MAC_HEADER_A4_QOS_HTC_LEN 36 /* Address 4, QoS Control and HTC included */ +#define WLAN_MAC_MGMT_HEADER_LEN 24 /* Address 4 excluded */ +#define WLAN_MAC_MGMT_HEADER_HTC_LEN 28 /* HTC included */ + +#define QOS_CTRL_LEN 2 +#define HT_CTRL_LEN 4 + +#define WLAN_MAC_CTS_ACK_LEN (WLAN_MAC_CTS_ACK_FRAME_HEADER_LEN + FCS_LEN) + +/* 6.2.1.1.2 Semantics of the service primitive */ +#define MSDU_MAX_LENGTH 2304 + +/* 7.1.3.3.3 Broadcast BSSID */ +#define BC_BSSID BC_MAC_ADDR + +/* 7.1.3.7 FCS field */ +#define FCS_LEN 4 + +/* 7.3.1.6 Listen Interval field */ +#define DEFAULT_LISTEN_INTERVAL_BY_DTIM_PERIOD 2 /* In unit of AP's DTIM interval, */ +#define DEFAULT_LISTEN_INTERVAL 10 + +/* 7.3.2.1 Broadcast(Wildcard) SSID */ +#define BC_SSID "" +#define BC_SSID_LEN 0 + +/* 7.3.2.2 Data Rate Value */ +#define RATE_1M 2 /* 1M in unit of 500kb/s */ +#define RATE_2M 4 /* 2M */ +#define RATE_5_5M 11 /* 5.5M */ +#define RATE_11M 22 /* 11M */ +#define RATE_22M 44 /* 22M */ +#define RATE_33M 66 /* 33M */ +#define RATE_6M 12 /* 6M */ +#define RATE_9M 18 /* 9M */ +#define RATE_12M 24 /* 12M */ +#define RATE_18M 36 /* 18M */ +#define RATE_24M 48 /* 24M */ +#define RATE_36M 72 /* 36M */ +#define RATE_48M 96 /* 48M */ +#define RATE_54M 108 /* 54M */ +/* 7.3.2.14 BSS membership selector */ +#define RATE_HT_PHY 127 /* BSS Selector - Clause 20. HT PHY */ +#define RATE_MASK BITS(0, 6) /* mask bits for the rate */ +#define RATE_BASIC_BIT BIT(7) /* mask bit for the rate belonging to the BSSBasicRateSet */ + +/* 8.3.2.2 TKIP MPDU formats */ +#define TKIP_MIC_LEN 8 + +/* 9.2.10 DIFS */ +#define DIFS 2 /* 2 x aSlotTime */ + +/* 11.3 STA Authentication and Association */ +#define STA_STATE_1 0 /* Accept Class 1 frames */ +#define STA_STATE_2 1 /* Accept Class 1 & 2 frames */ +#define STA_STATE_3 2 /* Accept Class 1,2 & 3 frames */ + +/* 15.4.8.5 802.11k RCPI-dBm mapping*/ +#define NDBM_LOW_BOUND_FOR_RCPI 110 +#define RCPI_LOW_BOUND 0 +#define RCPI_HIGH_BOUND 220 +#define RCPI_MEASUREMENT_NOT_AVAILABLE 255 + +/* PHY characteristics */ +/* 17.4.4/18.3.3/19.8.4 Slot Time (aSlotTime) */ +#define SLOT_TIME_LONG 20 /* Long Slot Time */ +#define SLOT_TIME_SHORT 9 /* Short Slot Time */ + +#define SLOT_TIME_HR_DSSS SLOT_TIME_LONG /* 802.11b aSlotTime */ +#define SLOT_TIME_OFDM SLOT_TIME_SHORT /* 802.11a aSlotTime(20M Spacing) */ +#define SLOT_TIME_OFDM_10M_SPACING 13 /* 802.11a aSlotTime(10M Spacing) */ +#define SLOT_TIME_ERP_LONG SLOT_TIME_LONG /* 802.11g aSlotTime(Long) */ +#define SLOT_TIME_ERP_SHORT SLOT_TIME_SHORT /* 802.11g aSlotTime(Short) */ + +/* 17.4.4/18.3.3/19.8.4 Contention Window (aCWmin & aCWmax) */ +#define CWMIN_OFDM 15 /* 802.11a aCWmin */ +#define CWMAX_OFDM 1023 /* 802.11a aCWmax */ + +#define CWMIN_HR_DSSS 31 /* 802.11b aCWmin */ +#define CWMAX_HR_DSSS 1023 /* 802.11b aCWmax */ + +#define CWMIN_ERP_0 31 /* 802.11g aCWmin(0) - for only have 1/2/5/11Mbps Rates */ +#define CWMIN_ERP_1 15 /* 802.11g aCWmin(1) */ +#define CWMAX_ERP 1023 /* 802.11g aCWmax */ + +/* Short Inter-Frame Space (aSIFSTime) */ +/* 15.3.3 802.11b aSIFSTime */ +#define SIFS_TIME_HR_DSSS 10 +/* 17.4.4 802.11a aSIFSTime */ +#define SIFS_TIME_OFDM 16 +/* 19.8.4 802.11g aSIFSTime */ +#define SIFS_TIME_ERP 10 + +/* 15.4.6.2 Number of operating channels */ +#define CH_1 0x1 +#define CH_2 0x2 +#define CH_3 0x3 +#define CH_4 0x4 +#define CH_5 0x5 +#define CH_6 0x6 +#define CH_7 0x7 +#define CH_8 0x8 +#define CH_9 0x9 +#define CH_10 0xa +#define CH_11 0xb +#define CH_12 0xc +#define CH_13 0xd +#define CH_14 0xe + +#define MAXIMUM_OPERATION_CHANNEL_LIST 46 + +/* 3 --------------- IEEE 802.11 PICS --------------- */ +/* Annex D - dot11OperationEntry 2 */ +#define DOT11_RTS_THRESHOLD_MIN 0 +#define DOT11_RTS_THRESHOLD_MAX 2347 /* from Windows DDK */ +/* #define DOT11_RTS_THRESHOLD_MAX 3000 // from Annex D */ + +#define DOT11_RTS_THRESHOLD_DEFAULT \ + DOT11_RTS_THRESHOLD_MAX + +/* Annex D - dot11OperationEntry 5 */ +#define DOT11_FRAGMENTATION_THRESHOLD_MIN 256 +#define DOT11_FRAGMENTATION_THRESHOLD_MAX 2346 /* from Windows DDK */ +/* #define DOT11_FRAGMENTATION_THRESHOLD_MAX 3000 // from Annex D */ + +#define DOT11_FRAGMENTATION_THRESHOLD_DEFAULT \ + DOT11_FRAGMENTATION_THRESHOLD_MAX + +/* Annex D - dot11OperationEntry 6 */ +#define DOT11_TRANSMIT_MSDU_LIFETIME_TU_MIN 1 +#define DOT11_TRANSMIT_MSDU_LIFETIME_TU_MAX 0xFFFFffff +#define DOT11_TRANSMIT_MSDU_LIFETIME_TU_DEFAULT 4095 /* 802.11 define 512 */ + /* MT5921 only aceept N <= 4095 */ + +/* Annex D - dot11OperationEntry 7 */ +#define DOT11_RECEIVE_LIFETIME_TU_MIN 1 +#define DOT11_RECEIVE_LIFETIME_TU_MAX 0xFFFFffff +#define DOT11_RECEIVE_LIFETIME_TU_DEFAULT 4096 /* 802.11 define 512 */ + +/* Annex D - dot11StationConfigEntry 12 */ +#define DOT11_BEACON_PERIOD_MIN 1 /* TU. */ +#define DOT11_BEACON_PERIOD_MAX 0xffff /* TU. */ +#define DOT11_BEACON_PERIOD_DEFAULT 100 /* TU. */ + +/* Annex D - dot11StationConfigEntry 13 */ +#define DOT11_DTIM_PERIOD_MIN 1 /* TU. */ +#define DOT11_DTIM_PERIOD_MAX 255 /* TU. */ +#define DOT11_DTIM_PERIOD_DEFAULT 1 /* TU. */ + +/* Annex D - dot11RegDomainsSupportValue */ +#define REGULATION_DOMAIN_FCC 0x10 /* FCC (US) */ +#define REGULATION_DOMAIN_IC 0x20 /* IC or DOC (Canada) */ +#define REGULATION_DOMAIN_ETSI 0x30 /* ETSI (Europe) */ +#define REGULATION_DOMAIN_SPAIN 0x31 /* Spain */ +#define REGULATION_DOMAIN_FRANCE 0x32 /* France */ +#define REGULATION_DOMAIN_JAPAN 0x40 /* MKK (Japan) */ +#define REGULATION_DOMAIN_CHINA 0x50 /* China */ +#define REGULATION_DOMAIN_OTHER 0x00 /* Other */ + +/* 3 --------------- IEEE 802.11 MAC header fields --------------- */ +/* 7.1.3.1 Masks for the subfields in the Frame Control field */ +#define MASK_FC_PROTOCOL_VER BITS(0, 1) +#define MASK_FC_TYPE BITS(2, 3) +#define MASK_FC_SUBTYPE BITS(4, 7) +#define MASK_FC_SUBTYPE_QOS_DATA BIT(7) +#define MASK_FC_TO_DS BIT(8) +#define MASK_FC_FROM_DS BIT(9) +#define MASK_FC_MORE_FRAG BIT(10) +#define MASK_FC_RETRY BIT(11) +#define MASK_FC_PWR_MGT BIT(12) +#define MASK_FC_MORE_DATA BIT(13) +#define MASK_FC_PROTECTED_FRAME BIT(14) +#define MASK_FC_ORDER BIT(15) + +#define MASK_FRAME_TYPE (MASK_FC_TYPE | MASK_FC_SUBTYPE) +#define MASK_TO_DS_FROM_DS (MASK_FC_TO_DS | MASK_FC_FROM_DS) + +#define MAX_NUM_OF_FC_SUBTYPES 16 +#define OFFSET_OF_FC_SUBTYPE 4 + +/* 7.1.3.1.2 MAC frame types and subtypes */ +#define MAC_FRAME_TYPE_MGT 0 +#define MAC_FRAME_TYPE_CTRL BIT(2) +#define MAC_FRAME_TYPE_DATA BIT(3) +#define MAC_FRAME_TYPE_QOS_DATA (MAC_FRAME_TYPE_DATA | MASK_FC_SUBTYPE_QOS_DATA) + +#define MAC_FRAME_ASSOC_REQ (MAC_FRAME_TYPE_MGT | 0x0000) +#define MAC_FRAME_ASSOC_RSP (MAC_FRAME_TYPE_MGT | 0x0010) +#define MAC_FRAME_REASSOC_REQ (MAC_FRAME_TYPE_MGT | 0x0020) +#define MAC_FRAME_REASSOC_RSP (MAC_FRAME_TYPE_MGT | 0x0030) +#define MAC_FRAME_PROBE_REQ (MAC_FRAME_TYPE_MGT | 0x0040) +#define MAC_FRAME_PROBE_RSP (MAC_FRAME_TYPE_MGT | 0x0050) +#define MAC_FRAME_BEACON (MAC_FRAME_TYPE_MGT | 0x0080) +#define MAC_FRAME_ATIM (MAC_FRAME_TYPE_MGT | 0x0090) +#define MAC_FRAME_DISASSOC (MAC_FRAME_TYPE_MGT | 0x00A0) +#define MAC_FRAME_AUTH (MAC_FRAME_TYPE_MGT | 0x00B0) +#define MAC_FRAME_DEAUTH (MAC_FRAME_TYPE_MGT | 0x00C0) +#define MAC_FRAME_ACTION (MAC_FRAME_TYPE_MGT | 0x00D0) +#define MAC_FRAME_ACTION_NO_ACK (MAC_FRAME_TYPE_MGT | 0x00E0) + +#define MAC_FRAME_CONTRL_WRAPPER (MAC_FRAME_TYPE_CTRL | 0x0070) +#define MAC_FRAME_BLOCK_ACK_REQ (MAC_FRAME_TYPE_CTRL | 0x0080) +#define MAC_FRAME_BLOCK_ACK (MAC_FRAME_TYPE_CTRL | 0x0090) +#define MAC_FRAME_PS_POLL (MAC_FRAME_TYPE_CTRL | 0x00A0) +#define MAC_FRAME_RTS (MAC_FRAME_TYPE_CTRL | 0x00B0) +#define MAC_FRAME_CTS (MAC_FRAME_TYPE_CTRL | 0x00C0) +#define MAC_FRAME_ACK (MAC_FRAME_TYPE_CTRL | 0x00D0) +#define MAC_FRAME_CF_END (MAC_FRAME_TYPE_CTRL | 0x00E0) +#define MAC_FRAME_CF_END_CF_ACK (MAC_FRAME_TYPE_CTRL | 0x00F0) + +#define MAC_FRAME_DATA (MAC_FRAME_TYPE_DATA | 0x0000) +#define MAC_FRAME_DATA_CF_ACK (MAC_FRAME_TYPE_DATA | 0x0010) +#define MAC_FRAME_DATA_CF_POLL (MAC_FRAME_TYPE_DATA | 0x0020) +#define MAC_FRAME_DATA_CF_ACK_CF_POLL (MAC_FRAME_TYPE_DATA | 0x0030) +#define MAC_FRAME_NULL (MAC_FRAME_TYPE_DATA | 0x0040) +#define MAC_FRAME_CF_ACK (MAC_FRAME_TYPE_DATA | 0x0050) +#define MAC_FRAME_CF_POLL (MAC_FRAME_TYPE_DATA | 0x0060) +#define MAC_FRAME_CF_ACK_CF_POLL (MAC_FRAME_TYPE_DATA | 0x0070) +#define MAC_FRAME_QOS_DATA (MAC_FRAME_TYPE_DATA | 0x0080) +#define MAC_FRAME_QOS_DATA_CF_ACK (MAC_FRAME_TYPE_DATA | 0x0090) +#define MAC_FRAME_QOS_DATA_CF_POLL (MAC_FRAME_TYPE_DATA | 0x00A0) +#define MAC_FRAME_QOS_DATA_CF_ACK_CF_POLL (MAC_FRAME_TYPE_DATA | 0x00B0) +#define MAC_FRAME_QOS_NULL (MAC_FRAME_TYPE_DATA | 0x00C0) +#define MAC_FRAME_QOS_CF_POLL (MAC_FRAME_TYPE_DATA | 0x00E0) +#define MAC_FRAME_QOS_CF_ACK_CF_POLL (MAC_FRAME_TYPE_DATA | 0x00F0) + +/* 7.1.3.2 Mask for the AID value in the Duration/ID field */ +#define MASK_DI_DURATION BITS(0, 14) +#define MASK_DI_AID BITS(0, 13) +#define MASK_DI_AID_MSB BITS(14, 15) +#define MASK_DI_CFP_FIXED_VALUE BIT(15) + +/* 7.1.3.4 Masks for the subfields in the Sequence Control field */ +#define MASK_SC_SEQ_NUM BITS(4, 15) +#define MASK_SC_SEQ_NUM_OFFSET 4 +#define MASK_SC_FRAG_NUM BITS(0, 3) +#define INVALID_SEQ_CTRL_NUM 0x000F /* According to 6.2.1.1.2 + * FRAG_NUM won't equal to 15 + */ + +/* 7.1.3.5 QoS Control field */ +#define TID_NUM 16 +#define TID_MASK BITS(0, 3) +#define EOSP BIT(4) +#define ACK_POLICY BITS(5, 6) +#define A_MSDU_PRESENT BIT(7) + +#define MASK_QC_TID BITS(0, 3) +#define MASK_QC_EOSP BIT(4) +#define MASK_QC_EOSP_OFFSET 4 +#define MASK_QC_ACK_POLICY BITS(5, 6) +#define MASK_QC_ACK_POLICY_OFFSET 5 +#define MASK_QC_A_MSDU_PRESENT BIT(7) + +/* 7.1.3.5a HT Control field */ +#define HT_CTRL_LINK_ADAPTATION_CTRL BITS(0, 15) +#define HT_CTRL_CALIBRATION_POSITION BITS(16, 17) +#define HT_CTRL_CALIBRATION_SEQUENCE BITS(18, 19) +#define HT_CTRL_CSI_STEERING BITS(22, 23) +#define HT_CTRL_NDP_ANNOUNCEMENT BIT(24) +#define HT_CTRL_AC_CONSTRAINT BIT(30) +#define HT_CTRL_RDG_MORE_PPDU BIT(31) + +#define LINK_ADAPTATION_CTRL_TRQ BIT(1) +#define LINK_ADAPTATION_CTRL_MAI_MRQ BIT(2) +#define LINK_ADAPTATION_CTRL_MAI_MSI BITS(3, 5) +#define LINK_ADAPTATION_CTRL_MFSI BITS(6, 8) +#define LINK_ADAPTATION_CTRL_MFB_ASELC_CMD BITS(9, 11) +#define LINK_ADAPTATION_CTRL_MFB_ASELC_DATA BITS(12, 15) + +/* 7.1.3.5.3 Ack Policy subfield*/ +#define ACK_POLICY_NORMAL_ACK_IMPLICIT_BA_REQ 0 +#define ACK_POLICY_NO_ACK 1 +#define ACK_POLICY_NO_EXPLICIT_ACK_PSMP_ACK 2 +#define ACK_POLICY_BA 3 + +/* 7.1.3.7 FCS field */ +#define FCS_LEN 4 + +/* 7.2.1.4 WLAN Control Frame - PS-POLL Frame */ +#define PSPOLL_FRAME_LEN 16 /* w/o FCS */ + +/* 7.2.7.1 BAR */ +#define OFFSET_BAR_SSC_SN 4 + +/* 8.3.2.2 TKIP MPDU formats */ +#define TKIP_MIC_LEN 8 + +/* 2009.11.30 mtk02468: Moved these definitions to the right place */ +#if 0 +/* Block Ack Parameter Set field */ +#define BA_PARM_BA_POLICY BIT(1) +#define BA_PARM_TID BITS(2, 5) +#define BA_PARM_BUFFER_SIZE BITS(6, 15) +#endif + +#define BA_POLICY_IMMEDIATE BIT(1) + +/* Block Ack Starting Sequence Control field */ +#define BA_START_SEQ_CTL_FRAG_NUM BITS(0, 3) +#define BA_START_SEQ_CTL_SSN BITS(4, 15) + +/* BAR Control field */ +#define BAR_CONTROL_NO_ACK_POLICY BIT(0) +#define BAR_CONTROL_MULTI_TID BIT(1) +#define BAR_CONTROL_COMPRESSED_BA BIT(2) +#define BAR_CONTROL_TID_INFO BITS(12, 15) +#define BAR_CONTROL_TID_INFO_OFFSET 12 + +/* TID Value */ +#define BAR_INFO_TID_VALUE BITS(12, 15) + +#define BAR_COMPRESSED_VARIANT_FRAME_LEN (16 + 4) + +/* 3 --------------- IEEE 802.11 frame body fields --------------- */ +/* 3 Management frame body components (I): Fixed Fields. */ +/* 7.3.1.1 Authentication Algorithm Number field */ +#define AUTH_ALGORITHM_NUM_FIELD_LEN 2 + +#define AUTH_ALGORITHM_NUM_OPEN_SYSTEM 0 /* Open System */ +#define AUTH_ALGORITHM_NUM_SHARED_KEY 1 /* Shared Key */ +#define AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION 2 /* Fast BSS Transition */ +#define AUTH_ALGORITHM_NUM_SAE 3 /* WPA3 - SAE */ + +/* 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_RADIO_MEASUREMENT BIT(12) +#define CAP_INFO_DSSS_OFDM BIT(13) +#define CAP_INFO_DELAYED_BLOCK_ACK BIT(14) +#define CAP_INFO_IMM_BLOCK_ACK BIT(15) +/* STA usage of CF-Pollable and CF-Poll Request subfields */ +/* STA: not CF-Pollable */ +#define CAP_CF_STA_NOT_POLLABLE 0x0000 +/* STA: CF-Pollable, not requesting on the CF-Polling list */ +#define CAP_CF_STA_NOT_ON_LIST CAP_INFO_CF_POLL_REQ +/* STA: CF-Pollable, requesting on the CF-Polling list */ +#define CAP_CF_STA_ON_LIST CAP_INFO_CF_POLLABLE +/* STA: CF-Pollable, requesting never to be polled */ +#define CAP_CF_STA_NEVER_POLLED (CAP_INFO_CF_POLLABLE | CAP_INFO_CF_POLL_REQ) + +/* AP usage of CF-Pollable and CF-Poll Request subfields */ +/* AP: No point coordinator (PC) */ +#define CAP_CF_AP_NO_PC 0x0000 +/* AP: PC at AP for delivery only (no polling) */ +#define CAP_CF_AP_DELIVERY_ONLY CAP_INFO_CF_POLL_REQ +/* AP: PC at AP for delivery and polling */ +#define CAP_CF_AP_DELIVERY_POLLING CAP_INFO_CF_POLLABLE + +/* 7.3.1.5 Current AP Address field */ +#define CURR_AP_ADDR_FIELD_LEN MAC_ADDR_LEN + +/* 7.3.1.6 Listen Interval field */ +#define LISTEN_INTERVAL_FIELD_LEN 2 + +/* 7.3.1.7 Reason Code field */ +#define REASON_CODE_FIELD_LEN 2 + +#define REASON_CODE_RESERVED 0 /* Reseved */ +#define REASON_CODE_UNSPECIFIED 1 /* Unspecified reason */ +#define REASON_CODE_PREV_AUTH_INVALID 2 /* Previous auth no longer valid */ +#define REASON_CODE_DEAUTH_LEAVING_BSS 3 /* Deauth because sending STA is leaving BSS */ +#define REASON_CODE_DISASSOC_INACTIVITY 4 /* Disassoc due to inactivity */ +#define REASON_CODE_DISASSOC_AP_OVERLOAD 5 /* Disassoc because AP is unable to handle all assoc STAs */ +#define REASON_CODE_CLASS_2_ERR 6 /* Class 2 frame rx from nonauth STA */ +#define REASON_CODE_CLASS_3_ERR 7 /* Class 3 frame rx from nonassoc STA */ +#define REASON_CODE_DISASSOC_LEAVING_BSS 8 /* Disassoc because sending STA is leaving BSS */ +#define REASON_CODE_ASSOC_BEFORE_AUTH 9 /* STA requesting (re)assoc is not auth with responding STA */ +#define REASON_CODE_DISASSOC_PWR_CAP_UNACCEPTABLE 10 /* + * Disassoc because the info in Power Capability is + * unacceptable + */ +#define REASON_CODE_DISASSOC_SUP_CHS_UNACCEPTABLE 11 /* + * Disassoc because the info in Supported Channels is + * unacceptable + */ +#define REASON_CODE_INVALID_INFO_ELEM 13 /* Invalid information element */ +#define REASON_CODE_MIC_FAILURE 14 /* MIC failure */ +#define REASON_CODE_4_WAY_HANDSHAKE_TIMEOUT 15 /* 4-way handshake timeout */ +#define REASON_CODE_GROUP_KEY_UPDATE_TIMEOUT 16 /* Group key update timeout */ +#define REASON_CODE_DIFFERENT_INFO_ELEM 17 /* + * Info element in 4-way handshake different from + * (Re-)associate request/Probe response/Beacon + */ +#define REASON_CODE_MULTICAST_CIPHER_NOT_VALID 18 /* Multicast Cipher is not valid */ +#define REASON_CODE_UNICAST_CIPHER_NOT_VALID 19 /* Unicast Cipher is not valid */ +#define REASON_CODE_AKMP_NOT_VALID 20 /* AKMP is not valid */ +#define REASON_CODE_UNSUPPORTED_RSNE_VERSION 21 /* Unsupported RSNE version */ +#define REASON_CODE_INVALID_RSNE_CAPABILITIES 22 /* Invalid RSNE Capabilities */ +#define REASON_CODE_IEEE_802_1X_AUTH_FAILED 23 /* IEEE 802.1X Authentication failed */ +#define REASON_CODE_CIPHER_REJECT_SEC_POLICY 24 /* Cipher suite rejected because of the security policy */ +#define REASON_CODE_DISASSOC_UNSPECIFIED_QOS 32 /* Disassoc for unspecified, QoS-related reason */ +#define REASON_CODE_DISASSOC_LACK_OF_BANDWIDTH 33 /* + * Disassoc because QAP lacks sufficient bandwidth + * for this QSTA + */ +#define REASON_CODE_DISASSOC_ACK_LOST_POOR_CHANNEL 34 /* + * Disassoc because of too many ACKs lost for AP transmissions + * and/or poor channel conditions + */ +#define REASON_CODE_DISASSOC_TX_OUTSIDE_TXOP_LIMIT 35 /* + * Disassoc because QSTA is transmitting outside the limits of + * its TXOPs + */ +#define REASON_CODE_PEER_WHILE_LEAVING 36 /* QSTA is leaving the QBSS or resetting */ +#define REASON_CODE_PEER_REFUSE_DLP 37 /* Peer does not want to use this mechanism */ +#define REASON_CODE_PEER_SETUP_REQUIRED 38 /* Frames received but a setup is reqired */ +#define REASON_CODE_PEER_TIME_OUT 39 /* Time out */ +#define REASON_CODE_PEER_CIPHER_UNSUPPORTED 45 /* Peer does not support the requested cipher suite */ +#define REASON_CODE_BEACON_TIMEOUT 100 /* for beacon timeout, defined by mediatek */ +#define REASON_CODE_BSS_SECURITY_CHANGE 101 /* for BSS security change, defined by mediatek */ +/* 7.3.1.8 AID field */ +#define AID_FIELD_LEN 2 +#define AID_MASK BITS(0, 13) +#define AID_MSB BITS(14, 15) +#define AID_MIN_VALUE 1 +#define AID_MAX_VALUE 2007 + +/* 7.3.1.9 Status Code field */ +#define STATUS_CODE_FIELD_LEN 2 + +#define STATUS_CODE_RESERVED 0 /* Reserved - Used by TX Auth */ +#define STATUS_CODE_SUCCESSFUL 0 /* Successful */ +#define STATUS_CODE_UNSPECIFIED_FAILURE 1 /* Unspecified failure */ +#define STATUS_CODE_CAP_NOT_SUPPORTED 10 /* Cannot support all requested cap in the Cap Info field */ +#define STATUS_CODE_REASSOC_DENIED_WITHOUT_ASSOC 11 /* + * Reassoc denied due to inability to confirm that + * assoc exists + */ +#define STATUS_CODE_ASSOC_DENIED_OUTSIDE_STANDARD 12 /* Assoc denied due to reason outside the scope of this std. */ +#define STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED 13 /* + * Responding STA does not support the specified + * auth algorithm + */ +#define STATUS_CODE_AUTH_OUT_OF_SEQ 14 /* + * Rx an auth frame with auth transaction seq num + * out of expected seq + */ +#define STATUS_CODE_AUTH_REJECTED_CHAL_FAIL 15 /* Auth rejected because of challenge failure */ +#define STATUS_CODE_AUTH_REJECTED_TIMEOUT 16 /* + * Auth rejected due to timeout waiting for next frame + * in sequence + */ +#define STATUS_CODE_ASSOC_DENIED_AP_OVERLOAD 17 /* + * Assoc denied because AP is unable to handle additional + * assoc STAs + */ +#define STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED 18 /* + * Assoc denied due to requesting STA not supporting + * all of basic rates + */ +#define STATUS_CODE_ASSOC_DENIED_NO_SHORT_PREAMBLE 19 /* + * Assoc denied due to requesting STA not supporting short + * preamble + */ +#define STATUS_CODE_ASSOC_DENIED_NO_PBCC 20 /* Assoc denied due to requesting STA not supporting PBCC */ +#define STATUS_CODE_ASSOC_DENIED_NO_CH_AGILITY 21 /* + * Assoc denied due to requesting STA not supporting channel + * agility + */ +#define STATUS_CODE_ASSOC_REJECTED_NO_SPEC_MGT 22 /* Assoc rejected because Spectrum Mgt capability is required */ +#define STATUS_CODE_ASSOC_REJECTED_PWR_CAP 23 /* + * Assoc rejected because the info in Power Capability + * is unacceptable + */ +#define STATUS_CODE_ASSOC_REJECTED_SUP_CHS 24 /* + * Assoc rejected because the info in Supported Channels + * is unacceptable + */ +#define STATUS_CODE_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25 /* + * Assoc denied due to requesting STA not supporting + * short slot time + */ +#define STATUS_CODE_ASSOC_DENIED_NO_DSSS_OFDM 26 /* + * Assoc denied due to requesting STA not supporting + * DSSS-OFDM + */ +#if CFG_SUPPORT_802_11W +#define STATUS_CODE_ASSOC_REJECTED_TEMPORARILY 30 /* IEEE 802.11w, Assoc denied due to the SA query */ +#define STATUS_CODE_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31 /* + * IEEE 802.11w, Assoc denied due to the MFP select + * policy + */ +#endif +#define STATUS_CODE_UNSPECIFIED_QOS_FAILURE 32 /* Unspecified, QoS-related failure */ +#define STATUS_CODE_ASSOC_DENIED_BANDWIDTH 33 /* + * Assoc denied due to insufficient bandwidth to handle another + * QSTA + */ +#define STATUS_CODE_ASSOC_DENIED_POOR_CHANNEL 34 /* + * Assoc denied due to excessive frame loss rates and/or poor + * channel conditions + */ +#define STATUS_CODE_ASSOC_DENIED_NO_QOS_FACILITY 35 /* + * Assoc denied due to requesting STA not supporting QoS + * facility + */ +#define STATUS_CODE_REQ_DECLINED 37 /* Request has been declined */ +#define STATUS_CODE_REQ_INVALID_PARAMETER_VALUE 38 /* + * Request has not been successful as one or more parameters + * have invalid values + */ +#define STATUS_CODE_REQ_NOT_HONORED_TSPEC 39 /* + * TS not created because request cannot be honored. + * Suggested TSPEC provided. + */ +#define STATUS_CODE_INVALID_INFO_ELEMENT 40 /* Invalid information element */ +#define STATUS_CODE_INVALID_GROUP_CIPHER 41 /* Invalid group cipher */ +#define STATUS_CODE_INVALID_PAIRWISE_CIPHER 42 /* Invalid pairwise cipher */ +#define STATUS_CODE_INVALID_AKMP 43 /* Invalid AKMP */ +#define STATUS_CODE_UNSUPPORTED_RSN_IE_VERSION 44 /* Unsupported RSN information element version */ +#define STATUS_CODE_INVALID_RSN_IE_CAP 45 /* Invalid RSN information element capabilities */ +#define STATUS_CODE_CIPHER_SUITE_REJECTED 46 /* Cipher suite rejected because of security policy */ +#define STATUS_CODE_REQ_NOT_HONORED_TS_DELAY 47 /* + * TS not created because request cannot be honored. + * Attempt to create a TS later. + */ +#define STATUS_CODE_DIRECT_LINK_NOT_ALLOWED 48 /* Direct Link is not allowed in the BSS by policy */ +#define STATUS_CODE_DESTINATION_STA_NOT_PRESENT 49 /* Destination STA is not present within this QBSS */ +#define STATUS_CODE_DESTINATION_STA_NOT_QSTA 50 /* Destination STA is not a QSTA */ +#define STATUS_CODE_ASSOC_DENIED_LARGE_LIS_INTERVAL 51 /* Association denied because the ListenInterval is too large */ + +/* proprietary definition of reserved field of Status Code */ +#define STATUS_CODE_JOIN_FAILURE 0xFFF0 /* Join failure */ +#define STATUS_CODE_JOIN_TIMEOUT 0xFFF1 /* Join timeout */ +#define STATUS_CODE_AUTH_TIMEOUT 0xFFF2 /* Authentication timeout */ +#define STATUS_CODE_ASSOC_TIMEOUT 0xFFF3 /* (Re)Association timeout */ +#define STATUS_CODE_CCX_CCKM_REASSOC_FAILURE 0xFFF4 /* CCX CCKM reassociation failure */ + +/* 7.3.1.10 Timestamp field */ +#define TIMESTAMP_FIELD_LEN 8 + +/* 7.3.1.11 Category of Action field */ +#define CATEGORY_SPEC_MGT 0 +#define CATEGORY_QOS_ACTION 1 /* QoS action */ +#define CATEGORY_DLS_ACTION 2 /* Direct Link Protocol (DLP) action */ +#define CATEGORY_BLOCK_ACK_ACTION 3 /* Block ack action */ +#define CATEGORY_PUBLIC_ACTION 4 /* Public action */ +#define CATEGORY_RM_ACTION 5 /* Radio measurement action */ +#define CATEGORY_HT_ACTION 7 +#if CFG_SUPPORT_802_11W +#define CATEGORY_SA_QUERT_ACTION 8 +#endif +#define CATEGORY_WNM_ACTION 10 /* 802.11v Wireless Network Management */ +#define CATEGORY_UNPROTECTED_WNM_ACTION 11 /* 802.11v Wireless Network Management */ +#define CATEGORY_WME_MGT_NOTIFICATION 17 /* WME management notification */ +#define CATEGORY_VENDOR_SPECIFIC_ACTION 127 + +/* Public Action field*/ +#define PUBLIC_ACTION_GAS_INITIAL_REQ 10 +#define PUBLIC_ACTION_GAS_INITIAL_RESP 11 +#define PUBLIC_ACTION_GAS_COMEBACK_REQ 12 +#define PUBLIC_ACTION_GAS_COMEBACK_RESP 13 + +/* 7.3.1.14 Block Ack Parameter Set field */ +#define BA_PARAM_SET_ACK_POLICY_MASK BIT(1) +#define BA_PARAM_SET_ACK_POLICY_MASK_OFFSET 1 +#define BA_PARAM_SET_TID_MASK BITS(2, 5) +#define BA_PARAM_SET_TID_MASK_OFFSET 2 +#define BA_PARAM_SET_BUFFER_SIZE_MASK BITS(6, 15) +#define BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET 6 + +#define BA_PARAM_SET_ACK_POLICY_IMMEDIATE_BA 1 +#define BA_PARAM_SET_ACK_POLICY_DELAYED_BA 0 + +/* 3 Management frame body components (II): Information Elements. */ +/* 7.3.2 Element IDs of information elements */ +#define ELEM_HDR_LEN 2 + +#define ELEM_ID_SSID 0 /* SSID */ +#define ELEM_ID_SUP_RATES 1 /* Supported rates */ +#define ELEM_ID_FH_PARAM_SET 2 /* FH parameter set */ +#define ELEM_ID_DS_PARAM_SET 3 /* DS parameter set */ +#define ELEM_ID_CF_PARAM_SET 4 /* CF parameter set */ +#define ELEM_ID_TIM 5 /* TIM */ +#define ELEM_ID_IBSS_PARAM_SET 6 /* IBSS parameter set */ +#define ELEM_ID_COUNTRY_INFO 7 /* Country information */ +#define ELEM_ID_HOPPING_PATTERN_PARAM 8 /* Hopping pattern parameters */ +#define ELEM_ID_HOPPING_PATTERN_TABLE 9 /* Hopping pattern table */ +#define ELEM_ID_REQUEST 10 /* Request */ +#define ELEM_ID_BSS_LOAD 11 /* BSS load */ +#define ELEM_ID_EDCA_PARAM_SET 12 /* EDCA parameter set */ +#define ELEM_ID_TSPEC 13 /* Traffic specification (TSPEC) */ +#define ELEM_ID_TCLAS 14 /* Traffic classification (TCLAS) */ +#define ELEM_ID_SCHEDULE 15 /* Schedule */ +#define ELEM_ID_CHALLENGE_TEXT 16 /* Challenge text */ + +#define ELEM_ID_PWR_CONSTRAINT 32 /* Power constraint */ +#define ELEM_ID_PWR_CAP 33 /* Power capability */ +#define ELEM_ID_TPC_REQ 34 /* TPC request */ +#define ELEM_ID_TPC_REPORT 35 /* TPC report */ +#define ELEM_ID_SUP_CHS 36 /* Supported channels */ +#define ELEM_ID_CH_SW_ANNOUNCEMENT 37 /* Channel switch announcement */ +#define ELEM_ID_MEASUREMENT_REQ 38 /* Measurement request */ +#define ELEM_ID_MEASUREMENT_REPORT 39 /* Measurement report */ +#define ELEM_ID_QUIET 40 /* Quiet */ +#define ELEM_ID_IBSS_DFS 41 /* IBSS DFS */ +#define ELEM_ID_ERP_INFO 42 /* ERP information */ +#define ELEM_ID_TS_DELAY 43 /* TS delay */ +#define ELEM_ID_TCLAS_PROCESSING 44 /* TCLAS processing */ +#define ELEM_ID_HT_CAP 45 /* HT Capabilities subelement */ +#define ELEM_ID_QOS_CAP 46 /* QoS capability */ +#define ELEM_ID_RSN 48 /* RSN IE */ +#define ELEM_ID_EXTENDED_SUP_RATES 50 /* Extended supported rates */ +#define ELEM_ID_AP_CHANNEL_REPORT 51 /* AP Channel Report Element */ +#define ELEM_ID_NEIGHBOR_REPORT 52 /* Neighbor Report */ +#define ELEM_ID_MOBILITY_DOMAIN 54 /* Mobility Domain for 802.11R */ +#define ELEM_ID_FAST_TRANSITION 55 /* Fast Bss Transition for 802.11 R */ +#define ELEM_ID_TIMEOUT_INTERVAL 56 /* 802.11w SA Timeout interval */ +#define ELEM_ID_RESOURCE_INFO_CONTAINER 57 /* Resource Information Container for 802.11 R */ +#define ELEM_ID_SUP_OPERATING_CLASS 59 /* Supported Operating Classes */ +#define ELEM_ID_CH_ESW_ANNOUNCEMENT 60 /* Channel switch announcement */ +#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_BSS_MAX_IDLE_PERIOD 90 /* AP Keep-Alive parameters */ +#define ELEM_ID_INTERWORKING 107 /* Interworking with External Network */ +#define ELEM_ID_ADVERTISEMENT_PROTOCOL 108 /* Advertisement Protocol */ +#define ELEM_ID_QOS_MAP_SET 110 /* QoS Map Set */ +#define ELEM_ID_ROAMING_CONSORTIUM 111 /* Roaming Consortium */ +#define ELEM_ID_EXTENDED_CAP 127 /* Extended capabilities */ + +#define ELEM_ID_VENDOR 221 /* Vendor specific IE */ +#define ELEM_ID_WPA ELEM_ID_VENDOR /* WPA IE */ +#define ELEM_ID_WMM ELEM_ID_VENDOR /* WMM IE */ +#define ELEM_ID_P2P ELEM_ID_VENDOR /* WiFi Direct */ +#define ELEM_ID_WFD ELEM_ID_VENDOR /* WiFi Direct */ +#define ELEM_ID_WSC ELEM_ID_VENDOR /* WSC IE */ + +#define ELEM_ID_RESERVED 255 /* Reserved */ + +/* 7.3.2.1 SSID element */ +#define ELEM_MAX_LEN_SSID 32 + +/* 7.3.2.2 Supported Rates */ +#define ELEM_MAX_LEN_SUP_RATES 8 + +/* 7.3.2.4 DS Parameter Set */ +#define ELEM_MAX_LEN_DS_PARAMETER_SET 1 + +/* 7.3.2.5 CF Parameter Set */ +#define ELEM_CF_PARM_LEN 8 + +/* 7.3.2.6 TIM */ +#define ELEM_MIX_LEN_TIM 4 +#define ELEM_MAX_LEN_TIM 254 + +/* 7.3.2.7 IBSS Parameter Set element */ +#define ELEM_MAX_LEN_IBSS_PARAMETER_SET 2 + +/* 7.3.2.8 Challenge Text element */ +#define ELEM_MIN_LEN_CHALLENGE_TEXT 1 +#define ELEM_MAX_LEN_CHALLENGE_TEXT 253 + +/* 7.3.2.9 Country Information element */ +/* Country IE should contain at least 3-bytes country code string and one subband triplet. */ +#define ELEM_MIN_LEN_COUNTRY_INFO 6 + +#define ELEM_ID_COUNTRY_INFO_TRIPLET_LEN_FIXED 3 +#define ELEM_ID_COUNTRY_INFO_SUBBAND_TRIPLET_LEN_FIXED 3 +#define ELEM_ID_COUNTRY_INFO_REGULATORY_TRIPLET_LEN_FIXED 3 + +/* 7.3.2.13 ERP Information element */ +#define ELEM_MAX_LEN_ERP 1 +/* -- bits in the ERP Information element */ +#define ERP_INFO_NON_ERP_PRESENT BIT(0) /* NonERP_Present bit */ +#define ERP_INFO_USE_PROTECTION BIT(1) /* Use_Protection bit */ +#define ERP_INFO_BARKER_PREAMBLE_MODE BIT(2) /* Barker_Preamble_Mode bit */ + +/* 7.3.2.14 Extended Supported Rates */ +#define ELEM_MAX_LEN_EXTENDED_SUP_RATES 255 + +#if CFG_SUPPORT_DFS +/* 7.3.2.19 Supported Channels element */ +#define ELEM_MAX_LEN_SUPPORTED_CHANNELS 7 +#endif + +/* 7.3.2.21 Measurement Request element */ +#define ELEM_RM_TYPE_BASIC_REQ 0 +#define ELEM_RM_TYPE_CCA_REQ 1 +#define ELEM_RM_TYPE_RPI_HISTOGRAM_REQ 2 +#define ELEM_RM_TYPE_CHNL_LOAD_REQ 3 +#define ELEM_RM_TYPE_NOISE_HISTOGRAM_REQ 4 +#define ELEM_RM_TYPE_BEACON_REQ 5 +#define ELEM_RM_TYPE_FRAME_REQ 6 +#define ELEM_RM_TYPE_STA_STATISTICS_REQ 7 +#define ELEM_RM_TYPE_LCI_REQ 8 +#define ELEM_RM_TYPE_TSM_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_TSM_REPORT 9 + +/* 7.3.2.25 RSN information element */ +#define ELEM_MAX_LEN_WPA 34 /* one pairwise, one AKM suite, one PMKID */ +#define ELEM_MAX_LEN_RSN 38 /* one pairwise, one AKM suite, one PMKID */ +#define ELEM_MAX_LEN_WAPI 38 /* one pairwise, one AKM suite, one BKID */ +#define ELEM_MAX_LEN_WSC 200 /* one pairwise, one AKM suite, one BKID */ + +#if CFG_SUPPORT_802_11W +#define ELEM_WPA_CAP_MFPR BIT(6) +#define ELEM_WPA_CAP_MFPC BIT(7) +#endif + +/* 7.3.2.27 Extended Capabilities information element */ +#define ELEM_EXT_CAP_20_40_COEXIST_SUPPORT BIT(0) +#define ELEM_EXT_CAP_ECS_SUPPORT BIT(2) +#define ELEM_EXT_CAP_PSMP_CAP BIT(4) +#define ELEM_EXT_CAP_SERVICE_INTERVAL_GRANULARITY BIT(5) +#define ELEM_EXT_CAP_SCHEDULE_PSMP BIT(6) + +#define ELEM_EXT_CAP_BSS_TRANSITION_BIT 19 +#define ELEM_EXT_CAP_UTC_TSF_OFFSET_BIT 27 +#define ELEM_EXT_CAP_INTERWORKING_BIT 31 +#define ELEM_EXT_CAP_QOSMAPSET_BIT 32 +#define ELEM_EXT_CAP_WNM_NOTIFICATION_BIT 46 + +#if CFG_SUPPORT_HOTSPOT_2_0 +#define ELEM_MAX_LEN_EXT_CAP (6) +#else +#define ELEM_MAX_LEN_EXT_CAP (3 - ELEM_HDR_LEN) +#endif + +/* 7.3.2.30 TSPEC element */ +#define TS_INFO_TRAFFIC_TYPE_MASK BIT(0) /* WMM: 0 (Asynchronous TS of low-duty cycles) */ +#define TS_INFO_TID_OFFSET 1 +#define TS_INFO_TID_MASK BITS(1, 4) +#define TS_INFO_DIRECTION_OFFSET 5 +#define TS_INFO_DIRECTION_MASK BITS(5, 6) +#define TS_INFO_ACCESS_POLICY_OFFSET 7 +#define TS_INFO_ACCESS_POLICY_MASK BITS(7, 8) +#define TS_INFO_AGGREGATION_MASK BIT(9) /* WMM: 0 */ +#define TS_INFO_APSD_MASK BIT(10) +#define TS_INFO_UP_OFFSET 11 +#define TS_INFO_UP_MASK BITS(11, 13) +#define TS_INFO_ACK_POLICY_OFFSET 14 +#define TS_INFO_ACK_POLICY_MASK BITS(14, 15) +#define TS_INFO_SCHEDULE_MASK 16 + +/* 7.3.2.45 RRM Enabled Capbility element */ +#define ELEM_MAX_LEN_RRM_CAP 5 +#define RRM_CAP_INFO_LINK_MEASURE_BIT 0 +#define RRM_CAP_INFO_NEIGHBOR_REPORT_BIT 1 +#define RRM_CAP_INFO_BEACON_PASSIVE_MEASURE_BIT 4 +#define RRM_CAP_INFO_BEACON_ACTIVE_MEASURE_BIT 5 +#define RRM_CAP_INFO_BEACON_TABLE_BIT 6 +#define RRM_CAP_INFO_TSM_BIT 14 +#define RRM_CAP_INFO_RRM_BIT 17 + +/* 7.3.2.56 HT capabilities element */ +#define ELEM_MAX_LEN_HT_CAP (28 - ELEM_HDR_LEN) /* sizeof(IE_HT_CAP_T)-2 */ + +/* 7.3.2.56.2 HT capabilities Info field */ +#define HT_CAP_INFO_LDPC_CAP BIT(0) +#define HT_CAP_INFO_SUP_CHNL_WIDTH BIT(1) +#define HT_CAP_INFO_SM_POWER_SAVE BITS(2, 3) +#define HT_CAP_INFO_HT_GF BIT(4) +#define HT_CAP_INFO_SHORT_GI_20M BIT(5) +#define HT_CAP_INFO_SHORT_GI_40M BIT(6) +#define HT_CAP_INFO_TX_STBC BIT(7) +#define HT_CAP_INFO_RX_STBC BITS(8, 9) +#define HT_CAP_INFO_HT_DELAYED_BA BIT(10) +#define HT_CAP_INFO_MAX_AMSDU_LEN BIT(11) +#define HT_CAP_INFO_DSSS_CCK_IN_40M BIT(12) +#define HT_CAP_INFO_40M_INTOLERANT BIT(14) +#define HT_CAP_INFO_LSIG_TXOP_SUPPORT BIT(15) + +#define HT_CAP_INFO_RX_STBC_NO_SUPPORTED 0 +#define HT_CAP_INFO_RX_STBC_1_SS BIT(8) +#define HT_CAP_INFO_RX_STBC_2_SS BIT(9) +#define HT_CAP_INFO_RX_STBC_3_SS HT_CAP_INFO_RX_STBC + +/* 7.3.2.56.3 A-MPDU Parameters field */ +#define AMPDU_PARAM_MAX_AMPDU_LEN_EXP BITS(0, 1) +#define AMPDU_PARAM_MIN_START_SPACING BITS(2, 4) + +#define AMPDU_PARAM_MAX_AMPDU_LEN_8K 0 +#define AMPDU_PARAM_MAX_AMPDU_LEN_16K BIT(0) +#define AMPDU_PARAM_MAX_AMPDU_LEN_32K BIT(1) +#define AMPDU_PARAM_MAX_AMPDU_LEN_64K BITS(0, 1) + +#define AMPDU_PARAM_MSS_NO_RESTRICIT 0 +#define AMPDU_PARAM_MSS_1_4_US BIT(2) +#define AMPDU_PARAM_MSS_1_2_US BIT(3) +#define AMPDU_PARAM_MSS_1_US BITS(2, 3) +#define AMPDU_PARAM_MSS_2_US BIT(4) +#define AMPDU_PARAM_MSS_4_US (BIT(4) | BIT(2)) +#define AMPDU_PARAM_MSS_8_US (BIT(4) | BIT(3)) +#define AMPDU_PARAM_MSS_16_US BITS(2, 4) + +/* 7.3.2.56.4 Supported MCS Set field (TX rate: octects 12~15) */ +#define SUP_MCS_TX_SET_DEFINED BIT(0) +#define SUP_MCS_TX_RX_SET_NOT_EQUAL BIT(1) +#define SUP_MCS_TX_MAX_NUM_SS BITS(2, 3) +#define SUP_MCS_TX_UNEQUAL_MODULATION BIT(4) + +#define SUP_MCS_TX_MAX_NUM_1_SS 0 +#define SUP_MCS_TX_MAX_NUM_2_SS BIT(2) +#define SUP_MCS_TX_MAX_NUM_3_SS BIT(3) +#define SUP_MCS_TX_MAX_NUM_4_SS BITS(2, 3) + +#define SUP_MCS_RX_BITMASK_OCTET_NUM 10 +#define SUP_MCS_RX_DEFAULT_HIGHEST_RATE 0 /* Not specify */ + +/* 7.3.2.56.5 HT Extended Capabilities field */ +#define HT_EXT_CAP_PCO BIT(0) +#define HT_EXT_CAP_PCO_TRANSITION_TIME BITS(1, 2) +#define HT_EXT_CAP_MCS_FEEDBACK BITS(8, 9) +#define HT_EXT_CAP_HTC_SUPPORT BIT(10) +#define HT_EXT_CAP_RD_RESPONDER BIT(11) + +#define HT_EXT_CAP_PCO_TRANS_TIME_NONE 0 +#define HT_EXT_CAP_PCO_TRANS_TIME_400US BIT(1) +#define HT_EXT_CAP_PCO_TRANS_TIME_1_5MS BIT(2) +#define HT_EXT_CAP_PCO_TRANS_TIME_5MS BITS(1, 2) + +#define HT_EXT_CAP_MCS_FEEDBACK_NO_FB 0 +#define HT_EXT_CAP_MCS_FEEDBACK_UNSOLICITED BIT(9) +#define HT_EXT_CAP_MCS_FEEDBACK_BOTH BITS(8, 9) + +/* 7.3.2.56.6 Transmit Beamforming Capabilities field */ + +/* 7.3.2.56.7 Antenna Selection Capability field */ +#define ASEL_CAP_CAPABLE BIT(0) +#define ASEL_CAP_CSI_FB_BY_TX_ASEL_CAPABLE BIT(1) +#define ASEL_CAP_ANT_INDICES_FB_BY_TX_ASEL_CAPABLE BIT(2) +#define ASEL_CAP_EXPLICIT_CSI_FB_CAPABLE BIT(3) +#define ASEL_CAP_ANT_INDICES_CAPABLE BIT(4) +#define ASEL_CAP_RX_ASEL_CAPABLE BIT(5) +#define ASEL_CAP_TX_SOUNDING_CAPABLE BIT(6) + +/* 7.3.2.57 HT Operation element */ +#define ELEM_MAX_LEN_HT_OP (24 - ELEM_HDR_LEN) /* sizeof(IE_HT_OP_T)-2 */ + +#define HT_OP_INFO1_SCO BITS(0, 1) +#define HT_OP_INFO1_STA_CHNL_WIDTH BIT(2) +#define HT_OP_INFO1_RIFS_MODE BIT(3) + +#define HT_OP_INFO2_HT_PROTECTION BITS(0, 1) +#define HT_OP_INFO2_NON_GF_HT_STA_PRESENT BIT(2) +#define HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT BIT(4) + +#define HT_OP_INFO3_DUAL_BEACON BIT(6) +#define HT_OP_INFO3_DUAL_CTS_PROTECTION BIT(7) +#define HT_OP_INFO3_STBC_BEACON BIT(8) +#define HT_OP_INFO3_LSIG_TXOP_FULL_SUPPORT BIT(9) +#define HT_OP_INFO3_PCO_ACTIVE BIT(10) +#define HT_OP_INFO3_PCO_PHASE BIT(11) + +/* 7.3.2.59 OBSS Scan Parameter element */ +#define ELEM_MAX_LEN_OBSS_SCAN (16 - ELEM_HDR_LEN) + +/* 7.3.2.60 20/40 BSS Coexistence element */ +#define ELEM_MAX_LEN_20_40_BSS_COEXIST (3 - ELEM_HDR_LEN) + +#define BSS_COEXIST_INFO_REQ BIT(0) +#define BSS_COEXIST_40M_INTOLERANT BIT(1) +#define BSS_COEXIST_20M_REQ BIT(2) +#define BSS_COEXIST_OBSS_SCAN_EXEMPTION_REQ BIT(3) +#define BSS_COEXIST_OBSS_SCAN_EXEMPTION_GRANT BIT(4) + +/* 802.11u 7.3.2.92 Interworking IE */ +#define ELEM_MAX_LEN_INTERWORKING (11 - ELEM_HDR_LEN) + +/* 802.11u 7.3.2.93 Advertisement Protocol IE */ +#define ELEM_MAX_LEN_ADV_PROTOCOL (4 - ELEM_HDR_LEN) + +/* 802.11u 7.3.2.96 Roaming Consortium IE */ +#define ELEM_MAX_LEN_ROAMING_CONSORTIUM (19 - ELEM_HDR_LEN) + +#define IW_IE_LENGTH_ANO 1 +#define IW_IE_LENGTH_ANO_VENUE 3 +#define IW_IE_LENGTH_ANO_HESSID 7 +#define IW_IE_LENGTH_ANO_VENUE_HESSID 9 + +/* 3 Management frame body components (III): 7.4 Action frame format details. */ +/* 7.4.1 Spectrum Measurement Action frame details */ +#define ACTION_MEASUREMENT_REQ 0 /* Spectrum measurement request */ +#define ACTION_MEASUREMENT_REPORT 1 /* Spectrum measurement report */ +#define ACTION_TPC_REQ 2 /* TPC request */ +#define ACTION_TPC_REPORT 3 /* TPC report */ +#define ACTION_CHNL_SWITCH 4 /* Channel Switch Announcement */ + +/* 7.4.2 QoS Action frame details */ +#define ACTION_ADDTS_REQ 0 /* ADDTS request */ +#define ACTION_ADDTS_RSP 1 /* ADDTS response */ +#define ACTION_DELTS 2 /* DELTS */ +#define ACTION_SCHEDULE 3 /* Schedule */ +#define ACTION_QOS_MAP_CONFIGURE 4 /*Qos Map Configure*/ + +#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 */ +#define ACTION_DELTS_FRAME_LEN (24 + 7) /*category + action + WMM TSinfo:3 + reason:2*/ + +/* 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 + +/* MTK Vendor Specific OUI */ +#define ELEM_MIN_LEN_MTK_OUI 7 +#define VENDOR_OUI_MTK { 0x00, 0x0C, 0xE7 } +#define MTK_SYNERGY_CAP_SUPPORT_24G_MCS89 BIT(3) +#define MTK_SYNERGY_CAP0 0x0 +#define MTK_SYNERGY_CAP1 0x0 +#define MTK_SYNERGY_CAP2 0x0 +#define MTK_SYNERGY_CAP3 0x0 + +/* 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 */ + +#define ACTION_WNM_NOTIFICATION_REQUEST 26 +/* 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_WNM_BSS_TRANSITION_MANAGEMENT_QUERY 6 +#define ACTION_WNM_BSS_TRANSITION_MANAGEMENT_REQ 7 +#define ACTION_WNM_BSS_TRANSITION_MANAGEMENT_RSP 8 +#define ACTION_UNPROTECTED_WNM_TIMING_MEAS_LEN 12 + +/* 3 --------------- WFA frame body fields --------------- */ +#define VENDOR_OUI_WFA { 0x00, 0x50, 0xF2 } +#define VENDOR_OUI_WFA_SPECIFIC { 0x50, 0x6F, 0x9A } +#define VENDOR_OUI_TYPE_WPA 1 +#define VENDOR_OUI_TYPE_WMM 2 +#define VENDOR_OUI_TYPE_WPS 4 +#define VENDOR_OUI_TYPE_P2P 9 +#define VENDOR_OUI_TYPE_WFD 10 +#define VENDOR_OUI_TYPE_HS20 16 + +#define VENDOR_OUI_TYPE_LEN 4 /* Length of OUI and Type */ + +/* VERSION(2 octets for WPA) / SUBTYPE(1 octet)-VERSION(1 octet) fields for WMM in WFA IE */ +#define VERSION_WPA 0x0001 /* Little Endian Format */ +#define VENDOR_OUI_SUBTYPE_VERSION_WMM_INFO 0x0100 +#define VENDOR_OUI_SUBTYPE_VERSION_WMM_PARAM 0x0101 + +/* SUBTYPE(1 octet) for WMM */ +#define VENDOR_OUI_SUBTYPE_WMM_INFO 0x00 /* WMM Spec version 1.1 */ +#define VENDOR_OUI_SUBTYPE_WMM_PARAM 0x01 +#define VENDOR_OUI_SUBTYPE_WMM_TSPEC 0x02 + +/* VERSION(1 octet) for WMM */ +#define VERSION_WMM 0x01 /* WMM Spec version 1.1 */ + +/* WMM-2.1.6 QoS Control Field */ +#define WMM_QC_UP_MASK BITS(0, 2) +#define WMM_QC_EOSP BIT(4) +#define WMM_QC_ACK_POLICY_MASK BITS(5, 6) +#define WMM_QC_ACK_POLICY_OFFSET 5 +#define WMM_QC_ACK_POLICY_ACKNOWLEDGE 0 +#define WMM_QC_ACK_POLICY_NOT_ACKNOWLEDGE (1 << WMM_QC_ACK_POLICY_OFFSET) + +/* WMM-2.2.1 WMM Information Element */ +#define ELEM_MIN_LEN_WFA_OUI_TYPE_SUBTYPE 6 + +/* HOTSPOT 2.0 Indication IE*/ +#define ELEM_MAX_LEN_HS20_INDICATION 5 +#define ELEM_MIN_LEN_HS20_INDICATION 4 + +/* Hotspot Configuration*/ +#define ELEM_HS_CONFIG_DGAF_DISABLED_MASK BIT(0) /* Downstream Group-Addressed Forwarding */ + +/* 3 Control frame body */ +/* 7.2.1.7 BlockAckReq */ +#define CTRL_BAR_BAR_CONTROL_OFFSET 16 +#define CTRL_BAR_BAR_INFORMATION_OFFSET 18 + +/* 802.11-2012, 8.5.7 Radio Measurement action fields, table 8-206 */ +#define RM_ACTION_NEIGHBOR_REQUEST 4 +#define RM_ACTION_REIGHBOR_RESPONSE 5 +#define RM_ACTION_RM_REQUEST 0 +#define RM_ACTION_RM_REPORT 1 +#define RM_ACTION_LM_REQUEST 2 +#define RM_ACTION_LM_REPORT 3 +#define RM_ACTION_NEIGHBOR_REQUEST 4 +#define RM_ACTION_REIGHBOR_RESPONSE 5 + +/******************************************************************************* +* 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; + +typedef struct _BOOTP_PROTOCOL_T { + UINT_8 ucOperation; + UINT_8 ucHdrType; + UINT_8 ucHdrLen; + UINT_8 ucHops; + UINT_32 u4TransId; + UINT_16 u2Seconds; + UINT_16 u2Flags; + UINT_32 u4CIAddr; + UINT_32 u4YIAddr; + UINT_32 u4SIAddr; + UINT_32 u4GIAddr; + UINT_8 aucCHAddr[16]; + UINT_8 aucServerName[64]; + UINT_8 aucFileName[128]; + UINT_8 aucOptions[0]; +} __KAL_ATTRIB_PACKED__ BOOTP_PROTOCOL_T, *P_BOOTP_PROTOCOL_T; + +/* IEEE 802.11 WLAN Frame Structure */ +/* WLAN MAC Header (without Address 4 and QoS Control fields) */ +typedef struct _WLAN_MAC_HEADER_T { + UINT_16 u2FrameCtrl; + UINT_16 u2DurationID; + UINT_8 aucAddr1[MAC_ADDR_LEN]; + UINT_8 aucAddr2[MAC_ADDR_LEN]; + UINT_8 aucAddr3[MAC_ADDR_LEN]; + UINT_16 u2SeqCtrl; +} __KAL_ATTRIB_PACKED__ WLAN_MAC_HEADER_T, *P_WLAN_MAC_HEADER_T; + +/* WLAN MAC Header (QoS Control fields included) */ +typedef struct _WLAN_MAC_HEADER_QOS_T { + UINT_16 u2FrameCtrl; + UINT_16 u2DurationID; + UINT_8 aucAddr1[MAC_ADDR_LEN]; + UINT_8 aucAddr2[MAC_ADDR_LEN]; + UINT_8 aucAddr3[MAC_ADDR_LEN]; + UINT_16 u2SeqCtrl; + UINT_16 u2QosCtrl; +} __KAL_ATTRIB_PACKED__ WLAN_MAC_HEADER_QOS_T, *P_WLAN_MAC_HEADER_QOS_T; + +/* WLAN MAC Header (HT Control fields included) */ +typedef struct _WLAN_MAC_HEADER_HT_T { + UINT_16 u2FrameCtrl; + UINT_16 u2DurationID; + UINT_8 aucAddr1[MAC_ADDR_LEN]; + UINT_8 aucAddr2[MAC_ADDR_LEN]; + UINT_8 aucAddr3[MAC_ADDR_LEN]; + UINT_16 u2SeqCtrl; + UINT_16 u2QosCtrl; + UINT_32 u4HtCtrl; +} __KAL_ATTRIB_PACKED__ WLAN_MAC_HEADER_HT_T, *P_WLAN_MAC_HEADER_HT_T; + +/* WLAN MAC Header (Address 4 included) */ +typedef struct _WLAN_MAC_HEADER_A4_T { + UINT_16 u2FrameCtrl; + UINT_16 u2DurationID; + UINT_8 aucAddr1[MAC_ADDR_LEN]; + UINT_8 aucAddr2[MAC_ADDR_LEN]; + UINT_8 aucAddr3[MAC_ADDR_LEN]; + UINT_16 u2SeqCtrl; + UINT_8 aucAddr4[MAC_ADDR_LEN]; +} __KAL_ATTRIB_PACKED__ WLAN_MAC_HEADER_A4_T, *P_WLAN_MAC_HEADER_A4_T; + +/* WLAN MAC Header (Address 4 and QoS Control fields included) */ +typedef struct _WLAN_MAC_HEADER_A4_QOS_T { + UINT_16 u2FrameCtrl; + UINT_16 u2DurationID; + UINT_8 aucAddr1[MAC_ADDR_LEN]; + UINT_8 aucAddr2[MAC_ADDR_LEN]; + UINT_8 aucAddr3[MAC_ADDR_LEN]; + UINT_16 u2SeqCtrl; + UINT_8 aucAddr4[MAC_ADDR_LEN]; + UINT_16 u2QosCtrl; +} __KAL_ATTRIB_PACKED__ WLAN_MAC_HEADER_A4_QOS_T, *P_WLAN_MAC_HEADER_A4_QOS_T; + +typedef struct _WLAN_MAC_HEADER_A4_HT_T { + UINT_16 u2FrameCtrl; + UINT_16 u2DurationID; + UINT_8 aucAddr1[MAC_ADDR_LEN]; + UINT_8 aucAddr2[MAC_ADDR_LEN]; + UINT_8 aucAddr3[MAC_ADDR_LEN]; + UINT_16 u2SeqCtrl; + UINT_8 aucAddr4[MAC_ADDR_LEN]; + UINT_16 u2QosCtrl; + UINT_32 u4HtCtrl; +} __KAL_ATTRIB_PACKED__ WLAN_MAC_HEADER_A4_HT_T, *P_WLAN_MAC_HEADER_A4_HT_T; + +/* 7.2.3 WLAN MAC Header for Management Frame - MMPDU */ +typedef struct _WLAN_MAC_MGMT_HEADER_T { + UINT_16 u2FrameCtrl; + UINT_16 u2Duration; + UINT_8 aucDestAddr[MAC_ADDR_LEN]; + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; + UINT_8 aucBSSID[MAC_ADDR_LEN]; + UINT_16 u2SeqCtrl; +} __KAL_ATTRIB_PACKED__ WLAN_MAC_MGMT_HEADER_T, *P_WLAN_MAC_MGMT_HEADER_T; + +/* WLAN MAC Header for Management Frame (HT Control fields included) */ +typedef struct _WLAN_MAC_MGMT_HEADER_HT_T { + UINT_16 u2FrameCtrl; + UINT_16 u2DurationID; + UINT_8 aucAddr1[MAC_ADDR_LEN]; + UINT_8 aucAddr2[MAC_ADDR_LEN]; + UINT_8 aucAddr3[MAC_ADDR_LEN]; + UINT_16 u2SeqCtrl; + UINT_32 u4HtCtrl; +} __KAL_ATTRIB_PACKED__ WLAN_MAC_MGMT_HEADER_HT_T, *P_WLAN_MAC_MGMT_HEADER_HT_T; + +/* 3 WLAN CONTROL Frame */ +/* 7.2.1.4 WLAN Control Frame - PS-POLL Frame */ +typedef struct _CTRL_PSPOLL_FRAME_T { + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2AID; /* AID */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_8 aucTA[MAC_ADDR_LEN]; /* TA */ +} __KAL_ATTRIB_PACKED__ CTRL_PSPOLL_FRAME_T, *P_CTRL_PSPOLL_FRAME_T; + +/* BAR */ +typedef struct _CTRL_BAR_FRAME_T { + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* RA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* TA */ + UINT_16 u2BarControl; + UINT_8 aucBarInfo[2]; /* Variable size */ +} __KAL_ATTRIB_PACKED__ CTRL_BAR_FRAME_T, *P_CTRL_BAR_FRAME_T; + +/* 3 WLAN Management Frame. */ +/* 7.2.3.1 WLAN Management Frame - Beacon Frame */ +typedef struct _WLAN_BEACON_FRAME_T { + /* Beacon header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Beacon frame body */ + UINT_32 au4Timestamp[2]; /* Timestamp */ + UINT_16 u2BeaconInterval; /* Beacon Interval */ + UINT_16 u2CapInfo; /* Capability */ + UINT_8 aucInfoElem[1]; /* Various IEs, start from SSID */ +} __KAL_ATTRIB_PACKED__ WLAN_BEACON_FRAME_T, *P_WLAN_BEACON_FRAME_T; + +typedef struct _WLAN_BEACON_FRAME_BODY_T { + /* Beacon frame body */ + UINT_32 au4Timestamp[2]; /* Timestamp */ + UINT_16 u2BeaconInterval; /* Beacon Interval */ + UINT_16 u2CapInfo; /* Capability */ + UINT_8 aucInfoElem[1]; /* Various IEs, start from SSID */ +} __KAL_ATTRIB_PACKED__ WLAN_BEACON_FRAME_BODY_T, *P_WLAN_BEACON_FRAME_BODY_T; + +/* 7.2.3.3 WLAN Management Frame - Disassociation Frame */ +typedef struct _WLAN_DISASSOC_FRAME_T { + /* Authentication MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Disassociation frame body */ + UINT_16 u2ReasonCode; /* Reason code */ + UINT_8 aucInfoElem[1]; /* Various IEs, possible no. */ +} __KAL_ATTRIB_PACKED__ WLAN_DISASSOC_FRAME_T, *P_WLAN_DISASSOC_FRAME_T; + +/* 7.2.3.4 WLAN Management Frame - Association Request frame */ +typedef struct _WLAN_ASSOC_REQ_FRAME_T { + /* Association Request MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Association Request frame body */ + UINT_16 u2CapInfo; /* Capability information */ + UINT_16 u2ListenInterval; /* Listen interval */ + UINT_8 aucInfoElem[1]; /* Information elements, include WPA IE */ +} __KAL_ATTRIB_PACKED__ WLAN_ASSOC_REQ_FRAME_T, *P_WLAN_ASSOC_REQ_FRAME_T; + +/* 7.2.3.5 WLAN Management Frame - Association Response frame */ +typedef struct _WLAN_ASSOC_RSP_FRAME_T { + /* Association Response MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Association Response frame body */ + UINT_16 u2CapInfo; /* Capability information */ + UINT_16 u2StatusCode; /* Status code */ + UINT_16 u2AssocId; /* Association ID */ + UINT_8 aucInfoElem[1]; /* + * Information elements, such as + * supported rates, and etc. + */ +} __KAL_ATTRIB_PACKED__ WLAN_ASSOC_RSP_FRAME_T, *P_WLAN_ASSOC_RSP_FRAME_T; + +/* 7.2.3.6 WLAN Management Frame - Reassociation Request frame */ +typedef struct _WLAN_REASSOC_REQ_FRAME_T { + /* Reassociation Request MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Reassociation Request frame body */ + UINT_16 u2CapInfo; /* Capability information */ + UINT_16 u2ListenInterval; /* Listen interval */ + UINT_8 aucCurrentAPAddr[MAC_ADDR_LEN]; /* Current AP address */ + UINT_8 aucInfoElem[1]; /* Information elements, include WPA IE */ +} __KAL_ATTRIB_PACKED__ WLAN_REASSOC_REQ_FRAME_T, *P_WLAN_REASSOC_REQ_FRAME_T; + +/* + * 7.2.3.7 WLAN Management Frame - Reassociation Response frame + * (the same as Association Response frame) + */ +typedef WLAN_ASSOC_RSP_FRAME_T WLAN_REASSOC_RSP_FRAME_T, *P_WLAN_REASSOC_RSP_FRAME_T; + +/* 7.2.3.9 WLAN Management Frame - Probe Response Frame */ +typedef WLAN_BEACON_FRAME_T WLAN_PROBE_RSP_FRAME_T, *P_WLAN_PROBE_RSP_FRAME_T; + +/* 7.2.3.10 WLAN Management Frame - Authentication Frame */ +typedef struct _WLAN_AUTH_FRAME_T { + /* Authentication MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Authentication frame body */ + UINT_16 u2AuthAlgNum; /* Authentication algorithm number */ + UINT_16 u2AuthTransSeqNo; /* Authentication transaction sequence number */ + UINT_16 u2StatusCode; /* Status code */ + UINT_8 aucInfoElem[1]; /* Various IEs for Fast BSS Transition */ +} __KAL_ATTRIB_PACKED__ WLAN_AUTH_FRAME_T, *P_WLAN_AUTH_FRAME_T; + +/* 7.2.3.11 WLAN Management Frame - Deauthentication Frame */ +typedef struct _WLAN_DEAUTH_FRAME_T { + /* Authentication MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Deauthentication frame body */ + UINT_16 u2ReasonCode; /* Reason code */ + UINT_8 aucInfoElem[1]; /* Various IEs, possible no. */ +} __KAL_ATTRIB_PACKED__ WLAN_DEAUTH_FRAME_T, *P_WLAN_DEAUTH_FRAME_T; + +/* 3 Information Elements. */ +/* 7.3.2 Generic element format */ +typedef struct _IE_HDR_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucInfo[1]; +} __KAL_ATTRIB_PACKED__ IE_HDR_T, *P_IE_HDR_T; + +/* 7.3.2.1 SSID element */ +typedef struct _IE_SSID_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; +} __KAL_ATTRIB_PACKED__ IE_SSID_T, *P_IE_SSID_T; + +/* 7.3.2.2 Supported Rates element */ +typedef struct _IE_SUPPORTED_RATE_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucSupportedRates[ELEM_MAX_LEN_SUP_RATES]; +} __KAL_ATTRIB_PACKED__ IE_SUPPORTED_RATE_T, *P_IE_SUPPORTED_RATE_T; + +/* 7.3.2.4 DS Parameter Set element */ +typedef struct _IE_DS_PARAM_SET_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucCurrChnl; +} __KAL_ATTRIB_PACKED__ IE_DS_PARAM_SET_T, *P_IE_DS_PARAM_SET_T; + +/* 7.3.2.5 CF Parameter Set element */ +typedef struct _IE_CF_PARAM_SET_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucCFPCount; + UINT_8 ucCFPPeriod; + UINT_16 u2CFPMaxDur; + UINT_16 u2DurRemaining; +} __KAL_ATTRIB_PACKED__ IE_CF_PARAM_SET_T, *P_IE_CF_PARAM_SET_T; + +/* 7.3.2.6 TIM */ +typedef struct _IE_TIM_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucDTIMCount; + UINT_8 ucDTIMPeriod; + UINT_8 ucBitmapControl; + UINT_8 aucPartialVirtualMap[1]; +} __KAL_ATTRIB_PACKED__ IE_TIM_T, *P_IE_TIM_T; + +/* 7.3.2.7 IBSS Parameter Set element */ +typedef struct _IE_IBSS_PARAM_SET_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_16 u2ATIMWindow; +} __KAL_ATTRIB_PACKED__ IE_IBSS_PARAM_SET_T, *P_IE_IBSS_PARAM_SET_T; + +/* 7.3.2.8 Challenge Text element */ +typedef struct _IE_CHALLENGE_TEXT_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucChallengeText[ELEM_MAX_LEN_CHALLENGE_TEXT]; +} __KAL_ATTRIB_PACKED__ IE_CHALLENGE_TEXT_T, *P_IE_CHALLENGE_TEXT_T; + +/* 7.3.2.9 Country information element */ +#if CFG_SUPPORT_802_11D +/*! \brief COUNTRY_INFO_TRIPLET is defined for the COUNTRY_INFO_ELEM structure. */ +typedef struct _COUNTRY_INFO_TRIPLET_T { + UINT_8 ucParam1; /* + * !< If param1 >= 201, this triplet is referred to as + * Regulatory Triplet in 802_11J. + */ + UINT_8 ucParam2; + UINT_8 ucParam3; +} __KAL_ATTRIB_PACKED__ COUNTRY_INFO_TRIPLET_T, *P_COUNTRY_INFO_TRIPLET_T; + +typedef struct _COUNTRY_INFO_SUBBAND_TRIPLET_T { + UINT_8 ucFirstChnlNum; /*!< First Channel Number */ + UINT_8 ucNumOfChnl; /*!< Number of Channels */ + INT_8 cMaxTxPwrLv; /*!< Maximum Transmit Power Level */ +} __KAL_ATTRIB_PACKED__ COUNTRY_INFO_SUBBAND_TRIPLET_T, *P_COUNTRY_INFO_SUBBAND_TRIPLET_T; + +typedef struct _COUNTRY_INFO_REGULATORY_TRIPLET_T { + UINT_8 ucRegExtId; /* + * !< Regulatory Extension Identifier, should + * be greater than or equal to 201 + */ + UINT_8 ucRegClass; /* !< Regulatory Class */ + UINT_8 ucCoverageClass; /* + * !< Coverage Class, unsigned 1-octet value 0~31, + * 32~255 reserved + */ +} __KAL_ATTRIB_PACKED__ COUNTRY_INFO_REGULATORY_TRIPLET_T, *P_COUNTRY_INFO_REGULATORY_TRIPLET_T; + +typedef struct _IE_COUNTRY_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucCountryStr[3]; + COUNTRY_INFO_SUBBAND_TRIPLET_T arCountryStr[1]; +} __KAL_ATTRIB_PACKED__ IE_COUNTRY_T, *P_IE_COUNTRY_T; +#endif /* CFG_SUPPORT_802_11D */ + +/* 7.3.2.13 ERP element */ +typedef struct _IE_ERP_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucERP; +} __KAL_ATTRIB_PACKED__ IE_ERP_T, *P_IE_ERP_T; + +/* 7.3.2.14 Extended Supported Rates element */ +typedef struct _IE_EXT_SUPPORTED_RATE_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucExtSupportedRates[ELEM_MAX_LEN_EXTENDED_SUP_RATES]; +} __KAL_ATTRIB_PACKED__ IE_EXT_SUPPORTED_RATE_T, *P_IE_EXT_SUPPORTED_RATE_T; + +/* 7.3.2.15 Power Constraint element */ +typedef struct _IE_POWER_CONSTRAINT_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucLocalPowerConstraint; /* Unit: dBm */ +} __KAL_ATTRIB_PACKED__ IE_POWER_CONSTRAINT_T, *P_IE_POWER_CONSTRAINT_T; + +/* 7.3.2.16 Power Capability element */ +typedef struct _IE_POWER_CAP_T { + UINT_8 ucId; + UINT_8 ucLength; + INT_8 cMinTxPowerCap; /* Unit: dBm */ + INT_8 cMaxTxPowerCap; /* Unit: dBm */ +} __KAL_ATTRIB_PACKED__ IE_POWER_CAP_T, *P_IE_POWER_CAP_T; + +/* 7.3.2.17 TPC request element */ +typedef struct _IE_TPC_REQ_T { + UINT_8 ucId; + UINT_8 ucLength; +} __KAL_ATTRIB_PACKED__ IE_TPC_REQ_T, *P_IE_TPC_REQ_T; + +/* 7.3.2.18 TPC report element */ +typedef struct _IE_TPC_REPORT_T { + UINT_8 ucId; + UINT_8 ucLength; + INT_8 cTxPower; /* Unit: dBm */ + INT_8 cLinkMargin; /* Unit: dB */ +} __KAL_ATTRIB_PACKED__ IE_TPC_REPORT_T, *P_IE_TPC_REPORT_T; + +#if CFG_SUPPORT_DFS /* Add by Enlai */ +/* 7.3.2.19 Supported Channels element*/ +typedef struct _IE_SUPPORTED_CHANNELS_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucChannelNum[ELEM_MAX_LEN_SUPPORTED_CHANNELS * 2]; +} __KAL_ATTRIB_PACKED__ IE_SUPPORTED_CHANNELS_T, *P_IE_SUPPORTED_CHANNELS_T; + +/* 7.3.2.20 Channel Switch Announcement element */ +typedef struct _IE_CHANNEL_SWITCH_T { + UINT_8 ucId; + UINT_8 ucLength; /* 3 bytes */ + UINT_8 ucChannelSwitchMode; + UINT_8 ucNewChannelNum; + UINT_8 ucChannelSwitchCount; +} __KAL_ATTRIB_PACKED__ IE_CHANNEL_SWITCH_T, *P_IE_CHANNEL_SWITCH_T; +#endif +typedef struct _IE_EXT_CHANNEL_SWITCH_T { + UINT_8 ucId; + UINT_8 ucLength; /* 4 bytes */ + UINT_8 ucChannelSwitchMode; + UINT_8 ucOpClass; + UINT_8 ucNewChannelNum; + UINT_8 ucChannelSwitchCount; +} __KAL_ATTRIB_PACKED__ IE_EXT_CHANNEL_SWITCH_T, *P_IE_EXT_CHANNEL_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; + +struct __KAL_ATTRIB_PACKED__ RM_BCN_REPORT { + UINT_8 ucRegulatoryClass; + UINT_8 ucChannel; + UINT_8 aucStartTime[8]; + UINT_16 u2Duration; + UINT_8 ucReportInfo; + UINT_8 ucRCPI; + UINT_8 ucRSNI; + UINT_8 aucBSSID[MAC_ADDR_LEN]; + UINT_8 ucAntennaID; + UINT_8 aucParentTSF[4]; + UINT_8 aucOptElem[0]; +}; + +struct __KAL_ATTRIB_PACKED__ RM_TSM_REPORT { + UINT_64 u8ActualStartTime; + UINT_16 u2Duration; + UINT_8 aucPeerAddress[MAC_ADDR_LEN]; + UINT_8 ucTID; + UINT_8 ucReason; + UINT_32 u4TransmittedMsduCnt; + UINT_32 u4DiscardedMsduCnt; + UINT_32 u4FailedMsduCnt; + UINT_32 u4MultiRetryCnt; + UINT_32 u4CfPollLostCnt; + UINT_32 u4AvgQueDelay; + UINT_32 u4AvgDelay; + UINT_8 ucBin0Range; + UINT_32 u4Bin[6]; + UINT_8 aucOptSubElems[0]; +}; + +/* 7.3.2.23 Quiet element */ +typedef struct _IE_QUIET_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucCount; + UINT_8 ucPeriod; + UINT_16 u2Duration; + UINT_16 u2Offset; +} __KAL_ATTRIB_PACKED__ IE_QUIET_T, *P_IE_QUIET_T; + +/* 7.3.2.27 Extended Capabilities element */ +typedef struct _IE_EXT_CAP_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucCapabilities[5]; +} __KAL_ATTRIB_PACKED__ IE_EXT_CAP_T, *P_EXT_CAP_T; + +/* 7.3.2.27 hs20 Extended Capabilities element */ +typedef struct _IE_HS20_EXT_CAP_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucCapabilities[6]; +} __KAL_ATTRIB_PACKED__ IE_HS20_EXT_CAP_T, *P_HS20_EXT_CAP_T; + + +/* 7.3.2.27 Extended Capabilities element */ +typedef struct _IE_RRM_ENABLED_CAP_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucCap[5]; +} __KAL_ATTRIB_PACKED__ IE_RRM_ENABLED_CAP_T, *P_IE_RRM_ENABLED_CAP_T; + +/* 7.3.2.51 Timeout Interval element (TIE) */ +typedef struct _IE_TIMEOUT_INTERVAL_T { + UINT_8 ucId; + UINT_8 ucLength; +#define IE_TIMEOUT_INTERVAL_TYPE_RESERVED 0 +#define IE_TIMEOUT_INTERVAL_TYPE_REASSOC 1 +#define IE_TIMEOUT_INTERVAL_TYPE_KEY_LIFETIME 2 +#define IE_TIMEOUT_INTERVAL_TYPE_ASSOC_COMEBACK 3 + UINT_8 ucType; + UINT_32 u4Value; +} __KAL_ATTRIB_PACKED__ IE_TIMEOUT_INTERVAL_T; + +/* 7.3.2.56 HT Capabilities element */ +typedef struct _SUP_MCS_SET_FIELD { + UINT_8 aucRxMcsBitmask[SUP_MCS_RX_BITMASK_OCTET_NUM]; + UINT_16 u2RxHighestSupportedRate; + UINT_32 u4TxRateInfo; +} __KAL_ATTRIB_PACKED__ SUP_MCS_SET_FIELD, *P_SUP_MCS_SET_FIELD; + +typedef struct _IE_HT_CAP_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_16 u2HtCapInfo; + UINT_8 ucAmpduParam; + SUP_MCS_SET_FIELD rSupMcsSet; + UINT_16 u2HtExtendedCap; + UINT_32 u4TxBeamformingCap; + UINT_8 ucAselCap; +} __KAL_ATTRIB_PACKED__ IE_HT_CAP_T, *P_IE_HT_CAP_T; + +/* 7.3.2.57 HT Operation element */ +typedef struct _IE_HT_OP_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucPrimaryChannel; + UINT_8 ucInfo1; + UINT_16 u2Info2; + UINT_16 u2Info3; + UINT_8 aucBasicMcsSet[16]; +} __KAL_ATTRIB_PACKED__ IE_HT_OP_T, *P_IE_HT_OP_T; + +/* 7.3.2.25 RSN Information element format */ +typedef struct _RSN_INFO_ELEM_T { + UCHAR ucElemId; + UCHAR ucLength; + UINT_16 u2Version; + UINT_32 u4GroupKeyCipherSuite; + UINT_16 u2PairwiseKeyCipherSuiteCount; + UCHAR aucPairwiseKeyCipherSuite1[4]; +} __KAL_ATTRIB_PACKED__ RSN_INFO_ELEM_T, *P_RSN_INFO_ELEM_T; + +/* 7.3.2.26 WPA Information element format */ +typedef struct _WPA_INFO_ELEM_T { + UCHAR ucElemId; + UCHAR ucLength; + UCHAR aucOui[3]; + UCHAR ucOuiType; + UINT_16 u2Version; + UINT_32 u4GroupKeyCipherSuite; + UINT_16 u2PairwiseKeyCipherSuiteCount; + UCHAR aucPairwiseKeyCipherSuite1[4]; +} __KAL_ATTRIB_PACKED__ WPA_INFO_ELEM_T, *P_WPA_INFO_ELEM_T; + +/* 7.3.2.58 20/40 BSS Intolerant Channel Report element */ +typedef struct _IE_INTOLERANT_CHNL_REPORT_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucRegulatoryClass; + UINT_8 aucChannelList[1]; +} __KAL_ATTRIB_PACKED__ IE_INTOLERANT_CHNL_REPORT_T, *P_IE_INTOLERANT_CHNL_REPORT_T; + +/* 7.3.2.59 OBSS Scan Parameters element */ +typedef struct _IE_OBSS_SCAN_PARAM_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_16 u2ScanPassiveDwell; + UINT_16 u2ScanActiveDwell; + UINT_16 u2TriggerScanInterval; + UINT_16 u2ScanPassiveTotalPerChnl; + UINT_16 u2ScanActiveTotalPerChnl; + UINT_16 u2WidthTransDelayFactor; + UINT_16 u2ScanActivityThres; +} __KAL_ATTRIB_PACKED__ IE_OBSS_SCAN_PARAM_T, *P_IE_OBSS_SCAN_PARAM_T; + +/* 7.3.2.60 20/40 BSS Coexistence element */ +typedef struct _IE_20_40_COEXIST_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucData; +} __KAL_ATTRIB_PACKED__ IE_20_40_COEXIST_T, *P_IE_20_40_COEXIST_T; + +/* 7.3.2.60 20/40 BSS Coexistence element */ +typedef struct _IE_SUP_OPERATING_CLASS_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucCur; + UINT_8 ucSup[255]; +} __KAL_ATTRIB_PACKED__ IE_SUP_OPERATING_CLASS_T, *P_IE_SUP_OPERATING_CLASS_T; + +/* 8.4.2.30 BSS Load element */ +struct __KAL_ATTRIB_PACKED__ IE_BSS_LOAD { + UINT_8 ucId; + UINT_8 ucLength; + UINT_16 u2StaCnt; + UINT_8 ucChnlUtilizaion; + UINT_16 u2AvailabeAC; +}; + +/* 8.4.2.81 Bss Max Idle Period */ +struct __KAL_ATTRIB_PACKED__ IE_BSS_MAX_IDLE_PERIOD { + UINT_8 ucId; + UINT_8 ucLength; + UINT_16 u2MaxIdlePeriod; /* unit is 1000 TUs, 1024ms */ + UINT_8 ucIdleOption; /* BIT(0) is now means Protected Keep-Alive Required, other bits are reserved */ +}; + +struct __KAL_ATTRIB_PACKED__ IE_NEIGHBOR_REPORT_T { + UINT_8 ucId; /* Element ID */ + UINT_8 ucLength; /* Length */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* OUI */ + UINT_8 aucBSSIDInfo[4]; /* Type */ + UINT_8 ucOperClass; /* Hotspot Configuration */ + UINT_8 ucChnlNumber; + UINT_8 ucPhyType; + UINT_8 aucSubElem[0]; +}; + +struct __KAL_ATTRIB_PACKED__ SUB_ELEMENT_T { + UINT_8 ucSubID; + UINT_8 ucLength; + UINT_8 aucOptInfo[1]; +}; + +/* 3 7.4 Action Frame. */ +/* 7.4 Action frame format */ +typedef struct _WLAN_ACTION_FRAME { + /* Action MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Action frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucActionDetails[1]; /* Action details */ +} __KAL_ATTRIB_PACKED__ WLAN_ACTION_FRAME, *P_WLAN_ACTION_FRAME; + +/* 7.4.1.1 Spectrum Measurement Request frame format */ +typedef struct _ACTION_SM_REQ_FRAME { + /* ADDTS Request MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* ADDTS Request frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 aucInfoElem[1]; /* Information elements */ +} __KAL_ATTRIB_PACKED__ ACTION_SM_REQ_FRAME, *P_ACTION_SM_REQ_FRAME; + +/* 7.4.1.2 Spectrum Measurement Report frame format */ +typedef ACTION_SM_REQ_FRAME ACTION_SM_REPORT_FRAME, *P_ACTION_SM_REPORT_FRAME; + +/* 7.4.1.5 Channel Switch Announcement frame format */ +typedef struct _ACTION_CHANNEL_SWITCH_FRAME { + /* ADDTS Request MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* ADDTS Request frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 aucInfoElem[5]; /* Information elements */ +} __KAL_ATTRIB_PACKED__ _ACTION_CHANNEL_SWITCH_FRAME, *P_ACTION_CHANNEL_SWITCH_FRAME; + +/* 7.4.2.1 ADDTS Request frame format */ +typedef struct _ACTION_ADDTS_REQ_FRAME { + /* ADDTS Request MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* ADDTS Request frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 aucInfoElem[1]; /* + * Information elements, such as + * TS Delay, and etc. + */ +} __KAL_ATTRIB_PACKED__ ACTION_ADDTS_REQ_FRAME, *P_ACTION_ADDTS_REQ_FRAME; + +/* 7.4.2.2 ADDTS Response frame format */ +typedef struct _ACTION_ADDTS_RSP_FRAME { + /* ADDTS Response MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* ADDTS Response frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 ucStatusCode; /* WMM Status Code is of one byte */ + UINT_8 aucInfoElem[1]; /* + * Information elements, such as + * TS Delay, and etc. + */ +} __KAL_ATTRIB_PACKED__ ACTION_ADDTS_RSP_FRAME, *P_ACTION_ADDTS_RSP_FRAME; + +/* 7.4.2.3 DELTS frame format */ +typedef struct _ACTION_DELTS_FRAME { + /* DELTS MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* DELTS frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 aucTsInfo[3]; /* TS Info */ +} __KAL_ATTRIB_PACKED__ ACTION_DELTS_FRAME, *P_ACTION_DELTS_FRAME; + +/* 7.4.2.3 QOSMAP frame format */ +struct _ACTION_QOS_MAP_CONFIGURE_FRAME { + /* QOSMAP CONFIGURE 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 qosMapSet[1]; /* qosmapset */ +}; + +/* 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; + +#if CFG_SUPPORT_NCHO +/* 7.4.5.1 vendor-specific frame format */ +typedef struct _ACTION_VENDOR_SPEC_FRAME_T { + /* Action 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 */ + UINT_8 aucElemInfo[0]; /* Pointer to frame data */ +} __KAL_ATTRIB_PACKED__ ACTION_VENDOR_SPEC_FRAME_T, *P_ACTION_VENDOR_SPEC_FRAME_T; +#endif + +/* 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; + +/* 8.5.7.6/8.5.7.7 Neighbor Report Request/Response frame format */ +struct ACTION_NEIGHBOR_REPORT_FRAME { + /* Neighbor Report Request/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 */ + /* Neighbor Report Request/Response frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 aucInfoElem[1]; /* subelements */ +}; +struct IE_WFA_OSEN { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucOui[3]; + UINT_8 ucOuiType; + UINT_32 u4GroupKeyCipherSuite; + UINT_16 u2PairwiseKeyCipherSuiteCount; + UINT_8 aucPairwiseKeyCipherSuite1[4]; +}; + + +/* 3 Information Elements from WFA. */ +typedef struct _IE_WFA_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucOui[3]; + UINT_8 ucOuiType; + UINT_8 aucOuiSubTypeVersion[2]; + /* + * !< Please be noted. WPA defines a 16 bit field version + * instead of one subtype field and one version field + */ +} __KAL_ATTRIB_PACKED__ IE_WFA_T, *P_IE_WFA_T; + +/* HS20 3.1 - HS 2.0 Indication Information Element */ +typedef struct _IE_HS20_INDICATION_T { + UINT_8 ucId; /* Element ID */ + UINT_8 ucLength; /* Length */ + UINT_8 aucOui[3]; /* OUI */ + UINT_8 ucType; /* Type */ + UINT_8 ucHotspotConfig; /* Hotspot Configuration */ +} __KAL_ATTRIB_PACKED__ IE_HS20_INDICATION_T, *P_IE_HS20_INDICATION_T; + +/* WAPI Information element format */ +typedef struct _WAPI_INFO_ELEM_T { + UCHAR ucElemId; + UCHAR ucLength; + UINT_16 u2Version; + UINT_16 u2AuthKeyMgtSuiteCount; + UCHAR aucAuthKeyMgtSuite1[4]; + UINT_16 u2PairwiseKeyCipherSuiteCount; + UINT_32 au4PairwiseKeyCipherSuite; + UINT_32 u4GroupKeyCipherSuite; + UINT_16 u2WapiCap; +} __KAL_ATTRIB_PACKED__ WAPI_INFO_ELEM_T, *P_WAPI_INFO_ELEM_T; +/* Information Elements from MTK Synergies.*/ +typedef struct _IE_MTK_OUI_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucOui[3]; + UINT_8 aucCapability[4]; + UINT_8 aucInfoElem[1]; +} __KAL_ATTRIB_PACKED__ IE_MTK_OUI_T, *P_IE_MTK_OUI_T; + +typedef struct _ACTION_ECSA_T { + UINT_16 frame_control; + UINT_16 duration; + UINT_8 da[MAC_ADDR_LEN]; + UINT_8 sa[MAC_ADDR_LEN]; + UINT_8 bssid[MAC_ADDR_LEN]; + UINT_16 seq_ctrl; + + UINT_8 caegory; + UINT_8 action_code; + + UINT_8 mode; + UINT_8 new_operating_class; + UINT_8 new_ch_num; + UINT_8 count; + + UINT_8 variable[0]; +} __KAL_ATTRIB_PACKED__ ACTIOIN_ECSA_T, *P_ACTION_ECSA_T; + +typedef struct _ACTION_CSA_T { + UINT_16 frame_control; + UINT_16 duration; + UINT_8 da[MAC_ADDR_LEN]; + UINT_8 sa[MAC_ADDR_LEN]; + UINT_8 bssid[MAC_ADDR_LEN]; + UINT_16 seq_ctrl; + + UINT_8 caegory; + UINT_8 action_code; + + UINT_8 csa_id; + UINT_8 clen; + UINT_8 mode; + UINT_8 new_ch_num; + UINT_8 count; + + UINT_8 sco_id; + UINT_8 slen; + UINT_8 sco; + + UINT_8 variable[0]; +} __KAL_ATTRIB_PACKED__ ACTIOIN_CSA_T, *P_ACTION_CSA_T; + +#if defined(WINDOWS_DDK) || defined(WINDOWS_CE) +#pragma pack() +#endif + +struct __KAL_ATTRIB_PACKED__ SUB_IE_BSS_TERM_DURATION_T { + UINT_8 ucSubId; + UINT_8 ucLength; + UINT_8 aucTermTsf[8]; + UINT_16 u2Duration; +}; + +struct __KAL_ATTRIB_PACKED__ SUB_IE_BSS_CAND_PREFERENCE_T { + UINT_8 ucSubId; + UINT_8 ucLength; + UINT_8 ucPreference; +}; + +struct __KAL_ATTRIB_PACKED__ ACTION_BTM_QUERY_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 */ + /* BSS Coexistence Management frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + + UINT_8 ucDialogToken; + UINT_8 ucQueryReason; + PUINT_8 pucNeighborBss; +}; + +struct __KAL_ATTRIB_PACKED__ ACTION_BTM_REQ_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 */ + /* BSS Coexistence Management frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + + UINT_8 ucDialogToken; + UINT_8 ucRequestMode; + UINT_16 u2DisassocTimer; + UINT_8 ucValidityInterval; + UINT_8 aucOptInfo[0]; + /* Optional: Bss Termination Duration(0~12 bytes), + * Session Information URL, Bss Transition Candidate List + */ +}; + +struct __KAL_ATTRIB_PACKED__ ACTION_BTM_RSP_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 */ + /* BSS Coexistence Management frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + + UINT_8 ucDialogToken; + UINT_8 ucStatusCode; + UINT_8 ucBssTermDelay; + UINT_8 aucOptInfo[0]; + /* Optional Target BSSID and Transition Candidate Entry list */ +}; + +struct __KAL_ATTRIB_PACKED__ IE_MOBILITY_DOMAIN_T { + UINT_8 ucId; /* Element ID = 54 */ + UINT_8 ucLength; /* Length is 3 */ + UINT_16 u2MDID; + UINT_8 ucBitMap; /* Bit 0: FT over DS; Bit 1: Resource Request Protocol Capbility, others: reserved */ +}; + +struct __KAL_ATTRIB_PACKED__ IE_FAST_TRANSITION_T { + UINT_8 ucId; /* Element ID = 55 */ + UINT_8 ucLength; /* Length is variable */ + UINT_8 ucMicCtrl; /* Bit 0 ~ Bit 7: reserved; Bit 8 ~ Bit 15: IE count used to calculate MIC, 0 means No MIC*/ + UINT_8 aucMic[16]; /* */ + UINT_8 aucANonce[32]; /* Nonce of R1KH */ + UINT_8 aucSNonce[32]; /* Nonce of S1KH */ + UINT_8 aucOptParam[0]; +}; + +struct __KAL_ATTRIB_PACKED__ SUB_IE_FAST_TRANSITION_T { + UINT_8 ucSubId; /* 0, 4-255: reserved; 1: R1KH-ID; 2: GTK; 3: R0KH-ID */ + UINT_8 ucLength; /* bytes, R1KH-ID: 6; GTK: 15-42; R0KH-ID: 1-48 */ + UINT_8 aucData[1]; +}; + +struct __KAL_ATTRIB_PACKED__ SUB_IE_GTK_T { + UINT_8 ucSubId; /* subId=2 */ + UINT_8 ucLength; /* length is 15-42 */ + UINT_16 u2KeyInfo; /* Bit0-Bit1: Key ID; Bit2-Bit15: reserved */ + UINT_8 ucKeyLength; + UINT_8 aucRsc[8]; + UINT_8 aucKey[5]; +}; + +/* 8.5.7.4 Link Measurement Request frame format */ +struct __KAL_ATTRIB_PACKED__ ACTION_LM_REQUEST_FRAME { + /* Link Measurement 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 */ + /* Link Measurement Request frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 ucTxPowerUsed; /* */ + UINT_8 ucTxPowerMax; /* */ + UINT_8 aucInfoElem[1]; /* subelements */ +}; + +/* 8.5.7.5 Link Measurement Report frame format */ +struct __KAL_ATTRIB_PACKED__ ACTION_LM_REPORT_FRAME { + /* Link Measurement Report 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 */ + /* Link Measurement Report frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 aucTpcReportIE[4]; /* */ + UINT_8 ucRxAntennaID; + UINT_8 ucTxAntennaID; + UINT_8 ucRCPI; + UINT_8 ucRSNI; + UINT_8 aucInfoElem[1]; /* subelements */ +}; + +struct __KAL_ATTRIB_PACKED__ IE_REQUEST_T { + UINT_8 ucId; /* ELEM_ID_REQUEST */ + UINT_8 ucLength; /* 0 to 237 */ + UINT_8 aucReqIds[0]; +}; + +struct __KAL_ATTRIB_PACKED__ IE_AP_CHNL_REPORT_T { + UINT_8 ucId; /* ELEM_ID_AP_CHANNEL_REPORT */ + UINT_8 ucLength; /* 1 to 237 */ + UINT_8 ucOpClass; + UINT_8 aucChnlList[0]; +}; + +struct __KAL_ATTRIB_PACKED__ SUB_IE_REPORTING_DETAIL_T { + UINT_8 ucSubID; /* 2 */ + UINT_8 ucLength; + /* 0: No fixed length fields or elemets. 1: all fixed length fields and requested IEs 2: */ + UINT_8 ucDetailValue; +}; + +struct __KAL_ATTRIB_PACKED__ IE_TSPEC_BODY { + UINT_8 aucTsInfo[3]; /* 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 */ +}; + +struct __KAL_ATTRIB_PACKED__ WMM_ACTION_TSPEC_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, value is 17 */ + UINT_8 ucAction; /* Action Value, value: 2, delts */ + UINT_8 ucDlgToken; + UINT_8 ucStatusCode; + UINT_8 aucInfoElem[1]; +}; +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/* Convert the ECWmin(max) to CWmin(max) */ +#define ECW_TO_CW(_ECW) ((1 << (_ECW)) - 1) + +/* Convert the RCPI to dBm */ +#define RCPI_TO_dBm(_rcpi) \ + ((PARAM_RSSI)(((_rcpi) > RCPI_HIGH_BOUND ? RCPI_HIGH_BOUND : (_rcpi)) >> 1) - NDBM_LOW_BOUND_FOR_RCPI) + +/* Convert the dBm to RCPI */ +#define dBm_TO_RCPI(_dbm) \ + (RCPI)(((((PARAM_RSSI)(_dbm) + NDBM_LOW_BOUND_FOR_RCPI) << 1) > RCPI_HIGH_BOUND) ? RCPI_HIGH_BOUND : \ + ((((PARAM_RSSI)(_dbm) + NDBM_LOW_BOUND_FOR_RCPI) << 1) < RCPI_LOW_BOUND ? RCPI_LOW_BOUND : \ + (((PARAM_RSSI)(_dbm) + NDBM_LOW_BOUND_FOR_RCPI) << 1))) + +/* Convert an unsigned char pointer to an information element pointer */ +#define IE_ID(fp) (((P_IE_HDR_T) fp)->ucId) +#define IE_LEN(fp) (((P_IE_HDR_T) fp)->ucLength) +#define IE_SIZE(fp) (ELEM_HDR_LEN + IE_LEN(fp)) + +#define SSID_IE(fp) ((P_IE_SSID_T) fp) + +#define SUP_RATES_IE(fp) ((P_IE_SUPPORTED_RATE_T) fp) + +#define DS_PARAM_IE(fp) ((P_IE_DS_PARAM_SET_T) fp) + +#define TIM_IE(fp) ((P_IE_TIM_T) fp) + +#define IBSS_PARAM_IE(fp) ((P_IE_IBSS_PARAM_SET_T) fp) + +#define ERP_INFO_IE(fp) ((P_IE_ERP_T) fp) + +#define EXT_SUP_RATES_IE(fp) ((P_IE_EXT_SUPPORTED_RATE_T) fp) + +#define WFA_IE(fp) ((P_IE_WFA_T) fp) + +#if CFG_SUPPORT_802_11D +#define COUNTRY_IE(fp) ((P_IE_COUNTRY_T) fp) +#endif + +#define EXT_CAP_IE(fp) ((P_EXT_CAP_T) fp) + +#define HT_CAP_IE(fp) ((P_IE_HT_CAP_T) fp) + +#define HT_OP_IE(fp) ((P_IE_HT_OP_T) fp) + +#define OBSS_SCAN_PARAM_IE(fp) ((P_IE_OBSS_SCAN_PARAM_T) fp) + +#define BSS_20_40_COEXIST_IE(fp) ((P_IE_20_40_COEXIST_T) fp) + +#define SUP_OPERATING_CLASS_IE(fp) ((P_IE_SUP_OPERATING_CLASS_T) fp) + +#define QUIET_IE(fp) ((P_IE_QUIET_T) fp) +#define MTK_OUI_IE(fp) ((P_IE_MTK_OUI_T) fp) + + +#if CFG_SUPPORT_DFS /* Add by Enlai */ +#define SUPPORTED_CHANNELS_IE(fp) ((P_IE_SUPPORTED_CHANNELS_T)fp) +#endif + +#define TIMEOUT_INTERVAL_IE(fp) ((IE_TIMEOUT_INTERVAL_T *)fp) + +/* The macro to check if the MAC address is B/MCAST Address */ +#define IS_BMCAST_MAC_ADDR(_pucDestAddr) \ + ((BOOLEAN) (((PUINT_8)(_pucDestAddr))[0] & BIT(0))) + +/* The macro to check if the MAC address is UCAST Address */ +#define IS_UCAST_MAC_ADDR(_pucDestAddr) \ + ((BOOLEAN) !(((PUINT_8)(_pucDestAddr))[0] & BIT(0))) + +/* The macro to copy the MAC address */ +#define COPY_MAC_ADDR(_pucDestAddr, _pucSrcAddr) \ + kalMemCopy(_pucDestAddr, _pucSrcAddr, MAC_ADDR_LEN) + +/* The macro to check if two MAC addresses are equal */ +#define EQUAL_MAC_ADDR(_pucDestAddr, _pucSrcAddr) \ + (!kalMemCmp(_pucDestAddr, _pucSrcAddr, MAC_ADDR_LEN)) + +/* The macro to check if two MAC addresses are not equal */ +#define UNEQUAL_MAC_ADDR(_pucDestAddr, _pucSrcAddr) \ + (kalMemCmp(_pucDestAddr, _pucSrcAddr, MAC_ADDR_LEN)) + +/* The macro to check whether two SSIDs are equal */ +#define EQUAL_SSID(pucSsid1, ucSsidLen1, pucSsid2, ucSsidLen2) \ + ((ucSsidLen1 <= ELEM_MAX_LEN_SSID) && \ + (ucSsidLen2 <= ELEM_MAX_LEN_SSID) && \ + ((ucSsidLen1) == (ucSsidLen2)) && \ + !kalMemCmp(pucSsid1, pucSsid2, ucSsidLen1)) + +/* The macro to check whether two SSIDs are equal */ +#define UNEQUAL_SSID(pucSsid1, ucSsidLen1, pucSsid2, ucSsidLen2) \ + ((ucSsidLen1 > ELEM_MAX_LEN_SSID) || \ + (ucSsidLen2 > ELEM_MAX_LEN_SSID) || \ + ((ucSsidLen1) != (ucSsidLen2)) || \ + kalMemCmp(pucSsid1, pucSsid2, ucSsidLen1)) + +/* The macro to copy the SSID, the length of pucDestSsid should have at least 32 bytes */ +#define COPY_SSID(pucDestSsid, ucDestSsidLen, pucSrcSsid, ucSrcSsidLen) \ + do { \ + ucDestSsidLen = (ucSrcSsidLen > ELEM_MAX_LEN_SSID) \ + ? ELEM_MAX_LEN_SSID : ucSrcSsidLen; \ + if (ucDestSsidLen) { \ + kalMemCopy(pucDestSsid, pucSrcSsid, ucDestSsidLen); \ + } \ + } while (FALSE) + +/* The macro to copy the IE */ +#define COPY_IE(pucDestIE, pucSrcIE) \ + do { \ + kalMemCopy((PUINT_8)pucDestIE, \ + (PUINT_8)pucSrcIE,\ + IE_SIZE(pucSrcIE)); \ + } while (FALSE) + +#define IE_FOR_EACH(_pucIEsBuf, _u2IEsBufLen, _u2Offset) \ + for ((_u2Offset) = 0;\ + ((((_u2Offset) + 2) <= (_u2IEsBufLen)) && (((_u2Offset) + IE_SIZE(_pucIEsBuf)) <= (_u2IEsBufLen))); \ + (_u2Offset) += IE_SIZE(_pucIEsBuf), (_pucIEsBuf) += IE_SIZE(_pucIEsBuf)) + +#define SET_EXT_CAP(_aucField, _ucFieldLength, _ucBit) \ + do { \ + if ((_ucBit) < ((_ucFieldLength) * 8)) { \ + PUINT_8 aucExtCap = (PUINT_8)(_aucField); \ + ((aucExtCap)[(_ucBit) / 8]) |= BIT((_ucBit) % 8); \ + } \ + } while (FALSE) + +#define TEST_EXT_CAP(_aucField, _ucFieldLength, _ucBit) \ + ((((_ucFieldLength) * 8) > (_ucBit)) && (((_aucField)[(_ucBit) / 8]) & BIT((_ucBit) % 8))) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _MAC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/mtreg.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/mtreg.h new file mode 100644 index 0000000000000..3cf56ec27e859 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/mtreg.h @@ -0,0 +1,258 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _MTREG_H +#define _MTREG_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/* 1 MT6628 MCR Definition */ + +/* 2 Host Interface */ + +/* 4 CHIP ID Register */ +#define MCR_WCIR 0x0000 + +/* 4 HIF Low Power Control Register */ +#define MCR_WHLPCR 0x0004 + +/* 4 Control Status Register */ +#define MCR_WSDIOCSR 0x0008 +#define MCR_WSPICSR 0x0008 + +/* 4 HIF Control Register */ +#define MCR_WHCR 0x000C + +/* 4 HIF Interrupt Status Register */ +#define MCR_WHISR 0x0010 + +/* 4 HIF Interrupt Enable Register */ +#define MCR_WHIER 0x0014 + +/* 4 Abnormal Status Register */ +#define MCR_WASR 0x0018 + +/* 4 WLAN Software Interrupt Control Register */ +#define MCR_WSICR 0x001C + +/* 4 WLAN TX Status Register */ +#define MCR_WTSR0 0x0020 + +/* 4 WLAN TX Status Register */ +#define MCR_WTSR1 0x0024 + +/* 4 WLAN TX Data Register 0 */ +#define MCR_WTDR0 0x0028 + +/* 4 WLAN TX Data Register 1 */ +#define MCR_WTDR1 0x002C + +/* 4 WLAN RX Data Register 0 */ +#define MCR_WRDR0 0x0030 + +/* 4 WLAN RX Data Register 1 */ +#define MCR_WRDR1 0x0034 + +/* 4 Host to Device Send Mailbox 0 Register */ +#define MCR_H2DSM0R 0x0038 + +/* 4 Host to Device Send Mailbox 1 Register */ +#define MCR_H2DSM1R 0x003c + +/* 4 Device to Host Receive Mailbox 0 Register */ +#define MCR_D2HRM0R 0x0040 + +/* 4 Device to Host Receive Mailbox 1 Register */ +#define MCR_D2HRM1R 0x0044 + +/* 4 Device to Host Receive Mailbox 2 Register */ +#define MCR_D2HRM2R 0x0048 + +/* 4 WLAN RX Packet Length Register */ +#define MCR_WRPLR 0x0050 + +/* 4 HSIF Transaction Count Register */ +#define MCR_HSTCR 0x0058 + +/* #if CFG_SDIO_INTR_ENHANCE */ +typedef struct _ENHANCE_MODE_DATA_STRUCT_T { + UINT_32 u4WHISR; + union { + struct { + UINT_8 ucTQ0Cnt; + UINT_8 ucTQ1Cnt; + UINT_8 ucTQ2Cnt; + UINT_8 ucTQ3Cnt; + UINT_8 ucTQ4Cnt; + UINT_8 ucTQ5Cnt; + UINT_16 u2Rsrv; + } u; + UINT_32 au4WTSR[2]; + } rTxInfo; + union { + struct { + UINT_16 u2NumValidRx0Len; + UINT_16 u2NumValidRx1Len; + UINT_16 au2Rx0Len[16]; + UINT_16 au2Rx1Len[16]; + } u; + UINT_32 au4RxStatusRaw[17]; + } rRxInfo; + UINT_32 u4RcvMailbox0; + UINT_32 u4RcvMailbox1; +} ENHANCE_MODE_DATA_STRUCT_T, *P_ENHANCE_MODE_DATA_STRUCT_T; +/* #endif */ /* ENHANCE_MODE_DATA_STRUCT_T */ + +/* 2 Definition in each register */ +/* 3 WCIR 0x0000 */ +#define WCIR_WLAN_READY BIT(21) +#define WCIR_POR_INDICATOR BIT(20) +#define WCIR_REVISION_ID BITS(16, 19) +#define WCIR_CHIP_ID BITS(0, 15) + +#define MTK_CHIP_REV_72 0x00006572 +#define MTK_CHIP_REV_82 0x00006582 +#define MTK_CHIP_REV_92 0x00006592 +#define MTK_CHIP_MP_REVERSION_ID 0x0 + +/* 3 WHLPCR 0x0004 */ +#define WHLPCR_FW_OWN_REQ_CLR BIT(9) +#define WHLPCR_FW_OWN_REQ_SET BIT(8) +#define WHLPCR_IS_DRIVER_OWN BIT(8) +#define WHLPCR_INT_EN_CLR BIT(1) +#define WHLPCR_INT_EN_SET BIT(0) + +/* 3 WSDIOCSR 0x0008 */ +#define WSDIOCSR_SDIO_RE_INIT_EN BIT(0) + +/* 3 WSPICSR 0x0008 */ +#define WCSR_SPI_MODE_SEL BITS(3, 4) +#define WCSR_SPI_ENDIAN_BIG BIT(2) +#define WCSR_SPI_INT_OUT_MODE BIT(1) +#define WCSR_SPI_DATA_OUT_MODE BIT(0) + +/* 3 WHCR 0x000C */ +#define WHCR_RX_ENHANCE_MODE_EN BIT(16) +#define WHCR_MAX_HIF_RX_LEN_NUM BITS(4, 7) +#define WHCR_W_MAILBOX_RD_CLR_EN BIT(2) +#define WHCR_W_INT_CLR_CTRL BIT(1) +#define WHCR_MCU_DBG_EN BIT(0) +#define WHCR_OFFSET_MAX_HIF_RX_LEN_NUM 4 + +/* 3 WHISR 0x0010 */ +#define WHISR_D2H_SW_INT BITS(8, 31) +#define WHISR_D2H_SW_ASSERT_INFO_INT BIT(31) +#define WHISR_FW_OWN_BACK_INT BIT(4) +#define WHISR_ABNORMAL_INT BIT(3) +#define WHISR_RX1_DONE_INT BIT(2) +#define WHISR_RX0_DONE_INT BIT(1) +#define WHISR_TX_DONE_INT BIT(0) + +/* 3 WHIER 0x0014 */ +#define WHIER_D2H_SW_INT BITS(8, 31) +#define WHIER_FW_OWN_BACK_INT_EN BIT(4) +#define WHIER_ABNORMAL_INT_EN BIT(3) +#define WHIER_RX1_DONE_INT_EN BIT(2) +#define WHIER_RX0_DONE_INT_EN BIT(1) +#define WHIER_TX_DONE_INT_EN BIT(0) +#define WHIER_DEFAULT (WHIER_RX0_DONE_INT_EN | \ + WHIER_RX1_DONE_INT_EN | \ + WHIER_TX_DONE_INT_EN | \ + WHIER_ABNORMAL_INT_EN | \ + WHIER_D2H_SW_INT \ + ) + +/* 3 WASR 0x0018 */ +#define WASR_FW_OWN_INVALID_ACCESS BIT(4) +#define WASR_RX1_UNDER_FLOW BIT(3) +#define WASR_RX0_UNDER_FLOW BIT(2) +#define WASR_TX1_OVER_FLOW BIT(1) +#define WASR_TX0_OVER_FLOW BIT(0) + +/* 3 WSICR 0x001C */ +#define WSICR_H2D_SW_INT_SET BITS(16, 31) + +/* 3 WRPLR 0x0050 */ +#define WRPLR_RX1_PACKET_LENGTH BITS(16, 31) +#define WRPLR_RX0_PACKET_LENGTH BITS(0, 15) + +/* 3 HSTCR 0x0058 */ +#define HSTCR_AFF_BURST_LEN BITS(24, 25) +#define HSTCR_AFF_BURST_LEN_OFFSET 24 +#define HSTCR_TRANS_TARGET BITS(20, 22) +#define HSTCR_TRANS_TARGET_OFFSET 20 +#define HSTCR_HSIF_TRANS_CNT BITS(2, 19) +#define HSTCR_HSIF_TRANS_CNT_OFFSET 2 + +/* HSTCR_TRANS_TARGET */ +typedef enum _eTransTarget { + TRANS_TARGET_TXD0 = 0, + TRANS_TARGET_TXD1, + TRANS_TARGET_RXD0, + TRANS_TARGET_RXD1, + TRANS_TARGET_WHISR, + NUM_TRANS_TARGET +} E_TRANS_TARGET_T; + +typedef enum _E_AFF_BURST_LEN { + BURST_1_DW = 0, + BURST_4_DW, + BURST_8_DW, + BURST_RSV, + NUM_AFF_BURST_LEN +} E_AFF_BURST_LEN; + +#endif /* _MTREG_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/nic.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/nic.h new file mode 100644 index 0000000000000..fffd5350ce6d8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/nic.h @@ -0,0 +1,306 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _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, +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP + IE_UPD_METHOD_UPDATE_PROBE_RSP, +#endif +} ENUM_IE_UPD_METHOD_T, *P_ENUM_IE_UPD_METHOD_T; + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +extern BOOLEAN fgIsResetting; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Routines in nic.c */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicAllocateAdapterMemory(IN P_ADAPTER_T prAdapter); + +VOID nicReleaseAdapterMemory(IN P_ADAPTER_T prAdapter); + +VOID nicDisableInterrupt(IN P_ADAPTER_T prAdapter); + +VOID nicEnableInterrupt(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS nicProcessIST(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS nicProcessIST_impl(IN P_ADAPTER_T prAdapter, IN UINT_32 u4IntStatus); + +WLAN_STATUS nicInitializeAdapter(IN P_ADAPTER_T prAdapter); + +VOID nicMCRInit(IN P_ADAPTER_T prAdapter); + +BOOLEAN nicVerifyChipID(IN P_ADAPTER_T prAdapter); + +#if CFG_SDIO_INTR_ENHANCE +VOID nicSDIOInit(IN P_ADAPTER_T prAdapter); + +VOID nicSDIOReadIntStatus(IN P_ADAPTER_T prAdapter, OUT PUINT_32 pu4IntStatus); +#endif + +BOOLEAN nicpmSetDriverOwn(IN P_ADAPTER_T prAdapter); + +VOID nicpmSetFWOwn(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnableGlobalInt); + +BOOLEAN nicpmSetAcpiPowerD0(IN P_ADAPTER_T prAdapter); + +BOOLEAN nicpmSetAcpiPowerD3(IN P_ADAPTER_T prAdapter); + +#if defined(_HIF_SPI) +void nicRestoreSpiDefMode(IN P_ADAPTER_T prAdapter); +#endif + +VOID nicProcessSoftwareInterrupt(IN P_ADAPTER_T prAdapter); + +VOID nicProcessAbnormalInterrupt(IN P_ADAPTER_T prAdapter); + +VOID nicPutMailbox(IN P_ADAPTER_T prAdapter, IN UINT_32 u4MailboxNum, IN UINT_32 u4Data); + +VOID nicGetMailbox(IN P_ADAPTER_T prAdapter, IN UINT_32 u4MailboxNum, OUT PUINT_32 pu4Data); + +VOID nicSetSwIntr(IN P_ADAPTER_T prAdapter, IN UINT_32 u4SwIntrBitmap); + +P_CMD_INFO_T nicGetPendingCmdInfo(IN P_ADAPTER_T prAdapter, IN UINT_8 ucSeqNum); + +P_MSDU_INFO_T nicGetPendingTxMsduInfo(IN P_ADAPTER_T prAdapter, IN UINT_8 ucSeqNum); + +P_MSDU_INFO_T nicGetPendingStaMMPDU(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIdx); + +VOID nicFreePendingTxMsduInfoByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType); + +UINT_8 nicIncreaseCmdSeqNum(IN P_ADAPTER_T prAdapter); + +UINT_8 nicIncreaseTxSeqNum(IN P_ADAPTER_T prAdapter); + +/* Media State Change */ +WLAN_STATUS +nicMediaStateChange(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType, IN P_EVENT_CONNECTION_STATUS prConnectionStatus); + +/* Utility function for channel number conversion */ +UINT_32 nicChannelNum2Freq(IN UINT_32 u4ChannelNum); + +UINT_32 nicFreq2ChannelNum(IN UINT_32 u4FreqInKHz); + +/* firmware command wrapper */ + /* NETWORK (WIFISYS) */ +WLAN_STATUS nicActivateNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); + +WLAN_STATUS nicDeactivateNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); + + /* BSS-INFO */ +WLAN_STATUS nicUpdateBss(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); + + /* BSS-INFO Indication (PM) */ +WLAN_STATUS nicPmIndicateBssCreated(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); + +WLAN_STATUS nicPmIndicateBssConnected(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); + +WLAN_STATUS nicPmIndicateBssAbort(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); + + /* Beacon Template Update */ +WLAN_STATUS +nicUpdateBeaconIETemplate(IN P_ADAPTER_T prAdapter, + IN ENUM_IE_UPD_METHOD_T eIeUpdMethod, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN UINT_16 u2Capability, IN PUINT_8 aucIe, IN UINT_16 u2IELen); + +WLAN_STATUS nicQmUpdateWmmParms(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); + +WLAN_STATUS nicQmSetRxBASize(IN P_ADAPTER_T prAdapter, BOOLEAN enable, UINT32 size); + +WLAN_STATUS nicSetAutoTxPower(IN P_ADAPTER_T prAdapter, IN P_CMD_AUTO_POWER_PARAM_T prAutoPwrParam); + +WLAN_STATUS nicSetUApsdParam(IN P_ADAPTER_T prAdapter, + IN PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T rUapsdParams, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); + +/*----------------------------------------------------------------------------*/ +/* Calibration Control */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicUpdateTxPower(IN P_ADAPTER_T prAdapter, IN P_CMD_TX_PWR_T prTxPwrParam); +#if CFG_SUPPORT_TX_POWER_BACK_OFF +WLAN_STATUS nicUpdateTxPowerOffset(IN P_ADAPTER_T prAdapter, + IN P_CMD_MITIGATED_PWR_OFFSET_T prTxPwrOffsetParam); +WLAN_STATUS nicTxPowerBackOff(IN P_ADAPTER_T prAdapter, IN UINT32 TxPowerBackOffParam); +#endif +WLAN_STATUS nicUpdate5GOffset(IN P_ADAPTER_T prAdapter, IN P_CMD_5G_PWR_OFFSET_T pr5GPwrOffset); + +WLAN_STATUS nicUpdateDPD(IN P_ADAPTER_T prAdapter, IN P_CMD_PWR_PARAM_T prDpdCalResult); + +/*----------------------------------------------------------------------------*/ +/* PHY configuration */ +/*----------------------------------------------------------------------------*/ +VOID nicSetAvailablePhyTypeSet(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* MGMT and System Service Control */ +/*----------------------------------------------------------------------------*/ +VOID nicInitSystemService(IN P_ADAPTER_T prAdapter); + +VOID nicResetSystemService(IN P_ADAPTER_T prAdapter); + +VOID nicUninitSystemService(IN P_ADAPTER_T prAdapter); + +VOID nicInitMGMT(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo); + +VOID nicUninitMGMT(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS +nicConfigPowerSaveProfile(IN P_ADAPTER_T prAdapter, + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, PARAM_POWER_MODE ePwrMode, BOOLEAN fgEnCmdEvent); + +WLAN_STATUS nicEnterCtiaMode(IN P_ADAPTER_T prAdapter, BOOLEAN fgEnterCtia, BOOLEAN fgEnCmdEvent); +/*----------------------------------------------------------------------------*/ +/* Scan Result Processing */ +/*----------------------------------------------------------------------------*/ +UINT_32 +nicAddScanResult(IN P_ADAPTER_T prAdapter, + IN PARAM_MAC_ADDRESS rMacAddr, + IN P_PARAM_SSID_T prSsid, + IN UINT_16 u2CapInfo, + 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 + +#if CFG_SUPPORT_SET_CAM_BY_PROC +VOID nicForceSetCAM(BOOLEAN enabled); +#endif + +#endif /* _NIC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/nic_rx.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/nic_rx.h new file mode 100644 index 0000000000000..d0a2e474a08c6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/nic_rx.h @@ -0,0 +1,280 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _NIC_RX_H +#define _NIC_RX_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +extern void kalDevLoopbkRxHandle(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb); + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define MAX_SEQ_NO 4095 +#define MAX_SEQ_NO_COUNT 4096 +#define HALF_SEQ_NO_CNOUT 2048 + +#define HALF_SEQ_NO_COUNT 2048 + +#define MT6620_FIXED_WIN_SIZE 64 +#define CFG_RX_MAX_BA_ENTRY 4 +#define CFG_RX_MAX_BA_TID_NUM 8 + +#if (CFG_SRAM_SIZE_OPTION == 1) +/* set default RXBA size to 16, for DIR-635/DIR-655 IOT issue + * (ALPS02494017 BA size must be power of 2) + */ +#define IOT_RX_BA_SIZE 16 +#elif (CFG_SRAM_SIZE_OPTION == 0) +#define IOT_RX_BA_SIZE 8 +#endif + +#define RX_STATUS_FLAG_MORE_PACKET BIT(30) +#define RX_STATUS_CHKSUM_MASK BITS(0, 10) + +#define RX_RFB_LEN_FIELD_LEN 4 +#define RX_HEADER_OFFSET 2 + +#define RX_RETURN_INDICATED_RFB_TIMEOUT_SEC 3 + +#define RX_FW_FLUSH_PKT_THRESHOLD 20 + + +#if defined(_HIF_SDIO) && defined(WINDOWS_DDK) +/*! On XP, maximum Tx+Rx Statue <= 64-4(HISR)*/ +#define SDIO_MAXIMUM_RX_LEN_NUM 0 /*!< 0~15 (0: un-limited) */ +#else +#define SDIO_MAXIMUM_RX_LEN_NUM 0 /*!< 0~15 (0: un-limited) */ +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_RX_STATISTIC_COUNTER_T { + RX_MPDU_TOTAL_COUNT = 0, + RX_SIZE_ERR_DROP_COUNT, + + RX_DATA_INDICATION_COUNT, + RX_DATA_RETURNED_COUNT, + RX_DATA_RETAINED_COUNT, + + RX_DROP_TOTAL_COUNT, + RX_TYPE_ERR_DROP_COUNT, + RX_CLASS_ERR_DROP_COUNT, + RX_DST_NULL_DROP_COUNT, + +#if CFG_TCP_IP_CHKSUM_OFFLOAD || CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 + RX_CSUM_TCP_FAILED_COUNT, + RX_CSUM_UDP_FAILED_COUNT, + RX_CSUM_IP_FAILED_COUNT, + RX_CSUM_TCP_SUCCESS_COUNT, + RX_CSUM_UDP_SUCCESS_COUNT, + RX_CSUM_IP_SUCCESS_COUNT, + RX_CSUM_UNKNOWN_L4_PKT_COUNT, + RX_CSUM_UNKNOWN_L3_PKT_COUNT, + RX_IP_V6_PKT_CCOUNT, +#endif + RX_STATISTIC_COUNTER_NUM +} ENUM_RX_STATISTIC_COUNTER_T; + +typedef enum _ENUM_RX_PKT_DESTINATION_T { + RX_PKT_DESTINATION_HOST, /* to OS */ + RX_PKT_DESTINATION_FORWARD, /* to TX queue for forward, AP mode */ + RX_PKT_DESTINATION_HOST_WITH_FORWARD, /* to both TX and OS, AP mode broadcast packet */ + RX_PKT_DESTINATION_NULL, /* packet to be freed */ + RX_PKT_DESTINATION_NUM +} ENUM_RX_PKT_DESTINATION_T; + +struct _SW_RFB_T { + QUE_ENTRY_T rQueEntry; + PVOID pvPacket; /*!< ptr to rx Packet Descriptor */ + PUINT_8 pucRecvBuff; /*!< ptr to receive data buffer */ + P_HIF_RX_HEADER_T prHifRxHdr; + UINT_32 u4HifRxHdrFlag; + PVOID pvHeader; + UINT_16 u2PacketLen; + UINT_16 u2HeaderLen; + UINT_16 u2SSN; + UINT_8 ucTid; + UINT_8 ucWlanIdx; + UINT_8 ucPacketType; + UINT_8 ucStaRecIdx; + + ENUM_CSUM_RESULT_T aeCSUM[CSUM_TYPE_NUM]; + ENUM_RX_PKT_DESTINATION_T eDst; + ENUM_TRAFFIC_CLASS_INDEX_T eTC; /* only valid when eDst == FORWARD */ + + UINT_64 rRxTime; +}; + +/*! RX configuration type structure */ +typedef struct _RX_CTRL_T { + UINT_32 u4RxCachedSize; + PUINT_8 pucRxCached; + QUE_T rFreeSwRfbList; + QUE_T rReceivedRfbList; + QUE_T rIndicatedRfbList; + QUE_T rUnInitializedRfbList; + +#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 + +#if CFG_SUPPORT_MULTITHREAD + QUE_T rRxDataRfbList; +#endif + +} RX_CTRL_T, *P_RX_CTRL_T; + +typedef struct _RX_MAILBOX_T { + UINT_32 u4RxMailbox[2]; /* for Device-to-Host Mailbox */ +} RX_MAILBOX_T, *P_RX_MAILBOX_T; + +typedef WLAN_STATUS(*PROCESS_RX_MGT_FUNCTION) (P_ADAPTER_T, P_SW_RFB_T); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define RX_INC_CNT(prRxCtrl, eCounter) \ + {((P_RX_CTRL_T)prRxCtrl)->au8Statistics[eCounter]++; } + +#define RX_ADD_CNT(prRxCtrl, eCounter, u8Amount) \ + {((P_RX_CTRL_T)prRxCtrl)->au8Statistics[eCounter] += (UINT_64)u8Amount; } + +#define RX_GET_CNT(prRxCtrl, eCounter) \ + (((P_RX_CTRL_T)prRxCtrl)->au8Statistics[eCounter]) + +#define RX_RESET_ALL_CNTS(prRxCtrl) \ + {kalMemZero(&prRxCtrl->au8Statistics[0], sizeof(prRxCtrl->au8Statistics)); } + +#define RX_STATUS_TEST_MORE_FLAG(flag) \ + ((BOOLEAN)((flag & RX_STATUS_FLAG_MORE_PACKET) ? TRUE : FALSE)) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +VOID nicRxInitialize(IN P_ADAPTER_T prAdapter); + +VOID nicRxUninitialize(IN P_ADAPTER_T prAdapter); + +VOID nicRxProcessRFBs(IN P_ADAPTER_T prAdapter); + +#if !CFG_SDIO_INTR_ENHANCE +VOID nicRxReceiveRFBs(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS nicRxReadBuffer(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb); + +#else +VOID nicRxSDIOReceiveRFBs(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS +nicRxEnhanceReadBuffer(IN P_ADAPTER_T prAdapter, + IN UINT_32 u4DataPort, IN UINT_16 u2RxLength, IN OUT P_SW_RFB_T prSwRfb); +#endif /* CFG_SDIO_INTR_ENHANCE */ + +#if CFG_SDIO_RX_AGG +VOID nicRxSDIOAggReceiveRFBs(IN P_ADAPTER_T prAdapter); +#endif + +WLAN_STATUS nicRxSetupRFB(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prRfb); + +VOID nicRxReturnRFB(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID nicRxReturnRFBwithUninit(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb + , IN BOOLEAN fgIsUninitRfb); + +VOID nicProcessRxInterrupt(IN P_ADAPTER_T prAdapter); + +VOID nicRxProcessPktWithoutReorder(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID nicRxProcessForwardPkt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID nicRxProcessGOBroadcastPkt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID nicRxFillRFB(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb); + +VOID nicRxProcessDataPacket(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb); + +VOID nicRxProcessEventPacket(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb); + +VOID nicRxProcessMgmtPacket(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +VOID nicRxFillChksumStatus(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb, IN UINT_32 u4TcpUdpIpCksStatus); + +VOID nicRxUpdateCSUMStatistics(IN P_ADAPTER_T prAdapter, IN const ENUM_CSUM_RESULT_T aeCSUM[]); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +VOID nicRxQueryStatus(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuffer, OUT PUINT_32 pu4Count); + +VOID nicRxClearStatistics(IN P_ADAPTER_T prAdapter); + +VOID nicRxQueryStatistics(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuffer, OUT PUINT_32 pu4Count); + +WLAN_STATUS +nicRxWaitResponse(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucPortIdx, OUT PUINT_8 pucRspBuffer, IN UINT_32 u4MaxRespBufferLen, OUT PUINT_32 pu4Length); + +VOID nicRxEnablePromiscuousMode(IN P_ADAPTER_T prAdapter); + +VOID nicRxDisablePromiscuousMode(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS nicRxFlush(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS nicRxProcessActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +#endif /* _NIC_RX_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/nic_tx.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/nic_tx.h new file mode 100644 index 0000000000000..290de73613bd6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/nic_tx.h @@ -0,0 +1,417 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _NIC_TX_H +#define _NIC_TX_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define NIC_TX_RESOURCE_POLLING_TIMEOUT 256 +#define NIC_TX_RESOURCE_POLLING_DELAY_MSEC 50 + +/* Maximum buffer count for individual HIF TCQ */ + +#if defined(MT6620) +#if CFG_SLT_SUPPORT + /* 20101215 mtk01725 Redistributed the initial TC resources for SLT operation */ +#define NIC_TX_BUFF_COUNT_TC0 0 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC1 16 /* First connection: 32 */ +#define NIC_TX_BUFF_COUNT_TC2 0 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC3 0 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC4 4 /* First connection: 2 */ +#define NIC_TX_BUFF_COUNT_TC5 0 /* First connection: 0 */ +#else + /* 20100302 mtk02468 Redistributed the initial TC resources for normal operation */ +#define NIC_TX_BUFF_COUNT_TC0 6 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC1 8 /* First connection: 32 */ +#define NIC_TX_BUFF_COUNT_TC2 8 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC3 8 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC4 4 /* First connection: 2 */ +#define NIC_TX_BUFF_COUNT_TC5 2 /* First connection: 0 */ +#endif +#elif defined(MT6628) +#if (CFG_SRAM_SIZE_OPTION == 0) +#define NIC_TX_BUFF_COUNT_TC0 1 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC1 20 /* First connection: 32 */ +#define NIC_TX_BUFF_COUNT_TC2 1 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC3 1 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC4 4 /* First connection: 2 */ +#define NIC_TX_BUFF_COUNT_TC5 1 /* First connection: 0 */ +#elif (CFG_SRAM_SIZE_OPTION == 1) +#define NIC_TX_BUFF_COUNT_TC0 1 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC1 36 /* First connection: 32 */ +#define NIC_TX_BUFF_COUNT_TC2 1 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC3 1 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC4 4 /* First connection: 2 */ +#define NIC_TX_BUFF_COUNT_TC5 1 /* First connection: 0 */ +#elif (CFG_SRAM_SIZE_OPTION == 2) +#define NIC_TX_BUFF_COUNT_TC0 1 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC1 48 /* First connection: 32 */ +#define NIC_TX_BUFF_COUNT_TC2 1 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC3 1 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC4 4 /* First connection: 2 */ +#define NIC_TX_BUFF_COUNT_TC5 1 /* First connection: 0 */ +#else +#error "> Set TX_BUFF_COUNT_TC error!" +#endif +#endif + +#define NIC_TX_BUFF_SUM (NIC_TX_BUFF_COUNT_TC0 + \ + NIC_TX_BUFF_COUNT_TC1 + \ + NIC_TX_BUFF_COUNT_TC2 + \ + NIC_TX_BUFF_COUNT_TC3 + \ + NIC_TX_BUFF_COUNT_TC4 + \ + NIC_TX_BUFF_COUNT_TC5) +#if CFG_ENABLE_FW_DOWNLOAD + +#define NIC_TX_INIT_BUFF_COUNT_TC0 8 +#define NIC_TX_INIT_BUFF_COUNT_TC1 0 +#define NIC_TX_INIT_BUFF_COUNT_TC2 0 +#define NIC_TX_INIT_BUFF_COUNT_TC3 0 +#define NIC_TX_INIT_BUFF_COUNT_TC4 0 +#define NIC_TX_INIT_BUFF_COUNT_TC5 0 + +#define NIC_TX_INIT_BUFF_SUM (NIC_TX_INIT_BUFF_COUNT_TC0 + \ + NIC_TX_INIT_BUFF_COUNT_TC1 + \ + NIC_TX_INIT_BUFF_COUNT_TC2 + \ + NIC_TX_INIT_BUFF_COUNT_TC3 + \ + NIC_TX_INIT_BUFF_COUNT_TC4 + \ + NIC_TX_INIT_BUFF_COUNT_TC5) + +#endif + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE +#define NIC_TX_TIME_THRESHOLD 100 /* in unit of ms */ +#endif + +#define MSDU_OPT_PROTECTED_FRAME BIT(13) + +/******************************************************************************* +* 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_FW_FLUSH = 78, + TX_RESULT_NUM +} ENUM_TX_RESULT_CODE_T, *P_ENUM_TX_RESULT_CODE_T; + +struct _WLAN_CFG_ENTRY_T { + UINT_8 aucKey[WLAN_CFG_KEY_LEN_MAX]; + UINT_8 aucValue[WLAN_CFG_VALUE_LEN_MAX]; + WLAN_CFG_SET_CB pfSetCb; + PVOID pPrivate; + UINT_32 u4Flags; +}; + +struct _WLAN_CFG_T { + UINT_32 u4WlanCfgEntryNumMax; + UINT_32 u4WlanCfgKeyLenMax; + UINT_32 u4WlanCfgValueLenMax; + WLAN_CFG_ENTRY_T arWlanCfgBuf[WLAN_CFG_ENTRY_NUM_MAX]; +}; + +/* TX Call Back Function */ +typedef WLAN_STATUS(*PFN_TX_DONE_HANDLER) (IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE +typedef struct _PKT_PROFILE_T { + BOOLEAN fgIsValid; +#if CFG_PRINT_RTP_PROFILE + BOOLEAN fgIsPrinted; + UINT_16 u2IpSn; + UINT_16 u2RtpSn; + UINT_8 ucTcxFreeCount; +#endif + OS_SYSTIME rHardXmitArrivalTimestamp; + OS_SYSTIME rEnqueueTimestamp; + OS_SYSTIME rDequeueTimestamp; + OS_SYSTIME rHifTxDoneTimestamp; +} PKT_PROFILE_T, *P_PKT_PROFILE_T; +#endif + +/* TX transactions could be divided into 4 kinds: + * + * 1) 802.1X / Bluetooth-over-Wi-Fi Security Frames + * [CMD_INFO_T] - [prPacket] - in skb or NDIS_PACKET form + * + * 2) MMPDU + * [CMD_INFO_T] - [prPacket] - [MSDU_INFO_T] - [prPacket] - direct buffer for frame body + * + * 3) Command Packets + * [CMD_INFO_T] - [pucInfoBuffer] - direct buffer for content of command packet + * + * 4) Normal data frame + * [MSDU_INFO_T] - [prPacket] - in skb or NDIS_PACKET form + */ + +/* PS_FORWARDING_TYPE_NON_PS means that the receiving STA is in Active Mode +* from the perspective of host driver (maybe not synchronized with FW --> SN is needed) +*/ + +struct _MSDU_INFO_T { + QUE_ENTRY_T rQueEntry; + P_NATIVE_PACKET prPacket; + + ENUM_TX_PACKET_SRC_T eSrc; /* specify OS/FORWARD packet */ + UINT_8 ucUserPriority; + + /* For composing HIF TX header */ + UINT_8 ucTC; /* Traffic Class: 0~4 (HIF TX0), 5 (HIF TX1) */ + UINT_8 ucPacketType; /* 0: Data, 1: Command, 2: HIF Loopback 3: Management Frame */ + UINT_8 ucStaRecIndex; + UINT_8 ucNetworkType; /* See ENUM_NETWORK_TYPE_T */ + UINT_8 ucFormatID; /* 0: MAUI, Linux, Windows NDIS 5.1 */ + BOOLEAN fgIs802_1x; /* TRUE: 802.1x frame */ + BOOLEAN fgIs802_11; /* TRUE: 802.11 header is present */ + UINT_16 u2PalLLH; /* PAL Logical Link Header (for BOW network) */ + UINT_16 u2AclSN; /* ACL Sequence Number (for BOW network) */ + UINT_8 ucPsForwardingType; /* See ENUM_PS_FORWARDING_TYPE_T */ + UINT_8 ucPsSessionID; /* PS Session ID specified by the FW for the STA */ + BOOLEAN fgIsBurstEnd; /* TRUE means this is the last packet of the burst for (STA, TID) */ + BOOLEAN fgIsBIP; /* Management Frame Protection */ + BOOLEAN fgIsBasicRate; /* Force Basic Rate Transmission */ + + /* flattened from PACKET_INFO_T */ + UINT_8 ucMacHeaderLength; + UINT_8 ucLlcLength; /* w/o EtherType */ + UINT_16 u2FrameLength; + UINT_8 aucEthDestAddr[MAC_ADDR_LEN]; /* Ethernet Destination Address */ + + /* for TX done tracking */ + UINT_8 ucTxSeqNum; + PFN_TX_DONE_HANDLER pfTxDoneHandler; + BOOLEAN fgNeedTxDoneStatus; + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + PKT_PROFILE_T rPktProfile; +#endif + UINT_64 u8Cookie; + COMMAND_TYPE eCmdType; + UINT_8 ucCID; + UINT_32 u4InqueTime; + UINT_32 u4DbgTxPktStatusIndex; + +}; + + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define TX_INC_CNT(prTxCtrl, eCounter) \ + {((P_TX_CTRL_T)prTxCtrl)->au4Statistics[eCounter]++; } + +#define TX_ADD_CNT(prTxCtrl, eCounter, u8Amount) \ + {((P_TX_CTRL_T)prTxCtrl)->au4Statistics[eCounter] += (UINT_32)u8Amount; } + +#define TX_GET_CNT(prTxCtrl, eCounter) \ + (((P_TX_CTRL_T)prTxCtrl)->au4Statistics[eCounter]) + +#define TX_RESET_ALL_CNTS(prTxCtrl) \ + {kalMemZero(&prTxCtrl->au4Statistics[0], sizeof(prTxCtrl->au4Statistics)); } + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE +#define PRINT_PKT_PROFILE(_pkt_profile, _note) \ +{ \ + if (!(_pkt_profile)->fgIsPrinted) { \ + DBGLOG(TX, TRACE, "X[%u] E[%u] D[%u] HD[%u] B[%d] RTP[%d] %s\n", \ + (UINT_32)((_pkt_profile)->rHardXmitArrivalTimestamp), \ + (UINT_32)((_pkt_profile)->rEnqueueTimestamp), \ + (UINT_32)((_pkt_profile)->rDequeueTimestamp), \ + (UINT_32)((_pkt_profile)->rHifTxDoneTimestamp), \ + (UINT_8)((_pkt_profile)->ucTcxFreeCount), \ + (UINT_16)((_pkt_profile)->u2RtpSn), \ + (_note)); \ + (_pkt_profile)->fgIsPrinted = TRUE; \ + } \ +} + +#define CHK_PROFILES_DELTA(_pkt1, _pkt2, _delta) \ + (CHECK_FOR_TIMEOUT((_pkt1)->rHardXmitArrivalTimestamp, (_pkt2)->rHardXmitArrivalTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt1)->rEnqueueTimestamp, (_pkt2)->rEnqueueTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt1)->rDequeueTimestamp, (_pkt2)->rDequeueTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt1)->rHifTxDoneTimestamp, (_pkt2)->rHifTxDoneTimestamp, (_delta))) + +#define CHK_PROFILE_DELTA(_pkt, _delta) \ + (CHECK_FOR_TIMEOUT((_pkt)->rEnqueueTimestamp, (_pkt)->rHardXmitArrivalTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt)->rDequeueTimestamp, (_pkt)->rEnqueueTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt)->rHifTxDoneTimestamp, (_pkt)->rDequeueTimestamp, (_delta))) +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID nicTxInitialize(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS nicTxAcquireResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC, IN BOOLEAN pfgIsSecOrMgmt); + +WLAN_STATUS nicTxPollingResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC); + +BOOLEAN nicTxReleaseResource(IN P_ADAPTER_T prAdapter, IN UINT_8 *aucTxRlsCnt); + +WLAN_STATUS nicTxResetResource(IN P_ADAPTER_T prAdapter); + +UINT_8 nicTxGetResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC); + +WLAN_STATUS nicTxMsduInfoList(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead); + +WLAN_STATUS nicTxMsduQueue(IN P_ADAPTER_T prAdapter, UINT_8 ucPortIdx, P_QUE_T prQue); + +WLAN_STATUS nicTxCmd(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN UINT_8 ucTC); + +VOID nicTxRelease(IN P_ADAPTER_T prAdapter); + +VOID nicProcessTxInterrupt(IN P_ADAPTER_T prAdapter); + +VOID nicTxFreeMsduInfoPacket(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead); + +VOID nicTxReturnMsduInfo(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead); + +BOOLEAN nicTxFillMsduInfo(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN P_NATIVE_PACKET prNdisPacket); + +WLAN_STATUS nicTxAdjustTcq(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS nicTxFlush(IN P_ADAPTER_T prAdapter); + +#if CFG_ENABLE_FW_DOWNLOAD +WLAN_STATUS nicTxInitCmd(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN UINT_8 ucTC); + +WLAN_STATUS nicTxInitResetResource(IN P_ADAPTER_T prAdapter); +#endif + +WLAN_STATUS nicTxEnqueueMsdu(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +UINT_32 nicTxGetFreeCmdCount(IN P_ADAPTER_T prAdapter); + +VOID nicTxConfigPktOption(IN P_MSDU_INFO_T prMsduInfo, IN UINT_32 u4OptionMask, + IN BOOLEAN fgSetOption); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _NIC_TX_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/p2p.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/p2p.h new file mode 100644 index 0000000000000..1c7c5cdc97255 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/p2p.h @@ -0,0 +1,165 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _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-" + +#define MAX_GC_DEAUTH_RETRY_COUNT 1 + +#define P2P_DEAUTH_TIMEOUT_TIME_MS 1000 + +#define P2P_AP_CHNL_HOLD_TIME_MS 5000 + +#define P2P_CHNL_EXTEND_CHAN_TIME 500 + +#define AP_DEFAULT_CHANNEL_2G 6 +#define AP_DEFAULT_CHANNEL_5G 36 + +#define P2P_MAX_AKM_SUITES 2 + +/******************************************************************************* +* 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; + +/* P2P public action frames */ +enum P2P_ACTION_FRAME_TYPE { + P2P_GO_NEG_REQ = 0, + P2P_GO_NEG_RESP = 1, + P2P_GO_NEG_CONF = 2, + P2P_INVITATION_REQ = 3, + P2P_INVITATION_RESP = 4, + P2P_DEV_DISC_REQ = 5, + P2P_DEV_DISC_RESP = 6, + P2P_PROV_DISC_REQ = 7, + P2P_PROV_DISC_RESP = 8 +}; + +struct P2P_QUEUED_ACTION_FRAME { + int32_t u4Freq; + uint8_t *prHeader; + uint16_t u2Length; +}; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#endif /*_P2P_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/p2p_cmd_buf.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/p2p_cmd_buf.h new file mode 100644 index 0000000000000..16a82a843dfc5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/p2p_cmd_buf.h @@ -0,0 +1,71 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _P2P_CMD_BUF_H +#define _P2P_CMD_BUF_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/*--------------------------------------------------------------*/ +/* Firmware Command Packer */ +/*--------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendSetQueryP2PCmd(IN P_ADAPTER_T prAdapter, + UINT_8 ucCID, + BOOLEAN fgSetQuery, + BOOLEAN fgNeedResp, + BOOLEAN fgIsOid, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + UINT_32 u4SetQueryInfoLen, + PUINT_8 pucInfoBuffer, OUT PVOID pvSetQueryBuffer, IN UINT_32 u4SetQueryBufferLen); + +#endif /* _P2P_CMD_BUF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/p2p_mac.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/p2p_mac.h new file mode 100644 index 0000000000000..c3ff25c8affc0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/p2p_mac.h @@ -0,0 +1,210 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _P2P_MAC_H +#define _P2P_MAC_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define ACTION_PUBLIC_WIFI_DIRECT 9 +#define ACTION_GAS_INITIAL_REQUEST 10 +#define ACTION_GAS_INITIAL_RESPONSE 11 +#define ACTION_GAS_COMEBACK_REQUEST 12 +#define ACTION_GAS_COMEBACK_RESPONSE 13 + +/* P2P 4.2.8.1 - P2P Public Action Frame Type. */ +#define P2P_PUBLIC_ACTION_GO_NEGO_REQ 0 +#define P2P_PUBLIC_ACTION_GO_NEGO_RSP 1 +#define P2P_PUBLIC_ACTION_GO_NEGO_CFM 2 +#define P2P_PUBLIC_ACTION_INVITATION_REQ 3 +#define P2P_PUBLIC_ACTION_INVITATION_RSP 4 +#define P2P_PUBLIC_ACTION_DEV_DISCOVER_REQ 5 +#define P2P_PUBLIC_ACTION_DEV_DISCOVER_RSP 6 +#define P2P_PUBLIC_ACTION_PROV_DISCOVERY_REQ 7 +#define P2P_PUBLIC_ACTION_PROV_DISCOVERY_RSP 8 + +/* P2P 4.2.9.1 - P2P Action Frame Type */ +#define P2P_ACTION_NOTICE_OF_ABSENCE 0 +#define P2P_ACTION_P2P_PRESENCE_REQ 1 +#define P2P_ACTION_P2P_PRESENCE_RSP 2 +#define P2P_ACTION_GO_DISCOVER_REQ 3 + +#define P2P_PUBLIC_ACTION_FRAME_LEN (WLAN_MAC_MGMT_HEADER_LEN+8) +#define P2P_ACTION_FRAME_LEN (WLAN_MAC_MGMT_HEADER_LEN+7) + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/* P2P 4.2.8.2 P2P Public Action Frame Format */ +typedef struct _P2P_PUBLIC_ACTION_FRAME_T { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* P2P Public Action Frame Body */ + UINT_8 ucCategory; /* Category, 0x04 */ + UINT_8 ucAction; /* Action Value, 0x09 */ + UINT_8 aucOui[3]; /* 0x50, 0x6F, 0x9A */ + UINT_8 ucOuiType; /* 0x09 */ + UINT_8 ucOuiSubtype; /* GO Nego Req/Rsp/Cfm, P2P Invittion Req/Rsp, Device Discoverability Req/Rsp */ + UINT_8 ucDialogToken; /* Dialog Token. */ + UINT_8 aucInfoElem[1]; /* P2P IE, WSC IE. */ +} __KAL_ATTRIB_PACKED__ P2P_PUBLIC_ACTION_FRAME_T, *P_P2P_PUBLIC_ACTION_FRAME_T; + +/* P2P 4.2.9.1 - General Action Frame Format. */ +typedef struct _P2P_ACTION_FRAME_T { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* P2P Action Frame Body */ + UINT_8 ucCategory; /* 0x7F */ + UINT_8 aucOui[3]; /* 0x50, 0x6F, 0x9A */ + UINT_8 ucOuiType; /* 0x09 */ + UINT_8 ucOuiSubtype; /* */ + UINT_8 ucDialogToken; + UINT_8 aucInfoElem[1]; +} __KAL_ATTRIB_PACKED__ P2P_ACTION_FRAME_T, *P_P2P_ACTION_FRAME_T; + +/* P2P C.1 GAS Public Action Initial Request Frame Format */ +typedef struct _GAS_PUBLIC_ACTION_INITIAL_REQUEST_FRAME_T { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* P2P Public Action Frame Body */ + UINT_8 ucCategory; /* Category, 0x04 */ + UINT_8 ucAction; /* Action Value, 0x09 */ + UINT_8 ucDialogToken; /* Dialog Token. */ + UINT_8 aucInfoElem[1]; /* Advertisement IE. */ +} __KAL_ATTRIB_PACKED__ GAS_PUBLIC_ACTION_INITIAL_REQUEST_FRAME_T, *P_GAS_PUBLIC_ACTION_INITIAL_REQUEST_FRAME_T; + +/* P2P C.2 GAS Public Action Initial Response Frame Format */ +typedef struct _GAS_PUBLIC_ACTION_INITIAL_RESPONSE_FRAME_T { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* P2P Public Action Frame Body */ + UINT_8 ucCategory; /* Category, 0x04 */ + UINT_8 ucAction; /* Action Value, 0x09 */ + UINT_8 ucDialogToken; /* Dialog Token. */ + UINT_16 u2StatusCode; /* Initial Response. */ + UINT_16 u2ComebackDelay; /* Initial Response. *//* In unit of TU. */ + UINT_8 aucInfoElem[1]; /* Advertisement IE. */ +} __KAL_ATTRIB_PACKED__ GAS_PUBLIC_ACTION_INITIAL_RESPONSE_FRAME_T, *P_GAS_PUBLIC_ACTION_INITIAL_RESPONSE_FRAME_T; + +/* P2P C.3-1 GAS Public Action Comeback Request Frame Format */ +typedef struct _GAS_PUBLIC_ACTION_COMEBACK_REQUEST_FRAME_T { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* P2P Public Action Frame Body */ + UINT_8 ucCategory; /* Category, 0x04 */ + UINT_8 ucAction; /* Action Value, 0x09 */ + UINT_8 ucDialogToken; /* Dialog Token. */ +} __KAL_ATTRIB_PACKED__ GAS_PUBLIC_ACTION_COMEBACK_REQUEST_FRAME_T, *P_GAS_PUBLIC_ACTION_COMEBACK_REQUEST_FRAME_T; + +/* P2P C.3-2 GAS Public Action Comeback Response Frame Format */ +typedef struct _GAS_PUBLIC_ACTION_COMEBACK_RESPONSE_FRAME_T { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* P2P Public Action Frame Body */ + UINT_8 ucCategory; /* Category, 0x04 */ + UINT_8 ucAction; /* Action Value, 0x09 */ + UINT_8 ucDialogToken; /* Dialog Token. */ + UINT_16 u2StatusCode; /* Comeback Response. */ + UINT_8 ucFragmentID; /*Comeback Response. */ + UINT_16 u2ComebackDelay; /* Comeback Response. */ + UINT_8 aucInfoElem[1]; /* Advertisement IE. */ +} __KAL_ATTRIB_PACKED__ GAS_PUBLIC_ACTION_COMEBACK_RESPONSE_FRAME_T, *P_GAS_PUBLIC_ACTION_COMEBACK_RESPONSE_FRAME_T; + +typedef struct _P2P_SD_VENDER_SPECIFIC_CONTENT_T { + /* Service Discovery Vendor-specific Content. */ + UINT_8 ucOuiSubtype; /* 0x09 */ + UINT_16 u2ServiceUpdateIndicator; + UINT_8 aucServiceTLV[1]; +} __KAL_ATTRIB_PACKED__ P2P_SD_VENDER_SPECIFIC_CONTENT_T, *P_P2P_SD_VENDER_SPECIFIC_CONTENT_T; + +typedef struct _P2P_SERVICE_REQUEST_TLV_T { + UINT_16 u2Length; + UINT_8 ucServiceProtocolType; + UINT_8 ucServiceTransID; + UINT_8 aucQueryData[1]; +} __KAL_ATTRIB_PACKED__ P2P_SERVICE_REQUEST_TLV_T, *P_P2P_SERVICE_REQUEST_TLV_T; + +typedef struct _P2P_SERVICE_RESPONSE_TLV_T { + UINT_16 u2Length; + UINT_8 ucServiceProtocolType; + UINT_8 ucServiceTransID; + UINT_8 ucStatusCode; + UINT_8 aucResponseData[1]; +} __KAL_ATTRIB_PACKED__ P2P_SERVICE_RESPONSE_TLV_T, *P_P2P_SERVICE_RESPONSE_TLV_T; + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/p2p_nic.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/p2p_nic.h new file mode 100644 index 0000000000000..0123da613f01d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/p2p_nic.h @@ -0,0 +1,65 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _P2P_NIC_H +#define _P2P_NIC_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +VOID +nicP2pMediaStateChange(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType, IN P_EVENT_CONNECTION_STATUS prConnectionStatus); + +VOID +nicRxAddP2pDevice(IN P_ADAPTER_T prAdapter, + IN P_EVENT_P2P_DEV_DISCOVER_RESULT_T prP2pResult, IN PUINT_8 pucRxIEBuf, IN UINT_16 u2RxIELength); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/p2p_nic_cmd_event.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/p2p_nic_cmd_event.h new file mode 100644 index 0000000000000..9e1c14fa788f7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/p2p_nic_cmd_event.h @@ -0,0 +1,75 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _P2P_NIC_CMD_EVENT_H +#define _P2P_NIC_CMD_EVENT_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +typedef struct _EVENT_P2P_DEV_DISCOVER_RESULT_T { +/* UINT_8 aucCommunicateAddr[MAC_ADDR_LEN]; // Deprecated. */ + UINT_8 aucDeviceAddr[MAC_ADDR_LEN]; /* Device Address. */ + UINT_8 aucInterfaceAddr[MAC_ADDR_LEN]; /* Device Address. */ + UINT_8 ucDeviceCapabilityBitmap; + UINT_8 ucGroupCapabilityBitmap; + UINT_16 u2ConfigMethod; /* Configure Method. */ + P2P_DEVICE_TYPE_T rPriDevType; + UINT_8 ucSecDevTypeNum; + P2P_DEVICE_TYPE_T arSecDevType[2]; + UINT_16 u2NameLength; + UINT_8 aucName[32]; + PUINT_8 pucIeBuf; + UINT_16 u2IELength; + UINT_8 aucBSSID[MAC_ADDR_LEN]; + /* TODO: Service Information or PasswordID valid? */ +} EVENT_P2P_DEV_DISCOVER_RESULT_T, *P_EVENT_P2P_DEV_DISCOVER_RESULT_T; + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/que_mgt.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/que_mgt.h new file mode 100644 index 0000000000000..c93e646408720 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/que_mgt.h @@ -0,0 +1,909 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _QUE_MGT_H +#define _QUE_MGT_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/* Queue Manager Features */ +/* 1: Indicate the last TX packet to the FW for each burst */ +#define QM_BURST_END_INFO_ENABLED 1 +/* 1: To fairly share TX resource among active STAs */ +#define QM_FORWARDING_FAIRNESS 1 +/* 1: To adaptively adjust resource for each TC */ +#define QM_ADAPTIVE_TC_RESOURCE_CTRL 1 +/* 1: To print TC resource adjustment results */ +#define QM_PRINT_TC_RESOURCE_CTRL 0 +/* 1: If pkt with SSN is missing, auto advance the RX reordering window */ +#define QM_RX_WIN_SSN_AUTO_ADVANCING 1 +/* 1: Indicate the packets falling behind to OS before the frame with SSN is received */ +#define QM_RX_INIT_FALL_BEHIND_PASS 1 +/* 1: Count times of TC resource empty happened */ +#define QM_TC_RESOURCE_EMPTY_COUNTER 1 +/* Parameters */ + +/* + * In TDLS or AP mode, peer maybe enter "sleep mode". + * + * If QM_INIT_TIME_TO_UPDATE_QUE_LEN = 60 when peer is in sleep mode, + * we need to wait 60 * u4TimeToAdjustTcResource = 180 packets + * u4TimeToAdjustTcResource = 3, + * then we will adjust TC resouce for VI or VO. + * + * But in TDLS test case, the throughput is very low, only 0.8Mbps in 5.7, + * we will to wait about 12 seconds to collect 180 packets. + * but the test time is only 20 seconds. + */ +#define QM_INIT_TIME_TO_UPDATE_QUE_LEN 60 /* p: Update queue lengths when p TX packets are enqueued */ +#define QM_INIT_TIME_TO_UPDATE_QUE_LEN_MIN 5 + +#define QM_INIT_TIME_TO_ADJUST_TC_RSC 3 /* s: Adjust the TC resource every s updates of queue lengths */ +#define QM_QUE_LEN_MOVING_AVE_FACTOR 3 /* Factor for Que Len averaging */ + +#define QM_MIN_RESERVED_TC0_RESOURCE 1 +#define QM_MIN_RESERVED_TC1_RESOURCE 1 +#define QM_MIN_RESERVED_TC2_RESOURCE 1 +#define QM_MIN_RESERVED_TC3_RESOURCE 1 +#define QM_MIN_RESERVED_TC4_RESOURCE 2 /* Resource for TC4 is not adjustable */ +#define QM_MIN_RESERVED_TC5_RESOURCE 1 + +#if defined(MT6620) + +#define QM_GUARANTEED_TC0_RESOURCE 4 +#define QM_GUARANTEED_TC1_RESOURCE 4 +#define QM_GUARANTEED_TC2_RESOURCE 9 +#define QM_GUARANTEED_TC3_RESOURCE 11 +#define QM_GUARANTEED_TC4_RESOURCE 2 /* Resource for TC4 is not adjustable */ +#define QM_GUARANTEED_TC5_RESOURCE 4 + +#elif defined(MT6628) + +#define QM_GUARANTEED_TC0_RESOURCE 4 +#define QM_GUARANTEED_TC1_RESOURCE 4 +#define QM_GUARANTEED_TC2_RESOURCE 6 +#define QM_GUARANTEED_TC3_RESOURCE 6 +#define QM_GUARANTEED_TC4_RESOURCE 2 /* Resource for TC4 is not adjustable */ +#define QM_GUARANTEED_TC5_RESOURCE 4 + +#else +#error +#endif + +#define QM_EXTRA_RESERVED_RESOURCE_WHEN_BUSY 0 + +#define QM_TOTAL_TC_RESOURCE (\ + NIC_TX_BUFF_COUNT_TC0 + NIC_TX_BUFF_COUNT_TC1 +\ + NIC_TX_BUFF_COUNT_TC2 + NIC_TX_BUFF_COUNT_TC3 +\ + NIC_TX_BUFF_COUNT_TC5) +#define QM_AVERAGE_TC_RESOURCE 6 + +/* Note: QM_INITIAL_RESIDUAL_TC_RESOURCE shall not be less than 0 */ +/* for 6628: QM_TOTAL_TC_RESOURCE = 28, RESIDUAL = 4 4 6 6 2 4 = 26 */ +#define QM_INITIAL_RESIDUAL_TC_RESOURCE (QM_TOTAL_TC_RESOURCE - \ + (QM_GUARANTEED_TC0_RESOURCE +\ + QM_GUARANTEED_TC1_RESOURCE +\ + QM_GUARANTEED_TC2_RESOURCE +\ + QM_GUARANTEED_TC3_RESOURCE +\ + QM_GUARANTEED_TC5_RESOURCE \ + )) + +/* Hard-coded network type for Phase 3: NETWORK_TYPE_AIS/P2P/BOW */ +#define QM_OPERATING_NETWORK_TYPE NETWORK_TYPE_AIS + +#define QM_TEST_MODE 0 +#define QM_TEST_TRIGGER_TX_COUNT 50 +#define QM_TEST_STA_REC_DETERMINATION 0 +#define QM_TEST_STA_REC_DEACTIVATION 0 +#define QM_TEST_FAIR_FORWARDING 0 + +#define QM_DEBUG_COUNTER 0 + +/* Per-STA Queues: [0] AC0, [1] AC1, [2] AC2, [3] AC3, [4] 802.1x */ +/* Per-Type Queues: [0] BMCAST */ +#define NUM_OF_PER_STA_TX_QUEUES 5 +#define NUM_OF_PER_TYPE_TX_QUEUES 1 + +/* These two constants are also used for FW to verify the STA_REC index */ +#define STA_REC_INDEX_BMCAST 0xFF +#define STA_REC_INDEX_NOT_FOUND 0xFE + +/* TX Queue Index */ +#define TX_QUEUE_INDEX_BMCAST 0 +#define TX_QUEUE_INDEX_NO_STA_REC 0 +#define TX_QUEUE_INDEX_AC0 0 +#define TX_QUEUE_INDEX_AC1 1 +#define TX_QUEUE_INDEX_AC2 2 +#define TX_QUEUE_INDEX_AC3 3 +#define TX_QUEUE_INDEX_802_1X 4 +#define TX_QUEUE_INDEX_NON_QOS 1 + +/* 1 WMM-related */ +/* WMM FLAGS */ +#define WMM_FLAG_SUPPORT_WMM BIT(0) +#define WMM_FLAG_SUPPORT_WMMSA BIT(1) +#define WMM_FLAG_AC_PARAM_PRESENT BIT(2) +#define WMM_FLAG_SUPPORT_UAPSD BIT(3) + +/* WMM Admission Control Mandatory FLAGS */ +#define ACM_FLAG_ADM_NOT_REQUIRED 0 +#define ACM_FLAG_ADM_GRANTED BIT(0) +#define ACM_FLAG_ADM_REQUIRED BIT(1) + +/* WMM Power Saving FLAGS */ +#define AC_FLAG_TRIGGER_ENABLED BIT(1) +#define AC_FLAG_DELIVERY_ENABLED BIT(2) + +/* WMM-2.2.1 WMM Information Element */ +#define ELEM_MAX_LEN_WMM_INFO 7 + +/* WMM-2.2.2 WMM Parameter Element */ +#define ELEM_MAX_LEN_WMM_PARAM 24 + +/* WMM-2.2.1 WMM QoS Info field */ +#define WMM_QOS_INFO_PARAM_SET_CNT BITS(0, 3) /* Sent by AP */ +#define WMM_QOS_INFO_UAPSD BIT(7) + +#define WMM_QOS_INFO_VO_UAPSD BIT(0) /* Sent by non-AP STA */ +#define WMM_QOS_INFO_VI_UAPSD BIT(1) +#define WMM_QOS_INFO_BK_UAPSD BIT(2) +#define WMM_QOS_INFO_BE_UAPSD BIT(3) +#define WMM_QOS_INFO_MAX_SP_LEN_MASK BITS(5, 6) +#define WMM_QOS_INFO_MAX_SP_ALL 0 +#define WMM_QOS_INFO_MAX_SP_2 BIT(5) +#define WMM_QOS_INFO_MAX_SP_4 BIT(6) +#define WMM_QOS_INFO_MAX_SP_6 BITS(5, 6) + +/* -- definitions for Max SP length field */ +#define WMM_MAX_SP_LENGTH_ALL 0 +#define WMM_MAX_SP_LENGTH_2 2 +#define WMM_MAX_SP_LENGTH_4 4 +#define WMM_MAX_SP_LENGTH_6 6 + +/* WMM-2.2.2 WMM ACI/AIFSN field */ +/* -- subfields in the ACI/AIFSN field */ +#define WMM_ACIAIFSN_AIFSN BITS(0, 3) +#define WMM_ACIAIFSN_ACM BIT(4) +#define WMM_ACIAIFSN_ACI BITS(5, 6) +#define WMM_ACIAIFSN_ACI_OFFSET 5 + +/* -- definitions for ACI field */ +#define WMM_ACI_AC_BE 0 +#define WMM_ACI_AC_BK BIT(5) +#define WMM_ACI_AC_VI BIT(6) +#define WMM_ACI_AC_VO BITS(5, 6) + +#define WMM_ACI(_AC) (_AC << WMM_ACIAIFSN_ACI_OFFSET) + +/* -- definitions for ECWmin/ECWmax field */ +#define WMM_ECW_WMIN_MASK BITS(0, 3) +#define WMM_ECW_WMAX_MASK BITS(4, 7) +#define WMM_ECW_WMAX_OFFSET 4 + +#define TXM_DEFAULT_FLUSH_QUEUE_GUARD_TIME 0 /* Unit: 64 us */ + +#define DEFAULT_QM_RX_BA_ENTRY_MISS_TIMEOUT_MS (200) +#define SHORT_QM_RX_BA_ENTRY_MISS_TIMEOUT_MS (50) + +#if CFG_RX_BA_REORDERING_ENHANCEMENT +#define QM_RX_MAX_FW_DROP_SSN_SIZE 8 +#define QM_SSN_MASK 0xFFF0 +#endif + +/******************************************************************************* +* 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 _EVENT_CHECK_REORDER_BUBBLE_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 ucTid; +} EVENT_CHECK_REORDER_BUBBLE_T, *P_EVENT_CHECK_REORDER_BUBBLE_T; + + +typedef struct _RX_BA_ENTRY_T { + BOOLEAN fgIsValid; + QUE_T rReOrderQue; +#if CFG_RX_BA_REORDERING_ENHANCEMENT + QUE_T rNoNeedWaitQue; +#endif + UINT_16 u2WinStart; + UINT_16 u2WinEnd; + UINT_16 u2WinSize; + + /* For identifying the RX BA agreement */ + UINT_8 ucStaRecIdx; + UINT_8 ucTid; + TIMER_T rReorderBubbleTimer; + UINT_16 u2FirstBubbleSn; + + BOOLEAN fgIsWaitingForPktWithSsn; + BOOLEAN fgHasBubble; + BOOLEAN fgHasBubbleInQue; + + /* UINT_8 ucTxBufferSize; */ + /* BOOL fgIsAcConstrain; */ + /* BOOL fgIsBaEnabled; */ +} RX_BA_ENTRY_T, *P_RX_BA_ENTRY_T; + +/* The mailbox message (could be used for Host-To-Device or Device-To-Host Mailbox) */ +typedef struct _MAILBOX_MSG_T { + UINT_32 u4Msg[2]; /* [0]: D2HRM0R or H2DRM0R, [1]: D2HRM1R or H2DRM1R */ +} MAILBOX_MSG_T, *P_MAILBOX_MSG_T; + +/* Used for adaptively adjusting TC resources */ +typedef struct _TC_RESOURCE_CTRL_T { + /* TC0, TC1, TC2, TC3, TC5 */ + UINT_32 au4AverageQueLen[TC_NUM - 1]; +} TC_RESOURCE_CTRL_T, *P_TC_RESOURCE_CTRL_T; + +typedef struct _QUE_MGT_T { /* Queue Management Control Info */ + + /* Per-Type Queues: [0] BMCAST or UNKNOWN-STA packets */ + QUE_T arTxQueue[NUM_OF_PER_TYPE_TX_QUEUES]; + +#if 0 + /* For TX Scheduling */ + UINT_8 arRemainingTxOppt[NUM_OF_PER_STA_TX_QUEUES]; + UINT_8 arCurrentTxStaIndex[NUM_OF_PER_STA_TX_QUEUES]; + +#endif + + /* Reordering Queue Parameters */ + RX_BA_ENTRY_T arRxBaTable[CFG_NUM_OF_RX_BA_AGREEMENTS]; + + /* Current number of activated RX BA agreements <= CFG_NUM_OF_RX_BA_AGREEMENTS */ + UINT_8 ucRxBaCount; + +#if QM_TEST_MODE + UINT_32 u4PktCount; + P_ADAPTER_T prAdapter; + +#if QM_TEST_FAIR_FORWARDING + UINT_32 u4CurrentStaRecIndexToEnqueue; +#endif + +#endif + +#if QM_FORWARDING_FAIRNESS + /* The current TX count for a STA with respect to a TC index */ + UINT_32 au4ForwardCount[NUM_OF_PER_STA_TX_QUEUES]; + + /* The current serving STA with respect to a TC index */ + UINT_32 au4HeadStaRecIndex[NUM_OF_PER_STA_TX_QUEUES]; +#endif + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + UINT_32 au4AverageQueLen[TC_NUM]; + UINT_32 au4CurrentTcResource[TC_NUM]; + UINT_32 au4MinReservedTcResource[TC_NUM]; /* The minimum amount of resource no matter busy or idle */ + UINT_32 au4GuaranteedTcResource[TC_NUM]; /* The minimum amount of resource when extremely busy */ + + UINT_32 u4TimeToAdjustTcResource; + UINT_32 u4TimeToUpdateQueLen; + UINT_32 u4TxNumOfVi, u4TxNumOfVo; /* number of VI/VO packets */ + + /* + * Set to TRUE if the last TC adjustment has not been completely applied (i.e., waiting more TX-Done events + * to align the TC quotas to the TC resource assignment) + */ + BOOLEAN fgTcResourcePostAnnealing; + +#endif + +#if QM_DEBUG_COUNTER + UINT_32 au4QmDebugCounters[QM_DBG_CNT_NUM]; +#endif +#if QM_TC_RESOURCE_EMPTY_COUNTER + UINT_32 au4QmTcResourceEmptyCounter[NET_TYPE_NUM][TC_NUM]; + UINT_32 au4QmTcResourceBackCounter[TC_NUM]; + UINT_32 au4DequeueNoTcResourceCounter[TC_NUM]; + + UINT_32 au4ResourceUsedCounter[TC_NUM]; + + UINT_32 au4ResourceWantedCounter[TC_NUM]; + + UINT_32 u4EnqeueuCounter; + UINT_32 u4DequeueCounter; +#endif +} QUE_MGT_T, *P_QUE_MGT_T; + +typedef struct _EVENT_RX_ADDBA_T { + /* Event header */ + UINT_16 u2Length; + UINT_16 u2Reserved1; /* Must be filled with 0x0001 (EVENT Packet) */ + UINT_8 ucEID; + UINT_8 ucSeqNum; + UINT_8 aucReserved2[2]; + + /* Fields not present in the received ADDBA_REQ */ + UINT_8 ucStaRecIdx; + + /* Fields that are present in the received ADDBA_REQ */ + UINT_8 ucDialogToken; /* Dialog Token chosen by the sender */ + UINT_16 u2BAParameterSet; /* BA policy, TID, buffer size */ + UINT_16 u2BATimeoutValue; + UINT_16 u2BAStartSeqCtrl; /* SSN */ + +} EVENT_RX_ADDBA_T, *P_EVENT_RX_ADDBA_T; + +typedef struct _EVENT_RX_DELBA_T { + /* Event header */ + UINT_16 u2Length; + UINT_16 u2Reserved1; /* Must be filled with 0x0001 (EVENT Packet) */ + UINT_8 ucEID; + UINT_8 ucSeqNum; + UINT_8 aucReserved2[2]; + + /* Fields not present in the received ADDBA_REQ */ + UINT_8 ucStaRecIdx; + UINT_8 ucTid; +} EVENT_RX_DELBA_T, *P_EVENT_RX_DELBA_T; + +typedef struct _EVENT_BSS_ABSENCE_PRESENCE_T { + /* Event header */ + UINT_16 u2Length; + UINT_16 u2Reserved1; /* Must be filled with 0x0001 (EVENT Packet) */ + UINT_8 ucEID; + UINT_8 ucSeqNum; + UINT_8 aucReserved2[2]; + + /* Event Body */ + UINT_8 ucNetTypeIdx; + BOOLEAN fgIsAbsent; + UINT_8 ucBssFreeQuota; + UINT_8 aucReserved[1]; +} EVENT_BSS_ABSENCE_PRESENCE_T, *P_EVENT_BSS_ABSENCE_PRESENCE_T; + +typedef struct _EVENT_STA_CHANGE_PS_MODE_T { + /* Event header */ + UINT_16 u2Length; + UINT_16 u2Reserved1; /* Must be filled with 0x0001 (EVENT Packet) */ + UINT_8 ucEID; + UINT_8 ucSeqNum; + UINT_8 aucReserved2[2]; + + /* Event Body */ + UINT_8 ucStaRecIdx; + BOOLEAN fgIsInPs; + UINT_8 ucUpdateMode; + UINT_8 ucFreeQuota; +} EVENT_STA_CHANGE_PS_MODE_T, *P_EVENT_STA_CHANGE_PS_MODE_T; + +/* The free quota is used by PS only now */ +/* The event may be used by per STA flow conttrol in general */ +typedef struct _EVENT_STA_UPDATE_FREE_QUOTA_T { + /* Event header */ + UINT_16 u2Length; + UINT_16 u2Reserved1; /* Must be filled with 0x0001 (EVENT Packet) */ + UINT_8 ucEID; + UINT_8 ucSeqNum; + UINT_8 aucReserved2[2]; + + /* Event Body */ + UINT_8 ucStaRecIdx; + UINT_8 ucUpdateMode; + UINT_8 ucFreeQuota; + UINT_8 aucReserved[1]; +} EVENT_STA_UPDATE_FREE_QUOTA_T, *P_EVENT_STA_UPDATE_FREE_QUOTA_T; + +/* WMM-2.2.1 WMM Information Element */ +typedef struct _IE_WMM_INFO_T { + UINT_8 ucId; /* Element ID */ + UINT_8 ucLength; /* Length */ + UINT_8 aucOui[3]; /* OUI */ + UINT_8 ucOuiType; /* OUI Type */ + UINT_8 ucOuiSubtype; /* OUI Subtype */ + UINT_8 ucVersion; /* Version */ + UINT_8 ucQosInfo; /* QoS Info field */ + UINT_8 ucDummy[3]; /* Dummy for pack */ +} IE_WMM_INFO_T, *P_IE_WMM_INFO_T; + +/* WMM-2.2.2 WMM Parameter Element */ +typedef struct _IE_WMM_PARAM_T { + UINT_8 ucId; /* Element ID */ + UINT_8 ucLength; /* Length */ + + /* IE Body */ + UINT_8 aucOui[3]; /* OUI */ + UINT_8 ucOuiType; /* OUI Type */ + UINT_8 ucOuiSubtype; /* OUI Subtype */ + UINT_8 ucVersion; /* Version */ + + /* WMM IE Body */ + UINT_8 ucQosInfo; /* QoS Info field */ + UINT_8 ucReserved; + + /* AC Parameters */ + UINT_8 ucAciAifsn_BE; + UINT_8 ucEcw_BE; + UINT_8 aucTxopLimit_BE[2]; + + UINT_8 ucAciAifsn_BG; + UINT_8 ucEcw_BG; + UINT_8 aucTxopLimit_BG[2]; + + UINT_8 ucAciAifsn_VI; + UINT_8 ucEcw_VI; + UINT_8 aucTxopLimit_VI[2]; + + UINT_8 ucAciAifsn_VO; + UINT_8 ucEcw_VO; + UINT_8 aucTxopLimit_VO[2]; + +} IE_WMM_PARAM_T, *P_IE_WMM_PARAM_T; + +typedef struct _IE_WMM_TSPEC_T { + UINT_8 ucId; /* Element ID */ + UINT_8 ucLength; /* Length */ + UINT_8 aucOui[3]; /* OUI */ + UINT_8 ucOuiType; /* OUI Type */ + UINT_8 ucOuiSubtype; /* OUI Subtype */ + UINT_8 ucVersion; /* Version */ + /* WMM TSPEC body */ + UINT_8 aucTsInfo[3]; /* TS Info */ + UINT_8 aucTspecBodyPart[1]; /* Note: Utilize PARAM_QOS_TSPEC to fill (memory copy) */ +} IE_WMM_TSPEC_T, *P_IE_WMM_TSPEC_T; + +typedef struct _IE_WMM_HDR_T { + UINT_8 ucId; /* Element ID */ + UINT_8 ucLength; /* Length */ + UINT_8 aucOui[3]; /* OUI */ + UINT_8 ucOuiType; /* OUI Type */ + UINT_8 ucOuiSubtype; /* OUI Subtype */ + UINT_8 ucVersion; /* Version */ + UINT_8 aucBody[1]; /* IE body */ +} IE_WMM_HDR_T, *P_IE_WMM_HDR_T; + +typedef struct _AC_QUE_PARMS_T { + UINT_16 u2CWmin; /*!< CWmin */ + UINT_16 u2CWmax; /*!< CWmax */ + UINT_16 u2TxopLimit; /*!< TXOP limit */ + UINT_16 u2Aifsn; /*!< AIFSN */ + UINT_8 ucGuradTime; /*!< GuardTime for STOP/FLUSH. */ + BOOLEAN fgIsACMSet; +} AC_QUE_PARMS_T, *P_AC_QUE_PARMS_T; + +/* WMM ACI (AC index) */ +typedef enum _ENUM_WMM_ACI_T { + WMM_AC_BE_INDEX = 0, + WMM_AC_BK_INDEX, + WMM_AC_VI_INDEX, + WMM_AC_VO_INDEX, + WMM_AC_INDEX_NUM +} ENUM_WMM_ACI_T, *P_ENUM_WMM_ACI_T; + +/* WMM QOS user priority from 802.1D/802.11e */ +enum ENUM_WMM_UP_T { + WMM_UP_BE_INDEX = 0, + WMM_UP_BK_INDEX, + WMM_UP_RESV_INDEX, + WMM_UP_EE_INDEX, + WMM_UP_CL_INDEX, + WMM_UP_VI_INDEX, + WMM_UP_VO_INDEX, + WMM_UP_NC_INDEX, + WMM_UP_INDEX_NUM +}; + +/* Used for CMD Queue Operation */ +typedef enum _ENUM_FRAME_ACTION_T { + FRAME_ACTION_DROP_PKT = 0, + FRAME_ACTION_QUEUE_PKT, + FRAME_ACTION_TX_PKT, + FRAME_ACTION_NUM +} ENUM_FRAME_ACTION_T; + +typedef enum _ENUM_FRAME_TYPE_IN_CMD_Q_T { + FRAME_TYPE_802_1X = 0, + FRAME_TYPE_MMPDU, + FRAME_TYPE_NUM +} ENUM_FRAME_TYPE_IN_CMD_Q_T; + +typedef enum _ENUM_FREE_QUOTA_MODET_T { + FREE_QUOTA_UPDATE_MODE_INIT = 0, + FREE_QUOTA_UPDATE_MODE_OVERWRITE, + FREE_QUOTA_UPDATE_MODE_INCREASE, + FREE_QUOTA_UPDATE_MODE_DECREASE +} ENUM_FREE_QUOTA_MODET_T, *P_ENUM_FREE_QUOTA_MODET_T; + +typedef struct _CMD_UPDATE_WMM_PARMS_T { + AC_QUE_PARMS_T arACQueParms[AC_NUM]; + UINT_8 ucNetTypeIndex; + UINT_8 fgIsQBSS; + UINT_8 aucReserved[2]; +} CMD_UPDATE_WMM_PARMS_T, *P_CMD_UPDATE_WMM_PARMS_T; + +typedef struct _CMD_TX_AMPDU_T { + BOOLEAN fgEnable; + UINT_8 aucReserved[3]; +} CMD_TX_AMPDU_T, *P_CMD_TX_AMPDU_T; + +typedef struct _CMD_ADDBA_REJECT { + BOOLEAN fgEnable; + UINT_8 aucReserved[3]; +} CMD_ADDBA_REJECT_T, *P_CMD_ADDBA_REJECT_T; + +typedef struct _CMD_SPECIFIC_RX_BA_WIN_SIZE_T { + BOOLEAN fgEnabled; + UINT_16 SpecificRxBAWinSize; +} CMD_SPECIFIC_RX_BA_WIN_SIZE_T, *P_CMD_SPECIFIC_RX_BA_WIN_SIZE_T; + +#if CFG_RX_BA_REORDERING_ENHANCEMENT +typedef enum _ENUM_NO_NEED_WATIT_DROP_REASON_T { + PACKET_DROP_BY_FW = 0, + PACKET_DROP_BY_DRIVER, + PACKET_DROP_BY_INDEPENDENT_PKT +} ENUM_NO_NEED_WATIT_DROP_REASON_T, *P_ENUM_NO_NEED_WATIT_DROP_REASON_T; + +typedef struct _NO_NEED_WAIT_PKT_T { + QUE_ENTRY_T rQueEntry; + UINT_16 u2SSN; + ENUM_NO_NEED_WATIT_DROP_REASON_T eDropReason; +} NO_NEED_WAIT_PKT_T, *P_NO_NEED_WAIT_PKT_T; + +typedef struct _EVENT_PACKET_DROP_BY_FW_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 ucTid; + UINT_16 u2StartSSN; + UINT_8 au1BitmapSSN[QM_RX_MAX_FW_DROP_SSN_SIZE]; +} EVENT_PACKET_DROP_BY_FW_T, *P_EVENT_PACKET_DROP_BY_FW_T; +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define 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 + +#if CFG_RX_BA_REORDERING_ENHANCEMENT +#define QM_GET_PREVIOUS_SSN(_u2CurrSSN) \ + ((UINT_16) (_u2CurrSSN == 0 ? (MAX_SEQ_NO_COUNT - 1) : (_u2CurrSSN - 1))) +#define QM_GET_DROP_BY_FW_SSN(_u2SSN) \ + ((UINT_16) (_u2SSN >>= 4)) +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Queue Management and STA_REC Initialization */ +/*----------------------------------------------------------------------------*/ + +VOID qmInit(IN P_ADAPTER_T prAdapter); + +#if QM_TEST_MODE +VOID qmTestCases(IN P_ADAPTER_T prAdapter); +#endif + +VOID qmActivateStaRec(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +VOID qmDeactivateStaRec(IN P_ADAPTER_T prAdapter, IN UINT_32 u4StaRecIdx); + +/*----------------------------------------------------------------------------*/ +/* TX-Related Queue Management */ +/*----------------------------------------------------------------------------*/ + +P_MSDU_INFO_T qmFlushTxQueues(IN P_ADAPTER_T prAdapter); + +P_MSDU_INFO_T qmFlushStaTxQueues(IN P_ADAPTER_T prAdapter, IN UINT_32 u4StaRecIdx); + +P_MSDU_INFO_T qmEnqueueTxPackets(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead); + +P_MSDU_INFO_T qmDequeueTxPackets(IN P_ADAPTER_T prAdapter, IN P_TX_TCQ_STATUS_T prTcqStatus); + +VOID qmAdjustTcQuotas(IN P_ADAPTER_T prAdapter, OUT P_TX_TCQ_ADJUST_T prTcqAdjust, IN P_TX_TCQ_STATUS_T prTcqStatus); + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL +VOID qmReassignTcResource(IN P_ADAPTER_T prAdapter); + +VOID qmUpdateAverageTxQueLen(IN P_ADAPTER_T prAdapter); +#endif + +/*----------------------------------------------------------------------------*/ +/* RX-Related Queue Management */ +/*----------------------------------------------------------------------------*/ + +VOID qmInitRxQueues(IN P_ADAPTER_T prAdapter); + +P_SW_RFB_T qmFlushRxQueues(IN P_ADAPTER_T prAdapter); + +P_SW_RFB_T qmHandleRxPackets(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfbListHead); + +VOID qmProcessPktWithReordering(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT P_QUE_T prReturnedQue); + +VOID qmProcessBarFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT P_QUE_T prReturnedQue); + +VOID +qmInsertFallWithinReorderPkt(IN P_SW_RFB_T prSwRfb, IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue); + +VOID qmInsertFallAheadReorderPkt(IN P_SW_RFB_T prSwRfb, IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue); + +BOOLEAN +qmPopOutDueToFallWithin(P_ADAPTER_T prAdapter, IN P_RX_BA_ENTRY_T prReorderQueParm, + OUT P_QUE_T prReturnedQue, OUT BOOLEAN *fgIsTimeout); + +VOID qmPopOutDueToFallAhead(P_ADAPTER_T prAdapter, IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue); + +VOID qmHandleMailboxRxMessage(IN MAILBOX_MSG_T prMailboxRxMsg); + +BOOLEAN qmCompareSnIsLessThan(IN UINT_32 u4SnLess, IN UINT_32 u4SnGreater); + +VOID qmHandleEventRxAddBa(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); + +VOID qmHandleEventRxDelBa(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); + +P_RX_BA_ENTRY_T qmLookupRxBaEntry(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIdx, IN UINT_8 ucTid); + +BOOLEAN +qmAddRxBaEntry(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucStaRecIdx, IN UINT_8 ucTid, IN UINT_16 u2WinStart, IN UINT_16 u2WinSize); + +VOID qmDelRxBaEntry(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIdx, IN UINT_8 ucTid, IN BOOLEAN fgFlushToHost); + +#if CFG_RX_BA_REORDERING_ENHANCEMENT +VOID qmInsertNoNeedWaitPkt(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, IN ENUM_NO_NEED_WATIT_DROP_REASON_T eDropReason); + +VOID qmHandleEventDropByFW(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); + +VOID qmHandleNoNeedWaitPktList(IN P_RX_BA_ENTRY_T prReorderQueParm); + +P_NO_NEED_WAIT_PKT_T qmSearchNoNeedWaitPktBySSN(IN P_RX_BA_ENTRY_T prReorderQueParm, IN UINT_32 u2SSN); + +BOOLEAN qmIsIndependentPkt(IN P_SW_RFB_T prSwRfb); + +VOID qmRemoveAllNoNeedWaitPkt(IN P_RX_BA_ENTRY_T prReorderQueParm); + +VOID qmDumpNoNeedWaitPkt(IN P_RX_BA_ENTRY_T prReorderQueParm); + +VOID qmProcessIndepentReorderQueue(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +#endif + +VOID mqmProcessAssocRsp(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength); + +VOID +mqmParseEdcaParameters(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength, IN BOOLEAN fgForceOverride); + +VOID mqmFillAcQueParam(IN P_IE_WMM_PARAM_T prIeWmmParam, IN UINT_32 u4AcOffset, OUT P_AC_QUE_PARMS_T prAcQueParams); + +VOID mqmProcessScanResult(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prScanResult, OUT P_STA_RECORD_T prStaRec); + +/* Utility function: for deciding STA-REC index */ +UINT_8 qmGetStaRecIdx(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEthDestAddr, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType); + +UINT_32 +mqmGenerateWmmInfoIEByParam(BOOLEAN fgSupportUAPSD, + UINT_8 ucBmpDeliveryAC, UINT_8 ucBmpTriggerAC, UINT_8 ucUapsdSp, UINT_8 *pOutBuf); + +VOID mqmGenerateWmmInfoIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +UINT_32 mqmGenerateWmmParamIEByParam(P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, UINT_8 *pOutBuf, ENUM_OP_MODE_T ucOpMode); + +VOID mqmGenerateWmmParamIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +ENUM_FRAME_ACTION_T +qmGetFrameAction(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType, + IN UINT_8 ucStaRecIdx, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_FRAME_TYPE_IN_CMD_Q_T eFrameType); + +VOID qmHandleEventBssAbsencePresence(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); + +VOID qmHandleEventStaChangePsMode(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); + +VOID mqmProcessAssocReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength); + +VOID qmHandleEventStaUpdateFreeQuota(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); + +VOID +qmUpdateFreeQuota(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, IN UINT_8 ucUpdateMode, IN UINT_8 ucFreeQuota, IN UINT_8 ucNumOfTxDone); + +VOID qmFreeAllByNetType(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); + +UINT_32 qmGetRxReorderQueuedBufferCount(IN P_ADAPTER_T prAdapter); + +VOID qmHandleReorderBubbleTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); +VOID qmHandleEventCheckReorderBubble(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +VOID qmHandleMissTimeout(IN P_RX_BA_ENTRY_T prReorderQueParm); + +#if ARP_MONITER_ENABLE +VOID qmDetectArpNoResponse(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); +VOID qmResetArpDetect(VOID); +VOID qmHandleRxArpPackets(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); +VOID qmHandleRxDhcpPackets(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); +#endif +VOID qmHandleRxIpPackets(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, UINT_16 *flag); + +VOID qmMoveStaTxQueue(P_STA_RECORD_T prSrcStaRec, P_STA_RECORD_T prDstStaRec); +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +VOID qmHandleDelTspec(P_ADAPTER_T prAdapter, ENUM_NETWORK_TYPE_INDEX_T eNetType, + P_STA_RECORD_T prStaRec, ENUM_ACI_T eAci); + +#endif /* _QUE_MGT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/wlan_def.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/wlan_def.h new file mode 100644 index 0000000000000..3be7a95170da2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic/wlan_def.h @@ -0,0 +1,873 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _WLAN_DEF_H +#define _WLAN_DEF_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* disconnect reason */ +#define DISCONNECT_REASON_CODE_RESERVED 0 +#define DISCONNECT_REASON_CODE_RADIO_LOST 1 +#define DISCONNECT_REASON_CODE_DEAUTHENTICATED 2 +#define DISCONNECT_REASON_CODE_DISASSOCIATED 3 +#define DISCONNECT_REASON_CODE_NEW_CONNECTION 4 +#define DISCONNECT_REASON_CODE_REASSOCIATION 5 +#define DISCONNECT_REASON_CODE_ROAMING 6 + +/* The rate definitions */ +#define TX_MODE_CCK 0x00 +#define TX_MODE_OFDM 0x40 +#define TX_MODE_HT_MM 0x80 +#define TX_MODE_HT_GF 0xC0 + +#define RATE_CCK_SHORT_PREAMBLE 0x10 +#define RATE_OFDM 0x20 + +#define PHY_RATE_1M 0x0 +#define PHY_RATE_2M 0x1 +#define PHY_RATE_5_5M 0x2 +#define PHY_RATE_11M 0x3 +#define PHY_RATE_6M 0xB +#define PHY_RATE_9M 0xF +#define PHY_RATE_12M 0xA +#define PHY_RATE_18M 0xE +#define PHY_RATE_24M 0x9 +#define PHY_RATE_36M 0xD +#define PHY_RATE_48M 0x8 +#define PHY_RATE_54M 0xC +#define PHY_RATE_MCS0 0x0 +#define PHY_RATE_MCS1 0x1 +#define PHY_RATE_MCS2 0x2 +#define PHY_RATE_MCS3 0x3 +#define PHY_RATE_MCS4 0x4 +#define PHY_RATE_MCS5 0x5 +#define PHY_RATE_MCS6 0x6 +#define PHY_RATE_MCS7 0x7 +#define PHY_RATE_MCS32 0x20 + +#define RATE_CCK_1M_LONG (TX_MODE_CCK | PHY_RATE_1M) +#define RATE_CCK_2M_LONG (TX_MODE_CCK | PHY_RATE_2M) +#define RATE_CCK_5_5M_LONG (TX_MODE_CCK | PHY_RATE_5_5M) +#define RATE_CCK_11M_LONG (TX_MODE_CCK | PHY_RATE_11M) +#define RATE_CCK_2M_SHORT (TX_MODE_CCK | PHY_RATE_2M | RATE_CCK_SHORT_PREAMBLE) +#define RATE_CCK_5_5M_SHORT (TX_MODE_CCK | PHY_RATE_5_5M | RATE_CCK_SHORT_PREAMBLE) +#define RATE_CCK_11M_SHORT (TX_MODE_CCK | PHY_RATE_11M | RATE_CCK_SHORT_PREAMBLE) +#define RATE_OFDM_6M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_6M) +#define RATE_OFDM_9M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_9M) +#define RATE_OFDM_12M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_12M) +#define RATE_OFDM_18M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_18M) +#define RATE_OFDM_24M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_24M) +#define RATE_OFDM_36M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_36M) +#define RATE_OFDM_48M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_48M) +#define RATE_OFDM_54M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_54M) + +#define RATE_MM_MCS_0 (TX_MODE_HT_MM | PHY_RATE_MCS0) +#define RATE_MM_MCS_1 (TX_MODE_HT_MM | PHY_RATE_MCS1) +#define RATE_MM_MCS_2 (TX_MODE_HT_MM | PHY_RATE_MCS2) +#define RATE_MM_MCS_3 (TX_MODE_HT_MM | PHY_RATE_MCS3) +#define RATE_MM_MCS_4 (TX_MODE_HT_MM | PHY_RATE_MCS4) +#define RATE_MM_MCS_5 (TX_MODE_HT_MM | PHY_RATE_MCS5) +#define RATE_MM_MCS_6 (TX_MODE_HT_MM | PHY_RATE_MCS6) +#define RATE_MM_MCS_7 (TX_MODE_HT_MM | PHY_RATE_MCS7) +#define RATE_MM_MCS_32 (TX_MODE_HT_MM | PHY_RATE_MCS32) + +#define RATE_GF_MCS_0 (TX_MODE_HT_GF | PHY_RATE_MCS0) +#define RATE_GF_MCS_1 (TX_MODE_HT_GF | PHY_RATE_MCS1) +#define RATE_GF_MCS_2 (TX_MODE_HT_GF | PHY_RATE_MCS2) +#define RATE_GF_MCS_3 (TX_MODE_HT_GF | PHY_RATE_MCS3) +#define RATE_GF_MCS_4 (TX_MODE_HT_GF | PHY_RATE_MCS4) +#define RATE_GF_MCS_5 (TX_MODE_HT_GF | PHY_RATE_MCS5) +#define RATE_GF_MCS_6 (TX_MODE_HT_GF | PHY_RATE_MCS6) +#define RATE_GF_MCS_7 (TX_MODE_HT_GF | PHY_RATE_MCS7) +#define RATE_GF_MCS_32 (TX_MODE_HT_GF | PHY_RATE_MCS32) + +#define RATE_TX_MODE_MASK BITS(6, 7) +#define RATE_TX_MODE_OFFSET 6 +#define RATE_CODE_GET_TX_MODE(_ucRateCode) ((_ucRateCode & RATE_TX_MODE_MASK) >> RATE_TX_MODE_OFFSET) +#define RATE_PHY_RATE_MASK BITS(0, 5) +#define RATE_PHY_RATE_OFFSET 0 +#define RATE_CODE_GET_PHY_RATE(_ucRateCode) ((_ucRateCode & RATE_PHY_RATE_MASK) >> RATE_PHY_RATE_OFFSET) +#define RATE_PHY_RATE_SHORT_PREAMBLE BIT(4) +#define RATE_CODE_IS_SHORT_PREAMBLE(_ucRateCode) ((_ucRateCode & RATE_PHY_RATE_SHORT_PREAMBLE)?TRUE:FALSE) + +#define CHNL_LIST_SZ_2G 14 +#define CHNL_LIST_SZ_5G 14 + +/*! CNM(STA_RECORD_T) related definition */ +#define CFG_STA_REC_NUM 20 + +/* PHY TYPE bit definitions */ +#define PHY_TYPE_BIT_HR_DSSS BIT(PHY_TYPE_HR_DSSS_INDEX) /* HR/DSSS PHY (clause 18) */ +#define PHY_TYPE_BIT_ERP BIT(PHY_TYPE_ERP_INDEX) /* ERP PHY (clause 19) */ +#define PHY_TYPE_BIT_OFDM BIT(PHY_TYPE_OFDM_INDEX) /* OFDM 5 GHz PHY (clause 17) */ +#define PHY_TYPE_BIT_HT BIT(PHY_TYPE_HT_INDEX) /* HT PHY (clause 20) */ + +/* PHY TYPE set definitions */ +#define PHY_TYPE_SET_802_11ABGN (PHY_TYPE_BIT_OFDM | \ + PHY_TYPE_BIT_HR_DSSS | \ + PHY_TYPE_BIT_ERP | \ + PHY_TYPE_BIT_HT) + +#define PHY_TYPE_SET_802_11BGN (PHY_TYPE_BIT_HR_DSSS | \ + PHY_TYPE_BIT_ERP | \ + PHY_TYPE_BIT_HT) + +#define PHY_TYPE_SET_802_11GN (PHY_TYPE_BIT_ERP | \ + PHY_TYPE_BIT_HT) + +#define PHY_TYPE_SET_802_11AN (PHY_TYPE_BIT_OFDM | \ + PHY_TYPE_BIT_HT) + +#define PHY_TYPE_SET_802_11ABG (PHY_TYPE_BIT_OFDM | \ + PHY_TYPE_BIT_HR_DSSS | \ + PHY_TYPE_BIT_ERP) + +#define PHY_TYPE_SET_802_11BG (PHY_TYPE_BIT_HR_DSSS | \ + PHY_TYPE_BIT_ERP) + +#define PHY_TYPE_SET_802_11A (PHY_TYPE_BIT_OFDM) + +#define PHY_TYPE_SET_802_11G (PHY_TYPE_BIT_ERP) + +#define PHY_TYPE_SET_802_11B (PHY_TYPE_BIT_HR_DSSS) + +#define PHY_TYPE_SET_802_11N (PHY_TYPE_BIT_HT) + +/* Rate set bit definitions */ +#define RATE_SET_BIT_1M BIT(RATE_1M_INDEX) /* Bit 0: 1M */ +#define RATE_SET_BIT_2M BIT(RATE_2M_INDEX) /* Bit 1: 2M */ +#define RATE_SET_BIT_5_5M BIT(RATE_5_5M_INDEX) /* Bit 2: 5.5M */ +#define RATE_SET_BIT_11M BIT(RATE_11M_INDEX) /* Bit 3: 11M */ +#define RATE_SET_BIT_22M BIT(RATE_22M_INDEX) /* Bit 4: 22M */ +#define RATE_SET_BIT_33M BIT(RATE_33M_INDEX) /* Bit 5: 33M */ +#define RATE_SET_BIT_6M BIT(RATE_6M_INDEX) /* Bit 6: 6M */ +#define RATE_SET_BIT_9M BIT(RATE_9M_INDEX) /* Bit 7: 9M */ +#define RATE_SET_BIT_12M BIT(RATE_12M_INDEX) /* Bit 8: 12M */ +#define RATE_SET_BIT_18M BIT(RATE_18M_INDEX) /* Bit 9: 18M */ +#define RATE_SET_BIT_24M BIT(RATE_24M_INDEX) /* Bit 10: 24M */ +#define RATE_SET_BIT_36M BIT(RATE_36M_INDEX) /* Bit 11: 36M */ +#define RATE_SET_BIT_48M BIT(RATE_48M_INDEX) /* Bit 12: 48M */ +#define RATE_SET_BIT_54M BIT(RATE_54M_INDEX) /* Bit 13: 54M */ +#define RATE_SET_BIT_HT_PHY BIT(RATE_HT_PHY_INDEX) /* Bit 14: BSS Selector */ + +/* Rate set definitions */ +#define RATE_SET_HR_DSSS (RATE_SET_BIT_1M | \ + RATE_SET_BIT_2M | \ + RATE_SET_BIT_5_5M | \ + RATE_SET_BIT_11M) + +#define RATE_SET_ERP (RATE_SET_BIT_1M | \ + RATE_SET_BIT_2M | \ + RATE_SET_BIT_5_5M | \ + RATE_SET_BIT_11M | \ + RATE_SET_BIT_6M | \ + RATE_SET_BIT_9M | \ + RATE_SET_BIT_12M | \ + RATE_SET_BIT_18M | \ + RATE_SET_BIT_24M | \ + RATE_SET_BIT_36M | \ + RATE_SET_BIT_48M | \ + RATE_SET_BIT_54M) + +#define RATE_SET_ERP_P2P (RATE_SET_BIT_6M | \ + RATE_SET_BIT_9M | \ + RATE_SET_BIT_12M | \ + RATE_SET_BIT_18M | \ + RATE_SET_BIT_24M | \ + RATE_SET_BIT_36M | \ + RATE_SET_BIT_48M | \ + RATE_SET_BIT_54M) + +#define RATE_SET_OFDM (RATE_SET_BIT_6M | \ + RATE_SET_BIT_9M | \ + RATE_SET_BIT_12M | \ + RATE_SET_BIT_18M | \ + RATE_SET_BIT_24M | \ + RATE_SET_BIT_36M | \ + RATE_SET_BIT_48M | \ + RATE_SET_BIT_54M) + +#define RATE_SET_HT (RATE_SET_ERP) +/* #define RATE_SET_HT (RATE_SET_ERP | RATE_SET_BIT_HT_PHY) *//* NOTE(Kevin): TBD */ + +#define RATE_SET_ALL_ABG RATE_SET_ERP + +#define BASIC_RATE_SET_HR_DSSS (RATE_SET_BIT_1M | \ + RATE_SET_BIT_2M) + +#define BASIC_RATE_SET_HR_DSSS_ERP (RATE_SET_BIT_1M | \ + RATE_SET_BIT_2M | \ + RATE_SET_BIT_5_5M | \ + RATE_SET_BIT_11M) + +#define BASIC_RATE_SET_ERP (RATE_SET_BIT_1M | \ + RATE_SET_BIT_2M | \ + RATE_SET_BIT_5_5M | \ + RATE_SET_BIT_11M | \ + RATE_SET_BIT_6M | \ + RATE_SET_BIT_12M | \ + RATE_SET_BIT_24M) + +#define BASIC_RATE_SET_OFDM (RATE_SET_BIT_6M | \ + RATE_SET_BIT_12M | \ + RATE_SET_BIT_24M) + +#define BASIC_RATE_SET_ERP_P2P (RATE_SET_BIT_6M | \ + RATE_SET_BIT_12M | \ + RATE_SET_BIT_24M) + +#define INITIAL_RATE_SET_RCPI_100 RATE_SET_ALL_ABG + +#define INITIAL_RATE_SET_RCPI_80 (RATE_SET_BIT_1M | \ + RATE_SET_BIT_2M | \ + RATE_SET_BIT_5_5M | \ + RATE_SET_BIT_11M | \ + RATE_SET_BIT_6M | \ + RATE_SET_BIT_9M | \ + RATE_SET_BIT_12M | \ + RATE_SET_BIT_24M) + +#define INITIAL_RATE_SET_RCPI_60 (RATE_SET_BIT_1M | \ + RATE_SET_BIT_2M | \ + RATE_SET_BIT_5_5M | \ + RATE_SET_BIT_11M | \ + RATE_SET_BIT_6M) + +#define INITIAL_RATE_SET(_rcpi) (INITIAL_RATE_SET_ ## _rcpi) + +#define RCPI_100 100 /* -60 dBm */ +#define RCPI_80 80 /* -70 dBm */ +#define RCPI_60 60 /* -80 dBm */ + +/* The number of RCPI records used to calculate their average value */ +#define MAX_NUM_RCPI_RECORDS 10 + +/* The number of RCPI records used to calculate their average value */ +#define NO_RCPI_RECORDS -128 +#define MAX_RCPI_DBM 0 +#define MIN_RCPI_DBM -100 + +#define MAC_TX_RESERVED_FIELD 0 /* NOTE(Kevin): Should defined in tx.h */ + +#define MAX_ASSOC_ID (CFG_STA_REC_NUM) /* Available AID: 1 ~ 20(STA_REC_NUM) */ + +#define MAX_DEAUTH_INFO_COUNT 4 /* NOTE(Kevin): Used in auth.c */ +#define MIN_DEAUTH_INTERVAL_MSEC 500 /* The minimum interval if continuously send Deauth Frame */ + +/* Authentication Type */ +#define AUTH_TYPE_OPEN_SYSTEM BIT(AUTH_ALGORITHM_NUM_OPEN_SYSTEM) +#define AUTH_TYPE_SHARED_KEY BIT(AUTH_ALGORITHM_NUM_SHARED_KEY) +#define AUTH_TYPE_FAST_BSS_TRANSITION BIT(AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION) +#define AUTH_TYPE_SAE BIT(AUTH_ALGORITHM_NUM_SAE) + +/* Authentication Retry Limit */ +#define TX_AUTH_ASSOCI_RETRY_LIMIT 2 +#define TX_AUTH_ASSOCI_RETRY_LIMIT_FOR_ROAMING 1 + +/* WMM-2.2.1 WMM Information Element */ +#define ELEM_MAX_LEN_WMM_INFO 7 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef UINT_16 PHY_TYPE, *P_PHY_TYPE; +typedef UINT_8 RCPI, *P_RCPI; +typedef UINT_8 ALC_VAL, *P_ALC_VAL; + +typedef enum _ENUM_HW_BSSID_T { + BSSID_0 = 0, + BSSID_1, + BSSID_NUM +} ENUM_HW_BSSID_T; + +typedef enum _ENUM_HW_MAC_ADDR_T { + MAC_ADDR_0 = 0, + MAC_ADDR_1, + MAC_ADDR_NUM +} ENUM_HW_MAC_ADDR_T; + +typedef enum _ENUM_HW_OP_MODE_T { + HW_OP_MODE_STA = 0, + HW_OP_MODE_AP, + HW_OP_MODE_ADHOC, + HW_OP_MODE_NUM +} ENUM_HW_OP_MODE_T; + +typedef enum _ENUM_TSF_T { + ENUM_LOCAL_TSF_0, + ENUM_LOCAL_TSF_1, + ENUM_LOCAL_TSF_NUM +} ENUM_LOCAL_TSF_T, *P_ENUM_LOCAL_TSF_T; + +typedef enum _HAL_TS_HW_UPDATE_MODE { + HAL_TSF_HW_UPDATE_BY_TICK_AND_RECEIVED_FRAME, + HAL_TSF_HW_UPDATE_BY_TICK_ONLY, + HAL_TSF_HW_UPDATE_BY_RECEIVED_FRAME_ONLY, + HAL_TSF_HW_UPDATE_BY_TICK_AND_RECEIVED_FRAME_AD_HOC +} HAL_TSF_HW_UPDATE_MODE; + +typedef enum _ENUM_AC_T { + AC0 = 0, + AC1, + AC2, + AC3, + AC_NUM +} ENUM_AC_T, *P_ENUM_AC_T; + +/* The Type of Network been activated */ +typedef enum _ENUM_NETWORK_TYPE_INDEX_T { + NETWORK_TYPE_AIS_INDEX = 0, + NETWORK_TYPE_P2P_INDEX, + NETWORK_TYPE_BOW_INDEX, + NETWORK_TYPE_INDEX_NUM +} ENUM_NETWORK_TYPE_INDEX_T; + +/* The Type of STA Type. */ +typedef enum _ENUM_STA_TYPE_INDEX_T { + STA_TYPE_LEGACY_INDEX = 0, + STA_TYPE_P2P_INDEX, + STA_TYPE_BOW_INDEX, + STA_TYPE_INDEX_NUM +} ENUM_STA_TYPE_INDEX_T; + +#define STA_ROLE_BASE_INDEX 4 + +typedef enum _ENUM_STA_ROLE_INDEX_T { + STA_ROLE_ADHOC_INDEX = STA_ROLE_BASE_INDEX, /* 4 */ + STA_ROLE_CLIENT_INDEX, + STA_ROLE_AP_INDEX, + STA_ROLE_TDLS_INDEX, + STA_ROLE_DLS_INDEX /* Note: need to extend P_CMD_UPDATE_STA_RECORD_T */ +} ENUM_STA_ROLE_INDEX_T; + +/* The Power State of a specific Network */ +typedef enum _ENUM_PWR_STATE_T { + PWR_STATE_IDLE = 0, + PWR_STATE_ACTIVE, + PWR_STATE_PS, + PWR_STATE_NUM +} ENUM_PWR_STATE_T; + +typedef enum _ENUM_PHY_TYPE_INDEX_T { + /* PHY_TYPE_DSSS_INDEX, *//* DSSS PHY (clause 15) -- Not used anymore */ + PHY_TYPE_HR_DSSS_INDEX = 0, /* HR/DSSS PHY (clause 18) */ + PHY_TYPE_ERP_INDEX, /* ERP PHY (clause 19) */ + PHY_TYPE_ERP_P2P_INDEX, /* ERP PHY (clause 19) w/o HR/DSSS */ + PHY_TYPE_OFDM_INDEX, /* OFDM 5 GHz PHY (clause 17) */ + PHY_TYPE_HT_INDEX, /* HT PHY (clause 20) */ + PHY_TYPE_INDEX_NUM /* 5 */ +} ENUM_PHY_TYPE_INDEX_T, *P_ENUM_PHY_TYPE_INDEX_T; + +typedef enum _ENUM_ACPI_STATE_T { + ACPI_STATE_D0 = 0, + ACPI_STATE_D1, + ACPI_STATE_D2, + ACPI_STATE_D3 +} ENUM_ACPI_STATE_T; + +/* The operation mode of a specific Network */ +typedef enum _ENUM_OP_MODE_T { + OP_MODE_INFRASTRUCTURE = 0, /* Infrastructure/GC */ + OP_MODE_IBSS, /* AdHoc */ + OP_MODE_ACCESS_POINT, /* For GO */ + OP_MODE_P2P_DEVICE, /* P2P Device */ + OP_MODE_BOW, + OP_MODE_NUM +} ENUM_OP_MODE_T, *P_ENUM_OP_MODE_T; + +/* + * NL80211 interface type. + * Refer to the definition of nl80211_iftype in kernel/nl80211.h + */ +enum ENUM_IFTYPE { + IFTYPE_UNSPECIFIED = 0, + IFTYPE_ADHOC, + IFTYPE_STATION, + IFTYPE_AP, + IFTYPE_AP_VLAN, + IFTYPE_WDS, + IFTYPE_MONITOR, + IFTYPE_MESH_POINT, + IFTYPE_P2P_CLIENT, + IFTYPE_P2P_GO, + IFTYPE_P2P_DEVICE, + IFTYPE_OCB, + IFTYPE_NAN, + IFTYPE_NUM +}; + +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; + enum nl80211_dfs_state eDFS; +} RF_CHANNEL_INFO_T, *P_RF_CHANNEL_INFO_T; + +typedef enum _ENUM_RATE_INDEX_T { + RATE_1M_INDEX = 0, /* 1M */ + RATE_2M_INDEX, /* 2M */ + RATE_5_5M_INDEX, /* 5.5M */ + RATE_11M_INDEX, /* 11M */ + RATE_22M_INDEX, /* 22M */ + RATE_33M_INDEX, /* 33M */ + RATE_6M_INDEX, /* 6M */ + RATE_9M_INDEX, /* 9M */ + RATE_12M_INDEX, /* 12M */ + RATE_18M_INDEX, /* 18M */ + RATE_24M_INDEX, /* 24M */ + RATE_36M_INDEX, /* 36M */ + RATE_48M_INDEX, /* 48M */ + RATE_54M_INDEX, /* 54M */ + RATE_HT_PHY_INDEX, /* BSS Selector - HT PHY */ + RATE_NUM /* 15 */ +} ENUM_RATE_INDEX_T, *P_ENUM_RATE_INDEX_T; + +typedef enum _ENUM_HT_RATE_INDEX_T { + HT_RATE_MCS0_INDEX = 0, + HT_RATE_MCS1_INDEX, + HT_RATE_MCS2_INDEX, + HT_RATE_MCS3_INDEX, + HT_RATE_MCS4_INDEX, + HT_RATE_MCS5_INDEX, + HT_RATE_MCS6_INDEX, + HT_RATE_MCS7_INDEX, + HT_RATE_MCS32_INDEX, + HT_RATE_NUM /* 9 */ +} ENUM_HT_RATE_INDEX_T, *P_ENUM_HT_RATE_INDEX_T; + +typedef enum _ENUM_PREMABLE_OPTION_T { + PREAMBLE_DEFAULT_LONG_NONE = 0, /* LONG for PHY_TYPE_HR_DSSS, NONE for PHY_TYPE_OFDM */ + PREAMBLE_OPTION_SHORT, /* SHORT mandatory for PHY_TYPE_ERP, SHORT option for PHY_TYPE_HR_DSSS */ + PREAMBLE_HT_MIXED_MODE, + PREAMBLE_HT_GREEN_FIELD, + PREAMBLE_OPTION_NUM +} ENUM_PREMABLE_OPTION_T, *P_ENUM_PREMABLE_OPTION_T; + +typedef enum _ENUM_CHANNEL_WIDTH_T { + CW_20_40MHZ = 0, + CW_80MHZ = 1, + CW_160MHZ = 2, + CW_80P80MHZ = 3 +} ENUM_CHANNEL_WIDTH_T, *P_ENUM_CHANNEL_WIDTH_P; + +typedef enum _ENUM_MODULATION_SYSTEM_T { + MODULATION_SYSTEM_CCK = 0, + MODULATION_SYSTEM_OFDM, + MODULATION_SYSTEM_HT20, + MODULATION_SYSTEM_HT40, + MODULATION_SYSTEM_NUM +} ENUM_MODULATION_SYSTEM_T, *P_ENUM_MODULATION_SYSTEM_T; + +typedef enum _ENUM_MODULATION_TYPE_T { + MODULATION_TYPE_CCK_BPSK = 0, + MODULATION_TYPE_QPSK, + MODULATION_TYPE_16QAM, + MODULATION_TYPE_64QAM, + MODULATION_TYPE_NUM +} ENUM_MODULATION_TYPE_T, *P_ENUM_MODULATION_TYPE_T; + +typedef enum _ENUM_PS_FORWARDING_TYPE_T { + PS_FORWARDING_TYPE_NON_PS = 0, + PS_FORWARDING_TYPE_DELIVERY_ENABLED, + PS_FORWARDING_TYPE_NON_DELIVERY_ENABLED, + PS_FORWARDING_MORE_DATA_ENABLED, + PS_FORWARDING_TYPE_NUM +} ENUM_PS_FORWARDING_TYPE_T, *P_ENUM_PS_FORWARDING_TYPE_T; + +typedef struct _DEAUTH_INFO_T { + UINT_8 aucRxAddr[MAC_ADDR_LEN]; + OS_SYSTIME rLastSendTime; +} DEAUTH_INFO_T, *P_DEAUTH_INFO_T; + +/*----------------------------------------------------------------------------*/ +/* Information Element (IE) handlers */ +/*----------------------------------------------------------------------------*/ +typedef VOID(*PFN_APPEND_IE_FUNC) (P_ADAPTER_T, P_MSDU_INFO_T); +typedef VOID(*PFN_HANDLE_IE_FUNC) (P_ADAPTER_T, P_SW_RFB_T, P_IE_HDR_T); +typedef VOID(*PFN_VERIFY_IE_FUNC) (P_ADAPTER_T, P_SW_RFB_T, P_IE_HDR_T, PUINT_16); +typedef UINT_32(*PFN_CALCULATE_VAR_IE_LEN_FUNC) (P_ADAPTER_T, ENUM_NETWORK_TYPE_INDEX_T, P_STA_RECORD_T); + +typedef struct _APPEND_IE_ENTRY_T { + UINT_16 u2EstimatedIELen; + PFN_APPEND_IE_FUNC pfnAppendIE; +} APPEND_IE_ENTRY_T, *P_APPEND_IE_ENTRY_T; + +typedef struct _APPEND_VAR_IE_ENTRY_T { + UINT_16 u2EstimatedFixedIELen; /* For Fixed Length */ + PFN_CALCULATE_VAR_IE_LEN_FUNC pfnCalculateVariableIELen; + PFN_APPEND_IE_FUNC pfnAppendIE; +} APPEND_VAR_IE_ENTRY_T, *P_APPEND_VAR_IE_ENTRY_T; + +typedef struct _HANDLE_IE_ENTRY_T { + UINT_8 ucElemID; + PFN_HANDLE_IE_FUNC pfnHandleIE; +} HANDLE_IE_ENTRY_T, *P_HANDLE_IE_ENTRY_T; + +typedef struct _VERIFY_IE_ENTRY_T { + UINT_8 ucElemID; + PFN_VERIFY_IE_FUNC pfnVarifyIE; +} VERIFY_IE_ENTRY_T, *P_VERIFY_IE_ENTRY_T; + +/*----------------------------------------------------------------------------*/ +/* Parameters of User Configuration */ +/*----------------------------------------------------------------------------*/ +typedef enum _ENUM_PARAM_CONNECTION_POLICY_T { + CONNECT_BY_SSID_BEST_RSSI = 0, + CONNECT_BY_SSID_GOOD_RSSI_MIN_CH_LOAD, + CONNECT_BY_SSID_ANY, /* NOTE(Kevin): Needed by WHQL */ + CONNECT_BY_BSSID, + CONNECT_BY_CUSTOMIZED_RULE /* NOTE(Kevin): TBD */ +} ENUM_PARAM_CONNECTION_POLICY_T, *P_ENUM_PARAM_CONNECTION_POLICY_T; + +typedef enum _ENUM_PARAM_PREAMBLE_TYPE_T { + PREAMBLE_TYPE_LONG = 0, + PREAMBLE_TYPE_SHORT, + PREAMBLE_TYPE_AUTO /*!< Try preamble short first, if fail tray preamble long. */ +} ENUM_PARAM_PREAMBLE_TYPE_T, *P_ENUM_PARAM_PREAMBLE_TYPE_T; + +/* This is enum defined for user to select a phy config listed in combo box */ +typedef enum _ENUM_PARAM_PHY_CONFIG_T { + /*!< Can associated with 802.11abg AP but without n capability, Scan dual band. */ + PHY_CONFIG_802_11ABG = 0, + PHY_CONFIG_802_11BG, /*!< Can associated with 802_11bg AP, Scan single band and not report 5G BSSs. */ + PHY_CONFIG_802_11G, /*!< Can associated with 802_11g only AP, Scan single band and not report 5G BSSs. */ + PHY_CONFIG_802_11A, /*!< Can associated with 802_11a only AP, Scan single band and not report 2.4G BSSs. */ + PHY_CONFIG_802_11B, /*!< Can associated with 802_11b only AP, Scan single band and not report 5G BSSs. */ + PHY_CONFIG_802_11ABGN, /*!< Can associated with 802.11abgn AP, Scan dual band. */ + PHY_CONFIG_802_11BGN, /*!< Can associated with 802_11bgn AP, Scan single band and not report 5G BSSs. */ + PHY_CONFIG_802_11AN, /*!< Can associated with 802_11an AP, Scan single band and not report 2.4G BSSs. */ + PHY_CONFIG_802_11GN, /*!< Can associated with 802_11gn AP, Scan single band and not report 5G BSSs. */ + PHY_CONFIG_NUM /* 9 */ +} ENUM_PARAM_PHY_CONFIG_T, *P_ENUM_PARAM_PHY_CONFIG_T; + +/* This is enum defined for user to select an AP Mode */ +typedef enum _ENUM_PARAM_AP_MODE_T { + AP_MODE_11B = 0, /*!< Create 11b BSS if we support 802.11abg/802.11bg. */ + AP_MODE_MIXED_11BG, /*!< Create 11bg mixed BSS if we support 802.11abg/802.11bg/802.11g. */ + AP_MODE_11G, /*!< Create 11g only BSS if we support 802.11abg/802.11bg/802.11g. */ + AP_MODE_11G_P2P, /*!< Create 11g only BSS for P2P if we support 802.11abg/802.11bg/802.11g. */ + AP_MODE_11A, /*!< Create 11a only BSS if we support 802.11abg. */ + AP_MODE_NUM /* 4 */ +} ENUM_PARAM_AP_MODE_T, *P_ENUM_PARAM_AP_MODE_T; + +/* Masks for determining the Network Type or the Station Role, given the ENUM_STA_TYPE_T */ +#define NETWORK_TYPE_AIS_MASK BIT(NETWORK_TYPE_AIS_INDEX) +#define NETWORK_TYPE_P2P_MASK BIT(NETWORK_TYPE_P2P_INDEX) +#define NETWORK_TYPE_BOW_MASK BIT(NETWORK_TYPE_BOW_INDEX) +#define STA_TYPE_LEGACY_MASK BIT(STA_TYPE_LEGACY_INDEX) +#define STA_TYPE_P2P_MASK BIT(STA_TYPE_P2P_INDEX) +#define STA_TYPE_BOW_MASK BIT(STA_TYPE_BOW_INDEX) +#define STA_TYPE_ADHOC_MASK BIT(STA_ROLE_ADHOC_INDEX) +#define STA_TYPE_CLIENT_MASK BIT(STA_ROLE_CLIENT_INDEX) +#define STA_TYPE_AP_MASK BIT(STA_ROLE_AP_INDEX) +#define STA_TYPE_DLS_MASK BIT(STA_ROLE_DLS_INDEX) +#define STA_TYPE_TDLS_MASK BIT(STA_ROLE_TDLS_INDEX) + +/* Macros for obtaining the Network Type or the Station Role, given the ENUM_STA_TYPE_T */ +#define IS_STA_IN_AIS(_prStaRec) ((_prStaRec)->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) +#define IS_STA_IN_P2P(_prStaRec) ((_prStaRec)->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) +#define IS_STA_IN_BOW(_prStaRec) ((_prStaRec)->ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX) +#define IS_STA_LEGACY_TYPE(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_LEGACY_MASK) +#define IS_STA_P2P_TYPE(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_P2P_MASK) +#define IS_STA_BOW_TYPE(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_BOW_MASK) +#define IS_ADHOC_STA(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_ADHOC_MASK) +#define IS_CLIENT_STA(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_CLIENT_MASK) +#define IS_AP_STA(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_AP_MASK) +#define IS_DLS_STA(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_DLS_MASK) +#define IS_TDLS_STA(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_TDLS_MASK) + +/* + * The ENUM_STA_TYPE_T accounts for ENUM_NETWORK_TYPE_T and ENUM_STA_ROLE_INDEX_T. + * It is a merged version of Network Type and STA Role. + * + */ +typedef enum _ENUM_STA_TYPE_T { + STA_TYPE_LEGACY_AP = (STA_TYPE_LEGACY_MASK | STA_TYPE_AP_MASK), + STA_TYPE_LEGACY_CLIENT = (STA_TYPE_LEGACY_MASK | STA_TYPE_CLIENT_MASK), + STA_TYPE_ADHOC_PEER = (STA_TYPE_LEGACY_MASK | STA_TYPE_ADHOC_MASK), +#if CFG_ENABLE_WIFI_DIRECT + STA_TYPE_P2P_GO = (STA_TYPE_P2P_MASK | STA_TYPE_AP_MASK), + STA_TYPE_P2P_GC = (STA_TYPE_P2P_MASK | STA_TYPE_CLIENT_MASK), +#endif +#if CFG_ENABLE_BT_OVER_WIFI + STA_TYPE_BOW_AP = (STA_TYPE_BOW_MASK | STA_TYPE_AP_MASK), + STA_TYPE_BOW_CLIENT = (STA_TYPE_BOW_MASK | STA_TYPE_CLIENT_MASK), +#endif + STA_TYPE_DLS_PEER = (STA_TYPE_LEGACY_MASK | STA_TYPE_DLS_MASK), + STA_TYPE_TDLS_PEER = (STA_TYPE_LEGACY_MASK | STA_TYPE_TDLS_MASK) +} ENUM_STA_TYPE_T, *P_ENUM_STA_TYPE_T; + +/* The type of BSS we discovered */ +typedef enum _ENUM_BSS_TYPE_T { + BSS_TYPE_INFRASTRUCTURE = 1, + BSS_TYPE_IBSS, + BSS_TYPE_P2P_DEVICE, + BSS_TYPE_BOW_DEVICE, + BSS_TYPE_NUM +} ENUM_BSS_TYPE_T, *P_ENUM_BSS_TYPE_T; + +/*----------------------------------------------------------------------------*/ +/* RSN structures */ +/*----------------------------------------------------------------------------*/ +/* #if defined(WINDOWS_DDK) || defined(WINDOWS_CE) */ +/* #pragma pack(1) */ +/* #endif */ + +#define MAX_NUM_SUPPORTED_CIPHER_SUITES 9 /* max number of supported cipher suites */ +#if CFG_SUPPORT_802_11W +#define MAX_NUM_SUPPORTED_AKM_SUITES 13 /* max number of supported AKM suites */ +#else +#define MAX_NUM_SUPPORTED_AKM_SUITES 9 /* 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_BE32(_memAddr_p, _value_p) \ + { \ + PUINT_8 __cp = (PUINT_8)(_memAddr_p); \ + *(PUINT_32)(_value_p) = ((UINT_32)__cp[0] << 24) | \ + ((UINT_32)__cp[1] << 16) | ((UINT_32)__cp[2] << 8) | \ + ((UINT_32)__cp[3]); \ + } + +#define WLAN_GET_FIELD_64(_memAddr_p, _value_p) \ + { \ + PUINT_8 __cp = (PUINT_8) (_memAddr_p); \ + *(PUINT_64)(_value_p) = \ + ((UINT_64) __cp[0]) | ((UINT_64) __cp[1] << 8) | \ + ((UINT_64) __cp[2] << 16) | ((UINT_64) __cp[3] << 24) | \ + ((UINT_64) __cp[4] << 32) | ((UINT_64) __cp[5] << 40) | \ + ((UINT_64) __cp[6] << 48) | ((UINT_64) __cp[7] << 56); \ + } + +#define WLAN_SET_FIELD_16(_memAddr_p, _value) \ + { \ + PUINT_8 __cp = (PUINT_8) (_memAddr_p); \ + __cp[0] = (UINT_8) (_value); \ + __cp[1] = (UINT_8) ((_value) >> 8); \ + } + +#define WLAN_SET_FIELD_BE16(_memAddr_p, _value) \ + { \ + PUINT_8 __cp = (PUINT_8) (_memAddr_p); \ + __cp[0] = (UINT_8) ((_value) >> 8); \ + __cp[1] = (UINT_8) (_value); \ + } + +#define WLAN_SET_FIELD_32(_memAddr_p, _value) \ + { \ + PUINT_8 __cp = (PUINT_8) (_memAddr_p); \ + __cp[0] = (UINT_8) (_value); \ + __cp[1] = (UINT_8) ((_value) >> 8); \ + __cp[2] = (UINT_8) ((_value) >> 16); \ + __cp[3] = (UINT_8) ((_value) >> 24); \ + } + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _WLAN_DEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic_cmd_event.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic_cmd_event.h new file mode 100644 index 0000000000000..6883dff97bfc9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic_cmd_event.h @@ -0,0 +1,1958 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _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) +#define MAX_FW_LOG_LENGTH (896) + +/* Action field in structure CMD_CH_PRIVILEGE_T */ +#define CMD_CH_ACTION_REQ 0 +#define CMD_CH_ACTION_ABORT 1 + +/* Status field in structure EVENT_CH_PRIVILEGE_T */ +#define EVENT_CH_STATUS_GRANT 0 + +#define SCN_PSCAN_SWC_RSSI_WIN_MAX 75 +#define SCN_PSCAN_SWC_MAX_NUM 8 +#define SCN_PSCAN_HOTLIST_REPORT_MAX_NUM 8 + +typedef enum _ENUM_CMD_ID_T { + CMD_ID_TEST_MODE = 1, /* 0x01 (Set) */ + CMD_ID_RESET_REQUEST, /* 0x02 (Set) */ + CMD_ID_BUILD_CONNECTION, /* 0x03 (Set) */ + CMD_ID_SCAN_REQ_V2, /* 0x04 (Set) */ + CMD_ID_NIC_POWER_CTRL, /* 0x05 (Set) */ + CMD_ID_POWER_SAVE_MODE, /* 0x06 (Set) */ + CMD_ID_LINK_ATTRIB, /* 0x07 (Set) */ + CMD_ID_ADD_REMOVE_KEY, /* 0x08 (Set) */ + CMD_ID_DEFAULT_KEY_ID, /* 0x09 (Set) */ + CMD_ID_INFRASTRUCTURE, /* 0x0a (Set) */ + CMD_ID_SET_RX_FILTER, /* 0x0b (Set) */ + CMD_ID_DOWNLOAD_BUF, /* 0x0c (Set) */ + CMD_ID_WIFI_START, /* 0x0d (Set) */ + CMD_ID_CMD_BT_OVER_WIFI, /* 0x0e (Set) */ + CMD_ID_SET_MEDIA_CHANGE_DELAY_TIME, /* 0x0f (Set) */ + CMD_ID_SEND_ADDBA_RSP, /* 0x10 (Set) */ + CMD_ID_WAPI_MODE, /* 0x11 (Set) (obsolete) */ + CMD_ID_WAPI_ASSOC_INFO, /* 0x12 (Set) (obsolete) */ + CMD_ID_SET_DOMAIN_INFO, /* 0x13 (Set) */ + CMD_ID_SET_IP_ADDRESS, /* 0x14 (Set) */ + CMD_ID_BSS_ACTIVATE_CTRL, /* 0x15 (Set) */ + CMD_ID_SET_BSS_INFO, /* 0x16 (Set) */ + CMD_ID_UPDATE_STA_RECORD, /* 0x17 (Set) */ + CMD_ID_REMOVE_STA_RECORD, /* 0x18 (Set) */ + CMD_ID_INDICATE_PM_BSS_CREATED, /* 0x19 (Set) */ + CMD_ID_INDICATE_PM_BSS_CONNECTED, /* 0x1a (Set) */ + CMD_ID_INDICATE_PM_BSS_ABORT, /* 0x1b (Set) */ + CMD_ID_UPDATE_BEACON_CONTENT, /* 0x1c (Set) */ + CMD_ID_SET_BSS_RLM_PARAM, /* 0x1d (Set) */ + CMD_ID_SCAN_REQ, /* 0x1e (Set) */ + CMD_ID_SCAN_CANCEL, /* 0x1f (Set) */ + CMD_ID_CH_PRIVILEGE, /* 0x20 (Set) */ + CMD_ID_UPDATE_WMM_PARMS, /* 0x21 (Set) */ + CMD_ID_SET_WMM_PS_TEST_PARMS, /* 0x22 (Set) */ + CMD_ID_TX_AMPDU, /* 0x23 (Set) */ + CMD_ID_ADDBA_REJECT, /* 0x24 (Set) */ + CMD_ID_SET_PS_PROFILE_ADV, /* 0x25 (Set) */ + CMD_ID_SET_RAW_PATTERN, /* 0x26 (Set) */ + CMD_ID_CONFIG_PATTERN_FUNC, /* 0x27 (Set) */ + CMD_ID_SET_TX_PWR, /* 0x28 (Set) */ + CMD_ID_SET_5G_PWR_OFFSET, /* 0x29 (Set) */ + CMD_ID_SET_PWR_PARAM, /* 0x2A (Set) */ + CMD_ID_P2P_ABORT, /* 0x2B (Set) */ +#if CFG_STRESS_TEST_SUPPORT + CMD_ID_RANDOM_RX_RESET_EN = 0x2C, /* 0x2C (Set ) */ + CMD_ID_RANDOM_RX_RESET_DE = 0x2D, /* 0x2D (Set ) */ + CMD_ID_SAPP_EN = 0x2E, /* 0x2E (Set ) */ + CMD_ID_SAPP_DE = 0x2F, /* 0x2F (Set ) */ +#endif + CMD_ID_ROAMING_TRANSIT = 0x30, /* 0x30 (Set) */ + CMD_ID_SET_PHY_PARAM, /* 0x31 (Set) */ + CMD_ID_SET_NOA_PARAM, /* 0x32 (Set) */ + CMD_ID_SET_OPPPS_PARAM, /* 0x33 (Set) */ + CMD_ID_SET_UAPSD_PARAM, /* 0x34 (Set) */ + CMD_ID_SET_SIGMA_STA_SLEEP, /* 0x35 (Set) */ + CMD_ID_SET_EDGE_TXPWR_LIMIT, /* 0x36 (Set) */ + CMD_ID_SET_DEVICE_MODE, /* 0x37 (Set) */ + CMD_ID_SET_TXPWR_CTRL, /* 0x38 (Set) */ + CMD_ID_SET_AUTOPWR_CTRL, /* 0x39 (Set) */ + CMD_ID_SET_WFD_CTRL, /* 0x3A (Set) */ + CMD_ID_SET_5G_EDGE_TXPWR_LIMIT, /* 0x3B (Set) */ + CMD_ID_SET_RSSI_COMPENSATE, /* 0x3C (Set) */ + CMD_ID_SET_BAND_SUPPORT = 0x3D, /* 0x3D (Set) */ + CMD_ID_SET_NLO_REQ, /* 0x3E (Set) */ + CMD_ID_SET_NLO_CANCEL, /* 0x3F (Set) */ + CMD_ID_SET_BATCH_REQ, /* 0x40 (Set) */ + CMD_ID_SET_WOWLAN, /* 0x41 (Set) */ /*CFG_SUPPORT_WOWLAN */ + CMD_ID_GET_PSCAN_CAPABILITY = 0x42, /* 0x42 (Set) */ + CMD_ID_SET_PSCN_ENABLE = 0x43, /* 0x43 (Set) */ + CMD_ID_SET_PSCAN_PARAM = 0x44, /* 0x44 (Set) */ + CMD_ID_SET_PSCN_ADD_HOTLIST_BSSID = 0x45, /* 0x45 (Set) */ + CMD_ID_SET_PSCN_ADD_SW_BSSID = 0x46, /* 0x46 (Set) */ + CMD_ID_SET_PSCN_MAC_ADDR = 0x47, /* 0x47 (Set) */ + CMD_ID_GET_GSCN_SCN_RESULT = 0x48, /* 0x48 (Get) */ + CMD_ID_SET_COUNTRY_POWER_LIMIT = 0x4A, /* 0x4A (Set) */ + CMD_ID_SET_RRM_CAPABILITY = 0x59, /* 0x59 (Set) */ + CMD_ID_SET_MAX_TXPWR_LIMIT = 0x5A, /* 0x5A (Set) */ + CMD_ID_REQ_CHNL_UTILIZATION = 0x5C, /* 0x5C (Get) */ +#if CFG_SUPPORT_P2P_ECSA + CMD_ID_SET_ECSA_PARAM = 0x5D, /* 0x5D (Set) */ +#endif + CMD_ID_SET_TSM_STATISTICS_REQUEST = 0x5E, + CMD_ID_GET_TSM_STATISTICS = 0x5F, + CMD_ID_SET_SYSTEM_SUSPEND = 0x60, /* 0x60 (Set) */ + CMD_ID_UPDATE_AC_PARMS = 0x6A, /* 0x6A (Set) */ + CMD_ID_SET_CTIA_MODE_STATUS = 0x6B, /* 0x6B (Set) */ + CMD_ID_SET_ROAMING_SKIP = 0x6D, /* 0x6D (Set) */ + CMD_ID_SET_DROP_PACKET_CFG = 0x6E, /* 0x6E (Set) */ +#if (CFG_SUPPORT_FCC_DYNAMIC_TX_PWR_ADJUST || CFG_SUPPORT_FCC_POWER_BACK_OFF) + CMD_ID_SET_FCC_TX_PWR_CERT = 0x6F, /* 0x6F (Set) */ +#endif +#ifdef FW_CFG_SUPPORT + CMD_ID_GET_SET_CUSTOMER_CFG = 0x70, +#endif + CMD_ID_SET_ALWAYS_SCAN_PARAM = 0x73,/*0x73(set)*/ + CMD_ID_SET_RX_BA_WIN_SIZE = 0x74, /* 0x74 (Set) */ + CMD_ID_TDLS_PS = 0x75, /* 0x75 (Set) */ +#if CFG_SUPPORT_EMI_DEBUG + CMD_ID_DRIVER_DUMP_EMI_LOG = 0x76, /* 0x76 (Set) */ +#endif + CMD_ID_GET_NIC_CAPABILITY = 0x80, /* 0x80 (Query) */ + CMD_ID_GET_LINK_QUALITY, /* 0x81 (Query) */ + CMD_ID_GET_STATISTICS, /* 0x82 (Query) */ + CMD_ID_GET_CONNECTION_STATUS, /* 0x83 (Query) */ + CMD_ID_GET_ASSOC_INFO, /* 0x84 (Query) (obsolete) */ + CMD_ID_GET_STA_STATISTICS = 0x85, /* 0x85 (Query) */ + CMD_ID_GET_DEBUG_CODE = 0x86, /* 0x86 (Query) */ + CMD_ID_GET_LTE_CHN = 0x87, /* 0x87 (Query) */ + CMD_ID_GET_CHN_LOADING = 0x88, /* 0x88 (Query) */ + CMD_ID_GET_STATISTICS_PL = 0x89, /* 0x87 (Query) */ +#if CFG_SUPPORT_GAMING_MODE + CMD_ID_SET_GAMING_MODE = 0x8B, /* 0x8B (Set) */ +#endif /* CFG_SUPPORT_GAMING_MODE */ +#if CFG_SUPPORT_OSHARE + CMD_ID_SET_OSHARE_MODE = 0x8C, +#endif + CMD_ID_WIFI_LOG_LEVEL = 0x8D, /* 0x8D (Set / Query) */ + CMD_ID_WFC_KEEP_ALIVE = 0xa0, /* 0xa0(Set) */ + CMD_ID_RSSI_MONITOR = 0xa1, /* 0xa1(Set) */ + 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_TX_POWER_BACK_OFF + CMD_ID_SET_TX_PWR_OFFSET = 0xC9, /* 0xc9 (Set) */ +#endif + CMD_ID_CHIP_CONFIG = 0xCA, /* 0xca (Set / Query) */ +#if CFG_SUPPORT_TX_POWER_BACK_OFF + CMD_ID_SET_TX_PWR_BACKOFF = 0xCC, /* 0xcc (Set) */ +#endif +#if CFG_SUPPORT_RDD_TEST_MODE + CMD_ID_SET_RDD_CH = 0xE1, +#endif + + CMD_ID_SET_NVRAM_SETTINGS = 0xEF, + CMD_ID_SET_BWCS = 0xF1, + CMD_ID_SET_ROAMING_INFO = 0xF3, + +#if CFG_SUPPORT_BUILD_DATE_CODE + CMD_ID_GET_BUILD_DATE_CODE = 0xF8, +#endif + CMD_ID_GET_BSS_INFO = 0xF9, +#if 1 /* CFG_SUPPORT_HOTSPOT_OPTIMIZATION */ + CMD_ID_SET_HOTSPOT_OPTIMIZATION = 0xFA, /* 0xFA (Set) */ +#endif + + CMD_ID_TDLS_CORE = 0xFC, + CMD_ID_STATS = 0xFD, + CMD_ID_TX_AR_ERR_CONFIG = 0xFF +} ENUM_CMD_ID_T, *P_ENUM_CMD_ID_T; + +typedef enum _ENUM_EVENT_ID_T { + EVENT_ID_CMD_RESULT = 1, /* 0x01 (Query) */ + EVENT_ID_NIC_CAPABILITY, /* 0x02 (Query) */ + EVENT_ID_CONNECTION_STATUS, /* 0x03 (Query / Unsolicited) (obsolete) */ + EVENT_ID_SCAN_RESULT, /* 0x04 (Query / Unsolicited) (obselete) */ + EVENT_ID_LINK_QUALITY, /* 0x05 (Query / Unsolicited) */ + EVENT_ID_STATISTICS, /* 0x06 (Query) */ + EVENT_ID_MIC_ERR_INFO, /* 0x07 (Unsolicited) */ + EVENT_ID_ASSOC_INFO, /* 0x08 (Query - CMD_ID_GET_ASSOC_INFO) */ + EVENT_ID_BASIC_CONFIG, /* 0x09 (Query - CMD_ID_BASIC_CONFIG) */ + EVENT_ID_ACCESS_REG, /* 0x0a (Query - CMD_ID_ACCESS_REG) */ + EVENT_ID_MAC_MCAST_ADDR, /* 0x0b (Query - CMD_ID_MAC_MCAST_ADDR) */ + EVENT_ID_802_11_PMKID, /* 0x0c (Query - CMD_ID_802_11_PMKID) */ + EVENT_ID_ACCESS_EEPROM, /* 0x0d (Query - CMD_ID_ACCESS_EEPROM) */ + EVENT_ID_SLEEPY_NOTIFY, /* 0x0e (Query) */ + EVENT_ID_BT_OVER_WIFI, /* 0x0f (Unsolicited) */ + EVENT_ID_TEST_STATUS, /* 0x10 (Query - CMD_ID_TEST_MODE) */ + EVENT_ID_RX_ADDBA, /* 0x11 (Unsolicited) (obsolete) */ + EVENT_ID_RX_DELBA, /* 0x12 (Unsolicited) (obsolete) */ + EVENT_ID_ACTIVATE_STA_REC_T, /* 0x13 (Unsolicited) */ + EVENT_ID_DEACTIVATE_STA_REC_T, /* 0x14 (Unsolicited) */ + EVENT_ID_SCAN_DONE, /* 0x15 (Unsoiicited) */ + EVENT_ID_RX_FLUSH, /* 0x16 (Unsolicited) */ + EVENT_ID_TX_DONE, /* 0x17 (Unsolicited) */ + EVENT_ID_CH_PRIVILEGE, /* 0x18 (Unsolicited) */ + EVENT_ID_BSS_ABSENCE_PRESENCE = 0x19, /* 0x19 (Unsolicited) */ + EVENT_ID_STA_CHANGE_PS_MODE, /* 0x1A (Unsolicited) */ + EVENT_ID_BSS_BEACON_TIMEOUT, /* 0x1B (Unsolicited) */ + EVENT_ID_UPDATE_NOA_PARAMS, /* 0x1C (Unsolicited) */ + EVENT_ID_AP_OBSS_STATUS, /* 0x1D (Unsolicited) */ + EVENT_ID_STA_UPDATE_FREE_QUOTA, /* 0x1E (Unsolicited) */ + EVENT_ID_SW_DBG_CTRL, /* 0x1F (Query - CMD_ID_SW_DBG_CTRL) */ + EVENT_ID_ROAMING_STATUS, /* 0x20 (Unsolicited) */ + EVENT_ID_STA_AGING_TIMEOUT, /* 0x21 (Unsolicited) */ +#if 1 /* CFG_SUPPORT_ANTI_PIRACY */ + EVENT_ID_SEC_CHECK_RSP, /* 0x22 (Unsolicited) */ +#endif + EVENT_ID_SEND_DEAUTH, /* 0x23 (Unsolicited) */ + +#if CFG_SUPPORT_RDD_TEST_MODE + EVENT_ID_UPDATE_RDD_STATUS, /* 0x24 (Unsolicited) */ +#endif + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS + EVENT_ID_UPDATE_BWCS_STATUS = 0x25, /* 0x25 (Unsolicited) */ + EVENT_ID_UPDATE_BCM_DEBUG, /* 0x26 (Unsolicited) */ +#endif + EVENT_ID_RX_ERR, + EVENT_ID_DUMP_MEM, + EVENT_ID_STA_STATISTICS = 0x29, /* 0x29 (Query ) */ + EVENT_ID_STA_STATISTICS_UPDATE, /* 0x2A (Unsolicited) */ + EVENT_ID_NLO_DONE = 0x2b, + + EVENT_ID_GSCAN_CAPABILITY = 0x30, + EVENT_ID_GSCAN_SCAN_COMPLETE = 0x31, + EVENT_ID_GSCAN_FULL_RESULT = 0x32, + EVENT_ID_GSCAN_SIGNIFICANT_CHANGE = 0x33, + EVENT_ID_GSCAN_GEOFENCE_FOUND = 0x34, + EVENT_ID_GSCAN_SCAN_AVAILABLE = 0x35, + EVENT_ID_GSCAN_RESULT = 0x36, + EVENT_ID_BATCH_RESULT = 0x37, + + EVENT_ID_CHECK_REORDER_BUBBLE = 0x39, +#if CFG_SUPPORT_P2P_ECSA + EVENT_ID_ECSA_RESULT = 0x3D, +#endif + EVENT_ID_ADD_PKEY_DONE = 0x44, /* 0x44 (Unsolicited) */ + EVENT_ID_GET_TSM_STATISTICS = 0x47, + + + +#if CFG_RX_BA_REORDERING_ENHANCEMENT + EVENT_ID_BA_FW_DROP_SN = 0x51, +#endif + EVENT_ID_RSP_CHNL_UTILIZATION = 0x59, /* 0x59 (Query - CMD_ID_REQ_CHNL_UTILIZATION) */ +#if CFG_SUPPORT_EMI_DEBUG + EVENT_ID_DRIVER_DUMP_LOG = 0x76, /*request driver to dump EMI message*/ +#endif + EVENT_ID_TDLS = 0x80, + EVENT_ID_STATS_ENV = 0x81, + EVENT_ID_WIFI_LOG_LEVEL = 0x8D, + EVENT_ID_RSSI_MONITOR = 0xa1, + +#if CFG_SUPPORT_BUILD_DATE_CODE + EVENT_ID_BUILD_DATE_CODE = 0xF8, +#endif + EVENT_ID_GET_AIS_BSS_INFO = 0xF9, + EVENT_ID_DEBUG_CODE = 0xFB, + EVENT_ID_RFTEST_READY = 0xFC, /* 0xFC */ + EVENT_ID_TX_DONE_STATUS = 0xFD, + EVENT_ID_FW_LOG_ENV = 0xFE, /* 0xFE, FW real time debug log */ +} ENUM_EVENT_ID_T, *P_ENUM_EVENT_ID_T; + +#if CFG_SUPPORT_P2P_ECSA +typedef enum _ENUM_ECSA_STATE_T { + ECSA_EVENT_STATUS_SUCCESS = 0, + ECSA_EVENT_STATUS_UPDATE_BEACON = 1, /*Notify Driver to update GO’s ECSA/CSA IE*/ + ECSA_EVENT_STATUS_INVALID_PARAM = 2, + ECSA_EVENT_STATUS_CHNL_SWITCH_FAILED = 3, + ECSA_EVENT_STATUS_UNACCEPTABLE = 4, + ECSA_EVENT_STATUS_NUM, +} ENUM_ECSA_STATE_T; +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +#ifndef LINUX +typedef UINT_8 CMD_STATUS; +#endif + +#if (CFG_SUPPORT_FCC_DYNAMIC_TX_PWR_ADJUST || CFG_SUPPORT_FCC_POWER_BACK_OFF) +/* TX Power Adjust For FCC/CE Certification */ +typedef struct _CMD_FCC_TX_PWR_ADJUST_T { + UINT_8 fgFccTxPwrAdjust; + UINT_8 Offset_CCK; /* Offset for CH 11~14 */ + UINT_8 Offset_HT20; /* Offset for CH 11~14 */ + UINT_8 Offset_HT40; /* Offset for CH 11~14 */ + UINT_8 Channel_CCK[2]; /* [0] for start channel, [1] for ending channel */ + UINT_8 Channel_HT20[2]; /* [0] for start channel, [1] for ending channel */ + UINT_8 Channel_HT40[2]; /* [0] for start channel, [1] for ending channel */ + UINT_8 Channel_Bandedge[2]; /* Set specical bandedge for flight mode + *[0] for start channel, [1] for ending channel + */ +} CMD_FCC_TX_PWR_ADJUST, *P_CMD_FCC_TX_PWR_ADJUST; +#endif + +typedef struct _EVENT_TX_DONE_STATUS_T { + UINT_8 ucPacketSeq; + UINT_8 ucStatus; + UINT_16 u2SequenceNumber; + UINT_32 au4Reserved1; + UINT_32 au4Reserved2; + UINT_32 au4Reserved3; + UINT_32 u4PktBufInfo; + UINT_8 aucPktBuf[200]; +} EVENT_TX_DONE_STATUS_T, *P_EVENT_TX_DONE_STATUS_T; + +/* for Event Packet (via HIF-RX) */ + /* following CM's documentation v0.7 */ +typedef struct _WIFI_CMD_T { + UINT_16 u2TxByteCount_UserPriority; + UINT_8 ucEtherTypeOffset; + UINT_8 ucResource_PktType_CSflags; + UINT_8 ucCID; + UINT_8 ucSetQuery; + UINT_8 ucSeqNum; + UINT_8 aucReserved2; + + UINT_8 aucBuffer[0]; +} WIFI_CMD_T, *P_WIFI_CMD_T; + +/* for Command Packet (via HIF-TX) */ + /* following CM's documentation v0.7 */ +typedef struct _WIFI_EVENT_T { + UINT_16 u2PacketLen; + UINT_16 u2PacketType; + UINT_8 ucEID; + UINT_8 ucSeqNum; + UINT_8 aucReserved2[2]; + + UINT_8 aucBuffer[0]; +} WIFI_EVENT_T, *P_WIFI_EVENT_T; + +/* CMD_ID_TEST_MODE */ +typedef struct _CMD_TEST_CTRL_T { + UINT_8 ucAction; + UINT_8 aucReserved[3]; + union { + UINT_32 u4OpMode; + UINT_32 u4ChannelFreq; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + } u; +} CMD_TEST_CTRL_T, *P_CMD_TEST_CTRL_T; + +/* EVENT_TEST_STATUS */ +typedef struct _PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T { + UINT_32 u4PktSentStatus; + UINT_32 u4PktSentCount; + UINT_16 u2AvgAlc; + UINT_8 ucCckGainControl; + UINT_8 ucOfdmGainControl; +} PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T, *P_PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T; + +typedef struct _PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T { + UINT_32 u4IntRxOk; /*!< number of packets that Rx ok from interrupt */ + UINT_32 u4IntCrcErr; /*!< number of packets that CRC error from interrupt */ + UINT_32 u4IntShort; /*!< number of packets that is short preamble from interrupt */ + UINT_32 u4IntLong; /*!< number of packets that is long preamble from interrupt */ + UINT_32 u4PauRxPktCount; /*!< number of packets that Rx ok from PAU */ + UINT_32 u4PauCrcErrCount; /*!< number of packets that CRC error from PAU */ + UINT_32 u4PauRxFifoFullCount; /*!< number of packets that is short preamble from PAU */ + UINT_32 u4PauCCACount; /*!< CCA rising edge count */ +} PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T, *P_PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T; + +typedef union _EVENT_TEST_STATUS { + PARAM_MTK_WIFI_TEST_STRUCT_T rATInfo; +/* PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T rTxStatus; */ +/* PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T rRxStatus; */ +} EVENT_TEST_STATUS, *P_EVENT_TEST_STATUS; + +/* CMD_BUILD_CONNECTION */ +typedef struct _CMD_BUILD_CONNECTION { + UINT_8 ucInfraMode; + UINT_8 ucAuthMode; + UINT_8 ucEncryptStatus; + UINT_8 ucSsidLen; + UINT_8 aucSsid[PARAM_MAX_LEN_SSID]; + UINT_8 aucBssid[PARAM_MAC_ADDR_LEN]; + + /* Ad-hoc mode */ + UINT_16 u2BeaconPeriod; + UINT_16 u2ATIMWindow; + UINT_8 ucJoinOnly; + UINT_8 ucReserved; + UINT_32 u4FreqInKHz; + + /* for faster connection */ + UINT_8 aucScanResult[0]; +} CMD_BUILD_CONNECTION, *P_CMD_BUILD_CONNECTION; + +/* CMD_ADD_REMOVE_KEY */ +typedef struct _CMD_802_11_KEY { + UINT_8 ucAddRemove; + UINT_8 ucTxKey; + UINT_8 ucKeyType; + UINT_8 ucIsAuthenticator; + UINT_8 aucPeerAddr[6]; + UINT_8 ucNetType; + UINT_8 ucAlgorithmId; + UINT_8 ucKeyId; + UINT_8 ucKeyLen; + UINT_8 aucReverved[2]; + UINT_8 aucKeyMaterial[32]; + UINT_8 aucKeyRsc[16]; +} CMD_802_11_KEY, *P_CMD_802_11_KEY; + +/* WPA2 PMKID cache structure */ +typedef struct _PMKID_ENTRY_T { +#if (CFG_REFACTORY_PMKSA == 0) + PARAM_BSSID_INFO_T rBssidInfo; + BOOLEAN fgPmkidExist; +#else + LINK_ENTRY_T rLinkEntry; + PARAM_PMKID_T rBssidInfo; +#endif +} PMKID_ENTRY_T, *P_PMKID_ENTRY_T; + +typedef struct _CMD_802_11_PMKID { + ULONG u4BSSIDInfoCount; + P_PMKID_ENTRY_T arPMKIDInfo[1]; +} CMD_802_11_PMKID, *P_CMD_802_11_PMKID; + +/* CMD_BASIC_CONFIG */ +typedef struct _CMD_CSUM_OFFLOAD { + UINT_16 u2RxChecksum; /* bit0: IP, bit1: UDP, bit2: TCP */ + UINT_16 u2TxChecksum; /* bit0: IP, bit1: UDP, bit2: TCP */ +} CMD_CSUM_OFFLOAD, *P_CMD_CSUM_OFFLOAD; + +typedef struct _CMD_BASIC_CONFIG { + PARAM_MAC_ADDRESS rMyMacAddr; + UINT_8 ucNative80211; + UINT_8 aucReserved[1]; + + CMD_CSUM_OFFLOAD rCsumOffload; +} CMD_BASIC_CONFIG, *P_CMD_BASIC_CONFIG, EVENT_BASIC_CONFIG, *P_EVENT_BASIC_CONFIG; + +/* CMD_MAC_MCAST_ADDR */ +typedef struct _CMD_MAC_MCAST_ADDR { + UINT_32 u4NumOfGroupAddr; + UINT_8 ucNetTypeIndex; + UINT_8 aucReserved[3]; + PARAM_MAC_ADDRESS arAddress[MAX_NUM_GROUP_ADDR]; +} CMD_MAC_MCAST_ADDR, *P_CMD_MAC_MCAST_ADDR, EVENT_MAC_MCAST_ADDR, *P_EVENT_MAC_MCAST_ADDR; + +/* CMD_ACCESS_EEPROM */ +typedef struct _CMD_ACCESS_EEPROM { + UINT_16 u2Offset; + UINT_16 u2Data; +} CMD_ACCESS_EEPROM, *P_CMD_ACCESS_EEPROM, EVENT_ACCESS_EEPROM, *P_EVENT_ACCESS_EEPROM; + +typedef struct _CMD_CUSTOM_NOA_PARAM_STRUCT_T { + UINT_32 u4NoaDurationMs; + UINT_32 u4NoaIntervalMs; + UINT_32 u4NoaCount; +} CMD_CUSTOM_NOA_PARAM_STRUCT_T, *P_CMD_CUSTOM_NOA_PARAM_STRUCT_T; + +typedef struct _CMD_CUSTOM_OPPPS_PARAM_STRUCT_T { + UINT_32 u4CTwindowMs; +} CMD_CUSTOM_OPPPS_PARAM_STRUCT_T, *P_CMD_CUSTOM_OPPPS_PARAM_STRUCT_T; + +typedef struct _CMD_CUSTOM_UAPSD_PARAM_STRUCT_T { + UINT_8 fgEnAPSD; + UINT_8 fgEnAPSD_AcBe; + UINT_8 fgEnAPSD_AcBk; + UINT_8 fgEnAPSD_AcVo; + UINT_8 fgEnAPSD_AcVi; + UINT_8 ucMaxSpLen; + UINT_8 aucResv[2]; +} CMD_CUSTOM_UAPSD_PARAM_STRUCT_T, *P_CMD_CUSTOM_UAPSD_PARAM_STRUCT_T; + +struct CMD_SET_MAX_TXPWR_LIMIT { + UINT_8 ucMaxTxPwrLimitEnable; + INT_8 cMaxTxPwr; /* in unit of 0.5 dBm */ + INT_8 cMinTxPwr; /* in unit of 0.5 dBm */ + UINT_8 ucReserved; +}; + +struct CMD_SET_RRM_CAPABILITY { + UINT_8 ucDot11RadioMeasurementEnabled; + UINT_8 aucCapabilities[5]; + UINT_8 aucReserved[2]; +}; + +/* EVENT_CONNECTION_STATUS */ +typedef struct _EVENT_CONNECTION_STATUS { + UINT_8 ucMediaStatus; + UINT_8 ucReasonOfDisconnect; + + UINT_8 ucInfraMode; + UINT_8 ucSsidLen; + UINT_8 aucSsid[PARAM_MAX_LEN_SSID]; + UINT_8 aucBssid[PARAM_MAC_ADDR_LEN]; + UINT_8 ucAuthenMode; + UINT_8 ucEncryptStatus; + UINT_16 u2BeaconPeriod; + UINT_16 u2AID; + UINT_16 u2ATIMWindow; + UINT_8 ucNetworkType; + UINT_8 aucReserved[1]; + UINT_32 u4FreqInKHz; + +#if CFG_ENABLE_WIFI_DIRECT + UINT_8 aucInterfaceAddr[PARAM_MAC_ADDR_LEN]; +#endif + +} EVENT_CONNECTION_STATUS, *P_EVENT_CONNECTION_STATUS; + +/* EVENT_NIC_CAPABILITY */ +typedef struct _EVENT_NIC_CAPABILITY { + UINT_16 u2ProductID; + UINT_16 u2FwVersion; + UINT_16 u2DriverVersion; + UINT_8 ucHw5GBandDisabled; + UINT_8 ucEepromUsed; + UINT_8 ucEfuseValid; + UINT_8 ucMacAddrValid; +#if CFG_REPORT_RFBB_VERSION + UINT_8 ucRfVersion; + UINT_8 ucPhyVersion; +#endif +#if CFG_ENABLE_CAL_LOG + UINT_8 ucRfCalFail; + UINT_8 ucBbCalFail; +#endif + +#define FEATURE_SET_OFFSET_TDLS 0 +#define FEATURE_SET_OFFSET_5G_SUPPORT 1 + UINT_8 ucFeatureSet; /* bit0: TDLS */ + + UINT_8 aucReserved[1]; +#if CFG_EMBED_FIRMWARE_BUILD_DATE_CODE + UINT_8 aucDateCode[16]; +#endif +} EVENT_NIC_CAPABILITY, *P_EVENT_NIC_CAPABILITY; + +/* modified version of WLAN_BEACON_FRAME_BODY_T for simplier buffering */ +typedef struct _WLAN_BEACON_FRAME_BODY_T_LOCAL { + /* Beacon frame body */ + UINT_32 au4Timestamp[2]; /* Timestamp */ + UINT_16 u2BeaconInterval; /* Beacon Interval */ + UINT_16 u2CapInfo; /* Capability */ + UINT_8 aucInfoElem[MAX_IE_LENGTH]; /* Various IEs, start from SSID */ + UINT_16 u2IELength; /* This field is *NOT* carried by F/W but caculated by nic_rx */ +} WLAN_BEACON_FRAME_BODY_T_LOCAL, *P_WLAN_BEACON_FRAME_BODY_T_LOCAL; + +/* EVENT_SCAN_RESULT */ +typedef struct _EVENT_SCAN_RESULT_T { + INT_32 i4RSSI; + UINT_32 u4LinkQuality; + UINT_32 u4DSConfig; /* Center frequency */ + UINT_32 u4DomainInfo; /* Require CM opinion */ + UINT_32 u4Reserved; + UINT_8 ucNetworkType; + UINT_8 ucOpMode; + UINT_8 aucBssid[MAC_ADDR_LEN]; + UINT_8 aucRatesEx[PARAM_MAX_LEN_RATES_EX]; + WLAN_BEACON_FRAME_BODY_T_LOCAL rBeaconFrameBody; +} EVENT_SCAN_RESULT_T, *P_EVENT_SCAN_RESULT_T; + +/* event of tkip mic error */ +typedef struct _EVENT_MIC_ERR_INFO { + UINT_32 u4Flags; +} EVENT_MIC_ERR_INFO, *P_EVENT_MIC_ERR_INFO; + +typedef struct _EVENT_PMKID_CANDIDATE_LIST_T { + UINT_32 u4Version; /*!< Version */ + UINT_32 u4NumCandidates; /*!< How many candidates follow */ + PARAM_PMKID_CANDIDATE_T arCandidateList[1]; +} EVENT_PMKID_CANDIDATE_LIST_T, *P_EVENT_PMKID_CANDIDATE_LIST_T; + +typedef struct _EVENT_CMD_RESULT { + UINT_8 ucCmdID; + UINT_8 ucStatus; + UINT_8 aucReserved[2]; +} EVENT_CMD_RESULT, *P_EVENT_CMD_RESULT; + +/* CMD_ID_ACCESS_REG & EVENT_ID_ACCESS_REG */ +typedef struct _CMD_ACCESS_REG { + UINT_32 u4Address; + UINT_32 u4Data; +} CMD_ACCESS_REG, *P_CMD_ACCESS_REG; + +/* CMD_DUMP_MEMORY */ +typedef struct _CMD_DUMP_MEM { + UINT_32 u4Address; + UINT_32 u4Length; + UINT_32 u4RemainLength; + UINT_8 ucFragNum; +} CMD_DUMP_MEM, *P_CMD_DUMP_MEM; + +typedef struct _EVENT_DUMP_MEM_T { + UINT_32 u4Address; + UINT_32 u4Length; + UINT_32 u4RemainLength; + UINT_8 ucFragNum; + UINT_8 aucBuffer[1]; +} EVENT_DUMP_MEM_T, *P_EVENT_DUMP_MEM_T; + +typedef struct _CMD_SW_DBG_CTRL_T { + UINT_32 u4Id; + UINT_32 u4Data; + /* Debug Support */ + UINT_32 u4DebugCnt[64]; +} CMD_SW_DBG_CTRL_T, *P_CMD_SW_DBG_CTRL_T; + +/* CMD_ID_LINK_ATTRIB */ +typedef struct _CMD_LINK_ATTRIB { + INT_8 cRssiTrigger; + UINT_8 ucDesiredRateLen; + UINT_16 u2DesiredRate[32]; + UINT_8 ucMediaStreamMode; + UINT_8 aucReserved[1]; +} CMD_LINK_ATTRIB, *P_CMD_LINK_ATTRIB; + +/* CMD_ID_NIC_POWER_CTRL */ +typedef struct _CMD_NIC_POWER_CTRL { + UINT_8 ucPowerMode; + UINT_8 aucReserved[3]; +} CMD_NIC_POWER_CTRL, *P_CMD_NIC_POWER_CTRL; + +/* CMD_ID_POWER_SAVE_MODE */ +typedef struct _CMD_PS_PROFILE_T { + UINT_8 ucNetTypeIndex; + UINT_8 ucPsProfile; + UINT_8 aucReserved[2]; +} CMD_PS_PROFILE_T, *P_CMD_PS_PROFILE_T; + +/* EVENT_LINK_QUALITY */ +typedef struct _EVENT_LINK_QUALITY { + INT_8 cRssi; + INT_8 cLinkQuality; + UINT_16 u2LinkSpeed; + UINT_8 ucMediumBusyPercentage; +} EVENT_LINK_QUALITY, *P_EVENT_LINK_QUALITY; + +#if CFG_SUPPORT_P2P_RSSI_QUERY +/* EVENT_LINK_QUALITY */ +typedef struct _EVENT_LINK_QUALITY_EX { + INT_8 cRssi; + INT_8 cLinkQuality; + UINT_16 u2LinkSpeed; + UINT_8 ucMediumBusyPercentage; + UINT_8 ucIsLQ0Rdy; + INT_8 cRssiP2P; /* For P2P Network. */ + INT_8 cLinkQualityP2P; + UINT_16 u2LinkSpeedP2P; + UINT_8 ucMediumBusyPercentageP2P; + UINT_8 ucIsLQ1Rdy; +} EVENT_LINK_QUALITY_EX, *P_EVENT_LINK_QUALITY_EX; +#endif + +/* EVENT_ID_STATISTICS */ +typedef struct _EVENT_STATISTICS { + LARGE_INTEGER rTransmittedFragmentCount; + LARGE_INTEGER rMulticastTransmittedFrameCount; + LARGE_INTEGER rFailedCount; + LARGE_INTEGER rRetryCount; + LARGE_INTEGER rMultipleRetryCount; + LARGE_INTEGER rRTSSuccessCount; + LARGE_INTEGER rRTSFailureCount; + LARGE_INTEGER rACKFailureCount; + LARGE_INTEGER rFrameDuplicateCount; + LARGE_INTEGER rReceivedFragmentCount; + LARGE_INTEGER rMulticastReceivedFrameCount; + LARGE_INTEGER rFCSErrorCount; +} EVENT_STATISTICS, *P_EVENT_STATISTICS; + +/* EVENT_ID_FW_SLEEPY_NOTIFY */ +typedef struct _EVENT_SLEEPY_NOTIFY { + UINT_8 ucSleepyState; + UINT_8 aucReserved[3]; +} EVENT_SLEEPY_NOTIFY, *P_EVENT_SLEEPY_NOTIFY; + +typedef struct _EVENT_ACTIVATE_STA_REC_T { + UINT_8 aucMacAddr[6]; + UINT_8 ucStaRecIdx; + UINT_8 ucNetworkTypeIndex; + BOOLEAN fgIsQoS; + BOOLEAN fgIsAP; + UINT_8 aucReserved[2]; +} EVENT_ACTIVATE_STA_REC_T, *P_EVENT_ACTIVATE_STA_REC_T; + +typedef struct _EVENT_DEACTIVATE_STA_REC_T { + UINT_8 ucStaRecIdx; + UINT_8 aucReserved[3]; +} EVENT_DEACTIVATE_STA_REC_T, *P_EVENT_DEACTIVATE_STA_REC_T; + +/* CMD_BT_OVER_WIFI */ +typedef struct _CMD_BT_OVER_WIFI { + UINT_8 ucAction; /* 0: query, 1: setup, 2: destroy */ + UINT_8 ucChannelNum; + PARAM_MAC_ADDRESS rPeerAddr; + UINT_16 u2BeaconInterval; + UINT_8 ucTimeoutDiscovery; + UINT_8 ucTimeoutInactivity; + UINT_8 ucRole; + UINT_8 PAL_Capabilities; + UINT_8 cMaxTxPower; + UINT_8 ucChannelBand; + UINT_8 ucReserved[1]; +} CMD_BT_OVER_WIFI, *P_CMD_BT_OVER_WIFI; + +/* EVENT_BT_OVER_WIFI */ +typedef struct _EVENT_BT_OVER_WIFI { + UINT_8 ucLinkStatus; + UINT_8 ucSelectedChannel; + INT_8 cRSSI; + UINT_8 ucReserved[1]; +} EVENT_BT_OVER_WIFI, *P_EVENT_BT_OVER_WIFI; + +/* Same with DOMAIN_SUBBAND_INFO */ +typedef struct _CMD_SUBBAND_INFO { + UINT_8 ucRegClass; + UINT_8 ucBand; + UINT_8 ucChannelSpan; + UINT_8 ucFirstChannelNum; + UINT_8 ucNumChannels; + UINT_8 aucReserved[3]; +} CMD_SUBBAND_INFO, *P_CMD_SUBBAND_INFO; + +/* CMD_SET_DOMAIN_INFO */ +typedef struct _CMD_SET_DOMAIN_INFO_T { + UINT_16 u2CountryCode; + UINT_16 u2IsSetPassiveScan; /* 0: set channel domain; 1: set passive scan channel domain */ + CMD_SUBBAND_INFO rSubBand[6]; + + UINT_8 uc2G4Bandwidth; /* CONFIG_BW_20_40M or CONFIG_BW_20M */ + UINT_8 uc5GBandwidth; /* CONFIG_BW_20_40M or CONFIG_BW_20M */ + UINT_8 aucReserved[2]; +} CMD_SET_DOMAIN_INFO_T, *P_CMD_SET_DOMAIN_INFO_T; + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +/* CMD_SET_PWR_LIMIT_TABLE */ +typedef struct _CMD_CHANNEL_POWER_LIMIT { + UINT_8 ucCentralCh; + INT_8 cPwrLimitCCK; + INT_8 cPwrLimit20; + INT_8 cPwrLimit40; + INT_8 cPwrLimit80; + INT_8 cPwrLimit160; + UINT_8 ucFlag; + UINT_8 aucReserved[1]; +} CMD_CHANNEL_POWER_LIMIT, *P_CMD_CHANNEL_POWER_LIMIT; + +typedef struct _CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T { + UINT_16 u2CountryCode; + UINT_8 ucCountryFlag; + UINT_8 ucNum; + UINT_8 aucReserved[4]; + CMD_CHANNEL_POWER_LIMIT rChannelPowerLimit[1]; +} CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T, *P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T; + +#endif + +/* CMD_SET_IP_ADDRESS */ +typedef struct _IPV4_NETWORK_ADDRESS { + UINT_8 aucIpAddr[4]; +} IPV4_NETWORK_ADDRESS, *P_IPV4_NETWORK_ADDRESS; + +typedef struct _CMD_SET_NETWORK_ADDRESS_LIST { + UINT_8 ucNetTypeIndex; + UINT_8 ucAddressCount; + UINT_8 ucReserved[2]; + IPV4_NETWORK_ADDRESS arNetAddress[1]; +} CMD_SET_NETWORK_ADDRESS_LIST, *P_CMD_SET_NETWORK_ADDRESS_LIST; + +typedef struct _PATTERN_DESCRIPTION { + UINT_8 fgCheckBcA1; + UINT_8 fgCheckMcA1; + UINT_8 ePatternHeader; + UINT_8 fgAndOp; + UINT_8 fgNotOp; + UINT_8 ucPatternMask; + UINT_16 ucPatternOffset; + UINT_8 aucPattern[8]; +} PATTERN_DESCRIPTION, *P_PATTERN_DESCRIPTION; + +typedef struct _CMD_RAW_PATTERN_CONFIGURATION_T { + PATTERN_DESCRIPTION arPatternDesc[4]; +} CMD_RAW_PATTERN_CONFIGURATION_T, *P_CMD_RAW_PATTERN_CONFIGURATION_T; + +typedef struct _CMD_PATTERN_FUNC_CONFIG { + BOOLEAN fgBcA1En; + BOOLEAN fgMcA1En; + BOOLEAN fgBcA1MatchDrop; + BOOLEAN fgMcA1MatchDrop; +} CMD_PATTERN_FUNC_CONFIG, *P_CMD_PATTERN_FUNC_CONFIG; + +typedef struct _EVENT_TX_DONE_T { + UINT_8 ucPacketSeq; + UINT_8 ucStatus; + UINT_16 u2SequenceNumber; + UINT_32 au4Reserved1; + UINT_32 au4Reserved2; + UINT_32 au4Reserved3; +} EVENT_TX_DONE_T, *P_EVENT_TX_DONE_T; + +typedef struct _CMD_BSS_ACTIVATE_CTRL { + UINT_8 ucNetTypeIndex; + UINT_8 ucActive; + /* version=1 means Has new format */ + UINT_8 ucVersion; + UINT_8 ucReserved; + UINT_8 aucBssMacAddr[MAC_ADDR_LEN]; + UINT_32 au4Reserved[8]; +} CMD_BSS_ACTIVATE_CTRL, *P_CMD_BSS_ACTIVATE_CTRL; + +typedef struct _CMD_SET_BSS_RLM_PARAM_T { + UINT_8 ucNetTypeIndex; + UINT_8 ucRfBand; + UINT_8 ucPrimaryChannel; + UINT_8 ucRfSco; + UINT_8 ucErpProtectMode; + UINT_8 ucHtProtectMode; + UINT_8 ucGfOperationMode; + UINT_8 ucTxRifsMode; + UINT_16 u2HtOpInfo3; + UINT_16 u2HtOpInfo2; + UINT_8 ucHtOpInfo1; + UINT_8 ucUseShortPreamble; + UINT_8 ucUseShortSlotTime; + UINT_8 ucCheckId; /* Fixed value: 0x72 */ +} CMD_SET_BSS_RLM_PARAM_T, *P_CMD_SET_BSS_RLM_PARAM_T; + +typedef struct _CMD_SET_BSS_INFO { + UINT_8 ucNetTypeIndex; + UINT_8 ucConnectionState; + UINT_8 ucCurrentOPMode; + UINT_8 ucSSIDLen; + UINT_8 aucSSID[32]; + UINT_8 aucBSSID[6]; + UINT_8 ucIsQBSS; + UINT_8 ucReserved1; + UINT_16 u2OperationalRateSet; + UINT_16 u2BSSBasicRateSet; + UINT_8 ucStaRecIdxOfAP; + UINT_8 ucReserved2; + UINT_8 ucReserved3; + UINT_8 ucNonHTBasicPhyType; /* For Slot Time and CWmin */ + UINT_8 ucAuthMode; + UINT_8 ucEncStatus; + UINT_8 ucPhyTypeSet; + UINT_8 aucOwnMac[6]; + UINT_8 fgWapiMode; + UINT_8 fgIsApMode; + UINT_8 fgHiddenSsidMode; + CMD_SET_BSS_RLM_PARAM_T rBssRlmParam; +} CMD_SET_BSS_INFO, *P_CMD_SET_BSS_INFO; + +typedef struct _CMD_UPDATE_STA_RECORD_T { + UINT_8 ucIndex; + UINT_8 ucStaType; + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + UINT_16 u2AssocId; + UINT_16 u2ListenInterval; + UINT_8 ucNetTypeIndex; + UINT_8 ucDesiredPhyTypeSet; + UINT_16 u2DesiredNonHTRateSet; + UINT_16 u2BSSBasicRateSet; + UINT_8 ucIsQoS; + UINT_8 ucIsUapsdSupported; + UINT_8 ucStaState; + UINT_8 ucMcsSet; + UINT_8 ucSupMcs32; + UINT_8 ucAmpduParam; + UINT_16 u2HtCapInfo; + UINT_16 u2HtExtendedCap; + UINT_32 u4TxBeamformingCap; + UINT_8 ucAselCap; + UINT_8 ucRCPI; + UINT_8 ucNeedResp; + UINT_8 ucUapsdAc; /* b0~3: Trigger enabled, b4~7: Delivery enabled */ + UINT_8 ucUapsdSp; /* 0: all, 1: max 2, 2: max 4, 3: max 6 */ + UINT_8 ucKeepAliveDuration; /* unit is 1s */ + UINT_8 ucKeepAliveOption; /* only bit0 is used now */ + UINT_8 ucApplyPmf; + /* TBD */ +} CMD_UPDATE_STA_RECORD_T, *P_CMD_UPDATE_STA_RECORD_T; + +typedef struct _CMD_REMOVE_STA_RECORD_T { + UINT_8 ucIndex; + UINT_8 ucReserved; + UINT_8 aucMacAddr[MAC_ADDR_LEN]; +} CMD_REMOVE_STA_RECORD_T, *P_CMD_REMOVE_STA_RECORD_T; + +typedef struct _CMD_INDICATE_PM_BSS_CREATED_T { + UINT_8 ucNetTypeIndex; + UINT_8 ucDtimPeriod; + UINT_16 u2BeaconInterval; + UINT_16 u2AtimWindow; + UINT_8 aucReserved[2]; +} CMD_INDICATE_PM_BSS_CREATED, *P_CMD_INDICATE_PM_BSS_CREATED; + +typedef struct _CMD_INDICATE_PM_BSS_CONNECTED_T { + UINT_8 ucNetTypeIndex; + UINT_8 ucDtimPeriod; + UINT_16 u2AssocId; + UINT_16 u2BeaconInterval; + UINT_16 u2AtimWindow; + UINT_8 fgIsUapsdConnection; + UINT_8 ucBmpDeliveryAC; + UINT_8 ucBmpTriggerAC; + UINT_8 aucReserved[1]; +} CMD_INDICATE_PM_BSS_CONNECTED, *P_CMD_INDICATE_PM_BSS_CONNECTED; + +typedef struct _CMD_INDICATE_PM_BSS_ABORT { + UINT_8 ucNetTypeIndex; + UINT_8 aucReserved[3]; +} CMD_INDICATE_PM_BSS_ABORT, *P_CMD_INDICATE_PM_BSS_ABORT; + +typedef struct _CMD_BEACON_TEMPLATE_UPDATE { + UINT_8 ucUpdateMethod; /* 0: update randomly, + * 1: update all, + * 2: delete all (1 and 2 will update directly without search) + */ + UINT_8 ucNetTypeIndex; + UINT_8 aucReserved[2]; + UINT_16 u2Capability; + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; +} CMD_BEACON_TEMPLATE_UPDATE, *P_CMD_BEACON_TEMPLATE_UPDATE; + +typedef struct _CMD_SET_WMM_PS_TEST_STRUCT_T { + UINT_8 ucNetTypeIndex; + UINT_8 bmfgApsdEnAc; /* b0~3: trigger-en AC0~3. b4~7: delivery-en AC0~3 */ + UINT_8 ucIsEnterPsAtOnce; /* enter PS immediately without 5 second guard after connected */ + UINT_8 ucIsDisableUcTrigger; /* not to trigger UC on beacon TIM is matched (under U-APSD) */ +} CMD_SET_WMM_PS_TEST_STRUCT_T, *P_CMD_SET_WMM_PS_TEST_STRUCT_T; + +/* Definition for CHANNEL_INFO.ucBand: + * 0: Reserved + * 1: BAND_2G4 + * 2: BAND_5G + * Others: Reserved + */ +typedef struct _CHANNEL_INFO_T { + UINT_8 ucBand; + UINT_8 ucChannelNum; +} CHANNEL_INFO_T, *P_CHANNEL_INFO_T; + +typedef struct _CMD_SCAN_REQ_EXT_CH_T { + UINT_8 ucSeqNum; + UINT_8 ucNetworkType; + UINT_8 ucScanType; + UINT_8 ucSSIDType; /* BIT(0) wildcard / BIT(1) P2P-wildcard / BIT(2) specific */ + UINT_8 ucSSIDLength; + UINT_8 aucReserved[1]; + UINT_16 u2ChannelMinDwellTime; + UINT_8 aucSSID[32]; + UINT_16 u2ChannelDwellTime; /* For P2P */ + UINT_8 ucChannelType; + UINT_8 ucChannelListNum; + CHANNEL_INFO_T arChannelList[MAXIMUM_OPERATION_CHANNEL_LIST]; + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; +} CMD_SCAN_REQ_EXT_CH, *P_CMD_SCAN_REQ_EXT_CH; + +typedef struct _CMD_SCAN_REQ_T { + UINT_8 ucSeqNum; + UINT_8 ucNetworkType; + UINT_8 ucScanType; + UINT_8 ucSSIDType; /* BIT(0) wildcard / BIT(1) P2P-wildcard / BIT(2) specific */ + UINT_8 ucSSIDLength; + UINT_8 ucStructVersion; + UINT_16 u2ChannelMinDwellTime; + UINT_8 aucSSID[32]; + UINT_16 u2ChannelDwellTime; /* For P2P */ + UINT_8 ucChannelType; + UINT_8 ucChannelListNum; + CHANNEL_INFO_T arChannelList[32]; + UINT_8 aucBSSID[MAC_ADDR_LEN]; + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; +} CMD_SCAN_REQ, *P_CMD_SCAN_REQ; + +typedef struct _CMD_SCAN_REQ_V2_EXT_CH_T { + UINT_8 ucSeqNum; + UINT_8 ucNetworkType; + UINT_8 ucScanType; + UINT_8 ucSSIDType; + PARAM_SSID_T arSSID[4]; + UINT_16 u2ProbeDelayTime; + UINT_16 u2ChannelDwellTime; /* For P2P */ + UINT_8 ucChannelType; + UINT_8 ucChannelListNum; + CHANNEL_INFO_T arChannelList[MAXIMUM_OPERATION_CHANNEL_LIST]; + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; +} CMD_SCAN_REQ_V2_EXT_CH, *P_CMD_SCAN_REQ_V2_EXT_CH; + +typedef struct _CMD_SCAN_REQ_V2_T { + UINT_8 ucSeqNum; + UINT_8 ucNetworkType; + UINT_8 ucScanType; + UINT_8 ucSSIDType; + PARAM_SSID_T arSSID[4]; + UINT_16 u2ProbeDelayTime; + UINT_16 u2ChannelDwellTime; /* For P2P */ + UINT_8 ucChannelType; + UINT_8 ucChannelListNum; + CHANNEL_INFO_T arChannelList[32]; + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; +} CMD_SCAN_REQ_V2, *P_CMD_SCAN_REQ_V2; + +/* MULTI SSID */ +typedef struct _CMD_SCAN_REQ_V3_EXT_CH_T { + UINT_8 ucSeqNum; + UINT_8 ucNetworkType; + UINT_8 ucScanType; + UINT_8 ucSSIDType; + PARAM_SSID_T arSSID[11]; + UINT_16 u2ProbeDelayTime; + UINT_16 u2ChannelDwellTime; /* For P2P */ + UINT_8 ucChannelType; + UINT_8 ucChannelListNum; + CHANNEL_INFO_T arChannelList[MAXIMUM_OPERATION_CHANNEL_LIST]; + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; +} CMD_SCAN_REQ_V3_EXT_CH, *P_CMD_SCAN_REQ_V3_EXT_CH; + +typedef struct _CMD_SCAN_REQ_V3_T { + UINT_8 ucSeqNum; + UINT_8 ucNetworkType; + UINT_8 ucScanType; + UINT_8 ucSSIDType; + PARAM_SSID_T arSSID[11]; + 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_V3, *P_CMD_SCAN_REQ_V3; + +/* MULTI SSID */ +struct CMD_SCAN_REQ_V4_EXT_CH { + UINT_8 ucSeqNum; + UINT_8 ucNetworkType; + UINT_8 ucScanType; + UINT_8 ucSSIDType; + PARAM_SSID_T arSSID[11]; + UINT_16 u2ProbeDelayTime; + UINT_16 u2ChannelDwellTime; /* For P2P */ + UINT_8 ucChannelType; + UINT_8 ucChannelListNum; + CHANNEL_INFO_T arChannelList[MAXIMUM_OPERATION_CHANNEL_LIST]; + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; + UINT_8 ucScnFuncMask; + UINT_8 aucRandomMac[MAC_ADDR_LEN]; +}; + +struct CMD_SCAN_REQ_V4 { + UINT_8 ucSeqNum; + UINT_8 ucNetworkType; + UINT_8 ucScanType; + UINT_8 ucSSIDType; + PARAM_SSID_T arSSID[11]; + 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]; + UINT_8 ucScnFuncMask; + UINT_8 aucRandomMac[MAC_ADDR_LEN]; +}; + +typedef struct _CMD_SCAN_CANCEL_T { + UINT_8 ucSeqNum; + UINT_8 ucIsExtChannel; /* For P2P channel extension. */ + UINT_8 aucReserved[2]; +} CMD_SCAN_CANCEL, *P_CMD_SCAN_CANCEL; + +typedef struct _EVENT_SCAN_DONE_T { + UINT_8 ucSeqNum; + UINT_8 ucSparseChannelValid; + CHANNEL_INFO_T rSparseChannel; +} EVENT_SCAN_DONE, *P_EVENT_SCAN_DONE; + +#if CFG_SUPPORT_GET_CH_ENV +typedef struct _CH_ENV_T { + UINT_8 ucChNum; + UINT_8 ucApNum; +} CH_ENV_T, *P_CH_ENV_T; +#endif + +#if 0 /* CFG_SUPPORT_BATCH_SCAN */ +typedef struct _CMD_BATCH_REQ_T { + UINT_8 ucSeqNum; + UINT_8 ucNetTypeIndex; + UINT_8 ucCmd; /* Start/ Stop */ + UINT_8 ucMScan; /* an integer number of scans per batch */ + UINT_8 ucBestn; /* an integer number of the max AP to remember per scan */ + UINT_8 ucRtt; /* + * an integer number of highest-strength AP for which we'd + * like approximate distance reported + */ + UINT_8 ucChannel; /* channels */ + UINT_8 ucChannelType; + UINT_8 ucChannelListNum; + UINT_8 aucReserved[3]; + UINT_32 u4Scanfreq; /* an integer number of seconds between scans */ + CHANNEL_INFO_T arChannelList[32]; /* channels */ +} CMD_BATCH_REQ_T, *P_CMD_BATCH_REQ_T; + +typedef struct _EVENT_BATCH_RESULT_ENTRY_T { + UINT_8 aucBssid[MAC_ADDR_LEN]; + UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; + UINT_8 ucSSIDLen; + INT_8 cRssi; + UINT_32 ucFreq; + UINT_32 u4Age; + UINT_32 u4Dist; + UINT_32 u4Distsd; +} EVENT_BATCH_RESULT_ENTRY_T, *P_EVENT_BATCH_RESULT_ENTRY_T; + +typedef struct _EVENT_BATCH_RESULT_T { + UINT_8 ucScanCount; + UINT_8 aucReserved[3]; + EVENT_BATCH_RESULT_ENTRY_T arBatchResult[12]; /* Must be the same with SCN_BATCH_STORE_MAX_NUM */ +} EVENT_BATCH_RESULT_T, *P_EVENT_BATCH_RESULT_T; +#endif + +typedef struct _CMD_CH_PRIVILEGE_T { + UINT_8 ucNetTypeIndex; + UINT_8 ucTokenID; + UINT_8 ucAction; + UINT_8 ucPrimaryChannel; + UINT_8 ucRfSco; + UINT_8 ucRfBand; + UINT_8 ucReqType; + UINT_8 ucReserved; + UINT_32 u4MaxInterval; /* In unit of ms */ + UINT_8 aucBSSID[6]; + UINT_8 aucReserved[2]; +} CMD_CH_PRIVILEGE_T, *P_CMD_CH_PRIVILEGE_T; + +typedef struct _CMD_TX_PWR_T { + INT_8 cTxPwr2G4Cck; /* signed, in unit of 0.5dBm */ +#if defined(MT6620) + INT_8 acReserved[3]; +#elif defined(MT6628) + INT_8 cTxPwr2G4Dsss; /* signed, in unit of 0.5dBm */ + INT_8 acReserved[2]; +#else +#error "No valid definition!" +#endif + + INT_8 cTxPwr2G4OFDM_BPSK; + INT_8 cTxPwr2G4OFDM_QPSK; + INT_8 cTxPwr2G4OFDM_16QAM; + INT_8 cTxPwr2G4OFDM_Reserved; + INT_8 cTxPwr2G4OFDM_48Mbps; + INT_8 cTxPwr2G4OFDM_54Mbps; + + INT_8 cTxPwr2G4HT20_BPSK; + INT_8 cTxPwr2G4HT20_QPSK; + INT_8 cTxPwr2G4HT20_16QAM; + INT_8 cTxPwr2G4HT20_MCS5; + INT_8 cTxPwr2G4HT20_MCS6; + INT_8 cTxPwr2G4HT20_MCS7; + + INT_8 cTxPwr2G4HT40_BPSK; + INT_8 cTxPwr2G4HT40_QPSK; + INT_8 cTxPwr2G4HT40_16QAM; + INT_8 cTxPwr2G4HT40_MCS5; + INT_8 cTxPwr2G4HT40_MCS6; + INT_8 cTxPwr2G4HT40_MCS7; + + INT_8 cTxPwr5GOFDM_BPSK; + INT_8 cTxPwr5GOFDM_QPSK; + INT_8 cTxPwr5GOFDM_16QAM; + INT_8 cTxPwr5GOFDM_Reserved; + INT_8 cTxPwr5GOFDM_48Mbps; + INT_8 cTxPwr5GOFDM_54Mbps; + + INT_8 cTxPwr5GHT20_BPSK; + INT_8 cTxPwr5GHT20_QPSK; + INT_8 cTxPwr5GHT20_16QAM; + INT_8 cTxPwr5GHT20_MCS5; + INT_8 cTxPwr5GHT20_MCS6; + INT_8 cTxPwr5GHT20_MCS7; + + INT_8 cTxPwr5GHT40_BPSK; + INT_8 cTxPwr5GHT40_QPSK; + INT_8 cTxPwr5GHT40_16QAM; + INT_8 cTxPwr5GHT40_MCS5; + INT_8 cTxPwr5GHT40_MCS6; + INT_8 cTxPwr5GHT40_MCS7; +} CMD_TX_PWR_T, *P_CMD_TX_PWR_T; + +typedef struct _CMD_5G_PWR_OFFSET_T { + INT_8 cOffsetBand0; /* 4.915-4.980G */ + INT_8 cOffsetBand1; /* 5.000-5.080G */ + INT_8 cOffsetBand2; /* 5.160-5.180G */ + INT_8 cOffsetBand3; /* 5.200-5.280G */ + INT_8 cOffsetBand4; /* 5.300-5.340G */ + INT_8 cOffsetBand5; /* 5.500-5.580G */ + INT_8 cOffsetBand6; /* 5.600-5.680G */ + INT_8 cOffsetBand7; /* 5.700-5.825G */ +} CMD_5G_PWR_OFFSET_T, *P_CMD_5G_PWR_OFFSET_T; + +#if CFG_SUPPORT_TX_POWER_BACK_OFF +typedef struct _CMD_MITIGATED_PWR_OFFSET_T { + MITIGATED_PWR_BY_CH_BY_MODE arRlmMitigatedPwrByChByMode[40]; +} CMD_MITIGATED_PWR_OFFSET_T, *P_CMD_MITIGATED_PWR_OFFSET_T; +#endif + +typedef struct _CMD_PWR_PARAM_T { + UINT_32 au4Data[28]; + UINT_32 u4RefValue1; + UINT_32 u4RefValue2; +} CMD_PWR_PARAM_T, *P_CMD_PWR_PARAM_T; + +typedef struct _CMD_PHY_PARAM_T { + UINT_8 aucData[144]; /* eFuse content */ +} CMD_PHY_PARAM_T, *P_CMD_PHY_PARAM_T; + +typedef struct _CMD_AUTO_POWER_PARAM_T { + UINT_8 ucType; /* 0: Disable 1: Enalbe 0x10: Change parameters */ + UINT_8 ucNetTypeIndex; + UINT_8 aucReserved[2]; + UINT_8 aucLevelRcpiTh[3]; + UINT_8 aucReserved2[1]; + INT_8 aicLevelPowerOffset[3]; /* signed, in unit of 0.5dBm */ + UINT_8 aucReserved3[1]; + UINT_8 aucReserved4[8]; +} CMD_AUTO_POWER_PARAM_T, *P_CMD_AUTO_POWER_PARAM_T; + +/*for WMMAC, CMD_ID_UPDATE_AC_PARAMS*/ +typedef struct _CMD_UPDATE_AC_PARAMS_T { + UINT_8 ucAcIndex; /*0 ~3, from AC0 to AC3*/ + UINT_8 ucNetTypeIndex; /*no use*/ + UINT_16 u2MediumTime; /*if 0, disable ACM for ACx specified by ucAcIndex, + * otherwise in unit of 32us + */ + UINT_32 u4PhyRate; /* rate to be used to tx packet with priority ucAcIndex , unit: bps */ + UINT_16 u2EDCALifeTime; /* msdu life time for this TC, unit: 2TU */ + UINT_8 ucRetryCount; /* if we use fix rate to tx packets, should tell firmware the limited retries */ + UINT_8 aucReserved[5]; +} CMD_UPDATE_AC_PARAMS_T, *P_CMD_UPDATE_AC_PARAMS_T; +/* S56 Traffic Stream Metrics */ +typedef struct _CMD_SET_TSM_STATISTICS_REQUEST_T { + UINT_8 ucEnabled; /* 0, disable; 1, enable; */ + UINT_8 ucNetTypeIndex; /* always NETWORK_TYPE_AIS_INDEX now */ + UINT_8 ucAcIndex; /* wmm ac index, the statistics should be on this TC */ + UINT_8 ucTid; + UINT_8 aucPeerAddr[MAC_ADDR_LEN]; /* packet to the target address to be mesured */ + UINT_8 ucBin0Range; + UINT_8 aucReserved[3]; + + /* if this variable is 0, followed variables are meaningless + * only report once for a same trigger condition in this time frame + */ + UINT_8 ucTriggerCondition; /* for triggered mode: bit(0):average, bit(1):consecutive, bit(2):delay */ + UINT_8 ucAvgErrThreshold; + UINT_8 ucConsecutiveErrThreshold; + UINT_8 ucDelayThreshold; + UINT_8 ucMeasureCount; + UINT_8 ucTriggerTimeout; /* unit: 100 TU*/ +} CMD_SET_TSM_STATISTICS_REQUEST_T, *P_CMD_SET_TSM_STATISTICS_REQUEST_T; + +typedef struct _CMD_GET_TSM_STATISTICS_T { + UINT_8 ucNetTypeIndex; /* always NETWORK_TYPE_AIS_INDEX now */ + UINT_8 ucAcIndex; /* wmm ac index, the statistics should be on this TC or TS */ + UINT_8 ucTid; /* */ + UINT_8 aucPeerAddr[MAC_ADDR_LEN]; /* indicating the RA for the measured frames */ + UINT_8 ucReportReason; /* for triggered mode: bit(0):average, bit(1):consecutive, bit(2):delay */ + UINT_16 u2Reserved; + + UINT_32 u4PktTxDoneOK; + UINT_32 u4PktDiscard; /* u2PktTotal - u2PktTxDoneOK */ + UINT_32 u4PktFail; /* failed count for exceeding retry limit */ + UINT_32 u4PktRetryTxDoneOK; + UINT_32 u4PktQosCfPollLost; + + /* 802.11k - Average Packet Transmission delay for all packets per this TC or TS */ + UINT_32 u4AvgPktTxDelay; + /* 802.11k - Average Packet Queue Delay */ + UINT_32 u4AvgPktQueueDelay; + UINT_64 u8StartTime; /* represented by TSF */ + /* sum of packets whose packet tx delay is less than Bi (i=0~6) range value(unit: TU) */ + UINT_32 au4PktCntBin[6]; +} CMD_GET_TSM_STATISTICS_T, *P_CMD_GET_TSM_STATISTICS_T; + +typedef struct _CMD_MAX_TXPWR_LIMIT_T { + UINT_8 ucMaxTxPwrLimitEnable; + UINT_8 ucMaxTxPwr; + UINT_8 ucReserved[2]; +} CMD_MAX_TXPWR_LIMIT_T, *P_CMD_MAX_TXPWR_LIMIT_T; + +typedef struct _EVENT_CH_PRIVILEGE_T { + UINT_8 ucNetTypeIndex; + UINT_8 ucTokenID; + UINT_8 ucStatus; + UINT_8 ucPrimaryChannel; + UINT_8 ucRfSco; + UINT_8 ucRfBand; + UINT_8 ucReqType; + UINT_8 ucReserved; + UINT_32 u4GrantInterval; /* In unit of ms */ +} EVENT_CH_PRIVILEGE_T, *P_EVENT_CH_PRIVILEGE_T; + +typedef enum _ENUM_BEACON_TIMEOUT_TYPE_T { + BEACON_TIMEOUT_LOST_BEACON = 0, + BEACON_TIMEOUT_AGE, + BEACON_TIMEOUT_CONNECT, + BEACON_TIMEOUT_BEACON_INTERVAL, + BEACON_TIMEOUT_ABORT, + BEACON_TIMEOUT_TX_ERROR, + BEACON_TIMEOUT_TYPE_NUM +} ENUM_BEACON_TIMEOUT_TYPE_T, *P_ENUM_BEACON_TIMEOUT_TYPE_T; + +typedef struct _EVENT_BSS_BEACON_TIMEOUT_T { + UINT_8 ucNetTypeIndex; + UINT_8 ucReason; /* ENUM_BEACON_TIMEOUT_TYPE_T */ + UINT_8 aucReserved[2]; +} EVENT_BSS_BEACON_TIMEOUT_T, *P_EVENT_BSS_BEACON_TIMEOUT_T; + +typedef struct _EVENT_STA_AGING_TIMEOUT_T { + UINT_8 ucStaRecIdx; + UINT_8 aucReserved[3]; +} EVENT_STA_AGING_TIMEOUT_T, *P_EVENT_STA_AGING_TIMEOUT_T; + +typedef struct _EVENT_NOA_TIMING_T { + UINT_8 fgIsInUse; /* Indicate if this entry is in use or not */ + UINT_8 ucCount; /* Count */ + UINT_8 aucReserved[2]; + + UINT_32 u4Duration; /* Duration */ + UINT_32 u4Interval; /* Interval */ + UINT_32 u4StartTime; /* Start Time */ +} EVENT_NOA_TIMING_T, *P_EVENT_NOA_TIMING_T; + +typedef struct _EVENT_UPDATE_NOA_PARAMS_T { + UINT_8 ucNetTypeIndex; + UINT_8 aucReserved[2]; + UINT_8 fgEnableOppPS; + UINT_16 u2CTWindow; + + UINT_8 ucNoAIndex; + UINT_8 ucNoATimingCount; /* Number of NoA Timing */ + EVENT_NOA_TIMING_T arEventNoaTiming[8 /*P2P_MAXIMUM_NOA_COUNT */]; +} EVENT_UPDATE_NOA_PARAMS_T, *P_EVENT_UPDATE_NOA_PARAMS_T; + +typedef struct _EVENT_AP_OBSS_STATUS_T { + UINT_8 ucNetTypeIndex; + UINT_8 ucObssErpProtectMode; + UINT_8 ucObssHtProtectMode; + UINT_8 ucObssGfOperationMode; + UINT_8 ucObssRifsOperationMode; + UINT_8 ucObssBeaconForcedTo20M; + UINT_8 aucReserved[2]; +} EVENT_AP_OBSS_STATUS_T, *P_EVENT_AP_OBSS_STATUS_T; + +struct EVENT_ADD_KEY_DONE_INFO { + UINT_8 ucNetworkType; + UINT_8 ucReserved; + UINT_8 aucStaAddr[MAC_ADDR_LEN]; +}; + +typedef struct _CMD_EDGE_TXPWR_LIMIT_T { + INT_8 cBandEdgeMaxPwrCCK; + INT_8 cBandEdgeMaxPwrOFDM20; + INT_8 cBandEdgeMaxPwrOFDM40; + INT_8 cBandEdgeCert; +} CMD_EDGE_TXPWR_LIMIT_T, *P_CMD_EDGE_TXPWR_LIMIT_T; + +typedef struct _CMD_RSSI_COMPENSATE_T { + UINT_8 uc2GRssiCompensation; + UINT_8 uc5GRssiCompensation; + UINT_8 ucRssiCompensationValidbit; + UINT_8 cReserved; +} CMD_RSSI_COMPENSATE_T, *P_CMD_RSSI_COMPENSATE_T; + +typedef struct _CMD_BAND_SUPPORT_T { + UINT_8 uc5GBandSupport; + UINT_8 cReserved[3]; +} CMD_BAND_SUPPORT_T, *P_CMD_BAND_SUPPORT_T; + +typedef struct _CMD_TX_PWR_CE_T { + INT_8 cTxPwrCckLmt; /* signed, in unit of 0.5dBm */ + INT_8 cTxPwrOfdmLmt; /* signed, in unit of 0.5dBm */ + INT_8 cTxPwrHt20Lmt; + INT_8 cTxPwrHt40Lmt; +} CMD_TX_PWR_CE_T, *P_CMD_TX_PWR_CE_T; + +typedef struct _CMD_SET_DEVICE_MODE_T { + UINT_16 u2ChipID; + UINT_16 u2Mode; +} CMD_SET_DEVICE_MODE_T, *P_CMD_SET_DEVICE_MODE_T; + +#if CFG_SUPPORT_RDD_TEST_MODE +typedef struct _CMD_RDD_CH_T { + UINT_8 ucRddTestMode; + UINT_8 ucRddShutCh; + UINT_8 ucRddStartCh; + UINT_8 ucRddStopCh; + UINT_8 ucRddDfs; + UINT_8 ucReserved; + UINT_8 ucReserved1; + UINT_8 ucReserved2; +} CMD_RDD_CH_T, *P_CMD_RDD_CH_T; + +typedef struct _EVENT_RDD_STATUS_T { + UINT_8 ucRddStatus; + UINT_8 aucReserved[3]; +} EVENT_RDD_STATUS_T, *P_EVENT_RDD_STATUS_T; +#endif + +typedef struct _EVENT_AIS_BSS_INFO_T { + ENUM_PARAM_MEDIA_STATE_T eConnectionState; /* Connected Flag used in AIS_NORMAL_TR */ + ENUM_OP_MODE_T eCurrentOPMode; /* Current Operation Mode - Infra/IBSS */ + BOOLEAN fgIsNetActive; /* TRUE if this network has been actived */ + UINT_8 ucReserved[3]; +} EVENT_AIS_BSS_INFO_T, *P_EVENT_AIS_BSS_INFO_T; + +typedef struct _CMD_SET_TXPWR_CTRL_T { + INT_8 c2GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0 */ + INT_8 c2GHotspotPwrOffset; + INT_8 c2GP2pPwrOffset; + INT_8 c2GBowPwrOffset; + INT_8 c5GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0 */ + INT_8 c5GHotspotPwrOffset; + INT_8 c5GP2pPwrOffset; + INT_8 c5GBowPwrOffset; + UINT_8 ucConcurrencePolicy; /* + * TX power policy when concurrence + * in the same channel + * 0: Highest power has priority + * 1: Lowest power has priority + */ + INT_8 acReserved1[3]; /* Must be zero */ + + /* Power limit by channel for all data rates */ + INT_8 acTxPwrLimit2G[14]; /* Channel 1~14, Unit: 0.5dBm */ + INT_8 acTxPwrLimit5G[4]; /* UNII 1~4 */ + INT_8 acReserved2[2]; /* Must be zero */ +} CMD_SET_TXPWR_CTRL_T, *P_CMD_SET_TXPWR_CTRL_T; + +#if CFG_SUPPORT_BUILD_DATE_CODE +typedef struct _CMD_GET_BUILD_DATE_CODE { + UINT_8 aucReserved[4]; +} CMD_GET_BUILD_DATE_CODE, *P_CMD_GET_BUILD_DATE_CODE; + +typedef struct _EVENT_BUILD_DATE_CODE { + UINT_8 aucDateCode[16]; +} EVENT_BUILD_DATE_CODE, *P_EVENT_BUILD_DATE_CODE; +#endif + +typedef struct _CMD_GET_STA_STATISTICS_T { + UINT_8 ucIndex; + UINT_8 ucFlags; + UINT_8 ucReadClear; + UINT_8 aucReserved0[1]; + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + UINT_8 aucReserved1[2]; + UINT_8 aucReserved2[16]; +} CMD_GET_STA_STATISTICS_T, *P_CMD_GET_STA_STATISTICS_T; + +/* CFG_SUPPORT_WFD */ +typedef struct _EVENT_STA_STATISTICS_T { + UINT_8 ucVersion; + UINT_8 aucReserved1[3]; + UINT_32 u4Flags; /* Bit0: valid */ + + UINT_8 ucStaRecIdx; + UINT_8 ucNetworkTypeIndex; + UINT_8 ucWTEntry; + UINT_8 aucReserved4[1]; + + UINT_8 ucMacAddr[MAC_ADDR_LEN]; + UINT_8 ucPer; /* base: 128 */ + UINT_8 ucRcpi; + + UINT_32 u4PhyMode; /* SGI BW */ + UINT_16 u2LinkSpeed; /* unit is 0.5 Mbits */ + UINT_8 ucLinkQuality; + UINT_8 ucLinkReserved; + + UINT_32 u4TxCount; + UINT_32 u4TxFailCount; + UINT_32 u4TxLifeTimeoutCount; + UINT_32 u4TxDoneAirTime; + + UINT_8 aucReserved[64]; +} EVENT_STA_STATISTICS_T, *P_EVENT_STA_STATISTICS_T; + +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION +typedef struct _CMD_HOTSPOT_OPTIMIZATION_CONFIG { + UINT_32 fgHotspotOptimizationEn; + UINT_32 u4Level; +} CMD_HOTSPOT_OPTIMIZATION_CONFIG, *P_HOTSPOT_OPTIMIZATION_CONFIG; +#endif + +typedef struct _EVENT_LTE_SAFE_CHN_T { + UINT_8 ucVersion; + UINT_8 aucReserved[3]; + UINT_32 u4Flags; /* Bit0: valid */ + LTE_SAFE_CHN_INFO_T rLteSafeChn; +} EVENT_LTE_SAFE_CHN_T, *P_EVENT_LTE_SAFE_CHN_T; + +typedef struct _CMD_ROAMING_INFO_T { + UINT_32 fgIsFastRoamingApplied; + UINT_32 Reserved[9]; +} CMD_ROAMING_INFO_T; + +typedef struct _CMD_WFD_DEBUG_MODE_INFO_T { + UINT_8 ucDebugMode; + UINT_16 u2PeriodInteval; + UINT_8 Reserved; +} CMD_WFD_DEBUG_MODE_INFO_T, *P_CMD_WFD_DEBUG_MODE_INFO_T; + +typedef struct _EVENT_FW_LOG_T { + UINT_8 fileName[64]; + UINT_32 lineNo; + UINT_32 WifiUpTime; + UINT_8 log[MAX_FW_LOG_LENGTH]; /* total size is aucBuffer in WIFI_EVENT_T */ +} EVENT_FW_LOG_T, *P_EVENT_FW_LOG_T; + +typedef enum _ENUM_NLO_CIPHER_ALGORITHM { + NLO_CIPHER_ALGO_NONE = 0x00, + NLO_CIPHER_ALGO_WEP40 = 0x01, + NLO_CIPHER_ALGO_TKIP = 0x02, + NLO_CIPHER_ALGO_CCMP = 0x04, + NLO_CIPHER_ALGO_WEP104 = 0x05, + NLO_CIPHER_ALGO_WPA_USE_GROUP = 0x100, + NLO_CIPHER_ALGO_RSN_USE_GROUP = 0x100, + NLO_CIPHER_ALGO_WEP = 0x101, +} ENUM_NLO_CIPHER_ALGORITHM, *P_ENUM_NLO_CIPHER_ALGORITHM; + +typedef enum _ENUM_NLO_AUTH_ALGORITHM { + NLO_AUTH_ALGO_80211_OPEN = 1, + NLO_AUTH_ALGO_80211_SHARED_KEY = 2, + NLO_AUTH_ALGO_WPA = 3, + NLO_AUTH_ALGO_WPA_PSK = 4, + NLO_AUTH_ALGO_WPA_NONE = 5, + NLO_AUTH_ALGO_RSNA = 6, + NLO_AUTH_ALGO_RSNA_PSK = 7, +} ENUM_NLO_AUTH_ALGORITHM, *P_ENUM_NLO_AUTH_ALGORITHM; + +typedef struct _NLO_NETWORK { + UINT_8 ucNumChannelHint[4]; + UINT_8 ucSSIDLength; + UINT_8 ucCipherAlgo; + UINT_16 u2AuthAlgo; + UINT_8 aucSSID[32]; +} NLO_NETWORK, *P_NLO_NETWORK; + +typedef struct _CMD_NLO_REQ { + UINT_8 ucSeqNum; + UINT_8 ucBssIndex; + UINT_8 ucNetworkType; + UINT_8 fgStopAfterIndication; + UINT_8 ucFastScanIteration; + UINT_16 u2FastScanPeriod; + UINT_16 u2SlowScanPeriod; + UINT_8 ucEntryNum; + UINT_8 ucReserved; + UINT_16 u2IELen; + NLO_NETWORK arNetworkList[16]; + UINT_8 aucIE[0]; + UINT_8 ucScanType; +#if CFG_NLO_MSP + BOOLEAN fgNLOMspEnable; /*Flag for NLO/PNO MSP enable indicator*/ + UINT_8 ucNLOMspEntryNum; /*indicates the entry num of MSP List */ + UINT_16 au2NLOMspList[10]; +#endif + UINT_8 ucScnFuncMask; +} CMD_NLO_REQ, *P_CMD_NLO_REQ; + +typedef struct _CMD_NLO_CANCEL_T { + UINT_8 ucSeqNum; + UINT_8 aucReserved[3]; +} CMD_NLO_CANCEL, *P_CMD_NLO_CANCEL; + + +struct CMD_SET_CTIA_MODE { + UINT_8 ucCmdVersion; + UINT_8 ucCtiaModeEnable; + UINT_8 ucReserved[2]; +}; + +typedef struct _EVENT_NLO_DONE_T { + UINT_8 ucSeqNum; + UINT_8 ucStatus; + UINT_8 aucReserved[2]; +} EVENT_NLO_DONE_T, *P_EVENT_NLO_DONE_T; + +typedef struct _EVENT_GSCAN_CAPABILITY_T { + UINT_8 ucVersion; + UINT_8 aucReserved1[3]; + UINT_32 u4MaxScanCacheSize; + UINT_32 u4MaxScanBuckets; + UINT_32 u4MaxApCachePerScan; + UINT_32 u4MaxRssiSampleSize; + UINT_32 u4MaxScanReportingThreshold; + UINT_32 u4MaxHotlistAps; + UINT_32 u4MaxSignificantWifiChangeAps; + UINT_32 au4Reserved[4]; +} EVENT_GSCAN_CAPABILITY_T, *P_EVENT_GSCAN_CAPABILITY_T; + +typedef struct _EVENT_GSCAN_SCAN_AVAILABLE_T { + UINT_16 u2Num; + UINT_8 aucReserved[2]; +} EVENT_GSCAN_SCAN_AVAILABLE_T, *P_EVENT_GSCAN_SCAN_AVAILABLE_T; + +typedef struct _EVENT_GSCAN_SCAN_COMPLETE_T { + UINT_8 ucScanState; + UINT_8 aucReserved[3]; +} EVENT_GSCAN_SCAN_COMPLETE_T, *P_EVENT_GSCAN_SCAN_COMPLETE_T; + +typedef struct WIFI_GSCAN_RESULT { + UINT_64 u8Ts; /* Time of discovery */ + UINT_8 arSsid[ELEM_MAX_LEN_SSID + 1]; /* null terminated */ + UINT_8 arMacAddr[6]; /* BSSID */ + UINT_32 u4Channel; /* channel frequency in MHz */ + INT_32 i4Rssi; /* in db */ + UINT_64 u8Rtt; /* in nanoseconds */ + UINT_64 u8RttSd; /* standard deviation in rtt */ + UINT_16 u2BeaconPeriod; /* units are Kusec */ + UINT_16 u2Capability; /* Capability information */ + UINT_32 u4IeLength; /* byte length of Information Elements */ + UINT_8 ucIeData[1]; /* IE data to follow */ +} WIFI_GSCAN_RESULT_T, *P_WIFI_GSCAN_RESULT_T; + +typedef struct _EVENT_GSCAN_RESULT_T { + UINT_8 ucVersion; + UINT_8 aucReserved[3]; + UINT_16 u2ScanId; + UINT_16 u2ScanFlags; + UINT_16 u2NumOfResults; + WIFI_GSCAN_RESULT_T rResult[1]; +} EVENT_GSCAN_RESULT_T, *P_EVENT_GSCAN_RESULT_T; + +typedef struct _EVENT_GSCAN_FULL_RESULT_T { + WIFI_GSCAN_RESULT_T rResult; + UINT_32 u4BucketMask; /* scan chbucket bitmask */ + UINT_32 u4IeLength; /* byte length of Information Elements */ + UINT_8 ucIeData[1]; /* IE data to follow */ +} EVENT_GSCAN_FULL_RESULT_T, *P_EVENT_GSCAN_FULL_RESULT_T; + +typedef struct GSCAN_SWC_NET { + UINT_16 u2Flags; + UINT_16 u2Channel; + UINT_8 arBssid[6]; + INT_8 aicRssi[SCN_PSCAN_SWC_RSSI_WIN_MAX]; +} GSCAN_SWC_NET_T, P_GSCAN_SWC_NET_T; + +typedef struct _EVENT_GSCAN_SIGNIFICANT_CHANGE_T { + UINT_8 ucVersion; + UINT_8 aucReserved[3]; + GSCAN_SWC_NET_T arNet[SCN_PSCAN_SWC_MAX_NUM]; +} EVENT_GSCAN_SIGNIFICANT_CHANGE_T, *P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T; + +typedef struct _EVENT_GSCAN_GEOFENCE_FOUND_T { + UINT_8 ucVersion; + UINT_8 aucReserved[3]; + WIFI_GSCAN_RESULT_T rResult[SCN_PSCAN_HOTLIST_REPORT_MAX_NUM]; +} EVENT_GSCAN_GEOFENCE_FOUND_T, *P_EVENT_GSCAN_GEOFENCE_FOUND_T; + +#if CFG_SUPPORT_BATCH_SCAN + +#if 0 /* !CFG_SUPPORT_GSCN */ +typedef struct _CMD_BATCH_REQ_T { + UINT_8 ucSeqNum; + UINT_8 ucNetTypeIndex; + UINT_8 ucCmd; /* Start/ Stop */ + UINT_8 ucMScan; /* an integer number of scans per batch */ + UINT_8 ucBestn; /* an integer number of the max AP to remember per scan */ + UINT_8 ucRtt; /* + * an integer number of highest-strength AP for which + * we'd like approximate distance reported + */ + UINT_8 ucChannel; /* channels */ + UINT_8 ucChannelType; + UINT_8 ucChannelListNum; + UINT_8 aucReserved[3]; + UINT_32 u4Scanfreq; /* an integer number of seconds between scans */ + CHANNEL_INFO_T arChannelList[32]; /* channels */ +} CMD_BATCH_REQ_T, *P_CMD_BATCH_REQ_T; + +#endif + +typedef struct _EVENT_BATCH_RESULT_ENTRY_T { + UINT_8 aucBssid[MAC_ADDR_LEN]; + UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; + UINT_8 ucSSIDLen; + INT_8 cRssi; + UINT_32 ucFreq; + UINT_32 u4Age; + UINT_32 u4Dist; + UINT_32 u4Distsd; +} EVENT_BATCH_RESULT_ENTRY_T, *P_EVENT_BATCH_RESULT_ENTRY_T; + +typedef struct _EVENT_BATCH_RESULT_T { + UINT_8 ucScanCount; + UINT_8 aucReserved[3]; + EVENT_BATCH_RESULT_ENTRY_T arBatchResult[12]; /* Must be the same with SCN_BATCH_STORE_MAX_NUM */ +} EVENT_BATCH_RESULT_T, *P_EVENT_BATCH_RESULT_T; +#endif + +typedef struct _CMD_RLM_INFO_T { + UINT_32 u4Version; + UINT_32 fgIsErrRatioEnhanceApplied; + UINT_8 ucErrRatio2LimitMinRate; + /* + * 0:1M, 1:2M, 2:5.5M, 3:11M, 6:6M, 7:9M, 8:12M, 9:18M, 10:24M, 11:36M, 12:48M, 13:54M + */ + UINT_8 ucMinLegacyRateIdx; + INT_8 cMinRssiThreshold; + BOOLEAN fgIsRtsApplied; + UINT_8 ucRecoverTime; + + UINT_32 u4Reserved[0]; +} CMD_RLM_INFO_T; + +typedef struct _WIFI_SYSTEM_SUSPEND_CMD_T { + BOOLEAN fgIsSystemSuspend; + UINT_8 reserved[3]; +} WIFI_SYSTEM_SUSPEND_CMD_T, *P_WIFI_SYSTEM_SUSPEND_CMD_T; + +typedef struct _CMD_ID_SET_ROAMING_SKIP_T { + BOOLEAN IsRoamingSkipOneAp; +} CMD_ID_SET_ROAMING_SKIP_T, *P_CMD_ID_SET_ROAMING_SKIP_T; + +struct CMD_TDLS_PS_T { + UINT_8 ucIsEnablePs; /* 0: disable tdls power save; 1: enable tdls power save */ + UINT_8 aucReserved[3]; +}; + + +struct CMD_REQ_CHNL_UTILIZATION { + UINT_16 u2MeasureDuration; + UINT_8 ucChannelNum; + UINT_8 aucChannelList[48]; + UINT_8 aucReserved[13]; +}; + +#if CFG_SUPPORT_EMI_DEBUG +typedef struct _CMD_DRIVER_DUMP_EMI_LOG_T { + BOOLEAN fgIsDriverDumpEmiLogEnable; /* TRUE: notify to FW Driver supoort*/ +} CMD_DRIVER_DUMP_EMI_LOG_T, *P_CMD_DRIVER_DUMP_EMI_LOG_T; + +typedef struct _EVENT_DRIVER_DUMP_EMI_LOG_T { + UINT_32 u4RequestDriverDumpAddr; /*EMI dump end page num */ +} EVENT_DRIVER_DUMP_EMI_LOG_T, *P_EVENT_DRIVER_DUMP_EMI_LOG_T; +#endif + +struct EVENT_RSP_CHNL_UTILIZATION { + UINT_8 ucChannelNum; + UINT_8 aucChannelMeasureList[48]; + UINT_8 aucReserved0[15]; + UINT_8 aucChannelUtilization[48]; + UINT_8 aucReserved1[16]; + UINT_8 aucChannelBusyTime[48]; + UINT_8 aucReserved2[16]; +}; + +#if CFG_SUPPORT_P2P_ECSA +typedef struct _CMD_SET_ECSA_PARAM_T { + UINT_8 ucNetTypeIndex; + UINT_8 ucSwitchMode; + UINT_8 ucOperatingClass; + UINT_8 ucSwitchTotalCount; /* unit:tbtt, min value: 1 sec */ + UINT_8 ucPrimaryChannel; + UINT_8 ucRfSco; + UINT_8 ucReserved[2]; +} CMD_SET_ECSA_PARAM, *P_CMD_SET_ECSA_PARAM; +typedef struct _EVENT_ECSA_RESULT_T { + UINT_8 ucNetTypeIndex; + UINT_8 ucStatus; /* + * 0: ECSA success + * 1: update beacon success + * 2: Fail due to wrong parameter + * 3: Set channel fail + */ + UINT_8 ucPrimaryChannel; + UINT_8 ucRfSco; + UINT_8 ucReserved[4]; +} EVENT_ECSA_RESULT, *P_EVENT_ECSA_RESULT; +#endif + +#if CFG_SUPPORT_GAMING_MODE +struct GAMING_MODE_SETTING { + UINT_8 fgEnable; + UINT_8 aucReserved[7]; +}; + +struct CMD_GAMING_MODE_HEADER { + UINT_8 ucVersion; + UINT_8 ucType; + UINT_8 ucMagicCode; + UINT_8 ucBufferLen; + struct GAMING_MODE_SETTING rSetting; +}; +#endif /* CFG_SUPPORT_GAMING_MODE */ + +struct CMD_EVENT_LOG_LEVEL { + UINT_32 u4Version; + UINT_32 u4LogLevel; + UINT_8 aucReserved[3]; +}; + +enum ENUM_SCN_FUNC_MASK { + ENUM_SCN_RANDOM_MAC_EN = (1 << 0), +}; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +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); + +VOID nicCmdEventSetStopSchedScan(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +/* Statistics responder */ +VOID nicCmdEventQueryXmitOk(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryRecvOk(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryXmitError(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryRecvError(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryRecvNoBuffer(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryRecvCrcError(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryRecvErrorAlignment(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryXmitOneCollision(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryXmitMoreCollisions(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryXmitMaxCollisions(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +/* for timeout check */ +VOID nicOidCmdTimeoutCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +VOID nicCmdTimeoutCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +VOID nicOidCmdEnterRFTestTimeout(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +#if CFG_SUPPORT_BUILD_DATE_CODE +VOID nicCmdEventBuildDateCode(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +#endif + +VOID nicCmdEventQueryStaStatistics(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryLteSafeChn(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +#if CFG_SUPPORT_BATCH_SCAN +VOID nicCmdEventBatchScanResult(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +#endif + +VOID nicCmdEventGetBSSInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +#ifdef FW_CFG_SUPPORT +VOID nicCmdEventQueryCfgRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +#endif +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _NIC_CMD_EVENT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic_init_cmd_event.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic_init_cmd_event.h new file mode 100644 index 0000000000000..dc6d8bb984344 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/nic_init_cmd_event.h @@ -0,0 +1,149 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _NIC_INIT_CMD_EVENT_H +#define _NIC_INIT_CMD_EVENT_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "gl_typedef.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define INIT_CMD_STATUS_SUCCESS 0 +#define INIT_CMD_STATUS_REJECTED_INVALID_PARAMS 1 +#define INIT_CMD_STATUS_REJECTED_CRC_ERROR 2 +#define INIT_CMD_STATUS_REJECTED_DECRYPT_FAIL 3 +#define INIT_CMD_STATUS_UNKNOWN 4 + +#define EVENT_HDR_SIZE OFFSET_OF(WIFI_EVENT_T, aucBuffer[0]) + +typedef enum _ENUM_INIT_CMD_ID { + INIT_CMD_ID_DOWNLOAD_BUF = 1, + INIT_CMD_ID_WIFI_START, + INIT_CMD_ID_ACCESS_REG, + INIT_CMD_ID_QUERY_PENDING_ERROR +} ENUM_INIT_CMD_ID, *P_ENUM_INIT_CMD_ID; + +typedef enum _ENUM_INIT_EVENT_ID { + INIT_EVENT_ID_CMD_RESULT = 1, + INIT_EVENT_ID_ACCESS_REG, + INIT_EVENT_ID_PENDING_ERROR +} ENUM_INIT_EVENT_ID, *P_ENUM_INIT_EVENT_ID; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef UINT_8 CMD_STATUS; + +/* commands */ +typedef struct _INIT_WIFI_CMD_T { + UINT_8 ucCID; + UINT_8 ucSeqNum; + UINT_16 u2Reserved; + UINT_8 aucBuffer[0]; +} INIT_WIFI_CMD_T, *P_INIT_WIFI_CMD_T; + +typedef struct _INIT_HIF_TX_HEADER_T { + UINT_16 u2TxByteCount; + UINT_8 ucEtherTypeOffset; + UINT_8 ucCSflags; + INIT_WIFI_CMD_T rInitWifiCmd; +} INIT_HIF_TX_HEADER_T, *P_INIT_HIF_TX_HEADER_T; + +#define DOWNLOAD_BUF_ENCRYPTION_MODE BIT(0) +#define DOWNLOAD_BUF_NO_CRC_CHECKING BIT(30) +#define DOWNLOAD_BUF_ACK_OPTION BIT(31) +typedef struct _INIT_CMD_DOWNLOAD_BUF { + UINT_32 u4Address; + UINT_32 u4Length; + UINT_32 u4CRC32; + UINT_32 u4DataMode; + UINT_8 aucBuffer[0]; +} INIT_CMD_DOWNLOAD_BUF, *P_INIT_CMD_DOWNLOAD_BUF; + +typedef struct _INIT_CMD_WIFI_START { + UINT_32 u4Override; + UINT_32 u4Address; +} INIT_CMD_WIFI_START, *P_INIT_CMD_WIFI_START; + +typedef struct _INIT_CMD_ACCESS_REG { + UINT_8 ucSetQuery; + UINT_8 aucReserved[3]; + UINT_32 u4Address; + UINT_32 u4Data; +} INIT_CMD_ACCESS_REG, *P_INIT_CMD_ACCESS_REG; + +/* Events */ +typedef struct _INIT_WIFI_EVENT_T { + UINT_16 u2RxByteCount; + UINT_8 ucEID; + UINT_8 ucSeqNum; + UINT_8 aucBuffer[0]; +} INIT_WIFI_EVENT_T, *P_INIT_WIFI_EVENT_T; + +typedef struct _INIT_HIF_RX_HEADER_T { + INIT_WIFI_EVENT_T rInitWifiEvent; +} INIT_HIF_RX_HEADER_T, *P_INIT_HIF_RX_HEADER_T; + +typedef struct _INIT_EVENT_CMD_RESULT { + UINT_8 ucStatus; /* 0: success */ + /* 1: rejected by invalid param */ + /* 2: rejected by incorrect CRC */ + /* 3: rejected by decryption failure */ + /* 4: unknown CMD */ + UINT_8 aucReserved[3]; +} INIT_EVENT_CMD_RESULT, *P_INIT_EVENT_CMD_RESULT, INIT_EVENT_PENDING_ERROR, *P_INIT_EVENT_PENDING_ERROR; + +typedef struct _INIT_EVENT_ACCESS_REG { + UINT_32 u4Address; + UINT_32 u4Data; +} INIT_EVENT_ACCESS_REG, *P_INIT_EVENT_ACCESS_REG; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _NIC_INIT_CMD_EVENT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/p2p_precomp.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/p2p_precomp.h new file mode 100644 index 0000000000000..4eac7dc8a141b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/p2p_precomp.h @@ -0,0 +1,205 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _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" + + +#if CFG_ENABLE_WIFI_DIRECT +#include "p2p_typedef.h" +#include "p2p_cmd_buf.h" +#include "p2p_nic_cmd_event.h" +#include "p2p_mac.h" +#include "p2p_nic.h" +#endif + +/*------------------------------------------------------------------------------ + * .\include\mgmt + *------------------------------------------------------------------------------ + */ + +#include "hem_mbox.h" + +#include "scan.h" +#include "bss.h" + +#include "wlan_lib.h" +#include "wlan_oid.h" +#include "wlan_bow.h" + +#include "wlan_p2p.h" + +#include "hal.h" + +#if defined(MT6620) +#include "mt6620_reg.h" +#endif + +#include "rlm.h" +#include "rlm_domain.h" +#include "rlm_protection.h" +#include "rlm_obss.h" +#include "rate.h" +#include "wnm.h" + +#include "aa_fsm.h" + +#include "cnm_timer.h" +#include "que_mgt.h" +#include "wmm.h" + +#if CFG_ENABLE_BT_OVER_WIFI +#include "bow.h" +#include "bow_fsm.h" +#endif + +#include "pwr_mgt.h" + +#include "cnm.h" +/* Dependency: aa_fsm.h (ENUM_AA_STATE_T), p2p_fsm.h (WPS_ATTRI_MAX_LEN_DEVICE_NAME) */ +#include "cnm_mem.h" +#include "cnm_scan.h" + +#include "p2p_rlm_obss.h" +#include "p2p_bss.h" +#include "p2p.h" +/* Dependency: cnm_timer.h (TIMER_T) */ +#include "p2p_fsm.h" +#include "p2p_scan.h" +#include "p2p_state.h" +#include "p2p_func.h" +#include "p2p_rlm.h" +#include "p2p_assoc.h" +#include "p2p_ie.h" + +#include "privacy.h" + +#include "mib.h" + +#include "auth.h" +#include "assoc.h" + +#include "ais_fsm.h" + +#include "adapter.h" + +#include "que_mgt.h" +#include "rftest.h" + +#if CFG_RSN_MIGRATION +#include "rsn.h" +#include "sec_fsm.h" +#endif + +#if CFG_SUPPORT_WAPI +#include "wapi.h" +#endif + +/*------------------------------------------------------------------------------ + * NVRAM structure + *------------------------------------------------------------------------------ + */ +#include "CFG_Wifi_File.h" + +#include "gl_p2p_kal.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /*_P2P_PRECOMP_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/p2p_typedef.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/p2p_typedef.h new file mode 100644 index 0000000000000..a460a5289806f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/p2p_typedef.h @@ -0,0 +1,167 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _P2P_TYPEDEF_H +#define _P2P_TYPEDEF_H + +#if CFG_ENABLE_WIFI_DIRECT + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/* +* type definition of pointer to p2p structure +*/ +/* typedef struct _GL_P2P_INFO_T GL_P2P_INFO_T, *P_GL_P2P_INFO_T; */ +typedef struct _P2P_INFO_T P2P_INFO_T, *P_P2P_INFO_T; + +typedef struct _P2P_FSM_INFO_T P2P_FSM_INFO_T, *P_P2P_FSM_INFO_T; + +typedef struct _P2P_CONNECTION_SETTINGS_T P2P_CONNECTION_SETTINGS_T, *P_P2P_CONNECTION_SETTINGS_T; + +/* Type definition for function pointer to p2p function*/ +typedef BOOLEAN(*P2P_LAUNCH) (P_GLUE_INFO_T prGlueInfo); + +typedef BOOLEAN(*P2P_REMOVE) (P_GLUE_INFO_T prGlueInfo, BOOLEAN fgIsWlanLaunched); + +typedef BOOLEAN(*KAL_P2P_GET_CIPHER) (IN P_GLUE_INFO_T prGlueInfo); + +typedef BOOLEAN(*KAL_P2P_GET_TKIP_CIPHER) (IN P_GLUE_INFO_T prGlueInfo); + +typedef BOOLEAN(*KAL_P2P_GET_CCMP_CIPHER) (IN P_GLUE_INFO_T prGlueInfo); + +typedef BOOLEAN(*KAL_P2P_GET_WSC_MODE) (IN P_GLUE_INFO_T prGlueInfo); + +typedef struct net_device *(*KAL_P2P_GET_DEV_HDLR) (P_GLUE_INFO_T prGlueInfo); + +typedef VOID(*KAL_P2P_SET_MULTICAST_WORK_ITEM) (P_GLUE_INFO_T prGlueInfo); + +typedef VOID(*P2P_NET_REGISTER) (P_GLUE_INFO_T prGlueInfo); + +typedef VOID(*P2P_NET_UNREGISTER) (P_GLUE_INFO_T prGlueInfo); + +typedef VOID(*KAL_P2P_UPDATE_ASSOC_INFO) (IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBody, + IN UINT_32 u4FrameBodyLen, IN BOOLEAN fgReassocRequest); + +typedef BOOLEAN(*P2P_VALIDATE_AUTH) (IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, IN PP_STA_RECORD_T pprStaRec, OUT PUINT_16 pu2StatusCode); + +typedef BOOLEAN(*P2P_VALIDATE_ASSOC_REQ) (IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu4ControlFlags); + +typedef VOID(*P2P_RUN_EVENT_AAA_TX_FAIL) (IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +typedef BOOLEAN(*P2P_PARSE_CHECK_FOR_P2P_INFO_ELEM) (IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBuf, OUT PUINT_8 pucOuiType); + +typedef WLAN_STATUS(*P2P_RUN_EVENT_AAA_COMPLETE) (IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +typedef VOID(*P2P_PROCESS_EVENT_UPDATE_NOA_PARAM) (IN P_ADAPTER_T prAdapter, + UINT_8 ucNetTypeIndex, + P_EVENT_UPDATE_NOA_PARAMS_T prEventUpdateNoaParam); + +typedef VOID(*SCAN_P2P_PROCESS_BEACON_AND_PROBE_RESP) (IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN P_WLAN_STATUS prStatus, + IN P_BSS_DESC_T prBssDesc, + IN P_WLAN_BEACON_FRAME_T prWlanBeaconFrame); + +typedef VOID(*P2P_RX_PUBLIC_ACTION_FRAME) (P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +typedef VOID(*RLM_RSP_GENERATE_OBSS_SCAN_IE) (P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + +typedef VOID(*RLM_UPDATE_BW_BY_CH_LIST_FOR_AP) (P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); + +typedef VOID(*RLM_PROCESS_PUBLIC_ACTION) (P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); + +typedef VOID(*RLM_PROCESS_HT_ACTION) (P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); + +typedef VOID(*RLM_UPDATE_PARAMS_FOR_AP) (P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, BOOLEAN fgUpdateBeacon); + +typedef VOID(*RLM_HANDLE_OBSS_STATUS_EVENT_PKT) (P_ADAPTER_T prAdapter, P_EVENT_AP_OBSS_STATUS_T prObssStatus); + +typedef BOOLEAN(*P2P_FUNC_VALIDATE_PROBE_REQ) (IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, OUT PUINT_32 pu4ControlFlags); + +typedef VOID(*RLM_BSS_INIT_FOR_AP) (P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); + +typedef UINT_32(*P2P_GET_PROB_RSP_IE_TABLE_SIZE) (VOID); + +typedef PUINT_8(*P2P_BUILD_REASSOC_REQ_FRAME_COMMON_IES) (IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN PUINT_8 pucBuffer); + +typedef VOID(*P2P_FUNC_DISCONNECT) (IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, IN BOOLEAN fgSendDeauth, IN UINT_16 u2ReasonCode); + +typedef VOID(*P2P_FSM_RUN_EVENT_RX_DEAUTH) (IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb); + +typedef VOID(*P2P_FSM_RUN_EVENT_RX_DISASSOC) (IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb); + +typedef BOOLEAN(*P2P_FUN_IS_AP_MODE) (IN P_P2P_FSM_INFO_T prP2pFsmInfo); + +typedef VOID(*P2P_FSM_RUN_EVENT_BEACON_TIMEOUT) (IN P_ADAPTER_T prAdapter); + +typedef VOID(*P2P_FUNC_STORE_ASSOC_RSP_IE_BUFFER) (IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +typedef VOID(*P2P_GENERATE_P2P_IE) (IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +typedef UINT_32(*P2P_CALCULATE_P2P_IE_LEN) (IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /*CFG_ENABLE_WIFI_DIRECT */ + +#endif /* _P2P_TYPEDEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/precomp.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/precomp.h new file mode 100644 index 0000000000000..1c57d66074a94 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/precomp.h @@ -0,0 +1,239 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _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" + + +#if CFG_ENABLE_WIFI_DIRECT +#include "p2p_typedef.h" +#include "p2p_cmd_buf.h" +#include "p2p_nic_cmd_event.h" +#include "p2p_mac.h" +#include "p2p_nic.h" +#endif + +/*------------------------------------------------------------------------------ + * .\include\mgmt + *------------------------------------------------------------------------------ + */ + +#include "hem_mbox.h" + +#include "scan.h" +#include "bss.h" + +#include "wlan_lib.h" +#include "wlan_oid.h" +#include "wlan_bow.h" + +#if CFG_ENABLE_WIFI_DIRECT +#include "wlan_p2p.h" +#endif + +#include "hal.h" + +#if defined(MT6620) +#include "mt6620_reg.h" +#elif defined(MT6628) +/* #include "mt6628_reg.h" */ +#include "mtreg.h" +#endif + +#include "rlm.h" +#include "rlm_domain.h" +#include "rlm_protection.h" +#include "rlm_obss.h" +#include "rate.h" +#include "wnm.h" + +#include "qosmap.h" + +#include "aa_fsm.h" + +#include "cnm_timer.h" + +#include "que_mgt.h" + +#include "wmm.h" + +#if CFG_ENABLE_BT_OVER_WIFI +#include "bow.h" +#include "bow_fsm.h" +#endif + +#include "pwr_mgt.h" + +#if (CFG_SUPPORT_STATISTICS == 1) +#include "stats.h" +#endif /* CFG_SUPPORT_STATISTICS */ + +#include "cnm.h" +/* Dependency: aa_fsm.h (ENUM_AA_STATE_T), p2p_fsm.h (WPS_ATTRI_MAX_LEN_DEVICE_NAME) */ +#include "cnm_mem.h" +#include "cnm_scan.h" + +#if CFG_ENABLE_WIFI_DIRECT +#include "p2p_rlm_obss.h" +#include "p2p_bss.h" +#include "p2p.h" +#include "p2p_fsm.h" +#include "p2p_scan.h" +#include "p2p_state.h" +#include "p2p_func.h" +#include "p2p_rlm.h" +#include "p2p_assoc.h" +#include "p2p_ie.h" +#endif + +#include "privacy.h" + +#include "mib.h" + +#include "auth.h" +#include "assoc.h" + +#if CFG_SUPPORT_ROAMING +#include "roaming_fsm.h" +#endif /* CFG_SUPPORT_ROAMING */ + +#include "ais_fsm.h" + +#include "adapter.h" + +#include "que_mgt.h" +#include "rftest.h" + +#if CFG_RSN_MIGRATION +#include "rsn.h" +#include "sec_fsm.h" +#endif + +#if CFG_SUPPORT_WAPI +#include "wapi.h" +#endif + +/*------------------------------------------------------------------------------ + * NVRAM structure + *------------------------------------------------------------------------------ + */ +#include "CFG_Wifi_File.h" + +#if CFG_ENABLE_WIFI_DIRECT +#include "gl_p2p_kal.h" +#endif + +typedef int (*set_p2p_mode) (struct net_device *netdev, PARAM_CUSTOM_P2P_SET_STRUCT_T p2pmode); + +extern void wlanRegisterNotifier(void); +extern void wlanUnregisterNotifier(void); +extern void register_set_p2p_mode_handler(set_p2p_mode handler); + +extern BOOLEAN fgIsResetting; + +extern UINT_8 g_aucBufIpAddr[32]; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _PRECOMP_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/pwr_mgt.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/pwr_mgt.h new file mode 100644 index 0000000000000..2e885fdc15b3b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/pwr_mgt.h @@ -0,0 +1,100 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _PWR_MGT_H +#define _PWR_MGT_H +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define PM_UAPSD_AC0 (BIT(0)) +#define PM_UAPSD_AC1 (BIT(1)) +#define PM_UAPSD_AC2 (BIT(2)) +#define PM_UAPSD_AC3 (BIT(3)) + +#define PM_UAPSD_ALL (PM_UAPSD_AC0 | PM_UAPSD_AC1 | PM_UAPSD_AC2 | PM_UAPSD_AC3) +#define PM_UAPSD_NONE 0 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef struct _PM_PROFILE_SETUP_INFO_T { + /* Profile setup */ + UINT_8 ucBmpDeliveryAC; /* 0: AC_BE, 1: AC_BK, 2: AC_VI, 3: AC_VO */ + UINT_8 ucBmpTriggerAC; /* 0: AC_BE, 1: AC_BK, 2: AC_VI, 3: AC_VO */ + + UINT_8 ucUapsdSp; /* Number of triggered packets in UAPSD */ + +} PM_PROFILE_SETUP_INFO_T, *P_PM_PROFILE_SETUP_INFO_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#if !CFG_ENABLE_FULL_PM +#define ACQUIRE_POWER_CONTROL_FROM_PM(_prAdapter) +#define RECLAIM_POWER_CONTROL_TO_PM(_prAdapter, _fgEnableGINT_in_IST) +#else +#define ACQUIRE_POWER_CONTROL_FROM_PM(_prAdapter) \ + { \ + if (_prAdapter->fgIsFwOwn) { \ + nicpmSetDriverOwn(_prAdapter); \ + } \ + /* Increase Block to Enter Low Power Semaphore count */ \ + GLUE_INC_REF_CNT(_prAdapter->u4PwrCtrlBlockCnt); \ + } + +#define RECLAIM_POWER_CONTROL_TO_PM(_prAdapter, _fgEnableGINT_in_IST) \ + { \ + ASSERT(_prAdapter->u4PwrCtrlBlockCnt != 0); \ + /* Decrease Block to Enter Low Power Semaphore count */ \ + GLUE_DEC_REF_CNT(_prAdapter->u4PwrCtrlBlockCnt); \ + if (_prAdapter->fgWiFiInSleepyState && (_prAdapter->u4PwrCtrlBlockCnt == 0)) { \ + nicpmSetFWOwn(_prAdapter, _fgEnableGINT_in_IST); \ + } \ + } +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _PWR_MGT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/queue.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/queue.h new file mode 100644 index 0000000000000..da508aa241d10 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/queue.h @@ -0,0 +1,170 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _QUEUE_H +#define _QUEUE_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_typedef.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Singly Queue Structures - Entry Part */ +typedef struct _QUE_ENTRY_T { + struct _QUE_ENTRY_T *prNext; + struct _QUE_ENTRY_T *prPrev; /* For Rx buffer reordering used only */ +} QUE_ENTRY_T, *P_QUE_ENTRY_T; + +/* Singly Queue Structures - Queue Part */ +typedef struct _QUE_T { + P_QUE_ENTRY_T prHead; + P_QUE_ENTRY_T prTail; + UINT_32 u4NumElem; +} QUE_T, *P_QUE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/* + * To resolve compiler warning of address check -Waddress + * Redefine a ASSERT dedicate for queue operation + */ +#if DBG +#define QUE_ASSERT ASSERT +#else +#define QUE_ASSERT(_exp) +#endif + +#define QUEUE_INITIALIZE(prQueue) \ + { \ + (prQueue)->prHead = (P_QUE_ENTRY_T)NULL; \ + (prQueue)->prTail = (P_QUE_ENTRY_T)NULL; \ + (prQueue)->u4NumElem = 0; \ + } + +#define QUEUE_IS_EMPTY(prQueue) (((P_QUE_T)(prQueue))->prHead == (P_QUE_ENTRY_T)NULL) + +#define QUEUE_IS_NOT_EMPTY(prQueue) ((prQueue)->u4NumElem > 0) + +#define QUEUE_GET_HEAD(prQueue) ((prQueue)->prHead) + +#define QUEUE_GET_TAIL(prQueue) ((prQueue)->prTail) + +#define QUEUE_GET_NEXT_ENTRY(prQueueEntry) ((prQueueEntry)->prNext) + +#define QUEUE_INSERT_HEAD(prQueue, prQueueEntry) \ + { \ + QUE_ASSERT(prQueue); \ + QUE_ASSERT(prQueueEntry); \ + (prQueueEntry)->prNext = (prQueue)->prHead; \ + (prQueue)->prHead = (prQueueEntry); \ + if ((prQueue)->prTail == (P_QUE_ENTRY_T)NULL) { \ + (prQueue)->prTail = (prQueueEntry); \ + } \ + ((prQueue)->u4NumElem)++; \ + } + +#define QUEUE_INSERT_TAIL(prQueue, prQueueEntry) \ + { \ + QUE_ASSERT(prQueue); \ + QUE_ASSERT(prQueueEntry); \ + (prQueueEntry)->prNext = (P_QUE_ENTRY_T)NULL; \ + if ((prQueue)->prTail) { \ + ((prQueue)->prTail)->prNext = (prQueueEntry); \ + } else { \ + (prQueue)->prHead = (prQueueEntry); \ + } \ + (prQueue)->prTail = (prQueueEntry); \ + ((prQueue)->u4NumElem)++; \ + } + +/* NOTE: We assume the queue entry located at the beginning of "prQueueEntry Type", + * so that we can cast the queue entry to other data type without doubts. + * And this macro also decrease the total entry count at the same time. + */ +#define QUEUE_REMOVE_HEAD(prQueue, prQueueEntry, _P_TYPE) \ + { \ + QUE_ASSERT(prQueue); \ + prQueueEntry = (_P_TYPE)((prQueue)->prHead); \ + if (prQueueEntry) { \ + (prQueue)->prHead = ((P_QUE_ENTRY_T)(prQueueEntry))->prNext; \ + if ((prQueue)->prHead == (P_QUE_ENTRY_T)NULL) { \ + (prQueue)->prTail = (P_QUE_ENTRY_T)NULL; \ + } \ + ((P_QUE_ENTRY_T)(prQueueEntry))->prNext = (P_QUE_ENTRY_T)NULL; \ + ((prQueue)->u4NumElem)--; \ + } \ + } + +#define QUEUE_MOVE_ALL(prDestQueue, prSrcQueue) \ + { \ + QUE_ASSERT(prDestQueue); \ + QUE_ASSERT(prSrcQueue); \ + *(P_QUE_T)prDestQueue = *(P_QUE_T)prSrcQueue; \ + QUEUE_INITIALIZE(prSrcQueue); \ + } + +#define QUEUE_CONCATENATE_QUEUES(prDestQueue, prSrcQueue) \ + { \ + QUE_ASSERT(prDestQueue); \ + QUE_ASSERT(prSrcQueue); \ + if (prSrcQueue->u4NumElem > 0) { \ + if ((prDestQueue)->prTail) { \ + ((prDestQueue)->prTail)->prNext = (prSrcQueue)->prHead; \ + } else { \ + (prDestQueue)->prHead = (prSrcQueue)->prHead; \ + } \ + (prDestQueue)->prTail = (prSrcQueue)->prTail; \ + ((prDestQueue)->u4NumElem) += ((prSrcQueue)->u4NumElem); \ + QUEUE_INITIALIZE(prSrcQueue); \ + } \ + } + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _QUEUE_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/rftest.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/rftest.h new file mode 100644 index 0000000000000..261bd6f5acbbb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/rftest.h @@ -0,0 +1,260 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _RFTEST_H +#define _RFTEST_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* Table Version */ +#define RF_AUTO_TEST_FUNCTION_TABLE_VERSION 0x01000001 + +/* Power */ +#define RF_AT_PARAM_POWER_MASK BITS(0, 7) +#define RF_AT_PARAM_POWER_MAX RF_AT_PARAM_POWER_MASK + +/* Rate */ +#define RF_AT_PARAM_RATE_MCS_MASK BIT(31) +#define RF_AT_PARAM_RATE_MASK BITS(0, 7) +#define RF_AT_PARAM_RATE_CCK_MAX 3 +#define RF_AT_PARAM_RATE_1M 0 +#define RF_AT_PARAM_RATE_2M 1 +#define RF_AT_PARAM_RATE_5_5M 2 +#define RF_AT_PARAM_RATE_11M 3 +#define RF_AT_PARAM_RATE_6M 4 +#define RF_AT_PARAM_RATE_9M 5 +#define RF_AT_PARAM_RATE_12M 6 +#define RF_AT_PARAM_RATE_18M 7 +#define RF_AT_PARAM_RATE_24M 8 +#define RF_AT_PARAM_RATE_36M 9 +#define RF_AT_PARAM_RATE_48M 10 +#define RF_AT_PARAM_RATE_54M 11 + +/* Antenna */ +#define RF_AT_PARAM_ANTENNA_ID_MASK BITS(0, 7) +#define RF_AT_PARAM_ANTENNA_ID_MAX 1 + +/* Packet Length */ +#define RF_AT_PARAM_TX_80211HDR_BYTE_MAX (32) +#define RF_AT_PARAM_TX_80211PAYLOAD_BYTE_MAX (2048) + +#define RF_AT_PARAM_TX_PKTLEN_BYTE_DEFAULT 1024 +#define RF_AT_PARAM_TX_PKTLEN_BYTE_MAX \ + ((UINT_16)(RF_AT_PARAM_TX_80211HDR_BYTE_MAX + RF_AT_PARAM_TX_80211PAYLOAD_BYTE_MAX)) + +/* Packet Count */ +#define RF_AT_PARAM_TX_PKTCNT_DEFAULT 1000 +#define RF_AT_PARAM_TX_PKTCNT_UNLIMITED 0 + +/* Packet Interval */ +#define RF_AT_PARAM_TX_PKT_INTERVAL_US_DEFAULT 50 + +/* ALC */ +#define RF_AT_PARAM_ALC_DISABLE 0 +#define RF_AT_PARAM_ALC_ENABLE 1 + +/* TXOP */ +#define RF_AT_PARAM_TXOP_DEFAULT 0 +#define RF_AT_PARAM_TXOPQUE_QMASK BITS(16, 31) +#define RF_AT_PARAM_TXOPQUE_TMASK BITS(0, 15) +#define RF_AT_PARAM_TXOPQUE_AC0 (0<<16) +#define RF_AT_PARAM_TXOPQUE_AC1 (1<<16) +#define RF_AT_PARAM_TXOPQUE_AC2 (2<<16) +#define RF_AT_PARAM_TXOPQUE_AC3 (3<<16) +#define RF_AT_PARAM_TXOPQUE_AC4 (4<<16) +#define RF_AT_PARAM_TXOPQUE_QOFFSET 16 + +/* Retry Limit */ +#define RF_AT_PARAM_TX_RETRY_DEFAULT 0 +#define RF_AT_PARAM_TX_RETRY_MAX 6 + +/* QoS Queue */ +#define RF_AT_PARAM_QOSQUE_AC0 0 +#define RF_AT_PARAM_QOSQUE_AC1 1 +#define RF_AT_PARAM_QOSQUE_AC2 2 +#define RF_AT_PARAM_QOSQUE_AC3 3 +#define RF_AT_PARAM_QOSQUE_AC4 4 +#define RF_AT_PARAM_QOSQUE_DEFAULT RF_AT_PARAM_QOSQUE_AC0 + +/* Bandwidth */ +#define RF_AT_PARAM_BANDWIDTH_20MHZ 0 +#define RF_AT_PARAM_BANDWIDTH_40MHZ 1 +#define RF_AT_PARAM_BANDWIDTH_U20_IN_40MHZ 2 +#define RF_AT_PARAM_BANDWIDTH_D20_IN_40MHZ 3 +#define RF_AT_PARAM_BANDWIDTH_DEFAULT RF_AT_PARAM_BANDWIDTH_20MHZ + +/* GI (Guard Interval) */ +#define RF_AT_PARAM_GI_800NS 0 +#define RF_AT_PARAM_GI_400NS 1 +#define RF_AT_PARAM_GI_DEFAULT RF_AT_PARAM_GI_800NS + +/* STBC */ +#define RF_AT_PARAM_STBC_DISABLE 0 +#define RF_AT_PARAM_STBC_ENABLE 1 + +/* RIFS */ +#define RF_AT_PARAM_RIFS_DISABLE 0 +#define RF_AT_PARAM_RIFS_ENABLE 1 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Function ID List */ +typedef enum _ENUM_RF_AT_FUNCID_T { + RF_AT_FUNCID_VERSION = 0, + RF_AT_FUNCID_COMMAND, + RF_AT_FUNCID_POWER, + RF_AT_FUNCID_RATE, + RF_AT_FUNCID_PREAMBLE, + RF_AT_FUNCID_ANTENNA, + RF_AT_FUNCID_PKTLEN, + RF_AT_FUNCID_PKTCNT, + RF_AT_FUNCID_PKTINTERVAL, + RF_AT_FUNCID_TEMP_COMPEN, + RF_AT_FUNCID_TXOPLIMIT, + RF_AT_FUNCID_ACKPOLICY, + RF_AT_FUNCID_PKTCONTENT, + RF_AT_FUNCID_RETRYLIMIT, + RF_AT_FUNCID_QUEUE, + RF_AT_FUNCID_BANDWIDTH, + RF_AT_FUNCID_GI, + RF_AT_FUNCID_STBC, + RF_AT_FUNCID_CHNL_FREQ, + RF_AT_FUNCID_RIFS, + RF_AT_FUNCID_TRSW_TYPE, + RF_AT_FUNCID_RF_SX_SHUTDOWN, + RF_AT_FUNCID_PLL_SHUTDOWN, + RF_AT_FUNCID_SLOW_CLK_MODE, + RF_AT_FUNCID_ADC_CLK_MODE, + RF_AT_FUNCID_MEASURE_MODE, + RF_AT_FUNCID_VOLT_COMPEN, + RF_AT_FUNCID_DPD_TX_GAIN, + RF_AT_FUNCID_DPD_MODE, + RF_AT_FUNCID_TSSI_MODE, + RF_AT_FUNCID_TX_GAIN_CODE, + RF_AT_FUNCID_TX_PWR_MODE, + + /* Query command */ + RF_AT_FUNCID_TXED_COUNT = 32, + RF_AT_FUNCID_TXOK_COUNT, + RF_AT_FUNCID_RXOK_COUNT, + RF_AT_FUNCID_RXERROR_COUNT, + RF_AT_FUNCID_RESULT_INFO, + RF_AT_FUNCID_TRX_IQ_RESULT, + RF_AT_FUNCID_TSSI_RESULT, + RF_AT_FUNCID_DPD_RESULT, + RF_AT_FUNCID_RXV_DUMP, + RF_AT_FUNCID_RX_PHY_STATIS, + RF_AT_FUNCID_MEASURE_RESULT, + RF_AT_FUNCID_TEMP_SENSOR, + RF_AT_FUNCID_VOLT_SENSOR, + RF_AT_FUNCID_READ_EFUSE, + RF_AT_FUNCID_RX_RSSI, + RF_AT_FUNCID_FW_INFO, + RF_AT_FUNCID_DRV_INFO, + + /* Set command */ + RF_AT_FUNCID_SET_DPD_RESULT = 64, + RF_AT_FUNCID_SET_CW_MODE, + RF_AT_FUNCID_SET_JAPAN_CH14_FILTER, + RF_AT_FUNCID_WRITE_EFUSE, + RF_AT_FUNCID_SET_MAC_ADDRESS +} ENUM_RF_AT_FUNCID_T; + +/* Command */ +typedef enum _ENUM_RF_AT_COMMAND_T { + RF_AT_COMMAND_STOPTEST = 0, + RF_AT_COMMAND_STARTTX, + RF_AT_COMMAND_STARTRX, + RF_AT_COMMAND_RESET, + RF_AT_COMMAND_OUTPUT_POWER, /* Payload */ + RF_AT_COMMAND_LO_LEAKAGE, /* Local freq is renamed to Local leakage */ + RF_AT_COMMAND_CARRIER_SUPPR, /* OFDM (LTF/STF), CCK (PI,PI/2) */ + RF_AT_COMMAND_TRX_IQ_CAL, + RF_AT_COMMAND_TSSI_CAL, + RF_AT_COMMAND_DPD_CAL, + RF_AT_COMMAND_CW, + RF_AT_COMMAND_NUM +} ENUM_RF_AT_COMMAND_T; + +/* Preamble */ +typedef enum _ENUM_RF_AT_PREAMBLE_T { + RF_AT_PREAMBLE_NORMAL = 0, + RF_AT_PREAMBLE_CCK_SHORT, + RF_AT_PREAMBLE_11N_MM, + RF_AT_PREAMBLE_11N_GF, + RF_AT_PREAMBLE_NUM +} ENUM_RF_AT_PREAMBLE_T; + +/* Ack Policy */ +typedef enum _ENUM_RF_AT_ACK_POLICY_T { + RF_AT_ACK_POLICY_NORMAL = 0, + RF_AT_ACK_POLICY_NOACK, + RF_AT_ACK_POLICY_NOEXPLICTACK, + RF_AT_ACK_POLICY_BLOCKACK, + RF_AT_ACK_POLICY_NUM +} ENUM_RF_AT_ACK_POLICY_T; + +typedef enum _ENUM_RF_AUTOTEST_STATE_T { + RF_AUTOTEST_STATE_STANDBY = 0, + RF_AUTOTEST_STATE_TX, + RF_AUTOTEST_STATE_RX, + RF_AUTOTEST_STATE_RESET, + RF_AUTOTEST_STATE_OUTPUT_POWER, + RF_AUTOTEST_STATE_LOCA_FREQUENCY, + RF_AUTOTEST_STATE_CARRIER_SUPRRESION, + RF_AUTOTEST_STATE_NUM +} ENUM_RF_AUTOTEST_STATE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +WLAN_STATUS rftestSetATInfo(IN P_ADAPTER_T prAdapter, UINT_32 u4FuncIndex, UINT_32 u4FuncData); + +WLAN_STATUS +rftestQueryATInfo(IN P_ADAPTER_T prAdapter, + UINT_32 u4FuncIndex, UINT_32 u4FuncData, OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen); + +WLAN_STATUS rftestSetFrequency(IN P_ADAPTER_T prAdapter, IN UINT_32 u4FreqInKHz, IN PUINT_32 pu4SetInfoLen); + +#endif /* _RFTEST_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/tdls_extr.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/tdls_extr.h new file mode 100644 index 0000000000000..ef5a1cf8bdf89 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/tdls_extr.h @@ -0,0 +1,424 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _TDLS_EXTR_H +#define _TDLS_EXTR_H + +#if (CFG_SUPPORT_TDLS == 1) + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#define TDLS_TX_QUOTA_EMPTY_TIMEOUT 10 + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* protocol */ +#define TDLS_FRM_PROT_TYPE 0x890d + +/* TDLS uses Ethertype 89-0d frames. The UP shall be AC_VI, unless otherwise specified. */ +#define USER_PRIORITY_TDLS 5 + +/* Status code */ +#define TDLS_STATUS WLAN_STATUS + +#define TDLS_STATUS_SUCCESS WLAN_STATUS_SUCCESS +#define TDLS_STATUS_FAILURE WLAN_STATUS_FAILURE +#define TDLS_STATUS_INVALID_LENGTH WLAN_STATUS_INVALID_LENGTH +#define TDLS_STATUS_RESOURCES WLAN_STATUS_RESOURCES + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +#define TDLS_U32 UINT32 +#define TDLS_U16 UINT16 +#define TDLS_U8 UINT8 + +typedef enum _TDLS_REASON_CODE { + TDLS_REASON_CODE_UNREACHABLE = 25, + TDLS_REASON_CODE_UNSPECIFIED = 26, + + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_UNKNOWN = 0x80, /* 128 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_WIFI_OFF = 0x81, /* 129 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_ROAMING = 0x82, /* 130 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_TIMEOUT = 0x83, /* 131 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_AGE_TIMEOUT = 0x84, /* 132 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_REKEY = 0x85, /* 133 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_SEND_FAIL = 0x86, /* 134 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_SEND_MAX_FAIL = 0x87, /* 135 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_WRONG_NETWORK_IDX = 0x88, /* 136 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_NON_STATE3 = 0x89, /* 137 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_TX_QUOTA_EMPTY = 0x8a, /* 138 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_LOST_TEAR_DOWN = 0x8b /* 139 */ +} TDLS_REASON_CODE; + +/* TDLS FSM */ +typedef struct _TDLS_CMD_PEER_ADD_T { + + TDLS_U8 aucPeerMac[6]; + ENUM_NETWORK_TYPE_INDEX_T eNetworkType; +#if 0 + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex; + UINT_16 u2CapInfo; + + UINT_16 u2OperationalRateSet; + UINT_16 u2BSSBasicRateSet; + BOOLEAN fgIsUnknownBssBasicRate; + + UINT_8 ucPhyTypeSet; +#endif +} TDLS_CMD_PEER_ADD_T; + +typedef struct _TDLS_CMD_LINK_T { + ENUM_NETWORK_TYPE_INDEX_T eNetworkType; + TDLS_U8 aucPeerMac[6]; + BOOLEAN fgIsEnabled; +} TDLS_CMD_LINK_T; + +typedef struct _TDLS_CMD_PEER_UPDATE_HT_CAP_MCS_INFO_T { + TDLS_U8 arRxMask[10]; + TDLS_U16 u2RxHighest; + TDLS_U8 ucTxParams; + TDLS_U8 Reserved[3]; +} TDLS_CMD_PEER_UPDATE_HT_CAP_MCS_INFO_T; + +typedef struct _TDLS_CMD_PEER_UPDATE_HT_CAP_T { + TDLS_U16 u2CapInfo; + TDLS_U8 ucAmpduParamsInfo; + + /* 16 bytes MCS information */ + TDLS_CMD_PEER_UPDATE_HT_CAP_MCS_INFO_T rMCS; + + TDLS_U16 u2ExtHtCapInfo; + TDLS_U32 u4TxBfCapInfo; + TDLS_U8 ucAntennaSelInfo; +} TDLS_CMD_PEER_UPDATE_HT_CAP_T; + +typedef struct _TDLS_CMD_PEER_UPDATE_T { + + ENUM_NETWORK_TYPE_INDEX_T eNetworkType; + TDLS_U8 aucPeerMac[6]; + +#define TDLS_CMD_PEER_UPDATE_SUP_CHAN_MAX 50 + TDLS_U8 aucSupChan[TDLS_CMD_PEER_UPDATE_SUP_CHAN_MAX]; + + TDLS_U16 u2StatusCode; + +#define TDLS_CMD_PEER_UPDATE_SUP_RATE_MAX 50 + TDLS_U8 aucSupRate[TDLS_CMD_PEER_UPDATE_SUP_RATE_MAX]; + TDLS_U16 u2SupRateLen; + + TDLS_U8 UapsdBitmap; + TDLS_U8 UapsdMaxSp; /* MAX_SP */ + + TDLS_U16 u2Capability; +#define TDLS_CMD_PEER_UPDATE_EXT_CAP_MAXLEN 5 + TDLS_U8 aucExtCap[TDLS_CMD_PEER_UPDATE_EXT_CAP_MAXLEN]; + TDLS_U16 u2ExtCapLen; + + TDLS_CMD_PEER_UPDATE_HT_CAP_T rHtCap; + BOOLEAN fgIsSupHt; + +} TDLS_CMD_PEER_UPDATE_T; + +/* Command to TDLS core module */ +typedef enum _TDLS_CMD_CORE_ID { + TDLS_CORE_CMD_TEST_NULL_RCV = 0x00, + TDLS_CORE_CMD_TEST_PTI_RSP = 0x01, + TDLS_CORE_CMD_MIB_UPDATE = 0x02, + TDLS_CORE_CMD_TEST_TX_FAIL_SKIP = 0x03, + TDLS_CORE_CMD_UAPSD_CONF = 0x04, + TDLS_CORE_CMD_TEST_DATA_RCV = 0x05, + TDLS_CORE_CMD_TEST_PTI_REQ = 0x06, + TDLS_CORE_CMD_TEST_CHSW_REQ = 0x07, + TDLS_CORE_CMD_CHSW_CONF = 0x08, + TDLS_CORE_CMD_TEST_KEEP_ALIVE_SKIP = 0x09, + TDLS_CORE_CMD_TEST_CHSW_TIMEOUT_SKIP = 0x0a, + TDLS_CORE_CMD_TEST_CHSW_RSP = 0x0b, + TDLS_CORE_CMD_TEST_SCAN_SKIP = 0x0c, + TDLS_CORE_CMD_SETUP_CONF = 0x0d, + TDLS_CORE_CMD_TEST_TEAR_DOWN = 0x0e, + TDLS_CORE_CMD_KEY_INFO = 0x0f, + TDLS_CORE_CMD_TEST_PTI_TX_FAIL = 0x10 +} TDLS_CMD_CORE_ID; + +typedef struct _TDLS_CMD_CORE_TEST_NULL_RCV_T { + + TDLS_U32 u4PM; +} TDLS_CMD_CORE_TEST_NULL_RCV_T; + +typedef struct _TDLS_CMD_CORE_TEST_PTI_REQ_RCV_T { + + TDLS_U32 u4DialogToken; +} TDLS_CMD_CORE_TEST_PTI_REQ_RCV_T; + +typedef struct _TDLS_CMD_CORE_TEST_PTI_RSP_RCV_T { + + TDLS_U32 u4DialogToken; + TDLS_U32 u4PM; +} TDLS_CMD_CORE_TEST_PTI_RSP_RCV_T; + +typedef struct _TDLS_CMD_CORE_TEST_TEAR_DOWN_RCV_T { + + TDLS_U32 u4ReasonCode; +} TDLS_CMD_CORE_TEST_TEAR_DOWN_RCV_T; + +typedef struct _TDLS_CMD_CORE_TEST_CHST_REQ_RCV_T { + + TDLS_U32 u4Chan; + TDLS_U32 u4RegClass; + TDLS_U32 u4SecChanOff; + TDLS_U32 u4SwitchTime; + TDLS_U32 u4SwitchTimeout; +} TDLS_CMD_CORE_TEST_CHST_REQ_RCV_T; + +typedef struct _TDLS_CMD_CORE_TEST_CHST_RSP_RCV_T { + + TDLS_U32 u4Chan; + TDLS_U32 u4SwitchTime; + TDLS_U32 u4SwitchTimeout; + TDLS_U32 u4StatusCode; +} TDLS_CMD_CORE_TEST_CHST_RSP_RCV_T; + +typedef struct _TDLS_CMD_CORE_TEST_DATA_RCV_T { + + TDLS_U32 u4PM; + TDLS_U32 u4UP; + TDLS_U32 u4EOSP; + TDLS_U32 u4IsNull; +} TDLS_CMD_CORE_TEST_DATA_RCV_T; + +typedef struct _TDLS_CMD_CORE_MIB_PARAM_UPDATE_T { + + BOOLEAN Tdlsdot11TunneledDirectLinkSetupImplemented; + BOOLEAN Tdlsdot11TDLSPeerUAPSDBufferSTAActivated; + BOOLEAN Tdlsdot11TDLSPeerPSMActivated; + TDLS_U16 Tdlsdot11TDLSPeerUAPSDIndicationWindow; + BOOLEAN Tdlsdot11TDLSChannelSwitchingActivated; + TDLS_U8 Tdlsdot11TDLSPeerSTAMissingAckRetryLimit; + TDLS_U8 Tdlsdot11TDLSResponseTimeout; + TDLS_U16 Tdlsdot11TDLSProbeDelay; + TDLS_U8 Tdlsdot11TDLSDiscoveryRequestWindow; + TDLS_U8 Tdlsdot11TDLSACDeterminationInterval; +} TDLS_CMD_CORE_MIB_PARAM_UPDATE_T; + +typedef struct _TDLS_CMD_CORE_TEST_TX_FAIL_SKIP_T { + + BOOLEAN fgIsEnable; +} TDLS_CMD_CORE_TEST_TX_FAIL_SKIP_T; + +typedef struct _TDLS_CMD_CORE_UAPSD_CONFIG_T { + + BOOLEAN fgIsSpTimeoutSkip; + BOOLEAN fgIsPtiTimeoutSkip; +} TDLS_CMD_CORE_UAPSD_CONFIG_T; + +typedef struct _TDLS_CMD_CORE_SETUP_CONFIG_T { + + BOOLEAN fgIs2040Supported; +} TDLS_CMD_CORE_SETUP_CONFIG_T; + +typedef struct _TDLS_CMD_CORE_CHSW_CONFIG_T { + + TDLS_U8 ucNetTypeIndex; + BOOLEAN fgIsChSwEnabled; + BOOLEAN fgIsChSwStarted; + TDLS_U8 ucRegClass; + TDLS_U8 ucTargetChan; + TDLS_U8 ucSecChanOff; + BOOLEAN fgIsChSwRegular; +} TDLS_CMD_CORE_CHSW_CONFIG_T; + +typedef struct _TDLS_CMD_CORE_TEST_KEEP_ALIVE_SKIP_T { + + BOOLEAN fgIsEnable; +} TDLS_CMD_CORE_TEST_KEEP_ALIVE_SKIP_T; + +typedef struct _TDLS_CMD_CORE_TEST_CHSW_TIMEOUT_SKIP_T { + + BOOLEAN fgIsEnable; +} TDLS_CMD_CORE_TEST_CHSW_TIMEOUT_SKIP_T; + +typedef struct _TDLS_CMD_CORE_TEST_PROHIBIT_T { + + BOOLEAN fgIsEnable; + BOOLEAN fgIsSet; +} TDLS_CMD_CORE_TEST_PROHIBIT_T; + +typedef struct _TDLS_CMD_CORE_TEST_SCAN_SKIP_T { + + BOOLEAN fgIsEnable; +} TDLS_CMD_CORE_TEST_SCAN_SKIP_T; + +typedef struct _TDLS_CMD_CORE_INFO_DISPLAY_T { + + BOOLEAN fgIsToClearAllHistory; +} TDLS_CMD_CORE_INFO_DISPLAY_T; + +typedef struct _TDLS_CMD_CORE_TEST_PTI_TX_FAIL_T { + + BOOLEAN fgIsEnable; +} TDLS_CMD_CORE_TEST_PTI_TX_FAIL_T; + +typedef struct _TDLS_CMD_CORE_T { + + TDLS_U32 u4Command; /* TDLS_CMD_CORE_ID */ + + TDLS_U8 aucPeerMac[6]; + TDLS_U8 ucNetTypeIndex; + +#define TDLS_CMD_CORE_RESERVED_SIZE 50 + union { + TDLS_CMD_CORE_TEST_NULL_RCV_T rCmdNullRcv; + TDLS_CMD_CORE_TEST_PTI_REQ_RCV_T rCmdPtiReqRcv; + TDLS_CMD_CORE_TEST_PTI_RSP_RCV_T rCmdPtiRspRcv; + TDLS_CMD_CORE_TEST_TEAR_DOWN_RCV_T rCmdTearDownRcv; + TDLS_CMD_CORE_TEST_CHST_REQ_RCV_T rCmdChStReqRcv; + TDLS_CMD_CORE_TEST_CHST_RSP_RCV_T rCmdChStRspRcv; + TDLS_CMD_CORE_TEST_DATA_RCV_T rCmdDatRcv; + TDLS_CMD_CORE_TEST_TX_FAIL_SKIP_T rCmdTxFailSkip; + TDLS_CMD_CORE_TEST_KEEP_ALIVE_SKIP_T rCmdKeepAliveSkip; + TDLS_CMD_CORE_TEST_CHSW_TIMEOUT_SKIP_T rCmdChSwTimeoutSkip; + TDLS_CMD_CORE_TEST_PROHIBIT_T rCmdProhibit; + TDLS_CMD_CORE_TEST_SCAN_SKIP_T rCmdScanSkip; + TDLS_CMD_CORE_TEST_PTI_TX_FAIL_T rCmdPtiTxFail; + + TDLS_CMD_CORE_MIB_PARAM_UPDATE_T rCmdMibUpdate; + TDLS_CMD_CORE_UAPSD_CONFIG_T rCmdUapsdConf; + TDLS_CMD_CORE_CHSW_CONFIG_T rCmdChSwConf; + TDLS_CMD_CORE_SETUP_CONFIG_T rCmdSetupConf; + TDLS_CMD_CORE_INFO_DISPLAY_T rCmdInfoDisplay; + TDLS_U8 Reserved[TDLS_CMD_CORE_RESERVED_SIZE]; + } Content; +} TDLS_CMD_CORE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/* + * assign station record idx for the packet only when STA_STATE_3 + * Or we will try to send data frame when the TDLS peer's state is STA_STATE_1 + * EX: + * 1. mtk_cfg80211_add_station: First create the STA_RECORD_T; + * 2. TdlsexCfg80211TdlsMgmt: Send a TDLS request frame. + * 3. mtk_cfg80211_add_station: Change state to STA_STATE_1. + * 4. TdlsexCfg80211TdlsMgmt: Send a TDLS request frame. + */ +#define TDLSEX_STA_REC_IDX_GET(__prAdapter__, __MsduInfo__) \ +{ \ + STA_RECORD_T *__StaRec__; \ + __MsduInfo__->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; \ + __StaRec__ = cnmGetStaRecByAddress(__prAdapter__, \ + (UINT_8) NETWORK_TYPE_AIS_INDEX, \ + __MsduInfo__->aucEthDestAddr); \ + if ((__StaRec__ != NULL) && \ + ((__StaRec__)->ucStaState == STA_STATE_3) && \ + (IS_TDLS_STA(__StaRec__))) { \ + __MsduInfo__->ucStaRecIndex = __StaRec__->ucIndex; \ + } \ +} + +/* fill wiphy flag */ +#define TDLSEX_WIPHY_FLAGS_INIT(__fgFlag__)\ +{ \ + __fgFlag__ |= (WIPHY_FLAG_SUPPORTS_TDLS | WIPHY_FLAG_TDLS_EXTERNAL_SETUP);\ +} + +/* assign user priority of a TDLS action frame */ +/* + * According to 802.11z: Setup req/resp are sent in AC_BK, otherwise we should default + * to AC_VI. + */ +#define TDLSEX_UP_ASSIGN(__UserPriority__) \ +{ \ + __UserPriority__ = USER_PRIORITY_TDLS; \ +} + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +int +TdlsexCfg80211TdlsMgmt(struct wiphy *wiphy, struct net_device *dev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, + bool initiator, const u8 *buf, size_t len); + +int TdlsexCfg80211TdlsOper(struct wiphy *wiphy, struct net_device *dev, + const u8 *peer, enum nl80211_tdls_operation oper); + +VOID TdlsexCmd(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +VOID TdlsexBssExtCapParse(STA_RECORD_T *prStaRec, UINT_8 *pucIE); + +VOID TdlsexEventHandle(P_GLUE_INFO_T prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen); + +TDLS_STATUS TdlsexKeyHandle(ADAPTER_T *prAdapter, PARAM_KEY_T *prNewKey, ENUM_NETWORK_TYPE_INDEX_T eNetworkType); + +VOID TdlsexInit(ADAPTER_T *prAdapter); + +BOOLEAN TdlsexIsAnyPeerInPowerSave(ADAPTER_T *prAdapter); + +TDLS_STATUS TdlsexLinkCtrl(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +VOID +TdlsexLinkHistoryRecord(GLUE_INFO_T *prGlueInfo, + BOOLEAN fgIsTearDown, UINT8 *pucPeerMac, BOOLEAN fgIsFromUs, UINT16 u2ReasonCode); + +TDLS_STATUS TdlsexMgmtCtrl(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +TDLS_STATUS TdlsexPeerAdd(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, PUINT_32 pu4SetInfoLen); + +TDLS_STATUS TdlsexPeerUpdate(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, PUINT_32 pu4SetInfoLen); + +BOOLEAN TdlsexRxFrameDrop(GLUE_INFO_T *prGlueInfo, struct sk_buff *skb); + +VOID TdlsexRxFrameHandle(GLUE_INFO_T *prGlueInfo, struct sk_buff *skb); + +TDLS_STATUS TdlsexStaRecIdxGet(ADAPTER_T *prAdapter, MSDU_INFO_T *prMsduInfo); + +VOID TdlsexTxQuotaCheck(GLUE_INFO_T *prGlueInfo, STA_RECORD_T *prStaRec, UINT8 FreeQuota); + +VOID TdlsexUninit(ADAPTER_T *prAdapter); + +VOID TdlsexForwardFrameTag(struct sk_buff *skb, BOOLEAN fgDrop); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* CFG_SUPPORT_TDLS */ + +#endif /* _TDLS_EXTR_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/typedef.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/typedef.h new file mode 100644 index 0000000000000..071b5938e65fc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/typedef.h @@ -0,0 +1,155 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _TYPEDEF_H +#define _TYPEDEF_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/* ieee80211.h of linux has duplicated definitions */ +#if defined(WLAN_STATUS_SUCCESS) +#undef WLAN_STATUS_SUCCESS +#endif + +#define WLAN_STATUS_SUCCESS ((WLAN_STATUS) 0x00000000L) +#define WLAN_STATUS_PENDING ((WLAN_STATUS) 0x00000103L) +#define WLAN_STATUS_NOT_ACCEPTED ((WLAN_STATUS) 0x00010003L) + +#define WLAN_STATUS_MEDIA_CONNECT ((WLAN_STATUS) 0x4001000BL) +#define WLAN_STATUS_MEDIA_DISCONNECT ((WLAN_STATUS) 0x4001000CL) +#define WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY ((WLAN_STATUS) 0x4001000DL) + +#define WLAN_STATUS_MEDIA_SPECIFIC_INDICATION ((WLAN_STATUS) 0x40010012L) + +#define WLAN_STATUS_SCAN_COMPLETE ((WLAN_STATUS) 0x60010001L) +#define WLAN_STATUS_MSDU_OK ((WLAN_STATUS) 0x60010002L) + +/* TODO(Kevin): double check if 0x60010001 & 0x60010002 is proprietary */ +#define WLAN_STATUS_ROAM_OUT_FIND_BEST ((WLAN_STATUS) 0x60010101L) +#define WLAN_STATUS_ROAM_DISCOVERY ((WLAN_STATUS) 0x60010102L) + +#define WLAN_STATUS_FAILURE ((WLAN_STATUS) 0xC0000001L) +#define WLAN_STATUS_RESOURCES ((WLAN_STATUS) 0xC000009AL) +#define WLAN_STATUS_NOT_SUPPORTED ((WLAN_STATUS) 0xC00000BBL) + +#define WLAN_STATUS_MULTICAST_FULL ((WLAN_STATUS) 0xC0010009L) +#define WLAN_STATUS_INVALID_PACKET ((WLAN_STATUS) 0xC001000FL) +#define WLAN_STATUS_ADAPTER_NOT_READY ((WLAN_STATUS) 0xC0010011L) +#define WLAN_STATUS_NOT_INDICATING ((WLAN_STATUS) 0xC0010013L) +#define WLAN_STATUS_INVALID_LENGTH ((WLAN_STATUS) 0xC0010014L) +#define WLAN_STATUS_INVALID_DATA ((WLAN_STATUS) 0xC0010015L) +#define WLAN_STATUS_BUFFER_TOO_SHORT ((WLAN_STATUS) 0xC0010016L) +#define WLAN_STATUS_BWCS_UPDATE ((WLAN_STATUS) 0xC0010017L) + +#define WLAN_STATUS_JOIN_FAILURE ((WLAN_STATUS) 0xC0010018L) + +/* NIC status flags */ +#define ADAPTER_FLAG_HW_ERR 0x00400000 + +/* Type Length */ +#define TL_IPV4 0x0008 +#define TL_IPV6 0xDD86 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Type definition for GLUE_INFO structure */ +typedef struct _GLUE_INFO_T GLUE_INFO_T, *P_GLUE_INFO_T; + +/* Type definition for WLAN STATUS */ +typedef UINT_32 WLAN_STATUS, *P_WLAN_STATUS; + +/* Type definition for ADAPTER structure */ +typedef struct _ADAPTER_T ADAPTER_T, *P_ADAPTER_T; + +/* Type definition for MESSAGE HEADER structure */ +typedef struct _MSG_HDR_T MSG_HDR_T, *P_MSG_HDR_T; + +/* Type definition for WLAN configuration */ +typedef struct _WLAN_CFG_T WLAN_CFG_T, *P_WLAN_CFG_T; + +/* Type definition for WLAN configuration entry */ +typedef struct _WLAN_CFG_ENTRY_T WLAN_CFG_ENTRY_T, *P_WLAN_CFG_ENTRY_T; + +/* Type definition for WLAN configuration callback */ +typedef WLAN_STATUS(*WLAN_CFG_SET_CB) (P_ADAPTER_T prAdapter, + PUINT_8 pucKey, PUINT_8 pucValue, PVOID pPrivate, UINT_32 u4Flags); + +/* Type definition for Pointer to OS Native Packet */ +typedef void *P_NATIVE_PACKET; + +/* Type definition for STA_RECORD_T structure to handle the connectivity and packet reception + * for a particular STA. + */ +typedef struct _STA_RECORD_T STA_RECORD_T, *P_STA_RECORD_T, **PP_STA_RECORD_T; + +/* CMD_INFO_T is used by Glue Layer to send a cluster of Command(OID) information to + * the TX Path to reduce the parameters of a function call. + */ +typedef struct _CMD_INFO_T CMD_INFO_T, *P_CMD_INFO_T; + +/* Following typedef should be removed later, because Glue Layer should not + * be aware of following data type. + */ +typedef struct _SW_RFB_T SW_RFB_T, *P_SW_RFB_T, **PP_SW_RFB_T; + +typedef struct _MSDU_INFO_T MSDU_INFO_T, *P_MSDU_INFO_T; + +typedef struct _REG_ENTRY_T REG_ENTRY_T, *P_REG_ENTRY_T; + +/* IST handler definition */ +typedef VOID(*IST_EVENT_FUNCTION) (P_ADAPTER_T); + +/* Type definition for function pointer of timer handler */ +typedef VOID(*PFN_TIMER_CALLBACK) (IN P_GLUE_INFO_T); + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _TYPEDEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/wlan_bow.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/wlan_bow.h new file mode 100644 index 0000000000000..5c1ce79c90801 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/wlan_bow.h @@ -0,0 +1,250 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _WLAN_BOW_H +#define _WLAN_BOW_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "nic/bow.h" +#include "nic/cmd_buf.h" + +#if CFG_ENABLE_BT_OVER_WIFI + +#if CFG_BOW_TEST +extern UINT_32 g_arBowRevPalPacketTime[32]; +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define BOWCMD_STATUS_SUCCESS 0 +#define BOWCMD_STATUS_FAILURE 1 +#define BOWCMD_STATUS_UNACCEPTED 2 +#define BOWCMD_STATUS_INVALID 3 +#define BOWCMD_STATUS_TIMEOUT 4 + +#define BOW_WILDCARD_SSID "AMP" +#define BOW_WILDCARD_SSID_LEN 3 +#define BOW_SSID_LEN 21 + + /* 0: query, 1: setup, 2: destroy */ +#define BOW_QUERY_CMD 0 +#define BOW_SETUP_CMD 1 +#define BOW_DESTROY_CMD 2 + +#define BOW_INITIATOR 0 +#define BOW_RESPONDER 1 + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +typedef struct _BOW_TABLE_T { + UINT_8 ucAcquireID; + BOOLEAN fgIsValid; + ENUM_BOW_DEVICE_STATE eState; + UINT_8 aucPeerAddress[6]; + /* UINT_8 ucRole; */ + /* UINT_8 ucChannelNum; */ + UINT_16 u2Reserved; +} BOW_TABLE_T, *P_BOW_TABLE_T; + +typedef WLAN_STATUS(*PFN_BOW_CMD_HANDLE) (P_ADAPTER_T, P_AMPC_COMMAND); + +typedef struct _BOW_CMD_T { + UINT_8 uCmdID; + PFN_BOW_CMD_HANDLE pfCmdHandle; +} BOW_CMD_T, *P_BOW_CMD_T; + +typedef struct _BOW_EVENT_ACTIVITY_REPORT_T { + UINT_8 ucReason; + UINT_8 aucReserved; + UINT_8 aucPeerAddress[6]; +} BOW_EVENT_ACTIVITY_REPORT_T, *P_BOW_EVENT_ACTIVITY_REPORT_T; + +/* + * ucReason: 0: success + * 1: general failure + * 2: too much time (> 2/3 second totally) requested for scheduling. + * Others: reserved. + */ + +typedef struct _BOW_EVENT_SYNC_TSF_T { + UINT_64 u4TsfTime; + UINT_32 u4TsfSysTime; + UINT_32 u4ScoTime; + UINT_32 u4ScoSysTime; +} BOW_EVENT_SYNC_TSF_T, *P_BOW_EVENT_SYNC_TSF_T; + +typedef struct _BOW_ACTIVITY_REPORT_BODY_T { + UINT_32 u4StartTime; + UINT_32 u4Duration; + UINT_32 u4Periodicity; +} BOW_ACTIVITY_REPORT_BODY_T, *P_BOW_ACTIVITY_REPORT_BODY_T; + +typedef struct _BOW_ACTIVITY_REPORT_T { + UINT_8 aucPeerAddress[6]; + UINT_8 ucScheduleKnown; + UINT_8 ucNumReports; + BOW_ACTIVITY_REPORT_BODY_T arBowActivityReportBody[MAX_ACTIVITY_REPORT]; +} BOW_ACTIVITY_REPORT_T, *P_BOW_ACTIVITY_REPORT_T; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*--------------------------------------------------------------*/ +/* Firmware Command Packer */ +/*--------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendSetQueryBowCmd(IN P_ADAPTER_T prAdapter, + UINT_8 ucCID, + BOOLEAN fgSetQuery, + BOOLEAN fgNeedResp, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + UINT_32 u4SetQueryInfoLen, PUINT_8 pucInfoBuffer, IN UINT_8 ucSeqNumber); + +/*--------------------------------------------------------------*/ +/* Command Dispatcher */ +/*--------------------------------------------------------------*/ +WLAN_STATUS wlanbowHandleCommand(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); + +/*--------------------------------------------------------------*/ +/* Routines to handle command */ +/*--------------------------------------------------------------*/ +WLAN_STATUS bowCmdGetMacStatus(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); + +WLAN_STATUS bowCmdSetupConnection(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); + +WLAN_STATUS bowCmdDestroyConnection(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); + +WLAN_STATUS bowCmdSetPTK(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); + +WLAN_STATUS bowCmdReadRSSI(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); + +WLAN_STATUS bowCmdReadLinkQuality(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); + +WLAN_STATUS bowCmdShortRangeMode(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); + +WLAN_STATUS bowCmdGetChannelList(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); + +VOID wlanbowCmdEventSetStatus(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd, IN UINT_8 ucEventBuf); + +/*--------------------------------------------------------------*/ +/* Callbacks for event indication */ +/*--------------------------------------------------------------*/ +VOID wlanbowCmdEventSetCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID wlanbowCmdEventLinkConnected(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID wlanbowCmdEventLinkDisconnected(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID wlanbowCmdEventSetSetupConnection(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID wlanbowCmdEventReadLinkQuality(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID wlanbowCmdEventReadRssi(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID wlanbowCmdTimeoutHandler(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +VOID bowStopping(IN P_ADAPTER_T prAdapter); + +VOID bowStarting(IN P_ADAPTER_T prAdapter); + +VOID bowAssignSsid(IN PUINT_8 pucSsid, IN PUINT_8 pucSsidLen); + +BOOLEAN bowValidateProbeReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_32 pu4ControlFlags); + +VOID bowSendBeacon(IN P_ADAPTER_T prAdapter, ULONG ulParam); + +VOID bowResponderScan(IN P_ADAPTER_T prAdapter); + +VOID bowResponderScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID bowResponderCancelScan(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsChannelExtention); + +VOID bowResponderJoin(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc); + +VOID bowFsmRunEventJoinComplete(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID +bowIndicationOfMediaStateToHost(IN P_ADAPTER_T prAdapter, + ENUM_PARAM_MEDIA_STATE_T eConnectionState, BOOLEAN fgDelayIndication); + +VOID bowRunEventAAATxFail(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +WLAN_STATUS bowRunEventAAAComplete(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +WLAN_STATUS bowRunEventRxDeAuth(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb); + +VOID bowDisconnectLink(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +BOOLEAN bowValidateAssocReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu2StatusCode); + +BOOLEAN +bowValidateAuth(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, IN PP_STA_RECORD_T pprStaRec, OUT PUINT_16 pu2StatusCode); + +VOID bowRunEventChGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID bowRequestCh(IN P_ADAPTER_T prAdapter); + +VOID bowReleaseCh(IN P_ADAPTER_T prAdapter); + +VOID bowChGrantedTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParam); + +BOOLEAN bowNotifyAllLinkDisconnected(IN P_ADAPTER_T prAdapter); + +BOOLEAN bowCheckBowTableIfVaild(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6]); + +BOOLEAN bowGetBowTableContent(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBowTableIdx, OUT P_BOW_TABLE_T prBowTable); + +BOOLEAN +bowGetBowTableEntryByPeerAddress(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6], OUT PUINT_8 pucBowTableIdx); + +BOOLEAN bowGetBowTableFreeEntry(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucBowTableIdx); + +ENUM_BOW_DEVICE_STATE bowGetBowTableState(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6]); + +BOOLEAN bowSetBowTableState(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6], IN ENUM_BOW_DEVICE_STATE eState); + +BOOLEAN bowSetBowTableContent(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBowTableIdx, IN P_BOW_TABLE_T prBowTable); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif +#endif /* _WLAN_BOW_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/wlan_lib.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/wlan_lib.h new file mode 100644 index 0000000000000..11cb9bf10cb8a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/wlan_lib.h @@ -0,0 +1,697 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _WLAN_LIB_H +#define _WLAN_LIB_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "CFG_Wifi_File.h" +#include "rlm_domain.h" +#include "wlan_typedef.h" + + +extern BOOLEAN fgIsResetting; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define MAX_NUM_GROUP_ADDR 32 /* max number of group addresses */ + +#define TX_CS_TCP_UDP_GEN BIT(1) +#define TX_CS_IP_GEN BIT(0) + +#define CSUM_OFFLOAD_EN_TX_TCP BIT(0) +#define CSUM_OFFLOAD_EN_TX_UDP BIT(1) +#define CSUM_OFFLOAD_EN_TX_IP BIT(2) +#define CSUM_OFFLOAD_EN_RX_TCP BIT(3) +#define CSUM_OFFLOAD_EN_RX_UDP BIT(4) +#define CSUM_OFFLOAD_EN_RX_IPv4 BIT(5) +#define CSUM_OFFLOAD_EN_RX_IPv6 BIT(6) +#define CSUM_OFFLOAD_EN_TX_MASK BITS(0, 2) +#define CSUM_OFFLOAD_EN_ALL BITS(0, 6) + +/* TCP, UDP, IP Checksum */ +#define RX_CS_TYPE_UDP BIT(7) +#define RX_CS_TYPE_TCP BIT(6) +#define RX_CS_TYPE_IPv6 BIT(5) +#define RX_CS_TYPE_IPv4 BIT(4) + +#define RX_CS_STATUS_UDP BIT(3) +#define RX_CS_STATUS_TCP BIT(2) +#define RX_CS_STATUS_IP BIT(0) + +#define CSUM_NOT_SUPPORTED 0x0 + +#define TXPWR_USE_PDSLOPE 0 + +/* NVRAM error code definitions */ +#define NVRAM_ERROR_VERSION_MISMATCH BIT(1) +#define NVRAM_ERROR_INVALID_TXPWR BIT(2) +#define NVRAM_ERROR_INVALID_DPD BIT(3) +#define NVRAM_ERROR_INVALID_MAC_ADDR BIT(4) +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY +#define NVRAM_POWER_LIMIT_TABLE_INVALID BIT(5) +#endif + +#define NUM_TC_RESOURCE_TO_STATISTICS 4 +#if CFG_SUPPORT_NCHO +#define WLAN_CFG_ARGV_MAX 64 +#else +#define WLAN_CFG_ARGV_MAX 8 +#endif +#define WLAN_CFG_ENTRY_NUM_MAX 128 +#define WLAN_CFG_KEY_LEN_MAX 32 /* include \x00 EOL */ +#define WLAN_CFG_VALUE_LEN_MAX 32 /* include \x00 EOL */ +#define WLAN_CFG_FLAG_SKIP_CB BIT(0) +#define WLAN_CFG_FILE_BUF_SIZE 2048 + +#define WLAN_CFG_SET_CHIP_LEN_MAX 10 +#define WLAN_CFG_SET_DEBUG_LEVEL_LEN_MAX 10 +#define WLAN_CFG_SET_SW_CTRL_LEN_MAX 10 + +#define WLAN_OID_TIMEOUT_THRESHOLD 2000 /* OID timeout (in ms) */ +#define WLAN_OID_TIMEOUT_THRESHOLD_IN_RESETTING 300 /* OID timeout during chip-resetting (in ms) */ + +#define WLAN_OID_NO_ACK_THRESHOLD 3 + +#define WLAN_TX_THREAD_TASK_PRIORITY 0 /* If not setting the priority, 0 is the default */ +#define WLAN_TX_THREAD_TASK_NICE (-10) /* If not setting the nice, -10 is the default */ + +#define WLAN_DOWNLOAD_IMAGE_TIMEOUT 2500 /*ms*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef WLAN_STATUS(*PFN_OID_HANDLER_FUNC) (IN P_ADAPTER_T prAdapter, + IN PVOID pvBuf, IN UINT_32 u4BufLen, OUT PUINT_32 pu4OutInfoLen); + +typedef enum _ENUM_CSUM_TYPE_T { + CSUM_TYPE_IPV4, + CSUM_TYPE_IPV6, + CSUM_TYPE_TCP, + CSUM_TYPE_UDP, + CSUM_TYPE_NUM +} ENUM_CSUM_TYPE_T, *P_ENUM_CSUM_TYPE_T; + +typedef enum _ENUM_CSUM_RESULT_T { + CSUM_RES_NONE, + CSUM_RES_SUCCESS, + CSUM_RES_FAILED, + CSUM_RES_NUM +} ENUM_CSUM_RESULT_T, *P_ENUM_CSUM_RESULT_T; + +typedef enum _ENUM_PHY_MODE_T { + ENUM_PHY_2G4_CCK, + ENUM_PHY_2G4_OFDM_BPSK, + ENUM_PHY_2G4_OFDM_QPSK, + ENUM_PHY_2G4_OFDM_16QAM, + ENUM_PHY_2G4_OFDM_48M, + ENUM_PHY_2G4_OFDM_54M, + ENUM_PHY_2G4_HT20_BPSK, + ENUM_PHY_2G4_HT20_QPSK, + ENUM_PHY_2G4_HT20_16QAM, + ENUM_PHY_2G4_HT20_MCS5, + ENUM_PHY_2G4_HT20_MCS6, + ENUM_PHY_2G4_HT20_MCS7, + ENUM_PHY_2G4_HT40_BPSK, + ENUM_PHY_2G4_HT40_QPSK, + ENUM_PHY_2G4_HT40_16QAM, + ENUM_PHY_2G4_HT40_MCS5, + ENUM_PHY_2G4_HT40_MCS6, + ENUM_PHY_2G4_HT40_MCS7, + ENUM_PHY_5G_OFDM_BPSK, + ENUM_PHY_5G_OFDM_QPSK, + ENUM_PHY_5G_OFDM_16QAM, + ENUM_PHY_5G_OFDM_48M, + ENUM_PHY_5G_OFDM_54M, + ENUM_PHY_5G_HT20_BPSK, + ENUM_PHY_5G_HT20_QPSK, + ENUM_PHY_5G_HT20_16QAM, + ENUM_PHY_5G_HT20_MCS5, + ENUM_PHY_5G_HT20_MCS6, + ENUM_PHY_5G_HT20_MCS7, + ENUM_PHY_5G_HT40_BPSK, + ENUM_PHY_5G_HT40_QPSK, + ENUM_PHY_5G_HT40_16QAM, + ENUM_PHY_5G_HT40_MCS5, + ENUM_PHY_5G_HT40_MCS6, + ENUM_PHY_5G_HT40_MCS7, + ENUM_PHY_MODE_NUM +} ENUM_PHY_MODE_T, *P_ENUM_PHY_MODE_T; + +typedef enum _ENUM_POWER_SAVE_POLL_MODE_T { + ENUM_POWER_SAVE_POLL_DISABLE, + ENUM_POWER_SAVE_POLL_LEGACY_NULL, + ENUM_POWER_SAVE_POLL_QOS_NULL, + ENUM_POWER_SAVE_POLL_NUM +} ENUM_POWER_SAVE_POLL_MODE_T, *P_ENUM_POWER_SAVE_POLL_MODE_T; + +typedef enum _ENUM_AC_TYPE_T { + ENUM_AC_TYPE_AC0, + ENUM_AC_TYPE_AC1, + ENUM_AC_TYPE_AC2, + ENUM_AC_TYPE_AC3, + ENUM_AC_TYPE_AC4, + ENUM_AC_TYPE_AC5, + ENUM_AC_TYPE_AC6, + ENUM_AC_TYPE_BMC, + ENUM_AC_TYPE_NUM +} ENUM_AC_TYPE_T, *P_ENUM_AC_TYPE_T; + +typedef enum _ENUM_ADV_AC_TYPE_T { + ENUM_ADV_AC_TYPE_RX_NSW, + ENUM_ADV_AC_TYPE_RX_PTA, + ENUM_ADV_AC_TYPE_RX_SP, + ENUM_ADV_AC_TYPE_TX_PTA, + ENUM_ADV_AC_TYPE_TX_RSP, + ENUM_ADV_AC_TYPE_NUM +} ENUM_ADV_AC_TYPE_T, *P_ENUM_ADV_AC_TYPE_T; + +typedef enum _ENUM_REG_CH_MAP_T { + REG_CH_MAP_COUNTRY_CODE, + REG_CH_MAP_TBL_IDX, + REG_CH_MAP_CUSTOMIZED, + REG_CH_MAP_NUM +} ENUM_REG_CH_MAP_T, *P_ENUM_REG_CH_MAP_T; + +#define CHIP_CONFIG_RESP_SIZE 320 +enum { + CHIP_CONFIG_TYPE_WO_RESPONSE = 0x00, + CHIP_CONFIG_TYPE_MEM8 = 0x01, + CHIP_CONFIG_TYPE_MEM32 = 0x02, + CHIP_CONFIG_TYPE_ASCII = 0x03, + CHIP_CONFIG_TYPE_BINARY = 0x04, + CHIP_CONFIG_TYPE_DRV_PASSTHROUGH = 0x05, + CHIP_CONFIG_TYPE_END +}; + +typedef struct _SET_TXPWR_CTRL_T { + INT_8 c2GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0 */ + INT_8 c2GHotspotPwrOffset; + INT_8 c2GP2pPwrOffset; + INT_8 c2GBowPwrOffset; + INT_8 c5GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0 */ + INT_8 c5GHotspotPwrOffset; + INT_8 c5GP2pPwrOffset; + INT_8 c5GBowPwrOffset; + UINT_8 ucConcurrencePolicy; /* + * TX power policy when concurrence + * in the same channel + * 0: Highest power has priority + * 1: Lowest power has priority + */ + INT_8 acReserved1[3]; /* Must be zero */ + + /* Power limit by channel for all data rates */ + INT_8 acTxPwrLimit2G[14]; /* Channel 1~14, Unit: 0.5dBm */ + INT_8 acTxPwrLimit5G[4]; /* UNII 1~4 */ + INT_8 acReserved2[2]; /* Must be zero */ +#if CFG_SUPPORT_TX_POWER_BACK_OFF + MITIGATED_PWR_BY_CH_BY_MODE arRlmMitigatedPwrByChByMode[40]; +#endif +} SET_TXPWR_CTRL_T, *P_SET_TXPWR_CTRL_T; + +/* For storing driver initialization value from glue layer */ +typedef struct _REG_INFO_T { + UINT_32 u4SdBlockSize; /* SDIO block size */ + UINT_32 u4SdBusWidth; /* SDIO bus width. 1 or 4 */ + UINT_32 u4SdClockRate; /* SDIO clock rate. (in unit of HZ) */ + UINT_32 u4StartAddress; /* Starting address of Wi-Fi Firmware */ + UINT_32 u4LoadAddress; /* Load address of Wi-Fi Firmware */ + UINT_16 aucFwImgFilename[65]; /* Firmware filename */ + UINT_16 aucFwImgFilenameE6[65]; /* Firmware filename for E6 */ + UINT_32 u4StartFreq; /* Start Frequency for Ad-Hoc network : in unit of KHz */ + UINT_32 u4AdhocMode; /* Default mode for Ad-Hoc network : ENUM_PARAM_AD_HOC_MODE_T */ + UINT_32 u4RddStartFreq; + UINT_32 u4RddStopFreq; + UINT_32 u4RddTestMode; + UINT_32 u4RddShutFreq; + UINT_32 u4RddDfs; + INT_32 i4HighRssiThreshold; + INT_32 i4MediumRssiThreshold; + INT_32 i4LowRssiThreshold; + INT_32 au4TxPriorityTag[ENUM_AC_TYPE_NUM]; + INT_32 au4RxPriorityTag[ENUM_AC_TYPE_NUM]; + INT_32 au4AdvPriorityTag[ENUM_ADV_AC_TYPE_NUM]; + UINT_32 u4FastPSPoll; + UINT_32 u4PTA; /* 0: disable, 1: enable */ + UINT_32 u4TXLimit; /* 0: disable, 1: enable */ + UINT_32 u4SilenceWindow; /* range: 100 - 625, unit: us */ + UINT_32 u4TXLimitThreshold; /* range: 250 - 1250, unit: us */ + UINT_32 u4PowerMode; + UINT_32 fgEnArpFilter; + UINT_32 u4PsCurrentMeasureEn; + UINT_32 u4UapsdAcBmp; + UINT_32 u4MaxSpLen; + UINT_32 fgDisOnlineScan; /* 0: enable online scan, non-zero: disable online scan */ + UINT_32 fgDisBcnLostDetection; /* 0: enable online scan, non-zero: disable online scan */ + UINT_32 u4FixedRate; /* 0: automatic, non-zero: fixed rate */ + UINT_32 u4ArSysParam0; + UINT_32 u4ArSysParam1; + UINT_32 u4ArSysParam2; + UINT_32 u4ArSysParam3; + UINT_32 fgDisRoaming; /* 0:enable roaming 1:disable */ + + /* NVRAM - MP Data -START- */ + UINT_8 aucMacAddr[6]; + UINT_16 au2CountryCode[4]; /* Country code (in ISO 3166-1 expression, ex: "US", "TW") */ + TX_PWR_PARAM_T rTxPwr; + UINT_8 aucEFUSE[144]; + UINT_8 ucTxPwrValid; + UINT_8 ucSupport5GBand; + UINT_8 fg2G4BandEdgePwrUsed; + INT_8 cBandEdgeMaxPwrCCK; + INT_8 cBandEdgeMaxPwrOFDM20; + INT_8 cBandEdgeMaxPwrOFDM40; + ENUM_REG_CH_MAP_T eRegChannelListMap; + UINT_8 ucRegChannelListIndex; + DOMAIN_INFO_ENTRY rDomainInfo; + /* NVRAM - MP Data -END- */ + + /* NVRAM - Functional Data -START- */ + UINT_8 uc2G4BwFixed20M; + UINT_8 uc5GBwFixed20M; + UINT_8 ucEnable5GBand; + UINT_8 uc2GRssiCompensation; + UINT_8 uc5GRssiCompensation; + UINT_8 fgRssiCompensationValidbit; + UINT_8 ucRxAntennanumber; +#if CFG_SUPPORT_TX_POWER_BACK_OFF + MITIGATED_PWR_BY_CH_BY_MODE arRlmMitigatedPwrByChByMode[40]; + UINT_8 fgRlmMitigatedPwrByChByMode; + BOOLEAN bTxPowerLimitEnable2G; + BOOLEAN bTxPowerLimitEnable5G; + UINT8 cTxBackOffMaxPower2G; + UINT8 cTxBackOffMaxPower5G; +#endif +#if CFG_SUPPORT_FCC_POWER_BACK_OFF + FCC_TX_PWR_ADJUST rFccTxPwrAdjust; + UINT_8 aucChannelBandEdge[2]; +#endif + /* NVRAM - Functional Data -END- */ + +} REG_INFO_T, *P_REG_INFO_T; + +/* for divided firmware loading */ +typedef struct _FWDL_SECTION_INFO_T { + UINT_32 u4Offset; + UINT_32 u4Reserved; + UINT_32 u4Length; + UINT_32 u4DestAddr; +} FWDL_SECTION_INFO_T, *P_FWDL_SECTION_INFO_T; + +typedef struct _FIRMWARE_DIVIDED_DOWNLOAD_T { + UINT_32 u4Signature; + UINT_32 u4CRC; /* CRC calculated without first 8 bytes included */ + UINT_32 u4NumOfEntries; + UINT_32 u4Reserved; + FWDL_SECTION_INFO_T arSection[]; +} FIRMWARE_DIVIDED_DOWNLOAD_T, *P_FIRMWARE_DIVIDED_DOWNLOAD_T; + +typedef struct _PARAM_MCR_RW_STRUCT_T { + UINT_32 u4McrOffset; + UINT_32 u4McrData; +} PARAM_MCR_RW_STRUCT_T, *P_PARAM_MCR_RW_STRUCT_T; + +typedef struct _PARAM_GET_STA_STATISTICS { + UINT_8 ucInvalid; + UINT_8 ucVersion; + /* Per-STA statistic */ + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + UINT_32 u4LinkScore; + UINT_32 u4Flag; + + /* From FW */ + UINT_8 ucPer; /* base: 128 */ + UINT_8 ucRcpi; + UINT_32 u4PhyMode; + UINT_16 u2LinkSpeed; /* unit is 0.5 Mbits */ + + UINT_32 u4TxFailCount; + UINT_32 u4TxLifeTimeoutCount; + UINT_32 u4TxAverageAirTime; + + /* From driver */ + UINT_32 u4TxTotalCount; + UINT_32 u4TxExceedThresholdCount; + UINT_32 u4TxAverageProcessTime; + + UINT_32 u4TxMaxTime; + UINT_32 u4TxMaxHifTime; + UINT_32 u4TxAverageHifTime; + + /* + * How many packages Enqueue/Deqeue during statistics interval + */ + UINT_32 u4EnqueueCounter; + UINT_32 u4DequeueCounter; + + UINT_32 u4EnqueueStaCounter; + UINT_32 u4DequeueStaCounter; + + UINT_32 IsrCnt; + UINT_32 IsrPassCnt; + UINT_32 TaskIsrCnt; + + UINT_32 IsrAbnormalCnt; + UINT_32 IsrSoftWareCnt; + UINT_32 IsrRxCnt; + UINT_32 IsrTxCnt; + + UINT_32 au4TcResourceEmptyCount[NUM_TC_RESOURCE_TO_STATISTICS]; + UINT_32 au4DequeueNoTcResource[NUM_TC_RESOURCE_TO_STATISTICS]; + UINT_32 au4TcResourceBackCount[NUM_TC_RESOURCE_TO_STATISTICS]; + + UINT_32 au4TcResourceUsedCount[NUM_TC_RESOURCE_TO_STATISTICS]; + UINT_32 au4TcResourceWantedCount[NUM_TC_RESOURCE_TO_STATISTICS]; + + UINT_32 au4TcQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + /* Global queue management statistic */ + UINT_32 au4TcAverageQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + UINT_32 au4TcCurrentQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + + /* Reserved fields */ + UINT_8 au4Reserved[32]; +} PARAM_GET_STA_STA_STATISTICS, *P_PARAM_GET_STA_STATISTICS; + +typedef enum _ENUM_BAND_EDGE_CERT_T { + BAND_EDGE_CERT_FCC = 0, + BAND_EDGE_CERT_KCC = 1, + BAND_EDGE_CERT_NUM = 2 +} ENUM_BAND_EDGE_CERT_T, *P_ENUM_BAND_EDGE_CERT_T; + +enum ENUM_MAX_BANDWIDTH_SETTING { + MAX_BW_20MHZ = 0, + MAX_BW_40MHZ, + MAX_BW_80MHZ, + MAX_BW_160MHZ, + MAX_BW_80_80_MHZ, + MAX_BW_UNKNOWN +}; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define BUILD_SIGN(ch0, ch1, ch2, ch3) \ + ((UINT_32)(UINT_8)(ch0) | ((UINT_32)(UINT_8)(ch1) << 8) | \ + ((UINT_32)(UINT_8)(ch2) << 16) | ((UINT_32)(UINT_8)(ch3) << 24)) + +#define MTK_WIFI_SIGNATURE BUILD_SIGN('M', 'T', 'K', 'W') + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +P_ADAPTER_T wlanAdapterCreate(IN P_GLUE_INFO_T prGlueInfo); + +VOID wlanAdapterDestroy(IN P_ADAPTER_T prAdapter); + +VOID wlanCardEjected(IN P_ADAPTER_T prAdapter); + +VOID wlanIST(IN P_ADAPTER_T prAdapter); + +BOOLEAN wlanISR(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgGlobalIntrCtrl); + +WLAN_STATUS wlanProcessCommandQueue(IN P_ADAPTER_T prAdapter, IN P_QUE_T prCmdQue); + +WLAN_STATUS wlanSendCommand(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +VOID wlanReleaseCommand(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +VOID wlanReleasePendingOid(IN P_ADAPTER_T prAdapter, IN ULONG ulData); + +VOID wlanReleasePendingCMDbyNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType); + +VOID wlanReturnPacket(IN P_ADAPTER_T prAdapter, IN PVOID pvPacket); + +VOID wlanReturnIndicatedPacketsTimeOut(IN P_ADAPTER_T prAdapter, IN ULONG ulData); + +WLAN_STATUS +wlanQueryInformation(IN P_ADAPTER_T prAdapter, + IN PFN_OID_HANDLER_FUNC pfOidQryHandler, + IN PVOID pvInfoBuf, IN UINT_32 u4InfoBufLen, OUT PUINT_32 pu4QryInfoLen); + +WLAN_STATUS +wlanSetInformation(IN P_ADAPTER_T prAdapter, + IN PFN_OID_HANDLER_FUNC pfOidSetHandler, + IN PVOID pvInfoBuf, IN UINT_32 u4InfoBufLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanAdapterStart(IN P_ADAPTER_T prAdapter, + IN P_REG_INFO_T prRegInfo, IN PVOID pvFwImageMapFile, IN UINT_32 u4FwImageFileLength); + +WLAN_STATUS wlanAdapterStop(IN P_ADAPTER_T prAdapter); + +#if CFG_SUPPORT_WAPI +BOOLEAN wlanQueryWapiMode(IN P_ADAPTER_T prAdapter); +#endif + +VOID wlanReturnRxPacket(IN PVOID pvAdapter, IN PVOID pvPacket); + +VOID wlanRxSetBroadcast(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnableBroadcast); + +BOOLEAN wlanIsHandlerNeedHwAccess(IN PFN_OID_HANDLER_FUNC pfnOidHandler, IN BOOLEAN fgSetInfo); + +VOID wlanSetPromiscuousMode(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnablePromiscuousMode); + +#if CFG_ENABLE_FW_DOWNLOAD +#if CFG_ENABLE_FW_DOWNLOAD_AGGREGATION +WLAN_STATUS +wlanImageSectionDownloadAggregated(IN P_ADAPTER_T prAdapter, + IN UINT_32 u4DestAddr, IN UINT_32 u4ImgSecSize, IN PUINT_8 pucImgSecBuf); +#endif + +WLAN_STATUS +wlanImageSectionDownload(IN P_ADAPTER_T prAdapter, + IN UINT_32 u4DestAddr, IN UINT_32 u4ImgSecSize, IN PUINT_8 pucImgSecBuf); + +#if !CFG_ENABLE_FW_DOWNLOAD_ACK +WLAN_STATUS wlanImageQueryStatus(IN P_ADAPTER_T prAdapter); +#else +WLAN_STATUS wlanImageSectionDownloadStatus(IN P_ADAPTER_T prAdapter, IN UINT_8 ucCmdSeqNum); +#endif + +WLAN_STATUS wlanConfigWifiFunc(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnable, IN UINT_32 u4StartAddress); + +UINT_32 wlanCRC32(PUINT_8 buf, UINT_32 len); + +#endif + +WLAN_STATUS wlanSendNicPowerCtrlCmd(IN P_ADAPTER_T prAdapter, IN UINT_8 ucPowerMode); + +BOOLEAN wlanIsHandlerAllowedInRFTest(IN PFN_OID_HANDLER_FUNC pfnOidHandler, IN BOOLEAN fgSetInfo); + +WLAN_STATUS wlanProcessQueuedSwRfb(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfbListHead); + +WLAN_STATUS wlanProcessQueuedMsduInfo(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead); + +BOOLEAN wlanoidTimeoutCheck(IN P_ADAPTER_T prAdapter, IN PFN_OID_HANDLER_FUNC pfnOidHandler); + +VOID wlanoidClearTimeoutCheck(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS wlanUpdateNetworkAddress(IN P_ADAPTER_T prAdapter); + +BOOLEAN wlanQueryTestMode(IN P_ADAPTER_T prAdapter); + +/* Security Frame Handling */ +BOOLEAN wlanProcessSecurityFrame(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prPacket); + +VOID wlanSecurityFrameTxDone(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID wlanSecurityFrameTxTimeout(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +/*----------------------------------------------------------------------------*/ +/* OID/IOCTL Handling */ +/*----------------------------------------------------------------------------*/ +VOID wlanClearScanningResult(IN P_ADAPTER_T prAdapter); + +VOID wlanClearBssInScanningResult(IN P_ADAPTER_T prAdapter, IN PUINT_8 arBSSID); + +#if CFG_TEST_WIFI_DIRECT_GO +VOID wlanEnableP2pFunction(IN P_ADAPTER_T prAdapter); + +VOID wlanEnableATGO(IN P_ADAPTER_T prAdapter); +#endif + +/*----------------------------------------------------------------------------*/ +/* Address Retrieve by Polling */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanQueryPermanentAddress(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* NIC Capability Retrieve by Polling */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanQueryNicCapability(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* NIC Capability Retrieve by Polling */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanQueryDebugCode(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* Compiler Flags Retrieve by Polling */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanQueryCompileFlags(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* PD MCR Retrieve by Polling */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanQueryPdMcr(IN P_ADAPTER_T prAdapter, IN P_PARAM_MCR_RW_STRUCT_T prMcrRdInfo); +/*----------------------------------------------------------------------------*/ +/* Loading Manufacture Data */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanLoadManufactureData(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo); + +/*----------------------------------------------------------------------------*/ +/* Media Stream Mode */ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanResetMediaStreamMode(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* Timer Timeout Check (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanTimerTimeoutCheck(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Check (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanProcessMboxMessage(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* TX Pending Packets Handling (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanEnqueueTxPacket(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prNativePacket); + +WLAN_STATUS wlanFlushTxPendingPackets(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS wlanTxPendingPackets(IN P_ADAPTER_T prAdapter, IN OUT PBOOLEAN pfgHwAccess); + +/*----------------------------------------------------------------------------*/ +/* Low Power Acquire/Release (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanAcquirePowerControl(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS wlanReleasePowerControl(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* Pending Packets Number Reporting (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +UINT_32 wlanGetTxPendingFrameCount(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* ACPI state inquiry (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +ENUM_ACPI_STATE_T wlanGetAcpiState(IN P_ADAPTER_T prAdapter); + +VOID wlanSetAcpiState(IN P_ADAPTER_T prAdapter, IN ENUM_ACPI_STATE_T ePowerState); + +VOID wlanDefTxPowerCfg(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* get ECO version from Revision ID register (for Win32) */ +/*----------------------------------------------------------------------------*/ +UINT_8 wlanGetEcoVersion(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* set preferred band configuration corresponding to network type */ +/*----------------------------------------------------------------------------*/ +VOID +wlanSetPreferBandByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_BAND_T eBand, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); + +/*----------------------------------------------------------------------------*/ +/* get currently operating channel information */ +/*----------------------------------------------------------------------------*/ +UINT_8 wlanGetChannelNumberByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); + +/*----------------------------------------------------------------------------*/ +/* get BSS Descriptor information */ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T wlanGetTargetBssDescByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); + +#if CFG_SUPPORT_ADD_CONN_AP +/*----------------------------------------------------------------------------*/ +/* check for system configuration to generate message on scan list */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanCheckConnectedAP(IN P_ADAPTER_T prAdapter); +#endif + +/*----------------------------------------------------------------------------*/ +/* check for system configuration to generate message on scan list */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanCheckSystemConfiguration(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* query sta statistics information from driver and firmware */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryStaStatistics(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS wlanCfgParseArgument(CHAR *cmdLine, INT_32 *argc, CHAR *argv[]); + +P_WLAN_CFG_ENTRY_T wlanCfgGetEntry(IN P_ADAPTER_T prAdapter, const PCHAR pucKey); + +WLAN_STATUS +wlanCfgGet(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, PCHAR pucValue, PCHAR pucValueDef, UINT_32 u4Flags); + +UINT_32 wlanCfgGetUint32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, UINT_32 u4ValueDef); + +INT_32 wlanCfgGetInt32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, INT_32 i4ValueDef); + +WLAN_STATUS wlanCfgSetUint32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, UINT_32 u4Value); + +WLAN_STATUS wlanCfgSet(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, PCHAR pucValue, UINT_32 u4Flags); + +WLAN_STATUS +wlanCfgSetCb(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, WLAN_CFG_SET_CB pfSetCb, void *pPrivate, UINT_32 u4Flags); + +#if CFG_SUPPORT_CFG_FILE +WLAN_STATUS wlanCfgInit(IN P_ADAPTER_T prAdapter, PUINT_8 pucConfigBuf, UINT_32 u4ConfigBufLen, UINT_32 u4Flags); + +VOID wlanCfgApply(IN P_ADAPTER_T prAdapter); +#endif /* CFG_SUPPORT_CFG_FILE */ + +extern VOID mtk_wcn_wmt_set_wifi_ver(UINT_32 Value); +VOID wlanReleasePendingCmdById(P_ADAPTER_T prAdapter, UINT_8 ucCid); + +UINT_32 wlanDecimalStr2Hexadecimals(PUINT_8 pucDecimalStr, PUINT_16 pu2Out); + +WLAN_STATUS wlanQueryLteSafeChannel(IN P_ADAPTER_T prAdapter); + +uint8_t +wlanGetChannelIndex(IN uint8_t channel); + +#endif /* _WLAN_LIB_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/wlan_oid.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/wlan_oid.h new file mode 100644 index 0000000000000..dcd5adb45faf0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/wlan_oid.h @@ -0,0 +1,2034 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _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 0xF0000000 +#define PARAM_PACKET_FILTER_PROBE_REQ 0x80000000 +#define PARAM_PACKET_FILTER_ACTION_FRAME 0x40000000 +#define PARAM_PACKET_FILTER_AUTH 0x20000000 +#define PARAM_PACKET_FILTER_ASSOC_REQ 0x10000000 +#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 + +#if CFG_SUPPORT_GAMING_MODE +#define GAMING_MODE_MAGIC_CODE 0x86 +#define GAMING_MODE_CMD_V1 0x1 + +#define GED_EVENT_GAS (1 << 4) +#define GED_EVENT_NETWORK (1 << 11) +#define GED_EVENT_DOPT_WIFI_SCAN (1 << 12) +#endif /* CFG_SUPPORT_GAMING_MODE */ + +/******************************************************************************* +* 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_NON_RSN_FT, /* Fast Bss Transition in a Non FT */ + 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_WPA2_FT, /* Fast Bss Transition for 802.1x */ + AUTH_MODE_WPA2_FT_PSK, /* Fast Bss Transition for WPA2 PSK */ + AUTH_MODE_WPA_OSEN, + AUTH_MODE_WPA3_SAE, + AUTH_MODE_WPA3_OWE, + 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; + +struct PARAM_EXTERNAL_AUTH { + uint8_t bssid[PARAM_MAC_ADDR_LEN]; + uint16_t status; + uint8_t ucBssIdx; +}; + +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]; +#if !defined(CFG_MULTI_SSID_SCAN) + UINT_32 u4CenterFreq; +#endif +} PARAM_SSID_T, *P_PARAM_SSID_T; + +typedef struct _PARAM_CONNECT_T { + UINT_32 u4SsidLen; /*!< SSID length in bytes. Zero length is broadcast(any) SSID */ + UINT_8 *pucSsid; + UINT_8 *pucBssid; + UINT_32 u4CenterFreq; +} PARAM_CONNECT_T, *P_PARAM_CONNECT_T; + +/* This is enum defined for user to select an AdHoc Mode */ +typedef enum _ENUM_PARAM_AD_HOC_MODE_T { + AD_HOC_MODE_11B = 0, /*!< Create 11b IBSS if we support 802.11abg/802.11bg. */ + AD_HOC_MODE_MIXED_11BG, /*!< Create 11bg mixed IBSS if we support 802.11abg/802.11bg/802.11g. */ + AD_HOC_MODE_11G, /*!< Create 11g only IBSS if we support 802.11abg/802.11bg/802.11g. */ + AD_HOC_MODE_11A, /*!< Create 11a only IBSS if we support 802.11abg. */ + AD_HOC_MODE_NUM /* 4 */ +} ENUM_PARAM_AD_HOC_MODE_T, *P_ENUM_PARAM_AD_HOC_MODE_T; + +typedef enum _ENUM_PARAM_MEDIA_STATE_T { + PARAM_MEDIA_STATE_CONNECTED, + PARAM_MEDIA_STATE_DISCONNECTED, + PARAM_MEDIA_STATE_DISCONNECT_PREV, + 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_FT_AUTH_STATUS, + 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; +#if (CFG_REFACTORY_PMKSA == 0) +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; +#endif +/*! \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_16 u2CapInfo; + 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 ucCipher; + UINT_8 aucKeyMaterial[32]; /*!< Key content by above setting */ +} PARAM_KEY_T, *P_PARAM_KEY_T; + +typedef struct _PARAM_REMOVE_KEY_T { + UINT_32 u4Length; /*!< Length of structure */ + UINT_32 u4KeyIndex; /*!< KeyID */ + PARAM_MAC_ADDRESS arBSSID; /*!< MAC address */ +} PARAM_REMOVE_KEY_T, *P_PARAM_REMOVE_KEY_T; + +#if CFG_SUPPORT_WAPI +typedef enum _ENUM_KEY_TYPE { + ENUM_WPI_PAIRWISE_KEY = 0, + ENUM_WPI_GROUP_KEY +} ENUM_KEY_TYPE; + +typedef enum _ENUM_WPI_PROTECT_TYPE { + ENUM_WPI_NONE, + ENUM_WPI_RX, + ENUM_WPI_TX, + ENUM_WPI_RX_TX +} ENUM_WPI_PROTECT_TYPE; + +typedef struct _PARAM_WPI_KEY_T { + ENUM_KEY_TYPE eKeyType; + ENUM_WPI_PROTECT_TYPE eDirection; + UINT_8 ucKeyID; + UINT_8 aucRsv[3]; + UINT_8 aucAddrIndex[12]; + UINT_32 u4LenWPIEK; + UINT_8 aucWPIEK[256]; + UINT_32 u4LenWPICK; + UINT_8 aucWPICK[256]; + UINT_8 aucPN[16]; +} PARAM_WPI_KEY_T, *P_PARAM_WPI_KEY_T; +#endif + +typedef enum _PARAM_POWER_MODE { + Param_PowerModeCAM, + Param_PowerModeMAX_PSP, + Param_PowerModeFast_PSP, +#if CFG_SUPPORT_DBG_POWERMODE + Param_PowerModeKeepActiveOn, /* privilege mode, always active */ + Param_PowerModeKeepActiveOff, /* to leave privilege mode */ +#endif + Param_PowerModeMax /* Upper bound, not real case */ +} PARAM_POWER_MODE, *PPARAM_POWER_MODE; + +typedef enum _PARAM_DEVICE_POWER_STATE { + ParamDeviceStateUnspecified = 0, + ParamDeviceStateD0, + ParamDeviceStateD1, + ParamDeviceStateD2, + ParamDeviceStateD3, + ParamDeviceStateMaximum +} PARAM_DEVICE_POWER_STATE, *PPARAM_DEVICE_POWER_STATE; + +#if CFG_SUPPORT_802_11D + +/*! \brief The enumeration definitions for OID_IPN_MULTI_DOMAIN_CAPABILITY */ +typedef enum _PARAM_MULTI_DOMAIN_CAPABILITY { + ParamMultiDomainCapDisabled, + ParamMultiDomainCapEnabled +} PARAM_MULTI_DOMAIN_CAPABILITY, *P_PARAM_MULTI_DOMAIN_CAPABILITY; +#endif + +typedef struct _COUNTRY_STRING_ENTRY { + UINT_8 aucCountryCode[2]; + UINT_8 aucEnvironmentCode[2]; +} COUNTRY_STRING_ENTRY, *P_COUNTRY_STRING_ENTRY; + +/* Power management related definition and enumerations */ +#define UAPSD_NONE 0 +#define UAPSD_AC0 (BIT(0) | BIT(4)) +#define UAPSD_AC1 (BIT(1) | BIT(5)) +#define UAPSD_AC2 (BIT(2) | BIT(6)) +#define UAPSD_AC3 (BIT(3) | BIT(7)) +#define UAPSD_ALL (UAPSD_AC0 | UAPSD_AC1 | UAPSD_AC2 | UAPSD_AC3) + +typedef enum _ENUM_POWER_SAVE_PROFILE_T { + ENUM_PSP_CONTINUOUS_ACTIVE = 0, + ENUM_PSP_CONTINUOUS_POWER_SAVE, + ENUM_PSP_FAST_SWITCH, + ENUM_PSP_NUM +} ENUM_POWER_SAVE_PROFILE_T, *PENUM_POWER_SAVE_PROFILE_T; + +/*--------------------------------------------------------------*/ +/*! \brief Set/Query testing type. */ +/*--------------------------------------------------------------*/ +#if (CFG_REFACTORY_PMKSA == 0) +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; +#endif +/*--------------------------------------------------------------*/ +/*! \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; +#if (CFG_REFACTORY_PMKSA == 0) + UINT_32 u4NoOfPMKIDs; +#endif + UINT_32 u4NoOfAuthEncryptPairsSupported; + PARAM_AUTH_ENCRYPTION_T arAuthenticationEncryptionSupported[1]; +} PARAM_CAPABILITY_T, *P_PARAM_CAPABILITY_T; + +#if (CFG_REFACTORY_PMKSA == 0) +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; +#endif + +typedef struct _PARAM_PMKID_T { +#if (CFG_REFACTORY_PMKSA == 0) + UINT_32 u4Length; + UINT_32 u4BSSIDInfoCount; + PARAM_BSSID_INFO_T arBSSIDInfo[1]; +#else + uint8_t arBSSID[PARAM_MAC_ADDR_LEN]; + uint8_t arPMKID[IW_PMKID_LEN]; + uint8_t ucBssIdx; +#endif +} PARAM_PMKID_T, *P_PARAM_PMKID_T; + +/*! \brief PMKID candidate lists. */ +typedef struct _PARAM_PMKID_CANDIDATE_T { +#if (CFG_REFACTORY_PMKSA == 0) + PARAM_MAC_ADDRESS arBSSID; + UINT_32 u4Flags; +#else + uint8_t arBSSID[PARAM_MAC_ADDR_LEN]; + uint32_t u4Flags; +#endif +} PARAM_PMKID_CANDIDATE_T, *P_PARAM_PMKID_CANDIDATE_T; + +#if (CFG_REFACTORY_PMKSA == 0) +/* #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 */ +#else +struct PARAM_INDICATION_EVENT { + PARAM_STATUS_INDICATION_T rStatus; + union { + PARAM_AUTH_REQUEST_T rAuthReq; + PARAM_PMKID_CANDIDATE_T rCandi; + }; +}; +#endif + +typedef struct _PARAM_CUSTOM_MCR_RW_STRUCT_T { + UINT_32 u4McrOffset; + UINT_32 u4McrData; +} PARAM_CUSTOM_MCR_RW_STRUCT_T, *P_PARAM_CUSTOM_MCR_RW_STRUCT_T; + +typedef struct _PARAM_CUSTOM_MEM_DUMP_STRUCT_T { + UINT_32 u4Address; + UINT_32 u4Length; + UINT_32 u4RemainLength; + UINT_8 ucFragNum; +} PARAM_CUSTOM_MEM_DUMP_STRUCT_T, *P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T; + +typedef struct _PARAM_CUSTOM_SW_CTRL_STRUCT_T { + UINT_32 u4Id; + UINT_32 u4Data; +} PARAM_CUSTOM_SW_CTRL_STRUCT_T, *P_PARAM_CUSTOM_SW_CTRL_STRUCT_T; + +typedef struct _CMD_CHIP_CONFIG_T { + UINT_16 u2Id; + UINT_8 ucType; + UINT_8 ucRespType; + UINT_16 u2MsgSize; + UINT_8 aucReserved0[2]; + UINT_8 aucCmd[CHIP_CONFIG_RESP_SIZE]; +} CMD_CHIP_CONFIG_T, *P_CMD_CHIP_CONFIG_T; + +typedef struct _PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T { + UINT_16 u2Id; + UINT_8 ucType; + UINT_8 ucRespType; + UINT_16 u2MsgSize; + UINT_8 aucReserved0[2]; + UINT_8 aucCmd[CHIP_CONFIG_RESP_SIZE]; +} PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T, *P_PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T; + +typedef struct _PARAM_ECSA_CONFIG_STRUCT_T { + UINT_8 mode; + UINT_8 channel; + UINT_8 op_class; + UINT_8 sco; + UINT_8 count; +} PARAM_ECSA_CONFIG_STRUCT_T, *P_PARAM_ECSA_CONFIG_STRUCT_T; + +typedef struct _PARAM_CUSTOM_KEY_CFG_STRUCT_T { + UINT_8 aucKey[WLAN_CFG_KEY_LEN_MAX]; + UINT_8 aucValue[WLAN_CFG_VALUE_LEN_MAX]; +} PARAM_CUSTOM_KEY_CFG_STRUCT_T, *P_PARAM_CUSTOM_KEY_CFG_STRUCT_T; + +typedef struct _PARAM_CUSTOM_EEPROM_RW_STRUCT_T { + UINT_8 ucEepromMethod; /* For read only read: 1, query size: 0 */ + UINT_8 ucEepromIndex; + UINT_8 reserved; + UINT_16 u2EepromData; +} PARAM_CUSTOM_EEPROM_RW_STRUCT_T, *P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T, +PARAM_CUSTOM_NVRAM_RW_STRUCT_T, *P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T; + +typedef struct _PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T { + UINT_8 bmfgApsdEnAc; /* b0~3: trigger-en AC0~3. b4~7: delivery-en AC0~3 */ + UINT_8 ucIsEnterPsAtOnce; /* enter PS immediately without 5 second guard after connected */ + UINT_8 ucIsDisableUcTrigger; /* not to trigger UC on beacon TIM is matched (under U-APSD) */ + UINT_8 reserved; +} PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T, *P_PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T; + +typedef struct _PARAM_CUSTOM_NOA_PARAM_STRUCT_T { + UINT_32 u4NoaDurationMs; + UINT_32 u4NoaIntervalMs; + UINT_32 u4NoaCount; +} PARAM_CUSTOM_NOA_PARAM_STRUCT_T, *P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T; + +typedef struct _PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T { + UINT_32 u4CTwindowMs; +} PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T, *P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T; + +typedef struct _PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T { + UINT_8 fgEnAPSD; + UINT_8 fgEnAPSD_AcBe; + UINT_8 fgEnAPSD_AcBk; + UINT_8 fgEnAPSD_AcVo; + UINT_8 fgEnAPSD_AcVi; + UINT_8 ucMaxSpLen; + UINT_8 aucResv[2]; +} PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T, *P_PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T; + +typedef struct _PARAM_CUSTOM_P2P_SET_STRUCT_T { + UINT_32 u4Enable; + UINT_32 u4Mode; +} PARAM_CUSTOM_P2P_SET_STRUCT_T, *P_PARAM_CUSTOM_P2P_SET_STRUCT_T; + +typedef enum _ENUM_CFG_SRC_TYPE_T { + CFG_SRC_TYPE_EEPROM, + CFG_SRC_TYPE_NVRAM, + CFG_SRC_TYPE_UNKNOWN, + CFG_SRC_TYPE_NUM +} ENUM_CFG_SRC_TYPE_T, *P_ENUM_CFG_SRC_TYPE_T; + +typedef enum _ENUM_EEPROM_TYPE_T { + EEPROM_TYPE_NO, + EEPROM_TYPE_PRESENT, + EEPROM_TYPE_NUM +} ENUM_EEPROM_TYPE_T, *P_ENUM_EEPROM_TYPE_T; + +typedef struct _PARAM_QOS_TSINFO { + UINT_8 ucTrafficType; /* Traffic Type: 1 for isochronous 0 for asynchronous */ + UINT_8 ucTid; /* TSID: must be between 8 ~ 15 */ + UINT_8 ucDirection; /* direction */ + UINT_8 ucAccessPolicy; /* access policy */ + UINT_8 ucAggregation; /* aggregation */ + UINT_8 ucApsd; /* APSD */ + UINT_8 ucuserPriority; /* user priority */ + UINT_8 ucTsInfoAckPolicy; /* TSINFO ACK policy */ + UINT_8 ucSchedule; /* Schedule */ +} PARAM_QOS_TSINFO, *P_PARAM_QOS_TSINFO; + +typedef struct _PARAM_QOS_TSPEC { + PARAM_QOS_TSINFO rTsInfo; /* TS info field */ + UINT_16 u2NominalMSDUSize; /* nominal MSDU size */ + UINT_16 u2MaxMSDUsize; /* maximum MSDU size */ + UINT_32 u4MinSvcIntv; /* minimum service interval */ + UINT_32 u4MaxSvcIntv; /* maximum service interval */ + UINT_32 u4InactIntv; /* inactivity interval */ + UINT_32 u4SpsIntv; /* suspension interval */ + UINT_32 u4SvcStartTime; /* service start time */ + UINT_32 u4MinDataRate; /* minimum Data rate */ + UINT_32 u4MeanDataRate; /* mean data rate */ + UINT_32 u4PeakDataRate; /* peak data rate */ + UINT_32 u4MaxBurstSize; /* maximum burst size */ + UINT_32 u4DelayBound; /* delay bound */ + UINT_32 u4MinPHYRate; /* minimum PHY rate */ + UINT_16 u2Sba; /* surplus bandwidth allowance */ + UINT_16 u2MediumTime; /* medium time */ + UINT_8 ucDialogToken; +} PARAM_QOS_TSPEC, *P_PARAM_QOS_TSPEC; + +typedef struct _PARAM_QOS_ADDTS_REQ_INFO { + PARAM_QOS_TSPEC rTspec; +} PARAM_QOS_ADDTS_REQ_INFO, *P_PARAM_QOS_ADDTS_REQ_INFO; + +typedef struct _PARAM_VOIP_CONFIG { + UINT_32 u4VoipTrafficInterval; /* 0: disable VOIP configuration */ +} PARAM_VOIP_CONFIG, *P_PARAM_VOIP_CONFIG; + +/*802.11 Statistics Struct*/ +typedef struct _PARAM_802_11_STATISTICS_STRUCT_T { + UINT_32 u4Length; /* Length of structure */ + LARGE_INTEGER rTransmittedFragmentCount; + LARGE_INTEGER rMulticastTransmittedFrameCount; + LARGE_INTEGER rFailedCount; + LARGE_INTEGER rRetryCount; + LARGE_INTEGER rMultipleRetryCount; + LARGE_INTEGER rRTSSuccessCount; + LARGE_INTEGER rRTSFailureCount; + LARGE_INTEGER rACKFailureCount; + LARGE_INTEGER rFrameDuplicateCount; + LARGE_INTEGER rReceivedFragmentCount; + LARGE_INTEGER rMulticastReceivedFrameCount; + LARGE_INTEGER rFCSErrorCount; + LARGE_INTEGER rTKIPLocalMICFailures; + LARGE_INTEGER rTKIPICVErrors; + LARGE_INTEGER rTKIPCounterMeasuresInvoked; + LARGE_INTEGER rTKIPReplays; + LARGE_INTEGER rCCMPFormatErrors; + LARGE_INTEGER rCCMPReplays; + LARGE_INTEGER rCCMPDecryptErrors; + LARGE_INTEGER rFourWayHandshakeFailures; + LARGE_INTEGER rWEPUndecryptableCount; + LARGE_INTEGER rWEPICVErrorCount; + LARGE_INTEGER rDecryptSuccessCount; + LARGE_INTEGER rDecryptFailureCount; +} PARAM_802_11_STATISTICS_STRUCT_T, *P_PARAM_802_11_STATISTICS_STRUCT_T; + +/* Linux Network Device Statistics Struct */ +typedef struct _PARAM_LINUX_NETDEV_STATISTICS_T { + UINT_32 u4RxPackets; + UINT_32 u4TxPackets; + UINT_32 u4RxBytes; + UINT_32 u4TxBytes; + UINT_32 u4RxErrors; + UINT_32 u4TxErrors; + UINT_32 u4Multicast; +} PARAM_LINUX_NETDEV_STATISTICS_T, *P_PARAM_LINUX_NETDEV_STATISTICS_T; + +typedef struct _PARAM_MTK_WIFI_TEST_STRUCT_T { + UINT_32 u4FuncIndex; + UINT_32 u4FuncData; + UINT_32 u4FuncData2; /*FW don't support*/ +} PARAM_MTK_WIFI_TEST_STRUCT_T, *P_PARAM_MTK_WIFI_TEST_STRUCT_T; + +/* 802.11 Media stream constraints */ +typedef enum _ENUM_MEDIA_STREAM_MODE { + ENUM_MEDIA_STREAM_OFF, + ENUM_MEDIA_STREAM_ON +} ENUM_MEDIA_STREAM_MODE, *P_ENUM_MEDIA_STREAM_MODE; + +/* for NDIS 5.1 Media Streaming Change */ +typedef struct _PARAM_MEDIA_STREAMING_INDICATION { + PARAM_STATUS_INDICATION_T rStatus; + ENUM_MEDIA_STREAM_MODE eMediaStreamMode; +} PARAM_MEDIA_STREAMING_INDICATION, *P_PARAM_MEDIA_STREAMING_INDICATION; + +#define PARAM_PROTOCOL_ID_DEFAULT 0x00 +#define PARAM_PROTOCOL_ID_TCP_IP 0x02 +#define PARAM_PROTOCOL_ID_IPX 0x06 +#define PARAM_PROTOCOL_ID_NBF 0x07 +#define PARAM_PROTOCOL_ID_MAX 0x0F +#define PARAM_PROTOCOL_ID_MASK 0x0F + +/* for NDIS OID_GEN_NETWORK_LAYER_ADDRESSES */ +typedef struct _PARAM_NETWORK_ADDRESS_IP { + UINT_16 sin_port; + UINT_32 in_addr; + UINT_8 sin_zero[8]; +} PARAM_NETWORK_ADDRESS_IP, *P_PARAM_NETWORK_ADDRESS_IP; + +typedef struct _PARAM_NETWORK_ADDRESS { + UINT_16 u2AddressLength; /* length in bytes of Address[] in this */ + UINT_16 u2AddressType; /* type of this address (PARAM_PROTOCOL_ID_XXX above) */ + UINT_8 aucAddress[1]; /* actually AddressLength bytes long */ +} PARAM_NETWORK_ADDRESS, *P_PARAM_NETWORK_ADDRESS; + +/* The following is used with OID_GEN_NETWORK_LAYER_ADDRESSES to set network layer addresses on an interface */ + +typedef struct _PARAM_NETWORK_ADDRESS_LIST { + UINT_32 u4AddressCount; /* number of addresses following */ + UINT_16 u2AddressType; /* type of this address (NDIS_PROTOCOL_ID_XXX above) */ + PARAM_NETWORK_ADDRESS arAddress[1]; /* actually AddressCount elements long */ +} PARAM_NETWORK_ADDRESS_LIST, *P_PARAM_NETWORK_ADDRESS_LIST; + +#if CFG_SLT_SUPPORT + +#define FIXED_BW_LG20 0x0000 +#define FIXED_BW_UL20 0x2000 +#define FIXED_BW_DL40 0x3000 + +#define FIXED_EXT_CHNL_U20 0x4000 /* For AGG register. */ +#define FIXED_EXT_CHNL_L20 0xC000 /* For AGG regsiter. */ + +typedef enum _ENUM_MTK_LP_TEST_MODE_T { + ENUM_MTK_LP_TEST_NORMAL, + ENUM_MTK_LP_TEST_GOLDEN_SAMPLE, + ENUM_MTK_LP_TEST_DUT, + ENUM_MTK_LP_TEST_MODE_NUM +} ENUM_MTK_LP_TEST_MODE_T, *P_ENUM_MTK_LP_TEST_MODE_T; + +typedef enum _ENUM_MTK_SLT_FUNC_IDX_T { + ENUM_MTK_SLT_FUNC_DO_NOTHING, + ENUM_MTK_SLT_FUNC_INITIAL, + ENUM_MTK_SLT_FUNC_RATE_SET, + ENUM_MTK_SLT_FUNC_LP_SET, + ENUM_MTK_SLT_FUNC_NUM +} ENUM_MTK_SLT_FUNC_IDX_T, *P_ENUM_MTK_SLT_FUNC_IDX_T; + +typedef struct _PARAM_MTK_SLT_LP_TEST_STRUCT_T { + ENUM_MTK_LP_TEST_MODE_T rLpTestMode; + UINT_32 u4BcnRcvNum; +} PARAM_MTK_SLT_LP_TEST_STRUCT_T, *P_PARAM_MTK_SLT_LP_TEST_STRUCT_T; + +typedef struct _PARAM_MTK_SLT_TR_TEST_STRUCT_T { + ENUM_PARAM_NETWORK_TYPE_T rNetworkType; /* Network Type OFDM5G or OFDM2.4G */ + UINT_32 u4FixedRate; /* Fixed Rate including BW */ +} PARAM_MTK_SLT_TR_TEST_STRUCT_T, *P_PARAM_MTK_SLT_TR_TEST_STRUCT_T; + +typedef struct _PARAM_MTK_SLT_INITIAL_STRUCT_T { + UINT_8 aucTargetMacAddr[PARAM_MAC_ADDR_LEN]; + UINT_16 u2SiteID; +} PARAM_MTK_SLT_INITIAL_STRUCT_T, *P_PARAM_MTK_SLT_INITIAL_STRUCT_T; + +typedef struct _PARAM_MTK_SLT_TEST_STRUCT_T { + ENUM_MTK_SLT_FUNC_IDX_T rSltFuncIdx; + UINT_32 u4Length; /* + * Length of structure, + * including myself + */ + UINT_32 u4FuncInfoLen; /* + * Include following content + * field and myself + */ + union { + PARAM_MTK_SLT_INITIAL_STRUCT_T rMtkInitTest; + PARAM_MTK_SLT_LP_TEST_STRUCT_T rMtkLpTest; + PARAM_MTK_SLT_TR_TEST_STRUCT_T rMtkTRTest; + } unFuncInfoContent; + +} PARAM_MTK_SLT_TEST_STRUCT_T, *P_PARAM_MTK_SLT_TEST_STRUCT_T; + +#endif + +/*--------------------------------------------------------------*/ +/*! \brief For Fixed Rate Configuration (Registry) */ +/*--------------------------------------------------------------*/ +typedef enum _ENUM_REGISTRY_FIXED_RATE_T { + FIXED_RATE_NONE, + FIXED_RATE_1M, + FIXED_RATE_2M, + FIXED_RATE_5_5M, + FIXED_RATE_11M, + FIXED_RATE_6M, + FIXED_RATE_9M, + FIXED_RATE_12M, + FIXED_RATE_18M, + FIXED_RATE_24M, + FIXED_RATE_36M, + FIXED_RATE_48M, + FIXED_RATE_54M, + FIXED_RATE_MCS0_20M_800NS, + FIXED_RATE_MCS1_20M_800NS, + FIXED_RATE_MCS2_20M_800NS, + FIXED_RATE_MCS3_20M_800NS, + FIXED_RATE_MCS4_20M_800NS, + FIXED_RATE_MCS5_20M_800NS, + FIXED_RATE_MCS6_20M_800NS, + FIXED_RATE_MCS7_20M_800NS, + FIXED_RATE_MCS0_20M_400NS, + FIXED_RATE_MCS1_20M_400NS, + FIXED_RATE_MCS2_20M_400NS, + FIXED_RATE_MCS3_20M_400NS, + FIXED_RATE_MCS4_20M_400NS, + FIXED_RATE_MCS5_20M_400NS, + FIXED_RATE_MCS6_20M_400NS, + FIXED_RATE_MCS7_20M_400NS, + FIXED_RATE_MCS0_40M_800NS, + FIXED_RATE_MCS1_40M_800NS, + FIXED_RATE_MCS2_40M_800NS, + FIXED_RATE_MCS3_40M_800NS, + FIXED_RATE_MCS4_40M_800NS, + FIXED_RATE_MCS5_40M_800NS, + FIXED_RATE_MCS6_40M_800NS, + FIXED_RATE_MCS7_40M_800NS, + FIXED_RATE_MCS32_800NS, + FIXED_RATE_MCS0_40M_400NS, + FIXED_RATE_MCS1_40M_400NS, + FIXED_RATE_MCS2_40M_400NS, + FIXED_RATE_MCS3_40M_400NS, + FIXED_RATE_MCS4_40M_400NS, + FIXED_RATE_MCS5_40M_400NS, + FIXED_RATE_MCS6_40M_400NS, + FIXED_RATE_MCS7_40M_400NS, + FIXED_RATE_MCS32_400NS, + FIXED_RATE_NUM +} ENUM_REGISTRY_FIXED_RATE_T, *P_ENUM_REGISTRY_FIXED_RATE_T; + +typedef enum _ENUM_BT_CMD_T { + BT_CMD_PROFILE = 0, + BT_CMD_UPDATE, + BT_CMD_NUM +} ENUM_BT_CMD_T; + +typedef enum _ENUM_BT_PROFILE_T { + BT_PROFILE_CUSTOM = 0, + BT_PROFILE_SCO, + BT_PROFILE_ACL, + BT_PROFILE_MIXED, + BT_PROFILE_NO_CONNECTION, + BT_PROFILE_NUM +} ENUM_BT_PROFILE_T; + +typedef struct _PTA_PROFILE_T { + ENUM_BT_PROFILE_T eBtProfile; + union { + UINT_8 aucBTPParams[BT_PROFILE_PARAM_LEN]; + /* + * 0: sco reserved slot time, + * 1: sco idle slot time, + * 2: acl throughput, + * 3: bt tx power, + * 4: bt rssi + * 5: VoIP interval + * 6: BIT(0) Use this field, BIT(1) 0 apply single/ 1 dual PTA setting. + */ + UINT_32 au4Btcr[4]; + } u; +} PTA_PROFILE_T, *P_PTA_PROFILE_T; + +typedef struct _PTA_IPC_T { + UINT_8 ucCmd; + UINT_8 ucLen; + union { + PTA_PROFILE_T rProfile; + UINT_8 aucBTPParams[BT_PROFILE_PARAM_LEN]; + } u; +} PARAM_PTA_IPC_T, *P_PARAM_PTA_IPC_T, PTA_IPC_T, *P_PTA_IPC_T; + +/*--------------------------------------------------------------*/ +/*! \brief CFG80211 Scan Request Container */ +/*--------------------------------------------------------------*/ + +typedef struct _PARAM_SCAN_REQUEST_EXT_T { + PARAM_SSID_T rSsid; + UINT_32 u4IELength; + PUINT_8 pucIE; + /* partial scan temp save request info */ + PUINT_8 puPartialScanReq; +} PARAM_SCAN_REQUEST_EXT_T, *P_PARAM_SCAN_REQUEST_EXT_T; + +/* MULTI SSID */ +typedef struct _PARAM_SCAN_REQUEST_ADV_T { + UINT_32 u4SsidNum; + PARAM_SSID_T rSsid[CFG_SCAN_SSID_MAX_NUM]; + UINT_32 u4IELength; + PUINT_8 pucIE; + /* partial scan temp save request info */ + PUINT_8 puPartialScanReq; + UINT_8 aucRandomMac[MAC_ADDR_LEN]; +} PARAM_SCAN_REQUEST_ADV_T, *P_PARAM_SCAN_REQUEST_ADV_T; + +/*--------------------------------------------------------------*/ +/*! \brief CFG80211 Scheduled Scan Request Container */ +/*--------------------------------------------------------------*/ +typedef struct _PARAM_SCHED_SCAN_REQUEST_T { +#if CFG_SUPPORT_SCHED_SCN_SSID_SETS + UINT_32 u4SsidNum; /*passed in the probe_reqs*/ + PARAM_SSID_T arSsid[CFG_SCAN_HIDDEN_SSID_MAX_NUM]; + UINT_32 u4MatchSsidNum; /*matched for a scan request*/ + PARAM_SSID_T arMatchSsid[CFG_SCAN_SSID_MATCH_MAX_NUM]; +#else + UINT_32 u4SsidNum; + PARAM_SSID_T arSsid[CFG_SCAN_SSID_MATCH_MAX_NUM]; +#endif + UINT_32 u4IELength; + PUINT_8 pucIE; + UINT_16 u2ScanInterval; /* in milliseconds */ + UINT_8 ucScnFuncMask; + UINT_8 aucRandomMac[MAC_ADDR_LEN]; + UINT_8 aucRandomMacMask[MAC_ADDR_LEN]; +} PARAM_SCHED_SCAN_REQUEST, *P_PARAM_SCHED_SCAN_REQUEST; + +#if CFG_SUPPORT_HOTSPOT_2_0 +typedef struct _PARAM_HS20_SET_BSSID_POOL { + BOOLEAN fgIsEnable; + UINT_8 ucNumBssidPool; + PARAM_MAC_ADDRESS arBSSID[8]; +} PARAM_HS20_SET_BSSID_POOL, *P_PARAM_HS20_SET_BSSID_POOL; + +#endif + +typedef struct _PARAM_CUSTOM_WFD_DEBUG_STRUCT_T { + UINT_8 ucWFDDebugMode; /* + * 0: Disable + * 1:Enable but only show inqueue skb ether SN + * 2.show skb ether SN and the statistics of skb inqueue time + */ + UINT_16 u2SNPeriod; /* The Ether SN Period */ + + UINT_8 reserved; +} PARAM_CUSTOM_WFD_DEBUG_STRUCT_T, *P_PARAM_CUSTOM_WFD_DEBUG_STRUCT_T; + +typedef struct _CMD_GET_PSCAN_CAPABILITY { +/* TBD */ +} CMD_GET_GSCAN_CAPABILITY, *P_CMD_GET_GSCAN_CAPABILITY; + +typedef enum _ENUM_PSCAN_ACT_T { + PSCAN_ACT_DISABLE = 0, + PSCAN_ACT_ENABLE, + PSCAN_ACT_SUSPEND, + PSCAN_ACT_CLEAR +} ENUM_PSCAN_ACT_T, *P_ENUM_PSCAN_ACT_T; + +typedef struct _CMD_SET_PSCAN_ENABLE { + UINT_8 ucPscanAct; + UINT_8 aucReserved[3]; +} CMD_SET_PSCAN_ENABLE, *P_CMD_SET_PSCAN_ENABLE; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#define MAX_PACKET_DROP_LENGTH 24 + +typedef struct _PACKET_DROP_HEADER_T { + UINT_8 cmdVersion; /*== 0*/ + UINT_8 cmdType; /*== 0*/ + UINT_8 magicCode; /*==> Magic code 0x72 */ + UINT_8 cmdBufferLen; /*buffer length */ + UINT_8 buffer[MAX_PACKET_DROP_LENGTH]; /*64bit * 3*/ +} __KAL_ATTRIB_PACKED__ PACKET_DROP_T, *P_PACKET_DROP_T; + +typedef struct _PACKET_DROP_SETTING_V1_T { + union{ + /* bit endian issue */ + struct { + UINT_64 all:1; + UINT_64 MDNS:1; + UINT_64 LLMNR:1; + UINT_64 BROWSER:1; + UINT_64 CAPWAP:1; + UINT_64 DNS:1; + UINT_64 NBNS:1; + UINT_64 SSDP:1; + UINT_64 others:1; + UINT_64 IGMP:1; + UINT_64 DHCP:1; + UINT_64 reserved:53; + } UDPbits; + + struct { + UINT_64 all:1; + } IGMPbits; + + /* byte endian issue */ + UINT_64 bytes; + } Drop_IPv4; + + union{ + /* bit endian issue */ + struct { + UINT_64 all:1; + UINT_64 Multicast:1; + UINT_64 reserved:62; + } bits; + /* byte endian issue */ + UINT_64 bytes; + } Drop_IPv6; + union{ + /* bit endian issue */ + struct { + UINT_64 all:1; + UINT_64 CDP:1; + UINT_64 STP:1; + UINT_64 XID:1; + UINT_64 others:1; + UINT_64 reserved:59; + } bits; + /* byte endian issue */ + UINT_64 bytes; + } Drop_SNAP; + +} __KAL_ATTRIB_PACKED__ PACKET_DROP_SETTING_V1_T, *P_PACKET_DROP_SETTING_V1_T; + +#if CFG_SUPPORT_OSHARE +/*OSHARE Mode*/ +#define MAX_OSHARE_MODE_LENGTH 64 +#define OSHARE_MODE_MAGIC_CODE 0x18 +#define OSHARE_MODE_CMD_V1 0x1 + +struct OSHARE_MODE_T { + UINT_8 cmdVersion;/*CMD version = OSHARE_MODE_CMD_V1 */ + UINT_8 cmdType;/*1-set 0-query*/ + UINT_8 magicCode;/*It's like CRC, OSHARE_MODE_MAGIC_CODE*/ + UINT_8 cmdBufferLen;/*buffer length <= 64*/ + UINT_8 buffer[MAX_OSHARE_MODE_LENGTH]; +}; + +struct OSHARE_MODE_SETTING_V1_T { + UINT_8 osharemode;/*0: disable, 1:Enable*/ + UINT_8 reserved[7]; +}; +#endif + +/*--------------------------------------------------------------*/ +/*! \brief MTK Auto Channel Selection related Container */ +/*--------------------------------------------------------------*/ +typedef struct _LTE_SAFE_CHN_INFO_T { + UINT_32 au4SafeChannelBitmask[5]; /* NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_MAX */ +} LTE_SAFE_CHN_INFO_T, *P_CMD_LTE_SAFE_CHN_INFO_T; + +typedef struct _PARAM_CHN_LOAD_INFO { + /* Per-CHN Load */ + UINT_8 ucChannel; + UINT_16 u2APNum; + UINT_16 u2APNumScore; + UINT_8 aucReserved[3]; +} PARAM_CHN_LOAD_INFO, *P_PARAM_CHN_LOAD_INFO; + +typedef struct _PARAM_GET_CHN_INFO { + LTE_SAFE_CHN_INFO_T rLteSafeChnList; + PARAM_CHN_LOAD_INFO rEachChnLoad[MAX_CHN_NUM]; + UINT_8 aucReserved[3]; +} PARAM_GET_CHN_INFO, *P_PARAM_GET_CHN_INFO; + +typedef struct _PARAM_PREFER_CHN_INFO { + UINT_8 ucChannel; + UINT_16 u2APNumScore; + UINT_8 ucReserved; +} PARAM_PREFER_CHN_INFO, *P_PARAM_PREFER_CHN_INFO; + +struct PARAM_WIFI_LOG_LEVEL_UI { + UINT_32 u4Version; + UINT_32 u4Module; + UINT_32 u4Enable; +}; + +struct PARAM_WIFI_LOG_LEVEL { + UINT_32 u4Version; + UINT_32 u4Module; + UINT_32 u4Level; +}; + +struct PARAM_GET_WIFI_TYPE { + struct net_device *prNetDev; + uint8_t arWifiTypeName[8]; +}; + +enum ENUM_WIFI_LOG_LEVEL_VERSION_T { + ENUM_WIFI_LOG_LEVEL_VERSION_V1 = 1, + ENUM_WIFI_LOG_LEVEL_VERSION_NUM +}; + +enum ENUM_WIFI_LOG_LEVEL_T { + ENUM_WIFI_LOG_LEVEL_OFF = 0, + ENUM_WIFI_LOG_LEVEL_DEFAULT, + ENUM_WIFI_LOG_LEVEL_EXTREME, + ENUM_WIFI_LOG_LEVEL_NUM +}; + +enum ENUM_WIFI_LOG_MODULE_T { + ENUM_WIFI_LOG_MODULE_DRIVER = 0, + ENUM_WIFI_LOG_MODULE_FW, + ENUM_WIFI_LOG_MODULE_NUM, +}; + +enum ENUM_WIFI_LOG_LEVEL_SUPPORT_T { + ENUM_WIFI_LOG_LEVEL_SUPPORT_DISABLE = 0, + ENUM_WIFI_LOG_LEVEL_SUPPORT_ENABLE, + ENUM_WIFI_LOG_LEVEL_SUPPORT_NUM +}; + +struct TX_POWER_SCENARIO_ENTRY { + bool fgEnable2G; + uint8_t ucTxPowerLimit2G; + bool fgEnable5G; + uint8_t ucTxPowerLimit5G; +}; + +struct PARAM_TX_POWER_LIMIT { + /* iScenario: -2:use following values, -1:reset, >=0:scenario index */ + int32_t iScenario; + bool fgEnable2G; + uint8_t ucTxPowerLimit2G; + bool fgEnable5G; + uint8_t ucTxPowerLimit5G; +}; + +/******************************************************************************* +* P U B 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 +wlanoidSetBssidListScanAdv(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen);/* MULTI SSID */ + +WLAN_STATUS +wlanoidQueryBssidList(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetBssid(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetSsid(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetConnect(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQuerySsid(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryInfrastructureMode(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetInfrastructureMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryAuthMode(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetAuthMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +#if 0 +WLAN_STATUS +wlanoidQueryPrivacyFilter(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetPrivacyFilter(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +WLAN_STATUS +wlanoidSetEncryptionStatus(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryEncryptionStatus(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetAddWep(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetRemoveWep(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +_wlanoidSetAddKey(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, IN BOOLEAN fgIsOid, IN UINT_8 ucAlgorithmId, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetAddKey(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetRemoveKey(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetReloadDefaults(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#if (CFG_REFACTORY_PMKSA == 0) +WLAN_STATUS +wlanoidSetTest(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif +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 +wlanoidRssiMonitor(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +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); +#if (CFG_REFACTORY_PMKSA == 0) + +WLAN_STATUS +wlanoidQueryPmkid(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); +#else +WLAN_STATUS + +wlanoidDelPmkid(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS + +wlanoidFlushPmkid(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen); + +#endif +WLAN_STATUS +wlanoidSetPmkid(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQuerySupportedRates(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryDesiredRates(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetDesiredRates(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryPermanentAddr(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuf, IN UINT_32 u4QueryBufLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryCurrentAddr(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuf, IN UINT_32 u4QueryBufLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryPermanentAddr(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuf, IN UINT_32 u4QueryBufLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryLinkSpeed(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryMcrRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryMemDump(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetMcrWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQuerySwCtrlRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetSwCtrlWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryEepromRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetEepromWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryRfTestRxStatus(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryRfTestTxStatus(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryOidInterfaceVersion(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryVendorId(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryMulticastList(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetMulticastList(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryRcvError(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryRcvNoBuffer(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryRcvCrcError(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryStatistics(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); +WLAN_STATUS +wlanoidQueryStatisticsPL(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +#ifdef LINUX + +WLAN_STATUS +wlanoidQueryStatisticsForLinux(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +#endif + +WLAN_STATUS +wlanoidQueryMediaStreamMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetMediaStreamMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryRcvOk(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryXmitOk(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryXmitError(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryXmitOneCollision(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryXmitMoreCollisions(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryXmitMaxCollisions(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetCurrentPacketFilter(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryCurrentPacketFilter(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetAcpiDevicePowerState(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryAcpiDevicePowerState(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetDisassociate(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryFragThreshold(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetFragThreshold(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryAdHocMode(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetAdHocMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryBeaconInterval(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetBeaconInterval(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetCurrentAddr(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +WLAN_STATUS +wlanoidSetCSUMOffload(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +WLAN_STATUS +wlanoidSetNetworkAddress(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryMaxFrameSize(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryMaxTotalSize(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetCurrentLookahead(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +/* RF Test related APIs */ +WLAN_STATUS +wlanoidRftestSetTestMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidRftestSetAbortTestMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidRftestQueryAutoTest(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidRftestSetAutoTest(IN P_ADAPTER_T prAdapter, + OUT PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +#if CFG_SUPPORT_WAPI +WLAN_STATUS +wlanoidSetWapiMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetWapiAssocInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetWapiKey(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +#if CFG_ENABLE_WAKEUP_ON_LAN +WLAN_STATUS +wlanoidSetAddWakeupPattern(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetRemoveWakeupPattern(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryEnableWakeup(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 u4QueryInfoLen); + +WLAN_STATUS +wlanoidSetEnableWakeup(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +WLAN_STATUS +wlanoidSetWiFiWmmPsTest(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetTxAmpdu(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryBSSInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetAddbaReject(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryNvramRead(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetNvramWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryCfgSrcType(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryEepromType(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetCountryCode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +#ifdef CFG_TC1_FEATURE /* for Passive Scan */ +WLAN_STATUS +wlanoidSetPassiveScan(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +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 +wlanoidSetRxPacketFilterPriv(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +#if CFG_SUPPORT_OSHARE + WLAN_STATUS + wlanoidSetOshareMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +#if CFG_SUPPORT_BUILD_DATE_CODE +WLAN_STATUS +wlanoidQueryBuildDateCode(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); +#endif + +#if CFG_ENABLE_WIFI_DIRECT +WLAN_STATUS +wlanoidSetP2pMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +#if CFG_SUPPORT_BATCH_SCAN +WLAN_STATUS +wlanoidSetBatchScanReq(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryBatchScanResult(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); +#endif + +#if CFG_SUPPORT_HOTSPOT_2_0 +WLAN_STATUS +wlanoidSetHS20Info(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetHS20BssidPool(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +WLAN_STATUS +wlanoidSetRoamingInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetWfdDebugMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetStartSchedScan(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetStopSchedScan(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +#if CFG_SUPPORT_GSCN +WLAN_STATUS +wlanoidSetGSCNAction(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetGSCNParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetGSCNConfig(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidGetGSCNResult(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +WLAN_STATUS +wlanoidSetTxRateInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetChipConfig(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidNotifyFwSuspend(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen); + +#if CFG_SUPPORT_TDLS +WLAN_STATUS +wlanoidDisableTdlsPs(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +WLAN_STATUS +wlanoidPacketKeepAlive(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidConfigRoaming(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#ifdef FW_CFG_SUPPORT +WLAN_STATUS wlanoidQueryCfgRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS wlanoidSetFwParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen); +#endif +#if CFG_SUPPORT_EMI_DEBUG +WLAN_STATUS +wlanoidSetEnableDumpEMILog(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +WLAN_STATUS +wlanoidUpdateFtIes(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSync11kCapbilities(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSendNeighborRequest(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS wlanoidSendBTMQuery(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS wlanoidTspecOperation( + IN P_ADAPTER_T prAdapter, IN PVOID pvBuffer, IN UINT_32 u4BufferLen, OUT PUINT_32 pu4InfoLen); + +#endif /* _WLAN_OID_H */ +WLAN_STATUS +wlanoidSetChipConfig(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +#if CFG_SUPPORT_P2P_ECSA +WLAN_STATUS +wlanoidSetECSAConfig(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +WLAN_STATUS +wlanoidNotifyFwSuspend(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetAlwaysScan(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + + +WLAN_STATUS +wlanoidDisableTdlsPs(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +#if CFG_SUPPORT_GAMING_MODE +WLAN_STATUS wlanoidSetGamingMode(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif /* CFG_SUPPORT_GAMING_MODE */ + +WLAN_STATUS wlanoidSetPacketFilter(P_ADAPTER_T prAdapter, UINT_32 u4PacketFilter, + BOOLEAN fgIsOid, PVOID pvSetBuffer, UINT_32 u4SetBufferLen); + +WLAN_STATUS wlanoidSetDrvRoamingPolicy(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS wlanoidRadioMeasurementIT( + P_ADAPTER_T prAdapter, PVOID pvBuffer, UINT_32 u4BufferLen, PUINT_32 pu4InfoLen); + +WLAN_STATUS +wlanoidDumpUapsdSetting(P_ADAPTER_T prAdapter, PVOID pvBuffer, UINT_32 u4BufferLen, + PUINT_32 pu4InfoLen); + +#if CFG_SUPPORT_FCC_POWER_BACK_OFF +WLAN_STATUS +wlanoidSetFccCert(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +#if CFG_SUPPORT_NCHO +#define NCHO_CMD_MAX_LENGTH 128 + +WLAN_STATUS +wlanoidSetNchoRoamTrigger(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryNchoRoamTrigger(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetNchoRoamDelta(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryNchoRoamDelta(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetNchoRoamScnPeriod(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryNchoRoamScnPeriod(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetNchoRoamScnChnl(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryNchoRoamScnChnl(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetNchoRoamScnCtrl(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryNchoRoamScnCtrl(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetNchoScnChnlTime(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryNchoScnChnlTime(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetNchoScnHomeTime(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryNchoScnHomeTime(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetNchoScnHomeAwayTime(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryNchoScnHomeAwayTime(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetNchoScnNprobes(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryNchoScnNprobes(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidGetNchoReassocInfo(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSendNchoActionFrameStart(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSendNchoActionFrameEnd(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetNchoWesMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryNchoWesMode(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetNchoBand(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryNchoBand(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetNchoDfsScnMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryNchoDfsScnMode(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetNchoEnable(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryNchoEnable(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +#endif /* CFG_SUPPORT_NCHO */ + +WLAN_STATUS +wlanoidAbortScan(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryWifiLogLevelSupport(IN P_ADAPTER_T prAdapter, + OUT PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryWifiLogLevel(IN P_ADAPTER_T prAdapter, + OUT PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetWifiLogLevel(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +uint32_t +wlanoidSetTxPowerLimit(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidGetWifiType(IN P_ADAPTER_T prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidExternalAuthDone(IN P_ADAPTER_T prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetScanMacOui(IN P_ADAPTER_T prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/wlan_p2p.h b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/wlan_p2p.h new file mode 100644 index 0000000000000..8812f3a438219 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen2/include/wlan_p2p.h @@ -0,0 +1,221 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef _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; + +/******************************************************************************* +* 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 +_wlanoidSetAddP2PTDLSKey(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + + +WLAN_STATUS +wlanoidSetRemoveP2PKey(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetNetworkAddress(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetP2PMulticastList(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +/*--------------------------------------------------------------*/ +/* Service Discovery Subroutines */ +/*--------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendP2PSDRequest(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSendP2PSDResponse(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidGetP2PSDRequest(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidGetP2PSDResponse(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 puQueryInfoLen); + +WLAN_STATUS +wlanoidSetP2PTerminateSDPhase(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +#if CFG_SUPPORT_ANTI_PIRACY +WLAN_STATUS +wlanoidSetSecCheckRequest(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidGetSecCheckResponse(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); +#endif + +WLAN_STATUS +wlanoidSetNoaParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetOppPsParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetUApsdParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryP2pPowerSaveProfile(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetP2pPowerSaveProfile(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetP2pSetNetworkAddress(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryP2pOpChannel(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryP2pVersion(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetP2pSupplicantVersion(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetP2pWPSmode(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +#if CFG_SUPPORT_P2P_RSSI_QUERY +WLAN_STATUS +wlanoidQueryP2pRssi(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); +#endif + +WLAN_STATUS +wlanoidAbortP2pScan(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen); + +/*--------------------------------------------------------------*/ +/* Callbacks for event indication */ +/*--------------------------------------------------------------*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif +#endif /* _WLAN_P2P_H */ From 09ecce4445b8655c6debf97c495e2333cd1bc86a Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 21:58:48 +0800 Subject: [PATCH 16/32] Add files via upload --- .../connectivity/wlan/core/gen3/Android.mk | 25 + .../connectivity/wlan/core/gen3/Makefile | 262 + .../connectivity/wlan/core/gen3/README | 2 + .../wlan/core/gen3/common/debug.c | 738 + .../connectivity/wlan/core/gen3/common/dump.c | 327 + .../wlan/core/gen3/common/fwcfg.c | 377 + .../wlan/core/gen3/common/makefile | 8 + .../wlan/core/gen3/common/sources.ce | 11 + .../wlan/core/gen3/common/sources.ddk | 11 + .../wlan/core/gen3/common/wlan_bow.c | 3205 ++++ .../wlan/core/gen3/common/wlan_lib.c | 7609 +++++++++ .../wlan/core/gen3/common/wlan_oid.c | 12854 ++++++++++++++++ .../wlan/core/gen3/common/wlan_p2p.c | 1687 ++ .../connectivity/wlan/core/gen3/lint/co.lnt | 32 + .../wlan/core/gen3/lint/mt6620.lnt | 87 + .../wlan/core/gen3/lint/mtk-sup.lnt | 27 + .../connectivity/wlan/core/gen3/lint/mtk.lnt | 169 + .../wlan/core/gen3/lint/options.lnt | 84 + .../connectivity/wlan/core/gen3/lint/std.lnt | 12 + .../connectivity/wlan/core/gen3/nic/cmd_buf.c | 275 + .../connectivity/wlan/core/gen3/nic/makefile | 8 + .../connectivity/wlan/core/gen3/nic/nic.c | 4128 +++++ .../wlan/core/gen3/nic/nic_cmd_event.c | 2263 +++ .../wlan/core/gen3/nic/nic_pwr_mgt.c | 507 + .../wlan/core/gen3/nic/nic_rate.c | 394 + .../connectivity/wlan/core/gen3/nic/nic_rx.c | 3995 +++++ .../connectivity/wlan/core/gen3/nic/nic_tx.c | 3485 +++++ .../connectivity/wlan/core/gen3/nic/p2p_nic.c | 201 + .../connectivity/wlan/core/gen3/nic/que_mgt.c | 6660 ++++++++ .../wlan/core/gen3/nic/sources.ce | 11 + .../wlan/core/gen3/nic/sources.ddk | 11 + .../connectivity/wlan/core/gen3/os/dirs | 3 + .../wlan/core/gen3/os/linux/gl_ate_agent.c | 1974 +++ .../wlan/core/gen3/os/linux/gl_bow.c | 1138 ++ .../wlan/core/gen3/os/linux/gl_cfg80211.c | 3305 ++++ .../wlan/core/gen3/os/linux/gl_hook_api.c | 3400 ++++ .../wlan/core/gen3/os/linux/gl_init.c | 2991 ++++ .../wlan/core/gen3/os/linux/gl_kal.c | 6032 ++++++++ .../wlan/core/gen3/os/linux/gl_p2p.c | 4190 +++++ .../wlan/core/gen3/os/linux/gl_p2p_cfg80211.c | 2262 +++ .../wlan/core/gen3/os/linux/gl_p2p_init.c | 159 + .../wlan/core/gen3/os/linux/gl_p2p_kal.c | 1580 ++ .../wlan/core/gen3/os/linux/gl_proc.c | 1588 ++ .../wlan/core/gen3/os/linux/gl_qa_agent.c | 7666 +++++++++ .../wlan/core/gen3/os/linux/gl_rst.c | 314 + .../wlan/core/gen3/os/linux/gl_vendor.c | 2423 +++ .../wlan/core/gen3/os/linux/gl_wext.c | 4295 ++++++ .../wlan/core/gen3/os/linux/gl_wext_priv.c | 4037 +++++ .../core/gen3/os/linux/hif/ahb_sdioLike/ahb.c | 1515 ++ .../os/linux/hif/ahb_sdioLike/ahb_cqdma.c | 493 + .../gen3/os/linux/hif/ahb_sdioLike/ahb_pdma.c | 457 + .../core/gen3/os/linux/hif/ahb_sdioLike/arm.c | 24 + .../os/linux/hif/ahb_sdioLike/include/hif.h | 282 + .../hif/ahb_sdioLike/include/hif_cqdma.h | 181 + .../linux/hif/ahb_sdioLike/include/hif_pdma.h | 143 + .../os/linux/hif/ahb_sdioLike/include/sdio.h | 319 + .../linux/hif/ahb_sdioLike/sdio_bus_driver.c | 434 + .../wlan/core/gen3/os/linux/hif/ehpi/arm.c | 506 + .../core/gen3/os/linux/hif/ehpi/colibri.c | 506 + .../wlan/core/gen3/os/linux/hif/ehpi/ehpi.c | 377 + .../gen3/os/linux/hif/ehpi/include/colibri.h | 154 + .../core/gen3/os/linux/hif/ehpi/include/hif.h | 101 + .../wlan/core/gen3/os/linux/hif/sdio/arm.c | 24 + .../core/gen3/os/linux/hif/sdio/include/hif.h | 153 + .../gen3/os/linux/hif/sdio/include/hif_sdio.h | 211 + .../os/linux/hif/sdio/include/mtk_porting.h | 55 + .../wlan/core/gen3/os/linux/hif/sdio/sdio.c | 1100 ++ .../wlan/core/gen3/os/linux/hif/sdio/x86.c | 24 + .../core/gen3/os/linux/include/gl_ate_agent.h | 154 + .../core/gen3/os/linux/include/gl_cfg80211.h | 340 + .../core/gen3/os/linux/include/gl_hook_api.h | 187 + .../wlan/core/gen3/os/linux/include/gl_kal.h | 1188 ++ .../wlan/core/gen3/os/linux/include/gl_os.h | 1003 ++ .../core/gen3/os/linux/include/gl_p2p_ioctl.h | 605 + .../core/gen3/os/linux/include/gl_p2p_kal.h | 230 + .../core/gen3/os/linux/include/gl_p2p_os.h | 283 + .../core/gen3/os/linux/include/gl_qa_agent.h | 228 + .../wlan/core/gen3/os/linux/include/gl_rst.h | 180 + .../wlan/core/gen3/os/linux/include/gl_sec.h | 36 + .../core/gen3/os/linux/include/gl_typedef.h | 244 + .../core/gen3/os/linux/include/gl_vendor.h | 921 ++ .../wlan/core/gen3/os/linux/include/gl_wext.h | 431 + .../core/gen3/os/linux/include/gl_wext_priv.h | 310 + .../wlan/core/gen3/os/linux/platform.c | 473 + .../connectivity/wlan/core/gen3/os/version.h | 99 + 85 files changed, 110793 insertions(+) create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/Android.mk create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/Makefile create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/README create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/common/debug.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/common/dump.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/common/fwcfg.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/common/makefile create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/common/sources.ce create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/common/sources.ddk create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/common/wlan_bow.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/common/wlan_lib.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/common/wlan_oid.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/common/wlan_p2p.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/lint/co.lnt create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/lint/mt6620.lnt create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/lint/mtk-sup.lnt create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/lint/mtk.lnt create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/lint/options.lnt create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/lint/std.lnt create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/cmd_buf.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/makefile create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/nic.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/nic_cmd_event.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/nic_pwr_mgt.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/nic_rate.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/nic_rx.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/nic_tx.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/p2p_nic.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/que_mgt.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/sources.ce create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/sources.ddk create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/dirs create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_ate_agent.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_bow.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_cfg80211.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_hook_api.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_init.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_kal.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_p2p.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_p2p_cfg80211.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_p2p_init.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_p2p_kal.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_proc.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_qa_agent.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_rst.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_vendor.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_wext.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_wext_priv.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/ahb.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/ahb_cqdma.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/ahb_pdma.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/arm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/include/hif.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/include/hif_cqdma.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/include/hif_pdma.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/include/sdio.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/sdio_bus_driver.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ehpi/arm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ehpi/colibri.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ehpi/ehpi.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ehpi/include/colibri.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ehpi/include/hif.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/sdio/arm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/sdio/include/hif.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/sdio/include/hif_sdio.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/sdio/include/mtk_porting.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/sdio/sdio.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/sdio/x86.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_ate_agent.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_cfg80211.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_hook_api.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_kal.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_os.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_p2p_ioctl.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_p2p_kal.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_p2p_os.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_qa_agent.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_rst.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_sec.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_typedef.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_vendor.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_wext.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_wext_priv.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/platform.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/os/version.h diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/Android.mk b/drivers/misc/mediatek/connectivity/wlan/core/gen3/Android.mk new file mode 100644 index 0000000000000..3c4dabb13da60 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/Android.mk @@ -0,0 +1,25 @@ +#copyright (C) 2016 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify it under the terms of the +# GNU General Public License version 2 as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with this program. +# If not, see . + +LOCAL_PATH := $(call my-dir) + +ifeq ($(MTK_WLAN_SUPPORT), yes) + +include $(CLEAR_VARS) +LOCAL_MODULE := wlan_drv_gen3.ko +LOCAL_PROPRIETARY_MODULE := true +LOCAL_MODULE_OWNER := mtk +LOCAL_REQUIRED_MODULES := wmt_chrdev_wifi.ko +include $(MTK_KERNEL_MODULE) + +endif + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/Makefile b/drivers/misc/mediatek/connectivity/wlan/core/gen3/Makefile new file mode 100644 index 0000000000000..51460ac391044 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/Makefile @@ -0,0 +1,262 @@ +MTK_PLATFORM := $(subst ",,$(CONFIG_MTK_PLATFORM)) +############################################################################### +# Necessary Check + +ifeq ($(AUTOCONF_H),) + $(error AUTOCONF_H is not defined) +endif + +ccflags-y += -imacros $(AUTOCONF_H) + +# Force build fail on modpost warning +KBUILD_MODPOST_FAIL_ON_WARNINGS := y +############################################################################### + +# --------------------------------------------------- +# Compile Options +# --------------------------------------------------- +ifneq ($(filter "CONSYS_6797" "CONSYS_6759" "CONSYS_6758" "CONSYS_6775" "CONSYS_6771", $(CONFIG_MTK_COMBO_CHIP)),) +WLAN_CHIP_ID=MT6631 +else +WLAN_CHIP_ID=MT6630 +endif +DRIVER_BUILD_DATE=$(shell date +%Y%m%d%H%M%S) +ccflags-y += -DDRIVER_BUILD_DATE='"$(DRIVER_BUILD_DATE)"' + +ccflags-y += -DLINUX -D$(WLAN_CHIP_ID) + +ccflags-y += -DCFG_SUPPORT_DEBUG_FS=0 +ccflags-y += -DWLAN_INCLUDE_PROC +ccflags-y += -DCFG_SUPPORT_AGPS_ASSIST=1 +ccflags-y += -DCFG_SUPPORT_TSF_USING_BOOTTIME=1 +ccflags-y += -DARP_MONITER_ENABLE=1 + +ifeq ($(CONFIG_MTK_AEE_FEATURE), y) + ccflags-y += -DCFG_SUPPORT_AEE=1 +else + ccflags-y += -DCFG_SUPPORT_AEE=0 +endif + +# Disable ASSERT() for user load, enable for others +ifneq ($(TARGET_BUILD_VARIANT),user) + ccflags-y += -DBUILD_QA_DBG=1 +else + ccflags-y += -DBUILD_QA_DBG=0 +endif + +ifeq ($(CONFIG_MTK_PASSPOINT_R2_SUPPORT), y) + ccflags-y += -DCFG_SUPPORT_PASSPOINT=1 + ccflags-y += -DCFG_HS20_DEBUG=1 + ccflags-y += -DCFG_ENABLE_GTK_FRAME_FILTER=1 +else + ccflags-y += -DCFG_SUPPORT_PASSPOINT=0 + ccflags-y += -DCFG_HS20_DEBUG=0 + ccflags-y += -DCFG_ENABLE_GTK_FRAME_FILTER=0 +endif + +MTK_MET_PROFILING_SUPPORT = yes +ifeq ($(MTK_MET_PROFILING_SUPPORT), yes) + ccflags-y += -DCFG_MET_PACKET_TRACE_SUPPORT=1 +else + ccflags-y += -DCFG_MET_PACKET_TRACE_SUPPORT=0 +endif + +ifeq ($(CONFIG_MTK_CONN_LTE_IDC_SUPPORT),y) + ccflags-y += -DWMT_IDC_SUPPORT=1 +else + ccflags-y += -DWMT_IDC_SUPPORT=0 +endif + + +ccflags-y += -DDBG=0 + +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat +ccflags-y += -I$(srctree)/drivers/misc/mediatek/emi/$(MTK_PLATFORM) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/emi/submodule +ccflags-y += -I$(srctree)/drivers/devfreq +ccflags-y += -I$(srctree)/drivers/misc/mediatek/pmic/include/ + +ifeq ($(WLAN_CHIP_ID), MT6631) +# temp disable emi_mpu on these platforms since it is not ready +ifneq ($(filter "CONSYS_6775" "CONSYS_6771", $(CONFIG_MTK_COMBO_CHIP)),) +ccflags-y += -DCFG_ENABLE_EMI_MPU=0 +else +ccflags-y += -DCFG_ENABLE_EMI_MPU=1 +endif +# Only MT6631 firmware support to set or get log level by UI +ccflags-y += -DCFG_SUPPORT_WIFI_FW_LOG_UI=1 +ccflags-y += -I$(src)/os -I$(src)/os/linux/include -I$(src)/os/linux/hif/ahb_sdioLike/include +else +ccflags-y += -D_HIF_SDIO=1 +ccflags-y += -I$(src)/os -I$(src)/os/linux/include -I$(src)/os/linux/hif/sdio/include +endif + +ccflags-y += -I$(src)/include -I$(src)/include/nic -I$(src)/include/mgmt +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include + +WMT_ANDROID_MK := $(TOP)/vendor/mediatek/kernel_modules/connectivity/common/Android.mk +ifeq (,$(wildcard $(WMT_ANDROID_MK))) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/connectivity/common/common_main/include +ccflags-y += -I$(srctree)/drivers/misc/mediatek/connectivity/common/common_main/linux/include +else +ccflags-y += -I$(TOP)/vendor/mediatek/kernel_modules/connectivity/common/common_main/include +ccflags-y += -I$(TOP)/vendor/mediatek/kernel_modules/connectivity/common/common_main/linux/include +endif +ccflags-y += -I$(srctree)/drivers/misc/mediatek/connectivity/common/ +ccflags-y += -D MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + +MODULE_NAME := wlan_drv_gen3 +obj-m += $(MODULE_NAME).o + +# --------------------------------------------------- +# Directory List +# --------------------------------------------------- +COMMON_DIR := common/ +OS_DIR := os/linux/ +NIC_DIR := nic/ +MGMT_DIR := mgmt/ +FWCFG_DIR := $(src)/$(MTK_PROJECT)/ + +ifeq ($(WLAN_CHIP_ID), MT6631) +HIF_DIR := os/linux/hif/ahb_sdioLike/ +PLAT_DIR := os/linux/plat/$(MTK_PLATFORM)/ +else +HIF_DIR := os/linux/hif/sdio/ +endif + +# --------------------------------------------------- +# Objects List +# --------------------------------------------------- + +COMMON_OBJS := $(COMMON_DIR)dump.o \ + $(COMMON_DIR)wlan_lib.o \ + $(COMMON_DIR)wlan_oid.o \ + $(COMMON_DIR)wlan_bow.o \ + $(COMMON_DIR)debug.o + +NIC_OBJS := $(NIC_DIR)nic.o \ + $(NIC_DIR)nic_tx.o \ + $(NIC_DIR)nic_rx.o \ + $(NIC_DIR)nic_pwr_mgt.o \ + $(NIC_DIR)nic_rate.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_ate_agent.o \ + $(OS_DIR)gl_qa_agent.o \ + $(OS_DIR)gl_hook_api.o \ + $(OS_DIR)gl_proc.o \ + $(OS_DIR)gl_rst.o \ + $(OS_DIR)gl_cfg80211.o \ + $(OS_DIR)gl_vendor.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)swcr.o \ + $(MGMT_DIR)roaming_fsm.o \ + $(MGMT_DIR)tkip_mic.o \ + $(MGMT_DIR)hs20.o \ + $(MGMT_DIR)tdls.o \ + $(MGMT_DIR)wnm.o \ + $(MGMT_DIR)qosmap.o \ + $(MGMT_DIR)wmm.o +# --------------------------------------------------- +# STATS Objects List +# --------------------------------------------------- +MGMT_OBJS += $(MGMT_DIR)stats.o + +# --------------------------------------------------- +# P2P Objects List +# --------------------------------------------------- + +COMMON_OBJS += $(COMMON_DIR)wlan_p2p.o + +NIC_OBJS += $(NIC_DIR)p2p_nic.o + +OS_OBJS += $(OS_DIR)gl_p2p.o \ + $(OS_DIR)gl_p2p_cfg80211.o \ + $(OS_DIR)gl_p2p_init.o \ + $(OS_DIR)gl_p2p_kal.o + +MGMT_OBJS += $(MGMT_DIR)p2p_dev_fsm.o \ + $(MGMT_DIR)p2p_dev_state.o \ + $(MGMT_DIR)p2p_role_fsm.o \ + $(MGMT_DIR)p2p_role_state.o \ + $(MGMT_DIR)p2p_func.o \ + $(MGMT_DIR)p2p_scan.o \ + $(MGMT_DIR)p2p_ie.o \ + $(MGMT_DIR)p2p_rlm.o \ + $(MGMT_DIR)p2p_assoc.o \ + $(MGMT_DIR)p2p_bss.o \ + $(MGMT_DIR)p2p_rlm_obss.o + +MGMT_OBJS += $(MGMT_DIR)wapi.o + + +HIF_OBJS := $(HIF_DIR)arm.o +ifeq ($(WLAN_CHIP_ID), MT6631) +HIF_OBJS += $(HIF_DIR)ahb.o\ + $(HIF_DIR)sdio_bus_driver.o + +ifeq ($(CONFIG_ARCH_MT6797), y) +ccflags-y += -DMT6797 +HIF_OBJS += $(HIF_DIR)ahb_pdma.o +else +HIF_OBJS += $(HIF_DIR)ahb_cqdma.o +endif +ifneq ($(wildcard $(src)/$(PLAT_DIR)plat_priv.c),) +PLAT_OBJS := $(PLAT_DIR)plat_priv.o +endif +$(MODULE_NAME)-objs += $(PLAT_OBJS) + +else +HIF_OBJS += $(HIF_DIR)sdio.o +endif + +# --------------------------------------------------- +# FW customization +# --------------------------------------------------- +FW_CUSTOMIZATION = y +ifeq ($(FW_CUSTOMIZATION), y) +ifneq ($(wildcard $(FWCFG_DIR)fw_config.c),) + COMMON_OBJS += $(MTK_PROJECT)/fw_config.o +endif + COMMON_OBJS += $(COMMON_DIR)fwcfg.o + ccflags-y += -DFW_CFG_SUPPORT + ccflags-y += -DENABLED_IN_ENGUSERDEBUG +endif +# --------------------------------------------------- + +$(MODULE_NAME)-objs += $(COMMON_OBJS) +$(MODULE_NAME)-objs += $(NIC_OBJS) +$(MODULE_NAME)-objs += $(OS_OBJS) +$(MODULE_NAME)-objs += $(HIF_OBJS) +$(MODULE_NAME)-objs += $(MGMT_OBJS) + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/README b/drivers/misc/mediatek/connectivity/wlan/core/gen3/README new file mode 100644 index 0000000000000..6fbe613656caf --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/README @@ -0,0 +1,2 @@ +Wlan gen3 driver - kernel modules move out of kernel tree + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/debug.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/debug.c new file mode 100644 index 0000000000000..d71c7a1352088 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/debug.c @@ -0,0 +1,738 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#include "precomp.h" + +#if (CFG_SUPPORT_DEBUG_STATISTICS == 1) +struct _PKT_STATUS_ENTRY { + UINT_8 u1Type; + UINT_16 u2IpId; + UINT_8 status; +}; + +struct _PKT_STATUS_RECORD { + struct _PKT_STATUS_ENTRY *pTxPkt; + struct _PKT_STATUS_ENTRY *pRxPkt; + UINT_32 u4TxIndex; + UINT_32 u4RxIndex; +}; + +#define PKT_STATUS_BUF_MAX_NUM 450 +#define PKT_STATUS_MSG_GROUP_RANGE 80 +#define PKT_STATUS_MSG_LENGTH 900 + +static PKT_STATUS_RECORD grPktStaRec; +#endif + +#if (CFG_SUPPORT_TRACE_TC4 == 1) +struct COMMAND { + UINT_8 ucCID; + BOOLEAN fgSetQuery; + BOOLEAN fgNeedResp; + UINT_8 ucCmdSeqNum; +}; + +struct SECURITY_FRAME { + UINT_16 u2EthType; + UINT_16 u2Reserved; +}; + +struct MGMT_FRAME { + UINT_16 u2FrameCtl; + UINT_16 u2DurationID; +}; + +typedef struct _TC_RES_RELEASE_ENTRY { + UINT_64 u8RelaseTime; + UINT_32 u4RelCID; + UINT_16 u2Tc4RelCnt; + UINT_16 u2AvailableTc4; +} TC_RES_RELEASE_ENTRY, *P_TC_RES_RELEASE_ENTRY; + +typedef struct _CMD_TRACE_ENTRY { + UINT_64 u8TxTime; + COMMAND_TYPE eCmdType; + union { + struct COMMAND rCmd; + struct SECURITY_FRAME rSecFrame; + struct MGMT_FRAME rMgmtFrame; + } u; +} CMD_TRACE_ENTRY, *P_CMD_TRACE_ENTRY; + +#define TC_RELEASE_TRACE_BUF_MAX_NUM 100 +#define TXED_CMD_TRACE_BUF_MAX_NUM 100 + +static P_TC_RES_RELEASE_ENTRY gprTcReleaseTraceBuffer; +static P_CMD_TRACE_ENTRY gprCmdTraceEntry; + +VOID wlanDebugTC4Init(VOID) +{ + /* debug for command/tc4 resource begin */ + gprTcReleaseTraceBuffer = + kalMemAlloc(TC_RELEASE_TRACE_BUF_MAX_NUM * sizeof(TC_RES_RELEASE_ENTRY), PHY_MEM_TYPE); + kalMemZero(gprTcReleaseTraceBuffer, TC_RELEASE_TRACE_BUF_MAX_NUM * sizeof(TC_RES_RELEASE_ENTRY)); + gprCmdTraceEntry = kalMemAlloc(TXED_CMD_TRACE_BUF_MAX_NUM * sizeof(CMD_TRACE_ENTRY), PHY_MEM_TYPE); + kalMemZero(gprCmdTraceEntry, TXED_CMD_TRACE_BUF_MAX_NUM * sizeof(CMD_TRACE_ENTRY)); + /* debug for command/tc4 resource end */ +} + +VOID wlanDebugTC4Uninit(VOID) +{ + /* debug for command/tc4 resource begin */ + kalMemFree(gprTcReleaseTraceBuffer, PHY_MEM_TYPE, + TC_RELEASE_TRACE_BUF_MAX_NUM * sizeof(TC_RES_RELEASE_ENTRY)); + kalMemFree(gprCmdTraceEntry, PHY_MEM_TYPE, TXED_CMD_TRACE_BUF_MAX_NUM * sizeof(CMD_TRACE_ENTRY)); + /* debug for command/tc4 resource end */ +} + +VOID wlanTraceTxCmd(P_CMD_INFO_T prCmd) +{ + static UINT_16 u2CurEntry; + P_CMD_TRACE_ENTRY prCurCmd = &gprCmdTraceEntry[u2CurEntry]; + + prCurCmd->u8TxTime = sched_clock(); + prCurCmd->eCmdType = prCmd->eCmdType; + if (prCmd->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) { + P_WLAN_MAC_MGMT_HEADER_T prMgmt = (P_WLAN_MAC_MGMT_HEADER_T)prCmd->prMsduInfo->prPacket; + + prCurCmd->u.rMgmtFrame.u2FrameCtl = prMgmt->u2FrameCtrl; + prCurCmd->u.rMgmtFrame.u2DurationID = prMgmt->u2Duration; + } else if (prCmd->eCmdType == COMMAND_TYPE_SECURITY_FRAME) { + PUINT_8 pucPkt = (PUINT_8)((struct sk_buff *)prCmd->prPacket)->data; + + prCurCmd->u.rSecFrame.u2EthType = + (pucPkt[ETH_TYPE_LEN_OFFSET] << 8) | (pucPkt[ETH_TYPE_LEN_OFFSET + 1]); + } else { + prCurCmd->u.rCmd.ucCID = prCmd->ucCID; + prCurCmd->u.rCmd.ucCmdSeqNum = prCmd->ucCmdSeqNum; + prCurCmd->u.rCmd.fgNeedResp = prCmd->fgNeedResp; + prCurCmd->u.rCmd.fgSetQuery = prCmd->fgSetQuery; + } + u2CurEntry++; + if (u2CurEntry == TC_RELEASE_TRACE_BUF_MAX_NUM) + u2CurEntry = 0; +} + +VOID wlanTraceReleaseTcRes(P_ADAPTER_T prAdapter, UINT_16 u2TxRlsCnt, UINT_16 u2Available) +{ + static UINT_16 u2CurEntry; + P_TC_RES_RELEASE_ENTRY prCurBuf = &gprTcReleaseTraceBuffer[u2CurEntry]; + /* Here we should wait FW to find right way to trace release CID */ + /* HAL_MCR_RD(prAdapter, MCR_D2HRM2R, &prCurBuf->u4RelCID); */ + prCurBuf->u8RelaseTime = sched_clock(); + prCurBuf->u2Tc4RelCnt = u2TxRlsCnt; + prCurBuf->u2AvailableTc4 = u2Available; + u2CurEntry++; + if (u2CurEntry == TXED_CMD_TRACE_BUF_MAX_NUM) + u2CurEntry = 0; +} + +VOID wlanDumpTcResAndTxedCmd(PUINT_8 pucBuf, UINT_32 maxLen) +{ + UINT_16 i = 0; + P_CMD_TRACE_ENTRY prCmd = gprCmdTraceEntry; + P_TC_RES_RELEASE_ENTRY prTcRel = gprTcReleaseTraceBuffer; + + if (pucBuf) { + int bufLen = 0; + + for (; i < TXED_CMD_TRACE_BUF_MAX_NUM/2; i++) { + bufLen = snprintf(pucBuf, maxLen, + "%d: Time %llu, Type %d, Content %08x; %d: Time %llu, Type %d, Content %08x\n", + i*2, prCmd[i*2].u8TxTime, prCmd[i*2].eCmdType, *(PUINT_32)(&prCmd[i*2].u.rCmd.ucCID), + i*2+1, prCmd[i*2+1].u8TxTime, prCmd[i*2+1].eCmdType, + *(PUINT_32)(&prCmd[i*2+1].u.rCmd.ucCID)); + if (bufLen <= 0) + break; + pucBuf += bufLen; + maxLen -= bufLen; + } + for (i = 0; i < TC_RELEASE_TRACE_BUF_MAX_NUM/2; i++) { + bufLen = snprintf(pucBuf, maxLen, + "%d: Time %llu, Tc4Cnt %d, Free %d, CID %08x; %d: Time %llu, Tc4Cnt %d, Free %d CID %08x\n", + i*2, prTcRel[i*2].u8RelaseTime, prTcRel[i*2].u2Tc4RelCnt, prTcRel[i*2].u2AvailableTc4, + prTcRel[i*2].u4RelCID, + i*2+1, prTcRel[i*2+1].u8RelaseTime, prTcRel[i*2+1].u2Tc4RelCnt, + prTcRel[i*2+1].u2AvailableTc4, prTcRel[i*2+1].u4RelCID); + if (bufLen <= 0) + break; + pucBuf += bufLen; + maxLen -= bufLen; + } + } else { + for (; i < TXED_CMD_TRACE_BUF_MAX_NUM/4; i++) { + LOG_FUNC("%d: Time %llu, Type %d, Content %08x; %d: Time %llu, Type %d, Content %08x; ", + i*4, prCmd[i*4].u8TxTime, prCmd[i*4].eCmdType, + *(PUINT_32)(&prCmd[i*4].u.rCmd.ucCID), + i*4+1, prCmd[i*4+1].u8TxTime, prCmd[i*4+1].eCmdType, + *(PUINT_32)(&prCmd[i*4+1].u.rCmd.ucCID)); + LOG_FUNC("%d: Time %llu, Type %d, Content %08x; %d: Time %llu, Type %d, Content %08x\n", + i*4+2, prCmd[i*4+2].u8TxTime, prCmd[i*4+2].eCmdType, + *(PUINT_32)(&prCmd[i*4+2].u.rCmd.ucCID), + i*4+3, prCmd[i*4+3].u8TxTime, prCmd[i*4+3].eCmdType, + *(PUINT_32)(&prCmd[i*4+3].u.rCmd.ucCID)); + } + for (i = 0; i < TC_RELEASE_TRACE_BUF_MAX_NUM/4; i++) { + LOG_FUNC( + "%d: Time %llu, Tc4Cnt %d, Free %d, CID %08x; %d: Time %llu, Tc4Cnt %d, Free %d, CID %08x;", + i*4, prTcRel[i*4].u8RelaseTime, prTcRel[i*4].u2Tc4RelCnt, + prTcRel[i*4].u2AvailableTc4, prTcRel[i*4].u4RelCID, + i*4+1, prTcRel[i*4+1].u8RelaseTime, prTcRel[i*4+1].u2Tc4RelCnt, + prTcRel[i*4+1].u2AvailableTc4, prTcRel[i*4+1].u4RelCID); + LOG_FUNC( + " %d: Time %llu, Tc4Cnt %d, Free %d, CID %08x; %d: Time %llu, Tc4Cnt %d, Free %d, CID %08x\n", + i*4+2, prTcRel[i*4+2].u8RelaseTime, prTcRel[i*4+2].u2Tc4RelCnt, + prTcRel[i*4+2].u2AvailableTc4, prTcRel[i*4+2].u4RelCID, + i*4+3, prTcRel[i*4+3].u8RelaseTime, prTcRel[i*4+3].u2Tc4RelCnt, + prTcRel[i*4+3].u2AvailableTc4, prTcRel[i*4+3].u4RelCID); + } + } +} +#endif + +#if (CFG_SUPPORT_DEBUG_STATISTICS == 1) +VOID wlanPktStatusDebugTraceInfoARP(UINT_8 status, UINT_8 eventType, UINT_16 u2ArpOpCode, PUINT_8 pucPkt) +{ + if (eventType == PKT_TX) + status = 0xFF; + wlanPktStatusDebugTraceInfo(status, eventType, ETH_P_ARP, 0, 0, u2ArpOpCode, pucPkt); +} + +VOID wlanPktStatusDebugTraceInfoIP(UINT_8 status, UINT_8 eventType, UINT_8 ucIpProto, UINT_16 u2IpId, PUINT_8 pucPkt) +{ + if (eventType == PKT_TX) + status = 0xFF; + wlanPktStatusDebugTraceInfo(status, eventType, ETH_P_IP, ucIpProto, u2IpId, 0, pucPkt); +} + +VOID wlanPktStatusDebugTraceInfo(UINT_8 status, UINT_8 eventType + , UINT_16 u2EtherType, UINT_8 ucIpProto, UINT_16 u2IpId, UINT_16 u2ArpOpCode, PUINT_8 pucPkt) +{ + struct _PKT_STATUS_ENTRY *prPktSta = NULL; + UINT_32 index; + + DBGLOG(TX, LOUD, "PKT id = 0x%02x, status =%d, Proto = %d, type =%d\n" + , u2IpId, status, ucIpProto, eventType); + do { + if (grPktStaRec.pTxPkt == NULL) { + DBGLOG(TX, ERROR, "pTxStaPkt is null point !"); + break; + } + + /* debug for Package info begin */ + if (eventType == PKT_TX) { + prPktSta = &grPktStaRec.pTxPkt[grPktStaRec.u4TxIndex]; + grPktStaRec.u4TxIndex++; + if (grPktStaRec.u4TxIndex == PKT_STATUS_BUF_MAX_NUM) { + DBGLOG(TX, INFO, "grPktStaRec.u4TxIndex reset"); + grPktStaRec.u4TxIndex = 0; + } + } else if (eventType == PKT_RX) { + prPktSta = &grPktStaRec.pRxPkt[grPktStaRec.u4RxIndex]; + grPktStaRec.u4RxIndex++; + if (grPktStaRec.u4RxIndex == PKT_STATUS_BUF_MAX_NUM) { + DBGLOG(TX, INFO, "grPktStaRec.u4RxIndex reset"); + grPktStaRec.u4RxIndex = 0; + } + } + + if (prPktSta) { + prPktSta->u1Type = kalGetPktEtherType(pucPkt); + prPktSta->status = status; + prPktSta->u2IpId = u2IpId; + } + + /* Update tx status */ + if (eventType == PKT_TX_DONE) { + /* Support Ethernet type = IP*/ + if (u2EtherType == ETH_P_IP) { + for (index = 0; index < PKT_STATUS_BUF_MAX_NUM; index++) { + if (grPktStaRec.pTxPkt[index].u2IpId == u2IpId) { + grPktStaRec.pTxPkt[index].status = status; + DBGLOG(TX, INFO, "Status: PKT_TX_DONE match\n"); + break; + } + } + } + } + } while (FALSE); +} + +VOID wlanPktStatusDebugDumpInfo(P_ADAPTER_T prAdapter) +{ + UINT_32 i; + UINT_32 index; + UINT_32 offsetMsg; + struct _PKT_STATUS_ENTRY *prPktInfo; + UINT_8 pucMsg[PKT_STATUS_MSG_LENGTH]; + UINT_32 u4PktCnt; + + do { + + if (grPktStaRec.pTxPkt == NULL || grPktStaRec.pRxPkt == NULL) + break; + + if (grPktStaRec.u4TxIndex == 0 && grPktStaRec.u4RxIndex == 0) + break; + + DBGLOG(TX, INFO, "Pkt dump: TxCnt %d, RxCnt %d\n", grPktStaRec.u4TxIndex, grPktStaRec.u4RxIndex); + offsetMsg = 0; + /* start dump pkt info of tx/rx by decrease timestap */ + for (i = 0 ; i < 2 ; i++) { + if (i == 0) + u4PktCnt = grPktStaRec.u4TxIndex; + else + u4PktCnt = grPktStaRec.u4RxIndex; + + for (index = 0; index < u4PktCnt; index++) { + if (i == 0) + prPktInfo = &grPktStaRec.pTxPkt[index]; + else + prPktInfo = &grPktStaRec.pRxPkt[index]; + /*ucIpProto = 0x01 ICMP */ + /*ucIpProto = 0x11 UPD */ + /*ucIpProto = 0x06 TCP */ + offsetMsg += kalSnprintf(pucMsg + offsetMsg + , PKT_STATUS_MSG_LENGTH + , "%d,%02x,%x" + , prPktInfo->u1Type + , prPktInfo->u2IpId + , prPktInfo->status); + + if (((index + 1) % PKT_STATUS_MSG_GROUP_RANGE == 0) || (index == (u4PktCnt - 1))) { + if (i == 0) + DBGLOG(TX, INFO, "%s\n", pucMsg); + else if (i == 1) + DBGLOG(RX, INFO, "%s\n", pucMsg); + + offsetMsg = 0; + kalMemSet(pucMsg, '\0', PKT_STATUS_MSG_LENGTH); + } + } + } + } while (FALSE); + u4PktCnt = grPktStaRec.u4TxIndex = 0; + u4PktCnt = grPktStaRec.u4RxIndex = 0; +} +#endif + +VOID wlanDebugTC4AndPktInit(VOID) +{ +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanDebugTC4Init(); +#endif +#if (CFG_SUPPORT_DEBUG_STATISTICS == 1) + /* debug for package info begin */ + grPktStaRec.pTxPkt = kalMemAlloc(PKT_STATUS_BUF_MAX_NUM * sizeof(PKT_STATUS_ENTRY), VIR_MEM_TYPE); + kalMemZero(grPktStaRec.pTxPkt, PKT_STATUS_BUF_MAX_NUM * sizeof(PKT_STATUS_ENTRY)); + grPktStaRec.u4TxIndex = 0; + grPktStaRec.pRxPkt = kalMemAlloc(PKT_STATUS_BUF_MAX_NUM * sizeof(PKT_STATUS_ENTRY), VIR_MEM_TYPE); + kalMemZero(grPktStaRec.pRxPkt, PKT_STATUS_BUF_MAX_NUM * sizeof(PKT_STATUS_ENTRY)); + grPktStaRec.u4RxIndex = 0; + /* debug for package info end */ +#endif +} + +VOID wlanDebugTC4AndPktUninit(VOID) +{ +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanDebugTC4Uninit(); +#endif +#if (CFG_SUPPORT_DEBUG_STATISTICS == 1) + + /* debug for package status info begin */ + kalMemFree(grPktStaRec.pTxPkt, VIR_MEM_TYPE, PKT_STATUS_BUF_MAX_NUM * sizeof(PKT_STATUS_ENTRY)); + grPktStaRec.u4TxIndex = 0; + kalMemFree(grPktStaRec.pRxPkt, VIR_MEM_TYPE, PKT_STATUS_BUF_MAX_NUM * sizeof(PKT_STATUS_ENTRY)); + grPktStaRec.u4RxIndex = 0; + /* debug for package status info end */ +#endif +} + +static UINT_32 gu4LogLevel[ENUM_WIFI_LOG_MODULE_NUM]; + +VOID wlanDbgLogLevelInit(VOID) +{ + UINT_32 u4LogLevel = ENUM_WIFI_LOG_LEVEL_OFF; +#if DBG + /* Adjust log level to extreme in DBG mode */ + wlanDbgSetGlobalLogLevel(ENUM_WIFI_LOG_MODULE_DRIVER, ENUM_WIFI_LOG_LEVEL_EXTREME); + wlanDbgSetGlobalLogLevel(ENUM_WIFI_LOG_MODULE_FW, ENUM_WIFI_LOG_LEVEL_EXTREME); +#else + wlanDbgSetGlobalLogLevel(ENUM_WIFI_LOG_MODULE_DRIVER, ENUM_WIFI_LOG_LEVEL_OFF); + wlanDbgSetGlobalLogLevel(ENUM_WIFI_LOG_MODULE_FW, ENUM_WIFI_LOG_LEVEL_OFF); +#endif /* DBG */ + + /* Set driver level first, and set fw log level until fw is ready */ + wlanDbgGetGlobalLogLevel(ENUM_WIFI_LOG_MODULE_DRIVER, &u4LogLevel); + wlanDbgSetLogLevelImpl(NULL, + ENUM_WIFI_LOG_LEVEL_VERSION_V1, + ENUM_WIFI_LOG_MODULE_DRIVER, + u4LogLevel); +} + +VOID wlanDbgLogLevelUninit(VOID) +{ + UINT_8 i; + UINT_32 u4DriverLevel = ENUM_WIFI_LOG_LEVEL_OFF; + UINT_32 u4FWLevel = ENUM_WIFI_LOG_LEVEL_OFF; + + /* re-enable printk too much detection */ + wlanDbgGetGlobalLogLevel(ENUM_WIFI_LOG_MODULE_DRIVER, &u4DriverLevel); + wlanDbgGetGlobalLogLevel(ENUM_WIFI_LOG_MODULE_FW, &u4FWLevel); + if (u4DriverLevel > ENUM_WIFI_LOG_LEVEL_OFF || + u4FWLevel > ENUM_WIFI_LOG_LEVEL_OFF) { +#ifdef CONFIG_LOG_TOO_MUCH_WARNING + set_logtoomuch_enable(1); +#endif + wlanDbgSetGlobalLogLevel(ENUM_WIFI_LOG_MODULE_DRIVER, ENUM_WIFI_LOG_LEVEL_OFF); + wlanDbgSetGlobalLogLevel(ENUM_WIFI_LOG_MODULE_FW, ENUM_WIFI_LOG_LEVEL_OFF); + for (i = 0; i < DBG_MODULE_NUM; i++) + aucDebugModule[i] = DBG_LOG_LEVEL_OFF; + } + +} + +UINT_32 wlanDbgLevelUiSupport(IN P_ADAPTER_T prAdapter, UINT_32 u4Version, UINT_32 ucModule) +{ + UINT_32 u4Enable = ENUM_WIFI_LOG_LEVEL_SUPPORT_DISABLE; + + switch (u4Version) { + case ENUM_WIFI_LOG_LEVEL_VERSION_V1: + switch (ucModule) { + case ENUM_WIFI_LOG_MODULE_DRIVER: + u4Enable = ENUM_WIFI_LOG_LEVEL_SUPPORT_ENABLE; + break; + case ENUM_WIFI_LOG_MODULE_FW: +#if CFG_SUPPORT_WIFI_FW_LOG_UI + u4Enable = ENUM_WIFI_LOG_LEVEL_SUPPORT_ENABLE; +#else + u4Enable = ENUM_WIFI_LOG_LEVEL_SUPPORT_DISABLE; +#endif + break; + } + break; + default: + break; + } + + return u4Enable; +} + +UINT_32 wlanDbgGetLogLevelImpl(IN P_ADAPTER_T prAdapter, UINT_32 u4Version, + UINT_32 ucModule) +{ + UINT_32 u4Level = ENUM_WIFI_LOG_LEVEL_OFF; + + switch (u4Version) { + case ENUM_WIFI_LOG_LEVEL_VERSION_V1: + wlanDbgGetGlobalLogLevel(ucModule, &u4Level); + break; + default: + break; + } + return u4Level; +} + +VOID wlanDbgSetLogLevelImpl(IN P_ADAPTER_T prAdapter, UINT_32 u4Version, + UINT_32 u4Module, UINT_32 u4level) +{ +#ifdef CONFIG_LOG_TOO_MUCH_WARNING + UINT_32 u4DriverLevel = ENUM_WIFI_LOG_LEVEL_OFF; + UINT_32 u4FWLevel = ENUM_WIFI_LOG_LEVEL_OFF; +#endif + if (u4level >= ENUM_WIFI_LOG_LEVEL_NUM) + return; + + switch (u4Version) { + case ENUM_WIFI_LOG_LEVEL_VERSION_V1: + wlanDbgSetGlobalLogLevel(u4Module, u4level); + switch (u4Module) { + case ENUM_WIFI_LOG_MODULE_DRIVER: + { + UINT_8 i; + UINT_32 u4DriverLogMask; + + if (u4level == ENUM_WIFI_LOG_LEVEL_OFF) + u4DriverLogMask = DBG_LOG_LEVEL_OFF; + else if (u4level == ENUM_WIFI_LOG_LEVEL_DEFAULT) + u4DriverLogMask = DBG_LOG_LEVEL_DEFAULT; + else + u4DriverLogMask = DBG_LOG_LEVEL_EXTREME; + + for (i = 0; i < DBG_MODULE_NUM; i++) + aucDebugModule[i] = u4DriverLogMask & DBG_CLASS_MASK; + } + break; + case ENUM_WIFI_LOG_MODULE_FW: + { + struct CMD_EVENT_LOG_LEVEL cmd; + + kalMemZero(&cmd, sizeof(struct CMD_EVENT_LOG_LEVEL)); + cmd.u4Version = u4Version; + cmd.u4LogLevel = u4level; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_WIFI_LOG_LEVEL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_EVENT_LOG_LEVEL), (PUINT_8)&cmd, NULL, 0); + } + break; + default: + break; + } + break; + default: + break; + } +#ifdef CONFIG_LOG_TOO_MUCH_WARNING + wlanDbgGetGlobalLogLevel(ENUM_WIFI_LOG_MODULE_DRIVER, &u4DriverLevel); + wlanDbgGetGlobalLogLevel(ENUM_WIFI_LOG_MODULE_FW, &u4FWLevel); + if (u4DriverLevel > ENUM_WIFI_LOG_LEVEL_OFF || + u4FWLevel > ENUM_WIFI_LOG_LEVEL_OFF) { + DBGLOG(OID, INFO, + "Disable printk to much. driver: %d, fw: %d\n", + u4DriverLevel, + u4FWLevel); + set_logtoomuch_enable(0); + } +#endif +} + +VOID wlanDbgLevelSync(VOID) +{ + UINT_8 i = 0; + UINT_32 u4PorcLogLevel = DBG_CLASS_MASK; + UINT_32 u4DriverLogLevel = ENUM_WIFI_LOG_LEVEL_OFF; + + /* get the lowest level as module's level */ + for (i = 0; i < DBG_MODULE_NUM; i++) + u4PorcLogLevel &= aucDebugModule[i]; + + if (u4PorcLogLevel & ENUM_WIFI_LOG_LEVEL_EXTREME) + u4DriverLogLevel = ENUM_WIFI_LOG_LEVEL_EXTREME; + else if (u4PorcLogLevel & ENUM_WIFI_LOG_LEVEL_DEFAULT) + u4DriverLogLevel = ENUM_WIFI_LOG_LEVEL_DEFAULT; + else + u4DriverLogLevel = ENUM_WIFI_LOG_LEVEL_OFF; + + wlanDbgSetGlobalLogLevel(ENUM_WIFI_LOG_MODULE_DRIVER, u4DriverLogLevel); +} + +BOOLEAN wlanDbgGetGlobalLogLevel(UINT_32 u4Module, UINT_32 *pu4Level) +{ + if (u4Module != ENUM_WIFI_LOG_MODULE_DRIVER && u4Module != ENUM_WIFI_LOG_MODULE_FW) + return FALSE; + + *pu4Level = gu4LogLevel[u4Module]; + return TRUE; +} +BOOLEAN wlanDbgSetGlobalLogLevel(UINT_32 u4Module, UINT_32 u4Level) +{ + if (u4Module != ENUM_WIFI_LOG_MODULE_DRIVER && u4Module != ENUM_WIFI_LOG_MODULE_FW) + return FALSE; + + gu4LogLevel[u4Module] = u4Level; + return TRUE; +} + +#if CFG_SUPPORT_MGMT_FRAME_DEBUG +#define MGMG_FRAME_MAX_LENGTH (WLAN_MAC_MGMT_HEADER_LEN + CFG_CFG80211_IE_BUF_LEN) +#define MGMG_FRAME_MAX_NUM 6 + +struct MGMT_FRAME_ENTRY { + UINT_32 u4Length; + UINT_8 aucFrameBody[MGMG_FRAME_MAX_LENGTH]; +}; + +struct SAA_MGMT_RECORD { + struct MGMT_FRAME_ENTRY *pMgmtFrame; + UINT_32 u4MgmtIndex; +}; + +static struct SAA_MGMT_RECORD grSaaMgmtRec; +#endif + +#if CFG_SUPPORT_MGMT_FRAME_DEBUG +VOID wlanMgmtFrameDebugInit(VOID) +{ + grSaaMgmtRec.pMgmtFrame = kalMemAlloc(MGMG_FRAME_MAX_NUM * sizeof(struct MGMT_FRAME_ENTRY), VIR_MEM_TYPE); + if (grSaaMgmtRec.pMgmtFrame) + kalMemZero(grSaaMgmtRec.pMgmtFrame, MGMG_FRAME_MAX_NUM * sizeof(struct MGMT_FRAME_ENTRY)); + grSaaMgmtRec.u4MgmtIndex = 0; +} + +VOID wlanMgmtFrameDebugUnInit(VOID) +{ + if (grSaaMgmtRec.pMgmtFrame) + kalMemFree(grSaaMgmtRec.pMgmtFrame, VIR_MEM_TYPE, MGMG_FRAME_MAX_NUM * sizeof(struct MGMT_FRAME_ENTRY)); + grSaaMgmtRec.u4MgmtIndex = 0; +} + +VOID wlanMgmtFrameDebugReset(VOID) +{ + UINT_8 uIndex = 0; + struct MGMT_FRAME_ENTRY *prMgmtFrame = NULL; + + if (!grSaaMgmtRec.pMgmtFrame) { + DBGLOG(SAA, WARN, "grSaaMgmtRec.pMgmtFrame is NULL!"); + return; + } + + for (uIndex = 0; uIndex < MGMG_FRAME_MAX_NUM; uIndex++) { + prMgmtFrame = &grSaaMgmtRec.pMgmtFrame[uIndex]; + kalMemZero(prMgmtFrame->aucFrameBody, MGMG_FRAME_MAX_LENGTH); + prMgmtFrame->u4Length = 0; + } + grSaaMgmtRec.u4MgmtIndex = 0; +} + +VOID wlanMgmtFrameDebugAdd(IN PUINT_8 pucStartAddr, IN UINT_32 u4Length) +{ + struct MGMT_FRAME_ENTRY *prMgmtFrame = NULL; + + if (!grSaaMgmtRec.pMgmtFrame) { + DBGLOG(SAA, WARN, "grSaaMgmtRec.pMgmtFrame is NULL!"); + return; + } + + if (grSaaMgmtRec.u4MgmtIndex == MGMG_FRAME_MAX_NUM) { + DBGLOG(SAA, INFO, "Management frame buffer full, dump old records."); + wlanMgmtFrameDebugDump(); + } + + if (grSaaMgmtRec.u4MgmtIndex < MGMG_FRAME_MAX_NUM) { + prMgmtFrame = &grSaaMgmtRec.pMgmtFrame[grSaaMgmtRec.u4MgmtIndex]; + if (u4Length < MGMG_FRAME_MAX_LENGTH) { + kalMemCopy(prMgmtFrame->aucFrameBody, pucStartAddr, u4Length); + prMgmtFrame->u4Length = u4Length; + } else { + kalMemCopy(prMgmtFrame->aucFrameBody, pucStartAddr, MGMG_FRAME_MAX_LENGTH); + prMgmtFrame->u4Length = MGMG_FRAME_MAX_LENGTH; + } + grSaaMgmtRec.u4MgmtIndex++; + } +} + +VOID wlanMgmtFrameDebugDump(VOID) +{ + UINT_8 uIndex = 0; + struct MGMT_FRAME_ENTRY *prMgmtFrame = NULL; + + if (!grSaaMgmtRec.pMgmtFrame) { + DBGLOG(SAA, WARN, "grSaaMgmtRec.pMgmtFrame is NULL!"); + return; + } + + if (grSaaMgmtRec.u4MgmtIndex > MGMG_FRAME_MAX_NUM) { + DBGLOG(SAA, WARN, "grSaaMgmtRec.u4MgmtIndex(%d) exceeds maximum value!", + grSaaMgmtRec.u4MgmtIndex); + grSaaMgmtRec.u4MgmtIndex = MGMG_FRAME_MAX_NUM; + } + + for (uIndex = 0; uIndex < grSaaMgmtRec.u4MgmtIndex; uIndex++) { + prMgmtFrame = &grSaaMgmtRec.pMgmtFrame[uIndex]; + dumpMemory8(prMgmtFrame->aucFrameBody, prMgmtFrame->u4Length); + kalMemZero(prMgmtFrame->aucFrameBody, MGMG_FRAME_MAX_LENGTH); + prMgmtFrame->u4Length = 0; + } + grSaaMgmtRec.u4MgmtIndex = 0; +} +#endif + +VOID wlanPrintFwLog(PUINT_8 pucLogContent, UINT_16 u2MsgSize, UINT_8 ucMsgType) +{ +#define OLD_KBUILD_MODNAME KBUILD_MODNAME +#define OLD_LOG_FUNC LOG_FUNC +#undef KBUILD_MODNAME +#undef LOG_FUNC +#define KBUILD_MODNAME "wlan_gen3_fw" +#define LOG_FUNC pr_info + + if (u2MsgSize > DEBUG_MSG_SIZE_MAX - 1) { + LOG_FUNC("Firmware Log Size(%d) is too large, type %d\n", u2MsgSize, ucMsgType); + return; + } + switch (ucMsgType) { + case DEBUG_MSG_TYPE_ASCII: + pucLogContent[u2MsgSize] = '\0'; + LOG_FUNC("%s\n", pucLogContent); + break; + case DEBUG_MSG_TYPE_MEM8: + DBGLOG_MEM8(RX, INFO, pucLogContent, u2MsgSize); + break; + default: + DBGLOG_MEM32(RX, INFO, (PUINT_32)pucLogContent, u2MsgSize); + break; + } + +#undef KBUILD_MODNAME +#undef LOG_FUNC +#define KBUILD_MODNAME OLD_KBUILD_MODNAME +#define LOG_FUNC OLD_LOG_FUNC +#undef OLD_KBUILD_MODNAME +#undef OLD_LOG_FUNC +} + +/* Begin: Functions used to breakdown packet jitter, for test case VoE 5.7 */ +static VOID wlanSetBE32(UINT_32 u4Val, PUINT_8 pucBuf) +{ + PUINT_8 littleEn = (PUINT_8)&u4Val; + + pucBuf[0] = littleEn[3]; + pucBuf[1] = littleEn[2]; + pucBuf[2] = littleEn[1]; + pucBuf[3] = littleEn[0]; +} + +VOID wlanFillTimestamp(P_ADAPTER_T prAdapter, PVOID pvPacket, UINT_8 ucPhase) +{ + struct sk_buff *skb = (struct sk_buff *)pvPacket; + PUINT_8 pucEth = NULL; + UINT_32 u4Length = 0; + PUINT_8 pucUdp = NULL; + struct timeval tval; + + if (!prAdapter || !prAdapter->rDebugInfo.fgVoE5_7Test || !skb) + return; + pucEth = skb->data; + u4Length = skb->len; + if (u4Length < 200 || + ((pucEth[ETH_TYPE_LEN_OFFSET] << 8) | (pucEth[ETH_TYPE_LEN_OFFSET + 1])) != ETH_P_IPV4) + return; + if (pucEth[ETH_HLEN+9] != IP_PRO_UDP) + return; + pucUdp = &pucEth[ETH_HLEN+28]; + if (kalStrnCmp(pucUdp, "1345678", 7)) + return; + do_gettimeofday(&tval); + switch (ucPhase) { + case PHASE_XMIT_RCV: /* xmit */ + pucUdp += 20; + break; + case PHASE_ENQ_QM: /* enq */ + pucUdp += 28; + break; + case PHASE_HIF_TX: /* tx */ + pucUdp += 36; + break; + } + wlanSetBE32(tval.tv_sec, pucUdp); + wlanSetBE32(tval.tv_usec, pucUdp+4); +} +/* End: Functions used to breakdown packet jitter, for test case VoE 5.7 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/dump.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/dump.c new file mode 100644 index 0000000000000..e378be266224e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/dump.c @@ -0,0 +1,327 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/common/dump.c#1 + */ + +/* + * ! \file "dump.c" + * \brief Provide memory dump function for debugging. + * + * Provide memory dump function for debugging. + */ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to dump a segment of memory in bytes. +* +* \param[in] pucStartAddr Pointer to the starting address of the memory to be dumped. +* \param[in] u4Length Length of the memory to be dumped. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID dumpMemory8(IN PUINT_8 pucStartAddr, IN UINT_32 u4Length) +{ + ASSERT(pucStartAddr); + + LOG_FUNC("DUMP8 ADDRESS: %p, Length: %u\n", pucStartAddr, u4Length); + + while (u4Length > 0) { + if (u4Length >= 16) { + LOG_FUNC( + "(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x %02x %02x %02x\n", + pucStartAddr, pucStartAddr[0], pucStartAddr[1], + pucStartAddr[2], pucStartAddr[3], pucStartAddr[4], pucStartAddr[5], + pucStartAddr[6], pucStartAddr[7], pucStartAddr[8], pucStartAddr[9], + pucStartAddr[10], pucStartAddr[11], pucStartAddr[12], + pucStartAddr[13], pucStartAddr[14], pucStartAddr[15]); + u4Length -= 16; + pucStartAddr += 16; + } else { + switch (u4Length) { + case 1: + LOG_FUNC("(%p) %02x\n", pucStartAddr, pucStartAddr[0]); + break; + case 2: + LOG_FUNC("(%p) %02x %02x\n", pucStartAddr, pucStartAddr[0], pucStartAddr[1]); + break; + case 3: + LOG_FUNC("(%p) %02x %02x %02x\n", + pucStartAddr, pucStartAddr[0], pucStartAddr[1], pucStartAddr[2]); + break; + case 4: + LOG_FUNC("(%p) %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3]); + break; + case 5: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4]); + break; + case 6: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5]); + break; + case 7: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6]); + break; + case 8: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7]); + break; + case 9: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8]); + break; + case 10: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8], pucStartAddr[9]); + break; + case 11: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8], pucStartAddr[9], pucStartAddr[10]); + break; + case 12: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8], pucStartAddr[9], pucStartAddr[10], pucStartAddr[11]); + break; + case 13: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8], pucStartAddr[9], pucStartAddr[10], pucStartAddr[11], + pucStartAddr[12]); + break; + case 14: + LOG_FUNC( + "(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8], pucStartAddr[9], pucStartAddr[10], pucStartAddr[11], + pucStartAddr[12], pucStartAddr[13]); + break; + case 15: + LOG_FUNC( + "(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8], pucStartAddr[9], pucStartAddr[10], pucStartAddr[11], + pucStartAddr[12], pucStartAddr[13], pucStartAddr[14]); + break; + } + u4Length = 0; + } + } + + LOG_FUNC("\n"); +} /* end of dumpMemory8() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to dump a segment of memory in double words. +* +* \param[in] pucStartAddr Pointer to the starting address of the memory to be dumped. +* \param[in] u4Length Length of the memory to be dumped. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID dumpMemory32(IN PUINT_32 pu4StartAddr, IN UINT_32 u4Length) +{ + PUINT_8 pucAddr; + + ASSERT(pu4StartAddr); + + LOG_FUNC("DUMP32 ADDRESS: %p, Length: %u\n", pu4StartAddr, u4Length); + + if (IS_NOT_ALIGN_4((ULONG) pu4StartAddr)) { + UINT_32 u4ProtrudeLen = sizeof(UINT_32) - ((ULONG) pu4StartAddr % 4); + + u4ProtrudeLen = ((u4Length < u4ProtrudeLen) ? u4Length : u4ProtrudeLen); + LOG_FUNC("pu4StartAddr is not at DW boundary.\n"); + pucAddr = (PUINT_8) &pu4StartAddr[0]; + + switch (u4ProtrudeLen) { + case 1: + LOG_FUNC("(%p) %02x------\n", pu4StartAddr, pucAddr[0]); + break; + case 2: + LOG_FUNC("(%p) %02x%02x----\n", pu4StartAddr, pucAddr[1], pucAddr[0]); + break; + case 3: + LOG_FUNC("(%p) %02x%02x%02x--\n", pu4StartAddr, pucAddr[2], pucAddr[1], pucAddr[0]); + break; + default: + break; + } + + u4Length -= u4ProtrudeLen; + pu4StartAddr = (PUINT_32) ((ULONG) pu4StartAddr + u4ProtrudeLen); + } + + while (u4Length > 0) { + if (u4Length >= 16) { + LOG_FUNC("(%p) %08x %08x %08x %08x\n", + pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2], pu4StartAddr[3]); + pu4StartAddr += 4; + u4Length -= 16; + } else { + switch (u4Length) { + case 1: + pucAddr = (PUINT_8) &pu4StartAddr[0]; + LOG_FUNC("(%p) ------%02x\n", pu4StartAddr, pucAddr[0]); + break; + case 2: + pucAddr = (PUINT_8) &pu4StartAddr[0]; + LOG_FUNC("(%p) ----%02x%02x\n", pu4StartAddr, pucAddr[1], pucAddr[0]); + break; + case 3: + pucAddr = (PUINT_8) &pu4StartAddr[0]; + LOG_FUNC("(%p) --%02x%02x%02x\n", pu4StartAddr, pucAddr[2], pucAddr[1], pucAddr[0]); + break; + case 4: + LOG_FUNC("(%p) %08x\n", pu4StartAddr, pu4StartAddr[0]); + break; + case 5: + pucAddr = (PUINT_8) &pu4StartAddr[1]; + LOG_FUNC("(%p) %08x ------%02x\n", pu4StartAddr, pu4StartAddr[0], pucAddr[0]); + break; + case 6: + pucAddr = (PUINT_8) &pu4StartAddr[1]; + LOG_FUNC("(%p) %08x ----%02x%02x\n", + pu4StartAddr, pu4StartAddr[0], pucAddr[1], pucAddr[0]); + break; + case 7: + pucAddr = (PUINT_8) &pu4StartAddr[1]; + LOG_FUNC("(%p) %08x --%02x%02x%02x\n", + pu4StartAddr, pu4StartAddr[0], pucAddr[2], pucAddr[1], pucAddr[0]); + break; + case 8: + LOG_FUNC("(%p) %08x %08x\n", pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1]); + break; + case 9: + pucAddr = (PUINT_8) &pu4StartAddr[2]; + LOG_FUNC("(%p) %08x %08x ------%02x\n", + pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1], pucAddr[0]); + break; + case 10: + pucAddr = (PUINT_8) &pu4StartAddr[2]; + LOG_FUNC("(%p) %08x %08x ----%02x%02x\n", + pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1], pucAddr[1], pucAddr[0]); + break; + case 11: + pucAddr = (PUINT_8) &pu4StartAddr[2]; + LOG_FUNC("(%p) %08x %08x --%02x%02x%02x\n", + pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], pucAddr[2], pucAddr[1], pucAddr[0]); + break; + case 12: + LOG_FUNC("(%p) %08x %08x %08x\n", + pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2]); + break; + case 13: + pucAddr = (PUINT_8) &pu4StartAddr[3]; + LOG_FUNC("(%p) %08x %08x %08x ------%02x\n", + pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2], pucAddr[0]); + break; + case 14: + pucAddr = (PUINT_8) &pu4StartAddr[3]; + LOG_FUNC("(%p) %08x %08x %08x ----%02x%02x\n", + pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2], pucAddr[1], pucAddr[0]); + break; + case 15: + pucAddr = (PUINT_8) &pu4StartAddr[3]; + LOG_FUNC("(%p) %08x %08x %08x --%02x%02x%02x\n", + pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2], + pucAddr[2], pucAddr[1], pucAddr[0]); + break; + } + u4Length = 0; + } + } +} /* end of dumpMemory32() */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/fwcfg.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/fwcfg.c new file mode 100644 index 0000000000000..0c185227bf2e4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/fwcfg.c @@ -0,0 +1,377 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file fwcfg.c +* \brief Main routines of Linux driver +* +* This file contains the main routines of Linux driver for MediaTek Inc. 802.11 +* Wireless LAN Adapters. +*/ + +#include "fwcfg.h" + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static char *strtok_r(char *s, const char *delim, char **last); +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +struct _FW_CFG __weak fwCfgArray[] = { +}; +#ifdef CFG_SUPPORT_COEX_IOT_AP +/* + * Currently,Just supports Coex IOT AP List, + * Please don't add other type of IOT AP into arrary as below, + * Otherwise it could cause to unexpected exception! + */ +struct FwCfgForIotAP fwCfgIotAP[] = { + { + COEX_ISSUE_TYPE_ID, + {0x80, 0x89, 0x17, 0x00, 0x00, 0x00}, + {0xff, 0xff, 0xff, 0x00, 0x00, 0x00}, + "A2DPUseCTS2Self 1", + "A2DPUseCTS2Self 0", + }, + { + COEX_ISSUE_TYPE_ID, + {0x6c, 0xe8, 0x73, 0x00, 0x00, 0x00}, + {0xff, 0xff, 0xff, 0x00, 0x00, 0x00}, + "A2DPUseCTS2Self 1", + "A2DPUseCTS2Self 0", + }, + +}; +#endif +/* ****************************************************************************** +* F U N C T I O N S +********************************************************************************* +*/ +INT_32 __weak getFwCfgItemNum() +{ + return ARRAY_SIZE(fwCfgArray); +} + +PUINT_8 __weak getFwCfgItemKey(UINT_8 i) +{ + if (i < ARRAY_SIZE(fwCfgArray)) + return fwCfgArray[i].key; + else + return NULL; +} + +PUINT_8 __weak getFwCfgItemValue(UINT_8 i) +{ + if (i < ARRAY_SIZE(fwCfgArray)) + return fwCfgArray[i].value; + else + return NULL; +} + +void wlanCfgFwSetParam(PUINT_8 fwBuffer, PCHAR cmdStr, PCHAR value, int num, int type) +{ + struct _CMD_FORMAT_V1_T *cmd = (struct _CMD_FORMAT_V1_T *)fwBuffer + num; + + kalMemSet(cmd, 0, sizeof(struct _CMD_FORMAT_V1_T)); + cmd->itemType = type; + + cmd->itemStringLength = strlen(cmdStr); + if (cmd->itemStringLength > MAX_CMD_NAME_MAX_LENGTH) + cmd->itemStringLength = MAX_CMD_NAME_MAX_LENGTH; + + /* here will not ensure the end will be '\0' */ + kalMemCopy(cmd->itemString, cmdStr, cmd->itemStringLength); + + cmd->itemValueLength = strlen(value); + if (cmd->itemValueLength > MAX_CMD_VALUE_MAX_LENGTH) + cmd->itemValueLength = MAX_CMD_VALUE_MAX_LENGTH; + + /* here will not ensure the end will be '\0' */ + kalMemCopy(cmd->itemValue, value, cmd->itemValueLength); +} + +WLAN_STATUS wlanCfgSetGetFw(IN P_ADAPTER_T prAdapter, const PCHAR fwBuffer, int cmdNum, enum _CMD_TYPE_T cmdType) +{ + struct _CMD_HEADER_T *pcmdV1Header = NULL; + + pcmdV1Header = (struct _CMD_HEADER_T *) kalMemAlloc(sizeof(struct _CMD_HEADER_T), VIR_MEM_TYPE); + + if (pcmdV1Header == NULL) + return WLAN_STATUS_FAILURE; + + kalMemSet(pcmdV1Header->buffer, 0, MAX_CMD_BUFFER_LENGTH); + pcmdV1Header->cmdType = cmdType; + pcmdV1Header->cmdVersion = CMD_VER_1_EXT; + pcmdV1Header->itemNum = cmdNum; + pcmdV1Header->cmdBufferLen = cmdNum * sizeof(struct _CMD_FORMAT_V1_T); + kalMemCopy(pcmdV1Header->buffer, fwBuffer, pcmdV1Header->cmdBufferLen); + + wlanSendSetQueryCmd(prAdapter, CMD_ID_GET_SET_CUSTOMER_CFG, + TRUE, FALSE, FALSE, + NULL, NULL, + sizeof(struct _CMD_HEADER_T), + (PUINT_8) pcmdV1Header, + NULL, 0); + kalMemFree(pcmdV1Header, VIR_MEM_TYPE, sizeof(struct _CMD_HEADER_T)); + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS wlanFwArrayCfg(IN P_ADAPTER_T prAdapter) +{ + int kk = 0; + PUINT_8 cmdBuffer = NULL; + int fwCfgItemNum = getFwCfgItemNum(); + + if (!fwCfgItemNum) + return WLAN_STATUS_FAILURE; + + cmdBuffer = kalMemAlloc(MAX_CMD_BUFFER_LENGTH, VIR_MEM_TYPE); + + if (cmdBuffer == 0) + return WLAN_STATUS_FAILURE; + + kalMemSet(cmdBuffer, 0, MAX_CMD_BUFFER_LENGTH); + + for (; kk < fwCfgItemNum;) { + wlanCfgFwSetParam(cmdBuffer, getFwCfgItemKey(kk), + getFwCfgItemValue(kk), (kk % MAX_CMD_ITEM_MAX), 1); + kk++; + if (kk % MAX_CMD_ITEM_MAX == 0) { + wlanCfgSetGetFw(prAdapter, cmdBuffer, MAX_CMD_ITEM_MAX, CMD_TYPE_SET); + kalMemSet(cmdBuffer, 0, MAX_CMD_BUFFER_LENGTH); + } + } + if (kk % MAX_CMD_ITEM_MAX) + wlanCfgSetGetFw(prAdapter, cmdBuffer, (kk % MAX_CMD_ITEM_MAX), CMD_TYPE_SET); + + kalMemFree(cmdBuffer, VIR_MEM_TYPE, MAX_CMD_BUFFER_LENGTH); + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS wlanFwFileCfg(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4FwCfgReadLen = 0; + PUINT_8 pucFwCfgBuf = (PUINT_8) kalMemAlloc(WLAN_CFG_FILE_BUF_SIZE, VIR_MEM_TYPE); + + if (!pucFwCfgBuf) { + DBGLOG(INIT, INFO, "omega, pucFwCfgBuf alloc fail!"); + return WLAN_STATUS_FAILURE; + } + kalMemZero(pucFwCfgBuf, WLAN_CFG_FILE_BUF_SIZE); + + if (kalReadToFile(FW_CFG_FILE, pucFwCfgBuf, + WLAN_CFG_FILE_BUF_SIZE, &u4FwCfgReadLen)) { + kalMemFree(pucFwCfgBuf, VIR_MEM_TYPE, WLAN_CFG_FILE_BUF_SIZE); + return WLAN_STATUS_FAILURE; + } else + DBGLOG(INIT, INFO, "file: %s read done\n", FW_CFG_FILE); + + if (pucFwCfgBuf[0] != '\0' && u4FwCfgReadLen > 0) { + /* Here limited the file length < 2048, bcz only for dbg purpose + * Meanwhile, if the file length == 2048, it MAY cause the last + * several <= 4 cmd failed + */ + if (u4FwCfgReadLen == WLAN_CFG_FILE_BUF_SIZE) + pucFwCfgBuf[WLAN_CFG_FILE_BUF_SIZE - 1] = '\0'; + + wlanFwCfgParse(prAdapter, pucFwCfgBuf); + } + kalMemFree(pucFwCfgBuf, VIR_MEM_TYPE, WLAN_CFG_FILE_BUF_SIZE); + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS wlanFwCfgParse(IN P_ADAPTER_T prAdapter, PUINT_8 pucConfigBuf) +{ + /* here return a list should be better */ + char *saveptr1 = NULL, *saveptr2 = NULL; + char *cfgItems = pucConfigBuf; + UINT_8 cmdNum = 0; + + PUINT_8 cmdBuffer = kalMemAlloc(MAX_CMD_BUFFER_LENGTH, VIR_MEM_TYPE); + + if (cmdBuffer == 0) { + DBGLOG(INIT, INFO, "omega, cmd buffer return fail!"); + return WLAN_STATUS_FAILURE; + } + kalMemSet(cmdBuffer, 0, MAX_CMD_BUFFER_LENGTH); + + while (1) { + char *keyStr = NULL; + char *valueStr = NULL; + char *cfgEntry = strtok_r(cfgItems, "\n\r", &saveptr1); + + if (!cfgEntry) { + if (cmdNum) + wlanCfgSetGetFw(prAdapter, cmdBuffer, cmdNum, CMD_TYPE_SET); + + if (cmdBuffer) + kalMemFree(cmdBuffer, VIR_MEM_TYPE, MAX_CMD_BUFFER_LENGTH); + return WLAN_STATUS_SUCCESS; + } + cfgItems = NULL; + + keyStr = strtok_r(cfgEntry, " \t", &saveptr2); + valueStr = strtok_r(NULL, "\0", &saveptr2); + + /* maybe a blank line, but with some tab or whitespace */ + if (!keyStr) + continue; + + /* here take '#' at the beginning of line as comment */ + if (keyStr[0] == '#') + continue; + + /* remove the \t " " at the beginning of the valueStr */ + while (valueStr && (*valueStr == '\t' || *valueStr == ' ')) + valueStr++; + + if (keyStr && valueStr) { + wlanCfgFwSetParam(cmdBuffer, keyStr, valueStr, cmdNum, 1); + cmdNum++; + if (cmdNum == MAX_CMD_ITEM_MAX) { + wlanCfgSetGetFw(prAdapter, cmdBuffer, MAX_CMD_ITEM_MAX, CMD_TYPE_SET); + kalMemSet(cmdBuffer, 0, MAX_CMD_BUFFER_LENGTH); + cmdNum = 0; + } + } else { + /* here will not to try send the cmd has been parsed, but not sent yet */ + if (cmdBuffer) + kalMemFree(cmdBuffer, VIR_MEM_TYPE, MAX_CMD_BUFFER_LENGTH); + return WLAN_STATUS_FAILURE; + } + } +} + +/* + * This func is mainly from bionic's strtok.c + */ +static char *strtok_r(char *s, const char *delim, char **last) +{ + char *spanp; + int c, sc; + char *tok; + + + if (s == NULL) { + s = *last; + if (s == 0) + return 0; + } +cont: + c = *s++; + for (spanp = (char *)delim; (sc = *spanp++) != 0;) { + if (c == sc) + goto cont; + } + + if (c == 0) { /* no non-delimiter characters */ + *last = NULL; + return NULL; + } + tok = s - 1; + + for (;;) { + c = *s++; + spanp = (char *)delim; + do { + sc = *spanp++; + if (sc == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + *last = s; + return tok; + } + } while (sc != 0); + } +} +#ifdef CFG_SUPPORT_COEX_IOT_AP +WLAN_STATUS wlanFWCfgForIotAP(IN P_ADAPTER_T prAdapter, UINT_8 aucBssid[]) +{ + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + UINT_8 aucTargetBssid[MAC_ADDR_LEN]; + UINT_8 aucCmdString[CMD_FORMAT_V1_LENGTH]; + UINT_8 i = 0, j = 0, ucPrevItem = 0; + int fwIotCfgItemNum = 0; + UINT_8 fgEnBssid = FALSE; + + if (!prAdapter || !(prAdapter->rWifiVar.ucEnCoexIotAP)) + return WLAN_STATUS_FAILURE; + fwIotCfgItemNum = ARRAY_SIZE(fwCfgIotAP); + DBGLOG(INIT, INFO, "Total item num:%d\n", fwIotCfgItemNum); + if (fwIotCfgItemNum < 1) + return WLAN_STATUS_FAILURE; + for (j = 0; j < fwIotCfgItemNum; j++) { + if (fwCfgIotAP[j].ucIotType != COEX_ISSUE_TYPE_ID) + continue; + for (i = 0; i < MAC_ADDR_LEN; i++) { + aucMacAddr[i] = (fwCfgIotAP[j].aucIotApMacAddr[i]) & (fwCfgIotAP[j].ucMacAddrMask[i]); + aucTargetBssid[i] = aucBssid[i] & (fwCfgIotAP[j].ucMacAddrMask[i]); + } + fgEnBssid = EQUAL_MAC_ADDR(aucTargetBssid, aucMacAddr); + if (fgEnBssid == TRUE) + break; + } + /* For Iot AP which don't stop tx when sta enters into Power save */ + if (fgEnBssid && (prAdapter->fgEnCts2Self == FALSE)) { + kalMemCopy(aucCmdString, fwCfgIotAP[j].aucEnableCmdString, strlen(fwCfgIotAP[j].aucEnableCmdString)+1); + DBGLOG(INIT, INFO, "CMD:%s, item: %d\n", aucCmdString, j); + wlanFwCfgParse(prAdapter, (PUINT_8)(aucCmdString)); + prAdapter->fgEnCts2Self = TRUE; + prAdapter->ucPrevItem = j; + } else if (fgEnBssid == FALSE && (prAdapter->fgEnCts2Self)) { + ucPrevItem = prAdapter->ucPrevItem; + if (ucPrevItem >= fwIotCfgItemNum) { + DBGLOG(INIT, WARN, "Invalid Index:%d\n", ucPrevItem); + ucPrevItem = 0; + } + kalMemCopy(aucCmdString, fwCfgIotAP[ucPrevItem].aucDisableCmdString, + strlen(fwCfgIotAP[ucPrevItem].aucDisableCmdString)+1); + DBGLOG(INIT, INFO, "CMD:%s, item: %d\n", aucCmdString, ucPrevItem); + wlanFwCfgParse(prAdapter, (PUINT_8)(aucCmdString)); + prAdapter->fgEnCts2Self = FALSE; + prAdapter->ucPrevItem = 0; + } + DBGLOG(INIT, INFO, "End fgEnabled = %d\n", prAdapter->fgEnCts2Self); + return WLAN_STATUS_SUCCESS; +} +WLAN_STATUS wlanFWCfgForceDisIotAP(IN P_ADAPTER_T prAdapter) +{ + UINT_8 aucCmdString[CMD_FORMAT_V1_LENGTH]; + UINT_8 j = 0; + int fwIotCfgItemNum = 0; + + if (!prAdapter || !(prAdapter->rWifiVar.ucEnCoexIotAP)) + return WLAN_STATUS_FAILURE; + fwIotCfgItemNum = ARRAY_SIZE(fwCfgIotAP); + if (fwIotCfgItemNum < 1) + return WLAN_STATUS_FAILURE; + for (j = 0; j < fwIotCfgItemNum; j++) { + if (prAdapter->fgEnCts2Self && fwCfgIotAP[j].ucIotType == COEX_ISSUE_TYPE_ID) { + kalMemCopy(aucCmdString, fwCfgIotAP[j].aucDisableCmdString, + strlen(fwCfgIotAP[j].aucDisableCmdString)+1); + DBGLOG(INIT, INFO, "CMD:%s, item: %d\n", aucCmdString, j); + wlanFwCfgParse(prAdapter, (PUINT_8)(aucCmdString)); + prAdapter->fgEnCts2Self = FALSE; + prAdapter->ucPrevItem = 0; + break; + } + } + DBGLOG(INIT, INFO, "End fgEnabled = %d\n", prAdapter->fgEnCts2Self); + return WLAN_STATUS_SUCCESS; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/makefile b/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/makefile new file mode 100644 index 0000000000000..89b63909cac98 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/makefile @@ -0,0 +1,8 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the driver components of the Windows NT DDK +#!INCLUDE $(NTMAKEENV)\makefile.def + +#!INCLUDE $(_MAKEENVROOT)\makefile.def +!INCLUDE $(_WINDOW_MAKE_ROOT)\makefile.def diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/sources.ce b/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/sources.ce new file mode 100644 index 0000000000000..59b0b291e680d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/sources.ce @@ -0,0 +1,11 @@ +TARGETNAME=$(DRIVER_NAME)_cmn_$(WINCEDEBUG)_51 +TARGETTYPE=LIBRARY + +INCLUDES=$(_INCLUDES_DIRS) + +C_DEFINES=$(C_DEFINES) -DNDIS_MINIPORT_DRIVER + +C_DEFINES=$(C_DEFINES) -DNDIS51_MINIPORT=1 -D_WIN2K_COMPAT_SLIST_USAGE=1 +CDEFINES=$(CDEFINES) -D$(DEVICE_ID) -DNDIS51_MINIPORT=1 $(_BUILD_MODULE_DEF) + +SOURCES= $(_COMMON_FILES) diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/sources.ddk b/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/sources.ddk new file mode 100644 index 0000000000000..d20e1b94fb820 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/sources.ddk @@ -0,0 +1,11 @@ +TARGETPATH=$(_LIB_PATH) +TARGETNAME=$(DRIVER_NAME)_cmn_51 +TARGETTYPE=DRIVER_LIBRARY + +INCLUDES=$(_INCLUDES_DIRS) + +C_DEFINES=$(C_DEFINES) -DNDIS_MINIPORT_DRIVER -DNDIS51_MINIPORT=1 +C_DEFINES=$(C_DEFINES) -D_WIN2K_COMPAT_SLIST_USAGE=1 +C_DEFINES=$(C_DEFINES) -DNDIS_WDM=1 $(_BUILD_MODULE_DEF) + +SOURCES= $(_COMMON_FILES) diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/wlan_bow.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/wlan_bow.c new file mode 100644 index 0000000000000..4a202166e63ca --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/wlan_bow.c @@ -0,0 +1,3205 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/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. + */ + +/****************************************************************************** +* C O M P I L E R F L A G S +******************************************************************************* +*/ + +/****************************************************************************** +* E X T E R N A L R E F E R E N C E S +******************************************************************************* +*/ +#include "precomp.h" + +#if CFG_ENABLE_BT_OVER_WIFI + +/****************************************************************************** +* C O N S T A N T S +******************************************************************************* +*/ + +/****************************************************************************** +* D A T A T Y P E S +******************************************************************************* +*/ + +/****************************************************************************** +* P U B L I C D A T A +******************************************************************************* +*/ + +#if 1 /* Marked for MT6630 */ +static UINT_32 g_u4LinkCount; +static UINT_32 g_u4Beaconing; +static BOW_TABLE_T arBowTable[CFG_BOW_PHYSICAL_LINK_NUM]; +#endif + +/****************************************************************************** +* 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 +******************************************************************************* +*/ + +#if 1 /* Marked for MT6630 */ +/*----------------------------------------------------------------------------*/ +/*! +* \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 UINT_8 ucBssIdx, + 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->ucBssIndex = ucBssIdx; + 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 = 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; +} + +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ +#if 1 /* Marked for MT6630 */ + 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; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ +#if 1 /* Marked for MT6630 */ + 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] = { {0} }; + + ASSERT(prAdapter); + + /* 3 <1> If LinkCount != 0 -> OK (optional) */ + + eBand = BAND_2G4; + eBssSCO = CHNL_EXT_SCN; + + /* fill event header */ + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_MAC_STATUS)), VIR_MEM_TYPE); + + if (prEvent == NULL) + return WLAN_STATUS_FAILURE; + + prEvent->rHeader.ucEventId = BOW_EVENT_ID_MAC_STATUS; + prEvent->rHeader.ucSeqNumber = prCmd->rHeader.ucSeqNumber; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_MAC_STATUS); + + /* fill event body */ + prMacStatus = (P_BOW_MAC_STATUS) (prEvent->aucPayload); + kalMemZero(prMacStatus, sizeof(BOW_MAC_STATUS)); + + /* 3 <2> Call CNM to decide if BOW available. */ + if (cnmBowIsPermitted(prAdapter)) + prMacStatus->ucAvailability = TRUE; + else + prMacStatus->ucAvailability = FALSE; + + memcpy(prMacStatus->aucMacAddr, prAdapter->rWifiVar.aucDeviceAddress, PARAM_MAC_ADDR_LEN); + + if (cnmPreferredChannel(prAdapter, &eBand, &ucPrimaryChannel, &eBssSCO)) { + DBGLOG(BOW, EVENT, "bowCmdGetMacStatus, Get preferred channel.\n"); + + prMacStatus->ucNumOfChannel = 1; + prMacStatus->arChannelList[0].ucChannelBand = eBand; + prMacStatus->arChannelList[0].ucChannelNum = ucPrimaryChannel; + } else { + DBGLOG(BOW, EVENT, + "bowCmdGetMacStatus, Get channel list. Current number of channel, %d.\n", ucNumOfChannel); + + rlmDomainGetChnlList(prAdapter, BAND_2G4, FALSE, MAX_BOW_NUMBER_OF_CHANNEL_2G4, + &ucNumOfChannel, aucChannelList); + + if (ucNumOfChannel > 0) { + for (idx = 0; idx < ucNumOfChannel; idx++) { + prMacStatus->arChannelList[idx].ucChannelBand = aucChannelList[idx].eBand; + prMacStatus->arChannelList[idx].ucChannelNum = aucChannelList[idx].ucChannelNum; + } + + prMacStatus->ucNumOfChannel = ucNumOfChannel; + } + + rlmDomainGetChnlList(prAdapter, BAND_5G, FALSE, MAX_BOW_NUMBER_OF_CHANNEL_5G, + &ucNumOfChannel, aucChannelList); + + if (ucNumOfChannel > 0) { + for (idx = 0; idx < ucNumOfChannel; idx++) { + prMacStatus->arChannelList[prMacStatus->ucNumOfChannel + + idx].ucChannelBand = aucChannelList[idx].eBand; + prMacStatus->arChannelList[prMacStatus->ucNumOfChannel + + idx].ucChannelNum = aucChannelList[idx].ucChannelNum; + } + + prMacStatus->ucNumOfChannel = prMacStatus->ucNumOfChannel + ucNumOfChannel; + + } + } + + 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, %x, %x.\n", + prMacStatus->ucNumOfChannel, prMacStatus->arChannelList[0].ucChannelBand); + DBGLOG(BOW, EVENT, + "prMacStatus->arChannelList, %x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x.\n", + prMacStatus->arChannelList[0].ucChannelNum, + prMacStatus->arChannelList[1].ucChannelNum, + prMacStatus->arChannelList[2].ucChannelNum, + prMacStatus->arChannelList[3].ucChannelNum, + prMacStatus->arChannelList[4].ucChannelNum, + prMacStatus->arChannelList[5].ucChannelNum, + prMacStatus->arChannelList[6].ucChannelNum, + prMacStatus->arChannelList[7].ucChannelNum, + prMacStatus->arChannelList[8].ucChannelNum, + prMacStatus->arChannelList[9].ucChannelNum, + prMacStatus->arChannelList[10].ucChannelNum, + prMacStatus->arChannelList[11].ucChannelNum, + prMacStatus->arChannelList[12].ucChannelNum, + prMacStatus->arChannelList[13].ucChannelNum, + prMacStatus->arChannelList[14].ucChannelNum, + prMacStatus->arChannelList[15].ucChannelNum, + prMacStatus->arChannelList[16].ucChannelNum, + prMacStatus->arChannelList[17].ucChannelNum); + + DBGLOG(BOW, 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]); + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_MAC_STATUS))); + + return WLAN_STATUS_SUCCESS; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ +#if 1 /* Marked for MT6630 */ + 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; + + 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); + + /* 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.eState = BOW_DEVICE_STATE_ACQUIRING_CHANNEL; + /* 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); + + DBGLOG(BOW, EVENT, "bowStarting, g_u4LinkCount, %x.\n", g_u4LinkCount); + + if (g_u4LinkCount == 1) { + DBGLOG(BOW, EVENT, "bowStarting, cnmTimerInitTimer.\n"); + DBGLOG(BOW, EVENT, "prBowFsmInfo->u2BeaconInterval, %d.\n", prBowFsmInfo->u2BeaconInterval); + + cnmTimerInitTimer(prAdapter, + &prBowFsmInfo->rStartingBeaconTimer, + (PFN_MGMT_TIMEOUT_FUNC) bowSendBeacon, (ULONG) NULL); + + cnmTimerInitTimer(prAdapter, + &prBowFsmInfo->rChGrantedTimer, + (PFN_MGMT_TIMEOUT_FUNC) bowChGrantedTimeout, (ULONG) NULL); + + /* Reset Global Variable */ + g_u4Beaconing = 0; + + DBGLOG(BOW, EVENT, "bowCmdSetupConnection, g_u4LinkCount, %x.\n", g_u4LinkCount); + DBGLOG(BOW, EVENT, "kalInitBowDevice, bow0\n"); + +#if CFG_BOW_SEPARATE_DATA_PATH + kalInitBowDevice(prAdapter->prGlueInfo, BOWDEVNAME); +#endif + + /*Active BoW Network */ + SET_NET_ACTIVE(prAdapter, prBowFsmInfo->ucBssIndex); + SET_NET_PWR_STATE_ACTIVE(prAdapter, prBowFsmInfo->ucBssIndex); + nicActivateNetwork(prAdapter, prBowFsmInfo->ucBssIndex); + + } + + 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; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ +#if 1 /* Marked for MT6630 */ + P_BOW_DESTROY_CONNECTION prBowDestroyConnection; + CMD_BT_OVER_WIFI rCmdBtOverWifi; + P_BOW_FSM_INFO_T prBowFsmInfo; + + UINT_8 ucIdx; + + 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)) { + DBGLOG(BOW, EVENT, "bowCmdDestroyConnection, bowCheckIfVaild, not accepted.\n"); + return WLAN_STATUS_NOT_ACCEPTED; + } + + 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]); + + /* fill CMD_BT_OVER_WIFI */ + rCmdBtOverWifi.ucAction = 2; + COPY_MAC_ADDR(rCmdBtOverWifi.rPeerAddr, prBowDestroyConnection->aucPeerAddress); + COPY_MAC_ADDR(prBowFsmInfo->aucPeerAddress, prBowDestroyConnection->aucPeerAddress); + + 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]); + + 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]); + } + + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_SUCCESS); + + return wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + prBowFsmInfo->ucBssIndex, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, + sizeof(CMD_BT_OVER_WIFI), + (PUINT_8)&rCmdBtOverWifi, prCmd->rHeader.ucSeqNumber); + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ +#if 1 /* Marked for MT6630 */ + P_BOW_SET_PTK prBowSetPTK; + CMD_802_11_KEY rCmdKey; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_STA_RECORD_T prStaRec = NULL; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + /* parameter size check */ + if (prCmd->rHeader.u2PayloadLength != sizeof(BOW_SET_PTK)) + return WLAN_STATUS_INVALID_LENGTH; + + prBowSetPTK = (P_BOW_SET_PTK) &(prCmd->aucPayload[0]); + + 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)); + + 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.ucBssIdx = prBowFsmInfo->ucBssIndex; /* BT Over Wi-Fi */ + rCmdKey.ucAlgorithmId = CIPHER_SUITE_CCMP; /* AES */ + rCmdKey.ucKeyId = 0; + rCmdKey.ucKeyLen = 16; /* AES = 128bit */ + kalMemCopy(rCmdKey.aucKeyMaterial, prBowSetPTK->aucTemporalKey, 16); + + /* BT Over Wi-Fi */ + prStaRec = cnmGetStaRecByAddress(prAdapter, prBowFsmInfo->ucBssIndex, prBowSetPTK->aucPeerAddress); + + if (prStaRec == NULL) + return WLAN_STATUS_FAILURE; + + rCmdKey.ucWlanIndex = prStaRec->ucWlanIndex; + + 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]); + + return wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_ADD_REMOVE_KEY, + prBowFsmInfo->ucBssIndex, + TRUE, + FALSE, + wlanbowCmdEventSetCommon, + wlanbowCmdTimeoutHandler, + sizeof(CMD_802_11_KEY), (PUINT_8)&rCmdKey, prCmd->rHeader.ucSeqNumber); +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ +#if 1 /* Marked for MT6630 */ + P_BOW_READ_RSSI prBowReadRSSI; + P_BOW_FSM_INFO_T prBowFsmInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + /* 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, + prBowFsmInfo->ucBssIndex, + FALSE, + TRUE, + wlanbowCmdEventReadRssi, + wlanbowCmdTimeoutHandler, 0, NULL, prCmd->rHeader.ucSeqNumber); + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ +#if 1 /* Marked for MT6630 */ + P_BOW_READ_LINK_QUALITY prBowReadLinkQuality; + P_BOW_FSM_INFO_T prBowFsmInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + /* 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, + prBowFsmInfo->ucBssIndex, + FALSE, + TRUE, + wlanbowCmdEventReadLinkQuality, + wlanbowCmdTimeoutHandler, 0, NULL, prCmd->rHeader.ucSeqNumber); + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ +#if 1 /* Marked for MT6630 */ + P_BOW_SHORT_RANGE_MODE prBowShortRangeMode; + CMD_TX_PWR_T rTxPwrParam; + + ASSERT(prAdapter); + + DBGLOG(BOW, EVENT, "bowCmdShortRangeMode.\n"); + + 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; + } + + 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]); + + 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) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_FAILURE); + return WLAN_STATUS_FAILURE; + } + + DBGLOG(BOW, EVENT, "bowCmdShortRangeMode, %x.\n", WLAN_STATUS_SUCCESS); + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_SUCCESS); + return WLAN_STATUS_SUCCESS; +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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; +} + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is generic command done handler +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanbowCmdEventSetStatus(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd, IN UINT_8 ucEventBuf) +{ + P_AMPC_EVENT prEvent; + P_BOW_COMMAND_STATUS prBowCmdStatus; + + ASSERT(prAdapter); + + /* fill event header */ + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS)), VIR_MEM_TYPE); + if (prEvent == NULL) + return; + prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; + prEvent->rHeader.ucSeqNumber = prCmd->rHeader.ucSeqNumber; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_COMMAND_STATUS); + + /* fill event body */ + prBowCmdStatus = (P_BOW_COMMAND_STATUS) (prEvent->aucPayload); + kalMemZero(prBowCmdStatus, sizeof(BOW_COMMAND_STATUS)); + + prBowCmdStatus->ucStatus = ucEventBuf; + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS))); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is generic command done handler +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanbowCmdEventSetCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_AMPC_EVENT prEvent; + P_BOW_COMMAND_STATUS prBowCmdStatus; + + ASSERT(prAdapter); + + /* fill event header */ + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS)), VIR_MEM_TYPE); + if (prEvent == NULL) + return; + prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_COMMAND_STATUS); + + /* fill event body */ + prBowCmdStatus = (P_BOW_COMMAND_STATUS) (prEvent->aucPayload); + kalMemZero(prBowCmdStatus, sizeof(BOW_COMMAND_STATUS)); + + prBowCmdStatus->ucStatus = BOWCMD_STATUS_SUCCESS; + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS))); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief command done handler for CMD_ID_CMD_BT_OVER_WIFI +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanbowCmdEventLinkConnected(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_AMPC_EVENT prEvent; + P_BOW_LINK_CONNECTED prBowLinkConnected; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + /* fill event header */ + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_LINK_CONNECTED)), VIR_MEM_TYPE); + if (prEvent == NULL) + return; + prEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_CONNECTED; + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_LINK_CONNECTED); + + /* fill event body */ + prBowLinkConnected = (P_BOW_LINK_CONNECTED) (prEvent->aucPayload); + kalMemZero(prBowLinkConnected, sizeof(BOW_LINK_CONNECTED)); + prBowLinkConnected->rChannel.ucChannelNum = prBssInfo->ucPrimaryChannel; + prBowLinkConnected->rChannel.ucChannelBand = prBssInfo->eBand; + COPY_MAC_ADDR(prBowLinkConnected->aucPeerAddress, prBowFsmInfo->aucPeerAddress); + + 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); + + /*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; + ENUM_BOW_DEVICE_STATE eFsmState; + UINT_8 ucBowTableIdx = 0; + 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); + if (prEvent == NULL) + return; + prEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_DISCONNECTED; + if ((prCmdInfo->u4PrivateData)) + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + else + prEvent->rHeader.ucSeqNumber = 0; + + prEvent->rHeader.u2PayloadLength = sizeof(BOW_LINK_DISCONNECTED); + + /* fill event body */ + prBowLinkDisconnected = (P_BOW_LINK_DISCONNECTED) (prEvent->aucPayload); + kalMemZero(prBowLinkDisconnected, sizeof(BOW_LINK_DISCONNECTED)); + prBowLinkDisconnected->ucReason = 0x0; + COPY_MAC_ADDR(prBowLinkDisconnected->aucPeerAddress, prBowFsmInfo->aucPeerAddress); + + 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); + + /*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, prBowFsmInfo->ucBssIndex, prBowLinkDisconnected->aucPeerAddress); + + if (prBowFsmInfo->prTargetStaRec == NULL) { + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_DISCONNECTED))); + return; + } + + /*Release channel if granted */ + if (prBowFsmInfo->fgIsChannelGranted) { + cnmTimerStopTimer(prAdapter, &prBowFsmInfo->rChGrantedTimer); + bowReleaseCh(prAdapter); + /*Requested, not granted yet */ + } else if (prBowFsmInfo->fgIsChannelRequested) { + prBowFsmInfo->fgIsChannelRequested = FALSE; + /* bowReleaseCh(prAdapter); */ + } +#if 1 + /*Send Deauth to connected peer */ + if (eFsmState == BOW_DEVICE_STATE_CONNECTED && (prBowFsmInfo->prTargetStaRec->ucStaState == STA_STATE_3)) { + fgSendDeauth = TRUE; + DBGLOG(BOW, EVENT, + "wlanbowCmdEventLinkDisconnected, bowGetBowTableState, %x.\n", + bowGetBowTableState(prAdapter, prBowLinkDisconnected->aucPeerAddress)); + authSendDeauthFrame(prAdapter, NULL, 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; + rBowTable.ucAcquireID = 0; /* todo: add when fix coverity issue, correct it if needed */ + bowSetBowTableContent(prAdapter, ucBowTableIdx, &rBowTable); + + /*Indicate BoW event to PAL */ + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_DISCONNECTED))); + + /*Decrease link count */ + GLUE_DEC_REF_CNT(g_u4LinkCount); + + /*If no need to send deauth, DO disconnect now */ + /*If need to send deauth, DO disconnect at deauth Tx done */ + if (!fgSendDeauth) + bowDisconnectLink(prAdapter, NULL, TX_RESULT_SUCCESS); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief command done handler for CMD_ID_CMD_BT_OVER_WIFI +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanbowCmdEventSetSetupConnection(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_AMPC_EVENT prEvent; + P_BOW_COMMAND_STATUS prBowCmdStatus; + P_WIFI_CMD_T prWifiCmd; + P_CMD_BT_OVER_WIFI prCmdBtOverWifi; + P_BOW_FSM_INFO_T prBowFsmInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + /* restore original command for rPeerAddr */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prCmdBtOverWifi = (P_CMD_BT_OVER_WIFI) (prWifiCmd->aucBuffer); + + /* fill event header */ + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS)), VIR_MEM_TYPE); + if (prEvent == NULL) + return; + prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_COMMAND_STATUS); + + /* fill event body */ + prBowCmdStatus = (P_BOW_COMMAND_STATUS) (prEvent->aucPayload); + kalMemZero(prBowCmdStatus, sizeof(BOW_COMMAND_STATUS)); + prBowCmdStatus->ucStatus = BOWCMD_STATUS_SUCCESS; + + /*Indicate BoW event to PAL */ + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS))); + + /* set to starting status */ + kalSetBowState(prAdapter->prGlueInfo, BOW_DEVICE_STATE_STARTING, prCmdBtOverWifi->rPeerAddr); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is the command done handler for BOW_CMD_ID_READ_LINK_QUALITY +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanbowCmdEventReadLinkQuality(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_LINK_QUALITY prLinkQuality; + P_AMPC_EVENT prEvent; + P_BOW_LINK_QUALITY prBowLinkQuality; + + ASSERT(prAdapter); + + prLinkQuality = (P_EVENT_LINK_QUALITY) pucEventBuf; + + /* fill event header */ + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_LINK_QUALITY)), VIR_MEM_TYPE); + if (prEvent == NULL) + return; + prEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_QUALITY; + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_LINK_QUALITY); + + /* fill event body */ + prBowLinkQuality = (P_BOW_LINK_QUALITY) (prEvent->aucPayload); + kalMemZero(prBowLinkQuality, sizeof(BOW_LINK_QUALITY)); + prBowLinkQuality->ucLinkQuality = (UINT_8) prLinkQuality->cLinkQuality; + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_QUALITY))); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is the command done handler for BOW_CMD_ID_READ_RSSI +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanbowCmdEventReadRssi(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_LINK_QUALITY prLinkQuality; + P_AMPC_EVENT prEvent; + P_BOW_RSSI prBowRssi; + + ASSERT(prAdapter); + + prLinkQuality = (P_EVENT_LINK_QUALITY) pucEventBuf; + + /* fill event header */ + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_LINK_QUALITY)), VIR_MEM_TYPE); + if (prEvent == NULL) + return; + prEvent->rHeader.ucEventId = BOW_EVENT_ID_RSSI; + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_RSSI); + + /* fill event body */ + prBowRssi = (P_BOW_RSSI) (prEvent->aucPayload); + kalMemZero(prBowRssi, sizeof(BOW_RSSI)); + prBowRssi->cRssi = (INT_8) prLinkQuality->cRssi; + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_QUALITY))); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is the default command timeout handler +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanbowCmdTimeoutHandler(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + P_AMPC_EVENT prEvent; + P_BOW_COMMAND_STATUS prBowCmdStatus; + + ASSERT(prAdapter); + + /* fill event header */ + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS)), VIR_MEM_TYPE); + if (prEvent == NULL) + return; + prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_COMMAND_STATUS); + + /* fill event body */ + prBowCmdStatus = (P_BOW_COMMAND_STATUS) (prEvent->aucPayload); + kalMemZero(prBowCmdStatus, sizeof(BOW_COMMAND_STATUS)); + + prBowCmdStatus->ucStatus = BOWCMD_STATUS_TIMEOUT; /* timeout */ + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS))); +} + +/* Bruce, 20140224 */ +UINT_8 bowInit(IN P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prBowBssInfo; + P_BOW_FSM_INFO_T prBowFsmInfo; + + ASSERT(prAdapter); + + prBowBssInfo = cnmGetBssInfoAndInit(prAdapter, NETWORK_TYPE_BOW, TRUE); + if (prBowBssInfo == NULL) + return BSS_INFO_NUM; + + /*Initiate BSS_INFO_T - common part -move from bowstarting */ + BSS_INFO_INIT(prAdapter, prBowBssInfo); + + prBowBssInfo->eCurrentOPMode = OP_MODE_BOW; + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowFsmInfo->ucBssIndex = prBowBssInfo->ucBssIndex; + + /* Setup Own MAC & BSSID */ + COPY_MAC_ADDR(prBowBssInfo->aucOwnMacAddr, prAdapter->rWifiVar.aucDeviceAddress); + COPY_MAC_ADDR(prBowBssInfo->aucBSSID, prAdapter->rWifiVar.aucDeviceAddress); + + return prBowBssInfo->ucBssIndex; +} + +/* Bruce, 20140224 */ +VOID bowUninit(IN P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prBowBssInfo; + P_BOW_FSM_INFO_T prBowFsmInfo; + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + cnmFreeBssInfo(prAdapter, prBowBssInfo); +} + +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 = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + 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]); + DBGLOG(BOW, EVENT, "BoW Stoping,[%d,%d]\n", g_u4LinkCount, g_u4Beaconing); + + if (g_u4LinkCount == 0) { + /*Stop beaconing */ + GLUE_DEC_REF_CNT(g_u4Beaconing); + + /*Deactive BoW network */ + /* prBowBssInfo->fgIsNetActive = FALSE; */ + /* prBowBssInfo->fgIsBeaconActivated = FALSE; */ + nicPmIndicateBssAbort(prAdapter, prBowBssInfo->ucBssIndex); + bowChangeMediaState(prBowBssInfo, PARAM_MEDIA_STATE_DISCONNECTED); + nicUpdateBss(prAdapter, prBowBssInfo->ucBssIndex); + /*temp solution for FW hal_pwr_mgt.c#3037 ASSERT */ + nicDeactivateNetwork(prAdapter, prBowBssInfo->ucBssIndex); + SET_NET_PWR_STATE_IDLE(prAdapter, prBowBssInfo->ucBssIndex); + UNSET_NET_ACTIVE(prAdapter, prBowBssInfo->ucBssIndex); + + } + +} + +VOID bowStarting(IN P_ADAPTER_T prAdapter) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if (g_u4LinkCount == 1) { + DBGLOG(BOW, EVENT, "BoW Starting.\n"); + DBGLOG(BOW, EVENT, "BoW channel granted.\n"); + + /* 3 <1> Update BSS_INFO_T per Network Basis */ + /* 4 <1.1> Setup Operation Mode */ + + /* Bruce, 20140224 */ + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + /* 4 <1.2> Setup SSID */ + prBssInfo->ucSSIDLen = BOW_SSID_LEN; + bowAssignSsid(prBssInfo->aucSSID, prBssInfo->aucOwnMacAddr); + + 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]); + + /* 4 <1.3> Clear current AP's STA_RECORD_T and current AID */ + prBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; + prBssInfo->u2AssocId = 0; + + /* 4 <1.4> Setup Channel, Band and Phy Attributes */ + prBssInfo->ucPrimaryChannel = prBowFsmInfo->ucPrimaryChannel; + if (prBowFsmInfo->eBand == BAND_2G4) + prBssInfo->eBand = BAND_2G4; + else + prBssInfo->eBand = BAND_5G; + +#if CFG_BOW_SUPPORT_11N + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11BGN; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; + + prBssInfo->ucNonHTBasicPhyType = (UINT_8) + rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].ePhyTypeIndex; + prBssInfo->u2BSSBasicRateSet = rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].u2BSSBasicRateSet; + + prBssInfo->u2OperationalRateSet = + rNonHTPhyAttributes[prBssInfo->ucNonHTBasicPhyType].u2SupportedRateSet; + + rateGetDataRatesFromRateSet(prBssInfo->u2OperationalRateSet, + prBssInfo->u2BSSBasicRateSet, + prBssInfo->aucAllSupportedRates, &prBssInfo->ucAllSupportedRatesLen); + +#else + if (prBssInfo->eBand == BAND_2G4) { + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11BG; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; + + /* RATE_SET_ERP; */ + prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_ERP; + prBssInfo->u2OperationalRateSet = RATE_SET_ERP; + prBssInfo->ucNonHTBasicPhyType = PHY_TYPE_ERP_INDEX; + } else { + /* Depend on eBand */ + /* prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11BG; */ + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + /* prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; */ + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11A; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_11A; + + /* RATE_SET_ERP; */ + /* prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_ERP; */ + /* prBssInfo->u2OperationalRateSet = RATE_SET_ERP; */ + + /* RATE_SET_ERP; */ + prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_OFDM; + prBssInfo->u2OperationalRateSet = RATE_SET_OFDM; + prBssInfo->ucNonHTBasicPhyType = PHY_TYPE_OFDM_INDEX; + } + +#endif + prBssInfo->fgErpProtectMode = FALSE; + + /* 4 <1.5> Setup MIB for current BSS */ + prBssInfo->u2BeaconInterval = prBowFsmInfo->u2BeaconInterval; + prBssInfo->ucDTIMPeriod = DOT11_DTIM_PERIOD_DEFAULT; + prBssInfo->u2ATIMWindow = 0; + prBssInfo->ucBeaconTimeoutCount = 0; + if (prBowFsmInfo->fgSupportQoS) { + prAdapter->rWifiVar.ucQoS = TRUE; + prBssInfo->fgIsQBSS = TRUE; + } + + /* 3 <2> Update BSS_INFO_T common part */ +#if CFG_SUPPORT_AAA + bssInitForAP(prAdapter, prBssInfo, TRUE); + nicQmUpdateWmmParms(prAdapter, prBssInfo->ucBssIndex); +#endif /* CFG_SUPPORT_AAA */ + prBssInfo->fgIsNetActive = TRUE; + prBssInfo->fgIsBeaconActivated = TRUE; + + /* 3 <3> Set MAC HW */ + + 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]); + + /* 4 <3.1> use command packets to inform firmware */ + rlmBssInitForAPandIbss(prAdapter, prBssInfo); + nicUpdateBss(prAdapter, prBssInfo->ucBssIndex); + + /* 4 <3.2> Update AdHoc PM parameter */ + nicPmIndicateBssCreated(prAdapter, prBssInfo->ucBssIndex); + + /* 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); + + DBGLOG(BOW, EVENT, "BoW Starting,[%d,%d]\n", g_u4LinkCount, g_u4Beaconing); + DBGLOG(BOW, EVENT, "bowStarting, g_u4LinkCount, %x.\n", g_u4LinkCount); + + /*Start beaconing */ + if ((g_u4Beaconing < 1) && (prBssInfo)) { + GLUE_INC_REF_CNT(g_u4Beaconing); + bssSendBeaconProbeResponse(prAdapter, prBssInfo->ucBssIndex, NULL, 0); + cnmTimerStartTimer(prAdapter, &prBowFsmInfo->rStartingBeaconTimer, prBowFsmInfo->u2BeaconInterval); + } +#if 0 + /*Responder: Start to scan Initiator */ + if (prBowFsmInfo->ucRole == BOW_RESPONDER) { + DBGLOG(BOW, EVENT, "bowStarting responder, start scan result searching.\n"); + cnmTimerStopTimer(prAdapter, &prBowFsmInfo->rChGrantedTimer); + bowReleaseCh(prAdapter); + bowResponderScan(prAdapter); + } + /*Initiator: Request channel, wait for responder */ + /* + * else + * bowRequestCh(prAdapter); + */ +#endif + + /* wlanBindBssIdxToNetInterface(prAdapter->prGlueInfo, NET_DEV_BOW_IDX, prBssInfo->ucBssIndex); */ +} + +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; + } +} + +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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) +{ +#if 1 /* Marked for MT6630 */ + + 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); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + +#if 0 + DBGLOG(BOW, EVENT, "bowValidateProbeReq.\n"); +#endif + + /* 4 <1> Parse Probe Req IE and Get IE ptr (SSID, Supported Rate IE, ...) */ + prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T) prSwRfb->pvHeader; + + u2IELength = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen; + pucIE = (PUINT_8) (((ULONG) prSwRfb->pvHeader) + prSwRfb->u2HeaderLen); + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (IE_ID(pucIE) == ELEM_ID_SSID) { + 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 (IE_ID(pucIE) == ELEM_ID_SSID) { + 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; +#else + return 0; +#endif +} + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Media Disconnect" to HOST +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bowSendBeacon(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr) +{ + 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, prBowFsmInfo->ucBssIndex, NULL, 0); + cnmTimerStartTimer(prAdapter, &prBowFsmInfo->rStartingBeaconTimer, prBowFsmInfo->u2BeaconInterval); + } else { + DBGLOG(BOW, EVENT, "BoW Send Beacon,[%d,%d]\n", g_u4LinkCount, g_u4Beaconing); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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 = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + DBGLOG(BOW, EVENT, "bowResponderScan.\n"); + DBGLOG(BOW, EVENT, "BOW SCAN [REQ:%d]\n", prBowFsmInfo->ucSeqNumOfScanReq + 1); + + 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->ucBssIndex = prBowFsmInfo->ucBssIndex; + 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 */ +} + +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID bowResponderScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ +#if 1 /* Marked for MT6630 */ + 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); + + ucSeqNumOfCompMsg = prScanDoneMsg->ucSeqNum; + eScanStatus = prScanDoneMsg->eScanStatus; + + cnmMemFree(prAdapter, prMsgHdr); + + DBGLOG(BOW, EVENT, "bowResponderScanDone.\n"); + DBGLOG(BOW, EVENT, "BOW SCAN [DONE:%d]\n", ucSeqNumOfCompMsg); + + if (eScanStatus == SCAN_STATUS_CANCELLED) { + DBGLOG(BOW, EVENT, "BOW SCAN [CANCELLED:%d]\n", ucSeqNumOfCompMsg); + if (eFsmState == BOW_DEVICE_STATE_DISCONNECTING) { + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + prBowFsmInfo->ucBssIndex, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, 0, NULL, 0); + } + return; + } else if (eFsmState == BOW_DEVICE_STATE_DISCONNECTED) { + /* bowDisconnectLink(prAdapter, NULL, TX_RESULT_SUCCESS); */ + } else if (ucSeqNumOfCompMsg != prBowFsmInfo->ucSeqNumOfScanReq) { + DBGLOG(BOW, EVENT, "Sequence no. of BOW Responder scan done is not matched.\n"); + } else { + prConnSettings->fgIsScanReqIssued = FALSE; + prBssDesc = scanSearchBssDescByBssid(prAdapter, prBowFsmInfo->aucPeerAddress); + DBGLOG(BOW, EVENT, "End scan result searching.\n"); + DBGLOG(BOW, EVENT, + "prBowFsmInfo->aucPeerAddress: [" MACSTR "]\n", MAC2STR(prBowFsmInfo->aucPeerAddress)); + + /*Initiator is FOUND */ + if (prBssDesc != NULL) { /* (prBssDesc->aucBSSID != NULL)) */ + 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"); + + /*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 + } + } +#endif /* Marked for MT6630 */ +} + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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) { + DBGLOG(BOW, EVENT, "BOW SCAN [CANCEL:%d]\n", prBowFsmInfo->ucSeqNumOfScanReq); + + /* There is a channel privilege on hand. */ + + DBGLOG(BOW, 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(BOW, TRACE, "Buffer not enough, can not cancel scan.\n"); + ASSERT(FALSE); + break; + } + + prScanCancel->rMsgHdr.eMsgId = MID_BOW_SCN_SCAN_CANCEL; + prScanCancel->ucBssIndex = prBowFsmInfo->ucBssIndex; + 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 = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + 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, prBssInfo->ucBssIndex, prBssDesc); + if (prStaRec == NULL) + return; + prBowFsmInfo->prTargetStaRec = prStaRec; + + /* 4 <3> Update ucAvailableAuthTypes which we can choice during SAA */ + prStaRec->fgIsReAssoc = FALSE; + prBowFsmInfo->ucAvailableAuthTypes = (UINT_8) AUTH_TYPE_OPEN_SYSTEM; + prStaRec->ucTxAuthAssocRetryLimit = TX_AUTH_ASSOCI_RETRY_LIMIT; + + /* 4 <4> Use an appropriate Authentication Algorithm Number among the ucAvailableAuthTypes */ + if (prBowFsmInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_OPEN_SYSTEM) { + + DBGLOG(BOW, LOUD, "JOIN INIT: Try to do Authentication with AuthType == OPEN_SYSTEM.\n"); + prBowFsmInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_OPEN_SYSTEM; + + prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_OPEN_SYSTEM; + } else { + ASSERT(0); + } + + /* 4 <4.1> sync. to firmware domain */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + /* 4 <5> Overwrite Connection Setting for eConnectionPolicy */ + if (prBssDesc->ucSSIDLen) { + COPY_SSID(prConnSettings->aucSSID, prConnSettings->ucSSIDLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + DBGLOG(BOW, EVENT, "bowResponderJoin, SSID %s.\n", prBssDesc->aucSSID); + DBGLOG(BOW, EVENT, "bowResponderJoin, SSID %s.\n", prConnSettings->aucSSID); + } + /* 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; + + DBGLOG(BOW, EVENT, "prStaRec->eStaType, %x.\n", prStaRec->eStaType); + DBGLOG(BOW, EVENT, "BoW trigger SAA [" MACSTR "]\n", MAC2STR(prStaRec->aucMacAddr)); + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinReqMsg, MSG_SEND_METHOD_BUF); +} + +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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) +{ +#if 1 /* Marked for MT6630 */ + + P_MSG_JOIN_COMP_T prJoinCompMsg; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_STA_RECORD_T prStaRec; + P_SW_RFB_T prAssocRspSwRfb; + 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; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + prJoinCompMsg = (P_MSG_JOIN_COMP_T) prMsgHdr; + prStaRec = prJoinCompMsg->prStaRec; + + DBGLOG(BOW, EVENT, "Start bowfsmRunEventJoinComplete.\n"); + DBGLOG(BOW, EVENT, "bowfsmRunEventJoinComplete ptr check\n"); + DBGLOG(BOW, EVENT, "prMsgHdr %p\n", prMsgHdr); + DBGLOG(BOW, EVENT, "prAdapter %p\n", prAdapter); + DBGLOG(BOW, EVENT, "prBowFsmInfo %p\n", prBowFsmInfo); + DBGLOG(BOW, EVENT, "prStaRec %p\n", prStaRec); + + 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; + + u2IELength = + (UINT_16) ((prAssocRspSwRfb->u2PacketLen - + prAssocRspSwRfb->u2HeaderLen) - + (OFFSET_OF(WLAN_ASSOC_RSP_FRAME_T, aucInfoElem[0]) - WLAN_MAC_MGMT_HEADER_LEN)); + pucIE = prAssocRspFrame->aucInfoElem; + + prStaRec->eStaType = STA_TYPE_BOW_AP; + prStaRec->u2DesiredNonHTRateSet &= prBowBssInfo->u2OperationalRateSet; + prStaRec->ucDesiredPhyTypeSet = prStaRec->ucPhyTypeSet & prBowBssInfo->ucPhyTypeSet; +#if CFG_BOW_RATE_LIMITATION + /* 4 <1.2>Update Rate Set */ + /*Limit Rate Set to 24M, 48M, 54M */ + prStaRec->u2DesiredNonHTRateSet &= (RATE_SET_BIT_24M | RATE_SET_BIT_48M | RATE_SET_BIT_54M); + /*If peer cannot support the above rate set, fix on the available highest rate */ + if (prStaRec->u2DesiredNonHTRateSet == 0) { + UINT_8 ucHighestRateIndex; + + if (rateGetHighestRateIndexFromRateSet + (prBowBssInfo->u2OperationalRateSet, &ucHighestRateIndex)) { + prStaRec->u2DesiredNonHTRateSet = BIT(ucHighestRateIndex); + } + } +#endif + + /* 4 <1.1> Change FW's Media State immediately. */ + bowChangeMediaState(prBowBssInfo, 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, prBowBssInfo->ucBssIndex); + DBGLOG(BOW, EVENT, "Finish bowUpdateBssInfoForJOIN.\n"); + + /* 4 <1.4> Activate current AP's STA_RECORD_T in Driver. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + DBGLOG(BOW, EVENT, "bowFsmRunEventJoinComplete, qmActivateStaRec.\n"); + + /* 4 <1.7> Set the Next State of BOW FSM */ + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + prBowFsmInfo->ucBssIndex, + 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 + DBGLOG(BOW, EVENT, "Start bowfsmRunEventJoinComplete -- Join failed.\n"); + DBGLOG(BOW, EVENT, "BoW trigger SAA REJOIN\n"); + } + } + + cnmMemFree(prAdapter, prMsgHdr); + +#endif /* Marked for MT6630 */ +} + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + /* 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 { + + rEventConnStatus.ucReasonOfDisconnect = prBssInfo->ucReasonOfDisconnect; + + } + + /* 4 <2> Indication */ + nicMediaStateChange(prAdapter, prBssInfo->ucBssIndex, &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)); + } +} + +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Event of Tx Fail of AAA Module. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bowRunEventAAATxFail(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ +#if 1 /* Marked for MT6630 */ + P_BSS_INFO_T prBssInfo; + P_BOW_FSM_INFO_T prBowFsmInfo; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + DBGLOG(BOW, EVENT, "bowRunEventAAATxFail , bssRemoveStaRecFromClientList.\n"); + DBGLOG(BOW, EVENT, "BoW AAA TxFail, target state %d\n", prStaRec->ucStaState + 1); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + bssRemoveClient(prAdapter, prBssInfo, prStaRec); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Event of Successful Completion of AAA Module. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS bowRunEventAAAComplete(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ +#if 1 /* Marked for MT6630 */ + P_BSS_INFO_T prBssInfo; + P_BOW_FSM_INFO_T prBowFsmInfo; + + ASSERT(prStaRec); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + DBGLOG(BOW, STATE, "bowRunEventAAAComplete, cnmStaRecChangeState, STA_STATE_3.\n"); + DBGLOG(BOW, EVENT, "BoW AAA complete [" MACSTR "]\n", MAC2STR(prStaRec->aucMacAddr)); + + /*Update BssInfo to connected */ + bowChangeMediaState(prBssInfo, PARAM_MEDIA_STATE_CONNECTED); + nicUpdateBss(prAdapter, prBowFsmInfo->ucBssIndex); + + /*Update StaRec to State3 */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + /*Connected */ + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + prBowFsmInfo->ucBssIndex, + TRUE, FALSE, wlanbowCmdEventLinkConnected, wlanbowCmdTimeoutHandler, 0, NULL, 0); + + return WLAN_STATUS_SUCCESS; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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) +{ +#if 1 /* Marked for MT6630 */ + P_BSS_INFO_T prBowBssInfo; + P_BOW_FSM_INFO_T prBowFsmInfo; + ENUM_BOW_DEVICE_STATE eFsmState; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + if (!IS_STA_BOW_TYPE(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 (prStaRec->ucStaState == STA_STATE_3) { + /* 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, + prBowFsmInfo->ucBssIndex, + TRUE, + FALSE, wlanbowCmdEventLinkDisconnected, wlanbowCmdTimeoutHandler, 0, NULL, 0); + + return WLAN_STATUS_SUCCESS; + } + + return WLAN_STATUS_NOT_ACCEPTED; + +#else + return 0; +#endif +} + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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); */ + 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 + if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) { + wlanLoadManufactureData(prAdapter, kalGetConfiguration(prAdapter->prGlueInfo)); + } else { + DBGLOG(REQ, WARN, + "%s: load manufacture data fail\n", __func__); + } +#endif + /*Uninit BoW Interface */ +#if CFG_BOW_SEPARATE_DATA_PATH + kalUninitBowDevice(prAdapter->prGlueInfo); +#endif + } +} + +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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) +{ +#if 1 /* Marked for MT6630 */ + + BOOLEAN fgReplyAssocResp = FALSE; + P_BSS_INFO_T prBowBssInfo; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_WLAN_ASSOC_REQ_FRAME_T prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) NULL; + OS_SYSTIME rCurrentTime; + static OS_SYSTIME rLastRejectAssocTime; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) prSwRfb->pvHeader; + *pu2StatusCode = STATUS_CODE_REQ_DECLINED; + + 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]); + + /*Assoc Accept */ + while (EQUAL_MAC_ADDR(prAssocReqFrame->aucSrcAddr, prBowFsmInfo->aucPeerAddress)) { + DBGLOG(BOW, EVENT, "bowValidateAssocReq, return wlanbowCmdEventLinkConnected.\n"); + + /*Update StaRec */ + prStaRec = cnmGetStaRecByAddress(prAdapter, prBowFsmInfo->ucBssIndex, prAssocReqFrame->aucSrcAddr); + if (prStaRec == NULL) + break; + prStaRec->eStaType = STA_TYPE_BOW_CLIENT; + prStaRec->u2DesiredNonHTRateSet &= prBowBssInfo->u2OperationalRateSet; + prStaRec->ucDesiredPhyTypeSet = prStaRec->ucPhyTypeSet & prBowBssInfo->ucPhyTypeSet; + +#if CFG_BOW_RATE_LIMITATION + /*Limit Rate Set to 24M, 48M, 54M */ + prStaRec->u2DesiredNonHTRateSet &= (RATE_SET_BIT_24M | RATE_SET_BIT_48M | RATE_SET_BIT_54M); + /*If peer cannot support the above rate set, fix on the available highest rate */ + if (prStaRec->u2DesiredNonHTRateSet == 0) { + UINT_8 ucHighestRateIndex; + + if (rateGetHighestRateIndexFromRateSet(prBowBssInfo->u2OperationalRateSet, &ucHighestRateIndex)) + prStaRec->u2DesiredNonHTRateSet = BIT(ucHighestRateIndex); + else { + /*If no available rate is found, DECLINE the association */ + *pu2StatusCode = STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED; + break; + } + } +#endif + + /*Undpate BssInfo to FW */ + bowChangeMediaState(prBowBssInfo, PARAM_MEDIA_STATE_CONNECTED); + nicUpdateBss(prAdapter, prStaRec->ucBssIndex); + + /*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; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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) +{ +#if 1 /* Marked for MT6630 */ + BOOLEAN fgReplyAuth = FALSE; + P_BSS_INFO_T prBowBssInfo; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_WLAN_AUTH_FRAME_T prAuthFrame = (P_WLAN_AUTH_FRAME_T) NULL; + OS_SYSTIME rCurrentTime; + static OS_SYSTIME rLastRejectAuthTime; + + /* + * TODO(Kevin): Call BoW functions to check .. + * 1. Check we are BoW now. + * 2. Check we can accept connection from thsi peer + * 3. Check Black List here. + */ + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; + + 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]); + + prStaRec = cnmGetStaRecByAddress(prAdapter, prBowFsmInfo->ucBssIndex, prAuthFrame->aucSrcAddr); + if (!prStaRec) { + DBGLOG(BOW, EVENT, "bowValidateAuth, cnmStaRecAlloc.\n"); + prStaRec = cnmStaRecAlloc(prAdapter, + STA_TYPE_BOW_CLIENT, prBowFsmInfo->ucBssIndex, prAuthFrame->aucSrcAddr); + + /* TODO(Kevin): Error handling of allocation of STA_RECORD_T for + * exhausted case and do removal of unused STA_RECORD_T. + */ + if (prStaRec == NULL) + return fgReplyAuth; + COPY_MAC_ADDR(prStaRec->aucMacAddr, prAuthFrame->aucSrcAddr); + prSwRfb->ucStaRecIdx = prStaRec->ucIndex; + prBowBssInfo->prStaRecOfAP = prStaRec; + + /* NOTE(Kevin): Better to change state here, not at TX Done */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + DBGLOG(BOW, EVENT, "bowValidateAuth, cnmStaRecChangeState.\n"); + } else { + prSwRfb->ucStaRecIdx = prStaRec->ucIndex; + DBGLOG(BOW, EVENT, "bowValidateAuth, prStaRec->ucIndex, %x.\n", prStaRec->ucIndex); + bssRemoveClient(prAdapter, prBowBssInfo, prStaRec); + } + + if (EQUAL_MAC_ADDR(prAuthFrame->aucSrcAddr, prBowFsmInfo->aucPeerAddress)) { + DBGLOG(BOW, EVENT, "bowValidateAuth, prStaRec->eStaType, %x.\n", prStaRec->eStaType); + DBGLOG(BOW, EVENT, "bowValidateAuth, prStaRec->ucBssIndex, %x.\n", prStaRec->ucBssIndex); + + /* 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); + *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; + } + } + + DBGLOG(BOW, EVENT, "bowValidateAuth, fgReplyAuth, %x.\n", fgReplyAuth); + return fgReplyAuth; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ +#if 1 /* Marked for MT6630 */ + 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); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + prMsgChGrant = (P_MSG_CH_GRANT_T) prMsgHdr; + ucTokenID = prMsgChGrant->ucTokenID; + u4GrantInterval = prMsgChGrant->u4GrantInterval; + + /* 1. free message */ + cnmMemFree(prAdapter, prMsgHdr); + prBowFsmInfo->fgIsChannelGranted = TRUE; + + DBGLOG(BOW, EVENT, "Entering bowRunEventChGrant.\n"); + + eFsmState = bowGetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress); + + /*Release channel */ + if ((!prBowFsmInfo->fgIsChannelRequested) || + (prBowFsmInfo->ucSeqNumOfChReq != ucTokenID) || + (eFsmState == BOW_DEVICE_STATE_DISCONNECTED) || (eFsmState == BOW_DEVICE_STATE_DISCONNECTING)) { + DBGLOG(BOW, EVENT, "BoW Channel [GIVE UP:%d]\n", ucTokenID); + DBGLOG(BOW, EVENT, "[Requested:%d][ucSeqNumOfChReq:%d][eFsmState:%d]\n", + prBowFsmInfo->fgIsChannelRequested, prBowFsmInfo->ucSeqNumOfChReq, eFsmState); + 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 */ + + DBGLOG(BOW, EVENT, "BoW Channel [GRANTED:%d].\n", ucTokenID); + + 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, prBowFsmInfo->ucBssIndex); + bowReleaseCh(prAdapter); + } + + return; +#endif /* Marked for MT6630 */ +} /* end of aisFsmRunEventChGrant() */ + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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) { + + DBGLOG(BOW, EVENT, "BoW channel [REQUEST:%d], %d, %d.\n", + prBowFsmInfo->ucSeqNumOfChReq + 1, + prBowFsmInfo->ucPrimaryChannel, prBowFsmInfo->eBand); + + 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->ucBssIndex = prBowFsmInfo->ucBssIndex; + prMsgChReq->ucTokenID = ++prBowFsmInfo->ucSeqNumOfChReq; + prMsgChReq->eReqType = CH_REQ_TYPE_JOIN; +#if 0 + prMsgChReq->u4MaxInterval = BOW_JOIN_CH_REQUEST_INTERVAL; +#else + prMsgChReq->u4MaxInterval = 1; +#endif + /* prBowFsmInfo->prTargetBssDesc->ucChannelNum; */ + prMsgChReq->ucPrimaryChannel = prBowFsmInfo->ucPrimaryChannel; + /* prBowFsmInfo->prTargetBssDesc->eSco; */ + prMsgChReq->eRfSco = CHNL_EXT_SCN; + /* prBowFsmInfo->prTargetBssDesc->eBand; */ + prMsgChReq->eRfBand = prBowFsmInfo->eBand; + + /* To do: check if 80/160MHz bandwidth is needed here */ + prMsgChReq->eRfChannelWidth = 0; + prMsgChReq->ucRfCenterFreqSeg1 = 0; + prMsgChReq->ucRfCenterFreqSeg2 = 0; + + 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) { + DBGLOG(BOW, EVENT, + "BoW channel [RELEASE:%d] %d, %d.\n", prBowFsmInfo->ucSeqNumOfChReq, + prBowFsmInfo->ucPrimaryChannel, prBowFsmInfo->eBand); + + 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->ucBssIndex = prBowFsmInfo->ucBssIndex; + prMsgChAbort->ucTokenID = prBowFsmInfo->ucSeqNumOfChReq; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChAbort, MSG_SEND_METHOD_BUF); + } +} /* end of aisFsmReleaseCh() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Media Disconnect" to HOST +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bowChGrantedTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + ENUM_BOW_DEVICE_STATE eFsmState; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + DBGLOG(BOW, EVENT, "BoW Channel [TIMEOUT]\n"); + +#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 +} + +#endif /* Marked for MT6630 */ + +BOOLEAN bowNotifyAllLinkDisconnected(IN P_ADAPTER_T prAdapter) +{ +#if 1 /* Marked for MT6630 */ + + UINT_8 ucBowTableIdx = 0; + CMD_INFO_T rCmdInfo; + P_BOW_FSM_INFO_T prBowFsmInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + 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); + 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); +#if 1 + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + prBowFsmInfo->ucBssIndex, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, 0, NULL, 0); +#else + wlanbowCmdEventLinkDisconnected(prAdapter, &rCmdInfo, NULL); +#endif + } + + ucBowTableIdx += 1; + } + + return TRUE; + +#else + return 0; +#endif +} + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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)) { + + 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); + + 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 * pprBowTable) +{ + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + if (arBowTable[ucBowTableIdx].fgIsValid) { + + DBGLOG(BOW, EVENT, + "bowGetBowTableContent, arBowTable[idx].fgIsValid, %x, %x.\n", + ucBowTableIdx, arBowTable[ucBowTableIdx].fgIsValid); + DBGLOG(BOW, EVENT, "GET State [%d]\n", arBowTable[ucBowTableIdx].eState); + *pprBowTable = &(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); */ + + DBGLOG(BOW, EVENT, "SET State [%d]\n", arBowTable[ucBowTableIdx].eState); + DBGLOG(BOW, EVENT, + "kalCheckBowifVaild, arBowTable[ucBowTableIdx].fgIsValid, %x, %x.\n", ucBowTableIdx, + arBowTable[ucBowTableIdx].fgIsValid); + + 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)) { + + 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); + 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) { + DBGLOG(BOW, EVENT, + "bowGetBowTableFreeEntry, arBowTable[idx].fgIsValid, %x, %x.\n", + idx, arBowTable[idx].fgIsValid); + *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)) { + DBGLOG(BOW, EVENT, + "bowGetState, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, + aucPeerAddress[0], aucPeerAddress[1], aucPeerAddress[2], + aucPeerAddress[3], aucPeerAddress[4], aucPeerAddress[5]); + DBGLOG(BOW, EVENT, + "bowGetState, arBowTable[idx].aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", + idx, arBowTable[idx].aucPeerAddress[0], + arBowTable[idx].aucPeerAddress[1], + arBowTable[idx].aucPeerAddress[2], + arBowTable[idx].aucPeerAddress[3], + arBowTable[idx].aucPeerAddress[4], arBowTable[idx].aucPeerAddress[5]); + DBGLOG(BOW, EVENT, + "bowGetState, arBowTable[idx].fgIsValid, %x, %x.\n", idx, arBowTable[idx].fgIsValid); + DBGLOG(BOW, EVENT, + "bowGetState, arBowTable[idx].eState;, %x, %x.\n", idx, arBowTable[idx].eState); + DBGLOG(BOW, EVENT, "GET State [%d]\n", arBowTable[idx].eState); + + 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; + DBGLOG(BOW, EVENT, "SET State [%d]\n", eState); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + kalSetBowState(prAdapter->prGlueInfo, eState, aucPeerAddress); + return TRUE; + } + return FALSE; +} + +#endif + +#endif /* Marked for MT6630 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/wlan_lib.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/wlan_lib.c new file mode 100644 index 0000000000000..92e5979eed15a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/wlan_lib.c @@ -0,0 +1,7609 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * ! \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. + */ + +/******************************************************************************* + * C O M P I L E 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 + ******************************************************************************** + */ + +/* 6.1.1.2 Interpretation of priority parameter in MAC service primitives */ +/* Static convert the Priority Parameter/TID(User Priority/TS Identifier) to Traffic Class */ +const UINT_8 aucPriorityParam2TC[] = { + TC1_INDEX, + TC0_INDEX, + TC0_INDEX, + TC1_INDEX, + TC2_INDEX, + TC2_INDEX, + TC3_INDEX, + TC3_INDEX +}; + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************** + */ +typedef struct _CODE_MAPPING_T { + UINT_32 u4RegisterValue; + INT_32 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 +******************************************************************************** +*/ +#if CFG_ENABLE_FW_DOWNLOAD +static WLAN_STATUS +wlanImageFullDownload(IN P_ADAPTER_T prAdapter, + IN PVOID pvFwImageMapFile, + IN UINT_32 u4FwLoadAddr, + IN UINT_32 u4FwImageFileLength); + +#if CFG_ENABLE_FW_DIVIDED_DOWNLOAD +static WLAN_STATUS +wlanImageDividDownloadByEntry(IN P_ADAPTER_T prAdapter, + IN PVOID pvFwImageMapFile, + IN P_FIRMWARE_DIVIDED_DOWNLOAD_T prFwHead, + IN UINT_32 index); + +static WLAN_STATUS +wlanImageDividDownload(IN P_ADAPTER_T prAdapter, IN PVOID pvFwImageMapFile); +#endif +#endif +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +UINT_32 dumpCrBeforeReset(P_GLUE_INFO_T prGlueInfo, UINT_16 u2ChipID) +{ +#if defined(MT6631) + UINT_32 val = 0; + UINT_32 u4InfraPseOffset = 0x0394; + + if (prGlueInfo == NULL) { + DBGLOG(INIT, WARN, "prGlueInfo == NULL\n"); + return 1; + } + + /*Pin-Hao need check some cr.*/ + /* SET INFRA AO REMAPPING PSE Client REG according to Chip ID */ + switch (u2ChipID) { + case 0x6797: + u4InfraPseOffset = 0x0340; + break; + case 0x6759: + case 0x6758: + case 0x6775: + u4InfraPseOffset = 0x0384; + break; + case 0x6771: + u4InfraPseOffset = 0x0394; + break; + default: + DBGLOG(INIT, WARN, "Using default offset 0x%04x for chip id 0x%04x\n", + u4InfraPseOffset, u2ChipID); + break; + } + + if (prGlueInfo->rHifInfo.HifRegBaseAddr == NULL) { + DBGLOG(INIT, ERROR, "prGlueInfo->rHifInfo.InfraRegBaseAddr == NULL.\n"); + return 1; + } + + DBGLOG(INIT, ERROR, + "HIF_BASE_ADDR+0x300: 0x%08x\n", + CONNSYS_REG_READ(prGlueInfo->rHifInfo.HifRegBaseAddr, + 0x300)); + + DBGLOG(INIT, ERROR, + "HIF_BASE_ADDR+0x304: 0x%08x\n", + CONNSYS_REG_READ(prGlueInfo->rHifInfo.HifRegBaseAddr, + 0x304)); + + DBGLOG(INIT, ERROR, + "HIF_BASE_ADDR+0x308: 0x%08x\n", + CONNSYS_REG_READ(prGlueInfo->rHifInfo.HifRegBaseAddr, + 0x308)); + + DBGLOG(INIT, ERROR, + "HIF_BASE_ADDR+0x310: 0x%08x\n", + CONNSYS_REG_READ(prGlueInfo->rHifInfo.HifRegBaseAddr, + 0x310)); + + DBGLOG(INIT, ERROR, + "HIF_BASE_ADDR+0x320: 0x%08x\n", + CONNSYS_REG_READ(prGlueInfo->rHifInfo.HifRegBaseAddr, + 0x320)); + + DBGLOG(INIT, ERROR, + "HIF_BASE_ADDR+0x328: 0x%08x\n", + CONNSYS_REG_READ(prGlueInfo->rHifInfo.HifRegBaseAddr, + 0x328)); + + DBGLOG(INIT, ERROR, + "HIF_BASE_ADDR+0x32c: 0x%08x\n", + CONNSYS_REG_READ(prGlueInfo->rHifInfo.HifRegBaseAddr, + 0x32c)); + + DBGLOG(INIT, ERROR, + "HIF_BASE_ADDR+0x330: 0x%08x\n", + CONNSYS_REG_READ(prGlueInfo->rHifInfo.HifRegBaseAddr, + 0x330)); + + if (prGlueInfo->rHifInfo.InfraRegBaseAddr == NULL) { + DBGLOG(INIT, ERROR, "prGlueInfo->rHifInfo.InfraRegBaseAddr == NULL.\n"); + return 1; + } + + DBGLOG(INIT, ERROR, "INFRASYS_AO_REG_BASE+0x0394 write 0x800c.\n"); + if (u2ChipID == 0x6771) { + val = 0x800c; + CONNSYS_REG_WRITE(prGlueInfo->rHifInfo.InfraRegBaseAddr, + u4InfraPseOffset, val); + } else { + val = 0x800c << 16; + CONNSYS_REG_WRITE(prGlueInfo->rHifInfo.InfraRegBaseAddr, u4InfraPseOffset, + CONNSYS_REG_READ(prGlueInfo->rHifInfo.InfraRegBaseAddr, + u4InfraPseOffset) | val); + } + + if (prGlueInfo->rHifInfo.ConnCfgRegBaseAddr == NULL) { + DBGLOG(INIT, ERROR, "prGlueInfo->rHifInfo.ConnCfgRegBaseAddr == NULL.\n"); + return 1; + } + + DBGLOG(INIT, ERROR, "CONNSYS_CONFIG+0x6c write 0x6\n"); + val = 0x6; + CONNSYS_REG_WRITE(prGlueInfo->rHifInfo.ConnCfgRegBaseAddr, + 0x6c, val); + DBGLOG(INIT, ERROR, + "CONNSYS_CONFIG+0x6c: 0x%08x\n", + CONNSYS_REG_READ(prGlueInfo->rHifInfo.ConnCfgRegBaseAddr, + 0x6c)); + + DBGLOG(INIT, ERROR, "CONNSYS_CONFIG+0x6c write 0x3\n"); + val = 0x3; + CONNSYS_REG_WRITE(prGlueInfo->rHifInfo.ConnCfgRegBaseAddr, + 0x6c, val); + DBGLOG(INIT, ERROR, + "CONNSYS_CONFIG+0x6c: 0x%08x\n", + CONNSYS_REG_READ(prGlueInfo->rHifInfo.ConnCfgRegBaseAddr, + 0x6c)); + + DBGLOG(INIT, ERROR, "CONNSYS_CONFIG+0x6c write 0x4\n"); + val = 0x4; + CONNSYS_REG_WRITE(prGlueInfo->rHifInfo.ConnCfgRegBaseAddr, + 0x6c, val); + DBGLOG(INIT, ERROR, + "CONNSYS_CONFIG+0x6c: 0x%08x\n", + CONNSYS_REG_READ(prGlueInfo->rHifInfo.ConnCfgRegBaseAddr, + 0x6c)); + + DBGLOG(INIT, ERROR, "CONNSYS_CONFIG+0x6c write 0x12\n"); + val = 0x12; + CONNSYS_REG_WRITE(prGlueInfo->rHifInfo.ConnCfgRegBaseAddr, + 0x6c, val); + DBGLOG(INIT, ERROR, + "CONNSYS_CONFIG+0x6c: 0x%08x\n", + CONNSYS_REG_READ(prGlueInfo->rHifInfo.ConnCfgRegBaseAddr, + 0x6c)); + + DBGLOG(INIT, ERROR, "CONNSYS_CONFIG+0x6c write 0x17\n"); + val = 0x17; + CONNSYS_REG_WRITE(prGlueInfo->rHifInfo.ConnCfgRegBaseAddr, + 0x6c, val); + DBGLOG(INIT, ERROR, + "CONNSYS_CONFIG+0x6c: 0x%08x\n", + CONNSYS_REG_READ(prGlueInfo->rHifInfo.ConnCfgRegBaseAddr, + 0x6c)); +#endif + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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, FALSE); + +} /* 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)); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + UINT_32 i, u4Value = 0; + UINT_32 u4WHISR = 0; + UINT_16 au2TxCount[16]; +#if CFG_ENABLE_FW_DOWNLOAD + UINT_32 u4FwLoadAddr = CFG_FW_LOAD_ADDRESS; + UINT_32 u4FwStartAddr = CFG_FW_START_ADDRESS; + PVOID prFwBuffer = NULL; + UINT_32 u4FwSize = 0; + +#if CFG_ENABLE_FW_DIVIDED_DOWNLOAD + P_FIRMWARE_DIVIDED_DOWNLOAD_T prFwHead; + const UINT_32 u4CRCOffset = offsetof(FIRMWARE_DIVIDED_DOWNLOAD_T, u4NumOfEntries); +#endif +#endif + + enum ENUM_ADAPTER_START_FAIL_REASON { + ALLOC_ADAPTER_MEM_FAIL, + DRIVER_OWN_FAIL, + INIT_ADAPTER_FAIL, + RAM_CODE_DOWNLOAD_FAIL, + WAIT_FIRMWARE_READY_FAIL, + FAIL_REASON_MAX + } eFailReason; + ASSERT(prAdapter); + + DEBUGFUNC("wlanAdapterStart"); + + eFailReason = FAIL_REASON_MAX; + /* 4 <0> Reset variables in ADAPTER_T */ + /* prAdapter->fgIsFwOwn = TRUE; */ + prAdapter->fgIsEnterD3ReqIssued = FALSE; + + prAdapter->u4OwnFailedCount = 0; + prAdapter->u4OwnFailedLogCount = 0; + + QUEUE_INITIALIZE(&(prAdapter->rPendingCmdQueue)); +#if CFG_SUPPORT_MULTITHREAD + QUEUE_INITIALIZE(&prAdapter->rTxCmdQueue); + QUEUE_INITIALIZE(&prAdapter->rTxCmdDoneQueue); + QUEUE_INITIALIZE(&prAdapter->rTxP0Queue); + QUEUE_INITIALIZE(&prAdapter->rTxP1Queue); + QUEUE_INITIALIZE(&prAdapter->rRxQueue); +#endif + + /* Initialize rWlanInfo */ + kalMemSet(&(prAdapter->rWlanInfo), 0, sizeof(WLAN_INFO_T)); + + /* Initialize aprBssInfo[]. + * Important: index shall be same when mapping between aprBssInfo[] + * and arBssInfoPool[]. rP2pDevInfo is indexed to final one. + */ + for (i = 0; i < BSS_INFO_NUM; i++) + prAdapter->aprBssInfo[i] = &prAdapter->rWifiVar.arBssInfoPool[i]; + prAdapter->aprBssInfo[P2P_DEV_BSS_INDEX] = &prAdapter->rWifiVar.rP2pDevInfo; + + /* 4 <0.1> reset fgIsBusAccessFailed */ + fgIsBusAccessFailed = FALSE; + prAdapter->ulSuspendFlag = 0; + do { + u4Status = nicAllocateAdapterMemory(prAdapter); + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "nicAllocateAdapterMemory Error!\n"); + u4Status = WLAN_STATUS_FAILURE; + eFailReason = ALLOC_ADAPTER_MEM_FAIL; + break; + } + + prAdapter->u4OsPacketFilter = PARAM_PACKET_FILTER_SUPPORTED; + + DBGLOG(INIT, TRACE, "wlanAdapterStart(): Acquiring LP-OWN\n"); + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + DBGLOG(INIT, TRACE, "wlanAdapterStart(): Acquiring LP-OWN-end\n"); + +#if !CFG_ENABLE_FULL_PM + nicpmSetDriverOwn(prAdapter); +#endif + + if (prAdapter->fgIsFwOwn == TRUE) { + DBGLOG(INIT, ERROR, "nicpmSetDriverOwn() failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + eFailReason = DRIVER_OWN_FAIL; + break; + } + /* 4 <1> Initialize the Adapter */ + u4Status = nicInitializeAdapter(prAdapter); + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "nicInitializeAdapter failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + eFailReason = INIT_ADAPTER_FAIL; + break; + } + + /* 4 <2.1> Initialize System Service (MGMT Memory pool and STA_REC) */ + nicInitSystemService(prAdapter); + + /* 4 <2.2> Initialize Feature Options */ + wlanInitFeatureOption(prAdapter); +#if CFG_SUPPORT_MTK_SYNERGY + if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) { + if (prRegInfo->prNvramSettings->u2FeatureReserved & BIT(MTK_FEATURE_2G_256QAM_DISABLED)) + prAdapter->rWifiVar.aucMtkFeature[0] &= ~(MTK_SYNERGY_CAP_SUPPORT_24G_MCS89); + } +#endif + + + /* 4 <2.3> Overwrite debug level settings */ + wlanCfgSetDebugLevel(prAdapter); + + + /* 4 <3> Initialize Tx */ + nicTxInitialize(prAdapter); + wlanDefTxPowerCfg(prAdapter); + + /* 4 <4> Initialize Rx */ + nicRxInitialize(prAdapter); + +#if CFG_ENABLE_FW_DOWNLOAD + if (!kalFirmwareImageMapping(prAdapter->prGlueInfo, &prFwBuffer, &u4FwSize)) { + DBGLOG(INIT, ERROR, "No valid RAM code found!\n"); + u4Status = WLAN_STATUS_FAILURE; + eFailReason = RAM_CODE_DOWNLOAD_FAIL; + break; + } + +#if defined(MT6631) && defined(CONFIG_OF) + if (prAdapter->prGlueInfo->rHifInfo.Dev) { + if (of_property_read_u32_index(prAdapter->prGlueInfo->rHifInfo.Dev->of_node, + "hardware-values", 1, &u4FwLoadAddr) || + of_property_read_u32_index(prAdapter->prGlueInfo->rHifInfo.Dev->of_node, + "hardware-values", 2, &u4FwStartAddr)) + DBGLOG(INIT, ERROR, "Failed to get hardware-values from DT!\n"); + } +#endif + + prRegInfo->u4LoadAddress = u4FwLoadAddr; + prRegInfo->u4StartAddress = u4FwStartAddr; + + /* 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 */ + DBGLOG(INIT, TRACE, "FW download start...\n"); + +#if CFG_ENABLE_FW_DIVIDED_DOWNLOAD + /* 3a. parse file header for decision of divided firmware download or not */ + prFwHead = (P_FIRMWARE_DIVIDED_DOWNLOAD_T)prFwBuffer; + + if (prFwHead->u4Signature == MTK_WIFI_SIGNATURE && + prFwHead->u4CRC == wlanCRC32((PUINT_8)prFwBuffer + u4CRCOffset, + u4FwSize - u4CRCOffset)) { + /* 3b. engage divided firmware downloading */ + u4Status = wlanImageDividDownload(prAdapter, prFwBuffer); + } else +#endif + u4Status = wlanImageFullDownload(prAdapter, prFwBuffer, u4FwLoadAddr, u4FwSize); + + /* escape to top */ + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "FW download failed!\n"); + eFailReason = RAM_CODE_DOWNLOAD_FAIL; + break; + } + +#if !CFG_ENABLE_FW_DOWNLOAD_ACK + /* Send INIT_CMD_ID_QUERY_PENDING_ERROR command and wait for response */ + if (wlanImageQueryStatus(prAdapter) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "FW download failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + eFailReason = RAM_CODE_DOWNLOAD_FAIL; + break; + } +#endif + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, NULL, prFwBuffer); + DBGLOG(INIT, INFO, "FW download end\n"); +#endif + + /* 4. send Wi-Fi Start command */ +#if CFG_OVERRIDE_FW_START_ADDRESS + wlanConfigWifiFunc(prAdapter, TRUE, prRegInfo->u4StartAddress); +#else + wlanConfigWifiFunc(prAdapter, FALSE, 0); +#endif + + DBGLOG(INIT, TRACE, "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, INFO, "Ready bit asserted\n"); + break; + } else if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + eFailReason = WAIT_FIRMWARE_READY_FAIL; + break; + } else if (i >= CFG_RESPONSE_POLLING_TIMEOUT) { + UINT_32 u4MailBox0; + + nicGetMailbox(prAdapter, 0, &u4MailBox0); + DBGLOG(INIT, ERROR, "Waiting for Ready bit timeout, Device to Host MailBox 0x%x\n", + (u4MailBox0 & 0x0000FFFF)); + u4Status = WLAN_STATUS_FAILURE; + eFailReason = WAIT_FIRMWARE_READY_FAIL; + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP | RST_FLAG_PREVENT_POWER_OFF); + break; + } + + i++; + kalMsleep(10); + } + + if (u4Status == WLAN_STATUS_SUCCESS) { + /* 1. reset interrupt status */ + HAL_READ_INTR_STATUS(prAdapter, 4, (PUINT_8)&u4WHISR); + if (HAL_IS_TX_DONE_INTR(u4WHISR)) + HAL_READ_TX_RELEASED_COUNT(prAdapter, au2TxCount); + + /* 2. query & reset TX Resource for normal operation */ + wlanQueryNicResourceInformation(prAdapter); + +#if (CFG_SUPPORT_NIC_CAPABILITY == 1) + /* 3. query for NIC capability */ + wlanQueryNicCapability(prAdapter); +#endif + + /* 4. update basic configuration */ + wlanUpdateBasicConfig(prAdapter); + + /* 5. Override network address */ + wlanUpdateNetworkAddress(prAdapter); + + /* 6. Apply Network Address */ + nicApplyNetworkAddress(prAdapter); + + /* 7. 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) { + DBGLOG(INIT, ERROR, "Wait firmware ready fail\n"); + eFailReason = WAIT_FIRMWARE_READY_FAIL; + break; + } + + /* OID timeout timer initialize */ + cnmTimerInitTimer(prAdapter, + &prAdapter->rOidTimeoutTimer, + (PFN_MGMT_TIMEOUT_FUNC) wlanReleasePendingOid, (ULONG) NULL); + + prAdapter->ucOidTimeoutCount = 0; + + prAdapter->fgIsChipNoAck = FALSE; + + /* Return Indicated Rfb list timer */ + cnmTimerInitTimer(prAdapter, + &prAdapter->rPacketDelaySetupTimer, + (PFN_MGMT_TIMEOUT_FUNC) wlanReturnPacketDelaySetupTimeout, (ULONG) NULL); + + /* Power state initialization */ + prAdapter->fgWiFiInSleepyState = FALSE; + prAdapter->rAcpiState = ACPI_STATE_D0; + + /* Online scan option */ + if (prRegInfo->fgDisOnlineScan == 0) + prAdapter->fgEnOnlineScan = TRUE; + else + prAdapter->fgEnOnlineScan = FALSE; + + /* Beacon lost detection option */ + if (prRegInfo->fgDisBcnLostDetection != 0) + prAdapter->fgDisBcnLostDetection = TRUE; + + /* Load compile time constant */ + prAdapter->rWlanInfo.u2BeaconPeriod = CFG_INIT_ADHOC_BEACON_INTERVAL; + prAdapter->rWlanInfo.u2AtimWindow = CFG_INIT_ADHOC_ATIM_WINDOW; + +#if 1 /* set PM parameters */ + prAdapter->fgEnArpFilter = prRegInfo->fgEnArpFilter; + prAdapter->u4PsCurrentMeasureEn = prRegInfo->u4PsCurrentMeasureEn; + + prAdapter->u4UapsdAcBmp = prRegInfo->u4UapsdAcBmp; + + prAdapter->u4MaxSpLen = prRegInfo->u4MaxSpLen; + + DBGLOG(INIT, TRACE, "[1] fgEnArpFilter:0x%x, u4UapsdAcBmp:0x%x, u4MaxSpLen:0x%x", + prAdapter->fgEnArpFilter, prAdapter->u4UapsdAcBmp, prAdapter->u4MaxSpLen); + + prAdapter->fgEnCtiaPowerMode = FALSE; + prAdapter->fgEnCtiaMode = 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; + +#if CFG_RX_BA_REORDERING_ENHANCEMENT + prAdapter->rWifiVar.fgEnableReportIndependentPkt = TRUE; +#endif + /* configure available PHY type set */ + nicSetAvailablePhyTypeSet(prAdapter); + +#if 0 /* Marked for MT6630 */ +#if 1 /* set PM parameters */ + { +#if CFG_SUPPORT_PWR_MGT + prAdapter->u4PowerMode = prRegInfo->u4PowerMode; +#if CFG_ENABLE_WIFI_DIRECT + prAdapter->rWlanInfo.arPowerSaveMode[NETWORK_TYPE_P2P_INDEX].ucNetTypeIndex = + NETWORK_TYPE_P2P_INDEX; + prAdapter->rWlanInfo.arPowerSaveMode[NETWORK_TYPE_P2P_INDEX].ucPsProfile = ENUM_PSP_FAST_SWITCH; +#endif +#else + prAdapter->u4PowerMode = ENUM_PSP_CONTINUOUS_ACTIVE; +#endif + + nicConfigPowerSaveProfile(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, prAdapter->u4PowerMode, FALSE); + } + +#endif +#endif + +#if CFG_SUPPORT_NVRAM + /* load manufacture data */ + if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) + wlanLoadManufactureData(prAdapter, prRegInfo); + else + DBGLOG(INIT, WARN, "%s: load manufacture data fail\n", __func__); +#endif + +#if 0 + /* Update Auto rate parameters in FW */ + nicRlmArUpdateParms(prAdapter, + prRegInfo->u4ArSysParam0, + prRegInfo->u4ArSysParam1, prRegInfo->u4ArSysParam2, prRegInfo->u4ArSysParam3); +#endif + } while (FALSE); + + if (u4Status == WLAN_STATUS_SUCCESS) { + /* restore to hardware default */ + HAL_SET_INTR_STATUS_READ_CLEAR(prAdapter); + HAL_SET_MAILBOX_READ_CLEAR(prAdapter, FALSE); + + /* Enable interrupt */ + nicEnableInterrupt(prAdapter); + + } else { + /* release allocated memory */ + switch (eFailReason) { + case WAIT_FIRMWARE_READY_FAIL: + nicRxUninitialize(prAdapter); + nicTxRelease(prAdapter, FALSE); + /* System Service Uninitialization */ + nicUninitSystemService(prAdapter); + nicReleaseAdapterMemory(prAdapter); + wlanPollingCpupcr(4, 5); + break; + case RAM_CODE_DOWNLOAD_FAIL: + nicRxUninitialize(prAdapter); + nicTxRelease(prAdapter, FALSE); + /* System Service Uninitialization */ + nicUninitSystemService(prAdapter); + nicReleaseAdapterMemory(prAdapter); + wlanPollingCpupcr(4, 5); + break; + case INIT_ADAPTER_FAIL: + nicReleaseAdapterMemory(prAdapter); + break; + case DRIVER_OWN_FAIL: + nicReleaseAdapterMemory(prAdapter); + break; + case ALLOC_ADAPTER_MEM_FAIL: + default: + break; + } + } + + return u4Status; +} /* wlanAdapterStart */ + +#if CFG_ENABLE_FW_DOWNLOAD +static WLAN_STATUS +wlanImageFullDownload(IN P_ADAPTER_T prAdapter, + IN PVOID pvFwImageMapFile, + IN UINT_32 u4FwLoadAddr, + IN UINT_32 u4FwImageFileLength) +{ + UINT_32 u4ImgSecSize; + UINT_32 j; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + do { + if (wlanImageSectionConfig(prAdapter, + u4FwLoadAddr, + u4FwImageFileLength, + TRUE, + TRUE, + 0) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "Firmware download configuration failed!\n"); + + u4Status = WLAN_STATUS_FAILURE; + break; + } + + for (j = 0; j < u4FwImageFileLength; j += CMD_PKT_SIZE_FOR_IMAGE) { + if (j + CMD_PKT_SIZE_FOR_IMAGE < u4FwImageFileLength) + u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; + else + u4ImgSecSize = u4FwImageFileLength - j; + + if (wlanImageSectionDownload(prAdapter, + u4ImgSecSize, + (PUINT_8) pvFwImageMapFile + j) != + WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "Firmware scatter download failed!\n"); + + u4Status = WLAN_STATUS_FAILURE; + break; + } + } + + } while (0); + + return u4Status; +} + +#if CFG_ENABLE_FW_DIVIDED_DOWNLOAD +static WLAN_STATUS +wlanImageDividDownloadByEntry(IN P_ADAPTER_T prAdapter, + IN PVOID pvFwImageMapFile, + IN P_FIRMWARE_DIVIDED_DOWNLOAD_T prFwHead, + IN UINT_32 index) +{ + UINT_32 u4ImgSecSize; + UINT_32 j; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + do { + if (wlanImageSectionConfig(prAdapter, + prFwHead->arSection[index].u4DestAddr, + prFwHead->arSection[index].u4Length, + index == 0 ? TRUE : FALSE, +#if defined(MT6631) + prFwHead->arSection[index].ucEnc ? TRUE : FALSE, + prFwHead->arSection[index].ucKIdx +#else + TRUE, + 0 +#endif + ) != WLAN_STATUS_SUCCESS) { + + DBGLOG(INIT, ERROR, "Firmware download configuration failed! idx %u, dst 0x%08x, len %u\n", + index, + prFwHead->arSection[index].u4DestAddr, + prFwHead->arSection[index].u4Length); + + u4Status = WLAN_STATUS_FAILURE; + break; + } + + for (j = 0; j < prFwHead->arSection[index].u4Length; j += CMD_PKT_SIZE_FOR_IMAGE) { + if (j + CMD_PKT_SIZE_FOR_IMAGE < prFwHead->arSection[index].u4Length) + u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; + else + u4ImgSecSize = prFwHead->arSection[index].u4Length - j; + + if (wlanImageSectionDownload(prAdapter, + u4ImgSecSize, + (PUINT_8)pvFwImageMapFile + + prFwHead->arSection[index].u4Offset + j) != + WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "Firmware scatter download failed! idx %u, dst 0x%08x, len %u, offset %u\n", + index, + prFwHead->arSection[index].u4DestAddr, + prFwHead->arSection[index].u4Length, + j); + + u4Status = WLAN_STATUS_FAILURE; + break; + } + } + + } while (0); + + return u4Status; +} + +static WLAN_STATUS +wlanImageDividDownload(IN P_ADAPTER_T prAdapter, IN PVOID pvFwImageMapFile) +{ +#define ENTRY_DIRECTLY_TO_CHIP 2 + + UINT_32 i; + P_FIRMWARE_DIVIDED_DOWNLOAD_T prFwHead = (P_FIRMWARE_DIVIDED_DOWNLOAD_T) pvFwImageMapFile; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; +#if defined(MT6631) + UINT_8 __iomem *prWifiEmiBaseAddr; +#endif + + /* engage divided firmware downloading */ + /* DLM + ILM */ + for (i = 0; i < prFwHead->u4NumOfEntries && i < ENTRY_DIRECTLY_TO_CHIP; i++) { + u4Status = wlanImageDividDownloadByEntry(prAdapter, + pvFwImageMapFile, prFwHead, i); + if (u4Status == WLAN_STATUS_FAILURE) + return u4Status; + } + +#if defined(MT6631) +/* WIFI using TOP 512KB, but the last 32KB is reserved for BT */ +#define WIFI_EMI_AVAILABLE_MEM_SIZE (480 * 1024) + + if (!gConEmiPhyBase) { + DBGLOG(INIT, ERROR, "Consys EMI phy address is invalid\n"); + return WLAN_STATUS_FAILURE; + } + + kalSetEmiMpuProtection(gConEmiPhyBase, WIFI_EMI_MEM_SIZE, FALSE); + prWifiEmiBaseAddr = ioremap_nocache(gConEmiPhyBase, WIFI_EMI_AVAILABLE_MEM_SIZE); + + /* IEMI + DEMI */ + for (i = ENTRY_DIRECTLY_TO_CHIP; i < prFwHead->u4NumOfEntries; i++) { + UINT_32 u4DestAddr = prFwHead->arSection[i].u4DestAddr & 0xfffff; + UINT_32 u4Length = prFwHead->arSection[i].u4Length; + + if (u4DestAddr + u4Length > WIFI_EMI_MEM_SIZE) { + DBGLOG(INIT, ERROR, "FW section length out of bound! idx %u, dst 0x%08x, len %u\n", + i, u4DestAddr, u4Length); + u4Status = WLAN_STATUS_FAILURE; + break; + } + DBGLOG(INIT, TRACE, + "ConsysEmiPhyBase 0x%lx, WifiEmiBaseAddr %p, idx %u, dst 0x%08x, len %u\n", + gConEmiPhyBase, prWifiEmiBaseAddr, i, u4DestAddr, u4Length); + + /* TODO, EMI download only if reboot */ + kalMemCopy(prWifiEmiBaseAddr + u4DestAddr, + (PUINT_8)pvFwImageMapFile + prFwHead->arSection[i].u4Offset, + u4Length); + } + + kalSetEmiMpuProtection(gConEmiPhyBase, WIFI_EMI_MEM_SIZE, TRUE); + iounmap(prWifiEmiBaseAddr); +#endif + return u4Status; +} +#endif +#endif + +WLAN_STATUS wlanPowerOffInt(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4Value = 0; + UINT_32 u4Feedback = 0; + UINT_32 u4Loop = 0; + + + if (!prAdapter) + return WLAN_STATUS_SUCCESS; + + wlanPollingCpupcr(4, 5); + + DBGLOG(INIT, INFO, "Using INT for Power OFF\n"); + nicPutMailbox(prAdapter, CFG_MCU_POWER_OFF_MAILBOX_INDEX, + CFG_MCU_POWER_OFF_MAGIC_CODE); + + HAL_MCR_WR(prAdapter, MCR_WSICR, BIT(CFG_MCU_POWER_OFF_SOFTINT_BIT)); + + for (u4Loop = 0; u4Loop < CFG_MCU_POWER_OFF_POLLING_CNT; u4Loop++) { + nicGetMailbox(prAdapter, CFG_MCU_POWER_OFF_MAILBOX_INDEX, &u4Feedback); + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4Value); + DBGLOG(INIT, INFO, "INT FeedBack: 0x%x, MCR_WCIR: 0x%x\n", u4Feedback, u4Value); + + if ((u4Value & WCIR_WLAN_READY) == 0) { + /* Cleanup MailBox */ + nicPutMailbox(prAdapter, CFG_MCU_POWER_OFF_MAILBOX_INDEX, 0x0); + DBGLOG(INIT, INFO, "Power OFF by INT successfully\n"); + return WLAN_STATUS_SUCCESS; + } + u4Feedback = 0; + u4Value = 0; + wlanPollingCpupcr(4, 5); + } + + /* Cleanup MailBox */ + nicPutMailbox(prAdapter, CFG_MCU_POWER_OFF_MAILBOX_INDEX, 0x0); + + return WLAN_STATUS_FAILURE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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); + + /* Release all CMD/MGMT/SEC frame in command queue */ + kalClearCommandQueue(prAdapter->prGlueInfo); + +#if CFG_SUPPORT_MULTITHREAD + + /* Flush all items in queues for multi-thread */ + wlanClearTxCommandQueue(prAdapter); + + wlanClearTxCommandDoneQueue(prAdapter); + + wlanClearDataQueue(prAdapter); + + wlanClearRxToOsQueue(prAdapter); + +#endif + + if (prAdapter->rAcpiState == ACPI_STATE_D0 && + !wlanIsChipNoAck(prAdapter) && !kalIsCardRemoved(prAdapter->prGlueInfo)) { + UINT_32 u4RegValue = 0; + UINT_32 u4RegValueNew = 0; + + /* 0. Disable interrupt, this can be done without Driver own */ + nicDisableInterrupt(prAdapter); + + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + HAL_MCR_RD(prAdapter, MCR_WHLPCR, &u4RegValue); + + /* 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 cleard */ + i = 0; + while (1) { + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4Value); + + if ((u4Value & WCIR_WLAN_READY) == 0) { + break; + } else if (i >= CFG_RESPONSE_CLEAR_RDY_TIMEOUT && i < CFG_RESPONSE_POLLING_TIMEOUT) { +#if defined(MT6631) + if (prAdapter->prGlueInfo->rHifInfo.InfraRegBaseAddr) + DBGLOG(INIT, INFO, + "count %d, INFRA_TOPAXI_PROTECTEN: 0x%08x, INFRA_TOPAXI_PROTECTEN_STA1: 0x%08x\n", + i, + CONNSYS_REG_READ(prAdapter->prGlueInfo->rHifInfo.InfraRegBaseAddr, + INFRA_TOPAXI_PROTECTEN), + CONNSYS_REG_READ(prAdapter->prGlueInfo->rHifInfo.InfraRegBaseAddr, + INFRA_TOPAXI_PROTECTEN_STA1)); +#endif + HAL_MCR_RD(prAdapter, MCR_WHLPCR, &u4RegValueNew); + DBGLOG(INIT, INFO, + "Recorded WHLPCR: 0x%08x, Current WHLPCR: 0x%08x, fgIsFwOwn: %d\n", + u4RegValue, u4RegValueNew, prAdapter->fgIsFwOwn); + if (wlanPowerOffInt(prAdapter) == WLAN_STATUS_SUCCESS) + break; +#if defined(MT6631) + if (prAdapter->prGlueInfo->rHifInfo.HifRegBaseAddr) + DBGLOG(INIT, INFO, + "count %d, HIF_DBGCR02: 0x%08x, HIF_DBGCR08: 0x%08x\n", + i, + CONNSYS_REG_READ(prAdapter->prGlueInfo->rHifInfo.HifRegBaseAddr, + CONN_HIF_DBGCR02), + CONNSYS_REG_READ(prAdapter->prGlueInfo->rHifInfo.HifRegBaseAddr, + CONN_HIF_DBGCR08)); +#endif + } else if (kalIsCardRemoved(prAdapter->prGlueInfo) + || fgIsBusAccessFailed || (i >= CFG_RESPONSE_POLLING_TIMEOUT)) { + + DBGLOG(INIT, WARN, + "%s: Failure to get RDY bit cleared! CardRemoved[%u] BusFailed[%u] Timeout[%u]", + __func__, + kalIsCardRemoved(prAdapter->prGlueInfo), fgIsBusAccessFailed, i); + wlanPollingCpupcr(4, 5); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP | RST_FLAG_PREVENT_POWER_OFF); + break; + } + i++; + kalMsleep(1); + } + } + + /* 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, FALSE); + + /* MGMT - unitialization */ + nicUninitMGMT(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); + + if (KAL_WAKE_LOCK_ACTIVE(prAdapter, &prAdapter->prGlueInfo->rIntrWakeLock)) + KAL_WAKE_UNLOCK(prAdapter, &prAdapter->prGlueInfo->rIntrWakeLock); + +#if !defined(MT6631) + nicEnableInterrupt(prAdapter); +#endif + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will check command queue to find out if any could be dequeued +* and/or send to HIF to MT6620 +* +* \param prAdapter Pointer of Adapter Data Structure +* \param prCmdQue Pointer of Command Queue (in Glue Layer) +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanProcessCommandQueue(IN P_ADAPTER_T prAdapter, IN P_QUE_T prCmdQue) +{ + WLAN_STATUS rStatus; + QUE_T rTempCmdQue, rMergeCmdQue, rStandInCmdQue; + P_QUE_T prTempCmdQue, prMergeCmdQue, prStandInCmdQue; + P_QUE_ENTRY_T prQueueEntry; + P_CMD_INFO_T prCmdInfo; + P_MSDU_INFO_T prMsduInfo; + ENUM_FRAME_ACTION_T eFrameAction = FRAME_ACTION_DROP_PKT; + + KAL_SPIN_LOCK_DECLARATION(); + + 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; + DBGLOG(TX, TRACE, + "CMD: CID=0x%x, SEQ=%d, CMD type=%d\n", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum, + prCmdInfo->eCmdType); + switch (prCmdInfo->eCmdType) { + case COMMAND_TYPE_NETWORK_IOCTL: + if (prCmdInfo->ucCID == CMD_ID_ADD_REMOVE_KEY) { + P_BSS_INFO_T prBssInfo = prAdapter->aprBssInfo[prCmdInfo->ucBssIndex]; + P_WIFI_CMD_T prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + P_CMD_802_11_KEY prKey = (P_CMD_802_11_KEY)prWifiCmd->aucBuffer; + + if ((prBssInfo->eNetworkType == NETWORK_TYPE_AIS || + (prBssInfo->eNetworkType == NETWORK_TYPE_P2P && + prCmdInfo->ucBssIndex == P2P_DEV_BSS_INDEX)) && + prKey->ucAddRemove && prKey->ucTxKey && + (prKey->ucAlgorithmId == CIPHER_SUITE_TKIP || + prKey->ucAlgorithmId == CIPHER_SUITE_CCMP)) {/* add key */ + switch (prBssInfo->ucKeyCmdAction) { + case SEC_DROP_KEY_COMMAND: + eFrameAction = FRAME_ACTION_DROP_PKT; + break; + case SEC_QUEUE_KEY_COMMAND: + eFrameAction = FRAME_ACTION_QUEUE_PKT; + break; + case SEC_TX_KEY_COMMAND: + eFrameAction = FRAME_ACTION_TX_PKT; + break; + } + DBGLOG(TX, INFO, "Add Key Cmd Action %d\n", eFrameAction); + break; + } + } + case COMMAND_TYPE_GENERAL_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->ucBssIndex, + prCmdInfo->ucStaRecIndex, NULL, FRAME_TYPE_802_1X, + prCmdInfo->u2InfoBufLen); + break; + + case COMMAND_TYPE_MANAGEMENT_FRAME: + /* inquire with QM */ + prMsduInfo = prCmdInfo->prMsduInfo; + + eFrameAction = qmGetFrameAction(prAdapter, prMsduInfo->ucBssIndex, + prMsduInfo->ucStaRecIndex, prMsduInfo, FRAME_TYPE_MMPDU, + prMsduInfo->u2FrameLength); + break; + + default: + ASSERT(0); + break; + } + + /* 4 <3> handling upon dequeue result */ + if (eFrameAction == FRAME_ACTION_DROP_PKT) { + DBGLOG(TX, INFO, "DROP CMD TYPE[%u] ID[0x%02X] SEQ[%u]\n", + prCmdInfo->eCmdType, prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + wlanReleaseCommand(prAdapter, prCmdInfo, TX_RESULT_DROPPED_IN_DRIVER); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } else if (eFrameAction == FRAME_ACTION_QUEUE_PKT) { + DBGLOG(TX, TRACE, "QUE back CMD TYPE[%u] ID[0x%02X] SEQ[%u]\n", + prCmdInfo->eCmdType, prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + + QUEUE_INSERT_TAIL(prMergeCmdQue, prQueueEntry); + } else if (eFrameAction == FRAME_ACTION_TX_PKT) { + /* 4 <4> Send the command */ +#if CFG_SUPPORT_MULTITHREAD + rStatus = wlanSendCommandMthread(prAdapter, prCmdInfo); + + if (rStatus == WLAN_STATUS_RESOURCES) { + /* no more TC4 resource for further transmission */ + DBGLOG(TX, WARN, "NO Resource for CMD TYPE[%u] ID[0x%02X] SEQ[%u]\n", + prCmdInfo->eCmdType, prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + + QUEUE_INSERT_TAIL(prMergeCmdQue, prQueueEntry); + break; + } else if (rStatus != WLAN_STATUS_SUCCESS && rStatus != WLAN_STATUS_PENDING) { + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + if (prCmdInfo->fgIsOid) + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, + prCmdInfo->u4SetInfoLen, rStatus); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + DBGLOG(TX, WARN, "TX CMD FAILED, Status[%u] TYPE[%u] ID[0x%02X] SEQ[%u]\n", + rStatus, prCmdInfo->eCmdType, prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + } else + DBGLOG(TX, TRACE, + "Send CMD, status=%u, CID=0x%x, SEQ=%d, CMD type=%d, OID=%d\n", + rStatus, prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum, + prCmdInfo->eCmdType, prCmdInfo->fgIsOid); +#else + rStatus = wlanSendCommand(prAdapter, prCmdInfo); + + if (rStatus == WLAN_STATUS_RESOURCES) { + /* no more TC4 resource for further transmission */ + + DBGLOG(TX, WARN, "NO Resource for CMD TYPE[%u] ID[0x%02X] SEQ[%u]\n", + prCmdInfo->eCmdType, prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + + 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); + } +#endif + } 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); + +#if CFG_SUPPORT_MULTITHREAD + kalSetTxCmdEvent2Hif(prAdapter->prGlueInfo); +#endif + + return WLAN_STATUS_SUCCESS; +} /* end of wlanProcessCommandQueue() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will take CMD_INFO_T which carry some informantion 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; + + 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) */ + ucTC = nicTxGetCmdResourceType(prCmdInfo); + + /* <1.2> Check if pending packet or resource was exhausted */ + rStatus = nicTxAcquireResource(prAdapter, ucTC, nicTxGetCmdPageCount(prCmdInfo)); + if (rStatus == WLAN_STATUS_RESOURCES) { + DBGLOG(INIT, INFO, "NO Resource:%d\n", ucTC); + break; + } + /* <1.3> Forward CMD_INFO_T to NIC Layer */ + rStatus = nicTxCmd(prAdapter, prCmdInfo, ucTC); + + /* <1.4> Set Pending in response to Query Command/Need Response */ + if (rStatus == WLAN_STATUS_SUCCESS) { + if ((!prCmdInfo->fgSetQuery) || (prCmdInfo->fgNeedResp)) + rStatus = WLAN_STATUS_PENDING; + } + } + /* <2> Special case for access Driver Domain MCR */ + else { + P_CMD_ACCESS_REG prCmdAccessReg; + + prCmdAccessReg = (P_CMD_ACCESS_REG) (prCmdInfo->pucInfoBuffer + CMD_HDR_SIZE); + + if (prCmdInfo->fgSetQuery) { + /* address is in DWORD unit */ + HAL_MCR_WR(prAdapter, (prCmdAccessReg->u4Address & BITS(2, 31)), + prCmdAccessReg->u4Data); + } else { + P_CMD_ACCESS_REG prEventAccessReg; + UINT_32 u4Address; + + u4Address = prCmdAccessReg->u4Address; + prEventAccessReg = (P_CMD_ACCESS_REG) prCmdInfo->pucInfoBuffer; + prEventAccessReg->u4Address = u4Address; + /* address is in DWORD unit */ + HAL_MCR_RD(prAdapter, prEventAccessReg->u4Address & BITS(2, 31), + &prEventAccessReg->u4Data); + } + } + + } while (FALSE); + + return rStatus; +} /* end of wlanSendCommand() */ + +#if CFG_SUPPORT_MULTITHREAD + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will take CMD_INFO_T which carry some information of +* incoming OID and notify the NIC_TX to send CMD. +* +* \param prAdapter Pointer of Adapter Data Structure +* \param prCmdInfo Pointer of P_CMD_INFO_T +* +* \retval WLAN_STATUS_SUCCESS : CMD was written to HIF and be freed(CMD Done) immediately. +* \retval WLAN_STATUS_RESOURCE : No resource for current command, need to wait for previous +* frame finishing their transmission. +* \retval WLAN_STATUS_FAILURE : Get failure while access HIF or been rejected. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanSendCommandMthread(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; + + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue; + +#if CFG_DBG_MGT_BUF + struct MEM_TRACK *prMemTrack = NULL; +#endif + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + prTxCtrl = &prAdapter->rTxCtrl; + +#if CFG_DBG_MGT_BUF + if (prCmdInfo->pucInfoBuffer && !IS_FROM_BUF(prAdapter, prCmdInfo->pucInfoBuffer)) + prMemTrack = (struct MEM_TRACK *)((PUINT_8)prCmdInfo->pucInfoBuffer - sizeof(struct MEM_TRACK)); +#endif + prTempCmdQue = &rTempCmdQue; + QUEUE_INITIALIZE(prTempCmdQue); + + 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) */ + ucTC = nicTxGetCmdResourceType(prCmdInfo); + + /* <1.2> Check if pending packet or resource was exhausted */ + rStatus = nicTxAcquireResource(prAdapter, ucTC, nicTxGetCmdPageCount(prCmdInfo)); + if (rStatus == WLAN_STATUS_RESOURCES) { +#if 0 + DBGLOG(INIT, WARN, "%s: NO Resource for CMD TYPE[%u] ID[0x%02X] SEQ[%u] TC[%u]\n", + __func__, + prCmdInfo->eCmdType, + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum, ucTC); +#endif + break; + } + + /* Process to pending command queue firest */ + if ((!prCmdInfo->fgSetQuery) || (prCmdInfo->fgNeedResp)) { + /* command packet which needs further handling upon response */ + /* + * KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + * QUEUE_INSERT_TAIL(&(prAdapter->rPendingCmdQueue), (P_QUE_ENTRY_T)prCmdInfo); + * KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + */ + } + +#if CFG_DBG_MGT_BUF + if (prMemTrack) { + prMemTrack->u2CmdIdAndWhere &= 0x00FF; + prMemTrack->u2CmdIdAndWhere |= 0x0100; + } +#endif + QUEUE_INSERT_TAIL(prTempCmdQue, (P_QUE_ENTRY_T) prCmdInfo); + + /* <1.4> Set Pending in response to Query Command/Need Response */ + if (rStatus == WLAN_STATUS_SUCCESS) { + if ((!prCmdInfo->fgSetQuery) || + (prCmdInfo->fgNeedResp) || (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME)) { + rStatus = WLAN_STATUS_PENDING; + } + } + } + /* <2> Special case for access Driver Domain MCR */ + else { +#if CFG_DBG_MGT_BUF + if (prMemTrack) { + prMemTrack->u2CmdIdAndWhere &= 0x00FF; + prMemTrack->u2CmdIdAndWhere |= 0x0100; + } +#endif + QUEUE_INSERT_TAIL(prTempCmdQue, (P_QUE_ENTRY_T) prCmdInfo); + rStatus = WLAN_STATUS_PENDING; + } + } while (FALSE); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); + QUEUE_CONCATENATE_QUEUES(&(prAdapter->rTxCmdQueue), prTempCmdQue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); + + return rStatus; +} /* end of wlanSendCommandMthread() */ + +WLAN_STATUS wlanTxCmdMthread(IN P_ADAPTER_T prAdapter) +{ + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue; + QUE_T rTempCmdDoneQue; + P_QUE_T prTempCmdDoneQue; + P_QUE_ENTRY_T prQueueEntry; + P_CMD_INFO_T prCmdInfo; + P_CMD_ACCESS_REG prCmdAccessReg; + P_CMD_ACCESS_REG prEventAccessReg; + UINT_32 u4Address; + UINT_32 u4TxDoneQueueSize; +#if CFG_DBG_MGT_BUF + struct MEM_TRACK *prMemTrack = NULL; +#endif + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prTempCmdQue = &rTempCmdQue; + QUEUE_INITIALIZE(prTempCmdQue); + + prTempCmdDoneQue = &rTempCmdDoneQue; + QUEUE_INITIALIZE(prTempCmdDoneQue); + + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_TX_CMD_CLEAR); + + /* TX Command Queue */ + /* 4 <1> Move whole list of CMD_INFO to temp queue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, &prAdapter->rTxCmdQueue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_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; +#if CFG_DBG_MGT_BUF + if (prCmdInfo->pucInfoBuffer && !IS_FROM_BUF(prAdapter, prCmdInfo->pucInfoBuffer)) + prMemTrack = (struct MEM_TRACK *)((PUINT_8)prCmdInfo->pucInfoBuffer - sizeof(struct MEM_TRACK)); +#endif + + if (!prCmdInfo->fgDriverDomainMCR) { + rStatus = nicTxCmd(prAdapter, prCmdInfo, TC4_INDEX); + + if (rStatus == WLAN_STATUS_SUCCESS) { + if ((!prCmdInfo->fgSetQuery) || (prCmdInfo->fgNeedResp)) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); +#if CFG_DBG_MGT_BUF + if (prMemTrack) { + prMemTrack->u2CmdIdAndWhere &= 0x00FF; + prMemTrack->u2CmdIdAndWhere |= 0x0200; + } +#endif + QUEUE_INSERT_TAIL(&(prAdapter->rPendingCmdQueue), (P_QUE_ENTRY_T) prCmdInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + } else { +#if CFG_DBG_MGT_BUF + if (prMemTrack) { + prMemTrack->u2CmdIdAndWhere &= 0x00FF; + prMemTrack->u2CmdIdAndWhere |= 0x0300; + } +#endif + QUEUE_INSERT_TAIL(prTempCmdDoneQue, prQueueEntry); + } + } else { + QUEUE_INSERT_TAIL(prTempCmdDoneQue, prQueueEntry); + } + /* + * DBGLOG(INIT, INFO, + * ("==> TX CMD QID: %d (Q:%d)\n", prCmdInfo->ucCID, prTempCmdQue->u4NumElem)); + */ + } else { + prCmdAccessReg = (P_CMD_ACCESS_REG) (prCmdInfo->pucInfoBuffer + CMD_HDR_SIZE); + + if (prCmdInfo->fgSetQuery) { + /* address is in DWORD unit */ + HAL_MCR_WR(prAdapter, (prCmdAccessReg->u4Address & BITS(2, 31)), + prCmdAccessReg->u4Data); + } else { + u4Address = prCmdAccessReg->u4Address; + prEventAccessReg = (P_CMD_ACCESS_REG) prCmdInfo->pucInfoBuffer; + prEventAccessReg->u4Address = u4Address; + /* address is in DWORD unit */ + HAL_MCR_RD(prAdapter, prEventAccessReg->u4Address & BITS(2, 31), + &prEventAccessReg->u4Data); + } +#if CFG_DBG_MGT_BUF + if (prMemTrack) { + prMemTrack->u2CmdIdAndWhere &= 0x00FF; + prMemTrack->u2CmdIdAndWhere |= 0x0300; + } +#endif + QUEUE_INSERT_TAIL(prTempCmdDoneQue, prQueueEntry); + } + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); + QUEUE_CONCATENATE_QUEUES(&prAdapter->rTxCmdDoneQueue, prTempCmdDoneQue); + u4TxDoneQueueSize = prAdapter->rTxCmdDoneQueue.u4NumElem; + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); + + KAL_RELEASE_MUTEX(prAdapter, MUTEX_TX_CMD_CLEAR); + + if (u4TxDoneQueueSize > 0) { + /* call tx thread to work */ + set_bit(GLUE_FLAG_TX_CMD_DONE_BIT, &prAdapter->prGlueInfo->ulFlag); + wake_up_interruptible(&prAdapter->prGlueInfo->waitq); + } + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS wlanTxCmdDoneMthread(IN P_ADAPTER_T prAdapter) +{ + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue; + P_QUE_ENTRY_T prQueueEntry; + P_CMD_INFO_T prCmdInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prTempCmdQue = &rTempCmdQue; + QUEUE_INITIALIZE(prTempCmdQue); + + /* 4 <1> Move whole list of CMD_INFO to temp queue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, &prAdapter->rTxCmdDoneQueue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_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; + + if (prCmdInfo->pfCmdDoneHandler) + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prCmdInfo->pucInfoBuffer); + /* Not pending cmd, free it after TX succeed! */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to clear all commands in TX command queue +* \param prAdapter Pointer of Adapter Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanClearTxCommandQueue(IN P_ADAPTER_T prAdapter) +{ + 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(); + QUEUE_INITIALIZE(prTempCmdQue); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, &prAdapter->rTxCmdQueue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + nicTxReleaseTCResource(prAdapter, + nicTxGetCmdResourceType(prCmdInfo), + nicTxGetCmdPageCount(prCmdInfo)); + if (prCmdInfo->pfCmdTimeoutHandler) + prCmdInfo->pfCmdTimeoutHandler(prAdapter, prCmdInfo); + else + wlanReleaseCommand(prAdapter, prCmdInfo, TX_RESULT_QUEUE_CLEARANCE); + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to clear OID commands in TX command queue +* \param prAdapter Pointer of Adapter Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanClearTxOidCommand(IN P_ADAPTER_T prAdapter) +{ + 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(); + QUEUE_INITIALIZE(prTempCmdQue); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); + + QUEUE_MOVE_ALL(prTempCmdQue, &prAdapter->rTxCmdQueue); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + if (prCmdInfo->fgIsOid) { + + nicTxReleaseTCResource(prAdapter, + nicTxGetCmdResourceType(prCmdInfo), + nicTxGetCmdPageCount(prCmdInfo)); + + if (prCmdInfo->pfCmdTimeoutHandler) + prCmdInfo->pfCmdTimeoutHandler(prAdapter, prCmdInfo); + else + wlanReleaseCommand(prAdapter, prCmdInfo, TX_RESULT_QUEUE_CLEARANCE); + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + } else { + QUEUE_INSERT_TAIL(&prAdapter->rTxCmdQueue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to clear all commands in TX command done queue +* \param prAdapter Pointer of Adapter Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanClearTxCommandDoneQueue(IN P_ADAPTER_T prAdapter) +{ + QUE_T rTempCmdDoneQue; + P_QUE_T prTempCmdDoneQue = &rTempCmdDoneQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + QUEUE_INITIALIZE(prTempCmdDoneQue); + + /* 4 <1> Move whole list of CMD_INFO to temp queue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); + QUEUE_MOVE_ALL(prTempCmdDoneQue, &prAdapter->rTxCmdDoneQueue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); + + /* 4 <2> Dequeue from head and check it is able to be sent */ + QUEUE_REMOVE_HEAD(prTempCmdDoneQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + if (prCmdInfo->pfCmdDoneHandler) + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prCmdInfo->pucInfoBuffer); + /* Not pending cmd, free it after TX succeed! */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + QUEUE_REMOVE_HEAD(prTempCmdDoneQue, prQueueEntry, P_QUE_ENTRY_T); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to clear all buffer in port 0/1 queue +* \param prAdapter Pointer of Adapter Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanClearDataQueue(IN P_ADAPTER_T prAdapter) +{ + QUE_T qDataPort0, qDataPort1; + P_QUE_T prDataPort0, prDataPort1; + + KAL_SPIN_LOCK_DECLARATION(); + + prDataPort0 = &qDataPort0; + prDataPort1 = &qDataPort1; + + QUEUE_INITIALIZE(prDataPort0); + QUEUE_INITIALIZE(prDataPort1); + + /* <1> Move whole list of CMD_INFO to temp queue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + QUEUE_MOVE_ALL(prDataPort0, &prAdapter->rTxP0Queue); + QUEUE_MOVE_ALL(prDataPort1, &prAdapter->rTxP1Queue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + + /* <2> Release Tx resource */ + nicTxReleaseMsduResource(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(prDataPort0)); + nicTxReleaseMsduResource(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(prDataPort1)); + + /* <3> Return sk buffer */ + nicTxReturnMsduInfo(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(prDataPort0)); + nicTxReturnMsduInfo(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(prDataPort1)); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to clear all buffer in port 0/1 queue +* \param prAdapter Pointer of Adapter Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanClearRxToOsQueue(IN P_ADAPTER_T prAdapter) +{ + QUE_T rTempRxQue; + P_QUE_T prTempRxQue = &rTempRxQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + QUEUE_INITIALIZE(prTempRxQue); + + /* 4 <1> Move whole list of CMD_INFO to temp queue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); + QUEUE_MOVE_ALL(prTempRxQue, &prAdapter->rRxQueue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); + + /* 4 <2> Remove all skbuf */ + QUEUE_REMOVE_HEAD(prTempRxQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + kalRxIndicateOnePkt(prAdapter->prGlueInfo, (PVOID) GLUE_GET_PKT_DESCRIPTOR(prQueueEntry)); + QUEUE_REMOVE_HEAD(prTempRxQue, prQueueEntry, P_QUE_ENTRY_T); + } + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + * \param rTxDoneStatus Tx done status + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +VOID wlanReleaseCommand(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + 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: + DBGLOG(INIT, INFO, "Free CMD: BSS[%u] ID[0x%x] SeqNum[%u] OID[%u]\n", + prCmdInfo->ucBssIndex, + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum, prCmdInfo->fgIsOid); + + if (prCmdInfo->fgIsOid) { + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, WLAN_STATUS_FAILURE); + } + break; + + case COMMAND_TYPE_SECURITY_FRAME: + case COMMAND_TYPE_MANAGEMENT_FRAME: + prMsduInfo = prCmdInfo->prMsduInfo; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) { + kalSecurityFrameSendComplete(prAdapter->prGlueInfo, prCmdInfo->prPacket, WLAN_STATUS_FAILURE); + /* Avoid skb multiple free */ + prMsduInfo->prPacket = NULL; + } + + DBGLOG(INIT, INFO, + "Free %s Frame: BSS[%u] WIDX:PID[%u:%u] SEQ[%u] STA[%u] RSP[%u] CMDSeq[%u]\n", + prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME ? "SEC" : "MGMT", + prMsduInfo->ucBssIndex, + prMsduInfo->ucWlanIndex, + prMsduInfo->ucPID, + prMsduInfo->ucTxSeqNum, + prMsduInfo->ucStaRecIndex, + prMsduInfo->pfTxDoneHandler ? TRUE : FALSE, prCmdInfo->ucCmdSeqNum); + + /* invoke callbacks */ + if (prMsduInfo->pfTxDoneHandler != NULL) + prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, rTxDoneStatus); + + if (prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) + GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum); + + cnmMgtPktFree(prAdapter, prMsduInfo); + break; + + default: + ASSERT(0); + break; + } + +} /* end of wlanReleaseCommand() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will search the CMD Queue to look for the pending OID and +* compelete it immediately when system request a reset. +* +* \param prAdapter ointer of Adapter Data Structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanReleasePendingOid(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr) +{ + 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); + + do { + if (ulParamPtr == 1) + break; + + if (prAdapter->prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(INIT, INFO, "%s stopped! Releasing pending OIDs ..\n", KAL_GET_CURRENT_THREAD_NAME()); + } else { + DBGLOG(INIT, ERROR, "OID Timeout! Releasing pending OIDs ..\n"); + prAdapter->ucOidTimeoutCount++; + + if (prAdapter->ucOidTimeoutCount >= WLAN_OID_NO_ACK_THRESHOLD) { + if (!prAdapter->fgIsChipNoAck) { + DBGLOG(INIT, WARN, + "No response from chip for %u times, set NoAck flag!\n", + prAdapter->ucOidTimeoutCount); +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanDumpTcResAndTxedCmd(NULL, 0); +#endif + #if defined(MT6631) + kalDumpHifCR(prAdapter->prGlueInfo); + #endif + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP); + } + + prAdapter->fgIsChipNoAck = TRUE; + } + } + } while (FALSE); + + do { +#if CFG_SUPPORT_MULTITHREAD + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_TX_CMD_CLEAR); +#endif + + /* 1: Clear pending OID in glue layer command queue */ + kalOidCmdClearance(prAdapter->prGlueInfo); + +#if CFG_SUPPORT_MULTITHREAD + /* Clear pending OID in main_thread to hif_thread command queue */ + wlanClearTxOidCommand(prAdapter); +#endif + /* 2: 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); + + /* 3: Clear pending OID queued in pvOidEntry with REQ_FLAG_OID set */ + kalOidClearance(prAdapter->prGlueInfo); + +#if CFG_SUPPORT_MULTITHREAD + KAL_RELEASE_MUTEX(prAdapter, MUTEX_TX_CMD_CLEAR); +#endif + } while (FALSE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will search the CMD Queue to look for the pending CMD/OID for specific +* NETWORK TYPE and compelete it immediately when system request a reset. +* +* \param prAdapter ointer of Adapter Data Structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanReleasePendingCMDbyBssIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex) +{ + 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 BSS:%d\n", prCmdInfo->ucBssIndex); + + if (prCmdInfo->ucBssIndex == ucBssIndex) { + if (prCmdInfo->pfCmdTimeoutHandler) { + prCmdInfo->pfCmdTimeoutHandler(prAdapter, prCmdInfo); + } else if (prCmdInfo->fgIsOid) { + 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); +} /* wlanReleasePendingCMDbyBssIdx */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Return the indicated packet buffer and reallocate one to the RFB +* +* \param prAdapter Pointer of Adapter Data Structure +* \param pvPacket Pointer of returned packet +* +* \retval WLAN_STATUS_SUCCESS: Success +* \retval WLAN_STATUS_FAILURE: Failed +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanReturnPacketDelaySetupTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr) +{ + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = NULL; + WLAN_STATUS status = WLAN_STATUS_SUCCESS; + P_QUE_T prQueList; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + prQueList = &prRxCtrl->rIndicatedRfbList; + DBGLOG(RX, WARN, "%s: IndicatedRfbList num = %u\n", __func__, prQueList->u4NumElem); + + while (QUEUE_IS_NOT_EMPTY(&prRxCtrl->rIndicatedRfbList)) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rIndicatedRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + status = nicRxSetupRFB(prAdapter, prSwRfb); + nicRxReturnRFB(prAdapter, prSwRfb); + + if (status != WLAN_STATUS_SUCCESS) + break; + } + + if (status != WLAN_STATUS_SUCCESS) { + DBGLOG(RX, WARN, "Restart ReturnIndicatedRfb Timer (%u)\n", RX_RETURN_INDICATED_RFB_TIMEOUT_SEC); + /* restart timer */ + cnmTimerStartTimer(prAdapter, + &prAdapter->rPacketDelaySetupTimer, + SEC_TO_MSEC(RX_RETURN_INDICATED_RFB_TIMEOUT_SEC)); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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)) { + /*Todo:: nothing*/ + /*Todo:: nothing*/ + } +#endif + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rIndicatedRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + if (!prSwRfb) { + DBGLOG(RX, WARN, "No free SwRfb!\n"); + return; + } + + if (nicRxSetupRFB(prAdapter, prSwRfb)) { + DBGLOG(RX, WARN, "Cannot allocate packet buffer for SwRfb!\n"); + if (!timerPendingTimer(&prAdapter->rPacketDelaySetupTimer)) { + DBGLOG(RX, WARN, + "Start ReturnIndicatedRfb Timer (%u)\n", RX_RETURN_INDICATED_RFB_TIMEOUT_SEC); + cnmTimerStartTimer(prAdapter, &prAdapter->rPacketDelaySetupTimer, + SEC_TO_MSEC(RX_RETURN_INDICATED_RFB_TIMEOUT_SEC)); + } + } + 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)) { + /* + * note: return WLAN_STATUS_FAILURE or + * WLAN_STATUS_SUCCESS for blocking OIDs during current measurement ?? + */ + return WLAN_STATUS_SUCCESS; + } +#if 1 + /* most OID handler will just queue a command packet */ + status = pfnOidQryHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4QryInfoLen); +#else + if (wlanIsHandlerNeedHwAccess(pfnOidQryHandler, FALSE)) { + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + /* Reset sleepy state */ + if (prAdapter->fgWiFiInSleepyState == TRUE) + prAdapter->fgWiFiInSleepyState = FALSE; + + status = pfnOidQryHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4QryInfoLen); + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + } else + status = pfnOidQryHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4QryInfoLen); +#endif + + return status; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a required function that allows bound protocol drivers, +* or NDIS, to request changes in the state information that the miniport +* maintains for particular object identifiers, such as changes in multicast +* addresses. +* +* \param[IN] prAdapter Pointer to the Glue info structure. +* \param[IN] pfnOidSetHandler Points to the OID set handlers. +* \param[IN] pvInfoBuf Points to a buffer containing the OID-specific data for the set. +* \param[IN] u4InfoBufLen Specifies the number of bytes at prSetBuffer. +* \param[OUT] pu4SetInfoLen Points to the number of bytes it read or is needed. +* +* \retval WLAN_STATUS_xxx Different WLAN_STATUS code returned by different handlers. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanSetInformation(IN P_ADAPTER_T prAdapter, + IN PFN_OID_HANDLER_FUNC pfnOidSetHandler, + IN PVOID pvInfoBuf, IN UINT_32 u4InfoBufLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS status = WLAN_STATUS_FAILURE; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* ignore any OID request after connected, under PS current measurement mode */ + if (prAdapter->u4PsCurrentMeasureEn && + (prAdapter->prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_CONNECTED)) { + /* + * note: return WLAN_STATUS_FAILURE or WLAN_STATUS_SUCCESS + * for blocking OIDs during current measurement ?? + */ + return WLAN_STATUS_SUCCESS; + } +#if 1 + /* + * most OID handler will just queue a command packet + * for power state transition OIDs, handler will acquire power control by itself + */ + status = pfnOidSetHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4SetInfoLen); +#else + if (wlanIsHandlerNeedHwAccess(pfnOidSetHandler, TRUE)) { + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + /* Reset sleepy state */ + if (prAdapter->fgWiFiInSleepyState == TRUE) + prAdapter->fgWiFiInSleepyState = FALSE; + + status = pfnOidSetHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4SetInfoLen); + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + } else { + status = pfnOidSetHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4SetInfoLen); + } +#endif + + return status; +} + +#if CFG_SUPPORT_WAPI +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a used to query driver's config wapi mode or not +* +* \param[IN] prAdapter Pointer to the Glue info structure. +* +* \retval TRUE for use wapi mode +* +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanQueryWapiMode(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + return prAdapter->rWifiVar.rConnSettings.fgWapiMode; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to set RX filter to Promiscuous Mode. +* +* \param[IN] prAdapter Pointer to the Adapter structure. +* \param[IN] fgEnablePromiscuousMode Enable/ disable RX Promiscuous Mode. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanSetPromiscuousMode(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnablePromiscuousMode) +{ + ASSERT(prAdapter); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to set RX filter to allow to receive +* broadcast address packets. +* +* \param[IN] prAdapter Pointer to the Adapter structure. +* \param[IN] fgEnableBroadcast Enable/ disable broadcast packet to be received. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanRxSetBroadcast(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnableBroadcast) +{ + ASSERT(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to send out CMD_NIC_POWER_CTRL command packet +* +* \param[IN] prAdapter Pointer to the Adapter structure. +* \param[IN] ucPowerMode refer to CMD/EVENT document +* +* \return WLAN_STATUS_SUCCESS +* \return WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanSendNicPowerCtrlCmd(IN P_ADAPTER_T prAdapter, IN UINT_8 ucPowerMode) +{ + WLAN_STATUS status = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_8 ucTC, ucCmdSeqNum; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + + /* 1. Prepare CMD */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_NIC_POWER_CTRL))); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* 2.1 increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + DBGLOG(REQ, TRACE, "ucCmdSeqNum =%d\n", ucCmdSeqNum); + + /* 2.2 Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = (UINT_16) (CMD_HDR_SIZE + sizeof(CMD_NIC_POWER_CTRL)); + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->pfCmdTimeoutHandler = NULL; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_NIC_POWER_CTRL; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(CMD_NIC_POWER_CTRL); + + /* 2.3 Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + 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, nicTxGetCmdPageCount(prCmdInfo)) == 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; + prAdapter->fgIsChipNoAck = TRUE; + break; + } + continue; + } + /* 3.2 Send CMD Info Packet */ + if (nicTxCmd(prAdapter, prCmdInfo, ucTC) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "Fail to transmit CMD_NIC_POWER_CTRL command\n"); + status = WLAN_STATUS_FAILURE; + } + + break; + }; + + /* 4. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + /* 5. Add flag */ + if (ucPowerMode == 1) + prAdapter->fgIsEnterD3ReqIssued = TRUE; + + return status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to check if it is RF test mode and +* the OID is allowed to be called or not +* +* \param[IN] prAdapter Pointer to the Adapter structure. +* \param[IN] fgEnableBroadcast Enable/ disable broadcast packet to be received. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanIsHandlerAllowedInRFTest(IN PFN_OID_HANDLER_FUNC pfnOidHandler, IN BOOLEAN fgSetInfo) +{ + PFN_OID_HANDLER_FUNC *apfnOidHandlerAllowedInRFTest; + UINT_32 i; + UINT_32 u4NumOfElem; + + if (fgSetInfo) { + apfnOidHandlerAllowedInRFTest = apfnOidSetHandlerAllowedInRFTest; + u4NumOfElem = sizeof(apfnOidSetHandlerAllowedInRFTest) / sizeof(PFN_OID_HANDLER_FUNC); + } else { + apfnOidHandlerAllowedInRFTest = apfnOidQueryHandlerAllowedInRFTest; + u4NumOfElem = sizeof(apfnOidQueryHandlerAllowedInRFTest) / sizeof(PFN_OID_HANDLER_FUNC); + } + + for (i = 0; i < u4NumOfElem; i++) { + if (apfnOidHandlerAllowedInRFTest[i] == pfnOidHandler) + return TRUE; + } + + return FALSE; +} + +#if CFG_ENABLE_FW_DOWNLOAD +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to configure FWDL parameters +* +* @param prAdapter Pointer to the Adapter structure. +* u4DestAddr Address of destination address +* u4ImgSecSize Length of the firmware block +* fgReset should be set to TRUE if this is the 1st configuration +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanImageSectionConfig(IN P_ADAPTER_T prAdapter, IN UINT_32 u4DestAddr, IN UINT_32 u4ImgSecSize, IN BOOLEAN fgReset, + IN UINT_8 ucEnc, IN UINT_8 ucKIdx) +{ + P_CMD_INFO_T prCmdInfo; + P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; + P_INIT_CMD_DOWNLOAD_CONFIG prInitCmdDownloadConfig; + UINT_8 ucTC, ucCmdSeqNum; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + + DEBUGFUNC("wlanImageSectionConfig"); + + 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_CONFIG)); + + 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_CONFIG); + + /* 2. Use TC4's resource to download image. (TC4 as CPU) */ + ucTC = TC4_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->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prInitHifTxHeader->u2PQ_ID = INIT_CMD_PQ_ID; + + prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_DOWNLOAD_CONFIG; + prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = INIT_CMD_PACKET_TYPE_ID; + prInitHifTxHeader->rInitWifiCmd.ucReserved = 0; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + /* 5. Setup Download config */ + prInitCmdDownloadConfig = (P_INIT_CMD_DOWNLOAD_CONFIG) (prInitHifTxHeader->rInitWifiCmd.aucBuffer); + prInitCmdDownloadConfig->u4Address = u4DestAddr; + prInitCmdDownloadConfig->u4Length = u4ImgSecSize; + prInitCmdDownloadConfig->u4DataMode = 0; + + /* ACK needed */ +#if CFG_ENABLE_FW_DOWNLOAD_ACK + prInitCmdDownloadConfig->u4DataMode |= DOWNLOAD_CONFIG_ACK_OPTION; +#endif + + +#if CFG_ENABLE_FW_ENCRYPTION +#if defined(MT6631) + if (ucEnc) { + prInitCmdDownloadConfig->u4DataMode |= DOWNLOAD_CONFIG_ENCRYPTION_MODE; + prInitCmdDownloadConfig->u4DataMode |= (ucKIdx & BITS(0, 1)) << DOWNLOAD_CONFIG_ENCRYPT_IDX_OFFSET; + } +#else + /* MT6630 don't check ucEnc and ucKIdx now, but forcibly enable download encryption */ + prInitCmdDownloadConfig->u4DataMode |= DOWNLOAD_CONFIG_ENCRYPTION_MODE; +#endif +#endif + + if (fgReset) + prInitCmdDownloadConfig->u4DataMode |= DOWNLOAD_CONFIG_RESET_OPTION; + + /* 6. Send Download config command */ + while (1) { + /* 6.1 Acquire TX Resource */ + if (nicTxAcquireResource + (prAdapter, ucTC, nicTxGetPageCount(prCmdInfo->u2InfoBufLen, TRUE)) == WLAN_STATUS_RESOURCES) { + if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); + break; + } + continue; + } + /* 6.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to transmit download config command\n"); + break; + } +#if CFG_ENABLE_FW_DOWNLOAD_ACK + /* 7. Wait for INIT_EVENT_ID_CMD_RESULT */ + u4Status = wlanImageSectionDownloadStatus(prAdapter, ucCmdSeqNum); +#endif + break; + } + + /* 8. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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 u4ImgSecSize, IN PUINT_8 pucImgSecBuf) +{ + P_CMD_INFO_T prCmdInfo; + P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; + 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) + u4ImgSecSize); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prCmdInfo->u2InfoBufLen = sizeof(INIT_HIF_TX_HEADER_T) + (UINT_16) u4ImgSecSize; + + /* 2. Setup common CMD Info Packet */ + prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prInitHifTxHeader->u2PQ_ID = INIT_CMD_PDA_PQ_ID; + + prInitHifTxHeader->rInitWifiCmd.ucCID = 0; + prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = INIT_CMD_PDA_PACKET_TYPE_ID; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = 0; + + /* 3. Copy FW image scatter section */ + kalMemCopy(prInitHifTxHeader->rInitWifiCmd.aucBuffer, pucImgSecBuf, u4ImgSecSize); + + /* 4. Send FW image scatter section */ + if (nicTxInitCmd(prAdapter, prCmdInfo) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to transmit FW image scatter section\n"); + } + /* 5. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + +/* for AOSP */ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to download FW by ilm and dlm section. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ + +VOID +wlanFwDvdDwnloadHandler(IN P_ADAPTER_T prAdapter, + IN P_FIRMWARE_DIVIDED_DOWNLOAD_T prFwHead, IN PVOID pvFwImageMapFile, + OUT WLAN_STATUS *u4Status) +{ + UINT_32 u4ImgSecSize, i, j; + + for (i = 0; i < prFwHead->u4NumOfEntries; i++) { + if (wlanImageSectionConfig(prAdapter, + prFwHead->arSection[i].u4DestAddr, + prFwHead->arSection[i].u4Length, + i == 0 ? TRUE : FALSE, +#if defined(MT6631) + prFwHead->arSection[i].ucEnc ? TRUE : FALSE, + prFwHead->arSection[i].ucKIdx +#else + TRUE, + 0 +#endif + ) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "Firmware download configuration failed!\n"); + *u4Status = WLAN_STATUS_FAILURE; + break; + } + + 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, + 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; + } + } + + /* escape from loop if any pending error occurs */ + if (*u4Status == WLAN_STATUS_FAILURE) + break; + } +} + +/* for AOSP */ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to download FW +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ + +VOID +wlanFwDwnloadHandler(IN P_ADAPTER_T prAdapter, + IN UINT_32 u4FwImgLength, IN PVOID pvFwImageMapFile, OUT WLAN_STATUS *u4Status) +{ + UINT_32 u4ImgSecSize, i; + + 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, + u4ImgSecSize, (PUINT_8) pvFwImageMapFile + i) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "wlanImageSectionDownload failed!\n"); + *u4Status = WLAN_STATUS_FAILURE; + break; + } + } +} + +#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->pucInfoBuffer, 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->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prInitHifTxHeader->u2PQ_ID = INIT_CMD_PQ_ID; + + prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_QUERY_PENDING_ERROR; + prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = INIT_CMD_PACKET_TYPE_ID; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + /* 5. Send Query pending error command */ + while (1) { + /* 5.1 Acquire TX Resource */ + if (nicTxAcquireResource + (prAdapter, ucTC, nicTxGetPageCount(prCmdInfo->u2InfoBufLen, TRUE)) == WLAN_STATUS_RESOURCES) { + if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); + break; + } + continue; + } + /* 5.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to transmit query pending error command\n"); + } + + break; + }; + + /* 6. Wait for INIT_EVENT_ID_PENDING_ERROR */ + do { + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + } else if (nicRxWaitResponse(prAdapter, + 0, + aucBuffer, + sizeof(INIT_HIF_RX_HEADER_T) + + sizeof(INIT_EVENT_PENDING_ERROR), &u4RxPktLength) != WLAN_STATUS_SUCCESS) { + UINT_32 u4MailBox0; + UINT_32 u4MailBox1; + + nicGetMailbox(prAdapter, 0, &u4MailBox0); + nicGetMailbox(prAdapter, 1, &u4MailBox1); + DBGLOG(INIT, WARN, "Device to Host Mailbox 0x%08x, 0x%08x\n", u4MailBox0, u4MailBox1); + u4Status = WLAN_STATUS_FAILURE; + } else { + prInitHifRxHeader = (P_INIT_HIF_RX_HEADER_T) aucBuffer; + + /* EID / SeqNum check */ + if (prInitHifRxHeader->rInitWifiEvent.ucEID != INIT_EVENT_ID_PENDING_ERROR) { + DBGLOG(INIT, ERROR, "Unexpected Event ID %d! expect %d\n", + prInitHifRxHeader->rInitWifiEvent.ucEID, INIT_EVENT_ID_PENDING_ERROR); + u4Status = WLAN_STATUS_FAILURE; + } else if (prInitHifRxHeader->rInitWifiEvent.ucSeqNum != ucCmdSeqNum) { + DBGLOG(INIT, ERROR, "Unexpected SeqNum %d! expect %d\n", + prInitHifRxHeader->rInitWifiEvent.ucSeqNum, ucCmdSeqNum); + u4Status = WLAN_STATUS_FAILURE; + } else { + prEventPendingError = + (P_INIT_EVENT_PENDING_ERROR) (prInitHifRxHeader->rInitWifiEvent.aucBuffer); + if (prEventPendingError->ucStatus != 0) { /* 0 for download success */ + DBGLOG(INIT, ERROR, "Event status error %d!\n", prEventPendingError->ucStatus); + u4Status = WLAN_STATUS_FAILURE; + } else { + u4Status = WLAN_STATUS_SUCCESS; + } + } + } + } while (FALSE); + + /* 7. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + +#else +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to confirm the status of +* previously downloaded firmware scatter +* +* @param prAdapter Pointer to the Adapter structure. +* ucCmdSeqNum Sequence number of previous firmware scatter +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanImageSectionDownloadStatus(IN P_ADAPTER_T prAdapter, IN UINT_8 ucCmdSeqNum) +{ + UINT_8 aucBuffer[sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_EVENT_CMD_RESULT)]; + P_INIT_HIF_RX_HEADER_T prInitHifRxHeader; + P_INIT_EVENT_CMD_RESULT prEventCmdResult; + UINT_32 u4RxPktLength; + WLAN_STATUS u4Status; + + ASSERT(prAdapter); + + do { + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + } else if (nicRxWaitResponse(prAdapter, + 0, + aucBuffer, + sizeof(INIT_HIF_RX_HEADER_T) + + sizeof(INIT_EVENT_CMD_RESULT), &u4RxPktLength) != WLAN_STATUS_SUCCESS) { + UINT_32 u4MailBox0; + UINT_32 u4MailBox1; + + nicGetMailbox(prAdapter, 0, &u4MailBox0); + nicGetMailbox(prAdapter, 1, &u4MailBox1); + DBGLOG(INIT, WARN, "Device to Host Mailbox 0x%08x, 0x%08x\n", u4MailBox0, u4MailBox1); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP | RST_FLAG_PREVENT_POWER_OFF); + u4Status = WLAN_STATUS_FAILURE; + } else { + prInitHifRxHeader = (P_INIT_HIF_RX_HEADER_T) aucBuffer; + + /* EID / SeqNum check */ + if (prInitHifRxHeader->rInitWifiEvent.ucEID != INIT_EVENT_ID_CMD_RESULT) { + DBGLOG(INIT, ERROR, "Unexpected Event ID %d! expect %d\n", + prInitHifRxHeader->rInitWifiEvent.ucEID, INIT_EVENT_ID_CMD_RESULT); + u4Status = WLAN_STATUS_FAILURE; + } else if (prInitHifRxHeader->rInitWifiEvent.ucSeqNum != ucCmdSeqNum) { + DBGLOG(INIT, ERROR, "Unexpected SeqNum %d! expect %d\n", + prInitHifRxHeader->rInitWifiEvent.ucSeqNum, ucCmdSeqNum); + u4Status = WLAN_STATUS_FAILURE; + } else { + prEventCmdResult = + (P_INIT_EVENT_CMD_RESULT) (prInitHifRxHeader->rInitWifiEvent.aucBuffer); + if (prEventCmdResult->ucStatus != 0) { /* 0 for download success */ + DBGLOG(INIT, ERROR, "Event status error %d!\n", prEventCmdResult->ucStatus); + u4Status = WLAN_STATUS_FAILURE; + } else { + u4Status = WLAN_STATUS_SUCCESS; + } + } + if (u4Status == WLAN_STATUS_FAILURE) + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP | RST_FLAG_PREVENT_POWER_OFF); + } + } while (FALSE); + + return u4Status; +} + +#endif +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to start FW normal operation. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanConfigWifiFunc(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnable, IN UINT_32 u4StartAddress) +{ + P_CMD_INFO_T prCmdInfo; + P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; + P_INIT_CMD_WIFI_START prInitCmdWifiStart; + UINT_8 ucTC, ucCmdSeqNum; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + + DEBUGFUNC("wlanConfigWifiFunc"); + + /* 1. Allocate CMD Info Packet and its Buffer. */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_WIFI_START)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + kalMemZero(prCmdInfo->pucInfoBuffer, sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_WIFI_START)); + prCmdInfo->u2InfoBufLen = sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_WIFI_START); + + /* 2. Always use TC0 */ + ucTC = TC0_INDEX; + + /* 3. Increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* 4. Setup common CMD Info Packet */ + prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prInitHifTxHeader->u2PQ_ID = INIT_CMD_PQ_ID; + + prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_WIFI_START; + prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = INIT_CMD_PACKET_TYPE_ID; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + prInitCmdWifiStart = (P_INIT_CMD_WIFI_START) (prInitHifTxHeader->rInitWifiCmd.aucBuffer); + prInitCmdWifiStart->u4Override = (fgEnable == TRUE ? 1 : 0); + prInitCmdWifiStart->u4Address = u4StartAddress; + + /* 5. Send WIFI start command */ + while (1) { + /* 5.1 Acquire TX Resource */ + if (nicTxAcquireResource + (prAdapter, ucTC, nicTxGetPageCount(prCmdInfo->u2InfoBufLen, TRUE)) == WLAN_STATUS_RESOURCES) { + if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); + break; + } + continue; + } + /* 5.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo) != 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; + P_STA_RECORD_T prStaRec; + + 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: + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (prStaRec && IS_STA_IN_AIS(prStaRec)) { +#if ARP_MONITER_ENABLE + qmHandleRxArpPackets(prAdapter, prSwRfb); +#endif + } + 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; + UINT_32 u4OidTimeout; + + apfnOidHandlerWOTimeoutCheck = apfnOidWOTimeoutCheck; + u4NumOfElem = sizeof(apfnOidWOTimeoutCheck) / sizeof(PFN_OID_HANDLER_FUNC); + + for (i = 0; i < u4NumOfElem; i++) { + if (apfnOidHandlerWOTimeoutCheck[i] == pfnOidHandler) + return FALSE; + } + + /* Decrease OID timeout threshold if chip NoAck/resetting */ + if (wlanIsChipNoAck(prAdapter)) { + u4OidTimeout = WLAN_OID_TIMEOUT_THRESHOLD_IN_RESETTING; + DBGLOG(INIT, INFO, "Decrease OID timeout to %ums due to NoACK/CHIP-RESET\n", u4OidTimeout); + } else { + u4OidTimeout = WLAN_OID_TIMEOUT_THRESHOLD; + } + + /* Set OID timer for timeout check */ + cnmTimerStartTimer(prAdapter, &(prAdapter->rOidTimeoutTimer), u4OidTimeout); + + 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 override network address +* if NVRAM has a valid value +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return WLAN_STATUS_FAILURE The request could not be processed +* WLAN_STATUS_PENDING The request has been queued for later processing +* WLAN_STATUS_SUCCESS The request has been processed +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanUpdateNetworkAddress(IN P_ADAPTER_T prAdapter) +{ + const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; + PARAM_MAC_ADDRESS rMacAddr = {0}; + UINT_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 == FALSE) { +#if CFG_SHOW_MACADDR_SOURCE + DBGLOG(INIT, TRACE, "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 embedded MAC address"); +#endif + return WLAN_STATUS_SUCCESS; + } + + } else { +#if CFG_SHOW_MACADDR_SOURCE + DBGLOG(INIT, INFO, "Using host-supplied MAC address"); +#endif + } + + COPY_MAC_ADDR(prAdapter->rWifiVar.aucMacAddress, rMacAddr); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to update basic configuration into 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 wlanUpdateBasicConfig(IN P_ADAPTER_T prAdapter) +{ + UINT_8 ucCmdSeqNum; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_CMD_BASIC_CONFIG_T prCmdBasicConfig; + + DEBUGFUNC("wlanUpdateBasicConfig"); + + ASSERT(prAdapter); + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE + sizeof(CMD_BASIC_CONFIG_T)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_BUILD_CONNECTION cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_BASIC_CONFIG_T); + 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_T); + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + /* configure CMD_BASIC_CONFIG */ + prCmdBasicConfig = (P_CMD_BASIC_CONFIG_T) (prWifiCmd->aucBuffer); + 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) { + kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + return WLAN_STATUS_PENDING; + } + + 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; +} + +BOOLEAN wlanProcessTxFrame(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prPacket) +{ + UINT_32 u4SysTime; + UINT_8 ucMacHeaderLen; + TX_PACKET_INFO rTxPacketInfo; + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(prPacket); + + if (kalQoSFrameClassifierAndPacketInfo(prAdapter->prGlueInfo, prPacket, &rTxPacketInfo)) { + + /* Save the value of Priority Parameter */ + GLUE_SET_PKT_TID(prPacket, rTxPacketInfo.ucPriorityParam); + + if (rTxPacketInfo.u2Flag) { + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_1X)) { + P_STA_RECORD_T prStaRec; + + DBGLOG(RSN, TRACE, "T1X len=%d\n", rTxPacketInfo.u4PacketLen); + + prStaRec = cnmGetStaRecByAddress(prAdapter, + GLUE_GET_PKT_BSS_IDX(prPacket), + rTxPacketInfo.aucEthDestAddr); + + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_1X); + if (secIsProtected1xFrame(prAdapter, prStaRec)) { + if (prStaRec->ucBssIndex <= HW_BSSID_NUM) + prBssInfo = prAdapter->aprBssInfo[prStaRec->ucBssIndex]; + else + prBssInfo = NULL; + /* 1st 4way-handshake don't encrypted */ + /* gen3 default Un_protected, no need to set. */ + if (!prBssInfo || !(prBssInfo->fgUnencryptedEapol)) { + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_PROTECTED_1X); + DBGLOG(RSN, TRACE, "This EAP Frame will be encrypted\n"); + } + } + } + + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_802_3)) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_802_3); + + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_VLAN_EXIST)) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_VLAN_EXIST); + + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_DHCP)) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_DHCP); + + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_ARP)) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_ARP); + + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_ICMP)) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_ICMP); + + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_TDLS)) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_TDLS); + + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_DNS)) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_DNS); + + } + + ucMacHeaderLen = ETHER_HEADER_LEN; + + /* 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) rTxPacketInfo.u4PacketLen); + + /* Save the value of Arrival Time */ + u4SysTime = (OS_SYSTIME) kalGetTimeTick(); + GLUE_SET_PKT_ARRIVAL_TIME(prPacket, u4SysTime); + + return TRUE; + } + + return FALSE; +} + +WLAN_STATUS +nicTxSecFrameTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + UINT_8 ucKeyCmdAction = SEC_TX_KEY_COMMAND; + + DBGLOG(TX, INFO, "SEC Frame TX DONE WIDX:PID[%u:%u] Status[%u] SeqNo[%u]\n", + prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, rTxDoneStatus, + prMsduInfo->ucTxSeqNum); + + if (rTxDoneStatus != TX_RESULT_SUCCESS) + ucKeyCmdAction = SEC_DROP_KEY_COMMAND; + else + ucKeyCmdAction = SEC_TX_KEY_COMMAND; + secSetKeyCmdAction(prAdapter->aprBssInfo[prMsduInfo->ucBssIndex], + prMsduInfo->ucEapolKeyType, ucKeyCmdAction); + kalSetEvent(prAdapter->prGlueInfo); + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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) +{ + P_CMD_INFO_T prCmdInfo; + P_STA_RECORD_T prStaRec; + UINT_8 ucBssIndex; + UINT_32 u4PacketLen; + UINT_8 aucEthDestAddr[PARAM_MAC_ADDR_LEN]; + P_MSDU_INFO_T prMsduInfo; + + ASSERT(prAdapter); + ASSERT(prPacket); + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, 0); + + /* Get MSDU_INFO for TxDone */ + prMsduInfo = cnmPktAlloc(prAdapter, 0); + + u4PacketLen = (UINT_32) GLUE_GET_PKT_FRAME_LEN(prPacket); + + if (prCmdInfo && prMsduInfo) { + ucBssIndex = GLUE_GET_PKT_BSS_IDX(prPacket); + + kalGetEthDestAddr(prAdapter->prGlueInfo, prPacket, aucEthDestAddr); + + prStaRec = cnmGetStaRecByAddress(prAdapter, ucBssIndex, aucEthDestAddr); + + prCmdInfo->eCmdType = COMMAND_TYPE_SECURITY_FRAME; + prCmdInfo->u2InfoBufLen = (UINT_16) u4PacketLen; + prCmdInfo->prPacket = prPacket; + prCmdInfo->prMsduInfo = prMsduInfo; + if (prStaRec) + prCmdInfo->ucStaRecIndex = prStaRec->ucIndex; + else + prCmdInfo->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; + prCmdInfo->ucBssIndex = ucBssIndex; + prCmdInfo->pfCmdDoneHandler = wlanSecurityFrameTxDone; + prCmdInfo->pfCmdTimeoutHandler = wlanSecurityFrameTxTimeout; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + + /* Fill-up MSDU_INFO */ + nicTxSetDataPacket(prAdapter, prMsduInfo, ucBssIndex, + prCmdInfo->ucStaRecIndex, 0, u4PacketLen, nicTxSecFrameTxDone, + MSDU_RATE_MODE_AUTO, TX_PACKET_OS, 0, FALSE, TRUE); + + prMsduInfo->prPacket = prPacket; + prMsduInfo->ucTxSeqNum = GLUE_GET_PKT_SEQ_NO(prPacket); + /* No Tx descriptor template for MMPDU */ + prMsduInfo->fgIsTXDTemplateValid = FALSE; + + if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_PROTECTED_1X)) + nicTxConfigPktOption(prMsduInfo, MSDU_OPT_PROTECTED_FRAME, TRUE); +#if CFG_SUPPORT_MULTITHREAD + nicTxComposeSecurityFrameDesc(prAdapter, prCmdInfo, prMsduInfo->aucTxDescBuffer, NULL); +#endif + + kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + GLUE_SET_EVENT(prAdapter->prGlueInfo); + + } else { + DBGLOG(RSN, INFO, "Failed to alloc CMD/MGMT INFO for 1X frame!!\n"); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + cnmPktFree(prAdapter, prMsduInfo); + return FALSE; + } + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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 (GET_BSS_INFO_BY_INDEX(prAdapter, prCmdInfo->ucBssIndex)->eNetworkType == + NETWORK_TYPE_AIS && prAdapter->rWifiVar.rAisSpecificBssInfo.fgCounterMeasure) { + P_STA_RECORD_T prSta = cnmGetStaRecByIndex(prAdapter, prCmdInfo->ucBssIndex); + + if (prSta) { + kalMsleep(10); + if (authSendDeauthFrame(prAdapter, + GET_BSS_INFO_BY_INDEX(prAdapter, + prCmdInfo->ucBssIndex), prSta, + (P_SW_RFB_T) NULL, REASON_CODE_MIC_FAILURE, (PFN_TX_DONE_HANDLER) NULL + /* secFsmEventDeauthTxDone left upper layer handle the 60 timer */ + ) != WLAN_STATUS_SUCCESS) { + ASSERT(FALSE); + } + /* secFsmEventEapolTxDone(prAdapter, prSta, TX_RESULT_SUCCESS); */ + } + } + + /* Clear the flag when Eapol frame tx Done */ + GET_BSS_INFO_BY_INDEX(prAdapter, prCmdInfo->ucBssIndex)->fgUnencryptedEapol = FALSE; + 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; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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 - + (((ULONG) pucIEPtr) + u4IELength - + ((ULONG) (&(prAdapter->rWlanInfo.aucScanIEBuf[0])))); + + kalMemCopy(pucIEPtr, (PUINT_8) (((ULONG) pucIEPtr) + u4IELength), u4IEMoveLength); + + prAdapter->rWlanInfo.u4ScanIEBufferUsage -= u4IELength; + + /* correction of pointers to IE buffer */ + for (j = 0; j < prAdapter->rWlanInfo.u4ScanResultNum; j++) { + if (prAdapter->rWlanInfo.apucScanResultIEs[j] > pucIEPtr) { + prAdapter->rWlanInfo.apucScanResultIEs[j] = + (PUINT_8) ((ULONG) (prAdapter->rWlanInfo.apucScanResultIEs[j]) - + u4IELength); + } + } + } + } + + i++; + } +} + +#if CFG_TEST_WIFI_DIRECT_GO +VOID wlanEnableP2pFunction(IN P_ADAPTER_T prAdapter) +{ +#if 0 + P_MSG_P2P_FUNCTION_SWITCH_T prMsgFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) NULL; + + prMsgFuncSwitch = + (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_FUNCTION_SWITCH_T)); + if (!prMsgFuncSwitch) { + ASSERT(FALSE); + return; + } + + prMsgFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; + prMsgFuncSwitch->fgIsFuncOn = TRUE; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgFuncSwitch, MSG_SEND_METHOD_BUF); +#endif +} + +VOID wlanEnableATGO(IN P_ADAPTER_T prAdapter) +{ + + P_MSG_P2P_CONNECTION_REQUEST_T prMsgConnReq = (P_MSG_P2P_CONNECTION_REQUEST_T) NULL; + UINT_8 aucTargetDeviceID[MAC_ADDR_LEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + + prMsgConnReq = + (P_MSG_P2P_CONNECTION_REQUEST_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_CONNECTION_REQUEST_T)); + if (!prMsgConnReq) { + ASSERT(FALSE); + return; + } + + prMsgConnReq->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_REQ; + + /*=====Param Modified for test=====*/ + COPY_MAC_ADDR(prMsgConnReq->aucDeviceID, aucTargetDeviceID); + prMsgConnReq->fgIsTobeGO = TRUE; + prMsgConnReq->fgIsPersistentGroup = FALSE; + + /*=====Param Modified for test=====*/ + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgConnReq, MSG_SEND_METHOD_BUF); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to retrieve NIC capability from firmware +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 g_u2FwIDVersion; +WLAN_STATUS wlanQueryNicCapability(IN P_ADAPTER_T prAdapter) +{ + UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; + 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_T)]; + P_HW_MAC_RX_DESC_T prRxStatus; + P_WIFI_EVENT_T prEvent; + P_EVENT_NIC_CAPABILITY_T prEventNicCapability; + + ASSERT(prAdapter); + + DEBUGFUNC("wlanQueryNicCapability"); + + /* 1. Allocate CMD Info Packet and its Buffer */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE + sizeof(EVENT_NIC_CAPABILITY_T)); + if (!prCmdInfo) { + DBGLOG(NIC, 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_T); + 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 = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + 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_T), + &u4RxPktLength) != WLAN_STATUS_SUCCESS) { + return WLAN_STATUS_FAILURE; + } + + /* Header checking .. */ + prRxStatus = (P_HW_MAC_RX_DESC_T) aucBuffer; + if (prRxStatus->u2PktTYpe != RXM_RXD_PKT_TYPE_SW_EVENT) { + DBGLOG(INIT, ERROR, "Unexpected packet type %d! not SW_EVENT\n", prRxStatus->u2PktTYpe); + return WLAN_STATUS_FAILURE; + } + + prEvent = (P_WIFI_EVENT_T) aucBuffer; + if (prEvent->ucEID != EVENT_ID_NIC_CAPABILITY) { + DBGLOG(INIT, ERROR, "Unexpected Event ID %d! expect %d\n", + prEvent->ucEID, EVENT_ID_NIC_CAPABILITY); + return WLAN_STATUS_FAILURE; + } + + prEventNicCapability = (P_EVENT_NIC_CAPABILITY_T) (prEvent->aucBuffer); + + prAdapter->rVerInfo.u2FwProductID = prEventNicCapability->u2ProductID; + prAdapter->rVerInfo.u2FwOwnVersion = prEventNicCapability->u2FwVersion; + prAdapter->rVerInfo.u2FwPeerVersion = prEventNicCapability->u2DriverVersion; + + /* Support FW version extend */ + prAdapter->rVerInfo.u4FwOwnVersionExtend = + (prEventNicCapability->aucFwVerExtend[0] << 24) + | (prEventNicCapability->aucFwVerExtend[1] << 16) + | (prEventNicCapability->aucFwVerExtend[2] << 8) + | (prEventNicCapability->aucFwVerExtend[3]); + + prAdapter->fgIsHw5GBandDisabled = (BOOLEAN) prEventNicCapability->ucHw5GBandDisabled; + prAdapter->fgIsEepromUsed = (BOOLEAN) prEventNicCapability->ucEepromUsed; + prAdapter->fgIsEmbbededMacAddrValid = (BOOLEAN) + (!IS_BMCAST_MAC_ADDR(prEventNicCapability->aucMacAddr) && + !EQUAL_MAC_ADDR(aucZeroMacAddr, prEventNicCapability->aucMacAddr)); + + COPY_MAC_ADDR(prAdapter->rWifiVar.aucPermanentAddress, prEventNicCapability->aucMacAddr); + COPY_MAC_ADDR(prAdapter->rWifiVar.aucMacAddress, prEventNicCapability->aucMacAddr); + + prAdapter->u4FwCompileFlag0 = prEventNicCapability->u4CompileFlag0; + prAdapter->u4FwCompileFlag1 = prEventNicCapability->u4CompileFlag1; + prAdapter->u4FwFeatureFlag0 = prEventNicCapability->u4FeatureFlag0; + prAdapter->u4FwFeatureFlag1 = prEventNicCapability->u4FeatureFlag1; + +#if CFG_SUPPORT_ANT_SWAP + prAdapter->fgIsAntSwpSupport = prEventNicCapability->ucAntSwapEn; + DBGLOG(NIC, INFO, "prAdapter->fgIsAntSwpSupport = %u\n", prAdapter->fgIsAntSwpSupport); +#endif + + g_u2FwIDVersion = (prAdapter->rVerInfo.u2FwProductID << 16) | (prAdapter->rVerInfo.u2FwOwnVersion); +#if CFG_ENABLE_CAL_LOG + DBGLOG(NIC, LOUD, " RF CAL FAIL = (%d),BB CAL FAIL = (%d)\n", + prEventNicCapability->ucRfCalFail, prEventNicCapability->ucBbCalFail); +#endif + + DBGLOG(NIC, INFO, "FW Ver DEC[%d.%d] HEX[%x.%x], Driver Ver[%d.%d]\n", + (prAdapter->rVerInfo.u2FwOwnVersion >> 8), + (UINT_16)(prAdapter->rVerInfo.u2FwOwnVersion & BITS(0, 7)), + (prAdapter->rVerInfo.u2FwOwnVersion >> 8), + (UINT_16)(prAdapter->rVerInfo.u2FwOwnVersion & BITS(0, 7)), + (prAdapter->rVerInfo.u2FwPeerVersion >> 8), + (UINT_16)(prAdapter->rVerInfo.u2FwPeerVersion & BITS(0, 7))); + + return WLAN_STATUS_SUCCESS; +} + +UINT_32 wlanGetFwIDVersion(void) +{ + UINT_32 u4FwIDVersion = 0; + + u4FwIDVersion = g_u2FwIDVersion; + + return u4FwIDVersion; +} +EXPORT_SYMBOL(wlanGetFwIDVersion); + +#if TXPWR_USE_PDSLOPE + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanQueryPdMcr(IN P_ADAPTER_T prAdapter, P_PARAM_MCR_RW_STRUCT_T prMcrRdInfo) +{ + UINT_8 ucCmdSeqNum; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_32 u4RxPktLength; + UINT_8 aucBuffer[sizeof(WIFI_EVENT_T) + sizeof(CMD_ACCESS_REG)]; + P_HW_MAC_RX_DESC_T prRxStatus; + 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 = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + 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 .. */ + prRxStatus = (P_HW_MAC_RX_DESC_T) aucBuffer; + if (prRxStatus->u2PktTYpe != RXM_RXD_PKT_TYPE_SW_EVENT) { + DBGLOG(INIT, ERROR, "Unexpected packet type %d! not SW_EVENT\n", prRxStatus->u2PktTYpe); + return WLAN_STATUS_FAILURE; + } + + prEvent = (P_WIFI_EVENT_T) aucBuffer; + if (prEvent->ucEID != EVENT_ID_ACCESS_REG) { + DBGLOG(INIT, ERROR, "Unexpected Event ID %d! expect %d\n", + prEvent->ucEID, EVENT_ID_ACCESS_REG); + return WLAN_STATUS_FAILURE; + } + + prCmdMcrQuery = (P_CMD_ACCESS_REG) (prEvent->aucBuffer); + prMcrRdInfo->u4McrOffset = prCmdMcrQuery->u4Address; + prMcrRdInfo->u4McrData = prCmdMcrQuery->u4Data; + + return WLAN_STATUS_SUCCESS; +} + +static INT_32 wlanIntRound(INT_32 au4Input) +{ + + if (au4Input >= 0) { + if ((au4Input % 10) == 5) { + au4Input = au4Input + 5; + return au4Input; + } + } + + if (au4Input < 0) { + if ((au4Input % 10) == -5) { + au4Input = au4Input - 5; + return au4Input; + } + } + + return au4Input; +} + +static INT_32 wlanCal6628EfuseForm(IN P_ADAPTER_T prAdapter, INT_32 au4Input) +{ + + PARAM_MCR_RW_STRUCT_T rMcrRdInfo; + INT_32 au4PdSlope, au4TxPwrOffset, au4TxPwrOffset_Round; + INT_8 auTxPwrOffset_Round; + + rMcrRdInfo.u4McrOffset = 0x60205c68; + rMcrRdInfo.u4McrData = 0; + au4TxPwrOffset = au4Input; + wlanQueryPdMcr(prAdapter, &rMcrRdInfo); + + au4PdSlope = (rMcrRdInfo.u4McrData) & BITS(0, 6); + au4TxPwrOffset_Round = wlanIntRound((au4TxPwrOffset * au4PdSlope)) / 10; + + au4TxPwrOffset_Round = -au4TxPwrOffset_Round; + + if (au4TxPwrOffset_Round < -128) + au4TxPwrOffset_Round = 128; + else if (au4TxPwrOffset_Round < 0) + au4TxPwrOffset_Round += 256; + else if (au4TxPwrOffset_Round > 127) + au4TxPwrOffset_Round = 127; + + auTxPwrOffset_Round = (UINT_8) au4TxPwrOffset_Round; + + return au4TxPwrOffset_Round; +} + +#endif + +#if CFG_SUPPORT_NVRAM_5G +WLAN_STATUS wlanLoadManufactureData_5G(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo) +{ + + P_BANDEDGE_5G_T pr5GBandEdge; + + ASSERT(prAdapter); + + pr5GBandEdge = &prRegInfo->prOldEfuseMapping->r5GBandEdgePwr; + + /* 1. set band edge tx power if available */ + if (pr5GBandEdge->uc5GBandEdgePwrUsed != 0) { + CMD_EDGE_TXPWR_LIMIT_T rCmdEdgeTxPwrLimit; + + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrCCK = 0; + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM20 = pr5GBandEdge->c5GBandEdgeMaxPwrOFDM20; + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM40 = pr5GBandEdge->c5GBandEdgeMaxPwrOFDM40; + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM80 = pr5GBandEdge->c5GBandEdgeMaxPwrOFDM80; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_EDGE_TXPWR_LIMIT_5G, + TRUE, + FALSE, + FALSE, + NULL, + NULL, sizeof(CMD_EDGE_TXPWR_LIMIT_T), (PUINT_8) &rCmdEdgeTxPwrLimit, NULL, 0); + + /* dumpMemory8(&rCmdEdgeTxPwrLimit,4); */ + } + + /*2.set channel offset for 8 sub-band */ + if (prRegInfo->prOldEfuseMapping->uc5GChannelOffsetVaild) { + CMD_POWER_OFFSET_T rCmdPowerOffset; + UINT_8 i; + + rCmdPowerOffset.ucBand = BAND_5G; + for (i = 0; i < MAX_SUBBAND_NUM_5G; i++) + rCmdPowerOffset.ucSubBandOffset[i] = prRegInfo->prOldEfuseMapping->auc5GChOffset[i]; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_CHANNEL_PWR_OFFSET, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(rCmdPowerOffset), (PUINT_8) &rCmdPowerOffset, NULL, 0); + /* dumpMemory8(&rCmdPowerOffset,9); */ + } + + /*3.set 5G AC power */ + if (prRegInfo->prOldEfuseMapping->uc11AcTxPwrValid) { + CMD_TX_AC_PWR_T rCmdAcPwr; + + kalMemCopy(&rCmdAcPwr.rAcPwr, &prRegInfo->prOldEfuseMapping->r11AcTxPwr, sizeof(AC_PWR_SETTING_STRUCT)); + rCmdAcPwr.ucBand = BAND_5G; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_80211AC_TX_PWR, + TRUE, + FALSE, FALSE, NULL, NULL, sizeof(CMD_TX_AC_PWR_T), (PUINT_8) &rCmdAcPwr, NULL, 0); + /* dumpMemory8(&rCmdAcPwr,9); */ + } + + return WLAN_STATUS_SUCCESS; +} +#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 +#if CFG_SUPPORT_FCC_DYNAMIC_TX_PWR_ADJUST + CMD_FCC_TX_PWR_ADJUST FccTxPwrAdjust = {0x00}; +#endif + + CMD_NVRAM_SETTING_T rCmdNvramSettings; +#if CFG_SUPPORT_PCC + UINT_16 u2Cnt = 0; +#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 (prAdapter->rVerInfo.u2Part1CfgPeerVersion > CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part2CfgPeerVersion > CFG_DRV_OWN_VERSION + || 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))); + } + } + +#if CFG_SUPPORT_FCC_DYNAMIC_TX_PWR_ADJUST + /* Tx Power Adjust for FCC/CE Certification */ + FccTxPwrAdjust.fgFccTxPwrAdjust = 1; /* 1:enable; 0:disable */ + FccTxPwrAdjust.Offset_CCK = 14; /* drop 7dB */ + FccTxPwrAdjust.Offset_HT20 = 16; /* drop 8dB */ + FccTxPwrAdjust.Offset_HT40 = 14; /* drop 7dB*/ + FccTxPwrAdjust.Channel_CCK[0] = 11; /* [0] for start channel */ + FccTxPwrAdjust.Channel_CCK[1] = 13; /* [1] for ending channel */ + FccTxPwrAdjust.Channel_HT20[0] = 11; /* [0] for start channel */ + FccTxPwrAdjust.Channel_HT20[1] = 13; /* [1] for ending channel */ + FccTxPwrAdjust.Channel_HT40[0] = 7; /* [0] for start channel,engineer mode ch9(2452) */ + FccTxPwrAdjust.Channel_HT40[1] = 9; /* [1] for ending channel,engineer mode ch11(2462) */ + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_FCC_TX_PWR_CERT, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_FCC_TX_PWR_ADJUST), (PUINT_8) (&FccTxPwrAdjust), NULL, 0); +#endif + + /* 3. Check if needs to support 5GHz */ + if (prRegInfo->ucEnable5GBand) { +#if CFG_SUPPORT_NVRAM_5G + wlanLoadManufactureData_5G(prAdapter, prRegInfo); +#endif + /* 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 CFG_SUPPORT_NVRAM_5G + /* If NvRAM read failed, this pointer will be NULL */ + if (prRegInfo->prOldEfuseMapping) { + /*2.set channel offset for 3 sub-band */ + if (prRegInfo->prOldEfuseMapping->ucChannelOffsetVaild) { + CMD_POWER_OFFSET_T rCmdPowerOffset; + UINT_8 i; + + rCmdPowerOffset.ucBand = BAND_2G4; + for (i = 0; i < 3; i++) + rCmdPowerOffset.ucSubBandOffset[i] = prRegInfo->prOldEfuseMapping->aucChOffset[i]; + rCmdPowerOffset.ucSubBandOffset[i] = prRegInfo->prOldEfuseMapping->acAllChannelOffset; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_CHANNEL_PWR_OFFSET, + TRUE, + FALSE, + FALSE, + NULL, NULL, sizeof(rCmdPowerOffset), (PUINT_8) &rCmdPowerOffset, NULL, 0); + /* dumpMemory8(&rCmdPowerOffset,9); */ + } + } +#else + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_PHY_PARAM, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_PHY_PARAM_T), (PUINT_8) (prRegInfo->aucEFUSE), NULL, 0); + +#endif + /*RSSI path compasation */ + if (prRegInfo->ucRssiPathCompasationUsed) { + CMD_RSSI_PATH_COMPASATION_T rCmdRssiPathCompasation; + + rCmdRssiPathCompasation.c2GRssiCompensation = prRegInfo->rRssiPathCompasation.c2GRssiCompensation; + rCmdRssiPathCompasation.c5GRssiCompensation = prRegInfo->rRssiPathCompasation.c5GRssiCompensation; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_PATH_COMPASATION, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(rCmdRssiPathCompasation), (PUINT_8) &rCmdRssiPathCompasation, 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); + /* Update supported channel list in channel table */ + wlanUpdateChannelTable(prAdapter->prGlueInfo); + + /* 7. set band edge tx power if available */ + if (prRegInfo->fg2G4BandEdgePwrUsed) { + CMD_EDGE_TXPWR_LIMIT_T rCmdEdgeTxPwrLimit; + + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrCCK = prRegInfo->cBandEdgeMaxPwrCCK; + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM20 = prRegInfo->cBandEdgeMaxPwrOFDM20; + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM40 = prRegInfo->cBandEdgeMaxPwrOFDM40; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_EDGE_TXPWR_LIMIT, + TRUE, + FALSE, + FALSE, + NULL, + NULL, sizeof(CMD_EDGE_TXPWR_LIMIT_T), (PUINT_8) &rCmdEdgeTxPwrLimit, NULL, 0); + } + /*8. Set 2.4G AC power */ + if (prRegInfo->prOldEfuseMapping) { + if (prRegInfo->prOldEfuseMapping->uc11AcTxPwrValid2G) { + CMD_TX_AC_PWR_T rCmdAcPwr; + + kalMemCopy(&rCmdAcPwr.rAcPwr, &prRegInfo->prOldEfuseMapping->r11AcTxPwr2G, + sizeof(AC_PWR_SETTING_STRUCT)); + rCmdAcPwr.ucBand = BAND_2G4; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_80211AC_TX_PWR, + TRUE, + FALSE, FALSE, NULL, NULL, sizeof(CMD_TX_AC_PWR_T), + (PUINT_8)&rCmdAcPwr, NULL, 0); + /* dumpMemory8(&rCmdAcPwr,9); */ + } + } +#if CFG_MODIFY_TX_POWER_BY_BAT_VOLT + if (wlan_bat_volt == 3550) + kalSetTxPwrBackoffByBattVolt(prAdapter, TRUE); +#endif + /* 9. Send the full Parameters of NVRAM to FW */ + +#if CFG_SUPPORT_PCC + for (u2Cnt = 64; u2Cnt < 96; u2Cnt++) + DBGLOG(INIT, TRACE, + "Dump NVRAM:[0x%x~0x%x]: 0x%x-0x%x-0x%x-0x%x-0x%x-0x%x-0x%x-0x%x\n", + u2Cnt*8, u2Cnt*8+7, + prRegInfo->aucNvram[u2Cnt*8], + prRegInfo->aucNvram[u2Cnt*8+1], + prRegInfo->aucNvram[u2Cnt*8+2], + prRegInfo->aucNvram[u2Cnt*8+3], + prRegInfo->aucNvram[u2Cnt*8+4], + prRegInfo->aucNvram[u2Cnt*8+5], + prRegInfo->aucNvram[u2Cnt*8+6], + prRegInfo->aucNvram[u2Cnt*8+7]); +#endif + + kalMemCopy(&rCmdNvramSettings.rNvramSettings, + &prRegInfo->prNvramSettings->u2Part1OwnVersion, sizeof(WIFI_CFG_PARAM_STRUCT)); + ASSERT(sizeof(WIFI_CFG_PARAM_STRUCT) == EXTEND_NVRAM_SIZE); + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_NVRAM_SETTINGS, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(rCmdNvramSettings), (PUINT_8) &rCmdNvramSettings, 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; + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + + prMsduInfo = cnmPktAlloc(prAdapter, 0); + + if (!prMsduInfo) + return WLAN_STATUS_RESOURCES; + + if (nicTxFillMsduInfo(prAdapter, prMsduInfo, prNativePacket)) { + /* prMsduInfo->eSrc = TX_PACKET_OS; */ + + /* Tx profiling */ + wlanTxProfilingTagMsdu(prAdapter, prMsduInfo, TX_PROF_TAG_DRV_ENQUE); + + /* enqueue to QM */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + } else { + kalSendComplete(prAdapter->prGlueInfo, prNativePacket, WLAN_STATUS_INVALID_PACKET); + + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + + return WLAN_STATUS_INVALID_PACKET; + } + + 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; + +#if !CFG_SUPPORT_MULTITHREAD + ASSERT(pfgHwAccess); +#endif + + /* <1> dequeue packet by txDequeuTxPackets() */ +#if CFG_SUPPORT_MULTITHREAD + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + prMsduInfo = qmDequeueTxPacketsMthread(prAdapter, &prTxCtrl->rTc); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); +#else + 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); +#endif + if (prMsduInfo != NULL) { + if (kalIsCardRemoved(prAdapter->prGlueInfo) == FALSE) { +#if !CFG_SUPPORT_MULTITHREAD + /* <2> Acquire LP-OWN if necessary */ + if (*pfgHwAccess == FALSE) { + *pfgHwAccess = TRUE; + + wlanAcquirePowerControl(prAdapter); + } +#endif + /* <3> send packets */ +#if CFG_SUPPORT_MULTITHREAD + nicTxMsduInfoListMthread(prAdapter, prMsduInfo); +#else + nicTxMsduInfoList(prAdapter, prMsduInfo); +#endif + /* <4> update TC by txAdjustTcQuotas() */ + nicTxAdjustTcq(prAdapter); + } else + wlanProcessQueuedMsduInfo(prAdapter, prMsduInfo); + } + + 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); + + /* DBGLOG(INIT, INFO, ("Acquire Power Ctrl\n")); */ + + 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); + + /* DBGLOG(INIT, INFO, ("Release Power Ctrl\n")); */ + + 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; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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) +{ + UINT_8 ucEcoVersion; + + ASSERT(prAdapter); + +#if defined(MT6630) +#if CFG_MULTI_ECOVER_SUPPORT + ucEcoVersion = nicGetChipEcoVer(); + DBGLOG(INIT, TRACE, "Chip ECO Ver: E%u\n", ucEcoVersion); +#else + nicGetChipID(prAdapter); + ucEcoVersion = prAdapter->ucRevID + 1; +#endif +#else /* MT6631 A-D die chip */ + ucEcoVersion = 1; +#endif + + return ucEcoVersion; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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 ucBssIndex BSS Info Index +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanSetPreferBandByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_BAND_T eBand, IN UINT_8 ucBssIndex) +{ + ASSERT(prAdapter); + ASSERT(eBand <= BAND_NUM); + ASSERT(ucBssIndex <= MAX_BSS_INDEX); + ASSERT(ucBssIndex <= BSS_INFO_NUM); + + /* 1. set prefer band according to network type */ + prAdapter->aePreferBand[ucBssIndex] = eBand; + + /* 2. remove buffered BSS descriptors correspondingly */ + if (eBand == BAND_2G4) + scanRemoveBssDescByBandAndNetwork(prAdapter, BAND_5G, ucBssIndex); + else if (eBand == BAND_5G) + scanRemoveBssDescByBandAndNetwork(prAdapter, BAND_2G4, ucBssIndex); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to +* get channel information corresponding to specified network type +* +* @param prAdapter Pointer of Adapter Data Structure +* @param ucBssIndex BSS Info Index +* +* @return channel number +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 wlanGetChannelNumberByNetwork(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex) +{ + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= MAX_BSS_INDEX); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + return prBssInfo->ucPrimaryChannel; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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 (CFG_SUPPORT_PWR_LIMIT_COUNTRY == 1) + if (fgIsConfExist == TRUE && (prAdapter->rVerInfo.u2Part1CfgPeerVersion > CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part2CfgPeerVersion > CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part1CfgOwnVersion < CFG_DRV_PEER_VERSION + || prAdapter->rVerInfo.u2Part2CfgOwnVersion < CFG_DRV_PEER_VERSION /* NVRAM */ + || prAdapter->rVerInfo.u2FwPeerVersion > CFG_DRV_OWN_VERSION + || 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 || prAdapter->fgIsPowerLimitTableValid == FALSE)) + fgGenErrMsg = TRUE; +#else + if (fgIsConfExist == TRUE && (prAdapter->rVerInfo.u2Part1CfgPeerVersion > CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part2CfgPeerVersion > CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part1CfgOwnVersion < CFG_DRV_PEER_VERSION + || prAdapter->rVerInfo.u2Part2CfgOwnVersion < CFG_DRV_PEER_VERSION /* NVRAM */ + || prAdapter->rVerInfo.u2FwPeerVersion > CFG_DRV_OWN_VERSION + || 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 +#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, aucBCAddr); + 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) && (prSsid)) { + COPY_SSID(prSsid->aucSSID, prSsid->ucLength, NVRAM_ERR_MSG, (UINT_8) (strlen(NVRAM_ERR_MSG))); + + kalIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) prBeacon, + OFFSET_OF(WLAN_BEACON_FRAME_T, + aucInfoElem) + OFFSET_OF(IE_SSID_T, aucSSID) + prSsid->ucLength, 1, 0); + + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, NVRAM_ERR_MSG, strlen(NVRAM_ERR_MSG)); + nicAddScanResult(prAdapter, + prBeacon->aucBSSID, + &rSsid, + 0, + 0, + PARAM_NETWORK_TYPE_FH, + &rConfiguration, + NET_TYPE_INFRA, + rSupportedRates, + OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem) + OFFSET_OF(IE_SSID_T, + aucSSID) + + prSsid->ucLength - WLAN_MAC_MGMT_HEADER_LEN, + (PUINT_8) ((ULONG) (prBeacon) + WLAN_MAC_MGMT_HEADER_LEN)); + } +#endif + +#if (CFG_SW_NVRAM_VERSION_CHECK == 1) +#define VER_ERR_MSG "NVRAM WARNING: Err = 0x%02X" + if (fgIsConfExist == TRUE) { + if ((prAdapter->rVerInfo.u2Part1CfgPeerVersion > CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part2CfgPeerVersion > CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part1CfgOwnVersion < CFG_DRV_PEER_VERSION + || prAdapter->rVerInfo.u2Part2CfgOwnVersion < CFG_DRV_PEER_VERSION /* NVRAM */ + || prAdapter->rVerInfo.u2FwPeerVersion > CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2FwOwnVersion < CFG_DRV_PEER_VERSION)) + u4ErrCode |= NVRAM_ERROR_VERSION_MISMATCH; + + if (prRegInfo->ucTxPwrValid == 0) + u4ErrCode |= NVRAM_ERROR_INVALID_TXPWR; + + if (prAdapter->fgIsEmbbededMacAddrValid == FALSE && (IS_BMCAST_MAC_ADDR(prRegInfo->aucMacAddr) + || EQUAL_MAC_ADDR(aucZeroMacAddr, + prRegInfo->aucMacAddr))) { + u4ErrCode |= NVRAM_ERROR_INVALID_MAC_ADDR; + } +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + if (prAdapter->fgIsPowerLimitTableValid == FALSE) + u4ErrCode |= NVRAM_POWER_LIMIT_TABLE_INVALID; +#endif + if ((u4ErrCode != 0) && (prSsid)) { + if (0 < sprintf(aucErrMsg, VER_ERR_MSG, (unsigned int)u4ErrCode)) + COPY_SSID(prSsid->aucSSID, prSsid->ucLength, aucErrMsg, (UINT_8) (strlen(aucErrMsg))); + else { + prSsid->aucSSID[0] = ' '; + prSsid->aucSSID[1] = '\0'; + prSsid->ucLength = 1; + } + + kalIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) prBeacon, + OFFSET_OF(WLAN_BEACON_FRAME_T, + aucInfoElem) + OFFSET_OF(IE_SSID_T, + aucSSID) + prSsid->ucLength, 1, 0); + + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, NVRAM_ERR_MSG, strlen(NVRAM_ERR_MSG)); + nicAddScanResult(prAdapter, prBeacon->aucBSSID, &rSsid, 0, 0, + PARAM_NETWORK_TYPE_FH, &rConfiguration, NET_TYPE_INFRA, + rSupportedRates, OFFSET_OF(WLAN_BEACON_FRAME_T, + aucInfoElem) + + OFFSET_OF(IE_SSID_T, + aucSSID) + prSsid->ucLength - + WLAN_MAC_MGMT_HEADER_LEN, + (PUINT_8) ((ULONG) (prBeacon) + WLAN_MAC_MGMT_HEADER_LEN)); + } + } +#endif + + if (fgGenErrMsg == TRUE) + cnmMemFree(prAdapter, prBeacon); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidQueryBssStatistics(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_GET_BSS_STATISTICS prQueryBssStatistics; + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + WLAN_STATUS rResult = WLAN_STATUS_FAILURE; + UINT_8 ucBssIndex; + ENUM_WMM_ACI_T eAci; + + DEBUGFUNC("wlanoidQueryBssStatistics"); + + do { + ASSERT(pvQueryBuffer); + + /* 4 1. Sanity test */ + if ((prAdapter == NULL) || (pu4QueryInfoLen == NULL)) + break; + + if ((u4QueryBufferLen) && (pvQueryBuffer == NULL)) + break; + + if (u4QueryBufferLen < sizeof(P_PARAM_GET_BSS_STATISTICS)) { + *pu4QueryInfoLen = sizeof(P_PARAM_GET_BSS_STATISTICS); + rResult = WLAN_STATUS_BUFFER_TOO_SHORT; + break; + } + + prQueryBssStatistics = (P_PARAM_GET_BSS_STATISTICS) pvQueryBuffer; + *pu4QueryInfoLen = sizeof(PARAM_GET_BSS_STATISTICS); + + ucBssIndex = prQueryBssStatistics->ucBssIndex; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (prBssInfo) { + /*AIS*/ + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + prStaRec = prBssInfo->prStaRecOfAP; + if (prStaRec) { + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prQueryBssStatistics->arLinkStatistics[eAci].u4TxMsdu = + prStaRec->arLinkStatistics[eAci].u4TxMsdu; + prQueryBssStatistics->arLinkStatistics[eAci].u4RxMsdu = + prStaRec->arLinkStatistics[eAci].u4RxMsdu; + prQueryBssStatistics->arLinkStatistics[eAci].u4TxDropMsdu = + prStaRec->arLinkStatistics[eAci].u4TxDropMsdu + + prBssInfo->arLinkStatistics[eAci].u4TxDropMsdu; + prQueryBssStatistics->arLinkStatistics[eAci].u4TxFailMsdu = + prStaRec->arLinkStatistics[eAci].u4TxFailMsdu; + prQueryBssStatistics->arLinkStatistics[eAci].u4TxRetryMsdu = + prStaRec->arLinkStatistics[eAci].u4TxRetryMsdu; + } + } + } + rResult = WLAN_STATUS_SUCCESS; + + /*P2P */ + /* TODO */ + + /*BOW*/ + /* TODO */ + } + + } while (FALSE); + + return rResult; + +} + +VOID wlanDumpBssStatistics(IN P_ADAPTER_T prAdapter, UINT_8 ucBssIdx) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + ENUM_WMM_ACI_T eAci; + WIFI_WMM_AC_STAT_T arLLStats[WMM_AC_INDEX_NUM]; + UINT_8 ucIdx; + + if (ucBssIdx > MAX_BSS_INDEX) { + DBGLOG(SW4, WARN, "Invalid BssInfo index[%u], skip dump!\n", ucBssIdx); + return; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + if (!prBssInfo || !IS_BSS_ACTIVE(prBssInfo)) { + DBGLOG(SW4, WARN, "Invalid BssInfo index[%u] or inactive, skip dump!\n", ucBssIdx); + return; + } + /* <1> fill per-BSS statistics */ +#if 0 + /*AIS*/ if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + prStaRec = prBssInfo->prStaRecOfAP; + if (prStaRec) { + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prBssInfo->arLinkStatistics[eAci].u4TxMsdu = prStaRec->arLinkStatistics[eAci].u4TxMsdu; + prBssInfo->arLinkStatistics[eAci].u4RxMsdu = prStaRec->arLinkStatistics[eAci].u4RxMsdu; + prBssInfo->arLinkStatistics[eAci].u4TxDropMsdu += + prStaRec->arLinkStatistics[eAci].u4TxDropMsdu; + prBssInfo->arLinkStatistics[eAci].u4TxFailMsdu = + prStaRec->arLinkStatistics[eAci].u4TxFailMsdu; + prBssInfo->arLinkStatistics[eAci].u4TxRetryMsdu = + prStaRec->arLinkStatistics[eAci].u4TxRetryMsdu; + } + } + } +#else + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + arLLStats[eAci].u4TxMsdu = prBssInfo->arLinkStatistics[eAci].u4TxMsdu; + arLLStats[eAci].u4RxMsdu = prBssInfo->arLinkStatistics[eAci].u4RxMsdu; + arLLStats[eAci].u4TxDropMsdu = prBssInfo->arLinkStatistics[eAci].u4TxDropMsdu; + arLLStats[eAci].u4TxFailMsdu = prBssInfo->arLinkStatistics[eAci].u4TxFailMsdu; + arLLStats[eAci].u4TxRetryMsdu = prBssInfo->arLinkStatistics[eAci].u4TxRetryMsdu; + } + + for (ucIdx = 0; ucIdx < CFG_NUM_OF_STA_RECORD; ucIdx++) { + prStaRec = cnmGetStaRecByIndex(prAdapter, ucIdx); + if (!prStaRec || prStaRec->ucBssIndex != ucBssIdx) + continue; + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + arLLStats[eAci].u4TxMsdu += prStaRec->arLinkStatistics[eAci].u4TxMsdu; + arLLStats[eAci].u4RxMsdu += prStaRec->arLinkStatistics[eAci].u4RxMsdu; + arLLStats[eAci].u4TxDropMsdu += prStaRec->arLinkStatistics[eAci].u4TxDropMsdu; + arLLStats[eAci].u4TxFailMsdu += prStaRec->arLinkStatistics[eAci].u4TxFailMsdu; + arLLStats[eAci].u4TxRetryMsdu += prStaRec->arLinkStatistics[eAci].u4TxRetryMsdu; + } + } +#endif + + /* <2>Dump BSS statistics */ + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + DBGLOG(BSS, TRACE, "LLS BSS[%u] AC[%u]: T[%u] R[%u] T_D[%u] T_F[%u]\n", + prBssInfo->ucBssIndex, eAci, arLLStats[eAci].u4TxMsdu, + arLLStats[eAci].u4RxMsdu, arLLStats[eAci].u4TxDropMsdu, + arLLStats[eAci].u4TxFailMsdu); + } +} + +VOID wlanDumpAllBssStatistics(IN P_ADAPTER_T prAdapter) +{ + /* ENUM_WMM_ACI_T eAci; */ + UINT_32 ucIdx; + + /* wlanUpdateAllBssStatistics(prAdapter); */ + + for (ucIdx = 0; ucIdx < BSS_INFO_NUM; ucIdx++) + wlanDumpBssStatistics(prAdapter, ucIdx); +} + +WLAN_STATUS +wlanoidQueryStaStatistics(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + return wlanQueryStaStatistics(prAdapter, pvQueryBuffer, u4QueryBufferLen, pu4QueryInfoLen, TRUE); +} + +WLAN_STATUS wlanQueryStaStatistics(IN P_ADAPTER_T prAdapter, IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen, BOOLEAN fgIsOid) +{ + WLAN_STATUS rResult = WLAN_STATUS_FAILURE; + P_STA_RECORD_T prStaRec, prTempStaRec; + P_PARAM_GET_STA_STATISTICS prQueryStaStatistics; + UINT_8 ucStaRecIdx; + P_QUE_MGT_T prQM = &prAdapter->rQM; + CMD_GET_STA_STATISTICS_T rQueryCmdStaStatistics; + UINT_8 ucIdx; + ENUM_WMM_ACI_T eAci; + + DEBUGFUNC("wlanoidQueryStaStatistics"); + do { + ASSERT(pvQueryBuffer); + + /* 4 1. Sanity test */ + if ((prAdapter == NULL) || (pu4QueryInfoLen == NULL)) + break; + + if ((u4QueryBufferLen) && (pvQueryBuffer == NULL)) + break; + + if (u4QueryBufferLen < sizeof(PARAM_GET_STA_STA_STATISTICS)) { + *pu4QueryInfoLen = sizeof(PARAM_GET_STA_STA_STATISTICS); + rResult = WLAN_STATUS_BUFFER_TOO_SHORT; + break; + } + + prQueryStaStatistics = (P_PARAM_GET_STA_STATISTICS) pvQueryBuffer; + *pu4QueryInfoLen = sizeof(PARAM_GET_STA_STA_STATISTICS); + + /* 4 5. Get driver global QM counter */ + for (ucIdx = TC0_INDEX; ucIdx <= TC3_INDEX; ucIdx++) { + prQueryStaStatistics->au4TcAverageQueLen[ucIdx] = prQM->au4AverageQueLen[ucIdx]; + prQueryStaStatistics->au4TcCurrentQueLen[ucIdx] = prQM->au4CurrentTcResource[ucIdx]; + } + + /* 4 2. Get StaRec by MAC address */ + prStaRec = NULL; + + for (ucStaRecIdx = 0; ucStaRecIdx < CFG_NUM_OF_STA_RECORD; ucStaRecIdx++) { + prTempStaRec = &(prAdapter->arStaRec[ucStaRecIdx]); + if (prTempStaRec->fgIsValid && prTempStaRec->fgIsInUse) { + if (EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, prQueryStaStatistics->aucMacAddr)) { + prStaRec = prTempStaRec; + break; + } + } + } + + if (!prStaRec) { + rResult = WLAN_STATUS_INVALID_DATA; + break; + } + + prQueryStaStatistics->u4Flag |= BIT(0); + +#if CFG_ENABLE_PER_STA_STATISTICS + + DBGLOG(TX, TRACE, "skbToDriver %lld, skbFreed: %lld\n", + prAdapter->prGlueInfo->u8SkbToDriver, + prAdapter->prGlueInfo->u8SkbFreed); + prAdapter->prGlueInfo->u8SkbFreed = 0; + prAdapter->prGlueInfo->u8SkbToDriver = 0; + + /* 4 3. Get driver statistics */ + prQueryStaStatistics->u4TxTotalCount = prStaRec->u4TotalTxPktsNumber; + prQueryStaStatistics->u4RxTotalCount = prStaRec->u4TotalRxPktsNumber; + prQueryStaStatistics->u4TxExceedThresholdCount = prStaRec->u4ThresholdCounter; + prQueryStaStatistics->u4TxMaxTime = prStaRec->u4MaxTxPktsTime; + prQueryStaStatistics->u4TxMaxHifTime = prStaRec->u4MaxTxPktsHifTime; + + if (prStaRec->u4TotalTxPktsNumber) { + prQueryStaStatistics->u4TxAverageProcessTime = + (prStaRec->u4TotalTxPktsTime / prStaRec->u4TotalTxPktsNumber); + prQueryStaStatistics->u4TxAverageHifTime = + prStaRec->u4TotalTxPktsHifTxTime / prStaRec->u4TotalTxPktsNumber; + } else + prQueryStaStatistics->u4TxAverageProcessTime = 0; + + /*link layer statistics */ + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prQueryStaStatistics->arLinkStatistics[eAci].u4TxMsdu = + prStaRec->arLinkStatistics[eAci].u4TxMsdu; + prQueryStaStatistics->arLinkStatistics[eAci].u4RxMsdu = + prStaRec->arLinkStatistics[eAci].u4RxMsdu; + prQueryStaStatistics->arLinkStatistics[eAci].u4TxDropMsdu = + prStaRec->arLinkStatistics[eAci].u4TxDropMsdu; + } + + for (ucIdx = TC0_INDEX; ucIdx <= TC3_INDEX; ucIdx++) { + prQueryStaStatistics->au4TcResourceEmptyCount[ucIdx] = + prQM->au4QmTcResourceEmptyCounter[prStaRec->ucBssIndex][ucIdx]; + /* Reset */ + prQM->au4QmTcResourceEmptyCounter[prStaRec->ucBssIndex][ucIdx] = 0; + prQueryStaStatistics->au4TcResourceBackCount[ucIdx] = + prQM->au4QmTcResourceBackCounter[ucIdx]; + prQM->au4QmTcResourceBackCounter[ucIdx] = 0; + prQueryStaStatistics->au4DequeueNoTcResource[ucIdx] = + prQM->au4DequeueNoTcResourceCounter[ucIdx]; + prQM->au4DequeueNoTcResourceCounter[ucIdx] = 0; + prQueryStaStatistics->au4TcResourceUsedPageCount[ucIdx] = + prQM->au4QmTcUsedPageCounter[ucIdx]; + prQM->au4QmTcUsedPageCounter[ucIdx] = 0; + prQueryStaStatistics->au4TcResourceWantedPageCount[ucIdx] = + prQM->au4QmTcWantedPageCounter[ucIdx]; + prQM->au4QmTcWantedPageCounter[ucIdx] = 0; + } + + prQueryStaStatistics->u4EnqueueCounter = prQM->u4EnqueueCounter; + prQueryStaStatistics->u4EnqueueStaCounter = prStaRec->u4EnqueueCounter; + + prQueryStaStatistics->u4DequeueCounter = prQM->u4DequeueCounter; + prQueryStaStatistics->u4DequeueStaCounter = prStaRec->u4DeqeueuCounter; + + prQueryStaStatistics->IsrCnt = prAdapter->prGlueInfo->IsrCnt; + prQueryStaStatistics->IsrPassCnt = prAdapter->prGlueInfo->IsrPassCnt; + prQueryStaStatistics->TaskIsrCnt = prAdapter->prGlueInfo->TaskIsrCnt; + + prQueryStaStatistics->IsrAbnormalCnt = prAdapter->prGlueInfo->IsrAbnormalCnt; + prQueryStaStatistics->IsrSoftWareCnt = prAdapter->prGlueInfo->IsrSoftWareCnt; + prQueryStaStatistics->IsrRxCnt = prAdapter->prGlueInfo->IsrRxCnt; + prQueryStaStatistics->IsrTxCnt = prAdapter->prGlueInfo->IsrTxCnt; + + + /* 4 4.1 Reset statistics */ + if (prQueryStaStatistics->ucReadClear) { + prStaRec->u4ThresholdCounter = 0; + prStaRec->u4TotalTxPktsNumber = 0; + + prStaRec->u4TotalTxPktsTime = 0; + prStaRec->u4TotalTxPktsHifTxTime = 0; + + prStaRec->u4TotalRxPktsNumber = 0; + + prStaRec->u4MaxTxPktsTime = 0; + prStaRec->u4MaxTxPktsHifTime = 0; + prQM->u4EnqueueCounter = 0; + prQM->u4DequeueCounter = 0; + prStaRec->u4EnqueueCounter = 0; + prStaRec->u4DeqeueuCounter = 0; + + prAdapter->prGlueInfo->IsrCnt = 0; + prAdapter->prGlueInfo->IsrPassCnt = 0; + prAdapter->prGlueInfo->TaskIsrCnt = 0; + + prAdapter->prGlueInfo->IsrAbnormalCnt = 0; + prAdapter->prGlueInfo->IsrSoftWareCnt = 0; + prAdapter->prGlueInfo->IsrRxCnt = 0; + prAdapter->prGlueInfo->IsrTxCnt = 0; + } + /*link layer statistics */ + if (prQueryStaStatistics->ucLlsReadClear) { + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prStaRec->arLinkStatistics[eAci].u4TxMsdu = 0; + prStaRec->arLinkStatistics[eAci].u4RxMsdu = 0; + prStaRec->arLinkStatistics[eAci].u4TxDropMsdu = 0; + } + } +#endif + + for (ucIdx = TC0_INDEX; ucIdx <= TC3_INDEX; ucIdx++) + prQueryStaStatistics->au4TcQueLen[ucIdx] = prStaRec->arTxQueue[ucIdx].u4NumElem; + + rResult = WLAN_STATUS_SUCCESS; + + /* 4 6. Ensure FW supports get station link status */ + if (prAdapter->u4FwCompileFlag0 & COMPILE_FLAG0_GET_STA_LINK_STATUS) { + + rQueryCmdStaStatistics.ucIndex = prStaRec->ucIndex; + COPY_MAC_ADDR(rQueryCmdStaStatistics.aucMacAddr, prQueryStaStatistics->aucMacAddr); + rQueryCmdStaStatistics.ucReadClear = prQueryStaStatistics->ucReadClear; + rQueryCmdStaStatistics.ucLlsReadClear = prQueryStaStatistics->ucLlsReadClear; + + rResult = wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STA_STATISTICS, + FALSE, + TRUE, + fgIsOid, + nicCmdEventQueryStaStatistics, + nicOidCmdTimeoutCommon, + sizeof(CMD_GET_STA_STATISTICS_T), + (PUINT_8) &rQueryCmdStaStatistics, + pvQueryBuffer, u4QueryBufferLen); + if ((!fgIsOid) && (rResult == WLAN_STATUS_PENDING)) + rResult = WLAN_STATUS_SUCCESS; + prQueryStaStatistics->u4Flag |= BIT(1); + } else { + rResult = WLAN_STATUS_NOT_SUPPORTED; + } + + } while (FALSE); + + return rResult; +} /* wlanoidQueryP2pVersion */ +WLAN_STATUS +wlanQueryStatistics(IN P_ADAPTER_T prAdapter, IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen, BOOLEAN fgIsOid) +{ + DEBUGFUNC("wlanoidQueryStatistics"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(PARAM_802_11_STATISTICS_STRUCT_T)) { + DBGLOG(OID, WARN, "Too short length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + P_PARAM_802_11_STATISTICS_STRUCT_T prStatistics; + + *pu4QueryInfoLen = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + prStatistics = (P_PARAM_802_11_STATISTICS_STRUCT_T) pvQueryBuffer; + + prStatistics->u4Length = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + prStatistics->rTransmittedFragmentCount = prAdapter->rStatStruct.rTransmittedFragmentCount; + prStatistics->rMulticastTransmittedFrameCount = prAdapter->rStatStruct.rMulticastTransmittedFrameCount; + prStatistics->rFailedCount = prAdapter->rStatStruct.rFailedCount; + prStatistics->rRetryCount = prAdapter->rStatStruct.rRetryCount; + prStatistics->rMultipleRetryCount = prAdapter->rStatStruct.rMultipleRetryCount; + prStatistics->rRTSSuccessCount = prAdapter->rStatStruct.rRTSSuccessCount; + prStatistics->rRTSFailureCount = prAdapter->rStatStruct.rRTSFailureCount; + prStatistics->rACKFailureCount = prAdapter->rStatStruct.rACKFailureCount; + prStatistics->rFrameDuplicateCount = prAdapter->rStatStruct.rFrameDuplicateCount; + prStatistics->rReceivedFragmentCount = prAdapter->rStatStruct.rReceivedFragmentCount; + prStatistics->rMulticastReceivedFrameCount = prAdapter->rStatStruct.rMulticastReceivedFrameCount; + prStatistics->rFCSErrorCount = prAdapter->rStatStruct.rFCSErrorCount; + prStatistics->rTKIPLocalMICFailures.QuadPart = 0; + prStatistics->rTKIPICVErrors.QuadPart = 0; + prStatistics->rTKIPCounterMeasuresInvoked.QuadPart = 0; + prStatistics->rTKIPReplays.QuadPart = 0; + prStatistics->rCCMPFormatErrors.QuadPart = 0; + prStatistics->rCCMPReplays.QuadPart = 0; + prStatistics->rCCMPDecryptErrors.QuadPart = 0; + prStatistics->rFourWayHandshakeFailures.QuadPart = 0; + prStatistics->rWEPUndecryptableCount.QuadPart = 0; + prStatistics->rWEPICVErrorCount.QuadPart = 0; + prStatistics->rDecryptSuccessCount.QuadPart = 0; + prStatistics->rDecryptFailureCount.QuadPart = 0; + } else +#endif + { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + fgIsOid, + nicCmdEventQueryStatistics, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + } + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryStatistics */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to query Nic resource information +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanQueryNicResourceInformation(IN P_ADAPTER_T prAdapter) +{ + /* 3 1. Get Nic resource information from FW */ + + /* 3 2. Setup resource parameter */ + + /* 3 3. Reset Tx resource */ + nicTxResetResource(prAdapter); +} + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to SET network interface index for a network interface. +* A network interface is a TX/RX data port hooked to OS. +* +* @param prGlueInfo Pointer of prGlueInfo Data Structure +* @param ucNetInterfaceIndex Index of network interface +* @param ucBssIndex Index of BSS +* +* @return VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanBindNetInterface(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucNetInterfaceIndex, IN PVOID pvNetInterface) +{ + P_NET_INTERFACE_INFO_T prNetIfInfo; + + prNetIfInfo = &prGlueInfo->arNetInterfaceInfo[ucNetInterfaceIndex]; + + prNetIfInfo->pvNetInterface = pvNetInterface; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to SET BSS index for a network interface. +* A network interface is a TX/RX data port hooked to OS. +* +* @param prGlueInfo Pointer of prGlueInfo Data Structure +* @param ucNetInterfaceIndex Index of network interface +* @param ucBssIndex Index of BSS +* +* @return VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanBindBssIdxToNetInterface(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucBssIndex, IN PVOID pvNetInterface) +{ + P_NET_INTERFACE_INFO_T prNetIfInfo; + + if (ucBssIndex >= MAX_BSS_INDEX) + return; + + prNetIfInfo = &prGlueInfo->arNetInterfaceInfo[ucBssIndex]; + + prNetIfInfo->ucBssIndex = ucBssIndex; + prNetIfInfo->pvNetInterface = pvNetInterface; + /* prGlueInfo->aprBssIdxToNetInterfaceInfo[ucBssIndex] = prNetIfInfo; */ +} + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to GET BSS index for a network interface. +* A network interface is a TX/RX data port hooked to OS. +* +* @param prGlueInfo Pointer of prGlueInfo Data Structure +* @param ucNetInterfaceIndex Index of network interface +* +* @return UINT_8 Index of BSS +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 wlanGetBssIdxByNetInterface(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvNetInterface) +{ + UINT_8 ucIdx = 0; + + for (ucIdx = 0; ucIdx < HW_BSSID_NUM; ucIdx++) { + if (prGlueInfo->arNetInterfaceInfo[ucIdx].pvNetInterface == pvNetInterface) + break; + } + + return ucIdx; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to GET network interface for a BSS. +* A network interface is a TX/RX data port hooked to OS. +* +* @param prGlueInfo Pointer of prGlueInfo Data Structure +* @param ucBssIndex Index of BSS +* +* @return PVOID pointer of network interface structure +*/ +/*----------------------------------------------------------------------------*/ +PVOID wlanGetNetInterfaceByBssIdx(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucBssIndex) +{ + if (ucBssIndex < HW_BSSID_NUM) + return prGlueInfo->arNetInterfaceInfo[ucBssIndex].pvNetInterface; + return NULL; +} + +uint8_t wlanGetBssIdx(struct net_device *ndev) +{ + if (ndev) { + struct _NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate + = (struct _NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(ndev); + + DBGLOG(REQ, LOUD, + "ucBssIndex = %d\n", + prNetDevPrivate->ucBssIdx); + + return prNetDevPrivate->ucBssIdx; + } + + DBGLOG(REQ, LOUD, + "ucBssIndex = 0xff\n"); + + return 0xff; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to get BSS-INDEX for AIS network. +* +* @param prAdapter Pointer of ADAPTER_T +* +* @return value, as corresponding index of BSS +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 wlanGetAisBssIndex(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + return prAdapter->prAisBssInfo->ucBssIndex; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to initialize WLAN feature options +* +* @param prAdapter Pointer of ADAPTER_T +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanInitFeatureOption(IN P_ADAPTER_T prAdapter) +{ + P_WIFI_VAR_T prWifiVar = &prAdapter->rWifiVar; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + /* Feature options will be filled by config file */ + + prWifiVar->ucQoS = (UINT_8) wlanCfgGetUint32(prAdapter, "Qos", FEATURE_ENABLED); + + prWifiVar->aucAifsN[WMM_AC_BE_INDEX] = (UINT_8) wlanCfgGetUint32(prAdapter, "BeAifsN", 3); + prWifiVar->aucAifsN[WMM_AC_BK_INDEX] = (UINT_8) wlanCfgGetUint32(prAdapter, "BkAifsN", 7); + prWifiVar->aucAifsN[WMM_AC_VI_INDEX] = (UINT_8) wlanCfgGetUint32(prAdapter, "ViAifsN", 1); + prWifiVar->aucAifsN[WMM_AC_VO_INDEX] = (UINT_8) wlanCfgGetUint32(prAdapter, "VoAifsN", 1); + + prWifiVar->aucCwMin[WMM_AC_BE_INDEX] = (UINT_8) wlanCfgGetUint32(prAdapter, "BeCwMin", 15); + prWifiVar->aucCwMin[WMM_AC_BK_INDEX] = (UINT_8) wlanCfgGetUint32(prAdapter, "BkCwMin", 15); + prWifiVar->aucCwMin[WMM_AC_VI_INDEX] = (UINT_8) wlanCfgGetUint32(prAdapter, "ViCwMin", 7); + prWifiVar->aucCwMin[WMM_AC_VO_INDEX] = (UINT_8) wlanCfgGetUint32(prAdapter, "VoCwMin", 3); + + prWifiVar->au2CwMax[WMM_AC_BE_INDEX] = (UINT_16) wlanCfgGetUint32(prAdapter, "BeCwMax", 63); + prWifiVar->au2CwMax[WMM_AC_BK_INDEX] = (UINT_16) wlanCfgGetUint32(prAdapter, "BkCwMax", 1023); + prWifiVar->au2CwMax[WMM_AC_VI_INDEX] = (UINT_16) wlanCfgGetUint32(prAdapter, "ViCwMax", 15); + prWifiVar->au2CwMax[WMM_AC_VO_INDEX] = (UINT_16) wlanCfgGetUint32(prAdapter, "VoCwMax", 7); + + prWifiVar->au2TxOp[WMM_AC_BE_INDEX] = (UINT_16) wlanCfgGetUint32(prAdapter, "BeTxOp", 0); + prWifiVar->au2TxOp[WMM_AC_BK_INDEX] = (UINT_16) wlanCfgGetUint32(prAdapter, "BkTxOp", 0); + prWifiVar->au2TxOp[WMM_AC_VI_INDEX] = (UINT_16) wlanCfgGetUint32(prAdapter, "ViTxOp", 94); + prWifiVar->au2TxOp[WMM_AC_VO_INDEX] = (UINT_16) wlanCfgGetUint32(prAdapter, "VoTxOp", 47); + + prWifiVar->ucStaHt = (UINT_8) wlanCfgGetUint32(prAdapter, "StaHT", FEATURE_ENABLED); + prWifiVar->ucStaVht = (UINT_8) wlanCfgGetUint32(prAdapter, "StaVHT", FEATURE_ENABLED); + + prWifiVar->ucApHt = (UINT_8) wlanCfgGetUint32(prAdapter, "ApHT", FEATURE_DISABLED); + prWifiVar->ucApVht = (UINT_8) wlanCfgGetUint32(prAdapter, "ApVHT", FEATURE_ENABLED); + + prWifiVar->ucP2pGoHt = (UINT_8) wlanCfgGetUint32(prAdapter, "P2pGoHT", FEATURE_ENABLED); + prWifiVar->ucP2pGoVht = (UINT_8) wlanCfgGetUint32(prAdapter, "P2pGoVHT", FEATURE_ENABLED); + + prWifiVar->ucP2pGcHt = (UINT_8) wlanCfgGetUint32(prAdapter, "P2pGcHT", FEATURE_ENABLED); + prWifiVar->ucP2pGcVht = (UINT_8) wlanCfgGetUint32(prAdapter, "P2pGcVHT", FEATURE_ENABLED); + + prWifiVar->ucAmpduRx = (UINT_8) wlanCfgGetUint32(prAdapter, "AmpduRx", FEATURE_ENABLED); + prWifiVar->ucAmpduTx = (UINT_8) wlanCfgGetUint32(prAdapter, "AmpduTx", FEATURE_ENABLED); + + prWifiVar->ucTspec = (UINT_8) wlanCfgGetUint32(prAdapter, "Tspec", FEATURE_DISABLED); + + prWifiVar->ucUapsd = (UINT_8) wlanCfgGetUint32(prAdapter, "Uapsd", FEATURE_ENABLED); + prWifiVar->ucStaUapsd = (UINT_8) wlanCfgGetUint32(prAdapter, "StaUapsd", FEATURE_DISABLED); + prWifiVar->ucApUapsd = (UINT_8) wlanCfgGetUint32(prAdapter, "ApUapsd", FEATURE_DISABLED); + prWifiVar->ucP2pUapsd = (UINT_8) wlanCfgGetUint32(prAdapter, "P2pUapsd", FEATURE_ENABLED); + + prWifiVar->ucTxShortGI = (UINT_8) wlanCfgGetUint32(prAdapter, "SgiTx", FEATURE_ENABLED); + prWifiVar->ucRxShortGI = (UINT_8) wlanCfgGetUint32(prAdapter, "SgiRx", FEATURE_ENABLED); + + prWifiVar->ucTxLdpc = (UINT_8) wlanCfgGetUint32(prAdapter, "LdpcTx", FEATURE_ENABLED); + prWifiVar->ucRxLdpc = (UINT_8) wlanCfgGetUint32(prAdapter, "LdpcRx", FEATURE_ENABLED); + + prWifiVar->ucTxStbc = (UINT_8) wlanCfgGetUint32(prAdapter, "StbcTx", FEATURE_DISABLED); + prWifiVar->ucRxStbc = (UINT_8) wlanCfgGetUint32(prAdapter, "StbcRx", FEATURE_ENABLED); + + prWifiVar->ucTxGf = (UINT_8) wlanCfgGetUint32(prAdapter, "GfTx", FEATURE_ENABLED); + prWifiVar->ucRxGf = (UINT_8) wlanCfgGetUint32(prAdapter, "GfRx", FEATURE_ENABLED); + + prWifiVar->ucSigTaRts = (UINT_8) wlanCfgGetUint32(prAdapter, "SigTaRts", FEATURE_DISABLED); + prWifiVar->ucDynBwRts = (UINT_8) wlanCfgGetUint32(prAdapter, "DynBwRts", FEATURE_DISABLED); + prWifiVar->ucTxopPsTx = (UINT_8) wlanCfgGetUint32(prAdapter, "TxopPsTx", FEATURE_DISABLED); + + prWifiVar->ucStaHtBfee = (UINT_8) wlanCfgGetUint32(prAdapter, "StaHTBfee", FEATURE_DISABLED); + prWifiVar->ucStaVhtBfee = (UINT_8) wlanCfgGetUint32(prAdapter, "StaVHTBfee", FEATURE_ENABLED); + prWifiVar->ucStaBfer = (UINT_8) wlanCfgGetUint32(prAdapter, "StaBfer", FEATURE_DISABLED); +#ifdef MT6630 + prWifiVar->ucStaVhtMuBfee = (UINT_8) wlanCfgGetUint32(prAdapter, "StaVHTMuBfee", FEATURE_DISABLED); +#else + prWifiVar->ucStaVhtMuBfee = (UINT_8) wlanCfgGetUint32(prAdapter, "StaVHTMuBfee", FEATURE_ENABLED); +#endif + + prWifiVar->ucApWpsMode = (UINT_8) wlanCfgGetUint32(prAdapter, "ApWpsMode", 0); + prWifiVar->ucCert11nMode = (UINT_8)wlanCfgGetUint32(prAdapter, "Cert11nMode", 0); + DBGLOG(INIT, LOUD, "CFG_FILE: ucApWpsMode = %u, ucCert11nMode = %u\n", + prWifiVar->ucApWpsMode, prWifiVar->ucCert11nMode); + + prWifiVar->ucThreadScheduling = (UINT_8) wlanCfgGetUint32(prAdapter, "ThreadSched", 0); + prWifiVar->ucThreadPriority = + (UINT_8) wlanCfgGetUint32(prAdapter, "ThreadPriority", WLAN_TX_THREAD_TASK_PRIORITY); + prWifiVar->cThreadNice = (INT_8) wlanCfgGetInt32(prAdapter, "ThreadNice", WLAN_TX_THREAD_TASK_NICE); + + prAdapter->rQM.u4MaxForwardBuffer = + (UINT_32) wlanCfgGetUint32(prAdapter, "ApForwardBufferCnt", QM_FWD_PKT_QUE_HIGH_THRESHOLD); + prAdapter->rQM.u4MaxForwardBufferForLowUP = + (UINT_32) wlanCfgGetUint32(prAdapter, "ApForwardBufferCntForLowUP", QM_FWD_PKT_QUE_LOW_THRESHOLD); + + /* + * AP channel setting + * 0: auto + */ + prWifiVar->ucApChannel = (UINT_8) wlanCfgGetUint32(prAdapter, "ApChannel", 0); + + /* + * 0: SCN + * 1: SCA + * 2: RES + * 3: SCB + */ + prWifiVar->ucApSco = (UINT_8) wlanCfgGetUint32(prAdapter, "ApSco", 0); + prWifiVar->ucP2pGoSco = (UINT_8) wlanCfgGetUint32(prAdapter, "P2pGoSco", 0); + + /* + * Max bandwidth setting + * 0: 20Mhz + * 1: 40Mhz + * 2: 80Mhz + * 3: 80+80 or 160Mhz + * Note: For VHT STA, BW 80Mhz is a must! + */ + prWifiVar->ucStaBandwidth = (UINT_8) wlanCfgGetUint32(prAdapter, "StaBw", MAX_BW_80MHZ); + prWifiVar->ucSta2gBandwidth = (UINT_8) wlanCfgGetUint32(prAdapter, "Sta2gBw", MAX_BW_20MHZ); + prWifiVar->ucSta5gBandwidth = (UINT_8) wlanCfgGetUint32(prAdapter, "Sta5gBw", MAX_BW_80MHZ); + prWifiVar->ucAp2gBandwidth = (UINT_8) wlanCfgGetUint32(prAdapter, "Ap2gBw", MAX_BW_20MHZ); + prWifiVar->ucAp5gBandwidth = (UINT_8) wlanCfgGetUint32(prAdapter, "Ap5gBw", MAX_BW_40MHZ); + prWifiVar->ucP2p2gBandwidth = (UINT_8) wlanCfgGetUint32(prAdapter, "P2p2gBw", MAX_BW_20MHZ); + prWifiVar->ucP2p5gBandwidth = (UINT_8) wlanCfgGetUint32(prAdapter, "P2p5gBw", MAX_BW_40MHZ); + prWifiVar->u2ApMaxIdlePeriod = (UINT_16) wlanCfgGetUint32(prAdapter, "ApMaxIdlePeriod", FEATURE_DISABLED); + prWifiVar->ucApIdleOption = (UINT_8) wlanCfgGetUint32(prAdapter, "ApIdleOption", 0); + + prWifiVar->ucStaDisconnectDetectTh = (UINT_8) wlanCfgGetUint32(prAdapter, "StaDisconnectDetectTh", 0); + prWifiVar->ucApDisconnectDetectTh = (UINT_8) wlanCfgGetUint32(prAdapter, "ApDisconnectDetectTh", 0); + prWifiVar->ucP2pDisconnectDetectTh = (UINT_8) wlanCfgGetUint32(prAdapter, "P2pDisconnectDetectTh", 0); + + prWifiVar->ucTcRestrict = (UINT_8) wlanCfgGetUint32(prAdapter, "TcRestrict", 0xFF); + /* Max Tx dequeue limit: 0 => auto */ + prWifiVar->u4MaxTxDeQLimit = (UINT_32) wlanCfgGetUint32(prAdapter, "MaxTxDeQLimit", 0x0); + prWifiVar->ucAlwaysResetUsedRes = (UINT_32) wlanCfgGetUint32(prAdapter, "AlwaysResetUsedRes", 0x0); + +#if CFG_SUPPORT_MTK_SYNERGY + prWifiVar->ucMtkOui = (UINT_8) wlanCfgGetUint32(prAdapter, "MtkOui", FEATURE_ENABLED); + prWifiVar->u4MtkOuiCap = (UINT_32) wlanCfgGetUint32(prAdapter, "MtkOuiCap", 0); + prWifiVar->aucMtkFeature[0] = 0xff; + prWifiVar->aucMtkFeature[1] = 0xff; + prWifiVar->aucMtkFeature[2] = 0xff; + prWifiVar->aucMtkFeature[3] = 0xff; +#endif + + prWifiVar->ucCmdRsvResource = (UINT_8) wlanCfgGetUint32(prAdapter, "TxCmdRsv", QM_CMD_RESERVED_THRESHOLD); + prWifiVar->u4MgmtQueueDelayTimeout = + (UINT_32) wlanCfgGetUint32(prAdapter, "TxMgmtQueTO", QM_MGMT_QUEUED_TIMEOUT); /* ms */ + + /* Performance related */ + prWifiVar->u4HifIstLoopCount = (UINT_32) wlanCfgGetUint32(prAdapter, "IstLoop", CFG_IST_LOOP_COUNT); + prWifiVar->u4Rx2OsLoopCount = (UINT_32) wlanCfgGetUint32(prAdapter, "Rx2OsLoop", 4); + prWifiVar->u4HifTxloopCount = (UINT_32) wlanCfgGetUint32(prAdapter, "HifTxLoop", 1); + prWifiVar->u4HifTxDataloopCount = (UINT_32) wlanCfgGetUint32(prAdapter, "HifTxDataLoop", 1); + prWifiVar->u4TxFromOsLoopCount = (UINT_32) wlanCfgGetUint32(prAdapter, "OsTxLoop", 1); + prWifiVar->u4TxRxLoopCount = (UINT_32) wlanCfgGetUint32(prAdapter, "Rx2ReorderLoop", 1); + + prWifiVar->u4NetifStopTh = + (UINT_32) wlanCfgGetUint32(prAdapter, "NetifStopTh", CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD); + prWifiVar->u4NetifStartTh = + (UINT_32) wlanCfgGetUint32(prAdapter, "NetifStartTh", CFG_TX_START_NETIF_PER_QUEUE_THRESHOLD); + prWifiVar->ucTxBaSize = (UINT_8) wlanCfgGetUint32(prAdapter, "TxBaSize", 64); + prWifiVar->ucRxHtBaSize = (UINT_8) wlanCfgGetUint32(prAdapter, "RxHtBaSize", 64); +#ifdef MT6630 + prWifiVar->ucRxVhtBaSize = (UINT_8) wlanCfgGetUint32(prAdapter, "RxVhtBaSize", 32); +#else + prWifiVar->ucRxVhtBaSize = (UINT_8) wlanCfgGetUint32(prAdapter, "RxVhtBaSize", 64); +#endif + /* Tx Buffer Management */ + prWifiVar->ucExtraTxDone = (UINT_32) wlanCfgGetUint32(prAdapter, "ExtraTxDone", 1); + prWifiVar->ucTxDbg = (UINT_32) wlanCfgGetUint32(prAdapter, "TxDbg", 0); + + kalMemZero(prWifiVar->au4TcPageCount, sizeof(prWifiVar->au4TcPageCount)); + + prWifiVar->au4TcPageCount[TC0_INDEX] = (UINT_32) wlanCfgGetUint32(prAdapter, "Tc0Page", NIC_TX_PAGE_COUNT_TC0); + prWifiVar->au4TcPageCount[TC1_INDEX] = (UINT_32) wlanCfgGetUint32(prAdapter, "Tc1Page", NIC_TX_PAGE_COUNT_TC1); + prWifiVar->au4TcPageCount[TC2_INDEX] = (UINT_32) wlanCfgGetUint32(prAdapter, "Tc2Page", NIC_TX_PAGE_COUNT_TC2); + prWifiVar->au4TcPageCount[TC3_INDEX] = (UINT_32) wlanCfgGetUint32(prAdapter, "Tc3Page", NIC_TX_PAGE_COUNT_TC3); + prWifiVar->au4TcPageCount[TC4_INDEX] = (UINT_32) wlanCfgGetUint32(prAdapter, "Tc4Page", NIC_TX_PAGE_COUNT_TC4); + prWifiVar->au4TcPageCount[TC5_INDEX] = (UINT_32) wlanCfgGetUint32(prAdapter, "Tc5Page", NIC_TX_PAGE_COUNT_TC5); + + prQM->au4MinReservedTcResource[TC0_INDEX] = + (UINT_32) wlanCfgGetUint32(prAdapter, "Tc0MinRsv", QM_MIN_RESERVED_TC0_RESOURCE); + prQM->au4MinReservedTcResource[TC1_INDEX] = + (UINT_32) wlanCfgGetUint32(prAdapter, "Tc1MinRsv", QM_MIN_RESERVED_TC1_RESOURCE); + prQM->au4MinReservedTcResource[TC2_INDEX] = + (UINT_32) wlanCfgGetUint32(prAdapter, "Tc2MinRsv", QM_MIN_RESERVED_TC2_RESOURCE); + prQM->au4MinReservedTcResource[TC3_INDEX] = + (UINT_32) wlanCfgGetUint32(prAdapter, "Tc3MinRsv", QM_MIN_RESERVED_TC3_RESOURCE); + prQM->au4MinReservedTcResource[TC4_INDEX] = + (UINT_32) wlanCfgGetUint32(prAdapter, "Tc4MinRsv", QM_MIN_RESERVED_TC4_RESOURCE); + prQM->au4MinReservedTcResource[TC5_INDEX] = + (UINT_32) wlanCfgGetUint32(prAdapter, "Tc5MinRsv", QM_MIN_RESERVED_TC5_RESOURCE); + + prQM->au4GuaranteedTcResource[TC0_INDEX] = + (UINT_32) wlanCfgGetUint32(prAdapter, "Tc0Grt", QM_GUARANTEED_TC0_RESOURCE); + prQM->au4GuaranteedTcResource[TC1_INDEX] = + (UINT_32) wlanCfgGetUint32(prAdapter, "Tc1Grt", QM_GUARANTEED_TC1_RESOURCE); + prQM->au4GuaranteedTcResource[TC2_INDEX] = + (UINT_32) wlanCfgGetUint32(prAdapter, "Tc2Grt", QM_GUARANTEED_TC2_RESOURCE); + prQM->au4GuaranteedTcResource[TC3_INDEX] = + (UINT_32) wlanCfgGetUint32(prAdapter, "Tc3Grt", QM_GUARANTEED_TC3_RESOURCE); + prQM->au4GuaranteedTcResource[TC4_INDEX] = + (UINT_32) wlanCfgGetUint32(prAdapter, "Tc4Grt", QM_GUARANTEED_TC4_RESOURCE); + prQM->au4GuaranteedTcResource[TC5_INDEX] = + (UINT_32) wlanCfgGetUint32(prAdapter, "Tc5Grt", QM_GUARANTEED_TC5_RESOURCE); + + prQM->u4TimeToAdjustTcResource = + (UINT_32) wlanCfgGetUint32(prAdapter, "TcAdjustTime", QM_INIT_TIME_TO_ADJUST_TC_RSC); + prQM->u4TimeToUpdateQueLen = + (UINT_32) wlanCfgGetUint32(prAdapter, "QueLenUpdateTime", QM_INIT_TIME_TO_UPDATE_QUE_LEN); + prQM->u4QueLenMovingAverage = + (UINT_32) wlanCfgGetUint32(prAdapter, "QueLenMovingAvg", QM_QUE_LEN_MOVING_AVE_FACTOR); + prQM->u4ExtraReservedTcResource = + (UINT_32) wlanCfgGetUint32(prAdapter, "TcExtraRsv", QM_EXTRA_RESERVED_RESOURCE_WHEN_BUSY); + + /* Stats log */ + prWifiVar->u4StatsLogTimeout = (UINT_32) wlanCfgGetUint32(prAdapter, "StatsLogTO", WLAN_TX_STATS_LOG_TIMEOUT); + prWifiVar->u4StatsLogDuration = + (UINT_32) wlanCfgGetUint32(prAdapter, "StatsLogDur", WLAN_TX_STATS_LOG_DURATION); + + prWifiVar->ucDhcpTxDone = (UINT_8) wlanCfgGetUint32(prAdapter, "DhcpTxDone", 1); + prWifiVar->ucArpTxDone = (UINT_8) wlanCfgGetUint32(prAdapter, "ArpTxDone", 1); + prWifiVar->ucIcmpTxDone = (UINT_8) wlanCfgGetUint32(prAdapter, "IcmpTxDone", 1); + prWifiVar->ePowerMode = (PARAM_POWER_MODE) wlanCfgGetUint32(prAdapter, "PowerSave", Param_PowerModeMax); + prWifiVar->rScanInfo.rScanParam.u2DefaultDwellTime = + (UINT_16)wlanCfgGetUint32(prAdapter, "DefaultDwellTime", 0); +#ifdef CFG_SUPPORT_DATA_STALL + prWifiVar->u4PerHighThreshold = (uint32_t) wlanCfgGetUint32( + prAdapter, "PerHighThreshold", + EVENT_PER_HIGH_THRESHOLD); + prWifiVar->u4TxLowRateThreshold = (uint32_t) wlanCfgGetUint32( + prAdapter, "TxLowRateThreshold", + EVENT_TX_LOW_RATE_THRESHOLD); + prWifiVar->u4RxLowRateThreshold = (uint32_t) wlanCfgGetUint32( + prAdapter, "RxLowRateThreshold", + EVENT_RX_LOW_RATE_THRESHOLD); + prWifiVar->u4ReportEventInterval = (uint32_t) wlanCfgGetUint32( + prAdapter, "ReportEventInterval", + REPORT_EVENT_INTERVAL); + prWifiVar->u4TrafficThreshold = (uint32_t) wlanCfgGetUint32( + prAdapter, "TrafficThreshold", + TRAFFIC_RHRESHOLD); +#endif + +#ifdef CFG_SUPPORT_COEX_IOT_AP + prWifiVar->ucEnCoexIotAP = (UINT_8) wlanCfgGetUint32(prAdapter, "EnCoexIotAP", 1); +#endif + +} + +VOID wlanCfgSetSwCtrl(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i = 0; + CHAR aucKey[WLAN_CFG_VALUE_LEN_MAX]; + CHAR aucValue[WLAN_CFG_VALUE_LEN_MAX]; + CHAR *pcPtr = NULL; + CHAR *pcDupValue = NULL; + UINT_32 au4Values[2] = {0}; + UINT_32 u4TokenCount = 0; + UINT_32 u4BufLen = 0; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo; + INT_32 u4Ret = 0; + const CHAR acDelim[] = " "; + + for (i = 0; i < WLAN_CFG_SET_SW_CTRL_LEN_MAX; i++) { + kalMemZero(aucValue, WLAN_CFG_VALUE_LEN_MAX); + kalMemZero(aucKey, WLAN_CFG_VALUE_LEN_MAX); + if (0 > kalSprintf(aucKey, "SwCtrl%d", i)) + continue; + + /* get nothing */ + if (wlanCfgGet(prAdapter, aucKey, aucValue, "", 0) != WLAN_STATUS_SUCCESS) + continue; + if (!kalStrCmp(aucValue, "")) + continue; + + pcDupValue = aucValue; + u4TokenCount = 0; + + while ((pcPtr = kalStrSep((char **)(&pcDupValue), acDelim)) != NULL) { + + if (!kalStrCmp(pcPtr, "")) + continue; + + /* au4Values[u4TokenCount] = kalStrtoul(pcPtr, NULL, 0); */ + u4Ret = kalkStrtou32(pcPtr, 0, &(au4Values[u4TokenCount])); + if (u4Ret) + DBGLOG(INIT, LOUD, "parse au4Values error u4Ret=%d\n", u4Ret); + u4TokenCount++; + + /* Only need 2 tokens */ + if (u4TokenCount >= 2) + break; + } + + if (u4TokenCount != 2) + continue; + + rSwCtrlInfo.u4Id = au4Values[0]; + rSwCtrlInfo.u4Data = au4Values[1]; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), FALSE, FALSE, TRUE, &u4BufLen); + + } +} + +VOID wlanCfgSetChip(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i = 0; + CHAR aucKey[WLAN_CFG_VALUE_LEN_MAX]; + CHAR aucValue[WLAN_CFG_VALUE_LEN_MAX]; + + UINT_32 u4BufLen = 0; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T rChipConfigInfo; + + for (i = 0; i < WLAN_CFG_SET_CHIP_LEN_MAX; i++) { + kalMemZero(aucValue, WLAN_CFG_VALUE_LEN_MAX); + kalMemZero(aucKey, WLAN_CFG_VALUE_LEN_MAX); + if (0 > kalSprintf(aucKey, "SetChip%d", i)) + continue; + + /* get nothing */ + if (wlanCfgGet(prAdapter, aucKey, aucValue, "", 0) != WLAN_STATUS_SUCCESS) + continue; + if (!kalStrCmp(aucValue, "")) + continue; + + kalMemZero(&rChipConfigInfo, sizeof(rChipConfigInfo)); + + rChipConfigInfo.ucType = CHIP_CONFIG_TYPE_WO_RESPONSE; + rChipConfigInfo.u2MsgSize = kalStrnLen(aucValue, WLAN_CFG_VALUE_LEN_MAX); + kalStrnCpy(rChipConfigInfo.aucCmd, aucValue, CHIP_CONFIG_RESP_SIZE); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetChipConfig, + &rChipConfigInfo, sizeof(rChipConfigInfo), FALSE, FALSE, TRUE, &u4BufLen); + } + +} + +VOID wlanGetFwInfo(IN P_ADAPTER_T prAdapter) +{ + CMD_GET_FW_INFO_T rCmdGetFwInfo; + + rCmdGetFwInfo.ucValue = 0x1; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_FW_INFO, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_GET_FW_INFO_T), + (PUINT_8)&rCmdGetFwInfo, NULL, 0); +} + +VOID wlanCfgSetDebugLevel(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i = 0; + CHAR aucKey[WLAN_CFG_VALUE_LEN_MAX]; + CHAR aucValue[WLAN_CFG_VALUE_LEN_MAX]; + const CHAR acDelim[] = " "; + CHAR *pcDupValue; + CHAR *pcPtr = NULL; + + UINT_32 au4Values[2] = {0}; + UINT_32 u4TokenCount = 0; + UINT_32 u4DbgIdx = 0; + UINT_32 u4DbgMask = 0; + INT_32 u4Ret = 0; + + for (i = 0; i < WLAN_CFG_SET_DEBUG_LEVEL_LEN_MAX; i++) { + kalMemZero(aucValue, WLAN_CFG_VALUE_LEN_MAX); + kalMemZero(aucKey, WLAN_CFG_VALUE_LEN_MAX); + if (0 > kalSprintf(aucKey, "DbgLevel%d", i)) + continue; + + /* get nothing */ + if (wlanCfgGet(prAdapter, aucKey, aucValue, "", 0) != WLAN_STATUS_SUCCESS) + continue; + if (!kalStrCmp(aucValue, "")) + continue; + + pcDupValue = aucValue; + u4TokenCount = 0; + + while ((pcPtr = kalStrSep((char **)(&pcDupValue), acDelim)) != NULL) { + + if (!kalStrCmp(pcPtr, "")) + continue; + + /* au4Values[u4TokenCount] = kalStrtoul(pcPtr, NULL, 0); */ + u4Ret = kalkStrtou32(pcPtr, 0, &(au4Values[u4TokenCount])); + if (u4Ret) + DBGLOG(INIT, LOUD, "parse au4Values error u4Ret=%d\n", u4Ret); + u4TokenCount++; + + /* Only need 2 tokens */ + if (u4TokenCount >= 2) + break; + } + + if (u4TokenCount != 2) + continue; + + u4DbgIdx = au4Values[0]; + u4DbgMask = au4Values[1]; + + /* DBG level special control */ + if (u4DbgIdx == 0xFFFFFFFF) { + wlanSetDebugLevel(DBG_ALL_MODULE_IDX, u4DbgMask); + DBGLOG(INIT, INFO, "Set ALL DBG module log level to [0x%02x]!", (UINT_8) u4DbgMask); + } else if (u4DbgIdx == 0xFFFFFFFE) { + wlanDebugInit(); + DBGLOG(INIT, INFO, "Reset ALL DBG module log level to DEFAULT!"); + } else if (u4DbgIdx < DBG_MODULE_NUM) { + wlanSetDebugLevel(u4DbgIdx, u4DbgMask); + DBGLOG(INIT, INFO, + "Set DBG module[%u] log level to [0x%x]!", u4DbgIdx, u4DbgMask); + } + } + +} + +VOID wlanCfgSetCountryCode(IN P_ADAPTER_T prAdapter) +{ + CHAR aucValue[WLAN_CFG_VALUE_LEN_MAX]; + + /* Apply COUNTRY Config */ + if (wlanCfgGet(prAdapter, "Country", aucValue, "", 0) == WLAN_STATUS_SUCCESS) { + prAdapter->rWifiVar.rConnSettings.u2CountryCode = + (((UINT_16) aucValue[0]) << 8) | ((UINT_16) aucValue[1]); + + /* Force to re-search country code in regulatory domains */ + prAdapter->prDomainInfo = NULL; + rlmDomainSendCmd(prAdapter); + + /* Update supported channel list in channel table based on current country domain */ + wlanUpdateChannelTable(prAdapter->prGlueInfo); + } +} + +#if CFG_SUPPORT_CFG_FILE + +P_WLAN_CFG_ENTRY_T wlanCfgGetEntry(IN P_ADAPTER_T prAdapter, const PCHAR pucKey) +{ + + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + P_WLAN_CFG_T prWlanCfg; + UINT_32 i; + + prWlanCfg = prAdapter->prWlanCfg; + + ASSERT(prWlanCfg); + ASSERT(pucKey); + + prWlanCfgEntry = NULL; + + for (i = 0; i < WLAN_CFG_ENTRY_NUM_MAX; i++) { + prWlanCfgEntry = &prWlanCfg->arWlanCfgBuf[i]; + if (prWlanCfgEntry->aucKey[0] != '\0') { + if (kalStrnCmp(pucKey, prWlanCfgEntry->aucKey, WLAN_CFG_KEY_LEN_MAX - 1) == 0) { + DBGLOG(INIT, TRACE, "wifi config find key \'%s\'\n", pucKey); + return prWlanCfgEntry; + } + } + } + + DBGLOG(INIT, LOUD, "wifi config there is no entry \'%s\'\n", pucKey); + return NULL; + +} + +WLAN_STATUS wlanCfgGet(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, PCHAR pucValue, PCHAR pucValueDef, UINT_32 u4Flags) +{ + + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + P_WLAN_CFG_T prWlanCfg; + + prWlanCfg = prAdapter->prWlanCfg; + + ASSERT(prWlanCfg); + ASSERT(pucValue); + + /* Find the exist */ + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey); + + if (prWlanCfgEntry) { + kalStrnCpy(pucValue, prWlanCfgEntry->aucValue, WLAN_CFG_VALUE_LEN_MAX - 1); + } else { + if (pucValueDef) + kalStrnCpy(pucValue, pucValueDef, WLAN_CFG_VALUE_LEN_MAX - 1); + return WLAN_STATUS_FAILURE; + } + + return WLAN_STATUS_SUCCESS; +} + +UINT_32 wlanCfgGetUint32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, UINT_32 u4ValueDef) +{ + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + P_WLAN_CFG_T prWlanCfg; + UINT_32 u4Value; + INT_32 u4Ret; + + prWlanCfg = prAdapter->prWlanCfg; + + + ASSERT(prWlanCfg); + + u4Value = u4ValueDef; + /* Find the exist */ + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey); + + if (prWlanCfgEntry) { + /* u4Ret = kalStrtoul(prWlanCfgEntry->aucValue, NULL, 0); */ + u4Ret = kalkStrtou32(prWlanCfgEntry->aucValue, 0, &u4Value); + if (u4Ret) + DBGLOG(INIT, LOUD, "parse aucValue error u4Ret=%d\n", u4Ret); + } + + return u4Value; + +} + +INT_32 wlanCfgGetInt32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, INT_32 i4ValueDef) +{ + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + P_WLAN_CFG_T prWlanCfg; + INT_32 i4Value = 0; + INT_32 i4Ret = 0; + + prWlanCfg = prAdapter->prWlanCfg; + + ASSERT(prWlanCfg); + + i4Value = i4ValueDef; + /* Find the exist */ + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey); + + if (prWlanCfgEntry) { + /* i4Ret = kalStrtol(prWlanCfgEntry->aucValue, NULL, 0); */ + i4Ret = kalkStrtos32(prWlanCfgEntry->aucValue, 0, &i4Value); + if (i4Ret) + DBGLOG(INIT, LOUD, "parse aucValue error i4Ret=%d\n", i4Ret); + } + + return i4Value; + +} + +WLAN_STATUS wlanCfgSet(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, PCHAR pucValue, UINT_32 u4Flags) +{ + + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + P_WLAN_CFG_T prWlanCfg; + UINT_32 u4EntryIndex; + UINT_32 i; + UINT_8 ucExist; + + prWlanCfg = prAdapter->prWlanCfg; + ASSERT(prWlanCfg); + ASSERT(pucKey); + + /* Find the exist */ + ucExist = 0; + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey); + + if (!prWlanCfgEntry) { + /* Find the empty */ + for (i = 0; i < WLAN_CFG_ENTRY_NUM_MAX; i++) { + prWlanCfgEntry = &prWlanCfg->arWlanCfgBuf[i]; + if (prWlanCfgEntry->aucKey[0] == '\0') + break; + } + + u4EntryIndex = i; + if (u4EntryIndex < WLAN_CFG_ENTRY_NUM_MAX) { + prWlanCfgEntry = &prWlanCfg->arWlanCfgBuf[u4EntryIndex]; + kalMemZero(prWlanCfgEntry, sizeof(WLAN_CFG_ENTRY_T)); + } else { + prWlanCfgEntry = NULL; + DBGLOG(INIT, ERROR, "wifi config there is no empty entry\n"); + } + } /* !prWlanCfgEntry */ + else + ucExist = 1; + + if (prWlanCfgEntry) { + if (ucExist == 0) { + kalStrnCpy(prWlanCfgEntry->aucKey, pucKey, WLAN_CFG_KEY_LEN_MAX - 1); + prWlanCfgEntry->aucKey[WLAN_CFG_KEY_LEN_MAX - 1] = '\0'; + } + + if (pucValue && pucValue[0] != '\0') { + kalStrnCpy(prWlanCfgEntry->aucValue, pucValue, WLAN_CFG_VALUE_LEN_MAX - 1); + prWlanCfgEntry->aucValue[WLAN_CFG_VALUE_LEN_MAX - 1] = '\0'; + + if (ucExist) { + if (prWlanCfgEntry->pfSetCb) + prWlanCfgEntry->pfSetCb(prAdapter, + prWlanCfgEntry->aucKey, + prWlanCfgEntry->aucValue, prWlanCfgEntry->pPrivate, 0); + } + } else { + /* Call the pfSetCb if value is empty ? */ + /* remove the entry if value is empty */ + kalMemZero(prWlanCfgEntry, sizeof(WLAN_CFG_ENTRY_T)); + } + + } + /* prWlanCfgEntry */ + if (prWlanCfgEntry) { + DBGLOG(INIT, INFO, "Set wifi config exist %u \'%s\' \'%s\'\n", + ucExist, prWlanCfgEntry->aucKey, prWlanCfgEntry->aucValue); + } else { + if (pucKey) { + DBGLOG(INIT, ERROR, + "Set wifi config error key \'%s\'\n", pucKey); + } + if (pucValue) { + DBGLOG(INIT, ERROR, + "Set wifi config error value \'%s\'\n", pucValue); + } + return WLAN_STATUS_FAILURE; + } + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanCfgSetCb(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, WLAN_CFG_SET_CB pfSetCb, void *pPrivate, UINT_32 u4Flags) +{ + + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + P_WLAN_CFG_T prWlanCfg; + + prWlanCfg = prAdapter->prWlanCfg; + ASSERT(prWlanCfg); + + /* Find the exist */ + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey); + + if (prWlanCfgEntry) { + prWlanCfgEntry->pfSetCb = pfSetCb; + prWlanCfgEntry->pPrivate = pPrivate; + } + + if (prWlanCfgEntry) + return WLAN_STATUS_SUCCESS; + else + return WLAN_STATUS_FAILURE; + +} + +WLAN_STATUS wlanCfgSetUint32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, UINT_32 u4Value) +{ + + P_WLAN_CFG_T prWlanCfg; + INT_32 ret = 0; + UINT_8 aucBuf[WLAN_CFG_VALUE_LEN_MAX]; + + prWlanCfg = prAdapter->prWlanCfg; + + ASSERT(prWlanCfg); + + kalMemZero(aucBuf, sizeof(aucBuf)); + + ret = kalSnprintf(aucBuf, WLAN_CFG_VALUE_LEN_MAX, "0x%x", (unsigned int)u4Value); + if (ret < 0) + return WLAN_STATUS_FAILURE; + + return wlanCfgSet(prAdapter, pucKey, aucBuf, 0); +} + +enum { + STATE_EOF = 0, + STATE_TEXT = 1, + STATE_NEWLINE = 2 +}; + +struct WLAN_CFG_PARSE_STATE_S { + CHAR *ptr; + CHAR *text; + INT_32 nexttoken; + UINT_32 maxSize; +}; + +INT_32 wlanCfgFindNextToken(struct WLAN_CFG_PARSE_STATE_S *state) +{ + CHAR *x = state->ptr; + CHAR *s; + + if (state->nexttoken) { + INT_32 t = state->nexttoken; + + state->nexttoken = 0; + return t; + } + + for (;;) { + switch (*x) { + case 0: + state->ptr = x; + return STATE_EOF; + case '\n': + x++; + state->ptr = x; + return STATE_NEWLINE; + case ' ': + case '\t': + case '\r': + x++; + continue; + case '#': + while (*x && (*x != '\n')) + x++; + if (*x == '\n') { + state->ptr = x + 1; + } else { + state->ptr = x; + return STATE_EOF; + } + return STATE_NEWLINE; + default: + goto text; + } + } + +textdone: + state->ptr = x; + *s = 0; + return STATE_TEXT; +text: + state->text = s = x; +textresume: + for (;;) { + switch (*x) { + case 0: + goto textdone; + case ' ': + case '\t': + case '\r': + x++; + goto textdone; + case '\n': + state->nexttoken = STATE_NEWLINE; + x++; + goto textdone; + case '"': + x++; + for (;;) { + switch (*x) { + case 0: + /* unterminated quoted thing */ + state->ptr = x; + return STATE_EOF; + case '"': + x++; + goto textresume; + default: + *s++ = *x++; + } + } + break; + case '\\': + x++; + switch (*x) { + case 0: + goto textdone; + case 'n': + *s++ = '\n'; + break; + case 'r': + *s++ = '\r'; + break; + case 't': + *s++ = '\t'; + break; + case '\\': + *s++ = '\\'; + break; + case '\r': + /* \ -> line continuation */ + if (x[1] != '\n') { + x++; + continue; + } + case '\n': + /* \ -> line continuation */ + x++; + /* eat any extra whitespace */ + while ((*x == ' ') || (*x == '\t')) + x++; + continue; + default: + /* unknown escape -- just copy */ + *s++ = *x++; + } + continue; + default: + *s++ = *x++; + } + } + return STATE_EOF; +} + +WLAN_STATUS wlanCfgParseArgument(CHAR *cmdLine, INT_32 *argc, CHAR *argv[]) +{ + struct WLAN_CFG_PARSE_STATE_S state; + CHAR **args; + INT_32 nargs; + + if (cmdLine == NULL || argc == NULL || argv == NULL) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + args = argv; + nargs = 0; + state.ptr = cmdLine; + state.nexttoken = 0; + state.maxSize = 0; + + if (kalStrnLen(cmdLine, 512) >= 512) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + for (;;) { + switch (wlanCfgFindNextToken(&state)) { + case STATE_EOF: + goto exit; + case STATE_NEWLINE: + goto exit; + case STATE_TEXT: + if (nargs < WLAN_CFG_ARGV_MAX) + args[nargs++] = state.text; + break; + } + } + +exit: + *argc = nargs; + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanCfgParseAddEntry(IN P_ADAPTER_T prAdapter, + PUINT_8 pucKeyHead, PUINT_8 pucKeyTail, PUINT_8 pucValueHead, PUINT_8 pucValueTail) +{ + + UINT_8 aucKey[WLAN_CFG_KEY_LEN_MAX]; + UINT_8 aucValue[WLAN_CFG_VALUE_LEN_MAX]; + UINT_32 u4Len; + + kalMemZero(aucKey, sizeof(aucKey)); + kalMemZero(aucValue, sizeof(aucValue)); + + if ((pucKeyHead == NULL) + || (pucValueHead == NULL) + ) + return WLAN_STATUS_FAILURE; + + if (pucKeyTail) { + if (pucKeyHead > pucKeyTail) + return WLAN_STATUS_FAILURE; + u4Len = pucKeyTail - pucKeyHead + 1; + } else + u4Len = kalStrnLen(pucKeyHead, WLAN_CFG_KEY_LEN_MAX - 1); + + if (u4Len >= WLAN_CFG_KEY_LEN_MAX) + u4Len = WLAN_CFG_KEY_LEN_MAX - 1; + + kalStrnCpy(aucKey, pucKeyHead, u4Len); + + if (pucValueTail) { + if (pucValueHead > pucValueTail) + return WLAN_STATUS_FAILURE; + u4Len = pucValueTail - pucValueHead + 1; + } else + u4Len = kalStrnLen(pucValueHead, WLAN_CFG_VALUE_LEN_MAX - 1); + + if (u4Len >= WLAN_CFG_VALUE_LEN_MAX) + u4Len = WLAN_CFG_VALUE_LEN_MAX - 1; + + kalStrnCpy(aucValue, pucValueHead, u4Len); + + return wlanCfgSet(prAdapter, aucKey, aucValue, 0); +} + +enum { + WAIT_KEY_HEAD = 0, + WAIT_KEY_TAIL, + WAIT_VALUE_HEAD, + WAIT_VALUE_TAIL, + WAIT_COMMENT_TAIL +}; + +WLAN_STATUS wlanCfgParse(IN P_ADAPTER_T prAdapter, PUINT_8 pucConfigBuf, UINT_32 u4ConfigBufLen) +{ + + struct WLAN_CFG_PARSE_STATE_S state; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + CHAR **args; + INT_32 nargs; + + if (pucConfigBuf == NULL) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + if (kalStrnLen(pucConfigBuf, 4000) >= 4000) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + if (u4ConfigBufLen == 0) + return WLAN_STATUS_FAILURE; + args = apcArgv; + nargs = 0; + state.ptr = pucConfigBuf; + state.nexttoken = 0; + state.maxSize = u4ConfigBufLen; + + for (;;) { + switch (wlanCfgFindNextToken(&state)) { + case STATE_EOF: + if (nargs > 1) + wlanCfgParseAddEntry(prAdapter, args[0], NULL, args[1], NULL); + goto exit; + case STATE_NEWLINE: + if (nargs > 1) + wlanCfgParseAddEntry(prAdapter, args[0], NULL, args[1], NULL); + nargs = 0; + break; + case STATE_TEXT: + if (nargs < WLAN_CFG_ARGV_MAX) + args[nargs++] = state.text; + break; + } + } + +exit: + return WLAN_STATUS_SUCCESS; + +#if 0 + /* Old version */ + UINT_32 i; + UINT_8 c; + PUINT_8 pbuf; + UINT_8 ucState; + PUINT_8 pucKeyTail = NULL; + PUINT_8 pucKeyHead = NULL; + PUINT_8 pucValueHead = NULL; + PUINT_8 pucValueTail = NULL; + + ucState = WAIT_KEY_HEAD; + pbuf = pucConfigBuf; + + for (i = 0; i < u4ConfigBufLen; i++) { + c = pbuf[i]; + if (c == '\r' || c == '\n') { + + if (ucState == WAIT_VALUE_TAIL) { + /* Entry found */ + if (pucValueHead) + wlanCfgParseAddEntry(prAdapter, pucKeyHead, pucKeyTail, + pucValueHead, pucValueTail); + } + ucState = WAIT_KEY_HEAD; + pucKeyTail = NULL; + pucKeyHead = NULL; + pucValueHead = NULL; + pucValueTail = NULL; + + } else if (c == '=') { + if (ucState == WAIT_KEY_TAIL) { + pucKeyTail = &pbuf[i - 1]; + ucState = WAIT_VALUE_HEAD; + } + } else if (c == ' ' || c == '\t') { + if (ucState == WAIT_KEY_TAIL) { + pucKeyTail = &pbuf[i - 1]; + ucState = WAIT_VALUE_HEAD; + } + } else { + + if (c == '#') { + /* comments */ + if (ucState == WAIT_KEY_HEAD) + ucState = WAIT_COMMENT_TAIL; + else if (ucState == WAIT_VALUE_TAIL) + pucValueTail = &pbuf[i]; + + } else { + if (ucState == WAIT_KEY_HEAD) { + pucKeyHead = &pbuf[i]; + pucKeyTail = &pbuf[i]; + ucState = WAIT_KEY_TAIL; + } else if (ucState == WAIT_VALUE_HEAD) { + pucValueHead = &pbuf[i]; + pucValueTail = &pbuf[i]; + ucState = WAIT_VALUE_TAIL; + } else if (ucState == WAIT_VALUE_TAIL) + pucValueTail = &pbuf[i]; + } + } + + } /* for */ + + if (ucState == WAIT_VALUE_TAIL) { + /* Entry found */ + if (pucValueTail) + wlanCfgParseAddEntry(prAdapter, pucKeyHead, pucKeyTail, pucValueHead, pucValueTail); + } +#endif + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS wlanCfgInit(IN P_ADAPTER_T prAdapter, PUINT_8 pucConfigBuf, UINT_32 u4ConfigBufLen, UINT_32 u4Flags) +{ + P_WLAN_CFG_T prWlanCfg; + /* P_WLAN_CFG_ENTRY_T prWlanCfgEntry; */ + prAdapter->prWlanCfg = &prAdapter->rWlanCfg; + prWlanCfg = prAdapter->prWlanCfg; + + kalMemZero(prWlanCfg, sizeof(WLAN_CFG_T)); + ASSERT(prWlanCfg); + prWlanCfg->u4WlanCfgEntryNumMax = WLAN_CFG_ENTRY_NUM_MAX; + prWlanCfg->u4WlanCfgKeyLenMax = WLAN_CFG_KEY_LEN_MAX; + prWlanCfg->u4WlanCfgValueLenMax = WLAN_CFG_VALUE_LEN_MAX; + + DBGLOG(INIT, LOUD, "Init wifi config len %u max entry %u\n", u4ConfigBufLen, prWlanCfg->u4WlanCfgEntryNumMax); +#if DBG + /* self test */ + wlanCfgSet(prAdapter, "ConfigValid", "0x123", 0); + if (wlanCfgGetUint32(prAdapter, "ConfigValid", 0) != 0x123) + DBGLOG(INIT, ERROR, "wifi config error %u\n", __LINE__); + + wlanCfgSet(prAdapter, "ConfigValid", "1", 0); + if (wlanCfgGetUint32(prAdapter, "ConfigValid", 0) != 1) + DBGLOG(INIT, ERROR, "wifi config error %u\n", __LINE__); + +#endif + + /* Parse the pucConfigBuf */ + if (pucConfigBuf && (u4ConfigBufLen > 0)) + wlanCfgParse(prAdapter, pucConfigBuf, u4ConfigBufLen); + + return WLAN_STATUS_SUCCESS; +} + +#endif /* CFG_SUPPORT_CFG_FILE */ + +INT_32 wlanHexToNum(CHAR c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; +} + +INT_32 wlanHexToByte(PCHAR hex) +{ + INT_32 a, b; + + a = wlanHexToNum(*hex++); + if (a < 0) + return -1; + b = wlanHexToNum(*hex++); + if (b < 0) + return -1; + return (a << 4) | b; +} + +INT_32 wlanHwAddrToBin(PCHAR txt, UINT_8 *addr) +{ + INT_32 i; + PCHAR pos = txt; + + for (i = 0; i < 6; i++) { + INT_32 a, b; + + while (*pos == ':' || *pos == '.' || *pos == '-') + pos++; + + a = wlanHexToNum(*pos++); + if (a < 0) + return -1; + b = wlanHexToNum(*pos++); + if (b < 0) + return -1; + *addr++ = (a << 4) | b; + } + + return pos - txt; +} + +BOOLEAN wlanIsChipNoAck(IN P_ADAPTER_T prAdapter) +{ + BOOLEAN fgIsNoAck; + + fgIsNoAck = prAdapter->fgIsChipNoAck || kalIsResetting() + || fgIsBusAccessFailed; + + return fgIsNoAck; +} + +#if CFG_ENABLE_PER_STA_STATISTICS +VOID wlanTxLifetimeUpdateStaStats(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_STA_RECORD_T prStaRec; + UINT_32 u4DeltaTime; + UINT_32 u4DeltaHifTxTime; + P_PKT_PROFILE_T prPktProfile = &prMsduInfo->rPktProfile; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (prStaRec) { + u4DeltaTime = (UINT_32) (prPktProfile->rHifTxDoneTimestamp - prPktProfile->rHardXmitArrivalTimestamp); + u4DeltaHifTxTime = (UINT_32) (prPktProfile->rHifTxDoneTimestamp - prPktProfile->rDequeueTimestamp); + + + /* Update StaRec statistics */ + prStaRec->u4TotalTxPktsNumber++; + prStaRec->u4TotalTxPktsTime += u4DeltaTime; + prStaRec->u4TotalTxPktsHifTxTime += u4DeltaHifTxTime; + + if (u4DeltaTime > prStaRec->u4MaxTxPktsTime) + prStaRec->u4MaxTxPktsTime = u4DeltaTime; + + if (u4DeltaHifTxTime > prStaRec->u4MaxTxPktsHifTime) + prStaRec->u4MaxTxPktsHifTime = u4DeltaHifTxTime; + + + if (u4DeltaTime >= NIC_TX_TIME_THRESHOLD) + prStaRec->u4ThresholdCounter++; +#if 0 /* Currently these code are useless */ + if (u4PktPrintPeriod && (prStaRec->u4TotalTxPktsNumber >= u4PktPrintPeriod)) { + DBGLOG(TX, TRACE, "[%u]N[%4lu]A[%5lu]M[%4lu]T[%4lu]E[%4lu]\n", + prStaRec->ucIndex, + prStaRec->u4TotalTxPktsNumber, + (prStaRec->u4TotalTxPktsTime / prStaRec->u4TotalTxPktsNumber), + prStaRec->u4MaxTxPktsTime, + prStaRec->u4ThresholdCounter, + prQM->au4QmTcResourceEmptyCounter[prStaRec->ucBssIndex][TC2_INDEX]); + + prStaRec->u4TotalTxPktsNumber = 0; + prStaRec->u4TotalTxPktsTime = 0; + prStaRec->u4MaxTxPktsTime = 0; + prStaRec->u4ThresholdCounter = 0; + prQM->au4QmTcResourceEmptyCounter[prStaRec->ucBssIndex][TC2_INDEX] = 0; + } +#endif + } +} +#endif + +BOOLEAN wlanTxLifetimeIsProfilingEnabled(IN P_ADAPTER_T prAdapter) +{ + BOOLEAN fgEnabled = FALSE; +#if CFG_SUPPORT_WFD + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + + prWfdCfgSettings = &prAdapter->rWifiVar.rWfdConfigureSettings; + + if (prWfdCfgSettings->ucWfdEnable > 0) + fgEnabled = TRUE; +#endif + + return fgEnabled; +} + +BOOLEAN wlanTxLifetimeIsTargetMsdu(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + BOOLEAN fgResult = TRUE; + +#if 0 + switch (prMsduInfo->ucTID) { + /* BK */ + case 1: + case 2: + + /* BE */ + case 0: + case 3: + fgResult = FALSE; + break; + /* VI */ + case 4: + case 5: + + /* VO */ + case 6: + case 7: + fgResult = TRUE; + break; + default: + break; + } +#endif + return fgResult; +} + +VOID wlanTxLifetimeTagPacket(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_PROFILING_TAG_T eTag) +{ + P_PKT_PROFILE_T prPktProfile = &prMsduInfo->rPktProfile; + + if (!wlanTxLifetimeIsProfilingEnabled(prAdapter)) + return; + + switch (eTag) { + case TX_PROF_TAG_OS_TO_DRV: + /* arrival time is tagged in wlanProcessTxFrame */ + break; + + case TX_PROF_TAG_DRV_ENQUE: + /* Reset packet profile */ + prPktProfile->fgIsValid = FALSE; + if (wlanTxLifetimeIsTargetMsdu(prAdapter, prMsduInfo)) { + /* Enable packet lifetime profiling */ + prPktProfile->fgIsValid = TRUE; + + /* Packet arrival time at kernel Hard Xmit */ + prPktProfile->rHardXmitArrivalTimestamp = GLUE_GET_PKT_ARRIVAL_TIME(prMsduInfo->prPacket); + + /* Packet enqueue time */ + prPktProfile->rEnqueueTimestamp = (OS_SYSTIME) kalGetTimeTick(); + } + break; + + case TX_PROF_TAG_DRV_DEQUE: + if (prPktProfile->fgIsValid) + prPktProfile->rDequeueTimestamp = (OS_SYSTIME) kalGetTimeTick(); + break; + + case TX_PROF_TAG_DRV_TX_DONE: + if (prPktProfile->fgIsValid) { + prPktProfile->rHifTxDoneTimestamp = (OS_SYSTIME) kalGetTimeTick(); +#if CFG_ENABLE_PER_STA_STATISTICS + wlanTxLifetimeUpdateStaStats(prAdapter, prMsduInfo); +#endif + } + break; + + case TX_PROF_TAG_MAC_TX_DONE: + break; + + default: + break; + } +} + +VOID wlanTxLifetimeTagPacketQue(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead, + IN ENUM_TX_PROFILING_TAG_T eTag) +{ + P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead, prNextMsduInfo; + P_PKT_PROFILE_T prPktProfile = NULL; + + if (!wlanTxLifetimeIsProfilingEnabled(prAdapter)) + return; + + while (prMsduInfo) { + prPktProfile = &prMsduInfo->rPktProfile; + prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); + + switch (eTag) { + case TX_PROF_TAG_OS_TO_DRV: + /* arrival time is tagged in wlanProcessTxFrame */ + break; + + case TX_PROF_TAG_DRV_ENQUE: + /* Reset packet profile */ + prPktProfile->fgIsValid = FALSE; + if (wlanTxLifetimeIsTargetMsdu(prAdapter, prMsduInfo)) { + /* Enable packet lifetime profiling */ + prPktProfile->fgIsValid = TRUE; + + /* Packet arrival time at kernel Hard Xmit */ + prPktProfile->rHardXmitArrivalTimestamp = + GLUE_GET_PKT_ARRIVAL_TIME(prMsduInfo->prPacket); + + /* Packet enqueue time */ + prPktProfile->rEnqueueTimestamp = (OS_SYSTIME) kalGetTimeTick(); + } + break; + + case TX_PROF_TAG_DRV_DEQUE: + if (prPktProfile->fgIsValid) + prPktProfile->rDequeueTimestamp = (OS_SYSTIME) kalGetTimeTick(); + break; + + case TX_PROF_TAG_DRV_TX_DONE: + if (prPktProfile->fgIsValid) { + prPktProfile->rHifTxDoneTimestamp = (OS_SYSTIME) kalGetTimeTick(); +#if CFG_ENABLE_PER_STA_STATISTICS + wlanTxLifetimeUpdateStaStats(prAdapter, prMsduInfo); +#endif + } + break; + + case TX_PROF_TAG_MAC_TX_DONE: + break; + + default: + break; + } + + prMsduInfo = prNextMsduInfo; + }; +} + +VOID wlanTxProfilingTagPacket(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prPacket, IN ENUM_TX_PROFILING_TAG_T eTag) +{ +#if CFG_MET_PACKET_TRACE_SUPPORT + kalMetTagPacket(prAdapter->prGlueInfo, prPacket, eTag); +#endif +} + +VOID wlanTxProfilingTagMsdu(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_PROFILING_TAG_T eTag) +{ + wlanTxLifetimeTagPacket(prAdapter, prMsduInfo, eTag); + + wlanTxProfilingTagPacket(prAdapter, prMsduInfo->prPacket, eTag); +} + +VOID wlanUpdateTxStatistics(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN BOOLEAN fgTxDrop) +{ + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prBssInfo; + ENUM_WMM_ACI_T eAci = WMM_AC_BE_INDEX; + P_QUE_MGT_T prQM = &prAdapter->rQM; + OS_SYSTIME rCurTime; + + eAci = aucTid2ACI[prMsduInfo->ucUserPriority]; + + if (eAci < 0) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (prStaRec) { + if (fgTxDrop) + prStaRec->arLinkStatistics[eAci].u4TxDropMsdu++; + else + prStaRec->arLinkStatistics[eAci].u4TxMsdu++; + } else { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + + if (fgTxDrop) + prBssInfo->arLinkStatistics[eAci].u4TxDropMsdu++; + else + prBssInfo->arLinkStatistics[eAci].u4TxMsdu++; + } + + /* Trigger FW stats log every 20s */ + rCurTime = (OS_SYSTIME) kalGetTimeTick(); + + DBGLOG(INIT, TRACE, "CUR[%u] LAST[%u] TO[%u]\n", rCurTime, + prQM->rLastTxPktDumpTime, CHECK_FOR_TIMEOUT(rCurTime, + prQM->rLastTxPktDumpTime, + MSEC_TO_SYSTIME(prAdapter-> + rWifiVar.u4StatsLogTimeout))); + + if (CHECK_FOR_TIMEOUT(rCurTime, prQM->rLastTxPktDumpTime, + MSEC_TO_SYSTIME(prAdapter->rWifiVar.u4StatsLogTimeout))) { + + wlanTriggerStatsLog(prAdapter, prAdapter->rWifiVar.u4StatsLogDuration); + wlanDumpAllBssStatistics(prAdapter); + + prQM->rLastTxPktDumpTime = rCurTime; + } +} + +VOID wlanUpdateRxStatistics(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_STA_RECORD_T prStaRec; + ENUM_WMM_ACI_T eAci = WMM_AC_BE_INDEX; + + eAci = aucTid2ACI[prSwRfb->ucTid]; + if (eAci < 0) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (prStaRec) + prStaRec->arLinkStatistics[eAci].u4RxMsdu++; +} + +WLAN_STATUS wlanTriggerStatsLog(IN P_ADAPTER_T prAdapter, IN UINT_32 u4DurationInMs) +{ + CMD_STATS_LOG_T rStatsLogCmd; + WLAN_STATUS rResult; + + kalMemZero(&rStatsLogCmd, sizeof(CMD_STATS_LOG_T)); + + rStatsLogCmd.u4DurationInMs = u4DurationInMs; + + rResult = wlanSendSetQueryCmd(prAdapter, CMD_ID_STATS_LOG, TRUE, FALSE, + FALSE, nicCmdEventSetCommon, nicOidCmdTimeoutCommon, + sizeof(CMD_STATS_LOG_T), (PUINT_8) &rStatsLogCmd, NULL, 0); + + return rResult; +} + +WLAN_STATUS +wlanDhcpTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + DBGLOG(TX, INFO, "DHCP PKT TX DONE WIDX:PID[%u:%u] Status[%u] SeqNo[%u]\n", + prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, rTxDoneStatus, prMsduInfo->ucTxSeqNum); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanArpTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + UINT_16 u2ArpOp = 0; + PUINT_8 pucAheadBuf = NULL; + PUINT_8 pucArp = NULL; + UINT_32 u4PacketLen = 0; + + if (prMsduInfo->pucCookie) { + pucAheadBuf = prMsduInfo->pucCookie; + u4PacketLen = prMsduInfo->u2CookieLen; + pucArp = pucAheadBuf + ETH_HLEN; + if (u4PacketLen > (ETHER_HEADER_LEN+ARP_OPERATION_OFFSET)) { + WLAN_GET_FIELD_BE16(&pucAheadBuf[ETHER_HEADER_LEN+ARP_OPERATION_OFFSET], &u2ArpOp); + } else + DBGLOG(TX, WARN, "packet len:%u\n", u4PacketLen); + if (rTxDoneStatus) + DBGLOG(TX, INFO, + "ARP %s PKT[0x%p] WIDX:PID[%u:%u] SN[%d] TxDone[%u] TMAC&IP[" MACSTR "]&[" IPV4STR "]\n", + u2ArpOp == ARP_OPERATION_REQUEST ? "REQ" : "RSP", + prMsduInfo->pucCookie, prMsduInfo->ucWlanIndex, + prMsduInfo->ucPID, prMsduInfo->ucTxSeqNum, rTxDoneStatus, + MAC2STR(&pucArp[ARP_TARGET_MAC_OFFSET]), + IPV4TOSTR(&pucArp[ARP_TARGET_IP_OFFSET])); + else + DBGLOG_LIMITED(TX, INFO, + "ARP %s PKT[0x%p] WIDX:PID[%u:%u] SN[%d] TxDone[%u] TMAC&IP[" MACSTR "]&[" IPV4STR "]\n", + u2ArpOp == ARP_OPERATION_REQUEST ? "REQ" : "RSP", + prMsduInfo->pucCookie, prMsduInfo->ucWlanIndex, + prMsduInfo->ucPID, prMsduInfo->ucTxSeqNum, rTxDoneStatus, + MAC2STR(&pucArp[ARP_TARGET_MAC_OFFSET]), + IPV4TOSTR(&pucArp[ARP_TARGET_IP_OFFSET])); + } else { + if (rTxDoneStatus) + DBGLOG(TX, INFO, "ARP PKT WIDX:PID[%u:%u] SN[%u] TXDONE[%u]\n", + prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, prMsduInfo->ucTxSeqNum, rTxDoneStatus); + else + DBGLOG_LIMITED(TX, INFO, "ARP PKT WIDX:PID[%u:%u] SN[%u] TXDONE[%u]\n", + prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, prMsduInfo->ucTxSeqNum, rTxDoneStatus); + } + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanIcmpTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + DBGLOG_LIMITED(TX, INFO, "ICMP PKT TX DONE WIDX:PID[%u:%u] Status[%u] SeqNo[%u]\n", + prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, rTxDoneStatus, prMsduInfo->ucTxSeqNum); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanTdlsTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + DBGLOG(TX, INFO, "TDLS PKT TX DONE WIDX:PID[%u:%u] Status[%u] SeqNo[%u]\n", + prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, rTxDoneStatus, prMsduInfo->ucTxSeqNum); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanDnsTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + if (rTxDoneStatus) + DBGLOG(TX, INFO, "DNS PKT TX DONE WIDX:PID[%u:%u] Status[%u] SeqNo[%u]\n", + prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, rTxDoneStatus, prMsduInfo->ucTxSeqNum); + else + DBGLOG(TX, TRACE, "DNS PKT TX DONE WIDX:PID[%u:%u] Status[%u] SeqNo[%u]\n", + prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, rTxDoneStatus, prMsduInfo->ucTxSeqNum); + + return WLAN_STATUS_SUCCESS; +} + +VOID wlanReleasePendingCmdById(P_ADAPTER_T prAdapter, UINT_8 ucCid) +{ + 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); + DBGLOG(OID, INFO, "Remove pending Cmd: CID %d\n", ucCid); + + /* 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->ucCID != ucCid) { + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + continue; + } + + if (prCmdInfo->pfCmdTimeoutHandler) { + prCmdInfo->pfCmdTimeoutHandler(prAdapter, prCmdInfo); + } else if (prCmdInfo->fgIsOid) { + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, 0, WLAN_STATUS_FAILURE); + } + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); +} + +/* Translate Decimals string to Hex +** The result will be put in a 2bytes variable. +** Integer part will occupy the left most 3 bits, and decimal part is in the left 13 bits +** Integer part can be parsed by kstrtou16, decimal part should be translated by mutiplying +** 16 and then pick integer part. +** For example +*/ +UINT_32 wlanDecimalStr2Hexadecimals(PUINT_8 pucDecimalStr, PUINT_16 pu2Out) +{ + UINT_8 aucDecimalStr[32] = {0}; + PUINT_8 pucDecimalPart = NULL; + PUINT_8 tmp = NULL; + UINT_32 u4Result = 0; + UINT_32 u4Ret = 0; + UINT_32 u4Degree = 0; + UINT_32 u4Remain = 0; + UINT_8 ucAccuracy = 4; /* Hex decimals accuarcy is 4 bytes */ + UINT_32 u4Base = 1; + + if (!pu2Out || !pucDecimalStr) + return 1; + + while (*pucDecimalStr == '0') + pucDecimalStr++; + kalStrnCpy(aucDecimalStr, pucDecimalStr, sizeof(aucDecimalStr) - 1); + aucDecimalStr[31] = 0; + pucDecimalPart = strchr(aucDecimalStr, '.'); + if (!pucDecimalPart) { + DBGLOG(INIT, INFO, "No decimal part, ori str %s\n", pucDecimalStr); + goto integer_part; + } + *pucDecimalPart++ = 0; + /* get decimal degree */ + tmp = pucDecimalPart + strlen(pucDecimalPart); + do { + if (tmp == pucDecimalPart) { + DBGLOG(INIT, INFO, "Decimal part are all 0, ori str %s\n", pucDecimalStr); + goto integer_part; + } + tmp--; + } while (*tmp == '0'); + + *(++tmp) = 0; + u4Degree = (UINT_32)(tmp - pucDecimalPart); + /* if decimal part is not 0, translate it to hexadecimal decimals */ + /* Power(10, degree) */ + for (; u4Remain < u4Degree; u4Remain++) + u4Base *= 10; + + while (*pucDecimalPart == '0') + pucDecimalPart++; + + u4Ret = kstrtou32(pucDecimalPart, 0, &u4Remain); + if (u4Ret) { + DBGLOG(INIT, ERROR, "Parse decimal str %s error, degree %u\n", + pucDecimalPart, u4Degree); + return u4Ret; + } + + do { + u4Remain *= 16; + u4Result |= (u4Remain / u4Base) << ((ucAccuracy-1) * 4); + u4Remain %= u4Base; + ucAccuracy--; + } while (u4Remain && ucAccuracy > 0); + /* Each Hex Decimal byte was left shift more than 3 bits, so need + ** right shift 3 bits at last + ** For example, mmmnnnnnnnnnnnnn. + ** mmm is integer part, n represents decimals part. + ** the left most 4 n are shift 9 bits. But in for loop, we shift 12 bits + **/ + u4Result >>= 3; + u4Remain = 0; + +integer_part: + u4Ret = kstrtou32(aucDecimalStr, 0, &u4Remain); + u4Result |= u4Remain << 13; + + if (u4Ret) + DBGLOG(INIT, ERROR, "Parse integer str %s error\n", aucDecimalStr); + else { + *pu2Out = u4Result & 0xffff; + DBGLOG(INIT, TRACE, "Result 0x%04x\n", *pu2Out); + } + return u4Ret; +} +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR +/* link quality monitor */ +void wlanLinkQualityMonitor(P_GLUE_INFO_T prGlueInfo) +{ + P_ADAPTER_T prAdapter; + struct WIFI_LINK_QUALITY_INFO *prLinkQualityInfo = NULL; + P_PARAM_GET_STA_STATISTICS prQueryStaStatistics; + P_PARAM_802_11_STATISTICS_STRUCT_T prStat; + UINT_32 u4BufLen = 0; + UINT_8 arBssid[PARAM_MAC_ADDR_LEN]; + + prAdapter = prGlueInfo->prAdapter; + if (prAdapter == NULL) { + DBGLOG(SW4, ERROR, "prAdapter is null\n"); + return; + } + /* Completely record the Link quality and store the current time */ + prAdapter->u4LastLinkQuality = kalGetTimeTick(); + DBGLOG(NIC, TRACE, "LastLinkQuality:%u\n", prAdapter->u4LastLinkQuality); + + kalMemZero(arBssid, MAC_ADDR_LEN); + wlanQueryInformation(prAdapter, wlanoidQueryBssid, + &arBssid[0], sizeof(arBssid), &u4BufLen); + + /* send cmd to firmware */ + prQueryStaStatistics = &(prAdapter->rQueryStaStatistics); + prStat = &(prAdapter->rStat); + kalMemZero(prQueryStaStatistics, + sizeof(PARAM_GET_STA_STA_STATISTICS)); + kalMemZero(prStat, sizeof(PARAM_802_11_STATISTICS_STRUCT_T)); + COPY_MAC_ADDR(prQueryStaStatistics->aucMacAddr, arBssid); + prQueryStaStatistics->ucReadClear = TRUE; + wlanQueryStaStatistics(prAdapter, + prQueryStaStatistics, + sizeof(PARAM_GET_STA_STA_STATISTICS), + &(prAdapter->u4BufLen), + FALSE); + wlanQueryStatistics(prAdapter, prStat, sizeof(PARAM_802_11_STATISTICS_STRUCT_T), + &(prAdapter->u4BufLen), FALSE); + if (prAdapter->u4LastLinkQuality == 0) + return; + + /* prepare to set/get statistics from BSSInfo's rLinkQualityInfo */ + prLinkQualityInfo = &(prAdapter->rLinkQualityInfo); + + DBGLOG(SW4, INFO, + "Link Quality: Tx(rate:%u, total:%lu, retry:%lu, fail:%u, RTS fail:%lu, ACK fail:%lu), Rx(rate:%u, total:%lu, dup:%u, error:%lu), PER(%u), Congestion(idle slot:%u, diff:%u)\n", + prLinkQualityInfo->u4CurTxRate, /* tx rate, current tx link speed */ + prLinkQualityInfo->u8TxTotalCount, /* tx total packages */ + prLinkQualityInfo->u8TxRetryCount, /* tx retry count */ + prLinkQualityInfo->u8TxFailCount, /* tx fail count */ + prLinkQualityInfo->u8TxRtsFailCount, /* tx RTS fail count */ + prLinkQualityInfo->u8TxAckFailCount, /* tx ACK fail count */ + prLinkQualityInfo->u4CurRxRate, /* rx rate */ + prLinkQualityInfo->u8RxTotalCount, /* rx total packages */ + prLinkQualityInfo->u4RxDupCount, /* rx duplicate package count */ + prLinkQualityInfo->u8RxErrCount, /* rx error count */ + prLinkQualityInfo->u4CurTxPer, /* PER */ + prLinkQualityInfo->u8IdleSlotCount, /* congestion stats: idle slot */ + prLinkQualityInfo->u8DiffIdleSlotCount + ); +} +/* link quality monitor */ +void wlanFinishCollectingLinkQuality(P_GLUE_INFO_T prGlueInfo) +{ + P_ADAPTER_T prAdapter; + struct WIFI_LINK_QUALITY_INFO *prLinkQualityInfo = NULL; + P_RX_CTRL_T prRxCtrl; + UINT_32 u4CurRxRate, u4MaxRxRate; + UINT_64 u8TxFailCntDif, u8TxTotalCntDif; + int rv; + + prAdapter = prGlueInfo->prAdapter; + if (prAdapter == NULL) { + DBGLOG(SW4, ERROR, "prAdapter is null\n"); + return; + } + + prLinkQualityInfo = &(prAdapter->rLinkQualityInfo); + u8TxTotalCntDif = (prLinkQualityInfo->u8TxTotalCount > + prLinkQualityInfo->u8LastTxTotalCount) ? + (prLinkQualityInfo->u8TxTotalCount - + prLinkQualityInfo->u8LastTxTotalCount) : 0; + u8TxFailCntDif = (prLinkQualityInfo->u8TxFailCount > + prLinkQualityInfo->u8LastTxFailCount) ? + (prLinkQualityInfo->u8TxFailCount - + prLinkQualityInfo->u8LastTxFailCount) : 0; + if (u8TxTotalCntDif >= u8TxFailCntDif) + prLinkQualityInfo->u4CurTxPer = (u8TxTotalCntDif == 0) ? 0 : + (int)((u8TxFailCntDif * 100) / (u8TxTotalCntDif)); + else + prLinkQualityInfo->u4CurTxPer = 0; + if (prLinkQualityInfo->u8IdleSlotCount < prLinkQualityInfo->u8LastIdleSlotCount) { + prLinkQualityInfo->u8DiffIdleSlotCount = 0; + DBGLOG(NIC, WARN, "idle slot is error\n"); + } else + prLinkQualityInfo->u8DiffIdleSlotCount = prLinkQualityInfo->u8IdleSlotCount - + prLinkQualityInfo->u8LastIdleSlotCount; + + /* Get Rx Dup Count from RxCtrl */ + prRxCtrl = &prAdapter->rRxCtrl; + prLinkQualityInfo->u4RxDupCount = + (uint32_t)RX_GET_CNT(prRxCtrl, RX_DUPICATE_DROP_COUNT); + + /* Get Rx Rate */ + rv = kalGetRxRate(prGlueInfo, &u4CurRxRate, &u4MaxRxRate); + if (rv < 0) { + DBGLOG(NIC, ERROR, "kalGetRxRate error\n"); + prLinkQualityInfo->u4CurRxRate = 0; + } else + prLinkQualityInfo->u4CurRxRate = u4CurRxRate; + + prLinkQualityInfo->u8LastTxFailCount = prLinkQualityInfo->u8TxFailCount; + prLinkQualityInfo->u8LastTxTotalCount = prLinkQualityInfo->u8TxTotalCount; + prLinkQualityInfo->u8LastIdleSlotCount = prLinkQualityInfo->u8IdleSlotCount; +#ifdef CFG_SUPPORT_DATA_STALL + /* Just for Station mode */ + if (!(prAdapter->prAisBssInfo->prStaRecOfAP)) + return; + if (u8TxTotalCntDif >= (UINT_64)prAdapter->rWifiVar.u4TrafficThreshold) { + if (prLinkQualityInfo->u4CurTxPer > prAdapter->rWifiVar.u4PerHighThreshold) + mtk_cfg80211_vendor_event_driver_error(prGlueInfo->prAdapter, + EVENT_PER_HIGH, (UINT_16)sizeof(UINT_8)); + else if (prLinkQualityInfo->u4CurTxRate < prAdapter->rWifiVar.u4TxLowRateThreshold) + mtk_cfg80211_vendor_event_driver_error(prGlueInfo->prAdapter, + EVENT_TX_LOW_RATE, (UINT_16)sizeof(UINT_8)); + else if (prLinkQualityInfo->u4CurRxRate && + (prLinkQualityInfo->u4CurRxRate < prAdapter->rWifiVar.u4RxLowRateThreshold)) + mtk_cfg80211_vendor_event_driver_error(prGlueInfo->prAdapter, + EVENT_RX_LOW_RATE, (UINT_16)sizeof(UINT_8)); + } +#endif +} + +UINT_32 wlanGetStaIdxByWlanIdx(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucIndex, OUT PUINT_8 pucStaIdx) +{ + P_WLAN_TABLE_T prWtbl; + + ASSERT(prAdapter); + prWtbl = prAdapter->rWifiVar.arWtbl; + + if (ucIndex < WTBL_SIZE) { + if (prWtbl[ucIndex].ucUsed && prWtbl[ucIndex].ucPairwise) { + *pucStaIdx = prWtbl[ucIndex].ucStaIndex; + return WLAN_STATUS_SUCCESS; + } + } + return WLAN_STATUS_FAILURE; +} +#endif + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to query LTE safe channels. + * + * \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_PENDING + * \retval WLAN_STATUS_FAILURE + */ +/*----------------------------------------------------------------------------*/ +UINT_32 +wlanQueryLteSafeChannel(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucRoleIndex) +{ + UINT_32 rResult = WLAN_STATUS_FAILURE; + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo; + + + DBGLOG(P2P, TRACE, "[ACS] Get safe LTE Channels\n"); + + do { + if (!prAdapter) + break; + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + ucRoleIndex); + kalMemZero(&(prP2pRoleFsmInfo->rLteSafeChnInfo), sizeof(PARAM_GET_CHN_INFO)); + prP2pRoleFsmInfo->rLteSafeChnInfo.ucRoleIndex = ucRoleIndex; + + /* Get LTE safe channel list */ + wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LTE_CHN, + FALSE, + TRUE, + FALSE, /* Query ID */ + nicCmdEventQueryLteSafeChn, /* The handler to receive + * firmware notification + */ + nicOidCmdTimeoutCommon, + 0, + NULL, + &(prP2pRoleFsmInfo->rLteSafeChnInfo), + 0); + rResult = WLAN_STATUS_SUCCESS; + } while (FALSE); + return rResult; +} /* wlanoidQueryLteSafeChannel */ + +UINT_8 +wlanGetChannelIndex(IN UINT_8 channel) +{ + UINT_8 ucIdx = 1; + + if (channel <= 14) + ucIdx = channel - 1; + else if (channel >= 36 && channel <= 64) + ucIdx = 14 + (channel - 36) / 4; + else if (channel >= 100 && channel <= 140) + ucIdx = 14 + 8 + (channel - 100) / 4; + else if (channel >= 149 && channel <= 173) + ucIdx = 14 + 8 + 11 + (channel - 149) / 4; + else if (channel >= 184 && channel <= 216) + ucIdx = 14 + 8 + 11 + 7 + (channel - 184) / 4; + else{ + /* if channel num=2,the return inx is 1; if invalid,will also return 1.need to distinguish */ + DBGLOG(SCN, ERROR, "Invalid ch %u\n", channel); + return 255; + } + return ucIdx; +} + +#if CFG_SUPPORT_REPORT_MISC +UINT_32 wlanExtSrcReportMisc(P_GLUE_INFO_T prGlueInfo) +{ + if ((prGlueInfo == NULL) || (prGlueInfo->prAdapter == NULL)) { + DBGLOG(INIT, WARN, "Invalid parameter.\n"); + return 1; + } + if (test_and_clear_bit(EXT_SRC_DHCP_BIT, + &(prGlueInfo->prAdapter->rReportMiscSet.ulExtSrcFlag))) { + if (prGlueInfo->prAdapter->rReportMiscSet.eQueryNum + != REPORT_DHCP_START) { + wlanSendSetQueryCmd(prGlueInfo->prAdapter, + CMD_ID_GET_REPORT_MISC, + FALSE, + TRUE, + FALSE, + nicCmdEventReportMisc, + NULL, + 0, + NULL, + NULL, + 0); + prGlueInfo->prAdapter->rReportMiscSet.i4Rssi = 0; + prGlueInfo->prAdapter->rReportMiscSet.eQueryNum + = REPORT_DHCP_START; + } + } + + if (test_and_clear_bit(EXT_SRC_DISCONNCT_BIT, + &(prGlueInfo->prAdapter->rReportMiscSet.ulExtSrcFlag))) { + if (prGlueInfo->prAdapter->rReportMiscSet.eQueryNum + == REPORT_4WAYHS_START) { + wlanSendSetQueryCmd(prGlueInfo->prAdapter, + CMD_ID_GET_REPORT_MISC, + FALSE, + TRUE, + FALSE, + nicCmdEventReportMisc, + NULL, + 0, + NULL, + NULL, + 0); + prGlueInfo->prAdapter->rReportMiscSet.eQueryNum + = REPORT_4WAYHS_END; + } + } + return 0; +} +#endif + +void kalDumpHifCR(P_GLUE_INFO_T prGlueInfo) +{ + if (prGlueInfo != NULL) { +#if CFG_SUPPORT_MULTITHREAD + set_bit(GLUE_FLAG_HIF_PRT_HIF_DBG_INFO_BIT, &(prGlueInfo->ulFlag)); + wake_up_interruptible(&prGlueInfo->waitq_hif); +#endif + } +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/wlan_oid.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/wlan_oid.c new file mode 100644 index 0000000000000..2729d5d74948b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/wlan_oid.c @@ -0,0 +1,12854 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/common/wlan_oid.c#11 +*/ + +/* + * ! \file wlanoid.c + * \brief This file contains the WLAN OID processing routines of Windows 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" +#include "mgmt/rsn.h" +#include "gl_wext.h" +#include "debug.h" +#include + +#ifdef FW_CFG_SUPPORT +#include "fwcfg.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 +******************************************************************************* +*/ +const struct TXPWR_LIMIT_SAR_T g_aucSarTableMainAnt[CFG_MAX_SAR_TABLE_SIZE] = { +/* +* iwpriv wlan0 driver "O-SAR-ENABLE 0" +* function off +* +* iwpriv wlan0 driver "O-SAR-ENABLE 1" +* function on +* use g_aucSarTableMainAnt[0] parameter. +* +* iwpriv wlan0 driver "O-SAR-ENABLE 16" +* function on +* use g_aucSarTableMainAnt[15] parameter. +*/ + {0x01, {0x01, 0x01, 0x01, 0x01} },/*should reserve for old version*/ + {0x02, {0x02, 0x03, 0x04, 0x05} },/*should reserve for old version*/ + {0x26, {0x15, 0x15, 0x15, 0x15} },/*already used*/ + {0x20, {0x13, 0x13, 0x13, 0x13} },/*already used*/ + + {0x00, {0x00, 0x00, 0x00, 0x00} },/*already used*/ + {0x26, {0x1F, 0x1F, 0x1F, 0x1F} },/*already used*/ + {0x07, {0x02, 0x03, 0x04, 0x05} }, + {0x08, {0x02, 0x03, 0x04, 0x05} }, + + {0x09, {0x03, 0x03, 0x03, 0x03} }, + {0x0a, {0x02, 0x03, 0x04, 0x05} }, + {0x0b, {0x02, 0x03, 0x04, 0x05} }, + {0x0c, {0x02, 0x03, 0x04, 0x05} }, + + {0x0d, {0x02, 0x03, 0x04, 0x05} }, + {0x0e, {0x02, 0x03, 0x04, 0x05} }, + {0x0f, {0x02, 0x03, 0x04, 0x05} }, + {0x00, {0x06, 0x06, 0x06, 0x06} } +}; + +const struct TXPWR_LIMIT_SAR_T g_aucSarTableAuxiliaryAnt[CFG_MAX_SAR_TABLE_SIZE] = { +/* +* iwpriv wlan0 driver "O-SAR-ENABLE 0" +* function off +* +* iwpriv wlan0 driver "O-SAR-ENABLE 1" +* function on +* use g_aucSarTableAuxiliaryAnt[0] parameter. +* +* iwpriv wlan0 driver "O-SAR-ENABLE 16" +* function on +* use g_aucSarTableAuxiliaryAnt[15] parameter. +*/ + {0x01, {0x01, 0x04, 0x01, 0x01} },/*should reserve for old version*/ + {0x02, {0x02, 0x07, 0x04, 0x05} },/*should reserve for old version*/ + {0x26, {0x19, 0x19, 0x19, 0x19} },/*already used*/ + {0x20, {0x15, 0x15, 0x15, 0x15} },/*already used*/ + + {0x00, {0x00, 0x00, 0x00, 0x00} },/*already used*/ + {0x26, {0x1F, 0x1F, 0x1F, 0x1F} },/*already used*/ + {0x07, {0x02, 0x07, 0x04, 0x05} }, + {0x08, {0x02, 0x07, 0x04, 0x05} }, + + {0x09, {0x03, 0x07, 0x03, 0x03} }, + {0x0a, {0x02, 0x07, 0x04, 0x05} }, + {0x0b, {0x02, 0x07, 0x04, 0x05} }, + {0x0c, {0x02, 0x07, 0x04, 0x05} }, + + {0x0d, {0x02, 0x07, 0x04, 0x05} }, + {0x0e, {0x02, 0x07, 0x04, 0x05} }, + {0x0f, {0x02, 0x07, 0x04, 0x05} }, + {0x00, {0x06, 0x07, 0x06, 0x06} } +}; +/****************************************************************************** +* M A 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 DBG && 0 +static VOID SetRCID(BOOLEAN fgOneTb3, BOOL *fgRCID); +#endif + +#if CFG_SLT_SUPPORT +static VOID SetTestChannel(UINT_8 *pucPrimaryChannel); +#endif + +/****************************************************************************** +* 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 + +#if DBG && 0 +static VOID SetRCID(BOOLEAN fgOneTb3, BOOL *fgRCID) +{ + if (fgOneTb3) + *fgRCID = 0; + else + *fgRCID = 1; +} +#endif + +#if CFG_SLT_SUPPORT +static VOID SetTestChannel(UINT_8 *pucPrimaryChannel) +{ + if (*pucPrimaryChannel < 5) + *pucPrimaryChannel = 8; + else if (*pucPrimaryChannel > 10) + *pucPrimaryChannel = 3; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the supported physical layer network +* type that can be used by the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryNetworkTypesSupported(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + UINT_32 u4NumItem = 0; + ENUM_PARAM_NETWORK_TYPE_T eSupportedNetworks[PARAM_NETWORK_TYPE_NUM]; + PPARAM_NETWORK_TYPE_LIST prSupported; + + /* The array of all physical layer network subtypes that the driver supports. */ + + DEBUGFUNC("wlanoidQueryNetworkTypesSupported"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + /* Init. */ + for (u4NumItem = 0; u4NumItem < PARAM_NETWORK_TYPE_NUM; u4NumItem++) + eSupportedNetworks[u4NumItem] = 0; + + u4NumItem = 0; + + eSupportedNetworks[u4NumItem] = PARAM_NETWORK_TYPE_DS; + u4NumItem++; + + eSupportedNetworks[u4NumItem] = PARAM_NETWORK_TYPE_OFDM24; + u4NumItem++; + + *pu4QueryInfoLen = + (UINT_32) OFFSET_OF(PARAM_NETWORK_TYPE_LIST, eNetworkType) + + (u4NumItem * sizeof(ENUM_PARAM_NETWORK_TYPE_T)); + + if (u4QueryBufferLen < *pu4QueryInfoLen) + return WLAN_STATUS_INVALID_LENGTH; + + prSupported = (PPARAM_NETWORK_TYPE_LIST) pvQueryBuffer; + prSupported->NumberOfItems = u4NumItem; + kalMemCopy(prSupported->eNetworkType, eSupportedNetworks, u4NumItem * sizeof(ENUM_PARAM_NETWORK_TYPE_T)); + + DBGLOG(OID, TRACE, "NDIS supported network type list: %u\n", prSupported->NumberOfItems); + DBGLOG_MEM8(OID, TRACE, prSupported, *pu4QueryInfoLen); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryNetworkTypesSupported */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current physical layer network +* type used by the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the +* call failed due to invalid length of the query +* buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryNetworkTypeInUse(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + /* TODO: need to check the OID handler content again!! */ + + ENUM_PARAM_NETWORK_TYPE_T rCurrentNetworkTypeInUse = PARAM_NETWORK_TYPE_OFDM24; + + DEBUGFUNC("wlanoidQueryNetworkTypeInUse"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(ENUM_PARAM_NETWORK_TYPE_T)) { + *pu4QueryInfoLen = sizeof(ENUM_PARAM_NETWORK_TYPE_T); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) + rCurrentNetworkTypeInUse = (ENUM_PARAM_NETWORK_TYPE_T) (prAdapter->rWlanInfo.ucNetworkType); + else + rCurrentNetworkTypeInUse = (ENUM_PARAM_NETWORK_TYPE_T) (prAdapter->rWlanInfo.ucNetworkTypeInUse); + + *(P_ENUM_PARAM_NETWORK_TYPE_T) pvQueryBuffer = rCurrentNetworkTypeInUse; + *pu4QueryInfoLen = sizeof(ENUM_PARAM_NETWORK_TYPE_T); + + DBGLOG(OID, TRACE, "Network type in use: %d\n", rCurrentNetworkTypeInUse); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryNetworkTypeInUse */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the physical layer network type used +* by the driver. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns the +* amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS The given network type is supported and accepted. +* \retval WLAN_STATUS_INVALID_DATA The given network type is not in the +* supported list. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetNetworkTypeInUse(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + /* TODO: need to check the OID handler content again!! */ + + ENUM_PARAM_NETWORK_TYPE_T eNewNetworkType; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidSetNetworkTypeInUse"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(ENUM_PARAM_NETWORK_TYPE_T)) { + *pu4SetInfoLen = sizeof(ENUM_PARAM_NETWORK_TYPE_T); + return WLAN_STATUS_INVALID_LENGTH; + } + + eNewNetworkType = *(P_ENUM_PARAM_NETWORK_TYPE_T) pvSetBuffer; + *pu4SetInfoLen = sizeof(ENUM_PARAM_NETWORK_TYPE_T); + + DBGLOG(OID, INFO, "New network type: %d mode\n", eNewNetworkType); + + switch (eNewNetworkType) { + + case PARAM_NETWORK_TYPE_DS: + prAdapter->rWlanInfo.ucNetworkTypeInUse = (UINT_8) PARAM_NETWORK_TYPE_DS; + break; + + case PARAM_NETWORK_TYPE_OFDM5: + prAdapter->rWlanInfo.ucNetworkTypeInUse = (UINT_8) PARAM_NETWORK_TYPE_OFDM5; + break; + + case PARAM_NETWORK_TYPE_OFDM24: + prAdapter->rWlanInfo.ucNetworkTypeInUse = (UINT_8) PARAM_NETWORK_TYPE_OFDM24; + break; + + case PARAM_NETWORK_TYPE_AUTOMODE: + prAdapter->rWlanInfo.ucNetworkTypeInUse = (UINT_8) PARAM_NETWORK_TYPE_AUTOMODE; + break; + + case PARAM_NETWORK_TYPE_FH: + DBGLOG(OID, INFO, "Not support network type: %d\n", eNewNetworkType); + rStatus = WLAN_STATUS_NOT_SUPPORTED; + break; + + default: + DBGLOG(OID, INFO, "Unknown network type: %d\n", eNewNetworkType); + rStatus = WLAN_STATUS_INVALID_DATA; + break; + } + + /* Verify if we support the new network type. */ + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(OID, WARN, "Unknown network type: %d\n", eNewNetworkType); + + return rStatus; +} /* wlanoidSetNetworkTypeInUse */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current BSSID. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryBssid(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryBssid"); + + ASSERT(prAdapter); + + if (u4QueryBufferLen < MAC_ADDR_LEN) { + ASSERT(pu4QueryInfoLen); + *pu4QueryInfoLen = MAC_ADDR_LEN; + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + ASSERT(u4QueryBufferLen >= MAC_ADDR_LEN); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) + kalMemCopy(pvQueryBuffer, prAdapter->rWlanInfo.rCurrBssId.arMacAddress, MAC_ADDR_LEN); + else if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_IBSS) { + PARAM_MAC_ADDRESS aucTemp; /*!< BSSID */ + + COPY_MAC_ADDR(aucTemp, prAdapter->rWlanInfo.rCurrBssId.arMacAddress); + aucTemp[0] &= ~BIT(0); + aucTemp[1] |= BIT(1); + COPY_MAC_ADDR(pvQueryBuffer, aucTemp); + } else + rStatus = WLAN_STATUS_ADAPTER_NOT_READY; + + *pu4QueryInfoLen = MAC_ADDR_LEN; + return rStatus; +} /* wlanoidQueryBssid */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the list of all BSSIDs detected by +* the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryBssidList(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + UINT_32 i, u4BssidListExLen; + P_PARAM_BSSID_LIST_EX_T prList; + P_PARAM_BSSID_EX_T prBssidEx; + PUINT_8 cp; + + DEBUGFUNC("wlanoidQueryBssidList"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + + if (!pvQueryBuffer) + return WLAN_STATUS_INVALID_DATA; + } + + prGlueInfo = prAdapter->prGlueInfo; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in qeury BSSID list! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + u4BssidListExLen = 0; + + if (prAdapter->fgIsRadioOff == FALSE) { + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) + u4BssidListExLen += ALIGN_4(prAdapter->rWlanInfo.arScanResult[i].u4Length); + } + + if (u4BssidListExLen) + u4BssidListExLen += 4; /* u4NumberOfItems. */ + else + u4BssidListExLen = sizeof(PARAM_BSSID_LIST_EX_T); + + *pu4QueryInfoLen = u4BssidListExLen; + + if (u4QueryBufferLen < *pu4QueryInfoLen) + return WLAN_STATUS_INVALID_LENGTH; + + /* Clear the buffer */ + kalMemZero(pvQueryBuffer, u4BssidListExLen); + + prList = (P_PARAM_BSSID_LIST_EX_T) pvQueryBuffer; + cp = (PUINT_8) &prList->arBssid[0]; + + if (prAdapter->fgIsRadioOff == FALSE && prAdapter->rWlanInfo.u4ScanResultNum > 0) { + /* fill up for each entry */ + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + prBssidEx = (P_PARAM_BSSID_EX_T) cp; + + /* copy structure */ + kalMemCopy(prBssidEx, + &(prAdapter->rWlanInfo.arScanResult[i]), OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); + + /*For WHQL test, Rssi should be in range -10 ~ -200 dBm */ + if (prBssidEx->rRssi > PARAM_WHQL_RSSI_MAX_DBM) + prBssidEx->rRssi = PARAM_WHQL_RSSI_MAX_DBM; + + if (prAdapter->rWlanInfo.arScanResult[i].u4IELength > 0) { + /* copy IEs */ + kalMemCopy(prBssidEx->aucIEs, + prAdapter->rWlanInfo.apucScanResultIEs[i], + prAdapter->rWlanInfo.arScanResult[i].u4IELength); + } + /* 4-bytes alignement */ + prBssidEx->u4Length = ALIGN_4(prBssidEx->u4Length); + + cp += prBssidEx->u4Length; + prList->u4NumberOfItems++; + } + } + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryBssidList */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request the driver to perform +* scanning. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBssidListScan(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_SSID_T prSsid; + PARAM_SSID_T rSsid; + + DEBUGFUNC("wlanoidSetBssidListScan()"); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in set BSSID list scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pu4SetInfoLen); + *pu4SetInfoLen = 0; + + if (prAdapter->fgIsRadioOff) { + DBGLOG(OID, WARN, "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + 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 + return WLAN_STATUS_FAILURE; + } else + return WLAN_STATUS_FAILURE; + } else +#endif + { + if (prAdapter->fgEnOnlineScan == TRUE) + aisFsmScanRequest(prAdapter, prSsid, NULL, 0); + else if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) + aisFsmScanRequest(prAdapter, prSsid, NULL, 0); + else + return WLAN_STATUS_FAILURE; + } + + 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(OID, ERROR, + "Fail in set BSSID list scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (prAdapter->fgTestMode) { + DBGLOG(OID, WARN, "didn't support Scan in test mode\n"); + return WLAN_STATUS_FAILURE; + } + + ASSERT(pu4SetInfoLen); + *pu4SetInfoLen = 0; + + if (u4SetBufferLen != sizeof(PARAM_SCAN_REQUEST_EXT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + if (prAdapter->fgIsRadioOff) { + DBGLOG(OID, INFO, "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + DBGLOG(OID, TRACE, "ScanEX\n"); + 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 + return WLAN_STATUS_FAILURE; + } else + return WLAN_STATUS_FAILURE; + } else +#endif + { + if (prAdapter->fgEnOnlineScan == TRUE) + aisFsmScanRequest(prAdapter, prSsid, pucIe, u4IeLength); + else if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) + aisFsmScanRequest(prAdapter, prSsid, pucIe, u4IeLength); + else + return WLAN_STATUS_FAILURE; + } + + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetBssidListScanWithIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request the driver to perform +* scanning with attaching information elements(IEs) specified from user space +* and multiple SSID +* +* \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 +wlanoidSetBssidListScanAdv(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_SCAN_REQUEST_ADV_T prScanRequest; + struct _PARAM_SCAN_RANDOM_MAC_ADDR_T rScanRandMacAddr; + PARAM_SSID_T rSsid[CFG_SCAN_SSID_MAX_NUM]; + PUINT_8 pucIe; + UINT_8 ucSsidNum; + UINT_32 i, u4IeLength; + + DEBUGFUNC("wlanoidSetBssidListScanAdv()"); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in set BSSID list scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (prAdapter->fgTestMode) { + DBGLOG(OID, WARN, "didn't support Scan in test mode\n"); + return WLAN_STATUS_FAILURE; + } + + ASSERT(pu4SetInfoLen); + *pu4SetInfoLen = 0; + + if (u4SetBufferLen != sizeof(PARAM_SCAN_REQUEST_ADV_T)) + return WLAN_STATUS_INVALID_LENGTH; + else if (pvSetBuffer == NULL) + return WLAN_STATUS_INVALID_DATA; + + if (prAdapter->fgIsRadioOff) { + DBGLOG(OID, WARN, "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + prScanRequest = (P_PARAM_SCAN_REQUEST_ADV_T) pvSetBuffer; + kalMemCopy(&rScanRandMacAddr, &(prScanRequest->rScanRandomMacAddr), + sizeof(struct _PARAM_SCAN_RANDOM_MAC_ADDR_T)); + ucSsidNum = (UINT_8) (prScanRequest->u4SsidNum); + for (i = 0; i < prScanRequest->u4SsidNum; i++) { + if (prScanRequest->rSsid[i].u4SsidLen > ELEM_MAX_LEN_SSID) { + DBGLOG(OID, ERROR, + "[%s] SSID(%s) Length(%u) is over than ELEM_MAX_LEN_SSID(%d)\n", + __func__, prScanRequest->rSsid[i].aucSsid, + prScanRequest->rSsid[i].u4SsidLen, ELEM_MAX_LEN_SSID); + DBGLOG_MEM8(REQ, ERROR, prScanRequest, sizeof(PARAM_SCAN_REQUEST_ADV_T)); + + } + COPY_SSID(rSsid[i].aucSsid, + rSsid[i].u4SsidLen, prScanRequest->rSsid[i].aucSsid, prScanRequest->rSsid[i].u4SsidLen); + } + + pucIe = prScanRequest->pucIE; + u4IeLength = prScanRequest->u4IELength; + +#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) { + aisFsmScanRequestAdv(prAdapter, ucSsidNum, rSsid, pucIe, u4IeLength, + prScanRequest->ucSetChannel, &rScanRandMacAddr); + + } else + return WLAN_STATUS_FAILURE; + } else + return WLAN_STATUS_FAILURE; + } else +#endif + { + if (prAdapter->fgEnOnlineScan == TRUE) { + aisFsmScanRequestAdv(prAdapter, ucSsidNum, rSsid, pucIe, u4IeLength, + prScanRequest->ucSetChannel, &rScanRandMacAddr); + } else if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) { + aisFsmScanRequestAdv(prAdapter, ucSsidNum, rSsid, pucIe, u4IeLength, + prScanRequest->ucSetChannel, &rScanRandMacAddr); + } else + return WLAN_STATUS_FAILURE; + } + cnmTimerStartTimer(prAdapter, &prAdapter->rWifiVar.rAisFsmInfo.rScanDoneTimer, + SEC_TO_MSEC(AIS_SCN_DONE_TIMEOUT_SEC)); + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetBssidListScanAdv */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine will initiate the join procedure to attempt to associate +* with the specified BSSID. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBssid(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + P_UINT_8 pAddr; + UINT_32 i; + INT_32 i4Idx = -1; + P_MSG_AIS_ABORT_T prAisAbortMsg; + UINT_8 ucReasonOfDisconnect; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = MAC_ADDR_LEN; + if (u4SetBufferLen != MAC_ADDR_LEN) { + *pu4SetInfoLen = MAC_ADDR_LEN; + return WLAN_STATUS_INVALID_LENGTH; + } else if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set ssid! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + prGlueInfo = prAdapter->prGlueInfo; + pAddr = (P_UINT_8) pvSetBuffer; + + /* re-association check */ + if (kalGetMediaStateIndicated(prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, pAddr)) { + kalSetMediaStateIndicated(prGlueInfo, PARAM_MEDIA_STATE_TO_BE_INDICATED); + ucReasonOfDisconnect = DISCONNECT_REASON_CODE_REASSOCIATION; + } else { + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; + } + } else { + ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; + } + + /* check if any scanned result matchs with the BSSID */ + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.arScanResult[i].arMacAddress, pAddr)) { + i4Idx = (INT_32) i; + break; + } + } + + /* prepare message to AIS */ + if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_IBSS + || prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_DEDICATED_IBSS) { + /* IBSS *//* beacon period */ + prAdapter->rWifiVar.rConnSettings.u2BeaconPeriod = prAdapter->rWlanInfo.u2BeaconPeriod; + prAdapter->rWifiVar.rConnSettings.u2AtimWindow = prAdapter->rWlanInfo.u2AtimWindow; + } + + /* Set Connection Request Issued Flag */ + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = TRUE; + prAdapter->rWifiVar.rConnSettings.eConnectionPolicy = CONNECT_BY_BSSID; + + /* Send AIS Abort Message */ + prAisAbortMsg = (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); + if (!prAisAbortMsg) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; + prAisAbortMsg->ucReasonOfDisconnect = ucReasonOfDisconnect; + + /* Update the information to CONNECTION_SETTINGS_T */ + prAdapter->rWifiVar.rConnSettings.ucSSIDLen = 0; + prAdapter->rWifiVar.rConnSettings.aucSSID[0] = '\0'; + COPY_MAC_ADDR(prAdapter->rWifiVar.rConnSettings.aucBSSID, pAddr); + + if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, pAddr)) + prAisAbortMsg->fgDelayIndication = TRUE; + else + prAisAbortMsg->fgDelayIndication = FALSE; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); + + 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(OID, WARN, "Fail in set ssid! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + pParamSsid = (P_PARAM_SSID_T) pvSetBuffer; + + if (pParamSsid->u4SsidLen > 32) + return WLAN_STATUS_INVALID_LENGTH; + + prGlueInfo = prAdapter->prGlueInfo; + + /* prepare for CMD_BUILD_CONNECTION & CMD_GET_CONNECTION_STATUS */ + /* re-association check */ + if (kalGetMediaStateIndicated(prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + if (EQUAL_SSID(prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, + prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen, + pParamSsid->aucSsid, pParamSsid->u4SsidLen)) { + kalSetMediaStateIndicated(prGlueInfo, PARAM_MEDIA_STATE_TO_BE_INDICATED); + } else + 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 (!((pParamSsid->aucSsid[i] > 0) + && (pParamSsid->aucSsid[i] <= 0x1F))) { + fgIsValidSsid = TRUE; + break; + } + } + } + } + + /* Set Connection Request Issued Flag */ + if (fgIsValidSsid) { + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = TRUE; + + if (pParamSsid->u4SsidLen) + prAdapter->rWifiVar.rConnSettings.eConnectionPolicy = CONNECT_BY_SSID_BEST_RSSI; + else + /* wildcard SSID */ + prAdapter->rWifiVar.rConnSettings.eConnectionPolicy = CONNECT_BY_SSID_ANY; + } else + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = FALSE; + + /* Send AIS Abort Message */ + prAisAbortMsg = (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); + if (!prAisAbortMsg) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; + COPY_SSID(prAdapter->rWifiVar.rConnSettings.aucSSID, + prAdapter->rWifiVar.rConnSettings.ucSSIDLen, pParamSsid->aucSsid, (UINT_8) pParamSsid->u4SsidLen); + + if (EQUAL_SSID(prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, + prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen, pParamSsid->aucSsid, pParamSsid->u4SsidLen)) { + prAisAbortMsg->fgDelayIndication = TRUE; + } else { + /* Update the information to CONNECTION_SETTINGS_T */ + prAisAbortMsg->fgDelayIndication = FALSE; + } + DBGLOG(OID, 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 will initiate the join procedure to attempt +* to associate with the new BSS, base on given SSID, BSSID, and freqency. +* If the target connecting BSS is in the same ESS as current connected BSS, roaming +* will be performed. +* +* \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 +wlanoidSetConnect(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + P_PARAM_CONNECT_T pParamConn; + P_CONNECTION_SETTINGS_T prConnSettings; + UINT_32 i; + P_MSG_AIS_ABORT_T prAisAbortMsg; + BOOLEAN fgIsValidSsid = TRUE; + BOOLEAN fgEqualSsid = FALSE; + BOOLEAN fgEqualBssid = FALSE; + const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* MSDN: + * Powering on the radio if the radio is powered off through a setting of OID_802_11_DISASSOCIATE + */ + if (prAdapter->fgIsRadioOff == TRUE) + prAdapter->fgIsRadioOff = FALSE; + + if (u4SetBufferLen != sizeof(PARAM_CONNECT_T)) + return WLAN_STATUS_INVALID_LENGTH; + else if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set ssid! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + prAisAbortMsg = (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); + if (!prAisAbortMsg) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; + + pParamConn = (P_PARAM_CONNECT_T) pvSetBuffer; + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + + if (pParamConn->u4SsidLen > 32) { + cnmMemFree(prAdapter, prAisAbortMsg); + DBGLOG(OID, WARN, "SsidLen [%d] is invalid!\n", + pParamConn->u4SsidLen); + return WLAN_STATUS_INVALID_LENGTH; + } else if (!pParamConn->pucBssid && !pParamConn->pucSsid) { + cnmMemFree(prAdapter, prAisAbortMsg); + DBGLOG(OID, WARN, "Bssid or ssid is invalid!\n"); + return WLAN_STATUS_INVALID_LENGTH; + } + + prGlueInfo = prAdapter->prGlueInfo; + kalMemZero(prConnSettings->aucSSID, sizeof(prConnSettings->aucSSID)); + kalMemZero(prConnSettings->aucBSSID, sizeof(prConnSettings->aucBSSID)); + prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_ANY; + prConnSettings->fgIsConnByBssidIssued = FALSE; + + if (pParamConn->pucSsid) { + prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_BEST_RSSI; + COPY_SSID(prConnSettings->aucSSID, + prConnSettings->ucSSIDLen, pParamConn->pucSsid, (UINT_8) pParamConn->u4SsidLen); + if (EQUAL_SSID + (prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, + prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen, pParamConn->pucSsid, pParamConn->u4SsidLen)) + fgEqualSsid = TRUE; + } + if (pParamConn->pucBssid) { + if (!EQUAL_MAC_ADDR(aucZeroMacAddr, pParamConn->pucBssid) + && IS_UCAST_MAC_ADDR(pParamConn->pucBssid)) { + prConnSettings->eConnectionPolicy = CONNECT_BY_BSSID; + prConnSettings->fgIsConnByBssidIssued = TRUE; + COPY_MAC_ADDR(prConnSettings->aucBSSID, pParamConn->pucBssid); + if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, pParamConn->pucBssid)) + fgEqualBssid = TRUE; + } else + DBGLOG(OID, INFO, "wrong bssid " MACSTR "to connect\n", MAC2STR(pParamConn->pucBssid)); + } else + DBGLOG(OID, TRACE, "No Bssid set\n"); + prConnSettings->u4FreqInKHz = pParamConn->u4CenterFreq; + + /* prepare for CMD_BUILD_CONNECTION & CMD_GET_CONNECTION_STATUS */ + /* re-association check */ + if (kalGetMediaStateIndicated(prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + if (fgEqualSsid) { + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_ROAMING; + if (fgEqualBssid) { + kalSetMediaStateIndicated(prGlueInfo, PARAM_MEDIA_STATE_TO_BE_INDICATED); + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_REASSOCIATION; + } + } else { + DBGLOG(OID, INFO, "DisBySsid\n"); + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; + cnmMemFree(prAdapter, prAisAbortMsg); + /* reject this connect to avoid to install key fail */ + return WLAN_STATUS_FAILURE; + } + } else + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; +#if 0 + /* check if any scanned result matchs with the SSID */ + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + PUINT_8 aucSsid = prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid; + UINT_8 ucSsidLength = (UINT_8) prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen; + INT_32 i4RSSI = prAdapter->rWlanInfo.arScanResult[i].rRssi; + + if (EQUAL_SSID(aucSsid, ucSsidLength, pParamConn->pucSsid, pParamConn->u4SsidLen) && + i4RSSI >= i4MaxRSSI) { + i4Idx = (INT_32) i; + i4MaxRSSI = i4RSSI; + } + if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.arScanResult[i].arMacAddress, pAddr)) { + i4Idx = (INT_32) i; + break; + } + } +#endif + /* prepare message to AIS */ + if (prConnSettings->eOPMode == NET_TYPE_IBSS || prConnSettings->eOPMode == NET_TYPE_DEDICATED_IBSS) { + /* IBSS *//* beacon period */ + prConnSettings->u2BeaconPeriod = prAdapter->rWlanInfo.u2BeaconPeriod; + prConnSettings->u2AtimWindow = prAdapter->rWlanInfo.u2AtimWindow; + } + + if (prAdapter->rWifiVar.fgSupportWZCDisassociation) { + if (pParamConn->u4SsidLen == ELEM_MAX_LEN_SSID && pParamConn->pucSsid) { + fgIsValidSsid = FALSE; + + for (i = 0; i < ELEM_MAX_LEN_SSID; i++) { + if (!((pParamConn->pucSsid[i] > 0) + && (pParamConn->pucSsid[i] <= 0x1F))) { + fgIsValidSsid = TRUE; + break; + } + } + } + } + + /* Set Connection Request Issued Flag */ + if (fgIsValidSsid) { + prConnSettings->fgIsConnReqIssued = TRUE; + } else { + prConnSettings->eReConnectLevel = RECONNECT_LEVEL_USER_SET; + prConnSettings->fgIsConnReqIssued = FALSE; + } + + if (fgEqualSsid || fgEqualBssid) + prAisAbortMsg->fgDelayIndication = TRUE; + else + /* Update the information to CONNECTION_SETTINGS_T */ + prAisAbortMsg->fgDelayIndication = FALSE; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); + + DBGLOG(OID, INFO, "ssid %s, bssid " MACSTR ", conn policy %d, disc reason %d\n", + prConnSettings->aucSSID, MAC2STR(prConnSettings->aucBSSID), + prConnSettings->eConnectionPolicy, prAisAbortMsg->ucReasonOfDisconnect); + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetConnect */ + +#if CFG_SUPPORT_ABORT_SCAN +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to do abort scan +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval Always WLAN_STATUS_SUCCESS +* +* \note The setting buffer NULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAbortScan(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + ASSERT(prAdapter); + + /* Do abort SCAN */ + if (AisFsmGetScanState(prAdapter)) { + DBGLOG(OID, INFO, "ABORT scan on scanning state by user\n"); + aisFsmStateAbort_SCAN(prAdapter); + } else { + DBGLOG(OID, INFO, "ABORT scan need remove cmd from queue by user\n"); + prAdapter->fgAbortScan = TRUE; + } + return WLAN_STATUS_SUCCESS; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \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); + if (pu4QueryInfoLen == NULL) + return WLAN_STATUS_FAILURE; + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_SSID_T); + + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prAssociatedSsid = (P_PARAM_SSID_T) pvQueryBuffer; + + kalMemZero(prAssociatedSsid->aucSsid, sizeof(prAssociatedSsid->aucSsid)); + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + prAssociatedSsid->u4SsidLen = prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen; + + if (prAssociatedSsid->u4SsidLen) { + kalMemCopy(prAssociatedSsid->aucSsid, + prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, prAssociatedSsid->u4SsidLen); + } + } else { + prAssociatedSsid->u4SsidLen = 0; + + DBGLOG(OID, TRACE, "Null SSID\n"); + } + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQuerySsid */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current 802.11 network type. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryInfrastructureMode(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryInfrastructureMode"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(ENUM_PARAM_OP_MODE_T); + + if (u4QueryBufferLen < sizeof(ENUM_PARAM_OP_MODE_T)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *(P_ENUM_PARAM_OP_MODE_T) pvQueryBuffer = prAdapter->rWifiVar.rConnSettings.eOPMode; + + /* + ** According to OID_802_11_INFRASTRUCTURE_MODE + ** If there is no prior OID_802_11_INFRASTRUCTURE_MODE, + ** NDIS_STATUS_ADAPTER_NOT_READY shall be returned. + */ +#if DBG + switch (*(P_ENUM_PARAM_OP_MODE_T) pvQueryBuffer) { + case NET_TYPE_IBSS: + DBGLOG(OID, INFO, "IBSS mode\n"); + break; + case NET_TYPE_INFRA: + DBGLOG(OID, INFO, "Infrastructure mode\n"); + break; + default: + DBGLOG(OID, INFO, "Automatic mode\n"); + } +#endif + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryInfrastructureMode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set mode to infrastructure or +* IBSS, or automatic switch between the two. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid +* length of the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetInfrastructureMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + ENUM_PARAM_OP_MODE_T eOpMode; +/* P_WLAN_TABLE_T prWlanTable; */ +#if CFG_SUPPORT_802_11W +/* P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; */ +#endif +/* P_BSS_INFO_T prBssInfo; */ +/* UINT_8 i; */ + + DEBUGFUNC("wlanoidSetInfrastructureMode"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prGlueInfo = prAdapter->prGlueInfo; + + if (u4SetBufferLen < sizeof(ENUM_PARAM_OP_MODE_T)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + *pu4SetInfoLen = sizeof(ENUM_PARAM_OP_MODE_T); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in set infrastructure mode! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + eOpMode = *(P_ENUM_PARAM_OP_MODE_T) pvSetBuffer; + /* Verify the new infrastructure mode. */ + if (eOpMode >= NET_TYPE_NUM) { + DBGLOG(OID, TRACE, "Invalid mode value %d\n", eOpMode); + return WLAN_STATUS_INVALID_DATA; + } + + /* check if possible to switch to AdHoc mode */ + if (eOpMode == NET_TYPE_IBSS || eOpMode == NET_TYPE_DEDICATED_IBSS) { + if (cnmAisIbssIsPermitted(prAdapter) == FALSE) { + DBGLOG(OID, TRACE, "Mode value %d unallowed\n", eOpMode); + return WLAN_STATUS_FAILURE; + } + } + + /* Save the new infrastructure mode setting. */ + prAdapter->rWifiVar.rConnSettings.eOPMode = eOpMode; + + prAdapter->rWifiVar.rConnSettings.fgWapiMode = FALSE; + +#if CFG_SUPPORT_802_11W + prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = FALSE; + prAdapter->rWifiVar.rAisSpecificBssInfo.fgBipKeyInstalled = FALSE; +#endif + +#if 0 /* STA record remove at AIS_ABORT nicUpdateBss and DISCONNECT */ + for (i = 0; i < BSS_INFO_NUM; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) + cnmStaFreeAllStaByNetwork(prAdapter, prBssInfo->ucBssIndex, 0); + } +#endif + + /* Clean up the Tx key flag */ + prAdapter->prAisBssInfo->fgTxBcKeyExist = FALSE; + prAdapter->prAisBssInfo->ucTxDefaultKeyID = 0; + prAdapter->prAisBssInfo->ucCurrentGtkId = 0; + + /* prWlanTable = prAdapter->rWifiVar.arWtbl; */ + /* prWlanTable[prAdapter->prAisBssInfo->ucBMCWlanIndex].ucKeyId = 0; */ + +#if DBG + DBGLOG(RSN, TRACE, "wlanoidSetInfrastructureMode\n"); +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_INFRASTRUCTURE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, nicOidCmdTimeoutCommon, 0, NULL, pvSetBuffer, u4SetBufferLen); +} /* wlanoidSetInfrastructureMode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current 802.11 authentication +* mode. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryAuthMode(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryAuthMode"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(ENUM_PARAM_AUTH_MODE_T); + + if (u4QueryBufferLen < sizeof(ENUM_PARAM_AUTH_MODE_T)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + *(P_ENUM_PARAM_AUTH_MODE_T) pvQueryBuffer = prAdapter->rWifiVar.rConnSettings.eAuthMode; + +#if DBG + switch (*(P_ENUM_PARAM_AUTH_MODE_T) pvQueryBuffer) { + case AUTH_MODE_OPEN: + DBGLOG(OID, INFO, "Current auth mode: Open\n"); + break; + + case AUTH_MODE_SHARED: + DBGLOG(OID, INFO, "Current auth mode: Shared\n"); + break; + + case AUTH_MODE_AUTO_SWITCH: + DBGLOG(OID, INFO, "Current auth mode: Auto-switch\n"); + break; + + case AUTH_MODE_WPA: + DBGLOG(OID, INFO, "Current auth mode: WPA\n"); + break; + + case AUTH_MODE_WPA_PSK: + DBGLOG(OID, INFO, "Current auth mode: WPA PSK\n"); + break; + + case AUTH_MODE_WPA_NONE: + DBGLOG(OID, INFO, "Current auth mode: WPA None\n"); + break; + + case AUTH_MODE_WPA2: + DBGLOG(OID, INFO, "Current auth mode: WPA2\n"); + break; + + case AUTH_MODE_WPA2_PSK: + DBGLOG(OID, INFO, "Current auth mode: WPA2 PSK\n"); + break; + + default: + DBGLOG(OID, INFO, "Current auth mode: %d\n", *(P_ENUM_PARAM_AUTH_MODE_T) pvQueryBuffer); + break; + } +#endif + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryAuthMode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the IEEE 802.11 authentication mode +* to the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_NOT_ACCEPTED +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAuthMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + /* UINT_32 i, u4AkmSuite; */ + /* P_DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY prEntry; */ + + DEBUGFUNC("wlanoidSetAuthMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + prGlueInfo = prAdapter->prGlueInfo; + + *pu4SetInfoLen = sizeof(ENUM_PARAM_AUTH_MODE_T); + + if (u4SetBufferLen < sizeof(ENUM_PARAM_AUTH_MODE_T)) + return WLAN_STATUS_INVALID_LENGTH; + + /* RF Test */ + /* if (IS_ARB_IN_RFTEST_STATE(prAdapter)) { */ + /* return WLAN_STATUS_SUCCESS; */ + /* } */ + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in set Authentication mode! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + /* Check if the new authentication mode is valid. */ + if (*(P_ENUM_PARAM_AUTH_MODE_T) pvSetBuffer >= AUTH_MODE_NUM) { + DBGLOG(OID, TRACE, "Invalid auth mode %d\n", *(P_ENUM_PARAM_AUTH_MODE_T) pvSetBuffer); + return WLAN_STATUS_INVALID_DATA; + } + + switch (*(P_ENUM_PARAM_AUTH_MODE_T) pvSetBuffer) { + case AUTH_MODE_WPA: + case AUTH_MODE_WPA_PSK: + case AUTH_MODE_WPA2: + case AUTH_MODE_WPA2_PSK: + case AUTH_MODE_WPA2_FT: + case AUTH_MODE_WPA2_FT_PSK: + case AUTH_MODE_WPA3_SAE: + case AUTH_MODE_WPA3_OWE: + /* infrastructure mode only */ + if (prAdapter->rWifiVar.rConnSettings.eOPMode != NET_TYPE_INFRA) + return WLAN_STATUS_NOT_ACCEPTED; + break; + + case AUTH_MODE_WPA_NONE: + /* ad hoc mode only */ + if (prAdapter->rWifiVar.rConnSettings.eOPMode != NET_TYPE_IBSS) + return WLAN_STATUS_NOT_ACCEPTED; + break; + + default: + break; + } + + /* Save the new authentication mode. */ + prAdapter->rWifiVar.rConnSettings.eAuthMode = *(P_ENUM_PARAM_AUTH_MODE_T) pvSetBuffer; + +#if DBG + switch (prAdapter->rWifiVar.rConnSettings.eAuthMode) { + case AUTH_MODE_OPEN: + DBGLOG(RSN, TRACE, "New auth mode: open\n"); + break; + + case AUTH_MODE_SHARED: + DBGLOG(RSN, TRACE, "New auth mode: shared\n"); + break; + + case AUTH_MODE_AUTO_SWITCH: + DBGLOG(RSN, TRACE, "New auth mode: auto-switch\n"); + break; + + case AUTH_MODE_WPA: + DBGLOG(RSN, TRACE, "New auth mode: WPA\n"); + break; + + case AUTH_MODE_WPA_PSK: + DBGLOG(RSN, TRACE, "New auth mode: WPA PSK\n"); + break; + + case AUTH_MODE_WPA_NONE: + DBGLOG(RSN, TRACE, "New auth mode: WPA None\n"); + break; + + case AUTH_MODE_WPA2: + DBGLOG(RSN, TRACE, "New auth mode: WPA2\n"); + break; + + case AUTH_MODE_WPA2_PSK: + DBGLOG(RSN, TRACE, "New auth mode: WPA2 PSK\n"); + break; + + default: + DBGLOG(RSN, TRACE, "New auth mode: unknown (%d)\n", prAdapter->rWifiVar.rConnSettings.eAuthMode); + } +#endif + +#if 0 + 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 + } +#endif + + return WLAN_STATUS_SUCCESS; + +} /* wlanoidSetAuthMode */ + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current 802.11 privacy filter +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryPrivacyFilter(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryPrivacyFilter"); + + ASSERT(prAdapter); + + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(ENUM_PARAM_PRIVACY_FILTER_T); + + if (u4QueryBufferLen < sizeof(ENUM_PARAM_PRIVACY_FILTER_T)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + *(P_ENUM_PARAM_PRIVACY_FILTER_T) pvQueryBuffer = prAdapter->rWlanInfo.ePrivacyFilter; + +#if DBG + switch (*(P_ENUM_PARAM_PRIVACY_FILTER_T) pvQueryBuffer) { + case PRIVACY_FILTER_ACCEPT_ALL: + DBGLOG(OID, INFO, "Current privacy mode: open mode\n"); + break; + + case PRIVACY_FILTER_8021xWEP: + DBGLOG(OID, INFO, "Current privacy mode: filtering mode\n"); + break; + + default: + DBGLOG(OID, INFO, "Current auth mode: %d\n", *(P_ENUM_PARAM_AUTH_MODE_T) pvQueryBuffer); + } +#endif + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryPrivacyFilter */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the IEEE 802.11 privacy filter +* to the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_NOT_ACCEPTED +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetPrivacyFilter(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + + DEBUGFUNC("wlanoidSetPrivacyFilter"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + prGlueInfo = prAdapter->prGlueInfo; + + *pu4SetInfoLen = sizeof(ENUM_PARAM_PRIVACY_FILTER_T); + + if (u4SetBufferLen < sizeof(ENUM_PARAM_PRIVACY_FILTER_T)) + return WLAN_STATUS_INVALID_LENGTH; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in set Authentication mode! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + /* Check if the new authentication mode is valid. */ + if (*(P_ENUM_PARAM_PRIVACY_FILTER_T) pvSetBuffer >= PRIVACY_FILTER_NUM) { + DBGLOG(OID, TRACE, "Invalid privacy filter %d\n", *(P_ENUM_PARAM_PRIVACY_FILTER_T) pvSetBuffer); + return WLAN_STATUS_INVALID_DATA; + } + + switch (*(P_ENUM_PARAM_PRIVACY_FILTER_T) pvSetBuffer) { + default: + break; + } + + /* Save the new authentication mode. */ + prAdapter->rWlanInfo.ePrivacyFilter = *(ENUM_PARAM_PRIVACY_FILTER_T) pvSetBuffer; + + return WLAN_STATUS_SUCCESS; + +} /* wlanoidSetPrivacyFilter */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to reload the available default settings for +* the specified type field. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetReloadDefaults(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + ENUM_PARAM_NETWORK_TYPE_T eNetworkType; + UINT_32 u4Len; + UINT_8 ucCmdSeqNum; + + DEBUGFUNC("wlanoidSetReloadDefaults"); + + ASSERT(prAdapter); + + ASSERT(pu4SetInfoLen); + *pu4SetInfoLen = sizeof(PARAM_RELOAD_DEFAULTS); + + /* if (IS_ARB_IN_RFTEST_STATE(prAdapter)) { */ + /* return WLAN_STATUS_SUCCESS; */ + /* } */ + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in set Reload default! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pvSetBuffer); + /* Verify the available reload options and reload the settings. */ + switch (*(P_PARAM_RELOAD_DEFAULTS) pvSetBuffer) { + case ENUM_RELOAD_WEP_KEYS: + /* + * Reload available default WEP keys from the permanent + * storage. + */ + prAdapter->rWifiVar.rConnSettings.eAuthMode = AUTH_MODE_OPEN; + /* ENUM_ENCRYPTION_DISABLED; */ + prAdapter->rWifiVar.rConnSettings.eEncStatus = ENUM_ENCRYPTION1_KEY_ABSENT; + { + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_CMD_802_11_KEY prCmdKey; + UINT_8 aucBCAddr[] = BC_MAC_ADDR; + + prGlueInfo = prAdapter->prGlueInfo; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_802_11_KEY))); + + if (!prCmdInfo) { + DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_802_11_KEY cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + 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 = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prCmdKey = (P_CMD_802_11_KEY) (prWifiCmd->aucBuffer); + + kalMemZero((PUINT_8) prCmdKey, sizeof(CMD_802_11_KEY)); + + prCmdKey->ucAddRemove = 0; /* Remove */ + prCmdKey->ucKeyId = 0; /* (UINT_8)(prRemovedKey->u4KeyIndex & 0x000000ff); */ + kalMemCopy(prCmdKey->aucPeerAddr, aucBCAddr, MAC_ADDR_LEN); + + ASSERT(prCmdKey->ucKeyId < MAX_KEY_NUM); + + prCmdKey->ucKeyType = 0; + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; + } + + break; + + default: + DBGLOG(OID, TRACE, "Invalid reload option %d\n", *(P_PARAM_RELOAD_DEFAULTS) pvSetBuffer); + rStatus = WLAN_STATUS_INVALID_DATA; + } + + /* OID_802_11_RELOAD_DEFAULTS requiest to reset to auto mode */ + eNetworkType = PARAM_NETWORK_TYPE_AUTOMODE; + wlanoidSetNetworkTypeInUse(prAdapter, &eNetworkType, sizeof(eNetworkType), &u4Len); + + return rStatus; +} /* wlanoidSetReloadDefaults */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a WEP key to the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +#ifdef LINUX +UINT_8 keyBuffer[sizeof(PARAM_KEY_T) + 16 /* LEGACY_KEY_MAX_LEN */]; +UINT_8 aucBCAddr[] = BC_MAC_ADDR; +#endif +WLAN_STATUS +wlanoidSetAddWep(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ +#ifndef LINUX + UINT_8 keyBuffer[sizeof(PARAM_KEY_T) + 16 /* LEGACY_KEY_MAX_LEN */]; + UINT_8 aucBCAddr[] = BC_MAC_ADDR; +#endif + P_PARAM_WEP_T prNewWepKey; + P_PARAM_KEY_T prParamKey = (P_PARAM_KEY_T) keyBuffer; + UINT_32 u4KeyId, u4SetLen; + + DEBUGFUNC("wlanoidSetAddWep"); + + ASSERT(prAdapter); + + *pu4SetInfoLen = OFFSET_OF(PARAM_WEP_T, aucKeyMaterial); + + if (u4SetBufferLen < OFFSET_OF(PARAM_WEP_T, aucKeyMaterial)) { + ASSERT(pu4SetInfoLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set add WEP! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + prNewWepKey = (P_PARAM_WEP_T) pvSetBuffer; + + /* Verify the total buffer for minimum length. */ + if (u4SetBufferLen < OFFSET_OF(PARAM_WEP_T, aucKeyMaterial) + prNewWepKey->u4KeyLength) { + DBGLOG(OID, WARN, "Invalid total buffer length (%d) than minimum length (%d)\n", + (UINT_8) u4SetBufferLen, (UINT_8) OFFSET_OF(PARAM_WEP_T, aucKeyMaterial)); + + *pu4SetInfoLen = OFFSET_OF(PARAM_WEP_T, aucKeyMaterial); + return WLAN_STATUS_INVALID_DATA; + } + + /* Verify the key structure length. */ + if (prNewWepKey->u4Length > u4SetBufferLen) { + DBGLOG(OID, WARN, + "Invalid key structure length (%d) greater than total buffer length (%d)\n", + (UINT_8) prNewWepKey->u4Length, (UINT_8) u4SetBufferLen); + + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_INVALID_DATA; + } + + /* Verify the key material length for maximum key material length:16 */ + if (prNewWepKey->u4KeyLength > 16 /* LEGACY_KEY_MAX_LEN */) { + DBGLOG(OID, WARN, + "Invalid key material length (%d) greater than maximum key material length (16)\n", + (UINT_8) prNewWepKey->u4KeyLength); + + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_INVALID_DATA; + } + + *pu4SetInfoLen = u4SetBufferLen; + + u4KeyId = prNewWepKey->u4KeyIndex & BITS(0, 29) /* WEP_KEY_ID_FIELD */; + + /* + * Verify whether key index is valid or not, current version + * driver support only 4 global WEP keys setting by this OID + */ + if (u4KeyId > MAX_KEY_NUM - 1) { + DBGLOG(OID, ERROR, "Error, invalid WEP key ID: %d\n", (UINT_8) u4KeyId); + return WLAN_STATUS_INVALID_DATA; + } + + prParamKey->u4KeyIndex = u4KeyId; + + /* Transmit key */ + if (prNewWepKey->u4KeyIndex & IS_TRANSMIT_KEY) + prParamKey->u4KeyIndex |= IS_TRANSMIT_KEY; + + /* Per client key */ + if (prNewWepKey->u4KeyIndex & IS_UNICAST_KEY) + prParamKey->u4KeyIndex |= IS_UNICAST_KEY; + + prParamKey->u4KeyLength = prNewWepKey->u4KeyLength; + + kalMemCopy(prParamKey->arBSSID, aucBCAddr, MAC_ADDR_LEN); + + kalMemCopy(prParamKey->aucKeyMaterial, prNewWepKey->aucKeyMaterial, prNewWepKey->u4KeyLength); + + prParamKey->u4Length = OFFSET_OF(PARAM_KEY_T, aucKeyMaterial) + prNewWepKey->u4KeyLength; + + wlanoidSetAddKey(prAdapter, (PVOID) prParamKey, prParamKey->u4Length, &u4SetLen); + + return WLAN_STATUS_PENDING; +} /* wlanoidSetAddWep */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request the driver to remove the WEP key +* at the specified key index. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetRemoveWep(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + UINT_32 u4KeyId, u4SetLen; + PARAM_REMOVE_KEY_T rRemoveKey; + UINT_8 aucBCAddr[] = BC_MAC_ADDR; + + DEBUGFUNC("wlanoidSetRemoveWep"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_KEY_INDEX); + + if (u4SetBufferLen < sizeof(PARAM_KEY_INDEX)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + u4KeyId = *(PUINT_32) pvSetBuffer; + + /* Dump PARAM_WEP content. */ + DBGLOG(OID, INFO, "Set: Dump PARAM_KEY_INDEX content\n"); + DBGLOG(OID, INFO, "Index : 0x%08x\n", u4KeyId); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in set remove WEP! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + if (u4KeyId & IS_TRANSMIT_KEY) { + /* Bit 31 should not be set */ + DBGLOG(OID, ERROR, "Invalid WEP key index: 0x%08x\n", u4KeyId); + return WLAN_STATUS_INVALID_DATA; + } + + u4KeyId &= BITS(0, 7); + + /* + * Verify whether key index is valid or not. Current version + * driver support only 4 global WEP keys. + */ + if (u4KeyId > MAX_KEY_NUM - 1) { + DBGLOG(OID, ERROR, "invalid WEP key ID %u\n", u4KeyId); + return WLAN_STATUS_INVALID_DATA; + } + + rRemoveKey.u4Length = sizeof(PARAM_REMOVE_KEY_T); + rRemoveKey.u4KeyIndex = *(PUINT_32) pvSetBuffer; + + kalMemCopy(rRemoveKey.arBSSID, aucBCAddr, MAC_ADDR_LEN); + + wlanoidSetRemoveKey(prAdapter, (PVOID)&rRemoveKey, sizeof(PARAM_REMOVE_KEY_T), &u4SetLen); + + return WLAN_STATUS_PENDING; +} /* wlanoidSetRemoveWep */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a key to the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer PARAM_KEY_T, which is set by NDIS, is unpacked. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAddKey(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, 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; + P_BSS_INFO_T prBssInfo; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + P_WLAN_TABLE_T prWlanTable; + P_STA_RECORD_T prStaRec = NULL; + BOOL fgAddTxBcKey = FALSE; + +#if CFG_SUPPORT_TDLS + P_STA_RECORD_T prTmpStaRec; +#endif + + DEBUGFUNC("wlanoidSetAddKey"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set add key! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + prNewKey = (P_PARAM_KEY_T) pvSetBuffer; + + /* Verify the key structure length. */ + if (prNewKey->u4Length > u4SetBufferLen) { + DBGLOG(OID, WARN, + "Invalid key structure length (%d) greater than total buffer length (%d)\n", + (UINT_8) prNewKey->u4Length, (UINT_8) u4SetBufferLen); + + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_INVALID_LENGTH; + } + + /* Verify the key material length for key material buffer */ + if (prNewKey->u4KeyLength > prNewKey->u4Length - OFFSET_OF(PARAM_KEY_T, aucKeyMaterial)) { + DBGLOG(OID, WARN, "Invalid key material length (%d)\n", (UINT_8) prNewKey->u4KeyLength); + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_INVALID_DATA; + } + + /* Exception check */ + if (prNewKey->u4KeyIndex & 0x0fffff00) + return WLAN_STATUS_INVALID_DATA; + + /* Exception check, pairwise key must with transmit bit enabled */ + if ((prNewKey->u4KeyIndex & BITS(30, 31)) == 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(OID, INFO, "PARAM_KEY Length: 0x%x, Key Index: 0x%x, Key Length: 0x%x, BSSID: "MACSTR"\n", + prNewKey->u4Length, prNewKey->u4KeyIndex, prNewKey->u4KeyLength, + MAC2STR(prNewKey->arBSSID)); + DBGLOG(OID, TRACE, "Key RSC:\n"); + DBGLOG_MEM8(OID, TRACE, &prNewKey->rKeyRSC, sizeof(PARAM_KEY_RSC)); + DBGLOG(OID, TRACE, "Key Material:\n"); + DBGLOG_MEM8(OID, TRACE, prNewKey->aucKeyMaterial, prNewKey->u4KeyLength); + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + prBssInfo = prAdapter->prAisBssInfo; + + if (prAdapter->rWifiVar.rConnSettings.eAuthMode >= AUTH_MODE_WPA && + prAdapter->rWifiVar.rConnSettings.eAuthMode != AUTH_MODE_WPA_NONE) { + if ((prNewKey->arBSSID[0] & prNewKey->arBSSID[1] & prNewKey->arBSSID[2] & + prNewKey->arBSSID[3] & prNewKey->arBSSID[4] & prNewKey->arBSSID[5]) == 0xFF) { + prStaRec = cnmGetStaRecByAddress(prAdapter, prBssInfo->ucBssIndex, prBssInfo->aucBSSID); + } else { + prStaRec = cnmGetStaRecByAddress(prAdapter, prBssInfo->ucBssIndex, prNewKey->arBSSID); + } + if (!prStaRec) { /* Already disconnected ? */ + DBGLOG(OID, INFO, "[wlan] Not set the WPA key while disconnect\n"); + return WLAN_STATUS_SUCCESS; + } + } + + prWlanTable = prAdapter->rWifiVar.arWtbl; + + prGlueInfo = prAdapter->prGlueInfo; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_802_11_KEY))); + + if (!prCmdInfo) { + DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + DBGLOG(OID, TRACE, "ucCmdSeqNum = %d\n", ucCmdSeqNum); + + /* compose CMD_802_11_KEY cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->ucBssIndex = prBssInfo->ucBssIndex; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_802_11_KEY); +#if CFG_SUPPORT_REPLAY_DETECTION + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetAddKey; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutSetAddKey; +#else + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; +#endif + 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 = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + 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); + kalMemCopy(prCmdKey->aucKeyRsc, (PUINT_8) & prNewKey->rKeyRSC, sizeof(PARAM_KEY_RSC)); + + prCmdKey->ucBssIdx = prBssInfo->ucBssIndex; /* AIS BSS */ + + 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) { + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + prCmdKey->ucAlgorithmId = CIPHER_SUITE_BIP; + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + prAisSpecBssInfo->fgBipKeyInstalled = TRUE; + } else +#endif + { + prCmdKey->ucAlgorithmId = CIPHER_SUITE_CCMP; + if (rsnCheckPmkidCandicate(prAdapter)) { + + DBGLOG(RSN, TRACE, + "Add key: Prepare a timer to indicate candidate PMKID Candidate\n"); + cnmTimerStopTimer(prAdapter, &prAisSpecBssInfo->rPreauthenticationTimer); + cnmTimerStartTimer(prAdapter, + &prAisSpecBssInfo->rPreauthenticationTimer, + SEC_TO_MSEC(WAIT_TIME_IND_PMKID_CANDICATE_SEC)); + } + } + } + + } else if (prNewKey->u4KeyLength == 32) { + if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA_NONE) { + if (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION2_ENABLED) + prCmdKey->ucAlgorithmId = CIPHER_SUITE_TKIP; + else if (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION3_ENABLED) { + prCmdKey->ucAlgorithmId = CIPHER_SUITE_CCMP; + prCmdKey->ucKeyLen = CCMP_KEY_LEN; + } + } else { + prCmdKey->ucAlgorithmId = CIPHER_SUITE_TKIP; + kalMemCopy(prAdapter->rWifiVar.rAisSpecificBssInfo.aucRxMicKey, + &prCmdKey->aucKeyMaterial[16], MIC_KEY_LEN); + kalMemCopy(prAdapter->rWifiVar.rAisSpecificBssInfo.aucTxMicKey, + &prCmdKey->aucKeyMaterial[24], MIC_KEY_LEN); + if (0 /* Todo::GCMP & GCMP-BIP ? */) { + if (rsnCheckPmkidCandicate(prAdapter)) { + + DBGLOG(RSN, TRACE, + "Add key: Prepare a timer to indicate candidate PMKID Candidate\n"); + cnmTimerStopTimer(prAdapter, &prAisSpecBssInfo->rPreauthenticationTimer); + cnmTimerStartTimer(prAdapter, + &prAisSpecBssInfo->rPreauthenticationTimer, + SEC_TO_MSEC(WAIT_TIME_IND_PMKID_CANDICATE_SEC)); + } + } else { + prCmdKey->ucAlgorithmId = CIPHER_SUITE_TKIP; + } + } + } + + { + if ((prCmdKey->aucPeerAddr[0] & prCmdKey->aucPeerAddr[1] & prCmdKey->aucPeerAddr[2] & prCmdKey-> + aucPeerAddr[3] & prCmdKey->aucPeerAddr[4] & prCmdKey->aucPeerAddr[5]) == 0xFF) { + if (prAdapter->rWifiVar.rConnSettings.eAuthMode >= AUTH_MODE_WPA + && prAdapter->rWifiVar.rConnSettings.eAuthMode != AUTH_MODE_WPA_NONE + && 1 /* Connected */) { + prStaRec = cnmGetStaRecByAddress(prAdapter, prBssInfo->ucBssIndex, prBssInfo->aucBSSID); + ASSERT(prStaRec); /* AIS RSN Group key, addr is BC addr */ + kalMemCopy(prCmdKey->aucPeerAddr, prStaRec->aucMacAddr, MAC_ADDR_LEN); + } else { + prStaRec = NULL; + } + } else { + prStaRec = cnmGetStaRecByAddress(prAdapter, prBssInfo->ucBssIndex, prCmdKey->aucPeerAddr); + } + +#if CFG_SUPPORT_TDLS + prTmpStaRec = cnmGetStaRecByAddress(prAdapter, prBssInfo->ucBssIndex, prNewKey->arBSSID); + if (prTmpStaRec) { + if (IS_DLS_STA(prTmpStaRec)) { + prStaRec = prTmpStaRec; + prCmdKey->ucAlgorithmId = CIPHER_SUITE_CCMP; /*128 ,TODO GCMP 256 */ + kalMemCopy(prCmdKey->aucPeerAddr, prStaRec->aucMacAddr, MAC_ADDR_LEN); + } + } +#endif + +#if CFG_SUPPORT_802_11W + if (prCmdKey->ucAlgorithmId == CIPHER_SUITE_BIP) { + ASSERT(prStaRec); + prCmdKey->ucWlanIndex = prStaRec->ucBMCWlanIndex; + /* prCmdKey->ucKeyId; */ + } else +#endif + if (prCmdKey->ucTxKey) { + if (prStaRec) { + if (prCmdKey->ucKeyType) { /* AIS RSN STA */ + prCmdKey->ucWlanIndex = prStaRec->ucWlanIndex; + prStaRec->fgTransmitKeyExist = TRUE; /* wait for CMD Done ? */ + } else { + ASSERT(FALSE); + /* prCmdKey->ucWlanIndex = */ + /* secPrivacySeekForBcEntry(prAdapter, */ + /* prBssInfo->ucBssIndex, */ + /* NETWORK_TYPE_AIS, */ + /* prCmdKey->aucPeerAddr, */ + /* prCmdKey->ucAlgorithmId, */ + /* prCmdKey->ucKeyId, */ + /* prStaRec->ucCurrentGtkId, */ + /* BIT(1)); */ + /* Todo:: Check the prCmdKey->ucKeyType */ + /* for some case, like wep, add bc wep key before sta create, */ + /* so use the rAisSpecificBssInfo to save key setting */ + fgAddTxBcKey = TRUE; + } + } + if (fgAddTxBcKey || !prStaRec) { + + if ((prCmdKey->aucPeerAddr[0] & prCmdKey->aucPeerAddr[1] & prCmdKey-> + aucPeerAddr[2] & prCmdKey->aucPeerAddr[3] & prCmdKey->aucPeerAddr[4] & prCmdKey-> + aucPeerAddr[5]) == 0xFF) { + prCmdKey->ucWlanIndex = 255; /* AIS WEP Tx key */ + } else { /* Exist this case ? */ + ASSERT(FALSE); + /* prCmdKey->ucWlanIndex = */ + /* secPrivacySeekForBcEntry(prAdapter, */ + /* prBssInfo->ucBssIndex, */ + /* NETWORK_TYPE_AIS, */ + /* prCmdKey->aucPeerAddr, */ + /* prCmdKey->ucAlgorithmId, */ + /* prCmdKey->ucKeyId, */ + /* prBssInfo->ucCurrentGtkId, */ + /* BIT(1)); */ + } + + prBssInfo->fgTxBcKeyExist = TRUE; + prBssInfo->ucBMCWlanIndex = prCmdKey->ucWlanIndex; /* Saved for AIS WEP */ + prBssInfo->ucTxDefaultKeyID = prCmdKey->ucKeyId; + + } + } else { + /* Including IBSS RSN Rx BC key ? */ + if ((prCmdKey->aucPeerAddr[0] & prCmdKey->aucPeerAddr[1] & prCmdKey->aucPeerAddr[2] & prCmdKey-> + aucPeerAddr[3] & prCmdKey->aucPeerAddr[4] & prCmdKey->aucPeerAddr[5]) == 0xFF) { + prCmdKey->ucWlanIndex = 255; /* AIS WEP */ + } else { + if (prStaRec) { /* AIS RSN Group key but addr is BSSID */ + ASSERT(prStaRec->ucBMCWlanIndex < WTBL_SIZE); + prCmdKey->ucWlanIndex = + secPrivacySeekForBcEntry(prAdapter, + prStaRec->ucBssIndex, + prStaRec->aucMacAddr, + prStaRec->ucIndex, + prCmdKey->ucAlgorithmId, + prCmdKey->ucKeyId, + prStaRec->ucCurrentGtkId, BIT(0)); + prStaRec->ucBMCWlanIndex = prCmdKey->ucWlanIndex; + } else { /* Exist this case ? */ + ASSERT(FALSE); + /* prCmdKey->ucWlanIndex = */ + /* secPrivacySeekForBcEntry(prAdapter, */ + /* prBssInfo->ucBssIndex, */ + /* NETWORK_TYPE_AIS, */ + /* prCmdKey->aucPeerAddr, */ + /* prCmdKey->ucAlgorithmId, */ + /* prCmdKey->ucKeyId, */ + /* prBssInfo->ucCurrentGtkId, */ + /* BIT(0)); */ + } + } + } + + /* Update Group Key Id after Seek Bc entry */ +#if CFG_SUPPORT_802_11W + if (prCmdKey->ucAlgorithmId == CIPHER_SUITE_BIP) + ; + else +#endif + if (!prCmdKey->ucKeyType) { + if (prStaRec) { + prStaRec->ucCurrentGtkId = prCmdKey->ucKeyId; + } else { + /* AIS WEP */ + prBssInfo->ucCurrentGtkId = prCmdKey->ucKeyId; + } + } +#if DBG && 0 + if (prCmdKey->ucWlanIndex < WTBL_SIZE) { + UINT_8 entry = prCmdKey->ucWlanIndex; + P_HAL_WTBL_SEC_CONFIG_T prWtblCfg; + BOOLEAN fgOneTb3 = FALSE; + + /* ASSERT(prWlanTable[prCmdKey->ucWlanIndex].ucUsed == TRUE); */ + /* prWlanTable[prCmdKey->ucWlanIndex].ucBssIndex = prCmdKey->ucBssIdx; */ + /* prWlanTable[prCmdKey->ucWlanIndex].ucKeyId = prCmdKey->ucKeyId; */ + /* kalMemCopy(prWlanTable[prCmdKey->ucWlanIndex].aucMacAddr, */ + /* prCmdKey->aucPeerAddr, */ + /* MAC_ADDR_LEN); */ + + prWtblCfg = prAdapter->rWifiVar.arWtblCfg; + + if (prCmdKey->ucAlgorithmId == CIPHER_SUITE_WEP40 + || prCmdKey->ucAlgorithmId == CIPHER_SUITE_WEP104 + || prCmdKey->ucAlgorithmId == CIPHER_SUITE_WEP128 + || prCmdKey->ucAlgorithmId == CIPHER_SUITE_WPI) + fgOneTb3 = TRUE; + + if (prCmdKey->ucTxKey) { + if (prStaRec) { + prWtblCfg[entry].fgRCA2 = 1; + prWtblCfg[entry].fgRV = 1; + prWtblCfg[entry].fgIKV = 0; + prWtblCfg[entry].fgRKV = 1; + if (fgOneTb3) + prWtblCfg[entry].fgRCID = 0; + else + prWtblCfg[entry].fgRCID = 1; + prWtblCfg[entry].ucKeyID = prCmdKey->ucKeyId; + prWtblCfg[entry].fgRCA1 = 1; +#if 0 + if (prCmdKey->ucIsAuthenticator) + prWtblCfg[entry].fgEvenPN = 0; + else +#endif + prWtblCfg[entry].fgEvenPN = 1; + prWtblCfg[entry].ucMUARIdx = 0x00; /* Omac */ + } else { +#if 0 + if (prCmdKey->ucIsAuthenticator) { + prWtblCfg[entry].fgRCA2 = 0; + prWtblCfg[entry].fgRV = 0; + prWtblCfg[entry].fgIKV = 0; + prWtblCfg[entry].fgRKV = 0; + prWtblCfg[entry].fgRCID = 0; + prWtblCfg[entry].ucKeyID = prCmdKey->ucKeyId; + prWtblCfg[entry].fgRCA1 = 0; + prWtblCfg[entry].fgEvenPN = 0; + } else +#endif + { + prWtblCfg[entry].fgRCA2 = 1; + prWtblCfg[entry].fgRV = 1; + prWtblCfg[entry].fgIKV = 0; + prWtblCfg[entry].fgRKV = 1; + + prCmdKey->ucTxKey = + ((prNewKey->u4KeyIndex & IS_TRANSMIT_KEY) == + IS_TRANSMIT_KEY) ? 1 : 0; + prCmdKey->ucKeyType = + ((prNewKey->u4KeyIndex & IS_UNICAST_KEY) == IS_UNICAST_KEY) ? 1 : 0; + + SetRCID(fgOneTb3, &prWtblCfg[entry].fgRCID); + /*AOSP*/ prWtblCfg[entry].ucKeyID = prCmdKey->ucKeyId; + prWtblCfg[entry].fgRCA1 = 0; + prWtblCfg[entry].fgEvenPN = 1; + } + } + } else { + prWtblCfg[entry].fgRCA2 = 1; + prWtblCfg[entry].fgRV = 1; + prWtblCfg[entry].fgIKV = 0; + prWtblCfg[entry].fgRKV = 1; + if (fgOneTb3) + prWtblCfg[entry].fgRCID = 0; + else + prWtblCfg[entry].fgRCID = 1; + prWtblCfg[entry].ucKeyID = prCmdKey->ucKeyId; + prWtblCfg[entry].fgRCA1 = 1; + prWtblCfg[entry].ucMUARIdx = 0x30; +#if 0 + if (prCmdKey->ucIsAuthenticator) + prWtblCfg[entry].fgEvenPN = 0; + else +#endif + prWtblCfg[entry].fgEvenPN = 1; + } + secPrivacyDumpWTBL3(prAdapter, entry); + } +#endif + } + + /* 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; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + P_WLAN_TABLE_T prWlanTable; + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prAisBssInfo; + + DEBUGFUNC("wlanoidSetRemoveKey"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + prAisBssInfo = prAdapter->prAisBssInfo; + + *pu4SetInfoLen = sizeof(PARAM_REMOVE_KEY_T); + + if (u4SetBufferLen < sizeof(PARAM_REMOVE_KEY_T)) + return WLAN_STATUS_INVALID_LENGTH; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in set remove key! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pvSetBuffer); + prRemovedKey = (P_PARAM_REMOVE_KEY_T) pvSetBuffer; + + /* Dump PARAM_REMOVE_KEY content. */ + DBGLOG(OID, TRACE, "Set: Dump PARAM_REMOVE_KEY content\n"); + DBGLOG(OID, TRACE, "Length : 0x%08x\n", prRemovedKey->u4Length); + DBGLOG(OID, TRACE, "Key Index : 0x%08x\n", prRemovedKey->u4KeyIndex); + DBGLOG(OID, TRACE, "BSSID:\n"); + DBGLOG_MEM8(OID, TRACE, prRemovedKey->arBSSID, MAC_ADDR_LEN); + + /* Check bit 31: this bit should always 0 */ + if (prRemovedKey->u4KeyIndex & IS_TRANSMIT_KEY) { + /* Bit 31 should not be set */ + DBGLOG(OID, ERROR, "invalid key index: 0x%08x\n", prRemovedKey->u4KeyIndex); + return WLAN_STATUS_INVALID_DATA; + } + + /* Check bits 8 ~ 29 should always be 0 */ + if (prRemovedKey->u4KeyIndex & BITS(8, 29)) { + /* Bit 31 should not be set */ + DBGLOG(OID, ERROR, "invalid key index: 0x%08x\n", prRemovedKey->u4KeyIndex); + return WLAN_STATUS_INVALID_DATA; + } + + prGlueInfo = prAdapter->prGlueInfo; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_802_11_KEY))); + + if (!prCmdInfo) { + DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + prWlanTable = prAdapter->rWifiVar.arWtbl; + + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_802_11_KEY cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + 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 = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + 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); + prCmdKey->ucBssIdx = prAdapter->prAisBssInfo->ucBssIndex; + +#if CFG_SUPPORT_802_11W + ASSERT(prCmdKey->ucKeyId < MAX_KEY_NUM + 2); +#else + /* ASSERT(prCmdKey->ucKeyId < MAX_KEY_NUM); */ +#endif + + /* Clean up the Tx key flag */ + prStaRec = cnmGetStaRecByAddress(prAdapter, prAdapter->prAisBssInfo->ucBssIndex, prRemovedKey->arBSSID); + + if (prRemovedKey->u4KeyIndex & IS_UNICAST_KEY) { + if (prStaRec) { + prCmdKey->ucKeyType = 1; + prCmdKey->ucWlanIndex = prStaRec->ucWlanIndex; + prStaRec->fgTransmitKeyExist = FALSE; + } else if (prCmdKey->ucKeyId == prAdapter->prAisBssInfo->ucTxDefaultKeyID) + prAdapter->prAisBssInfo->fgTxBcKeyExist = FALSE; + } else { + if (prCmdKey->ucKeyId == prAdapter->prAisBssInfo->ucTxDefaultKeyID) + prAdapter->prAisBssInfo->fgTxBcKeyExist = FALSE; + } + + if (!prStaRec) { + if (prAdapter->rWifiVar.rConnSettings.eAuthMode < AUTH_MODE_WPA) + prCmdKey->ucWlanIndex = prAdapter->prAisBssInfo->ucBMCWlanIndex; + else { + prCmdKey->ucWlanIndex = WTBL_RESERVED_ENTRY; + /* ASSERT(FALSE); */ + } + } + + if (prCmdKey->ucAlgorithmId == CIPHER_SUITE_WEP40 + || prCmdKey->ucAlgorithmId == CIPHER_SUITE_WEP104) { + /* if (prAdapter->prAisBssInfo->ucTxDefaultKeyID == prCmdKey->ucKeyId) */ + /* secPrivacyFreeForEntry(prAdapter, prCmdKey->ucWlanIndex); */ + /* else */ + /* ; Clear key material only */ + } else { + DBGLOG(RSN, TRACE, "wlanoidSetRemoveKey\n"); + if (prAisBssInfo->eConnectionState != PARAM_MEDIA_STATE_CONNECTED) + secPrivacyFreeForEntry(prAdapter, prCmdKey->ucWlanIndex); + } + + if (prCmdKey->ucKeyId < 4) { /* BIP */ + /* kalMemZero(prAisSpecBssInfo->aucKeyMaterial[prCmdKey->ucKeyId], 16); */ + } + /* 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->prAisBssInfo->fgTxBcKeyExist; + + 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; + 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(OID, ERROR, "Unknown Encryption Status Setting:%d\n", + prAdapter->rWifiVar.rConnSettings.eEncStatus); + } + +#if DBG + DBGLOG(OID, INFO, + "Encryption status: %d Return:%d\n", prAdapter->rWifiVar.rConnSettings.eEncStatus, eEncStatus); +#endif + + *(P_ENUM_PARAM_ENCRYPTION_STATUS_T) pvQueryBuffer = eEncStatus; + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryEncryptionStatus */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the encryption status to the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_NOT_SUPPORTED +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetEncryptionStatus(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + ENUM_PARAM_ENCRYPTION_STATUS_T eEewEncrypt; + + DEBUGFUNC("wlanoidSetEncryptionStatus"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prGlueInfo = prAdapter->prGlueInfo; + + *pu4SetInfoLen = sizeof(ENUM_PARAM_ENCRYPTION_STATUS_T); + + /* if (IS_ARB_IN_RFTEST_STATE(prAdapter)) { */ + /* return WLAN_STATUS_SUCCESS; */ + /* } */ + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in set encryption status! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + eEewEncrypt = *(P_ENUM_PARAM_ENCRYPTION_STATUS_T) pvSetBuffer; + DBGLOG(OID, TRACE, "ENCRYPTION_STATUS %d\n", eEewEncrypt); + + switch (eEewEncrypt) { + case ENUM_ENCRYPTION_DISABLED: /* Disable WEP, TKIP, AES */ + DBGLOG(RSN, TRACE, "Disable Encryption\n"); + secSetCipherSuite(prAdapter, CIPHER_FLAG_WEP40 | CIPHER_FLAG_WEP104 | CIPHER_FLAG_WEP128); + break; + + case ENUM_ENCRYPTION1_ENABLED: /* Enable WEP. Disable TKIP, AES */ + DBGLOG(RSN, TRACE, "Enable Encryption1\n"); + secSetCipherSuite(prAdapter, CIPHER_FLAG_WEP40 | CIPHER_FLAG_WEP104 | CIPHER_FLAG_WEP128); + break; + + case ENUM_ENCRYPTION2_ENABLED: /* Enable WEP, TKIP. Disable AES */ + secSetCipherSuite(prAdapter, + CIPHER_FLAG_WEP40 | CIPHER_FLAG_WEP104 | CIPHER_FLAG_WEP128 | CIPHER_FLAG_TKIP); + DBGLOG(RSN, TRACE, "Enable Encryption2\n"); + break; + + case ENUM_ENCRYPTION3_ENABLED: /* Enable WEP, TKIP, AES */ + secSetCipherSuite(prAdapter, + CIPHER_FLAG_WEP40 | + CIPHER_FLAG_WEP104 | CIPHER_FLAG_WEP128 | CIPHER_FLAG_TKIP | CIPHER_FLAG_CCMP); + DBGLOG(RSN, TRACE, "Enable Encryption3\n"); + break; + + default: + DBGLOG(RSN, WARN, "Unacceptible encryption status: %d\n", + *(P_ENUM_PARAM_ENCRYPTION_STATUS_T) pvSetBuffer); + + rStatus = WLAN_STATUS_NOT_SUPPORTED; + } + + if (rStatus == WLAN_STATUS_SUCCESS) { + /* Save the new encryption status. */ + prAdapter->rWifiVar.rConnSettings.eEncStatus = *(P_ENUM_PARAM_ENCRYPTION_STATUS_T) pvSetBuffer; + } + + return rStatus; +} /* wlanoidSetEncryptionStatus */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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 = 0; + P_PARAM_PMKID_T prPmkid; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + DEBUGFUNC("wlanoidSetPmkid"); + + DBGLOG(OID, TRACE, "wlanoidSetPmkid\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = u4SetBufferLen; + + /* It's possibble BSSIDInfoCount is zero, because OS wishes to clean PMKID */ + if (u4SetBufferLen < OFFSET_OF(PARAM_PMKID_T, arBSSIDInfo)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + ASSERT(pvSetBuffer); + prPmkid = (P_PARAM_PMKID_T) pvSetBuffer; + + if (u4SetBufferLen < + ((prPmkid->u4BSSIDInfoCount * sizeof(PARAM_BSSID_INFO_T)) + OFFSET_OF(PARAM_PMKID_T, arBSSIDInfo))) + return WLAN_STATUS_INVALID_DATA; + + if (prPmkid->u4BSSIDInfoCount > CFG_MAX_PMKID_CACHE) + return WLAN_STATUS_INVALID_DATA; + + DBGLOG(OID, TRACE, "Count %u\n", prPmkid->u4BSSIDInfoCount); + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + /* This OID replace everything in the PMKID cache. */ + if (prPmkid->u4BSSIDInfoCount == 0) { + prAisSpecBssInfo->u4PmkidCacheCount = 0; + kalMemZero(prAisSpecBssInfo->arPmkidCache, sizeof(PMKID_ENTRY_T) * CFG_MAX_PMKID_CACHE); + } + if ((prAisSpecBssInfo->u4PmkidCacheCount + prPmkid->u4BSSIDInfoCount > CFG_MAX_PMKID_CACHE)) { + prAisSpecBssInfo->u4PmkidCacheCount = 0; + kalMemZero(prAisSpecBssInfo->arPmkidCache, sizeof(PMKID_ENTRY_T) * CFG_MAX_PMKID_CACHE); + } + + /* + * The driver can only clear its PMKID cache whenever it make a media disconnect + * indication. Otherwise, it must change the PMKID cache only when set through this OID. + */ + 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) { + 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=%u PMKID value " MACSTR "\n", + MAC2STR(prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arBSSID), j, + MAC2STR(prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arPMKID)); + prAisSpecBssInfo->arPmkidCache[j].fgPmkidExist = TRUE; + } + } + if (prAdapter->rWifiVar.rConnSettings.fgOkcEnabled) { + P_BSS_DESC_T prBssDesc = prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc; + P_UINT_8 pucPmkID = NULL; + + if (prPmkid->u4Length & BIT(31)) { + /* the case that force add pmkid for target Bss Descriptor + ** see mtk_cfg80211_connect + */ + if (j == CFG_MAX_PMKID_CACHE) { + j = 0; + kalMemCopy(prAisSpecBssInfo->arPmkidCache[0].rBssidInfo.arBSSID, + prPmkid->arBSSIDInfo[0].arBSSID, sizeof(PARAM_MAC_ADDRESS)); + kalMemCopy(prAisSpecBssInfo->arPmkidCache[0].rBssidInfo.arPMKID, + prPmkid->arBSSIDInfo[0].arPMKID, sizeof(PARAM_PMKID_VALUE)); + prAisSpecBssInfo->arPmkidCache[0].fgPmkidExist = TRUE; + } + pucPmkID = prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arPMKID; + DBGLOG(RSN, INFO, + "set by connect, %pM OKC PMKID %02x%02x%02x%02x%02x%02x%02x%02x...\n", + prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arBSSID, + pucPmkID[0], pucPmkID[1], pucPmkID[2], pucPmkID[3], + pucPmkID[4], pucPmkID[5], pucPmkID[6], pucPmkID[7]); + aisFsmRunEventSetOkcPmk(prAdapter); + } else if (prBssDesc && rsnSearchPmkidEntry(prAdapter, (PUINT_8)prBssDesc->aucBSSID, &j)) { + /* the case that normally add pmkid, but just match with target Bss Descriptor */ + pucPmkID = prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arPMKID; + DBGLOG(RSN, INFO, + "%pM OKC PMKID %02x%02x%02x%02x%02x%02x%02x%02x...\n", + prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arBSSID, + pucPmkID[0], pucPmkID[1], pucPmkID[2], pucPmkID[3], + pucPmkID[4], pucPmkID[5], pucPmkID[6], pucPmkID[7]); + aisFsmRunEventSetOkcPmk(prAdapter); + } + } + + return WLAN_STATUS_SUCCESS; + +} /* wlanoidSetPmkid */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the set of supported data rates that +* the radio is capable of running +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query +* \param[in] u4QueryBufferLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number +* of bytes written into the query buffer. If the +* call failed due to invalid length of the query +* buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQuerySupportedRates(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + PARAM_RATES eRate = { + /* BSSBasicRateSet for 802.11n Non-HT rates */ + 0x8C, /* 6M */ + 0x92, /* 9M */ + 0x98, /* 12M */ + 0xA4, /* 18M */ + 0xB0, /* 24M */ + 0xC8, /* 36M */ + 0xE0, /* 48M */ + 0xEC /* 54M */ + }; + + DEBUGFUNC("wlanoidQuerySupportedRates"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_RATES_EX); + + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + kalMemCopy(pvQueryBuffer, (PVOID) &eRate, sizeof(PARAM_RATES)); + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidQuerySupportedRates() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query current desired rates. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryDesiredRates(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryDesiredRates"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_RATES_EX); + + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + kalMemCopy(pvQueryBuffer, (PVOID) &(prAdapter->rWlanInfo.eDesiredRates), sizeof(PARAM_RATES)); + + return WLAN_STATUS_SUCCESS; + +} /* end of wlanoidQueryDesiredRates() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set the desired rates. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetDesiredRates(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + UINT_32 i; + + DEBUGFUNC("wlanoidSetDesiredRates"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(PARAM_RATES)) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = sizeof(PARAM_RATES); + + if (u4SetBufferLen < sizeof(PARAM_RATES)) + return WLAN_STATUS_INVALID_LENGTH; + + kalMemCopy((PVOID) &(prAdapter->rWlanInfo.eDesiredRates), pvSetBuffer, sizeof(PARAM_RATES)); + + prAdapter->rWlanInfo.eLinkAttr.ucDesiredRateLen = PARAM_MAX_LEN_RATES; + for (i = 0; i < PARAM_MAX_LEN_RATES; i++) + prAdapter->rWlanInfo.eLinkAttr.u2DesiredRate[i] = (UINT_16) (prAdapter->rWlanInfo.eDesiredRates[i]); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_LINK_ATTRIB, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_LINK_ATTRIB), + (PUINT_8) &(prAdapter->rWlanInfo.eLinkAttr), pvSetBuffer, u4SetBufferLen); + +} /* end of wlanoidSetDesiredRates() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the maximum frame size in bytes, +* not including the header. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the +* call failed due to invalid length of the query +* buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMaxFrameSize(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryMaxFrameSize"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_INVALID_LENGTH; + } + + *(PUINT_32) pvQueryBuffer = ETHERNET_MAX_PKT_SZ - ETHERNET_HEADER_SZ; + *pu4QueryInfoLen = sizeof(UINT_32); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryMaxFrameSize */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the maximum total packet length +* in bytes. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMaxTotalSize(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryMaxTotalSize"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_INVALID_LENGTH; + } + + *(PUINT_32) pvQueryBuffer = ETHERNET_MAX_PKT_SZ; + *pu4QueryInfoLen = sizeof(UINT_32); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryMaxTotalSize */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the vendor ID of the NIC. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryVendorId(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ +#if DBG + PUINT_8 cp; +#endif + DEBUGFUNC("wlanoidQueryVendorId"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_INVALID_LENGTH; + } + + kalMemCopy(pvQueryBuffer, prAdapter->aucMacAddress, 3); + *((PUINT_8) pvQueryBuffer + 3) = 1; + *pu4QueryInfoLen = sizeof(UINT_32); + +#if DBG + cp = (PUINT_8) pvQueryBuffer; + DBGLOG(OID, LOUD, "Vendor ID=%02x-%02x-%02x-%02x\n", cp[0], cp[1], cp[2], cp[3]); +#endif + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryVendorId */ + +WLAN_STATUS +wlanoidRssiMonitor(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + PARAM_RSSI_MONITOR_T rRssi; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_RSSI_MONITOR_T); + + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(OID, WARN, "Too short length %u\n", u4QueryBufferLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + kalMemZero(&rRssi, sizeof(PARAM_RSSI_MONITOR_T)); +#if 0 + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_DISCONNECTED) + return WLAN_STATUS_ADAPTER_NOT_READY; +#endif + kalMemCopy(&rRssi, pvQueryBuffer, sizeof(PARAM_RSSI_MONITOR_T)); + if (rRssi.enable) { + if (rRssi.max_rssi_value > PARAM_WHQL_RSSI_MAX_DBM) + rRssi.max_rssi_value = PARAM_WHQL_RSSI_MAX_DBM; + if (rRssi.min_rssi_value < -120) + rRssi.min_rssi_value = -120; + } else { + rRssi.max_rssi_value = 0; + rRssi.min_rssi_value = 0; + } + + DBGLOG(OID, INFO, "enable=%d, max_rssi_value=%d, min_rssi_value=%d\n", + rRssi.enable, rRssi.max_rssi_value, rRssi.min_rssi_value); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_RSSI_MONITOR, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(PARAM_RSSI_MONITOR_T), (PUINT_8)&rRssi, NULL, 0); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current RSSI value. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call failed due to invalid length of +* the query buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRssi(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryRssi"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_RSSI); + + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(OID, WARN, "Too short length %u\n", u4QueryBufferLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_DISCONNECTED) { + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (prAdapter->fgIsLinkQualityValid == TRUE && + (kalGetTimeTick() - prAdapter->rLinkQualityUpdateTime) <= CFG_LINK_QUALITY_VALID_PERIOD) { + PARAM_RSSI rRssi; + + rRssi = (PARAM_RSSI) prAdapter->rLinkQuality.cRssi; /* ranged from (-128 ~ 30) in unit of dBm */ + + if (rRssi > PARAM_WHQL_RSSI_MAX_DBM) + rRssi = PARAM_WHQL_RSSI_MAX_DBM; + else if (rRssi < PARAM_WHQL_RSSI_MIN_DBM) + rRssi = PARAM_WHQL_RSSI_MIN_DBM; + + kalMemCopy(pvQueryBuffer, &rRssi, sizeof(PARAM_RSSI)); + return WLAN_STATUS_SUCCESS; + } +#ifdef LINUX + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryLinkQuality, + nicOidCmdTimeoutCommon, + *pu4QueryInfoLen, pvQueryBuffer, pvQueryBuffer, u4QueryBufferLen); +#else + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryLinkQuality, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + +#endif +} /* end of wlanoidQueryRssi() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current RSSI trigger value. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call failed due to invalid length of +* the query buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRssiTrigger(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryRssiTrigger"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (prAdapter->rWlanInfo.eRssiTriggerType == ENUM_RSSI_TRIGGER_NONE) + return WLAN_STATUS_ADAPTER_NOT_READY; + + *pu4QueryInfoLen = sizeof(PARAM_RSSI); + + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(OID, WARN, "Too short length %u\n", u4QueryBufferLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + *(PARAM_RSSI *) pvQueryBuffer = prAdapter->rWlanInfo.rRssiTriggerValue; + DBGLOG(OID, INFO, "RSSI trigger: %d dBm\n", *(PARAM_RSSI *) pvQueryBuffer); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryRssiTrigger */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a trigger value of the RSSI event. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns the +* amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetRssiTrigger(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PARAM_RSSI rRssiTriggerValue; + + DEBUGFUNC("wlanoidSetRssiTrigger"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_RSSI); + rRssiTriggerValue = *(PARAM_RSSI *) pvSetBuffer; + + if (rRssiTriggerValue > PARAM_WHQL_RSSI_MAX_DBM || rRssiTriggerValue < PARAM_WHQL_RSSI_MIN_DBM) + return + /* Save the RSSI trigger value to the Adapter structure */ + prAdapter->rWlanInfo.rRssiTriggerValue = rRssiTriggerValue; + + /* + * If the RSSI trigger value is equal to the current RSSI value, the + * indication triggers immediately. We need to indicate the protocol + * that an RSSI status indication event triggers. + */ + if (rRssiTriggerValue == (PARAM_RSSI) (prAdapter->rLinkQuality.cRssi)) { + prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_TRIGGERED; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID) &prAdapter->rWlanInfo.rRssiTriggerValue, sizeof(PARAM_RSSI)); + } else if (rRssiTriggerValue < (PARAM_RSSI) (prAdapter->rLinkQuality.cRssi)) + prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_GREATER; + else if (rRssiTriggerValue > (PARAM_RSSI) (prAdapter->rLinkQuality.cRssi)) + prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_LESS; + + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetRssiTrigger */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a suggested value for the number of +* bytes of received packet data that will be indicated to the protocol +* driver. We just accept the set and ignore this value. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetCurrentLookahead(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + DEBUGFUNC("wlanoidSetCurrentLookahead"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(UINT_32)) { + *pu4SetInfoLen = sizeof(UINT_32); + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = sizeof(UINT_32); + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetCurrentLookahead */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of frames that the driver +* receives but does not indicate to the protocols due to errors. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRcvError(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryRcvError"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + /* @FIXME, RX_ERROR_DROP_COUNT/RX_FIFO_FULL_DROP_COUNT is not calculated */ + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rFCSErrorCount.QuadPart; + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rFCSErrorCount.QuadPart; + } + + } else +#endif + { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryRecvError, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + } + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryRcvError */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the number of frames that the NIC +* cannot receive due to lack of NIC receive buffer space. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS If success; +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRcvNoBuffer(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryRcvNoBuffer"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) 0; /* @FIXME */ + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) 0; /* @FIXME */ + } + + } else +#endif + { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryRecvNoBuffer, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + } + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryRcvNoBuffer */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the number of frames that the NIC +* received and it is CRC error. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS If success; +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRcvCrcError(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryRcvCrcError"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rFCSErrorCount.QuadPart; + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rFCSErrorCount.QuadPart; + } + + } else +#endif + { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryRecvCrcError, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + } + return WLAN_STATUS_SUCCESS; +} /* 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) +{ + return wlanQueryStatistics(prAdapter, pvQueryBuffer, u4QueryBufferLen, pu4QueryInfoLen, TRUE); + +} /* wlanoidQueryStatistics */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query current media streaming status. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMediaStreamMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryMediaStreamMode"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(ENUM_MEDIA_STREAM_MODE); + + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + *(P_ENUM_MEDIA_STREAM_MODE) pvQueryBuffer = + prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode == 0 ? ENUM_MEDIA_STREAM_OFF : ENUM_MEDIA_STREAM_ON; + + return WLAN_STATUS_SUCCESS; + +} /* wlanoidQueryMediaStreamMode */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to enter media streaming mode or exit media streaming mode +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetMediaStreamMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + ENUM_MEDIA_STREAM_MODE eStreamMode; + + DEBUGFUNC("wlanoidSetMediaStreamMode"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(ENUM_MEDIA_STREAM_MODE)) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = sizeof(ENUM_MEDIA_STREAM_MODE); + + eStreamMode = *(P_ENUM_MEDIA_STREAM_MODE) pvSetBuffer; + + if (eStreamMode == ENUM_MEDIA_STREAM_OFF) + prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode = 0; + else + prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode = 1; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_LINK_ATTRIB, + TRUE, + FALSE, + TRUE, + nicCmdEventSetMediaStreamMode, + nicOidCmdTimeoutCommon, + sizeof(CMD_LINK_ATTRIB), + (PUINT_8) &(prAdapter->rWlanInfo.eLinkAttr), pvSetBuffer, u4SetBufferLen); +} /* wlanoidSetMediaStreamMode */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the permanent MAC address of the NIC. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryPermanentAddr(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryPermanentAddr"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < MAC_ADDR_LEN) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + COPY_MAC_ADDR(pvQueryBuffer, prAdapter->rWifiVar.aucPermanentAddress); + *pu4QueryInfoLen = MAC_ADDR_LEN; + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryPermanentAddr */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the MAC address the NIC is currently using. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryCurrentAddr(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryCurrentAddr"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < MAC_ADDR_LEN) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + COPY_MAC_ADDR(pvQueryBuffer, prAdapter->rWifiVar.aucMacAddress); + *pu4QueryInfoLen = MAC_ADDR_LEN; + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryCurrentAddr */ + +#if CFG_SUPPORT_ANT_SWAP +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query antenna swap capability.. +* +* \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 +wlanoidQueryAntSwapCapability(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryAntSwapCapability"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *((PUINT32)pvQueryBuffer) = (UINT_32)prAdapter->fgIsAntSwpSupport; + *pu4QueryInfoLen = sizeof(UINT_32); + + DBGLOG(INIT, TRACE, "AntSwapCapability Query(%u)-len(%u)\n", + *((PUINT32)pvQueryBuffer), *pu4QueryInfoLen); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryAntSwapCapability */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query NIC link speed. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryLinkSpeed(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryLinkSpeed"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(UINT_32); + + if (u4QueryBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) { + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (prAdapter->fgIsLinkRateValid == TRUE && + (kalGetTimeTick() - prAdapter->rLinkRateUpdateTime) <= CFG_LINK_QUALITY_VALID_PERIOD) { + *(PUINT_32) pvQueryBuffer = prAdapter->rLinkQuality.u2LinkSpeed * 5000; /* change to unit of 100bps */ + return WLAN_STATUS_SUCCESS; + } else { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryLinkSpeed, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + } +} /* end of wlanoidQueryLinkSpeed() */ + +#if CFG_SUPPORT_QA_TOOL +#if CFG_SUPPORT_BUFFER_MODE +WLAN_STATUS +wlanoidSetEfusBufferMode(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_EFUSE_BUFFER_MODE_T prSetEfuseBufModeInfo; + P_PARAM_CUSTOM_EFUSE_BUFFER_MODE_1_T prSetEfuseBufModeInfo_1; + CMD_EFUSE_BUFFER_MODE_T rCmdSetEfuseBufModeInfo; + CMD_EFUSE_BUFFER_MODE_1_T rCmdSetEfuseBufModeInfo_1; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidSetEfusBufferMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (prAdapter->rWifiVar.ucEfuseBufferModeCal == TRUE) { /* structure for MT7668 */ + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_1_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_1_T)) + return WLAN_STATUS_INVALID_LENGTH; + + } else { + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T)) + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvSetBuffer); + + if (prAdapter->rWifiVar.ucEfuseBufferModeCal == TRUE) { /* structure for MT7668 */ + prSetEfuseBufModeInfo_1 = (P_PARAM_CUSTOM_EFUSE_BUFFER_MODE_1_T) pvSetBuffer; + } else { + prSetEfuseBufModeInfo = (P_PARAM_CUSTOM_EFUSE_BUFFER_MODE_T) pvSetBuffer; + } + + if (prAdapter->rWifiVar.ucEfuseBufferModeCal == TRUE) { /* structure for MT7668 */ + + rCmdSetEfuseBufModeInfo_1.ucSourceMode = prSetEfuseBufModeInfo_1->ucSourceMode; + rCmdSetEfuseBufModeInfo_1.ucCount = prSetEfuseBufModeInfo_1->ucCount; + rCmdSetEfuseBufModeInfo_1.ucCmdType = prSetEfuseBufModeInfo_1->ucCmdType; + rCmdSetEfuseBufModeInfo_1.ucReserved = prSetEfuseBufModeInfo_1->ucReserved; + + /* kalMemCopy(rCmdSetEfuseBufModeInfo.aBinContent, prSetEfuseBufModeInfo->aBinContent, */ + /* sizeof(BIN_CONTENT_T) * EFUSE_CONTENT_SIZE); */ + + kalMemCopy(rCmdSetEfuseBufModeInfo_1.aBinContent, prSetEfuseBufModeInfo_1->aBinContent, + sizeof(UINT_8) * EFUSE_CONTENT_SIZE_1); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_EFUSE_BUFFER_MODE, + FALSE, + TRUE, + TRUE, + NULL, /* No Tx done function wait until fw ack */ + nicOidCmdTimeoutCommon, + sizeof(CMD_EFUSE_BUFFER_MODE_1_T), + (PUINT_8) (&rCmdSetEfuseBufModeInfo_1), + pvSetBuffer, u4SetBufferLen); + } else{ + rCmdSetEfuseBufModeInfo.ucSourceMode = prSetEfuseBufModeInfo->ucSourceMode; + rCmdSetEfuseBufModeInfo.ucCount = prSetEfuseBufModeInfo->ucCount; + rCmdSetEfuseBufModeInfo.ucReserved[0] = prSetEfuseBufModeInfo->ucReserved[0]; + rCmdSetEfuseBufModeInfo.ucReserved[1] = prSetEfuseBufModeInfo->ucReserved[1]; + kalMemCopy(rCmdSetEfuseBufModeInfo.aBinContent, prSetEfuseBufModeInfo->aBinContent, + sizeof(BIN_CONTENT_T) * EFUSE_CONTENT_SIZE); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_EFUSE_BUFFER_MODE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_EFUSE_BUFFER_MODE_T), + (PUINT_8) (&rCmdSetEfuseBufModeInfo), + pvSetBuffer, u4SetBufferLen); + } + + return rWlanStatus; +} + +/*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to read efuse content. +* +* \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 +wlanoidQueryProcessAccessEfuseRead(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_ACCESS_EFUSE_T prSetAccessEfuseInfo; + CMD_ACCESS_EFUSE_T rCmdSetAccessEfuse; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryProcessAccessEfuseRead"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(P_PARAM_CUSTOM_ACCESS_EFUSE_T); + + if (u4SetBufferLen < sizeof(P_PARAM_CUSTOM_ACCESS_EFUSE_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prSetAccessEfuseInfo = (P_PARAM_CUSTOM_ACCESS_EFUSE_T) pvSetBuffer; + + kalMemSet(&rCmdSetAccessEfuse, 0, sizeof(CMD_ACCESS_EFUSE_T)); + + rCmdSetAccessEfuse.u4Address = prSetAccessEfuseInfo->u4Address; + rCmdSetAccessEfuse.u4Valid = prSetAccessEfuseInfo->u4Valid; + + + DBGLOG(INIT, INFO, "wlanoidQueryProcessAccessEfuseRead, address=%d\n", rCmdSetAccessEfuse.u4Address); + + kalMemCopy(rCmdSetAccessEfuse.aucData, prSetAccessEfuseInfo->aucData, + sizeof(UINT_8) * 16); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_EFUSE_ACCESS, + FALSE, /* Query Bit: True->write False->read*/ + TRUE, + TRUE, + NULL, /* No Tx done function wait until fw ack */ + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_EFUSE_T), + (PUINT_8) (&rCmdSetAccessEfuse), pvSetBuffer, u4SetBufferLen); + + return rWlanStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to write efuse content. +* +* \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 +wlanoidQueryProcessAccessEfuseWrite(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_ACCESS_EFUSE_T prSetAccessEfuseInfo; + CMD_ACCESS_EFUSE_T rCmdSetAccessEfuse; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryProcessAccessEfuseWrite"); + DBGLOG(INIT, INFO, "wlanoidQueryProcessAccessEfuseWrite\n"); + + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(P_PARAM_CUSTOM_ACCESS_EFUSE_T); + + if (u4SetBufferLen < sizeof(P_PARAM_CUSTOM_ACCESS_EFUSE_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prSetAccessEfuseInfo = (P_PARAM_CUSTOM_ACCESS_EFUSE_T) pvSetBuffer; + + kalMemSet(&rCmdSetAccessEfuse, 0, sizeof(CMD_ACCESS_EFUSE_T)); + + rCmdSetAccessEfuse.u4Address = prSetAccessEfuseInfo->u4Address; + rCmdSetAccessEfuse.u4Valid = prSetAccessEfuseInfo->u4Valid; + + DBGLOG(INIT, INFO, "wlanoidQueryProcessAccessEfuseWrite, address=%d\n", rCmdSetAccessEfuse.u4Address); + + + kalMemCopy(rCmdSetAccessEfuse.aucData, prSetAccessEfuseInfo->aucData, + sizeof(UINT_8) * 16); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_EFUSE_ACCESS, + TRUE, /* Query Bit: True->write False->read*/ + TRUE, + TRUE, + NULL, /* No Tx done function wait until fw ack */ + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_EFUSE_T), + (PUINT_8) (&rCmdSetAccessEfuse), pvSetBuffer, u4SetBufferLen); + + return rWlanStatus; +} + + + + +WLAN_STATUS +wlanoidQueryEfuseFreeBlock(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_EFUSE_FREE_BLOCK_T prGetEfuseFreeBlockInfo; + CMD_EFUSE_FREE_BLOCK_T rCmdGetEfuseFreeBlock; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryEfuseFreeBlock"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(P_PARAM_CUSTOM_EFUSE_FREE_BLOCK_T); + + if (u4SetBufferLen < sizeof(P_PARAM_CUSTOM_EFUSE_FREE_BLOCK_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prGetEfuseFreeBlockInfo = (P_PARAM_CUSTOM_EFUSE_FREE_BLOCK_T) pvSetBuffer; + + kalMemSet(&rCmdGetEfuseFreeBlock, 0, sizeof(CMD_EFUSE_FREE_BLOCK_T)); + + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_EFUSE_FREE_BLOCK, + TRUE, /* Query Bit: True->write False->read*/ + TRUE, + TRUE, + NULL, /* No Tx done function wait until fw ack */ + nicOidCmdTimeoutCommon, + sizeof(CMD_EFUSE_FREE_BLOCK_T), + (PUINT_8) (&rCmdGetEfuseFreeBlock), pvSetBuffer, u4SetBufferLen); + + return rWlanStatus; +} + +/*#endif*/ + +#endif /* CFG_SUPPORT_BUFFER_MODE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query RX statistics. +* +* \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 +wlanoidQueryRxStatistics(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_CUSTOM_ACCESS_RX_STAT prRxStatistics; + P_CMD_ACCESS_RX_STAT prCmdAccessRxStat; + CMD_ACCESS_RX_STAT rCmdAccessRxStat; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; +/* UINT_32 u4MemSize = PARAM_MEM_DUMP_MAX_SIZE; */ + UINT_32 u4SeqNum = 0; + UINT_32 u4TotalNum = 0; + + prCmdAccessRxStat = &rCmdAccessRxStat; + + DEBUGFUNC("wlanoidQueryRxStatistics"); + DBGLOG(INIT, LOUD, "\n"); + + DBGLOG(INIT, ERROR, "wlanoidQueryRxStatistics\n"); + + prRxStatistics = (P_PARAM_CUSTOM_ACCESS_RX_STAT) pvQueryBuffer; + + *pu4QueryInfoLen = 8 + prRxStatistics->u4TotalNum; + + u4SeqNum = prRxStatistics->u4SeqNum; + u4TotalNum = prRxStatistics->u4TotalNum; + + do { + prCmdAccessRxStat->u4SeqNum = u4SeqNum; + prCmdAccessRxStat->u4TotalNum = u4TotalNum; + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_RX_STAT, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryRxStatistics, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_RX_STAT), + (PUINT_8) prCmdAccessRxStat, pvQueryBuffer, u4QueryBufferLen); + } while (FALSE); + + return rStatus; +} + +#if CFG_SUPPORT_TX_BF + +WLAN_STATUS +wlanoidStaRecUpdate(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_CMD_STAREC_UPDATE_T prStaRecUpdateInfo; + P_CMD_STAREC_COMMON_T prStaRecCmm; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidStaRecUpdate"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(CMD_STAREC_COMMON_T); + if (u4SetBufferLen < sizeof(CMD_STAREC_COMMON_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prStaRecUpdateInfo = + (P_CMD_STAREC_UPDATE_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, (CMD_STAREC_UPDATE_HDR_SIZE + u4SetBufferLen)); + if (!prStaRecUpdateInfo) { + DBGLOG(INIT, ERROR, "Allocate P_CMD_DEV_INFO_UPDATE_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* fix me: configurable ucBssIndex */ + prStaRecCmm = (P_CMD_STAREC_COMMON_T) pvSetBuffer; + prStaRecUpdateInfo->ucBssIndex = 0; + prStaRecUpdateInfo->ucWlanIdx = prStaRecCmm->u2Reserve1; + prStaRecUpdateInfo->u2TotalElementNum = 1; + kalMemCopy(prStaRecUpdateInfo->aucBuffer, pvSetBuffer, u4SetBufferLen); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_STAREC_UPDATE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + (CMD_STAREC_UPDATE_HDR_SIZE + u4SetBufferLen), + (PUINT_8) prStaRecUpdateInfo, NULL, 0); + + cnmMemFree(prAdapter, prStaRecUpdateInfo); + + return rWlanStatus; +} + +WLAN_STATUS +wlanoidStaRecBFUpdate(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_CMD_STAREC_UPDATE_T prStaRecUpdateInfo; + P_CMD_STAREC_BF prStaRecBF; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidStaRecBFUpdate"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(CMD_STAREC_BF); + if (u4SetBufferLen < sizeof(CMD_STAREC_BF)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prStaRecUpdateInfo = + (P_CMD_STAREC_UPDATE_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, (CMD_STAREC_UPDATE_HDR_SIZE + u4SetBufferLen)); + if (!prStaRecUpdateInfo) { + DBGLOG(INIT, ERROR, "Allocate P_CMD_DEV_INFO_UPDATE_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* fix me: configurable ucBssIndex */ + prStaRecBF = (P_CMD_STAREC_BF) pvSetBuffer; + prStaRecUpdateInfo->ucBssIndex = prStaRecBF->ucReserved[0]; + prStaRecUpdateInfo->ucWlanIdx = prStaRecBF->ucReserved[1]; + prStaRecUpdateInfo->u2TotalElementNum = 1; + kalMemCopy(prStaRecUpdateInfo->aucBuffer, pvSetBuffer, u4SetBufferLen); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_STAREC_UPDATE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + (CMD_STAREC_UPDATE_HDR_SIZE + u4SetBufferLen), + (PUINT_8) prStaRecUpdateInfo, NULL, 0); + + cnmMemFree(prAdapter, prStaRecUpdateInfo); + + return rWlanStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief extend command packet generation utility +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] ucCID Command ID +* \param[in] ucExtCID Extend 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 +wlanSendSetQueryExtCmd(IN P_ADAPTER_T prAdapter, + UINT_8 ucCID, + UINT_8 ucExtCID, + 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->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->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 = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + /*prWifiCmd->u2Length = prCmdInfo->u2InfoBufLen - (UINT_16) OFFSET_OF(WIFI_CMD_T, u2Length);*/ + /*prWifiCmd->u2PqId = CMD_PQ_ID;*/ + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + /*prWifiCmd->ucExtenCID = ucExtCID;*/ + 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; +} + +WLAN_STATUS +wlanoidBssInfoBasic(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_CMD_BSS_INFO_UPDATE_T prBssInfoUpdateBasic; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidManualAssoc"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(CMD_BSSINFO_BASIC_T); + if (u4SetBufferLen < sizeof(CMD_BSSINFO_BASIC_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prBssInfoUpdateBasic = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, (CMD_BSSINFO_UPDATE_HDR_SIZE + u4SetBufferLen)); + if (!prBssInfoUpdateBasic) { + DBGLOG(INIT, ERROR, "Allocate P_CMD_DEV_INFO_UPDATE_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* fix me: configurable ucBssIndex */ + prBssInfoUpdateBasic->ucBssIndex = 0; + prBssInfoUpdateBasic->u2TotalElementNum = 1; + kalMemCopy(prBssInfoUpdateBasic->aucBuffer, pvSetBuffer, u4SetBufferLen); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_BSSINFO_UPDATE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + (CMD_BSSINFO_UPDATE_HDR_SIZE + u4SetBufferLen), + (PUINT_8) prBssInfoUpdateBasic, NULL, 0); + + cnmMemFree(prAdapter, prBssInfoUpdateBasic); + + return rWlanStatus; +} + +WLAN_STATUS +wlanoidDevInfoActive(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_CMD_DEV_INFO_UPDATE_T prDevInfoUpdateActive; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidManualAssoc"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(CMD_DEVINFO_ACTIVE_T); + if (u4SetBufferLen < sizeof(CMD_DEVINFO_ACTIVE_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prDevInfoUpdateActive = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, (CMD_DEVINFO_UPDATE_HDR_SIZE + u4SetBufferLen)); + if (!prDevInfoUpdateActive) { + DBGLOG(INIT, ERROR, "Allocate P_CMD_DEV_INFO_UPDATE_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* fix me: configurable ucOwnMacIdx */ + prDevInfoUpdateActive->ucOwnMacIdx = 0; + prDevInfoUpdateActive->ucAppendCmdTLV = 0; + prDevInfoUpdateActive->u2TotalElementNum = 1; + kalMemCopy(prDevInfoUpdateActive->aucBuffer, pvSetBuffer, u4SetBufferLen); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_DEVINFO_UPDATE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + (CMD_DEVINFO_UPDATE_HDR_SIZE + u4SetBufferLen), + (PUINT_8) prDevInfoUpdateActive, NULL, 0); + + cnmMemFree(prAdapter, prDevInfoUpdateActive); + + return rWlanStatus; +} + +WLAN_STATUS +wlanoidManualAssoc(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_CMD_STAREC_UPDATE_T prStaRecManualAssoc; + P_CMD_MANUAL_ASSOC_STRUCT_T prManualAssoc; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidManualAssoc"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(CMD_STAREC_UPDATE_T); + if (u4SetBufferLen < sizeof(CMD_STAREC_UPDATE_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prStaRecManualAssoc = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, (CMD_STAREC_UPDATE_HDR_SIZE + u4SetBufferLen)); + if (!prStaRecManualAssoc) { + DBGLOG(INIT, ERROR, "Allocate P_CMD_STAREC_UPDATE_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prManualAssoc = (P_CMD_MANUAL_ASSOC_STRUCT_T) pvSetBuffer; + prStaRecManualAssoc->ucWlanIdx = prManualAssoc->ucWtbl; + prStaRecManualAssoc->ucBssIndex = prManualAssoc->ucOwnmac; + prStaRecManualAssoc->u2TotalElementNum = 1; + kalMemCopy(prStaRecManualAssoc->aucBuffer, pvSetBuffer, u4SetBufferLen); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_STAREC_UPDATE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + (CMD_STAREC_UPDATE_HDR_SIZE + u4SetBufferLen), + (PUINT_8) prStaRecManualAssoc, NULL, 0); + + cnmMemFree(prAdapter, prStaRecManualAssoc); + + return rWlanStatus; +} + +typedef struct _TXBF_CMD_DONE_HANDLER_T { + UINT_32 u4TxBfCmdId; + void (*pFunc)(P_ADAPTER_T, P_CMD_INFO_T, PUINT_8); +} TXBF_CMD_DONE_HANDLER_T, *P_TXBF_CMD_DONE_HANDLER_T; + +TXBF_CMD_DONE_HANDLER_T rTxBfCmdDoneHandler[] = { + {BF_SOUNDING_OFF, nicCmdEventSetCommon}, + {BF_SOUNDING_ON, nicCmdEventSetCommon}, + {BF_HW_CTRL, nicCmdEventSetCommon}, + {BF_DATA_PACKET_APPLY, nicCmdEventSetCommon}, + {BF_PFMU_MEM_ALLOCATE, nicCmdEventSetCommon}, + {BF_PFMU_MEM_RELEASE, nicCmdEventSetCommon}, + {BF_PFMU_TAG_READ, nicCmdEventPfmuTagRead}, + {BF_PFMU_TAG_WRITE, nicCmdEventSetCommon}, + {BF_PROFILE_READ, nicCmdEventPfmuDataRead}, + {BF_PROFILE_WRITE, nicCmdEventSetCommon}, + {BF_PN_READ, nicCmdEventSetCommon}, + {BF_PN_WRITE, nicCmdEventSetCommon}, + {BF_PFMU_MEM_ALLOC_MAP_READ, nicCmdEventSetCommon} +}; + +WLAN_STATUS +wlanoidTxBfAction(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_TXBF_ACTION_STRUCT_T prTxBfActionInfo; + CMD_TXBF_ACTION_T rCmdTxBfActionInfo; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + BOOLEAN fgSetQuery, fgNeedResp; + UINT_32 u4TxBfCmdId; + + DEBUGFUNC("wlanoidTxBfAction"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_TXBF_ACTION_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_TXBF_ACTION_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prTxBfActionInfo = (P_PARAM_CUSTOM_TXBF_ACTION_STRUCT_T) pvSetBuffer; + + memcpy(&rCmdTxBfActionInfo, prTxBfActionInfo, sizeof(CMD_TXBF_ACTION_T)); + + u4TxBfCmdId = rCmdTxBfActionInfo.rProfileTagRead.ucTxBfCategory; + if (TXBF_CMD_NEED_TO_RESPONSE(u4TxBfCmdId) == 0) { /* don't need response */ + fgSetQuery = TRUE; + fgNeedResp = FALSE; + } else { + fgSetQuery = FALSE; + fgNeedResp = TRUE; + } + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_BF_ACTION, + fgSetQuery, + fgNeedResp, + TRUE, + rTxBfCmdDoneHandler[u4TxBfCmdId].pFunc, + nicOidCmdTimeoutCommon, + sizeof(CMD_TXBF_ACTION_T), + (PUINT_8) &rCmdTxBfActionInfo, pvSetBuffer, u4SetBufferLen); + + return rWlanStatus; +} + +#if CFG_SUPPORT_MU_MIMO +WLAN_STATUS +wlanoidMuMimoAction(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T prMuMimoActionInfo; + CMD_MUMIMO_ACTION_T rCmdMuMimoActionInfo; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + BOOLEAN fgSetQuery, fgNeedResp; + UINT_32 u4MuMimoCmdId; + + VOID (*pFunc)(P_ADAPTER_T, P_CMD_INFO_T, PUINT_8); + + DEBUGFUNC("wlanoidMuMimoAction"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prMuMimoActionInfo = (P_PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T) pvSetBuffer; + + memcpy(&rCmdMuMimoActionInfo, prMuMimoActionInfo, sizeof(CMD_MUMIMO_ACTION_T)); + + u4MuMimoCmdId = rCmdMuMimoActionInfo.ucMuMimoCategory; + if (MU_CMD_NEED_TO_RESPONSE(u4MuMimoCmdId) == 0) { + fgSetQuery = TRUE; + fgNeedResp = FALSE; + } else { + fgSetQuery = FALSE; + fgNeedResp = TRUE; + } + + pFunc = nicCmdEventSetCommon; + if (u4MuMimoCmdId == MU_HQA_GET_QD) + pFunc = nicCmdEventGetQd; + else if (u4MuMimoCmdId == MU_HQA_GET_CALC_LQ) + pFunc = nicCmdEventGetCalcLq; + else if (u4MuMimoCmdId == MU_GET_CALC_INIT_MCS) + pFunc = nicCmdEventGetCalcInitMcs; + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_MU_CTRL, + fgSetQuery, + fgNeedResp, + TRUE, + pFunc, + nicOidCmdTimeoutCommon, + sizeof(CMD_MUMIMO_ACTION_T), + (PUINT_8) &rCmdMuMimoActionInfo, pvSetBuffer, u4SetBufferLen); + + return rWlanStatus; +} +#endif /* CFG_SUPPORT_MU_MIMO */ +#endif /* CFG_SUPPORT_TX_BF */ +#endif /* CFG_SUPPORT_QA_TOOL */ +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query MCR value. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS +wlanoidQueryMcrRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_CUSTOM_MCR_RW_STRUCT_T prMcrRdInfo; + CMD_ACCESS_REG rCmdAccessReg; + + DEBUGFUNC("wlanoidQueryMcrRead"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T); + + if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + prMcrRdInfo = (P_PARAM_CUSTOM_MCR_RW_STRUCT_T) pvQueryBuffer; + + /* 0x9000 - 0x9EFF reserved for FW */ +#if CFG_SUPPORT_SWCR + if ((prMcrRdInfo->u4McrOffset >> 16) == 0x9F00) { + swCrReadWriteCmd(prAdapter, + SWCR_READ, + (UINT_16) (prMcrRdInfo->u4McrOffset & BITS(0, 15)), &prMcrRdInfo->u4McrData); + return WLAN_STATUS_SUCCESS; + } +#endif /* CFG_SUPPORT_SWCR */ + + /* Check if access F/W Domain MCR (due to WiFiSYS is placed from 0x6000-0000 */ + if (prMcrRdInfo->u4McrOffset & 0xFFFF0000) { +#if defined(MT6797) + UINT32 val = 0x77777777; +#endif + /* fill command */ + rCmdAccessReg.u4Address = prMcrRdInfo->u4McrOffset; + rCmdAccessReg.u4Data = 0; +#if defined(MT6797) + if ((prMcrRdInfo->u4McrOffset & 0xFFFF0000) == 0x180f0000) { + + val = readl((volatile UINT_32 *)((*g_pHifRegBaseAddr) + (prMcrRdInfo->u4McrOffset & 0xffff))); + + DBGLOG(INIT, TRACE, "sarah MCR Read: Offset = %#08lx, Data = %#08lx\n", + prMcrRdInfo->u4McrOffset, val); + + + } else +#endif + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryMcrRead, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8) &rCmdAccessReg, pvQueryBuffer, u4QueryBufferLen); + } else { + HAL_MCR_RD(prAdapter, prMcrRdInfo->u4McrOffset & BITS(2, 31), /* address is in DWORD unit */ + &prMcrRdInfo->u4McrData); + + DBGLOG(OID, TRACE, "MCR Read: Offset = %#08x, Data = %#08x\n", + prMcrRdInfo->u4McrOffset, prMcrRdInfo->u4McrData); + return WLAN_STATUS_SUCCESS; + } + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidQueryMcrRead() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to write MCR and enable specific function. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetMcrWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_MCR_RW_STRUCT_T prMcrWrInfo; + CMD_ACCESS_REG rCmdAccessReg; + +#if CFG_STRESS_TEST_SUPPORT + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prBssInfo = prAdapter->prAisBssInfo; + P_STA_RECORD_T prStaRec = prBssInfo->prStaRecOfAP; + UINT_32 u4McrOffset, u4McrData; +#endif + + DEBUGFUNC("wlanoidSetMcrWrite"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prMcrWrInfo = (P_PARAM_CUSTOM_MCR_RW_STRUCT_T) pvSetBuffer; + + /* 0x9000 - 0x9EFF reserved for FW */ + /* 0xFFFE reserved for FW */ + + /* -- Puff Stress Test Begin */ +#if CFG_STRESS_TEST_SUPPORT + + /* 0xFFFFFFFE for Control Rate */ + if (prMcrWrInfo->u4McrOffset == 0xFFFFFFFE) { + if (prMcrWrInfo->u4McrData < FIXED_RATE_NUM && prMcrWrInfo->u4McrData > 0) + prAdapter->rWifiVar.eRateSetting = (ENUM_REGISTRY_FIXED_RATE_T) (prMcrWrInfo->u4McrData); + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + DEBUGFUNC("[Stress Test]Complete Rate is Changed...\n"); + DBGLOG(OID, TRACE, "[Stress Test] Rate is Changed to index %d...\n", prAdapter->rWifiVar.eRateSetting); + } + /* 0xFFFFFFFD for Switch Channel */ + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFFD) { + if (prMcrWrInfo->u4McrData <= 11 && prMcrWrInfo->u4McrData >= 1) + prBssInfo->ucPrimaryChannel = prMcrWrInfo->u4McrData; + nicUpdateBss(prAdapter, prBssInfo->ucNetTypeIndex); + DBGLOG(OID, TRACE, "[Stress Test] Channel is switched to %d ...\n", prBssInfo->ucPrimaryChannel); + + return WLAN_STATUS_SUCCESS; + } + /* 0xFFFFFFFFC for Control RF Band and SCO */ + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFFC) { + /* Band */ + if (prMcrWrInfo->u4McrData & 0x80000000) { + /* prBssInfo->eBand = BAND_5G; */ + /* prBssInfo->ucPrimaryChannel = 52; // Bond to Channel 52 */ + } else { + prBssInfo->eBand = BAND_2G4; + prBssInfo->ucPrimaryChannel = 8; /* Bond to Channel 6 */ + } + + /* Bandwidth */ + if (prMcrWrInfo->u4McrData & 0x00010000) { + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; + prStaRec->ucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + + if (prMcrWrInfo->u4McrData == 0x00010002) { + prBssInfo->eBssSCO = CHNL_EXT_SCB; /* U20 */ + prBssInfo->ucPrimaryChannel += 2; + } else if (prMcrWrInfo->u4McrData == 0x00010001) { + prBssInfo->eBssSCO = CHNL_EXT_SCA; /* L20 */ + prBssInfo->ucPrimaryChannel -= 2; + } else { + prBssInfo->eBssSCO = CHNL_EXT_SCA; /* 40 */ + } + } + + if (prMcrWrInfo->u4McrData & 0x00000000) { + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SUP_CHNL_WIDTH; + prBssInfo->eBssSCO = CHNL_EXT_SCN; + } + rlmBssInitForAPandIbss(prAdapter, prBssInfo); + } + /* 0xFFFFFFFB for HT Capability */ + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFFB) { + /* Enable HT Capability */ + if (prMcrWrInfo->u4McrData & 0x00000001) { + prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + DEBUGFUNC("[Stress Test]Enable HT capability...\n"); + } else { + prStaRec->u2HtCapInfo &= (~HT_CAP_INFO_HT_GF); + DEBUGFUNC("[Stress Test]Disable HT capability...\n"); + } + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + } + /* 0xFFFFFFFA for Enable Random Rx Reset */ + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFFA) { + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_RANDOM_RX_RESET_EN, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); + } + /* 0xFFFFFFF9 for Disable Random Rx Reset */ + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFF9) { + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_RANDOM_RX_RESET_DE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); + } + /* 0xFFFFFFF8 for Enable SAPP */ + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFF8) { + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SAPP_EN, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); + } + /* 0xFFFFFFF7 for Disable SAPP */ + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFF7) { + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SAPP_DE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); + } + + else +#endif + /* -- Puff Stress Test End */ + + /* Check if access F/W Domain MCR */ + if (prMcrWrInfo->u4McrOffset & 0xFFFF0000) { +#if defined(MT6797) + if ((prMcrWrInfo->u4McrOffset & 0xFFFF0000) == 0x180f0000) { + + writel(prMcrWrInfo->u4McrData, (volatile UINT_32 *)((*g_pHifRegBaseAddr) + + (prMcrWrInfo->u4McrOffset & 0xffff))); + + DBGLOG(INIT, TRACE, "sarah MCR write: Offset = %#08lx, wData = %#08lx\n", + prMcrWrInfo->u4McrOffset, prMcrWrInfo->u4McrData); + + return WLAN_STATUS_SUCCESS; + } +#endif + /* 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 + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN + if (prMcrWrInfo->u4McrOffset == 0x22220000) { + /* read test mode */ + kalSetSdioTestPattern(prAdapter->prGlueInfo, TRUE, TRUE); + + return WLAN_STATUS_SUCCESS; + } + + if (prMcrWrInfo->u4McrOffset == 0x22220001) { + /* write test mode */ + kalSetSdioTestPattern(prAdapter->prGlueInfo, TRUE, FALSE); + + return WLAN_STATUS_SUCCESS; + } + + if (prMcrWrInfo->u4McrOffset == 0x22220002) { + /* leave from test mode */ + kalSetSdioTestPattern(prAdapter->prGlueInfo, FALSE, FALSE); + + return WLAN_STATUS_SUCCESS; + } +#endif + + /* fill command */ + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); + } else { + HAL_MCR_WR(prAdapter, (prMcrWrInfo->u4McrOffset & BITS(2, 31)), /* address is in DWORD unit */ + prMcrWrInfo->u4McrData); + + DBGLOG(OID, TRACE, "MCR Write: Offset = %#08x, Data = %#08x\n", + prMcrWrInfo->u4McrOffset, prMcrWrInfo->u4McrData); + + return WLAN_STATUS_SUCCESS; + } +} /* wlanoidSetMcrWrite */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query SW CTRL +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQuerySwCtrlRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_CUSTOM_SW_CTRL_STRUCT_T prSwCtrlInfo; + WLAN_STATUS rWlanStatus; + UINT_16 u2Id, u2SubId; + UINT_32 u4Data; + + CMD_SW_DBG_CTRL_T rCmdSwCtrl; + + DEBUGFUNC("wlanoidQuerySwCtrlRead"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T); + + if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + prSwCtrlInfo = (P_PARAM_CUSTOM_SW_CTRL_STRUCT_T) pvQueryBuffer; + + u2Id = (UINT_16) (prSwCtrlInfo->u4Id >> 16); + u2SubId = (UINT_16) (prSwCtrlInfo->u4Id & BITS(0, 15)); + u4Data = 0; + rWlanStatus = WLAN_STATUS_SUCCESS; + + switch (u2Id) { + /* 0x9000 - 0x9EFF reserved for FW */ + /* 0xFFFE reserved for FW */ + +#if CFG_SUPPORT_SWCR + case 0x9F00: + swCrReadWriteCmd(prAdapter, SWCR_READ,/* Read */ + (UINT_16) u2SubId, &u4Data); + break; +#endif /* CFG_SUPPORT_SWCR */ + + case 0xFFFF: + { + u4Data = 0x5AA56620; + } + break; + + case 0xBABA: + switch ((u2SubId >> 8) & BITS(0, 7)) { + case 0x00: + /* Dump Tx resource and queue status */ + qmDumpQueueStatus(prAdapter); + cnmDumpMemoryStatus(prAdapter); + break; + + case 0x01: + /* Dump StaRec info by index */ + cnmDumpStaRec(prAdapter, (UINT_8) (u2SubId & BITS(0, 7))); + break; + + case 0x02: + /* Dump BSS info by index */ + bssDumpBssInfo(prAdapter, (UINT_8) (u2SubId & BITS(0, 7))); + break; + + case 0x03: + /*Dump BSS statistics by index */ + wlanDumpBssStatistics(prAdapter, (UINT_8) (u2SubId & BITS(0, 7))); + break; + + default: + break; + } + + u4Data = 0xBABABABA; + break; + + case 0x9000: + default: + { + rCmdSwCtrl.u4Id = prSwCtrlInfo->u4Id; + rCmdSwCtrl.u4Data = 0; + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + FALSE, + TRUE, + TRUE, + nicCmdEventQuerySwCtrlRead, + nicOidCmdTimeoutCommon, + sizeof(CMD_SW_DBG_CTRL_T), + (PUINT_8) &rCmdSwCtrl, pvQueryBuffer, u4QueryBufferLen); + } + } /* switch(u2Id) */ + + prSwCtrlInfo->u4Data = u4Data; + + return rWlanStatus; + +} + + /* end of wlanoidQuerySwCtrlRead() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to write SW CTRL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetSwCtrlWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_SW_CTRL_STRUCT_T prSwCtrlInfo; + CMD_SW_DBG_CTRL_T rCmdSwCtrl; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + UINT_16 u2Id, u2SubId; + UINT_32 u4Data; + + DEBUGFUNC("wlanoidSetSwCtrlWrite"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prSwCtrlInfo = (P_PARAM_CUSTOM_SW_CTRL_STRUCT_T) pvSetBuffer; + + u2Id = (UINT_16) (prSwCtrlInfo->u4Id >> 16); + u2SubId = (UINT_16) (prSwCtrlInfo->u4Id & BITS(0, 15)); + u4Data = prSwCtrlInfo->u4Data; + + 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; + + nicPowerSaveInfoMap(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, + ePowerMode, PS_CALLER_SW_WRITE); + + rWlanStatus = nicConfigPowerSaveProfile(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, + 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.ucUapsd = (BOOLEAN) u4Data; + else if (u2SubId == 0x3) { + prAdapter->u4UapsdAcBmp = u4Data & BITS(0, 15); + GET_BSS_INFO_BY_INDEX(prAdapter, + u4Data >> 16)->rPmProfSetupInfo.ucBmpDeliveryAC = + (UINT_8) prAdapter->u4UapsdAcBmp; + GET_BSS_INFO_BY_INDEX(prAdapter, + 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; +#if CFG_RX_BA_REORDERING_ENHANCEMENT + else if (u2SubId == 0x6) + prAdapter->rWifiVar.fgEnableReportIndependentPkt = (BOOLEAN) u4Data; +#endif + else if (u2SubId == 0x0100) { + if (u4Data == 2) + prAdapter->rWifiVar.ucRxGf = FEATURE_DISABLED; + else + prAdapter->rWifiVar.ucRxGf = FEATURE_ENABLED; + } else if (u2SubId == 0x0101) + prAdapter->rWifiVar.ucRxShortGI = (UINT_8) u4Data; + else if (u2SubId == 0x0103) { /* AP Mode WMMPS */ + PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T rUapsdParams; + + DBGLOG(OID, INFO, "ApUapsd 0x10010103 cmd received: %d\n", u4Data); + if ((BOOLEAN) u4Data) { + prAdapter->rWifiVar.ucApUapsd = TRUE; + rUapsdParams.fgEnAPSD = 1; + rUapsdParams.fgEnAPSD_AcBe = 1; + rUapsdParams.fgEnAPSD_AcBk = 1; + rUapsdParams.fgEnAPSD_AcVi = 1; + rUapsdParams.fgEnAPSD_AcVo = 1; + rUapsdParams.ucMaxSpLen = 0; /* default: 0, do not limit delivery pkt number */ + } else { + prAdapter->rWifiVar.ucApUapsd = FALSE; + rUapsdParams.fgEnAPSD = 0; + rUapsdParams.fgEnAPSD_AcBe = 0; + rUapsdParams.fgEnAPSD_AcBk = 0; + rUapsdParams.fgEnAPSD_AcVi = 0; + rUapsdParams.fgEnAPSD_AcVo = 0; + rUapsdParams.ucMaxSpLen = 0; /* default: 0, do not limit delivery pkt number */ + } + nicSetUapsdParam(prAdapter, &rUapsdParams, NETWORK_TYPE_P2P); + } + + break; + +#if CFG_SUPPORT_SWCR + case 0x1002: +#if CFG_RX_PKTS_DUMP + if (u2SubId == 0x0) { + if (u4Data) + u4Data = BIT(HIF_RX_PKT_TYPE_MANAGEMENT); + swCrFrameCheckEnable(prAdapter, u4Data); + } +#endif + 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 + case 0x1003: /* for debug switches */ + switch (u2SubId) { + case 1: + DBGLOG(OID, INFO, "Enable VoE 5.7 Packet Jitter test\n"); + prAdapter->rDebugInfo.fgVoE5_7Test = !!u4Data; + break; + case 0x0002: + { + CMD_TX_AMPDU_T rTxAmpdu; + WLAN_STATUS rStatus; + + rTxAmpdu.fgEnable = !!u4Data; + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_TX_AMPDU, + TRUE, FALSE, FALSE, NULL, NULL, + sizeof(CMD_TX_AMPDU_T), (PUINT_8)&rTxAmpdu, NULL, 0); + DBGLOG(OID, INFO, "disable tx ampdu status %u\n", rStatus); + break; + } + default: + break; + } + break; + +#if CFG_SUPPORT_802_11W + case 0x2000: + DBGLOG(RSN, TRACE, "802.11w test 0x%x\n", u2SubId); + if (u2SubId == 0x0) + rsnStartSaQuery(prAdapter); + if (u2SubId == 0x1) + rsnStopSaQuery(prAdapter); + if (u2SubId == 0x2) + rsnSaQueryRequest(prAdapter, NULL); + if (u2SubId == 0x3) { + P_BSS_INFO_T prBssInfo = prAdapter->prAisBssInfo; + + authSendDeauthFrame(prAdapter, prBssInfo, prBssInfo->prStaRecOfAP, NULL, 7, NULL); + } + /* wext_set_mode */ + /* + * if (u2SubId == 0x3) { + * prAdapter->prGlueInfo->rWpaInfo.u4Mfp = RSN_AUTH_MFP_DISABLED; + * } + * if (u2SubId == 0x4) { + * //prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = TRUE; + * prAdapter->prGlueInfo->rWpaInfo.u4Mfp = RSN_AUTH_MFP_OPTIONAL; + * } + * if (u2SubId == 0x5) { + * //prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = TRUE; + * prAdapter->prGlueInfo->rWpaInfo.u4Mfp = RSN_AUTH_MFP_REQUIRED; + * } + */ + break; +#endif + case 0xFFFF: + { + /* CMD_ACCESS_REG rCmdAccessReg; */ +#if 1 /* CFG_MT6573_SMT_TEST */ + if (u2SubId == 0x0123) { + + DBGLOG(HAL, TRACE, "set smt fixed rate: %u\n", u4Data); + + if ((ENUM_REGISTRY_FIXED_RATE_T) (u4Data) < FIXED_RATE_NUM) + prAdapter->rWifiVar.eRateSetting = (ENUM_REGISTRY_FIXED_RATE_T) (u4Data); + else + prAdapter->rWifiVar.eRateSetting = FIXED_RATE_NONE; + + if (prAdapter->rWifiVar.eRateSetting == FIXED_RATE_NONE) + /* Enable Auto (Long/Short) Preamble */ + prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_AUTO; + else if ((prAdapter->rWifiVar.eRateSetting >= + FIXED_RATE_MCS0_20M_400NS + && prAdapter->rWifiVar.eRateSetting <= FIXED_RATE_MCS7_20M_400NS) + || (prAdapter->rWifiVar.eRateSetting >= + FIXED_RATE_MCS0_40M_400NS + && prAdapter->rWifiVar.eRateSetting <= FIXED_RATE_MCS32_400NS)) + /* Force Short Preamble */ + prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_SHORT; + else + /* Force Long Preamble */ + prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_LONG; + + /* abort to re-connect */ +#if 1 + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); +#else + aisBssBeaconTimeout(prAdapter); +#endif + + return WLAN_STATUS_SUCCESS; + + } else if (u2SubId == 0x1234) { + /* 1. Disable On-Lin Scan */ + /* 3. Disable FIFO FULL no ack */ + /* 4. Disable Roaming */ + /* Disalbe auto tx power */ + /* 2. Keep at CAM mode */ + /* 5. Disable Beacon Timeout Detection */ + rWlanStatus = nicEnterCtiaMode(prAdapter, TRUE, TRUE); + } else if (u2SubId == 0x1235) { + /* 1. Enaable On-Lin Scan */ + /* 3. Enable FIFO FULL no ack */ + /* 4. Enable Roaming */ + /* Enable auto tx power */ + /* 2. Keep at Fast PS */ + /* 5. Enable Beacon Timeout Detection */ + rWlanStatus = nicEnterCtiaMode(prAdapter, FALSE, TRUE); + } else if (u2SubId == 0x1260) { + /* Disable On-Line Scan */ + rWlanStatus = nicEnterCtiaModeOfScan(prAdapter, TRUE, TRUE); + } else if (u2SubId == 0x1261) { + /* Enable On-Line Scan */ + rWlanStatus = nicEnterCtiaModeOfScan(prAdapter, FALSE, TRUE); + } else if (u2SubId == 0x1262) { + /* Disable Roaming */ + rWlanStatus = nicEnterCtiaModeOfRoaming(prAdapter, TRUE, TRUE); + } else if (u2SubId == 0x1263) { + /* Enable Roaming */ + rWlanStatus = nicEnterCtiaModeOfRoaming(prAdapter, FALSE, TRUE); + } else if (u2SubId == 0x1264) { + /* Keep at CAM mode */ + rWlanStatus = nicEnterCtiaModeOfCAM(prAdapter, TRUE, TRUE); + } else if (u2SubId == 0x1265) { + /* Keep at Fast PS */ + rWlanStatus = nicEnterCtiaModeOfCAM(prAdapter, FALSE, TRUE); + } else if (u2SubId == 0x1266) { + /* Disable Beacon Timeout Detection */ + rWlanStatus = nicEnterCtiaModeOfBCNTimeout(prAdapter, TRUE, TRUE); + } else if (u2SubId == 0x1267) { + /* Enable Beacon Timeout Detection */ + rWlanStatus = nicEnterCtiaModeOfBCNTimeout(prAdapter, FALSE, TRUE); + } else if (u2SubId == 0x1268) { + /* Disalbe auto tx power */ + rWlanStatus = nicEnterCtiaModeOfAutoTxPower(prAdapter, TRUE, TRUE); + } else if (u2SubId == 0x1269) { + /* Enable auto tx power */ + rWlanStatus = nicEnterCtiaModeOfAutoTxPower(prAdapter, FALSE, TRUE); + } else if (u2SubId == 0x1270) { + /* Disalbe FIFO FULL no ack */ + rWlanStatus = nicEnterCtiaModeOfFIFOFullNoAck(prAdapter, TRUE, TRUE); + } else if (u2SubId == 0x1271) { + /* Enable FIFO FULL no ack */ + rWlanStatus = nicEnterCtiaModeOfFIFOFullNoAck(prAdapter, FALSE, TRUE); + } +#endif +#if CFG_MTK_STAGE_SCAN + else if (u2SubId == 0x1250) + prAdapter->aePreferBand[KAL_NETWORK_TYPE_AIS_INDEX] = BAND_NULL; + else if (u2SubId == 0x1251) + prAdapter->aePreferBand[KAL_NETWORK_TYPE_AIS_INDEX] = BAND_2G4; + else if (u2SubId == 0x1252) { + if (prAdapter->fgEnable5GBand) + prAdapter->aePreferBand[KAL_NETWORK_TYPE_AIS_INDEX] = BAND_5G; + else + /* Skip this setting if 5G band is disabled */ + DBGLOG(SCN, INFO, "Skip 5G stage scan request due to 5G is disabled\n"); + } +#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 */ + +WLAN_STATUS +wlanoidQueryChipConfig(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T prChipConfigInfo; + CMD_CHIP_CONFIG_T rCmdChipConfig; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQuerySwCtrlRead"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T); + + if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + prChipConfigInfo = (P_PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T) pvQueryBuffer; + kalMemZero(&rCmdChipConfig, sizeof(rCmdChipConfig)); + + rCmdChipConfig.u2Id = prChipConfigInfo->u2Id; + rCmdChipConfig.ucType = prChipConfigInfo->ucType; + rCmdChipConfig.ucRespType = prChipConfigInfo->ucRespType; + rCmdChipConfig.u2MsgSize = prChipConfigInfo->u2MsgSize; + if (rCmdChipConfig.u2MsgSize > CHIP_CONFIG_RESP_SIZE) { + DBGLOG(OID, INFO, "Chip config Msg Size %u is not valid (query)\n", rCmdChipConfig.u2MsgSize); + rCmdChipConfig.u2MsgSize = CHIP_CONFIG_RESP_SIZE; + } + kalMemCopy(rCmdChipConfig.aucCmd, prChipConfigInfo->aucCmd, rCmdChipConfig.u2MsgSize); + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, CMD_ID_CHIP_CONFIG, FALSE, TRUE, TRUE, + /*nicCmdEventQuerySwCtrlRead, */ + nicCmdEventQueryChipConfig, + nicOidCmdTimeoutCommon, + sizeof(CMD_CHIP_CONFIG_T), + (PUINT_8) &rCmdChipConfig, pvQueryBuffer, u4QueryBufferLen); + + return rWlanStatus; + +} + + /* end of wlanoidQueryChipConfig() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set chip +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetChipConfig(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T prChipConfigInfo; + CMD_CHIP_CONFIG_T rCmdChipConfig; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DATA_STRUCT_INSPECTING_ASSERT(sizeof(prChipConfigInfo->aucCmd) == CHIP_CONFIG_RESP_SIZE); + DEBUGFUNC("wlanoidSetChipConfig"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prChipConfigInfo = (P_PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T) pvSetBuffer; + kalMemZero(&rCmdChipConfig, sizeof(rCmdChipConfig)); + + rCmdChipConfig.u2Id = prChipConfigInfo->u2Id; + rCmdChipConfig.ucType = prChipConfigInfo->ucType; + rCmdChipConfig.ucRespType = prChipConfigInfo->ucRespType; + rCmdChipConfig.u2MsgSize = prChipConfigInfo->u2MsgSize; + if (rCmdChipConfig.u2MsgSize > CHIP_CONFIG_RESP_SIZE) { + DBGLOG(OID, INFO, "Chip config Msg Size %u is not valid (set)\n", rCmdChipConfig.u2MsgSize); + rCmdChipConfig.u2MsgSize = CHIP_CONFIG_RESP_SIZE; + } + kalMemCopy(rCmdChipConfig.aucCmd, prChipConfigInfo->aucCmd, rCmdChipConfig.u2MsgSize); + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_CHIP_CONFIG, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CHIP_CONFIG_T), + (PUINT_8) &rCmdChipConfig, pvSetBuffer, u4SetBufferLen); + + return rWlanStatus; +} /* wlanoidSetChipConfig */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set cfg and callback +* +* \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 +wlanoidSetKeyCfg(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_PARAM_CUSTOM_KEY_CFG_STRUCT_T prKeyCfgInfo; + + DEBUGFUNC("wlanoidSetKeyCfg"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_KEY_CFG_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_KEY_CFG_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + prKeyCfgInfo = (P_PARAM_CUSTOM_KEY_CFG_STRUCT_T) pvSetBuffer; + + wlanCfgSet(prAdapter, prKeyCfgInfo->aucKey, prKeyCfgInfo->aucValue, 0); + + wlanInitFeatureOption(prAdapter); + + return rWlanStatus; +} + + /* wlanoidSetSwCtrlWrite */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query EEPROM value. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryEepromRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T prEepromRwInfo; + CMD_ACCESS_EEPROM rCmdAccessEeprom; + + DEBUGFUNC("wlanoidQueryEepromRead"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T); + + if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + prEepromRwInfo = (P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T) pvQueryBuffer; + + kalMemZero(&rCmdAccessEeprom, sizeof(CMD_ACCESS_EEPROM)); + rCmdAccessEeprom.u2Offset = prEepromRwInfo->ucEepromIndex; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_EEPROM, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryEepromRead, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_EEPROM), + (PUINT_8) &rCmdAccessEeprom, pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryEepromRead */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to write EEPROM value. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetEepromWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T prEepromRwInfo; + CMD_ACCESS_EEPROM rCmdAccessEeprom; + + DEBUGFUNC("wlanoidSetEepromWrite"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prEepromRwInfo = (P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T) pvSetBuffer; + + kalMemZero(&rCmdAccessEeprom, sizeof(CMD_ACCESS_EEPROM)); + rCmdAccessEeprom.u2Offset = prEepromRwInfo->ucEepromIndex; + rCmdAccessEeprom.u2Data = prEepromRwInfo->u2EepromData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_EEPROM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_EEPROM), + (PUINT_8) &rCmdAccessEeprom, pvSetBuffer, u4SetBufferLen); + +} /* wlanoidSetEepromWrite */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of the successfully transmitted +* packets. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryXmitOk(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryXmitOk"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rTransmittedFragmentCount.QuadPart; + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rTransmittedFragmentCount.QuadPart; + } + + } else +#endif + { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryXmitOk, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + } + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryXmitOk */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of the successfully received +* packets. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRcvOk(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryRcvOk"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rReceivedFragmentCount.QuadPart; + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rReceivedFragmentCount.QuadPart; + } + + } else +#endif + { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryRecvOk, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + } + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryRcvOk */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of frames that the driver +* fails to transmit. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryXmitError(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryXmitError"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rFailedCount.QuadPart; + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rFailedCount.QuadPart; + } + } else +#endif + { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryXmitError, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + } + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryXmitError */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of frames successfully +* transmitted after exactly one collision. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryXmitOneCollision(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryXmitOneCollision"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) + (prAdapter->rStatStruct.rMultipleRetryCount.QuadPart - + prAdapter->rStatStruct.rRetryCount.QuadPart); + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) + (prAdapter->rStatStruct.rMultipleRetryCount.QuadPart - + prAdapter->rStatStruct.rRetryCount.QuadPart); + } + } else +#endif + { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryXmitOneCollision, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + } + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryXmitOneCollision */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of frames successfully +* transmitted after more than one collision. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryXmitMoreCollisions(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryXmitMoreCollisions"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) (prAdapter->rStatStruct.rMultipleRetryCount.QuadPart); + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) (prAdapter->rStatStruct.rMultipleRetryCount.QuadPart); + } + } else +#endif + { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryXmitMoreCollisions, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + } + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryXmitMoreCollisions */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of frames +* not transmitted due to excessive collisions. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryXmitMaxCollisions(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryXmitMaxCollisions"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rFailedCount.QuadPart; + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rFailedCount.QuadPart; + } + } else +#endif + { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryXmitMaxCollisions, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + } + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryXmitMaxCollisions */ + +#define MTK_CUSTOM_OID_INTERFACE_VERSION 0x00006620 /* for WPDWifi DLL */ +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query current the OID interface version, +* which is the interface between the application and driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryOidInterfaceVersion(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryOidInterfaceVersion"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *(PUINT_32) pvQueryBuffer = MTK_CUSTOM_OID_INTERFACE_VERSION; + *pu4QueryInfoLen = sizeof(UINT_32); + + DBGLOG(OID, WARN, "Custom OID interface version: %#08x\n", *(PUINT_32) pvQueryBuffer); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryOidInterfaceVersion */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query current Multicast Address List. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMulticastList(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ +#ifndef LINUX + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_MAC_MCAST_ADDR, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryMcastAddr, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); +#else + return WLAN_STATUS_SUCCESS; +#endif +} /* end of wlanoidQueryMulticastList() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set Multicast Address List. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetMulticastList(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + CMD_MAC_MCAST_ADDR rCmdMacMcastAddr; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* The data must be a multiple of the Ethernet address size. */ + if ((u4SetBufferLen % MAC_ADDR_LEN)) { + DBGLOG(OID, WARN, "Invalid MC list length %u\n", u4SetBufferLen); + + *pu4SetInfoLen = (((u4SetBufferLen + MAC_ADDR_LEN) - 1) / MAC_ADDR_LEN) * MAC_ADDR_LEN; + + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = u4SetBufferLen; + + /* Verify if we can support so many multicast addresses. */ + if (u4SetBufferLen > MAC_ADDR_LEN * MAX_NUM_GROUP_ADDR) { + DBGLOG(OID, WARN, "Too many MC addresses\n"); + + return WLAN_STATUS_MULTICAST_FULL; + } + + /* NOTE(Kevin): Windows may set u4SetBufferLen == 0 && + * pvSetBuffer == NULL to clear exist Multicast List. + */ + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in set multicast list! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + kalMemZero(&rCmdMacMcastAddr, sizeof(rCmdMacMcastAddr)); + rCmdMacMcastAddr.u4NumOfGroupAddr = u4SetBufferLen / MAC_ADDR_LEN; + rCmdMacMcastAddr.ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + kalMemCopy(rCmdMacMcastAddr.arAddress, pvSetBuffer, u4SetBufferLen); + DBGLOG(OID, TRACE, + "MCAST white list: total=%d MAC0="MACSTR" MAC1="MACSTR" MAC2="MACSTR" MAC3="MACSTR" MAC4="MACSTR"\n", + rCmdMacMcastAddr.u4NumOfGroupAddr, + MAC2STR(rCmdMacMcastAddr.arAddress[0]), MAC2STR(rCmdMacMcastAddr.arAddress[1]), + MAC2STR(rCmdMacMcastAddr.arAddress[2]), MAC2STR(rCmdMacMcastAddr.arAddress[3]), + MAC2STR(rCmdMacMcastAddr.arAddress[4])); + + 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(OID, TRACE, "New packet filter: %#08x\n", u4NewPacketFilter); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in set current packet filter! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + do { + /* + * Verify the bits of the new packet filter. If any bits are set that + * we don't support, leave. + */ + if (u4NewPacketFilter & ~(PARAM_PACKET_FILTER_SUPPORTED)) { + rStatus = WLAN_STATUS_NOT_SUPPORTED; + break; + } +#if DBG + /* + * Need to enable or disable promiscuous support depending on the new + * filter. + */ + if (u4NewPacketFilter & PARAM_PACKET_FILTER_PROMISCUOUS) + DBGLOG(OID, TRACE, "Enable promiscuous mode\n"); + else + DBGLOG(OID, TRACE, "Disable promiscuous mode\n"); + + if (u4NewPacketFilter & PARAM_PACKET_FILTER_ALL_MULTICAST) + DBGLOG(OID, TRACE, "Enable all-multicast mode\n"); + else if (u4NewPacketFilter & PARAM_PACKET_FILTER_MULTICAST) + DBGLOG(OID, TRACE, "Enable multicast\n"); + else + DBGLOG(OID, TRACE, "Disable multicast\n"); + + if (u4NewPacketFilter & PARAM_PACKET_FILTER_BROADCAST) + DBGLOG(OID, TRACE, "Enable Broadcast\n"); + else + DBGLOG(OID, TRACE, "Disable Broadcast\n"); +#endif + + prAdapter->fgAllMulicastFilter = FALSE; + if (u4NewPacketFilter & PARAM_PACKET_FILTER_ALL_MULTICAST) + prAdapter->fgAllMulicastFilter = TRUE; + } while (FALSE); + + if (rStatus == WLAN_STATUS_SUCCESS) { + /* Store the packet filter */ + prAdapter->u4OsPacketFilter &= PARAM_PACKET_FILTER_P2P_MASK; + prAdapter->u4OsPacketFilter |= u4NewPacketFilter; + rStatus = wlanoidSetPacketFilter(prAdapter, prAdapter->u4OsPacketFilter, + TRUE, pvSetBuffer, u4SetBufferLen); + } + DBGLOG(OID, TRACE, "[MC debug] u4OsPacketFilter=0x%x\n", prAdapter->u4OsPacketFilter); + return rStatus; +} /* wlanoidSetCurrentPacketFilter */ + +WLAN_STATUS wlanoidSetPacketFilter(P_ADAPTER_T prAdapter, UINT_32 u4PacketFilter, + BOOLEAN fgIsOid, PVOID pvSetBuffer, UINT_32 u4SetBufferLen) +{ +#if CFG_SUPPORT_DROP_ALL_MC_PACKET + if (prAdapter->prGlueInfo->fgIsInSuspendMode) + u4PacketFilter &= ~(PARAM_PACKET_FILTER_MULTICAST | PARAM_PACKET_FILTER_ALL_MULTICAST); +#else + if (prAdapter->prGlueInfo->fgIsInSuspendMode) { + u4PacketFilter &= ~(PARAM_PACKET_FILTER_ALL_MULTICAST); + u4PacketFilter |= (PARAM_PACKET_FILTER_MULTICAST); + } +#endif + DBGLOG(OID, TRACE, "[MC debug] u4PacketFilter=0x%x, IsSuspend=%d\n", u4PacketFilter, + prAdapter->prGlueInfo->fgIsInSuspendMode); + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RX_FILTER, + TRUE, + FALSE, + fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(UINT_32), + (PUINT_8)&u4PacketFilter, + pvSetBuffer, u4SetBufferLen); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query current packet filter. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryCurrentPacketFilter(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryCurrentPacketFilter"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(UINT_32); + + if (u4QueryBufferLen >= sizeof(UINT_32)) { + ASSERT(pvQueryBuffer); + *(PUINT_32) pvQueryBuffer = prAdapter->u4OsPacketFilter; + } + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryCurrentPacketFilter */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query ACPI device power state. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryAcpiDevicePowerState(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ +#if DBG + PPARAM_DEVICE_POWER_STATE prPowerState; +#endif + + DEBUGFUNC("wlanoidQueryAcpiDevicePowerState"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_DEVICE_POWER_STATE); + +#if DBG + prPowerState = (PPARAM_DEVICE_POWER_STATE) pvQueryBuffer; + switch (*prPowerState) { + case ParamDeviceStateD0: + DBGLOG(OID, INFO, "Query Power State: D0\n"); + break; + case ParamDeviceStateD1: + DBGLOG(OID, INFO, "Query Power State: D1\n"); + break; + case ParamDeviceStateD2: + DBGLOG(OID, INFO, "Query Power State: D2\n"); + break; + case ParamDeviceStateD3: + DBGLOG(OID, INFO, "Query Power State: D3\n"); + break; + default: + break; + } +#endif + + /* + * Since we will disconnect the newwork, therefore we do not + * need to check queue empty + */ + *(PPARAM_DEVICE_POWER_STATE) pvQueryBuffer = ParamDeviceStateD3; + /* WARNLOG(("Ready to transition to D3\n")); */ + return WLAN_STATUS_SUCCESS; + +} /* pwrmgtQueryPower */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set ACPI device power state. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAcpiDevicePowerState(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PPARAM_DEVICE_POWER_STATE prPowerState; + BOOLEAN fgRetValue = TRUE; + + DEBUGFUNC("wlanoidSetAcpiDevicePowerState"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_DEVICE_POWER_STATE); + + ASSERT(pvSetBuffer); + prPowerState = (PPARAM_DEVICE_POWER_STATE) pvSetBuffer; + switch (*prPowerState) { + case ParamDeviceStateD0: + DBGLOG(OID, INFO, "Set Power State: D0\n"); + kalDevSetPowerState(prAdapter->prGlueInfo, (UINT_32) ParamDeviceStateD0); + fgRetValue = nicpmSetAcpiPowerD0(prAdapter); + break; + case ParamDeviceStateD1: + DBGLOG(OID, INFO, "Set Power State: D1\n"); + /* no break here */ + case ParamDeviceStateD2: + DBGLOG(OID, INFO, "Set Power State: D2\n"); + /* no break here */ + case ParamDeviceStateD3: + DBGLOG(OID, INFO, "Set Power State: D3\n"); + fgRetValue = nicpmSetAcpiPowerD3(prAdapter); + kalDevSetPowerState(prAdapter->prGlueInfo, (UINT_32) ParamDeviceStateD3); + break; + default: + break; + } + + if (fgRetValue == TRUE) + return WLAN_STATUS_SUCCESS; + else + return WLAN_STATUS_FAILURE; +} /* end of wlanoidSetAcpiDevicePowerState() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current fragmentation threshold. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryFragThreshold(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryFragThreshold"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + DBGLOG(OID, LOUD, "\n"); + +#if CFG_TX_FRAGMENT + + return WLAN_STATUS_SUCCESS; + +#else + + return WLAN_STATUS_NOT_SUPPORTED; +#endif /* CFG_TX_FRAGMENT */ + +} /* end of wlanoidQueryFragThreshold() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a new fragmentation threshold to the +* driver. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetFragThreshold(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ +#if CFG_TX_FRAGMENT + + return WLAN_STATUS_SUCCESS; + +#else + + return WLAN_STATUS_NOT_SUPPORTED; +#endif /* CFG_TX_FRAGMENT */ + +} /* end of wlanoidSetFragThreshold() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current RTS threshold. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRtsThreshold(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryRtsThreshold"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + DBGLOG(OID, LOUD, "\n"); + + if (u4QueryBufferLen < sizeof(PARAM_RTS_THRESHOLD)) { + *pu4QueryInfoLen = sizeof(PARAM_RTS_THRESHOLD); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + *((PARAM_RTS_THRESHOLD *) pvQueryBuffer) = prAdapter->rWlanInfo.eRtsThreshold; + + return WLAN_STATUS_SUCCESS; + +} /* wlanoidQueryRtsThreshold */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a new RTS threshold to the driver. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetRtsThreshold(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PARAM_RTS_THRESHOLD *prRtsThreshold; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_RTS_THRESHOLD); + if (u4SetBufferLen < sizeof(PARAM_RTS_THRESHOLD)) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prRtsThreshold = (PARAM_RTS_THRESHOLD *) pvSetBuffer; + *prRtsThreshold = prAdapter->rWlanInfo.eRtsThreshold; + + return WLAN_STATUS_SUCCESS; + +} /* wlanoidSetRtsThreshold */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to turn radio off. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetDisassociate(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_MSG_AIS_ABORT_T prAisAbortMsg; + + DEBUGFUNC("wlanoidSetDisassociate"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 0; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in set disassociate! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + /* prepare message to AIS */ + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = FALSE; + prAdapter->rWifiVar.rConnSettings.eReConnectLevel = RECONNECT_LEVEL_USER_SET; + + /* 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_LOCALLY, NULL, 0); + +#if !defined(LINUX) + prAdapter->fgIsRadioOff = TRUE; +#endif + + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetDisassociate */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to query the power save profile. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQuery802dot11PowerSaveProfile(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQuery802dot11PowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen != 0) { + ASSERT(pvQueryBuffer); + +/* *(PPARAM_POWER_MODE) pvQueryBuffer = (PARAM_POWER_MODE)(prAdapter->rWlanInfo.ePowerSaveMode.ucPsProfile); */ + *(PPARAM_POWER_MODE) pvQueryBuffer = + (PARAM_POWER_MODE) (prAdapter->rWlanInfo. + arPowerSaveMode[prAdapter->prAisBssInfo->ucBssIndex].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; + P_PARAM_POWER_MODE_T prPowerMode; + P_BSS_INFO_T prBssInfo; + + const PUINT_8 apucPsMode[Param_PowerModeMax] = { + (PUINT_8) "CAM", + (PUINT_8) "MAX PS", + (PUINT_8) "FAST PS" + }; + + DEBUGFUNC("wlanoidSet802dot11PowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_POWER_MODE_T); + prPowerMode = (P_PARAM_POWER_MODE_T) pvSetBuffer; + + if (u4SetBufferLen < sizeof(PARAM_POWER_MODE_T)) { + DBGLOG(OID, WARN, "Set power mode error: Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } else if (prPowerMode->ePowerMode >= Param_PowerModeMax) { + DBGLOG(OID, WARN, "Set power mode error: Invalid power mode(%u)\n", prPowerMode->ePowerMode); + return WLAN_STATUS_INVALID_DATA; + } else if (prPowerMode->ucBssIdx >= BSS_INFO_NUM) { + DBGLOG(OID, WARN, "Set power mode error: Invalid BSS index(%d)\n", prPowerMode->ucBssIdx); + return WLAN_STATUS_INVALID_DATA; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prPowerMode->ucBssIdx); + + if (prAdapter->fgEnCtiaPowerMode) { + if (prPowerMode->ePowerMode != Param_PowerModeCAM) { + /* User setting to PS mode (Param_PowerModeMAX_PSP or Param_PowerModeFast_PSP) */ + + if (prAdapter->u4CtiaPowerMode == 0) + /* force to keep in CAM mode */ + prPowerMode->ePowerMode = Param_PowerModeCAM; + else if (prAdapter->u4CtiaPowerMode == 1) + prPowerMode->ePowerMode = Param_PowerModeMAX_PSP; + else if (prAdapter->u4CtiaPowerMode == 2) + prPowerMode->ePowerMode = Param_PowerModeFast_PSP; + } + } else if (prAdapter->rWifiVar.ePowerMode != Param_PowerModeMax) + prPowerMode->ePowerMode = prAdapter->rWifiVar.ePowerMode; + + nicPowerSaveInfoMap(prAdapter, prPowerMode->ucBssIdx, + prPowerMode->ePowerMode, PS_CALLER_COMMON); + + status = nicConfigPowerSaveProfile(prAdapter, prPowerMode->ucBssIdx, prPowerMode->ePowerMode, TRUE); + + if (prPowerMode->ePowerMode < Param_PowerModeMax) { + if (prBssInfo->eNetworkType >= 0 && prPowerMode->ePowerMode >= 0) + DBGLOG(OID, INFO, "Set %s Network BSS(%u) PS mode to %s (%d)\n", + apucNetworkType[prBssInfo->eNetworkType], + prPowerMode->ucBssIdx, apucPsMode[prPowerMode->ePowerMode], prPowerMode->ePowerMode); + } else { + if (prBssInfo->eNetworkType >= 0) + DBGLOG(OID, INFO, "Invalid PS mode setting (%d) for %s Network BSS(%u)\n", + prPowerMode->ePowerMode, apucNetworkType[prBssInfo->eNetworkType], prPowerMode->ucBssIdx); + } + + 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->prAisBssInfo->ucPrimaryChannel); + else + *(PUINT_32) pvQueryBuffer = 0; + } else + *(PUINT_32) pvQueryBuffer = nicChannelNum2Freq(prAdapter->rWifiVar.rConnSettings.ucAdHocChannelNum); + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidQueryFrequency() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set RF frequency by User Settings. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetFrequency(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PUINT_32 pu4FreqInKHz; + + DEBUGFUNC("wlanoidSetFrequency"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(UINT_32); + + if (u4SetBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + pu4FreqInKHz = (PUINT_32) pvSetBuffer; + + prAdapter->rWifiVar.rConnSettings.ucAdHocChannelNum = (UINT_8) nicFreq2ChannelNum(*pu4FreqInKHz); + prAdapter->rWifiVar.rConnSettings.eAdHocBand = *pu4FreqInKHz < 5000000 ? BAND_2G4 : BAND_5G; + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetFrequency() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set 802.11 channel of the radio frequency. +* This is a proprietary function call to Lunux currently. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetChannel(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + ASSERT(0); /* // */ + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the Beacon Interval from User Settings. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryBeaconInterval(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryBeaconInterval"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(UINT_32); + + if (u4QueryBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_INFRA) + *(PUINT_32) pvQueryBuffer = prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4BeaconPeriod; + else + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rWlanInfo.u2BeaconPeriod; + } else { + if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_INFRA) + *(PUINT_32) pvQueryBuffer = 0; + else + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rWlanInfo.u2BeaconPeriod; + } + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidQueryBeaconInterval() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the Beacon Interval to User Settings. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBeaconInterval(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PUINT_32 pu4BeaconInterval; + + DEBUGFUNC("wlanoidSetBeaconInterval"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(UINT_32); + if (u4SetBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + pu4BeaconInterval = (PUINT_32) pvSetBuffer; + + if ((*pu4BeaconInterval < DOT11_BEACON_PERIOD_MIN) + || (*pu4BeaconInterval > DOT11_BEACON_PERIOD_MAX)) { + DBGLOG(OID, TRACE, "Invalid Beacon Interval = %u\n", *pu4BeaconInterval); + return WLAN_STATUS_INVALID_DATA; + } + + prAdapter->rWlanInfo.u2BeaconPeriod = (UINT_16) *pu4BeaconInterval; + + DBGLOG(OID, INFO, "Set beacon interval: %d\n", prAdapter->rWlanInfo.u2BeaconPeriod); + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetBeaconInterval() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the ATIM window from User Settings. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryAtimWindow(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryAtimWindow"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(UINT_32); + + if (u4QueryBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_INFRA) + *(PUINT_32) pvQueryBuffer = 0; + else + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rWlanInfo.u2AtimWindow; + + return WLAN_STATUS_SUCCESS; + +} /* end of wlanoidQueryAtimWindow() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the ATIM window to User Settings. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAtimWindow(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PUINT_32 pu4AtimWindow; + + DEBUGFUNC("wlanoidSetAtimWindow"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(UINT_32); + + if (u4SetBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + pu4AtimWindow = (PUINT_32) pvSetBuffer; + + prAdapter->rWlanInfo.u2AtimWindow = (UINT_16) *pu4AtimWindow; + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetAtimWindow() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set the MAC address which is currently used by the NIC. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetCurrentAddr(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + ASSERT(0); /* // */ + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetCurrentAddr() */ + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setting the checksum offload function. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetCSUMOffload(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + UINT_32 u4CSUMFlags; + CMD_BASIC_CONFIG_T rCmdBasicConfig; + + DEBUGFUNC("wlanoidSetCSUMOffload"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(UINT_32); + + if (u4SetBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + u4CSUMFlags = *(PUINT_32) pvSetBuffer; + + kalMemZero(&rCmdBasicConfig, sizeof(CMD_BASIC_CONFIG_T)); + + 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_T), + (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, u4IPv4AddrIdx; + P_CMD_SET_NETWORK_ADDRESS_LIST prCmdNetworkAddressList; + P_PARAM_NETWORK_ADDRESS_LIST prNetworkAddressList = (P_PARAM_NETWORK_ADDRESS_LIST) pvSetBuffer; + P_PARAM_NETWORK_ADDRESS prNetworkAddress; + UINT_32 u4IPv4AddrCount, u4CmdSize; +#if CFG_ENABLE_GTK_FRAME_FILTER + UINT_32 u4IpV4AddrListSize; + P_BSS_INFO_T prBssInfo = &prAdapter->rWifiVar.arBssInfoPool[KAL_NETWORK_TYPE_AIS_INDEX]; +#endif + + DEBUGFUNC("wlanoidSetNetworkAddress"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 4; + + if (u4SetBufferLen < OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress)) + return WLAN_STATUS_INVALID_DATA; + + *pu4SetInfoLen = 0; + u4IPv4AddrCount = 0; + + /* 4 <1.1> Get IPv4 address count */ + /* We only suppot IPv4 address setting */ + prNetworkAddress = prNetworkAddressList->arAddress; + for (i = 0; i < prNetworkAddressList->u4AddressCount; i++) { + if ((prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP) && + (prNetworkAddress->u2AddressLength == IPV4_ADDR_LEN)) { + u4IPv4AddrCount++; + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prNetworkAddress + (ULONG) + (prNetworkAddress->u2AddressLength + + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + + /* 4 <2> Calculate command buffer size */ + /* construct payload of command packet */ + if (u4IPv4AddrCount == 0) + u4CmdSize = sizeof(CMD_SET_NETWORK_ADDRESS_LIST); + else + u4CmdSize = OFFSET_OF(CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress) + + (sizeof(IPV4_NETWORK_ADDRESS) * u4IPv4AddrCount); + + /* 4 <3> Allocate command buffer */ + prCmdNetworkAddressList = (P_CMD_SET_NETWORK_ADDRESS_LIST) kalMemAlloc(u4CmdSize, VIR_MEM_TYPE); + + if (prCmdNetworkAddressList == NULL) + return WLAN_STATUS_FAILURE; + +#if CFG_ENABLE_GTK_FRAME_FILTER + u4IpV4AddrListSize = OFFSET_OF(IPV4_NETWORK_ADDRESS_LIST, arNetAddr) + + (u4IPv4AddrCount * sizeof(IPV4_NETWORK_ADDRESS)); + if (prBssInfo->prIpV4NetAddrList) + FREE_IPV4_NETWORK_ADDR_LIST(prBssInfo->prIpV4NetAddrList); + prBssInfo->prIpV4NetAddrList = (P_IPV4_NETWORK_ADDRESS_LIST) kalMemAlloc(u4IpV4AddrListSize, VIR_MEM_TYPE); + if (prBssInfo->prIpV4NetAddrList == NULL) { + kalMemFree(prCmdNetworkAddressList, VIR_MEM_TYPE, u4CmdSize); + return WLAN_STATUS_FAILURE; + } + prBssInfo->prIpV4NetAddrList->ucAddrCount = (UINT_8) u4IPv4AddrCount; +#endif + + /* 4 <4> Fill P_CMD_SET_NETWORK_ADDRESS_LIST */ + prCmdNetworkAddressList->ucBssIndex = prNetworkAddressList->ucBssIdx; + + /* only to set IP address to FW once ARP filter is enabled */ + if (prAdapter->fgEnArpFilter) { + prCmdNetworkAddressList->ucAddressCount = (UINT_8) u4IPv4AddrCount; + prNetworkAddress = prNetworkAddressList->arAddress; + + /* DBGLOG(INIT, INFO, ("%s: u4IPv4AddrCount (%lu)\n", __FUNCTION__, u4IPv4AddrCount)); */ + + for (i = 0, u4IPv4AddrIdx = 0; i < prNetworkAddressList->u4AddressCount; i++) { + if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == IPV4_ADDR_LEN) { + + kalMemCopy(prCmdNetworkAddressList->arNetAddress[u4IPv4AddrIdx].aucIpAddr, + prNetworkAddress->aucAddress, sizeof(UINT_32)); + +#if CFG_ENABLE_GTK_FRAME_FILTER + kalMemCopy(prBssInfo->prIpV4NetAddrList->arNetAddr[u4IPv4AddrIdx].aucIpAddr, + prNetworkAddress->aucAddress, sizeof(UINT_32)); +#endif + + DBGLOG(OID, INFO, + "%s: IPv4 Addr [%u][" IPV4STR "]\n", __func__, + u4IPv4AddrIdx, IPV4TOSTR(prNetworkAddress->aucAddress)); + + u4IPv4AddrIdx++; + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prNetworkAddress + (ULONG) + (prNetworkAddress->u2AddressLength + + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + + } else { + prCmdNetworkAddressList->ucAddressCount = 0; + } + + DBGLOG(OID, INFO, + "%s: Set %u IPv4 address for BSS[%d]\n", __func__, u4IPv4AddrCount, + prCmdNetworkAddressList->ucBssIndex); + + /* 4 <5> Send command */ + 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(pu4SetInfoLen); + + *pu4SetInfoLen = 0; + + if (u4SetBufferLen == 0) { + if ((prAdapter->fgTestMode == FALSE) + || (prAdapter->fgIcapMode == TRUE)) { + /* switch to RF Test mode */ + rCmdTestCtrl.ucAction = 0; /* Switch mode */ + rCmdTestCtrl.u.u4OpMode = 1; /* RF test mode */ + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_TEST_CTRL, + 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 RF test ICAP 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 +wlanoidRftestSetTestIcapMode(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(pu4SetInfoLen); + + *pu4SetInfoLen = 0; + + if (u4SetBufferLen == 0) { + if (prAdapter->fgIcapMode == FALSE) { + /* switch to RF Test mode */ + rCmdTestCtrl.ucAction = 0; /* Switch mode */ + rCmdTestCtrl.u.u4OpMode = 2; /* RF test mode */ + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_TEST_CTRL, + TRUE, + FALSE, + TRUE, + nicCmdEventEnterRfTest, + nicOidCmdEnterRFTestTimeout, + sizeof(CMD_TEST_CTRL_T), + (PUINT_8) &rCmdTestCtrl, pvSetBuffer, u4SetBufferLen); + } else { + /* already in ICAP 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(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_CTRL, + 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_STRUCT_T prRfATInfo; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidRftestQueryAutoTest"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(PARAM_MTK_WIFI_TEST_STRUCT_T); + + if (u4QueryBufferLen != sizeof(PARAM_MTK_WIFI_TEST_STRUCT_T)) { + DBGLOG(OID, ERROR, "Invalid data. QueryBufferLen: %u.\n", u4QueryBufferLen); + /* return WLAN_STATUS_INVALID_LENGTH; */ + } + + prRfATInfo = (P_PARAM_MTK_WIFI_TEST_STRUCT_T) pvQueryBuffer; + rStatus = rftestQueryATInfo(prAdapter, + prRfATInfo->u4FuncIndex, prRfATInfo->u4FuncData, pvQueryBuffer, u4QueryBufferLen); + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set RF test parameter +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +* \return WLAN_STATUS_ADAPTER_NOT_READY +* \return WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidRftestSetAutoTest(IN P_ADAPTER_T prAdapter, + OUT PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_MTK_WIFI_TEST_STRUCT_T prRfATInfo; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidRftestSetAutoTest"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_MTK_WIFI_TEST_STRUCT_T); + + if (u4SetBufferLen != sizeof(PARAM_MTK_WIFI_TEST_STRUCT_T)) { + DBGLOG(OID, ERROR, "Invalid data. SetBufferLen: %u.\n", u4SetBufferLen); + /* return WLAN_STATUS_INVALID_LENGTH; */ + } + + prRfATInfo = (P_PARAM_MTK_WIFI_TEST_STRUCT_T) pvSetBuffer; + + DBGLOG(OID, TRACE, "u4FuncIndex(%u)-u4FuncData(%u)\n", + prRfATInfo->u4FuncIndex, prRfATInfo->u4FuncData); + + rStatus = rftestSetATInfo(prAdapter, prRfATInfo->u4FuncIndex, prRfATInfo->u4FuncData); + + return rStatus; +} + +/* RF test OID set handler */ +WLAN_STATUS rftestSetATInfo(IN P_ADAPTER_T prAdapter, UINT_32 u4FuncIndex, UINT_32 u4FuncData) +{ + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_CMD_TEST_CTRL_T pCmdTestCtrl; + UINT_8 ucCmdSeqNum; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_TEST_CTRL_T))); + + if (!prCmdInfo) { + DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_TEST_CTRL_T); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_TEST_CTRL; + 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 = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + 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; + + if ((u4FuncIndex == RF_AT_FUNCID_COMMAND) && (u4FuncData == RF_AT_COMMAND_ICAP)) { + g_bIcapEnable = TRUE; + g_bCaptureDone = FALSE; + } + /* ICAP dump name Reset */ + if ((u4FuncIndex == RF_AT_FUNCID_COMMAND) && (u4FuncData == RF_AT_COMMAND_RESET_DUMP_NAME)) + g_u2DumpIndex = 0; + /* 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); + prTestStatus->rATInfo.u4FuncData2 = prAdapter->rVerInfo.u4FwOwnVersionExtend; + u4QueryBufferLen = sizeof(EVENT_TEST_STATUS); + + } 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); + + } else if (u4FuncIndex == RF_AT_FUNCID_QUERY_ICAP_DUMP_FILE) { + /* driver implementation */ + prTestStatus = (P_EVENT_TEST_STATUS) pvQueryBuffer; + + prTestStatus->rATInfo.u4FuncData = g_u2DumpIndex; + u4QueryBufferLen = sizeof(EVENT_TEST_STATUS); + + } 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_CTRL; + 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 = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + 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; + } + + return WLAN_STATUS_SUCCESS; +} + +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_CTRL, + 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; + + if (!prAdapter || !prAdapter->prAisBssInfo) { + DBGLOG(OID, ERROR, "prAdapter or prAisBssInfo is not allocated.\n"); + return WLAN_STATUS_FAILURE; + } + + prGlueInfo = prAdapter->prGlueInfo; + if (!prGlueInfo) { + /* When wlanRemove is called, can't do wlanTriggerStatsLog in auth/assoc tx done */ + return WLAN_STATUS_FAILURE; + } + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + u4SetQueryInfoLen)); + + DEBUGFUNC("wlanSendSetQueryCmd"); + + if (!prCmdInfo) { + DBGLOG(OID, ERROR, "prCmdInfo is not allocated.\n"); + return WLAN_STATUS_FAILURE; + } + + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + DBGLOG(OID, TRACE, "ucCmdSeqNum =%d\n", ucCmdSeqNum); + + /* Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + 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 = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + if (u4SetQueryInfoLen > 0 && pucInfoBuffer != NULL) + kalMemCopy(prWifiCmd->aucBuffer, pucInfoBuffer, u4SetQueryInfoLen); + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + return WLAN_STATUS_PENDING; +} + +#if CFG_SUPPORT_WAPI +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called by WAPI ui to set wapi mode, which is needed to info the the driver +* to operation at WAPI mode while driver initialize. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. +* \retval WLAN_STATUS_INVALID_LENGTH +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetWapiMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + DEBUGFUNC("wlanoidSetWapiMode"); + DBGLOG(OID, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + /* Todo:: For support WAPI and Wi-Fi at same driver, use the set wapi assoc ie at the check point */ + /* The Adapter Connection setting fgUseWapi will cleat whil oid set mode (infra), */ + /* And set fgUseWapi True while set wapi assoc ie */ + /* policay selection, add key all depend on this flag, */ + /* The fgUseWapi may remove later */ + if (*(PUINT_32) pvSetBuffer) + prAdapter->fgUseWapi = TRUE; + else + prAdapter->fgUseWapi = FALSE; + +#if 0 + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + 4)); + + if (!prCmdInfo) { + DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_BUILD_CONNECTION cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + 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 = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + 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; + P_CONNECTION_SETTINGS_T prConnSettings; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + DEBUGFUNC("wlanoidSetWapiAssocInfo"); + DBGLOG(OID, LOUD, "\r\n"); + + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + prConnSettings->fgWapiMode = FALSE; + + if (u4SetBufferLen < 20 /* From EID to Group cipher */) + return WLAN_STATUS_INVALID_LENGTH; + + if (!wextSrchDesiredWAPIIE((PUINT_8) pvSetBuffer, u4SetBufferLen, (PUINT_8 *) &prWapiInfo)) + return WLAN_STATUS_INVALID_LENGTH; + + if (!prWapiInfo || prWapiInfo->ucLength < 18) + return WLAN_STATUS_INVALID_LENGTH; + + /* Skip Version check */ + + /*Cipher suite count check, only one of each for now*/ + if (prWapiInfo->u2AKMSuiteCount > 1 || + prWapiInfo->u2PairSuiteCount > 1) + return WLAN_STATUS_INVALID_LENGTH; + + DBGLOG(SEC, TRACE, "WAPI: Assoc Info auth mgt suite [%d]: %02x-%02x-%02x-%02x\n", + prWapiInfo->u2AKMSuiteCount, + (UCHAR) (prWapiInfo->u4AKMSuite & 0x000000FF), + (UCHAR) ((prWapiInfo->u4AKMSuite >> 8) & 0x000000FF), + (UCHAR) ((prWapiInfo->u4AKMSuite >> 16) & 0x000000FF), + (UCHAR) ((prWapiInfo->u4AKMSuite >> 24) & 0x000000FF)); + + if (prWapiInfo->u4AKMSuite != WAPI_AKM_SUITE_802_1X && + prWapiInfo->u4AKMSuite != WAPI_AKM_SUITE_PSK) + return WLAN_STATUS_NOT_SUPPORTED; + + DBGLOG(SEC, TRACE, "WAPI: Assoc Info pairwise cipher suite [%d]: %02x-%02x-%02x-%02x\n", + prWapiInfo->u2PairSuiteCount, + (UCHAR) (prWapiInfo->u4PairSuite & 0x000000FF), + (UCHAR) ((prWapiInfo->u4PairSuite >> 8) & 0x000000FF), + (UCHAR) ((prWapiInfo->u4PairSuite >> 16) & 0x000000FF), + (UCHAR) ((prWapiInfo->u4PairSuite >> 24) & 0x000000FF)); + + if (prWapiInfo->u4PairSuite != WAPI_CIPHER_SUITE_WPI) + return WLAN_STATUS_NOT_SUPPORTED; + + DBGLOG(SEC, TRACE, "WAPI: Assoc Info group cipher suite : %02x-%02x-%02x-%02x\n", + (UCHAR) (prWapiInfo->u4GroupSuite & 0x000000FF), + (UCHAR) ((prWapiInfo->u4GroupSuite >> 8) & 0x000000FF), + (UCHAR) ((prWapiInfo->u4GroupSuite >> 16) & 0x000000FF), + (UCHAR) ((prWapiInfo->u4GroupSuite >> 24) & 0x000000FF)); + + if (prWapiInfo->u4GroupSuite != WAPI_CIPHER_SUITE_WPI) + return WLAN_STATUS_NOT_SUPPORTED; + + prConnSettings->u4WapiSelectedAKMSuite = prWapiInfo->u4AKMSuite; + prConnSettings->u4WapiSelectedPairwiseCipher = prWapiInfo->u4PairSuite; + prConnSettings->u4WapiSelectedGroupCipher = prWapiInfo->u4GroupSuite; + + prConnSettings->fgWapiMode = TRUE; + + 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; + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prBssInfo; + + DEBUGFUNC("wlanoidSetWapiKey"); + DBGLOG(OID, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in set add key! (Adapter not ready). ACPI=D%d, Radio=%d\r\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + prNewKey = (P_PARAM_WPI_KEY_T) pvSetBuffer; + + DBGLOG_MEM8(OID, TRACE, (PUINT_8) pvSetBuffer, 560); + pc = (PUINT_8) pvSetBuffer; + + *pu4SetInfoLen = u4SetBufferLen; + + /* Todo:: WAPI AP mode !!!!! */ + prBssInfo = prAdapter->prAisBssInfo; + + prNewKey->ucKeyID = prNewKey->ucKeyID & BIT(0); + + /* Dump P_PARAM_WPI_KEY_T content. */ + DBGLOG(OID, TRACE, "Set: Dump P_PARAM_WPI_KEY_T content\r\n"); + DBGLOG(OID, TRACE, "TYPE : %d\r\n", prNewKey->eKeyType); + DBGLOG(OID, TRACE, "Direction : %d\r\n", prNewKey->eDirection); + DBGLOG(OID, TRACE, "KeyID : %d\r\n", prNewKey->ucKeyID); + DBGLOG(OID, TRACE, "AddressIndex:\r\n"); + DBGLOG_MEM8(OID, TRACE, prNewKey->aucAddrIndex, 12); + prNewKey->u4LenWPIEK = 16; + + DBGLOG_MEM8(OID, TRACE, (PUINT_8) prNewKey->aucWPIEK, (UINT_8) prNewKey->u4LenWPIEK); + prNewKey->u4LenWPICK = 16; + + DBGLOG(OID, TRACE, "CK Key(%d):\r\n", (UINT_8) prNewKey->u4LenWPICK); + DBGLOG_MEM8(OID, TRACE, (PUINT_8) prNewKey->aucWPICK, (UINT_8) prNewKey->u4LenWPICK); + DBGLOG(OID, TRACE, "PN:\r\n"); + if (prNewKey->eKeyType == 0) { + prNewKey->aucPN[0] = 0x5c; + prNewKey->aucPN[1] = 0x36; + prNewKey->aucPN[2] = 0x5c; + prNewKey->aucPN[3] = 0x36; + prNewKey->aucPN[4] = 0x5c; + prNewKey->aucPN[5] = 0x36; + prNewKey->aucPN[6] = 0x5c; + prNewKey->aucPN[7] = 0x36; + prNewKey->aucPN[8] = 0x5c; + prNewKey->aucPN[9] = 0x36; + prNewKey->aucPN[10] = 0x5c; + prNewKey->aucPN[11] = 0x36; + prNewKey->aucPN[12] = 0x5c; + prNewKey->aucPN[13] = 0x36; + prNewKey->aucPN[14] = 0x5c; + prNewKey->aucPN[15] = 0x36; + } + + DBGLOG_MEM8(OID, TRACE, (PUINT_8) prNewKey->aucPN, 16); + + prGlueInfo = prAdapter->prGlueInfo; + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + u4SetBufferLen)); + + if (!prCmdInfo) { + DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_ID_ADD_REMOVE_KEY cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + 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 = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + 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); + if ((prCmdKey->aucPeerAddr[0] & prCmdKey->aucPeerAddr[1] & prCmdKey->aucPeerAddr[2] & + prCmdKey->aucPeerAddr[3] & prCmdKey->aucPeerAddr[4] & prCmdKey->aucPeerAddr[5]) == 0xFF) { + prStaRec = cnmGetStaRecByAddress(prAdapter, prBssInfo->ucBssIndex, prBssInfo->aucBSSID); + ASSERT(prStaRec); /* AIS RSN Group key, addr is BC addr */ + kalMemCopy(prCmdKey->aucPeerAddr, prStaRec->aucMacAddr, MAC_ADDR_LEN); + } else { + prStaRec = cnmGetStaRecByAddress(prAdapter, prBssInfo->ucBssIndex, prCmdKey->aucPeerAddr); + } + + prCmdKey->ucBssIdx = prAdapter->prAisBssInfo->ucBssIndex; /* 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); + + if (prCmdKey->ucTxKey) { + if (prStaRec) { + if (prCmdKey->ucKeyType) { /* AIS RSN STA */ + prCmdKey->ucWlanIndex = prStaRec->ucWlanIndex; + prStaRec->fgTransmitKeyExist = TRUE; /* wait for CMD Done ? */ + } else { + ASSERT(FALSE); + } + } +#if 0 + if (fgAddTxBcKey || !prStaRec) { + + if ((prCmdKey->aucPeerAddr[0] & prCmdKey->aucPeerAddr[1] & prCmdKey->aucPeerAddr[2] & prCmdKey-> + aucPeerAddr[3] & prCmdKey->aucPeerAddr[4] & prCmdKey->aucPeerAddr[5]) == 0xFF) { + prCmdKey->ucWlanIndex = 255; /* AIS WEP Tx key */ + } else { /* Exist this case ? */ + ASSERT(FALSE); + /* prCmdKey->ucWlanIndex = */ + /* secPrivacySeekForBcEntry(prAdapter, */ + /* prBssInfo->ucBssIndex, */ + /* NETWORK_TYPE_AIS, */ + /* prCmdKey->aucPeerAddr, */ + /* prCmdKey->ucAlgorithmId, */ + /* prCmdKey->ucKeyId, */ + /* prBssInfo->ucCurrentGtkId, */ + /* BIT(1)); */ + } + + prBssInfo->fgTxBcKeyExist = TRUE; + prBssInfo->ucBMCWlanIndex = prCmdKey->ucWlanIndex; /* Saved for AIS WEP */ + prBssInfo->ucTxDefaultKeyID = prCmdKey->ucKeyId; + } +#endif + } else { + /* Including IBSS RSN Rx BC key ? */ + if ((prCmdKey->aucPeerAddr[0] & prCmdKey->aucPeerAddr[1] & prCmdKey->aucPeerAddr[2] & prCmdKey-> + aucPeerAddr[3] & prCmdKey->aucPeerAddr[4] & prCmdKey->aucPeerAddr[5]) == 0xFF) { + prCmdKey->ucWlanIndex = 255; /* AIS WEP, should not have this case!! */ + } else { + if (prStaRec) { /* AIS RSN Group key but addr is BSSID */ + /* ASSERT(prStaRec->ucBMCWlanIndex < WTBL_SIZE) */ + prCmdKey->ucWlanIndex = + secPrivacySeekForBcEntry(prAdapter, prStaRec->ucBssIndex, + prStaRec->aucMacAddr, + prStaRec->ucIndex, + prCmdKey->ucAlgorithmId, + prCmdKey->ucKeyId, prStaRec->ucCurrentGtkId, BIT(0)); + prStaRec->ucBMCWlanIndex = prCmdKey->ucWlanIndex; + } else { /* Exist this case ? */ + ASSERT(FALSE); + /* prCmdKey->ucWlanIndex = */ + /* secPrivacySeekForBcEntry(prAdapter, */ + /* prBssInfo->ucBssIndex, */ + /* NETWORK_TYPE_AIS, */ + /* prCmdKey->aucPeerAddr, */ + /* prCmdKey->ucAlgorithmId, */ + /* prCmdKey->ucKeyId, */ + /* prBssInfo->ucCurrentGtkId, */ + /* BIT(0)); */ + } + } + } + + /* 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_ENABLE_WAKEUP_ON_LAN +WLAN_STATUS +wlanoidSetAddWakeupPattern(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_PM_PACKET_PATTERN prPacketPattern; + + DEBUGFUNC("wlanoidSetAddWakeupPattern"); + DBGLOG(OID, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_PM_PACKET_PATTERN); + + if (u4SetBufferLen < sizeof(PARAM_PM_PACKET_PATTERN)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prPacketPattern = (P_PARAM_PM_PACKET_PATTERN) pvSetBuffer; + + /* + * FIXME: + * Send the struct to firmware + */ + + return WLAN_STATUS_FAILURE; +} + +WLAN_STATUS +wlanoidSetRemoveWakeupPattern(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_PM_PACKET_PATTERN prPacketPattern; + + DEBUGFUNC("wlanoidSetAddWakeupPattern"); + DBGLOG(OID, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_PM_PACKET_PATTERN); + + if (u4SetBufferLen < sizeof(PARAM_PM_PACKET_PATTERN)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prPacketPattern = (P_PARAM_PM_PACKET_PATTERN) pvSetBuffer; + + /* + * FIXME: + * Send the struct to firmware + */ + + return WLAN_STATUS_FAILURE; +} + +WLAN_STATUS +wlanoidQueryEnableWakeup(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + PUINT_32 pu4WakeupEventEnable; + + DEBUGFUNC("wlanoidQueryEnableWakeup"); + DBGLOG(OID, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(UINT_32); + + if (u4QueryBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + pu4WakeupEventEnable = (PUINT_32) pvQueryBuffer; + + *pu4WakeupEventEnable = prAdapter->u4WakeupEventEnable; + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidSetEnableWakeup(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PUINT_32 pu4WakeupEventEnable; + + DEBUGFUNC("wlanoidSetEnableWakup"); + DBGLOG(OID, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(UINT_32); + + if (u4SetBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + pu4WakeupEventEnable = (PUINT_32) pvSetBuffer; + prAdapter->u4WakeupEventEnable = *pu4WakeupEventEnable; + + /* + * FIXME: + * Send Command Event for setting wakeup-pattern / Magic Packet to firmware + */ + + return WLAN_STATUS_FAILURE; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to configure PS related settings for WMM-PS test. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetWiFiWmmPsTest(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T prWmmPsTestInfo; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + CMD_SET_WMM_PS_TEST_STRUCT_T rSetWmmPsTestParam; + UINT_16 u2CmdBufLen; + P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo; + P_BSS_INFO_T prBssInfo; + + DEBUGFUNC("wlanoidSetWiFiWmmPsTest"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T); + + prWmmPsTestInfo = (P_PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T) pvSetBuffer; + + rSetWmmPsTestParam.ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + rSetWmmPsTestParam.bmfgApsdEnAc = prWmmPsTestInfo->bmfgApsdEnAc; + rSetWmmPsTestParam.ucIsEnterPsAtOnce = prWmmPsTestInfo->ucIsEnterPsAtOnce; + rSetWmmPsTestParam.ucIsDisableUcTrigger = prWmmPsTestInfo->ucIsDisableUcTrigger; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, rSetWmmPsTestParam.ucBssIndex); + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + prPmProfSetupInfo->ucBmpDeliveryAC = (rSetWmmPsTestParam.bmfgApsdEnAc >> 4) & BITS(0, 3); + prPmProfSetupInfo->ucBmpTriggerAC = rSetWmmPsTestParam.bmfgApsdEnAc & BITS(0, 3); + + u2CmdBufLen = sizeof(CMD_SET_WMM_PS_TEST_STRUCT_T); + +#if 0 + /* it will apply the disable trig or not immediately */ + if (prPmInfo->ucWmmPsDisableUcPoll && prPmInfo->ucWmmPsConnWithTrig) + ; /* NIC_PM_WMM_PS_DISABLE_UC_TRIG(prAdapter, TRUE); */ + else + ; /* NIC_PM_WMM_PS_DISABLE_UC_TRIG(prAdapter, FALSE); */ +#endif + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_WMM_PS_TEST_PARMS, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + u2CmdBufLen, + (PUINT_8) (&rSetWmmPsTestParam), + NULL, + 0); + return rStatus; +} /* wlanoidSetWiFiWmmPsTest */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to configure enable/disable TX A-MPDU feature. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetTxAmpdu(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + CMD_TX_AMPDU_T rTxAmpdu; + UINT_16 u2CmdBufLen; + PBOOLEAN pfgEnable; + + DEBUGFUNC("wlanoidSetTxAmpdu"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(BOOLEAN); + + pfgEnable = (PBOOLEAN) pvSetBuffer; + + rTxAmpdu.fgEnable = *pfgEnable; + + u2CmdBufLen = sizeof(CMD_TX_AMPDU_T); + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_TX_AMPDU, + TRUE, FALSE, TRUE, NULL, NULL, u2CmdBufLen, (PUINT_8) &rTxAmpdu, NULL, 0); + + return rStatus; +} /* wlanoidSetTxAmpdu */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to configure reject/accept ADDBA Request. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAddbaReject(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + CMD_ADDBA_REJECT_T rAddbaReject; + UINT_16 u2CmdBufLen; + PBOOLEAN pfgEnable; + + DEBUGFUNC("wlanoidSetAddbaReject"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(BOOLEAN); + + pfgEnable = (PBOOLEAN) pvSetBuffer; + + rAddbaReject.fgEnable = *pfgEnable; + + u2CmdBufLen = sizeof(CMD_ADDBA_REJECT_T); + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_ADDBA_REJECT, + TRUE, FALSE, TRUE, NULL, NULL, u2CmdBufLen, (PUINT_8) &rAddbaReject, NULL, 0); + + return rStatus; +} /* wlanoidSetAddbaReject */ + +#if CFG_SLT_SUPPORT + +WLAN_STATUS +wlanoidQuerySLTStatus(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_PARAM_MTK_SLT_TEST_STRUCT_T prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUCT_T) NULL; + P_SLT_INFO_T prSltInfo = (P_SLT_INFO_T) NULL; + + DEBUGFUNC("wlanoidQuerySLTStatus"); + DBGLOG(OID, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(PARAM_MTK_SLT_TEST_STRUCT_T); + + if (u4QueryBufferLen < sizeof(PARAM_MTK_SLT_TEST_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvQueryBuffer); + + prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUCT_T) pvQueryBuffer; + + prSltInfo = &(prAdapter->rWifiVar.rSltInfo); + + switch (prMtkSltInfo->rSltFuncIdx) { + case ENUM_MTK_SLT_FUNC_LP_SET: + { + P_PARAM_MTK_SLT_LP_TEST_STRUCT_T prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUCT_T) NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_LP_TEST_STRUCT_T)); + + prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUCT_T) &prMtkSltInfo->unFuncInfoContent; + + prLpSetting->u4BcnRcvNum = prSltInfo->u4BeaconReceiveCnt; + } + break; + default: + /* TBD... */ + break; + } + + return rWlanStatus; +} /* wlanoidQuerySLTStatus */ + +WLAN_STATUS +wlanoidUpdateSLTMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_PARAM_MTK_SLT_TEST_STRUCT_T prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUCT_T) NULL; + P_SLT_INFO_T prSltInfo = (P_SLT_INFO_T) NULL; + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; + + /* 1. Action: Update or Initial Set + * 2. Role. + * 3. Target MAC address. + * 4. RF BW & Rate Settings + */ + + DEBUGFUNC("wlanoidUpdateSLTMode"); + DBGLOG(OID, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_MTK_SLT_TEST_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_MTK_SLT_TEST_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUCT_T) pvSetBuffer; + + prSltInfo = &(prAdapter->rWifiVar.rSltInfo); + prBssInfo = prAdapter->prAisBssInfo; + + switch (prMtkSltInfo->rSltFuncIdx) { + case ENUM_MTK_SLT_FUNC_INITIAL: /* Initialize */ + { + P_PARAM_MTK_SLT_INITIAL_STRUCT_T prMtkSltInit = (P_PARAM_MTK_SLT_INITIAL_STRUCT_T) NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_INITIAL_STRUCT_T)); + + prMtkSltInit = (P_PARAM_MTK_SLT_INITIAL_STRUCT_T) &prMtkSltInfo->unFuncInfoContent; + + if (prSltInfo->prPseudoStaRec != NULL) { + /* The driver has been initialized. */ + prSltInfo->prPseudoStaRec = NULL; + } + + prSltInfo->prPseudoBssDesc = scanSearchExistingBssDesc(prAdapter, + BSS_TYPE_IBSS, + prMtkSltInit->aucTargetMacAddr, + prMtkSltInit->aucTargetMacAddr); + + prSltInfo->u2SiteID = prMtkSltInit->u2SiteID; + + /* Bandwidth 2.4G: Channel 1~14 + * Bandwidth 5G: *36, 40, 44, 48, 52, 56, 60, 64, + * *100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, + * 149, 153, *157, 161, + * 184, 188, 192, 196, 200, 204, 208, 212, *216 + */ + prSltInfo->ucChannel2G4 = 1 + (prSltInfo->u2SiteID % 4) * 5; + + switch (prSltInfo->ucChannel2G4) { + case 1: + prSltInfo->ucChannel5G = 36; + break; + case 6: + prSltInfo->ucChannel5G = 52; + break; + case 11: + prSltInfo->ucChannel5G = 104; + break; + case 16: + prSltInfo->ucChannel2G4 = 14; + prSltInfo->ucChannel5G = 161; + break; + default: + ASSERT(FALSE); + } + + if (prSltInfo->prPseudoBssDesc == NULL) { + do { + prSltInfo->prPseudoBssDesc = scanAllocateBssDesc(prAdapter); + + if (prSltInfo->prPseudoBssDesc == NULL) + rWlanStatus = WLAN_STATUS_FAILURE; + 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_STRUCT_T prTRSetting = (P_PARAM_MTK_SLT_TR_TEST_STRUCT_T) NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_TR_TEST_STRUCT_T)); + + prStaRec = prSltInfo->prPseudoStaRec; + prTRSetting = (P_PARAM_MTK_SLT_TR_TEST_STRUCT_T) &prMtkSltInfo->unFuncInfoContent; + + if (prTRSetting->rNetworkType == PARAM_NETWORK_TYPE_OFDM5) { + prBssInfo->eBand = BAND_5G; + prBssInfo->ucPrimaryChannel = prSltInfo->ucChannel5G; + } + if (prTRSetting->rNetworkType == PARAM_NETWORK_TYPE_OFDM24) { + prBssInfo->eBand = BAND_2G4; + prBssInfo->ucPrimaryChannel = prSltInfo->ucChannel2G4; + } + + if ((prTRSetting->u4FixedRate & FIXED_BW_DL40) != 0) { + /* RF 40 */ + /* It would controls RFBW capability in WTBL. */ + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; + /* This controls RF BW, RF BW would be 40 only if + * 1. PHY_TYPE_BIT_HT is TRUE. + * 2. SCO is SCA/SCB. + */ + prStaRec->ucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + + /* U20/L20 Control. */ + switch (prTRSetting->u4FixedRate & 0xC000) { + case FIXED_EXT_CHNL_U20: + prBssInfo->eBssSCO = CHNL_EXT_SCB; /* +2 */ + if (prTRSetting->rNetworkType == PARAM_NETWORK_TYPE_OFDM5) { + prBssInfo->ucPrimaryChannel += 2; + } else { + /* For channel 1, testing L20 at channel 8. AOSP */ + SetTestChannel(&prBssInfo->ucPrimaryChannel); + } + break; + case FIXED_EXT_CHNL_L20: + default: /* 40M */ + prBssInfo->eBssSCO = CHNL_EXT_SCA; /* -2 */ + if (prTRSetting->rNetworkType == PARAM_NETWORK_TYPE_OFDM5) { + prBssInfo->ucPrimaryChannel -= 2; + } else { + /* For channel 11 / 14. testing U20 at channel 3. AOSP */ + SetTestChannel(&prBssInfo->ucPrimaryChannel); + } + 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_SW_INDEX); + break; + case RATE_OFDM_48M: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_48M_SW_INDEX); + break; + case RATE_OFDM_36M: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_36M_SW_INDEX); + break; + case RATE_OFDM_24M: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_24M_SW_INDEX); + break; + case RATE_OFDM_6M: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_6M_SW_INDEX); + break; + case RATE_CCK_11M_LONG: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_11M_SW_INDEX); + break; + case RATE_CCK_1M_LONG: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_1M_SW_INDEX); + break; + case RATE_GF_MCS_0: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_HT_PHY_SW_INDEX); + prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + break; + case RATE_MM_MCS_7: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_HT_PHY_SW_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_SW_INDEX); + prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + break; + default: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_36M_SW_INDEX); + break; + } + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + } + break; + case ENUM_MTK_SLT_FUNC_LP_SET: /* Reset LP Test Result. */ + { + P_PARAM_MTK_SLT_LP_TEST_STRUCT_T prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUCT_T) NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_LP_TEST_STRUCT_T)); + + prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUCT_T) &prMtkSltInfo->unFuncInfoContent; + + /* Please initial SLT Mode first. */ + if (prSltInfo->prPseudoBssDesc == NULL) + break; + + prBssDesc = prSltInfo->prPseudoBssDesc; + + switch (prLpSetting->rLpTestMode) { + case ENUM_MTK_LP_TEST_NORMAL: + /* In normal mode, we would use target MAC address to be the BSSID. */ + COPY_MAC_ADDR(prBssDesc->aucBSSID, prBssInfo->aucOwnMacAddr); + prSltInfo->fgIsDUT = FALSE; + break; + case ENUM_MTK_LP_TEST_GOLDEN_SAMPLE: + /* 1. Lower AIFS of BCN queue. + * 2. Fixed Random Number tobe 0. + */ + prSltInfo->fgIsDUT = FALSE; + /* In LP test mode, we would use MAC address of Golden Sample to be the BSSID. */ + COPY_MAC_ADDR(prBssDesc->aucBSSID, prBssInfo->aucOwnMacAddr); + break; + case ENUM_MTK_LP_TEST_DUT: + /* 1. Enter Sleep Mode. + * 2. Fix random number a large value & enlarge AIFN of BCN queue. + */ + COPY_MAC_ADDR(prBssDesc->aucBSSID, prBssDesc->aucSrcAddr); + prSltInfo->u4BeaconReceiveCnt = 0; + prSltInfo->fgIsDUT = TRUE; + break; + } + + } + + break; + default: + break; + } + + return WLAN_STATUS_FAILURE; + + return rWlanStatus; +} /* wlanoidUpdateSLTMode */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query NVRAM value. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryNvramRead(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T prNvramRwInfo; + UINT_16 u2Data; + BOOLEAN fgStatus; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryNvramRead"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_NVRAM_RW_STRUCT_T); + + if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_NVRAM_RW_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + prNvramRwInfo = (P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T) pvQueryBuffer; + + if (prNvramRwInfo->ucEepromMethod == PARAM_EEPROM_READ_METHOD_READ) { + fgStatus = kalCfgDataRead16(prAdapter->prGlueInfo, prNvramRwInfo->ucEepromIndex << 1, + &u2Data); /* change to byte offset */ + + if (fgStatus) { + prNvramRwInfo->u2EepromData = u2Data; + DBGLOG(OID, INFO, "NVRAM Read: index=%#X, data=%#02X\r\n", + prNvramRwInfo->ucEepromIndex, u2Data); + } else { + DBGLOG(OID, ERROR, "NVRAM Read Failed: index=%#x.\r\n", prNvramRwInfo->ucEepromIndex); + rStatus = WLAN_STATUS_FAILURE; + } + } else if (prNvramRwInfo->ucEepromMethod == PARAM_EEPROM_READ_METHOD_GETSIZE) { + prNvramRwInfo->u2EepromData = CFG_FILE_WIFI_REC_SIZE; + DBGLOG(OID, INFO, "EEPROM size =%d\r\n", prNvramRwInfo->u2EepromData); + } + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T); + + return rStatus; +} /* wlanoidQueryNvramRead */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to write NVRAM value. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetNvramWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T prNvramRwInfo; + BOOLEAN fgStatus; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidSetNvramWrite"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_NVRAM_RW_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_NVRAM_RW_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prNvramRwInfo = (P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T) pvSetBuffer; + + fgStatus = kalCfgDataWrite16(prAdapter->prGlueInfo, prNvramRwInfo->ucEepromIndex << 1, + prNvramRwInfo->u2EepromData); /* change to byte offset */ + + if (fgStatus == FALSE) { + DBGLOG(OID, ERROR, "NVRAM Write Failed.\r\n"); + rStatus = WLAN_STATUS_FAILURE; + } + + return rStatus; +} /* wlanoidSetNvramWrite */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get the config data source type. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryCfgSrcType(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + ASSERT(prAdapter); + + *pu4QueryInfoLen = sizeof(ENUM_CFG_SRC_TYPE_T); + + if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) + *(P_ENUM_CFG_SRC_TYPE_T) pvQueryBuffer = CFG_SRC_TYPE_NVRAM; + else + *(P_ENUM_CFG_SRC_TYPE_T) pvQueryBuffer = CFG_SRC_TYPE_EEPROM; + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get the config data source type. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryEepromType(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + ASSERT(prAdapter); + + *pu4QueryInfoLen = sizeof(P_ENUM_EEPROM_TYPE_T); + +#if CFG_SUPPORT_NIC_CAPABILITY + if (prAdapter->fgIsEepromUsed == TRUE) + *(P_ENUM_EEPROM_TYPE_T) pvQueryBuffer = EEPROM_TYPE_PRESENT; + else + *(P_ENUM_EEPROM_TYPE_T) pvQueryBuffer = EEPROM_TYPE_NO; +#else + *(P_ENUM_EEPROM_TYPE_T) pvQueryBuffer = EEPROM_TYPE_NO; +#endif + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get the config data source type. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetCountryCode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PUINT_8 pucCountry; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(u4SetBufferLen == 2); + + *pu4SetInfoLen = 2; + + pucCountry = pvSetBuffer; + + prAdapter->rWifiVar.rConnSettings.u2CountryCode = (((UINT_16) pucCountry[0]) << 8) | ((UINT_16) pucCountry[1]); + + /* Force to re-search country code in regulatory domains */ + prAdapter->prDomainInfo = NULL; + rlmDomainSendCmd(prAdapter); + + /* Update supported channel list in channel table based on current country domain */ + wlanUpdateChannelTable(prAdapter->prGlueInfo); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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(OID, WARN, "Fail to set BT profile because of ACPI_D3\n"); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pvSetBuffer); + prPtaIpc = (P_PTA_IPC_T) pvSetBuffer; + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS && CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(OID, INFO, "BCM BWCS CMD: BWCS CMD = %02x%02x%02x%02x\n", + prPtaIpc->u.aucBTPParams[0], prPtaIpc->u.aucBTPParams[1], + prPtaIpc->u.aucBTPParams[2], prPtaIpc->u.aucBTPParams[3]); + + DBGLOG(OID, INFO, + "BCM BWCS CMD: BTPParams[0]=%02x, BTPParams[1]=%02x, BTPParams[2]=%02x, BTPParams[3]=%02x.\n", + prPtaIpc->u.aucBTPParams[0], prPtaIpc->u.aucBTPParams[1], + prPtaIpc->u.aucBTPParams[2], prPtaIpc->u.aucBTPParams[3]); + +#endif + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_BWCS, + TRUE, FALSE, FALSE, NULL, NULL, sizeof(PTA_IPC_T), (PUINT_8) prPtaIpc, NULL, 0); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query current BT profile and BTCR values +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryBT(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ +/* P_PARAM_PTA_IPC_T prPtaIpc; */ +/* UINT_32 u4QueryBuffLen; */ + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PTA_IPC_T); + + /* Check for query buffer length */ + if (u4QueryBufferLen != sizeof(PTA_IPC_T)) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvQueryBuffer); +/* prPtaIpc = (P_PTA_IPC_T)pvQueryBuffer; */ +/* prPtaIpc->ucCmd = BT_CMD_PROFILE; */ +/* prPtaIpc->ucLen = sizeof(prPtaIpc->u); */ +/* nicPtaGetProfile(prAdapter, (PUINT_8)&prPtaIpc->u, &u4QueryBuffLen); */ + + return WLAN_STATUS_SUCCESS; +} + +#if 0 +WLAN_STATUS +wlanoidQueryBtSingleAntenna(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PTA_INFO_T prPtaInfo; + PUINT_32 pu4SingleAntenna; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(UINT_32); + + /* Check for query buffer length */ + if (u4QueryBufferLen != sizeof(UINT_32)) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvQueryBuffer); + + prPtaInfo = &prAdapter->rPtaInfo; + pu4SingleAntenna = (PUINT_32) pvQueryBuffer; + + if (prPtaInfo->fgSingleAntenna) { + /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"Q Single Ant = 1\r\n")); */ + *pu4SingleAntenna = 1; + } else { + /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"Q Single Ant = 0\r\n")); */ + *pu4SingleAntenna = 0; + } + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidSetBtSingleAntenna(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + + PUINT_32 pu4SingleAntenna; + UINT_32 u4SingleAntenna; + P_PTA_INFO_T prPtaInfo; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + prPtaInfo = &prAdapter->rPtaInfo; + + *pu4SetInfoLen = sizeof(UINT_32); + if (u4SetBufferLen != sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + if (IS_ARB_IN_RFTEST_STATE(prAdapter)) + return WLAN_STATUS_SUCCESS; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail to set antenna because of ACPI_D3\n"); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pvSetBuffer); + pu4SingleAntenna = (PUINT_32) pvSetBuffer; + u4SingleAntenna = *pu4SingleAntenna; + + if (u4SingleAntenna == 0) { + /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"Set Single Ant = 0\r\n")); */ + prPtaInfo->fgSingleAntenna = FALSE; + } else { + /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"Set Single Ant = 1\r\n")); */ + prPtaInfo->fgSingleAntenna = TRUE; + } + ptaFsmRunEventSetConfig(prAdapter, &prPtaInfo->rPtaParam); + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS +WLAN_STATUS +wlanoidQueryPta(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PTA_INFO_T prPtaInfo; + PUINT_32 pu4Pta; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(UINT_32); + + /* Check for query buffer length */ + if (u4QueryBufferLen != sizeof(UINT_32)) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvQueryBuffer); + + prPtaInfo = &prAdapter->rPtaInfo; + pu4Pta = (PUINT_32) pvQueryBuffer; + + if (prPtaInfo->fgEnabled) { + /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"PTA = 1\r\n")); */ + *pu4Pta = 1; + } else { + /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"PTA = 0\r\n")); */ + *pu4Pta = 0; + } + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidSetPta(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PUINT_32 pu4PtaCtrl; + UINT_32 u4PtaCtrl; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(UINT_32); + if (u4SetBufferLen != sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + if (IS_ARB_IN_RFTEST_STATE(prAdapter)) + return WLAN_STATUS_SUCCESS; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail to set BT setting because of ACPI_D3\n"); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pvSetBuffer); + pu4PtaCtrl = (PUINT_32) pvSetBuffer; + u4PtaCtrl = *pu4PtaCtrl; + + if (u4PtaCtrl == 0) { + /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"Set Pta= 0\r\n")); */ + nicPtaSetFunc(prAdapter, FALSE); + } else { + /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"Set Pta= 1\r\n")); */ + nicPtaSetFunc(prAdapter, TRUE); + } + + return WLAN_STATUS_SUCCESS; +} +#endif + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set Tx power profile. +* +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetTxPower(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_SET_TXPWR_CTRL_T pTxPwr = (P_SET_TXPWR_CTRL_T) pvSetBuffer; + P_SET_TXPWR_CTRL_T prCmd; + UINT_32 i; + WLAN_STATUS rStatus; + + DEBUGFUNC("wlanoidSetTxPower"); + DBGLOG(OID, LOUD, "\r\n"); + + prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(SET_TXPWR_CTRL_T)); + kalMemZero(prCmd, sizeof(SET_TXPWR_CTRL_T)); + prCmd->c2GLegacyStaPwrOffset = pTxPwr->c2GLegacyStaPwrOffset; + prCmd->c2GHotspotPwrOffset = pTxPwr->c2GHotspotPwrOffset; + prCmd->c2GP2pPwrOffset = pTxPwr->c2GP2pPwrOffset; + prCmd->c2GBowPwrOffset = pTxPwr->c2GBowPwrOffset; + prCmd->c5GLegacyStaPwrOffset = pTxPwr->c5GLegacyStaPwrOffset; + prCmd->c5GHotspotPwrOffset = pTxPwr->c5GHotspotPwrOffset; + prCmd->c5GP2pPwrOffset = pTxPwr->c5GP2pPwrOffset; + prCmd->c5GBowPwrOffset = pTxPwr->c5GBowPwrOffset; + prCmd->ucConcurrencePolicy = pTxPwr->ucConcurrencePolicy; + for (i = 0; i < 14; i++) + prCmd->acTxPwrLimit2G[i] = pTxPwr->acTxPwrLimit2G[i]; + + for (i = 0; i < 4; i++) + prCmd->acTxPwrLimit5G[i] = pTxPwr->acTxPwrLimit5G[i]; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + +#if 0 + DBGLOG(OID, INFO, "c2GLegacyStaPwrOffset=%d\n", pTxPwr->c2GLegacyStaPwrOffset); + DBGLOG(OID, INFO, "c2GHotspotPwrOffset=%d\n", pTxPwr->c2GHotspotPwrOffset); + DBGLOG(OID, INFO, "c2GP2pPwrOffset=%d\n", pTxPwr->c2GP2pPwrOffset); + DBGLOG(OID, INFO, "c2GBowPwrOffset=%d\n", pTxPwr->c2GBowPwrOffset); + DBGLOG(OID, INFO, "c5GLegacyStaPwrOffset=%d\n", pTxPwr->c5GLegacyStaPwrOffset); + DBGLOG(OID, INFO, "c5GHotspotPwrOffset=%d\n", pTxPwr->c5GHotspotPwrOffset); + DBGLOG(OID, INFO, "c5GP2pPwrOffset=%d\n", pTxPwr->c5GP2pPwrOffset); + DBGLOG(OID, INFO, "c5GBowPwrOffset=%d\n", pTxPwr->c5GBowPwrOffset); + DBGLOG(OID, INFO, "ucConcurrencePolicy=%d\n", pTxPwr->ucConcurrencePolicy); + + for (i = 0; i < 14; i++) + DBGLOG(OID, INFO, "acTxPwrLimit2G[%d]=%d\n", i, pTxPwr->acTxPwrLimit2G[i]); + + for (i = 0; i < 4; i++) + DBGLOG(OID, INFO, "acTxPwrLimit5G[%d]=%d\n", i, pTxPwr->acTxPwrLimit5G[i]); +#endif + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_TXPWR_CTRL, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + TRUE, /* fgIsOid */ + nicCmdEventSetCommon, nicOidCmdTimeoutCommon, sizeof(SET_TXPWR_CTRL_T), + (PUINT_8) prCmd, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + /* ASSERT(rStatus == WLAN_STATUS_PENDING); */ + cnmMemFree(prAdapter, prCmd); + + return rStatus; + +} + +WLAN_STATUS wlanSendMemDumpCmd(IN P_ADAPTER_T prAdapter, IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen) +{ + P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T prMemDumpInfo; + P_CMD_DUMP_MEM prCmdDumpMem; + CMD_DUMP_MEM rCmdDumpMem; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4MemSize = PARAM_MEM_DUMP_MAX_SIZE; + + UINT_32 u4RemainLeng = 0; + UINT_32 u4CurAddr = 0; + UINT_8 ucFragNum = 0; + + prCmdDumpMem = &rCmdDumpMem; + prMemDumpInfo = (P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T) pvQueryBuffer; + + u4RemainLeng = prMemDumpInfo->u4RemainLength; + u4CurAddr = prMemDumpInfo->u4Address + prMemDumpInfo->u4Length; + ucFragNum = prMemDumpInfo->ucFragNum + 1; + + /* Query. If request length is larger than max length, do it as ping pong. + * Send a command and wait for a event. Send next command while the event is received. + * + */ + do { + UINT_32 u4CurLeng = 0; + + if (u4RemainLeng > u4MemSize) { + u4CurLeng = u4MemSize; + u4RemainLeng -= u4MemSize; + } else { + u4CurLeng = u4RemainLeng; + u4RemainLeng = 0; + } + + prCmdDumpMem->u4Address = u4CurAddr; + prCmdDumpMem->u4Length = u4CurLeng; + prCmdDumpMem->u4RemainLength = u4RemainLeng; + prCmdDumpMem->ucFragNum = ucFragNum; +#if CFG_SUPPORT_QA_TOOL + prCmdDumpMem->u4IcapContent = prMemDumpInfo->u4IcapContent; +#endif /* CFG_SUPPORT_QA_TOOL */ + + DBGLOG(RFTEST, INFO, "[ucFragNum = %d] u4Address = 0x%x, len %u, remain len %u\n", + ucFragNum, prCmdDumpMem->u4Address, prCmdDumpMem->u4Length, prCmdDumpMem->u4RemainLength); + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_DUMP_MEM, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryMemDump, + nicOidCmdTimeoutCommon, + sizeof(CMD_DUMP_MEM), + (PUINT_8) prCmdDumpMem, pvQueryBuffer, u4QueryBufferLen); + + } while (FALSE); + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to dump memory. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMemDump(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T prMemDumpInfo; + + DBGLOG(RFTEST, INFO, "wlanoidQueryMemDump----->\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(UINT_32); + + prMemDumpInfo = (P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T) pvQueryBuffer; + DBGLOG(OID, TRACE, "Dump 0x%X, len %u\n", prMemDumpInfo->u4Address, prMemDumpInfo->u4Length); + + prMemDumpInfo->u4RemainLength = prMemDumpInfo->u4Length; + prMemDumpInfo->u4Length = 0; + prMemDumpInfo->ucFragNum = 0; + return wlanSendMemDumpCmd(prAdapter, pvQueryBuffer, u4QueryBufferLen); +} /* end of wlanoidQueryMcrRead() */ + +#if CFG_ENABLE_WIFI_DIRECT +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to set the p2p mode. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2pMode(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS status = WLAN_STATUS_SUCCESS; + P_PARAM_CUSTOM_P2P_SET_STRUCT_T prSetP2P = (P_PARAM_CUSTOM_P2P_SET_STRUCT_T) NULL; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_P2P_SET_STRUCT_T); + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_P2P_SET_STRUCT_T)) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prSetP2P = (P_PARAM_CUSTOM_P2P_SET_STRUCT_T) pvSetBuffer; + + DBGLOG(P2P, INFO, "Set P2P enable[%u] mode[%u]\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); + if (prAdapter->rWifiVar.ucApUapsd && prSetP2P->u4Mode == 1) { + PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T rUapsdParams; + + DBGLOG(OID, INFO, "wlanoidSetP2pMode Default enable ApUapsd\n"); + rUapsdParams.fgEnAPSD = 1; + rUapsdParams.fgEnAPSD_AcBe = 1; + rUapsdParams.fgEnAPSD_AcBk = 1; + rUapsdParams.fgEnAPSD_AcVi = 1; + rUapsdParams.fgEnAPSD_AcVo = 1; + rUapsdParams.ucMaxSpLen = 0; /* default:0, Do not limit delivery pkt num */ + nicSetUapsdParam(prAdapter, &rUapsdParams, NETWORK_TYPE_P2P); + } + } else { + if (prAdapter->fgIsP2PRegistered) + p2pRemove(prAdapter->prGlueInfo); + } + + return status; + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the default key +* +* \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 +wlanoidSetDefaultKey(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_DEFAULT_KEY_T prDefaultKey; + P_CMD_DEFAULT_KEY prCmdDefaultKey; + UINT_8 ucCmdSeqNum; + + DEBUGFUNC("wlanoidSetDefaultKey"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set add key! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + prDefaultKey = (P_PARAM_DEFAULT_KEY_T) pvSetBuffer; + + *pu4SetInfoLen = u4SetBufferLen; + + /* Dump PARAM_DEFAULT_KEY_T content. */ + DBGLOG(OID, INFO, "Key Index : %d, Unicast Key : %d, Multicast Key : %d\n", + prDefaultKey->ucKeyID, prDefaultKey->ucUnicast, prDefaultKey->ucMulticast); + + /* prWlanTable = prAdapter->rWifiVar.arWtbl; */ + prGlueInfo = prAdapter->prGlueInfo; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_DEFAULT_KEY))); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + DBGLOG(OID, TRACE, "ucCmdSeqNum = %d\n", ucCmdSeqNum); + + /* compose CMD_802_11_KEY cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_DEFAULT_KEY); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_DEFAULT_KEY_ID; + 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 = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prCmdDefaultKey = (P_CMD_DEFAULT_KEY) (prWifiCmd->aucBuffer); + + kalMemZero(prCmdDefaultKey, sizeof(CMD_DEFAULT_KEY)); + + prCmdDefaultKey->ucBssIdx = prAdapter->prAisBssInfo->ucBssIndex; + prCmdDefaultKey->ucKeyId = prDefaultKey->ucKeyID; + prCmdDefaultKey->ucUnicast = prDefaultKey->ucUnicast; + prCmdDefaultKey->ucMulticast = prDefaultKey->ucMulticast; + + if (prDefaultKey->ucMulticast) { + prAdapter->prAisBssInfo->fgTxBcKeyExist = TRUE; + prAdapter->prAisBssInfo->ucTxDefaultKeyID = prDefaultKey->ucKeyID; + /* prBssInfo->ucBMCWlanIndex = secPrivacySeekForBcEntry(prAdapter, prBssInfo->ucBssIndex, */ + /* NETWORK_TYPE_AIS, prCmdKey->aucPeerAddr, prCmdKey->ucAlgorithmId, prCmdKey->ucKeyId, */ + /* prBssInfo->ucCurrentGtkId, BIT(1)); */ + /* prCmdDefaultKey->ucBMCWlanIndex = prBssInfo->ucBMCWlanIndex; */ + } else { + ASSERT(FALSE); + } + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; +} /* wlanoidSetDefaultKey */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the GTK rekey data +* +* \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 +wlanoidSetGtkRekeyData(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + CMD_GTK_REKEY_DATA_T rCmdContent; + WLAN_STATUS rStatus; + + ASSERT(prAdapter); + + kalMemCopy(&rCmdContent, (PUINT_8) pvSetBuffer, u4SetBufferLen); + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_GTK_REKEY_DATA, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + TRUE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_GTK_REKEY_DATA_T), /* u4SetQueryInfoLen */ + (PUINT_8) &rCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + /* ASSERT(rStatus == WLAN_STATUS_PENDING); */ + + return rStatus; +} /* wlanoidSetGtkRekeyData */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request starting of schedule scan +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetStartSchedScan(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_SCHED_SCAN_REQUEST prSchedScanRequest; + + DEBUGFUNC("wlanoidSetStartSchedScan()"); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in set scheduled scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pu4SetInfoLen); + *pu4SetInfoLen = 0; + + if (u4SetBufferLen != sizeof(PARAM_SCHED_SCAN_REQUEST)) + return WLAN_STATUS_INVALID_LENGTH; + else if (pvSetBuffer == NULL) + return WLAN_STATUS_INVALID_DATA; + else if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED + && prAdapter->fgEnOnlineScan == FALSE) + return WLAN_STATUS_FAILURE; + + if (prAdapter->fgIsRadioOff) { + DBGLOG(OID, WARN, "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + prSchedScanRequest = (P_PARAM_SCHED_SCAN_REQUEST) pvSetBuffer; + + if (scnFsmSchedScanRequest(prAdapter, prSchedScanRequest) == TRUE) + return WLAN_STATUS_SUCCESS; + else + return WLAN_STATUS_FAILURE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request termination of schedule scan +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetStopSchedScan(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + ASSERT(prAdapter); + + /* ask SCN module to stop scan request */ + if (scnFsmSchedScanStopRequest(prAdapter) == TRUE) + return WLAN_STATUS_SUCCESS; + else + return WLAN_STATUS_FAILURE; +} + +#if CFG_M0VE_BA_TO_DRIVER +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to reset BA scoreboard. +* +* +* \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 wlanoidResetBAScoreboard(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen) +{ + WLAN_STATUS rStatus; + + DEBUGFUNC("wlanoidResetBAScoreboard"); + DBGLOG(OID, WARN, "[Puff]wlanoidResetBAScoreboard\n"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_RESET_BA_SCOREBOARD, /* 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; + +} + +#endif + +#if CFG_SUPPORT_BATCH_SCAN + +#define CMD_WLS_BATCHING "WLS_BATCHING" + +#define BATCHING_SET "SET" +#define BATCHING_GET "GET" +#define BATCHING_STOP "STOP" + +#define PARAM_SCANFREQ "SCANFREQ" +#define PARAM_MSCAN "MSCAN" +#define PARAM_BESTN "BESTN" +#define PARAM_CHANNEL "CHANNEL" +#define PARAM_RTT "RTT" + +WLAN_STATUS +batchSetCmd(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4WritenLen) +{ + P_CHANNEL_INFO_T prRfChannelInfo; + CMD_BATCH_REQ_T rCmdBatchReq; + + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + PCHAR head, p, p2; + UINT_32 tokens; + INT_32 scanfreq, mscan, bestn, rtt; + char *pcTemp; + /* CHAR c_scanfreq[4], c_mscan[4], c_bestn[4], c_rtt[4], c_channel[100]; */ + /* INT32 ch_type; */ + UINT_32 u4Value = 0; + INT_32 i4Ret = 0; + + DBGLOG(SCN, TRACE, "[BATCH] command=%s, len=%u\n", (PUINT_8)pvSetBuffer, u4SetBufferLen); + + if (!pu4WritenLen) + return -EINVAL; + *pu4WritenLen = 0; + + if (u4SetBufferLen < kalStrLen(CMD_WLS_BATCHING)) { + DBGLOG(SCN, TRACE, "[BATCH] invalid len %u\n", u4SetBufferLen); + return -EINVAL; + } + + head = pvSetBuffer + kalStrLen(CMD_WLS_BATCHING) + 1; + kalMemSet(&rCmdBatchReq, 0, sizeof(CMD_BATCH_REQ_T)); + + if (!kalStrnCmp(head, BATCHING_SET, kalStrLen(BATCHING_SET))) { + + DBGLOG(SCN, TRACE, "XXX Start Batch Scan XXX\n"); + + head += kalStrLen(BATCHING_SET) + 1; + + /* SCANFREQ, MSCAN, BESTN */ + tokens = sscanf(head, "SCANFREQ=%d MSCAN=%d BESTN=%d", &scanfreq, &mscan, &bestn); + if (tokens != 3) { + DBGLOG(SCN, TRACE, + "[BATCH] Parse fail: tokens=%d, SCANFREQ=%d MSCAN=%d BESTN=%d\n", + tokens, scanfreq, mscan, bestn); + return -EINVAL; + } + /* RTT */ + p = kalStrStr(head, PARAM_RTT); + if (!p) { + DBGLOG(SCN, TRACE, "[BATCH] Parse RTT fail. head=%s\n", head); + return -EINVAL; + } + tokens = sscanf(p, "RTT=%d", &rtt); + if (tokens != 1) { + DBGLOG(SCN, TRACE, "[BATCH] Parse fail: tokens=%d, rtt=%d\n", tokens, rtt); + return -EINVAL; + } + /* CHANNEL */ + p = kalStrStr(head, PARAM_CHANNEL); + if (!p) { + DBGLOG(SCN, TRACE, "[BATCH] Parse CHANNEL fail(1)\n"); + return -EINVAL; + } + head = p; + p = kalStrChr(head, '>'); + if (!p) { + DBGLOG(SCN, TRACE, "[BATCH] Parse CHANNEL fail(2)\n"); + return -EINVAL; + } + /* + * else { + * *p = '.'; // remove '>' because sscanf can not parse <%s> + * } + */ + /* + * tokens = sscanf(head, "CHANNEL=<%s", c_channel); + * if (tokens != 1) { + * DBGLOG(SCN, TRACE, "[BATCH] Parse fail: tokens=%d, CHANNEL=<%s>\n", + * tokens, c_channel); + * return -EINVAL; + * } + */ + rCmdBatchReq.ucChannelType = SCAN_CHANNEL_SPECIFIED; + rCmdBatchReq.ucChannelListNum = 0; + prRfChannelInfo = &rCmdBatchReq.arChannelList[0]; + p = head + kalStrLen(PARAM_CHANNEL) + 2; /* c_channel; */ + pcTemp = (char *)p; + while ((p2 = kalStrSep(&pcTemp, ",")) != NULL) { + if (p2 == NULL || *p2 == 0) + break; + if (*p2 == '\0') + continue; + if (*p2 == 'A') { + rCmdBatchReq.ucChannelType = + rCmdBatchReq.ucChannelType == + SCAN_CHANNEL_2G4 ? SCAN_CHANNEL_FULL : SCAN_CHANNEL_5G; + } else if (*p2 == 'B') { + rCmdBatchReq.ucChannelType = + rCmdBatchReq.ucChannelType == + SCAN_CHANNEL_5G ? SCAN_CHANNEL_FULL : SCAN_CHANNEL_2G4; + } else { + + /* Translate Freq from MHz to channel number. */ + /* prRfChannelInfo->ucChannelNum = kalStrtol(p2, NULL, 0); */ + i4Ret = kalkStrtou32(p2, 0, &u4Value); + if (i4Ret) + DBGLOG(SCN, TRACE, "parse ucChannelNum error i4Ret=%d\n", i4Ret); + prRfChannelInfo->ucChannelNum = (UINT_8) u4Value; + DBGLOG(SCN, TRACE, "Scanning Channel:%d, freq: %d\n", + prRfChannelInfo->ucChannelNum, + nicChannelNum2Freq(prRfChannelInfo->ucChannelNum)); + prRfChannelInfo->ucBand = prRfChannelInfo->ucChannelNum < 15 ? BAND_2G4 : BAND_5G; + + rCmdBatchReq.ucChannelListNum++; + if (rCmdBatchReq.ucChannelListNum >= 32) + break; + prRfChannelInfo++; + } + } + + /* set channel for test */ +#if 0 + rCmdBatchReq.ucChannelType = 4; /* SCAN_CHANNEL_SPECIFIED; */ + rCmdBatchReq.ucChannelListNum = 0; + prRfChannelInfo = &rCmdBatchReq.arChannelList[0]; + for (i = 1; i <= 14; i++) { + + /* filter out some */ + if (i == 1 || i == 5 || i == 11) + continue; + + /* Translate Freq from MHz to channel number. */ + prRfChannelInfo->ucChannelNum = i; + DBGLOG(SCN, TRACE, "Scanning Channel:%d, freq: %d\n", + prRfChannelInfo->ucChannelNum, nicChannelNum2Freq(prRfChannelInfo->ucChannelNum)); + prRfChannelInfo->ucBand = BAND_2G4; + + rCmdBatchReq.ucChannelListNum++; + prRfChannelInfo++; + } +#endif +#if 0 + rCmdBatchReq.ucChannelType = 0; /* SCAN_CHANNEL_FULL; */ +#endif + + rCmdBatchReq.u4Scanfreq = scanfreq; + rCmdBatchReq.ucMScan = mscan > CFG_BATCH_MAX_MSCAN ? CFG_BATCH_MAX_MSCAN : mscan; + rCmdBatchReq.ucBestn = bestn; + rCmdBatchReq.ucRtt = rtt; + DBGLOG(SCN, TRACE, "[BATCH] SCANFREQ=%d MSCAN=%d BESTN=%d RTT=%d\n", + rCmdBatchReq.u4Scanfreq, rCmdBatchReq.ucMScan, rCmdBatchReq.ucBestn, rCmdBatchReq.ucRtt); + + if (rCmdBatchReq.ucChannelType != SCAN_CHANNEL_SPECIFIED) { + DBGLOG(SCN, TRACE, "[BATCH] CHANNELS = %s\n", + rCmdBatchReq.ucChannelType == + SCAN_CHANNEL_FULL ? "FULL" : rCmdBatchReq.ucChannelType == + SCAN_CHANNEL_2G4 ? "2.4G all" : "5G all"); + } else { + DBGLOG(SCN, TRACE, "[BATCH] CHANNEL list\n"); + prRfChannelInfo = &rCmdBatchReq.arChannelList[0]; + for (tokens = 0; tokens < rCmdBatchReq.ucChannelListNum; tokens++) { + DBGLOG(SCN, TRACE, "[BATCH] %s, %d\n", + prRfChannelInfo->ucBand == + BAND_2G4 ? "2.4G" : "5G", prRfChannelInfo->ucChannelNum); + prRfChannelInfo++; + } + } + + rCmdBatchReq.ucSeqNum = 1; + rCmdBatchReq.ucNetTypeIndex = KAL_NETWORK_TYPE_AIS_INDEX; + rCmdBatchReq.ucCmd = SCAN_BATCH_REQ_START; + + *pu4WritenLen = kalSnprintf(pvSetBuffer, 3, "%d", rCmdBatchReq.ucMScan); + + } else if (!kalStrnCmp(head, BATCHING_STOP, kalStrLen(BATCHING_STOP))) { + + DBGLOG(SCN, TRACE, "XXX Stop Batch Scan XXX\n"); + + rCmdBatchReq.ucSeqNum = 1; + rCmdBatchReq.ucNetTypeIndex = KAL_NETWORK_TYPE_AIS_INDEX; + rCmdBatchReq.ucCmd = SCAN_BATCH_REQ_STOP; + } else { + return -EINVAL; + } + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_BATCH_REQ, + TRUE, FALSE, TRUE, NULL, NULL, sizeof(CMD_BATCH_REQ_T), (PUINT_8) &rCmdBatchReq, NULL, 0); + + /* kalMemSet(pvSetBuffer, 0, u4SetBufferLen); */ + /* rStatus = kalSnprintf(pvSetBuffer, 2, "%s", "OK"); */ + +/* exit: */ + return rStatus; +} + +WLAN_STATUS +batchGetCmd(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + CMD_BATCH_REQ_T rCmdBatchReq; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_EVENT_BATCH_RESULT_T prEventBatchResult; + /* UINT_32 i; */ + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + prEventBatchResult = (P_EVENT_BATCH_RESULT_T) pvQueryBuffer; + + DBGLOG(SCN, TRACE, "XXX Get Batch Scan Result (%d) XXX\n", prEventBatchResult->ucScanCount); + + *pu4QueryInfoLen = sizeof(EVENT_BATCH_RESULT_T); + + rCmdBatchReq.ucSeqNum = 2; + rCmdBatchReq.ucCmd = SCAN_BATCH_REQ_RESULT; + rCmdBatchReq.ucMScan = prEventBatchResult->ucScanCount; /* Get which round result */ + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_BATCH_REQ, + FALSE, + TRUE, + TRUE, + nicCmdEventBatchScanResult, + nicOidCmdTimeoutCommon, + sizeof(CMD_BATCH_REQ_T), + (PUINT_8) &rCmdBatchReq, (PVOID) pvQueryBuffer, u4QueryBufferLen); + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. +* \retval WLAN_STATUS_INVALID_LENGTH +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBatchScanReq(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + return batchSetCmd(prAdapter, pvSetBuffer, u4SetBufferLen, pu4SetInfoLen); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryBatchScanResult(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + return batchGetCmd(prAdapter, pvQueryBuffer, u4QueryBufferLen, pu4QueryInfoLen); + +} /* end of wlanoidQueryBatchScanResult() */ + +#endif /* CFG_SUPPORT_BATCH_SCAN */ + +#if CFG_SUPPORT_GSCN +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a periodically PSCN action +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetGSCNAction(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_CMD_SET_PSCAN_ENABLE prCmdPscnAction; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(SCN, ERROR, "Adapter not ready: ACPI=%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + if (u4SetBufferLen != sizeof(CMD_SET_PSCAN_ENABLE)) { + DBGLOG(SCN, ERROR, "u4SetBufferLen != sizeof(CMD_SET_PSCAN_ENABLE)\n"); + return WLAN_STATUS_INVALID_LENGTH; + } else if (pvSetBuffer == NULL) { + DBGLOG(SCN, ERROR, "pvSetBuffer == NULL\n"); + return WLAN_STATUS_INVALID_DATA; + } + + if (prAdapter->fgIsRadioOff) { + DBGLOG(SCN, ERROR, "Radio off: ACPI=%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + prCmdPscnAction = (P_CMD_SET_PSCAN_ENABLE) pvSetBuffer; + + if (prCmdPscnAction) { + DBGLOG(SCN, TRACE, "ucPscanAct=[%d]\n", prCmdPscnAction->ucPscanAct); + if (prCmdPscnAction->ucPscanAct == PSCAN_ACT_ENABLE) { + prAdapter->rWifiVar.rScanInfo.fgGScnAction = TRUE; + scnPSCNFsm(prAdapter, PSCN_SCANNING); + } else if (prCmdPscnAction->ucPscanAct == PSCAN_ACT_DISABLE) { + scnCombineParamsIntoPSCN(prAdapter, NULL, NULL, NULL, NULL, FALSE, FALSE, TRUE); + if (prAdapter->rWifiVar.rScanInfo.prPscnParam->fgNLOScnEnable + || prAdapter->rWifiVar.rScanInfo.prPscnParam->fgBatchScnEnable) + scnPSCNFsm(prAdapter, PSCN_RESET); /* in case there is any PSCN */ + else + scnPSCNFsm(prAdapter, PSCN_IDLE); + } + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to configure GScan PARAMs +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetGSCNParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_WIFI_GSCAN_CMD_PARAMS prCmdGscnParam; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(SCN, ERROR, "Adapter not ready: ACPI=%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + if (u4SetBufferLen != sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)) { + DBGLOG(SCN, ERROR, "u4SetBufferLen != sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)\n"); + return WLAN_STATUS_INVALID_LENGTH; + } + if (pvSetBuffer == NULL) { + DBGLOG(SCN, ERROR, "pvSetBuffer == NULL\n"); + return WLAN_STATUS_INVALID_DATA; + } + if (prAdapter->fgIsRadioOff) { + DBGLOG(SCN, ERROR, "Radio off: ACPI=%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + prCmdGscnParam = (P_PARAM_WIFI_GSCAN_CMD_PARAMS) pvSetBuffer; + DBGLOG(SCN, TRACE, "prCmdGscnParam: base_period[%u], num_buckets[%u] band[%d] num_channels[%u]\n", + prCmdGscnParam->base_period, prCmdGscnParam->num_buckets, + prCmdGscnParam->buckets[0].band, prCmdGscnParam->buckets[0].num_channels); + + if (scnSetGSCNParam(prAdapter, prCmdGscnParam)) + return WLAN_STATUS_SUCCESS; + else + return WLAN_STATUS_FAILURE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to configure GScan PARAMs +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetGSCNConfig(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_WIFI_GSCAN_CMD_PARAMS prCmdGscnConfigParam; + CMD_GSCN_SCN_COFIG_T rCmdGscnConfig; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(SCN, ERROR, "Adapter not ready: ACPI=%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + if (u4SetBufferLen != sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)) { + DBGLOG(SCN, ERROR, "u4SetBufferLen != sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)\n"); + return WLAN_STATUS_INVALID_LENGTH; + } else if (pvSetBuffer == NULL) { + DBGLOG(SCN, ERROR, "pvSetBuffer == NULL\n"); + return WLAN_STATUS_INVALID_DATA; + } + if (prAdapter->fgIsRadioOff) { + DBGLOG(SCN, ERROR, "Radio off: ACPI=%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + prCmdGscnConfigParam = (P_PARAM_WIFI_GSCAN_CMD_PARAMS) pvSetBuffer; + kalMemZero(&rCmdGscnConfig, sizeof(CMD_GSCN_SCN_COFIG_T)); + + if (prCmdGscnConfigParam) { + rCmdGscnConfig.u4BufferThreshold = prCmdGscnConfigParam->report_threshold_percent; + rCmdGscnConfig.ucNumApPerScn = prCmdGscnConfigParam->max_ap_per_scan; + rCmdGscnConfig.u4NumScnToCache = prCmdGscnConfigParam->report_threshold_num_scans; + } + DBGLOG(SCN, TRACE, "rCmdGscnScnConfig: threshold_percent[%d] max_ap_per_scan[%d] num_scans[%d]\n", + rCmdGscnConfig.u4BufferThreshold, + rCmdGscnConfig.ucNumApPerScn, rCmdGscnConfig.u4NumScnToCache); + + if (scnSetGSCNConfig(prAdapter, &rCmdGscnConfig) == TRUE) + return WLAN_STATUS_SUCCESS; + else + return WLAN_STATUS_FAILURE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get a GScan result +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidGetGSCNResult(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_WIFI_GSCAN_GET_RESULT_PARAMS prGetGscnScnResultParm; + CMD_GET_GSCAN_RESULT_T rGetGscnScnResultCmd; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(SCN, ERROR, "Adapter not ready: ACPI=%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + if (u4SetBufferLen != sizeof(PARAM_WIFI_GSCAN_GET_RESULT_PARAMS)) { + DBGLOG(SCN, ERROR, "u4SetBufferLen != sizeof(PARAM_WIFI_GSCAN_GET_RESULT_PARAMS))\n"); + return WLAN_STATUS_INVALID_LENGTH; + } else if (pvSetBuffer == NULL) { + DBGLOG(SCN, ERROR, "pvSetBuffer == NULL\n"); + return WLAN_STATUS_INVALID_DATA; + } + + if (prAdapter->fgIsRadioOff) { + DBGLOG(SCN, ERROR, "Radio off: ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + prGetGscnScnResultParm = (P_PARAM_WIFI_GSCAN_GET_RESULT_PARAMS) pvSetBuffer; + kalMemZero(&rGetGscnScnResultCmd, sizeof(CMD_GET_GSCAN_RESULT_T)); + + if (prGetGscnScnResultParm) { + rGetGscnScnResultCmd.u4Num = prGetGscnScnResultParm->get_num; + rGetGscnScnResultCmd.ucFlush = prGetGscnScnResultParm->flush; + rGetGscnScnResultCmd.ucVersion = PSCAN_VERSION; + } + + if (scnFsmGetGSCNResult(prAdapter, &rGetGscnScnResultCmd, pu4SetInfoLen) == TRUE) + return WLAN_STATUS_SUCCESS; + else + return WLAN_STATUS_FAILURE; +} +#endif /* CFG_SUPPORT_GSCN */ + + +#if CFG_SUPPORT_PASSPOINT +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called by HS2.0 to set the assoc info, which is needed to add to +* Association request frame while join HS2.0 AP. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. +* \retval WLAN_STATUS_INVALID_LENGTH +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetHS20Info(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_IE_HS20_INDICATION_T prHS20IndicationIe; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + DEBUGFUNC("wlanoidSetHS20AssocInfo"); + DBGLOG(OID, LOUD, "\r\n"); + + if (u4SetBufferLen == 0) + return WLAN_STATUS_INVALID_LENGTH; + + *pu4SetInfoLen = u4SetBufferLen; + + prHS20IndicationIe = (P_IE_HS20_INDICATION_T) pvSetBuffer; + + prAdapter->prGlueInfo->ucHotspotConfig = prHS20IndicationIe->ucHotspotConfig; + prAdapter->prGlueInfo->fgConnectHS20AP = TRUE; + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called by WSC to set the assoc info, which is needed to add to +* Association request frame while join WPS AP. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. +* \retval WLAN_STATUS_INVALID_LENGTH +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetInterworkingInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ +#if 0 + P_HS20_INFO_T prHS20Info = NULL; + P_IE_INTERWORKING_T prInterWorkingIe; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prHS20Info = &(prAdapter->rWifiVar.rHS20Info); + + DEBUGFUNC("wlanoidSetInterworkingInfo"); + DBGLOG(OID, TRACE, "\r\n"); + + if (u4SetBufferLen == 0) + return WLAN_STATUS_INVALID_LENGTH; + + *pu4SetInfoLen = u4SetBufferLen; + prInterWorkingIe = (P_IE_INTERWORKING_T) pvSetBuffer; + + prHS20Info->ucAccessNetworkOptions = prInterWorkingIe->ucAccNetOpt; + prHS20Info->ucVenueGroup = prInterWorkingIe->ucVenueGroup; + prHS20Info->ucVenueType = prInterWorkingIe->ucVenueType; + COPY_MAC_ADDR(prHS20Info->aucHESSID, prInterWorkingIe->aucHESSID); + + DBGLOG(SEC, TRACE, "IW IE sz %ld\n", u4SetBufferLen); +#endif + return WLAN_STATUS_SUCCESS; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called by WSC to set the Roaming Consortium IE info, which is needed to +* add to Association request frame while join WPS AP. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. +* \retval WLAN_STATUS_INVALID_LENGTH +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetRoamingConsortiumIEInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ +#if 0 + P_HS20_INFO_T prHS20Info = NULL; + P_PARAM_HS20_ROAMING_CONSORTIUM_INFO prRCInfo; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prHS20Info = &(prAdapter->rWifiVar.rHS20Info); + + /* DEBUGFUNC("wlanoidSetRoamingConsortiumInfo"); */ + /* DBGLOG(HS2, TRACE, ("\r\n")); */ + + if (u4SetBufferLen == 0) + return WLAN_STATUS_INVALID_LENGTH; + + *pu4SetInfoLen = u4SetBufferLen; + prRCInfo = (P_PARAM_HS20_ROAMING_CONSORTIUM_INFO) pvSetBuffer; + + kalMemCopy(&(prHS20Info->rRCInfo), prRCInfo, sizeof(PARAM_HS20_ROAMING_CONSORTIUM_INFO)); + + /* DBGLOG(HS2, TRACE, ("RoamingConsortium IE sz %ld\n", u4SetBufferLen)); */ +#endif + return WLAN_STATUS_SUCCESS; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set_bssid_pool +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetHS20BssidPool(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (u4SetBufferLen < sizeof(PARAM_HS20_SET_BSSID_POOL)) { + *pu4SetInfoLen = sizeof(PARAM_HS20_SET_BSSID_POOL); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + rWlanStatus = hs20SetBssidPool(prAdapter, pvSetBuffer, KAL_NETWORK_TYPE_AIS_INDEX); + + return rWlanStatus; +} /* end of wlanoidSendHS20GASRequest() */ + +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_SNIFFER +WLAN_STATUS +wlanoidSetMonitor(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_MONITOR_SET_STRUCT_T prMonitorSetInfo; + CMD_MONITOR_SET_INFO_T rCmdMonitorSetInfo; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidSetMonitor"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_MONITOR_SET_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_MONITOR_SET_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prMonitorSetInfo = (P_PARAM_CUSTOM_MONITOR_SET_STRUCT_T) pvSetBuffer; + + rCmdMonitorSetInfo.ucEnable = prMonitorSetInfo->ucEnable; + rCmdMonitorSetInfo.ucBand = prMonitorSetInfo->ucBand; + rCmdMonitorSetInfo.ucPriChannel = prMonitorSetInfo->ucPriChannel; + rCmdMonitorSetInfo.ucSco = prMonitorSetInfo->ucSco; + rCmdMonitorSetInfo.ucChannelWidth = prMonitorSetInfo->ucChannelWidth; + rCmdMonitorSetInfo.ucChannelS1 = prMonitorSetInfo->ucChannelS1; + rCmdMonitorSetInfo.ucChannelS2 = prMonitorSetInfo->ucChannelS2; + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_MONITOR, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_MONITOR_SET_INFO_T), + (PUINT_8) &rCmdMonitorSetInfo, pvSetBuffer, u4SetBufferLen); + + return rWlanStatus; +} +#endif + +#if CFG_SUPPORT_RSSI_DISCONNECT +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the latest RSSI value before disconnecting. +* +* \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 +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS +wlanoidQueryRssiDisconnect(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + PARAM_RSSI i4cRssi; + + DEBUGFUNC("wlanoidQueryRssiDisconnect"); + + if (!prAdapter || !pu4QueryInfoLen) + return -EPERM; + if (u4QueryBufferLen && !pvQueryBuffer) + return -EPERM; + + *pu4QueryInfoLen = sizeof(PARAM_RSSI); + + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(OID, WARN, "Too short length %u\n", u4QueryBufferLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + DBGLOG(OID, INFO, "fgIsLinkQualityValid = %d, rLinkQualityUpdateTime = %d\n", + prAdapter->fgIsLinkQualityValid, prAdapter->rLinkQualityUpdateTime); + if (!prAdapter->rLinkQualityUpdateTime || kalGetMediaStateIndicated(prAdapter->prGlueInfo) + == PARAM_MEDIA_STATE_CONNECTED) + return WLAN_STATUS_NOT_SUPPORTED; + + i4cRssi = (PARAM_RSSI) prAdapter->rLinkQuality.cRssi; /* ranged from (-128 ~ 30) in unit of dBm */ + + if (i4cRssi > PARAM_WHQL_RSSI_MAX_DBM) + i4cRssi = PARAM_WHQL_RSSI_MAX_DBM; + else if (i4cRssi < PARAM_WHQL_RSSI_MIN_DBM) + i4cRssi = PARAM_WHQL_RSSI_MIN_DBM; + DBGLOG(OID, INFO, "i4cRssi = %d\n", i4cRssi); + kalMemCopy(pvQueryBuffer, &i4cRssi, sizeof(PARAM_RSSI)); + return WLAN_STATUS_SUCCESS; + +} /* end of wlanoidQueryRssiDisconnect() */ +#endif + +WLAN_STATUS +wlanoidNotifyFwSuspend(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + CMD_SUSPEND_MODE_SETTING_T rSuspendCmd; + + if (!prAdapter || !pvSetBuffer) + return WLAN_STATUS_INVALID_DATA; + + rSuspendCmd.fIsEnableSuspendMode = *(PBOOLEAN)pvSetBuffer; + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_SUSPEND_MODE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(BOOLEAN), + (PUINT_8)&rSuspendCmd, + NULL, + 0); +} + +WLAN_STATUS +wlanoidPacketKeepAlive(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_PARAM_PACKET_KEEPALIVE_T prPacket; + + DEBUGFUNC("wlanoidPacketKeepAlive"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(PARAM_PACKET_KEEPALIVE_T); + + /* Check for query buffer length */ + if (u4SetBufferLen < *pu4SetInfoLen) { + DBGLOG(OID, WARN, "Too short length %u\n", u4SetBufferLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + prPacket = (P_PARAM_PACKET_KEEPALIVE_T)kalMemAlloc(sizeof(PARAM_PACKET_KEEPALIVE_T), VIR_MEM_TYPE); + if (!prPacket) { + DBGLOG(OID, ERROR, "Can not alloc memory for PARAM_PACKET_KEEPALIVE_T\n"); + return -ENOMEM; + } + kalMemCopy(prPacket, pvSetBuffer, sizeof(PARAM_PACKET_KEEPALIVE_T)); + + DBGLOG(OID, INFO, "enable=%d, index=%d\r\n", prPacket->enable, prPacket->index); + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_WFC_KEEP_ALIVE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(PARAM_PACKET_KEEPALIVE_T), (PUINT_8)prPacket, NULL, 0); + kalMemFree(prPacket, VIR_MEM_TYPE, sizeof(PARAM_PACKET_KEEPALIVE_T)); + return rStatus; +} + +WLAN_STATUS +wlanoidSetRoamingCtrl( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + CMD_ROAMING_CTRL_T rRoamingCtrl; + BOOLEAN fgIsSuspend = *(PUINT_8)pvSetBuffer; + + kalMemZero(&rRoamingCtrl, sizeof(rRoamingCtrl)); + /* fgEnable: enable roaming detect or not, in suspend, don't trigger roaming */ + rRoamingCtrl.fgEnable = !fgIsSuspend; + #if 0 + /* u2RcpiLowThr: RCPI threshold to trigger roaming event */ + rRoamingCtrl.u2RcpiLowThr = (fgEnable == TRUE) ? 57:57; + /* ucRoamingRetryLimit: at most how many times report roaming discovery if roaming failed last time */ + rRoamingCtrl.ucRoamingRetryLimit = 0; + #endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ROAMING_CONTROL, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(rRoamingCtrl), + (PUINT_8)&rRoamingCtrl, + pvSetBuffer, + u4SetBufferLen + ); +} + +#ifdef FW_CFG_SUPPORT +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query fw cfg info +* +* \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_PENDING +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanoidQueryCfgRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + struct _CMD_HEADER_T *prCmdV1Header = (struct _CMD_HEADER_T *)pvQueryBuffer; + struct _CMD_HEADER_T cmdV1Header; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct _CMD_HEADER_T); + + if (u4QueryBufferLen < sizeof(struct _CMD_HEADER_T)) + return WLAN_STATUS_INVALID_LENGTH; + + kalMemCopy(&cmdV1Header, prCmdV1Header, sizeof(struct _CMD_HEADER_T)); + rStatus = wlanSendSetQueryCmd( + prAdapter, + CMD_ID_GET_SET_CUSTOMER_CFG, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryCfgRead, + nicOidCmdTimeoutCommon, + sizeof(struct _CMD_HEADER_T), + (PUINT_8) &cmdV1Header, + pvQueryBuffer, + u4QueryBufferLen); + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set fw cfg info +* +* \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_INVALID_DATA +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanoidSetFwParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + ASSERT(prAdapter); + + if (!pvSetBuffer || !u4SetBufferLen) { + DBGLOG(OID, ERROR, "Buffer is NULL\n"); + return WLAN_STATUS_INVALID_DATA; + } + DBGLOG(OID, INFO, "Fw Params: %s\n", (PUINT_8)pvSetBuffer); + return wlanFwCfgParse(prAdapter, (PUINT_8)pvSetBuffer); +} +#endif + +WLAN_STATUS +wlanoidDisableTdlsPs(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + struct CMD_TDLS_PS_T rTdlsPs; + + if (!prAdapter || !pvSetBuffer) + return WLAN_STATUS_INVALID_DATA; + + rTdlsPs.ucIsEnablePs = *(PUINT_8)pvSetBuffer - '0'; + DBGLOG(OID, INFO, "enable tdls ps %d\n", rTdlsPs.ucIsEnablePs); + wlanSendSetQueryCmd(prAdapter, + CMD_ID_TDLS_PS, + TRUE, + FALSE, + FALSE, + NULL, + nicOidCmdTimeoutCommon, + sizeof(rTdlsPs), + (PUINT_8)&rTdlsPs, + NULL, + 0); + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidSetDrvRoamingPolicy(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + UINT_32 u4RoamingPoily = 0; + P_ROAMING_INFO_T prRoamingFsmInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + UINT_32 u4CurConPolicy; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + + u4RoamingPoily = *(PUINT_32)pvSetBuffer; + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + prConnSettings = (P_CONNECTION_SETTINGS_T) &prAdapter->rWifiVar.rConnSettings; + u4CurConPolicy = prConnSettings->eConnectionPolicy; + + if (u4RoamingPoily == 1) { + if (((prAdapter->rWifiVar.rAisFsmInfo.eCurrentState == AIS_STATE_NORMAL_TR) + || (prAdapter->rWifiVar.rAisFsmInfo.eCurrentState == AIS_STATE_ONLINE_SCAN)) + && (prRoamingFsmInfo->eCurrentState == ROAMING_STATE_IDLE)) + roamingFsmRunEventStart(prAdapter); + + /*Change Connect by any , avoid to connect by BSSID on roaming or beacon timeout!*/ + prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_ANY; + kalMemZero(prConnSettings->aucBSSID, MAC_ADDR_LEN); + } else { + if (prRoamingFsmInfo->eCurrentState != ROAMING_STATE_IDLE) + roamingFsmRunEventAbort(prAdapter); + } + prRoamingFsmInfo->fgDrvRoamingAllow = (BOOLEAN)u4RoamingPoily; + + DBGLOG(REQ, INFO, "wlanoidSetDrvRoamingPolicy, RoamingPoily= %d, conn policy= [%d] -> [%d]\n", + u4RoamingPoily, u4CurConPolicy, prConnSettings->eConnectionPolicy); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidUpdateFtIes(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, + PUINT_32 pu4SetInfoLen) +{ + struct FT_IES *prFtIes = NULL; + UINT_32 u4IeLen = 0; + PUINT_8 pucIEStart = NULL; + struct cfg80211_update_ft_ies_params *ftie = NULL; + P_STA_RECORD_T prStaRec = NULL; + struct MSG_SAA_FT_CONTINUE *prFtContinueMsg = NULL; + + if (!pvSetBuffer || u4SetBufferLen == 0) { + DBGLOG(OID, ERROR, "pvSetBuffer is Null %d, Buffer Len %u\n", !pvSetBuffer, u4SetBufferLen); + return WLAN_STATUS_INVALID_DATA; + } + prStaRec = prAdapter->rWifiVar.rAisFsmInfo.prTargetStaRec; + ftie = (struct cfg80211_update_ft_ies_params *)pvSetBuffer; + prFtIes = &prAdapter->prGlueInfo->rFtIeForTx; + if (ftie->ie_len == 0) { + DBGLOG(OID, WARN, "FT Ies length is 0\n"); + return WLAN_STATUS_SUCCESS; + } + if (prFtIes->u4IeLength != ftie->ie_len) { + kalMemFree(prFtIes->pucIEBuf, VIR_MEM_TYPE, prFtIes->u4IeLength); + prFtIes->pucIEBuf = kalMemAlloc(ftie->ie_len, VIR_MEM_TYPE); + prFtIes->u4IeLength = ftie->ie_len; + } + + if (!prFtIes->pucIEBuf) { + DBGLOG(OID, ERROR, "FT: prFtIes->pucIEBuf memory allocation failed, ft ie_len=%u\n", ftie->ie_len); + prFtIes->u4IeLength = 0; + return WLAN_STATUS_FAILURE; + } + + pucIEStart = prFtIes->pucIEBuf; + u4IeLen = prFtIes->u4IeLength; + prFtIes->u2MDID = ftie->md; + prFtIes->prFTIE = NULL; + prFtIes->prMDIE = NULL; + prFtIes->prRsnIE = NULL; + prFtIes->prTIE = NULL; + if (u4IeLen) + kalMemCopy(pucIEStart, ftie->ie, u4IeLen); + while (u4IeLen >= 2) { + UINT_32 u4InfoElemLen = IE_SIZE(pucIEStart); + + if (u4InfoElemLen > u4IeLen) + break; + switch (pucIEStart[0]) { + case ELEM_ID_MOBILITY_DOMAIN: + prFtIes->prMDIE = (struct IE_MOBILITY_DOMAIN_T *)pucIEStart; + break; + case ELEM_ID_FAST_TRANSITION: + prFtIes->prFTIE = (struct IE_FAST_TRANSITION_T *)pucIEStart; + break; + case ELEM_ID_RESOURCE_INFO_CONTAINER: + break; + case ELEM_ID_TIMEOUT_INTERVAL: + prFtIes->prTIE = (IE_TIMEOUT_INTERVAL_T *)pucIEStart; + break; + case ELEM_ID_RSN: + prFtIes->prRsnIE = (P_RSN_INFO_ELEM_T)pucIEStart; + break; + } + u4IeLen -= u4InfoElemLen; + pucIEStart += u4InfoElemLen; + } + DBGLOG(OID, INFO, "MdId %d IesLen %u, MDIE %d FTIE %d RSN %d TIE %d\n", ftie->md, prFtIes->u4IeLength, + !!prFtIes->prMDIE, !!prFtIes->prFTIE, !!prFtIes->prRsnIE, !!prFtIes->prTIE); + /* check if SAA is waiting to send Reassoc req */ + if (!prStaRec || prStaRec->ucAuthTranNum != AUTH_TRANSACTION_SEQ_2 || + !prStaRec->fgIsReAssoc || prStaRec->ucStaState != STA_STATE_1) + return WLAN_STATUS_SUCCESS; + + prFtContinueMsg = (struct MSG_SAA_FT_CONTINUE *) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_SAA_FT_CONTINUE)); + if (!prFtContinueMsg) { + DBGLOG(OID, WARN, "failed to allocate Join Req Msg\n"); + return WLAN_STATUS_FAILURE; + } + prFtContinueMsg->rMsgHdr.eMsgId = MID_OID_SAA_FSM_CONTINUE; + prFtContinueMsg->prStaRec = prStaRec; + /* ToDo: for Resource Request Protocol, we need to check if RIC request is included. */ + if (prFtIes->prMDIE && (prFtIes->prMDIE->ucBitMap & BIT(1))) + prFtContinueMsg->fgFTRicRequest = TRUE; + else + prFtContinueMsg->fgFTRicRequest = FALSE; + DBGLOG(OID, INFO, "continue to do auth/assoc, Ft Request %d\n", prFtContinueMsg->fgFTRicRequest); + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prFtContinueMsg, MSG_SEND_METHOD_BUF); + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidSendNeighborRequest(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, + PUINT_32 pu4SetInfoLen) +{ + struct SUB_ELEMENT_LIST *prSSIDIE = NULL; + P_BSS_INFO_T prAisBssInfo = NULL; + UINT_8 ucSSIDIELen = 0; + PUINT_8 pucSSID = (PUINT_8)pvSetBuffer; + + if (!prAdapter || !prAdapter->prAisBssInfo) + return WLAN_STATUS_INVALID_DATA; + prAisBssInfo = prAdapter->prAisBssInfo; + if (prAisBssInfo->eConnectionState != PARAM_MEDIA_STATE_CONNECTED) { + DBGLOG(OID, ERROR, "didn't connected any Access Point\n"); + return WLAN_STATUS_FAILURE; + } + if (u4SetBufferLen == 0 || !pucSSID) { + rlmTxNeighborReportRequest(prAdapter, prAisBssInfo->prStaRecOfAP, NULL); + return WLAN_STATUS_SUCCESS; + } + + ucSSIDIELen = (UINT_8)(u4SetBufferLen + sizeof(*prSSIDIE)); + prSSIDIE = kalMemAlloc(ucSSIDIELen, PHY_MEM_TYPE); + if (!prSSIDIE) { + DBGLOG(OID, ERROR, "No Memory\n"); + return WLAN_STATUS_FAILURE; + } + prSSIDIE->prNext = NULL; + prSSIDIE->rSubIE.ucSubID = ELEM_ID_SSID; + prSSIDIE->rSubIE.ucLength = (UINT_8)u4SetBufferLen; + kalMemCopy(&prSSIDIE->rSubIE.aucOptInfo[0], pucSSID, (UINT_8)u4SetBufferLen); + DBGLOG(OID, INFO, "Send Neighbor Request, SSID=%s\n", pucSSID); + rlmTxNeighborReportRequest(prAdapter, prAisBssInfo->prStaRecOfAP, prSSIDIE); + kalMemFree(prSSIDIE, PHY_MEM_TYPE, ucSSIDIELen); + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidSync11kCapabilities(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, + PUINT_32 pu4SetInfoLen) +{ + struct CMD_SET_RRM_CAPABILITY rCmdRrmCapa; + + kalMemZero(&rCmdRrmCapa, sizeof(rCmdRrmCapa)); + rCmdRrmCapa.ucDot11RadioMeasurementEnabled = 1; + rlmFillRrmCapa(&rCmdRrmCapa.aucCapabilities[0]); + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RRM_CAPABILITY, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_SET_RRM_CAPABILITY), + (PUINT_8) &rCmdRrmCapa, pvSetBuffer, u4SetBufferLen); +} + +WLAN_STATUS +wlanoidSendBTMQuery(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, + PUINT_32 pu4SetInfoLen) +{ + P_STA_RECORD_T prStaRec = NULL; + struct BSS_TRANSITION_MGT_PARAM_T *prBtmMgt = NULL; + + if (!prAdapter->prAisBssInfo || prAdapter->prAisBssInfo->eConnectionState != + PARAM_MEDIA_STATE_CONNECTED) { + DBGLOG(OID, INFO, "Not connected yet\n"); + return WLAN_STATUS_FAILURE; + } + prStaRec = prAdapter->prAisBssInfo->prStaRecOfAP; + if (!prStaRec || !prStaRec->fgSupportBTM) { + DBGLOG(OID, INFO, "Target BSS(%p) didn't support Bss Transition Management\n", prStaRec); + return WLAN_STATUS_FAILURE; + } + prBtmMgt = &prAdapter->rWifiVar.rAisSpecificBssInfo.rBTMParam; + prBtmMgt->ucDialogToken = wnmGetBtmToken(); + prBtmMgt->ucQueryReason = pvSetBuffer ? (*(PUINT_8)pvSetBuffer - '0'):BSS_TRANSITION_LOW_RSSI; + DBGLOG(OID, INFO, "Send BssTransitionManagementQuery, Reason %d\n", prBtmMgt->ucQueryReason); + wnmSendBTMQueryFrame(prAdapter, prStaRec); + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidSendSarEnable(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, + PUINT_32 pu4SetInfoLen) +{ + struct CMD_SAR_ENABLE_T rCmdSarMode; + UINT_32 u4Para = 0; + + u4Para = *((PUINT_32)pvSetBuffer); + + DBGLOG(OID, INFO, "wlanoidSendSarEnable %u\n", u4Para); + + if (u4Para > CFG_MAX_SAR_TABLE_SIZE) { + DBGLOG(OID, ERROR, + "u4Para > CFG_MAX_SAR_TABLE_SIZE(%u).\n", + CFG_MAX_SAR_TABLE_SIZE); + return WLAN_STATUS_FAILURE; + } + + if (prAdapter == NULL) { + DBGLOG(OID, ERROR, "prAdapter == NULL.\n"); + return WLAN_STATUS_FAILURE; + } + + kalMemZero(&rCmdSarMode, sizeof(struct CMD_SAR_ENABLE_T)); + + rCmdSarMode.u1SAREnable = (u4Para == 0) ? 0 : 1; + + if (u4Para <= 2) { + /*old flow firmware get data from nvram.*/ + rCmdSarMode.u1CmdVersion = 2; + rCmdSarMode.u1SAREnable = u4Para; + } else { + /*new flow firmware get data from driver.*/ + rCmdSarMode.u1CmdVersion = 3; + + rCmdSarMode.rTxPwrLmtSar[0].acTxPwrLimit2G = + g_aucSarTableMainAnt[u4Para-1].acTxPwrLimit2G; + rCmdSarMode.rTxPwrLmtSar[0].acTxPwrLimit5G[0] = + g_aucSarTableMainAnt[u4Para-1].acTxPwrLimit5G[0]; + rCmdSarMode.rTxPwrLmtSar[0].acTxPwrLimit5G[1] = + g_aucSarTableMainAnt[u4Para-1].acTxPwrLimit5G[1]; + rCmdSarMode.rTxPwrLmtSar[0].acTxPwrLimit5G[2] = + g_aucSarTableMainAnt[u4Para-1].acTxPwrLimit5G[2]; + rCmdSarMode.rTxPwrLmtSar[0].acTxPwrLimit5G[3] = + g_aucSarTableMainAnt[u4Para-1].acTxPwrLimit5G[3]; + + rCmdSarMode.rTxPwrLmtSar[1].acTxPwrLimit2G = + g_aucSarTableAuxiliaryAnt[u4Para-1].acTxPwrLimit2G; + rCmdSarMode.rTxPwrLmtSar[1].acTxPwrLimit5G[0] = + g_aucSarTableAuxiliaryAnt[u4Para-1].acTxPwrLimit5G[0]; + rCmdSarMode.rTxPwrLmtSar[1].acTxPwrLimit5G[1] = + g_aucSarTableAuxiliaryAnt[u4Para-1].acTxPwrLimit5G[1]; + rCmdSarMode.rTxPwrLmtSar[1].acTxPwrLimit5G[2] = + g_aucSarTableAuxiliaryAnt[u4Para-1].acTxPwrLimit5G[2]; + rCmdSarMode.rTxPwrLmtSar[1].acTxPwrLimit5G[3] = + g_aucSarTableAuxiliaryAnt[u4Para-1].acTxPwrLimit5G[3]; + } + + DBGLOG(OID, INFO, + "SAR-E(%u)-V(%u)-M-2G( %u)-5G(%u,%u,%u,%u) A-2G( %u)-5G(%u,%u,%u,%u)\n", + rCmdSarMode.u1SAREnable, + rCmdSarMode.u1CmdVersion, + rCmdSarMode.rTxPwrLmtSar[0].acTxPwrLimit2G, + rCmdSarMode.rTxPwrLmtSar[0].acTxPwrLimit5G[0], + rCmdSarMode.rTxPwrLmtSar[0].acTxPwrLimit5G[1], + rCmdSarMode.rTxPwrLmtSar[0].acTxPwrLimit5G[2], + rCmdSarMode.rTxPwrLmtSar[0].acTxPwrLimit5G[3], + rCmdSarMode.rTxPwrLmtSar[1].acTxPwrLimit2G, + rCmdSarMode.rTxPwrLmtSar[1].acTxPwrLimit5G[0], + rCmdSarMode.rTxPwrLmtSar[1].acTxPwrLimit5G[1], + rCmdSarMode.rTxPwrLmtSar[1].acTxPwrLimit5G[2], + rCmdSarMode.rTxPwrLmtSar[1].acTxPwrLimit5G[3]); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_SAR_ENABLE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_SAR_ENABLE_T), + (PUINT_8)&rCmdSarMode, pvSetBuffer, u4SetBufferLen); + +} + +/* + * This func is mainly from bionic's strtok.c + */ +static CHAR *strtok_r(CHAR *s, const CHAR *delim, CHAR **last) +{ + char *spanp; + int c, sc; + char *tok; + + + if (s == NULL) { + s = *last; + if (s == 0) + return NULL; + } +cont: + c = *s++; + for (spanp = (char *)delim; (sc = *spanp++) != 0;) { + if (c == sc) + goto cont; + } + + if (c == 0) { /* no non-delimiter characters */ + *last = NULL; + return NULL; + } + tok = s - 1; + + for (;;) { + c = *s++; + spanp = (char *)delim; + do { + sc = *spanp++; + if (sc == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + *last = s; + return tok; + } + } while (sc != 0); + } +} + +WLAN_STATUS wlanoidTspecOperation(P_ADAPTER_T prAdapter, PVOID pvBuffer, UINT_32 u4BufferLen, + PUINT_32 pu4InfoLen) +{ + P_PARAM_QOS_TSPEC prTspecParam = NULL; + struct MSG_TS_OPERATE *prMsgTsOperate = NULL; + PUINT_8 pucCmd = (PUINT_8)pvBuffer; + PUINT_8 pucSavedPtr = NULL; + PUINT_8 pucItem = NULL; + INT_32 i4Ret = 0; + UINT_32 u4Ret = 1; + UINT_8 ucApsdSetting = 2; /* 0: legacy; 1: u-apsd; 2: not set yet */ + enum TSPEC_OP_CODE eTsOp; + +#if !CFG_SUPPORT_WMM_AC + DBGLOG(OID, INFO, "WMM AC is not supported\n"); + return WLAN_STATUS_FAILURE; +#endif + if (kalStrniCmp(pucCmd, "dumpts", 6) == 0) { + i4Ret = kalSnprintf(pucCmd, u4BufferLen, "%s", "\nAll Active Tspecs:\n"); + + if (i4Ret < 0) + return WLAN_STATUS_FAILURE; + + *pu4InfoLen = (UINT_32)i4Ret; + + u4BufferLen -= *pu4InfoLen; + pucCmd += *pu4InfoLen; + *pu4InfoLen += wmmDumpActiveTspecs(prAdapter, pucCmd, u4BufferLen); + return WLAN_STATUS_SUCCESS; + } + + if (kalStrniCmp(pucCmd, "addts", 5) == 0) + eTsOp = TX_ADDTS_REQ; + else if (kalStrniCmp(pucCmd, "delts", 5) == 0) + eTsOp = TX_DELTS_REQ; + else { + DBGLOG(OID, INFO, "wrong operation %s\n", pucCmd); + return WLAN_STATUS_FAILURE; + } + /* addts token n,tid n,dir n,psb n,up n,fixed n,size n,maxsize n,maxsrvint n, minsrvint n, + ** inact n, suspension n, srvstarttime n, minrate n,meanrate n,peakrate n,burst n,delaybound n, + ** phyrate n,SBA n,mediumtime n + */ + prMsgTsOperate = (struct MSG_TS_OPERATE *)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(struct MSG_TS_OPERATE)); + if (!prMsgTsOperate) + return WLAN_STATUS_FAILURE; + + kalMemZero(prMsgTsOperate, sizeof(struct MSG_TS_OPERATE)); + prMsgTsOperate->rMsgHdr.eMsgId = MID_OID_WMM_TSPEC_OPERATE; + prMsgTsOperate->eOpCode = eTsOp; + prTspecParam = &prMsgTsOperate->rTspecParam; + pucCmd += 6; + pucItem = (PUINT_8)strtok_r((CHAR *)pucCmd, ",", (CHAR **)&pucSavedPtr); + while (pucItem) { + if (kalStrniCmp(pucItem, "token ", 6) == 0) + u4Ret = kstrtou8(pucItem+6, 0, &prTspecParam->ucDialogToken); + else if (kalStrniCmp(pucItem, "tid ", 4) == 0) { + u4Ret = kstrtou8(pucItem+4, 0, &prMsgTsOperate->ucTid); + prTspecParam->rTsInfo.ucTid = prMsgTsOperate->ucTid; + } else if (kalStrniCmp(pucItem, "dir ", 4) == 0) + u4Ret = kstrtou8(pucItem+4, 0, &prTspecParam->rTsInfo.ucDirection); + else if (kalStrniCmp(pucItem, "psb ", 4) == 0) + u4Ret = kstrtou8(pucItem+4, 0, &ucApsdSetting); + else if (kalStrniCmp(pucItem, "up ", 3) == 0) + u4Ret = kstrtou8(pucItem+3, 0, &prTspecParam->rTsInfo.ucuserPriority); + else if (kalStrniCmp(pucItem, "size ", 5) == 0) { + UINT_16 u2Size = 0; + + u4Ret = kstrtou16(pucItem+5, 0, &u2Size); + prTspecParam->u2NominalMSDUSize |= u2Size; + } else if (kalStrniCmp(pucItem, "fixed ", 6) == 0) { + UINT_8 ucFixed = 0; + + u4Ret = kstrtou8(pucItem+6, 0, &ucFixed); + if (ucFixed) + prTspecParam->u2NominalMSDUSize |= BIT(15); + } else if (kalStrniCmp(pucItem, "maxsize ", 8) == 0) + u4Ret = kstrtou16(pucItem+8, 0, &prTspecParam->u2MaxMSDUsize); + else if (kalStrniCmp(pucItem, "maxsrvint ", 10) == 0) + u4Ret = kalkStrtou32(pucItem+10, 0, &prTspecParam->u4MaxSvcIntv); + else if (kalStrniCmp(pucItem, "minsrvint ", 10) == 0) + u4Ret = kalkStrtou32(pucItem+10, 0, &prTspecParam->u4MinSvcIntv); + else if (kalStrniCmp(pucItem, "inact ", 6) == 0) + u4Ret = kalkStrtou32(pucItem+6, 0, &prTspecParam->u4InactIntv); + else if (kalStrniCmp(pucItem, "suspension ", 11) == 0) + u4Ret = kalkStrtou32(pucItem+11, 0, &prTspecParam->u4SpsIntv); + else if (kalStrniCmp(pucItem, "srvstarttime ", 13) == 0) + u4Ret = kalkStrtou32(pucItem+13, 0, &prTspecParam->u4SvcStartTime); + else if (kalStrniCmp(pucItem, "minrate ", 8) == 0) + u4Ret = kalkStrtou32(pucItem+8, 0, &prTspecParam->u4MinDataRate); + else if (kalStrniCmp(pucItem, "meanrate ", 9) == 0) + u4Ret = kalkStrtou32(pucItem+9, 0, &prTspecParam->u4MeanDataRate); + else if (kalStrniCmp(pucItem, "peakrate ", 9) == 0) + u4Ret = kalkStrtou32(pucItem+9, 0, &prTspecParam->u4PeakDataRate); + else if (kalStrniCmp(pucItem, "burst ", 6) == 0) + u4Ret = kalkStrtou32(pucItem+6, 0, &prTspecParam->u4MaxBurstSize); + else if (kalStrniCmp(pucItem, "delaybound ", 11) == 0) + u4Ret = kalkStrtou32(pucItem+11, 0, &prTspecParam->u4DelayBound); + else if (kalStrniCmp(pucItem, "phyrate ", 8) == 0) + u4Ret = kalkStrtou32(pucItem+8, 0, &prTspecParam->u4MinPHYRate); + else if (kalStrniCmp(pucItem, "sba ", 4) == 0) + u4Ret = wlanDecimalStr2Hexadecimals(pucItem+4, &prTspecParam->u2Sba); + else if (kalStrniCmp(pucItem, "mediumtime ", 11) == 0) + u4Ret = kstrtou16(pucItem+11, 0, &prTspecParam->u2MediumTime); + + if (u4Ret) { + DBGLOG(OID, ERROR, "Parse %s error\n", pucItem); + cnmMemFree(prAdapter, prMsgTsOperate); + return WLAN_STATUS_FAILURE; + } + pucItem = (PUINT_8)strtok_r(NULL, ",", (CHAR **)&pucSavedPtr); + } + /* if APSD is not set in addts request, use global wmmps settings */ + if (!prAdapter->prAisBssInfo) + DBGLOG(OID, ERROR, "AisBssInfo is NULL!\n"); + else if (ucApsdSetting == 2) { + P_PM_PROFILE_SETUP_INFO_T prPmProf = NULL; + ENUM_ACI_T eAc = aucUp2ACIMap[prTspecParam->rTsInfo.ucuserPriority]; + + prPmProf = &prAdapter->prAisBssInfo->rPmProfSetupInfo; + switch (prTspecParam->rTsInfo.ucDirection) { + case UPLINK_TS: /* UpLink*/ + if (prPmProf->ucBmpTriggerAC & BIT(eAc)) + prTspecParam->rTsInfo.ucApsd = 1; + break; + case DOWNLINK_TS:/* DownLink */ + if (prPmProf->ucBmpDeliveryAC & BIT(eAc)) + prTspecParam->rTsInfo.ucApsd = 1; + break; + case BI_DIR_TS: /* Bi-directional */ + if ((prPmProf->ucBmpTriggerAC & BIT(eAc)) && + (prPmProf->ucBmpDeliveryAC & BIT(eAc))) + prTspecParam->rTsInfo.ucApsd = 1; + break; + } + } else + prTspecParam->rTsInfo.ucApsd = ucApsdSetting; + *(--pucCmd) = 0; + pucCmd -= 5; + DBGLOG(OID, INFO, "%s %d %d %d %d %d %d %d %u %u %u %u %u %u %u %u %u %u %u 0x%04x %d\n", pucCmd, + prTspecParam->ucDialogToken, prTspecParam->rTsInfo.ucTid, prTspecParam->rTsInfo.ucDirection, + prTspecParam->rTsInfo.ucApsd, prTspecParam->rTsInfo.ucuserPriority, prTspecParam->u2NominalMSDUSize, + prTspecParam->u2MaxMSDUsize, prTspecParam->u4MaxSvcIntv, prTspecParam->u4MinSvcIntv, + prTspecParam->u4InactIntv, prTspecParam->u4SpsIntv, prTspecParam->u4SvcStartTime, + prTspecParam->u4MinDataRate, prTspecParam->u4MeanDataRate, prTspecParam->u4PeakDataRate, + prTspecParam->u4MaxBurstSize, prTspecParam->u4DelayBound, prTspecParam->u4MinPHYRate, + prTspecParam->u2Sba, prTspecParam->u2MediumTime); + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T)prMsgTsOperate, MSG_SEND_METHOD_BUF); + return WLAN_STATUS_SUCCESS; +} + +/* It's a Integretion Test function for RadioMeasurement. If you found errors during doing Radio Measurement, +** you can run this IT function with iwpriv wlan0 set_str_cmd \"31 RM-IT xx,xx,xx, xx\" +** xx,xx,xx,xx is the RM request frame data +*/ +WLAN_STATUS +wlanoidPktProcessIT(P_ADAPTER_T prAdapter, PVOID pvBuffer, UINT_32 u4BufferLen, + PUINT_32 pu4InfoLen) +{ + SW_RFB_T rSwRfb; + static UINT_8 aucPacket[200] = {0,}; + PUINT_8 pucSavedPtr = (CHAR *)pvBuffer; + PUINT_8 pucItem = NULL; + UINT_8 j = 0; + INT_8 i = 0; + UINT_8 ucByte; + VOID(*process_func)(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); + + if (!pvBuffer) { + DBGLOG(OID, ERROR, "pvBuffer is NULL\n"); + return WLAN_STATUS_FAILURE; + } + + if (!kalStrniCmp(pucSavedPtr, "RM-IT ", 6)) { + process_func = rlmProcessRadioMeasurementRequest; + pucSavedPtr += 6; + } else if (!kalStrniCmp(pucSavedPtr, "BTM-IT ", 7)) { + process_func = wnmRecvBTMRequest; + pucSavedPtr += 7; + } else { + pucSavedPtr[10] = 0; + DBGLOG(OID, ERROR, "IT type %s is not supported\n", pucSavedPtr); + return WLAN_STATUS_NOT_SUPPORTED; + } + kalMemZero(aucPacket, sizeof(aucPacket)); + pucItem = strtok_r(pucSavedPtr, ",", (CHAR **)&pucSavedPtr); + while (pucItem) { + ucByte = *pucItem; + i = 0; + while (ucByte) { + if (i > 1) { + DBGLOG(OID, ERROR, "more than 2 char for one byte\n"); + return WLAN_STATUS_FAILURE; + } else if (i == 1) + aucPacket[j] <<= 4; + if (ucByte >= '0' && ucByte <= '9') + aucPacket[j] |= ucByte - '0'; + else if (ucByte >= 'a' && ucByte <= 'f') + aucPacket[j] |= ucByte - 'a' + 10; + else if (ucByte >= 'A' && ucByte <= 'F') + aucPacket[j] |= ucByte - 'A' + 10; + else { + DBGLOG(OID, ERROR, "not a hex char %c\n", ucByte); + return WLAN_STATUS_FAILURE; + } + ucByte = *(++pucItem); + i++; + } + j++; + pucItem = strtok_r(NULL, ",", (CHAR **)&pucSavedPtr); + } + DBGLOG(OID, INFO, "Dump IT packet, len %d\n", j); + dumpMemory8(aucPacket, j); + if (j < WLAN_MAC_MGMT_HEADER_LEN) { + DBGLOG(OID, ERROR, "packet length %d less than mac header 24\n", j); + return WLAN_STATUS_FAILURE; + } + rSwRfb.pvHeader = (PVOID)&aucPacket[0]; + rSwRfb.u2PacketLen = j; + rSwRfb.u2HeaderLen = WLAN_MAC_MGMT_HEADER_LEN; + process_func(prAdapter, &rSwRfb); + return WLAN_STATUS_SUCCESS; +} + +/* Firmware Integration Test functions +** This function receives commands that are input by a firmware IT test script +** By using IT test script, RD no need to run IT with a real Access Point +** For example: iwpriv wlan0 driver \"Fw-Event Roaming ....\" +*/ +WLAN_STATUS +wlanoidFwEventIT(P_ADAPTER_T prAdapter, PVOID pvBuffer, UINT_32 u4BufferLen, PUINT_32 pu4InfoLen) { + PUINT_8 pucCmd = (CHAR *)pvBuffer; + + /* Firmware roaming Integration Test case */ + if (!kalStrniCmp(pucCmd, "Roaming", 7)) { + UINT_8 ucRCPI = 0; + UINT_8 ucFrameType = 0; + UINT_32 i = 0; + P_CMD_INFO_T prCmdInfo; + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + P_WLAN_ACTION_FRAME prAction = NULL; + P_QUE_ENTRY_T prEntry = NULL; + P_QUE_ENTRY_T prPreEntry = NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + if (prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc) + ucRCPI = prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc->ucRCPI; + roamingFsmRunEventDiscovery(prAdapter, ucRCPI); + /* Try to find the BTM query frame which is sent by roamingFsmRunEventDiscovery */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + for (prEntry = QUEUE_GET_HEAD(&prGlueInfo->rCmdQueue); + prEntry != NULL; prPreEntry = prEntry, + prEntry = QUEUE_GET_NEXT_ENTRY(&prCmdInfo->rQueEntry)) { + prCmdInfo = (P_CMD_INFO_T)prEntry; + if (!prCmdInfo->prMsduInfo || prCmdInfo->prMsduInfo->eSrc != TX_PACKET_MGMT || + !prCmdInfo->prMsduInfo->prPacket) + continue; + prAction = (P_WLAN_ACTION_FRAME)prCmdInfo->prMsduInfo->prPacket; + if (prAction->u2FrameCtrl != MAC_FRAME_ACTION) + continue; + if (prAction->ucCategory == CATEGORY_RM_ACTION && + prAction->ucAction == ACTION_NEIGHBOR_REPORT_REQ) { + ucFrameType = 1; + break; + } + if (prAction->ucCategory == CATEGORY_WNM_ACTION && + prAction->ucAction == ACTION_WNM_BSS_TRANSITION_MANAGEMENT_QUERY) { + ucFrameType = 2; + break; + } + } + if (prEntry) { + if (prPreEntry) { + prPreEntry->prNext = prEntry->prNext; + prGlueInfo->rCmdQueue.u4NumElem--; + } else + QUEUE_INITIALIZE(&prGlueInfo->rCmdQueue); + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + if (ucFrameType == 2) { /* roamingFsmRunEventDiscovery has sent a btm query frame */ + struct ACTION_BTM_QUERY_FRAME_T *prBtmQuery = (struct ACTION_BTM_QUERY_FRAME_T *)prAction; + + /* IT string may be "Roaming ", to reuse btm it function, + ** we need to replace Roaming with BTM-IT. Length of Roaming is 7 bytes, so pucCmd + ** need to self add 1, and buffer length need to self minus 1, and copy BTM-IT to pucCmd. + */ + pucCmd++; + u4BufferLen--; + kalMemCopy(pucCmd, "BTM-IT", 6); + + /* Find the diaglogToken string in , + ** it follows "BTM-IT ", whose length is 7 + */ + for (ucRCPI = 0, i = 7; i < u4BufferLen; i++) { + if (pucCmd[i] == ',') + ucRCPI++; + if (ucRCPI == OFFSET_OF(struct ACTION_BTM_QUERY_FRAME_T, ucDialogToken)) + break; + } + /* Replace diaglog token string with the token that is in query frame */ + ucRCPI = prBtmQuery->ucDialogToken; + ucFrameType = (ucRCPI >> 4) & 0xf; + if (ucFrameType > 9) + pucCmd[++i] = ucFrameType + 'a' - 10; + else + pucCmd[++i] = ucFrameType + '0'; + ucFrameType = ucRCPI & 0xf; + if (ucFrameType > 9) + pucCmd[++i] = ucFrameType + 'a' - 10; + else + pucCmd[++i] = ucFrameType + '0'; + wlanoidPktProcessIT(prAdapter, (PVOID)pucCmd, u4BufferLen, pu4InfoLen); + } else if (ucFrameType == 1) { + /* Not support neighbor ap report request IT now */ + } + } else { + DBGLOG(OID, ERROR, "Not supported Fw Event IT type %s\n", pucCmd); + return WLAN_STATUS_FAILURE; + } + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidDumpUapsdSetting(P_ADAPTER_T prAdapter, PVOID pvBuffer, UINT_32 u4BufferLen, + PUINT_32 pu4InfoLen) +{ + PUINT_8 pucCmd = (PUINT_8)pvBuffer; + UINT_8 ucFinalSetting = 0; + UINT_8 ucStaticSetting = 0; + P_PM_PROFILE_SETUP_INFO_T prPmProf = NULL; + + if (!pvBuffer) { + DBGLOG(OID, ERROR, "pvBuffer is NULL\n"); + return WLAN_STATUS_FAILURE; + } + if (!prAdapter->prAisBssInfo) + return WLAN_STATUS_FAILURE; + prPmProf = &prAdapter->prAisBssInfo->rPmProfSetupInfo; + ucStaticSetting = (prPmProf->ucBmpDeliveryAC << 4) | prPmProf->ucBmpTriggerAC; + ucFinalSetting = wmmCalculateUapsdSetting(prAdapter); + *pu4InfoLen = kalSnprintf(pucCmd, u4BufferLen, + "\nStatic Uapsd Setting:0x%02x\nFinal Uapsd Setting:0x%02x", ucStaticSetting, ucFinalSetting); + + if (*pu4InfoLen < 0) + return WLAN_STATUS_FAILURE; + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_SUPPORT_LOWLATENCY_MODE +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to enable/disable LowLatency mode +* +* \param[in] pvAdapter A 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_PENDING +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanoidSetLowLatencyMode(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + struct CMD_LOWLATENCY_MODE_HEADER rLowLatencyModeHeader; + BOOLEAN fgEnable, fgEnScan, fgLatencyStat; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_32 u4Events; + PARAM_POWER_MODE_T rPowerMode; + UINT_32 u4OldValue; + + DEBUGFUNC("wlanoidSetLowLatencyMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + kalMemCopy(&u4Events, pvSetBuffer, u4SetBufferLen); + + DBGLOG(OID, TRACE, "Event change gaming=%d, network:%d whitelist:%d\n", + (u4Events & GED_EVENT_GAS), + (u4Events & GED_EVENT_NETWORK), + (u4Events & GED_EVENT_DOPT_WIFI_SCAN)); + + fgEnable = ((u4Events & GED_EVENT_GAS) != 0) && ((u4Events & GED_EVENT_NETWORK) != 0); + + if (fgEnable && (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED)) + return WLAN_STATUS_SUCCESS; + fgEnScan = (!fgEnable || ((u4Events & GED_EVENT_DOPT_WIFI_SCAN) != 0)); + + rPowerMode.ucBssIdx = prAdapter->prAisBssInfo->ucBssIndex; + + DBGLOG(OID, INFO, "Gaming mode event change Enable=%d EnableScan:%d\n", + fgEnable, fgEnScan); + + prAdapter->fgEnCfg80211Scan = fgEnScan; + + u4OldValue = prAdapter->rWlanInfo.u4PowerSaveFlag[rPowerMode.ucBssIdx]; + fgLatencyStat = (u4OldValue & BIT(PS_CALLER_GPU)) ? TRUE : FALSE; + DBGLOG(OID, INFO, "LowLatency mode fgLatencyStat=%d\n", fgLatencyStat); + if (fgEnable == fgLatencyStat) + return WLAN_STATUS_SUCCESS; + + prAdapter->u4QmRxBaMissTimeout = fgEnable ? + SHORT_QM_RX_BA_ENTRY_MISS_TIMEOUT_MS : DEFAULT_QM_RX_BA_ENTRY_MISS_TIMEOUT_MS; + + rLowLatencyModeHeader.ucVersion = LOWLATENCY_MODE_CMD_V1; + rLowLatencyModeHeader.ucType = 0; + rLowLatencyModeHeader.ucMagicCode = LOWLATENCY_MODE_MAGIC_CODE; + rLowLatencyModeHeader.ucBufferLen = sizeof(struct LOWLATENCY_MODE_SETTING); + rLowLatencyModeHeader.rSetting.fgEnable = fgEnable; + + DBGLOG(OID, INFO, "Set LowLatency mode enable=%d\n", fgEnable); + + + if (fgEnable) + rPowerMode.ePowerMode = Param_PowerModeCAM; + else + rPowerMode.ePowerMode = Param_PowerModeFast_PSP; + + wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_ENABLE_LOW_LATENCEY_MODE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct CMD_LOWLATENCY_MODE_HEADER), /* u4SetQueryInfoLen */ + (PUINT_8) & rLowLatencyModeHeader, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + + nicPowerSaveInfoMap(prAdapter, rPowerMode.ucBssIdx, rPowerMode.ePowerMode, PS_CALLER_GPU); + rStatus = nicConfigPowerSaveProfile(prAdapter, + rPowerMode.ucBssIdx, rPowerMode.ePowerMode, + FALSE); + + return rStatus; +} +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + +/* Oshare mode enable command */ +#if CFG_SUPPORT_OSHARE +WLAN_STATUS wlanoidSetOshareMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + if (!prAdapter || !pvSetBuffer) + return WLAN_STATUS_INVALID_DATA; + + DBGLOG(OID, TRACE, "wlanoidSetOshareMode\n"); + + return wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_OSHARE_MODE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + TRUE, /* fgIsOid */ + nicCmdEventSetCommon, /* pfCmdDoneHandler*/ + nicOidCmdTimeoutCommon, /* pfCmdTimeoutHandler */ + u4SetBufferLen, /* u4SetQueryInfoLen */ + (PUINT_8) pvSetBuffer,/* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0); /* u4SetQueryBufferLen */ +} +#endif + +WLAN_STATUS +wlanoidQueryWifiLogLevelSupport(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + struct PARAM_WIFI_LOG_LEVEL_UI *pparam; + + DEBUGFUNC("wlanoidQueryWifiLogLevelSupport"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + pparam = (struct PARAM_WIFI_LOG_LEVEL_UI *) pvQueryBuffer; + + DBGLOG(OID, INFO, "version: %d, module: %d, enable: %d\n", pparam->u4Version, + pparam->u4Module, pparam->u4Enable); + + pparam->u4Enable = wlanDbgLevelUiSupport(prAdapter, pparam->u4Version, pparam->u4Module); + *pu4QueryInfoLen = sizeof(struct PARAM_WIFI_LOG_LEVEL_UI); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidQueryWifiLogLevel(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + struct PARAM_WIFI_LOG_LEVEL *pparam; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryWifiLogLevel"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + pparam = (struct PARAM_WIFI_LOG_LEVEL *) pvQueryBuffer; + + DBGLOG(OID, INFO, "version: %d, module: %d\n", pparam->u4Version, pparam->u4Module); + + pparam->u4Level = wlanDbgGetLogLevelImpl(prAdapter, pparam->u4Version, pparam->u4Module); + *pu4QueryInfoLen = sizeof(struct PARAM_WIFI_LOG_LEVEL_UI); + + return rStatus; +} + +WLAN_STATUS +wlanoidSetWifiLogLevel(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + struct PARAM_WIFI_LOG_LEVEL *pparam; + + DEBUGFUNC("wlanoidSetWifiLogLevel"); + + ASSERT(prAdapter); + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + pparam = (struct PARAM_WIFI_LOG_LEVEL *) pvSetBuffer; + + DBGLOG(OID, INFO, "version: %d, module: %d, level: %d\n", pparam->u4Version, + pparam->u4Module, pparam->u4Level); + + wlanDbgSetLogLevelImpl(prAdapter, pparam->u4Version, pparam->u4Module, + pparam->u4Level); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidEnableRoaming(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + DBGLOG(OID, INFO, "enable roaming\n"); + + aisRemoveBlacklistBySource(prAdapter, AIS_BLACK_LIST_FROM_FWK); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidConfigRoaming(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + struct nlattr *attrlist; + struct AIS_BLACKLIST_ITEM *prBlackList; + UINT_32 len_shift = 0; + UINT_32 numOfList[2] = { 0 }; + int i; + + attrlist = (struct nlattr *)pvSetBuffer; + + /* get the number of blacklist and copy those mac addresses from HAL */ + if (attrlist->nla_type == WIFI_ATTRIBUTE_ROAMING_BLACKLIST_NUM) { + numOfList[0] = nla_get_u32(attrlist); + len_shift += NLA_ALIGN(attrlist->nla_len); + } + DBGLOG(REQ, INFO, "Get the number of blacklist=%d\n", numOfList[0]); + + if (numOfList[0] >= 0 && numOfList[0] <= MAX_FW_ROAMING_BLACKLIST_SIZE) { + /*Refresh all the FWKBlacklist */ + aisRemoveBlacklistBySource(prAdapter, AIS_BLACK_LIST_FROM_FWK); + + /* Start to receive blacklist mac addresses and set to FWK blacklist */ + attrlist = (struct nlattr *)((UINT_8 *) pvSetBuffer + len_shift); + for (i = 0; i < numOfList[0]; i++) { + if (attrlist->nla_type == WIFI_ATTRIBUTE_ROAMING_BLACKLIST_BSSID) + prBlackList = aisAddBlacklistByBssid(prAdapter, nla_data(attrlist), + AIS_BLACK_LIST_FROM_FWK); + len_shift += NLA_ALIGN(attrlist->nla_len); + attrlist = (struct nlattr *)((UINT_8 *) pvSetBuffer + len_shift); + } + } + + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanoidGetWifiType(IN P_ADAPTER_T prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct PARAM_GET_WIFI_TYPE *prParamGetWifiType; + P_NETDEV_PRIVATE_GLUE_INFO prNetDevPrivate; + P_BSS_INFO_T prBssInfo = NULL; + uint8_t ucBssIdx; + uint8_t ucPhyType; + uint8_t ucMaxCopySize; + uint8_t *pNameBuf; + + *pu4SetInfoLen = 0; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, ERROR, + "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + prParamGetWifiType = (struct PARAM_GET_WIFI_TYPE *)pvSetBuffer; + prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) + netdev_priv(prParamGetWifiType->prNetDev); + ucBssIdx = prNetDevPrivate->ucBssIdx; + + DBGLOG(OID, INFO, "bss index=%d\n", ucBssIdx); + + kalMemZero(prParamGetWifiType->arWifiTypeName, + sizeof(prParamGetWifiType->arWifiTypeName)); + pNameBuf = &prParamGetWifiType->arWifiTypeName[0]; + ucMaxCopySize = sizeof(prParamGetWifiType->arWifiTypeName) - 1; + + if (ucBssIdx > HW_BSSID_NUM) { + DBGLOG(OID, ERROR, "invalid bss index: %u\n", ucBssIdx); + return WLAN_STATUS_INVALID_DATA; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + if ((!prBssInfo) || (!IS_BSS_ACTIVE(prBssInfo))) { + DBGLOG(OID, ERROR, "invalid BssInfo: %p, %u\n", + prBssInfo, ucBssIdx); + return WLAN_STATUS_INVALID_DATA; + } + + ucPhyType = prBssInfo->ucPhyTypeSet; + if (ucPhyType & PHY_TYPE_SET_802_11AC) + kalStrnCpy(pNameBuf, "11AC", ucMaxCopySize); + else if (ucPhyType & PHY_TYPE_SET_802_11N) + kalStrnCpy(pNameBuf, "11N", ucMaxCopySize); + else if (ucPhyType & PHY_TYPE_SET_802_11B) + kalStrnCpy(pNameBuf, "11B", ucMaxCopySize); + else if (ucPhyType & PHY_TYPE_SET_802_11G) + kalStrnCpy(pNameBuf, "11G", ucMaxCopySize); + else if (ucPhyType & PHY_TYPE_SET_802_11A) + kalStrnCpy(pNameBuf, "11A", ucMaxCopySize); + else + DBGLOG(OID, INFO, + "unknown wifi type, prBssInfo->ucPhyTypeSet: %u\n", + ucPhyType); + + *pu4SetInfoLen = kalStrLen(pNameBuf); + + DBGLOG(OID, INFO, "wifi type=[%s](%d), phyType=%u\n", + pNameBuf, *pu4SetInfoLen, ucPhyType); + + return WLAN_STATUS_SUCCESS; +} +WLAN_STATUS +wlanoidSetScanMacOui(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + struct PARAM_BSS_MAC_OUI *prParamMacOui; + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(prAdapter->prGlueInfo); + ASSERT(pvSetBuffer); + ASSERT(u4SetBufferLen == sizeof(struct PARAM_BSS_MAC_OUI)); + + prParamMacOui = (struct PARAM_BSS_MAC_OUI *)pvSetBuffer; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prParamMacOui->ucBssIndex); + if (!prBssInfo) { + DBGLOG(REQ, ERROR, "Invalid bss info (ind=%u)\n", + prParamMacOui->ucBssIndex); + return WLAN_STATUS_FAILURE; + } + + kalMemCopy(prBssInfo->ucScanOui, prParamMacOui->ucMacOui, MAC_OUI_LEN); + prBssInfo->fgIsScanOuiSet = TRUE; + *pu4SetInfoLen = MAC_OUI_LEN; + + return WLAN_STATUS_SUCCESS; +} +WLAN_STATUS +wlanoidStopApRole(P_ADAPTER_T prAdapter, void *pvSetBuffer, + UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + unsigned char u4Idx = 0; + P_MSG_P2P_SWITCH_OP_MODE_T prP2pSwitchMode = (P_MSG_P2P_SWITCH_OP_MODE_T) NULL; + + if ((prAdapter == NULL) || (pvSetBuffer == NULL) + || (pu4SetInfoLen == NULL)) { + DBGLOG(OID, WARN, + "(prAdapter == NULL) ||(pvSetBuffer == NULL) ||(pu4SetInfoLen == NULL)\n"); + return WLAN_STATUS_FAILURE; + } + + *pu4SetInfoLen = sizeof(unsigned char); + if (u4SetBufferLen < sizeof(unsigned char)) { + DBGLOG(OID, WARN, "u4SetBufferLen < sizeof(unsigned char)\n"); + return WLAN_STATUS_INVALID_LENGTH; + } + + u4Idx = *(unsigned char *) pvSetBuffer; + + DBGLOG(OID, INFO, "wlanoidStopApRole ucRoleIdx = %d\n", u4Idx); + + prP2pSwitchMode = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_SWITCH_OP_MODE_T)); + if (prP2pSwitchMode == NULL) { + DBGLOG(OID, WARN, "prP2pSwitchMode == NULL.\n"); + return WLAN_STATUS_FAILURE; + } + + prP2pSwitchMode->rMsgHdr.eMsgId = MID_MNY_P2P_STOP_AP; + prP2pSwitchMode->ucRoleIdx = u4Idx; + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prP2pSwitchMode, MSG_SEND_METHOD_UNBUF); + + DBGLOG(OID, INFO, "done, ucRoleIdx = %d\n", u4Idx); + + return WLAN_STATUS_SUCCESS; + +} +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR +/* link quality monitor */ +UINT_32 wlanoidGetLinkQualityInfo(IN struct _ADAPTER_T *prAdapter, + IN void *pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT UINT_32 *pu4SetInfoLen) +{ + struct PARAM_GET_LINK_QUALITY_INFO *prParam; + struct WIFI_LINK_QUALITY_INFO *prSrcLinkQualityInfo = NULL; + struct WIFI_LINK_QUALITY_INFO *prDstLinkQualityInfo = NULL; + + prParam = (struct PARAM_GET_LINK_QUALITY_INFO *)pvSetBuffer; + prSrcLinkQualityInfo = &(prAdapter->rLinkQualityInfo); + prDstLinkQualityInfo = prParam->prLinkQualityInfo; + kalMemCopy(prDstLinkQualityInfo, prSrcLinkQualityInfo, + sizeof(struct WIFI_LINK_QUALITY_INFO)); + + return WLAN_STATUS_SUCCESS; +} +#endif + +uint32_t +wlanoidExternalAuthDone(IN struct _ADAPTER_T *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct _STA_RECORD_T *prStaRec; + struct PARAM_EXTERNAL_AUTH *prParams; + struct MSG_SAA_EXTERNAL_AUTH_DONE *prExternalAuthMsg = NULL; + struct _AIS_FSM_INFO_T *prAisFsmInfo; + UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; + UINT_8 ucBssIndex = 0; + + prParams = (struct PARAM_EXTERNAL_AUTH *) pvSetBuffer; + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + ucBssIndex = prParams->ucBssIdx; + if (!IS_BSS_INDEX_VALID(ucBssIndex)) { + DBGLOG(REQ, ERROR, + "SAE-confirm failed with invalid BssIdx in ndev\n"); + return WLAN_STATUS_INVALID_DATA; + } + + prExternalAuthMsg = (struct MSG_SAA_EXTERNAL_AUTH_DONE *)cnmMemAlloc( + prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_SAA_EXTERNAL_AUTH_DONE)); + if (!prExternalAuthMsg) { + DBGLOG(OID, WARN, + "SAE-confirm failed to allocate Msg\n"); + return WLAN_STATUS_RESOURCES; + } + + /*In case of sometimes the external auth result*/ + /*did not contain BSSID, we use prTargetBssDesc*/ + if (EQUAL_MAC_ADDR(prParams->bssid, aucZeroMacAddr) && + prAisFsmInfo->prTargetBssDesc != NULL) { + DBGLOG(OID, WARN, "BSSID is Null, Set as AIS target BSSID\n"); + COPY_MAC_ADDR(prParams->bssid, prAisFsmInfo->prTargetBssDesc->aucBSSID); + } + + prStaRec = cnmGetStaRecByAddress(prAdapter, ucBssIndex, prParams->bssid); + if (!prStaRec) { + DBGLOG(REQ, WARN, "SAE-confirm failed with bssid:" MACSTR "\n", + prParams->bssid); + return WLAN_STATUS_INVALID_DATA; + } + + prExternalAuthMsg->rMsgHdr.eMsgId = MID_OID_SAA_FSM_EXTERNAL_AUTH; + prExternalAuthMsg->prStaRec = prStaRec; + prExternalAuthMsg->status = prParams->status; + + mboxSendMsg(prAdapter, MBOX_ID_0, (struct _MSG_HDR_T *)prExternalAuthMsg, + MSG_SEND_METHOD_BUF); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidSetP2pRandomMac(P_ADAPTER_T prAdapter, void *pvSetBuffer, + UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + P_BSS_INFO_T prDevBssInfo = NULL; + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_BSS_INFO_T prRoleBssInfo = NULL; + + if ((prAdapter == NULL) || (pvSetBuffer == NULL) + || (pu4SetInfoLen == NULL)) { + DBGLOG(OID, WARN, + "(prAdapter == NULL) ||(pvSetBuffer == NULL) ||(pu4SetInfoLen == NULL)\n"); + return WLAN_STATUS_FAILURE; + } + + DBGLOG(OID, INFO, "wlanoidSetP2pRandomMac.\n"); + /*Todo: block set random mac when p2p goup work or hotspot work*/ + + prDevBssInfo = prAdapter->aprBssInfo[P2P_DEV_BSS_INDEX]; + if (prDevBssInfo == NULL) { + DBGLOG(OID, WARN, "prDevBssInfo == NULL\n"); + return WLAN_STATUS_FAILURE; + } + + prP2pRoleFsmInfo = prAdapter->rWifiVar.aprP2pRoleFsmInfo[0]; + if (prP2pRoleFsmInfo == NULL) { + DBGLOG(OID, WARN, + "prP2pRoleFsmInfo == NULL\n"); + return WLAN_STATUS_FAILURE; + } + + if (prP2pRoleFsmInfo->ucBssIndex > BSS_INFO_NUM) { + DBGLOG(OID, WARN, + "Invalid Bssindex %u.\n", prP2pRoleFsmInfo->ucBssIndex); + return WLAN_STATUS_FAILURE; + } + + prRoleBssInfo = prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex]; + if (prRoleBssInfo == NULL) { + DBGLOG(OID, WARN, "prDevBssInfo == NULL\n"); + return WLAN_STATUS_FAILURE; + } + + prGlueInfo = prAdapter->prGlueInfo; + if ((prGlueInfo == NULL) || (prGlueInfo->prP2PInfo == NULL) + || (prGlueInfo->prP2PInfo->prDevHandler == NULL)) { + DBGLOG(OID, WARN, "invalid parameter.\n"); + return WLAN_STATUS_FAILURE; + } + + /* 1. update dev bss*/ + COPY_MAC_ADDR(prDevBssInfo->aucOwnMacAddr, + (PUINT_8)pvSetBuffer); + + /* 2. update role bss, role index is always 0 in gen3 */ + COPY_MAC_ADDR(prRoleBssInfo->aucOwnMacAddr, + (PUINT_8)pvSetBuffer); + + /* 3. update netdevice addr*/ + COPY_MAC_ADDR(prGlueInfo->prP2PInfo->prDevHandler->dev_addr, + (PUINT_8)pvSetBuffer); + + /* 4. update dev addr in wifivar*/ + COPY_MAC_ADDR(prAdapter->rWifiVar.aucDeviceAddress, + (PUINT_8)pvSetBuffer); + + /* 5. update interface addr in wifivar*/ + COPY_MAC_ADDR(prAdapter->rWifiVar.aucInterfaceAddress, + (PUINT_8)pvSetBuffer); + + DBGLOG(OID, INFO, "Done, Set p2p random mac to"MACSTR"\n", + MAC2STR((PUINT_8)pvSetBuffer)); + + return WLAN_STATUS_SUCCESS; + +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/wlan_p2p.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/wlan_p2p.c new file mode 100644 index 0000000000000..9bb128a2006d2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/common/wlan_p2p.c @@ -0,0 +1,1687 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** 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. + */ + +/****************************************************************************** +* C O M P I L E R F L A G S +******************************************************************************* +*/ + +/****************************************************************************** +* E X T E R N A L R E F E R E N C E S +******************************************************************************* +*/ +#include "precomp.h" +#include "gl_p2p_ioctl.h" + +/****************************************************************************** +* C O N S T A N T S +******************************************************************************* +*/ + +/****************************************************************************** +* D A T A T Y P E S +******************************************************************************* +*/ + +/****************************************************************************** +* P U B L I C D A T A +******************************************************************************* +*/ + +/****************************************************************************** +* P R I V A T E D A T A +******************************************************************************* +*/ + +/****************************************************************************** +* M A C R O S +******************************************************************************* +*/ + +/****************************************************************************** +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************* +*/ + +/****************************************************************************** +* F U N C T I O N S +******************************************************************************* +*/ +/*----------------------------------------------------------------------------*/ +/*! +* \brief command packet generation utility +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] ucCID Command ID +* \param[in] fgSetQuery Set or Query +* \param[in] fgNeedResp Need for response +* \param[in] pfCmdDoneHandler Function pointer when command is done +* \param[in] u4SetQueryInfoLen The length of the set/query buffer +* \param[in] pucInfoBuffer Pointer to set/query buffer +* +* +* \retval WLAN_STATUS_PENDING +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendSetQueryP2PCmd(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucCID, + IN UINT_8 ucBssIdx, + IN BOOLEAN fgSetQuery, + IN BOOLEAN fgNeedResp, + IN BOOLEAN fgIsOid, + IN PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + IN PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + IN UINT_32 u4SetQueryInfoLen, + IN 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->ucBssIndex = ucBssIdx; + 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 = 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; + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + + DEBUGFUNC("wlanoidSetAddP2PKey"); + DBGLOG(REQ, INFO, "wlanoidSetAddP2PKey\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; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prNewKey->ucBssIdx); + ASSERT(prBssInfo); + + if (prBssInfo->ucBMCWlanIndex >= WTBL_SIZE) { + prBssInfo->ucBMCWlanIndex = + secPrivacySeekForBcEntry(prAdapter, prBssInfo->ucBssIndex, prBssInfo->aucBSSID, + 0xff, CIPHER_SUITE_NONE, 0xff, 0x0, BIT(0)); + } + /* 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 0 + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { /* group client */ +#else + if (kalP2PGetRole(prAdapter->prGlueInfo) == 1) { /* group client */ +#endif + + rCmdKey.ucIsAuthenticator = 0; + } else { /* group owner */ + rCmdKey.ucIsAuthenticator = 1; + /* Force to set GO/AP Tx */ + rCmdKey.ucTxKey = 1; + } + + COPY_MAC_ADDR(rCmdKey.aucPeerAddr, prNewKey->arBSSID); + rCmdKey.ucBssIdx = prNewKey->ucBssIdx; + + if (prNewKey->ucCipher) { + rCmdKey.ucAlgorithmId = prNewKey->ucCipher; + } else { + DBGLOG(REQ, WARN, "prNewKey->ucCipher == 0!\n"); +#if 0 + 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 */ + else if (prNewKey->u4KeyLength == WEP_40_LEN) + rCmdKey.ucAlgorithmId = CIPHER_SUITE_WEP40; /* WEP 40 */ + else if (prNewKey->u4KeyLength == WEP_104_LEN) + rCmdKey.ucAlgorithmId = CIPHER_SUITE_WEP104; /* WEP 104 */ + else + ASSERT(FALSE); +#endif + } + + rCmdKey.ucKeyId = (UINT_8) (prNewKey->u4KeyIndex & 0xff); + rCmdKey.ucKeyLen = (UINT_8) prNewKey->u4KeyLength; + kalMemCopy(rCmdKey.aucKeyMaterial, (PUINT_8) prNewKey->aucKeyMaterial, rCmdKey.ucKeyLen); + +#if CFG_SUPPORT_802_11W + if (IS_BSS_P2P(prBssInfo) && + (rCmdKey.ucAlgorithmId == CIPHER_SUITE_BIP)) { + /* AP PMF */ + if ((rCmdKey.ucKeyId >= 4 && rCmdKey.ucKeyId <= 5) + && (rCmdKey.ucAlgorithmId == CIPHER_SUITE_BIP)) { + DBGLOG_LIMITED(RSN, INFO, "AP mode set BIP\n"); + prBssInfo->rApPmfCfg.fgBipKeyInstalled = TRUE; + } + } +#endif + + if ((rCmdKey.aucPeerAddr[0] & rCmdKey.aucPeerAddr[1] & rCmdKey.aucPeerAddr[2] & + rCmdKey.aucPeerAddr[3] & rCmdKey.aucPeerAddr[4] & rCmdKey.aucPeerAddr[5]) == 0xFF) { + kalMemCopy(rCmdKey.aucPeerAddr, prBssInfo->aucBSSID, MAC_ADDR_LEN); + if (!rCmdKey.ucIsAuthenticator) { + prStaRec = cnmGetStaRecByAddress(prAdapter, rCmdKey.ucBssIdx, rCmdKey.aucPeerAddr); + if (!prStaRec) + ASSERT(FALSE); + } + } else { + prStaRec = cnmGetStaRecByAddress(prAdapter, rCmdKey.ucBssIdx, rCmdKey.aucPeerAddr); + } + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if (rCmdKey.ucAlgorithmId == CIPHER_SUITE_BIP) { + if (rCmdKey.ucIsAuthenticator) { + DBGLOG_LIMITED(RSN, INFO, + "Authenticator BIP bssid:%d\n", + prBssInfo->ucBssIndex); + + rCmdKey.ucWlanIndex = + secPrivacySeekForBcEntry(prAdapter, + prBssInfo->ucBssIndex, + prBssInfo->aucOwnMacAddr, + STA_REC_INDEX_NOT_FOUND, + rCmdKey.ucAlgorithmId, + rCmdKey.ucKeyId, + 0, + 0); + } else { + rCmdKey.ucWlanIndex = + secPrivacySeekForBcEntry(prAdapter, + prBssInfo->ucBssIndex, + prBssInfo->prStaRecOfAP->aucMacAddr, + prBssInfo->prStaRecOfAP->ucIndex, + rCmdKey.ucAlgorithmId, + rCmdKey.ucKeyId, + 0, + 0); + } + + DBGLOG_LIMITED(RSN, INFO, "BIP BC wtbl index:%d\n", + rCmdKey.ucWlanIndex); + } else +#endif + if (1) { + if (rCmdKey.ucTxKey) { + if (prStaRec) { + if (rCmdKey.ucKeyType) { /* RSN STA */ + ASSERT(prStaRec->ucWlanIndex < WTBL_SIZE); + rCmdKey.ucWlanIndex = prStaRec->ucWlanIndex; + prStaRec->fgTransmitKeyExist = TRUE; /* wait for CMD Done ? */ +#if CFG_SUPPORT_802_11W + /* AP PMF */ + DBGLOG_LIMITED(RSN, TRACE, + "Assign client PMF flag = %d\n", + prStaRec->rPmfCfg.fgApplyPmf); + rCmdKey.ucMgmtProtection = + prStaRec->rPmfCfg.fgApplyPmf; +#endif + + } else { + ASSERT(FALSE); + /* prCmdKey->ucWlanIndex = secPrivacySeekForBcEntry(prAdapter,*/ + /* prBssInfo->ucBssIndex, */ + /* NETWORK_TYPE_AIS, prCmdKey->aucPeerAddr,*/ + /* prCmdKey->ucAlgorithmId, prCmdKey->ucKeyId, */ + /* prStaRec->ucCurrentGtkId, BIT(1)); */ + /* Todo:: Check the prCmdKey->ucKeyType */ + /* for some case, like wep, add bc wep key before sta create,*/ + /* so use the rAisSpecificBssInfo to save key setting */ + /* fgAddTxBcKey = TRUE; */ + } + } else { /* GO/AP Tx BC */ + ASSERT(prBssInfo->ucBMCWlanIndex < WTBL_SIZE); + rCmdKey.ucWlanIndex = prBssInfo->ucBMCWlanIndex; + /* rCmdKey.ucWlanIndex = secPrivacySeekForBcEntry(prAdapter, prBssInfo->ucBssIndex, */ + /* prBssInfo->aucBSSID, 0xff, rCmdKey.ucAlgorithmId, rCmdKey.ucKeyId, */ + /* prBssInfo->ucCurrentGtkId, BIT(1)); */ + prBssInfo->fgTxBcKeyExist = TRUE; + prBssInfo->ucTxDefaultKeyID = rCmdKey.ucKeyId; + } + } else { + if (((rCmdKey.aucPeerAddr[0] & rCmdKey.aucPeerAddr[1] & rCmdKey.aucPeerAddr[2] & + rCmdKey.aucPeerAddr[3] & rCmdKey.aucPeerAddr[4] & rCmdKey.aucPeerAddr[5]) == 0xFF) + || + ((rCmdKey.aucPeerAddr[0] | rCmdKey.aucPeerAddr[1] | rCmdKey. + aucPeerAddr[2] | rCmdKey.aucPeerAddr[3] | rCmdKey.aucPeerAddr[4] + | rCmdKey.aucPeerAddr[5]) == 0x00)) { + rCmdKey.ucWlanIndex = 255; /* GC WEP ? */ + ASSERT(FALSE); + } else { + if (prStaRec) { /* GC Rx RSN Group key */ + rCmdKey.ucWlanIndex = + secPrivacySeekForBcEntry(prAdapter, prStaRec->ucBssIndex, + prStaRec->aucMacAddr, + prStaRec->ucIndex, + rCmdKey.ucAlgorithmId, rCmdKey.ucKeyId, + prStaRec->ucCurrentGtkId, BIT(0)); + prStaRec->ucBMCWlanIndex = rCmdKey.ucWlanIndex; + ASSERT(prStaRec->ucBMCWlanIndex < WTBL_SIZE); + } else { /* Exist this case ? */ + ASSERT(FALSE); + /* prCmdKey->ucWlanIndex = */ + /* secPrivacySeekForBcEntry(prAdapter, */ + /* prBssInfo->ucBssIndex, */ + /* NETWORK_TYPE_AIS, */ + /* prCmdKey->aucPeerAddr, */ + /* prCmdKey->ucAlgorithmId, */ + /* prCmdKey->ucKeyId, */ + /* prBssInfo->ucCurrentGtkId, */ + /* BIT(0)); */ + } + } + } + + /* Update Group Key Id after Seek Bc entry */ + if (!rCmdKey.ucKeyType) { + if (prStaRec) + prStaRec->ucCurrentGtkId = rCmdKey.ucKeyId; + else { + /* GC WEP? */ + prBssInfo->ucCurrentGtkId = rCmdKey.ucKeyId; + } + } + } + + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_ADD_REMOVE_KEY, + prNewKey->ucBssIdx, + 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; + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + UINT_32 u4KeyIndex = 0; + + DEBUGFUNC("wlanoidSetRemoveP2PKey"); + ASSERT(prAdapter); + + if (u4SetBufferLen < sizeof(PARAM_REMOVE_KEY_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + prRemovedKey = (P_PARAM_REMOVE_KEY_T) pvSetBuffer; + + /* Check bit 31: this bit should always 0 */ + if (prRemovedKey->u4KeyIndex & IS_TRANSMIT_KEY) { + /* Bit 31 should not be set */ + DBGLOG(REQ, ERROR, "invalid key index: 0x%08x\n", prRemovedKey->u4KeyIndex); + return WLAN_STATUS_INVALID_DATA; + } + + /* Check bits 8 ~ 29 should always be 0 */ + if (prRemovedKey->u4KeyIndex & BITS(8, 29)) { + /* Bit 31 should not be set */ + DBGLOG(REQ, ERROR, "invalid key index: 0x%08x\n", prRemovedKey->u4KeyIndex); + return WLAN_STATUS_INVALID_DATA; + } + + u4KeyIndex = prRemovedKey->u4KeyIndex & 0x000000FF; + + if (u4KeyIndex >= 4) { + DBGLOG(RSN, INFO, "Remove bip key Index : 0x%08x\n", + u4KeyIndex); + return WLAN_STATUS_SUCCESS; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prRemovedKey->ucBssIdx); + + kalMemZero((PUINT_8)&rCmdKey, sizeof(CMD_802_11_KEY)); + + rCmdKey.ucAddRemove = 0; /* remove */ + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { /* group client */ + rCmdKey.ucIsAuthenticator = 0; + } else { /* group owner */ + rCmdKey.ucIsAuthenticator = 1; + } + kalMemCopy(rCmdKey.aucPeerAddr, (PUINT_8) prRemovedKey->arBSSID, MAC_ADDR_LEN); + rCmdKey.ucBssIdx = prRemovedKey->ucBssIdx; + rCmdKey.ucKeyId = (UINT_8) (prRemovedKey->u4KeyIndex & 0x000000ff); + + /* Clean up the Tx key flag */ + prStaRec = cnmGetStaRecByAddress(prAdapter, prRemovedKey->ucBssIdx, prRemovedKey->arBSSID); + + /* mark for MR1 to avoid remove-key, but remove the wlan_tbl0 at the same time */ + if (1/*prRemovedKey->u4KeyIndex & IS_UNICAST_KEY */) { + if (prStaRec) { + rCmdKey.ucKeyType = 1; + rCmdKey.ucWlanIndex = prStaRec->ucWlanIndex; + prStaRec->fgTransmitKeyExist = FALSE; + } else if (rCmdKey.ucIsAuthenticator) + prBssInfo->fgTxBcKeyExist = FALSE; + } else { + if (rCmdKey.ucIsAuthenticator) + prBssInfo->fgTxBcKeyExist = FALSE; + } + + if (!prStaRec) { + if (prAdapter->rWifiVar.rConnSettings.eAuthMode < AUTH_MODE_WPA + && prAdapter->rWifiVar.rConnSettings.eEncStatus != ENUM_ENCRYPTION_DISABLED) { + rCmdKey.ucWlanIndex = prBssInfo->ucBMCWlanIndex; + } else { + rCmdKey.ucWlanIndex = WTBL_RESERVED_ENTRY; + return WLAN_STATUS_SUCCESS; + } + } + + /* mark for MR1 to avoid remove-key, but remove the wlan_tbl0 at the same time */ + /* secPrivacyFreeForEntry(prAdapter, rCmdKey.ucWlanIndex); */ + + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_ADD_REMOVE_KEY, + prRemovedKey->ucBssIdx, + 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) ((ULONG) prNetworkAddress + + (ULONG) (prNetworkAddress->u2AddressLength + + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + + /* construct payload of command packet */ + u4CmdSize = OFFSET_OF(CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress) + + sizeof(IPV4_NETWORK_ADDRESS) * u4IpAddressCount; + + prCmdNetworkAddressList = (P_CMD_SET_NETWORK_ADDRESS_LIST) kalMemAlloc(u4CmdSize, VIR_MEM_TYPE); + + if (prCmdNetworkAddressList == NULL) + return WLAN_STATUS_FAILURE; + + /* fill P_CMD_SET_NETWORK_ADDRESS_LIST */ + prCmdNetworkAddressList->ucBssIndex = prNetworkAddressList->ucBssIdx; + prCmdNetworkAddressList->ucAddressCount = (UINT_8) u4IpAddressCount; + prNetworkAddress = prNetworkAddressList->arAddress; + for (i = 0, j = 0; i < prNetworkAddressList->u4AddressCount; i++) { + if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { + prNetAddrIp = (P_PARAM_NETWORK_ADDRESS_IP) prNetworkAddress->aucAddress; + + kalMemCopy(prCmdNetworkAddressList->arNetAddress[j].aucIpAddr, + &(prNetAddrIp->in_addr), sizeof(UINT_32)); + + j++; + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prNetworkAddress + + (ULONG) (prNetworkAddress->u2AddressLength + + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_IP_ADDRESS, + TRUE, + FALSE, + TRUE, + nicCmdEventSetIpAddress, + nicOidCmdTimeoutCommon, + u4CmdSize, (PUINT_8) prCmdNetworkAddressList, pvSetBuffer, u4SetBufferLen); + + kalMemFree(prCmdNetworkAddressList, VIR_MEM_TYPE, u4CmdSize); + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to query the power save profile. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryP2pPowerSaveProfile(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryP2pPowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen != 0) { + ASSERT(pvQueryBuffer); + /* TODO: FIXME */ + /* *(PPARAM_POWER_MODE) pvQueryBuffer = + * (PARAM_POWER_MODE)(prAdapter->rWlanInfo.arPowerSaveMode[P2P_DEV_BSS_INDEX].ucPsProfile); + */ + /* *pu4QueryInfoLen = sizeof(PARAM_POWER_MODE); */ + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to set the power save profile. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2pPowerSaveProfile(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS status; + PARAM_POWER_MODE ePowerMode; + + DEBUGFUNC("wlanoidSetP2pPowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_POWER_MODE); + if (u4SetBufferLen < sizeof(PARAM_POWER_MODE)) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } else if (*(PPARAM_POWER_MODE) pvSetBuffer >= Param_PowerModeMax) { + DBGLOG(REQ, WARN, "Invalid power mode %d\n", *(PPARAM_POWER_MODE) pvSetBuffer); + return WLAN_STATUS_INVALID_DATA; + } + + ePowerMode = *(PPARAM_POWER_MODE) pvSetBuffer; + + if (prAdapter->fgEnCtiaPowerMode) { + if (ePowerMode == Param_PowerModeCAM) { + /*Todo:: Nothing*/ + /*Todo:: Nothing*/ + } else { + /* User setting to PS mode (Param_PowerModeMAX_PSP or Param_PowerModeFast_PSP) */ + + if (prAdapter->u4CtiaPowerMode == 0) { + /* force to keep in CAM mode */ + ePowerMode = Param_PowerModeCAM; + } else if (prAdapter->u4CtiaPowerMode == 1) { + ePowerMode = Param_PowerModeMAX_PSP; + } else if (prAdapter->u4CtiaPowerMode == 2) { + ePowerMode = Param_PowerModeFast_PSP; + } + } + } + + nicPowerSaveInfoMap(prAdapter, P2P_DEV_BSS_INDEX, ePowerMode, PS_CALLER_P2P); + + status = nicConfigPowerSaveProfile(prAdapter, P2P_DEV_BSS_INDEX, /* TODO: FIXME */ + 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"); + DBGLOG(INIT, INFO, "wlanoidSetP2pSetNetworkAddress (%d)\n", (INT_16) u4SetBufferLen); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 4; + + if (u4SetBufferLen < sizeof(PARAM_NETWORK_ADDRESS_LIST)) + return WLAN_STATUS_INVALID_DATA; + + *pu4SetInfoLen = 0; + u4IpAddressCount = 0; + + prNetworkAddress = prNetworkAddressList->arAddress; + for (i = 0; i < prNetworkAddressList->u4AddressCount; i++) { + if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { + u4IpAddressCount++; + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prNetworkAddress + + (ULONG) (prNetworkAddress->u2AddressLength + + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + + /* construct payload of command packet */ + u4CmdSize = OFFSET_OF(CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress) + + sizeof(IPV4_NETWORK_ADDRESS) * u4IpAddressCount; + + if (u4IpAddressCount == 0) + u4CmdSize = sizeof(CMD_SET_NETWORK_ADDRESS_LIST); + + prCmdNetworkAddressList = (P_CMD_SET_NETWORK_ADDRESS_LIST) kalMemAlloc(u4CmdSize, VIR_MEM_TYPE); + + if (prCmdNetworkAddressList == NULL) + return WLAN_STATUS_FAILURE; + + /* fill P_CMD_SET_NETWORK_ADDRESS_LIST */ + prCmdNetworkAddressList->ucBssIndex = prNetworkAddressList->ucBssIdx; + + /* only to set IP address to FW once ARP filter is enabled */ + if (prAdapter->fgEnArpFilter) { + prCmdNetworkAddressList->ucAddressCount = (UINT_8) u4IpAddressCount; + prNetworkAddress = prNetworkAddressList->arAddress; + + DBGLOG(INIT, INFO, "u4IpAddressCount (%u)\n", u4IpAddressCount); + for (i = 0, j = 0; i < prNetworkAddressList->u4AddressCount; i++) { + if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { + prNetAddrIp = (P_PARAM_NETWORK_ADDRESS_IP) prNetworkAddress->aucAddress; + + kalMemCopy(prCmdNetworkAddressList->arNetAddress[j].aucIpAddr, + &(prNetAddrIp->in_addr), sizeof(UINT_32)); + + j++; + + pucBuf = (PUINT_8) &prNetAddrIp->in_addr; + DBGLOG(INIT, INFO, "prNetAddrIp->in_addr:%d:%d:%d:%d\n", + (UINT_8) pucBuf[0], (UINT_8) pucBuf[1], + (UINT_8) pucBuf[2], (UINT_8) pucBuf[3]); + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prNetworkAddress + + (ULONG) (prNetworkAddress->u2AddressLength + + OFFSET_OF + (PARAM_NETWORK_ADDRESS, aucAddress))); + } + + } else { + prCmdNetworkAddressList->ucAddressCount = 0; + } + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_IP_ADDRESS, + TRUE, + FALSE, + TRUE, + nicCmdEventSetIpAddress, + nicOidCmdTimeoutCommon, + u4CmdSize, (PUINT_8) prCmdNetworkAddressList, pvSetBuffer, u4SetBufferLen); + + kalMemFree(prCmdNetworkAddressList, VIR_MEM_TYPE, u4CmdSize); + return rStatus; +} /* end of wlanoidSetP2pSetNetworkAddress() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set Multicast Address List. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2PMulticastList(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + CMD_MAC_MCAST_ADDR rCmdMacMcastAddr; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* The data must be a multiple of the Ethernet address size. */ + if ((u4SetBufferLen % MAC_ADDR_LEN)) { + DBGLOG(REQ, WARN, "Invalid MC list length %u\n", u4SetBufferLen); + + *pu4SetInfoLen = (((u4SetBufferLen + MAC_ADDR_LEN) - 1) / MAC_ADDR_LEN) * MAC_ADDR_LEN; + + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = u4SetBufferLen; + + /* Verify if we can support so many multicast addresses. */ + if (u4SetBufferLen > MAX_NUM_GROUP_ADDR * MAC_ADDR_LEN) { + 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.ucBssIndex = P2P_DEV_BSS_INDEX; /* TODO: */ + kalMemCopy(rCmdMacMcastAddr.arAddress, pvSetBuffer, u4SetBufferLen); + + return wlanoidSendSetQueryP2PCmd(prAdapter, CMD_ID_MAC_MCAST_ADDR, P2P_DEV_BSS_INDEX, /* TODO: */ + /* This CMD response is no need to complete the OID. Or the event would unsync. */ + TRUE, FALSE, FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_MAC_MCAST_ADDR), + (PUINT_8) &rCmdMacMcastAddr, pvSetBuffer, u4SetBufferLen); + +} /* end of wlanoidSetP2PMulticastList() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to send GAS frame for P2P Service Discovery Request +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendP2PSDRequest(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (u4SetBufferLen < sizeof(PARAM_P2P_SEND_SD_REQUEST)) { + *pu4SetInfoLen = sizeof(PARAM_P2P_SEND_SD_REQUEST); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } +/* rWlanStatus = p2pFsmRunEventSDRequest(prAdapter, (P_PARAM_P2P_SEND_SD_REQUEST)pvSetBuffer); */ + + return rWlanStatus; +} /* end of wlanoidSendP2PSDRequest() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to send GAS frame for P2P Service Discovery Response +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendP2PSDResponse(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (u4SetBufferLen < sizeof(PARAM_P2P_SEND_SD_RESPONSE)) { + *pu4SetInfoLen = sizeof(PARAM_P2P_SEND_SD_RESPONSE); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } +/* rWlanStatus = p2pFsmRunEventSDResponse(prAdapter, (P_PARAM_P2P_SEND_SD_RESPONSE)pvSetBuffer); */ + + return rWlanStatus; +} /* end of wlanoidGetP2PSDRequest() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get GAS frame for P2P Service Discovery Request +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidGetP2PSDRequest(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + /*PUINT_8 pucPacketBuffer = NULL, pucTA = NULL;*/ +/* PUINT_8 pucChannelNum = NULL; */ + /*PUINT_16 pu2PacketLength = NULL;*/ + /*P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T) NULL;*/ + /*UINT_8 ucVersionNum = 0;*/ +/* UINT_8 ucChannelNum = 0, ucSeqNum = 0; */ + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(PARAM_P2P_GET_SD_REQUEST)) { + *pu4QueryInfoLen = sizeof(PARAM_P2P_GET_SD_REQUEST); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + DBGLOG(P2P, TRACE, "Get Service Discovery Request\n"); +#if 0 + ucVersionNum = p2pFuncGetVersionNumOfSD(prAdapter); + if (ucVersionNum == 0) { + P_PARAM_P2P_GET_SD_REQUEST prP2pGetSdReq = (P_PARAM_P2P_GET_SD_REQUEST) pvQueryBuffer; + + pucPacketBuffer = prP2pGetSdReq->aucPacketContent; + pu2PacketLength = &prP2pGetSdReq->u2PacketLength; + pucTA = &prP2pGetSdReq->rTransmitterAddr; + } else { + P_PARAM_P2P_GET_SD_REQUEST_EX prP2pGetSdReqEx = (P_PARAM_P2P_GET_SD_REQUEST_EX) NULL; + + prP2pGetSdReqEx = (P_PARAM_P2P_GET_SD_REQUEST) pvQueryBuffer; + pucPacketBuffer = prP2pGetSdReqEx->aucPacketContent; + pu2PacketLength = &prP2pGetSdReqEx->u2PacketLength; + pucTA = &prP2pGetSdReqEx->rTransmitterAddr; + pucChannelNum = &prP2pGetSdReqEx->ucChannelNum; + ucSeqNum = prP2pGetSdReqEx->ucSeqNum; + } + + rWlanStatus = p2pFuncGetServiceDiscoveryFrame(prAdapter, + pucPacketBuffer, + (u4QueryBufferLen - + sizeof(PARAM_P2P_GET_SD_REQUEST)), + (PUINT_32) pu2PacketLength, pucChannelNum, ucSeqNum); +#else + *pu4QueryInfoLen = 0; + return rWlanStatus; +#endif +#if 0 + 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; +#endif +} /* end of wlanoidGetP2PSDRequest() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get GAS frame for P2P Service Discovery Response +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidGetP2PSDResponse(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + /*P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T) NULL;*/ + /* UINT_8 ucSeqNum = 0, */ + /*UINT_8 ucVersionNum = 0;*/ + /*PUINT_8 pucPacketContent = (PUINT_8) NULL, pucTA = (PUINT_8) NULL;*/ + /*PUINT_16 pu2PacketLength = (PUINT_16) NULL;*/ + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(PARAM_P2P_GET_SD_RESPONSE)) { + *pu4QueryInfoLen = sizeof(PARAM_P2P_GET_SD_RESPONSE); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + DBGLOG(P2P, TRACE, "Get Service Discovery Response\n"); + +#if 0 + ucVersionNum = p2pFuncGetVersionNumOfSD(prAdapter); + if (ucVersionNum == 0) { + P_PARAM_P2P_GET_SD_RESPONSE prP2pGetSdRsp = (P_PARAM_P2P_GET_SD_RESPONSE) NULL; + + prP2pGetSdRsp = (P_PARAM_P2P_GET_SD_REQUEST) pvQueryBuffer; + pucPacketContent = prP2pGetSdRsp->aucPacketContent; + pucTA = &prP2pGetSdRsp->rTransmitterAddr; + pu2PacketLength = &prP2pGetSdRsp->u2PacketLength; + } else { + P_PARAM_P2P_GET_SD_RESPONSE_EX prP2pGetSdRspEx = (P_PARAM_P2P_GET_SD_RESPONSE_EX) NULL; + + prP2pGetSdRspEx = (P_PARAM_P2P_GET_SD_RESPONSE_EX) pvQueryBuffer; + pucPacketContent = prP2pGetSdRspEx->aucPacketContent; + pucTA = &prP2pGetSdRspEx->rTransmitterAddr; + pu2PacketLength = &prP2pGetSdRspEx->u2PacketLength; + ucSeqNum = prP2pGetSdRspEx->ucSeqNum; + } + +/* rWlanStatus = p2pFuncGetServiceDiscoveryFrame(prAdapter, */ +/* pucPacketContent, */ +/* (u4QueryBufferLen - sizeof(PARAM_P2P_GET_SD_RESPONSE)), */ +/* (PUINT_32)pu2PacketLength, */ +/* NULL, */ +/* ucSeqNum); */ +#else + *pu4QueryInfoLen = 0; + return rWlanStatus; +#endif +#if 0 + 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; +#endif +} /* 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, + P2P_DEV_BSS_INDEX, + FALSE, + TRUE, + TRUE, + NULL, + nicOidCmdTimeoutCommon, + u4SetBufferLen, (PUINT_8) pvSetBuffer, pvSetBuffer, u4SetBufferLen); + +} /* end of wlanoidSetSecCheckRequest() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidGetSecCheckResponse(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + /* P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T)NULL; */ + P_GLUE_INFO_T prGlueInfo; + + prGlueInfo = prAdapter->prGlueInfo; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen > 256) + u4QueryBufferLen = 256; + + *pu4QueryInfoLen = u4QueryBufferLen; + +#if DBG + DBGLOG_MEM8(SEC, LOUD, prGlueInfo->prP2PInfo->aucSecCheckRsp, u4QueryBufferLen); +#endif + kalMemCopy((PUINT_8) (pvQueryBuffer + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer)), + prGlueInfo->prP2PInfo->aucSecCheckRsp, u4QueryBufferLen); + + return rWlanStatus; +} /* end of wlanoidGetSecCheckResponse() */ +#endif + +WLAN_STATUS +wlanoidSetNoaParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T prNoaParam; + CMD_CUSTOM_NOA_PARAM_STRUCT_T rCmdNoaParam; + + DEBUGFUNC("wlanoidSetNoaParam"); + DBGLOG(INIT, TRACE, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_NOA_PARAM_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_NOA_PARAM_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prNoaParam = (P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T) pvSetBuffer; + + kalMemZero(&rCmdNoaParam, sizeof(CMD_CUSTOM_NOA_PARAM_STRUCT_T)); + rCmdNoaParam.u4NoaDurationMs = prNoaParam->u4NoaDurationMs; + rCmdNoaParam.u4NoaIntervalMs = prNoaParam->u4NoaIntervalMs; + rCmdNoaParam.u4NoaCount = prNoaParam->u4NoaCount; + +#if 0 + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_NOA_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_NOA_PARAM_STRUCT_T), + (PUINT_8) &rCmdNoaParam, pvSetBuffer, u4SetBufferLen); +#else + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_NOA_PARAM, + prNoaParam->ucBssIdx, + TRUE, + FALSE, + TRUE, + NULL, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_NOA_PARAM_STRUCT_T), + (PUINT_8) &rCmdNoaParam, pvSetBuffer, u4SetBufferLen); + +#endif + +} + +WLAN_STATUS +wlanoidSetOppPsParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T prOppPsParam; + CMD_CUSTOM_OPPPS_PARAM_STRUCT_T rCmdOppPsParam; + + DEBUGFUNC("wlanoidSetOppPsParam"); + DBGLOG(INIT, TRACE, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prOppPsParam = (P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T) pvSetBuffer; + + kalMemZero(&rCmdOppPsParam, sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T)); + rCmdOppPsParam.u4CTwindowMs = prOppPsParam->u4CTwindowMs; + +#if 0 + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_OPPPS_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T), + (PUINT_8) &rCmdOppPsParam, pvSetBuffer, u4SetBufferLen); +#else + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_NOA_PARAM, + prOppPsParam->ucBssIdx, + TRUE, + FALSE, + TRUE, + NULL, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T), + (PUINT_8) &rCmdOppPsParam, pvSetBuffer, u4SetBufferLen); + +#endif + +} + +WLAN_STATUS +wlanoidSetUApsdParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T prUapsdParam; + CMD_CUSTOM_UAPSD_PARAM_STRUCT_T rCmdUapsdParam; + P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo; + P_BSS_INFO_T prBssInfo; + + DEBUGFUNC("wlanoidSetUApsdParam"); + DBGLOG(INIT, TRACE, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prUapsdParam = (P_PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T) pvSetBuffer; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prUapsdParam->ucBssIdx); + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + + kalMemZero(&rCmdUapsdParam, sizeof(CMD_CUSTOM_UAPSD_PARAM_STRUCT_T)); + rCmdUapsdParam.fgEnAPSD = 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 wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_UAPSD_PARAM, + prBssInfo->ucBssIndex, + TRUE, + FALSE, + TRUE, + NULL, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_UAPSD_PARAM_STRUCT_T), + (PUINT_8) &rCmdUapsdParam, pvSetBuffer, u4SetBufferLen); +} + +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 */ + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to set the WPS mode. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2pWPSmode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS status; + UINT_32 u4IsWPSmode = 0; + + DEBUGFUNC("wlanoidSetP2pWPSmode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (pvSetBuffer) + u4IsWPSmode = *(PUINT_32) pvSetBuffer; + else + u4IsWPSmode = 0; + + if (u4IsWPSmode) + prAdapter->rWifiVar.prP2PConnSettings->fgIsWPSMode = 1; + else + prAdapter->rWifiVar.prP2PConnSettings->fgIsWPSMode = 0; + + status = nicUpdateBss(prAdapter, P2P_DEV_BSS_INDEX); + + return status; +} /* end of wlanoidSetP2pWPSmode() */ + +#endif + +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/misc/mediatek/connectivity/wlan/core/gen3/lint/co.lnt b/drivers/misc/mediatek/connectivity/wlan/core/gen3/lint/co.lnt new file mode 100644 index 0000000000000..b3f0f527b3ce2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/lint/co.lnt @@ -0,0 +1,32 @@ +// co.lnt +// Compiler Options for Generic C compiler + +// This file contains options to allow PC-lint to process source +// files for your compiler. It is used as follows: +// +// lint co.lnt source-file(s) +// + + // while processing compiler (library) header files ... +-wlib(1) // sets the warning level within library headers to 1 + // (no warnings, just syntax errors). Comment out if you + // are actually linting library headers. This + // option makes obsolete options of the form -elib(axxx) where + // xxx >= 400 which may be retained for historical reasons. +-elib(652) // suppress message about #define of earlier declared symbols +-elib(762) // suppress message about multiple identical declarations and +-elib(760) // suppress message about multiple identical macro defs +-elib(553) // undefined pre-processor variables are regarded as + // 0 without complaint + +// The following functions exhibit variable return modes. +// That is, they may equally-usefully be called for a value +// as called just for their effects. Accordingly we inhibit +// Warning 534 for these functions. +// Feel free to add to or subtract from this list. + +-esym(534,close,creat,fclose,fprintf,fputc) +-esym(534,fputs,fscanf,fseek,fwrite,lseek,memcpy,memmove,memset) +-esym(534,printf,puts,scanf,sprintf,sscanf,strcat,strcpy) +-esym(534,strncat,strncpy,unlink,write) + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/lint/mt6620.lnt b/drivers/misc/mediatek/connectivity/wlan/core/gen3/lint/mt6620.lnt new file mode 100644 index 0000000000000..3b5c2190dddf5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/lint/mt6620.lnt @@ -0,0 +1,87 @@ +// Please note -- this is the set of error/warning suppression options +// for MT6620 driver. + +// Microsoft C/C++, Versions 4.0 - 12.0(VC6) +-cmsc + +//=========================================================================== +// Define include path of MT6620 headers +// Currently we'll use windows' gl_os.h +// +-i".\include" +-i".\include\nic" +-i".\os" +-i".\os\windows\include" +-i".\os\windows\ce\hif\sdio\include" + +//=========================================================================== +// NOTE(Kevin): we need to define following compiling flags to avoid +// Warning 553: Undefined preprocessor variable. +// +-dDBG=1 +-dMT6620 + +//=========================================================================== +// Integer-model-for-Enum flag (default OFF). +// Warning 641: Converting enum 'ENUM_INT_EVENT_T' to int +// for (u4IntIdx = 0; u4IntIdx < INT_EVENT_NUM; u4IntIdx++) ++fie + +//=========================================================================== +// dump.c +// Warning 661: Possible access of out-of-bounds pointer +// Warning 662: Possible creation of out-of-bounds pointer +-efunc(613,dumpMemory8) +-efunc(661,dumpMemory8) +-efunc(662,dumpMemory8) +-efunc(613,dumpMemory32) +-efunc(661,dumpMemory32) +-efunc(662,dumpMemory32) + + +//Warning 507: Size incompatibility - (UINT_8)NULL +-emacro(507,NULL) + +// debug.h +//Warning 506: Constant value Boolean +-emacro(506,DBGLOG) +-emacro(774,DBGLOG) + +// ASSERT(0) +-emacro(506,ASSERT) +-emacro(774,ASSERT) + +// Ignore WARN 621 Likeness between Symbols - identifier clash +-e621 + +// Ignore INFO 793 ANSI limit of 1024 'macros in module' exceeded +// Ignore INFO 793 ANSI limit of 6 'external identifiers +-e793 + +// Ignore NOTE 950 Non-ANSI reserved word or construct: '//' +-e950 + +-emacro(534, HAL_MCR_RD) +-emacro(534, HAL_MCR_WR) +-emacro(534, HAL_PORT_RD) +-emacro(534, HAL_PORT_WR) + +//Ignore fgIsTransition not used warning, actuall used at macro +-e550 + +//Kevin: Ignore Warning 534: Ignoring return value of function +-e534 + +//Kevin: Ignore Warning 526: Symbol 'kal*()' not defined +-e526 + +//Kevin: Ignore Warning 506: Constant value Boolean [MTK Rule 6.1.3] +// MTK Rule 6.1.3 metion that we shouldn't write code like that - if (fgXxx == TRUE) +// However Warning 506 cannot check that, it only can check while(0), while(1), if (1) ... cases +-e506 + +//Kevin: Ignore Warning 613, the null pointer should be check by every handler. +-efunc(613, wlanSetInformation, wlanQueryInformation) + +-efunc(415,wlanoidQueryCapability) +-efunc(416,wlanoidQueryCapability) diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/lint/mtk-sup.lnt b/drivers/misc/mediatek/connectivity/wlan/core/gen3/lint/mtk-sup.lnt new file mode 100644 index 0000000000000..f1697e02f6e42 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/lint/mtk-sup.lnt @@ -0,0 +1,27 @@ +// Please note -- this is a representative set of error suppression +// options. Please adjust to suit your own policies +// See manual (chapter LIVING WITH LINT) +// for further details. + + +// MISRA Required Rules +// +-e46 // Bit field type should be 'int' +-e801 // Use of goto is deprecated +-e912 // Implicit binary conversion from 'type' to 'type' +-e917 // Prototype coercion 'type' to 'type' +-e920 // Cast from 'type' to void +-e923 // Cast from a non-pointer to a pointer or vice versa +-e971 // Use of 'char' without 'signed' or 'unsigned' +-esym(960,54) // Null statement not in line by itself +-esym(960,57) // 'continue' statement detected +-esym(960,58) // 'break' used outside of a 'switch' +-esym(960,69) // Function has variable number of arguments +-esym(960,110) // Bitfields inside union +-esym(961,44) // Redundant explicit casting +-esym(961,60) // No 'else' at end of 'if ... else if' chain +-"esym(793,identifiers in one block)" + // ANSI limit of 511 'identifiers in one block' + // exceeded + + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/lint/mtk.lnt b/drivers/misc/mediatek/connectivity/wlan/core/gen3/lint/mtk.lnt new file mode 100644 index 0000000000000..e0adf70ef362a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/lint/mtk.lnt @@ -0,0 +1,169 @@ +// Standard lint options in MTK + +// MTK Log Format +// -hsb_3 // formatting options required for MicroVision IDE +// -format="*** LINT: %(%f(%l) %)%t %n: %m" +// -width(0,10) // Don't break lines + +// MTK requirements +-t4 /* TAB=4 */ +-A /* strict ANSI */ +// -w2 /* Show Error and Warning only */ + +// MTK Coding Standards +-append(537,[MTK Rule 2.1.3]) // Repeated include file + ++e725 // Expected positive indentation from ... +-append(525,[MTK Rule 2.2.3]) // Negative indentation from ... +-append(539,[MTK Rule 2.2.3]) // Did not expect positive indentation from ... +-append(725,[MTK Rule 2.2.3]) + ++e960 // Violates MISRA Required Rule ++e961 // Violates MISRA Advisory Rule +-append(960(42),[MTK Rule 2.2.6]) // Comma operator used outside of 'for' + ++e721 // Suspicious use of ';' ++e722 // Suspicious use of ';' +-append(721,[MTK Rule 2.2.8]) +-append(722,[MTK Rule 2.2.8]) +-append(960(59),[MTK Rule 2.2.8]) // Left brace expected for if, else, for, do and while + ++e783 // Line does not end with new-line +-append(783,[MTK Rule 2.2.11]) + + +// 5.1.1 Always declare an explicit function return type +-fvr /* varying return mode not allowed */ ++e745 // Function has no explicit type +-append(745,[MTK Rule 5.1.1]) + +// 5.1.2 Always provide formal parameter names in function declaraions ++e718 // Symbol undeclared ++e936 // Old-style function definition ++e937 // Old-style function declaration ++e938 // Parameter not explicitly declared ++e957 // Function defined without a prototype in scope +-append(628,[MTK Rule 5.1.2]) // No argument information provided for function +-append(718,[MTK Rule 5.1.2]) +-append(936,[MTK Rule 5.1.2]) +-append(937,[MTK Rule 5.1.2]) +-append(938,[MTK Rule 5.1.2]) +-append(957,[MTK Rule 5.1.2]) + +-append(18,[MTK Rule 5.1.5]) /* symbol redeclared */ +-append(516,[MTK Rule 5.1.5]) // Symbol has arg. type conflict +-append(532,[MTK Rule 5.1.5]) // Return mode of function inconsistent with ... +-append(578,[MTK Rule 5.1.5]) // Declaration of symbol x hides symbol (location) +-append(580,[MTK Rule 5.1.5]) // Redeclaration of function causes loss of prototype +-append(652,[MTK Rule 5.1.5]) // #define of symbol declared previously at ... + +-append(674,[MTK Rule 5.1.6]) // Returning address of auto variable + ++e970 // Use of modifier or type outside of a typedef ++e971 // Use of 'char' without 'signed' or 'unsigned' +-append(970,[MTK Rule 5.2.1]) +-append(971,[MTK Rule 5.2.1]) + ++e834 // Operator 'x' followed by operator 'y' is confusing. + // Use parentheses +-append(834,[MTK Rule 6.1.1]) + ++e731 // Boolean argument to equal/not euqal +-append(506,[MTK Rule 6.1.3]) // Constant value Boolean +-append(731,[MTK Rule 6.1.3]) + ++e773 // Expression-like macro not parenthesized +-append(773,[MTK Rule 6.1.4]) + ++e744 // Switch has no default +-append(744,[MTK Rule 6.2.2]) +-append(960(60),[MTK Rule 6.2.2]) // No 'else' at end of 'is else if' chain +-append(961(60),[MTK Rule 6.2.2]) + ++e801 // Use of goto is deprecated +-append(801,[MTK Rule 6.2.3]) + +-append(960(58),[MTK Rule 6.2.4]) // 'break' used outside of a 'switch' + +// 6.2.5 Avoid variables used before being explicity initialized ++e727 // Static or global variable not explicitly initialized ++e728 ++e729 ++e771 /* Symbol conceivably not initialized */ ++e772 +-append(530,[MTK Rule 6.2.5]) // Local vairable not initialized +-append(603,[MTK Rule 6.2.5]) +-append(644,[MTK Rule 6.2.5]) // Variable may not been initialized +-append(645,[MTK Rule 6.2.5]) +-append(727,[MTK Rule 6.2.5]) +-append(728,[MTK Rule 6.2.5]) +-append(729,[MTK Rule 6.2.5]) +-append(771,[MTK Rule 6.2.5]) +-append(772,[MTK Rule 6.2.5]) + ++e794 // Conceivable use of null pointer +-append(413,[MTK Rule 7.1.1]) // Likely use of null pointer +-append(613,[MTK Rule 7.1.1]) // Possible use of null pointer +-append(794,[MTK Rule 7.1.1]) + +-append(415,[MTK Rule 8.2.3]) // Access of out-of-bounds pointer + +-append(564,[MTK Rule 8.2.5]) // Variable depends on order of evaluation +-append(961(47),[MTK Rule 8.2.5]) // Dependence placed on C's operator precedence + ++e713 // Loss of precision without casting ++e732 // Loss of sign without casting ++e737 // Loss of sign in promotion ++e912 // Implicit binary conversion +-append(570,[MTK Rule 8.2.6]) // Loss of sign +-append(713,[MTK Rule 8.2.6]) +-append(732,[MTK Rule 8.2.6]) +-append(737,[MTK Rule 8.2.6]) +-append(912,[MTK Rule 8.2.6]) + ++e701 // Shift left of signed quantity ++e702 // Shift right of signed quantity +-append(701,[MTK Rule 8.2.7]) +-append(702,[MTK Rule 8.2.7]) + ++e712 // Loss of precision ++e747 // Significant prototype coercion ++e912 // Implicit binary conversion ++e917 // Prototype coercion ++e918 // Prototype coercion of pointers ++e920 // Cast from Type to void +-append(712,[MTK Rule 8.3.1]) +-append(747,[MTK Rule 8.3.1]) +-append(912,[MTK Rule 8.3.1]) +-append(917,[MTK Rule 8.3.1]) +-append(918,[MTK Rule 8.3.1]) +-append(920,[MTK Rule 8.3.1]) + ++e740 // Unusual pointer cast (incompatible indirect types) +-append(740,[MTK Rule 8.3.2]) + ++e793 // ANSI limit of 'xxx' exceeded ++e950 // Non-ANSI reserved word or constrcut +-append(793,[MTK Rule 10.1.1]) +-append(950,[MTK Rule 10.1.1]) + + +// Check MISRA's rules +.\lnt\au-misra.lnt + +// Message suppression (un-used errors or warnings) +-e14 // Symbol previously defined + +// JL Added Message suppression (un-used errors or warnings) +-e714 // Symbol not referenced +-e716 // while (1) ... +-e734 // Loss of precision +-e746 // Call to function not made in the presence of a prototype +-e749 -e?75? -e?76? // Constructs not reference +-e778 // Constant expression evaluates to 0 +-e827 // Loop not reachable +-esym( 960, 33, 68 ) // Side effect on right hand side of logical operator + // Function not declared in file scope +-esym( 961, 18, 55 ) // Constant requires numerical suffix + // Non-case lable + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/lint/options.lnt b/drivers/misc/mediatek/connectivity/wlan/core/gen3/lint/options.lnt new file mode 100644 index 0000000000000..dcf0f439a8afd --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/lint/options.lnt @@ -0,0 +1,84 @@ +// Please note -- this is a representative set of error suppression +// options. Please adjust to suit your own policies +// See manual (chapter LIVING WITH LINT) +// for further details. + +//=========================================================================== +// Library control +// + +-wlib(0) // Inhibit all library messages except syntactic + // errors. + ++libclass(angle,ansi) // Treat all headers specified with angle brackets + // and standard ANSI headers as library files + ++libh(nucleus.h,*x_os.h) // Ignore nucleus.h and x_os.h + +//=========================================================================== +// General attributes +// + +-epn // Inhibit messages that pointer types differ + // nominally. + ++fll // Enable type 'long long' + ++fdi // Search #include files in the directory of + // source file, rather than in current directory. + ++fpn // All pointer parameters are assumed to be + // possibly NULL. + ++fem // Early modifiers (__packed, etc.) + +-d__arm // Define __arm + +-d__FUNCTION__="function" // Non-standard preprocessor macro + +//=========================================================================== +// General message inhibitions +// + +-e537 // Repeated include file +-e730 // Boolean argument to function +-e788 // enum constant not used within defaulted switch + +//=========================================================================== +// Specific function inhibitions +// + +// Ignoring return value of function +-esym(534, Printf, SPrintf) +-esym(534, x_memcpy, x_memcmp, x_memmove, x_memset) + +// Function takes printf-like format +-printf(1, Printf) +-printf(2, SPrintf) + +// ASSERT specific ++dASSERT=__assert // lock in the define of ASSERT to be the builtin function +-esym(1055,__assert) // the built-in is undeclared +-esym(526,__assert) // and not defined either. +-esym(516,__assert) // arguments may vary. +-esym(534,__assert) // the return value is ignored +-esym(628,__assert) // and no argument information given +-esym(746,__assert) // and no formal prototype provided +-esym(718,__assert) // Symbol undeclared + // otherwise __assert() is an 'ideal' assert function. + +//=========================================================================== +// Special keyword ignorance + +// Add reserved word: __irq ++rw(__irq, __packed) +-rw(__align) + +// Ignore __global_reg(x), used in nucleus.h +-rw_asgn(__global_reg, _to_eol) + +// Ignore __align(x), used in global variable declaration alignment +-rw_asgn(__align, _to_brackets) + +// Ignore embedded inline assembly functions +-rw_asgn(__asm, _to_brackets) diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/lint/std.lnt b/drivers/misc/mediatek/connectivity/wlan/core/gen3/lint/std.lnt new file mode 100644 index 0000000000000..ad1e84116824a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/lint/std.lnt @@ -0,0 +1,12 @@ +// Generic Compilers, -si4 -sp4, +// Standard lint options + +// Set sizes of data types +-ss2 -si4 -sl4 -sp4 + +// Include options +co.lnt +mtk.lnt +mtk-sup.lnt +options.lnt +mt6620.lnt diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/cmd_buf.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/cmd_buf.c new file mode 100644 index 0000000000000..1c70b6c84f9d0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/cmd_buf.c @@ -0,0 +1,275 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/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. + */ + +/******************************************************************************* +* C O M P I L E 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 +******************************************************************************** +*/ +BOOLEAN fgCmdDumpIsDone = FALSE; +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to initial the MGMT memory pool for CMD Packet. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cmdBufInitialize(IN P_ADAPTER_T prAdapter) +{ + P_CMD_INFO_T prCmdInfo; + UINT_32 i; + + ASSERT(prAdapter); + + QUEUE_INITIALIZE(&prAdapter->rFreeCmdList); + + for (i = 0; i < CFG_TX_MAX_CMD_PKT_NUM; i++) { + prCmdInfo = &prAdapter->arHifCmdDesc[i]; + QUEUE_INSERT_TAIL(&prAdapter->rFreeCmdList, &prCmdInfo->rQueEntry); + } + fgCmdDumpIsDone = FALSE; +} /* end of cmdBufInitialize() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief dump CMD queue and print to trace, for debug use only +* @param[in] prQueue Pointer to the command Queue to be dumped +* @param[in] quename Name of the queue +*/ +/*----------------------------------------------------------------------------*/ +VOID cmdBufDumpCmdQueue(P_QUE_T prQueue, CHAR *queName) +{ + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T)QUEUE_GET_HEAD(prQueue); + + DBGLOG(NIC, INFO, "Dump CMD info for %s, Elem number:%u\n", queName, prQueue->u4NumElem); + while (prCmdInfo) { + P_CMD_INFO_T prCmdInfo1, prCmdInfo2, prCmdInfo3; + + prCmdInfo1 = (P_CMD_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prCmdInfo); + if (!prCmdInfo1) { + DBGLOG(NIC, INFO, "CID:%d SEQ:%d\n", prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + break; + } + prCmdInfo2 = (P_CMD_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prCmdInfo1); + if (!prCmdInfo2) { + DBGLOG(NIC, INFO, "CID:%d, SEQ:%d; CID:%d, SEQ:%d\n", prCmdInfo->ucCID, + prCmdInfo->ucCmdSeqNum, prCmdInfo1->ucCID, prCmdInfo1->ucCmdSeqNum); + break; + } + prCmdInfo3 = (P_CMD_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prCmdInfo2); + if (!prCmdInfo3) { + DBGLOG(NIC, INFO, "CID:%d, SEQ:%d; CID:%d, SEQ:%d; CID:%d, SEQ:%d\n", prCmdInfo->ucCID, + prCmdInfo->ucCmdSeqNum, prCmdInfo1->ucCID, prCmdInfo1->ucCmdSeqNum, + prCmdInfo2->ucCID, prCmdInfo2->ucCmdSeqNum); + break; + } + DBGLOG(NIC, INFO, "CID:%d, SEQ:%d; CID:%d, SEQ:%d; CID:%d, SEQ:%d; CID:%d, SEQ:%d\n", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum, prCmdInfo1->ucCID, + prCmdInfo1->ucCmdSeqNum, prCmdInfo2->ucCID, prCmdInfo2->ucCmdSeqNum, + prCmdInfo3->ucCID, prCmdInfo3->ucCmdSeqNum); + prCmdInfo = (P_CMD_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prCmdInfo3); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Allocate CMD_INFO_T from a free list and MGMT memory pool. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] u4Length Length of the frame buffer to allocate. +* +* @retval NULL Pointer to the valid CMD Packet handler +* @retval !NULL Fail to allocat CMD Packet +*/ +/*----------------------------------------------------------------------------*/ +#if CFG_DBG_MGT_BUF +P_CMD_INFO_T cmdBufAllocateCmdInfoX(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Length, PUINT_8 fileAndLine) +#else +P_CMD_INFO_T cmdBufAllocateCmdInfo(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Length) +#endif +{ + 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 */ + prCmdInfo->u2InfoBufLen = 0; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + + if (u4Length) { + /* Start address of allocated memory */ +#if CFG_DBG_MGT_BUF + prCmdInfo->pucInfoBuffer = cnmMemAllocX(prAdapter, RAM_TYPE_BUF, u4Length, fileAndLine); +#else + prCmdInfo->pucInfoBuffer = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4Length); +#endif + + 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->pucInfoBuffer = NULL; + } + fgCmdDumpIsDone = FALSE; + } else if (!fgCmdDumpIsDone) { + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + P_QUE_T prCmdQue = &prGlueInfo->rCmdQueue; + P_QUE_T prPendingCmdQue = &prAdapter->rPendingCmdQueue; + P_QUE_T prCmdTxQue = &prAdapter->rTxCmdQueue; + P_TX_TCQ_STATUS_T prTc = &prAdapter->rTxCtrl.rTc; + + fgCmdDumpIsDone = TRUE; + cmdBufDumpCmdQueue(prCmdQue, "waiting Tx CMD queue"); + cmdBufDumpCmdQueue(prPendingCmdQue, "waiting response CMD queue"); + cmdBufDumpCmdQueue(prCmdTxQue, "waiting Txing to hif queue"); + if (prCmdQue->u4NumElem + prPendingCmdQue->u4NumElem + + prCmdTxQue->u4NumElem + prAdapter->rFreeCmdList.u4NumElem < CFG_TX_MAX_CMD_PKT_NUM) { + UINT_8 i = 0; + P_CMD_INFO_T prCmd = &prAdapter->arHifCmdDesc[0]; + + DBGLOG(NIC, INFO, "There maybe some cmd info were leaked, free %u\n", + prAdapter->rFreeCmdList.u4NumElem); + for (i = 0; i <= CFG_TX_MAX_CMD_PKT_NUM - 4; i += 4) { + DBGLOG(NIC, INFO, + "ID:%d, N:%p, S:%p; ID:%d, N:%p, S:%p; ID:%d, N:%p, S:%p; ID:%d, N:%p, S:%p\n", + prCmd[i].ucCID, prCmd[i].rQueEntry.prNext, &prCmd[i], + prCmd[i + 1].ucCID, prCmd[i + 1].rQueEntry.prNext, &prCmd[i + 1], + prCmd[i + 2].ucCID, prCmd[i + 2].rQueEntry.prNext, &prCmd[i + 2], + prCmd[i + 3].ucCID, prCmd[i + 3].rQueEntry.prNext, &prCmd[i + 3]); + } + } + DBGLOG(NIC, INFO, "Tc4 number:%d\n", prTc->au2FreeBufferCount[TC4_INDEX]); + /* glResetTrigger(prAdapter); */ + } + + if (prCmdInfo) { + DBGLOG(MEM, LOUD, "CMD[0x%p] allocated! LEN[%04u], Rest[%u]\n", + prCmdInfo, u4Length, prAdapter->rFreeCmdList.u4NumElem); + } else { + DBGLOG(MEM, ERROR, "CMD allocation failed! LEN[%04u], Rest[%u]\n", + u4Length, prAdapter->rFreeCmdList.u4NumElem); + } + + 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); + + 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); + } + + if (prCmdInfo) + DBGLOG(MEM, LOUD, "CMD[0x%p] freed! Rest[%u]\n", prCmdInfo, prAdapter->rFreeCmdList.u4NumElem); + +} /* end of cmdBufFreeCmdPacket() */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/makefile b/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/makefile new file mode 100644 index 0000000000000..89b63909cac98 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/makefile @@ -0,0 +1,8 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the driver components of the Windows NT DDK +#!INCLUDE $(NTMAKEENV)\makefile.def + +#!INCLUDE $(_MAKEENVROOT)\makefile.def +!INCLUDE $(_WINDOW_MAKE_ROOT)\makefile.def diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/nic.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/nic.c new file mode 100644 index 0000000000000..782ba2bc74205 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/nic.c @@ -0,0 +1,4128 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic.c#4 + */ + +/* + * ! \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. + */ + +/******************************************************************************* +* C O M P I L E 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 defined(MT6631) +#include "sdio.h" +#endif + + +/******************************************************************************* +* 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 */ + PHY_TYPE_SET_802_11AC, + PHY_TYPE_SET_802_11ANAC, + PHY_TYPE_SET_802_11ABGNAC +}; + +const ECO_INFO_T g_arEcoVersionTable[] = { + /* HW version, ROM version, Factory version */ + {0x00, 0x00, 0xA}, /* E1 */ + {0x10, 0x10, 0xA}, /* E2 */ + {0x11, 0x11, 0xA}, /* E3 */ + {0x12, 0x11, 0xA} +}; + +/******************************************************************************* +* 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(MEM, TRACE, "Allocating %u bytes for %s.\n", u4Size, pucComment); \ + pucMem = (PUINT_8)kalMemAlloc(u4Size, eMemType); \ + if (pucMem == (PUINT_8)NULL) { \ + DBGLOG(MEM, ERROR, "Could not allocate %u bytes for %s.\n", u4Size, pucComment); \ + break; \ + } \ + ASSERT(((ULONG)pucMem % 4) == 0); \ + DBGLOG(MEM, LOUD, "Virtual Address = %p for %s.\n", pucMem, pucComment); \ + } + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @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, PHY_MEM_TYPE, "COMMON MGMT MEMORY POOL"); + + /* 4 <2> Memory for RX Descriptor */ + /* Initialize the number of rx buffers we will have in our queue. */ + /* We may setup ucRxPacketDescriptors by GLUE Layer, and using + * this variable directly. + */ + /* Allocate memory for the SW receive structures. */ + prRxCtrl->u4RxCachedSize = CFG_RX_MAX_PKT_NUM * ALIGN_4(sizeof(SW_RFB_T)); + + LOCAL_NIC_ALLOCATE_MEMORY(prRxCtrl->pucRxCached, prRxCtrl->u4RxCachedSize, VIR_MEM_TYPE, "SW_RFB_T"); + + /* 4 <3> Memory for TX DEscriptor */ + prTxCtrl->u4TxCachedSize = CFG_TX_MAX_PKT_NUM * ALIGN_4(sizeof(MSDU_INFO_T)); + + LOCAL_NIC_ALLOCATE_MEMORY(prTxCtrl->pucTxCached, prTxCtrl->u4TxCachedSize, VIR_MEM_TYPE, "MSDU_INFO_T"); + + /* 4 <4> Memory for Common Coalescing Buffer */ +#if CFG_COALESCING_BUFFER_SIZE || CFG_SDIO_RX_AGG + prAdapter->pucCoalescingBufCached = (PUINT_8) NULL; + + /* Allocate memory for the common coalescing buffer. */ + prAdapter->u4CoalescingBufCachedSize = + CFG_COALESCING_BUFFER_SIZE > + CFG_RX_COALESCING_BUFFER_SIZE ? CFG_COALESCING_BUFFER_SIZE : CFG_RX_COALESCING_BUFFER_SIZE; + + prAdapter->pucCoalescingBufCached = kalAllocateIOBuffer(prAdapter->u4CoalescingBufCachedSize); + + if (prAdapter->pucCoalescingBufCached == NULL) { + DBGLOG(NIC, ERROR, + "Could not allocate %u bytes for coalescing buffer.\n", + prAdapter->u4CoalescingBufCachedSize); + break; + } +#endif /* CFG_COALESCING_BUFFER_SIZE */ + + /* 4 <5> Memory for enhanced interrupt response */ + prAdapter->prSDIOCtrl = (P_SDIO_CTRL_T) + kalAllocateIOBuffer(sizeof(ENHANCE_MODE_DATA_STRUCT_T)); + + if (prAdapter->prSDIOCtrl == NULL) { + DBGLOG(NIC, ERROR, + "Could not allocate %zu bytes for interrupt response.\n", + sizeof(ENHANCE_MODE_DATA_STRUCT_T)); + break; + } + +#if CFG_DBG_MGT_BUF + LINK_INITIALIZE(&prAdapter->rMemTrackLink); +#endif + 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, PHY_MEM_TYPE, prAdapter->u4MgtBufCachedSize); + prAdapter->pucMgtBufCached = (PUINT_8) NULL; + } +#if CFG_DBG_MGT_BUF + do { + BOOLEAN fgUnfreedMem = FALSE; + P_BUF_INFO_T prBufInfo; + + /* Dynamic allocated memory from OS */ + if (prAdapter->u4MemFreeDynamicCount != prAdapter->u4MemAllocDynamicCount) + fgUnfreedMem = TRUE; + + /* MSG buffer */ + prBufInfo = &prAdapter->rMsgBufInfo; + if (prBufInfo->u4AllocCount != (prBufInfo->u4FreeCount + prBufInfo->u4AllocNullCount)) + fgUnfreedMem = TRUE; + + /* MGT buffer */ + prBufInfo = &prAdapter->rMgtBufInfo; + if (prBufInfo->u4AllocCount != (prBufInfo->u4FreeCount + prBufInfo->u4AllocNullCount)) + fgUnfreedMem = TRUE; + + /* Check if all allocated memories are free */ + if (fgUnfreedMem) { + DBGLOG(MEM, ERROR, "Unequal memory alloc/free count!\n"); + + qmDumpQueueStatus(prAdapter); + cnmDumpMemoryStatus(prAdapter); + } + + if (!wlanIsChipNoAck(prAdapter)) { + /* Skip this ASSERT if chip is no ACK */ +#if CFG_DBG_MGT_BUF + if (prAdapter->u4MemFreeDynamicCount != prAdapter->u4MemAllocDynamicCount) { + struct MEM_TRACK *prMemTrack = NULL; + + DBGLOG(MEM, ERROR, "----- Memory Leak -----\n"); + LINK_FOR_EACH_ENTRY(prMemTrack, &prAdapter->rMemTrackLink, rLinkEntry, + struct MEM_TRACK) { + DBGLOG(MEM, ERROR, "file:line %s, command id: %u, where: %u\n", + prMemTrack->pucFileAndLine, + prMemTrack->u2CmdIdAndWhere & 0x00FF, + (prMemTrack->u2CmdIdAndWhere & 0xFF00) >> 8); + } + } +#endif + } + } while (FALSE); +#endif + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief disable global interrupt +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicDisableInterrupt(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); +#if defined(MT6631) + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_INT_EN_CLR); +#else + HAL_BYTE_WR(prAdapter, MCR_WHLPCR, WHLPCR_INT_EN_CLR); +#endif + 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); +#if defined(MT6631) + __enable_irq(); +#endif + prAdapter->fgIsFwOwn = TRUE; + } + } + /* If INT was not enabled, enable it now */ + else if (!fgIsIntEnableCache) { +#if defined(MT6631) + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_INT_EN_SET); + __enable_irq(); +#else + HAL_BYTE_WR(prAdapter, MCR_WHLPCR, WHLPCR_INT_EN_SET); +#endif + } + +} /* end of nicEnableInterrupt() */ + +#if CFG_SDIO_INTR_ENHANCE +/*----------------------------------------------------------------------------*/ +/*! +* @brief For SDIO enhance mode, set the max rx len and tx status +* +* @param prAdapter a pointer to adapter private data structure. +* +* @return - none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicSDIOInit(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4Value = 0; + + ASSERT(prAdapter); + + /* 4 <1> Check STATUS Buffer is DW alignment. */ + ASSERT(IS_ALIGN_4((ULONG)&prAdapter->prSDIOCtrl->u4WHISR)); + + /* 4 <2> Setup STATUS count. */ + { + HAL_MCR_RD(prAdapter, MCR_WHCR, &u4Value); + + /* 4 <2.1> Setup the number of maximum RX length to be report */ + u4Value &= ~(WHCR_MAX_HIF_RX_LEN_NUM); + u4Value |= ((SDIO_MAXIMUM_RX_LEN_NUM << WHCR_OFFSET_MAX_HIF_RX_LEN_NUM)); + + /* 4 <2.2> Setup RX enhancement mode */ +#if CFG_SDIO_RX_ENHANCE + u4Value |= WHCR_RX_ENHANCE_MODE_EN; +#else + u4Value &= ~WHCR_RX_ENHANCE_MODE_EN; +#endif /* CFG_SDIO_RX_AGG */ + + HAL_MCR_WR(prAdapter, MCR_WHCR, u4Value); + } + + return; + +} /* end of nicSDIOInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read interrupt status from hardware +* +* @param prAdapter pointer to the Adapter handler +* @param the interrupts +* +* @return N/A +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicSDIOReadIntStatus(IN P_ADAPTER_T prAdapter, OUT PUINT_32 pu4IntStatus) +{ + P_SDIO_CTRL_T prSDIOCtrl; + + DEBUGFUNC("nicSDIOReadIntStatus"); + + ASSERT(prAdapter); + ASSERT(pu4IntStatus); + + prSDIOCtrl = prAdapter->prSDIOCtrl; + ASSERT(prSDIOCtrl); + + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + *pu4IntStatus = 0; + return; + } + + HAL_PORT_RD(prAdapter, + MCR_WHISR, + sizeof(ENHANCE_MODE_DATA_STRUCT_T), (PUINT_8) prSDIOCtrl, sizeof(ENHANCE_MODE_DATA_STRUCT_T)); + + /* workaround */ + if ((prSDIOCtrl->u4WHISR & WHISR_TX_DONE_INT) == 0 && (prSDIOCtrl->rTxInfo.au4WTSR[0] + | prSDIOCtrl->rTxInfo.au4WTSR[1] + | prSDIOCtrl->rTxInfo.au4WTSR[2] + | prSDIOCtrl->rTxInfo.au4WTSR[3] + | prSDIOCtrl->rTxInfo.au4WTSR[4] + | prSDIOCtrl->rTxInfo.au4WTSR[5] + | prSDIOCtrl->rTxInfo.au4WTSR[6] + | prSDIOCtrl->rTxInfo.au4WTSR[7])) { + prSDIOCtrl->u4WHISR |= WHISR_TX_DONE_INT; + } + + if ((prSDIOCtrl->u4WHISR & BIT(31)) == 0 && + HAL_GET_MAILBOX_READ_CLEAR(prAdapter) == TRUE && + (prSDIOCtrl->u4RcvMailbox0 != 0 || prSDIOCtrl->u4RcvMailbox1 != 0)) { + prSDIOCtrl->u4WHISR |= BIT(31); + } + + *pu4IntStatus = prSDIOCtrl->u4WHISR; + +} /* end of nicSDIOReadIntStatus() */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief The function used to read interrupt status and then invoking +* dispatching procedure for the appropriate functions +* corresponding to specific interrupt bits +* +* @param prAdapter pointer to the Adapter handler +* +* @retval WLAN_STATUS_SUCCESS +* @retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicProcessIST(IN P_ADAPTER_T prAdapter) +{ + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + UINT_32 u4IntStatus = 0; + UINT_32 i; + + 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; + } + + for (i = 0; i < prAdapter->rWifiVar.u4HifIstLoopCount; i++) { + +#if CFG_SDIO_INTR_ENHANCE + nicSDIOReadIntStatus(prAdapter, &u4IntStatus); +#else + HAL_MCR_RD(prAdapter, MCR_WHISR, &u4IntStatus); +#endif /* CFG_SDIO_INTR_ENHANCE */ + + /* DBGLOG(NIC, TRACE, ("u4IntStatus: 0x%x\n", u4IntStatus)); */ + + if (u4IntStatus & ~(WHIER_DEFAULT | WHIER_FW_OWN_BACK_INT_EN)) { + DBGLOG(INTR, WARN, "Un-handled HISR %#x, HISR = %#x (HIER:0x%x)\n", + (UINT_32)(u4IntStatus & ~WHIER_DEFAULT), u4IntStatus, (UINT_32)WHIER_DEFAULT); + u4IntStatus &= WHIER_DEFAULT; + } + + nicProcessIST_impl(prAdapter, u4IntStatus); + + if (u4IntStatus == 0) { + if (i == 0) + u4Status = WLAN_STATUS_NOT_INDICATING; + break; + } + } + + return u4Status; +} /* end of nicProcessIST() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief The function used to dispatch the appropriate functions for specific +* interrupt bits +* +* @param prAdapter pointer to the Adapter handler +* u4IntStatus interrupt status bits +* +* @retval WLAN_STATUS_SUCCESS +* @retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicProcessIST_impl(IN P_ADAPTER_T prAdapter, IN UINT_32 u4IntStatus) +{ + UINT_32 u4IntCount = 0; + P_INT_EVENT_MAP_T prIntEventMap = NULL; + + ASSERT(prAdapter); + + prAdapter->u4IntStatus = u4IntStatus; + + /* Process each of the interrupt status consequently */ + prIntEventMap = &arIntEventMapTable[0]; + for (u4IntCount = 0; u4IntCount < ucIntEventMapSize; prIntEventMap++, u4IntCount++) { + if (prIntEventMap->u4Int & prAdapter->u4IntStatus) { + if (prIntEventMap->u4Event == INT_EVENT_RX && prAdapter->fgIsEnterD3ReqIssued == TRUE) { + /* ignore */ + } else if (apfnEventFuncTable[prIntEventMap->u4Event] != NULL) { + apfnEventFuncTable[prIntEventMap->u4Event] (prAdapter); + } else { + DBGLOG(INTR, WARN, + "Empty INTR handler! ISAR bit#: %u, event:%u, func: %p\n", + prIntEventMap->u4Int, prIntEventMap->u4Event, + apfnEventFuncTable[prIntEventMap->u4Event]); + + ASSERT(0); /* to trap any NULL interrupt handler */ + } + prAdapter->u4IntStatus &= ~prIntEventMap->u4Int; + } + } + + return WLAN_STATUS_SUCCESS; +} /* end of nicProcessIST_impl() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Query HW code from HIFSYS CR and convert to SW used Chip ID +* +* @param prAdapter a pointer to adapter private data structure. +* +* @return Chip ID in hex format +*/ +/*----------------------------------------------------------------------------*/ +UINT_16 nicGetChipID(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + if (prAdapter->fgIsReadRevID == FALSE) { + + HAL_GET_CHIP_ID_VER(prAdapter, &prAdapter->u2ChipID, &prAdapter->ucRevID); + + /* Convert HW code to SW used Chip ID */ + switch (prAdapter->u2ChipID) { + case 0x0279: + prAdapter->u2ChipID = 0x6797; + break; + case 0x0507: + prAdapter->u2ChipID = 0x6759; + break; + case 0x0688: + prAdapter->u2ChipID = 0x6758; + break; + case 0x0713: + prAdapter->u2ChipID = 0x6775; + break; + case 0x0788: + prAdapter->u2ChipID = 0x6771; + break; + default: + DBGLOG(NIC, INFO, "Using original chip id 0x%04x\n", + prAdapter->u2ChipID); + break; + } + + prAdapter->fgIsReadRevID = TRUE; + } + + return prAdapter->u2ChipID; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Verify the Chip ID (HW code) from HIFSYS CR +* +* @param prAdapter a pointer to adapter private data structure. +* +* +* @retval TRUE HW code is the same as the setting compiled +* @retval FALSE HW code is different from the setting compiled +*/ +/*----------------------------------------------------------------------------*/ +BOOL nicVerifyChipID(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4CIR = 0; + UINT_32 u4HwCode = MTK_CHIP_REV; + + ASSERT(prAdapter); + ASSERT(prAdapter->prGlueInfo); + + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4CIR); + +#if defined(MT6631) +#ifdef CONFIG_OF + if (prAdapter->prGlueInfo->rHifInfo.Dev) { + if (of_property_read_u32_index(prAdapter->prGlueInfo->rHifInfo.Dev->of_node, + "hardware-values", 0, &u4HwCode)) + DBGLOG(NIC, ERROR, "Failed to get hardware-values from DT! skip verify chip id\n"); + else + if ((u4CIR & WCIR_CHIP_ID) != u4HwCode) { + DBGLOG(NIC, ERROR, "HW code mismatch from chip[%04x] and DT[%04x]\n", + (UINT_16)(u4CIR & WCIR_CHIP_ID), (UINT_16)u4HwCode); + return FALSE; + } + } +#endif +#else + if ((u4CIR & WCIR_CHIP_ID) != u4HwCode) { + DBGLOG(NIC, ERROR, "HW code mismatch from chip[%04x] and pre-defined[%04x]\n", + u4CIR & WCIR_CHIP_ID, u4HwCode); + return FALSE; + } +#endif + + 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); + + DBGLOG(NIC, INFO, "Chip ID[%04X] Version[E%u]\n", nicGetChipID(prAdapter), wlanGetEcoVersion(prAdapter)); + + return u4Status; +} + +#if defined(_HIF_SPI) +/*----------------------------------------------------------------------------*/ +/*! +* \brief Restore the SPI Mode Select to default mode, +* this is important while driver is unload, and this must be last mcr +* since the operation will let the hif use 8bit mode access +* +* \param[in] prAdapter a pointer to adapter private data structure. +* \param[in] eGPIO2_Mode GPIO2 operation mode +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void nicRestoreSpiDefMode(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + HAL_MCR_WR(prAdapter, MCR_WCSR, SPICSR_8BIT_MODE_DATA); + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process rx interrupt. When the rx +* Interrupt is asserted, it means there are frames in queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicProcessAbnormalInterrupt(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4Value = 0; +#if defined(MT6631) + UINT_32 u4Value1 = 0; +#endif + prAdapter->prGlueInfo->IsrAbnormalCnt++; + +#if defined(MT6631) + HAL_MCR_RD(prAdapter, MCR_WASR, &u4Value); + HAL_MCR_RD(prAdapter, MCR_WASR2, &u4Value1); + DBGLOG(REQ, ERROR, "MCR_WASR: 0x%x, MCR_WASR2: 0x%x\n", u4Value, u4Value1); +#else + HAL_MCR_RD(prAdapter, MCR_WASR, &u4Value); + DBGLOG(REQ, WARN, "MCR_WASR: 0x%x\n", u4Value); +#endif + + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief . +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicProcessFwOwnBackInterrupt(IN P_ADAPTER_T prAdapter) +{ +} /* end of nicProcessFwOwnBackInterrupt() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief . +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicProcessSoftwareInterrupt(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4IntrBits; + + ASSERT(prAdapter); + + prAdapter->prGlueInfo->IsrSoftWareCnt++; + u4IntrBits = prAdapter->u4IntStatus & BITS(8, 31); + + if ((u4IntrBits & WHISR_D2H_SW_ASSERT_INFO_INT) != 0) { + nicPrintFirmwareAssertInfo(prAdapter); +#if CFG_CHIP_RESET_SUPPORT + glSendResetRequest(); +#endif + } + + DBGLOG(REQ, WARN, "u4IntrBits: 0x%x\n", u4IntrBits); + +} /* end of nicProcessSoftwareInterrupt() */ + +VOID nicPutMailbox(IN P_ADAPTER_T prAdapter, IN UINT_32 u4MailboxNum, IN UINT_32 u4Data) +{ + if (u4MailboxNum == 0) + HAL_MCR_WR(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 interrupt in HW bit 16 is mapping to SW bit 0 (shift 16bit in HW transparancy) + * SW interrupt valid from b0~b15 + */ + ASSERT((u4SwIntrBitmap & BITS(0, 15)) == 0); +/* DBGLOG(NIC, TRACE, ("u4SwIntrBitmap: 0x%08x\n", u4SwIntrBitmap)); */ + + HAL_MCR_WR(prAdapter, MCR_WSICR, u4SwIntrBitmap); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This procedure is used to dequeue from prAdapter->rPendingCmdQueue +* with specified sequential number +* +* @param prAdapter Pointer of ADAPTER_T +* ucSeqNum Sequential Number +* +* @retval - P_CMD_INFO_T +*/ +/*----------------------------------------------------------------------------*/ +P_CMD_INFO_T nicGetPendingCmdInfo(IN P_ADAPTER_T prAdapter, IN UINT_8 ucSeqNum) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + + prCmdQue = &prAdapter->rPendingCmdQueue; + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + if (prCmdInfo->ucCmdSeqNum == ucSeqNum) + break; + + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + prCmdInfo = NULL; + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + QUEUE_CONCATENATE_QUEUES(prCmdQue, prTempCmdQue); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + + return prCmdInfo; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This procedure is used to dequeue from prAdapter->rTxCtrl.rTxMgmtTxingQueue +* with specified sequential number +* +* @param prAdapter Pointer of ADAPTER_T +* ucSeqNum Sequential Number +* +* @retval - P_MSDU_INFO_T +*/ +/*----------------------------------------------------------------------------*/ +P_MSDU_INFO_T nicGetPendingTxMsduInfo(IN P_ADAPTER_T prAdapter, IN UINT_8 ucWlanIndex, IN UINT_8 ucPID) +{ + 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->ucPID == ucPID) && (prMsduInfo->ucWlanIndex == ucWlanIndex)) + break; + + QUEUE_INSERT_TAIL(prTxingQue, prQueueEntry); + prMsduInfo = NULL; + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); + } + QUEUE_CONCATENATE_QUEUES(prTxingQue, prTempQue); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + if (prMsduInfo) { + DBGLOG(TX, TRACE, "Get Msdu WIDX:PID[%u:%u] SEQ[%u] from Pending Q\n", + prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, prMsduInfo->ucTxSeqNum); + } else { + DBGLOG(TX, WARN, "Cannot get Target Msdu WIDX:PID[%u:%u] from Pending Q\n", ucWlanIndex, ucPID); + } + + 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(); + + ASSERT(prAdapter); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + do { + prTxingQue = &(prAdapter->rTxCtrl.rTxMgmtTxingQueue); + QUEUE_MOVE_ALL(prTempQue, prTxingQue); + + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prMsduInfo = (P_MSDU_INFO_T) prQueueEntry; + + if ((prMsduInfo->ucStaRecIndex == ucStaRecIdx) + && (prMsduInfo->pfTxDoneHandler != NULL)) { + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfo, prMsduInfoListHead); + prMsduInfoListHead = prMsduInfo; + } else { + QUEUE_INSERT_TAIL(prTxingQue, prQueueEntry); + + prMsduInfo = NULL; + } + + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); + } + + } while (FALSE); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + return prMsduInfoListHead; +} /* nicGetPendingStaMMPDU */ + +VOID nicFreePendingTxMsduInfoByBssIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex) +{ + 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 (prMsduInfo->ucBssIndex == ucBssIndex) { + DBGLOG(TX, INFO, "%s: Get Msdu WIDX:PID[%u:%u] SEQ[%u] from Pending Q\n", + __func__, + prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, prMsduInfo->ucTxSeqNum); + + 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); + nicTxReturnMsduInfo(prAdapter, prMsduInfoListHead); + } + + return; + +} /* end of nicFreePendingTxMsduInfoByBssIdx() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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); + + ucRetval = prAdapter->ucTxSeqNum; + + 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 UINT_8 ucBssIndex, IN P_EVENT_CONNECTION_STATUS prConnectionStatus) +{ + P_GLUE_INFO_T prGlueInfo; + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + + switch (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType) { + case NETWORK_TYPE_AIS: + 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: + break; +#endif + +#if CFG_ENABLE_WIFI_DIRECT + case NETWORK_TYPE_P2P: + break; +#endif + default: + ASSERT(0); + } + + return WLAN_STATUS_SUCCESS; +} /* nicMediaStateChange */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to generate a join failure event to OS +* +* @param +* +* @retval +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicMediaJoinFailure(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN WLAN_STATUS rStatus) +{ + P_GLUE_INFO_T prGlueInfo; + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + + switch (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType) { + case NETWORK_TYPE_AIS: + kalIndicateStatusAndComplete(prGlueInfo, rStatus, NULL, 0); + + break; + + case NETWORK_TYPE_BOW: + case NETWORK_TYPE_P2P: + default: + break; + } + + return WLAN_STATUS_SUCCESS; +} /* end of nicMediaJoinFailure() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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 */ +#if CFG_SUPPORT_QA_TOOL + else if (u4ChannelNum >= 34 && u4ChannelNum <= 181) + u4ChannelInMHz = 5000 + u4ChannelNum * 5; +#else + else if (u4ChannelNum >= 34 && u4ChannelNum <= 165) + u4ChannelInMHz = 5000 + u4ChannelNum * 5; +#endif + 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 5720000: + return 144; + case 5745000: + return 149; + case 5765000: + return 153; + case 5785000: + return 157; + case 5805000: + return 161; + case 5825000: + return 165; + case 5845000: + return 169; + case 5865000: + return 173; +#if CFG_SUPPORT_QA_TOOL + case 5855000: + return 171; + case 5875000: + return 175; + case 5885000: + return 177; + case 5895000: + return 179; + case 5905000: + return 181; +#endif + default: + DBGLOG(NIC, WARN, "Return Invalid Channelnum = %u\n", u4FreqInKHz); + return 0; + } +} + +UINT_8 nicGetVhtS1(UINT_8 ucPrimaryChannel) +{ + /* find S1 (central channel 42, 58, 106, 122, and 155) */ + if (ucPrimaryChannel >= 36 && ucPrimaryChannel <= 48) + return 42; + else if (ucPrimaryChannel >= 52 && ucPrimaryChannel <= 64) + return 58; + else if (ucPrimaryChannel >= 100 && ucPrimaryChannel <= 112) + return 106; + else if (ucPrimaryChannel >= 116 && ucPrimaryChannel <= 128) + return 122; + else if (ucPrimaryChannel >= 132 && ucPrimaryChannel <= 144) + return 138; + else if (ucPrimaryChannel >= 149 && ucPrimaryChannel <= 161) + return 155; + 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 UINT_8 ucBssIndex) +{ + CMD_BSS_ACTIVATE_CTRL rCmdActivateCtrl; + P_BSS_INFO_T prBssInfo; + const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; + + ASSERT(prAdapter); + ASSERT(IS_BSS_INDEX_VALID(ucBssIndex)); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + prBssInfo->fg40mBwAllowed = FALSE; + prBssInfo->fgAssoc40mBwAllowed = FALSE; + + rCmdActivateCtrl.ucBssIndex = ucBssIndex; + rCmdActivateCtrl.ucActive = 1; + rCmdActivateCtrl.ucNetworkType = (UINT_8) prBssInfo->eNetworkType; + rCmdActivateCtrl.ucOwnMacAddrIndex = prBssInfo->ucOwnMacIndex; + COPY_MAC_ADDR(rCmdActivateCtrl.aucBssMacAddr, prBssInfo->aucOwnMacAddr); + + if (EQUAL_MAC_ADDR(aucZeroMacAddr, prBssInfo->aucBSSID)) { + prBssInfo->ucBMCWlanIndex = + secPrivacySeekForBcEntry(prAdapter, prBssInfo->ucBssIndex, + prBssInfo->aucOwnMacAddr, 0xff, CIPHER_SUITE_NONE, 0xff, 0x0, BIT(0)); + } else { + prBssInfo->ucBMCWlanIndex = + secPrivacySeekForBcEntry(prAdapter, prBssInfo->ucBssIndex, prBssInfo->aucBSSID, + 0xff, CIPHER_SUITE_NONE, 0xff, 0x0, BIT(0)); + } + + rCmdActivateCtrl.ucBMCWlanIndex = prBssInfo->ucBMCWlanIndex; + + kalMemZero(&rCmdActivateCtrl.ucReserved, sizeof(rCmdActivateCtrl.ucReserved)); + +#if DBG + DBGLOG(NIC, TRACE, "[wlan index][Network]=%d activate=%d\n", ucBssIndex, 1); + DBGLOG(NIC, TRACE, + "[wlan index][Network] OwnMac=" MACSTR " BSSID=" MACSTR " NetType=%d BCIndex=%d\n", + MAC2STR(prBssInfo->aucOwnMacAddr), + MAC2STR(prBssInfo->aucBSSID), + prBssInfo->eNetworkType, prBssInfo->ucBMCWlanIndex); +#endif + + 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 UINT_8 ucBssIndex) +{ + WLAN_STATUS u4Status; + CMD_BSS_ACTIVATE_CTRL rCmdActivateCtrl; + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(IS_BSS_INDEX_VALID(ucBssIndex)); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + kalMemZero(&rCmdActivateCtrl, sizeof(CMD_BSS_ACTIVATE_CTRL)); + + rCmdActivateCtrl.ucBssIndex = ucBssIndex; + rCmdActivateCtrl.ucActive = 0; + rCmdActivateCtrl.ucNetworkType = + (UINT_8)prBssInfo->eNetworkType; + rCmdActivateCtrl.ucOwnMacAddrIndex = + prBssInfo->ucOwnMacIndex; + rCmdActivateCtrl.ucBMCWlanIndex = + prBssInfo->ucBMCWlanIndex; + + DBGLOG(NIC, TRACE, "[wlan index][Network]=%d activate=%d\n", ucBssIndex, 0); + DBGLOG(NIC, TRACE, + "[wlan index][Network] OwnMac=" MACSTR " BSSID=" MACSTR " BCIndex = %d NetType=%d\n", + MAC2STR(prBssInfo->aucOwnMacAddr), + MAC2STR(prBssInfo->aucBSSID), + prBssInfo->ucBMCWlanIndex, + prBssInfo->eNetworkType); + + u4Status = wlanSendSetQueryCmd(prAdapter, + CMD_ID_BSS_ACTIVATE_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, sizeof(CMD_BSS_ACTIVATE_CTRL), (PUINT_8)&rCmdActivateCtrl, NULL, 0); + + /* free the wlan table of BSS INFO */ + secPrivacyFreeForEntry(prAdapter, prBssInfo->ucBMCWlanIndex); + prBssInfo->ucBMCWlanIndex = WTBL_RESERVED_ENTRY; + + /* free all correlated station records */ + cnmStaFreeAllStaByNetwork(prAdapter, ucBssIndex, STA_REC_EXCLUDE_NONE); + qmFreeAllByBssIdx(prAdapter, ucBssIndex); + nicFreePendingTxMsduInfoByBssIdx(prAdapter, ucBssIndex); + kalClearSecurityFramesByBssIdx(prAdapter->prGlueInfo, ucBssIndex); + + 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 +* ucBssIndex Index of BSS-INFO +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicUpdateBss(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex) +{ + WLAN_STATUS u4Status; + P_BSS_INFO_T prBssInfo; + CMD_SET_BSS_INFO rCmdSetBssInfo; + P_WIFI_VAR_T prWifiVar; + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= MAX_BSS_INDEX); + + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + prWifiVar = &prAdapter->rWifiVar; + + kalMemZero(&rCmdSetBssInfo, sizeof(CMD_SET_BSS_INFO)); + + rCmdSetBssInfo.ucBssIndex = ucBssIndex; + 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.u2HwDefaultFixedRateCode = prBssInfo->u2HwDefaultFixedRateCode; + rCmdSetBssInfo.ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + rCmdSetBssInfo.u4PrivateData = prBssInfo->u4PrivateData; + rCmdSetBssInfo.ucBMCWlanIndex = prBssInfo->ucBMCWlanIndex; +#ifdef CFG_ENABLE_WIFI_DIRECT + rCmdSetBssInfo.ucHiddenSsidMode = prBssInfo->eHiddenSsidType; +#endif + rlmFillSyncCmdParam(&rCmdSetBssInfo.rBssRlmParam, prBssInfo); + + rCmdSetBssInfo.ucWapiMode = (UINT_8) FALSE; + + if (rCmdSetBssInfo.ucBssIndex == prAdapter->prAisBssInfo->ucBssIndex) { + P_CONNECTION_SETTINGS_T prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + rCmdSetBssInfo.ucAuthMode = (UINT_8) prConnSettings->eAuthMode; + rCmdSetBssInfo.ucEncStatus = (UINT_8) prConnSettings->eEncStatus; + rCmdSetBssInfo.ucWapiMode = (UINT_8) prConnSettings->fgWapiMode; + rCmdSetBssInfo.ucDisconnectDetectTh = prWifiVar->ucStaDisconnectDetectTh; + /* If connect to a AP in bandwidth VHT80, change vcore to 0.8v + ** otherwise, if disconnect from VHT80 AP or leave VHT80, change vcore to 0.725v + */ + if (prBssInfo->ucVhtChannelWidth == VHT_OP_CHANNEL_WIDTH_80 && + prBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) + kalTakeVcoreAction(VCORE_ADD_HIGHER_REQ); + else if (prBssInfo->eConnectionState != PARAM_MEDIA_STATE_TO_BE_INDICATED) + kalTakeVcoreAction(VCORE_DEC_HIGHER_REQ); + } +#if CFG_ENABLE_BT_OVER_WIFI + else if (IS_BSS_BOW(prBssInfo)) { + 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) { + P_P2P_CONNECTION_SETTINGS_T prP2PConnSettings = prWifiVar->prP2PConnSettings; + + if (kalP2PGetCcmpCipher(prAdapter->prGlueInfo)) { + rCmdSetBssInfo.ucAuthMode = (UINT_8) AUTH_MODE_WPA2_PSK; + rCmdSetBssInfo.ucEncStatus = (UINT_8) ENUM_ENCRYPTION3_ENABLED; + } else if (kalP2PGetTkipCipher(prAdapter->prGlueInfo)) { + rCmdSetBssInfo.ucAuthMode = (UINT_8) AUTH_MODE_WPA_PSK; + rCmdSetBssInfo.ucEncStatus = (UINT_8) ENUM_ENCRYPTION2_ENABLED; + } else if (kalP2PGetCipher(prAdapter->prGlueInfo)) { + rCmdSetBssInfo.ucAuthMode = (UINT_8) AUTH_MODE_OPEN; + rCmdSetBssInfo.ucEncStatus = (UINT_8) ENUM_ENCRYPTION1_ENABLED; + } else { + rCmdSetBssInfo.ucAuthMode = (UINT_8) AUTH_MODE_OPEN; + rCmdSetBssInfo.ucEncStatus = (UINT_8) ENUM_ENCRYPTION_DISABLED; + } + /* + * In AP WPS Certification, need firmware to report Probe Request and + * hostapd to send Probe Response for bringing manufacturer information + * and detecting the PBC overlap. + */ + if (prP2PConnSettings && prP2PConnSettings->fgIsWPSMode) + rCmdSetBssInfo.ucIsApMode = FALSE; + else + rCmdSetBssInfo.ucIsApMode = p2pFuncIsAPMode(prP2PConnSettings); + + if (rCmdSetBssInfo.ucIsApMode) + rCmdSetBssInfo.ucDisconnectDetectTh = prWifiVar->ucApDisconnectDetectTh; + else + rCmdSetBssInfo.ucDisconnectDetectTh = prWifiVar->ucP2pDisconnectDetectTh; + } +#else + rCmdSetBssInfo.ucAuthMode = (UINT_8) AUTH_MODE_WPA2_PSK; + rCmdSetBssInfo.ucEncStatus = (UINT_8) ENUM_ENCRYPTION3_KEY_ABSENT; +#endif + } + /* Firmware didn't define AUTH_MODE_NON_RSN_FT, so AUTH_MODE_OPEN is zero in firmware, + ** but it is 1 in driver. so we need to minus 1 for all authmode except AUTH_MODE_NON_RSN_FT, + ** because AUTH_MODE_NON_RSN_FT will be same as AUTH_MODE_OPEN in firmware + **/ + if (rCmdSetBssInfo.ucAuthMode != AUTH_MODE_NON_RSN_FT) + rCmdSetBssInfo.ucAuthMode -= 1; + + if (ucBssIndex == prAdapter->prAisBssInfo->ucBssIndex && + prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE && prBssInfo->prStaRecOfAP != NULL) { + rCmdSetBssInfo.ucStaRecIdxOfAP = prBssInfo->prStaRecOfAP->ucIndex; + + cnmAisInfraConnectNotify(prAdapter); + } +#if CFG_ENABLE_WIFI_DIRECT + else if ((prAdapter->fgIsP2PRegistered) && + (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) && + (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) && (prBssInfo->prStaRecOfAP != NULL)) { + rCmdSetBssInfo.ucStaRecIdxOfAP = prBssInfo->prStaRecOfAP->ucIndex; + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI /* disabled for BOW to finish ucBssIndex migration */ + else if (prBssInfo->eNetworkType == NETWORK_TYPE_BOW && + prBssInfo->eCurrentOPMode == OP_MODE_BOW && prBssInfo->prStaRecOfAP != NULL) { + rCmdSetBssInfo.ucStaRecIdxOfAP = prBssInfo->prStaRecOfAP->ucIndex; + } +#endif + else + rCmdSetBssInfo.ucStaRecIdxOfAP = STA_REC_INDEX_NOT_FOUND; + + DBGLOG(BSS, INFO, + "Update Bss[%u] ConnState[%u] OPmode[%u] BSSID[" MACSTR + "] AuthMode[%u] EncStatus[%u]\n", ucBssIndex, prBssInfo->eConnectionState, + prBssInfo->eCurrentOPMode, MAC2STR(prBssInfo->aucBSSID), rCmdSetBssInfo.ucAuthMode, + rCmdSetBssInfo.ucEncStatus); + + 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 */ + bssInitializeClientList(prAdapter, prBssInfo); + +#if DBG + DBGLOG(BSS, TRACE, "nicUpdateBss for disconnect state\n"); +#endif + /* free all correlated station records */ + cnmStaFreeAllStaByNetwork(prAdapter, ucBssIndex, STA_REC_EXCLUDE_NONE); + qmFreeAllByBssIdx(prAdapter, ucBssIndex); + kalClearSecurityFramesByBssIdx(prAdapter->prGlueInfo, ucBssIndex); +#if CFG_ENABLE_GTK_FRAME_FILTER + if (prBssInfo->prIpV4NetAddrList) + FREE_IPV4_NETWORK_ADDR_LIST(prBssInfo->prIpV4NetAddrList); +#endif + + } + + return u4Status; +} + +/* BSS-INFO Indication (PM) */ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to indicate PM that +* a BSS has been created. (for AdHoc / P2P-GO) +* +* @param prAdapter Pointer of ADAPTER_T +* ucBssIndex Index of BSS-INFO +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicPmIndicateBssCreated(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex) +{ + P_BSS_INFO_T prBssInfo; + CMD_INDICATE_PM_BSS_CREATED rCmdIndicatePmBssCreated; + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= MAX_BSS_INDEX); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + rCmdIndicatePmBssCreated.ucBssIndex = ucBssIndex; + 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 UINT_8 ucBssIndex) +{ + P_BSS_INFO_T prBssInfo; + CMD_INDICATE_PM_BSS_CONNECTED rCmdIndicatePmBssConnected; + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= MAX_BSS_INDEX); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + rCmdIndicatePmBssConnected.ucBssIndex = ucBssIndex; + 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 ((GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType == NETWORK_TYPE_AIS) +#if CFG_ENABLE_WIFI_DIRECT + || ((GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType == NETWORK_TYPE_P2P) + && (prAdapter->fgIsP2PRegistered)) +#endif + ) { + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE && prBssInfo->prStaRecOfAP) { + UINT_8 ucUapsd = wmmCalculateUapsdSetting(prAdapter); + + /* should sync Tspec uapsd settings */ + rCmdIndicatePmBssConnected.ucBmpDeliveryAC = (ucUapsd >> 4) & 0xf; + rCmdIndicatePmBssConnected.ucBmpTriggerAC = ucUapsd & 0xf; + 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 +* ucBssIndex Index of BSS-INFO +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicPmIndicateBssAbort(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex) +{ + CMD_INDICATE_PM_BSS_ABORT rCmdIndicatePmBssAbort; + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= MAX_BSS_INDEX); + + rCmdIndicatePmBssAbort.ucBssIndex = ucBssIndex; + + 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); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to set power save bit map +* +* +* @param prAdapter Pointer of ADAPTER_T +* ucBssIndex Index of BSS-INFO +* ucSet enter power save or not(1 PS, 0 not PS) +* ucCaller index of bit mapfor caller +* @retval - +*/ +/*----------------------------------------------------------------------------*/ + +VOID nicPowerSaveInfoMap(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, + IN PARAM_POWER_MODE ePowerMode, IN enum POWER_SAVE_CALLER_T ucCaller) +{ + UINT_32 u4OldValue; + + /*max caller 24*/ + if (ucCaller >= PS_CALLER_MAX_NUM) + ASSERT(0); + + u4OldValue = prAdapter->rWlanInfo.u4PowerSaveFlag[ucBssIndex]; + + DBGLOG(NIC, TRACE, "unicCheckPowerSaveSend u4OldValue=0x%04x, ucCaller=%d\n", u4OldValue, ucCaller); + + + if (ePowerMode != Param_PowerModeCAM) { + if ((u4OldValue & 0x00ffffff) == BIT(ucCaller)) + u4OldValue |= PS_SYNC_WITH_FW; /*set send command flag*/ + u4OldValue &= ~BIT(ucCaller); + } else { + if (u4OldValue == 0) + u4OldValue |= PS_SYNC_WITH_FW; /*set send command flag*/ + u4OldValue |= BIT(ucCaller); + } + + prAdapter->rWlanInfo.u4PowerSaveFlag[ucBssIndex] = u4OldValue; + DBGLOG(NIC, TRACE, "unicCheckPowerSaveSend u4PowerSaveFlag[%d]=0x%04x\n", ucBssIndex, + prAdapter->rWlanInfo.u4PowerSaveFlag[ucBssIndex]); +} + + +WLAN_STATUS +nicConfigPowerSaveProfile(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN PARAM_POWER_MODE ePwrMode, + IN BOOLEAN fgEnCmdEvent) +{ + UINT_32 u4OldValue; + WLAN_STATUS rWlanStatus; + + DEBUGFUNC("nicConfigPowerSaveProfile"); + DBGLOG(NIC, TRACE, "ucBssIndex:%d, ePwrMode:%d, fgEnCmdEvent:%d\n", ucBssIndex, ePwrMode, fgEnCmdEvent); + + ASSERT(prAdapter); + + if (ucBssIndex >= BSS_INFO_NUM) { + ASSERT(0); + return WLAN_STATUS_NOT_SUPPORTED; + } + + + + u4OldValue = prAdapter->rWlanInfo.u4PowerSaveFlag[ucBssIndex]; + + prAdapter->rWlanInfo.arPowerSaveMode[ucBssIndex].ucBssIndex = ucBssIndex; + prAdapter->rWlanInfo.arPowerSaveMode[ucBssIndex].ucPsProfile = (UINT_8) ePwrMode; + + + DBGLOG(NIC, TRACE, "nicConfigPowerSaveProfile u4OldValue=0x%04x\n", u4OldValue); + /*set send command flag*/ + if (u4OldValue & PS_SYNC_WITH_FW) { + prAdapter->rWlanInfo.u4PowerSaveFlag[ucBssIndex] &= ~PS_SYNC_WITH_FW; + DBGLOG(NIC, TRACE, "nicConfigPowerSaveProfile u4PowerSaveFlag[%d]=0x%04x\n", ucBssIndex, + prAdapter->rWlanInfo.u4PowerSaveFlag[ucBssIndex]); + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_POWER_SAVE_MODE, + TRUE, + FALSE, + fgEnCmdEvent, + (fgEnCmdEvent ? nicCmdEventSetCommon : NULL), + (fgEnCmdEvent ? nicOidCmdTimeoutCommon : NULL), + sizeof(CMD_PS_PROFILE_T), + (PUINT_8)&(prAdapter->rWlanInfo.arPowerSaveMode[ucBssIndex]), + NULL, sizeof(PARAM_POWER_MODE)); + + if (fgEnCmdEvent) + return rWlanStatus; + } + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetAcpiDevicePowerStateMode() */ + +WLAN_STATUS nicEnterCtiaMode(IN P_ADAPTER_T prAdapter, BOOLEAN fgEnterCtia, BOOLEAN fgEnCmdEvent) +{ + CMD_SW_DBG_CTRL_T rCmdSwCtrl; + /* CMD_ACCESS_REG rCmdAccessReg; */ + WLAN_STATUS rWlanStatus; + + DEBUGFUNC("nicEnterCtiaMode"); + DBGLOG(NIC, INFO, "nicEnterCtiaMode: %d\n", fgEnterCtia); + + ASSERT(prAdapter); + + rWlanStatus = WLAN_STATUS_SUCCESS; + prAdapter->fgEnCtiaMode = fgEnterCtia; + + if (fgEnterCtia) { + /* 1. Disable On-Lin Scan */ + prAdapter->fgEnOnlineScan = FALSE; + + /* 2. Disable FIFO FULL no ack */ + /* 3. Disable Roaming */ + /* 4. Disalbe auto tx power */ + rCmdSwCtrl.u4Id = 0xa0100003; + rCmdSwCtrl.u4Data = 0x0; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); + + /* 2. Keep at CAM mode */ + { + PARAM_POWER_MODE ePowerMode; + + prAdapter->u4CtiaPowerMode = 0; + prAdapter->fgEnCtiaPowerMode = TRUE; + + ePowerMode = Param_PowerModeCAM; + + nicPowerSaveInfoMap(prAdapter, prAdapter->prAisBssInfo->ucBssIndex, + ePowerMode, PS_CALLER_CTIA_MODE); + + rWlanStatus = nicConfigPowerSaveProfile(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, ePowerMode, + fgEnCmdEvent); + } + + /* 5. Disable Beacon Timeout Detection */ + prAdapter->fgDisBcnLostDetection = TRUE; + } else { + /* 1. Enaable On-Lin Scan */ + prAdapter->fgEnOnlineScan = TRUE; + + /* 2. Enable FIFO FULL no ack */ + /* 3. Enable Roaming */ + /* 4. Enable auto tx power */ + /* */ + + rCmdSwCtrl.u4Id = 0xa0100003; + rCmdSwCtrl.u4Data = 0x1; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); + + /* 2. Keep at Fast PS */ + { + PARAM_POWER_MODE ePowerMode; + + prAdapter->u4CtiaPowerMode = 2; + prAdapter->fgEnCtiaPowerMode = TRUE; + + ePowerMode = Param_PowerModeFast_PSP; + + nicPowerSaveInfoMap(prAdapter, prAdapter->prAisBssInfo->ucBssIndex, + ePowerMode, PS_CALLER_CTIA_MODE); + + rWlanStatus = nicConfigPowerSaveProfile(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, ePowerMode, + fgEnCmdEvent); + } + + /* 5. Enable Beacon Timeout Detection */ + prAdapter->fgDisBcnLostDetection = FALSE; + + } + + return rWlanStatus; +} /* end of nicEnterCtiaMode() */ + +WLAN_STATUS nicEnterCtiaModeOfScan(IN P_ADAPTER_T prAdapter, BOOLEAN fgEnterCtia, BOOLEAN fgEnCmdEvent) +{ + WLAN_STATUS rWlanStatus; + + ASSERT(prAdapter); + DBGLOG(INIT, INFO, "nicEnterCtiaModeOfScan: %d\n", fgEnterCtia); + + rWlanStatus = WLAN_STATUS_SUCCESS; + prAdapter->fgEnCtiaMode = fgEnterCtia; + + if (fgEnterCtia) { + /* Disable On-Line Scan */ + prAdapter->fgEnOnlineScan = FALSE; + } else { + /* Enable On-Line Scan */ + prAdapter->fgEnOnlineScan = TRUE; + } + + return rWlanStatus; +} + +WLAN_STATUS nicEnterCtiaModeOfRoaming(IN P_ADAPTER_T prAdapter, BOOLEAN fgEnterCtia, BOOLEAN fgEnCmdEvent) +{ + CMD_SW_DBG_CTRL_T rCmdSwCtrl; + WLAN_STATUS rWlanStatus; + + ASSERT(prAdapter); + DBGLOG(INIT, INFO, "nicEnterCtiaModeOfRoaming: %d\n", fgEnterCtia); + + rWlanStatus = WLAN_STATUS_SUCCESS; + prAdapter->fgEnCtiaMode = fgEnterCtia; + + if (fgEnterCtia) { + /* Disable Roaming */ + rCmdSwCtrl.u4Id = 0x55660000; + rCmdSwCtrl.u4Data = 0x0; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), + (PUINT_8)&rCmdSwCtrl, NULL, 0); + } else { + /* Enable Roaming */ + rCmdSwCtrl.u4Id = 0x55660000; + rCmdSwCtrl.u4Data = 0x1; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), + (PUINT_8)&rCmdSwCtrl, NULL, 0); + } + + return rWlanStatus; +} + +WLAN_STATUS nicEnterCtiaModeOfCAM(IN P_ADAPTER_T prAdapter, BOOLEAN fgEnterCtia, BOOLEAN fgEnCmdEvent) +{ + WLAN_STATUS rWlanStatus; + + ASSERT(prAdapter); + DBGLOG(INIT, INFO, "nicEnterCtiaModeOfCAM: %d\n", fgEnterCtia); + + rWlanStatus = WLAN_STATUS_SUCCESS; + prAdapter->fgEnCtiaMode = fgEnterCtia; + + if (fgEnterCtia) { + /* Keep at CAM mode */ + { + PARAM_POWER_MODE ePowerMode; + + prAdapter->u4CtiaPowerMode = 0; + prAdapter->fgEnCtiaPowerMode = TRUE; + + ePowerMode = Param_PowerModeCAM; + + nicPowerSaveInfoMap(prAdapter, prAdapter->prAisBssInfo->ucBssIndex, + ePowerMode, PS_CALLER_CTIA); + + rWlanStatus = nicConfigPowerSaveProfile(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, ePowerMode, + fgEnCmdEvent); + } + } else { + /* Keep at Fast PS */ + { + PARAM_POWER_MODE ePowerMode; + + prAdapter->u4CtiaPowerMode = 2; + prAdapter->fgEnCtiaPowerMode = TRUE; + + ePowerMode = Param_PowerModeFast_PSP; + nicPowerSaveInfoMap(prAdapter, prAdapter->prAisBssInfo->ucBssIndex, + ePowerMode, PS_CALLER_CTIA); + + rWlanStatus = nicConfigPowerSaveProfile(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, ePowerMode, + fgEnCmdEvent); + } + } + + return rWlanStatus; +} + +WLAN_STATUS nicEnterCtiaModeOfBCNTimeout(IN P_ADAPTER_T prAdapter, BOOLEAN fgEnterCtia, BOOLEAN fgEnCmdEvent) +{ + WLAN_STATUS rWlanStatus; + + ASSERT(prAdapter); + DBGLOG(INIT, INFO, "nicEnterCtiaModeOfBCNTimeout: %d\n", fgEnterCtia); + + rWlanStatus = WLAN_STATUS_SUCCESS; + prAdapter->fgEnCtiaMode = fgEnterCtia; + + if (fgEnterCtia) { + /* Disable Beacon Timeout Detection */ + prAdapter->fgDisBcnLostDetection = TRUE; + } else { + /* Enable Beacon Timeout Detection */ + prAdapter->fgDisBcnLostDetection = FALSE; + } + + return rWlanStatus; +} + +WLAN_STATUS nicEnterCtiaModeOfAutoTxPower(IN P_ADAPTER_T prAdapter, BOOLEAN fgEnterCtia, BOOLEAN fgEnCmdEvent) +{ + CMD_SW_DBG_CTRL_T rCmdSwCtrl; + WLAN_STATUS rWlanStatus; + + ASSERT(prAdapter); + DBGLOG(INIT, INFO, "nicEnterCtiaModeOfAutoTxPower: %d\n", fgEnterCtia); + + rWlanStatus = WLAN_STATUS_SUCCESS; + prAdapter->fgEnCtiaMode = fgEnterCtia; + + if (fgEnterCtia) { + /* Disalbe auto tx power */ + rCmdSwCtrl.u4Id = 0x55670003; + rCmdSwCtrl.u4Data = 0x0; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); + } else { + /* Enable auto tx power */ + rCmdSwCtrl.u4Id = 0x55670003; + rCmdSwCtrl.u4Data = 0x1; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); + } + + return rWlanStatus; +} + +WLAN_STATUS nicEnterCtiaModeOfFIFOFullNoAck(IN P_ADAPTER_T prAdapter, BOOLEAN fgEnterCtia, BOOLEAN fgEnCmdEvent) +{ + CMD_SW_DBG_CTRL_T rCmdSwCtrl; + WLAN_STATUS rWlanStatus; + + ASSERT(prAdapter); + DBGLOG(INIT, INFO, "nicEnterCtiaModeOfFIFOFullNoAck: %d\n", fgEnterCtia); + + rWlanStatus = WLAN_STATUS_SUCCESS; + prAdapter->fgEnCtiaMode = fgEnterCtia; + + if (fgEnterCtia) { + /* Disable FIFO FULL no ack */ + rCmdSwCtrl.u4Id = 0x55680000; + rCmdSwCtrl.u4Data = 0x0; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); + } else { + /* Enable FIFO FULL no ack */ + rCmdSwCtrl.u4Id = 0x55680000; + rCmdSwCtrl.u4Data = 0x1; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); + } + + return rWlanStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to indicate firmware domain +* for beacon generation parameters +* +* @param prAdapter Pointer of ADAPTER_T +* eIeUpdMethod, Update Method +* ucBssIndex Index of BSS-INFO +* 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 UINT_8 ucBssIndex, 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"); + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + + if (u2IELen > MAX_IE_LENGTH) + return WLAN_STATUS_INVALID_DATA; + + if (eIeUpdMethod == IE_UPD_METHOD_UPDATE_RANDOM || eIeUpdMethod == IE_UPD_METHOD_UPDATE_ALL) { + u2CmdBufLen = OFFSET_OF(CMD_BEACON_TEMPLATE_UPDATE, aucIE) + u2IELen; + } else if (eIeUpdMethod == IE_UPD_METHOD_DELETE_ALL) { + u2CmdBufLen = OFFSET_OF(CMD_BEACON_TEMPLATE_UPDATE, u2IELen); + } else { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + /* prepare command info */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + u2CmdBufLen)); + if (!prCmdInfo) { + DBGLOG(NIC, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + DBGLOG(REQ, TRACE, "ucCmdSeqNum =%d\n", ucCmdSeqNum); + + /* Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->ucBssIndex = ucBssIndex; + 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 = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + 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->ucBssIndex = ucBssIndex; + prCmdBcnUpdate->u2Capability = u2Capability; + prCmdBcnUpdate->u2IELen = u2IELen; + if (u2IELen > 0) + kalMemCopy(prCmdBcnUpdate->aucIE, aucIe, u2IELen); + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + return WLAN_STATUS_PENDING; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to initialization PHY related +* varaibles +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicSetAvailablePhyTypeSet(IN P_ADAPTER_T prAdapter) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + + ASSERT(prAdapter); + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + if (prConnSettings->eDesiredPhyConfig >= PHY_CONFIG_NUM) { + ASSERT(0); + return; + } + + prAdapter->rWifiVar.ucAvailablePhyTypeSet = aucPhyCfg2PhyTypeSet[prConnSettings->eDesiredPhyConfig]; + + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_BIT_ERP) + prAdapter->rWifiVar.eNonHTBasicPhyType2G4 = PHY_TYPE_ERP_INDEX; + /* NOTE(Kevin): Because we don't have N only mode, TBD */ + else /* if (ucNonHTPhyTypeSet & PHY_TYPE_HR_DSSS_INDEX) */ + prAdapter->rWifiVar.eNonHTBasicPhyType2G4 = PHY_TYPE_HR_DSSS_INDEX; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update WMM Parms +* +* @param prAdapter Pointer of ADAPTER_T +* ucBssIndex Index of BSS-INFO +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicQmUpdateWmmParms(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex) +{ + P_BSS_INFO_T prBssInfo; + CMD_UPDATE_WMM_PARMS_T rCmdUpdateWmmParms; + + ASSERT(prAdapter); + + DBGLOG(QM, TRACE, "Update WMM parameters for BSS[%u]\n", ucBssIndex); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + rCmdUpdateWmmParms.ucBssIndex = (UINT_8) ucBssIndex; + 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) +{ +#if 0 /* It is not needed anymore */ + 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); +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update DPD calibration result +* +* @param prAdapter Pointer of ADAPTER_T +* pr5GPwrOffset Pointer of parameter for DPD calibration result +* +* @retval WLAN_STATUS_PENDING +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicUpdateDPD(IN P_ADAPTER_T prAdapter, IN P_CMD_PWR_PARAM_T prDpdCalResult) +{ + DEBUGFUNC("nicUpdateDPD"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_PWR_PARAM, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_PWR_PARAM_T), (PUINT_8) prDpdCalResult, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function starts system service such as timer and +* memory pools +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicInitSystemService(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + /* <1> Initialize MGMT Memory pool and STA_REC */ + cnmMemInit(prAdapter); + cnmStaRecInit(prAdapter); + cmdBufInitialize(prAdapter); + + /* <2> Mailbox Initialization */ + mboxInitialize(prAdapter); + + /* <3> Timer Initialization */ + cnmTimerInitialize(prAdapter); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function reset some specific system service, +* such as STA-REC +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicResetSystemService(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update WMM Parms +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicUninitSystemService(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + /* Timer Destruction */ + cnmTimerDestroy(prAdapter); + + /* Mailbox Destruction */ + mboxDestroy(prAdapter); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update WMM Parms +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicInitMGMT(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo) +{ + ASSERT(prAdapter); + + /* CNM Module - initialization */ + cnmInit(prAdapter); + + wmmInit(prAdapter); + + /* RLM Module - initialization */ + rlmFsmEventInit(prAdapter); + + /* SCN Module - initialization */ + scnInit(prAdapter); + + /* AIS Module - intiailization */ + aisFsmInit(prAdapter); + aisInitializeConnectionSettings(prAdapter, prRegInfo); + +#if CFG_SUPPORT_ROAMING + /* Roaming Module - intiailization */ + roamingFsmInit(prAdapter); +#endif /* CFG_SUPPORT_ROAMING */ + +#if CFG_SUPPORT_SWCR + swCrDebugInit(prAdapter); +#endif /* CFG_SUPPORT_SWCR */ + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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); + + wmmUnInit(prAdapter); + + /* RLM Module - uninitialization */ + rlmFsmEventUninit(prAdapter); + + /* CNM Module - uninitialization */ + cnmUninit(prAdapter); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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) +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +nicAddScanResult(IN P_ADAPTER_T prAdapter, + IN PARAM_MAC_ADDRESS rMacAddr, + IN P_PARAM_SSID_T prSsid, + IN UINT_16 u2CapInfo, + 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 = ARRAY_SIZE(prAdapter->rWlanInfo.aucScanIEBuf); + + 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].u2CapInfo = u2CapInfo; + prAdapter->rWlanInfo.arScanResult[i].u4Privacy = u2CapInfo & CAP_INFO_PRIVACY ? 1 : 0; + 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].u2CapInfo = u2CapInfo; + prAdapter->rWlanInfo.arScanResult[i].u4Privacy = u2CapInfo & CAP_INFO_PRIVACY ? 1 : 0; + 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].u2CapInfo = u2CapInfo; + prAdapter->rWlanInfo.arScanResult[i].u4Privacy = u2CapInfo & CAP_INFO_PRIVACY ? 1 : 0; + 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; + } + } + return i; + } + return i - 1; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is invoked to free IE buffer for dedicated scan result +* +* @param prAdapter Pointer to the Adapter structure. +* @param u4Idx Index of Scan Result +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicFreeScanResultIE(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Idx) +{ + UINT_32 i; + PUINT_8 pucPivot, pucMovePivot; + UINT_32 u4MoveSize, u4FreeSize, u4ReserveSize; + + ASSERT(prAdapter); + ASSERT(u4Idx < CFG_MAX_NUM_BSS_LIST); + + if (prAdapter->rWlanInfo.arScanResult[u4Idx].u4IELength == 0 + || prAdapter->rWlanInfo.apucScanResultIEs[u4Idx] == NULL) { + return; + } + + u4FreeSize = ALIGN_4(prAdapter->rWlanInfo.arScanResult[u4Idx].u4IELength); + + pucPivot = prAdapter->rWlanInfo.apucScanResultIEs[u4Idx]; + pucMovePivot = (PUINT_8) ((ULONG) (prAdapter->rWlanInfo.apucScanResultIEs[u4Idx]) + u4FreeSize); + + u4ReserveSize = ((ULONG) pucPivot) - (ULONG) (&(prAdapter->rWlanInfo.aucScanIEBuf[0])); + u4MoveSize = prAdapter->rWlanInfo.u4ScanIEBufferUsage - u4ReserveSize - u4FreeSize; + + /* 1. rest of buffer to move forward */ + kalMemCopy(pucPivot, pucMovePivot, u4MoveSize); + + /* 1.1 modify pointers */ + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + if (i != u4Idx) { + if (prAdapter->rWlanInfo.apucScanResultIEs[i] >= pucMovePivot) { + prAdapter->rWlanInfo.apucScanResultIEs[i] = + (PUINT_8) ((ULONG) (prAdapter->rWlanInfo.apucScanResultIEs[i]) + - u4FreeSize); + } + } + } + + /* 1.2 reset the freed one */ + prAdapter->rWlanInfo.arScanResult[u4Idx].u4IELength = 0; + prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; + + /* 2. reduce IE buffer usage */ + prAdapter->rWlanInfo.u4ScanIEBufferUsage -= u4FreeSize; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to hack parameters for WLAN TABLE for +* fixed rate settings +* +* @param prAdapter Pointer to the Adapter structure. +* @param eRateSetting +* @param pu2DesiredNonHTRateSet, +* @param pu2BSSBasicRateSet, +* @param pucMcsSet +* @param pucSupMcs32 +* @param pu2HtCapInfo +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicUpdateRateParams(IN P_ADAPTER_T prAdapter, + IN ENUM_REGISTRY_FIXED_RATE_T eRateSetting, + IN PUINT_8 pucDesiredPhyTypeSet, + IN PUINT_16 pu2DesiredNonHTRateSet, + IN PUINT_16 pu2BSSBasicRateSet, + IN PUINT_8 pucMcsSet, IN PUINT_8 pucSupMcs32, IN PUINT_16 pu2HtCapInfo) +{ + ASSERT(prAdapter); + ASSERT(eRateSetting > FIXED_RATE_NONE && eRateSetting < FIXED_RATE_NUM); + + switch (prAdapter->rWifiVar.eRateSetting) { + case FIXED_RATE_1M: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HR_DSSS; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_1M; + *pu2BSSBasicRateSet = RATE_SET_BIT_1M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_2M: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HR_DSSS; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_2M; + *pu2BSSBasicRateSet = RATE_SET_BIT_2M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_5_5M: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HR_DSSS; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_5_5M; + *pu2BSSBasicRateSet = RATE_SET_BIT_5_5M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_11M: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HR_DSSS; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_11M; + *pu2BSSBasicRateSet = RATE_SET_BIT_11M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_6M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_6M; + *pu2BSSBasicRateSet = RATE_SET_BIT_6M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_9M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_9M; + *pu2BSSBasicRateSet = RATE_SET_BIT_9M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_12M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_12M; + *pu2BSSBasicRateSet = RATE_SET_BIT_12M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_18M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_18M; + *pu2BSSBasicRateSet = RATE_SET_BIT_18M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_24M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_24M; + *pu2BSSBasicRateSet = RATE_SET_BIT_24M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_36M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_36M; + *pu2BSSBasicRateSet = RATE_SET_BIT_36M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_48M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_48M; + *pu2BSSBasicRateSet = RATE_SET_BIT_48M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_54M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_54M; + *pu2BSSBasicRateSet = RATE_SET_BIT_54M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_MCS0_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS0_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS1_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS1_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS2_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS2_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS3_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS3_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS4_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS4_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS5_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS5_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS6_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS6_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS7_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS7_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS0_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS0_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS1_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS1_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS2_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS2_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS3_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS3_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS4_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS4_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS5_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS5_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS6_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS6_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS7_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS7_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS0_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS0_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS1_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS1_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS2_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS2_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS3_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS3_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS4_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS4_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS5_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS5_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS6_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS6_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS7_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS7_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS32_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS32_INDEX; + *pucSupMcs32 = 1; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS0_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS0_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS1_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS1_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS2_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS2_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS3_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS3_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS4_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS4_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS5_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS5_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS6_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS6_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS7_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS7_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS32_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS32_INDEX; + *pucSupMcs32 = 1; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + default: + ASSERT(0); + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to write the register +* +* @param u4Address Register address +* u4Value the value to be written +* +* @retval WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS nicWriteMcr(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Address, IN UINT_32 u4Value) +{ + CMD_ACCESS_REG rCmdAccessReg; + + rCmdAccessReg.u4Address = u4Address; + rCmdAccessReg.u4Data = u4Value; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_ACCESS_REG), (PUINT_8) &rCmdAccessReg, NULL, 0); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to modify the auto rate parameters +* +* @param u4ArSysParam0 see description below +* u4ArSysParam1 +* u4ArSysParam2 +* u4ArSysParam3 +* +* +* @retval WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +* +* @note +* ArSysParam0[0:3] -> auto rate version (0:disable 1:version1 2:version2) +* ArSysParam0[4:5]-> auto bw version (0:disable 1:version1 2:version2) +* ArSysParam0[6:7]-> auto gi version (0:disable 1:version1 2:version2) +* ArSysParam0[8:15]-> HT rate clear mask +* ArSysParam0[16:31]-> Legacy rate clear mask +* ArSysParam1[0:7]-> Auto Rate check weighting window +* ArSysParam1[8:15]-> Auto Rate v1 Force Rate down +* ArSysParam1[16:23]-> Auto Rate v1 PerH +* ArSysParam1[24:31]-> Auto Rate v1 PerL +* +* Examples +* ArSysParam0 = 1, +* Enable auto rate version 1 +* +* ArSysParam0 = 983041, +* Enable auto rate version 1 +* Remove CCK 1M, 2M, 5.5M, 11M +* +* ArSysParam0 = 786433 +* Enable auto rate version 1 +* Remove CCK 5.5M 11M +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS +nicRlmArUpdateParms(IN P_ADAPTER_T prAdapter, + IN UINT_32 u4ArSysParam0, + IN UINT_32 u4ArSysParam1, IN UINT_32 u4ArSysParam2, IN UINT_32 u4ArSysParam3) +{ + UINT_8 ucArVer, ucAbwVer, ucAgiVer; + UINT_16 u2HtClrMask; + UINT_16 u2LegacyClrMask; + UINT_8 ucArCheckWindow; + UINT_8 ucArPerL; + UINT_8 ucArPerH; + UINT_8 ucArPerForceRateDownPer; + + ucArVer = (UINT_8) (u4ArSysParam0 & BITS(0, 3)); + ucAbwVer = (UINT_8) ((u4ArSysParam0 & BITS(4, 5)) >> 4); + ucAgiVer = (UINT_8) ((u4ArSysParam0 & BITS(6, 7)) >> 6); + u2HtClrMask = (UINT_16) ((u4ArSysParam0 & BITS(8, 15)) >> 8); + u2LegacyClrMask = (UINT_16) ((u4ArSysParam0 & BITS(16, 31)) >> 16); + +#if 0 + ucArCheckWindow = (UINT_8) (u4ArSysParam1 & BITS(0, 7)); + ucArPerForceRateDownPer = (UINT_8) ((u4ArSysParam1 & BITS(8, 15)) >> 8); + ucArPerH = (UINT_8) ((u4ArSysParam1 & BITS(16, 23)) >> 16); + ucArPerL = (UINT_8) ((u4ArSysParam1 & BITS(24, 31)) >> 24); +#endif + + ucArCheckWindow = (UINT_8) (u4ArSysParam1 & BITS(0, 7)); + ucArPerForceRateDownPer = (UINT_8) (((u4ArSysParam1 >> 8) & BITS(0, 7))); + ucArPerH = (UINT_8) (((u4ArSysParam1 >> 16) & BITS(0, 7))); + ucArPerL = (UINT_8) (((u4ArSysParam1 >> 24) & BITS(0, 7))); + + DBGLOG(NIC, INFO, "ArParam %u %u %u %u, ArVer %d AbwVer %d AgiVer %d\n", + u4ArSysParam0, u4ArSysParam1, u4ArSysParam2, u4ArSysParam3, + ucArVer, ucAbwVer, ucAgiVer); + DBGLOG(NIC, INFO, "HtMask %x LegacyMask %x, CheckWin %u RateDownPer %u PerH %u PerL %u\n", + u2HtClrMask, u2LegacyClrMask, 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'; + + LOG_FUNC("[%s][wifi][Firmware] Assert at \"%s\" #%u\n\n", NIC_NAME, aucAssertFile, line); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to update Link Quality information +* +* @param prAdapter Pointer of Adapter Data Structure +* ucBssIndex +* prEventLinkQuality +* cRssi +* cLinkQuality +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicUpdateLinkQuality(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN P_EVENT_LINK_QUALITY_V2 prEventLinkQuality) +{ + INT_8 cRssi; + UINT_16 u2AdjustRssi = 10; + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= MAX_BSS_INDEX); + ASSERT(prEventLinkQuality); + + switch (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType) { + case NETWORK_TYPE_AIS: + if (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->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) { + /* ranged from (-128 ~ 30) in unit of dBm */ + cRssi = prEventLinkQuality->rLq[ucBssIndex].cRssi; + cRssi = (INT_8) (((INT_16) (cRssi) * u2AdjustRssi) / 10); + DBGLOG(RLM, INFO, + "Rssi=%d, NewRssi=%d\n", prEventLinkQuality->rLq[ucBssIndex].cRssi, cRssi); + nicUpdateRSSI(prAdapter, ucBssIndex, cRssi, + prEventLinkQuality->rLq[ucBssIndex].cLinkQuality); + } + + if (prAdapter->fgIsLinkRateValid == FALSE + || (kalGetTimeTick() - prAdapter->rLinkRateUpdateTime) > CFG_LINK_QUALITY_VALID_PERIOD) { + nicUpdateLinkSpeed(prAdapter, ucBssIndex, + prEventLinkQuality->rLq[ucBssIndex].u2LinkSpeed); + } + + } + break; + +#if 0 /* #if CFG_ENABLE_WIFI_DIRECT && CFG_SUPPORT_P2P_RSSI_QUERY */ + case NETWORK_TYPE_P2P: + 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, ucBssIndex, prEventLQEx->cRssiP2P, prEventLQEx->cLinkQualityP2P); + } + break; +#endif + default: + break; + + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to update RSSI and Link Quality information +* +* @param prAdapter Pointer of Adapter Data Structure +* ucBssIndex +* cRssi +* cLinkQuality +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicUpdateRSSI(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN INT_8 cRssi, IN INT_8 cLinkQuality) +{ + ASSERT(prAdapter); + ASSERT(ucBssIndex <= MAX_BSS_INDEX); + + switch (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType) { + case NETWORK_TYPE_AIS: + if (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->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 && CFG_SUPPORT_P2P_RSSI_QUERY + case NETWORK_TYPE_P2P: + 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 + default: + break; + + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to update Link Quality information +* +* @param prAdapter Pointer of Adapter Data Structure +* ucBssIndex +* prEventLinkQuality +* cRssi +* cLinkQuality +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicUpdateLinkSpeed(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN UINT_16 u2LinkSpeed) +{ + ASSERT(prAdapter); + ASSERT(ucBssIndex <= MAX_BSS_INDEX); + + switch (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType) { + case NETWORK_TYPE_AIS: + if (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + /* buffer statistics for further query */ + prAdapter->fgIsLinkRateValid = TRUE; + prAdapter->rLinkRateUpdateTime = kalGetTimeTick(); + + prAdapter->rLinkQuality.u2LinkSpeed = u2LinkSpeed; + } + break; + + default: + break; + + } + +} + +#if CFG_SUPPORT_RDD_TEST_MODE +WLAN_STATUS nicUpdateRddTestMode(IN P_ADAPTER_T prAdapter, IN P_CMD_RDD_CH_T prRddChParam) +{ + DEBUGFUNC("nicUpdateRddTestMode.\n"); + + ASSERT(prAdapter); + +/* aisFsmScanRequest(prAdapter, NULL); */ + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RDD_CH, + TRUE, + FALSE, FALSE, NULL, NULL, sizeof(CMD_RDD_CH_T), (PUINT_8) prRddChParam, NULL, 0); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to apply network address setting to +* both OS side and firmware domain +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS nicApplyNetworkAddress(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i; + + ASSERT(prAdapter); + + /* copy to adapter */ + COPY_MAC_ADDR(prAdapter->rMyMacAddr, prAdapter->rWifiVar.aucMacAddress); + + /* 4 <3> Update new MAC address to all 3 networks */ + 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; + +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { + for (i = 0; i < BSS_INFO_NUM; i++) { + if (prAdapter->rWifiVar.arBssInfoPool[i].eNetworkType == NETWORK_TYPE_P2P) { + COPY_MAC_ADDR(prAdapter->rWifiVar.arBssInfoPool[i].aucOwnMacAddr, + prAdapter->rWifiVar.aucDeviceAddress); + } + } + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + for (i = 0; i < BSS_INFO_NUM; i++) { + if (prAdapter->rWifiVar.arBssInfoPool[i].eNetworkType == NETWORK_TYPE_BOW) { + COPY_MAC_ADDR(prAdapter->rWifiVar.arBssInfoPool[i].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 WLAN_STATUS_SUCCESS; +} + +UINT_8 nicGetChipHwVer(VOID) +{ + return mtk_wcn_wmt_ic_info_get(WMTCHIN_HWVER) & BITS(0, 7); +} + +UINT_8 nicGetChipSwVer(VOID) +{ + return mtk_wcn_wmt_ic_info_get(WMTCHIN_FWVER) & BITS(0, 7); +} + +UINT_8 nicGetChipFactoryVer(VOID) +{ + return (mtk_wcn_wmt_ic_info_get(WMTCHIN_FWVER) & BITS(8, 11)) >> 8; +} + +UINT_8 nicGetChipEcoVer(VOID) +{ + P_ECO_INFO_T prEcoInfo; + UINT_8 ucEcoVer, ucMaxEcoVer; + UINT_8 ucCurSwVer, ucCurHwVer, ucCurFactoryVer; + + ucCurSwVer = nicGetChipSwVer(); + ucCurHwVer = nicGetChipHwVer(); + ucCurFactoryVer = nicGetChipFactoryVer(); + + ucMaxEcoVer = (sizeof(g_arEcoVersionTable) / sizeof(ECO_INFO_T)); + + for (ucEcoVer = 0; ucEcoVer < ucMaxEcoVer; ucEcoVer++) { + /* Get ECO info from table */ + prEcoInfo = (P_ECO_INFO_T) &(g_arEcoVersionTable[ucEcoVer]); + + if ((prEcoInfo->ucRomVer == ucCurSwVer) && + (prEcoInfo->ucHwVer == ucCurHwVer) && (prEcoInfo->ucFactoryVer == ucCurFactoryVer)) { + + return ucEcoVer + 1; + } + } + + DBGLOG(INIT, INFO, + "Cannot get ECO version for SwVer[0x%02x]HwVer[0x%02x]FactoryVer[0x%1x],recognize as latest version[E%u]\n", + ucCurSwVer, ucCurHwVer, ucCurFactoryVer, ucEcoVer); + + return ucEcoVer; +} + +BOOLEAN nicIsEcoVerEqualTo(UINT_8 ucEcoVer) +{ + P_ECO_INFO_T prEcoInfo; + UINT_8 ucMaxEcoVer; + + /* Sanity check for ECO table size */ + /* Acceptable ECO version: + * (ucEcoVer > 0) && (ucEcoVer <= Eco table size) + */ + + ucMaxEcoVer = (sizeof(g_arEcoVersionTable) / sizeof(ECO_INFO_T)); + + /* Unknown ECO version */ + if ((ucEcoVer > ucMaxEcoVer) || (ucEcoVer == 0)) + return FALSE; + + /* Get ECO info from table */ + prEcoInfo = (P_ECO_INFO_T) &(g_arEcoVersionTable[ucEcoVer - 1]); + + /* Check HW version */ + if (prEcoInfo->ucHwVer != nicGetChipHwVer()) + return FALSE; + + /* Check ROM version */ + if (prEcoInfo->ucRomVer != nicGetChipSwVer()) + return FALSE; + + /* Check factory version */ + if (prEcoInfo->ucFactoryVer != nicGetChipFactoryVer()) + return FALSE; + + return TRUE; +} + +BOOLEAN nicIsEcoVerEqualOrLaterTo(UINT_8 ucEcoVer) +{ + P_ECO_INFO_T prEcoInfo; + UINT_8 ucMaxEcoVer; + + /* Sanity check for ECO table size */ + /* Acceptable ECO version: + * (ucEcoVer > 0) && (ucEcoVer <= Eco table size) + */ + + ucMaxEcoVer = (sizeof(g_arEcoVersionTable) / sizeof(ECO_INFO_T)); + + if (ucEcoVer == 0) + return TRUE; + + /* Unknown ECO version */ + if (ucEcoVer > ucMaxEcoVer) + return FALSE; + + /* Get ECO info from table */ + prEcoInfo = (P_ECO_INFO_T) &(g_arEcoVersionTable[ucEcoVer - 1]); + + /* Check HW version */ + if (prEcoInfo->ucHwVer > nicGetChipHwVer()) + return FALSE; + + /* Check ROM version */ + if (prEcoInfo->ucRomVer > nicGetChipSwVer()) + return FALSE; + + /* Check factory version */ + if (prEcoInfo->ucFactoryVer > nicGetChipFactoryVer()) + return FALSE; + + return TRUE; +} + +WLAN_STATUS nicSetUapsdParam(IN P_ADAPTER_T prAdapter, + IN P_PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T prUapsdParams, IN ENUM_NETWORK_TYPE_T eNetworkTypeIdx) +{ + CMD_CUSTOM_UAPSD_PARAM_STRUCT_T rCmdUapsdParam; + P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo; + P_BSS_INFO_T prBssInfo; + WLAN_STATUS ret; + + DEBUGFUNC("nicSetUApsdParam"); + + ASSERT(prAdapter); + ASSERT(prUapsdParams); + + if (eNetworkTypeIdx >= NETWORK_TYPE_NUM) { + DBGLOG(NIC, ERROR, "nicSetUApsdParam Invalid eNetworkTypeIdx\n"); + return WLAN_STATUS_FAILURE; + } + + prBssInfo = prAdapter->aprBssInfo[eNetworkTypeIdx]; + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + + kalMemZero(&rCmdUapsdParam, sizeof(CMD_CUSTOM_UAPSD_PARAM_STRUCT_T)); + + rCmdUapsdParam.fgEnAPSD = prUapsdParams->fgEnAPSD; + rCmdUapsdParam.fgEnAPSD_AcBe = prUapsdParams->fgEnAPSD_AcBe; + rCmdUapsdParam.fgEnAPSD_AcBk = prUapsdParams->fgEnAPSD_AcBk; + rCmdUapsdParam.fgEnAPSD_AcVo = prUapsdParams->fgEnAPSD_AcVo; + rCmdUapsdParam.fgEnAPSD_AcVi = prUapsdParams->fgEnAPSD_AcVi; + rCmdUapsdParam.ucMaxSpLen = prUapsdParams->ucMaxSpLen; + + /* Fill BmpDeliveryAC and BmpTriggerAC by UapsdParams */ + prPmProfSetupInfo->ucBmpDeliveryAC = + ((prUapsdParams->fgEnAPSD_AcBe << 0) | + (prUapsdParams->fgEnAPSD_AcBk << 1) | + (prUapsdParams->fgEnAPSD_AcVi << 2) | + (prUapsdParams->fgEnAPSD_AcVo << 3)); + + prPmProfSetupInfo->ucBmpTriggerAC = + ((prUapsdParams->fgEnAPSD_AcBe << 0) | + (prUapsdParams->fgEnAPSD_AcBk << 1) | + (prUapsdParams->fgEnAPSD_AcVi << 2) | + (prUapsdParams->fgEnAPSD_AcVo << 3)); + + prPmProfSetupInfo->ucUapsdSp = prUapsdParams->ucMaxSpLen; + + DBGLOG(NIC, INFO, "nicSetUApsdParam EnAPSD[%d] Be[%d] Bk[%d] Vo[%d] Vi[%d] SPLen[%d]\n", + rCmdUapsdParam.fgEnAPSD, rCmdUapsdParam.fgEnAPSD_AcBe, rCmdUapsdParam.fgEnAPSD_AcBk, + rCmdUapsdParam.fgEnAPSD_AcVo, rCmdUapsdParam.fgEnAPSD_AcVi, rCmdUapsdParam.ucMaxSpLen); + + switch (eNetworkTypeIdx) { + case NETWORK_TYPE_AIS: + ret = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_UAPSD_PARAM, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_CUSTOM_UAPSD_PARAM_STRUCT_T), + (PUINT_8)&rCmdUapsdParam, NULL, 0); + break; + + case NETWORK_TYPE_P2P: + ret = wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_UAPSD_PARAM, + prBssInfo->ucBssIndex, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_CUSTOM_UAPSD_PARAM_STRUCT_T), + (PUINT_8)&rCmdUapsdParam, NULL, 0); + break; + + default: + ret = WLAN_STATUS_FAILURE; + break; + } + + return ret; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/nic_cmd_event.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/nic_cmd_event.c new file mode 100644 index 0000000000000..02bbb835e42e7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/nic_cmd_event.c @@ -0,0 +1,2263 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_cmd_event.c#3 + */ + +/* + * ! \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. + */ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" +#include "gl_ate_agent.h" + +#ifdef FW_CFG_SUPPORT +#include "fwcfg.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 +******************************************************************************** +*/ +UINT_32 u4IQDataIndex; +UINT_32 u4IQDataOffset; +VOID nicCmdEventQueryMcrRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_PARAM_CUSTOM_MCR_RW_STRUCT_T prMcrRdInfo; + P_GLUE_INFO_T prGlueInfo; + P_CMD_ACCESS_REG prCmdAccessReg; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prCmdAccessReg = (P_CMD_ACCESS_REG) (pucEventBuf); + + u4QueryInfoLen = sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T); + + prMcrRdInfo = (P_PARAM_CUSTOM_MCR_RW_STRUCT_T) prCmdInfo->pvInformationBuffer; + prMcrRdInfo->u4McrOffset = prCmdAccessReg->u4Address; + prMcrRdInfo->u4McrData = prCmdAccessReg->u4Data; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + + return; + +} + +#if CFG_SUPPORT_QA_TOOL +VOID nicCmdEventQueryRxStatistics(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_PARAM_CUSTOM_ACCESS_RX_STAT prRxStatistics; + P_EVENT_ACCESS_RX_STAT prEventAccessRxStat; + UINT_32 u4QueryInfoLen, i; + P_GLUE_INFO_T prGlueInfo; + PUINT_32 prElement; + UINT_32 u4Temp; + /* P_CMD_ACCESS_RX_STAT prCmdRxStat, prRxStat; */ + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventAccessRxStat = (P_EVENT_ACCESS_RX_STAT) (pucEventBuf); + + prRxStatistics = (P_PARAM_CUSTOM_ACCESS_RX_STAT) prCmdInfo->pvInformationBuffer; + prRxStatistics->u4SeqNum = prEventAccessRxStat->u4SeqNum; + prRxStatistics->u4TotalNum = prEventAccessRxStat->u4TotalNum; + + u4QueryInfoLen = sizeof(CMD_ACCESS_RX_STAT); + + if (prRxStatistics->u4SeqNum == u4RxStatSeqNum) { + prElement = &g_HqaRxStat.MAC_FCS_Err; + for (i = 0; i < sizeof(PARAM_RX_STAT_T)/4; i++) { + u4Temp = ntohl(prEventAccessRxStat->au4Buffer[i]); + kalMemCopy(prElement, &u4Temp, 4); + + if (i < ((sizeof(PARAM_RX_STAT_T)/4) - 1)) + prElement++; + } + /* + * for (i = 0; i < HQA_RX_STATISTIC_NUM; i++) { + * u4Temp = ntohl(prEventAccessRxStat->au4Buffer[i]); + * kalMemCopy(prElement, &u4Temp, 4); + + * if (i < (HQA_RX_STATISTIC_NUM - 1)) + * prElement++; + * } + */ + } + + DBGLOG(INIT, ERROR, + "RX Statistics Test SeqNum = %d, TotalNum = %d, Buffer [0] = %d, Buffer [1] = %d\n", + (unsigned int)prEventAccessRxStat->u4SeqNum, (unsigned int)prEventAccessRxStat->u4TotalNum, + (unsigned int)prEventAccessRxStat->au4Buffer[0], + (unsigned int)prEventAccessRxStat->au4Buffer[1]); + + DBGLOG(INIT, ERROR, "Buffer [66] = %d, Buffer [67] = %d\n", + (unsigned int)prEventAccessRxStat->au4Buffer[66], + (unsigned int)prEventAccessRxStat->au4Buffer[67]); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} + +#if CFG_SUPPORT_TX_BF +VOID nicCmdEventPfmuDataRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_GLUE_INFO_T prGlueInfo; + P_PFMU_DATA prEventPfmuDataRead = NULL; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventPfmuDataRead = (P_PFMU_DATA) (pucEventBuf); + + u4QueryInfoLen = sizeof(PFMU_DATA); + + g_rPfmuData = *prEventPfmuDataRead; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + + DBGLOG(INIT, INFO, "=========== Before ===========\n"); + if (prEventPfmuDataRead != NULL) { + DBGLOG(INIT, INFO, "u2Phi11 = 0x%x\n", prEventPfmuDataRead->rField.u2Phi11); + DBGLOG(INIT, INFO, "ucPsi21 = 0x%x\n", prEventPfmuDataRead->rField.ucPsi21); + DBGLOG(INIT, INFO, "u2Phi21 = 0x%x\n", prEventPfmuDataRead->rField.u2Phi21); + DBGLOG(INIT, INFO, "ucPsi31 = 0x%x\n", prEventPfmuDataRead->rField.ucPsi31); + DBGLOG(INIT, INFO, "u2Phi31 = 0x%x\n", prEventPfmuDataRead->rField.u2Phi31); + DBGLOG(INIT, INFO, "ucPsi41 = 0x%x\n", prEventPfmuDataRead->rField.ucPsi41); + DBGLOG(INIT, INFO, "u2Phi22 = 0x%x\n", prEventPfmuDataRead->rField.u2Phi22); + DBGLOG(INIT, INFO, "ucPsi32 = 0x%x\n", prEventPfmuDataRead->rField.ucPsi32); + DBGLOG(INIT, INFO, "u2Phi32 = 0x%x\n", prEventPfmuDataRead->rField.u2Phi32); + DBGLOG(INIT, INFO, "ucPsi42 = 0x%x\n", prEventPfmuDataRead->rField.ucPsi42); + DBGLOG(INIT, INFO, "u2Phi33 = 0x%x\n", prEventPfmuDataRead->rField.u2Phi33); + DBGLOG(INIT, INFO, "ucPsi43 = 0x%x\n", prEventPfmuDataRead->rField.ucPsi43); + DBGLOG(INIT, INFO, "u2dSNR00 = 0x%x\n", prEventPfmuDataRead->rField.u2dSNR00); + DBGLOG(INIT, INFO, "u2dSNR01 = 0x%x\n", prEventPfmuDataRead->rField.u2dSNR01); + DBGLOG(INIT, INFO, "u2dSNR02 = 0x%x\n", prEventPfmuDataRead->rField.u2dSNR02); + DBGLOG(INIT, INFO, "u2dSNR03 = 0x%x\n", prEventPfmuDataRead->rField.u2dSNR03); + } +} + +VOID nicCmdEventPfmuTagRead(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_PFMU_TAG_READ_T prEventPfmuTagRead = NULL; + P_PARAM_CUSTOM_PFMU_TAG_READ_STRUCT_T prPfumTagRead = NULL; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (!prCmdInfo->fgIsOid) { + DBGLOG(NIC, INFO, "Not a OID, bypass\n"); + return; + } + prGlueInfo = prAdapter->prGlueInfo; + prEventPfmuTagRead = (P_EVENT_PFMU_TAG_READ_T) (pucEventBuf); + + prPfumTagRead = (P_PARAM_CUSTOM_PFMU_TAG_READ_STRUCT_T) prCmdInfo->pvInformationBuffer; + + kalMemCopy(prPfumTagRead, prEventPfmuTagRead, sizeof(EVENT_PFMU_TAG_READ_T)); + + u4QueryInfoLen = sizeof(CMD_TXBF_ACTION_T); + + g_rPfmuTag1 = prPfumTagRead->ru4TxBfPFMUTag1; + g_rPfmuTag2 = prPfumTagRead->ru4TxBfPFMUTag2; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + DBGLOG(INIT, INFO, "========================== (R)Tag1 info ==========================\n"); + + DBGLOG(INIT, INFO, " Row data0 : %x, Row data1 : %x, Row data2 : %x, Row data3 : %x\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.au4RawData[0], + prEventPfmuTagRead->ru4TxBfPFMUTag1.au4RawData[1], + prEventPfmuTagRead->ru4TxBfPFMUTag1.au4RawData[2], prEventPfmuTagRead->ru4TxBfPFMUTag1.au4RawData[3]); + DBGLOG(INIT, INFO, "ProfileID = %d Invalid status = %d\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucProfileID, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucInvalidProf); + DBGLOG(INIT, INFO, "0:iBF / 1:eBF = %d\n", prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucTxBf); + DBGLOG(INIT, INFO, "0:SU / 1:MU = %d\n", prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucSU_MU); + DBGLOG(INIT, INFO, "DBW(0/1/2/3 BW20/40/80/160NC) = %d\n", prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucDBW); + DBGLOG(INIT, INFO, "RMSD = %d\n", prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucRMSD); + DBGLOG(INIT, INFO, "Nrow = %d, Ncol = %d, Ng = %d, LM = %d\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucNrow, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucNcol, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucNgroup, prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucLM); + DBGLOG(INIT, INFO, "Mem1(%d, %d), Mem2(%d, %d), Mem3(%d, %d), Mem4(%d, %d)\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr1ColIdx, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr1RowIdx, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr2ColIdx, + (prEventPfmuTagRead->ru4TxBfPFMUTag1. + rField.ucMemAddr2RowIdx | (prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr2RowIdxMsb << 5)), + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr3ColIdx, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr3RowIdx, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr4ColIdx, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr4RowIdx); + DBGLOG(INIT, INFO, "SNR STS0=0x%x, SNR STS1=0x%x, SNR STS2=0x%x, SNR STS3=0x%x\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucSNR_STS0, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucSNR_STS1, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucSNR_STS2, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucSNR_STS3); + DBGLOG(INIT, INFO, "===============================================================\n"); + + DBGLOG(INIT, INFO, "========================== (R)Tag2 info ==========================\n"); + DBGLOG(INIT, INFO, " Row data0 : %x, Row data1 : %x, Row data2 : %x\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.au4RawData[0], + prEventPfmuTagRead->ru4TxBfPFMUTag2.au4RawData[1], prEventPfmuTagRead->ru4TxBfPFMUTag2.au4RawData[2]); + DBGLOG(INIT, INFO, "Smart Ant Cfg = %d\n", prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.u2SmartAnt); + DBGLOG(INIT, INFO, "SE index = %d\n", prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucSEIdx); + DBGLOG(INIT, INFO, "RMSD Threshold = %d\n", prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucRMSDThd); + DBGLOG(INIT, INFO, "MCS TH L1SS = %d, S1SS = %d, L2SS = %d, S2SS = %d\n" + "L3SS = %d, S3SS = %d\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucMCSThL1SS, + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucMCSThS1SS, + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucMCSThL2SS, + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucMCSThS2SS, + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucMCSThL3SS, + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucMCSThS3SS); + DBGLOG(INIT, INFO, "iBF lifetime limit(unit:4ms) = 0x%x\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.uciBfTimeOut); + DBGLOG(INIT, INFO, "iBF desired DBW = %d\n 0/1/2/3 : BW20/40/80/160NC\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.uciBfDBW); + DBGLOG(INIT, INFO, "iBF desired Ncol = %d\n 0/1/2 : Ncol = 1 ~ 3\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.uciBfNcol); + DBGLOG(INIT, INFO, "iBF desired Nrow = %d\n 0/1/2/3 : Nrow = 1 ~ 4\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.uciBfNrow); + DBGLOG(INIT, INFO, "===============================================================\n"); + +} + +#endif /* CFG_SUPPORT_TX_BF */ +#if CFG_SUPPORT_MU_MIMO +VOID nicCmdEventGetQd(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_HQA_GET_QD prEventHqaGetQd; + UINT_32 i; + + P_PARAM_CUSTOM_GET_QD_STRUCT_T prGetQd = NULL; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (!prCmdInfo->fgIsOid) { + DBGLOG(NIC, INFO, "Not OID\n"); + return; + } + prGlueInfo = prAdapter->prGlueInfo; + prEventHqaGetQd = (P_EVENT_HQA_GET_QD) (pucEventBuf); + + prGetQd = (P_PARAM_CUSTOM_GET_QD_STRUCT_T) prCmdInfo->pvInformationBuffer; + + kalMemCopy(prGetQd, prEventHqaGetQd, sizeof(EVENT_HQA_GET_QD)); + + u4QueryInfoLen = sizeof(CMD_MUMIMO_ACTION_T); + + /* g_rPfmuTag1 = prPfumTagRead->ru4TxBfPFMUTag1; */ + /* g_rPfmuTag2 = prPfumTagRead->ru4TxBfPFMUTag2; */ + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + + DBGLOG(NIC, INFO, "event id : %x\n", prGetQd->u4EventId); + for (i = 0; i < 14; i++) + DBGLOG(NIC, INFO, "au4RawData[%d]: %x\n", i, prGetQd->au4RawData[i]); + +} + +VOID nicCmdEventGetCalcLq(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_HQA_GET_MU_CALC_LQ prEventHqaGetMuCalcLq; + UINT_32 i; + INT_32 *qRep = NULL; + + P_PARAM_CUSTOM_GET_MU_CALC_LQ_STRUCT_T prGetMuCalcLq = NULL; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (!prCmdInfo->fgIsOid) { + DBGLOG(NIC, INFO, "Not OID\n"); + return; + } + prGlueInfo = prAdapter->prGlueInfo; + prEventHqaGetMuCalcLq = (P_EVENT_HQA_GET_MU_CALC_LQ) (pucEventBuf); + + prGetMuCalcLq = (P_PARAM_CUSTOM_GET_MU_CALC_LQ_STRUCT_T) prCmdInfo->pvInformationBuffer; + + kalMemCopy(prGetMuCalcLq, prEventHqaGetMuCalcLq, sizeof(EVENT_HQA_GET_MU_CALC_LQ)); + + u4QueryInfoLen = sizeof(CMD_MUMIMO_ACTION_T); + + /* g_rPfmuTag1 = prPfumTagRead->ru4TxBfPFMUTag1; */ + /* g_rPfmuTag2 = prPfumTagRead->ru4TxBfPFMUTag2; */ + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + + DBGLOG(NIC, INFO, " event id : %x\n", prGetMuCalcLq->u4EventId); + for (i = 0; i < NUM_OF_USER; i++) { + qRep = &prGetMuCalcLq->rEntry.lq_report[i][0]; + DBGLOG(NIC, INFO, "lq_report[%d]:%x,%x,%x,%x,%x\n", i, qRep[0], qRep[1], qRep[2], qRep[3], qRep[4]); + } + +} + +VOID nicCmdEventGetCalcInitMcs(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_SHOW_GROUP_TBL_ENTRY prEventShowGroupTblEntry = NULL; + + P_PARAM_CUSTOM_SHOW_GROUP_TBL_ENTRY_STRUCT_T prShowGroupTbl; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (!prCmdInfo->fgIsOid) { + DBGLOG(NIC, INFO, "Not OID\n"); + return; + } + prGlueInfo = prAdapter->prGlueInfo; + prEventShowGroupTblEntry = (P_EVENT_SHOW_GROUP_TBL_ENTRY) (pucEventBuf); + + prShowGroupTbl = (P_PARAM_CUSTOM_SHOW_GROUP_TBL_ENTRY_STRUCT_T) prCmdInfo->pvInformationBuffer; + + kalMemCopy(prShowGroupTbl, prEventShowGroupTblEntry, sizeof(EVENT_SHOW_GROUP_TBL_ENTRY)); + + u4QueryInfoLen = sizeof(CMD_MUMIMO_ACTION_T); + + /* g_rPfmuTag1 = prPfumTagRead->ru4TxBfPFMUTag1; */ + /* g_rPfmuTag2 = prPfumTagRead->ru4TxBfPFMUTag2; */ + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + + DBGLOG(INIT, INFO, "========================== (R)Group table info ==========================\n"); + DBGLOG(INIT, INFO, " event id : %x\n", prEventShowGroupTblEntry->u4EventId); + DBGLOG(INIT, INFO, "index = %x numUser = %x\n", prEventShowGroupTblEntry->index, + prEventShowGroupTblEntry->numUser); + DBGLOG(INIT, INFO, "BW = %x NS0/1/ = %x/%x\n", prEventShowGroupTblEntry->BW, prEventShowGroupTblEntry->NS0, + prEventShowGroupTblEntry->NS1); + DBGLOG(INIT, INFO, "PFIDUser0/1 = %x/%x\n", prEventShowGroupTblEntry->PFIDUser0, + prEventShowGroupTblEntry->PFIDUser1); + DBGLOG(INIT, INFO, "fgIsShortGI = %x, fgIsUsed = %x, fgIsDisable = %x\n", prEventShowGroupTblEntry->fgIsShortGI, + prEventShowGroupTblEntry->fgIsUsed, prEventShowGroupTblEntry->fgIsDisable); + DBGLOG(INIT, INFO, "initMcsUser0/1 = %x/%x\n", prEventShowGroupTblEntry->initMcsUser0, + prEventShowGroupTblEntry->initMcsUser1); + DBGLOG(INIT, INFO, "dMcsUser0: 0/1/ = %x/%x\n", prEventShowGroupTblEntry->dMcsUser0, + prEventShowGroupTblEntry->dMcsUser1); + +} +#endif /* CFG_SUPPORT_MU_MIMO */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +VOID nicCmdEventQuerySwCtrlRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_PARAM_CUSTOM_SW_CTRL_STRUCT_T prSwCtrlInfo; + P_GLUE_INFO_T prGlueInfo; + P_CMD_SW_DBG_CTRL_T prCmdSwCtrl; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prCmdSwCtrl = (P_CMD_SW_DBG_CTRL_T) (pucEventBuf); + + u4QueryInfoLen = sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T); + + prSwCtrlInfo = (P_PARAM_CUSTOM_SW_CTRL_STRUCT_T) prCmdInfo->pvInformationBuffer; + prSwCtrlInfo->u4Id = prCmdSwCtrl->u4Id; + prSwCtrlInfo->u4Data = prCmdSwCtrl->u4Data; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + + return; + +} + +VOID nicCmdEventQueryChipConfig(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T prChipConfigInfo; + P_GLUE_INFO_T prGlueInfo; + P_CMD_CHIP_CONFIG_T prCmdChipConfig; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prCmdChipConfig = (P_CMD_CHIP_CONFIG_T) (pucEventBuf); + + u4QueryInfoLen = sizeof(PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T); + + if (prCmdInfo->u4InformationBufferLength < sizeof(PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T)) { + DBGLOG(REQ, INFO, + "Chip config u4InformationBufferLength %u is not valid (event)\n", + prCmdInfo->u4InformationBufferLength); + } + prChipConfigInfo = (P_PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T) prCmdInfo->pvInformationBuffer; + prChipConfigInfo->ucRespType = prCmdChipConfig->ucRespType; + prChipConfigInfo->u2MsgSize = prCmdChipConfig->u2MsgSize; + DBGLOG(REQ, INFO, "%s: RespTyep %u\n", __func__, prChipConfigInfo->ucRespType); + DBGLOG(REQ, INFO, "%s: u2MsgSize %u\n", __func__, prChipConfigInfo->u2MsgSize); + + if (prChipConfigInfo->u2MsgSize > CHIP_CONFIG_RESP_SIZE) { + DBGLOG(REQ, INFO, + "Chip config Msg Size %u is not valid (event)\n", prChipConfigInfo->u2MsgSize); + prChipConfigInfo->u2MsgSize = CHIP_CONFIG_RESP_SIZE; + } + kalMemCopy(prChipConfigInfo->aucCmd, prCmdChipConfig->aucCmd, prChipConfigInfo->u2MsgSize); + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + + return; + +} + +VOID nicCmdEventSetCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4InformationBufferLength, WLAN_STATUS_SUCCESS); + } + +} + +VOID nicCmdEventSetDisassociate(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); + } + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + +#if !defined(LINUX) + prAdapter->fgIsRadioOff = TRUE; +#endif + +} + +VOID nicCmdEventSetIpAddress(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4Count; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + u4Count = (prCmdInfo->u4SetInfoLen - OFFSET_OF(CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress)) + / sizeof(IPV4_NETWORK_ADDRESS); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress) + u4Count * + (OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + + sizeof(PARAM_NETWORK_ADDRESS_IP)), WLAN_STATUS_SUCCESS); + } + +} + +VOID nicCmdEventQueryRfTestATInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_TEST_STATUS prTestStatus, prQueryBuffer; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prTestStatus = (P_EVENT_TEST_STATUS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prQueryBuffer = (P_EVENT_TEST_STATUS) prCmdInfo->pvInformationBuffer; + + /* Memory copy length is depended on upper-layer */ + kalMemCopy(prQueryBuffer, prTestStatus, prCmdInfo->u4InformationBufferLength); + + u4QueryInfoLen = sizeof(EVENT_TEST_STATUS); + + /* Update Query Information Length */ + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} + +VOID nicCmdEventQueryLinkQuality(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + PARAM_RSSI rRssi, *prRssi; + P_EVENT_LINK_QUALITY prLinkQuality; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prLinkQuality = (P_EVENT_LINK_QUALITY) pucEventBuf; + + rRssi = (PARAM_RSSI) prLinkQuality->cRssi; /* ranged from (-128 ~ 30) in unit of dBm */ + + if (prAdapter->prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + if (rRssi > PARAM_WHQL_RSSI_MAX_DBM) + rRssi = PARAM_WHQL_RSSI_MAX_DBM; + else if (rRssi < PARAM_WHQL_RSSI_MIN_DBM) + rRssi = PARAM_WHQL_RSSI_MIN_DBM; + } else { + rRssi = PARAM_WHQL_RSSI_MIN_DBM; + } + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prRssi = (PARAM_RSSI *) prCmdInfo->pvInformationBuffer; + + kalMemCopy(prRssi, &rRssi, sizeof(PARAM_RSSI)); + u4QueryInfoLen = sizeof(PARAM_RSSI); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This routine is in response of OID_GEN_LINK_SPEED query request +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the pending command info +* @param pucEventBuf +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicCmdEventQueryLinkSpeed(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_LINK_QUALITY prLinkQuality; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4LinkSpeed; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prLinkQuality = (P_EVENT_LINK_QUALITY) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + pu4LinkSpeed = (PUINT_32) (prCmdInfo->pvInformationBuffer); + + *pu4LinkSpeed = prLinkQuality->u2LinkSpeed * 5000; + + u4QueryInfoLen = sizeof(UINT_32); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +VOID nicCmdEventQueryStatistics(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_PARAM_802_11_STATISTICS_STRUCT_T prStatistics; + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + /* link quality monitor */ + struct WIFI_LINK_QUALITY_INFO *prLinkQualityInfo; +#endif + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; + + 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; +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + prStatistics->rMdrdyCnt = prEventStatistics->rMdrdyCnt; + prStatistics->rChnlIdleCnt = prEventStatistics->rChnlIdleCnt; + + /* link quality monitor */ + prLinkQualityInfo = + &(prAdapter->rLinkQualityInfo); + + prLinkQualityInfo->u8TxRetryCount = + prStatistics->rRetryCount.QuadPart; + + prLinkQualityInfo->u8TxRtsFailCount = + prStatistics->rRTSFailureCount.QuadPart; + prLinkQualityInfo->u8TxAckFailCount = + prStatistics->rACKFailureCount.QuadPart; + prLinkQualityInfo->u8TxFailCount = prLinkQualityInfo->u8TxRtsFailCount + + prLinkQualityInfo->u8TxAckFailCount; + prLinkQualityInfo->u8TxTotalCount = + prStatistics->rTransmittedFragmentCount.QuadPart; + + prLinkQualityInfo->u8RxTotalCount = + prStatistics->rReceivedFragmentCount.QuadPart; + /* FW report is diff, driver count total */ + prLinkQualityInfo->u8RxErrCount += + prStatistics->rFCSErrorCount.QuadPart; + prLinkQualityInfo->u8MdrdyCount = + prStatistics->rMdrdyCnt.QuadPart; + prLinkQualityInfo->u8IdleSlotCount = + prStatistics->rChnlIdleCnt.QuadPart; + + wlanFinishCollectingLinkQuality(prGlueInfo); +#endif + if (prCmdInfo->fgIsOid) + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + +} + +VOID nicCmdEventEnterRfTest(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ +#define WAIT_FW_READY_RETRY_CNT 200 + + UINT_32 u4WHISR = 0, u4Value = 0; + UINT_16 au2TxCount[16]; + UINT_16 u2RetryCnt = 0; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + kalTakeVcoreAction(VCORE_ADD_HIGHER_REQ); + kalMayChangeVcore(); + /* [driver-land] */ + /* prAdapter->fgTestMode = TRUE; */ + if (prAdapter->fgTestMode) + prAdapter->fgTestMode = FALSE; + else + 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, TRUE); + + /* 1.1 clear pending Security / Management Frames */ + kalClearSecurityFrames(prAdapter->prGlueInfo); + kalClearMgmtFrames(prAdapter->prGlueInfo); + + /* 1.2 clear pending TX packet queued in glue layer */ + kalFlushPendingTxPackets(prAdapter->prGlueInfo); + + /* 2. Reset driver-domain FSMs */ + nicUninitMGMT(prAdapter); + + nicResetSystemService(prAdapter); + nicInitMGMT(prAdapter, NULL); + + /* 3. Disable Interrupt */ + HAL_INTR_DISABLE(prAdapter); + + /* 4. Block til firmware completed entering into RF test mode */ + kalMsleep(500); + while (1) { + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4Value); + + if (u4Value & WCIR_WLAN_READY) { + break; + } else if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE || + kalIsResetting() || u2RetryCnt >= WAIT_FW_READY_RETRY_CNT) { + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4SetInfoLen, WLAN_STATUS_NOT_SUPPORTED); + + } + return; + } + kalMsleep(10); + u2RetryCnt++; + } + + /* 5. Clear Interrupt Status */ + HAL_READ_INTR_STATUS(prAdapter, 4, (PUINT_8)&u4WHISR); + if (HAL_IS_TX_DONE_INTR(u4WHISR)) + HAL_READ_TX_RELEASED_COUNT(prAdapter, au2TxCount); + /* 6. Reset TX Counter */ + nicTxResetResource(prAdapter); + + /* 7. Re-enable Interrupt */ + HAL_INTR_ENABLE(prAdapter); + + /* 8. completion indication */ + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, WLAN_STATUS_SUCCESS); + } +#if CFG_SUPPORT_NVRAM + /* 9. load manufacture data */ + if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) + wlanLoadManufactureData(prAdapter, kalGetConfiguration(prAdapter->prGlueInfo)); + else + DBGLOG(REQ, WARN, "%s: load manufacture data fail\n", __func__); +#endif + +} + +VOID nicCmdEventLeaveRfTest(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ +#define WAIT_FW_READY_RETRY_CNT 200 + + UINT_32 u4WHISR = 0, u4Value = 0; + UINT_16 au2TxCount[16]; + UINT_16 u2RetryCnt = 0; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + kalTakeVcoreAction(VCORE_RESTORE_DEF); + kalTakeVcoreAction(VCORE_DEC_HIGHER_REQ); + /* 1. Disable Interrupt */ + HAL_INTR_DISABLE(prAdapter); + + /* 2. Block til firmware completed leaving from RF test mode */ + kalMsleep(500); + while (1) { + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4Value); + + if (u4Value & WCIR_WLAN_READY) { + break; + } else if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE || + kalIsResetting() || u2RetryCnt >= WAIT_FW_READY_RETRY_CNT) { + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4SetInfoLen, WLAN_STATUS_NOT_SUPPORTED); + + } + return; + } + u2RetryCnt++; + 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, au2TxCount); + /* 4. Reset TX Counter */ + nicTxResetResource(prAdapter); + + /* 5. Re-enable Interrupt */ + HAL_INTR_ENABLE(prAdapter); + + /* 6. set driver-land variable */ + prAdapter->fgTestMode = FALSE; + prAdapter->fgIcapMode = FALSE; + + /* 7. completion indication */ + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, WLAN_STATUS_SUCCESS); + } + + /* 8. Indicate as disconnected */ + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_DISCONNECTED) { + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + + prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); + } +#if CFG_SUPPORT_NVRAM + /* 9. load manufacture data */ + if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) + wlanLoadManufactureData(prAdapter, kalGetConfiguration(prAdapter->prGlueInfo)); + else + DBGLOG(REQ, WARN, "%s: load manufacture data fail\n", __func__); +#endif + + /* 10. Override network address */ + wlanUpdateNetworkAddress(prAdapter); + +} + +VOID nicCmdEventQueryMcastAddr(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_GLUE_INFO_T prGlueInfo; + P_EVENT_MAC_MCAST_ADDR prEventMacMcastAddr; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventMacMcastAddr = (P_EVENT_MAC_MCAST_ADDR) (pucEventBuf); + + u4QueryInfoLen = prEventMacMcastAddr->u4NumOfGroupAddr * MAC_ADDR_LEN; + + /* buffer length check */ + if (prCmdInfo->u4InformationBufferLength < u4QueryInfoLen) { + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_BUFFER_TOO_SHORT); + } else { + kalMemCopy(prCmdInfo->pvInformationBuffer, + prEventMacMcastAddr->arAddress, + prEventMacMcastAddr->u4NumOfGroupAddr * MAC_ADDR_LEN); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + } +} + +VOID nicCmdEventQueryEepromRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T prEepromRdInfo; + P_GLUE_INFO_T prGlueInfo; + P_EVENT_ACCESS_EEPROM prEventAccessEeprom; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventAccessEeprom = (P_EVENT_ACCESS_EEPROM) (pucEventBuf); + + u4QueryInfoLen = sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T); + + prEepromRdInfo = (P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T) prCmdInfo->pvInformationBuffer; + prEepromRdInfo->ucEepromIndex = (UINT_8) (prEventAccessEeprom->u2Offset); + prEepromRdInfo->u2EepromData = prEventAccessEeprom->u2Data; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + + return; + +} + +VOID nicCmdEventSetMediaStreamMode(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + PARAM_MEDIA_STREAMING_INDICATION rParamMediaStreamIndication; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, WLAN_STATUS_SUCCESS); + } + + rParamMediaStreamIndication.rStatus.eStatusType = ENUM_STATUS_TYPE_MEDIA_STREAM_MODE; + rParamMediaStreamIndication.eMediaStreamMode = + prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode == 0 ? ENUM_MEDIA_STREAM_OFF : ENUM_MEDIA_STREAM_ON; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID)&rParamMediaStreamIndication, sizeof(PARAM_MEDIA_STREAMING_INDICATION)); +} + +VOID nicCmdEventSetStopSchedScan(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + /* + * DBGLOG(SCN, INFO, "--->nicCmdEventSetStopSchedScan\n" )); + */ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + /* + * DBGLOG(SCN, INFO, "<--kalSchedScanStopped\n" ); + */ + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4InformationBufferLength, WLAN_STATUS_SUCCESS); + } + + DBGLOG(SCN, INFO, "nicCmdEventSetStopSchedScan OID done, release lock and send event to uplayer\n"); + /* Due to dead lock issue, need to release the IO control before calling kernel APIs */ + kalSchedScanStopped(prAdapter->prGlueInfo, !prCmdInfo->fgIsOid); + +} + +/* 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_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + 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_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + 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); + + if (prCmdInfo->fgIsOid) + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_FAILURE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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, TRUE); + + /* 1.1 clear pending Security / Management Frames */ + kalClearSecurityFrames(prAdapter->prGlueInfo); + kalClearMgmtFrames(prAdapter->prGlueInfo); + + /* 1.2 clear pending TX packet queued in glue layer */ + kalFlushPendingTxPackets(prAdapter->prGlueInfo); + + /* 2. indicate for OID failure */ + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_FAILURE); +} + +#if CFG_SUPPORT_QA_TOOL +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when received dump memory event packet. +* transfer the memory data to the IQ format data and write into file +* +* @param prIQAry Pointer to the array store I or Q data. +* prDataLen The return data length - bytes +* u4IQ 0: get I data +* 1 : get Q data +* +* @return -1: open file error +* +*/ +/*----------------------------------------------------------------------------*/ +INT_32 GetIQData(INT_32 **prIQAry, UINT_32 *prDataLen, UINT_32 u4IQ, UINT_32 u4GetWf1) +{ +#if 1 + if (u4GetWf1 == 0) { + if (u4IQ == 0) + *prIQAry = &g_au4I0Data[0][u4IQDataOffset]; + else + *prIQAry = &g_au4Q0Data[0][u4IQDataOffset]; + u4IQDataOffset += 200; + if (u4IQDataOffset > u4IQDataIndex) { + *prDataLen = 0; + u4IQDataOffset = 0; + } else + *prDataLen = 800; + } else { + *prDataLen = 0; + u4IQDataIndex = 0; + u4IQDataOffset = 0; + } + DBGLOG(INIT, INFO, "QA_AGENT GetIQData prDataLen = %d\n", *prDataLen); + return 0; +#else + UINT_8 aucPath[50]; /* the path for iq data dump out */ + UINT_8 aucData[50]; /* iq data in string format */ + UINT_32 i = 0, j = 0, count = 0; + INT_32 ret = -1; + INT_32 rv; + struct file *file = NULL; + + i = 0; + + /* sprintf(aucPath, "/pattern.txt"); // CSD's Pattern */ + sprintf(aucPath, "/data/dump_out_001_WF0.txt"); + DBGLOG(INIT, INFO, "iCap Read Dump File dump_out_001_WF0.txt\n"); + /*sprintf(aucPath, "/data/dump_out_00007_WF%d.txt", u4GetWf1);*/ + + file = kalFileOpen(aucPath, O_RDONLY, 0); + + if ((file != NULL) && !IS_ERR(file)) { + *prIQAry = &g_au4IQData[g_u2DumpIndex][0]; + DBGLOG(INIT, INFO, "open /data/dump_out_001_WF0.txt success\n"); + /* read 1K data per time */ + for (i = 0; i < RTN_IQ_DATA_LEN / sizeof(UINT_32); + i++, g_au4Offset[u4GetWf1][u4IQ] += IQ_FILE_LINE_OFFSET) { + if (kalFileRead(file, g_au4Offset[u4GetWf1][u4IQ], aucData, IQ_FILE_IQ_STR_LEN) == 0) + break; + + count = 0; + + for (j = 0; j < 8; j++) { + if (aucData[j] != ' ') + aucData[count++] = aucData[j]; + } + + aucData[count] = '\0'; + + rv = kstrtoint(aucData, 0, &g_au4IQData[g_u2DumpIndex][i]); + } + *prDataLen = i * sizeof(UINT_32); + kalFileClose(file); + ret = 0; + } else { + DBGLOG(INIT, INFO, "open /data/dump_out_001_WF0.txt fail\n"); + } + DBGLOG(INIT, INFO, "QA_AGENT GetIQData i = %d, prDataLen = %d\n\n", i, *prDataLen); + return ret; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when received dump memory event packet. +* transfer the memory data to the IQ format data and write into file +* +* @param prEventDumpMem Pointer to the event dump memory structure. +* +* @return 0: SUCCESS, -1: FAIL +* +*/ +/*----------------------------------------------------------------------------*/ + +UINT_32 TsfRawData2IqFmt(P_EVENT_DUMP_MEM_T prEventDumpMem) +{ + static UINT_8 aucPathWF0[40]; /* the path for iq data dump out */ + static UINT_8 aucPathWF1[40]; /* the path for iq data dump out */ + static UINT_8 aucPathRAWWF0[40]; /* the path for iq data dump out */ + static UINT_8 aucPathRAWWF1[40]; /* the path for iq data dump out */ + PUINT_8 pucDataWF0; /* the data write into file */ + PUINT_8 pucDataWF1; /* the data write into file */ + PUINT_8 pucDataRAWWF0; /* the data write into file */ + PUINT_8 pucDataRAWWF1; /* the data write into file */ + UINT_32 u4SrcOffset; /* record the buffer offset */ + UINT_32 u4FmtLen = 0; /* bus format length */ + UINT_32 u4CpyLen = 0; + UINT_32 u4RemainByte; + BOOLEAN fgAppend; + /*INT_32 u4Iqc160WF0Q0, u4Iqc160WF1I1;*/ + + static UINT_8 ucDstOffset; /* for alignment. bcs we send 2KB data per packet,*/ + /*the data will not align in 12 bytes case. */ + static UINT_32 u4CurTimeTick; + + static ICAP_BUS_FMT icapBusData; + UINT_32 *ptr; + + pucDataWF0 = kmalloc(150, GFP_KERNEL); + pucDataWF1 = kmalloc(150, GFP_KERNEL); + pucDataRAWWF0 = kmalloc(150, GFP_KERNEL); + pucDataRAWWF1 = kmalloc(150, GFP_KERNEL); + + if ((!pucDataWF0) || (!pucDataWF1) || + (!pucDataRAWWF0) || (!pucDataRAWWF1)) { + DBGLOG(INIT, ERROR, "kmalloc failed.\n"); + kfree(pucDataWF0); + kfree(pucDataWF1); + kfree(pucDataRAWWF0); + kfree(pucDataRAWWF1); + return -1; + } + + fgAppend = TRUE; + + DBGLOG(RFTEST, INFO, "TsfRawData2IqFmt : prEventDumpMem->u4RemainLength = %u\n", + prEventDumpMem->u4RemainLength); + + if (prEventDumpMem->ucFragNum == 1) { + + u4CurTimeTick = kalGetTimeTick(); + /* Store memory dump into sdcard, + * path /sdcard/dump___.hex + */ +#if defined(LINUX) + + /*if blbist mkdir undre /data/blbist, the dump files wouls put on it */ + sprintf(aucPathWF0, "/dump_out_%05hd_WF0.txt", g_u2DumpIndex); + sprintf(aucPathWF1, "/dump_out_%05hd_WF1.txt", g_u2DumpIndex); + DBGLOG(RFTEST, INFO, "kalCheckPath(aucPathWF0) == %d\n", kalCheckPath(aucPathWF0)); + if (kalCheckPath(aucPathWF0) == -1) { + kalMemSet(aucPathWF0, 0x00, sizeof(aucPathWF0)); + sprintf(aucPathWF0, "/data/dump_out_%05hd_WF0.txt", g_u2DumpIndex); + } else + kalTrunkPath(aucPathWF0); + DBGLOG(RFTEST, INFO, "kalCheckPath(aucPathWF1) == %d\n", kalCheckPath(aucPathWF1)); + if (kalCheckPath(aucPathWF1) == -1) { + kalMemSet(aucPathWF1, 0x00, sizeof(aucPathWF1)); + sprintf(aucPathWF1, "/data/dump_out_%05hd_WF1.txt", g_u2DumpIndex); + } else + kalTrunkPath(aucPathWF1); + + sprintf(aucPathRAWWF0, "/dump_RAW_%05hd_WF0.txt", g_u2DumpIndex); + sprintf(aucPathRAWWF1, "/dump_RAW_%05hd_WF1.txt", g_u2DumpIndex); + DBGLOG(RFTEST, INFO, "kalCheckPath(aucPathRAWWF0) == %d\n", kalCheckPath(aucPathRAWWF0)); + if (kalCheckPath(aucPathRAWWF0) == -1) { + kalMemSet(aucPathRAWWF0, 0x00, sizeof(aucPathRAWWF0)); + sprintf(aucPathRAWWF0, "/data/dump_RAW_%05hd_WF0.txt", g_u2DumpIndex); + } else + kalTrunkPath(aucPathRAWWF0); + DBGLOG(RFTEST, INFO, "kalCheckPath(aucPathRAWWF1) == %d\n", kalCheckPath(aucPathRAWWF1)); + if (kalCheckPath(aucPathRAWWF1) == -1) { + kalMemSet(aucPathRAWWF1, 0x00, sizeof(aucPathRAWWF1)); + sprintf(aucPathRAWWF1, "/data/dump_RAW_%05hd_WF1.txt", g_u2DumpIndex); + } else + kalTrunkPath(aucPathRAWWF1); + +#else + kal_sprintf_ddk(aucPathWF0, sizeof(aucPathWF0), + u4CurTimeTick, + prEventDumpMem->u4Address, prEventDumpMem->u4Length + prEventDumpMem->u4RemainLength); + kal_sprintf_ddk(aucPathWF1, sizeof(aucPathWF1), + u4CurTimeTick, + prEventDumpMem->u4Address, prEventDumpMem->u4Length + prEventDumpMem->u4RemainLength); +#endif + /* fgAppend = FALSE; */ + } + + ptr = (PUINT_32)(&prEventDumpMem->aucBuffer[0]); + DBGLOG(RFTEST, INFO, ": ==> (prEventDumpMem->eIcapContent = %x)\n", prEventDumpMem->eIcapContent); + /*prEventDumpMem->eIcapContent = ICAP_CONTENT_ADC;*/ + + for (u4SrcOffset = 0, u4RemainByte = prEventDumpMem->u4Length; u4RemainByte > 0;) { + u4FmtLen = 4; + if (u4RemainByte & 0x80000000) { + u4RemainByte = 0; + u4CpyLen = 0; + } else { + u4CpyLen = (u4RemainByte >= u4FmtLen) ? u4FmtLen : u4RemainByte; + } + + DBGLOG(RFTEST, TRACE, "TsfRawData2IqFmt : u4CpyLen = %u\n", u4CpyLen); + + memcpy(&icapBusData + ucDstOffset, &prEventDumpMem->aucBuffer[0] + u4SrcOffset, u4CpyLen); + if (prEventDumpMem->eIcapContent == ICAP_CONTENT_FIIQ || + prEventDumpMem->eIcapContent == ICAP_CONTENT_FDIQ) { + /* sprintf(pucDataWF0, "%8d,%8d\n", + *icapBusData.rIqcBusData.u4Iqc0I, icapBusData.rIqcBusData.u4Iqc0Q); + */ + if (icapBusData.rIqcBusData.u4Iqc0I & (1<<10)) + g_au4I0Data[0][u4IQDataIndex] = (UINT_32)icapBusData.rIqcBusData.u4Iqc0I | 0xFFFFF800; + else + g_au4I0Data[0][u4IQDataIndex] = icapBusData.rIqcBusData.u4Iqc0I; + + if (icapBusData.rIqcBusData.u4Iqc0Q & (1<<10)) + g_au4Q0Data[0][u4IQDataIndex] = (UINT_32)icapBusData.rIqcBusData.u4Iqc0Q | 0xFFFFF800; + else + g_au4Q0Data[0][u4IQDataIndex] = icapBusData.rIqcBusData.u4Iqc0Q; + } else if (prEventDumpMem->eIcapContent == ICAP_CONTENT_SPECTRUM) { + sprintf(pucDataWF0, "%8d,%8d\n", icapBusData.rSpectrumBusData.u4DcocI, + icapBusData.rSpectrumBusData.u4DcocQ); + } else if (prEventDumpMem->eIcapContent == ICAP_CONTENT_ADC) { + if (icapBusData.rPackedAdcBusData.u4AdcI0T0 & (1<<10)) + g_au4I0Data[0][u4IQDataIndex] = + (UINT_32)icapBusData.rPackedAdcBusData.u4AdcI0T0 | 0xFFFFFC00; + else + g_au4I0Data[0][u4IQDataIndex] = icapBusData.rPackedAdcBusData.u4AdcI0T0; + + if (icapBusData.rPackedAdcBusData.u4AdcQ0T0 & (1<<10)) + g_au4Q0Data[0][u4IQDataIndex] = + (UINT_32)icapBusData.rPackedAdcBusData.u4AdcQ0T0 | 0xFFFFFC00; + else + g_au4Q0Data[0][u4IQDataIndex] = icapBusData.rPackedAdcBusData.u4AdcQ0T0; + } else if (prEventDumpMem->eIcapContent == ICAP_CONTENT_TOAE) { + /* actually, this is DCOC. we take TOAE as DCOC */ + sprintf(pucDataWF0, "%8d,%8d\n", icapBusData.rAdcBusData.u4Dcoc0I, + icapBusData.rAdcBusData.u4Dcoc0Q); + sprintf(pucDataWF1, "%8d,%8d\n", icapBusData.rAdcBusData.u4Dcoc1I, + icapBusData.rAdcBusData.u4Dcoc1Q); + } +#if 0 + if (u4CpyLen == u4FmtLen) {/* the data format is complete */ + DBGLOG(RFTEST, INFO, "pucDataWF0 : %s\n", pucDataWF0); + /* DBGLOG(RFTEST, INFO, "pucDataWF1 : %s\n", pucDataWF1); */ + + /* kalWriteToFile(aucPathWF0, fgAppend, pucDataWF0, strlen(pucDataWF0)); */ + /* kalWriteToFile(aucPathWF1, fgAppend, pucDataWF1, strlen(pucDataWF1)); */ + } +#endif + ptr = (PUINT_32)(&prEventDumpMem->aucBuffer[0] + u4SrcOffset); + sprintf(pucDataRAWWF0, "%08x%08x%08x\n", *(ptr + 2), *(ptr + 1), *ptr); + /* kalWriteToFile(aucPathRAWWF0, fgAppend, pucDataRAWWF0, strlen(pucDataRAWWF0)); */ + /* kalWriteToFile(aucPathRAWWF1, fgAppend, pucDataRAWWF1, strlen(pucDataRAWWF1)); */ + + u4IQDataIndex += 1; + u4RemainByte -= u4CpyLen; + u4SrcOffset += u4CpyLen; /* shift offset */ + ucDstOffset = 0; /* only use ucDstOffset at first packet for align 2KB */ + } + /* if this is a last packet, we can't transfer the remain data. + * bcs we can't guarantee the data is complete align data format + */ + if (u4CpyLen != u4FmtLen) { /* the data format is complete */ + ucDstOffset = u4CpyLen; /* not align 2KB, keep the data and next packet data will append it */ + } + + kfree(pucDataWF0); + kfree(pucDataWF1); + kfree(pucDataRAWWF0); + kfree(pucDataRAWWF1); + + if (u4RemainByte < 0) { + ASSERT(-1); + return -1; + } + + return 0; +} +#endif /* CFG_SUPPORT_QA_TOOL */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to handle dump burst event +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* @param pucEventBuf Pointer to event buffer +* +* @return none +* +*/ +/*----------------------------------------------------------------------------*/ + +VOID nicEventQueryMemDump(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEventBuf) +{ + static UINT_8 aucPath[256]; + static UINT_8 aucPath_done[300]; + static UINT_32 u4CurTimeTick; + P_EVENT_DUMP_MEM_T prEventDumpMem; + + DBGLOG(RFTEST, INFO, "nicEventQueryMemDump\n"); + + ASSERT(prAdapter); + ASSERT(pucEventBuf); + + sprintf(aucPath, "/data/blbist/dump_%05d.hex", g_u2DumpIndex); + + prEventDumpMem = (P_EVENT_DUMP_MEM_T) (pucEventBuf); + + if (kalCheckPath(aucPath) == -1) { + DBGLOG(RFTEST, INFO, "kalCheckPath(/data/blbist/dump_) == -1\n"); + kalMemSet(aucPath, 0x00, 256); + sprintf(aucPath, "/data/dump_%05d.hex", g_u2DumpIndex); + } + + DBGLOG(RFTEST, INFO, "prEventDumpMem->ucFragNum = %d\n", prEventDumpMem->ucFragNum); + if (prEventDumpMem->ucFragNum == 1) { + /* Store memory dump into sdcard, + * path /sdcard/dump___.hex + */ + u4CurTimeTick = kalGetTimeTick(); +#if defined(LINUX) + DBGLOG(RFTEST, INFO, + "defined(LINUX): if blbist mkdir undre /data/blbist, the dump files wouls put on it\n"); + + /*if blbist mkdir undre /data/blbist, the dump files wouls put on it */ + sprintf(aucPath, "/data/blbist/dump_%05d.hex", g_u2DumpIndex); + if (kalCheckPath(aucPath) == -1) { + kalMemSet(aucPath, 0x00, 256); + sprintf(aucPath, "/data/dump_%05d.hex", g_u2DumpIndex); + } +#else + DBGLOG(RFTEST, INFO, "defined(!LINUX): kal_sprintf_ddk(aucPath, sizeof(aucPath)\n"); + kal_sprintf_ddk(aucPath, sizeof(aucPath), + u4CurTimeTick, + prEventDumpMem->u4Address, prEventDumpMem->u4Length + prEventDumpMem->u4RemainLength); +#endif + 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 CFG_SUPPORT_QA_TOOL + TsfRawData2IqFmt(prEventDumpMem); +#endif /* CFG_SUPPORT_QA_TOOL */ + DBGLOG(INIT, INFO, + ": ==> (u4RemainLength = %x, u4Address=%x )\n", prEventDumpMem->u4RemainLength, + prEventDumpMem->u4Address); + + if (prEventDumpMem->u4RemainLength == 0 || prEventDumpMem->u4Address == 0xFFFFFFFF) { + + /* The request is finished or firmware response a error */ + /* Reply time tick to iwpriv */ + + g_bIcapEnable = FALSE; + g_bCaptureDone = TRUE; + + sprintf(aucPath_done, "/data/blbist/file_dump_done.txt"); + if (kalCheckPath(aucPath_done) == -1) { + kalMemSet(aucPath_done, 0x00, 256); + sprintf(aucPath_done, "/data/file_dump_done.txt"); + } + DBGLOG(INIT, INFO, ": ==> gen done_file\n"); + kalWriteToFile(aucPath_done, FALSE, aucPath_done, sizeof(aucPath_done)); +#if CFG_SUPPORT_QA_TOOL + g_au4Offset[0][0] = 0; + g_au4Offset[0][1] = 9; + g_au4Offset[1][0] = 0; + g_au4Offset[1][1] = 9; +#endif /* CFG_SUPPORT_QA_TOOL */ + g_u2DumpIndex++; + + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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) +{ + static UINT_8 aucPath[256]; + /*static UINT_8 aucPath_done[300];*/ + static UINT_32 u4CurTimeTick; + P_GLUE_INFO_T prGlueInfo; + P_EVENT_DUMP_MEM_T prEventDumpMem; + UINT_32 u4QueryInfoLen; + + DBGLOG(RFTEST, INFO, "nicCmdEventQueryMemDump\n"); + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (1) { + prGlueInfo = prAdapter->prGlueInfo; + prEventDumpMem = (P_EVENT_DUMP_MEM_T) (pucEventBuf); + + u4QueryInfoLen = sizeof(P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T); + + DBGLOG(RFTEST, INFO, "prEventDumpMem->ucFragNum = %d\n", prEventDumpMem->ucFragNum); + if (prEventDumpMem->ucFragNum == 1) { + /* Store memory dump into sdcard, + * path /sdcard/dump___.hex + */ + u4CurTimeTick = kalGetTimeTick(); +#if defined(LINUX) + /* PeiHsuan add for avoiding out of memory 20160801 */ + + if (g_u2DumpIndex >= 20) + g_u2DumpIndex = 0; + + DBGLOG(RFTEST, INFO, + "defined(LINUX) : if blbist mkdir undre /data/blbist, the dump files wouls put on it\n"); + /*if blbist mkdir undre /data/blbist, the dump files wouls put on it */ + sprintf(aucPath, "/data/blbist/dump_%05hd.hex", g_u2DumpIndex); + if (kalCheckPath(aucPath) == -1) { + kalMemSet(aucPath, 0x00, 256); + sprintf(aucPath, "/data/dump_%05hd.hex", g_u2DumpIndex); + } else + kalTrunkPath(aucPath); + DBGLOG(INIT, INFO, "iCap Create New Dump File dump_%05hd.hex\n", g_u2DumpIndex); +#else + DBGLOG(RFTEST, INFO, "kal_sprintf_ddk(aucPath, sizeof(aucPath),\n"); + kal_sprintf_ddk(aucPath, sizeof(aucPath), + u4CurTimeTick, + prEventDumpMem->u4Address, + prEventDumpMem->u4Length + prEventDumpMem->u4RemainLength); + /* strcpy(aucPath, "dump.hex"); */ +#endif + 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 CFG_SUPPORT_QA_TOOL + TsfRawData2IqFmt(prEventDumpMem); +#endif /* CFG_SUPPORT_QA_TOOL */ + + if (prEventDumpMem->u4RemainLength == 0 || prEventDumpMem->u4Address == 0xFFFFFFFF) { + /* The request is finished or firmware response a error */ + /* Reply time tick to iwpriv */ + if (prCmdInfo->fgIsOid) { + + /* + * the oid would be complete only in oid-trigger mode, + * that is no need to if the event-trigger + */ + if (g_bIcapEnable == FALSE) { + *((PUINT_32) prCmdInfo->pvInformationBuffer) = u4CurTimeTick; + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + } + g_bIcapEnable = FALSE; + g_bCaptureDone = TRUE; +#if defined(LINUX) + g_u2DumpIndex++; + +#else + kal_sprintf_done_ddk(aucPath_done, sizeof(aucPath_done)); + kalWriteToFile(aucPath_done, FALSE, aucPath_done, sizeof(aucPath_done)); +#endif + } else { +#if defined(LINUX) + +#else /* 2013/05/26 fw would try to send the buffer successfully */ + /* The memory dump request is not finished, Send next command */ + wlanSendMemDumpCmd(prAdapter, + prCmdInfo->pvInformationBuffer, prCmdInfo->u4InformationBufferLength); +#endif + } + } + + return; + +} + +#if CFG_SUPPORT_BATCH_SCAN +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when event for SUPPORT_BATCH_SCAN +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* @param pucEventBuf Pointer to the event buffer +* +* @return none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicCmdEventBatchScanResult(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_EVENT_BATCH_RESULT_T prEventBatchResult; + P_GLUE_INFO_T prGlueInfo; + + DBGLOG(SCN, TRACE, "nicCmdEventBatchScanResult"); + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventBatchResult = (P_EVENT_BATCH_RESULT_T) pucEventBuf; + + u4QueryInfoLen = sizeof(EVENT_BATCH_RESULT_T); + kalMemCopy(prCmdInfo->pvInformationBuffer, prEventBatchResult, sizeof(EVENT_BATCH_RESULT_T)); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} +#endif + +#if CFG_SUPPORT_BUILD_DATE_CODE +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when event for build date code information +* has been retrieved +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* @param pucEventBuf Pointer to the event buffer +* +* @return none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicCmdEventBuildDateCode(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_EVENT_BUILD_DATE_CODE prEvent; + P_GLUE_INFO_T prGlueInfo; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEvent = (P_EVENT_BUILD_DATE_CODE) pucEventBuf; + + u4QueryInfoLen = sizeof(UINT_8) * 16; + kalMemCopy(prCmdInfo->pvInformationBuffer, prEvent->aucDateCode, sizeof(UINT_8) * 16); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when event for query STA link status +* has been retrieved +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* @param pucEventBuf Pointer to the event buffer +* +* @return none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicCmdEventQueryStaStatistics(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4LinkScore; + UINT_32 u4TotalError; + UINT_32 u4TxExceedThresholdCount; + UINT_32 u4TxTotalCount; + UINT_32 u4QueryInfoLen; + P_EVENT_STA_STATISTICS_T prEvent; + P_GLUE_INFO_T prGlueInfo; + P_PARAM_GET_STA_STATISTICS prStaStatistics; + ENUM_WMM_ACI_T eAci; + P_STA_RECORD_T prStaRec; +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + /* link quality monitor */ + struct WIFI_LINK_QUALITY_INFO *prLinkQualityInfo; +#endif + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + prGlueInfo = prAdapter->prGlueInfo; + prEvent = (P_EVENT_STA_STATISTICS_T) pucEventBuf; + prStaStatistics = (P_PARAM_GET_STA_STATISTICS) prCmdInfo->pvInformationBuffer; + + u4QueryInfoLen = sizeof(PARAM_GET_STA_STA_STATISTICS); + + /* Statistics from FW is valid */ + if (prEvent->u4Flags & BIT(0)) { + prStaStatistics->ucPer = prEvent->ucPer; + prStaStatistics->ucRcpi = prEvent->ucRcpi; + prStaStatistics->u4PhyMode = prEvent->u4PhyMode; + prStaStatistics->u2LinkSpeed = prEvent->u2LinkSpeed; + + prStaStatistics->u4TxFailCount = prEvent->u4TxFailCount; + prStaStatistics->u4TxLifeTimeoutCount = prEvent->u4TxLifeTimeoutCount; + + prStaStatistics->u4TransmitCount = prEvent->u4TransmitCount; + prStaStatistics->u4TransmitFailCount = prEvent->u4TransmitFailCount; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prEvent->ucStaRecIdx); + + if (prStaRec) { + /*link layer statistics */ + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prStaStatistics->arLinkStatistics[eAci].u4TxFailMsdu = + prEvent->arLinkStatistics[eAci].u4TxFailMsdu; + prStaStatistics->arLinkStatistics[eAci].u4TxRetryMsdu = + prEvent->arLinkStatistics[eAci].u4TxRetryMsdu; + + /*for dump bss statistics */ + prStaRec->arLinkStatistics[eAci].u4TxFailMsdu = + prEvent->arLinkStatistics[eAci].u4TxFailMsdu; + prStaRec->arLinkStatistics[eAci].u4TxRetryMsdu = + prEvent->arLinkStatistics[eAci].u4TxRetryMsdu; + } + } + if (prEvent->u4TxCount) { + UINT_32 u4TxDoneAirTimeMs = USEC_TO_MSEC(prEvent->u4TxDoneAirTime * 32); + + prStaStatistics->u4TxAverageAirTime = (u4TxDoneAirTimeMs / prEvent->u4TxCount); + } else { + prStaStatistics->u4TxAverageAirTime = 0; + } +#if CFG_SUPPORT_WFD /* dump statistics for WFD */ + if (prAdapter->rWifiVar.rWfdConfigureSettings.ucWfdEnable == 1) { + /* Calcute Link Score */ + u4TxExceedThresholdCount = prStaStatistics->u4TxExceedThresholdCount; + u4TxTotalCount = prStaStatistics->u4TxTotalCount; + u4TotalError = prStaStatistics->u4TxFailCount + prStaStatistics->u4TxLifeTimeoutCount; + + /* u4LinkScore 10~100 , ExceedThreshold ratio 0~90 only */ + /* u4LinkScore 0~9 , Drop packet ratio 0~9 and all packets exceed threshold */ + if (u4TxTotalCount) { + if (u4TxExceedThresholdCount <= u4TxTotalCount) + u4LinkScore = (90 - + ((u4TxExceedThresholdCount * 90) / u4TxTotalCount)); + else + u4LinkScore = 0; + } else + u4LinkScore = 90; + + u4LinkScore += 10; + if (u4LinkScore == 10) { + if (u4TotalError <= u4TxTotalCount) + u4LinkScore = (10 - ((u4TotalError * 10) / u4TxTotalCount)); + else + u4LinkScore = 0; + } + + if (u4LinkScore > 100) + u4LinkScore = 100; + + DBGLOG(P2P, INFO, "link_score=%u, rssi=%u, rate=%u, threshold_cnt=%u, fail_cnt=%u\n", + u4LinkScore, prStaStatistics->ucRcpi, prStaStatistics->u2LinkSpeed, + prStaStatistics->u4TxExceedThresholdCount, prStaStatistics->u4TxFailCount); + DBGLOG(P2P, INFO, "timeout_cnt=%u, apt=%u, aat=%u, total_cnt=%u\n", + prStaStatistics->u4TxLifeTimeoutCount, prStaStatistics->u4TxAverageProcessTime, + prStaStatistics->u4TxAverageAirTime, prStaStatistics->u4TxTotalCount); + } +#endif +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + /* link quality monitor */ + prLinkQualityInfo = &(prAdapter->rLinkQualityInfo); + prLinkQualityInfo->u4CurTxRate = prEvent->u2LinkSpeed * 5; +#endif + } + + if (prCmdInfo->fgIsOid) + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + +} + +/*the same as gen4m*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when event for query LTE safe channels +* has been retrieved +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* @param pucEventBuf Pointer to the event buffer +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicCmdEventQueryLteSafeChn(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_LTE_SAFE_CHN_T prEvent; + P_PARAM_GET_CHN_INFO prLteSafeChnInfo; + UINT_8 ucIdx = 0; + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo; + + if ((prAdapter == NULL) + || (prCmdInfo == NULL) + || (pucEventBuf == NULL) + || (prCmdInfo->pvInformationBuffer == NULL)) { + ASSERT(FALSE); + return; + } + + prEvent = (P_EVENT_LTE_SAFE_CHN_T) pucEventBuf; /* FW responsed data */ + + prLteSafeChnInfo = (P_PARAM_GET_CHN_INFO) prCmdInfo->pvInformationBuffer; + if (prLteSafeChnInfo->ucRoleIndex >= BSS_P2P_NUM) { + ASSERT(FALSE); + return; + } + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prLteSafeChnInfo->ucRoleIndex); + + /* Statistics from FW is valid */ + if (prEvent->u4Flags & BIT(0)) { + P_CMD_LTE_SAFE_CHN_INFO_T prLteSafeChnList; + + prLteSafeChnList = &prLteSafeChnInfo->rLteSafeChnList; + for (ucIdx = 0; ucIdx < 5; ucIdx++) { + prLteSafeChnList->au4SafeChannelBitmask[ucIdx] + = prEvent->rLteSafeChn. + au4SafeChannelBitmask[ucIdx]; + + DBGLOG(NIC, INFO, + "[ACS]LTE safe channels[%d]=0x%08x\n", + ucIdx, + prLteSafeChnList->au4SafeChannelBitmask[ucIdx]); + } + + } else { + DBGLOG(NIC, ERROR, "FW's event is NOT valid.\n"); + } + + p2pFunProcessAcsReport(prAdapter, + prLteSafeChnInfo->ucRoleIndex, + prLteSafeChnInfo, + &(prP2pRoleFsmInfo->rAcsReqInfo)); +} + + +#ifdef FW_CFG_SUPPORT +VOID nicCmdEventQueryCfgRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + struct _CMD_HEADER_T *prInCfgHeader; + P_GLUE_INFO_T prGlueInfo; + struct _CMD_HEADER_T *prOutCfgHeader; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prInCfgHeader = (struct _CMD_HEADER_T *) pucEventBuf; + u4QueryInfoLen = sizeof(struct _CMD_HEADER_T); + prOutCfgHeader = (struct _CMD_HEADER_T *) prCmdInfo->pvInformationBuffer; + kalMemCopy(prOutCfgHeader, prInCfgHeader, sizeof(struct _CMD_HEADER_T)); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} +#endif + +VOID nicEventUpdateFwInfo(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + UINT_8 i; + P_EVENT_UPDATE_FW_INFO_T prEventUpdateFwInfo; + + prEventUpdateFwInfo = (P_EVENT_UPDATE_FW_INFO_T)(prEvent->aucBuffer); + for (i = 0; i < (HW_BSSID_NUM + 1); i++) { + if (prAdapter->aprBssInfo[i]) { + prAdapter->aprBssInfo[i]->u4CoexPhyRateLimit = prEventUpdateFwInfo->au4PhyRateLimit[i]; + DBGLOG(NIC, TRACE, "Coex:BSS[%d]R:%d\n", i, prAdapter->aprBssInfo[i]->u4CoexPhyRateLimit); + } + } +} + +#if CFG_SUPPORT_REPLAY_DETECTION +VOID nicCmdEventSetAddKey(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_WIFI_CMD_T prWifiCmd = NULL; + P_CMD_802_11_KEY prCmdKey = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + struct GL_DETECT_REPLAY_INFO *prDetRplyInfo = NULL; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4InformationBufferLength, WLAN_STATUS_SUCCESS); + } + + prGlueInfo = prAdapter->prGlueInfo; + prDetRplyInfo = &prGlueInfo->prDetRplyInfo; + if (pucEventBuf) { + prWifiCmd = (P_WIFI_CMD_T) (pucEventBuf); + prCmdKey = (P_CMD_802_11_KEY) (prWifiCmd->aucBuffer); + if (!prCmdKey->ucKeyType && prCmdKey->ucKeyId >= 0 && prCmdKey->ucKeyId < 4) { + /* Only save data broadcast key info. ucKeyType == 1 means unicast key + ** ucKeyId == 4 or ucKeyId == 5 means it is a PMF key + */ + prDetRplyInfo->ucCurKeyId = prCmdKey->ucKeyId; + prDetRplyInfo->ucKeyType = prCmdKey->ucKeyType; + prDetRplyInfo->arReplayPNInfo[prCmdKey->ucKeyId].fgRekey = TRUE; + kalMemCopy(prDetRplyInfo->arReplayPNInfo[prCmdKey->ucKeyId].auPN, + prCmdKey->aucKeyRsc, 16); + DBGLOG_MEM8(NIC, TRACE, + prDetRplyInfo->arReplayPNInfo[prCmdKey->ucKeyId].auPN, + 8); + DBGLOG(NIC, TRACE, "Keyid is %d, ucKeyType is %d\n", + prCmdKey->ucKeyId, prCmdKey->ucKeyType); + } + } +} +VOID nicOidCmdTimeoutSetAddKey(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + ASSERT(prAdapter); + + DBGLOG(NIC, WARN, "Wlan setaddkey timeout.\n"); + if (prCmdInfo->fgIsOid) + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_FAILURE); +} +#endif + +#if CFG_SUPPORT_REPORT_MISC +VOID nicCmdEventReportMisc(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + ASSERT(prAdapter); + + if (pucEventBuf) { + UINT_64 now = 0; + struct EVENT_REPORT_MISC *prEvent = (struct EVENT_REPORT_MISC *)pucEventBuf; + struct EVENT_REPORT_MISC *prReportMisc = &prAdapter->rReportMiscSet.reportMisc; + char *periodStr = NULL; + + switch (prAdapter->rReportMiscSet.eQueryNum) { + case REPORT_AUTHASSOC_START: + case REPORT_4WAYHS_START: + case REPORT_DHCP_START: + prReportMisc->ucFwVerMajor = prEvent->ucFwVerMajor; + prReportMisc->ucFwVerMinor = prEvent->ucFwVerMinor; + prReportMisc->u2FwVerBeta = prEvent->u2FwVerBeta; + prReportMisc->u4MdrdyCnt = prEvent->u4RxMpduCnt; + prReportMisc->u4ChannelIdleCnt = prEvent->u4ChannelIdleCnt; + prAdapter->rReportMiscSet.u8Ts = sched_clock(); + break; + case REPORT_AUTHASSOC_END: + periodStr = "auth to assoc"; + goto REPORT_MISC; + case REPORT_4WAYHS_END: + periodStr = "4-way flow"; + if (prEvent->cRssi) + prAdapter->rReportMiscSet.i4Rssi = prEvent->cRssi; + goto REPORT_MISC; + case REPORT_DHCP_END: + periodStr = "dhcp flow"; + if (prEvent->cRssi) + prAdapter->rReportMiscSet.i4Rssi = prEvent->cRssi; + /* don't break here */ +REPORT_MISC: + now = sched_clock(); + DBGLOG(NIC, TRACE, "Ver=0x%x.%x.%04x,Time=%llu,Period=%s,MDRDY=%u,SLOTID=%u,MPDU=%u,RSSI=%d\n", + prReportMisc->ucFwVerMajor, + prReportMisc->ucFwVerMinor, + prReportMisc->u2FwVerBeta, + now - prAdapter->rReportMiscSet.u8Ts, + periodStr, + prEvent->u4MdrdyCnt - prReportMisc->u4MdrdyCnt, + prEvent->u4ChannelIdleCnt - prReportMisc->u4ChannelIdleCnt, + prEvent->u4RxMpduCnt - prReportMisc->u4RxMpduCnt, + prAdapter->rReportMiscSet.i4Rssi); + prAdapter->rReportMiscSet.eQueryNum = 0; + break; + default: + DBGLOG(NIC, WARN, "Report Misc Error, prAdapter->rReportMiscSet.eQueryNum: %d\n", + prAdapter->rReportMiscSet.eQueryNum); + break; + + } + } + if (prCmdInfo->fgIsOid) + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->u4InformationBufferLength, 0, WLAN_STATUS_SUCCESS); +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/nic_pwr_mgt.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/nic_pwr_mgt.c new file mode 100644 index 0000000000000..703e5184d470e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/nic_pwr_mgt.c @@ -0,0 +1,507 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/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. + */ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to process the POWER ON procedure. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicpmSetFWOwn(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnableGlobalInt) +{ + UINT_32 u4RegValue = 0; + BOOLEAN fgHifFwOwn = TRUE; + + ASSERT(prAdapter); + + HAL_MCR_RD(prAdapter, MCR_WHLPCR, &u4RegValue); + fgHifFwOwn = !(u4RegValue & WHLPCR_FW_OWN_REQ_SET); + if (fgHifFwOwn != prAdapter->fgIsFwOwn) { + DBGLOG(NIC, ERROR, + "FW own status mismatch! fgIsFwOwn=%d, WHLPCR=0x%x\n", + prAdapter->fgIsFwOwn, u4RegValue); + if (fgHifFwOwn) { + prAdapter->fgIsFwOwn = TRUE; + return; + } + } else if (prAdapter->fgIsFwOwn) + return; + + if (nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) { + DBGLOG(NIC, INFO, "FW OWN Failed due to pending INT\n"); + /* pending interrupts */ + return; + } + + if (fgEnableGlobalInt) { + DBGLOG(NIC, INFO, "FW OWN, fgEnableGlobalInt=TRUE\n"); + prAdapter->fgIsIntEnableWithLPOwnSet = TRUE; + return; + } + 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); + DBGLOG(NIC, INFO, "FW OWN fail\n"); + return; + } + kalTakeVcoreAction(VCORE_RESTORE_DEF); + prAdapter->fgIsFwOwn = TRUE; + DBGLOG(NIC, TRACE, "FW OWN\n"); +} + +VOID nicpmCheckAndTriggerDriverOwn(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4RegValue = 0; + + HAL_MCR_RD(prAdapter, MCR_WHLPCR, &u4RegValue); + + if (u4RegValue & WHLPCR_FW_OWN_REQ_SET) { + /* WLAN_DRV_OWN is asserted on initial stage, but chip WLAN function is FW_OWN state actually, + * this is an issue due to HIF un-sync reset. + * + * Trigger FW_OWN to let HIF clear WLAN_DRV_OWN bit and make power state synchronized. + * F/W should remember to clear the residual bit in HWFISR.DRV_SET_FW_OWN. + */ + DBGLOG(NIC, WARN, "DRIVER OWN already set on initial stage!! trigger FW OWN to sync power state\n"); + 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) { + /* Impossible case, H/W will clear WLAN_DRV_OWN bit immediately after + * WHLPCR.FW_OWN_REQ_SET is set + */ + DBGLOG(NIC, ERROR, "FW OWN fail, anyway continue to trigger DRIVER OWN\n"); + } + } + + prAdapter->fgIsFwOwn = TRUE; + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_CLR); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 512 /* exponential of 2 */ +#define LP_OWN_BACK_CLR_OWN_ITERATION 256 /* exponential of 2 */ +#define LP_OWN_BACK_FAILED_RETRY_CNT 5 +#define LP_OWN_BACK_FAILED_LOG_SKIP_MS 2000 +#define LP_OWN_BACK_FAILED_RESET_CNT 5 +#define LP_OWN_BACK_LOOP_DELAY_MIN_US 900 +#define LP_OWN_BACK_LOOP_DELAY_MAX_US 1000 + +/* Polling cpupcr before driver own. WARN: Only for debug. Enable this feature will cut down throughput */ +#define POLL_CPUPCR_BEFORE_DRIVER_OWN 0 +#if POLL_CPUPCR_BEFORE_DRIVER_OWN +#define POLL_CPUPCR_BEFORE_DRIVER_OWN_COUNT 5 + UINT_32 u4PolCnt = 0; + UINT_32 au4Cpupcr[POLL_CPUPCR_BEFORE_DRIVER_OWN_COUNT] = {0}; +#endif + BOOLEAN fgStatus = TRUE; + UINT_32 i, u4CurrTick, u4RegValue = 0; + BOOLEAN fgTimeout; + BOOLEAN fgHifFwOwn = TRUE; + + ASSERT(prAdapter); + + HAL_MCR_RD(prAdapter, MCR_WHLPCR, &u4RegValue); + fgHifFwOwn = !(u4RegValue & WHLPCR_FW_OWN_REQ_SET); + if (fgHifFwOwn != prAdapter->fgIsFwOwn) { + DBGLOG(NIC, ERROR, + "Driver own status mismatch! fgIsFwOwn=%d, WHLPCR=0x%x\n", + prAdapter->fgIsFwOwn, u4RegValue); + if (!fgHifFwOwn) { + prAdapter->fgIsFwOwn = FALSE; + return fgStatus; + } + } else if (!prAdapter->fgIsFwOwn) + return fgStatus; + + DBGLOG(INIT, TRACE, "DRIVER OWN\n"); + + u4CurrTick = kalGetTimeTick(); +#if POLL_CPUPCR_BEFORE_DRIVER_OWN + for (u4PolCnt = 0; u4PolCnt < POLL_CPUPCR_BEFORE_DRIVER_OWN_COUNT; u4PolCnt++) { + if (wlanGetCpupcr(&au4Cpupcr[u4PolCnt]) == WLAN_STATUS_FAILURE) + DBGLOG(INIT, ERROR, + "Polling Cpupcr before driver own %d failed!\n", u4PolCnt); + } +#endif + i = 0; + while (1) { + HAL_MCR_RD(prAdapter, MCR_WHLPCR, &u4RegValue); + + fgTimeout = ((kalGetTimeTick() - u4CurrTick) > LP_OWN_BACK_TOTAL_DELAY_MS) ? TRUE : FALSE; + + if (u4RegValue & WHLPCR_FW_OWN_REQ_SET) { + prAdapter->fgIsFwOwn = FALSE; + prAdapter->u4OwnFailedCount = 0; + prAdapter->u4OwnFailedLogCount = 0; + break; + } else if ((i > LP_OWN_BACK_FAILED_RETRY_CNT) && + (kalIsCardRemoved(prAdapter->prGlueInfo) || fgIsBusAccessFailed || fgTimeout + || wlanIsChipNoAck(prAdapter))) { + + if ((prAdapter->u4OwnFailedCount == 0) || + CHECK_FOR_TIMEOUT(u4CurrTick, prAdapter->rLastOwnFailedLogTime, + MSEC_TO_SYSTIME(LP_OWN_BACK_FAILED_LOG_SKIP_MS))) { + + DBGLOG(NIC, ERROR, + "LP fail, Timeout(%ums) Bus Error[%u] Resetting[%u] NoAck[%u] Cnt[%u]", + kalGetTimeTick() - u4CurrTick, fgIsBusAccessFailed, kalIsResetting(), + wlanIsChipNoAck(prAdapter), prAdapter->u4OwnFailedCount); + /* polling cpupcr for debug */ +#if POLL_CPUPCR_BEFORE_DRIVER_OWN + for (u4PolCnt = 0; u4PolCnt < POLL_CPUPCR_BEFORE_DRIVER_OWN_COUNT; u4PolCnt++) { + DBGLOG(INIT, ERROR, + "count:%d cpupcr before: %08x\n", + u4PolCnt, au4Cpupcr[u4PolCnt]); + } +#endif + wlanPollingCpupcr(4, 5); + prAdapter->u4OwnFailedLogCount++; + if (prAdapter->u4OwnFailedLogCount > LP_OWN_BACK_FAILED_RESET_CNT) { + /* Trigger RESET */ + GL_RESET_TRIGGER(prAdapter, RST_FLAG_CHIP_RESET); + } + GET_CURRENT_SYSTIME(&prAdapter->rLastOwnFailedLogTime); + } + + prAdapter->u4OwnFailedCount++; + fgStatus = FALSE; + break; + } + + if ((i & (LP_OWN_BACK_CLR_OWN_ITERATION - 1)) == 0) { + /* Driver request LP ownership - per 256 iterations */ + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_CLR); + } + + /* Delay for LP engine to complete its operation. */ + kalUsleep_range(LP_OWN_BACK_LOOP_DELAY_MIN_US, LP_OWN_BACK_LOOP_DELAY_MAX_US); + i++; + } + if (i > 10) + DBGLOG(NIC, INFO, "DRIVER OWN, status=%d count=%d\n", fgStatus, i); + else + DBGLOG(NIC, TRACE, "DRIVER OWN, status=%d count=%d\n", fgStatus, 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_16 au2TxCount[16]; + UINT_32 i; +#if CFG_ENABLE_FW_DOWNLOAD + UINT_32 u4FwImgLength, u4FwLoadAddr; + PVOID prFwMappingHandle; + PVOID pvFwImageMapFile = NULL; +#if CFG_ENABLE_FW_DIVIDED_DOWNLOAD + P_FIRMWARE_DIVIDED_DOWNLOAD_T prFwHead; + BOOLEAN fgValidHead; + const UINT_32 u4CRCOffset = offsetof(FIRMWARE_DIVIDED_DOWNLOAD_T, u4NumOfEntries); +#endif +#endif + + DEBUGFUNC("nicpmSetAcpiPowerD0"); + + ASSERT(prAdapter); + + do { + /* 0. Reset variables in ADAPTER_T */ + prAdapter->fgIsFwOwn = TRUE; + prAdapter->fgWiFiInSleepyState = FALSE; + prAdapter->rAcpiState = ACPI_STATE_D0; + prAdapter->fgIsEnterD3ReqIssued = FALSE; + + /* 1. Request Ownership to enter F/W download state */ + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); +#if !CFG_ENABLE_FULL_PM + nicpmSetDriverOwn(prAdapter); +#endif + /* 2. Initialize the Adapter */ + u4Status = nicInitializeAdapter(prAdapter); + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(NIC, ERROR, "nicInitializeAdapter failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } + +#if CFG_ENABLE_FW_DOWNLOAD + prFwMappingHandle = kalFirmwareImageMapping(prAdapter->prGlueInfo, &pvFwImageMapFile, &u4FwImgLength); + if (!prFwMappingHandle) { + DBGLOG(NIC, ERROR, "Fail to load FW image from file!\n"); + pvFwImageMapFile = NULL; + } + + if (pvFwImageMapFile) { + /* 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) { + wlanFwDvdDwnloadHandler(prAdapter, prFwHead, pvFwImageMapFile, &u4Status); + } else +#endif + { + if (wlanImageSectionConfig(prAdapter, + u4FwLoadAddr, + u4FwImgLength, + TRUE, + TRUE, + 0) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "Firmware download configuration failed!\n"); + + u4Status = WLAN_STATUS_FAILURE; + break; + } + + wlanFwDwnloadHandler(prAdapter, u4FwImgLength, pvFwImageMapFile, &u4Status); + } + /* escape to top */ + 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 +#endif + + /* 5. check Wi-Fi FW asserts ready bit */ + DBGLOG(NIC, TRACE, "wlanAdapterStart(): Waiting for Ready bit..\n"); + i = 0; + while (1) { + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4Value); + + if (u4Value & WCIR_WLAN_READY) { + DBGLOG(NIC, TRACE, "Ready bit asserted\n"); + break; + } else if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + break; + } else if (i >= CFG_RESPONSE_POLLING_TIMEOUT) { + DBGLOG(NIC, ERROR, "Waiting for Ready bit: Timeout\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } + + i++; + kalMsleep(10); + } + + if (u4Status == WLAN_STATUS_SUCCESS) { + /* 6.1 reset interrupt status */ + HAL_READ_INTR_STATUS(prAdapter, 4, (PUINT_8)&u4WHISR); + if (HAL_IS_TX_DONE_INTR(u4WHISR)) + HAL_READ_TX_RELEASED_COUNT(prAdapter, au2TxCount); + + /* 6.2 reset TX Resource for normal operation */ + nicTxResetResource(prAdapter); + + /* 6.3 Enable interrupt */ + nicEnableInterrupt(prAdapter); + + /* 6.4 Update basic configuration */ + wlanUpdateBasicConfig(prAdapter); + + /* 6.5 Apply Network Address */ + nicApplyNetworkAddress(prAdapter); + + /* 6.6 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, TRUE); + + /* 5.1 clear pending Security / Management Frames */ + kalClearSecurityFrames(prAdapter->prGlueInfo); + kalClearMgmtFrames(prAdapter->prGlueInfo); + + /* 5.2 clear pending TX packet queued in glue layer */ + kalFlushPendingTxPackets(prAdapter->prGlueInfo); + + /* 6. Set Onwership to F/W */ + nicpmSetFWOwn(prAdapter, FALSE); + + /* 7. Set variables */ + prAdapter->rAcpiState = ACPI_STATE_D3; + + return TRUE; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/nic_rate.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/nic_rate.c new file mode 100644 index 0000000000000..c92378bed7cbf --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/nic_rate.c @@ -0,0 +1,394 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * ! \file "nic_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. + */ + +/******************************************************************************* +* C O M P I L E 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_16 au2RateCCKLong[CCK_RATE_NUM] = { + 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 */ +}; + +const UINT_16 au2RateCCKShort[CCK_RATE_NUM] = { + 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 */ +}; + +const UINT_16 au2RateOFDM[OFDM_RATE_NUM] = { + 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 */ +}; + +const UINT_16 au2RateHTMixed[HT_RATE_NUM] = { + RATE_MM_MCS_32, /* RATE_MCS32_INDEX, */ + 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, */ +}; + +const UINT_16 au2RateHTGreenField[HT_RATE_NUM] = { + RATE_GF_MCS_32, /* RATE_MCS32_INDEX, */ + 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, */ +}; + +const UINT_16 au2RateVHT[VHT_RATE_NUM] = { + RATE_VHT_MCS_0, /* RATE_MCS0_INDEX, */ + RATE_VHT_MCS_1, /* RATE_MCS1_INDEX, */ + RATE_VHT_MCS_2, /* RATE_MCS2_INDEX, */ + RATE_VHT_MCS_3, /* RATE_MCS3_INDEX, */ + RATE_VHT_MCS_4, /* RATE_MCS4_INDEX, */ + RATE_VHT_MCS_5, /* RATE_MCS5_INDEX, */ + RATE_VHT_MCS_6, /* RATE_MCS6_INDEX, */ + RATE_VHT_MCS_7, /* RATE_MCS7_INDEX, */ + RATE_VHT_MCS_8, /* RATE_MCS8_INDEX, */ + RATE_VHT_MCS_9 /* RATE_MCS9_INDEX, */ +}; + +const EMU_MAC_RATE_INFO_T arMcsRate2PhyRate[] = { + RATE_INFO(PHY_RATE_MCS0, 65, 72, 135, 150, 293, 325, 585, 650), + RATE_INFO(PHY_RATE_MCS1, 130, 144, 270, 300, 585, 650, 1170, 1300), + RATE_INFO(PHY_RATE_MCS2, 195, 217, 405, 450, 878, 975, 1755, 1950), + RATE_INFO(PHY_RATE_MCS3, 260, 289, 540, 600, 1170, 1300, 2340, 2600), + RATE_INFO(PHY_RATE_MCS4, 390, 433, 810, 900, 1755, 1950, 3510, 3900), + RATE_INFO(PHY_RATE_MCS5, 520, 578, 1080, 1200, 2340, 2600, 4680, 5200), + RATE_INFO(PHY_RATE_MCS6, 585, 650, 1215, 1350, 2633, 2925, 5265, 5850), + RATE_INFO(PHY_RATE_MCS7, 650, 722, 1350, 1500, 2925, 3250, 5850, 6500), + RATE_INFO(PHY_RATE_MCS8, 780, 867, 1620, 1800, 3510, 3900, 7020, 7800), + RATE_INFO(PHY_RATE_MCS9, 0, 0, 1800, 2000, 3900, 4333, 7800, 8667), + RATE_INFO(PHY_RATE_MCS32, 0, 0, 60, 67, 0, 0, 0, 0) +}; + +const UINT_8 aucHwRate2PhyRate[] = { + RATE_1M, /*1M long */ + RATE_2M, /*2M long */ + RATE_5_5M, /*5.5M long */ + RATE_11M, /*11M long */ + RATE_1M, /*1M short invalid */ + RATE_2M, /*2M short */ + RATE_5_5M, /*5.5M short */ + RATE_11M, /*11M short */ + RATE_48M, /*48M */ + RATE_24M, /*24M */ + RATE_12M, /*12M */ + RATE_6M, /*6M */ + RATE_54M, /*54M */ + RATE_36M, /*36M */ + RATE_18M, /*18M */ + RATE_9M /*9M */ +}; +/******************************************************************************* +* 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 +******************************************************************************** +*/ +UINT_32 +nicGetPhyRateByMcsRate( + IN UINT_8 ucIdx, + IN UINT_8 ucBw, + IN UINT_8 ucGI) +{ + return arMcsRate2PhyRate[ucIdx].u4PhyRate[ucBw][ucGI]; +} + +UINT_32 +nicGetHwRateByPhyRate( + IN UINT_8 ucIdx) +{ + return aucHwRate2PhyRate[ucIdx]; /* uint : 500 kbps */ +} + +WLAN_STATUS +nicSwIndex2RateIndex( + IN UINT_8 ucRateSwIndex, + OUT PUINT_8 pucRateIndex, + OUT PUINT_8 pucPreambleOption + ) +{ + ASSERT(pucRateIndex); + ASSERT(pucPreambleOption); + if (ucRateSwIndex >= RATE_6M_SW_INDEX) { + *pucRateIndex = ucRateSwIndex - RATE_6M_SW_INDEX; + *pucPreambleOption = PREAMBLE_OFDM_MODE; + } else { + *pucRateIndex = ucRateSwIndex; + *pucPreambleOption = PREAMBLE_DEFAULT_LONG_NONE; + } + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS nicRateIndex2RateCode(IN UINT_8 ucPreambleOption, IN UINT_8 ucRateIndex, OUT PUINT_16 pu2RateCode) +{ + switch (ucPreambleOption) { + case PREAMBLE_DEFAULT_LONG_NONE: + if (ucRateIndex >= CCK_RATE_NUM) + return WLAN_STATUS_INVALID_DATA; + *pu2RateCode = au2RateCCKLong[ucRateIndex]; + break; + + case PREAMBLE_OPTION_SHORT: + if (ucRateIndex >= CCK_RATE_NUM) + return WLAN_STATUS_INVALID_DATA; + *pu2RateCode = au2RateCCKShort[ucRateIndex]; + break; + + case PREAMBLE_OFDM_MODE: + if (ucRateIndex >= OFDM_RATE_NUM) + return WLAN_STATUS_INVALID_DATA; + *pu2RateCode = au2RateOFDM[ucRateIndex]; + break; + + case PREAMBLE_HT_MIXED_MODE: + if (ucRateIndex >= HT_RATE_NUM) + return WLAN_STATUS_INVALID_DATA; + *pu2RateCode = au2RateHTMixed[ucRateIndex]; + break; + + case PREAMBLE_HT_GREEN_FIELD: + if (ucRateIndex >= HT_RATE_NUM) + return WLAN_STATUS_INVALID_DATA; + *pu2RateCode = au2RateHTGreenField[ucRateIndex]; + break; + + case PREAMBLE_VHT_FIELD: + if (ucRateIndex >= VHT_RATE_NUM) + return WLAN_STATUS_INVALID_DATA; + *pu2RateCode = au2RateVHT[ucRateIndex]; + break; + + default: + return WLAN_STATUS_INVALID_DATA; + } + + return WLAN_STATUS_SUCCESS; +} + +UINT_32 +nicRateCode2PhyRate( + IN UINT_16 u2RateCode, + IN UINT_8 ucBandwidth, + IN UINT_8 ucGI, + IN UINT_8 ucRateNss) +{ + UINT_8 ucPhyRate; + UINT_16 u2TxMode; + UINT_32 u4PhyRateBy1SS, u4PhyRateIn100Kbps = 0; + + ucPhyRate = RATE_CODE_GET_PHY_RATE(u2RateCode); + u2TxMode = u2RateCode & RATE_TX_MODE_MASK; + ucRateNss = ucRateNss + AR_SS_1; /* change to be base=1 */ + if ((u2TxMode == TX_MODE_HT_GF) || (u2TxMode == TX_MODE_HT_MM)) { + if (ucPhyRate > PHY_RATE_MCS7) + u2RateCode = u2RateCode - HT_RATE_MCS7_INDEX; + else + ucRateNss = AR_SS_1; + } else if ((u2TxMode == TX_MODE_OFDM) || (u2TxMode == TX_MODE_CCK)) { + ucRateNss = AR_SS_1; + } + + u4PhyRateBy1SS = nicRateCode2DataRate(u2RateCode, ucBandwidth, ucGI); + u4PhyRateIn100Kbps = u4PhyRateBy1SS * ucRateNss; + + DBGLOG(NIC, TRACE, "Coex:nicRateCode2PhyRate,RC:%x,B:%d,I:%d,1ss R:%d,PHY R:%d\n", + u2RateCode, ucBandwidth, ucGI, u4PhyRateBy1SS, u4PhyRateIn100Kbps); + + return u4PhyRateIn100Kbps; +} + +UINT_32 +nicRateCode2DataRate( + IN UINT_16 u2RateCode, + IN UINT_8 ucBandwidth, + IN UINT_8 ucGI) +{ + UINT_8 ucPhyRate, ucIdx, ucBw = 0; + UINT_32 u4PhyRateIn100Kbps = 0; + UINT_16 u2TxMode; + + if ((ucBandwidth == FIX_BW_NO_FIXED) || (ucBandwidth == FIX_BW_20)) + ucBw = MAC_BW_20; + else if (ucBandwidth == FIX_BW_40) + ucBw = MAC_BW_40; + else if (ucBandwidth == FIX_BW_80) + ucBw = MAC_BW_80; + else if (ucBandwidth == FIX_BW_160) + ucBw = MAC_BW_160; + + ucPhyRate = RATE_CODE_GET_PHY_RATE(u2RateCode); + u2TxMode = u2RateCode & RATE_TX_MODE_MASK; + /* Set MMSS parameter if HT/VHT rate */ + if ((u2TxMode == TX_MODE_HT_GF) || + (u2TxMode == TX_MODE_HT_MM) || + (u2TxMode == TX_MODE_VHT)) { + /* No SGI Greenfield for 1T */ + /* Refer to section 20.3.11.11.6 of IEEE802.11-2012 */ + if (u2TxMode == TX_MODE_HT_GF) + ucGI = MAC_GI_NORMAL; + + ucIdx = ucPhyRate; + + if (ucIdx == PHY_RATE_MCS32) + ucIdx = 10; + + u4PhyRateIn100Kbps = nicGetPhyRateByMcsRate(ucIdx, ucBw, ucGI); + } else if ((u2TxMode == TX_MODE_OFDM) || + (u2TxMode == TX_MODE_CCK)) { + u4PhyRateIn100Kbps = (nicGetHwRateByPhyRate(ucPhyRate & BITS(0, 3)))*5; + } else { + ASSERT(FALSE); + } + return u4PhyRateIn100Kbps; +} + +BOOLEAN +nicGetRateIndexFromRateSetWithLimit( + IN UINT_16 u2RateSet, + IN UINT_32 u4PhyRateLimit, + IN BOOLEAN fgGetLowest, + OUT PUINT_8 pucRateSwIndex) +{ + UINT_32 i; + UINT_32 u4CurPhyRate, u4TarPhyRate, u4HighestPhyRate, u4LowestPhyRate; + UINT_8 ucRateIndex, ucRatePreamble, ucTarRateSwIndex, ucHighestPhyRateSwIdx, ucLowestPhyRateSwIdx; + UINT_16 u2CurRateCode; + UINT_32 u4Status; + + /* Set init value */ + if (fgGetLowest) { + u4TarPhyRate = 0xFFFFFFFF; + u4HighestPhyRate = 0; + ucHighestPhyRateSwIdx = RATE_NUM_SW; + } else { + u4TarPhyRate = 0; + u4LowestPhyRate = 0xFFFFFFFF; + ucLowestPhyRateSwIdx = RATE_NUM_SW; + } + + ucTarRateSwIndex = RATE_NUM_SW; + + /* Find SW rate index by limitation */ + for (i = RATE_1M_SW_INDEX; i <= RATE_54M_SW_INDEX; i++) { + if (u2RateSet & BIT(i)) { + + /* Convert SW rate index to phy rate in 100kbps */ + nicSwIndex2RateIndex(i, &ucRateIndex, &ucRatePreamble); + u4Status = nicRateIndex2RateCode(ucRatePreamble, ucRateIndex, &u2CurRateCode); + + if (u4Status != WLAN_STATUS_SUCCESS) + continue; + + u4CurPhyRate = + nicRateCode2DataRate(u2CurRateCode, MAC_BW_20, MAC_GI_NORMAL); + + /* Compare */ + if (fgGetLowest) { + if (u4HighestPhyRate < u4CurPhyRate) { + u4HighestPhyRate = u4CurPhyRate; + ucHighestPhyRateSwIdx = i; + } + if ((u4CurPhyRate >= u4PhyRateLimit) && (u4CurPhyRate <= u4TarPhyRate)) { + u4TarPhyRate = u4CurPhyRate; + ucTarRateSwIndex = i; + } + } else { + if (u4LowestPhyRate > u4CurPhyRate) { + u4LowestPhyRate = u4CurPhyRate; + ucLowestPhyRateSwIdx = i; + } + if ((u4CurPhyRate <= u4PhyRateLimit) && (u4CurPhyRate >= u4TarPhyRate)) { + u4TarPhyRate = u4CurPhyRate; + ucTarRateSwIndex = i; + } + } + } + } + + /* Return target SW rate index */ + if (ucTarRateSwIndex < RATE_NUM_SW) { + *pucRateSwIndex = ucTarRateSwIndex; + } else { + if (fgGetLowest) + *pucRateSwIndex = ucHighestPhyRateSwIdx; + else + *pucRateSwIndex = ucLowestPhyRateSwIdx; + } + return TRUE; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/nic_rx.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/nic_rx.c new file mode 100644 index 0000000000000..f4ef2ca3e977b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/nic_rx.c @@ -0,0 +1,3995 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_rx.c#5 + */ + +/* + * ! \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. + */ + +/******************************************************************************* +* C O M P I L E 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 "que_mgt.h" + +#ifndef LINUX +#include +#else +#include +#endif + +#if CFG_SUPPORT_SCN_PSCN +#include "gl_os.h" +#include "debug.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include +#include +#include +#include "gl_cfg80211.h" +#include "gl_vendor.h" +#endif +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define RX_RESPONSE_TIMEOUT (1000) + +#if 0 /* CFG_SUPPORT_SNIFFER */ +/* in unit of 100kb/s */ +const EMU_MAC_RATE_INFO_T arMcsRate2PhyRate[] = { + /* Phy Rate Code, BW20, BW20 SGI, BW40, BW40 SGI, BW80, BW80 SGI, BW160, BW160 SGI */ + RATE_INFO(PHY_RATE_MCS0, 65, 72, 135, 150, 293, 325, 585, 650), + RATE_INFO(PHY_RATE_MCS1, 130, 144, 270, 300, 585, 650, 1170, 1300), + RATE_INFO(PHY_RATE_MCS2, 195, 217, 405, 450, 878, 975, 1755, 1950), + RATE_INFO(PHY_RATE_MCS3, 260, 289, 540, 600, 1170, 1300, 2340, 2600), + RATE_INFO(PHY_RATE_MCS4, 390, 433, 810, 900, 1755, 1950, 3510, 3900), + RATE_INFO(PHY_RATE_MCS5, 520, 578, 1080, 1200, 2340, 2600, 4680, 5200), + RATE_INFO(PHY_RATE_MCS6, 585, 650, 1215, 1350, 2633, 2925, 5265, 5850), + RATE_INFO(PHY_RATE_MCS7, 650, 722, 1350, 1500, 2925, 3250, 5850, 6500), + RATE_INFO(PHY_RATE_MCS8, 780, 867, 1620, 1800, 3510, 3900, 7020, 7800), + RATE_INFO(PHY_RATE_MCS9, 0, 0, 1800, 2000, 3900, 4333, 7800, 8667), + RATE_INFO(PHY_RATE_MCS32, 0, 0, 60, 67, 0, 0, 0, 0) +}; + +/* in uint of 500kb/s */ +const UINT_8 aucHwRate2PhyRate[] = { + RATE_1M, /*1M long */ + RATE_2M, /*2M long */ + RATE_5_5M, /*5.5M long */ + RATE_11M, /*11M long */ + RATE_1M, /*1M short invalid */ + RATE_2M, /*2M short */ + RATE_5_5M, /*5.5M short */ + RATE_11M, /*11M short */ + RATE_48M, /*48M */ + RATE_24M, /*24M */ + RATE_12M, /*12M */ + RATE_6M, /*6M */ + RATE_54M, /*54M */ + RATE_36M, /*36M */ + RATE_18M, /*18M */ + RATE_9M /*9M */ +}; +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +#if CFG_MGMT_FRAME_HANDLING +static PROCESS_RX_MGT_FUNCTION apfnProcessRxMgtFrame[MAX_NUM_OF_FC_SUBTYPES] = { +#if CFG_SUPPORT_AAA + aaaFsmRunEventRxAssoc, /* subtype 0000: Association request */ +#else + NULL, /* subtype 0000: Association request */ +#endif /* CFG_SUPPORT_AAA */ + saaFsmRunEventRxAssoc, /* subtype 0001: Association response */ +#if CFG_SUPPORT_AAA + aaaFsmRunEventRxAssoc, /* subtype 0010: Reassociation request */ +#else + NULL, /* subtype 0010: Reassociation request */ +#endif /* CFG_SUPPORT_AAA */ + saaFsmRunEventRxAssoc, /* subtype 0011: Reassociation response */ +#if CFG_SUPPORT_ADHOC || CFG_ENABLE_WIFI_DIRECT + 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)); + } + if (prRxCtrl->rFreeSwRfbList.u4NumElem != CFG_RX_MAX_PKT_NUM) + ASSERT_NOMEM(); + /* 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; + HAL_CFG_MAX_HIF_RX_LEN_NUM(prAdapter, CFG_SDIO_MAX_RX_AGG_NUM); +#else + HAL_CFG_MAX_HIF_RX_LEN_NUM(prAdapter, 1); +#endif + +#if CFG_HIF_STATISTICS + prRxCtrl->u4TotalRxAccessNum = 0; + prRxCtrl->u4TotalRxPacketNum = 0; +#endif + +#if CFG_HIF_RX_STARVATION_WARNING + prRxCtrl->u4QueuedCnt = 0; + prRxCtrl->u4DequeuedCnt = 0; +#endif + +} /* end of nicRxInitialize() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Uninitialize the RFBs +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxUninitialize(IN P_ADAPTER_T prAdapter) +{ + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + nicRxFlush(prAdapter); + + do { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rReceivedRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + if (prSwRfb) { + if (prSwRfb->pvPacket) + kalPacketFree(prAdapter->prGlueInfo, prSwRfb->pvPacket); + prSwRfb->pvPacket = NULL; + } else { + break; + } + } while (TRUE); + + do { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + if (prSwRfb) { + if (prSwRfb->pvPacket) + kalPacketFree(prAdapter->prGlueInfo, prSwRfb->pvPacket); + prSwRfb->pvPacket = NULL; + } else { + break; + } + } while (TRUE); + +} /* end of nicRxUninitialize() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Fill RFB +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb specify the RFB to receive rx data +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxFillRFB(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) +{ + P_HW_MAC_RX_DESC_T prRxStatus; + + UINT_32 u4PktLen = 0; + /* UINT_32 u4MacHeaderLen; */ + UINT_32 u4HeaderOffset; + UINT_16 u2RxStatusOffset; + + DEBUGFUNC("nicRxFillRFB"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + u4PktLen = (UINT_32) HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus); + u4HeaderOffset = (UINT_32) (HAL_RX_STATUS_GET_HEADER_OFFSET(prRxStatus)); + /* u4MacHeaderLen = (UINT_32)(HAL_RX_STATUS_GET_HEADER_LEN(prRxStatus)); */ + + /* DBGLOG(RX, TRACE, ("u4HeaderOffset = %d, u4MacHeaderLen = %d\n", */ + /* u4HeaderOffset, u4MacHeaderLen)); */ + u2RxStatusOffset = sizeof(HW_MAC_RX_DESC_T); + prSwRfb->ucGroupVLD = (UINT_8) HAL_RX_STATUS_GET_GROUP_VLD(prRxStatus); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_4)) { + prSwRfb->prRxStatusGroup4 = (P_HW_MAC_RX_STS_GROUP_4_T) ((P_UINT_8) prRxStatus + u2RxStatusOffset); + u2RxStatusOffset += sizeof(HW_MAC_RX_STS_GROUP_4_T); + + } + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_1)) { + prSwRfb->prRxStatusGroup1 = (P_HW_MAC_RX_STS_GROUP_1_T) ((P_UINT_8) prRxStatus + u2RxStatusOffset); + u2RxStatusOffset += sizeof(HW_MAC_RX_STS_GROUP_1_T); + + } + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_2)) { + prSwRfb->prRxStatusGroup2 = (P_HW_MAC_RX_STS_GROUP_2_T) ((P_UINT_8) prRxStatus + u2RxStatusOffset); + u2RxStatusOffset += sizeof(HW_MAC_RX_STS_GROUP_2_T); + + } + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_3)) { + prSwRfb->prRxStatusGroup3 = (P_HW_MAC_RX_STS_GROUP_3_T) ((P_UINT_8) prRxStatus + u2RxStatusOffset); + u2RxStatusOffset += sizeof(HW_MAC_RX_STS_GROUP_3_T); + } + + prSwRfb->u2RxStatusOffst = u2RxStatusOffset; + prSwRfb->pvHeader = (PUINT_8) prRxStatus + u2RxStatusOffset + u4HeaderOffset; + prSwRfb->u2PacketLen = (UINT_16) (u4PktLen - (u2RxStatusOffset + u4HeaderOffset)); + prSwRfb->u2HeaderLen = (UINT_16) HAL_RX_STATUS_GET_HEADER_LEN(prRxStatus); + prSwRfb->ucWlanIdx = (UINT_8) HAL_RX_STATUS_GET_WLAN_IDX(prRxStatus); + prSwRfb->ucStaRecIdx = secGetStaIdxByWlanIdx(prAdapter, (UINT_8) HAL_RX_STATUS_GET_WLAN_IDX(prRxStatus)); + prSwRfb->prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + prSwRfb->ucTid = (UINT_8) HAL_RX_STATUS_GET_TID(prRxStatus); + + /* 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 Defragment the incoming packets. +* +* \param[in] prSWRfb The RFB which is being processed. +* \param[in] UINT_16 u2FrameCtrl +* +* \retval NOT NULL Receive the last fragment data +* \retval NULL Receive the fragment packet which is not the last +*/ +/*----------------------------------------------------------------------------*/ +P_SW_RFB_T nicRxDefragMPDU(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSWRfb, OUT P_QUE_T prReturnedQue) +{ + + P_SW_RFB_T prOutputSwRfb = (P_SW_RFB_T) NULL; +#if 1 + P_FRAG_INFO_T prFragInfo; + UINT_32 i = 0, j; + UINT_16 u2SeqCtrl, u2FrameCtrl; + UINT_8 ucFragNum; + BOOLEAN fgFirst = FALSE; + BOOLEAN fgLast = FALSE; + OS_SYSTIME rCurrentTime; + P_WLAN_MAC_HEADER_T prWlanHeader = NULL; + P_HW_MAC_RX_DESC_T prRxStatus = NULL; + P_HW_MAC_RX_STS_GROUP_4_T prRxStatusGroup4 = NULL; + + DEBUGFUNC("nicRx: rxmDefragMPDU\n"); + + ASSERT(prSWRfb); + + prRxStatus = prSWRfb->prRxStatus; + ASSERT(prRxStatus); + + if (HAL_RX_STATUS_IS_HEADER_TRAN(prRxStatus) == FALSE) { + prWlanHeader = (P_WLAN_MAC_HEADER_T) prSWRfb->pvHeader; + prSWRfb->u2SequenceControl = prWlanHeader->u2SeqCtrl; + u2FrameCtrl = prWlanHeader->u2FrameCtrl; + } else { + prRxStatusGroup4 = prSWRfb->prRxStatusGroup4; + prSWRfb->u2SequenceControl = HAL_RX_STATUS_GET_SEQFrag_NUM(prRxStatusGroup4); + u2FrameCtrl = HAL_RX_STATUS_GET_FRAME_CTL_FIELD(prRxStatusGroup4); + } + u2SeqCtrl = prSWRfb->u2SequenceControl; + ucFragNum = (UINT_8) (u2SeqCtrl & MASK_SC_FRAG_NUM); + prSWRfb->u2FrameCtrl = u2FrameCtrl; + + if (!(u2FrameCtrl & MASK_FC_MORE_FRAG)) { + /* The last fragment frame */ + if (ucFragNum) { + DBGLOG(RX, LOUD, + "FC %04hx M %d SQ %04hx\n", + u2FrameCtrl, !!(u2FrameCtrl & MASK_FC_MORE_FRAG), u2SeqCtrl); + fgLast = TRUE; + } + /* Non-fragment frame */ + else + return prSWRfb; + } + /* The fragment frame except the last one */ + else { + if (ucFragNum == 0) { + DBGLOG(RX, LOUD, + "FC %04hx M %d SQ %04hx\n", + u2FrameCtrl, !!(u2FrameCtrl & MASK_FC_MORE_FRAG), u2SeqCtrl); + fgFirst = TRUE; + } else { + DBGLOG(RX, LOUD, + "FC %04hx M %d SQ %04hx\n", + u2FrameCtrl, !!(u2FrameCtrl & MASK_FC_MORE_FRAG), u2SeqCtrl); + } + } + + GET_CURRENT_SYSTIME(&rCurrentTime); + + for (j = 0; j < MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS; j++) { + prFragInfo = &prSWRfb->prStaRec->rFragInfo[j]; + if (prFragInfo->pr1stFrag) { + /* I. If the receive timer for the MSDU or MMPDU that is stored in the + * fragments queue exceeds dot11MaxReceiveLifetime, we discard the + * uncompleted fragments. + * II. If we didn't receive the last MPDU for a period, we use + * this function for remove frames. + */ + if (CHECK_FOR_EXPIRATION(rCurrentTime, prFragInfo->rReceiveLifetimeLimit)) { + + /* cnmPktFree((P_PKT_INFO_T)prFragInfo->pr1stFrag, TRUE); */ + prFragInfo->pr1stFrag->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prFragInfo->pr1stFrag); + + prFragInfo->pr1stFrag = (P_SW_RFB_T) NULL; + } + } + } + + for (i = 0; i < MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS; i++) { + + prFragInfo = &prSWRfb->prStaRec->rFragInfo[i]; + + if (fgFirst) { /* looking for timed-out frag buffer */ + + if (prFragInfo->pr1stFrag == (P_SW_RFB_T) NULL) /* find a free frag buffer */ + break; + } else { /* looking for a buffer with desired next seqctrl */ + + if (prFragInfo->pr1stFrag == (P_SW_RFB_T) NULL) + continue; + + if (RXM_IS_QOS_DATA_FRAME(u2FrameCtrl)) { + if (RXM_IS_QOS_DATA_FRAME(prFragInfo->pr1stFrag->u2FrameCtrl)) { + if (u2SeqCtrl == prFragInfo->u2NextFragSeqCtrl) + break; + } + } else { + if (!RXM_IS_QOS_DATA_FRAME(prFragInfo->pr1stFrag->u2FrameCtrl)) { + if (u2SeqCtrl == prFragInfo->u2NextFragSeqCtrl) + break; + } + } + } + } + + if (i >= MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS) { + + /* Can't find a proper FRAG_INFO_T. + * I. 1st Fragment MPDU, all of the FragInfo are exhausted + * II. 2nd ~ (n-1)th Fragment MPDU, can't find the right FragInfo for defragment. + * Because we won't process fragment frame outside this function, so + * we should free it right away. + */ + nicRxReturnRFB(prAdapter, prSWRfb); + + return (P_SW_RFB_T) NULL; + } + + /* retrieve Rx payload */ + prSWRfb->u2HeaderLen = HAL_RX_STATUS_GET_HEADER_LEN(prRxStatus); + prSWRfb->pucPayload = (PUINT_8) (((ULONG) prSWRfb->pvHeader) + prSWRfb->u2HeaderLen); + prSWRfb->u2PayloadLength = + (UINT_16) (HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus) - ((ULONG) prSWRfb->pucPayload - (ULONG) prRxStatus)); + + if (fgFirst) { + DBGLOG(RX, LOUD, "rxDefragMPDU first\n"); + + SET_EXPIRATION_TIME(prFragInfo->rReceiveLifetimeLimit, + TU_TO_SYSTIME(DOT11_RECEIVE_LIFETIME_TU_DEFAULT)); + + prFragInfo->pr1stFrag = prSWRfb; + + prFragInfo->pucNextFragStart = + (PUINT_8) prSWRfb->pucRecvBuff + HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus); + + prFragInfo->u2NextFragSeqCtrl = u2SeqCtrl + 1; + DBGLOG(RX, LOUD, "First: nextFragmentSeqCtrl = %04x, u2SeqCtrl = %04x\n", + prFragInfo->u2NextFragSeqCtrl, u2SeqCtrl); + + /* prSWRfb->fgFragmented = TRUE; */ + /* whsu: todo for checksum */ + } else { + prFragInfo->pr1stFrag->prRxStatus->u2RxByteCount += prSWRfb->u2PayloadLength; + + if (prFragInfo->pr1stFrag->prRxStatus->u2RxByteCount > CFG_RX_MAX_PKT_SIZE) { + + prFragInfo->pr1stFrag->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prFragInfo->pr1stFrag); + + prFragInfo->pr1stFrag = (P_SW_RFB_T) NULL; + + nicRxReturnRFB(prAdapter, prSWRfb); + } else { + kalMemCopy(prFragInfo->pucNextFragStart, prSWRfb->pucPayload, prSWRfb->u2PayloadLength); + /* [6630] update rx byte count and packet length */ + prFragInfo->pr1stFrag->u2PacketLen += prSWRfb->u2PayloadLength; + prFragInfo->pr1stFrag->u2PayloadLength += prSWRfb->u2PayloadLength; + + if (fgLast) { /* The last one, free the buffer */ + DBGLOG(RX, LOUD, "Defrag: finished\n"); + + prOutputSwRfb = prFragInfo->pr1stFrag; + + prFragInfo->pr1stFrag = (P_SW_RFB_T) NULL; + } else { + DBGLOG(RX, LOUD, "Defrag: mid fraged\n"); + + prFragInfo->pucNextFragStart += prSWRfb->u2PayloadLength; + + prFragInfo->u2NextFragSeqCtrl++; + } + + nicRxReturnRFB(prAdapter, prSWRfb); + } + } + + /* DBGLOG_MEM8(RXM, INFO, */ + /* prFragInfo->pr1stFrag->pucPayload, */ + /* prFragInfo->pr1stFrag->u2PayloadLength); */ +#endif + return prOutputSwRfb; +} /* end of rxmDefragMPDU() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Do duplicate detection +* +* @param prSwRfb Pointer to the RX packet +* +* @return TRUE: a duplicate, FALSE: not a duplicate +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN nicRxIsDuplicateFrame(IN OUT P_SW_RFB_T prSwRfb) +{ + + /* Non-QoS Unicast Data or Unicast MMPDU: SC Cache #4; + * QoS Unicast Data: SC Cache #0~3; + * Broadcast/Multicast: RetryBit == 0 + */ + UINT_32 u4SeqCtrlCacheIdx; + UINT_16 u2SequenceControl, u2FrameCtrl; + BOOLEAN fgIsDuplicate = FALSE, fgIsAmsduSubframe = FALSE; + P_WLAN_MAC_HEADER_T prWlanHeader = NULL; + P_HW_MAC_RX_DESC_T prRxStatus = NULL; + P_HW_MAC_RX_STS_GROUP_4_T prRxStatusGroup4 = NULL; + + DEBUGFUNC("nicRx: Enter rxmIsDuplicateFrame()\n"); + + ASSERT(prSwRfb); + + /* Situations in which the STC_REC is missing include: + * (1) Probe Request (2) (Re)Association Request (3) IBSS data frames (4) Probe Response + */ + if (!prSwRfb->prStaRec) + return FALSE; + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + fgIsAmsduSubframe = HAL_RX_STATUS_GET_PAYLOAD_FORMAT(prRxStatus); + if (HAL_RX_STATUS_IS_HEADER_TRAN(prRxStatus) == FALSE) { + prWlanHeader = (P_WLAN_MAC_HEADER_T) prSwRfb->pvHeader; + u2SequenceControl = prWlanHeader->u2SeqCtrl; + u2FrameCtrl = prWlanHeader->u2FrameCtrl; + } else { + prRxStatusGroup4 = prSwRfb->prRxStatusGroup4; + u2SequenceControl = HAL_RX_STATUS_GET_SEQFrag_NUM(prRxStatusGroup4); + u2FrameCtrl = HAL_RX_STATUS_GET_FRAME_CTL_FIELD(prRxStatusGroup4); + } + prSwRfb->u2SequenceControl = u2SequenceControl; + + /* Case 1: Unicast QoS data */ + if (RXM_IS_QOS_DATA_FRAME(u2FrameCtrl)) { /* WLAN header shall exist when doing duplicate detection */ + if (prSwRfb->prStaRec->aprRxReorderParamRefTbl[prSwRfb->ucTid]) { + + /* QoS data with an RX BA agreement + * Case 1: The packet is not an AMPDU subframe, so the RetryBit may be set to 1 (TBC). + * Case 2: The RX BA agreement was just established. Some enqueued packets may not be + * sent with aggregation. + */ + + DBGLOG(RX, LOUD, "RX: SC=0x%X (BA Entry present)\n", u2SequenceControl); + + /* + * Update the SN cache in order to ensure the correctness of duplicate + * removal in case the BA agreement is deleted + */ + prSwRfb->prStaRec->au2CachedSeqCtrl[prSwRfb->ucTid] = u2SequenceControl; + + /* debug */ +#if 0 + DBGLOG(RXM, LOUD, "RXM: SC= 0x%X (Cache[%d] updated) with BA\n", + u2SequenceControl, prSwRfb->ucTID); + + if (g_prMqm->arRxBaTable[prSwRfb->prStaRec->aucRxBaTable[prSwRfb->ucTID]].ucStatus == + BA_ENTRY_STATUS_DELETING) { + DBGLOG(RXM, LOUD, + "RXM: SC= 0x%X (Cache[%d] updated) with DELETING BA ****************\n", + u2SequenceControl, prSwRfb->ucTID); + } +#endif + + /* HW scoreboard shall take care Case 1. Let the layer layer handle Case 2. */ + return FALSE; /* Not a duplicate */ + } + + if (prSwRfb->prStaRec->ucDesiredPhyTypeSet & (PHY_TYPE_BIT_HT | PHY_TYPE_BIT_VHT)) { + u4SeqCtrlCacheIdx = prSwRfb->ucTid; + } else { + if (prSwRfb->ucTid < 8) { /* UP = 0~7 */ + u4SeqCtrlCacheIdx = aucTid2ACI[prSwRfb->ucTid]; + } else { + DBGLOG(RX, WARN, + "RXM: (Warning) Unknown QoS Data with TID=%d\n", prSwRfb->ucTid); + return TRUE; /* Will be dropped */ + } + } + + } + /* Case 2: Unicast non-QoS data or MMPDUs */ + else + u4SeqCtrlCacheIdx = TID_NUM; + + /* If this is a retransmission */ + if (u2FrameCtrl & MASK_FC_RETRY) { + if (u2SequenceControl != prSwRfb->prStaRec->au2CachedSeqCtrl[u4SeqCtrlCacheIdx]) { + prSwRfb->prStaRec->au2CachedSeqCtrl[u4SeqCtrlCacheIdx] = u2SequenceControl; + if (fgIsAmsduSubframe == RX_PAYLOAD_FORMAT_FIRST_SUB_AMSDU) + prSwRfb->prStaRec->afgIsIgnoreAmsduDuplicate[u4SeqCtrlCacheIdx] = TRUE; + DBGLOG(RX, LOUD, "RXM: SC= 0x%hX (Cache[%u] updated)\n", u2SequenceControl, u4SeqCtrlCacheIdx); + } else { + /* A duplicate. */ + if (prSwRfb->prStaRec->afgIsIgnoreAmsduDuplicate[u4SeqCtrlCacheIdx]) { + if (fgIsAmsduSubframe == RX_PAYLOAD_FORMAT_LAST_SUB_AMSDU) + prSwRfb->prStaRec->afgIsIgnoreAmsduDuplicate[u4SeqCtrlCacheIdx] = FALSE; + } else { + fgIsDuplicate = TRUE; + DBGLOG(RX, LOUD, "RXM: SC= 0x%hX (Cache[%u] duplicate)\n", + u2SequenceControl, u4SeqCtrlCacheIdx); + } + } + } + + /* Not a retransmission */ + else { + + prSwRfb->prStaRec->au2CachedSeqCtrl[u4SeqCtrlCacheIdx] = u2SequenceControl; + prSwRfb->prStaRec->afgIsIgnoreAmsduDuplicate[u4SeqCtrlCacheIdx] = FALSE; + + DBGLOG(RX, LOUD, "RXM: SC= 0x%hX (Cache[%u] updated)\n", u2SequenceControl, u4SeqCtrlCacheIdx); + } + + return fgIsDuplicate; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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; +#if !defined(LINUX) + UINT_32 u4CurrentRxBufferCount; +#endif + /* P_STA_RECORD_T prStaRec = (P_STA_RECORD_T)NULL; */ +#if CFG_SUPPORT_MULTITHREAD + KAL_SPIN_LOCK_DECLARATION(); +#endif + DEBUGFUNC("nicRxProcessPktWithoutReorder"); + /* DBGLOG(RX, TRACE, ("\n")); */ + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); +#if !defined(LINUX) + u4CurrentRxBufferCount = prRxCtrl->rFreeSwRfbList.u4NumElem; +#endif + /* QM USED = $A, AVAILABLE COUNT = $B, INDICATED TO OS = $C + * TOTAL = $A + $B + $C + * + * Case #1 (Retain) + * ------------------------------------------------------- + * $A + $B < THRESHOLD := $A + $B + $C < THRESHOLD + $C := $TOTAL - THRESHOLD < $C + * => $C used too much, retain + * + * Case #2 (Non-Retain) + * ------------------------------------------------------- + * $A + $B > THRESHOLD := $A + $B + $C > THRESHOLD + $C := $TOTAL - THRESHOLD > $C + * => still available for $C to use + * + */ + +#if defined(LINUX) + fgIsRetained = FALSE; +#else + fgIsRetained = (((u4CurrentRxBufferCount + + qmGetRxReorderQueuedBufferCount(prAdapter) + + prTxCtrl->i4PendingFwdFrameCount) < CFG_RX_RETAINED_PKT_THRESHOLD) ? TRUE : FALSE); +#endif + + /* DBGLOG(RX, INFO, ("fgIsRetained = %d\n", fgIsRetained)); */ +#if CFG_ENABLE_PER_STA_STATISTICS + if (prSwRfb->prStaRec && (prAdapter->rWifiVar.rWfdConfigureSettings.ucWfdEnable > 0)) + prSwRfb->prStaRec->u4TotalRxPktsNumber++; +#endif + 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"); + + nicRxReturnRFB(prAdapter, prSwRfb); + return; + } + +#if !CFG_SUPPORT_MULTITHREAD + prRxCtrl->apvIndPacket[prRxCtrl->ucNumIndPacket] = prSwRfb->pvPacket; + prRxCtrl->ucNumIndPacket++; +#endif + +#if CFG_SUPPORT_MULTITHREAD + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); + QUEUE_INSERT_TAIL(&(prAdapter->rRxQueue), (P_QUE_ENTRY_T) GLUE_GET_PKT_QUEUE_ENTRY(prSwRfb->pvPacket)); + prRxCtrl->ucNumIndPacket++; +#endif + +#if !defined(LINUX) + if (fgIsRetained) { + prRxCtrl->apvRetainedPacket[prRxCtrl->ucNumRetainedPacket] = prSwRfb->pvPacket; + prRxCtrl->ucNumRetainedPacket++; + /* TODO : error handling of nicRxSetupRFB */ + nicRxSetupRFB(prAdapter, prSwRfb); + nicRxReturnRFB(prAdapter, prSwRfb); + } else +#endif + { + prSwRfb->pvPacket = NULL; + nicRxReturnRFB(prAdapter, prSwRfb); + } + +#if CFG_SUPPORT_MULTITHREAD + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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; + + prMsduInfo = cnmPktAlloc(prAdapter, 0); + + 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) { + + /* parsing forward frame */ + wlanProcessTxFrame(prAdapter, (P_NATIVE_PACKET) (prSwRfb->pvPacket)); + /* pack into MSDU_INFO_T */ + nicTxFillMsduInfo(prAdapter, prMsduInfo, (P_NATIVE_PACKET) (prSwRfb->pvPacket)); + + prMsduInfo->eSrc = TX_PACKET_FORWARDING; + prMsduInfo->ucBssIndex = secGetBssIdxByWlanIdx(prAdapter, prSwRfb->ucWlanIdx); + prMsduInfo->ucUserPriority = prSwRfb->ucTid; + + /* 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 */ + DBGLOG(QM, INFO, "No Tx MSDU_INFO for forwarding frames\n"); + nicRxReturnRFB(prAdapter, prSwRfb); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process broadcast data packet for both host and forwarding +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxProcessGOBroadcastPkt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_SW_RFB_T prSwRfbDuplicated; + P_TX_CTRL_T prTxCtrl; + P_RX_CTRL_T prRxCtrl; + P_HW_MAC_RX_DESC_T prRxStatus; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxProcessGOBroadcastPkt"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prTxCtrl = &prAdapter->rTxCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + 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_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfbDuplicated, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + if (prSwRfbDuplicated) { + kalMemCopy(prSwRfbDuplicated->pucRecvBuff, + prSwRfb->pucRecvBuff, ALIGN_4(prRxStatus->u2RxByteCount + HIF_RX_HW_APPENDED_LEN)); + + prSwRfbDuplicated->ucPacketType = RX_PKT_TYPE_RX_DATA; + prSwRfbDuplicated->ucStaRecIdx = prSwRfb->ucStaRecIdx; + nicRxFillRFB(prAdapter, prSwRfbDuplicated); + + /* 2. Modify eDst */ + prSwRfbDuplicated->eDst = RX_PKT_DESTINATION_FORWARD; + + GLUE_SET_PKT_BSS_IDX(prSwRfbDuplicated->pvPacket, + secGetBssIdxByWlanIdx(prAdapter, prSwRfbDuplicated->ucWlanIdx)); + + /* 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); + +} + +#if CFG_SUPPORT_SNIFFER +VOID nicRxFillRadiotapMCS(IN OUT P_MONITOR_RADIOTAP_T prMonitorRadiotap, IN P_HW_MAC_RX_STS_GROUP_3_T prRxStatusGroup3) +{ + UINT_8 ucFrMode; + UINT_8 ucShortGI; + UINT_8 ucRxMode; + UINT_8 ucLDPC; + UINT_8 ucSTBC; + UINT_8 ucNess; + + ucFrMode = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET); + /* VHTA1 B0-B1 */ + ucShortGI = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_SHORT_GI) ? 1 : 0; /* HT_shortgi */ + ucRxMode = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_RX_MODE_MASK) >> RX_VT_RX_MODE_OFFSET); + ucLDPC = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_LDPC) ? 1 : 0; /* HT_adcode */ + ucSTBC = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_STBC_MASK) >> RX_VT_STBC_OFFSET); /* HT_stbc */ + ucNess = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_NESS_MASK) >> RX_VT_NESS_OFFSET); /* HT_extltf */ + + prMonitorRadiotap->ucMcsKnown = (BITS(0, 6) | (((ucNess & BIT(1)) >> 1) << 7)); + + prMonitorRadiotap->ucMcsFlags = ((ucFrMode) | + (ucShortGI << 2) | + ((ucRxMode & BIT(0)) << 3) | + (ucLDPC << 4) | (ucSTBC << 5) | ((ucNess & BIT(0)) << 7)); + /* Bit[6:0] for 802.11n, mcs0 ~ mcs7 */ + prMonitorRadiotap->ucMcsMcs = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_RX_RATE_MASK); +} + +VOID nicRxFillRadiotapVHT(IN OUT P_MONITOR_RADIOTAP_T prMonitorRadiotap, IN P_HW_MAC_RX_STS_GROUP_3_T prRxStatusGroup3) +{ + UINT_8 ucSTBC; + UINT_8 ucTxopPsNotAllow; + UINT_8 ucShortGI; + UINT_8 ucNsym; + UINT_8 ucLDPC; + UINT_8 ucBeamFormed; + UINT_8 ucFrMode; + UINT_8 ucNsts; + UINT_8 ucMcs; + + prMonitorRadiotap->u2VhtKnown = BITS(0, 8); + + ucSTBC = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_STBC_MASK) >> RX_VT_STBC_OFFSET); /* BIT[7]: VHTA1 B3 */ + ucTxopPsNotAllow = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_TXOP_PS_NOT_ALLOWED) ? 1 : 0; /* VHTA1 B22 */ + ucShortGI = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_SHORT_GI) ? 1 : 0; /* VHTA2 B0 */ + ucNsym = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_SHORT_GI_NSYM) ? 1 : 0; /* VHTA2 B1 */ + ucLDPC = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_LDPC) ? 1 : 0; /* HT_adcode */ + ucBeamFormed = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_BEAMFORMED) ? 1 : 0; /* VHTA2 B8 */ + prMonitorRadiotap->ucVhtFlags = ((ucSTBC) | + (ucTxopPsNotAllow << 1) | + (ucShortGI << 2) | (ucNsym << 3) | (ucLDPC << 4) | (ucBeamFormed << 5)); + + ucFrMode = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET); + /* VHTA1 B0-B1 */ + switch (ucFrMode) { + case RX_VT_FR_MODE_20: + prMonitorRadiotap->ucVhtBandwidth = 0; + break; + case RX_VT_FR_MODE_40: + prMonitorRadiotap->ucVhtBandwidth = 1; + break; + case RX_VT_FR_MODE_80: + prMonitorRadiotap->ucVhtBandwidth = 4; + break; + case RX_VT_FR_MODE_160: + prMonitorRadiotap->ucVhtBandwidth = 11; + break; + default: + prMonitorRadiotap->ucVhtBandwidth = 0; + } + + /* Set to 0~7 for 1~8 space time streams */ + ucNsts = (((prRxStatusGroup3)->u4RxVector[1] & RX_VT_NSTS_MASK) >> RX_VT_NSTS_OFFSET) + 1; + /* VHTA1 B10-B12 */ + + /* Bit[3:0] for 802.11ac, mcs0 ~ mcs9 */ + ucMcs = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_RX_RATE_AC_MASK); + + /* STBC = Nsts - Nss */ + prMonitorRadiotap->aucVhtMcsNss[0] = ((ucMcs << 4) | (ucNsts - ucSTBC)); + + /* VHTA2 B2-B3 */ + prMonitorRadiotap->ucVhtCoding = (((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_CODING_MASK) >> RX_VT_CODING_OFFSET); + /* VHTA1 B4-B9 */ + prMonitorRadiotap->ucVhtGroupId = (((((prRxStatusGroup3)->u4RxVector[1] & + RX_VT_GROUPID_1_MASK) >> RX_VT_GROUPID_1_OFFSET) + << 2) | (((prRxStatusGroup3)->u4RxVector[0] + & RX_VT_GROUPID_0_MASK) >> RX_VT_GROUPID_0_OFFSET)); + /* VHTA1 B13-B21 */ + prMonitorRadiotap->u2VhtPartialAid = ((((prRxStatusGroup3)->u4RxVector[2] & + RX_VT_AID_1_MASK) << 4) | + (((prRxStatusGroup3)->u4RxVector[1] & + RX_VT_AID_0_MASK) >> RX_VT_AID_0_OFFSET)); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process HIF monitor packet +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxProcessMonitorPacket(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) +{ + struct sk_buff *prSkb = NULL; + P_RX_CTRL_T prRxCtrl; + P_HW_MAC_RX_DESC_T prRxStatus; + P_HW_MAC_RX_STS_GROUP_2_T prRxStatusGroup2; + P_HW_MAC_RX_STS_GROUP_3_T prRxStatusGroup3; + MONITOR_RADIOTAP_T rMonitorRadiotap; + RADIOTAP_FIELD_VENDOR_T rRadiotapFieldVendor; + PUINT_8 prVendorNsOffset; + UINT_32 u4VendorNsLen; + UINT_32 u4RadiotapLen; + UINT_32 u4ItPresent; + UINT_8 aucMtkOui[] = VENDOR_OUI_MTK; + UINT_8 ucRxRate; + UINT_8 ucRxMode; + UINT_8 ucChanNum; + UINT_8 ucMcs; + UINT_8 ucFrMode; + UINT_8 ucShortGI; + UINT_32 u4PhyRate; + +#if CFG_SUPPORT_MULTITHREAD + KAL_SPIN_LOCK_DECLARATION(); +#endif + + DEBUGFUNC("nicRxProcessMonitorPacket"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + + nicRxFillRFB(prAdapter, prSwRfb); + + /* can't parse radiotap info if no rx vector */ + if (((prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_2)) == 0) || ((prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_3)) == 0)) { + nicRxReturnRFB(prAdapter, prSwRfb); + return; + } + + prRxStatus = prSwRfb->prRxStatus; + prRxStatusGroup2 = prSwRfb->prRxStatusGroup2; + prRxStatusGroup3 = prSwRfb->prRxStatusGroup3; + + /* Bit Number 30 Vendor Namespace */ + u4VendorNsLen = sizeof(RADIOTAP_FIELD_VENDOR_T); + rRadiotapFieldVendor.aucOUI[0] = aucMtkOui[0]; + rRadiotapFieldVendor.aucOUI[1] = aucMtkOui[1]; + rRadiotapFieldVendor.aucOUI[2] = aucMtkOui[2]; + rRadiotapFieldVendor.ucSubNamespace = 0; + rRadiotapFieldVendor.u2DataLen = u4VendorNsLen - 6; + /* VHTA1 B0-B1 */ + rRadiotapFieldVendor.ucData = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_FR_MODE_MASK) >> + RX_VT_FR_MODE_OFFSET); + + ucRxMode = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_RX_MODE_MASK) >> RX_VT_RX_MODE_OFFSET); + + if (ucRxMode == RX_VT_VHT_MODE) { + u4RadiotapLen = RADIOTAP_LEN_VHT; + u4ItPresent = RADIOTAP_FIELDS_VHT; + } else if ((ucRxMode == RX_VT_MIXED_MODE) || (ucRxMode == RX_VT_GREEN_MODE)) { + u4RadiotapLen = RADIOTAP_LEN_HT; + u4ItPresent = RADIOTAP_FIELDS_HT; + } else { + u4RadiotapLen = RADIOTAP_LEN_LEGACY; + u4ItPresent = RADIOTAP_FIELDS_LEGACY; + } + + /* Radiotap Header & Bit Number 30 Vendor Namespace */ + prVendorNsOffset = (PUINT_8) &rMonitorRadiotap + u4RadiotapLen; + u4RadiotapLen += u4VendorNsLen; + kalMemSet(&rMonitorRadiotap, 0, sizeof(MONITOR_RADIOTAP_T)); + kalMemCopy(prVendorNsOffset, (PUINT_8) &rRadiotapFieldVendor, u4VendorNsLen); + rMonitorRadiotap.u2ItLen = cpu_to_le16(u4RadiotapLen); + rMonitorRadiotap.u4ItPresent = u4ItPresent; + + /* Bit Number 0 TSFT */ + rMonitorRadiotap.u8MacTime = (prRxStatusGroup2->u4Timestamp); + + /* Bit Number 1 FLAGS */ + if (HAL_RX_STATUS_IS_FRAG(prRxStatus) == TRUE) + rMonitorRadiotap.ucFlags |= BIT(3); + + if (HAL_RX_STATUS_IS_FCS_ERROR(prRxStatus) == TRUE) + rMonitorRadiotap.ucFlags |= BIT(6); + + /* Bit Number 2 RATE */ + if ((ucRxMode == RX_VT_LEGACY_CCK) || (ucRxMode == RX_VT_LEGACY_OFDM)) { + /* Bit[2:0] for Legacy CCK, Bit[3:0] for Legacy OFDM */ + ucRxRate = ((prRxStatusGroup3)->u4RxVector[0] & BITS(0, 3)); + rMonitorRadiotap.ucRate = nicGetHwRateByPhyRate(ucRxRate); + } else { + ucMcs = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_RX_RATE_AC_MASK); + /* VHTA1 B0-B1 */ + ucFrMode = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET); + ucShortGI = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_SHORT_GI) ? 1 : 0; /* VHTA2 B0 */ + + /* ucRate(500kbs) = u4PhyRate(100kbps) / 5, max ucRate = 0xFF */ + u4PhyRate = nicGetPhyRateByMcsRate(ucMcs, ucFrMode, ucShortGI); + if (u4PhyRate > 1275) + rMonitorRadiotap.ucRate = 0xFF; + else + rMonitorRadiotap.ucRate = u4PhyRate / 5; + } + + /* Bit Number 3 CHANNEL */ + if (ucRxMode == RX_VT_LEGACY_CCK) + rMonitorRadiotap.u2ChFlags |= BIT(5); + else /* OFDM */ + rMonitorRadiotap.u2ChFlags |= BIT(6); + + ucChanNum = HAL_RX_STATUS_GET_CHNL_NUM(prRxStatus); + if (HAL_RX_STATUS_GET_RF_BAND(prRxStatus) == BAND_2G4) { + rMonitorRadiotap.u2ChFlags |= BIT(7); + rMonitorRadiotap.u2ChFrequency = (ucChanNum * 5 + 2407); + } else { /* BAND_5G */ + rMonitorRadiotap.u2ChFlags |= BIT(8); + rMonitorRadiotap.u2ChFrequency = (ucChanNum * 5 + 5000); + } + + /* Bit Number 5 ANT SIGNAL */ + rMonitorRadiotap.ucAntennaSignal = (((prRxStatusGroup3)->u4RxVector[3] & RX_VT_IB_RSSI_MASK)); + + /* Bit Number 6 ANT NOISE */ + rMonitorRadiotap.ucAntennaNoise = ((((prRxStatusGroup3)->u4RxVector[5] & RX_VT_NF0_MASK) >> 1) + 128); + + /* Bit Number 11 ANT */ + rMonitorRadiotap.ucAntenna = ((prRxStatusGroup3)->u4RxVector[2] & RX_VT_SEL_ANT) ? 1 : 0; + + /* Bit Number 19 MCS */ + if ((u4ItPresent & RADIOTAP_FIELD_MCS)) + nicRxFillRadiotapMCS(&rMonitorRadiotap, prRxStatusGroup3); + + /* Bit Number 20 AMPDU */ + if (HAL_RX_STATUS_IS_AMPDU_SUB_FRAME(prRxStatus)) { + if (HAL_RX_STATUS_GET_RXV_SEQ_NO(prRxStatus)) + ++prRxCtrl->u4AmpduRefNum; + rMonitorRadiotap.u4AmpduRefNum = prRxCtrl->u4AmpduRefNum; + } + + /* Bit Number 21 VHT */ + if ((u4ItPresent & RADIOTAP_FIELD_VHT)) + nicRxFillRadiotapVHT(&rMonitorRadiotap, prRxStatusGroup3); + + prSwRfb->pvHeader -= u4RadiotapLen; + kalMemCopy(prSwRfb->pvHeader, &rMonitorRadiotap, u4RadiotapLen); + + prSkb = (struct sk_buff *)(prSwRfb->pvPacket); + prSkb->data = (unsigned char *)(prSwRfb->pvHeader); + + skb_reset_tail_pointer(prSkb); + skb_trim(prSkb, 0); + skb_put(prSkb, (u4RadiotapLen + prSwRfb->u2PacketLen)); + +#if CFG_SUPPORT_MULTITHREAD + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); + QUEUE_INSERT_TAIL(&(prAdapter->rRxQueue), (P_QUE_ENTRY_T) GLUE_GET_PKT_QUEUE_ENTRY(prSwRfb->pvPacket)); + prRxCtrl->ucNumIndPacket++; +#else + prRxCtrl->apvIndPacket[prRxCtrl->ucNumIndPacket] = prSwRfb->pvPacket; + prRxCtrl->ucNumIndPacket++; +#endif + + prSwRfb->pvPacket = NULL; + nicRxReturnRFB(prAdapter, prSwRfb); + +#if CFG_SUPPORT_MULTITHREAD + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); +#endif +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process HIF data packet +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +static UINT_32 u4LastRxPacketTime; +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_HW_MAC_RX_DESC_T prRxStatus; + BOOLEAN fgDrop; + P_STA_RECORD_T prStaRec; + UINT_8 ucBssIndex = 0; + UINT_8 ucKeyCmdAction = SEC_TX_KEY_COMMAND; + UINT_32 uEapolKeyType; + + DEBUGFUNC("nicRxProcessDataPacket"); + /* DBGLOG(INIT, TRACE, ("\n")); */ + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + fgDrop = FALSE; + + prRxStatus = prSwRfb->prRxStatus; + prRxCtrl = &prAdapter->rRxCtrl; + + /* Check AMPDU_nERR_Bitmap */ + prSwRfb->fgDataFrame = TRUE; + prSwRfb->fgFragFrame = FALSE; + prSwRfb->fgReorderBuffer = FALSE; + + /* BA session */ + if ((prRxStatus->u2StatusFlag & RXS_DW2_AMPDU_nERR_BITMAP) == RXS_DW2_AMPDU_nERR_VALUE) + prSwRfb->fgReorderBuffer = TRUE; + /* non BA session */ + else if ((prRxStatus->u2StatusFlag & RXS_DW2_RX_nERR_BITMAP) == RXS_DW2_RX_nERR_VALUE) { + if ((prRxStatus->u2StatusFlag & RXS_DW2_RX_nDATA_BITMAP) == RXS_DW2_RX_nDATA_VALUE) + prSwRfb->fgDataFrame = FALSE; + + if ((prRxStatus->u2StatusFlag & RXS_DW2_RX_FRAG_BITMAP) == RXS_DW2_RX_FRAG_VALUE) + prSwRfb->fgFragFrame = TRUE; + + } else { + fgDrop = TRUE; + if (!HAL_RX_STATUS_IS_ICV_ERROR(prRxStatus) + && HAL_RX_STATUS_IS_TKIP_MIC_ERROR(prRxStatus)) { + prStaRec = cnmGetStaRecByAddress(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, + prAdapter->rWlanInfo.rCurrBssId.arMacAddress); + if (prStaRec) { + DBGLOG(RSN, ERROR, "MIC_ERR_PKT\n"); + rsnTkipHandleMICFailure(prAdapter, prStaRec, 0); + } + } else if (HAL_RX_STATUS_IS_LLC_MIS(prRxStatus)) { + DBGLOG(RSN, ERROR, "LLC_MIS_ERR\n"); + fgDrop = TRUE; /* Drop after send de-auth */ + } + } + +#if CFG_TCP_IP_CHKSUM_OFFLOAD || CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 + if (fgDrop == FALSE) { + UINT_32 u4TcpUdpIpCksStatus; + PUINT_32 pu4Temp; + + pu4Temp = (PUINT_32) prRxStatus; + u4TcpUdpIpCksStatus = *(pu4Temp + (ALIGN_4(prRxStatus->u2RxByteCount) >> 2)); + nicRxFillChksumStatus(prAdapter, prSwRfb, u4TcpUdpIpCksStatus); + } +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + /* if(secCheckClassError(prAdapter, prSwRfb, prStaRec) == TRUE && */ + if (prAdapter->fgTestMode || fgDrop) { + nicRxReturnRFB(prAdapter, prSwRfb); + RX_INC_CNT(prRxCtrl, RX_CLASS_ERR_DROP_COUNT); + RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); + return; + } + +#if CFG_HIF_RX_STARVATION_WARNING + prRxCtrl->u4QueuedCnt++; +#endif + nicRxFillRFB(prAdapter, prSwRfb); + ucBssIndex = secGetBssIdxByWlanIdx(prAdapter, prSwRfb->ucWlanIdx); + GLUE_SET_PKT_BSS_IDX(prSwRfb->pvPacket, ucBssIndex); + StatsRxPktInfoDisplay(prAdapter, prSwRfb); + + prRetSwRfb = qmHandleRxPackets(prAdapter, prSwRfb); + + while (prRetSwRfb) { +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + if (prRetSwRfb->ucGroupVLD + & BIT(RX_GROUP_VLD_3)) { + prAdapter->arStaRec[prRetSwRfb->ucStaRecIdx].u4RxVector0 = + HAL_RX_VECTOR_GET_RX_VECTOR( + prRetSwRfb->prRxStatusGroup3, 0); + prAdapter->arStaRec[prRetSwRfb->ucStaRecIdx].u4RxVector1 = + HAL_RX_VECTOR_GET_RX_VECTOR( + prRetSwRfb->prRxStatusGroup3, 1); + prAdapter->arStaRec[prRetSwRfb->ucStaRecIdx].u4RxVector2 = + HAL_RX_VECTOR_GET_RX_VECTOR( + prRetSwRfb->prRxStatusGroup3, 2); + prAdapter->arStaRec[prRetSwRfb->ucStaRecIdx].u4RxVector3 = + HAL_RX_VECTOR_GET_RX_VECTOR( + prRetSwRfb->prRxStatusGroup3, 3); + prAdapter->arStaRec[prRetSwRfb->ucStaRecIdx].u4RxVector4 = + HAL_RX_VECTOR_GET_RX_VECTOR( + prRetSwRfb->prRxStatusGroup3, 4); + } +#endif + /* 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: + prStaRec = cnmGetStaRecByIndex(prAdapter, prRetSwRfb->ucStaRecIdx); + if (prStaRec && IS_STA_IN_AIS(prStaRec)) { +#if ARP_MONITER_ENABLE + qmHandleRxArpPackets(prAdapter, prRetSwRfb); + qmHandleRxDhcpPackets(prAdapter, prRetSwRfb); +#endif + u4LastRxPacketTime = kalGetTimeTick(); + } + + do { + if (prRetSwRfb->u2PacketLen <= ETHER_HEADER_LEN) { + DBGLOG(RX, ERROR, "Packet Length is %d\n", prRetSwRfb->u2PacketLen); + break; + } + uEapolKeyType = secGetEapolKeyType((PUINT_8)prRetSwRfb->pvHeader); + if (uEapolKeyType != EAPOL_KEY_3_OF_4) + break; + /* STA has install key,and AP encrypted 3/4 Eapol frame + * We will set key after AP reply ACK for 4/4 + */ +#if CFG_SUPPORT_REPORT_MISC + if (prAdapter->rReportMiscSet.eQueryNum == REPORT_4WAYHS_START) { + wlanSendSetQueryCmd(prAdapter, CMD_ID_GET_REPORT_MISC, + FALSE, + TRUE, + FALSE, + nicCmdEventReportMisc, + NULL, + 0, + NULL, + NULL, + 0); + prAdapter->rReportMiscSet.eQueryNum = REPORT_4WAYHS_END; + } +#endif + if (HAL_RX_STATUS_GET_SEC_MODE(prRxStatus) != 0 && + HAL_RX_STATUS_IS_CIPHER_MISMATCH(prRxStatus) == 0) + ucKeyCmdAction = SEC_QUEUE_KEY_COMMAND; + if (ucBssIndex <= HW_BSSID_NUM) { + secSetKeyCmdAction(prAdapter->aprBssInfo[ucBssIndex], EAPOL_KEY_3_OF_4, + ucKeyCmdAction); + break; + } else if (prStaRec && prStaRec->ucBssIndex <= HW_BSSID_NUM) { + DBGLOG(RX, INFO, + "BSS IDX got from wlan idx is wrong, using bss index from sta record\n"); + secSetKeyCmdAction(prAdapter->aprBssInfo[prStaRec->ucBssIndex], + EAPOL_KEY_3_OF_4, ucKeyCmdAction); + break; + } + ucBssIndex = secGetBssIdxByNetType(prAdapter); + if (ucBssIndex <= HW_BSSID_NUM) { + secSetKeyCmdAction(prAdapter->aprBssInfo[ucBssIndex], EAPOL_KEY_3_OF_4, + ucKeyCmdAction); + break; + } + DBGLOG(RX, ERROR, "Can't get bss index base on network type\n"); + } while (FALSE); + + 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; + + } +} + +#if CFG_SUPPORT_GSCN +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process GSCAN event packet +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 nicRxProcessGSCNEvent(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) +{ + P_SCAN_INFO_T prScanInfo; + P_WIFI_EVENT_T prEvent; + P_GLUE_INFO_T prGlueInfo; + struct wiphy *wiphy; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prEvent = (P_WIFI_EVENT_T) prSwRfb->pucRecvBuff; + prGlueInfo = prAdapter->prGlueInfo; + /* Push the data to the skb */ + wiphy = priv_to_wiphy(prGlueInfo); + + /* Event Handling */ + switch (prEvent->ucEID) { + case EVENT_ID_GSCAN_SCAN_AVAILABLE: + { + P_EVENT_GSCAN_SCAN_AVAILABLE_T prEventGscnAvailable; + + DBGLOG(SCN, INFO, "EVENT_ID_GSCAN_SCAN_AVAILABLE\n"); + prEventGscnAvailable = (P_EVENT_GSCAN_SCAN_AVAILABLE_T) (prEvent->aucBuffer); + mtk_cfg80211_vendor_event_scan_results_available(wiphy, + prGlueInfo->prDevHandler->ieee80211_ptr, prEventGscnAvailable->u2Num); + } + break; + + case EVENT_ID_GSCAN_RESULT: + { + P_EVENT_GSCAN_RESULT_T prEventBuffer; + + DBGLOG(SCN, INFO, "EVENT_ID_GSCAN_RESULT 2\n"); + prEventBuffer = (P_EVENT_GSCAN_RESULT_T) (prEvent->aucBuffer); + /* scnFsmGSCNResults(prAdapter, prEventBuffer); */ + } + break; + + case EVENT_ID_GSCAN_CAPABILITY: + { + P_EVENT_GSCAN_CAPABILITY_T prEventGscnCapbiblity; + + DBGLOG(SCN, INFO, "EVENT_ID_GSCAN_CAPABILITY\n"); + prEventGscnCapbiblity = (P_EVENT_GSCAN_CAPABILITY_T) (prEvent->aucBuffer); + mtk_cfg80211_vendor_get_gscan_capabilities(wiphy, prGlueInfo->prDevHandler->ieee80211_ptr, + prEventGscnCapbiblity, sizeof(EVENT_GSCAN_CAPABILITY_T)); + } + break; + + case EVENT_ID_GSCAN_SCAN_COMPLETE: + { + P_EVENT_GSCAN_SCAN_COMPLETE_T prEventGscnScnDone; + + DBGLOG(SCN, INFO, "EVENT_ID_GSCAN_SCAN_COMPLETE\n"); + prEventGscnScnDone = (P_EVENT_GSCAN_SCAN_COMPLETE_T) (prEvent->aucBuffer); + mtk_cfg80211_vendor_event_complete_scan(wiphy, + prGlueInfo->prDevHandler->ieee80211_ptr, prEventGscnScnDone->ucScanState); + } + break; + + case EVENT_ID_GSCAN_FULL_RESULT: + { + UINT_32 ie_len = 0; + P_EVENT_GSCAN_FULL_RESULT_T prEventGscnFullResult; + /* P_PARAM_WIFI_GSCAN_FULL_RESULT prParamGscnFullResult; */ + + DBGLOG(SCN, TRACE, "EVENT_ID_GSCAN_FULL_RESULT\n"); + + prEventGscnFullResult = (P_EVENT_GSCAN_FULL_RESULT_T)(prEvent->aucBuffer); + ie_len = min(prEventGscnFullResult->u4IeLength, (UINT_32)CFG_IE_BUFFER_SIZE); + + DBGLOG(SCN, LOUD, "arSsid=%s, bssid="MACSTR", u4Channel=%d u4IeLength=%d\n", + prEventGscnFullResult->rResult.arSsid, + MAC2STR(prEventGscnFullResult->rResult.arMacAddr), + prEventGscnFullResult->rResult.u4Channel, prEventGscnFullResult->u4IeLength); + + kalMemZero(prScanInfo->prGscnFullResult, + offsetof(PARAM_WIFI_GSCAN_FULL_RESULT, ie_data) + CFG_IE_BUFFER_SIZE); + /* WIFI_GSCAN_RESULT_T similar to PARAM_WIFI_GSCAN_RESULT*/ + kalMemCopy(&prScanInfo->prGscnFullResult->fixed, &prEventGscnFullResult->rResult, + sizeof(WIFI_GSCAN_RESULT_T)); + prScanInfo->prGscnFullResult->u4BucketMask = prEventGscnFullResult->u4BucketMask; + prScanInfo->prGscnFullResult->ie_length = prEventGscnFullResult->u4IeLength; + kalMemCopy(prScanInfo->prGscnFullResult->ie_data, prEventGscnFullResult->ucIeData, ie_len); + + mtk_cfg80211_vendor_event_full_scan_results(wiphy, + prGlueInfo->prDevHandler->ieee80211_ptr, + prScanInfo->prGscnFullResult, + offsetof(PARAM_WIFI_GSCAN_FULL_RESULT, ie_data) + ie_len); + } + break; + + case EVENT_ID_GSCAN_SIGNIFICANT_CHANGE: + { + P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T prEventGscnSignificantChange; + + prEventGscnSignificantChange = (P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T) (prEvent->aucBuffer); + memcpy(prEventGscnSignificantChange, (P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T) (prEvent->aucBuffer), + sizeof(EVENT_GSCAN_SIGNIFICANT_CHANGE_T)); + } + break; + + case EVENT_ID_GSCAN_GEOFENCE_FOUND: + { + P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T prEventGscnGeofenceFound; + + prEventGscnGeofenceFound = (P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T) (prEvent->aucBuffer); + memcpy(prEventGscnGeofenceFound, (P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T) (prEvent->aucBuffer), + sizeof(EVENT_GSCAN_SIGNIFICANT_CHANGE_T)); + } + break; + + default: + DBGLOG(SCN, ERROR, "not a GSCN event\n"); + break; + } + + return 0; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @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; + BOOLEAN fgIsNewVersion; + struct wiphy *wiphy; + + DEBUGFUNC("nicRxProcessEventPacket"); + /* DBGLOG(INIT, TRACE, ("\n")); */ + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prEvent = (P_WIFI_EVENT_T) prSwRfb->pucRecvBuff; + prGlueInfo = prAdapter->prGlueInfo; + wiphy = priv_to_wiphy(prGlueInfo); + + if (prEvent->ucEID != EVENT_ID_LINK_QUALITY && + prEvent->ucEID != EVENT_ID_RX_ADDBA && + prEvent->ucEID != EVENT_ID_TX_DONE && + prEvent->ucEID != EVENT_ID_BSS_ABSENCE_PRESENCE && + prEvent->ucEID != EVENT_ID_STA_STATISTICS && + prEvent->ucEID != EVENT_ID_DEBUG_MSG && + prEvent->ucEID != EVENT_ID_CHECK_REORDER_BUBBLE) + DBGLOG(RX, EVENT, "RX EVENT: ID[0x%02X] SEQ[%u] LEN[%u]\n", + prEvent->ucEID, prEvent->ucSeqNum, prEvent->u2PacketLength); + + /* Event Handling */ + switch (prEvent->ucEID) { +#if 0 /* It is removed now */ + 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; +#endif + +#if 0 + case EVENT_ID_CONNECTION_STATUS: + /* OBSELETE */ + { + P_EVENT_CONNECTION_STATUS prConnectionStatus; + + prConnectionStatus = (P_EVENT_CONNECTION_STATUS) (prEvent->aucBuffer); + + DbgPrint("RX EVENT: EVENT_ID_CONNECTION_STATUS = %d\n", prConnectionStatus->ucMediaStatus); + if (prConnectionStatus->ucMediaStatus == PARAM_MEDIA_STATE_DISCONNECTED) { + /* disconnected */ + if (kalGetMediaStateIndicated(prGlueInfo) != PARAM_MEDIA_STATE_DISCONNECTED) { + + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + + prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); + } + } else if (prConnectionStatus->ucMediaStatus == PARAM_MEDIA_STATE_CONNECTED) { + /* connected */ + prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); + + /* fill information for association result */ + prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen = prConnectionStatus->ucSsidLen; + kalMemCopy(prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, + prConnectionStatus->aucSsid, prConnectionStatus->ucSsidLen); + + kalMemCopy(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, + prConnectionStatus->aucBssid, MAC_ADDR_LEN); + /* @FIXME */ + prAdapter->rWlanInfo.rCurrBssId.u4Privacy = prConnectionStatus->ucEncryptStatus; + prAdapter->rWlanInfo.rCurrBssId.rRssi = 0; /* @FIXME */ + /* @FIXME */ + prAdapter->rWlanInfo.rCurrBssId.eNetworkTypeInUse = PARAM_NETWORK_TYPE_AUTOMODE; + prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4BeaconPeriod + = prConnectionStatus->u2BeaconPeriod; + prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4ATIMWindow + = prConnectionStatus->u2ATIMWindow; + prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4DSConfig + = prConnectionStatus->u4FreqInKHz; + prAdapter->rWlanInfo.ucNetworkType = prConnectionStatus->ucNetworkType; + + switch (prConnectionStatus->ucInfraMode) { + case 0: + prAdapter->rWlanInfo.rCurrBssId.eOpMode = NET_TYPE_IBSS; + break; + case 1: + prAdapter->rWlanInfo.rCurrBssId.eOpMode = NET_TYPE_INFRA; + break; + case 2: + default: + prAdapter->rWlanInfo.rCurrBssId.eOpMode = NET_TYPE_AUTO_SWITCH; + break; + } + /* always indicate to OS according to MSDN (re-association/roaming) */ + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_CONNECT, NULL, 0); + } + } + break; + + case EVENT_ID_SCAN_RESULT: + /* OBSELETE */ + break; +#endif + + case EVENT_ID_RX_ADDBA: + /* The FW indicates that an RX BA agreement will be established */ + qmHandleEventRxAddBa(prAdapter, prEvent); + break; + + case EVENT_ID_RX_DELBA: + /* The FW indicates that an RX BA agreement has been deleted */ + qmHandleEventRxDelBa(prAdapter, prEvent); + break; + + case EVENT_ID_CHECK_REORDER_BUBBLE: + qmHandleEventCheckReorderBubble(prAdapter, prEvent); + break; + +#if CFG_RX_BA_REORDERING_ENHANCEMENT + case EVENT_ID_BA_FW_DROP_SN: + qmHandleEventDropByFW(prAdapter, prEvent); + break; +#endif + 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, 0, (P_EVENT_LINK_QUALITY) prLqEx); + if (prLqEx->ucIsLQ1Rdy) + nicUpdateLinkQuality(prAdapter, 1, (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, 0, (P_EVENT_LINK_QUALITY) (prEvent->aucBuffer)); + } +#else + /*only support ais query */ + { + UINT_8 ucBssIndex; + P_BSS_INFO_T prBssInfo; + + for (ucBssIndex = 0; ucBssIndex < BSS_INFO_NUM; ucBssIndex++) { + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + + if ((prBssInfo->eNetworkType == NETWORK_TYPE_AIS) + && (prBssInfo->fgIsInUse)) + break; + } + + if (ucBssIndex >= BSS_INFO_NUM) + ucBssIndex = 1; /* No hit(bss1 for default ais network) */ + nicUpdateLinkQuality(prAdapter, ucBssIndex, (P_EVENT_LINK_QUALITY_V2) (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, + prAdapter->prAisBssInfo->ucBssIndex, + prAdapter->rWlanInfo.rCurrBssId.arMacAddress); + ASSERT(prStaRec); + + if (prStaRec) + rsnTkipHandleMICFailure(prAdapter, prStaRec, (BOOLEAN) prMicError->u4Flags); + else + DBGLOG(RSN, WARN, "No STA rec!!\n"); +#if 0 + prAuthEvent = (P_PARAM_AUTH_EVENT_T) prAdapter->aucIndicationEventBuffer; + + /* Status type: Authentication Event */ + prAuthEvent->rStatus.eStatusType = ENUM_STATUS_TYPE_AUTHENTICATION; + + /* Authentication request */ + prAuthEvent->arRequest[0].u4Length = sizeof(PARAM_AUTH_REQUEST_T); + kalMemCopy((PVOID) prAuthEvent->arRequest[0].arBssid, + (PVOID) prAdapter->rWlanInfo.rCurrBssId.arMacAddress, + /* whsu:Todo? */ + PARAM_MAC_ADDR_LEN); + + if (prMicError->u4Flags != 0) + prAuthEvent->arRequest[0].u4Flags = PARAM_AUTH_REQUEST_GROUP_ERROR; + else + prAuthEvent->arRequest[0].u4Flags = PARAM_AUTH_REQUEST_PAIRWISE_ERROR; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID) prAuthEvent, + sizeof(PARAM_STATUS_INDICATION_T) + sizeof(PARAM_AUTH_REQUEST_T)); +#endif + } + break; + +#if 0 /* Marked for MT6630 */ + 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->u2PacketLength - 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->u2PacketLength - 8); + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID) prAuthEvent, + sizeof(PARAM_STATUS_INDICATION_T) + u4LenOfUsedBuffer); + } + break; +#endif + +#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: + fgIsNewVersion = FALSE; + if (prEvent->u2PacketLength > (EVENT_HDR_SIZE + sizeof(EVENT_SCAN_DONE) - SCAN_DONE_DIFFERENCE)) + fgIsNewVersion = TRUE; + scnEventScanDone(prAdapter, (P_EVENT_SCAN_DONE) (prEvent->aucBuffer), fgIsNewVersion); + break; + + case EVENT_ID_NLO_DONE: + DBGLOG(INIT, INFO, "EVENT_ID_NLO_DONE\n"); + scnEventNloDone(prAdapter, (P_EVENT_NLO_DONE_T) (prEvent->aucBuffer)); +#if CFG_SUPPORT_PNO + prAdapter->prAisBssInfo->fgIsPNOEnable = FALSE; + if (prAdapter->prAisBssInfo->fgIsNetRequestInActive && prAdapter->prAisBssInfo->fgIsPNOEnable) { + UNSET_NET_ACTIVE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + DBGLOG(RX, INFO, "INACTIVE AIS from ACTIVEto disable PNO\n"); + /* sync with firmware */ + nicDeactivateNetwork(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + } +#endif + break; + + case EVENT_ID_TX_DONE: +#if 1 + nicTxProcessTxDoneEvent(prAdapter, prEvent); +#else + { + P_EVENT_TX_DONE_T prTxDone; + + prTxDone = (P_EVENT_TX_DONE_T) (prEvent->aucBuffer); + + DBGLOG(RX, TRACE, "EVENT_ID_TX_DONE WIDX:PID[%u:%u] Status[%u] SN[%u]\n", + prTxDone->ucWlanIndex, prTxDone->ucPacketSeq, prTxDone->ucStatus, + prTxDone->u2SequenceNumber); + + /* call related TX Done Handler */ + prMsduInfo = nicGetPendingTxMsduInfo(prAdapter, prTxDone->ucWlanIndex, prTxDone->ucPacketSeq); + +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT + DBGLOG(RX, TRACE, "EVENT_ID_TX_DONE u4TimeStamp = %x u2AirDelay = %x\n", + prTxDone->au4Reserved1, prTxDone->au4Reserved2); + + wnmReportTimingMeas(prAdapter, prMsduInfo->ucStaRecIndex, + prTxDone->au4Reserved1, prTxDone->au4Reserved1 + prTxDone->au4Reserved2); +#endif + + if (prMsduInfo) { + prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, + (ENUM_TX_RESULT_CODE_T) (prTxDone->ucStatus)); + + if (prMsduInfo->eSrc == TX_PACKET_MGMT) + cnmMgtPktFree(prAdapter, prMsduInfo); + else + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } + } +#endif + break; + + case EVENT_ID_SLEEPY_INFO: + { + P_EVENT_SLEEPY_INFO_T prEventSleepyNotify; + + prEventSleepyNotify = (P_EVENT_SLEEPY_INFO_T) (prEvent->aucBuffer); + + /* DBGLOG(RX, INFO, ("ucSleepyState = %d\n", prEventSleepyNotify->ucSleepyState)); */ + + prAdapter->fgWiFiInSleepyState = (BOOLEAN) (prEventSleepyNotify->ucSleepyState); + +#if CFG_SUPPORT_MULTITHREAD + if (prEventSleepyNotify->ucSleepyState) + kalSetFwOwnEvent2Hif(prGlueInfo); +#endif + } + 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_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; + P_EVENT_BSS_BEACON_TIMEOUT_T prEventBssBeaconTimeout; + + prEventBssBeaconTimeout = (P_EVENT_BSS_BEACON_TIMEOUT_T) (prEvent->aucBuffer); + + if (prEventBssBeaconTimeout->ucBssIndex >= BSS_INFO_NUM) + break; + + DBGLOG(RX, INFO, "Beacon Timeout Reason: %d, update bad RSSI=-127 to upper layer\n", + prEventBssBeaconTimeout->ucReasonCode); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prEventBssBeaconTimeout->ucBssIndex); + + if (prEventBssBeaconTimeout->ucBssIndex == prAdapter->prAisBssInfo->ucBssIndex) { + if (prAdapter->prAisBssInfo->eConnectionState != PARAM_MEDIA_STATE_CONNECTED) + break; + if (prEventBssBeaconTimeout->ucReasonCode == BEACON_TIMEOUT_DUE_2_NO_TX_DONE_EVENT) + break; + + if (!CHECK_FOR_TIMEOUT(kalGetTimeTick(), u4LastRxPacketTime, SEC_TO_MSEC(2))) { + DBGLOG(RX, INFO, "Ignore beacon timeout\n"); + break; + } + /* Report a lowest RSSI value to wlan framework, who will transfer it to modem and then + ** modem can make a decision if need to switch to LTE data link. + */ + mtk_cfg80211_vendor_event_rssi_beyond_range(wiphy, + ((prAdapter->prGlueInfo)->prDevHandler)->ieee80211_ptr, + (INT_32)-127); /* the lowest limit of FWK */ + + prAdapter->prAisBssInfo->u2DeauthReason = prEventBssBeaconTimeout->ucReasonCode; + aisBssBeaconTimeout(prAdapter); + aisRecordBeaconTimeout(prAdapter, prAdapter->prAisBssInfo); + } +#if CFG_ENABLE_WIFI_DIRECT + else if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) + p2pRoleFsmRunEventBeaconTimeout(prAdapter, prBssInfo); +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (GET_BSS_INFO_BY_INDEX(prAdapter, prEventBssBeaconTimeout->ucBssIndex)->eNetworkType == + NETWORK_TYPE_BOW) { + /* ToDo:: Nothing */ + } +#endif + else { + DBGLOG(RX, ERROR, + "EVENT_ID_BSS_BEACON_TIMEOUT: (ucBssIndex = %d)\n", + prEventBssBeaconTimeout->ucBssIndex); + } + } + + 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 (GET_BSS_INFO_BY_INDEX(prAdapter, prEventUpdateNoaParam->ucBssIndex)->eNetworkType == + NETWORK_TYPE_P2P) { + p2pProcessEvent_UpdateNOAParam(prAdapter, prEventUpdateNoaParam->ucBssIndex, + prEventUpdateNoaParam); + } else { + ASSERT(0); + } + } +#else + ASSERT(0); +#endif + break; + + case EVENT_ID_STA_AGING_TIMEOUT: +#if CFG_ENABLE_WIFI_DIRECT + { + if (prAdapter->fgDisStaAgingTimeoutDetection == FALSE) { + P_EVENT_STA_AGING_TIMEOUT_T prEventStaAgingTimeout; + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; + + prEventStaAgingTimeout = (P_EVENT_STA_AGING_TIMEOUT_T) (prEvent->aucBuffer); + prStaRec = cnmGetStaRecByIndex(prAdapter, prEventStaAgingTimeout->ucStaRecIdx); + if (prStaRec == NULL) + break; + + DBGLOG(RX, INFO, "EVENT_ID_STA_AGING_TIMEOUT %u " MACSTR "\n", + prEventStaAgingTimeout->ucStaRecIdx, MAC2STR(prStaRec->aucMacAddr)); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + bssRemoveClient(prAdapter, prBssInfo, prStaRec); + + /* Call False Auth */ + if (prAdapter->fgIsP2PRegistered) { + p2pFuncDisconnect(prAdapter, prBssInfo, 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_CMD_ROAMING_TRANSIT_T prTransit; + + prTransit = (P_CMD_ROAMING_TRANSIT_T) (prEvent->aucBuffer); + roamingFsmProcessEvent(prAdapter, prTransit); + } +#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 (authSendDeauthFrame(prAdapter, + NULL, + NULL, + prSwRfb, + REASON_CODE_CLASS_3_ERR, + (PFN_TX_DONE_HANDLER) NULL) == WLAN_STATUS_SUCCESS) { + DBGLOG(RX, WARN, "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 + DBGLOG(RSN, EVENT, "BCM BWCS Event: %02x%02x%02x%02x\n", + prEventBwcsStatus->u.aucBTPParams[0], + prEventBwcsStatus->u.aucBTPParams[1], + prEventBwcsStatus->u.aucBTPParams[2], prEventBwcsStatus->u.aucBTPParams[3]); +#endif + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_BWCS_UPDATE, + (PVOID) prEventBwcsStatus, sizeof(PTA_IPC_T)); + } + + break; + + case EVENT_ID_UPDATE_BCM_DEBUG: + { + P_PTA_IPC_T prEventBwcsStatus; + + prEventBwcsStatus = (P_PTA_IPC_T) (prEvent->aucBuffer); + +#if CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(RSN, EVENT, "BCM FW status: %02x%02x%02x%02x\n", + prEventBwcsStatus->u.aucBTPParams[0], + prEventBwcsStatus->u.aucBTPParams[1], + prEventBwcsStatus->u.aucBTPParams[2], prEventBwcsStatus->u.aucBTPParams[3]); +#endif + } + + break; +#endif + case EVENT_ID_ADD_PKEY_DONE: + { + P_EVENT_ADD_KEY_DONE_INFO prAddKeyDone; + P_STA_RECORD_T prStaRec; + + prAddKeyDone = (P_EVENT_ADD_KEY_DONE_INFO) (prEvent->aucBuffer); + + DBGLOG(RSN, TRACE, + "EVENT_ID_ADD_PKEY_DONE BSSIDX=%d " MACSTR "\n", + prAddKeyDone->ucBSSIndex, MAC2STR(prAddKeyDone->aucStaAddr)); + + prStaRec = cnmGetStaRecByAddress(prAdapter, prAddKeyDone->ucBSSIndex, prAddKeyDone->aucStaAddr); + + if (prStaRec) { + DBGLOG(RSN, EVENT, "STA " MACSTR " Add Key Done!!\n", MAC2STR(prStaRec->aucMacAddr)); + prStaRec->fgIsTxKeyReady = TRUE; + qmUpdateStaRec(prAdapter, prStaRec); + } + } + break; + case EVENT_ID_ICAP_DONE: + { + P_EVENT_ICAP_STATUS_T prEventIcapStatus; + PARAM_CUSTOM_MEM_DUMP_STRUCT_T rMemDumpInfo; + UINT_32 u4QueryInfo; + + DBGLOG(RFTEST, INFO, "EVENT_ID_ICAP_DONE <-----\n"); + + prEventIcapStatus = (P_EVENT_ICAP_STATUS_T) (prEvent->aucBuffer); + + rMemDumpInfo.u4Address = prEventIcapStatus->u4StartAddress; + rMemDumpInfo.u4Length = prEventIcapStatus->u4IcapSieze; +#if CFG_SUPPORT_QA_TOOL + rMemDumpInfo.u4IcapContent = prEventIcapStatus->u4IcapContent; +#endif /* CFG_SUPPORT_QA_TOOL */ + wlanoidQueryMemDump(prAdapter, &rMemDumpInfo, sizeof(rMemDumpInfo), &u4QueryInfo); + + } + + break; + case EVENT_ID_DEBUG_MSG: + { + P_EVENT_DEBUG_MSG_T prEventDebugMsg; + UINT_8 ucMsgType; + UINT_16 u2MsgSize; + P_UINT_8 pucMsg; + + prEventDebugMsg = (P_EVENT_DEBUG_MSG_T)(prEvent->aucBuffer); + ucMsgType = prEventDebugMsg->ucMsgType; + u2MsgSize = prEventDebugMsg->u2MsgSize; + pucMsg = prEventDebugMsg->aucMsg; + + wlanPrintFwLog(pucMsg, u2MsgSize, ucMsgType); + } + break; + +#if CFG_SUPPORT_GSCN + case EVENT_ID_GSCAN_SCAN_AVAILABLE: + case EVENT_ID_GSCAN_CAPABILITY: + case EVENT_ID_GSCAN_SCAN_COMPLETE: + case EVENT_ID_GSCAN_FULL_RESULT: + case EVENT_ID_GSCAN_SIGNIFICANT_CHANGE: + case EVENT_ID_GSCAN_GEOFENCE_FOUND: + case EVENT_ID_GSCAN_RESULT: + nicRxProcessGSCNEvent(prAdapter, prSwRfb); + break; +#endif + +#if CFG_SUPPORT_BATCH_SCAN + case EVENT_ID_BATCH_RESULT: + DBGLOG(SCN, TRACE, "Got EVENT_ID_BATCH_RESULT"); + + /* command response handling */ + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + if (prCmdInfo->pfCmdDoneHandler) + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); + else if (prCmdInfo->fgIsOid) + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + + break; +#endif /* CFG_SUPPORT_BATCH_SCAN */ + + case EVENT_ID_RSSI_MONITOR: + { + INT_32 rssi = 0; + + kalMemCopy(&rssi, prEvent->aucBuffer, sizeof(INT_32)); + DBGLOG(RX, TRACE, "EVENT_ID_RSSI_MONITOR value=%d\n", rssi); + + mtk_cfg80211_vendor_event_rssi_beyond_range(wiphy, + prGlueInfo->prDevHandler->ieee80211_ptr, rssi); + } + break; + +#if CFG_SUPPORT_TDLS + case EVENT_ID_TDLS: + + TdlsexEventHandle(prAdapter->prGlueInfo, + (UINT_8 *) prEvent->aucBuffer, (UINT_32) (prEvent->u2PacketLength - 8)); + break; +#endif /* CFG_SUPPORT_TDLS */ + + case EVENT_ID_DUMP_MEM: + DBGLOG(RX, INFO, "%s: EVENT_ID_DUMP_MEM\n", __func__); + + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + DBGLOG(RX, INFO, "EVENT_ID_DUMP_MEM, prCmdInfo=%p\n", prCmdInfo); + 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); + } else { + /* Burst mode */ + nicEventQueryMemDump(prAdapter, prEvent->aucBuffer); + } + break; + case EVENT_ID_RSP_CHNL_UTILIZATION: + cnmHandleChannelUtilization(prAdapter, (struct EVENT_RSP_CHNL_UTILIZATION *)prEvent->aucBuffer); + break; + case EVENT_ID_UPDATE_FW_INFO: + nicEventUpdateFwInfo(prAdapter, prEvent); + break; + case EVENT_ID_ACCESS_REG: + case EVENT_ID_NIC_CAPABILITY: + /* 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); + } else if (prEvent->ucEID == EVENT_ID_GET_TSM_STATISTICS)/* in case of unsolicited event */ + wmmComposeTsmRpt(prAdapter, NULL, prEvent->aucBuffer); + + break; + } + + /* Reset Chip NoAck flag */ + if (prGlueInfo->prAdapter->fgIsChipNoAck) { + DBGLOG(RX, WARN, "Got response from chip, clear NoAck flag!\n"); + WARN_ON(TRUE); + } + prGlueInfo->prAdapter->ucOidTimeoutCount = 0; + prGlueInfo->prAdapter->fgIsChipNoAck = FALSE; + + 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); + if (prSwRfb->prRxStatusGroup3 == NULL) { + DBGLOG(RX, WARN, + "rxStatusGroup3 for MGMT frame is NULL, drop this packet, dump RXD and Packet\n"); + DBGLOG_MEM8(RX, WARN, (PUINT_8) prSwRfb->prRxStatus, sizeof(*prSwRfb->prRxStatus)); + if (prSwRfb->pvHeader) + DBGLOG_MEM8(RX, WARN, (PUINT_8) prSwRfb->pvHeader, + prSwRfb->u2PacketLen > 32 ? 32:prSwRfb->u2PacketLen); + nicRxReturnRFB(prAdapter, prSwRfb); + RX_INC_CNT(&prAdapter->rRxCtrl, RX_DROP_TOTAL_COUNT); +#if defined(MT6631) + kalDumpHifCR(prAdapter->prGlueInfo); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP); +#endif + return; + } + + ucSubtype = (*(PUINT_8) (prSwRfb->pvHeader) & MASK_FC_SUBTYPE) >> OFFSET_OF_FC_SUBTYPE; + +#if CFG_RX_PKTS_DUMP + { + P_WLAN_MAC_MGMT_HEADER_T prWlanMgmtHeader; + UINT_16 u2TxFrameCtrl; + + 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) { + + prWlanMgmtHeader = (P_WLAN_MAC_MGMT_HEADER_T) (prSwRfb->pvHeader); + + DBGLOG(SW4, INFO, "QM RX MGT: net %u sta idx %u wlan idx %u", + prSwRfb->prStaRec->ucBssIndex, + prSwRfb->ucStaRecIdx, + prSwRfb->ucWlanIdx); + DBGLOG(SW4, INFO, "ssn %u ptype %u subtype %u 11 %u\n", + prWlanMgmtHeader->u2SeqCtrl, + /* 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 CFG_SUPPORT_802_11W + if (HAL_RX_STATUS_IS_ICV_ERROR(prSwRfb->prRxStatus)) { + if (HAL_RX_STATUS_GET_SEC_MODE(prSwRfb->prRxStatus) == CIPHER_SUITE_BIP) + DBGLOG(RSN, INFO, "[MFP] RX with BIP ICV ERROR\n"); + else + DBGLOG(RSN, INFO, "[MFP] RX with ICV ERROR\n"); + + nicRxReturnRFB(prAdapter, prSwRfb); + RX_INC_CNT(&prAdapter->rRxCtrl, RX_DROP_TOTAL_COUNT); + return; + } +#endif + + if (prAdapter->fgTestMode == FALSE) { +#if CFG_MGMT_FRAME_HANDLING + if (apfnProcessRxMgtFrame[ucSubtype]) { + switch (apfnProcessRxMgtFrame[ucSubtype] (prAdapter, prSwRfb)) { + case WLAN_STATUS_PENDING: + return; + case WLAN_STATUS_SUCCESS: + case WLAN_STATUS_FAILURE: + break; + + default: + DBGLOG(RX, WARN, "Unexpected MMPDU(0x%02X) returned with abnormal status\n", ucSubtype); + break; + } + } +#endif + } + + nicRxReturnRFB(prAdapter, prSwRfb); +} + + +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG +static VOID nicRxCheckWakeupReason(P_SW_RFB_T prSwRfb) +{ + PUINT_8 pvHeader = NULL; + P_HW_MAC_RX_DESC_T prRxStatus; + UINT_16 u2PktLen = 0; + UINT_32 u4HeaderOffset; + + if (!prSwRfb) + return; + prRxStatus = prSwRfb->prRxStatus; + if (!prRxStatus) + return; + prSwRfb->ucGroupVLD = (UINT_8) HAL_RX_STATUS_GET_GROUP_VLD(prRxStatus); + + switch (prSwRfb->ucPacketType) { + case RX_PKT_TYPE_RX_DATA: + { + UINT_16 u2Temp = 0; + + u2PktLen = HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus); + u4HeaderOffset = (UINT_32) (HAL_RX_STATUS_GET_HEADER_OFFSET(prRxStatus)); + u2Temp = sizeof(HW_MAC_RX_DESC_T); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_4)) + u2Temp += sizeof(HW_MAC_RX_STS_GROUP_4_T); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_1)) + u2Temp += sizeof(HW_MAC_RX_STS_GROUP_1_T); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_2)) + u2Temp += sizeof(HW_MAC_RX_STS_GROUP_2_T); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_3)) + u2Temp += sizeof(HW_MAC_RX_STS_GROUP_3_T); + pvHeader = (PUINT_8)prRxStatus + u2Temp + u4HeaderOffset; + u2PktLen -= u2Temp + u4HeaderOffset; + if (!pvHeader) { + DBGLOG(RX, ERROR, "data packet but pvHeader is NULL!\n"); + break; + } + if ((prRxStatus->u2StatusFlag & (RXS_DW2_RX_nERR_BITMAP | RXS_DW2_RX_nDATA_BITMAP)) == + RXS_DW2_RX_nDATA_VALUE) { + P_WLAN_MAC_HEADER_T prWlanMacHeader = (P_WLAN_MAC_HEADER_T)pvHeader; + + if ((prWlanMacHeader->u2FrameCtrl & MASK_FRAME_TYPE) == + MAC_FRAME_BLOCK_ACK_REQ) { + DBGLOG(RX, INFO, "BAR frame[SSN:%d, TID:%d] wakeup host\n", + prSwRfb->u2SSN, prSwRfb->ucTid); + break; + } + } + u2Temp = (pvHeader[ETH_TYPE_LEN_OFFSET] << 8) | (pvHeader[ETH_TYPE_LEN_OFFSET + 1]); + + switch (u2Temp) { + case ETH_P_IPV4: + u2Temp = *(UINT_16 *) &pvHeader[ETH_HLEN + 4]; + DBGLOG(RX, INFO, "IP Packet from:%d.%d.%d.%d, IP ID 0x%04x wakeup host\n", + pvHeader[ETH_HLEN + 12], pvHeader[ETH_HLEN + 13], + pvHeader[ETH_HLEN + 14], pvHeader[ETH_HLEN + 15], u2Temp); + break; + case ETH_P_ARP: + break; + case ETH_P_1X: + case ETH_P_PRE_1X: +#if CFG_SUPPORT_WAPI + case ETH_WPI_1X: +#endif + case ETH_P_AARP: + case ETH_P_IPV6: + case ETH_P_IPX: + case 0x8100: /* VLAN */ + case 0x890d: /* TDLS */ + DBGLOG(RX, INFO, "Data Packet, EthType 0x%04x wakeup host\n", u2Temp); + break; + default: + DBGLOG(RX, WARN, "maybe abnormal data packet, EthType 0x%04x wakeup host, dump it\n", + u2Temp); + DBGLOG_MEM8(RX, INFO, pvHeader, u2PktLen > 50 ? 50:u2PktLen); + break; + } + break; + } + case RX_PKT_TYPE_SW_DEFINED: + /* HIF_RX_PKT_TYPE_EVENT */ + if ((prSwRfb->prRxStatus->u2PktTYpe & RXM_RXD_PKT_TYPE_SW_BITMAP) == RXM_RXD_PKT_TYPE_SW_EVENT) { + P_WIFI_EVENT_T prEvent = (P_WIFI_EVENT_T) prSwRfb->pucRecvBuff; + + DBGLOG(RX, INFO, "Event 0x%02x wakeup host\n", prEvent->ucEID); + break; + + } + /* case HIF_RX_PKT_TYPE_MANAGEMENT: */ + else if ((prSwRfb->prRxStatus->u2PktTYpe & RXM_RXD_PKT_TYPE_SW_BITMAP) == + RXM_RXD_PKT_TYPE_SW_FRAME) { + UINT_8 ucSubtype; + P_WLAN_MAC_MGMT_HEADER_T prWlanMgmtHeader; + UINT_16 u2Temp = sizeof(HW_MAC_RX_DESC_T); + + u4HeaderOffset = (UINT_32) (HAL_RX_STATUS_GET_HEADER_OFFSET(prRxStatus)); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_4)) + u2Temp += sizeof(HW_MAC_RX_STS_GROUP_4_T); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_1)) + u2Temp += sizeof(HW_MAC_RX_STS_GROUP_1_T); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_2)) + u2Temp += sizeof(HW_MAC_RX_STS_GROUP_2_T); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_3)) + u2Temp += sizeof(HW_MAC_RX_STS_GROUP_3_T); + pvHeader = (PUINT_8)prRxStatus + u2Temp + u4HeaderOffset; + if (!pvHeader) { + DBGLOG(RX, ERROR, "Mgmt Frame but pvHeader is NULL!\n"); + break; + } + prWlanMgmtHeader = (P_WLAN_MAC_MGMT_HEADER_T)pvHeader; + ucSubtype = (prWlanMgmtHeader->u2FrameCtrl & MASK_FC_SUBTYPE) >> + OFFSET_OF_FC_SUBTYPE; + DBGLOG(RX, INFO, "MGMT frame subtype: %d SeqCtrl %d wakeup host\n", + ucSubtype, prWlanMgmtHeader->u2SeqCtrl); + } else { + DBGLOG(RX, ERROR, + "[%s]ERROR: u2PktTYpe(0x%04X) is OUT OF DEF.!!!\n", __func__, + prSwRfb->prRxStatus->u2PktTYpe); + ASSERT(0); + } + break; + default: + DBGLOG(RX, WARN, "Unknown Packet %d wakeup host\n", prSwRfb->ucPacketType); + break; + } +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief nicProcessRFBs is used to process RFBs in the rReceivedRFBList queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxProcessRFBs(IN P_ADAPTER_T prAdapter) +{ + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; + QUE_T rTempRfbList; + P_QUE_T prTempRfbList = &rTempRfbList; + UINT_32 u4RxLoopCount; + static UINT_32 u4PktErrCount; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxProcessRFBs"); + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + prRxCtrl->ucNumIndPacket = 0; + prRxCtrl->ucNumRetainedPacket = 0; + u4RxLoopCount = prAdapter->rWifiVar.u4TxRxLoopCount; + + QUEUE_INITIALIZE(prTempRfbList); + + while (u4RxLoopCount--) { + while (QUEUE_IS_NOT_EMPTY(&prRxCtrl->rReceivedRfbList)) { + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_MOVE_ALL(prTempRfbList, &prRxCtrl->rReceivedRfbList); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + while (QUEUE_IS_NOT_EMPTY(prTempRfbList)) { + QUEUE_REMOVE_HEAD(prTempRfbList, prSwRfb, P_SW_RFB_T); + + if (!prSwRfb) + break; +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG + if (kalIsWakeupByWlan(prAdapter)) + nicRxCheckWakeupReason(prSwRfb); +#endif + + switch (prSwRfb->ucPacketType) { + case RX_PKT_TYPE_RX_DATA: + u4PktErrCount = 0; +#if CFG_SUPPORT_SNIFFER + if (prAdapter->prGlueInfo->fgIsEnableMon) { + nicRxProcessMonitorPacket(prAdapter, prSwRfb); + break; + } +#endif + nicRxProcessDataPacket(prAdapter, prSwRfb); + break; + + case RX_PKT_TYPE_SW_DEFINED: + u4PktErrCount = 0; + /* HIF_RX_PKT_TYPE_EVENT */ + if ((prSwRfb->prRxStatus->u2PktTYpe & RXM_RXD_PKT_TYPE_SW_BITMAP) == + RXM_RXD_PKT_TYPE_SW_EVENT) { + nicRxProcessEventPacket(prAdapter, prSwRfb); + } + /* case HIF_RX_PKT_TYPE_MANAGEMENT: */ + else if ((prSwRfb->prRxStatus->u2PktTYpe & RXM_RXD_PKT_TYPE_SW_BITMAP) == + RXM_RXD_PKT_TYPE_SW_FRAME) { + nicRxProcessMgmtPacket(prAdapter, prSwRfb); + } else { + DBGLOG(RX, ERROR, "u2PktTYpe(0x%04X) is OUT OF DEF!!!\n", + prSwRfb->prRxStatus->u2PktTYpe); + DBGLOG(RX, ERROR, "prSwRfb(%p), prRxStatus:(%p), pvHeader(%p)\n", + prSwRfb, + prSwRfb->prRxStatus, + prSwRfb->pvHeader); + DBGLOG_MEM32(RX, ERROR, (PUINT_32)prSwRfb->prRxStatus, + sizeof(UINT_32)); + } + break; + + /* case HIF_RX_PKT_TYPE_TX_LOOPBACK: */ + /* case HIF_RX_PKT_TYPE_MANAGEMENT: */ + case RX_PKT_TYPE_TX_STATUS: + case RX_PKT_TYPE_RX_VECTOR: + case RX_PKT_TYPE_TM_REPORT: + default: + RX_INC_CNT(prRxCtrl, RX_TYPE_ERR_DROP_COUNT); + RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); + DBGLOG(RX, ERROR, "ucPacketType = %d, u2RxByteCount= %d\n", + prSwRfb->ucPacketType, prSwRfb->prRxStatus->u2RxByteCount); + u4PktErrCount++; + if (u4PktErrCount >= 5) { + DBGLOG(RX, ERROR, + "Continuous %d Rx packet type error, dump current packet:\n", + u4PktErrCount); + if (prSwRfb->prRxStatus->u2RxByteCount < 200) + DBGLOG_MEM32(RX, ERROR, + (PUINT_32)prSwRfb->prRxStatus, + prSwRfb->prRxStatus->u2RxByteCount); + else + DBGLOG_MEM32(RX, ERROR, + (PUINT_32)prSwRfb->prRxStatus, 200); + #if defined(MT6631) + kalDumpHifCR(prAdapter->prGlueInfo); + #endif + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP); + } else + DBGLOG_MEM32(RX, ERROR, (PUINT_32)prSwRfb->prRxStatus, + sizeof(HW_MAC_RX_DESC_T)); + break; + } + + } + + if (prRxCtrl->ucNumIndPacket > 0) { + RX_ADD_CNT(prRxCtrl, RX_DATA_INDICATION_COUNT, prRxCtrl->ucNumIndPacket); + RX_ADD_CNT(prRxCtrl, RX_DATA_RETAINED_COUNT, prRxCtrl->ucNumRetainedPacket); +#if CFG_SUPPORT_MULTITHREAD + kalSetTxEvent2Rx(prAdapter->prGlueInfo); +#else + /* 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 +#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_HW_MAC_RX_DESC_T prRxStatus; + UINT_32 u4PktLen = 0, u4ReadBytes; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + UINT_32 u4RegValue; + UINT_32 rxNum; + + DEBUGFUNC("nicRxReadBuffer"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + pucBuf = prSwRfb->pucRecvBuff; + prRxStatus = prSwRfb->prRxStatus; + + ASSERT(prRxStatus); + ASSERT(pucBuf); + DBGLOG(RX, TRACE, "pucBuf= 0x%x, prRxStatus= 0x%x\n", pucBuf, prRxStatus); + + do { + /* Read the RFB DW length and packet length */ + HAL_MCR_RD(prAdapter, MCR_WRPLR, &u4RegValue); + + /* 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) HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus)) { + DBGLOG(RX, ERROR, "Read u4PktLen = %d, prHifRxHdr->u2PacketLen: %d\n", + u4PktLen, HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus)); +#if DBG + dumpMemory8((PUINT_8) prRxStatus, + (HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus) > + 4096) ? 4096 : prRxStatus->u2RxByteCount); +#endif + ASSERT(0); + } + /* u4PktLen is byte unit, not inlude HW appended DW */ + + prSwRfb->ucPacketType = (UINT_8) HAL_RX_STATUS_GET_PKT_TYPE(prRxStatus); + DBGLOG(RX, TRACE, "ucPacketType = %d\n", prSwRfb->ucPacketType); + + prSwRfb->ucStaRecIdx = + secGetStaIdxByWlanIdx(prAdapter, (UINT_8) HAL_RX_STATUS_GET_WLAN_IDX(prRxStatus)); + + DBGLOG(RX, TRACE, "Dump RX buffer, length = %u\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_HW_MAC_RX_DESC_T prRxStatus; + UINT_32 u4HwAppendDW; + PUINT_32 pu4Temp; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxReceiveRFBs"); + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + do { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_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); + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + pu4Temp = (PUINT_32) prRxStatus; + u4HwAppendDW = *(pu4Temp + (ALIGN_4(prRxStatus->u2RxByteCount) >> 2)); + DBGLOG(RX, TRACE, "u4HwAppendDW = 0x%x\n", u4HwAppendDW); + DBGLOG(RX, TRACE, "u2PacketLen = 0x%x\n", HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus)); + } 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_HW_MAC_RX_DESC_T prRxStatus; + UINT_32 u4PktLen = 0; + WLAN_STATUS u4Status = WLAN_STATUS_FAILURE; + + DEBUGFUNC("nicRxEnhanceReadBuffer"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + pucBuf = prSwRfb->pucRecvBuff; + ASSERT(pucBuf); + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + /* 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); + + u4PktLen = (UINT_32) (HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus)); + /* DBGLOG(RX, TRACE, ("u4PktLen = %d\n", u4PktLen)); */ + + prSwRfb->ucPacketType = (UINT_8) HAL_RX_STATUS_GET_PKT_TYPE(prRxStatus); + /* DBGLOG(RX, TRACE, ("ucPacketType = %d\n", prSwRfb->ucPacketType)); */ + + prSwRfb->ucStaRecIdx = + secGetStaIdxByWlanIdx(prAdapter, (UINT_8) HAL_RX_STATUS_GET_WLAN_IDX(prRxStatus)); + + /* 4 <2> if the RFB dw size or packet size is zero */ + if (u4PktLen == 0) { + DBGLOG(RX, ERROR, "Packet Length = %u\n", u4PktLen); + ASSERT(0); + break; + } + /* 4 <3> if the packet is too large or too small */ + /* ToDo[6630]: adjust CFG_RX_MAX_PKT_SIZE */ + if (u4PktLen > CFG_RX_MAX_PKT_SIZE) { + DBGLOG(RX, TRACE, "Read RX Packet Lentgh Error (%u)\n", u4PktLen); + ASSERT(0); + break; + } + + u4Status = WLAN_STATUS_SUCCESS; + } while (FALSE); + + DBGLOG_MEM8(RX, TRACE, pucBuf, ALIGN_4(u2RxLength + HIF_RX_HW_APPENDED_LEN)); + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read frames from the data port for SDIO +* I/F, fill RFB and put each frame into the rReceivedRFBList queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxSDIOReceiveRFBs(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i, rxNum; + UINT_16 u2RxPktNum, u2RxLength = 0, u2Tmp = 0; + P_SDIO_CTRL_T prSDIOCtrl; + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxSDIOReceiveRFBs"); + + ASSERT(prAdapter); + + prSDIOCtrl = prAdapter->prSDIOCtrl; + ASSERT(prSDIOCtrl); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + for (rxNum = 0; rxNum < 2; rxNum++) { + u2RxPktNum = + (rxNum == 0 ? prSDIOCtrl->rRxInfo.u.u2NumValidRx0Len : prSDIOCtrl->rRxInfo.u.u2NumValidRx1Len); + + if (u2RxPktNum == 0) + continue; + + for (i = 0; i < u2RxPktNum; i++) { + if (rxNum == 0) { + /* HAL_READ_RX_LENGTH */ + HAL_READ_RX_LENGTH(prAdapter, &u2RxLength, &u2Tmp); + } else if (rxNum == 1) { + /* HAL_READ_RX_LENGTH */ + HAL_READ_RX_LENGTH(prAdapter, &u2Tmp, &u2RxLength); + } + + if (!u2RxLength) + break; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + if (!prSwRfb) { + DBGLOG(RX, TRACE, "No More RFB\n"); + break; + } + ASSERT(prSwRfb); + + if (nicRxEnhanceReadBuffer(prAdapter, rxNum, u2RxLength, prSwRfb) == WLAN_STATUS_FAILURE) { + DBGLOG(RX, TRACE, "nicRxEnhanceRxReadBuffer failed\n"); + nicRxReturnRFB(prAdapter, prSwRfb); + break; + } + /* prSDIOCtrl->au4RxLength[i] = 0; */ + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_INSERT_TAIL(&prRxCtrl->rReceivedRfbList, &prSwRfb->rQueEntry); + RX_INC_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + } + } + + prSDIOCtrl->rRxInfo.u.u2NumValidRx0Len = 0; + prSDIOCtrl->rRxInfo.u.u2NumValidRx1Len = 0; + +} /* end of nicRxSDIOReceiveRFBs() */ + +#endif /* CFG_SDIO_INTR_ENHANCE */ + +#if CFG_SDIO_RX_AGG +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read frames from the data port for SDIO with Rx aggregation enabled +* I/F, fill RFB and put each frame into the rReceivedRFBList queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxSDIOAggReceiveRFBs(IN P_ADAPTER_T prAdapter) +{ + P_ENHANCE_MODE_DATA_STRUCT_T prEnhDataStr; + P_RX_CTRL_T prRxCtrl; + P_SDIO_CTRL_T prSDIOCtrl; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; + UINT_16 u2PktLength; + UINT_32 i, rxNum; + UINT_32 u4RxAggCount = 0, u4RxAggLength = 0; + UINT_32 u4RxAvailAggLen, u4CurrAvailFreeRfbCnt; + PUINT_8 pucSrcAddr; + P_HW_MAC_RX_DESC_T prRxStatus; + BOOLEAN fgIsRxEnhanceMode; + UINT_16 u2RxPktNum; +#if CFG_SDIO_RX_ENHANCE + UINT_32 u4MaxLoopCount = CFG_MAX_RX_ENHANCE_LOOP_COUNT; +#endif + UINT_64 u8Current = 0; + static UINT_16 u2PktLenExceptionCount; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxSDIOAggReceiveRFBs"); + + ASSERT(prAdapter); + prEnhDataStr = prAdapter->prSDIOCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + prSDIOCtrl = prAdapter->prSDIOCtrl; + +#if CFG_SDIO_RX_ENHANCE + fgIsRxEnhanceMode = TRUE; +#else + fgIsRxEnhanceMode = FALSE; +#endif + + do { +#if CFG_SDIO_RX_ENHANCE + /* to limit maximum loop for RX */ + u4MaxLoopCount--; + if (u4MaxLoopCount == 0) + break; +#endif + + if (prEnhDataStr->rRxInfo.u.u2NumValidRx0Len == 0 && prEnhDataStr->rRxInfo.u.u2NumValidRx1Len == 0) + break; + + for (rxNum = 0; rxNum < 2; rxNum++) { + u2RxPktNum = + (rxNum == + 0 ? prEnhDataStr->rRxInfo.u.u2NumValidRx0Len : prEnhDataStr->rRxInfo.u.u2NumValidRx1Len); + + if (u2RxPktNum > 16) { + DBGLOG(RX, ERROR, "Abnormal PktNum(%d) in RX%u, need chip reset!\n", + u2RxPktNum, rxNum); + DBGLOG_MEM32(RX, WARN, (PUINT_32)&prEnhDataStr->rRxInfo, + sizeof(prEnhDataStr->rRxInfo)); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP); + return; + } + + 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 + CFG_NUM_OF_BUBBLE_TIMEOUT_EVENT)) { +#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++) { + u2PktLength = (rxNum == 0 ? + prEnhDataStr->rRxInfo.u.au2Rx0Len[i] : + prEnhDataStr->rRxInfo.u.au2Rx1Len[i]); + + if (!u2PktLength) { + DBGLOG(RX, ERROR, "Abnormal PktLen(%d) in RX%u idx %u, need chip reset!\n", + u2PktLength, rxNum, i); + DBGLOG_MEM32(RX, WARN, (PUINT_32)&prEnhDataStr->rRxInfo, + sizeof(prEnhDataStr->rRxInfo)); + #if defined(MT6631) + HAL_DUMP_AHB_INFO(prAdapter, prAdapter->u2ChipID); + #endif + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP); + return; + } else if (u2PktLength > CFG_RX_MAX_PKT_SIZE) { + DBGLOG(RX, ERROR, + "PktLen(%d) > MAX_PKT_SIZE(%d) in RX%u idx %u, try to read out all\n", + u2PktLength, CFG_RX_MAX_PKT_SIZE, rxNum, i); + DBGLOG_MEM32(RX, WARN, (PUINT_32)&prEnhDataStr->rRxInfo, + sizeof(prEnhDataStr->rRxInfo)); + /* + * Rx packet length is too large and untrustable, + * try to read out all data in this Rx port to + * make HIF back to normal. (DE required) + * Since the coalescing buffer may be not enough for saving all data, + * at most read out the buffer size. + * If the total data length is less than it, + * HIF will automatically pad with 0; + * if there is still residual data after this read, + * HIF will become abnormal and need chip reset. + */ + u4RxAvailAggLen = 0; + u4RxAggCount++; + #if defined(MT6631) + HAL_DUMP_AHB_INFO(prAdapter, prAdapter->u2ChipID); + #endif + break; + } + + if (ALIGN_4(u2PktLength + HIF_RX_HW_APPENDED_LEN) <= u4RxAvailAggLen) { + u4RxAvailAggLen -= ALIGN_4(u2PktLength + HIF_RX_HW_APPENDED_LEN); + u4RxAggCount++; + continue; + } else { /* Impossible case, since every packet has reasonable size */ + ASSERT(0); + break; + } + } + + u4RxAggLength = (CFG_RX_COALESCING_BUFFER_SIZE - u4RxAvailAggLen); + + HAL_READ_RX_PORT(prAdapter, + rxNum, + u4RxAggLength, prRxCtrl->pucRxCoalescingBufPtr, CFG_RX_COALESCING_BUFFER_SIZE); + + pucSrcAddr = prRxCtrl->pucRxCoalescingBufPtr; + + u8Current = sched_clock(); + + for (i = 0; i < u4RxAggCount; i++) { + u2PktLength = (rxNum == 0 ? + prEnhDataStr->rRxInfo.u.au2Rx0Len[i] : + prEnhDataStr->rRxInfo.u.au2Rx1Len[i]); + + if (u2PktLength > CFG_RX_MAX_PKT_SIZE) { + UINT_32 j, u4PktTotalLen = 0; + + for (j = 0; j < u2RxPktNum; j++) { + u4PktTotalLen += (rxNum == 0 ? + prEnhDataStr->rRxInfo.u.au2Rx0Len[j] : + prEnhDataStr->rRxInfo.u.au2Rx1Len[j]); + DBGLOG(RX, ERROR, + "RX%u idx %u PktLen(%d), TotalLen(%d)\n", + rxNum, j, (rxNum == 0 ? + prEnhDataStr->rRxInfo.u.au2Rx0Len[j] : + prEnhDataStr->rRxInfo.u.au2Rx1Len[j]), u4PktTotalLen); + } + DBGLOG(RX, ERROR, "Abnormal PktLen(%d) in RX%u idx %u, RxByteCount(%d)!\n", + u2PktLength, rxNum, i, ((HW_MAC_RX_DESC_T *)pucSrcAddr)->u2RxByteCount); + + if (((HW_MAC_RX_DESC_T *)pucSrcAddr)->u2RxByteCount < 200) + DBGLOG_MEM32(RX, ERROR, + pucSrcAddr, + ((HW_MAC_RX_DESC_T *)pucSrcAddr)->u2RxByteCount); + else + DBGLOG_MEM32(RX, ERROR, + pucSrcAddr, 200); + #if defined(MT6631) + HAL_DUMP_AHB_INFO(prAdapter, prAdapter->u2ChipID); + #endif + u2PktLenExceptionCount++; + /* + * Trigger chip reset if we can not read out all data in one time + * when packet length exception or + * the exception occurs continuously. + */ +#if 0 + /* HIF DE think no need to do chip reset, just read out and drop, + * and hardware can return idle state and it can works well. + */ + if (u2PktLenExceptionCount >= 2 || + u4PktTotalLen > CFG_RX_COALESCING_BUFFER_SIZE) + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP); +#endif + return; + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + ASSERT(prSwRfb); + kalMemCopy(prSwRfb->pucRecvBuff, pucSrcAddr, + ALIGN_4(u2PktLength + HIF_RX_HW_APPENDED_LEN)); + + /* prHifRxHdr = prSwRfb->prHifRxHdr; */ + /* ASSERT(prHifRxHdr); */ + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + prSwRfb->ucPacketType = (UINT_8) HAL_RX_STATUS_GET_PKT_TYPE(prRxStatus); + /* DBGLOG(RX, TRACE, ("ucPacketType = %d\n", prSwRfb->ucPacketType)); */ + + GLUE_RX_SET_PKT_INT_TIME(prSwRfb->pvPacket, prAdapter->prGlueInfo->u8HifIntTime); + GLUE_RX_SET_PKT_RX_TIME(prSwRfb->pvPacket, u8Current); + 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); + } + +#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 + /* Reset count when this rx data is normal */ + u2PktLenExceptionCount = 0; + } while ((prEnhDataStr->rRxInfo.u.u2NumValidRx0Len || prEnhDataStr->rRxInfo.u.u2NumValidRx1Len) + && fgIsRxEnhanceMode); + +} +#endif /* CFG_SDIO_RX_AGG */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Setup a RFB and allocate the os packet to the RFB +* +* @param prAdapter Pointer to the Adapter structure. +* @param prSwRfb Pointer to the RFB +* +* @retval WLAN_STATUS_SUCCESS +* @retval WLAN_STATUS_RESOURCES +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicRxSetupRFB(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + PVOID pvPacket; + PUINT_8 pucRecvBuff; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + if (!prSwRfb->pvPacket) { + kalMemZero(prSwRfb, sizeof(SW_RFB_T)); + pvPacket = kalPacketAlloc(prAdapter->prGlueInfo, CFG_RX_MAX_PKT_SIZE, &pucRecvBuff); + if (pvPacket == NULL) + return WLAN_STATUS_RESOURCES; + + prSwRfb->pvPacket = pvPacket; + prSwRfb->pucRecvBuff = (PVOID) pucRecvBuff; + } else { + kalMemZero(((PUINT_8) prSwRfb + OFFSET_OF(SW_RFB_T, prRxStatus)), + (sizeof(SW_RFB_T) - OFFSET_OF(SW_RFB_T, prRxStatus))); + } + + /* ToDo: remove prHifRxHdr */ + /* prSwRfb->prHifRxHdr = (P_HIF_RX_HEADER_T)(prSwRfb->pucRecvBuff); */ + prSwRfb->prRxStatus = (P_HW_MAC_RX_DESC_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_FREE_QUE); + + if (prSwRfb->pvPacket) { + /* QUEUE_INSERT_TAIL */ + QUEUE_INSERT_TAIL(&prRxCtrl->rFreeSwRfbList, prQueEntry); + } else { + /* QUEUE_INSERT_TAIL */ + QUEUE_INSERT_TAIL(&prRxCtrl->rIndicatedRfbList, prQueEntry); + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); +} /* end of nicRxReturnRFB() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process rx interrupt. When the rx +* Interrupt is asserted, it means there are frames in queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicProcessRxInterrupt(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + prAdapter->prGlueInfo->IsrRxCnt++; +#if CFG_SDIO_INTR_ENHANCE +#if CFG_SDIO_RX_AGG + nicRxSDIOAggReceiveRFBs(prAdapter); +#else + nicRxSDIOReceiveRFBs(prAdapter); +#endif +#else + nicRxReceiveRFBs(prAdapter); +#endif /* CFG_SDIO_INTR_ENHANCE */ + +#if CFG_SUPPORT_MULTITHREAD + set_bit(GLUE_FLAG_RX_BIT, &(prAdapter->prGlueInfo->ulFlag)); + wake_up_interruptible(&(prAdapter->prGlueInfo->waitq)); +#else + nicRxProcessRFBs(prAdapter); +#endif + + 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)) { + /* count success num */ + RX_INC_CNT(prRxCtrl, RX_CSUM_IP_SUCCESS_COUNT); + } else if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_FAILED) || (aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_FAILED)) { + RX_INC_CNT(prRxCtrl, RX_CSUM_IP_FAILED_COUNT); + } else if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_NONE) && (aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_NONE)) { + RX_INC_CNT(prRxCtrl, RX_CSUM_UNKNOWN_L3_PKT_COUNT); + } else { + ASSERT(0); + } + + if (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_SUCCESS) { + /* count success num */ + RX_INC_CNT(prRxCtrl, RX_CSUM_TCP_SUCCESS_COUNT); + } else if (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_FAILED) { + RX_INC_CNT(prRxCtrl, RX_CSUM_TCP_FAILED_COUNT); + } else if (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_SUCCESS) { + RX_INC_CNT(prRxCtrl, RX_CSUM_UDP_SUCCESS_COUNT); + } else if (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_FAILED) { + RX_INC_CNT(prRxCtrl, RX_CSUM_UDP_FAILED_COUNT); + } else if ((aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_NONE) && (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_NONE)) { + RX_INC_CNT(prRxCtrl, RX_CSUM_UNKNOWN_L4_PKT_COUNT); + } else { + ASSERT(0); + } + +} /* end of nicRxUpdateCSUMStatistics() */ +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief 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; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + UINT_32 u4Time, u4Current; + P_RX_CTRL_T prRxCtrl; + P_WIFI_EVENT_T prEvent; + UINT_32 loop = 0; + + DEBUGFUNC("nicRxWaitResponse"); + + ASSERT(prAdapter); + ASSERT(pucRspBuffer); + ASSERT(ucPortIdx < 2); + + prRxCtrl = &prAdapter->rRxCtrl; + + u4Time = (UINT_32) kalGetTimeTick(); + + do { + /* Read the packet length */ + HAL_MCR_RD(prAdapter, MCR_WRPLR, &u4Value); + + if (ucPortIdx == 0) + u4PktLen = u4Value & 0xFFFF; + else + u4PktLen = (u4Value >> 16) & 0xFFFF; + + if (u4PktLen == 0) { + /* timeout exceeding check */ + u4Current = (UINT_32) kalGetTimeTick(); + + if ((u4Current > u4Time) && ((u4Current - u4Time) > RX_RESPONSE_TIMEOUT)) { + DBGLOG(RX, ERROR, "Wait Response packet timeout!\n"); + return WLAN_STATUS_FAILURE; + } else if (u4Current < u4Time && ((u4Current + (0xFFFFFFFF - u4Time)) > RX_RESPONSE_TIMEOUT)) { + DBGLOG(RX, ERROR, "Wait Response packet timeout!\n"); + return WLAN_STATUS_FAILURE; + } + /* Response packet is not ready */ + kalUdelay(50); + + } else { + if (loop >= 5) + return WLAN_STATUS_FAILURE; + loop++; + if (u4PktLen > u4MaxRespBufferLen) { + DBGLOG(RX, ERROR, "loop:%u, Not enough buffer length: required %u, available %u\n", + loop, u4PktLen, u4MaxRespBufferLen); +#if CFG_SDIO_RX_AGG + HAL_PORT_RD(prAdapter, + ucPortIdx == 0 ? MCR_WRDR0 : MCR_WRDR1, + ALIGN_4(u4PktLen) + 4, + prRxCtrl->pucRxCoalescingBufPtr, CFG_RX_COALESCING_BUFFER_SIZE); +#else +#error "Please turn on RX coalescing" +#endif + DBGLOG_MEM8(RX, WARN, prRxCtrl->pucRxCoalescingBufPtr, u4PktLen > 200 ? 200:u4PktLen); + /*return WLAN_STATUS_FAILURE;*/ + } else { + +#if CFG_SDIO_RX_AGG + HAL_PORT_RD(prAdapter, + ucPortIdx == 0 ? MCR_WRDR0 : MCR_WRDR1, + ALIGN_4(u4PktLen) + 4, + prRxCtrl->pucRxCoalescingBufPtr, CFG_RX_COALESCING_BUFFER_SIZE); + kalMemCopy(pucRspBuffer, prRxCtrl->pucRxCoalescingBufPtr, u4PktLen); +#else +#error "Please turn on RX coalescing" +#endif + + DBGLOG(RX, LOUD, "Dump Response buffer, length = %u\n", u4PktLen); + DBGLOG_MEM8(RX, LOUD, pucRspBuffer, u4PktLen); + + prEvent = (P_WIFI_EVENT_T) pucRspBuffer; + DBGLOG(RX, TRACE, "RX EVENT: ID[0x%02X] SEQ[%u] LEN[%u]\n", + prEvent->ucEID, prEvent->ucSeqNum, prEvent->u2PacketLength); + + *pu4Length = u4PktLen; + break; + } + } + } while (TRUE); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Set filter to enable Promiscuous Mode +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxEnablePromiscuousMode(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); +} /* end of nicRxEnablePromiscuousMode() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Set filter to disable Promiscuous Mode +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxDisablePromiscuousMode(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); +} /* end of nicRxDisablePromiscuousMode() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief this function flushes all packets queued in reordering module +* +* @param prAdapter Pointer to the Adapter structure. +* +* @retval WLAN_STATUS_SUCCESS Flushed successfully +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicRxFlush(IN P_ADAPTER_T prAdapter) +{ + P_SW_RFB_T prSwRfb; + + ASSERT(prAdapter); + prSwRfb = qmFlushRxQueues(prAdapter); + if (prSwRfb != NULL) { + do { + P_SW_RFB_T prNextSwRfb; + + /* save next first */ + prNextSwRfb = (P_SW_RFB_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prSwRfb); + + /* free */ + nicRxReturnRFB(prAdapter, prSwRfb); + + prSwRfb = prNextSwRfb; + } while (prSwRfb); + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param +* +* @retval +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicRxProcessActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_WLAN_ACTION_FRAME prActFrame; +#if CFG_SUPPORT_802_11W + BOOL fgRobustAction = FALSE; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; +#endif + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + DBGLOG(RSN, TRACE, "[Rx] nicRxProcessActionFrame\n"); + + if (prSwRfb->u2PacketLen < sizeof(WLAN_ACTION_FRAME) - 1) + return WLAN_STATUS_INVALID_PACKET; + prActFrame = (P_WLAN_ACTION_FRAME) prSwRfb->pvHeader; + + /* DBGLOG(RSN, TRACE, ("[Rx] nicRxProcessActionFrame\n")); */ + +#if CFG_SUPPORT_802_11W + /* + *Action frame that need protect according to PMF. + * ucCategory == CATEGORY_SPEC_MGT || + * ucCategory == CATEGORY_QOS_ACTION || + * ucCategory == CATEGORY_DLS_ACTION || + * ucCategory == CATEGORY_BLOCK_ACK_ACTION || + * ucCategory == CATEGORY_RM_ACTION || + * ucCategory == CATEGORY_FT_ACTION || + * ucCategory == CATEGORY_SA_QUERY_ACTION || + * ucCategory == CATEGORY_PROTECTED_DUAL_OF_PUBLIC_ACTION || + * ucCategory == CATEGORY_WNM_ACTION || + * ucCategory == CATEGORY_TDLS_ACTION || + * ucCategory == CATEGORY_MESH_ACTION || + * ucCategory == CATEGORY_MULTIHOP_ACTION || + * ucCategory == CATEGORY_DMG_ACTION || + * ucCategory == CATEGORY_FST_ACTION || + * ucCategory == CATEGORY_ROBUST_AV_STREAMING_ACTION || + * ucCategory == CATEGORY_VENDOR_SPECIFIC_PROTECTED_ACTION + */ + + if ((prActFrame->ucCategory <= CATEGORY_ROBUST_AV_STREAMING_ACTION && + prActFrame->ucCategory != CATEGORY_PUBLIC_ACTION && + prActFrame->ucCategory != CATEGORY_HT_ACTION && + prActFrame->ucCategory != CATEGORY_UNPROTECTED_WNM_ACTION && + prActFrame->ucCategory != CATEGORY_SELF_PROTECTED_ACTION && + prActFrame->ucCategory != CATEGORY_WME_MGT_NOTIFICATION) || + (prActFrame->ucCategory == CATEGORY_VENDOR_SPECIFIC_ACTION_PROTECTED)) { + fgRobustAction = TRUE; + } + /* DBGLOG(RSN, TRACE, ("[Rx] fgRobustAction=%d\n", fgRobustAction)); */ + if (!prSwRfb->prStaRec) + nicRxMgmtNoWTBLHandling(prAdapter, prSwRfb); + + if (fgRobustAction && prSwRfb->prStaRec && + GET_BSS_INFO_BY_INDEX(prAdapter, prSwRfb->prStaRec->ucBssIndex)->eNetworkType == NETWORK_TYPE_AIS) { + prAisSpecBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); + + DBGLOG(RSN, INFO, + "[Rx]RobustAction %x %x %x\n", prSwRfb->prRxStatus->u2StatusFlag, + prSwRfb->prRxStatus->ucWlanIdx, prSwRfb->prRxStatus->ucTidSecMode); + + if (prAisSpecBssInfo->fgMgmtProtection && (!(prActFrame->u2FrameCtrl & MASK_FC_PROTECTED_FRAME) + && (HAL_RX_STATUS_GET_SEC_MODE(prSwRfb->prRxStatus) == + CIPHER_SUITE_CCMP))) { + DBGLOG(RSN, INFO, "[MFP] Not handle and drop un-protected robust action frame!!\n"); + return WLAN_STATUS_INVALID_PACKET; + } + } + /* DBGLOG(RSN, TRACE, ("[Rx] pre check done, handle cateory %d\n", prActFrame->ucCategory)); */ +#endif + + switch (prActFrame->ucCategory) { +#if CFG_M0VE_BA_TO_DRIVER + case CATEGORY_BLOCK_ACK_ACTION: + DBGLOG(RX, WARN, "[Puff][%s] Rx CATEGORY_BLOCK_ACK_ACTION\n", __func__); + + if (prSwRfb->prStaRec) + mqmHandleBaActionFrame(prAdapter, prSwRfb); + + break; +#endif + +#if DSCP_SUPPORT + case CATEGORY_QOS_ACTION: + DBGLOG(RX, INFO, "received dscp action frame: %d\n", + __LINE__); + handleQosMapConf(prAdapter, prSwRfb); + break; +#endif + + case CATEGORY_PUBLIC_ACTION: + { + UINT_8 ucProcessed = 0; + + if (IS_BMCAST_MAC_ADDR(prActFrame->aucDestAddr) || + EQUAL_MAC_ADDR(prActFrame->aucDestAddr, prAdapter->rWifiVar.aucMacAddress)) { + aisFuncValidateRxActionFrame(prAdapter, prSwRfb); + ucProcessed = 1; + } +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered && + (IS_BMCAST_MAC_ADDR(prActFrame->aucDestAddr) || + EQUAL_MAC_ADDR(prActFrame->aucDestAddr, prAdapter->rWifiVar.aucDeviceAddress))) { + rlmProcessPublicAction(prAdapter, prSwRfb); + + p2pFuncValidateRxActionFrame(prAdapter, prSwRfb); + ucProcessed |= 2; + } +#endif + if (!ucProcessed) + DBGLOG(RX, WARN, "Not processed public action frame, DA:%pM, Our: %pM\n", + prActFrame->aucDestAddr, prAdapter->rWifiVar.aucMacAddress); + 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_QUERY_ACTION: + { + P_BSS_INFO_T prBssInfo; + + if (prSwRfb->prStaRec) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prSwRfb->prStaRec->ucBssIndex); + ASSERT(prBssInfo); + if ((prBssInfo->eNetworkType == NETWORK_TYPE_AIS) && + prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection /* Use MFP */) { + /* MFP test plan 5.3.3.4 */ + rsnSaQueryAction(prAdapter, prSwRfb); + } else if ((prBssInfo->eNetworkType == NETWORK_TYPE_P2P) + && (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { + /* AP PMF */ + DBGLOG(RSN, INFO, "[Rx] nicRx AP PMF SAQ action\n"); + if (rsnCheckBipKeyInstalled(prAdapter, + prSwRfb->prStaRec)) { + /* MFP test plan 4.3.3.4 */ + rsnApSaQueryAction(prAdapter, prSwRfb); + } + } + } + } + break; +#endif + case CATEGORY_WNM_ACTION: + { + wnmWNMAction(prAdapter, prSwRfb); + } + break; + +#if CFG_SUPPORT_DFS + case CATEGORY_SPEC_MGT: + { + if (prAdapter->fgEnable5GBand) + rlmProcessSpecMgtAction(prAdapter, prSwRfb); + } + break; +#endif +#if CFG_SUPPORT_802_11K + case CATEGORY_RM_ACTION: + switch (prActFrame->ucAction) { + case RM_ACTION_RM_REQUEST: + rlmProcessRadioMeasurementRequest(prAdapter, prSwRfb); + break; + case RM_ACTION_REIGHBOR_RESPONSE: + rlmProcessNeighborReportResonse(prAdapter, prActFrame, prSwRfb->u2PacketLen); + break; + } + break; +#endif + case CATEGORY_WME_MGT_NOTIFICATION: + wmmParseQosAction(prAdapter, prSwRfb); + break; + default: + break; + } /* end of switch case */ + + return WLAN_STATUS_SUCCESS; +} + +VOID nicRxMgmtNoWTBLHandling(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) +{ + /* WTBL error handling. if no WTBL */ + P_WLAN_MAC_MGMT_HEADER_T prMgmtHdr = (P_WLAN_MAC_MGMT_HEADER_T)prSwRfb->pvHeader; + + prSwRfb->ucStaRecIdx = secLookupStaRecIndexFromTA(prAdapter, prMgmtHdr->aucSrcAddr); + if (prSwRfb->ucStaRecIdx >= CFG_NUM_OF_STA_RECORD) + return; + prSwRfb->prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prSwRfb->prStaRec) { + prSwRfb->ucWlanIdx = prSwRfb->prStaRec->ucWlanIndex; + DBGLOG(RX, INFO, "current wlan index is %d, dump all used wtbl entry\n", prSwRfb->ucWlanIdx); + } else + DBGLOG(RX, INFO, "not find station record base on TA, dump all used wtbl entry\n"); +#ifdef MT6797 + kalDumpWTBL(prAdapter); +#endif +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/nic_tx.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/nic_tx.c new file mode 100644 index 0000000000000..fb32ae68fc9df --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/nic_tx.c @@ -0,0 +1,3485 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_tx.c#2 + */ + +/* + * ! \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. + */ + +/******************************************************************************* +* C O M P I L E 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 "que_mgt.h" + +#ifdef UDP_SKT_WIFI +#include +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +static const TX_RESOURCE_CONTROL_T arTcResourceControl[TC_NUM] = { + /* dest port index, dest queue index, HIF TX queue index */ + /* First HW queue */ + {PORT_INDEX_LMAC, MAC_TXQ_AC0_INDEX, HIF_TX_AC0_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC1_INDEX, HIF_TX_AC1_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC2_INDEX, HIF_TX_AC2_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC3_INDEX, HIF_TX_AC3_INDEX}, + {PORT_INDEX_MCU, MCU_Q1_INDEX, HIF_TX_CPU_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC4_INDEX, HIF_TX_AC4_INDEX}, + + /* Second HW queue */ +#if NIC_TX_ENABLE_SECOND_HW_QUEUE + {PORT_INDEX_LMAC, MAC_TXQ_AC10_INDEX, HIF_TX_AC10_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC11_INDEX, HIF_TX_AC11_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC12_INDEX, HIF_TX_AC12_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC13_INDEX, HIF_TX_AC13_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC14_INDEX, HIF_TX_AC14_INDEX}, +#endif +}; + +/* Traffic settings per TC */ +static const TX_TC_TRAFFIC_SETTING_T arTcTrafficSettings[NET_TC_NUM] = { + /* Tx desc template format, Remaining Tx time, Retry count */ + /* For Data frame with StaRec, set Long Format to enable the following settings */ + {NIC_TX_DESC_SHORT_FORMAT_LENGTH, NIC_TX_AC_BE_REMAINING_TX_TIME, + NIC_TX_DATA_DEFAULT_RETRY_COUNT_LIMIT}, + {NIC_TX_DESC_SHORT_FORMAT_LENGTH, NIC_TX_AC_BK_REMAINING_TX_TIME, + NIC_TX_DATA_DEFAULT_RETRY_COUNT_LIMIT}, + {NIC_TX_DESC_SHORT_FORMAT_LENGTH, NIC_TX_AC_VI_REMAINING_TX_TIME, + NIC_TX_DATA_DEFAULT_RETRY_COUNT_LIMIT}, + {NIC_TX_DESC_SHORT_FORMAT_LENGTH, NIC_TX_AC_VO_REMAINING_TX_TIME, + NIC_TX_DATA_DEFAULT_RETRY_COUNT_LIMIT}, + + /* MGMT frame */ + {NIC_TX_DESC_LONG_FORMAT_LENGTH, TX_DESC_TX_TIME_NO_LIMIT, + NIC_TX_MGMT_DEFAULT_RETRY_COUNT_LIMIT}, + + /* non-StaRec frame (BMC, etc...) */ + {NIC_TX_DESC_LONG_FORMAT_LENGTH, TX_DESC_TX_TIME_NO_LIMIT, + NIC_TX_DATA_DEFAULT_RETRY_COUNT_LIMIT}, +}; + +/******************************************************************************* +* 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); + + prTxCtrl->pucTxCoalescingBufPtr = prAdapter->pucCoalescingBufCached; + + /* 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; + + /* Assign init value */ + /* Tx sequence number */ + prAdapter->ucTxSeqNum = 0; + /* PID pool */ + DBGLOG(TX, INFO, "Init PID pool mach:%d size:%d", + __BITS_PER_LONG, sizeof(prAdapter->au8PidPool)); + kalMemZero(prAdapter->au8PidPool, sizeof(prAdapter->au8PidPool)); + + prTxCtrl->u4PageSize = NIC_TX_PAGE_SIZE; + + qmInit(prAdapter); + + TX_RESET_ALL_CNTS(prTxCtrl); + +} /* end of nicTxInitialize() */ + +BOOLEAN nicTxSanityCheckResource(IN P_ADAPTER_T prAdapter) +{ + P_TX_CTRL_T prTxCtrl; + UINT_8 ucTC; + UINT_32 ucTotalMaxResource = 0; + UINT_32 ucTotalFreeResource = 0; + BOOLEAN fgError = FALSE; + + if (prAdapter->rWifiVar.ucTxDbg & BIT(0)) { + prTxCtrl = &prAdapter->rTxCtrl; + + prTxCtrl->u4TotalPageNum = 546; + + for (ucTC = TC0_INDEX; ucTC < TC_NUM; ucTC++) { + ucTotalMaxResource += prTxCtrl->rTc.au2MaxNumOfPage[ucTC]; + ucTotalFreeResource += prTxCtrl->rTc.au2FreePageCount[ucTC]; + + if (prTxCtrl->rTc.au2FreePageCount[ucTC] > prTxCtrl->u4TotalPageNum) { + DBGLOG(TX, ERROR, "%s:%u\n error\n", __func__, __LINE__); + fgError = TRUE; + } + + if (prTxCtrl->rTc.au2MaxNumOfPage[ucTC] > prTxCtrl->u4TotalPageNum) { + DBGLOG(TX, ERROR, "%s:%u\n error\n", __func__, __LINE__); + fgError = TRUE; + } + + if (prTxCtrl->rTc.au2FreePageCount[ucTC] > prTxCtrl->rTc.au2MaxNumOfPage[ucTC]) { + DBGLOG(TX, ERROR, "%s:%u\n error\n", __func__, __LINE__); + fgError = TRUE; + } + } + + if (ucTotalMaxResource != prTxCtrl->u4TotalPageNum) { + DBGLOG(TX, ERROR, "%s:%u\n error\n", __func__, __LINE__); + fgError = TRUE; + } + + if (ucTotalMaxResource < ucTotalFreeResource) { + DBGLOG(TX, ERROR, "%s:%u\n error\n", __func__, __LINE__); + fgError = TRUE; + } + + if (ucTotalFreeResource > prTxCtrl->u4TotalPageNum) { + DBGLOG(TX, ERROR, "%s:%u\n error\n", __func__, __LINE__); + fgError = TRUE; + } + + if (fgError) { + DBGLOG(TX, ERROR, "Total resource[%u]\n", prTxCtrl->u4TotalPageNum); + qmDumpQueueStatus(prAdapter); + } + } + + return !fgError; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Driver maintain a variable that is synchronous with the usage of individual +* TC Buffer Count. This function will check if has enough TC Buffer for incoming +* packet and then update the value after promise to provide the resources. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] ucTC Specify the resource of TC +* +* \retval WLAN_STATUS_SUCCESS Resource is available and been assigned. +* \retval WLAN_STATUS_RESOURCES Resource is not available. +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 u4CurrTick; +WLAN_STATUS nicTxAcquireResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC, IN UINT_8 ucPageCount) +{ +#define TC4_NO_RESOURCE_DELAY_MS 5 /* exponential of 5s */ + + 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); + + if (prTxCtrl->rTc.au2FreePageCount[ucTC] >= ucPageCount) { + + if (ucTC == TC4_INDEX) + u4CurrTick = 0; + prTxCtrl->rTc.au2FreePageCount[ucTC] -= ucPageCount; + + prTxCtrl->rTc.au2FreeBufferCount[ucTC] = + (prTxCtrl->rTc.au2FreePageCount[ucTC] / NIC_TX_MAX_PAGE_PER_FRAME); + + DBGLOG(TX, TRACE, + "Acquire: TC%d AcquirePageCnt[%u] FreeBufferCnt[%u] FreePageCnt[%u]\n", + ucTC, ucPageCount, prTxCtrl->rTc.au2FreeBufferCount[ucTC], + prTxCtrl->rTc.au2FreePageCount[ucTC]); + + u4Status = WLAN_STATUS_SUCCESS; + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + if (ucTC == TC4_INDEX) { + if (u4CurrTick == 0) + u4CurrTick = kalGetTimeTick(); + if (CHECK_FOR_TIMEOUT(kalGetTimeTick(), u4CurrTick, + SEC_TO_SYSTIME(TC4_NO_RESOURCE_DELAY_MS))) { +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanDumpTcResAndTxedCmd(NULL, 0); +#endif + cmdBufDumpCmdQueue(&prAdapter->rPendingCmdQueue, "waiting response CMD queue"); + } + } + + 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_16 au2WTSR[HIF_TX_NUM] = {0}; + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + if (ucTC >= TC_NUM) + return WLAN_STATUS_FAILURE; + + if (prTxCtrl->rTc.au2FreeBufferCount[ucTC] > 0) + return WLAN_STATUS_SUCCESS; + + while (i-- > 0) { + HAL_READ_TX_RELEASED_COUNT(prAdapter, au2WTSR); + + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + break; + } else if (nicTxReleaseResource(prAdapter, au2WTSR)) { + if (prTxCtrl->rTc.au2FreeBufferCount[ucTC] > 0) { + u4Status = WLAN_STATUS_SUCCESS; + break; + } + 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 %ld times, %ld 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 calculate TC page count according to +* the given TX_STATUS COUNTER after TX Done. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] au2TxRlsCnt array of TX STATUS +* \param[in] au2FreeTcResource array of free & available resource count +* +* @return TRUE there are available resource to release +* @return FALSE no available resource to release +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN nicTxCalculateResource(IN P_ADAPTER_T prAdapter, IN UINT_16 *au2TxRlsCnt, OUT UINT_16 *au2FreeTcResource) +{ + P_TX_TCQ_STATUS_T prTcqStatus; + BOOLEAN bStatus = FALSE; + UINT_8 ucTcIdx; + UINT_16 u2TotalTxDoneCnt = 0; + UINT_16 u2TotalExtraTxDone = 0; + UINT_16 au2UsedCnt[TC_NUM]; + UINT_16 au2ExtraTxDone[TC_NUM]; + + PUINT_16 au2TxDoneCnt; + PUINT_16 au2PreUsedCnt; + UINT_16 u2AvaliableCnt; + BOOLEAN fgEnExtraTxDone; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prTcqStatus = &prAdapter->rTxCtrl.rTc; + + au2TxDoneCnt = prTcqStatus->au2TxDonePageCount; + au2PreUsedCnt = prTcqStatus->au2PreUsedPageCount; + u2AvaliableCnt = prTcqStatus->u2AvaliablePageCount; + fgEnExtraTxDone = prAdapter->rWifiVar.ucExtraTxDone; + + /* Get used page count */ + if (fgEnExtraTxDone) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + for (ucTcIdx = TC0_INDEX; ucTcIdx < TC_NUM; ucTcIdx++) { + au2UsedCnt[ucTcIdx] = prTcqStatus->au2MaxNumOfPage[ucTcIdx] - + prTcqStatus->au2FreePageCount[ucTcIdx]; + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + } + + /* Get Tx done & available page count */ + u2AvaliableCnt += au2TxRlsCnt[HIF_TX_FFA_INDEX]; + for (ucTcIdx = TC0_INDEX; ucTcIdx < TC_NUM; ucTcIdx++) { + + /* Get Tx done count from Tx interrupt status */ + au2TxDoneCnt[ucTcIdx] += au2TxRlsCnt[arTcResourceControl[ucTcIdx].ucHifTxQIndex]; + + /* Get Available EXTRA Tx done */ + if (fgEnExtraTxDone) { + /* Release Tx done if there are pre-used resource */ + if (au2TxDoneCnt[ucTcIdx] >= au2PreUsedCnt[ucTcIdx]) { + au2TxDoneCnt[ucTcIdx] -= au2PreUsedCnt[ucTcIdx]; + au2PreUsedCnt[ucTcIdx] = 0; + } else { + au2PreUsedCnt[ucTcIdx] -= au2TxDoneCnt[ucTcIdx]; + au2TxDoneCnt[ucTcIdx] = 0; + } + + /* Calculate extra Tx done to share rest FFA resource */ + if (au2TxDoneCnt[ucTcIdx] >= au2UsedCnt[ucTcIdx]) { + au2TxDoneCnt[ucTcIdx] = au2UsedCnt[ucTcIdx]; + au2ExtraTxDone[ucTcIdx] = 0; + } else { + au2ExtraTxDone[ucTcIdx] = au2UsedCnt[ucTcIdx] - au2TxDoneCnt[ucTcIdx]; + } + u2TotalExtraTxDone += au2ExtraTxDone[ucTcIdx]; + } + + u2TotalTxDoneCnt += au2TxDoneCnt[ucTcIdx]; + + } + + DBGLOG(TX, TRACE, "TxDone result, FFA[%u] AC[%u:%u:%u:%u:%u] CPU[%u]\n", + au2TxRlsCnt[HIF_TX_FFA_INDEX], au2TxRlsCnt[HIF_TX_AC0_INDEX], + au2TxRlsCnt[HIF_TX_AC1_INDEX], au2TxRlsCnt[HIF_TX_AC2_INDEX], + au2TxRlsCnt[HIF_TX_AC3_INDEX], au2TxRlsCnt[HIF_TX_AC4_INDEX], + au2TxRlsCnt[HIF_TX_CPU_INDEX]); +#if 0 + DBGLOG(TX, TRACE, "Tx Done INT result, AC5/6[%u:%u] BMC/BCN[%u:%u] AC10~14[%u:%u:%u:%u:%u]\n", + au2TxRlsCnt[HIF_TX_AC5_INDEX], au2TxRlsCnt[HIF_TX_AC6_INDEX], + au2TxRlsCnt[HIF_TX_BMC_INDEX], au2TxRlsCnt[HIF_TX_BCN_INDEX], + au2TxRlsCnt[HIF_TX_AC10_INDEX], au2TxRlsCnt[HIF_TX_AC11_INDEX], + au2TxRlsCnt[HIF_TX_AC12_INDEX], au2TxRlsCnt[HIF_TX_AC13_INDEX], + au2TxRlsCnt[HIF_TX_AC14_INDEX]); +#endif + DBGLOG(TX, TRACE, "TxDone Page count, TC[%u:%u:%u:%u:%u:%u]\n", + au2TxDoneCnt[TC0_INDEX], au2TxDoneCnt[TC1_INDEX], + au2TxDoneCnt[TC2_INDEX], au2TxDoneCnt[TC3_INDEX], + au2TxDoneCnt[TC4_INDEX], au2TxDoneCnt[TC5_INDEX]); + + /* Calculate free Tc page count */ + if (u2AvaliableCnt && u2TotalTxDoneCnt) { + /* Distribute resource by Tx done counter */ + if (u2AvaliableCnt >= u2TotalTxDoneCnt) { + /* Fulfill all TC resource */ + kalMemCopy(au2FreeTcResource, prTcqStatus->au2TxDonePageCount, + sizeof(prTcqStatus->au2TxDonePageCount)); + + kalMemZero(prTcqStatus->au2TxDonePageCount, sizeof(prTcqStatus->au2TxDonePageCount)); + + u2AvaliableCnt -= u2TotalTxDoneCnt; + } else { + /* Round-robin distribute resource */ + ucTcIdx = prTcqStatus->ucNextTcIdx; + while (u2AvaliableCnt) { + /* Enough resource, fulfill this TC */ + if (u2AvaliableCnt >= au2TxDoneCnt[ucTcIdx]) { + au2FreeTcResource[ucTcIdx] = au2TxDoneCnt[ucTcIdx]; + u2AvaliableCnt -= au2TxDoneCnt[ucTcIdx]; + au2TxDoneCnt[ucTcIdx] = 0; + + /* Round-robin get next TC */ + ucTcIdx++; + ucTcIdx %= TC_NUM; + } + /* no more resource, distribute rest of resource to this TC */ + else { + au2FreeTcResource[ucTcIdx] = u2AvaliableCnt; + au2TxDoneCnt[ucTcIdx] -= u2AvaliableCnt; + u2AvaliableCnt = 0; + } + } + prTcqStatus->ucNextTcIdx = ucTcIdx; + } + bStatus = TRUE; + } + + if (u2AvaliableCnt && u2TotalExtraTxDone && fgEnExtraTxDone) { + /* Distribute resource by EXTRA Tx done counter */ + if (u2AvaliableCnt >= u2TotalExtraTxDone) { + for (ucTcIdx = TC0_INDEX; ucTcIdx < TC_NUM; ucTcIdx++) { + au2FreeTcResource[ucTcIdx] += au2ExtraTxDone[ucTcIdx]; + au2PreUsedCnt[ucTcIdx] += au2ExtraTxDone[ucTcIdx]; + au2ExtraTxDone[ucTcIdx] = 0; + } + + u2AvaliableCnt -= u2TotalExtraTxDone; + } else { + /* Round-robin distribute resource */ + ucTcIdx = prTcqStatus->ucNextTcIdx; + while (u2AvaliableCnt) { + /* Enough resource, fulfill this TC */ + if (u2AvaliableCnt >= au2ExtraTxDone[ucTcIdx]) { + au2FreeTcResource[ucTcIdx] += au2ExtraTxDone[ucTcIdx]; + au2PreUsedCnt[ucTcIdx] += au2ExtraTxDone[ucTcIdx]; + u2AvaliableCnt -= au2ExtraTxDone[ucTcIdx]; + au2ExtraTxDone[ucTcIdx] = 0; + + /* Round-robin get next TC */ + ucTcIdx++; + ucTcIdx %= TC_NUM; + } + /* no more resource, distribute rest of resource to this TC */ + else { + au2FreeTcResource[ucTcIdx] += u2AvaliableCnt; + au2PreUsedCnt[ucTcIdx] += u2AvaliableCnt; + au2ExtraTxDone[ucTcIdx] -= u2AvaliableCnt; + u2AvaliableCnt = 0; + } + } + prTcqStatus->ucNextTcIdx = ucTcIdx; + } + bStatus = TRUE; + } + + prTcqStatus->u2AvaliablePageCount = u2AvaliableCnt; + + return bStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 nicTxReleaseTCResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC, IN UINT_16 u2ReleasePageCnt) +{ + P_TX_TCQ_STATUS_T prTcqStatus; + BOOLEAN bStatus = FALSE; + UINT_32 u4BufferCountToBeFreed; + P_QUE_MGT_T prQM = NULL; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prTcqStatus = &prAdapter->rTxCtrl.rTc; + prQM = &prAdapter->rQM; + + /* Calculate free page count */ + if (ucTC >= TC_NUM) + return bStatus; + if (u2ReleasePageCnt > 0) { + /* Return free Tc page count */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + /* Real page counter */ + prTcqStatus->au2FreePageCount[ucTC] += u2ReleasePageCnt; + + /* Buffer counter. For development only */ + /* Convert page count to buffer count */ + u4BufferCountToBeFreed = (prTcqStatus->au2FreePageCount[ucTC] / NIC_TX_MAX_PAGE_PER_FRAME); + prTcqStatus->au2FreeBufferCount[ucTC] = u4BufferCountToBeFreed; + + DBGLOG(TX, TRACE, + "Release: TC%u ReturnPageCnt[%hu] FreePageCnt[%hu] FreeBufferCnt[%hu]\n", + ucTC, u2ReleasePageCnt, prTcqStatus->au2FreePageCount[ucTC], + prTcqStatus->au2FreeBufferCount[ucTC]); +#if (CFG_SUPPORT_TRACE_TC4 == 1) + if (ucTC == TC4_INDEX) + wlanTraceReleaseTcRes(prAdapter, u2ReleasePageCnt, + prTcqStatus->au2FreePageCount[ucTC]); +#endif + + prQM->au4QmTcResourceBackCounter[ucTC] += u2ReleasePageCnt; + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + bStatus = TRUE; + } + + if (!nicTxSanityCheckResource(prAdapter)) + DBGLOG(TX, ERROR, "Release TC[%u] resource page count [%u]\n", + ucTC, u2ReleasePageCnt); + + DBGLOG(TX, LOUD, + "TCQ Status Free Page:Buf[%03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u]\n", + prTcqStatus->au2FreePageCount[TC0_INDEX], + prTcqStatus->au2FreeBufferCount[TC0_INDEX], + prTcqStatus->au2FreePageCount[TC1_INDEX], + prTcqStatus->au2FreeBufferCount[TC1_INDEX], + prTcqStatus->au2FreePageCount[TC2_INDEX], + prTcqStatus->au2FreeBufferCount[TC2_INDEX], + prTcqStatus->au2FreePageCount[TC3_INDEX], + prTcqStatus->au2FreeBufferCount[TC3_INDEX], + prTcqStatus->au2FreePageCount[TC4_INDEX], + prTcqStatus->au2FreeBufferCount[TC4_INDEX], + prTcqStatus->au2FreePageCount[TC5_INDEX], prTcqStatus->au2FreeBufferCount[TC5_INDEX]); + + return bStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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_16 *au2TxRlsCnt) +{ + P_TX_TCQ_STATUS_T prTcqStatus; + BOOLEAN bStatus = FALSE; + UINT_32 i, u4BufferCountToBeFreed; + UINT_16 au2FreeTcResource[TC_NUM] = { 0 }; + P_QUE_MGT_T prQM = NULL; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prTcqStatus = &prAdapter->rTxCtrl.rTc; + prQM = &prAdapter->rQM; + + /* Calculate free page count */ + if (nicTxCalculateResource(prAdapter, au2TxRlsCnt, au2FreeTcResource)) { + + /* Return free Tc page count */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + for (i = TC0_INDEX; i < TC_NUM; i++) { + + /* Real page counter */ + prTcqStatus->au2FreePageCount[i] += au2FreeTcResource[i]; + + /* Buffer counter. For development only */ + /* Convert page count to buffer count */ + u4BufferCountToBeFreed = (prTcqStatus->au2FreePageCount[i] / NIC_TX_MAX_PAGE_PER_FRAME); + prTcqStatus->au2FreeBufferCount[i] = u4BufferCountToBeFreed; + + if (au2FreeTcResource[i]) { + DBGLOG(TX, TRACE, + "Release: TC%u ReturnPageCnt[%hu] FreePageCnt[%hu] FreeBufferCnt[%hu]\n", + i, au2FreeTcResource[i], prTcqStatus->au2FreePageCount[i], + prTcqStatus->au2FreeBufferCount[i]); +#if (CFG_SUPPORT_TRACE_TC4 == 1) + if (i == TC4_INDEX) + wlanTraceReleaseTcRes(prAdapter, au2FreeTcResource[i], + prTcqStatus->au2FreePageCount[i]); +#endif + } + } + + for (i = TC0_INDEX; i < TC_NUM; i++) + prQM->au4QmTcResourceBackCounter[i] += au2FreeTcResource[i]; + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + bStatus = TRUE; + } + + if (!nicTxSanityCheckResource(prAdapter)) + DBGLOG(TX, ERROR, "Tx Done INT result, FFA[%u] AC[%u:%u:%u:%u:%u] CPU[%u]\n", + au2TxRlsCnt[HIF_TX_FFA_INDEX], au2TxRlsCnt[HIF_TX_AC0_INDEX], + au2TxRlsCnt[HIF_TX_AC1_INDEX], au2TxRlsCnt[HIF_TX_AC2_INDEX], + au2TxRlsCnt[HIF_TX_AC3_INDEX], au2TxRlsCnt[HIF_TX_AC4_INDEX], + au2TxRlsCnt[HIF_TX_CPU_INDEX]); + + DBGLOG(TX, LOUD, + "TCQ Status Free Page:Buf[%03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u]\n", + prTcqStatus->au2FreePageCount[TC0_INDEX], + prTcqStatus->au2FreeBufferCount[TC0_INDEX], + prTcqStatus->au2FreePageCount[TC1_INDEX], + prTcqStatus->au2FreeBufferCount[TC1_INDEX], + prTcqStatus->au2FreePageCount[TC2_INDEX], + prTcqStatus->au2FreeBufferCount[TC2_INDEX], + prTcqStatus->au2FreePageCount[TC3_INDEX], + prTcqStatus->au2FreeBufferCount[TC3_INDEX], + prTcqStatus->au2FreePageCount[TC4_INDEX], + prTcqStatus->au2FreeBufferCount[TC4_INDEX], + prTcqStatus->au2FreePageCount[TC5_INDEX], + prTcqStatus->au2FreeBufferCount[TC5_INDEX]); + + return bStatus; +} /* end of nicTxReleaseResource() */ + +VOID nicTxReleaseMsduResource(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead) +{ + P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead, prNextMsduInfo; + + while (prMsduInfo) { + prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); + + nicTxReleaseTCResource(prAdapter, + prMsduInfo->ucTC, + nicTxGetPageCount(prMsduInfo->u2FrameLength, FALSE)); + prMsduInfo = prNextMsduInfo; + }; +} +/*----------------------------------------------------------------------------*/ +/*! +* \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; + UINT_8 ucIdx; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicTxResetResource"); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + /* Delta page count */ + kalMemZero(prTxCtrl->rTc.au2TxDonePageCount, sizeof(prTxCtrl->rTc.au2TxDonePageCount)); + kalMemZero(prTxCtrl->rTc.au2PreUsedPageCount, sizeof(prTxCtrl->rTc.au2PreUsedPageCount)); + + prTxCtrl->rTc.ucNextTcIdx = TC0_INDEX; + prTxCtrl->rTc.u2AvaliablePageCount = 0; + + DBGLOG(TX, LOUD, "Default TCQ free resource [%u %u %u %u %u %u]\n", + prAdapter->rWifiVar.au4TcPageCount[TC0_INDEX], + prAdapter->rWifiVar.au4TcPageCount[TC1_INDEX], + prAdapter->rWifiVar.au4TcPageCount[TC2_INDEX], + prAdapter->rWifiVar.au4TcPageCount[TC3_INDEX], + prAdapter->rWifiVar.au4TcPageCount[TC4_INDEX], + prAdapter->rWifiVar.au4TcPageCount[TC5_INDEX]); + + prAdapter->rTxCtrl.u4TotalPageNum = 0; + prAdapter->rTxCtrl.u4TotalTxRsvPageNum = 0; + + for (ucIdx = TC0_INDEX; ucIdx < TC_NUM; ucIdx++) { + /* Page Count */ + prTxCtrl->rTc.au2MaxNumOfPage[ucIdx] = prAdapter->rWifiVar.au4TcPageCount[ucIdx]; + prTxCtrl->rTc.au2FreePageCount[ucIdx] = prAdapter->rWifiVar.au4TcPageCount[ucIdx]; + + DBGLOG(TX, LOUD, "Set TC%u Default[%u] Max[%u] Free[%u]\n", + ucIdx, + prAdapter->rWifiVar.au4TcPageCount[ucIdx], + prTxCtrl->rTc.au2MaxNumOfPage[ucIdx], prTxCtrl->rTc.au2FreePageCount[ucIdx]); + + /* Buffer count */ + prTxCtrl->rTc.au2MaxNumOfBuffer[ucIdx] = + (prTxCtrl->rTc.au2MaxNumOfPage[ucIdx] / NIC_TX_MAX_PAGE_PER_FRAME); + prTxCtrl->rTc.au2FreeBufferCount[ucIdx] = + (prTxCtrl->rTc.au2FreePageCount[ucIdx] / NIC_TX_MAX_PAGE_PER_FRAME); + + DBGLOG(TX, LOUD, "Set TC%u Default[%u] Buffer Max[%u] Free[%u]\n", + ucIdx, + prAdapter->rWifiVar.au4TcPageCount[ucIdx], + prTxCtrl->rTc.au2MaxNumOfBuffer[ucIdx], prTxCtrl->rTc.au2FreeBufferCount[ucIdx]); + + prAdapter->rTxCtrl.u4TotalPageNum += prTxCtrl->rTc.au2MaxNumOfPage[ucIdx]; + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + DBGLOG(TX, TRACE, "Reset TCQ free resource to Page:Buf [%u:%u %u:%u %u:%u %u:%u %u:%u %u:%u ]\n", + prTxCtrl->rTc.au2FreePageCount[TC0_INDEX], + prTxCtrl->rTc.au2FreeBufferCount[TC0_INDEX], + prTxCtrl->rTc.au2FreePageCount[TC1_INDEX], + prTxCtrl->rTc.au2FreeBufferCount[TC1_INDEX], + prTxCtrl->rTc.au2FreePageCount[TC2_INDEX], + prTxCtrl->rTc.au2FreeBufferCount[TC2_INDEX], + prTxCtrl->rTc.au2FreePageCount[TC3_INDEX], + prTxCtrl->rTc.au2FreeBufferCount[TC3_INDEX], + prTxCtrl->rTc.au2FreePageCount[TC4_INDEX], + prTxCtrl->rTc.au2FreeBufferCount[TC4_INDEX], + prTxCtrl->rTc.au2FreePageCount[TC5_INDEX], prTxCtrl->rTc.au2FreeBufferCount[TC5_INDEX]); + + DBGLOG(TX, TRACE, "Reset TCQ MAX resource to Page:Buf [%u:%u %u:%u %u:%u %u:%u %u:%u %u:%u]\n", + prTxCtrl->rTc.au2MaxNumOfPage[TC0_INDEX], + prTxCtrl->rTc.au2MaxNumOfBuffer[TC0_INDEX], + prTxCtrl->rTc.au2MaxNumOfPage[TC1_INDEX], + prTxCtrl->rTc.au2MaxNumOfBuffer[TC1_INDEX], + prTxCtrl->rTc.au2MaxNumOfPage[TC2_INDEX], + prTxCtrl->rTc.au2MaxNumOfBuffer[TC2_INDEX], + prTxCtrl->rTc.au2MaxNumOfPage[TC3_INDEX], + prTxCtrl->rTc.au2MaxNumOfBuffer[TC3_INDEX], + prTxCtrl->rTc.au2MaxNumOfPage[TC4_INDEX], + prTxCtrl->rTc.au2MaxNumOfBuffer[TC4_INDEX], + prTxCtrl->rTc.au2MaxNumOfPage[TC5_INDEX], prTxCtrl->rTc.au2MaxNumOfBuffer[TC5_INDEX]); + + 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_16 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.au2FreePageCount[ucTC]; +} + +UINT_8 nicTxGetFrameResourceType(IN UINT_8 eFrameType, IN P_MSDU_INFO_T prMsduInfo) +{ + UINT_8 ucTC; + + switch (eFrameType) { + case FRAME_TYPE_802_1X: + ucTC = TC4_INDEX; + break; + + case FRAME_TYPE_MMPDU: + if (prMsduInfo) + ucTC = prMsduInfo->ucTC; + else + ucTC = TC4_INDEX; + break; + + default: + DBGLOG(TX, WARN, "Undefined Frame Type(%u)\n", eFrameType); + ucTC = TC4_INDEX; + break; + } + + return ucTC; +} + +UINT_8 nicTxGetCmdResourceType(IN P_CMD_INFO_T prCmdInfo) +{ + UINT_8 ucTC; + + switch (prCmdInfo->eCmdType) { + case COMMAND_TYPE_NETWORK_IOCTL: + case COMMAND_TYPE_GENERAL_IOCTL: + ucTC = TC4_INDEX; + break; + + case COMMAND_TYPE_SECURITY_FRAME: + ucTC = nicTxGetFrameResourceType(FRAME_TYPE_802_1X, NULL); + break; + + case COMMAND_TYPE_MANAGEMENT_FRAME: + ucTC = nicTxGetFrameResourceType(FRAME_TYPE_MMPDU, prCmdInfo->prMsduInfo); + break; + + default: + DBGLOG(TX, WARN, "Undefined CMD Type(%u)\n", prCmdInfo->eCmdType); + ucTC = TC4_INDEX; + break; + } + + return 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; + P_QUE_T prDataPort0, prDataPort1; + WLAN_STATUS status; + + ASSERT(prAdapter); + ASSERT(prMsduInfoListHead); + + prMsduInfo = prMsduInfoListHead; + + prDataPort0 = &qDataPort0; + prDataPort1 = &qDataPort1; + + QUEUE_INITIALIZE(prDataPort0); + QUEUE_INITIALIZE(prDataPort1); + + /* 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); + + 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(prDataPort0, (P_QUE_ENTRY_T) prMsduInfo); + status = + nicTxAcquireResource(prAdapter, prMsduInfo->ucTC, + nicTxGetPageCount(prMsduInfo->u2FrameLength, FALSE)); + ASSERT(status == WLAN_STATUS_SUCCESS); + + break; + + case TC4_INDEX: /* Management packets */ + QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo) = NULL; + QUEUE_INSERT_TAIL(prDataPort1, (P_QUE_ENTRY_T) prMsduInfo); + + status = + nicTxAcquireResource(prAdapter, prMsduInfo->ucTC, + nicTxGetPageCount(prMsduInfo->u2FrameLength, FALSE)); + ASSERT(status == WLAN_STATUS_SUCCESS); + + break; + + default: + ASSERT(0); + break; + } + + prMsduInfo = prNextMsduInfo; + } + + if (prDataPort0->u4NumElem > 0) + nicTxMsduQueue(prAdapter, 0, prDataPort0); + + if (prDataPort1->u4NumElem > 0) + nicTxMsduQueue(prAdapter, 1, prDataPort1); + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_SUPPORT_MULTITHREAD +/*----------------------------------------------------------------------------*/ +/*! +* @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 nicTxMsduInfoListMthread(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead) +{ + P_MSDU_INFO_T prMsduInfo, prNextMsduInfo; + QUE_T qDataPort0, qDataPort1; + P_QUE_T prDataPort0, prDataPort1; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prMsduInfoListHead); + + prMsduInfo = prMsduInfoListHead; + + prDataPort0 = &qDataPort0; + prDataPort1 = &qDataPort1; + + QUEUE_INITIALIZE(prDataPort0); + QUEUE_INITIALIZE(prDataPort1); + + /* 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); + + 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(prDataPort0, (P_QUE_ENTRY_T) prMsduInfo); + break; + + case TC4_INDEX: /* Management packets */ + QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo) = NULL; + QUEUE_INSERT_TAIL(prDataPort1, (P_QUE_ENTRY_T) prMsduInfo); + break; + + default: + ASSERT(0); + break; + } + + nicTxFillDesc(prAdapter, prMsduInfo, prMsduInfo->aucTxDescBuffer, NULL); + + prMsduInfo = prNextMsduInfo; + } + + if (prDataPort0->u4NumElem > 0 || prDataPort1->u4NumElem > 0) { + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + QUEUE_CONCATENATE_QUEUES((&(prAdapter->rTxP0Queue)), (prDataPort0)); + QUEUE_CONCATENATE_QUEUES((&(prAdapter->rTxP1Queue)), (prDataPort1)); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + + kalSetTxEvent2Hif(prAdapter->prGlueInfo); + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief In this function, we'll write frame(PACKET_INFO_T) into HIF when apply multithread. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @retval WLAN_STATUS_SUCCESS Bus access ok. +* @retval WLAN_STATUS_FAILURE Bus access fail. +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 nicTxMsduQueueMthread(IN P_ADAPTER_T prAdapter) +{ + QUE_T qDataPort0, qDataPort1; + P_QUE_T prDataPort0, prDataPort1; + UINT_32 u4TxLoopCount; + UINT_32 u4TxDataLoopCount; + + KAL_SPIN_LOCK_DECLARATION(); + + prDataPort0 = &qDataPort0; + prDataPort1 = &qDataPort1; + + QUEUE_INITIALIZE(prDataPort0); + QUEUE_INITIALIZE(prDataPort1); + + u4TxLoopCount = prAdapter->rWifiVar.u4HifTxloopCount; + u4TxDataLoopCount = prAdapter->rWifiVar.u4HifTxDataloopCount; + + while (u4TxLoopCount--) { + while (u4TxDataLoopCount--) { + if (QUEUE_IS_NOT_EMPTY((&(prAdapter->rTxP0Queue)))) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + QUEUE_MOVE_ALL((prDataPort0), (&(prAdapter->rTxP0Queue))); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + + nicTxMsduQueue(prAdapter, 0, prDataPort0); + } + } + while (QUEUE_IS_NOT_EMPTY((&(prAdapter->rTxP1Queue)))) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + QUEUE_MOVE_ALL((prDataPort1), (&(prAdapter->rTxP1Queue))); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + + nicTxMsduQueue(prAdapter, 1, prDataPort1); + } + } + + return WLAN_STATUS_SUCCESS; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief In this function, we'll compose the Tx descriptor of the MSDU. +* +* @param prAdapter Pointer to the Adapter structure. +* @param prMsduInfo Pointer to the Msdu info +* @param prTxDesc Pointer to the Tx descriptor buffer +* +* @retval VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicTxComposeDesc(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, + IN UINT_8 ucTxDescLength, IN BOOLEAN fgIsTemplate, OUT PUINT_8 prTxDescBuffer) +{ + P_HW_MAC_TX_DESC_T prTxDesc; + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prBssInfo; + UINT_8 ucEtherTypeOffsetInWord; + UINT_8 ucTxDescAndPaddingLength; + + prTxDesc = (P_HW_MAC_TX_DESC_T) prTxDescBuffer; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + ucTxDescAndPaddingLength = ucTxDescLength + NIC_TX_DESC_PADDING_LENGTH; + + kalMemZero(prTxDesc, ucTxDescAndPaddingLength); + + /* Move to nicTxFillDesc */ + /* Tx byte count */ + /* HAL_MAC_TX_DESC_SET_TX_BYTE_COUNT(prTxDesc, ucTxDescAndPaddingLength + prMsduInfo->u2FrameLength); */ + + /* Ether-type offset */ + if (prMsduInfo->fgIs802_11) { + ucEtherTypeOffsetInWord = + (NIC_TX_DESC_AND_PADDING_LENGTH + prMsduInfo->ucMacHeaderLength + prMsduInfo->ucLlcLength) >> 1; + } else { + ucEtherTypeOffsetInWord = ((ETHER_HEADER_LEN - ETHER_TYPE_LEN) + ucTxDescAndPaddingLength) >> 1; + } + HAL_MAC_TX_DESC_SET_ETHER_TYPE_OFFSET(prTxDesc, ucEtherTypeOffsetInWord); + + if (prMsduInfo->ucTC >= TC_NUM) + return; + /* Port index / queue index */ + HAL_MAC_TX_DESC_SET_PORT_INDEX(prTxDesc, arTcResourceControl[prMsduInfo->ucTC].ucDestPortIndex); + HAL_MAC_TX_DESC_SET_QUEUE_INDEX(prTxDesc, arTcResourceControl[prMsduInfo->ucTC].ucDestQueueIndex); + + /* BMC packet */ + if (prMsduInfo->ucStaRecIndex == STA_REC_INDEX_BMCAST) { + HAL_MAC_TX_DESC_SET_BMC(prTxDesc); + + /* Must set No ACK to mask retry bit in FC */ + HAL_MAC_TX_DESC_SET_NO_ACK(prTxDesc); + } + /* WLAN index */ + prMsduInfo->ucWlanIndex = nicTxGetWlanIdx(prAdapter, prMsduInfo->ucBssIndex, prMsduInfo->ucStaRecIndex); + +#if DBG + DBGLOG(RSN, TRACE, + "Tx WlanIndex = %d eAuthMode = %d\n", prMsduInfo->ucWlanIndex, + prAdapter->rWifiVar.rConnSettings.eAuthMode); +#endif + HAL_MAC_TX_DESC_SET_WLAN_INDEX(prTxDesc, prMsduInfo->ucWlanIndex); + + /* Header format */ + if (prMsduInfo->fgIs802_11) { + HAL_MAC_TX_DESC_SET_HEADER_FORMAT(prTxDesc, HEADER_FORMAT_802_11_NORMAL_MODE); + HAL_MAC_TX_DESC_SET_802_11_HEADER_LENGTH(prTxDesc, (prMsduInfo->ucMacHeaderLength >> 1)); + } else { + HAL_MAC_TX_DESC_SET_HEADER_FORMAT(prTxDesc, HEADER_FORMAT_NON_802_11); + HAL_MAC_TX_DESC_SET_ETHERNET_II(prTxDesc); + } + + /* Header Padding */ + HAL_MAC_TX_DESC_SET_HEADER_PADDING(prTxDesc, NIC_TX_DESC_HEADER_PADDING_LENGTH); + + /* TID */ + HAL_MAC_TX_DESC_SET_TID(prTxDesc, prMsduInfo->ucUserPriority); + + /* Protection */ + if (secIsProtectedFrame(prAdapter, prMsduInfo, prStaRec)) { + /* Update Packet option, PF bit will be set in nicTxFillDescByPktOption() */ + nicTxConfigPktOption(prMsduInfo, MSDU_OPT_PROTECTED_FRAME, TRUE); + } + /* Own MAC */ + HAL_MAC_TX_DESC_SET_OWN_MAC_INDEX(prTxDesc, prBssInfo->ucOwnMacIndex); + + if (ucTxDescLength == NIC_TX_DESC_SHORT_FORMAT_LENGTH) { + HAL_MAC_TX_DESC_SET_SHORT_FORMAT(prTxDesc); + + /* Update Packet option */ + nicTxFillDescByPktOption(prMsduInfo, prTxDesc); + + /* Short format, Skip DW 2~6 */ + return; + } + + HAL_MAC_TX_DESC_SET_LONG_FORMAT(prTxDesc); + /* Update Packet option */ + nicTxFillDescByPktOption(prMsduInfo, prTxDesc); + nicTxFillDescByPktControl(prMsduInfo, prTxDesc); + + /* Type */ + if (prMsduInfo->fgIs802_11) { + P_WLAN_MAC_HEADER_T prWlanHeader = + (P_WLAN_MAC_HEADER_T) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + HAL_MAC_TX_DESC_SET_TYPE(prTxDesc, (prWlanHeader->u2FrameCtrl & MASK_FC_TYPE) >> 2); + HAL_MAC_TX_DESC_SET_SUB_TYPE(prTxDesc, + (prWlanHeader->u2FrameCtrl & MASK_FC_SUBTYPE) >> OFFSET_OF_FC_SUBTYPE); + } + /* PID */ + if (prMsduInfo->pfTxDoneHandler) { + UINT_8 ucWlanIndex = prMsduInfo->ucWlanIndex; + + if (prMsduInfo->ucPacketType == TX_PACKET_TYPE_DATA) + ucWlanIndex |= BIT(7); + prMsduInfo->ucPID = nicTxAssignPID(prAdapter, ucWlanIndex); + if (prMsduInfo->ucPID > 0) { + HAL_MAC_TX_DESC_SET_PID(prTxDesc, prMsduInfo->ucPID); + HAL_MAC_TX_DESC_SET_TXS_TO_MCU(prTxDesc); + } + } + /* Remaining TX time */ + if (!(prMsduInfo->u4Option & MSDU_OPT_MANUAL_LIFE_TIME)) + prMsduInfo->u4RemainingLifetime = arTcTrafficSettings[prMsduInfo->ucTC].u4RemainingTxTime; + HAL_MAC_TX_DESC_SET_REMAINING_LIFE_TIME_IN_MS(prTxDesc, prMsduInfo->u4RemainingLifetime); + + /* Tx count limit */ + if (!(prMsduInfo->u4Option & MSDU_OPT_MANUAL_RETRY_LIMIT)) { + /* Note: BMC packet retry limit is set to unlimited */ + prMsduInfo->ucRetryLimit = arTcTrafficSettings[prMsduInfo->ucTC].ucTxCountLimit; + } + HAL_MAC_TX_DESC_SET_REMAINING_TX_COUNT(prTxDesc, prMsduInfo->ucRetryLimit); + + /* Power Offset */ + HAL_MAC_TX_DESC_SET_POWER_OFFSET(prTxDesc, prMsduInfo->cPowerOffset); + + /* Fix rate */ + switch (prMsduInfo->ucRateMode) { + case MSDU_RATE_MODE_MANUAL_DESC: + HAL_MAC_TX_DESC_SET_DW(prTxDesc, 6, 1, &prMsduInfo->u4FixedRateOption); + HAL_MAC_TX_DESC_SET_FIXED_RATE_MODE_TO_DESC(prTxDesc); + HAL_MAC_TX_DESC_SET_FIXED_RATE_ENABLE(prTxDesc); + break; + + case MSDU_RATE_MODE_MANUAL_CR: + HAL_MAC_TX_DESC_SET_FIXED_RATE_MODE_TO_CR(prTxDesc); + HAL_MAC_TX_DESC_SET_FIXED_RATE_ENABLE(prTxDesc); + break; + + case MSDU_RATE_MODE_AUTO: + default: + break; + } + +} + +VOID +nicTxComposeSecurityFrameDesc(IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, OUT PUINT_8 prTxDescBuffer, OUT PUINT_8 pucTxDescLength) +{ + P_HW_MAC_TX_DESC_T prTxDesc = (P_HW_MAC_TX_DESC_T) prTxDescBuffer; + UINT_8 ucTxDescAndPaddingLength = NIC_TX_DESC_LONG_FORMAT_LENGTH + NIC_TX_DESC_PADDING_LENGTH; + /* P_STA_RECORD_T prStaRec = cnmGetStaRecByIndex(prAdapter, prCmdInfo->ucStaRecIndex); */ + P_BSS_INFO_T prBssInfo; + UINT_8 ucTid = 0; + UINT_8 ucTempTC = TC4_INDEX; + P_NATIVE_PACKET prNativePacket; + UINT_8 ucEtherTypeOffsetInWord; + P_MSDU_INFO_T prMsduInfo; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prCmdInfo->ucBssIndex); + prMsduInfo = prCmdInfo->prMsduInfo; + prNativePacket = prMsduInfo->prPacket; + + ASSERT(prNativePacket); + + kalMemZero(prTxDesc, ucTxDescAndPaddingLength); + + /* WLAN index */ + prMsduInfo->ucWlanIndex = nicTxGetWlanIdx(prAdapter, prMsduInfo->ucBssIndex, prMsduInfo->ucStaRecIndex); + + /* UC to a connected peer */ + HAL_MAC_TX_DESC_SET_WLAN_INDEX(prTxDesc, prMsduInfo->ucWlanIndex); + /* Redirect Security frame to TID0 */ + /* ucTempTC = arNetwork2TcResource[prStaRec->ucBssIndex][aucTid2ACI[ucTid]]; */ + + /* Tx byte count */ + HAL_MAC_TX_DESC_SET_TX_BYTE_COUNT(prTxDesc, ucTxDescAndPaddingLength + prCmdInfo->u2InfoBufLen); + + /* Ether-type offset */ + ucEtherTypeOffsetInWord = ((ETHER_HEADER_LEN - ETHER_TYPE_LEN) + ucTxDescAndPaddingLength) >> 1; + HAL_MAC_TX_DESC_SET_ETHER_TYPE_OFFSET(prTxDesc, ucEtherTypeOffsetInWord); + + /* Port index / queue index */ + HAL_MAC_TX_DESC_SET_PORT_INDEX(prTxDesc, arTcResourceControl[ucTempTC].ucDestPortIndex); + HAL_MAC_TX_DESC_SET_QUEUE_INDEX(prTxDesc, arTcResourceControl[ucTempTC].ucDestQueueIndex); + + /* Header format */ + HAL_MAC_TX_DESC_SET_HEADER_FORMAT(prTxDesc, HEADER_FORMAT_NON_802_11); + + /* Long Format */ + HAL_MAC_TX_DESC_SET_LONG_FORMAT(prTxDesc); + + /* Update Packet option */ + nicTxFillDescByPktOption(prMsduInfo, prTxDesc); + + if (!GLUE_TEST_PKT_FLAG(prNativePacket, ENUM_PKT_802_3)) { + /* Set EthernetII */ + HAL_MAC_TX_DESC_SET_ETHERNET_II(prTxDesc); + } + /* Header Padding */ + HAL_MAC_TX_DESC_SET_HEADER_PADDING(prTxDesc, NIC_TX_DESC_HEADER_PADDING_LENGTH); + + /* TID */ + HAL_MAC_TX_DESC_SET_TID(prTxDesc, ucTid); + + /* Remaining TX time */ + HAL_MAC_TX_DESC_SET_REMAINING_LIFE_TIME_IN_MS(prTxDesc, arTcTrafficSettings[ucTempTC].u4RemainingTxTime); + + /* Tx count limit */ + HAL_MAC_TX_DESC_SET_REMAINING_TX_COUNT(prTxDesc, arTcTrafficSettings[ucTempTC].ucTxCountLimit); + + /* Set lowest BSS basic rate */ + HAL_MAC_TX_DESC_SET_FR_RATE(prTxDesc, prBssInfo->u2HwDefaultFixedRateCode); + HAL_MAC_TX_DESC_SET_FIXED_RATE_MODE_TO_DESC(prTxDesc); + HAL_MAC_TX_DESC_SET_FIXED_RATE_ENABLE(prTxDesc); + + /* Own MAC */ + HAL_MAC_TX_DESC_SET_OWN_MAC_INDEX(prTxDesc, prBssInfo->ucOwnMacIndex); + + /* PID */ + if (prMsduInfo->pfTxDoneHandler) { + prMsduInfo->ucPID = nicTxAssignPID(prAdapter, prMsduInfo->ucWlanIndex); + if (prMsduInfo->ucPID > 0) { + HAL_MAC_TX_DESC_SET_PID(prTxDesc, prMsduInfo->ucPID); + HAL_MAC_TX_DESC_SET_TXS_TO_MCU(prTxDesc); + } + } + + if (pucTxDescLength) + *pucTxDescLength = ucTxDescAndPaddingLength; +} + +BOOLEAN nicTxIsTXDTemplateAllowd(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN P_STA_RECORD_T prStaRec) +{ + + if (prMsduInfo->fgIsTXDTemplateValid && (prMsduInfo->ucControlFlag == 0) + && prStaRec && !prMsduInfo->pfTxDoneHandler) { + + return TRUE; + } else { + return FALSE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief In this function, we'll compose the Tx descriptor of the MSDU. +* +* @param prAdapter Pointer to the Adapter structure. +* @param prMsduInfo Pointer to the Msdu info +* @param prTxDesc Pointer to the Tx descriptor buffer +* +* @retval VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicTxFillDesc(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, OUT PUINT_8 prTxDescBuffer, OUT PUINT_8 pucTxDescLength) +{ + P_HW_MAC_TX_DESC_T prTxDesc = (P_HW_MAC_TX_DESC_T) prTxDescBuffer; + P_HW_MAC_TX_DESC_T prTxDescTemplate = NULL; + P_STA_RECORD_T prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + UINT_8 ucTxDescLength; +#if CFG_TCP_IP_CHKSUM_OFFLOAD + UINT_8 ucChksumFlag = 0; +#endif + +/* +*------------------------------------------------------------------------------ +* Fill up common fileds +*------------------------------------------------------------------------------ +*/ + /* Get TXD from pre-allocated template */ + if (nicTxIsTXDTemplateAllowd(prAdapter, prMsduInfo, prStaRec)) { + prTxDescTemplate = prStaRec->aprTxDescTemplate[prMsduInfo->ucUserPriority]; + + if (HAL_MAC_TX_DESC_IS_LONG_FORMAT(prTxDescTemplate)) + ucTxDescLength = NIC_TX_DESC_LONG_FORMAT_LENGTH; + else + ucTxDescLength = NIC_TX_DESC_SHORT_FORMAT_LENGTH; + + kalMemCopy(prTxDesc, prTxDescTemplate, ucTxDescLength); + + /* Overwrite fields for EOSP or More data */ + nicTxFillDescByPktOption(prMsduInfo, prTxDesc); + } + /* Compose TXD by Msdu info */ + else { + ucTxDescLength = NIC_TX_DESC_LONG_FORMAT_LENGTH; + nicTxComposeDesc(prAdapter, prMsduInfo, ucTxDescLength, FALSE, prTxDescBuffer); + } + +/* +*------------------------------------------------------------------------------ +* Fill up remaining parts, per-packet variant fields +*------------------------------------------------------------------------------ +*/ + /* Calculate Tx byte count */ + HAL_MAC_TX_DESC_SET_TX_BYTE_COUNT(prTxDesc, + ucTxDescLength + NIC_TX_DESC_PADDING_LENGTH + prMsduInfo->u2FrameLength); + + /* Checksum offload */ +#if CFG_TCP_IP_CHKSUM_OFFLOAD + if (prMsduInfo->eSrc == TX_PACKET_OS) { + if (prAdapter->u4CSUMFlags & + (CSUM_OFFLOAD_EN_TX_TCP | CSUM_OFFLOAD_EN_TX_UDP | CSUM_OFFLOAD_EN_TX_IP)) { + kalQueryTxChksumOffloadParam(prMsduInfo->prPacket, &ucChksumFlag); + if ((ucChksumFlag & TX_CS_IP_GEN)) + HAL_MAC_TX_DESC_SET_IP_CHKSUM(prTxDesc); + if ((ucChksumFlag & TX_CS_TCP_UDP_GEN)) + HAL_MAC_TX_DESC_SET_TCP_UDP_CHKSUM(prTxDesc); + } + } +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + /* Set EtherType & VLAN for non 802.11 frame */ + if (!prMsduInfo->fgIs802_11) { + if (prMsduInfo->fgIs802_3) + HAL_MAC_TX_DESC_UNSET_ETHERNET_II(prTxDesc); + if (prMsduInfo->fgIsVlanExists) + HAL_MAC_TX_DESC_SET_VLAN(prTxDesc); + } + + if (pucTxDescLength) + *pucTxDescLength = ucTxDescLength; +} + +VOID +nicTxCopyDesc(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucTarTxDesc, IN PUINT_8 pucSrcTxDesc, OUT PUINT_8 pucTxDescLength) +{ + UINT_8 ucTxDescLength; + + if (HAL_MAC_TX_DESC_IS_LONG_FORMAT((P_HW_MAC_TX_DESC_T) pucSrcTxDesc)) + ucTxDescLength = NIC_TX_DESC_LONG_FORMAT_LENGTH; + else + ucTxDescLength = NIC_TX_DESC_SHORT_FORMAT_LENGTH; + + kalMemCopy(pucTarTxDesc, pucSrcTxDesc, ucTxDescLength); + + if (pucTxDescLength) + *pucTxDescLength = ucTxDescLength; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief In this function, we'll generate Tx descriptor template for each TID. +* +* @param prAdapter Pointer to the Adapter structure. +* @param prStaRec Pointer to the StaRec structure. +* +* @retval VOID +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicTxGenerateDescTemplate(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + UINT_8 ucTid; + UINT_8 ucTc; + UINT_16 u2TxDescSize; + P_HW_MAC_TX_DESC_T prTxDesc; + P_MSDU_INFO_T prMsduInfo; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + + /* Free previous template, first */ + /* nicTxFreeDescTemplate(prAdapter, prStaRec); */ + for (ucTid = 0; ucTid < TX_DESC_TID_NUM; ucTid++) + prStaRec->aprTxDescTemplate[ucTid] = NULL; + + prMsduInfo = cnmPktAlloc(prAdapter, 0); + + if (!prMsduInfo) + return WLAN_STATUS_RESOURCES; + + /* Fill up MsduInfo template */ + prMsduInfo->eSrc = TX_PACKET_OS; + prMsduInfo->fgIs802_11 = FALSE; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_3 = FALSE; + prMsduInfo->fgIsVlanExists = FALSE; + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->prPacket = NULL; + prMsduInfo->u2FrameLength = 0; + prMsduInfo->u4Option = 0; + prMsduInfo->u4FixedRateOption = 0; + prMsduInfo->ucRateMode = MSDU_RATE_MODE_AUTO; + prMsduInfo->ucBssIndex = prStaRec->ucBssIndex; + prMsduInfo->ucPacketType = TX_PACKET_TYPE_DATA; + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucPID = NIC_TX_DESC_PID_INVALID; + + u2TxDescSize = NIC_TX_DESC_SHORT_FORMAT_LENGTH; + + DBGLOG(TX, TRACE, "Generate TXD template for STA[%u] QoS[%u]\n", prStaRec->ucIndex, prStaRec->fgIsQoS); + + /* Generate new template */ + if (prStaRec->fgIsQoS) { + /* For QoS STA, generate 8 TXD template (TID0~TID7) */ + for (ucTid = 0; ucTid < TX_DESC_TID_NUM; ucTid++) { + + if (prAdapter->rWifiVar.ucTcRestrict < TC_NUM) + ucTc = prAdapter->rWifiVar.ucTcRestrict; + else + ucTc = arNetwork2TcResource[prStaRec->ucBssIndex][aucTid2ACI[ucTid]]; + u2TxDescSize = arTcTrafficSettings[ucTc].ucTxDescLength; + + prTxDesc = kalMemAlloc(u2TxDescSize, VIR_MEM_TYPE); + if (!prTxDesc) { + rStatus = WLAN_STATUS_RESOURCES; + break; + } + + /* Update MsduInfo TID & TC */ + prMsduInfo->ucUserPriority = ucTid; + prMsduInfo->ucTC = ucTc; + + /* Compose Tx desc template */ + nicTxComposeDesc(prAdapter, prMsduInfo, u2TxDescSize, TRUE, (PUINT_8) prTxDesc); + + prStaRec->aprTxDescTemplate[ucTid] = prTxDesc; + } + } else { + /* For non-QoS STA, generate 1 TXD template (TID0) */ + do { + if (prAdapter->rWifiVar.ucTcRestrict < TC_NUM) { + ucTc = prAdapter->rWifiVar.ucTcRestrict; + } else { + ucTc = arNetwork2TcResource[prStaRec->ucBssIndex] + [NET_TC_NON_STAREC_NON_QOS_INDEX]; + } + /* ucTxDescSize = arTcTrafficSettings[ucTc].ucTxDescLength; */ + u2TxDescSize = NIC_TX_DESC_SHORT_FORMAT_LENGTH; + + prTxDesc = kalMemAlloc(u2TxDescSize, VIR_MEM_TYPE); + if (!prTxDesc) { + rStatus = WLAN_STATUS_RESOURCES; + break; + } + /* Update MsduInfo TID & TC */ + prMsduInfo->ucUserPriority = 0; + prMsduInfo->ucTC = ucTc; + + /* Compose Tx desc template */ + nicTxComposeDesc(prAdapter, prMsduInfo, u2TxDescSize, TRUE, (PUINT_8) prTxDesc); + + for (ucTid = 0; ucTid < TX_DESC_TID_NUM; ucTid++) { + prStaRec->aprTxDescTemplate[ucTid] = prTxDesc; + DBGLOG(TX, TRACE, "TXD template: TID[%hhu] Ptr[%p]\n", ucTid, prTxDesc); + } + } while (FALSE); + } + + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief In this function, we'll free Tx descriptor template for each TID. +* +* @param prAdapter Pointer to the Adapter structure. +* @param prStaRec Pointer to the StaRec structure. +* +* @retval VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID nicTxFreeDescTemplate(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + UINT_8 ucTid; + UINT_8 ucTxDescSize; + P_HW_MAC_TX_DESC_T prTxDesc; + + DBGLOG(TX, TRACE, "Free TXD template for STA[%u] QoS[%u]\n", prStaRec->ucIndex, prStaRec->fgIsQoS); + + if (prStaRec->fgIsQoS) { + for (ucTid = 0; ucTid < TX_DESC_TID_NUM; ucTid++) { + prTxDesc = (P_HW_MAC_TX_DESC_T) prStaRec->aprTxDescTemplate[ucTid]; + + if (prTxDesc) { + if (HAL_MAC_TX_DESC_IS_LONG_FORMAT(prTxDesc)) + ucTxDescSize = NIC_TX_DESC_LONG_FORMAT_LENGTH; + else + ucTxDescSize = NIC_TX_DESC_SHORT_FORMAT_LENGTH; + + kalMemFree(prTxDesc, VIR_MEM_TYPE, ucTxDescSize); + + prTxDesc = prStaRec->aprTxDescTemplate[ucTid] = NULL; + } + } + } else { + prTxDesc = (P_HW_MAC_TX_DESC_T) prStaRec->aprTxDescTemplate[0]; + if (prTxDesc) { + if (HAL_MAC_TX_DESC_IS_LONG_FORMAT(prTxDesc)) + ucTxDescSize = NIC_TX_DESC_LONG_FORMAT_LENGTH; + else + ucTxDescSize = NIC_TX_DESC_SHORT_FORMAT_LENGTH; + + kalMemFree(prTxDesc, VIR_MEM_TYPE, ucTxDescSize); + prTxDesc = NULL; + } + for (ucTid = 0; ucTid < TX_DESC_TID_NUM; ucTid++) + prStaRec->aprTxDescTemplate[ucTid] = NULL; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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; + P_NATIVE_PACKET prNativePacket; + PUINT_8 pucOutputBuf = (PUINT_8) NULL; /* Pointer to Transmit Data Structure Frame */ + P_HW_MAC_TX_DESC_T prTXD = NULL; + UINT_8 ucTxDescSize; + UINT_32 u4ValidBufSize; + UINT_32 u4TotalLength; + P_TX_CTRL_T prTxCtrl; + QUE_T rFreeQueue; + P_QUE_T prFreeQueue; + PUINT_8 pucAheadBuf = NULL; +#if ((CFG_SDIO_TX_AGG == 1) && (CFG_SDIO_TX_AGG_LIMIT != 0)) + BOOLEAN fgWriteNow; +#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 + + prFreeQueue = &rFreeQueue; + + QUEUE_INITIALIZE(prFreeQueue); + + if (!prQue->u4NumElem) + return WLAN_STATUS_SUCCESS; + + prMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_HEAD(prQue); + pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; + u4TotalLength = 0; + + kalMayChangeVcore(); + + while (prMsduInfo) { + + prNativePacket = prMsduInfo->prPacket; + + ASSERT(prNativePacket); + + prTXD = (P_HW_MAC_TX_DESC_T)(pucOutputBuf + u4TotalLength); +#if CFG_SUPPORT_MULTITHREAD + nicTxCopyDesc(prAdapter, (PUINT_8)prTXD, + prMsduInfo->aucTxDescBuffer, &ucTxDescSize); +#else + nicTxFillDesc(prAdapter, prMsduInfo, (PUINT_8)prTXD, &ucTxDescSize); +#endif + u4TotalLength += (ucTxDescSize + NIC_TX_DESC_PADDING_LENGTH); + if (prMsduInfo->eSrc == TX_PACKET_OS) + wlanFillTimestamp(prAdapter, prMsduInfo->prPacket, PHASE_HIF_TX); + 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); + + StatsEnvTxTime2Hif(prAdapter, prMsduInfo); + + prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY(&prMsduInfo->rQueEntry); + + /* Free MSDU_INFO */ + if (prMsduInfo->eSrc == TX_PACKET_MGMT) { + GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum); + } else if (prMsduInfo->eSrc == TX_PACKET_OS) { + wlanTxProfilingTagMsdu(prAdapter, prMsduInfo, TX_PROF_TAG_DRV_DEQUE); + if (prMsduInfo->pfTxDoneHandler) { + /* Record history */ + pucAheadBuf = ((struct sk_buff *)prMsduInfo->prPacket)->data; + prMsduInfo->u2CookieLen = ((struct sk_buff *)prMsduInfo->prPacket)->len; + DBGLOG(TX, TRACE, "u2CookieLen is %u\n", prMsduInfo->u2CookieLen); + prMsduInfo->pucCookie = kalMemAlloc(prMsduInfo->u2CookieLen, VIR_MEM_TYPE); + if (prMsduInfo->pucCookie != NULL) + kalMemCopy(prMsduInfo->pucCookie, pucAheadBuf, prMsduInfo->u2CookieLen); + else + DBGLOG(TX, INFO, "prMsduInfo->pucCookie Alloc failed\n"); + /* Record history */ + } + kalSendComplete(prAdapter->prGlueInfo, prNativePacket, WLAN_STATUS_SUCCESS); + prMsduInfo->prPacket = NULL; + } else if (prMsduInfo->eSrc == TX_PACKET_FORWARDING) { + GLUE_DEC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount); + } + + if (prMsduInfo->pfTxDoneHandler) { + KAL_SPIN_LOCK_DECLARATION(); + DBGLOG(TX, TRACE, "Wait WIDX:PID[%u:%u] SEQ[%u]\n", + prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, prMsduInfo->ucTxSeqNum); + + if (prMsduInfo->ucPID > 0) { + 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 { + prMsduInfo->ucPID = nicTxAssignPID(prAdapter, prMsduInfo->ucWlanIndex | BIT(7)); + if (prMsduInfo->ucPID > 0) { + HAL_MAC_TX_DESC_SET_PID(prTXD, prMsduInfo->ucPID); + HAL_MAC_TX_DESC_SET_TXS_TO_MCU(prTXD); + 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 { + DBGLOG(TX, WARN, "Give up req TX done, handler %p, no PID can be assigned\n", + prMsduInfo->pfTxDoneHandler); + if (prMsduInfo->eSrc == TX_PACKET_MGMT) + cnmMgtPktFree(prAdapter, prMsduInfo); + else + QUEUE_INSERT_TAIL(prFreeQueue, (P_QUE_ENTRY_T) prMsduInfo); + } + } + } else { + if (prMsduInfo->eSrc == TX_PACKET_MGMT) + cnmMgtPktFree(prAdapter, prMsduInfo); + else + QUEUE_INSERT_TAIL(prFreeQueue, (P_QUE_ENTRY_T) prMsduInfo); + } + if (prMsduInfo->ucPID > NIC_TX_DESC_DRIVER_PID_MAX) + DBGLOG(TX, INFO, "Abnormal PID:%d\n", prMsduInfo->ucPID); +#if (CFG_SDIO_TX_AGG == 0) + ASSERT(u4TotalLength <= u4ValidBufSize); + + HAL_WRITE_TX_PORT(prAdapter, u4TotalLength, pucOutputBuf, u4ValidBufSize); + + /* reset total length */ + u4TotalLength = 0; + +#elif ((CFG_SDIO_TX_AGG == 1) && (CFG_SDIO_TX_AGG_LIMIT != 0)) + fgWriteNow = TRUE; + + if (prNextMsduInfo) { + if ((u4TotalLength + NIC_TX_DESC_AND_PADDING_LENGTH + + ALIGN_4(prNextMsduInfo->u2FrameLength)) < CFG_SDIO_TX_AGG_LIMIT) + fgWriteNow = FALSE; + } + + /* Write to HIF */ + if (fgWriteNow) { + ASSERT(u4TotalLength <= u4ValidBufSize); + + HAL_WRITE_TX_PORT(prAdapter, u4TotalLength, pucOutputBuf, u4ValidBufSize); + + /* reset total length */ + u4TotalLength = 0; + } +#endif + + prMsduInfo = prNextMsduInfo; + } + +#if ((CFG_SDIO_TX_AGG == 1) && (CFG_SDIO_TX_AGG_LIMIT == 0)) + if (u4TotalLength > u4ValidBufSize) { + DBGLOG(TX, ERROR, "Tx Error! Port[%u] u4TotalLength[%u] > u4ValidBufSize[%u]\n", + ucPortIdx, u4TotalLength, u4ValidBufSize); + + DBGLOG(TX, ERROR, "Tx Error! TxQ count[%u], FreeQ count[%u]\n", + prQue->u4NumElem, prFreeQueue->u4NumElem); + + prMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_HEAD(prFreeQueue); + DBGLOG(TX, WARN, "=== Dump MsduInfo ===\n"); + while (prMsduInfo) { + + DBGLOG(TX, WARN, "Msdu[0x%p] Src[%u] Len[%u] Bss[%u] Sta[%u] TC[%u]\n", + prMsduInfo, prMsduInfo->eSrc, prMsduInfo->u2FrameLength, + prMsduInfo->ucBssIndex, prMsduInfo->ucStaRecIndex, + prMsduInfo->ucTC); + + prMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY(&prMsduInfo->rQueEntry); + } + DBGLOG(TX, WARN, "=== Dump done ===\n"); + + qmDumpQueueStatus(prAdapter); + } + + ASSERT(u4TotalLength <= u4ValidBufSize); + + HAL_WRITE_TX_PORT(prAdapter, u4TotalLength, pucOutputBuf, u4ValidBufSize); +#endif + wlanTxLifetimeTagPacketQue(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(&rFreeQueue), + TX_PROF_TAG_DRV_TX_DONE); + + 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; + P_MSDU_INFO_T prMsduInfo; + P_NATIVE_PACKET prNativePacket; + P_WLAN_MAC_HEADER_T prMgmtHeader; + UINT_16 u2OverallLength; + UINT_8 ucTxDescLength; + PUINT_8 pucOutputBuf = (PUINT_8) NULL; /* Pointer to Transmit Data Structure Frame */ + P_TX_CTRL_T prTxCtrl; + P_HW_MAC_TX_DESC_T prTxDesc = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_SCAN_INFO_T prScanInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prTxCtrl = &prAdapter->rTxCtrl; + pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; + prTxDesc = (P_HW_MAC_TX_DESC_T)&pucOutputBuf[0]; + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanTraceTxCmd(prCmdInfo); +#endif + if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) { + kalMayChangeVcore(); + prMsduInfo = prCmdInfo->prMsduInfo; + +#if CFG_SUPPORT_MULTITHREAD + nicTxCopyDesc(prAdapter, (PUINT_8)prTxDesc, prMsduInfo->aucTxDescBuffer, &ucTxDescLength); +#else + nicTxComposeSecurityFrameDesc(prAdapter, prCmdInfo, (PUINT_8)prTxDesc, &ucTxDescLength); +#endif + + u2OverallLength = ALIGN_4(ucTxDescLength + NIC_TX_DESC_PADDING_LENGTH + prCmdInfo->u2InfoBufLen); + + prNativePacket = prMsduInfo->prPacket; + if (prNativePacket) { + prMsduInfo->prPacket = NULL; + prMsduInfo->ucEapolKeyType = kalGetEapolKeyType(prNativePacket); + /* <3> Copy Frame Body */ + kalCopyFrame(prAdapter->prGlueInfo, prNativePacket, + pucOutputBuf + ucTxDescLength + NIC_TX_DESC_PADDING_LENGTH); + } else { + DBGLOG(TX, WARN, "prNativePacket is null\n"); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + rStatus = WLAN_STATUS_FAILURE; + goto out; + } + DBGLOG(TX, INFO, + "TX SEC:BSS[%u]WIDX:PID[%u:%u]S[%u]L[%u]E[%u]R[%u]S[%d]F[%u]FR[%u]AI[%d]PO[%d]\n", + prCmdInfo->ucBssIndex, + HAL_MAC_TX_DESC_GET_WLAN_INDEX(prTxDesc), + prMsduInfo->ucPID, prCmdInfo->ucStaRecIndex, + ucTxDescLength + prCmdInfo->u2InfoBufLen, + HAL_MAC_TX_DESC_IS_PROTECTION(prTxDesc), + prMsduInfo->pfTxDoneHandler ? TRUE : FALSE, + prMsduInfo->ucTxSeqNum, + GLUE_GET_PKT_FLAG(prNativePacket), + prTxDesc->u2FixedRate, + prTxDesc->ucAntID, + prTxDesc->ucPowerOffset); + + if (prMsduInfo->pfTxDoneHandler) { + /* DBGLOG(INIT, TRACE,("Wait Cmd TxSeqNum:%d\n", prMsduInfo->ucTxSeqNum)); */ + if (prMsduInfo->ucPID > 0) { + 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 { + prMsduInfo->ucPID = nicTxAssignPID(prAdapter, prMsduInfo->ucWlanIndex); + if (prMsduInfo->ucPID > 0) { + HAL_MAC_TX_DESC_SET_PID(prTxDesc, prMsduInfo->ucPID); + HAL_MAC_TX_DESC_SET_TXS_TO_MCU(prTxDesc); + 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 { + DBGLOG(TX, WARN, + "EAPOL: Give up req TX done since no slot, handler %p, EAPOL type %d\n", + prMsduInfo->pfTxDoneHandler, prMsduInfo->ucEapolKeyType); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } + } + } else { + /* Only return MSDU_INFO */ + /* NativePacket will be freed at SEC frame CMD callback */ + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } + + } else if (prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) { + prMsduInfo = prCmdInfo->prMsduInfo; + + ASSERT(prMsduInfo->fgIs802_11 == TRUE); + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + prMgmtHeader = (P_WLAN_MAC_HEADER_T) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + +#if CFG_SUPPORT_MULTITHREAD + nicTxCopyDesc(prAdapter, (PUINT_8)prTxDesc, prMsduInfo->aucTxDescBuffer, &ucTxDescLength); +#else + nicTxFillDesc(prAdapter, prMsduInfo, (PUINT_8)prTxDesc, &ucTxDescLength); +#endif + + u2OverallLength = ALIGN_4(ucTxDescLength + NIC_TX_DESC_PADDING_LENGTH + prMsduInfo->u2FrameLength); + + /* <3> Copy Frame Body */ + kalMemCopy(pucOutputBuf + ucTxDescLength + NIC_TX_DESC_PADDING_LENGTH, + prMsduInfo->prPacket, prMsduInfo->u2FrameLength); + + DBGLOG(TX, INFO, + "TX MGMT Frame: SUBTYPE[%x] BSS[%d] WIDX:PID[%d:%d] SEQ[%d] STA[%d] LEN[%d] RSP[%d]\n", + (UINT_16)(prMgmtHeader->u2FrameCtrl & MASK_FC_SUBTYPE) >> OFFSET_OF_FC_SUBTYPE, + prCmdInfo->ucBssIndex, prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, + prMsduInfo->ucTxSeqNum, prMsduInfo->ucStaRecIndex, u2OverallLength, + prMsduInfo->pfTxDoneHandler ? TRUE : FALSE); + + /* <4> Management Frame Post-Processing */ + GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum); + + if (prMsduInfo->pfTxDoneHandler) { + /* DBGLOG(INIT, TRACE,("Wait Cmd TxSeqNum:%d\n", prMsduInfo->ucTxSeqNum)); */ + if (prMsduInfo->ucPID > 0) { + 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 { + prMsduInfo->ucPID = nicTxAssignPID(prAdapter, prMsduInfo->ucWlanIndex); + if (prMsduInfo->ucPID > 0) { + HAL_MAC_TX_DESC_SET_PID(prTxDesc, prMsduInfo->ucPID); + HAL_MAC_TX_DESC_SET_TXS_TO_MCU(prTxDesc); + 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 { + DBGLOG(TX, WARN, + "MGMT: Give up req TX done since no slot, handler %p, SEQ:%d\n", + prMsduInfo->pfTxDoneHandler, prMsduInfo->ucTxSeqNum); + cnmMgtPktFree(prAdapter, prMsduInfo); + } + } + } else { + cnmMgtPktFree(prAdapter, prMsduInfo); + } + + } else { + prWifiCmd = (P_WIFI_CMD_T) prCmdInfo->pucInfoBuffer; + + /* <2> Compose the Header of Transmit Data Structure for CMD Packet */ + u2OverallLength = ALIGN_4(prCmdInfo->u2InfoBufLen); + + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + + /* <3> Copy CMD Header to command buffer (by using pucCoalescingBufCached) */ + kalMemCopy(pucOutputBuf, prCmdInfo->pucInfoBuffer, prCmdInfo->u2InfoBufLen); + + ASSERT(u2OverallLength <= prAdapter->u4CoalescingBufCachedSize); + + if ((prWifiCmd->ucCID == CMD_ID_SCAN_REQ) || + (prWifiCmd->ucCID == CMD_ID_SCAN_CANCEL) || + (prWifiCmd->ucCID == CMD_ID_SCAN_REQ_V2)) { + DBGLOG(TX, INFO, "TX CMD: ID[0x%02X] SEQ[%u] SET[%u] LEN[%u]\n", + prWifiCmd->ucCID, prWifiCmd->ucSeqNum, prWifiCmd->ucSetQuery, + prWifiCmd->u2TxByteCount); + } else { + DBGLOG(TX, TRACE, "TX CMD: ID[0x%02X] SEQ[%u] SET[%u] LEN[%u]\n", + prWifiCmd->ucCID, prWifiCmd->ucSeqNum, prWifiCmd->ucSetQuery, + prWifiCmd->u2TxByteCount); + } + } + + if (prScanInfo->ucScanDoneTimeoutCnt) { + #if defined(MT6631) + HAL_DUMP_AHB_INFO(prAdapter, prAdapter->u2ChipID); + #endif + /* <4> Write frame to data port */ + HAL_WRITE_TX_PORT(prAdapter, + (UINT_32) u2OverallLength, pucOutputBuf, + prAdapter->u4CoalescingBufCachedSize); + #if defined(MT6631) + HAL_DUMP_AHB_INFO(prAdapter, prAdapter->u2ChipID); + #endif + } else + HAL_WRITE_TX_PORT(prAdapter, + (UINT_32) u2OverallLength, pucOutputBuf, + prAdapter->u4CoalescingBufCachedSize); +out: + return rStatus; +} /* 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, IN BOOLEAN fgProcTxDoneHandler) +{ + 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) { + DBGLOG(TX, INFO, "%s: Get Msdu WIDX:PID[%u:%u] SEQ[%u] from Pending Q\n", + __func__, + prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, prMsduInfo->ucTxSeqNum); + + /* invoke done handler */ + if (prMsduInfo->pfTxDoneHandler && fgProcTxDoneHandler) + prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_DROPPED_IN_DRIVER); + + nicTxFreeMsduInfoPacket(prAdapter, prMsduInfo); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } else { + break; + } + } while (TRUE); + +} /* end of nicTxRelease() */ + +VOID nicTxInterruptSanityCheck(IN P_ADAPTER_T prAdapter, IN UINT_16 *au2TxRlsCnt) +{ + UINT_8 ucIdx; + BOOLEAN fgError = FALSE; + + if (prAdapter->rWifiVar.ucTxDbg & BIT(1)) { + for (ucIdx = HIF_TX_AC0_INDEX; ucIdx < HIF_TX_NUM; ucIdx++) { + if (au2TxRlsCnt[ucIdx] > CFG_MAX_TX_PAGE_COUNT) + fgError = TRUE; + } + + if (fgError) + DBGLOG(TX, ERROR, "Tx Done INT result, FFA[%u] AC[%u:%u:%u:%u:%u] CPU[%u]\n", + au2TxRlsCnt[HIF_TX_FFA_INDEX], au2TxRlsCnt[HIF_TX_AC0_INDEX], + au2TxRlsCnt[HIF_TX_AC1_INDEX], au2TxRlsCnt[HIF_TX_AC2_INDEX], + au2TxRlsCnt[HIF_TX_AC3_INDEX], au2TxRlsCnt[HIF_TX_AC4_INDEX], + au2TxRlsCnt[HIF_TX_CPU_INDEX]); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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); + prAdapter->prGlueInfo->IsrTxCnt++; + /* Get the TX STATUS */ +#if CFG_SDIO_INTR_ENHANCE + + prSDIOCtrl = prAdapter->prSDIOCtrl; +#if DBG + /* dumpMemory8((PUINT_8)prSDIOCtrl, sizeof(SDIO_CTRL_T)); */ +#endif + + nicTxInterruptSanityCheck(prAdapter, (PUINT_16) &prSDIOCtrl->rTxInfo); + nicTxReleaseResource(prAdapter, (PUINT_16) &prSDIOCtrl->rTxInfo); + kalMemZero(&prSDIOCtrl->rTxInfo, sizeof(prSDIOCtrl->rTxInfo)); + +#else + + HAL_MCR_RD(prAdapter, MCR_WTSR0, &au4TxCount[0]); + HAL_MCR_RD(prAdapter, MCR_WTSR1, &au4TxCount[1]); + DBGLOG(EMU, TRACE, "MCR_WTSR0: 0x%x, MCR_WTSR1: 0x%x\n", au4TxCount[0], au4TxCount[1]); + + nicTxReleaseResource(prAdapter, (PUINT_8) au4TxCount); + +#endif /* CFG_SDIO_INTR_ENHANCE */ + + nicTxAdjustTcq(prAdapter); + + /* Indicate Service Thread */ + if (kalGetTxPendingCmdCount(prAdapter->prGlueInfo) > 0 || wlanGetTxPendingFrameCount(prAdapter) > 0) + kalSetEvent(prAdapter->prGlueInfo); + +} /* end of nicProcessTxInterrupt() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief this function frees packet of P_MSDU_INFO_T linked-list +* +* @param prAdapter Pointer to the Adapter structure. +* @param prMsduInfoList a link list of P_MSDU_INFO_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicTxFreeMsduInfoPacket(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead) +{ + P_NATIVE_PACKET prNativePacket; + P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead; + P_TX_CTRL_T prTxCtrl; + + ASSERT(prAdapter); + ASSERT(prMsduInfoListHead); + + prTxCtrl = &prAdapter->rTxCtrl; + + while (prMsduInfo) { + prNativePacket = prMsduInfo->prPacket; + + if (prMsduInfo->eSrc == TX_PACKET_OS) { + if (prNativePacket) + kalSendComplete(prAdapter->prGlueInfo, prNativePacket, WLAN_STATUS_FAILURE); + /*get per-AC Tx drop packets */ + wlanUpdateTxStatistics(prAdapter, prMsduInfo, TRUE); + } else if (prMsduInfo->eSrc == TX_PACKET_MGMT) { + if (prMsduInfo->pfTxDoneHandler) + prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_DROPPED_IN_DRIVER); + if (prNativePacket) + 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); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief this function returns P_MSDU_INFO_T of MsduInfoList to TxCtrl->rfreeMsduInfoList +* +* @param prAdapter Pointer to the Adapter structure. +* @param prMsduInfoList a link list of P_MSDU_INFO_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicTxReturnMsduInfo(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead) +{ + P_TX_CTRL_T prTxCtrl; + P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead, prNextMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + while (prMsduInfo) { + prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); + + switch (prMsduInfo->eSrc) { + case TX_PACKET_FORWARDING: + wlanReturnPacket(prAdapter, prMsduInfo->prPacket); + break; + case TX_PACKET_OS: + case TX_PACKET_OS_OID: + case TX_PACKET_MGMT: + default: + break; + } + + /* Reset MSDU_INFO fields */ + if (prMsduInfo->pucCookie) + kalMemFree(prMsduInfo->pucCookie, VIR_MEM_TYPE, prMsduInfo->u2CookieLen); + kalMemZero(prMsduInfo, sizeof(MSDU_INFO_T)); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + QUEUE_INSERT_TAIL(&prTxCtrl->rFreeMsduInfoList, (P_QUE_ENTRY_T) prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + prMsduInfo = prNextMsduInfo; + }; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief this function fills packet information to P_MSDU_INFO_T +* +* @param prAdapter Pointer to the Adapter structure. +* @param prMsduInfo P_MSDU_INFO_T +* @param prPacket P_NATIVE_PACKET +* +* @retval TRUE Success to extract information +* @retval FALSE Fail to extract correct information +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN nicTxFillMsduInfo(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN P_NATIVE_PACKET prPacket) +{ + P_GLUE_INFO_T prGlueInfo; + + ASSERT(prAdapter); + + kalMemZero(prMsduInfo, sizeof(MSDU_INFO_T)); + + prGlueInfo = prAdapter->prGlueInfo; + ASSERT(prGlueInfo); + + kalGetEthDestAddr(prAdapter->prGlueInfo, prPacket, prMsduInfo->aucEthDestAddr); + + prMsduInfo->prPacket = prPacket; + prMsduInfo->ucBssIndex = GLUE_GET_PKT_BSS_IDX(prPacket); + prMsduInfo->ucUserPriority = GLUE_GET_PKT_TID(prPacket); + prMsduInfo->ucMacHeaderLength = GLUE_GET_PKT_HEADER_LEN(prPacket); + prMsduInfo->u2FrameLength = (UINT_16) GLUE_GET_PKT_FRAME_LEN(prPacket); + prMsduInfo->ucPageCount = nicTxGetPageCount(prMsduInfo->u2FrameLength, FALSE); + + if (GLUE_IS_PKT_FLAG_SET(prPacket)) { + prMsduInfo->fgIs802_1x = GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_1X); + prMsduInfo->fgIs802_3 = GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_802_3); + prMsduInfo->fgIsVlanExists = GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_VLAN_EXIST); + + if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_DHCP) && prAdapter->rWifiVar.ucDhcpTxDone) { + prMsduInfo->pfTxDoneHandler = wlanDhcpTxDone; + prMsduInfo->ucTxSeqNum = GLUE_GET_PKT_SEQ_NO(prPacket); + } else if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_ARP) && prAdapter->rWifiVar.ucArpTxDone) { + prMsduInfo->pfTxDoneHandler = wlanArpTxDone; + prMsduInfo->ucTxSeqNum = GLUE_GET_PKT_SEQ_NO(prPacket); + } else if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_ICMP) && prAdapter->rWifiVar.ucIcmpTxDone) { + prMsduInfo->pfTxDoneHandler = wlanIcmpTxDone; + prMsduInfo->ucTxSeqNum = GLUE_GET_PKT_SEQ_NO(prPacket); + } else if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_TDLS)) { + prMsduInfo->pfTxDoneHandler = wlanTdlsTxDone; + prMsduInfo->ucTxSeqNum = GLUE_GET_PKT_SEQ_NO(prPacket); + } else if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_DNS)) { + prMsduInfo->pfTxDoneHandler = wlanDnsTxDone; + prMsduInfo->ucTxSeqNum = GLUE_GET_PKT_SEQ_NO(prPacket); + } + if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_DHCP) || GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_ARP)) { + prMsduInfo->ucUserPriority = 6; /* use VO priority */ + prMsduInfo->ucDhcpArpFlag = 1; + } + } + + /* Reset to default value by memory zero */ + /* prMsduInfo->ucPID = NIC_TX_DESC_PID_INVALID; */ + /* prMsduInfo->ucRateMode = MSDU_RATE_MODE_AUTO; */ + /* prMsduInfo->fgIsTXDTemplateValid = FALSE; */ + /* prMsduInfo->ucPacketType = TX_PACKET_TYPE_DATA; */ + /* prMsduInfo->fgIs802_11 = FALSE; */ + + 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) +{ +#if CFG_SUPPORT_MULTITHREAD + TX_TCQ_ADJUST_T rTcqAdjust; + P_TX_CTRL_T prTxCtrl; + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + qmAdjustTcQuotasMthread(prAdapter, &rTcqAdjust, &prTxCtrl->rTc); + +#else + + UINT_32 u4Num; + TX_TCQ_ADJUST_T rTcqAdjust; + P_TX_CTRL_T prTxCtrl; + P_TX_TCQ_STATUS_T prTcqStatus; + + KAL_SPIN_LOCK_DECLARATION(); + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + prTcqStatus = &prAdapter->rTxCtrl.rTc; + ASSERT(prTxCtrl); + + if (qmAdjustTcQuotas(prAdapter, &rTcqAdjust, &prTxCtrl->rTc)) { + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + for (u4Num = 0; u4Num < TC_NUM; u4Num++) { + /* Page count */ + prTxCtrl->rTc.au2FreePageCount[u4Num] += + (rTcqAdjust.acVariation[u4Num] * NIC_TX_MAX_PAGE_PER_FRAME); + prTxCtrl->rTc.au2MaxNumOfPage[u4Num] += + (rTcqAdjust.acVariation[u4Num] * NIC_TX_MAX_PAGE_PER_FRAME); + + /* Buffer count */ + prTxCtrl->rTc.au2FreeBufferCount[u4Num] += rTcqAdjust.acVariation[u4Num]; + prTxCtrl->rTc.au2MaxNumOfBuffer[u4Num] += rTcqAdjust.acVariation[u4Num]; + + ASSERT(prTxCtrl->rTc.au2FreeBufferCount[u4Num] >= 0); + ASSERT(prTxCtrl->rTc.au2MaxNumOfBuffer[u4Num] >= 0); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); +#if 0 + DBGLOG(TX, LOUD, + "TCQ Status Free Page:Buf[%03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u]\n", + prTcqStatus->au2FreePageCount[TC0_INDEX], + prTcqStatus->au2FreeBufferCount[TC0_INDEX], + prTcqStatus->au2FreePageCount[TC1_INDEX], + prTcqStatus->au2FreeBufferCount[TC1_INDEX], + prTcqStatus->au2FreePageCount[TC2_INDEX], + prTcqStatus->au2FreeBufferCount[TC2_INDEX], + prTcqStatus->au2FreePageCount[TC3_INDEX], + prTcqStatus->au2FreeBufferCount[TC3_INDEX], + prTcqStatus->au2FreePageCount[TC4_INDEX], + prTcqStatus->au2FreeBufferCount[TC4_INDEX], + prTcqStatus->au2FreePageCount[TC5_INDEX], prTcqStatus->au2FreeBufferCount[TC5_INDEX])); +#endif + DBGLOG(TX, LOUD, + "TCQ Status Max Page:Buf[%03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u]\n", + prTcqStatus->au2MaxNumOfPage[TC0_INDEX], + prTcqStatus->au2MaxNumOfBuffer[TC0_INDEX], + prTcqStatus->au2MaxNumOfPage[TC1_INDEX], + prTcqStatus->au2MaxNumOfBuffer[TC1_INDEX], + prTcqStatus->au2MaxNumOfPage[TC2_INDEX], + prTcqStatus->au2MaxNumOfBuffer[TC2_INDEX], + prTcqStatus->au2MaxNumOfPage[TC3_INDEX], + prTcqStatus->au2MaxNumOfBuffer[TC3_INDEX], + prTcqStatus->au2MaxNumOfPage[TC4_INDEX], + prTcqStatus->au2MaxNumOfBuffer[TC4_INDEX], + prTcqStatus->au2MaxNumOfPage[TC5_INDEX], prTcqStatus->au2MaxNumOfBuffer[TC5_INDEX])); + + } +#endif + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief this function flushes all packets queued in STA/AC queue +* +* @param prAdapter Pointer to the Adapter structure. +* +* @retval WLAN_STATUS_SUCCESS Flushed successfully +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS nicTxFlush(IN P_ADAPTER_T prAdapter) +{ + P_MSDU_INFO_T prMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + ASSERT(prAdapter); + + /* ask Per STA/AC queue to be fllushed and return all queued packets */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + prMsduInfo = qmFlushTxQueues(prAdapter); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + + if (prMsduInfo != NULL) { + nicTxFreeMsduInfoPacket(prAdapter, prMsduInfo); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_ENABLE_FW_DOWNLOAD +/*----------------------------------------------------------------------------*/ +/*! +* \brief In this function, we'll write Command(CMD_INFO_T) into HIF. +* However this function is used for INIT_CMD. +* +* In order to avoid further maintenance issues, these 2 functions are separated +* +* @param prAdapter Pointer to the Adapter structure. +* @param prPacketInfo Pointer of CMD_INFO_T +* @param ucTC Specify the resource of TC +* +* @retval WLAN_STATUS_SUCCESS Bus access ok. +* @retval WLAN_STATUS_FAILURE Bus access fail. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicTxInitCmd(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + UINT_16 u2OverallLength; + PUINT_8 pucOutputBuf = (PUINT_8) NULL; /* Pointer to Transmit Data Structure Frame */ + P_TX_CTRL_T prTxCtrl; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prTxCtrl = &prAdapter->rTxCtrl; + pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; + u2OverallLength = ALIGN_4(prCmdInfo->u2InfoBufLen); + + /* <1> Copy CMD Header to command buffer (by using pucCoalescingBufCached) */ + kalMemCopy(pucOutputBuf, prCmdInfo->pucInfoBuffer, prCmdInfo->u2InfoBufLen); + + ASSERT(u2OverallLength <= prAdapter->u4CoalescingBufCachedSize); + + /* <2> Write frame to data port */ + HAL_WRITE_TX_PORT(prAdapter, + (UINT_32) u2OverallLength, pucOutputBuf, 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; + UINT_8 ucIdx; + + DEBUGFUNC("nicTxInitResetResource"); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + /* Delta page count */ + kalMemZero(prTxCtrl->rTc.au2TxDonePageCount, sizeof(prTxCtrl->rTc.au2TxDonePageCount)); + kalMemZero(prTxCtrl->rTc.au2PreUsedPageCount, sizeof(prTxCtrl->rTc.au2PreUsedPageCount)); + prTxCtrl->rTc.ucNextTcIdx = TC0_INDEX; + prTxCtrl->rTc.u2AvaliablePageCount = 0; + + /* Page count */ + prTxCtrl->rTc.au2MaxNumOfPage[TC0_INDEX] = NIC_TX_INIT_PAGE_COUNT_TC0; + prTxCtrl->rTc.au2FreePageCount[TC0_INDEX] = NIC_TX_INIT_PAGE_COUNT_TC0; + + prTxCtrl->rTc.au2MaxNumOfPage[TC1_INDEX] = NIC_TX_INIT_PAGE_COUNT_TC1; + prTxCtrl->rTc.au2FreePageCount[TC1_INDEX] = NIC_TX_INIT_PAGE_COUNT_TC1; + + prTxCtrl->rTc.au2MaxNumOfPage[TC2_INDEX] = NIC_TX_INIT_PAGE_COUNT_TC2; + prTxCtrl->rTc.au2FreePageCount[TC2_INDEX] = NIC_TX_INIT_PAGE_COUNT_TC2; + + prTxCtrl->rTc.au2MaxNumOfPage[TC3_INDEX] = NIC_TX_INIT_PAGE_COUNT_TC3; + prTxCtrl->rTc.au2FreePageCount[TC3_INDEX] = NIC_TX_INIT_PAGE_COUNT_TC3; + + prTxCtrl->rTc.au2MaxNumOfPage[TC4_INDEX] = NIC_TX_INIT_PAGE_COUNT_TC4; + prTxCtrl->rTc.au2FreePageCount[TC4_INDEX] = NIC_TX_INIT_PAGE_COUNT_TC4; + + prTxCtrl->rTc.au2MaxNumOfPage[TC5_INDEX] = NIC_TX_INIT_PAGE_COUNT_TC5; + prTxCtrl->rTc.au2FreePageCount[TC5_INDEX] = NIC_TX_INIT_PAGE_COUNT_TC5; + + /* Buffer count */ + for (ucIdx = TC0_INDEX; ucIdx < TC_NUM; ucIdx++) { + prTxCtrl->rTc.au2MaxNumOfBuffer[ucIdx] = + prTxCtrl->rTc.au2MaxNumOfPage[ucIdx] / NIC_TX_MAX_PAGE_PER_FRAME; + prTxCtrl->rTc.au2FreeBufferCount[ucIdx] = + prTxCtrl->rTc.au2FreePageCount[ucIdx] / NIC_TX_MAX_PAGE_PER_FRAME; + } + + return WLAN_STATUS_SUCCESS; + +} + +#endif + +BOOLEAN nicTxProcessMngPacket(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + + if (prMsduInfo->eSrc != TX_PACKET_MGMT) + return FALSE; + + /* Sanity check */ + if (!prMsduInfo->prPacket) + return FALSE; + + if (!prMsduInfo->u2FrameLength) + return FALSE; + + if (!prMsduInfo->ucMacHeaderLength) + return FALSE; + + + /* MMPDU: force stick to TC4 */ + prMsduInfo->ucTC = TC4_INDEX; + + /* No Tx descriptor template for MMPDU */ + prMsduInfo->fgIsTXDTemplateValid = FALSE; + + /* Fixed Rate */ + if (prMsduInfo->ucRateMode == MSDU_RATE_MODE_AUTO) + + + nicTxSetPktLowestFixedRate(prAdapter, prMsduInfo); + +#if CFG_SUPPORT_MULTITHREAD + nicTxFillDesc(prAdapter, prMsduInfo, prMsduInfo->aucTxDescBuffer, NULL); +#endif + + return TRUE; +} + +VOID nicTxProcessTxDoneEvent(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_EVENT_TX_DONE_T prTxDone; + P_MSDU_INFO_T prMsduInfo; + + prTxDone = (P_EVENT_TX_DONE_T) (prEvent->aucBuffer); + if (prTxDone->ucPacketSeq < NIC_TX_DESC_DRIVER_PID_MIN || + prTxDone->ucPacketSeq > NIC_TX_DESC_DRIVER_PID_MAX) { + DBGLOG(TX, ERROR, "PacketSeq in TX done event is wrong, value %d\n", prTxDone->ucPacketSeq); + return; + } + if (prTxDone->ucWlanIndex >= WTBL_SIZE) { + DBGLOG(TX, ERROR, "WlanIndex in TX done event is wrong, value %d\n", prTxDone->ucWlanIndex); + return; + } + + clear_bit(prTxDone->ucPacketSeq, &prAdapter->au8PidPool[prTxDone->ucWlanIndex][0]); + + if (prTxDone->ucFlag & BIT(0)) { + /* Tx Done with advanced info */ + DBGLOG(TX, TRACE, "EVENT_ID_TX_DONE WIDX:PID[%u:%u] Status[%u] SN[%u] CNT[%u] RATE[0x%04x]\n", + prTxDone->ucWlanIndex, prTxDone->ucPacketSeq, prTxDone->ucStatus, + prTxDone->u2SequenceNumber, prTxDone->ucTxCount, prTxDone->u2TxRate); + } else { + DBGLOG(TX, TRACE, "EVENT_ID_TX_DONE WIDX:PID[%u:%u] Status[%u] SN[%u]\n", + prTxDone->ucWlanIndex, prTxDone->ucPacketSeq, prTxDone->ucStatus, + prTxDone->u2SequenceNumber); + } + + /* call related TX Done Handler */ + prMsduInfo = nicGetPendingTxMsduInfo(prAdapter, prTxDone->ucWlanIndex, prTxDone->ucPacketSeq); + +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT + DBGLOG(TX, 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)); + + if (prMsduInfo->eSrc == TX_PACKET_MGMT) + cnmMgtPktFree(prAdapter, prMsduInfo); + else + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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_QUE_T prDataPort0, prDataPort1; + P_CMD_INFO_T prCmdInfo; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + KAL_SPIN_LOCK_DECLARATION(); + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + prDataPort0 = &qDataPort0; + prDataPort1 = &qDataPort1; + + QUEUE_INITIALIZE(prDataPort0); + QUEUE_INITIALIZE(prDataPort1); + + /* 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) { + if (nicTxProcessMngPacket(prAdapter, prMsduInfo)) { + /* Valid MGMT */ + QUEUE_INSERT_TAIL(prDataPort1, (P_QUE_ENTRY_T) prMsduInfo); + } else { + /* Invalid MGMT */ + DBGLOG(TX, WARN, "Invalid MGMT[0x%p] BSS[%u] STA[%u],free it\n", + prMsduInfo, prMsduInfo->ucBssIndex, + prMsduInfo->ucStaRecIndex); + + cnmMgtPktFree(prAdapter, prMsduInfo); + } + } else { + QUEUE_INSERT_TAIL(prDataPort0, (P_QUE_ENTRY_T) prMsduInfo); + } + + prMsduInfo = prNextMsduInfo; + } + + if (prDataPort0->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(prDataPort0)); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + + /* post-process for dropped packets */ + if (prRetMsduInfo) { /* unable to enqueue */ + nicTxFreeMsduInfoPacket(prAdapter, prRetMsduInfo); + nicTxReturnMsduInfo(prAdapter, prRetMsduInfo); + } + } + + if (prDataPort1->u4NumElem) { + prMsduInfoHead = (P_MSDU_INFO_T) QUEUE_GET_HEAD(prDataPort1); + + if (nicTxGetFreeCmdCount(prAdapter) < NIC_TX_CMD_INFO_RESERVED_COUNT) { + /* 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)); + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + /* Tag MGMT enqueue time */ + GET_CURRENT_SYSTIME(&prMsduInfoHead->rPktProfile.rEnqueueTimestamp); +#endif + prCmdInfo->eCmdType = COMMAND_TYPE_MANAGEMENT_FRAME; + prCmdInfo->u2InfoBufLen = prMsduInfoHead->u2FrameLength; + prCmdInfo->pucInfoBuffer = NULL; + prCmdInfo->prMsduInfo = prMsduInfoHead; + prCmdInfo->ucStaRecIndex = prMsduInfoHead->ucStaRecIndex; + prCmdInfo->ucBssIndex = prMsduInfoHead->ucBssIndex; + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->pfCmdTimeoutHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->ucCmdSeqNum = prMsduInfoHead->ucTxSeqNum; + + DBGLOG(TX, TRACE, "%s: EN-Q MSDU[0x%p] SEQ[%u] BSS[%u] STA[%u] to CMD Q\n", + __func__, prMsduInfoHead, + prMsduInfoHead->ucTxSeqNum, prMsduInfoHead->ucBssIndex, + prMsduInfoHead->ucStaRecIndex); + + kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + } else { + /* Cmd free count is larger than expected, but allocation fail. */ + u4Status = WLAN_STATUS_FAILURE; + + if (prMsduInfoHead->pfTxDoneHandler != NULL) { + prMsduInfoHead->pfTxDoneHandler(prAdapter, + prMsduInfoHead, + TX_RESULT_DROPPED_IN_DRIVER); + } + + 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 WLAN index +* +* @param prAdapter Pointer to the Adapter structure. +* +* @retval +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 nicTxGetWlanIdx(P_ADAPTER_T prAdapter, UINT_8 ucBssIdx, UINT_8 ucStaRecIdx) +{ + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prBssInfo; + UINT_8 ucWlanIndex = NIC_TX_DEFAULT_WLAN_INDEX; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIdx); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + + if (prStaRec) + ucWlanIndex = prStaRec->ucWlanIndex; + else if ((ucStaRecIdx == STA_REC_INDEX_BMCAST) && prBssInfo->fgIsInUse) + ucWlanIndex = prBssInfo->ucBMCWlanIndex; + + if (ucWlanIndex >= WTBL_SIZE) { + DBGLOG(TX, WARN, "%s: Unexpected WIDX[%hhu] BSS[%hhu] STA[%hhu], set WIDX to default value[%u]\n", + __func__, ucWlanIndex, ucBssIdx, ucStaRecIdx, NIC_TX_DEFAULT_WLAN_INDEX); + + ucWlanIndex = NIC_TX_DEFAULT_WLAN_INDEX; + } + + return ucWlanIndex; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* @param prAdapter Pointer to the Adapter structure. +* +* @retval +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN nicTxIsMgmtResourceEnough(IN P_ADAPTER_T prAdapter) +{ + if (nicTxGetFreeCmdCount(prAdapter) > (CFG_TX_MAX_CMD_PKT_NUM / 2)) + return TRUE; + else + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief this function returns page count of frame +* +* @param u4FrameLength frame length +* +* @retval page count of this frame +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 nicTxGetPageCount(IN UINT_32 u4FrameLength, IN BOOLEAN fgIncludeDesc) +{ + UINT_32 u4RequiredBufferSize; + UINT_8 ucPageCount; + + /* Frame Buffer + * |<--Tx Descriptor-->|<--Tx descriptor padding-->|<--802.3/802.11 Header-->| + * <--Header padding-->|<--Payload-->| + */ + + if (fgIncludeDesc) + u4RequiredBufferSize = u4FrameLength; + else + u4RequiredBufferSize = NIC_TX_DESC_LONG_FORMAT_LENGTH + NIC_TX_DESC_PADDING_LENGTH + u4FrameLength; + + if (NIC_TX_PAGE_SIZE_IS_POWER_OF_2) + ucPageCount = (UINT_8) ((u4RequiredBufferSize + (NIC_TX_PAGE_SIZE - 1)) >> + NIC_TX_PAGE_SIZE_IN_POWER_OF_2); + else + ucPageCount = (UINT_8) ((u4RequiredBufferSize + (NIC_TX_PAGE_SIZE - 1)) / NIC_TX_PAGE_SIZE); + + return ucPageCount; +} + +UINT_8 nicTxGetCmdPageCount(IN P_CMD_INFO_T prCmdInfo) +{ + UINT_8 ucPageCount; + + switch (prCmdInfo->eCmdType) { + case COMMAND_TYPE_NETWORK_IOCTL: + case COMMAND_TYPE_GENERAL_IOCTL: + ucPageCount = nicTxGetPageCount(prCmdInfo->u2InfoBufLen, TRUE); + break; + + case COMMAND_TYPE_SECURITY_FRAME: + case COMMAND_TYPE_MANAGEMENT_FRAME: + ucPageCount = nicTxGetPageCount(prCmdInfo->u2InfoBufLen, FALSE); + break; + + default: + DBGLOG(TX, WARN, "Undefined CMD Type(%u)\n", prCmdInfo->eCmdType); + ucPageCount = nicTxGetPageCount(prCmdInfo->u2InfoBufLen, FALSE); + break; + } + + return ucPageCount; +} + +VOID +nicTxSetMngPacket(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo, + UINT_8 ucBssIndex, UINT_8 ucStaRecIndex, UINT_8 ucMacHeaderLength, + UINT_16 u2FrameLength, PFN_TX_DONE_HANDLER pfTxDoneHandler, UINT_8 ucRateMode) +{ + static UINT_16 u2SwSN; + + ASSERT(prMsduInfo); + + prMsduInfo->ucBssIndex = ucBssIndex; + prMsduInfo->ucStaRecIndex = ucStaRecIndex; + prMsduInfo->ucMacHeaderLength = ucMacHeaderLength; + prMsduInfo->u2FrameLength = u2FrameLength; + prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; + prMsduInfo->ucRateMode = ucRateMode; + + /* Reset default value for MMPDU */ + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->u4FixedRateOption = 0; + prMsduInfo->cPowerOffset = 0; + prMsduInfo->u4Option = 0; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->ucPID = NIC_TX_DESC_PID_INVALID; + prMsduInfo->ucPacketType = TX_PACKET_TYPE_MGMT; + prMsduInfo->ucUserPriority = 0; + prMsduInfo->eSrc = TX_PACKET_MGMT; + u2SwSN++; + if (u2SwSN > 4095) + u2SwSN = 0; + nicTxSetPktSequenceNumber(prMsduInfo, u2SwSN); +} + +VOID +nicTxSetDataPacket(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo, + UINT_8 ucBssIndex, UINT_8 ucStaRecIndex, UINT_8 ucMacHeaderLength, + UINT_16 u2FrameLength, PFN_TX_DONE_HANDLER pfTxDoneHandler, + UINT_8 ucRateMode, ENUM_TX_PACKET_SRC_T eSrc, UINT_8 ucTID, + BOOLEAN fgIs802_11Frame, BOOLEAN fgIs1xFrame) +{ + ASSERT(prMsduInfo); + + prMsduInfo->ucBssIndex = ucBssIndex; + prMsduInfo->ucStaRecIndex = ucStaRecIndex; + prMsduInfo->ucMacHeaderLength = ucMacHeaderLength; + prMsduInfo->u2FrameLength = u2FrameLength; + prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; + prMsduInfo->ucRateMode = ucRateMode; + prMsduInfo->ucUserPriority = ucTID; + prMsduInfo->fgIs802_11 = fgIs802_11Frame; + prMsduInfo->eSrc = eSrc; + prMsduInfo->fgIs802_1x = fgIs1xFrame; + + /* Reset default value for data packet */ + prMsduInfo->u4FixedRateOption = 0; + prMsduInfo->cPowerOffset = 0; + prMsduInfo->u4Option = 0; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->ucPID = NIC_TX_DESC_PID_INVALID; + prMsduInfo->ucPacketType = TX_PACKET_TYPE_DATA; +} + +VOID nicTxFillDescByPktOption(P_MSDU_INFO_T prMsduInfo, P_HW_MAC_TX_DESC_T prTxDesc) +{ + UINT_32 u4PktOption = prMsduInfo->u4Option; + BOOLEAN fgIsLongFormat; + BOOLEAN fgProtected = FALSE; + + /* Skip this function if no options is set */ + if (!u4PktOption) + return; + + fgIsLongFormat = HAL_MAC_TX_DESC_IS_LONG_FORMAT(prTxDesc); + + /* Fields in DW0 and DW1 (Short Format) */ + if (u4PktOption & MSDU_OPT_NO_ACK) + HAL_MAC_TX_DESC_SET_NO_ACK(prTxDesc); + + if (u4PktOption & MSDU_OPT_PROTECTED_FRAME) { + HAL_MAC_TX_DESC_SET_PROTECTION(prTxDesc); + fgProtected = TRUE; + } + + switch (HAL_MAC_TX_DESC_GET_HEADER_FORMAT(prTxDesc)) { + case HEADER_FORMAT_802_11_ENHANCE_MODE: + if (u4PktOption & MSDU_OPT_EOSP) + HAL_MAC_TX_DESC_SET_EOSP(prTxDesc); + + if (u4PktOption & MSDU_OPT_AMSDU) + HAL_MAC_TX_DESC_SET_AMSDU(prTxDesc); + break; + + case HEADER_FORMAT_NON_802_11: + if (u4PktOption & MSDU_OPT_EOSP) + HAL_MAC_TX_DESC_SET_EOSP(prTxDesc); + + if (u4PktOption & MSDU_OPT_MORE_DATA) + HAL_MAC_TX_DESC_SET_MORE_DATA(prTxDesc); + + if (u4PktOption & MSDU_OPT_REMOVE_VLAN) + HAL_MAC_TX_DESC_SET_REMOVE_VLAN(prTxDesc); + break; + + case HEADER_FORMAT_802_11_NORMAL_MODE: + if (fgProtected && prMsduInfo->prPacket) { + P_WLAN_MAC_HEADER_T prWlanHeader = + (P_WLAN_MAC_HEADER_T) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prWlanHeader->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + } + break; + + default: + break; + } + + if (!fgIsLongFormat) + return; + + /* Fields in DW2~6 (Long Format) */ + if (u4PktOption & MSDU_OPT_NO_AGGREGATE) + HAL_MAC_TX_DESC_SET_BA_DISABLE(prTxDesc); + + if (u4PktOption & MSDU_OPT_TIMING_MEASURE) + HAL_MAC_TX_DESC_SET_TIMING_MEASUREMENT(prTxDesc); + + if (u4PktOption & MSDU_OPT_NDP) + HAL_MAC_TX_DESC_SET_NDP(prTxDesc); + + if (u4PktOption & MSDU_OPT_NDPA) + HAL_MAC_TX_DESC_SET_NDPA(prTxDesc); + + if (u4PktOption & MSDU_OPT_SOUNDING) + HAL_MAC_TX_DESC_SET_SOUNDING_FRAME(prTxDesc); + + if (u4PktOption & MSDU_OPT_FORCE_RTS) + HAL_MAC_TX_DESC_SET_FORCE_RTS_CTS(prTxDesc); + + if (u4PktOption & MSDU_OPT_BIP) + HAL_MAC_TX_DESC_SET_BIP(prTxDesc); + + /* SW field */ + if (u4PktOption & MSDU_OPT_SW_DURATION) + HAL_MAC_TX_DESC_SET_DURATION_CONTROL_BY_SW(prTxDesc); + + if (u4PktOption & MSDU_OPT_SW_PS_BIT) + HAL_MAC_TX_DESC_SET_SW_PM_CONTROL(prTxDesc); + + if (u4PktOption & MSDU_OPT_SW_HTC) + HAL_MAC_TX_DESC_SET_HTC_EXIST(prTxDesc); + + if (u4PktOption & MSDU_OPT_SW_BAR_SN) + HAL_MAC_TX_DESC_SET_SW_BAR_SSN(prTxDesc); + + if (u4PktOption & MSDU_OPT_MANUAL_SN) { + HAL_MAC_TX_DESC_SET_TXD_SN_VALID(prTxDesc); + HAL_MAC_TX_DESC_SET_SEQUENCE_NUMBER(prTxDesc, prMsduInfo->u2SwSN); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Extra configuration for Tx packet +* +* @retval +*/ +/*----------------------------------------------------------------------------*/ +VOID nicTxConfigPktOption(P_MSDU_INFO_T prMsduInfo, UINT_32 u4OptionMask, BOOLEAN fgSetOption) +{ + if (fgSetOption) + prMsduInfo->u4Option |= u4OptionMask; + else + prMsduInfo->u4Option &= ~u4OptionMask; +} + +VOID nicTxFillDescByPktControl(P_MSDU_INFO_T prMsduInfo, P_HW_MAC_TX_DESC_T prTxDesc) +{ + UINT_8 ucPktControl = prMsduInfo->ucControlFlag; + UINT_8 ucSwReserved; + + /* Skip this function if no options is set */ + if (!ucPktControl) + return; + + if (HAL_MAC_TX_DESC_IS_LONG_FORMAT(prTxDesc)) { + ucSwReserved = HAL_MAC_TX_DESC_GET_SW_RESERVED(prTxDesc); + + if (ucPktControl & MSDU_CONTROL_FLAG_FORCE_TX) + ucSwReserved |= MSDU_CONTROL_FLAG_FORCE_TX; + + HAL_MAC_TX_DESC_SET_SW_RESERVED(prTxDesc, ucSwReserved); + } +} + +VOID nicTxConfigPktControlFlag(P_MSDU_INFO_T prMsduInfo, UINT_8 ucControlFlagMask, BOOLEAN fgSetFlag) +{ + /* Set control flag */ + if (fgSetFlag) + prMsduInfo->ucControlFlag |= ucControlFlagMask; + else + prMsduInfo->ucControlFlag &= ~ucControlFlagMask; /* Clear control flag */ +} + +VOID nicTxSetPktLifeTime(P_MSDU_INFO_T prMsduInfo, UINT_32 u4TxLifeTimeInMs) +{ + prMsduInfo->u4RemainingLifetime = u4TxLifeTimeInMs; + prMsduInfo->u4Option |= MSDU_OPT_MANUAL_LIFE_TIME; +} + +VOID nicTxSetPktRetryLimit(P_MSDU_INFO_T prMsduInfo, UINT_8 ucRetryLimit) +{ + prMsduInfo->ucRetryLimit = ucRetryLimit; + prMsduInfo->u4Option |= MSDU_OPT_MANUAL_RETRY_LIMIT; +} + +VOID nicTxSetPktPowerOffset(P_MSDU_INFO_T prMsduInfo, INT_8 cPowerOffset) +{ + prMsduInfo->cPowerOffset = cPowerOffset; + prMsduInfo->u4Option |= MSDU_OPT_MANUAL_POWER_OFFSET; +} + +VOID nicTxSetPktSequenceNumber(P_MSDU_INFO_T prMsduInfo, UINT_16 u2SN) +{ + prMsduInfo->u2SwSN = u2SN; + prMsduInfo->u4Option |= MSDU_OPT_MANUAL_SN; +} + +VOID nicTxSetPktMacTxQue(P_MSDU_INFO_T prMsduInfo, UINT_8 ucMacTxQue) +{ + UINT_8 ucTcIdx; + + for (ucTcIdx = TC0_INDEX; ucTcIdx < TC_NUM; ucTcIdx++) { + if (arTcResourceControl[ucTcIdx].ucDestQueueIndex == ucMacTxQue) + break; + } + + if (ucTcIdx < TC_NUM) { + prMsduInfo->ucTC = ucTcIdx; + prMsduInfo->u4Option |= MSDU_OPT_MANUAL_TX_QUE; + } +} + +VOID +nicTxSetPktFixedRateOptionFull(P_MSDU_INFO_T prMsduInfo, + UINT_16 u2RateCode, + UINT_8 ucBandwidth, + BOOLEAN fgShortGI, + BOOLEAN fgLDPC, + BOOLEAN fgDynamicBwRts, + BOOLEAN fgSpatialExt, + BOOLEAN fgEtxBeamforming, + BOOLEAN fgItxBeamforming, UINT_8 ucAntennaIndex, UINT_8 ucAntennaPriority) +{ + HW_MAC_TX_DESC_T rTxDesc; + P_HW_MAC_TX_DESC_T prTxDesc = &rTxDesc; + + kalMemZero(prTxDesc, NIC_TX_DESC_LONG_FORMAT_LENGTH); + + /* Follow the format of Tx descriptor DW 6 */ + HAL_MAC_TX_DESC_SET_FR_RATE(prTxDesc, u2RateCode); + + if (ucBandwidth) + HAL_MAC_TX_DESC_SET_FR_BW(prTxDesc, ucBandwidth); + + if (fgShortGI) + HAL_MAC_TX_DESC_SET_FR_SHORT_GI(prTxDesc); + + if (fgLDPC) + HAL_MAC_TX_DESC_SET_FR_LDPC(prTxDesc); + + if (fgDynamicBwRts) + HAL_MAC_TX_DESC_SET_FR_DYNAMIC_BW_RTS(prTxDesc); + + if (fgSpatialExt) + HAL_MAC_TX_DESC_SET_FR_SPE_EN(prTxDesc); + + if (fgEtxBeamforming) + HAL_MAC_TX_DESC_SET_FR_ETX_BF(prTxDesc); + + if (fgItxBeamforming) + HAL_MAC_TX_DESC_SET_FR_ITX_BF(prTxDesc); + + HAL_MAC_TX_DESC_SET_FR_ANTENNA_ID(prTxDesc, ucAntennaIndex); + + HAL_MAC_TX_DESC_SET_FR_ANTENNA_PRIORITY(prTxDesc, ucAntennaPriority); + + /* Write back to RateOption of MSDU_INFO */ + HAL_MAC_TX_DESC_GET_DW(prTxDesc, 6, 1, &prMsduInfo->u4FixedRateOption); + +} + +VOID +nicTxSetPktFixedRateOption(P_MSDU_INFO_T prMsduInfo, + UINT_16 u2RateCode, UINT_8 ucBandwidth, BOOLEAN fgShortGI, BOOLEAN fgDynamicBwRts) +{ + HW_MAC_TX_DESC_T rTxDesc; + P_HW_MAC_TX_DESC_T prTxDesc = &rTxDesc; + + kalMemZero(prTxDesc, NIC_TX_DESC_LONG_FORMAT_LENGTH); + + /* Follow the format of Tx descriptor DW 6 */ + HAL_MAC_TX_DESC_SET_FR_RATE(prTxDesc, u2RateCode); + + if (ucBandwidth) + HAL_MAC_TX_DESC_SET_FR_BW(prTxDesc, ucBandwidth); + + if (fgShortGI) + HAL_MAC_TX_DESC_SET_FR_SHORT_GI(prTxDesc); + + if (fgDynamicBwRts) + HAL_MAC_TX_DESC_SET_FR_DYNAMIC_BW_RTS(prTxDesc); + + /* Write back to RateOption of MSDU_INFO */ + HAL_MAC_TX_DESC_GET_DW(prTxDesc, 6, 1, &prMsduInfo->u4FixedRateOption); +} + +VOID nicTxSetPktLowestFixedRate(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_BSS_INFO_T prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + P_STA_RECORD_T prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + UINT_8 ucRateSwIndex, ucRateIndex, ucRatePreamble; + UINT_16 u2RateCode, u2RateCodeLimit = 0, u2OperationalRateSet; + UINT_32 u4CurrentPhyRate, u4Status; + + prMsduInfo->fgIsTXDTemplateValid = FALSE; + prMsduInfo->ucRateMode = MSDU_RATE_MODE_MANUAL_DESC; + if (prStaRec) { + u2RateCode = prStaRec->u2HwDefaultFixedRateCode; + u2OperationalRateSet = prStaRec->u2OperationalRateSet; + } else { + u2RateCode = prBssInfo->u2HwDefaultFixedRateCode; + u2OperationalRateSet = prBssInfo->u2OperationalRateSet; + } + if (prBssInfo->u4CoexPhyRateLimit != 0) { + u4CurrentPhyRate = nicRateCode2PhyRate(u2RateCode, FIX_BW_NO_FIXED, MAC_GI_NORMAL, AR_SS_NULL); + if (prBssInfo->u4CoexPhyRateLimit > u4CurrentPhyRate) { + nicGetRateIndexFromRateSetWithLimit( + u2OperationalRateSet, + prBssInfo->u4CoexPhyRateLimit, TRUE, &ucRateSwIndex); + nicSwIndex2RateIndex(ucRateSwIndex, &ucRateIndex, &ucRatePreamble); + u4Status = nicRateIndex2RateCode(ucRatePreamble, ucRateIndex, &u2RateCodeLimit); + DBGLOG(NIC, INFO, + "Coex RatePreamble=%d, R_SW_IDX:%d, R_CODE:0x%x, R_CODE_LIMIT:0x%x, Status:0x%x\n", + ucRatePreamble, ucRateIndex, u2RateCode, u2RateCodeLimit, u4Status); + if (u4Status == WLAN_STATUS_SUCCESS) + u2RateCode = u2RateCodeLimit; + } + } + nicTxSetPktFixedRateOption(prMsduInfo, u2RateCode, FIX_BW_NO_FIXED, FALSE, FALSE); +} + +VOID nicTxSetPktMoreData(P_MSDU_INFO_T prCurrentMsduInfo, BOOLEAN fgSetMoreDataBit) +{ + P_WLAN_MAC_HEADER_T prWlanMacHeader = NULL; + + if (prCurrentMsduInfo->fgIs802_11) { + prWlanMacHeader = + (P_WLAN_MAC_HEADER_T) (((PUINT_8) (prCurrentMsduInfo->prPacket)) + MAC_TX_RESERVED_FIELD); + } + + if (fgSetMoreDataBit) { + if (!prCurrentMsduInfo->fgIs802_11) + prCurrentMsduInfo->u4Option |= MSDU_OPT_MORE_DATA; + else + prWlanMacHeader->u2FrameCtrl |= MASK_FC_MORE_DATA; + } else { + if (!prCurrentMsduInfo->fgIs802_11) + prCurrentMsduInfo->u4Option &= ~MSDU_OPT_MORE_DATA; + else + prWlanMacHeader->u2FrameCtrl &= ~MASK_FC_MORE_DATA; + } +} + +UINT_8 nicTxAssignPID(IN P_ADAPTER_T prAdapter, IN UINT_8 ucWlanIndex) +{ + UINT_8 ucRetval = 0; + UINT_8 ucZeroBits = 0; + PULONG pu8PidPool; + + /* Bit 7 represents data frame, don't assign PID directly */ + BOOLEAN fgCanAssign = !(ucWlanIndex & BIT(7)); + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ucWlanIndex &= ~BIT(7); + if (ucWlanIndex >= WTBL_SIZE) { + DBGLOG(TX, ERROR, "Wrong wlan index %d\n", ucWlanIndex); + return 0; + } + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + pu8PidPool = &prAdapter->au8PidPool[ucWlanIndex][0]; + if (!fgCanAssign) { + /* Because we always assign PID from the lowest one, if the highest reserved bits are not set, + ** means left PIDs are enough for data frame; otherwise, need to count left PID number in slow path. + ** The reserved number of PIDs is defined by CFG_TX_DONE_SLOTS_RESERVED_FOR_MGMT. + */ + if (pu8PidPool[NIC_TX_DESC_DRIVER_PID_MAX/__BITS_PER_LONG] + & BITS( + __BITS_PER_LONG - 1 - NIC_TX_DESC_PID_RESERVED_FOR_MGMT, + __BITS_PER_LONG - 1)) { + /* Slow path to count left number of PIDs */ + for (ucRetval = NIC_TX_DESC_DRIVER_PID_MIN; + ucRetval <= NIC_TX_DESC_DRIVER_PID_MAX && + ucZeroBits <= NIC_TX_DESC_PID_RESERVED_FOR_MGMT; ucRetval++) { + if (!test_bit(ucRetval, pu8PidPool)) + ucZeroBits++; + } + ucRetval = 0; + fgCanAssign = (ucZeroBits > NIC_TX_DESC_PID_RESERVED_FOR_MGMT); + DBGLOG(TX, TRACE, "Slow path to check can assign %d\n", fgCanAssign); + } else /* left PIDs are enough, assign directly */ + fgCanAssign = TRUE; + } + + if (fgCanAssign) { + ucRetval = find_next_zero_bit(pu8PidPool, NIC_TX_DESC_DRIVER_PID_MAX + 1, NIC_TX_DESC_DRIVER_PID_MIN); + if (ucRetval <= NIC_TX_DESC_DRIVER_PID_MAX) + set_bit(ucRetval, pu8PidPool); + else + ucRetval = 0; + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + return ucRetval; +} + +VOID nicTxSetPktEOSP(P_MSDU_INFO_T prCurrentMsduInfo, BOOLEAN fgSetEOSPBit) +{ + P_WLAN_MAC_HEADER_QOS_T prWlanMacHeader = NULL; + BOOLEAN fgWriteToDesc = TRUE; + + if (prCurrentMsduInfo->fgIs802_11) { + prWlanMacHeader = + (P_WLAN_MAC_HEADER_QOS_T) (((PUINT_8) (prCurrentMsduInfo->prPacket)) + MAC_TX_RESERVED_FIELD); + fgWriteToDesc = FALSE; + } + + if (fgSetEOSPBit) { + if (fgWriteToDesc) + prCurrentMsduInfo->u4Option |= MSDU_OPT_EOSP; + else + prWlanMacHeader->u2QosCtrl |= MASK_QC_EOSP; + } else { + if (fgWriteToDesc) + prCurrentMsduInfo->u4Option &= ~MSDU_OPT_EOSP; + else + prWlanMacHeader->u2QosCtrl &= ~MASK_QC_EOSP; + } +} + +WLAN_STATUS +nicTxDummyTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + DBGLOG(TX, TRACE, "Msdu WIDX:PID[%u:%u] SEQ[%u] Tx Status[%u]\n", + prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, prMsduInfo->ucTxSeqNum, rTxDoneStatus); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Update BSS Tx Params +* +* @param prStaRec The peer +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicTxUpdateBssDefaultRate(P_BSS_INFO_T prBssInfo) +{ + UINT_8 ucLowestBasicRateIndex; + + prBssInfo->u2HwDefaultFixedRateCode = RATE_OFDM_6M; + + /* 4 <1> Find Lowest Basic Rate Index for default TX Rate of MMPDU */ + if (rateGetLowestRateIndexFromRateSet(prBssInfo->u2BSSBasicRateSet, &ucLowestBasicRateIndex)) { + nicRateIndex2RateCode(PREAMBLE_DEFAULT_LONG_NONE, ucLowestBasicRateIndex, + &prBssInfo->u2HwDefaultFixedRateCode); + } else { + switch (prBssInfo->ucNonHTBasicPhyType) { + case PHY_TYPE_ERP_INDEX: + case PHY_TYPE_OFDM_INDEX: + prBssInfo->u2HwDefaultFixedRateCode = RATE_OFDM_6M; + break; + + default: + prBssInfo->u2HwDefaultFixedRateCode = RATE_CCK_1M_LONG; + break; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Update StaRec Tx parameters +* +* @param prStaRec The peer +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicTxUpdateStaRecDefaultRate(P_STA_RECORD_T prStaRec) +{ + UINT_8 ucLowestBasicRateIndex; + + prStaRec->u2HwDefaultFixedRateCode = RATE_OFDM_6M; + + /* 4 <1> Find Lowest Basic Rate Index for default TX Rate of MMPDU */ + if (rateGetLowestRateIndexFromRateSet(prStaRec->u2BSSBasicRateSet, &ucLowestBasicRateIndex)) { + nicRateIndex2RateCode(PREAMBLE_DEFAULT_LONG_NONE, + ucLowestBasicRateIndex, &prStaRec->u2HwDefaultFixedRateCode); + } else { + if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11B) + prStaRec->u2HwDefaultFixedRateCode = RATE_CCK_1M_LONG; + else if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11G) + prStaRec->u2HwDefaultFixedRateCode = RATE_OFDM_6M; + else if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11A) + prStaRec->u2HwDefaultFixedRateCode = RATE_OFDM_6M; + else if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11N) + prStaRec->u2HwDefaultFixedRateCode = RATE_MM_MCS_0; + } +} + +VOID nicTxChangeDataPortByAc(P_STA_RECORD_T prStaRec, UINT_8 ucAci, BOOLEAN fgToMcu) +{ + UINT_8 ucTid; + PVOID *pprTxDTemplate = NULL; + + if (!prStaRec) + return; + DBGLOG(TX, INFO, "Data Packets in Aci %d will route to %s\n", ucAci, fgToMcu ? "MCU":"LMAC"); + pprTxDTemplate = &prStaRec->aprTxDescTemplate[0]; + for (ucTid = 0; ucTid < TX_DESC_TID_NUM; ucTid++) { + if (aucTid2ACI[ucTid] != ucAci) + continue; + HAL_MAC_TX_DESC_SET_PORT_INDEX((P_HW_MAC_TX_DESC_T)pprTxDTemplate[ucTid], + fgToMcu ? PORT_INDEX_MCU:PORT_INDEX_LMAC); + } +} + +/* if some msdus are waiting tx done status, but now roaming done, then need to change +** wlan index of these msdus to match tx done status event +** In multi-thread solution, we also need to check if pending tx packets in hif_thread tx queue. +*/ +VOID nicTxHandleRoamingDone(P_ADAPTER_T prAdapter, P_STA_RECORD_T prOldStaRec, P_STA_RECORD_T prNewStaRec) +{ + P_MSDU_INFO_T prMsduInfo = NULL; + UINT_8 ucOldWlanIndex = prOldStaRec->ucWlanIndex; + UINT_8 ucNewWlanIndex = prNewStaRec->ucWlanIndex; + + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + prMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_HEAD(&prAdapter->rTxCtrl.rTxMgmtTxingQueue); + while (prMsduInfo) { + if (prMsduInfo->ucWlanIndex == ucOldWlanIndex) + prMsduInfo->ucWlanIndex = ucNewWlanIndex; + prMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY(&prMsduInfo->rQueEntry); + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + /* I think any time we disconnect with previous AP, rTxP0Queue and rTxP1Queue should be + ** empty. because we have stopped dequeue when initial to connect the new roaming AP. + ** It is enough time for hif_thread to send out these packets. But anyway, let's prepare code + ** for that case to avoid scheduler corner case. + */ +#if CFG_SUPPORT_MULTITHREAD + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + prMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_HEAD(&prAdapter->rTxP0Queue); + while (prMsduInfo) { + if (prMsduInfo->ucWlanIndex == ucOldWlanIndex) + prMsduInfo->ucWlanIndex = ucNewWlanIndex; + prMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY(&prMsduInfo->rQueEntry); + } + prMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_HEAD(&prAdapter->rTxP1Queue); + while (prMsduInfo) { + if (prMsduInfo->ucWlanIndex == ucOldWlanIndex) + prMsduInfo->ucWlanIndex = ucNewWlanIndex; + prMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY(&prMsduInfo->rQueEntry); + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); +#endif +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/p2p_nic.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/p2p_nic.c new file mode 100644 index 0000000000000..dc2d98ac044fc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/p2p_nic.c @@ -0,0 +1,201 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: @(#) p2p_nic.c@@ +*/ + +/* + * ! \file p2p_nic.c + * \brief Wi-Fi Direct Functions that provide operation in NIC's (Network Interface Card) point of view. + * + * This file includes functions which unite multiple hal(Hardware) operations + * and also take the responsibility of Software Resource Management in order + * to keep the synchronization with Hardware Manipulation. + */ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief When Probe Rsp & Beacon frame is received and decide a P2P device, +* this function will be invoked to buffer scan result +* +* @param prAdapter Pointer to the Adapter structure. +* @param prEventScanResult Pointer of EVENT_SCAN_RESULT_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxAddP2pDevice(IN P_ADAPTER_T prAdapter, + IN P_EVENT_P2P_DEV_DISCOVER_RESULT_T prP2pResult, IN PUINT_8 pucRxIEBuf, IN UINT_16 u2RxIELength) +{ + P_P2P_INFO_T prP2pInfo = (P_P2P_INFO_T) NULL; + P_EVENT_P2P_DEV_DISCOVER_RESULT_T prTargetResult = (P_EVENT_P2P_DEV_DISCOVER_RESULT_T) NULL; + UINT_32 u4Idx = 0; + BOOLEAN bUpdate = FALSE; + + PUINT_8 pucIeBuf = (PUINT_8) NULL; + UINT_16 u2IELength = 0; + UINT_8 zeroMac[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; + + ASSERT(prAdapter); + + prP2pInfo = prAdapter->prP2pInfo; + + for (u4Idx = 0; u4Idx < prP2pInfo->u4DeviceNum; u4Idx++) { + prTargetResult = &prP2pInfo->arP2pDiscoverResult[u4Idx]; + + if (EQUAL_MAC_ADDR(prTargetResult->aucDeviceAddr, prP2pResult->aucDeviceAddr)) { + bUpdate = TRUE; + + /* Backup OLD buffer result. */ + pucIeBuf = prTargetResult->pucIeBuf; + u2IELength = prTargetResult->u2IELength; + + /* Update Device Info. */ + /* zero */ + kalMemZero(prTargetResult, sizeof(EVENT_P2P_DEV_DISCOVER_RESULT_T)); + + /* then buffer */ + kalMemCopy(prTargetResult, (PVOID) prP2pResult, sizeof(EVENT_P2P_DEV_DISCOVER_RESULT_T)); + + /* See if new IE length is longer or not. */ + if ((u2RxIELength > u2IELength) && (u2IELength != 0)) { + /* Buffer is not enough. */ + u2RxIELength = u2IELength; + } else if ((u2IELength == 0) && (u2RxIELength != 0)) { + /* RX new IE buf. */ + ASSERT(pucIeBuf == NULL); + pucIeBuf = prP2pInfo->pucCurrIePtr; + + if (((ULONG) prP2pInfo->pucCurrIePtr + (ULONG) u2RxIELength) > + (ULONG)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN]) { + /* Common Buffer is no enough. */ + u2RxIELength = + (UINT_16) ((ULONG)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN] - + (ULONG) prP2pInfo->pucCurrIePtr); + } + + /* Step to next buffer address. */ + prP2pInfo->pucCurrIePtr = + (PUINT_8) ((ULONG) prP2pInfo->pucCurrIePtr + (ULONG) u2RxIELength); + } + + /* Restore buffer pointer. */ + prTargetResult->pucIeBuf = pucIeBuf; + + if (pucRxIEBuf) { + /* If new received IE is available. + * Replace the old one & update new IE length. + */ + kalMemCopy(pucIeBuf, pucRxIEBuf, u2RxIELength); + prTargetResult->u2IELength = u2RxIELength; + } else { + /* There is no new IE information, keep the old one. */ + prTargetResult->u2IELength = u2IELength; + } + } + } + + if (!bUpdate) { + /* We would flush the whole scan result after each scan request is issued. + * If P2P device is too many, it may over the scan list. + */ + if ((u4Idx < CFG_MAX_NUM_BSS_LIST) && (UNEQUAL_MAC_ADDR(zeroMac, prP2pResult->aucDeviceAddr))) { + 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)); + + if (u2RxIELength) { + prTargetResult->pucIeBuf = prP2pInfo->pucCurrIePtr; + + if (((ULONG) prP2pInfo->pucCurrIePtr + (ULONG) u2RxIELength) > + (ULONG)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN]) { + /* Common Buffer is no enough. */ + u2IELength = + (UINT_16) ((ULONG)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN] - + (ULONG) prP2pInfo->pucCurrIePtr); + } else { + u2IELength = u2RxIELength; + } + + prP2pInfo->pucCurrIePtr = + (PUINT_8) ((ULONG) prP2pInfo->pucCurrIePtr + (ULONG) u2IELength); + + kalMemCopy((PVOID) prTargetResult->pucIeBuf, (PVOID) pucRxIEBuf, (UINT_32) u2IELength); + prTargetResult->u2IELength = u2IELength; + } else { + prTargetResult->pucIeBuf = NULL; + prTargetResult->u2IELength = 0; + } + + prP2pInfo->u4DeviceNum++; + + } else { + /* TODO: Fixme to replace an old one. (?) */ + ASSERT(FALSE); + } + } +} /* nicRxAddP2pDevice */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/que_mgt.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/que_mgt.c new file mode 100644 index 0000000000000..5fd467d01e178 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/que_mgt.c @@ -0,0 +1,6660 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/que_mgt.c#3 +*/ + +/* + * ! \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. + */ + +/******************************************************************************* +* C O M P I L E 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 "queue.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]; + +const UINT_8 aucTid2ACI[TX_DESC_TID_NUM] = { + WMM_AC_BE_INDEX, /* TID0 */ + WMM_AC_BK_INDEX, /* TID1 */ + WMM_AC_BK_INDEX, /* TID2 */ + WMM_AC_BE_INDEX, /* TID3 */ + WMM_AC_VI_INDEX, /* TID4 */ + WMM_AC_VI_INDEX, /* TID5 */ + WMM_AC_VO_INDEX, /* TID6 */ + WMM_AC_VO_INDEX /* TID7 */ +}; + +const UINT_8 aucACI2TxQIdx[WMM_AC_INDEX_NUM] = { + TX_QUEUE_INDEX_AC1, /* WMM_AC_BE_INDEX */ + TX_QUEUE_INDEX_AC0, /* WMM_AC_BK_INDEX */ + TX_QUEUE_INDEX_AC2, /* WMM_AC_VI_INDEX */ + TX_QUEUE_INDEX_AC3 /* WMM_AC_VO_INDEX */ +}; + +const UINT_8 arNetwork2TcResource[HW_BSSID_NUM + 1][NET_TC_NUM] = { + /* HW Queue Set 1 */ + /* AC_BE, AC_BK, AC_VI, AC_VO, MGMT, non-StaRec/non-QoS/BMC */ + {TC1_INDEX, TC0_INDEX, TC2_INDEX, TC3_INDEX, TC4_INDEX, TC5_INDEX}, /* AIS */ + {TC1_INDEX, TC0_INDEX, TC2_INDEX, TC3_INDEX, TC4_INDEX, TC5_INDEX}, /* P2P/BoW */ + {TC1_INDEX, TC0_INDEX, TC2_INDEX, TC3_INDEX, TC4_INDEX, TC5_INDEX}, /* P2P/BoW */ + {TC1_INDEX, TC0_INDEX, TC2_INDEX, TC3_INDEX, TC4_INDEX, TC5_INDEX}, /* P2P/BoW */ + {TC1_INDEX, TC0_INDEX, TC2_INDEX, TC3_INDEX, TC4_INDEX, TC5_INDEX}, /* P2P_DEV */ + + /* HW Queue Set 2 */ + /* {TC7_INDEX, TC6_INDEX, TC8_INDEX, TC9_INDEX, TC4_INDEX, TC10_INDEX}, */ +}; + +const UINT_8 aucWmmAC2TcResourceSet1[WMM_AC_INDEX_NUM] = { + TC1_INDEX, + TC0_INDEX, + TC2_INDEX, + TC3_INDEX +}; + +#if NIC_TX_ENABLE_SECOND_HW_QUEUE +const UINT_8 aucWmmAC2TcResourceSet2[WMM_AC_INDEX_NUM] = { + TC7_INDEX, + TC6_INDEX, + TC8_INDEX, + TC9_INDEX +}; +#endif +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if ARP_MONITER_ENABLE +static UINT_16 arpMoniter; +static UINT_8 apIp[4]; +static UINT_8 gatewayIp[4]; +#endif + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#if CFG_RX_REORDERING_ENABLED +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR +#define qmHandleRxPackets_AOSP_1 \ +do { \ + /* ToDo[6630]: duplicate removal */ \ + if (!fgIsBMC && nicRxIsDuplicateFrame(prCurrSwRfb) == TRUE) { \ + DBGLOG(QM, TRACE, "Duplicated packet is detected\n");\ + RX_INC_CNT(&prAdapter->rRxCtrl, RX_DUPICATE_DROP_COUNT);\ + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; \ + } \ + /* ToDo[6630]: defragmentation */ \ + if (prCurrSwRfb->fgFragFrame) { \ + prCurrSwRfb = nicRxDefragMPDU(prAdapter, prCurrSwRfb, prReturnedQue); \ + if (prCurrSwRfb) { \ + prRxStatus = prCurrSwRfb->prRxStatus; \ + DBGLOG(QM, TRACE, "defragmentation RxStatus=%p\n", prRxStatus); \ + } \ + } \ + if (prCurrSwRfb) { \ + fgMicErr = FALSE; \ + if (HAL_RX_STATUS_GET_SEC_MODE(prRxStatus) == CIPHER_SUITE_TKIP_WO_MIC) { \ + if (prCurrSwRfb->prStaRec) { \ + UINT_8 ucBssIndex; \ + P_BSS_INFO_T prBssInfo = NULL; \ + PUINT_8 pucMicKey = NULL; \ + ucBssIndex = prCurrSwRfb->prStaRec->ucBssIndex; \ + ASSERT(ucBssIndex < BSS_INFO_NUM); \ + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); \ + ASSERT(prBssInfo); \ + if (prBssInfo && prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { \ + pucMicKey = &(prAdapter->rWifiVar.rAisSpecificBssInfo.aucRxMicKey[0]); \ + } \ + else { \ + ASSERT(FALSE); \ + /* pucMicKey = &prCurrSwRfb->prStaRec->aucRxMicKey[0]; */ \ + } \ + /* SW TKIP MIC verify */ \ + /* TODO:[6630] Need to Check Header Translation Case */ \ + if (pucMicKey == NULL) { \ + DBGLOG(RX, ERROR, "No TKIP Mic Key\n"); \ + fgMicErr = TRUE; \ + } \ + else if (tkipMicDecapsulate(prCurrSwRfb, pucMicKey) == FALSE) { \ + fgMicErr = TRUE; \ + } \ + } \ + if (fgMicErr) { \ + DBGLOG(RX, ERROR, "Mark NULL the Packet for TKIP Mic Error\n"); \ + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; \ + } \ + } \ + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T)prCurrSwRfb); \ + } \ +} while (0) +#else +#define qmHandleRxPackets_AOSP_1 \ +do { \ + /* ToDo[6630]: duplicate removal */ \ + if (!fgIsBMC && nicRxIsDuplicateFrame(prCurrSwRfb) == TRUE) { \ + DBGLOG(QM, TRACE, "Duplicated packet is detected\n");\ + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; \ + } \ + /* ToDo[6630]: defragmentation */ \ + if (prCurrSwRfb->fgFragFrame) { \ + prCurrSwRfb = nicRxDefragMPDU(prAdapter, prCurrSwRfb, prReturnedQue); \ + if (prCurrSwRfb) { \ + prRxStatus = prCurrSwRfb->prRxStatus; \ + DBGLOG(QM, TRACE, "defragmentation RxStatus=%p\n", prRxStatus); \ + } \ + } \ + if (prCurrSwRfb) { \ + fgMicErr = FALSE; \ + if (HAL_RX_STATUS_GET_SEC_MODE(prRxStatus) == CIPHER_SUITE_TKIP_WO_MIC) { \ + if (prCurrSwRfb->prStaRec) { \ + UINT_8 ucBssIndex; \ + P_BSS_INFO_T prBssInfo = NULL; \ + PUINT_8 pucMicKey = NULL; \ + ucBssIndex = prCurrSwRfb->prStaRec->ucBssIndex; \ + ASSERT(ucBssIndex < BSS_INFO_NUM); \ + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); \ + ASSERT(prBssInfo); \ + if (prBssInfo && prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { \ + pucMicKey = &(prAdapter->rWifiVar.rAisSpecificBssInfo.aucRxMicKey[0]); \ + } \ + else { \ + ASSERT(FALSE); \ + /* pucMicKey = &prCurrSwRfb->prStaRec->aucRxMicKey[0]; */ \ + } \ + /* SW TKIP MIC verify */ \ + /* TODO:[6630] Need to Check Header Translation Case */ \ + if (pucMicKey == NULL) { \ + DBGLOG(RX, ERROR, "No TKIP Mic Key\n"); \ + fgMicErr = TRUE; \ + } \ + else if (tkipMicDecapsulate(prCurrSwRfb, pucMicKey) == FALSE) { \ + fgMicErr = TRUE; \ + } \ + } \ + if (fgMicErr) { \ + DBGLOG(RX, ERROR, "Mark NULL the Packet for TKIP Mic Error\n"); \ + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; \ + } \ + } \ + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T)prCurrSwRfb); \ + } \ +} while (0) +#endif +#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 Init Queue Management for TX +* +* \param[in] (none) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmInit(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4Idx; +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + UINT_32 u4TotalMinReservedTcResource = 0; + UINT_32 u4TotalTcResource = 0; + UINT_32 u4TotalGurantedTcResource = 0; +#endif + + P_QUE_MGT_T prQM = &prAdapter->rQM; + + /* DbgPrint("QM: Enter qmInit()\n"); */ + + /* 4 <2> Initialize other TX queues (queues not in STA_RECs) */ + for (u4Idx = 0; u4Idx < NUM_OF_PER_TYPE_TX_QUEUES; u4Idx++) + QUEUE_INITIALIZE(&(prQM->arTxQueue[u4Idx])); + + /* 4 <3> Initialize the RX BA table and RX queues */ + /* Initialize the RX Reordering Parameters and Queues */ + for (u4Idx = 0; u4Idx < CFG_NUM_OF_RX_BA_AGREEMENTS; u4Idx++) { + prQM->arRxBaTable[u4Idx].fgIsValid = FALSE; + QUEUE_INITIALIZE(&(prQM->arRxBaTable[u4Idx].rReOrderQue)); +#if CFG_RX_BA_REORDERING_ENHANCEMENT + QUEUE_INITIALIZE(&(prQM->arRxBaTable[u4Idx].rNoNeedWaitQue)); +#endif + prQM->arRxBaTable[u4Idx].u2WinStart = 0xFFFF; + prQM->arRxBaTable[u4Idx].u2WinEnd = 0xFFFF; + + prQM->arRxBaTable[u4Idx].fgIsWaitingForPktWithSsn = FALSE; + prQM->arRxBaTable[u4Idx].fgHasBubble = FALSE; + + cnmTimerInitTimer(prAdapter, + &(prQM->arRxBaTable[u4Idx].rReorderBubbleTimer), + (PFN_MGMT_TIMEOUT_FUNC) qmHandleReorderBubbleTimeout, + (ULONG) (&prQM->arRxBaTable[u4Idx])); + + } + prQM->ucRxBaCount = 0; + + kalMemSet(&g_arMissTimeout, 0, sizeof(g_arMissTimeout)); + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + /* 4 <4> Initialize TC resource control variables */ + for (u4Idx = 0; u4Idx < TC_NUM; u4Idx++) + prQM->au4AverageQueLen[u4Idx] = 0; + + ASSERT(prQM->u4TimeToAdjustTcResource && prQM->u4TimeToUpdateQueLen); + + for (u4Idx = 0; u4Idx < TC_NUM; u4Idx++) { + prQM->au4CurrentTcResource[u4Idx] = prAdapter->rTxCtrl.rTc.au2MaxNumOfBuffer[u4Idx]; + + if (u4Idx != TC4_INDEX) { + u4TotalTcResource += prQM->au4CurrentTcResource[u4Idx]; + u4TotalGurantedTcResource += prQM->au4GuaranteedTcResource[u4Idx]; + u4TotalMinReservedTcResource += prQM->au4MinReservedTcResource[u4Idx]; + } + } + + /* Sanity Check */ + if (u4TotalMinReservedTcResource > u4TotalTcResource) + kalMemZero(prQM->au4MinReservedTcResource, sizeof(prQM->au4MinReservedTcResource)); + + if (u4TotalGurantedTcResource > u4TotalTcResource) + kalMemZero(prQM->au4GuaranteedTcResource, sizeof(prQM->au4GuaranteedTcResource)); + + u4TotalGurantedTcResource = 0; + + /* Initialize Residual TC resource */ + for (u4Idx = 0; u4Idx < TC_NUM; u4Idx++) { + if (prQM->au4GuaranteedTcResource[u4Idx] < prQM->au4MinReservedTcResource[u4Idx]) + prQM->au4GuaranteedTcResource[u4Idx] = prQM->au4MinReservedTcResource[u4Idx]; + + if (u4Idx != TC4_INDEX) + u4TotalGurantedTcResource += prQM->au4GuaranteedTcResource[u4Idx]; + } + + prQM->u4ResidualTcResource = u4TotalTcResource - u4TotalGurantedTcResource; + + prQM->fgTcResourcePostAnnealing = FALSE; + +#if QM_FAST_TC_RESOURCE_CTRL + prQM->fgTcResourceFastReaction = FALSE; +#endif + +#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->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + COPY_MAC_ADDR((prStaRec)->aucMacAddr, aucMacAddr); + + } + +#endif + +#endif + +#if QM_FORWARDING_FAIRNESS + for (u4Idx = 0; u4Idx < NUM_OF_PER_STA_TX_QUEUES; u4Idx++) { + prQM->au4ResourceUsedCount[u4Idx] = 0; + prQM->au4HeadStaRecIndex[u4Idx] = 0; + } + + prQM->u4GlobalResourceUsedCount = 0; +#endif + + prQM->u4TxAllowedStaCount = 0; + + prQM->rLastTxPktDumpTime = (OS_SYSTIME) kalGetTimeTick(); + +} + +#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, &prAdapter->arStaRec[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 Update a STA_REC +* +* \param[in] prAdapter Pointer to the Adapter instance +* \param[in] prStaRec The pointer of the STA_REC +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmUpdateStaRec(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + P_BSS_INFO_T prBssInfo; + BOOLEAN fgIsTxAllowed = FALSE; + + if (!prStaRec) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + /* 4 <1> Ensure STA is valid */ + if (prStaRec->fgIsValid) { + /* 4 <2.1> STA/BSS is protected */ + if (secIsProtectedBss(prAdapter, prBssInfo)) { + if (prStaRec->fgIsTxKeyReady) + fgIsTxAllowed = TRUE; + } + /* 4 <2.2> OPEN security */ + else + fgIsTxAllowed = TRUE; + } + /* 4 Update StaRec */ + if (prStaRec->fgIsTxAllowed != fgIsTxAllowed) { + if (fgIsTxAllowed) + prAdapter->rQM.u4TxAllowedStaCount++; + else + prAdapter->rQM.u4TxAllowedStaCount--; + } + + prStaRec->fgIsTxAllowed = fgIsTxAllowed; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Activate a STA_REC +* +* \param[in] prAdapter Pointer to the Adapter instance +* \param[in] prStaRec The pointer of the STA_REC +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmActivateStaRec(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + /* 4 <1> Deactivate first */ + if (!prStaRec) + return; + + 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); /* To flush TX/RX queues and del RX BA agreements */ + } + /* 4 <2> Activate the STA_REC */ + /* Reset buffer count */ + prStaRec->ucFreeQuota = 0; + prStaRec->ucFreeQuotaForDelivery = 0; + prStaRec->ucFreeQuotaForNonDelivery = 0; + + /* Init the STA_REC */ + prStaRec->fgIsValid = TRUE; + prStaRec->fgIsInPS = FALSE; + + /* Default setting of TX/RX AMPDU */ + prStaRec->fgTxAmpduEn = IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucAmpduTx); + prStaRec->fgRxAmpduEn = IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucAmpduRx); + + nicTxGenerateDescTemplate(prAdapter, prStaRec); + + qmUpdateStaRec(prAdapter, prStaRec); + + /* Done in qmInit() or qmDeactivateStaRec() */ +#if 0 + /* At the beginning, no RX BA agreements have been established */ + for (i = 0; i < CFG_RX_MAX_BA_TID_NUM; i++) + (prStaRec->aprRxReorderParamRefTbl)[i] = NULL; +#endif + + DBGLOG(QM, TRACE, "QM: +STA[%d]\n", (UINT_32) prStaRec->ucIndex); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Deactivate a STA_REC +* +* \param[in] prAdapter Pointer to the Adapter instance +* \param[in] u4StaRecIdx The index of the STA_REC +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmDeactivateStaRec(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + UINT_32 i; + P_MSDU_INFO_T prFlushedTxPacketList = NULL; + + if (!prStaRec) + return; + /* 4 <1> Flush TX queues */ + prFlushedTxPacketList = qmFlushStaTxQueues(prAdapter, prStaRec->ucIndex); + + 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, prStaRec->ucIndex, (UINT_8) i, FALSE); + } + + /* 4 <3> Deactivate the STA_REC */ + prStaRec->fgIsValid = FALSE; + prStaRec->fgIsInPS = FALSE; + prStaRec->fgIsTxKeyReady = FALSE; + + /* Reset buffer count */ + prStaRec->ucFreeQuota = 0; + prStaRec->ucFreeQuotaForDelivery = 0; + prStaRec->ucFreeQuotaForNonDelivery = 0; + + nicTxFreeDescTemplate(prAdapter, prStaRec); + + qmUpdateStaRec(prAdapter, prStaRec); + + DBGLOG(QM, TRACE, "QM: -STA[%u]\n", prStaRec->ucIndex); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Deactivate a STA_REC +* +* \param[in] prAdapter Pointer to the Adapter instance +* \param[in] ucBssIndex The index of the BSS +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmFreeAllByBssIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex) +{ + + 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->ucBssIndex == ucBssIndex) { + /* QUEUE_INSERT_TAIL */ + QUEUE_INSERT_TAIL(prNeedToFreeQue, (P_QUE_ENTRY_T) prMsduInfo); + } else { + /* QUEUE_INSERT_TAIL */ + QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prMsduInfo); + } + + QUEUE_REMOVE_HEAD(prTempQue, prMsduInfo, P_MSDU_INFO_T); + } + if (QUEUE_IS_NOT_EMPTY(prNeedToFreeQue)) + wlanProcessQueuedMsduInfo(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(prNeedToFreeQue)); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Flush all TX queues +* +* \param[in] (none) +* +* \return The flushed packets (in a list of MSDU_INFOs) +*/ +/*----------------------------------------------------------------------------*/ +P_MSDU_INFO_T qmFlushTxQueues(IN P_ADAPTER_T prAdapter) +{ + UINT_8 ucStaArrayIdx; + UINT_8 ucQueArrayIdx; + + P_MSDU_INFO_T prMsduInfoListHead; + P_MSDU_INFO_T prMsduInfoListTail; + + P_QUE_MGT_T prQM = &prAdapter->rQM; + + DBGLOG(QM, TRACE, "QM: Enter qmFlushTxQueues()\n"); + + prMsduInfoListHead = NULL; + prMsduInfoListTail = NULL; + + /* Concatenate all MSDU_INFOs in per-STA queues */ + for (ucStaArrayIdx = 0; ucStaArrayIdx < CFG_NUM_OF_STA_RECORD; ucStaArrayIdx++) { + + /* Always check each STA_REC when flushing packets no matter it is inactive or active */ +#if 0 + if (!prAdapter->arStaRec[ucStaArrayIdx].fgIsValid) + continue; /* Continue to check the next STA_REC */ +#endif + + for (ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_STA_TX_QUEUES; ucQueArrayIdx++) { + if (QUEUE_IS_EMPTY(&(prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]))) + continue; /* Continue to check the next TX queue of the same STA */ + + if (!prMsduInfoListHead) { + + /* The first MSDU_INFO is found */ + prMsduInfoListHead = (P_MSDU_INFO_T) + QUEUE_GET_HEAD(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]); + prMsduInfoListTail = (P_MSDU_INFO_T) + QUEUE_GET_TAIL(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]); + } else { + /* Concatenate the MSDU_INFO list with the existing list */ + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, + QUEUE_GET_HEAD(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue + [ucQueArrayIdx])); + + prMsduInfoListTail = (P_MSDU_INFO_T) + QUEUE_GET_TAIL(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]); + } + + QUEUE_INITIALIZE(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]); + } + } + + /* Flush per-Type queues */ + for (ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_TYPE_TX_QUEUES; ucQueArrayIdx++) { + + if (QUEUE_IS_EMPTY(&(prQM->arTxQueue[ucQueArrayIdx]))) + continue; /* Continue to check the next TX queue of the same STA */ + + if (!prMsduInfoListHead) { + + /* The first MSDU_INFO is found */ + prMsduInfoListHead = (P_MSDU_INFO_T) + QUEUE_GET_HEAD(&prQM->arTxQueue[ucQueArrayIdx]); + prMsduInfoListTail = (P_MSDU_INFO_T) + QUEUE_GET_TAIL(&prQM->arTxQueue[ucQueArrayIdx]); + } else { + /* Concatenate the MSDU_INFO list with the existing list */ + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, QUEUE_GET_HEAD(&prQM->arTxQueue[ucQueArrayIdx])); + + prMsduInfoListTail = (P_MSDU_INFO_T) + QUEUE_GET_TAIL(&prQM->arTxQueue[ucQueArrayIdx]); + } + + QUEUE_INITIALIZE(&prQM->arTxQueue[ucQueArrayIdx]); + + } + + if (prMsduInfoListTail) { + /* Terminate the MSDU_INFO list with a NULL pointer */ + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, NULL); + } + + return prMsduInfoListHead; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Flush TX packets for a particular STA +* +* \param[in] u4StaRecIdx STA_REC index +* +* \return The flushed packets (in a list of MSDU_INFOs) +*/ +/*----------------------------------------------------------------------------*/ +P_MSDU_INFO_T qmFlushStaTxQueues(IN P_ADAPTER_T prAdapter, IN UINT_32 u4StaRecIdx) +{ + UINT_8 ucQueArrayIdx; + P_MSDU_INFO_T prMsduInfoListHead; + P_MSDU_INFO_T prMsduInfoListTail; + P_STA_RECORD_T prStaRec; + + DBGLOG(QM, TRACE, "QM: Enter qmFlushStaTxQueues(%d)\n", u4StaRecIdx); + + ASSERT(u4StaRecIdx < CFG_NUM_OF_STA_RECORD); + + prMsduInfoListHead = NULL; + prMsduInfoListTail = NULL; + + prStaRec = &prAdapter->arStaRec[u4StaRecIdx]; + ASSERT(prStaRec); + + /* No matter whether this is an activated STA_REC, do flush */ +#if 0 + if (!prStaRec->fgIsValid) + return NULL; +#endif + + /* Concatenate all MSDU_INFOs in TX queues of this STA_REC */ + for (ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_STA_TX_QUEUES; ucQueArrayIdx++) { + if (QUEUE_IS_EMPTY(&(prStaRec->arTxQueue[ucQueArrayIdx]))) + continue; + + if (!prMsduInfoListHead) { + /* The first MSDU_INFO is found */ + prMsduInfoListHead = (P_MSDU_INFO_T) + QUEUE_GET_HEAD(&prStaRec->arTxQueue[ucQueArrayIdx]); + prMsduInfoListTail = (P_MSDU_INFO_T) + QUEUE_GET_TAIL(&prStaRec->arTxQueue[ucQueArrayIdx]); + } else { + /* Concatenate the MSDU_INFO list with the existing list */ + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, + QUEUE_GET_HEAD(&prStaRec->arTxQueue[ucQueArrayIdx])); + + prMsduInfoListTail = (P_MSDU_INFO_T) QUEUE_GET_TAIL(&prStaRec->arTxQueue[ucQueArrayIdx]); + } + + QUEUE_INITIALIZE(&prStaRec->arTxQueue[ucQueArrayIdx]); + + } + +#if 0 + if (prMsduInfoListTail) { + /* Terminate the MSDU_INFO list with a NULL pointer */ + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, nicGetPendingStaMMPDU(prAdapter, (UINT_8) u4StaRecIdx)); + } else { + prMsduInfoListHead = nicGetPendingStaMMPDU(prAdapter, (UINT_8) u4StaRecIdx); + } +#endif + + return prMsduInfoListHead; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Flush RX packets +* +* \param[in] (none) +* +* \return The flushed packets (in a list of SW_RFBs) +*/ +/*----------------------------------------------------------------------------*/ +P_SW_RFB_T qmFlushRxQueues(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i; + P_SW_RFB_T prSwRfbListHead; + P_SW_RFB_T prSwRfbListTail; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + prSwRfbListHead = prSwRfbListTail = NULL; + + DBGLOG(QM, TRACE, "QM: Enter qmFlushRxQueues()\n"); + + for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) { + if (QUEUE_IS_NOT_EMPTY(&(prQM->arRxBaTable[i].rReOrderQue))) { + if (!prSwRfbListHead) { + + /* The first MSDU_INFO is found */ + prSwRfbListHead = (P_SW_RFB_T) + QUEUE_GET_HEAD(&(prQM->arRxBaTable[i].rReOrderQue)); + prSwRfbListTail = (P_SW_RFB_T) + QUEUE_GET_TAIL(&(prQM->arRxBaTable[i].rReOrderQue)); + } else { + /* Concatenate the MSDU_INFO list with the existing list */ + QM_TX_SET_NEXT_MSDU_INFO(prSwRfbListTail, + QUEUE_GET_HEAD(&(prQM->arRxBaTable[i].rReOrderQue))); + + prSwRfbListTail = (P_SW_RFB_T) + QUEUE_GET_TAIL(&(prQM->arRxBaTable[i].rReOrderQue)); + } + + QUEUE_INITIALIZE(&(prQM->arRxBaTable[i].rReOrderQue)); + + } else { + continue; + } + } + + if (prSwRfbListTail) { + /* Terminate the MSDU_INFO list with a NULL pointer */ + QM_TX_SET_NEXT_SW_RFB(prSwRfbListTail, NULL); + } + return prSwRfbListHead; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Flush RX packets with respect to a particular STA +* +* \param[in] u4StaRecIdx STA_REC index +* \param[in] u4Tid TID +* +* \return The flushed packets (in a list of SW_RFBs) +*/ +/*----------------------------------------------------------------------------*/ +P_SW_RFB_T qmFlushStaRxQueue(IN P_ADAPTER_T prAdapter, IN UINT_32 u4StaRecIdx, IN UINT_32 u4Tid) +{ + /* UINT_32 i; */ + P_SW_RFB_T prSwRfbListHead; + P_SW_RFB_T prSwRfbListTail; + P_RX_BA_ENTRY_T prReorderQueParm; + P_STA_RECORD_T prStaRec; + + DBGLOG(QM, TRACE, "QM: Enter qmFlushStaRxQueues(%u)\n", u4StaRecIdx); + + prSwRfbListHead = prSwRfbListTail = NULL; + + prStaRec = &prAdapter->arStaRec[u4StaRecIdx]; + ASSERT(prStaRec); + + /* No matter whether this is an activated STA_REC, do flush */ +#if 0 + if (!prStaRec->fgIsValid) + return NULL; +#endif + + /* Obtain the RX BA Entry pointer */ + prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[u4Tid]); + + /* Note: For each queued packet, prCurrSwRfb->eDst equals RX_PKT_DESTINATION_HOST */ + if (prReorderQueParm) { + + if (QUEUE_IS_NOT_EMPTY(&(prReorderQueParm->rReOrderQue))) { + + prSwRfbListHead = (P_SW_RFB_T) + QUEUE_GET_HEAD(&(prReorderQueParm->rReOrderQue)); + prSwRfbListTail = (P_SW_RFB_T) + QUEUE_GET_TAIL(&(prReorderQueParm->rReOrderQue)); + + QUEUE_INITIALIZE(&(prReorderQueParm->rReOrderQue)); + + } + } + + if (prSwRfbListTail) { + /* Terminate the MSDU_INFO list with a NULL pointer */ + QM_TX_SET_NEXT_SW_RFB(prSwRfbListTail, NULL); + } + return prSwRfbListHead; + +} + +P_QUE_T qmDetermineStaTxQueue( + IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN UINT_8 ucActiveTs, OUT PUINT_8 pucTC) +{ + P_QUE_T prTxQue = NULL; + P_STA_RECORD_T prStaRec; + ENUM_WMM_ACI_T eAci = WMM_AC_BE_INDEX; + BOOLEAN fgCheckACMAgain; + UINT_8 ucTC; + P_BSS_INFO_T prBssInfo; + UINT_8 aucNextUP[WMM_AC_INDEX_NUM] = { 1 /* BEtoBK */, + 1 /* na */, + 0 /* VItoBE */, + 4 /* VOtoVI */ + }; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prMsduInfo->ucStaRecIndex); + if (prStaRec == NULL) + return prTxQue; + + if (prMsduInfo->ucUserPriority < 8) { + QM_DBG_CNT_INC(&prAdapter->rQM, prMsduInfo->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) { + if (prMsduInfo->ucUserPriority < TX_DESC_TID_NUM) { + eAci = aucTid2ACI[prMsduInfo->ucUserPriority]; + prTxQue = &prStaRec->arTxQueue[aucACI2TxQIdx[eAci]]; + ucTC = arNetwork2TcResource[prMsduInfo->ucBssIndex][eAci]; + } else { + prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC1]; + ucTC = TC1_INDEX; + eAci = WMM_AC_BE_INDEX; + DBGLOG(QM, WARN, "Packet TID is not in [0~7]\n"); + ASSERT(0); + } + if ((prBssInfo->arACQueParms[eAci].ucIsACMSet) && + !(ucActiveTs & BIT(eAci)) && (eAci != WMM_AC_BK_INDEX)) { + prMsduInfo->ucUserPriority = aucNextUP[eAci]; + fgCheckACMAgain = TRUE; + } + } else { + prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_NON_QOS]; + ucTC = arNetwork2TcResource[prMsduInfo->ucBssIndex][NET_TC_NON_STAREC_NON_QOS_INDEX]; + } + + if (prAdapter->rWifiVar.ucTcRestrict < TC_NUM) { + ucTC = prAdapter->rWifiVar.ucTcRestrict; + prTxQue = &prStaRec->arTxQueue[ucTC]; + } + + } while (fgCheckACMAgain); + + *pucTC = ucTC; + /* + * Record how many packages enqueue this STA + * to TX during statistic intervals + */ + prStaRec->u4EnqueueCounter++; + + return prTxQue; +} + +VOID qmSetTxPacketDescTemplate(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_STA_RECORD_T prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prMsduInfo->ucStaRecIndex); + + /* Check the Tx descriptor template is valid */ + if (prStaRec && prStaRec->aprTxDescTemplate[prMsduInfo->ucUserPriority]) { + prMsduInfo->fgIsTXDTemplateValid = TRUE; + } else { + if (prStaRec) { + DBGLOG(QM, TRACE, + "Cannot get TXD template for STA[%u] QoS[%u] MSDU UP[%u]\n", + prStaRec->ucIndex, prStaRec->fgIsQoS, prMsduInfo->ucUserPriority); + } + prMsduInfo->fgIsTXDTemplateValid = FALSE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief : To StaRec, function to stop TX +* +* \param[in] : +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +qmSetStaRecTxAllowed(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, IN BOOLEAN fgIsTxAllowed) +{ + if (prStaRec->fgIsTxAllowed != fgIsTxAllowed) { + if (fgIsTxAllowed) + prAdapter->rQM.u4TxAllowedStaCount++; + else + prAdapter->rQM.u4TxAllowedStaCount--; + } + prStaRec->fgIsTxAllowed = fgIsTxAllowed; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 ucTC; + P_TX_CTRL_T prTxCtrl = &prAdapter->rTxCtrl; + P_QUE_MGT_T prQM = &prAdapter->rQM; + P_BSS_INFO_T prBssInfo; + BOOLEAN fgDropPacket; + UINT_8 ucActivedTspec = 0; + + DBGLOG(QM, LOUD, "Enter qmEnqueueTxPackets\n"); + + ASSERT(prMsduInfoListHead); + + prMsduInfoReleaseList = NULL; + prCurrentMsduInfo = NULL; + QUEUE_INITIALIZE(&rNotEnqueuedQue); + prNextMsduInfo = prMsduInfoListHead; + ucActivedTspec = wmmHasActiveTspec(&prAdapter->rWifiVar.rWmmInfo); + + do { + prCurrentMsduInfo = prNextMsduInfo; + prNextMsduInfo = QM_TX_GET_NEXT_MSDU_INFO(prCurrentMsduInfo); + ucTC = TC1_INDEX; + + /* 4 <0> Sanity check of BSS_INFO */ + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prCurrentMsduInfo->ucBssIndex); + + if (!prBssInfo) { + /* No BSS_INFO */ + fgDropPacket = TRUE; + } else if (IS_BSS_ACTIVE(prBssInfo)) { + /* BSS active */ + fgDropPacket = FALSE; + } else { + /* BSS inactive */ + fgDropPacket = TRUE; + } + + if (!fgDropPacket) { + /* 4 <1> Lookup the STA_REC index */ + /* The ucStaRecIndex will be set in this function */ + qmDetermineStaRecIndex(prAdapter, prCurrentMsduInfo); + + wlanUpdateTxStatistics(prAdapter, prCurrentMsduInfo, FALSE); /*get per-AC Tx packets */ + if (prCurrentMsduInfo->ucDhcpArpFlag && !prAdapter->fgEnCtiaMode) + nicTxSetPktLowestFixedRate(prAdapter, prCurrentMsduInfo); + switch (prCurrentMsduInfo->ucStaRecIndex) { + case STA_REC_INDEX_BMCAST: + prTxQue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST]; + ucTC = arNetwork2TcResource[prCurrentMsduInfo->ucBssIndex] + [NET_TC_NON_STAREC_NON_QOS_INDEX]; + + /* Always set BMC packet retry limit to unlimited */ + if (!(prCurrentMsduInfo->u4Option & MSDU_OPT_MANUAL_RETRY_LIMIT)) + nicTxSetPktRetryLimit(prCurrentMsduInfo, TX_DESC_TX_COUNT_NO_LIMIT); + + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_23); + break; + + case STA_REC_INDEX_NOT_FOUND: + /* Drop packet if no STA_REC is found */ + DBGLOG(QM, TRACE, "Drop the Packet for no STA_REC\n"); + + prTxQue = &rNotEnqueuedQue; + + TX_INC_CNT(prTxCtrl, TX_INACTIVE_STA_DROP); + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_24); + break; + + default: + prTxQue = qmDetermineStaTxQueue(prAdapter, prCurrentMsduInfo, ucActivedTspec, &ucTC); + if (!prTxQue) { + DBGLOG(QM, INFO, "Drop the Packet for no determined TxQue\n"); + prTxQue = &rNotEnqueuedQue; + TX_INC_CNT(prTxCtrl, TX_INACTIVE_STA_DROP); + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_24); + } +#if ARP_MONITER_ENABLE + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prCurrentMsduInfo->ucStaRecIndex); + if (prStaRec && IS_STA_IN_AIS(prStaRec) && prCurrentMsduInfo->eSrc == TX_PACKET_OS) + qmDetectArpNoResponse(prAdapter, prCurrentMsduInfo); +#endif + break; /*default */ + } /* switch (prCurrentMsduInfo->ucStaRecIndex) */ + + if ((prTxQue != &rNotEnqueuedQue) && + (prCurrentMsduInfo->eSrc == TX_PACKET_FORWARDING)) { + if (prTxCtrl->i4PendingFwdFrameCount > prQM->u4MaxForwardBuffer) { + DBGLOG_LIMITED(QM, INFO, + "Drop the Packet UP[%u] for full pending forwarding count (%u)\n", + prCurrentMsduInfo->ucUserPriority, prQM->u4MaxForwardBuffer); + prTxQue = &rNotEnqueuedQue; + TX_INC_CNT(prTxCtrl, TX_FORWARD_OVERFLOW_DROP); + } else if (prTxCtrl->i4PendingFwdFrameCount > prQM->u4MaxForwardBufferForLowUP && + prCurrentMsduInfo->ucUserPriority < 4) { + DBGLOG_LIMITED(QM, INFO, + "Drop the low priority Packet UP[%u] for full pending forwarding count (%u)\n", + prCurrentMsduInfo->ucUserPriority, prQM->u4MaxForwardBufferForLowUP); + prTxQue = &rNotEnqueuedQue; + TX_INC_CNT(prTxCtrl, TX_FORWARD_OVERFLOW_DROP); + } else { + DBGLOG(QM, LOUD, "Forward Packet to STA[%u] TC[%u]\n", + prCurrentMsduInfo->ucStaRecIndex, ucTC); + } + } + + } else { + DBGLOG(QM, INFO, "Drop the Packet for inactive BSS[%u]\n", prCurrentMsduInfo->ucBssIndex); + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_31); + prTxQue = &rNotEnqueuedQue; + TX_INC_CNT(prTxCtrl, TX_INACTIVE_BSS_DROP); + } + + /* 4 <3> Fill the MSDU_INFO for constructing HIF TX header */ + /* Note that the BSS Index and STA_REC index are determined in + * qmDetermineStaRecIndex(prCurrentMsduInfo). + */ + prCurrentMsduInfo->ucTC = ucTC; + + /* Check the Tx descriptor template is valid */ + qmSetTxPacketDescTemplate(prAdapter, prCurrentMsduInfo); + + /* 4 <4> Enqueue the packet */ + QUEUE_INSERT_TAIL(prTxQue, (P_QUE_ENTRY_T) prCurrentMsduInfo); + wlanFillTimestamp(prAdapter, prCurrentMsduInfo->prPacket, PHASE_ENQ_QM); + /* + * Record how many packages enqueue to TX during statistic intervals + */ + if (prTxQue != &rNotEnqueuedQue) { + DBGLOG(QM, LOUD, "Enqueue MSDU[0x%p] to STA[%u] TC[%u]\n", + prCurrentMsduInfo, prCurrentMsduInfo->ucStaRecIndex, prCurrentMsduInfo->ucTC); + prQM->u4EnqueueCounter++; + /* how many page count this frame wanted */ + prQM->au4QmTcWantedPageCounter[ucTC] += prCurrentMsduInfo->ucPageCount; + +#if QM_TC_RESOURCE_EMPTY_COUNTER + if (prCurrentMsduInfo->ucPageCount > prTxCtrl->rTc.au2FreePageCount[ucTC]) + prQM->au4QmTcResourceEmptyCounter[prCurrentMsduInfo->ucBssIndex][ucTC]++; +#endif +#if QM_FAST_TC_RESOURCE_CTRL && QM_ADAPTIVE_TC_RESOURCE_CTRL + /* Check and trigger fast TC resource adjustment for queued packets */ + qmCheckForFastTcResourceCtrl(prAdapter, ucTC); +#endif + } + +#if QM_TEST_MODE + if (++prQM->u4PktCount == QM_TEST_TRIGGER_TX_COUNT) { + prQM->u4PktCount = 0; + qmTestCases(prAdapter); + } +#endif + } 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); + } +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + /* 4 Update TC resource control related variables */ + /* Keep track of the queue length */ + qmDoAdaptiveTcResourceCtrl(prAdapter); +#endif + + return prMsduInfoReleaseList; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Determine the STA_REC index for a packet +* +* \param[in] prMsduInfo Pointer to the packet +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmDetermineStaRecIndex(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + UINT_32 i; + + P_STA_RECORD_T prTempStaRec; + P_BSS_INFO_T prBssInfo; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + prTempStaRec = NULL; + + ASSERT(prMsduInfo); + + DBGLOG(QM, LOUD, "MSDU BSS[%u] OpMode[%u] StaRecOfApExist[%u]\n", + prMsduInfo->ucBssIndex, prBssInfo->eCurrentOPMode, prBssInfo->prStaRecOfAP ? TRUE : FALSE); + + switch (prBssInfo->eCurrentOPMode) { + case OP_MODE_IBSS: + case OP_MODE_ACCESS_POINT: + /* 4 <1> DA = BMCAST */ + if (IS_BMCAST_MAC_ADDR(prMsduInfo->aucEthDestAddr)) { + prMsduInfo->ucStaRecIndex = STA_REC_INDEX_BMCAST; + DBGLOG(QM, LOUD, "TX with DA = BMCAST\n"); + return; + } + break; + + /* Infra Client/GC */ + case OP_MODE_INFRASTRUCTURE: + case OP_MODE_BOW: + if (prBssInfo->prStaRecOfAP) { +#if CFG_SUPPORT_TDLS + + prTempStaRec = + cnmGetTdlsPeerByAddress(prAdapter, prBssInfo->ucBssIndex, prMsduInfo->aucEthDestAddr); + if (IS_DLS_STA(prTempStaRec) && prTempStaRec->ucStaState == STA_STATE_3) { + if (g_arTdlsLink[prTempStaRec->ucTdlsIndex]) { + prMsduInfo->ucStaRecIndex = prTempStaRec->ucIndex; + return; + } + } +#endif + /* 4 <2> Check if an AP STA is present */ + prTempStaRec = prBssInfo->prStaRecOfAP; + + DBGLOG(QM, LOUD, + "StaRecOfAP Idx[%u] WIDX[%u] Valid[%u] TxAllowed[%u] InUse[%u] Type[%u]\n", + prTempStaRec->ucIndex, prTempStaRec->ucWlanIndex, + prTempStaRec->fgIsValid, prTempStaRec->fgIsTxAllowed, + prTempStaRec->fgIsInUse, prTempStaRec->eStaType); + + if (prTempStaRec->fgIsInUse) { + prMsduInfo->ucStaRecIndex = prTempStaRec->ucIndex; + DBGLOG(QM, LOUD, "TX with AP_STA[%u]\n", prTempStaRec->ucIndex); + return; + } + } + break; + + case OP_MODE_P2P_DEVICE: + break; + + default: + break; + } + + /* 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->fgIsInUse) { + if (EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, prMsduInfo->aucEthDestAddr)) { + prMsduInfo->ucStaRecIndex = prTempStaRec->ucIndex; + DBGLOG(QM, LOUD, "TX with STA[%u]\n", 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, "TX with STA_REC_INDEX_NOT_FOUND\n"); + +#if (QM_TEST_MODE && QM_TEST_FAIR_FORWARDING) + prMsduInfo->ucStaRecIndex = (UINT_8) prQM->u4CurrentStaRecIndexToEnqueue; +#endif +} + +P_STA_RECORD_T qmDetermineStaToBeDequeued(IN P_ADAPTER_T prAdapter, IN UINT_32 u4StartStaRecIndex) +{ + + return NULL; +} + +P_QUE_T qmDequeueStaTxPackets(IN P_ADAPTER_T prAdapter) +{ + + return NULL; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +qmDequeueTxPacketsFromPerStaQueues(IN P_ADAPTER_T prAdapter, + OUT P_QUE_T prQue, + IN UINT_8 ucTC, IN UINT_32 u4CurrentQuota, IN UINT_32 u4TotalQuota) +{ + UINT_32 ucLoop; /* Loop for */ + + UINT_32 u4CurStaIndex = 0; + UINT_32 u4CurStaUsedResource = 0; + + 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 u4CurStaForwardFrameCount; /* To remember the total forwarded packets for a STA */ + UINT_32 u4MaxForwardFrameCountLimit; /* The maximum number of packets a STA can forward */ + UINT_32 u4AvaliableResource; /* The TX resource amount */ + UINT_32 u4MaxResourceLimit; + + BOOLEAN fgEndThisRound; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + PUINT_8 pucPsStaFreeQuota; +#if CFG_SUPPORT_SOFT_ACM + UINT_8 ucAc; + BOOLEAN fgAcmFlowCtrl = FALSE; + static const UINT_8 aucTc2Ac[] = {ACI_BK, ACI_BE, ACI_VI, ACI_VO}; +#endif + + /* Sanity Check */ + if (!u4CurrentQuota) { + DBGLOG(TX, LOUD, "(Fairness) Skip TC = %u u4CurrentQuota = %u\n", ucTC, u4CurrentQuota); + prQM->au4DequeueNoTcResourceCounter[ucTC]++; + return u4CurrentQuota; + } + /* 4 <1> Assign init value */ + u4AvaliableResource = u4CurrentQuota; + u4MaxResourceLimit = u4TotalQuota; + +#if QM_FORWARDING_FAIRNESS + u4CurStaIndex = prQM->au4HeadStaRecIndex[ucTC]; + u4CurStaUsedResource = prQM->au4ResourceUsedCount[ucTC]; +#endif + + fgEndThisRound = FALSE; + ucLoop = 0; + u4CurStaForwardFrameCount = 0; + + DBGLOG(QM, LOUD, "(Fairness) TC[%u] Init Head STA[%u] Resource[%u]\n", + ucTC, u4CurStaIndex, u4AvaliableResource); + + /* 4 <2> Traverse STA array from Head STA */ + /* From STA[x] to STA[x+1] to STA[x+2] to ... to STA[x] */ + while (ucLoop < CFG_NUM_OF_STA_RECORD) { + prStaRec = &prAdapter->arStaRec[u4CurStaIndex]; + + /* 4 <2.1> Find a Tx allowed STA */ + /* Only Data frame (1x was not included) will be queued in */ + if (prStaRec->fgIsTxAllowed) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + prCurrQueue = &prStaRec->arTxQueue[ucTC]; + prDequeuedPkt = NULL; + pucPsStaFreeQuota = NULL; + /* Set default forward count limit to unlimited */ + u4MaxForwardFrameCountLimit = QM_STA_FORWARD_COUNT_UNLIMITED; + + /* 4 <2.2> Update forward frame/page count limit for this STA */ + /* AP mode: STA in PS buffer handling */ + if (prStaRec->fgIsInPS) { + if (prStaRec->fgIsQoS && + prStaRec->fgIsUapsdSupported && (prStaRec->ucBmpTriggerAC & BIT(ucTC))) { + u4MaxForwardFrameCountLimit = prStaRec->ucFreeQuotaForDelivery; + pucPsStaFreeQuota = &prStaRec->ucFreeQuotaForDelivery; + } else { + /* ASSERT(prStaRec->ucFreeQuotaForDelivery == 0); */ + u4MaxForwardFrameCountLimit = prStaRec->ucFreeQuotaForNonDelivery; + pucPsStaFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery; + } + + } + + /* fgIsInPS */ + /* Absent BSS handling */ + if (prBssInfo->fgIsNetAbsent) { + if (u4MaxForwardFrameCountLimit > prBssInfo->ucBssFreeQuota) + u4MaxForwardFrameCountLimit = prBssInfo->ucBssFreeQuota; + } +#if CFG_SUPPORT_SOFT_ACM + if (ucTC <= TC3_INDEX && prStaRec->afgAcmRequired[aucTc2Ac[ucTC]]) { + ucAc = aucTc2Ac[ucTC]; + DBGLOG(QM, TRACE, "AC %d Pending Pkts %u\n", ucAc, prCurrQueue->u4NumElem); + /* Quick check remain medium time and pending packets */ + if (QUEUE_IS_EMPTY(prCurrQueue) || !wmmAcmCanDequeue(prAdapter, ucAc, 0)) + goto skip_dequeue; + fgAcmFlowCtrl = TRUE; + } else + fgAcmFlowCtrl = FALSE; +#endif + /* 4 <2.3> Dequeue packet */ + /* Three cases to break: (1) No resource (2) No packets (3) Fairness */ + while (!QUEUE_IS_EMPTY(prCurrQueue)) { + prDequeuedPkt = (P_MSDU_INFO_T) QUEUE_GET_HEAD(prCurrQueue); + + if ((u4CurStaForwardFrameCount >= u4MaxForwardFrameCountLimit) || + (u4CurStaUsedResource >= u4MaxResourceLimit)) { + /* Exceeds Limit */ + prQM->au4DequeueNoTcResourceCounter[ucTC]++; + break; + } else if (prDequeuedPkt->ucPageCount > u4AvaliableResource) { + /* Available Resource is not enough */ + prQM->au4DequeueNoTcResourceCounter[ucTC]++; + if (!(prAdapter->rWifiVar.ucAlwaysResetUsedRes & BIT(0))) + fgEndThisRound = TRUE; + break; + } +#if CFG_SUPPORT_SOFT_ACM + if (fgAcmFlowCtrl) { + UINT_32 u4PktTxTime = 0; + + u4PktTxTime = wmmCalculatePktUsedTime(prBssInfo, prStaRec, + prDequeuedPkt->u2FrameLength - ETH_HLEN); + if (!wmmAcmCanDequeue(prAdapter, ucAc, u4PktTxTime)) + break; + } +#endif + /* Available to be Tx */ + QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T); + + 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); + prStaRec->u4DeqeueuCounter++; + prQM->u4DequeueCounter++; + + u4AvaliableResource -= prDequeuedPkt->ucPageCount; + u4CurStaUsedResource += prDequeuedPkt->ucPageCount; + u4CurStaForwardFrameCount++; + + } +#if CFG_SUPPORT_SOFT_ACM +skip_dequeue: +#endif + /* AP mode: Update STA in PS Free quota */ + if (prStaRec->fgIsInPS && pucPsStaFreeQuota) { + if ((*pucPsStaFreeQuota) >= u4CurStaForwardFrameCount) + (*pucPsStaFreeQuota) -= u4CurStaForwardFrameCount; + else + (*pucPsStaFreeQuota) = 0; + } + + if (prBssInfo->fgIsNetAbsent) { + if (prBssInfo->ucBssFreeQuota >= u4CurStaForwardFrameCount) + prBssInfo->ucBssFreeQuota -= u4CurStaForwardFrameCount; + else + prBssInfo->ucBssFreeQuota = 0; + } + } + + if (fgEndThisRound) { + /* End this round */ + break; + } + + /* Prepare for next STA */ + ucLoop++; + u4CurStaIndex++; + u4CurStaIndex %= CFG_NUM_OF_STA_RECORD; + u4CurStaUsedResource = 0; + u4CurStaForwardFrameCount = 0; + } + + /* 4 <3> Store Head Sta information to QM */ + /* No need to count used resource if thers is only one STA */ + if ((prQM->u4TxAllowedStaCount == 1) || (prAdapter->rWifiVar.ucAlwaysResetUsedRes & BIT(1))) + u4CurStaUsedResource = 0; +#if QM_FORWARDING_FAIRNESS + prQM->au4HeadStaRecIndex[ucTC] = u4CurStaIndex; + prQM->au4ResourceUsedCount[ucTC] = u4CurStaUsedResource; +#endif + + DBGLOG(QM, LOUD, "(Fairness) TC[%u] Scheduled Head STA[%u] Left Resource[%u]\n", + ucTC, u4CurStaIndex, u4AvaliableResource); + + return u4AvaliableResource; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 available resource +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +qmDequeueTxPacketsFromPerTypeQueues(IN P_ADAPTER_T prAdapter, + OUT P_QUE_T prQue, + IN UINT_8 ucTC, IN UINT_32 u4CurrentQuota, IN UINT_32 u4TotalQuota) +{ + UINT_32 u4AvaliableResource, u4LeftResource; + UINT_32 u4MaxResourceLimit; + UINT_32 u4TotalUsedResource = 0; + P_QUE_MGT_T prQM; + PFN_DEQUEUE_FUNCTION pfnDeQFunc[2]; + BOOLEAN fgChangeDeQFunc = TRUE; + BOOLEAN fgGlobalQueFirst = TRUE; + + DBGLOG(QM, LOUD, "Enter %s (TC = %d, quota = %u)\n", __func__, ucTC, u4CurrentQuota); + + /* TC5: Broadcast/Multicast data packets */ + if ((u4CurrentQuota == 0) || (ucTC != TC5_INDEX)) + return; + + prQM = &prAdapter->rQM; + + u4AvaliableResource = u4CurrentQuota; + u4MaxResourceLimit = u4TotalQuota; +#if QM_FORWARDING_FAIRNESS + u4TotalUsedResource = prQM->u4GlobalResourceUsedCount; + fgGlobalQueFirst = prQM->fgGlobalQFirst; +#endif + + /* Dequeue function selection */ + if (fgGlobalQueFirst) { + pfnDeQFunc[0] = qmDequeueTxPacketsFromGlobalQueue; + pfnDeQFunc[1] = qmDequeueTxPacketsFromPerStaQueues; + } else { + pfnDeQFunc[0] = qmDequeueTxPacketsFromPerStaQueues; + pfnDeQFunc[1] = qmDequeueTxPacketsFromGlobalQueue; + } + + /* 1st dequeue function */ + u4LeftResource = pfnDeQFunc[0] (prAdapter, + prQue, ucTC, u4AvaliableResource, (u4MaxResourceLimit - u4TotalUsedResource)); + + /* dequeue function comsumes no resource, change */ + if ((u4LeftResource >= u4AvaliableResource) && (u4AvaliableResource >= NIC_TX_MAX_PAGE_PER_FRAME)) { + + fgChangeDeQFunc = TRUE; + } else { + u4TotalUsedResource += (u4AvaliableResource - u4LeftResource); + /* Used resource exceeds limit, change */ + if (u4TotalUsedResource >= u4MaxResourceLimit) + fgChangeDeQFunc = TRUE; + } + + if (fgChangeDeQFunc) { + fgGlobalQueFirst = !fgGlobalQueFirst; + u4TotalUsedResource = 0; + } + + /* 2nd dequeue function */ + u4LeftResource = pfnDeQFunc[1] (prAdapter, prQue, ucTC, u4LeftResource, u4MaxResourceLimit); + +#if QM_FORWARDING_FAIRNESS + prQM->fgGlobalQFirst = fgGlobalQueFirst; + prQM->u4GlobalResourceUsedCount = u4TotalUsedResource; +#endif + +} /* qmDequeueTxPacketsFromPerTypeQueues */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Dequeue TX packets from a QM global 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 available resource +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +qmDequeueTxPacketsFromGlobalQueue(IN P_ADAPTER_T prAdapter, + OUT P_QUE_T prQue, IN UINT_8 ucTC, IN UINT_32 u4CurrentQuota, IN UINT_32 u4TotalQuota) +{ + P_BSS_INFO_T prBssInfo; + P_QUE_T prCurrQueue; + UINT_32 u4AvaliableResource; + P_MSDU_INFO_T prDequeuedPkt; + QUE_T rMergeQue; + P_QUE_T prMergeQue; + P_QUE_MGT_T prQM; + + DBGLOG(QM, LOUD, "Enter %s (TC = %d, quota = %u)\n", __func__, ucTC, u4CurrentQuota); + + /* TC5: Broadcast/Multicast data packets */ + if (u4CurrentQuota == 0) + return u4CurrentQuota; + + prQM = &prAdapter->rQM; + + /* 4 <1> Determine the queue */ + prCurrQueue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST]; + u4AvaliableResource = u4CurrentQuota; + prDequeuedPkt = NULL; + + QUEUE_INITIALIZE(&rMergeQue); + prMergeQue = &rMergeQue; + + /* 4 <2> Dequeue packets */ + while (!QUEUE_IS_EMPTY(prCurrQueue)) { + prDequeuedPkt = (P_MSDU_INFO_T) QUEUE_GET_HEAD(prCurrQueue); + if (prDequeuedPkt->ucPageCount > u4AvaliableResource) + break; + + QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T); + ASSERT(prDequeuedPkt->ucTC == ucTC); + ASSERT(prDequeuedPkt->ucBssIndex <= MAX_BSS_INDEX); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prDequeuedPkt->ucBssIndex); + + if (IS_BSS_ACTIVE(prBssInfo)) { + if (!prBssInfo->fgIsNetAbsent) { + QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prDequeuedPkt); + prQM->u4DequeueCounter++; + u4AvaliableResource -= prDequeuedPkt->ucPageCount; + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_26); + } else { + QUEUE_INSERT_TAIL(prMergeQue, (P_QUE_ENTRY_T) prDequeuedPkt); + } + } else { + QM_TX_SET_NEXT_MSDU_INFO(prDequeuedPkt, NULL); + wlanProcessQueuedMsduInfo(prAdapter, prDequeuedPkt); + } + } + + if (QUEUE_IS_NOT_EMPTY(prMergeQue)) { + QUEUE_CONCATENATE_QUEUES(prMergeQue, prCurrQueue); + QUEUE_MOVE_ALL(prCurrQueue, prMergeQue); + if (QUEUE_GET_TAIL(prCurrQueue)) + QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T) QUEUE_GET_TAIL(prCurrQueue), NULL); + } + + return u4AvaliableResource; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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; + UINT_32 u4MaxQuotaLimit; + + DBGLOG(QM, LOUD, "Enter qmDequeueTxPackets\n"); + + QUEUE_INITIALIZE(&rReturnedQue); + + prReturnedPacketListHead = NULL; + + /* TC0 to TC3: AC0~AC3 (commands packets are not handled by QM) */ + for (i = TC3_INDEX; i >= TC0_INDEX; i--) { + DBGLOG(QM, LOUD, "Dequeue packets from Per-STA queue[%u]\n", i); + + /* If only one STA is Tx allowed, no need to restrict Max quota */ + if (prAdapter->rWifiVar.u4MaxTxDeQLimit) + u4MaxQuotaLimit = prAdapter->rWifiVar.u4MaxTxDeQLimit; + else if (prAdapter->rQM.u4TxAllowedStaCount == 1) + u4MaxQuotaLimit = QM_STA_FORWARD_COUNT_UNLIMITED; + else + u4MaxQuotaLimit = (UINT_32) prTcqStatus->au2MaxNumOfPage[i]; + + qmDequeueTxPacketsFromPerStaQueues(prAdapter, + &rReturnedQue, + (UINT_8) i, + (UINT_32) prTcqStatus->au2FreePageCount[i], u4MaxQuotaLimit); + + /* The aggregate number of dequeued packets */ + DBGLOG(QM, LOUD, "DQA)[%u](%u)\n", i, rReturnedQue.u4NumElem); + } + + /* TC5 (BMCAST or non-QoS packets) */ + qmDequeueTxPacketsFromPerTypeQueues(prAdapter, + &rReturnedQue, + TC5_INDEX, + prTcqStatus->au2FreePageCount[TC5_INDEX], + prTcqStatus->au2MaxNumOfPage[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; +} + +#if CFG_SUPPORT_MULTITHREAD +/*----------------------------------------------------------------------------*/ +/*! +* \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 qmDequeueTxPacketsMthread(IN P_ADAPTER_T prAdapter, IN P_TX_TCQ_STATUS_T prTcqStatus) +{ + + /* INT_32 i; */ + P_MSDU_INFO_T prReturnedPacketListHead; + /* QUE_T rReturnedQue; */ + /* UINT_32 u4MaxQuotaLimit; */ + P_MSDU_INFO_T prMsduInfo, prNextMsduInfo; + + UINT_8 ucPageCount; + P_QUE_MGT_T prQM; + + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + prQM = &prAdapter->rQM; + + prReturnedPacketListHead = qmDequeueTxPackets(prAdapter, prTcqStatus); + + /* require the resource first to prevent from unsync */ + prMsduInfo = prReturnedPacketListHead; + while (prMsduInfo) { + prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); + ucPageCount = nicTxGetPageCount(prMsduInfo->u2FrameLength, FALSE); + prTcqStatus->au2FreePageCount[prMsduInfo->ucTC] -= ucPageCount; + prQM->au4QmTcUsedPageCounter[prMsduInfo->ucTC] += ucPageCount; + prTcqStatus->au2FreeBufferCount[prMsduInfo->ucTC] = + (prTcqStatus->au2FreePageCount[prMsduInfo->ucTC] / NIC_TX_MAX_PAGE_PER_FRAME); + prMsduInfo = prNextMsduInfo; + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + 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) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +qmAdjustTcQuotasMthread(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; + + KAL_SPIN_LOCK_DECLARATION(); + + /* Must initialize */ + for (i = 0; i < QM_ACTIVE_TC_NUM; i++) + prTcqAdjust->acVariation[i] = 0; + + /* 4 <1> If TC resource is not just adjusted, exit directly */ + if (!prQM->fgTcResourcePostAnnealing) + return FALSE; + /* 4 <2> Adjust TcqStatus according to the updated prQM->au4CurrentTcResource */ + else { + INT_32 i4TotalExtraQuota = 0; + INT_32 ai4ExtraQuota[QM_ACTIVE_TC_NUM]; + BOOLEAN fgResourceRedistributed = TRUE; + + /* Must initialize */ + for (i = 0; i < TC_NUM; i++) + prTcqAdjust->acVariation[i] = 0; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + /* Obtain the free-to-distribute resource */ + for (i = 0; i < QM_ACTIVE_TC_NUM; i++) { + ai4ExtraQuota[i] = + (INT_32) prTcqStatus->au2MaxNumOfBuffer[i] - (INT_32) prQM->au4CurrentTcResource[i]; + + if (ai4ExtraQuota[i] > 0) { /* The resource shall be reallocated to other TCs */ + if (ai4ExtraQuota[i] > prTcqStatus->au2FreeBufferCount[i]) { + ai4ExtraQuota[i] = prTcqStatus->au2FreeBufferCount[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 < QM_ACTIVE_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); + + for (i = 0; i < TC_NUM; i++) { + prTcqStatus->au2FreePageCount[i] += (prTcqAdjust->acVariation[i] * NIC_TX_MAX_PAGE_PER_FRAME); + prTcqStatus->au2MaxNumOfPage[i] += (prTcqAdjust->acVariation[i] * NIC_TX_MAX_PAGE_PER_FRAME); + + prTcqStatus->au2FreeBufferCount[i] += prTcqAdjust->acVariation[i]; + prTcqStatus->au2MaxNumOfBuffer[i] += prTcqAdjust->acVariation[i]; + + ASSERT(prTcqStatus->au2FreeBufferCount[i] >= 0); + ASSERT(prTcqStatus->au2MaxNumOfBuffer[i] >= 0); + } + +#if QM_FAST_TC_RESOURCE_CTRL + prQM->fgTcResourceFastReaction = FALSE; +#endif + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + } + + return TRUE; +#else + return FALSE; +#endif +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN 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 < QM_ACTIVE_TC_NUM; i++) + prTcqAdjust->acVariation[i] = 0; + + /* 4 <1> If TC resource is not just adjusted, exit directly */ + if (!prQM->fgTcResourcePostAnnealing) + return FALSE; + /* 4 <2> Adjust TcqStatus according to the updated prQM->au4CurrentTcResource */ + else { + INT_32 i4TotalExtraQuota = 0; + INT_32 ai4ExtraQuota[QM_ACTIVE_TC_NUM]; + BOOLEAN fgResourceRedistributed = TRUE; + + /* Obtain the free-to-distribute resource */ + for (i = 0; i < QM_ACTIVE_TC_NUM; i++) { + ai4ExtraQuota[i] = + (INT_32) prTcqStatus->au2MaxNumOfBuffer[i] - (INT_32) prQM->au4CurrentTcResource[i]; + + if (ai4ExtraQuota[i] > 0) { /* The resource shall be reallocated to other TCs */ + if (ai4ExtraQuota[i] > prTcqStatus->au2FreeBufferCount[i]) { + ai4ExtraQuota[i] = prTcqStatus->au2FreeBufferCount[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 < QM_ACTIVE_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_FAST_TC_RESOURCE_CTRL + prQM->fgTcResourceFastReaction = FALSE; +#endif + +#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->au2FreeBufferCount[0], + prTcqStatus->au2FreeBufferCount[1], + prTcqStatus->au2FreeBufferCount[2], + prTcqStatus->au2FreeBufferCount[3], + prTcqStatus->au2FreeBufferCount[4], prTcqStatus->au2FreeBufferCount[5]); +#endif + } + + return TRUE; +#else + return FALSE; +#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, u4Tc, u4StaRecIdx; + P_STA_RECORD_T prStaRec; + P_QUE_MGT_T prQM = &prAdapter->rQM; + P_BSS_INFO_T prBssInfo; + + /* 4 <1> Update the queue lengths for TC0 to TC3 (skip TC4) and TC5 */ + for (u4Tc = 0; u4Tc < QM_ACTIVE_TC_NUM; u4Tc++) { + u4CurrQueLen = 0; + + /* Calculate per-STA queue length */ + for (u4StaRecIdx = 0; u4StaRecIdx < CFG_NUM_OF_STA_RECORD; u4StaRecIdx++) { + prStaRec = cnmGetStaRecByIndex(prAdapter, u4StaRecIdx); + if (prStaRec) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + /* If the STA is activated, get the queue length */ + if ((prStaRec->fgIsValid) && (!prBssInfo->fgIsNetAbsent)) + u4CurrQueLen += (prStaRec->arTxQueue[u4Tc].u4NumElem); + } + } + + if (u4Tc == TC5_INDEX) { + /* Update the queue length for TC5 (BMCAST) */ + u4CurrQueLen += prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST].u4NumElem; + } + + if (prQM->au4AverageQueLen[u4Tc] == 0) { + prQM->au4AverageQueLen[u4Tc] = (u4CurrQueLen << prQM->u4QueLenMovingAverage); + } else { + prQM->au4AverageQueLen[u4Tc] -= (prQM->au4AverageQueLen[u4Tc] >> prQM->u4QueLenMovingAverage); + prQM->au4AverageQueLen[u4Tc] += (u4CurrQueLen); + } + } +#if 0 + /* Update the queue length for TC5 (BMCAST) */ + u4CurrQueLen = prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST].u4NumElem; + + if (prQM->au4AverageQueLen[TC5_INDEX] == 0) { + prQM->au4AverageQueLen[TC5_INDEX] = (u4CurrQueLen << QM_QUE_LEN_MOVING_AVE_FACTOR); + } else { + prQM->au4AverageQueLen[TC5_INDEX] -= + (prQM->au4AverageQueLen[TC5_INDEX] >> QM_QUE_LEN_MOVING_AVE_FACTOR); + prQM->au4AverageQueLen[TC5_INDEX] += (u4CurrQueLen); + } +#endif +} + +#if 1 +VOID +qmAllocateResidualTcResource(IN P_ADAPTER_T prAdapter, + IN PINT_32 ai4TcResDemand, IN PUINT_32 pu4ResidualResource, IN PUINT_32 pu4ShareCount) +{ + P_QUE_MGT_T prQM = &prAdapter->rQM; + UINT_32 u4Share = 0; + UINT_32 u4TcIdx; + UINT_8 ucIdx; + UINT_32 au4AdjTc[] = { TC3_INDEX, TC2_INDEX, TC5_INDEX, TC1_INDEX, TC0_INDEX }; + UINT_32 u4AdjTcSize = (sizeof(au4AdjTc) / sizeof(UINT_32)); + UINT_32 u4ResidualResource = *pu4ResidualResource; + UINT_32 u4ShareCount = *pu4ShareCount; + + /* If there is no resource left, exit directly */ + if (u4ResidualResource == 0) + return; + + /* This shall not happen */ + if (u4ShareCount == 0) { + prQM->au4CurrentTcResource[TC1_INDEX] += u4ResidualResource; + DBGLOG(QM, ERROR, "QM: (Error) u4ShareCount = 0\n"); + return; + } + + /* Share the residual resource evenly */ + u4Share = (u4ResidualResource / u4ShareCount); + if (u4Share) { + for (u4TcIdx = 0; u4TcIdx < QM_ACTIVE_TC_NUM; u4TcIdx++) { + /* Skip TC4 (not adjustable) */ + if (u4TcIdx == TC4_INDEX) + continue; + + if (ai4TcResDemand[u4TcIdx] > 0) { + if (ai4TcResDemand[u4TcIdx] > u4Share) { + prQM->au4CurrentTcResource[u4TcIdx] += u4Share; + u4ResidualResource -= u4Share; + ai4TcResDemand[u4TcIdx] -= u4Share; + } else { + prQM->au4CurrentTcResource[u4TcIdx] += ai4TcResDemand[u4TcIdx]; + u4ResidualResource -= ai4TcResDemand[u4TcIdx]; + ai4TcResDemand[u4TcIdx] = 0; + } + } + } + } + + /* By priority, allocate the left resource that is not divisible by u4Share */ + ucIdx = 0; + while (u4ResidualResource) { + u4TcIdx = au4AdjTc[ucIdx]; + + if (ai4TcResDemand[u4TcIdx]) { + prQM->au4CurrentTcResource[u4TcIdx]++; + u4ResidualResource--; + ai4TcResDemand[u4TcIdx]--; + + if (ai4TcResDemand[u4TcIdx] == 0) + u4ShareCount--; + } + + if (u4ShareCount <= 0) + break; + + ucIdx++; + ucIdx %= u4AdjTcSize; + } + + /* Allocate the left resource */ + prQM->au4CurrentTcResource[TC3_INDEX] += u4ResidualResource; + + *pu4ResidualResource = u4ResidualResource; + *pu4ShareCount = u4ShareCount; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 u4TcIdx; + INT_32 ai4TcResDemand[QM_ACTIVE_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 (u4TcIdx = 0; u4TcIdx < QM_ACTIVE_TC_NUM; u4TcIdx++) { + /* Skip TC4, which is not adjustable */ + if (u4TcIdx == TC4_INDEX) + continue; + + /* Define: extra_demand = que_length + min_reserved_quota - current_quota */ + ai4TcResDemand[u4TcIdx] = (QM_GET_TX_QUEUE_LEN(prAdapter, u4TcIdx) + + prQM->au4MinReservedTcResource[u4TcIdx] - + prQM->au4CurrentTcResource[u4TcIdx]); + + /* If there are queued packets, allocate extra resource for the TC (for TCP consideration) */ + if (QM_GET_TX_QUEUE_LEN(prAdapter, u4TcIdx)) + ai4TcResDemand[u4TcIdx] += prQM->u4ExtraReservedTcResource; + + i4TotalResourceDemand += ai4TcResDemand[u4TcIdx]; + } + + /* 4 <2> Case 1: Demand <= Total Resource */ + if (i4TotalResourceDemand <= 0) { + + /* 4 <2.1> Calculate the residual resource evenly */ + u4ShareCount = (QM_ACTIVE_TC_NUM - 1); /* excluding TC4 */ + u4ResidualResource = (UINT_32) (-i4TotalResourceDemand); + u4Share = (u4ResidualResource / u4ShareCount); + + /* 4 <2.2> Satisfy every TC and share the residual resource evenly */ + for (u4TcIdx = 0; u4TcIdx < QM_ACTIVE_TC_NUM; u4TcIdx++) { + /* Skip TC4 (not adjustable) */ + if (u4TcIdx == TC4_INDEX) + continue; + + prQM->au4CurrentTcResource[u4TcIdx] += (ai4TcResDemand[u4TcIdx] + u4Share); + + /* Every TC is fully satisfied */ + ai4TcResDemand[u4TcIdx] = 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 = prQM->u4ResidualTcResource; + + /* 4 <3.1> Allocated resouce amount = minimum of (guaranteed, total demand) */ + for (u4TcIdx = 0; u4TcIdx < QM_ACTIVE_TC_NUM; u4TcIdx++) { + /* Skip TC4 (not adjustable) */ + if (u4TcIdx == TC4_INDEX) + continue; + + /* The demand can be fulfilled with the guaranteed resource amount */ + if ((prQM->au4CurrentTcResource[u4TcIdx] + ai4TcResDemand[u4TcIdx]) <= + prQM->au4GuaranteedTcResource[u4TcIdx]) { + + prQM->au4CurrentTcResource[u4TcIdx] += ai4TcResDemand[u4TcIdx]; + u4ResidualResource += + (prQM->au4GuaranteedTcResource[u4TcIdx] - prQM->au4CurrentTcResource[u4TcIdx]); + ai4TcResDemand[u4TcIdx] = 0; + } + + /* The demand can not be fulfilled with the guaranteed resource amount */ + else { + ai4TcResDemand[u4TcIdx] -= + (prQM->au4GuaranteedTcResource[u4TcIdx] - prQM->au4CurrentTcResource[u4TcIdx]); + + prQM->au4CurrentTcResource[u4TcIdx] = prQM->au4GuaranteedTcResource[u4TcIdx]; + u4ShareCount++; + } + } + + /* 4 <3.2> Allocate the residual resource */ + qmAllocateResidualTcResource(prAdapter, ai4TcResDemand, &u4ResidualResource, &u4ShareCount); + } + + prQM->fgTcResourcePostAnnealing = TRUE; + +#if QM_PRINT_TC_RESOURCE_CTRL + /* Debug print */ + DBGLOG(QM, INFO, "QM: TC Rsc adjust to [%03u:%03u:%03u:%03u:%03u:%03u]\n", + prQM->au4CurrentTcResource[0], prQM->au4CurrentTcResource[1], + prQM->au4CurrentTcResource[2], prQM->au4CurrentTcResource[3], + prQM->au4CurrentTcResource[4], prQM->au4CurrentTcResource[5]); +#endif + +} +#else +VOID qmReassignTcResource(IN P_ADAPTER_T prAdapter) +{ + INT_32 i4TotalResourceDemand = 0; + UINT_32 u4ResidualResource = 0; + UINT_32 u4TcIdx; + INT_32 ai4PerTcResourceDemand[QM_ACTIVE_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 (u4TcIdx = 0; u4TcIdx < QM_ACTIVE_TC_NUM; u4TcIdx++) { + /* Skip TC4, which is not adjustable */ + if (u4TcIdx == TC4_INDEX) + continue; + + /* Define: extra_demand = que_length + min_reserved_quota - current_quota */ + ai4PerTcResourceDemand[u4TcIdx] = (QM_GET_TX_QUEUE_LEN(prAdapter, u4TcIdx) + + prQM->au4MinReservedTcResource[u4TcIdx] - + prQM->au4CurrentTcResource[u4TcIdx]); + + /* If there are queued packets, allocate extra resource for the TC (for TCP consideration) */ + if (QM_GET_TX_QUEUE_LEN(prAdapter, u4TcIdx)) + ai4PerTcResourceDemand[u4TcIdx] += QM_EXTRA_RESERVED_RESOURCE_WHEN_BUSY; + + i4TotalResourceDemand += ai4PerTcResourceDemand[u4TcIdx]; + } + + /* 4 <2> Case 1: Demand <= Total Resource */ + if (i4TotalResourceDemand <= 0) { +#if 0 + /* 4 <2.1> Satisfy every TC */ + for (u4TcIdx = 0; u4TcIdx < QM_ACTIVE_TC_NUM; u4TcIdx++) { + /* Skip TC4 (not adjustable) */ + if (u4TcIdx == TC4_INDEX) + continue; + + prQM->au4CurrentTcResource[u4TcIdx] += ai4PerTcResourceDemand[u4TcIdx]; + } + + /* 4 <2.2> Share the residual resource evenly */ + u4ShareCount = (QM_ACTIVE_TC_NUM - 1); /* excluding TC4 */ + u4ResidualResource = (UINT_32) (-i4TotalResourceDemand); + u4Share = (u4ResidualResource / u4ShareCount); + + for (u4TcIdx = 0; u4TcIdx < QM_ACTIVE_TC_NUM; u4TcIdx++) { + /* Skip TC4 (not adjustable) */ + if (u4TcIdx == TC4_INDEX) + continue; + + prQM->au4CurrentTcResource[u4TcIdx] += u4Share; + + /* Every TC is fully satisfied */ + ai4PerTcResourceDemand[u4TcIdx] = 0; + + /* The left resource will be allocated to TC3 */ + u4ResidualResource -= u4Share; + } +#else + /* Optimization */ + /* 4 <2.1> Calculate the residual resource evenly */ + u4ShareCount = (QM_ACTIVE_TC_NUM - 1); /* excluding TC4 */ + u4ResidualResource = (UINT_32) (-i4TotalResourceDemand); + u4Share = (u4ResidualResource / u4ShareCount); + + /* 4 <2.2> Satisfy every TC and share the residual resource evenly */ + for (u4TcIdx = 0; u4TcIdx < QM_ACTIVE_TC_NUM; u4TcIdx++) { + /* Skip TC4 (not adjustable) */ + if (u4TcIdx == TC4_INDEX) + continue; + + prQM->au4CurrentTcResource[u4TcIdx] += (ai4PerTcResourceDemand[u4TcIdx] + u4Share); + + /* Every TC is fully satisfied */ + ai4PerTcResourceDemand[u4TcIdx] = 0; + + /* The left resource will be allocated to TC3 */ + u4ResidualResource -= u4Share; + } +#endif + + /* 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 = prQM->u4ResidualTcResource; + + /* 4 <3.1> Allocated resouce amount = minimum of (guaranteed, total demand) */ + for (u4TcIdx = 0; u4TcIdx < QM_ACTIVE_TC_NUM; u4TcIdx++) { + /* Skip TC4 (not adjustable) */ + if (u4TcIdx == TC4_INDEX) + continue; + + /* The demand can be fulfilled with the guaranteed resource amount */ + if ((prQM->au4CurrentTcResource[u4TcIdx] + ai4PerTcResourceDemand[u4TcIdx]) < + prQM->au4GuaranteedTcResource[u4TcIdx]) { + prQM->au4CurrentTcResource[u4TcIdx] += ai4PerTcResourceDemand[u4TcIdx]; + u4ResidualResource += + (prQM->au4GuaranteedTcResource[u4TcIdx] - prQM->au4CurrentTcResource[u4TcIdx]); + ai4PerTcResourceDemand[u4TcIdx] = 0; + } + + /* The demand can not be fulfilled with the guaranteed resource amount */ + else { + ai4PerTcResourceDemand[u4TcIdx] -= + (prQM->au4GuaranteedTcResource[u4TcIdx] - prQM->au4CurrentTcResource[u4TcIdx]); + prQM->au4CurrentTcResource[u4TcIdx] = prQM->au4GuaranteedTcResource[u4TcIdx]; + 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 (u4TcIdx = 0; u4TcIdx < QM_ACTIVE_TC_NUM; u4TcIdx++) { + /* Skip TC4 (not adjustable) */ + if (u4TcIdx == TC4_INDEX) + continue; + if (ai4PerTcResourceDemand[u4TcIdx] == 0) + continue; + if (ai4PerTcResourceDemand[u4TcIdx] - u4Share) { + prQM->au4CurrentTcResource[u4TcIdx] += u4Share; + u4ResidualResource -= u4Share; + ai4PerTcResourceDemand[u4TcIdx] -= u4Share; + } else { + prQM->au4CurrentTcResource[u4TcIdx] += + ai4PerTcResourceDemand[u4TcIdx]; + u4ResidualResource -= ai4PerTcResourceDemand[u4TcIdx]; + ai4PerTcResourceDemand[u4TcIdx] = 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, INFO, "QM: TC Rsc adjust to [%03u:%03u:%03u:%03u:%03u:%03u]\n", + prQM->au4CurrentTcResource[0], + prQM->au4CurrentTcResource[1], + prQM->au4CurrentTcResource[2], + prQM->au4CurrentTcResource[3], prQM->au4CurrentTcResource[4], prQM->au4CurrentTcResource[5]); +#endif + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Adjust TX resource for each TC according to TX queue length and current assignment +* +* \param (none) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmDoAdaptiveTcResourceCtrl(IN P_ADAPTER_T prAdapter) +{ + P_QUE_MGT_T prQM = &prAdapter->rQM; + + /* 4 <0> Check to update queue length or not */ + if (--prQM->u4TimeToUpdateQueLen) + return; + /* 4 <1> Update TC queue length */ + prQM->u4TimeToUpdateQueLen = QM_INIT_TIME_TO_UPDATE_QUE_LEN; + qmUpdateAverageTxQueLen(prAdapter); + + /* 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); +#if QM_FAST_TC_RESOURCE_CTRL + if (prQM->fgTcResourceFastReaction) { + prQM->fgTcResourceFastReaction = FALSE; + nicTxAdjustTcq(prAdapter); + } +#endif + } + } + + /* Debug */ +#if QM_PRINT_TC_RESOURCE_CTRL + do { + UINT_32 u4Tc; + + for (u4Tc = 0; u4Tc < QM_ACTIVE_TC_NUM; u4Tc++) { + if (QM_GET_TX_QUEUE_LEN(prAdapter, u4Tc) >= 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; + } + } + } while (FALSE); +#endif + +} + +#if QM_FAST_TC_RESOURCE_CTRL +VOID qmCheckForFastTcResourceCtrl(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTc) +{ + P_QUE_MGT_T prQM = &prAdapter->rQM; + + /* Trigger TC resource adjustment if there is a requirement coming for a empty TC */ + if (!prQM->au4CurrentTcResource[ucTc]) { + prQM->u4TimeToUpdateQueLen = 1; + prQM->u4TimeToAdjustTcResource = 1; + prQM->fgTcResourceFastReaction = TRUE; + + DBGLOG(QM, LOUD, "Trigger TC Resource adjustment for TC[%u]\n", ucTc); + } +} +#endif + +#endif + +/*----------------------------------------------------------------------------*/ +/* RX-Related Queue Management */ +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +/*! +* \brief Init Queue Management for RX +* +* \param[in] (none) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmInitRxQueues(IN P_ADAPTER_T prAdapter) +{ + /* DbgPrint("QM: Enter qmInitRxQueues()\n"); */ + /* TODO */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Handle RX packets (buffer reordering) +* +* \param[in] prSwRfbListHead The list of RX packets +* +* \return The list of packets which are not buffered for reordering +*/ +/*----------------------------------------------------------------------------*/ +P_SW_RFB_T qmHandleRxPackets(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfbListHead) +{ + +#if CFG_RX_REORDERING_ENABLED + P_SW_RFB_T prCurrSwRfb; + P_SW_RFB_T prNextSwRfb; + P_HW_MAC_RX_DESC_T prRxStatus; + QUE_T rReturnedQue; + P_QUE_T prReturnedQue; + PUINT_8 pucEthDestAddr; + BOOLEAN fgIsBMC, fgIsHTran; + BOOLEAN fgMicErr; +#if CFG_SUPPORT_REPLAY_DETECTION + UINT_8 ucBssIndexRly = 0; + P_BSS_INFO_T prBssInfoRly = NULL; +#endif + + DEBUGFUNC("qmHandleRxPackets"); + + ASSERT(prSwRfbListHead); + + prReturnedQue = &rReturnedQue; + + QUEUE_INITIALIZE(prReturnedQue); + prNextSwRfb = prSwRfbListHead; + + do { + prCurrSwRfb = prNextSwRfb; + prNextSwRfb = QM_RX_GET_NEXT_SW_RFB(prCurrSwRfb); + + /* prHifRxHdr = prCurrSwRfb->prHifRxHdr; // TODO: (Tehuang) Use macro to obtain the pointer */ + prRxStatus = prCurrSwRfb->prRxStatus; + + /* 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), */ + prCurrSwRfb->ucStaRecIdx, prRxStatus->ucWlanIdx, + /* HIF_RX_HDR_GET_SN(prHifRxHdr), *//* The new SN of the frame */ + HAL_RX_STATUS_GET_TID(prRxStatus), + prCurrSwRfb->ucPacketType, prCurrSwRfb->fgReorderBuffer); + + DBGLOG_MEM8(SW4, TRACE, (PUINT_8) prCurrSwRfb->pvHeader, prCurrSwRfb->u2PacketLen); + } +#endif + + fgIsBMC = HAL_RX_STATUS_IS_BC(prRxStatus) | HAL_RX_STATUS_IS_MC(prRxStatus); + fgIsHTran = FALSE; + + if (HAL_RX_STATUS_GET_HEADER_TRAN(prRxStatus) == TRUE) { /* (!HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)){ */ + + UINT_8 ucBssIndex; + P_BSS_INFO_T prBssInfo; + UINT_8 aucTaAddr[MAC_ADDR_LEN]; + + fgIsHTran = TRUE; + pucEthDestAddr = prCurrSwRfb->pvHeader; + + if (prCurrSwRfb->prRxStatusGroup4 == NULL) { + DBGLOG(QM, ERROR, "H/W did Header Trans but prRxStatusGroup4 is NULL !!!\n"); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + DBGLOG_MEM8(QM, ERROR, (PUINT_8) prRxStatus, sizeof(*prRxStatus)); + if (prCurrSwRfb->pvHeader) + DBGLOG_MEM8(QM, ERROR, prCurrSwRfb->pvHeader, + prCurrSwRfb->u2PacketLen > 32 ? 32 : prCurrSwRfb->u2PacketLen); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP); + continue; + } + + if (prCurrSwRfb->prStaRec == NULL) { + /* Workaround WTBL Issue */ + HAL_RX_STATUS_GET_TA(prCurrSwRfb->prRxStatusGroup4, aucTaAddr); + prCurrSwRfb->ucStaRecIdx = secLookupStaRecIndexFromTA(prAdapter, aucTaAddr); + if (prCurrSwRfb->ucStaRecIdx < CFG_NUM_OF_STA_RECORD) { + prCurrSwRfb->prStaRec = + cnmGetStaRecByIndex(prAdapter, prCurrSwRfb->ucStaRecIdx); + DBGLOG(QM, TRACE, + "Re-search the staRec = %d, mac = " MACSTR ", byteCnt= %d\n", + prCurrSwRfb->ucStaRecIdx, MAC2STR(aucTaAddr), prRxStatus->u2RxByteCount); + } + + if (prCurrSwRfb->prStaRec == NULL) { + DBGLOG(QM, TRACE, "Mark NULL the Packet for no STA_REC, wlanIdx=%d\n", + prRxStatus->ucWlanIdx); + /* DBGLOG_MEM8(SW4, TRACE, (PUINT_8)prRxStatus, prRxStatus->u2RxByteCount); */ + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + continue; + } + + prCurrSwRfb->ucWlanIdx = prCurrSwRfb->prStaRec->ucWlanIndex; + GLUE_SET_PKT_BSS_IDX(prCurrSwRfb->pvPacket, + secGetBssIdxByWlanIdx(prAdapter, prCurrSwRfb->ucWlanIdx)); + } + if (prCurrSwRfb->u2PacketLen > CFG_RX_MAX_PKT_SIZE) { + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + continue; + } else { + HAL_RX_STATUS_GET_TA(prCurrSwRfb->prRxStatusGroup4, aucTaAddr); + if (kalMemCmp("\x0\x0\x0\x0\x0\x0", aucTaAddr, MAC_ADDR_LEN) == 0) { + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + continue; + } + } + + ucBssIndex = prCurrSwRfb->prStaRec->ucBssIndex; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (!IS_BSS_ACTIVE(prBssInfo)) { + DBGLOG(QM, TRACE, "Mark NULL the Packet for inactive Bss %u\n", ucBssIndex); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + continue; + } + + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + if (IS_BMCAST_MAC_ADDR(pucEthDestAddr)) { + prCurrSwRfb->eDst = RX_PKT_DESTINATION_HOST_WITH_FORWARD; + } else if (UNEQUAL_MAC_ADDR(prBssInfo->aucOwnMacAddr, pucEthDestAddr) && + bssGetClientByAddress(prBssInfo, pucEthDestAddr)) { + prCurrSwRfb->eDst = RX_PKT_DESTINATION_FORWARD; + /* TODO : need to check the dst mac is valid */ + /* If src mac is invalid, the packet will be freed in fw */ + } + } +#if CFG_SUPPORT_PASSPOINT + else if (hs20IsFrameFilterEnabled(prAdapter, prBssInfo) && + hs20IsUnsecuredFrame(prAdapter, prBssInfo, prCurrSwRfb)) { + DBGLOG(QM, WARN, + "Mark NULL the Packet for Dropped Packet %u\n", ucBssIndex); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + continue; + } +#endif /* CFG_SUPPORT_PASSPOINT */ + + } else { + UINT_16 u2FrameCtrl = 0; + P_WLAN_MAC_HEADER_T prWlanHeader = NULL; + UINT_8 aucTaAddr[MAC_ADDR_LEN]; + + prWlanHeader = (P_WLAN_MAC_HEADER_T) prCurrSwRfb->pvHeader; + u2FrameCtrl = prWlanHeader->u2FrameCtrl; + if (prCurrSwRfb->prStaRec == NULL && RXM_IS_DATA_FRAME(u2FrameCtrl)) { + /* Rx header translation */ + DBGLOG(QM, INFO, + "S/W Header Trans: FC=0x%04x GVLD=0x%x StaRecIdx=%d WlanIdx=%d PktLen=%d\n", + u2FrameCtrl, prCurrSwRfb->ucGroupVLD, + prCurrSwRfb->ucStaRecIdx, prCurrSwRfb->ucWlanIdx, prCurrSwRfb->u2PacketLen); + + /* search StaRec related info */ + kalMemCopy(aucTaAddr, prWlanHeader->aucAddr2, MAC_ADDR_LEN); /* use A2 instead */ + + prCurrSwRfb->ucStaRecIdx = secLookupStaRecIndexFromTA(prAdapter, aucTaAddr); + DBGLOG(QM, INFO, "prCurrSwRfb->ucStaRecIdx %u\n", prCurrSwRfb->ucStaRecIdx); + + if (prCurrSwRfb->ucStaRecIdx < CFG_NUM_OF_STA_RECORD) { + prCurrSwRfb->prStaRec = + cnmGetStaRecByIndex(prAdapter, prCurrSwRfb->ucStaRecIdx); + DBGLOG(QM, WARN, + "Re-search staRec=%d, mac=" MACSTR ", byteCnt=%d\n", + prCurrSwRfb->ucStaRecIdx, + MAC2STR(aucTaAddr), HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus)); + } + + if (prCurrSwRfb->prStaRec != NULL) { + UINT_16 u2MACLen = 0; + PUINT_16 pu2PktLen = &prCurrSwRfb->u2PacketLen; + + if (RXM_IS_QOS_DATA_FRAME(u2FrameCtrl)) /* QoS data, VHT */ + u2MACLen = sizeof(WLAN_MAC_HEADER_QOS_T); + else + u2MACLen = sizeof(WLAN_MAC_HEADER_T); + u2MACLen += ETH_LLC_LEN + ETH_SNAP_OUI_LEN; + u2MACLen -= ETHER_TYPE_LEN_OFFSET; + + if (*pu2PktLen <= u2MACLen) { + DBGLOG_MEM8(QM, WARN, (PUINT_8) prCurrSwRfb->pvHeader, + (*pu2PktLen > 64) ? 64 : *pu2PktLen); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + continue; + } + + prCurrSwRfb->pvHeader += u2MACLen; /* use prWlanHeader think deeply */ + + if (((u2FrameCtrl&0x0300) == 0x0100) /*to DS*/ + && (prCurrSwRfb->u2PacketLen > (sizeof(WLAN_MAC_HEADER_QOS_T) + 8)) + && (((unsigned char *)(prCurrSwRfb->pvHeader))[12] == 0x88) + && (((unsigned char *)(prCurrSwRfb->pvHeader))[13] == 0x8e)) { + + DBGLOG_MEM8(QM, WARN, (PUINT_8) prCurrSwRfb->pvHeader, + (*pu2PktLen > 120) ? 120 : *pu2PktLen); + + kalMemCopy(prCurrSwRfb->pvHeader, prWlanHeader->aucAddr3, MAC_ADDR_LEN); + kalMemCopy(prCurrSwRfb->pvHeader + MAC_ADDR_LEN, prWlanHeader->aucAddr2, + MAC_ADDR_LEN); + DBGLOG(QM, INFO, " To ds case transfer header.\n"); + } else { + kalMemCopy(prCurrSwRfb->pvHeader, prWlanHeader->aucAddr1, MAC_ADDR_LEN); + kalMemCopy(prCurrSwRfb->pvHeader + MAC_ADDR_LEN, prWlanHeader->aucAddr3, + MAC_ADDR_LEN); + DBGLOG(QM, INFO, " Old transfer header way.\n"); + } + *pu2PktLen -= u2MACLen; + + prCurrSwRfb->ucWlanIdx = prCurrSwRfb->prStaRec->ucWlanIndex; + GLUE_SET_PKT_BSS_IDX(prCurrSwRfb->pvPacket, + secGetBssIdxByWlanIdx(prAdapter, prCurrSwRfb->ucWlanIdx)); + DBGLOG_MEM8(QM, WARN, (PUINT_8) prCurrSwRfb->pvHeader, + (*pu2PktLen > 64) ? 64 : *pu2PktLen); + } + } + } + +#if CFG_SUPPORT_WAPI + /* Todo:: Move the data class error check here */ + if (prCurrSwRfb->u2PacketLen > ETHER_HEADER_LEN) { + PUINT_8 pc = (PUINT_8) prCurrSwRfb->pvHeader; + UINT_16 u2Etype = 0; + + u2Etype = (pc[ETHER_TYPE_LEN_OFFSET] << 8) | (pc[ETHER_TYPE_LEN_OFFSET + 1]); + /* + * for wapi integrity test. WPI_1x packet should be always in non-encrypted mode. + * if we received any WPI(0x88b4) packet that is encrypted, drop here. + */ + if (u2Etype == ETH_WPI_1X && + HAL_RX_STATUS_GET_SEC_MODE(prRxStatus) != 0 && + HAL_RX_STATUS_IS_CIPHER_MISMATCH(prRxStatus) == 0) { + DBGLOG(QM, INFO, "drop wpi packet with sec mode\n"); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + continue; + } + } +#endif + +#if CFG_SUPPORT_REPLAY_DETECTION + if (prCurrSwRfb->prStaRec) { + ucBssIndexRly = prCurrSwRfb->prStaRec->ucBssIndex; + prBssInfoRly = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndexRly); + if (!IS_BSS_ACTIVE(prBssInfoRly)) { + DBGLOG(QM, INFO, + "Mark NULL the Packet for inactive Bss %u\n", + ucBssIndexRly); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + continue; + } + } + if (fgIsBMC + && prBssInfoRly + && IS_BSS_AIS(prBssInfoRly) + && qmHandleRxReplay(prAdapter, prCurrSwRfb)) { + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + continue; + } +#endif + + if (prCurrSwRfb->fgReorderBuffer && !fgIsBMC && fgIsHTran) { + /* + * 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. + */ + if (prCurrSwRfb->ucTid >= CFG_RX_MAX_BA_TID_NUM) { + DBGLOG(QM, ERROR, "TID from RXD = %d, out of range !!!\n", prCurrSwRfb->ucTid); + DBGLOG_MEM8(QM, ERROR, prCurrSwRfb->pucRecvBuff, + HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus)); + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + } else + qmProcessPktWithReordering(prAdapter, prCurrSwRfb, prReturnedQue); + + } else if (prCurrSwRfb->fgDataFrame) { + /* Check Class Error */ + if (secCheckClassError(prAdapter, prCurrSwRfb, prCurrSwRfb->prStaRec) == TRUE) { + P_RX_BA_ENTRY_T prReorderQueParm = NULL; + + if ((prCurrSwRfb->ucTid < CFG_RX_MAX_BA_TID_NUM) && + !fgIsBMC && fgIsHTran && RXM_IS_QOS_DATA_FRAME( + HAL_RX_STATUS_GET_FRAME_CTL_FIELD(prCurrSwRfb->prRxStatusGroup4))) { + prReorderQueParm = + ((prCurrSwRfb->prStaRec->aprRxReorderParamRefTbl)[prCurrSwRfb->ucTid]); + } + + if (prReorderQueParm && prReorderQueParm->fgIsValid) { + /* Only QoS Data frame with BA aggrement shall enter reordering buffer */ + qmProcessPktWithReordering(prAdapter, prCurrSwRfb, prReturnedQue); + } + else + qmHandleRxPackets_AOSP_1; + } else { + DBGLOG(QM, TRACE, "Mark NULL the Packet for class error\n"); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + } + } else { + P_WLAN_MAC_HEADER_T prWlanMacHeader; + + ASSERT(prCurrSwRfb->pvHeader); + + prWlanMacHeader = (P_WLAN_MAC_HEADER_T) prCurrSwRfb->pvHeader; + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + + switch (prWlanMacHeader->u2FrameCtrl & MASK_FRAME_TYPE) { + /* BAR frame */ + case MAC_FRAME_BLOCK_ACK_REQ: + qmProcessBarFrame(prAdapter, prCurrSwRfb, prReturnedQue); + break; + default: + DBGLOG(QM, TRACE, "Mark NULL the Packet for non-interesting type\n"); + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + break; + } + } + + } while (prNextSwRfb); + + /* The returned list of SW_RFBs must end with a NULL pointer */ + if (QUEUE_IS_NOT_EMPTY(prReturnedQue)) + QM_TX_SET_NEXT_MSDU_INFO((P_SW_RFB_T) QUEUE_GET_TAIL(prReturnedQue), NULL); + + return (P_SW_RFB_T) QUEUE_GET_HEAD(prReturnedQue); + +#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_HW_MAC_RX_DESC_T prRxStatus; + P_RX_BA_ENTRY_T prReorderQueParm; + + UINT_32 u4SeqNo; + UINT_32 u4WinStart; + UINT_32 u4WinEnd; + P_QUE_T prReorderQue; + + DEBUGFUNC("qmProcessPktWithReordering"); + + ASSERT(prSwRfb); + ASSERT(prReturnedQue); + ASSERT(prSwRfb->prRxStatus); + + /* We should have STA_REC here */ + prStaRec = prSwRfb->prStaRec; + ASSERT(prStaRec); + ASSERT(prSwRfb->ucTid < CFG_RX_MAX_BA_TID_NUM); + + prRxStatus = prSwRfb->prRxStatus; + + /* Check whether the BA agreement exists */ + prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[prSwRfb->ucTid]); + if (!prReorderQueParm || !(prReorderQueParm->fgIsValid)) { /* VHT single AMPDU */ + DBGLOG(QM, TRACE, "AMPDU from STA[%d] TID[%d] without BA agreement, no-reordering\n", + prStaRec->ucIndex, prSwRfb->ucTid); + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); + return; + } + + prSwRfb->u2SSN = HAL_RX_STATUS_GET_SEQFrag_NUM(prSwRfb->prRxStatusGroup4) >> RX_STATUS_SEQ_NUM_OFFSET; + + /* Start to reorder packets */ + u4SeqNo = (UINT_32) (prSwRfb->u2SSN); + prReorderQue = &(prReorderQueParm->rReOrderQue); + u4WinStart = (UINT_32) (prReorderQueParm->u2WinStart); + u4WinEnd = (UINT_32) (prReorderQueParm->u2WinEnd); +#if CFG_RX_BA_REORDERING_ENHANCEMENT + if (prAdapter->rWifiVar.fgEnableReportIndependentPkt) { + PUINT_16 pu2RecentSsn = &prReorderQueParm->au2RecentSsn[0]; + UINT_8 i = 0; + /* Cache index for this packet */ + UINT_8 ucNewSlot = (prReorderQueParm->ucLastSlot + 1) % QM_RECENT_SSN_CACHE_NUM; + PUINT_8 pucEth = (PUINT_8)prSwRfb->pvHeader; + PUINT_8 pucEthBody = NULL; + UINT_16 u2EthType = 0; + + /* Clear SSN cache while window end was updated last time */ + for (i = 0; i < QM_RECENT_SSN_CACHE_NUM; i++) { + if (pu2RecentSsn[i] == QM_INVALID_SSN) + continue; + if (pu2RecentSsn[i] <= u4WinEnd) { + if (pu2RecentSsn[i] + HALF_SEQ_NO_COUNT < u4WinEnd) + pu2RecentSsn[i] = QM_INVALID_SSN; + } else if (pu2RecentSsn[i] < u4WinEnd + HALF_SEQ_NO_COUNT) + pu2RecentSsn[i] = QM_INVALID_SSN; + } + + if (qmIsIndependentPkt(prSwRfb)) { + /* If the sequence number equals last value, just drop it. */ + if (u4SeqNo == pu2RecentSsn[prReorderQueParm->ucLastSlot]) + i = prReorderQueParm->ucLastSlot; + else + i = 0; + if (prSwRfb->u2PacketLen > ETH_HLEN) { + pucEthBody = &pucEth[ETH_HLEN]; + u2EthType = (pucEth[ETH_TYPE_LEN_OFFSET] << 8) | pucEth[ETH_TYPE_LEN_OFFSET + 1]; + } + DBGLOG(QM, TRACE, "Cur: %d, SsnCache: %d %d %d %d %d %d %d %d %d %d\n", + u4SeqNo, + pu2RecentSsn[0], pu2RecentSsn[1], pu2RecentSsn[2], pu2RecentSsn[3], + pu2RecentSsn[4], pu2RecentSsn[5], pu2RecentSsn[6], pu2RecentSsn[7], + pu2RecentSsn[8], pu2RecentSsn[9]); + for (; i < QM_RECENT_SSN_CACHE_NUM; i++) { + if (pu2RecentSsn[i] == u4SeqNo) { + switch (u2EthType) { + case ETH_P_ARP: + DBGLOG(QM, WARN, "Drop dup arp, op %d from %pi4, Seq %u\n", + (pucEthBody[6] << 8) | pucEthBody[7], &pucEthBody[14], u4SeqNo); + break; + case ETH_P_IP: + DBGLOG(QM, WARN, "Drop dup IP, Id 0x%02x Proto %d from %pi4, Seq %u\n", + *(UINT_16 *)&pucEthBody[4], pucEthBody[9], &pucEthBody[12], + u4SeqNo); + break; + default: + DBGLOG(QM, WARN, "Drop pkt with Eth type %d, Seq %u\n", + u2EthType, u4SeqNo); + } + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); + return; + } + if (pu2RecentSsn[ucNewSlot] != QM_INVALID_SSN && pu2RecentSsn[i] == QM_INVALID_SSN) { + DBGLOG(QM, TRACE, "empty slot %d, value %d\n", i, pu2RecentSsn[i]); + ucNewSlot = i; + } + } + pu2RecentSsn[ucNewSlot] = u4SeqNo; + prReorderQueParm->ucLastSlot = ucNewSlot; + DBGLOG(QM, TRACE, "Insert independentPkt to returnedQue directly\n"); + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); + qmInsertNoNeedWaitPkt(prSwRfb, PACKET_DROP_BY_INDEPENDENT_PKT); + qmHandleNoNeedWaitPktList(prReorderQueParm); + return; + } + } +#endif + + /* 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))) { +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + qmInsertFallWithinReorderPkt(prAdapter, prSwRfb, prReorderQueParm, prReturnedQue); +#else + qmInsertFallWithinReorderPkt(prSwRfb, prReorderQueParm, prReturnedQue); +#endif + +#if QM_RX_WIN_SSN_AUTO_ADVANCING + if (prReorderQueParm->fgIsWaitingForPktWithSsn) { + /* Let the first received packet pass the reorder check */ + DBGLOG(QM, LOUD, "QM:(A)[%hhu](%u){%u,%u}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); + + prReorderQueParm->u2WinStart = (UINT_16) u4SeqNo; + prReorderQueParm->u2WinEnd = + ((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT; + prReorderQueParm->fgIsWaitingForPktWithSsn = FALSE; + } +#endif + + qmPopOutDueToFallWithin(prAdapter, 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(prAdapter, prReorderQueParm, prReturnedQue); + + } + /* Case 3: Fall behind */ + else { +#if CFG_SUPPORT_OSHARE + if (prSwRfb->u2PacketLen > ETHER_HEADER_LEN) { + + PUINT_8 pucData = (PUINT_8) prSwRfb->pvHeader; + UINT_16 u2Etype = (pucData[ETH_TYPE_LEN_OFFSET] << 8) | (pucData[ETH_TYPE_LEN_OFFSET + 1]); + UINT_8 ucBssIndex = secGetBssIdxByWlanIdx(prAdapter, prSwRfb->ucWlanIdx); + + if ((prAdapter->fgEnOshareMode) && (ucBssIndex != 0xff) && + (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType == NETWORK_TYPE_P2P)) { + if (u2Etype == ETH_P_IP) { + PUINT_8 pucEthBody = &pucData[ETH_HLEN]; + UINT_8 ucIpProto = pucEthBody[9]; + + if (ucIpProto == IP_PRO_UDP || ucIpProto == IP_PRO_TCP) { + DBGLOG(QM, LOUD, + "QM: Don't drop packet:Tid[%u]SeqNo(%u){Start%u,End%u}\n", + prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); + + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); + return; + } + } + } + } +#endif + +#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_RX_BA_ENTRY_T prReorderQueParm; + P_CTRL_BAR_FRAME_T prBarCtrlFrame; + + UINT_32 u4SSN; + UINT_32 u4WinStart; + UINT_32 u4WinEnd; + /* P_SW_RFB_T prReorderedSwRfb; */ + + ASSERT(prSwRfb); + ASSERT(prReturnedQue); + ASSERT(prSwRfb->prRxStatus); + if (prSwRfb->pvHeader == NULL) + return; + + prBarCtrlFrame = (P_CTRL_BAR_FRAME_T) prSwRfb->pvHeader; + + prSwRfb->ucTid = + (*((PUINT_16) ((PUINT_8) prBarCtrlFrame + CTRL_BAR_BAR_CONTROL_OFFSET))) >> BAR_CONTROL_TID_INFO_OFFSET; + prSwRfb->u2SSN = + (*((PUINT_16) ((PUINT_8) prBarCtrlFrame + CTRL_BAR_BAR_INFORMATION_OFFSET))) >> OFFSET_BAR_SSC_SN; + + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); + + /* Incorrect STA_REC index */ + prSwRfb->ucStaRecIdx = secLookupStaRecIndexFromTA(prAdapter, prBarCtrlFrame->aucSrcAddr); + 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 */ + prSwRfb->prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + prStaRec = prSwRfb->prStaRec; + if (prStaRec == NULL) { + /* ASSERT(prStaRec); */ + return; + } +#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); + 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)[%hhu](%u){%hu,%hu}\n", prSwRfb->ucTid, u4SSN, + prReorderQueParm->u2WinStart, prReorderQueParm->u2WinEnd); + qmPopOutDueToFallAhead(prAdapter, prReorderQueParm, prReturnedQue); + } else { + DBGLOG(QM, TRACE, "QM:(BAR)(%hhu)(%u){%u,%u}\n", prSwRfb->ucTid, u4SSN, u4WinStart, u4WinEnd); + } +} +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR +VOID qmInsertFallWithinReorderPkt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, + IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue) +#else +VOID qmInsertFallWithinReorderPkt(IN P_SW_RFB_T prSwRfb, + IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue) +#endif +{ + 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); +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + RX_INC_CNT(&prAdapter->rRxCtrl, RX_DUPICATE_DROP_COUNT); +#endif + 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_ADAPTER_T prAdapter, 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; +#if CFG_RX_BA_REORDERING_ENHANCEMENT + qmHandleNoNeedWaitPktList(prReorderQueParm); +#endif + DBGLOG(QM, TRACE, "qmPopOutDueToFallWithin SSN: %u, WS: %u, WE: %u\n", + prReorderedSwRfb->u2SSN, prReorderQueParm->u2WinStart, prReorderQueParm->u2WinEnd); + + /* 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 { + /* Start bubble timer */ + if (!prReorderQueParm->fgHasBubble) { + cnmTimerStartTimer(prAdapter, + &(prReorderQueParm->rReorderBubbleTimer), + prAdapter->u4QmRxBaMissTimeout); + prReorderQueParm->fgHasBubble = TRUE; + prReorderQueParm->u2FirstBubbleSn = prReorderQueParm->u2WinStart; + + DBGLOG(QM, TRACE, + "QM:(Bub Timer) STA[%u] TID[%u] BubSN[%u] Win{%d, %d}\n", + prReorderQueParm->ucStaRecIdx, prReorderedSwRfb->ucTid, + prReorderQueParm->u2FirstBubbleSn, + prReorderQueParm->u2WinStart, prReorderQueParm->u2WinEnd); + } + + if ((fgMissing == TRUE) && + CHECK_FOR_TIMEOUT(rCurrentTime, *prMissTimeout, + MSEC_TO_SYSTIME(prAdapter->u4QmRxBaMissTimeout))) { + 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_ADAPTER_T prAdapter, 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; +#if CFG_RX_BA_REORDERING_ENHANCEMENT + qmHandleNoNeedWaitPktList(prReorderQueParm); +#endif + DBGLOG(QM, TRACE, "qmPopOutDueToFallAhead SSN: %u, WS: %u, WE: %u\n", + prReorderedSwRfb->u2SSN, prReorderQueParm->u2WinStart, prReorderQueParm->u2WinEnd); + + /* 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 { + /* Start bubble timer */ + if (!prReorderQueParm->fgHasBubble) { + cnmTimerStartTimer(prAdapter, + &(prReorderQueParm->rReorderBubbleTimer), + prAdapter->u4QmRxBaMissTimeout); + prReorderQueParm->fgHasBubble = TRUE; + prReorderQueParm->u2FirstBubbleSn = prReorderQueParm->u2WinStart; + + DBGLOG(QM, TRACE, + "QM:(Bub Timer) STA[%u] TID[%u] BubSN[%u] Win{%d, %d}\n", + prReorderQueParm->ucStaRecIdx, prReorderedSwRfb->ucTid, + prReorderQueParm->u2FirstBubbleSn, + prReorderQueParm->u2WinStart, prReorderQueParm->u2WinEnd); + } + 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); + +} + +VOID qmHandleReorderBubbleTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr) +{ + P_RX_BA_ENTRY_T prReorderQueParm = (P_RX_BA_ENTRY_T) ulParamPtr; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; + P_EVENT_CHECK_REORDER_BUBBLE_T prCheckReorderEvent; + + KAL_SPIN_LOCK_DECLARATION(); + + if (!prReorderQueParm->fgIsValid) { + DBGLOG(QM, TRACE, "QM:(Bub Check Cancel) STA[%u] TID[%u], No Rx BA entry\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + return; + } + + if (!prReorderQueParm->fgHasBubble) { + DBGLOG(QM, TRACE, + "QM:(Bub Check Cancel) STA[%u] TID[%u], Bubble has been filled\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + return; + } + + DBGLOG(QM, TRACE, "QM:(Bub Timeout) STA[%u] TID[%u] BubSN[%u]\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid, prReorderQueParm->u2FirstBubbleSn); + + /* Generate a self-inited event to Rx path */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_REMOVE_HEAD(&prAdapter->rRxCtrl.rFreeSwRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + if (prSwRfb) { + prCheckReorderEvent = (P_EVENT_CHECK_REORDER_BUBBLE_T) prSwRfb->pucRecvBuff; + + prSwRfb->ucPacketType = RX_PKT_TYPE_SW_DEFINED; + + prSwRfb->prRxStatus->u2PktTYpe = RXM_RXD_PKT_TYPE_SW_EVENT; + + prCheckReorderEvent->ucEID = EVENT_ID_CHECK_REORDER_BUBBLE; + prCheckReorderEvent->ucSeqNum = 0; + + prCheckReorderEvent->ucStaRecIdx = prReorderQueParm->ucStaRecIdx; + prCheckReorderEvent->ucTid = prReorderQueParm->ucTid; + prCheckReorderEvent->u2Length = sizeof(EVENT_CHECK_REORDER_BUBBLE_T); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_INSERT_TAIL(&prAdapter->rRxCtrl.rReceivedRfbList, &prSwRfb->rQueEntry); + RX_INC_CNT(&prAdapter->rRxCtrl, RX_MPDU_TOTAL_COUNT); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + DBGLOG(QM, LOUD, "QM:(Bub Check Event Sent) STA[%u] TID[%u]\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + + nicRxProcessRFBs(prAdapter); + + DBGLOG(QM, LOUD, "QM:(Bub Check Event Handled) STA[%u] TID[%u]\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + } else { + DBGLOG(QM, TRACE, + "QM:(Bub Check Cancel) STA[%u] TID[%u], Bub check event alloc failed\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + + cnmTimerStartTimer(prAdapter, &(prReorderQueParm->rReorderBubbleTimer), prAdapter->u4QmRxBaMissTimeout); + + DBGLOG(QM, TRACE, "QM:(Bub Timer Restart) STA[%u] TID[%u] BubSN[%u] Win{%d, %d}\n", + prReorderQueParm->ucStaRecIdx, + prReorderQueParm->ucTid, + prReorderQueParm->u2FirstBubbleSn, + prReorderQueParm->u2WinStart, prReorderQueParm->u2WinEnd); + } + +} + +VOID qmHandleEventCheckReorderBubble(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_EVENT_CHECK_REORDER_BUBBLE_T prCheckReorderEvent = (P_EVENT_CHECK_REORDER_BUBBLE_T) prEvent; + P_RX_BA_ENTRY_T prReorderQueParm; + P_QUE_T prReorderQue; + QUE_T rReturnedQue; + P_QUE_T prReturnedQue = &rReturnedQue; + P_SW_RFB_T prReorderedSwRfb, prSwRfb; + OS_SYSTIME *prMissTimeout; + + QUEUE_INITIALIZE(prReturnedQue); + + /* Get target Rx BA entry */ + prReorderQueParm = qmLookupRxBaEntry(prAdapter, prCheckReorderEvent->ucStaRecIdx, prCheckReorderEvent->ucTid); + + /* Sanity Check */ + if (!prReorderQueParm) { + DBGLOG(QM, TRACE, "QM:(Bub Check Cancel) STA[%u] TID[%u], No Rx BA entry\n", + prCheckReorderEvent->ucStaRecIdx, prCheckReorderEvent->ucTid); + return; + } + + if (!prReorderQueParm->fgIsValid) { + DBGLOG(QM, TRACE, "QM:(Bub Check Cancel) STA[%u] TID[%u], No Rx BA entry\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + return; + } + + if (!prReorderQueParm->fgHasBubble) { + DBGLOG(QM, TRACE, + "QM:(Bub Check Cancel) STA[%u] TID[%u], Bubble has been filled\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + return; + } + + prReorderQue = &(prReorderQueParm->rReOrderQue); + + if (QUEUE_IS_EMPTY(prReorderQue)) { + prReorderQueParm->fgHasBubble = FALSE; + + DBGLOG(QM, TRACE, + "QM:(Bub Check Cancel) STA[%u] TID[%u], Bubble has been filled\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + + return; + } + + DBGLOG(QM, TRACE, "QM:(Bub Check Event Got) STA[%u] TID[%u]\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + + /* Expected bubble timeout => pop out packets before win_end */ + if (prReorderQueParm->u2FirstBubbleSn == prReorderQueParm->u2WinStart) { + + prReorderedSwRfb = (P_SW_RFB_T) QUEUE_GET_TAIL(prReorderQue); + + prReorderQueParm->u2WinStart = prReorderedSwRfb->u2SSN + 1; + prReorderQueParm->u2WinEnd = + ((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT; + + qmPopOutDueToFallAhead(prAdapter, prReorderQueParm, prReturnedQue); + + DBGLOG(QM, TRACE, "QM:(Bub Flush) STA[%u] TID[%u] BubSN[%u] Win{%d, %d}\n", + prReorderQueParm->ucStaRecIdx, + prReorderQueParm->ucTid, + prReorderQueParm->u2FirstBubbleSn, + prReorderQueParm->u2WinStart, prReorderQueParm->u2WinEnd); + + if (QUEUE_IS_NOT_EMPTY(prReturnedQue)) { + QM_TX_SET_NEXT_MSDU_INFO((P_SW_RFB_T) QUEUE_GET_TAIL(prReturnedQue), NULL); + + prSwRfb = (P_SW_RFB_T) QUEUE_GET_HEAD(prReturnedQue); + while (prSwRfb) { + DBGLOG(QM, TRACE, + "QM:(Bub Flush) STA[%u] TID[%u] Pop Out SN[%u]\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid, prSwRfb->u2SSN); + + prSwRfb = (P_SW_RFB_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prSwRfb); + } + + wlanProcessQueuedSwRfb(prAdapter, (P_SW_RFB_T) QUEUE_GET_HEAD(prReturnedQue)); + } else { + DBGLOG(QM, TRACE, "QM:(Bub Flush) STA[%u] TID[%u] Pop Out 0 packet\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + } + + prReorderQueParm->fgHasBubble = FALSE; + } + /* First bubble has been filled but others exist */ + else { + prReorderQueParm->u2FirstBubbleSn = prReorderQueParm->u2WinStart; + cnmTimerStartTimer(prAdapter, &(prReorderQueParm->rReorderBubbleTimer), prAdapter->u4QmRxBaMissTimeout); + + DBGLOG(QM, TRACE, "QM:(Bub Timer) STA[%u] TID[%u] BubSN[%u] Win{%d, %d}\n", + prReorderQueParm->ucStaRecIdx, + prReorderQueParm->ucTid, + prReorderQueParm->u2FirstBubbleSn, + prReorderQueParm->u2WinStart, prReorderQueParm->u2WinEnd); + } + + prMissTimeout = &g_arMissTimeout[prReorderQueParm->ucStaRecIdx][prReorderQueParm->ucTid]; + if (QUEUE_IS_EMPTY(prReorderQue)) { + DBGLOG(QM, TRACE, "QM:(Bub Check) Reset prMissTimeout to zero\n"); + *prMissTimeout = 0; + } else { + DBGLOG(QM, TRACE, "QM:(Bub Check) Reset prMissTimeout to current time\n"); + GET_CURRENT_SYSTIME(prMissTimeout); + } +} + +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; + } + + /* 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; + prRxBaEntry->fgHasBubble = FALSE; + prRxBaEntry->ucLastSlot = QM_RECENT_SSN_CACHE_NUM - 1; + for (i = 0; i < QM_RECENT_SSN_CACHE_NUM; i++) + prRxBaEntry->au2RecentSsn[i] = QM_INVALID_SSN; + + 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 = NULL; + 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 */ + if (ucTid < CFG_RX_MAX_BA_TID_NUM) { + 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 (prRxBaEntry->fgHasBubble) { + DBGLOG(QM, TRACE, "QM:(Bub Check Cancel) STA[%u] TID[%u], DELBA\n", + prRxBaEntry->ucStaRecIdx, prRxBaEntry->ucTid); + + cnmTimerStopTimer(prAdapter, &prRxBaEntry->rReorderBubbleTimer); + prRxBaEntry->fgHasBubble = FALSE; + } +#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 +} + +#if CFG_RX_BA_REORDERING_ENHANCEMENT +VOID qmInsertNoNeedWaitPkt(IN P_SW_RFB_T prSwRfb, IN ENUM_NO_NEED_WATIT_DROP_REASON_T eDropReason) +{ + P_RX_BA_ENTRY_T prRxBaEntry; + P_NO_NEED_WAIT_PKT_T prNoNeedWaitPkt; + + prSwRfb->u2SSN = HAL_RX_STATUS_GET_SEQFrag_NUM(prSwRfb->prRxStatusGroup4) >> RX_STATUS_SEQ_NUM_OFFSET; + prSwRfb->ucTid = (UINT_8) (HAL_RX_STATUS_GET_TID(prSwRfb->prRxStatus)); + prRxBaEntry = ((prSwRfb->prStaRec->aprRxReorderParamRefTbl)[prSwRfb->ucTid]); + + if (!(prRxBaEntry) || !(prRxBaEntry->fgIsValid)) { + DBGLOG(QM, WARN, "qmInsertNoNeedWaitPkt for a NULL ReorderQueParm, SSN:[%u], DropReason:(%d)\n", + prSwRfb->u2SSN, eDropReason); + return; + } + + prNoNeedWaitPkt = (P_NO_NEED_WAIT_PKT_T) kalMemAlloc(sizeof(NO_NEED_WAIT_PKT_T), VIR_MEM_TYPE); + if (!prNoNeedWaitPkt) { + DBGLOG(QM, ERROR, "qmInsertNoNeedWaitPkt alloc error SSN:[%d], DropReason:(%d)\n", + prSwRfb->u2SSN, eDropReason); + return; + } + + prNoNeedWaitPkt->u2SSN = prSwRfb->u2SSN; + prNoNeedWaitPkt->eDropReason = eDropReason; + DBGLOG_LIMITED(QM, INFO, "qmInsertNoNeedWaitPkt SSN:[%u], DropReason:(%d)\n", prSwRfb->u2SSN, eDropReason); + QUEUE_INSERT_TAIL(&(prRxBaEntry->rNoNeedWaitQue), (P_QUE_ENTRY_T) prNoNeedWaitPkt); +} + +VOID qmHandleEventDropByFW(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_EVENT_PACKET_DROP_BY_FW_T prDropSSNEvt = (P_EVENT_PACKET_DROP_BY_FW_T) prEvent; + P_RX_BA_ENTRY_T prRxBaEntry; + P_NO_NEED_WAIT_PKT_T prNoNeedWaitPkt; + UINT_16 u2StartSSN; + UINT_8 u1BitmapSSN; + UINT_8 u1SetCount, u1Count; + UINT_16 u2OfCount; + + u2StartSSN = QM_GET_DROP_BY_FW_SSN(prDropSSNEvt->u2StartSSN); + + /* Get target Rx BA entry */ + prRxBaEntry = qmLookupRxBaEntry(prAdapter, prDropSSNEvt->ucStaRecIdx, prDropSSNEvt->ucTid); + + /* Sanity Check */ + if (!prRxBaEntry) { + DBGLOG(QM, ERROR, "qmHandleEventDropByFW STA[%u] TID[%u], No Rx BA entry\n", + prDropSSNEvt->ucStaRecIdx, prDropSSNEvt->ucTid); + return; + } + + u2OfCount = 0; + + for (u1SetCount = 0; u1SetCount < QM_RX_MAX_FW_DROP_SSN_SIZE; u1SetCount++) { + u1BitmapSSN = prDropSSNEvt->au1BitmapSSN[u1SetCount]; + + for (u1Count = 0; u1Count < 8; u1Count++) { + if ((u1BitmapSSN & BIT(0)) == 1) { + prNoNeedWaitPkt = (P_NO_NEED_WAIT_PKT_T) kalMemAlloc(sizeof(NO_NEED_WAIT_PKT_T), + VIR_MEM_TYPE); + if (prNoNeedWaitPkt == NULL) { + DBGLOG(QM, ERROR, + "qmHandleEventDropByFW alloc error SSN:[%u], DropReason:(%d)\n", + (u2StartSSN + u2OfCount), PACKET_DROP_BY_FW); + continue; + } + prNoNeedWaitPkt->u2SSN = u2StartSSN + u2OfCount; + prNoNeedWaitPkt->eDropReason = PACKET_DROP_BY_FW; + DBGLOG(QM, INFO, "qmHandleEventDropByFW SSN:[%u], DropReason:(%d)\n", + prNoNeedWaitPkt->u2SSN, prNoNeedWaitPkt->eDropReason); + QUEUE_INSERT_TAIL(&(prRxBaEntry->rNoNeedWaitQue), (P_QUE_ENTRY_T) prNoNeedWaitPkt); + } + u1BitmapSSN >>= 1; + u2OfCount++; + } + } +} + +VOID qmHandleNoNeedWaitPktList(IN P_RX_BA_ENTRY_T prReorderQueParm) +{ + P_QUE_T prNoNeedWaitQue; + P_NO_NEED_WAIT_PKT_T prNoNeedWaitPkt; + P_NO_NEED_WAIT_PKT_T prNoNeedWaitNextPkt; + UINT_16 u2SSN, u2WinStart, u2WinEnd, u2AheadPoint; + + prNoNeedWaitQue = &(prReorderQueParm->rNoNeedWaitQue); + + if (QUEUE_IS_NOT_EMPTY(prNoNeedWaitQue)) { + prNoNeedWaitPkt = (P_NO_NEED_WAIT_PKT_T) QUEUE_GET_HEAD(prNoNeedWaitQue); + + u2WinStart = prReorderQueParm->u2WinStart; + u2WinEnd = prReorderQueParm->u2WinEnd; + + /* Remove all packets that SSN is less than WinStart */ + do { + u2SSN = prNoNeedWaitPkt->u2SSN; + prNoNeedWaitNextPkt = + (P_NO_NEED_WAIT_PKT_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prNoNeedWaitPkt); + + u2AheadPoint = u2WinStart + HALF_SEQ_NO_COUNT; + if (u2AheadPoint >= MAX_SEQ_NO_COUNT) + u2AheadPoint -= MAX_SEQ_NO_COUNT; + + if /*0: End - AheadPoint - SSN - Start :4095*/ + (((u2SSN < u2WinStart) + && (u2AheadPoint < u2SSN) + && (u2WinEnd < u2AheadPoint)) + /*0: Start - End - AheadPoint - SSN :4095*/ + || ((u2AheadPoint < u2SSN) + && (u2WinEnd < u2AheadPoint) + && (u2WinStart < u2WinEnd)) + /*0: SSN - Start - End - AheadPhoint :4095*/ + || ((u2WinEnd < u2AheadPoint) + && (u2WinStart < u2WinEnd) + && (u2SSN < u2WinStart)) + /*0: AheadPoint - SSN - Start - End :4095*/ + || ((u2WinStart < u2WinEnd) + && (u2SSN < u2WinStart) + && (u2AheadPoint < u2SSN))) { + + QUEUE_REMOVE_HEAD(prNoNeedWaitQue, prNoNeedWaitPkt, P_NO_NEED_WAIT_PKT_T); + kalMemFree(prNoNeedWaitPkt, VIR_MEM_TYPE, sizeof(NO_NEED_WAIT_PKT_T)); + + DBGLOG(QM, TRACE, "qmHandleNoNeedWaitPktList Remove SSN:[%u], WS:%u, WE:%u\n", + u2SSN, u2WinStart, u2WinEnd); + } + + prNoNeedWaitPkt = prNoNeedWaitNextPkt; + } while (prNoNeedWaitPkt); + + /* Adjust WinStart if current WinStart is contain in NoNeedWaitQue */ + while ((prNoNeedWaitPkt = qmSearchNoNeedWaitPktBySSN(prReorderQueParm, prReorderQueParm->u2WinStart)) + != NULL) { + prReorderQueParm->u2WinStart = (((prNoNeedWaitPkt->u2SSN) + 1) % MAX_SEQ_NO_COUNT); + prReorderQueParm->u2WinEnd = + (((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT); + QUEUE_REMOVE_HEAD(prNoNeedWaitQue, prNoNeedWaitPkt, P_NO_NEED_WAIT_PKT_T); + kalMemFree(prNoNeedWaitPkt, VIR_MEM_TYPE, sizeof(NO_NEED_WAIT_PKT_T)); + } + } +} + +P_NO_NEED_WAIT_PKT_T qmSearchNoNeedWaitPktBySSN(IN P_RX_BA_ENTRY_T prReorderQueParm, IN UINT_32 u2SSN) +{ + P_QUE_T prNoNeedWaitQue = NULL; + P_NO_NEED_WAIT_PKT_T prNoNeedWaitPkt = NULL; + + prNoNeedWaitQue = &(prReorderQueParm->rNoNeedWaitQue); + + if (QUEUE_IS_NOT_EMPTY(prNoNeedWaitQue)) { + prNoNeedWaitPkt = (P_NO_NEED_WAIT_PKT_T) QUEUE_GET_HEAD(prNoNeedWaitQue); + + do { + if (prNoNeedWaitPkt->u2SSN == u2SSN) + return prNoNeedWaitPkt; + + prNoNeedWaitPkt = (P_NO_NEED_WAIT_PKT_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prNoNeedWaitPkt); + } while (prNoNeedWaitPkt); + } + + return NULL; +} + +VOID qmRemoveAllNoNeedWaitPkt(IN P_RX_BA_ENTRY_T prReorderQueParm) +{ + P_QUE_T prNoNeedWaitQue; + P_NO_NEED_WAIT_PKT_T prNoNeedWaitPkt; + P_NO_NEED_WAIT_PKT_T prNoNeedWaitNextPkt; + + prNoNeedWaitQue = &(prReorderQueParm->rNoNeedWaitQue); + + if (QUEUE_IS_NOT_EMPTY(prNoNeedWaitQue)) { + prNoNeedWaitPkt = (P_NO_NEED_WAIT_PKT_T) QUEUE_GET_HEAD(prNoNeedWaitQue); + + do { + prNoNeedWaitNextPkt = + (P_NO_NEED_WAIT_PKT_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prNoNeedWaitPkt); + QUEUE_REMOVE_HEAD(prNoNeedWaitQue, prNoNeedWaitPkt, P_NO_NEED_WAIT_PKT_T); + kalMemFree(prNoNeedWaitPkt, VIR_MEM_TYPE, sizeof(NO_NEED_WAIT_PKT_T)); + prNoNeedWaitPkt = prNoNeedWaitNextPkt; + } while (prNoNeedWaitNextPkt); + } +} + +VOID qmDumpNoNeedWaitPkt(IN P_RX_BA_ENTRY_T prReorderQueParm) +{ + P_QUE_T prNoNeedWaitQue; + P_NO_NEED_WAIT_PKT_T prNoNeedWaitPkt; + + prNoNeedWaitQue = &(prReorderQueParm->rNoNeedWaitQue); + + if (QUEUE_IS_NOT_EMPTY(prNoNeedWaitQue)) { + prNoNeedWaitPkt = (P_NO_NEED_WAIT_PKT_T) QUEUE_GET_HEAD(prNoNeedWaitQue); + + do { + DBGLOG(QM, INFO, "qmDumpNoNeedWaitPkt > SSN:[%u] DropReason:(%d)\n", + prNoNeedWaitPkt->u2SSN, prNoNeedWaitPkt->eDropReason); + prNoNeedWaitPkt = (P_NO_NEED_WAIT_PKT_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prNoNeedWaitPkt); + } while (prNoNeedWaitPkt); + } else + DBGLOG(QM, INFO, "qmDumpNoNeedWaitPkt > QUEUE EMPTY\n"); +} + +BOOLEAN qmIsIndependentPkt(IN P_SW_RFB_T prSwRfb) +{ + struct sk_buff *skb = NULL; + + if (prSwRfb->u2PacketLen <= ETHER_HEADER_LEN) + return FALSE; + + skb = (struct sk_buff *)(prSwRfb->pvPacket); + if (!skb) + return FALSE; + + if (GLUE_GET_INDEPENDENT_PKT(skb)) + return TRUE; + + return FALSE; +} +#endif + +VOID mqmParseAssocReqWmmIe(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucIE, IN P_STA_RECORD_T prStaRec) +{ + P_IE_WMM_INFO_T prIeWmmInfo; + UINT_8 ucQosInfo; + UINT_8 ucQosInfoAC; + UINT_8 ucBmpAC; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + + if ((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) && (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) { + + switch (WMM_IE_OUI_SUBTYPE(pucIE)) { + case VENDOR_OUI_SUBTYPE_WMM_INFO: + if (IE_LEN(pucIE) != 7) + break; /* WMM Info IE with a wrong length */ + + + prStaRec->fgIsQoS = TRUE; + prStaRec->fgIsWmmSupported = TRUE; + + prIeWmmInfo = (P_IE_WMM_INFO_T) pucIE; + ucQosInfo = prIeWmmInfo->ucQosInfo; + ucQosInfoAC = ucQosInfo & BITS(0, 3); + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucUapsd)) + prStaRec->fgIsUapsdSupported = (ucQosInfoAC) ? TRUE : FALSE; + else + prStaRec->fgIsUapsdSupported = FALSE; + + 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; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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; + UINT_32 u4Flags; + + 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; + + /* If the device does not support QoS or if WMM is not supported by the peer, exit. */ + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS)) + return; + + /* Determine whether QoS is enabled with the association */ + else { + prStaRec->u4Flags = 0; + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_VENDOR: + mqmParseAssocReqWmmIe(prAdapter, pucIE, prStaRec); + +#if CFG_SUPPORT_MTK_SYNERGY + if (rlmParseCheckMTKOuiIE(prAdapter, pucIE, &u4Flags)) + prStaRec->u4Flags = u4Flags; +#endif + + 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); + + } +} + +VOID mqmParseAssocRspWmmIe(IN PUINT_8 pucIE, IN P_STA_RECORD_T prStaRec) +{ + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + + if ((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) && (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) { + P_IE_WMM_PARAM_T prWmmParam = (P_IE_WMM_PARAM_T) pucIE; + ENUM_ACI_T eAci; + + 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; + prStaRec->fgIsUapsdSupported = !!(prWmmParam->ucQosInfo & WMM_QOS_INFO_UAPSD); + for (eAci = ACI_BE; eAci < ACI_NUM; eAci++) + prStaRec->afgAcmRequired[eAci] = + !!(prWmmParam->arAcParam[eAci].ucAciAifsn & WMM_ACIAIFSN_ACM); + DBGLOG(WMM, INFO, "WMM: "MACSTR "ACM BK=%d BE=%d VI=%d VO=%d\n", + MAC2STR(prStaRec->aucMacAddr), + prStaRec->afgAcmRequired[ACI_BK], + prStaRec->afgAcmRequired[ACI_BE], + prStaRec->afgAcmRequired[ACI_VI], + prStaRec->afgAcmRequired[ACI_VO]); + 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; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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_32 u4Flags; + + 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.ucQoS); + + /* If the device does not support QoS or if WMM is not supported by the peer, exit. */ + /* if((!prAdapter->rWifiVar.fgSupportQoS) || (!prStaRec->fgIsWmmSupported)) */ + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS)) + return; + + /* Determine whether QoS is enabled with the association */ + else { + prStaRec->u4Flags = 0; + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_VENDOR: + /* Process WMM related IE */ + mqmParseAssocRspWmmIe(pucIE, prStaRec); + +#if CFG_SUPPORT_MTK_SYNERGY + if (rlmParseCheckMTKOuiIE(prAdapter, pucIE, &u4Flags)) + prStaRec->u4Flags = u4Flags; +#endif + + 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; +#if DSCP_SUPPORT + case ELEM_ID_QOS_MAP_SET: + DBGLOG(QM, WARN, "QM: received assoc resp qosmapset ie\n"); + qosParseQosMapSet(prAdapter, prStaRec, pucIE); + break; +#endif + default: + break; + } + } + + /* Parse AC parameters and write to HW CRs */ + if ((prStaRec->fgIsQoS) && (prStaRec->eStaType == STA_TYPE_LEGACY_AP)) { + mqmParseEdcaParameters(prAdapter, prSwRfb, pucIEStart, u2IELength, TRUE); +#if ARP_MONITER_ENABLE + qmResetArpDetect(); +#endif + } + DBGLOG(QM, TRACE, "MQM: Assoc_Rsp Parsing (QoS Enabled=%d)\n", prStaRec->fgIsQoS); + if (prStaRec->fgIsWmmSupported) + nicQmUpdateWmmParms(prAdapter, prStaRec->ucBssIndex); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mqmProcessBcn(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength) +{ + P_BSS_INFO_T prBssInfo; + BOOLEAN fgNewParameter; + UINT_8 i; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + ASSERT(pucIE); + + DBGLOG(QM, TRACE, "Enter %s\n", __func__); + + fgNewParameter = FALSE; + + for (i = 0; i < BSS_INFO_NUM; i++) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, i); + + 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 = mqmParseEdcaParameters(prAdapter, + prSwRfb, pucIE, u2IELength, FALSE); + } + } + + /* Appy new parameters if necessary */ + if (fgNewParameter) { + /* DBGLOG(QM, INFO, ("Update EDCA parameter for BSS[%u]\n", prBssInfo->ucBssIndex)); */ + nicQmUpdateWmmParms(prAdapter, prBssInfo->ucBssIndex); + fgNewParameter = FALSE; + } + } /* end of IS_BSS_ACTIVE() */ + } +} + +BOOLEAN mqmUpdateEdcaParameters(IN P_BSS_INFO_T prBssInfo, IN PUINT_8 pucIE, IN BOOLEAN fgForceOverride) +{ + P_AC_QUE_PARMS_T prAcQueParams; + P_IE_WMM_PARAM_T prIeWmmParam; + ENUM_WMM_ACI_T eAci; + BOOLEAN fgNewParameter = FALSE; + + do { + if (IE_LEN(pucIE) != 24) + break; /* WMM Param IE with a wrong length */ + + prIeWmmParam = (P_IE_WMM_PARAM_T) pucIE; + + /* Check the Parameter Set Count to determine whether EDCA parameters have been changed */ + if (!fgForceOverride) { + if (mqmCompareEdcaParameters(prIeWmmParam, prBssInfo)) { + fgNewParameter = FALSE; + break; + } + } + + fgNewParameter = TRUE; + /* Update Parameter Set Count */ + prBssInfo->ucWmmParamSetCount = (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); + } + DBGLOG(QM, INFO, + "BSS[%u]: ACM[%d,%d,%d,%d] Aifsn[%d,%d,%d,%d] CWmin/max[%d,%d;%d,%d;%d,%d;%d,%d] Txop[%d,%d,%d,%d]\n", + prBssInfo->ucBssIndex, + prBssInfo->arACQueParms[0].ucIsACMSet, prBssInfo->arACQueParms[1].ucIsACMSet, + prBssInfo->arACQueParms[2].ucIsACMSet, prBssInfo->arACQueParms[3].ucIsACMSet, + prBssInfo->arACQueParms[0].u2Aifsn, prBssInfo->arACQueParms[1].u2Aifsn, + prBssInfo->arACQueParms[2].u2Aifsn, prBssInfo->arACQueParms[3].u2Aifsn, + prBssInfo->arACQueParms[0].u2CWmin, prBssInfo->arACQueParms[0].u2CWmax, + prBssInfo->arACQueParms[1].u2CWmin, prBssInfo->arACQueParms[1].u2CWmax, + prBssInfo->arACQueParms[2].u2CWmin, prBssInfo->arACQueParms[2].u2CWmax, + prBssInfo->arACQueParms[3].u2CWmin, prBssInfo->arACQueParms[3].u2CWmax, + prBssInfo->arACQueParms[0].u2TxopLimit, prBssInfo->arACQueParms[1].u2TxopLimit, + prBssInfo->arACQueParms[2].u2TxopLimit, prBssInfo->arACQueParms[3].u2TxopLimit); + } while (FALSE); + + return fgNewParameter; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +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; + BOOLEAN fgNewParameter = FALSE; + + DEBUGFUNC("mqmParseEdcaParameters"); + + if (!prSwRfb) + return FALSE; + + if (!pucIE) + return FALSE; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + /* ASSERT(prStaRec); */ + + if (prStaRec == NULL) + return FALSE; + + DBGLOG(QM, TRACE, "QM: (fgIsWmmSupported=%d, fgIsQoS=%d)\n", prStaRec->fgIsWmmSupported, prStaRec->fgIsQoS); + + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS) || (!prStaRec->fgIsWmmSupported) + || (!prStaRec->fgIsQoS)) + return FALSE; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + /* Goal: Obtain the EDCA parameters */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_WMM: + if (!((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) && + (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3)))) + break; + + switch (WMM_IE_OUI_SUBTYPE(pucIE)) { + case VENDOR_OUI_SUBTYPE_WMM_PARAM: + fgNewParameter = mqmUpdateEdcaParameters(prBssInfo, pucIE, fgForceOverride); + break; + + default: + /* Other WMM QoS IEs. Ignore */ + break; + } + + /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS, ... (not cared) */ + break; + default: + break; + } + } + + return fgNewParameter; +} + +BOOLEAN mqmCompareEdcaParameters(IN P_IE_WMM_PARAM_T prIeWmmParam, IN P_BSS_INFO_T prBssInfo) +{ + P_AC_QUE_PARMS_T prAcQueParams; + P_WMM_AC_PARAM_T prWmmAcParams; + ENUM_WMM_ACI_T eAci; + + /* return FALSE; */ + + /* Check Set Count */ + if (prBssInfo->ucWmmParamSetCount != (prIeWmmParam->ucQosInfo & WMM_QOS_INFO_PARAM_SET_CNT)) + return FALSE; + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prAcQueParams = &prBssInfo->arACQueParms[eAci]; + prWmmAcParams = &prIeWmmParam->arAcParam[eAci]; + + /* ACM */ + if (prAcQueParams->ucIsACMSet != ((prWmmAcParams->ucAciAifsn & WMM_ACIAIFSN_ACM) ? TRUE : FALSE)) + return FALSE; + + /* AIFSN */ + if (prAcQueParams->u2Aifsn != (prWmmAcParams->ucAciAifsn & WMM_ACIAIFSN_AIFSN)) + return FALSE; + + /* CW Max */ + if (prAcQueParams->u2CWmax != + (BIT((prWmmAcParams->ucEcw & WMM_ECW_WMAX_MASK) >> WMM_ECW_WMAX_OFFSET) - 1)) + return FALSE; + + /* CW Min */ + if (prAcQueParams->u2CWmin != (BIT(prWmmAcParams->ucEcw & WMM_ECW_WMIN_MASK) - 1)) + return FALSE; + + if (prAcQueParams->u2TxopLimit != prWmmAcParams->u2TxopLimit) + return FALSE; + } + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ + P_WMM_AC_PARAM_T prAcParam = &prIeWmmParam->arAcParam[u4AcOffset]; + + prAcQueParams->ucIsACMSet = (prAcParam->ucAciAifsn & WMM_ACIAIFSN_ACM) ? TRUE : FALSE; + + prAcQueParams->u2Aifsn = (prAcParam->ucAciAifsn & WMM_ACIAIFSN_AIFSN); + + prAcQueParams->u2CWmax = BIT((prAcParam->ucEcw & WMM_ECW_WMAX_MASK) >> WMM_ECW_WMAX_OFFSET) - 1; + + prAcQueParams->u2CWmin = BIT(prAcParam->ucEcw & WMM_ECW_WMIN_MASK) - 1; + + WLAN_GET_FIELD_16(&prAcParam->u2TxopLimit, &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; + BOOLEAN fgIsHtVht; + + DEBUGFUNC("mqmProcessScanResult"); + + ASSERT(prScanResult); + ASSERT(prStaRec); + + /* Reset the flag before parsing */ + prStaRec->fgIsWmmSupported = FALSE; + prStaRec->fgIsUapsdSupported = FALSE; + prStaRec->fgIsQoS = FALSE; + + fgIsHtVht = FALSE; + + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS)) + return; + + u2IELength = prScanResult->u2IELength; + pucIE = prScanResult->aucIEBuf; + + /* <1> Determine whether the peer supports WMM/QoS and UAPSDU */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + + case ELEM_ID_EXTENDED_CAP: +#if CFG_SUPPORT_TDLS + TdlsBssExtCapParse(prStaRec, pucIE); +#endif /* CFG_SUPPORT_TDLS */ +#if CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT + prStaRec->fgSupportBTM = !!((*(PUINT_32)(pucIE+2)) & BIT(ELEM_EXT_CAP_BSS_TRANSITION_BIT)); +#endif + break; + + case ELEM_ID_WMM: + if ((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) && + (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) { + P_IE_WMM_PARAM_T prWmmParam = (P_IE_WMM_PARAM_T) pucIE; + ENUM_ACI_T eAci; + + switch (WMM_IE_OUI_SUBTYPE(pucIE)) { + case VENDOR_OUI_SUBTYPE_WMM_PARAM: + if (IE_LEN(pucIE) != 24) + break; /* WMM Param IE with a wrong length */ + prStaRec->fgIsWmmSupported = TRUE; + prStaRec->fgIsUapsdSupported = !!(prWmmParam->ucQosInfo & WMM_QOS_INFO_UAPSD); + for (eAci = ACI_BE; eAci < ACI_NUM; eAci++) + prStaRec->afgAcmRequired[eAci] = + !!(prWmmParam->arAcParam[eAci].ucAciAifsn & WMM_ACIAIFSN_ACM); + DBGLOG(WMM, INFO, "WMM: "MACSTR "ACM BK=%d BE=%d VI=%d VO=%d\n", + MAC2STR(prStaRec->aucMacAddr), + prStaRec->afgAcmRequired[ACI_BK], + prStaRec->afgAcmRequired[ACI_BE], + prStaRec->afgAcmRequired[ACI_VI], + prStaRec->afgAcmRequired[ACI_VO]); + break; + + case VENDOR_OUI_SUBTYPE_WMM_INFO: + if (IE_LEN(pucIE) != 7) + break; /* WMM Info IE with a wrong length */ + + prStaRec->fgIsWmmSupported = TRUE; + prStaRec->fgIsUapsdSupported = + (((((P_IE_WMM_INFO_T) pucIE)->ucQosInfo) & WMM_QOS_INFO_UAPSD) ? + TRUE : FALSE); + break; + + default: + /* A WMM QoS IE that doesn't matter. Ignore it. */ + break; + } + } + /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS, ... (not cared) */ + + break; + + default: + /* A WMM IE that doesn't matter. Ignore it. */ + break; + } + } + + /* <1> Determine QoS */ + if (prStaRec->ucDesiredPhyTypeSet & (PHY_TYPE_SET_802_11N | PHY_TYPE_SET_802_11AC)) + fgIsHtVht = TRUE; + + if (fgIsHtVht || prStaRec->fgIsWmmSupported) + prStaRec->fgIsQoS = TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Generate the WMM Info IE by Param +* +* \param[in] prAdapter Adapter pointer +* @param prMsduInfo The TX MMPDU +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +mqmFillWmmInfoIE(P_UINT_8 pucOutBuf, + BOOLEAN fgSupportUAPSD, UINT_8 ucBmpDeliveryAC, UINT_8 ucBmpTriggerAC, UINT_8 ucUapsdSp) +{ + P_IE_WMM_INFO_T prIeWmmInfo; + UINT_32 ucUapsd[] = { + WMM_QOS_INFO_BE_UAPSD, + WMM_QOS_INFO_BK_UAPSD, + WMM_QOS_INFO_VI_UAPSD, + WMM_QOS_INFO_VO_UAPSD + }; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + + ASSERT(pucOutBuf); + + prIeWmmInfo = (P_IE_WMM_INFO_T) pucOutBuf; + + prIeWmmInfo->ucId = ELEM_ID_WMM; + prIeWmmInfo->ucLength = ELEM_MAX_LEN_WMM_INFO; + + /* WMM-2.2.1 WMM Information Element Field Values */ + prIeWmmInfo->aucOui[0] = aucWfaOui[0]; + prIeWmmInfo->aucOui[1] = aucWfaOui[1]; + prIeWmmInfo->aucOui[2] = aucWfaOui[2]; + prIeWmmInfo->ucOuiType = VENDOR_OUI_TYPE_WMM; + prIeWmmInfo->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_INFO; + + prIeWmmInfo->ucVersion = VERSION_WMM; + prIeWmmInfo->ucQosInfo = 0; + + /* UAPSD initial queue configurations (delivery and trigger enabled) */ + if (fgSupportUAPSD) { + UINT_8 ucQosInfo = 0; + UINT_8 i; + + /* Static U-APSD setting */ + for (i = ACI_BE; i <= ACI_VO; i++) { + if (ucBmpDeliveryAC & ucBmpTriggerAC & BIT(i)) + ucQosInfo |= (UINT_8) ucUapsd[i]; + } + + if (ucBmpDeliveryAC & ucBmpTriggerAC) { + switch (ucUapsdSp) { + case WMM_MAX_SP_LENGTH_ALL: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_ALL; + break; + + case WMM_MAX_SP_LENGTH_2: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_2; + break; + + case WMM_MAX_SP_LENGTH_4: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_4; + break; + + case WMM_MAX_SP_LENGTH_6: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_6; + break; + + default: + DBGLOG(QM, 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. */ + return IE_SIZE(prIeWmmInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Generate the WMM Info IE +* +* \param[in] prAdapter Adapter pointer +* @param prMsduInfo The TX MMPDU +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +mqmGenerateWmmInfoIEByStaRec(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_STA_RECORD_T prStaRec, P_UINT_8 pucOutBuf) +{ + P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo; + BOOLEAN fgSupportUapsd; + + ASSERT(pucOutBuf); + + /* In case QoS is not turned off, exit directly */ + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS)) + return 0; + + if (prStaRec == NULL) + return 0; + + if (!prStaRec->fgIsQoS) + return 0; + + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + + fgSupportUapsd = (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucUapsd) + && prStaRec->fgIsUapsdSupported); + + return mqmFillWmmInfoIE(pucOutBuf, + fgSupportUapsd, + prPmProfSetupInfo->ucBmpDeliveryAC, + prPmProfSetupInfo->ucBmpTriggerAC, prPmProfSetupInfo->ucUapsdSp); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + UINT_32 u4Length; + + DEBUGFUNC("mqmGenerateWmmInfoIE"); + + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + if (prStaRec == NULL) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + u4Length = mqmGenerateWmmInfoIEByStaRec(prAdapter, + prBssInfo, + prStaRec, ((PUINT_8) prMsduInfo->prPacket + prMsduInfo->u2FrameLength)); + + prMsduInfo->u2FrameLength += u4Length; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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; + P_WMM_AC_PARAM_T prAcParam; + + DEBUGFUNC("mqmGenerateWmmParamIE"); + DBGLOG(QM, LOUD, "\n"); + + ASSERT(prMsduInfo); + + /* In case QoS is not turned off, exit directly */ + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS)) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (prStaRec) { + if (!prStaRec->fgIsQoS) + return; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + + if (!prBssInfo->fgIsQBSS) + return; + + 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 initial queue configurations (delivery and trigger enabled) */ + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucUapsd)) + prIeWmmParam->ucQosInfo |= WMM_QOS_INFO_UAPSD; + + /* EDCA parameter */ + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prAcParam = &prIeWmmParam->arAcParam[eAci]; + + /* DBGLOG(QM, LOUD, ("MQM: eAci=%d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", */ + /* eAci,prBssInfo->arACQueParmsForBcast[eAci].ucIsACMSet , */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn, */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmin, */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmax, */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit)); */ + + /* ACI */ + prAcParam->ucAciAifsn = aucACI[eAci]; + /* ACM */ + if (prBssInfo->arACQueParmsForBcast[eAci].ucIsACMSet) + prAcParam->ucAciAifsn |= WMM_ACIAIFSN_ACM; + /* AIFSN */ + prAcParam->ucAciAifsn |= (prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn & WMM_ACIAIFSN_AIFSN); + + /* ECW Min */ + prAcParam->ucEcw = (prBssInfo->aucCWminLog2ForBcast[eAci] & WMM_ECW_WMIN_MASK); + /* ECW Max */ + prAcParam->ucEcw |= + ((prBssInfo->aucCWmaxLog2ForBcast[eAci] << WMM_ECW_WMAX_OFFSET) & WMM_ECW_WMAX_MASK); + + /* Txop limit */ + WLAN_SET_FIELD_16(&prAcParam->u2TxopLimit, prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit); + + } + + /* Increment the total IE length for the Element ID and Length fields. */ + prMsduInfo->u2FrameLength += IE_SIZE(prIeWmmParam); + +} + +#if CFG_SUPPORT_TDLS +/*----------------------------------------------------------------------------*/ +/*! +* @brief Generate the WMM Param IE +* +* \param[in] prAdapter Adapter pointer +* @param prMsduInfo The TX MMPDU +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 mqmGenerateWmmParamIEByParam(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, PUINT_8 pOutBuf) +{ + P_IE_WMM_PARAM_T prIeWmmParam; + + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + + UINT_8 aucACI[] = { + WMM_ACI_AC_BE, + WMM_ACI_AC_BK, + WMM_ACI_AC_VI, + WMM_ACI_AC_VO + }; + + ENUM_WMM_ACI_T eAci; + P_WMM_AC_PARAM_T prAcParam; + + DEBUGFUNC("mqmGenerateWmmParamIE"); + DBGLOG(QM, LOUD, "\n"); + + ASSERT(pOutBuf); + + /* In case QoS is not turned off, exit directly */ + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS)) + return WLAN_STATUS_SUCCESS; + + if (!prBssInfo->fgIsQBSS) + return WLAN_STATUS_SUCCESS; + + prIeWmmParam = (P_IE_WMM_PARAM_T) pOutBuf; + + prIeWmmParam->ucId = ELEM_ID_WMM; + prIeWmmParam->ucLength = ELEM_MAX_LEN_WMM_PARAM; + + /* WMM-2.2.1 WMM Information Element Field Values */ + prIeWmmParam->aucOui[0] = aucWfaOui[0]; + prIeWmmParam->aucOui[1] = aucWfaOui[1]; + prIeWmmParam->aucOui[2] = aucWfaOui[2]; + prIeWmmParam->ucOuiType = VENDOR_OUI_TYPE_WMM; + prIeWmmParam->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_PARAM; + + prIeWmmParam->ucVersion = VERSION_WMM; + prIeWmmParam->ucQosInfo = (prBssInfo->ucWmmParamSetCount & WMM_QOS_INFO_PARAM_SET_CNT); + + /* UAPSD initial queue configurations (delivery and trigger enabled) */ + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucUapsd)) + prIeWmmParam->ucQosInfo |= WMM_QOS_INFO_UAPSD; + + /* EDCA parameter */ + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prAcParam = &prIeWmmParam->arAcParam[eAci]; + + /* DBGLOG(QM, LOUD, ("MQM: eAci=%d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", */ + /* eAci,prBssInfo->arACQueParmsForBcast[eAci].ucIsACMSet , */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn, */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmin, */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmax, */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit)); */ + + /* ACI */ + prAcParam->ucAciAifsn = aucACI[eAci]; + /* ACM */ + if (prBssInfo->arACQueParmsForBcast[eAci].ucIsACMSet) + prAcParam->ucAciAifsn |= WMM_ACIAIFSN_ACM; + /* AIFSN */ + prAcParam->ucAciAifsn |= (prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn & WMM_ACIAIFSN_AIFSN); + + /* ECW Min */ + prAcParam->ucEcw = (prBssInfo->aucCWminLog2ForBcast[eAci] & WMM_ECW_WMIN_MASK); + /* ECW Max */ + prAcParam->ucEcw |= + ((prBssInfo->aucCWmaxLog2ForBcast[eAci] << WMM_ECW_WMAX_OFFSET) & WMM_ECW_WMAX_MASK); + + /* Txop limit */ + WLAN_SET_FIELD_16(&prAcParam->u2TxopLimit, prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit); + + } + + /* Increment the total IE length for the Element ID and Length fields. */ + return IE_SIZE(prIeWmmParam); + +} + +#endif + +ENUM_FRAME_ACTION_T +qmGetFrameAction(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, + IN UINT_8 ucStaRecIdx, IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_FRAME_TYPE_IN_CMD_Q_T eFrameType, IN UINT_16 u2FrameLength) +{ + ENUM_FRAME_ACTION_T eFrameAction = FRAME_ACTION_TX_PKT; + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + UINT_8 ucTC = nicTxGetFrameResourceType(eFrameType, prMsduInfo); + UINT_16 u2FreeResource = nicTxGetResource(prAdapter, ucTC); + UINT_8 ucReqResource; + P_WIFI_VAR_T prWifiVar = &prAdapter->rWifiVar; + + DEBUGFUNC("qmGetFrameAction"); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + prStaRec = (ucStaRecIdx < CFG_STA_REC_NUM) ? &prAdapter->arStaRec[ucStaRecIdx] : NULL; + + do { + /* 4 <1> Tx, if FORCE_TX is set */ + if (prMsduInfo) { + if (prMsduInfo->ucControlFlag & MSDU_CONTROL_FLAG_FORCE_TX) { + eFrameAction = FRAME_ACTION_TX_PKT; + break; + } + } + /* 4 <2> Drop, if BSS is inactive */ + if (!IS_BSS_ACTIVE(prBssInfo)) { + DBGLOG(QM, TRACE, "Drop packets (BSS[%u] is INACTIVE)\n", prBssInfo->ucBssIndex); + eFrameAction = FRAME_ACTION_DROP_PKT; + break; + } + /* 4 <3> Check based on StaRec */ + if (prStaRec) { + /* 4 <3.1> Drop, if StaRec is not in use */ + if (!prStaRec->fgIsInUse) { + DBGLOG(QM, TRACE, "Drop packets (Sta[%u] not in USE)\n", prStaRec->ucIndex); + eFrameAction = FRAME_ACTION_DROP_PKT; + break; + } + /* 4 <3.2> Sta in PS */ + if (prStaRec->fgIsInPS) { + ucReqResource = nicTxGetPageCount(u2FrameLength, FALSE) + + prWifiVar->ucCmdRsvResource + QM_MGMT_QUEUED_THRESHOLD; + + /* 4 <3.2.1> Tx, if resource is enough */ + if (u2FreeResource >= ucReqResource) { + eFrameAction = FRAME_ACTION_TX_PKT; + break; + } + /* 4 <3.2.2> Queue, if resource is not enough */ + else { + DBGLOG(QM, INFO, "Queue packets (Sta[%u] in PS)\n", prStaRec->ucIndex); + eFrameAction = FRAME_ACTION_QUEUE_PKT; + break; + } + } + } + /* 4 <4> Queue, if BSS is absent */ + if (prBssInfo->fgIsNetAbsent) { + DBGLOG(QM, TRACE, "Queue packets (BSS[%u] Absent)\n", prBssInfo->ucBssIndex); + eFrameAction = FRAME_ACTION_QUEUE_PKT; + break; + } + + /* <5> Reserve resource for CMD & 1X */ + if (eFrameType == FRAME_TYPE_MMPDU) { + ucReqResource = nicTxGetPageCount(u2FrameLength, FALSE) + prWifiVar->ucCmdRsvResource; + + if (u2FreeResource < ucReqResource) { + eFrameAction = FRAME_ACTION_QUEUE_PKT; + DBGLOG(QM, INFO, "Queue MGMT (MSDU[0x%p] Req/Rsv/Free[%u/%u/%u])\n", + prMsduInfo, + nicTxGetPageCount(u2FrameLength, FALSE), + prWifiVar->ucCmdRsvResource, u2FreeResource); + } + } + } while (FALSE); + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + /* <6> Timeout check! */ + if (eFrameType == FRAME_TYPE_MMPDU) { + if ((eFrameAction == FRAME_ACTION_QUEUE_PKT) && prMsduInfo) { + OS_SYSTIME rCurrentTime, rEnqTime; + + GET_CURRENT_SYSTIME(&rCurrentTime); + rEnqTime = prMsduInfo->rPktProfile.rEnqueueTimestamp; + + if (CHECK_FOR_TIMEOUT(rCurrentTime, rEnqTime, + MSEC_TO_SYSTIME(prWifiVar->u4MgmtQueueDelayTimeout))) { + eFrameAction = FRAME_ACTION_DROP_PKT; + DBGLOG(QM, INFO, "Drop MGMT (MSDU[0x%p] timeout[%ums])\n", + prMsduInfo, prWifiVar->u4MgmtQueueDelayTimeout); + } + } + } +#endif + + return eFrameAction; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 = GET_BSS_INFO_BY_INDEX(prAdapter, prEventBssStatus->ucBssIndex); + fgIsNetAbsentOld = prBssInfo->fgIsNetAbsent; + prBssInfo->fgIsNetAbsent = prEventBssStatus->ucIsAbsent; + prBssInfo->ucBssFreeQuota = prEventBssStatus->ucBssFreeQuota; + + /* DBGLOG(QM, TRACE, ("qmHandleEventBssAbsencePresence (ucNetTypeIdx=%d, fgIsAbsent=%d, FreeQuota=%d)\n", */ + /* prEventBssStatus->ucNetTypeIdx, prBssInfo->fgIsNetAbsent, prBssInfo->ucBssFreeQuota)); */ + + DBGLOG(QM, INFO, "Bss Absence Presence NAF=%d,%d,%d\n", + prEventBssStatus->ucBssIndex, prBssInfo->fgIsNetAbsent, prBssInfo->ucBssFreeQuota); + + if (!prBssInfo->fgIsNetAbsent) { + /* ToDo:: QM_DBG_CNT_INC */ + QM_DBG_CNT_INC(&(prAdapter->rQM), QM_DBG_CNT_27); + } else { + /* ToDo:: QM_DBG_CNT_INC */ + 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->ucIsInPs; + + qmUpdateFreeQuota(prAdapter, + prStaRec, prEventStaChangePsMode->ucUpdateMode, prEventStaChangePsMode->ucFreeQuota); + + /* DBGLOG(QM, TRACE, ("qmHandleEventStaChangePsMode (ucStaRecIdx=%d, fgIsInPs=%d)\n", */ + /* prEventStaChangePsMode->ucStaRecIdx, prStaRec->fgIsInPS)); */ + + DBGLOG(QM, INFO, "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); + /* 2013/08/30 + * Station Record possible been freed. + */ + /* 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; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Dump current queue status +* +* \param[in] (none) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmDumpQueueStatus(IN P_ADAPTER_T prAdapter) +{ + P_TX_CTRL_T prTxCtrl; + P_QUE_MGT_T prQM; + P_GLUE_INFO_T prGlueInfo; + UINT_32 i, u4TotalBufferCount, u4TotalPageCount; + UINT_32 u4CurBufferCount, u4CurPageCount; + + DEBUGFUNC(("%s", __func__)); + + prTxCtrl = &prAdapter->rTxCtrl; + prQM = &prAdapter->rQM; + prGlueInfo = prAdapter->prGlueInfo; + u4TotalBufferCount = 0; + u4TotalPageCount = 0; + u4CurBufferCount = 0; + u4CurPageCount = 0; + + DBGLOG(SW4, INFO, "\n------------\n"); + + for (i = TC0_INDEX; i < TC_NUM; i++) { + DBGLOG(SW4, INFO, "TC%u ResCount: Max[%02u/%03u] Free[%02u/%03u] PreUsed[%03u]\n", + i, prTxCtrl->rTc.au2MaxNumOfBuffer[i], + prTxCtrl->rTc.au2MaxNumOfPage[i], + prTxCtrl->rTc.au2FreeBufferCount[i], + prTxCtrl->rTc.au2FreePageCount[i], prTxCtrl->rTc.au2PreUsedPageCount[i]); + + u4TotalBufferCount += prTxCtrl->rTc.au2MaxNumOfBuffer[i]; + u4TotalPageCount += prTxCtrl->rTc.au2MaxNumOfPage[i]; + u4CurBufferCount += prTxCtrl->rTc.au2FreeBufferCount[i]; + u4CurPageCount += prTxCtrl->rTc.au2FreePageCount[i]; + } + + DBGLOG(SW4, INFO, "ToT ResCount: Max[%02u/%03u] Free[%02u/%03u]\n", + u4TotalBufferCount, u4TotalPageCount, u4CurBufferCount, u4CurPageCount); + + DBGLOG(SW4, INFO, "---------------------------------\n"); + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + for (i = TC0_INDEX; i < TC_NUM; i++) { + DBGLOG(SW4, INFO, "TC%u AvgQLen[%04u] minRsv[%02u] CurTcRes[%02u] GrtdTcRes[%02u]\n", + i, QM_GET_TX_QUEUE_LEN(prAdapter, i), + prQM->au4MinReservedTcResource[i], prQM->au4CurrentTcResource[i], + prQM->au4GuaranteedTcResource[i]); + } + + DBGLOG(SW4, INFO, "Resource Residual[%u] ExtraRsv[%u]\n", + prQM->u4ResidualTcResource, prQM->u4ExtraReservedTcResource); + DBGLOG(SW4, INFO, "QueLenMovingAvg[%u] Time2AdjResource[%u] Time2UpdateQLen[%u]\n", + prQM->u4QueLenMovingAverage, + prQM->u4TimeToAdjustTcResource, prQM->u4TimeToUpdateQueLen); +#endif + + DBGLOG(SW4, INFO, "---------------------------------\n"); + +#if QM_FORWARDING_FAIRNESS + for (i = 0; i < NUM_OF_PER_STA_TX_QUEUES; i++) { + DBGLOG(SW4, INFO, "TC%u HeadSta[%u] ResourceUsedCount[%u]\n", + i, prQM->au4HeadStaRecIndex[i], prQM->au4ResourceUsedCount[i]); + } +#endif + + DBGLOG(SW4, INFO, "BMC or unknown TxQueue Len[%u]\n", prQM->arTxQueue[0].u4NumElem); + DBGLOG(SW4, INFO, "Pending QLen Normal[%u] Sec[%u]\n", + prGlueInfo->i4TxPendingFrameNum, prGlueInfo->i4TxPendingSecurityFrameNum); + +#if defined(LINUX) + for (i = 0; i < HW_BSSID_NUM; i++) { + DBGLOG(SW4, INFO, "Pending BSS[%u] QLen[%u:%u:%u:%u]\n", + i, prGlueInfo->ai4TxPendingFrameNumPerQueue[i][0], + prGlueInfo->ai4TxPendingFrameNumPerQueue[i][1], + prGlueInfo->ai4TxPendingFrameNumPerQueue[i][2], + prGlueInfo->ai4TxPendingFrameNumPerQueue[i][3]); + } +#endif + DBGLOG(SW4, INFO, "Pending FWD CNT[%d]\n", prTxCtrl->i4PendingFwdFrameCount); + DBGLOG(SW4, INFO, "Pending MGMT CNT[%d]\n", prTxCtrl->i4TxMgmtPendingNum); + + DBGLOG(SW4, INFO, "---------------------------------\n"); + + DBGLOG(SW4, INFO, "Total RFB[%u]\n", CFG_RX_MAX_PKT_NUM); + 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); + + DBGLOG(SW4, INFO, "---------------------------------\n"); + DBGLOG(SW4, INFO, "CMD: FreeCmd[%u/%u] PendingCmd[%u] Cmd2Tx[%u]\n", + prAdapter->rFreeCmdList.u4NumElem, CFG_TX_MAX_CMD_PKT_NUM, + prAdapter->rPendingCmdQueue.u4NumElem, prGlueInfo->rCmdQueue.u4NumElem); + DBGLOG(SW4, INFO, "MGMT: FreeMgmt[%u/%u] PendingMgmt[%u]\n", + prAdapter->rTxCtrl.rFreeMsduInfoList.u4NumElem, CFG_TX_MAX_PKT_NUM, + prAdapter->rTxCtrl.rTxMgmtTxingQueue.u4NumElem); + + DBGLOG(SW4, INFO, "---------------------------------\n\n"); +} + +#if CFG_M0VE_BA_TO_DRIVER +/*----------------------------------------------------------------------------*/ +/*! +* @brief Send DELBA Action frame +* +* @param fgIsInitiator DELBA_ROLE_INITIATOR or DELBA_ROLE_RECIPIENT +* @param prStaRec Pointer to the STA_REC of the receiving peer +* @param u4Tid TID of the BA entry +* @param u4ReasonCode The reason code carried in the Action frame +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +mqmSendDelBaFrame(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsInitiator, IN P_STA_RECORD_T prStaRec, IN UINT_32 u4Tid, IN UINT_32 u4ReasonCode) +{ + + P_MSDU_INFO_T prTxMsduInfo; + P_ACTION_DELBA_FRAME_T prDelBaFrame; + P_BSS_INFO_T prBssInfo; + + DBGLOG(QM, WARN, "[Puff]: Enter mqmSendDelBaFrame()\n"); + + ASSERT(prStaRec); + + /* 3 <1> Block the message in case of invalid STA */ + if (!prStaRec->fgIsInUse) { + DBGLOG(QM, WARN, "[Puff][%s]: (Warning) sta_rec is not inuse\n", __func__); + return; + } + /* Check HT-capabale STA */ + if (!(prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_HT)) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) sta is NOT HT-capable(0x%08X)\n", __func__, + prStaRec->ucDesiredPhyTypeSet); + return; + } + /* 4 <2> Construct the DELBA frame */ + prTxMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, ACTION_DELBA_FRAME_LEN); + + if (!prTxMsduInfo) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) DELBA for TID=%ld was not sent (MSDU_INFO alloc failure)\n", + __func__, u4Tid); + return; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + /* Fill the Action frame */ + prDelBaFrame = (P_ACTION_DELBA_FRAME_T) ((UINT_32) (prTxMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + prDelBaFrame->u2FrameCtrl = MAC_FRAME_ACTION; +#if CFG_SUPPORT_802_11W + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(QM, WARN, "[Puff][%s]: (Warning) DELBA is 80211w enabled\n", __func__); + prDelBaFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + } +#endif + + prDelBaFrame->u2DurationID = 0; + prDelBaFrame->ucCategory = CATEGORY_BLOCK_ACK_ACTION; + prDelBaFrame->ucAction = ACTION_DELBA; + + prDelBaFrame->u2DelBaParameterSet = 0; + prDelBaFrame->u2DelBaParameterSet |= ((fgIsInitiator ? ACTION_DELBA_INITIATOR_MASK : 0)); + prDelBaFrame->u2DelBaParameterSet |= ((u4Tid << ACTION_DELBA_TID_OFFSET) & ACTION_DELBA_TID_MASK); + prDelBaFrame->u2ReasonCode = u4ReasonCode; + + COPY_MAC_ADDR(prDelBaFrame->aucDestAddr, prStaRec->aucMacAddr); + COPY_MAC_ADDR(prDelBaFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prDelBaFrame->aucBSSID, prBssInfo->aucBSSID); + + /* 4 <3> Configure the MSDU_INFO and forward it to TXM */ + TX_SET_MMPDU(prAdapter, + prTxMsduInfo, + prStaRec->ucBssIndex, + (prStaRec != NULL) ? (prStaRec->ucIndex) : (STA_REC_INDEX_NOT_FOUND), + WLAN_MAC_HEADER_LEN, ACTION_DELBA_FRAME_LEN, NULL, MSDU_RATE_MODE_AUTO); + +#if CFG_SUPPORT_802_11W + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(RSN, INFO, "Set MSDU_OPT_PROTECTED_FRAME\n"); + nicTxConfigPktOption(prTxMsduInfo, MSDU_OPT_PROTECTED_FRAME, TRUE); + } +#endif + + /* TID and fgIsInitiator are needed when processing TX Done of the DELBA frame */ + prTxMsduInfo->ucTID = (UINT_8) u4Tid; + prTxMsduInfo->ucControlFlag = (fgIsInitiator ? 1 : 0); + + nicTxEnqueueMsdu(prAdapter, prTxMsduInfo); + + DBGLOG(QM, WARN, "[Puff][%s]: Send DELBA for TID=%ld Initiator=%d\n", __func__, u4Tid, fgIsInitiator); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Callback function for the TX Done event for an ADDBA_RSP +* +* @param prMsduInfo The TX packet +* @param rWlanStatus WLAN_STATUS_SUCCESS if TX is successful +* +* @return WLAN_STATUS_BUFFER_RETAINED is returned if the buffer shall not be freed by TXM +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +mqmCallbackAddBaRspSent(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + P_RX_BA_ENTRY_T prRxBaEntry; + P_STA_RECORD_T prStaRec; + P_QUE_MGT_T prQM; + + UINT_32 u4Tid = 0; + + /* ASSERT(prMsduInfo); */ + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + prQM = &prAdapter->rQM; + + DBGLOG(QM, WARN, "[Puff]: Enter mqmCallbackAddBaRspSent()\n"); + + /* 4 <0> Check STA_REC status */ + /* Check STA_REC is inuse */ + if (!prStaRec->fgIsInUse) { + DBGLOG(QM, WARN, "[Puff][%s]: (Warning) sta_rec is not inuse\n", __func__); + return WLAN_STATUS_SUCCESS; + } + /* Check HT-capabale STA */ + if (!(prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_HT)) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) sta is NOT HT-capable(0x%08X)\n", __func__, + prStaRec->ucDesiredPhyTypeSet); + return WLAN_STATUS_SUCCESS; /* To free the received ADDBA_REQ directly */ + } + /* 4 <1> Find the corresponding BA entry */ + u4Tid = prMsduInfo->ucTID; /* TID is stored in MSDU_INFO when composing the ADDBA_RSP frame */ + prRxBaEntry = &prQM->arRxBaTable[u4Tid]; + + /* Note: Due to some reason, for example, receiving a DELBA, the BA entry may not be in state NEGO */ + /* 4 <2> INVALID state */ + if (!prRxBaEntry) { + DBGLOG(QM, WARN, + "[Puff][%s]: (RX_BA) ADDBA_RSP ---> peer (STA=%d TID=%d)(TX successful)(invalid BA)\n", + __func__, prStaRec->ucIndex, u4Tid); + } + /* 4 <3> NEGO, ACTIVE, or DELETING state */ + else { + switch (rTxDoneStatus) { + /* 4 TX Success */ + case TX_RESULT_SUCCESS: + + DBGLOG(QM, WARN, + "[Puff][%s]: (RX_BA) ADDBA_RSP ---> peer (STA=%d TID=%d)(TX successful)\n", + __func__, prStaRec->ucIndex, u4Tid); + + /* 4 NEGO or ACTIVE state */ + if (prRxBaEntry->ucStatus != BA_ENTRY_STATUS_DELETING) + mqmRxModifyBaEntryStatus(prAdapter, prRxBaEntry, BA_ENTRY_STATUS_ACTIVE); + /* 4 DELETING state */ + /* else */ + /* Deleting is on-going, so do nothing and wait for TX done of the DELBA frame */ + + break; + + /* 4 TX Failure */ + default: + + DBGLOG(QM, WARN, + "[Puff][%s]: (RX_BA) ADDBA_RSP ---> peer (STA=%d TID=%ld Entry_Status=%d)(TX failed)\n", + __func__, prStaRec->ucIndex, u4Tid, prRxBaEntry->ucStatus); + + /* 4 NEGO or ACTIVE state */ + /* Notify the host to delete the agreement */ + if (prRxBaEntry->ucStatus != BA_ENTRY_STATUS_DELETING) { + mqmRxModifyBaEntryStatus(prAdapter, prRxBaEntry, BA_ENTRY_STATUS_DELETING); + + /* Send DELBA to the peer to ensure the BA state is synchronized */ + mqmSendDelBaFrame(prAdapter, DELBA_ROLE_RECIPIENT, prStaRec, u4Tid, + STATUS_CODE_UNSPECIFIED_FAILURE); + } + /* 4 DELETING state */ + /* else */ + /* Deleting is on-going, so do nothing and wait for the TX done of the DELBA frame */ + + break; + } + + } + + return WLAN_STATUS_SUCCESS; /* TXM shall release the packet */ + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Check if there is any idle RX BA +* +* @param u4Param (not used) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID mqmTimeoutCheckIdleRxBa(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr) +{ + INT_8 i; + P_RX_BA_ENTRY_T prRxBa; + UINT_32 u4IdleCountThreshold = 0; + P_STA_RECORD_T prStaRec; + P_QUE_MGT_T prQM; + + DBGLOG(QM, WARN, "[Puff]: Enter mqmTimeoutIdleRxBaDetection()\n"); + + prQM = &prAdapter->rQM; + + /* 4 <1> Restart the timer */ + cnmTimerStopTimer(prAdapter, &prAdapter->rMqmIdleRxBaDetectionTimer); + cnmTimerStartTimer(prAdapter, &prAdapter->rMqmIdleRxBaDetectionTimer, MQM_IDLE_RX_BA_CHECK_INTERVAL); + + /* 4 <2> Increment the idle count for each idle BA */ + for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) { + + prRxBa = &prQM->arRxBaTable[i]; + + if (prRxBa->ucStatus == BA_ENTRY_STATUS_ACTIVE) { + + prStaRec = cnmGetStaRecByIndex(prAdapter, prRxBa->ucStaRecIdx); + + if (!prStaRec->fgIsInUse) { + DBGLOG(QM, WARN, "[Puff][%s]: (Warning) sta_rec is not inuse\n", __func__); + ASSERT(0); + } + /* Check HT-capabale STA */ + if (!(prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_HT)) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) sta is NOT HT-capable(0x%08X)\n", + __func__, prStaRec->ucDesiredPhyTypeSet); + ASSERT(0); + } + /* 4 <2.1> Idle detected, increment idle count and see if a DELBA should be sent */ + if (prRxBa->u2SnapShotSN == prStaRec->au2CachedSeqCtrl[prRxBa->ucTid]) { + + prRxBa->ucIdleCount++; + + ASSERT(prRxBa->ucTid < 8); + switch (aucTid2ACI[prRxBa->ucTid]) { + case 0: /* BK */ + u4IdleCountThreshold = MQM_DEL_IDLE_RXBA_THRESHOLD_BK; + break; + case 1: /* BE */ + u4IdleCountThreshold = MQM_DEL_IDLE_RXBA_THRESHOLD_BE; + break; + case 2: /* VI */ + u4IdleCountThreshold = MQM_DEL_IDLE_RXBA_THRESHOLD_VI; + break; + case 3: /* VO */ + u4IdleCountThreshold = MQM_DEL_IDLE_RXBA_THRESHOLD_VO; + break; + } + + if (prRxBa->ucIdleCount >= u4IdleCountThreshold) { + mqmRxModifyBaEntryStatus(prAdapter, prRxBa, BA_ENTRY_STATUS_INVALID); + mqmSendDelBaFrame(prAdapter, DELBA_ROLE_RECIPIENT, prStaRec, + (UINT_32) prRxBa->ucTid, REASON_CODE_PEER_TIME_OUT); + qmDelRxBaEntry(prAdapter, prStaRec->ucIndex, prRxBa->ucTid, TRUE); + } + } + /* 4 <2.2> Activity detected */ + else { + prRxBa->u2SnapShotSN = prStaRec->au2CachedSeqCtrl[prRxBa->ucTid]; + prRxBa->ucIdleCount = 0; + continue; /* check the next BA entry */ + } + } + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Do RX BA entry state transition +* +* @param prRxBaEntry The BA entry pointer +* @param eStatus The state to transition to +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +mqmRxModifyBaEntryStatus(IN P_ADAPTER_T prAdapter, IN P_RX_BA_ENTRY_T prRxBaEntry, IN ENUM_BA_ENTRY_STATUS_T eStatus) +{ + P_STA_RECORD_T prStaRec; + P_QUE_MGT_T prQM; + + BOOLEAN fgResetScoreBoard = FALSE; + + ASSERT(prRxBaEntry); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prRxBaEntry->ucStaRecIdx); + ASSERT(prStaRec); + prQM = &prAdapter->rQM; + + if (prRxBaEntry->ucStatus == (UINT_8) eStatus) { + DBGLOG(QM, WARN, "[Puff][%s]: eStatus are identical...\n", __func__, prRxBaEntry->ucStatus); + return; + } + /* 4 <1> State transition from state X */ + switch (prRxBaEntry->ucStatus) { + + /* 4 <1.1> From (X = INVALID) to (ACTIVE or NEGO or DELETING) */ + case BA_ENTRY_STATUS_INVALID: + + /* Associate the BA entry with the STA_REC when leaving INVALID state */ + kalMemCopy(&prQM->arRxBaTable[prRxBaEntry->ucTid], prRxBaEntry, sizeof(RX_BA_ENTRY_T)); + + /* Increment the RX BA counter */ + prQM->ucRxBaCount++; + ASSERT(prQM->ucRxBaCount <= CFG_NUM_OF_RX_BA_AGREEMENTS); + + /* Since AMPDU may be received during INVALID state */ + fgResetScoreBoard = TRUE; + + /* Reset Idle Count since this BA entry is being activated now. + * Note: If there is no ACTIVE entry, the idle detection timer will not be started. + */ + prRxBaEntry->ucIdleCount = 0; + break; + + /* 4 <1.2> Other cases */ + default: + break; + } + + /* 4 <2> State trasition to state Y */ + switch (eStatus) { + + /* 4 <2.1> From (NEGO, ACTIVE, DELETING) to (Y=INVALID) */ + case BA_ENTRY_STATUS_INVALID: + + /* Disassociate the BA entry with the STA_REC */ + kalMemZero(&prQM->arRxBaTable[prRxBaEntry->ucTid], sizeof(RX_BA_ENTRY_T)); + + /* Decrement the RX BA counter */ + prQM->ucRxBaCount--; + ASSERT(prQM->ucRxBaCount < CFG_NUM_OF_RX_BA_AGREEMENTS); + + /* (TBC) */ + fgResetScoreBoard = TRUE; + + /* If there is not any BA agreement, stop doing idle detection */ + if (prQM->ucRxBaCount == 0) { + if (MQM_CHECK_FLAG(prAdapter->u4FlagBitmap, MQM_FLAG_IDLE_RX_BA_TIMER_STARTED)) { + cnmTimerStopTimer(prAdapter, &prAdapter->rMqmIdleRxBaDetectionTimer); + MQM_CLEAR_FLAG(prAdapter->u4FlagBitmap, MQM_FLAG_IDLE_RX_BA_TIMER_STARTED); + } + } + + break; + + /* 4 <2.2> From (any) to (Y=ACTIVE) */ + case BA_ENTRY_STATUS_ACTIVE: + + /* If there is at least one BA going into ACTIVE, start idle detection */ + if (!MQM_CHECK_FLAG(prAdapter->u4FlagBitmap, MQM_FLAG_IDLE_RX_BA_TIMER_STARTED)) { + cnmTimerInitTimer(prAdapter, &prAdapter->rMqmIdleRxBaDetectionTimer, + (PFN_MGMT_TIMEOUT_FUNC) mqmTimeoutCheckIdleRxBa, (ULONG) NULL); /* No parameter */ + + cnmTimerStopTimer(prAdapter, &prAdapter->rMqmIdleRxBaDetectionTimer); + +#if MQM_IDLE_RX_BA_DETECTION + cnmTimerStartTimer(prAdapter, &prAdapter->rMqmIdleRxBaDetectionTimer, + MQM_IDLE_RX_BA_CHECK_INTERVAL); + MQM_SET_FLAG(prAdapter->u4FlagBitmap, MQM_FLAG_IDLE_RX_BA_TIMER_STARTED); +#endif + } + + break; + + case BA_ENTRY_STATUS_NEGO: + default: + break; + } + + if (fgResetScoreBoard) { + P_CMD_RESET_BA_SCOREBOARD_T prCmdBody; + + prCmdBody = (P_CMD_RESET_BA_SCOREBOARD_T) + cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_RESET_BA_SCOREBOARD_T)); + ASSERT(prCmdBody); + + prCmdBody->ucflag = MAC_ADDR_TID_MATCH; + prCmdBody->ucTID = prRxBaEntry->ucTid; + kalMemCopy(prCmdBody->aucMacAddr, prStaRec->aucMacAddr, PARAM_MAC_ADDR_LEN); + + wlanoidResetBAScoreboard(prAdapter, prCmdBody, sizeof(CMD_RESET_BA_SCOREBOARD_T)); + cnmMemFree(prAdapter, prCmdBody); + } + + DBGLOG(QM, WARN, "[Puff]QM: (RX_BA) [STA=%d TID=%d] status from %d to %d\n", + prRxBaEntry->ucStaRecIdx, prRxBaEntry->ucTid, prRxBaEntry->ucStatus, eStatus); + + prRxBaEntry->ucStatus = (UINT_8) eStatus; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mqmHandleAddBaReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prBssInfo; + P_ACTION_ADDBA_REQ_FRAME_T prAddBaReq; + ACTION_ADDBA_REQ_BODY_T rAddBaReqBody; + P_ACTION_ADDBA_RSP_FRAME_T prAddBaRsp; + ACTION_ADDBA_RSP_BODY_T rAddBaRspBody; + P_RX_BA_ENTRY_T prRxBaEntry; + P_MSDU_INFO_T prTxMsduInfo; + P_QUE_MGT_T prQM; + + BOOLEAN fgIsReqAccepted = TRUE; /* Reject or accept the ADDBA_REQ */ + BOOLEAN fgIsNewEntryAdded = FALSE; /* Indicator: Whether a new RX BA entry will be added */ + + UINT_32 u4Tid; + UINT_32 u4StaRecIdx; + UINT_16 u2WinStart; + UINT_16 u2WinSize; + UINT_32 u4BuffSize; + +#if CFG_SUPPORT_BCM + UINT_32 u4BuffSizeBT; +#endif + + ASSERT(prSwRfb); + + prStaRec = prSwRfb->prStaRec; + prQM = &prAdapter->rQM; + + do { + + /* 4 <0> Check if this is an active HT-capable STA */ + /* Check STA_REC is inuse */ + if (!prStaRec->fgIsInUse) { + DBGLOG(QM, WARN, "[Puff][%s]: (Warning) sta_rec is not inuse\n", __func__); + break; + } + /* Check HT-capabale STA */ + if (!(prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_HT)) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) sta is NOT HT-capable(0x%08X)\n", __func__, + prStaRec->ucDesiredPhyTypeSet); + break; /* To free the received ADDBA_REQ directly */ + } + /* 4 <1> Check user configurations and HW capabilities */ + /* Check configurations (QoS support, AMPDU RX support) */ + if ((!prAdapter->rWifiVar.fgSupportQoS) || + (!prAdapter->rWifiVar.fgSupportAmpduRx) || (!prStaRec->fgRxAmpduEn)) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) BA ACK Policy not supported fgSupportQoS(%d)", + __func__, prAdapter->rWifiVar.fgSupportQoS); + DBGLOG(QM, WARN, + "fgSupportAmpduRx(%d), fgRxAmpduEn(%d)\n", + prAdapter->rWifiVar.fgSupportAmpduRx, prStaRec->fgRxAmpduEn); + fgIsReqAccepted = FALSE; /* Will send an ADDBA_RSP with DECLINED */ + } + /* Check capability */ + prAddBaReq = ((P_ACTION_ADDBA_REQ_FRAME_T) (prSwRfb->pvHeader)); + kalMemCopy((PUINT_8) (&rAddBaReqBody), (PUINT_8) (&(prAddBaReq->aucBAParameterSet[0])), 6); + if ((((rAddBaReqBody.u2BAParameterSet) & BA_PARAM_SET_ACK_POLICY_MASK) >> + BA_PARAM_SET_ACK_POLICY_MASK_OFFSET) + != BA_PARAM_SET_ACK_POLICY_IMMEDIATE_BA) { /* Only Immediate_BA is supported */ + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) BA ACK Policy not supported (0x%08X)\n", + __func__, rAddBaReqBody.u2BAParameterSet); + fgIsReqAccepted = FALSE; /* Will send an ADDBA_RSP with DECLINED */ + } + + /* 4 <2> Determine the RX BA entry (existing or to be added) */ + /* Note: BA entry index = (TID, STA_REC index) */ + u4Tid = (((rAddBaReqBody.u2BAParameterSet) & BA_PARAM_SET_TID_MASK) >> BA_PARAM_SET_TID_MASK_OFFSET); + u4StaRecIdx = prStaRec->ucIndex; + DBGLOG(QM, WARN, + "[Puff][%s]: BA entry index = [TID(%d), STA_REC index(%d)]\n", __func__, u4Tid, u4StaRecIdx); + + u2WinStart = ((rAddBaReqBody.u2BAStartSeqCtrl) >> OFFSET_BAR_SSC_SN); + u2WinSize = (((rAddBaReqBody.u2BAParameterSet) & BA_PARAM_SET_BUFFER_SIZE_MASK) + >> BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET); + DBGLOG(QM, WARN, + "[Puff][%s]: BA entry info = [WinStart(%d), WinSize(%d)]\n", __func__, u2WinStart, u2WinSize); + + if (fgIsReqAccepted) { + + prRxBaEntry = &prQM->arRxBaTable[u4Tid]; + + if (!prRxBaEntry) { + + /* 4 INVALID state && BA entry available --> Add a new entry and accept */ + if (prQM->ucRxBaCount < CFG_NUM_OF_RX_BA_AGREEMENTS) { + + fgIsNewEntryAdded = qmAddRxBaEntry(prAdapter, + (UINT_8) u4StaRecIdx, + (UINT_8) u4Tid, u2WinStart, u2WinSize); + + if (!fgIsNewEntryAdded) { + DBGLOG(QM, ERROR, + "[Puff][%s]: (Error) Free RX BA entry alloc failure\n"); + fgIsReqAccepted = FALSE; + } else { + DBGLOG(QM, WARN, "[Puff][%s]: Create a new BA Entry\n"); + } + } + /* 4 INVALID state && BA entry unavailable --> Reject the ADDBA_REQ */ + else { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) Free RX BA entry unavailable(req: %d)\n", + __func__, prQM->ucRxBaCount); + fgIsReqAccepted = FALSE; /* Will send an ADDBA_RSP with DECLINED */ + } + } else { + + /* 4 NEGO or DELETING state --> Ignore the ADDBA_REQ */ + /* For NEGO: do nothing. Wait for TX Done of ADDBA_RSP */ + /* For DELETING: do nothing. Wait for TX Done of DELBA */ + if (prRxBaEntry->ucStatus != BA_ENTRY_STATUS_ACTIVE) { + DBGLOG(QM, WARN, + "[Puff][%s]:(Warning)ADDBA_REQ for TID=%ld is received, status:%d)\n", + __func__, u4Tid, prRxBaEntry->ucStatus); + break; /* Ignore the ADDBA_REQ since the current state is NEGO */ + } + /* 4 ACTIVE state --> Accept */ + /* Send an ADDBA_RSP to accept the request again */ + /* else */ + } + } + /* 4 <3> Construct the ADDBA_RSP frame */ + prTxMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, ACTION_ADDBA_RSP_FRAME_LEN); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + if (!prTxMsduInfo) { + + /* The peer may send an ADDBA_REQ message later. + * Do nothing to the BA entry. No DELBA will be sent (because cnmMgtPktAlloc() may fail again). + * No BA deletion event will be sent to the host (because cnmMgtPktAlloc() may fail again). + */ + DBGLOG(QM, WARN, "[Puff][%s]: (Warning) ADDBA_RSP alloc failure\n", __func__); + + if (fgIsNewEntryAdded) { /* If a new entry has been created due to this ADDBA_REQ, delete it */ + ASSERT(prRxBaEntry); + mqmRxModifyBaEntryStatus(prAdapter, prRxBaEntry, BA_ENTRY_STATUS_INVALID); + } + + break; /* Exit directly to free the ADDBA_REQ */ + } + + /* Fill the ADDBA_RSP message */ + prAddBaRsp = (P_ACTION_ADDBA_RSP_FRAME_T) ((UINT_32) (prTxMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + prAddBaRsp->u2FrameCtrl = MAC_FRAME_ACTION; + +#if CFG_SUPPORT_802_11W + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(QM, WARN, "[Puff][%s]: (Warning) ADDBA_RSP is 80211w enabled\n", __func__); + prAddBaReq->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + } +#endif + prAddBaRsp->u2DurationID = 0; + prAddBaRsp->ucCategory = CATEGORY_BLOCK_ACK_ACTION; + prAddBaRsp->ucAction = ACTION_ADDBA_RSP; + prAddBaRsp->ucDialogToken = prAddBaReq->ucDialogToken; + + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) ADDBA_RSP DurationID(%d) Category(%d) Action(%d) DialogToken(%d)\n", + __func__, prAddBaRsp->u2DurationID, prAddBaRsp->ucCategory, + prAddBaRsp->ucAction, prAddBaRsp->ucDialogToken); + + if (fgIsReqAccepted) + rAddBaRspBody.u2StatusCode = STATUS_CODE_SUCCESSFUL; + else + rAddBaRspBody.u2StatusCode = STATUS_CODE_REQ_DECLINED; + + /* WinSize = min(WinSize in ADDBA_REQ, CFG_RX_BA_MAX_WINSIZE) */ + u4BuffSize = (((rAddBaReqBody.u2BAParameterSet) & BA_PARAM_SET_BUFFER_SIZE_MASK) + >> BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET); + + /*If ADDBA req WinSize<=0 => use default WinSize(16) */ + if ((u4BuffSize > CFG_RX_BA_MAX_WINSIZE) || (u4BuffSize <= 0)) + u4BuffSize = CFG_RX_BA_MAX_WINSIZE; +#if CFG_SUPPORT_BCM + /* TODO: Call BT coexistence function to limit the winsize */ + u4BuffSizeBT = bcmRequestBaWinSize(); + DBGLOG(QM, WARN, "[Puff][%s]: (Warning) bcmRequestBaWinSize(%d)\n", __func__, u4BuffSizeBT); + + if (u4BuffSize > u4BuffSizeBT) + u4BuffSize = u4BuffSizeBT; +#endif /* CFG_SUPPORT_BCM */ + + rAddBaRspBody.u2BAParameterSet = (BA_POLICY_IMMEDIATE | + (u4Tid << BA_PARAM_SET_TID_MASK_OFFSET) | + (u4BuffSize << BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET)); + + /* TODO: Determine the BA timeout value according to the default preference */ + rAddBaRspBody.u2BATimeoutValue = rAddBaReqBody.u2BATimeoutValue; + + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) ADDBA_RSP u4BuffSize(%d) StatusCode(%d)", + __func__, u4BuffSize, rAddBaRspBody.u2StatusCode); + DBGLOG(QM, WARN, + "BAParameterSet(0x%08X) BATimeoutValue(%d)\n", + rAddBaRspBody.u2BAParameterSet, rAddBaRspBody.u2BATimeoutValue); + kalMemCopy((PUINT_8) (&(prAddBaRsp->aucStatusCode[0])), (PUINT_8) (&rAddBaRspBody), 6); + + COPY_MAC_ADDR(prAddBaRsp->aucDestAddr, prStaRec->aucMacAddr); + COPY_MAC_ADDR(prAddBaRsp->aucSrcAddr, prBssInfo->aucOwnMacAddr); + /* COPY_MAC_ADDR(prAddBaRsp->aucBSSID,g_aprBssInfo[prStaRec->ucNetTypeIndex]->aucBSSID); */ + COPY_MAC_ADDR(prAddBaRsp->aucBSSID, prAddBaReq->aucBSSID); + + /* 4 <4> Forward the ADDBA_RSP to TXM */ + TX_SET_MMPDU(prAdapter, + prTxMsduInfo, + prStaRec->ucBssIndex, + (prStaRec != NULL) ? (prStaRec->ucIndex) : (STA_REC_INDEX_NOT_FOUND), + WLAN_MAC_HEADER_LEN, + ACTION_ADDBA_RSP_FRAME_LEN, mqmCallbackAddBaRspSent, MSDU_RATE_MODE_AUTO); + +#if CFG_SUPPORT_802_11W + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(RSN, INFO, "Set MSDU_OPT_PROTECTED_FRAME\n"); + nicTxConfigPktOption(prTxMsduInfo, MSDU_OPT_PROTECTED_FRAME, TRUE); + } +#endif + + /* Note: prTxMsduInfo->ucTID is not used for transmitting the ADDBA_RSP. + * However, when processing TX Done of this ADDBA_RSP, the TID value is needed, so + * store the TID value in advance to prevent parsing the ADDBA_RSP frame + */ + prTxMsduInfo->ucTID = (UINT_8) u4Tid; + + nicTxEnqueueMsdu(prAdapter, prTxMsduInfo); + + DBGLOG(QM, WARN, + "[Puff][%s]: (RX_BA) ADDBA_RSP ---> peer (STA=%d TID=%ld)\n", __func__, + prStaRec->ucIndex, u4Tid); + +#if 0 + /* 4 <5> Notify the host to start buffer reordering */ + if (fgIsNewEntryAdded) { /* Only when a new BA entry is indeed added will the host be notified */ + ASSERT(fgIsReqAccepted); + + prSwRfbEventToHost = (P_SW_RFB_T) cnmMgtPktAlloc(EVENT_RX_ADDBA_PACKET_LEN); + + if (!prSwRfbEventToHost) { + + /* Note: DELBA will not be sent since cnmMgtPktAlloc() may fail again. However, + * it does not matter because upon receipt of AMPDUs without a RX BA agreement, + * MQM will send DELBA frames + */ + + DBGLOG(MQM, WARN, "MQM: (Warning) EVENT packet alloc failed\n"); + + /* Ensure that host and FW are synchronized */ + mqmRxModifyBaEntryStatus(prRxBaEntry, BA_ENTRY_STATUS_INVALID); + } else { + + prEventRxAddBa = (P_EVENT_RX_ADDBA_T) prSwRfbEventToHost->pucBuffer; + prEventRxAddBa->ucStaRecIdx = (UINT_8) u4StaRecIdx; + prEventRxAddBa->u2Length = EVENT_RX_ADDBA_PACKET_LEN; + prEventRxAddBa->ucEID = EVENT_ID_RX_ADDBA; + prEventRxAddBa->ucSeqNum = 0; /* Unsolicited event packet */ + prEventRxAddBa->u2BAParameterSet = rAddBaRspBody.u2BAParameterSet; + prEventRxAddBa->u2BAStartSeqCtrl = rAddBaReqBody.u2BAStartSeqCtrl; + prEventRxAddBa->u2BATimeoutValue = rAddBaReqBody.u2BATimeoutValue; + prEventRxAddBa->ucDialogToken = prAddBaReq->ucDialogToken; + + DBGLOG(MQM, INFO, + "MQM: (RX_BA) Event ADDBA ---> driver (STA=%ld TID=%ld WinStart=%d)\n", + u4StaRecIdx, u4Tid, (prEventRxAddBa->u2BAStartSeqCtrl >> 4)); + + /* Configure the SW_RFB for the Event packet */ + RXM_SET_EVENT_PACKET( + /* P_SW_RFB_T */ (P_SW_RFB_T) + prSwRfbEventToHost, + /* HIF RX Packet pointer */ + (PUINT_8) prEventRxAddBa, + /* HIF RX port number */ HIF_RX0_INDEX + ); + + rxmSendEventToHost(prSwRfbEventToHost); + } + + } +#endif + + } while (FALSE); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mqmHandleAddBaRsp(IN P_SW_RFB_T prSwRfb) +{ + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mqmHandleDelBa(IN P_SW_RFB_T prSwRfb) +{ + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mqmHandleBaActionFrame(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; + DBGLOG(RLM, WARN, "[Puff][%s] Action(%d)\n", __func__, prRxFrame->ucAction); + + switch (prRxFrame->ucAction) { + + case ACTION_ADDBA_REQ: + DBGLOG(RLM, WARN, "[Puff][%s] (RX_BA) ADDBA_REQ <--- peer\n", __func__); + mqmHandleAddBaReq(prAdapter, prSwRfb); + break; + + case ACTION_ADDBA_RSP: + DBGLOG(RLM, WARN, "[Puff][%s] (RX_BA) ADDBA_RSP <--- peer\n", __func__); + mqmHandleAddBaRsp(prSwRfb); + break; + + case ACTION_DELBA: + DBGLOG(RLM, WARN, "[Puff][%s] (RX_BA) DELBA <--- peer\n", __func__); + mqmHandleDelBa(prSwRfb); + break; + + default: + DBGLOG(RLM, WARN, "[Puff][%s] Unknown BA Action Frame\n", __func__); + break; + } + +} + +#endif + +#if ARP_MONITER_ENABLE +VOID qmDetectArpNoResponse(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + struct sk_buff *prSkb = NULL; + PUINT_8 pucData = NULL; + UINT_16 u2EtherType = 0; + int arpOpCode = 0; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prSkb = (struct sk_buff *)prMsduInfo->prPacket; + + if (!prSkb || (prSkb->len <= ETHER_HEADER_LEN)) + return; + + pucData = prSkb->data; + if (!pucData) + return; + u2EtherType = (pucData[ETH_TYPE_LEN_OFFSET] << 8) | (pucData[ETH_TYPE_LEN_OFFSET + 1]); + + if (u2EtherType != ETH_P_ARP) + return; + + if (kalMemCmp(apIp, &pucData[ETH_TYPE_LEN_OFFSET + 26], sizeof(apIp)) && + kalMemCmp(gatewayIp, &pucData[ETH_TYPE_LEN_OFFSET + 26], sizeof(gatewayIp))) + return; + + arpOpCode = (pucData[ETH_TYPE_LEN_OFFSET + 8] << 8) | (pucData[ETH_TYPE_LEN_OFFSET + 8 + 1]); + if (arpOpCode == ARP_PRO_REQ) { + arpMoniter++; + if (arpMoniter > 20) { + DBGLOG(INIT, WARN, "IOT Critical issue, arp no resp, check AP!\n"); + if (prAdapter->prAisBssInfo) + prAdapter->prAisBssInfo->u2DeauthReason = BEACON_TIMEOUT_DUE_2_APR_NO_RESPONSE; + kalSetResetConnEvent(prAdapter->prGlueInfo); + arpMoniter = 0; + kalMemZero(apIp, sizeof(apIp)); + } + } +} + +VOID qmHandleRxArpPackets(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) +{ + PUINT_8 pucData = NULL; + UINT_16 u2EtherType = 0; + int arpOpCode = 0; + + if (prSwRfb->u2PacketLen <= ETHER_HEADER_LEN) + return; + + pucData = (PUINT_8)prSwRfb->pvHeader; + if (!pucData) + return; + u2EtherType = (pucData[ETH_TYPE_LEN_OFFSET] << 8) | (pucData[ETH_TYPE_LEN_OFFSET + 1]); + + if (u2EtherType != ETH_P_ARP) + return; + + arpOpCode = (pucData[ETH_TYPE_LEN_OFFSET + 8] << 8) | (pucData[ETH_TYPE_LEN_OFFSET + 8 + 1]); + if (arpOpCode != ARP_PRO_RSP) + return; + arpMoniter = 0; + if (prAdapter->prAisBssInfo && prAdapter->prAisBssInfo->prStaRecOfAP && + EQUAL_MAC_ADDR(&(pucData[ETH_TYPE_LEN_OFFSET + 10]), /* source hardware address */ + prAdapter->prAisBssInfo->prStaRecOfAP->aucMacAddr)) { + kalMemCopy(apIp, &(pucData[ETH_TYPE_LEN_OFFSET + 16]), sizeof(apIp)); + DBGLOG(INIT, TRACE, "get arp response from AP %d.%d.%d.%d\n", + apIp[0], apIp[1], apIp[2], apIp[3]); + } +} + +VOID qmHandleRxDhcpPackets(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) +{ + PUINT_8 pucData = NULL; + PUINT_8 pucEthBody = NULL; + PUINT_8 pucUdpBody = NULL; + UINT_32 udpLength = 0; + UINT_32 i = 0; + P_BOOTP_PROTOCOL_T prBootp = NULL; + UINT_32 u4DhcpMagicCode = 0; + UINT_8 dhcpTypeGot = 0; + UINT_8 dhcpGatewayGot = 0; + + if (prSwRfb->u2PacketLen <= ETHER_HEADER_LEN) + return; + + pucData = (PUINT_8)prSwRfb->pvHeader; + if (!pucData) + return; + if (((pucData[ETH_TYPE_LEN_OFFSET] << 8) | pucData[ETH_TYPE_LEN_OFFSET + 1]) != ETH_P_IPV4) + return; + + pucEthBody = &pucData[ETH_HLEN]; + if (((pucEthBody[0] & IPVH_VERSION_MASK) >> IPVH_VERSION_OFFSET) != IPVERSION) + return; + if (pucEthBody[9] != IP_PRO_UDP) + return; + + pucUdpBody = &pucEthBody[(pucEthBody[0] & 0x0F) * 4]; + if ((pucUdpBody[0] << 8 | pucUdpBody[1]) != UDP_PORT_DHCPS || + (pucUdpBody[2] << 8 | pucUdpBody[3]) != UDP_PORT_DHCPC) + return; + + udpLength = pucUdpBody[4] << 8 | pucUdpBody[5]; + + prBootp = (P_BOOTP_PROTOCOL_T) &pucUdpBody[8]; + + WLAN_GET_FIELD_BE32(&prBootp->aucOptions[0], &u4DhcpMagicCode); + if (u4DhcpMagicCode != DHCP_MAGIC_NUMBER) { + DBGLOG(INIT, WARN, "dhcp wrong magic number, magic code: %d\n", u4DhcpMagicCode); + return; + } + + /* 1. 248 is from udp header to the beginning of dhcp option + * 2. not sure the dhcp option always usd 255 as a end mark? if so, while condition should be removed? + */ + while (i < udpLength - 248) { + /* bcz of the strange P_BOOTP_PROTOCOL_T, the dhcp magic code was count in dhcp options + * so need to [i + 4] to skip it + */ + switch (prBootp->aucOptions[i + 4]) { + case 3: + /* both dhcp ack and offer will update it */ + if (prBootp->aucOptions[i + 6] || + prBootp->aucOptions[i + 7] || + prBootp->aucOptions[i + 8] || + prBootp->aucOptions[i + 9]) { + gatewayIp[0] = prBootp->aucOptions[i + 6]; + gatewayIp[1] = prBootp->aucOptions[i + 7]; + gatewayIp[2] = prBootp->aucOptions[i + 8]; + gatewayIp[3] = prBootp->aucOptions[i + 9]; + + DBGLOG(INIT, TRACE, "Gateway ip: %d.%d.%d.%d\n", + gatewayIp[0], + gatewayIp[1], + gatewayIp[2], + gatewayIp[3]); + }; + dhcpGatewayGot = 1; + break; + case 53: + if (prBootp->aucOptions[i + 6] != 0x02 && prBootp->aucOptions[i + 6] != 0x05) { + DBGLOG(INIT, WARN, "wrong dhcp message type, type: %d\n", prBootp->aucOptions[i + 6]); + if (dhcpGatewayGot) + kalMemZero(gatewayIp, sizeof(gatewayIp)); + return; + } + dhcpTypeGot = 1; + break; + case 255: + return; + + default: + break; + } + if (dhcpGatewayGot && dhcpTypeGot) + return; + + i += prBootp->aucOptions[i + 5] + 2; + } + DBGLOG(INIT, WARN, "can't find the dhcp option 255?, need to check the net log\n"); +} + +VOID qmResetArpDetect(VOID) +{ + arpMoniter = 0; + kalMemZero(apIp, sizeof(apIp)); + kalMemZero(gatewayIp, sizeof(gatewayIp)); +} +#endif + +#ifdef CFG_SUPPORT_REPLAY_DETECTION +/* To change PN number to UINT64 */ +#define CCMPTSCPNNUM 6 +BOOLEAN qmRxPNtoU64(PUINT_8 pucPN, UINT_8 uPNNum, PUINT_64 pu8Rets) +{ + UINT_8 ucCount = 0; + UINT_64 u8Data = 0; + + if (!pu8Rets) { + DBGLOG(QM, ERROR, "Please input valid pu8Rets\n"); + return FALSE; + } + + if (uPNNum > CCMPTSCPNNUM) { + DBGLOG(QM, ERROR, "Please input valid uPNNum:%d\n", uPNNum); + return FALSE; + } + + *pu8Rets = 0; + for (; ucCount < uPNNum; ucCount++) { + u8Data = ((UINT_64)pucPN[ucCount]) << 8*ucCount; + *pu8Rets += u8Data; + } + return TRUE; +} + +/* To check PN/TSC between RxStatus and local record. return TRUE if PNS is not bigger than PNT */ +BOOLEAN qmRxDetectReplay(PUINT_8 pucPNS, PUINT_8 pucPNT) +{ + UINT_64 u8RxNum = 0; + UINT_64 u8LocalRec = 0; + + if (!pucPNS || !pucPNT) { + DBGLOG(QM, ERROR, "Please input valid PNS:%p and PNT:%p\n", pucPNS, pucPNT); + return TRUE; + } + + if (!qmRxPNtoU64(pucPNS, CCMPTSCPNNUM, &u8RxNum) + || !qmRxPNtoU64(pucPNT, CCMPTSCPNNUM, &u8LocalRec)) { + DBGLOG(QM, ERROR, "PN2U64 failed\n"); + return TRUE; + } + /* PN overflow ? */ + return !(u8RxNum > u8LocalRec); +} + +/* TO filter broadcast and multicast data packet replay issue. */ +BOOLEAN qmHandleRxReplay(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) +{ + PUINT_8 pucPN = NULL; + UINT_8 ucKeyID = 0; /* 0~4 */ + UINT_8 ucSecMode = CIPHER_SUITE_NONE; /* CIPHER_SUITE_NONE~CIPHER_SUITE_GCMP */ + P_GLUE_INFO_T prGlueInfo = NULL; + P_GL_WPA_INFO_T prWpaInfo = NULL; + struct GL_DETECT_REPLAY_INFO *prDetRplyInfo = NULL; + P_HW_MAC_RX_DESC_T prRxStatus = NULL; + + if (!prAdapter) + return TRUE; + if (prSwRfb->u2PacketLen <= ETHER_HEADER_LEN) + return TRUE; + + if (!(prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_1))) { + DBGLOG_LIMITED(QM, TRACE, "Group 1 invalid\n"); + return FALSE; + } + + /* BMC only need check CCMP and TKIP Cipher suite */ + prRxStatus = prSwRfb->prRxStatus; + ucSecMode = HAL_RX_STATUS_GET_SEC_MODE(prRxStatus); + + prGlueInfo = prAdapter->prGlueInfo; + prWpaInfo = &prGlueInfo->rWpaInfo; + + if (ucSecMode != CIPHER_SUITE_CCMP && ucSecMode != CIPHER_SUITE_TKIP) { + DBGLOG_LIMITED(QM, LOUD, "SecMode: %d and CipherGroup: %d, no need check replay\n", + ucSecMode, prWpaInfo->u4CipherGroup); + return FALSE; + } + + ucKeyID = HAL_RX_STATUS_GET_KEY_ID(prRxStatus); + if (ucKeyID >= MAX_KEY_NUM) { + DBGLOG(QM, ERROR, "KeyID: %d error\n", ucKeyID); + return TRUE; + } + + prDetRplyInfo = &prGlueInfo->prDetRplyInfo; + pucPN = prSwRfb->prRxStatusGroup1->aucPN; + /* TODO : Need check fw rekey while fw rekey event. */ + if (ucKeyID != prDetRplyInfo->ucCurKeyId) + DBGLOG(QM, TRACE, + "use last keyID[0x%x] check. Some AP set key[0x%x] slowly than our device.\n", + prDetRplyInfo->ucCurKeyId, ucKeyID); + + DBGLOG_LIMITED(QM, LOUD, + "BC packet 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x--0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n", + pucPN[0], pucPN[1], pucPN[2], pucPN[3], pucPN[4], pucPN[5], + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN[0], + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN[1], + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN[2], + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN[3], + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN[4], + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN[5]); + if (qmRxDetectReplay(pucPN, prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN)) { + DBGLOG_LIMITED(QM, WARN, "Drop BC replay packet, ucKeyID[0x%x]!\n", ucKeyID); + return TRUE; + } + + HAL_RX_STATUS_GET_PN(prSwRfb->prRxStatusGroup1, prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN); + return FALSE; +} + +#endif +VOID qmMoveStaTxQueue(P_STA_RECORD_T prSrcStaRec, P_STA_RECORD_T prDstStaRec) +{ + UINT_8 ucQueArrayIdx; + P_QUE_T prSrcQue = NULL; + P_QUE_T prDstQue = NULL; + P_MSDU_INFO_T prMsduInfo = NULL; + UINT_8 ucDstStaIndex = 0; + + ASSERT(prSrcStaRec); + ASSERT(prDstStaRec); + + prSrcQue = &prSrcStaRec->arTxQueue[0]; + prDstQue = &prDstStaRec->arTxQueue[0]; + ucDstStaIndex = prDstStaRec->ucIndex; + + DBGLOG(QM, INFO, "Pending MSDUs for TC 0~3, %u %u %u %u\n", prSrcQue[TC0_INDEX].u4NumElem, + prSrcQue[TC1_INDEX].u4NumElem, prSrcQue[TC2_INDEX].u4NumElem, prSrcQue[TC3_INDEX].u4NumElem); + /* Concatenate all MSDU_INFOs in TX queues of this STA_REC */ + for (ucQueArrayIdx = 0; ucQueArrayIdx < TC4_INDEX; ucQueArrayIdx++) { + prMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_HEAD(&prSrcQue[ucQueArrayIdx]); + while (prMsduInfo) { + prMsduInfo->ucStaRecIndex = ucDstStaIndex; + prMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY(&prMsduInfo->rQueEntry); + } + QUEUE_CONCATENATE_QUEUES((&prDstQue[ucQueArrayIdx]), (&prSrcQue[ucQueArrayIdx])); + } +} + +VOID qmHandleDelTspec(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, ENUM_ACI_T eAci) +{ + UINT_8 aucNextUP[ACI_NUM] = { 1 /* BEtoBK */, 1 /*na */, 0 /*VItoBE */, 4 /*VOtoVI */}; + ENUM_ACI_T aeNextAci[ACI_NUM] = {ACI_BK, ACI_BK, ACI_BE, ACI_VI}; + UINT_8 ucActivedTspec = 0; + UINT_8 ucNewUp = 0; + P_QUE_T prSrcQue = NULL; + P_QUE_T prDstQue = NULL; + P_MSDU_INFO_T prMsduInfo = NULL; + P_AC_QUE_PARMS_T prAcQueParam = NULL; + UINT_8 ucTc = 0; + + if (!prStaRec || eAci == ACI_NUM || eAci == ACI_BK || !prAdapter || !prAdapter->prAisBssInfo) { + DBGLOG(QM, ERROR, "prSta NULL %d, eAci %d, prAdapter NULL %d\n", !prStaRec, eAci, !prAdapter); + return; + } + prSrcQue = &prStaRec->arTxQueue[aucWmmAC2TcResourceSet1[eAci]]; + prAcQueParam = &(prAdapter->prAisBssInfo->arACQueParms[0]); + ucActivedTspec = wmmHasActiveTspec(&prAdapter->rWifiVar.rWmmInfo); + + while (prAcQueParam[eAci].ucIsACMSet && + !(ucActivedTspec & BIT(eAci)) && eAci != ACI_BK) { + eAci = aeNextAci[eAci]; + ucNewUp = aucNextUP[eAci]; + } + DBGLOG(QM, INFO, "new ACI %d, ACM %d, HasTs %d\n", + eAci, prAcQueParam[eAci].ucIsACMSet, !!(ucActivedTspec & BIT(eAci))); + ucTc = aucWmmAC2TcResourceSet1[eAci]; + prDstQue = &prStaRec->arTxQueue[ucTc]; + prMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_HEAD(prSrcQue); + while (prMsduInfo) { + prMsduInfo->ucUserPriority = ucNewUp; + prMsduInfo->ucTC = ucTc; + prMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY(&prMsduInfo->rQueEntry); + } + QUEUE_CONCATENATE_QUEUES(prDstQue, prSrcQue); + qmUpdateAverageTxQueLen(prAdapter); + qmReassignTcResource(prAdapter); + nicTxAdjustTcq(prAdapter); + kalSetEvent(prAdapter->prGlueInfo); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/sources.ce b/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/sources.ce new file mode 100644 index 0000000000000..4627c52191a38 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/sources.ce @@ -0,0 +1,11 @@ +TARGETNAME=$(DRIVER_NAME)_nic_$(WINCEDEBUG)_51 +TARGETTYPE=LIBRARY + +INCLUDES=$(_INCLUDES_DIRS) + +C_DEFINES=$(C_DEFINES) -DNDIS_MINIPORT_DRIVER + +C_DEFINES=$(C_DEFINES) -DNDIS51_MINIPORT=1 -D_WIN2K_COMPAT_SLIST_USAGE=1 +CDEFINES=$(CDEFINES) -D$(DEVICE_ID) -DNDIS51_MINIPORT=1 $(_BUILD_MODULE_DEF) + +SOURCES= $(_NIC_FILES) diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/sources.ddk b/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/sources.ddk new file mode 100644 index 0000000000000..a233fee2a36f9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/nic/sources.ddk @@ -0,0 +1,11 @@ +TARGETPATH=$(_LIB_PATH) +TARGETNAME=$(DRIVER_NAME)_nic_51 +TARGETTYPE=DRIVER_LIBRARY + +INCLUDES=$(_INCLUDES_DIRS) + +C_DEFINES=$(C_DEFINES) -DNDIS_MINIPORT_DRIVER -DNDIS51_MINIPORT=1 +C_DEFINES=$(C_DEFINES) -D_WIN2K_COMPAT_SLIST_USAGE=1 +C_DEFINES=$(C_DEFINES) -DNDIS_WDM=1 $(_BUILD_MODULE_DEF) + +SOURCES= $(_NIC_FILES) diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/dirs b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/dirs new file mode 100644 index 0000000000000..3dc42d39e648d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/dirs @@ -0,0 +1,3 @@ +DIRS= \ + windows + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_ate_agent.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_ate_agent.c new file mode 100644 index 0000000000000..b31d51dd9048f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_ate_agent.c @@ -0,0 +1,1974 @@ + +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + *************************************************************************** + + Module Name: + gl_ate_agent.c +*/ +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ + +#include "precomp.h" +#if CFG_SUPPORT_QA_TOOL +#include "gl_wext.h" +#include "gl_cfg80211.h" +#include "gl_ate_agent.h" +#include "gl_hook_api.h" +#include "gl_qa_agent.h" +/* #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) */ +#include +/* #endif */ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#if CFG_SUPPORT_TX_BF +PFMU_PROFILE_TAG1 g_rPfmuTag1; +PFMU_PROFILE_TAG2 g_rPfmuTag2; +PFMU_DATA g_rPfmuData; +#endif + +typedef struct _ATE_PRIV_CMD { + UINT_8 *name; + int (*set_proc)(struct net_device *prNetDev, UINT_8 *prInBuf); +} ATE_PRIV_CMD, *P_ATE_PRIV_CMD; + +ATE_PRIV_CMD rAtePrivCmdTable[] = { + {"ResetCounter", Set_ResetStatCounter_Proc}, + {"ATE", SetATE}, +#if 0 + {"ADCDump", SetADCDump}, + {"ATEBSSID", SetATEBssid}, +#endif + {"ATEDA", SetATEDa}, + {"ATESA", SetATESa}, + {"ATECHANNEL", SetATEChannel}, + {"ATETXPOW0", SetATETxPower0}, + {"ATETXGI", SetATETxGi}, + {"ATETXBW", SetATETxBw}, + {"ATETXLEN", SetATETxLength}, + {"ATETXCNT", SetATETxCount}, + {"ATETXMCS", SetATETxMcs}, + {"ATETXMODE", SetATETxMode}, + {"ATEIPG", SetATEIpg}, +#if CFG_SUPPORT_TX_BF + {"TxBfProfileTagHelp", Set_TxBfProfileTag_Help}, + {"TxBfProfileTagInValid", Set_TxBfProfileTag_InValid}, + {"TxBfProfileTagPfmuIdx", Set_TxBfProfileTag_PfmuIdx}, + {"TxBfProfileTagBfType", Set_TxBfProfileTag_BfType}, + {"TxBfProfileTagBw", Set_TxBfProfileTag_DBW}, + {"TxBfProfileTagSuMu", Set_TxBfProfileTag_SuMu}, + {"TxBfProfileTagMemAlloc", Set_TxBfProfileTag_Mem}, + {"TxBfProfileTagMatrix", Set_TxBfProfileTag_Matrix}, + {"TxBfProfileTagSnr", Set_TxBfProfileTag_SNR}, + {"TxBfProfileTagSmtAnt", Set_TxBfProfileTag_SmartAnt}, + {"TxBfProfileTagSeIdx", Set_TxBfProfileTag_SeIdx}, + {"TxBfProfileTagRmsdThrd", Set_TxBfProfileTag_RmsdThrd}, + {"TxBfProfileTagMcsThrd", Set_TxBfProfileTag_McsThrd}, + {"TxBfProfileTagTimeOut", Set_TxBfProfileTag_TimeOut}, + {"TxBfProfileTagDesiredBw", Set_TxBfProfileTag_DesiredBW}, + {"TxBfProfileTagDesiredNc", Set_TxBfProfileTag_DesiredNc}, + {"TxBfProfileTagDesiredNr", Set_TxBfProfileTag_DesiredNr}, + {"TxBfProfileTagRead", Set_TxBfProfileTagRead}, + {"TxBfProfileTagWrite", Set_TxBfProfileTagWrite}, + {"TxBfProfileDataRead", Set_TxBfProfileDataRead}, + {"TxBfProfileDataWrite", Set_TxBfProfileDataWrite}, + {"TxBfProfilePnRead", Set_TxBfProfilePnRead}, + {"TxBfProfilePnWrite", Set_TxBfProfilePnWrite}, + {"TxBfSounding", Set_Trigger_Sounding_Proc}, + {"TxBfSoundingStop", Set_Stop_Sounding_Proc}, + {"TxBfTxApply", Set_TxBfTxApply}, + {"TxBfManualAssoc", Set_TxBfManualAssoc}, + {"TxBfPfmuMemAlloc", Set_TxBfPfmuMemAlloc}, + {"TxBfPfmuMemRelease", Set_TxBfPfmuMemRelease}, + {"StaRecCmmUpdate", Set_StaRecCmmUpdate}, + {"StaRecBfUpdate", Set_StaRecBfUpdate}, + {"DevInfoUpdate", Set_DevInfoUpdate}, + {"BssInfoUpdate", Set_BssInfoUpdate}, +#if CFG_SUPPORT_MU_MIMO + {"MUGetInitMCS", Set_MUGetInitMCS}, + {"MUCalInitMCS", Set_MUCalInitMCS}, + {"MUCalLQ", Set_MUCalLQ}, + {"MUGetLQ", Set_MUGetLQ}, + {"MUSetSNROffset", Set_MUSetSNROffset}, + {"MUSetZeroNss", Set_MUSetZeroNss}, + {"MUSetSpeedUpLQ", Set_MUSetSpeedUpLQ}, + {"MUSetMUTable", Set_MUSetMUTable}, + {"MUSetGroup", Set_MUSetGroup}, + {"MUGetQD", Set_MUGetQD}, + {"MUSetEnable", Set_MUSetEnable}, + {"MUSetGID_UP", Set_MUSetGID_UP}, + {"MUTriggerTx", Set_MUTriggerTx}, +#endif +#endif + + {"WriteEfuse", WriteEfuse}, + + {NULL,} +}; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Reset RX Statistic Counters. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +int Set_ResetStatCounter_Proc(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + INT_32 i4Status; + + DBGLOG(REQ, INFO, ": ATE_AGENT iwpriv Set_ResetStatCounter_Proc\n"); + + i4Status = MT_ATEResetTXRXCounter(prNetDev); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set Start Test Mode / Stop Test Mode / Start TX / Stop TX / Start RX / Stop RX. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetATE(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + INT_32 i4Status; + + DBGLOG(REQ, INFO, ": ATE_AGENT iwpriv SetATE\n"); + + if (!strcmp(prInBuf, "ATESTART")) { + DBGLOG(REQ, INFO, ": ATE_AGENT iwpriv SetATE - ATESTART\n"); + i4Status = MT_ATEStart(prNetDev, prInBuf); + } else if (!strcmp(prInBuf, "ICAPSTART")) { + DBGLOG(REQ, INFO, ": ATE_AGENT iwpriv SetATE - ICAPSTART\n"); + i4Status = MT_ICAPStart(prNetDev, prInBuf); + } else if (!strcmp(prInBuf, "ATESTOP")) { + DBGLOG(REQ, INFO, ": ATE_AGENT iwpriv SetATE - ATESTOP\n"); + i4Status = MT_ATEStop(prNetDev, prInBuf); + } else if (!strcmp(prInBuf, "TXFRAME")) { + DBGLOG(REQ, INFO, ": ATE_AGENT iwpriv SetATE - TXFRAME\n"); + i4Status = MT_ATEStartTX(prNetDev, prInBuf); + } else if (!strcmp(prInBuf, "TXSTOP")) { + DBGLOG(REQ, INFO, ": ATE_AGENT iwpriv SetATE - TXSTOP\n"); + i4Status = MT_ATEStopTX(prNetDev, prInBuf); + } else if (!strcmp(prInBuf, "RXFRAME")) { + DBGLOG(REQ, INFO, ": ATE_AGENT iwpriv SetATE - RXFRAME\n"); + i4Status = MT_ATEStartRX(prNetDev, prInBuf); + } else if (!strcmp(prInBuf, "RXSTOP")) { + DBGLOG(REQ, INFO, ": ATE_AGENT iwpriv SetATE - RXSTOP\n"); + i4Status = MT_ATEStopRX(prNetDev, prInBuf); + } else { + return -EINVAL; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set TX Destination Address. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetATEDa(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + INT_32 i4Status = 0; + UINT_32 addr[MAC_ADDR_LEN]; + UINT_8 addr2[MAC_ADDR_LEN]; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, ": ATE_AGENT iwpriv SetDa\n"); + /* xx:xx:xx:xx:xx:xx */ + rv = sscanf(prInBuf, "%x:%x:%x:%x:%x:%x", &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]); + if (rv == 6) { + DBGLOG(RFTEST, ERROR, ": ATE_AGENT iwpriv SetATEDa Sa:%02x:%02x:%02x:%02x:%02x:%02x\n", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + + addr2[0] = (UINT_8) addr[0]; + addr2[1] = (UINT_8) addr[1]; + addr2[2] = (UINT_8) addr[2]; + addr2[3] = (UINT_8) addr[3]; + addr2[4] = (UINT_8) addr[4]; + addr2[5] = (UINT_8) addr[5]; + + i4Status = MT_ATESetMACAddress(prNetDev, RF_AT_FUNCID_SET_MAC_ADDRESS, addr2); + } else { + return -EINVAL; + } + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set TX Source Address. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetATESa(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + INT_32 i4Status = 0; + UINT_32 addr[MAC_ADDR_LEN]; + UINT_8 addr2[MAC_ADDR_LEN]; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, ": ATE_AGENT iwpriv SetSa\n"); + /* xx:xx:xx:xx:xx:xx */ + rv = sscanf(prInBuf, "%x:%x:%x:%x:%x:%x", &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]); + if (rv == 6) { + DBGLOG(RFTEST, ERROR, ": ATE_AGENT iwpriv SetATESa Sa:%02x:%02x:%02x:%02x:%02x:%02x\n", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + + addr2[0] = (UINT_8) addr[0]; + addr2[1] = (UINT_8) addr[1]; + addr2[2] = (UINT_8) addr[2]; + addr2[3] = (UINT_8) addr[3]; + addr2[4] = (UINT_8) addr[4]; + addr2[5] = (UINT_8) addr[5]; + + i4Status = MT_ATESetMACAddress(prNetDev, RF_AT_FUNCID_SET_TA, addr2); + } else { + return -EINVAL; + } + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set Channel Frequency. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetATEChannel(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 i4SetFreq = 0; + INT_32 i4Status, i4SetChan = 0; + INT_32 rv; + + DBGLOG(REQ, INFO, ": ATE_AGENT iwpriv SetChannel\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetChan); + if (rv == 0) { + i4SetFreq = nicChannelNum2Freq(i4SetChan); + i4Status = MT_ATESetChannel(prNetDev, 0, i4SetFreq); + } else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set TX WF0 Power. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetATETxPower0(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 i4SetTxPower0 = 0; + INT_32 i4Status; + INT_32 rv; + + DBGLOG(REQ, INFO, ": ATE_AGENT iwpriv SetTxPower0\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxPower0); + if (rv == 0) + i4Status = MT_ATESetTxPower0(prNetDev, i4SetTxPower0); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set TX Guard Interval. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetATETxGi(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 i4SetTxGi = 0; + INT_32 i4Status; + INT_32 rv; + + DBGLOG(REQ, INFO, ": ATE_AGENT iwpriv SetTxGi\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxGi); + if (rv == 0) + i4Status = MT_ATESetTxGi(prNetDev, i4SetTxGi); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set TX System Bandwidth. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetATETxBw(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 i4SetSystemBW = 0; + INT_32 i4Status; + INT_32 rv; + + DBGLOG(REQ, INFO, ": ATE_AGENT iwpriv SetSystemBW\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetSystemBW); + if (rv == 0) + i4Status = MT_ATESetSystemBW(prNetDev, i4SetSystemBW); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set TX Mode (Preamble). +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetATETxMode(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 i4SetTxMode = 0; + INT_32 i4Status; + INT_32 rv; + + DBGLOG(REQ, INFO, ": ATE_AGENT iwpriv SetTxMode\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxMode); + if (rv == 0) + i4Status = MT_ATESetPreamble(prNetDev, i4SetTxMode); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set TX Length. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetATETxLength(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 i4SetTxLength = 0; + INT_32 i4Status; + INT_32 rv; + + DBGLOG(REQ, INFO, ": ATE_AGENT iwpriv SetTxLength\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxLength); + if (rv == 0) + i4Status = MT_ATESetTxLength(prNetDev, i4SetTxLength); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set TX Count. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetATETxCount(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 i4SetTxCount = 0; + INT_32 i4Status; + INT_32 rv; + UCHAR addr[MAC_ADDR_LEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + + DBGLOG(REQ, INFO, ": ATE_AGENT iwpriv SetTxCount\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxCount); + if (rv == 0) + i4Status = MT_ATESetTxCount(prNetDev, i4SetTxCount); + else + return -EINVAL; + + i4Status = MT_ATESetMACAddress(prNetDev, RF_AT_FUNCID_SET_MAC_ADDRESS, addr); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set TX Rate. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetATETxMcs(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 i4SetTxMcs = 0; + INT_32 i4Status; + INT_32 rv; + + DBGLOG(REQ, INFO, ": ATE_AGENT iwpriv SetTxMcs\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxMcs); + if (rv == 0) + i4Status = MT_ATESetRate(prNetDev, i4SetTxMcs); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set Inter-Packet Guard Interval. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetATEIpg(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 i4SetTxIPG = 0; + INT_32 i4Status; + INT_32 rv; + + DBGLOG(REQ, INFO, ": ATE_AGENT iwpriv SetIpg\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxIPG); + if (rv == 0) + i4Status = MT_ATESetTxIPG(prNetDev, i4SetTxIPG); + else + return -EINVAL; + + return i4Status; +} + +#if CFG_SUPPORT_TX_BF +int Set_TxBfProfileTag_Help(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + DBGLOG(RFTEST, ERROR, + "========================================================================================================================\n" + "TxBfProfile Tag1 setting example :\n" + "iwpriv ra0 set TxBfProfileTagPfmuIdx =xx\n" + "iwpriv ra0 set TxBfProfileTagBfType =xx (0: iBF; 1: eBF)\n" + "iwpriv ra0 set TxBfProfileTagBw =xx (0/1/2/3 : BW20/40/80/160NC)\n" + "iwpriv ra0 set TxBfProfileTagSuMu =xx (0:SU, 1:MU)\n" + "iwpriv ra0 set TxBfProfileTagInvalid =xx (0: valid, 1: invalid)\n" + "iwpriv ra0 set TxBfProfileTagMemAlloc =xx:xx:xx:xx:xx:xx:xx:xx (mem_row, mem_col), ..\n" + "iwpriv ra0 set TxBfProfileTagMatrix =nrow:nol:ng:LM\n" + "iwpriv ra0 set TxBfProfileTagSnr =SNR_STS0:SNR_STS1:SNR_STS2:SNR_STS3\n" + "\n\n" + "TxBfProfile Tag2 setting example :\n" + "iwpriv ra0 set TxBfProfileTagSmtAnt =xx (11:0)\n" + "iwpriv ra0 set TxBfProfileTagSeIdx =xx\n" + "iwpriv ra0 set TxBfProfileTagRmsdThrd =xx\n" + "iwpriv ra0 set TxBfProfileTagMcsThrd =xx:xx:xx:xx:xx:xx (MCS TH L1SS:S1SS:L2SS:....)\n" + "iwpriv ra0 set TxBfProfileTagTimeOut =xx\n" + "iwpriv ra0 set TxBfProfileTagDesiredBw=xx (0/1/2/3 : BW20/40/80/160NC)\n" + "iwpriv ra0 set TxBfProfileTagDesiredNc=xx\n" + "iwpriv ra0 set TxBfProfileTagDesiredNr=xx\n" + "\n\n" + "Read TxBf profile Tag :\n" + "iwpriv ra0 set TxBfProfileTagRead =xx (PFMU ID)\n" + "\n" + "Write TxBf profile Tag :\n" + "iwpriv ra0 set TxBfProfileTagWrite =xx (PFMU ID)\n" + "When you use one of relative CMD to update one of tag parameters, you should call TxBfProfileTagWrite to update Tag\n" + "\n\n" + "Read TxBf profile Data :\n" + "iwpriv ra0 set TxBfProfileDataRead =xx (PFMU ID)\n" + "\n" + "Write TxBf profile Data :\n" + "iwpriv ra0 set TxBfProfileDataWrite =BW :subcarrier:phi11:psi2l:Phi21:Psi31:Phi31:Psi41:Phi22:Psi32:Phi32:Psi42:Phi33:Psi43\n" + "iwpriv ra0 set TxBfProfileDataWriteAll=Profile ID : BW (BW : 0x00 (20M) , 0x01 (40M), 0x02 (80M), 0x3 (160M)\n" + "When you use CMD TxBfProfileDataWrite to update profile data per subcarrier, you should call TxBfProfileDataWriteAll to update all of\n" + "subcarrier's profile data.\n\n" + "Read TxBf profile PN :\n" + "iwpriv ra0 set TxBfProfilePnRead =xx (PFMU ID)\n" + "\n" + "Write TxBf profile PN :\n" + "iwpriv ra0 set TxBfProfilePnWrite =Profile ID:BW:1STS_Tx0:1STS_Tx1:1STS_Tx2:1STS_Tx3:2STS_Tx0:2STS_Tx1:2STS_Tx2:2STS_Tx3:3STS_Tx1:3STS_Tx2:3STS_Tx3\n" + "========================================================================================================================\n"); + return 0; +} + +int Set_TxBfProfileTag_InValid(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 ucInValid; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_InValid\n"); + + rv = kstrtoint(prInBuf, 0, &ucInValid); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_InValid prInBuf = %s, ucInValid = %d\n", prInBuf, + ucInValid); + i4Status = TxBfProfileTag_InValid(prNetDev, &g_rPfmuTag1, ucInValid); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_PfmuIdx(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 ucProfileIdx; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_PfmuIdx\n"); + + rv = kstrtoint(prInBuf, 0, &ucProfileIdx); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_PfmuIdx prInBuf = %s, ucProfileIdx = %d\n", prInBuf, + ucProfileIdx); + i4Status = TxBfProfileTag_PfmuIdx(prNetDev, &g_rPfmuTag1, ucProfileIdx); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_BfType(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 ucBFType; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_BfType\n"); + + rv = kstrtoint(prInBuf, 0, &ucBFType); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_BfType prInBuf = %s, ucBFType = %d\n", + prInBuf, ucBFType); + i4Status = TxBfProfileTag_TxBfType(prNetDev, &g_rPfmuTag1, ucBFType); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_DBW(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 ucBW; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_DBW\n"); + + rv = kstrtoint(prInBuf, 0, &ucBW); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_DBW prInBuf = %s, ucBW = %d\n", prInBuf, ucBW); + i4Status = TxBfProfileTag_DBW(prNetDev, &g_rPfmuTag1, ucBW); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_SuMu(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 ucSuMu; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_SuMu\n"); + + rv = kstrtoint(prInBuf, 0, &ucSuMu); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_SuMu prInBuf = %s, ucSuMu = %d\n", prInBuf, ucSuMu); + i4Status = TxBfProfileTag_SuMu(prNetDev, &g_rPfmuTag1, ucSuMu); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_Mem(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 aucInput[8]; + INT_32 i4Status = 0; + UINT_8 aucMemAddrColIdx[4], aucMemAddrRowIdx[4]; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_Mem\n"); + + rv = sscanf(prInBuf, "%d:%d:%d:%d:%d:%d:%d:%d", + &aucInput[0], &aucInput[1], &aucInput[2], &aucInput[3], &aucInput[4], &aucInput[5], &aucInput[6], + &aucInput[7]); + /* mem col0:row0:col1:row1:col2:row2:col3:row3 */ + if (rv == 8) { + DBGLOG(RFTEST, ERROR, + ": ATE_AGENT iwpriv Set_TxBfProfileTag_Mem aucInput:%d:%d:%d:%d:%d:%d:%d:%d\n", + aucInput[0], aucInput[1], aucInput[2], aucInput[3], aucInput[4], aucInput[5], aucInput[6], + aucInput[7]); + + aucMemAddrColIdx[0] = (UINT_8) aucInput[0]; + aucMemAddrRowIdx[0] = (UINT_8) aucInput[1]; + aucMemAddrColIdx[1] = (UINT_8) aucInput[2]; + aucMemAddrRowIdx[1] = (UINT_8) aucInput[3]; + aucMemAddrColIdx[2] = (UINT_8) aucInput[4]; + aucMemAddrRowIdx[2] = (UINT_8) aucInput[5]; + aucMemAddrColIdx[3] = (UINT_8) aucInput[6]; + aucMemAddrRowIdx[3] = (UINT_8) aucInput[7]; + + i4Status = TxBfProfileTag_Mem(prNetDev, &g_rPfmuTag1, aucMemAddrColIdx, aucMemAddrRowIdx); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_Matrix(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 aucInput[6]; + UINT_8 ucNrow, ucNcol, ucNgroup, ucLM, ucCodeBook, ucHtcExist; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_Matrix\n"); + + rv = sscanf(prInBuf, "%d:%d:%d:%d:%d:%d", + &aucInput[0], &aucInput[1], &aucInput[2], &aucInput[3], &aucInput[4], &aucInput[5]); + /* nrow:nol:ng:LM:CodeBook:HtcExist */ + if (rv == 6) { + DBGLOG(RFTEST, ERROR, + ": ATE_AGENT iwpriv Set_TxBfProfileTag_Matrix aucInput:%d:%d:%d:%d:%d:%d\n", + aucInput[0], aucInput[1], aucInput[2], aucInput[3], aucInput[4], aucInput[5]); + ucNrow = (UINT_8) aucInput[0]; + ucNcol = (UINT_8) aucInput[1]; + ucNgroup = (UINT_8) aucInput[2]; + ucLM = (UINT_8) aucInput[3]; + ucCodeBook = (UINT_8) aucInput[4]; + ucHtcExist = (UINT_8) aucInput[5]; + + i4Status = TxBfProfileTag_Matrix(prNetDev, + &g_rPfmuTag1, ucNrow, ucNcol, ucNgroup, ucLM, ucCodeBook, ucHtcExist); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_SNR(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 aucInput[4]; + UINT_8 ucSNR_STS0, ucSNR_STS1, ucSNR_STS2, ucSNR_STS3; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_SNR\n"); + + rv = sscanf(prInBuf, "%d:%d:%d:%d", &aucInput[0], &aucInput[1], &aucInput[2], &aucInput[3]); + if (rv == 4) { + DBGLOG(RFTEST, ERROR, ": ATE_AGENT iwpriv Set_TxBfProfileTag_SNR aucInput:%d:%d:%d:%d\n", + aucInput[0], aucInput[1], aucInput[2], aucInput[3]); + + ucSNR_STS0 = (UINT_8) aucInput[0]; + ucSNR_STS1 = (UINT_8) aucInput[1]; + ucSNR_STS2 = (UINT_8) aucInput[2]; + ucSNR_STS3 = (UINT_8) aucInput[3]; + + i4Status = TxBfProfileTag_SNR(prNetDev, &g_rPfmuTag1, ucSNR_STS0, ucSNR_STS1, ucSNR_STS2, ucSNR_STS3); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_SmartAnt(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + INT_32 i4Status = 0; + UINT_32 ucSmartAnt; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_SmartAnt\n"); + + rv = kstrtoint(prInBuf, 0, &ucSmartAnt); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_SmartAnt prInBuf = %s, ucSmartAnt = %d\n", prInBuf, + ucSmartAnt); + i4Status = TxBfProfileTag_SmtAnt(prNetDev, &g_rPfmuTag2, ucSmartAnt); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_SeIdx(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + INT_32 i4Status = 0; + UINT_32 ucSeIdx; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_SeIdx\n"); + + rv = kstrtoint(prInBuf, 0, &ucSeIdx); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "TxBfProfileTag_SeIdx prInBuf = %s, ucSeIdx = %d\n", prInBuf, ucSeIdx); + i4Status = TxBfProfileTag_SeIdx(prNetDev, &g_rPfmuTag2, ucSeIdx); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_RmsdThrd(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + INT_32 i4Status = 0; + UINT_32 ucRmsdThrd; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_RmsdThrd\n"); + + rv = kstrtoint(prInBuf, 0, &ucRmsdThrd); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_RmsdThrd prInBuf = %s, ucRmsdThrd = %d\n", prInBuf, + ucRmsdThrd); + i4Status = TxBfProfileTag_RmsdThd(prNetDev, &g_rPfmuTag2, ucRmsdThrd); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_McsThrd(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 aucInput[6]; + UINT_8 ucMcsLss[3], ucMcsSss[3]; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_McsThrd\n"); + + rv = sscanf(prInBuf, "%d:%d:%d:%d:%d:%d", + &aucInput[0], &aucInput[1], &aucInput[2], &aucInput[3], &aucInput[4], &aucInput[5]); + if (rv == 6) { + DBGLOG(RFTEST, ERROR, + ": ATE_AGENT iwpriv Set_TxBfProfileTag_McsThrd aucInput:%d:%d:%d:%d:%d:%d\n", + aucInput[0], aucInput[1], aucInput[2], aucInput[3], aucInput[4], aucInput[5]); + + ucMcsLss[0] = (UINT_8) aucInput[0]; + ucMcsSss[0] = (UINT_8) aucInput[1]; + ucMcsLss[1] = (UINT_8) aucInput[2]; + ucMcsSss[1] = (UINT_8) aucInput[3]; + ucMcsLss[2] = (UINT_8) aucInput[4]; + ucMcsSss[2] = (UINT_8) aucInput[5]; + + i4Status = TxBfProfileTag_McsThd(prNetDev, &g_rPfmuTag2, ucMcsLss, ucMcsSss); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_TimeOut(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 ucTimeOut; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_TimeOut\n"); + + rv = kstrtouint(prInBuf, 0, &ucTimeOut); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_TimeOut prInBuf = %s, ucTimeOut = %d\n", prInBuf, + ucTimeOut); + i4Status = TxBfProfileTag_TimeOut(prNetDev, &g_rPfmuTag2, ucTimeOut); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_DesiredBW(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 ucDesiredBW; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_DesiredBW\n"); + + rv = kstrtoint(prInBuf, 0, &ucDesiredBW); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_DesiredBW prInBuf = %s, ucDesiredBW = %d\n", prInBuf, + ucDesiredBW); + i4Status = TxBfProfileTag_DesiredBW(prNetDev, &g_rPfmuTag2, ucDesiredBW); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_DesiredNc(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 ucDesiredNc; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_DesiredNc\n"); + + rv = kstrtoint(prInBuf, 0, &ucDesiredNc); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_DesiredNc prInBuf = %s, ucDesiredNc = %d\n", prInBuf, + ucDesiredNc); + i4Status = TxBfProfileTag_DesiredNc(prNetDev, &g_rPfmuTag2, ucDesiredNc); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_DesiredNr(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 ucDesiredNr; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_DesiredNr\n"); + + rv = kstrtoint(prInBuf, 0, &ucDesiredNr); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_DesiredNr prInBuf = %s, ucDesiredNr = %d\n", prInBuf, + ucDesiredNr); + i4Status = TxBfProfileTag_DesiredNr(prNetDev, &g_rPfmuTag2, ucDesiredNr); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTagWrite(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 profileIdx; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTagWrite\n"); + + rv = kstrtoint(prInBuf, 0, &profileIdx); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTagWrite prInBuf = %s, profileIdx = %d\n", prInBuf, + profileIdx); + i4Status = TxBfProfileTagWrite(prNetDev, &g_rPfmuTag1, &g_rPfmuTag2, profileIdx); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTagRead(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 profileIdx, fgBFer; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTagRead\n"); + + rv = sscanf(prInBuf, "%d:%d", &profileIdx, &fgBFer); + if (rv == 2) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTagRead prInBuf = %s, profileIdx = %d, fgBFer = %d\n", + prInBuf, profileIdx, fgBFer); + i4Status = TxBfProfileTagRead(prNetDev, profileIdx, fgBFer); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileDataRead(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 profileIdx, fgBFer, subcarrierIdxMsb, subcarrierIdxLsb; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileDataRead\n"); + + rv = sscanf(prInBuf, "%d:%d:%x:%x", &profileIdx, &fgBFer, &subcarrierIdxMsb, &subcarrierIdxLsb); + if (rv == 4) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileDataRead prInBuf = %s, profileIdx = %d, fgBFer = %d, subcarrierIdxMsb:%x, subcarrierIdxLsb:%x\n", + prInBuf, profileIdx, fgBFer, subcarrierIdxMsb, subcarrierIdxLsb); + i4Status = TxBfProfileDataRead(prNetDev, profileIdx, fgBFer, subcarrierIdxMsb, subcarrierIdxLsb); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileDataWrite(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + + UINT_32 u4ProfileIdx; + UINT_32 u4SubcarrierIdx; + UINT_32 au4Phi[6]; + UINT_32 au4Psi[6]; + UINT_32 au4DSnr[4]; + UINT_16 au2Phi[6]; + UINT_8 aucPsi[6]; + UINT_8 aucDSnr[4]; + UINT_32 i; + INT_32 rv; + + INT_32 i4Status = 0; + + DBGLOG(RFTEST, ERROR, "TxBfProfileDataWrite\n"); + + rv = sscanf(prInBuf, "%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x", + &u4ProfileIdx, &u4SubcarrierIdx, &au4Phi[0], &au4Psi[0], &au4Phi[1], &au4Psi[1], + &au4Phi[2], &au4Psi[2], &au4Phi[3], &au4Psi[3], &au4Phi[4], &au4Psi[4], + &au4Phi[5], &au4Psi[5], + &au4DSnr[0], &au4DSnr[1], &au4DSnr[2], &au4DSnr[3]); + + if (rv == 18) { + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite prInBuf = %s, u4ProfileIdx = %x, u4SubcarrierIdx = %x, au4Phi[0]:%x, au4Phi[1]:%x, au4Phi[2]:%x, au4Phi[3]:%x, au4Phi[4]:%x, au4Phi[5]:%x, au4Psi[0]:%x, au4Psi[1]:%x, au4Psi[2]:%x, au4Psi[3]:%x, au4Psi[4]:%x, au4Psi[5]:%x,au4DSnr[0]:%x, au4DSnr[1]:%x, au4DSnr[2]:%x, au4DSnr[3]:%x\n", + prInBuf, u4ProfileIdx, u4SubcarrierIdx, + au4Phi[0], au4Phi[1], au4Phi[2], au4Phi[3], au4Phi[4], au4Phi[5], + au4Psi[0], au4Psi[1], au4Psi[2], au4Psi[3], au4Psi[4], au4Psi[5], + au4DSnr[0], au4DSnr[1], au4DSnr[2], au4DSnr[3]); + for (i = 0; i < 6; i++) { + au2Phi[i] = au4Phi[i]; + aucPsi[i] = au4Psi[i]; + } + for (i = 0; i < 4; i++) + aucDSnr[i] = au4DSnr[i]; + + i4Status = TxBfProfileDataWrite(prNetDev, u4ProfileIdx, u4SubcarrierIdx, au2Phi, aucPsi, aucDSnr); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfilePnRead(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 profileIdx; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfilePnRead\n"); + + rv = kstrtoint(prInBuf, 0, &profileIdx); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "Set_TxBfProfilePnRead prInBuf = %s, profileIdx = %d\n", + prInBuf, profileIdx); + i4Status = TxBfProfilePnRead(prNetDev, profileIdx); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfilePnWrite(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4ProfileIdx; + UINT_16 u2bw; + UINT_16 au2XSTS[12]; + INT_32 rv; + + + DBGLOG(RFTEST, ERROR, "TxBfProfilePnWrite\n"); + + rv = sscanf(prInBuf, "%u:%hu:%hu:%hu:%hu:%hu:%hu:%hu:%hu:%hu:%hu:%hu:%hu:%hu", + &u4ProfileIdx, &u2bw, &au2XSTS[0], &au2XSTS[1], &au2XSTS[2], &au2XSTS[3], + &au2XSTS[4], &au2XSTS[5], &au2XSTS[6], &au2XSTS[7], &au2XSTS[8], &au2XSTS[9], &au2XSTS[10], + &au2XSTS[11]); + if (rv != 14) + return -EINVAL; + + DBGLOG(RFTEST, ERROR, + "prInBuf=%s,Idx=%u,u2bw=%d, au2XSTS: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n", + prInBuf, u4ProfileIdx, u2bw, au2XSTS[0], au2XSTS[1], au2XSTS[2], au2XSTS[3], au2XSTS[4], au2XSTS[5], + au2XSTS[6], au2XSTS[7], au2XSTS[8], au2XSTS[9], au2XSTS[10], au2XSTS[11]); + + return TxBfProfilePnWrite(prNetDev, u4ProfileIdx, u2bw, au2XSTS); +} + +/* Su_Mu:NumSta:SndInterval:WLan0:WLan1:WLan2:WLan3 */ +int Set_Trigger_Sounding_Proc(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 ucSuMu, ucNumSta, ucSndInterval, ucWLan0, ucWLan1, ucWLan2, ucWLan3; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_Trigger_Sounding_Proc\n"); + + rv = sscanf + (prInBuf, "%x:%x:%x:%x:%x:%x:%x", &ucSuMu, &ucNumSta, &ucSndInterval, &ucWLan0, &ucWLan1, &ucWLan2, + &ucWLan3); + if (rv != 7) + return -EINVAL; + + DBGLOG(RFTEST, ERROR, + "Set_Trigger_Sounding_Proc prInBuf = %s, ucSuMu = %d, ucNumSta = %d, ucSndInterval = %d, ucWLan0 = %d, ucWLan1 = %d, ucWLan2:%d, ucWLan3:%d\n", + prInBuf, ucSuMu, ucNumSta, ucSndInterval, ucWLan0, ucWLan1, ucWLan2, ucWLan3); + i4Status = TxBfSounding(prNetDev, ucSuMu, ucNumSta, ucSndInterval, ucWLan0, ucWLan1, ucWLan2, ucWLan3); + + return i4Status; +} + +int Set_Stop_Sounding_Proc(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + INT_32 i4Status = 0; + + DBGLOG(RFTEST, ERROR, "Set_Stop_Sounding_Proc\n"); + + i4Status = TxBfSoundingStop(prNetDev); + + return i4Status; +} + +int Set_TxBfTxApply(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4WlanId, u4ETxBf, u4ITxBf, u4MuTxBf; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "TxBfTxApply\n"); + + rv = sscanf(prInBuf, "%d:%d:%d:%d", &u4WlanId, &u4ETxBf, &u4ITxBf, &u4MuTxBf); + if (rv == 4) { + DBGLOG(RFTEST, ERROR, + "TxBfTxApply prInBuf = %s, u4WlanId = %d, u4ETxBf = %d, u4ITxBf = %d, u4MuTxBf = %d\n", + prInBuf, u4WlanId, u4ETxBf, u4ITxBf, u4MuTxBf); + i4Status = TxBfTxApply(prNetDev, u4WlanId, u4ETxBf, u4ITxBf, u4MuTxBf); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfManualAssoc(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + INT_32 au4Mac[MAC_ADDR_LEN]; + INT_32 u4Type, u4Wtbl, u4Ownmac, u4PhyMode, u4Bw, u4Nss, u4PfmuId, u4Mode, u4Marate, u4SpeIdx, ucaid, u4Rv; + INT_8 aucMac[MAC_ADDR_LEN]; + INT_32 i4Status = 0; + INT_32 i = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "TxBfManualAssoc\n"); + + rv = sscanf(prInBuf, "%x:%x:%x:%x:%x:%x:%x:%d:%x:%x:%x:%x:%d:%x:%x:%x:%d:%x", + &au4Mac[0], &au4Mac[1], &au4Mac[2], &au4Mac[3], &au4Mac[4], &au4Mac[5], + &u4Type, &u4Wtbl, &u4Ownmac, &u4PhyMode, &u4Bw, &u4Nss, &u4PfmuId, &u4Mode, &u4Marate, &u4SpeIdx, + &ucaid, &u4Rv); + if (rv == 18) { + DBGLOG(RFTEST, ERROR, + "TxBfManualAssoc au4Mac[0] = %x, au4Mac[1] = %x, au4Mac[2] = %xau4Mac[3] = %x, au4Mac[4] = %x, au4Mac[5] = %x, u4Type = %x, u4Wtbl = %d, u4Ownmac = %x, u4PhyMode = %x u4Bw = %x, u4Nss = %x, u4PfmuId = %d, u4Mode = %x, u4Marate = %x, u4SpeIdx = %d, ucaid = %d, u4Rv = %x", + au4Mac[0], au4Mac[1], au4Mac[2], au4Mac[3], au4Mac[4], au4Mac[5], u4Type, u4Wtbl, u4Ownmac, + u4PhyMode, u4Bw, u4Nss, u4PfmuId, u4Mode, u4Marate, u4SpeIdx, ucaid, u4Rv); + for (i = 0; i < MAC_ADDR_LEN; i++) + aucMac[i] = au4Mac[i]; + + i4Status = + TxBfManualAssoc(prNetDev, aucMac, u4Type, u4Wtbl, u4Ownmac, u4Mode, u4Bw, u4Nss, u4PfmuId, u4Marate, + u4SpeIdx, ucaid, u4Rv); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfPfmuMemAlloc(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 ucSuMuMode, ucWlanIdx; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "TxBfPfmuMemAlloc\n"); + + rv = sscanf(prInBuf, "%d:%d", &ucSuMuMode, &ucWlanIdx); + if (rv == 2) { + DBGLOG(RFTEST, ERROR, "TxBfPfmuMemAlloc ucSuMuMode = %d, ucWlanIdx = %d", ucSuMuMode, ucWlanIdx); + i4Status = TxBfPfmuMemAlloc(prNetDev, ucSuMuMode, ucWlanIdx); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfPfmuMemRelease(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 ucWlanId; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "TxBfPfmuMemRelease\n"); + + rv = kstrtoint(prInBuf, 0, &ucWlanId); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "TxBfPfmuMemRelease ucWlanId = %d", ucWlanId); + i4Status = TxBfPfmuMemRelease(prNetDev, ucWlanId); + } else + return -EINVAL; + + return i4Status; +} + +int Set_DevInfoUpdate(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4OwnMacIdx, fgBand; + UINT_32 OwnMacAddr[MAC_ADDR_LEN]; + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + INT_32 i4Status = 0; + UINT_32 i; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "DevInfoUpdate\n"); + + rv = sscanf + (prInBuf, "%d:%x:%x:%x:%x:%x:%x:%d", &u4OwnMacIdx, &OwnMacAddr[0], &OwnMacAddr[1], &OwnMacAddr[2], + &OwnMacAddr[3], &OwnMacAddr[4], &OwnMacAddr[5], &fgBand); + if (rv == 8) { + DBGLOG(RFTEST, ERROR, + "DevInfoUpdate prInBuf = %s, u4OwnMacIdx = %x, fgBand = %x,OwnMacAddr[0]:%x, OwnMacAddr[1]:%x, OwnMacAddr[2]:%x, OwnMacAddr[3]:%x, OwnMacAddr[4]:%x, OwnMacAddr[5]:%x,", + prInBuf, u4OwnMacIdx, fgBand, OwnMacAddr[0], OwnMacAddr[1], OwnMacAddr[2], OwnMacAddr[3], + OwnMacAddr[4], OwnMacAddr[5]); + for (i = 0; i < MAC_ADDR_LEN; i++) + aucMacAddr[i] = OwnMacAddr[i]; + + i4Status = DevInfoUpdate(prNetDev, u4OwnMacIdx, fgBand, aucMacAddr); + } else + return -EINVAL; + + return i4Status; +} + +int Set_BssInfoUpdate(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4OwnMacIdx, u4BssIdx; + UINT_32 au4BssId[MAC_ADDR_LEN]; + UINT_8 aucBssId[MAC_ADDR_LEN]; + INT_32 i4Status = 0; + UINT_32 i; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "BssInfoUpdate\n"); + + rv = sscanf + (prInBuf, "%d:%d:%x:%x:%x:%x:%x:%x", &u4OwnMacIdx, &u4BssIdx, &au4BssId[0], &au4BssId[1], &au4BssId[2], + &au4BssId[3], &au4BssId[4], &au4BssId[5]); + if (rv == 8) { + DBGLOG(RFTEST, ERROR, + "BssInfoUpdate prInBuf = %s, u4OwnMacIdx = %x, u4BssIdx = %x,au4BssId[0]:%x, au4BssId[1]:%x, au4BssId[2]:%x, au4BssId[3]:%x, au4BssId[4]:%x, au4BssId[5]:%x,", + prInBuf, u4OwnMacIdx, u4BssIdx, au4BssId[0], au4BssId[1], au4BssId[2], au4BssId[3], au4BssId[4], + au4BssId[5]); + for (i = 0; i < MAC_ADDR_LEN; i++) + aucBssId[i] = au4BssId[i]; + + i4Status = BssInfoUpdate(prNetDev, u4OwnMacIdx, u4BssIdx, aucBssId); + } else + return -EINVAL; + + return i4Status; +} + +int Set_StaRecCmmUpdate(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4WlanId, u4BssId, u4Aid; + UINT_32 au4MacAddr[MAC_ADDR_LEN]; + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + INT_32 i4Status = 0; + UINT_32 i; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_StaRecCmmUpdate\n"); + + rv = sscanf + (prInBuf, "%x:%x:%x:%x:%x:%x:%x:%x:%x", &u4WlanId, &u4BssId, &u4Aid, &au4MacAddr[0], &au4MacAddr[1], + &au4MacAddr[2], &au4MacAddr[3], &au4MacAddr[4], &au4MacAddr[5]); + if (rv == 9) { + DBGLOG(RFTEST, ERROR, + "Set_StaRecCmmUpdate prInBuf = %s, u4WlanId = %x, u4BssId = %x, u4Aid = %x,aucMacAddr[0]:%x, aucMacAddr[1]:%x, aucMacAddr[2]:%x, aucMacAddr[3]:%x, aucMacAddr[4]:%x, aucMacAddr[5]:%x,", + prInBuf, u4WlanId, u4BssId, u4Aid, au4MacAddr[0], au4MacAddr[1], au4MacAddr[2], au4MacAddr[3], + au4MacAddr[4], au4MacAddr[5]); + for (i = 0; i < MAC_ADDR_LEN; i++) + aucMacAddr[i] = au4MacAddr[i]; + + i4Status = StaRecCmmUpdate(prNetDev, u4WlanId, u4BssId, u4Aid, aucMacAddr); + } else + return -EINVAL; + + return i4Status; +} + +int Set_StaRecBfUpdate(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + STA_REC_BF_UPD_ARGUMENT rStaRecBfUpdArg; + UINT_8 aucMemRow[4], aucMemCol[4]; + INT_32 i4Status = 0; + UINT_32 i; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_StaRecBfUpdate\n"); + + rv = sscanf(prInBuf, "%x:%x:%x:%x:%x:%d:%d:%d:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x", + &rStaRecBfUpdArg.u4WlanId, &rStaRecBfUpdArg.u4BssId, &rStaRecBfUpdArg.u4PfmuId, + &rStaRecBfUpdArg.u4SuMu, &rStaRecBfUpdArg.u4eTxBfCap, &rStaRecBfUpdArg.u4NdpaRate, + &rStaRecBfUpdArg.u4NdpRate, &rStaRecBfUpdArg.u4ReptPollRate, &rStaRecBfUpdArg.u4TxMode, + &rStaRecBfUpdArg.u4Nc, &rStaRecBfUpdArg.u4Nr, &rStaRecBfUpdArg.u4Bw, &rStaRecBfUpdArg.u4SpeIdx, + &rStaRecBfUpdArg.u4TotalMemReq, &rStaRecBfUpdArg.u4MemReq20M, &rStaRecBfUpdArg.au4MemRow[0], + &rStaRecBfUpdArg.au4MemCol[0], &rStaRecBfUpdArg.au4MemRow[1], &rStaRecBfUpdArg.au4MemCol[1], + &rStaRecBfUpdArg.au4MemRow[2], &rStaRecBfUpdArg.au4MemCol[2], &rStaRecBfUpdArg.au4MemRow[3], + &rStaRecBfUpdArg.au4MemCol[3]); + if (rv == 23) { + /* DBGLOG(RFTEST, ERROR, + * "Set_StaRecBfUpdate prInBuf = %s, u4WlanId = %x, u4BssId = %x, u4Aid = %x, + * aucMacAddr[0]:%x, aucMacAddr[1]:%x, aucMacAddr[2]:%x, aucMacAddr[3]:%x, aucMacAddr[4]:%x, + * aucMacAddr[5]:%x", + * prInBuf, u4OwnMacIdx, u4BssIdx, u4Aid, + * aucMacAddr[0], aucMacAddr[1], aucMacAddr[2], aucMacAddr[3], aucMacAddr[4], aucMacAddr[5]); + */ + for (i = 0; i < 4; i++) { + aucMemRow[i] = rStaRecBfUpdArg.au4MemRow[i]; + aucMemCol[i] = rStaRecBfUpdArg.au4MemCol[i]; + } + i4Status = StaRecBfUpdate(prNetDev, rStaRecBfUpdArg, aucMemRow, aucMemCol); + } else + return -EINVAL; + + return i4Status; +} + +#if CFG_SUPPORT_MU_MIMO +int Set_MUGetInitMCS(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T rMuMimoActionInfo; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + + UINT_32 u4groupIdx; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_MUGetInitMCS\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rv = kstrtouint(prInBuf, 0, &u4groupIdx); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "Test\n"); + DBGLOG(RFTEST, ERROR, "Set_MUGetInitMCS prInBuf = %s, u4groupIdx = %x", prInBuf, u4groupIdx); + + rMuMimoActionInfo.ucMuMimoCategory = MU_GET_CALC_INIT_MCS; + rMuMimoActionInfo.unMuMimoParam.rMuGetCalcInitMcs.ucgroupIdx = u4groupIdx; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, sizeof(rMuMimoActionInfo), TRUE, TRUE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUCalInitMCS(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T rMuMimoActionInfo; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + + UINT_32 u4NumOfUser, u4Bandwidth, u4NssOfUser0, u4NssOfUser1, u4PfMuIdOfUser0, u4PfMuIdOfUser1, u4NumOfTxer, + u4SpeIndex, u4GroupIndex; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_MUCalInitMCS\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rv = sscanf + (prInBuf, "%x:%x:%x:%x:%x:%x:%x:%x:%x", &u4NumOfUser, &u4Bandwidth, &u4NssOfUser0, &u4NssOfUser1, + &u4PfMuIdOfUser0, &u4PfMuIdOfUser1, &u4NumOfTxer, &u4SpeIndex, &u4GroupIndex); + if (rv == 9) { + DBGLOG(RFTEST, ERROR, + "Set_MUCalInitMCS prInBuf = %s, u4NumOfUser = %x, u4Bandwidth = %x, u4NssOfUser0 = %x, u4NssOfUser1 = %x, u4PfMuIdOfUser0 = %x, u4PfMuIdOfUser1 = %x, u4NumOfTxer = %x, u4SpeIndex = %x, u4GroupIndex = %x", + prInBuf, u4NumOfUser, u4Bandwidth, u4NssOfUser0, u4NssOfUser1, u4PfMuIdOfUser0, u4PfMuIdOfUser1, + u4NumOfTxer, u4SpeIndex, u4GroupIndex); + + rMuMimoActionInfo.ucMuMimoCategory = MU_SET_CALC_INIT_MCS; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucNumOfUser = u4NumOfUser; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucBandwidth = u4Bandwidth; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucNssOfUser0 = u4NssOfUser0; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucNssOfUser1 = u4NssOfUser1; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucPfMuIdOfUser0 = u4PfMuIdOfUser0; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucPfMuIdOfUser1 = u4PfMuIdOfUser1; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucNumOfTxer = u4NumOfTxer; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucSpeIndex = u4SpeIndex; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.u4GroupIndex = u4GroupIndex; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, sizeof(rMuMimoActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUCalLQ(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T rMuMimoActionInfo; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + + UINT_32 u4NumOfUser, u4Bandwidth, u4NssOfUser0, u4NssOfUser1, u4PfMuIdOfUser0, u4PfMuIdOfUser1, + u4NumOfTxer, u4SpeIndex, u4GroupIndex; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_MUCalLQ\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rv = sscanf + (prInBuf, "%x:%x:%x:%x:%x:%x:%x:%x:%x", &u4NumOfUser, &u4Bandwidth, &u4NssOfUser0, &u4NssOfUser1, + &u4PfMuIdOfUser0, &u4PfMuIdOfUser1, &u4NumOfTxer, &u4SpeIndex, &u4GroupIndex); + if (rv == 9) { + DBGLOG(RFTEST, ERROR, + "Set_MUCalLQ prInBuf = %s, u4NumOfUser = %x, u4Bandwidth = %x, u4NssOfUser0 = %x, u4NssOfUser1 = %x, u4PfMuIdOfUser0 = %x, u4PfMuIdOfUser1 = %x, u4NumOfTxer = %x, u4SpeIndex = %x, u4GroupIndex = %x", + prInBuf, u4NumOfUser, u4Bandwidth, u4NssOfUser0, u4NssOfUser1, u4PfMuIdOfUser0, u4PfMuIdOfUser1, + u4NumOfTxer, u4SpeIndex, u4GroupIndex); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_CALC_LQ; + /* rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucType = u4Type; */ + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucNumOfUser = u4NumOfUser; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucBandwidth = u4Bandwidth; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucNssOfUser0 = u4NssOfUser0; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucNssOfUser1 = u4NssOfUser1; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucPfMuIdOfUser0 = u4PfMuIdOfUser0; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucPfMuIdOfUser1 = u4PfMuIdOfUser1; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucNumOfTxer = u4NumOfTxer; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucSpeIndex = u4SpeIndex; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.u4GroupIndex = u4GroupIndex; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, sizeof(rMuMimoActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUGetLQ(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T rMuMimoActionInfo; + INT_32 i4Status = 0; + /* UINT_32 u4Type; */ + UINT_32 u4BufLen = 0; + + DBGLOG(RFTEST, ERROR, "Set_MUGetLQ\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* if (sscanf(prInBuf, "%x", &u4Type) == 1) */ + /* { */ + /* DBGLOG(RFTEST, ERROR, "Set_MUGetLQ prInBuf = %s, u4Type = %x", prInBuf, u4Type); */ + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_GET_CALC_LQ; + /* rMuMimoActionInfo.unMuMimoParam.rMuGetLq.ucType = u4Type; */ + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, sizeof(rMuMimoActionInfo), TRUE, TRUE, TRUE, &u4BufLen); + /* } */ + /* else */ + /* { */ + /* return -EINVAL; */ + /* } */ + + return i4Status; +} + +int Set_MUSetSNROffset(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T rMuMimoActionInfo; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + + UINT_32 u4Val; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_MUSetSNROffset\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rv = kstrtoint(prInBuf, 0, &u4Val); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "Set_MUSetSNROffset prInBuf = %s, u4Val = %x", prInBuf, u4Val); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_SNR_OFFSET; + rMuMimoActionInfo.unMuMimoParam.rMuSetSnrOffset.ucVal = u4Val; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, sizeof(rMuMimoActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUSetZeroNss(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T rMuMimoActionInfo; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + + UINT_32 u4Val; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_MUSetZeroNss\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rv = kstrtouint(prInBuf, 0, &u4Val); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "Set_MUSetZeroNss prInBuf = %s, u4Val = %x", prInBuf, u4Val); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_ZERO_NSS; + rMuMimoActionInfo.unMuMimoParam.rMuSetZeroNss.ucVal = u4Val; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, sizeof(rMuMimoActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUSetSpeedUpLQ(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T rMuMimoActionInfo; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + + UINT_32 u4Val; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_MUSetSpeedUpLQ\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rv = kstrtouint(prInBuf, 0, &u4Val); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "Set_MUSetSpeedUpLQ prInBuf = %s, u4Val = %x", prInBuf, u4Val); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_SPEED_UP_LQ; + rMuMimoActionInfo.unMuMimoParam.rMuSpeedUpLq.u4Val = u4Val; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, sizeof(rMuMimoActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUSetMUTable(struct net_device *prNetDev, UINT_8 *prTable) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T rMuMimoActionInfo; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + /* UINT_32 i; */ + + /* UINT_32 u4Type, u4Length; */ + + DBGLOG(RFTEST, ERROR, "Set_MUSetMUTable\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* if (sscanf(prInBuf, "%x:%x", &u4Type, &u4Length) == 2) */ + /* { */ + /* DBGLOG(RFTEST, ERROR, "Set_MUSetMUTable prInBuf = %s, */ + /* u4Type = %x, u4Length = %x", prInBuf, u4Type, u4Length); */ + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_MU_TABLE; + /* rMuMimoActionInfo.unMuMimoParam.rMuSetMuTable.u2Type = u4Type; */ + /* rMuMimoActionInfo.unMuMimoParam.rMuSetMuTable.u4Length = u4Length; */ + + /* for ( i = 0 ; i < NUM_MUT_NR_NUM * NUM_MUT_FEC * NUM_MUT_MCS * NUM_MUT_INDEX ; i++) */ + /* { */ + memcpy(rMuMimoActionInfo.unMuMimoParam.rMuSetMuTable.aucMetricTable, prTable, + NUM_MUT_NR_NUM * NUM_MUT_FEC * NUM_MUT_MCS * NUM_MUT_INDEX); + /* } */ + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, sizeof(rMuMimoActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + /* } */ + /* else */ + /* { */ + /* return -EINVAL; */ + /* } */ + + return i4Status; +} + +int Set_MUSetGroup(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T rMuMimoActionInfo; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + UINT_32 i = 0; + + UINT_32 aucUser0MacAddr[PARAM_MAC_ADDR_LEN], aucUser1MacAddr[PARAM_MAC_ADDR_LEN]; + + DBGLOG(RFTEST, ERROR, "Set_MUSetGroup\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (sscanf(prInBuf, "%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x", + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4GroupIndex, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4NumOfUser, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0Ldpc, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1Ldpc, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4ShortGI, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4Bw, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0Nss, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1Nss, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4GroupId, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0UP, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1UP, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0MuPfId, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1MuPfId, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0InitMCS, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1InitMCS, &aucUser0MacAddr[0], + &aucUser0MacAddr[1], &aucUser0MacAddr[2], &aucUser0MacAddr[3], &aucUser0MacAddr[4], + &aucUser0MacAddr[5], &aucUser1MacAddr[0], &aucUser1MacAddr[1], &aucUser1MacAddr[2], + &aucUser1MacAddr[3], &aucUser1MacAddr[4], &aucUser1MacAddr[5]) == 27) { + DBGLOG(RFTEST, ERROR, + "Set_MUSetGroup prInBuf = %s,u4GroupIndex = %d, u4NumOfUser = %d, u4User0Ldpc = %d, u4User1Ldpc = %d, u4ShortGI = %d, u4Bw = %d, u4User0Nss = %d, u4User1Nss = %d, u4GroupId = %d, u4User0UP = %d, u4User1UP = %d, u4User0MuPfId = %d, u4User1MuPfId = %d, u4User0InitMCS = %d, u4User1InitMCS = %d,aucUser0MacAddr[0] = %x, aucUser0MacAddr[1] = %x, aucUser0MacAddr[2] = %x, aucUser0MacAddr[3] = %x, aucUser0MacAddr[4] = %x, aucUser0MacAddr[5] = %x,aucUser1MacAddr[0] = %x, aucUser1MacAddr[1] = %x, aucUser1MacAddr[2] = %x, aucUser1MacAddr[3] = %x, aucUser1MacAddr[4] = %x, aucUser1MacAddr[5] = %x,", + prInBuf, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4GroupIndex, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4NumOfUser, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0Ldpc, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1Ldpc, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4ShortGI, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4Bw, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0Nss, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1Nss, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4GroupId, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0UP, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1UP, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0MuPfId, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1MuPfId, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0InitMCS, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1InitMCS, aucUser0MacAddr[0], + aucUser0MacAddr[1], aucUser0MacAddr[2], aucUser0MacAddr[3], aucUser0MacAddr[4], + aucUser0MacAddr[5], aucUser1MacAddr[0], aucUser1MacAddr[1], aucUser1MacAddr[2], + aucUser1MacAddr[3], aucUser1MacAddr[4], aucUser1MacAddr[5] + ); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_GROUP; + for (i = 0; i < PARAM_MAC_ADDR_LEN; i++) { + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.aucUser0MacAddr[i] = aucUser0MacAddr[i]; + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.aucUser1MacAddr[i] = aucUser1MacAddr[i]; + } + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, sizeof(rMuMimoActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + } else { + return -EINVAL; + } + + return i4Status; +} + +int Set_MUGetQD(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T rMuMimoActionInfo; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + + UINT_32 u4SubcarrierIndex, u4Length; + + DBGLOG(RFTEST, ERROR, "Set_MUGetQD\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (sscanf(prInBuf, "%x:%x", &u4SubcarrierIndex, &u4Length) == 2) { + DBGLOG(RFTEST, ERROR, "Set_MUGetQD prInBuf = %s, u4SubcarrierIndex = %x, u4Length = %x", prInBuf, + u4SubcarrierIndex, u4Length); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_GET_QD; + rMuMimoActionInfo.unMuMimoParam.rMuGetQd.ucSubcarrierIndex = u4SubcarrierIndex; + /* rMuMimoActionInfo.unMuMimoParam.rMuGetQd.u4Length = u4Length; */ + /* rMuMimoActionInfo.unMuMimoParam.rMuGetQd.ucgroupIdx = ucgroupIdx; */ + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, sizeof(rMuMimoActionInfo), TRUE, TRUE, TRUE, &u4BufLen); + } else { + return -EINVAL; + } + + return i4Status; +} + +int Set_MUSetEnable(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T rMuMimoActionInfo; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + + UINT_32 u4Val; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "Set_MUSetEnable\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rv = kstrtouint(prInBuf, 0, &u4Val); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "Set_MUSetEnable prInBuf = %s, u4Val = %x", prInBuf, u4Val); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_ENABLE; + rMuMimoActionInfo.unMuMimoParam.rMuSetEnable.ucVal = u4Val; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, sizeof(rMuMimoActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUSetGID_UP(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T rMuMimoActionInfo; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + + DBGLOG(RFTEST, ERROR, "Set_MUSetGID_UP\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (sscanf(prInBuf, "%x:%x:%x:%x:%x:%x", + &rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Gid[0], + &rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Gid[1], + &rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[0], + &rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[1], + &rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[2], + &rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[3]) == 6) { + DBGLOG(RFTEST, ERROR, + "Set_MUSetGID_UP prInBuf = %s, au4Gid[0] = %x, au4Gid[1] = %x, au4Up[0] = %x, au4Up[1] = %x, au4Up[2] = %x, au4Up[3] = %x", + prInBuf, rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Gid[0], + rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Gid[1], + rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[0], + rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[1], + rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[2], + rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[3]); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_STA_PARAM; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, sizeof(rMuMimoActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + } else { + return -EINVAL; + } + + return i4Status; +} + +int Set_MUTriggerTx(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T rMuMimoActionInfo; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + UINT_32 i, j; + + UINT_32 u4IsRandomPattern, u4MsduPayloadLength0, u4MsduPayloadLength1, u4MuPacketCount, u4NumOfSTAs; + UINT_32 au4MacAddrs[2][6]; + + DBGLOG(RFTEST, ERROR, "Set_MUTriggerTx\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (sscanf(prInBuf, "%d:%x:%x:%x:%d:%d:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x", + &u4IsRandomPattern, &u4MsduPayloadLength0, &u4MsduPayloadLength1, &u4MuPacketCount, &u4NumOfSTAs, + &au4MacAddrs[0][0], &au4MacAddrs[0][1], &au4MacAddrs[0][2], &au4MacAddrs[0][3], &au4MacAddrs[0][4], + &au4MacAddrs[0][5], &au4MacAddrs[1][0], &au4MacAddrs[1][1], &au4MacAddrs[1][2], &au4MacAddrs[1][3], + &au4MacAddrs[1][4], &au4MacAddrs[1][5]) == 17) { + DBGLOG(RFTEST, ERROR, + "Set_MUTriggerTx prInBuf = %s, u4IsRandomPattern = %x, u4MsduPayloadLength0 = %x, u4MsduPayloadLength1 = %x, u4MuPacketCount = %x, u4NumOfSTAs = %x, au4MacAddrs[0][0] = %x, au4MacAddrs[0][1] = %x, au4MacAddrs[0][2] = %x, au4MacAddrs[0][3] = %x, au4MacAddrs[0][4] = %x, au4MacAddrs[0][5] = %x,au4MacAddrs[1][0] = %x, au4MacAddrs[1][1] = %x, au4MacAddrs[1][2] = %x, au4MacAddrs[1][3] = %x, au4MacAddrs[1][4] = %x, au4MacAddrs[1][5] = %x", + prInBuf, u4IsRandomPattern, u4MsduPayloadLength0, u4MsduPayloadLength1, u4MuPacketCount, + u4NumOfSTAs, au4MacAddrs[0][0], au4MacAddrs[0][1], au4MacAddrs[0][2], au4MacAddrs[0][3], + au4MacAddrs[0][4], au4MacAddrs[0][5], au4MacAddrs[1][0], au4MacAddrs[1][1], au4MacAddrs[1][2], + au4MacAddrs[1][3], au4MacAddrs[1][4], au4MacAddrs[1][5]); + + rMuMimoActionInfo.ucMuMimoCategory = MU_SET_TRIGGER_MU_TX; + rMuMimoActionInfo.unMuMimoParam.rMuTriggerMuTx.fgIsRandomPattern = u4IsRandomPattern; + rMuMimoActionInfo.unMuMimoParam.rMuTriggerMuTx.u4MsduPayloadLength0 = u4MsduPayloadLength0; + rMuMimoActionInfo.unMuMimoParam.rMuTriggerMuTx.u4MsduPayloadLength1 = u4MsduPayloadLength1; + rMuMimoActionInfo.unMuMimoParam.rMuTriggerMuTx.u4MuPacketCount = u4MuPacketCount; + rMuMimoActionInfo.unMuMimoParam.rMuTriggerMuTx.u4NumOfSTAs = u4NumOfSTAs; + + for (i = 0 ; i < 2 ; i++) { + for (j = 0 ; j < PARAM_MAC_ADDR_LEN ; j++) + rMuMimoActionInfo.unMuMimoParam.rMuTriggerMuTx.aucMacAddrs[i][j] = au4MacAddrs[i][j]; + } + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, sizeof(rMuMimoActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + } else { + return -EINVAL; + } + + return i4Status; +} +#endif +#endif + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Write Efuse. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int WriteEfuse(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + INT_32 i4Status; + INT_32 rv; + UINT_32 addr[2]; + UINT_16 addr2[2]; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv WriteEfuse, buf: %s\n", prInBuf); + + rv = sscanf(prInBuf, "%x:%x", &addr[0], &addr[1]); + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv WriteEfuse, prInBuf: %s\n", prInBuf); + DBGLOG(INIT, ERROR, "ATE_AGENT iwpriv WriteEfuse :%02x:%02x\n", addr[0], addr[1]); + + addr2[0] = (UINT_16) addr[0]; + addr2[1] = (UINT_16) addr[1]; + + if (rv == 2) + i4Status = MT_ATEWriteEfuse(prNetDev, addr2[0], addr2[1]); + else + return -EINVAL; + + return i4Status; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to search the corresponding ATE agent function. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int AteCmdSetHandle(struct net_device *prNetDev, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + UINT_8 *this_char, *value; + P_ATE_PRIV_CMD prAtePrivCmd; + INT_32 i4Status = 0; + + while ((this_char = strsep((char **)&prInBuf, ",")) != NULL) { + if (!*this_char) + continue; + DBGLOG(RFTEST, ERROR, "ATE_AGENT iwpriv this_char = %s\n", this_char); + DBGLOG(RFTEST, INFO, "ATE_AGENT iwpriv this_char = %s\n", this_char); + + value = strchr(this_char, '='); + if (value != NULL) + *value++ = 0; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv cmd = %s, value = %s\n", this_char, value); + + for (prAtePrivCmd = rAtePrivCmdTable; prAtePrivCmd->name; prAtePrivCmd++) { + if (!strcmp(this_char, prAtePrivCmd->name)) { + /*FALSE:Set private failed then return Invalid argument */ + if (prAtePrivCmd->set_proc(prNetDev, value) != 0) + i4Status = -EINVAL; + break; /*Exit for loop. */ + } + } + + if (prAtePrivCmd->name == NULL) { /*Not found argument */ + i4Status = -EINVAL; + break; + } + } + return i4Status; +} +#endif /*CFG_SUPPORT_QA_TOOL */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_bow.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_bow.c new file mode 100644 index 0000000000000..9804e437486ec --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_bow.c @@ -0,0 +1,1138 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * 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. + */ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "debug.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "precomp.h" +#include +#include "bss.h" + +#if CFG_ENABLE_BT_OVER_WIFI + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* @FIXME if there is command/event with payload length > 28 */ +#define MAX_BUFFER_SIZE (64) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +UINT_32 g_u4PrevSysTime; +UINT_32 g_u4CurrentSysTime; +UINT_32 g_arBowRevPalPacketTime[32]; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/* forward declarations */ +static ssize_t bow_ampc_read(IN struct file *filp, IN char __user *buf, IN size_t size, IN OUT loff_t *ppos); + +static ssize_t bow_ampc_write(IN struct file *filp, OUT const char __user *buf, IN size_t size, IN OUT loff_t *ppos); + +static long bow_ampc_ioctl(IN struct file *filp, IN unsigned int cmd, IN OUT unsigned long arg); + +static unsigned int bow_ampc_poll(IN struct file *filp, IN poll_table * wait); + +static int bow_ampc_open(IN struct inode *inodep, IN struct file *filp); + +static int bow_ampc_release(IN struct inode *inodep, IN struct file *filp); + +/* character file operations */ +static const struct file_operations bow_ampc_fops = { + /* .owner = THIS_MODULE, */ + .read = bow_ampc_read, + .write = bow_ampc_write, + .unlocked_ioctl = bow_ampc_ioctl, + .poll = bow_ampc_poll, + .open = bow_ampc_open, + .release = bow_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); + + DBGLOG(BOW, TRACE, "Register for character device to communicate with 802.11 PAL.\n"); + + if (prGlueInfo->rBowInfo.fgIsRegistered == TRUE) + return FALSE; + +#if 0 + /* 1. allocate major number dynamically */ + + if (alloc_chrdev_region(&(prGlueInfo->rBowInfo.u4DeviceNumber), 0, /* first minor number */ + 1, /* number */ + GLUE_BOW_DEVICE_NAME) != 0) + + return FALSE; +#endif + +#if 1 + +#if defined(CONFIG_AMPC_CDEV_NUM) + prGlueInfo->rBowInfo.u4DeviceNumber = MKDEV(CONFIG_AMPC_CDEV_NUM, 0); +#else + prGlueInfo->rBowInfo.u4DeviceNumber = MKDEV(226, 0); +#endif + + if (register_chrdev_region(prGlueInfo->rBowInfo.u4DeviceNumber, 1, /* number */ + GLUE_BOW_DEVICE_NAME) != 0) + + return FALSE; +#endif + + /* 2. spin-lock initialization */ + /* spin_lock_init(&(prGlueInfo->rBowInfo.rSpinLock)); */ + + /* 3. initialize kfifo */ + /* + * prGlueInfo->rBowInfo.prKfifo = kfifo_alloc(GLUE_BOW_KFIFO_DEPTH, + * GFP_KERNEL, + * &(prGlueInfo->rBowInfo.rSpinLock)); + */ + if ((kfifo_alloc((struct kfifo *)&(prGlueInfo->rBowInfo.rKfifo), GLUE_BOW_KFIFO_DEPTH, GFP_KERNEL))) + goto fail_kfifo_alloc; + + /* if(prGlueInfo->rBowInfo.prKfifo == NULL) */ + if (&(prGlueInfo->rBowInfo.rKfifo) == NULL) + goto fail_kfifo_alloc; + + /* 4. initialize cdev */ + cdev_init(&(prGlueInfo->rBowInfo.cdev), &bow_ampc_fops); + /* prGlueInfo->rBowInfo.cdev.owner = THIS_MODULE; */ + prGlueInfo->rBowInfo.cdev.ops = &bow_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); + + DBGLOG(BOW, INFO, "Unregister character device for communicating with 802.11 PAL.\n"); + + if (prGlueInfo->rBowInfo.fgIsRegistered == FALSE) + return FALSE; + + prGlueInfo->rBowInfo.fgIsRegistered = FALSE; + + /* 1. free netdev if necessary */ +#if CFG_BOW_SEPARATE_DATA_PATH + kalUninitBowDevice(prGlueInfo); +#endif + + /* 2. removal of character device */ + cdev_del(&(prGlueInfo->rBowInfo.cdev)); + + /* 3. free kfifo */ +/* kfifo_free(prGlueInfo->rBowInfo.prKfifo); */ + kfifo_free(&(prGlueInfo->rBowInfo.rKfifo)); +/* prGlueInfo->rBowInfo.prKfifo = NULL; */ +/* prGlueInfo->rBowInfo.rKfifo = NULL; */ + + /* 4. free device number */ + unregister_chrdev_region(prGlueInfo->rBowInfo.u4DeviceNumber, 1); + + return TRUE; +} /* end of glUnregisterAmpc */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief read handler for character device to communicate with 802.11 PAL +* +* \param[in] +* \return +* Follows Linux Character Device Interface +* +*/ +/*----------------------------------------------------------------------------*/ +static ssize_t bow_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); + + DBGLOG(BOW, INFO, "BoW EVENT read.\n"); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return -EFAULT; + /* size check */ +/* if(kfifo_len(prGlueInfo->rBowInfo.prKfifo) >= size) */ + if (kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)) >= size) + retval = size; + else + retval = kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)); +/* retval = kfifo_len(prGlueInfo->rBowInfo.prKfifo); */ + +/* kfifo_get(prGlueInfo->rBowInfo.prKfifo, aucBuffer, retval); */ +/* kfifo_out(prGlueInfo->rBowInfo.prKfifo, aucBuffer, retval); */ + if (!(kfifo_out(&(prGlueInfo->rBowInfo.rKfifo), aucBuffer, retval))) { + if (copy_to_user(buf, aucBuffer, retval)) + retval = -EIO; + } else + 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 bow_ampc_write(IN struct file *filp, OUT const char __user *buf, IN size_t size, IN OUT loff_t *ppos) +{ + UINT_8 i; + + UINT_8 aucBuffer[MAX_BUFFER_SIZE]; + P_AMPC_COMMAND prCmd; + P_GLUE_INFO_T prGlueInfo; + + prGlueInfo = (P_GLUE_INFO_T) (filp->private_data); + ASSERT(prGlueInfo); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return -EFAULT; + + if (size > MAX_BUFFER_SIZE) + return -EINVAL; + else if (copy_from_user(aucBuffer, buf, size)) + return -EIO; + + DBGLOG(BOW, EVENT, "AMP driver CMD buffer size : %zu.\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"); + + prCmd = (P_AMPC_COMMAND) aucBuffer; + + DBGLOG(BOW, EVENT, "AMP write content payload length : %d.\n", prCmd->rHeader.u2PayloadLength); + + DBGLOG(BOW, EVENT, "AMP write content header length : %zu.\n", sizeof(AMPC_COMMAND_HEADER_T)); + + /* size check */ + if (prCmd->rHeader.u2PayloadLength + sizeof(AMPC_COMMAND_HEADER_T) != size) { + DBGLOG(BOW, EVENT, "Wrong CMD total length.\n"); + + 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 bow_ampc_ioctl(IN struct file *filp, IN unsigned int cmd, IN OUT unsigned long arg) +{ + int err = 0; + P_GLUE_INFO_T prGlueInfo; + + prGlueInfo = (P_GLUE_INFO_T) (filp->private_data); + + ASSERT(prGlueInfo); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return -EFAULT; + /* permission check */ + if (_IOC_DIR(cmd) & _IOC_READ) + err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)); + else if (_IOC_DIR(cmd) & _IOC_WRITE) + err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)); + if (err) + return -EFAULT; + + /* no ioctl is implemented yet */ + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief ioctl handler for character device to communicate with 802.11 PAL +* +* \param[in] +* \return +* Follows Linux Character Device Interface +* +*/ +/*----------------------------------------------------------------------------*/ +static unsigned int bow_ampc_poll(IN struct file *filp, IN poll_table * wait) +{ + unsigned int retval; + P_GLUE_INFO_T prGlueInfo; + + prGlueInfo = (P_GLUE_INFO_T) (filp->private_data); + + ASSERT(prGlueInfo); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return -EFAULT; + + poll_wait(filp, &prGlueInfo->rBowInfo.outq, wait); + + retval = (POLLOUT | POLLWRNORM); /* always accepts incoming command packets */ + +/* DBGLOG(BOW, EVENT, ("bow_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, ("bow_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 bow_ampc_open(IN struct inode *inodep, IN struct file *filp) +{ + P_GLUE_INFO_T prGlueInfo; + P_GL_BOW_INFO prBowInfo; + + DBGLOG(BOW, INFO, "in %s\n", __func__); + + 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 bow_ampc_release(IN struct inode *inodep, IN struct file *filp) +{ + P_GLUE_INFO_T prGlueInfo; + + prGlueInfo = (P_GLUE_INFO_T) (filp->private_data); + + DBGLOG(BOW, INFO, "in %s\n", __func__); + + ASSERT(prGlueInfo); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to indicate event for Bluetooth over Wi-Fi +* +* \param[in] +* prGlueInfo +* prEvent +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalIndicateBOWEvent(IN P_GLUE_INFO_T prGlueInfo, IN P_AMPC_EVENT prEvent) +{ + size_t u4AvailSize, u4EventSize; + + ASSERT(prGlueInfo); + ASSERT(prEvent); + + /* check device */ + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return; + + /* + * u4AvailSize = + * GLUE_BOW_KFIFO_DEPTH - kfifo_len(prGlueInfo->rBowInfo.prKfifo); + */ + + u4AvailSize = GLUE_BOW_KFIFO_DEPTH - kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)); + + u4EventSize = prEvent->rHeader.u2PayloadLength + sizeof(AMPC_EVENT_HEADER_T); + + /* check kfifo availability */ + if (u4AvailSize < u4EventSize) { + DBGLOG(BOW, EVENT, "[bow] no space for event: %zu/%zu\n", u4EventSize, u4AvailSize); + return; + } + /* queue into kfifo */ + /* kfifo_put(prGlueInfo->rBowInfo.prKfifo, (PUINT_8)prEvent, u4EventSize); */ + /* kfifo_in(prGlueInfo->rBowInfo.prKfifo, (PUINT_8)prEvent, u4EventSize); */ + kfifo_in(&(prGlueInfo->rBowInfo.rKfifo), (PUINT_8) prEvent, u4EventSize); + wake_up_interruptible(&(prGlueInfo->rBowInfo.outq)); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Bluetooth-over-Wi-Fi state from glue layer +* +* \param[in] +* prGlueInfo +* rPeerAddr +* \return +* ENUM_BOW_DEVICE_STATE +*/ +/*----------------------------------------------------------------------------*/ +ENUM_BOW_DEVICE_STATE kalGetBowState(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 aucPeerAddress[6]) +{ + UINT_8 i; + + ASSERT(prGlueInfo); + + DBGLOG(BOW, EVENT, "kalGetBowState.\n"); + + for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { + if (EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr, aucPeerAddress) == 0) { + 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]); + + 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 0 /* fix me for 32bit project build error */ + DBGLOG(BOW, EVENT, "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]); +#endif + + DBGLOG(BOW, EVENT, "aucPeerAddress, %x:%x:%x:%x:%x:%x\n", + aucPeerAddress[0], aucPeerAddress[1], + aucPeerAddress[2], aucPeerAddress[3], + aucPeerAddress[4], aucPeerAddress[5]); + + for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { + if (EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr, aucPeerAddress) == 0) { + prGlueInfo->rBowInfo.aeState[i] = eBowState; + + DBGLOG(BOW, EVENT, "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, "prGlueInfo->rBowInfo.aeState %x, %x.\n", i, + prGlueInfo->rBowInfo.aeState[i]); + + 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) { + /* Henry, 0 : Responder, 1 : Initiator */ + prGlueInfo->rBowInfo.aucRole[i] = ucRole; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 + DBGLOG(BOW, EVENT, "kalGetBowAvailablePhysicalLinkCount, ucLinkCount, %c.\n", ucLinkCount); +#endif + + return ucLinkCount; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This inline function is to extract some packet information for BoW +* +* @param prGlueInfo Pointer to the glue structure +* @param prNdisPacket Packet descriptor +* @param pfgIs1X 802.1x packet or not +* +* @retval TRUE Success to extract information +* @retval FALSE Fail to extract correct information +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalBowFrameClassifier(IN P_GLUE_INFO_T prGlueInfo, IN P_NATIVE_PACKET prPacket, OUT PBOOLEAN pfgIs1X) +{ + UINT_32 u4PacketLen; + UINT_16 u2EtherTypeLen; + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + PUINT_8 aucLookAheadBuf = NULL; + UINT_8 ucEthTypeLenOffset = ETHER_HEADER_LEN - ETHER_TYPE_LEN; + PUINT_8 pucNextProtocol = NULL; + UINT_8 aucLLC[] = ETH_LLC; + UINT_8 aucSnapBtOui[] = ETH_SNAP_BT_SIG_OUI; + UINT_8 ucMinLength = ucEthTypeLenOffset + ETHER_TYPE_LEN + ETH_LLC_LEN + ETH_SNAP_LEN; + + DEBUGFUNC("kalQoSFrameClassifierAndPacketInfo"); + + u4PacketLen = prSkb->len; + + if (u4PacketLen < ETHER_HEADER_LEN) { + DBGLOG(INIT, WARN, "Invalid Ether packet length: %u\n", u4PacketLen); + return FALSE; + } + + aucLookAheadBuf = prSkb->data; + + *pfgIs1X = FALSE; + + /* 4 <0> Obtain Ether Type/Len */ + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[ucEthTypeLenOffset], &u2EtherTypeLen); + + /* 4 <1> Skip 802.1Q header (VLAN Tagging) */ + if (u2EtherTypeLen == ETH_P_VLAN) { + ucEthTypeLenOffset += ETH_802_1Q_HEADER_LEN; + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[ucEthTypeLenOffset], &u2EtherTypeLen); + } + /* 4 <2> Obtain next protocol pointer */ + pucNextProtocol = &aucLookAheadBuf[ucEthTypeLenOffset + ETHER_TYPE_LEN]; + + /* 4 <3> Handle ethernet format */ + if (u2EtherTypeLen > ETH_802_3_MAX_LEN) { + /* Not BoW frame */ + return FALSE; + } + /* 4 <4> Check for PAL (BT over Wi-Fi) */ + /* BoW LLC/SNAP header check */ + if (u4PacketLen >= ucMinLength && + !kalMemCmp(pucNextProtocol, aucLLC, ETH_LLC_LEN) && + !kalMemCmp(pucNextProtocol + ETH_LLC_LEN, aucSnapBtOui, ETH_SNAP_OUI_LEN)) { + UINT_16 u2LocalCode; + + WLAN_GET_FIELD_BE16(pucNextProtocol + ETH_LLC_LEN + ETH_SNAP_OUI_LEN, &u2LocalCode); + + if (u2LocalCode == BOW_PROTOCOL_ID_SECURITY_FRAME) + *pfgIs1X = TRUE; + + return TRUE; + } + + return FALSE; +} /* end of kalBoWFrameClassifier() */ + +#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; +}; + +#if 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; + UINT_8 ucBssIndex; + + 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)) { + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(BOW, TRACE, "GLUE_FLAG_HALT skip tx\n"); + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } + + GLUE_SET_PKT_FLAG_PAL(prSkb); + + ucBssIndex = wlanGetBssIdxByNetInterface(prGlueInfo, NET_DEV_BOW_IDX); + + GLUE_SET_PKT_BSS_IDX(prSkb, ucBssIndex); + + prQueueEntry = (P_QUE_ENTRY_T) GLUE_GET_PKT_QUEUE_ENTRY(prSkb); + prTxQueue = &prGlueInfo->rTxQueue; + + 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[ucBssIndex][u2QueueIdx]); + + if (prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex][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; +} +#else +/*----------------------------------------------------------------------------*/ +/*! + * \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_NETDEV_PRIVATE_GLUE_INFO prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_8 ucBssIndex; + BOOLEAN fgIs1x; + + ASSERT(prSkb); + ASSERT(prDev); + +#if 1 + prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(prDev); + prGlueInfo = prNetDevPrivate->prGlueInfo; + ucBssIndex = prNetDevPrivate->ucBssIdx; +#else + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + + ucBssIndex = wlanGetBssIdxByNetInterface(prGlueInfo, NET_DEV_BOW_IDX); +#endif + + kalResetPacket(prGlueInfo, (P_NATIVE_PACKET) prSkb); + prGlueInfo->u8SkbToDriver++; + + /* Discard frames not generated by PAL */ + /* Parsing BOW frame info */ + if (!kalBowFrameClassifier(prGlueInfo, (P_NATIVE_PACKET) prSkb, &fgIs1x)) { + /* Cannot extract packet */ + DBGLOG(BOW, INFO, "Invalid BOW frame, skip Tx\n"); + dev_kfree_skb(prSkb); + prGlueInfo->u8SkbFreed++; + return NETDEV_TX_OK; + } + + if (fgIs1x) + GLUE_SET_PKT_FLAG(prSkb, ENUM_PKT_1X); + + if (kalHardStartXmit(prSkb, prDev, prGlueInfo, ucBssIndex) == WLAN_STATUS_SUCCESS) { + /* Successfully enqueue to Tx queue */ + /* Successfully enqueue to Tx queue */ + } + + /* For Linux, we'll always return OK FLAG, because we'll free this skb by ourself */ + return NETDEV_TX_OK; +} +#endif + +/* 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; + P_NETDEV_PRIVATE_GLUE_INFO prNetDevPriv = (P_NETDEV_PRIVATE_GLUE_INFO) NULL; + + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->rBowInfo.fgIsRegistered == TRUE); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prHif = &prGlueInfo->rHifInfo; + ASSERT(prHif); + + if (prGlueInfo->rBowInfo.fgIsNetRegistered == FALSE) { + prGlueInfo->rBowInfo.prDevHandler = + alloc_netdev_mq(sizeof(P_GLUE_INFO_T), prDevName, + NET_NAME_PREDICTABLE, ether_setup, CFG_MAX_TXQ_NUM); + + if (!prGlueInfo->rBowInfo.prDevHandler) + return FALSE; + + /* 1. setup netdev */ + /* 1.1 Point to shared glue structure */ + /* *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->rBowInfo.prDevHandler)) = prGlueInfo; */ + prNetDevPriv = (P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(prGlueInfo->rBowInfo.prDevHandler); + prNetDevPriv->prGlueInfo = prGlueInfo; + + /* 1.2 fill hardware address */ + COPY_MAC_ADDR(rMacAddr, prAdapter->rMyMacAddr); + rMacAddr[0] |= 0x2; /* change to local administrated address */ + ether_addr_copy(prGlueInfo->rBowInfo.prDevHandler->dev_addr, rMacAddr); + ether_addr_copy(prGlueInfo->rBowInfo.prDevHandler->perm_addr, + prGlueInfo->rBowInfo.prDevHandler->dev_addr); + + /* 1.3 register callback functions */ + prGlueInfo->rBowInfo.prDevHandler->netdev_ops = &bow_netdev_ops; + +#if (MTK_WCN_HIF_SDIO == 0) + SET_NETDEV_DEV(prGlueInfo->rBowInfo.prDevHandler, prHif->Dev); +#endif + + register_netdev(prGlueInfo->rBowInfo.prDevHandler); + + /* 2. net device initialize */ + netif_carrier_off(prGlueInfo->rBowInfo.prDevHandler); + netif_tx_stop_all_queues(prGlueInfo->rBowInfo.prDevHandler); + + /* 2.1 bind NetDev pointer to NetDev index */ + wlanBindBssIdxToNetInterface(prGlueInfo, bowInit(prAdapter), + (PVOID) prGlueInfo->rBowInfo.prDevHandler); + prNetDevPriv->ucBssIdx = prAdapter->rWifiVar.rBowFsmInfo.ucBssIndex; + /* wlanBindNetInterface(prGlueInfo, NET_DEV_BOW_IDX, */ + /* (PVOID)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) +{ + P_ADAPTER_T prAdapter; + + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + /* ASSERT(prGlueInfo->rBowInfo.fgIsRegistered == TRUE); */ + + if (prGlueInfo->rBowInfo.fgIsNetRegistered == TRUE) { + + prGlueInfo->rBowInfo.fgIsNetRegistered = FALSE; + + bowUninit(prAdapter); + + if (netif_carrier_ok(prGlueInfo->rBowInfo.prDevHandler)) + netif_carrier_off(prGlueInfo->rBowInfo.prDevHandler); + + netif_tx_stop_all_queues(prGlueInfo->rBowInfo.prDevHandler); + + /* netdevice unregistration & free */ + unregister_netdev(prGlueInfo->rBowInfo.prDevHandler); + free_netdev(prGlueInfo->rBowInfo.prDevHandler); + prGlueInfo->rBowInfo.prDevHandler = NULL; + + return TRUE; + + } else { + return FALSE; + } +} + +#endif /* CFG_BOW_SEPARATE_DATA_PATH */ +#endif /* CFG_ENABLE_BT_OVER_WIFI */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_cfg80211.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_cfg80211.c new file mode 100644 index 0000000000000..47721b38dc5ab --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_cfg80211.c @@ -0,0 +1,3305 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** 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. + */ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "debug.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "precomp.h" +#include +#include +#include +#include "gl_cfg80211.h" + +/******************************************************************************* +* 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 responsible for change STA type between + * 1. Infrastructure Client (Non-AP STA) + * 2. Ad-Hoc IBSS + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +#if (KERNEL_VERSION(4, 12, 0) <= LINUX_VERSION_CODE) +int +mtk_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, enum nl80211_iftype type, struct vif_params *params) +#else +int +mtk_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, enum nl80211_iftype type, u32 *flags, struct vif_params *params) +#endif +{ + 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, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, + "set infrastructure mode error:%x\n", rStatus); + } + + /* reset wpa info */ + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + prGlueInfo->rWpaInfo.u4KeyMgmt = 0; + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; +#if CFG_SUPPORT_802_11W + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; + prGlueInfo->rWpaInfo.ucRSNMfpCap = RSN_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], tmp2[8]; + + const UINT_8 aucBCAddr[] = BC_MAC_ADDR; + const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if DBG + DBGLOG(RSN, TRACE, "mtk_cfg80211_add_key\n"); + if (mac_addr) { + DBGLOG(RSN, TRACE, + "keyIdx = %d pairwise = %d mac = " MACSTR "\n", key_index, pairwise, MAC2STR(mac_addr)); + } else { + DBGLOG(RSN, TRACE, "keyIdx = %d pairwise = %d null mac\n", key_index, pairwise); + } + DBGLOG(RSN, TRACE, "Cipher = %x\n", params->cipher); + DBGLOG_MEM8(RSN, TRACE, params->key, params->key_len); +#endif + + kalMemZero(&rKey, sizeof(PARAM_KEY_T)); + + rKey.u4KeyIndex = key_index; + + if (mac_addr) { + if (EQUAL_MAC_ADDR(mac_addr, aucZeroMacAddr)) + COPY_MAC_ADDR(rKey.arBSSID, aucBCAddr); + else + COPY_MAC_ADDR(rKey.arBSSID, mac_addr); + + if (pairwise) { + /* if (!((rKey.arBSSID[0] */ + /* & rKey.arBSSID[1] */ + /* & rKey.arBSSID[2] */ + /* & rKey.arBSSID[3] */ + /* & rKey.arBSSID[4] */ + /* & rKey.arBSSID[5]) == 0xFF)) { */ + /* rKey.u4KeyIndex |= BIT(31); */ + /* } */ + rKey.u4KeyIndex |= BIT(31); + rKey.u4KeyIndex |= BIT(30); + } + } else { /* Group key */ + COPY_MAC_ADDR(rKey.arBSSID, aucBCAddr); + } + + if (params->key) { + kalMemCopy(rKey.aucKeyMaterial, params->key, params->key_len); + if (params->key_len == 32) { + kalMemCopy(tmp1, ¶ms->key[16], 8); + kalMemCopy(tmp2, ¶ms->key[24], 8); + kalMemCopy(&rKey.aucKeyMaterial[16], tmp2, 8); + kalMemCopy(&rKey.aucKeyMaterial[24], tmp1, 8); + } + } + + rKey.u4KeyLength = params->key_len; + rKey.u4Length = OFFSET_OF(PARAM_KEY_T, aucKeyMaterial) + rKey.u4KeyLength; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetAddKey, &rKey, rKey.u4Length, FALSE, FALSE, TRUE, &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 + DBGLOG(INIT, INFO, "--> %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); + +#if DBG + DBGLOG(RSN, TRACE, "mtk_cfg80211_del_key\n"); + if (mac_addr) { + DBGLOG(RSN, TRACE, + "keyIdx = %d pairwise = %d mac = " MACSTR "\n", key_index, pairwise, MAC2STR(mac_addr)); + } else { + DBGLOG(RSN, TRACE, "keyIdx = %d pairwise = %d null mac\n", key_index, pairwise); + } +#endif + + 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, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + /* ToDo:: DBGLOG */ + DBGLOG(REQ, WARN, "remove key error:%x\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; + PARAM_DEFAULT_KEY_T rDefaultKey; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + INT_32 i4Rst = -EINVAL; + UINT_32 u4BufLen = 0; + BOOLEAN fgDef = FALSE, fgMgtDef = FALSE; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if DBG + DBGLOG(RSN, TRACE, "mtk_cfg80211_set_default_key\n"); + DBGLOG(RSN, TRACE, "keyIdx = %d unicast = %d multicast = %d\n", key_index, unicast, multicast); +#endif + + rDefaultKey.ucKeyID = key_index; + rDefaultKey.ucUnicast = unicast; + rDefaultKey.ucMulticast = multicast; + if (rDefaultKey.ucUnicast && !rDefaultKey.ucMulticast) + return WLAN_STATUS_SUCCESS; + + if (rDefaultKey.ucUnicast && rDefaultKey.ucMulticast) + fgDef = TRUE; + + if (!rDefaultKey.ucUnicast && rDefaultKey.ucMulticast) + fgMgtDef = TRUE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetDefaultKey, + &rDefaultKey, sizeof(PARAM_DEFAULT_KEY_T), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_SUCCESS) + i4Rst = 0; + + return i4Rst; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for getting station information such as RSSI + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, const u8 *mac, struct station_info *sinfo) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + PARAM_MAC_ADDRESS arBssid; + UINT_32 u4BufLen, u4Rate; + INT_32 i4Rssi; + PARAM_GET_STA_STA_STATISTICS rQueryStaStatistics; + UINT_32 u4TotalError; + struct net_device_stats *prDevStats; + + 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 MAC address */ + /* Should be currently connected BSSID or device itself + * wificond will bring the MAC address of device itself to retrieve TX/RX statistics + */ + if (UNEQUAL_MAC_ADDR(arBssid, mac) && UNEQUAL_MAC_ADDR(ndev->dev_addr, mac)) { + /* wrong MAC address */ + DBGLOG(REQ, WARN, + "Incorrect MAC addr[" MACSTR "], device[" MACSTR "], currently connected BSSID[" MACSTR "]\n", + MAC2STR(mac), MAC2STR(ndev->dev_addr), MAC2STR(arBssid)); + return -ENOENT; + } + + /* 2. fill TX rate */ + if (prGlueInfo->eParamMediaStateIndicated != PARAM_MEDIA_STATE_CONNECTED) { + /* not connected */ + DBGLOG(REQ, WARN, "not yet connected\n"); + return 0; + } + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryLinkSpeed, &u4Rate, sizeof(u4Rate), TRUE, FALSE, FALSE, &u4BufLen); + + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); +#else + sinfo->filled |= STATION_INFO_TX_BITRATE; +#endif + + if ((rStatus != WLAN_STATUS_SUCCESS) || (u4Rate == 0)) { + /* + * DBGLOG(REQ, WARN, "unable to retrieve link speed\n")); + */ + DBGLOG(REQ, WARN, "last link speed\n"); + sinfo->txrate.legacy = prGlueInfo->u4LinkSpeedCache; + } else { + /* + * sinfo->filled |= STATION_INFO_TX_BITRATE; + */ + sinfo->txrate.legacy = u4Rate / 1000; /* convert from 100bps to 100kbps */ + prGlueInfo->u4LinkSpeedCache = u4Rate / 1000; + } + + /* 3. fill RSSI */ + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryRssi, &i4Rssi, sizeof(i4Rssi), TRUE, FALSE, FALSE, &u4BufLen); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); +#else + sinfo->filled |= STATION_INFO_SIGNAL; +#endif + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "Query RSSI failed, use last RSSI %d\n", prGlueInfo->i4RssiCache); + sinfo->signal = prGlueInfo->i4RssiCache ? prGlueInfo->i4RssiCache : PARAM_WHQL_RSSI_INITIAL_DBM; + } else if (i4Rssi == PARAM_WHQL_RSSI_MIN_DBM || i4Rssi == PARAM_WHQL_RSSI_MAX_DBM) { + DBGLOG(REQ, WARN, "RSSI abnormal, use last RSSI %d\n", prGlueInfo->i4RssiCache); + sinfo->signal = prGlueInfo->i4RssiCache ? prGlueInfo->i4RssiCache : i4Rssi; + } else { + sinfo->signal = i4Rssi; /* dBm */ + prGlueInfo->i4RssiCache = i4Rssi; + } + + /* Get statistics from net_dev */ + prDevStats = (struct net_device_stats *)kalGetStats(ndev); + + if (prDevStats) { + /* 4. fill RX_PACKETS */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS); + sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES64); +#else + sinfo->filled |= STATION_INFO_RX_PACKETS; + sinfo->filled |= STATION_INFO_RX_BYTES64; +#endif + sinfo->rx_packets = prDevStats->rx_packets; + sinfo->rx_bytes = prDevStats->rx_bytes; + + /* 5. fill TX_PACKETS */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS); + sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES64); +#else + sinfo->filled |= STATION_INFO_TX_PACKETS; + sinfo->filled |= STATION_INFO_TX_BYTES64; +#endif + sinfo->tx_packets = prDevStats->tx_packets; + sinfo->tx_bytes = prDevStats->tx_bytes; + + /* 6. fill TX_FAILED */ + kalMemZero(&rQueryStaStatistics, sizeof(rQueryStaStatistics)); + COPY_MAC_ADDR(rQueryStaStatistics.aucMacAddr, arBssid); + rQueryStaStatistics.ucReadClear = TRUE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStaStatistics, + &rQueryStaStatistics, sizeof(rQueryStaStatistics), TRUE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "unable to retrieve link speed,status code = %d\n", rStatus); + } else { + DBGLOG(REQ, INFO, + "BSSID: [" MACSTR "] TxFail:%u TxTimeOut:%u, TxOK:%u RxOK:%u\n", + MAC2STR(arBssid), rQueryStaStatistics.u4TxFailCount, + rQueryStaStatistics.u4TxLifeTimeoutCount, + sinfo->tx_packets, sinfo->rx_packets); + + u4TotalError = rQueryStaStatistics.u4TxFailCount + rQueryStaStatistics.u4TxLifeTimeoutCount; + prDevStats->tx_errors += u4TotalError; + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + sinfo->filled |= BIT(NL80211_STA_INFO_TX_FAILED); +#else + sinfo->filled |= STATION_INFO_TX_FAILED; +#endif + sinfo->tx_failed = prDevStats->tx_errors; + } +#if (CFG_SUPPORT_DEBUG_STATISTICS == 1) + wlanPktStatusDebugDumpInfo(prGlueInfo->prAdapter); +#endif + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for getting statistics for Link layer statistics + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*------------------------------------------------------------------------*/ +int mtk_cfg80211_get_link_statistics(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; + INT_32 i4Rssi; + PARAM_GET_STA_STA_STATISTICS rQueryStaStatistics; + PARAM_GET_BSS_STATISTICS rQueryBssStatistics; + struct net_device_stats *prDevStats; + P_NETDEV_PRIVATE_GLUE_INFO prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) NULL; + UINT_8 ucBssIndex; + + 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 RSSI */ + if (prGlueInfo->eParamMediaStateIndicated != PARAM_MEDIA_STATE_CONNECTED) { + /* not connected */ + DBGLOG(REQ, WARN, "not yet connected\n"); + } else { + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryRssi, &i4Rssi, sizeof(i4Rssi), TRUE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "unable to retrieve rssi\n"); + } + + /* Get statistics from net_dev */ + prDevStats = (struct net_device_stats *)kalGetStats(ndev); + + /*3. get link layer statistics from Driver and FW */ + if (prDevStats) { + /* 3.1 get per-STA link statistics */ + kalMemZero(&rQueryStaStatistics, sizeof(rQueryStaStatistics)); + COPY_MAC_ADDR(rQueryStaStatistics.aucMacAddr, arBssid); + rQueryStaStatistics.ucLlsReadClear = FALSE; /* dont clear for get BSS statistic */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStaStatistics, + &rQueryStaStatistics, sizeof(rQueryStaStatistics), TRUE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "unable to retrieve per-STA link statistics\n"); + + /*3.2 get per-BSS link statistics */ + if (rStatus == WLAN_STATUS_SUCCESS) { + /* get Bss Index from ndev */ + prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(ndev); + ASSERT(prNetDevPrivate->prGlueInfo == prGlueInfo); + ucBssIndex = prNetDevPrivate->ucBssIdx; + + kalMemZero(&rQueryBssStatistics, sizeof(rQueryBssStatistics)); + rQueryBssStatistics.ucBssIndex = ucBssIndex; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryBssStatistics, + &rQueryBssStatistics, + sizeof(rQueryBssStatistics), TRUE, FALSE, TRUE, &u4BufLen); + } else { + DBGLOG(REQ, WARN, "unable to retrieve per-BSS link statistics\n"); + } + + } + + return 0; +} +/*----------------------------------------------------------------------------*/ /*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_get_channel_info(P_GLUE_INFO_T prGlueInfo, struct cfg80211_scan_request *request) +{ + struct ieee80211_channel *prchannelinfo; + P_PARTIAL_SCAN_INFO prPartialScanChannel = NULL; + ENUM_BAND_T eBand; + UINT_8 ucChannel; + P_ADAPTER_T prAdapter; + UINT_8 i = 0; + UINT_8 j = 0; + UINT_8 channel_num = 0; + UINT_8 channel_counts = 0; + + if (prGlueInfo == NULL) + return 0; + prAdapter = prGlueInfo->prAdapter; + if (prAdapter == NULL) + return 0; + + prPartialScanChannel = (P_PARTIAL_SCAN_INFO)&prGlueInfo->rScanChannelInfo; + + + if (cnmAisInfraChannelFixed(prAdapter, &eBand, &ucChannel) == TRUE) { + DBGLOG(REQ, TRACE, "partial scan not normal scan\n"); + return 0; + } + + channel_counts = request->n_channels; + DBGLOG(REQ, TRACE, "partial scan channel_counts=%d\n", channel_counts); + /* 1. partial scan, max channels is 6 + * 2. some scan case, it will set band info to driver and not set channel info + * so, supplicant will set all channel with this scan + * for this case, partial scan must to check to avoid this scan + * channel num is MAXIMUM_OPERATION_CHANNEL_LIST + * 3. some scan case, it will set band info to supplicant, not to driver, + * partial scan should handle this case. + * for this cse, band info include 2.4G and 5G band. + * channel num is channel num(2.4G or 5G band) + * + * so, for partial scan limit channel num less MAXIMUM_OPERATION_CHANNEL_LIST + */ + if (channel_counts > 25) + return 0; + + while (j < channel_counts) { + + prchannelinfo = request->channels[j]; + DBGLOG(REQ, TRACE, "partial scan set channel band=%d\n", prchannelinfo->band); + + switch (prchannelinfo->band) { + case KAL_BAND_2GHZ: + prPartialScanChannel->arChnlInfoList[i].eBand = BAND_2G4; + break; + + case KAL_BAND_5GHZ: + prPartialScanChannel->arChnlInfoList[i].eBand = BAND_5G; + break; + + default: + j++; + continue; + } + + DBGLOG(REQ, TRACE, "set channel channel_center_freq =%d\n", + prchannelinfo->center_freq); + + channel_num = (UINT_8)nicFreq2ChannelNum( + prchannelinfo->center_freq * 1000); + + DBGLOG(REQ, TRACE, "partial scan set channel channel_num=%d\n", + channel_num); + prPartialScanChannel->arChnlInfoList[i].ucChannelNum = channel_num; + + j++; + i++; + } + DBGLOG(REQ, INFO, "partial scan set channel i=%d\n", i); + if (i > 0) { + prPartialScanChannel->ucChannelListNum = i; + /*prGlueInfo->pucScanChannel = (PUINT_8)prPartialScanChannel;*/ + DBGLOG(REQ, TRACE, "partial scan set pucScanChannel\n"); + return 1; + } + + kalMemSet(prPartialScanChannel, 0, sizeof(PARTIAL_SCAN_INFO)); + prGlueInfo->pucScanChannel = NULL; + 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 cfg80211_scan_request *request) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 i, u4BufLen; + UINT_8 ucSetChannelFlag = 0; + P_ADAPTER_T prAdapter = NULL; + + PARAM_SCAN_REQUEST_ADV_T rScanRequest; + struct _PARAM_SCAN_RANDOM_MAC_ADDR_T *prScanRandMacAddr = NULL; + UINT_32 num_ssid = 0, u4ValidIdx; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + /* check if there is any pending scan/sched_scan not yet finished */ + if (prGlueInfo->prScanRequest != NULL) + return -EBUSY; + + prAdapter = prGlueInfo->prAdapter; + if (prAdapter == NULL) + return -EINVAL; + + if ((!prAdapter->fgEnCfg80211Scan) && + (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED)) { + DBGLOG(REQ, INFO, "mtk_cfg80211_scan LowLatency mode reject scan\n"); + return -EBUSY; + } + + kalMemZero(&rScanRequest, sizeof(PARAM_SCAN_REQUEST_ADV_T)); + prScanRandMacAddr = &(rScanRequest.rScanRandomMacAddr); + + num_ssid = (UINT_32)request->n_ssids; + DBGLOG(REQ, INFO, "request->n_ssids=%d", request->n_ssids); + + if (request->n_ssids == 0) { + rScanRequest.u4SsidNum = 0; + } else if (request->n_ssids <= (SCN_SSID_MAX_NUM + 1)) { + u4ValidIdx = 0; + for (i = 0; i < request->n_ssids; i++) { + if ((request->ssids[i].ssid[0] == 0) + || (request->ssids[i].ssid_len == 0)) { + num_ssid--; /* remove if this is a wildcard scan*/ + DBGLOG(REQ, INFO, "i=%d, num_ssid-- for wildcard scan\n", i); + continue; + } + COPY_SSID(rScanRequest.rSsid[u4ValidIdx].aucSsid, + rScanRequest.rSsid[u4ValidIdx].u4SsidLen, + request->ssids[i].ssid, request->ssids[i].ssid_len); + DBGLOG(REQ, INFO, "i=%d, u4ValidIdx=%d, aucSsid=%s, u4SsidLen=%d\n", + i, u4ValidIdx, + rScanRequest.rSsid[u4ValidIdx].aucSsid, rScanRequest.rSsid[u4ValidIdx].u4SsidLen); + + u4ValidIdx++; + if (u4ValidIdx == SCN_SSID_MAX_NUM) { + DBGLOG(REQ, INFO, "i=%d, u4ValidIdx is SCN_SSID_MAX_NUM\n", i); + break; + } + } + rScanRequest.u4SsidNum = u4ValidIdx; /* real SSID number to firmware */ + } else { + DBGLOG(REQ, ERROR, "request->n_ssids:%d\n", request->n_ssids); + return -EINVAL; + } + DBGLOG(REQ, INFO, "mtk_cfg80211_scan(), n_ssids=%d, num_ssid=%d\n", request->n_ssids, num_ssid); + /* + * Only request MAC address randomization when station is not associated. + * FW SCAN Module will check whether station is not associated. + */ + if (kalScanParseRandomMac(prGlueInfo, request, prScanRandMacAddr->aucRandomMac)) + prScanRandMacAddr->ucScnFuncMask |= ENUM_SCN_RANDOM_MAC_EN; + if (request->ie_len > 0) { + rScanRequest.u4IELength = request->ie_len; + rScanRequest.pucIE = (PUINT_8) (request->ie); + } + + /* temp get request ieee80211_channel info */ + if ((prGlueInfo->pucScanChannel == NULL) && + (prGlueInfo->rScanChannelInfo.ucChannelListNum == 0)) { + DBGLOG(REQ, TRACE, "there is not any partial scan\n"); + if ((request->n_channels > 0) && (request->n_channels < MAXIMUM_OPERATION_CHANNEL_LIST)) { + ucSetChannelFlag = mtk_cfg80211_get_channel_info(prGlueInfo, request); + rScanRequest.ucSetChannel = ucSetChannelFlag; + DBGLOG(REQ, TRACE, "partial scan get channel return %d\n", ucSetChannelFlag); + } + + } + + prGlueInfo->prScanRequest = request; + rStatus = kalIoctl(prGlueInfo, + wlanoidSetBssidListScanAdv, + &rScanRequest, sizeof(PARAM_SCAN_REQUEST_ADV_T), FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + prGlueInfo->prScanRequest = NULL; + DBGLOG(REQ, ERROR, "scan error:%x\n", rStatus); + if (ucSetChannelFlag) { + /*need reset pucScanChannel and memset rScanChannelInfo*/ + kalMemSet(&(prGlueInfo->rScanChannelInfo), 0, sizeof(PARTIAL_SCAN_INFO)); + prGlueInfo->pucScanChannel = NULL; + + } + + return -EINVAL; + } + + return 0; +} + +#if CFG_SUPPORT_ABORT_SCAN +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to abort a scan + * + * @param + * struct wiphy *wiphy:wireless hardware description + * struct wireless_dev *wdev:wireless device state + * + * @retval void + */ +/*----------------------------------------------------------------------------*/ +void mtk_cfg80211_abort_scan(struct wiphy *wiphy, + struct wireless_dev *wdev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_32 u4BufLen = 0; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + if (prGlueInfo && + prGlueInfo->ucAbortScanCnt < ABORT_SCAN_COUNT && + prGlueInfo->u4LastNormalScanTime != 0 && + !(CHECK_FOR_TIMEOUT(kalGetTimeTick(), + prGlueInfo->u4LastNormalScanTime, + SEC_TO_SYSTIME(ABORT_SCAN_INTERVAl)))) { + + rStatus = kalIoctl(prGlueInfo, wlanoidSetAbortScan, NULL, 0, + FALSE, FALSE, TRUE, &u4BufLen); + } + + DBGLOG(REQ, INFO, "ABORT SCAN %s!\n", rStatus ? "Failed" : "Successed"); +} +#endif + +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 = AUTH_MODE_NUM; + UINT_32 cipher; + PARAM_CONNECT_T rNewSsid; + ENUM_PARAM_OP_MODE_T eOpMode; + UINT_32 i, u4AkmSuite = 0; + P_DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY prEntry; + P_CONNECTION_SETTINGS_T prConnSettings = NULL; + struct wireless_dev *wdev = NULL; +#if CFG_SUPPORT_REPLAY_DETECTION + struct GL_DETECT_REPLAY_INFO *prDetRplyInfo = NULL; +#endif + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + if (ndev == NULL) { + DBGLOG(REQ, ERROR, "ndev is NULL\n"); + return -EINVAL; + } + wdev = ndev->ieee80211_ptr; + + /* Supplicant requests connecting during driver do disconnecting, + * it will cause to install key fail, error is -67(link has been + * servered). + * Beacaus driver disconnected is done, but cfg80211 is disconnecting. + * Reject this request.Supplicant will issue the connecting request again. + */ + if (wdev->current_bss && + kalGetMediaStateIndicated(prGlueInfo) == PARAM_MEDIA_STATE_DISCONNECTED) { + DBGLOG(REQ, WARN, "Reject this connecting request\n"); + return -EALREADY; + } + + prConnSettings = &prGlueInfo->prAdapter->rWifiVar.rConnSettings; + + if (prConnSettings->eOPMode > NET_TYPE_AUTO_SWITCH) + eOpMode = NET_TYPE_AUTO_SWITCH; + else + eOpMode = prConnSettings->eOPMode; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetInfrastructureMode, &eOpMode, sizeof(eOpMode), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "wlanoidSetInfrastructureMode fail 0x%x\n", rStatus); + return -EFAULT; + } + + /* after set operation mode, key table are cleared */ + + /* reset wpa info */ + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + prGlueInfo->rWpaInfo.u4KeyMgmt = 0; + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; +#if CFG_SUPPORT_REPLAY_DETECTION + /* reset Detect replay information */ + prDetRplyInfo = &prGlueInfo->prDetRplyInfo; + kalMemZero(prDetRplyInfo, sizeof(struct GL_DETECT_REPLAY_INFO)); +#endif + +#if CFG_SUPPORT_802_11W + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; + prGlueInfo->rWpaInfo.ucRSNMfpCap = RSN_AUTH_MFP_DISABLED; +#endif + + DBGLOG(REQ, INFO, + "sme:Flag=%08x Type=%x Ver=%x Na=%d Nc=%d Pri=%d Len=%d\n", + sme->flags, sme->auth_type, + sme->crypto.wpa_versions, + sme->crypto.n_akm_suites, + sme->crypto.n_ciphers_pairwise, + sme->privacy, sme->ie_len); + + 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; + case NL80211_AUTHTYPE_FT: + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_FT; + break; + case NL80211_AUTHTYPE_SAE: + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_SAE; + break; + default: + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM | IW_AUTH_ALG_SHARED_KEY; + break; + } + + if (sme->crypto.n_ciphers_pairwise) { + DBGLOG(SCN, INFO, "[wlan] cipher pairwise (%x)\n", sme->crypto.ciphers_pairwise[0]); + + prConnSettings->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) { + prConnSettings->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; + } + } + /* DBGLOG(SCN, INFO, ("akm_suites=%x\n", sme->crypto.akm_suites[0])); */ + if (sme->crypto.n_akm_suites) { + prConnSettings->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; + u4AkmSuite = WPA_AKM_SUITE_802_1X; + break; + case WLAN_AKM_SUITE_PSK: + eAuthMode = AUTH_MODE_WPA_PSK; + u4AkmSuite = WPA_AKM_SUITE_PSK; + break; + default: + DBGLOG(REQ, WARN, "invalid akm (%u)\n", sme->crypto.akm_suites[0]); + 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; + u4AkmSuite = RSN_AKM_SUITE_802_1X; + break; + case WLAN_AKM_SUITE_PSK: + eAuthMode = AUTH_MODE_WPA2_PSK; + u4AkmSuite = RSN_AKM_SUITE_PSK; + break; +#if CFG_SUPPORT_802_11R + case WLAN_AKM_SUITE_FT_8021X: + eAuthMode = AUTH_MODE_WPA2_FT; + u4AkmSuite = RSN_AKM_SUITE_FT_802_1X; + break; + case WLAN_AKM_SUITE_FT_PSK: + eAuthMode = AUTH_MODE_WPA2_FT_PSK; + u4AkmSuite = RSN_AKM_SUITE_FT_PSK; + break; +#endif +#if CFG_SUPPORT_802_11W + /* Notice:: Need kernel patch!! */ + case WLAN_AKM_SUITE_8021X_SHA256: + eAuthMode = AUTH_MODE_WPA2; + u4AkmSuite = RSN_AKM_SUITE_802_1X_SHA256; + break; + case WLAN_AKM_SUITE_PSK_SHA256: + eAuthMode = AUTH_MODE_WPA2_PSK; + u4AkmSuite = RSN_AKM_SUITE_PSK_SHA256; + break; +#endif + case WLAN_AKM_SUITE_SAE: + eAuthMode = AUTH_MODE_WPA3_SAE; + u4AkmSuite = RSN_CIPHER_SUITE_SAE; + break; + case WLAN_AKM_SUITE_OWE: + DBGLOG(REQ, WARN, "Akm Suite = OWE 0x000FAC12\n"); + eAuthMode = AUTH_MODE_WPA3_OWE; + u4AkmSuite = RSN_CIPHER_SUITE_OWE; + break; + default: + DBGLOG(REQ, WARN, "invalid wpa2 akm (%u)\n", sme->crypto.akm_suites[0]); + return -EINVAL; + } + } + } + + if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_DISABLED) { + switch (prGlueInfo->rWpaInfo.u4AuthAlg) { + case IW_AUTH_ALG_OPEN_SYSTEM: + eAuthMode = AUTH_MODE_OPEN; + break; + case IW_AUTH_ALG_FT: + eAuthMode = AUTH_MODE_NON_RSN_FT; + break; + default: + eAuthMode = AUTH_MODE_AUTO_SWITCH; + break; + } + } + + prGlueInfo->rWpaInfo.fgPrivacyInvoke = sme->privacy; + prGlueInfo->fgWpsActive = FALSE; + +#if CFG_SUPPORT_PASSPOINT + prGlueInfo->fgConnectHS20AP = FALSE; +#endif /* CFG_SUPPORT_PASSPOINT */ + prConnSettings->fgOkcEnabled = FALSE; + prConnSettings->fgOkcPmksaReady = FALSE; + if (sme->ie && sme->ie_len > 0) { + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + PUINT_8 prDesiredIE = NULL; + PUINT_8 pucIEStart = (PUINT_8)sme->ie; + + /*We need to check the length of IEs*/ + if (sme->ie_len > MSDU_MAX_LENGTH) { + DBGLOG(REQ, ERROR, "IE len exceeds limit %d\n", sme->ie_len); + return -EINVAL; + } +#if CFG_SUPPORT_WAPI + rStatus = kalIoctl(prGlueInfo, + wlanoidSetWapiAssocInfo, pucIEStart, sme->ie_len, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, TRACE, "[wapi] set wapi assoc info error:%x\n", rStatus); +#endif +#if CFG_SUPPORT_WPS2 + if (wextSrchDesiredWPSIE(pucIEStart, sme->ie_len, 0xDD, (PUINT_8 *) &prDesiredIE)) { + prGlueInfo->fgWpsActive = TRUE; + } +#endif +#if CFG_SUPPORT_PASSPOINT + if (wextSrchDesiredHS20IE(pucIEStart, sme->ie_len, (PUINT_8 *) &prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetHS20Info, + prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, TRUE, &u4BufLen); +#if 0 + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "[HS20] set HS20 assoc info error:%x\n", rStatus); +#endif + } + if (wextSrchDesiredInterworkingIE(pucIEStart, sme->ie_len, (PUINT_8 *) &prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetInterworkingInfo, + prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, TRUE, &u4BufLen); +#if 0 + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "[HS20] set Interworking assoc info error:%x\n", rStatus); +#endif + } + if (wextSrchDesiredRoamingConsortiumIE(pucIEStart, sme->ie_len, (PUINT_8 *) &prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRoamingConsortiumIEInfo, + prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, TRUE, &u4BufLen); +#if 0 + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "[HS20] set RoamingConsortium assoc info error:%x\n", rStatus); +#endif + } +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_802_11W + if (wextSrchDesiredWPAIE(pucIEStart, sme->ie_len, 0x30, + (PUINT_8 *) &prDesiredIE)) { + RSN_INFO_T rRsnInfo; + + if (rsnParseRsnIE(prGlueInfo->prAdapter, + (P_RSN_INFO_ELEM_T)prDesiredIE, &rRsnInfo)) { + + if (rRsnInfo.u2RsnCap & ELEM_WPA_CAP_MFPC) { + prGlueInfo->rWpaInfo.ucRSNMfpCap = + RSN_AUTH_MFP_OPTIONAL; + if (rRsnInfo.u2RsnCap & + ELEM_WPA_CAP_MFPR) + prGlueInfo->rWpaInfo.ucRSNMfpCap = + RSN_AUTH_MFP_REQUIRED; + } else + prGlueInfo->rWpaInfo.ucRSNMfpCap = + RSN_AUTH_MFP_DISABLED; + } + } +#endif + +#if CFG_SUPPORT_OKC + i = 0; + wextSrchOkcAndPMKID(pucIEStart, sme->ie_len, (PUINT_8 *) &prDesiredIE, (PUINT_8)&i); + prConnSettings->fgOkcEnabled = !!i; + if (prConnSettings->fgOkcEnabled) { + UINT_16 u2PmkIdCnt = 0; + PUINT_8 pucBssid = sme->bssid ? (PUINT_8)sme->bssid : (PUINT_8)sme->bssid_hint; + + if (prDesiredIE) + u2PmkIdCnt = *(PUINT_16)prDesiredIE; + DBGLOG(REQ, TRACE, "u2PmkIdCnt %d, has-bssid %d\n", u2PmkIdCnt, !!pucBssid); + if (u2PmkIdCnt && pucBssid && !EQUAL_MAC_ADDR("\x0\x0\x0\x0\x0\x0", pucBssid) && + IS_UCAST_MAC_ADDR(pucBssid)) { + PARAM_PMKID_T rPmkid; + + rPmkid.u4Length = (UINT_32)(sizeof(rPmkid) | (1 << 31)); + rPmkid.u4BSSIDInfoCount = 1; + kalMemCopy(rPmkid.arBSSIDInfo[0].arBSSID, pucBssid, MAC_ADDR_LEN); + kalMemCopy(rPmkid.arBSSIDInfo[0].arPMKID, prDesiredIE + 2, IW_PMKID_LEN); + rStatus = kalIoctl(prGlueInfo, wlanoidSetPmkid, (PVOID)&rPmkid, + sizeof(rPmkid), FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "failed to add OKC PMKID\n"); + } + } +#endif + /*We need to free buffer first*/ + if (prConnSettings->assocIeLen > 0) { + kalMemFree(prConnSettings->pucAssocIEs, VIR_MEM_TYPE, + prConnSettings->assocIeLen); + prConnSettings->assocIeLen = 0; + } + /*Do mem allocate*/ + if (prConnSettings->assocIeLen == 0) { + prConnSettings->pucAssocIEs = + kalMemAlloc(sme->ie_len, VIR_MEM_TYPE); + prConnSettings->assocIeLen = sme->ie_len; + } + if (prConnSettings->pucAssocIEs) + kalMemCopy(prConnSettings->pucAssocIEs, + sme->ie, prConnSettings->assocIeLen); + else { + DBGLOG(INIT, INFO, + "allocate memory for AssocIEs failed!\n"); + prConnSettings->assocIeLen = 0; + return -ENOMEM; + } + } + +#if CFG_SUPPORT_802_11W + switch (sme->mfp) { + case NL80211_MFP_NO: + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; + /* Change Mfp parameter from DISABLED to OPTIONAL + * if upper layer set MFPC = 1 in RSNE + * since upper layer can't bring MFP OPTIONAL information + * to driver by sme->mfp + */ + if (prGlueInfo->rWpaInfo.ucRSNMfpCap == RSN_AUTH_MFP_OPTIONAL) + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_OPTIONAL; + else if (prGlueInfo->rWpaInfo.ucRSNMfpCap == + RSN_AUTH_MFP_REQUIRED) + DBGLOG(REQ, WARN, + "mfp parameter(DISABLED) conflict with mfp cap(REQUIRED)\n"); + break; + /* There's no OPTIONAL defination in both kernel and wpa_supplicant cfg80211 driver */ + case NL80211_MFP_REQUIRED: + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_REQUIRED; + break; + default: + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; + break; + } + /* DBGLOG(SCN, INFO, ("MFP=%d\n", prGlueInfo->rWpaInfo.u4Mfp)); */ +#endif + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAuthMode, &eAuthMode, sizeof(eAuthMode), FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "set auth mode error:%x\n", rStatus); + + /* Enable the specific AKM suite only. */ + for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) { + prEntry = &prGlueInfo->prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[i]; + + if (prEntry->dot11RSNAConfigAuthenticationSuite == u4AkmSuite) + prEntry->dot11RSNAConfigAuthenticationSuiteEnabled = TRUE; + else + prEntry->dot11RSNAConfigAuthenticationSuiteEnabled = FALSE; + } + + 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, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "set encryption mode error:%x\n", rStatus); + + if (sme->key_len != 0 && prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_DISABLED) { + P_PARAM_WEP_T prWepKey = (P_PARAM_WEP_T) wepBuf; + + kalMemSet(prWepKey, 0, sizeof(PARAM_WEP_T)); + 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, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "wlanoidSetAddWep fail 0x%x\n", rStatus); + return -EFAULT; + } + } + + rNewSsid.u4CenterFreq = sme->channel ? sme->channel->center_freq : 0; + rNewSsid.pucBssid = (UINT_8 *)sme->bssid; + rNewSsid.pucSsid = (UINT_8 *)sme->ssid; + rNewSsid.u4SsidLen = sme->ssid_len; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetConnect, (PVOID)&rNewSsid, sizeof(PARAM_CONNECT_T), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set SSID:%x\n", rStatus); + return -EINVAL; + } + return 0; +} + +#if (defined(NL80211_ATTR_EXTERNAL_AUTH_SUPPORT) \ + || LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for receiveing external auth result + * + * @param + * + * @retval always successful + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_external_auth(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_external_auth_params *params) +{ + struct _GLUE_INFO_T *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_FAILURE; + uint32_t u4BufLen; + struct PARAM_EXTERNAL_AUTH auth; + + prGlueInfo = (struct _GLUE_INFO_T *) wiphy_priv(wiphy); + if (!prGlueInfo) + DBGLOG(REQ, WARN, + "SAE-confirm failed with invalid prGlueInfo\n"); + + COPY_MAC_ADDR(auth.bssid, params->bssid); + auth.status = params->status; + auth.ucBssIdx = wlanGetBssIdx(ndev); + rStatus = kalIoctl(prGlueInfo, wlanoidExternalAuthDone, (void *)&auth, + sizeof(auth), FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(OID, INFO, "SAE-confirm failed with: 0x%x\n", rStatus); + return 0; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * @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; + struct wireless_dev *wdev = NULL; + P_BSS_INFO_T prAisBssInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + + if (ndev == NULL) { + DBGLOG(REQ, ERROR, "ndev is NULL\n"); + return -EINVAL; + } + wdev = ndev->ieee80211_ptr; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + if ((prGlueInfo == NULL) || (prGlueInfo->prAdapter == NULL)) { + DBGLOG(REQ, ERROR, + "mtk_cfg80211_disconnect, prGlueInfo ==NULL!!\n"); + return -EFAULT; + } + + prAisBssInfo = (prGlueInfo->prAdapter)->prAisBssInfo; + if (prAisBssInfo == NULL) { + DBGLOG(REQ, ERROR, + "mtk_cfg80211_disconnect, prAisBssInfo ==NULL!!\n"); + return -EFAULT; + } + + DBGLOG(REQ, INFO, "Current_bss %d ssid_len %d StateIndicated %d %d\n", + (wdev->current_bss == NULL) ? 0 : 1, wdev->ssid_len, + prAisBssInfo->eConnectionStateIndicated, + prGlueInfo->eParamMediaStateIndicated); + + /* Check if kernel state = connected but driver state = disconnected. + * If yes, report disconnected to kernel directly since driver has + * already stayed in disconnected state. + */ + if ((wdev->current_bss && wdev->ssid_len > 0) && + prAisBssInfo->eConnectionStateIndicated + == PARAM_MEDIA_STATE_DISCONNECTED) { + DBGLOG(REQ, ERROR, + "Kernel & driver have differnet conn state!!\n"); + cfg80211_disconnected(prGlueInfo->prDevHandler, reason_code, + NULL, 0, + WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY, + GFP_KERNEL); + return 0; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, NULL, 0, FALSE, FALSE, TRUE, &u4BufLen); + +#if CFG_SUPPORT_REPORT_MISC + set_bit(EXT_SRC_DISCONNCT_BIT, + &(prGlueInfo->prAdapter->rReportMiscSet.ulExtSrcFlag)); + + kalSetReportMiscEvent(prGlueInfo); +#endif + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "disassociate error:%x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to join an IBSS group + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_ibss_params *params) +{ + PARAM_SSID_T rNewSsid; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4ChnlFreq; /* Store channel or frequency information */ + UINT_32 u4BufLen = 0; + WLAN_STATUS rStatus; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + /* set channel */ + if (params->channel_fixed) { + u4ChnlFreq = params->chandef.center_freq1; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetFrequency, + &u4ChnlFreq, sizeof(u4ChnlFreq), 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, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set SSID:%x\n", rStatus); + return -EFAULT; + } + + return 0; + + return -EINVAL; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to leave from IBSS group + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, NULL, 0, FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "disassociate error:%x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to configure + * WLAN power managemenet + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, bool enabled, int timeout) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + PARAM_POWER_MODE_T rPowerMode; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + if (!prGlueInfo) + return -EFAULT; + + if (!prGlueInfo->prAdapter->prAisBssInfo) + return -EFAULT; + + if (enabled) { + if (timeout == -1) + rPowerMode.ePowerMode = Param_PowerModeFast_PSP; + else + rPowerMode.ePowerMode = Param_PowerModeMAX_PSP; + } else { + rPowerMode.ePowerMode = Param_PowerModeCAM; + } + + rPowerMode.ucBssIdx = prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, sizeof(PARAM_POWER_MODE_T), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set_power_mgmt error:%x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to cache + * a PMKID for a BSSID + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_pmksa *pmksa) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + P_PARAM_PMKID_T prPmkid; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + prPmkid = (P_PARAM_PMKID_T) kalMemAlloc(8 + sizeof(PARAM_BSSID_INFO_T), VIR_MEM_TYPE); + if (!prPmkid) { + DBGLOG(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, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "add pmkid error:%x\n", rStatus); + kalMemFree(prPmkid, VIR_MEM_TYPE, 8 + sizeof(PARAM_BSSID_INFO_T)); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to remove + * a cached PMKID for a BSSID + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_pmksa *pmksa) +{ + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to flush + * all cached PMKID + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + P_PARAM_PMKID_T prPmkid; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + prPmkid = (P_PARAM_PMKID_T) kalMemAlloc(8, VIR_MEM_TYPE); + if (!prPmkid) { + DBGLOG(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, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "flush pmkid error:%x\n", rStatus); + kalMemFree(prPmkid, VIR_MEM_TYPE, 8); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for setting the rekey data + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_gtk_rekey_data *data) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + P_PARAM_GTK_REKEY_DATA prGtkData; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + prGtkData = (P_PARAM_GTK_REKEY_DATA) kalMemAlloc(sizeof(PARAM_GTK_REKEY_DATA), VIR_MEM_TYPE); + if (!prGtkData) { + DBGLOG(INIT, INFO, "Can not alloc memory for PARAM_GTK_REKEY_DATA\n"); + return -ENOMEM; + } + + DBGLOG(RSN, TRACE, "cfg80211_set_rekey_data!\n"); + + kalMemCopy(prGtkData, data, sizeof(PARAM_GTK_REKEY_DATA)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetGtkRekeyData, + prGtkData, sizeof(PARAM_GTK_REKEY_DATA), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "set GTK rekey data error:%x\n", rStatus); + kalMemFree(prGtkData, VIR_MEM_TYPE, sizeof(PARAM_GTK_REKEY_DATA)); + + return 0; +} + +void mtk_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, + IN struct wireless_dev *wdev, + IN u16 frame_type, IN bool reg) +{ +#if 0 + P_MSG_P2P_MGMT_FRAME_REGISTER_T prMgmtFrameRegister = (P_MSG_P2P_MGMT_FRAME_REGISTER_T) NULL; +#endif + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + + do { + + DBGLOG(INIT, TRACE, "mtk_cfg80211_mgmt_frame_register\n"); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + switch (frame_type) { + case MAC_FRAME_PROBE_REQ: + if (reg) { + prGlueInfo->u4OsMgmtFrameFilter |= PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(INIT, TRACE, "Open packet filer probe request\n"); + } else { + prGlueInfo->u4OsMgmtFrameFilter &= ~PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(INIT, TRACE, "Close packet filer probe request\n"); + } + break; + case MAC_FRAME_ACTION: + if (reg) { + prGlueInfo->u4OsMgmtFrameFilter |= PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(INIT, TRACE, "Open packet filer action frame.\n"); + } else { + prGlueInfo->u4OsMgmtFrameFilter &= ~PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(INIT, TRACE, "Close packet filer action frame.\n"); + } + break; + default: + DBGLOG(INIT, TRACE, "Ask frog to add code for mgmt:%x\n", frame_type); + break; + } + + if (prGlueInfo->prAdapter != NULL) { + + set_bit(GLUE_FLAG_FRAME_FILTER_AIS_BIT, &prGlueInfo->ulFlag); + + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + + if (in_interrupt()) + DBGLOG(INIT, TRACE, "It is in interrupt level\n"); + } +#if 0 + + prMgmtFrameRegister = + (P_MSG_P2P_MGMT_FRAME_REGISTER_T) cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, sizeof(MSG_P2P_MGMT_FRAME_REGISTER_T)); + + if (prMgmtFrameRegister == NULL) { + ASSERT(FALSE); + break; + } + + prMgmtFrameRegister->rMsgHdr.eMsgId = MID_MNY_P2P_MGMT_FRAME_REGISTER; + + prMgmtFrameRegister->u2FrameType = frame_type; + prMgmtFrameRegister->fgIsRegister = reg; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMgmtFrameRegister, MSG_SEND_METHOD_BUF); + +#endif + + } while (FALSE); + +} /* mtk_cfg80211_mgmt_frame_register */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to stay on a + * specified channel + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, + unsigned int duration, u64 *cookie) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_REMAIN_ON_CHANNEL_T prMsgChnlReq = (P_MSG_REMAIN_ON_CHANNEL_T) NULL; + + do { + if ((wiphy == NULL) + || (wdev == NULL) + || (chan == NULL) + || (cookie == NULL)) { + break; + } + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if 1 + DBGLOG(INIT, INFO, "--> %s()\n", __func__); +#endif + + *cookie = prGlueInfo->u8Cookie++; + + prMsgChnlReq = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_REMAIN_ON_CHANNEL_T)); + + if (prMsgChnlReq == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgChnlReq->rMsgHdr.eMsgId = MID_MNY_AIS_REMAIN_ON_CHANNEL; + prMsgChnlReq->u8Cookie = *cookie; + prMsgChnlReq->u4DurationMs = duration; + + prMsgChnlReq->ucChannelNum = nicFreq2ChannelNum(chan->center_freq * 1000); + + switch (chan->band) { + case KAL_BAND_2GHZ: + prMsgChnlReq->eBand = BAND_2G4; + break; + case KAL_BAND_5GHZ: + prMsgChnlReq->eBand = BAND_5G; + break; + default: + prMsgChnlReq->eBand = BAND_2G4; + break; + } + + prMsgChnlReq->eSco = CHNL_EXT_SCN; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChnlReq, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to cancel staying + * on a specified channel + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_CANCEL_REMAIN_ON_CHANNEL_T prMsgChnlAbort = (P_MSG_CANCEL_REMAIN_ON_CHANNEL_T) NULL; + + do { + if ((wiphy == NULL) + || (wdev == NULL) + ) { + break; + } + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + prMsgChnlAbort = + cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_CANCEL_REMAIN_ON_CHANNEL_T)); + + if (prMsgChnlAbort == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgChnlAbort->rMsgHdr.eMsgId = MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL; + prMsgChnlAbort->u8Cookie = cookie; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChnlAbort, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to send a management frame + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_MGMT_TX_REQUEST_T prMsgTxReq = (P_MSG_MGMT_TX_REQUEST_T) NULL; + P_MSDU_INFO_T prMgmtFrame = (P_MSDU_INFO_T) NULL; + PUINT_8 pucFrameBuf = (PUINT_8) NULL; + + do { + if ((wiphy == NULL) || (wdev == NULL) || (params == 0) || (cookie == NULL)) + break; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + *cookie = prGlueInfo->u8Cookie++; + + DBGLOG(REQ, INFO, "%s\n", __func__); + + /* Channel & Channel Type & Wait time are ignored. */ + prMsgTxReq = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_MGMT_TX_REQUEST_T)); + + if (prMsgTxReq == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgTxReq->fgNoneCckRate = FALSE; + prMsgTxReq->fgIsWaitRsp = TRUE; + + prMgmtFrame = cnmMgtPktAlloc(prGlueInfo->prAdapter, (UINT_32) (params->len + MAC_TX_RESERVED_FIELD)); + prMsgTxReq->prMgmtMsduInfo = prMgmtFrame; + if (prMsgTxReq->prMgmtMsduInfo == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgTxReq->u8Cookie = *cookie; + prMsgTxReq->rMsgHdr.eMsgId = MID_MNY_AIS_MGMT_TX; + + pucFrameBuf = (PUINT_8) ((ULONG) prMgmtFrame->prPacket + MAC_TX_RESERVED_FIELD); + + kalMemCopy(pucFrameBuf, params->buf, params->len); + + prMgmtFrame->u2FrameLength = params->len; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgTxReq, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + if ((i4Rslt != 0) && (prMsgTxReq != NULL)) { + if (prMsgTxReq->prMgmtMsduInfo != NULL) + cnmMgtPktFree(prGlueInfo->prAdapter, prMsgTxReq->prMgmtMsduInfo); + + cnmMemFree(prGlueInfo->prAdapter, prMsgTxReq); + } + + return i4Rslt; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to cancel the wait time + * from transmitting a management frame on another channel + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if 1 + DBGLOG(INIT, INFO, "--> %s()\n", __func__); +#endif + + /* not implemented */ + + return -EINVAL; +} + +#if CONFIG_NL80211_TESTMODE + +#if CFG_SUPPORT_PASSPOINT +int mtk_cfg80211_testmode_hs20_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + struct wpa_driver_hs20_data_s *prParams = NULL; + WLAN_STATUS rstatus = WLAN_STATUS_SUCCESS; + int fgIsValid = 0; + UINT_32 u4SetInfoLen = 0; + + ASSERT(wiphy); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + +#if 1 + DBGLOG(INIT, INFO, "--> %s()\n", __func__); +#endif + + if (data && len) + prParams = (struct wpa_driver_hs20_data_s *)data; + + if (prParams) { + int i; + + DBGLOG(INIT, INFO, "[%s] Cmd Type (%d)\n", __func__, prParams->CmdType); + switch (prParams->CmdType) { + case HS20_CMD_ID_SET_BSSID_POOL: + DBGLOG(INIT, INFO, + "[%s] fgBssidPoolIsEnable (%d)\n", __func__, + prParams->hs20_set_bssid_pool.fgBssidPoolIsEnable); + DBGLOG(INIT, INFO, + "[%s] ucNumBssidPool (%d)\n", __func__, + prParams->hs20_set_bssid_pool.ucNumBssidPool); + + for (i = 0; i < prParams->hs20_set_bssid_pool.ucNumBssidPool; i++) { + DBGLOG(INIT, INFO, "[%s][%d][" MACSTR "]\n", __func__, i, + MAC2STR(prParams->hs20_set_bssid_pool.arBssidPool[i])); + } + rstatus = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC) wlanoidSetHS20BssidPool, + &prParams->hs20_set_bssid_pool, + sizeof(struct param_hs20_set_bssid_pool), FALSE, FALSE, TRUE, &u4SetInfoLen); + break; + default: + DBGLOG(INIT, INFO, "[%s] Unknown Cmd Type (%d)\n", __func__, prParams->CmdType); + rstatus = WLAN_STATUS_FAILURE; + + } + + } + + if (rstatus != WLAN_STATUS_SUCCESS) + fgIsValid = -EFAULT; + + return fgIsValid; +} + +#endif /* CFG_SUPPORT_PASSPOINT */ + +#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 + DBGLOG(INIT, INFO, "--> %s()\n", __func__); +#endif + + if (data && len) + prParams = (P_NL80211_DRIVER_SET_KEY_EXTS) data; + + if (prParams) + prIWEncExt = (struct iw_encode_exts *)&prParams->ext; + else + return -EINVAL; + + if ((prIWEncExt != NULL) && (prIWEncExt->alg == IW_ENCODE_ALG_SMS4)) { + /* KeyID */ + prWpiKey->ucKeyID = prParams->key_index; + prWpiKey->ucKeyID--; + if (prWpiKey->ucKeyID > 1) { + /* key id is out of range */ + return -EINVAL; + } + + if (prIWEncExt->key_len != 32) { + /* key length not valid */ + return -EINVAL; + } + + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + prWpiKey->eKeyType = ENUM_WPI_GROUP_KEY; + prWpiKey->eDirection = ENUM_WPI_RX; + } else if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { + prWpiKey->eKeyType = ENUM_WPI_PAIRWISE_KEY; + prWpiKey->eDirection = ENUM_WPI_RX_TX; + } +/* #if CFG_SUPPORT_WAPI */ + /* handle_sec_msg_final(prIWEncExt->key, 32, prIWEncExt->key, NULL); */ +/* #endif */ + /* PN */ + memcpy(prWpiKey->aucPN, prIWEncExt->tx_seq, IW_ENCODE_SEQ_MAX_SIZE); + memcpy(prWpiKey->aucPN + IW_ENCODE_SEQ_MAX_SIZE, prIWEncExt->rx_seq, IW_ENCODE_SEQ_MAX_SIZE); + + /* BSSID */ + memcpy(prWpiKey->aucAddrIndex, prIWEncExt->addr, 6); + + memcpy(prWpiKey->aucWPIEK, prIWEncExt->key, 16); + prWpiKey->u4LenWPIEK = 16; + + memcpy(prWpiKey->aucWPICK, &prIWEncExt->key[16], 16); + prWpiKey->u4LenWPICK = 16; + + rstatus = kalIoctl(prGlueInfo, + wlanoidSetWapiKey, prWpiKey, sizeof(PARAM_WPI_KEY_T), FALSE, FALSE, TRUE, &u4BufLen); + + if (rstatus != WLAN_STATUS_SUCCESS) + fgIsValid = -EFAULT; + + } + return fgIsValid; +} +#endif + +int +mtk_cfg80211_testmode_get_sta_statistics(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + INT_32 i4Status = -EINVAL; + UINT_32 u4BufLen; + UINT_32 u4LinkScore; + UINT_32 u4TotalError; + UINT_32 u4TxExceedThresholdCount; + UINT_32 u4TxTotalCount; + UINT_8 u1buf = 0; + + P_NL80211_DRIVER_GET_STA_STATISTICS_PARAMS prParams = NULL; + PARAM_GET_STA_STA_STATISTICS rQueryStaStatistics; + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(prGlueInfo); + + if (data && len) + prParams = (P_NL80211_DRIVER_GET_STA_STATISTICS_PARAMS) data; + + if (!prParams) { + DBGLOG(QM, TRACE, "%s prParams is NULL\n", __func__); + return -EINVAL; + } + + skb = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(PARAM_GET_STA_STA_STATISTICS) + 1); + + if (!skb) { + DBGLOG(QM, TRACE, "%s allocate skb failed:%x\n", __func__, rStatus); + return -ENOMEM; + } + DBGLOG(QM, TRACE, "Get [" MACSTR "] STA statistics\n", + MAC2STR(prParams->aucMacAddr)); + + kalMemZero(&rQueryStaStatistics, sizeof(rQueryStaStatistics)); + COPY_MAC_ADDR(rQueryStaStatistics.aucMacAddr, prParams->aucMacAddr); + rQueryStaStatistics.ucReadClear = TRUE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStaStatistics, + &rQueryStaStatistics, sizeof(rQueryStaStatistics), TRUE, FALSE, TRUE, &u4BufLen); + + /* Calcute Link Score */ + u4TxExceedThresholdCount = rQueryStaStatistics.u4TxExceedThresholdCount; + u4TxTotalCount = rQueryStaStatistics.u4TxTotalCount; + u4TotalError = rQueryStaStatistics.u4TxFailCount + rQueryStaStatistics.u4TxLifeTimeoutCount; + + /* u4LinkScore 10~100 , ExceedThreshold ratio 0~90 only */ + /* u4LinkScore 0~9 , Drop packet ratio 0~9 and all packets exceed threshold */ + if (u4TxTotalCount) { + if (u4TxExceedThresholdCount <= u4TxTotalCount) + u4LinkScore = (90 - ((u4TxExceedThresholdCount * 90) / u4TxTotalCount)); + else + u4LinkScore = 0; + } else { + u4LinkScore = 90; + } + + u4LinkScore += 10; + + if (u4LinkScore == 10) { + + if (u4TotalError <= u4TxTotalCount) + u4LinkScore = (10 - ((u4TotalError * 10) / u4TxTotalCount)); + else + u4LinkScore = 0; + + } + + if (u4LinkScore > 100) + u4LinkScore = 100; + + do { + u1buf = 0; + + if (!NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_INVALID, &u1buf)) + break; + u1buf = NL80211_DRIVER_TESTMODE_VERSION; + if (!NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_VERSION, &u1buf)) + break; + if (!NLA_PUT(skb, NL80211_TESTMODE_STA_STATISTICS_MAC, MAC_ADDR_LEN, prParams->aucMacAddr)) + break; + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE, &u4LinkScore)) + break; + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_FLAG, &rQueryStaStatistics.u4Flag)) + break; + + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_ENQUEUE, &rQueryStaStatistics.u4EnqueueCounter)) + break; + + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_DEQUEUE, &rQueryStaStatistics.u4DequeueCounter)) + break; + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_STA_ENQUEUE, + &rQueryStaStatistics.u4EnqueueStaCounter)) + break; + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_STA_DEQUEUE, + &rQueryStaStatistics.u4DequeueStaCounter)) + break; + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_CNT, + &rQueryStaStatistics.IsrCnt)) + break; + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_PASS_CNT, + &rQueryStaStatistics.IsrPassCnt)) + break; + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_TASK_CNT, + &rQueryStaStatistics.TaskIsrCnt)) + break; + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_AB_CNT, + &rQueryStaStatistics.IsrAbnormalCnt)) + break; + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_SW_CNT, + &rQueryStaStatistics.IsrSoftWareCnt)) + break; + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_TX_CNT, + &rQueryStaStatistics.IsrTxCnt)) + break; + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_RX_CNT, + &rQueryStaStatistics.IsrRxCnt)) + break; + /* FW part STA link status */ + if (!NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_PER, &rQueryStaStatistics.ucPer)) + break; + if (!NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_RSSI, &rQueryStaStatistics.ucRcpi)) + break; + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_PHY_MODE, &rQueryStaStatistics.u4PhyMode)) + break; + if (!NLA_PUT_U16(skb, NL80211_TESTMODE_STA_STATISTICS_TX_RATE, &rQueryStaStatistics.u2LinkSpeed)) + break; + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT, &rQueryStaStatistics.u4TxFailCount)) + break; + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT, + &rQueryStaStatistics.u4TxLifeTimeoutCount)) + break; + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME, + &rQueryStaStatistics.u4TxAverageAirTime)) + break; + /* Driver part link status */ + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT, &rQueryStaStatistics.u4TxTotalCount)) + break; + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT, + &rQueryStaStatistics.u4TxExceedThresholdCount)) + break; + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME, + &rQueryStaStatistics.u4TxAverageProcessTime)) + break; + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_MAX_PROCESS_TIME, + &rQueryStaStatistics.u4TxMaxTime)) + break; + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_AVG_HIF_PROCESS_TIME, + &rQueryStaStatistics.u4TxAverageHifTime)) + break; + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_MAX_HIF_PROCESS_TIME, + &rQueryStaStatistics.u4TxMaxHifTime)) + break; + /* Network counter */ + if (!NLA_PUT(skb, + NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY, + sizeof(rQueryStaStatistics.au4TcResourceEmptyCount), + rQueryStaStatistics.au4TcResourceEmptyCount)) + break; + if (!NLA_PUT(skb, + NL80211_TESTMODE_STA_STATISTICS_NO_TC_ARRAY, + sizeof(rQueryStaStatistics.au4DequeueNoTcResource), + rQueryStaStatistics.au4DequeueNoTcResource)) + break; + if (!NLA_PUT(skb, + NL80211_TESTMODE_STA_STATISTICS_RB_ARRAY, + sizeof(rQueryStaStatistics.au4TcResourceBackCount), + rQueryStaStatistics.au4TcResourceBackCount)) + break; + + if (!NLA_PUT(skb, + NL80211_TESTMODE_STA_STATISTICS_USED_TC_PGCT_ARRAY, + sizeof(rQueryStaStatistics.au4TcResourceUsedPageCount), + rQueryStaStatistics.au4TcResourceUsedPageCount)) + break; + if (!NLA_PUT(skb, + NL80211_TESTMODE_STA_STATISTICS_WANTED_TC_PGCT_ARRAY, + sizeof(rQueryStaStatistics.au4TcResourceWantedPageCount), + rQueryStaStatistics.au4TcResourceWantedPageCount)) + break; + + /* Sta queue length */ + if (!NLA_PUT(skb, + NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY, + sizeof(rQueryStaStatistics.au4TcQueLen), rQueryStaStatistics.au4TcQueLen)) + break; + /* Global QM counter */ + if (!NLA_PUT(skb, + NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY, + sizeof(rQueryStaStatistics.au4TcAverageQueLen), rQueryStaStatistics.au4TcAverageQueLen)) + break; + if (!NLA_PUT(skb, + NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY, + sizeof(rQueryStaStatistics.au4TcCurrentQueLen), rQueryStaStatistics.au4TcCurrentQueLen)) + break; + /* Reserved field */ + if (!NLA_PUT(skb, + NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY, + sizeof(rQueryStaStatistics.au4Reserved), rQueryStaStatistics.au4Reserved)) + break; + i4Status = cfg80211_testmode_reply(skb); + } while (0); + + return i4Status; +} + +int +mtk_cfg80211_testmode_get_link_detection(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo) +{ + + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + INT_32 i4Status = -EINVAL; + UINT_32 u4BufLen; + UINT_8 u1buf = 0; + + PARAM_802_11_STATISTICS_STRUCT_T rStatistics; + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(prGlueInfo); + + skb = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(PARAM_GET_STA_STA_STATISTICS) + 1); + + if (!skb) { + DBGLOG(QM, TRACE, "%s allocate skb failed:%x\n", __func__, rStatus); + return -ENOMEM; + } + + kalMemZero(&rStatistics, sizeof(rStatistics)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStatistics, + &rStatistics, sizeof(rStatistics), TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "query statistics error:%x\n", rStatus); + + do { + if (!NLA_PUT_U8(skb, NL80211_TESTMODE_LINK_INVALID, &u1buf)) + break; + if (!NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_TX_FAIL_CNT, &rStatistics.rFailedCount.QuadPart)) + break; + if (!NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_TX_RETRY_CNT, &rStatistics.rRetryCount.QuadPart)) + break; + if (!NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_TX_MULTI_RETRY_CNT, + &rStatistics.rMultipleRetryCount.QuadPart)) + break; + if (!NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_ACK_FAIL_CNT, &rStatistics.rACKFailureCount.QuadPart)) + break; + if (!NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_FCS_ERR_CNT, &rStatistics.rFCSErrorCount.QuadPart)) + break; + if (!NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_TX_CNT, &rStatistics.rTransmittedFragmentCount.QuadPart)) + break; + if (!NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_RX_CNT, &rStatistics.rReceivedFragmentCount.QuadPart)) + break; + + i4Status = cfg80211_testmode_reply(skb); + } while (0); + + return i4Status; +} + +int mtk_cfg80211_testmode_sw_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_SW_CMD_PARAMS prParams = (P_NL80211_DRIVER_SW_CMD_PARAMS) NULL; + WLAN_STATUS rstatus = WLAN_STATUS_SUCCESS; + int fgIsValid = 0; + UINT_32 u4SetInfoLen = 0; + + ASSERT(wiphy); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + 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, &u4SetInfoLen); + } + } + DBGLOG(REQ, TRACE, "prParams=%p, status=%u\n", prParams, rstatus); + + if (rstatus != WLAN_STATUS_SUCCESS) + fgIsValid = -EFAULT; + + return fgIsValid; +} + +int mtk_cfg80211_testmode_cmd(IN struct wiphy *wiphy, IN struct wireless_dev *wdev, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_TEST_MODE_PARAMS prParams = NULL; + INT_32 i4Status = -EINVAL; + + ASSERT(wiphy); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + if (data && len) + prParams = (P_NL80211_DRIVER_TEST_MODE_PARAMS) data; + else { + DBGLOG(REQ, ERROR, "data is NULL\n"); + return i4Status; + } + + /* Clear the version byte */ + prParams->index = prParams->index & ~BITS(24, 31); + + switch (prParams->index) { + case TESTMODE_CMD_ID_SW_CMD: /* SW cmd */ + i4Status = mtk_cfg80211_testmode_sw_cmd(wiphy, data, len); + break; +#if CFG_SUPPORT_WAPI + case TESTMODE_CMD_ID_WAPI: /* WAPI */ + i4Status = mtk_cfg80211_testmode_set_key_ext(wiphy, data, len); + break; +#endif + case 0x10: + i4Status = mtk_cfg80211_testmode_get_sta_statistics(wiphy, data, len, prGlueInfo); + break; + case 0x20: + i4Status = mtk_cfg80211_testmode_get_link_detection(wiphy, data, len, prGlueInfo); + break; +#if CFG_SUPPORT_PASSPOINT + case TESTMODE_CMD_ID_HS20: + i4Status = mtk_cfg80211_testmode_hs20_cmd(wiphy, data, len); + break; +#endif + case TESTMODE_CMD_ID_STR_CMD: + i4Status = mtk_cfg80211_process_str_cmd(prGlueInfo, + (PUINT_8)(prParams+1), len - sizeof(*prParams)); + break; + default: + i4Status = -EINVAL; + break; + } + if (i4Status != 0) + DBGLOG(REQ, TRACE, "prParams->index=%d, status=%d\n", prParams->index, i4Status); + + return i4Status; +} +#endif + +int +mtk_cfg80211_sched_scan_start(IN struct wiphy *wiphy, + IN struct net_device *ndev, IN struct cfg80211_sched_scan_request *request) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 i, u4BufLen; + P_PARAM_SCHED_SCAN_REQUEST prSchedScanRequest; + P_SCAN_INFO_T prScanInfo; +#if CFG_SUPPORT_SCHED_SCN_SSID_SETS + UINT_32 num = 0; +#endif + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + /* check if there is any pending scan/sched_scan not yet finished */ + if (prGlueInfo->prSchedScanRequest != NULL) { + DBGLOG(SCN, ERROR, "prGlueInfo->prSchedScanRequest != NULL\n"); + return -EBUSY; + } else if (request == NULL || request->n_match_sets > CFG_SCAN_SSID_MATCH_MAX_NUM) { + DBGLOG(SCN, ERROR, "(request == NULL || request->n_match_sets > CFG_SCAN_SSID_MATCH_MAX_NUM)\n"); + /* invalid scheduled scan request */ + return -EINVAL; + } else if (!request->n_match_sets) { + /* invalid scheduled scan request */ + DBGLOG(SCN, ERROR, "n_match_sets is 0\n"); + return -EINVAL; + } +#if CFG_SUPPORT_SCHED_SCN_SSID_SETS + else if (!request->n_ssids || request->n_ssids > CFG_SCAN_HIDDEN_SSID_MAX_NUM) { + /* invalid scheduled scan request */ + DBGLOG(SCN, ERROR, "invalid n_ssids=%d\n", request->n_ssids); + return -EINVAL; + } +#endif + DBGLOG(REQ, INFO, "--> %s() n_ssid:%d , match_set:%d\n", __func__, request->n_ssids, request->n_match_sets); + + prSchedScanRequest = (P_PARAM_SCHED_SCAN_REQUEST) kalMemAlloc(sizeof(PARAM_SCHED_SCAN_REQUEST), VIR_MEM_TYPE); + if (prSchedScanRequest == NULL) { + DBGLOG(SCN, ERROR, "(prSchedScanRequest == NULL) kalMemAlloc fail\n"); + return -ENOMEM; + } + kalMemZero(prSchedScanRequest, sizeof(PARAM_SCHED_SCAN_REQUEST)); + +#if CFG_SUPPORT_SCHED_SCN_SSID_SETS + /* passed in the probe_reqs in active scans */ + if (request->ssids) { + for (i = 0; i < request->n_ssids; i++) { + DBGLOG(SCN, TRACE, "ssids : (%d)[%s]\n", i, request->ssids[i].ssid); + /* driver ignored the null ssid */ + if (request->ssids[i].ssid_len == 0 || request->ssids[i].ssid[0] == 0) + DBGLOG(SCN, WARN, "ignore the null ssid, index:%d\n", i); + else { + COPY_SSID(prSchedScanRequest->arSsid[num].aucSsid, + prSchedScanRequest->arSsid[num].u4SsidLen, + request->ssids[i].ssid, request->ssids[i].ssid_len); + num++; + } + } + } + prSchedScanRequest->u4SsidNum = num; + num = 0; + if (request->match_sets) { + for (i = 0; i < request->n_match_sets; i++) { + DBGLOG(SCN, TRACE, "match : (%d)[%s]\n", i, request->match_sets[i].ssid.ssid); + /* driver ignored the null ssid */ + if (request->match_sets[i].ssid.ssid_len == 0 + || request->match_sets[i].ssid.ssid[0] == 0) + DBGLOG(SCN, WARN, "ignore the null ssid, index:%d\n", i); + else { + COPY_SSID(prSchedScanRequest->arMatchSsid[num].aucSsid, + prSchedScanRequest->arMatchSsid[num].u4SsidLen, + request->match_sets[i].ssid.ssid, + request->match_sets[i].ssid.ssid_len); + prSchedScanRequest->acRssiThresold[i] = (INT_8)request->match_sets[i].rssi_thold; + num++; + } + } + } + prSchedScanRequest->u4MatchSsidNum = num; +#else + prSchedScanRequest->u4SsidNum = request->n_match_sets; + for (i = 0; i < request->n_match_sets; i++) { + if (request->match_sets == NULL || &(request->match_sets[i]) == NULL) { + prSchedScanRequest->arSsid[i].u4SsidLen = 0; + } else { + COPY_SSID(prSchedScanRequest->arSsid[i].aucSsid, + prSchedScanRequest->arSsid[i].u4SsidLen, + request->match_sets[i].ssid.ssid, request->match_sets[i].ssid.ssid_len); + prSchedScanRequest->acRssiThresold[i] = 0;/* (INT_8)request->match_sets[i].rssi_thold;*/ + } + } +#endif + + prSchedScanRequest->u4IELength = request->ie_len; + if (request->ie_len > 0) { + prSchedScanRequest->pucIE = kalMemAlloc(request->ie_len, VIR_MEM_TYPE); + if (prSchedScanRequest->pucIE == NULL) { + DBGLOG(SCN, ERROR, "prSchedScanRequest->pucIE kalMemAlloc fail\n"); + } else { + kalMemZero(prSchedScanRequest->pucIE, request->ie_len); + kalMemCopy(prSchedScanRequest->pucIE, (PUINT_8)request->ie, request->ie_len); + } + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + prSchedScanRequest->u2ScanInterval = (UINT_16) (request->scan_plans[0].interval); +#else + prSchedScanRequest->u2ScanInterval = (UINT_16) (request->interval); +#endif + prSchedScanRequest->ucChnlNum = (UINT_8)request->n_channels; + prSchedScanRequest->pucChannels = kalMemAlloc(request->n_channels, VIR_MEM_TYPE); + if (!prSchedScanRequest->pucChannels) { + DBGLOG(SCN, ERROR, "prSchedScanRequest->pucChannels kalMemAlloc fail\n"); + prSchedScanRequest->ucChnlNum = 0; + } else + for (i = 0; i < request->n_channels; i++) + prSchedScanRequest->pucChannels[i] = + nicFreq2ChannelNum(request->channels[i]->center_freq * 1000); + if (kalSchedScanParseRandomMac(ndev, request)) { + prSchedScanRequest->ucScnFuncMask |= ENUM_SCN_RANDOM_MAC_EN; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetStartSchedScan, + prSchedScanRequest, sizeof(PARAM_SCHED_SCAN_REQUEST), FALSE, FALSE, TRUE, &u4BufLen); + + kalMemFree(prSchedScanRequest->pucChannels, VIR_MEM_TYPE, request->n_channels); + kalMemFree(prSchedScanRequest->pucIE, VIR_MEM_TYPE, request->ie_len); + kalMemFree(prSchedScanRequest, VIR_MEM_TYPE, sizeof(PARAM_SCHED_SCAN_REQUEST)); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "scheduled scan error:%x\n", rStatus); + prScanInfo = &(prGlueInfo->prAdapter->rWifiVar.rScanInfo); + prScanInfo->fgNloScanning = FALSE; + return -EINVAL; + } + + prGlueInfo->prSchedScanRequest = request; + + return 0; +} + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) +int mtk_cfg80211_sched_scan_stop(IN struct wiphy *wiphy, IN struct net_device *ndev) +#else +int mtk_cfg80211_sched_scan_stop(IN struct wiphy *wiphy, IN struct net_device *ndev, IN UINT_64 reqid) +#endif +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, INFO, "--> %s()\n", __func__); + + /* check if there is any pending scan/sched_scan not yet finished */ + if (prGlueInfo->prSchedScanRequest == NULL) + return -EBUSY; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetStopSchedScan, NULL, 0, FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_FAILURE) { + DBGLOG(REQ, WARN, "scheduled scan error:%x\n", rStatus); + return -EINVAL; + } + + if (prGlueInfo->prSchedScanRequest != NULL) + prGlueInfo->prSchedScanRequest = NULL; + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for handling association request + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_assoc(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_assoc_request *req) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MAC_ADDRESS arBssid; +#if CFG_SUPPORT_PASSPOINT + PUINT_8 prDesiredIE = NULL; +#endif /* CFG_SUPPORT_PASSPOINT */ + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + kalMemZero(arBssid, MAC_ADDR_LEN); + wlanQueryInformation(prGlueInfo->prAdapter, wlanoidQueryBssid, &arBssid[0], sizeof(arBssid), &u4BufLen); + + /* 1. check BSSID */ + if (UNEQUAL_MAC_ADDR(arBssid, req->bss->bssid)) { + /* wrong MAC address */ + DBGLOG(REQ, WARN, + "incorrect BSSID: [" MACSTR "] currently connected BSSID[" MACSTR "]\n", + MAC2STR(req->bss->bssid), + MAC2STR(arBssid)); + return -ENOENT; + } + + if (req->ie && req->ie_len > 0) { +#if CFG_SUPPORT_PASSPOINT + if (wextSrchDesiredHS20IE((PUINT_8) req->ie, req->ie_len, (PUINT_8 *) &prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetHS20Info, + prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + /* + * DBGLOG(REQ, TRACE, + * ("[HS20] set HS20 assoc info error:%lx\n", rStatus)); + */ + } + } + + if (wextSrchDesiredInterworkingIE((PUINT_8) req->ie, req->ie_len, (PUINT_8 *) &prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetInterworkingInfo, + prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + /* + * DBGLOG(REQ, TRACE, + * ("[HS20] set Interworking assoc info error:%lx\n", rStatus)); + */ + } + } + + if (wextSrchDesiredRoamingConsortiumIE((PUINT_8) req->ie, req->ie_len, (PUINT_8 *) &prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRoamingConsortiumIEInfo, + prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + /* + * DBGLOG(REQ, TRACE, + * ("[HS20] set RoamingConsortium assoc info error:%lx\n", rStatus)); + */ + } + } +#endif /* CFG_SUPPORT_PASSPOINT */ + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetBssid, (PVOID) req->bss->bssid, MAC_ADDR_LEN, FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set BSSID:%x\n", rStatus); + return -EINVAL; + } + + return 0; +} + +#if CFG_SUPPORT_NFC_BEAM_PLUS + +int mtk_cfg80211_testmode_get_scan_done(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo) +{ +#define NL80211_TESTMODE_P2P_SCANDONE_INVALID 0 +#define NL80211_TESTMODE_P2P_SCANDONE_STATUS 1 + + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + INT_32 i4Status = -EINVAL, READY_TO_BEAM = 0; + UINT_8 u1Buf = 0; + + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(prGlueInfo); + + skb = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(UINT_32)); + /* READY_TO_BEAM = */ + /* (UINT_32)(prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsGOInitialDone) */ + /* &(!prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsScanRequest); */ + READY_TO_BEAM = 1; + /* DBGLOG(QM, TRACE, */ + /* ("NFC:GOInitialDone[%d] and P2PScanning[%d]\n", */ + /* prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsGOInitialDone, */ + /* prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsScanRequest)); */ + + if (!skb) { + DBGLOG(QM, TRACE, "%s allocate skb failed:%x\n", __func__, rStatus); + return -ENOMEM; + } + + if (!NLA_PUT_U8(skb, NL80211_TESTMODE_P2P_SCANDONE_INVALID, &u1Buf)) + return i4Status; + + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_P2P_SCANDONE_STATUS, &READY_TO_BEAM)) + return i4Status; + + i4Status = cfg80211_testmode_reply(skb); + return i4Status; +} + +#endif + +#if CFG_SUPPORT_TDLS + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for changing a station information + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_change_station(struct wiphy *wiphy, struct net_device *ndev, const u8 *mac, + struct station_parameters *params) +{ + + /* return 0; */ + + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + P_GLUE_INFO_T prGlueInfo = NULL; + CMD_PEER_UPDATE_T rCmdUpdate; + WLAN_STATUS rStatus; + UINT_32 u4BufLen, u4Temp; + ADAPTER_T *prAdapter; + P_BSS_INFO_T prAisBssInfo; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + /* make up command */ + + prAdapter = prGlueInfo->prAdapter; + prAisBssInfo = prAdapter->prAisBssInfo; + + if (params == NULL) + return 0; + else if (params->supported_rates == NULL) + return 0; + + /* init */ + kalMemZero(&rCmdUpdate, sizeof(rCmdUpdate)); + kalMemCopy(rCmdUpdate.aucPeerMac, mac, 6); + + if (params->supported_rates != NULL) { + + u4Temp = params->supported_rates_len; + if (u4Temp > CMD_PEER_UPDATE_SUP_RATE_MAX) + u4Temp = CMD_PEER_UPDATE_SUP_RATE_MAX; + kalMemCopy(rCmdUpdate.aucSupRate, params->supported_rates, u4Temp); + rCmdUpdate.u2SupRateLen = u4Temp; + } + + /* + * In supplicant, only recognize WLAN_EID_QOS 46, not 0xDD WMM + * So force to support UAPSD here. + */ + rCmdUpdate.UapsdBitmap = 0x0F; /*params->uapsd_queues; */ + rCmdUpdate.UapsdMaxSp = 0; /*params->max_sp; */ + + rCmdUpdate.u2Capability = params->capability; + + if (params->ext_capab != NULL) { + + u4Temp = params->ext_capab_len; + if (u4Temp > CMD_PEER_UPDATE_EXT_CAP_MAXLEN) + u4Temp = CMD_PEER_UPDATE_EXT_CAP_MAXLEN; + kalMemCopy(rCmdUpdate.aucExtCap, params->ext_capab, u4Temp); + rCmdUpdate.u2ExtCapLen = u4Temp; + } + + if (params->ht_capa != NULL) { + + rCmdUpdate.rHtCap.u2CapInfo = params->ht_capa->cap_info; + rCmdUpdate.rHtCap.ucAmpduParamsInfo = params->ht_capa->ampdu_params_info; + rCmdUpdate.rHtCap.u2ExtHtCapInfo = params->ht_capa->extended_ht_cap_info; + rCmdUpdate.rHtCap.u4TxBfCapInfo = params->ht_capa->tx_BF_cap_info; + rCmdUpdate.rHtCap.ucAntennaSelInfo = params->ht_capa->antenna_selection_info; + kalMemCopy(rCmdUpdate.rHtCap.rMCS.arRxMask, + params->ht_capa->mcs.rx_mask, sizeof(rCmdUpdate.rHtCap.rMCS.arRxMask)); + + rCmdUpdate.rHtCap.rMCS.u2RxHighest = params->ht_capa->mcs.rx_highest; + rCmdUpdate.rHtCap.rMCS.ucTxParams = params->ht_capa->mcs.tx_params; + rCmdUpdate.fgIsSupHt = TRUE; + } + /* vht */ + + if (params->vht_capa != NULL) { + /* rCmdUpdate.rVHtCap */ + /* rCmdUpdate.rVHtCap */ + } + + /* update a TDLS peer record */ + /* sanity check */ + if ((params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) + rCmdUpdate.eStaType = STA_TYPE_DLS_PEER; + rStatus = kalIoctl(prGlueInfo, cnmPeerUpdate, &rCmdUpdate, sizeof(CMD_PEER_UPDATE_T), FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EINVAL; + /* for Ch Sw AP prohibit case */ + if (prAisBssInfo->fgTdlsIsChSwProhibited) { + /* disable TDLS ch sw function */ + + rStatus = kalIoctl(prGlueInfo, + TdlsSendChSwControlCmd, + &TdlsSendChSwControlCmd, sizeof(CMD_TDLS_CH_SW_T), FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for adding a station information + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_add_station(struct wiphy *wiphy, struct net_device *ndev, + const u8 *mac, struct station_parameters *params) +{ + /* return 0; */ + + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + P_GLUE_INFO_T prGlueInfo = NULL; + CMD_PEER_ADD_T rCmdCreate; + ADAPTER_T *prAdapter; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + /* make up command */ + + prAdapter = prGlueInfo->prAdapter; + + /* init */ + kalMemZero(&rCmdCreate, sizeof(rCmdCreate)); + kalMemCopy(rCmdCreate.aucPeerMac, mac, 6); + + /* create a TDLS peer record */ + if ((params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) { + rCmdCreate.eStaType = STA_TYPE_DLS_PEER; + rStatus = kalIoctl(prGlueInfo, cnmPeerAdd, &rCmdCreate, sizeof(CMD_PEER_ADD_T), FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EINVAL; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for deleting a station information + * + * @param + * + * @retval 0: successful + * others: failure + * + * @other + * must implement if you have add_station(). + */ +/*----------------------------------------------------------------------------*/ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +int mtk_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, struct station_del_parameters *params) +#else +int mtk_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, const u8 *mac) +#endif +{ +/* fgIsTDLSlinkEnable = 0; */ + + /* return 0; */ + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + + P_GLUE_INFO_T prGlueInfo = NULL; + ADAPTER_T *prAdapter; + STA_RECORD_T *prStaRec; + u8 deleteMac[MAC_ADDR_LEN]; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + if (!prGlueInfo) { + DBGLOG(INIT, ERROR, "prGlueInfo is NULL\n"); + return -1; + } + + prAdapter = prGlueInfo->prAdapter; + /* For kernel 3.18 modification, we trasfer to local buff to query sta */ + memset(deleteMac, 0, MAC_ADDR_LEN); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + memcpy(&deleteMac, params->mac, MAC_ADDR_LEN); +#else + memcpy(&deleteMac, mac, MAC_ADDR_LEN); +#endif + + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) prAdapter->prAisBssInfo->ucBssIndex, deleteMac); + + if (prStaRec != NULL) + cnmStaRecFree(prAdapter, prStaRec); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to transmit a TDLS data frame from nl80211. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] +* \param[in] +* \param[in] buf includes RSN IE + FT IE + Lifetimeout IE +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, + bool initiator, const u8 *buf, size_t len) +{ + + GLUE_INFO_T *prGlueInfo; + TDLS_CMD_LINK_MGT_T rCmdMgt; + UINT_32 u4BufLen; + + /* sanity check */ + if ((wiphy == NULL) || (peer == NULL) || (buf == NULL)) + return -EINVAL; + + /* init */ + prGlueInfo = (GLUE_INFO_T *) wiphy_priv(wiphy); + if (prGlueInfo == NULL) + return -EINVAL; + + kalMemZero(&rCmdMgt, sizeof(rCmdMgt)); + rCmdMgt.u2StatusCode = status_code; + rCmdMgt.u4SecBufLen = len; + rCmdMgt.ucDialogToken = dialog_token; + rCmdMgt.ucActionCode = action_code; + kalMemCopy(&(rCmdMgt.aucPeer), peer, 6); + kalMemCopy(&(rCmdMgt.aucSecBuf), buf, len); + + kalIoctl(prGlueInfo, TdlsexLinkMgt, &rCmdMgt, sizeof(TDLS_CMD_LINK_MGT_T), FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + return 0; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to hadel TDLS link from nl80211. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] +* \param[in] +* \param[in] buf includes RSN IE + FT IE + Lifetimeout IE +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, + const u8 *peer, enum nl80211_tdls_operation oper) +{ + + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4BufLen; + ADAPTER_T *prAdapter; + TDLS_CMD_LINK_OPER_T rCmdOper; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rCmdOper, sizeof(rCmdOper)); + kalMemCopy(rCmdOper.aucPeerMac, peer, 6); + + rCmdOper.oper = oper; + + kalIoctl(prGlueInfo, TdlsexLinkOper, &rCmdOper, sizeof(TDLS_CMD_LINK_OPER_T), FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + return 0; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @brief cfg80211 suspend callback, will be invoked in wiphy_suspend. + * + * @param wiphy: pointer to wiphy + * wow: pointer to cfg80211_wowlan + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + if (kalHaltTryLock()) + return 0; + + if (kalIsHalted() || !wiphy) + goto end; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + set_bit(SUSPEND_FLAG_FOR_WAKEUP_REASON, &prGlueInfo->prAdapter->ulSuspendFlag); + set_bit(SUSPEND_FLAG_CLEAR_WHEN_RESUME, &prGlueInfo->prAdapter->ulSuspendFlag); +end: + kalHaltUnlock(); + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief cfg80211 resume callback, will be invoked in wiphy_resume. + * + * @param wiphy: pointer to wiphy + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_resume(struct wiphy *wiphy) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_BSS_DESC_T *pprBssDesc = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_8 i = 0; + + if (kalHaltTryLock()) + return 0; + + if (kalIsHalted() || !wiphy) + goto end; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + prAdapter = prGlueInfo->prAdapter; + clear_bit(SUSPEND_FLAG_CLEAR_WHEN_RESUME, &prAdapter->ulSuspendFlag); + pprBssDesc = &prAdapter->rWifiVar.rScanInfo.rNloParam.aprPendingBssDescToInd[0]; + for (; i < SCN_SSID_MATCH_MAX_NUM; i++) { + if (pprBssDesc[i] == NULL) + break; + if (pprBssDesc[i]->u2RawLength == 0) + continue; + kalIndicateBssInfo(prGlueInfo, + (PUINT_8) pprBssDesc[i]->aucRawBuf, + pprBssDesc[i]->u2RawLength, + pprBssDesc[i]->ucChannelNum, + RCPI_TO_dBm(pprBssDesc[i]->ucRCPI)); + } + DBGLOG(SCN, INFO, "pending %d sched scan results\n", i); + if (i > 0) + kalMemZero(&pprBssDesc[0], i * sizeof(P_BSS_DESC_T)); +end: + kalHaltUnlock(); + return 0; +} + +INT_32 mtk_cfg80211_process_str_cmd(P_GLUE_INFO_T prGlueInfo, PUINT_8 cmd, INT_32 len) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4SetInfoLen = 0; + + if (strncasecmp(cmd, "tdls-ps ", 8) == 0) { +#if CFG_SUPPORT_TDLS + rStatus = kalIoctl(prGlueInfo, + wlanoidDisableTdlsPs, + (PVOID)(cmd+8), 1, FALSE, FALSE, TRUE, &u4SetInfoLen); +#else + DBGLOG(REQ, WARN, "not support tdls\n"); + return -EOPNOTSUPP; +#endif + } else if (strncasecmp(cmd, "NEIGHBOR-REQUEST", 16) == 0) { + PUINT_8 pucSSID = NULL; + UINT_32 u4SSIDLen = 0; + + if (len > 16 && (strncasecmp(cmd+16, " SSID=", 6) == 0)) { + pucSSID = cmd + 22; + u4SSIDLen = len - 22; + DBGLOG(REQ, INFO, "cmd=%s, ssid len %u, ssid=%s\n", cmd, u4SSIDLen, pucSSID); + } + rStatus = kalIoctl(prGlueInfo, wlanoidSendNeighborRequest, + (PVOID)pucSSID, u4SSIDLen, FALSE, FALSE, TRUE, &u4SetInfoLen); + } else if (strncasecmp(cmd, "BSS-TRANSITION-QUERY", 20) == 0) { + PUINT_8 pucReason = NULL; + + if (len > 20 && (strncasecmp(cmd+20, " reason=", 8) == 0)) + pucReason = cmd + 28; + rStatus = kalIoctl(prGlueInfo, + wlanoidSendBTMQuery, + (PVOID)pucReason, 1, FALSE, FALSE, TRUE, &u4SetInfoLen); + } else if (strncasecmp(cmd, "O-SAR-ENABLE", 12) == 0) { + UINT_32 u2SarMode = 0; + INT_8 ret = -1; + + DBGLOG(REQ, INFO, "cmd=%s\n", cmd); + do { + if (len <= 13) { + DBGLOG(REQ, ERROR, "len <= 13 (%d).\n", len); + break; + } + + ret = kstrtouint(cmd+13, 0, &u2SarMode); + if (ret) { + DBGLOG(REQ, ERROR, "string to int fail %d.\n", ret); + break; + } + + DBGLOG(REQ, INFO, "u2SarMode=%d\n", u2SarMode); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSendSarEnable, + (PVOID)&u2SarMode, + sizeof(u2SarMode), + FALSE, + FALSE, + TRUE, + &u4SetInfoLen); + + } while (FALSE); + + } else if (kalStrniCmp(cmd, "OSHAREMOD ", 10) == 0) { +#if CFG_SUPPORT_OSHARE + struct OSHARE_MODE_T cmdBuf; + struct OSHARE_MODE_T *pCmdHeader = NULL; + struct OSHARE_MODE_SETTING_V1_T *pCmdData = NULL; + + kalMemZero(&cmdBuf, sizeof(cmdBuf)); + + pCmdHeader = &cmdBuf; + pCmdHeader->cmdVersion = OSHARE_MODE_CMD_V1; + pCmdHeader->cmdType = 1; /*1-set 0-query*/ + pCmdHeader->magicCode = OSHARE_MODE_MAGIC_CODE; + pCmdHeader->cmdBufferLen = MAX_OSHARE_MODE_LENGTH; + + pCmdData = (struct OSHARE_MODE_SETTING_V1_T *)&(pCmdHeader->buffer[0]); + pCmdData->osharemode = *(PUINT_8)(cmd + 10) - '0'; + + DBGLOG(REQ, INFO, "cmd=%s, osharemode=%u\n", cmd, pCmdData->osharemode); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetOshareMode, + &cmdBuf, + sizeof(struct OSHARE_MODE_T), + FALSE, + FALSE, + TRUE, + &u4SetInfoLen); + if (rStatus == WLAN_STATUS_SUCCESS) + prGlueInfo->prAdapter->fgEnOshareMode = pCmdData->osharemode; +#else + DBGLOG(REQ, WARN, "not support OSHAREMOD\n"); + return -EOPNOTSUPP; +#endif + + } else + return -EOPNOTSUPP; + + if (rStatus == WLAN_STATUS_SUCCESS) + return 0; + + return -EINVAL; +} + +int mtk_cfg80211_update_ft_ies(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_update_ft_ies_params *ftie) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4InfoBufLen = 0; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + +#if !CFG_SUPPORT_802_11R + DBGLOG(OID, INFO, "802.11R is not enabled\n"); + return 0; +#endif + if (!wiphy) + return -1; + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + rStatus = kalIoctl(prGlueInfo, wlanoidUpdateFtIes, (PVOID)ftie, sizeof(*ftie), FALSE, + FALSE, FALSE, &u4InfoBufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(OID, INFO, "update Ft IE failed\n"); + return 0; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_hook_api.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_hook_api.c new file mode 100644 index 0000000000000..0964d003aefd4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_hook_api.c @@ -0,0 +1,3400 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ +/* + *************************************************************************** + + Module Name: + gl_ate_agent.c +*/ +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ +#include "precomp.h" +#if CFG_SUPPORT_QA_TOOL +#include "gl_wext.h" +#include "gl_cfg80211.h" +#include "gl_ate_agent.h" +#include "gl_qa_agent.h" +/* #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) */ +#include +/* #endif */ +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +enum { + ATE_LOG_RXV = 1, + ATE_LOG_RDD, + ATE_LOG_RE_CAL, + ATE_LOG_TYPE_NUM, + ATE_LOG_RXINFO, + ATE_LOG_TXDUMP, + ATE_LOG_TEST, +}; + +enum { + ATE_LOG_OFF, + ATE_LOG_ON, + ATE_LOG_DUMP, + ATE_LOG_CTRL_NUM, +}; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Enter Test Mode. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEStart(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetTestMode, /* pfnOidHandler */ + NULL, /* pvInfoBuf */ + 0, /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Enter ICAP Mode. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ICAPStart(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetTestIcapMode, /* pfnOidHandler */ + NULL, /* pvInfoBuf */ + 0, /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Abort Test Mode. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEStop(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAbortTestMode, /* pfnOidHandler */ + NULL, /* pvInfoBuf */ + 0, /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Start auto Tx test in packet format and the driver will enter auto Tx test mode. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEStartTX(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_STARTTX; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Stop TX/RX test action if the driver is in any test mode. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEStopTX(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_STOPTEST; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Start auto Rx test and the driver will enter auto Rx test mode. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEStartRX(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_STARTRX; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Stop TX/RX test action if the driver is in any test mode. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEStopRX(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_STOPTEST; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set Channel Frequency. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4SetFreq Center frequency in unit of KHz +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetChannel(struct net_device *prNetDev, UINT_32 u4SXIdx, UINT_32 u4SetFreq) +{ + UINT_32 u4BufLen = 0; + UINT_32 i4SetChan; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + i4SetChan = nicFreq2ChannelNum(u4SetFreq); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetChannel=%d, Freq=%d\n", i4SetChan, u4SetFreq); + + if (u4SetFreq == 0) + return -EINVAL; + + if (u4SXIdx == 0) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_CHNL_FREQ; + rRfATInfo.u4FuncData = u4SetFreq; + } else { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_CHNL_FREQ | BIT(16); + rRfATInfo.u4FuncData = u4SetFreq; + } + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set Preamble. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4Mode depends on Rate. 0--> normal, 1--> CCK short preamble, 2: 11n MM, 3: 11n GF 4: 11ac VHT +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetPreamble(struct net_device *prNetDev, UINT_32 u4Mode) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetPreamble=%d\n", u4Mode); + + if (u4Mode > 4) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_PREAMBLE; + rRfATInfo.u4FuncData = u4Mode; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set Channel Bandwidth. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4BW Choose Channel Bandwidth 0: 20 / 1: 40 / 2: 80 / 3: 160 +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetSystemBW(struct net_device *prNetDev, UINT_32 u4BW) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 u4BWMapping; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetSystemBW=%d\n", u4BW); + + if (u4BW > 6) + return -EINVAL; + + if (u4BW == 0) + u4BWMapping = 0; + else if (u4BW == 1) + u4BWMapping = 1; + else if (u4BW == 2) + u4BWMapping = 2; + else if (u4BW == 3) + u4BWMapping = 6; + else if (u4BW == 4) + u4BWMapping = 5; + else if (u4BW == 5) + u4BWMapping = 3; + else if (u4BW == 6) + u4BWMapping = 4; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_CBW; + rRfATInfo.u4FuncData = u4BWMapping; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set TX Length. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4TxLength Packet length (MPDU) +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetTxLength(struct net_device *prNetDev, UINT_32 u4TxLength) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetTxLength=%d\n", u4TxLength); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_PKTLEN; + rRfATInfo.u4FuncData = u4TxLength; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set TX Count. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4TxCount Total packet count to send. 0 : unlimited, until stopped +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetTxCount(struct net_device *prNetDev, UINT_32 u4TxCount) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetTxCount=%d\n", u4TxCount); + + if (u4TxCount < 0) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_PKTCNT; + rRfATInfo.u4FuncData = u4TxCount; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set TX Inter-Packet Guard. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4TxIPG In unit of us. The min value is 19us and max value is 2314us. +* \ It will be round-up to (19+9n) us. +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetTxIPG(struct net_device *prNetDev, UINT_32 u4TxIPG) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetTxIPG=%d\n", u4TxIPG); + + if (u4TxIPG > 2314 || u4TxIPG < 19) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_PKTINTERVAL; + rRfATInfo.u4FuncData = u4TxIPG; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set WF0 TX Power. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4TxPower0 Tx Gain of RF. The value is signed absolute power +* (2's complement representation) in unit of 0.5 dBm. +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetTxPower0(struct net_device *prNetDev, UINT_32 u4TxPower0) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetTxPower0=0x%02x\n", u4TxPower0); + + if (u4TxPower0 > 0x3F) { + u4TxPower0 += 128; + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK Negative Power =0x%02x\n", u4TxPower0); + } + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_POWER; + rRfATInfo.u4FuncData = u4TxPower0; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set Per Packet BW. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4BW 0: 20 / 1: 40 / 2: 80 / 3: 160 +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetPerPacketBW(struct net_device *prNetDev, UINT_32 u4BW) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 u4BWMapping; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetPerPacketBW=%d\n", u4BW); + + if (u4BW > 6) + return -EINVAL; + + if (u4BW == 0) + u4BWMapping = 0; + else if (u4BW == 1) + u4BWMapping = 1; + else if (u4BW == 2) + u4BWMapping = 2; + else if (u4BW == 3) + u4BWMapping = 6; + else if (u4BW == 4) + u4BWMapping = 5; + else if (u4BW == 5) + u4BWMapping = 3; + else if (u4BW == 6) + u4BWMapping = 4; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_DBW; + rRfATInfo.u4FuncData = u4BWMapping; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Primary Channel Setting. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4PrimaryCh The range is from 0~7 +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEPrimarySetting(struct net_device *prNetDev, UINT_32 u4PrimaryCh) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK PrimarySetting=%d\n", u4PrimaryCh); + + if (u4PrimaryCh > 7) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_PRIMARY_CH; + rRfATInfo.u4FuncData = u4PrimaryCh; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set TX Guard Interval. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4SetTxGi 0: Normal GI, 1: Short GI +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetTxGi(struct net_device *prNetDev, UINT_32 u4SetTxGi) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetTxGi=%d\n", u4SetTxGi); + + if (u4SetTxGi != 0 && u4SetTxGi != 1) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_GI; + rRfATInfo.u4FuncData = u4SetTxGi; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set TX Path. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4Tx_path 0: All Tx, 1: WF0, 2: WF1, 3: WF0+WF1 +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetTxPath(struct net_device *prNetDev, UINT_32 u4Tx_path) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK u4Tx_path=%d\n", u4Tx_path); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TX_PATH; + rRfATInfo.u4FuncData = u4Tx_path; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set TX Payload Fix/Random. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4Stbc 0: Disable , 1 : Enable +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetTxPayLoad(struct net_device *prNetDev, UINT_32 u4Gen_payload_rule, UINT_8 ucPayload) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK rule=%d, len =0x%x\n", u4Gen_payload_rule, ucPayload); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_PAYLOAD; + rRfATInfo.u4FuncData = ((u4Gen_payload_rule << 16) | ucPayload); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set TX STBC. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4Stbc 0: Disable , 1 : Enable +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetTxSTBC(struct net_device *prNetDev, UINT_32 u4Stbc) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK u4Stbc=%d\n", u4Stbc); + + if (u4Stbc > 1) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_STBC; + rRfATInfo.u4FuncData = u4Stbc; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set TX Nss. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4Nss 1/2 +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetTxVhtNss(struct net_device *prNetDev, UINT_32 u4VhtNss) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK u4Nss=%d\n", u4VhtNss); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_NSS; + rRfATInfo.u4FuncData = u4VhtNss; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set Rate. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4Rate Rate +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetRate(struct net_device *prNetDev, UINT_32 u4Rate) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetRate=0x%08x\n", u4Rate); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_RATE; + rRfATInfo.u4FuncData = u4Rate; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set Encode Mode. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4Ldpc 0: BCC / 1: LDPC +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetEncodeMode(struct net_device *prNetDev, UINT_32 u4Ldpc) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetEncodeMode=%d\n", u4Ldpc); + + if (u4Ldpc != 0 && u4Ldpc != 1) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ENCODE_MODE; + rRfATInfo.u4FuncData = u4Ldpc; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set iBF Enable. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4iBF 0: disable / 1: enable +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetiBFEnable(struct net_device *prNetDev, UINT_32 u4iBF) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetiBFEnable=%d\n", u4iBF); + + if (u4iBF != 0 && u4iBF != 1) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_IBF_ENABLE; + rRfATInfo.u4FuncData = u4iBF; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set eBF Enable. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4eBF 0: disable / 1: enable +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESeteBFEnable(struct net_device *prNetDev, UINT_32 u4eBF) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SeteBFEnable=%d\n", u4eBF); + + if (u4eBF != 0 && u4eBF != 1) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_EBF_ENABLE; + rRfATInfo.u4FuncData = u4eBF; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set MAC Address. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4Type Address type +* \param[in] ucAddr Address ready to set +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetMACAddress(struct net_device *prNetDev, UINT_32 u4Type, PUINT_8 ucAddr) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, ERROR, "QA_ATE_HOOK SetMACAddress Type = %d, Addr = %02x:%02x:%02x:%02x:%02x:%02x\n", + u4Type, ucAddr[0], ucAddr[1], ucAddr[2], ucAddr[3], ucAddr[4], ucAddr[5]); + +#if 1 + rRfATInfo.u4FuncIndex = u4Type; + memcpy(&rRfATInfo.u4FuncData, ucAddr, 4); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; +#endif + rRfATInfo.u4FuncIndex = u4Type | BIT(18); + memset(&rRfATInfo.u4FuncData, 0, sizeof(rRfATInfo.u4FuncData)); + memcpy(&rRfATInfo.u4FuncData, ucAddr + 4, 2); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for RX Vector Dump. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4Type +* \param[in] u4On_off +* \param[in] u4Size +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATELogOnOff(struct net_device *prNetDev, UINT_32 u4Type, UINT_32 u4On_off, UINT_32 u4Size) +{ + INT_32 i4Status = 0, i4RXVLength, i, i4TargetLength = 36 * 30; + UINT_32 u4BufLen = 0, rxv; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATELogOnOff\n"); + + switch (u4Type) { + case ATE_LOG_RXV: + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATELogOnOff : ATE_LOG_RXV\n\n"); + break; + case ATE_LOG_RDD: + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATELogOnOff : ATE_LOG_RDD\n\n"); + break; + case ATE_LOG_RE_CAL: + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATELogOnOff : ATE_LOG_RE_CAL\n\n"); + break; + case ATE_LOG_RXINFO: + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATELogOnOff : ATE_LOG_RXINFO\n\n"); + break; + case ATE_LOG_TXDUMP: + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATELogOnOff : ATE_LOG_TXDUMP\n\n"); + break; + case ATE_LOG_TEST: + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATELogOnOff : ATE_LOG_TEST\n\n"); + break; + default: + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK log type %d not supported\n\n", u4Type); + } + + if ((u4On_off == ATE_LOG_DUMP) && (u4Type == ATE_LOG_RXV)) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_RXOK_COUNT; + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, + &rRfATInfo, sizeof(rRfATInfo), TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + i4TargetLength = rRfATInfo.u4FuncData * 36; + + if (i4TargetLength >= 3600) + i4TargetLength = 3600; + } + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_RESULT_INFO; + rRfATInfo.u4FuncData = RF_AT_FUNCID_RXV_DUMP; + + i4Status = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, + &rRfATInfo, sizeof(rRfATInfo), TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + i4RXVLength = rRfATInfo.u4FuncData; + DBGLOG(RFTEST, ERROR, "QA_ATE_HOOK Get RX Vector Total size = %d\n", i4RXVLength); + } else { + DBGLOG(RFTEST, ERROR, "QA_ATE_HOOK Get RX Vector Total Size Error!!!!\n\n"); + } + + TOOL_PRINTLOG(RFTEST, ERROR, "[LOG DUMP START]\n"); + + for (i = 0; i < i4TargetLength; i += 4) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_RXV_DUMP; + rRfATInfo.u4FuncData = i; + + i4Status = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, + &rRfATInfo, sizeof(rRfATInfo), TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + rxv = rRfATInfo.u4FuncData; + + if (i % 36 == 0) + TOOL_PRINTLOG(RFTEST, ERROR, "[RXV DUMP START][%d]\n", (i / 36) + 1); + + TOOL_PRINTLOG(RFTEST, ERROR, "[RXVD%d]%08x\n", ((i % 36) / 4) + 1, rxv); + + if (((i % 36) / 4) + 1 == 9) + TOOL_PRINTLOG(RFTEST, ERROR, "[RXV DUMP END]\n"); + } + } + + TOOL_PRINTLOG(RFTEST, ERROR, "[LOG DUMP END]\n"); + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Reset Counter. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEResetTXRXCounter(struct net_device *prNetDev) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATEResetTXRXCounter\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_RESETTXRXCOUNTER; + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set DBDC Band Index. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4BandIdx Band Index Number ready to set +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetDBDCBandIndex(struct net_device *prNetDev, UINT_32 u4BandIdx) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATESetDBDCBandIndex\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_DBDC_BAND_IDX; + rRfATInfo.u4FuncData = u4BandIdx; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set Band. (2G or 5G) +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] i4Band Band to set +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetBand(struct net_device *prNetDev, INT_32 i4Band) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATESetBand\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_BAND; + rRfATInfo.u4FuncData = i4Band; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set Tx Tone Type. (2G or 5G) +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] i4ToneType Set Single or Two Tone. +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetTxToneType(struct net_device *prNetDev, INT_32 i4ToneType) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATESetTxToneType\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TONE_TYPE; + rRfATInfo.u4FuncData = i4ToneType; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set Tx Tone Frequency. (DC/5M/10M/20M/40M) +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] i4ToneFreq Set Tx Tone Frequency. +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetTxToneBW(struct net_device *prNetDev, INT_32 i4ToneFreq) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATESetTxToneBW\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TONE_BW; + rRfATInfo.u4FuncData = i4ToneFreq; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set Tx Tone DC Offset. (DC Offset I / DC Offset Q) +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] i4DcOffsetI Set Tx Tone DC Offset I. +* \param[in] i4DcOffsetQ Set Tx Tone DC Offset Q. +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetTxToneDCOffset(struct net_device *prNetDev, INT_32 i4DcOffsetI, INT_32 i4DcOffsetQ) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATESetTxToneDCOffset\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TONE_DC_OFFSET; + rRfATInfo.u4FuncData = i4DcOffsetQ << 16 | i4DcOffsetI; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set Tx Tone Power. (RF and Digital) +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] i4AntIndex +* \param[in] i4RF_Power +* \param[in] i4Digi_Power +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetDBDCTxTonePower(struct net_device *prNetDev, INT_32 i4AntIndex, INT_32 i4RF_Power, INT_32 i4Digi_Power) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATESetDBDCTxTonePower\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TONE_RF_GAIN; + rRfATInfo.u4FuncData = i4AntIndex << 16 | i4RF_Power; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TONE_DIGITAL_GAIN; + rRfATInfo.u4FuncData = i4AntIndex << 16 | i4Digi_Power; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Start Tx Tone. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] i4Control Start or Stop TX Tone. +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEDBDCTxTone(struct net_device *prNetDev, INT_32 i4Control) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATEDBDCTxTone\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (i4Control) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_SINGLE_TONE; + } else { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_STOPTEST; + } + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set TX Mac Header. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4BandIdx Band Index Number ready to set +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetMacHeader(struct net_device *prNetDev, UINT_32 u4FrameCtrl, UINT_32 u4DurationID, UINT_32 u4SeqCtrl) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATESetMacHeader\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MAC_HEADER; + rRfATInfo.u4FuncData = u4FrameCtrl || (u4DurationID << 16); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_SEQ_CTRL; + rRfATInfo.u4FuncData = u4SeqCtrl; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for IRR Set ADC. (RF_AT_FUNCID_SET_ADC) +* +* \param[in] prNetDev Pointer to the Net Device +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATE_IRRSetADC(struct net_device *prNetDev, + UINT_32 u4WFIdx, + UINT_32 u4ChFreq, + UINT_32 u4BW, UINT_32 u4Sx, UINT_32 u4Band, UINT_32 u4RunType, UINT_32 u4FType) +{ + UINT_32 u4BufLen = 0, i = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 au4Param[7]; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATE_IRRSetADC\n"); + + if (u4BW == 3 || u4BW == 4 || u4BW > 5) + return -EINVAL; + + if (u4BW == 5) /* For BW160, UI will pass "5" */ + u4BW = 3; + + au4Param[0] = u4ChFreq; + au4Param[1] = u4WFIdx; + au4Param[2] = u4BW; + au4Param[3] = u4Sx; + au4Param[4] = u4Band; + au4Param[5] = u4RunType; + au4Param[6] = u4FType; + + for (i = 0; i < 8; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ADC | (i << 16); + if (i < 7) + rRfATInfo.u4FuncData = au4Param[i]; + else + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for IRR Set RX Gain. (RF_AT_FUNCID_SET_RX_GAIN) +* +* \param[in] prNetDev Pointer to the Net Device +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATE_IRRSetRxGain(struct net_device *prNetDev, + UINT_32 u4PgaLpfg, UINT_32 u4Lna, UINT_32 u4Band, UINT_32 u4WF_inx, UINT_32 u4Rfdgc) +{ + UINT_32 u4BufLen = 0, i = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 au4Param[5]; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATE_IRRSetRxGain\n"); + + au4Param[0] = u4PgaLpfg; + au4Param[1] = u4Lna; + au4Param[2] = u4Band; + au4Param[3] = u4WF_inx; + au4Param[4] = u4Rfdgc; + + for (i = 0; i < 6; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_RX_GAIN | (i << 16); + if (i < 5) + rRfATInfo.u4FuncData = au4Param[i]; + else + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for IRR Set TTG. (RF_AT_FUNCID_SET_TTG) +* +* \param[in] prNetDev Pointer to the Net Device +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATE_IRRSetTTG(struct net_device *prNetDev, + UINT_32 u4TTGPwrIdx, UINT_32 u4ChFreq, UINT_32 u4FIToneFreq, UINT_32 u4Band) +{ + UINT_32 u4BufLen = 0, i = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 au4Param[4]; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATE_IRRSetTTG\n"); + + au4Param[0] = u4ChFreq; + au4Param[1] = u4FIToneFreq; + au4Param[2] = u4TTGPwrIdx; + au4Param[3] = u4Band; + + for (i = 0; i < 5; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TTG | (i << 16); + if (i < 4) + rRfATInfo.u4FuncData = au4Param[i]; + else + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for IRR Set TTG On/Off. (RF_AT_FUNCID_TTG_ON_OFF) +* +* \param[in] prNetDev Pointer to the Net Device +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATE_IRRSetTrunOnTTG(struct net_device *prNetDev, UINT_32 u4TTGOnOff, UINT_32 u4Band, UINT_32 u4WF_inx) +{ + UINT_32 u4BufLen = 0, i = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 au4Param[3]; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATE_IRRSetTrunOnTTG\n"); + + au4Param[0] = u4TTGOnOff; + au4Param[1] = u4Band; + au4Param[2] = u4WF_inx; + + for (i = 0; i < 4; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_TTG_ON_OFF | (i << 16); + if (i < 3) + rRfATInfo.u4FuncData = au4Param[i]; + else + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for IRR Set TTG On/Off. +* +* \param[in] prNetDev Pointer to the Net Device +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATE_TMRSetting(struct net_device *prNetDev, + UINT_32 u4Setting, UINT_32 u4Version, UINT_32 u4MPThres, UINT_32 u4MPIter) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATE_TMRSetting\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TMR_ROLE; + rRfATInfo.u4FuncData = u4Setting; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TMR_MODULE; + rRfATInfo.u4FuncData = u4Version; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TMR_DBM; + rRfATInfo.u4FuncData = u4MPThres; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TMR_ITER; + rRfATInfo.u4FuncData = u4MPIter; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for MPS Setting. (Set Seq Data) +* +* \param[in] prNetDev Pointer to the Net Device +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEMPSSetSeqData(struct net_device *prNetDev, + UINT_32 u4TestNum, UINT_32 *pu4Phy, UINT_32 u4Band) +{ + UINT_32 u4BufLen = 0, i; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATEMPSSetSeqData\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_SIZE; + rRfATInfo.u4FuncData = u4TestNum; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + for (i = 0 ; i < u4TestNum ; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_SEQ_DATA | (i << 16); + rRfATInfo.u4FuncData = pu4Phy[i]; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for MPS Setting. (Set Payload Length) +* +* \param[in] prNetDev Pointer to the Net Device +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEMPSSetPayloadLength(struct net_device *prNetDev, + UINT_32 u4TestNum, UINT_32 *pu4Length, UINT_32 u4Band) +{ + UINT_32 u4BufLen = 0, i; + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATEMPSSetPayloadLength\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + for (i = 0 ; i < u4TestNum ; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_PAYLOAD_LEN | (i << 16); + rRfATInfo.u4FuncData = pu4Length[i]; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for MPS Setting. (Set Packet Count) +* +* \param[in] prNetDev Pointer to the Net Device +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEMPSSetPacketCount(struct net_device *prNetDev, + UINT_32 u4TestNum, UINT_32 *pu4PktCnt, UINT_32 u4Band) +{ + UINT_32 u4BufLen = 0, i; + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATEMPSSetPacketCount\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + for (i = 0 ; i < u4TestNum ; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_PKT_CNT | (i << 16); + rRfATInfo.u4FuncData = pu4PktCnt[i]; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for MPS Setting. (Set Power Gain) +* +* \param[in] prNetDev Pointer to the Net Device +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEMPSSetPowerGain(struct net_device *prNetDev, + UINT_32 u4TestNum, UINT_32 *pu4PwrGain, UINT_32 u4Band) +{ + UINT_32 u4BufLen = 0, i; + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATEMPSSetPowerGain\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + for (i = 0 ; i < u4TestNum ; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_PWR_GAIN | (i << 16); + rRfATInfo.u4FuncData = pu4PwrGain[i]; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for MPS Setting. (Set NSS) +* +* \param[in] prNetDev Pointer to the Net Device +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEMPSSetNss(struct net_device *prNetDev, + UINT_32 u4TestNum, UINT_32 *pu4Nss, UINT_32 u4Band) +{ + UINT_32 u4BufLen = 0, i; + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATEMPSSetNss\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + for (i = 0 ; i < u4TestNum ; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_NSS | (i << 16); + rRfATInfo.u4FuncData = pu4Nss[i]; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for MPS Setting. (Set NSS) +* +* \param[in] prNetDev Pointer to the Net Device +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEMPSSetPerpacketBW(struct net_device *prNetDev, + UINT_32 u4TestNum, UINT_32 *pu4PerPktBW, UINT_32 u4Band) +{ + UINT_32 u4BufLen = 0, i; + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATEMPSSetPerpacketBW\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + for (i = 0 ; i < u4TestNum ; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_PACKAGE_BW | (i << 16); + rRfATInfo.u4FuncData = pu4PerPktBW[i]; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Start RDD. +* +* \param[in] prNetDev Pointer to the Net Device +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATERDDStart(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_RDD; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Stop RDD. +* +* \param[in] prNetDev Pointer to the Net Device +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATERDDStop(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_RDD_OFF; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Write Efuse. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u2Offset Efuse offset +* \param[in] u2Content Efuse content +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEWriteEfuse(struct net_device *prNetDev, UINT_16 u2Offset, UINT_16 u2Content) +{ + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_ACCESS_EFUSE_T rAccessEfuseInfoRead, rAccessEfuseInfoWrite; + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS i4Status = WLAN_STATUS_SUCCESS; + UINT_8 u4Index = 0, u4Loop = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + kalMemSet(&rAccessEfuseInfoRead, 0, sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)); + kalMemSet(&rAccessEfuseInfoWrite, 0, sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)); + + + + /* Read */ + DBGLOG(INIT, INFO, "QA_AGENT HQA_WriteBulkEEPROM Read\n"); + kalMemSet(&rAccessEfuseInfoRead, 0, sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)); + rAccessEfuseInfoRead.u4Address = (u2Offset / EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + i4Status = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfoRead, + sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T), TRUE, TRUE, TRUE, &u4BufLen); + + + /* Write */ + kalMemSet(&rAccessEfuseInfoWrite, 0, sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)); + u4Index = u2Offset % EFUSE_BLOCK_SIZE; + + if (u4Index == 15) { + DBGLOG(INIT, ERROR, "u4Index == 15, u2Offset = %u.\n", u2Offset); + return -EFAULT; + } + + prGlueInfo->prAdapter->aucEepromVaule[u4Index] = u2Content; + prGlueInfo->prAdapter->aucEepromVaule[u4Index+1] = u2Content >> 8 & 0xff; + + kalMemCopy(rAccessEfuseInfoWrite.aucData, prGlueInfo->prAdapter->aucEepromVaule, 16); + + for (u4Loop = 0; u4Loop < (EFUSE_BLOCK_SIZE); u4Loop++) { + DBGLOG(INIT, INFO, "QA_AGENT aucEepromVaule u4Loop=%d u4Value=%x\n", + u4Loop, prGlueInfo->prAdapter->aucEepromVaule[u4Loop]); + + DBGLOG(INIT, INFO, "QA_AGENT rAccessEfuseInfoWrite.aucData u4Loop=%d u4Value=%x\n", + u4Loop, rAccessEfuseInfoWrite.aucData[u4Loop]); + } + + rAccessEfuseInfoWrite.u4Address = (u2Offset / EFUSE_BLOCK_SIZE)*EFUSE_BLOCK_SIZE; + + i4Status = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseWrite, + &rAccessEfuseInfoWrite, + sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T), FALSE, TRUE, TRUE, &u4BufLen); + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + + +#if CFG_SUPPORT_TX_BF +INT_32 TxBfProfileTag_InValid(struct net_device *prNetDev, P_PFMU_PROFILE_TAG1 prPfmuTag1, UINT_8 ucInValid) +{ + INT_32 i4Status = 0; + + prPfmuTag1->rField.ucInvalidProf = ucInValid; + + return i4Status; +} + +INT_32 TxBfProfileTag_PfmuIdx(struct net_device *prNetDev, P_PFMU_PROFILE_TAG1 prPfmuTag1, UINT_8 ucProfileIdx) +{ + INT_32 i4Status = 0; + + prPfmuTag1->rField.ucProfileID = ucProfileIdx; + + return i4Status; +} + +INT_32 TxBfProfileTag_TxBfType(struct net_device *prNetDev, P_PFMU_PROFILE_TAG1 prPfmuTag1, UINT_8 ucBFType) +{ + INT_32 i4Status = 0; + + prPfmuTag1->rField.ucTxBf = ucBFType; + + return i4Status; +} + +INT_32 TxBfProfileTag_DBW(struct net_device *prNetDev, P_PFMU_PROFILE_TAG1 prPfmuTag1, UINT_8 ucBW) +{ + INT_32 i4Status = 0; + + prPfmuTag1->rField.ucDBW = ucBW; + + return i4Status; +} + +INT_32 TxBfProfileTag_SuMu(struct net_device *prNetDev, P_PFMU_PROFILE_TAG1 prPfmuTag1, UINT_8 ucSuMu) +{ + INT_32 i4Status = 0; + + prPfmuTag1->rField.ucSU_MU = ucSuMu; + + return i4Status; +} + +INT_32 TxBfProfileTag_Mem(struct net_device *prNetDev, + P_PFMU_PROFILE_TAG1 prPfmuTag1, PUINT_8 aucMemAddrColIdx, PUINT_8 aucMemAddrRowIdx) +{ + INT_32 i4Status = 0; + + prPfmuTag1->rField.ucMemAddr1ColIdx = aucMemAddrColIdx[0]; + prPfmuTag1->rField.ucMemAddr1RowIdx = aucMemAddrRowIdx[0]; + prPfmuTag1->rField.ucMemAddr2ColIdx = aucMemAddrColIdx[1]; + prPfmuTag1->rField.ucMemAddr2RowIdx = aucMemAddrRowIdx[1] & 0x1F; + prPfmuTag1->rField.ucMemAddr2RowIdxMsb = aucMemAddrRowIdx[1] >> 5; + prPfmuTag1->rField.ucMemAddr3ColIdx = aucMemAddrColIdx[2]; + prPfmuTag1->rField.ucMemAddr3RowIdx = aucMemAddrRowIdx[2]; + prPfmuTag1->rField.ucMemAddr4ColIdx = aucMemAddrColIdx[3]; + prPfmuTag1->rField.ucMemAddr4RowIdx = aucMemAddrRowIdx[3]; + + return i4Status; +} + +INT_32 TxBfProfileTag_Matrix(struct net_device *prNetDev, + P_PFMU_PROFILE_TAG1 prPfmuTag1, + UINT_8 ucNrow, + UINT_8 ucNcol, UINT_8 ucNgroup, UINT_8 ucLM, UINT_8 ucCodeBook, UINT_8 ucHtcExist) +{ + INT_32 i4Status = 0; + + prPfmuTag1->rField.ucNrow = ucNrow; + prPfmuTag1->rField.ucNcol = ucNcol; + prPfmuTag1->rField.ucNgroup = ucNgroup; + prPfmuTag1->rField.ucLM = ucLM; + prPfmuTag1->rField.ucCodeBook = ucCodeBook; + prPfmuTag1->rField.ucHtcExist = ucHtcExist; + + return i4Status; +} + +INT_32 TxBfProfileTag_SNR(struct net_device *prNetDev, + P_PFMU_PROFILE_TAG1 prPfmuTag1, + UINT_8 ucSNR_STS0, UINT_8 ucSNR_STS1, UINT_8 ucSNR_STS2, UINT_8 ucSNR_STS3) +{ + INT_32 i4Status = 0; + + prPfmuTag1->rField.ucSNR_STS0 = ucSNR_STS0; + prPfmuTag1->rField.ucSNR_STS1 = ucSNR_STS1; + prPfmuTag1->rField.ucSNR_STS2 = ucSNR_STS2; + prPfmuTag1->rField.ucSNR_STS3 = ucSNR_STS3; + + return i4Status; +} + +INT_32 TxBfProfileTag_SmtAnt(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucSmartAnt) +{ + INT_32 i4Status = 0; + + prPfmuTag2->rField.u2SmartAnt = ucSmartAnt; + + return i4Status; +} + +INT_32 TxBfProfileTag_SeIdx(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucSeIdx) +{ + INT_32 i4Status = 0; + + prPfmuTag2->rField.ucSEIdx = ucSeIdx; + + return i4Status; +} + +INT_32 TxBfProfileTag_RmsdThd(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucRmsdThrd) +{ + INT_32 i4Status = 0; + + prPfmuTag2->rField.ucRMSDThd = ucRmsdThrd; + + return i4Status; +} + +INT_32 TxBfProfileTag_McsThd(struct net_device *prNetDev, + P_PFMU_PROFILE_TAG2 prPfmuTag2, PUINT_8 pMCSThLSS, PUINT_8 pMCSThSSS) +{ + INT_32 i4Status = 0; + + prPfmuTag2->rField.ucMCSThL1SS = pMCSThLSS[0]; + prPfmuTag2->rField.ucMCSThS1SS = pMCSThSSS[0]; + prPfmuTag2->rField.ucMCSThL2SS = pMCSThLSS[1]; + prPfmuTag2->rField.ucMCSThS2SS = pMCSThSSS[1]; + prPfmuTag2->rField.ucMCSThL3SS = pMCSThLSS[2]; + prPfmuTag2->rField.ucMCSThS3SS = pMCSThSSS[2]; + + return i4Status; +} + +INT_32 TxBfProfileTag_TimeOut(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucTimeOut) +{ + INT_32 i4Status = 0; + + prPfmuTag2->rField.uciBfTimeOut = ucTimeOut; + + return i4Status; +} + +INT_32 TxBfProfileTag_DesiredBW(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucDesiredBW) +{ + INT_32 i4Status = 0; + + prPfmuTag2->rField.uciBfDBW = ucDesiredBW; + + return i4Status; +} + +INT_32 TxBfProfileTag_DesiredNc(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucDesiredNc) +{ + INT_32 i4Status = 0; + + prPfmuTag2->rField.uciBfNcol = ucDesiredNc; + + return i4Status; +} + +INT_32 TxBfProfileTag_DesiredNr(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucDesiredNr) +{ + INT_32 i4Status = 0; + + prPfmuTag2->rField.uciBfNrow = ucDesiredNr; + + return i4Status; +} + +INT_32 TxBfProfileTagWrite(struct net_device *prNetDev, + P_PFMU_PROFILE_TAG1 prPfmuTag1, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 profileIdx) +{ + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_TXBF_ACTION_STRUCT_T rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : au4RawData[0] = 0x%08x\n", prPfmuTag1->au4RawData[0]); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : au4RawData[1] = 0x%08x\n", prPfmuTag1->au4RawData[1]); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : au4RawData[2] = 0x%08x\n", prPfmuTag1->au4RawData[2]); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : au4RawData[3] = 0x%08x\n", prPfmuTag1->au4RawData[3]); + + DBGLOG(RFTEST, ERROR, "prPfmuTag2 : au4RawData[0] = 0x%08x\n", prPfmuTag2->au4RawData[0]); + DBGLOG(RFTEST, ERROR, "prPfmuTag2 : au4RawData[1] = 0x%08x\n", prPfmuTag2->au4RawData[1]); + DBGLOG(RFTEST, ERROR, "prPfmuTag2 : au4RawData[2] = 0x%08x\n", prPfmuTag2->au4RawData[2]); + + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucProfileID= %d\n", prPfmuTag1->rField.ucProfileID); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : prPfmuTag1->rField.ucTxBf= %d\n", prPfmuTag1->rField.ucTxBf); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : prPfmuTag1->rField.ucDBW= %d\n", prPfmuTag1->rField.ucDBW); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : prPfmuTag1->rField.ucSU_MU= %d\n", prPfmuTag1->rField.ucSU_MU); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : prPfmuTag1->rField.ucInvalidProf= %d\n", + prPfmuTag1->rField.ucInvalidProf); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : prPfmuTag1->rField.ucRMSD= %d\n", prPfmuTag1->rField.ucRMSD); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr1ColIdx= %d\n", + prPfmuTag1->rField.ucMemAddr1ColIdx); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr1RowIdx= %d\n", + prPfmuTag1->rField.ucMemAddr1RowIdx); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr2ColIdx= %d\n", + prPfmuTag1->rField.ucMemAddr2ColIdx); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr2RowIdx= %d\n", + prPfmuTag1->rField.ucMemAddr2RowIdx); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr2RowIdxMsb= %d\n", + prPfmuTag1->rField.ucMemAddr2RowIdxMsb); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr3ColIdx= %d\n", + prPfmuTag1->rField.ucMemAddr3ColIdx); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr3RowIdx= %d\n", + prPfmuTag1->rField.ucMemAddr3RowIdx); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr4ColIdx= %d\n", + prPfmuTag1->rField.ucMemAddr4ColIdx); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr4RowIdx= %d\n", + prPfmuTag1->rField.ucMemAddr4RowIdx); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : prPfmuTag1->rField.ucReserved= %d\n", prPfmuTag1->rField.ucReserved); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : prPfmuTag1->rField.ucNrow= %d\n", prPfmuTag1->rField.ucNrow); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : prPfmuTag1->rField.ucNcol= %d\n", prPfmuTag1->rField.ucNcol); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : prPfmuTag1->rField.ucNgroup= %d\n", prPfmuTag1->rField.ucNgroup); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : prPfmuTag1->rField.ucLM= %d\n", prPfmuTag1->rField.ucLM); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : prPfmuTag1->rField.ucCodeBook= %d\n", prPfmuTag1->rField.ucCodeBook); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : prPfmuTag1->rField.ucHtcExist= %d\n", prPfmuTag1->rField.ucHtcExist); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucReserved1= %d\n", prPfmuTag1->rField.ucReserved1); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : prPfmuTag1->rField.ucSNR_STS0= %d\n", prPfmuTag1->rField.ucSNR_STS0); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : prPfmuTag1->rField.ucSNR_STS1= %d\n", prPfmuTag1->rField.ucSNR_STS1); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : prPfmuTag1->rField.ucSNR_STS2= %d\n", prPfmuTag1->rField.ucSNR_STS2); + DBGLOG(RFTEST, ERROR, "prPfmuTag1 : prPfmuTag1->rField.ucSNR_STS3= %d\n", prPfmuTag1->rField.ucSNR_STS3); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucIBfLnaIdx= %d\n", prPfmuTag1->rField.ucIBfLnaIdx); + + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.u2SmartAnt = %d\n", prPfmuTag2->rField.u2SmartAnt); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucReserved0 = %d\n", prPfmuTag2->rField.ucReserved0); + DBGLOG(RFTEST, ERROR, "prPfmuTag2 : prPfmuTag2->rField.ucSEIdx = %d\n", prPfmuTag2->rField.ucSEIdx); + DBGLOG(RFTEST, ERROR, "prPfmuTag2 : prPfmuTag2->rField.ucRMSDThd = %d\n", prPfmuTag2->rField.ucRMSDThd); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucReserved1 = %d\n", prPfmuTag2->rField.ucReserved1); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucMCSThL1SS = %d\n", prPfmuTag2->rField.ucMCSThL1SS); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucMCSThS1SS = %d\n", prPfmuTag2->rField.ucMCSThS1SS); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucMCSThL2SS = %d\n", prPfmuTag2->rField.ucMCSThL2SS); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucMCSThS2SS = %d\n", prPfmuTag2->rField.ucMCSThS2SS); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucMCSThL3SS = %d\n", prPfmuTag2->rField.ucMCSThL3SS); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucMCSThS3SS = %d\n", prPfmuTag2->rField.ucMCSThS3SS); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.uciBfTimeOut = %d\n", + prPfmuTag2->rField.uciBfTimeOut); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucReserved2 = %d\n", prPfmuTag2->rField.ucReserved2); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucReserved3 = %d\n", prPfmuTag2->rField.ucReserved3); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucReserved4 = %d\n", prPfmuTag2->rField.ucReserved4); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.uciBfDBW = %d\n", prPfmuTag2->rField.uciBfDBW); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.uciBfNcol = %d\n", prPfmuTag2->rField.uciBfNcol); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.uciBfNrow = %d\n", prPfmuTag2->rField.uciBfNrow); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.u2Reserved5 = %d\n", prPfmuTag2->rField.u2Reserved5); + + rTxBfActionInfo.rProfileTagWrite.ucTxBfCategory = BF_PFMU_TAG_WRITE; + rTxBfActionInfo.rProfileTagWrite.ucPfmuId = profileIdx; + memcpy(&rTxBfActionInfo.rProfileTagWrite.ucBuffer, prPfmuTag1, sizeof(PFMU_PROFILE_TAG1)); + memcpy(&rTxBfActionInfo.rProfileTagWrite.ucBuffer[16], prPfmuTag2, sizeof(PFMU_PROFILE_TAG2)); + + i4Status = kalIoctl(prGlueInfo, + wlanoidTxBfAction, + &rTxBfActionInfo, sizeof(rTxBfActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 TxBfProfileTagRead(struct net_device *prNetDev, UINT_8 profileIdx, UINT_8 fgBFer) +{ + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_TXBF_ACTION_STRUCT_T rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, "TxBfProfileTagRead : profileIdx = 0x%08x\n", profileIdx); + DBGLOG(RFTEST, ERROR, "TxBfProfileTagRead : fgBFer = 0x%08x\n", fgBFer); + + rTxBfActionInfo.rProfileTagRead.ucTxBfCategory = BF_PFMU_TAG_READ; + rTxBfActionInfo.rProfileTagRead.ucProfileIdx = profileIdx; + rTxBfActionInfo.rProfileTagRead.fgBfer = fgBFer; + + i4Status = kalIoctl(prGlueInfo, + wlanoidTxBfAction, &rTxBfActionInfo, sizeof(rTxBfActionInfo), TRUE, TRUE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 StaRecCmmUpdate(struct net_device *prNetDev, + UINT_8 ucWlanId, UINT_8 ucBssId, UINT_8 u4Aid, UINT_8 aucMacAddr[MAC_ADDR_LEN] +) +{ + CMD_STAREC_COMMON_T rStaRecCmm; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + INT_32 i4Status = 0; + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rStaRecCmm, sizeof(CMD_STAREC_COMMON_T)); + /* Tag assignment */ + rStaRecCmm.u2Tag = STA_REC_BASIC; + rStaRecCmm.u2Length = sizeof(CMD_STAREC_COMMON_T); + + /* content */ + kalMemCopy(rStaRecCmm.aucPeerMacAddr, aucMacAddr, MAC_ADDR_LEN); + rStaRecCmm.ucConnectionState = TRUE; + rStaRecCmm.u2AID = u4Aid; + rStaRecCmm.u2Reserve1 = ucWlanId; + + DBGLOG(RFTEST, ERROR, "ucWlanId = 0x%08x\n", ucWlanId); + + i4Status = kalIoctl(prGlueInfo, + wlanoidStaRecUpdate, + &rStaRecCmm, sizeof(CMD_STAREC_COMMON_T), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 StaRecBfUpdate(struct net_device *prNetDev, + STA_REC_BF_UPD_ARGUMENT rStaRecBfUpdArg, UINT_8 aucMemRow[4], UINT_8 aucMemCol[4] +) +{ + CMD_STAREC_BF rStaRecBF; + /* PARAM_CUSTOM_STA_REC_UPD_STRUCT_T rStaRecUpdateInfo = {0}; */ + /* P_STA_RECORD_T prStaRec; */ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + INT_32 i4Status = 0; + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rStaRecBF, sizeof(CMD_STAREC_BF)); + /* Tag assignment */ + rStaRecBF.u2Tag = STA_REC_BF; + rStaRecBF.u2Length = sizeof(CMD_STAREC_BF); + rStaRecBF.ucReserved[0] = rStaRecBfUpdArg.u4BssId; + rStaRecBF.ucReserved[1] = rStaRecBfUpdArg.u4WlanId; + /* content */ + rStaRecBF.rTxBfPfmuInfo.u2PfmuId = rStaRecBfUpdArg.u4PfmuId; + rStaRecBF.rTxBfPfmuInfo.ucTotMemRequire = rStaRecBfUpdArg.u4TotalMemReq; + rStaRecBF.rTxBfPfmuInfo.ucMemRequire20M = rStaRecBfUpdArg.u4MemReq20M; + rStaRecBF.rTxBfPfmuInfo.ucMemRow0 = aucMemRow[0]; + rStaRecBF.rTxBfPfmuInfo.ucMemCol0 = aucMemCol[0]; + rStaRecBF.rTxBfPfmuInfo.ucMemRow1 = aucMemRow[1]; + rStaRecBF.rTxBfPfmuInfo.ucMemCol1 = aucMemCol[1]; + rStaRecBF.rTxBfPfmuInfo.ucMemRow2 = aucMemRow[2]; + rStaRecBF.rTxBfPfmuInfo.ucMemCol2 = aucMemCol[2]; + rStaRecBF.rTxBfPfmuInfo.ucMemRow3 = aucMemRow[3]; + rStaRecBF.rTxBfPfmuInfo.ucMemCol3 = aucMemCol[3]; + /* 0 : SU, 1 : MU */ + rStaRecBF.rTxBfPfmuInfo.fgSU_MU = rStaRecBfUpdArg.u4SuMu; + /* 0: iBF, 1: eBF */ + rStaRecBF.rTxBfPfmuInfo.fgETxBfCap = rStaRecBfUpdArg.u4eTxBfCap; + /* 0: legacy, 1: OFDM, 2: HT, 4: VHT */ + rStaRecBF.rTxBfPfmuInfo.ucSoundingPhy = 1; + rStaRecBF.rTxBfPfmuInfo.ucNdpaRate = rStaRecBfUpdArg.u4NdpaRate; + rStaRecBF.rTxBfPfmuInfo.ucNdpRate = rStaRecBfUpdArg.u4NdpRate; + rStaRecBF.rTxBfPfmuInfo.ucReptPollRate = rStaRecBfUpdArg.u4ReptPollRate; + /* 0: legacy, 1: OFDM, 2: HT, 4: VHT */ + rStaRecBF.rTxBfPfmuInfo.ucTxMode = rStaRecBfUpdArg.u4TxMode; + rStaRecBF.rTxBfPfmuInfo.ucNc = rStaRecBfUpdArg.u4Nc; + rStaRecBF.rTxBfPfmuInfo.ucNr = rStaRecBfUpdArg.u4Nr; + /* 0 : 20M, 1 : 40M, 2 : 80M, 3 : 80 + 80M */ + rStaRecBF.rTxBfPfmuInfo.ucCBW = rStaRecBfUpdArg.u4Bw; + rStaRecBF.rTxBfPfmuInfo.ucSEIdx = rStaRecBfUpdArg.u4SpeIdx; + /* Default setting */ + rStaRecBF.rTxBfPfmuInfo.u2SmartAnt = 0; + rStaRecBF.rTxBfPfmuInfo.uciBfTimeOut = 0; + rStaRecBF.rTxBfPfmuInfo.uciBfDBW = 0; + rStaRecBF.rTxBfPfmuInfo.uciBfNcol = 0; + rStaRecBF.rTxBfPfmuInfo.uciBfNrow = 0; + + i4Status = kalIoctl(prGlueInfo, + wlanoidStaRecBFUpdate, &rStaRecBF, sizeof(CMD_STAREC_BF), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 DevInfoUpdate(struct net_device *prNetDev, UINT_8 ucOwnMacIdx, UINT_8 fgBand, UINT_8 aucMacAddr[MAC_ADDR_LEN]) +{ + CMD_DEVINFO_ACTIVE_T rDevInfo; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + INT_32 i4Status = 0; + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rDevInfo, sizeof(CMD_DEVINFO_ACTIVE_T)); + /* Tag assignment */ + rDevInfo.u2Tag = DEV_INFO_ACTIVE; + rDevInfo.u2Length = sizeof(CMD_DEVINFO_ACTIVE_T); + /* content */ + kalMemCopy(rDevInfo.aucOwnMacAddr, aucMacAddr, MAC_ADDR_LEN); + rDevInfo.ucActive = TRUE; + rDevInfo.ucBandNum = 0; + rDevInfo.aucReserve[0] = ucOwnMacIdx; + + i4Status = kalIoctl(prGlueInfo, + wlanoidDevInfoActive, + &rDevInfo, sizeof(CMD_DEVINFO_ACTIVE_T), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 BssInfoUpdate(struct net_device *prNetDev, UINT_8 ucOwnMacIdx, UINT_8 ucBssIdx, UINT_8 ucBssId[MAC_ADDR_LEN]) +{ + CMD_BSSINFO_BASIC_T rBssInfo; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + INT_32 i4Status = 0; + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rBssInfo, sizeof(CMD_BSSINFO_BASIC_T)); + /* Tag assignment */ + rBssInfo.u2Tag = BSS_INFO_BASIC; + rBssInfo.u2Length = sizeof(CMD_BSSINFO_BASIC_T); + /* content */ + kalMemCopy(rBssInfo.aucBSSID, ucBssId, MAC_ADDR_LEN); + rBssInfo.ucBcMcWlanidx = ucBssIdx; + rBssInfo.ucActive = TRUE; + rBssInfo.u4NetworkType = NETWORK_TYPE_AIS; + rBssInfo.u2BcnInterval = 100; + rBssInfo.ucDtimPeriod = 1; + + i4Status = kalIoctl(prGlueInfo, + wlanoidBssInfoBasic, &rBssInfo, sizeof(CMD_BSSINFO_BASIC_T), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 TxBfProfileDataRead(struct net_device *prNetDev, + UINT_8 profileIdx, UINT_8 fgBFer, UINT_8 ucSubCarrIdxMsb, UINT_8 ucSubCarrIdxLsb) +{ + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_TXBF_ACTION_STRUCT_T rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, "TxBfProfileDataRead : ucPfmuIdx = 0x%08x\n", profileIdx); + DBGLOG(RFTEST, ERROR, "TxBfProfileDataRead : fgBFer = 0x%08x\n", fgBFer); + DBGLOG(RFTEST, ERROR, "TxBfProfileDataRead : ucSubCarrIdxMsb = 0x%08x\n", ucSubCarrIdxMsb); + DBGLOG(RFTEST, ERROR, "TxBfProfileDataRead : ucSubCarrIdxLsb = 0x%08x\n", ucSubCarrIdxLsb); + + rTxBfActionInfo.rProfileDataRead.ucTxBfCategory = BF_PROFILE_READ; + rTxBfActionInfo.rProfileDataRead.ucPfmuIdx = profileIdx; + rTxBfActionInfo.rProfileDataRead.fgBFer = fgBFer; + rTxBfActionInfo.rProfileDataRead.ucSubCarrIdxMsb = ucSubCarrIdxMsb; + rTxBfActionInfo.rProfileDataRead.ucSubCarrIdxLsb = ucSubCarrIdxLsb; + + i4Status = kalIoctl(prGlueInfo, + wlanoidTxBfAction, &rTxBfActionInfo, sizeof(rTxBfActionInfo), TRUE, TRUE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 TxBfProfileDataWrite(struct net_device *prNetDev, + UINT_8 profileIdx, + UINT_16 u2SubCarrIdx, UINT_16 au2Phi[6], UINT_8 aucPsi[6], UINT_8 aucDSnr[4] +) +{ + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_TXBF_ACTION_STRUCT_T rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, "TxBfProfileDataWrite : ucPfmuIdx = 0x%08x\n", profileIdx); + DBGLOG(RFTEST, ERROR, "TxBfProfileDataWrite : u2SubCarrIdx = 0x%08x\n", u2SubCarrIdx); + + DBGLOG(RFTEST, ERROR, "TxBfProfileDataWrite : au2Phi[0] = 0x%08x\n", au2Phi[0]); + DBGLOG(RFTEST, ERROR, "TxBfProfileDataWrite : au2Phi[1] = 0x%08x\n", au2Phi[1]); + DBGLOG(RFTEST, ERROR, "TxBfProfileDataWrite : au2Phi[2] = 0x%08x\n", au2Phi[2]); + DBGLOG(RFTEST, ERROR, "TxBfProfileDataWrite : au2Phi[3] = 0x%08x\n", au2Phi[3]); + DBGLOG(RFTEST, ERROR, "TxBfProfileDataWrite : au2Phi[4] = 0x%08x\n", au2Phi[4]); + DBGLOG(RFTEST, ERROR, "TxBfProfileDataWrite : au2Phi[5] = 0x%08x\n", au2Phi[5]); + + DBGLOG(RFTEST, ERROR, "TxBfProfileDataWrite : aucPsi[0] = 0x%08x\n", aucPsi[0]); + DBGLOG(RFTEST, ERROR, "TxBfProfileDataWrite : aucPsi[1] = 0x%08x\n", aucPsi[1]); + DBGLOG(RFTEST, ERROR, "TxBfProfileDataWrite : aucPsi[2] = 0x%08x\n", aucPsi[2]); + DBGLOG(RFTEST, ERROR, "TxBfProfileDataWrite : aucPsi[3] = 0x%08x\n", aucPsi[3]); + DBGLOG(RFTEST, ERROR, "TxBfProfileDataWrite : aucPsi[4] = 0x%08x\n", aucPsi[4]); + DBGLOG(RFTEST, ERROR, "TxBfProfileDataWrite : aucPsi[5] = 0x%08x\n", aucPsi[5]); + + DBGLOG(RFTEST, ERROR, "TxBfProfileDataWrite : aucDSnr[0] = 0x%x\n", aucDSnr[0]); + DBGLOG(RFTEST, ERROR, "TxBfProfileDataWrite : aucDSnr[1] = 0x%x\n", aucDSnr[1]); + DBGLOG(RFTEST, ERROR, "TxBfProfileDataWrite : aucDSnr[2] = 0x%x\n", aucDSnr[2]); + DBGLOG(RFTEST, ERROR, "TxBfProfileDataWrite : aucDSnr[3] = 0x%x\n", aucDSnr[3]); + + rTxBfActionInfo.rProfileDataWrite.ucTxBfCategory = BF_PROFILE_WRITE; + rTxBfActionInfo.rProfileDataWrite.ucPfmuIdx = profileIdx; + rTxBfActionInfo.rProfileDataWrite.u2SubCarrIdxLsb = u2SubCarrIdx; + rTxBfActionInfo.rProfileDataWrite.u2SubCarrIdxMsb = u2SubCarrIdx >> 8; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2Phi11 = au2Phi[0]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2Phi21 = au2Phi[1]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2Phi31 = au2Phi[2]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2Phi22 = au2Phi[3]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2Phi32 = au2Phi[4]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2Phi33 = au2Phi[5]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.ucPsi21 = aucPsi[0]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.ucPsi31 = aucPsi[1]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.ucPsi41 = aucPsi[2]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.ucPsi32 = aucPsi[3]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.ucPsi42 = aucPsi[4]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.ucPsi43 = aucPsi[5]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2dSNR00 = aucDSnr[0]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2dSNR01 = aucDSnr[1]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2dSNR02 = aucDSnr[2]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2dSNR03 = aucDSnr[3]; + + i4Status = kalIoctl(prGlueInfo, + wlanoidTxBfAction, + &rTxBfActionInfo, sizeof(rTxBfActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 TxBfProfilePnRead(struct net_device *prNetDev, UINT_8 profileIdx) +{ + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_TXBF_ACTION_STRUCT_T rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, "TxBfProfilePnRead : ucPfmuIdx = 0x%08x\n", profileIdx); + + rTxBfActionInfo.rProfilePnRead.ucTxBfCategory = BF_PN_READ; + rTxBfActionInfo.rProfilePnRead.ucPfmuIdx = profileIdx; + + i4Status = kalIoctl(prGlueInfo, + wlanoidTxBfAction, + &rTxBfActionInfo, sizeof(rTxBfActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 TxBfProfilePnWrite(struct net_device *prNetDev, UINT_8 profileIdx, UINT_16 u2bw, UINT_16 au2XSTS[12]) +{ + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_TXBF_ACTION_STRUCT_T rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, "TxBfProfilePnWrite : ucPfmuIdx = 0x%08x\n", profileIdx); + DBGLOG(RFTEST, ERROR, "TxBfProfilePnWrite : u2bw = 0x%08x\n", u2bw); + DBGLOG(RFTEST, ERROR, "TxBfProfilePnWrite : au2XSTS[0] = 0x%08x\n", au2XSTS[0]); + DBGLOG(RFTEST, ERROR, "TxBfProfilePnWrite : au2XSTS[1] = 0x%08x\n", au2XSTS[1]); + DBGLOG(RFTEST, ERROR, "TxBfProfilePnWrite : au2XSTS[2] = 0x%08x\n", au2XSTS[2]); + DBGLOG(RFTEST, ERROR, "TxBfProfilePnWrite : au2XSTS[3] = 0x%08x\n", au2XSTS[3]); + DBGLOG(RFTEST, ERROR, "TxBfProfilePnWrite : au2XSTS[4] = 0x%08x\n", au2XSTS[4]); + DBGLOG(RFTEST, ERROR, "TxBfProfilePnWrite : au2XSTS[5] = 0x%08x\n", au2XSTS[5]); + DBGLOG(RFTEST, ERROR, "TxBfProfilePnWrite : au2XSTS[6] = 0x%08x\n", au2XSTS[6]); + DBGLOG(RFTEST, ERROR, "TxBfProfilePnWrite : au2XSTS[7] = 0x%08x\n", au2XSTS[7]); + DBGLOG(RFTEST, ERROR, "TxBfProfilePnWrite : au2XSTS[8] = 0x%08x\n", au2XSTS[8]); + DBGLOG(RFTEST, ERROR, "TxBfProfilePnWrite : au2XSTS[9] = 0x%08x\n", au2XSTS[9]); + DBGLOG(RFTEST, ERROR, "TxBfProfilePnWrite : au2XSTS[10] = 0x%08x\n", au2XSTS[10]); + DBGLOG(RFTEST, ERROR, "TxBfProfilePnWrite : au2XSTS[11] = 0x%08x\n", au2XSTS[11]); + + rTxBfActionInfo.rProfilePnWrite.ucTxBfCategory = BF_PN_WRITE; + rTxBfActionInfo.rProfilePnWrite.ucPfmuIdx = profileIdx; + rTxBfActionInfo.rProfilePnWrite.u2bw = u2bw; + memcpy(&rTxBfActionInfo.rProfilePnWrite.ucBuf[0], au2XSTS, 24); + + i4Status = kalIoctl(prGlueInfo, + wlanoidTxBfAction, + &rTxBfActionInfo, sizeof(rTxBfActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 TxBfSounding(struct net_device *prNetDev, UINT_8 ucSuMu, /* 0/1/2/3 */ + UINT_8 ucNumSta, /* 00~04 */ + UINT_8 ucSndInterval, /* 00~FF */ + UINT_8 ucWLan0, /* 00~7F */ + UINT_8 ucWLan1, /* 00~7F */ + UINT_8 ucWLan2, /* 00~7F */ + + UINT_8 ucWLan3 /* 00~7F */ +) +{ + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_TXBF_ACTION_STRUCT_T rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, "TxBfSounding : ucSuMu = 0x%08x\n", ucSuMu); + DBGLOG(RFTEST, ERROR, "TxBfSounding : ucNumSta = 0x%08x\n", ucNumSta); + DBGLOG(RFTEST, ERROR, "TxBfSounding : ucSndInterval = 0x%08x\n", ucSndInterval); + DBGLOG(RFTEST, ERROR, "TxBfSounding : ucWLan0 = 0x%08x\n", ucWLan0); + DBGLOG(RFTEST, ERROR, "TxBfSounding : ucWLan1 = 0x%08x\n", ucWLan1); + DBGLOG(RFTEST, ERROR, "TxBfSounding : ucWLan2 = 0x%08x\n", ucWLan2); + DBGLOG(RFTEST, ERROR, "TxBfSounding : ucWLan3 = 0x%08x\n", ucWLan3); + + switch (ucSuMu) { + case MU_SOUNDING: + + case MU_PERIODIC_SOUNDING: + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding.rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucCmdCategoryID = + BF_SOUNDING_ON; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding.rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucSuMuSndMode = + ucSuMu; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding.rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucStaNum = + ucNumSta; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding. + rExtCmdExtBfMuSndPeriodicTriggerCtrl.u4SoundingInterval = ucSndInterval; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding.rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucWlanId[0] = + ucWLan0; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding.rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucWlanId[1] = + ucWLan1; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding.rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucWlanId[2] = + ucWLan2; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding.rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucWlanId[3] = + ucWLan3; + break; + + case SU_SOUNDING: + case SU_PERIODIC_SOUNDING: + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding.rExtCmdExtBfSndPeriodicTriggerCtrl.ucCmdCategoryID = + BF_SOUNDING_ON; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding.rExtCmdExtBfSndPeriodicTriggerCtrl.ucSuMuSndMode = + ucSuMu; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding.rExtCmdExtBfSndPeriodicTriggerCtrl.u4SoundingInterval = + ucSndInterval; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding.rExtCmdExtBfSndPeriodicTriggerCtrl.ucWlanIdx = ucWLan0; + break; + default: + break; + } + + i4Status = kalIoctl(prGlueInfo, + wlanoidTxBfAction, + &rTxBfActionInfo, sizeof(rTxBfActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 TxBfSoundingStop(struct net_device *prNetDev) +{ + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_TXBF_ACTION_STRUCT_T rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, "TxBfSoundingStop\n"); + + rTxBfActionInfo.rTxBfSoundingStop.ucTxBfCategory = BF_SOUNDING_OFF; + rTxBfActionInfo.rTxBfSoundingStop.ucSndgStop = 1; + + i4Status = kalIoctl(prGlueInfo, + wlanoidTxBfAction, + &rTxBfActionInfo, sizeof(rTxBfActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 TxBfTxApply(struct net_device *prNetDev, UINT_8 ucWlanId, UINT_8 fgETxBf, UINT_8 fgITxBf, UINT_8 fgMuTxBf) +{ + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_TXBF_ACTION_STRUCT_T rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, + "TxBfTxApply : ucWlanId = 0x%08x, fgETxBf = 0x%08x,fgITxBf = 0x%08x,fgMuTxBf = 0x%08x\n", + ucWlanId, fgETxBf, fgITxBf, fgMuTxBf); + + rTxBfActionInfo.rTxBfTxApply.ucTxBfCategory = BF_DATA_PACKET_APPLY; + rTxBfActionInfo.rTxBfTxApply.ucWlanId = ucWlanId; + rTxBfActionInfo.rTxBfTxApply.fgETxBf = fgETxBf; + rTxBfActionInfo.rTxBfTxApply.fgITxBf = fgITxBf; + rTxBfActionInfo.rTxBfTxApply.fgMuTxBf = fgMuTxBf; + + i4Status = kalIoctl(prGlueInfo, + wlanoidTxBfAction, + &rTxBfActionInfo, sizeof(rTxBfActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 TxBfPfmuMemAlloc(struct net_device *prNetDev, UINT_8 ucSuMuMode, UINT_8 ucWlanIdx) +{ + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_TXBF_ACTION_STRUCT_T rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, + "TxBfPfmuMemAlloc : ucSuMuMode = 0x%08x, ucWlanIdx = 0x%08x\n", ucSuMuMode, ucWlanIdx); + + rTxBfActionInfo.rTxBfPfmuMemAlloc.ucTxBfCategory = BF_PFMU_MEM_ALLOCATE; + rTxBfActionInfo.rTxBfPfmuMemAlloc.ucSuMuMode = ucSuMuMode; + rTxBfActionInfo.rTxBfPfmuMemAlloc.ucWlanIdx = ucWlanIdx; + + i4Status = kalIoctl(prGlueInfo, + wlanoidTxBfAction, + &rTxBfActionInfo, sizeof(rTxBfActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 TxBfPfmuMemRelease(struct net_device *prNetDev, UINT_8 ucWlanId) +{ + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_TXBF_ACTION_STRUCT_T rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, "TxBfPfmuMemRelease : ucWlanId = 0x%08x\n", ucWlanId); + + rTxBfActionInfo.rTxBfPfmuMemRls.ucTxBfCategory = BF_PFMU_MEM_RELEASE; + rTxBfActionInfo.rTxBfPfmuMemRls.ucWlanId = ucWlanId; + + i4Status = kalIoctl(prGlueInfo, + wlanoidTxBfAction, + &rTxBfActionInfo, sizeof(rTxBfActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 TxBfBssInfoUpdate(struct net_device *prNetDev, UINT_8 ucOwnMacIdx, UINT_8 ucBssIdx, UINT_8 ucBssId[MAC_ADDR_LEN]) +{ + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + /* UINT_32 u4BufLen = 0; */ + PARAM_CUSTOM_TXBF_ACTION_STRUCT_T rTxBfActionInfo; + P_BSS_INFO_T prBssInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, "TxBfBssInfoUpdate : ucOwnMacIdx = 0x%08x\n", ucOwnMacIdx); + DBGLOG(RFTEST, ERROR, "TxBfBssInfoUpdate : ucBssIdx = 0x%08x\n", ucBssIdx); + DBGLOG(RFTEST, ERROR, "TxBfBssInfoUpdate : ucBssId[0] = 0x%08x\n", ucBssId[0]); + DBGLOG(RFTEST, ERROR, "TxBfBssInfoUpdate : ucBssId[1] = 0x%08x\n", ucBssId[1]); + DBGLOG(RFTEST, ERROR, "TxBfBssInfoUpdate : ucBssId[2] = 0x%08x\n", ucBssId[2]); + DBGLOG(RFTEST, ERROR, "TxBfBssInfoUpdate : ucBssId[3] = 0x%08x\n", ucBssId[3]); + DBGLOG(RFTEST, ERROR, "TxBfBssInfoUpdate : ucBssId[4] = 0x%08x\n", ucBssId[4]); + DBGLOG(RFTEST, ERROR, "TxBfBssInfoUpdate : ucBssId[5] = 0x%08x\n", ucBssId[5]); + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + if (!prBssInfo) + return WLAN_STATUS_FAILURE; + prBssInfo->ucOwnMacIndex = ucOwnMacIdx; + memcpy(&prBssInfo->aucBSSID, &ucBssId, MAC_ADDR_LEN); + + nicUpdateBss(prAdapter, prBssInfo->ucBssIndex); + + return i4Status; +} + +/* iwpriv ra0 set assoc=[mac:hh:hh:hh:hh:hh:hh]-[wtbl:dd]- + * [ownmac:dd]-[type:xx]-[mode:mmm]-[bw:dd]-[nss:ss]-[maxrate:kkk_dd] + */ +INT_32 TxBfManualAssoc(struct net_device *prNetDev, UINT_8 aucMac[MAC_ADDR_LEN], UINT_8 ucType, /* no use */ + UINT_8 ucWtbl, + UINT_8 ucOwnmac, + UINT_8 ucMode, + UINT_8 ucBw, + UINT_8 ucNss, UINT_8 ucPfmuId, UINT_8 ucMarate, UINT_8 ucSpeIdx, UINT_8 ucRca2, UINT_8 ucRv) +{ + CMD_MANUAL_ASSOC_STRUCT_T rManualAssoc; + /* P_STA_RECORD_T prStaRec; */ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + INT_32 i4Status = 0; + /* UINT_8 ucNsts; */ + /* UINT_32 i; */ + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rManualAssoc, sizeof(CMD_MANUAL_ASSOC_STRUCT_T)); + /* Tag assignment */ + rManualAssoc.u2Tag = STA_REC_MAUNAL_ASSOC; + rManualAssoc.u2Length = sizeof(CMD_MANUAL_ASSOC_STRUCT_T); + /* content */ + kalMemCopy(rManualAssoc.aucMac, aucMac, MAC_ADDR_LEN); + rManualAssoc.ucType = ucType; + rManualAssoc.ucWtbl = ucWtbl; + rManualAssoc.ucOwnmac = ucOwnmac; + rManualAssoc.ucMode = ucMode; + rManualAssoc.ucBw = ucBw; + rManualAssoc.ucNss = ucNss; + rManualAssoc.ucPfmuId = ucPfmuId; + rManualAssoc.ucMarate = ucMarate; + rManualAssoc.ucSpeIdx = ucSpeIdx; + rManualAssoc.ucaid = ucRca2; + +#if 0 + switch (ucMode) { + case 0: /* abggnanac */ + prStaRec->ucDesiredPhyTypeSet = aucPhyCfg2PhyTypeSet[PHY_TYPE_SET_802_11ABGNAC]; + break; + case 1: /* bggnan */ + prStaRec->ucDesiredPhyTypeSet = aucPhyCfg2PhyTypeSet[PHY_TYPE_SET_802_11ABGN]; + break; + case 2: /* aanac */ + prStaRec->ucDesiredPhyTypeSet = aucPhyCfg2PhyTypeSet[PHY_TYPE_SET_802_11ANAC]; + break; + default: + prStaRec->ucDesiredPhyTypeSet = aucPhyCfg2PhyTypeSet[PHY_TYPE_SET_802_11ABGNAC]; + break; + } + + prStaRec->rTxBfPfmuStaInfo.u2PfmuId = ucPfmuId; + + memcpy(prStaRec->aucMacAddr, aucMac, MAC_ADDR_LEN); + + i4Status = kalIoctl(prGlueInfo, + wlanoidStaRecUpdate, + &rStaRecUpdateInfo, + sizeof(PARAM_CUSTOM_STA_REC_UPD_STRUCT_T), FALSE, FALSE, TRUE, &u4BufLen); +#endif + + i4Status = kalIoctl(prGlueInfo, + wlanoidManualAssoc, + &rManualAssoc, sizeof(CMD_MANUAL_ASSOC_STRUCT_T), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +#endif +#endif /*CFG_SUPPORT_QA_TOOL */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_init.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_init.c new file mode 100644 index 0000000000000..8827dcd439f35 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_init.c @@ -0,0 +1,2991 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_init.c#11 +*/ + +/* + * ! \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. + */ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "gl_cfg80211.h" +#include "precomp.h" +#if CFG_SUPPORT_AGPS_ASSIST +#include "gl_kal.h" +#endif +#include "gl_vendor.h" + +#ifdef FW_CFG_SUPPORT +#include "fwcfg.h" +#endif +#ifndef MTK_WCN_BUILT_IN_DRIVER +#include "connectivity_build_in_adapter.h" +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) +#include "linux/sched/types.h" +#endif +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* #define MAX_IOREQ_NUM 10 */ +static struct wireless_dev *gprWdev; +BOOLEAN fgNvramAvailable; +UINT_8 g_aucNvram[CFG_FILE_WIFI_REC_SIZE]; + +static INT_32 g_fixedIfindex; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* + * Tasklet mechanism is like buttom-half in Linux. We just want to + * send a signal to OS for interrupt defer processing. All resources + * are NOT allowed reentry, so txPacket, ISR-DPC and ioctl must avoid preempty. + */ +typedef struct _WLANDEV_INFO_T { + struct net_device *prDev; +} WLANDEV_INFO_T, *P_WLANDEV_INFO_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +#define CHAN2G(_channel, _freq, _flags) \ +{ \ + .band = KAL_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 = KAL_BAND_5GHZ, \ + .center_freq = (((_channel >= 182) && (_channel <= 196)) ? \ + (4000 + (5 * (_channel))) : (5000 + (5 * (_channel)))), \ + .hw_value = (_channel), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} + +static struct ieee80211_channel mtk_5ghz_channels[] = { + /* UNII-1 */ + CHAN5G(34, 0), CHAN5G(36, 0), + CHAN5G(38, 0), CHAN5G(40, 0), + CHAN5G(42, 0), CHAN5G(44, 0), + CHAN5G(46, 0), CHAN5G(48, 0), + /* UNII-2 */ + CHAN5G(52, IEEE80211_CHAN_RADAR), + CHAN5G(56, IEEE80211_CHAN_RADAR), + CHAN5G(60, IEEE80211_CHAN_RADAR), + CHAN5G(64, IEEE80211_CHAN_RADAR), + /* UNII-2e */ + CHAN5G(100, IEEE80211_CHAN_RADAR), + CHAN5G(104, IEEE80211_CHAN_RADAR), + CHAN5G(108, IEEE80211_CHAN_RADAR), + CHAN5G(112, IEEE80211_CHAN_RADAR), + CHAN5G(116, IEEE80211_CHAN_RADAR), + CHAN5G(120, IEEE80211_CHAN_RADAR), + CHAN5G(124, IEEE80211_CHAN_RADAR), + CHAN5G(128, IEEE80211_CHAN_RADAR), + CHAN5G(132, IEEE80211_CHAN_RADAR), + CHAN5G(136, IEEE80211_CHAN_RADAR), + CHAN5G(140, IEEE80211_CHAN_RADAR), + CHAN5G(144, IEEE80211_CHAN_RADAR), + /* UNII-3 */ + CHAN5G(149, 0), + CHAN5G(153, 0), CHAN5G(157, 0), + CHAN5G(161, 0), CHAN5G(165, 0), + CHAN5G(169, 0), CHAN5G(173, 0), + CHAN5G(184, 0), CHAN5G(188, 0), + CHAN5G(192, 0), CHAN5G(196, 0), + CHAN5G(200, 0), CHAN5G(204, 0), + CHAN5G(208, 0), CHAN5G(212, 0), + CHAN5G(216, 0), +}; + +#define RATETAB_ENT(_rate, _rateid, _flags) \ +{ \ + .bitrate = (_rate), \ + .hw_value = (_rateid), \ + .flags = (_flags), \ +} + +/* for cfg80211 - rate table */ +static struct ieee80211_rate mtk_rates[] = { + RATETAB_ENT(10, 0x1000, 0), + RATETAB_ENT(20, 0x1001, 0), + RATETAB_ENT(55, 0x1002, 0), + RATETAB_ENT(110, 0x1003, 0), /* 802.11b */ + RATETAB_ENT(60, 0x2000, 0), + RATETAB_ENT(90, 0x2001, 0), + RATETAB_ENT(120, 0x2002, 0), + RATETAB_ENT(180, 0x2003, 0), + RATETAB_ENT(240, 0x2004, 0), + RATETAB_ENT(360, 0x2005, 0), + RATETAB_ENT(480, 0x2006, 0), + RATETAB_ENT(540, 0x2007, 0), /* 802.11a/g */ +}; + +#define mtk_a_rates (mtk_rates + 4) +#define mtk_a_rates_size (ARRAY_SIZE(mtk_rates) - 4) +#define mtk_g_rates (mtk_rates + 0) +#define mtk_g_rates_size (ARRAY_SIZE(mtk_rates) - 0) + +#define WLAN_MCS_INFO \ +{ \ + .rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0},\ + .rx_highest = 0, \ + .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ +} + +#define WLAN_VHT_MCS_INFO \ +{ \ + .rx_mcs_map = 0xFFFA, \ + .rx_highest = cpu_to_le16(867), \ + .tx_mcs_map = 0xFFFA, \ + .tx_highest = cpu_to_le16(867), \ +} + +#define WLAN_HT_CAP \ +{ \ + .ht_supported = true, \ + .cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 \ + | IEEE80211_HT_CAP_SM_PS \ + | IEEE80211_HT_CAP_GRN_FLD \ + | IEEE80211_HT_CAP_SGI_20 \ + | IEEE80211_HT_CAP_SGI_40, \ + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, \ + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE, \ + .mcs = WLAN_MCS_INFO, \ +} + +#define WLAN_VHT_CAP \ +{ \ + .vht_supported = true, \ + .cap = IEEE80211_VHT_CAP_RXLDPC \ + | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK \ + | IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 \ + | IEEE80211_VHT_CAP_RXLDPC \ + | IEEE80211_VHT_CAP_SHORT_GI_80 \ + | IEEE80211_VHT_CAP_TXSTBC \ + | IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE \ + | IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE, \ + .vht_mcs = WLAN_VHT_MCS_INFO, \ +} + +/********************************************************** +* Public for both legacy Wi-Fi and P2P to access +**********************************************************/ +struct ieee80211_supported_band mtk_band_2ghz = { + .band = KAL_BAND_2GHZ, + .channels = mtk_2ghz_channels, + .n_channels = ARRAY_SIZE(mtk_2ghz_channels), + .bitrates = mtk_g_rates, + .n_bitrates = mtk_g_rates_size, + .ht_cap = WLAN_HT_CAP, +}; + +/* public for both Legacy Wi-Fi / P2P access */ +struct ieee80211_supported_band mtk_band_5ghz = { + .band = KAL_BAND_5GHZ, + .channels = mtk_5ghz_channels, + .n_channels = ARRAY_SIZE(mtk_5ghz_channels), + .bitrates = mtk_a_rates, + .n_bitrates = mtk_a_rates_size, + .ht_cap = WLAN_HT_CAP, + .vht_cap = WLAN_VHT_CAP, +}; + +const UINT_32 mtk_cipher_suites[5] = { + /* keep WEP first, it may be removed below */ + WLAN_CIPHER_SUITE_WEP40, + WLAN_CIPHER_SUITE_WEP104, + WLAN_CIPHER_SUITE_TKIP, + WLAN_CIPHER_SUITE_CCMP, + + /* keep last -- depends on hw flags! */ + WLAN_CIPHER_SUITE_AES_CMAC +}; + +/*********************************************************/ + +/* NIC interface name */ +#define NIC_INF_NAME "wlan%d" + +#if CFG_SUPPORT_SNIFFER +#define NIC_MONITOR_INF_NAME "radiotap%d" +#endif + +UINT_8 aucDebugModule[DBG_MODULE_NUM]; + +/* 4 2007/06/26, mikewu, now we don't use this, we just fix the number of wlan device to 1 */ +static WLANDEV_INFO_T arWlanDevInfo[CFG_MAX_WLAN_DEVICES] = { {0} }; + +static UINT_32 u4WlanDevNum; /* How many NICs coexist now */ + +/**20150205 added work queue for sched_scan to avoid cfg80211 stop schedule scan dead loack**/ +struct delayed_work sched_workq; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +static struct cfg80211_ops mtk_wlan_ops = { + .suspend = mtk_cfg80211_suspend, + .resume = mtk_cfg80211_resume, + .change_virtual_intf = mtk_cfg80211_change_iface, + .add_key = mtk_cfg80211_add_key, + .get_key = mtk_cfg80211_get_key, + .del_key = mtk_cfg80211_del_key, + .set_default_key = mtk_cfg80211_set_default_key, + .get_station = mtk_cfg80211_get_station, +#if CFG_SUPPORT_TDLS + .change_station = mtk_cfg80211_change_station, + .add_station = mtk_cfg80211_add_station, + .del_station = mtk_cfg80211_del_station, +#endif + .scan = mtk_cfg80211_scan, +#if CFG_SUPPORT_ABORT_SCAN + .abort_scan = mtk_cfg80211_abort_scan, +#endif + .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, +#ifdef CONFIG_SUPPORT_GTK_REKEY + .set_rekey_data = mtk_cfg80211_set_rekey_data, +#endif + .assoc = mtk_cfg80211_assoc, + /* Action Frame TX/RX */ + .remain_on_channel = mtk_cfg80211_remain_on_channel, + .cancel_remain_on_channel = mtk_cfg80211_cancel_remain_on_channel, + .mgmt_tx = mtk_cfg80211_mgmt_tx, + /* .mgmt_tx_cancel_wait = mtk_cfg80211_mgmt_tx_cancel_wait, */ + .mgmt_frame_register = mtk_cfg80211_mgmt_frame_register, +#ifdef CONFIG_NL80211_TESTMODE + .testmode_cmd = mtk_cfg80211_testmode_cmd, +#endif + .sched_scan_start = mtk_cfg80211_sched_scan_start, + .sched_scan_stop = mtk_cfg80211_sched_scan_stop, +#if CFG_SUPPORT_TDLS + .tdls_oper = mtk_cfg80211_tdls_oper, + .tdls_mgmt = mtk_cfg80211_tdls_mgmt, +#endif + .update_ft_ies = mtk_cfg80211_update_ft_ies, +#if (defined(NL80211_ATTR_EXTERNAL_AUTH_SUPPORT) \ + || LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) + .external_auth = mtk_cfg80211_external_auth, +#endif +}; + +static const struct wiphy_vendor_command mtk_wlan_vendor_ops[] = { + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_GET_CHANNEL_LIST + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_channel_list + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_SET_COUNTRY_CODE + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_country_code + }, + /* Roaming */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_GET_ROAMING_CAPABILITIES + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_roaming_capabilities + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_CONFIG_ROAMING + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_config_roaming + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_ENABLE_ROAMING + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_enable_roaming + }, + /* GSCAN */ +#if CFG_SUPPORT_GSCN + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_SUBCMD_GET_CAPABILITIES + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_gscan_capabilities + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_SUBCMD_SET_CONFIG + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_config + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_SUBCMD_SET_SCAN_CONFIG + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_scan_config + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_SUBCMD_ENABLE_GSCAN + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_enable_scan + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_enable_full_scan_results + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_SUBCMD_GET_SCAN_RESULTS + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_gscan_result + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_significant_change + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_SUBCMD_SET_HOTLIST + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_hotlist + }, +#endif + /* RTT */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = RTT_SUBCMD_GETCAPABILITY + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_rtt_capabilities + }, + /* Link Layer Statistics */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = LSTATS_SUBCMD_GET_INFO + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_llstats_get_info + }, + /* RSSI Monitoring */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_SET_RSSI_MONITOR + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_rssi_monitoring + }, + /* Packet Keep Alive */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_OFFLOAD_START_MKEEP_ALIVE + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_packet_keep_alive_start + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_OFFLOAD_STOP_MKEEP_ALIVE + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_packet_keep_alive_stop + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV + | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_scan_mac_oui + }, + { + { + .vendor_id = OUI_QCA, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_roaming_policy + }, + /* Get Supported Feature Set */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_GET_FEATURE_SET + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_supported_feature_set + }, + /* Get Driver Version or Firmware Version */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = LOGGER_GET_VER + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_version + }, + /* Set Tx Power Scenario */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_SELECT_TX_POWER_SCENARIO + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_tx_power_scenario + }, + /* Get Driver Memory Dump */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = LOGGER_DRIVER_MEM_DUMP + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_driver_memory_dump + } + +}; + + +static const struct nl80211_vendor_cmd_info mtk_wlan_vendor_events[] = { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_HOTLIST_RESULTS_FOUND + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_SCAN_RESULTS_AVAILABLE + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_FULL_SCAN_RESULTS + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = RTT_EVENT_COMPLETE + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_COMPLETE_SCAN + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_HOTLIST_RESULTS_LOST + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_EVENT_RSSI_MONITOR + }, +#ifdef CFG_SUPPORT_DATA_STALL + { + .vendor_id = OUI_MTK, + .subcmd = WIFI_EVENT_DRIVER_ERROR + }, +#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_ais_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { + [NL80211_IFTYPE_ADHOC] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) + }, + [NL80211_IFTYPE_STATION] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) + }, + [NL80211_IFTYPE_AP] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + | BIT(IEEE80211_STYPE_ACTION >> 4) +#if CFG_SUPPORT_SOFTAP_WPA3 + | BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) +#endif + }, + [NL80211_IFTYPE_AP_VLAN] = { + /* copy AP */ + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) | BIT(IEEE80211_STYPE_ACTION >> 4) + }, + [NL80211_IFTYPE_P2P_CLIENT] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + }, + [NL80211_IFTYPE_P2P_GO] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | BIT(IEEE80211_STYPE_ACTION >> 4) + } +}; + +#ifdef CONFIG_PM +static const struct wiphy_wowlan_support mtk_wlan_wowlan_support = { + .flags = WIPHY_WOWLAN_DISCONNECT | WIPHY_WOWLAN_ANY, +}; +#endif + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \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; +} +#endif + +UINT_16 wlanSelectQueue(struct net_device *dev, struct sk_buff *skb, + void *accel_priv, select_queue_fallback_t fallback) +{ + UINT_16 au16Wlan1dToQueueIdx[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; + + /* Use Linux wireless utility function */ + skb->priority = cfg80211_classify8021d(skb, NULL); + + return au16Wlan1dToQueueIdx[skb->priority]; +} +/*----------------------------------------------------------------------------*/ +/*! + * \brief A method of struct net_device, to set the randomized mac address + * + * This method is called before Wifi Framework requests a new conenction with + * enabled feature "Connected Random Mac". + * + * \param[in] ndev Pointer to struct net_device. + * \param[in] addr Randomized Mac address passed from WIFI framework. + * + * \return int. + */ +/*----------------------------------------------------------------------------*/ +static int wlanSetMacAddress(struct net_device *ndev, void *addr) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + struct sockaddr *sa = NULL; + + /********************************************************************** + * Check if kernel passes valid data to us * + ********************************************************************** + */ + if (!ndev || !addr) { + DBGLOG(INIT, ERROR, "Set macaddr with ndev(%d) and addr(%d)\n", + (ndev == NULL) ? 0 : 1, (addr == NULL) ? 0 : 1); + return WLAN_STATUS_INVALID_DATA; + } + + /********************************************************************** + * 1. Change OwnMacAddr which will be updated to FW through * + * rlmActivateNetwork later. * + * 2. Change dev_addr stored in kernel to notify framework that the * + * mac addr has been changed and what the new value is. * + ********************************************************************** + */ + sa = (struct sockaddr *)addr; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(ndev)); + prAdapter = prGlueInfo->prAdapter; + + COPY_MAC_ADDR(prAdapter->prAisBssInfo->aucOwnMacAddr, sa->sa_data); + COPY_MAC_ADDR(prGlueInfo->prDevHandler->dev_addr, sa->sa_data); + DBGLOG(INIT, INFO, "Set connect random mac addr to " MACSTR ".\n", + MAC2STR(prAdapter->prAisBssInfo->aucOwnMacAddr)); + + return WLAN_STATUS_SUCCESS; +} /* end of wlanSetMacAddr() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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] = {0}; + PUINT_8 pucDest; + + ASSERT(prGlueInfo); + ASSERT(prRegInfo); + + if ((!prGlueInfo) || (!prRegInfo)) + return; + + DBGLOG(INIT, INFO, "fgNvramAvailable = %u\n", fgNvramAvailable); + prGlueInfo->fgNvramAvailable = fgNvramAvailable; + if (!prGlueInfo->fgNvramAvailable) { + DBGLOG(INIT, WARN, "Nvram not available\n"); + return; + } + + do { + /* load MAC Address */ + for (i = 0; i < PARAM_MAC_ADDR_LEN; i += sizeof(UINT_16)) { + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucMacAddress) + i, + (PUINT_16) (((PUINT_8) prRegInfo->aucMacAddr) + i)); + } + + /* 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]; + prRegInfo->ucRxDiversity = aucTmp[1]; + + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, fgRssiCompensationVaildbit), (PUINT_16) aucTmp); + prRegInfo->ucRssiPathCompasationUsed = aucTmp[0]; + prRegInfo->ucGpsDesense = aucTmp[1]; + +#if CFG_SUPPORT_NVRAM_5G + /* load EFUSE overriding part */ + for (i = 0; i < sizeof(prRegInfo->aucEFUSE); i += sizeof(UINT_16)) { + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, EfuseMapping) + i, + (PUINT_16) (((PUINT_8) &(prRegInfo->aucEFUSE)) + i)); + } + + prRegInfo->prOldEfuseMapping = (P_NEW_EFUSE_MAPPING2NVRAM_T)&prRegInfo->aucEFUSE; +#else + +/* 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)); + } +#endif + + /* load band edge tx power control */ + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, fg2G4BandEdgePwrUsed), (PUINT_16) aucTmp); + prRegInfo->fg2G4BandEdgePwrUsed = (BOOLEAN) aucTmp[0]; + if (aucTmp[0]) { + prRegInfo->cBandEdgeMaxPwrCCK = (INT_8) aucTmp[1]; + + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, cBandEdgeMaxPwrOFDM20), (PUINT_16) aucTmp); + prRegInfo->cBandEdgeMaxPwrOFDM20 = (INT_8) aucTmp[0]; + prRegInfo->cBandEdgeMaxPwrOFDM40 = (INT_8) aucTmp[1]; + } + + /* load regulation subbands */ + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, ucRegChannelListMap), (PUINT_16) aucTmp); + prRegInfo->eRegChannelListMap = (ENUM_REG_CH_MAP_T) aucTmp[0]; + prRegInfo->ucRegChannelListIndex = aucTmp[1]; + + if (prRegInfo->eRegChannelListMap == REG_CH_MAP_CUSTOMIZED) { + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + pucDest = (PUINT_8) &prRegInfo->rDomainInfo.rSubBand[i]; + for (j = 0; j < 6; j += sizeof(UINT_16)) { + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucRegSubbandInfo) + + (i * 6 + j), (PUINT_16) aucTmp); + + *pucDest++ = aucTmp[0]; + *pucDest++ = aucTmp[1]; + } + } + } + + /* load rssiPathCompensation */ + for (i = 0; i < sizeof(RSSI_PATH_COMPASATION_T); i += sizeof(UINT_16)) { + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, + rRssiPathCompensation) + i, + (PUINT_16) (((PUINT_8) &(prRegInfo->rRssiPathCompasation)) + + i)); + } +#if 1 + /* load full NVRAM */ + for (i = 0; i < sizeof(WIFI_CFG_PARAM_STRUCT); i += sizeof(UINT_16)) { + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part1OwnVersion) + i, + (PUINT_16) (((PUINT_8) &(prRegInfo->aucNvram)) + i)); + } + prRegInfo->prNvramSettings = (P_WIFI_CFG_PARAM_STRUCT)&prRegInfo->aucNvram; +#endif + } while (FALSE); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Release prDev from wlandev_array and free tasklet object related to it. +* +* \param[in] prDev Pointer to struct net_device +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static void wlanClearDevIdx(struct net_device *prDev) +{ + int i; + + ASSERT(prDev); + + for (i = 0; i < CFG_MAX_WLAN_DEVICES; i++) { + if (arWlanDevInfo[i].prDev == prDev) { + arWlanDevInfo[i].prDev = NULL; + u4WlanDevNum--; + } + } + +} /* end of wlanClearDevIdx() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Allocate an unique interface index, net_device::ifindex member for this +* wlan device. Store the net_device in wlandev_array, and initialize +* tasklet object related to it. +* +* \param[in] prDev Pointer to struct net_device +* +* \retval >= 0 The device number. +* \retval -1 Fail to get index. +*/ +/*----------------------------------------------------------------------------*/ +static int wlanGetDevIdx(struct net_device *prDev) +{ + int i; + + ASSERT(prDev); + + for (i = 0; i < CFG_MAX_WLAN_DEVICES; i++) { + if (arWlanDevInfo[i].prDev == (struct net_device *)NULL) { + /* Reserve 2 bytes space to store one digit of + * device number and NULL terminator. + */ + arWlanDevInfo[i].prDev = prDev; + u4WlanDevNum++; + return i; + } + } + + return -1; +} /* end of wlanGetDevIdx() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A method of struct net_device, a primary SOCKET interface to configure +* the interface lively. Handle an ioctl call on one of our devices. +* Everything Linux ioctl specific is done here. Then we pass the contents +* of the ifr->data to the request message handler. +* +* \param[in] prDev Linux kernel netdevice +* +* \param[in] prIfReq Our private ioctl request structure, typed for the generic +* struct ifreq so we can use ptr to function +* +* \param[in] cmd Command ID +* +* \retval 0 The IOCTL command is executed successfully. +* \retval <0 The execution of IOCTL command is failed. +*/ +/*----------------------------------------------------------------------------*/ +int wlanDoIOCTL(struct net_device *prDev, struct ifreq *prIfReq, int i4Cmd) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + int ret = 0; + + /* Verify input parameters for the following functions */ + ASSERT(prDev && prIfReq); + if (!prDev || !prIfReq) { + DBGLOG(INIT, ERROR, "Invalid input data\n"); + return -EINVAL; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + if (!prGlueInfo) { + DBGLOG(INIT, ERROR, "prGlueInfo is NULL\n"); + return -EFAULT; + } + + if (prGlueInfo->u4ReadyFlag == 0) { + DBGLOG(INIT, ERROR, "Adapter is not ready\n"); + return -EINVAL; + } + + if ((i4Cmd >= SIOCIWFIRST) && (i4Cmd < SIOCIWFIRSTPRIV)) { + /* 0x8B00 ~ 0x8BDF, wireless extension region */ + ret = wext_support_ioctl(prDev, prIfReq, i4Cmd); + } else if ((i4Cmd >= SIOCIWFIRSTPRIV) && (i4Cmd < SIOCIWLASTPRIV)) { + /* 0x8BE0 ~ 0x8BFF, private ioctl region */ + ret = priv_support_ioctl(prDev, prIfReq, i4Cmd); + } else if (i4Cmd == SIOCDEVPRIVATE + 1) { + ret = priv_support_driver_cmd(prDev, prIfReq, i4Cmd); + } else { + DBGLOG(INIT, WARN, "Unexpected ioctl command: 0x%04x\n", i4Cmd); + ret = -EOPNOTSUPP; + } + + return ret; +} /* end of wlanDoIOCTL() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief 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 +*/ +/*---------------------------------------------------------------------------*/ +P_GLUE_INFO_T wlanGetGlueInfo(VOID) +{ + if (!gprWdev) + return NULL; + return (P_GLUE_INFO_T) wiphy_priv(gprWdev->wiphy); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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; + + if (kalHaltLock(KAL_HALT_LOCK_TIMEOUT_NORMAL_CASE)) + return; + if (kalIsHalted()) { + kalHaltUnlock(); + return; + } + + prGlueInfo = (prDev != NULL) ? *((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); + kalHaltUnlock(); + return; + } + + if (prDev->flags & IFF_PROMISC) + u4PacketFilter |= PARAM_PACKET_FILTER_PROMISCUOUS; + + if (prDev->flags & IFF_BROADCAST) + u4PacketFilter |= PARAM_PACKET_FILTER_BROADCAST; + + if (prDev->flags & IFF_MULTICAST) { + if ((prDev->flags & IFF_ALLMULTI) || (netdev_mc_count(prDev) > MAX_NUM_GROUP_ADDR)) + u4PacketFilter |= PARAM_PACKET_FILTER_ALL_MULTICAST; + else + u4PacketFilter |= PARAM_PACKET_FILTER_MULTICAST; + } + + kalHaltUnlock(); + + if (kalIoctl(prGlueInfo, + wlanoidSetCurrentPacketFilter, + &u4PacketFilter, + sizeof(u4PacketFilter), FALSE, FALSE, TRUE, &u4SetInfoLen) != WLAN_STATUS_SUCCESS) { + return; + } + + if (u4PacketFilter & PARAM_PACKET_FILTER_MULTICAST) { + /* Prepare multicast address list */ + struct netdev_hw_addr *ha; + PUINT_8 prMCAddrList = NULL; + UINT_32 i = 0; + + if (kalHaltLock(KAL_HALT_LOCK_TIMEOUT_NORMAL_CASE)) + return; + + if (kalIsHalted()) { + kalHaltUnlock(); + return; + } + + prMCAddrList = kalMemAlloc(MAX_NUM_GROUP_ADDR * ETH_ALEN, VIR_MEM_TYPE); + if (!prMCAddrList) { + DBGLOG(INIT, WARN, "prMCAddrList memory alloc fail!\n"); + return; + } + netif_addr_lock_bh(prDev); + netdev_for_each_mc_addr(ha, prDev) { + if (i < MAX_NUM_GROUP_ADDR) { + kalMemCopy((prMCAddrList + i * ETH_ALEN), ha->addr, ETH_ALEN); + i++; + } + } + netif_addr_unlock_bh(prDev); + kalHaltUnlock(); + + kalIoctl(prGlueInfo, + wlanoidSetMulticastList, prMCAddrList, (i * ETH_ALEN), FALSE, FALSE, TRUE, &u4SetInfoLen); + + kalMemFree(prMCAddrList, VIR_MEM_TYPE, MAX_NUM_GROUP_ADDR * ETH_ALEN); + } + +} /* end of wlanSetMulticastList() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate scheduled scan has been stopped +* +* \param[in] +* prGlueInfo +* +* \return +* None +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanSchedScanStoppedWorkQueue(struct work_struct *work) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + struct net_device *prDev = gPrDev; + + DBGLOG(SCN, INFO, "wlanSchedScanStoppedWorkQueue\n"); + prGlueInfo = (prDev != NULL) ? *((P_GLUE_INFO_T *) netdev_priv(prDev)) : NULL; + if (!prGlueInfo) { + DBGLOG(SCN, INFO, "prGlueInfo == NULL unexpected\n"); + return; + } + + /* 2. indication to cfg80211 */ + /* 20150205 change cfg80211_sched_scan_stopped to work queue due to sched_scan_mtx dead lock issue */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) + cfg80211_sched_scan_stopped(priv_to_wiphy(prGlueInfo)); +#else + cfg80211_sched_scan_stopped(priv_to_wiphy(prGlueInfo), 0); +#endif + DBGLOG(SCN, INFO, + "cfg80211_sched_scan_stopped event send done WorkQueue thread return from wlanSchedScanStoppedWorkQueue\n"); + return; + +} + +/*----------------------------------------------------------------------------*/ +/* +* \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_NETDEV_PRIVATE_GLUE_INFO prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) NULL; + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + UINT_8 ucBssIndex; + + ASSERT(prSkb); + ASSERT(prDev); + ASSERT(prGlueInfo); + + prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(prDev); + ASSERT(prNetDevPrivate->prGlueInfo == prGlueInfo); + ucBssIndex = prNetDevPrivate->ucBssIdx; + prGlueInfo->u8SkbToDriver++; + +#if CFG_SUPPORT_PASSPOINT + if (prGlueInfo->fgIsDad) { + /* kalPrint("[Passpoint R2] Due to ipv4_dad...TX is forbidden\n"); */ + dev_kfree_skb(prSkb); + prGlueInfo->u8SkbFreed++; + return NETDEV_TX_OK; + } + if (prGlueInfo->fgIs6Dad) { + /* kalPrint("[Passpoint R2] Due to ipv6_dad...TX is forbidden\n"); */ + dev_kfree_skb(prSkb); + prGlueInfo->u8SkbFreed++; + + return NETDEV_TX_OK; + } +#endif /* CFG_SUPPORT_PASSPOINT */ + + kalResetPacket(prGlueInfo, (P_NATIVE_PACKET) prSkb); + + STATS_TX_TIME_ARRIVE(prSkb); + + if (kalHardStartXmit(prSkb, prDev, prGlueInfo, ucBssIndex) == WLAN_STATUS_SUCCESS) { + /* Successfully enqueue to Tx queue */ + /* Successfully enqueue to Tx queue */ + if (netif_carrier_ok(prDev)) + kalPerMonStart(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) +{ + return (struct net_device_stats *)kalGetStats(prDev); +} /* end of wlanGetStats() */ + +VOID wlanDebugInit(VOID) +{ + UINT_8 i; + + /* Set the initial debug level of each module */ +#if DBG + for (i = 0; i < DBG_MODULE_NUM; i++) + aucDebugModule[i] = DBG_CLASS_MASK; /* enable all */ +#else + for (i = 0; i < DBG_MODULE_NUM; i++) + aucDebugModule[i] = DBG_CLASS_ERROR | DBG_CLASS_WARN | DBG_CLASS_STATE | DBG_CLASS_INFO; + + aucDebugModule[DBG_INTR_IDX] = DBG_CLASS_ERROR; +#endif /* DBG */ + + LOG_FUNC("Reset ALL DBG module log level to DEFAULT!"); + +} + +WLAN_STATUS wlanSetDebugLevel(IN UINT_32 u4DbgIdx, IN UINT_32 u4DbgMask) +{ + UINT_32 u4Idx; + WLAN_STATUS fgStatus = WLAN_STATUS_SUCCESS; + + if (u4DbgIdx == DBG_ALL_MODULE_IDX) { + for (u4Idx = 0; u4Idx < DBG_MODULE_NUM; u4Idx++) + aucDebugModule[u4Idx] = (UINT_8) u4DbgMask; + LOG_FUNC("Set ALL DBG module log level to [0x%02x]\n", u4DbgMask); + } else if (u4DbgIdx < DBG_MODULE_NUM) { + aucDebugModule[u4DbgIdx] = (UINT_8) u4DbgMask; + LOG_FUNC("Set DBG module[%u] log level to [0x%02x]\n", u4DbgIdx, u4DbgMask); + } else { + fgStatus = WLAN_STATUS_FAILURE; + } + + return fgStatus; +} + +WLAN_STATUS wlanGetDebugLevel(IN UINT_32 u4DbgIdx, OUT PUINT_32 pu4DbgMask) +{ + if (u4DbgIdx < DBG_MODULE_NUM) { + *pu4DbgMask = aucDebugModule[u4DbgIdx]; + return WLAN_STATUS_SUCCESS; + } + + return WLAN_STATUS_FAILURE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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)); + INIT_DELAYED_WORK(&workq, wlanSetMulticastListWorkQueue); + +/* 20150205 work queue for sched_scan */ + INIT_DELAYED_WORK(&sched_workq, wlanSchedScanStoppedWorkQueue); + + return 0; /* success */ +} /* end of wlanInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A function for prDev->uninit +* +* \param[in] prDev Pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static void wlanUninit(struct net_device *prDev) +{ +} /* end of wlanUninit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A function for prDev->open +* +* \param[in] prDev Pointer to struct net_device. +* +* \retval 0 The execution of wlanOpen succeeds. +* \retval < 0 The execution of wlanOpen failed. +*/ +/*----------------------------------------------------------------------------*/ +static int wlanOpen(struct net_device *prDev) +{ + ASSERT(prDev); + + netif_tx_start_all_queues(prDev); + + return 0; /* success */ +} /* end of wlanOpen() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A function for prDev->stop +* +* \param[in] prDev Pointer to struct net_device. +* +* \retval 0 The execution of wlanStop succeeds. +* \retval < 0 The execution of wlanStop failed. +*/ +/*----------------------------------------------------------------------------*/ +static int wlanStop(struct net_device *prDev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + struct cfg80211_scan_request *prScanRequest = NULL; + + 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 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) + if (prScanRequest) { + struct cfg80211_scan_info info = { + .aborted = TRUE, + }; + cfg80211_scan_done(prScanRequest, &info); + } +#else + if (prScanRequest) + cfg80211_scan_done(prScanRequest, TRUE); +#endif + netif_tx_stop_all_queues(prDev); + + return 0; /* success */ +} /* end of wlanStop() */ + +#if CFG_SUPPORT_SNIFFER +static int wlanMonOpen(struct net_device *prDev) +{ + ASSERT(prDev); + + netif_tx_start_all_queues(prDev); + + return 0; /* success */ +} + +static int wlanMonStop(struct net_device *prDev) +{ + ASSERT(prDev); + + netif_tx_stop_all_queues(prDev); + + return 0; /* success */ +} + +static const struct net_device_ops wlan_mon_netdev_ops = { + .ndo_open = wlanMonOpen, + .ndo_stop = wlanMonStop, +}; + +void wlanMonWorkHandler(struct work_struct *work) +{ + P_GLUE_INFO_T prGlueInfo; + + prGlueInfo = container_of(work, GLUE_INFO_T, monWork); + + if (prGlueInfo->fgIsEnableMon) { + if (prGlueInfo->prMonDevHandler) + return; + + prGlueInfo->prMonDevHandler = + alloc_netdev_mq(sizeof(NETDEV_PRIVATE_GLUE_INFO), NIC_MONITOR_INF_NAME, + NET_NAME_PREDICTABLE, ether_setup, CFG_MAX_TXQ_NUM); + + if (prGlueInfo->prMonDevHandler == NULL) { + DBGLOG(INIT, ERROR, "wlanMonWorkHandler: Allocated prMonDevHandler context FAIL.\n"); + return; + } + + ((P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(prGlueInfo->prMonDevHandler))->prGlueInfo = prGlueInfo; + prGlueInfo->prMonDevHandler->type = ARPHRD_IEEE80211_RADIOTAP; + prGlueInfo->prMonDevHandler->netdev_ops = &wlan_mon_netdev_ops; + netif_carrier_off(prGlueInfo->prMonDevHandler); + netif_tx_stop_all_queues(prGlueInfo->prMonDevHandler); + kalResetStats(prGlueInfo->prMonDevHandler); + + if (register_netdev(prGlueInfo->prMonDevHandler) < 0) { + DBGLOG(INIT, ERROR, "wlanMonWorkHandler: Registered prMonDevHandler context FAIL.\n"); + free_netdev(prGlueInfo->prMonDevHandler); + prGlueInfo->prMonDevHandler = NULL; + } + DBGLOG(INIT, INFO, "wlanMonWorkHandler: Registered prMonDevHandler context DONE.\n"); + } else { + if (prGlueInfo->prMonDevHandler) { + unregister_netdev(prGlueInfo->prMonDevHandler); + prGlueInfo->prMonDevHandler = NULL; + DBGLOG(INIT, INFO, "wlanMonWorkHandler: unRegistered prMonDevHandler context DONE.\n"); + } + } +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief when station connect DFS channel, update all DFS channel as NL80211_DFS_USABLE. + * workaround this case: Hotspot can not setup when station connect DFS channel. + * \param[in] prGlueInfo Pointer to glue info + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +INT_32 wlanUpdateDfsChannelTable(P_GLUE_INFO_T prGlueInfo, UINT_8 ucCurrChNo) +{ + UINT_8 i, j; + UINT_8 ucNumOfChannel; + RF_CHANNEL_INFO_T aucChannelList[ARRAY_SIZE(mtk_5ghz_channels)] = { {0} }; + + DBGLOG(INIT, TRACE, "ucCurrChNo %u.\n", ucCurrChNo); + + /* 1. Get current domain DFS channel list */ + rlmDomainGetDfsChnls(prGlueInfo->prAdapter, ARRAY_SIZE(mtk_5ghz_channels), + &ucNumOfChannel, aucChannelList); + + /* 2. Enable specific channel based on domain channel list */ + for (i = 0; i < ucNumOfChannel; i++) { + + for (j = 0; j < ARRAY_SIZE(mtk_5ghz_channels); j++) { + if (mtk_5ghz_channels[j].hw_value == aucChannelList[i].ucChannelNum) { + + if (aucChannelList[i].ucChannelNum == ucCurrChNo) { + + mtk_5ghz_channels[j].dfs_state = NL80211_DFS_AVAILABLE; + mtk_5ghz_channels[j].flags &= ~IEEE80211_CHAN_RADAR; + mtk_5ghz_channels[j].orig_flags &= ~IEEE80211_CHAN_RADAR; + + DBGLOG(INIT, INFO, + "update all dfs channel %u to NL80211_DFS_AVAILABLE by force.\n", + aucChannelList[i].ucChannelNum); + } else { + + mtk_5ghz_channels[j].dfs_state = NL80211_DFS_USABLE; + mtk_5ghz_channels[j].flags |= IEEE80211_CHAN_RADAR; + mtk_5ghz_channels[j].orig_flags |= IEEE80211_CHAN_RADAR; + + DBGLOG(INIT, TRACE, + "update all dfs channel %u to NL80211_DFS_USABLE.\n", + aucChannelList[i].ucChannelNum); + } + break; + } + } + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Update channel table for cfg80211 based on current country domain + * + * \param[in] prGlueInfo Pointer to glue info + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +VOID wlanUpdateChannelTable(P_GLUE_INFO_T prGlueInfo) +{ + UINT_8 i, j; + UINT_8 ucNumOfChannel; + RF_CHANNEL_INFO_T aucChannelList[ARRAY_SIZE(mtk_2ghz_channels) + ARRAY_SIZE(mtk_5ghz_channels)] = { {0} }; + + /* 1. Disable all channels */ + for (i = 0; i < ARRAY_SIZE(mtk_2ghz_channels); i++) { + mtk_2ghz_channels[i].flags |= IEEE80211_CHAN_DISABLED; + mtk_2ghz_channels[i].orig_flags |= IEEE80211_CHAN_DISABLED; + } + + for (i = 0; i < ARRAY_SIZE(mtk_5ghz_channels); i++) { + mtk_5ghz_channels[i].flags |= IEEE80211_CHAN_DISABLED; + mtk_5ghz_channels[i].orig_flags |= IEEE80211_CHAN_DISABLED; + } + + /* 2. Get current domain channel list */ + rlmDomainGetChnlList(prGlueInfo->prAdapter, + BAND_NULL, FALSE, + ARRAY_SIZE(mtk_2ghz_channels) + ARRAY_SIZE(mtk_5ghz_channels), + &ucNumOfChannel, aucChannelList); + + /* 3. Enable specific channel based on domain channel list */ + for (i = 0; i < ucNumOfChannel; i++) { + switch (aucChannelList[i].eBand) { + case BAND_2G4: + for (j = 0; j < ARRAY_SIZE(mtk_2ghz_channels); j++) { + if (mtk_2ghz_channels[j].hw_value == aucChannelList[i].ucChannelNum) { + mtk_2ghz_channels[j].flags &= ~IEEE80211_CHAN_DISABLED; + mtk_2ghz_channels[j].orig_flags &= ~IEEE80211_CHAN_DISABLED; + break; + } + } + break; + + case BAND_5G: + for (j = 0; j < ARRAY_SIZE(mtk_5ghz_channels); j++) { + if (mtk_5ghz_channels[j].hw_value == aucChannelList[i].ucChannelNum) { + mtk_5ghz_channels[j].flags &= ~IEEE80211_CHAN_DISABLED; + mtk_5ghz_channels[j].orig_flags &= ~IEEE80211_CHAN_DISABLED; + mtk_5ghz_channels[j].dfs_state = + (aucChannelList[i].eDFS) ? + NL80211_DFS_USABLE : + NL80211_DFS_UNAVAILABLE; + break; + } + } + break; + + default: + DBGLOG(INIT, WARN, "Unknown band %d\n", aucChannelList[i].eBand); + break; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Register the device to the kernel and return the index. +* +* \param[in] prDev Pointer to struct net_device. +* +* \retval 0 The execution of wlanNetRegister succeeds. +* \retval < 0 The execution of wlanNetRegister failed. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 wlanNetRegister(struct wireless_dev *prWdev) +{ + P_GLUE_INFO_T prGlueInfo; + INT_32 i4DevIdx = -1; + P_NETDEV_PRIVATE_GLUE_INFO prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) NULL; + + ASSERT(prWdev); + + do { + if (!prWdev) + break; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); + i4DevIdx = wlanGetDevIdx(prWdev->netdev); + if (i4DevIdx < 0) { + DBGLOG(INIT, ERROR, "net_device number exceeds!\n"); + break; + } + + if (g_fixedIfindex != 0) { + prWdev->netdev->ifindex = g_fixedIfindex; + DBGLOG(INIT, INFO, "Use assigned ifindex %d.\n", + prWdev->netdev->ifindex); + } + + if (register_netdev(prWdev->netdev) < 0) { + /*if g_fixedIfindex is already in use, re-register..*/ + prWdev->netdev->ifindex = 0; + if (register_netdev(prWdev->netdev) < 0) { + DBGLOG(INIT, ERROR, "Register net_device failed\n"); + wlanClearDevIdx(prWdev->netdev); + i4DevIdx = -1; + } else { + g_fixedIfindex = prWdev->netdev->ifindex; + DBGLOG(INIT, INFO, "Use ifindex as %d from now\n", + g_fixedIfindex); + } + } else { + g_fixedIfindex = prWdev->netdev->ifindex; + DBGLOG(INIT, INFO, "Use ifindex as %d from now\n", + g_fixedIfindex); + } + +#if 1 + prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(prGlueInfo->prDevHandler); + ASSERT(prNetDevPrivate->prGlueInfo == prGlueInfo); + prNetDevPrivate->ucBssIdx = prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + wlanBindBssIdxToNetInterface(prGlueInfo, + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex, (PVOID) prWdev->netdev); +#else + wlanBindBssIdxToNetInterface(prGlueInfo, + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex, (PVOID) prWdev->netdev); + /* wlanBindNetInterface(prGlueInfo, NET_DEV_WLAN_IDX, (PVOID)prWdev->netdev); */ +#endif + if (i4DevIdx != -1) + prGlueInfo->fgIsRegistered = TRUE; + + } while (FALSE); + + return i4DevIdx; /* success */ +} /* end of wlanNetRegister() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Unregister the device from the kernel +* +* \param[in] prWdev Pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID wlanNetUnregister(struct wireless_dev *prWdev) +{ + P_GLUE_INFO_T prGlueInfo; + + if (!prWdev) { + DBGLOG(INIT, ERROR, "wlanNetUnregister: The device context is NULL\n"); + return; + } + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); + + wlanClearDevIdx(prWdev->netdev); + unregister_netdev(prWdev->netdev); + + prGlueInfo->fgIsRegistered = FALSE; + +#if CFG_SUPPORT_SNIFFER + if (prGlueInfo->prMonDevHandler) { + unregister_netdev(prGlueInfo->prMonDevHandler); + prGlueInfo->prMonDevHandler = NULL; + } + prGlueInfo->fgIsEnableMon = FALSE; +#endif + +} /* end of wlanNetUnregister() */ + +static const struct net_device_ops wlan_netdev_ops = { + .ndo_open = wlanOpen, + .ndo_stop = wlanStop, + .ndo_set_rx_mode = wlanSetMulticastList, + .ndo_get_stats = wlanGetStats, + .ndo_do_ioctl = wlanDoIOCTL, + .ndo_start_xmit = wlanHardStartXmit, + .ndo_init = wlanInit, + .ndo_uninit = wlanUninit, + .ndo_select_queue = wlanSelectQueue, + .ndo_set_mac_address = wlanSetMacAddress, +}; + +static UINT_8 wlanNvramBufHandler(PVOID ctx, const CHAR *buf, UINT_16 length) +{ + DBGLOG(INIT, INFO, "buf = %p, length = %u\n", buf, length); + if (buf == NULL || length <= 0 || length != sizeof(g_aucNvram)) + return -EINVAL; + + if (copy_from_user(g_aucNvram, buf, length)) { + DBGLOG(INIT, ERROR, "copy nvram fail\n"); + fgNvramAvailable = FALSE; + return -EINVAL; + } + + fgNvramAvailable = TRUE; + return 0; +} + + +static void createWirelessDevice(void) +{ + struct wiphy *prWiphy = NULL; + struct wireless_dev *prWdev = NULL; + + /* 4 <1.1> Create wireless_dev */ + prWdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (!prWdev) { + DBGLOG(INIT, ERROR, "Allocating memory to wireless_dev context failed\n"); + return; + } + /* 4 <1.2> Create wiphy */ + prWiphy = wiphy_new(&mtk_wlan_ops, sizeof(GLUE_INFO_T)); + if (!prWiphy) { + DBGLOG(INIT, ERROR, "Allocating memory to wiphy device failed\n"); + goto free_wdev; + } + /* 4 <1.3> configure wireless_dev & wiphy */ + prWdev->iftype = NL80211_IFTYPE_STATION; + prWiphy->max_scan_ssids = SCN_SSID_MAX_NUM + 1; /* include one wildcard ssid */ + prWiphy->max_scan_ie_len = 512; +#if CFG_SUPPORT_SCHED_SCN_SSID_SETS + prWiphy->max_sched_scan_ssids = CFG_SCAN_HIDDEN_SSID_MAX_NUM; +#else + prWiphy->max_sched_scan_ssids = CFG_SCAN_SSID_MAX_NUM; +#endif + prWiphy->max_match_sets = CFG_SCAN_SSID_MATCH_MAX_NUM; + prWiphy->max_sched_scan_ie_len = CFG_CFG80211_IE_BUF_LEN; + prWiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); + prWiphy->bands[KAL_BAND_2GHZ] = &mtk_band_2ghz; + /* + * always assign 5Ghz bands here, if the chip is not support 5Ghz, + * bands[NL80211_BAND_5GHZ] will be assign to NULL + */ + prWiphy->bands[KAL_BAND_5GHZ] = &mtk_band_5ghz; + prWiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + prWiphy->cipher_suites = mtk_cipher_suites; + prWiphy->n_cipher_suites = ARRAY_SIZE(mtk_cipher_suites); + + prWiphy->flags = WIPHY_FLAG_SUPPORTS_FW_ROAM + | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; +#if CFG_SUPPORT_AAA + prWiphy->flags |= WIPHY_FLAG_HAVE_AP_SME; +#endif +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) + prWiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; +#else + /*In kernel 4.12 or newer, this obsoletes WIPHY_FLAG_SUPPORTS_SCHED_SCAN*/ + prWiphy->max_sched_scan_reqs = 1; +#endif + prWiphy->regulatory_flags = REGULATORY_CUSTOM_REG; +#if CFG_SUPPORT_TDLS + TDLSEX_WIPHY_FLAGS_INIT(prWiphy->flags); + prWiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | + WIPHY_FLAG_TDLS_EXTERNAL_SETUP | WIPHY_FLAG_SUPPORTS_TDLS; +#endif /* CFG_SUPPORT_TDLS */ +#if (CFG_SUPPORT_SCAN_RANDOM_MAC && \ + (KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE)) + prWiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; + prWiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR; +#endif + prWiphy->features |= NL80211_FEATURE_SAE; + prWiphy->max_remain_on_channel_duration = 5000; + prWiphy->mgmt_stypes = mtk_cfg80211_ais_default_mgmt_stypes; + prWiphy->vendor_commands = mtk_wlan_vendor_ops; + prWiphy->n_vendor_commands = sizeof(mtk_wlan_vendor_ops) / sizeof(struct wiphy_vendor_command); + prWiphy->vendor_events = mtk_wlan_vendor_events; + prWiphy->n_vendor_events = ARRAY_SIZE(mtk_wlan_vendor_events); + + /* 4 <1.4> wowlan support */ +#ifdef CONFIG_PM + prWiphy->wowlan = &mtk_wlan_wowlan_support; +#endif +#ifdef CONFIG_CFG80211_WEXT + /* 4 <1.5> Use wireless extension to replace IOCTL */ + prWiphy->wext = &wext_handler_def; +#endif + + if (wiphy_register(prWiphy) < 0) { + DBGLOG(INIT, ERROR, "wiphy_register error\n"); + goto free_wiphy; + } + register_file_buf_handler(wlanNvramBufHandler, (PVOID)NULL, ENUM_BUF_TYPE_NVRAM); + prWdev->wiphy = prWiphy; + gprWdev = prWdev; + DBGLOG(INIT, INFO, "Create wireless device success\n"); + return; + +free_wiphy: + wiphy_free(prWiphy); +free_wdev: + kfree(prWdev); +} + +static void destroyWirelessDevice(void) +{ + wiphy_unregister(gprWdev->wiphy); + wiphy_free(gprWdev->wiphy); + kfree(gprWdev); + gprWdev = NULL; +} + +VOID wlanWakeLockInit(P_GLUE_INFO_T prGlueInfo) +{ + KAL_WAKE_LOCK_INIT(NULL, &prGlueInfo->rIntrWakeLock, "WLAN interrupt"); + KAL_WAKE_LOCK_INIT(NULL, &prGlueInfo->rTimeoutWakeLock, "WLAN timeout"); +} + +VOID wlanWakeLockUninit(P_GLUE_INFO_T prGlueInfo) +{ + if (KAL_WAKE_LOCK_ACTIVE(NULL, &prGlueInfo->rIntrWakeLock)) + KAL_WAKE_UNLOCK(NULL, &prGlueInfo->rIntrWakeLock); + KAL_WAKE_LOCK_DESTROY(NULL, &prGlueInfo->rIntrWakeLock); + + if (KAL_WAKE_LOCK_ACTIVE(NULL, &prGlueInfo->rTimeoutWakeLock)) + KAL_WAKE_UNLOCK(NULL, &prGlueInfo->rTimeoutWakeLock); + KAL_WAKE_LOCK_DESTROY(NULL, &prGlueInfo->rTimeoutWakeLock); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 = gprWdev; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 i; + struct device *prDev; + P_NETDEV_PRIVATE_GLUE_INFO prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) NULL; + + if (prWdev == NULL) { + DBGLOG(INIT, ERROR, "No wireless dev exist, abort power on\n"); + return NULL; + } + + /* 4 <1.3> co-relate wiphy & prDev */ +#if (MTK_WCN_HIF_SDIO == 1) + mtk_wcn_hif_sdio_get_dev(*((MTK_WCN_HIF_SDIO_CLTCTX *) pvData), &prDev); +#else + prDev = pvData; +#endif + if (!prDev) + DBGLOG(INIT, ERROR, "unable to get struct dev for wlan\n"); + /* + * don't set prDev as parent of wiphy->dev, because we have done device_add + * in driver init. if we set parent here, parent will be not able to know this child, + * and may occurs a KE in device_shutdown, to free wiphy->dev, because his parent + * has been freed. + */ + /*set_wiphy_dev(prWdev->wiphy, prDev); */ + + /* 4 <2> Create Glue structure */ + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); + kalMemZero(prGlueInfo, sizeof(GLUE_INFO_T)); + /* 4 <3> Initialize Glue structure */ + /* 4 <3.1> Create net device */ + prGlueInfo->prDevHandler = alloc_netdev_mq(sizeof(NETDEV_PRIVATE_GLUE_INFO), NIC_INF_NAME, + NET_NAME_PREDICTABLE, ether_setup, CFG_MAX_TXQ_NUM); + if (!prGlueInfo->prDevHandler) { + DBGLOG(INIT, ERROR, "Allocating memory to net_device context failed\n"); + goto netcreate_err; + } + + /* Device can help us to save at most 3000 packets, after we stopped queue */ + prGlueInfo->prDevHandler->tx_queue_len = 3000; + DBGLOG(INIT, INFO, "net_device prDev(0x%p) allocated\n", prGlueInfo->prDevHandler); + + /* 4 <3.1.1> Initialize net device varaiables */ +#if 1 + prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(prGlueInfo->prDevHandler); + prNetDevPrivate->prGlueInfo = prGlueInfo; +#else + *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->prDevHandler)) = prGlueInfo; +#endif + 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); + kalResetStats(prGlueInfo->prDevHandler); + +#if CFG_SUPPORT_SNIFFER + INIT_WORK(&(prGlueInfo->monWork), wlanMonWorkHandler); +#endif + + /* 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, prDev); + + /* 4 <3.2> Initialize Glue variables */ + prGlueInfo->eParamMediaStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; + prGlueInfo->ePowerState = (ENUM_ACPI_STATE_T)ParamDeviceStateD0; + prGlueInfo->fgIsMacAddrOverride = FALSE; + prGlueInfo->fgIsRegistered = FALSE; + prGlueInfo->prScanRequest = NULL; + prGlueInfo->prSchedScanRequest = NULL; + kalMemSet(&prGlueInfo->rScanChannelInfo, 0, sizeof(PARTIAL_SCAN_INFO)); + prGlueInfo->pucScanChannel = NULL; + /* Full2Partial */ + prGlueInfo->u4LastFullScanTime = 0; + + kalMemSet(prGlueInfo->arChannelScanInfo, 0, + sizeof(struct GL_Channel_scan_info) * FULL_SCAN_MAX_CHANNEL_NUM); + + kalMemSet(&prGlueInfo->rFullScanApChannel, 0, sizeof(PARTIAL_SCAN_INFO)); + /* alloc pucFullScan2PartialChannel buffer */ + prGlueInfo->pucFullScan2PartialChannel = NULL; +#if CFG_SUPPORT_ABORT_SCAN + prGlueInfo->u4LastNormalScanTime = 0; + prGlueInfo->ucAbortScanCnt = 0; +#endif + +#if CFG_SUPPORT_PASSPOINT + /* Init DAD */ + prGlueInfo->fgIsDad = FALSE; + prGlueInfo->fgIs6Dad = FALSE; + kalMemZero(prGlueInfo->aucDADipv4, 4); + kalMemZero(prGlueInfo->aucDADipv6, 16); +#endif /* CFG_SUPPORT_PASSPOINT */ + + init_completion(&prGlueInfo->rScanComp); + init_completion(&prGlueInfo->rHaltComp); + init_completion(&prGlueInfo->rPendComp); + +#if CFG_SUPPORT_MULTITHREAD + init_completion(&prGlueInfo->rHifHaltComp); + init_completion(&prGlueInfo->rRxHaltComp); + init_completion(&prGlueInfo->rHalRDMCRComp); + init_completion(&prGlueInfo->rHalWRMCRComp); +#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]); + } + + for (i = 0; i < MUTEX_NUM; i++) + mutex_init(&prGlueInfo->arMutex[i]); + + /* initialize semaphore for ioctl */ + sema_init(&prGlueInfo->ioctl_sem, 1); + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN + /* initialize SDIO read-write pattern control */ + prGlueInfo->fgEnSdioTestPattern = FALSE; + prGlueInfo->fgIsSdioTestInitialized = FALSE; +#endif + + /* 4 <8> Init Queues */ + init_waitqueue_head(&prGlueInfo->waitq); + QUEUE_INITIALIZE(&prGlueInfo->rCmdQueue); + QUEUE_INITIALIZE(&prGlueInfo->rTxQueue); + glSetHifInfo(prGlueInfo, (ULONG) pvData); + + /* main thread is created in this function */ +#if CFG_SUPPORT_MULTITHREAD + init_waitqueue_head(&prGlueInfo->waitq_rx); + init_waitqueue_head(&prGlueInfo->waitq_hif); + + prGlueInfo->u4TxThreadPid = 0xffffffff; + prGlueInfo->u4RxThreadPid = 0xffffffff; + prGlueInfo->u4HifThreadPid = 0xffffffff; +#endif + + /* 4 <4> Create Adapter structure */ + prAdapter = (P_ADAPTER_T) wlanAdapterCreate(prGlueInfo); + + if (!prAdapter) { + DBGLOG(INIT, ERROR, "Allocating memory to adapter failed\n"); + glClearHifInfo(prGlueInfo); + goto netcreate_err; + } + + prGlueInfo->prAdapter = prAdapter; + + goto netcreate_done; + +netcreate_err: + if (prGlueInfo->prDevHandler != NULL) { + free_netdev(prGlueInfo->prDevHandler); + prGlueInfo->prDevHandler = 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); + +} /* end of wlanNetDestroy() */ + +VOID wlanSetSuspendMode(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgEnable) +{ + struct net_device *prDev = NULL; + UINT_32 u4PacketFilter = 0; + UINT_32 u4SetInfoLen = 0; + + if (!prGlueInfo) + return; + +#if CFG_ROAMING_CTRL_BY_SUSPEND + { + UINT_32 u4SetInfoLen = 0; + + kalIoctl(prGlueInfo, wlanoidSetRoamingCtrl, &fgEnable, sizeof(fgEnable), + FALSE, FALSE, TRUE, &u4SetInfoLen); + } +#endif + prDev = prGlueInfo->prDevHandler; + if (!prDev) + return; + + /* new filter should not include p2p mask */ + u4PacketFilter = prGlueInfo->prAdapter->u4OsPacketFilter & (~PARAM_PACKET_FILTER_P2P_MASK); + + if (kalIoctl(prGlueInfo, + wlanoidSetCurrentPacketFilter, + &u4PacketFilter, + sizeof(u4PacketFilter), FALSE, FALSE, TRUE, &u4SetInfoLen) != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, ERROR, "set packet filter failed.\n"); + +#if !CFG_SUPPORT_DROP_ALL_MC_PACKET + if (u4PacketFilter & PARAM_PACKET_FILTER_MULTICAST) { + if (fgEnable) { + /* Prepare IPv6 RA packet when suspend */ + UINT_8 MC_address[ETH_ALEN] = {0x33, 0x33, 0, 0, 0, 1}; + + kalIoctl(prGlueInfo, + wlanoidSetMulticastList, MC_address, ETH_ALEN, FALSE, FALSE, TRUE, &u4SetInfoLen); + } else { + /* Prepare multicast address list when resume */ + struct netdev_hw_addr *ha; + PUINT_8 prMCAddrList = NULL; + UINT_32 i = 0; + + if (kalHaltLock(KAL_HALT_LOCK_TIMEOUT_NORMAL_CASE)) + return; + + if (kalIsHalted()) { + kalHaltUnlock(); + return; + } + + prMCAddrList = kalMemAlloc(MAX_NUM_GROUP_ADDR * ETH_ALEN, VIR_MEM_TYPE); + if (!prMCAddrList) { + DBGLOG(INIT, ERROR, "allocate prMCAddrList failed\n"); + kalHaltUnlock(); + return; + } + netdev_for_each_mc_addr(ha, prDev) { + if (i < MAX_NUM_GROUP_ADDR) { + kalMemCopy((prMCAddrList + i * ETH_ALEN), ha->addr, ETH_ALEN); + i++; + } + } + + kalHaltUnlock(); + + kalIoctl(prGlueInfo, wlanoidSetMulticastList, + prMCAddrList, (i * ETH_ALEN), FALSE, FALSE, TRUE, &u4SetInfoLen); + + kalMemFree(prMCAddrList, VIR_MEM_TYPE, MAX_NUM_GROUP_ADDR * ETH_ALEN); + } + } +#endif + kalSetNetAddressFromInterface(prGlueInfo, prDev, fgEnable); +} + +BOOLEAN wlanIsFwOwn(VOID) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + if (gprWdev) + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(gprWdev->wiphy); + + if (!prGlueInfo || !prGlueInfo->prAdapter) + return TRUE; + + return prGlueInfo->prAdapter->fgIsFwOwn; +} + +#if CFG_ENABLE_EARLY_SUSPEND +static struct early_suspend wlan_early_suspend_desc = { + .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN, +}; + +static void wlan_early_suspend(struct early_suspend *h) +{ + struct net_device *prDev = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + + /* 4 <1> Sanity Check */ + if ((u4WlanDevNum == 0) && (u4WlanDevNum > CFG_MAX_WLAN_DEVICES)) { + DBGLOG(INIT, ERROR, "wlanLateResume u4WlanDevNum==0 invalid!!\n"); + return; + } + + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + if (!prDev) + return; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + if (!prGlueInfo) + return; + + DBGLOG(INIT, INFO, "********<%s>********\n", __func__); + + if (prGlueInfo->fgIsInSuspendMode == TRUE) { + DBGLOG(INIT, INFO, "%s: Already in suspend mode, SKIP!\n", __func__); + return; + } + + prGlueInfo->fgIsInSuspendMode = TRUE; + + wlanSetSuspendMode(prGlueInfo, TRUE); + p2pSetSuspendMode(prGlueInfo, TRUE); +} + +static void wlan_late_resume(struct early_suspend *h) +{ + struct net_device *prDev = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + + /* 4 <1> Sanity Check */ + if ((u4WlanDevNum == 0) && (u4WlanDevNum > CFG_MAX_WLAN_DEVICES)) { + DBGLOG(INIT, ERROR, "wlanLateResume u4WlanDevNum==0 invalid!!\n"); + return; + } + + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + if (!prDev) + return; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + if (!prGlueInfo) + return; + + DBGLOG(INIT, INFO, "********<%s>********\n", __func__); + + if (prGlueInfo->fgIsInSuspendMode == FALSE) { + DBGLOG(INIT, INFO, "%s: Not in suspend mode, SKIP!\n", __func__); + return; + } + + prGlueInfo->fgIsInSuspendMode = FALSE; + + /* 4 <2> Set suspend mode for each network */ + wlanSetSuspendMode(prGlueInfo, FALSE); + p2pSetSuspendMode(prGlueInfo, FALSE); +} +#endif + +VOID nicConfigProcSetCamCfgWrite(BOOLEAN enabled) +{ + struct net_device *prDev = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + PARAM_POWER_MODE ePowerMode = Param_PowerModeFast_PSP; + UINT_8 ucBssIndex; + CMD_PS_PROFILE_T rPowerSaveMode; + + /* 4 <1> Sanity Check */ + if (!u4WlanDevNum || (u4WlanDevNum > CFG_MAX_WLAN_DEVICES)) { + DBGLOG(INIT, ERROR, "u4WlanDevNum %u is invalid!!\n", u4WlanDevNum); + return; + } + + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + if (!prDev) + return; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + if (!prGlueInfo) + return; + + prAdapter = prGlueInfo->prAdapter; + if ((!prAdapter) || (!prAdapter->prAisBssInfo)) + return; + + ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + if (ucBssIndex >= BSS_INFO_NUM) + return; + rPowerSaveMode.ucBssIndex = ucBssIndex; + + if (enabled) { + prAdapter->rWlanInfo.fgEnSpecPwrMgt = TRUE; + ePowerMode = Param_PowerModeCAM; + rPowerSaveMode.ucPsProfile = (UINT_8) ePowerMode; + DBGLOG(INIT, INFO, "Enable CAM BssIndex:%d, PowerMode:%d\n", + ucBssIndex, rPowerSaveMode.ucPsProfile); + } else { + prAdapter->rWlanInfo.fgEnSpecPwrMgt = FALSE; + rPowerSaveMode.ucPsProfile = + prAdapter->rWlanInfo.arPowerSaveMode[ucBssIndex].ucPsProfile; + DBGLOG(INIT, INFO, "Disable CAM BssIndex:%d, PowerMode:%d\n", + ucBssIndex, rPowerSaveMode.ucPsProfile); + } + + nicPowerSaveInfoMap(prAdapter, rPowerSaveMode.ucBssIndex, ePowerMode, PS_CALLER_CAMCFG); + + nicConfigPowerSaveProfile(prAdapter, rPowerSaveMode.ucBssIndex, ePowerMode, FALSE); +} + +void reset_p2p_mode(P_GLUE_INFO_T prGlueInfo) +{ + PARAM_CUSTOM_P2P_SET_STRUCT_T rSetP2P; + UINT_32 rWlanStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + if (!prGlueInfo) + return; + + rSetP2P.u4Enable = 0; + rSetP2P.u4Mode = 0; + + p2pNetUnregister(prGlueInfo, FALSE); + + rWlanStatus = kalIoctl(prGlueInfo, wlanoidSetP2pMode, (PVOID)&rSetP2P, + sizeof(PARAM_CUSTOM_P2P_SET_STRUCT_T), FALSE, FALSE, TRUE, &u4BufLen); + + if (rWlanStatus != WLAN_STATUS_SUCCESS) + prGlueInfo->prAdapter->fgIsP2PRegistered = FALSE; + + DBGLOG(INIT, INFO, + "ret = 0x%08x\n", (UINT_32) rWlanStatus); +} + +int set_p2p_mode_handler(struct net_device *netdev, PARAM_CUSTOM_P2P_SET_STRUCT_T p2pmode) +{ + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(netdev)); + PARAM_CUSTOM_P2P_SET_STRUCT_T rSetP2P; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + /* Resetting p2p mode if registered to avoid launch KE */ + if (p2pmode.u4Enable + && prGlueInfo->prAdapter->fgIsP2PRegistered + && !kalIsResetting()) { + DBGLOG(INIT, INFO, "Resetting p2p mode\n"); + reset_p2p_mode(prGlueInfo); + } + + rSetP2P.u4Enable = p2pmode.u4Enable; + rSetP2P.u4Mode = p2pmode.u4Mode; + + if ((!rSetP2P.u4Enable) && !kalIsResetting()) + p2pNetUnregister(prGlueInfo, FALSE); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetP2pMode, + &rSetP2P, sizeof(PARAM_CUSTOM_P2P_SET_STRUCT_T), FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "kalIoctl failed: 0x%08x\n", rStatus); + return -1; + } + + if ((rSetP2P.u4Enable) && !kalIsResetting()) + p2pNetRegister(prGlueInfo, FALSE); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Wlan probe function. This function probes and initializes the device. +* +* \param[in] pvData data passed by bus driver init function +* _HIF_EHPI: NULL +* _HIF_SDIO: sdio bus driver handle +* +* \retval 0 Success +* \retval negative value Failed +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 wlanProbe(PVOID pvData) +{ + struct wireless_dev *prWdev = NULL; + enum ENUM_PROBE_FAIL_REASON { + BUS_INIT_FAIL, + NET_CREATE_FAIL, + BUS_SET_IRQ_FAIL, + ADAPTER_START_FAIL, + NET_REGISTER_FAIL, + PROC_INIT_FAIL, + FAIL_MET_INIT_PROCFS, + FAIL_REASON_NUM + } eFailReason; + P_WLANDEV_INFO_T prWlandevInfo = NULL; + INT_32 i4DevIdx = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + INT_32 i4Status = 0; + BOOL bRet = FALSE; + UINT_32 u4LogLevel = ENUM_WIFI_LOG_LEVEL_OFF; + + eFailReason = FAIL_REASON_NUM; + do { + /* 4 <1> Initialize the IO port of the interface */ + /* GeorgeKuo: pData has different meaning for _HIF_XXX: + * _HIF_EHPI: pointer to memory base variable, which will be + * initialized by glBusInit(). + * _HIF_SDIO: bus driver handle + */ + kalTakeVcoreAction(VCORE_CLEAR_ALL_REQ); + bRet = glBusInit(pvData); + wlanDebugTC4AndPktInit(); + + /* Cannot get IO address from interface */ + if (bRet == FALSE) { + DBGLOG(INIT, ERROR, "wlanProbe: glBusInit() fail\n"); + i4Status = -EIO; + eFailReason = BUS_INIT_FAIL; + break; + } + /* 4 <2> Create network device, Adapter, KalInfo, prDevHandler(netdev) */ + prWdev = wlanNetCreate(pvData); + if (prWdev == NULL) { + DBGLOG(INIT, ERROR, "wlanProbe: No memory for dev and its private\n"); + i4Status = -ENOMEM; + eFailReason = NET_CREATE_FAIL; + break; + } + /* 4 <2.5> Set the ioaddr to HIF Info */ + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); + gPrDev = prGlueInfo->prDevHandler; + + /* prGlueInfo->main_thread = kthread_run(tx_thread, prGlueInfo->prDevHandler, "tx_thread"); */ + + /* 4 <4> Setup IRQ */ + prWlandevInfo = &arWlanDevInfo[i4DevIdx]; + + /* Init wakelock */ + wlanWakeLockInit(prGlueInfo); + + i4Status = glBusSetIrq(prWdev->netdev, NULL, prGlueInfo); + + if (i4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "wlanProbe: Set IRQ error\n"); + eFailReason = BUS_SET_IRQ_FAIL; + break; + } + + prGlueInfo->i4DevIdx = i4DevIdx; + + prAdapter = prGlueInfo->prAdapter; + + prGlueInfo->u4ReadyFlag = 0; + + update_driver_loaded_status(prGlueInfo->u4ReadyFlag); + prGlueInfo->u4FWRoamingEnable = 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 + + prAdapter->fgIsReadRevID = FALSE; + +#if CFG_SUPPORT_CFG_FILE + wlanCfgInit(prAdapter, NULL, 0, 0); +#ifdef ENABLED_IN_ENGUSERDEBUG + { + PUINT_8 pucConfigBuf; + UINT_32 u4ConfigReadLen; + + pucConfigBuf = (PUINT_8) kalMemAlloc(WLAN_CFG_FILE_BUF_SIZE, VIR_MEM_TYPE); + u4ConfigReadLen = 0; + kalMemZero(pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE); + if (pucConfigBuf) { + if (kalReadToFile("/storage/sdcard0/wifi.cfg", pucConfigBuf, + WLAN_CFG_FILE_BUF_SIZE, &u4ConfigReadLen) == 0) + ; + else + kalReadToFile("/data/misc/wifi/wifi.cfg", pucConfigBuf, + WLAN_CFG_FILE_BUF_SIZE, &u4ConfigReadLen); + + if (pucConfigBuf[0] != '\0' && u4ConfigReadLen > 0) + wlanCfgInit(prAdapter, pucConfigBuf, u4ConfigReadLen, 0); + kalMemFree(pucConfigBuf, VIR_MEM_TYPE, WLAN_CFG_FILE_BUF_SIZE); + } /* pucConfigBuf */ + } +#endif +#endif + /* Load NVRAM content to REG_INFO_T */ + kalMemZero(&prGlueInfo->rRegInfo, sizeof(REG_INFO_T)); + + glLoadNvram(prGlueInfo, &prGlueInfo->rRegInfo); + + /* kalMemCopy(&prGlueInfo->rRegInfo, prRegInfo, sizeof(REG_INFO_T)); */ + + prGlueInfo->rRegInfo.u4PowerMode = CFG_INIT_POWER_SAVE_PROF; + prGlueInfo->rRegInfo.fgEnArpFilter = TRUE; + + /* Trigger the action of switching power state to DRV_OWN */ + nicpmCheckAndTriggerDriverOwn(prAdapter); + + /* 4 <5> Start Device */ + if (wlanAdapterStart(prAdapter, &prGlueInfo->rRegInfo) != WLAN_STATUS_SUCCESS) { + i4Status = -EIO; + eFailReason = ADAPTER_START_FAIL; + break; + } + + prGlueInfo->main_thread = kthread_run(tx_thread, prGlueInfo->prDevHandler, "tx_thread"); +#if CFG_SUPPORT_MULTITHREAD + prGlueInfo->hif_thread = kthread_run(hif_thread, prGlueInfo->prDevHandler, "hif_thread"); + prGlueInfo->rx_thread = kthread_run(rx_thread, prGlueInfo->prDevHandler, "rx_thread"); +#endif + + /* TODO the change schedule API shall be provided by OS glue layer */ + /* Switch the Wi-Fi task priority to higher priority and change the scheduling method */ + if (prGlueInfo->prAdapter->rWifiVar.ucThreadPriority > 0) { + struct sched_param param = {.sched_priority = prGlueInfo->prAdapter->rWifiVar.ucThreadPriority + }; + sched_setscheduler(prGlueInfo->main_thread, + prGlueInfo->prAdapter->rWifiVar.ucThreadScheduling, ¶m); +#if CFG_SUPPORT_MULTITHREAD + sched_setscheduler(prGlueInfo->hif_thread, + prGlueInfo->prAdapter->rWifiVar.ucThreadScheduling, ¶m); + sched_setscheduler(prGlueInfo->rx_thread, + prGlueInfo->prAdapter->rWifiVar.ucThreadScheduling, ¶m); +#endif + DBGLOG(INIT, INFO, + "Set pri = %d, sched = %d\n", + prGlueInfo->prAdapter->rWifiVar.ucThreadPriority, + prGlueInfo->prAdapter->rWifiVar.ucThreadScheduling); + } + + if (prAdapter->fgEnable5GBand == FALSE) + prWdev->wiphy->bands[KAL_BAND_5GHZ] = NULL; + else + prWdev->wiphy->bands[KAL_BAND_5GHZ] = &mtk_band_5ghz; + + kalSetHalted(FALSE); + /* 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, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, WARN, "set MAC addr fail 0x%x\n", rStatus); + prGlueInfo->u4ReadyFlag = 0; + } else { + ether_addr_copy(prGlueInfo->prDevHandler->dev_addr, MacAddr.sa_data); + ether_addr_copy(prGlueInfo->prDevHandler->perm_addr, + prGlueInfo->prDevHandler->dev_addr); + + /* card is ready */ + prGlueInfo->u4ReadyFlag = 1; + update_driver_loaded_status(prGlueInfo->u4ReadyFlag); +#if CFG_SHOW_MACADDR_SOURCE + DBGLOG(INIT, INFO, "MAC address: " MACSTR, MAC2STR(MacAddr.sa_data)); +#endif + } + } + +#ifdef FW_CFG_SUPPORT + { + if (wlanFwArrayCfg(prAdapter) != WLAN_STATUS_FAILURE) + DBGLOG(INIT, TRACE, "FW Array Cfg done!"); + } +#ifdef ENABLED_IN_ENGUSERDEBUG + { + if (wlanFwFileCfg(prAdapter) != WLAN_STATUS_FAILURE) + DBGLOG(INIT, TRACE, "FW File Cfg done!"); + } +#endif +#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, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, WARN, "set HW checksum offload fail 0x%x\n", rStatus); + } +#endif +#if CFG_SUPPORT_802_11K + { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_32 u4SetInfoLen = 0; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSync11kCapabilities, + NULL, + 0, FALSE, FALSE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, WARN, "set 11k Capabilities fail 0x%x\n", rStatus); + } +#endif + + /* 4 <3> Register the card */ + i4DevIdx = wlanNetRegister(prWdev); + if (i4DevIdx < 0) { + i4Status = -ENXIO; + DBGLOG(INIT, ERROR, "wlanProbe: Cannot register the net_device context to the kernel\n"); + eFailReason = NET_REGISTER_FAIL; + break; + } + /* 4 <4> Register early suspend callback */ +#if CFG_ENABLE_EARLY_SUSPEND + glRegisterEarlySuspend(&wlan_early_suspend_desc, wlan_early_suspend, wlan_late_resume); +#endif + + /* 4 <5> Register Notifier callback */ + wlanRegisterNotifier(); + + /* 4 <6> Initialize /proc filesystem */ +#ifdef WLAN_INCLUDE_PROC + i4Status = procCreateFsEntry(prGlueInfo); + if (i4Status < 0) { + DBGLOG(INIT, ERROR, "wlanProbe: init procfs failed\n"); + eFailReason = PROC_INIT_FAIL; + break; + } +#endif /* WLAN_INCLUDE_PROC */ + +#ifdef FW_CFG_SUPPORT + i4Status = cfgCreateProcEntry(prGlueInfo); + if (i4Status < 0) { + DBGLOG(INIT, ERROR, "fw cfg proc failed\n"); + break; + } +#endif /* WLAN_INCLUDE_PROC */ + +#if CFG_MET_PACKET_TRACE_SUPPORT + kalMetInit(prGlueInfo); +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + prGlueInfo->rBowInfo.fgIsNetRegistered = FALSE; + prGlueInfo->rBowInfo.fgIsRegistered = FALSE; + glRegisterAmpc(prGlueInfo); +#endif + +#if (CFG_ENABLE_WIFI_DIRECT) + register_set_p2p_mode_handler(set_p2p_mode_handler); +#endif + +#if (CFG_MET_PACKET_TRACE_SUPPORT == 1) + DBGLOG(INIT, TRACE, "init MET procfs...\n"); + i4Status = kalMetInitProcfs(prGlueInfo); + if (i4Status < 0) { + DBGLOG(INIT, ERROR, "wlanProbe: init MET procfs failed\n"); + eFailReason = FAIL_MET_INIT_PROCFS; + break; + } +#endif + kalMemZero(&prGlueInfo->rFtIeForTx, sizeof(prGlueInfo->rFtIeForTx)); + } while (FALSE); + + if (i4Status == WLAN_STATUS_SUCCESS) { + wlanCfgSetSwCtrl(prGlueInfo->prAdapter); + wlanCfgSetChip(prGlueInfo->prAdapter); + wlanGetFwInfo(prGlueInfo->prAdapter); + wlanCfgSetCountryCode(prGlueInfo->prAdapter); + /* Init performance monitor structure */ + kalPerMonInit(prGlueInfo); +#if CFG_SUPPORT_AGPS_ASSIST + kalIndicateAgpsNotify(prAdapter, AGPS_EVENT_WLAN_ON, NULL, 0); +#endif + prAdapter->u4QmRxBaMissTimeout = DEFAULT_QM_RX_BA_ENTRY_MISS_TIMEOUT_MS; + prAdapter->fgEnCfg80211Scan = TRUE; + DBGLOG(INIT, TRACE, "wlanProbe success\n"); + prAdapter->u4QmRxBaMissTimeout = DEFAULT_QM_RX_BA_ENTRY_MISS_TIMEOUT_MS; + prAdapter->fgEnCfg80211Scan = TRUE; + wlanDbgGetGlobalLogLevel(ENUM_WIFI_LOG_MODULE_FW, &u4LogLevel); + if (u4LogLevel > ENUM_WIFI_LOG_LEVEL_OFF) + wlanDbgSetLogLevelImpl(prAdapter, + ENUM_WIFI_LOG_LEVEL_VERSION_V1, + ENUM_WIFI_LOG_MODULE_FW, + u4LogLevel); +#if CFG_SUPPORT_MGMT_FRAME_DEBUG + wlanMgmtFrameDebugInit(); +#endif + } else { + switch (eFailReason) { + case FAIL_MET_INIT_PROCFS: + kalMetRemoveProcfs(); + /* Fall through */ + case PROC_INIT_FAIL: + wlanNetUnregister(prWdev); + /* Fall through */ + case NET_REGISTER_FAIL: + set_bit(GLUE_FLAG_HALT_BIT, &prGlueInfo->ulFlag); + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + /* wait main thread stops */ + wait_for_completion_interruptible(&prGlueInfo->rHaltComp); + wlanAdapterStop(prAdapter); + /* Fall through */ + case ADAPTER_START_FAIL: + glBusFreeIrq(prWdev->netdev, *((P_GLUE_INFO_T *) netdev_priv(prWdev->netdev))); + /* Fall through */ + case BUS_SET_IRQ_FAIL: + wlanWakeLockUninit(prGlueInfo); + wlanNetDestroy(prWdev); + break; + case NET_CREATE_FAIL: + /* Fall through */ + case BUS_INIT_FAIL: + /* Fall through */ + default: + break; + } + + DBGLOG(INIT, ERROR, "wlanProbe failed\n"); + } + + return i4Status; +} /* end of wlanProbe() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A method to stop driver operation and release all resources. Following +* this call, no frame should go up or down through this interface. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID wlanRemove(VOID) +{ +#define KAL_WLAN_REMOVE_TIMEOUT_MSEC 3000 + struct net_device *prDev = NULL; + P_WLANDEV_INFO_T prWlandevInfo = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + + DBGLOG(INIT, INFO, "Remove wlan!\n"); + + kalTakeVcoreAction(VCORE_CLEAR_ALL_REQ); + /* 4 <0> Sanity check */ + ASSERT(u4WlanDevNum <= CFG_MAX_WLAN_DEVICES); + if (u4WlanDevNum == 0) { + DBGLOG(INIT, ERROR, "u4WlanDevNum = 0\n"); + return; + } +#if (CFG_ENABLE_WIFI_DIRECT) + register_set_p2p_mode_handler(NULL); +#endif + + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + prWlandevInfo = &arWlanDevInfo[u4WlanDevNum - 1]; + + ASSERT(prDev); + if (prDev == NULL) { + DBGLOG(INIT, ERROR, "prDev is NULL\n"); + return; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + if (prGlueInfo == NULL) { + DBGLOG(INIT, ERROR, "prGlueInfo is NULL\n"); + free_netdev(prDev); + return; + } +#ifdef FW_CFG_SUPPORT + cfgRemoveProcEntry(); +#endif +#ifdef WLAN_INCLUDE_PROC + procRemoveProcfs(); +#endif /* WLAN_INCLUDE_PROC */ + + kalPerMonDestroy(prGlueInfo); + + /* complete possible pending oid, which may block wlanRemove some time and then whole chip reset may failed */ + if (kalIsResetting()) + wlanReleasePendingOid(prGlueInfo->prAdapter, 1); + +#if CFG_ENABLE_BT_OVER_WIFI + if (prGlueInfo->rBowInfo.fgIsNetRegistered) { + bowNotifyAllLinkDisconnected(prGlueInfo->prAdapter); + /* wait 300ms for BoW module to send deauth */ + kalMsleep(300); + } +#endif + + flush_delayed_work(&workq); + +/* 20150205 work queue for sched_scan */ + + flush_delayed_work(&sched_workq); + + if (kalHaltLock(KAL_WLAN_REMOVE_TIMEOUT_MSEC) == -ETIME) { + DBGLOG(INIT, ERROR, "Halt Lock, need OidComplete.\n"); + kalOidComplete(prGlueInfo, FALSE, 0, WLAN_STATUS_NOT_ACCEPTED); + } + kalSetHalted(TRUE); + + /* 4 <2> Mark HALT, notify main thread to stop, and clean up queued requests */ + set_bit(GLUE_FLAG_HALT_BIT, &prGlueInfo->ulFlag); + +#if CFG_SUPPORT_MULTITHREAD + wake_up_interruptible(&prGlueInfo->waitq_hif); + if (!wait_for_completion_timeout(&prGlueInfo->rHifHaltComp, MSEC_TO_JIFFIES(KAL_WLAN_REMOVE_TIMEOUT_MSEC))) { + DBGLOG(INIT, ERROR, "wait hif_thread exit timeout, longer than 3s, show backtrace of hif_thread\n"); +#ifndef MTK_WCN_BUILT_IN_DRIVER + KERNEL_show_stack(prGlueInfo->hif_thread, NULL); +#else + show_stack(prGlueInfo->hif_thread, NULL); +#endif + } + wake_up_interruptible(&prGlueInfo->waitq_rx); + if (!wait_for_completion_timeout(&prGlueInfo->rRxHaltComp, MSEC_TO_JIFFIES(KAL_WLAN_REMOVE_TIMEOUT_MSEC))) { + DBGLOG(INIT, ERROR, "wait rx_thread exit timeout, longer than 3s, show backtrace of rx_thread\n"); +#ifndef MTK_WCN_BUILT_IN_DRIVER + KERNEL_show_stack(prGlueInfo->rx_thread, NULL); +#else + show_stack(prGlueInfo->rx_thread, NULL); +#endif + } +#endif + + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + /* wait main thread stops */ + if (!wait_for_completion_timeout(&prGlueInfo->rHaltComp, MSEC_TO_JIFFIES(KAL_WLAN_REMOVE_TIMEOUT_MSEC))) { + DBGLOG(INIT, ERROR, "wait tx_thread exit timeout, longer than 3s, show backtrace of tx_thread\n"); +#ifndef MTK_WCN_BUILT_IN_DRIVER + KERNEL_show_stack(prGlueInfo->main_thread, NULL); +#else + show_stack(prGlueInfo->main_thread, NULL); +#endif + } + + DBGLOG(INIT, INFO, "wlan thread stopped\n"); + + /* prGlueInfo->rHifInfo.main_thread = NULL; */ + prGlueInfo->main_thread = NULL; +#if CFG_SUPPORT_MULTITHREAD + prGlueInfo->hif_thread = NULL; + prGlueInfo->rx_thread = NULL; + + prGlueInfo->u4TxThreadPid = 0xffffffff; + prGlueInfo->u4HifThreadPid = 0xffffffff; +#endif + + /* Destroy wakelock */ + wlanWakeLockUninit(prGlueInfo); + + kalMemSet(&(prGlueInfo->prAdapter->rWlanInfo), 0, sizeof(WLAN_INFO_T)); + +#if CFG_ENABLE_WIFI_DIRECT + if (prGlueInfo->prAdapter->fgIsP2PRegistered) { + DBGLOG(INIT, TRACE, "p2pNetUnregister...\n"); + p2pNetUnregister(prGlueInfo, FALSE); + DBGLOG(INIT, TRACE, "p2pRemove...\n"); + /*p2pRemove must before wlanAdapterStop */ + p2pRemove(prGlueInfo); + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + if (prGlueInfo->rBowInfo.fgIsRegistered) + glUnregisterAmpc(prGlueInfo); +#endif + +#if (CFG_MET_PACKET_TRACE_SUPPORT == 1) + kalMetRemoveProcfs(); +#endif + /* 4 <4> wlanAdapterStop */ + prAdapter = prGlueInfo->prAdapter; +#if CFG_SUPPORT_AGPS_ASSIST + kalIndicateAgpsNotify(prAdapter, AGPS_EVENT_WLAN_OFF, NULL, 0); +#endif + + wlanAdapterStop(prAdapter); + DBGLOG(INIT, TRACE, "Number of Stalled Packets = %d\n", GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum)); + + /* 4 Stopping handling interrupt and free IRQ */ + glBusFreeIrq(prDev, prGlueInfo); + + /* 4 <5> Release the Bus */ + glBusRelease(prDev); + + kalHaltUnlock(); + wlanDebugTC4AndPktUninit(); +#if CFG_SUPPORT_MGMT_FRAME_DEBUG + wlanMgmtFrameDebugUnInit(); +#endif + /* 4 <6> Unregister the card */ + wlanNetUnregister(prDev->ieee80211_ptr); + + /* 4 <7> Destroy the device */ + wlanNetDestroy(prDev->ieee80211_ptr); + prDev = NULL; + + /* 4 <8> Unregister early suspend callback */ +#if CFG_ENABLE_EARLY_SUSPEND + glUnregisterEarlySuspend(&wlan_early_suspend_desc); +#endif + gprWdev->netdev = NULL; + + /* 4 <9> Unregister notifier callback */ + wlanUnregisterNotifier(); + update_driver_loaded_status(0); +} /* end of wlanRemove() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Driver entry point when the driver is configured as a Linux Module, and +* is called once at module load time, by the user-level modutils +* application: insmod or modprobe. +* +* \retval 0 Success +*/ +/*----------------------------------------------------------------------------*/ +/* 1 Module Entry Point */ +static int initWlan(void) +{ + int ret = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + + DBGLOG(INIT, INFO, "initWlan\n"); + g_fixedIfindex = 0; + + wlanDebugInit(); + fgNvramAvailable = FALSE; + /* memory pre-allocation */ + kalInitIOBuffer(); + procInitFs(); + + createWirelessDevice(); + if (gprWdev) + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(gprWdev->wiphy); + + if (!prGlueInfo) + return -1; + + glP2pCreateWirelessDevice(prGlueInfo); + + ret = ((glRegisterBus(wlanProbe, wlanRemove) == WLAN_STATUS_SUCCESS) ? 0 : -EIO); + + if (ret == -EIO) { + kalUninitIOBuffer(); + return ret; + } +#if (CFG_CHIP_RESET_SUPPORT) + glResetInit(); +#endif + + kalFbNotifierReg(prGlueInfo); +#if CFG_MODIFY_TX_POWER_BY_BAT_VOLT + kalBatNotifierReg(prGlueInfo); +#endif + +#if defined(MT6631) + /* Set WIFI EMI protection to consys permitted on system boot up */ + kalSetEmiMpuProtection(gConEmiPhyBase, WIFI_EMI_MEM_SIZE, TRUE); +#endif + kalVcoreInitUninit(TRUE); + return ret; +} /* end of initWlan() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Driver exit point when the driver as a Linux Module is removed. Called +* at module unload time, by the user level modutils application: rmmod. +* This is our last chance to clean up after ourselves. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +/* 1 Module Leave Point */ +static VOID exitWlan(void) +{ + + kalFbNotifierUnReg(); +#if CFG_MODIFY_TX_POWER_BY_BAT_VOLT + kalBatNotifierUnReg(); +#endif +#if CFG_CHIP_RESET_SUPPORT + glResetUninit(); +#endif + + glUnregisterBus(wlanRemove); + + /* free pre-allocated memory */ + kalUninitIOBuffer(); + destroyWirelessDevice(); + glP2pDestroyWirelessDevice(); + procUninitProcFs(); + kalVcoreInitUninit(FALSE); + + DBGLOG(INIT, INFO, "exitWlan\n"); + +} /* end of exitWlan() */ + +#ifdef MTK_WCN_BUILT_IN_DRIVER + +int mtk_wcn_wlan_gen3_init(void) +{ + return initWlan(); +} +EXPORT_SYMBOL(mtk_wcn_wlan_gen3_init); + +void mtk_wcn_wlan_gen3_exit(void) +{ + return exitWlan(); +} +EXPORT_SYMBOL(mtk_wcn_wlan_gen3_exit); + +#else + +module_init(initWlan); +module_exit(exitWlan); + +#endif + +MODULE_AUTHOR(NIC_AUTHOR); +MODULE_DESCRIPTION(NIC_DESC); +MODULE_SUPPORTED_DEVICE(NIC_NAME); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_kal.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_kal.c new file mode 100644 index 0000000000000..e7a390790cd29 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_kal.c @@ -0,0 +1,6032 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_kal.c#10 + */ + +/* + * ! \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. + */ + +/******************************************************************************* + * C O M P I L E 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 "gl_wext.h" +#include "precomp.h" +#include "gl_rst.h" +#if CFG_SUPPORT_AGPS_ASSIST +#include +#endif +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG +#include +#endif + +#ifndef MTK_WCN_BUILT_IN_DRIVER +#include "connectivity_build_in_adapter.h" +#endif + +#if defined(CONFIG_MTK_QOS_SUPPORT) +#include +#include +#endif + +#ifdef FW_CFG_SUPPORT +#ifdef CFG_SUPPORT_COEX_IOT_AP +#include "fwcfg.h" +#endif +#endif +#if CFG_MODIFY_TX_POWER_BY_BAT_VOLT +#include "pmic_lbat_service.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 + ******************************************************************************** + */ +#if DBG +int allocatedMemSize; +#endif + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static PVOID pvIoBuffer; +static UINT_32 pvIoBufferSize; +static UINT_32 pvIoBufferUsage; +static struct KAL_HALT_CTRL_T rHaltCtrl = { + .lock = __SEMAPHORE_INITIALIZER(rHaltCtrl.lock, 1), + .owner = NULL, + .fgHalt = TRUE, + .fgHeldByKalIoctl = FALSE, + .u4HoldStart = 0, +}; + +/* framebuffer callback related variable and status flag */ +static struct notifier_block wlan_fb_notifier; +void *wlan_fb_notifier_priv_data; +BOOLEAN wlan_fb_power_down = FALSE; +#if CFG_MODIFY_TX_POWER_BY_BAT_VOLT +void *wlan_bat_volt_notifier_priv_data; +unsigned int wlan_bat_volt; +#endif + +#if CFG_FORCE_ENABLE_PERF_MONITOR +BOOLEAN wlan_perf_monitor_force_enable = TRUE; +#else +BOOLEAN wlan_perf_monitor_force_enable = FALSE; +#endif + +#if defined(CONFIG_MTK_QOS_SUPPORT) +static struct pm_qos_request vcore_req; +static atomic_t vcore_req_cnt; +static atomic_t vcore_changed; +static struct mutex vcore_mutex; +#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_ENABLE_FW_DOWNLOAD + +static struct file *filp; +static uid_t orgfsuid; +static gid_t orgfsgid; +static mm_segment_t orgfs; + +static PUINT_8 apucFwPath[] = { + (PUINT_8) "/storage/sdcard0/", + (PUINT_8) "/etc/firmware/", + (PUINT_8) "/vendor/firmware/", +#if !CONFIG_ANDROID + (PUINT_8) "/lib/firmware/", +#endif + NULL +}; + +#if defined(MT6631) /* MT6631 A-D die chip */ + +static PUINT_8 apucFwName[] = { + (PUINT_8) CFG_FW_FILENAME "_", + NULL +}; + +static PPUINT_8 appucFwNameTable[] = { + apucFwName +}; + +#else /* MT6630 */ +/* E2 */ +static PUINT_8 apucFwNameE2[] = { + (PUINT_8) CFG_FW_FILENAME "_MT6630_E2", + (PUINT_8) CFG_FW_FILENAME "_MT6630", + NULL +}; + +/* E3 */ +static PUINT_8 apucFwNameE3[] = { + (PUINT_8) CFG_FW_FILENAME "_MT6630_E3", + (PUINT_8) CFG_FW_FILENAME "_MT6630", + (PUINT_8) CFG_FW_FILENAME "_MT6630_E2", + NULL +}; + +/* Default */ +static PUINT_8 apucFwName[] = { + (PUINT_8) CFG_FW_FILENAME "_MT6630", + (PUINT_8) CFG_FW_FILENAME "_MT6630_E2", + (PUINT_8) CFG_FW_FILENAME "_MT6630_E3", + NULL +}; + +static PPUINT_8 appucFwNameTable[] = { + apucFwName, + apucFwNameE2, + apucFwNameE3, + apucFwNameE3, +}; +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to +* open firmware image in kernel space +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* +* \retval WLAN_STATUS_SUCCESS. +* \retval WLAN_STATUS_FAILURE. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS kalFirmwareOpen(IN P_GLUE_INFO_T prGlueInfo) +{ + UINT_8 ucPathIdx, ucNameIdx; + PPUINT_8 apucNameTable; + UINT_8 ucMaxEcoVer = (sizeof(appucFwNameTable) / sizeof(PPUINT_8)); + UINT_8 ucCurEcoVer = wlanGetEcoVersion(prGlueInfo->prAdapter); +#if defined(MT6631) + UINT_16 u2ChipID = nicGetChipID(prGlueInfo->prAdapter); +#endif + UINT_8 aucFwName[128]; + BOOLEAN fgResult = FALSE; + + /* + * FIX ME: since we don't have hotplug script in the filesystem, + * so the request_firmware() KAPI can not work properly + */ + + /* + * save uid and gid used for filesystem access. + * set user and group to 0(root) + */ + struct cred *cred = (struct cred *)get_current_cred(); + + orgfsuid = cred->fsuid.val; + orgfsgid = cred->fsgid.val; + cred->fsuid.val = cred->fsgid.val = 0; + + ASSERT(prGlueInfo); + + orgfs = get_fs(); + set_fs(get_ds()); + + /* Get FW name table */ + if (ucMaxEcoVer < ucCurEcoVer) + apucNameTable = apucFwName; + else + apucNameTable = appucFwNameTable[ucCurEcoVer - 1]; + + /* Try to open FW binary */ + for (ucPathIdx = 0; apucFwPath[ucPathIdx]; ucPathIdx++) { + for (ucNameIdx = 0; apucNameTable[ucNameIdx]; ucNameIdx++) { + + if (kalSnprintf(aucFwName, sizeof(aucFwName), "%s%s", + apucFwPath[ucPathIdx], apucNameTable[ucNameIdx]) < 0) + continue; + +#if defined(MT6631) + switch (u2ChipID) { + case 0x6758: + /* fall through */ + case 0x6771: + /* fall through */ + case 0x6775: + u2ChipID = 0x6759; + break; + default: + break; + } + if (kalSnprintf(aucFwName + strlen(aucFwName), sizeof(aucFwName) - strlen(aucFwName), + "%x", u2ChipID) < 0) + continue; +#endif + + filp = filp_open(aucFwName, O_RDONLY, 0); + if (IS_ERR(filp)) { + DBGLOG(INIT, TRACE, "Open FW image %s failed, filp[%p]\n", + aucFwName, filp); + continue; + } else { + DBGLOG(INIT, INFO, "Open FW image %s success\n", aucFwName); + fgResult = TRUE; + break; + } + } + + if (fgResult) + break; + } + + /* Check result */ + if (!fgResult) { + DBGLOG(INIT, ERROR, "Open FW image failed! Cur/Max ECO Ver[E%u/E%u]\n", + ucCurEcoVer, ucMaxEcoVer); + goto error_open; + } + + return WLAN_STATUS_SUCCESS; + +error_open: + /* restore */ + set_fs(orgfs); + cred->fsuid.val = orgfsuid; + cred->fsgid.val = orgfsgid; + put_cred(cred); + return WLAN_STATUS_FAILURE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to +* release firmware image in kernel space +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* +* \retval WLAN_STATUS_SUCCESS. +* \retval WLAN_STATUS_FAILURE. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS kalFirmwareClose(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + if ((filp != NULL) && !IS_ERR(filp)) { + /* close firmware file */ + filp_close(filp, NULL); + + /* restore */ + set_fs(orgfs); + { + struct cred *cred = (struct cred *)get_current_cred(); + + cred->fsuid.val = orgfsuid; + cred->fsgid.val = orgfsgid; + put_cred(cred); + } + filp = NULL; + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to +* load firmware image in kernel space +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* +* \retval WLAN_STATUS_SUCCESS. +* \retval WLAN_STATUS_FAILURE. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS kalFirmwareLoad(IN P_GLUE_INFO_T prGlueInfo, OUT PVOID prBuf, IN UINT_32 u4Offset, OUT PUINT_32 pu4Size) +{ + ASSERT(prGlueInfo); + ASSERT(pu4Size); + ASSERT(prBuf); + + /* l = filp->f_path.dentry->d_inode->i_size; */ + + /* the object must have a read method */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + if ((filp == NULL) || IS_ERR(filp) || (filp->f_op == NULL)) { +#else + if ((filp == NULL) || IS_ERR(filp) || (filp->f_op == NULL) || (filp->f_op->read == NULL)) { +#endif + goto error_read; + } else { + filp->f_pos = u4Offset; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) + *pu4Size = kernel_read(filp, (__force void __user *)prBuf, *pu4Size, &filp->f_pos); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + *pu4Size = __vfs_read(filp, (__force void __user *)prBuf, *pu4Size, &filp->f_pos); +#else + *pu4Size = filp->f_op->read(filp, prBuf, *pu4Size, &filp->f_pos); +#endif + } + + return WLAN_STATUS_SUCCESS; + +error_read: + return WLAN_STATUS_FAILURE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to +* query firmware image size in kernel space +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* +* \retval WLAN_STATUS_SUCCESS. +* \retval WLAN_STATUS_FAILURE. +* +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS kalFirmwareSize(IN P_GLUE_INFO_T prGlueInfo, OUT PUINT_32 pu4Size) +{ + loff_t len; + ASSERT(prGlueInfo); + ASSERT(pu4Size); + len = vfs_llseek(filp, 0, SEEK_END); + if (len >= 0) + *pu4Size = (unsigned int)len; + else + return len; + vfs_llseek(filp, 0, SEEK_SET); + 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 { + UINT_32 u4FwSize = 0; + PVOID prFwBuffer = NULL; + + /* <1> Open firmware */ + if (kalFirmwareOpen(prGlueInfo) != WLAN_STATUS_SUCCESS) + break; + + /* <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) { + DBGLOG(INIT, INFO, "fw %s:request failed %d\n", CFG_FW_FILENAME, i4Ret); + } 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 PULONG plFlags) +{ + ULONG ulFlags = 0; + + ASSERT(prGlueInfo); + ASSERT(plFlags); + + 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], ulFlags); +#endif /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + + *plFlags = ulFlags; + } + +} /* 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 ULONG ulFlags) +{ + 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], ulFlags); +#endif /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + + } + +} /* end of kalReleaseSpinLock() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to acquire +* OS MUTEX. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] rMutexCategory Specify which MUTEX +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID kalAcquireMutex(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_MUTEX_CATEGORY_E rMutexCategory) +{ + ASSERT(prGlueInfo); + + if (rMutexCategory < MUTEX_NUM) { + DBGLOG(INIT, TRACE, "MUTEX_LOCK[%u] Try to acquire\n", rMutexCategory); + mutex_lock(&prGlueInfo->arMutex[rMutexCategory]); + DBGLOG(INIT, TRACE, "MUTEX_LOCK[%u] Acquired\n", rMutexCategory); + } + +} /* end of kalAcquireMutex() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to release +* OS MUTEX. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] rMutexCategory Specify which MUTEX +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID kalReleaseMutex(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_MUTEX_CATEGORY_E rMutexCategory) +{ + ASSERT(prGlueInfo); + + if (rMutexCategory < MUTEX_NUM) { + mutex_unlock(&prGlueInfo->arMutex[rMutexCategory]); + DBGLOG(INIT, TRACE, "MUTEX_UNLOCK[%u]\n", rMutexCategory); + } + +} /* end of kalReleaseMutex() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to update +* current MAC address. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pucMacAddr Pointer of current MAC address +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID kalUpdateMACAddress(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucMacAddr) +{ + ASSERT(prGlueInfo); + ASSERT(pucMacAddr); + + if (UNEQUAL_MAC_ADDR(prGlueInfo->prDevHandler->dev_addr, pucMacAddr)) + memcpy(prGlueInfo->prDevHandler->dev_addr, pucMacAddr, PARAM_MAC_ADDR_LEN); + +} + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +/*----------------------------------------------------------------------------*/ +/*! +* \brief To query the packet information for offload related parameters. +* +* \param[in] pvPacket Pointer to the packet descriptor. +* \param[in] pucFlag Points to the offload related parameter. +* +* \return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID kalQueryTxChksumOffloadParam(IN PVOID pvPacket, OUT PUINT_8 pucFlag) +{ + struct sk_buff *skb = (struct sk_buff *)pvPacket; + UINT_8 ucFlag = 0; + + ASSERT(pvPacket); + ASSERT(pucFlag); + + if (skb->ip_summed == CHECKSUM_PARTIAL) { +#if DBG + /* + * Kevin: do double check, we can remove this part in Normal Driver. + * Because we register NIC feature with NETIF_F_IP_CSUM for MT5912B MAC, so + * we'll process IP packet only. + */ + if (skb->protocol != htons(ETH_P_IP)) { + /* + * DBGLOG(INIT, INFO, "Wrong skb->protocol( = %08x) + * for TX Checksum Offload.\n", skb->protocol); + */ + } else +#endif + ucFlag |= (TX_CS_IP_GEN | TX_CS_TCP_UDP_GEN); + } + + *pucFlag = ucFlag; + +} /* kalQueryChksumOffloadParam */ + +/* 4 2007/10/8, mikewu, this is rewritten by Mike */ +/*----------------------------------------------------------------------------*/ +/*! +* \brief To update the checksum offload status to the packet to be indicated to OS. +* +* \param[in] pvPacket Pointer to the packet descriptor. +* \param[in] pucFlag Points to the offload related parameter. +* +* \return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID kalUpdateRxCSUMOffloadParam(IN PVOID pvPacket, IN ENUM_CSUM_RESULT_T aeCSUM[]) +{ + struct sk_buff *skb = (struct sk_buff *)pvPacket; + + ASSERT(pvPacket); + + if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_SUCCESS || aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_SUCCESS) + && ((aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_SUCCESS) + || (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_SUCCESS))) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + } else { + skb->ip_summed = CHECKSUM_NONE; +#if DBG + if (aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_NONE && aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_NONE) + DBGLOG(RX, TRACE, "RX: \"non-IPv4/IPv6\" Packet\n"); + else if (aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_FAILED) + DBGLOG(RX, TRACE, "RX: \"bad IP Checksum\" Packet\n"); + else if (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_FAILED) + DBGLOG(RX, TRACE, "RX: \"bad TCP Checksum\" Packet\n"); + else if (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_FAILED) + DBGLOG(RX, TRACE, "RX: \"bad UDP Checksum\" Packet\n"); + +#endif + } + +} /* kalUpdateRxCSUMOffloadParam */ +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to free packet allocated from kalPacketAlloc. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pvPacket Pointer of the packet descriptor +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID kalPacketFree(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket) +{ + dev_kfree_skb((struct sk_buff *)pvPacket); + if (prGlueInfo) + prGlueInfo->u8SkbFreed++; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Only handles driver own creating packet (coalescing buffer). +* +* \param prGlueInfo Pointer of GLUE Data Structure +* \param u4Size Pointer of Packet Handle +* \param ppucData Status Code for OS upper layer +* +* \return NULL: Failed to allocate skb, Not NULL get skb +*/ +/*----------------------------------------------------------------------------*/ +PVOID kalPacketAlloc(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Size, OUT PUINT_8 *ppucData) +{ + struct sk_buff *prSkb = NULL; + + if (in_interrupt()) + prSkb = __dev_alloc_skb(u4Size, GFP_ATOMIC); + else + prSkb = __dev_alloc_skb(u4Size, GFP_KERNEL); + + if (prSkb) { + *ppucData = (PUINT_8) (prSkb->data); + + kalResetPacket(prGlueInfo, (P_NATIVE_PACKET) prSkb); + } +#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; + + /* Reset skb */ + skb_reset_tail_pointer(skb); + skb_trim(skb, 0); + + if (skb->tail > skb->end || skb->tail + u4PacketLen > skb->end) { + DBGLOG(RX, ERROR, + "skb:0x%p len:%d protocol:0x%02X tail:%p end:%p data:%p PktLen:%d\n", + (PUINT_8) skb, skb->len, skb->protocol, skb->tail, skb->end, skb->data, u4PacketLen); + DBGLOG_MEM32(RX, ERROR, (PUINT_32) skb->data, skb->len); + return WLAN_STATUS_FAILURE; + } + + /* Put data */ + skb_put(skb, 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 = NULL; + + ASSERT(prGlueInfo); + ASSERT(apvPkts); + + prNetDev = prGlueInfo->prDevHandler; + for (ucIdx = 0; ucIdx < ucPktNum; ucIdx++) + kalRxIndicateOnePkt(prGlueInfo, apvPkts[ucIdx]); + if (netif_carrier_ok(prNetDev)) + kalPerMonStart(prGlueInfo); + + KAL_WAKE_LOCK_TIMEOUT(prGlueInfo->prAdapter, &prGlueInfo->rTimeoutWakeLock, + MSEC_TO_JIFFIES(WAKE_LOCK_RX_TIMEOUT)); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate one received packets is available for higher +* level protocol uses. +* +* \param[in] prGlueInfo Pointer to the Adapter structure. +* \param[in] pvPkt The packet to be indicated +* +* \retval TRUE Success. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS kalRxIndicateOnePkt(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPkt) +{ + struct net_device *prNetDev = prGlueInfo->prDevHandler; + struct sk_buff *prSkb = NULL; + UINT_8 bssIdx = 0; + + ASSERT(prGlueInfo); + ASSERT(pvPkt); + + prSkb = pvPkt; +#if DBG && 0 + 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 1 + bssIdx = GLUE_GET_PKT_BSS_IDX(prSkb); + prNetDev = (struct net_device *)wlanGetNetInterfaceByBssIdx(prGlueInfo, bssIdx); + if (!prNetDev) { + prNetDev = prGlueInfo->prDevHandler; + } else { + if (bssIdx == NET_DEV_P2P_IDX) { + if (prGlueInfo->prAdapter->rP2PNetRegState == ENUM_NET_REG_STATE_UNREGISTERED) { + DBGLOG(RX, INFO, "bssIdx = %d P2PNetRegState=%d\n", + bssIdx, prGlueInfo->prAdapter->rP2PNetRegState); + prNetDev = prGlueInfo->prDevHandler; + } + } + } +#if CFG_SUPPORT_SNIFFER + if (prGlueInfo->fgIsEnableMon) + prNetDev = prGlueInfo->prMonDevHandler; +#endif + prNetDev->stats.rx_bytes += prSkb->len; + prNetDev->stats.rx_packets++; +#else + 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++; + + } +#endif + StatsEnvRxTime2Host(prGlueInfo->prAdapter, prSkb); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)) + prNetDev->last_rx = jiffies; +#endif +#if CFG_SUPPORT_SNIFFER + if (prGlueInfo->fgIsEnableMon) { + skb_reset_mac_header(prSkb); + prSkb->ip_summed = CHECKSUM_UNNECESSARY; + prSkb->pkt_type = PACKET_OTHERHOST; + prSkb->protocol = htons(ETH_P_802_2); + } else { + prSkb->protocol = eth_type_trans(prSkb, prNetDev); + } +#else + prSkb->protocol = eth_type_trans(prSkb, prNetDev); +#endif + prSkb->dev = prNetDev; + /* DBGLOG_MEM32(RX, TRACE, (PUINT_32)prSkb->data, prSkb->len); */ + /* DBGLOG(RX, EVENT, ("kalRxIndicatePkts len = %d\n", prSkb->len)); */ + if (prSkb->tail > prSkb->end) { + DBGLOG(RX, ERROR, + "prSkb[%p] len[%u] protocol[0x%04x] tail[0x%lx], end[0x%lx]\n", + prSkb, prSkb->len, prSkb->protocol, (ULONG)prSkb->tail, (ULONG)prSkb->end); + DBGLOG_MEM32(RX, ERROR, (PUINT_32) prSkb->data, prSkb->len); + } + if (!in_interrupt()) + netif_rx_ni(prSkb); /* only in non-interrupt context */ + else + netif_rx(prSkb); + + 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); +#if CFG_SUPPORT_ABORT_SCAN + P_WLAN_STATUS pWlanStatus = (P_WLAN_STATUS)pvBuf; + OS_SYSTIME rCuttentTime = 0; +#endif + PARAM_MAC_ADDRESS arBssid; + struct cfg80211_scan_request *prScanRequest = NULL; + PARAM_SSID_T ssid; + struct ieee80211_channel *prChannel = NULL; + struct cfg80211_bss *bss = NULL; + UINT_8 ucChannelNum; + P_BSS_DESC_T prBssDesc = NULL; + OS_SYSTIME rCurrentTime; + BOOLEAN fgIsNeedUpdateBss = FALSE; + P_CONNECTION_SETTINGS_T prConnSettings = NULL; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) + struct cfg80211_scan_info rScanInfo = { 0 }; +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) + struct cfg80211_roam_info rRoamInfo = { }; +#endif + + GLUE_SPIN_LOCK_DECLARATION(); + + kalMemZero(arBssid, MAC_ADDR_LEN); + GET_CURRENT_SYSTIME(&rCurrentTime); + + ASSERT(prGlueInfo); + + switch (eStatus) { + case WLAN_STATUS_ROAM_OUT_FIND_BEST: + case WLAN_STATUS_MEDIA_CONNECT: + +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + /* clear the Rx Err count */ + prGlueInfo->prAdapter->rLinkQualityInfo.u8RxErrCount = 0; +#endif + 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) { + struct cfg80211_bss *bss_others = NULL; + UINT_8 ucLoopCnt = 15; /* only loop 15 times to avoid dead loop */ + + /* retrieve channel */ + ucChannelNum = + wlanGetChannelNumberByNetwork(prGlueInfo->prAdapter, + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex); + if (ucChannelNum <= 14) { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency + (ucChannelNum, KAL_BAND_2GHZ)); + } else { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency + (ucChannelNum, KAL_BAND_5GHZ)); + } + + if (prChannel) { + /* ensure BSS exists */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + bss = cfg80211_get_bss(priv_to_wiphy(prGlueInfo), prChannel, arBssid, + ssid.aucSsid, ssid.u4SsidLen, + IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY); +#else + bss = cfg80211_get_bss(priv_to_wiphy(prGlueInfo), prChannel, arBssid, + ssid.aucSsid, ssid.u4SsidLen, WLAN_CAPABILITY_ESS, + WLAN_CAPABILITY_ESS); +#endif + + prBssDesc = ((P_AIS_FSM_INFO_T) + (&(prGlueInfo->prAdapter->rWifiVar.rAisFsmInfo)))->prTargetBssDesc; + if (prBssDesc != NULL) { + /* + * cfg80211 using cfg80211_get_bss function to update wdev->current_bss in + * asynchronous way. In cfg80211_get_bss function, there will check if bss + * timeout. wdev->current_bss will be NULL if bss timeout and + * it will casue set key failed after 4-way handshake. cfg80211 bss expire + * time is 7s.So we need inform bss again if bss age is more than 5s after + * connected to avoid this timing case. + */ + if (CHECK_FOR_TIMEOUT(rCurrentTime, + prBssDesc->rUpdateTime, + SEC_TO_SYSTIME(5))) { + fgIsNeedUpdateBss = TRUE; + DBGLOG(SCN, INFO, "Bss age > 5s, update bss to cfg80211.\n"); + } + } + if (bss == NULL || fgIsNeedUpdateBss == TRUE) { + /* create BSS on-the-fly */ + if (prBssDesc != NULL) { + bss = cfg80211_inform_bss(priv_to_wiphy(prGlueInfo), + prChannel, + CFG80211_BSS_FTYPE_PRESP, + arBssid, + 0, /* TSF */ + prBssDesc->u2CapInfo, + prBssDesc->u2BeaconInterval, + prBssDesc->aucIEBuf, + prBssDesc->u2IELength, + RCPI_TO_dBm(prBssDesc->ucRCPI) * 100, + GFP_KERNEL); + } + } + } else + DBGLOG(SCN, ERROR, "prChannel is NULL and ucChannelNum is %d\n", ucChannelNum); + /* + * remove all bsses that before and only channel different with the current connected one + * if without this patch, UI will show channel A is connected even if AP has change channel + * from A to B + */ + while (ucLoopCnt--) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + bss_others = cfg80211_get_bss(priv_to_wiphy(prGlueInfo), NULL, arBssid, + ssid.aucSsid, ssid.u4SsidLen, + IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY); +#else + bss_others = cfg80211_get_bss(priv_to_wiphy(prGlueInfo), NULL, arBssid, + ssid.aucSsid, ssid.u4SsidLen, + WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); +#endif + if (bss && bss_others && bss_others != bss) { + DBGLOG(SCN, INFO, "remove BSSes that only channel different\n"); + cfg80211_unlink_bss(priv_to_wiphy(prGlueInfo), bss_others); + } else + break; + } + + StatsResetTxRx(); + + /* CFG80211 Indication */ + if (eStatus == WLAN_STATUS_ROAM_OUT_FIND_BEST) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) + rRoamInfo.bss = bss; + rRoamInfo.req_ie = prGlueInfo->aucReqIe; + rRoamInfo.req_ie_len = prGlueInfo->u4ReqIeLength; + rRoamInfo.resp_ie = prGlueInfo->aucRspIe; + rRoamInfo.resp_ie_len = prGlueInfo->u4RspIeLength; + cfg80211_roamed(prGlueInfo->prDevHandler, &rRoamInfo, GFP_KERNEL); +#else + cfg80211_roamed_bss(prGlueInfo->prDevHandler, + bss, + prGlueInfo->aucReqIe, + prGlueInfo->u4ReqIeLength, + prGlueInfo->aucRspIe, prGlueInfo->u4RspIeLength, GFP_KERNEL); +#endif + } else { + cfg80211_connect_result(prGlueInfo->prDevHandler, arBssid, + prGlueInfo->aucReqIe, + prGlueInfo->u4ReqIeLength, + prGlueInfo->aucRspIe, + prGlueInfo->u4RspIeLength, WLAN_STATUS_SUCCESS, GFP_KERNEL); + } + + /*workaround sta dfs channel + sap turn on fail issue.*/ + wlanUpdateDfsChannelTable(prGlueInfo, ucChannelNum); + + } + + break; + + case WLAN_STATUS_MEDIA_DISCONNECT: + case WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY: +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + /* clear the Rx Err count */ + prGlueInfo->prAdapter->rLinkQualityInfo.u8RxErrCount = 0; +#endif + /* 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); + + /*Full2Partial*/ + DBGLOG(INIT, TRACE, "Full2Partial disconnect reset value\n"); + prGlueInfo->u4LastFullScanTime = 0; + + + if (prGlueInfo->fgIsRegistered == TRUE) { + P_BSS_INFO_T prBssInfo = prGlueInfo->prAdapter->prAisBssInfo; + UINT_16 u2DeauthReason = 0; + + if (prBssInfo) { + if (eStatus == WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY) + u2DeauthReason = REASON_CODE_DEAUTH_LEAVING_BSS; + else + u2DeauthReason = prBssInfo->u2DeauthReason; + glNotifyDrvStatus(DISCONNECT_AP, (PVOID)prBssInfo); + } + + /* CFG80211 Indication */ + DBGLOG(INIT, INFO, "[wifi]Indicate disconnection: Reason=%d Locally[%d]\n", u2DeauthReason, + (eStatus == WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY)); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + cfg80211_disconnected(prGlueInfo->prDevHandler, u2DeauthReason, NULL, 0, + eStatus == WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY ? true : false, + GFP_KERNEL); +#else + cfg80211_disconnected(prGlueInfo->prDevHandler, u2DeauthReason, NULL, 0, GFP_KERNEL); +#endif + } + + kalMemFree(prGlueInfo->rFtIeForTx.pucIEBuf, VIR_MEM_TYPE, prGlueInfo->rFtIeForTx.u4IeLength); + kalMemZero(&prGlueInfo->rFtIeForTx, sizeof(prGlueInfo->rFtIeForTx)); + /* Prevent memory leakage */ + prConnSettings = + &prGlueInfo->prAdapter->rWifiVar.rConnSettings; + if (prConnSettings && prConnSettings->assocIeLen > 0) { + kalMemFree(prConnSettings->pucAssocIEs, VIR_MEM_TYPE, + prConnSettings->assocIeLen); + prConnSettings->assocIeLen = 0; + } + + prGlueInfo->eParamMediaStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; + + /*workaround sta dfs channel + sap turn on fail issue.*/ + wlanUpdateDfsChannelTable(prGlueInfo, 0); + +#if (defined FW_CFG_SUPPORT) && (defined CFG_SUPPORT_COEX_IOT_AP) + if (prGlueInfo->prAdapter) + wlanFWCfgForceDisIotAP(prGlueInfo->prAdapter); +#endif + break; + + case WLAN_STATUS_SCAN_COMPLETE: + /* indicate scan complete event */ + wext_indicate_wext_event(prGlueInfo, SIOCGIWSCAN, NULL, 0); + + DBGLOG(SCN, EVENT, "scan complete, cfg80211 scan request is %p\n", prGlueInfo->prScanRequest); + /* 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; + } else + DBGLOG(SCN, WARN, "scan complete but cfg80211 scan request is NULL\n"); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + +#if CFG_SUPPORT_ABORT_SCAN + /* 2. then CFG80211 Indication */ + if (prScanRequest && pWlanStatus) { + if (*pWlanStatus != WLAN_STATUS_ABORT_SCAN) { + GET_CURRENT_SYSTIME(&rCuttentTime); + prGlueInfo->u4LastNormalScanTime = rCuttentTime; + prGlueInfo->ucAbortScanCnt = 0; + DBGLOG(SCN, TRACE, + "LastNormalScanTime is %u and reset scan abort cnt\n", + prGlueInfo->u4LastNormalScanTime); + } else { + AisFsmSetScanState(prGlueInfo->prAdapter, FALSE); + prGlueInfo->ucAbortScanCnt++; + DBGLOG(SCN, INFO, + "Abort scan done event cnt %d\n", + prGlueInfo->ucAbortScanCnt); + } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) + rScanInfo.aborted = (*pWlanStatus == WLAN_STATUS_ABORT_SCAN); + cfg80211_scan_done(prScanRequest, &rScanInfo); +#else + cfg80211_scan_done(prScanRequest, (*pWlanStatus == WLAN_STATUS_ABORT_SCAN)); +#endif + } +#else + /* 2. then CFG80211 Indication */ + if (prScanRequest) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) + rScanInfo.aborted = FALSE, + cfg80211_scan_done(prScanRequest, &rScanInfo); +#else + cfg80211_scan_done(prScanRequest, FALSE); +#endif + } +#endif + 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: + /* 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: + { + 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++) { + cfg80211_pmksa_candidate_notify(prGlueInfo->prDevHandler, 1000, + prPmkidCand[i].arBSSID, + prPmkidCand[i].u4Flags, + GFP_KERNEL); + wext_indicate_wext_event(prGlueInfo, + IWEVPMKIDCAND, + (unsigned char *)&prPmkidCand[i], + pPmkid->u4NumCandidates); + } + break; + } + case ENUM_STATUS_TYPE_FT_AUTH_STATUS: + cfg80211_ft_event(prGlueInfo->prDevHandler, &prGlueInfo->rFtEventParam); + break; + + default: + /* case ENUM_STATUS_TYPE_MEDIA_STREAM_MODE */ + /* + */ + break; + } + } + 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 + case WLAN_STATUS_JOIN_FAILURE: + { + P_BSS_DESC_T prBssDesc = prGlueInfo->prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc; + + if (prBssDesc) { + DBGLOG(INIT, INFO, "JOIN Failure: u2JoinStatus=%d", prBssDesc->u2JoinStatus); + COPY_MAC_ADDR(arBssid, prBssDesc->aucBSSID); + } else + COPY_MAC_ADDR(arBssid, prGlueInfo->prAdapter->rWifiVar.rConnSettings.aucBSSID); + + if (prBssDesc && prBssDesc->u2JoinStatus != STATUS_CODE_SUCCESSFUL && + prBssDesc->u2JoinStatus != STATUS_CODE_AUTH_TIMEOUT && + prBssDesc->u2JoinStatus != STATUS_CODE_ASSOC_TIMEOUT) + cfg80211_connect_result(prGlueInfo->prDevHandler, + arBssid, + prGlueInfo->aucReqIe, + prGlueInfo->u4ReqIeLength, + prGlueInfo->aucRspIe, + prGlueInfo->u4RspIeLength, + prBssDesc->u2JoinStatus, GFP_KERNEL); + else + cfg80211_connect_result(prGlueInfo->prDevHandler, + arBssid, + prGlueInfo->aucReqIe, + prGlueInfo->u4ReqIeLength, + prGlueInfo->aucRspIe, + prGlueInfo->u4RspIeLength, WLAN_STATUS_AUTH_TIMEOUT, GFP_KERNEL); + /*workaround sta dfs channel + sap turn on fail issue.*/ + wlanUpdateDfsChannelTable(prGlueInfo, 0); + + prGlueInfo->eParamMediaStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; + break; + } + + case WLAN_STATUS_BSS_CH_SWITCH: + { + struct cfg80211_chan_def chan; + + if (!prGlueInfo->prAdapter || !prGlueInfo->prAdapter->prAisBssInfo) { + DBGLOG(INIT, ERROR, "No AIS BSS info\n"); + return; + } + + /* retrieve channel */ + ucChannelNum = prGlueInfo->prAdapter->prAisBssInfo->ucPrimaryChannel; + if (ucChannelNum <= 14) { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency + (ucChannelNum, NL80211_BAND_2GHZ)); + } else { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency + (ucChannelNum, NL80211_BAND_5GHZ)); + } + + /* create the chandef structure */ + cfg80211_chandef_create(&chan, prChannel, NL80211_CHAN_HT20); + + /* CFG80211 indication */ + cfg80211_ch_switch_notify(prGlueInfo->prDevHandler, &chan); + } + default: + 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) + return; + } else { + if (u4FrameBodyLen < 9) + return; + } + + cp = pucFrameBody; + + if (fgReassocRequest) { + /* Capability information field 2 */ + /* Listen interval field 2 */ + /* Current AP address 6 */ + cp += 10; + u4FrameBodyLen -= 10; + } else { + /* Capability information field 2 */ + /* Listen interval field 2 */ + cp += 4; + u4FrameBodyLen -= 4; + } + + wext_indicate_wext_event(prGlueInfo, IWEVASSOCREQIE, cp, u4FrameBodyLen); + + if (u4FrameBodyLen <= CFG_CFG80211_IE_BUF_LEN) { + prGlueInfo->u4ReqIeLength = u4FrameBodyLen; + kalMemCopy(prGlueInfo->aucReqIe, cp, u4FrameBodyLen); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This routine is called to update the (re)association +* response information to the structure used to reply with +* cfg80211_connect_result +* +* @param prGlueInfo Pointer to adapter descriptor +* @param pucFrameBody Pointer to the frame body of the last (Re)Association +* Response frame from the AP +* @param u4FrameBodyLen The length of the frame body of the last +* (Re)Association Response frame +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID kalUpdateReAssocRspInfo(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucFrameBody, IN UINT_32 u4FrameBodyLen) +{ + UINT_32 u4IEOffset = 6; /* cap_info, status_code & assoc_id */ + UINT_32 u4IELength = u4FrameBodyLen - u4IEOffset - WLAN_MAC_MGMT_HEADER_LEN; + + ASSERT(prGlueInfo); + + /* reset */ + prGlueInfo->u4RspIeLength = 0; + + if (u4IELength <= CFG_CFG80211_IE_BUF_LEN) { + prGlueInfo->u4RspIeLength = u4IELength; + kalMemCopy(prGlueInfo->aucRspIe, pucFrameBody + u4IEOffset, u4IELength); + } + +} /* kalUpdateReAssocRspInfo */ + +VOID kalResetPacket(IN P_GLUE_INFO_T prGlueInfo, IN P_NATIVE_PACKET prPacket) +{ + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + + /* Reset cb */ + kalMemZero(prSkb->cb, sizeof(prSkb->cb)); +} + +/*----------------------------------------------------------------------------*/ +/* +* \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 +* \param[in] prGlueInfo Pointer of prGlueInfo +* \param[in] ucBssIndex BSS index of this net device +* +* \retval WLAN_STATUS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +kalHardStartXmit(struct sk_buff *prSkb, IN struct net_device *prDev, P_GLUE_INFO_T prGlueInfo, UINT_8 ucBssIndex) +{ + P_QUE_ENTRY_T prQueueEntry = NULL; + P_QUE_T prTxQueue = NULL; + UINT_16 u2QueueIdx = 0; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prSkb); + ASSERT(prGlueInfo); + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(INIT, INFO, "GLUE_FLAG_HALT skip tx\n"); + dev_kfree_skb(prSkb); + prGlueInfo->u8SkbFreed++; + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + prQueueEntry = (P_QUE_ENTRY_T) GLUE_GET_PKT_QUEUE_ENTRY(prSkb); + prTxQueue = &prGlueInfo->rTxQueue; + + GLUE_SET_PKT_BSS_IDX(prSkb, ucBssIndex); + +#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 + + /* Parsing frame info */ + if (!wlanProcessTxFrame(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb)) { + /* Cannot extract packet */ + DBGLOG(INIT, INFO, "Cannot extract content, skip this frame\n"); + dev_kfree_skb(prSkb); + prGlueInfo->u8SkbFreed++; + return WLAN_STATUS_INVALID_PACKET; + } + + /* Tx profiling */ + wlanTxProfilingTagPacket(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb, TX_PROF_TAG_OS_TO_DRV); + + /* Handle normal data frame */ + u2QueueIdx = skb_get_queue_mapping(prSkb); + + if (u2QueueIdx >= CFG_MAX_TXQ_NUM) { + DBGLOG(INIT, INFO, "Incorrect queue index, skip this frame\n"); + dev_kfree_skb(prSkb); + prGlueInfo->u8SkbFreed++; + return WLAN_STATUS_INVALID_PACKET; + } + + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingFrameNum); + GLUE_INC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex][u2QueueIdx]); + + if (GLUE_GET_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex][u2QueueIdx]) + >= prGlueInfo->prAdapter->rWifiVar.u4NetifStopTh) { + netif_stop_subqueue(prDev, u2QueueIdx); + + DBGLOG(TX, INFO, + "Stop subqueue for BSS[%d] QIDX[%d] PKT_LEN[%u] TOT_CNT[%d] PER-Q_CNT[%d]\n", + ucBssIndex, u2QueueIdx, prSkb->len, + GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum), + GLUE_GET_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex] + [u2QueueIdx])); + } + + /* Update NetDev statisitcs */ + prDev->stats.tx_bytes += prSkb->len; + prDev->stats.tx_packets++; + + DBGLOG(TX, LOUD, + "Enqueue frame for BSS[%d] QIDX[%d] PKT_LEN[%u] TOT_CNT[%d] PER-Q_CNT[%d]\n", + ucBssIndex, u2QueueIdx, prSkb->len, + GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum), + GLUE_GET_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex][u2QueueIdx])); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_INSERT_TAIL(prTxQueue, prQueueEntry); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + + kalSetEvent(prGlueInfo); + + return WLAN_STATUS_SUCCESS; +} /* end of kalHardStartXmit() */ + +WLAN_STATUS kalResetStats(IN struct net_device *prDev) +{ + DBGLOG(QM, LOUD, "Reset NetDev[0x%p] statistics\n", prDev); + + kalMemZero(kalGetStats(prDev), sizeof(struct net_device_stats)); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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. +*/ +/*----------------------------------------------------------------------------*/ +PVOID kalGetStats(IN struct net_device *prDev) +{ + return (PVOID) &prDev->stats; +} /* end of wlanGetStats() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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 ucBssIndex = 0; + BOOLEAN fgIsValidDevice = TRUE; + + ASSERT(pvPacket); + /* ASSERT(prGlueInfo->i4TxPendingFrameNum); */ + + prSkb = (struct sk_buff *)pvPacket; + u2QueueIdx = skb_get_queue_mapping(prSkb); + ASSERT(u2QueueIdx < CFG_MAX_TXQ_NUM); + + ucBssIndex = GLUE_GET_PKT_BSS_IDX(pvPacket); + +#if CFG_ENABLE_WIFI_DIRECT + { + P_BSS_INFO_T prBssInfo = GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, ucBssIndex); + + /* in case packet was sent after P2P device is unregistered */ + if ((prBssInfo->eNetworkType == NETWORK_TYPE_P2P) && + (prGlueInfo->prAdapter->fgIsP2PRegistered == FALSE)) { + fgIsValidDevice = FALSE; + } + } +#endif + +#if 0 + if ((GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum) <= 0)) { + UINT_8 ucBssIdx; + UINT_16 u2QIdx; + + DBGLOG(INIT, INFO, "TxPendingFrameNum[%u] CurFrameId[%u]\n", prGlueInfo->i4TxPendingFrameNum, + GLUE_GET_PKT_ARRIVAL_TIME(pvPacket)); + + for (ucBssIdx = 0; ucBssIdx < HW_BSSID_NUM; ucBssIdx++) { + for (u2QIdx = 0; u2QIdx < CFG_MAX_TXQ_NUM; u2QIdx++) { + DBGLOG(INIT, INFO, "BSS[%u] Q[%u] TxPendingFrameNum[%u]\n", + ucBssIdx, u2QIdx, prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIdx][u2QIdx]); + } + } + } + + ASSERT((GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum) > 0)); +#endif + + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingFrameNum); + GLUE_DEC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex][u2QueueIdx]); + + DBGLOG(TX, LOUD, + "Release frame for BSS[%d] QIDX[%d] PKT_LEN[%u] TOT_CNT[%d] PER-Q_CNT[%d]\n", + ucBssIndex, u2QueueIdx, prSkb->len, + GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum), + GLUE_GET_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex][u2QueueIdx])); + + prDev = prSkb->dev; + + ASSERT(prDev); + + if (fgIsValidDevice == TRUE) { + UINT_32 u4StartTh = prGlueInfo->prAdapter->rWifiVar.u4NetifStartTh; + + if (netif_subqueue_stopped(prDev, prSkb) && + prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex][u2QueueIdx] <= u4StartTh) { + netif_wake_subqueue(prDev, u2QueueIdx); + DBGLOG(TX, INFO, + "WakeUp Queue BSS[%d] QIDX[%d] PKT_LEN[%u] TOT_CNT[%d] PER-Q_CNT[%d]\n", + ucBssIndex, u2QueueIdx, prSkb->len, + GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum), + GLUE_GET_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex] + [u2QueueIdx])); + } + } + + dev_kfree_skb((struct sk_buff *)pvPacket); + prGlueInfo->u8SkbFreed++; + DBGLOG(TX, LOUD, "----- pending frame %d -----\n", prGlueInfo->i4TxPendingFrameNum); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Copy Mac Address setting from registry. It's All Zeros in Linux. +* +* \param[in] prAdapter Pointer to the Adapter structure +* +* \param[out] paucMacAddr Pointer to the Mac Address buffer +* +* \retval WLAN_STATUS_SUCCESS +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +VOID kalQueryRegistryMacAddr(IN P_GLUE_INFO_T prGlueInfo, OUT PUINT_8 paucMacAddr) +{ + UINT_8 aucZeroMac[MAC_ADDR_LEN] = { 0, 0, 0, 0, 0, 0 } + + DEBUGFUNC("kalQueryRegistryMacAddr"); + + ASSERT(prGlueInfo); + ASSERT(paucMacAddr); + + kalMemCopy((PVOID) paucMacAddr, (PVOID) aucZeroMac, MAC_ADDR_LEN); + +} /* end of kalQueryRegistryMacAddr() */ + +#if CFG_SUPPORT_EXT_CONFIG +/*----------------------------------------------------------------------------*/ +/*! +* \brief Read external configuration, ex. NVRAM or file +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 kalReadExtCfg(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + /* + * External data is given from user space by ioctl or /proc, not read by + * driver. + */ + if (prGlueInfo->u4ExtCfgLength != 0) + DBGLOG(INIT, TRACE, "Read external configuration data -- OK\n"); + else + DBGLOG(INIT, TRACE, "Read external configuration data -- fail\n"); + + return prGlueInfo->u4ExtCfgLength; +} +#endif + +BOOLEAN +kalIPv4FrameClassifier(IN P_GLUE_INFO_T prGlueInfo, + IN P_NATIVE_PACKET prPacket, IN PUINT_8 pucIpHdr, + OUT P_TX_PACKET_INFO prTxPktInfo) +{ + UINT_8 ucIpVersion, ucIcmpType; + UINT_8 ucIpProto; + UINT_8 ucSeqNo; + PUINT_8 pucUdpHdr, pucIcmp; + UINT_16 u2DstPort, u2IcmpId, u2IcmpSeq; + P_BOOTP_PROTOCOL_T prBootp; + UINT_32 u4DhcpMagicCode; + + /* UINT_16 u2IpId; */ + + /* IPv4 version check */ + ucIpVersion = (pucIpHdr[0] & IP_VERSION_MASK) >> IP_VERSION_OFFSET; + if (ucIpVersion != IP_VERSION_4) { + DBGLOG(TX, WARN, "Invalid IPv4 packet version: %u\n", ucIpVersion); + return FALSE; + } + /* WLAN_GET_FIELD_16(&pucIpHdr[IPV4_HDR_IP_IDENTIFICATION_OFFSET], &u2IpId); */ + + ucIpProto = pucIpHdr[IPV4_HDR_IP_PROTOCOL_OFFSET]; + + if (ucIpProto == IP_PRO_UDP) { + pucUdpHdr = &pucIpHdr[IPV4_HDR_LEN]; + + /* DBGLOG_MEM8(INIT, INFO, pucUdpHdr, 256); */ + + /* Get UDP DST port */ + WLAN_GET_FIELD_BE16(&pucUdpHdr[UDP_HDR_DST_PORT_OFFSET], &u2DstPort); + + /* DBGLOG(INIT, INFO, ("UDP DST[%u]\n", u2DstPort)); */ + + /* Get UDP SRC port */ + /* WLAN_GET_FIELD_BE16(&pucUdpHdr[UDP_HDR_SRC_PORT_OFFSET], &u2SrcPort); */ + + /* BOOTP/DHCP protocol */ + if ((u2DstPort == IP_PORT_BOOTP_SERVER) || + (u2DstPort == IP_PORT_BOOTP_CLIENT)) { + + prBootp = (P_BOOTP_PROTOCOL_T) &pucUdpHdr[UDP_HDR_LEN]; + + WLAN_GET_FIELD_BE32(&prBootp->aucOptions[0], &u4DhcpMagicCode); + + if (u4DhcpMagicCode == DHCP_MAGIC_NUMBER) { + UINT_32 u4Xid; + + WLAN_GET_FIELD_BE32(&prBootp->u4TransId, &u4Xid); + + ucSeqNo = nicIncreaseTxSeqNum(prGlueInfo->prAdapter); + GLUE_SET_PKT_SEQ_NO(prPacket, ucSeqNo); + + DBGLOG(TX, INFO, "DHCP PKT[0x%p] XID[0x%08x] OPT[%u] TYPE[%u], SeqNo: %d\n", + prPacket, u4Xid, prBootp->aucOptions[4], prBootp->aucOptions[6], + ucSeqNo); + + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_DHCP); +#if CFG_SUPPORT_REPORT_MISC + set_bit(EXT_SRC_DHCP_BIT, + &(prGlueInfo->prAdapter->rReportMiscSet.ulExtSrcFlag)); + + kalSetReportMiscEvent(prGlueInfo); +#endif + } + } else if (u2DstPort == UDP_PORT_DNS) { + UINT_16 u2IpId = *(UINT_16 *) &pucIpHdr[IPV4_ADDR_LEN]; + PUINT_8 pucUdpPayload = &pucUdpHdr[UDP_HDR_LEN]; + UINT_16 u2TransId = (pucUdpPayload[0] << 8) | pucUdpPayload[1]; + + ucSeqNo = nicIncreaseTxSeqNum(prGlueInfo->prAdapter); + GLUE_SET_PKT_SEQ_NO(prPacket, ucSeqNo); + DBGLOG(TX, TRACE, " DNS: [0x%p] IPID[0x%02x] TransID[0x%04x] SeqNo[%d]\n", + prPacket, u2IpId, u2TransId, ucSeqNo); + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_DNS); + } + } else if (ucIpProto == IP_PRO_ICMP) { + /* the number of ICMP packets is seldom so we print log here */ + pucIcmp = &pucIpHdr[20]; + + ucIcmpType = pucIcmp[0]; + if (ucIcmpType == 3) /* don't log network unreachable packet */ + return FALSE; + u2IcmpId = *(UINT_16 *) &pucIcmp[4]; + u2IcmpSeq = *(UINT_16 *) &pucIcmp[6]; + + ucSeqNo = nicIncreaseTxSeqNum(prGlueInfo->prAdapter); + GLUE_SET_PKT_SEQ_NO(prPacket, ucSeqNo); + DBGLOG_LIMITED(SW4, INFO, " ICMP: Type %d, Id 0x04%x, Seq BE 0x%04x, SeqNo: %d\n", + ucIcmpType, u2IcmpId, u2IcmpSeq, ucSeqNo); + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_ICMP); + } + + return TRUE; +} + +BOOLEAN +kalArpFrameClassifier(IN P_GLUE_INFO_T prGlueInfo, + IN P_NATIVE_PACKET prPacket, IN PUINT_8 pucIpHdr, OUT P_TX_PACKET_INFO prTxPktInfo) +{ + UINT_16 u2ArpOp; + UINT_8 ucSeqNo; + + ucSeqNo = nicIncreaseTxSeqNum(prGlueInfo->prAdapter); + WLAN_GET_FIELD_BE16(&pucIpHdr[ARP_OPERATION_OFFSET], &u2ArpOp); + + DBGLOG_LIMITED(TX, INFO, "ARP %s PKT[0x%p] TAR MAC/IP[" MACSTR "]/[" IPV4STR "], SeqNo: %d\n", + u2ArpOp == ARP_OPERATION_REQUEST ? "REQ" : "RSP", + prPacket, MAC2STR(&pucIpHdr[ARP_TARGET_MAC_OFFSET]), + IPV4TOSTR(&pucIpHdr[ARP_TARGET_IP_OFFSET]), ucSeqNo); + + GLUE_SET_PKT_SEQ_NO(prPacket, ucSeqNo); + + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_ARP); + return TRUE; +} + +BOOLEAN +kalTdlsFrameClassifier(IN P_GLUE_INFO_T prGlueInfo, + IN P_NATIVE_PACKET prPacket, IN PUINT_8 pucIpHdr, OUT P_TX_PACKET_INFO prTxPktInfo) +{ + UINT_8 ucSeqNo; + UINT_8 ucActionCode; + + ucActionCode = pucIpHdr[TDLS_ACTION_CODE_OFFSET]; + + DBGLOG(TX, INFO, "TDLS action code: %d\n", ucActionCode); + + ucSeqNo = nicIncreaseTxSeqNum(prGlueInfo->prAdapter); + + GLUE_SET_PKT_SEQ_NO(prPacket, ucSeqNo); + + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_TDLS); + + return TRUE; +} + +BOOLEAN +kalSecurityFrameClassifier(IN P_GLUE_INFO_T prGlueInfo, + IN P_NATIVE_PACKET prPacket, IN PUINT_8 pucIpHdr, + IN UINT_16 u2EthType, OUT P_TX_PACKET_INFO prTxPktInfo) +{ + PUINT_8 pucEapol, pucPos; + UINT_8 ucEapolType; + UINT_8 ucSeqNo, ucAisBssIndex; + + UINT_8 ucSubType; /* sub type filed*/ + UINT_16 u2Length; + UINT_16 u2Seq; + INT_32 i4ExpVendor; + UINT_32 u32ExpType; + UINT_16 u2KeyInfo; + + pucEapol = pucIpHdr; + + if (u2EthType == ETH_P_1X) { + + ucEapolType = pucEapol[1]; + + switch (ucEapolType) { + case 0: /* eap packet */ + ucAisBssIndex = prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + + ucSeqNo = nicIncreaseTxSeqNum(prGlueInfo->prAdapter); + GLUE_SET_PKT_SEQ_NO(prPacket, ucSeqNo); + + DBGLOG(SW4, INFO, " EAP Packet: code %d, id %d, type %d, SeqNo: %d\n", + pucEapol[4], pucEapol[5], pucEapol[8], ucSeqNo); + pucPos = pucEapol + 8; + if (*pucPos != EAP_TYPE_EXPANDED) + break; + pucPos += 1; + WLAN_GET_FIELD_BE24(pucPos, &i4ExpVendor); + pucPos += 3; + WLAN_GET_FIELD_BE32(pucPos, &u32ExpType); + if (i4ExpVendor != EAP_VENDOR_WFA || u32ExpType != EAP_VENDOR_TYPE_WSC) + break; + pucPos += 4; + if (*pucPos != 5) + break; + if (GLUE_GET_PKT_BSS_IDX(prPacket) == ucAisBssIndex) + break; + DBGLOG(TX, INFO, "P2P: WSC Waiting EAP-FAILURE...\n"); + prGlueInfo->prAdapter->prP2pInfo->fgWaitEapFailure = TRUE; + prGlueInfo->prAdapter->prP2pInfo->u4EapWscDoneTxTime = kalGetTimeTick(); + + break; + case 1: /* eapol start */ + ucSeqNo = nicIncreaseTxSeqNum(prGlueInfo->prAdapter); + GLUE_SET_PKT_SEQ_NO(prPacket, ucSeqNo); + + DBGLOG(SW4, INFO, " EAPOL: start, SeqNo: %d\n", ucSeqNo); + break; + case 3: /* key */ + + ucSeqNo = nicIncreaseTxSeqNum(prGlueInfo->prAdapter); + GLUE_SET_PKT_SEQ_NO(prPacket, ucSeqNo); + + WLAN_GET_FIELD_BE16(&pucEapol[5], &u2KeyInfo); + DBGLOG(SW4, INFO, " EAPOL: key, KeyInfo 0x%04x, SeqNo: %d\n", + u2KeyInfo, ucSeqNo); + break; + } + + } else if (u2EthType == ETH_WPI_1X) { + + ucSubType = pucEapol[3]; /* sub type filed*/ + u2Length = *(PUINT_16)&pucEapol[6]; + u2Seq = *(PUINT_16)&pucEapol[8]; + ucSeqNo = nicIncreaseTxSeqNum(prGlueInfo->prAdapter); + GLUE_SET_PKT_SEQ_NO(prPacket, ucSeqNo); + + DBGLOG(SW4, INFO, " WAPI: subType %d, Len %d, Seq %d, SeqNo: %d\n", + ucSubType, u2Length, u2Seq, ucSeqNo); + + } + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_1X); + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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 prPacket Packet descriptor +* @param prTxPktInfo Extracted packet info +* +* @retval TRUE Success to extract information +* @retval FALSE Fail to extract correct information +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalQoSFrameClassifierAndPacketInfo(IN P_GLUE_INFO_T prGlueInfo, + IN P_NATIVE_PACKET prPacket, OUT P_TX_PACKET_INFO prTxPktInfo) +{ + UINT_32 u4PacketLen; + UINT_16 u2EtherType; + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + PUINT_8 aucLookAheadBuf = NULL; + UINT_8 ucEthTypeLenOffset = ETHER_HEADER_LEN - ETHER_TYPE_LEN; + PUINT_8 pucNextProtocol = NULL; +#if DSCP_SUPPORT + UINT_8 ucUserPriority; +#endif + + u4PacketLen = prSkb->len; + + if (u4PacketLen < ETHER_HEADER_LEN) { + DBGLOG(INIT, WARN, "Invalid Ether packet length: %u\n", u4PacketLen); + return FALSE; + } + + aucLookAheadBuf = prSkb->data; + + /* Reset Packet Info */ + kalMemZero(prTxPktInfo, sizeof(TX_PACKET_INFO)); + + /* 4 <0> Obtain Ether Type/Len */ + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[ucEthTypeLenOffset], &u2EtherType); + + /* 4 <1> Skip 802.1Q header (VLAN Tagging) */ + if (u2EtherType == ETH_P_VLAN) { + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_VLAN_EXIST); + ucEthTypeLenOffset += ETH_802_1Q_HEADER_LEN; + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[ucEthTypeLenOffset], &u2EtherType); + } + /* 4 <2> Obtain next protocol pointer */ + pucNextProtocol = &aucLookAheadBuf[ucEthTypeLenOffset + ETHER_TYPE_LEN]; + + /* 4 <3> Handle ethernet format */ + switch (u2EtherType) { + + case ETH_P_IPV4: + /* IPv4 header length check */ + if (u4PacketLen < (ucEthTypeLenOffset + ETHER_TYPE_LEN + IPV4_HDR_LEN)) { + DBGLOG(INIT, WARN, "Invalid IPv4 packet length: %u\n", u4PacketLen); + break; + } +#if DSCP_SUPPORT + if (GLUE_GET_PKT_BSS_IDX(prSkb) != P2P_DEV_BSS_INDEX) { + ucUserPriority = getUpFromDscp( + prGlueInfo, + GLUE_GET_PKT_BSS_IDX(prSkb), + (pucNextProtocol[1] >> 2) & 0x3F); + if (ucUserPriority != 0xFF) + prSkb->priority = ucUserPriority; + } +#endif + kalIPv4FrameClassifier(prGlueInfo, prPacket, pucNextProtocol, prTxPktInfo); + break; + + case ETH_P_ARP: + + kalArpFrameClassifier(prGlueInfo, prPacket, pucNextProtocol, prTxPktInfo); + break; + + case ETH_P_1X: + case ETH_P_PRE_1X: +#if CFG_SUPPORT_WAPI + case ETH_WPI_1X: +#endif + kalSecurityFrameClassifier(prGlueInfo, prPacket, pucNextProtocol, + u2EtherType, prTxPktInfo); + break; + + case ETH_PRO_TDLS: + kalTdlsFrameClassifier(prGlueInfo, prPacket, pucNextProtocol, prTxPktInfo); + break; + + case ETH_P_IPV6: +#if DSCP_SUPPORT + if (GLUE_GET_PKT_BSS_IDX(prSkb) != P2P_DEV_BSS_INDEX) { + UINT_16 u2Tmp = 0; + UINT_8 ucIpTos = 0; + + WLAN_GET_FIELD_BE16(pucNextProtocol, &u2Tmp); + ucIpTos = u2Tmp >> 4; + + ucUserPriority = getUpFromDscp( + prGlueInfo, + GLUE_GET_PKT_BSS_IDX(prSkb), + (ucIpTos >> 2) & 0x3F); + if (ucUserPriority != 0xFF) + prSkb->priority = ucUserPriority; + } +#endif + break; + + default: + /* 4 <4> Handle 802.3 format if LEN <= 1500 */ + if (u2EtherType <= ETH_802_3_MAX_LEN) + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_802_3); + break; + } + + /* 4 <4.1> Check for PAL (BT over Wi-Fi) */ + /* Move to kalBowFrameClassifier */ + + /* 4 <5> Return the value of Priority Parameter. */ + /* prSkb->priority is assigned by Linux wireless utility function(cfg80211_classify8021d) */ + /* at net_dev selection callback (ndo_select_queue) */ + prTxPktInfo->ucPriorityParam = prSkb->priority; + /* 4 <6> Retrieve Packet Information - DA */ + /* Packet Length/ Destination Address */ + prTxPktInfo->u4PacketLen = u4PacketLen; + + kalMemCopy(prTxPktInfo->aucEthDestAddr, aucLookAheadBuf, PARAM_MAC_ADDR_LEN); + + return TRUE; +} /* end of kalQoSFrameClassifier() */ + +BOOLEAN kalGetEthDestAddr(IN P_GLUE_INFO_T prGlueInfo, IN P_NATIVE_PACKET prPacket, OUT PUINT_8 pucEthDestAddr) +{ + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + PUINT_8 aucLookAheadBuf = NULL; + + /* Sanity Check */ + if (!prPacket || !prGlueInfo) + return FALSE; + + aucLookAheadBuf = prSkb->data; + + kalMemCopy(pucEthDestAddr, aucLookAheadBuf, PARAM_MAC_ADDR_LEN); + + return TRUE; +} + +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); + + prGlueInfo->rPendStatus = rOidStatus; + + prGlueInfo->u4OidCompleteFlag = 1; + /* complete ONLY if there are waiters */ + if (!completion_done(&prGlueInfo->rPendComp)) { + complete(&prGlueInfo->rPendComp); + } else { + DBGLOG(INIT, WARN, "SKIP multiple OID complete!\n"); + WARN_ON(TRUE); + } + + /* else let it timeout on kalIoctl entry */ +} + +VOID kalOidClearance(IN P_GLUE_INFO_T prGlueInfo) +{ + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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, OUT PUINT_32 pu4QryInfoLen) +{ + P_GL_IO_REQ_T prIoReq = NULL; + WLAN_STATUS ret = WLAN_STATUS_SUCCESS; + + if (kalIsResetting()) + return WLAN_STATUS_SUCCESS; + + /* GLUE_SPIN_LOCK_DECLARATION(); */ + ASSERT(prGlueInfo); + + /* + * if wait longer than double OID timeout timer, then will show backtrace who held halt lock. + * at this case, we will return kalIoctl failure because tx_thread may be hung + */ + if (kalHaltLock(2 * WLAN_OID_TIMEOUT_THRESHOLD)) + return WLAN_STATUS_FAILURE; + + if (kalIsHalted()) { + kalHaltUnlock(); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + if (down_interruptible(&prGlueInfo->ioctl_sem)) { + kalHaltUnlock(); + return WLAN_STATUS_FAILURE; + } + rHaltCtrl.fgHeldByKalIoctl = TRUE; + /* <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; + + /* <5> Reset the status of pending OID */ + prGlueInfo->rPendStatus = WLAN_STATUS_FAILURE; + /* prGlueInfo->u4TimeoutFlag = 0; */ + prGlueInfo->u4OidCompleteFlag = 0; + + /* <6> Check if we use the command queue */ + prIoReq->u4Flag = fgCmd; + + /* <7> schedule the OID bit */ + set_bit(GLUE_FLAG_OID_BIT, &prGlueInfo->ulFlag); + + /* <7.1> Hold wakelock to ensure OS won't be suspended */ + KAL_WAKE_LOCK_TIMEOUT(prGlueInfo->prAdapter, &prGlueInfo->rTimeoutWakeLock, + MSEC_TO_JIFFIES(WAKE_LOCK_THREAD_WAKEUP_TIMEOUT)); + + /* <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 2 secs */ + 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 + + /* <10> Clear bit for error handling */ + clear_bit(GLUE_FLAG_OID_BIT, &prGlueInfo->ulFlag); + + up(&prGlueInfo->ioctl_sem); + rHaltCtrl.fgHeldByKalIoctl = FALSE; + kalHaltUnlock(); + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to clear all pending security frames +* +* \param prGlueInfo Pointer of GLUE Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalClearSecurityFrames(IN P_GLUE_INFO_T prGlueInfo) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + QUE_T rReturnCmdQue; + P_QUE_T prReturnCmdQue = &rReturnCmdQue; + 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); + + QUEUE_INITIALIZE(prReturnCmdQue); + /* Clear pending security frames in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) { + if (prCmdInfo->pfCmdTimeoutHandler) + prCmdInfo->pfCmdTimeoutHandler(prGlueInfo->prAdapter, prCmdInfo); + else + wlanReleaseCommand(prGlueInfo->prAdapter, prCmdInfo, TX_RESULT_QUEUE_CLEARANCE); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + } else { + QUEUE_INSERT_TAIL(prReturnCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(prCmdQue, prReturnCmdQue); + 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 kalClearSecurityFramesByBssIdx(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucBssIndex) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + QUE_T rReturnCmdQue; + P_QUE_T prReturnCmdQue = &rReturnCmdQue; + 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); + + QUEUE_INITIALIZE(prReturnCmdQue); + /* Clear pending security frames in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + 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->ucBssIndex == ucBssIndex) { + if (prCmdInfo->pfCmdTimeoutHandler) + prCmdInfo->pfCmdTimeoutHandler(prGlueInfo->prAdapter, prCmdInfo); + else + wlanReleaseCommand(prGlueInfo->prAdapter, prCmdInfo, TX_RESULT_QUEUE_CLEARANCE); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + } else { + QUEUE_INSERT_TAIL(prReturnCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(prCmdQue, prReturnCmdQue); + 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; + QUE_T rReturnCmdQue; + P_QUE_T prReturnCmdQue = &rReturnCmdQue; + 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); + + QUEUE_INITIALIZE(prReturnCmdQue); + /* Clear pending management frames in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + 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, TX_RESULT_QUEUE_CLEARANCE); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + } else { + QUEUE_INSERT_TAIL(prReturnCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(prCmdQue, prReturnCmdQue); + 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 kalClearMgmtFramesByBssIdx(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucBssIndex) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + QUE_T rReturnCmdQue; + P_QUE_T prReturnCmdQue = &rReturnCmdQue; + 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); + + QUEUE_INITIALIZE(prReturnCmdQue); + /* Clear pending management frames in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + 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->ucBssIndex == ucBssIndex) { + wlanReleaseCommand(prGlueInfo->prAdapter, prCmdInfo, TX_RESULT_QUEUE_CLEARANCE); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + } else { + QUEUE_INSERT_TAIL(prReturnCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(prCmdQue, prReturnCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); +} /* kalClearMgmtFramesByBssIdx */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to clear all commands in command queue +* \param prGlueInfo Pointer of GLUE Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalClearCommandQueue(IN P_GLUE_INFO_T prGlueInfo) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + QUE_T rReturnCmdQue; + P_QUE_T prReturnCmdQue = &rReturnCmdQue; + 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); + + QUEUE_INITIALIZE(prReturnCmdQue); + + /* Clear ALL in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + if (prCmdInfo->pfCmdTimeoutHandler) + prCmdInfo->pfCmdTimeoutHandler(prGlueInfo->prAdapter, prCmdInfo); + else + wlanReleaseCommand(prGlueInfo->prAdapter, prCmdInfo, TX_RESULT_QUEUE_CLEARANCE); + + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } +} + +UINT_32 kalProcessTxPacket(P_GLUE_INFO_T prGlueInfo, struct sk_buff *prSkb) +{ + UINT_32 u4Status = WLAN_STATUS_SUCCESS; + + if (prSkb == NULL) { + DBGLOG(INIT, WARN, "prSkb == NULL in tx\n"); + return u4Status; + } + + /* Handle security frame */ + if (GLUE_TEST_PKT_FLAG(prSkb, ENUM_PKT_1X)) { + if (wlanProcessSecurityFrame(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb)) { + u4Status = WLAN_STATUS_SUCCESS; + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum); + } else { + u4Status = WLAN_STATUS_RESOURCES; + } + } + /* Handle normal frame */ + else + u4Status = wlanEnqueueTxPacket(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to process Tx request to tx_thread +* +* \param prGlueInfo Pointer of GLUE Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalProcessTxReq(P_GLUE_INFO_T prGlueInfo, PBOOLEAN pfgNeedHwAccess) +{ + P_QUE_T prCmdQue = NULL; + P_QUE_T prTxQueue = NULL; + QUE_T rTempQue; + P_QUE_T prTempQue = &rTempQue; + QUE_T rTempReturnQue; + P_QUE_T prTempReturnQue = &rTempReturnQue; + P_QUE_ENTRY_T prQueueEntry = NULL; + /* struct sk_buff *prSkb = NULL; */ + UINT_32 u4Status; +#if CFG_SUPPORT_MULTITHREAD + UINT_32 u4CmdCount = 0; +#endif + UINT_32 u4TxLoopCount; + + /* for spin lock acquire and release */ + GLUE_SPIN_LOCK_DECLARATION(); + + prTxQueue = &prGlueInfo->rTxQueue; + prCmdQue = &prGlueInfo->rCmdQueue; + + QUEUE_INITIALIZE(prTempQue); + QUEUE_INITIALIZE(prTempReturnQue); + + u4TxLoopCount = prGlueInfo->prAdapter->rWifiVar.u4TxFromOsLoopCount; + + /* Process Mailbox Messages */ + wlanProcessMboxMessage(prGlueInfo->prAdapter); + + /* Process CMD request */ +#if CFG_SUPPORT_MULTITHREAD + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + u4CmdCount = prCmdQue->u4NumElem; + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + if (u4CmdCount > 0) + wlanProcessCommandQueue(prGlueInfo->prAdapter, prCmdQue); +#else + if (prCmdQue->u4NumElem > 0) { + if (*pfgNeedHwAccess == FALSE) { + *pfgNeedHwAccess = TRUE; + + wlanAcquirePowerControl(prGlueInfo->prAdapter); + } + wlanProcessCommandQueue(prGlueInfo->prAdapter, prCmdQue); + } +#endif + + + while (u4TxLoopCount--) { + while (QUEUE_IS_NOT_EMPTY(prTxQueue)) { + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_MOVE_ALL(prTempQue, prTxQueue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + + /* Handle Packet Tx */ + while (QUEUE_IS_NOT_EMPTY(prTempQue)) { + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); + + if (prQueueEntry == NULL) + break; + + u4Status = + kalProcessTxPacket(prGlueInfo, + (struct sk_buff *)GLUE_GET_PKT_DESCRIPTOR(prQueueEntry)); +#if 0 + prSkb = (struct sk_buff *)GLUE_GET_PKT_DESCRIPTOR(prQueueEntry); + ASSERT(prSkb); + if (prSkb == NULL) { + DBGLOG(INIT, WARN, "prSkb == NULL in tx\n"); + continue; + } + + /* Handle security frame */ + if (GLUE_GET_PKT_IS_1X(prSkb)) { + if (wlanProcessSecurityFrame(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb)) { + u4Status = WLAN_STATUS_SUCCESS; + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum); + } else { + u4Status = WLAN_STATUS_RESOURCES; + } + } + /* Handle normal frame */ + else + u4Status = wlanEnqueueTxPacket(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb); +#endif + /* Enqueue packet back into TxQueue if resource is not enough */ + if (u4Status == WLAN_STATUS_RESOURCES) { + QUEUE_INSERT_TAIL(prTempReturnQue, prQueueEntry); + break; + } + } + + if (wlanGetTxPendingFrameCount(prGlueInfo->prAdapter) > 0) + wlanTxPendingPackets(prGlueInfo->prAdapter, pfgNeedHwAccess); + + /* Enqueue packet back into TxQueue if resource is not enough */ + if (QUEUE_IS_NOT_EMPTY(prTempReturnQue)) { + QUEUE_CONCATENATE_QUEUES(prTempReturnQue, prTempQue); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(prTxQueue, prTempReturnQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + + break; + } + } + + if (wlanGetTxPendingFrameCount(prGlueInfo->prAdapter) > 0) + wlanTxPendingPackets(prGlueInfo->prAdapter, pfgNeedHwAccess); + } + +} + +#if CFG_SUPPORT_MULTITHREAD +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param data data pointer to private data of hif_thread +* +* @retval If the function succeeds, the return value is 0. +* Otherwise, an error code is returned. +* +*/ +/*----------------------------------------------------------------------------*/ + +int hif_thread(void *data) +{ + struct net_device *dev = data; + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(dev)); + int ret = 0; + KAL_WAKE_LOCK_T *prHifThreadWakeLock; + + prHifThreadWakeLock = kalMemAlloc(sizeof(KAL_WAKE_LOCK_T), VIR_MEM_TYPE); + if (!prHifThreadWakeLock) { + DBGLOG(INIT, ERROR, "%s MemAlloc Fail\n", KAL_GET_CURRENT_THREAD_NAME()); + return FALSE; + } + + KAL_WAKE_LOCK_INIT(prGlueInfo->prAdapter, prHifThreadWakeLock, "WLAN hif_thread"); + KAL_WAKE_LOCK(prGlueInfo->prAdapter, prHifThreadWakeLock); + + DBGLOG(INIT, INFO, "%s:%u starts running...\n", KAL_GET_CURRENT_THREAD_NAME(), KAL_GET_CURRENT_THREAD_ID()); + + prGlueInfo->u4HifThreadPid = KAL_GET_CURRENT_THREAD_ID(); + + set_user_nice(current, prGlueInfo->prAdapter->rWifiVar.cThreadNice); + + while (TRUE) { + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(INIT, TRACE, "%s should stop now...\n", KAL_GET_CURRENT_THREAD_NAME()); + break; + } + + /* Unlock wakelock if hif_thread going to idle */ + if (!(prGlueInfo->ulFlag & GLUE_FLAG_HIF_PROCESS)) + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, prHifThreadWakeLock); + + /* + * 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 + * + */ + do { + ret = wait_event_interruptible(prGlueInfo->waitq_hif, + ((prGlueInfo->ulFlag & GLUE_FLAG_HIF_PROCESS) != 0)); + } while (ret != 0); + +#if 0 /*defined(MT6797)*/ + nicDisableInterrupt(prGlueInfo->prAdapter); +#endif + if (!KAL_WAKE_LOCK_ACTIVE(prGlueInfo->prAdapter, prHifThreadWakeLock)) + KAL_WAKE_LOCK(prGlueInfo->prAdapter, prHifThreadWakeLock); + + wlanAcquirePowerControl(prGlueInfo->prAdapter); + + /* Handle Interrupt */ + if (test_and_clear_bit(GLUE_FLAG_INT_BIT, &prGlueInfo->ulFlag)) { + /* + * 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; + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + /* Should stop now... skip pending interrupt */ + DBGLOG(INIT, INFO, "ignore pending interrupt\n"); + } else { + /* DBGLOG(INIT, INFO, ("HIF Interrupt!\n")); */ + prGlueInfo->TaskIsrCnt++; + wlanIST(prGlueInfo->prAdapter); + } + } + + /* TX Commands */ + if (test_and_clear_bit(GLUE_FLAG_HIF_TX_CMD_BIT, &prGlueInfo->ulFlag)) + wlanTxCmdMthread(prGlueInfo->prAdapter); + + /* Process TX data packet to HIF */ + if (test_and_clear_bit(GLUE_FLAG_HIF_TX_BIT, &prGlueInfo->ulFlag)) + nicTxMsduQueueMthread(prGlueInfo->prAdapter); + + /* Set FW own */ + if (test_and_clear_bit(GLUE_FLAG_HIF_FW_OWN_BIT, &prGlueInfo->ulFlag)) + prGlueInfo->prAdapter->fgWiFiInSleepyState = TRUE; + + if (test_and_clear_bit(GLUE_FLAG_HAL_MCR_RD_BIT, &prGlueInfo->ulFlag)) { + HAL_MCR_HIF_RD(prGlueInfo->prAdapter, prGlueInfo->u4Register, + prGlueInfo->prRegValue); + complete(&prGlueInfo->rHalRDMCRComp); + } + + if (test_and_clear_bit(GLUE_FLAG_HAL_MCR_WR_BIT, &prGlueInfo->ulFlag)) { + HAL_MCR_HIF_WR(prGlueInfo->prAdapter, prGlueInfo->u4Register, + prGlueInfo->u4RegValue); + complete(&prGlueInfo->rHalWRMCRComp); + } + + /* Read chip status when chip no response */ + if (test_and_clear_bit(GLUE_FLAG_HIF_PRT_HIF_DBG_INFO_BIT, + &prGlueInfo->ulFlag)) { +#if defined(MT6631) + if (prGlueInfo->prAdapter != NULL) + HAL_DUMP_AHB_INFO(prGlueInfo->prAdapter, + prGlueInfo->prAdapter->u2ChipID); +#endif + } + + /* Release to FW own */ + wlanReleasePowerControl(prGlueInfo->prAdapter); +#if defined(MT6631) + nicEnableInterrupt(prGlueInfo->prAdapter); +#endif + } + + complete(&prGlueInfo->rHifHaltComp); + + if (KAL_WAKE_LOCK_ACTIVE(prGlueInfo->prAdapter, prHifThreadWakeLock)) + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, prHifThreadWakeLock); + KAL_WAKE_LOCK_DESTROY(prGlueInfo->prAdapter, prHifThreadWakeLock); + kalMemFree(prHifThreadWakeLock, VIR_MEM_TYPE, sizeof(KAL_WAKE_LOCK_T)); + + DBGLOG(INIT, TRACE, "%s:%u stopped!\n", KAL_GET_CURRENT_THREAD_NAME(), KAL_GET_CURRENT_THREAD_ID()); + + return 0; +} + +int rx_thread(void *data) +{ + struct net_device *dev = data; + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(dev)); + + QUE_T rTempRxQue; + P_QUE_T prTempRxQue = NULL; + P_QUE_ENTRY_T prQueueEntry = NULL; + int ret = 0; + UINT_32 u4LoopCount; + KAL_WAKE_LOCK_T *prRxThreadWakeLock; + + /* for spin lock acquire and release */ + KAL_SPIN_LOCK_DECLARATION(); + prRxThreadWakeLock = kalMemAlloc(sizeof(KAL_WAKE_LOCK_T), VIR_MEM_TYPE); + if (!prRxThreadWakeLock) { + DBGLOG(INIT, ERROR, "%s MemAlloc Fail\n", KAL_GET_CURRENT_THREAD_NAME()); + return FALSE; + } + KAL_WAKE_LOCK_INIT(prGlueInfo->prAdapter, prRxThreadWakeLock, "WLAN rx_thread"); + KAL_WAKE_LOCK(prGlueInfo->prAdapter, prRxThreadWakeLock); + + DBGLOG(INIT, INFO, "%s:%u starts running...\n", KAL_GET_CURRENT_THREAD_NAME(), KAL_GET_CURRENT_THREAD_ID()); + + prGlueInfo->u4RxThreadPid = KAL_GET_CURRENT_THREAD_ID(); + + set_user_nice(current, prGlueInfo->prAdapter->rWifiVar.cThreadNice); + + prTempRxQue = &rTempRxQue; + + while (TRUE) { + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(INIT, TRACE, "%s should stop now...\n", KAL_GET_CURRENT_THREAD_NAME()); + break; + } + + /* Unlock wakelock if rx_thread going to idle */ + if (!(prGlueInfo->ulFlag & GLUE_FLAG_RX_PROCESS)) + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, prRxThreadWakeLock); + + /* + * sleep on waitqueue if no events occurred. + */ + do { + ret = wait_event_interruptible(prGlueInfo->waitq_rx, + ((prGlueInfo->ulFlag & GLUE_FLAG_RX_PROCESS) != 0)); + } while (ret != 0); + + if (!KAL_WAKE_LOCK_ACTIVE(prGlueInfo->prAdapter, prRxThreadWakeLock)) + KAL_WAKE_LOCK(prGlueInfo->prAdapter, prRxThreadWakeLock); + + if (test_and_clear_bit(GLUE_FLAG_RX_TO_OS_BIT, &prGlueInfo->ulFlag)) { + u4LoopCount = prGlueInfo->prAdapter->rWifiVar.u4Rx2OsLoopCount; + + while (u4LoopCount--) { + while (QUEUE_IS_NOT_EMPTY(&prGlueInfo->prAdapter->rRxQueue)) { + QUEUE_INITIALIZE(prTempRxQue); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_RX_TO_OS_QUE); + QUEUE_MOVE_ALL(prTempRxQue, &prGlueInfo->prAdapter->rRxQueue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_RX_TO_OS_QUE); + + while (QUEUE_IS_NOT_EMPTY(prTempRxQue)) { + QUEUE_REMOVE_HEAD(prTempRxQue, prQueueEntry, P_QUE_ENTRY_T); + kalRxIndicateOnePkt(prGlueInfo, + (PVOID) GLUE_GET_PKT_DESCRIPTOR(prQueueEntry)); + } + + KAL_WAKE_LOCK_TIMEOUT(prGlueInfo->prAdapter, &prGlueInfo->rTimeoutWakeLock, + MSEC_TO_JIFFIES(WAKE_LOCK_RX_TIMEOUT)); + } + } + } + } + + complete(&prGlueInfo->rRxHaltComp); + + if (KAL_WAKE_LOCK_ACTIVE(prGlueInfo->prAdapter, prRxThreadWakeLock)) + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, prRxThreadWakeLock); + KAL_WAKE_LOCK_DESTROY(prGlueInfo->prAdapter, prRxThreadWakeLock); + kalMemFree(prRxThreadWakeLock, VIR_MEM_TYPE, sizeof(KAL_WAKE_LOCK_T)); + DBGLOG(INIT, TRACE, "%s:%u stopped!\n", KAL_GET_CURRENT_THREAD_NAME(), KAL_GET_CURRENT_THREAD_ID()); + + return 0; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @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_GL_IO_REQ_T prIoReq = NULL; + int ret = 0; + BOOLEAN fgNeedHwAccess = FALSE; + KAL_WAKE_LOCK_T *prTxThreadWakeLock; + + prTxThreadWakeLock = kalMemAlloc(sizeof(KAL_WAKE_LOCK_T), VIR_MEM_TYPE); + if (!prTxThreadWakeLock) { + DBGLOG(INIT, ERROR, "%s MemAlloc Fail\n", KAL_GET_CURRENT_THREAD_NAME()); + return FALSE; + } +#if CFG_SUPPORT_MULTITHREAD + prGlueInfo->u4TxThreadPid = KAL_GET_CURRENT_THREAD_ID(); +#endif + + current->flags |= PF_NOFREEZE; + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prAdapter); + set_user_nice(current, prGlueInfo->prAdapter->rWifiVar.cThreadNice); + + KAL_WAKE_LOCK_INIT(prGlueInfo->prAdapter, prTxThreadWakeLock, "WLAN tx_thread"); + KAL_WAKE_LOCK(prGlueInfo->prAdapter, prTxThreadWakeLock); + + DBGLOG(INIT, INFO, "%s:%u starts running...\n", KAL_GET_CURRENT_THREAD_NAME(), KAL_GET_CURRENT_THREAD_ID()); + + while (TRUE) { + +#if CFG_ENABLE_WIFI_DIRECT + /*run p2p multicast list work. */ + if (test_and_clear_bit(GLUE_FLAG_SUB_MOD_MULTICAST_BIT, &prGlueInfo->ulFlag)) + p2pSetMulticastListWorkQueueWrapper(prGlueInfo); +#endif + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(INIT, TRACE, "%s should stop now...\n", KAL_GET_CURRENT_THREAD_NAME()); + break; + } + + /* Unlock wakelock if tx_thread going to idle */ + if (!(prGlueInfo->ulFlag & GLUE_FLAG_TX_PROCESS)) + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, prTxThreadWakeLock); + + /* + * 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 + * + */ + do { + ret = wait_event_interruptible(prGlueInfo->waitq, + ((prGlueInfo->ulFlag & GLUE_FLAG_TX_PROCESS) != 0)); + } while (ret != 0); + + if (!KAL_WAKE_LOCK_ACTIVE(prGlueInfo->prAdapter, prTxThreadWakeLock)) + KAL_WAKE_LOCK(prGlueInfo->prAdapter, prTxThreadWakeLock); +#if CFG_DBG_GPIO_PINS + /* TX thread Wake up */ + mtk_wcn_stp_debug_gpio_assert(IDX_TX_THREAD, DBG_TIE_LOW); +#endif + +#if CFG_ENABLE_WIFI_DIRECT + /*run p2p multicast list work. */ + if (test_and_clear_bit(GLUE_FLAG_SUB_MOD_MULTICAST_BIT, &prGlueInfo->ulFlag)) + p2pSetMulticastListWorkQueueWrapper(prGlueInfo); + + if (test_and_clear_bit(GLUE_FLAG_FRAME_FILTER_BIT, &prGlueInfo->ulFlag)) { + p2pFuncUpdateMgmtFrameRegister(prGlueInfo->prAdapter, + prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter); + } +#endif + if (test_and_clear_bit(GLUE_FLAG_FRAME_FILTER_AIS_BIT, &prGlueInfo->ulFlag)) { + P_AIS_FSM_INFO_T prAisFsmInfo = (P_AIS_FSM_INFO_T) NULL; + + prAisFsmInfo = &(prGlueInfo->prAdapter->rWifiVar.rAisFsmInfo); + prAisFsmInfo->u4AisPacketFilter = prGlueInfo->u4OsMgmtFrameFilter; + } + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(INIT, INFO, "%s should stop now...\n", KAL_GET_CURRENT_THREAD_NAME()); + break; + } + + fgNeedHwAccess = FALSE; + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN + if (prGlueInfo->fgEnSdioTestPattern == TRUE) { + if (fgNeedHwAccess == FALSE) { + fgNeedHwAccess = TRUE; + + wlanAcquirePowerControl(prGlueInfo->prAdapter); + } + + if (prGlueInfo->fgIsSdioTestInitialized == FALSE) { + /* enable PRBS mode */ + kalDevRegWrite(prGlueInfo, MCR_WTMCR, 0x00080002); + prGlueInfo->fgIsSdioTestInitialized = TRUE; + } + + if (prGlueInfo->fgSdioReadWriteMode == TRUE) { + /* read test */ + kalDevPortRead(prGlueInfo, + MCR_WTMDR, + 256, + prGlueInfo->aucSdioTestBuffer, sizeof(prGlueInfo->aucSdioTestBuffer)); + } else { + /* write test */ + kalDevPortWrite(prGlueInfo, + MCR_WTMDR, + 172, + prGlueInfo->aucSdioTestBuffer, sizeof(prGlueInfo->aucSdioTestBuffer)); + } + } +#endif +#if CFG_SUPPORT_MULTITHREAD +#else + /* Handle Interrupt */ + if (test_and_clear_bit(GLUE_FLAG_INT_BIT, &prGlueInfo->ulFlag)) { + + if (fgNeedHwAccess == FALSE) { + fgNeedHwAccess = TRUE; + + wlanAcquirePowerControl(prGlueInfo->prAdapter); + } + + /* + * the Wi-Fi interrupt is already disabled in mmc thread, + * so we set the flag only to enable the interrupt later + */ + prGlueInfo->prAdapter->fgIsIntEnable = FALSE; + /* wlanISR(prGlueInfo->prAdapter, TRUE); */ + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + /* Should stop now... skip pending interrupt */ + DBGLOG(INIT, INFO, "ignore pending interrupt\n"); + } else { + prGlueInfo->TaskIsrCnt++; + wlanIST(prGlueInfo->prAdapter); + } + } +#endif + /* Transfer ioctl to OID request */ + do { + if (test_and_clear_bit(GLUE_FLAG_OID_BIT, &prGlueInfo->ulFlag)) { + /* get current prIoReq */ + prIoReq = &(prGlueInfo->OidEntry); + if (prIoReq->fgRead == FALSE) { + 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 ONLY if there are waiters */ + if (!completion_done(&prGlueInfo->rPendComp)) + complete(&prGlueInfo->rPendComp); + else + DBGLOG(INIT, WARN, "SKIP multiple OID complete!\n"); + } 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 (test_and_clear_bit(GLUE_FLAG_TXREQ_BIT, &prGlueInfo->ulFlag)) + kalProcessTxReq(prGlueInfo, &fgNeedHwAccess); +#if CFG_SUPPORT_MULTITHREAD + /* Process RX */ + if (test_and_clear_bit(GLUE_FLAG_RX_BIT, &prGlueInfo->ulFlag)) + nicRxProcessRFBs(prGlueInfo->prAdapter); + if (test_and_clear_bit(GLUE_FLAG_TX_CMD_DONE_BIT, &prGlueInfo->ulFlag)) + wlanTxCmdDoneMthread(prGlueInfo->prAdapter); +#endif + + /* 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 CFG_SUPPORT_MULTITHREAD +#else + if (fgNeedHwAccess == TRUE) + wlanReleasePowerControl(prGlueInfo->prAdapter); +#endif + /* handle cnmTimer time out */ + if (test_and_clear_bit(GLUE_FLAG_TIMEOUT_BIT, &prGlueInfo->ulFlag)) + wlanTimerTimeoutCheck(prGlueInfo->prAdapter); +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN + if (prGlueInfo->fgEnSdioTestPattern == TRUE) + kalSetEvent(prGlueInfo); +#endif + if (test_and_clear_bit(GLUE_FLAG_RESET_CONN_BIT, &prGlueInfo->ulFlag)) { + aisBssBeaconTimeout(prGlueInfo->prAdapter); +#ifdef CFG_SUPPORT_DATA_STALL + mtk_cfg80211_vendor_event_driver_error(prGlueInfo->prAdapter, + EVENT_ARP_NO_RESPONSE, (UINT_16)sizeof(UINT_8)); +#endif + } + +#if CFG_SUPPORT_REPORT_MISC + if (test_and_clear_bit(GLUE_FLAG_REPORT_MISC_BIT, &prGlueInfo->ulFlag)) + wlanExtSrcReportMisc(prGlueInfo); + +#endif + +#if CFG_DBG_GPIO_PINS + /* TX thread go to sleep */ + if (!prGlueInfo->ulFlag) + mtk_wcn_stp_debug_gpio_assert(IDX_TX_THREAD, DBG_TIE_HIGH); +#endif + } + +#if 0 + if (fgNeedHwAccess == TRUE) + wlanReleasePowerControl(prGlueInfo->prAdapter); +#endif + + /* flush the pending TX packets */ + if (GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum) > 0) + kalFlushPendingTxPackets(prGlueInfo); + + /* flush pending security frames */ + if (GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum) > 0) + kalClearSecurityFrames(prGlueInfo); + + /* remove pending oid */ + wlanReleasePendingOid(prGlueInfo->prAdapter, 0); + + complete(&prGlueInfo->rHaltComp); + if (KAL_WAKE_LOCK_ACTIVE(prGlueInfo->prAdapter, prTxThreadWakeLock)) + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, prTxThreadWakeLock); + KAL_WAKE_LOCK_DESTROY(prGlueInfo->prAdapter, prTxThreadWakeLock); + kalMemFree(prTxThreadWakeLock, VIR_MEM_TYPE, sizeof(KAL_WAKE_LOCK_T)); + DBGLOG(INIT, TRACE, "%s:%u stopped!\n", KAL_GET_CURRENT_THREAD_NAME(), KAL_GET_CURRENT_THREAD_ID()); + + 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 (GLUE_GET_REF_CNT(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; + QUE_T rReturnCmdQue; + P_QUE_T prReturnCmdQue = &rReturnCmdQue; + 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); + + QUEUE_INITIALIZE(prReturnCmdQue); + + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + + if (((P_CMD_INFO_T) prQueueEntry)->fgIsOid) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + break; + } + + QUEUE_INSERT_TAIL(prReturnCmdQue, prQueueEntry); + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(prCmdQue, prReturnCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + if (prCmdInfo) { + if (prCmdInfo->pfCmdTimeoutHandler) + prCmdInfo->pfCmdTimeoutHandler(prGlueInfo->prAdapter, prCmdInfo); + else + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_NOT_ACCEPTED); + + prGlueInfo->u4OidCompleteFlag = 1; + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to insert command into prCmdQueue +* +* \param prGlueInfo Pointer of GLUE Data Structure +* prQueueEntry Pointer of queue entry to be inserted +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalEnqueueCommand(IN P_GLUE_INFO_T prGlueInfo, IN P_QUE_ENTRY_T prQueueEntry) +{ + P_QUE_T prCmdQue; + P_CMD_INFO_T prCmdInfo; +#if CFG_DBG_MGT_BUF + struct MEM_TRACK *prMemTrack = NULL; +#endif + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + ASSERT(prQueueEntry); + + prCmdQue = &prGlueInfo->rCmdQueue; + + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + +#if CFG_DBG_MGT_BUF + if (prCmdInfo->pucInfoBuffer && !IS_FROM_BUF(prGlueInfo->prAdapter, prCmdInfo->pucInfoBuffer)) { + prMemTrack = (struct MEM_TRACK *)((PUINT_8)prCmdInfo->pucInfoBuffer + - sizeof(struct MEM_TRACK)); + prMemTrack->u2CmdIdAndWhere = 0; + prMemTrack->u2CmdIdAndWhere |= prCmdInfo->ucCID; + } +#endif + + DBGLOG(TX, LOUD, "EN-Q CMD TYPE[%u] ID[0x%02X] SEQ[%u] to CMD Q\n", + prCmdInfo->eCmdType, prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + + 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); */ + kalSendCompleteAndAwakeQueue(prGlueInfo, pvPacket); + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum); +} + +UINT_32 kalGetTxPendingFrameCount(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return (UINT_32) (GLUE_GET_REF_CNT(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); + + mod_timer(&(prGlueInfo->tickfn), jiffies + u4Interval * HZ / MSEC_PER_SEC); + + return TRUE; /* success */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to cancel +* +* \param[in] prGlueInfo Pointer to GLUE Data Structure +* +* \retval TRUE : Timer has been canceled +* FALAE : Timer doens't exist +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalCancelTimer(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + clear_bit(GLUE_FLAG_TIMEOUT_BIT, &prGlueInfo->ulFlag); + + if (del_timer_sync(&(prGlueInfo->tickfn)) >= 0) + return TRUE; + else + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is a callback function for scanning done +* +* \param[in] prGlueInfo Pointer to GLUE Data Structure +* +* \retval none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID kalScanDone(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_KAL_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN WLAN_STATUS status) +{ + ASSERT(prGlueInfo); + scanLogEssResult(prGlueInfo->prAdapter); + + scanReportBss2Cfg80211(prGlueInfo->prAdapter, BSS_TYPE_INFRASTRUCTURE, NULL); + + /* check for system configuration for generating error message on scan list */ + wlanCheckSystemConfiguration(prGlueInfo->prAdapter); + +#if CFG_SUPPORT_ABORT_SCAN + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_SCAN_COMPLETE, &status, sizeof(WLAN_STATUS)); +#else + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_SCAN_COMPLETE, NULL, 0); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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->ulFlag); + wake_up_interruptible(&prGlueInfo->waitq); + +} + +VOID kalSetEvent(P_GLUE_INFO_T pr) +{ + set_bit(GLUE_FLAG_TXREQ_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq); +} + +VOID kalSetResetConnEvent(P_GLUE_INFO_T pr) +{ + set_bit(GLUE_FLAG_RESET_CONN_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq); +} + +#if CFG_SUPPORT_REPORT_MISC +VOID kalSetReportMiscEvent(P_GLUE_INFO_T pr) +{ + set_bit(GLUE_FLAG_REPORT_MISC_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq); +} +#endif + +#if CFG_SUPPORT_MULTITHREAD +VOID kalSetTxEvent2Hif(P_GLUE_INFO_T pr) +{ + if (!pr->hif_thread) + return; + + KAL_WAKE_LOCK_TIMEOUT(pr->prAdapter, &pr->rTimeoutWakeLock, MSEC_TO_JIFFIES(WAKE_LOCK_THREAD_WAKEUP_TIMEOUT)); + + set_bit(GLUE_FLAG_HIF_TX_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq_hif); +} + +VOID kalSetFwOwnEvent2Hif(P_GLUE_INFO_T pr) +{ + if (!pr->hif_thread) + return; + + KAL_WAKE_LOCK_TIMEOUT(pr->prAdapter, &pr->rTimeoutWakeLock, MSEC_TO_JIFFIES(WAKE_LOCK_THREAD_WAKEUP_TIMEOUT)); + + set_bit(GLUE_FLAG_HIF_FW_OWN_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq_hif); +} + +VOID kalSetTxEvent2Rx(P_GLUE_INFO_T pr) +{ + if (!pr->rx_thread) + return; + + KAL_WAKE_LOCK_TIMEOUT(pr->prAdapter, &pr->rTimeoutWakeLock, MSEC_TO_JIFFIES(WAKE_LOCK_THREAD_WAKEUP_TIMEOUT)); + + set_bit(GLUE_FLAG_RX_TO_OS_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq_rx); +} + +VOID kalSetTxCmdEvent2Hif(P_GLUE_INFO_T pr) +{ + if (!pr->hif_thread) + return; + + KAL_WAKE_LOCK_TIMEOUT(pr->prAdapter, &pr->rTimeoutWakeLock, MSEC_TO_JIFFIES(WAKE_LOCK_THREAD_WAKEUP_TIMEOUT)); + + set_bit(GLUE_FLAG_HIF_TX_CMD_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq_hif); +} +#endif +/*----------------------------------------------------------------------------*/ +/*! +* \brief to check if configuration file (NVRAM/Registry) exists +* +* \param[in] +* prGlueInfo +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalIsConfigurationExist(IN P_GLUE_INFO_T prGlueInfo) +{ +#if !defined(CONFIG_X86) + ASSERT(prGlueInfo); + + return prGlueInfo->fgNvramAvailable; +#else + /* there is no configuration data for x86-linux */ + return FALSE; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Registry information +* +* \param[in] +* prGlueInfo +* +* \return +* Pointer of REG_INFO_T +*/ +/*----------------------------------------------------------------------------*/ +P_REG_INFO_T kalGetConfiguration(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return &(prGlueInfo->rRegInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve version information of corresponding configuration file +* +* \param[in] +* prGlueInfo +* +* \param[out] +* pu2Part1CfgOwnVersion +* pu2Part1CfgPeerVersion +* pu2Part2CfgOwnVersion +* pu2Part2CfgPeerVersion +* +* \return +* NONE +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalGetConfigurationVersion(IN P_GLUE_INFO_T prGlueInfo, + OUT PUINT_16 pu2Part1CfgOwnVersion, + OUT PUINT_16 pu2Part1CfgPeerVersion, + OUT PUINT_16 pu2Part2CfgOwnVersion, OUT PUINT_16 pu2Part2CfgPeerVersion) +{ + ASSERT(prGlueInfo); + + ASSERT(pu2Part1CfgOwnVersion); + ASSERT(pu2Part1CfgPeerVersion); + ASSERT(pu2Part2CfgOwnVersion); + ASSERT(pu2Part2CfgPeerVersion); + + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part1OwnVersion), pu2Part1CfgOwnVersion); + + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part1PeerVersion), pu2Part1CfgPeerVersion); + + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part2OwnVersion), pu2Part2CfgOwnVersion); + + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part2PeerVersion), pu2Part2CfgPeerVersion); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to check if the WPS is active or not +* +* \param[in] +* prGlueInfo +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalWSCGetActiveState(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->fgWpsActive; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief update RSSI and LinkQuality to GLUE layer +* +* \param[in] +* prGlueInfo +* eNetTypeIdx +* cRssi +* cLinkQuality +* +* \return +* None +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalUpdateRSSI(IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_KAL_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN INT_8 cRssi, IN INT_8 cLinkQuality) +{ + struct iw_statistics *pStats = (struct iw_statistics *)NULL; + + ASSERT(prGlueInfo); + + switch (eNetTypeIdx) { + case KAL_NETWORK_TYPE_AIS_INDEX: + pStats = (struct iw_statistics *)(&(prGlueInfo->rIwStats)); + break; +#if CFG_ENABLE_WIFI_DIRECT +#if CFG_SUPPORT_P2P_RSSI_QUERY + case KAL_NETWORK_TYPE_P2P_INDEX: + pStats = (struct iw_statistics *)(&(prGlueInfo->rP2pIwStats)); + break; +#endif +#endif + default: + break; + + } + + if (pStats) { + pStats->qual.qual = cLinkQuality; + pStats->qual.noise = 0; + pStats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_NOISE_UPDATED | IW_QUAL_DBM; + pStats->qual.level = 0x100 + cRssi; + pStats->qual.updated |= IW_QUAL_LEVEL_UPDATED; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Pre-allocate I/O buffer +* +* \param[in] +* none +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalInitIOBuffer(VOID) +{ + UINT_32 u4Size; + + if (CFG_COALESCING_BUFFER_SIZE >= CFG_RX_COALESCING_BUFFER_SIZE) + u4Size = CFG_COALESCING_BUFFER_SIZE + sizeof(ENHANCE_MODE_DATA_STRUCT_T); + else + u4Size = CFG_RX_COALESCING_BUFFER_SIZE + sizeof(ENHANCE_MODE_DATA_STRUCT_T); + + 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) +{ + kfree(pvIoBuffer); + + pvIoBuffer = (PVOID) NULL; + pvIoBufferSize = 0; + pvIoBufferUsage = 0; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Dispatch pre-allocated I/O buffer +* +* \param[in] +* u4AllocSize +* +* \return +* PVOID for pointer of pre-allocated I/O buffer +*/ +/*----------------------------------------------------------------------------*/ +PVOID kalAllocateIOBuffer(IN UINT_32 u4AllocSize) +{ + PVOID ret = (PVOID) NULL; + + if (pvIoBuffer) { + if (u4AllocSize <= (pvIoBufferSize - pvIoBufferUsage)) { + ret = (PVOID) &(((PUINT_8) (pvIoBuffer))[pvIoBufferUsage]); + pvIoBufferUsage += u4AllocSize; + } + } else { + /* fault tolerance */ + ret = (PVOID) kalMemAlloc(u4AllocSize, PHY_MEM_TYPE); + } + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Release all dispatched I/O buffer +* +* \param[in] +* none +* +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalReleaseIOBuffer(IN PVOID pvAddr, IN UINT_32 u4Size) +{ + if (pvIoBuffer) { + pvIoBufferUsage -= u4Size; + } else { + /* fault tolerance */ + kalMemFree(pvAddr, PHY_MEM_TYPE, u4Size); + } +} + +#if (CFG_SUPPORT_DEBUG_STATISTICS == 1) +/*----------------------------------------------------------------------------*/ +/*! +* \brief decode ethernet type from package head +* +* \param[in] +* none +* +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 kalGetPktEtherType(IN PUINT_8 pucPkt) +{ + UINT_16 u2EtherType; + PUINT_8 pucEthBody; + UINT_8 ucResult = ENUM_PKT_FLAG_NUM; + + if (pucPkt == NULL) { + DBGLOG(INIT, WARN, "kalGetPktEtherType pucPkt is null!\n"); + return ucResult; + } + + u2EtherType = (pucPkt[ETH_TYPE_LEN_OFFSET] << 8) | (pucPkt[ETH_TYPE_LEN_OFFSET + 1]); + pucEthBody = &pucPkt[ETH_HLEN]; + + switch (u2EtherType) { + case ETH_P_ARP: + { + DBGLOG(INIT, LOUD, "kalGetPktEtherType : ARP\n"); + ucResult = ENUM_PKT_ARP; + break; + } + case ETH_P_IP: + { + UINT_8 ucIpProto = pucEthBody[9]; /* IP header without options */ + + switch (ucIpProto) { + case IP_PRO_ICMP: + { + DBGLOG(INIT, LOUD, "kalGetPktEtherType : ICMP\n"); + ucResult = ENUM_PKT_ICMP; + break; + } + case IP_PRO_UDP: + { + PUINT_8 pucUdp = &pucEthBody[20]; + UINT_16 u2UdpSrcPort; + UINT_16 u2UdpDstPort; + + u2UdpDstPort = (pucUdp[2] << 8) | pucUdp[3]; + u2UdpSrcPort = (pucUdp[0] << 8) | pucUdp[1]; + + if ((u2UdpDstPort == UDP_PORT_DHCPS) || (u2UdpDstPort == UDP_PORT_DHCPC)) { + DBGLOG(INIT, LOUD, "kalGetPktEtherType : DHCP\n"); + ucResult = ENUM_PKT_DHCP; + break; + } else if (u2UdpSrcPort == UDP_PORT_DNS) { + DBGLOG(INIT, LOUD, "kalGetPktEtherType : DNS\n"); + ucResult = ENUM_PKT_DNS; + break; + } + } + } + break; + } + case ETH_P_PRE_1X: + { + ucResult = ENUM_PKT_PROTECTED_1X; + break; + } + case ETH_P_1X: + { + ucResult = ENUM_PKT_1X; + break; + } + case TDLS_FRM_PROT_TYPE: + { + ucResult = ENUM_PKT_TDLS; + break; + } + default: + DBGLOG(INIT, LOUD, "unSupport pkt type:u2EtherType:0x%x\n" + , u2EtherType); + break; + } + + return ucResult; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalGetChannelList(IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_BAND_T eSpecificBand, + IN UINT_8 ucMaxChannelNum, IN PUINT_8 pucNumOfChannel, IN P_RF_CHANNEL_INFO_T paucChannelList) +{ + rlmDomainGetChnlList(prGlueInfo->prAdapter, eSpecificBand, FALSE, ucMaxChannelNum, + pucNumOfChannel, paucChannelList); +} + +#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; +} +/*----------------------------------------------------------------------------*/ +/*! + * \brief to check if the RSN IE CAP setting from supplicant + * + * \param[in] + * prGlueInfo + * + * \return + * TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +UINT_8 kalGetRsnIeMfpCap(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->rWpaInfo.ucRSNMfpCap; +} + +#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; + INT_32 ret = -1; + UINT_32 u4Flags = 0; + + if (fgDoAppend) + u4Flags = O_APPEND; + + file = kalFileOpen(pucPath, O_WRONLY | O_CREAT | u4Flags, S_IRWXU); + if (file != NULL) { + kalFileWrite(file, 0, pucData, u4Size); + kalFileClose(file); + ret = 0; + } + return ret; +} + +INT_32 kalReadToFile(const PUINT_8 pucPath, PUINT_8 pucData, UINT_32 u4Size, PUINT_32 pu4ReadSize) +{ + struct file *file = NULL; + INT_32 ret = -1; + UINT_32 u4ReadSize = 0; + + DBGLOG(INIT, TRACE, "kalReadToFile() path %s\n", pucPath); + + file = kalFileOpen(pucPath, O_RDONLY, 0); + + if ((file != NULL) && !IS_ERR(file)) { + u4ReadSize = kalFileRead(file, 0, pucData, u4Size); + kalFileClose(file); + if (pu4ReadSize) + *pu4ReadSize = u4ReadSize; + ret = 0; + } + return ret; +} + +UINT_32 kalCheckPath(const PUINT_8 pucPath) +{ + struct file *file = NULL; + UINT_32 u4Flags = 0; + + file = kalFileOpen(pucPath, O_WRONLY | O_CREAT | u4Flags, S_IRWXU); + if (!file) + return -1; + + kalFileClose(file); + return 1; +} + +UINT_32 kalTrunkPath(const PUINT_8 pucPath) +{ + struct file *file = NULL; + UINT_32 u4Flags = O_TRUNC; + + file = kalFileOpen(pucPath, O_WRONLY | O_CREAT | u4Flags, S_IRWXU); + if (!file) + return -1; + + kalFileClose(file); + return 1; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief read request firmware file binary to pucData +* +* \param[in] pucPath file name +* \param[out] pucData Request file output buffer +* \param[in] u4Size read size +* \param[out] pu4ReadSize real read size +* \param[in] dev +* +* \return +* 0 success +* >0 fail +*/ +/*----------------------------------------------------------------------------*/ +INT_32 kalRequestFirmware(const PUINT_8 pucPath, PUINT_8 pucData, UINT_32 u4Size, + PUINT_32 pu4ReadSize, struct device *dev) +{ + const struct firmware *fw = NULL; + int ret = 0; + + /* + * Driver support request_firmware() to get files + * Android path: "/etc/firmware", "/vendor/firmware", "/firmware/image" + * Linux path: "/lib/firmware", "/lib/firmware/update" + */ + ret = request_firmware(&fw, pucPath, dev); + + if (ret != 0) { + DBGLOG(INIT, INFO, "kalRequestFirmware %s Fail, errno[%d]!!\n", pucPath, ret); + pucData = NULL; + *pu4ReadSize = 0; + return ret; + } + + DBGLOG(INIT, INFO, "kalRequestFirmware(): %s OK\n", pucPath); + + if (fw->size < u4Size) + u4Size = fw->size; + + memcpy(pucData, fw->data, u4Size); + if (pu4ReadSize) + *pu4ReadSize = u4Size; + + release_firmware(fw); + + 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, KAL_BAND_2GHZ)); + } else { + prChannel = + ieee80211_get_channel(wiphy, ieee80211_channel_to_frequency(ucChannelNum, KAL_BAND_5GHZ)); + } + + if (prChannel != NULL && prGlueInfo->fgIsRegistered == TRUE) { + struct cfg80211_bss *bss; +#if CFG_SUPPORT_TSF_USING_BOOTTIME + struct ieee80211_mgmt *prMgmtFrame = (struct ieee80211_mgmt *)pucBeaconProbeResp; + + prMgmtFrame->u.beacon.timestamp = kalGetBootTime(); +#endif + + /* indicate to NL80211 subsystem */ + bss = cfg80211_inform_bss_frame(wiphy, + prChannel, + (struct ieee80211_mgmt *)pucBeaconProbeResp, + u4FrameLen, i4SignalStrength * 100, GFP_KERNEL); + + if (!bss) { + /* ToDo:: DBGLOG */ + DBGLOG(REQ, WARN, "cfg80211_inform_bss_frame() returned with NULL\n"); + } else + cfg80211_put_bss(wiphy, bss); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate channel ready +* +* \param[in] +* prGlueInfo +* +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalReadyOnChannel(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, + IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_8 ucChannelNum, IN UINT_32 u4DurationMs) +{ + struct ieee80211_channel *prChannel = NULL; + enum nl80211_channel_type rChannelType; + + /* ucChannelNum = wlanGetChannelNumberByNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_AIS_INDEX); */ + + if (prGlueInfo->fgIsRegistered == TRUE) { + if (ucChannelNum <= 14) { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, KAL_BAND_2GHZ)); + } else { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, KAL_BAND_5GHZ)); + } + + switch (eSco) { + case CHNL_EXT_SCN: + rChannelType = NL80211_CHAN_NO_HT; + break; + + case CHNL_EXT_SCA: + rChannelType = NL80211_CHAN_HT40MINUS; + break; + + case CHNL_EXT_SCB: + rChannelType = NL80211_CHAN_HT40PLUS; + break; + + case CHNL_EXT_RES: + default: + rChannelType = NL80211_CHAN_HT20; + break; + } + + if (prChannel == NULL) + DBGLOG(AIS, WARN, + "prChannel == NULL.\n"); + else + cfg80211_ready_on_channel( + prGlueInfo->prDevHandler->ieee80211_ptr, + u8Cookie, prChannel, + u4DurationMs, GFP_KERNEL); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate channel expiration +* +* \param[in] +* prGlueInfo +* +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalRemainOnChannelExpired(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_8 ucChannelNum) +{ + struct ieee80211_channel *prChannel = NULL; + enum nl80211_channel_type rChannelType; + + ucChannelNum = + wlanGetChannelNumberByNetwork(prGlueInfo->prAdapter, prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex); + + if (prGlueInfo->fgIsRegistered == TRUE) { + if (ucChannelNum <= 14) { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, KAL_BAND_2GHZ)); + } else { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, KAL_BAND_5GHZ)); + } + + switch (eSco) { + case CHNL_EXT_SCN: + rChannelType = NL80211_CHAN_NO_HT; + break; + + case CHNL_EXT_SCA: + rChannelType = NL80211_CHAN_HT40MINUS; + break; + + case CHNL_EXT_SCB: + rChannelType = NL80211_CHAN_HT40PLUS; + break; + + case CHNL_EXT_RES: + default: + rChannelType = NL80211_CHAN_HT20; + break; + } + + if (prChannel == NULL) + DBGLOG(AIS, WARN, + "prChannel == NULL.\n"); + else + cfg80211_remain_on_channel_expired( + prGlueInfo->prDevHandler->ieee80211_ptr, + u8Cookie, prChannel, + GFP_KERNEL); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate Mgmt tx status +* +* \param[in] +* prGlueInfo +* +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalIndicateMgmtTxStatus(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, IN BOOLEAN fgIsAck, IN PUINT_8 pucFrameBuf, IN UINT_32 u4FrameLen) +{ + + do { + if ((prGlueInfo == NULL) + || (pucFrameBuf == NULL) + || (u4FrameLen == 0)) { + DBGLOG(AIS, TRACE, + "Unexpected pointer PARAM. %p, %p, %u.", prGlueInfo, pucFrameBuf, u4FrameLen); + ASSERT(FALSE); + break; + } + + cfg80211_mgmt_tx_status( + prGlueInfo->prDevHandler->ieee80211_ptr, + u8Cookie, pucFrameBuf, u4FrameLen, fgIsAck, GFP_KERNEL); + + } while (FALSE); + +} /* kalIndicateMgmtTxStatus */ + +int kalExternalAuthRequest(IN struct _ADAPTER_T *prAdapter, + IN uint8_t uBssIndex) +{ +#if (defined(NL80211_ATTR_EXTERNAL_AUTH_SUPPORT) \ + || LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) + struct cfg80211_external_auth_params params; + struct _AIS_FSM_INFO_T *prAisFsmInfo = NULL; + struct _BSS_DESC_T *prBssDesc = NULL; + struct net_device *ndev = NULL; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, uBssIndex); + if (!prAisFsmInfo) { + DBGLOG(SAA, WARN, + "SAE auth failed with NULL prAisFsmInfo\n"); + return WLAN_STATUS_INVALID_DATA; + } + + prBssDesc = prAisFsmInfo->prTargetBssDesc; + if (!prBssDesc) { + DBGLOG(SAA, WARN, + "SAE auth failed without prTargetBssDesc\n"); + return WLAN_STATUS_INVALID_DATA; + } + + ndev = prAdapter->prGlueInfo->prDevHandler; + params.action = NL80211_EXTERNAL_AUTH_START; + COPY_MAC_ADDR(params.bssid, prBssDesc->aucBSSID); + COPY_SSID(params.ssid.ssid, params.ssid.ssid_len, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + params.key_mgmt_suite = RSN_CIPHER_SUITE_SAE; + DBGLOG(AIS, INFO, "[WPA3] "MACSTR" SSID:%s Len:%d Act:%d", + params.bssid, params.ssid.ssid, + params.ssid.ssid_len, params.action); + return cfg80211_external_auth_request(ndev, ¶ms, GFP_KERNEL); +#else + return WLAN_STATUS_NOT_SUPPORTED; +#endif +} + +VOID kalIndicateRxMgmtFrame(IN P_GLUE_INFO_T prGlueInfo, IN P_SW_RFB_T prSwRfb) +{ + INT_32 i4Freq = 0; + UINT_8 ucChnlNum = 0; + + do { + if ((prGlueInfo == NULL) || (prSwRfb == NULL)) { + ASSERT(FALSE); + break; + } + + ucChnlNum = (UINT_8) HAL_RX_STATUS_GET_CHNL_NUM(prSwRfb->prRxStatus); + + i4Freq = nicChannelNum2Freq(ucChnlNum) / 1000; + + if (!prGlueInfo->fgIsRegistered) { + DBGLOG(AIS, WARN, + "NetDev Not Ready\n"); + break; + } + + cfg80211_rx_mgmt( + prGlueInfo->prDevHandler->ieee80211_ptr, + i4Freq, /* in MHz */ + RCPI_TO_dBm((UINT_8) + HAL_RX_STATUS_GET_RCPI(prSwRfb->prRxStatusGroup3)), + prSwRfb->pvHeader, prSwRfb->u2PacketLen, GFP_ATOMIC); + } while (FALSE); + +} /* kalIndicateRxMgmtFrame */ + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN +/*----------------------------------------------------------------------------*/ +/*! +* \brief To configure SDIO test pattern mode +* +* \param[in] +* prGlueInfo +* fgEn +* fgRead +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalSetSdioTestPattern(IN P_GLUE_INFO_T prGlueInfo, IN BOOLEAN fgEn, IN BOOLEAN fgRead) +{ + const UINT_8 aucPattern[] = { + 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, + 0xaa, 0x55, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x80, + 0x80, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, + 0x40, 0x40, 0x40, 0xbf, 0x40, 0x40, 0x40, 0xbf, + 0xbf, 0xbf, 0x40, 0xbf, 0xbf, 0xbf, 0x20, 0x20, + 0x20, 0xdf, 0x20, 0x20, 0x20, 0xdf, 0xdf, 0xdf, + 0x20, 0xdf, 0xdf, 0xdf, 0x10, 0x10, 0x10, 0xef, + 0x10, 0x10, 0x10, 0xef, 0xef, 0xef, 0x10, 0xef, + 0xef, 0xef, 0x08, 0x08, 0x08, 0xf7, 0x08, 0x08, + 0x08, 0xf7, 0xf7, 0xf7, 0x08, 0xf7, 0xf7, 0xf7, + 0x04, 0x04, 0x04, 0xfb, 0x04, 0x04, 0x04, 0xfb, + 0xfb, 0xfb, 0x04, 0xfb, 0xfb, 0xfb, 0x02, 0x02, + 0x02, 0xfd, 0x02, 0x02, 0x02, 0xfd, 0xfd, 0xfd, + 0x02, 0xfd, 0xfd, 0xfd, 0x01, 0x01, 0x01, 0xfe, + 0x01, 0x01, 0x01, 0xfe, 0xfe, 0xfe, 0x01, 0xfe, + 0xfe, 0xfe, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff + }; + UINT_32 i; + + ASSERT(prGlueInfo); + + /* access to MCR_WTMCR to engage PRBS mode */ + prGlueInfo->fgEnSdioTestPattern = fgEn; + prGlueInfo->fgSdioReadWriteMode = fgRead; + + if (fgRead == FALSE) { + /* fill buffer for data to be written */ + for (i = 0; i < sizeof(aucPattern); i++) + prGlueInfo->aucSdioTestBuffer[i] = aucPattern[i]; + } + + return TRUE; +} +#endif + +#if (CFG_MET_PACKET_TRACE_SUPPORT == 1) +#define PROC_MET_PROF_CTRL "met_ctrl" +#define PROC_MET_PROF_PORT "met_port" + +struct proc_dir_entry *pMetProcDir; +void *pMetGlobalData; + +#endif +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate scheduled scan results are avilable +* +* \param[in] +* prGlueInfo +* +* \return +* None +*/ +/*----------------------------------------------------------------------------*/ +VOID kalSchedScanResults(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + scanReportBss2Cfg80211(prGlueInfo->prAdapter, BSS_TYPE_INFRASTRUCTURE, NULL); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) + cfg80211_sched_scan_results(priv_to_wiphy(prGlueInfo)); +#else + cfg80211_sched_scan_results(priv_to_wiphy(prGlueInfo), 0); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate scheduled scan has been stopped +* +* \param[in] +* prGlueInfo +* +* \return +* None +*/ +/*----------------------------------------------------------------------------*/ +VOID kalSchedScanStopped(IN P_GLUE_INFO_T prGlueInfo, BOOLEAN fgDriverTriggerd) +{ + /* DBGLOG(SCN, INFO, ("-->kalSchedScanStopped\n" )); */ + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + +#if 1 + /* 1. reset first for newly incoming request */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if (prGlueInfo->prSchedScanRequest != NULL) + prGlueInfo->prSchedScanRequest = NULL; + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); +#endif + DBGLOG(SCN, INFO, "Driver triggerd %d\n", fgDriverTriggerd); + + /* 2. indication to cfg80211 */ + /* + * 20150205 change cfg80211_sched_scan_stopped to work queue to use K thread to send event instead of Tx thread + * due to sched_scan_mtx dead lock issue by Tx thread serves oid cmds and send event in the same time + */ + if (fgDriverTriggerd) + schedule_delayed_work(&sched_workq, 0); +} + +BOOLEAN +kalGetIPv4Address(IN struct net_device *prDev, + IN UINT_32 u4MaxNumOfAddr, OUT PUINT_8 pucIpv4Addrs, OUT PUINT_32 pu4NumOfIpv4Addr) +{ + UINT_32 u4NumIPv4 = 0; + UINT_32 u4AddrLen = IPV4_ADDR_LEN; + struct in_ifaddr *prIfa; + + /* 4 <1> Sanity check of netDevice */ + if (!prDev || !(prDev->ip_ptr) || !((struct in_device *)(prDev->ip_ptr))->ifa_list) { + DBGLOG(INIT, INFO, "IPv4 address is not available for dev(0x%p)\n", prDev); + + *pu4NumOfIpv4Addr = 0; + return FALSE; + } + + prIfa = ((struct in_device *)(prDev->ip_ptr))->ifa_list; + + /* 4 <2> copy the IPv4 address */ + while ((u4NumIPv4 < u4MaxNumOfAddr) && prIfa) { + kalMemCopy(&pucIpv4Addrs[u4NumIPv4 * u4AddrLen], &prIfa->ifa_local, u4AddrLen); + prIfa = prIfa->ifa_next; + + DBGLOG(INIT, INFO, + "IPv4 addr [%u][" IPV4STR "]\n", u4NumIPv4, IPV4TOSTR(&pucIpv4Addrs[u4NumIPv4 * u4AddrLen])); + + u4NumIPv4++; + } + + *pu4NumOfIpv4Addr = u4NumIPv4; + + return TRUE; +} + +BOOLEAN +kalGetIPv6Address(IN struct net_device *prDev, + IN UINT_32 u4MaxNumOfAddr, OUT PUINT_8 pucIpv6Addrs, OUT PUINT_32 pu4NumOfIpv6Addr) +{ + UINT_32 u4NumIPv6 = 0; + UINT_32 u4AddrLen = IPV6_ADDR_LEN; + struct inet6_ifaddr *prIfa; + struct list_head *prAddrList; + + /* 4 <1> Sanity check of netDevice */ + if (!prDev || !(prDev->ip6_ptr)) { + DBGLOG(INIT, INFO, "IPv6 address is not available for dev(0x%p)\n", prDev); + + *pu4NumOfIpv6Addr = 0; + return FALSE; + } + + prAddrList = &((struct inet6_dev *)(prDev->ip6_ptr))->addr_list; + + /* 4 <2> copy the IPv6 address */ + list_for_each_entry(prIfa, prAddrList, if_list) { + kalMemCopy(&pucIpv6Addrs[u4NumIPv6 * u4AddrLen], &prIfa->addr, u4AddrLen); + + DBGLOG(INIT, INFO, + "IPv6 addr [%u][" IPV6STR "]\n", u4NumIPv6, IPV6TOSTR(&pucIpv6Addrs[u4NumIPv6 * u4AddrLen])); + + if ((u4NumIPv6 + 1) >= u4MaxNumOfAddr) + break; + u4NumIPv6++; + } + + *pu4NumOfIpv6Addr = u4NumIPv6; + + return TRUE; +} + +static void wlanNotifyFwSuspend(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgSuspend) +{ + WLAN_STATUS rStatus; + UINT_32 u4SetInfoLen; + + rStatus = kalIoctl(prGlueInfo, + wlanoidNotifyFwSuspend, + (PVOID)&fgSuspend, + sizeof(fgSuspend), + FALSE, + FALSE, + TRUE, + &u4SetInfoLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "wlanNotifyFwSuspend fail\n"); +} + +VOID +kalSetNetAddress(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucBssIdx, + IN PUINT_8 pucIPv4Addr, IN UINT_32 u4NumIPv4Addr, IN PUINT_8 pucIPv6Addr, IN UINT_32 u4NumIPv6Addr) +{ + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_32 u4SetInfoLen = 0; + UINT_32 u4Len = OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress); + P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList; + P_PARAM_NETWORK_ADDRESS prParamNetAddr; + UINT_32 i, u4AddrLen; + + /* 4 <1> Calculate buffer size */ + /* IPv4 */ + u4Len += (((sizeof(PARAM_NETWORK_ADDRESS) - 1) + IPV4_ADDR_LEN) * u4NumIPv4Addr); + /* IPv6 */ + u4Len += (((sizeof(PARAM_NETWORK_ADDRESS) - 1) + IPV6_ADDR_LEN) * u4NumIPv6Addr); + + /* 4 <2> Allocate buffer */ + prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST) kalMemAlloc(u4Len, VIR_MEM_TYPE); + + if (!prParamNetAddrList) { + DBGLOG(INIT, WARN, "Fail to alloc buffer for setting BSS[%u] network address!\n", ucBssIdx); + return; + } + /* 4 <3> Fill up network address */ + prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + prParamNetAddrList->u4AddressCount = 0; + prParamNetAddrList->ucBssIdx = ucBssIdx; + + /* 4 <3.1> Fill up IPv4 address */ + u4AddrLen = IPV4_ADDR_LEN; + prParamNetAddr = prParamNetAddrList->arAddress; + for (i = 0; i < u4NumIPv4Addr; i++) { + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + prParamNetAddr->u2AddressLength = u4AddrLen; + kalMemCopy(prParamNetAddr->aucAddress, &pucIPv4Addr[i * u4AddrLen], u4AddrLen); + + prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prParamNetAddr + + (ULONG) (u4AddrLen + + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + prParamNetAddrList->u4AddressCount += u4NumIPv4Addr; + + /* 4 <3.2> Fill up IPv6 address */ + u4AddrLen = IPV6_ADDR_LEN; + for (i = 0; i < u4NumIPv6Addr; i++) { + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + prParamNetAddr->u2AddressLength = u4AddrLen; + kalMemCopy(prParamNetAddr->aucAddress, &pucIPv6Addr[i * u4AddrLen], u4AddrLen); + + prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prParamNetAddr + + (ULONG) (u4AddrLen + + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + prParamNetAddrList->u4AddressCount += u4NumIPv6Addr; + + /* 4 <4> IOCTL to tx_thread */ + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNetworkAddress, + (PVOID) prParamNetAddrList, u4Len, FALSE, FALSE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "%s: Fail to set network address\n", __func__); + + kalMemFree(prParamNetAddrList, VIR_MEM_TYPE, u4Len); + +} + +VOID kalSetNetAddressFromInterface(IN P_GLUE_INFO_T prGlueInfo, IN struct net_device *prDev, IN BOOLEAN fgSet) +{ + UINT_32 u4NumIPv4, u4NumIPv6; + UINT_8 pucIPv4Addr[IPV4_ADDR_LEN * CFG_PF_ARP_NS_MAX_NUM], pucIPv6Addr[IPV6_ADDR_LEN * CFG_PF_ARP_NS_MAX_NUM]; + P_NETDEV_PRIVATE_GLUE_INFO prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) NULL; + + prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(prDev); + + if (prNetDevPrivate->prGlueInfo != prGlueInfo) + DBGLOG(REQ, WARN, "%s: unexpected prGlueInfo(0x%p)!\n", __func__, prNetDevPrivate->prGlueInfo); + + u4NumIPv4 = 0; + u4NumIPv6 = 0; + + if (fgSet) { + kalGetIPv4Address(prDev, CFG_PF_ARP_NS_MAX_NUM, pucIPv4Addr, &u4NumIPv4); + kalGetIPv6Address(prDev, CFG_PF_ARP_NS_MAX_NUM, pucIPv6Addr, &u4NumIPv6); + wlanNotifyFwSuspend(prGlueInfo, TRUE); + } else { + wlanNotifyFwSuspend(prGlueInfo, FALSE); + } + + if (u4NumIPv4 + u4NumIPv6 > CFG_PF_ARP_NS_MAX_NUM) { + if (u4NumIPv4 >= CFG_PF_ARP_NS_MAX_NUM) { + u4NumIPv4 = CFG_PF_ARP_NS_MAX_NUM; + u4NumIPv6 = 0; + } else { + u4NumIPv6 = CFG_PF_ARP_NS_MAX_NUM - u4NumIPv4; + } + } + + kalSetNetAddress(prGlueInfo, prNetDevPrivate->ucBssIdx, pucIPv4Addr, u4NumIPv4, pucIPv6Addr, u4NumIPv6); +} + +#if CFG_MET_PACKET_TRACE_SUPPORT + +BOOLEAN kalMetCheckProfilingPacket(IN P_GLUE_INFO_T prGlueInfo, IN P_NATIVE_PACKET prPacket) +{ + UINT_32 u4PacketLen; + UINT_16 u2EtherTypeLen; + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + PUINT_8 aucLookAheadBuf = NULL; + UINT_8 ucEthTypeLenOffset = ETHER_HEADER_LEN - ETHER_TYPE_LEN; + PUINT_8 pucNextProtocol = NULL; + + u4PacketLen = prSkb->len; + + if (u4PacketLen < ETHER_HEADER_LEN) { + DBGLOG(INIT, WARN, "Invalid Ether packet length: %u\n", u4PacketLen); + return FALSE; + } + + aucLookAheadBuf = prSkb->data; + + /* 4 <0> Obtain Ether Type/Len */ + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[ucEthTypeLenOffset], &u2EtherTypeLen); + + /* 4 <1> Skip 802.1Q header (VLAN Tagging) */ + if (u2EtherTypeLen == ETH_P_VLAN) { + ucEthTypeLenOffset += ETH_802_1Q_HEADER_LEN; + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[ucEthTypeLenOffset], &u2EtherTypeLen); + } + /* 4 <2> Obtain next protocol pointer */ + pucNextProtocol = &aucLookAheadBuf[ucEthTypeLenOffset + ETHER_TYPE_LEN]; + + /* 4 <3> Handle ethernet format */ + switch (u2EtherTypeLen) { + + /* IPv4 */ + case ETH_P_IPV4: + { + PUINT_8 pucIpHdr = pucNextProtocol; + UINT_8 ucIpVersion; + + /* IPv4 header length check */ + if (u4PacketLen < (ucEthTypeLenOffset + ETHER_TYPE_LEN + IPV4_HDR_LEN)) { + DBGLOG(INIT, WARN, "Invalid IPv4 packet length: %u\n", u4PacketLen); + return FALSE; + } + + /* IPv4 version check */ + ucIpVersion = (pucIpHdr[0] & IP_VERSION_MASK) >> IP_VERSION_OFFSET; + if (ucIpVersion != IP_VERSION_4) { + DBGLOG(INIT, WARN, "Invalid IPv4 packet version: %d\n", ucIpVersion); + return FALSE; + } + + if (pucIpHdr[IPV4_HDR_IP_PROTOCOL_OFFSET] == IP_PROTOCOL_UDP) { + PUINT_8 pucUdpHdr = &pucIpHdr[IPV4_HDR_LEN]; + UINT_16 u2UdpDstPort; + UINT_16 u2UdpSrcPort; + + /* Get UDP DST port */ + WLAN_GET_FIELD_BE16(&pucUdpHdr[UDP_HDR_DST_PORT_OFFSET], &u2UdpDstPort); + + /* Get UDP SRC port */ + WLAN_GET_FIELD_BE16(&pucUdpHdr[UDP_HDR_SRC_PORT_OFFSET], &u2UdpSrcPort); + + if (u2UdpSrcPort == prGlueInfo->u2MetUdpPort) { + UINT_16 u2IpId; + + /* Store IP ID for Tag */ + WLAN_GET_FIELD_BE16(&pucIpHdr[IPV4_HDR_IP_IDENTIFICATION_OFFSET], &u2IpId); +#if 0 + DBGLOG(INIT, INFO, "TX PKT PROTOCOL[0x%x] UDP DST port[%u] IP_ID[%u]\n", + pucIpHdr[IPV4_HDR_IP_PROTOCOL_OFFSET], u2UdpDstPort, + u2IpId); +#endif + GLUE_SET_PKT_IP_ID(prPacket, u2IpId); + + return TRUE; + } + } + } + break; + + default: + break; + } + + return FALSE; +} + +static unsigned long __read_mostly tracing_mark_write_addr; +static inline void __mt_update_tracing_mark_write_addr(void) +{ + if (unlikely(tracing_mark_write_addr == 0)) + tracing_mark_write_addr = kallsyms_lookup_name("tracing_mark_write"); +} + +VOID kalMetTagPacket(IN P_GLUE_INFO_T prGlueInfo, IN P_NATIVE_PACKET prPacket, IN ENUM_TX_PROFILING_TAG_T eTag) +{ + if (!prGlueInfo->fgMetProfilingEn) + return; + + switch (eTag) { + case TX_PROF_TAG_OS_TO_DRV: + if (kalMetCheckProfilingPacket(prGlueInfo, prPacket)) { + __mt_update_tracing_mark_write_addr(); +#ifdef CONFIG_TRACING /* #if CFG_MET_PACKET_TRACE_SUPPORT */ +#ifndef MTK_WCN_BUILT_IN_DRIVER + KERNEL_event_trace_printk(tracing_mark_write_addr, "S|%d|%s|%d\n", current->tgid, "WIFI-CHIP", + GLUE_GET_PKT_IP_ID(prPacket)); +#else + event_trace_printk(tracing_mark_write_addr, "S|%d|%s|%d\n", current->tgid, "WIFI-CHIP", + GLUE_GET_PKT_IP_ID(prPacket)); +#endif +#endif + GLUE_SET_PKT_FLAG_PROF_MET(prPacket); + } + break; + + case TX_PROF_TAG_DRV_TX_DONE: + if (GLUE_GET_PKT_IS_PROF_MET(prPacket)) { + __mt_update_tracing_mark_write_addr(); +#ifdef CONFIG_TRACING /* #if CFG_MET_PACKET_TRACE_SUPPORT */ +#ifndef MTK_WCN_BUILT_IN_DRIVER + KERNEL_event_trace_printk(tracing_mark_write_addr, "F|%d|%s|%d\n", current->tgid, "WIFI-CHIP", + GLUE_GET_PKT_IP_ID(prPacket)); +#else + event_trace_printk(tracing_mark_write_addr, "F|%d|%s|%d\n", current->tgid, "WIFI-CHIP", + GLUE_GET_PKT_IP_ID(prPacket)); +#endif +#endif + } + break; + + case TX_PROF_TAG_MAC_TX_DONE: + break; + + default: + break; + } +} + +VOID kalMetInit(IN P_GLUE_INFO_T prGlueInfo) +{ + prGlueInfo->fgMetProfilingEn = FALSE; + prGlueInfo->u2MetUdpPort = 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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. +*/ +/*----------------------------------------------------------------------------*/ +#if 0 +static ssize_t kalMetWriteProcfs(struct file *file, const char __user *buffer, size_t count, loff_t *off) +{ + char acBuf[128 + 1]; /* + 1 for "\0" */ + UINT_32 u4CopySize; + int u16MetUdpPort; + int u8MetProfEnable; + + IN P_GLUE_INFO_T prGlueInfo; + ssize_t result; + + u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + result = copy_from_user(acBuf, buffer, u4CopySize); + acBuf[u4CopySize] = '\0'; + + if (sscanf(acBuf, " %d %d", &u8MetProfEnable, &u16MetUdpPort) == 2) { + DBGLOG(INIT, INFO, + "MET_PROF: Write MET PROC Enable=%d UDP_PORT=%d\n", u8MetProfEnable, u16MetUdpPort); + } + if (pMetGlobalData != NULL) { + prGlueInfo = (P_GLUE_INFO_T) pMetGlobalData; + prGlueInfo->fgMetProfilingEn = (BOOLEAN) u8MetProfEnable; + prGlueInfo->u2MetUdpPort = (UINT_16) u16MetUdpPort; + } + return count; +} +#endif +static ssize_t kalMetCtrlWriteProcfs(struct file *file, const char __user *buffer, size_t count, loff_t *off) +{ + char acBuf[128 + 1]; /* + 1 for "\0" */ + UINT_32 u4CopySize; + int u8MetProfEnable; + ssize_t result; + + IN P_GLUE_INFO_T prGlueInfo; + + u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + result = copy_from_user(acBuf, buffer, u4CopySize); + acBuf[u4CopySize] = '\0'; + + if (sscanf(acBuf, " %d", &u8MetProfEnable) == 1) { + DBGLOG(INIT, INFO, + "MET_PROF: Write MET PROC Enable=%d\n", u8MetProfEnable); + } + if (pMetGlobalData != NULL) { + prGlueInfo = (P_GLUE_INFO_T) pMetGlobalData; + prGlueInfo->fgMetProfilingEn = (UINT_8) u8MetProfEnable; + } + return count; +} + +static ssize_t kalMetPortWriteProcfs(struct file *file, const char __user *buffer, size_t count, loff_t *off) +{ + char acBuf[128 + 1]; /* + 1 for "\0" */ + UINT_32 u4CopySize; + int u16MetUdpPort; + ssize_t result; + + IN P_GLUE_INFO_T prGlueInfo; + + u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + result = copy_from_user(acBuf, buffer, u4CopySize); + acBuf[u4CopySize] = '\0'; + + if (sscanf(acBuf, " %d", &u16MetUdpPort) == 1) { + DBGLOG(INIT, INFO, + "MET_PROF: Write MET PROC UDP_PORT=%d\n", u16MetUdpPort); + } + if (pMetGlobalData != NULL) { + prGlueInfo = (P_GLUE_INFO_T) pMetGlobalData; + prGlueInfo->u2MetUdpPort = (UINT_16) u16MetUdpPort; + } + return count; +} + +#if 0 +const struct file_operations rMetProcFops = { +.write = kalMetWriteProcfs +}; +#endif +const struct file_operations rMetProcCtrlFops = { +.write = kalMetCtrlWriteProcfs +}; + +const struct file_operations rMetProcPortFops = { +.write = kalMetPortWriteProcfs +}; + +int kalMetInitProcfs(IN P_GLUE_INFO_T prGlueInfo) +{ + /* struct proc_dir_entry *pMetProcDir; */ + if (init_net.proc_net == (struct proc_dir_entry *)NULL) { + DBGLOG(INIT, ERROR, "init proc fs fail: proc_net == NULL\n"); + return -ENOENT; + } + /* + * Directory: Root (/proc/net/wlan0) + */ + pMetProcDir = proc_mkdir("wlan0", init_net.proc_net); + if (pMetProcDir == NULL) + return -ENOENT; + /* + * /proc/net/wlan0 + * |-- met_ctrl (PROC_MET_PROF_CTRL) + */ + /* proc_create(PROC_MET_PROF_CTRL, 0x0644, pMetProcDir, &rMetProcFops); */ + proc_create(PROC_MET_PROF_CTRL, 0, pMetProcDir, &rMetProcCtrlFops); + proc_create(PROC_MET_PROF_PORT, 0, pMetProcDir, &rMetProcPortFops); + + pMetGlobalData = (void *)prGlueInfo; + + return 0; +} + +int kalMetRemoveProcfs(void) +{ + + if (init_net.proc_net == (struct proc_dir_entry *)NULL) { + DBGLOG(INIT, WARN, "remove proc fs fail: proc_net == NULL\n"); + return -ENOENT; + } + /* + * remove_proc_entry(PROC_MET_PROF_CTRL, pMetProcDir); + * remove_proc_entry(PROC_MET_PROF_PORT, pMetProcDir); + */ + /* remove root directory (proc/net/wlan0) */ + remove_proc_subtree("wlan0", init_net.proc_net); + /* clear MetGlobalData */ + pMetGlobalData = NULL; + + return 0; +} + +#endif +#if CFG_SUPPORT_AGPS_ASSIST +BOOLEAN kalIndicateAgpsNotify(P_ADAPTER_T prAdapter, UINT_8 cmd, PUINT_8 data, UINT_16 dataLen) +{ + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + + struct sk_buff *skb = cfg80211_testmode_alloc_event_skb(priv_to_wiphy(prGlueInfo), + dataLen, GFP_KERNEL); + if (!skb) { + DBGLOG(AIS, TRACE, "kalIndicateAgpsNotify: alloc skb failed\n"); + return FALSE; + } + /* DBGLOG(CCX, INFO, ("WLAN_STATUS_AGPS_NOTIFY, cmd=%d\n", cmd)); */ + if (unlikely(nla_put(skb, MTK_ATTR_AGPS_CMD, sizeof(cmd), &cmd) < 0)) + goto nla_put_failure; + if (dataLen > 0 && data && unlikely(nla_put(skb, MTK_ATTR_AGPS_DATA, dataLen, data) < 0)) + goto nla_put_failure; + if (unlikely(nla_put(skb, MTK_ATTR_AGPS_IFINDEX, sizeof(UINT_32), &prGlueInfo->prDevHandler->ifindex) < 0)) + goto nla_put_failure; + /* currently, the ifname maybe wlan0, p2p0, so the maximum name length will be 5 bytes */ + if (unlikely(nla_put(skb, MTK_ATTR_AGPS_IFNAME, 5, prGlueInfo->prDevHandler->name) < 0)) + goto nla_put_failure; + cfg80211_testmode_event(skb, GFP_KERNEL); + return TRUE; + +nla_put_failure: + kfree_skb(skb); + return FALSE; +} +#endif + +UINT_64 kalGetBootTime(void) +{ + struct timespec ts; + UINT_64 bootTime = 0; + + get_monotonic_boottime(&ts); + bootTime = ts.tv_sec; + bootTime *= USEC_PER_SEC; + bootTime += ts.tv_nsec / NSEC_PER_USEC; + return bootTime; +} + +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG + /* #if 0can not link this function defined by spm, so remove it. */ +/* if SPM is not implement this function, we will use this default one */ +wake_reason_t __weak slp_get_wake_reason(VOID) +{ + DBGLOG(INIT, WARN, "SPM didn't define this function!\n"); + return WR_NONE; +} + +#ifdef MT6630 +/* if SPM is not implement this function, we will use this default one */ +bool __weak spm_read_eint_status(UINT_32 u4EintNum) +{ + DBGLOG(INIT, WARN, "SPM didn't define this function!\n"); + return FALSE; +} +static inline BOOLEAN spm_check_wakesrc(VOID) +{ + return spm_read_eint_status(4); +} + +#else +/* if SPM is not implement this function, we will use this default one */ +UINT_32 __weak spm_get_last_wakeup_src(VOID) +{ + return 0; +} +static inline BOOLEAN spm_check_wakesrc(VOID) +{ + return !!(spm_get_last_wakeup_src() & WAKE_SRC_CONN2AP); +} +#endif + +BOOLEAN kalIsWakeupByWlan(P_ADAPTER_T prAdapter) +{ + /* + * SUSPEND_FLAG_FOR_WAKEUP_REASON is set means system has suspended, but may be failed + * duo to some driver suspend failed. so we need help of function slp_get_wake_reason + */ + if (test_and_clear_bit(SUSPEND_FLAG_FOR_WAKEUP_REASON, &prAdapter->ulSuspendFlag) == 0) + return FALSE; + /* + * if slp_get_wake_reason or spm_get_last_wakeup_src is NULL, it means SPM module didn't implement + * it. then we should return FALSE always. otherwise, if slp_get_wake_reason returns WR_WAKE_SRC, + * then it means the host is suspend successfully. + */ + if (slp_get_wake_reason() != WR_WAKE_SRC) + return FALSE; + /* + * spm_get_last_wakeup_src will returns the last wakeup source, + * WAKE_SRC_CONN2AP is connsys + */ + return spm_check_wakesrc(); +} +#endif + +INT_32 kalHaltLock(UINT_32 waitMs) +{ + INT_32 i4Ret = 0; + + if (waitMs) { + i4Ret = down_timeout(&rHaltCtrl.lock, MSEC_TO_JIFFIES(waitMs)); + if (!i4Ret) + goto success; + if (i4Ret != -ETIME) + return i4Ret; + if (rHaltCtrl.fgHeldByKalIoctl) { + P_GLUE_INFO_T prGlueInfo = wlanGetGlueInfo(); + + DBGLOG(INIT, ERROR, + "kalIoctl was executed longer than %u ms, show backtrace of tx_thread!\n", + kalGetTimeTick() - rHaltCtrl.u4HoldStart); + if (prGlueInfo) +#ifndef MTK_WCN_BUILT_IN_DRIVER + KERNEL_show_stack(prGlueInfo->main_thread, NULL); +#else + show_stack(prGlueInfo->main_thread, NULL); +#endif + } else { + DBGLOG(INIT, ERROR, "halt lock held by %s pid %d longer than %u ms!\n", + rHaltCtrl.owner->comm, rHaltCtrl.owner->pid, + kalGetTimeTick() - rHaltCtrl.u4HoldStart); +#ifndef MTK_WCN_BUILT_IN_DRIVER + KERNEL_show_stack(rHaltCtrl.owner, NULL); +#else + show_stack(rHaltCtrl.owner, NULL); +#endif + } + return i4Ret; + } + down(&rHaltCtrl.lock); +success: + rHaltCtrl.owner = current; + rHaltCtrl.u4HoldStart = kalGetTimeTick(); + return 0; +} + +INT_32 kalHaltTryLock(VOID) +{ + INT_32 i4Ret = 0; + + i4Ret = down_trylock(&rHaltCtrl.lock); + if (i4Ret) + return i4Ret; + rHaltCtrl.owner = current; + rHaltCtrl.u4HoldStart = kalGetTimeTick(); + return 0; +} + +VOID kalHaltUnlock(VOID) +{ + if (kalGetTimeTick() - rHaltCtrl.u4HoldStart > WLAN_OID_TIMEOUT_THRESHOLD * 2 && + rHaltCtrl.owner) + DBGLOG(INIT, ERROR, "process %s pid %d hold halt lock longer than 4s!\n", + rHaltCtrl.owner->comm, rHaltCtrl.owner->pid); + rHaltCtrl.owner = NULL; + up(&rHaltCtrl.lock); +} + +VOID kalSetHalted(BOOLEAN fgHalt) +{ + rHaltCtrl.fgHalt = fgHalt; +} + +BOOLEAN kalIsHalted(VOID) +{ + return rHaltCtrl.fgHalt; +} +#ifdef MT6797 +VOID kalDumpWTBL(P_ADAPTER_T prAdapter) +{ + UINT_8 i = 0; + UINT_32 au4WTBL[4] = {0,}; + P_WLAN_TABLE_T prWtbl = prAdapter->rWifiVar.arWtbl; + PUINT_8 pucWtblBaseAddr = NULL; + + pucWtblBaseAddr = glRemapConnsysAddr(prAdapter->prGlueInfo, 0x60320000, 1024); + if (!pucWtblBaseAddr) + return; + + for (i = 0; i < WTBL_SIZE; i++) + if (prWtbl[i].ucUsed) { + au4WTBL[0] = CONNSYS_REG_READ(pucWtblBaseAddr, i*0x20); + au4WTBL[1] = CONNSYS_REG_READ(pucWtblBaseAddr, i*0x20+4); + au4WTBL[2] = CONNSYS_REG_READ(pucWtblBaseAddr, i*0x20+8); + au4WTBL[3] = CONNSYS_REG_READ(pucWtblBaseAddr, i*0x20+12); + DBGLOG(RX, ERROR, "content of wlan index %d:0x%08x%08x%08x%08x\n", + i, au4WTBL[0], au4WTBL[1], au4WTBL[2], au4WTBL[3]); + } + glUnmapConnsysAddr(prAdapter->prGlueInfo, pucWtblBaseAddr, 0x60320000); +} +#endif + +#if 0 +VOID kalPerMonDump(IN P_GLUE_INFO_T prGlueInfo) +{ + struct PERF_MONITOR_T *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + DBGLOG(SW4, WARN, "ulPerfMonFlag:0x%lx\n", prPerMonitor->ulPerfMonFlag); + DBGLOG(SW4, WARN, "ulLastTxBytes:%ld\n", prPerMonitor->ulLastTxBytes); + DBGLOG(SW4, WARN, "ulLastRxBytes:%ld\n", prPerMonitor->ulLastRxBytes); + DBGLOG(SW4, WARN, "ulP2PLastTxBytes:%ld\n", prPerMonitor->ulP2PLastTxBytes); + DBGLOG(SW4, WARN, "ulP2PLastRxBytes:%ld\n", prPerMonitor->ulP2PLastRxBytes); + DBGLOG(SW4, WARN, "ulThroughput:%ld\n", prPerMonitor->ulThroughput); + DBGLOG(SW4, WARN, "u4UpdatePeriod:%d\n", prPerMonitor->u4UpdatePeriod); + DBGLOG(SW4, WARN, "u4TarPerfLevel:%d\n", prPerMonitor->u4TarPerfLevel); + DBGLOG(SW4, WARN, "u4CurrPerfLevel:%d\n", prPerMonitor->u4CurrPerfLevel); + DBGLOG(SW4, WARN, "netStats tx_bytes:%ld\n", prGlueInfo->prDevHandler->stats.tx_bytes); + DBGLOG(SW4, WARN, "netStats tx_bytes:%ld\n", prGlueInfo->prDevHandler->stats.rx_bytes); + DBGLOG(SW4, WARN, "p2p netStats tx_bytes:%ld\n", prGlueInfo->prP2PInfo->prDevHandler->stats.tx_bytes); + DBGLOG(SW4, WARN, "p2p netStats tx_bytes:%ld\n", prGlueInfo->prP2PInfo->prDevHandler->stats.rx_bytes); +} +#endif + +inline INT_32 kalPerMonInit(IN P_GLUE_INFO_T prGlueInfo) +{ + struct PERF_MONITOR_T *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + DBGLOG(SW4, TRACE, "enter %s\n", __func__); + if (KAL_TEST_BIT(PERF_MON_RUNNING_BIT, prPerMonitor->ulPerfMonFlag)) + DBGLOG(SW4, WARN, "abnormal, perf monitory already running\n"); + KAL_CLR_BIT(PERF_MON_RUNNING_BIT, prPerMonitor->ulPerfMonFlag); + KAL_CLR_BIT(PERF_MON_DISABLE_BIT, prPerMonitor->ulPerfMonFlag); + KAL_SET_BIT(PERF_MON_STOP_BIT, prPerMonitor->ulPerfMonFlag); + prPerMonitor->u4UpdatePeriod = 1000; + + cnmTimerInitTimer(prGlueInfo->prAdapter, + &prPerMonitor->rPerfMonTimer, + (PFN_MGMT_TIMEOUT_FUNC) kalPerMonHandler, (ULONG) NULL); + DBGLOG(SW4, TRACE, "exit %s\n", __func__); + return 0; +} + +inline INT_32 kalPerMonDisable(IN P_GLUE_INFO_T prGlueInfo) +{ + struct PERF_MONITOR_T *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + + DBGLOG(SW4, TRACE, "enter %s\n", __func__); + if (KAL_TEST_BIT(PERF_MON_RUNNING_BIT, prPerMonitor->ulPerfMonFlag)) { + DBGLOG(SW4, TRACE, "need to stop before disable\n"); + kalPerMonStop(prGlueInfo); + } + KAL_SET_BIT(PERF_MON_DISABLE_BIT, prPerMonitor->ulPerfMonFlag); + DBGLOG(SW4, TRACE, "exit %s\n", __func__); + return 0; +} + +inline INT_32 kalPerMonEnable(IN P_GLUE_INFO_T prGlueInfo) +{ + struct PERF_MONITOR_T *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + + DBGLOG(SW4, INFO, "enter %s\n", __func__); + KAL_CLR_BIT(PERF_MON_DISABLE_BIT, prPerMonitor->ulPerfMonFlag); + DBGLOG(SW4, TRACE, "exit %s\n", __func__); + return 0; +} + +inline INT_32 kalPerMonStart(IN P_GLUE_INFO_T prGlueInfo) +{ + struct PERF_MONITOR_T *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + DBGLOG(SW4, TRACE, "enter %s\n", __func__); + + if (!wlan_perf_monitor_force_enable && + (wlan_fb_power_down || prGlueInfo->fgIsInSuspendMode) && + !KAL_TEST_BIT(PERF_MON_DISABLE_BIT, prPerMonitor->ulPerfMonFlag)) { + /* + * Remove this to prevent KE, kalPerMonStart might be called in soft irq + * kalBoostCpu might call flush_work which will use wait_for_completion + * then KE will happen in this case + * Simply don't start performance monitor here + */ + /*kalPerMonDisable(prGlueInfo);*/ + return 0; + } + if (KAL_TEST_BIT(PERF_MON_DISABLE_BIT, prPerMonitor->ulPerfMonFlag) || + KAL_TEST_BIT(PERF_MON_RUNNING_BIT, prPerMonitor->ulPerfMonFlag)) + return 0; + + prPerMonitor->ulLastRxBytes = 0; + prPerMonitor->ulLastTxBytes = 0; + prPerMonitor->ulP2PLastRxBytes = 0; + prPerMonitor->ulP2PLastTxBytes = 0; + prPerMonitor->ulThroughput = 0; + prPerMonitor->u4CurrPerfLevel = 0; + prPerMonitor->u4TarPerfLevel = 0; + + cnmTimerStartTimer(prGlueInfo->prAdapter, &prPerMonitor->rPerfMonTimer, prPerMonitor->u4UpdatePeriod); + KAL_SET_BIT(PERF_MON_RUNNING_BIT, prPerMonitor->ulPerfMonFlag); + KAL_CLR_BIT(PERF_MON_STOP_BIT, prPerMonitor->ulPerfMonFlag); + DBGLOG(SW4, INFO, "perf monitor started\n"); + return 0; +} + +inline INT_32 kalPerMonStop(IN P_GLUE_INFO_T prGlueInfo) +{ + struct PERF_MONITOR_T *prPerMonitor; + + DBGLOG(SW4, TRACE, "enter %s\n", __func__); + + if ((prGlueInfo == NULL) || (prGlueInfo->prAdapter == NULL)) { + DBGLOG(SW4, ERROR, "%s Invalid parameter..\n", __func__); + return -1; + } + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + + if (KAL_TEST_BIT(PERF_MON_DISABLE_BIT, prPerMonitor->ulPerfMonFlag)) { + DBGLOG(SW4, TRACE, "perf monitory disabled\n"); + return 0; + } + + if (KAL_TEST_BIT(PERF_MON_STOP_BIT, prPerMonitor->ulPerfMonFlag)) { + DBGLOG(SW4, TRACE, "perf monitory already stopped\n"); + return 0; + } + + KAL_SET_BIT(PERF_MON_STOP_BIT, prPerMonitor->ulPerfMonFlag); + if (KAL_TEST_BIT(PERF_MON_RUNNING_BIT, prPerMonitor->ulPerfMonFlag)) { + cnmTimerStopTimer(prGlueInfo->prAdapter, &prPerMonitor->rPerfMonTimer); + KAL_CLR_BIT(PERF_MON_RUNNING_BIT, prPerMonitor->ulPerfMonFlag); + prPerMonitor->ulLastRxBytes = 0; + prPerMonitor->ulLastTxBytes = 0; + prPerMonitor->ulP2PLastRxBytes = 0; + prPerMonitor->ulP2PLastTxBytes = 0; + prPerMonitor->ulThroughput = 0; + prPerMonitor->u4CurrPerfLevel = 0; + prPerMonitor->u4TarPerfLevel = 0; + /*Cancel CPU performance mode request*/ + kalBoostCpu(0); + } + DBGLOG(SW4, TRACE, "exit %s\n", __func__); + return 0; +} + +inline INT_32 kalPerMonDestroy(IN P_GLUE_INFO_T prGlueInfo) +{ + kalPerMonDisable(prGlueInfo); + return 0; +} + +VOID kalPerMonHandler(IN P_ADAPTER_T prAdapter, ULONG ulParam) +{ + /*Calculate current throughput*/ + struct PERF_MONITOR_T *prPerMonitor; + struct net_device *prNetDev = NULL; + UINT_32 u4Idx = 0; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; +#ifdef CFG_SUPPORT_DATA_STALL + P_WIFI_VAR_T prWifiVar = &prAdapter->rWifiVar; +#endif + + LONG latestTxBytes, latestRxBytes, txDiffBytes, rxDiffBytes; + LONG p2pLatestTxBytes, p2pLatestRxBytes, p2pTxDiffBytes, p2pRxDiffBytes; + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + + if ((prGlueInfo->ulFlag & GLUE_FLAG_HALT) || (!prAdapter->fgIsP2PRegistered)) + return; + + for (u4Idx = 0; u4Idx < BSS_INFO_NUM; u4Idx++) { + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, (UINT_8) u4Idx); + if (prP2pBssInfo->eNetworkType == NETWORK_TYPE_P2P) + break; + } + prNetDev = prGlueInfo->prDevHandler; + + prPerMonitor = &prAdapter->rPerMonitor; + DBGLOG(SW4, TRACE, "enter kalPerMonHandler\n"); + + latestTxBytes = prGlueInfo->prDevHandler->stats.tx_bytes; + latestRxBytes = prGlueInfo->prDevHandler->stats.rx_bytes; + p2pLatestTxBytes = prGlueInfo->prP2PInfo->prDevHandler->stats.tx_bytes; + p2pLatestRxBytes = prGlueInfo->prP2PInfo->prDevHandler->stats.rx_bytes; + if (prPerMonitor->ulLastRxBytes == 0 && + prPerMonitor->ulLastTxBytes == 0 && + prPerMonitor->ulP2PLastRxBytes == 0 && + prPerMonitor->ulP2PLastTxBytes == 0) { + prPerMonitor->ulThroughput = 0; + } else { + txDiffBytes = latestTxBytes - prPerMonitor->ulLastTxBytes; + rxDiffBytes = latestRxBytes - prPerMonitor->ulLastRxBytes; + if (txDiffBytes < 0) + txDiffBytes = -(txDiffBytes); + if (rxDiffBytes < 0) + rxDiffBytes = -(rxDiffBytes); + + p2pTxDiffBytes = p2pLatestTxBytes - prPerMonitor->ulP2PLastTxBytes; + p2pRxDiffBytes = p2pLatestRxBytes - prPerMonitor->ulP2PLastRxBytes; + if (p2pTxDiffBytes < 0) + p2pTxDiffBytes = -(p2pTxDiffBytes); + if (p2pRxDiffBytes < 0) + p2pRxDiffBytes = -(p2pRxDiffBytes); + + prPerMonitor->ulThroughput = txDiffBytes + rxDiffBytes + p2pTxDiffBytes + p2pRxDiffBytes; + prPerMonitor->ulThroughput *= 1000; + prPerMonitor->ulThroughput /= prPerMonitor->u4UpdatePeriod; + prPerMonitor->ulThroughput <<= 3; + } + + prPerMonitor->ulLastTxBytes = latestTxBytes; + prPerMonitor->ulLastRxBytes = latestRxBytes; + prPerMonitor->ulP2PLastTxBytes = p2pLatestTxBytes; + prPerMonitor->ulP2PLastRxBytes = p2pLatestRxBytes; +#ifdef CFG_SUPPORT_DATA_STALL + /* test mode */ + if (prWifiVar->u4ReportEventInterval == 0) + mtk_cfg80211_vendor_event_driver_error(prAdapter, + EVENT_TEST_MODE, (uint16_t)sizeof(u_int8_t)); +#endif + + if (prPerMonitor->ulThroughput < THROUGHPUT_L1_THRESHOLD) + prPerMonitor->u4TarPerfLevel = 0; + else if (prPerMonitor->ulThroughput < THROUGHPUT_L2_THRESHOLD) + prPerMonitor->u4TarPerfLevel = 1; + else if (prPerMonitor->ulThroughput < THROUGHPUT_L3_THRESHOLD) + prPerMonitor->u4TarPerfLevel = 2; + else if (prPerMonitor->ulThroughput < THROUGHPUT_L4_THRESHOLD) + prPerMonitor->u4TarPerfLevel = 3; + else + prPerMonitor->u4TarPerfLevel = 9; + + if (!wlan_perf_monitor_force_enable && + (wlan_fb_power_down || + prGlueInfo->fgIsInSuspendMode || + !(netif_carrier_ok(prNetDev) || + (prP2pBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) || + (prP2pBssInfo->rStaRecOfClientList.u4NumElem > 0)))) + kalPerMonStop(prGlueInfo); + else { + if (prPerMonitor->u4TarPerfLevel != prPerMonitor->u4CurrPerfLevel) { + /* if tar level = 0; core_number=prPerMonitor->u4TarPerfLevel+1*/ + if (prPerMonitor->u4TarPerfLevel) { + DBGLOG(SW4, INFO, + "PerfMon total:%3lu.%03lu mbps lv:%u fg:0x%lx\n", + prPerMonitor->ulThroughput >> 20, + (prPerMonitor->ulThroughput >> 10) & BITS(0, 9), + prPerMonitor->u4TarPerfLevel, + prPerMonitor->ulPerfMonFlag); + kalBoostCpu(prPerMonitor->u4TarPerfLevel+1); + } + else + kalBoostCpu(0); + } + cnmTimerStartTimer(prGlueInfo->prAdapter, &prPerMonitor->rPerfMonTimer, prPerMonitor->u4UpdatePeriod); + } + prPerMonitor->u4CurrPerfLevel = prPerMonitor->u4TarPerfLevel; +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + /* link quality monitor */ + DBGLOG(SW4, TRACE, "new:%u, Link:%u\n", kalGetTimeTick(), prAdapter->u4LastLinkQuality); + if ((kalGetTimeTick() - prAdapter->u4LastLinkQuality) >= CFG_LINK_QUALITY_MONITOR_UPDATE_INTERVAL) + wlanLinkQualityMonitor(prGlueInfo); +#endif + DBGLOG(SW4, TRACE, "exit kalPerMonHandler\n"); +} + +INT_32 __weak kalBoostCpu(UINT_32 core_num) +{ + DBGLOG(SW4, WARN, "enter weak kalBoostCpu, core_num:%d\n", core_num); + return 0; +} + +INT_32 __weak kalSetCpuNumFreq(UINT_32 u4CoreNum, UINT_32 u4Freq) +{ + DBGLOG(SW4, INFO, "enter weak kalSetCpuNumFreq, u4CoreNum:%d, urFreq:%d\n", u4CoreNum, u4Freq); + return 0; +} + +INT_32 kalPerMonSetForceEnableFlag(UINT_8 uFlag) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)wlan_fb_notifier_priv_data; + + wlan_perf_monitor_force_enable = uFlag == 0 ? FALSE : TRUE; + DBGLOG(SW4, INFO, "uFlag:%d, wlan_perf_monitor_ctrl_flag:%d\n", uFlag, wlan_perf_monitor_force_enable); + + if (wlan_perf_monitor_force_enable && prGlueInfo && !kalIsHalted()) + kalPerMonEnable(prGlueInfo); + + return 0; +} + +static int wlan_fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data) +{ + struct fb_event *evdata = data; + INT_32 blank; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)wlan_fb_notifier_priv_data; + + /* If we aren't interested in this event, skip it immediately ... */ + if (event != FB_EVENT_BLANK || !prGlueInfo) + return 0; + + if (kalHaltTryLock()) + return 0; + + if (kalIsHalted()) { + kalHaltUnlock(); + return 0; + } + + blank = *(INT_32 *)evdata->data; + + switch (blank) { + case FB_BLANK_UNBLANK: + kalPerMonEnable(prGlueInfo); + wlan_fb_power_down = FALSE; + break; + case FB_BLANK_POWERDOWN: + wlan_fb_power_down = TRUE; + if (!wlan_perf_monitor_force_enable) + kalPerMonDisable(prGlueInfo); + break; + default: + break; + } + + kalHaltUnlock(); + return 0; +} + +INT_32 kalFbNotifierReg(IN P_GLUE_INFO_T prGlueInfo) +{ + INT_32 i4Ret; + + wlan_fb_notifier_priv_data = prGlueInfo; + wlan_fb_notifier.notifier_call = wlan_fb_notifier_callback; + i4Ret = fb_register_client(&wlan_fb_notifier); + if (i4Ret) + DBGLOG(SW4, WARN, "Register wlan_fb_notifier failed:%d\n", i4Ret); + else + DBGLOG(SW4, TRACE, "Register wlan_fb_notifier succeed\n"); + + return i4Ret; +} + +VOID kalFbNotifierUnReg(VOID) +{ + fb_unregister_client(&wlan_fb_notifier); + wlan_fb_notifier_priv_data = NULL; +} + +#if CFG_MODIFY_TX_POWER_BY_BAT_VOLT +VOID kalSetTxPwrBackoffByBattVolt(P_ADAPTER_T prAdapter, BOOLEAN ucEnable) +{ + struct CMD_TX_PWR_BACKOFF rTxPwrBackoff; + + ASSERT(prAdapter); + + if (!prAdapter) + return; + + rTxPwrBackoff.ucEnable = ucEnable; + rTxPwrBackoff.ucBackoffPwr = 3; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_TX_POWER_BACKOFF, + TRUE, + FALSE, FALSE, NULL, NULL, + sizeof(struct CMD_TX_PWR_BACKOFF), + (PUINT_8) & rTxPwrBackoff, NULL, 0); +} + +static VOID kal_bat_volt_notifier_callback(unsigned int volt) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)wlan_bat_volt_notifier_priv_data; + P_ADAPTER_T prAdapter = NULL; + P_REG_INFO_T prRegInfo = NULL; + static BOOLEAN fgIsTxPowerDecreased = FALSE; + + wlan_bat_volt = volt; + if (prGlueInfo == NULL) { + DBGLOG(NIC, ERROR, "volt = %d, prGlueInfo is NULL", volt); + return; + } + prAdapter = prGlueInfo->prAdapter; + prRegInfo = &prGlueInfo->rRegInfo; + + if (prRegInfo == NULL || prGlueInfo->prAdapter == NULL) { + DBGLOG(NIC, ERROR, "volt = %d, prRegInfo or prAdapter is NULL", volt); + return; + } + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(NIC, ERROR, "volt = %d, Wi-Fi is stopped", volt); + fgIsTxPowerDecreased = FALSE; + return; + } + DBGLOG(NIC, INFO, "volt = %d, fgIsTxPowerDecreased = %d\n", volt, fgIsTxPowerDecreased); + if (volt == 3650 && fgIsTxPowerDecreased == TRUE) { + kalSetTxPwrBackoffByBattVolt(prAdapter, FALSE); + fgIsTxPowerDecreased = FALSE; + } else if (volt == 3550 && fgIsTxPowerDecreased == FALSE) { + kalSetTxPwrBackoffByBattVolt(prAdapter, TRUE); + fgIsTxPowerDecreased = TRUE; + } +} + +INT_32 kalBatNotifierReg(IN P_GLUE_INFO_T prGlueInfo) +{ + INT_32 i4Ret; + static struct lbat_user rWifiBatVolt; + + wlan_bat_volt_notifier_priv_data = prGlueInfo; + i4Ret = lbat_user_register(&rWifiBatVolt, "WiFi Get Battery Voltage", + 3650, 3550, 0, kal_bat_volt_notifier_callback); + if (i4Ret) + DBGLOG(SW4, WARN, "Register rWifiBatVolt failed:%d\n", i4Ret); + else + DBGLOG(SW4, TRACE, "Register rWifiBatVolt succeed\n"); + return i4Ret; +} + +VOID kalBatNotifierUnReg(VOID) +{ + wlan_bat_volt_notifier_priv_data = NULL; +} +#endif + +UINT_8 kalGetEapolKeyType(P_NATIVE_PACKET prPacket) +{ + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + + if (!prSkb) + return EAPOL_KEY_NOT_KEY; + return (UINT_8)secGetEapolKeyType(prSkb->data); +} + +VOID __weak kalSetEmiMpuProtection(phys_addr_t emiPhyBase, UINT_32 size, BOOLEAN enable) +{ + DBGLOG(SW4, WARN, "EMI MPU function is not defined\n"); +} + +VOID kalVcoreInitUninit(BOOLEAN fgInit) +{ +#ifdef CONFIG_MTK_QOS_SUPPORT + if (fgInit) { + atomic_set(&vcore_req_cnt, 0); + atomic_set(&vcore_changed, 0); + mutex_init(&vcore_mutex); + pm_qos_add_request(&vcore_req, PM_QOS_VCORE_OPP, PM_QOS_VCORE_OPP_DEFAULT_VALUE); + } else { + pm_qos_update_request(&vcore_req, VCORE_OPP_UNREQ); + pm_qos_remove_request(&vcore_req); + } +#endif +} + +inline VOID kalMayChangeVcore(VOID) +{ +#ifdef CONFIG_MTK_QOS_SUPPORT + if (unlikely(!atomic_read(&vcore_changed))) { + atomic_inc(&vcore_changed); + kalTakeVcoreAction(VCORE_SET_HIGHER); + } +#endif +} + +VOID kalTakeVcoreAction(UINT_8 ucAction) +{ +#if defined(CONFIG_MTK_QOS_SUPPORT) + mutex_lock(&vcore_mutex); + switch (ucAction) { + case VCORE_ADD_HIGHER_REQ: + /* Only increase request count */ + atomic_inc(&vcore_req_cnt); + DBGLOG(SW4, INFO, "Add request higher vcore request, total request count %d\n", + atomic_read(&vcore_req_cnt)); + break; + case VCORE_DEC_HIGHER_REQ: + DBGLOG(SW4, INFO, "Remove request higher vcore request, total request count %d\n", + atomic_read(&vcore_req_cnt)); + if (atomic_read(&vcore_req_cnt) > 0 && atomic_dec_return(&vcore_req_cnt) == 0) + pm_qos_update_request(&vcore_req, PM_QOS_VCORE_OPP_DEFAULT_VALUE); /* default is 0.725v */ + break; + case VCORE_RESTORE_DEF: + if (atomic_read(&vcore_changed) > 0 && atomic_read(&vcore_req_cnt) > 0) { + DBGLOG(SW4, TRACE, "Connsys sleep, request to 0.725v\n"); + atomic_set(&vcore_changed, 0); + pm_qos_update_request(&vcore_req, PM_QOS_VCORE_OPP_DEFAULT_VALUE); /* default is 0.725v */ + } + break; + case VCORE_SET_HIGHER: + if (atomic_read(&vcore_req_cnt) > 0) { + DBGLOG(SW4, TRACE, "Start Txing data, request to 0.8v\n"); + pm_qos_update_request(&vcore_req, VCORE_OPP_0); /* OPP_0 represents 0.8v */ + } + break; + case VCORE_CLEAR_ALL_REQ: + atomic_set(&vcore_req_cnt, 0); + atomic_set(&vcore_changed, 0); + pm_qos_update_request(&vcore_req, PM_QOS_VCORE_OPP_DEFAULT_VALUE); /* default is 0.725v */ + DBGLOG(SW4, INFO, "Clear all vcore change request, and set vcore to default\n"); + break; + default: + DBGLOG(SW4, ERROR, "Unknown vcore action %d\n", ucAction); + break; + } + mutex_unlock(&vcore_mutex); +#endif +} + +BOOLEAN kalIsOuiMask(IN uint8_t pucMacAddrMask[MAC_ADDR_LEN]) +{ + return (pucMacAddrMask[0] == 0xFF && + pucMacAddrMask[1] == 0xFF && + pucMacAddrMask[2] == 0xFF); +} + +BOOLEAN kalIsValidMacAddr(IN const uint8_t *addr) +{ + return is_valid_ether_addr(addr); +} +#if (KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE) +static BOOLEAN kalParseRandomMac( + IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 *pucMacAddr, IN UINT_8 *pucMacAddrMask, + OUT UINT_8 *pucRandomMac) +{ + ASSERT(pucMacAddr); + ASSERT(pucMacAddrMask); + ASSERT(pucRandomMac); + +#if 0 + if (!kalIsOuiMask(ucMacAddrMask) && prGlueInfo->fgIsScanOuiSet) { + kalMemCopy(ucMacAddr, prGlueInfo->ucScanOui, MAC_OUI_LEN); + kalMemSet(ucMacAddrMask, 0xFF, MAC_OUI_LEN); + } +#endif + + get_random_mask_addr(pucRandomMac, pucMacAddr, pucMacAddrMask); + + DBGLOG(SCN, INFO, "random mac=" MACSTR " mac_addr=" MACSTR + ", mac_addr_mask=%pM\n", MAC2STR(pucRandomMac), + MAC2STR(pucMacAddr), pucMacAddrMask); + return TRUE; +} + +BOOLEAN kalScanParseRandomMac( + IN P_GLUE_INFO_T prGlueInfo, + IN struct cfg80211_scan_request *request, + OUT UINT_8 *pucRandomMac) +{ + if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) { + DBGLOG(SCN, TRACE, "Scan random mac is not set\n"); + return FALSE; + } + return kalParseRandomMac(prGlueInfo, request->mac_addr, + request->mac_addr_mask, pucRandomMac); +} +BOOLEAN kalSchedScanParseRandomMac( + const struct net_device *ndev, + IN struct cfg80211_sched_scan_request *request) +{ + P_NETDEV_PRIVATE_GLUE_INFO prNetDevPrivate = NULL; + + ASSERT(request); + ASSERT(ndev); + prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(ndev); + if (!prNetDevPrivate || !prNetDevPrivate->prGlueInfo) { + DBGLOG(SCN, WARN, "prNetdevPrivate or prGlueInfo is NULL\n"); + return FALSE; + } + if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) { + DBGLOG(SCN, TRACE, "Scan random mac is not set or not support\n"); + return FALSE; + } + return TRUE; +} +#else /* if (KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE) */ +BOOLEAN kalScanParseRandomMac( + IN P_GLUE_INFO_T prGlueInfo, + IN struct cfg80211_scan_request *request, + OUT PUINT_8 pucRandomMac) +{ + return FALSE; +} +BOOLEAN kalSchedScanParseRandomMac( + const struct net_device *ndev, + IN struct cfg80211_sched_scan_request *request) +{ + return FALSE; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_p2p.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_p2p.c new file mode 100644 index 0000000000000..336aa53e239dd --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_p2p.c @@ -0,0 +1,4190 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * 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. + */ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include + +#include "gl_os.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "gl_p2p_os.h" +#include "gl_p2p_ioctl.h" +#include "gl_vendor.h" + +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define ARGV_MAX_NUM (4) + +/*For CFG80211 - wiphy parameters*/ +#define MAX_SCAN_LIST_NUM (1) +#define MAX_SCAN_IE_LEN (512) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +static struct net_device *g_P2pPrDev; +static struct wireless_dev *gprP2pWdev; + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +static struct cfg80211_ops mtk_p2p_ops = { + /*.add_virtual_intf = mtk_p2p_cfg80211_add_iface,*/ + .change_virtual_intf = mtk_p2p_cfg80211_change_iface, /* 1 st */ + .del_virtual_intf = mtk_p2p_cfg80211_del_iface, + .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, + .mgmt_tx_cancel_wait = mtk_p2p_cfg80211_mgmt_tx_cancel_wait, + .connect = mtk_p2p_cfg80211_connect, + .disconnect = mtk_p2p_cfg80211_disconnect, + .deauth = mtk_p2p_cfg80211_deauth, + .disassoc = mtk_p2p_cfg80211_disassoc, + .start_ap = mtk_p2p_cfg80211_start_ap, + .change_beacon = mtk_p2p_cfg80211_change_beacon, + .stop_ap = mtk_p2p_cfg80211_stop_ap, + .set_wiphy_params = mtk_p2p_cfg80211_set_wiphy_params, + .del_station = mtk_p2p_cfg80211_del_station, + .set_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, + .set_default_mgmt_key = mtk_p2p_cfg80211_set_mgmt_key, + .join_ibss = mtk_p2p_cfg80211_join_ibss, + .leave_ibss = mtk_p2p_cfg80211_leave_ibss, + .set_tx_power = mtk_p2p_cfg80211_set_txpower, + .get_tx_power = mtk_p2p_cfg80211_get_txpower, + .set_power_mgmt = mtk_p2p_cfg80211_set_power_mgmt, +#ifdef CONFIG_NL80211_TESTMODE + .testmode_cmd = mtk_p2p_cfg80211_testmode_cmd, +#endif +}; + +static const struct wiphy_vendor_command mtk_p2p_vendor_ops[] = { + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_GET_CHANNEL_LIST + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_channel_list + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_SET_COUNTRY_CODE + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_country_code + }, +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + { + { + .vendor_id = OUI_QCA, + .subcmd = NL80211_VENDOR_SUBCMD_ACS + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV + | WIPHY_VENDOR_CMD_NEED_NETDEV + | WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = mtk_cfg80211_vendor_acs + }, +#endif + { + { + .vendor_id = OUI_QCA, + .subcmd = NL80211_VENDOR_SUBCMD_GET_FEATURES + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV + | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_features + }, +}; + +/* 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) +#if CFG_SUPPORT_SOFTAP_WPA3 + | BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) +#endif + + }, + [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) + } +}; + +static const struct ieee80211_iface_limit mtk_p2p_iface_limits[] = { + { + .max = 1, + .types = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_AP) + }, + { + .max = 1, + .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | + BIT(NL80211_IFTYPE_P2P_GO) + }, +}; + +static const struct ieee80211_iface_combination mtk_p2p_iface_combos[] = { + { + .max_interfaces = 2, + .num_different_channels = 2, + .n_limits = ARRAY_SIZE(mtk_p2p_iface_limits), + .limits = mtk_p2p_iface_limits + } +}; +#endif + +#if 0 +/* 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, +}; +#endif + +#if 0 +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, +}; +#endif + +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"} +}; + +#if 0 +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 +}; +#endif + +#ifdef CONFIG_PM +static const struct wiphy_wowlan_support mtk_p2p_wowlan_support = { + .flags = WIPHY_WOWLAN_DISCONNECT | WIPHY_WOWLAN_ANY, +}; +#endif + +/*need to check*/ +static const struct nl80211_vendor_cmd_info mtk_p2p_vendor_events[] = { + { + .vendor_id = OUI_QCA, + .subcmd = NL80211_VENDOR_SUBCMD_ACS + }, +}; + + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/* 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 p2pSetMACAddress(IN struct net_device *prDev, void *addr); + +static int p2pDoIOCTL(struct net_device *prDev, struct ifreq *prIfReq, int i4Cmd); + +#if 0 + +/*----------------------------------------------------------------------------*/ +/*! +* \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]; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ +} /* end of p2pUninit() */ + +const struct net_device_ops p2p_netdev_ops = { + .ndo_open = p2pOpen, + .ndo_stop = p2pStop, + .ndo_set_mac_address = p2pSetMACAddress, + .ndo_set_rx_mode = p2pSetMulticastList, + .ndo_get_stats = p2pGetStats, + .ndo_do_ioctl = p2pDoIOCTL, + .ndo_start_xmit = p2pHardStartXmit, + /* .ndo_select_queue = p2pSelectQueue, */ + .ndo_select_queue = wlanSelectQueue, + .ndo_init = p2pInit, + .ndo_uninit = p2pUninit, +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Allocate memory for P2P_INFO, GL_P2P_INFO, P2P_CONNECTION_SETTINGS +* P2P_SPECIFIC_BSS_INFO, P2P_FSM_INFO +* +* \param[in] prGlueInfo Pointer to glue info +* +* \return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2PAllocInfo(IN P_GLUE_INFO_T prGlueInfo) +{ + P_ADAPTER_T prAdapter = NULL; + P_WIFI_VAR_T prWifiVar = NULL; + /* UINT_32 u4Idx = 0; */ + + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + prWifiVar = &(prAdapter->rWifiVar); + + ASSERT(prAdapter); + ASSERT(prWifiVar); + + do { + if (prGlueInfo->prP2PInfo == NULL) { + /*alloc memory for p2p info */ + prGlueInfo->prP2PInfo = kalMemAlloc(sizeof(GL_P2P_INFO_T), VIR_MEM_TYPE); + prAdapter->prP2pInfo = kalMemAlloc(sizeof(P2P_INFO_T), VIR_MEM_TYPE); + prWifiVar->prP2PConnSettings = kalMemAlloc(sizeof(P2P_CONNECTION_SETTINGS_T), VIR_MEM_TYPE); + + prWifiVar->prP2pDevFsmInfo = kalMemAlloc(sizeof(P2P_DEV_FSM_INFO_T), VIR_MEM_TYPE); + + /* TODO: It can be moved to the interface been created. */ + /* + * for (u4Idx = 0; u4Idx < BSS_P2P_NUM; u4Idx++) { + * prWifiVar->aprP2pRoleFsmInfo[u4Idx] = + * kalMemAlloc(sizeof(P2P_ROLE_FSM_INFO_T),VIR_MEM_TYPE); + * } + */ + + prWifiVar->prP2pSpecificBssInfo = kalMemAlloc(sizeof(P2P_SPECIFIC_BSS_INFO_T), VIR_MEM_TYPE); + prWifiVar->prP2pQueryStaStatistics = kalMemAlloc(sizeof(PARAM_GET_STA_STA_STATISTICS), + VIR_MEM_TYPE); + } else { + ASSERT(prAdapter->prP2pInfo != NULL); + ASSERT(prWifiVar->prP2PConnSettings != NULL); + /* ASSERT(prWifiVar->prP2pFsmInfo != NULL); */ + ASSERT(prWifiVar->prP2pSpecificBssInfo != NULL); + } + /* MUST set memory to 0 */ + if (prGlueInfo->prP2PInfo) + kalMemZero(prGlueInfo->prP2PInfo, sizeof(GL_P2P_INFO_T)); + if (prAdapter->prP2pInfo) + kalMemZero(prAdapter->prP2pInfo, sizeof(P2P_INFO_T)); + if (prWifiVar->prP2PConnSettings) + kalMemZero(prWifiVar->prP2PConnSettings, sizeof(P2P_CONNECTION_SETTINGS_T)); + /* kalMemZero(prWifiVar->prP2pFsmInfo, sizeof(P2P_FSM_INFO_T)); */ + if (prWifiVar->prP2pSpecificBssInfo) + kalMemZero(prWifiVar->prP2pSpecificBssInfo, sizeof(P2P_SPECIFIC_BSS_INFO_T)); + if (prWifiVar->prP2pQueryStaStatistics) + kalMemZero(prWifiVar->prP2pQueryStaStatistics, sizeof(PARAM_GET_STA_STA_STATISTICS)); + + } while (FALSE); + + /* chk if alloc successful or not */ + if (prGlueInfo->prP2PInfo && prAdapter->prP2pInfo && prWifiVar->prP2PConnSettings && +/* prWifiVar->prP2pFsmInfo && */ + prWifiVar->prP2pSpecificBssInfo) { + return TRUE; + } + + if (prWifiVar->prP2pSpecificBssInfo) { + kalMemFree(prWifiVar->prP2pSpecificBssInfo, VIR_MEM_TYPE, sizeof(P2P_SPECIFIC_BSS_INFO_T)); + + prWifiVar->prP2pSpecificBssInfo = NULL; + } + if (prWifiVar->prP2pQueryStaStatistics) { + kalMemFree(prWifiVar->prP2pQueryStaStatistics, VIR_MEM_TYPE, sizeof(PARAM_GET_STA_STA_STATISTICS)); + prWifiVar->prP2pQueryStaStatistics = 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); + + /* 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)); + kalMemFree(prGlueInfo->prAdapter->rWifiVar.prP2pQueryStaStatistics, VIR_MEM_TYPE, + sizeof(PARAM_GET_STA_STA_STATISTICS)); + + kalMemFree(prGlueInfo->prAdapter->rWifiVar.prP2pDevFsmInfo, VIR_MEM_TYPE, sizeof(P2P_DEV_FSM_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; + prGlueInfo->prAdapter->rWifiVar.prP2pQueryStaStatistics = NULL; + prGlueInfo->prAdapter->rWifiVar.prP2pDevFsmInfo = NULL; + + return TRUE; + } else { + return FALSE; + } + +} + +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(); + } + + /* net device initialize */ + netif_carrier_off(prGlueInfo->prP2PInfo->prDevHandler); + netif_tx_stop_all_queues(prGlueInfo->prP2PInfo->prDevHandler); + + /* register for net device */ + if (register_netdev(prGlueInfo->prP2PInfo->prDevHandler) < 0) { + DBGLOG(INIT, WARN, "unable to register netdevice for p2p\n"); + + /* free dev in glUnregisterP2P() */ + /* 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); + + if (fgRollbackRtnlLock) + rtnl_lock(); + + prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_UNREGISTERED; + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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; + P_NETDEV_PRIVATE_GLUE_INFO prNetDevPriv = (P_NETDEV_PRIVATE_GLUE_INFO) NULL; +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + struct device *prDev; +#endif + + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prHif = &prGlueInfo->rHifInfo; + ASSERT(prHif); + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + if (!gprP2pWdev) { + DBGLOG(P2P, ERROR, "p2p wireless device is not exist\n"); + return FALSE; + } +#endif + + /*0. allocate p2pinfo */ + if (!p2PAllocInfo(prGlueInfo)) { + DBGLOG(INIT, WARN, "Allocate memory for p2p FAILED\n"); + ASSERT(0); + return FALSE; + } +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + + /* 1.1 fill wiphy parameters */ +#if MTK_WCN_HIF_SDIO + mtk_wcn_hif_sdio_get_dev(prHif->cltCtx, &prDev); + if (!prDev) { + DBGLOG(INIT, INFO, + "unable to get struct dev for p2p\n"); + } +#else + + prDev = prHif->Dev; + +#endif + prGlueInfo->prP2PInfo->prWdev = gprP2pWdev; + /*set_wiphy_dev(gprP2pWdev->wiphy, prDev);*/ + if (!prGlueInfo->prAdapter->fgEnable5GBand) + gprP2pWdev->wiphy->bands[KAL_BAND_5GHZ] = NULL; + + /* 2.2 wdev initialization */ + if (fgIsApMode) + gprP2pWdev->iftype = NL80211_IFTYPE_AP; + else + gprP2pWdev->iftype = NL80211_IFTYPE_P2P_CLIENT; + +#endif /* CFG_ENABLE_WIFI_DIRECT_CFG_80211 */ + + /* 3. allocate netdev */ + prGlueInfo->prP2PInfo->prDevHandler = + alloc_netdev_mq(sizeof(NETDEV_PRIVATE_GLUE_INFO), prDevName, + NET_NAME_PREDICTABLE, ether_setup, CFG_MAX_TXQ_NUM); + if (!prGlueInfo->prP2PInfo->prDevHandler) { + DBGLOG(INIT, WARN, "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; */ + prNetDevPriv = (P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(prGlueInfo->prP2PInfo->prDevHandler); + prNetDevPriv->prGlueInfo = prGlueInfo; + + /* 4.2 fill hardware address */ + COPY_MAC_ADDR(rMacAddr, prAdapter->rMyMacAddr); + rMacAddr[0] ^= 0x2; /* change to local administrated address */ + ether_addr_copy(prGlueInfo->prP2PInfo->prDevHandler->dev_addr, rMacAddr); + ether_addr_copy(prGlueInfo->prP2PInfo->prDevHandler->perm_addr, prGlueInfo->prP2PInfo->prDevHandler->dev_addr); + + /* 4.3 register callback functions */ + prGlueInfo->prP2PInfo->prDevHandler->netdev_ops = &p2p_netdev_ops; +/* prGlueInfo->prP2PInfo->prDevHandler->wireless_handlers = &mtk_p2p_wext_handler_def; */ + +#if (MTK_WCN_HIF_SDIO == 0) + SET_NETDEV_DEV(prGlueInfo->prP2PInfo->prDevHandler, prHif->Dev); +#endif + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + prGlueInfo->prP2PInfo->prDevHandler->ieee80211_ptr = gprP2pWdev; + gprP2pWdev->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 */ + + kalResetStats(prGlueInfo->prP2PInfo->prDevHandler); + +#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) { + DBGLOG(INIT, WARN, "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 */ + /* 13. bind netdev pointer to netdev index */ + wlanBindBssIdxToNetInterface(prGlueInfo, p2pDevFsmInit(prAdapter), (PVOID) prGlueInfo->prP2PInfo->prDevHandler); + + prGlueInfo->prP2PInfo->aprRoleHandler[0] = prGlueInfo->prP2PInfo->prDevHandler; + + prNetDevPriv->ucBssIdx = p2pRoleFsmInit(prAdapter, 0); + /* 11. Currently wpasupplicant can't support create interface. */ + /* so initial the corresponding data structure here. */ + wlanBindBssIdxToNetInterface(prGlueInfo, prNetDevPriv->ucBssIdx, + (PVOID) prGlueInfo->prP2PInfo->aprRoleHandler[0]); + + /* 13. bind netdev pointer to netdev index */ + /* wlanBindNetInterface(prGlueInfo, NET_DEV_P2P_IDX, (PVOID)prGlueInfo->prP2PInfo->prDevHandler); */ + + /* 12. setup running mode */ + p2pFuncInitConnectionSettings(prAdapter, prAdapter->rWifiVar.prP2PConnSettings, fgIsApMode); + + /* 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: + return FALSE; +} /* end of glRegisterP2P() */ + +BOOLEAN glP2pCreateWirelessDevice(P_GLUE_INFO_T prGlueInfo) +{ + struct wiphy *prWiphy = NULL; + struct wireless_dev *prWdev = NULL; +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + prWdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (!prWdev) { + DBGLOG(P2P, ERROR, "allocate p2p wireless device fail, no memory\n"); + return FALSE; + } + /* 1. allocate WIPHY */ + prWiphy = wiphy_new(&mtk_p2p_ops, sizeof(P_GLUE_INFO_T)); + if (!prWiphy) { + DBGLOG(P2P, ERROR, "unable to allocate wiphy for p2p\n"); + goto free_wdev; + } + + prWiphy->interface_modes = BIT(NL80211_IFTYPE_AP) + | BIT(NL80211_IFTYPE_P2P_CLIENT) + | BIT(NL80211_IFTYPE_P2P_GO) + | BIT(NL80211_IFTYPE_STATION); + + prWiphy->iface_combinations = mtk_p2p_iface_combos; + prWiphy->n_iface_combinations = ARRAY_SIZE(mtk_p2p_iface_combos); + + prWiphy->bands[KAL_BAND_2GHZ] = &mtk_band_2ghz; + prWiphy->bands[KAL_BAND_5GHZ] = &mtk_band_5ghz; + + prWiphy->mgmt_stypes = mtk_cfg80211_default_mgmt_stypes; + prWiphy->max_remain_on_channel_duration = 5000; + prWiphy->cipher_suites = mtk_cipher_suites; + prWiphy->n_cipher_suites = ARRAY_SIZE(mtk_cipher_suites); + prWiphy->flags = WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | WIPHY_FLAG_HAVE_AP_SME; + prWiphy->regulatory_flags = REGULATORY_CUSTOM_REG; + prWiphy->ap_sme_capa = 1; + + prWiphy->max_scan_ssids = MAX_SCAN_LIST_NUM; + prWiphy->max_scan_ie_len = MAX_SCAN_IE_LEN; + prWiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + prWiphy->vendor_commands = mtk_p2p_vendor_ops; + prWiphy->n_vendor_commands = sizeof(mtk_p2p_vendor_ops) / sizeof(struct wiphy_vendor_command); + prWiphy->vendor_events = mtk_p2p_vendor_events; + prWiphy->n_vendor_events = ARRAY_SIZE(mtk_p2p_vendor_events); + +#ifdef CONFIG_PM + prWiphy->wowlan = &mtk_p2p_wowlan_support; +#endif + +#if KERNEL_VERSION(3, 14, 0) < LINUX_VERSION_CODE + prWiphy->max_ap_assoc_sta = P2P_MAXIMUM_CLIENT_COUNT; +#endif + + /* 2.1 set priv as pointer to glue structure */ + *((P_GLUE_INFO_T *) wiphy_priv(prWiphy)) = prGlueInfo; + /* Here are functions which need rtnl_lock */ + if (wiphy_register(prWiphy) < 0) { + DBGLOG(INIT, WARN, "fail to register wiphy for p2p\n"); + goto free_wiphy; + } + prWdev->wiphy = prWiphy; + gprP2pWdev = prWdev; + return TRUE; + +free_wiphy: + wiphy_free(prWiphy); +free_wdev: + kfree(prWdev); +#endif + return FALSE; +} + +void glP2pDestroyWirelessDevice(void) +{ +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + wiphy_unregister(gprP2pWdev->wiphy); + wiphy_free(gprP2pWdev->wiphy); + kfree(gprP2pWdev); + gprP2pWdev = NULL; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ + UINT_8 ucRoleIdx; + P_ADAPTER_T prAdapter; + + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + + /* 4 <1> Uninit P2P dev FSM */ + /* Uninit P2P device FSM */ + p2pDevFsmUninit(prAdapter); + + /* 4 <2> Uninit P2P role FSM */ + for (ucRoleIdx = 0; ucRoleIdx < BSS_P2P_NUM; ucRoleIdx++) { + if (P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, ucRoleIdx)) + p2pRoleFsmUninit(prGlueInfo->prAdapter, ucRoleIdx); + } + + /* 4 <3> Free Wiphy & netdev */ + if (prGlueInfo->prP2PInfo->prDevHandler != NULL) { + free_netdev(prGlueInfo->prP2PInfo->prDevHandler); + prGlueInfo->prP2PInfo->prDevHandler = NULL; + } + + /* 4 <4> Free P2P internal memory */ + if (!p2PFreeInfo(prGlueInfo)) { + DBGLOG(INIT, WARN, "Free memory for p2p FAILED\n"); + ASSERT(0); + return FALSE; + } + + return TRUE; + +#if 0 + 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 */ + kalClearMgmtFramesByBssIdx(prGlueInfo, NETWORK_TYPE_P2P_INDEX); + kalClearSecurityFramesByBssIdx(prGlueInfo, NETWORK_TYPE_P2P_INDEX); + /* Clear PendingCmdQue */ + wlanReleasePendingCMDbyBssIdx(prGlueInfo->prAdapter, NETWORK_TYPE_P2P_INDEX); + /* Clear PendingTxMsdu */ + nicFreePendingTxMsduInfoByBssIdx(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)) { + DBGLOG(INIT, WARN, "Free memory for p2p FAILED\n"); + ASSERT(0); + return FALSE; + } +#endif + return TRUE; + +#else + return 0; +#endif +} /* end of glUnregisterP2P() */ + +/* 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. start TX queue, set carrier on after link is ready */ + 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; + struct cfg80211_scan_request *prScanRequest = NULL; + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; +/* P_MSG_P2P_FUNCTION_SWITCH_T prFuncSwitch; */ + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + prGlueP2pInfo = prGlueInfo->prP2PInfo; + /* CFG80211 down */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if (prGlueP2pInfo->prScanRequest != NULL) { + prScanRequest = prGlueP2pInfo->prScanRequest; + prGlueP2pInfo->prScanRequest = NULL; + } else + DBGLOG(P2P, WARN, "[p2p] scan complete but cfg80211 scan request is NULL\n"); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) + if (prScanRequest) { + struct cfg80211_scan_info info = { + .aborted = TRUE, + }; + cfg80211_scan_done(prScanRequest, &info); + } +#else + if (prScanRequest) + cfg80211_scan_done(prScanRequest, TRUE); +#endif + + /* 1. stop TX queue */ + netif_tx_stop_all_queues(prDev); +#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 */ + 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); + + 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) +{ + return (struct net_device_stats *)kalGetStats(prDev); +} /* end of p2pGetStats() */ + +static void p2pSetMulticastList(IN struct net_device *prDev) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + + prGlueInfo = (prDev != NULL) ? *((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); + return; + } + + g_P2pPrDev = prDev; + + /* 4 Mark HALT, notify main thread to finish current job */ + set_bit(GLUE_FLAG_SUB_MOD_MULTICAST_BIT, &prGlueInfo->ulFlag); + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + +} /* p2pSetMulticastList */ + +/* + * FIXME: Since we cannot sleep in the wlanSetMulticastList, we arrange + * another workqueue for sleeping. We don't want to block + * tx_thread, so we can't let tx_thread to do this + */ + +void p2pSetMulticastListWorkQueueWrapper(P_GLUE_INFO_T prGlueInfo) +{ + if (!prGlueInfo) { + DBGLOG(INIT, ERROR, "prGlueInfo is NULL\n"); + return; + } +#if CFG_ENABLE_WIFI_DIRECT + if (prGlueInfo->prAdapter->fgIsP2PRegistered) + mtk_p2p_wext_set_Multicastlist(prGlueInfo); +#endif +} /* end of p2pSetMulticastListWorkQueueWrapper() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is to set multicast list and set rx mode. + * + * \param[in] prDev Pointer to struct net_device + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void mtk_p2p_wext_set_Multicastlist(P_GLUE_INFO_T prGlueInfo) +{ + UINT_32 u4SetInfoLen = 0; + UINT_32 u4McCount; + struct net_device *prDev = g_P2pPrDev; + + prGlueInfo = (prDev != NULL) ? *((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); + 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; + u4McCount = netdev_mc_count(prDev); + + if (prDev->flags & IFF_MULTICAST) { + if ((prDev->flags & IFF_ALLMULTI) || (u4McCount > MAX_NUM_GROUP_ADDR)) + prGlueInfo->prP2PInfo->u4PacketFilter |= PARAM_PACKET_FILTER_ALL_MULTICAST; + else + prGlueInfo->prP2PInfo->u4PacketFilter |= PARAM_PACKET_FILTER_MULTICAST; + } + + if (prGlueInfo->prP2PInfo->u4PacketFilter & PARAM_PACKET_FILTER_MULTICAST) { + /* Prepare multicast address list */ + struct netdev_hw_addr *ha; + UINT_32 i = 0; + + netif_addr_lock_bh(prDev); + netdev_for_each_mc_addr(ha, prDev) { + if (i < MAX_NUM_GROUP_ADDR) { + COPY_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucMCAddrList[i]), ha->addr); + i++; + } + } + netif_addr_unlock_bh(prDev); + DBGLOG(P2P, TRACE, "SEt Multicast Address List\n"); + + if (i >= MAX_NUM_GROUP_ADDR) + return; + wlanoidSetP2PMulticastList(prGlueInfo->prAdapter, + &(prGlueInfo->prP2PInfo->aucMCAddrList[0]), (i * ETH_ALEN), &u4SetInfoLen); + + } + +} /* end of mtk_p2p_wext_set_Multicastlist() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is TX entry point of NET DEVICE. + * + * \param[in] prSkb Pointer of the sk_buff to be sent + * \param[in] prDev Pointer to struct net_device + * + * \retval NETDEV_TX_OK - on success. + * \retval NETDEV_TX_BUSY - on failure, packet will be discarded by upper layer. + */ +/*----------------------------------------------------------------------------*/ +int p2pHardStartXmit(IN struct sk_buff *prSkb, IN struct net_device *prDev) +{ + P_NETDEV_PRIVATE_GLUE_INFO prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_BSS_INFO_T prP2pBssInfo = NULL; + UINT_8 ucBssIndex; + + ASSERT(prSkb); + ASSERT(prDev); + + prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(prDev); + prGlueInfo = prNetDevPrivate->prGlueInfo; + ucBssIndex = prNetDevPrivate->ucBssIdx; + prGlueInfo->u8SkbToDriver++; + + kalResetPacket(prGlueInfo, (P_NATIVE_PACKET) prSkb); + + kalHardStartXmit(prSkb, prDev, prGlueInfo, ucBssIndex); + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, ucBssIndex); + if ((prP2pBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) || + (prP2pBssInfo->rStaRecOfClientList.u4NumElem > 0)) + kalPerMonStart(prGlueInfo); + + return NETDEV_TX_OK; +} /* end of p2pHardStartXmit() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief A method of struct net_device, a primary SOCKET interface to configure + * the interface lively. Handle an ioctl call on one of our devices. + * Everything Linux ioctl specific is done here. Then we pass the contents + * of the ifr->data to the request message handler. + * + * \param[in] prDev Linux kernel netdevice + * + * \param[in] prIfReq Our private ioctl request structure, typed for the generic + * struct ifreq so we can use ptr to function + * + * \param[in] cmd Command ID + * + * \retval 0 The IOCTL command is executed successfully. + * \retval <0 The execution of IOCTL command is failed. + */ +/*----------------------------------------------------------------------------*/ +int p2pDoIOCTL(struct net_device *prDev, struct ifreq *prIfReq, int i4Cmd) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + int ret = 0; + /* char *prExtraBuf = NULL; */ + /* UINT_32 u4ExtraSize = 0; */ + /* struct iwreq *prIwReq = (struct iwreq *)prIfReq; */ + /* struct iw_request_info rIwReqInfo; */ + + ASSERT(prDev && prIfReq); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + if (!prGlueInfo) { + DBGLOG(P2P, ERROR, "prGlueInfo is NULL\n"); + return -EFAULT; + } + + if (prGlueInfo->u4ReadyFlag == 0) { + DBGLOG(P2P, ERROR, "Adapter is not ready\n"); + return -EINVAL; + } + + if (i4Cmd == SIOCDEVPRIVATE + 1) { + ret = priv_support_driver_cmd(prDev, prIfReq, i4Cmd); + + } else { + DBGLOG(INIT, WARN, "Unexpected ioctl command: 0x%04x\n", i4Cmd); + ret = -1; + } + +#if 0 + /* 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)) { + DBGLOG(INIT, 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; + } +#endif /* 0 */ + + return ret; +} /* end of p2pDoIOCTL() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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_GLUE_INFO_T prGlueInfo = NULL; + struct sockaddr *sa = NULL; + UINT_32 rStatus; + UINT_32 u4BufLen; + UINT_8 aucRandomMac[MAC_ADDR_LEN]; + + prGlueInfo = *((P_GLUE_INFO_T *)netdev_priv(prDev)); + ASSERT(prGlueInfo); + + if (!prDev || !addr) { + DBGLOG(INIT, ERROR, "Set random mac addr with ndev(%d) and addr(%d)\n", + (prDev == NULL) ? 0 : 1, (addr == NULL) ? 0 : 1); + return WLAN_STATUS_INVALID_DATA; + } + + sa = (struct sockaddr *)addr; + COPY_MAC_ADDR(&aucRandomMac[0], sa->sa_data); + + DBGLOG(INIT, INFO, + "Set random mac addr to " MACSTR ".\n", + MAC2STR(aucRandomMac)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetP2pRandomMac, + &aucRandomMac[0], + sizeof(UINT_8)*MAC_ADDR_LEN, + FALSE, + FALSE, + TRUE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(P2P, ERROR, "Set random mac addr fail 0x%x\n", rStatus); + return rStatus; + } + + return WLAN_STATUS_SUCCESS; + +} + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! + * \brief To report the iw private args table to user space. + * + * \param[in] prDev Net device requested. + * \param[in] info Pointer to iw_request_info. + * \param[inout] wrqu Pointer to iwreq_data. + * \param[inout] extra + * + * \retval 0 For success. + * \retval -E2BIG For user's buffer size is too small. + * \retval -EFAULT For fail. + * + */ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_get_priv(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + struct iw_point *prData = (struct iw_point *)&wrqu->data; + UINT_16 u2BufferSize = prData->length; + + /* Update our private args table size */ + prData->length = (__u16)sizeof(rP2PIwPrivTable); + if (u2BufferSize < prData->length) + return -E2BIG; + + if (prData->length) { + if (copy_to_user(prData->pointer, rP2PIwPrivTable, sizeof(rP2PIwPrivTable))) + return -EFAULT; + } + + return 0; +} /* end of mtk_p2p_wext_get_priv() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To indicate P2P-FSM for re-associate to the connecting device + * + * \param[in] prDev Net device requested. + * \param[inout] wrqu Pointer to iwreq_data + * + * \retval 0 For success. + * \retval -EFAULT For fail. + * + */ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_reconnect(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ +#if 0 + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_MSG_HDR_T prMsgHdr; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prMsgHdr = (P_MSG_HDR_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_HDR_T)); + if (!prMsgHdr) { + ASSERT(0); /* Can't trigger P2P FSM */ + return -ENOMEM; + } + + /* 1.2 fill message */ + + DBGLOG(P2P, TRACE, "mtk_p2p_wext_reconnect: P2P Reconnect\n"); + + /* 1.3 send message */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgHdr, MSG_SEND_METHOD_BUF); +#endif + return 0; +} /* end of mtk_p2p_wext_reconnect() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief MLME command handler +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_mlme_handler(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ +#if 0 + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + struct iw_mlme *mlme = (struct iw_mlme *)extra; + P_MSG_P2P_CONNECTION_ABORT_T prMsgP2PConnAbt = (P_MSG_P2P_CONNECTION_ABORT_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + DBGLOG(P2P, TRACE, "mtk_p2p_wext_mlme_handler:\n"); + + switch (mlme->cmd) { + case IW_MLME_DISASSOC: + prMsgP2PConnAbt = + (P_MSG_HDR_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_CONNECTION_ABORT_T)); + if (!prMsgP2PConnAbt) { + ASSERT(0); /* Can't trigger P2P FSM */ + return -ENOMEM; + } + + COPY_MAC_ADDR(prMsgP2PConnAbt->aucTargetID, mlme->addr.sa_data); + + prMsgP2PConnAbt->u2ReasonCode = mlme->reason_code; + + if (EQUAL_MAC_ADDR(prMsgP2PConnAbt->aucTargetID, prP2pBssInfo->aucOwnMacAddr)) { + DBGLOG(P2P, TRACE, "P2P Connection Abort:\n"); + + /* 1.2 fill message */ + prMsgP2PConnAbt->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT; + } else { + DBGLOG(P2P, TRACE, "P2P Connection Pause:\n"); + + /* 1.2 fill message */ + } + + /* 1.3 send message */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgP2PConnAbt, MSG_SEND_METHOD_BUF); + + break; + + default: + return -EOPNOTSUPP; + } +#endif + return 0; +} /* end of mtk_p2p_wext_mlme_handler() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_PROVISION_COMPLETE) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_provision_complete(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ +#if 0 + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + struct iw_point *prData = (struct iw_point *)&wrqu->data; + P_MSG_HDR_T prMsgHdr; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + switch (prData->flags) { + case P2P_PROVISIONING_SUCCESS: + prMsgHdr = (P_MSG_HDR_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_HDR_T)); + if (!prMsgHdr) { + ASSERT(0); /* Can't trigger P2P FSM */ + return -ENOMEM; + } + + /* 1.2 fill message */ + + prGlueInfo->prP2PInfo->u4CipherPairwise = IW_AUTH_CIPHER_CCMP; + + /* 1.3 send message */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgHdr, MSG_SEND_METHOD_BUF); + + break; + + case P2P_PROVISIONING_FAIL: + + break; + + default: + return -EOPNOTSUPP; + } +#endif + + return 0; +} /* end of mtk_p2p_wext_set_provision_complete() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_START_STOP_DISCOVERY) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_start_stop_discovery(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ +#if 0 + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + struct iw_point *prData = (struct iw_point *)&wrqu->data; + P_IW_P2P_REQ_DEVICE_TYPE prReqDeviceType = (P_IW_P2P_REQ_DEVICE_TYPE) extra; + UINT_8 au4IeBuf[MAX_IE_LENGTH]; + P_MSG_HDR_T prMsgHdr; + P_MSG_P2P_DEVICE_DISCOVER_T prDiscoverMsg; + P_P2P_CONNECTION_SETTINGS_T prConnSettings; + UINT_8 aucNullAddr[] = NULL_MAC_ADDR; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + if (prData->flags == P2P_STOP_DISCOVERY) { + prMsgHdr = (P_MSG_HDR_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_HDR_T)); + + if (!prMsgHdr) { + ASSERT(0); /* Can't trigger P2P FSM */ + return -ENOMEM; + } + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgHdr, MSG_SEND_METHOD_BUF); + } else if (prData->flags == P2P_START_DISCOVERY) { + + /* retrieve IE for Probe Response */ + if (prReqDeviceType->probe_rsp_len > 0) { + if (prReqDeviceType->probe_rsp_len <= MAX_IE_LENGTH) { + if (copy_from_user + (prGlueInfo->prP2PInfo->aucWSCIE[2], + prReqDeviceType->probe_rsp_ie, prReqDeviceType->probe_rsp_len)) { + return -EFAULT; + } + prGlueInfo->prP2PInfo->u2WSCIELen[2] = prReqDeviceType->probe_rsp_len; + } else { + return -E2BIG; + } + } + + /* retrieve IE for Probe Request */ + if (prReqDeviceType->probe_req_len > 0) { + if (prReqDeviceType->probe_req_len <= MAX_IE_LENGTH) { + if (copy_from_user + (prGlueInfo->prP2PInfo->aucWSCIE[1], + prReqDeviceType->probe_req_ie, prReqDeviceType->probe_req_len)) { + return -EFAULT; + } + prGlueInfo->prP2PInfo->u2WSCIELen[1] = prReqDeviceType->probe_req_len; + } else { + return -E2BIG; + } + } + /* update IE for Probe Request */ + + if (prReqDeviceType->scan_type == P2P_LISTEN) { + /* update listening parameter */ + + /* @TODO: update prConnSettings for Probe Response IE */ + } else { + /* indicate P2P-FSM with MID_MNY_P2P_DEVICE_DISCOVERY */ + prDiscoverMsg = (P_MSG_P2P_DEVICE_DISCOVER_T) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(MSG_P2P_DEVICE_DISCOVER_T)); + + if (!prDiscoverMsg) { + ASSERT(0); /* Can't trigger P2P FSM */ + return -ENOMEM; + } + + prDiscoverMsg->rMsgHdr.eMsgId = MID_MNY_P2P_DEVICE_DISCOVERY; + prDiscoverMsg->u4DevDiscoverTime = 0; /* unlimited */ + prDiscoverMsg->fgIsSpecificType = TRUE; + prDiscoverMsg->rTargetDeviceType.u2CategoryID = + *(PUINT_16) (&(prReqDeviceType->pri_device_type[0])); + prDiscoverMsg->rTargetDeviceType.u2SubCategoryID = + *(PUINT_16) (&(prReqDeviceType->pri_device_type[6])); + COPY_MAC_ADDR(prDiscoverMsg->aucTargetDeviceID, aucNullAddr); + + /* @FIXME: parameter to be refined, where to pass IE buffer ? */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prDiscoverMsg, MSG_SEND_METHOD_BUF); + } + } else { + return -EINVAL; + } +#endif + + return 0; +} /* end of mtk_p2p_wext_start_stop_discovery() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_SET_INT) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Setting parameters not support. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_invitation_request(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + int i4Status = 0; +#if 0 + P_ADAPTER_T prAdapter = (P_ADAPTER_T) NULL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + struct iw_point *prData = (struct iw_point *)&wrqu->data; + P_IW_P2P_IOCTL_INVITATION_STRUCT prIoctlInvitation = (P_IW_P2P_IOCTL_INVITATION_STRUCT) NULL; + + do { + if ((prDev == NULL) || (extra == NULL)) { + ASSERT(FALSE); + i4Status = -EINVAL; + break; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + prIoctlInvitation = (P_IW_P2P_IOCTL_INVITATION_STRUCT) extra; + + if (prGlueInfo == NULL) { + i4Status = -EINVAL; + break; + } + + prAdapter = prGlueInfo->prAdapter; + + if (prAdapter == NULL) { + i4Status = -EINVAL; + break; + } + + if (prIoctlInvitation->ucReinvoke == 1) { + /* TODO: Set Group ID */ + p2pFuncSetGroupID(prAdapter, prIoctlInvitation->aucGroupID, + prIoctlInvitation->aucSsid, prIoctlInvitation->u4SsidLen); + } + + else { + P_MSG_P2P_INVITATION_REQUEST_T prMsgP2PInvitationReq = (P_MSG_P2P_INVITATION_REQUEST_T) NULL; + + /* TODO: Do Invitation. */ + prMsgP2PInvitationReq = + (P_MSG_P2P_INVITATION_REQUEST_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(MSG_P2P_INVITATION_REQUEST_T)); + if (!prMsgP2PInvitationReq) { + ASSERT(0); /* Can't trigger P2P FSM */ + i4Status = -ENOMEM; + break; + } + + /* 1.2 fill message */ + kalMemCopy(prMsgP2PInvitationReq->aucDeviceID, prIoctlInvitation->aucDeviceID, MAC_ADDR_LEN); + + DBGLOG(P2P, TRACE, "mtk_p2p_wext_invitation_request: P2P Invitation Req\n"); + + /* 1.3 send message */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgP2PInvitationReq, MSG_SEND_METHOD_BUF); + + } + + } while (FALSE); +#endif + + return i4Status; + +} + +/* mtk_p2p_wext_invitation_request */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_SET_INT) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Setting parameters not support. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_invitation_abort(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + int i4Status = 0; +#if 0 + P_ADAPTER_T prAdapter = (P_ADAPTER_T) NULL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + struct iw_point *prData = (struct iw_point *)&wrqu->data; + P_IW_P2P_IOCTL_ABORT_INVITATION prIoctlInvitationAbort = (P_IW_P2P_IOCTL_ABORT_INVITATION) NULL; + + UINT_8 bssid[MAC_ADDR_LEN]; + + do { + if ((prDev == NULL) || (extra == NULL)) { + ASSERT(FALSE); + i4Status = -EINVAL; + break; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + prIoctlInvitationAbort = (P_IW_P2P_IOCTL_ABORT_INVITATION) extra; + + if (prGlueInfo == NULL) { + i4Status = -EINVAL; + break; + } + + prAdapter = prGlueInfo->prAdapter; + + if (prAdapter == NULL) { + i4Status = -EINVAL; + } 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 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 (GLUE_CHK_PR2(prDev, prAuth) == FALSE) + 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) */ + mtk_p2p_wext_set_key_prkit(); + } 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() */ + +/* For resolve error and warning of AOSP coding style check */ +/* To be fixed */ +void mtk_p2p_wext_set_key_prkit(void) +{ + 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; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ + 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 (GLUE_CHK_PR2(prNetDev, prPower) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* 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, WARN, "%s(): unsupported power management mode value = %d.\n", + __func__, prPower->value; + + return -EINVAL; + } + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetP2pPowerSaveProfile, + &ePowerMode, sizeof(ePowerMode), FALSE, FALSE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + /* DBGLOG(INIT, INFO, ("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) +{ + /* 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 (GLUE_CHK_PR2(prNetDev, prPower) == FALSE) + 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); + + 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); + + 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); + + } +#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) +{ +#if 0 /* Marked for MT6630 (New ucBssIndex) */ + 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 */ +#endif + + 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); + + pu4IntBuf = (PUINT_32) extra; + + if (GLUE_CHK_PR2(prDev, wrqu) == FALSE) + return -EINVAL; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prP2pSpecificBssInfo = prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo; + prP2pConnSettings = prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings; + prP2pFsmInfo = prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo; + + u4SubCmd = (UINT_32) wrqu->mode; + index = pu4IntBuf[1]; + value = pu4IntBuf[2]; + + DBGLOG(INIT, WARN, + "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 (GLUE_CHK_PR2(prDev, wrqu) == FALSE) + return -EINVAL; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + u4SubCmd = (UINT_32) wrqu->data.flags; + + kalMemZero(&prGlueInfo->prP2PInfo->aucOidBuf[0], sizeof(prGlueInfo->prP2PInfo->aucOidBuf)); + + switch (u4SubCmd) { + case PRIV_CMD_OID: + if (copy_from_user(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), wrqu->data.pointer, wrqu->data.length)) { + status = -EFAULT; + break; + } + + if (!kalMemCmp(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), extra, wrqu->data.length)) + DBGLOG(INIT, WARN, "extra buffer is valid\n"); + else + DBGLOG(INIT, WARN, "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)) + DBGLOG(INIT, WARN, "extra buffer is valid\n"); + else + DBGLOG(INIT, WARN, "extra 0x%p\n", extra); + prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucSecCheck[0])); + + switch (prP2PReq->u4CmdId) { + case P2P_CMD_ID_SEC_CHECK: + status = mtk_p2p_wext_set_sec_check_request(prDev, info, wrqu, (char *)prP2PReq); + break; + default: + status = -EOPNOTSUPP; + } + break; +#endif + case PRIV_CMD_P2P_VERSION: + if (copy_from_user(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), wrqu->data.pointer, wrqu->data.length)) { + status = -EFAULT; + break; + } + + if (!kalMemCmp(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), extra, wrqu->data.length)) + DBGLOG(INIT, WARN, "extra buffer is valid\n"); + else + DBGLOG(INIT, WARN, "extra 0x%p\n", extra); + + prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucOidBuf[0])); + switch (prP2PReq->u4CmdId) { + case P2P_CMD_ID_P2P_VERSION: + status = mtk_p2p_wext_set_p2p_version(prDev, info, wrqu, (char *)prP2PReq); + break; + default: + status = -EOPNOTSUPP; + break; + } + break; + default: + status = -EOPNOTSUPP; + break; + } + + return status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_GET_STRUCT) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_get_struct(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + int status = 0; + UINT_32 u4SubCmd = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = NULL; + + ASSERT(prDev); + ASSERT(wrqu); + + if (!prDev || !wrqu) { + DBGLOG(INIT, WARN, "%s(): invalid param(0x%p, 0x%p)\n", __func__, prDev, wrqu); + return -EINVAL; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + u4SubCmd = (UINT_32) wrqu->data.flags; + + kalMemZero(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), sizeof(prGlueInfo->prP2PInfo->aucOidBuf)); + + switch (u4SubCmd) { + case PRIV_CMD_OID: + if (copy_from_user(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), + wrqu->data.pointer, sizeof(IW_P2P_TRANSPORT_STRUCT))) { + DBGLOG(INIT, WARN, "%s() copy_from_user oidBuf fail\n", __func__); + return -EFAULT; + } + + prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucOidBuf[0])); + + switch (prP2PReq->u4CmdId) { + case P2P_CMD_ID_GET_SD_REQUEST: + status = mtk_p2p_wext_get_service_discovery_request(prDev, info, wrqu, (char *)prP2PReq); + break; + + case P2P_CMD_ID_GET_SD_RESPONSE: + status = mtk_p2p_wext_get_service_discovery_response(prDev, info, wrqu, (char *)prP2PReq); + break; + + case P2P_CMD_ID_INVITATION_INDICATE: + { + status = + mtk_p2p_wext_invitation_indicate(prDev, info, wrqu, (char *)(prP2PReq->aucBuffer)); + prP2PReq->outBufferLength = wrqu->data.length; + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + wrqu->data.length + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + DBGLOG(INIT, WARN, "%s() copy_to_user() fail\n", __func__); + return -EIO; + } else { + return 0; + } + break; + } + case P2P_CMD_ID_INVITATION_STATUS: + { + status = + mtk_p2p_wext_invitation_status(prDev, info, wrqu, (char *)(prP2PReq->aucBuffer)); + prP2PReq->outBufferLength = wrqu->data.length; + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + wrqu->data.length + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + DBGLOG(INIT, WARN, "%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))) { + DBGLOG(INIT, WARN, "%s() copy_to_user() fail\n", __func__); + return -EIO; + } else { + return 0; + } + break; + } + + case P2P_CMD_ID_GET_OP_CH: + { + prP2PReq->inBufferLength = 4; + + status = wlanoidQueryP2pOpChannel(prGlueInfo->prAdapter, + prP2PReq->aucBuffer, + prP2PReq->inBufferLength, &prP2PReq->outBufferLength); + + if (status == 0) { /* WLAN_STATUS_SUCCESS */ + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + prP2PReq->outBufferLength + + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + DBGLOG(INIT, WARN, "%s() copy_to_user() fail\n", __func__); + return -EIO; + } + } else { + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + DBGLOG(INIT, WARN, "%s() copy_to_user() fail\n", __func__); + return -EIO; + } + } + break; + } + + default: + status = -EOPNOTSUPP; + } + + break; +#if CFG_SUPPORT_ANTI_PIRACY + case PRIV_SEC_CHECK_OID: + if (wrqu->data.length > 256) { + status = -EOPNOTSUPP; + break; + } + if (copy_from_user(&(prGlueInfo->prP2PInfo->aucSecCheck[0]), + wrqu->data.pointer, sizeof(IW_P2P_TRANSPORT_STRUCT))) { + DBGLOG(INIT, WARN, "%s() copy_from_user oidBuf fail\n", __func__); + return -EFAULT; + } + + prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucSecCheck[0])); + + switch (prP2PReq->u4CmdId) { + case P2P_CMD_ID_SEC_CHECK: + status = mtk_p2p_wext_get_sec_check_response(prDev, info, wrqu, (char *)prP2PReq); + break; + default: + status = -EOPNOTSUPP; + } + break; +#endif + case PRIV_CMD_P2P_VERSION: + if (copy_from_user(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), + wrqu->data.pointer, sizeof(IW_P2P_TRANSPORT_STRUCT))) { + DBGLOG(INIT, WARN, "%s() copy_from_user oidBuf fail\n", __func__); + return -EFAULT; + } + + prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucOidBuf[0])); + + switch (prP2PReq->u4CmdId) { + case P2P_CMD_ID_P2P_VERSION: + status = mtk_p2p_wext_get_p2p_version(prDev, info, wrqu, (char *)prP2PReq); + break; + default: + status = -EOPNOTSUPP; + break; + } + + /* Copy queried data to user. */ + if (status == 0) { /* WLAN_STATUS_SUCCESS */ + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + prP2PReq->outBufferLength + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + DBGLOG(INIT, WARN, "%s() copy_to_user() fail\n", __func__); + return -EIO; + } + } + + else { + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + DBGLOG(INIT, WARN, "%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; + + prP2PReq->outBufferLength = u4QueryInfoLen; + + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + u4QueryInfoLen + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + DBGLOG(INIT, WARN, "%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; + + prP2PReq->outBufferLength = u4QueryInfoLen; + + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + u4QueryInfoLen + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + DBGLOG(INIT, WARN, "%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); + + DBGLOG(INIT, INFO, "mtk_p2p_wext_get_sec_check_response\n"); + rStatus = kalIoctl(prGlueInfo, + wlanoidGetSecCheckResponse, + prP2PReq->aucBuffer, prP2PReq->outBufferLength, TRUE, FALSE, TRUE, TRUE, &u4QueryInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + prP2PReq->outBufferLength = u4QueryInfoLen; + + if (copy_to_user(wrqu->data.pointer, + prP2PReq->aucBuffer, u4QueryInfoLen + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + DBGLOG(INIT, WARN, "%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_STRUCT_T prNoaParam = (P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T) extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + DBGLOG(INIT, INFO, "mtk_p2p_wext_set_noa_param\n"); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetNoaParam, prNoaParam, /* prP2PReq->aucBuffer, */ + sizeof(PARAM_CUSTOM_NOA_PARAM_STRUCT_T), /* prP2PReq->inBufferLength, */ + FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + else + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_oppps_param(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4SetInfoLen; +/* P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT)extra; */ + P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T prOppPsParam = (P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T) extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + DBGLOG(INIT, INFO, "mtk_p2p_wext_set_oppps_param\n"); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetOppPsParam, prOppPsParam, /* prP2PReq->aucBuffer, */ + sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T), /* prP2PReq->inBufferLength, */ + FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + else + return 0; +} + +int +mtk_p2p_wext_set_p2p_version(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; + UINT_32 u4SetInfoLen; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetP2pSupplicantVersion, + prP2PReq->aucBuffer, prP2PReq->inBufferLength, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + else + return rStatus; + +} + +/* mtk_p2p_wext_set_p2p_version */ + +int +mtk_p2p_wext_get_p2p_version(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4QueryInfoLen; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryP2pVersion, + prP2PReq->aucBuffer, prP2PReq->outBufferLength, TRUE, FALSE, TRUE, TRUE, &u4QueryInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + else + return rStatus; + +} /* mtk_p2p_wext_get_p2p_version */ + +#if CFG_SUPPORT_P2P_RSSI_QUERY + +int +mtk_p2p_wext_get_rssi(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4QueryInfoLen; + struct iw_point *prData = (struct iw_point *)&wrqu->data; + UINT_16 u2BufferSize = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Rssi; + struct iw_statistics *pStats = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + if (!prGlueInfo) { + rStatus = WLAN_STATUS_FAILURE; + goto stat_out; + } + + pStats = (struct iw_statistics *)(&(prGlueInfo->rP2pIwStats)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryP2pRssi, &i4Rssi, sizeof(i4Rssi), TRUE, TRUE, TRUE, TRUE, &u4QueryInfoLen); + + u2BufferSize = prData->length; + + if (u2BufferSize < sizeof(struct iw_statistics)) + return -E2BIG; + + if (copy_to_user(prData->pointer, pStats, sizeof(struct iw_statistics))) + rStatus = WLAN_STATUS_FAILURE; + +stat_out: + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + else + return rStatus; + +} /* mtk_p2p_wext_get_rssi */ + +struct iw_statistics *mtk_p2p_wext_get_wireless_stats(struct net_device *prDev) +{ + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + P_GLUE_INFO_T prGlueInfo = NULL; + struct iw_statistics *pStats = NULL; + INT_32 i4Rssi; + UINT_32 bufLen = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) + goto stat_out; + + pStats = (struct iw_statistics *)(&(prGlueInfo->rP2pIwStats)); + + if (!prDev || !netif_carrier_ok(prDev)) { + /* network not connected */ + goto stat_out; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryP2pRssi, &i4Rssi, sizeof(i4Rssi), TRUE, TRUE, TRUE, TRUE, &bufLen); + +stat_out: + return pStats; +} /* mtk_p2p_wext_get_wireless_stats */ + +#endif /* CFG_SUPPORT_P2P_RSSI_QUERY */ + +int +mtk_p2p_wext_set_txpow(IN struct net_device *prDev, + IN struct iw_request_info *prIwrInfo, IN OUT union iwreq_data *prTxPow, IN char *pcExtra) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + P_ADAPTER_T prAdapter = (P_ADAPTER_T) NULL; +#if 0 + P_MSG_P2P_FUNCTION_SWITCH_T prMsgFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) NULL; +#endif + int i4Ret = 0; + + ASSERT(prDev); + ASSERT(prTxPow); + + do { + if ((!prDev) || (!prTxPow)) { + i4Ret = -EINVAL; + break; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + + if (!prGlueInfo) { + i4Ret = -EINVAL; + break; + } + + prAdapter = prGlueInfo->prAdapter; +#if 0 + prMsgFuncSwitch = + (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(MSG_P2P_FUNCTION_SWITCH_T)); + if (!prMsgFuncSwitch) { + ASSERT(0); + return -ENOMEM; + } + + prMsgFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; + + if (prTxPow->disabled) { + /* Dissolve. */ + prMsgFuncSwitch->fgIsFuncOn = FALSE; + } else { + + /* Re-enable function. */ + prMsgFuncSwitch->fgIsFuncOn = TRUE; + } + + /* 1.3 send message */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgFuncSwitch, MSG_SEND_METHOD_BUF); +#endif + + } while (FALSE); + + return i4Ret; +} /* mtk_p2p_wext_set_txpow */ + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_p2p_cfg80211.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_p2p_cfg80211.c new file mode 100644 index 0000000000000..f7b0038f08a1e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_p2p_cfg80211.c @@ -0,0 +1,2262 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * 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 +******************************************************************************** +*/ + +#include "config.h" + +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#include +#include +#include +#include +#include + +#include "precomp.h" +#include "gl_cfg80211.h" +#include "gl_p2p_ioctl.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wformat" +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +static BOOLEAN __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 KAL_BAND_2GHZ: + prRfChnlInfo->eBand = BAND_2G4; + break; + case KAL_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; +} /* __channel_format_switch */ + + +INT_32 mtk_Netdev_To_RoleIdx(P_GL_P2P_INFO_T prGlP2pInfo, struct net_device *ndev, PUINT_8 pucRoleIdx) +{ + INT_32 i4Ret = -1; + UINT_32 u4Idx = 0; + + if (pucRoleIdx == NULL) + return i4Ret; + + for (u4Idx = 0; u4Idx < KAL_P2P_NUM; u4Idx++) { + if (prGlP2pInfo->aprRoleHandler[u4Idx] == ndev) { + *pucRoleIdx = (UINT_8) u4Idx; + i4Ret = 0; + } + } +#if 1 + i4Ret = 0; + *pucRoleIdx = 0; +#endif + return i4Ret; + +} /* mtk_Netdev_To_RoleIdx */ + +struct wireless_dev * +mtk_p2p_cfg80211_add_iface(struct wiphy *wiphy, + const char *name, + enum nl80211_iftype type, u32 *flags, struct vif_params *params) +{ + /* 2 TODO: Fit kernel 3.10 modification */ +#if 0 + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + struct net_device *prNewNetDevice = NULL; + UINT_32 u4Idx = 0; + P_GL_P2P_INFO_T prP2pInfo = (P_GL_P2P_INFO_T) NULL; + + do { + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + if (prGlueInfo == NULL) + break; + + prP2pInfo = prGlueInfo->prP2PInfo; + + for (u4Idx = 0; u4Idx < KAL_P2P_NUM; u4Idx++) { + if (prP2pInfo->aprRoleHandler[u4Idx] == NULL) + p2pRoleFsmInit(prGlueInfo->prAdapter, u4Idx); + else if (prP2pInfo->aprRoleHandler[u4Idx] == prP2pInfo->prDevHandler) + break; + } + + if (u4Idx == 2) { + /* Role port full. */ + break; + } + + prNewNetDevice = alloc_netdev_mq(sizeof(P_GLUE_INFO_T), name, + NET_NAME_PREDICTABLE, ether_setup, CFG_MAX_TXQ_NUM); + + if (prNewNetDevice == NULL) + break; + + prP2pInfo->aprRoleHandler[u4Idx] = prNewNetDevice; + + *((P_GLUE_INFO_T *) netdev_priv(prNewNetDevice)) = prGlueInfo; + + ether_addr_copy(prNewNetDevice->perm_addr, prGlueInfo->prAdapter->rWifiVar.aucInterfaceAddress); + prNewNetDevice->dev_addr = prNewNetDevice->perm_addr; + + prNewNetDevice->netdev_ops = &p2p_netdev_ops; + +#if (MTK_WCN_HIF_SDIO == 0) + SET_NETDEV_DEV(prNewNetDevice, &(prGlueInfo->rHifInfo.func->dev)); +#endif + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + prNewNetDevice->ieee80211_ptr = &(prP2pInfo->wdev); +#endif + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + prNewNetDevice->features = NETIF_F_IP_CSUM; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + } while (FALSE); + + return prNewNetDevice; + +#else + return NULL; +#endif +} /* mtk_p2p_cfg80211_add_iface */ + +int mtk_p2p_cfg80211_del_iface(struct wiphy *wiphy, + struct wireless_dev *wdev) +{ + /* TODO: */ + return 0; +} /* mtk_p2p_cfg80211_del_iface */ + +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; + UINT_8 ucRoleIdx = 0; + const UINT_8 aucBCAddr[] = BC_MAC_ADDR; + const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo->prP2PInfo, ndev, &ucRoleIdx) != 0) + return -EINVAL; +#if 1 + /* DBG */ + DBGLOG(RSN, TRACE, "mtk_p2p_cfg80211_add_key\n"); + if (mac_addr) { + DBGLOG(RSN, TRACE, + "keyIdx = %d pairwise = %d mac = " MACSTR "\n", key_index, pairwise, MAC2STR(mac_addr)); + } else { + DBGLOG(RSN, TRACE, "keyIdx = %d pairwise = %d null mac\n", key_index, pairwise); + } + DBGLOG(RSN, TRACE, "Cipher = %x\n", params->cipher); + DBGLOG_MEM8(RSN, TRACE, params->key, params->key_len); +#endif + + if (params->key_len > 32) { + DBGLOG(RSN, WARN, "key_len [%d] is invalid!\n", + params->key_len); + return -EINVAL; + } + + /* Todo:: By Cipher to set the key */ + + kalMemZero(&rKey, sizeof(P2P_PARAM_KEY_T)); + + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &rKey.ucBssIdx) != WLAN_STATUS_SUCCESS) + return -EINVAL; + + rKey.u4KeyIndex = key_index; + + if (params->cipher) { + switch (params->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + rKey.ucCipher = CIPHER_SUITE_WEP40; + break; + case WLAN_CIPHER_SUITE_WEP104: + rKey.ucCipher = CIPHER_SUITE_WEP104; + break; +#if 0 + case WLAN_CIPHER_SUITE_WEP128: + rKey.ucCipher = CIPHER_SUITE_WEP128; + break; +#endif + case WLAN_CIPHER_SUITE_TKIP: + rKey.ucCipher = CIPHER_SUITE_TKIP; + break; + case WLAN_CIPHER_SUITE_CCMP: + rKey.ucCipher = CIPHER_SUITE_CCMP; + break; +#if 0 + case WLAN_CIPHER_SUITE_GCMP: + rKey.ucCipher = CIPHER_SUITE_GCMP; + break; + case WLAN_CIPHER_SUITE_CCMP_256: + rKey.ucCipher = CIPHER_SUITE_CCMP256; + break; +#endif + case WLAN_CIPHER_SUITE_SMS4: + rKey.ucCipher = CIPHER_SUITE_WPI; + break; + + case WLAN_CIPHER_SUITE_AES_CMAC: + rKey.ucCipher = CIPHER_SUITE_BIP; + break; + default: + ASSERT(FALSE); + } +} + + if (mac_addr) { + if (EQUAL_MAC_ADDR(mac_addr, aucZeroMacAddr)) + COPY_MAC_ADDR(rKey.arBSSID, aucBCAddr); + else + COPY_MAC_ADDR(rKey.arBSSID, mac_addr); + + if (pairwise) { + /* + * if (!((rKey.arBSSID[0] + * & rKey.arBSSID[1] + * & rKey.arBSSID[2] + * & rKey.arBSSID[3] + * & rKey.arBSSID[4] + * & rKey.arBSSID[5]) == 0xFF)) { + * rKey.u4KeyIndex |= BIT(31); + * } + */ + rKey.u4KeyIndex |= BIT(31); /* Tx */ + rKey.u4KeyIndex |= BIT(30); /* Pairwise */ + } + } else { + COPY_MAC_ADDR(rKey.arBSSID, aucBCAddr); + } + + if (params->key) + kalMemCopy(rKey.aucKeyMaterial, params->key, params->key_len); + rKey.u4KeyLength = params->key_len; + rKey.u4Length = ((ULONG)&(((P_P2P_PARAM_KEY_T) 0)->aucKeyMaterial)) + rKey.u4KeyLength; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetAddP2PKey, &rKey, rKey.u4Length, FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus == WLAN_STATUS_SUCCESS) + i4Rslt = 0; + + DBGLOG(RSN, TRACE, "mtk_p2p_cfg80211_add_key i4Rslt=%d\n", i4Rslt); + + 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 rRemoveKey; + INT_32 i4Rslt = -EINVAL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + UINT_8 ucRoleIdx = 0; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo->prP2PInfo, ndev, &ucRoleIdx) < 0) + return -EINVAL; +#if 1 + /* DBG */ + DBGLOG(RSN, TRACE, "mtk_p2p_cfg80211_del_key\n"); + if (mac_addr) { + DBGLOG(RSN, TRACE, + "keyIdx = %d pairwise = %d mac = " MACSTR "\n", key_index, pairwise, MAC2STR(mac_addr)); + } else { + DBGLOG(RSN, TRACE, "keyIdx = %d pairwise = %d null mac\n", key_index, pairwise); + } +#endif + + kalMemZero(&rRemoveKey, sizeof(PARAM_REMOVE_KEY_T)); + + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &rRemoveKey.ucBssIdx) != WLAN_STATUS_SUCCESS) + return -EINVAL; + + if (mac_addr) + COPY_MAC_ADDR(rRemoveKey.arBSSID, mac_addr); + rRemoveKey.u4KeyIndex = key_index; + rRemoveKey.u4Length = sizeof(PARAM_REMOVE_KEY_T); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRemoveP2PKey, &rRemoveKey, rRemoveKey.u4Length, FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_SUCCESS) + i4Rslt = 0; + + return i4Rslt; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for setting the default mgmt key index + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_p2p_cfg80211_set_mgmt_key(struct wiphy *wiphy, struct net_device *dev, u8 key_index) +{ + DBGLOG(RSN, INFO, "mtk_p2p_cfg80211_set_mgmt_key, kid:%d\n", key_index); + + return 0; +} + + +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; + /* PARAM_DEFAULT_KEY_T rDefaultKey; */ + UINT_8 ucRoleIdx = 0; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + INT_32 i4Rst = -EINVAL; + /* UINT_32 u4BufLen = 0; */ + /* BOOLEAN fgDef = FALSE, fgMgtDef = FALSE; */ + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo->prP2PInfo, netdev, &ucRoleIdx) != 0) + return -EINVAL; +#if 1 + /* DBG */ + DBGLOG(RSN, TRACE, "mtk_p2p_cfg80211_set_default_key\n"); + DBGLOG(RSN, TRACE, "keyIdx = %d unicast = %d multicast = %d\n", key_index, unicast, multicast); +#endif +#if 0 + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &rDefaultKey.ucBssIdx) != WLAN_STATUS_SUCCESS) + return -EINVAL; + + rDefaultKey.ucKeyID = key_index; + rDefaultKey.ucUnicast = unicast; + rDefaultKey.ucMulticast = multicast; + if (rDefaultKey.ucUnicast && !rDefaultKey.ucMulticast) + return -EINVAL; + + if (rDefaultKey.ucUnicast && rDefaultKey.ucMulticast) + fgDef = TRUE; + + if (!rDefaultKey.ucUnicast && rDefaultKey.ucMulticast) + fgMgtDef = TRUE; +#endif +#if 0 + rStatus = kalIoctl(prGlueInfo, + wlanoidSetDefaultP2PKey, + &rDefaultKey, sizeof(PARAM_DEFAULT_KEY_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); +#endif + + if (rStatus == WLAN_STATUS_SUCCESS) + i4Rst = 0; + + return i4Rst; +} + +int mtk_p2p_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, + const u8 *mac, struct station_info *sinfo) +{ + INT_32 i4RetRslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + P_GL_P2P_INFO_T prP2pGlueInfo = (P_GL_P2P_INFO_T) NULL; + P2P_STATION_INFO_T rP2pStaInfo; + + ASSERT(wiphy); + + do { + if ((wiphy == NULL) || (ndev == NULL) || (sinfo == NULL) || (mac == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_get_station\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + prP2pGlueInfo = prGlueInfo->prP2PInfo; + + sinfo->filled = 0; + + /* Get station information. */ + /* 1. Inactive time? */ + p2pFuncGetStationInfo(prGlueInfo->prAdapter, (PUINT_8)mac, &rP2pStaInfo); + + /* Inactive time. */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME); +#else + sinfo->filled |= STATION_INFO_INACTIVE_TIME; +#endif + sinfo->inactive_time = rP2pStaInfo.u4InactiveTime; + sinfo->generation = prP2pGlueInfo->i4Generation; + + i4RetRslt = 0; + } while (FALSE); + + return i4RetRslt; +} + +int mtk_p2p_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + P_GL_P2P_INFO_T prP2pGlueInfo = (P_GL_P2P_INFO_T) NULL; + P_MSG_P2P_SCAN_REQUEST_T prMsgScanRequest = (P_MSG_P2P_SCAN_REQUEST_T) NULL; + UINT_32 u4MsgSize = 0, u4Idx = 0; + INT_32 i4RetRslt = -EINVAL; + P_RF_CHANNEL_INFO_T prRfChannelInfo = (P_RF_CHANNEL_INFO_T) NULL; + P_P2P_SSID_STRUCT_T prSsidStruct = (P_P2P_SSID_STRUCT_T) NULL; + struct ieee80211_channel *prChannel = NULL; + struct cfg80211_ssid *prSsid = NULL; + UINT_8 ucBssIdx = 0; + + /* [---------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"); + } + /* TODO: */ + /* Find a way to distinct DEV port scan & ROLE port scan. + */ + ucBssIdx = P2P_DEV_BSS_INDEX; + DBGLOG(P2P, TRACE, "Device Port Scan.\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) { + DBGLOG(P2P, TRACE, "Allocate MsgScanRequest failed\n"); + i4RetRslt = -ENOMEM; + break; + } + + DBGLOG(P2P, TRACE, "Generating scan request message.\n"); + + prMsgScanRequest->rMsgHdr.eMsgId = MID_MNY_P2P_DEVICE_DISCOVERY; + prMsgScanRequest->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prMsgScanRequest->ucBssIdx = ucBssIdx; + + DBGLOG(P2P, INFO, "Requesting channel number:%d.\n", request->n_channels); + + for (u4Idx = 0; u4Idx < request->n_channels; u4Idx++) { + /* Translate Freq from MHz to channel number. */ + prRfChannelInfo = &(prMsgScanRequest->arChannelListInfo[u4Idx]); + prChannel = request->channels[u4Idx]; + + prRfChannelInfo->ucChannelNum = nicFreq2ChannelNum(prChannel->center_freq * 1000); + DBGLOG(P2P, TRACE, "Scanning Channel: %d, freq: %d\n", + prRfChannelInfo->ucChannelNum, prChannel->center_freq); + switch (prChannel->band) { + case KAL_BAND_2GHZ: + prRfChannelInfo->eBand = BAND_2G4; + break; + case KAL_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((ULONG) prSsidStruct == (ULONG)&(prMsgScanRequest->arChannelListInfo[u4Idx])); + prMsgScanRequest->prSSID = prSsidStruct; + } + + for (u4Idx = 0; u4Idx < request->n_ssids; u4Idx++) { + COPY_SSID(prSsidStruct->aucSsid, + prSsidStruct->ucSsidLen, request->ssids->ssid, request->ssids->ssid_len); + + prSsidStruct++; + prSsid++; + } + + prMsgScanRequest->i4SsidNum = request->n_ssids; + + DBGLOG(P2P, TRACE, "Finish SSID list:%d.\n", request->n_ssids); + + /* IE BUFFERS */ + prMsgScanRequest->pucIEBuf = (PUINT_8) prSsidStruct; + if (request->ie_len) { + kalMemCopy(prMsgScanRequest->pucIEBuf, request->ie, request->ie_len); + prMsgScanRequest->u4IELen = request->ie_len; + } else { + prMsgScanRequest->u4IELen = 0; + } + + 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, + struct wireless_dev *wdev, + enum nl80211_tx_power_setting type, int mbm) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* not implemented yet */ + + return -EINVAL; +} + +int mtk_p2p_cfg80211_get_txpower(struct wiphy *wiphy, + struct wireless_dev *wdev, + int *dbm) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* not implemented yet */ + + return -EINVAL; +} + +int mtk_p2p_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, bool enabled, int timeout) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_POWER_MODE ePowerMode; + PARAM_POWER_MODE_T rPowerMode; + UINT_32 u4Leng; + UINT_8 ucRoleIdx; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (enabled) + ePowerMode = Param_PowerModeFast_PSP; + else + ePowerMode = Param_PowerModeCAM; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_set_power_mgmt ps=%d.\n", enabled); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo->prP2PInfo, ndev, &ucRoleIdx) != 0) + return -EINVAL; + + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &rPowerMode.ucBssIdx) != WLAN_STATUS_SUCCESS) + return -EINVAL; + + rPowerMode.ePowerMode = ePowerMode; + + /* p2p_set_power_save */ + kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, &rPowerMode, sizeof(rPowerMode), FALSE, FALSE, TRUE, &u4Leng); + + return 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; + UINT_8 ucRoleIdx = 0; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_start_ap.\n"); + + do { + if ((wiphy == NULL) || (settings == NULL)) + break; + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo->prP2PInfo, dev, &ucRoleIdx) < 0) + break; + + mtk_p2p_cfg80211_set_channel(wiphy, &settings->chandef); + + 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->ucRoleIndex = ucRoleIdx; + 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 = pucBuffer + settings->beacon.head_len; + } else { + prP2pBcnUpdateMsg->u4BcnHdrLen = 0; + + prP2pBcnUpdateMsg->pucBcnHdr = NULL; + } + + if (settings->beacon.tail_len != 0) { + kalMemCopy(pucBuffer, settings->beacon.tail, settings->beacon.tail_len); + + prP2pBcnUpdateMsg->u4BcnBodyLen = settings->beacon.tail_len; + + prP2pBcnUpdateMsg->pucBcnBody = pucBuffer; + } 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->u4BcnInterval = settings->beacon_interval; + + prP2pStartAPMsg->u4DtimPeriod = settings->dtim_period; + + switch (settings->hidden_ssid) { + case NL80211_HIDDEN_SSID_ZERO_LEN: + prP2pStartAPMsg->eHiddenSsidType = ENUM_HIDDEN_SSID_ZERO_LEN; + break; + case NL80211_HIDDEN_SSID_ZERO_CONTENTS: + prP2pStartAPMsg->eHiddenSsidType = ENUM_HIDDEN_SSID_ZERO_CONTENT; + break; + default: + prP2pStartAPMsg->eHiddenSsidType = ENUM_HIDDEN_SSID_NONE; + break; + } + + prP2pStartAPMsg->fgIsPrivacy = settings->privacy; + + prP2pStartAPMsg->ucRoleIdx = ucRoleIdx; + + kalP2PSetRole(prGlueInfo, 2); + + 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; +} /* mtk_p2p_cfg80211_start_ap */ + +/* + * 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; + * }; + */ + +int mtk_p2p_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_beacon_data *beacon) +{ + 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; + UINT_8 ucRoleIdx = 0; + + do { + if ((wiphy == NULL) || (beacon == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_change_beacon.\n"); + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo->prP2PInfo, dev, &ucRoleIdx) < 0) + break; + + if ((beacon->head_len != 0) || (beacon->tail_len != 0)) { + prP2pBcnUpdateMsg = + (P_MSG_P2P_BEACON_UPDATE_T) cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + (sizeof(MSG_P2P_BEACON_UPDATE_T) + + beacon->head_len + beacon->tail_len)); + + if (prP2pBcnUpdateMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prP2pBcnUpdateMsg->ucRoleIndex = ucRoleIdx; + prP2pBcnUpdateMsg->rMsgHdr.eMsgId = MID_MNY_P2P_BEACON_UPDATE; + pucBuffer = prP2pBcnUpdateMsg->aucBuffer; + + if (beacon->head_len != 0) { + kalMemCopy(pucBuffer, beacon->head, beacon->head_len); + + prP2pBcnUpdateMsg->u4BcnHdrLen = beacon->head_len; + + prP2pBcnUpdateMsg->pucBcnHdr = pucBuffer; + + pucBuffer = pucBuffer + beacon->head_len; + } else { + prP2pBcnUpdateMsg->u4BcnHdrLen = 0; + + prP2pBcnUpdateMsg->pucBcnHdr = NULL; + } + + if (beacon->tail_len != 0) { + kalMemCopy(pucBuffer, beacon->tail, beacon->tail_len); + + prP2pBcnUpdateMsg->u4BcnBodyLen = beacon->tail_len; + + prP2pBcnUpdateMsg->pucBcnBody = pucBuffer; + } else { + prP2pBcnUpdateMsg->u4BcnBodyLen = 0; + prP2pBcnUpdateMsg->pucBcnBody = NULL; + } + + kalP2PSetRole(prGlueInfo, 2); + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, (P_MSG_HDR_T) prP2pBcnUpdateMsg, MSG_SEND_METHOD_BUF); + + } + } while (FALSE); + return i4Rslt; +} /* mtk_p2p_cfg80211_change_beacon */ + + +int mtk_p2p_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + INT_32 i4Rslt = -EINVAL; + + UINT_8 u4Idx = 0; + UINT_32 rStatus; + UINT_32 u4BufLen; + + do { + if (wiphy == NULL) { + DBGLOG(P2P, ERROR, "wiphy == NULL\n"); + break; + } + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_stop_ap.\n"); + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (prGlueInfo == NULL) { + DBGLOG(P2P, ERROR, "prGlueInfo == NULL\n"); + break; + } + + if (mtk_Netdev_To_RoleIdx(prGlueInfo->prP2PInfo, dev, &u4Idx) < 0) { + DBGLOG(P2P, ERROR, + "mtk_Netdev_To_RoleIdx fail idx(%u).\n", u4Idx); + break; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidStopApRole, + &u4Idx, sizeof(unsigned char), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(P2P, ERROR, "stop ap fail 0x%x\n", rStatus); + break; + } + + 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) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* not implemented yet */ + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_deauth.\n"); + + return -EINVAL; +} /* mtk_p2p_cfg80211_deauth */ + +/* TODO: */ +int mtk_p2p_cfg80211_disassoc(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_disassoc_request *req) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_disassoc.\n"); + + /* not implemented yet */ + + return -EINVAL; +} /* mtk_p2p_cfg80211_disassoc */ + +int mtk_p2p_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, + unsigned int duration, u64 *cookie) +{ + INT_32 i4Rslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + P_MSG_P2P_CHNL_REQUEST_T prChnlReqMsg = (P_MSG_P2P_CHNL_REQUEST_T) NULL; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_remain_on_channel\n"); + + 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++; + + prChnlReqMsg = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_CHNL_REQUEST_T)); + + if (prChnlReqMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + DBGLOG(P2P, INFO, "Cookie: 0x%llx, duration: %d\n", *cookie, duration); + + prChnlReqMsg->rMsgHdr.eMsgId = MID_MNY_P2P_CHNL_REQ; + prChnlReqMsg->u8Cookie = *cookie; + prChnlReqMsg->u4Duration = duration; + prChnlReqMsg->eChnlReqType = CH_REQ_TYPE_P2P_LISTEN; + + __channel_format_switch(chan, + NL80211_CHAN_NO_HT, + &prChnlReqMsg->rChannelInfo, &prChnlReqMsg->eChnlSco); + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prChnlReqMsg, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} + +/* mtk_p2p_cfg80211_remain_on_channel */ + +int mtk_p2p_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie) +{ + INT_32 i4Rslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + P_MSG_P2P_CHNL_ABORT_T prMsgChnlAbort = (P_MSG_P2P_CHNL_ABORT_T) NULL; + + do { + if (wiphy == NULL) + break; + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + prMsgChnlAbort = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_CHNL_ABORT_T)); + + if (prMsgChnlAbort == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + DBGLOG(P2P, INFO, "P2P: cancel remain on channel 0x%llx\n", cookie); + + prMsgChnlAbort->rMsgHdr.eMsgId = MID_MNY_P2P_CHNL_ABORT; + prMsgChnlAbort->u8Cookie = cookie; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChnlAbort, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_cancel_remain_on_channel */ + +int mtk_p2p_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + INT_32 i4Rslt = -EINVAL; + 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; + PUINT_64 pu8GlCookie = (PUINT_64) NULL; + UINT_8 ucRoleIdx = 0, ucBssIdx = 0; + struct net_device *dev = NULL; + + do { + if ((wiphy == NULL) || (wdev == NULL) || (params == 0) || (cookie == NULL)) + break; + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + dev = wdev->netdev; + if (mtk_Netdev_To_RoleIdx(prGlueP2pInfo, dev, &ucRoleIdx) < 0) { + /* Device Interface. */ + ucBssIdx = P2P_DEV_BSS_INDEX; + } else { + ASSERT(ucRoleIdx < KAL_P2P_NUM); + /* Role Interface. */ + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &ucBssIdx) != WLAN_STATUS_SUCCESS) { + /* Can't find BSS index. */ + break; + } + } + + *cookie = prGlueP2pInfo->u8Cookie++; + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_mgmt_tx, cookie: 0x%llx\n", *cookie); + + /* 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; + } + + if (params->offchan) { + DBGLOG(P2P, INFO, " Off channel TRUE\n"); + prMsgTxReq->fgIsOffChannel = TRUE; + + __channel_format_switch(params->chan, + NL80211_CHAN_NO_HT, + &prMsgTxReq->rChannelInfo, &prMsgTxReq->eChnlExt); + } else { + prMsgTxReq->fgIsOffChannel = FALSE; + } + + if (params->no_cck) + prMsgTxReq->fgNoneCckRate = TRUE; + else + prMsgTxReq->fgNoneCckRate = FALSE; + + if (params->dont_wait_for_ack) + prMsgTxReq->fgIsWaitRsp = FALSE; + else + prMsgTxReq->fgIsWaitRsp = TRUE; + prMgmtFrame = + cnmMgtPktAlloc(prGlueInfo->prAdapter, + (INT_32) (params->len + sizeof(UINT_64) + MAC_TX_RESERVED_FIELD)); + prMsgTxReq->prMgmtMsduInfo = prMgmtFrame; + if (prMsgTxReq->prMgmtMsduInfo == NULL) { + /* ASSERT(FALSE); */ + i4Rslt = -ENOMEM; + break; + } + + prMsgTxReq->u8Cookie = *cookie; + prMsgTxReq->rMsgHdr.eMsgId = MID_MNY_P2P_MGMT_TX; + prMsgTxReq->ucBssIdx = ucBssIdx; + + pucFrameBuf = (PUINT_8) ((ULONG) prMgmtFrame->prPacket + MAC_TX_RESERVED_FIELD); + + pu8GlCookie = (PUINT_64) ((ULONG) prMgmtFrame->prPacket + (ULONG)params->len + MAC_TX_RESERVED_FIELD); + + kalMemCopy(pucFrameBuf, params->buf, params->len); + + *pu8GlCookie = *cookie; + + prMgmtFrame->u2FrameLength = params->len; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgTxReq, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + if ((i4Rslt != 0) && (prMsgTxReq != NULL)) { + if (prMsgTxReq->prMgmtMsduInfo != NULL) + cnmMgtPktFree(prGlueInfo->prAdapter, prMsgTxReq->prMgmtMsduInfo); + + cnmMemFree(prGlueInfo->prAdapter, prMsgTxReq); + } + + return i4Rslt; +} /* mtk_p2p_cfg80211_mgmt_tx */ + +int mtk_p2p_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie) +{ + INT_32 i4Rslt = -EINVAL; + + return i4Rslt; +} /* mtk_p2p_cfg80211_mgmt_tx_cancel_wait */ + +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 */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, struct station_del_parameters *params) +#else +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, const u8 *mac) +#endif +{ + 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; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + const UINT_8 *mac = NULL; +#endif + + UINT_8 ucRoleIdx = 0; + + do { + if ((wiphy == NULL) || (dev == NULL)) + break; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + if (params->mac == NULL) + mac = aucBcMac; + else + mac = params->mac; +#else + if (mac == NULL) + mac = aucBcMac; +#endif + + DBGLOG(P2P, INFO, "Del_station: %pM.\n", mac); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo->prP2PInfo, dev, &ucRoleIdx) < 0) + break; + /* + * 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; + prDisconnectMsg->ucRoleIdx = ucRoleIdx; + COPY_MAC_ADDR(prDisconnectMsg->aucTargetID, mac); + prDisconnectMsg->fgSendDeauth = TRUE; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + if (params->reason_code == 0) + prDisconnectMsg->u2ReasonCode = REASON_CODE_UNSPECIFIED; + else + prDisconnectMsg->u2ReasonCode = params->reason_code; + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_del_station ReasonCode = %u\n", prDisconnectMsg->u2ReasonCode); +#else + prDisconnectMsg->u2ReasonCode = REASON_CODE_UNSPECIFIED; +#endif + + 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) +{ + UINT_8 ucRoleIdx = 0; + INT_32 i4Rslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_MSG_P2P_CONNECTION_REQUEST_T prConnReqMsg = (P_MSG_P2P_CONNECTION_REQUEST_T) NULL; + P_NETDEV_PRIVATE_GLUE_INFO prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) NULL; + P_BSS_INFO_T prP2pBssInfo = NULL; + struct wireless_dev *wdev = NULL; + + do { + if ((wiphy == NULL) || (dev == NULL) || (sme == NULL)) + break; + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_connect.\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* Supplicant asks to do connect while driver is disconnecting, + * it will lead to install key fail, error is -67 (link has been servered). + * Reject this request.Supplicant will handle the connecting request again. + */ + wdev = dev->ieee80211_ptr; + prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(dev); + ASSERT_BREAK((prGlueInfo != NULL) && (prNetDevPrivate != NULL)); + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, prNetDevPrivate->ucBssIdx); + + if (wdev->current_bss && (prP2pBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED)) { + DBGLOG(P2P, WARN, "Reject this connecting request\n"); + return -EALREADY; + } + + if (mtk_Netdev_To_RoleIdx(prGlueInfo->prP2PInfo, dev, &ucRoleIdx) < 0) + break; + + 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; + prConnReqMsg->ucRoleIdx = ucRoleIdx; + + 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:%zu\n", sme->ie_len); + kalMemCopy(prConnReqMsg->aucIEBuf, sme->ie, sme->ie_len); + prConnReqMsg->u4IELen = sme->ie_len; + + kalP2PSetCipher(prGlueInfo, IW_AUTH_CIPHER_NONE); + + if (sme->crypto.n_ciphers_pairwise) { + switch (sme->crypto.ciphers_pairwise[0]) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + kalP2PSetCipher(prGlueInfo, IW_AUTH_CIPHER_WEP40); + break; + case WLAN_CIPHER_SUITE_TKIP: + kalP2PSetCipher(prGlueInfo, IW_AUTH_CIPHER_TKIP); + break; + case WLAN_CIPHER_SUITE_CCMP: + case WLAN_CIPHER_SUITE_AES_CMAC: + kalP2PSetCipher(prGlueInfo, IW_AUTH_CIPHER_CCMP); + break; + default: + DBGLOG(REQ, WARN, "invalid cipher pairwise (%d)\n", sme->crypto.ciphers_pairwise[0]); + kalMemFree(prConnReqMsg, VIR_MEM_TYPE, + (sizeof(MSG_P2P_CONNECTION_REQUEST_T) + sme->ie_len)); + return -EINVAL; + } + } + + __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; + UINT_8 ucRoleIdx = 0; + + do { + if ((wiphy == NULL) || (dev == NULL)) + break; + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_disconnect.\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo->prP2PInfo, dev, &ucRoleIdx) < 0) + break; +/* 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->ucRoleIdx = ucRoleIdx; + prDisconnMsg->u2ReasonCode = reason_code; + prDisconnMsg->fgSendDeauth = TRUE; + COPY_MAC_ADDR(prDisconnMsg->aucTargetID, aucBCAddr); + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prDisconnMsg, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_disconnect */ + +#if (KERNEL_VERSION(4, 12, 0) <= LINUX_VERSION_CODE) +int +mtk_p2p_cfg80211_change_iface(IN struct wiphy *wiphy, + IN struct net_device *ndev, + IN enum nl80211_iftype type, IN struct vif_params *params) +#else +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) +#endif +{ + 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; + UINT_8 ucRoleIdx = 0; + + do { + if ((wiphy == NULL) || (ndev == NULL)) + break; + + DBGLOG(P2P, TRACE, "Change interface type to %d\n", type); + + if (ndev->ieee80211_ptr) + ndev->ieee80211_ptr->iftype = type; + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo->prP2PInfo, ndev, &ucRoleIdx) != 0) { + DBGLOG(P2P, TRACE, "Device Interface no need to change interface type.\n"); + return 0; + } + /* 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; + prSwitchModeMsg->ucRoleIdx = ucRoleIdx; + + switch (type) { + case NL80211_IFTYPE_P2P_CLIENT: + case NL80211_IFTYPE_STATION: + prSwitchModeMsg->eOpMode = OP_MODE_INFRASTRUCTURE; + kalP2PSetRole(prGlueInfo, 1); + break; + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_P2P_GO: + prSwitchModeMsg->eOpMode = OP_MODE_ACCESS_POINT; + kalP2PSetRole(prGlueInfo, 2); + break; + default: + prSwitchModeMsg->eOpMode = OP_MODE_P2P_DEVICE; + kalP2PSetRole(prGlueInfo, 0); + break; + } + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prSwitchModeMsg, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_change_iface */ + +int mtk_p2p_cfg80211_set_channel(IN struct wiphy *wiphy, + struct cfg80211_chan_def *chandef) +{ + INT_32 i4Rslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + RF_CHANNEL_INFO_T rRfChnlInfo; + UINT_8 ucRoleIdx = 0; + struct net_device *dev = NULL; + + do { + if ((wiphy == NULL) || (chandef == NULL)) + break; + dev = (struct net_device *)wiphy_dev(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + __channel_format_switch(chandef->chan, 0, &rRfChnlInfo, NULL); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo->prP2PInfo, dev, &ucRoleIdx) < 0) + break; + + p2pFuncSetChannel(prGlueInfo->prAdapter, ucRoleIdx, &rRfChnlInfo); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_set_channel */ + +int +mtk_p2p_cfg80211_set_bitrate_mask(IN struct wiphy *wiphy, + IN struct net_device *dev, + IN const u8 *peer, IN const struct cfg80211_bitrate_mask *mask) +{ + INT_32 i4Rslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + + do { + if ((wiphy == NULL) || (dev == NULL) || (mask == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_set_bitrate_mask\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* TODO: Set bitrate mask of the peer? */ + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_set_bitrate_mask */ + +void mtk_p2p_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, + struct wireless_dev *wdev, + IN u16 frame_type, IN bool reg) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + + do { + if (wiphy == 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; +#if CFG_SUPPORT_SOFTAP_WPA3 + case MAC_FRAME_AUTH: + if (reg) { + prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter + |= PARAM_PACKET_FILTER_AUTH; + DBGLOG(P2P, TRACE, "Open packet filer auth request\n"); + } else { + prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter + &= ~PARAM_PACKET_FILTER_AUTH; + DBGLOG(P2P, TRACE, "Close packet filer auth request\n"); + } + break; + case MAC_FRAME_ASSOC_REQ: + if (reg) { + prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter + |= PARAM_PACKET_FILTER_ASSOC_REQ; + DBGLOG(P2P, TRACE, "Open packet filer assoc request\n"); + } else { + prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter + &= ~PARAM_PACKET_FILTER_ASSOC_REQ; + DBGLOG(P2P, TRACE, "Close packet filer assoc request\n"); + } + break; +#endif + + default: + DBGLOG(P2P, ERROR, "Ask frog to add code for mgmt:%x\n", frame_type); + break; + } + + set_bit(GLUE_FLAG_FRAME_FILTER_BIT, &prGlueInfo->ulFlag); + + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + + if (in_interrupt()) + DBGLOG(P2P, TRACE, "It is in interrupt level\n"); + } while (FALSE); + +} /* mtk_p2p_cfg80211_mgmt_frame_register */ + +#if CONFIG_NL80211_TESTMODE + +int mtk_p2p_cfg80211_testmode_cmd(IN struct wiphy *wiphy, IN struct wireless_dev *wdev, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_TEST_PARAMS prParams = NULL; + INT_32 i4Status = -EINVAL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (data && len) { + prParams = (P_NL80211_DRIVER_TEST_PARAMS) data; + } else { + DBGLOG(P2P, ERROR, "data is NULL\n"); + return i4Status; + } + + if (prParams->index >> 24 == 0x01) { + /* New version */ + prParams->index = prParams->index & ~BITS(24, 31); + } else { + /* Old version */ + i4Status = mtk_p2p_cfg80211_testmode_p2p_sigma_pre_cmd(wiphy, data, len); + return i4Status; + } + + switch (prParams->index) { + case 1: /* P2P Simga */ +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION + { + P_NL80211_DRIVER_SW_CMD_PARAMS prParamsCmd; + + prParamsCmd = (P_NL80211_DRIVER_SW_CMD_PARAMS) data; + + if ((prParamsCmd->adr & 0xffff0000) == 0xffff0000) { + i4Status = mtk_p2p_cfg80211_testmode_sw_cmd(wiphy, data, len); + break; + } + } +#endif + i4Status = mtk_p2p_cfg80211_testmode_p2p_sigma_cmd(wiphy, data, len); + break; +#if CFG_SUPPORT_WFD + case 2: /* WFD */ + /* use normal driver command wifi_display */ + /* i4Status = mtk_p2p_cfg80211_testmode_wfd_update_cmd(wiphy, data, len); */ + break; +#endif +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + case 3: /* Hotspot Client Management */ + i4Status = mtk_p2p_cfg80211_testmode_hotspot_block_list_cmd(wiphy, data, len); + break; +#endif + case 0x10: + i4Status = mtk_cfg80211_testmode_get_sta_statistics(wiphy, data, len, prGlueInfo); + break; +#if CFG_SUPPORT_NFC_BEAM_PLUS + case 0x11: /* NFC Beam + Indication */ + if (data && len) { + P_NL80211_DRIVER_SET_NFC_PARAMS prParams = (P_NL80211_DRIVER_SET_NFC_PARAMS) data; + + DBGLOG(P2P, INFO, "NFC: BEAM[%d]\n", prParams->NFC_Enable); + } + break; + case 0x12: /* NFC Beam + Indication */ + DBGLOG(P2P, INFO, "NFC: Polling\n"); + i4Status = mtk_cfg80211_testmode_get_scan_done(wiphy, data, len, prGlueInfo); + break; +#endif + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + case 0x33: + i4Status = mtk_p2p_cfg80211_testmode_hotspot_config_cmd(wiphy, data, len); + break; +#endif + default: + i4Status = -EINVAL; + break; + } + + DBGLOG(P2P, TRACE, "prParams->index=%d, status=%d\n", prParams->index, i4Status); + + return i4Status; +} + +int mtk_p2p_cfg80211_testmode_p2p_sigma_pre_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + NL80211_DRIVER_TEST_PRE_PARAMS rParams; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + /* P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T)NULL; */ + UINT_32 index_mode; + UINT_32 index; + INT_32 value; + int status = 0; + UINT_32 u4Leng; + UINT_8 ucBssIdx; + + 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; */ + + if (data && len) + memcpy(&rParams, data, len); + + DBGLOG(P2P, TRACE, "NL80211_ATTR_TESTDATA, idx_mode=%d idx=%d value=%u\n", + rParams.idx_mode, rParams.idx, rParams.value); + + index_mode = rParams.idx_mode; + index = rParams.idx; + value = rParams.value; + + /* 3 FIX ME: Add p2p role index selection */ + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, 0, &ucBssIdx) != WLAN_STATUS_SUCCESS) + return -EINVAL; + + 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 */ + { + PARAM_POWER_MODE_T rPowerMode; + + rPowerMode.ePowerMode = Param_PowerModeMAX_PSP; + rPowerMode.ucBssIdx = ucBssIdx; + + kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, sizeof(rPowerMode), FALSE, FALSE, 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 */ + { + PARAM_POWER_MODE_T rPowerMode; + + rPowerMode.ePowerMode = value; + rPowerMode.ucBssIdx = ucBssIdx; + + kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, sizeof(rPowerMode), FALSE, FALSE, 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; + UINT_8 ucBssIdx; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + prP2pSpecificBssInfo = prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo; + /* prP2pConnSettings = prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings; */ + + if (data && len) { + prParams = (P_NL80211_DRIVER_P2P_SIGMA_PARAMS) data; + } else { + DBGLOG(P2P, ERROR, "data is NULL\n"); + return -EINVAL; + } + + index = (INT_32) prParams->idx; + value = (INT_32) prParams->value; + + DBGLOG(P2P, TRACE, "NL80211_ATTR_TESTDATA, idx=%u value=%u\n", + prParams->idx, prParams->value); + + /* 3 FIX ME: Add p2p role index selection */ + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, 0, &ucBssIdx) != WLAN_STATUS_SUCCESS) + return -EINVAL; + + 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 */ + { + PARAM_POWER_MODE_T rPowerMode; + + rPowerMode.ePowerMode = Param_PowerModeMAX_PSP; + rPowerMode.ucBssIdx = ucBssIdx; + + kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, sizeof(rPowerMode), FALSE, FALSE, 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 */ + { + PARAM_POWER_MODE_T rPowerMode; + + rPowerMode.ePowerMode = value; + rPowerMode.ucBssIdx = ucBssIdx; + + kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, sizeof(rPowerMode), FALSE, FALSE, TRUE, &u4Leng); + } + break; + case 109: /* Max Clients */ +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + kalP2PSetMaxClients(prGlueInfo, value); +#endif + break; + case 110: /* Hotspot WPS mode */ +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + kalIoctl(prGlueInfo, wlanoidSetP2pWPSmode, &value, sizeof(value), FALSE, FALSE, TRUE, &u4Leng); +#endif + break; + default: + break; + } + + return status; + +} + +#if CFG_SUPPORT_WFD && 0 +/* obsolete/decrepated */ +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.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 */ + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + +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; + + if (!prParams) + return fgIsValid; + + DBGLOG(P2P, INFO, "%s" MACSTR "\n", prParams->ucblocked?"Block":"Unblock", MAC2STR(prParams->aucBssid)); + + fgIsValid = kalP2PSetBlackList(prGlueInfo, prParams->aucBssid, prParams->ucblocked); + + return fgIsValid; + +} + +#endif + +int mtk_p2p_cfg80211_testmode_sw_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_SW_CMD_PARAMS prParams = (P_NL80211_DRIVER_SW_CMD_PARAMS) NULL; + WLAN_STATUS rstatus = WLAN_STATUS_SUCCESS; + int fgIsValid = 0; + UINT_32 u4SetInfoLen = 0; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + DBGLOG(P2P, TRACE, "--> %s()\n", __func__); + + if (data && len) + prParams = (P_NL80211_DRIVER_SW_CMD_PARAMS) data; + + if (prParams) { + if (prParams->set == 1) { + rstatus = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC) wlanoidSetSwCtrlWrite, + &prParams->adr, (UINT_32) 8, FALSE, FALSE, TRUE, &u4SetInfoLen); + } + } + + if (rstatus != WLAN_STATUS_SUCCESS) + fgIsValid = -EFAULT; + + return fgIsValid; +} + + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER +int mtk_p2p_cfg80211_testmode_hotspot_config_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; + + UINT_32 index; + UINT_32 value; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (data && len) { + prParams = (P_NL80211_DRIVER_P2P_SIGMA_PARAMS) data; + } else { + DBGLOG(P2P, ERROR, "data is NULL or len is 0\n"); + return -EINVAL; + } + + index = prParams->idx; + value = prParams->value; + + DBGLOG(P2P, TRACE, "HOTSPOT CONFIG, idx=%u value=%u\n", + prParams->idx, prParams->value); + switch (index) { + case 1: /* Max Clients */ + kalP2PSetMaxClients(prGlueInfo, value); + break; + default: + break; + } + + return 0; +} +#endif /*CFG_SUPPORT_HOTSPOT_WPS_MANAGER*/ + +#endif /* CONFIG_NL80211_TESTMODE */ + +#endif /* CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_WIFI_DIRECT_CFG_80211 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_p2p_init.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_p2p_init.c new file mode 100644 index 0000000000000..11c784002a7fa --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_p2p_init.c @@ -0,0 +1,159 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: @(#) gl_p2p_init.c@@ +*/ + +/* + * ! \file gl_p2p_init.c + * \brief init and exit routines of Linux driver interface for Wi-Fi Direct + * + * This file contains the main routines of Linux driver for MediaTek Inc. 802.11 + * Wireless LAN Adapters. + */ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define P2P_INF_NAME "p2p%d" +#define AP_INF_NAME "ap%d" + +#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 +******************************************************************************** +*/ +static PUCHAR ifname = P2P_INF_NAME; +static UINT_16 mode = RUNNING_P2P_MODE; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +VOID p2pSetSuspendMode(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgEnable) +{ + struct net_device *prDev = NULL; + + if (!prGlueInfo) + return; + + if (!prGlueInfo->prAdapter->fgIsP2PRegistered) { + DBGLOG(P2P, INFO, "%s: P2P is not enabled, SKIP!\n", __func__); + return; + } + + prDev = prGlueInfo->prP2PInfo->prDevHandler; + if (!prDev) { + DBGLOG(P2P, WARN, "%s: P2P dev is not available, SKIP!\n", __func__); + return; + } + + kalSetNetAddressFromInterface(prGlueInfo, prDev, fgEnable); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* run p2p init procedure, glue register p2p and set p2p registered flag +* +* \retval 1 Success +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2pLaunch(P_GLUE_INFO_T prGlueInfo) +{ + if (prGlueInfo->prAdapter->fgIsP2PRegistered == TRUE) { + DBGLOG(P2P, INFO, "p2p is already registered\n"); + return FALSE; + } + + if (!glRegisterP2P(prGlueInfo, ifname, (BOOLEAN) mode)) { + DBGLOG(P2P, ERROR, "Register p2p failed!\n"); + return FALSE; + } + + prGlueInfo->prAdapter->fgIsP2PRegistered = TRUE; + DBGLOG(P2P, INFO, "Register p2p succeed\n"); + return TRUE; +} + +VOID p2pSetMode(IN BOOLEAN fgIsAPMode) +{ + if (fgIsAPMode) { + mode = RUNNING_AP_MODE; + ifname = AP_INF_NAME; + } else { + mode = RUNNING_P2P_MODE; + ifname = P2P_INF_NAME; + } + +} /* p2pSetMode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* run p2p exit procedure, glue unregister p2p and set p2p registered flag +* +* \retval 1 Success +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2pRemove(P_GLUE_INFO_T prGlueInfo) +{ + if (prGlueInfo->prAdapter->fgIsP2PRegistered == FALSE) { + DBGLOG(P2P, INFO, "p2p is not registered\n"); + return FALSE; + } + + DBGLOG(P2P, INFO, "Prepare to remove p2p...\n"); + prGlueInfo->prAdapter->fgIsP2PRegistered = FALSE; + glUnregisterP2P(prGlueInfo); + return TRUE; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_p2p_kal.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_p2p_kal.c new file mode 100644 index 0000000000000..d728fa8cded01 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_p2p_kal.c @@ -0,0 +1,1580 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * 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" +#include "gl_wext.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 +******************************************************************************** +*/ + +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) + return; + } else { + if (u4FrameBodyLen < 9) + 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)) { + /* WPS IE found */ + } else if (wextSrchDesiredWPAIE(cp, u4FrameBodyLen, 0x30, &pucDesiredIE)) { + /* RSN IE found */ + } else if (wextSrchDesiredWPAIE(cp, u4FrameBodyLen, 0xDD, &pucDesiredIE)) { + /* 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]; + UINT_32 ret = 0; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + + if (eState == PARAM_MEDIA_STATE_CONNECTED) { + prGlueInfo->prP2PInfo->eState = PARAM_MEDIA_STATE_CONNECTED; + + ret = snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_STA_CONNECT=" MACSTR, MAC2STR(rPeerAddr)); + if ((ret < 0) || (ret > IW_CUSTOM_MAX - 1)) + DBGLOG(P2P, ERROR, + "[%u] snprintf failed, ret: %d\n", + __LINE__, ret); + 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) { + ret = snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_STA_DISCONNECT=" MACSTR, MAC2STR(rPeerAddr)); + if ((ret < 0) || (ret > IW_CUSTOM_MAX - 1)) + DBGLOG(P2P, ERROR, + "[%u] snprintf failed, ret: %d\n", + __LINE__, ret); + evt.data.length = strlen(aucBuffer); + + /* indicate in IWECUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + } else { + ASSERT(0); + } + +} /* end of kalP2PSetState() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Wi-Fi Direct operating frequency +* +* \param[in] +* prGlueInfo +* +* \return +* in unit of KHz +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 kalP2PGetFreqInKHz(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->prP2PInfo->u4FreqInKHz; +} /* end of kalP2PGetFreqInKHz() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Bluetooth-over-Wi-Fi role +* +* \param[in] +* prGlueInfo +* +* \return +* 0: P2P Device +* 1: Group Client +* 2: Group Owner +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 kalP2PGetRole(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->prP2PInfo->ucRole; +} /* end of kalP2PGetRole() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to set Wi-Fi Direct role +* +* \param[in] +* prGlueInfo +* ucResult +* 0: successful +* 1: error +* ucRole +* 0: P2P Device +* 1: Group Client +* 2: Group Owner +* +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +#if 1 +VOID kalP2PSetRole(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRole) +{ + ASSERT(prGlueInfo); + ASSERT(ucRole <= 2); + + prGlueInfo->prP2PInfo->ucRole = ucRole; + /* Remove non-used code */ +} /* end of kalP2PSetRole() */ + +#else +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) */ + + /* indicate in IWECUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PSetRole() */ + +#endif +/*----------------------------------------------------------------------------*/ +/*! +* \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; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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; + + if (prGlueInfo->prP2PInfo->u4CipherPairwise == IW_AUTH_CIPHER_WEP40) + 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); + +} + +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 > 560) { + DBGLOG(P2P, ERROR, + "Buffer length is not enough, GLUE only 560 bytes but %d received\n", u2BufferLength); + ASSERT(FALSE); + break; + } + + prGlP2pInfo = prGlueInfo->prP2PInfo; + + kalMemCopy(prGlP2pInfo->aucWSCIE[ucType], pucBuffer, u2BufferLength); + + prGlP2pInfo->u2WSCIELen[ucType] = u2BufferLength; + + } while (FALSE); + +} /* kalP2PUpdateWSC_IE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief indicate an event to supplicant for device connection request +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalP2PIndicateConnReq(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucDevName, + IN INT_32 u4NameLength, IN PARAM_MAC_ADDRESS rPeerAddr, + IN UINT_8 ucDevType, /* 0: P2P Device / 1: GC / 2: GO */ + IN INT_32 i4ConfigMethod, IN INT_32 i4ActiveConfigMethod) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + UINT_32 ret = 0; + + 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)); + + ret = snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_DVC_REQ"); + if ((ret < 0) || (ret > IW_CUSTOM_MAX - 1)) + DBGLOG(P2P, ERROR, + "[%u] snprintf failed, ret: %d\n", + __LINE__, ret); + evt.data.length = strlen(aucBuffer); + + /* indicate in IWEVCUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PIndicateConnReq() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Indicate an event to supplicant for device connection request from other device. +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* \param[in] pucGroupBssid Only valid when invitation Type equals to 0. +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalP2PInvitationIndication(IN P_GLUE_INFO_T prGlueInfo, + IN P_P2P_DEVICE_DESC_T prP2pDevDesc, + IN PUINT_8 pucSsid, + IN UINT_8 ucSsidLen, + IN UINT_8 ucOperatingChnl, IN UINT_8 ucInvitationType, IN PUINT_8 pucGroupBssid) +{ +#if 1 + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + UINT_32 ret = 0; + + 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)); + + ret = snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_INV_INDICATE"); + if ((ret < 0) || (ret > IW_CUSTOM_MAX - 1)) + DBGLOG(P2P, ERROR, + "[%u] snprintf failed, ret: %d\n", + __LINE__, ret); + 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]; + UINT_32 ret = 0; + + ASSERT(prGlueInfo); + + /* buffer peer information for later IOC_P2P_GET_STRUCT access */ + prGlueInfo->prP2PInfo->u4InvStatus = u4InvStatus; + + /* prepare event structure */ + memset(&evt, 0, sizeof(evt)); + + ret = snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_INV_STATUS"); + if ((ret < 0) || (ret > IW_CUSTOM_MAX - 1)) + DBGLOG(P2P, ERROR, + "[%u] snprintf failed, ret: %d\n", + __LINE__, ret); + evt.data.length = strlen(aucBuffer); + + /* indicate in IWEVCUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + +} /* kalP2PInvitationStatus */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Indicate an event to supplicant for Service Discovery request from other device. +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalP2PIndicateSDRequest(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rPeerAddr, IN UINT_8 ucSeqNum) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + UINT_32 ret = 0; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + + ret = snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_SD_REQ %d", ucSeqNum); + if ((ret < 0) || (ret > IW_CUSTOM_MAX - 1)) + DBGLOG(P2P, ERROR, + "[%u] snprintf failed, ret: %d\n", + __LINE__, ret); + evt.data.length = strlen(aucBuffer); + + /* indicate IWEVP2PSDREQ event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PIndicateSDRequest() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Indicate an event to supplicant for Service Discovery response +* from other device. +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +void kalP2PIndicateSDResponse(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rPeerAddr, IN UINT_8 ucSeqNum) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + UINT_32 ret = 0; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + + ret = snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_SD_RESP %d", ucSeqNum); + if ((ret < 0) || (ret > IW_CUSTOM_MAX - 1)) + DBGLOG(P2P, ERROR, + "[%u] snprintf failed, ret: %d\n", + __LINE__, ret); + evt.data.length = strlen(aucBuffer); + + /* indicate IWEVP2PSDREQ event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PIndicateSDResponse() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Indicate an event to supplicant for Service Discovery TX Done +* from other device. +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* \param[in] ucSeqNum Sequence number of the frame +* \param[in] ucStatus Status code for TX +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalP2PIndicateTXDone(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucSeqNum, IN UINT_8 ucStatus) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + UINT_32 ret = 0; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + + ret = snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_SD_XMITTED: %d %d", ucSeqNum, ucStatus); + if ((ret < 0) || (ret > IW_CUSTOM_MAX - 1)) + DBGLOG(P2P, ERROR, + "[%u] snprintf failed, ret: %d\n", + __LINE__, ret); + evt.data.length = strlen(aucBuffer); + + /* indicate IWEVP2PSDREQ event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PIndicateSDResponse() */ + +struct net_device *kalP2PGetDevHdlr(P_GLUE_INFO_T prGlueInfo) +{ + 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]; + UINT_32 ret = 0; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + ret = snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_SEC_CHECK_RSP="); + if ((ret < 0) || (ret > IW_CUSTOM_MAX - 1)) + DBGLOG(P2P, ERROR, + "[%u] snprintf failed, ret: %d\n", + __LINE__, ret); + kalMemCopy(prGlueInfo->prP2PInfo->aucSecCheckRsp, pucRsp, u2RspLen); + evt.data.length = strlen(aucBuffer); + +#if DBG + DBGLOG_MEM8(SEC, LOUD, prGlueInfo->prP2PInfo->aucSecCheckRsp, u2RspLen); +#endif + /* indicate in IWECUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); +} /* p2pFsmRunEventRxDisassociation */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalGetChnlList(IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_BAND_T eSpecificBand, + IN UINT_8 ucMaxChannelNum, IN PUINT_8 pucNumOfChannel, IN P_RF_CHANNEL_INFO_T paucChannelList) +{ + rlmDomainGetChnlList(prGlueInfo->prAdapter, eSpecificBand, FALSE, ucMaxChannelNum, + pucNumOfChannel, paucChannelList); +} /* kalGetChnlList */ + +/* ////////////////////////////////////ICS SUPPORT////////////////////////////////////// */ + +VOID +kalP2PIndicateChannelReady(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8SeqNum, + IN UINT_32 u4ChannelNum, + IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_32 u4Duration) +{ + struct ieee80211_channel *prIEEE80211ChnlStruct = (struct ieee80211_channel *)NULL; + RF_CHANNEL_INFO_T rChannelInfo; + enum nl80211_channel_type eChnlType = NL80211_CHAN_NO_HT; + + do { + if (prGlueInfo == NULL) + break; + + kalMemZero(&rChannelInfo, sizeof(RF_CHANNEL_INFO_T)); + + rChannelInfo.ucChannelNum = u4ChannelNum; + rChannelInfo.eBand = eBand; + + prIEEE80211ChnlStruct = kalP2pFuncGetChannelEntry(prGlueInfo->prP2PInfo, &rChannelInfo); + + kalP2pFuncGetChannelType(eSco, &eChnlType); + + if (prIEEE80211ChnlStruct == NULL) { + DBGLOG(P2P, WARN, + "prIEEE80211ChnlStruct == NULL.\n"); + } else { + cfg80211_ready_on_channel(prGlueInfo->prP2PInfo->prWdev, /* struct wireless_dev, */ + u8SeqNum, /* u64 cookie, */ + prIEEE80211ChnlStruct, /* struct ieee80211_channel * chan, */ + u4Duration, /* unsigned int duration, */ + GFP_KERNEL); /* gfp_t gfp *//* allocation flags */ + } + } while (FALSE); + +} /* kalP2PIndicateChannelReady */ + +VOID +kalP2PIndicateChannelExpired(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8SeqNum, + IN UINT_32 u4ChannelNum, IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco) +{ + + 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) { + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + if (prGlueP2pInfo == NULL) { + ASSERT(FALSE); + break; + } + + DBGLOG(P2P, TRACE, "kalP2PIndicateChannelExpired\n"); + + rRfChannelInfo.eBand = eBand; + rRfChannelInfo.ucChannelNum = u4ChannelNum; + + prIEEE80211ChnlStruct = kalP2pFuncGetChannelEntry(prGlueP2pInfo, &rRfChannelInfo); + + kalP2pFuncGetChannelType(eSco, &eChnlType); + + if (prIEEE80211ChnlStruct == NULL) { + DBGLOG(P2P, WARN, + "prIEEE80211ChnlStruct == NULL.\n"); + } else { + cfg80211_remain_on_channel_expired(prGlueP2pInfo->prWdev, /* struct wireless_dev, */ + u8SeqNum, prIEEE80211ChnlStruct, GFP_KERNEL); + } + } while (FALSE); + +} /* kalP2PIndicateChannelExpired */ + +VOID kalP2PIndicateScanDone(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRoleIndex, IN BOOLEAN fgIsAbort) +{ + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + struct cfg80211_scan_request *prScanRequest = NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + do { + if (prGlueInfo == NULL) { + + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + if (prGlueP2pInfo == NULL) { + ASSERT(FALSE); + break; + } + DBGLOG(P2P, TRACE, "scan complete, cfg80211 scan request is %p\n", prGlueP2pInfo->prScanRequest); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + if (prGlueP2pInfo->prScanRequest != NULL) { + prScanRequest = prGlueP2pInfo->prScanRequest; + prGlueP2pInfo->prScanRequest = NULL; + } else + DBGLOG(P2P, WARN, "[p2p] scan complete but cfg80211 scan request is NULL\n"); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + if (prScanRequest != NULL) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) + struct cfg80211_scan_info info; +#endif + + /* report all queued beacon/probe response frames to upper layer */ + scanReportBss2Cfg80211(prGlueInfo->prAdapter, BSS_TYPE_P2P_DEVICE, NULL); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) + info.aborted = fgIsAbort; + cfg80211_scan_done(prScanRequest, &info); +#else + cfg80211_scan_done(prScanRequest, fgIsAbort); +#endif + } + + } while (FALSE); + +} /* kalP2PIndicateScanDone */ + +VOID +kalP2PIndicateBssInfo(IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBuf, + IN UINT_32 u4BufLen, IN P_RF_CHANNEL_INFO_T prChannelInfo, IN INT_32 i4SignalStrength) +{ + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + struct ieee80211_channel *prChannelEntry = (struct ieee80211_channel *)NULL; + struct ieee80211_mgmt *prBcnProbeRspFrame = (struct ieee80211_mgmt *)pucFrameBuf; + struct cfg80211_bss *prCfg80211Bss = (struct cfg80211_bss *)NULL; + + do { + if ((prGlueInfo == NULL) || (pucFrameBuf == NULL) || (prChannelInfo == NULL)) { + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + if (prGlueP2pInfo == NULL) { + ASSERT(FALSE); + break; + } + + prChannelEntry = kalP2pFuncGetChannelEntry(prGlueP2pInfo, prChannelInfo); + + if (prChannelEntry == NULL) { + DBGLOG(P2P, WARN, "Unknown channel info\n"); + break; + } + + /* rChannelInfo.center_freq = nicChannelNum2Freq((UINT_32)prChannelInfo->ucChannelNum) / 1000; */ + + prCfg80211Bss = cfg80211_inform_bss_frame(prGlueP2pInfo->prWdev->wiphy, /* struct wiphy * wiphy, */ + prChannelEntry, + prBcnProbeRspFrame, u4BufLen, i4SignalStrength, GFP_KERNEL); + + if (!prCfg80211Bss) { + DBGLOG(P2P, INFO, "inform bss[%pM] failed\n", prBcnProbeRspFrame->bssid); + break; + } + /* Return this structure. */ + if (prCfg80211Bss) + cfg80211_put_bss(prGlueP2pInfo->prWdev->wiphy, prCfg80211Bss); + else + DBGLOG(P2P, WARN, "Indicate bss to cfg80211 failed\n"); + + } while (FALSE); + + return; + +} /* kalP2PIndicateBssInfo */ + +VOID kalP2PIndicateMgmtTxStatus(IN P_GLUE_INFO_T prGlueInfo, IN P_MSDU_INFO_T prMsduInfo, IN BOOLEAN fgIsAck) +{ + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + PUINT_64 pu8GlCookie = (PUINT_64) NULL; + struct net_device *prNetdevice = (struct net_device *)NULL; + + do { + if ((prGlueInfo == NULL) || (prMsduInfo == NULL)) { + DBGLOG(P2P, WARN, "Unexpected pointer PARAM. 0x%lx, 0x%lx.\n", prGlueInfo, prMsduInfo); + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + if (!prMsduInfo->prPacket) { + DBGLOG(P2P, INFO, "Buffer Cookie has been freed, do not access cookie\n"); + break; + } + + pu8GlCookie = + (PUINT_64) ((ULONG) prMsduInfo->prPacket + + (ULONG) prMsduInfo->u2FrameLength + MAC_TX_RESERVED_FIELD); + + if (prMsduInfo->ucBssIndex == P2P_DEV_BSS_INDEX) { + prNetdevice = prGlueP2pInfo->prDevHandler; + } else { + P_BSS_INFO_T prP2pBssInfo = + GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, prMsduInfo->ucBssIndex); + + prNetdevice = prGlueP2pInfo->aprRoleHandler[prP2pBssInfo->u4PrivateData]; + } + + cfg80211_mgmt_tx_status(prGlueP2pInfo->prWdev, /* struct net_device * dev, */ + *pu8GlCookie, + (PUINT_8) ((ULONG) prMsduInfo->prPacket + + MAC_TX_RESERVED_FIELD), + prMsduInfo->u2FrameLength, fgIsAck, GFP_KERNEL); + + } while (FALSE); + +} /* kalP2PIndicateMgmtTxStatus */ + +VOID +kalP2PIndicateRxMgmtFrame(IN P_GLUE_INFO_T prGlueInfo, + IN P_SW_RFB_T prSwRfb, IN BOOLEAN fgIsDevInterface, IN UINT_8 ucRoleIdx) +{ +#define DBG_P2P_MGMT_FRAME_INDICATION 1 + 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; + + /* ToDo[6630]: Get the following by channel freq */ + /* HAL_RX_STATUS_GET_CHAN_FREQ( prSwRfb->prRxStatus) */ + /* ucChnlNum = prSwRfb->prHifRxHdr->ucHwChannelNum; */ + + ucChnlNum = HAL_RX_STATUS_GET_CHNL_NUM(prSwRfb->prRxStatus); + +#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; + + cfg80211_rx_mgmt(prGlueP2pInfo->prWdev, /* struct net_device * dev, */ + i4Freq, + RCPI_TO_dBm(HAL_RX_STATUS_GET_RCPI(prSwRfb->prRxStatusGroup3)), + prSwRfb->pvHeader, prSwRfb->u2PacketLen, GFP_ATOMIC); + + } while (FALSE); + +} /* kalP2PIndicateRxMgmtFrame */ + +VOID +kalP2PGCIndicateConnectionStatus(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucRoleIndex, + IN P_P2P_CONNECTION_REQ_INFO_T prP2pConnInfo, + IN PUINT_8 pucRxIEBuf, IN UINT_16 u2RxIELen, IN UINT_16 u2StatusReason, + IN WLAN_STATUS eStatus) +{ + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + + do { + if (prGlueInfo == NULL) { + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + if (prP2pConnInfo) { + if (eStatus == WLAN_STATUS_MEDIA_CONNECT) { + /* switch carrier on */ + netif_carrier_on(prGlueP2pInfo->prDevHandler); + } + + cfg80211_connect_result(prGlueP2pInfo->aprRoleHandler[ucRoleIndex], + /* struct net_device * dev, */ + prP2pConnInfo->aucBssid, + prP2pConnInfo->aucIEBuf, + prP2pConnInfo->u4BufLength, + pucRxIEBuf, + u2RxIELen, + u2StatusReason, + GFP_KERNEL); /* gfp_t gfp *//* allocation flags */ + + prP2pConnInfo->eConnRequest = P2P_CONNECTION_TYPE_IDLE; + } else { + /* switch carrier off */ + if (netif_carrier_ok(prGlueP2pInfo->prDevHandler)) + netif_carrier_off(prGlueP2pInfo->prDevHandler); + + /* Disconnect, what if u2StatusReason == 0? */ + cfg80211_disconnected(prGlueP2pInfo->aprRoleHandler[ucRoleIndex], + /* struct net_device * dev, */ + u2StatusReason, pucRxIEBuf, u2RxIELen, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + eStatus == WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY ? true : false, +#endif + GFP_KERNEL); + } + + } while (FALSE); + +} /* kalP2PGCIndicateConnectionStatus */ + +VOID kalP2PGOIndicateStatus(IN P_GLUE_INFO_T prGlueInfo, IN BOOLEAN fgReady) +{ + P_GL_P2P_INFO_T prP2pGlueInfo = (P_GL_P2P_INFO_T) NULL; + + do { + if (prGlueInfo == NULL) { + ASSERT(FALSE); + break; + } + + prP2pGlueInfo = prGlueInfo->prP2PInfo; + + if (fgReady) { + /* switch carrier on */ + netif_carrier_on(prP2pGlueInfo->prDevHandler); + } else { + /* switch carrier off */ + if (netif_carrier_ok(prP2pGlueInfo->prDevHandler)) + netif_carrier_off(prP2pGlueInfo->prDevHandler); + } + + } while (FALSE); +} + +VOID +kalP2PGOStationUpdate(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucRoleIndex, IN P_STA_RECORD_T prCliStaRec, IN BOOLEAN fgIsNew) +{ + P_GL_P2P_INFO_T prP2pGlueInfo = (P_GL_P2P_INFO_T) NULL; + + do { + if ((prGlueInfo == NULL) || (prCliStaRec == NULL) || (ucRoleIndex >= 1)) + break; + + prP2pGlueInfo = prGlueInfo->prP2PInfo; + + if (fgIsNew) { + struct station_info rStationInfo; + + kalMemZero(&rStationInfo, sizeof(rStationInfo)); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +#else + rStationInfo.filled = STATION_INFO_ASSOC_REQ_IES; +#endif + rStationInfo.generation = ++prP2pGlueInfo->i4Generation; + + rStationInfo.assoc_req_ies = prCliStaRec->pucAssocReqIe; + rStationInfo.assoc_req_ies_len = prCliStaRec->u2AssocReqIeLen; + + cfg80211_new_sta(prGlueInfo->prP2PInfo->aprRoleHandler[ucRoleIndex], + /* struct net_device * dev, */ + prCliStaRec->aucMacAddr, &rStationInfo, GFP_KERNEL); + } else { + ++prP2pGlueInfo->i4Generation; + + cfg80211_del_sta(prGlueInfo->prP2PInfo->aprRoleHandler[ucRoleIndex], + /* struct net_device * dev, */ + prCliStaRec->aucMacAddr, GFP_KERNEL); + } + + } while (FALSE); + + return; + +} /* kalP2PGOStationUpdate */ + +BOOLEAN kalP2pFuncGetChannelType(IN ENUM_CHNL_EXT_T rChnlSco, OUT enum nl80211_channel_type *channel_type) +{ + BOOLEAN fgIsValid = FALSE; + + do { + if (channel_type) { + + switch (rChnlSco) { + case CHNL_EXT_SCN: + *channel_type = NL80211_CHAN_NO_HT; + break; + case CHNL_EXT_SCA: + *channel_type = NL80211_CHAN_HT40MINUS; + break; + case CHNL_EXT_SCB: + *channel_type = NL80211_CHAN_HT40PLUS; + break; + default: + ASSERT(FALSE); + *channel_type = NL80211_CHAN_NO_HT; + break; + } + + } + + fgIsValid = TRUE; + } while (FALSE); + + return fgIsValid; +} /* kalP2pFuncGetChannelType */ + +struct ieee80211_channel *kalP2pFuncGetChannelEntry(IN P_GL_P2P_INFO_T prP2pInfo, IN P_RF_CHANNEL_INFO_T prChannelInfo) +{ + struct ieee80211_channel *prTargetChannelEntry = (struct ieee80211_channel *)NULL; + UINT_32 u4TblSize = 0, u4Idx = 0; + struct wiphy *wiphy = NULL; + struct ieee80211_supported_band **bands; + + do { + if (!prP2pInfo || !prChannelInfo || !prP2pInfo->prWdev) + break; + + wiphy = prP2pInfo->prWdev->wiphy; + bands = &wiphy->bands[0]; + + switch (prChannelInfo->eBand) { + case BAND_2G4: + if (bands[KAL_BAND_2GHZ]) { + prTargetChannelEntry = bands[KAL_BAND_2GHZ]->channels; + u4TblSize = bands[KAL_BAND_2GHZ]->n_channels; + } else + DBGLOG(P2P, ERROR, "2.4G band entry is NULL!\n"); + break; + case BAND_5G: + if (bands[KAL_BAND_5GHZ]) { + prTargetChannelEntry = bands[KAL_BAND_5GHZ]->channels; + u4TblSize = bands[KAL_BAND_5GHZ]->n_channels; + } else + DBGLOG(P2P, ERROR, "5G band entry is NULL!\n"); + 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 */ + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + +/*----------------------------------------------------------------------------*/ +/*! +* \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 < P2P_BLACKLIST_MAX_COUNT; 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 < P2P_BLACKLIST_MAX_COUNT; 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 < P2P_BLACKLIST_MAX_COUNT; 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 || u4MaxClient >= 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; +} + +#endif + +/*the same as gen4m*/ +void kalP2pIndicateAcsResult(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucRoleIndex, + IN UINT_8 ucPrimaryCh, + IN UINT_8 ucSecondCh, + IN UINT_8 ucSeg0Ch, + IN UINT_8 ucSeg1Ch, + IN ENUM_MAX_BANDWIDTH_SETTING eChnlBw) +{ + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + struct sk_buff *vendor_event = NULL; + UINT_16 ch_width = MAX_BW_20MHZ; + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + if (!prGlueP2pInfo) { + DBGLOG(P2P, ERROR, "p2p glue info null.\n"); + return; + } + + switch (eChnlBw) { + case MAX_BW_20MHZ: + ch_width = 20; + break; + case MAX_BW_40MHZ: + ch_width = 40; + break; + case MAX_BW_80MHZ: + ch_width = 80; + break; + case MAX_BW_160MHZ: + ch_width = 160; + break; + default: + DBGLOG(P2P, ERROR, "unsupport width: %d.\n", ch_width); + break; + } + + DBGLOG(P2P, INFO, "r=%d, c=%d, s=%d, s0=%d, s1=%d, ch_w=%d\n", + ucRoleIndex, + ucPrimaryCh, + ucSecondCh, + ucSeg0Ch, + ucSeg1Ch, + ch_width); + +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE + vendor_event = cfg80211_vendor_event_alloc(prGlueP2pInfo->prWdev->wiphy, +#if KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE + prGlueP2pInfo->prWdev, +#endif + 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN, + WIFI_EVENT_ACS, + GFP_KERNEL); +#endif + + if (!vendor_event) { + DBGLOG(P2P, ERROR, "allocate vendor event fail.\n"); + goto nla_put_failure; + } + + if (unlikely(nla_put_u8(vendor_event, + WIFI_VENDOR_ATTR_ACS_PRIMARY_CHANNEL, + ucPrimaryCh) < 0)) { + DBGLOG(P2P, ERROR, "put primary channel fail.\n"); + goto nla_put_failure; + } + + if (unlikely(nla_put_u8(vendor_event, + WIFI_VENDOR_ATTR_ACS_SECONDARY_CHANNEL, + ucSecondCh) < 0)) { + DBGLOG(P2P, ERROR, "put secondary channel fail.\n"); + goto nla_put_failure; + } + + if (unlikely(nla_put_u8(vendor_event, + WIFI_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL, + ucSeg0Ch) < 0)) { + DBGLOG(P2P, ERROR, "put vht seg0 fail.\n"); + goto nla_put_failure; + } + + if (unlikely(nla_put_u8(vendor_event, + WIFI_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL, + ucSeg1Ch) < 0)) { + DBGLOG(P2P, ERROR, "put vht seg1 fail.\n"); + goto nla_put_failure; + } + + if (unlikely(nla_put_u16(vendor_event, + WIFI_VENDOR_ATTR_ACS_CHWIDTH, + ch_width) < 0)) { + DBGLOG(P2P, ERROR, "put ch width fail.\n"); + goto nla_put_failure; + } + + if (unlikely(nla_put_u8(vendor_event, + WIFI_VENDOR_ATTR_ACS_HW_MODE, + ucPrimaryCh > 14 ? + P2P_VENDOR_ACS_HW_MODE_11A : + P2P_VENDOR_ACS_HW_MODE_11G) < 0)) { + DBGLOG(P2P, ERROR, "put hw mode fail.\n"); + goto nla_put_failure; + } +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE + cfg80211_vendor_event(vendor_event, GFP_KERNEL); +#endif + return; + +nla_put_failure: + if (vendor_event) + kfree_skb(vendor_event); +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_proc.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_proc.c new file mode 100644 index 0000000000000..97dd106732882 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_proc.c @@ -0,0 +1,1588 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_proc.c#2 +*/ + +/* + * ! \file "gl_proc.c" + * \brief This file defines the interface which can interact with users in /proc fs. + * + * Detail description. + */ + +/******************************************************************************* +* C O M P I L E 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 "debug.h" +#include "wlan_lib.h" +#include "debug.h" + +#ifdef FW_CFG_SUPPORT +#include "fwcfg.h" +#endif +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define PROC_MCR_ACCESS "mcr" +#define PROC_ROOT_NAME "wlan" +#ifdef FW_CFG_SUPPORT +#define PROC_CFG_NAME "cfg" +#endif + +#if CFG_SUPPORT_DEBUG_FS +#define PROC_ROAM_PARAM "roam_param" +#define PROC_COUNTRY "country" +#endif +#define PROC_DRV_STATUS "status" +#define PROC_RX_STATISTICS "rx_statistics" +#define PROC_TX_STATISTICS "tx_statistics" +#define PROC_DBG_LEVEL_NAME "dbgLevel" +#define PROC_PKT_DELAY_DBG "pktDelay" +#define PROC_SET_CAM "setCAM" +#define PROC_AUTO_PERF_CFG "autoPerfCfg" +#define PROC_SET_WIFI_CFG "wificfg" + +#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 +#define PROC_UID_SHELL 2000 +#define PROC_GID_WIFI 1010 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static P_GLUE_INFO_T g_prGlueInfo_proc; +static UINT_32 u4McrOffset; +static struct proc_dir_entry *gprProcNetRoot; +static struct proc_dir_entry *gprProcRoot; +static UINT_8 aucDbModuleName[][PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN] = { + "INIT", "HAL", "INTR", "REQ", "TX", "RX", "RFTEST", "EMU", "SW1", "SW2", + "SW3", "SW4", "HEM", "AIS", "RLM", "MEM", "CNM", "RSN", "BSS", "SCN", + "SAA", "AAA", "P2P", "QM", "SEC", "BOW", "WAPI", "ROAMING", "TDLS", "OID", + "NIC", "WNM", "WMM" +}; +static UINT_8 aucProcBuf[1536]; + +#if FW_CFG_SUPPORT +static P_GLUE_INFO_T gprGlueInfo; +#endif + +#define DRV_STATUS_BUF_LEN 2048 +static wait_queue_head_t waitqDrvStatus; +static struct mutex drvStatusLock; +static UINT_8 aucDrvStatus[DRV_STATUS_BUF_LEN]; +static INT_64 i8WrStatusPos; +static BOOLEAN fgDrvStatus; +/******************************************************************************* +* M A 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 ssize_t procDbgLevelRead(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + UINT_8 *temp = &aucProcBuf[0]; + UINT_32 u4CopySize = sizeof(aucProcBuf); + UINT_16 i; + UINT_16 u2ModuleNum = 0; + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0) + return 0; + + kalStrnCpy(temp, "\nTEMP|LOUD|INFO|TRACE | EVENT|STATE|WARN|ERROR\n" + "bit7|bit6|bit5|bit4 | bit3|bit2|bit1|bit0\n\n" + "Usage: Module Index:Module Level, such as 0x00:0xff\n\n" + "Debug Module\tIndex\tLevel\tDebug Module\tIndex\tLevel\n\n", + sizeof(aucProcBuf)); + temp += kalStrLen(temp); + u4CopySize -= kalStrLen(temp); + + u2ModuleNum = (sizeof(aucDbModuleName) / PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN) & 0xfe; + for (i = 0; i < u2ModuleNum; i += 2) + SNPRINTF(temp, u4CopySize, ("DBG_%s_IDX\t(0x%02x):\t0x%02x\tDBG_%s_IDX\t(0x%02x):\t0x%02x\n", + &aucDbModuleName[i][0], i, aucDebugModule[i], + &aucDbModuleName[i+1][0], i+1, aucDebugModule[i+1])); + + if ((sizeof(aucDbModuleName) / PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN) & 0x1) + SNPRINTF(temp, u4CopySize, ("DBG_%s_IDX\t(0x%02x):\t0x%02x\n", + &aucDbModuleName[u2ModuleNum][0], u2ModuleNum, aucDebugModule[u2ModuleNum])); + + u4CopySize = kalStrLen(aucProcBuf); + if (u4CopySize > count) + u4CopySize = count; + if (copy_to_user(buf, aucProcBuf, u4CopySize)) { + DBGLOG(HAL, ERROR, "copy to user failed\n"); + return -EFAULT; + } + + *f_pos += u4CopySize; + return (ssize_t)u4CopySize; +} + +static ssize_t procDbgLevelWrite(struct file *file, const char __user *buffer, size_t count, loff_t *data) +{ + UINT_32 u4NewDbgModule, u4NewDbgLevel; + UINT_8 *temp = &aucProcBuf[0]; + UINT_32 u4CopySize = sizeof(aucProcBuf); + + kalMemSet(aucProcBuf, 0, u4CopySize); + if (u4CopySize > count) + u4CopySize = count; + else + u4CopySize = u4CopySize - 1; + + if (copy_from_user(aucProcBuf, buffer, u4CopySize)) { + pr_err("error of copy from user\n"); + return -EFAULT; + } + aucProcBuf[u4CopySize] = '\0'; + + + while (temp) { + if (sscanf(temp, "0x%x:0x%x", &u4NewDbgModule, &u4NewDbgLevel) != 2) { + pr_info("debug module and debug level should be one byte in length\n"); + break; + } + if (u4NewDbgModule == 0xFF) { + UINT_8 i = 0; + + for (; i < DBG_MODULE_NUM; i++) + aucDebugModule[i] = u4NewDbgLevel & DBG_CLASS_MASK; + + break; + } else if (u4NewDbgModule >= DBG_MODULE_NUM) { + pr_info("debug module index should less than %d\n", DBG_MODULE_NUM); + break; + } + aucDebugModule[u4NewDbgModule] = u4NewDbgLevel & DBG_CLASS_MASK; + temp = kalStrChr(temp, ','); + if (!temp) + break; + temp++; /* skip ',' */ + } + wlanDbgLevelSync(); + return count; +} + + +static const struct file_operations dbglevel_ops = { + .owner = THIS_MODULE, + .read = procDbgLevelRead, + .write = procDbgLevelWrite, +}; + +static ssize_t procPktDelayDbgCfgRead(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + UINT_8 *temp = &aucProcBuf[0]; + UINT_32 u4CopySize = sizeof(aucProcBuf); + UINT_8 ucTxRxFlag; + UINT_8 ucTxIpProto; + UINT_16 u2TxUdpPort; + UINT_32 u4TxDelayThreshold; + UINT_8 ucRxIpProto; + UINT_16 u2RxUdpPort; + UINT_32 u4RxDelayThreshold; + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0) + return 0; + + kalStrnCpy(temp, + "\nUsage: txLog/rxLog/reset 1(ICMP)/6(TCP)/11(UDP) Dst/SrcPortNum DelayThreshold(us)\n" + "Print tx delay log, such as: echo txLog 0 0 0 > pktDelay\n" + "Print tx UDP delay log, such as: echo txLog 11 0 0 > pktDelay\n" + "Print tx UDP dst port19305 delay log, such as: echo txLog 11 19305 0 > pktDelay\n" + "Print rx UDP src port19305 delay more than 500us log, such as: echo rxLog 11 19305 500 > pktDelay\n" + "Print tx TCP delay more than 500us log, such as: echo txLog 6 0 500 > pktDelay\n" + "Close log, such as: echo reset 0 0 0 > pktDelay\n\n", + sizeof(aucProcBuf)); + temp += kalStrLen(temp); + u4CopySize -= kalStrLen(temp); + + StatsEnvGetPktDelay(&ucTxRxFlag, &ucTxIpProto, &u2TxUdpPort, &u4TxDelayThreshold, + &ucRxIpProto, &u2RxUdpPort, &u4RxDelayThreshold); + + if (ucTxRxFlag & BIT(0)) + SNPRINTF(temp, u4CopySize, ("txLog %x %d %d\n", ucTxIpProto, u2TxUdpPort, u4TxDelayThreshold)); + + if (ucTxRxFlag & BIT(1)) + SNPRINTF(temp, u4CopySize, ("rxLog %x %d %d\n", ucRxIpProto, u2RxUdpPort, u4RxDelayThreshold)); + + if (!ucTxRxFlag) + SNPRINTF(temp, u4CopySize, ("reset 0 0 0, there is no tx/rx delay log\n")); + + u4CopySize = kalStrLen(aucProcBuf); + if (u4CopySize > count) + u4CopySize = count; + + if (copy_to_user(buf, aucProcBuf, u4CopySize)) { + pr_err("copy to user failed\n"); + return -EFAULT; + } + + *f_pos += u4CopySize; + return (ssize_t)u4CopySize; +} + +static ssize_t procPktDelayDbgCfgWrite(struct file *file, const char __user *buffer, size_t count, loff_t *data) +{ +#define MODULE_NAME_LENGTH 7 +#define MODULE_RESET 0 +#define MODULE_TX 1 +#define MODULE_RX 2 + + UINT_32 u4CopySize = sizeof(aucProcBuf); + UINT_8 *temp = &aucProcBuf[0]; + UINT_8 aucModule[MODULE_NAME_LENGTH]; + UINT_32 u4DelayThreshold = 0; + UINT_16 u2PortNum = 0; + UINT_32 u4IpProto = 0; + UINT_8 aucResetArray[MODULE_NAME_LENGTH] = "reset"; + UINT_8 aucTxArray[MODULE_NAME_LENGTH] = "txLog"; + UINT_8 aucRxArray[MODULE_NAME_LENGTH] = "rxLog"; + UINT_8 ucTxOrRx = 0; + + kalMemSet(aucProcBuf, 0, u4CopySize); + if (u4CopySize > count) + u4CopySize = count; + else + u4CopySize = u4CopySize - 1; + + if (copy_from_user(aucProcBuf, buffer, u4CopySize)) { + pr_err("error of copy from user\n"); + return -EFAULT; + } + aucProcBuf[u4CopySize] = '\0'; + + while (temp) { + /* pick up a string and teminated after meet : */ + if (sscanf(temp, "%6s %x %hu %u", aucModule, &u4IpProto, &u2PortNum, &u4DelayThreshold) != 4) { + pr_info("read param fail, aucModule=%s\n", aucModule); + break; + } + + if (kalStrnCmp(aucModule, aucResetArray, MODULE_NAME_LENGTH) == 0) { + ucTxOrRx = MODULE_RESET; + } else if (kalStrnCmp(aucModule, aucTxArray, MODULE_NAME_LENGTH) == 0) { + ucTxOrRx = MODULE_TX; + } else if (kalStrnCmp(aucModule, aucRxArray, MODULE_NAME_LENGTH) == 0) { + ucTxOrRx = MODULE_RX; + } else { + pr_info("input module error!\n"); + break; + } + + temp = kalStrChr(temp, ','); + if (!temp) + break; + temp++; /* skip ',' */ + } + + StatsEnvSetPktDelay(ucTxOrRx, (UINT_8)u4IpProto, u2PortNum, u4DelayThreshold); + + return count; +} + +static const struct file_operations proc_pkt_delay_dbg_ops = { + .owner = THIS_MODULE, + .read = procPktDelayDbgCfgRead, + .write = procPktDelayDbgCfgWrite, +}; + +static ssize_t procSetCamCfgWrite(struct file *file, const char __user *buffer, size_t count, loff_t *data) +{ +#define MODULE_NAME_LEN_1 5 + + UINT_32 u4CopySize = sizeof(aucProcBuf); + UINT_8 *temp = &aucProcBuf[0]; + BOOLEAN fgSetCamCfg = FALSE; + UINT_8 aucModule[MODULE_NAME_LEN_1]; + UINT_32 u4Enabled; + UINT_8 aucModuleArray[MODULE_NAME_LEN_1] = "CAM"; + BOOLEAN fgParamValue = TRUE; + + kalMemSet(aucProcBuf, 0, u4CopySize); + if (u4CopySize > count) + u4CopySize = count; + else + u4CopySize = u4CopySize - 1; + + if (copy_from_user(aucProcBuf, buffer, u4CopySize)) { + pr_err("error of copy from user\n"); + return -EFAULT; + } + aucProcBuf[u4CopySize] = '\0'; + temp = &aucProcBuf[0]; + while (temp) { + /* pick up a string and teminated after meet : */ + if (sscanf(temp, "%4s %d", aucModule, &u4Enabled) != 2) { + pr_info("read param fail, aucModule=%s\n", aucModule); + fgParamValue = FALSE; + break; + } + + if (kalStrnCmp(aucModule, aucModuleArray, MODULE_NAME_LEN_1) == 0) { + if (u4Enabled) + fgSetCamCfg = TRUE; + else + fgSetCamCfg = FALSE; + } + temp = kalStrChr(temp, ','); + if (!temp) + break; + temp++; /* skip ',' */ + } + + if (fgParamValue) + nicConfigProcSetCamCfgWrite(fgSetCamCfg); + + return count; +} + +static const struct file_operations proc_set_cam_ops = { + .owner = THIS_MODULE, + .write = procSetCamCfgWrite, +}; + +/******************************************************************************* +* 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 ssize_t procMCRRead(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + P_GLUE_INFO_T prGlueInfo; + PARAM_CUSTOM_MCR_RW_STRUCT_T rMcrInfo; + UINT_32 u4BufLen; + UINT_32 u4Count = sizeof(aucProcBuf); + UINT_8 *temp = &aucProcBuf[0]; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + /* Kevin: Apply PROC read method 1. */ + if (*f_pos > 0) + return 0; /* To indicate end of file. */ + + prGlueInfo = g_prGlueInfo_proc; + + rMcrInfo.u4McrOffset = u4McrOffset; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryMcrRead, (PVOID)&rMcrInfo, sizeof(rMcrInfo), TRUE, TRUE, TRUE, &u4BufLen); + kalMemZero(aucProcBuf, sizeof(aucProcBuf)); + SNPRINTF(temp, u4Count, ("MCR (0x%08xh): 0x%08x\n", rMcrInfo.u4McrOffset, rMcrInfo.u4McrData)); + + u4Count = kalStrLen(aucProcBuf); + if (copy_to_user(buf, aucProcBuf, u4Count)) { + pr_err("copy to user failed\n"); + return -EFAULT; + } + + *f_pos += u4Count; + + 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 ssize_t procMCRWrite(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + P_GLUE_INFO_T prGlueInfo; + char acBuf[PROC_MCR_ACCESS_MAX_USER_INPUT_LEN + 1]; /* + 1 for "\0" */ + UINT_32 i4CopySize; + PARAM_CUSTOM_MCR_RW_STRUCT_T rMcrInfo; + UINT_32 u4BufLen; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + int num = 0; + + ASSERT(data); + + i4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + if (copy_from_user(acBuf, buffer, i4CopySize)) + return 0; + acBuf[i4CopySize] = '\0'; + + num = sscanf(acBuf, "0x%x 0x%x", &rMcrInfo.u4McrOffset, &rMcrInfo.u4McrData); + switch (num) { + 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, &u4BufLen); + + } + break; + + case 1: + /* if (IS_ALIGN_4(rMcrInfo.u4McrOffset)) */ + { + u4McrOffset = rMcrInfo.u4McrOffset; + } + break; + + default: + break; + } + + return count; + +} /* end of procMCRWrite() */ + +static const struct file_operations mcr_ops = { + .owner = THIS_MODULE, + .read = procMCRRead, + .write = procMCRWrite, +}; + +#if CFG_SUPPORT_DEBUG_FS +static ssize_t procRoamRead(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + UINT_32 u4CopySize; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + + /* if *f_pos > 0, it means has read successed last time, don't try again */ + if (*f_pos > 0) + return 0; + + rStatus = kalIoctl(g_prGlueInfo_proc, wlanoidGetRoamParams, aucProcBuf, sizeof(aucProcBuf), + TRUE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "failed to read roam params\n"); + return -EINVAL; + } + + u4CopySize = kalStrLen(aucProcBuf); + if (copy_to_user(buf, aucProcBuf, u4CopySize)) { + pr_err("copy to user failed\n"); + return -EFAULT; + } + *f_pos += u4CopySize; + + return (INT_32)u4CopySize; +} + +static ssize_t procRoamWrite(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + WLAN_STATUS rStatus; + UINT_32 u4BufLen = 0; + UINT_32 u4CopySize = sizeof(aucProcBuf); + + kalMemSet(aucProcBuf, 0, u4CopySize); + if (u4CopySize >= count+1) + u4CopySize = count; + else + u4CopySize = u4CopySize - 1; + + if (copy_from_user(aucProcBuf, buffer, u4CopySize)) { + pr_err("error of copy from user\n"); + return -EFAULT; + } + aucProcBuf[u4CopySize] = '\0'; + + if (kalStrnCmp(aucProcBuf, "force_roam", 10) == 0) + rStatus = kalIoctl(g_prGlueInfo_proc, wlanoidSetForceRoam, NULL, 0, + FALSE, FALSE, TRUE, &u4BufLen); + else + rStatus = kalIoctl(g_prGlueInfo_proc, wlanoidSetRoamParams, aucProcBuf, + kalStrLen(aucProcBuf), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "failed to set roam params: %s\n", aucProcBuf); + return -EINVAL; + } + return count; +} + +static const struct file_operations roam_ops = { + .owner = THIS_MODULE, + .read = procRoamRead, + .write = procRoamWrite, +}; + +static ssize_t procCountryRead(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + UINT_32 u4CopySize; + UINT_16 u2CountryCode = 0; + UINT_32 u4BufLen; + WLAN_STATUS rStatus; + + /* if *f_pos > 0, it means has read successed last time, don't try again */ + if (*f_pos > 0) + return 0; + + rStatus = kalIoctl(g_prGlueInfo_proc, wlanoidGetCountryCode, &u2CountryCode, 2, TRUE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "failed to get country code\n"); + return -EINVAL; + } + if (u2CountryCode) + kalSprintf(aucProcBuf, "Current Country Code: %c%c\n", (u2CountryCode>>8) & 0xff, u2CountryCode & 0xff); + else + kalStrCpy(aucProcBuf, "Current Country Code: NULL\n"); + + u4CopySize = kalStrLen(aucProcBuf); + if (copy_to_user(buf, aucProcBuf, u4CopySize)) { + pr_err("copy to user failed\n"); + return -EFAULT; + } + *f_pos += u4CopySize; + + return (INT_32)u4CopySize; +} + +static ssize_t procCountryWrite(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + UINT_32 u4BufLen = 0; + WLAN_STATUS rStatus; + UINT_32 u4CopySize = sizeof(aucProcBuf); + + kalMemSet(aucProcBuf, 0, u4CopySize); + if (u4CopySize >= count+1) + u4CopySize = count; + else + u4CopySize = u4CopySize - 1; + + if (copy_from_user(aucProcBuf, buffer, u4CopySize)) { + pr_err("error of copy from user\n"); + return -EFAULT; + } + + aucProcBuf[u4CopySize] = '\0'; + rStatus = kalIoctl(g_prGlueInfo_proc, wlanoidSetCountryCode, &aucProcBuf[0], 2, FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "failed set country code: %s\n", aucProcBuf); + return -EINVAL; + } + return count; +} + +static const struct file_operations country_ops = { + .owner = THIS_MODULE, + .read = procCountryRead, + .write = procCountryWrite, +}; +#endif + +#if CFG_SUPPORT_CFG_FILE +static ssize_t procWifiCfgRead(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + P_WLAN_CFG_ENTRY_T prCfgEntry = NULL; + PUINT_8 pucBuf = &aucProcBuf[0]; + UINT_32 i; + P_ADAPTER_T prAdapter = NULL; + INT_32 i4CopySize = 0; + UINT_32 u4CopySize = 0; + + if (*f_pos >= WLAN_CFG_ENTRY_NUM_MAX || !g_prGlueInfo_proc) + return 0; + + prAdapter = g_prGlueInfo_proc->prAdapter; + kalMemSet(aucProcBuf, 0, sizeof(aucProcBuf)); + prCfgEntry = &prAdapter->prWlanCfg->arWlanCfgBuf[0]; + + for (i = 0; i < WLAN_CFG_ENTRY_NUM_MAX; i++, prCfgEntry++) { + if (prCfgEntry->aucKey[0] == '\0') { + if (!i) { + u4CopySize = 19; + kalMemCopy(pucBuf, "No configure items\n", u4CopySize); + } + DBGLOG(INIT, INFO, "i=%u\n", i); + i = WLAN_CFG_ENTRY_NUM_MAX; + break; + } + i4CopySize = kalSnprintf(pucBuf, sizeof(aucProcBuf) - u4CopySize, "%s %s\n", + prCfgEntry->aucKey, prCfgEntry->aucValue); + if (i4CopySize < 0) { + i = WLAN_CFG_ENTRY_NUM_MAX; + DBGLOG(INIT, WARN, "snprintf fail, key %s\n", prCfgEntry->aucKey); + break; + } + pucBuf += i4CopySize; + u4CopySize += i4CopySize; + if (u4CopySize + WLAN_CFG_KEY_LEN_MAX + WLAN_CFG_KEY_LEN_MAX + 1 > count) + break; + if (u4CopySize >= sizeof(aucProcBuf)) { + i = WLAN_CFG_ENTRY_NUM_MAX; + DBGLOG(INIT, WARN, "too many configure items, buffer full\n"); + break; + } + } + *f_pos = i; + if (copy_to_user(buf, aucProcBuf, u4CopySize)) { + pr_err("copy to user failed\n"); + return -EFAULT; + } + + return u4CopySize; +} + +static ssize_t procWifiCfgWrite(struct file *file, const char __user *buffer, size_t count, loff_t *data) +{ + UINT_32 u4CopySize = sizeof(aucProcBuf); + P_ADAPTER_T prAdapter = NULL; + + if (!g_prGlueInfo_proc) + return 0; + prAdapter = g_prGlueInfo_proc->prAdapter; + kalMemSet(aucProcBuf, 0, u4CopySize); + + u4CopySize = (u4CopySize >= count + 1) ? count : u4CopySize - 1; + + if (!u4CopySize || copy_from_user(aucProcBuf, buffer, u4CopySize)) { + pr_err("error of copy from user\n"); + return -EFAULT; + } + aucProcBuf[u4CopySize] = '\0'; + wlanCfgParse(prAdapter, aucProcBuf, u4CopySize); + wlanInitFeatureOption(prAdapter); + return count; +} + +static const struct file_operations wifi_cfg_ops = { + .owner = THIS_MODULE, + .read = procWifiCfgRead, + .write = procWifiCfgWrite, +}; +#endif +static ssize_t procAutoPerfCfgRead(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + UINT_8 *temp = &aucProcBuf[0]; + UINT_32 u4CopySize = 0; + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0) + return 0; + + kalStrnCpy(temp, "Auto Performance Configure usage:\nForceEnable:0 or 1\n" + "e.g. ForceEnable:1 to always enable performance monitor even\n", + sizeof(aucProcBuf)); + + u4CopySize = kalStrLen(aucProcBuf); + if (u4CopySize > count) + u4CopySize = count; + + if (copy_to_user(buf, aucProcBuf, u4CopySize)) { + DBGLOG(INIT, WARN, "copy_to_user error\n"); + return -EFAULT; + } + + *f_pos += u4CopySize; + return (ssize_t)u4CopySize; +} + +static ssize_t procAutoPerfCfgWrite(struct file *file, const char *buffer, size_t count, loff_t *data) +{ + UINT_32 u4CoreNum = 0; + UINT_32 u4CoreFreq = 0; + UINT_8 *temp = &aucProcBuf[0]; + UINT_32 u4CopySize = count; + UINT_8 i = 0; + UINT_32 u4ForceEnable = 0; + UINT_8 aucBuf[32]; + + + if (u4CopySize >= sizeof(aucProcBuf)) + u4CopySize = sizeof(aucProcBuf) - 1; + + kalMemSet(aucProcBuf, 0, u4CopySize); + + if (copy_from_user(aucProcBuf, buffer, u4CopySize)) { + DBGLOG(INIT, WARN, "copy_from_user error\n"); + return -EFAULT; + } + + aucProcBuf[u4CopySize] = '\0'; + + i = sscanf(temp, "%d:%d", &u4CoreNum, &u4CoreFreq); + if (i == 2) { + DBGLOG(INIT, INFO, "u4CoreNum:%d, u4CoreFreq:%d\n", u4CoreNum, u4CoreFreq); + kalSetCpuNumFreq(u4CoreNum, u4CoreFreq); + return u4CopySize; + } + + if (strlen(temp) > sizeof(aucBuf)) { + DBGLOG(INIT, WARN, "input string(%s) len is too long, over %zu\n", aucProcBuf, sizeof(aucBuf)); + return -EFAULT; + } + + i = sscanf(temp, "%11s:%u", aucBuf, &u4ForceEnable); + + if ((i == 2) && strstr(aucBuf, "ForceEnable")) { + kalPerMonSetForceEnableFlag(u4ForceEnable); + return u4CopySize; + } + + DBGLOG(INIT, WARN, "parameter format should be ForceEnable:0 or 1\n"); + + return -EFAULT; +} + +static const struct file_operations auto_perf_ops = { + .owner = THIS_MODULE, + .read = procAutoPerfCfgRead, + .write = procAutoPerfCfgWrite, +}; + +VOID glWriteStatus(PPUINT_8 ppucWrPos, PUINT_32 pu4RemainLen, PUINT_8 pucFwt, ...) +{ +#define TEMP_BUF_LEN 280 + PUINT_8 pucTemp = NULL; + INT_32 i4BufUsed = 0; + INT_32 i4TimeUsed = 0; + va_list ap; + struct timeval tval; + struct rtc_time tm; + static UINT_8 aucBuf[TEMP_BUF_LEN]; + + pucTemp = &aucBuf[0]; + do_gettimeofday(&tval); + tval.tv_sec -= sys_tz.tz_minuteswest * 60; + rtc_time_to_tm(tval.tv_sec, &tm); + i4TimeUsed = kalSnprintf(pucTemp, TEMP_BUF_LEN, "%04d-%02d-%02d %02d:%02d:%02d.%03d ", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, + tm.tm_min, tm.tm_sec, (INT_32)(tval.tv_usec / USEC_PER_MSEC)); + if (i4TimeUsed < 0) { + DBGLOG(INIT, INFO, "error to sprintf time\n"); + return; + } + va_start(ap, pucFwt); + i4BufUsed = vsnprintf(pucTemp + i4TimeUsed, TEMP_BUF_LEN - i4TimeUsed, pucFwt, ap); + va_end(ap); + if (i4BufUsed < 0) { + DBGLOG(INIT, INFO, "error to sprintf %s\n", pucFwt); + return; + } + i4BufUsed += i4TimeUsed; + + if (i4BufUsed > *pu4RemainLen) { + kalMemCopy(*ppucWrPos, pucTemp, *pu4RemainLen); + pucTemp += *pu4RemainLen; + i4BufUsed -= *pu4RemainLen; + i8WrStatusPos += (INT_64)*pu4RemainLen; + *pu4RemainLen = DRV_STATUS_BUF_LEN; + *ppucWrPos = &aucDrvStatus[0]; + } + kalMemCopy(*ppucWrPos, pucTemp, i4BufUsed); + *ppucWrPos += i4BufUsed; + *pu4RemainLen -= i4BufUsed; + i8WrStatusPos += (INT_64)i4BufUsed; +} + +/* Provide a real-time monitor mechanism to end-user to monitor wlan status */ +VOID glNotifyDrvStatus(enum DRV_STATUS_T eDrvStatus, PVOID pvInfo) +{ + UINT_32 u4WrLen = i8WrStatusPos % DRV_STATUS_BUF_LEN; + UINT_32 u4RemainLen = DRV_STATUS_BUF_LEN - u4WrLen; + PUINT_8 pucRealWrPos = &aucDrvStatus[u4WrLen]; +#define WRITE_STATUS(_fmt, ...)\ + glWriteStatus(&pucRealWrPos, &u4RemainLen, _fmt, ##__VA_ARGS__) + + if (!fgDrvStatus) + return; + + mutex_lock(&drvStatusLock); + switch (eDrvStatus) { + case UNSOL_BTM_REQ: + case SOL_BTM_REQ: + { + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo = (P_AIS_SPECIFIC_BSS_INFO_T)pvInfo; + P_LINK_T prApList = &prAisSpecBssInfo->rNeighborApList.rUsingLink; + struct NEIGHBOR_AP_T *prNeighborAP = NULL; + + if (!prAisSpecBssInfo) { + DBGLOG(INIT, ERROR, "prAisSpecBssInfo is NULL\n"); + break; + } + WRITE_STATUS("Receive %s Btm Req with Mode:%d\n", eDrvStatus == SOL_BTM_REQ ? + "solicited" : "unsolicited", prAisSpecBssInfo->rBTMParam.ucRequestMode); + if (!(prAisSpecBssInfo->rBTMParam.ucRequestMode & BTM_REQ_MODE_CAND_INCLUDED_BIT)) + break; + WRITE_STATUS("Candidate List(Total %u), Bssid / Preference / Channel:\n", prApList->u4NumElem); + LINK_FOR_EACH_ENTRY(prNeighborAP, prApList, rLinkEntry, struct NEIGHBOR_AP_T) { + WRITE_STATUS("%pM / %d / %d\n", prNeighborAP->aucBssid, prNeighborAP->ucPreference, + prNeighborAP->ucChannel); + } + break; + } + case NEIGHBOR_AP_REP: + { + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo = (P_AIS_SPECIFIC_BSS_INFO_T)pvInfo; + P_LINK_T prApList = &prAisSpecBssInfo->rNeighborApList.rUsingLink; + struct NEIGHBOR_AP_T *prNeighborAP = NULL; + + if (!prAisSpecBssInfo) { + DBGLOG(INIT, ERROR, "prAisSpecBssInfo is NULL\n"); + break; + } + WRITE_STATUS("Receive Neighbor AP report\nCandidate List(Total %u), Bssid / Preference / Channel:\n", + prApList->u4NumElem); + LINK_FOR_EACH_ENTRY(prNeighborAP, prApList, rLinkEntry, struct NEIGHBOR_AP_T) { + WRITE_STATUS("%pM / %d / %d\n", prNeighborAP->aucBssid, prNeighborAP->ucPreference, + prNeighborAP->ucChannel); + } + break; + } + case SND_BTM_RSP: + { + struct BSS_TRANSITION_MGT_PARAM_T *prBtm = (struct BSS_TRANSITION_MGT_PARAM_T *)pvInfo; + + if (!prBtm) { + DBGLOG(INIT, ERROR, "prBtm is NULL\n"); + break; + } + if (prBtm->ucStatusCode == BSS_TRANSITION_MGT_STATUS_ACCEPT) + WRITE_STATUS("Send Btm Response, Roaming Target:%pM\n", prBtm->aucTargetBssid); + else + WRITE_STATUS("Send Btm Response, Reject reason:%d\n", prBtm->ucStatusCode); + break; + } + case CONNECT_AP: + WRITE_STATUS("Connect to %pM\n", (PUINT_8)pvInfo); + break; + case JOIN_FAIL: + { + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T)pvInfo; + + if (!prStaRec) { + DBGLOG(INIT, ERROR, "prStaRec is NULL\n"); + break; + } + WRITE_STATUS("Connect with %pM was rejected %d\n", prStaRec->aucMacAddr, prStaRec->u2StatusCode); + break; + } + case DISCONNECT_AP: + { + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T)pvInfo; + + if (!prBssInfo) + WRITE_STATUS("Disconnected reason: unknown\n"); + else + WRITE_STATUS("Disconnected reason: %d, bssid %pM\n", + prBssInfo->u2DeauthReason, prBssInfo->aucBSSID); + break; + } + case BEACON_TIMEOUT: + WRITE_STATUS("Beacon timeout with %pM\n", (PUINT_8)pvInfo); + break; + case RCV_FW_ROAMING: + WRITE_STATUS("%s\n", "Receive FW roaming event"); + break; + case ROAMING_SCAN_START: + { + P_MSG_SCN_SCAN_REQ_V2 prMsg = (P_MSG_SCN_SCAN_REQ_V2)pvInfo; + + if (!prMsg) { + DBGLOG(INIT, ERROR, "prMsg is NULL\n"); + break; + } + if (prMsg->eScanChannel == SCAN_CHANNEL_SPECIFIED) { + if (prMsg->u2ChannelDwellTime > 0) + WRITE_STATUS("Roaming Scan channel num:%d, dwell time %d\n", prMsg->ucChannelListNum, + prMsg->u2ChannelDwellTime); + else + WRITE_STATUS("Roaming Scan channel num:%d, default dwell time\n", + prMsg->ucChannelListNum); + } else + WRITE_STATUS("Roaming Full Scan, excluded channel num:%d\n", prMsg->ucChannelListNum); + break; + } + case ROAMING_SCAN_DONE: + WRITE_STATUS("%s\n", "Roaming Scan done"); + break; + default: + break; + } + mutex_unlock(&drvStatusLock); + /* Wake up all readers if at least one is waiting */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)) + if (!list_empty(&waitqDrvStatus.task_list)) +#else + if (!list_empty(&waitqDrvStatus.head)) +#endif + wake_up_interruptible(&waitqDrvStatus); +} + +/* Read callback function +** *f_pos: read position of current reader, max size: 4G * 4G bytes +** i8WrStatusPos: writing position of writer, max size: 4G * 4G bytes +*/ +static ssize_t procReadDrvStatus(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ +#define NOT_ENABLE "Driver Status is not enabled" +#define TO_ENABLE "echo enable > /proc/net/wlan/status to enable" +#define TO_DISABLE "echo disable > /proc/net/wlan/status to disable\n" + PUINT_8 pucRdPos = NULL; + UINT_32 u4CopySize = 0; + INT_32 ret = -1; + + while (ret) { + ret = wait_event_interruptible(waitqDrvStatus, (!fgDrvStatus || i8WrStatusPos != *f_pos)); + if (ret == -ERESTARTSYS) { + DBGLOG(INIT, INFO, "May be pending signal, return and let user space handle it\n"); + return 1; + } + } + + if (!fgDrvStatus) { + PUINT_8 pucErrMsg = NOT_ENABLE"\n"TO_ENABLE"\n"TO_DISABLE; + UINT_32 u4Len = kalStrLen(pucErrMsg); + + if (*f_pos == u4Len) + return 0; + if (copy_to_user(buf, pucErrMsg, u4Len)) { + DBGLOG(INIT, WARN, "copy_to_user error\n"); + return -EFAULT; + } + *f_pos = u4Len; + return u4Len; + } + + if (i8WrStatusPos < *f_pos) { + DBGLOG(INIT, INFO, "exit WR:%lld, RD:%lld\n", i8WrStatusPos, *f_pos); + return 0; + } + mutex_lock(&drvStatusLock); + if (*f_pos > 0) {/* Read again */ + if (i8WrStatusPos - *f_pos > DRV_STATUS_BUF_LEN) { + u4CopySize = (UINT_32)(i8WrStatusPos % DRV_STATUS_BUF_LEN); + pucRdPos = &aucDrvStatus[u4CopySize]; + u4CopySize = DRV_STATUS_BUF_LEN - u4CopySize; + DBGLOG(INIT, INFO, "Status Info Lost %lld bytes, WR:%lld, RD:%lld, MaxRd:%u bytes\n", + (i8WrStatusPos - *f_pos - DRV_STATUS_BUF_LEN), + i8WrStatusPos, *f_pos, u4CopySize); + *f_pos = i8WrStatusPos - DRV_STATUS_BUF_LEN; + } else { + u4CopySize = (UINT_32)(*f_pos % DRV_STATUS_BUF_LEN); + pucRdPos = &aucDrvStatus[u4CopySize]; + if (i8WrStatusPos - *f_pos > DRV_STATUS_BUF_LEN - u4CopySize) + u4CopySize = DRV_STATUS_BUF_LEN - u4CopySize; + else + u4CopySize = i8WrStatusPos - *f_pos; + DBGLOG(INIT, INFO, "Continue to read, WR:%lld, RD:%lld, MaxRd:%u bytes\n", + i8WrStatusPos, *f_pos, u4CopySize); + } + } else {/* The first time t read for current reader */ + if (i8WrStatusPos > DRV_STATUS_BUF_LEN) { + u4CopySize = (UINT_32)(i8WrStatusPos % DRV_STATUS_BUF_LEN); + pucRdPos = &aucDrvStatus[u4CopySize]; + u4CopySize = DRV_STATUS_BUF_LEN - u4CopySize; + *f_pos = i8WrStatusPos - DRV_STATUS_BUF_LEN; + } else { + pucRdPos = &aucDrvStatus[0]; + u4CopySize = (UINT_32)i8WrStatusPos; + } + DBGLOG(INIT, INFO, "First time to read, WR:%lld, RD:%lld, MaxRd:%u bytes\n", + i8WrStatusPos, *f_pos, u4CopySize); + } + mutex_unlock(&drvStatusLock); + + if (u4CopySize > count) + u4CopySize = count; + DBGLOG(INIT, TRACE, "Read %u bytes\n", u4CopySize); + if (copy_to_user(buf, pucRdPos, u4CopySize)) { + DBGLOG(INIT, WARN, "copy_to_user error\n"); + return -EFAULT; + } + *f_pos += u4CopySize; + return (ssize_t)u4CopySize; +} + +static ssize_t procDrvStatusCfg(struct file *file, const char *buffer, size_t count, loff_t *data) +{ + if (count >= sizeof(aucProcBuf)) + count = sizeof(aucProcBuf) - 1; + + kalMemSet(aucProcBuf, 0, sizeof(aucProcBuf)); + + if (copy_from_user(aucProcBuf, buffer, count)) { + DBGLOG(INIT, WARN, "copy_from_user error\n"); + return -EFAULT; + } + + aucProcBuf[count] = '\0'; + + if (!kalStrnCmp(aucProcBuf, "enable", 6)) { + fgDrvStatus = TRUE; + i8WrStatusPos = 0; + return 6; + } else if (!kalStrnCmp(aucProcBuf, "disable", 7)) { + fgDrvStatus = FALSE; + wake_up_interruptible(&waitqDrvStatus); + return 7; + } + return -EINVAL; +} + +static const struct file_operations drv_status_ops = { + .owner = THIS_MODULE, + .read = procReadDrvStatus, + .write = procDrvStatusCfg, +}; + +INT_32 procInitFs(VOID) +{ + struct proc_dir_entry *prEntry; + + /* Create folder /proc/wlan/ to avoid dump by other processes, like netdiag */ + gprProcRoot = proc_mkdir(PROC_ROOT_NAME, NULL); + if (!gprProcRoot) { + pr_err("gprProcRoot == NULL\n"); + return -ENOENT; + } + + if (init_net.proc_net == (struct proc_dir_entry *)NULL) { + pr_err("init proc fs fail: proc_net == NULL\n"); + return -ENOENT; + } + + /* Create folder /proc/net/wlan */ + gprProcNetRoot = proc_mkdir(PROC_ROOT_NAME, init_net.proc_net); + if (!gprProcNetRoot) { + pr_err("gprProcNetRoot == NULL\n"); + return -ENOENT; + } + proc_set_user(gprProcNetRoot, KUIDT_INIT(PROC_UID_SHELL), KGIDT_INIT(PROC_GID_WIFI)); + + prEntry = proc_create(PROC_DBG_LEVEL_NAME, 0664, gprProcNetRoot, &dbglevel_ops); + if (!prEntry) { + pr_err("Unable to create /proc entry dbgLevel\n\r"); + return -1; + } + proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL), KGIDT_INIT(PROC_GID_WIFI)); + + prEntry = proc_create(PROC_AUTO_PERF_CFG, 0664, gprProcNetRoot, &auto_perf_ops); + if (!prEntry) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry %s/n", PROC_AUTO_PERF_CFG); + return -1; + } + proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL), KGIDT_INIT(PROC_GID_WIFI)); + + init_waitqueue_head(&waitqDrvStatus); + mutex_init(&drvStatusLock); + fgDrvStatus = TRUE; + prEntry = proc_create(PROC_DRV_STATUS, 0664, gprProcRoot, &drv_status_ops); + if (!prEntry) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry %s/n", PROC_DRV_STATUS); + return -1; + } + proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL), KGIDT_INIT(PROC_GID_WIFI)); + return 0; +} /* end of procInitProcfs() */ + +INT_32 procUninitProcFs(VOID) +{ + remove_proc_entry(PROC_DBG_LEVEL_NAME, gprProcNetRoot); + remove_proc_entry(PROC_AUTO_PERF_CFG, gprProcNetRoot); + remove_proc_entry(PROC_DRV_STATUS, gprProcRoot); + remove_proc_subtree(PROC_ROOT_NAME, init_net.proc_net); + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function clean up a PROC fs created by procInitProcfs(). +* +* \param[in] prDev Pointer to the struct net_device. +* \param[in] pucDevName Pointer to the name of net_device. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +INT_32 procRemoveProcfs(VOID) +{ + remove_proc_entry(PROC_MCR_ACCESS, gprProcNetRoot); + remove_proc_entry(PROC_PKT_DELAY_DBG, gprProcNetRoot); + remove_proc_entry(PROC_SET_CAM, gprProcNetRoot); +#if CFG_SUPPORT_DEBUG_FS + remove_proc_entry(PROC_ROAM_PARAM, gprProcNetRoot); + remove_proc_entry(PROC_COUNTRY, gprProcNetRoot); + +#endif + +#if CFG_SUPPORT_CFG_FILE + remove_proc_entry(PROC_SET_WIFI_CFG, gprProcNetRoot); +#endif + return 0; +} /* end of procRemoveProcfs() */ + +INT_32 procCreateFsEntry(P_GLUE_INFO_T prGlueInfo) +{ + struct proc_dir_entry *prEntry; + + DBGLOG(INIT, LOUD, "[%s]\n", __func__); + g_prGlueInfo_proc = prGlueInfo; + + prEntry = proc_create(PROC_MCR_ACCESS, 0664, gprProcNetRoot, &mcr_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry\n\r"); + return -1; + } + + prEntry = proc_create(PROC_PKT_DELAY_DBG, 0664, gprProcNetRoot, &proc_pkt_delay_dbg_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry PktDelayDug\n\r"); + return -ENOENT; + } + proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL), KGIDT_INIT(PROC_GID_WIFI)); + + prEntry = proc_create(PROC_SET_CAM, 0664, gprProcNetRoot, &proc_set_cam_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry SetCAM\n\r"); + return -1; + } + proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL), KGIDT_INIT(PROC_GID_WIFI)); +#if CFG_SUPPORT_DEBUG_FS + prEntry = proc_create(PROC_ROAM_PARAM, 0664, gprProcNetRoot, &roam_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry\n\r"); + return -1; + } + prEntry = proc_create(PROC_COUNTRY, 0664, gprProcNetRoot, &country_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry\n\r"); + return -1; + } +#endif + +#if CFG_SUPPORT_CFG_FILE + prEntry = proc_create(PROC_SET_WIFI_CFG, 0664, gprProcNetRoot, &wifi_cfg_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry\n\r"); + return -1; + } +#endif + return 0; +} + +#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 (kstrtouint(acBuf, 0, &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 (kstrtouint(acBuf, 0, &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 + +#ifdef FW_CFG_SUPPORT +#define MAX_CFG_OUTPUT_BUF_LENGTH 1024 +static UINT_8 aucCfgBuf[CMD_FORMAT_V1_LENGTH]; +static UINT_8 aucCfgQueryKey[MAX_CMD_NAME_MAX_LENGTH]; +static UINT_8 aucCfgOutputBuf[MAX_CFG_OUTPUT_BUF_LENGTH]; + +static ssize_t cfgRead(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_8 *temp = &aucCfgOutputBuf[0]; + UINT_32 u4CopySize = sizeof(aucCfgOutputBuf); + UINT_32 u4RetValue = 0; + + struct _CMD_HEADER_T cmdV1Header; + struct _CMD_FORMAT_V1_T *pr_cmd_v1 = (struct _CMD_FORMAT_V1_T *) cmdV1Header.buffer; + + /* if *f_pos > 0, we should return 0 to make cat command exit */ + if (*f_pos > 0 || gprGlueInfo == NULL) + return 0; + + kalMemSet(aucCfgOutputBuf, 0, MAX_CFG_OUTPUT_BUF_LENGTH); + + SNPRINTF(temp, u4CopySize, ("\nprocCfgRead() %s:\n", aucCfgQueryKey)); + + /* send to FW */ + cmdV1Header.cmdVersion = CMD_VER_1; + cmdV1Header.cmdType = CMD_TYPE_QUERY; + cmdV1Header.itemNum = 1; + cmdV1Header.cmdBufferLen = sizeof(struct _CMD_FORMAT_V1_T); + kalMemSet(cmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); + + pr_cmd_v1->itemStringLength = kalStrLen(aucCfgQueryKey); + + kalMemCopy(pr_cmd_v1->itemString, aucCfgQueryKey, kalStrLen(aucCfgQueryKey)); + + rStatus = kalIoctl(gprGlueInfo, + wlanoidQueryCfgRead, + (PVOID)&cmdV1Header, + sizeof(cmdV1Header), + TRUE, + TRUE, + TRUE, + &u4RetValue); + if (rStatus == WLAN_STATUS_FAILURE) + DBGLOG(INIT, ERROR, "prCmdV1Header kalIoctl wlanoidQueryCfgRead fail 0x%x\n", rStatus); + + SNPRINTF(temp, u4CopySize, ("%s\n", cmdV1Header.buffer)); + + u4CopySize = kalStrLen(aucCfgOutputBuf); + if (u4CopySize > count) + u4CopySize = count; + + if (copy_to_user(buf, aucCfgOutputBuf, u4CopySize)) + DBGLOG(INIT, ERROR, "copy to user failed\n"); + + *f_pos += u4CopySize; + return (ssize_t)u4CopySize; +} + +static ssize_t cfgWrite(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) +{ + /* echo xxx xxx > /proc/net/wlan/cfg */ + UINT_8 i = 0; + UINT_32 u4CopySize = sizeof(aucCfgBuf); + UINT_8 token_num = 1; + + if (!count) + return -EINVAL; + + kalMemSet(aucCfgBuf, 0, u4CopySize); + + if (u4CopySize > count) + u4CopySize = count; + else + u4CopySize = u4CopySize - 1; + + if (copy_from_user(aucCfgBuf, buf, u4CopySize)) { + DBGLOG(INIT, ERROR, "copy from user failed\n"); + return -EFAULT; + } + aucCfgBuf[u4CopySize] = '\0'; + + for (; i < u4CopySize; i++) { + if (aucCfgBuf[i] == ' ') { + token_num++; + break; + } + } + + if (token_num == 1) { + kalMemSet(aucCfgQueryKey, 0, sizeof(aucCfgQueryKey)); + /* remove the 0x0a */ + if (u4CopySize > sizeof(aucCfgQueryKey)) + return -EINVAL; + memcpy(aucCfgQueryKey, aucCfgBuf, u4CopySize); + if (aucCfgQueryKey[u4CopySize - 1] == 0x0a) + aucCfgQueryKey[u4CopySize - 1] = '\0'; + } else + wlanFwCfgParse(gprGlueInfo->prAdapter, aucCfgBuf); + + return count; +} + +static const struct file_operations cfg_ops = { + .owner = THIS_MODULE, + .read = cfgRead, + .write = cfgWrite, +}; + +INT_32 cfgRemoveProcEntry(void) +{ + remove_proc_entry(PROC_CFG_NAME, gprProcNetRoot); + return 0; +} + +INT_32 cfgCreateProcEntry(P_GLUE_INFO_T prGlueInfo) +{ + struct proc_dir_entry *prEntry; + + prGlueInfo->pProcRoot = gprProcNetRoot; + gprGlueInfo = prGlueInfo; + + prEntry = proc_create(PROC_CFG_NAME, 0664, gprProcNetRoot, &cfg_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry cfg\n\r"); + return -1; + } + proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL), KGIDT_INIT(PROC_GID_WIFI)); + + return 0; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_qa_agent.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_qa_agent.c new file mode 100644 index 0000000000000..b52aa3a243e95 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_qa_agent.c @@ -0,0 +1,7666 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ +/* + *************************************************************************** + + Module Name: + gl_ate_agent.c +*/ +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ + +#include "precomp.h" +#if (CFG_SUPPORT_QA_TOOL == 1) +#include "gl_wext.h" +#include "gl_cfg80211.h" +#include "gl_ate_agent.h" +#include "gl_qa_agent.h" +#include "gl_hook_api.h" +/* #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) */ +#include +/* #endif */ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +PARAM_RX_STAT_T g_HqaRxStat; +UINT_32 u4RxStatSeqNum; +BOOLEAN g_DBDCEnable = FALSE; +/* For SA Buffer Mode Temp Solution */ +BOOLEAN g_BufferDownload = FALSE; +UINT_32 u4EepromMode = 4; + +#if CFG_SUPPORT_BUFFER_MODE +UINT_8 uacEEPROMImage[MAX_EEPROM_BUFFER_SIZE] = { + /* 0x000 ~ 0x00F */ + 0xAE, 0x86, 0x06, 0x00, 0x18, 0x0D, 0x00, 0x00, 0xC0, 0x1F, 0xBD, 0x81, 0x3F, 0x01, 0x19, 0x00, + /* 0x010 ~ 0x01F */ + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, + /* 0x020 ~ 0x02F */ + 0x80, 0x02, 0x00, 0x00, 0x32, 0x66, 0xC3, 0x14, 0x32, 0x66, 0xC3, 0x14, 0x03, 0x22, 0xFF, 0xFF, + /* 0x030 ~ 0x03F */ + 0x23, 0x04, 0x0D, 0xF2, 0x8F, 0x02, 0x00, 0x80, 0x0A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x040 ~ 0x04F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x40, 0x00, 0x00, + /* 0x050 ~ 0x05F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x08, + /* 0x060 ~ 0x06F */ + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x08, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x08, + /* 0x070 ~ 0x07F */ + 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x080 ~ 0x08F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x090 ~ 0x09F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x0A0 ~ 0x0AF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x0B0 ~ 0x0BF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x10, 0x10, 0x28, 0x00, 0x00, 0x00, 0x00, + /* 0x0C0 ~ 0x0CF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x0D0 ~ 0x0DF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x0E0 ~ 0x0EF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x0F0 ~ 0x0FF */ + 0x0E, 0x05, 0x06, 0x06, 0x06, 0x0F, 0x00, 0x00, 0x0E, 0x05, 0x06, 0x05, 0x05, 0x09, 0xFF, 0x00, + /* 0x100 ~ 0x10F */ + 0x12, 0x34, 0x56, 0x78, 0x2C, 0x2C, 0x28, 0x28, 0x28, 0x26, 0x26, 0x28, 0x28, 0x28, 0x26, 0xFF, + /* 0x110 ~ 0x11F */ + 0x26, 0x25, 0x28, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x27, 0x27, 0x25, + /* 0x120 ~ 0x12F */ + 0x25, 0x25, 0x25, 0x25, 0x23, 0x23, 0x23, 0x21, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, + /* 0x130 ~ 0x13F */ + 0x40, 0x40, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + /* 0x140 ~ 0x14F */ + 0x25, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x150 ~ 0x15F */ + 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, + /* 0x160 ~ 0x16F */ + 0xD0, 0xD0, 0xD0, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x170 ~ 0x17F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, 0xC4, 0xC5, 0xC8, + /* 0x180 ~ 0x18F */ + 0x00, 0x26, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x190 ~ 0x19F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x1A0 ~ 0x1AF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0xD0, 0xD0, 0x0E, 0x05, 0x06, 0x05, 0x09, 0x0E, 0x00, + /* 0x1B0 ~ 0x1BF */ + 0x05, 0x06, 0x05, 0x05, 0x09, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + /* 0x1C0 ~ 0x1CF */ + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, + /* 0x1D0 ~ 0x1DF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x1E0 ~ 0x1EF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x1F0 ~ 0x1FF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x200 ~ 0x20F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x210 ~ 0x21F */ + 0x48, 0xF5, 0x27, 0x49, 0x48, 0xF5, 0x57, 0x12, 0x4B, 0x71, 0x80, 0x50, 0x91, 0xF6, 0x87, 0x50, + /* 0x220 ~ 0x22F */ + 0x7D, 0x29, 0x09, 0x42, 0x7D, 0x29, 0x41, 0x44, 0x7D, 0x29, 0x41, 0x3C, 0x7D, 0x29, 0x31, 0x4D, + /* 0x230 ~ 0x23F */ + 0x49, 0x71, 0x24, 0x49, 0x49, 0x71, 0x54, 0x12, 0x4B, 0x71, 0x80, 0x50, 0x91, 0xF6, 0x87, 0x50, + /* 0x240 ~ 0x24F */ + 0x7D, 0x29, 0x09, 0x42, 0x7D, 0x29, 0x41, 0x04, 0x7D, 0x29, 0x41, 0x04, 0x7D, 0x29, 0x01, 0x40, + /* 0x250 ~ 0x25F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x260 ~ 0x26F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x270 ~ 0x27F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x280 ~ 0x28F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x290 ~ 0x29F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x2A0 ~ 0x2AF */ + 0x7D, 0x29, 0xC9, 0x16, 0x7D, 0x29, 0xC9, 0x16, 0x44, 0x22, 0x32, 0x15, 0xEE, 0xEE, 0xEE, 0x08, + /* 0x2B0 ~ 0x2BF */ + 0x78, 0x90, 0x79, 0x1C, 0x78, 0x90, 0x79, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x2C0 ~ 0x2CF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x2D0 ~ 0x2DF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x2E0 ~ 0x2EF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x2F0 ~ 0x2FF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x300 ~ 0x30F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x310 ~ 0x31F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x42, 0x10, 0x42, 0x08, 0x21, + /* 0x320 ~ 0x32F */ + 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x21, + /* 0x330 ~ 0x33F */ + 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x21, + /* 0x340 ~ 0x34F */ + 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x01, + /* 0x350 ~ 0x35F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x360 ~ 0x36F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x370 ~ 0x37F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x380 ~ 0x38F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x390 ~ 0x39F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x3A0 ~ 0x3AF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x3B0 ~ 0x3BF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x3C0 ~ 0x3CF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x3D0 ~ 0x3DF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x3E0 ~ 0x3EF */ + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + /* 0x3F0 ~ 0x3FF */ + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + /* 0x400 ~ 0x40F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x410 ~ 0x41F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x420 ~ 0x42F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x430 ~ 0x43F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x440 ~ 0x44F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x450 ~ 0x45F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x460 ~ 0x46F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x470 ~ 0x47F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x480 ~ 0x48F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x490 ~ 0x49F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x4A0 ~ 0x4AF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Response ACK to QA Tool DLL. +* +* \param[in] HqaCmdFrame Ethernet Frame Format respond to QA Tool DLL +* \param[in] prIwReqData +* \param[in] i4Length Length of Ethernet Frame data field +* \param[in] i4Status Status to respond +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If copy_to_user fail +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 ResponseToQA(HQA_CMD_FRAME *HqaCmdFrame, + IN union iwreq_data *prIwReqData, INT_32 i4Length, INT_32 i4Status) +{ + HqaCmdFrame->Length = ntohs((i4Length)); + + i4Status = ntohs((i4Status)); + memcpy(HqaCmdFrame->Data, &i4Status, 2); + + prIwReqData->data.length = sizeof((HqaCmdFrame)->MagicNo) + sizeof((HqaCmdFrame)->Type) + + sizeof((HqaCmdFrame)->Id) + sizeof((HqaCmdFrame)->Length) + + sizeof((HqaCmdFrame)->Sequence) + ntohs((HqaCmdFrame)->Length); + + if (copy_to_user(prIwReqData->data.pointer, (UCHAR *) (HqaCmdFrame), prIwReqData->data.length)) { + DBGLOG(RFTEST, ERROR, " QA_AGENT copy_to_user() fail in %s\n", __func__); + return (-EFAULT); + } + DBGLOG(RFTEST, INFO, " QA_AGENT HQA command(0x%04x)[Magic number(0x%08x)] is done,i4Status(%d)\n", + ntohs(HqaCmdFrame->Id), ntohl(HqaCmdFrame->MagicNo), i4Status); + + return 0; +} + +static INT_32 ToDoFunction(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT ToDoFunction\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Open Adapter (called when QA Tool UI Open). +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_OpenAdapter(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_OpenAdapter\n"); + + i4Ret = MT_ATEStart(prNetDev, "ATESTART"); + + /* For SA Buffer Mode Temp Solution */ + g_BufferDownload = FALSE; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Close Adapter (called when QA Tool UI Close). +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_CloseAdapter(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_CloseAdapter\n"); + + i4Ret = MT_ATEStop(prNetDev, "ATESTOP"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Start TX. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_StartTx(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 TxCount; + UINT_16 TxLength; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_StartTx\n"); + + memcpy((PUCHAR) & TxCount, HqaCmdFrame->Data + 4 * 0, 4); + TxCount = ntohl(TxCount); + memcpy((PUCHAR) & TxLength, HqaCmdFrame->Data + 4 * 1, 2); + TxLength = ntohs(TxLength); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_StartTx TxCount = %u, TxLength = %u\n", TxCount, TxLength); + + i4Ret = MT_ATESetTxCount(prNetDev, TxCount); + i4Ret = MT_ATESetTxLength(prNetDev, (UINT_32) TxLength); + i4Ret = MT_ATEStartTX(prNetDev, "TXFRAME"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +/* 1 todo not support yet */ +static INT_32 HQA_StartTxExt(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_StartTxExt\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Start Continuous TX. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +/* 1 todo not support yet */ +static INT_32 HQA_StartTxContiTx(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_StartTxContiTx\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +/* 1 todo not support yets */ +static INT_32 HQA_StartTxCarrier(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_StartTxCarrier\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Start RX (Legacy function). +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_StartRx(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_StartRx\n"); + + MT_ATESetDBDCBandIndex(prNetDev, 0); + MT_ATEStartRX(prNetDev, "RXFRAME"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Stop TX (Legacy function). +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_StopTx(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_StopTx\n"); + + MT_ATESetDBDCBandIndex(prNetDev, 0); + MT_ATEStopRX(prNetDev, "RXSTOP"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Stop Continuous TX. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_StopContiTx(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_StopContiTx\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_StopTxCarrier(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_StopTxCarrier\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Stop RX (Legacy function). +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_StopRx(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_StopRx\n"); + + MT_ATESetDBDCBandIndex(prNetDev, 0); + MT_ATEStopRX(prNetDev, "RXSTOP"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set TX Path. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetTxPath(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetTxPath\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set RX Path. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetRxPath(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; +/* INT_16 Value = 0; + * P_GLUE_INFO_T prGlueInfo = NULL; + * PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + * UINT_32 u4BufLen = 0; + */ + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetRxPath\n"); + +#if 0 + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memcpy(&Value, HqaCmdFrame->Data + 4 * 0, 2); + Value = ntohs(Value); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetRxPath Value : %d\n", Value); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_RX_PATH; + rRfATInfo.u4FuncData = (UINT_32) ((Value << 16) || (0 & BITS(0, 15))); + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; +#endif + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set TX Inter-Packet Guard. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetTxIPG(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Aifs = 0; + + memcpy(&u4Aifs, HqaCmdFrame->Data + 4 * 0, 4); + u4Aifs = ntohs(u4Aifs); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetTxIPG u4Aifs : %u\n", u4Aifs); + + MT_ATESetTxIPG(prNetDev, u4Aifs); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set TX Power0 (Legacy Function). +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetTxPower0(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetTxPower0\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set TX Power1. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HAQ_SetTxPower1(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HAQ_SetTxPower1\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetTxPowerExt(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Power = 0; + UINT_32 u4Channel = 0; + UINT_32 u4Dbdc_idx = 0; + UINT_32 u4Band_idx = 0; + UINT_32 u4Ant_idx = 0; + + memcpy(&u4Power, HqaCmdFrame->Data + 4 * 0, 4); + u4Power = ntohl(u4Power); + memcpy(&u4Dbdc_idx, HqaCmdFrame->Data + 4 * 1, 4); + u4Dbdc_idx = ntohl(u4Dbdc_idx); + memcpy(&u4Channel, HqaCmdFrame->Data + 4 * 2, 4); + u4Channel = ntohl(u4Channel); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 3, 4); + u4Band_idx = ntohl(u4Band_idx); + memcpy(&u4Ant_idx, HqaCmdFrame->Data + 4 * 4, 4); + u4Ant_idx = ntohl(u4Ant_idx); + + DBGLOG(RFTEST, INFO, + " QA_AGENT HQA_SetTxPowerExt u4Power : %u,u4Dbdc_idx:%u, u4Channel:%u,u4Band_idx:%u, u4Ant_idx:%u\n", + u4Power, u4Dbdc_idx, u4Channel, u4Band_idx, u4Ant_idx); + + MT_ATESetDBDCBandIndex(prNetDev, u4Dbdc_idx); + MT_ATESetTxPower0(prNetDev, u4Power); + /* u4Freq = nicChannelNum2Freq(u4Channel); */ + /* i4Ret = MT_ATESetChannel(prNetDev, 0, u4Freq); */ + /* MT_ATESetBand(prNetDev, u4Band_idx); */ + /* Antenna?? */ + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetOnOff(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetOnOff\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Antenna Selection. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_AntennaSel(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_AntennaSel\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_FWPacketCMD_ClockSwitchDisable(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_FWPacketCMD_ClockSwitchDisable\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_CMD_SET0[] = { + /* cmd id start from 0x1000 */ + HQA_OpenAdapter, /* 0x1000 */ + HQA_CloseAdapter, /* 0x1001 */ + HQA_StartTx, /* 0x1002 */ + HQA_StartTxExt, /* 0x1003 */ + HQA_StartTxContiTx, /* 0x1004 */ + HQA_StartTxCarrier, /* 0x1005 */ + HQA_StartRx, /* 0x1006 */ + HQA_StopTx, /* 0x1007 */ + HQA_StopContiTx, /* 0x1008 */ + HQA_StopTxCarrier, /* 0x1009 */ + HQA_StopRx, /* 0x100A */ + HQA_SetTxPath, /* 0x100B */ + HQA_SetRxPath, /* 0x100C */ + HQA_SetTxIPG, /* 0x100D */ + HQA_SetTxPower0, /* 0x100E */ + HAQ_SetTxPower1, /* 0x100F */ + ToDoFunction, /* 0x1010 */ + HQA_SetTxPowerExt, /* 0x1011 */ + HQA_SetOnOff, /* 0x1012 */ + HQA_AntennaSel, /* 0x1013 */ + HQA_FWPacketCMD_ClockSwitchDisable, /* 0x1014 */ +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set Channel Frequency (Legacy Function). +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetChannel(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + UINT_32 i4SetFreq = 0, i4SetChan = 0; + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetChannel\n"); + + memcpy((PUCHAR) & i4SetChan, HqaCmdFrame->Data, 4); + i4SetChan = ntohl(i4SetChan); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetChannel Channel = %d\n", i4SetChan); + + i4SetFreq = nicChannelNum2Freq(i4SetChan); + i4Ret = MT_ATESetChannel(prNetDev, 0, i4SetFreq); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set Preamble (Legacy Function). +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetPreamble(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Mode = 0; + INT_32 i4Ret = 0; + + memcpy((PUCHAR) & i4Mode, HqaCmdFrame->Data, 4); + i4Mode = ntohl(i4Mode); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetPreamble Mode = %d\n", i4Mode); + + i4Ret = MT_ATESetPreamble(prNetDev, i4Mode); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set Rate (Legacy Function). +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetRate(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ +/* INT_32 i4Value = 0; */ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetRate\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set Nss. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetNss(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetNss\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set System BW (Legacy Function). +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetSystemBW(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + UINT_32 i4BW; + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetSystemBW\n"); + + memcpy((PUCHAR) & i4BW, HqaCmdFrame->Data, 4); + i4BW = ntohl(i4BW); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetSystemBW BW = %d\n", i4BW); + + i4Ret = MT_ATESetSystemBW(prNetDev, i4BW); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set Data BW (Legacy Function). +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetPerPktBW(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Perpkt_bw; + + memcpy((PUCHAR) & u4Perpkt_bw, HqaCmdFrame->Data, 4); + u4Perpkt_bw = ntohl(u4Perpkt_bw); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetPerPktBW u4Perpkt_bw = %u\n", u4Perpkt_bw); + + i4Ret = MT_ATESetPerPacketBW(prNetDev, u4Perpkt_bw); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set Primary BW. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetPrimaryBW(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Pri_sel = 0; + + memcpy(&u4Pri_sel, HqaCmdFrame->Data, 4); + u4Pri_sel = ntohl(u4Pri_sel); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetPrimaryBW u4Pri_sel : %d\n", u4Pri_sel); + + i4Ret = MT_ATEPrimarySetting(prNetDev, u4Pri_sel); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set Frequency Offset. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetFreqOffset(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4FreqOffset = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 u4BufLen = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memcpy(&u4FreqOffset, HqaCmdFrame->Data, 4); + u4FreqOffset = ntohl(u4FreqOffset); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetFreqOffset u4FreqOffset : %d\n", u4FreqOffset); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_FRWQ_OFFSET; + rRfATInfo.u4FuncData = (UINT_32) u4FreqOffset; + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetAutoResponder(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetAutoResponder\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetTssiOnOff(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetTssiOnOff\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +/* 1 todo not support yet */ + +static INT_32 HQA_SetRxHighLowTemperatureCompensation(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetRxHighLowTemperatureCompensation\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_LowPower(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_LowPower\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_CMD_SET1[] = { + /* cmd id start from 0x1100 */ + HQA_SetChannel, /* 0x1100 */ + HQA_SetPreamble, /* 0x1101 */ + HQA_SetRate, /* 0x1102 */ + HQA_SetNss, /* 0x1103 */ + HQA_SetSystemBW, /* 0x1104 */ + HQA_SetPerPktBW, /* 0x1105 */ + HQA_SetPrimaryBW, /* 0x1106 */ + HQA_SetFreqOffset, /* 0x1107 */ + HQA_SetAutoResponder, /* 0x1108 */ + HQA_SetTssiOnOff, /* 0x1109 */ + HQA_SetRxHighLowTemperatureCompensation, /* 0x110A */ + HQA_LowPower, /* 0x110B */ +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Reset TRX Counter +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_ResetTxRxCounter(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + UINT_32 i4Status; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_ResetTxRxCounter\n"); + + i4Status = MT_ATEResetTXRXCounter(prNetDev); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetStatistics(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_GetStatistics\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetRxOKData(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_GetRxOKData\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetRxOKOther(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_GetRxOKOther\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetRxAllPktCount(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_GetRxAllPktCount\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetTxTransmitted(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_GetTxTransmitted\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetHwCounter(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_GetHwCounter\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_CalibrationOperation(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_CalibrationOperation\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_CalibrationBypassExt(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Status = 0; + UINT_32 u4Item = 0; + UINT_32 u4Band_idx = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 u4BufLen = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memcpy(&u4Item, HqaCmdFrame->Data, 4); + u4Item = ntohl(u4Item); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, " QA_AGENT u4Item : 0x%08x, u4Band_idx : %u\n", u4Item, u4Band_idx); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_BYPASS_CAL_STEP; + rRfATInfo.u4FuncData = u4Item; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetRXVectorIdx(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 band_idx = 0; + UINT_32 Group_1 = 0, Group_2 = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 u4BufLen = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memcpy(&band_idx, HqaCmdFrame->Data + 4 * 0, 4); + band_idx = ntohl(band_idx); + memcpy(&Group_1, HqaCmdFrame->Data + 4 * 1, 4); + Group_1 = ntohl(Group_1); + memcpy(&Group_2, HqaCmdFrame->Data + 4 * 2, 4); + Group_2 = ntohl(Group_2); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetRXVectorIdx band_idx : %u, Group_1 : %u, Group_2 : %u\n", + band_idx, Group_1, Group_2); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_RXV_INDEX; + rRfATInfo.u4FuncData = (UINT_32) (Group_1); + rRfATInfo.u4FuncData |= (UINT_32) (Group_2 << 8); + rRfATInfo.u4FuncData |= (UINT_32) (band_idx << 16); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetRXVectorIdx rRfATInfo.u4FuncData : 0x%08x\n", + rRfATInfo.u4FuncData); + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set FAGC Rssi Path +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetFAGCRssiPath(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4band_idx = 0; + UINT_32 u4FAGC_Path = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 u4BufLen = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memcpy(&u4band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4band_idx = ntohl(u4band_idx); + memcpy(&u4FAGC_Path, HqaCmdFrame->Data + 4 * 1, 4); + u4FAGC_Path = ntohl(u4FAGC_Path); + + DBGLOG(RFTEST, INFO, " QA_AGENT u4band_idx : %d, u4FAGC_Path : %d\n", u4band_idx, u4FAGC_Path); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_FAGC_RSSI_PATH; + rRfATInfo.u4FuncData = (UINT_32) ((u4band_idx << 16) || (u4FAGC_Path & BITS(0, 15))); + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_CMD_SET2[] = { + /* cmd id start from 0x1200 */ + HQA_ResetTxRxCounter, /* 0x1200 */ + HQA_GetStatistics, /* 0x1201 */ + HQA_GetRxOKData, /* 0x1202 */ + HQA_GetRxOKOther, /* 0x1203 */ + HQA_GetRxAllPktCount, /* 0x1204 */ + HQA_GetTxTransmitted, /* 0x1205 */ + HQA_GetHwCounter, /* 0x1206 */ + HQA_CalibrationOperation, /* 0x1207 */ + HQA_CalibrationBypassExt, /* 0x1208 */ + HQA_SetRXVectorIdx, /* 0x1209 */ + HQA_SetFAGCRssiPath, /* 0x120A */ +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For MAC CR Read. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_MacBbpRegRead(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + UINT_32 u4Offset, u4Value; + INT_32 i4Status; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MCR_RW_STRUCT_T rMcrInfo; + + memcpy(&u4Offset, HqaCmdFrame->Data, 4); + u4Offset = ntohl(u4Offset); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_MacBbpRegRead Offset = 0x%08x\n", u4Offset); + + rMcrInfo.u4McrOffset = u4Offset; + rMcrInfo.u4McrData = 0; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, wlanoidQueryMcrRead, &rMcrInfo, sizeof(rMcrInfo), TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + u4Value = rMcrInfo.u4McrData; + + DBGLOG(RFTEST, INFO, " QA_AGENT Address = 0x%08x, Result = 0x%08x\n", u4Offset, u4Value); + + u4Value = ntohl(u4Value); + memcpy(HqaCmdFrame->Data + 2, &u4Value, 4); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For MAC CR Write. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_MacBbpRegWrite(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + +/* INT_32 i4Ret = 0; */ + UINT_32 u4Offset, u4Value; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MCR_RW_STRUCT_T rMcrInfo; + + memcpy(&u4Offset, HqaCmdFrame->Data, 4); + memcpy(&u4Value, HqaCmdFrame->Data + 4, 4); + + u4Offset = ntohl(u4Offset); + u4Value = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_MacBbpRegWrite Offset = 0x%08x, Value = 0x%08x\n", u4Offset, u4Value); + + rMcrInfo.u4McrOffset = u4Offset; + rMcrInfo.u4McrData = u4Value; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, wlanoidSetMcrWrite, &rMcrInfo, sizeof(rMcrInfo), FALSE, FALSE, TRUE, &u4BufLen); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Read Bulk MAC CR. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_MACBbpRegBulkRead(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + UINT_32 u4Index, u4Offset, u4Value; + UINT_16 u2Len; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MCR_RW_STRUCT_T rMcrInfo; + + memcpy(&u4Offset, HqaCmdFrame->Data, 4); + u4Offset = ntohl(u4Offset); + memcpy(&u2Len, HqaCmdFrame->Data + 4, 2); + u2Len = ntohs(u2Len); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_MACBbpRegBulkRead Offset = 0x%08x, Len = %hu\n", u4Offset, u2Len); + + for (u4Index = 0; u4Index < u2Len; u4Index++) { + rMcrInfo.u4McrOffset = u4Offset + u4Index * 4; + rMcrInfo.u4McrData = 0; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, + wlanoidQueryMcrRead, &rMcrInfo, sizeof(rMcrInfo), TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + u4Value = rMcrInfo.u4McrData; + + DBGLOG(RFTEST, INFO, " QA_AGENT Address = 0x%08x, Result = 0x%08x\n", + u4Offset + u4Index * 4, u4Value); + + u4Value = ntohl(u4Value); + memcpy(HqaCmdFrame->Data + 2 + (u4Index * 4), &u4Value, 4); + } + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + (u2Len * 4), i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Read Bulk RF CR. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_RfRegBulkRead(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + UINT_32 u4Index, u4WfSel, u4Offset, u4Length, u4Value; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MCR_RW_STRUCT_T rMcrInfo; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_RfRegBulkRead\n"); + + memcpy(&u4WfSel, HqaCmdFrame->Data, 4); + u4WfSel = ntohl(u4WfSel); + memcpy(&u4Offset, HqaCmdFrame->Data + 4, 4); + u4Offset = ntohl(u4Offset); + memcpy(&u4Length, HqaCmdFrame->Data + 8, 4); + u4Length = ntohl(u4Length); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_RfRegBulkRead WfSel = %u, Offset = 0x%08x, Length = %u\n", + u4WfSel, u4Offset, u4Length); + + if (u4WfSel == 0) + u4Offset = u4Offset | 0x99900000; + else if (u4WfSel == 1) + u4Offset = u4Offset | 0x99910000; + + + for (u4Index = 0; u4Index < u4Length; u4Index++) { + rMcrInfo.u4McrOffset = u4Offset + u4Index * 4; + rMcrInfo.u4McrData = 0; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, + wlanoidQueryMcrRead, &rMcrInfo, sizeof(rMcrInfo), TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + u4Value = rMcrInfo.u4McrData; + + DBGLOG(RFTEST, INFO, " QA_AGENT Address = 0x%08x, Result = 0x%08x\n", + u4Offset + u4Index * 4, u4Value); + + u4Value = ntohl(u4Value); + memcpy(HqaCmdFrame->Data + 2 + (u4Index * 4), &u4Value, 4); + } + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + (u4Length * 4), i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Write RF CR. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_RfRegBulkWrite(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + UINT_32 u4WfSel, u4Offset, u4Length, u4Value; + INT_32 i4Status; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MCR_RW_STRUCT_T rMcrInfo; + + memcpy(&u4WfSel, HqaCmdFrame->Data, 4); + u4WfSel = ntohl(u4WfSel); + memcpy(&u4Offset, HqaCmdFrame->Data + 4, 4); + u4Offset = ntohl(u4Offset); + memcpy(&u4Length, HqaCmdFrame->Data + 8, 4); + u4Length = ntohl(u4Length); + memcpy(&u4Value, HqaCmdFrame->Data + 12, 4); + u4Value = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, " QA_AGENT WfSel = %u, Offset = 0x%08x, Length = %u, Value = 0x%08x\n", + u4WfSel, u4Offset, u4Length, u4Value); + + if (u4WfSel == 0) + u4Offset = u4Offset | 0x99900000; + else if (u4WfSel == 1) + u4Offset = u4Offset | 0x99910000; + + + rMcrInfo.u4McrOffset = u4Offset; + rMcrInfo.u4McrData = u4Value; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, wlanoidSetMcrWrite, &rMcrInfo, sizeof(rMcrInfo), FALSE, FALSE, TRUE, &u4BufLen); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_ReadEEPROM(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + + UINT_16 Offset; + UINT_16 Len; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + UINT_32 u4BufLen = 0; + UINT_8 u4Index = 0; + UINT_16 u4Value = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_ACCESS_EFUSE_T rAccessEfuseInfo; +#endif + + DBGLOG(INIT, INFO, " QA_AGENT HQA_ReadEEPROM\n"); + + memcpy(&Offset, HqaCmdFrame->Data + 2 * 0, 2); + Offset = ntohs(Offset); + memcpy(&Len, HqaCmdFrame->Data + 2 * 1, 2); + Len = ntohs(Len); + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + kalMemSet(&rAccessEfuseInfo, 0, sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)); + + + rAccessEfuseInfo.u4Address = (Offset / EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfo, + sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T), TRUE, TRUE, TRUE, &u4BufLen); + + u4Index = Offset % EFUSE_BLOCK_SIZE; + if (u4Index <= 14) + u4Value = (prGlueInfo->prAdapter->aucEepromVaule[u4Index]) + | (prGlueInfo->prAdapter->aucEepromVaule[u4Index+1] << 8); + + + /* isVaild = pResult->u4Valid; */ + + if (rStatus == WLAN_STATUS_SUCCESS) { + + DBGLOG(INIT, INFO, " QA_AGENT HQA_ReadEEPROM u4Value = %x\n", u4Value); + + u4Value = ntohl(u4Value); + memcpy(HqaCmdFrame->Data + 2, &u4Value, sizeof(u4Value)); + } +#endif + + ResponseToQA(HqaCmdFrame, prIwReqData, 4, rStatus); + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_WriteEEPROM(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + UINT_16 u4WriteData = 0; + UINT_32 u4BufLen = 0; + UINT_8 u4Index = 0; + UINT_16 Offset; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_ACCESS_EFUSE_T rAccessEfuseInfoRead, rAccessEfuseInfoWrite; + + + memcpy(&Offset, HqaCmdFrame->Data + 2 * 0, 2); + Offset = ntohs(Offset); + memcpy(&u4WriteData, HqaCmdFrame->Data + 2 * 1, 2); + u4WriteData = ntohs(u4WriteData); + + + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* Read */ + DBGLOG(INIT, INFO, " QA_AGENT HQA_ReadEEPROM\n"); + kalMemSet(&rAccessEfuseInfoRead, 0, sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)); + rAccessEfuseInfoRead.u4Address = (Offset / EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfoRead, + sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T), FALSE, FALSE, TRUE, &u4BufLen); + + + /* Write */ + DBGLOG(INIT, INFO, " QA_AGENT HQA_WriteEEPROM\n"); + kalMemSet(&rAccessEfuseInfoWrite, 0, sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)); + u4Index = Offset % EFUSE_BLOCK_SIZE; + prGlueInfo->prAdapter->aucEepromVaule[u4Index] = u4WriteData & 0xff; /* Note: u4WriteData is UINT_16 */ + prGlueInfo->prAdapter->aucEepromVaule[u4Index+1] = u4WriteData >> 8 & 0xff; + + kalMemCopy(rAccessEfuseInfoWrite.aucData, prGlueInfo->prAdapter->aucEepromVaule, 16); + rAccessEfuseInfoWrite.u4Address = (Offset / EFUSE_BLOCK_SIZE)*EFUSE_BLOCK_SIZE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseWrite, + &rAccessEfuseInfoWrite, + sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T), FALSE, FALSE, TRUE, &u4BufLen); +#endif + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_ReadBulkEEPROM(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ +#if 0 + INT_32 i4Ret = 0; + UINT_16 Offset; + UINT_16 Len; +#endif +#if (CFG_EEPROM_PAGE_ACCESS == 1) + PARAM_CUSTOM_ACCESS_EFUSE_T rAccessEfuseInfo; + UINT_32 u4BufLen = 0; + UINT_8 u4Index = 0, u4Loop = 0; + UINT_16 u4Value = 0; + UINT_16 Buffer[EFUSE_BLOCK_SIZE>>1]; + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + kalMemSet(&rAccessEfuseInfo, 0, sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)); +#endif + + return 0; +#if 0 /* currently not used when fix coverity issue */ + memcpy(&Offset, HqaCmdFrame->Data + 2 * 0, 2); + Offset = ntohs(Offset); + memcpy(&Len, HqaCmdFrame->Data + 2 * 1, 2); + Len = ntohs(Len); + + DBGLOG(INIT, INFO, " QA_AGENT HQA_ReadBulkEEPROM Offset : %u, Len : %u\n", Offset, Len); + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + rAccessEfuseInfo.u4Address = (Offset / EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + + DBGLOG(INIT, INFO, " QA_AGENT HQA_ReadBulkEEPROM Address : %d\n", rAccessEfuseInfo.u4Address); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfo, + sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T), TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_FAILURE) + DBGLOG(INIT, INFO, " QA_AGENT HQA_ReadBulkEEPROM kal fail\n"); + + + + for (u4Loop = 0; u4Loop < (EFUSE_BLOCK_SIZE>>1); u4Loop++) { + + u4Index = u4Loop % EFUSE_BLOCK_SIZE; + if (u4Index <= 14) + u4Value = (prGlueInfo->prAdapter->aucEepromVaule[u4Index]) + | (prGlueInfo->prAdapter->aucEepromVaule[u4Index+1] << 8); + + + Buffer[u4Loop] = u4Value; + DBGLOG(INIT, INFO, " QA_AGENT HQA_ReadBulkEEPROM u4Loop=%d u4Value=%x\n", u4Loop, u4Value); + + } + + if (Offset + Len <= EEPROM_SIZE) + kalMemCopy(HqaCmdFrame->Data + 2, (UINT_8 *)Buffer, EFUSE_BLOCK_SIZE); + +#endif + /*kfree(Buffer);*/ + + /* Read from buffer array in driver */ + /* Pass these data to FW also */ + /* for (i = 0 ; i < Len ; i += 2) { + * memcpy(&u2Temp, uacEEPROMImage + Offset + i, 2); + * u2Temp = ntohs(u2Temp); + * memcpy(HqaCmdFrame->Data + 2 + i, &u2Temp, 2); + * } + */ + + /* For SA Buffer Mode Temp Solution + * if (Offset == 0x4A0 && !g_BufferDownload) { + * UINT_16 u2InitAddr = 0x000; + * UINT_32 i = 0, j = 0; + * UINT_32 u4BufLen = 0; + * WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + * P_GLUE_INFO_T prGlueInfo = NULL; + * PARAM_CUSTOM_EFUSE_BUFFER_MODE_T rSetEfuseBufModeInfo; + + * prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + * for (i = 0 ; i < MAX_EEPROM_BUFFER_SIZE/16 ; i++) { + * for (j = 0 ; j < 16 ; j++) { + * rSetEfuseBufModeInfo.aBinContent[j].u2Addr = u2InitAddr; + * rSetEfuseBufModeInfo.aBinContent[j].ucValue = uacEEPROMImage[u2InitAddr]; + * u2InitAddr += 1; + * } + + * rSetEfuseBufModeInfo.ucSourceMode = 1; + * rSetEfuseBufModeInfo.ucCount = EFUSE_CONTENT_SIZE; + * rStatus = kalIoctl(prGlueInfo, + * wlanoidSetEfusBufferMode, + * &rSetEfuseBufModeInfo, + * sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T), FALSE, FALSE, TRUE, &u4BufLen); + * } + + * g_BufferDownload = TRUE; + * } + */ + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + Len, i4Ret); + + return i4Ret; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_WriteBulkEEPROM(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_16 Offset; + UINT_16 Len; + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_ACCESS_EFUSE_T rAccessEfuseInfoRead, rAccessEfuseInfoWrite; + UINT_16 testBuffer1, testBuffer2, testBuffer; + UINT_16 *Buffer = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + UINT_8 u4Index = 0, u4Loop = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + ASSERT(prGlueInfo->prAdapter); + + kalMemSet(&rAccessEfuseInfoRead, 0, sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)); + kalMemSet(&rAccessEfuseInfoWrite, 0, sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)); +#else + UINT_16 ucTemp2; + UINT_16 i = 0; +#endif + + memcpy(&Offset, HqaCmdFrame->Data + 2 * 0, 2); + Offset = ntohs(Offset); + memcpy(&Len, HqaCmdFrame->Data + 2 * 1, 2); + Len = ntohs(Len); +#if (CFG_EEPROM_PAGE_ACCESS == 1) + memcpy(&testBuffer1, HqaCmdFrame->Data + 2 * 2, Len); + testBuffer2 = ntohs(testBuffer1); + testBuffer = ntohs(testBuffer1); +#endif + + DBGLOG(INIT, INFO, " QA_AGENT HQA_WriteBulkEEPROM Offset : %x, Len : %u\n", Offset, Len); + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + Buffer = kmalloc(sizeof(UINT_8)*(EFUSE_BLOCK_SIZE), GFP_KERNEL); + kalMemSet(Buffer, 0, sizeof(UINT_8)*(EFUSE_BLOCK_SIZE)); + + kalMemCopy((UINT_8 *)Buffer, (UINT_8 *)HqaCmdFrame->Data + 4, Len); + + for (u4Loop = 0; u4Loop < (EFUSE_BLOCK_SIZE>>1); u4Loop++) { + + DBGLOG(INIT, INFO, " QA_AGENT HQA_WriteBulkEEPROM u4Loop=%d u4Value=%x\n", + u4Loop, Buffer[u4Loop]); + } + + + /* Read */ + DBGLOG(INIT, INFO, " QA_AGENT HQA_WriteBulkEEPROM Read\n"); + kalMemSet(&rAccessEfuseInfoRead, 0, sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)); + rAccessEfuseInfoRead.u4Address = (Offset / EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfoRead, + sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T), TRUE, TRUE, TRUE, &u4BufLen); + + + /* Write */ + kalMemSet(&rAccessEfuseInfoWrite, 0, sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)); + u4Index = Offset % EFUSE_BLOCK_SIZE; + DBGLOG(INIT, INFO, " QA_AGENT HQA_WriteBulkEEPROM Write, u4Index=%x, testBuffer=%x\n", + u4Index, testBuffer); + + DBGLOG(INIT, INFO, " Buffer[0]=%x, Buffer[0]&0xff=%x\n", Buffer[0], Buffer[0]&0xff); + DBGLOG(INIT, INFO, " Buffer[0] >> 8 & 0xff=%x\n", Buffer[0] >> 8 & 0xff); + + + prGlueInfo->prAdapter->aucEepromVaule[u4Index] = testBuffer; + prGlueInfo->prAdapter->aucEepromVaule[u4Index+1] = testBuffer >> 8 & 0xff; + + kalMemCopy(rAccessEfuseInfoWrite.aucData, prGlueInfo->prAdapter->aucEepromVaule, 16); + + for (u4Loop = 0; u4Loop < (EFUSE_BLOCK_SIZE); u4Loop++) { + DBGLOG(INIT, INFO, " QA_AGENT aucEepromVaule u4Loop=%d u4Value=%x\n", + u4Loop, prGlueInfo->prAdapter->aucEepromVaule[u4Loop]); + DBGLOG(INIT, INFO, " QA_AGENT rAccessEfuseInfoWrite.aucData u4Loop=%d u4Value=%x\n", + u4Loop, rAccessEfuseInfoWrite.aucData[u4Loop]); + } + + rAccessEfuseInfoWrite.u4Address = (Offset / EFUSE_BLOCK_SIZE)*EFUSE_BLOCK_SIZE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseWrite, + &rAccessEfuseInfoWrite, + sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T), FALSE, TRUE, TRUE, &u4BufLen); + kfree(Buffer); +#else + + if (Len == 2) { + memcpy(&ucTemp2, HqaCmdFrame->Data + 2 * 2, 2); + ucTemp2 = ntohs(ucTemp2); + memcpy(uacEEPROMImage + Offset, &ucTemp2, Len); + } else { + for (i = 0 ; i < 8 ; i++) { + memcpy(&ucTemp2, HqaCmdFrame->Data + 2 * 2 + 2*i, 2); + ucTemp2 = ntohs(ucTemp2); + memcpy(uacEEPROMImage + Offset + 2*i, &ucTemp2, 2); + } + + if (!g_BufferDownload) { + UINT_16 u2InitAddr = Offset; + UINT_32 j = 0; + UINT_32 u4BufLen = 0; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_EFUSE_BUFFER_MODE_T rSetEfuseBufModeInfo; + PARAM_CUSTOM_EFUSE_BUFFER_MODE_1_T rSetEfuseBufModeInfo_1; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + kalMemZero(&rSetEfuseBufModeInfo, sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T)); + kalMemZero(&rSetEfuseBufModeInfo_1, sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_1_T)); + + if (prGlueInfo->prAdapter->rWifiVar.ucEfuseBufferModeCal == TRUE) { /* structure for MT7668 */ + + for (j = 0 ; j < 16 ; j++) { + /* rSetEfuseBufModeInfo.aBinContent[j].u2Addr = u2InitAddr; */ + /* rSetEfuseBufModeInfo.aBinContent[j].ucValue = uacEEPROMImage[u2InitAddr]; */ + + rSetEfuseBufModeInfo_1.aBinContent[j] = uacEEPROMImage[u2InitAddr]; + u2InitAddr += 1; + } + + rSetEfuseBufModeInfo_1.ucSourceMode = 1; + rSetEfuseBufModeInfo_1.ucCount = (UINT_8)EFUSE_CONTENT_SIZE_1; + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEfusBufferMode, + &rSetEfuseBufModeInfo_1, + sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_1_T), + FALSE, FALSE, TRUE, &u4BufLen); + } else { + + for (j = 0 ; j < 16 ; j++) { + rSetEfuseBufModeInfo.aBinContent[j].u2Addr = u2InitAddr; + rSetEfuseBufModeInfo.aBinContent[j].ucValue = uacEEPROMImage[u2InitAddr]; + u2InitAddr += 1; + } + + rSetEfuseBufModeInfo.ucSourceMode = 1; + rSetEfuseBufModeInfo.ucCount = EFUSE_CONTENT_SIZE; + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEfusBufferMode, + &rSetEfuseBufModeInfo, + sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T), + FALSE, FALSE, TRUE, &u4BufLen); + } + + if (Offset == 0x4A0) + g_BufferDownload = TRUE; + } + } +#endif + + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + Len, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_CheckEfuseMode(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 Value = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_CheckEfuseMode\n"); + + /* Value: 0:eeprom mode, 1:eFuse mode */ + Value = ntohl(Value); + memcpy(HqaCmdFrame->Data + 2, &(Value), sizeof(Value)); + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetFreeEfuseBlock(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + + INT_32 i4Ret = 0; + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + PARAM_CUSTOM_EFUSE_FREE_BLOCK_T rEfuseFreeBlock; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; +#endif + + DBGLOG(INIT, INFO, " QA_AGENT HQA_GetFreeEfuseBlock\n"); + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + kalMemSet(&rEfuseFreeBlock, 0, sizeof(PARAM_CUSTOM_EFUSE_FREE_BLOCK_T)); + + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryEfuseFreeBlock, + &rEfuseFreeBlock, + sizeof(PARAM_CUSTOM_EFUSE_FREE_BLOCK_T), FALSE, FALSE, TRUE, &u4BufLen); + + kalMemCopy(HqaCmdFrame->Data + 2, &(prGlueInfo->prAdapter->u4FreeBlockNum), 4); +#endif + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetEfuseBlockNr(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_GetEfuseBlockNr\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_WriteEFuseFromBuffer(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_WriteEFuseFromBuffer\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetTxPower(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Channel = 0, u4Band = 0, u4Ch_Band = 0; +/* UINT_32 u4EfuseAddr = 0, u4Power = 0; */ + + memcpy(&u4Channel, HqaCmdFrame->Data + 4 * 0, 4); + u4Channel = ntohl(u4Channel); + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 1, 4); + u4Band = ntohl(u4Band); + memcpy(&u4Ch_Band, HqaCmdFrame->Data + 4 * 2, 4); + u4Ch_Band = ntohl(u4Ch_Band); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_GetTxPower u4Channel : %u, u4Band : %u, u4Ch_Band : %u\n", + u4Channel, u4Band, u4Ch_Band); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetCfgOnOff(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 Type, Enable, Band; + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 u4BufLen = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memcpy(&Type, HqaCmdFrame->Data + 4 * 0, 4); + Type = ntohl(Type); + memcpy(&Enable, HqaCmdFrame->Data + 4 * 1, 4); + Enable = ntohl(Enable); + memcpy(&Band, HqaCmdFrame->Data + 4 * 2, 4); + Band = ntohl(Band); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetCfgOnOff Type : %u, Enable : %u, Band : %u\n", Type, Enable, Band); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TSSI; + rRfATInfo.u4FuncData = 0; + + if (Band == 0 && Enable == 1) + rRfATInfo.u4FuncData |= BIT(0); + else if (Band == 1 && Enable == 1) + rRfATInfo.u4FuncData |= BIT(1); + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetFreqOffset(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4FreqOffset = 0; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_GET_FREQ_OFFSET; + rRfATInfo.u4FuncData = 0; + + i4Ret = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, &rRfATInfo, sizeof(rRfATInfo), TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Ret == 0) { + u4FreqOffset = rRfATInfo.u4FuncData; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_GetFreqOffset u4FreqOffset = %d\n", u4FreqOffset); + + u4FreqOffset = ntohl(u4FreqOffset); + memcpy(HqaCmdFrame->Data + 2, &u4FreqOffset, sizeof(u4FreqOffset)); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_DBDCTXTone(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + INT_32 i4BandIdx = 0, i4Control = 0, i4AntIndex = 0, i4ToneType = 0, i4ToneFreq = 0; + INT_32 i4DcOffsetI = 0, i4DcOffsetQ = 0, i4Band = 0, i4RF_Power = 0, i4Digi_Power = 0; + + memcpy(&i4BandIdx, HqaCmdFrame->Data + 4 * 0, 4); /* DBDC Band Index : Band0, Band1 */ + i4BandIdx = ntohl(i4BandIdx); + memcpy(&i4Control, HqaCmdFrame->Data + 4 * 1, 4); /* Control TX Tone Start and Stop */ + i4Control = ntohl(i4Control); + memcpy(&i4AntIndex, HqaCmdFrame->Data + 4 * 2, 4); /* Select TX Antenna */ + i4AntIndex = ntohl(i4AntIndex); + memcpy(&i4ToneType, HqaCmdFrame->Data + 4 * 3, 4); /* ToneType : Single or Two */ + i4ToneType = ntohl(i4ToneType); + memcpy(&i4ToneFreq, HqaCmdFrame->Data + 4 * 4, 4); /* ToneFreq: DC/5M/10M/20M/40M */ + i4ToneFreq = ntohl(i4ToneFreq); + memcpy(&i4DcOffsetI, HqaCmdFrame->Data + 4 * 5, 4); /* DC Offset I : -512~1535 */ + i4DcOffsetI = ntohl(i4DcOffsetI); + memcpy(&i4DcOffsetQ, HqaCmdFrame->Data + 4 * 6, 4); /* DC Offset Q : -512~1535 */ + i4DcOffsetQ = ntohl(i4DcOffsetQ); + memcpy(&i4Band, HqaCmdFrame->Data + 4 * 7, 4); /* Band : 2.4G/5G */ + i4Band = ntohl(i4Band); + memcpy(&i4RF_Power, HqaCmdFrame->Data + 4 * 8, 4); /* RF_Power: (1db) 0~15 */ + i4RF_Power = ntohl(i4RF_Power); + memcpy(&i4Digi_Power, HqaCmdFrame->Data + 4 * 9, 4); /* Digi_Power: (0.25db) -32~31 */ + i4Digi_Power = ntohl(i4Digi_Power); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_DBDCTXTone BandIdx = 0x%08x\n", i4BandIdx); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_DBDCTXTone Control = 0x%08x\n", i4Control); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_DBDCTXTone AntIndex = 0x%08x\n", i4AntIndex); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_DBDCTXTone ToneType = 0x%08x\n", i4ToneType); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_DBDCTXTone ToneFreq = 0x%08x\n", i4ToneFreq); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_DBDCTXTone DcOffsetI = 0x%08x\n", i4DcOffsetI); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_DBDCTXTone DcOffsetQ = 0x%08x\n", i4DcOffsetQ); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_DBDCTXTone Band = 0x%08x\n", i4Band); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_DBDCTXTone RF_Power = 0x%08x\n", i4RF_Power); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_DBDCTXTone Digi_Power = 0x%08x\n", i4Digi_Power); + + /* + * Select TX Antenna + * RF_Power: (1db) 0~15 + * Digi_Power: (0.25db) -32~31 + */ + MT_ATESetDBDCTxTonePower(prNetDev, i4AntIndex, i4RF_Power, i4Digi_Power); + + /* DBDC Band Index : Band0, Band1 */ + MT_ATESetDBDCBandIndex(prNetDev, i4BandIdx); + + if (i4Control) { + /* Band : 2.4G/5G */ + MT_ATESetBand(prNetDev, i4Band); + + /* ToneType : Single or Two */ + MT_ATESetTxToneType(prNetDev, i4ToneType); + + /* ToneFreq: DC/5M/10M/20M/40M */ + MT_ATESetTxToneBW(prNetDev, i4ToneFreq); + + /* DC Offset I, DC Offset Q */ + MT_ATESetTxToneDCOffset(prNetDev, i4DcOffsetI, i4DcOffsetQ); + + /* Control TX Tone Start and Stop */ + MT_ATEDBDCTxTone(prNetDev, i4Control); + } else { + /* Control TX Tone Start and Stop */ + MT_ATEDBDCTxTone(prNetDev, i4Control); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_DBDCContinuousTX(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Band = 0, u4Control = 0, u4AntMask = 0, u4Phymode = 0, u4BW = 0; + UINT_32 u4Pri_Ch = 0, u4Rate = 0, u4Central_Ch = 0, u4TxfdMode = 0, u4Freq = 0; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 0, 4); + u4Band = ntohl(u4Band); + memcpy(&u4Control, HqaCmdFrame->Data + 4 * 1, 4); + u4Control = ntohl(u4Control); + memcpy(&u4AntMask, HqaCmdFrame->Data + 4 * 2, 4); + u4AntMask = ntohl(u4AntMask); + memcpy(&u4Phymode, HqaCmdFrame->Data + 4 * 3, 4); + u4Phymode = ntohl(u4Phymode); + memcpy(&u4BW, HqaCmdFrame->Data + 4 * 4, 4); + u4BW = ntohl(u4BW); + memcpy(&u4Pri_Ch, HqaCmdFrame->Data + 4 * 5, 4); + u4Pri_Ch = ntohl(u4Pri_Ch); + memcpy(&u4Rate, HqaCmdFrame->Data + 4 * 6, 4); + u4Rate = ntohl(u4Rate); + memcpy(&u4Central_Ch, HqaCmdFrame->Data + 4 * 7, 4); + u4Central_Ch = ntohl(u4Central_Ch); + memcpy(&u4TxfdMode, HqaCmdFrame->Data + 4 * 8, 4); + u4TxfdMode = ntohl(u4TxfdMode); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_DBDCContinuousTX u4Band : %d\n", u4Band); /* ok */ + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_DBDCContinuousTX u4Control : %d\n", u4Control); /* ok */ + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_DBDCContinuousTX u4AntMask : %d\n", u4AntMask); /* ok */ + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_DBDCContinuousTX u4Phymode : %d\n", u4Phymode); /* ok */ + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_DBDCContinuousTX u4BW : %d\n", u4BW); /* ok */ + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_DBDCContinuousTX u4Pri_Ch : %d\n", u4Pri_Ch); /* ok */ + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_DBDCContinuousTX u4Rate : %d\n", u4Rate); /* ok */ + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_DBDCContinuousTX u4Central_Ch : %d\n", u4Central_Ch); /* ok */ + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_DBDCContinuousTX u4TxfdMode : %d\n", u4TxfdMode); /* ok */ + + if (u4Control) { + MT_ATESetDBDCBandIndex(prNetDev, u4Band); + u4Freq = nicChannelNum2Freq(u4Central_Ch); + MT_ATESetChannel(prNetDev, 0, u4Freq); + MT_ATEPrimarySetting(prNetDev, u4Pri_Ch); + + if (u4Phymode == 1) { + u4Phymode = 0; + u4Rate += 4; + } else if ((u4Phymode == 0) && ((u4Rate == 9) || (u4Rate == 10) || (u4Rate == 11))) + u4Phymode = 1; + MT_ATESetPreamble(prNetDev, u4Phymode); + + if (u4Phymode == 0) { + u4Rate |= 0x00000000; + + DBGLOG(RFTEST, INFO, " QA_AGENT CCK/OFDM (normal preamble) rate : %d\n", u4Rate); + + MT_ATESetRate(prNetDev, u4Rate); + } else if (u4Phymode == 1) { + if (u4Rate == 9) + u4Rate = 1; + else if (u4Rate == 10) + u4Rate = 2; + else if (u4Rate == 11) + u4Rate = 3; + u4Rate |= 0x00000000; + + DBGLOG(RFTEST, INFO, " QA_AGENT CCK (short preamble) rate : %d\n", u4Rate); + + MT_ATESetRate(prNetDev, u4Rate); + } else if (u4Phymode >= 2 && u4Phymode <= 4) { + u4Rate |= 0x80000000; + + DBGLOG(RFTEST, INFO, " QA_AGENT HT/VHT rate : %d\n", u4Rate); + + MT_ATESetRate(prNetDev, u4Rate); + } + + MT_ATESetSystemBW(prNetDev, u4BW); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_CW_MODE; + rRfATInfo.u4FuncData = u4TxfdMode; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ANTMASK; + rRfATInfo.u4FuncData = u4AntMask; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_CW; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + } else { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_STOPTEST; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetRXFilterPktLen(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Band = 0, u4Control = 0, u4RxPktlen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 u4BufLen = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 0, 4); + u4Band = ntohl(u4Band); + memcpy(&u4Control, HqaCmdFrame->Data + 4 * 1, 4); + u4Control = ntohl(u4Control); + memcpy(&u4RxPktlen, HqaCmdFrame->Data + 4 * 2, 4); + u4RxPktlen = ntohl(u4RxPktlen); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetRXFilterPktLen Band : %d\n", u4Band); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetRXFilterPktLen Control : %d\n", u4Control); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetRXFilterPktLen RxPktlen : %d\n", u4RxPktlen); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_RX_FILTER_PKT_LEN; + rRfATInfo.u4FuncData = (UINT_32) (u4RxPktlen & BITS(0, 23)); + rRfATInfo.u4FuncData |= (UINT_32) (u4Band << 24); + + if (u4Control == 1) + rRfATInfo.u4FuncData |= BIT(30); + else + rRfATInfo.u4FuncData &= ~BIT(30); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetRXFilterPktLen rRfATInfo.u4FuncData : 0x%08x\n", + rRfATInfo.u4FuncData); + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetTXInfo(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + UINT_32 u4Txed_band0 = 0; + UINT_32 u4Txed_band1 = 0; + INT_32 i4Status; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_GetTXInfo\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_TXED_COUNT; + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, &rRfATInfo, sizeof(rRfATInfo), TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + u4Txed_band0 = rRfATInfo.u4FuncData; + + DBGLOG(RFTEST, INFO, " QA_AGENT u4Txed_band0 packet count = %d\n", u4Txed_band0); + + u4Txed_band0 = ntohl(u4Txed_band0); + memcpy(HqaCmdFrame->Data + 2, &u4Txed_band0, sizeof(u4Txed_band0)); + } + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_TXED_COUNT; + rRfATInfo.u4FuncIndex |= BIT(8); + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, &rRfATInfo, sizeof(rRfATInfo), TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + u4Txed_band1 = rRfATInfo.u4FuncData; + + DBGLOG(RFTEST, INFO, " QA_AGENT u4Txed_band1 packet count = %d\n", u4Txed_band1); + + u4Txed_band1 = ntohl(u4Txed_band1); + memcpy(HqaCmdFrame->Data + 2 + 4, &u4Txed_band1, sizeof(u4Txed_band1)); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + sizeof(u4Txed_band0) + sizeof(u4Txed_band1), i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetCfgOnOff(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_GetCfgOnOff\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_CMD_SET3[] = { + /* cmd id start from 0x1300 */ + HQA_MacBbpRegRead, /* 0x1300 */ + HQA_MacBbpRegWrite, /* 0x1301 */ + HQA_MACBbpRegBulkRead, /* 0x1302 */ + HQA_RfRegBulkRead, /* 0x1303 */ + HQA_RfRegBulkWrite, /* 0x1304 */ + HQA_ReadEEPROM, /* 0x1305 */ + HQA_WriteEEPROM, /* 0x1306 */ + HQA_ReadBulkEEPROM, /* 0x1307 */ + HQA_WriteBulkEEPROM, /* 0x1308 */ + HQA_CheckEfuseMode, /* 0x1309 */ + HQA_GetFreeEfuseBlock, /* 0x130A */ + HQA_GetEfuseBlockNr, /* 0x130B */ + HQA_WriteEFuseFromBuffer, /* 0x130C */ + HQA_GetTxPower, /* 0x130D */ + HQA_SetCfgOnOff, /* 0x130E */ + HQA_GetFreqOffset, /* 0x130F */ + HQA_DBDCTXTone, /* 0x1310 */ + HQA_DBDCContinuousTX, /* 0x1311 */ + HQA_SetRXFilterPktLen, /* 0x1312 */ + HQA_GetTXInfo, /* 0x1313 */ + HQA_GetCfgOnOff, /* 0x1314 */ +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_ReadTempReferenceValue(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_ReadTempReferenceValue\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Get Thermal Value. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetThermalValue(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + UINT_32 u4Value; + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_TEMP_SENSOR; + rRfATInfo.u4FuncData = 0; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, &rRfATInfo, sizeof(rRfATInfo), TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + u4Value = rRfATInfo.u4FuncData; + /*u4Value = u4Value >> 16;*/ + u4Value = u4Value & 0xff; + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_GetThermalValue Value = %d\n", u4Value); + + u4Value = ntohl(u4Value); + memcpy(HqaCmdFrame->Data + 2, &u4Value, 4); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetSideBandOption(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetSideBandOption\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_CMD_SET4[] = { + /* cmd id start from 0x1400 */ + HQA_ReadTempReferenceValue, /* 0x1400 */ + HQA_GetThermalValue, /* 0x1401 */ + HQA_SetSideBandOption, /* 0x1402 */ +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetFWInfo(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_GetFWInfo\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_StartContinousTx(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_StartContinousTx\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetSTBC(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetSTBC\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set short GI. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetShortGI(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4ShortGi; + + memcpy(&u4ShortGi, HqaCmdFrame->Data, 4); + u4ShortGi = ntohl(u4ShortGi); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetShortGI u4ShortGi = %d\n", u4ShortGi); + + i4Ret = MT_ATESetTxGi(prNetDev, u4ShortGi); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetDPD(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetDPD\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Get Rx Statistics. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetRxStatisticsAll(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_ACCESS_RX_STAT rRxStatisticsTest; + + /* memset(&g_HqaRxStat, 0, sizeof(PARAM_RX_STAT_T)); */ + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_GetRxStatisticsAll\n"); + + rRxStatisticsTest.u4SeqNum = u4RxStatSeqNum; + rRxStatisticsTest.u4TotalNum = HQA_RX_STATISTIC_NUM + 6; + + i4Ret = kalIoctl(prGlueInfo, + wlanoidQueryRxStatistics, + &rRxStatisticsTest, sizeof(rRxStatisticsTest), TRUE, TRUE, TRUE, &u4BufLen); + + /* ASSERT(rRxStatisticsTest.u4SeqNum == u4RxStatSeqNum); */ + + u4RxStatSeqNum++; + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.ACIHitLower : 0x%08x\n", g_HqaRxStat.ACIHitLower); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.ACIHitUpper : 0x%08x\n", g_HqaRxStat.ACIHitUpper); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.AllFCSErr0 : 0x%08x\n", g_HqaRxStat.AllFCSErr0); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.AllFCSErr1 : 0x%08x\n", g_HqaRxStat.AllFCSErr1); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.AllLengthMismatchCount_B0 : 0x%08x\n", + g_HqaRxStat.AllLengthMismatchCount_B0); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.AllLengthMismatchCount_B1 : 0x%08x\n", + g_HqaRxStat.AllLengthMismatchCount_B1); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.AllMacMdrdy0 : 0x%08x\n", g_HqaRxStat.AllMacMdrdy0); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.AllMacMdrdy1 : 0x%08x\n", g_HqaRxStat.AllMacMdrdy1); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.CCK_FCS_Err_Band1 : 0x%08x\n", g_HqaRxStat.CCK_FCS_Err_Band1); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.CCK_PD : 0x%08x\n", g_HqaRxStat.CCK_PD); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.CCK_PD_Band1 : 0x%08x\n", g_HqaRxStat.CCK_PD_Band1); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.CCK_SFD_Err : 0x%08x\n", g_HqaRxStat.CCK_SFD_Err); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.CCK_SFD_Err_Band1 : 0x%08x\n", g_HqaRxStat.CCK_SFD_Err_Band1); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.CCK_SIG_Err : 0x%08x\n", g_HqaRxStat.CCK_SIG_Err); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.CCK_SIG_Err_Band1 : 0x%08x\n", g_HqaRxStat.CCK_SIG_Err_Band1); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.DriverRxCount : 0x%08x\n", g_HqaRxStat.DriverRxCount); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.DriverRxCount1 : 0x%08x\n", g_HqaRxStat.DriverRxCount1); + DBGLOG(RFTEST, TRACE, " FAGCRssiIBR0:0x%08x, FAGCRssiIBR0:0x%08x, FAGCRssiIBR0:0x%08x, FAGCRssiIBR0:0x%08x\n", + g_HqaRxStat.FAGCRssiIBR0, g_HqaRxStat.FAGCRssiIBR1, g_HqaRxStat.FAGCRssiIBR2, g_HqaRxStat.FAGCRssiIBR3); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.FAGCRssiIBR1 : 0x%08x, FAGCRssiIBR2 : 0x%08x, FAGCRssiIBR3 : 0x%08x\n", + g_HqaRxStat.FAGCRssiIBR1, g_HqaRxStat.FAGCRssiIBR2, g_HqaRxStat.FAGCRssiIBR3); + DBGLOG(RFTEST, TRACE, + "FAGCRssiWBR0 : 0x%08x, FAGCRssiWBR1 : 0x%08x, FAGCRssiWBR2 : 0x%08x, FAGCRssiWBR3 : 0x%08x\n", + g_HqaRxStat.FAGCRssiWBR0, g_HqaRxStat.FAGCRssiWBR1, g_HqaRxStat.FAGCRssiWBR2, g_HqaRxStat.FAGCRssiWBR3); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.FCSErr_CCK : 0x%08x\n", g_HqaRxStat.FCSErr_CCK); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.FCSErr_OFDM : 0x%08x\n", g_HqaRxStat.FCSErr_OFDM); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.FreqOffsetFromRX : 0x%08x\n", g_HqaRxStat.FreqOffsetFromRX); + DBGLOG(RFTEST, TRACE, "IB_RSSI0 : 0x%08x, IB_RSSI1 : 0x%08x\n", g_HqaRxStat.IB_RSSI0, g_HqaRxStat.IB_RSSI1); + DBGLOG(RFTEST, TRACE, "InstRssiIBR0:0x%08x, InstRssiIBR1:0x%08x, InstRssiIBR2:0x%08x, InstRssiIBR3:0x%08x\n", + g_HqaRxStat.InstRssiIBR0, g_HqaRxStat.InstRssiIBR1, g_HqaRxStat.InstRssiIBR2, g_HqaRxStat.InstRssiIBR3); + + DBGLOG(RFTEST, TRACE, "InstRssiWBR0:0x%08x, InstRssiWBR1:0x%08x, InstRssiWBR2:0x%08x, InstRssiWBR3:0x%08x\n", + g_HqaRxStat.InstRssiWBR0, g_HqaRxStat.InstRssiWBR1, g_HqaRxStat.InstRssiWBR2, g_HqaRxStat.InstRssiWBR3); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.LengthMismatchCount_B0 : 0x%08x\n", g_HqaRxStat.LengthMismatchCount_B0); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.LengthMismatchCount_B1 : 0x%08x\n", g_HqaRxStat.LengthMismatchCount_B1); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.MAC_FCS_Err : 0x%08x\n", g_HqaRxStat.MAC_FCS_Err); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.MAC_FCS_Err1 : 0x%08x\n", g_HqaRxStat.MAC_FCS_Err1); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.MAC_Mdrdy : 0x%08x\n", g_HqaRxStat.MAC_Mdrdy); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.MAC_Mdrdy1 : 0x%08x\n", g_HqaRxStat.MAC_Mdrdy1); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.MRURxCount : 0x%08x\n", g_HqaRxStat.MRURxCount); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.Noise_Floor : 0x%08x\n", g_HqaRxStat.Noise_Floor); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.OFDM_FCS_Err_Band1 : 0x%08x\n", g_HqaRxStat.OFDM_FCS_Err_Band1); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.OFDM_PD : 0x%08x\n", g_HqaRxStat.OFDM_PD); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.OFDM_PD_Band1 : 0x%08x\n", g_HqaRxStat.OFDM_PD_Band1); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.OFDM_SIG_Err : 0x%08x\n", g_HqaRxStat.OFDM_SIG_Err); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.OFDM_SIG_Err_Band1 : 0x%08x\n", g_HqaRxStat.OFDM_SIG_Err_Band1); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.OFDM_TAG_Err : 0x%08x\n", g_HqaRxStat.OFDM_TAG_Err); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.OFDM_TAG_Err_Band1 : 0x%08x\n", g_HqaRxStat.OFDM_TAG_Err_Band1); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.OutOfResource : 0x%08x\n", g_HqaRxStat.OutOfResource); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.OutOfResource1 : 0x%08x\n", g_HqaRxStat.OutOfResource1); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.PER0 : 0x%08x\n", g_HqaRxStat.PER0); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.PER1 : 0x%08x\n", g_HqaRxStat.PER1); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.PhyMdrdyCCK : 0x%08x\n", g_HqaRxStat.PhyMdrdyCCK); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.PhyMdrdyOFDM : 0x%08x\n", g_HqaRxStat.PhyMdrdyOFDM); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.PHY_CCK_MDRDY_Band1 : 0x%08x\n", g_HqaRxStat.PHY_CCK_MDRDY_Band1); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.PHY_Mdrdy : 0x%08x\n", g_HqaRxStat.PHY_Mdrdy); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.PHY_OFDM_MDRDY_Band1 : 0x%08x\n", g_HqaRxStat.PHY_OFDM_MDRDY_Band1); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.RCPI0 : 0x%08x, RCPI1 : 0x%08x, RCPI2 : 0x%08x, RCPI3 : 0x%08x\n", + g_HqaRxStat.RCPI0, g_HqaRxStat.RCPI1, g_HqaRxStat.RCPI2, g_HqaRxStat.RCPI3); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.RSSI0 : 0x%08x, RSSI1 : 0x%08x, RSSI2 : 0x%08x, RSSI3 : 0x%08x\n", + g_HqaRxStat.RSSI0, g_HqaRxStat.RSSI1, g_HqaRxStat.RSSI2, g_HqaRxStat.RSSI3); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.RXOK0 : 0x%08x, RXOK1 : 0x%08x\n", g_HqaRxStat.RXOK0, g_HqaRxStat.RXOK1); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.RXVRSSI : 0x%08x\n", g_HqaRxStat.RXVRSSI); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.SIGMCS : 0x%08x\n", g_HqaRxStat.SIGMCS); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.SINR : 0x%08x\n", g_HqaRxStat.SINR); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.SNR0 : 0x%08x, SNR1 : 0x%08x, SNR2 : 0x%08x, SNR3 : 0x%08x\n", + g_HqaRxStat.SNR0, g_HqaRxStat.SNR1, g_HqaRxStat.SNR2, g_HqaRxStat.SNR3); + DBGLOG(RFTEST, TRACE, " g_HqaRxStat.WB_RSSI0 : 0x%08x, WB_RSSI1 : 0x%08x\n", + g_HqaRxStat.WB_RSSI0, g_HqaRxStat.WB_RSSI1); + + memcpy(HqaCmdFrame->Data + 2, &(g_HqaRxStat), sizeof(PARAM_RX_STAT_T)); + ResponseToQA(HqaCmdFrame, prIwReqData, (2 + sizeof(PARAM_RX_STAT_T)), i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_StartContiTxTone(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_StartContiTxTone\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_StopContiTxTone(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_StopContiTxTone\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_CalibrationTestMode(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Mode = 0; + UINT_32 u4IcapLen = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_CalibrationTestMode\n"); + + memcpy(&u4Mode, HqaCmdFrame->Data + 4 * 0, 4); + u4Mode = ntohl(u4Mode); + memcpy(&u4IcapLen, HqaCmdFrame->Data + 4 * 1, 4); + u4IcapLen = ntohl(u4IcapLen); + + if (u4Mode == 2) + i4Ret = MT_ICAPStart(prNetDev, "ICAPSTART"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_DoCalibrationTestItem(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Status = 0; + UINT_32 u4Item = 0; + UINT_32 u4Band_idx = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 u4BufLen = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memcpy(&u4Item, HqaCmdFrame->Data, 4); + u4Item = ntohl(u4Item); + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_DoCalibrationTestItem item : 0x%08x\n", u4Item); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_DoCalibrationTestItem band_idx : %d\n", u4Band_idx); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_RECAL_CAL_STEP; + rRfATInfo.u4FuncData = u4Item; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_eFusePhysicalWrite(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_eFusePhysicalWrite\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_eFusePhysicalRead(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_eFusePhysicalRead\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_eFuseLogicalRead(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_eFuseLogicalRead\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_eFuseLogicalWrite(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_eFuseLogicalWrite\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_TMRSetting(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Setting; + UINT_32 u4Version; + UINT_32 u4MPThres; + UINT_32 u4MPIter; + + memcpy(&u4Setting, HqaCmdFrame->Data + 4 * 0, 4); + u4Setting = ntohl(u4Setting); + memcpy(&u4Version, HqaCmdFrame->Data + 4 * 1, 4); + u4Version = ntohl(u4Version); + memcpy(&u4MPThres, HqaCmdFrame->Data + 4 * 2, 4); + u4MPThres = ntohl(u4MPThres); + memcpy(&u4MPIter, HqaCmdFrame->Data + 4 * 3, 4); + u4MPIter = ntohl(u4MPIter); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_TMRSetting u4Setting : %d\n", u4Setting); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_TMRSetting u4Version : %d\n", u4Version); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_TMRSetting u4MPThres : %d\n", u4MPThres); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_TMRSetting u4MPIter : %d\n", u4MPIter); + + i4Ret = MT_ATE_TMRSetting(prNetDev, u4Setting, u4Version, u4MPThres, u4MPIter); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetRxSNR(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_GetRxSNR\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_WriteBufferDone(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; +/* UINT_16 u2InitAddr = 0x000; */ + UINT_32 Value; +/* UINT_32 i = 0, j = 0; + * UINT_32 u4BufLen = 0; + */ + +/* WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; */ + P_GLUE_INFO_T prGlueInfo = NULL; +/* PARAM_CUSTOM_EFUSE_BUFFER_MODE_T rSetEfuseBufModeInfo; */ + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memcpy(&Value, HqaCmdFrame->Data + 4 * 0, 4); + Value = ntohl(Value); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_WriteBufferDone Value : %d\n", Value); + + u4EepromMode = Value; + +#if 0 + for (i = 0 ; i < MAX_EEPROM_BUFFER_SIZE/16 ; i++) { + for (j = 0 ; j < 16 ; j++) { + rSetEfuseBufModeInfo.aBinContent[j].u2Addr = u2InitAddr; + rSetEfuseBufModeInfo.aBinContent[j].ucValue = uacEEPROMImage[u2InitAddr]; + DBGLOG(RFTEST, INFO, "u2Addr = %x\n", rSetEfuseBufModeInfo.aBinContent[j].u2Addr); + DBGLOG(RFTEST, INFO, "ucValue = %x\n", rSetEfuseBufModeInfo.aBinContent[j].ucValue); + u2InitAddr += 1; + } + + rSetEfuseBufModeInfo.ucSourceMode = 1; + rSetEfuseBufModeInfo.ucCount = EFUSE_CONTENT_SIZE; + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEfusBufferMode, + &rSetEfuseBufModeInfo, + sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T), FALSE, FALSE, TRUE, &u4BufLen); + } +#endif + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_FFT(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_FFT\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetTxTonePower(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetTxTonePower\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetChipID(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 ChipId; +/* P_GLUE_INFO_T prGlueInfo = NULL; + * UINT_32 u4BufLen = 0; + * PARAM_CUSTOM_MCR_RW_STRUCT_T rMcrInfo; + */ + +#if 1 + ChipId = 0x00006631; +#else + /* Workaround for QA tool chip ID check */ +#if defined(_HIF_USB) + rMcrInfo.u4McrOffset = TOP_HCR; +#endif + rMcrInfo.u4McrData = 0; + rMcrInfo.ucMcrAntIdx = 0; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + i4Ret = kalIoctl(prGlueInfo, wlanoidQueryMcrRead, &rMcrInfo, sizeof(rMcrInfo), TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Ret == 0) + ChipId = rMcrInfo.u4McrData; +#endif + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_GetChipID ChipId = 0x%08x\n", ChipId); + + ChipId = ntohl(ChipId); + memcpy(HqaCmdFrame->Data + 2, &ChipId, 4); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_MPSSetSeqData(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 *mps_setting = NULL; + UINT_32 u4Band_idx = 0; + UINT_32 u4Offset = 0; + UINT_32 u4Len = 0; + UINT_32 i = 0; + UINT_32 u4Value = 0; + UINT_32 u4Mode = 0; + UINT_32 u4TxPath = 0; + UINT_32 u4Mcs = 0; + + u4Len = ntohs(HqaCmdFrame->Length)/sizeof(UINT_32) - 1; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_MPSSetSeqData u4Len : %d\n", u4Len); + + mps_setting = kmalloc(sizeof(UINT_32)*(u4Len), GFP_KERNEL); + + if (!mps_setting) + return -1; + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_MPSSetSeqData u4Band_idx : %d\n", u4Band_idx); + + for (i = 0 ; i < u4Len ; i++) { + u4Offset = 4 + 4 * i; + if (u4Offset + 4 > sizeof(HqaCmdFrame->Data)) /* Reserved at least 4 byte availbale data */ + break; + memcpy(&u4Value, HqaCmdFrame->Data + 4 + 4*i, 4); + u4Value = ntohl(u4Value); + + u4Mode = (u4Value & BITS(24, 27)) >> 24; + u4TxPath = (u4Value & BITS(8, 23)) >> 8; + u4Mcs = (u4Value & BITS(0, 7)); + + DBGLOG(RFTEST, INFO, + " QA_AGENT HQA_MPSSetSeqData mps_setting Case %d (Mode : %d / TX Path : %d / MCS : %d)\n" + , i, u4Mode, u4TxPath, u4Mcs); + + if (u4Mode == 1) { + u4Mode = 0; + u4Mcs += 4; + } else if ((u4Mode == 0) && ((u4Mcs == 9) || (u4Mcs == 10) || (u4Mcs == 11))) + u4Mode = 1; + + if (u4Mode == 0) { + u4Mcs |= 0x00000000; + + DBGLOG(RFTEST, INFO, " QA_AGENT CCK/OFDM (normal preamble) rate : %d\n", u4Mcs); + } else if (u4Mode == 1) { + if (u4Mcs == 9) + u4Mcs = 1; + else if (u4Mcs == 10) + u4Mcs = 2; + else if (u4Mcs == 11) + u4Mcs = 3; + u4Mcs |= 0x00000000; + + DBGLOG(RFTEST, INFO, " QA_AGENT CCK (short preamble) rate : %d\n", u4Mcs); + } else if (u4Mode >= 2 && u4Mode <= 4) { + u4Mcs |= 0x80000000; + + DBGLOG(RFTEST, INFO, " QA_AGENT HT/VHT rate : %d\n", u4Mcs); + } + + mps_setting[i] = (u4Mcs) | (u4TxPath << 8) | (u4Mode << 24); + + DBGLOG(RFTEST, INFO, + " QA_AGENT HQA_MPSSetSeqData mps_setting Case %u (Mode : %lu / TX Path : %lu / MCS : %lu)\n", + i, + (mps_setting[i] & BITS(24, 27)) >> 24, + (mps_setting[i] & BITS(8, 23)) >> 8, + (mps_setting[i] & BITS(0, 7))); + + } + + i4Ret = MT_ATEMPSSetSeqData(prNetDev, u4Len, mps_setting, u4Band_idx); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(mps_setting); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_MPSSetPayloadLength(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 *mps_setting = NULL; + UINT_32 u4Band_idx = 0; + UINT_32 u4Offset = 0; + UINT_32 u4Len = 0; + UINT_32 i = 0; + UINT_32 u4Value = 0; + + u4Len = ntohs(HqaCmdFrame->Length)/sizeof(UINT_32) - 1; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_MPSSetPayloadLength u4Len : %d\n", u4Len); + + mps_setting = kmalloc(sizeof(UINT_32)*(u4Len), GFP_KERNEL); + + if (!mps_setting) + return -1; + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_MPSSetPayloadLength u4Band_idx : %d\n", u4Band_idx); + + for (i = 0 ; i < u4Len ; i++) { + u4Offset = 4 + 4 * i; + if (u4Offset + 4 > sizeof(HqaCmdFrame->Data)) /* Reserved at least 4 byte availbale data */ + break; + memcpy(&u4Value, HqaCmdFrame->Data + 4 + 4*i, 4); + mps_setting[i] = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, + " QA_AGENT HQA_MPSSetPayloadLength mps_setting Case %d (Payload Length : %d)\n", + i, mps_setting[i]); + } + + i4Ret = MT_ATEMPSSetPayloadLength(prNetDev, u4Len, mps_setting, u4Band_idx); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(mps_setting); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_MPSSetPacketCount(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 *mps_setting = NULL; + UINT_32 u4Band_idx = 0; + UINT_32 u4Offset = 0; + UINT_32 u4Len = 0; + UINT_32 i = 0; + UINT_32 u4Value = 0; + + u4Len = ntohs(HqaCmdFrame->Length)/sizeof(UINT_32) - 1; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_MPSSetPacketCount u4Len : %d\n", u4Len); + + mps_setting = kmalloc(sizeof(UINT_32)*(u4Len), GFP_KERNEL); + + if (!mps_setting) + return -1; + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_MPSSetPacketCount u4Band_idx : %d\n", u4Band_idx); + + for (i = 0 ; i < u4Len ; i++) { + u4Offset = 4 + 4 * i; + if (u4Offset + 4 > sizeof(HqaCmdFrame->Data)) /* Reserved at least 4 byte availbale data */ + break; + memcpy(&u4Value, HqaCmdFrame->Data + 4 + 4*i, 4); + mps_setting[i] = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, + " QA_AGENT HQA_MPSSetPacketCount mps_setting Case %d (Packet Count : %d)\n", + i, mps_setting[i]); + } + + i4Ret = MT_ATEMPSSetPacketCount(prNetDev, u4Len, mps_setting, u4Band_idx); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(mps_setting); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_MPSSetPowerGain(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 *mps_setting = NULL; + UINT_32 u4Band_idx = 0; + UINT_32 u4Offset = 0; + UINT_32 u4Len = 0; + UINT_32 i = 0; + UINT_32 u4Value = 0; + + u4Len = ntohs(HqaCmdFrame->Length)/sizeof(UINT_32) - 1; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_MPSSetPowerGain u4Len : %d\n", u4Len); + + mps_setting = kmalloc(sizeof(UINT_32)*(u4Len), GFP_KERNEL); + + if (!mps_setting) + return -1; + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_MPSSetPowerGain u4Band_idx : %d\n", u4Band_idx); + + for (i = 0 ; i < u4Len ; i++) { + u4Offset = 4 + 4 * i; + if (u4Offset + 4 > sizeof(HqaCmdFrame->Data)) /* Reserved at least 4 byte availbale data */ + break; + memcpy(&u4Value, HqaCmdFrame->Data + 4 + 4*i, 4); + mps_setting[i] = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_MPSSetPowerGain mps_setting Case %d (Power : %d)\n", + i, mps_setting[i]); + } + + i4Ret = MT_ATEMPSSetPowerGain(prNetDev, u4Len, mps_setting, u4Band_idx); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(mps_setting); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_MPSStart(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Band_idx = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_MPSStart\n"); + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + MT_ATEStartTX(prNetDev, "TXFRAME"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_MPSStop(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Band_idx = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_MPSStop\n"); + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + /* To Do : MPS Stop for Specific Band. */ + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_MPSSetNss(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 *mps_setting = NULL; + UINT_32 u4Band_idx = 0; + UINT_32 u4Offset = 0; + UINT_32 u4Len = 0; + UINT_32 i = 0; + UINT_32 u4Value = 0; + + u4Len = ntohs(HqaCmdFrame->Length)/sizeof(UINT_32) - 1; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_MPSSetNss u4Len : %d\n", u4Len); + + mps_setting = kmalloc(sizeof(UINT_32)*(u4Len), GFP_KERNEL); + + if (!mps_setting) + return -1; + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_MPSSetNss u4Band_idx : %d\n", u4Band_idx); + + for (i = 0; i < u4Len; i++) { + u4Offset = 4 + 4 * i; + if (u4Offset + 4 > sizeof(HqaCmdFrame->Data)) /* Reserved at least 4 byte availbale data */ + break; + memcpy(&u4Value, HqaCmdFrame->Data + 4 + 4*i, 4); + mps_setting[i] = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_MPSSetNss mps_setting Case %d (Nss : %d)\n", + i, mps_setting[i]); + } + + i4Ret = MT_ATEMPSSetNss(prNetDev, u4Len, mps_setting, u4Band_idx); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(mps_setting); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_MPSSetPerpacketBW( + struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 *mps_setting = NULL; + UINT_32 u4Band_idx = 0; + UINT_32 u4Offset = 0; + UINT_32 u4Len = 0; + UINT_32 i = 0; + UINT_32 u4Value = 0; + + u4Len = ntohs(HqaCmdFrame->Length)/sizeof(UINT_32) - 1; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_MPSSetPerpacketBW u4Len : %d\n", u4Len); + + mps_setting = kmalloc(sizeof(UINT_32)*(u4Len), GFP_KERNEL); + + if (!mps_setting) + return -1; + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_MPSSetPerpacketBW u4Band_idx : %d\n", u4Band_idx); + + for (i = 0 ; i < u4Len ; i++) { + u4Offset = 4 + 4 * i; + if (u4Offset + 4 > sizeof(HqaCmdFrame->Data)) /* Reserved at least 4 byte availbale data */ + break; + memcpy(&u4Value, HqaCmdFrame->Data + 4 + 4*i, 4); + mps_setting[i] = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_MPSSetPerpacketBW mps_setting Case %d (BW : %d)\n", + i, mps_setting[i]); + } + + i4Ret = MT_ATEMPSSetPerpacketBW(prNetDev, u4Len, mps_setting, u4Band_idx); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(mps_setting); + + return i4Ret; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetAIFS(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 SlotTime = 0; + UINT_32 SifsTime = 0; + + memcpy(&SlotTime, HqaCmdFrame->Data + 4 * 0, 4); + SlotTime = ntohl(SlotTime); + memcpy(&SifsTime, HqaCmdFrame->Data + 4 * 1, 4); + SifsTime = ntohl(SifsTime); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetAIFS SlotTime = %d\n", SlotTime); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetAIFS SifsTime = %d\n", SifsTime); + + i4Ret = MT_ATESetTxIPG(prNetDev, SifsTime); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_CheckEfuseModeType(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 Value = u4EepromMode; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_CheckEfuseModeType\n"); + + /* + * Value: + * 1 -> efuse Mode + * 2 -> flash Mode + * 3 -> eeprom Mode + * 4 -> bin Mode + */ + Value = ntohl(Value); + memcpy(HqaCmdFrame->Data + 2, &(Value), sizeof(Value)); + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_CheckEfuseNativeModeType(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_CheckEfuseNativeModeType\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetBandMode(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Band_mode = 0; + UINT_32 u4Band_type = 0; + + memcpy((PUCHAR) & u4Band_mode, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_mode = ntohl(u4Band_mode); + memcpy((PUCHAR) & u4Band_type, HqaCmdFrame->Data + 4 * 1, 4); + u4Band_type = ntohl(u4Band_type); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetBandMode u4Band_mode : %d\n", u4Band_mode); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_SetBandMode u4Band_type : %d\n", u4Band_type); + + if (u4Band_mode == 2) + g_DBDCEnable = TRUE; + else if (u4Band_mode == 1) + g_DBDCEnable = FALSE; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetBandMode(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Band_mode = 0; + UINT_32 u4Band_idx = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 u4BufLen = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memcpy((PUCHAR) & u4Band_idx, HqaCmdFrame->Data, 4); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_GetBandMode u4Band_idx : %d\n", u4Band_idx); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_DBDC_ENABLE; + if (g_DBDCEnable) + rRfATInfo.u4FuncData = 1; + else + rRfATInfo.u4FuncData = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_GetBandMode g_DBDCEnable = %d\n", g_DBDCEnable); + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + + if (u4Band_idx == 0) { + u4Band_mode = 3; + } else { + if (g_DBDCEnable) + u4Band_mode = 3; + else + u4Band_mode = 0; + } + + u4Band_mode = ntohl(u4Band_mode); + + memcpy(HqaCmdFrame->Data + 2, &(u4Band_mode), sizeof(u4Band_mode)); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + sizeof(u4Band_mode), i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_RDDStartExt(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_RDDStartExt\n"); + + DBGLOG(RFTEST, INFO, "[RDD DUMP START]\n"); + + i4Ret = MT_ATERDDStart(prNetDev, "RDDSTART"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_RDDStopExt(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_RDDStopExt\n"); + + i4Ret = MT_ATERDDStop(prNetDev, "RDDSTOP"); + + DBGLOG(RFTEST, INFO, "[RDD DUMP END]\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_BssInfoUpdate(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 OwnMacIdx = 0, BssIdx = 0; + UINT_8 ucAddr1[MAC_ADDR_LEN]; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&OwnMacIdx, HqaCmdFrame->Data + 4 * 0, 4); + OwnMacIdx = ntohl(OwnMacIdx); + memcpy(&BssIdx, HqaCmdFrame->Data + 4 * 1, 4); + BssIdx = ntohl(BssIdx); + memcpy(ucAddr1, HqaCmdFrame->Data + 4 * 2, 6); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_BssInfoUpdate OwnMacIdx : %d\n", OwnMacIdx); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_BssInfoUpdate BssIdx : %d\n", BssIdx); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_BssInfoUpdate addr1:%02x:%02x:%02x:%02x:%02x:%02x\n", + ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], ucAddr1[4], ucAddr1[5]); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + if (kalSprintf(prInBuf, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + OwnMacIdx, BssIdx, ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], ucAddr1[4], ucAddr1[5]) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_BssInfoUpdate(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_DevInfoUpdate(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 Band = 0, OwnMacIdx = 0; + UINT_8 ucAddr1[MAC_ADDR_LEN]; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&Band, HqaCmdFrame->Data + 4 * 0, 4); + Band = ntohl(Band); + memcpy(&OwnMacIdx, HqaCmdFrame->Data + 4 * 1, 4); + OwnMacIdx = ntohl(OwnMacIdx); + memcpy(ucAddr1, HqaCmdFrame->Data + 4 * 2, 6); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_DevInfoUpdate Band : %d\n", Band); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_DevInfoUpdate OwnMacIdx : %d\n", OwnMacIdx); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_DevInfoUpdate addr1:%02x:%02x:%02x:%02x:%02x:%02x\n", + ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], ucAddr1[4], ucAddr1[5]); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + if (kalSprintf(prInBuf, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + OwnMacIdx, ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], ucAddr1[4], ucAddr1[5], Band) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_DevInfoUpdate(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_LogOnOff(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Band_idx = 0; + UINT_32 u4Log_type = 0; + UINT_32 u4Log_ctrl = 0; + UINT_32 u4Log_size = 200; + + memcpy(&u4Band_idx, HqaCmdFrame->Data, 4); + u4Band_idx = ntohl(u4Band_idx); + memcpy(&u4Log_type, HqaCmdFrame->Data + 4, 4); + u4Log_type = ntohl(u4Log_type); + memcpy(&u4Log_ctrl, HqaCmdFrame->Data + 4 + 4, 4); + u4Log_ctrl = ntohl(u4Log_ctrl); + memcpy(&u4Log_size, HqaCmdFrame->Data + 4 + 4 + 4, 4); + u4Log_size = ntohl(u4Log_size); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_LogOnOff band_idx : %d\n", u4Band_idx); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_LogOnOff log_type : %d\n", u4Log_type); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_LogOnOff log_ctrl : %d\n", u4Log_ctrl); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_LogOnOff log_size : %d\n", u4Log_size); + + i4Ret = MT_ATELogOnOff(prNetDev, u4Log_type, u4Log_ctrl, u4Log_size); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_CMD_SET5[] = { + /* cmd id start from 0x1500 */ + HQA_GetFWInfo, /* 0x1500 */ + HQA_StartContinousTx, /* 0x1501 */ + HQA_SetSTBC, /* 0x1502 */ + HQA_SetShortGI, /* 0x1503 */ + HQA_SetDPD, /* 0x1504 */ + HQA_SetTssiOnOff, /* 0x1505 */ + HQA_GetRxStatisticsAll, /* 0x1506 */ + HQA_StartContiTxTone, /* 0x1507 */ + HQA_StopContiTxTone, /* 0x1508 */ + HQA_CalibrationTestMode, /* 0x1509 */ + HQA_DoCalibrationTestItem, /* 0x150A */ + HQA_eFusePhysicalWrite, /* 0x150B */ + HQA_eFusePhysicalRead, /* 0x150C */ + HQA_eFuseLogicalRead, /* 0x150D */ + HQA_eFuseLogicalWrite, /* 0x150E */ + HQA_TMRSetting, /* 0x150F */ + HQA_GetRxSNR, /* 0x1510 */ + HQA_WriteBufferDone, /* 0x1511 */ + HQA_FFT, /* 0x1512 */ + HQA_SetTxTonePower, /* 0x1513 */ + HQA_GetChipID, /* 0x1514 */ + HQA_MPSSetSeqData, /* 0x1515 */ + HQA_MPSSetPayloadLength, /* 0x1516 */ + HQA_MPSSetPacketCount, /* 0x1517 */ + HQA_MPSSetPowerGain, /* 0x1518 */ + HQA_MPSStart, /* 0x1519 */ + HQA_MPSStop, /* 0x151A */ + ToDoFunction, /* 0x151B */ + ToDoFunction, /* 0x151C */ + ToDoFunction, /* 0x151D */ + ToDoFunction, /* 0x151E */ + ToDoFunction, /* 0x151F */ + ToDoFunction, /* 0x1520 */ + HQA_SetAIFS, /* 0x1521 */ + HQA_CheckEfuseModeType, /* 0x1522 */ + HQA_CheckEfuseNativeModeType, /* 0x1523 */ + ToDoFunction, /* 0x1524 */ + ToDoFunction, /* 0x1525 */ + ToDoFunction, /* 0x1526 */ + ToDoFunction, /* 0x1527 */ + ToDoFunction, /* 0x1528 */ + ToDoFunction, /* 0x1529 */ + ToDoFunction, /* 0x152A */ + ToDoFunction, /* 0x152B */ + HQA_SetBandMode, /* 0x152C */ + HQA_GetBandMode, /* 0x152D */ + HQA_RDDStartExt, /* 0x152E */ + HQA_RDDStopExt, /* 0x152F */ + ToDoFunction, /* 0x1530 */ + HQA_BssInfoUpdate, /* 0x1531 */ + HQA_DevInfoUpdate, /* 0x1532 */ + HQA_LogOnOff, /* 0x1533 */ + ToDoFunction, /* 0x1534 */ + ToDoFunction, /* 0x1535 */ + HQA_MPSSetNss, /* 0x1536 */ + HQA_MPSSetPerpacketBW, /* 0x1537 */ +}; + +#if CFG_SUPPORT_TX_BF +static INT_32 HQA_TxBfProfileTagInValid(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 invalid = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(invalid), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&invalid, HqaCmdFrame->Data, 4); + invalid = ntohl(invalid); + + kalMemSet(prInBuf, 0, sizeof(invalid)); + if (kalSprintf(prInBuf, "%u", invalid) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_InValid(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagPfmuIdx(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 pfmuidx = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(pfmuidx), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&pfmuidx, HqaCmdFrame->Data, 4); + pfmuidx = ntohl(pfmuidx); + + kalMemSet(prInBuf, 0, sizeof(pfmuidx)); + if (kalSprintf(prInBuf, "%u", pfmuidx) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_PfmuIdx(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagBfType(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 bftype = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(bftype), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&bftype, HqaCmdFrame->Data, 4); + bftype = ntohl(bftype); + + kalMemSet(prInBuf, 0, sizeof(bftype)); + if (kalSprintf(prInBuf, "%u", bftype) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_BfType(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagBw(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 tag_bw = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(tag_bw), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&tag_bw, HqaCmdFrame->Data, 4); + tag_bw = ntohl(tag_bw); + + kalMemSet(prInBuf, 0, sizeof(tag_bw)); + if (kalSprintf(prInBuf, "%u", tag_bw) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_DBW(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagSuMu(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 su_mu = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(su_mu), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&su_mu, HqaCmdFrame->Data, 4); + su_mu = ntohl(su_mu); + + kalMemSet(prInBuf, 0, sizeof(su_mu)); + if (kalSprintf(prInBuf, "%u", su_mu) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_SuMu(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagMemAlloc(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 col_idx0, row_idx0, col_idx1, row_idx1; + UINT_32 col_idx2, row_idx2, col_idx3, row_idx3; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&col_idx0, HqaCmdFrame->Data + 4 * 0, 4); + col_idx0 = ntohl(col_idx0); + memcpy(&row_idx0, HqaCmdFrame->Data + 4 * 1, 4); + row_idx0 = ntohl(row_idx0); + memcpy(&col_idx1, HqaCmdFrame->Data + 4 * 2, 4); + col_idx1 = ntohl(col_idx1); + memcpy(&row_idx1, HqaCmdFrame->Data + 4 * 3, 4); + row_idx1 = ntohl(row_idx1); + memcpy(&col_idx2, HqaCmdFrame->Data + 4 * 4, 4); + col_idx2 = ntohl(col_idx2); + memcpy(&row_idx2, HqaCmdFrame->Data + 4 * 5, 4); + row_idx2 = ntohl(row_idx2); + memcpy(&col_idx3, HqaCmdFrame->Data + 4 * 6, 4); + col_idx3 = ntohl(col_idx3); + memcpy(&row_idx3, HqaCmdFrame->Data + 4 * 7, 4); + row_idx3 = ntohl(row_idx3); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + if (kalSprintf(prInBuf, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + col_idx0, row_idx0, col_idx1, row_idx1, col_idx2, row_idx2, col_idx3, row_idx3) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_Mem(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagMatrix(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 nrow, ncol, ngroup, LM, code_book, htc_exist; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&nrow, HqaCmdFrame->Data + 4 * 0, 4); + nrow = ntohl(nrow); + memcpy(&ncol, HqaCmdFrame->Data + 4 * 1, 4); + ncol = ntohl(ncol); + memcpy(&ngroup, HqaCmdFrame->Data + 4 * 2, 4); + ngroup = ntohl(ngroup); + memcpy(&LM, HqaCmdFrame->Data + 4 * 3, 4); + LM = ntohl(LM); + memcpy(&code_book, HqaCmdFrame->Data + 4 * 4, 4); + code_book = ntohl(code_book); + memcpy(&htc_exist, HqaCmdFrame->Data + 4 * 5, 4); + htc_exist = ntohl(htc_exist); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + if (kalSprintf(prInBuf, "%02x:%02x:%02x:%02x:%02x:%02x", + nrow, ncol, ngroup, LM, code_book, htc_exist) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_Matrix(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagSnr(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 snr_sts0, snr_sts1, snr_sts2, snr_sts3; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&snr_sts0, HqaCmdFrame->Data + 4 * 0, 4); + snr_sts0 = ntohl(snr_sts0); + memcpy(&snr_sts1, HqaCmdFrame->Data + 4 * 1, 4); + snr_sts1 = ntohl(snr_sts1); + memcpy(&snr_sts2, HqaCmdFrame->Data + 4 * 2, 4); + snr_sts2 = ntohl(snr_sts2); + memcpy(&snr_sts3, HqaCmdFrame->Data + 4 * 3, 4); + snr_sts3 = ntohl(snr_sts3); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + if (kalSprintf(prInBuf, "%02x:%02x:%02x:%02x", snr_sts0, snr_sts1, snr_sts2, snr_sts3) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_SNR(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagSmtAnt(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 smt_ant = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(smt_ant), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&smt_ant, HqaCmdFrame->Data + 4 * 0, 4); + smt_ant = ntohl(smt_ant); + + kalMemSet(prInBuf, 0, sizeof(smt_ant)); + if (kalSprintf(prInBuf, "%u", smt_ant) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_SmartAnt(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagSeIdx(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 se_idx = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(se_idx), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&se_idx, HqaCmdFrame->Data + 4 * 0, 4); + se_idx = ntohl(se_idx); + + kalMemSet(prInBuf, 0, sizeof(se_idx)); + if (kalSprintf(prInBuf, "%u", se_idx) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_SeIdx(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagRmsdThrd(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 rmsd_thrd = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(rmsd_thrd), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&rmsd_thrd, HqaCmdFrame->Data + 4 * 0, 4); + rmsd_thrd = ntohl(rmsd_thrd); + + kalMemSet(prInBuf, 0, sizeof(rmsd_thrd)); + if (kalSprintf(prInBuf, "%u", rmsd_thrd) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_RmsdThrd(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagMcsThrd(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 mcs_lss0, mcs_sss0, mcs_lss1, mcs_sss1, mcs_lss2, mcs_sss2; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&mcs_lss0, HqaCmdFrame->Data + 4 * 0, 4); + mcs_lss0 = ntohl(mcs_lss0); + memcpy(&mcs_sss0, HqaCmdFrame->Data + 4 * 1, 4); + mcs_sss0 = ntohl(mcs_sss0); + memcpy(&mcs_lss1, HqaCmdFrame->Data + 4 * 2, 4); + mcs_lss1 = ntohl(mcs_lss1); + memcpy(&mcs_sss1, HqaCmdFrame->Data + 4 * 3, 4); + mcs_sss1 = ntohl(mcs_sss1); + memcpy(&mcs_lss2, HqaCmdFrame->Data + 4 * 4, 4); + mcs_lss2 = ntohl(mcs_lss2); + memcpy(&mcs_sss2, HqaCmdFrame->Data + 4 * 5, 4); + mcs_sss2 = ntohl(mcs_sss2); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + if (kalSprintf(prInBuf, "%02x:%02x:%02x:%02x:%02x:%02x", mcs_lss0, mcs_sss0, mcs_lss1, mcs_sss1, mcs_lss2, + mcs_sss2) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_McsThrd(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagTimeOut(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 bf_tout = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(bf_tout), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&bf_tout, HqaCmdFrame->Data + 4 * 0, 4); + bf_tout = ntohl(bf_tout); + + kalMemSet(prInBuf, 0, sizeof(bf_tout)); + if (kalSprintf(prInBuf, "%x", bf_tout) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_TimeOut(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagDesiredBw(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 desire_bw = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(desire_bw), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&desire_bw, HqaCmdFrame->Data + 4 * 0, 4); + desire_bw = ntohl(desire_bw); + + kalMemSet(prInBuf, 0, sizeof(desire_bw)); + if (kalSprintf(prInBuf, "%u", desire_bw) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_DesiredBW(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagDesiredNc(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 desire_nc = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(desire_nc), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&desire_nc, HqaCmdFrame->Data + 4 * 0, 4); + desire_nc = ntohl(desire_nc); + + kalMemSet(prInBuf, 0, sizeof(desire_nc)); + if (kalSprintf(prInBuf, "%u", desire_nc) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_DesiredNc(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagDesiredNr(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 desire_nr = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(desire_nr), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&desire_nr, HqaCmdFrame->Data + 4 * 0, 4); + desire_nr = ntohl(desire_nr); + + kalMemSet(prInBuf, 0, sizeof(desire_nr)); + if (kalSprintf(prInBuf, "%u", desire_nr) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_DesiredNr(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagWrite(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 idx = 0; /* WLAN_IDX */ + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(idx), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&idx, HqaCmdFrame->Data + 4 * 0, 4); + idx = ntohl(idx); + + kalMemSet(prInBuf, 0, sizeof(idx)); + if (kalSprintf(prInBuf, "%u", idx) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTagWrite(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagRead(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 idx = 0, isBFer = 0; + UINT_8 *prInBuf; + PFMU_PROFILE_TAG1 rPfmuTag1; + PFMU_PROFILE_TAG2 rPfmuTag2; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&idx, HqaCmdFrame->Data + 4 * 0, 4); + idx = ntohl(idx); + memcpy(&isBFer, HqaCmdFrame->Data + 4 * 1, 4); + isBFer = ntohl(isBFer); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + if (kalSprintf(prInBuf, "%02x:%02x", idx, isBFer) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTagRead(prNetDev, prInBuf); + + rPfmuTag1.au4RawData[0] = ntohl(g_rPfmuTag1.au4RawData[0]); + rPfmuTag1.au4RawData[1] = ntohl(g_rPfmuTag1.au4RawData[1]); + rPfmuTag1.au4RawData[2] = ntohl(g_rPfmuTag1.au4RawData[2]); + rPfmuTag1.au4RawData[3] = ntohl(g_rPfmuTag1.au4RawData[3]); + + rPfmuTag2.au4RawData[0] = ntohl(g_rPfmuTag2.au4RawData[0]); + rPfmuTag2.au4RawData[1] = ntohl(g_rPfmuTag2.au4RawData[1]); + rPfmuTag2.au4RawData[2] = ntohl(g_rPfmuTag2.au4RawData[2]); + + memcpy(HqaCmdFrame->Data + 2, &rPfmuTag1, sizeof(PFMU_PROFILE_TAG1)); + memcpy(HqaCmdFrame->Data + 2 + sizeof(PFMU_PROFILE_TAG1), &rPfmuTag2, sizeof(PFMU_PROFILE_TAG2)); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + sizeof(PFMU_PROFILE_TAG1) + sizeof(PFMU_PROFILE_TAG2), i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_StaRecCmmUpdate(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 wlan_idx, bss_idx, aid; + UINT_8 mac[MAC_ADDR_LEN]; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&wlan_idx, HqaCmdFrame->Data + 4 * 0, 4); + wlan_idx = ntohl(wlan_idx); + memcpy(&bss_idx, HqaCmdFrame->Data + 4 * 1, 4); + bss_idx = ntohl(bss_idx); + memcpy(&aid, HqaCmdFrame->Data + 4 * 2, 4); + aid = ntohl(aid); + + memcpy(mac, HqaCmdFrame->Data + 4 * 3, 6); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + i4Ret = kalSprintf(prInBuf, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + wlan_idx, bss_idx, aid, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + if (i4Ret < 0) { + DBGLOG(RFTEST, ERROR, "sprintf failed\n"); + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_StaRecCmmUpdate(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_StaRecBfUpdate(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 wlan_idx, bss_idx, PfmuId, su_mu, etxbf_cap, ndpa_rate, ndp_rate; + UINT_32 report_poll_rate, tx_mode, nc, nr, cbw, spe_idx, tot_mem_req; + UINT_32 mem_req_20m, mem_row0, mem_col0, mem_row1, mem_col1; + UINT_32 mem_row2, mem_col2, mem_row3, mem_col3; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&wlan_idx, HqaCmdFrame->Data + 4 * 0, 4); + wlan_idx = ntohl(wlan_idx); + memcpy(&bss_idx, HqaCmdFrame->Data + 4 * 1, 4); + bss_idx = ntohl(bss_idx); + memcpy(&PfmuId, HqaCmdFrame->Data + 4 * 2, 4); + PfmuId = ntohl(PfmuId); + memcpy(&su_mu, HqaCmdFrame->Data + 4 * 3, 4); + su_mu = ntohl(su_mu); + memcpy(&etxbf_cap, HqaCmdFrame->Data + 4 * 4, 4); + etxbf_cap = ntohl(etxbf_cap); + memcpy(&ndpa_rate, HqaCmdFrame->Data + 4 * 5, 4); + ndpa_rate = ntohl(ndpa_rate); + memcpy(&ndp_rate, HqaCmdFrame->Data + 4 * 6, 4); + ndp_rate = ntohl(ndp_rate); + memcpy(&report_poll_rate, HqaCmdFrame->Data + 4 * 7, 4); + report_poll_rate = ntohl(report_poll_rate); + memcpy(&tx_mode, HqaCmdFrame->Data + 4 * 8, 4); + tx_mode = ntohl(tx_mode); + memcpy(&nc, HqaCmdFrame->Data + 4 * 9, 4); + nc = ntohl(nc); + memcpy(&nr, HqaCmdFrame->Data + 4 * 10, 4); + nr = ntohl(nr); + memcpy(&cbw, HqaCmdFrame->Data + 4 * 11, 4); + cbw = ntohl(cbw); + memcpy(&spe_idx, HqaCmdFrame->Data + 4 * 12, 4); + spe_idx = ntohl(spe_idx); + memcpy(&tot_mem_req, HqaCmdFrame->Data + 4 * 13, 4); + tot_mem_req = ntohl(tot_mem_req); + memcpy(&mem_req_20m, HqaCmdFrame->Data + 4 * 14, 4); + mem_req_20m = ntohl(mem_req_20m); + memcpy(&mem_row0, HqaCmdFrame->Data + 4 * 15, 4); + mem_row0 = ntohl(mem_row0); + memcpy(&mem_col0, HqaCmdFrame->Data + 4 * 16, 4); + mem_col0 = ntohl(mem_col0); + memcpy(&mem_row1, HqaCmdFrame->Data + 4 * 17, 4); + mem_row1 = ntohl(mem_row1); + memcpy(&mem_col1, HqaCmdFrame->Data + 4 * 18, 4); + mem_col1 = ntohl(mem_col1); + memcpy(&mem_row2, HqaCmdFrame->Data + 4 * 19, 4); + mem_row2 = ntohl(mem_row2); + memcpy(&mem_col2, HqaCmdFrame->Data + 4 * 20, 4); + mem_col2 = ntohl(mem_col2); + memcpy(&mem_row3, HqaCmdFrame->Data + 4 * 21, 4); + mem_row3 = ntohl(mem_row3); + memcpy(&mem_col3, HqaCmdFrame->Data + 4 * 22, 4); + mem_col3 = ntohl(mem_col3); + + /* For Tool wrong memory row and col num 20160501 */ + if (PfmuId == 0) { + mem_row0 = 0; + mem_col0 = 0; + mem_row1 = 1; + mem_col1 = 0; + mem_row2 = 2; + mem_col2 = 0; + mem_row3 = 3; + mem_col3 = 0; + } else if (PfmuId == 1) { + mem_row0 = 0; + mem_col0 = 2; + mem_row1 = 1; + mem_col1 = 2; + mem_row2 = 2; + mem_col2 = 2; + mem_row3 = 3; + mem_col3 = 2; + } + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + if (kalSprintf(prInBuf, + "%02x:%02x:%02x:%02x:%02x:%02d:%02d:%02d:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + wlan_idx, bss_idx, PfmuId, su_mu, etxbf_cap, ndpa_rate, ndp_rate, report_poll_rate, tx_mode, nc, nr, + cbw, spe_idx, tot_mem_req, mem_req_20m, mem_row0, mem_col0, mem_row1, mem_col1, mem_row2, mem_col2, + mem_row3, mem_col3) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_StaRecBfUpdate(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_BFProfileDataRead(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 idx = 0, fgBFer = 0, subcarrIdx = 0, subcarr_start = 0, subcarr_end = 0; + UINT_32 NumOfsub = 0; + UINT_32 offset = 0; + UINT_8 *SubIdx = NULL; + UINT_8 *prInBuf; + PFMU_DATA rPfmuData; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&idx, HqaCmdFrame->Data + 4 * 0, 4); + idx = ntohl(idx); + memcpy(&fgBFer, HqaCmdFrame->Data + 4 * 1, 4); + fgBFer = ntohl(fgBFer); + memcpy(&subcarr_start, HqaCmdFrame->Data + 4 * 2, 4); + subcarr_start = ntohl(subcarr_start); + memcpy(&subcarr_end, HqaCmdFrame->Data + 4 * 3, 4); + subcarr_end = ntohl(subcarr_end); + + NumOfsub = subcarr_end - subcarr_start + 1; + NumOfsub = ntohl(NumOfsub); + + memcpy(HqaCmdFrame->Data + 2, &NumOfsub, sizeof(NumOfsub)); + offset += sizeof(NumOfsub); + + for (subcarrIdx = subcarr_start; subcarrIdx <= subcarr_end; subcarrIdx++) { + SubIdx = (UINT_8 *) &subcarrIdx; + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + if (kalSprintf(prInBuf, "%02x:%02x:%02x:%02x", idx, fgBFer, SubIdx[1], SubIdx[0]) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileDataRead(prNetDev, prInBuf); + + rPfmuData.au4RawData[0] = ntohl(g_rPfmuData.au4RawData[0]); + rPfmuData.au4RawData[1] = ntohl(g_rPfmuData.au4RawData[1]); + rPfmuData.au4RawData[2] = ntohl(g_rPfmuData.au4RawData[2]); + rPfmuData.au4RawData[3] = ntohl(g_rPfmuData.au4RawData[3]); + rPfmuData.au4RawData[4] = ntohl(g_rPfmuData.au4RawData[4]); + + memcpy(HqaCmdFrame->Data + 2 + offset, &rPfmuData, sizeof(rPfmuData)); + offset += sizeof(rPfmuData); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + offset, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_BFProfileDataWrite(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 pfmuid, subcarrier, phi11, psi21, phi21, psi31, phi31, psi41; + UINT_32 phi22, psi32, phi32, psi42, phi33, psi43, snr00, snr01, snr02, snr03; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&pfmuid, HqaCmdFrame->Data + 4 * 0, 4); + pfmuid = ntohl(pfmuid); + memcpy(&subcarrier, HqaCmdFrame->Data + 4 * 1, 4); + subcarrier = ntohl(subcarrier); + memcpy(&phi11, HqaCmdFrame->Data + 4 * 2, 4); + phi11 = ntohl(phi11); + memcpy(&psi21, HqaCmdFrame->Data + 4 * 3, 4); + psi21 = ntohl(psi21); + memcpy(&phi21, HqaCmdFrame->Data + 4 * 4, 4); + phi21 = ntohl(phi21); + memcpy(&psi31, HqaCmdFrame->Data + 4 * 5, 4); + psi31 = ntohl(psi31); + memcpy(&phi31, HqaCmdFrame->Data + 4 * 6, 4); + phi31 = ntohl(phi31); + memcpy(&psi41, HqaCmdFrame->Data + 4 * 7, 4); + psi41 = ntohl(psi41); + memcpy(&phi22, HqaCmdFrame->Data + 4 * 8, 4); + phi22 = ntohl(phi22); + memcpy(&psi32, HqaCmdFrame->Data + 4 * 9, 4); + psi32 = ntohl(psi32); + memcpy(&phi32, HqaCmdFrame->Data + 4 * 10, 4); + phi32 = ntohl(phi32); + memcpy(&psi42, HqaCmdFrame->Data + 4 * 11, 4); + psi42 = ntohl(psi42); + memcpy(&phi33, HqaCmdFrame->Data + 4 * 12, 4); + phi33 = ntohl(phi33); + memcpy(&psi43, HqaCmdFrame->Data + 4 * 13, 4); + psi43 = ntohl(psi43); + memcpy(&snr00, HqaCmdFrame->Data + 4 * 14, 4); + snr00 = ntohl(snr00); + memcpy(&snr01, HqaCmdFrame->Data + 4 * 15, 4); + snr01 = ntohl(snr01); + memcpy(&snr02, HqaCmdFrame->Data + 4 * 16, 4); + snr02 = ntohl(snr02); + memcpy(&snr03, HqaCmdFrame->Data + 4 * 17, 4); + snr03 = ntohl(snr03); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + if (kalSprintf(prInBuf, + "%02x:%03x:%03x:%02x:%03x:%02x:%03x:%02x:%03x:%02x:%03x:%02x:%03x:%02x:%02x:%02x:%02x:%02x", + pfmuid, subcarrier, phi11, psi21, phi21, psi31, phi31, psi41, + phi22, psi32, phi32, psi42, phi33, psi43, snr00, snr01, snr02, snr03) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileDataWrite(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_BFSounding(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 su_mu, mu_num, snd_interval, wlan_id0; + UINT_32 wlan_id1, wlan_id2, wlan_id3, band_idx; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&su_mu, HqaCmdFrame->Data + 4 * 0, 4); + su_mu = ntohl(su_mu); + memcpy(&mu_num, HqaCmdFrame->Data + 4 * 1, 4); + mu_num = ntohl(mu_num); + memcpy(&snd_interval, HqaCmdFrame->Data + 4 * 2, 4); + snd_interval = ntohl(snd_interval); + memcpy(&wlan_id0, HqaCmdFrame->Data + 4 * 3, 4); + wlan_id0 = ntohl(wlan_id0); + memcpy(&wlan_id1, HqaCmdFrame->Data + 4 * 4, 4); + wlan_id1 = ntohl(wlan_id1); + memcpy(&wlan_id2, HqaCmdFrame->Data + 4 * 5, 4); + wlan_id2 = ntohl(wlan_id2); + memcpy(&wlan_id3, HqaCmdFrame->Data + 4 * 6, 4); + wlan_id3 = ntohl(wlan_id3); + memcpy(&band_idx, HqaCmdFrame->Data + 4 * 7, 4); + band_idx = ntohl(band_idx); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + if (kalSprintf(prInBuf, "%02x:%02x:%02x:%02x:%02x:%02x:%02x", + su_mu, mu_num, snd_interval, wlan_id0, wlan_id1, wlan_id2, wlan_id3) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_Trigger_Sounding_Proc(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TXBFSoundingStop(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_TXBFSoundingStop\n"); + + i4Ret = Set_Stop_Sounding_Proc(prNetDev, NULL); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static INT_32 HQA_TXBFProfileDataWriteAllExt(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static INT_32 HQA_TxBfTxApply(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 eBF_enable = 0; + UINT_32 iBF_enable = 0; + UINT_32 wlan_id = 0; + UINT_32 MuTx_enable = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&eBF_enable, HqaCmdFrame->Data + 4 * 0, 4); + eBF_enable = ntohl(eBF_enable); + memcpy(&iBF_enable, HqaCmdFrame->Data + 4 * 1, 4); + iBF_enable = ntohl(iBF_enable); + memcpy(&wlan_id, HqaCmdFrame->Data + 4 * 2, 4); + wlan_id = ntohl(wlan_id); + memcpy(&MuTx_enable, HqaCmdFrame->Data + 4 * 3, 4); + MuTx_enable = ntohl(MuTx_enable); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + if (kalSprintf(prInBuf, "%02x:%02x:%02x:%02x", + wlan_id, eBF_enable, iBF_enable, MuTx_enable) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfTxApply(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_ManualAssoc(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 type; + UINT_32 wtbl_idx; + UINT_32 ownmac_idx; + UINT_32 phymode; + UINT_32 bw; + UINT_32 pfmuid; + UINT_32 marate_mode; + UINT_32 marate_mcs; + UINT_32 spe_idx; + UINT_32 aid; + UINT_8 ucAddr1[MAC_ADDR_LEN]; + UINT_32 nss = 1; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&type, HqaCmdFrame->Data + 4 * 0, 4); + type = ntohl(type); + memcpy(&wtbl_idx, HqaCmdFrame->Data + 4 * 1, 4); + wtbl_idx = ntohl(wtbl_idx); + memcpy(&ownmac_idx, HqaCmdFrame->Data + 4 * 2, 4); + ownmac_idx = ntohl(ownmac_idx); + memcpy(&phymode, HqaCmdFrame->Data + 4 * 3, 4); + phymode = ntohl(phymode); + memcpy(&bw, HqaCmdFrame->Data + 4 * 4, 4); + bw = ntohl(bw); + memcpy(&pfmuid, HqaCmdFrame->Data + 4 * 5, 4); + pfmuid = ntohl(pfmuid); + memcpy(&marate_mode, HqaCmdFrame->Data + 4 * 6, 4); + marate_mode = ntohl(marate_mode); + memcpy(&marate_mcs, HqaCmdFrame->Data + 4 * 7, 4); + marate_mcs = ntohl(marate_mcs); + memcpy(&spe_idx, HqaCmdFrame->Data + 4 * 8, 4); + spe_idx = ntohl(spe_idx); + memcpy(&aid, HqaCmdFrame->Data + 4 * 9, 4); + aid = ntohl(aid); + memcpy(ucAddr1, HqaCmdFrame->Data + 4 * 10, 6); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + if (kalSprintf(prInBuf, + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], ucAddr1[4], ucAddr1[5], type, wtbl_idx, ownmac_idx, + phymode, bw, nss, pfmuid, marate_mode, marate_mcs, spe_idx, aid, 0) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfManualAssoc(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_TXBF_CMDS[] = { + HQA_TxBfProfileTagInValid, /* 0x1540 */ + HQA_TxBfProfileTagPfmuIdx, /* 0x1541 */ + HQA_TxBfProfileTagBfType, /* 0x1542 */ + HQA_TxBfProfileTagBw, /* 0x1543 */ + HQA_TxBfProfileTagSuMu, /* 0x1544 */ + HQA_TxBfProfileTagMemAlloc, /* 0x1545 */ + HQA_TxBfProfileTagMatrix, /* 0x1546 */ + HQA_TxBfProfileTagSnr, /* 0x1547 */ + HQA_TxBfProfileTagSmtAnt, /* 0x1548 */ + HQA_TxBfProfileTagSeIdx, /* 0x1549 */ + HQA_TxBfProfileTagRmsdThrd, /* 0x154A */ + HQA_TxBfProfileTagMcsThrd, /* 0x154B */ + HQA_TxBfProfileTagTimeOut, /* 0x154C */ + HQA_TxBfProfileTagDesiredBw, /* 0x154D */ + HQA_TxBfProfileTagDesiredNc, /* 0x154E */ + HQA_TxBfProfileTagDesiredNr, /* 0x154F */ + HQA_TxBfProfileTagWrite, /* 0x1550 */ + HQA_TxBfProfileTagRead, /* 0x1551 */ + HQA_StaRecCmmUpdate, /* 0x1552 */ + HQA_StaRecBfUpdate, /* 0x1553 */ + HQA_BFProfileDataRead, /* 0x1554 */ + HQA_BFProfileDataWrite, /* 0x1555 */ + HQA_BFSounding, /* 0x1556 */ + HQA_TXBFSoundingStop, /* 0x1557 */ + HQA_TXBFProfileDataWriteAllExt, /* 0x1558 */ + HQA_TxBfTxApply, /* 0x1559 */ + HQA_ManualAssoc, /* 0x155A */ +}; + +#if CFG_SUPPORT_MU_MIMO +static INT_32 HQA_MUGetInitMCS(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Gid = 0; + UINT_32 u4User0InitMCS = 0; + UINT_32 u4User1InitMCS = 0; + UINT_32 u4User2InitMCS = 0; + UINT_32 u4User3InitMCS = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&u4Gid, HqaCmdFrame->Data, 4); + u4Gid = ntohl(u4Gid); + + kalMemSet(prInBuf, 0, sizeof(u4Gid)); + if (kalSprintf(prInBuf, "%u", u4Gid) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUGetInitMCS(prNetDev, prInBuf); + + u4User0InitMCS = ntohl(u4User0InitMCS); + u4User1InitMCS = ntohl(u4User1InitMCS); + u4User2InitMCS = ntohl(u4User2InitMCS); + u4User3InitMCS = ntohl(u4User3InitMCS); + + memcpy(HqaCmdFrame->Data + 2, &u4User0InitMCS, sizeof(UINT_32)); + memcpy(HqaCmdFrame->Data + 2 + 1 * sizeof(UINT_32), &u4User1InitMCS, sizeof(UINT_32)); + memcpy(HqaCmdFrame->Data + 2 + 2 * sizeof(UINT_32), &u4User2InitMCS, sizeof(UINT_32)); + memcpy(HqaCmdFrame->Data + 2 + 3 * sizeof(UINT_32), &u4User3InitMCS, sizeof(UINT_32)); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_MUCalInitMCS(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Num_of_user; + UINT_32 u4Bandwidth; + UINT_32 u4Nss_of_user0; + UINT_32 u4Nss_of_user1; + UINT_32 u4Nss_of_user2; + UINT_32 u4Nss_of_user3; + UINT_32 u4Pf_mu_id_of_user0; + UINT_32 u4Pf_mu_id_of_user1; + UINT_32 u4Pf_mu_id_of_user2; + UINT_32 u4Pf_mu_id_of_user3; + UINT_32 u4Num_of_txer; /* number of antenna */ + UINT_32 u4Spe_index; + UINT_32 u4Group_index; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&u4Num_of_user, HqaCmdFrame->Data + 4 * 0, 4); + u4Num_of_user = ntohl(u4Num_of_user); + memcpy(&u4Bandwidth, HqaCmdFrame->Data + 4 * 1, 4); + u4Bandwidth = ntohl(u4Bandwidth); + memcpy(&u4Nss_of_user0, HqaCmdFrame->Data + 4 * 2, 4); + u4Nss_of_user0 = ntohl(u4Nss_of_user0); + memcpy(&u4Nss_of_user1, HqaCmdFrame->Data + 4 * 3, 4); + u4Nss_of_user1 = ntohl(u4Nss_of_user1); + memcpy(&u4Nss_of_user2, HqaCmdFrame->Data + 4 * 4, 4); + u4Nss_of_user2 = ntohl(u4Nss_of_user2); + memcpy(&u4Nss_of_user3, HqaCmdFrame->Data + 4 * 5, 4); + u4Nss_of_user3 = ntohl(u4Nss_of_user3); + memcpy(&u4Pf_mu_id_of_user0, HqaCmdFrame->Data + 4 * 6, 4); + u4Pf_mu_id_of_user0 = ntohl(u4Pf_mu_id_of_user0); + memcpy(&u4Pf_mu_id_of_user1, HqaCmdFrame->Data + 4 * 7, 4); + u4Pf_mu_id_of_user1 = ntohl(u4Pf_mu_id_of_user1); + memcpy(&u4Pf_mu_id_of_user2, HqaCmdFrame->Data + 4 * 8, 4); + u4Pf_mu_id_of_user2 = ntohl(u4Pf_mu_id_of_user2); + memcpy(&u4Pf_mu_id_of_user3, HqaCmdFrame->Data + 4 * 9, 4); + u4Pf_mu_id_of_user3 = ntohl(u4Pf_mu_id_of_user3); + memcpy(&u4Num_of_txer, HqaCmdFrame->Data + 4 * 10, 4); + u4Num_of_txer = ntohl(u4Num_of_txer); + memcpy(&u4Spe_index, HqaCmdFrame->Data + 4 * 11, 4); + u4Spe_index = ntohl(u4Spe_index); + memcpy(&u4Group_index, HqaCmdFrame->Data + 4 * 12, 4); + u4Group_index = ntohl(u4Group_index); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + if (kalSprintf(prInBuf, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + u4Num_of_user, u4Bandwidth, u4Nss_of_user0, u4Nss_of_user1, u4Pf_mu_id_of_user0, u4Pf_mu_id_of_user1, + u4Num_of_txer, u4Spe_index, u4Group_index) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUCalInitMCS(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_MUCalLQ(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Type = 0; + UINT_32 u4Num_of_user; + UINT_32 u4Bandwidth; + UINT_32 u4Nss_of_user0; + UINT_32 u4Nss_of_user1; + UINT_32 u4Nss_of_user2; + UINT_32 u4Nss_of_user3; + UINT_32 u4Pf_mu_id_of_user0; + UINT_32 u4Pf_mu_id_of_user1; + UINT_32 u4Pf_mu_id_of_user2; + UINT_32 u4Pf_mu_id_of_user3; + UINT_32 u4Num_of_txer; /* number of antenna */ + UINT_32 u4Spe_index; + UINT_32 u4Group_index; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&u4Type, HqaCmdFrame->Data + 4 * 0, 4); + u4Type = ntohl(u4Type); + memcpy(&u4Num_of_user, HqaCmdFrame->Data + 4 * 1, 4); + u4Num_of_user = ntohl(u4Num_of_user); + memcpy(&u4Bandwidth, HqaCmdFrame->Data + 4 * 2, 4); + u4Bandwidth = ntohl(u4Bandwidth); + memcpy(&u4Nss_of_user0, HqaCmdFrame->Data + 4 * 3, 4); + u4Nss_of_user0 = ntohl(u4Nss_of_user0); + memcpy(&u4Nss_of_user1, HqaCmdFrame->Data + 4 * 4, 4); + u4Nss_of_user1 = ntohl(u4Nss_of_user1); + memcpy(&u4Nss_of_user2, HqaCmdFrame->Data + 4 * 5, 4); + u4Nss_of_user2 = ntohl(u4Nss_of_user2); + memcpy(&u4Nss_of_user3, HqaCmdFrame->Data + 4 * 6, 4); + u4Nss_of_user3 = ntohl(u4Nss_of_user3); + memcpy(&u4Pf_mu_id_of_user0, HqaCmdFrame->Data + 4 * 7, 4); + u4Pf_mu_id_of_user0 = ntohl(u4Pf_mu_id_of_user0); + memcpy(&u4Pf_mu_id_of_user1, HqaCmdFrame->Data + 4 * 8, 4); + u4Pf_mu_id_of_user1 = ntohl(u4Pf_mu_id_of_user1); + memcpy(&u4Pf_mu_id_of_user2, HqaCmdFrame->Data + 4 * 9, 4); + u4Pf_mu_id_of_user2 = ntohl(u4Pf_mu_id_of_user2); + memcpy(&u4Pf_mu_id_of_user3, HqaCmdFrame->Data + 4 * 10, 4); + u4Pf_mu_id_of_user3 = ntohl(u4Pf_mu_id_of_user3); + memcpy(&u4Num_of_txer, HqaCmdFrame->Data + 4 * 11, 4); + u4Num_of_txer = ntohl(u4Num_of_txer); + memcpy(&u4Spe_index, HqaCmdFrame->Data + 4 * 12, 4); + u4Spe_index = ntohl(u4Spe_index); + memcpy(&u4Group_index, HqaCmdFrame->Data + 4 * 13, 4); + u4Group_index = ntohl(u4Group_index); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + if (kalSprintf(prInBuf, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + u4Num_of_user, u4Bandwidth, u4Nss_of_user0, u4Nss_of_user1, u4Pf_mu_id_of_user0, u4Pf_mu_id_of_user1, + u4Num_of_txer, u4Spe_index, u4Group_index) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUCalLQ(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_MUGetLQ(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 i; + UINT_8 u4LqReport[NUM_OF_USER * NUM_OF_MODUL] = {0}; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUGetLQ(prNetDev, prInBuf); + + for (i = 0; i < NUM_OF_USER * NUM_OF_MODUL; i++) { + u4LqReport[i] = ntohl(u4LqReport[i]); + memcpy(HqaCmdFrame->Data + 2 + i * sizeof(UINT_32), &u4LqReport[i], sizeof(UINT_32)); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_MUSetSNROffset(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Offset = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&u4Offset, HqaCmdFrame->Data + 4 * 0, 4); + u4Offset = ntohl(u4Offset); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + if (kalSprintf(prInBuf, "%02x", u4Offset) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUSetSNROffset(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_MUSetZeroNss(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Zero_nss = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&u4Zero_nss, HqaCmdFrame->Data + 4 * 0, 4); + u4Zero_nss = ntohl(u4Zero_nss); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + if (kalSprintf(prInBuf, "%02x", u4Zero_nss) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUSetZeroNss(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_MUSetSpeedUpLQ(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4SpeedUpLq = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&u4SpeedUpLq, HqaCmdFrame->Data + 4 * 0, 4); + u4SpeedUpLq = ntohl(u4SpeedUpLq); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + if (kalSprintf(prInBuf, "%02x", u4SpeedUpLq) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUSetSpeedUpLQ(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; + +} + +static INT_32 HQA_MUSetMUTable(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_8 *prTable; + UINT_16 u2Len = 0; + UINT_32 u4SuMu = 0; + + prTable = kmalloc_array(u2Len, sizeof(UINT_8), GFP_KERNEL); + if (!prTable) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + u2Len = ntohl(HqaCmdFrame->Length) - sizeof(u4SuMu); + + memcpy(&u4SuMu, HqaCmdFrame->Data + 4 * 0, 4); + u4SuMu = ntohl(u4SuMu); + + memcpy(prTable, HqaCmdFrame->Data + 4, u2Len); + + i4Ret = Set_MUSetMUTable(prNetDev, prTable); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prTable); + + return i4Ret; +} + +static INT_32 HQA_MUSetGroup(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4GroupIndex, u4NumOfUser, u4User0Ldpc, u4User1Ldpc, u4User2Ldpc, u4User3Ldpc; + UINT_32 u4ShortGI, u4Bw, u4User0Nss, u4User1Nss, u4User2Nss, u4User3Nss; + UINT_32 u4GroupId, u4User0UP, u4User1UP, u4User2UP, u4User3UP; + UINT_32 u4User0MuPfId, u4User1MuPfId, u4User2MuPfId, u4User3MuPfId; + UINT_32 u4User0InitMCS, u4User1InitMCS, u4User2InitMCS, u4User3InitMCS; + UINT_8 ucAddr1[MAC_ADDR_LEN], ucAddr2[MAC_ADDR_LEN], ucAddr3[MAC_ADDR_LEN], ucAddr4[MAC_ADDR_LEN]; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&u4GroupIndex, HqaCmdFrame->Data + 4 * 0, 4); + u4GroupIndex = ntohl(u4GroupIndex); + memcpy(&u4NumOfUser, HqaCmdFrame->Data + 4 * 1, 4); + u4NumOfUser = ntohl(u4NumOfUser); + memcpy(&u4User0Ldpc, HqaCmdFrame->Data + 4 * 2, 4); + u4User0Ldpc = ntohl(u4User0Ldpc); + memcpy(&u4User1Ldpc, HqaCmdFrame->Data + 4 * 3, 4); + u4User1Ldpc = ntohl(u4User1Ldpc); + memcpy(&u4User2Ldpc, HqaCmdFrame->Data + 4 * 4, 4); + u4User2Ldpc = ntohl(u4User2Ldpc); + memcpy(&u4User3Ldpc, HqaCmdFrame->Data + 4 * 5, 4); + u4User3Ldpc = ntohl(u4User3Ldpc); + memcpy(&u4ShortGI, HqaCmdFrame->Data + 4 * 6, 4); + u4ShortGI = ntohl(u4ShortGI); + memcpy(&u4Bw, HqaCmdFrame->Data + 4 * 7, 4); + u4Bw = ntohl(u4Bw); + memcpy(&u4User0Nss, HqaCmdFrame->Data + 4 * 8, 4); + u4User0Nss = ntohl(u4User0Nss); + memcpy(&u4User1Nss, HqaCmdFrame->Data + 4 * 9, 4); + u4User1Nss = ntohl(u4User1Nss); + memcpy(&u4User2Nss, HqaCmdFrame->Data + 4 * 10, 4); + u4User2Nss = ntohl(u4User2Nss); + memcpy(&u4User3Nss, HqaCmdFrame->Data + 4 * 11, 4); + u4User3Nss = ntohl(u4User3Nss); + memcpy(&u4GroupId, HqaCmdFrame->Data + 4 * 12, 4); + u4GroupId = ntohl(u4GroupId); + memcpy(&u4User0UP, HqaCmdFrame->Data + 4 * 13, 4); + u4User0UP = ntohl(u4User0UP); + memcpy(&u4User1UP, HqaCmdFrame->Data + 4 * 14, 4); + u4User1UP = ntohl(u4User1UP); + memcpy(&u4User2UP, HqaCmdFrame->Data + 4 * 15, 4); + u4User2UP = ntohl(u4User2UP); + memcpy(&u4User3UP, HqaCmdFrame->Data + 4 * 16, 4); + u4User3UP = ntohl(u4User3UP); + memcpy(&u4User0MuPfId, HqaCmdFrame->Data + 4 * 17, 4); + u4User0MuPfId = ntohl(u4User0MuPfId); + memcpy(&u4User1MuPfId, HqaCmdFrame->Data + 4 * 18, 4); + u4User1MuPfId = ntohl(u4User1MuPfId); + memcpy(&u4User2MuPfId, HqaCmdFrame->Data + 4 * 19, 4); + u4User2MuPfId = ntohl(u4User2MuPfId); + memcpy(&u4User3MuPfId, HqaCmdFrame->Data + 4 * 20, 4); + u4User3MuPfId = ntohl(u4User3MuPfId); + memcpy(&u4User0InitMCS, HqaCmdFrame->Data + 4 * 21, 4); + u4User0InitMCS = ntohl(u4User0InitMCS); + memcpy(&u4User1InitMCS, HqaCmdFrame->Data + 4 * 22, 4); + u4User1InitMCS = ntohl(u4User1InitMCS); + memcpy(&u4User2InitMCS, HqaCmdFrame->Data + 4 * 23, 4); + u4User2InitMCS = ntohl(u4User2InitMCS); + memcpy(&u4User3InitMCS, HqaCmdFrame->Data + 4 * 24, 4); + u4User3InitMCS = ntohl(u4User3InitMCS); + + memcpy(ucAddr1, HqaCmdFrame->Data + 4 * 25, 6); + memcpy(ucAddr2, HqaCmdFrame->Data + 4 * 25 + 6 * 1, 6); + memcpy(ucAddr3, HqaCmdFrame->Data + 4 * 25 + 6 * 2, 6); + memcpy(ucAddr4, HqaCmdFrame->Data + 4 * 25 + 6 * 3, 6); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + if (kalSprintf(prInBuf, + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + u4GroupIndex, u4NumOfUser, u4User0Ldpc, u4User1Ldpc, u4ShortGI, u4Bw, u4User0Nss, u4User1Nss, + u4GroupId, u4User0UP, u4User1UP, u4User0MuPfId, u4User1MuPfId, u4User0InitMCS, u4User1InitMCS, + ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], ucAddr1[4], ucAddr1[5], ucAddr2[0], ucAddr2[1], + ucAddr2[2], ucAddr2[3], ucAddr2[4], ucAddr2[5]) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUSetGroup(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_MUGetQD(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4SubIdx = 0; + + /* TODO */ + UINT_32 u4User0InitMCS = 0; + UINT_32 u4User1InitMCS = 0; + UINT_32 u4User2InitMCS = 0; + UINT_32 u4User3InitMCS = 0; + + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&u4SubIdx, HqaCmdFrame->Data, 4); + u4SubIdx = ntohl(u4SubIdx); + + kalMemSet(prInBuf, 0, sizeof(u4SubIdx)); + if (kalSprintf(prInBuf, "%u", u4SubIdx) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUGetQD(prNetDev, prInBuf); + + /* TODO */ + u4User0InitMCS = ntohl(u4User0InitMCS); + u4User1InitMCS = ntohl(u4User1InitMCS); + u4User2InitMCS = ntohl(u4User2InitMCS); + u4User3InitMCS = ntohl(u4User3InitMCS); + + memcpy(HqaCmdFrame->Data + 2, &u4User0InitMCS, sizeof(UINT_32)); + memcpy(HqaCmdFrame->Data + 2 + 1 * sizeof(UINT_32), &u4User1InitMCS, sizeof(UINT_32)); + memcpy(HqaCmdFrame->Data + 2 + 2 * sizeof(UINT_32), &u4User2InitMCS, sizeof(UINT_32)); + memcpy(HqaCmdFrame->Data + 2 + 3 * sizeof(UINT_32), &u4User3InitMCS, sizeof(UINT_32)); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_MUSetEnable(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Enable = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&u4Enable, HqaCmdFrame->Data + 4 * 0, 4); + u4Enable = ntohl(u4Enable); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + if (kalSprintf(prInBuf, "%02x", u4Enable) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUSetEnable(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_MUSetGID_UP(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 au4Gid[2]; + UINT_32 au4Up[4]; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&au4Gid[0], HqaCmdFrame->Data + 4 * 0, 4); + au4Gid[0] = ntohl(au4Gid[0]); + memcpy(&au4Gid[1], HqaCmdFrame->Data + 4 * 1, 4); + au4Gid[1] = ntohl(au4Gid[1]); + memcpy(&au4Up[0], HqaCmdFrame->Data + 4 * 2, 4); + au4Up[0] = ntohl(au4Up[0]); + memcpy(&au4Up[1], HqaCmdFrame->Data + 4 * 3, 4); + au4Up[1] = ntohl(au4Up[1]); + memcpy(&au4Up[2], HqaCmdFrame->Data + 4 * 4, 4); + au4Up[2] = ntohl(au4Up[2]); + memcpy(&au4Up[3], HqaCmdFrame->Data + 4 * 5, 4); + au4Up[3] = ntohl(au4Up[3]); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + if (kalSprintf(prInBuf, "%02x:%02x:%02x:%02x:%02x:%02x", au4Gid[0], au4Gid[1], au4Up[0], au4Up[1], au4Up[2], + au4Up[3]) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUSetGID_UP(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_MUTriggerTx(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4BandIdx, u4IsRandomPattern; + UINT_32 u4MsduPayloadLength0, u4MsduPayloadLength1, u4MsduPayloadLength2, u4MsduPayloadLength3; + UINT_32 u4MuPacketCount, u4NumOfSTAs; + UINT_8 ucAddr1[MAC_ADDR_LEN], ucAddr2[MAC_ADDR_LEN], ucAddr3[MAC_ADDR_LEN], ucAddr4[MAC_ADDR_LEN]; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + if (!prInBuf) { + DBGLOG(RFTEST, ERROR, "allocate memory failed\n"); + return -1; + } + + memcpy(&u4BandIdx, HqaCmdFrame->Data + 4 * 0, 4); + u4BandIdx = ntohl(u4BandIdx); + memcpy(&u4IsRandomPattern, HqaCmdFrame->Data + 4 * 1, 4); + u4IsRandomPattern = ntohl(u4IsRandomPattern); + memcpy(&u4MsduPayloadLength0, HqaCmdFrame->Data + 4 * 2, 4); + u4MsduPayloadLength0 = ntohl(u4MsduPayloadLength0); + memcpy(&u4MsduPayloadLength1, HqaCmdFrame->Data + 4 * 3, 4); + u4MsduPayloadLength1 = ntohl(u4MsduPayloadLength1); + memcpy(&u4MsduPayloadLength2, HqaCmdFrame->Data + 4 * 4, 4); + u4MsduPayloadLength2 = ntohl(u4MsduPayloadLength2); + memcpy(&u4MsduPayloadLength3, HqaCmdFrame->Data + 4 * 5, 4); + u4MsduPayloadLength3 = ntohl(u4MsduPayloadLength3); + memcpy(&u4MuPacketCount, HqaCmdFrame->Data + 4 * 6, 4); + u4MuPacketCount = ntohl(u4MuPacketCount); + memcpy(&u4NumOfSTAs, HqaCmdFrame->Data + 4 * 7, 4); + u4NumOfSTAs = ntohl(u4NumOfSTAs); + memcpy(ucAddr1, HqaCmdFrame->Data + 4 * 8, 6); + memcpy(ucAddr2, HqaCmdFrame->Data + 4 * 8 + 6 * 1, 6); + memcpy(ucAddr3, HqaCmdFrame->Data + 4 * 8 + 6 * 2, 6); + memcpy(ucAddr4, HqaCmdFrame->Data + 4 * 8 + 6 * 3, 6); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + if (kalSprintf(prInBuf, + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + u4IsRandomPattern, u4MsduPayloadLength0, u4MsduPayloadLength1, u4MuPacketCount, u4NumOfSTAs, + ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], ucAddr1[4], ucAddr1[5], + ucAddr2[0], ucAddr2[1], ucAddr2[2], ucAddr2[3], ucAddr2[4], ucAddr2[5]) < 0) { + kfree(prInBuf); + return -1; + } + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUTriggerTx(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_TXMU_CMDS[] = { + HQA_MUGetInitMCS, /* 0x1560 */ + HQA_MUCalInitMCS, /* 0x1561 */ + HQA_MUCalLQ, /* 0x1562 */ + HQA_MUGetLQ, /* 0x1563 */ + HQA_MUSetSNROffset, /* 0x1564 */ + HQA_MUSetZeroNss, /* 0x1565 */ + HQA_MUSetSpeedUpLQ, /* 0x1566 */ + HQA_MUSetMUTable, /* 0x1567 */ + HQA_MUSetGroup, /* 0x1568 */ + HQA_MUGetQD, /* 0x1569 */ + HQA_MUSetEnable, /* 0x156A */ + HQA_MUSetGID_UP, /* 0x156B */ + HQA_MUTriggerTx, /* 0x156C */ +}; +#endif +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For ICAP +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_CapWiFiSpectrum(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 u4BufLen = 0; + UINT_32 u4Control = 0; + UINT_32 u4Trigger = 0; + UINT_32 u4RingCapEn = 0; + UINT_32 u4TriggerEvent = 0; + UINT_32 u4CaptureNode = 0; + static UINT_32 u4CaptureLen; + UINT_32 u4CapStopCycle = 0; + UINT_32 u4BW = 0; +/* UINT_32 u4MacTriggerEvent = 0; */ /* Temp unused */ +/* UINT_32 u4TriggerMac = 0; */ /* Temp unused */ + UINT_32 u4WFNum; + UINT_32 u4IQ; + UINT_32 u4TempLen = 0; + UINT_32 u4DataLen; + INT_32 i = 0, i4Ret = 0; + INT_32 *prIQAry; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memcpy((PUCHAR) & u4Control, HqaCmdFrame->Data + 4 * 0, 4); + u4Control = ntohl(u4Control); + memcpy((PUCHAR) & u4Trigger, HqaCmdFrame->Data + 4 * 1, 4); + u4Trigger = ntohl(u4Trigger); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_CapWiFiSpectrum u4Control = %d\n", u4Control); + + if (u4Control == 1 && u4Trigger == 1) { + memcpy((PUCHAR) & u4RingCapEn, HqaCmdFrame->Data + 4 * 2, 4); + u4RingCapEn = ntohl(u4RingCapEn); + memcpy((PUCHAR) & u4TriggerEvent, HqaCmdFrame->Data + 4 * 3, 4); + u4TriggerEvent = ntohl(u4TriggerEvent); + memcpy((PUCHAR) & u4CaptureNode, HqaCmdFrame->Data + 4 * 4, 4); + u4CaptureNode = ntohl(u4CaptureNode); + memcpy((PUCHAR) & u4CaptureLen, HqaCmdFrame->Data + 4 * 5, 4); + u4CaptureLen = ntohl(u4CaptureLen); + memcpy((PUCHAR) & u4CapStopCycle, HqaCmdFrame->Data + 4 * 6, 4); + u4CapStopCycle = ntohl(u4CapStopCycle); + memcpy((PUCHAR) & u4BW, HqaCmdFrame->Data + 4 * 7, 4); + u4BW = ntohl(u4BW); + + /* AT Command #1, Trigger always = 1 */ + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_CapWiFiSpectrum u4Trigger=%u, u4RingCapEn=%u, u4TriggerEvent=%u\n", + u4Trigger, u4RingCapEn, u4TriggerEvent); + DBGLOG(RFTEST, INFO, " QA_AGENT u4CaptureNode=%u, u4CaptureLen=%u, u4CapStopCycle=%u, u4BW=%u\n", + u4CaptureNode, u4CaptureLen, u4CapStopCycle, u4BW); + + memset(&g_au4I0Data[0][0], 0, 408000);/* ming-chih add */ + memset(&g_au4Q0Data[0][0], 0, 408000);/* ming-chih add */ + + /* iwpriv wlan205 set_test_cmd 75 0 (J mode Setting) */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_J_MODE; + rRfATInfo.u4FuncData = 0; + + DBGLOG(RFTEST, INFO, " Index = RF_AT_FUNCID_SET_J_MODE u4FuncData = %d\n", rRfATInfo.u4FuncData); + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + /* iwpriv wlan205 set_test_cmd 71 0 (Channel Bandwidth) */ + if (u4BW == 4) + u4BW = 3; + else if (u4BW == 3) + u4BW = 4; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_CBW; + rRfATInfo.u4FuncData = u4BW; + + DBGLOG(RFTEST, INFO, " Index = RF_AT_FUNCID_SET_CBW u4FuncData = %d\n", rRfATInfo.u4FuncData); + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + /* iwpriv wlan205 set_test_cmd 24 0 (ADC clock mode) */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_ADC_CLK_MODE; + rRfATInfo.u4FuncData = 0; + + DBGLOG(RFTEST, INFO, " Index = RF_AT_FUNCID_ADC_CLK_MODE u4FuncData = %d\n", rRfATInfo.u4FuncData); + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + /* iwpriv wlan205 set_test_cmd 84 18000 (Internal Capture Trigger Offset) */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ICAP_TRIGGER_OFFSET; + rRfATInfo.u4FuncData = u4CapStopCycle; + + DBGLOG(RFTEST, INFO, " Index = RF_AT_FUNCID_SET_ICAP_TRIGGER_OFFSET u4FuncData = %d\n", + rRfATInfo.u4FuncData); + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + if (u4CaptureLen == 0) + u4CaptureLen = 196615;/* 24000; */ + /* iwpriv wlan205 set_test_cmd 83 24576 (Internal Capture Size) */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ICAP_SIZE; + rRfATInfo.u4FuncData = u4CaptureLen; + + DBGLOG(RFTEST, INFO, " Index = RF_AT_FUNCID_SET_ICAP_SIZE u4FuncData = %d\n", rRfATInfo.u4FuncData); + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + /* iwpriv wlan205 set_test_cmd 80 0 (Internal Capture Content) */ + if (u4CaptureNode == 0x6) + u4CaptureNode = ICAP_CONTENT_ADC;/*0;*//*0x10000006;*/ + else if (u4CaptureNode == 0x8) + u4CaptureNode = ICAP_CONTENT_FIIQ;/*2;*//*0x49;*/ + else if (u4CaptureNode == 0x9) + u4CaptureNode = ICAP_CONTENT_FDIQ;/*3;*//*0x48;*/ + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ICAP_CONTENT; + rRfATInfo.u4FuncData = u4CaptureNode; + + DBGLOG(RFTEST, INFO, " Index = RF_AT_FUNCID_SET_ICAP_CONTENT u4FuncData = %d\n", + rRfATInfo.u4FuncData); + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + /* iwpriv wlan205 set_test_cmd 81 0 (Internal Capture Trigger mode) */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ICAP_MODE; + rRfATInfo.u4FuncData = u4TriggerEvent; + + DBGLOG(RFTEST, INFO, " Index = RF_AT_FUNCID_SET_ICAP_MODE u4FuncData = %d\n", rRfATInfo.u4FuncData); + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ICAP_RING; + rRfATInfo.u4FuncData = u4RingCapEn; + + DBGLOG(RFTEST, INFO, " Index = RF_AT_FUNCID_SET_ICAP_RING u4FuncData = %d\n", rRfATInfo.u4FuncData); + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + /* iwpriv wlan205 set_test_cmd 1 13 */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_CH_SWITCH_FOR_ICAP; + + DBGLOG(RFTEST, INFO, " Index = RF_AT_FUNCID_COMMAND u4FuncData = %d\n", rRfATInfo.u4FuncData); + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + /* iwpriv wlan205 set_test_cmd 1 11 */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_ICAP; + + DBGLOG(RFTEST, INFO, " Index = RF_AT_FUNCID_COMMAND u4FuncData = %d\n", rRfATInfo.u4FuncData); + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + } else if (u4Control == 2) { + if (g_bCaptureDone) { + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_CapWiFiSpectrum Done!!!!!!!!!!!!!!!!!\n"); + i4Ret = 0; + /* Query whether ICAP Done */ + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + } else { + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_CapWiFiSpectrum Wait!!!!!!!!!!!!!!!!!\n"); + i4Ret = 1; + /* Query whether ICAP Done */ + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + } + } else if (u4Control == 3) { + memcpy((PUCHAR) & u4WFNum, HqaCmdFrame->Data + 4 * 1, 4); + u4WFNum = ntohl(u4WFNum); + memcpy((PUCHAR) & u4IQ, HqaCmdFrame->Data + 4 * 2, 4); + u4IQ = ntohl(u4IQ); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_CapWiFiSpectrum u4WFNum = %u, u4IQ = %u\n", u4WFNum, u4IQ); + + if (u4WFNum <= 1) { + GetIQData(&prIQAry, &u4DataLen, u4IQ, u4WFNum); + u4TempLen = u4DataLen; + u4DataLen /= 4; + + u4Control = ntohl(u4Control); + memcpy(HqaCmdFrame->Data + 2 + 4 * 0, (UCHAR *) &u4Control, sizeof(u4Control)); + u4WFNum = ntohl(u4WFNum); + memcpy(HqaCmdFrame->Data + 2 + 4 * 1, (UCHAR *) &u4WFNum, sizeof(u4WFNum)); + u4IQ = ntohl(u4IQ); + memcpy(HqaCmdFrame->Data + 2 + 4 * 2, (UCHAR *) &u4IQ, sizeof(u4IQ)); + u4DataLen = ntohl(u4DataLen); + memcpy(HqaCmdFrame->Data + 2 + 4 * 3, (UCHAR *) &u4DataLen, sizeof(u4DataLen)); + + for (i = 0; i < u4TempLen/sizeof(UINT_32); i++) + prIQAry[i] = ntohl(prIQAry[i]); + + memcpy(HqaCmdFrame->Data + 2 + 4 * 4, (UCHAR *) &prIQAry[0], u4TempLen); + } else { + u4TempLen = 0; + } + + /* Get IQ Data and transmit them to UI DLL */ + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + 4 * 4 + u4TempLen, i4Ret); + } else { + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + } + return 0/*-EFAULT*/; +} + +static HQA_CMD_HANDLER HQA_ICAP_CMDS[] = { + HQA_CapWiFiSpectrum, /* 0x1580 */ +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 hqa_set_channel_ext(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Ext_id = 0; + UINT_32 u4Param_num = 0; + UINT_32 u4Band_idx = 0; + UINT_32 u4Central_ch0 = 0; + UINT_32 u4Central_ch1 = 0; + UINT_32 u4Sys_bw = 0; + UINT_32 u4Perpkt_bw = 0; + UINT_32 u4Pri_sel = 0; + UINT_32 u4Reason = 0; + UINT_32 u4Ch_band = 0; + UINT_32 u4SetFreq = 0; + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4Param_num, HqaCmdFrame->Data + 4 * 1, 4); + u4Param_num = ntohl(u4Param_num); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 2, 4); + u4Band_idx = ntohl(u4Band_idx); + memcpy(&u4Central_ch0, HqaCmdFrame->Data + 4 * 3, 4); + u4Central_ch0 = ntohl(u4Central_ch0); + memcpy(&u4Central_ch1, HqaCmdFrame->Data + 4 * 4, 4); + u4Central_ch1 = ntohl(u4Central_ch1); + memcpy(&u4Sys_bw, HqaCmdFrame->Data + 4 * 5, 4); + u4Sys_bw = ntohl(u4Sys_bw); + memcpy(&u4Perpkt_bw, HqaCmdFrame->Data + 4 * 6, 4); + u4Perpkt_bw = ntohl(u4Perpkt_bw); + memcpy(&u4Pri_sel, HqaCmdFrame->Data + 4 * 7, 4); + u4Pri_sel = ntohl(u4Pri_sel); + memcpy(&u4Reason, HqaCmdFrame->Data + 4 * 8, 4); + u4Reason = ntohl(u4Reason); + memcpy(&u4Ch_band, HqaCmdFrame->Data + 4 * 9, 4); + u4Ch_band = ntohl(u4Ch_band); + + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_set_channel_ext ext_id : %d\n", u4Ext_id); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_set_channel_ext param_num : %d\n", u4Param_num); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_set_channel_ext band_idx : %d\n", u4Band_idx); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_set_channel_ext central_ch0 : %d\n", u4Central_ch0); + /* for BW80+80 */ + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_set_channel_ext central_ch1 : %d\n", u4Central_ch1); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_set_channel_ext sys_bw : %d\n", u4Sys_bw); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_set_channel_ext perpkt_bw : %d\n", u4Perpkt_bw); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_set_channel_ext pri_sel : %d\n", u4Pri_sel); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_set_channel_ext reason : %d\n", u4Reason); + /* 0:2.4G 1:5G */ + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_set_channel_ext ch_band : %d\n", u4Ch_band); + + /* BW Mapping in QA Tool + * 0: BW20 + * 1: BW40 + * 2: BW80 + * 3: BW10 + * 4: BW5 + * 5: BW160C + * 6: BW160NC + */ + /* BW Mapping in FW + * 0: BW20 + * 1: BW40 + * 2: BW80 + * 3: BW160C + * 4: BW160NC + * 5: BW5 + * 6: BW10 + */ + /* For POR Cal Setting - 20160601 */ + if ((u4Central_ch0 == u4Central_ch1) && (u4Sys_bw == 6) && (u4Perpkt_bw == 6)) { + DBGLOG(RFTEST, INFO, " Wrong Setting for POR Cal\n"); + goto exit; + } + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + if ((u4Central_ch0 >= 7 && u4Central_ch0 <= 16) && u4Ch_band == 1) { + /*Ch7 - Ch12, 5G (5035-5060)*/ + u4SetFreq = 1000 * (5000 + u4Central_ch0 * 5); + } else if (u4Central_ch0 == 6 && u4Ch_band == 1) { + u4SetFreq = 1000 * 5032; + } else { + u4SetFreq = nicChannelNum2Freq(u4Central_ch0); + } + MT_ATESetChannel(prNetDev, 0, u4SetFreq); + + if (u4Sys_bw == 6) { + u4SetFreq = nicChannelNum2Freq(u4Central_ch1); + MT_ATESetChannel(prNetDev, 1, u4SetFreq); + } + + MT_ATESetSystemBW(prNetDev, u4Sys_bw); + + /* For POR Cal Setting - 20160601 */ + if ((u4Sys_bw == 6) && (u4Perpkt_bw == 6)) + MT_ATESetPerPacketBW(prNetDev, 5); + else + MT_ATESetPerPacketBW(prNetDev, u4Perpkt_bw); + MT_ATEPrimarySetting(prNetDev, u4Pri_sel); + /* PeiHsuan Memo : No Set Reason ? */ + MT_ATESetBand(prNetDev, u4Ch_band); + +exit: + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (UCHAR *) &u4Ext_id, sizeof(u4Ext_id)); + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 hqa_set_txcontent_ext(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Len = 0; + UINT_32 u4Ext_id = 0; + UINT_32 u4Param_num = 0; + UINT_32 u4Band_idx = 0; + UINT_32 u4FC = 0; + UINT_32 u4Dur = 0; + UINT_32 u4Seq = 0; + UINT_32 u4Gen_payload_rule = 0; + UINT_32 u4Txlen = 0; + UINT_32 u4Payload_len = 0; + UINT_8 ucAddr1[MAC_ADDR_LEN]; + UINT_8 ucAddr2[MAC_ADDR_LEN]; + UINT_8 ucAddr3[MAC_ADDR_LEN]; + UINT_32 ucPayload = 0; + + u4Len = ntohs(HqaCmdFrame->Length); + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4Param_num, HqaCmdFrame->Data + 4 * 1, 4); + u4Param_num = ntohl(u4Param_num); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 2, 4); + u4Band_idx = ntohl(u4Band_idx); + memcpy(&u4FC, HqaCmdFrame->Data + 4 * 3, 4); + u4FC = ntohl(u4FC); + memcpy(&u4Dur, HqaCmdFrame->Data + 4 * 4, 4); + u4Dur = ntohl(u4Dur); + memcpy(&u4Seq, HqaCmdFrame->Data + 4 * 5, 4); + u4Seq = ntohl(u4Seq); + memcpy(&u4Gen_payload_rule, HqaCmdFrame->Data + 4 * 6, 4); + u4Gen_payload_rule = ntohl(u4Gen_payload_rule); + memcpy(&u4Txlen, HqaCmdFrame->Data + 4 * 7, 4); + u4Txlen = ntohl(u4Txlen); + memcpy(&u4Payload_len, HqaCmdFrame->Data + 4 * 8, 4); + u4Payload_len = ntohl(u4Payload_len); + memcpy(ucAddr1, HqaCmdFrame->Data + 4 * 9, 6); + memcpy(ucAddr2, HqaCmdFrame->Data + 4 * 9 + 6 * 1, 6); + memcpy(ucAddr3, HqaCmdFrame->Data + 4 * 9 + 6 * 2, 6); + memcpy(&ucPayload, HqaCmdFrame->Data + 4 * 9 + 6 * 3, 1); + + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_set_txcontent_ext ext_id : %d\n", u4Ext_id); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_set_txcontent_ext param_num : %d\n", u4Param_num); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_set_txcontent_ext band_idx : %d\n", u4Band_idx); + /* Frame Control...0800 : Beacon */ + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_set_txcontent_ext FC : 0x%x\n", u4FC); + /* Duration....NAV */ + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_set_txcontent_ext dur : 0x%x\n", u4Dur); + /* Sequence Control */ + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_set_txcontent_ext seq : 0x%x\n", u4Seq); + /* Normal:0,Repeat:1,Random:2 */ + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_set_txcontent_ext gen_payload_rule : %d\n", u4Gen_payload_rule); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_set_txcontent_ext txlen : %d\n", u4Txlen); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_set_txcontent_ext payload_len : %d\n", u4Payload_len); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_set_txcontent_ext addr1:%02x:%02x:%02x:%02x:%02x:%02x\n", + ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], ucAddr1[4], ucAddr1[5]); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_set_txcontent_ext addr2:%02x:%02x:%02x:%02x:%02x:%02x\n", + ucAddr2[0], ucAddr2[1], ucAddr2[2], ucAddr2[3], ucAddr2[4], ucAddr2[5]); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_set_txcontent_ext addr3:%02x:%02x:%02x:%02x:%02x:%02x\n", + ucAddr3[0], ucAddr3[1], ucAddr3[2], ucAddr3[3], ucAddr3[4], ucAddr3[5]); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_start_tx_ext payload : 0x%x\n", ucPayload); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + MT_ATESetMacHeader(prNetDev, u4FC, u4Dur, u4Seq); + MT_ATESetTxPayLoad(prNetDev, u4Gen_payload_rule, ucPayload); + MT_ATESetTxLength(prNetDev, u4Txlen); + MT_ATESetMACAddress(prNetDev, RF_AT_FUNCID_SET_MAC_ADDRESS, ucAddr1); + MT_ATESetMACAddress(prNetDev, RF_AT_FUNCID_SET_TA, ucAddr2); + /* PeiHsuan Memo : No Set Addr3 */ + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (UCHAR *) &u4Ext_id, sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + sizeof(u4Ext_id), i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 hqa_start_tx_ext(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Ext_id = 0; + UINT_32 u4Param_num = 0; + UINT_32 u4Band_idx = 0; + UINT_32 u4Pkt_cnt = 0; + UINT_32 u4Phymode = 0; + UINT_32 u4Rate = 0; + UINT_32 u4Pwr = 0; + UINT_32 u4Stbc = 0; + UINT_32 u4Ldpc = 0; + UINT_32 u4iBF = 0; + UINT_32 u4eBF = 0; + UINT_32 u4Wlan_id = 0; + UINT_32 u4Aifs = 0; + UINT_32 u4Gi = 0; + UINT_32 u4Tx_path = 0; + UINT_32 u4Nss = 0; + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4Param_num, HqaCmdFrame->Data + 4 * 1, 4); + u4Param_num = ntohl(u4Param_num); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 2, 4); + u4Band_idx = ntohl(u4Band_idx); + memcpy(&u4Pkt_cnt, HqaCmdFrame->Data + 4 * 3, 4); + u4Pkt_cnt = ntohl(u4Pkt_cnt); + memcpy(&u4Phymode, HqaCmdFrame->Data + 4 * 4, 4); + u4Phymode = ntohl(u4Phymode); + memcpy(&u4Rate, HqaCmdFrame->Data + 4 * 5, 4); + u4Rate = ntohl(u4Rate); + memcpy(&u4Pwr, HqaCmdFrame->Data + 4 * 6, 4); + u4Pwr = ntohl(u4Pwr); + memcpy(&u4Stbc, HqaCmdFrame->Data + 4 * 7, 4); + u4Stbc = ntohl(u4Stbc); + memcpy(&u4Ldpc, HqaCmdFrame->Data + 4 * 8, 4); + u4Ldpc = ntohl(u4Ldpc); + memcpy(&u4iBF, HqaCmdFrame->Data + 4 * 9, 4); + u4iBF = ntohl(u4iBF); + memcpy(&u4eBF, HqaCmdFrame->Data + 4 * 10, 4); + u4eBF = ntohl(u4eBF); + memcpy(&u4Wlan_id, HqaCmdFrame->Data + 4 * 11, 4); + u4Wlan_id = ntohl(u4Wlan_id); + memcpy(&u4Aifs, HqaCmdFrame->Data + 4 * 12, 4); + u4Aifs = ntohl(u4Aifs); + memcpy(&u4Gi, HqaCmdFrame->Data + 4 * 13, 4); + u4Gi = ntohl(u4Gi); + memcpy(&u4Tx_path, HqaCmdFrame->Data + 4 * 14, 4); + u4Tx_path = ntohl(u4Tx_path); + memcpy(&u4Nss, HqaCmdFrame->Data + 4 * 15, 4); + u4Nss = ntohl(u4Nss); + + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_start_tx_ext ext_id : %d\n", u4Ext_id); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_start_tx_ext param_num : %d\n", u4Param_num); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_start_tx_ext band_idx : %d\n", u4Band_idx); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_start_tx_ext pkt_cnt : %d\n", u4Pkt_cnt); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_start_tx_ext phymode : %d\n", u4Phymode); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_start_tx_ext rate : %d\n", u4Rate); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_start_tx_ext pwr : %d\n", u4Pwr); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_start_tx_ext stbc : %d\n", u4Stbc); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_start_tx_ext ldpc : %d\n", u4Ldpc); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_start_tx_ext ibf : %d\n", u4iBF); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_start_tx_ext ebf : %d\n", u4eBF); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_start_tx_ext wlan_id : %d\n", u4Wlan_id); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_start_tx_ext aifs : %d\n", u4Aifs); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_start_tx_ext gi : %d\n", u4Gi); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_start_tx_ext tx_path : %d\n", u4Tx_path); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_start_tx_ext nss : %d\n", u4Nss); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + MT_ATESetTxCount(prNetDev, u4Pkt_cnt); + +#if 1 + if (u4Phymode == 1) { + u4Phymode = 0; + u4Rate += 4; + } else if ((u4Phymode == 0) && ((u4Rate == 9) || (u4Rate == 10) || (u4Rate == 11))) + u4Phymode = 1; + MT_ATESetPreamble(prNetDev, u4Phymode); + + if (u4Phymode == 0) { + u4Rate |= 0x00000000; + + DBGLOG(RFTEST, INFO, " QA_AGENT CCK/OFDM (normal preamble) rate : %d\n", u4Rate); + + MT_ATESetRate(prNetDev, u4Rate); + } else if (u4Phymode == 1) { + if (u4Rate == 9) + u4Rate = 1; + else if (u4Rate == 10) + u4Rate = 2; + else if (u4Rate == 11) + u4Rate = 3; + u4Rate |= 0x00000000; + + DBGLOG(RFTEST, INFO, " QA_AGENT CCK (short preamble) rate : %d\n", u4Rate); + + MT_ATESetRate(prNetDev, u4Rate); + } else if (u4Phymode >= 2 && u4Phymode <= 4) { + u4Rate |= 0x80000000; + + DBGLOG(RFTEST, INFO, " QA_AGENT HT/VHT rate : %d\n", u4Rate); + + MT_ATESetRate(prNetDev, u4Rate); + } +#endif + + MT_ATESetTxPower0(prNetDev, u4Pwr); + MT_ATESetTxSTBC(prNetDev, u4Stbc); + MT_ATESetEncodeMode(prNetDev, u4Ldpc); + MT_ATESetiBFEnable(prNetDev, u4iBF); + MT_ATESeteBFEnable(prNetDev, u4eBF); + /* PeiHsuan Memo : No Set Wlan ID */ + MT_ATESetTxIPG(prNetDev, u4Aifs); + MT_ATESetTxGi(prNetDev, u4Gi); + MT_ATESetTxVhtNss(prNetDev, u4Nss); + MT_ATESetTxPath(prNetDev, u4Tx_path); + MT_ATEStartTX(prNetDev, "TXFRAME"); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (UCHAR *) &u4Ext_id, sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + sizeof(u4Ext_id), i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 hqa_start_rx_ext(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Ext_id = 0; + UINT_32 u4Param_num = 0; + UINT_32 u4Band_idx = 0; + UINT_32 u4Rx_path = 0; + UCHAR ucOwn_mac[MAC_ADDR_LEN]; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 u4BufLen = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memcpy(&u4Ext_id, HqaCmdFrame->Data, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4Param_num, HqaCmdFrame->Data + 4, 4); + u4Param_num = ntohl(u4Param_num); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 + 4, 4); + u4Band_idx = ntohl(u4Band_idx); + memcpy(ucOwn_mac, HqaCmdFrame->Data + 4 + 4 + 4, 6); + memcpy(&u4Rx_path, HqaCmdFrame->Data + 4 + 4 + 4 + 6, 4); + u4Rx_path = ntohl(u4Rx_path); + + memset(&g_HqaRxStat, 0, sizeof(PARAM_RX_STAT_T)); + + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_start_rx_ext ext_id : %d\n", u4Ext_id); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_start_rx_ext param_num : %d\n", u4Param_num); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_start_rx_ext band_idx : %d\n", u4Band_idx); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_start_rx_ext own_mac:%02x:%02x:%02x:%02x:%02x:%02x\n", + ucOwn_mac[0], ucOwn_mac[1], ucOwn_mac[2], ucOwn_mac[3], ucOwn_mac[4], ucOwn_mac[5]); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_start_rx_ext rx_path : 0x%x\n", u4Rx_path); + + u4RxStatSeqNum = 0; + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_RX_PATH; + rRfATInfo.u4FuncData = u4Rx_path << 16 | u4Band_idx; + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + /* PeiHsuan Memo : No Set Own MAC Address */ + MT_ATEStartRX(prNetDev, "RXFRAME"); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (UCHAR *) &u4Ext_id, sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + sizeof(u4Ext_id), i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 hqa_stop_tx_ext(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Ext_id = 0; + UINT_32 u4Param_num = 0; + UINT_32 u4Band_idx = 0; + + memcpy(&u4Ext_id, HqaCmdFrame->Data, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4Param_num, HqaCmdFrame->Data + 4, 4); + u4Param_num = ntohl(u4Param_num); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 + 4, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_stop_tx_ext ext_id : %d\n", u4Ext_id); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_stop_tx_ext param_num : %d\n", u4Param_num); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_stop_tx_ext band_idx : %d\n", u4Band_idx); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + MT_ATEStopTX(prNetDev, "TXSTOP"); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (UCHAR *) &u4Ext_id, sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 hqa_stop_rx_ext(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Ext_id = 0; + UINT_32 u4Param_num = 0; + UINT_32 u4Band_idx = 0; + + memcpy(&u4Ext_id, HqaCmdFrame->Data, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4Param_num, HqaCmdFrame->Data + 4, 4); + u4Param_num = ntohl(u4Param_num); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 + 4, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_stop_rx_ext ext_id : %d\n", u4Ext_id); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_stop_rx_ext param_num : %d\n", u4Param_num); + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_stop_rx_ext band_idx : %d\n", u4Band_idx); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + MT_ATEStopRX(prNetDev, "RXSTOP"); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (UCHAR *) &u4Ext_id, sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +static INT_32 HQA_iBFInit(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_iBFInit\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static INT_32 HQA_iBFSetValue(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_iBFSetValue\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static INT_32 HQA_iBFGetStatus(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_iBFGetStatus\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static INT_32 HQA_iBFChanProfUpdate(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_iBFChanProfUpdate\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static INT_32 HQA_iBFProfileRead(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_iBFProfileRead\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static INT_32 HQA_IRRSetADC(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4WFIdx; + UINT_32 u4ChFreq; + UINT_32 u4BW; + UINT_32 u4Sx; + UINT_32 u4Band; + UINT_32 u4Ext_id; + UINT_32 u4RunType; + UINT_32 u4FType; + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4WFIdx, HqaCmdFrame->Data + 4 * 1, 4); + u4WFIdx = ntohl(u4WFIdx); + memcpy(&u4ChFreq, HqaCmdFrame->Data + 4 * 2, 4); + u4ChFreq = ntohl(u4ChFreq); + memcpy(&u4BW, HqaCmdFrame->Data + 4 * 3, 4); + u4BW = ntohl(u4BW); + memcpy(&u4Sx, HqaCmdFrame->Data + 4 * 4, 4); + u4Sx = ntohl(u4Sx); + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 5, 4); + u4Band = ntohl(u4Band); + memcpy(&u4RunType, HqaCmdFrame->Data + 4 * 6, 4); + u4RunType = ntohl(u4RunType); + memcpy(&u4FType, HqaCmdFrame->Data + 4 * 7, 4); + u4FType = ntohl(u4FType); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_IRRSetADC ext_id : %d\n", u4Ext_id); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_IRRSetADC u4WFIdx : %d\n", u4WFIdx); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_IRRSetADC u4ChFreq : %d\n", u4ChFreq); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_IRRSetADC u4BW : %d\n", u4BW); + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_IRRSetADC u4Sx : %d\n", u4Sx); /* SX : 0, 2 */ + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_IRRSetADC u4Band : %d\n", u4Band); + /* RunType : 0 -> QA, 1 -> ATE */ + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_IRRSetADC u4RunType : %d\n", u4RunType); + /* FType : 0 -> FI, 1 -> FD */ + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_IRRSetADC u4FType : %d\n", u4FType); + + i4Ret = MT_ATE_IRRSetADC(prNetDev, u4WFIdx, u4ChFreq, u4BW, u4Sx, u4Band, u4RunType, u4FType); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (UCHAR *) &u4Ext_id, sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +static INT_32 HQA_IRRSetRxGain(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4PgaLpfg; + UINT_32 u4Lna; + UINT_32 u4Band; + UINT_32 u4WF_inx; + UINT_32 u4Rfdgc; + UINT_32 u4Ext_id; + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4PgaLpfg, HqaCmdFrame->Data + 4 * 1, 4); + u4PgaLpfg = ntohl(u4PgaLpfg); + memcpy(&u4Lna, HqaCmdFrame->Data + 4 * 2, 4); + u4Lna = ntohl(u4Lna); + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 3, 4); + u4Band = ntohl(u4Band); + memcpy(&u4WF_inx, HqaCmdFrame->Data + 4 * 4, 4); + u4WF_inx = ntohl(u4WF_inx); + memcpy(&u4Rfdgc, HqaCmdFrame->Data + 4 * 5, 4); + u4Rfdgc = ntohl(u4Rfdgc); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_IRRSetRxGain ext_id : %d\n", u4Ext_id); + /* PGA is for MT663, LPFG is for MT7615 */ + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_IRRSetRxGain u4PgaLpfg : %d\n", u4PgaLpfg); + /* 5 : UH, 4 : H, 3 : M, 2 : L, 1 : UL */ + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_IRRSetRxGain u4Lna : %d\n", u4Lna); + /* DBDC band0 or band1 */ + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_IRRSetRxGain u4Band : %d\n", u4Band); + /* (each bit for each WF) */ + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_IRRSetRxGain u4WF_inx : 0x%x\n", u4WF_inx); + /* only for MT6632 */ + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_IRRSetRxGain u4Rfdgc : %d\n", u4Rfdgc); + + i4Ret = MT_ATE_IRRSetRxGain(prNetDev, u4PgaLpfg, u4Lna, u4Band, u4WF_inx, u4Rfdgc); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (UCHAR *) &u4Ext_id, sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +static INT_32 HQA_IRRSetTTG(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Ext_id; + UINT_32 u4TTGPwrIdx; + UINT_32 u4ChFreq; + UINT_32 u4FIToneFreq; + UINT_32 u4Band; + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4TTGPwrIdx, HqaCmdFrame->Data + 4 * 1, 4); + u4TTGPwrIdx = ntohl(u4TTGPwrIdx); + memcpy(&u4ChFreq, HqaCmdFrame->Data + 4 * 2, 4); + u4ChFreq = ntohl(u4ChFreq); + memcpy(&u4FIToneFreq, HqaCmdFrame->Data + 4 * 3, 4); + u4FIToneFreq = ntohl(u4FIToneFreq); + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 4, 4); + u4Band = ntohl(u4Band); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_IRRSetTTG ext_id : %d\n", u4Ext_id); + /* TTG Power Index: Power index value 0~15 */ + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_IRRSetTTG u4TTGPwrIdx : %d\n", u4TTGPwrIdx); + /* Ch Freq: channel frequency value */ + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_IRRSetTTG u4ChFreq : %d\n", u4ChFreq); + /* FI Tone Freq(float): driver calculate TTG Freq(TTG Freq = Ch_freq + FI tone freq) */ + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_IRRSetTTG u4FIToneFreq : %d\n", u4FIToneFreq); + /* Band: DBDC band0 or band1 */ + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_IRRSetTTG u4Band : %d\n", u4Band); + + i4Ret = MT_ATE_IRRSetTTG(prNetDev, u4TTGPwrIdx, u4ChFreq, u4FIToneFreq, u4Band); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (UCHAR *) &u4Ext_id, sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +static INT_32 HQA_IRRSetTrunOnTTG(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Ext_id; + UINT_32 u4TTGOnOff; + UINT_32 u4Band; + UINT_32 u4WF_inx = 0; + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4TTGOnOff, HqaCmdFrame->Data + 4 * 1, 4); + u4TTGOnOff = ntohl(u4TTGOnOff); + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 2, 4); + u4Band = ntohl(u4Band); + + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_IRRSetTrunOnTTG ext_id : %u\n", u4Ext_id); + /* TTG on/off: 0:off, 1: on */ + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_IRRSetTrunOnTTG u4TTGOnOff : %u\n", u4TTGOnOff); + /* Band: DBDC band0 or band1 */ + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_IRRSetTrunOnTTG u4Band : %u\n", u4Band); + /* (each bit for each WF) */ + DBGLOG(RFTEST, INFO, " QA_AGENT HQA_IRRSetTrunOnTTG u4WF_inx : %u\n", u4WF_inx); + + i4Ret = MT_ATE_IRRSetTrunOnTTG(prNetDev, u4TTGOnOff, u4Band, u4WF_inx); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (UCHAR *) &u4Ext_id, sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +static HQA_CMD_HANDLER hqa_ext_cmd_set[] = { + NULL, + hqa_set_channel_ext, /* 0x00000001 */ + hqa_set_txcontent_ext, /* 0x00000002 */ + hqa_start_tx_ext, /* 0x00000003 */ + hqa_start_rx_ext, /* 0x00000004 */ + hqa_stop_tx_ext, /* 0x00000005 */ + hqa_stop_rx_ext, /* 0x00000006 */ + HQA_iBFInit, /* 0x00000007 */ + HQA_iBFSetValue, /* 0x00000008 */ + HQA_iBFGetStatus, /* 0x00000009 */ + HQA_iBFChanProfUpdate, /* 0x0000000A */ + HQA_iBFProfileRead, /* 0x0000000B */ + ToDoFunction, /* 0x0000000C */ + ToDoFunction, /* 0x0000000D */ + ToDoFunction, /* 0x0000000E */ + ToDoFunction, /* 0x0000000F */ + ToDoFunction, /* 0x00000010 */ + ToDoFunction, /* 0x00000011 */ + ToDoFunction, /* 0x00000012 */ + ToDoFunction, /* 0x00000013 */ + ToDoFunction, /* 0x00000014 */ + ToDoFunction, /* 0x00000015 */ + ToDoFunction, /* 0x00000016 */ + ToDoFunction, /* 0x00000017 */ + ToDoFunction, /* 0x00000018 */ + ToDoFunction, /* 0x00000019 */ + ToDoFunction, /* 0x0000001A */ + ToDoFunction, /* 0x0000001B */ + ToDoFunction, /* 0x0000001C */ + ToDoFunction, /* 0x0000001D */ + ToDoFunction, /* 0x0000001E */ + ToDoFunction, /* 0x0000001F */ + HQA_IRRSetADC, /* 0x00000020 */ + HQA_IRRSetRxGain, /* 0x00000021 */ + HQA_IRRSetTTG, /* 0x00000022 */ + HQA_IRRSetTrunOnTTG, /* 0x00000023 */ +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Extension Commands (For MT7615). +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 hqa_ext_cmds(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + INT_32 i4Idx = 0; + + memmove((PUCHAR) & i4Idx, (PUCHAR) & HqaCmdFrame->Data, 4); + i4Idx = ntohl(i4Idx); + + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_ext_cmds index : %d\n", i4Idx); + + if (hqa_ext_cmd_set[i4Idx] != NULL) + i4Ret = (*hqa_ext_cmd_set[i4Idx]) (prNetDev, prIwReqData, HqaCmdFrame); + else + DBGLOG(RFTEST, INFO, " QA_AGENT hqa_ext_cmds cmd idx %d is not supported\n", i4Idx); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_CMD_SET6[] = { + /* cmd id start from 0x1600 */ + hqa_ext_cmds, /* 0x1600 */ +}; + +static HQA_CMD_TABLE HQA_CMD_TABLES[] = { + { + HQA_CMD_SET0, + sizeof(HQA_CMD_SET0) / sizeof(HQA_CMD_HANDLER), + 0x1000, + } + , + { + HQA_CMD_SET1, + sizeof(HQA_CMD_SET1) / sizeof(HQA_CMD_HANDLER), + 0x1100, + } + , + { + HQA_CMD_SET2, + sizeof(HQA_CMD_SET2) / sizeof(HQA_CMD_HANDLER), + 0x1200, + } + , + { + HQA_CMD_SET3, + sizeof(HQA_CMD_SET3) / sizeof(HQA_CMD_HANDLER), + 0x1300, + } + , + { + HQA_CMD_SET4, + sizeof(HQA_CMD_SET4) / sizeof(HQA_CMD_HANDLER), + 0x1400, + } + , + { + HQA_CMD_SET5, + sizeof(HQA_CMD_SET5) / sizeof(HQA_CMD_HANDLER), + 0x1500, + } + , +#if CFG_SUPPORT_TX_BF + { + HQA_TXBF_CMDS, + sizeof(HQA_TXBF_CMDS) / sizeof(HQA_CMD_HANDLER), + 0x1540, + } + , +#if CFG_SUPPORT_MU_MIMO + { + HQA_TXMU_CMDS, + sizeof(HQA_TXMU_CMDS) / sizeof(HQA_CMD_HANDLER), + 0x1560, + } + , +#endif +#endif + { + HQA_ICAP_CMDS, + sizeof(HQA_ICAP_CMDS) / sizeof(HQA_CMD_HANDLER), + 0x1580, + } + , + { + HQA_CMD_SET6, + sizeof(HQA_CMD_SET6) / sizeof(HQA_CMD_HANDLER), + 0x1600, + } + , +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Handle Ethernet command by Command Idx. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +int HQA_CMDHandler(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Status = 0; + UINT_32 u4CmdId; + UINT_32 u4TableIndex = 0; + + u4CmdId = ntohs(HqaCmdFrame->Id); + + while (u4TableIndex < (sizeof(HQA_CMD_TABLES) / sizeof(HQA_CMD_TABLE))) { + int CmdIndex = 0; + + CmdIndex = u4CmdId - HQA_CMD_TABLES[u4TableIndex].CmdOffset; + if ((CmdIndex >= 0) && (CmdIndex < HQA_CMD_TABLES[u4TableIndex].CmdSetSize)) { + HQA_CMD_HANDLER *pCmdSet; + + pCmdSet = HQA_CMD_TABLES[u4TableIndex].CmdSet; + + if (pCmdSet[CmdIndex] != NULL) + i4Status = (*pCmdSet[CmdIndex]) (prNetDev, prIwReqData, HqaCmdFrame); + break; + } + u4TableIndex++; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Ioctl entry from ATE Daemon. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqInfo +* \param[in] prIwReqData +* \param[in] pcExtra +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +int priv_qa_agent(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) +{ + INT_32 i4Status = 0; + HQA_CMD_FRAME *HqaCmdFrame; + UINT_32 u4ATEMagicNum, u4ATEId, u4ATEData; + + HqaCmdFrame = kmalloc(sizeof(*HqaCmdFrame), GFP_KERNEL); + + if (!HqaCmdFrame) { + i4Status = -ENOMEM; + goto ERROR0; + } + + memset(HqaCmdFrame, 0, sizeof(*HqaCmdFrame)); + + if (copy_from_user(HqaCmdFrame, prIwReqData->data.pointer, prIwReqData->data.length)) { + i4Status = -EFAULT; + goto ERROR1; + } + + u4ATEMagicNum = ntohl(HqaCmdFrame->MagicNo); + u4ATEId = ntohs(HqaCmdFrame->Id); + memcpy((PUCHAR) & u4ATEData, HqaCmdFrame->Data, 4); + u4ATEData = ntohl(u4ATEData); + + switch (u4ATEMagicNum) { + case HQA_CMD_MAGIC_NO: + i4Status = HQA_CMDHandler(prNetDev, prIwReqData, HqaCmdFrame); + break; + default: + i4Status = -EINVAL; + DBGLOG(RFTEST, INFO, " QA_AGENT ATEMagicNum Error!!!\n"); + break; + } + +ERROR1: + kfree(HqaCmdFrame); +ERROR0: + return i4Status; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_rst.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_rst.c new file mode 100644 index 0000000000000..d3111ca2c062e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_rst.c @@ -0,0 +1,314 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * 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. + */ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include + +#include "precomp.h" +#include "gl_rst.h" + + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +static BOOLEAN fgResetTriggered = FALSE; +static BOOLEAN fgIsResetting = FALSE; + +#if CFG_CHIP_RESET_SUPPORT + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static RESET_STRUCT_T wifi_rst; + +static void mtk_wifi_reset(struct work_struct *work); +static void mtk_wifi_trigger_reset(struct work_struct *work); + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static void *glResetCallback(enum ENUM_WMTDRV_TYPE eSrcType, + enum ENUM_WMTDRV_TYPE eDstType, + enum ENUM_WMTMSG_TYPE eMsgType, void *prMsgBody, unsigned int u4MsgLength); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for + * 1. register wifi reset callback + * 2. initialize wifi reset work + * + * @param none + * + * @retval none + */ +/*----------------------------------------------------------------------------*/ +VOID glResetInit(VOID) +{ + /* 1. Register reset callback */ + mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_WIFI, (PF_WMT_CB) glResetCallback); + + /* 2. Initialize reset work */ + INIT_WORK(&(wifi_rst.rst_work), mtk_wifi_reset); + INIT_WORK(&(wifi_rst.rst_trigger_work), mtk_wifi_trigger_reset); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for + * 1. deregister wifi reset callback + * + * @param none + * + * @retval none + */ +/*----------------------------------------------------------------------------*/ +VOID glResetUninit(VOID) +{ + /* 1. Deregister reset callback */ + mtk_wcn_wmt_msgcb_unreg(WMTDRV_TYPE_WIFI); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is invoked when there is reset messages indicated + * + * @param eSrcType + * eDstType + * eMsgType + * prMsgBody + * u4MsgLength + * + * @retval + */ +/*----------------------------------------------------------------------------*/ +static void *glResetCallback(enum ENUM_WMTDRV_TYPE eSrcType, + enum ENUM_WMTDRV_TYPE eDstType, + enum ENUM_WMTMSG_TYPE eMsgType, void *prMsgBody, unsigned int u4MsgLength) +{ + switch (eMsgType) { + case WMTMSG_TYPE_RESET: + if (u4MsgLength == sizeof(enum ENUM_WMTRSTMSG_TYPE)) { + enum ENUM_WMTRSTMSG_TYPE *prRstMsg = (enum ENUM_WMTRSTMSG_TYPE *) prMsgBody; + + switch (*prRstMsg) { + case WMTRSTMSG_RESET_START: + DBGLOG(INIT, WARN, "Whole chip reset start!\n"); + fgIsResetting = TRUE; + fgResetTriggered = FALSE; + wifi_reset_start(); + break; + + case WMTRSTMSG_RESET_END: + DBGLOG(INIT, WARN, "Whole chip reset end!\n"); + fgIsResetting = FALSE; + wifi_rst.rst_data = RESET_SUCCESS; + schedule_work(&(wifi_rst.rst_work)); + break; + + case WMTRSTMSG_RESET_END_FAIL: + DBGLOG(INIT, WARN, "Whole chip reset fail!\n"); + fgIsResetting = FALSE; + wifi_rst.rst_data = RESET_FAIL; + schedule_work(&(wifi_rst.rst_work)); + break; + + default: + break; + } + } + break; + + default: + break; + } + + return NULL; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is called for wifi reset + * + * @param skb + * info + * + * @retval 0 + * nonzero + */ +/*----------------------------------------------------------------------------*/ +static void mtk_wifi_reset(struct work_struct *work) +{ + RESET_STRUCT_T *rst = container_of(work, RESET_STRUCT_T, rst_work); + + wifi_reset_end(rst->rst_data); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is called for generating reset request to WMT + * + * @param None + * + * @retval None + */ +/*----------------------------------------------------------------------------*/ +VOID glSendResetRequest(VOID) +{ + /* WMT thread would trigger whole chip reset itself */ +} + + + +static void mtk_wifi_trigger_reset(struct work_struct *work) +{ + BOOLEAN fgResult = FALSE; + RESET_STRUCT_T *rst = container_of(work, RESET_STRUCT_T, rst_trigger_work); + + /* Set the power off flag to FALSE in WMT to prevent chip power off after + ** wlanProbe return failure, because we need to do core dump afterward. + */ + if (rst->rst_trigger_flag & RST_FLAG_PREVENT_POWER_OFF) + mtk_wcn_set_connsys_power_off_flag(FALSE); + if ((rst->rst_trigger_flag & RST_FLAG_DO_CORE_DUMP) && !fgIsBusAccessFailed) + fgResult = mtk_wcn_wmt_assert_timeout(WMTDRV_TYPE_WIFI, 0x40, 0); + else + fgResult = mtk_wcn_wmt_do_reset(WMTDRV_TYPE_WIFI); + DBGLOG(INIT, INFO, "reset result %d, trigger flag 0x%x\n", fgResult, rst->rst_trigger_flag); +} + +BOOLEAN glResetTrigger(P_ADAPTER_T prAdapter, UINT_32 u4RstFlag, const PUINT_8 pucFile, UINT_32 u4Line) +{ + BOOLEAN fgResult = TRUE; + + if (fgIsResetting || fgResetTriggered) { + DBGLOG(INIT, ERROR, + "Skip trigger whole-chip reset in %s line %u, during resetting! Chip[%04X E%u]\n", + pucFile, u4Line, + nicGetChipID(prAdapter), + wlanGetEcoVersion(prAdapter)); + DBGLOG(INIT, ERROR, + "FW Ver DEC[%u.%u] HEX[%x.%x], Driver Ver[%u.%u]\n", + (prAdapter->rVerInfo.u2FwOwnVersion >> 8), + (UINT_16)(prAdapter->rVerInfo.u2FwOwnVersion & BITS(0, 7)), + (prAdapter->rVerInfo.u2FwOwnVersion >> 8), + (UINT_16)(prAdapter->rVerInfo.u2FwOwnVersion & BITS(0, 7)), + (prAdapter->rVerInfo.u2FwPeerVersion >> 8), + (UINT_16)(prAdapter->rVerInfo.u2FwPeerVersion & BITS(0, 7))); + + fgResult = TRUE; + } else { + DBGLOG(INIT, ERROR, + "Trigger chip reset in %s line %u! Chip[%04X E%u] FW Ver DEC[%u.%u] HEX[%x.%x], Driver Ver[%u.%u]\n", + pucFile, u4Line, + nicGetChipID(prAdapter), + wlanGetEcoVersion(prAdapter), + (prAdapter->rVerInfo.u2FwOwnVersion >> 8), + (UINT_16)(prAdapter->rVerInfo.u2FwOwnVersion & BITS(0, 7)), + (prAdapter->rVerInfo.u2FwOwnVersion >> 8), + (UINT_16)(prAdapter->rVerInfo.u2FwOwnVersion & BITS(0, 7)), + (prAdapter->rVerInfo.u2FwPeerVersion >> 8), + (UINT_16)(prAdapter->rVerInfo.u2FwPeerVersion & BITS(0, 7))); + + fgResetTriggered = TRUE; + wifi_rst.rst_trigger_flag = u4RstFlag; + schedule_work(&(wifi_rst.rst_trigger_work)); + } + + return fgResult; +} + +#endif /* CFG_CHIP_RESET_SUPPORT */ +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is called for checking if connectivity chip is resetting + * + * @param None + * + * @retval TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +inline BOOLEAN kalIsResetting(VOID) +{ + return fgIsResetting; +} + +inline BOOLEAN kalIsResetTriggered(VOID) +{ + return fgResetTriggered; +} + +UINT32 wlanPollingCpupcr(UINT32 u4Times, UINT32 u4Sleep) +{ +#if defined(MT6631) + UINT32 u4Count; + + for (u4Count = 0; u4Count < u4Times; u4Count++) { + DBGLOG(INIT, ERROR, "i:%d,cpupcr:%08x\n", u4Count, wmt_plat_read_cpupcr()); + kalMsleep(u4Sleep); + } +#else + DBGLOG(INIT, ERROR, "This chip don't support polling cpupcr\n"); +#endif + return 0; +} + +WLAN_STATUS wlanGetCpupcr(PUINT32 pu4Cpupcr) +{ + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + +#if defined(MT6631) + if (pu4Cpupcr) { + *pu4Cpupcr = wmt_plat_read_cpupcr(); + rStatus = WLAN_STATUS_SUCCESS; + } +#else + DBGLOG(INIT, ERROR, "This chip don't support polling cpupcr\n"); +#endif + return rStatus; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_vendor.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_vendor.c new file mode 100644 index 0000000000000..c6adff81760a2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_vendor.c @@ -0,0 +1,2423 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * gl_vendor.c + * + * + */ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include + +#include "gl_os.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "precomp.h" +#include "gl_cfg80211.h" +#include "gl_vendor.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* These values must sync from Wifi HAL + * /hardware/libhardware_legacy/include/hardware_legacy/wifi_hal.h + */ +/* Basic infrastructure mode */ +#define WIFI_FEATURE_INFRA (0x0001) +/* Support for 5 GHz Band */ +#define WIFI_FEATURE_INFRA_5G (0x0002) +/* Support for GAS/ANQP */ +#define WIFI_FEATURE_HOTSPOT (0x0004) +/* Wifi-Direct */ +#define WIFI_FEATURE_P2P (0x0008) +/* Soft AP */ +#define WIFI_FEATURE_SOFT_AP (0x0010) +/* Google-Scan APIs */ +#define WIFI_FEATURE_GSCAN (0x0020) +/* Neighbor Awareness Networking */ +#define WIFI_FEATURE_NAN (0x0040) +/* Device-to-device RTT */ +#define WIFI_FEATURE_D2D_RTT (0x0080) +/* Device-to-AP RTT */ +#define WIFI_FEATURE_D2AP_RTT (0x0100) +/* Batched Scan (legacy) */ +#define WIFI_FEATURE_BATCH_SCAN (0x0200) +/* Preferred network offload */ +#define WIFI_FEATURE_PNO (0x0400) +/* Support for two STAs */ +#define WIFI_FEATURE_ADDITIONAL_STA (0x0800) +/* Tunnel directed link setup */ +#define WIFI_FEATURE_TDLS (0x1000) +/* Support for TDLS off channel */ +#define WIFI_FEATURE_TDLS_OFFCHANNEL (0x2000) +/* Enhanced power reporting */ +#define WIFI_FEATURE_EPR (0x4000) +/* Support for AP STA Concurrency */ +#define WIFI_FEATURE_AP_STA (0x8000) +/* Link layer stats collection */ +#define WIFI_FEATURE_LINK_LAYER_STATS (0x10000) +/* WiFi Logger */ +#define WIFI_FEATURE_LOGGER (0x20000) +/* WiFi PNO enhanced */ +#define WIFI_FEATURE_HAL_EPNO (0x40000) +/* RSSI Monitor */ +#define WIFI_FEATURE_RSSI_MONITOR (0x80000) +/* WiFi mkeep_alive */ +#define WIFI_FEATURE_MKEEP_ALIVE (0x100000) +/* ND offload configure */ +#define WIFI_FEATURE_CONFIG_NDO (0x200000) +/* Capture Tx transmit power levels */ +#define WIFI_FEATURE_TX_TRANSMIT_POWER (0x400000) +/* Enable/Disable firmware roaming */ +#define WIFI_FEATURE_CONTROL_ROAMING (0x800000) +/* Support Probe IE white listing */ +#define WIFI_FEATURE_IE_WHITELIST (0x1000000) +/* Support MAC & Probe Sequence Number randomization */ +#define WIFI_FEATURE_SCAN_RAND (0x2000000) +/* Support Tx Power Limit setting */ +#define WIFI_FEATURE_SET_TX_POWER_LIMIT (0x4000000) +/* Support Using Body/Head Proximity for SAR */ +#define WIFI_FEATURE_USE_BODY_HEAD_SAR (0x8000000) +/* Support Random P2P MAC */ +#define WIFI_FEATURE_P2P_RAND_MAC (0x100000000L) + +/* note: WIFI_FEATURE_GSCAN be enabled just for ACTS test item: scanner */ +#define WIFI_HAL_FEATURE_SET ((WIFI_FEATURE_P2P) |\ + (WIFI_FEATURE_SOFT_AP) |\ + (WIFI_FEATURE_AP_STA) |\ + (WIFI_FEATURE_PNO) |\ + (WIFI_FEATURE_TDLS) |\ + (WIFI_FEATURE_RSSI_MONITOR) |\ + (WIFI_FEATURE_CONTROL_ROAMING) |\ + (WIFI_FEATURE_P2P_RAND_MAC)) +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +static struct nla_policy nla_parse_wifi_policy[WIFI_ATTRIBUTE_ROAMING_WHITELIST_SSID + 1] = { + [WIFI_ATTRIBUTE_BAND] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_NUM_CHANNELS] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_CHANNEL_LIST] = {.type = NLA_UNSPEC}, + + [WIFI_ATTRIBUTE_NUM_FEATURE_SET] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_FEATURE_SET] = {.type = NLA_UNSPEC}, + [WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI] = {.type = NLA_UNSPEC}, + [WIFI_ATTRIBUTE_NODFS_VALUE] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_COUNTRY_CODE] = {.type = NLA_STRING}, + + [WIFI_ATTRIBUTE_MAX_RSSI] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_MIN_RSSI] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_RSSI_MONITOR_START] = {.type = NLA_U32}, + + [WIFI_ATTRIBUTE_ROAMING_CAPABILITIES] = {.type = NLA_UNSPEC}, + [WIFI_ATTRIBUTE_ROAMING_BLACKLIST_NUM] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_ROAMING_BLACKLIST_BSSID] = {.type = NLA_UNSPEC}, + [WIFI_ATTRIBUTE_ROAMING_WHITELIST_NUM] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_ROAMING_WHITELIST_SSID] = {.type = NLA_UNSPEC}, +}; + +static struct nla_policy nla_parse_gscan_policy[GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1] = { + [GSCAN_ATTRIBUTE_NUM_BUCKETS] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BASE_PERIOD] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BUCKETS_BAND] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BUCKET_ID] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BUCKET_PERIOD] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BUCKET_CHANNELS] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_REPORT_THRESHOLD] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_REPORT_EVENTS] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BSSID] = {.type = NLA_UNSPEC}, + [GSCAN_ATTRIBUTE_RSSI_LOW] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_RSSI_HIGH] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE] = {.type = NLA_U16}, + [GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_MIN_BREACHING] = {.type = NLA_U16}, + [GSCAN_ATTRIBUTE_NUM_AP] = {.type = NLA_U16}, + [GSCAN_ATTRIBUTE_HOTLIST_FLUSH] = {.type = NLA_U8}, + [GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH] = {.type = NLA_U8}, +}; + +static struct nla_policy nla_parse_offloading_policy[MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC + 1] = { + [MKEEP_ALIVE_ATTRIBUTE_ID] = {.type = NLA_U8}, + [MKEEP_ALIVE_ATTRIBUTE_IP_PKT] = {.type = NLA_UNSPEC}, + [MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN] = {.type = NLA_U16}, + [MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR] = {.type = NLA_UNSPEC}, + [MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR] = {.type = NLA_UNSPEC}, + [MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC] = {.type = NLA_U32}, +}; + +static const struct nla_policy nla_get_acs_policy[ + WIFI_VENDOR_ATTR_ACS_MAX + 1] = { + [WIFI_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 }, + [WIFI_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG }, + [WIFI_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG }, + [WIFI_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG }, + [WIFI_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 }, + [WIFI_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_UNSPEC }, + [WIFI_VENDOR_ATTR_ACS_FREQ_LIST] = { .type = NLA_UNSPEC }, +}; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +int mtk_cfg80211_NLA_PUT(struct sk_buff *skb, int attrtype, int attrlen, const void *data) +{ + if (unlikely(nla_put(skb, attrtype, attrlen, data) < 0)) + return 0; + return 1; +} + +int mtk_cfg80211_nla_put_type(struct sk_buff *skb, ENUM_NLA_PUT_DATE_TYPE type, int attrtype, const void *value) +{ + u8 u8data = 0; + u16 u16data = 0; + u32 u32data = 0; + u64 u64data = 0; + + switch (type) { + case NLA_PUT_DATE_U8: + u8data = *(u8 *)value; + return mtk_cfg80211_NLA_PUT(skb, attrtype, sizeof(u8), &u8data); + case NLA_PUT_DATE_U16: + u16data = *(u16 *)value; + return mtk_cfg80211_NLA_PUT(skb, attrtype, sizeof(u16), &u16data); + case NLA_PUT_DATE_U32: + u32data = *(u32 *)value; + return mtk_cfg80211_NLA_PUT(skb, attrtype, sizeof(u32), &u32data); + case NLA_PUT_DATE_U64: + u64data = *(u64 *)value; + return mtk_cfg80211_NLA_PUT(skb, attrtype, sizeof(u64), &u64data); + default: + break; + } + return 0; +} + +int mtk_cfg80211_vendor_get_channel_list(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo; + struct nlattr *attr; + UINT_32 band = 0; + UINT_8 ucNumOfChannel, i, j; + RF_CHANNEL_INFO_T aucChannelList[64] = { {0} }; + UINT_32 num_channels; + wifi_channel channels[64]; + struct sk_buff *skb; + + ASSERT(wiphy && wdev); + if ((data == NULL) || !data_len) + return -EINVAL; + + attr = (struct nlattr *)data; + if (attr->nla_type == WIFI_ATTRIBUTE_BAND) + band = nla_get_u32(attr); + + if (wdev->iftype == NL80211_IFTYPE_AP) + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + else + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + if (!prGlueInfo) + return -EFAULT; + + switch (band) { + case 1: /* 2.4G band */ + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_2G4, TRUE, + 64, &ucNumOfChannel, aucChannelList); + break; + case 2: /* 5G band without DFS channels */ + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_5G, TRUE, + 64, &ucNumOfChannel, aucChannelList); + break; + case 4: /* 5G band DFS channels only */ + rlmDomainGetDfsChnls(prGlueInfo->prAdapter, 64, &ucNumOfChannel, aucChannelList); + break; + default: + ucNumOfChannel = 0; + break; + } + + kalMemZero(channels, sizeof(channels)); + for (i = 0, j = 0; i < ucNumOfChannel; i++) { + /* We need to report frequency list to HAL */ + channels[j] = nicChannelNum2Freq(aucChannelList[i].ucChannelNum) / 1000; + if (channels[j] == 0) + continue; + else { + DBGLOG(REQ, TRACE, "channels[%d] = %d\n", j, channels[j]); + j++; + } + } + num_channels = j; + DBGLOG(REQ, INFO, "Get channel list for band: %d, num_channels=%d\n", band, num_channels); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(channels)); + if (!skb) { + DBGLOG(REQ, ERROR, "Allocate skb failed\n"); + return -ENOMEM; + } + + if (unlikely(nla_put_u32(skb, WIFI_ATTRIBUTE_NUM_CHANNELS, num_channels) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put(skb, WIFI_ATTRIBUTE_CHANNEL_LIST, + (sizeof(wifi_channel) * num_channels), channels) < 0)) + goto nla_put_failure; + + return cfg80211_vendor_cmd_reply(skb); + +nla_put_failure: + kfree_skb(skb); + return -EFAULT; +} + +int mtk_cfg80211_vendor_set_country_code(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + struct nlattr *attr; + UINT_8 country[2] = {0, 0}; + + ASSERT(wiphy && wdev); + if ((data == NULL) || (data_len == 0)) + return -EINVAL; + + attr = (struct nlattr *)data; + if (attr->nla_type == WIFI_ATTRIBUTE_COUNTRY_CODE) { + country[0] = *((PUINT_8)nla_data(attr)); + country[1] = *((PUINT_8)nla_data(attr) + 1); + } + + DBGLOG(REQ, INFO, "Set country code: %c%c, iftype=%d\n", country[0], country[1], wdev->iftype); + + if (wdev->iftype == NL80211_IFTYPE_AP) + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + else + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + if (!prGlueInfo) + return -EFAULT; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetCountryCode, country, 2, FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "Set country code error: %x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +int mtk_cfg80211_vendor_get_roaming_capabilities(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + UINT_32 maxNumOfList[2] = { MAX_FW_ROAMING_BLACKLIST_SIZE, MAX_FW_ROAMING_WHITELIST_SIZE }; + struct sk_buff *skb; + + if (wiphy == NULL || wdev == NULL) + return -EFAULT; + + DBGLOG(REQ, INFO, "Get roaming capabilities: max black/whitelist=%d/%d", maxNumOfList[0], maxNumOfList[1]); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(UINT_32) * 2); + if (!skb) { + DBGLOG(REQ, ERROR, "Allocate skb failed\n"); + return -ENOMEM; + } + + if (unlikely(nla_put(skb, WIFI_ATTRIBUTE_ROAMING_CAPABILITIES, + sizeof(UINT_32), &maxNumOfList[0]) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put(skb, WIFI_ATTRIBUTE_ROAMING_CAPABILITIES, + sizeof(UINT_32), &maxNumOfList[1]) < 0)) + goto nla_put_failure; + + return cfg80211_vendor_cmd_reply(skb); + +nla_put_failure: + kfree_skb(skb); + return -EFAULT; +} + +int mtk_cfg80211_vendor_config_roaming(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4ResultLen = 0; + + DBGLOG(REQ, TRACE, "Receives roaming blacklist & whitelist with data_len=%d\n", data_len); + if ((wiphy == NULL) || (wdev == NULL)) { + DBGLOG(REQ, INFO, "wiphy or wdev is NULL\n"); + return -EINVAL; + } + + if ((data == NULL) || (data_len == 0)) + return -EINVAL; + + if (wdev->iftype != NL80211_IFTYPE_STATION) + return -EINVAL; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + if (!prGlueInfo) + return -EINVAL; + + if (prGlueInfo->u4FWRoamingEnable == 0) { + DBGLOG(REQ, INFO, "FWRoaming is disabled (FWRoamingEnable=%d)\n", prGlueInfo->u4FWRoamingEnable); + return WLAN_STATUS_SUCCESS; + } + kalIoctl(prGlueInfo, wlanoidConfigRoaming, (PVOID)data, data_len, FALSE, FALSE, FALSE, &u4ResultLen); + + return WLAN_STATUS_SUCCESS; +} + +int mtk_cfg80211_vendor_enable_roaming(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4ResultLen = 0; + struct nlattr *attr; + + if ((wiphy == NULL) || (wdev == NULL)) { + DBGLOG(REQ, INFO, "wiphy or wdev is NULL\n"); + return -EINVAL; + } + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + if (!prGlueInfo) + return -EFAULT; + + attr = (struct nlattr *)data; + if (attr->nla_type == WIFI_ATTRIBUTE_ROAMING_STATE) + prGlueInfo->u4FWRoamingEnable = nla_get_u32(attr); + + if (prGlueInfo->u4FWRoamingEnable == 0) + kalIoctl(prGlueInfo, wlanoidEnableRoaming, NULL, 0, FALSE, FALSE, FALSE, &u4ResultLen); + + DBGLOG(REQ, INFO, "FWK set FWRoamingEnable = %d\n", prGlueInfo->u4FWRoamingEnable); + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_SUPPORT_GSCN +int mtk_cfg80211_vendor_get_gscan_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Status = -EINVAL; + PARAM_WIFI_GSCAN_CAPABILITIES_STRUCT_T rGscanCapabilities; + struct sk_buff *skb; + + DBGLOG(REQ, TRACE, "vendor command: data_len=%d\r\n", data_len); + + ASSERT(wiphy); + ASSERT(wdev); + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(rGscanCapabilities)); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed:%x\n", __func__, i4Status); + return -ENOMEM; + } + + kalMemZero(&rGscanCapabilities, sizeof(rGscanCapabilities)); + + /* GSCN capabilities return from driver not firmware */ + rGscanCapabilities.max_scan_cache_size = PSCAN_MAX_SCAN_CACHE_SIZE; + rGscanCapabilities.max_scan_buckets = GSCAN_MAX_BUCKETS; + rGscanCapabilities.max_ap_cache_per_scan = PSCAN_MAX_AP_CACHE_PER_SCAN; + rGscanCapabilities.max_rssi_sample_size = 10; + rGscanCapabilities.max_scan_reporting_threshold = GSCAN_MAX_REPORT_THRESHOLD; + rGscanCapabilities.max_hotlist_bssids = MAX_HOTLIST_BSSIDS; + rGscanCapabilities.max_hotlist_ssids = MAX_HOTLIST_SSIDS; + rGscanCapabilities.max_significant_wifi_change_aps = MAX_SIGNIFICANT_CHANGE_APS; + rGscanCapabilities.max_bssid_history_entries = PSCAN_MAX_AP_CACHE_PER_SCAN * PSCAN_MAX_SCAN_CACHE_SIZE; + rGscanCapabilities.max_number_epno_networks = 0; + rGscanCapabilities.max_number_epno_networks_by_ssid = 0; + rGscanCapabilities.max_number_of_white_listed_ssid = 0; + + /* NLA_PUT_U32(skb, NL80211_ATTR_VENDOR_ID, GOOGLE_OUI); */ + /* NLA_PUT_U32(skb, NL80211_ATTR_VENDOR_SUBCMD, GSCAN_SUBCMD_GET_CAPABILITIES); */ + /*NLA_PUT(skb, GSCAN_ATTRIBUTE_CAPABILITIES, sizeof(rGscanCapabilities), &rGscanCapabilities);*/ + if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_CAPABILITIES, + sizeof(rGscanCapabilities), &rGscanCapabilities) < 0)) + goto nla_put_failure; + + i4Status = cfg80211_vendor_cmd_reply(skb); + return i4Status; + +nla_put_failure: + kfree_skb(skb); + return i4Status; +} + +int mtk_cfg80211_vendor_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + /* CMD_GSCN_REQ_T rCmdGscnParam; */ + + /* INT_32 i4Status = -EINVAL; */ + P_PARAM_WIFI_GSCAN_CMD_PARAMS prWifiScanCmd = NULL; + struct nlattr *attr[GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD + 1]; + struct nlattr *pbucket, *pchannel; + UINT_32 len_basic, len_bucket, len_channel; + int i, j, k; + UINT_32 u4ArySize; + + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + + prWifiScanCmd = (P_PARAM_WIFI_GSCAN_CMD_PARAMS) kalMemAlloc(sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS), VIR_MEM_TYPE); + if (!prWifiScanCmd) { + DBGLOG(REQ, ERROR, "Can not alloc memory for PARAM_WIFI_GSCAN_CMD_PARAMS\n"); + return -ENOMEM; + } + + DBGLOG(REQ, TRACE, "vendor command: data_len=%d\r\n", data_len); + kalMemZero(prWifiScanCmd, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); + kalMemZero(attr, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD + 1)); + + NLA_PARSE_NESTED(attr, GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD, (struct nlattr *)(data - NLA_HDRLEN), + nla_parse_gscan_policy); + len_basic = 0; + for (k = GSCAN_ATTRIBUTE_NUM_BUCKETS; k <= GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD; k++) { + if (attr[k]) { + switch (k) { + case GSCAN_ATTRIBUTE_BASE_PERIOD: + prWifiScanCmd->base_period = nla_get_u32(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_NUM_BUCKETS: + u4ArySize = nla_get_u32(attr[k]); + prWifiScanCmd->num_buckets = + (u4ArySize <= GSCAN_MAX_BUCKETS) + ? u4ArySize : GSCAN_MAX_BUCKETS; + len_basic += NLA_ALIGN(attr[k]->nla_len); + DBGLOG(REQ, TRACE, "attr=0x%x, num_buckets=%d nla_len=%d,\r\n", + *(UINT_32 *) attr[k], prWifiScanCmd->num_buckets, attr[k]->nla_len); + break; + } + } + } + pbucket = (struct nlattr *)((UINT_8 *) data + len_basic); + DBGLOG(REQ, TRACE, "+++basic attribute size=%d pbucket=%p\r\n", len_basic, pbucket); + + for (i = 0; i < prWifiScanCmd->num_buckets; i++) { + if (NLA_PARSE_NESTED(attr, GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD, (struct nlattr *)pbucket, + nla_parse_gscan_policy) < 0) + goto nla_put_failure; + len_bucket = 0; + for (k = GSCAN_ATTRIBUTE_NUM_BUCKETS; k <= GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD; k++) { + if (attr[k] == NULL) + continue; + switch (k) { + case GSCAN_ATTRIBUTE_BUCKETS_BAND: + prWifiScanCmd->buckets[i].band = nla_get_u32(attr[k]); + len_bucket += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_BUCKET_ID: + prWifiScanCmd->buckets[i].bucket = nla_get_u32(attr[k]); + len_bucket += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_BUCKET_PERIOD: + prWifiScanCmd->buckets[i].period = nla_get_u32(attr[k]); + len_bucket += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT: + prWifiScanCmd->buckets[i].step_count = nla_get_u32(attr[k]); + len_bucket += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD: + prWifiScanCmd->buckets[i].max_period = nla_get_u32(attr[k]); + len_bucket += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_REPORT_EVENTS: + prWifiScanCmd->buckets[i].report_events = nla_get_u32(attr[k]); + /* parameter validity check */ + if (((prWifiScanCmd->buckets[i].report_events & REPORT_EVENTS_EACH_SCAN) + != REPORT_EVENTS_EACH_SCAN) + && ((prWifiScanCmd->buckets[i].report_events & REPORT_EVENTS_FULL_RESULTS) + != REPORT_EVENTS_FULL_RESULTS) + && ((prWifiScanCmd->buckets[i].report_events & REPORT_EVENTS_NO_BATCH) + != REPORT_EVENTS_NO_BATCH)) + prWifiScanCmd->buckets[i].report_events = REPORT_EVENTS_EACH_SCAN; + len_bucket += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS: + prWifiScanCmd->buckets[i].num_channels = nla_get_u32(attr[k]); + len_bucket += NLA_ALIGN(attr[k]->nla_len); + DBGLOG(REQ, TRACE, "bucket%d: attr=0x%x, num_channels=%d nla_len=%d,\r\n", + i, *(UINT_32 *) attr[k], nla_get_u32(attr[k]), attr[k]->nla_len); + break; + } + } + pbucket = (struct nlattr *)((UINT_8 *) pbucket + NLA_HDRLEN); + /* request.attr_start(i) as nested attribute */ + DBGLOG(REQ, TRACE, "+++pure bucket size=%d pbucket=%p\r\n", len_bucket, pbucket); + pbucket = (struct nlattr *)((UINT_8 *) pbucket + len_bucket); + /* pure bucket payload, not include channels */ + + /*don't need to use nla_parse_nested to parse channels */ + /* the header of channel in bucket i */ + pchannel = (struct nlattr *)((UINT_8 *) pbucket + NLA_HDRLEN); + for (j = 0; j < prWifiScanCmd->buckets[i].num_channels; j++) { + prWifiScanCmd->buckets[i].channels[j].channel = nla_get_u32(pchannel); + len_channel = NLA_ALIGN(pchannel->nla_len); + DBGLOG(REQ, TRACE, + "attr=0x%x, channel=%d,\r\n", *(UINT_32 *) pchannel, nla_get_u32(pchannel)); + + pchannel = (struct nlattr *)((UINT_8 *) pchannel + len_channel); + } + pbucket = pchannel; + } + + DBGLOG(REQ, INFO, "base_period=%d, num_buckets=%d, bucket0: %d %d %d %d %d %d\n", + prWifiScanCmd->base_period, prWifiScanCmd->num_buckets, + prWifiScanCmd->buckets[0].bucket, prWifiScanCmd->buckets[0].band, + prWifiScanCmd->buckets[0].period, prWifiScanCmd->buckets[0].max_period, + prWifiScanCmd->buckets[0].num_channels, prWifiScanCmd->buckets[0].report_events); + + DBGLOG(REQ, TRACE, "bucket0: num_channels=%d, %d, %d; bucket1: num_channels=%d, %d, %d\n", + prWifiScanCmd->buckets[0].num_channels, + prWifiScanCmd->buckets[0].channels[0].channel, prWifiScanCmd->buckets[0].channels[1].channel, + prWifiScanCmd->buckets[1].num_channels, + prWifiScanCmd->buckets[1].channels[0].channel, prWifiScanCmd->buckets[1].channels[1].channel); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetGSCNParam, + prWifiScanCmd, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS), FALSE, FALSE, TRUE, &u4BufLen); + kalMemFree(prWifiScanCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); + return 0; + +nla_put_failure: + if (prWifiScanCmd != NULL) + kalMemFree(prWifiScanCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); + return -ENOMEM; +} + +int mtk_cfg80211_vendor_set_scan_config(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + + INT_32 i4Status = -ENOMEM; + /*PARAM_WIFI_GSCAN_CMD_PARAMS rWifiScanCmd;*/ + P_PARAM_WIFI_GSCAN_CMD_PARAMS prWifiScanCmd = NULL; + struct nlattr *attr[GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE + 1]; + /* UINT_32 num_scans = 0; */ /* another attribute */ + int k; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + DBGLOG(REQ, TRACE, "vendor command: data_len=%d\r\n", data_len); + /*kalMemZero(&rWifiScanCmd, sizeof(rWifiScanCmd));*/ + prWifiScanCmd = kalMemAlloc(sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS), VIR_MEM_TYPE); + if (prWifiScanCmd == NULL) + goto nla_put_failure; + kalMemZero(prWifiScanCmd, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); + kalMemZero(attr, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE + 1)); + + if (NLA_PARSE_NESTED(attr, GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, + (struct nlattr *)(data - NLA_HDRLEN), nla_parse_gscan_policy) < 0) + goto nla_put_failure; + for (k = GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN; k <= GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE; k++) { + if (attr[k]) { + switch (k) { + case GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN: + prWifiScanCmd->max_ap_per_scan = nla_get_u32(attr[k]); + break; + case GSCAN_ATTRIBUTE_REPORT_THRESHOLD: + prWifiScanCmd->report_threshold_percent = nla_get_u32(attr[k]); + break; + case GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE: + prWifiScanCmd->report_threshold_num_scans = nla_get_u32(attr[k]); + break; + } + } + } + /* parameter validity check */ + if (prWifiScanCmd->report_threshold_percent > 100) + prWifiScanCmd->report_threshold_percent = 100; + DBGLOG(REQ, TRACE, "attr=0x%x, attr2=0x%x ", *(UINT_32 *) attr[GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN], + *(UINT_32 *) attr[GSCAN_ATTRIBUTE_REPORT_THRESHOLD]); + + DBGLOG(REQ, INFO, "max_ap_per_scan=%d, report_threshold=%d num_scans=%d\r\n", + prWifiScanCmd->max_ap_per_scan, prWifiScanCmd->report_threshold_percent, + prWifiScanCmd->report_threshold_num_scans); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetGSCNConfig, + prWifiScanCmd, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS), FALSE, FALSE, TRUE, &u4BufLen); + kalMemFree(prWifiScanCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); + return 0; + +nla_put_failure: + if (prWifiScanCmd != NULL) + kalMemFree(prWifiScanCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); + return i4Status; +} +#endif + +int mtk_cfg80211_vendor_set_significant_change(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + INT_32 i4Status = -EINVAL; + P_PARAM_WIFI_SIGNIFICANT_CHANGE prWifiChangeCmd = NULL; + UINT_8 flush = 0; + /* struct nlattr *attr[GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1]; */ + struct nlattr **attr = NULL; + struct nlattr *paplist; + int i, k; + UINT_32 len_basic, len_aplist; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + DBGLOG(REQ, TRACE, "vendor command: data_len=%d\r\n", data_len); + for (i = 0; i < 6; i++) + DBGLOG(REQ, LOUD, "0x%x 0x%x 0x%x 0x%x\r\n", + *((UINT_32 *) data + i * 4), *((UINT_32 *) data + i * 4 + 1), + *((UINT_32 *) data + i * 4 + 2), *((UINT_32 *) data + i * 4 + 3)); + prWifiChangeCmd = kalMemAlloc(sizeof(PARAM_WIFI_SIGNIFICANT_CHANGE), VIR_MEM_TYPE); + if (prWifiChangeCmd == NULL) + goto nla_put_failure; + kalMemZero(prWifiChangeCmd, sizeof(PARAM_WIFI_SIGNIFICANT_CHANGE)); + attr = kalMemAlloc(sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1), VIR_MEM_TYPE); + if (attr == NULL) + goto nla_put_failure; + kalMemZero(attr, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1)); + + if (NLA_PARSE_NESTED(attr, GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, + (struct nlattr *)(data - NLA_HDRLEN), nla_parse_gscan_policy) < 0) + goto nla_put_failure; + len_basic = 0; + for (k = GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE; k <= GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH; k++) { + if (attr[k]) { + switch (k) { + case GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE: + prWifiChangeCmd->rssi_sample_size = nla_get_u16(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE: + prWifiChangeCmd->lost_ap_sample_size = nla_get_u16(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_MIN_BREACHING: + prWifiChangeCmd->min_breaching = nla_get_u16(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_NUM_AP: + prWifiChangeCmd->num_ap = nla_get_u16(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + DBGLOG(REQ, TRACE, "attr=0x%x, num_ap=%d nla_len=%d,\r\n", + *(UINT_32 *) attr[k], prWifiChangeCmd->num_ap, attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH: + flush = nla_get_u8(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + } + } + } + paplist = (struct nlattr *)((UINT_8 *) data + len_basic); + DBGLOG(REQ, TRACE, "+++basic attribute size=%d flush=%d\r\n", len_basic, flush); + + if (paplist->nla_type == GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS) + paplist = (struct nlattr *)((UINT_8 *) paplist + NLA_HDRLEN); + + for (i = 0; i < prWifiChangeCmd->num_ap; i++) { + if (NLA_PARSE_NESTED(attr, GSCAN_ATTRIBUTE_RSSI_HIGH, (struct nlattr *)paplist, + nla_parse_gscan_policy) < 0) + goto nla_put_failure; + paplist = (struct nlattr *)((UINT_8 *) paplist + NLA_HDRLEN); + /* request.attr_start(i) as nested attribute */ + len_aplist = 0; + for (k = GSCAN_ATTRIBUTE_BSSID; k <= GSCAN_ATTRIBUTE_RSSI_HIGH; k++) { + if (attr[k]) { + switch (k) { + case GSCAN_ATTRIBUTE_BSSID: + kalMemCopy(prWifiChangeCmd->ap[i].bssid, nla_data(attr[k]), sizeof(mac_addr)); + len_aplist += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_RSSI_LOW: + prWifiChangeCmd->ap[i].low = nla_get_u32(attr[k]); + len_aplist += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_RSSI_HIGH: + prWifiChangeCmd->ap[i].high = nla_get_u32(attr[k]); + len_aplist += NLA_ALIGN(attr[k]->nla_len); + break; + } + } + } + if (((i + 1) % 4 == 0) || (i == prWifiChangeCmd->num_ap - 1)) + DBGLOG(REQ, TRACE, "ap[%d], len_aplist=%d\n", i, len_aplist); + else + DBGLOG(REQ, TRACE, "ap[%d], len_aplist=%d\t", i, len_aplist); + paplist = (struct nlattr *)((UINT_8 *) paplist + len_aplist); + } + + DBGLOG(REQ, TRACE, + "flush=%d, rssi_sample_size=%d lost_ap_sample_size=%d min_breaching=%d", + flush, prWifiChangeCmd->rssi_sample_size, prWifiChangeCmd->lost_ap_sample_size, + prWifiChangeCmd->min_breaching); + DBGLOG(REQ, TRACE, + "ap[0].channel=%d low=%d high=%d, ap[1].channel=%d low=%d high=%d", + prWifiChangeCmd->ap[0].channel, prWifiChangeCmd->ap[0].low, prWifiChangeCmd->ap[0].high, + prWifiChangeCmd->ap[1].channel, prWifiChangeCmd->ap[1].low, prWifiChangeCmd->ap[1].high); + kalMemFree(prWifiChangeCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_SIGNIFICANT_CHANGE)); + kalMemFree(attr, VIR_MEM_TYPE, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1)); + return 0; + +nla_put_failure: + if (prWifiChangeCmd) + kalMemFree(prWifiChangeCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_SIGNIFICANT_CHANGE)); + if (attr) + kalMemFree(attr, VIR_MEM_TYPE, + sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1)); + return i4Status; +} + +int mtk_cfg80211_vendor_set_hotlist(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + CMD_SET_PSCAN_ADD_HOTLIST_BSSID rCmdPscnAddHotlist; + + INT_32 i4Status = -EINVAL; + P_PARAM_WIFI_BSSID_HOTLIST prWifiHotlistCmd = NULL; + UINT_8 flush = 0; + /* struct nlattr *attr[GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1]; */ + struct nlattr **attr = NULL; + struct nlattr *paplist; + int i, k; + UINT_32 len_basic, len_aplist; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + DBGLOG(REQ, TRACE, "vendor command: data_len=%d\r\n", data_len); + for (i = 0; i < 5; i++) + DBGLOG(REQ, LOUD, "0x%x 0x%x 0x%x 0x%x\r\n", + *((UINT_32 *) data + i * 4), *((UINT_32 *) data + i * 4 + 1), + *((UINT_32 *) data + i * 4 + 2), *((UINT_32 *) data + i * 4 + 3)); + prWifiHotlistCmd = kalMemAlloc(sizeof(PARAM_WIFI_BSSID_HOTLIST), VIR_MEM_TYPE); + if (prWifiHotlistCmd == NULL) + goto nla_put_failure; + kalMemZero(prWifiHotlistCmd, sizeof(PARAM_WIFI_BSSID_HOTLIST)); + attr = kalMemAlloc(sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1), VIR_MEM_TYPE); + if (attr == NULL) + goto nla_put_failure; + kalMemZero(attr, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1)); + + if (NLA_PARSE_NESTED(attr, GSCAN_ATTRIBUTE_NUM_AP, (struct nlattr *)(data - NLA_HDRLEN), + nla_parse_gscan_policy) < 0) + goto nla_put_failure; + len_basic = 0; + for (k = GSCAN_ATTRIBUTE_HOTLIST_FLUSH; k <= GSCAN_ATTRIBUTE_NUM_AP; k++) { + if (attr[k]) { + switch (k) { + case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE: + prWifiHotlistCmd->lost_ap_sample_size = nla_get_u32(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_NUM_AP: + prWifiHotlistCmd->num_ap = nla_get_u16(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + DBGLOG(REQ, TRACE, "attr=0x%x, num_ap=%d nla_len=%d,\r\n", + *(UINT_32 *) attr[k], prWifiHotlistCmd->num_ap, attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_HOTLIST_FLUSH: + flush = nla_get_u8(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + } + } + } + paplist = (struct nlattr *)((UINT_8 *) data + len_basic); + DBGLOG(REQ, INFO, "+++basic attribute size=%d flush=%d\r\n", len_basic, flush); + + if (paplist->nla_type == GSCAN_ATTRIBUTE_HOTLIST_BSSIDS) + paplist = (struct nlattr *)((UINT_8 *) paplist + NLA_HDRLEN); + + for (i = 0; i < prWifiHotlistCmd->num_ap; i++) { + if (NLA_PARSE_NESTED(attr, GSCAN_ATTRIBUTE_RSSI_HIGH, (struct nlattr *)paplist, + nla_parse_gscan_policy) < 0) + goto nla_put_failure; + paplist = (struct nlattr *)((UINT_8 *) paplist + NLA_HDRLEN); + /* request.attr_start(i) as nested attribute */ + len_aplist = 0; + for (k = GSCAN_ATTRIBUTE_BSSID; k <= GSCAN_ATTRIBUTE_RSSI_HIGH; k++) { + if (attr[k]) { + switch (k) { + case GSCAN_ATTRIBUTE_BSSID: + kalMemCopy(prWifiHotlistCmd->ap[i].bssid, nla_data(attr[k]), sizeof(mac_addr)); + len_aplist += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_RSSI_LOW: + prWifiHotlistCmd->ap[i].low = nla_get_u32(attr[k]); + len_aplist += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_RSSI_HIGH: + prWifiHotlistCmd->ap[i].high = nla_get_u32(attr[k]); + len_aplist += NLA_ALIGN(attr[k]->nla_len); + break; + } + } + } + if (((i + 1) % 4 == 0) || (i == prWifiHotlistCmd->num_ap - 1)) + DBGLOG(REQ, TRACE, "ap[%d], len_aplist=%d\n", i, len_aplist); + else + DBGLOG(REQ, TRACE, "ap[%d], len_aplist=%d\t", i, len_aplist); + paplist = (struct nlattr *)((UINT_8 *) paplist + len_aplist); + } + + DBGLOG(REQ, INFO, + "flush=%d, lost_ap_sample_size=%d, Hotlist:ap[0].channel=%d low=%d high=%d, ap[1].channel=%d low=%d high=%d", + flush, prWifiHotlistCmd->lost_ap_sample_size, + prWifiHotlistCmd->ap[0].channel, prWifiHotlistCmd->ap[0].low, prWifiHotlistCmd->ap[0].high, + prWifiHotlistCmd->ap[1].channel, prWifiHotlistCmd->ap[1].low, prWifiHotlistCmd->ap[1].high); + + memcpy(&(rCmdPscnAddHotlist.aucMacAddr), &(prWifiHotlistCmd->ap[0].bssid), 6 * sizeof(UINT_8)); + rCmdPscnAddHotlist.ucFlags = (UINT_8) TRUE; + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + kalMemFree(prWifiHotlistCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_BSSID_HOTLIST)); + kalMemFree(attr, VIR_MEM_TYPE, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1)); + return 0; + +nla_put_failure: + if (prWifiHotlistCmd) + kalMemFree(prWifiHotlistCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_BSSID_HOTLIST)); + if (attr) + kalMemFree(attr, VIR_MEM_TYPE, + sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1)); + return i4Status; +} + +#if CFG_SUPPORT_GSCN +int mtk_cfg80211_vendor_enable_scan(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_WIFI_GSCAN_ACTION_CMD_PARAMS rWifiScanActionCmd; + + INT_32 i4Status = -EINVAL; + struct nlattr *attr; + UINT_8 gGScanEn = 0; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + DBGLOG(REQ, TRACE, "vendor command: data_len=%d, data=0x%x 0x%x\r\n", + data_len, *((UINT_32 *) data), *((UINT_32 *) data + 1)); + + attr = (struct nlattr *)data; + if (attr->nla_type == GSCAN_ATTRIBUTE_ENABLE_FEATURE) + gGScanEn = nla_get_u32(attr); + DBGLOG(REQ, INFO, "gGScanEn=%d\r\n", gGScanEn); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + if (gGScanEn == TRUE) + rWifiScanActionCmd.ucPscanAct = PSCAN_ACT_ENABLE; + else + rWifiScanActionCmd.ucPscanAct = PSCAN_ACT_DISABLE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetGSCNAction, + &rWifiScanActionCmd, + sizeof(PARAM_WIFI_GSCAN_ACTION_CMD_PARAMS), FALSE, FALSE, TRUE, &u4BufLen); + + return 0; + +nla_put_failure: + return i4Status; +} + +int mtk_cfg80211_vendor_enable_full_scan_results(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + INT_32 i4Status = -EINVAL; + struct nlattr *attr; + UINT_8 gFullScanResultsEn = 0; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + DBGLOG(REQ, TRACE, "vendor command: data_len=%d, data=0x%x 0x%x\r\n", + data_len, *((UINT_32 *) data), *((UINT_32 *) data + 1)); + + attr = (struct nlattr *)data; + if (attr->nla_type == GSCAN_ENABLE_FULL_SCAN_RESULTS) + gFullScanResultsEn = nla_get_u32(attr); + DBGLOG(REQ, INFO, "gFullScanResultsEn=%d\r\n", gFullScanResultsEn); + + return 0; + +nla_put_failure: + return i4Status; +} + +int mtk_cfg80211_vendor_get_gscan_result(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + /*WLAN_STATUS rStatus;*/ + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_WIFI_GSCAN_GET_RESULT_PARAMS rGScanResultParm; + + INT_32 i4Status = -EINVAL; + struct nlattr *attr; + UINT_32 get_num = 0, real_num = 0; + UINT_8 flush = 0; + /* PARAM_WIFI_GSCAN_RESULT result[4], *pResult; */ + /* struct sk_buff *skb; */ + int i; /*int j;*/ + /* UINT_32 scan_id; */ + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + DBGLOG(REQ, TRACE, "vendor command: data_len=%d\r\n", data_len); + for (i = 0; i < 2; i++) + DBGLOG(REQ, LOUD, "0x%x 0x%x 0x%x 0x%x\r\n", *((UINT_32 *) data + i * 4), + *((UINT_32 *) data + i * 4 + 1), *((UINT_32 *) data + i * 4 + 2), + *((UINT_32 *) data + i * 4 + 3)); + + attr = (struct nlattr *)data; + if (attr->nla_type == GSCAN_ATTRIBUTE_NUM_OF_RESULTS) { + get_num = nla_get_u32(attr); + attr = (struct nlattr *)((UINT_8 *) attr + attr->nla_len); + } + if (attr->nla_type == GSCAN_ATTRIBUTE_FLUSH_RESULTS) { + flush = nla_get_u8(attr); + attr = (struct nlattr *)((UINT_8 *) attr + attr->nla_len); + } + DBGLOG(REQ, TRACE, "number=%d, flush=%d\r\n", get_num, flush); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + /* parameter validity check */ + real_num = (get_num < PSCAN_MAX_AP_CACHE_PER_SCAN) ? get_num : PSCAN_MAX_AP_CACHE_PER_SCAN; + get_num = real_num; + + if (flush) + flush = TRUE; + + rGScanResultParm.get_num = get_num; + rGScanResultParm.flush = flush; + + kalIoctl(prGlueInfo, + wlanoidGetGSCNResult, + &rGScanResultParm, sizeof(PARAM_WIFI_GSCAN_GET_RESULT_PARAMS), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "u4BufLen=%d\r\n", u4BufLen); + return 0; + +nla_put_failure: + return i4Status; +} + +int mtk_cfg80211_vendor_gscan_results(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len, BOOLEAN complete, BOOLEAN compValue) +{ + P_PARAM_WIFI_GSCAN_RESULT_REPORT prGscnResult = NULL; + UINT_32 u4SizeofGScanResults; + P_PARAM_WIFI_GSCAN_RESULT prResults = NULL; /* similar to WIFI_GSCAN_RESULT_T*/ + UINT_32 scan_id = 0; + UINT_8 scan_flag = 0; + UINT_32 real_num = 0; + UINT_32 ch_bucket_mask = 0; + INT_32 i4Status = -EINVAL; + struct sk_buff *skb; + struct nlattr *attr1, *attr2; + + ASSERT(data); + prGscnResult = (P_PARAM_WIFI_GSCAN_RESULT_REPORT)data; + u4SizeofGScanResults = data_len; + + if (prGscnResult) { + scan_id = prGscnResult->u4ScanId; + scan_flag = prGscnResult->ucScanFlag; + ch_bucket_mask = prGscnResult->u4BucketMask; + real_num = prGscnResult->u4NumOfResults; + } + if (complete) + DBGLOG(SCN, INFO, "complete=%d, compValue=%d", complete, compValue); + else + DBGLOG(SCN, TRACE, "scan_id=%d 0x%x, bkt=0x%x, num=%d, u4SizeofGScanResults=%d\r\n", + scan_id, scan_flag, ch_bucket_mask, real_num, u4SizeofGScanResults); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, u4SizeofGScanResults); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed:%x\n", __func__, i4Status); + return -ENOMEM; + } + + attr1 = nla_nest_start(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS); + + if (complete == TRUE) { + /* NLA_PUT_U8(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, 1); */ + { + unsigned char __tmp = compValue; + + if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + } else { + attr2 = nla_nest_start(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS); + + /*NLA_PUT_U32(skb, GSCAN_ATTRIBUTE_SCAN_ID, scan_id);*/ + { + unsigned int __tmp = scan_id; + + if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_SCAN_ID, sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + /*NLA_PUT_U8(skb, GSCAN_ATTRIBUTE_SCAN_FLAGS, 1);*/ + { + unsigned char __tmp = scan_flag; + + if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_SCAN_FLAGS, sizeof(u8), &__tmp) < 0)) + goto nla_put_failure; + } + /*NLA_PUT_U32(skb, GSCAN_ATTRIBUTE_NUM_OF_RESULTS, real_num);*/ + { + unsigned int __tmp = real_num; + + if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_NUM_OF_RESULTS, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + { + unsigned int __tmp = ch_bucket_mask; + + if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + if (prGscnResult) + prResults = (P_PARAM_WIFI_GSCAN_RESULT) prGscnResult->rResult; + if (prResults) { + /*NLA_PUT(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS, + *sizeof(PARAM_WIFI_GSCAN_RESULT) * real_num, prResults); + */ + if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS, + sizeof(PARAM_WIFI_GSCAN_RESULT)*real_num, prResults) < 0)) + goto nla_put_failure; + } + + if (attr2) + nla_nest_end(skb, attr2); + } + + if (attr1) + nla_nest_end(skb, attr1); + + i4Status = cfg80211_vendor_cmd_reply(skb); + if (i4Status) + DBGLOG(REQ, ERROR, "i4Status=%d real_num=%d\n", i4Status, real_num); + return real_num; + +nla_put_failure: + kfree_skb(skb); + DBGLOG(REQ, ERROR, "nla_put_failure\n"); + return -ENOMEM; +} +#endif + +int mtk_cfg80211_vendor_get_rtt_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Status = -EINVAL; + PARAM_WIFI_RTT_CAPABILITIES rRttCapabilities; + struct sk_buff *skb; + + DBGLOG(REQ, TRACE, "vendor command\r\n"); + + ASSERT(wiphy); + ASSERT(wdev); + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(rRttCapabilities)); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed:%x\n", __func__, i4Status); + return -ENOMEM; + } + + kalMemZero(&rRttCapabilities, sizeof(rRttCapabilities)); + + /* RTT Capabilities return from driver not firmware */ + rRttCapabilities.rtt_one_sided_supported = 0; + rRttCapabilities.rtt_ftm_supported = 1; + rRttCapabilities.lci_support = 1; + rRttCapabilities.lcr_support = 1; + rRttCapabilities.preamble_support = 0x07; + rRttCapabilities.bw_support = 0x1c; + + if (unlikely(nla_put(skb, RTT_ATTRIBUTE_CAPABILITIES, + sizeof(rRttCapabilities), &rRttCapabilities) < 0)) + goto nla_put_failure; + + i4Status = cfg80211_vendor_cmd_reply(skb); + return i4Status; + +nla_put_failure: + kfree_skb(skb); + return i4Status; +} + +int mtk_cfg80211_vendor_llstats_get_info(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + INT_32 i4Status = -EINVAL; + WIFI_RADIO_STAT *pRadioStat; + struct sk_buff *skb; + UINT_32 u4BufLen = 0; + + ASSERT(wiphy); + ASSERT(wdev); + + u4BufLen = sizeof(WIFI_RADIO_STAT) + sizeof(WIFI_IFACE_STAT); + pRadioStat = kalMemAlloc(u4BufLen, VIR_MEM_TYPE); + if (!pRadioStat) { + DBGLOG(REQ, ERROR, "%s kalMemAlloc pRadioStat failed\n", __func__); + return -ENOMEM; + } + kalMemZero(pRadioStat, u4BufLen); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, u4BufLen); + if (!skb) { + kalMemFree(pRadioStat, VIR_MEM_TYPE, u4BufLen); + DBGLOG(REQ, TRACE, "%s allocate skb failed:%x\n", __func__, i4Status); + return -ENOMEM; + } + +#if 0 + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStatistics, + &rRadioStat, + sizeof(rRadioStat), + TRUE, + TRUE, + TRUE, + FALSE, + &u4BufLen); +#endif + /* only for test */ + pRadioStat->radio = 10; + pRadioStat->on_time = 11; + pRadioStat->tx_time = 12; + pRadioStat->num_channels = 4; + + /*NLA_PUT(skb, LSTATS_ATTRIBUTE_STATS, u4BufLen, pRadioStat);*/ + if (unlikely(nla_put(skb, LSTATS_ATTRIBUTE_STATS, u4BufLen, pRadioStat) < 0)) + goto nla_put_failure; + + i4Status = cfg80211_vendor_cmd_reply(skb); + kalMemFree(pRadioStat, VIR_MEM_TYPE, u4BufLen); + return -1; /* not support LLS now*/ + /* return i4Status; */ + +nla_put_failure: + kalMemFree(pRadioStat, VIR_MEM_TYPE, u4BufLen); + kfree_skb(skb); + return i4Status; +} + +int mtk_cfg80211_vendor_set_rssi_monitoring(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + + INT_32 i4Status = -EINVAL; + PARAM_RSSI_MONITOR_T rRSSIMonitor; + struct nlattr *attr[WIFI_ATTRIBUTE_RSSI_MONITOR_START + 1]; + UINT_32 i = 0; + + ASSERT(wiphy); + ASSERT(wdev); + + DBGLOG(REQ, TRACE, "vendor command: data_len=%d\r\n", data_len); + kalMemZero(&rRSSIMonitor, sizeof(PARAM_RSSI_MONITOR_T)); + if ((data == NULL) || !data_len) + goto nla_put_failure; + kalMemZero(attr, sizeof(struct nlattr *) * (WIFI_ATTRIBUTE_RSSI_MONITOR_START + 1)); + + if (NLA_PARSE_NESTED(attr, WIFI_ATTRIBUTE_RSSI_MONITOR_START, + (struct nlattr *)(data - NLA_HDRLEN), nla_parse_wifi_policy) < 0) { + DBGLOG(REQ, ERROR, "%s nla_parse_nested failed\n", __func__); + goto nla_put_failure; + } + + for (i = WIFI_ATTRIBUTE_MAX_RSSI; i <= WIFI_ATTRIBUTE_RSSI_MONITOR_START; i++) { + if (attr[i]) { + switch (i) { + case WIFI_ATTRIBUTE_MAX_RSSI: + rRSSIMonitor.max_rssi_value = nla_get_u32(attr[i]); + break; + case WIFI_ATTRIBUTE_MIN_RSSI: + rRSSIMonitor.min_rssi_value = nla_get_u32(attr[i]); + break; + case WIFI_ATTRIBUTE_RSSI_MONITOR_START: + rRSSIMonitor.enable = nla_get_u32(attr[i]); + break; + } + } + } + + DBGLOG(REQ, INFO, "mMax_rssi=%d, mMin_rssi=%d enable=%d\r\n", + rRSSIMonitor.max_rssi_value, rRSSIMonitor.min_rssi_value, rRSSIMonitor.enable); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + if (rRSSIMonitor.enable == TRUE) { + if (wdev->current_bss == NULL || + kalGetMediaStateIndicated(prGlueInfo) == PARAM_MEDIA_STATE_DISCONNECTED) { + DBGLOG(REQ, TRACE, "Reject Requsts to enable RSSI monitor when disconnected\n"); + return -EINVAL; + } + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidRssiMonitor, + &rRSSIMonitor, sizeof(PARAM_RSSI_MONITOR_T), FALSE, FALSE, TRUE, &u4BufLen); + return rStatus; + +nla_put_failure: + return i4Status; +} + +int mtk_cfg80211_vendor_packet_keep_alive_start(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + + INT_32 i4Status = -EINVAL; + P_PARAM_PACKET_KEEPALIVE_T prPkt = NULL; + struct nlattr *attr[MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC + 1]; + UINT_32 i = 0; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + + DBGLOG(REQ, TRACE, "vendor command: data_len=%d\r\n", data_len); + prPkt = (P_PARAM_PACKET_KEEPALIVE_T) kalMemAlloc(sizeof(PARAM_PACKET_KEEPALIVE_T), VIR_MEM_TYPE); + if (!prPkt) { + DBGLOG(REQ, ERROR, "Can not alloc memory for PARAM_PACKET_KEEPALIVE_T\n"); + return -ENOMEM; + } + kalMemZero(prPkt, sizeof(PARAM_PACKET_KEEPALIVE_T)); + kalMemZero(attr, sizeof(struct nlattr *) * (MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC + 1)); + + prPkt->enable = TRUE; /*start packet keep alive*/ + if (NLA_PARSE_NESTED(attr, MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC, + (struct nlattr *)(data - NLA_HDRLEN), nla_parse_offloading_policy) < 0) { + DBGLOG(REQ, ERROR, "%s nla_parse_nested failed\n", __func__); + goto nla_put_failure; + } + + for (i = MKEEP_ALIVE_ATTRIBUTE_ID; i <= MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC; i++) { + if (attr[i]) { + switch (i) { + case MKEEP_ALIVE_ATTRIBUTE_ID: + prPkt->index = nla_get_u8(attr[i]); + break; + case MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN: + prPkt->u2IpPktLen = (nla_get_u16(attr[i]) > sizeof(prPkt->pIpPkt)) + ? sizeof(prPkt->pIpPkt):nla_get_u16(attr[i]); + break; + case MKEEP_ALIVE_ATTRIBUTE_IP_PKT: + kalMemCopy(prPkt->pIpPkt, nla_data(attr[i]), prPkt->u2IpPktLen); + break; + case MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR: + kalMemCopy(prPkt->ucSrcMacAddr, nla_data(attr[i]), sizeof(mac_addr)); + break; + case MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR: + kalMemCopy(prPkt->ucDstMacAddr, nla_data(attr[i]), sizeof(mac_addr)); + break; + case MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC: + prPkt->u4PeriodMsec = nla_get_u32(attr[i]); + break; + } + } + } + + DBGLOG(REQ, INFO, "enable=%d, index=%d, u2IpPktLen=%d u4PeriodMsec=%d\n", + prPkt->enable, prPkt->index, prPkt->u2IpPktLen, prPkt->u4PeriodMsec); + DBGLOG(REQ, TRACE, "prPkt->pIpPkt=0x%02x%02x%02x%02x, %02x%02x%02x%02x, %02x%02x%02x%02x, %02x%02x%02x%02x", + prPkt->pIpPkt[0], prPkt->pIpPkt[1], prPkt->pIpPkt[2], prPkt->pIpPkt[3], + prPkt->pIpPkt[4], prPkt->pIpPkt[5], prPkt->pIpPkt[6], prPkt->pIpPkt[7], + prPkt->pIpPkt[8], prPkt->pIpPkt[9], prPkt->pIpPkt[10], prPkt->pIpPkt[11], + prPkt->pIpPkt[12], prPkt->pIpPkt[13], prPkt->pIpPkt[14], prPkt->pIpPkt[15]); + DBGLOG(REQ, TRACE, "prPkt->srcMAC=%02x:%02x:%02x:%02x:%02x:%02x, dstMAC=%02x:%02x:%02x:%02x:%02x:%02x\n", + prPkt->ucSrcMacAddr[0], prPkt->ucSrcMacAddr[1], prPkt->ucSrcMacAddr[2], prPkt->ucSrcMacAddr[3], + prPkt->ucSrcMacAddr[4], prPkt->ucSrcMacAddr[5], + prPkt->ucDstMacAddr[0], prPkt->ucDstMacAddr[1], prPkt->ucDstMacAddr[2], prPkt->ucDstMacAddr[3], + prPkt->ucDstMacAddr[4], prPkt->ucDstMacAddr[5]); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidPacketKeepAlive, + prPkt, sizeof(PARAM_PACKET_KEEPALIVE_T), FALSE, FALSE, TRUE, &u4BufLen); + kalMemFree(prPkt, VIR_MEM_TYPE, sizeof(PARAM_PACKET_KEEPALIVE_T)); + return rStatus; + +nla_put_failure: + if (prPkt != NULL) + kalMemFree(prPkt, VIR_MEM_TYPE, sizeof(PARAM_PACKET_KEEPALIVE_T)); + return i4Status; +} + +int mtk_cfg80211_vendor_packet_keep_alive_stop(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + + INT_32 i4Status = -EINVAL; + P_PARAM_PACKET_KEEPALIVE_T prPkt = NULL; + struct nlattr *attr; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + + DBGLOG(REQ, TRACE, "vendor command: data_len=%d\r\n", data_len); + prPkt = (P_PARAM_PACKET_KEEPALIVE_T) kalMemAlloc(sizeof(PARAM_PACKET_KEEPALIVE_T), VIR_MEM_TYPE); + if (!prPkt) { + DBGLOG(REQ, ERROR, "Can not alloc memory for PARAM_PACKET_KEEPALIVE_T\n"); + return -ENOMEM; + } + kalMemZero(prPkt, sizeof(PARAM_PACKET_KEEPALIVE_T)); + + prPkt->enable = FALSE; /*stop packet keep alive*/ + attr = (struct nlattr *)data; + if (attr->nla_type == MKEEP_ALIVE_ATTRIBUTE_ID) + prPkt->index = nla_get_u8(attr); + + DBGLOG(REQ, INFO, "enable=%d, index=%d\r\n", prPkt->enable, prPkt->index); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidPacketKeepAlive, + prPkt, sizeof(PARAM_PACKET_KEEPALIVE_T), FALSE, FALSE, TRUE, &u4BufLen); + kalMemFree(prPkt, VIR_MEM_TYPE, sizeof(PARAM_PACKET_KEEPALIVE_T)); + return rStatus; + +nla_put_failure: + if (prPkt != NULL) + kalMemFree(prPkt, VIR_MEM_TYPE, sizeof(PARAM_PACKET_KEEPALIVE_T)); + return i4Status; +} + +#if CFG_SUPPORT_GSCN +int mtk_cfg80211_vendor_event_complete_scan(struct wiphy *wiphy, struct wireless_dev *wdev, WIFI_SCAN_EVENT complete) +{ + struct sk_buff *skb; + WIFI_SCAN_EVENT complete_scan; + + ASSERT(wiphy); + ASSERT(wdev); + + DBGLOG(REQ, INFO, "vendor command complete=%d\r\n", complete); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + skb = cfg80211_vendor_event_alloc(wiphy, wdev, sizeof(complete), GSCAN_EVENT_COMPLETE_SCAN, GFP_KERNEL); +#else + skb = cfg80211_vendor_event_alloc(wiphy, sizeof(complete), GSCAN_EVENT_COMPLETE_SCAN, GFP_KERNEL); +#endif + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + complete_scan = WIFI_SCAN_RESULTS_AVAILABLE; + /*NLA_PUT_U32(skb, GSCAN_EVENT_COMPLETE_SCAN, complete);*/ + { + unsigned int __tmp = complete; + + if (unlikely(nla_put(skb, GSCAN_EVENT_COMPLETE_SCAN, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -ENOMEM; +} + +int mtk_cfg80211_vendor_event_scan_results_available(struct wiphy *wiphy, struct wireless_dev *wdev, UINT_32 num) +{ + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(wdev); + /* UINT_32 scan_result; */ + + DBGLOG(REQ, INFO, "vendor command num=%d\r\n", num); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + skb = cfg80211_vendor_event_alloc(wiphy, wdev, sizeof(num), GSCAN_EVENT_SCAN_RESULTS_AVAILABLE, GFP_KERNEL); +#else + skb = cfg80211_vendor_event_alloc(wiphy, sizeof(num), GSCAN_EVENT_COMPLETE_SCAN, GFP_KERNEL); +#endif + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + /* scan_result = 2; */ + /*NLA_PUT_U32(skb, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE, num);*/ + { + unsigned int __tmp = num; + + if (unlikely(nla_put(skb, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -ENOMEM; +} + +int mtk_cfg80211_vendor_event_full_scan_results(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_GSCAN_FULL_RESULT pdata, UINT_32 data_len) +{ + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(wdev); + ASSERT(pdata); + DBGLOG(REQ, TRACE, "ssid=%s, bssid="MACSTR", rssi=%d, %d, capa=0x%x, ie_length=%d\n", + pdata->fixed.ssid, + MAC2STR(pdata->fixed.bssid), + pdata->fixed.rssi, + pdata->fixed.channel, + pdata->fixed.capability, + pdata->ie_length); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + skb = cfg80211_vendor_event_alloc(wiphy, wdev, data_len, GSCAN_EVENT_FULL_SCAN_RESULTS, GFP_KERNEL); +#else + skb = cfg80211_vendor_event_alloc(wiphy, data_len, GSCAN_EVENT_FULL_SCAN_RESULTS, GFP_KERNEL); +#endif + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + /* kalMemCopy(&full_result, pdata, sizeof(PARAM_WIFI_GSCAN_FULL_RESULT); */ + /*NLA_PUT(skb, GSCAN_EVENT_FULL_SCAN_RESULTS, sizeof(full_result), &full_result);*/ + if (unlikely(nla_put(skb, GSCAN_EVENT_FULL_SCAN_RESULTS, + data_len, pdata) < 0)) + goto nla_put_failure; + + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -ENOMEM; +} +#endif + +int mtk_cfg80211_vendor_event_significant_change_results(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_CHANGE_RESULT pdata, UINT_32 data_len) +{ + struct sk_buff *skb; + PARAM_WIFI_CHANGE_RESULT result[2], *presult; + + ASSERT(wiphy); + ASSERT(wdev); + DBGLOG(REQ, TRACE, "vendor command\r\n"); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + skb = cfg80211_vendor_event_alloc(wiphy, wdev, sizeof(PARAM_WIFI_CHANGE_RESULT), + GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS, GFP_KERNEL); +#else + skb = cfg80211_vendor_event_alloc(wiphy, sizeof(PARAM_WIFI_CHANGE_RESULT), + GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS, GFP_KERNEL); +#endif + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + presult = result; + kalMemZero(presult, (sizeof(PARAM_WIFI_CHANGE_RESULT) * 2)); + /* only for test */ + kalMemCopy(presult->bssid, "213123", sizeof(mac_addr)); + presult->channel = 2437; + presult->rssi[0] = -40; + presult->rssi[1] = -50; + presult++; + presult->channel = 2412; + presult->rssi[0] = -50; + presult->rssi[1] = -60; + /*NLA_PUT(skb, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS, (sizeof(PARAM_WIFI_CHANGE_RESULT) * 2), result);*/ + if (unlikely(nla_put(skb, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS, + (sizeof(PARAM_WIFI_CHANGE_RESULT) * 2), result) < 0)) + goto nla_put_failure; + + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -ENOMEM; +} + +int mtk_cfg80211_vendor_event_hotlist_ap_found(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_GSCAN_RESULT pdata, UINT_32 data_len) +{ + struct sk_buff *skb; + PARAM_WIFI_GSCAN_RESULT result[2], *presult; + + ASSERT(wiphy); + ASSERT(wdev); + DBGLOG(REQ, TRACE, "vendor command\r\n"); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + skb = cfg80211_vendor_event_alloc(wiphy, wdev, sizeof(PARAM_WIFI_GSCAN_RESULT), + GSCAN_EVENT_HOTLIST_RESULTS_FOUND, GFP_KERNEL); +#else + skb = cfg80211_vendor_event_alloc(wiphy, sizeof(PARAM_WIFI_GSCAN_RESULT), + GSCAN_EVENT_HOTLIST_RESULTS_FOUND, GFP_KERNEL); +#endif + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + presult = result; + kalMemZero(presult, (sizeof(PARAM_WIFI_GSCAN_RESULT) * 2)); + /* only for test */ + kalMemCopy(presult->bssid, "123123", sizeof(mac_addr)); + presult->channel = 2441; + presult->rssi = -45; + presult++; + presult->channel = 2443; + presult->rssi = -47; + /*NLA_PUT(skb, GSCAN_EVENT_HOTLIST_RESULTS_FOUND, (sizeof(PARAM_WIFI_GSCAN_RESULT) * 2), result);*/ + if (unlikely(nla_put(skb, GSCAN_EVENT_HOTLIST_RESULTS_FOUND, + (sizeof(PARAM_WIFI_GSCAN_RESULT) * 2), result) < 0)) + goto nla_put_failure; + + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -ENOMEM; +} + +int mtk_cfg80211_vendor_event_hotlist_ap_lost(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_GSCAN_RESULT pdata, UINT_32 data_len) +{ + struct sk_buff *skb; + PARAM_WIFI_GSCAN_RESULT result[2], *presult; + + ASSERT(wiphy); + ASSERT(wdev); + DBGLOG(REQ, TRACE, "vendor command\r\n"); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + skb = cfg80211_vendor_event_alloc(wiphy, wdev, sizeof(PARAM_WIFI_GSCAN_RESULT), + GSCAN_EVENT_HOTLIST_RESULTS_LOST, GFP_KERNEL); +#else + skb = cfg80211_vendor_event_alloc(wiphy, sizeof(PARAM_WIFI_GSCAN_RESULT), + GSCAN_EVENT_HOTLIST_RESULTS_LOST, GFP_KERNEL); +#endif + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + presult = result; + kalMemZero(presult, (sizeof(PARAM_WIFI_GSCAN_RESULT) * 2)); + /* only for test */ + kalMemCopy(presult->bssid, "321321", sizeof(mac_addr)); + presult->channel = 2442; + presult->rssi = -40; + presult++; + presult->channel = 2447; + presult->rssi = -50; + /*NLA_PUT(skb, GSCAN_EVENT_HOTLIST_RESULTS_LOST, (sizeof(PARAM_WIFI_GSCAN_RESULT) * 2), result);*/ + if (unlikely(nla_put(skb, GSCAN_EVENT_HOTLIST_RESULTS_LOST, + (sizeof(PARAM_WIFI_GSCAN_RESULT) * 2), result) < 0)) + goto nla_put_failure; + + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -ENOMEM; +} + +int mtk_cfg80211_vendor_event_rssi_beyond_range(struct wiphy *wiphy, struct wireless_dev *wdev, INT_32 rssi) +{ + struct sk_buff *skb; + PARAM_RSSI_MONITOR_EVENT rRSSIEvt; + P_BSS_INFO_T prAisBssInfo; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(wiphy); + ASSERT(wdev); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, TRACE, "vendor command rssi=%d\r\n", rssi); + kalMemZero(&rRSSIEvt, sizeof(PARAM_RSSI_MONITOR_EVENT)); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + skb = cfg80211_vendor_event_alloc(wiphy, wdev, sizeof(PARAM_RSSI_MONITOR_EVENT), + WIFI_EVENT_RSSI_MONITOR, GFP_KERNEL); +#else + skb = cfg80211_vendor_event_alloc(wiphy, sizeof(PARAM_RSSI_MONITOR_EVENT), + WIFI_EVENT_RSSI_MONITOR, GFP_KERNEL); +#endif + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + prAisBssInfo = &(prGlueInfo->prAdapter->rWifiVar.arBssInfoPool[NETWORK_TYPE_AIS]); + kalMemCopy(rRSSIEvt.BSSID, prAisBssInfo->aucBSSID, sizeof(UINT_8) * MAC_ADDR_LEN); + + rRSSIEvt.version = 1; /* RSSI_MONITOR_EVT_VERSION = 1 */ + if (rssi > PARAM_WHQL_RSSI_MAX_DBM) + rssi = PARAM_WHQL_RSSI_MAX_DBM; + else if (rssi < -127) + rssi = -127; + rRSSIEvt.rssi = (INT_8)rssi; + DBGLOG(REQ, INFO, "RSSI Event: version=%d, rssi=%d, BSSID=" MACSTR "\r\n", + rRSSIEvt.version, rRSSIEvt.rssi, MAC2STR(rRSSIEvt.BSSID)); + + /*NLA_PUT_U32(skb, GOOGLE_RSSI_MONITOR_EVENT, rssi);*/ + { + /* unsigned int __tmp = rssi; */ + + if (unlikely(nla_put(skb, WIFI_EVENT_RSSI_MONITOR, + sizeof(PARAM_RSSI_MONITOR_EVENT), &rRSSIEvt) < 0)) + goto nla_put_failure; + } + + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -ENOMEM; +} + +int mtk_cfg80211_vendor_set_roaming_policy(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + struct nlattr *attr; + UINT_32 setRoaming = 0; + UINT_32 u4BufLen = 0; + INT_32 i4Status = -EINVAL; + + ASSERT(wiphy); + ASSERT(wdev); + + if ((data == NULL) || !data_len) + goto nla_put_failure; + + attr = (struct nlattr *)data; + setRoaming = nla_get_u32(attr); + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, INFO, "vendor command: data_len=%d, data=0x%x 0x%x, roaming policy=%d\r\n", + data_len, *((UINT_32 *) data), *((UINT_32 *) data + 1), setRoaming); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetDrvRoamingPolicy, + &setRoaming, sizeof(UINT_32), FALSE, FALSE, TRUE, &u4BufLen); + + return rStatus; + +nla_put_failure: + return i4Status; + +} + +int mtk_cfg80211_vendor_get_supported_feature_set(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + uint64_t u8FeatureSet = WIFI_HAL_FEATURE_SET; + P_GLUE_INFO_T prGlueInfo; + P_REG_INFO_T prRegInfo; + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(wdev); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + if (!prGlueInfo) + return -EFAULT; + prRegInfo = &(prGlueInfo->rRegInfo); + if (!prRegInfo) + return -EFAULT; + + if (prRegInfo->ucSupport5GBand) + u8FeatureSet |= WIFI_FEATURE_INFRA_5G; + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u8FeatureSet)); + if (!skb) { + DBGLOG(REQ, ERROR, "Allocate skb failed\n"); + return -ENOMEM; + } + + if (unlikely( + nla_put_nohdr(skb, sizeof(u8FeatureSet), &u8FeatureSet) < 0)) { + DBGLOG(REQ, ERROR, "nla_put_nohdr failed\n"); + goto nla_put_failure; + } + + DBGLOG(REQ, TRACE, "supported feature set=0x%llx\n", u8FeatureSet); + + return cfg80211_vendor_cmd_reply(skb); + +nla_put_failure: + kfree_skb(skb); + return -EFAULT; +} +int mtk_cfg80211_vendor_get_version(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + struct sk_buff *skb; + struct nlattr *attrlist; + char verInfoBuf[64]; + UINT_32 u4CopySize = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + return -ENOMEM; + kalMemZero(verInfoBuf, 64); + attrlist = (struct nlattr *)((UINT_8 *) data); + if (attrlist->nla_type == LOGGER_ATTRIBUTE_DRIVER_VER) { + char wifiDriverVersionStr[] = NIC_DRIVER_VERSION_STRING"-"DRIVER_BUILD_DATE; + UINT_32 u4StrSize = strlen(wifiDriverVersionStr); + u4CopySize = (u4StrSize >= 64) ? 63 : u4StrSize; + strncpy(verInfoBuf, wifiDriverVersionStr, u4CopySize); + } else if (attrlist->nla_type == LOGGER_ATTRIBUTE_FW_VER) { + WIFI_VER_INFO_T *prVerInfo; + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + prVerInfo = &(prGlueInfo->prAdapter->rVerInfo); + if (0 > sprintf(verInfoBuf, "%x.%x.%x", + (prVerInfo->u2FwOwnVersion >> 8), + (prVerInfo->u2FwOwnVersion & 0xff), + prVerInfo->u4FwOwnVersionExtend)) { + return -EFAULT; + } + u4CopySize = strlen(verInfoBuf); + } + if (u4CopySize <= 0) + return -EFAULT; + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, u4CopySize); + if (!skb) { + DBGLOG(REQ, ERROR, "Allocate skb failed\n"); + return -ENOMEM; + } + if (unlikely(nla_put_nohdr(skb, u4CopySize, &verInfoBuf[0]) < 0)) + goto nla_put_failure; + return cfg80211_vendor_cmd_reply(skb); +nla_put_failure: + kfree_skb(skb); + return -EFAULT; +} +int mtk_cfg80211_vendor_set_tx_power_scenario(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + /*Gen3 firmware do not support, just return*/ + return -EOPNOTSUPP; +} +int mtk_cfg80211_vendor_set_scan_mac_oui(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 rStatus = WLAN_STATUS_SUCCESS; + struct nlattr *attr; + UINT_32 i = 0; + struct PARAM_BSS_MAC_OUI rParamMacOui; + UINT_32 u4BufLen = 0; + P_NETDEV_PRIVATE_GLUE_INFO prNetDevPrivate = NULL; + + ASSERT(wiphy); + ASSERT(wdev); + + if (data == NULL || data_len <= 0) { + DBGLOG(REQ, ERROR, "data error(len=%d)\n", data_len); + return -EINVAL; + } + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + if (!prGlueInfo) { + DBGLOG(REQ, ERROR, "Invalid glue info\n"); + return -EFAULT; + } + prNetDevPrivate = + (P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(wdev->netdev); + if (!prNetDevPrivate) { + DBGLOG(REQ, ERROR, "Invalid net device private\n"); + return -EFAULT; + } + rParamMacOui.ucBssIndex = prNetDevPrivate->ucBssIdx; + + attr = (struct nlattr *)data; + kalMemZero(rParamMacOui.ucMacOui, MAC_OUI_LEN); + if (nla_type(attr) != WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI) { + DBGLOG(REQ, ERROR, "Set MAC oui type error(%u)\n", + nla_type(attr)); + return -EINVAL; + } + + if (nla_len(attr) != MAC_OUI_LEN) { + DBGLOG(REQ, ERROR, "Set MAC oui length error(%u), %u needed\n", + nla_len(attr), MAC_OUI_LEN); + return -EINVAL; + } + + for (i = 0; i < MAC_OUI_LEN; i++) + rParamMacOui.ucMacOui[i] = *((P_UINT_8)nla_data(attr) + i); + + DBGLOG(REQ, INFO, "Set MAC oui: %02x-%02x-%02x\n", + rParamMacOui.ucMacOui[0], rParamMacOui.ucMacOui[1], + rParamMacOui.ucMacOui[2]); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetScanMacOui, + &rParamMacOui, sizeof(rParamMacOui), + FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "Set MAC oui error: 0x%X\n", rStatus); + return -EFAULT; + } + + return 0; +} +int mtk_cfg80211_vendor_driver_memory_dump(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + struct LINK_QUALITY_INFO_OUTPUT_DATA { + UINT_16 u2Tag01; /* cur tx rate */ + UINT_16 u2Len01; + UINT_32 u4CurTxRate; + UINT_16 u2Tag02; /* tx total count */ + UINT_16 u2Len02; + UINT_64 u8TxTotalCount; + UINT_16 u2Tag03; /* tx retry count */ + UINT_16 u2Len03; + UINT_64 u8TxRetryCount; + UINT_16 u2Tag04; /* tx fail Count */ + UINT_16 u2Len04; + UINT_64 u8TxFailCount; + UINT_16 u2Tag05; /* Rts fail count */ + UINT_16 u2Len05; + UINT_64 u8TxRtsFailCount; + UINT_16 u2Tag06; /* Ack fail count */ + UINT_16 u2Len06; + UINT_64 u8TxAckFailCount; + UINT_16 u2Tag07; /* cur rx rate */ + UINT_16 u2Len07; + UINT_32 u4CurRxRate; + UINT_16 u2Tag08; /* Rx total count */ + UINT_16 u2Len08; + UINT_64 u8RxTotalCount; + UINT_16 u2Tag09; /* Rx dup count */ + UINT_16 u2Len09; + UINT_32 u4RxDupCount; + UINT_16 u2Tag10; /* Rx err count */ + UINT_16 u2Len10; + UINT_64 u8RxErrCount; + UINT_16 u2Tag11; /* Idle slot count */ + UINT_16 u2Len11; + UINT_64 u8IdleSlotCount; + } __packed outputData = { + .u2Tag01 = 1, /* tag: 1, cur tx rate */ + .u2Len01 = 4, /* len: 4, bytes */ + .u2Tag02 = 2, /* tag: 2, tx total count */ + .u2Len02 = 8, /* len: 8, bytes */ + .u2Tag03 = 3, /* tag: 3, tx retry count */ + .u2Len03 = 8, /* len: 8, bytes */ + .u2Tag04 = 4, /* tag: 4, tx fail count */ + .u2Len04 = 8, /* len: 8, bytes */ + .u2Tag05 = 5, /* tag: 5, tx rts fail count */ + .u2Len05 = 8, /* len: 8, bytes */ + .u2Tag06 = 6, /* tag: 6, tx ack fail count */ + .u2Len06 = 8, /* len: 8, bytes */ + .u2Tag07 = 7, /* tag: 7, cur rx rate */ + .u2Len07 = 4, /* len: 4, bytes */ + .u2Tag08 = 8, /* tag: 8, rx total count */ + .u2Len08 = 8, /* len: 8, bytes */ + .u2Tag09 = 9, /* tag: 9, rx dup count */ + .u2Len09 = 4, /* len: 4, bytes */ + .u2Tag10 = 10, /* tag: 10, rx err count */ + .u2Len10 = 8, /* len: 8, bytes */ + .u2Tag11 = 11, + .u2Len11 = 8 + }; + struct PARAM_GET_LINK_QUALITY_INFO rParam; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate; + struct WIFI_LINK_QUALITY_INFO rLinkQualityInfo; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4BufLen; +#endif + struct sk_buff *skb = NULL; + UINT_32 *puBuufer = NULL; + INT_32 i4Status = -EINVAL; + UINT_16 u2CopySize = 0; + + ASSERT(wiphy); + ASSERT(wdev); +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + prNetDevPrivate = + (struct NETDEV_PRIVATE_GLUE_INFO *) netdev_priv(wdev->netdev); + if (!prNetDevPrivate) { + DBGLOG(REQ, ERROR, "Invalid net device private\n"); + return -EFAULT; + } + rParam.ucBssIdx = 0; /* prNetDevPrivate->ucBssIdx; */ + rParam.prLinkQualityInfo = &rLinkQualityInfo; + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + i4Status = kalIoctl(prGlueInfo, wlanoidGetLinkQualityInfo, + &rParam, sizeof(struct PARAM_GET_LINK_QUALITY_INFO), + TRUE, FALSE, FALSE, &u4BufLen); + if (i4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "wlanoidGetLinkQualityInfo error\n"); + goto err_handle_label; + } + + outputData.u4CurTxRate = rLinkQualityInfo.u4CurTxRate; + outputData.u8TxTotalCount = rLinkQualityInfo.u8TxTotalCount; + outputData.u8TxRetryCount = rLinkQualityInfo.u8TxRetryCount; + outputData.u8TxFailCount = rLinkQualityInfo.u8TxFailCount; + outputData.u8TxRtsFailCount = rLinkQualityInfo.u8TxRtsFailCount; + outputData.u8TxAckFailCount = rLinkQualityInfo.u8TxAckFailCount; + outputData.u4CurRxRate = rLinkQualityInfo.u4CurRxRate; + outputData.u8RxTotalCount = rLinkQualityInfo.u8RxTotalCount; + outputData.u4RxDupCount = rLinkQualityInfo.u4RxDupCount; + outputData.u8RxErrCount = rLinkQualityInfo.u8RxErrCount; + outputData.u8IdleSlotCount = rLinkQualityInfo.u8IdleSlotCount; + + DBGLOG(REQ, INFO, + "LQ: Tx(rate:%u, total:%u, Rty:%lu, fail:%lu, RTSF:%lu, ACKF:%lu), Rx(rate:%u, total:%u, dup:%u, error:%lu), Idle:%lu\n", + outputData.u4CurTxRate, /* tx rate, current tx link speed */ + outputData.u8TxTotalCount, /* tx total packages */ + outputData.u8TxRetryCount, /* tx retry count */ + outputData.u8TxFailCount, /* tx fail count */ + outputData.u8TxRtsFailCount, /* tx RTS fail count */ + outputData.u8TxAckFailCount, /* tx ACK fail count */ + outputData.u4CurRxRate, /* rx rate */ + outputData.u8RxTotalCount, /* rx total packages */ + outputData.u4RxDupCount, /* rx duplicate package count */ + outputData.u8RxErrCount, /* rx error count */ + outputData.u8IdleSlotCount + ); + + u2CopySize = sizeof(struct LINK_QUALITY_INFO_OUTPUT_DATA); + puBuufer = (UINT_32 *)&outputData; +#endif + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, u2CopySize); + if (!skb) { + DBGLOG(REQ, ERROR, "allocate skb failed\n"); + i4Status = -ENOMEM; + goto err_handle_label; + } + + if (unlikely(nla_put_nohdr(skb, u2CopySize, puBuufer) < 0)) { + DBGLOG(REQ, ERROR, "nla_put_nohdr failed: len=%u, ptr=%p\n", + u2CopySize, puBuufer); + kfree_skb(skb); + i4Status = -EINVAL; + goto err_handle_label; + } + + i4Status = cfg80211_vendor_cmd_reply(skb); + +err_handle_label: + return i4Status; +} +int mtk_cfg80211_vendor_acs(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo; + struct nlattr *tb[WIFI_VENDOR_ATTR_ACS_MAX + 1] = { 0 }; + UINT_32 rStatus = WLAN_STATUS_SUCCESS; + bool ht_enabled, ht40_enabled, vht_enabled; + UINT_8 ch_width = 0; + enum P2P_VENDOR_ACS_HW_MODE hw_mode; + UINT_8 *ch_list = NULL; + UINT_8 ch_list_count = 0; + UINT_8 i; + UINT_32 msg_size; + struct MSG_P2P_ACS_REQUEST *prMsgAcsRequest; + P_RF_CHANNEL_INFO_T prRfChannelInfo; + struct sk_buff *reply_skb; + UINT_8 role_idx; + + if (!wiphy || !wdev || !data || !data_len) { + DBGLOG(REQ, ERROR, "input data null.\n"); + rStatus = -EINVAL; + goto exit; + } + + if (wdev->iftype == NL80211_IFTYPE_AP) + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + else + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + if (!prGlueInfo) { + DBGLOG(REQ, ERROR, "get glue structure fail.\n"); + rStatus = -EFAULT; + goto exit; + } + /*gen3 mtk_Netdev_To_RoleIdx:the first parameter is P_GL_P2P_INFO_T*/ + if (mtk_Netdev_To_RoleIdx(prGlueInfo->prP2PInfo, wdev->netdev, &role_idx) < 0) { + DBGLOG(REQ, ERROR, "get role index fail.\n"); + rStatus = -EFAULT; + goto exit; + } + + if (p2pRoleFsmIsAcsProcessing(prGlueInfo->prAdapter, role_idx)) { + DBGLOG(REQ, ERROR, "acs is already in processing.\n"); + rStatus = -EBUSY; + goto exit; + } + /*does it use nla_parse api in gen3?*/ + if (NLA_PARSE(tb, WIFI_VENDOR_ATTR_ACS_MAX, data, data_len, + nla_get_acs_policy)) { + DBGLOG(REQ, ERROR, "parse acs attr fail.\n"); + rStatus = -EINVAL; + goto exit; + } + + if (!tb[WIFI_VENDOR_ATTR_ACS_HW_MODE]) { + DBGLOG(REQ, ERROR, "attr hw_mode failed.\n"); + rStatus = -EINVAL; + goto exit; + } + hw_mode = nla_get_u8(tb[WIFI_VENDOR_ATTR_ACS_HW_MODE]); + + if (tb[WIFI_VENDOR_ATTR_ACS_HT_ENABLED]) + ht_enabled = + nla_get_flag(tb[WIFI_VENDOR_ATTR_ACS_HT_ENABLED]); + else + ht_enabled = 0; + + if (tb[WIFI_VENDOR_ATTR_ACS_HT40_ENABLED]) + ht40_enabled = + nla_get_flag(tb[WIFI_VENDOR_ATTR_ACS_HT40_ENABLED]); + else + ht40_enabled = 0; + + if (tb[WIFI_VENDOR_ATTR_ACS_VHT_ENABLED]) + vht_enabled = + nla_get_flag(tb[WIFI_VENDOR_ATTR_ACS_VHT_ENABLED]); + else + vht_enabled = 0; + + if (tb[WIFI_VENDOR_ATTR_ACS_CHWIDTH]) + ch_width = nla_get_u16(tb[WIFI_VENDOR_ATTR_ACS_CHWIDTH]); + + if (tb[WIFI_VENDOR_ATTR_ACS_CH_LIST]) { + char *tmp = nla_data(tb[WIFI_VENDOR_ATTR_ACS_CH_LIST]); + + ch_list_count = nla_len(tb[WIFI_VENDOR_ATTR_ACS_CH_LIST]); + if (ch_list_count) { + ch_list = kalMemAlloc(sizeof(UINT_8) * ch_list_count, + VIR_MEM_TYPE); + if (ch_list == NULL) { + DBGLOG(REQ, ERROR, "allocate ch_list fail.\n"); + rStatus = -ENOMEM; + goto exit; + } + + kalMemCopy(ch_list, tmp, ch_list_count); + } + } else if (tb[WIFI_VENDOR_ATTR_ACS_FREQ_LIST]) { + UINT_32 *freq = + nla_data(tb[WIFI_VENDOR_ATTR_ACS_FREQ_LIST]); + + ch_list_count = nla_len(tb[WIFI_VENDOR_ATTR_ACS_FREQ_LIST]) / + sizeof(UINT_32); + if (ch_list_count) { + ch_list = kalMemAlloc(sizeof(UINT_8) * ch_list_count, + VIR_MEM_TYPE); + if (ch_list == NULL) { + DBGLOG(REQ, ERROR, "allocate ch_list fail.\n"); + rStatus = -ENOMEM; + goto exit; + } + + for (i = 0; i < ch_list_count; i++) + ch_list[i] = + ieee80211_frequency_to_channel(freq[i]); + } + } + + if (!ch_list_count) { + DBGLOG(REQ, ERROR, "channel list count can NOT be 0\n"); + rStatus = -EINVAL; + goto exit; + } + + msg_size = sizeof(struct MSG_P2P_ACS_REQUEST) + + (ch_list_count * sizeof(RF_CHANNEL_INFO_T)); + + prMsgAcsRequest = cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, msg_size); + + if (prMsgAcsRequest == NULL) { + DBGLOG(REQ, ERROR, "allocate msg acs req. fail.\n"); + rStatus = -ENOMEM; + goto exit; + } + + kalMemSet(prMsgAcsRequest, 0, msg_size); + prMsgAcsRequest->rMsgHdr.eMsgId = MID_MNY_P2P_ACS; + prMsgAcsRequest->ucRoleIdx = role_idx; + prMsgAcsRequest->fgIsHtEnable = ht_enabled; + prMsgAcsRequest->fgIsHt40Enable = ht40_enabled; + prMsgAcsRequest->fgIsVhtEnable = vht_enabled; + switch (ch_width) { + case 20: + prMsgAcsRequest->eChnlBw = MAX_BW_20MHZ; + break; + case 40: + prMsgAcsRequest->eChnlBw = MAX_BW_40MHZ; + break; + case 80: + prMsgAcsRequest->eChnlBw = MAX_BW_80MHZ; + break; + case 160: + prMsgAcsRequest->eChnlBw = MAX_BW_160MHZ; + break; + default: + DBGLOG(REQ, ERROR, "unsupport width: %d.\n", ch_width); + prMsgAcsRequest->eChnlBw = MAX_BW_UNKNOWN; + break; + } + prMsgAcsRequest->eHwMode = hw_mode; + prMsgAcsRequest->u4NumChannel = ch_list_count; + + for (i = 0; i < ch_list_count; i++) { + /* Translate Freq from MHz to channel number. */ + prRfChannelInfo = + &(prMsgAcsRequest->arChannelListInfo[i]); + + prRfChannelInfo->ucChannelNum = ch_list[i]; + + if (prRfChannelInfo->ucChannelNum <= 14) + prRfChannelInfo->eBand = BAND_2G4; + else + prRfChannelInfo->eBand = BAND_5G; + + /* Iteration. */ + prRfChannelInfo++; + } + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prMsgAcsRequest, + MSG_SEND_METHOD_BUF); + +exit: + if (ch_list) + kalMemFree(ch_list, VIR_MEM_TYPE, + sizeof(UINT_8) * ch_list_count); + if (rStatus == WLAN_STATUS_SUCCESS) { + reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, + NLMSG_HDRLEN); + if (reply_skb != NULL) + return cfg80211_vendor_cmd_reply(reply_skb); + } + return rStatus; +} + +int mtk_cfg80211_vendor_get_features(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + struct sk_buff *reply_skb; + UINT_8 feature_flags[(NUM_VENDOR_FEATURES + 7) / 8] = {0}; + UINT_8 i; + + ASSERT(wiphy); + ASSERT(wdev); + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + feature_flags[(VENDOR_FEATURE_SUPPORT_HW_MODE_ANY / 8)] |= + (1 << (VENDOR_FEATURE_SUPPORT_HW_MODE_ANY % 8)); +#endif + + for (i = 0; i < ((NUM_VENDOR_FEATURES + 7) / 8); i++) { + DBGLOG(REQ, INFO, "Dump feature flags[%d]=0x%x.\n", i, + feature_flags[i]); + } + + reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, + sizeof(feature_flags) + NLMSG_HDRLEN); + + if (!reply_skb) + goto nla_put_failure; + + if (nla_put(reply_skb, WIFI_VENDOR_ATTR_FEATURE_FLAGS, + sizeof(feature_flags), feature_flags)) + goto nla_put_failure; + + return cfg80211_vendor_cmd_reply(reply_skb); + +nla_put_failure: + kfree_skb(reply_skb); + return -EINVAL; +} +#ifdef CFG_SUPPORT_DATA_STALL +int mtk_cfg80211_vendor_event_driver_error(struct _ADAPTER_T *prAdapter, + enum ENUM_VENDOR_DRIVER_EVENT event, UINT_32 dataLen) +{ + struct sk_buff *skb = NULL; + struct wiphy *wiphy; + struct wireless_dev *wdev; + P_WIFI_VAR_T prWifiVar = &prAdapter->rWifiVar; + + wiphy = priv_to_wiphy(prAdapter->prGlueInfo); + wdev = ((prAdapter->prGlueInfo)->prDevHandler)->ieee80211_ptr; + + if (!wiphy || !wdev || !prWifiVar) + return -ENOMEM; + + if (prAdapter->tmReportinterval > 0 && + !CHECK_FOR_TIMEOUT(kalGetTimeTick(), + prAdapter->tmReportinterval, + prWifiVar->u4ReportEventInterval*1000)) { + return -ENOMEM; + } + GET_CURRENT_SYSTIME(&prAdapter->tmReportinterval); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + skb = cfg80211_vendor_event_alloc(wiphy, wdev, dataLen, + WIFI_EVENT_DRIVER_ERROR, GFP_KERNEL); +#else + skb = cfg80211_vendor_event_alloc(wiphy, dataLen, + WIFI_EVENT_DRIVER_ERROR, GFP_KERNEL); +#endif + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + if (dataLen > 0 && + unlikely(nla_put(skb, WIFI_ATTRIBUTE_ERROR_REASON + , dataLen, &event) < 0)) + goto nla_put_failure; + + cfg80211_vendor_event(skb, GFP_KERNEL); + return TRUE; +nla_put_failure: + kfree_skb(skb); + return FALSE; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_wext.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_wext.c new file mode 100644 index 0000000000000..5fa9d7e709cc9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_wext.c @@ -0,0 +1,4295 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_wext.c#5 +*/ + +/* + * ! \file gl_wext.c + * \brief ioctl() (mostly Linux Wireless Extensions) routines for STA driver. + */ + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ + +#include "gl_os.h" + +#include "config.h" +#include "wlan_oid.h" + +#include "gl_wext.h" +#include "gl_wext_priv.h" + +#include "precomp.h" + +#if CFG_SUPPORT_WAPI +#include "gl_sec.h" +#endif + +/* compatibility to wireless extensions */ +#ifdef WIRELESS_EXT + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************** + */ +const long channel_freq[] = { + 2412, 2417, 2422, 2427, 2432, 2437, 2442, + 2447, 2452, 2457, 2462, 2467, 2472, 2484 +}; + +#define NUM_CHANNELS (ARRAY_SIZE(channel_freq)) + +#define MAX_SSID_LEN 32 +#define COUNTRY_CODE_LEN 10 /* country code length */ + +/******************************************************************************* + * 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, ""}, + + {IOCTL_GET_DRIVER, IW_PRIV_TYPE_CHAR | 2000, IW_PRIV_TYPE_CHAR | 2000, "driver"}, + +#if CFG_SUPPORT_QA_TOOL + /* added for ATE iwpriv Command */ + {IOCTL_IWPRIV_ATE, IW_PRIV_TYPE_CHAR | 2000, 0, ""}, +#endif + + /* 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 +#if CFG_SUPPORT_QA_TOOL + {PRIV_QACMD_SET, IW_PRIV_TYPE_CHAR | 2000, 0, "set"}, +#endif + {PRIV_CMD_SW_CTRL, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_sw_ctrl"}, + {PRIV_CMD_SW_CTRL, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_sw_ctrl"}, + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS + {PRIV_CUSTOM_BWCS_CMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_bwcs"}, + /* GET STRUCT sub-ioctls commands */ + {PRIV_CUSTOM_BWCS_CMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_bwcs"}, +#endif + + /* SET STRUCT sub-ioctls commands */ + {PRIV_CMD_OID, 256, 0, "set_oid"}, + /* GET STRUCT sub-ioctls commands */ + {PRIV_CMD_OID, 0, 256, "get_oid"}, + + {PRIV_CMD_BAND_CONFIG, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_band"}, + {PRIV_CMD_BAND_CONFIG, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_band"}, + + {PRIV_CMD_SET_TX_POWER, IW_PRIV_TYPE_INT | 4, 0, "set_txpower"}, + {PRIV_CMD_GET_CH_LIST, 0, IW_PRIV_TYPE_INT | 50, "get_ch_list"}, + {PRIV_CMD_DUMP_MEM, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_mem"}, + +#if CFG_ENABLE_WIFI_DIRECT + {PRIV_CMD_P2P_MODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_p2p_mode"}, +#endif + {PRIV_CMD_MET_PROFILING, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_met_prof"}, + +}; + +static const iw_handler rIwPrivHandler[] = { + [IOCTL_SET_INT - SIOCIWFIRSTPRIV] = priv_set_int, + [IOCTL_GET_INT - SIOCIWFIRSTPRIV] = priv_get_int, + [IOCTL_SET_ADDRESS - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_GET_ADDRESS - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_SET_STR - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_GET_STR - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_SET_KEY - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_GET_KEY - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_SET_STRUCT - SIOCIWFIRSTPRIV] = priv_set_struct, + [IOCTL_GET_STRUCT - SIOCIWFIRSTPRIV] = priv_get_struct, + [IOCTL_SET_STRUCT_FOR_EM - SIOCIWFIRSTPRIV] = priv_set_struct, + [IOCTL_SET_INTS - SIOCIWFIRSTPRIV] = priv_set_ints, + [IOCTL_GET_INTS - SIOCIWFIRSTPRIV] = priv_get_ints, + [IOCTL_GET_DRIVER - SIOCIWFIRSTPRIV] = priv_set_driver, +#if CFG_SUPPORT_QA_TOOL + [IOCTL_IWPRIV_ATE - SIOCIWFIRSTPRIV] = priv_ate_set +#endif +}; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) +static const iw_handler rIwStdHandler[] = { + IW_HANDLER(SIOCGIWNAME, std_wext_get_name), + IW_HANDLER(SIOCSIWFREQ, std_wext_set_freq), + IW_HANDLER(SIOCGIWFREQ, std_wext_get_freq), + IW_HANDLER(SIOCSIWMODE, std_wext_set_mode), + IW_HANDLER(SIOCGIWMODE, std_wext_get_mode), + IW_HANDLER(SIOCGIWRANGE, std_wext_get_range), + IW_HANDLER(SIOCSIWPRIV, std_wext_set_country), + IW_HANDLER(SIOCGIWPRIV, std_wext_get_priv), + IW_HANDLER(SIOCSIWAP, std_wext_set_ap), + IW_HANDLER(SIOCGIWAP, std_wext_get_ap), + IW_HANDLER(SIOCSIWMLME, std_wext_set_mlme), + IW_HANDLER(SIOCSIWSCAN, std_wext_set_scan), + IW_HANDLER(SIOCGIWSCAN, std_wext_get_scan), + IW_HANDLER(SIOCSIWESSID, std_wext_set_essid), + IW_HANDLER(SIOCGIWESSID, std_wext_get_essid), + IW_HANDLER(SIOCGIWRATE, std_wext_get_rate), + IW_HANDLER(SIOCSIWRTS, std_wext_set_rts), + IW_HANDLER(SIOCGIWRTS, std_wext_get_rts), + IW_HANDLER(SIOCGIWFRAG, std_wext_set_rts), + IW_HANDLER(SIOCSIWTXPOW, std_wext_set_txpow), + IW_HANDLER(SIOCGIWTXPOW, std_wext_get_txpow), + IW_HANDLER(SIOCSIWENCODE, std_wext_set_encode), + IW_HANDLER(SIOCGIWENCODE, std_wext_get_encode), + IW_HANDLER(SIOCSIWPOWER, std_wext_set_power), + IW_HANDLER(SIOCGIWPOWER, std_wext_get_power), +#if WIRELESS_EXT > 17 + IW_HANDLER(SIOCSIWGENIE, std_wext_SIOCSIWGENIE_Action), +#endif + IW_HANDLER(SIOCSIWAUTH, std_wext_set_auth), + IW_HANDLER(SIOCSIWENCODEEXT, std_wext_set_encode_ext), + IW_HANDLER(SIOCSIWPMKSA, std_wext_SIOCSIWPMKSA_Action), +}; +#endif + +const struct iw_handler_def wext_handler_def = { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) + .num_standard = (__u16) sizeof(rIwStdHandler) / sizeof(iw_handler), +#else + .num_standard = 0, +#endif +#if defined(CONFIG_WEXT_PRIV) + + .num_private = (__u16) sizeof(rIwPrivHandler) / sizeof(iw_handler), + .num_private_args = (__u16) sizeof(rIwPrivTable) / sizeof(struct iw_priv_args), +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) + .standard = rIwStdHandler, +#else + .standard = (iw_handler *)NULL, +#endif +#if defined(CONFIG_WEXT_PRIV) + + .private = rIwPrivHandler, + .private_args = rIwPrivTable, +#endif + .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 +******************************************************************************** +*/ +static void wext_support_ioctl_SIOCSIWGENIE(IN P_GLUE_INFO_T prGlueInfo, IN char *prExtraBuf, IN UINT_32 u4ExtraSize); + +static void +wext_support_ioctl_SIOCSIWPMKSA_Action(IN struct net_device *prDev, IN char *prExtraBuf, IN int ioMode, OUT int *ret); + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired WPA/RSN Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +wextSrchDesiredWPAIE(IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT PUINT_8 *ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ucDesiredElemId && i4InfoElemLen <= i4TotalIeLen) { + if (ucDesiredElemId != 0xDD) { + /* Non 0xDD, OK! */ + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + /* EID == 0xDD, check WPA IE */ + if (pucIEStart[1] >= 4) { + if (memcmp(&pucIEStart[2], "\x00\x50\xf2\x01", 4) == 0) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + } /* check WPA IE length */ + } + + /* check 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_PASSPOINT +/*----------------------------------------------------------------------------*/ +/*! +* \brief Check if exist the desired HS2.0 Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextIsDesiredHS20IE(IN PUINT_8 pucCurIE, IN INT_32 i4TotalIeLen) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucCurIE); + + i4InfoElemLen = (INT_32) pucCurIE[1] + 2; + + if (pucCurIE[0] == ELEM_ID_VENDOR && i4InfoElemLen <= i4TotalIeLen) { + if (pucCurIE[1] >= ELEM_MIN_LEN_HS20_INDICATION) { + if (memcmp(&pucCurIE[2], "\x50\x6f\x9a\x10", 4) == 0) + return TRUE; + } + } + /* check desired EID */ + return FALSE; +} /* wextIsDesiredHS20IE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Check if exist the desired interworking Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextIsDesiredInterworkingIE(IN PUINT_8 pucCurIE, IN INT_32 i4TotalIeLen) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucCurIE); + + i4InfoElemLen = (INT_32) pucCurIE[1] + 2; + + if (pucCurIE[0] == ELEM_ID_INTERWORKING && i4InfoElemLen <= i4TotalIeLen) { + switch (pucCurIE[1]) { + case IW_IE_LENGTH_ANO: + case IW_IE_LENGTH_ANO_HESSID: + case IW_IE_LENGTH_ANO_VENUE: + case IW_IE_LENGTH_ANO_VENUE_HESSID: + return TRUE; + default: + break; + } + + } + /* check desired EID */ + return FALSE; +} /* wextIsDesiredInterworkingIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Check if exist the desired Adv Protocol Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextIsDesiredAdvProtocolIE(IN PUINT_8 pucCurIE, IN INT_32 i4TotalIeLen) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucCurIE); + + i4InfoElemLen = (INT_32) pucCurIE[1] + 2; + + if (pucCurIE[0] == ELEM_ID_ADVERTISEMENT_PROTOCOL && i4InfoElemLen <= i4TotalIeLen) + return TRUE; + /* check desired EID */ + return FALSE; +} /* wextIsDesiredAdvProtocolIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Check if exist the desired Roaming Consortium Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextIsDesiredRoamingConsortiumIE(IN PUINT_8 pucCurIE, IN INT_32 i4TotalIeLen) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucCurIE); + + i4InfoElemLen = (INT_32) pucCurIE[1] + 2; + + if (pucCurIE[0] == ELEM_ID_ROAMING_CONSORTIUM && i4InfoElemLen <= i4TotalIeLen) + return TRUE; + /* check desired EID */ + return FALSE; +} /* wextIsDesiredRoamingConsortiumIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired HS2.0 Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextSrchDesiredHS20IE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ELEM_ID_VENDOR && i4InfoElemLen <= i4TotalIeLen) { + if (pucIEStart[1] >= ELEM_MIN_LEN_HS20_INDICATION) { + if (memcmp(&pucIEStart[2], "\x50\x6f\x9a\x10", 4) == 0) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + } + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* wextSrchDesiredHS20IE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired interworking Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextSrchDesiredInterworkingIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ELEM_ID_INTERWORKING && i4InfoElemLen <= i4TotalIeLen) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* wextSrchDesiredInterworkingIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired Adv Protocol Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextSrchDesiredAdvProtocolIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ELEM_ID_ADVERTISEMENT_PROTOCOL && i4InfoElemLen <= i4TotalIeLen) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* wextSrchDesiredAdvProtocolIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired Roaming Consortium Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextSrchDesiredRoamingConsortiumIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ELEM_ID_ROAMING_CONSORTIUM && i4InfoElemLen <= i4TotalIeLen) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* wextSrchDesiredRoamingConsortiumIE */ + +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_WPS +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired WPS Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +wextSrchDesiredWPSIE(IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT PUINT_8 *ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ucDesiredElemId && i4InfoElemLen <= i4TotalIeLen) { + if (ucDesiredElemId != 0xDD) { + /* Non 0xDD, OK! */ + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + + /* EID == 0xDD, check WPS IE */ + if (pucIEStart[1] >= 4) { + if (memcmp(&pucIEStart[2], "\x00\x50\xf2\x04", 4) == 0) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + } /* check WPS IE length */ + } + + /* check 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 size_t szNameSize, 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 (GLUE_CHK_PR2(prNetDev, pcName) == FALSE) + 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, &u4BufLen); + + switch (eNetWorkType) { + case PARAM_NETWORK_TYPE_DS: + strncpy(pcName, "IEEE 802.11b", szNameSize); + break; + case PARAM_NETWORK_TYPE_OFDM24: + strncpy(pcName, "IEEE 802.11bgn", szNameSize); + break; + case PARAM_NETWORK_TYPE_AUTOMODE: + case PARAM_NETWORK_TYPE_OFDM5: + strncpy(pcName, "IEEE 802.11abgn", szNameSize); + break; + case PARAM_NETWORK_TYPE_FH: + default: + strncpy(pcName, "IEEE 802.11", szNameSize); + break; + } + } else { + strncpy(pcName, "Disconnected", szNameSize); + } + + pcName[szNameSize - 1] = '\0'; + + 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 (GLUE_CHK_PR2(prNetDev, prIwFreq) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* 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 (rStatus != WLAN_STATUS_SUCCESS) + return -EINVAL; + } + /* Setting by channel number */ + else if ((prIwFreq->m > KILO) || (prIwFreq->e > 0)) + return -EOPNOTSUPP; + + /* Change to channel number format */ + u4ChnlFreq = (UINT_32) prIwFreq->m; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetChannel, &u4ChnlFreq, sizeof(u4ChnlFreq), FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + 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 (GLUE_CHK_PR2(prNetDev, prIwFreq) == FALSE) + 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, &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 (GLUE_CHK_PR2(prNetDev, pu4Mode) == FALSE) + 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", __func__, *pu4Mode); + return -EOPNOTSUPP; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetInfrastructureMode, &eOpMode, sizeof(eOpMode), FALSE, FALSE, TRUE, &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 (GLUE_CHK_PR2(prNetDev, pu4Mode) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryInfrastructureMode, &eOpMode, sizeof(eOpMode), TRUE, 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", __func__); + return -EINVAL; + } + + return 0; +} /* wext_get_mode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get the valid range for each configurable STA setting value. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prData Pointer to iw_point structure, not used. +* \param[out] pcExtra Pointer to buffer which is allocated by caller of this +* function, wext_support_ioctl() or ioctl_standard_call() in +* wireless.c. +* +* \retval 0 If data is valid. +* +* \note The extra buffer (pcExtra) is filled with information from driver. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_range(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, IN struct iw_point *prData, OUT char *pcExtra) +{ + struct iw_range *prRange = NULL; + PARAM_RATES_EX aucSuppRate = { 0 }; /* data buffers */ + int i = 0; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(pcExtra); + if (GLUE_CHK_PR2(prNetDev, pcExtra) == FALSE) + 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, &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 (GLUE_CHK_PR2(prNetDev, prAddr) == FALSE) + 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, sizeof(*prAddr)); + return 0; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryBssid, prAddr->sa_data, ETH_ALEN, TRUE, 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 (GLUE_CHK_PR2(prNetDev, pcExtra) == FALSE) + 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, &u4BufLen); + return 0; + } + + 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 struct iw_scan_req *prIwScanReq, 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 (GLUE_CHK_DEV(prNetDev) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + +#if WIRELESS_EXT > 17 + /* retrieve SSID */ + if (prIwScanReq) + essid_len = prIwScanReq->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, &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 (GLUE_CHK_PR3(prNetDev, prData, pcExtra) == FALSE) + 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 */ + /* wait_for_completion_interruptible_timeout(&prGlueInfo->rScanComp, 4 * KAL_HZ); */ + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryBssidList, prList, u4AllocBufLen, TRUE, FALSE, FALSE, &u4BufLen); + + if (rStatus == WLAN_STATUS_INVALID_LENGTH) { + +#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, &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:%u\n", prList->u4NumberOfItems); + goto error; + } + + /* Copy required data from pList to pcExtra */ + prBss = &prList->arBssid[0]; /* set to the first entry */ + for (i = 0; i < prList->u4NumberOfItems; ++i) { + /* BSSID */ + iwEvent.cmd = SIOCGIWAP; + iwEvent.len = IW_EV_ADDR_LEN; + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.ap_addr.sa_family = ARPHRD_ETHER; + ether_addr_copy(iwEvent.u.ap_addr.sa_data, prBss->arMacAddress); + memcpy(pcCur, &iwEvent, IW_EV_ADDR_LEN); + pcCur += IW_EV_ADDR_LEN; + + /* SSID */ + iwEvent.cmd = SIOCGIWESSID; + /* Modification to user space pointer(essid.pointer) is not needed. */ + iwEvent.u.essid.length = (__u16) prBss->rSsid.u4SsidLen; + iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.essid.length; + + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.essid.flags = 1; + iwEvent.u.essid.pointer = NULL; + +#if WIRELESS_EXT <= 18 + memcpy(pcCur, &iwEvent, iwEvent.len); +#else + memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); + memcpy(pcCur + IW_EV_LCP_LEN, &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF); +#endif + memcpy(pcCur + IW_EV_POINT_LEN, prBss->rSsid.aucSsid, iwEvent.u.essid.length); + pcCur += iwEvent.len; + /* Frequency */ + iwEvent.cmd = SIOCGIWFREQ; + iwEvent.len = IW_EV_FREQ_LEN; + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.freq.m = prBss->rConfiguration.u4DSConfig; + iwEvent.u.freq.e = 3; /* (in KHz) */ + iwEvent.u.freq.i = 0; + memcpy(pcCur, &iwEvent, IW_EV_FREQ_LEN); + pcCur += IW_EV_FREQ_LEN; + + /* Operation Mode */ + iwEvent.cmd = SIOCGIWMODE; + iwEvent.len = IW_EV_UINT_LEN; + if ((pcCur + iwEvent.len) > pcEnd) + break; + if (prBss->eOpMode == NET_TYPE_IBSS) + iwEvent.u.mode = IW_MODE_ADHOC; + else if (prBss->eOpMode == NET_TYPE_INFRA) + iwEvent.u.mode = IW_MODE_INFRA; + else + iwEvent.u.mode = IW_MODE_AUTO; + memcpy(pcCur, &iwEvent, IW_EV_UINT_LEN); + pcCur += IW_EV_UINT_LEN; + + /* Quality */ + iwEvent.cmd = IWEVQUAL; + iwEvent.len = IW_EV_QUAL_LEN; + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.qual.qual = 0; /* Quality not available now */ + /* -100 < Rssi < -10, normalized by adding 0x100 */ + iwEvent.u.qual.level = 0x100 + prBss->rRssi; + iwEvent.u.qual.noise = 0; /* Noise not available now */ + iwEvent.u.qual.updated = IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID; + memcpy(pcCur, &iwEvent, IW_EV_QUAL_LEN); + pcCur += IW_EV_QUAL_LEN; + + /* Security Mode */ + iwEvent.cmd = SIOCGIWENCODE; + iwEvent.len = IW_EV_POINT_LEN; + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.data.pointer = NULL; + iwEvent.u.data.flags = 0; + iwEvent.u.data.length = 0; + if (!prBss->u4Privacy) + iwEvent.u.data.flags |= IW_ENCODE_DISABLED; +#if WIRELESS_EXT <= 18 + memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN); +#else + memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); + memcpy(pcCur + IW_EV_LCP_LEN, &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF); +#endif + pcCur += IW_EV_POINT_LEN; + + /* rearrange rate information */ + u4BufIndex = sprintf(aucRatesBuf, "Rates (Mb/s):"); + u4HighestRate = 0; + for (j = 0; j < PARAM_MAX_LEN_RATES_EX; ++j) { + UINT_8 curRate = prBss->rSupportedRates[j] & 0x7F; + + if (curRate == 0) + break; + + if (curRate > u4HighestRate) + u4HighestRate = curRate; + + if (curRate == RATE_5_5M) + u4BufIndex += sprintf(aucRatesBuf + u4BufIndex, " 5.5"); + else + u4BufIndex += sprintf(aucRatesBuf + u4BufIndex, " %d", curRate / 2); +#if DBG + if (u4BufIndex > sizeof(aucRatesBuf)) + 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); + /* kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_SCAN_COMPLETE, NULL, 0); */ + +error: + /* free local query buffer */ + if (prList) + kalMemFree(prList, VIR_MEM_TYPE, u4AllocBufLen); + + return ret; +} /* wext_get_scan */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set desired network name ESSID. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prEssid Pointer of iw_point header. +* \param[in] pcExtra Pointer to buffer srtoring essid string. +* +* \retval 0 If netif_carrier_ok. +* \retval -E2BIG Essid string length is too big. +* \retval -EINVAL pcExtra is null pointer. +* \retval -EFAULT Driver fail to set new essid. +* +* \note If string length is ok, device will try connecting to the new network. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_set_essid(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, IN struct iw_point *prEssid, IN char *pcExtra) +{ + PARAM_SSID_T rNewSsid; + UINT_32 cipher; + ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus; + ENUM_PARAM_AUTH_MODE_T eAuthMode; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prEssid); + ASSERT(pcExtra); + if (GLUE_CHK_PR3(prNetDev, prEssid, pcExtra) == FALSE) + 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; + } 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; + break; + case IW_AUTH_KEY_MGMT_PSK: + eAuthMode = + (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA) ? + AUTH_MODE_WPA_PSK : AUTH_MODE_WPA2_PSK; + 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; */ +/* 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: + eAuthMode = AUTH_MODE_AUTO_SWITCH; + break; + } + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAuthMode, &eAuthMode, sizeof(eAuthMode), FALSE, FALSE, FALSE, &u4BufLen); + + /* set encryption status */ + cipher = prGlueInfo->rWpaInfo.u4CipherGroup | prGlueInfo->rWpaInfo.u4CipherPairwise; + 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; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEncryptionStatus, &eEncStatus, sizeof(eEncStatus), 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'; + */ + + if (kalIoctl(prGlueInfo, + wlanoidSetSsid, + (PVOID)&rNewSsid, sizeof(PARAM_SSID_T), FALSE, FALSE, TRUE, &u4BufLen) != WLAN_STATUS_SUCCESS) { + 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 (GLUE_CHK_PR3(prNetDev, prEssid, pcExtra) == FALSE) + 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, &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 rStatus; +} /* 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 (GLUE_CHK_PR2(prNetDev, prRate) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + 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 */ + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetDesiredRates, + &aucSuppRate, sizeof(aucSuppRate), &u4BufLen); + } else { + /* iwconfig wlan0 rate fixed */ + + /* fix rate to what? DO NOTHING */ + return -EINVAL; + } + return 0; + } + + 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 (GLUE_CHK_PR2(prNetDev, prRate) == FALSE) + 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, &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 (GLUE_CHK_PR2(prNetDev, prRts) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (prRts->disabled == 1) + u4RtsThresh = 2347; + else if (prRts->value >= 0 || prRts->value <= 2347) + u4RtsThresh = (PARAM_RTS_THRESHOLD) prRts->value; + else + return -EINVAL; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRtsThreshold, &u4RtsThresh, sizeof(u4RtsThresh), 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 (GLUE_CHK_PR2(prNetDev, prRts) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryRtsThreshold, &u4RtsThresh, sizeof(u4RtsThresh), TRUE, 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 (GLUE_CHK_PR2(prNetDev, prTxPow) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (prTxPow->disabled) { + /* <1> disconnect */ + rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, NULL, 0, FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + /* ToDo:: DBGLOG */ + 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 (GLUE_CHK_PR2(prNetDev, prTxPow) == FALSE) + 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 (GLUE_CHK_PR2(prNetDev, prEnc) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryEncryptionStatus, &eEncMode, sizeof(eEncMode), TRUE, 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 (GLUE_CHK_PR3(prNetDev, prEnc, pcExtra) == FALSE) + 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, &u4BufLen); + + eEncStatus = ENUM_ENCRYPTION_DISABLED; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEncryptionStatus, + &eEncStatus, sizeof(eEncStatus), 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, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "wlanoidSetAddWep fail 0x%x\n", rStatus); + return -EFAULT; + } + + /* change to auto switch */ + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_SHARED_KEY | IW_AUTH_ALG_OPEN_SYSTEM; + eAuthMode = AUTH_MODE_AUTO_SWITCH; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAuthMode, &eAuthMode, sizeof(eAuthMode), FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + 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, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + 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) +{ + PARAM_POWER_MODE ePowerMode; + INT_32 i4PowerValue; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + PARAM_POWER_MODE_T rPowerMode; + + ASSERT(prNetDev); + ASSERT(prPower); + if (GLUE_CHK_PR2(prNetDev, prPower) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (!prGlueInfo) + return -EFAULT; + + if (!prGlueInfo->prAdapter->prAisBssInfo) + return -EFAULT; + + 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", + __func__, prPower->value); + + return -EINVAL; + } + } + + rPowerMode.ePowerMode = ePowerMode; + rPowerMode.ucBssIdx = prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, sizeof(PARAM_POWER_MODE_T), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + 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 (GLUE_CHK_PR2(prNetDev, prPower) == FALSE) + 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 + + 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 (GLUE_CHK_PR2(prNetDev, prAuth) == FALSE) + 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, &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: + 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, &u4BufLen); + } + DBGLOG(INIT, INFO, "IW_AUTH_WAPI_ENABLED :%d\n", prAuth->value); + break; +#endif + default: + 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[1024]; /* 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 (GLUE_CHK_PR3(prNetDev, prEnc, pcExtra) == FALSE) + 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) + return 0; + + /* KeyID */ + prWpiKey->ucKeyID = (prEnc->flags & IW_ENCODE_INDEX); + prWpiKey->ucKeyID--; + if (prWpiKey->ucKeyID > 1) { + /* key id is out of range */ + return -EINVAL; + } + + if (prIWEncExt->key_len != 32) { + /* key length not valid */ + return -EINVAL; + } + + 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[0], &prIWEncExt->tx_seq[0], IW_ENCODE_SEQ_MAX_SIZE * 2);*/ + memcpy(&prWpiKey->aucPN[0], &prIWEncExt->tx_seq[0], IW_ENCODE_SEQ_MAX_SIZE); + memcpy(&prWpiKey->aucPN[8], &prIWEncExt->rx_seq[0], IW_ENCODE_SEQ_MAX_SIZE); + + /* 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, &u4BufLen); + + } else +#endif + { + + if ((prEnc->flags & IW_ENCODE_MODE) == IW_ENCODE_DISABLED) { + prRemoveKey->u4Length = sizeof(*prRemoveKey); + memcpy(prRemoveKey->arBSSID, prIWEncExt->addr.sa_data, 6); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRemoveKey, + prRemoveKey, prRemoveKey->u4Length, FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "remove key error:%x\n", rStatus); + return 0; + } + + if (prIWEncExt->key_len > sizeof(prKey->aucKeyMaterial)) { + DBGLOG(INIT, ERROR, "Invalid key length %d\n", prIWEncExt->key_len); + return -EINVAL; + } + + 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, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "wlanoidSetAddWep fail 0x%x\n", rStatus); + return -EFAULT; + } + + /* change to auto switch */ + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_SHARED_KEY | IW_AUTH_ALG_OPEN_SYSTEM; + eAuthMode = AUTH_MODE_AUTO_SWITCH; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAuthMode, + &eAuthMode, sizeof(eAuthMode), FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "wlanoidSetAuthMode fail 0x%x\n", rStatus); + return -EFAULT; + } + + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40; + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40; + + eEncStatus = ENUM_WEP_ENABLED; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEncryptionStatus, + &eEncStatus, + sizeof(ENUM_PARAM_ENCRYPTION_STATUS_T), + FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "wlanoidSetEncryptionStatus fail 0x%x\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%x\n", prKey->u4KeyIndex); + /* key id is out of range */ + return -EINVAL; + } + + /* bit(31) and bit(30) are shared by pKey and pRemoveKey */ + /* Tx Key Bit(31) */ + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + prKey->u4KeyIndex |= 0x1UL << 31; + + /* 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 = ((ULONG)&(((P_PARAM_KEY_T) 0)->aucKeyMaterial)) + prKey->u4KeyLength; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAddKey, prKey, prKey->u4Length, FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "add key error:%x\n", rStatus); + return -EFAULT; + } + break; + } + } + + return 0; +} /* wext_set_encode_ext */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set country code +* +* \param[in] prNetDev Net device requested. +* \param[in] prData iwreq.u.data carries country code value. +* +* \retval 0 For success. +* \retval -EEFAULT For fail. +* +* \note Country code is stored and channel list is updated based on current country domain. +*/ +/*----------------------------------------------------------------------------*/ +static int wext_set_country(IN struct net_device *prNetDev, IN struct iw_point *prData) +{ + P_GLUE_INFO_T prGlueInfo; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + UINT_8 aucCountry[COUNTRY_CODE_LEN]; + + ASSERT(prNetDev); + + /* prData->pointer should be like "COUNTRY US", "COUNTRY EU" + * and "COUNTRY JP" + */ + if (GLUE_CHK_PR2(prNetDev, prData) == FALSE || !prData->pointer || prData->length < COUNTRY_CODE_LEN) + return -EINVAL; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (copy_from_user(aucCountry, prData->pointer, COUNTRY_CODE_LEN)) + return -EFAULT; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetCountryCode, + &aucCountry[COUNTRY_CODE_LEN-2], 2, FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "Set country code error: %x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To report the iw private args table to user space. +* +* \param[in] prNetDev Net device requested. +* \param[out] prData iwreq.u.data to carry the private args table. +* +* \retval 0 For success. +* \retval -E2BIG For user's buffer size is too small. +* \retval -EFAULT For fail. +* +*/ +/*----------------------------------------------------------------------------*/ +static int wext_get_priv(IN struct net_device *prNetDev, OUT struct iw_point *prData) +{ + UINT_16 u2BufferSize = prData->length; + + /* Update our private args table size */ + prData->length = (__u16)sizeof(rIwPrivTable); + if (u2BufferSize < prData->length) + return -E2BIG; + + if (prData->length) { + if (copy_to_user(prData->pointer, rIwPrivTable, sizeof(rIwPrivTable))) + return -EFAULT; + } + + return 0; +} /* wext_get_priv */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) + +int std_wext_get_name(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + return wext_get_name(prDev, prIwrInfo, (char *)&wru->name, sizeof(wru->name), NULL); + +} + +int std_wext_set_freq(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wrqu, char *pcExtra) +{ + return wext_set_freq(prDev, NULL, &wrqu->freq, NULL); +} + +int std_wext_get_freq(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + return wext_get_freq(prDev, NULL, &wru->freq, NULL); + +} + +int std_wext_set_mode(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + return wext_set_mode(prDev, NULL, &wru->mode, NULL); +} + +int std_wext_get_mode(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + return wext_get_mode(prDev, NULL, &wru->mode, NULL); +} + +int std_wext_get_range(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + int ret = 0; + + if (!pcExtra) { + ret = -ENOMEM; + return ret; + } + if (wru->data.pointer != NULL) { + /* Buffer size should be large enough */ + if (wru->data.length < sizeof(struct iw_range)) { + ret = -E2BIG; + return ret; + } + + ret = wext_get_range(prDev, NULL, &wru->data, pcExtra); + } else { + ret = -EINVAL; + } + + return ret; +} + +int std_wext_set_ap(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + int ret = 0; + + if (wru->ap_addr.sa_data[0] == 0 && + wru->ap_addr.sa_data[1] == 0 && + wru->ap_addr.sa_data[2] == 0 && + wru->ap_addr.sa_data[3] == 0 && + wru->ap_addr.sa_data[4] == 0 && + wru->ap_addr.sa_data[5] == 0) { + /* WPA Supplicant will set 000000000000 in + * wpa_driver_wext_deinit(), do nothing here or disassoc again? + */ + ret = 0; + } else { + ret = wext_set_ap(prDev, NULL, &wru->ap_addr, NULL); + } + + return ret; +} + +int std_wext_get_ap(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + return wext_get_ap(prDev, NULL, &wru->ap_addr, NULL); +} + +int std_wext_set_mlme(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + int ret = 0; + + if (!pcExtra) { + ret = -ENOMEM; + return ret; + } + + if (!wru->data.pointer) { + ret = -EINVAL; + return ret; + } + + if (wru->data.length < sizeof(struct iw_mlme)) { + DBGLOG(INIT, INFO, "MLME buffer strange:%d\n", wru->data.length); + ret = -EINVAL; + return ret; + } + + ret = wext_set_mlme(prDev, NULL, &(wru->data), pcExtra); + + return ret; +} + +int std_wext_set_scan(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + int ret = 0; + struct iw_scan_req *prIwScanReq = NULL; + + if (!pcExtra) { + ret = -EINVAL; + return ret; + } + + if (wru->data.pointer == NULL) + ret = wext_set_scan(prDev, NULL, NULL, NULL); +#if WIRELESS_EXT > 17 + else if (wru->data.length == sizeof(struct iw_scan_req)) { + prIwScanReq = (struct iw_scan_req *)pcExtra; + + if (prIwScanReq->essid_len > IW_ESSID_MAX_SIZE) + prIwScanReq->essid_len = IW_ESSID_MAX_SIZE; + ret = wext_set_scan(prDev, NULL, prIwScanReq, &(prIwScanReq->essid[0])); + } +#endif + else + ret = -EINVAL; + + return ret; +} + +int std_wext_get_scan(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + int ret = 0; + UINT_32 u4ExtraSize = 0; + + if (!pcExtra) { + ret = -ENOMEM; + return ret; + } + + if (!wru->data.pointer) { + ret = -EINVAL; + return ret; + } + + u4ExtraSize = wru->data.length; + /* iwr->u.data.length may be updated by wext_get_scan() */ + ret = wext_get_scan(prDev, NULL, &wru->data, pcExtra); + if (ret != 0) { + if (ret == -E2BIG) + DBGLOG(INIT, INFO, "[wifi] wext_get_scan -E2BIG\n"); + } else { + /* check updated length is valid */ + ASSERT(wru->data.length <= u4ExtraSize); + if (wru->data.length > u4ExtraSize) { + DBGLOG(INIT, INFO, + "Updated result length is larger than allocated (%u > %u)\n", + wru->data.length, u4ExtraSize); + wru->data.length = u4ExtraSize; + } + } + + return ret; +} + +int std_wext_set_essid(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + int ret = 0; + UINT_32 u4ExtraSize = 0; + + u4ExtraSize = wru->essid.length; + + if (!pcExtra) { + ret = -ENOMEM; + return ret; + } + if (u4ExtraSize > IW_ESSID_MAX_SIZE) { + ret = -E2BIG; + return ret; + } + if (!wru->essid.pointer) { + ret = -EINVAL; + return ret; + } + + ret = wext_set_essid(prDev, NULL, &wru->essid, pcExtra); + return ret; +} + +int std_wext_get_essid(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + int ret = 0; + UINT_32 u4ExtraSize = 0; + + u4ExtraSize = wru->essid.length; + + if (!pcExtra) { + ret = -ENOMEM; + return ret; + } + if (!wru->essid.pointer) { + ret = -EINVAL; + return ret; + } + + if (u4ExtraSize != IW_ESSID_MAX_SIZE && u4ExtraSize != IW_ESSID_MAX_SIZE + 1) { + DBGLOG(INIT, INFO, "[wifi] iwr->u.essid.length:%d error\n", wru->essid.length); + ret = -E2BIG; /* let caller try larger buffer */ + return ret; + } + + /* iwr->u.essid.length is updated by wext_get_essid() */ + ret = wext_get_essid(prDev, NULL, &wru->essid, pcExtra); + return ret; +} + +int std_wext_get_rate(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + return wext_get_rate(prDev, NULL, &wru->bitrate, NULL); +} + +int std_wext_set_rts(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + return wext_set_rts(prDev, NULL, &wru->rts, NULL); +} + +int std_wext_get_rts(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + return wext_get_rts(prDev, NULL, &wru->rts, NULL); +} + +int std_wext_get_frag(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + return wext_get_frag(prDev, NULL, &wru->frag, NULL); +} + +int std_wext_set_txpow(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + return wext_set_txpow(prDev, NULL, &wru->txpower, NULL); +} + +int std_wext_get_txpow(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + return wext_get_txpow(prDev, NULL, &wru->txpower, NULL); +} + +int std_wext_set_encode(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + int ret = 0; + UINT_32 u4ExtraSize = 0; + + if (!pcExtra) { + ret = -ENOMEM; + return ret; + } + + u4ExtraSize = wru->encoding.length; + if (wru->encoding.pointer) { + if (u4ExtraSize > IW_ENCODING_TOKEN_MAX) { + ret = -E2BIG; + return ret; + } + } else + return -EINVAL; + + ret = wext_set_encode(prDev, NULL, &wru->encoding, pcExtra); + return ret; +} + +int std_wext_get_encode(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + return wext_get_encode(prDev, NULL, &wru->encoding, NULL); +} + +int std_wext_set_power(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + return wext_set_power(prDev, NULL, &wru->power, NULL); +} + +int std_wext_get_power(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + return wext_get_power(prDev, NULL, &wru->power, NULL); +} + +int std_wext_set_auth(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + return wext_set_auth(prDev, NULL, &wru->param, NULL); +} + +int std_wext_set_encode_ext(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + int ret = 0; + UINT_32 u4ExtraSize = 0; + + if (!pcExtra) { + ret = -ENOMEM; + return ret; + } + + if (wru->encoding.pointer) { + u4ExtraSize = wru->encoding.length; + if (!u4ExtraSize || u4ExtraSize > (sizeof(struct iw_encode_ext) + 32)) { + ret = -EINVAL; + return ret; + } + ret = wext_set_encode_ext(prDev, NULL, &wru->encoding, pcExtra); + } else if (wru->encoding.length != 0) + ret = -EINVAL; + + return ret; +} + +int std_wext_set_country(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + return wext_set_country(prDev, &wru->data); +} + +int std_wext_get_priv(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + UINT_16 u2TblSize = 0; + + /* Update our private args table size */ + u2TblSize = (__u16)sizeof(rIwPrivTable)/sizeof(struct iw_priv_args); + if (!pcExtra) + return -ENOMEM; + + if (wru->data.length < u2TblSize) + return -E2BIG; + + if (memcpy(pcExtra, rIwPrivTable, sizeof(rIwPrivTable))) + return -EFAULT; + + return 0; +} + +int std_wext_SIOCSIWPMKSA_Action(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + int ret = 0; + UINT_32 u4ExtraSize = 0; + + if (!pcExtra) { + ret = -ENOMEM; + return ret; + } + + if (wru->data.pointer) { + /* Fixed length structure */ + if (wru->data.length != sizeof(struct iw_pmksa)) { + ret = -EINVAL; + return ret; + } + + u4ExtraSize = sizeof(struct iw_pmksa); + switch (((struct iw_pmksa *)pcExtra)->cmd) { + case IW_PMKSA_ADD: + wext_support_ioctl_SIOCSIWPMKSA_Action(prDev, pcExtra, IW_PMKSA_ADD, + &ret); + break; + case IW_PMKSA_REMOVE: + break; + case IW_PMKSA_FLUSH: + wext_support_ioctl_SIOCSIWPMKSA_Action(prDev, pcExtra, + IW_PMKSA_FLUSH, &ret); + break; + default: + DBGLOG(INIT, INFO, "UNKNOWN iw_pmksa command:%d\n", + ((struct iw_pmksa *)pcExtra)->cmd); + ret = -EFAULT; + break; + } + } else if (wru->data.length != 0) { + ret = -EINVAL; + return ret; + } + + return ret; +} + +int std_wext_SIOCSIWGENIE_Action(struct net_device *prDev, + struct iw_request_info *prIwrInfo, + union iwreq_data *wru, char *pcExtra) +{ + int ret = 0; +#if WIRELESS_EXT > 17 + UINT_32 u4ExtraSize = 0; + + if (!pcExtra) { + ret = -ENOMEM; + return ret; + } + + if (wru->data.pointer) { + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + + u4ExtraSize = wru->data.length; +#if CFG_SUPPORT_WAPI + if (u4ExtraSize > 42 /* The max wapi ie buffer */) { + ret = -EINVAL; + return ret; + } +#endif + if (u4ExtraSize) + wext_support_ioctl_SIOCSIWGENIE(prGlueInfo, pcExtra, u4ExtraSize); + } +#endif + + return ret; +} + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief ioctl() (Linux Wireless Extensions) routines +* +* \param[in] prDev Net device requested. +* \param[in] ifr The ifreq structure for seeting the wireless extension. +* \param[in] i4Cmd The wireless extension ioctl command. +* +* \retval zero On success. +* \retval -EOPNOTSUPP If the cmd is not supported. +* \retval -EFAULT If copy_to_user goes wrong. +* \retval -EINVAL If any value's out of range. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int wext_support_ioctl(IN struct net_device *prDev, IN struct ifreq *prIfReq, IN int i4Cmd) +{ + struct iwreq *iwr = (struct iwreq *)prIfReq; + struct iw_request_info rIwReqInfo; + int ret = 0; + char *prExtraBuf = NULL; + UINT_32 u4ExtraSize = 0; + struct iw_scan_req *prIwScanReq = NULL; + + 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, sizeof(iwr->u.name), NULL); + break; + + /* case SIOCSIWNWID: 0x8B02, deprecated */ + /* case SIOCGIWNWID: 0x8B03, deprecated */ + + case SIOCSIWFREQ: /* 0x8B04, set channel */ + ret = wext_set_freq(prDev, NULL, &iwr->u.freq, NULL); + break; + + case SIOCGIWFREQ: /* 0x8B05, get channel */ + ret = wext_get_freq(prDev, NULL, &iwr->u.freq, NULL); + break; + + case SIOCSIWMODE: /* 0x8B06, set operation mode */ + ret = wext_set_mode(prDev, NULL, &iwr->u.mode, NULL); + /* ret = 0; */ + break; + + case SIOCGIWMODE: /* 0x8B07, get operation mode */ + ret = wext_get_mode(prDev, NULL, &iwr->u.mode, NULL); + break; + + /* case SIOCSIWSENS: 0x8B08, unsupported */ + /* case SIOCGIWSENS: 0x8B09, unsupported */ + + /* case SIOCSIWRANGE: 0x8B0A, unused */ + case SIOCGIWRANGE: /* 0x8B0B, get range of parameters */ + if (iwr->u.data.pointer != NULL) { + /* Buffer size should be large enough */ + if (iwr->u.data.length < sizeof(struct iw_range)) { + ret = -E2BIG; + break; + } + + prExtraBuf = kalMemAlloc(sizeof(struct iw_range), VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + /* reset all fields */ + memset(prExtraBuf, 0, sizeof(struct iw_range)); + iwr->u.data.length = sizeof(struct iw_range); + + ret = wext_get_range(prDev, NULL, &iwr->u.data, prExtraBuf); + /* Push up to the caller */ + if (copy_to_user(iwr->u.data.pointer, prExtraBuf, iwr->u.data.length)) + ret = -EFAULT; + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, sizeof(struct iw_range)); + prExtraBuf = NULL; + } else { + ret = -EINVAL; + } + break; + + case SIOCSIWPRIV: /* 0x8B0C, set country code */ + ret = wext_set_country(prDev, &iwr->u.data); + break; + + case SIOCGIWPRIV: /* 0x8B0D, get private args table */ + ret = wext_get_priv(prDev, &iwr->u.data); + break; + + /* 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; + } 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)) { + prIwScanReq = kalMemAlloc(iwr->u.data.length, VIR_MEM_TYPE); + if (!prIwScanReq) { + ret = -ENOMEM; + break; + } + if (copy_from_user(prIwScanReq, iwr->u.data.pointer, iwr->u.data.length)) + ret = -EFAULT; + else { + if (prIwScanReq->essid_len > IW_ESSID_MAX_SIZE) + prIwScanReq->essid_len = IW_ESSID_MAX_SIZE; + ret = wext_set_scan(prDev, NULL, prIwScanReq, &(prIwScanReq->essid[0])); + } + + kalMemFree(prIwScanReq, VIR_MEM_TYPE, iwr->u.data.length); + prIwScanReq = 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 (%u > %u)\n", + iwr->u.data.length, u4ExtraSize); + iwr->u.data.length = u4ExtraSize; + } + + if (copy_to_user(iwr->u.data.pointer, prExtraBuf, iwr->u.data.length)) + ret = -EFAULT; + } + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); + prExtraBuf = NULL; + + break; + +#endif + +#if 1 + case SIOCSIWESSID: /* 0x8B1A, set SSID (network name) */ + u4ExtraSize = iwr->u.essid.length; + if (u4ExtraSize > 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, u4ExtraSize)) + ret = -EFAULT; + else + ret = wext_set_essid(prDev, NULL, &iwr->u.essid, prExtraBuf); + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, IW_ESSID_MAX_SIZE + 4); + prExtraBuf = NULL; + break; + +#endif + + case SIOCGIWESSID: /* 0x8B1B, get SSID */ + u4ExtraSize = iwr->u.essid.length; + if (!iwr->u.essid.pointer) { + ret = -EINVAL; + break; + } + + if (u4ExtraSize != IW_ESSID_MAX_SIZE && u4ExtraSize != IW_ESSID_MAX_SIZE + 1) { + DBGLOG(INIT, INFO, "[wifi] iwr->u.essid.length:%d error\n", iwr->u.essid.length); + ret = -E2BIG; /* let caller try larger buffer */ + break; + } + + prExtraBuf = kalMemAlloc(IW_ESSID_MAX_SIZE + 1, 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 + 1); + 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 */ + u4ExtraSize = iwr->u.encoding.length; + if (iwr->u.encoding.pointer) { + if (u4ExtraSize > 16) { + ret = -E2BIG; + break; + } + + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, iwr->u.encoding.pointer, u4ExtraSize)) + ret = -EFAULT; + } else if (u4ExtraSize != 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)); + + u4ExtraSize = iwr->u.data.length; + if (1 /* wlanQueryWapiMode(prGlueInfo->prAdapter) */) { + /* Fixed length structure */ +#if CFG_SUPPORT_WAPI + if (u4ExtraSize > 42 /* The max wapi ie buffer */) { + ret = -EINVAL; + break; + } +#endif + if (u4ExtraSize) { + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + if (copy_from_user(prExtraBuf, iwr->u.data.pointer, u4ExtraSize)) + ret = -EFAULT; + else + wext_support_ioctl_SIOCSIWGENIE(prGlueInfo, prExtraBuf, u4ExtraSize); + 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; + if (!u4ExtraSize || u4ExtraSize > (sizeof(struct iw_encode_ext) + 32)) { + ret = -EINVAL; + break; + } + + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + kalMemZero(prExtraBuf, u4ExtraSize); + if (!copy_from_user(prExtraBuf, iwr->u.encoding.pointer, u4ExtraSize)) + ret = wext_set_encode_ext(prDev, NULL, &iwr->u.encoding, prExtraBuf); + else + ret = -EFAULT; + kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); + prExtraBuf = NULL; + } else if (iwr->u.encoding.length != 0) + ret = -EINVAL; + 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: + { + wext_support_ioctl_SIOCSIWPMKSA_Action(prDev, prExtraBuf, IW_PMKSA_ADD, + &ret); + } + break; + case IW_PMKSA_REMOVE: + break; + case IW_PMKSA_FLUSH: + { + wext_support_ioctl_SIOCSIWPMKSA_Action(prDev, prExtraBuf, + IW_PMKSA_FLUSH, &ret); + } + 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: + ret = -EOPNOTSUPP; + break; + } + + return ret; +} /* wext_support_ioctl */ + +static void wext_support_ioctl_SIOCSIWGENIE(IN P_GLUE_INFO_T prGlueInfo, IN char *prExtraBuf, IN UINT_32 u4ExtraSize) +{ + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + +#if CFG_SUPPORT_WAPI + rStatus = kalIoctl(prGlueInfo, wlanoidSetWapiAssocInfo, prExtraBuf, u4ExtraSize, FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + } +#endif + +} + +static void +wext_support_ioctl_SIOCSIWPMKSA_Action(IN struct net_device *prDev, IN char *prExtraBuf, IN int ioMode, OUT int *ret) +{ + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + P_PARAM_PMKID_T prPmkid; + + switch (ioMode) { + case IW_PMKSA_ADD: + 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, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "add pmkid error:%x\n", rStatus); + + kalMemFree(prPmkid, VIR_MEM_TYPE, 8 + sizeof(PARAM_BSSID_INFO_T)); + break; + case IW_PMKSA_FLUSH: + 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, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "flush pmkid error:%x\n", rStatus); + + kalMemFree(prPmkid, VIR_MEM_TYPE, 8); + break; + default: + break; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To send an event (RAW socket pacekt) to user process actively. +* +* \param[in] prGlueInfo Glue layer info. +* \param[in] u4cmd Which event command we want to indicate to user process. +* \param[in] pData Data buffer to be indicated. +* \param[in] dataLen Available data size in pData. +* +* \return (none) +* +* \note Event is indicated to upper layer if cmd is supported and data is valid. +* Using of kernel symbol wireless_send_event(), which is defined in +* after WE-14 (2.4.20). +*/ +/*----------------------------------------------------------------------------*/ +void +wext_indicate_wext_event(IN P_GLUE_INFO_T prGlueInfo, + IN unsigned int u4Cmd, IN unsigned char *pucData, IN unsigned int u4dataLen) +{ + union iwreq_data wrqu; + unsigned char *pucExtraInfo = NULL; +#if WIRELESS_EXT >= 15 + unsigned char *pucDesiredIE = NULL; + unsigned char aucExtraInfoBuf[200]; +#endif +#if WIRELESS_EXT < 18 + int i; +#endif + + memset(&wrqu, 0, sizeof(wrqu)); + + switch (u4Cmd) { + case SIOCGIWTXPOW: + memcpy(&wrqu.power, pucData, u4dataLen); + break; + case SIOCGIWSCAN: + complete_all(&prGlueInfo->rScanComp); + break; + + case SIOCGIWAP: + if (pucData) + ether_addr_copy(wrqu.ap_addr.sa_data, pucData); + else + /* memset(&wrqu.ap_addr.sa_data, 0, ETH_ALEN); */ + eth_zero_addr((u8 *)&wrqu.ap_addr.sa_data); + 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 */ + /* RSN IE found */ + } +#if 0 + else if (wextSrchDesiredWPSIE(pucData, u4dataLen, 0xDD, &pucDesiredIE)) { + /* WPS IE found */ + /* WPS IE found */ + } +#endif + else if (wextSrchDesiredWPAIE(pucData, u4dataLen, 0xDD, &pucDesiredIE)) { + /* WPA IE found */ + /* WPA IE found */ + } +#if CFG_SUPPORT_WAPI /* Android+ */ + else if (wextSrchDesiredWAPIIE(pucData, u4dataLen, &pucDesiredIE)) { + /* WAPI IE found */ + /* 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="); + /* 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 += snprintf(pucExtraInfo, sizeof(aucExtraInfoBuf), + "MLME-MICHAELMICFAILURE.indication %s", + (pAuthReq->u4Flags == PARAM_AUTH_REQUEST_GROUP_ERROR) ? + "groupcast " : "unicast "); + + wrqu.data.length = pucExtraInfo - aucExtraInfoBuf; + pucExtraInfo = aucExtraInfoBuf; + } +#endif /* WIRELESS_EXT < 15 */ + break; + + case IWEVPMKIDCAND: + if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA2 && + prGlueInfo->rWpaInfo.u4KeyMgmt == IW_AUTH_KEY_MGMT_802_1X) { + + /* only used in WPA2 */ +#if WIRELESS_EXT >= 18 + P_PARAM_PMKID_CANDIDATE_T prPmkidCand = (P_PARAM_PMKID_CANDIDATE_T) pucData; + + struct iw_pmkid_cand rPmkidCand; + + pucExtraInfo = aucExtraInfoBuf; + + rPmkidCand.flags = prPmkidCand->u4Flags; + rPmkidCand.index = 0; + rPmkidCand.bssid.sa_family = 0; + kalMemCopy(rPmkidCand.bssid.sa_data, prPmkidCand->arBSSID, 6); + + kalMemCopy(pucExtraInfo, (PUINT_8) &rPmkidCand, sizeof(struct iw_pmkid_cand)); + wrqu.data.length = sizeof(struct iw_pmkid_cand); + + /* pmkid canadidate list is supported after WE-18 */ + /* indicate struct iw_pmkid_cand */ +#else + goto skip_indicate_event; +#endif + } else { + 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: + 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, &bufLen); + +stat_out: + return pStats; +} /* wlan_get_wireless_stats */ + +BOOLEAN wextSrchOkcAndPMKID(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucPMKID, OUT PUINT_8 okc) +{ + INT_32 i4InfoElemLen; + UINT_8 ucDone = 0; + + ASSERT(pucIEStart); + ASSERT(ppucPMKID); + ASSERT(okc); + *okc = 0; + *ppucPMKID = NULL; + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + if (i4InfoElemLen > i4TotalIeLen) + break; + if (pucIEStart[0] == ELEM_ID_VENDOR) { + if (pucIEStart[1] != 4 || pucIEStart[2] != 0 || pucIEStart[3] != 0x8 || pucIEStart[4] != 0x22) + goto check_next; + *okc = pucIEStart[5]; + ucDone |= 1; + } else if (pucIEStart[0] == ELEM_ID_RSN) { + /* RSN IE: EID(1), Len(1), Version(2), GrpCipher(4), PairCipherCnt(2), + ** PairCipherList(PairCipherCnt * 4), AKMCnt(2), AkmList(4*AkmCnt), + ** RSNCap(2), PMKIDCnt(2), PMKIDList(16*PMKIDCnt), GrpMgtCipher(4) + */ + UINT_16 u2CipherCnt = 0; + UINT_16 u2AkmCnt = 0; + INT_32 i4LenToCheck = 8; + + /* if no Pairwise Cipher Count field, bypass */ + if (i4InfoElemLen < i4LenToCheck + 2) + goto check_next; + u2CipherCnt = *(PUINT_16)&pucIEStart[i4LenToCheck]; + i4LenToCheck += 2; /* include length of Pairwise Cipher Count field */ + i4LenToCheck += u2CipherCnt * 4; /* include cipher list field */ + /* if no AKM Count, bypass */ + if (i4InfoElemLen < i4LenToCheck + 2) + goto check_next; + u2AkmCnt = *(PUINT_16)&pucIEStart[i4LenToCheck]; + i4LenToCheck += 2; /* include length of AKM Count */ + i4LenToCheck += u2AkmCnt * 4 + 2; /* include akm list field and RSN Cap field */ + /* if IE length is 10 + u2CipherCnt * 4 + 2 + u2AkmCnt * 4 + 2 + 6, + ** means PMKID count field is zero, and Group Mgmt Cipher may be exist + */ + if (i4InfoElemLen <= i4LenToCheck + 6) + goto check_next; + *ppucPMKID = pucIEStart + i4LenToCheck; /* return PMKID field and started at PMKID count */ + ucDone |= 2; + } + if (ucDone == 3) + return TRUE; + /* check desired EID */ + /* Select next information element. */ +check_next: + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + return FALSE; +} + +#endif /* WIRELESS_EXT */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_wext_priv.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_wext_priv.c new file mode 100644 index 0000000000000..c4e22efed625e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/gl_wext_priv.c @@ -0,0 +1,4037 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_wext_priv.c#8 +*/ + +/* + * ! \file gl_wext_priv.c + * \brief This file includes private ioctl support. + */ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" +#include "gl_os.h" +#include "gl_wext_priv.h" +#if CFG_SUPPORT_WAPI +#include "gl_sec.h" +#endif +#if CFG_ENABLE_WIFI_DIRECT +#include "gl_p2p_os.h" +#endif + +#if CFG_SUPPORT_QA_TOOL +#include "gl_ate_agent.h" +#include "gl_qa_agent.h" +/* extern UINT_16 g_u2DumpIndex; */ +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define NUM_SUPPORTED_OIDS (sizeof(arWlanOidReqTable) / sizeof(WLAN_REQ_ENTRY)) +#define CMD_OID_BUF_LENGTH 4096 + +#define CMD_GET_WIFI_TYPE "GET_WIFI_TYPE" + +#define TX_RATE_MODE_CCK 0 +#define TX_RATE_MODE_OFDM 1 +#define TX_RATE_MODE_HTMIX 2 +#define TX_RATE_MODE_HTGF 3 +#define TX_RATE_MODE_VHT 4 +#define MAX_TX_MODE 5 + +/******************************************************************************* +* 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); + +static void +priv_driver_get_chip_config_16(PUINT_8 pucStartAddr, + UINT_32 u4Length, UINT_32 u4Line, int i4TotalLen, INT_32 i4BytesWritten, + char *pcCommand); + +static void +priv_driver_get_chip_config_4(PUINT_32 pu4StartAddr, + UINT_32 u4Length, UINT_32 u4Line, int i4TotalLen, INT_32 i4BytesWritten, char *pcCommand); + +#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 U B L I C D A T A + ******************************************************************************* + */ +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR +/* link quality monitor */ +/* data rate mapping table for CCK */ +struct cckDataRateMappingTable_t { + UINT_32 rate[4]; +} g_rCckDataRateMappingTable = { + {10, 20, 55, 110} +}; +/* data rate mapping table for OFDM */ +struct ofdmDataRateMappingTable_t { + UINT_32 rate[8]; +} g_rOfdmDataRateMappingTable = { + {60, 90, 120, 180, 240, 360, 480, 540} +}; +/* data rate mapping table for 802.11n and 802.11ac */ +struct dataRateMappingTable_t { + struct nsts_t { + struct bw_t { + struct sgi_t { + UINT_32 rate[10]; + } sgi[2]; + } bw[4]; + } nsts[3]; +} g_rDataRateMappingTable = { + { { { { { /* 20MHz */ + { /* no SGI */ + {65, 130, 195, 260, 390, 520, 585, 650, 780, 0} }, + { /* SGI */ + {72, 144, 217, 289, 433, 578, 650, 722, 867, 0} } + } + }, + { { /* 40MHz */ + { /* no SGI */ + {135, 270, 405, 540, 810, 1080, 1215, 1350, 1620, 1800} }, + { /* SGI */ + {150, 300, 450, 600, 900, 1200, 1350, 1500, 1800, 2000} } + } + }, + { { /* 80MHz */ + { /* no SGI */ + {293, 585, 878, 1170, 1755, 2340, 2633, 2925, 3510, 3900} }, + { /* SGI */ + {325, 650, 975, 1300, 1950, 2600, 2925, 3250, 3900, 4333} } + } + }, + { { /* 160MHz */ + { /* no SGI */ + {585, 1170, 1755, 2340, 3510, 4680, 5265, 5850, 7020, 7800} }, + { /* SGI */ + {650, 1300, 1950, 2600, 3900, 5200, 5850, 6500, 7800, 8667} } + } + } + } + }, + { { { { /* 20MHz */ + { /* no SGI */ + {130, 260, 390, 520, 780, 1040, 1170, 1300, 1560, 0} }, + { /* SGI */ + {144, 289, 433, 578, 867, 1156, 1303, 1444, 1733, 0} } + } + }, + { { /* 40MHz */ + { /* no SGI */ + {270, 540, 810, 1080, 1620, 2160, 2430, 2700, 3240, 3600} }, + { /* SGI */ + {300, 600, 900, 1200, 1800, 2400, 2700, 3000, 3600, 4000} } + } + }, + { { /* 80MHz */ + { /* no SGI */ + {585, 1170, 1755, 2340, 3510, 4680, 5265, 5850, 7020, 7800} }, + { /* SGI */ + {650, 1300, 1950, 2600, 3900, 5200, 5850, 6500, 7800, 8667} } + } + }, + { { /* 160MHz */ + { /* no SGI */ + {1170, 2340, 3510, 4680, 7020, 9360, 1053, 1170, 1404, 1560} }, + { /* SGI */ + {1300, 2600, 3900, 5200, 7800, 10400, 11700, 13000, 15600, 17333} } + } + } + } + }, + { { { { /* 20MHz */ + { /* no SGI */ + {195, 390, 585, 780, 1170, 1560, 1755, 1950, 2340, 2600} }, + { /* SGI */ + {217, 433, 650, 867, 1300, 1733, 1950, 2167, 2600, 2889} } + } + }, + { { /* 40MHz */ + { /* no SGI */ + {405, 810, 1215, 1620, 2430, 3240, 3645, 4050, 4860, 5400} }, + { /* SGI */ + {450, 900, 1350, 1800, 2700, 3600, 4050, 4500, 5400, 6000} } + } + }, + { { /* 80MHz */ + { /* no SGI */ + {878, 1755, 2633, 3510, 5265, 7020, 0, 8775, 10530, 11700} }, + { /* SGI */ + {975, 1950, 2925, 3900, 5850, 7800, 0, 9750, 11700, 13000} } + } + }, + { { /* 160MHz */ + { /* no SGI */ + {1755, 3510, 5265, 7020, 10530, 14040, 15795, 17550, 21060, 0} }, + { /* SGI */ + {1950, 3900, 5850, 7800, 11700, 15600, 17550, 19500, 23400, 0} } + } + } + } + } + } +}; +#endif +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static UINT_8 aucOidBuf[CMD_OID_BUF_LENGTH] = { 0 }; +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR +static UINT_32 hw_rate_ofdm_num(uint16_t ofdm_idx) +{ + switch (ofdm_idx) { + case 11: /* 6M */ + return g_rOfdmDataRateMappingTable.rate[0]; + case 15: /* 9M */ + return g_rOfdmDataRateMappingTable.rate[1]; + case 10: /* 12M */ + return g_rOfdmDataRateMappingTable.rate[2]; + case 14: /* 18M */ + return g_rOfdmDataRateMappingTable.rate[3]; + case 9: /* 24M */ + return g_rOfdmDataRateMappingTable.rate[4]; + case 13: /* 36M */ + return g_rOfdmDataRateMappingTable.rate[5]; + case 8: /* 48M */ + return g_rOfdmDataRateMappingTable.rate[6]; + case 12: /* 54M */ + return g_rOfdmDataRateMappingTable.rate[7]; + default: + return 0; + } +} +#endif +/* OID processing table */ +/* + * Order is important here because the OIDs should be in order of + * increasing value for binary searching. + */ +static WLAN_REQ_ENTRY arWlanOidReqTable[] = { + /* + * {(NDIS_OID)rOid, + * (PUINT_8)pucOidName, + * fgQryBufLenChecking, fgSetBufLenChecking, fgIsHandleInGlueLayerOnly, u4InfoBufLen, + * pfOidQueryHandler, + * pfOidSetHandler} + */ + /* General Operational Characteristics */ + + /* Ethernet Operational Characteristics */ + {OID_802_3_CURRENT_ADDRESS, + DISP_STRING("OID_802_3_CURRENT_ADDRESS"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 6, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryCurrentAddr, + NULL}, + + /* OID_802_3_MULTICAST_LIST */ + /* OID_802_3_MAXIMUM_LIST_SIZE */ + /* Ethernet Statistics */ + + /* NDIS 802.11 Wireless LAN OIDs */ + {OID_802_11_SUPPORTED_RATES, + DISP_STRING("OID_802_11_SUPPORTED_RATES"), + TRUE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_RATES_EX), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQuerySupportedRates, + NULL} + , + /* + * {OID_802_11_CONFIGURATION, + * DISP_STRING("OID_802_11_CONFIGURATION"), + * TRUE, TRUE, ENUM_OID_GLUE_EXTENSION, sizeof(PARAM_802_11_CONFIG_T), + * (PFN_OID_HANDLER_FUNC_REQ)reqExtQueryConfiguration, + * (PFN_OID_HANDLER_FUNC_REQ)reqExtSetConfiguration}, + */ + {OID_PNP_SET_POWER, + DISP_STRING("OID_PNP_SET_POWER"), + TRUE, FALSE, ENUM_OID_GLUE_EXTENSION, sizeof(PARAM_DEVICE_POWER_STATE), + NULL, + (PFN_OID_HANDLER_FUNC_REQ) reqExtSetAcpiDevicePowerState} + , + + /* Custom OIDs */ + {OID_CUSTOM_OID_INTERFACE_VERSION, + DISP_STRING("OID_CUSTOM_OID_INTERFACE_VERSION"), + TRUE, FALSE, ENUM_OID_DRIVER_CORE, 4, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryOidInterfaceVersion, + NULL} + , + + /* + * #if PTA_ENABLED + * {OID_CUSTOM_BT_COEXIST_CTRL, + * DISP_STRING("OID_CUSTOM_BT_COEXIST_CTRL"), + * FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_BT_COEXIST_T), + * NULL, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetBtCoexistCtrl}, + * #endif + */ + + /* + * {OID_CUSTOM_POWER_MANAGEMENT_PROFILE, + * DISP_STRING("OID_CUSTOM_POWER_MANAGEMENT_PROFILE"), + * FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryPwrMgmtProfParam, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetPwrMgmtProfParam}, + * {OID_CUSTOM_PATTERN_CONFIG, + * DISP_STRING("OID_CUSTOM_PATTERN_CONFIG"), + * TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_PATTERN_SEARCH_CONFIG_STRUCT_T), + * NULL, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetPatternConfig}, + * {OID_CUSTOM_BG_SSID_SEARCH_CONFIG, + * DISP_STRING("OID_CUSTOM_BG_SSID_SEARCH_CONFIG"), + * FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + * NULL, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetBgSsidParam}, + * {OID_CUSTOM_VOIP_SETUP, + * DISP_STRING("OID_CUSTOM_VOIP_SETUP"), + * TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryVoipConnectionStatus, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetVoipConnectionStatus}, + * {OID_CUSTOM_ADD_TS, + * DISP_STRING("OID_CUSTOM_ADD_TS"), + * TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + * NULL, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidAddTS}, + * {OID_CUSTOM_DEL_TS, + * DISP_STRING("OID_CUSTOM_DEL_TS"), + * TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + * NULL, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidDelTS}, + */ + + /* + * #if CFG_LP_PATTERN_SEARCH_SLT + * {OID_CUSTOM_SLT, + * DISP_STRING("OID_CUSTOM_SLT"), + * FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidQuerySltResult, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetSltMode}, + * #endif + * + * {OID_CUSTOM_ROAMING_EN, + * DISP_STRING("OID_CUSTOM_ROAMING_EN"), + * TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryRoamingFunction, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetRoamingFunction}, + * {OID_CUSTOM_WMM_PS_TEST, + * DISP_STRING("OID_CUSTOM_WMM_PS_TEST"), + * TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + * NULL, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetWiFiWmmPsTest}, + * {OID_CUSTOM_COUNTRY_STRING, + * DISP_STRING("OID_CUSTOM_COUNTRY_STRING"), + * FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryCurrentCountry, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetCurrentCountry}, + * + * #if CFG_SUPPORT_802_11D + * {OID_CUSTOM_MULTI_DOMAIN_CAPABILITY, + * DISP_STRING("OID_CUSTOM_MULTI_DOMAIN_CAPABILITY"), + * FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryMultiDomainCap, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetMultiDomainCap}, + * #endif + * + * {OID_CUSTOM_GPIO2_MODE, + * DISP_STRING("OID_CUSTOM_GPIO2_MODE"), + * FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(ENUM_PARAM_GPIO2_MODE_T), + * NULL, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetGPIO2Mode}, + * {OID_CUSTOM_CONTINUOUS_POLL, + * DISP_STRING("OID_CUSTOM_CONTINUOUS_POLL"), + * FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CONTINUOUS_POLL_T), + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryContinuousPollInterval, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetContinuousPollProfile}, + * {OID_CUSTOM_DISABLE_BEACON_DETECTION, + * DISP_STRING("OID_CUSTOM_DISABLE_BEACON_DETECTION"), + * FALSE, TRUE, ENUM_OID_DRIVER_CORE, 4, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryDisableBeaconDetectionFunc, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetDisableBeaconDetectionFunc}, + */ + + /* WPS */ + /* + * {OID_CUSTOM_DISABLE_PRIVACY_CHECK, + * DISP_STRING("OID_CUSTOM_DISABLE_PRIVACY_CHECK"), + * FALSE, TRUE, ENUM_OID_DRIVER_CORE, 4, + * NULL, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetDisablePriavcyCheck}, + */ + + {OID_CUSTOM_MCR_RW, + DISP_STRING("OID_CUSTOM_MCR_RW"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryMcrRead, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetMcrWrite} + , + + {OID_CUSTOM_EEPROM_RW, + DISP_STRING("OID_CUSTOM_EEPROM_RW"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryEepromRead, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetEepromWrite} + , + + {OID_CUSTOM_SW_CTRL, + DISP_STRING("OID_CUSTOM_SW_CTRL"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQuerySwCtrlRead, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetSwCtrlWrite} + , + + {OID_CUSTOM_MEM_DUMP, + DISP_STRING("OID_CUSTOM_MEM_DUMP"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_MEM_DUMP_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryMemDump, + NULL} + , + + {OID_CUSTOM_TEST_MODE, + DISP_STRING("OID_CUSTOM_TEST_MODE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + NULL, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestSetTestMode} + , + + /* + * {OID_CUSTOM_TEST_RX_STATUS, + * DISP_STRING("OID_CUSTOM_TEST_RX_STATUS"), + * FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T), + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryRfTestRxStatus, + * NULL}, + * {OID_CUSTOM_TEST_TX_STATUS, + * DISP_STRING("OID_CUSTOM_TEST_TX_STATUS"), + * FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T), + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryRfTestTxStatus, + * NULL}, + */ + {OID_CUSTOM_ABORT_TEST_MODE, + DISP_STRING("OID_CUSTOM_ABORT_TEST_MODE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + NULL, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestSetAbortTestMode} + , + {OID_CUSTOM_MTK_WIFI_TEST, + DISP_STRING("OID_CUSTOM_MTK_WIFI_TEST"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_MTK_WIFI_TEST_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestQueryAutoTest, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestSetAutoTest} + , + {OID_CUSTOM_TEST_ICAP_MODE, + DISP_STRING("OID_CUSTOM_TEST_ICAP_MODE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + NULL, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestSetTestIcapMode} + , + + /* 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 + * ISP_STRING("OID_CUSTOM_SINGLE_ANTENNA") + * ALSE, FALSE, ENUM_OID_DRIVER_CORE, 4 + * PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryBtSingleAntenna + * PFN_OID_HANDLER_FUNC_REQ)wlanoidSetBtSingleAntenna}, + * {OID_CUSTOM_SET_PTA + * ISP_STRING("OID_CUSTOM_SET_PTA + * FALSE, FALSE, ENUM_OID_DRIVER_CORE, + * (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryP + * (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_LOWLATENCY_MODE + {OID_CUSTOM_LOWLATENCY_MODE, + DISP_STRING("OID_CUSTOM_LOWLATENCY_MODE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(UINT_32), + NULL, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetLowLatencyMode} + , +#endif + + {OID_IPC_WIFI_LOG_UI, + DISP_STRING("OID_IPC_WIFI_LOG_UI"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(struct PARAM_WIFI_LOG_LEVEL_UI), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryWifiLogLevelSupport, + NULL} + , + + {OID_IPC_WIFI_LOG_LEVEL, + DISP_STRING("OID_IPC_WIFI_LOG_LEVEL"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(struct PARAM_WIFI_LOG_LEVEL), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryWifiLogLevel, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetWifiLogLevel} + , + +#if CFG_SUPPORT_ANT_SWAP + {OID_CUSTOM_QUERY_ANT_SWAP_CAPABILITY, + DISP_STRING("OID_CUSTOM_QUERY_ANT_SWAP_CAPABILITY"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(UINT_32), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryAntSwapCapability, + NULL} + , +#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; + + /* prNetDev 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)); + +#if (CFG_SUPPORT_QA_TOOL) + case IOCTL_QA_TOOL_DAEMON: + return priv_qa_agent(prNetDev, &rIwReqInfo, &(prIwReq->u), (char *)&(prIwReq->u)); +#endif + + default: + return -EOPNOTSUPP; + + } /* end of switch */ + +} /* priv_support_ioctl */ + +#if CFG_SUPPORT_BATCH_SCAN + +EVENT_BATCH_RESULT_T g_rEventBatchResult[CFG_BATCH_MAX_MSCAN]; + +UINT_32 batchChannelNum2Freq(UINT_32 u4ChannelNum) +{ + UINT_32 u4ChannelInMHz; + + if (u4ChannelNum >= 1 && u4ChannelNum <= 13) + u4ChannelInMHz = 2412 + (u4ChannelNum - 1) * 5; + else if (u4ChannelNum == 14) + u4ChannelInMHz = 2484; + else if (u4ChannelNum == 133) + u4ChannelInMHz = 3665; /* 802.11y */ + else if (u4ChannelNum == 137) + u4ChannelInMHz = 3685; /* 802.11y */ + else if (u4ChannelNum >= 34 && u4ChannelNum <= 165) + u4ChannelInMHz = 5000 + u4ChannelNum * 5; + else if (u4ChannelNum >= 183 && u4ChannelNum <= 196) + u4ChannelInMHz = 4000 + u4ChannelNum * 5; + else + u4ChannelInMHz = 0; + + return u4ChannelInMHz; +} + +#define TMP_TEXT_LEN_S 40 +#define TMP_TEXT_LEN_L 60 +static UCHAR text1[TMP_TEXT_LEN_S], text2[TMP_TEXT_LEN_L], text3[TMP_TEXT_LEN_L]; /* A safe len */ + +WLAN_STATUS +batchConvertResult(IN P_EVENT_BATCH_RESULT_T prEventBatchResult, + OUT PVOID pvBuffer, IN UINT_32 u4MaxBufferLen, OUT PUINT_32 pu4RetLen) +{ + CHAR *p = pvBuffer; + CHAR ssid[ELEM_MAX_LEN_SSID + 1]; + INT_32 nsize, nsize1, nsize2, nsize3, scancount; + INT_32 i, j, nleft; + UINT_32 freq; + UINT_8 ucSSIDLen = 0; + + P_EVENT_BATCH_RESULT_ENTRY_T prEntry; + P_EVENT_BATCH_RESULT_T pBr; + + nsize = 0; + nleft = u4MaxBufferLen - 5; /* -5 for "----\n" */ + + pBr = prEventBatchResult; + scancount = 0; + for (j = 0; j < CFG_BATCH_MAX_MSCAN; j++) { + scancount += pBr->ucScanCount; + pBr++; + } + + nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "scancount=%d\nnextcount=%d\n", scancount, scancount); + if (nsize1 < nleft) { + nsize1 = kalSnprintf(p, nleft, "%s", text1); + if (nsize1 < 0) + return WLAN_STATUS_FAILURE; + p += nsize1; + nleft -= nsize1; + } else + goto short_buf; + + pBr = prEventBatchResult; + for (j = 0; j < CFG_BATCH_MAX_MSCAN; j++) { + DBGLOG(SCN, TRACE, "convert mscan = %d, apcount=%d, nleft=%d\n", j, pBr->ucScanCount, nleft); + + if (pBr->ucScanCount == 0) { + pBr++; + continue; + } + + nleft -= 5; /* -5 for "####\n" */ + + /* We only support one round scan result now. */ + nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "apcount=%d\n", pBr->ucScanCount); + if (nsize1 < nleft) { + nsize1 = kalSnprintf(p, nleft, "%s", text1); + if (nsize1 < 0) + return WLAN_STATUS_FAILURE; + p += nsize1; + nleft -= nsize1; + } else + goto short_buf; + + for (i = 0; i < pBr->ucScanCount; i++) { + prEntry = &pBr->arBatchResult[i]; + + nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "bssid=" MACSTR "\n", + MAC2STR(prEntry->aucBssid)); + if (nsize1 < 0) { + DBGLOG(SCN, ERROR, "kalSnprintf fail\n"); + return WLAN_STATUS_FAILURE; + } + + ucSSIDLen = prEntry->ucSSIDLen < ELEM_MAX_LEN_SSID ? prEntry->ucSSIDLen : ELEM_MAX_LEN_SSID; + kalMemCopy(ssid, prEntry->aucSSID, ucSSIDLen); + + ucSSIDLen = (prEntry->ucSSIDLen < + (ELEM_MAX_LEN_SSID - 1) ? prEntry->ucSSIDLen : (ELEM_MAX_LEN_SSID - 1)); + ssid[ucSSIDLen] = '\0'; + nsize2 = kalSnprintf(text2, TMP_TEXT_LEN_L, "ssid=%s\n", ssid); + + if (nsize2 < 0) { + DBGLOG(SCN, ERROR, "kalSnprintf fail\n"); + return WLAN_STATUS_FAILURE; + } + + freq = batchChannelNum2Freq(prEntry->ucFreq); + nsize3 = + kalSnprintf(text3, TMP_TEXT_LEN_L, + "freq=%u\nlevel=%d\ndist=%u\ndistSd=%u\n====\n", + freq, prEntry->cRssi, prEntry->u4Dist, prEntry->u4Distsd); + + if (nsize3 < 0) { + DBGLOG(SCN, ERROR, "kalSnprintf fail\n"); + return WLAN_STATUS_FAILURE; + } + + nsize = nsize1 + nsize2 + nsize3; + if (nsize < nleft) { + + kalStrnCpy(p, text1, TMP_TEXT_LEN_S); + p += nsize1; + + kalStrnCpy(p, text2, TMP_TEXT_LEN_L); + p += nsize2; + + kalStrnCpy(p, text3, TMP_TEXT_LEN_L); + p += nsize3; + + nleft -= nsize; + } else { + DBGLOG(SCN, TRACE, "Warning: Early break! (%d)\n", i); + break; /* discard following entries, TODO: apcount? */ + } + } + + nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "%s", "####\n"); + + if (nsize1 < 0) { + DBGLOG(SCN, ERROR, "kalSnprintf fail\n"); + return WLAN_STATUS_FAILURE; + } + + p += kalSnprintf(p, nleft, "%s", text1); + + nleft -= nsize1; + pBr++; + } + + nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "%s", "----\n"); + if (nsize1 < 0) { + DBGLOG(SCN, ERROR, "kalSnprintf fail\n"); + return WLAN_STATUS_FAILURE; + } + + nleft -= kalSnprintf(p, nleft, "%s", text1); + + *pu4RetLen = u4MaxBufferLen - nleft; + DBGLOG(SCN, TRACE, "total len = %u (max len = %u)\n", *pu4RetLen, u4MaxBufferLen); + + return WLAN_STATUS_SUCCESS; + +short_buf: + DBGLOG(SCN, TRACE, "Short buffer issue! %u > %u, %s\n", + u4MaxBufferLen + (nsize - nleft), u4MaxBufferLen, (PUINT_8)pvBuffer); + return WLAN_STATUS_INVALID_LENGTH; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Private ioctl set int handler. +* +* \param[in] prNetDev Net device requested. +* \param[in] prIwReqInfo Pointer to iwreq structure. +* \param[in] prIwReqData The ioctl data structure, use the field of sub-command. +* \param[in] pcExtra The buffer with input value +* +* \retval 0 For success. +* \retval -EOPNOTSUPP If cmd is not supported. +* \retval -EINVAL If a value is out of range. +* +*/ +/*----------------------------------------------------------------------------*/ +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 (GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra) == FALSE) + 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: + 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 if (pu4IntBuf[1] == PRIV_CMD_TEST_MAGIC_KEY_ICAP) { + prNdisReq->ndisOidCmd = OID_CUSTOM_TEST_ICAP_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: + 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: + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + if (pu4IntBuf[1] == PRIV_CMD_TEST_MAGIC_KEY) { + if (pu4IntBuf[2] == PRIV_CMD_TEST_MAGIC_KEY) + prGlueInfo->fgMcrAccessAllowed = TRUE; + status = 0; + break; + } + if (prGlueInfo->fgMcrAccessAllowed) { + 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: + 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: + /* pu4IntBuf[0] is used as input SubCmd */ + rStatus = wlanSetInformation(prGlueInfo->prAdapter, wlanoidSetBeaconInterval, (PVOID)&pu4IntBuf[1], + 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, &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: + { + PARAM_POWER_MODE_T rPowerMode; + P_BSS_INFO_T prBssInfo = prGlueInfo->prAdapter->prAisBssInfo; + + if (!prBssInfo) + break; + + rPowerMode.ePowerMode = (PARAM_POWER_MODE) pu4IntBuf[1]; + rPowerMode.ucBssIdx = prBssInfo->ucBssIndex; + + /* pu4IntBuf[0] is used as input SubCmd */ + kalIoctl(prGlueInfo, wlanoidSet802dot11PowerSaveProfile, &rPowerMode, + sizeof(PARAM_POWER_MODE_T), FALSE, FALSE, TRUE, &u4BufLen); + } + break; + + case PRIV_CMD_WMM_PS: + { + PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T rWmmPsTest; + + rWmmPsTest.bmfgApsdEnAc = (UINT_8) pu4IntBuf[1]; + rWmmPsTest.ucIsEnterPsAtOnce = (UINT_8) pu4IntBuf[2]; + rWmmPsTest.ucIsDisableUcTrigger = (UINT_8) pu4IntBuf[3]; + rWmmPsTest.reserved = 0; + + kalIoctl(prGlueInfo, + wlanoidSetWiFiWmmPsTest, + (PVOID)&rWmmPsTest, + sizeof(PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T), FALSE, FALSE, TRUE, &u4BufLen); + } + break; + +#if 0 + case PRIV_CMD_ADHOC_MODE: + /* pu4IntBuf[0] is used as input SubCmd */ + rStatus = wlanSetInformation(prGlueInfo->prAdapter, wlanoidSetAdHocMode, (PVOID)&pu4IntBuf[1], + sizeof(UINT_32), &u4BufLen); + break; +#endif + + case PRIV_CUSTOM_BWCS_CMD: + + DBGLOG(REQ, INFO, + "pu4IntBuf[1] = %x, size of PTA_IPC_T = %zu.\n", pu4IntBuf[1], sizeof(PARAM_PTA_IPC_T)); + + prPtaIpc = (P_PTA_IPC_T) aucOidBuf; + prPtaIpc->u.aucBTPParams[0] = (UINT_8) (pu4IntBuf[1] >> 24); + prPtaIpc->u.aucBTPParams[1] = (UINT_8) (pu4IntBuf[1] >> 16); + prPtaIpc->u.aucBTPParams[2] = (UINT_8) (pu4IntBuf[1] >> 8); + prPtaIpc->u.aucBTPParams[3] = (UINT_8) (pu4IntBuf[1]); + + DBGLOG(REQ, INFO, + "BCM BWCS CMD : PRIV_CUSTOM_BWCS_CMD : aucBTPParams[0] = %02x, aucBTPParams[1] = %02x.\n", + prPtaIpc->u.aucBTPParams[0], prPtaIpc->u.aucBTPParams[1]); + DBGLOG(REQ, INFO, + "BCM BWCS CMD : PRIV_CUSTOM_BWCS_CMD : aucBTPParams[2] = %02x, aucBTPParams[3] = %02x.\n", + 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 (status != WLAN_STATUS_SUCCESS) + 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_STRUCT_T rSetP2P; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + rSetP2P.u4Enable = pu4IntBuf[1]; + rSetP2P.u4Mode = pu4IntBuf[2]; +#if 1 + if (!rSetP2P.u4Enable) + p2pNetUnregister(prGlueInfo, TRUE); + + /* pu4IntBuf[0] is used as input SubCmd */ + rWlanStatus = kalIoctl(prGlueInfo, wlanoidSetP2pMode, (PVOID)&rSetP2P, + sizeof(PARAM_CUSTOM_P2P_SET_STRUCT_T), FALSE, FALSE, TRUE, &u4BufLen); + + if ((rSetP2P.u4Enable) && (rWlanStatus == WLAN_STATUS_SUCCESS)) + p2pNetRegister(prGlueInfo, TRUE); +#endif + + } + break; +#endif + +#if (CFG_MET_PACKET_TRACE_SUPPORT == 1) + case PRIV_CMD_MET_PROFILING: + { + /* PARAM_CUSTOM_WFD_DEBUG_STRUCT_T rWfdDebugModeInfo; */ + /* rWfdDebugModeInfo.ucWFDDebugMode=(UINT_8)pu4IntBuf[1]; */ + /* rWfdDebugModeInfo.u2SNPeriod=(UINT_16)pu4IntBuf[2]; */ + /* DBGLOG(REQ, INFO, ("WFD Debug Mode:%d Period:%d\n", */ + /* rWfdDebugModeInfo.ucWFDDebugMode, rWfdDebugModeInfo.u2SNPeriod)); */ + prGlueInfo->fgMetProfilingEn = (UINT_8) pu4IntBuf[1]; + prGlueInfo->u2MetUdpPort = (UINT_16) pu4IntBuf[2]; + /* + * DBGLOG(INIT, INFO, ("MET_PROF: Enable=%d UDP_PORT=%d\n", + * prGlueInfo->fgMetProfilingEn, prGlueInfo->u2MetUdpPort); + */ + + } + 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; + + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + if (GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra) == FALSE) + 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: + 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) { + prIwReqData->mode = *(PUINT_32) &prNdisReq->ndisOidContent[4]; + /* + * if (copy_to_user(prIwReqData->data.pointer, + * &prNdisReq->ndisOidContent[4], 4)) { + * return -EFAULT; + * } + */ + } + return status; + +#if CFG_SUPPORT_PRIV_MCR_RW + case PRIV_CMD_ACCESS_MCR: + 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) + 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 = sizeof(PARAM_CUSTOM_MEM_DUMP_STRUCT_T); + prNdisReq->outNdisOidLength = sizeof(PARAM_CUSTOM_MEM_DUMP_STRUCT_T); + + status = priv_get_ndis(prNetDev, prNdisReq, &u4BufLen); + if (status == 0) + prIwReqData->mode = *(PUINT_32) &prNdisReq->ndisOidContent[0]; + return status; + + case PRIV_CMD_SW_CTRL: + + 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) + 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_8 ucNumOfChannel, i; + UINT_8 ucMaxChannelNum = 50; + RF_CHANNEL_INFO_T aucChannelList[50] = { {0} }; + INT_32 ch[50]; + + kalGetChannelList(prGlueInfo, BAND_NULL, ucMaxChannelNum, &ucNumOfChannel, aucChannelList); + DBGLOG(RLM, INFO, "PRIV_CMD_GET_CH_LIST: return %d channels\n", ucNumOfChannel); + if (ucNumOfChannel > 50) + ucNumOfChannel = 50; + + for (i = 0; i < ucNumOfChannel; i++) + ch[i] = (INT_32) aucChannelList[i].ucChannelNum; + + prIwReqData->data.length = ucNumOfChannel; + if (copy_to_user(prIwReqData->data.pointer, ch, ucNumOfChannel * 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_16 i = 0; + UINT_32 u4SubCmd, u4BufLen, u4CmdLen; + P_GLUE_INFO_T prGlueInfo; + INT_32 setting[4] = {0}; + int status = 0; + UINT_8 idx = 0; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_SET_TXPWR_CTRL_T prTxpwr; + + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + + if (GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + u4SubCmd = (UINT_32) prIwReqData->data.flags; + u4CmdLen = (UINT_32) prIwReqData->data.length; + + switch (u4SubCmd) { + case PRIV_CMD_SET_TX_POWER: + { + if (u4CmdLen > 4) + return -EINVAL; + if (copy_from_user(setting, prIwReqData->data.pointer, u4CmdLen)) + return -EFAULT; + + 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) && (setting[1] >= 1)) { + idx = setting[1] - 1; + prTxpwr->acTxPwrLimit2G[idx] = 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) && (setting[1] >= 1)) { + idx = setting[1] - 1; + prTxpwr->acTxPwrLimit5G[idx] = 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), FALSE, FALSE, TRUE, &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; + + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + if (GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra) == FALSE) + 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_8 ucNumOfChannel, i; + UINT_8 ucMaxChannelNum = 50; + RF_CHANNEL_INFO_T aucChannelList[50] = { {0} }; + INT_32 ch[50]; + + kalGetChannelList(prGlueInfo, BAND_NULL, ucMaxChannelNum, &ucNumOfChannel, aucChannelList); + DBGLOG(RLM, INFO, "PRIV_CMD_GET_CH_LIST: return %d channels\n", ucNumOfChannel); + if (ucNumOfChannel > 50) + ucNumOfChannel = 50; + + for (i = 0; i < ucNumOfChannel; i++) + ch[i] = (INT_32) aucChannelList[i].ucChannelNum; + + prIwReqData->data.length = ucNumOfChannel; + if (copy_to_user(prIwReqData->data.pointer, ch, ucNumOfChannel * sizeof(INT_32))) + return -EFAULT; + else + return status; + } + default: + break; + } + + return status; +} /* priv_get_ints */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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; + + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + /* ASSERT(prIwReqInfo); */ + ASSERT(prIwReqData); + /* ASSERT(pcExtra); */ + + kalMemZero(&aucOidBuf[0], sizeof(aucOidBuf)); + + if (GLUE_CHK_PR2(prNetDev, prIwReqData) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + u4SubCmd = (UINT_32) prIwReqData->data.flags; + +#if 0 + DBGLOG(INIT, INFO, "priv_set_struct(): prIwReqInfo->cmd(0x%X), u4SubCmd(%ld)\n", + prIwReqInfo->cmd, u4SubCmd; +#endif + + switch (u4SubCmd) { +#if 0 /* PTA_ENABLED */ + case PRIV_CMD_BT_COEXIST: + u4CmdLen = prIwReqData->data.length * sizeof(UINT_32); + ASSERT(sizeof(PARAM_CUSTOM_BT_COEXIST_T) >= u4CmdLen); + if (sizeof(PARAM_CUSTOM_BT_COEXIST_T) < u4CmdLen) + return -EFAULT; + + if (copy_from_user(&aucOidBuf[0], prIwReqData->data.pointer, u4CmdLen)) { + status = -EFAULT; /* return -EFAULT; */ + break; + } + + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetBtCoexistCtrl, (PVOID)&aucOidBuf[0], u4CmdLen, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + 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 (status != WLAN_STATUS_SUCCESS) + status = -EFAULT; + + break; + +#if CFG_SUPPORT_WPS2 + case PRIV_CMD_WSC_PROBE_REQ: + { + /* retrieve IE for Probe Request */ + u4CmdLen = prIwReqData->data.length; + if (u4CmdLen > GLUE_INFO_WSCIE_LENGTH) { + DBGLOG(REQ, ERROR, "Input data length is invalid %u\n", u4CmdLen); + return -EINVAL; + } + + if (prIwReqData->data.length > 0) { + if (copy_from_user(prGlueInfo->aucWSCIE, + prIwReqData->data.pointer, + u4CmdLen)) { + status = -EFAULT; + break; + } + prGlueInfo->u2WSCIELen = u4CmdLen; + } else { + prGlueInfo->u2WSCIELen = 0; + } + } + break; +#endif + case PRIV_CMD_OID: + u4CmdLen = prIwReqData->data.length; + if (u4CmdLen > CMD_OID_BUF_LENGTH) { + DBGLOG(REQ, ERROR, "Input data length is invalid %u\n", u4CmdLen); + return -EINVAL; + } + if (copy_from_user(&aucOidBuf[0], prIwReqData->data.pointer, u4CmdLen)) { + status = -EFAULT; + break; + } + if (!kalMemCmp(&aucOidBuf[0], pcExtra, u4CmdLen)) { + /* ToDo:: DBGLOG */ + 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: + u4CmdLen = prIwReqData->data.length; + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + if (u4CmdLen > sizeof(prNdisReq->ndisOidContent)) { + DBGLOG(REQ, ERROR, "Input data length is invalid %u\n", u4CmdLen); + return -EINVAL; + } + + if (copy_from_user(&prNdisReq->ndisOidContent[0], + prIwReqData->data.pointer, + u4CmdLen)) { + 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; + + + case PRIV_CMD_GET_WIFI_TYPE: + { + int32_t i4ResultLen; + + u4CmdLen = prIwReqData->data.length; + if (u4CmdLen >= CMD_OID_BUF_LENGTH) { + DBGLOG(REQ, ERROR, + "u4CmdLen:%u >= CMD_OID_BUF_LENGTH:%d\n", + u4CmdLen, CMD_OID_BUF_LENGTH); + return -EINVAL; + } + + if (copy_from_user(&aucOidBuf[0], + prIwReqData->data.pointer, + u4CmdLen)) { + DBGLOG(REQ, ERROR, "copy_from_user fail\n"); + return -EFAULT; + } + + aucOidBuf[u4CmdLen] = 0; + i4ResultLen = priv_driver_cmds(prNetDev, aucOidBuf, + u4CmdLen); + if (i4ResultLen > 1) { + if (copy_to_user(prIwReqData->data.pointer, + &aucOidBuf[0], i4ResultLen)) { + DBGLOG(REQ, ERROR, + "copy_to_user fail\n"); + return -EFAULT; + } + prIwReqData->data.length = i4ResultLen; + } else { + DBGLOG(REQ, ERROR, + "i4ResultLen:%d <= 1\n", i4ResultLen); + return -EFAULT; + } + + } + 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; + + kalMemZero(&aucOidBuf[0], sizeof(aucOidBuf)); + + ASSERT(prNetDev); + ASSERT(prIwReqData); + if (!prNetDev || !prIwReqData) { + DBGLOG(REQ, INFO, "priv_get_struct(): invalid param(0x%p, 0x%p)\n", prNetDev, prIwReqData); + return -EINVAL; + } + + u4SubCmd = (UINT_32) prIwReqData->data.flags; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, "priv_get_struct(): invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, *((P_GLUE_INFO_T *) netdev_priv(prNetDev))); + return -EINVAL; + } +#if 0 + DBGLOG(INIT, INFO, "priv_get_struct(): prIwReqInfo->cmd(0x%X), u4SubCmd(%ld)\n", + prIwReqInfo->cmd, u4SubCmd); +#endif + memset(aucOidBuf, 0, sizeof(aucOidBuf)); + + switch (u4SubCmd) { + case PRIV_CMD_OID: + if (copy_from_user(&aucOidBuf[0], prIwReqData->data.pointer, sizeof(NDIS_TRANSPORT_STRUCT))) { + DBGLOG(REQ, INFO, "priv_get_struct() copy_from_user oidBuf fail\n"); + return -EFAULT; + } + + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; +#if 0 + DBGLOG(INIT, INFO, "\n priv_get_struct cmd 0x%02x len:%d OID:0x%08x OID Len:%d\n", + cmd, pIwReq->u.data.length, ndisReq->ndisOidCmd, ndisReq->inNdisOidlength; +#endif + if (priv_get_ndis(prNetDev, prNdisReq, &u4BufLen) == 0) { + prNdisReq->outNdisOidLength = u4BufLen; + if (copy_to_user(prIwReqData->data.pointer, + &aucOidBuf[0], + u4BufLen + sizeof(NDIS_TRANSPORT_STRUCT) - + sizeof(prNdisReq->ndisOidContent))) { + DBGLOG(REQ, INFO, "priv_get_struct() copy_to_user oidBuf fail(1)\n"); + return -EFAULT; + } + } 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; + } + return 0; + + case PRIV_CMD_SW_CTRL: + pu4IntBuf = (PUINT_32) prIwReqData->data.pointer; + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + if (prIwReqData->data.length > sizeof(prNdisReq->ndisOidContent)) { + DBGLOG(REQ, INFO, "priv_get_struct() exceeds length limit\n"); + return -EFAULT; + } + + 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; + + if (!priv_get_ndis(prNetDev, prNdisReq, &u4BufLen)) { + prNdisReq->outNdisOidLength = u4BufLen; + if (copy_to_user(prIwReqData->data.pointer, + &prNdisReq->ndisOidContent[4], + 4 /* OFFSET_OF(NDIS_TRANSPORT_STRUCT, ndisOidContent) */)) { + DBGLOG(REQ, INFO, "priv_get_struct() copy_to_user oidBuf fail(2)\n"); + } + } + return 0; + default: + DBGLOG(REQ, WARN, "get struct cmd:0x%x\n", u4SubCmd); + break; + } + return -EOPNOTSUPP; +} /* priv_get_struct */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The routine handles a set operation for a single OID. +* +* \param[in] pDev Net device requested. +* \param[in] ndisReq Ndis request OID information copy from user. +* \param[out] outputLen_p If the call is successful, returns the number of +* bytes written into the query buffer. If the +* call failed due to invalid length of the query +* buffer, returns the amount of storage needed.. +* +* \retval 0 On success. +* \retval -EOPNOTSUPP If cmd is not supported. +* +*/ +/*----------------------------------------------------------------------------*/ +static int +priv_set_ndis(IN struct net_device *prNetDev, IN NDIS_TRANSPORT_STRUCT * prNdisReq, OUT PUINT_32 pu4OutputLen) +{ + P_WLAN_REQ_ENTRY prWlanReqEntry = NULL; + WLAN_STATUS status = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4SetInfoLen = 0; + + ASSERT(prNetDev); + ASSERT(prNdisReq); + ASSERT(pu4OutputLen); + + if (!prNetDev || !prNdisReq || !pu4OutputLen) { + DBGLOG(REQ, INFO, "priv_set_ndis(): invalid param(0x%p, 0x%p, 0x%p)\n", + prNetDev, prNdisReq, pu4OutputLen); + return -EINVAL; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, "priv_set_ndis(): invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, *((P_GLUE_INFO_T *) netdev_priv(prNetDev))); + return -EINVAL; + } +#if 0 + DBGLOG(INIT, INFO, "priv_set_ndis(): prNdisReq->ndisOidCmd(0x%lX)\n", prNdisReq->ndisOidCmd); +#endif + + if (reqSearchSupportedOidEntry(prNdisReq->ndisOidCmd, &prWlanReqEntry) == FALSE) { + /* WARNLOG(("Set OID: 0x%08lx (unknown)\n", prNdisReq->ndisOidCmd)); */ + return -EOPNOTSUPP; + } + + if (prWlanReqEntry->pfOidSetHandler == NULL) { + /* WARNLOG(("Set %s: Null set handler\n", prWlanReqEntry->pucOidName)); */ + return -EOPNOTSUPP; + } +#if 0 + DBGLOG(INIT, INFO, "priv_set_ndis(): %s\n", prWlanReqEntry->pucOidName); +#endif + + if (prWlanReqEntry->fgSetBufLenChecking) { + if (prNdisReq->inNdisOidlength != prWlanReqEntry->u4InfoBufLen) { + DBGLOG(REQ, WARN, "Set %s: Invalid length (current=%u, needed=%u)\n", + prWlanReqEntry->pucOidName, + prNdisReq->inNdisOidlength, prWlanReqEntry->u4InfoBufLen); + + *pu4OutputLen = prWlanReqEntry->u4InfoBufLen; + return -EINVAL; + } + } + + if (prWlanReqEntry->eOidMethod == ENUM_OID_GLUE_ONLY) { + /* GLUE sw info only */ + status = prWlanReqEntry->pfOidSetHandler(prGlueInfo, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, &u4SetInfoLen); + } else if (prWlanReqEntry->eOidMethod == ENUM_OID_GLUE_EXTENSION) { + /* multiple sw operations */ + status = prWlanReqEntry->pfOidSetHandler(prGlueInfo, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, &u4SetInfoLen); + } else if (prWlanReqEntry->eOidMethod == ENUM_OID_DRIVER_CORE) { + /* driver core */ + + status = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC) prWlanReqEntry->pfOidSetHandler, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, FALSE, FALSE, TRUE, &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 (status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return 0; +} /* priv_set_ndis */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The routine handles a query operation for a single OID. Basically we +* return information about the current state of the OID in question. +* +* \param[in] pDev Net device requested. +* \param[in] ndisReq Ndis request OID information copy from user. +* \param[out] outputLen_p If the call is successful, returns the number of +* bytes written into the query buffer. If the +* call failed due to invalid length of the query +* buffer, returns the amount of storage needed.. +* +* \retval 0 On success. +* \retval -EOPNOTSUPP If cmd is not supported. +* \retval -EINVAL invalid input parameters +* +*/ +/*----------------------------------------------------------------------------*/ +static int +priv_get_ndis(IN struct net_device *prNetDev, IN NDIS_TRANSPORT_STRUCT * prNdisReq, OUT PUINT_32 pu4OutputLen) +{ + P_WLAN_REQ_ENTRY prWlanReqEntry = NULL; + UINT_32 u4BufLen = 0; + WLAN_STATUS status = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prNetDev); + ASSERT(prNdisReq); + ASSERT(pu4OutputLen); + + if (!prNetDev || !prNdisReq || !pu4OutputLen) { + DBGLOG(REQ, INFO, "priv_get_ndis(): invalid param(0x%p, 0x%p, 0x%p)\n", + prNetDev, prNdisReq, pu4OutputLen); + return -EINVAL; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, "priv_get_ndis(): invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, *((P_GLUE_INFO_T *) netdev_priv(prNetDev))); + return -EINVAL; + } +#if 0 + DBGLOG(INIT, INFO, "priv_get_ndis(): prNdisReq->ndisOidCmd(0x%lX)\n", prNdisReq->ndisOidCmd); +#endif + + if (reqSearchSupportedOidEntry(prNdisReq->ndisOidCmd, &prWlanReqEntry) == FALSE) { + /* WARNLOG(("Query OID: 0x%08lx (unknown)\n", prNdisReq->ndisOidCmd)); */ + return -EOPNOTSUPP; + } + + if (prWlanReqEntry->pfOidQueryHandler == NULL) { + /* WARNLOG(("Query %s: Null query handler\n", prWlanReqEntry->pucOidName)); */ + return -EOPNOTSUPP; + } +#if 0 + DBGLOG(INIT, INFO, "priv_get_ndis(): %s\n", prWlanReqEntry->pucOidName); +#endif + + if (prWlanReqEntry->fgQryBufLenChecking) { + if (prNdisReq->inNdisOidlength < prWlanReqEntry->u4InfoBufLen) { + /* Not enough room in InformationBuffer. Punt */ + /* WARNLOG(("Query %s: Buffer too short (current=%ld, needed=%ld)\n", */ + /* prWlanReqEntry->pucOidName, */ + /* prNdisReq->inNdisOidlength, */ + /* prWlanReqEntry->u4InfoBufLen)); */ + + *pu4OutputLen = prWlanReqEntry->u4InfoBufLen; + + status = WLAN_STATUS_INVALID_LENGTH; + return -EINVAL; + } + } + + if (prWlanReqEntry->eOidMethod == ENUM_OID_GLUE_ONLY) { + /* GLUE sw info only */ + status = prWlanReqEntry->pfOidQueryHandler(prGlueInfo, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, &u4BufLen); + } else if (prWlanReqEntry->eOidMethod == ENUM_OID_GLUE_EXTENSION) { + /* multiple sw operations */ + status = prWlanReqEntry->pfOidQueryHandler(prGlueInfo, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, &u4BufLen); + } else if (prWlanReqEntry->eOidMethod == ENUM_OID_DRIVER_CORE) { + /* driver core */ + + status = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC) prWlanReqEntry->pfOidQueryHandler, + prNdisReq->ndisOidContent, prNdisReq->inNdisOidlength, TRUE, TRUE, TRUE, &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 (status != WLAN_STATUS_SUCCESS) + return -EOPNOTSUPP; + + return 0; +} /* priv_get_ndis */ + +#if CFG_SUPPORT_QA_TOOL +/*----------------------------------------------------------------------------*/ +/*! +* \brief The routine handles ATE set operation. +* +* \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 -EFAULT If copy from user space buffer fail. +* +*/ +/*----------------------------------------------------------------------------*/ +int +priv_ate_set(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) +{ + P_GLUE_INFO_T GlueInfo; + INT_32 i4Status; + UINT_8 *InBuf; + /* UINT_8 *addr_str, *value_str; */ + UINT_32 InBufLen; + UINT_32 u4SubCmd; + /* BOOLEAN isWrite = 0; + * UINT_32 u4BufLen = 0; + * P_NDIS_TRANSPORT_STRUCT prNdisReq; + * UINT_32 pu4IntBuf[2]; + */ + + /* sanity check */ + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + + /* init */ + DBGLOG(REQ, INFO, "priv_set_string (%s)(%d)\n", + (UINT_8 *) prIwReqData->data.pointer, (INT_32) prIwReqData->data.length); + + if (GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra) == FALSE) + return -EINVAL; + + GlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + u4SubCmd = (UINT_32) prIwReqData->data.flags; + + DBGLOG(REQ, INFO, " priv_ate_set u4SubCmd = %d\n", u4SubCmd); + + switch (u4SubCmd) { + case PRIV_QACMD_SET: + DBGLOG(REQ, INFO, " priv_ate_set PRIV_QACMD_SET\n"); + InBuf = aucOidBuf; + InBufLen = prIwReqData->data.length; + i4Status = 0; + + if (copy_from_user(InBuf, prIwReqData->data.pointer, prIwReqData->data.length)) + return -EFAULT; + i4Status = AteCmdSetHandle(prNetDev, InBuf, InBufLen); + break; + + default: + return -EOPNOTSUPP; + } + return 0; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ + UINT32 i = 0, j = 0, k = 0; + + 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 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Private ioctl driver 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_set_driver(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + UINT_32 u4SubCmd = 0; + UINT_16 u2Cmd = 0; + + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4BytesWritten = 0; + + ASSERT(prNetDev); + ASSERT(prIwReqData); + if (!prNetDev || !prIwReqData) { + DBGLOG(REQ, INFO, "priv_set_driver(): invalid param(0x%p, 0x%p)\n", prNetDev, prIwReqData); + return -EINVAL; + } + + u2Cmd = prIwReqInfo->cmd; + DBGLOG(REQ, INFO, "prIwReqInfo->cmd %u\n", u2Cmd); + + u4SubCmd = (UINT_32) prIwReqData->data.flags; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, "priv_set_driver(): invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, *((P_GLUE_INFO_T *) netdev_priv(prNetDev))); + return -EINVAL; + } + + /* trick,hack in ./net/wireless/wext-priv.c ioctl_private_iw_point */ + /* because the cmd number is odd (get), the input string will not be copy_to_user */ + + DBGLOG(REQ, INFO, "prIwReqData->data.length %u\n", prIwReqData->data.length); + + /* Use GET type becauase large data by iwpriv. */ + + ASSERT(IW_IS_GET(u2Cmd)); + if (prIwReqData->data.length != 0) { + if (!access_ok(VERIFY_READ, prIwReqData->data.pointer, prIwReqData->data.length)) { + DBGLOG(REQ, INFO, "%s access_ok Read fail written = %d\n", __func__, i4BytesWritten); + return -EFAULT; + } + if (copy_from_user(pcExtra, prIwReqData->data.pointer, prIwReqData->data.length)) { + DBGLOG(REQ, INFO, + "%s copy_form_user fail written = %d\n", __func__, prIwReqData->data.length); + return -EFAULT; + } + } + + if (pcExtra) { + pcExtra[1999] = '\0'; + DBGLOG(REQ, INFO, "pcExtra %s\n", pcExtra); + /* Please check max length in rIwPrivTable */ + DBGLOG(REQ, INFO, "%s prIwReqData->data.length = %d\n", __func__, prIwReqData->data.length); + i4BytesWritten = priv_driver_cmds(prNetDev, pcExtra, 2000 /*prIwReqData->data.length */); + DBGLOG(REQ, INFO, "%s i4BytesWritten = %d\n", __func__, i4BytesWritten); + } + + DBGLOG(REQ, INFO, "pcExtra done\n"); + + if (i4BytesWritten > 0) { + + if (i4BytesWritten > 2000) + i4BytesWritten = 2000; + prIwReqData->data.length = i4BytesWritten; /* the iwpriv will use the length */ + + } else if (i4BytesWritten == 0) { + prIwReqData->data.length = i4BytesWritten; + } +#if 0 + /* trick,hack in ./net/wireless/wext-priv.c ioctl_private_iw_point */ + /* because the cmd number is even (set), the return string will not be copy_to_user */ + ASSERT(IW_IS_SET(u2Cmd)); + if (!access_ok(VERIFY_WRITE, prIwReqData->data.pointer, i4BytesWritten)) { + DBGLOG(REQ, INFO, "%s access_ok Write fail written = %d\n", __func__, i4BytesWritten); + return -EFAULT; + } + if (copy_to_user(prIwReqData->data.pointer, pcExtra, i4BytesWritten)) { + DBGLOG(REQ, INFO, "%s copy_to_user fail written = %d\n", __func__, i4BytesWritten); + return -EFAULT; + } +#endif + + return 0; + +} /* priv_set_driver */ + +#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; +} + +#define CMD_START "START" +#define CMD_STOP "STOP" +#define CMD_SCAN_ACTIVE "SCAN-ACTIVE" +#define CMD_SCAN_PASSIVE "SCAN-PASSIVE" +#define CMD_RSSI "RSSI" +#define CMD_LINKSPEED "LINKSPEED" +#define CMD_RXFILTER_START "RXFILTER-START" +#define CMD_RXFILTER_STOP "RXFILTER-STOP" +#define CMD_RXFILTER_ADD "RXFILTER-ADD" +#define CMD_RXFILTER_REMOVE "RXFILTER-REMOVE" +#define CMD_BTCOEXSCAN_START "BTCOEXSCAN-START" +#define CMD_BTCOEXSCAN_STOP "BTCOEXSCAN-STOP" +#define CMD_BTCOEXMODE "BTCOEXMODE" +#define CMD_SETSUSPENDOPT "SETSUSPENDOPT" +#define CMD_SETSUSPENDMODE "SETSUSPENDMODE" +#define CMD_P2P_DEV_ADDR "P2P_DEV_ADDR" +#define CMD_SETFWPATH "SETFWPATH" +#define CMD_SETBAND "SETBAND" +#define CMD_GETBAND "GETBAND" +#define CMD_SET_TXPOWER "SET_TXPOWER" +#define CMD_COUNTRY "COUNTRY" +#define CMD_P2P_SET_NOA "P2P_SET_NOA" +#define CMD_P2P_GET_NOA "P2P_GET_NOA" +#define CMD_P2P_SET_PS "P2P_SET_PS" +#define CMD_SET_AP_WPS_P2P_IE "SET_AP_WPS_P2P_IE" +#define CMD_SETROAMMODE "SETROAMMODE" +#define CMD_MIRACAST "MIRACAST" + +#define CMD_PNOSSIDCLR_SET "PNOSSIDCLR" +#define CMD_PNOSETUP_SET "PNOSETUP " +#define CMD_PNOENABLE_SET "PNOFORCE" +#define CMD_PNODEBUG_SET "PNODEBUG" +#define CMD_WLS_BATCHING "WLS_BATCHING" + +#define CMD_OKC_SET_PMK "SET_PMK" +#define CMD_OKC_ENABLE "OKC_ENABLE" + +#define CMD_SETMONITOR "MONITOR" +#define CMD_SETBUFMODE "BUFFER_MODE" + +#if CFG_SUPPORT_QA_TOOL +#define CMD_GET_RX_STATISTICS "GET_RX_STATISTICS" +#endif + +/* miracast related definition */ +#define MIRACAST_MODE_OFF 0 +#define MIRACAST_MODE_SOURCE 1 +#define MIRACAST_MODE_SINK 2 + +#ifndef MIRACAST_AMPDU_SIZE +#define MIRACAST_AMPDU_SIZE 8 +#endif + +#ifndef MIRACAST_MCHAN_ALGO +#define MIRACAST_MCHAN_ALGO 1 +#endif + +#ifndef MIRACAST_MCHAN_BW +#define MIRACAST_MCHAN_BW 25 +#endif + +#define CMD_BAND_AUTO 0 +#define CMD_BAND_5G 1 +#define CMD_BAND_2G 2 +#define CMD_BAND_ALL 3 + +/* Mediatek private command */ + +#define CMD_SET_SW_CTRL "SET_SW_CTRL" +#define CMD_GET_SW_CTRL "GET_SW_CTRL" +#define CMD_SET_CFG "SET_CFG" +#define CMD_GET_CFG "GET_CFG" +#define CMD_SET_CHIP "SET_CHIP" +#define CMD_GET_CHIP "GET_CHIP" +#define CMD_SET_DBG_LEVEL "SET_DBG_LEVEL" +#define CMD_GET_DBG_LEVEL "GET_DBG_LEVEL" +#define CMD_ADD_TS "addts" +#define CMD_DEL_TS "delts" +#define CMD_DUMP_TS "dumpts" +#define CMD_RM_IT "RM-IT" +#define CMD_DUMP_UAPSD "dumpuapsd" +#define CMD_FW_EVENT "FW-EVENT " +#define CMD_O_SAR "O-SAR-ENABLE" +#define CMD_FW_PARAM "set_fw_param " +#define CMD_RSSI_DISCONNECT "DISCONRSSI" +#define PRIV_CMD_SIZE 512 + +static UINT_8 g_ucMiracastMode = MIRACAST_MODE_OFF; + +typedef struct cmd_tlv { + char prefix; + char version; + char subver; + char reserved; +} cmd_tlv_t; + +typedef struct priv_driver_cmd_s { + char buf[PRIV_CMD_SIZE]; + int used_len; + int total_len; +} priv_driver_cmd_t; + + +static int priv_driver_get_sw_ctrl(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + INT_32 u4Ret = 0; + + PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo = { 0, 0 }; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= 2) { + /* rSwCtrlInfo.u4Id = kalStrtoul(apcArgv[1], NULL, 0); */ + rSwCtrlInfo.u4Data = 0; + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rSwCtrlInfo.u4Id)); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + + DBGLOG(REQ, LOUD, "id is %x\n", rSwCtrlInfo.u4Id); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "0x%08x", (unsigned int)rSwCtrlInfo.u4Data); + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + + if (i4BytesWritten < 0) + return -1; + } + + return i4BytesWritten; + +} /* priv_driver_get_sw_ctrl */ + +int priv_driver_set_sw_ctrl(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + INT_32 u4Ret = 0; + + PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= 3) { + /* + * rSwCtrlInfo.u4Id = kalStrtoul(apcArgv[1], NULL, 0); + * rSwCtrlInfo.u4Data = kalStrtoul(apcArgv[2], NULL, 0); + */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rSwCtrlInfo.u4Id)); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + u4Ret = kalkStrtou32(apcArgv[2], 0, &(rSwCtrlInfo.u4Data)); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + } + + return i4BytesWritten; + +} /* priv_driver_set_sw_ctrl */ + +#if CFG_SUPPORT_QA_TOOL +#if CFG_SUPPORT_BUFFER_MODE +static int priv_driver_set_efuse_buffer_mode(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4Argc = 0; + INT_32 i4BytesWritten = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + PARAM_CUSTOM_EFUSE_BUFFER_MODE_T rSetEfuseBufModeInfo; +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 0) + int i = 0; +#endif + PUINT_8 pucConfigBuf; + UINT_32 u4ConfigReadLen; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + pucConfigBuf = (PUINT_8) kalMemAlloc(2048, VIR_MEM_TYPE); + if (!pucConfigBuf) { + DBGLOG(INIT, INFO, "allocate pucConfigBuf failed\n"); + return -ENOMEM; + } + kalMemZero(pucConfigBuf, 2048); + u4ConfigReadLen = 0; + + if (pucConfigBuf) { + if (kalReadToFile("/MT6632_eFuse_usage_table.xlsm.bin", pucConfigBuf, 2048, &u4ConfigReadLen) == 0) { + /* ToDo:: Nothing */ + } else { + DBGLOG(INIT, INFO, "can't find file\n"); + return -1; + } + + kalMemFree(pucConfigBuf, VIR_MEM_TYPE, 2048); + } + /* pucConfigBuf */ + kalMemZero(&rSetEfuseBufModeInfo, sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T)); + + rSetEfuseBufModeInfo.ucSourceMode = 1; + rSetEfuseBufModeInfo.ucCount = (UINT_8)EFUSE_CONTENT_SIZE; + +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 0) + for (i = 0; i < EFUSE_CONTENT_SIZE; i++) { + rSetEfuseBufModeInfo.aBinContent[i].u2Addr = i; + rSetEfuseBufModeInfo.aBinContent[i].ucValue = *(pucConfigBuf + i); + } + + for (i = 0; i < 20; i++) + DBGLOG(INIT, INFO, "%x\n", rSetEfuseBufModeInfo.aBinContent[i].ucValue); +#endif + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEfusBufferMode, + &rSetEfuseBufModeInfo, sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T), FALSE, FALSE, TRUE, + &u4BufLen); + + i4BytesWritten = + snprintf(pcCommand, i4TotalLen, "set buffer mode %s", + (rStatus == WLAN_STATUS_SUCCESS) ? "success" : "fail"); + + if (i4BytesWritten < 0) + return -1; + + return i4BytesWritten; +} +#endif /* CFG_SUPPORT_BUFFER_MODE */ + +static int priv_driver_get_rx_statistics(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + INT_32 u4Ret = 0; + PARAM_CUSTOM_ACCESS_RX_STAT rRxStatisticsTest; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + DBGLOG(INIT, ERROR, " priv_driver_get_rx_statistics\n"); + + if (i4Argc >= 2) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rRxStatisticsTest.u4SeqNum)); + rRxStatisticsTest.u4TotalNum = sizeof(PARAM_RX_STAT_T) / 4; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryRxStatistics, + &rRxStatisticsTest, sizeof(rRxStatisticsTest), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } + + return i4BytesWritten; +} +#endif /* CFG_SUPPORT_QA_TOOL */ + +int priv_driver_set_cfg(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + + PARAM_CUSTOM_KEY_CFG_STRUCT_T rKeyCfgInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + kalMemZero(&rKeyCfgInfo, sizeof(rKeyCfgInfo)); + + if (i4Argc >= 3) { + /* wlanCfgSet(prAdapter, apcArgv[1], apcArgv[2], 0); */ + /* Call by wlanoid because the set_cfg will trigger callback */ + kalStrnCpy(rKeyCfgInfo.aucKey, apcArgv[1], WLAN_CFG_KEY_LEN_MAX - 1); + kalStrnCpy(rKeyCfgInfo.aucValue, apcArgv[2], WLAN_CFG_VALUE_LEN_MAX - 1); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetKeyCfg, &rKeyCfgInfo, sizeof(rKeyCfgInfo), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } + + return i4BytesWritten; + +} /* priv_driver_set_cfg */ + +int priv_driver_get_cfg(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + CHAR aucValue[WLAN_CFG_VALUE_LEN_MAX]; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + prAdapter = prGlueInfo->prAdapter; + + if (i4Argc >= 2) { + /* by wlanoid ? */ + if (wlanCfgGet(prAdapter, apcArgv[1], aucValue, "", 0) == WLAN_STATUS_SUCCESS) { + kalStrnCpy(pcCommand, aucValue, WLAN_CFG_VALUE_LEN_MAX); + i4BytesWritten = kalStrnLen(pcCommand, WLAN_CFG_VALUE_LEN_MAX); + } + } + + return i4BytesWritten; + +} /* priv_driver_get_cfg */ + +int priv_driver_set_chip_config(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + UINT_32 u4CmdLen = 0; + UINT_32 u4PrefixLen = 0; + /* INT_32 i4Argc = 0; */ + /* PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = {0}; */ + + PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T rChipConfigInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + /* wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); */ + /* DBGLOG(REQ, LOUD,("argc is %i\n",i4Argc)); */ + u4CmdLen = kalStrnLen(pcCommand, i4TotalLen); + u4PrefixLen = kalStrLen(CMD_SET_CHIP) + 1 /*space */; + + kalMemZero(&rChipConfigInfo, sizeof(rChipConfigInfo)); + + /* if(i4Argc >= 2) { */ + if (u4CmdLen > u4PrefixLen) { + + rChipConfigInfo.ucType = CHIP_CONFIG_TYPE_WO_RESPONSE; + /* rChipConfigInfo.u2MsgSize = kalStrnLen(apcArgv[1],CHIP_CONFIG_RESP_SIZE); */ + rChipConfigInfo.u2MsgSize = u4CmdLen - u4PrefixLen; + /* kalStrnCpy(rChipConfigInfo.aucCmd,apcArgv[1],CHIP_CONFIG_RESP_SIZE); */ + kalStrnCpy(rChipConfigInfo.aucCmd, pcCommand + u4PrefixLen, CHIP_CONFIG_RESP_SIZE - 1); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetChipConfig, + &rChipConfigInfo, sizeof(rChipConfigInfo), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, INFO, "%s: kalIoctl ret=%d\n", __func__, rStatus); + i4BytesWritten = -1; + } + } + + return i4BytesWritten; + +} /* priv_driver_set_chip_config */ + +int priv_driver_get_chip_config(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4BytesWritten = 0; + UINT_32 u4BufLen = 0; + UINT_32 u2MsgSize = 0; + UINT_32 u4CmdLen = 0; + UINT_32 u4PrefixLen = 0; + /* INT_32 i4Argc = 0; */ + /* PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; */ + + PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T rChipConfigInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + /* wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); */ + /* DBGLOG(REQ, LOUD,("argc is %i\n",i4Argc)); */ + + u4CmdLen = kalStrnLen(pcCommand, i4TotalLen); + u4PrefixLen = kalStrLen(CMD_GET_CHIP) + 1 /*space */; + + /* if(i4Argc >= 2) { */ + if (u4CmdLen > u4PrefixLen) { + rChipConfigInfo.ucRespType = CHIP_CONFIG_TYPE_WO_RESPONSE; + rChipConfigInfo.ucType = CHIP_CONFIG_TYPE_ASCII; + /* rChipConfigInfo.u2MsgSize = kalStrnLen(apcArgv[1],CHIP_CONFIG_RESP_SIZE); */ + rChipConfigInfo.u2MsgSize = u4CmdLen - u4PrefixLen; + /* kalStrnCpy(rChipConfigInfo.aucCmd,apcArgv[1],CHIP_CONFIG_RESP_SIZE); */ + kalStrnCpy(rChipConfigInfo.aucCmd, pcCommand + u4PrefixLen, CHIP_CONFIG_RESP_SIZE - 1); + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryChipConfig, + &rChipConfigInfo, sizeof(rChipConfigInfo), TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, INFO, "%s: kalIoctl ret=%d\n", __func__, rStatus); + return -1; + } + + /* Check respType */ + u2MsgSize = rChipConfigInfo.u2MsgSize; + DBGLOG(REQ, INFO, "%s: RespTyep %u\n", __func__, rChipConfigInfo.ucRespType); + DBGLOG(REQ, INFO, "%s: u2MsgSize %u\n", __func__, rChipConfigInfo.u2MsgSize); + + if (u2MsgSize > sizeof(rChipConfigInfo.aucCmd)) { + DBGLOG(REQ, INFO, "%s: u2MsgSize error ret=%u\n", __func__, rChipConfigInfo.u2MsgSize); + return -1; + } + + if (u2MsgSize > 0) { + + if (rChipConfigInfo.ucRespType == CHIP_CONFIG_TYPE_ASCII) { + i4BytesWritten = + snprintf(pcCommand + i4BytesWritten, i4TotalLen, "%s", rChipConfigInfo.aucCmd); + } else { + UINT_32 u4Length; + UINT_32 u4Line; + + if (rChipConfigInfo.ucRespType == CHIP_CONFIG_TYPE_MEM8) { + PUINT_8 pucStartAddr = NULL; + + pucStartAddr = (PUINT_8) rChipConfigInfo.aucCmd; + /* align 16 bytes because one print line is 16 bytes */ + u4Length = (((u2MsgSize + 15) >> 4)) << 4; + u4Line = 0; + priv_driver_get_chip_config_16(pucStartAddr, u4Length, u4Line, i4TotalLen, + i4BytesWritten, pcCommand); + } else { + PUINT_32 pu4StartAddr = NULL; + + pu4StartAddr = (PUINT_32) rChipConfigInfo.aucCmd; + /* align 16 bytes because one print line is 16 bytes */ + u4Length = (((u2MsgSize + 15) >> 4)) << 4; + u4Line = 0; + + if (IS_ALIGN_4((ULONG) pu4StartAddr)) { + priv_driver_get_chip_config_4(pu4StartAddr, u4Length, u4Line, + i4TotalLen, i4BytesWritten, pcCommand); + } else { + DBGLOG(REQ, INFO, + "%s: rChipConfigInfo.aucCmd is not 4 bytes alignment %p\n", + __func__, rChipConfigInfo.aucCmd); + } + } /* ChipConfigInfo.ucRespType */ + } + } + /* u2MsgSize > 0 */ + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + } + /* i4Argc */ + return i4BytesWritten; + +} /* priv_driver_get_chip_config */ + +static void +priv_driver_get_chip_config_16(PUINT_8 pucStartAddr, UINT_32 u4Length, UINT_32 u4Line, int i4TotalLen, + INT_32 i4BytesWritten, char *pcCommand) +{ + + while (u4Length >= 16) { + if (i4TotalLen > i4BytesWritten) { + i4BytesWritten += + snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%04x %02x %02x %02x %02x %02x %02x %02x %02x-%02x %02x %02x %02x %02x %02x %02x %02x\n", + u4Line, 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]); + } + + pucStartAddr += 16; + u4Length -= 16; + u4Line += 16; + } /* u4Length */ +} + +static void +priv_driver_get_chip_config_4(PUINT_32 pu4StartAddr, UINT_32 u4Length, UINT_32 u4Line, int i4TotalLen, + INT_32 i4BytesWritten, char *pcCommand) +{ + while (u4Length >= 16) { + if (i4TotalLen > i4BytesWritten) { + i4BytesWritten += + snprintf(pcCommand + + i4BytesWritten, + i4TotalLen - + i4BytesWritten, + "%04x %08x %08x %08x %08x\n", + u4Line, pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2], pu4StartAddr[3]); + } + + pu4StartAddr += 4; + u4Length -= 16; + u4Line += 4; + } /* u4Length */ +} + +int priv_driver_get_linkspeed(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + UINT_32 u4Rate = 0; + UINT_32 u4LinkSpeed = 0; + INT_32 i4BytesWritten = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (!netif_carrier_ok(prNetDev)) + return -1; + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryLinkSpeed, &u4Rate, sizeof(u4Rate), TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + u4LinkSpeed = u4Rate * 100; + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "LinkSpeed %u", (unsigned int)u4LinkSpeed); + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + + if (i4BytesWritten < 0) + return -1; + + return i4BytesWritten; + +} /* priv_driver_get_linkspeed */ + +int priv_driver_set_band(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Argc = 0; + UINT_32 ucBand = 0; + UINT_8 ucBssIndex; + ENUM_BAND_T eBand = BAND_NULL; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + INT_32 u4Ret = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + prAdapter = prGlueInfo->prAdapter; + if (i4Argc >= 2) { + /* ucBand = kalStrtoul(apcArgv[1], NULL, 0); */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &ucBand); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse ucBand error u4Ret=%d\n", u4Ret); + + ucBssIndex = wlanGetAisBssIndex(prGlueInfo->prAdapter); + if (ucBssIndex >= BSS_INFO_NUM) + return -1; + eBand = BAND_NULL; + if (ucBand == CMD_BAND_5G) + eBand = BAND_5G; + else if (ucBand == CMD_BAND_2G) + eBand = BAND_2G4; + prAdapter->aePreferBand[ucBssIndex] = eBand; + /* XXX call wlanSetPreferBandByNetwork directly in different thread */ + /* wlanSetPreferBandByNetwork (prAdapter, eBand, ucBssIndex); */ + } + + return 0; +} + +int priv_driver_set_txpower(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + P_SET_TXPWR_CTRL_T prTxpwr; + UINT_16 i; + INT_32 u4Ret = 0; + INT_32 ai4Setting[4] = {0}; + UINT_8 idx = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + prTxpwr = &prGlueInfo->rTxPwr; + + if (i4Argc >= 3 && i4Argc <= 5) { + for (i = 0; i < (i4Argc - 1); i++) { + /* ai4Setting[i] = kalStrtol(apcArgv[i + 1], NULL, 0); */ + u4Ret = kalkStrtos32(apcArgv[i + 1], 0, &(ai4Setting[i])); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", u4Ret); + } + } else { + DBGLOG(REQ, INFO, "set_txpower wrong argc : %d\n", i4Argc); + return -1; + } + + /* + * ai4Setting[0] + * 0 : Set TX power offset for specific network + * 1 : Set TX power offset policy when multiple networks are in the same channel + * 2 : Set TX power limit for specific channel in 2.4GHz band + * 3 : Set TX power limit of specific sub-band in 5GHz band + * 4 : Enable or reset setting + */ + if (ai4Setting[0] == 0 && (i4Argc - 1) == 4 /* argc num */) { + /* ai4Setting[1] : 0 (All networks), 1 (legacy STA), 2 (Hotspot AP), 3 (P2P), 4 (BT over Wi-Fi) */ + /* ai4Setting[2] : 0 (All bands),1 (2.4G), 2 (5G) */ + /* ai4Setting[3] : -30 ~ 20 in unit of 0.5dBm (default: 0) */ + if (ai4Setting[1] == 1 || ai4Setting[1] == 0) { + if (ai4Setting[2] == 0 || ai4Setting[2] == 1) + prTxpwr->c2GLegacyStaPwrOffset = ai4Setting[3]; + if (ai4Setting[2] == 0 || ai4Setting[2] == 2) + prTxpwr->c5GLegacyStaPwrOffset = ai4Setting[3]; + } + if (ai4Setting[1] == 2 || ai4Setting[1] == 0) { + if (ai4Setting[2] == 0 || ai4Setting[2] == 1) + prTxpwr->c2GHotspotPwrOffset = ai4Setting[3]; + if (ai4Setting[2] == 0 || ai4Setting[2] == 2) + prTxpwr->c5GHotspotPwrOffset = ai4Setting[3]; + } + if (ai4Setting[1] == 3 || ai4Setting[1] == 0) { + if (ai4Setting[2] == 0 || ai4Setting[2] == 1) + prTxpwr->c2GP2pPwrOffset = ai4Setting[3]; + if (ai4Setting[2] == 0 || ai4Setting[2] == 2) + prTxpwr->c5GP2pPwrOffset = ai4Setting[3]; + } + if (ai4Setting[1] == 4 || ai4Setting[1] == 0) { + if (ai4Setting[2] == 0 || ai4Setting[2] == 1) + prTxpwr->c2GBowPwrOffset = ai4Setting[3]; + if (ai4Setting[2] == 0 || ai4Setting[2] == 2) + prTxpwr->c5GBowPwrOffset = ai4Setting[3]; + } + } else if (ai4Setting[0] == 1 && (i4Argc - 1) == 2) { + /* ai4Setting[1] : 0 (highest power is used) (default), 1 (lowest power is used) */ + prTxpwr->ucConcurrencePolicy = ai4Setting[1]; + } else if (ai4Setting[0] == 2 && (i4Argc - 1) == 3) { + /* ai4Setting[1] : 0 (all channels in 2.4G), 1~14 */ + /* ai4Setting[2] : 10 ~ 46 in unit of 0.5dBm (default: 46) */ + if (ai4Setting[1] == 0) { + for (i = 0; i < 14; i++) + prTxpwr->acTxPwrLimit2G[i] = ai4Setting[2]; + } else if ((ai4Setting[1] <= 14) && (ai4Setting[1] >= 1)) { + idx = ai4Setting[1] - 1; + prTxpwr->acTxPwrLimit2G[idx] = ai4Setting[2]; + } + } else if (ai4Setting[0] == 3 && (i4Argc - 1) == 3) { + /* + * ai4Setting[1] : 0 (all sub-bands in 5G), + * 1 (5000 ~ 5250MHz), + * 2 (5255 ~ 5350MHz), + * 3 (5355 ~ 5725MHz), + * 4 (5730 ~ 5825MHz) + */ + /* ai4Setting[2] : 10 ~ 46 in unit of 0.5dBm (default: 46) */ + if (ai4Setting[1] == 0) { + for (i = 0; i < 4; i++) + prTxpwr->acTxPwrLimit5G[i] = ai4Setting[2]; + } else if ((ai4Setting[1] <= 4) && (ai4Setting[1] >= 1)) { + idx = ai4Setting[1] - 1; + prTxpwr->acTxPwrLimit5G[idx] = ai4Setting[2]; + } + } else if (ai4Setting[0] == 4 && (i4Argc - 1) == 2) { + /* ai4Setting[1] : 1 (enable), 0 (reset and disable) */ + if (ai4Setting[1] == 0) + wlanDefTxPowerCfg(prGlueInfo->prAdapter); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetTxPower, prTxpwr, sizeof(SET_TXPWR_CTRL_T), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } else + return -EFAULT; + + return 0; +} + +int priv_driver_set_country(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + UINT_8 aucCountry[2]; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= 2) { + /* command like "COUNTRY US", "COUNTRY EU" and "COUNTRY JP" */ + aucCountry[0] = apcArgv[1][0]; + aucCountry[1] = apcArgv[1][1]; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetCountryCode, &aucCountry[0], 2, FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } + return 0; +} + +int priv_driver_set_miracast(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 i4BytesWritten = 0; + /* WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; */ + /* UINT_32 u4BufLen = 0; */ + INT_32 i4Argc = 0; + UINT_32 ucMode = 0; + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T prMsgWfdCfgUpdate = (P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T) NULL; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + INT_32 u4Ret = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + prAdapter = prGlueInfo->prAdapter; + if (i4Argc >= 2) { + /* ucMode = kalStrtoul(apcArgv[1], NULL, 0); */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &ucMode); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse ucMode error u4Ret=%d\n", u4Ret); + + if (g_ucMiracastMode == (UINT_8)ucMode) { + /* XXX: continue or skip */ + /* XXX: continue or skip */ + } + + g_ucMiracastMode = (UINT_8)ucMode; + prMsgWfdCfgUpdate = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_WFD_CONFIG_SETTINGS_CHANGED_T)); + + if (prMsgWfdCfgUpdate != NULL) { + + prWfdCfgSettings = &(prAdapter->rWifiVar.rWfdConfigureSettings); + prMsgWfdCfgUpdate->rMsgHdr.eMsgId = MID_MNY_P2P_WFD_CFG_UPDATE; + prMsgWfdCfgUpdate->prWfdCfgSettings = prWfdCfgSettings; + + if (ucMode == MIRACAST_MODE_OFF) { + prWfdCfgSettings->ucWfdEnable = 0; + if (snprintf(pcCommand, i4TotalLen, CMD_SET_CHIP " mira 0") < 0) + return -1; + } else if (ucMode == MIRACAST_MODE_SOURCE) { + prWfdCfgSettings->ucWfdEnable = 1; + if (snprintf(pcCommand, i4TotalLen, CMD_SET_CHIP " mira 1") < 0) + return -1; + } else if (ucMode == MIRACAST_MODE_SINK) { + prWfdCfgSettings->ucWfdEnable = 2; + if (snprintf(pcCommand, i4TotalLen, CMD_SET_CHIP " mira 2") < 0) + return -1; + } else { + prWfdCfgSettings->ucWfdEnable = 0; + if (snprintf(pcCommand, i4TotalLen, CMD_SET_CHIP " mira 0") < 0) + return -1; + } + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgWfdCfgUpdate, MSG_SEND_METHOD_BUF); + + priv_driver_set_chip_config(prNetDev, pcCommand, i4TotalLen); + } /* prMsgWfdCfgUpdate */ + else { + ASSERT(FALSE); + i4BytesWritten = -1; + } + } + + /* i4Argc */ + return i4BytesWritten; +} + +int priv_driver_set_suspend_mode(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + BOOLEAN fgEnable; + UINT_32 u4Enable = 0; + INT_32 u4Ret = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= 2) { + /* fgEnable = (kalStrtoul(apcArgv[1], NULL, 0) == 1) ? TRUE : FALSE; */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Enable); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse u4Enable error u4Ret=%d\n", u4Ret); + if (u4Enable == 1) + fgEnable = TRUE; + else + fgEnable = FALSE; + + DBGLOG(REQ, INFO, "%s: Set suspend mode [%u]\n", __func__, fgEnable); + + if (prGlueInfo->fgIsInSuspendMode == fgEnable) { + DBGLOG(REQ, INFO, "%s: Already in suspend mode, SKIP!\n", __func__); + return 0; + } + + prGlueInfo->fgIsInSuspendMode = fgEnable; + + wlanSetSuspendMode(prGlueInfo, fgEnable); + p2pSetSuspendMode(prGlueInfo, fgEnable); + } + + return 0; +} + +static int priv_driver_get_wifi_type(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct PARAM_GET_WIFI_TYPE rParamGetWifiType; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 rStatus; + UINT_32 u4BytesWritten = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) { + DBGLOG(REQ, ERROR, "GLUE_CHK_PR2 fail\n"); + return -1; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rParamGetWifiType.prNetDev = prNetDev; + + rStatus = kalIoctl(prGlueInfo, + wlanoidGetWifiType, + (void *)&rParamGetWifiType, + sizeof(void *), + FALSE, + FALSE, + FALSE, + &u4BytesWritten); + + if (rStatus == WLAN_STATUS_SUCCESS) { + if (u4BytesWritten > 0) { + if (u4BytesWritten > i4TotalLen) + u4BytesWritten = i4TotalLen; + kalMemCopy(pcCommand, rParamGetWifiType.arWifiTypeName, + u4BytesWritten); + } + } else { + DBGLOG(REQ, ERROR, "rStatus=%x\n", rStatus); + u4BytesWritten = 0; + } + + return (int)u4BytesWritten; +} + +#if CFG_SUPPORT_SNIFFER +int priv_driver_set_monitor(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4Argc = 0; + INT_32 i4BytesWritten = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + PARAM_CUSTOM_MONITOR_SET_STRUCT_T rMonitorSetInfo; + UINT_8 ucEnable = 0; + UINT_8 ucPriChannel = 0; + UINT_8 ucChannelWidth = 0; + UINT_8 ucExt = 0; + UINT_8 ucSco = 0; + UINT_8 ucChannelS1 = 0; + UINT_8 ucChannelS2 = 0; + BOOLEAN fgIsLegalChannel = FALSE; + BOOLEAN fgError = FALSE; + BOOLEAN fgEnable = FALSE; + ENUM_BAND_T eBand = BAND_NULL; + UINT_32 u4Parse = 0; + INT_32 u4Ret = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc >= 5) { + /* + * ucEnable = (UINT_8) (kalStrtoul(apcArgv[1], NULL, 0)); + * ucPriChannel = (UINT_8) (kalStrtoul(apcArgv[2], NULL, 0)); + * ucChannelWidth = (UINT_8) (kalStrtoul(apcArgv[3], NULL, 0)); + * ucExt = (UINT_8) (kalStrtoul(apcArgv[4], NULL, 0)); + */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", u4Ret); + ucEnable = (UINT_8)u4Parse; + u4Ret = kalkStrtou32(apcArgv[2], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", u4Ret); + ucPriChannel = (UINT_8)u4Parse; + u4Ret = kalkStrtou32(apcArgv[3], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", u4Ret); + ucChannelWidth = (UINT_8)u4Parse; + u4Ret = kalkStrtou32(apcArgv[4], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", u4Ret); + ucExt = (UINT_8)u4Parse; + + eBand = (ucPriChannel <= 14) ? BAND_2G4 : BAND_5G; + fgIsLegalChannel = rlmDomainIsLegalChannel(prAdapter, eBand, ucPriChannel); + + if (fgIsLegalChannel == FALSE) { + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "Illegal primary channel %d", ucPriChannel); + if (i4BytesWritten < 0) + return -1; + return i4BytesWritten; + } + + switch (ucChannelWidth) { + case 160: + ucChannelWidth = (UINT_8) CW_160MHZ; + ucSco = (UINT_8) CHNL_EXT_SCN; + + if (ucPriChannel >= 36 && ucPriChannel <= 64) + ucChannelS2 = 50; + else if (ucPriChannel >= 100 && ucPriChannel <= 128) + ucChannelS2 = 114; + else + fgError = TRUE; + break; + + case 80: + ucChannelWidth = (UINT_8) CW_80MHZ; + ucSco = (UINT_8) CHNL_EXT_SCN; + + if (ucPriChannel >= 36 && ucPriChannel <= 48) + ucChannelS1 = 42; + else if (ucPriChannel >= 52 && ucPriChannel <= 64) + ucChannelS1 = 58; + else if (ucPriChannel >= 100 && ucPriChannel <= 112) + ucChannelS1 = 106; + else if (ucPriChannel >= 116 && ucPriChannel <= 128) + ucChannelS1 = 122; + else if (ucPriChannel >= 132 && ucPriChannel <= 144) + ucChannelS1 = 138; + else if (ucPriChannel >= 149 && ucPriChannel <= 161) + ucChannelS1 = 155; + else + fgError = TRUE; + break; + + case 40: + ucChannelWidth = (UINT_8) CW_20_40MHZ; + ucSco = (ucExt) ? (UINT_8) CHNL_EXT_SCA : (UINT_8) CHNL_EXT_SCB; + break; + + case 20: + ucChannelWidth = (UINT_8) CW_20_40MHZ; + ucSco = (UINT_8) CHNL_EXT_SCN; + break; + + default: + fgError = TRUE; + break; + } + + if (fgError) { + i4BytesWritten = + snprintf(pcCommand, i4TotalLen, "Invalid primary channel %d with bandwidth %d", + ucPriChannel, ucChannelWidth); + + if (i4BytesWritten < 0) + return -1; + + return i4BytesWritten; + } + + fgEnable = (ucEnable) ? TRUE : FALSE; + + if (prGlueInfo->fgIsEnableMon != fgEnable) { + prGlueInfo->fgIsEnableMon = fgEnable; + schedule_work(&prGlueInfo->monWork); + } + + kalMemZero(&rMonitorSetInfo, sizeof(rMonitorSetInfo)); + + rMonitorSetInfo.ucEnable = ucEnable; + rMonitorSetInfo.ucPriChannel = ucPriChannel; + rMonitorSetInfo.ucSco = ucSco; + rMonitorSetInfo.ucChannelWidth = ucChannelWidth; + rMonitorSetInfo.ucChannelS1 = ucChannelS1; + rMonitorSetInfo.ucChannelS2 = ucChannelS2; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetMonitor, + &rMonitorSetInfo, sizeof(rMonitorSetInfo), FALSE, FALSE, TRUE, &u4BufLen); + + i4BytesWritten = + snprintf(pcCommand, i4TotalLen, "set monitor config %s", + (rStatus == WLAN_STATUS_SUCCESS) ? "success" : "fail"); + + if (i4BytesWritten < 0) + return -1; + + return i4BytesWritten; + } + + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "monitor [Enable][PriChannel][ChannelWidth][Sco]"); + if (i4BytesWritten < 0) + return -1; + + return i4BytesWritten; +} +#endif + +#if CFG_SUPPORT_RSSI_DISCONNECT +int priv_driver_get_rssiDisconnect(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + PARAM_RSSI i4Rssi = 0; + INT_32 i4BytesWritten = 0; + + if (!prNetDev) + return -EPERM; + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -EPERM; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryRssiDisconnect, &i4Rssi, + sizeof(i4Rssi), TRUE, TRUE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + return -EPERM; + + DBGLOG(REQ, INFO, "i4Rssi = %d\n", i4Rssi); + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "DISCONRSSI %d", i4Rssi); + if (i4BytesWritten < 0) + return -EPERM; + + DBGLOG(REQ, INFO, "%s: Command result is %s\n", __func__, pcCommand); + return i4BytesWritten; +} +#endif + +#if CFG_SUPPORT_BATCH_SCAN +#define CMD_BATCH_SET "WLS_BATCHING SET" +#define CMD_BATCH_GET "WLS_BATCHING GET" +#define CMD_BATCH_STOP "WLS_BATCHING STOP" +#endif + +typedef int(*PRIV_CMD_FUNCTION) ( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen); + +struct PRIV_CMD_HANDLER { + UINT_8 *pcCmdStr; + PRIV_CMD_FUNCTION pfHandler; +}; + +struct PRIV_CMD_HANDLER priv_cmd_handlers[] = { + {CMD_GET_WIFI_TYPE, priv_driver_get_wifi_type}, +}; + +INT_32 priv_driver_cmds(IN struct net_device *prNetDev, IN PCHAR pcCommand, IN INT_32 i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4BytesWritten = 0; + INT_32 i4CmdFound = 0; + int i; + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + for (i = 0; i < sizeof(priv_cmd_handlers) / sizeof(struct + PRIV_CMD_HANDLER); i++) { + if (strnicmp(pcCommand, + priv_cmd_handlers[i].pcCmdStr, + strlen(priv_cmd_handlers[i].pcCmdStr)) == 0) { + + if (priv_cmd_handlers[i].pfHandler != NULL) { + i4BytesWritten = + priv_cmd_handlers[i].pfHandler( + prNetDev, + pcCommand, + i4TotalLen); + } + i4CmdFound = 1; + } + } + + if (i4CmdFound == 0) { + i4CmdFound = 1; + if (strncasecmp(pcCommand, CMD_RSSI, strlen(CMD_RSSI)) == 0) { + /* + * i4BytesWritten = + * wl_android_get_rssi(net, command, i4TotalLen); + */ + } else if (strncasecmp(pcCommand, CMD_LINKSPEED, strlen(CMD_LINKSPEED)) == 0) { + i4BytesWritten = priv_driver_get_linkspeed(prNetDev, pcCommand, i4TotalLen); + } else if (strncasecmp(pcCommand, CMD_PNOSSIDCLR_SET, strlen(CMD_PNOSSIDCLR_SET)) == 0) { + /* ToDo:: Nothing */ + } else if (strncasecmp(pcCommand, CMD_PNOSETUP_SET, strlen(CMD_PNOSETUP_SET)) == 0) { + /* ToDo:: Nothing */ + } else if (strncasecmp(pcCommand, CMD_PNOENABLE_SET, strlen(CMD_PNOENABLE_SET)) == 0) { + /* ToDo:: Nothing */ + } else if (strncasecmp(pcCommand, CMD_SETSUSPENDOPT, strlen(CMD_SETSUSPENDOPT)) == 0) { + /* i4BytesWritten = wl_android_set_suspendopt(net, pcCommand, i4TotalLen); */ + } else if (strncasecmp(pcCommand, CMD_SETSUSPENDMODE, strlen(CMD_SETSUSPENDMODE)) == 0) { + i4BytesWritten = priv_driver_set_suspend_mode(prNetDev, pcCommand, i4TotalLen); + } else if (strncasecmp(pcCommand, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) { + i4BytesWritten = priv_driver_set_band(prNetDev, pcCommand, i4TotalLen); + } else if (strncasecmp(pcCommand, CMD_GETBAND, strlen(CMD_GETBAND)) == 0) { + /* i4BytesWritten = wl_android_get_band(net, pcCommand, i4TotalLen); */ + } else if (strncasecmp(pcCommand, CMD_SET_TXPOWER, strlen(CMD_SET_TXPOWER)) == 0) { + i4BytesWritten = priv_driver_set_txpower(prNetDev, pcCommand, i4TotalLen); + } else if (strncasecmp(pcCommand, CMD_COUNTRY, strlen(CMD_COUNTRY)) == 0) { + i4BytesWritten = priv_driver_set_country(prNetDev, pcCommand, i4TotalLen); + } else if (strncasecmp(pcCommand, CMD_MIRACAST, strlen(CMD_MIRACAST)) == 0) { + i4BytesWritten = priv_driver_set_miracast(prNetDev, pcCommand, i4TotalLen); + } + /* Mediatek private command */ + else if (strncasecmp(pcCommand, CMD_SET_SW_CTRL, strlen(CMD_SET_SW_CTRL)) == 0) { + i4BytesWritten = priv_driver_set_sw_ctrl(prNetDev, pcCommand, i4TotalLen); + } else if (strncasecmp(pcCommand, CMD_GET_SW_CTRL, strlen(CMD_GET_SW_CTRL)) == 0) { + i4BytesWritten = priv_driver_get_sw_ctrl(prNetDev, pcCommand, i4TotalLen); + } else if (strncasecmp(pcCommand, CMD_SET_CFG, strlen(CMD_SET_CFG)) == 0) { + i4BytesWritten = priv_driver_set_cfg(prNetDev, pcCommand, i4TotalLen); + } else if (strncasecmp(pcCommand, CMD_GET_CFG, strlen(CMD_GET_CFG)) == 0) { + i4BytesWritten = priv_driver_get_cfg(prNetDev, pcCommand, i4TotalLen); + } else if (strncasecmp(pcCommand, CMD_SET_CHIP, strlen(CMD_SET_CHIP)) == 0) { + i4BytesWritten = priv_driver_set_chip_config(prNetDev, pcCommand, i4TotalLen); + } else if (strncasecmp(pcCommand, CMD_GET_CHIP, strlen(CMD_GET_CHIP)) == 0) { + i4BytesWritten = priv_driver_get_chip_config(prNetDev, pcCommand, i4TotalLen); + } + +#if CFG_SUPPORT_QA_TOOL + else if (strncasecmp(pcCommand, CMD_GET_RX_STATISTICS, strlen(CMD_GET_RX_STATISTICS)) == 0) + i4BytesWritten = priv_driver_get_rx_statistics(prNetDev, pcCommand, i4TotalLen); +#if CFG_SUPPORT_BUFFER_MODE + else if (strncasecmp(pcCommand, CMD_SETBUFMODE, strlen(CMD_SETBUFMODE)) == 0) + i4BytesWritten = priv_driver_set_efuse_buffer_mode(prNetDev, pcCommand, i4TotalLen); +#endif +#endif + +#if CFG_SUPPORT_BATCH_SCAN + else if (strncasecmp(pcCommand, CMD_BATCH_SET, strlen(CMD_BATCH_SET)) == 0) { + kalIoctl(prGlueInfo, + wlanoidSetBatchScanReq, + (PVOID) pcCommand, i4TotalLen, FALSE, FALSE, TRUE, &i4BytesWritten); + } else if (strncasecmp(pcCommand, CMD_BATCH_GET, strlen(CMD_BATCH_GET)) == 0) { + /* strcpy(pcCommand, "BATCH SCAN DATA FROM FIRMWARE"); */ + /* i4BytesWritten = strlen("BATCH SCAN DATA FROM FIRMWARE") + 1; */ + /* i4BytesWritten = priv_driver_get_linkspeed (prNetDev, pcCommand, i4TotalLen); */ + + UINT_32 u4BufLen; + int i; + /* int rlen=0; */ + + for (i = 0; i < CFG_BATCH_MAX_MSCAN; i++) { + g_rEventBatchResult[i].ucScanCount = i + 1; /* for get which mscan */ + kalIoctl(prGlueInfo, + wlanoidQueryBatchScanResult, + (PVOID)&g_rEventBatchResult[i], + sizeof(EVENT_BATCH_RESULT_T), TRUE, TRUE, TRUE, &u4BufLen); + } + +#if 0 + DBGLOG(SCN, INFO, "Batch Scan Results, scan count = %u\n", g_rEventBatchResult.ucScanCount); + for (i = 0; i < g_rEventBatchResult.ucScanCount; i++) { + prEntry = &g_rEventBatchResult.arBatchResult[i]; + DBGLOG(SCN, INFO, "Entry %u\n", i); + DBGLOG(SCN, INFO, " BSSID = " MACSTR "\n", MAC2STR(prEntry->aucBssid)); + DBGLOG(SCN, INFO, " SSID = %s\n", prEntry->aucSSID); + DBGLOG(SCN, INFO, " SSID len = %u\n", prEntry->ucSSIDLen); + DBGLOG(SCN, INFO, " RSSI = %d\n", prEntry->cRssi); + DBGLOG(SCN, INFO, " Freq = %u\n", prEntry->ucFreq); + } +#endif + + batchConvertResult(&g_rEventBatchResult[0], pcCommand, i4TotalLen, &i4BytesWritten); + + /* Dump for debug */ + /* + * print_hex_dump(KERN_INFO, + * "BATCH", DUMP_PREFIX_ADDRESS, 16, 1, pcCommand, i4BytesWritten, TRUE); + */ + + } else if (strncasecmp(pcCommand, CMD_BATCH_STOP, strlen(CMD_BATCH_STOP)) == 0) { + kalIoctl(prGlueInfo, + wlanoidSetBatchScanReq, + (PVOID) pcCommand, i4TotalLen, FALSE, FALSE, TRUE, &i4BytesWritten); + } +#endif +#if CFG_SUPPORT_SNIFFER + else if (strncasecmp(pcCommand, CMD_SETMONITOR, strlen(CMD_SETMONITOR)) == 0) + i4BytesWritten = priv_driver_set_monitor(prNetDev, pcCommand, i4TotalLen); +#endif + else if (!strncasecmp(pcCommand, CMD_DUMP_TS, strlen(CMD_DUMP_TS)) || + !strncasecmp(pcCommand, CMD_ADD_TS, strlen(CMD_ADD_TS)) || + !strncasecmp(pcCommand, CMD_DEL_TS, strlen(CMD_DEL_TS))) { + kalIoctl(prGlueInfo, wlanoidTspecOperation, (PVOID)pcCommand, + i4TotalLen, FALSE, FALSE, FALSE, &i4BytesWritten); + } else if (kalStrStr(pcCommand, "-IT ")) { + kalIoctl(prGlueInfo, wlanoidPktProcessIT, (PVOID)pcCommand, + i4TotalLen, FALSE, FALSE, FALSE, &i4BytesWritten); + } else if (!strncasecmp(pcCommand, CMD_FW_EVENT, 9)) { + kalIoctl(prGlueInfo, wlanoidFwEventIT, (PVOID)(pcCommand + 9), + i4TotalLen, FALSE, FALSE, FALSE, &i4BytesWritten); + } else if (!strncasecmp(pcCommand, CMD_DUMP_UAPSD, strlen(CMD_DUMP_UAPSD))) + kalIoctl(prGlueInfo, wlanoidDumpUapsdSetting, (PVOID)pcCommand, + i4TotalLen, FALSE, FALSE, FALSE, &i4BytesWritten); + else if (!strncasecmp(pcCommand, CMD_O_SAR, strlen(CMD_O_SAR))) { + UINT_32 u2SarMode = 0; + INT_8 ret = -1; + + DBGLOG(REQ, INFO, "cmd=%s\n", pcCommand); + do { + if (strlen(pcCommand) <= strlen(CMD_O_SAR)) { + DBGLOG(REQ, ERROR, + "strlen(pcCommand) <= strlen(CMD_O_SAR).\n", ret); + break; + } + + ret = kstrtouint(pcCommand+13, 0, &u2SarMode); + if (ret) { + DBGLOG(REQ, ERROR, "string to int fail %d.\n", ret); + break; + } + + DBGLOG(REQ, INFO, "u2SarMode=%d\n", u2SarMode); + + kalIoctl(prGlueInfo, + wlanoidSendSarEnable, + (PVOID)&u2SarMode, + sizeof(u2SarMode), + FALSE, + FALSE, + TRUE, + &i4BytesWritten); + } while (FALSE); + + } else if (!strncasecmp(pcCommand, CMD_FW_PARAM, strlen(CMD_FW_PARAM))) { + kalIoctl(prGlueInfo, wlanoidSetFwParam, (PVOID)(pcCommand + 13), + i4TotalLen - 13, FALSE, FALSE, FALSE, &i4BytesWritten); + } +#if CFG_SUPPORT_RSSI_DISCONNECT + else if (!strncasecmp(pcCommand, CMD_RSSI_DISCONNECT, strlen(CMD_RSSI_DISCONNECT))) + i4BytesWritten = priv_driver_get_rssiDisconnect(prNetDev, pcCommand, i4TotalLen); +#endif + else + i4CmdFound = 0; + } + /* i4CmdFound */ + if (i4CmdFound == 0) + DBGLOG(REQ, INFO, "Unknown driver command %s - ignored\n", pcCommand); + + if (i4BytesWritten >= 0) { + if ((i4BytesWritten == 0) && (i4TotalLen > 0)) { + /* reset the command buffer */ + pcCommand[0] = '\0'; + } + + if (i4BytesWritten >= i4TotalLen) { + DBGLOG(REQ, INFO, + "%s: i4BytesWritten %d > i4TotalLen < %d\n", __func__, i4BytesWritten, i4TotalLen); + i4BytesWritten = i4TotalLen; + } else { + pcCommand[i4BytesWritten] = '\0'; + i4BytesWritten++; + } + } + + return i4BytesWritten; + +} /* priv_driver_cmds */ + +int priv_support_driver_cmd(IN struct net_device *prNetDev, IN OUT struct ifreq *prReq, IN int i4Cmd) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + int ret = 0; + char *pcCommand = NULL; + priv_driver_cmd_t *priv_cmd = NULL; + int i4BytesWritten = 0; + int i4TotalLen = 0; + + if (!prReq->ifr_data) { + ret = -EINVAL; + goto exit; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (!prGlueInfo) { + DBGLOG(REQ, WARN, "No glue info\n"); + ret = -EFAULT; + goto exit; + } + if (prGlueInfo->u4ReadyFlag == 0) { + ret = -EINVAL; + goto exit; + } + + priv_cmd = kzalloc(sizeof(priv_driver_cmd_t), GFP_KERNEL); + if (!priv_cmd) { + DBGLOG(REQ, WARN, "%s, alloc mem failed\n", __func__); + return -ENOMEM; + } + + if (copy_from_user(priv_cmd, prReq->ifr_data, sizeof(priv_driver_cmd_t))) { + DBGLOG(REQ, ERROR, "%s: copy_from_user fail\n", __func__); + ret = -EFAULT; + goto exit; + } + + i4TotalLen = priv_cmd->total_len; + + if (i4TotalLen <= 0 || i4TotalLen > PRIV_CMD_SIZE) { + ret = -EINVAL; + DBGLOG(REQ, ERROR, "%s: i4TotalLen invalid\n", __func__); + goto exit; + } + priv_cmd->buf[PRIV_CMD_SIZE - 1] = '\0'; + pcCommand = priv_cmd->buf; + + DBGLOG(REQ, INFO, "%s: driver cmd \"%s\" on %s\n", __func__, pcCommand, prReq->ifr_name); + + i4BytesWritten = priv_driver_cmds(prNetDev, pcCommand, i4TotalLen); + + if (i4BytesWritten == -EOPNOTSUPP) { + /* Report positive status */ + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, + "%s", "UNSUPPORTED"); + if (i4BytesWritten < 0) { + ret = -EINVAL; + DBGLOG(REQ, ERROR, "%s: i4BytesWritten < 0.\n", __func__); + goto exit; + } + i4BytesWritten++; + } + if (i4BytesWritten >= 0) { + priv_cmd->used_len = i4BytesWritten; + if ((i4BytesWritten == 0) && (priv_cmd->total_len > 0)) + pcCommand[0] = '\0'; + if (i4BytesWritten >= priv_cmd->total_len) + i4BytesWritten = priv_cmd->total_len; + else + i4BytesWritten++; + priv_cmd->used_len = i4BytesWritten; + if (copy_to_user(prReq->ifr_data, priv_cmd, + sizeof(struct priv_driver_cmd_s))) { + ret = -EFAULT; + DBGLOG(REQ, INFO, "copy fail"); + } + } else + ret = i4BytesWritten; + +exit: + kfree(priv_cmd); + + return ret; +} /* priv_support_driver_cmd */ +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR +/* link quality monitor */ +int kalGetRate(uint32_t txmode, uint32_t rate, uint32_t frmode, uint32_t sgi, + uint32_t nsts, uint32_t *pu4CurRate, uint32_t *pu4MaxRate) +{ + uint32_t u4CurRate, u4MaxRate; + uint8_t ucMaxIdx; + + if (txmode == TX_RATE_MODE_CCK) { + ucMaxIdx = ARRAY_SIZE(g_rCckDataRateMappingTable.rate); + if (rate >= ucMaxIdx) { + DBGLOG(SW4, ERROR, "rate error for CCK: %u\n", rate); + return -1; + } + u4CurRate = g_rCckDataRateMappingTable.rate[rate]; + u4MaxRate = g_rCckDataRateMappingTable.rate[ucMaxIdx - 1]; + } else if (txmode == TX_RATE_MODE_OFDM) { + u4CurRate = hw_rate_ofdm_num(rate); + if (u4CurRate == 0) { + DBGLOG(SW4, ERROR, "rate error for OFDM\n"); + return -1; + } + ucMaxIdx = ARRAY_SIZE(g_rOfdmDataRateMappingTable.rate); + u4MaxRate = g_rOfdmDataRateMappingTable.rate[ucMaxIdx - 1]; + } else if ((txmode == TX_RATE_MODE_HTMIX) || + (txmode == TX_RATE_MODE_HTGF)) { + if (rate < 8) + nsts = 0; + else if (rate < 16) { + nsts = 1; + rate -= 8; + } else if (rate <= 23) { + nsts = 2; + rate -= 16; + } else { + DBGLOG(SW4, ERROR, "rate error for HT: %u\n", rate); + return -1; + } + u4CurRate = + g_rDataRateMappingTable.nsts[nsts]. + bw[frmode].sgi[sgi].rate[rate]; + ucMaxIdx = + ARRAY_SIZE(g_rDataRateMappingTable.nsts[nsts]. + bw[frmode].sgi[sgi].rate); + u4MaxRate = + g_rDataRateMappingTable.nsts[nsts]. + bw[frmode].sgi[sgi].rate[ucMaxIdx - 1]; + } else { + if ((nsts == 0) || (nsts >= 4)) { + DBGLOG(SW4, ERROR, "nsts error: %u\n", nsts); + return -1; + } + rate &= RX_VT_RX_RATE_AC_MASK; + u4CurRate = + g_rDataRateMappingTable.nsts[nsts - 1]. + bw[frmode].sgi[sgi].rate[rate]; + ucMaxIdx = + ARRAY_SIZE(g_rDataRateMappingTable.nsts[nsts - 1]. + bw[frmode].sgi[sgi].rate); + u4MaxRate = + g_rDataRateMappingTable.nsts[nsts - 1]. + bw[frmode].sgi[sgi].rate[ucMaxIdx - 1]; + } + *pu4CurRate = u4CurRate; + *pu4MaxRate = u4MaxRate; + return 0; +} + +/* link quality monitor */ +int kalGetRxRate(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_32 *pu4CurRate, IN UINT_32 *pu4MaxRate) +{ + P_ADAPTER_T prAdapter; + UINT_32 txmode = 0, rate = 0, frmode = 0, sgi = 0, nsts = 0, groupid = 0; + UINT_32 u4RxVector0 = 0, u4RxVector1 = 0; + UINT_8 ucWlanIdx, ucStaIdx; + int rv; + + *pu4CurRate = 0; + *pu4MaxRate = 0; + prAdapter = prGlueInfo->prAdapter; + + /* Get AIS AP address for no argument */ + if (prAdapter->prAisBssInfo->prStaRecOfAP) { + ucWlanIdx = prAdapter->prAisBssInfo->prStaRecOfAP + ->ucWlanIndex; + } else { /* try get a peer */ + DBGLOG(SW4, ERROR, "no connected peer found!\n"); + goto errhandle; + } + + if (wlanGetStaIdxByWlanIdx(prAdapter, ucWlanIdx, &ucStaIdx) == + WLAN_STATUS_SUCCESS) { + u4RxVector0 = prAdapter->arStaRec[ucStaIdx].u4RxVector0; + u4RxVector1 = prAdapter->arStaRec[ucStaIdx].u4RxVector1; + } else { + DBGLOG(SW4, ERROR, "Last RX Rate not support"); + goto errhandle; + } + + txmode = (u4RxVector0 & RX_VT_RX_MODE_MASK) >> RX_VT_RX_MODE_OFFSET; + rate = (u4RxVector0 & RX_VT_RX_RATE_MASK) >> RX_VT_RX_RATE_OFFSET; + frmode = (u4RxVector0 & RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET; + nsts = ((u4RxVector1 & RX_VT_NSTS_MASK) >> RX_VT_NSTS_OFFSET); + sgi = u4RxVector0 & RX_VT_SHORT_GI; + groupid = (u4RxVector1 & RX_VT_GROUP_ID_MASK) >> RX_VT_GROUP_ID_OFFSET; + + if (u4RxVector0 == 0 && u4RxVector1 == 0) + goto errhandle; + /* Read Clear */ + prAdapter->arStaRec[ucStaIdx].u4RxVector0 = 0; + prAdapter->arStaRec[ucStaIdx].u4RxVector1 = 0; + if (groupid && groupid != 63) { + /* mu = 1; */ + } else { + /* mu = 0; */ + nsts += 1; + } + sgi = (sgi == 0) ? 0 : 1; + if (frmode >= 4) { + DBGLOG(SW4, ERROR, "frmode error: %u\n", frmode); + goto errhandle; + } + DBGLOG(SW4, TRACE, + "staIdx:%d,u4RxVector0=[%x], u4RxVector1=[%x], txmode=[%u], rate=[%u], frmode=[%u], sgi=[%u], nsts=[%u]\n", + ucStaIdx, u4RxVector0, u4RxVector1, txmode, rate, frmode, sgi, nsts + ); + rv = kalGetRate(txmode, rate, frmode, sgi, nsts, pu4CurRate, + pu4MaxRate); + if (rv < 0) + goto errhandle; + return 0; + +errhandle: + DBGLOG(SW4, ERROR, + "u4RxVector0=[%x], u4RxVector1=[%x], txmode=[%u], rate=[%u], frmode=[%u], sgi=[%u], nsts=[%u]\n", + u4RxVector0, u4RxVector1, txmode, rate, frmode, sgi, nsts + ); + return -1; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/ahb.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/ahb.c new file mode 100644 index 0000000000000..93f85ee50674d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/ahb.c @@ -0,0 +1,1515 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#include +#ifndef CONFIG_X86 +#include +#endif + +#ifdef CONFIG_OF +#include +#include +#include +#endif + +#include "gl_os.h" +#include "mt6630_reg.h" +#include "sdio.h" +#include "gl_rst.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* #define MTK_DMA_BUF_MEMCPY_SUP no virt_to_phys() use */ + +#define NIC_TX_PAGE_SIZE 128 /* in unit of bytes */ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static int HifAhbProbe(VOID); + +static int HifAhbRemove(VOID); + +static int HifAhbBusCntGet(VOID); + +static int HifAhbBusCntClr(VOID); + +static int HifAhbIsWifiDrvOwn(VOID); + +static int HifTxCnt; + +#if (CONF_HIF_DEV_MISC == 1) +static ssize_t HifAhbMiscRead(IN struct file *Filp, OUT char __user *DstBuf, IN size_t Size, IN loff_t *Ppos); + +static ssize_t HifAhbMiscWrite(IN struct file *Filp, IN const char __user *SrcBuf, IN size_t Size, IN loff_t *Ppos); + +static int HifAhbMiscIoctl(IN struct file *Filp, IN unsigned int Cmd, IN unsigned long arg); + +static int HifAhbMiscOpen(IN struct inode *Inodep, IN struct file *Filp); + +static int HifAhbMiscClose(IN struct inode *Inodep, IN struct file *Filp); +#else + +static int HifAhbPltmProbe(IN struct platform_device *pDev); + +static int HifAhbPltmRemove(IN struct platform_device *pDev); + +#ifdef CONFIG_PM +static int HifAhbPltmSuspend(IN struct platform_device *pDev, pm_message_t message); + +static int HifAhbPltmResume(IN struct platform_device *pDev); +#endif /* CONFIG_PM */ + +#endif /* CONF_HIF_DEV_MISC */ + +#if (CONF_HIF_LOOPBACK_AUTO == 1) /* only for development test */ +static VOID HifAhbLoopbkAuto(IN unsigned long arg); +#endif /* CONF_HIF_LOOPBACK_AUTO */ + +static irqreturn_t HifAhbISR(IN int irq, IN void *arg); + +#if (CONF_HIF_DMA_INT == 1) +static irqreturn_t HifDmaISR(IN int irq, IN void *arg); +#endif /* CONF_HIF_DMA_INT */ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +DEFINE_SPINLOCK(HifLock); +DEFINE_SPINLOCK(HifSdioLock); + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/* initialiation function from other module */ +static probe_card pfWlanProbe; + +/* release function from other module */ +static remove_card pfWlanRemove; + +static BOOLEAN WlanDmaFatalErr; + +int sdioDisableRefCnt; + +#if (CONF_HIF_DEV_MISC == 1) +static const struct file_operations MtkAhbOps = { + .owner = THIS_MODULE, + .read = HifAhbMiscRead, + .write = HifAhbMiscWrite, + .unlocked_ioctl = HifAhbMiscIoctl, + .compat_ioctl = HifAhbMiscIoctl, + .open = HifAhbMiscOpen, + .release = HifAhbMiscClose, +}; + +static struct miscdevice MtkAhbDriver = { + .minor = MISC_DYNAMIC_MINOR, /* any minor number */ + .name = HIF_MOD_NAME, + .fops = &MtkAhbOps, +}; +#else + +#ifdef CONFIG_OF +static const struct of_device_id apwifi_of_ids[] = { + {.compatible = "mediatek,wifi",}, + {} +}; +#endif + +struct platform_driver MtkAhbPltmDriver = { + .driver = { + .name = "mt-wifi", + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = apwifi_of_ids, +#endif + }, + .probe = HifAhbPltmProbe, +#ifdef CONFIG_PM + .suspend = HifAhbPltmSuspend, + .resume = HifAhbPltmResume, +#else + .suspend = NULL, + .resume = NULL, +#endif /* CONFIG_PM */ + .remove = __exit_p(HifAhbPltmRemove), +}; + +static struct platform_device *HifAhbPDev; + +#endif /* CONF_HIF_DEV_MISC */ + +/******************************************************************************* +* P U B L I C F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will register sdio bus to the os +* +* \param[in] pfProbe Function pointer to detect card +* \param[in] pfRemove Function pointer to remove card +* +* \return The result of registering HIF driver (WLAN_STATUS_SUCCESS = 0) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS glRegisterBus(probe_card pfProbe, remove_card pfRemove) +{ + WLAN_STATUS ret; + + ASSERT(pfProbe); + ASSERT(pfRemove); + + pfWlanProbe = pfProbe; /* wlan card initialization in other modules = wlanProbe() */ + pfWlanRemove = pfRemove; + +#if (CONF_HIF_DEV_MISC == 1) + ret = misc_register(&MtkAhbDriver); + if (ret != 0) + return ret; + HifAhbProbe(); +#else + ret = platform_driver_register(&MtkAhbPltmDriver); +#endif /* CONF_HIF_DEV_MISC */ + + return ret; +} /* end of glRegisterBus() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will unregister sdio bus to the os +* +* \param[in] pfRemove Function pointer to remove card +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glUnregisterBus(remove_card pfRemove) +{ + ASSERT(pfRemove); + + pfRemove(); + +#if (CONF_HIF_DEV_MISC == 1) + HifAhbRemove(); + + if ((misc_deregister(&MtkAhbDriver)) != 0) + ; +#else + platform_driver_unregister(&MtkAhbPltmDriver); +#endif /* CONF_HIF_DEV_MISC */ + + return; + +} /* end of glUnregisterBus() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will inform us whole chip reset start event. +* +* \param[in] GlueInfo Pointer to glue info structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glResetHif(GLUE_INFO_T *GlueInfo) +{ + GL_HIF_INFO_T *HifInfo; + + ASSERT(GlueInfo); + HifInfo = &GlueInfo->rHifInfo; + if (HifInfo->DmaOps) + HifInfo->DmaOps->DmaReset(HifInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function stores hif related info, which is initialized before. +* +* \param[in] GlueInfo Pointer to glue info structure +* \param[in] u4Cookie Pointer to UINT_32 memory base variable for _HIF_HPI +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 **g_pHifRegBaseAddr; + +VOID glSetHifInfo(GLUE_INFO_T *GlueInfo, ULONG ulCookie) +{ + GL_HIF_INFO_T *HifInfo; + UINT_32 val = HIF_DRV_BASE, val_h = 0; + + /* Init WIFI HIF */ + ASSERT(GlueInfo); + HifInfo = &GlueInfo->rHifInfo; +#if (CONF_HIF_DEV_MISC == 1) + HifInfo->Dev = MtkAhbDriver.this_device; +#else + HifInfo->Dev = &HifAhbPDev->dev; +#endif /* CONF_HIF_DEV_MISC */ + SET_NETDEV_DEV(GlueInfo->prDevHandler, HifInfo->Dev); + +#ifdef CONFIG_OF + HifInfo->HifRegBaseAddr = (PUINT_8)of_iomap(HifInfo->Dev->of_node, 0); + if (of_property_read_u32_index(HifInfo->Dev->of_node, "reg", 0, &val_h) || + of_property_read_u32_index(HifInfo->Dev->of_node, "reg", 1, &val)) { + DBGLOG(INIT, ERROR, "Failed to get WIFI-HIF base addr from DT!! Tx/Rx maybe abnormal!!\n"); + } +#if __BITS_PER_LONG == 32 + HifInfo->HifRegPhyBase = (ULONG)val; +#else + HifInfo->HifRegPhyBase = (((ULONG)val_h << 16) << 16) | (ULONG)val; +#endif + HifInfo->InfraRegBaseAddr = (PUINT_8)of_iomap(HifInfo->Dev->of_node, 2); + HifInfo->ConnCfgRegBaseAddr = (PUINT_8)of_iomap(HifInfo->Dev->of_node, 3); +#else + HifInfo->HifRegBaseAddr = ioremap(HIF_DRV_BASE, HIF_DRV_LENGTH); + HifInfo->HifRegPhyBase = HIF_DRV_BASE; + HifInfo->InfraRegBaseAddr = ioremap(INFRA_AO_DRV_BASE, INFRA_AO_DRV_LENGTH); + HifInfo->ConnCfgRegBaseAddr = ioremap(CONN_REMAP_CONF_BASE, CONN_REMAP_CONF_LENGTH); +#endif +#if defined(MT6797) + HifInfo->confRegBaseAddr = ioremap(DYNAMIC_REMAP_CONF_BASE, DYNAMIC_REMAP_CONF_LENGTH); +#endif + g_pHifRegBaseAddr = &(HifInfo->HifRegBaseAddr); + + DBGLOG(INIT, INFO, "HifRegBaseAddr = %p, HifRegPhyBase = 0x%lx\n", + HifInfo->HifRegBaseAddr, HifInfo->HifRegPhyBase); + + /* default disable DMA */ + HifInfo->fgDmaEnable = FALSE; + HifInfo->DmaRegBaseAddr = 0; + HifInfo->DmaOps = NULL; + + sdio_open(); + + /* Init DMA */ + WlanDmaFatalErr = 0; /* reset error flag */ + sdioDisableRefCnt = 0; +#if (CONF_MTK_AHB_DMA == 1) + HifDmaInit(HifInfo); +#endif /* CONF_MTK_AHB_DMA */ + + /* Start loopback test after 10 seconds */ +#if (CONF_HIF_LOOPBACK_AUTO == 1) /* only for development test */ + { + init_timer(&(HifInfo->HifTmrLoopbkFn)); + HifInfo->HifTmrLoopbkFn.function = HifAhbLoopbkAuto; + HifInfo->HifTmrLoopbkFn.data = (unsigned long)GlueInfo; + + init_waitqueue_head(&HifInfo->HifWaitq); + /* TODO: implement kalDevLoopbkThread to enable loopback function */ + /*HifInfo->HifTaskLoopbkFn = kthread_run(kalDevLoopbkThread, GlueInfo->prDevHandler, "LoopbkThread");*/ + HifInfo->HifLoopbkFlg = 0; + + /* Note: in FPGA, clock is not accuracy so 3000 here, not 10000 */ + HifInfo->HifTmrLoopbkFn.expires = jiffies + MSEC_TO_SYSTIME(30000); + add_timer(&(HifInfo->HifTmrLoopbkFn)); + + DBGLOG(HAL, INFO, "Start loopback test after 10 seconds (jiffies = %u)...\n", jiffies); + } +#endif /* CONF_HIF_LOOPBACK_AUTO */ + +#if (CONF_HIF_DMA_INT == 1) + init_waitqueue_head(&HifInfo->HifDmaWaitq); + HifInfo->HifDmaFinishFlag = 0; +#endif /* CONF_HIF_DMA_INT */ + +} /* end of glSetHifInfo() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function clears hif related info. +* +* \param[in] GlueInfo Pointer to glue info structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glClearHifInfo(GLUE_INFO_T *GlueInfo) +{ +#if (CONF_MTK_AHB_DMA == 1) + HifDmaUnInit(&GlueInfo->rHifInfo); +#endif + iounmap(GlueInfo->rHifInfo.HifRegBaseAddr); + if (GlueInfo->rHifInfo.InfraRegBaseAddr) + iounmap(GlueInfo->rHifInfo.InfraRegBaseAddr); + if (GlueInfo->rHifInfo.ConnCfgRegBaseAddr) + iounmap(GlueInfo->rHifInfo.ConnCfgRegBaseAddr); +#if defined(MT6797) + iounmap(GlueInfo->rHifInfo.confRegBaseAddr); +#endif +} /* 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) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN glBusInit(PVOID pvData) +{ + return TRUE; +} /* end of glBusInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus operation and release resources. +* +* \param[in] pvData A pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glBusRelease(PVOID pvData) +{ +} /* end of glBusRelease() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setup bus interrupt operation and interrupt handler for os. +* +* \param[in] pvData A pointer to struct net_device. +* \param[in] pfnIsr A pointer to interrupt handler function. +* \param[in] pvCookie Private data for pfnIsr function. +* +* \retval WLAN_STATUS_SUCCESS if success +* NEGATIVE_VALUE if fail +*/ +/*----------------------------------------------------------------------------*/ +INT_32 glBusSetIrq(PVOID pvData, PVOID pfnIsr, PVOID pvCookie) +{ +#ifdef CONFIG_OF + struct device_node *node = NULL; +#endif + struct net_device *prNetDevice; + GLUE_INFO_T *prGlueInfo; + unsigned int irq_id; + unsigned int irq_flags = 0; +#if (CONF_HIF_DMA_INT == 1) + unsigned int dma_irq_id; +#endif + + if (!pvData) { + DBGLOG(INIT, ERROR, "Invalid pvData!\n"); + return -1; + } + prNetDevice = (struct net_device *)pvData; + + prGlueInfo = (GLUE_INFO_T *) pvCookie; + if (!prGlueInfo || !prGlueInfo->rHifInfo.Dev) { + DBGLOG(INIT, ERROR, "No glue info!\n"); + return -1; + } + +#ifdef CONFIG_OF + node = prGlueInfo->rHifInfo.Dev->of_node; + irq_id = irq_of_parse_and_map(node, 0); + DBGLOG(INIT, TRACE, "WIFI-HIF irq %d\n", irq_id); + + /* Get the interrupt flags and then used it for request_irq, but this can be skiped + * and just set IRQF_TRIGGER_NONE in request_irq since device tree has already set it. + */ + if (of_property_read_u32_index(node, "interrupts", 2, &irq_flags)) + DBGLOG(INIT, ERROR, "Failed to get WIFI-HIF irq flags from DT!\n"); + else + DBGLOG(INIT, TRACE, "WIFI-HIF irq flags 0x%x\n", irq_flags); + +#else + irq_id = MT_WF_HIF_IRQ_ID; + irq_flags = IRQF_TRIGGER_LOW; +#endif + + /* Register HIF IRQ */ + if (request_irq(irq_id, HifAhbISR, irq_flags, HIF_MOD_NAME, prNetDevice)) { + DBGLOG(INIT, ERROR, "Failed to request irq %d!\n", irq_id); + return -1; + } + + prGlueInfo->rHifInfo.HifIRQ = irq_id; + +#if (CONF_HIF_DMA_INT == 1) +#ifdef CONFIG_OF + dma_irq_id = irq_of_parse_and_map(node, 1); + DBGLOG(INIT, INFO, "WIFI-HIF DMA irq %d\n", dma_irq_id); + + if (of_property_read_u32_index(node, "interrupts", 5, &irq_flags)) + DBGLOG(INIT, ERROR, "Failed to get WIFI-HIF DMA irq flags from DT!\n"); + else + DBGLOG(INIT, INFO, "WIFI-HIF DMA irq flags 0x%x\n", irq_flags); + +#else + dma_irq_id = MT_WF_HIF_DMA_IRQ_ID; + irq_flags = IRQF_TRIGGER_LOW; +#endif + + /* Register HIF DMA IRQ */ + if (request_irq(dma_irq_id, HifDmaISR, irq_flags, "AHB_DMA", prNetDevice)) { + DBGLOG(INIT, ERROR, "Failed to request irq %d!\n", dma_irq_id); + free_irq(irq_id, prNetDevice); + return -1; + } + + prGlueInfo->rHifInfo.HifDmaIRQ = dma_irq_id; +#endif /* CONF_HIF_DMA_INT */ + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus interrupt operation and disable interrupt handling for os. +* +* \param[in] pvData A pointer to struct net_device. +* \param[in] pvCookie Private data for pfnIsr function. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glBusFreeIrq(PVOID pvData, PVOID pvCookie) +{ + struct net_device *prNetDevice; + GLUE_INFO_T *prGlueInfo; + + if (!pvData) { + DBGLOG(INIT, ERROR, "Invalid pvData!\n"); + return; + } + prNetDevice = (struct net_device *)pvData; + + prGlueInfo = (GLUE_INFO_T *) pvCookie; + if (!prGlueInfo) { + DBGLOG(INIT, ERROR, "No glue info!\n"); + return; + } + + /* Free the IRQ */ + free_irq(prGlueInfo->rHifInfo.HifIRQ, prNetDevice); + +#if (CONF_HIF_DMA_INT == 1) + free_irq(prGlueInfo->rHifInfo.HifDmaIRQ, prNetDevice); +#endif /* CONF_HIF_DMA_INT */ + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Read a 32-bit device register +* +* \param[in] GlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] RegOffset Register offset +* \param[in] pu4Value Pointer to variable used to store read value +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalDevRegRead(IN GLUE_INFO_T *GlueInfo, IN UINT_32 RegOffset, OUT UINT_32 *pu4Value) +{ + GL_HIF_INFO_T *HifInfo; + + ASSERT(GlueInfo); + ASSERT(pu4Value); + HifInfo = &GlueInfo->rHifInfo; + + /* PIO mode to read HIF controller driver domain register */ + *pu4Value = HIF_REG_READL(HifInfo, RegOffset); + + return TRUE; +} /* end of kalDevRegRead() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write a 32-bit device register +* +* \param[in] GlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] RegOffset Register offset +* \param[in] RegValue RegValue to be written +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalDevRegWrite(IN GLUE_INFO_T *GlueInfo, IN UINT_32 RegOffset, IN UINT_32 RegValue) +{ + GL_HIF_INFO_T *HifInfo; + + ASSERT(GlueInfo); + HifInfo = &GlueInfo->rHifInfo; + + /* PIO mode to write HIF controller driver domain register */ + HIF_REG_WRITEL(HifInfo, RegOffset, RegValue); + + return TRUE; +} /* end of kalDevRegWrite() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Read device I/O port +* +* \param[in] GlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] Port I/O port offset +* \param[in] Size Length to be read +* \param[out] Buf Pointer to read buffer +* \param[in] MaxBufSize Length of the buffer valid to be accessed +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalDevPortRead(IN P_GLUE_INFO_T GlueInfo, IN UINT_16 Port, IN UINT_32 Size, OUT PUINT_8 Buf, IN UINT_32 MaxBufSize) +{ + GL_HIF_INFO_T *HifInfo; +#if (CONF_MTK_AHB_DMA == 1) + MTK_WCN_HIF_DMA_CONF DmaConf; +#endif /* CONF_MTK_AHB_DMA */ + UINT_32 idx, u4DwNum; + UINT_32 *p; + BOOLEAN ret = TRUE; + + sdio_gen3_cmd53_info info; + struct sdio_func *func = &g_sdio_func; + UINT_32 count; + + /* sanity check */ + if (WlanDmaFatalErr) { + DBGLOG(HAL, ERROR, "WlanDmaFatalErr: %d\n", WlanDmaFatalErr); + return FALSE; + } + + ASSERT(GlueInfo); + HifInfo = &GlueInfo->rHifInfo; + + ASSERT(Buf); + ASSERT(Size <= MaxBufSize); + + /********** SDIO like operation **********/ + count = ALIGN_4(Size); + + /* 1. Setup command information */ + info.word = 0; + info.field.rw_flag = SDIO_GEN3_READ; + info.field.func_num = func->num; + + /* CMD53 port mode to read n-byte, if count >= block size => block mode, otherwise => byte mode */ + if (count >= func->cur_blksize) { /* block mode */ + info.field.block_mode = SDIO_GEN3_BLOCK_MODE; + info.field.count = count/func->cur_blksize; + if (count % func->cur_blksize > 0) + info.field.count++; + count = info.field.count * func->cur_blksize; + if (count > MaxBufSize) { + DBGLOG(HAL, ERROR, "blk mode count(%d->%d), MaxSz(%d)\n", Size, count, MaxBufSize); + ASSERT(0); + } + } else { /* byte mode */ + if (func->use_dma && (Port != MCR_WHISR)) /* safe for reading 4 bytes WHISR */ + count = ((Size + 7) & ~7u); /* if DMA mode, RX 8 bytes alignment is required */ + info.field.block_mode = SDIO_GEN3_BYTE_MODE; + info.field.count = count; + if (count > MaxBufSize) { + DBGLOG(HAL, ERROR, "byte mode count(%d->%d), MaxSz(%d)\n", Size, count, MaxBufSize); + ASSERT(0); + } + } + + info.field.op_mode = SDIO_GEN3_FIXED_PORT_MODE; /* fix mode */ + info.field.addr = Port; + + DBGLOG(HAL, TRACE, "readsb use_dma(%d), count(%d->%d), blk_size(%d), port(0x%x), CMD_SETUP(0x%08x)\n", + func->use_dma, Size, count, func->cur_blksize, Port, info.word); + +#if (CONF_MTK_AHB_DMA == 1) + if (func->use_dma && (HifInfo->fgDmaEnable == TRUE) && (HifInfo->DmaOps != NULL) + && ((Port == MCR_WRDR0) || (Port == MCR_WRDR1))) { + /* move forward since clk_prepare_enable can only be called in non-atomic context */ + HifInfo->DmaOps->DmaClockCtrl(HifInfo, TRUE); + } +#endif + + my_sdio_disable(HifLock); + __disable_irq(); + + writel(info.word, (volatile UINT_32 *)(*g_pHifRegBaseAddr + SDIO_GEN3_CMD_SETUP)); + wmb(); + + /* 2. Read CMD53 port */ +#if (CONF_MTK_AHB_DMA == 1) + if (func->use_dma && (HifInfo->fgDmaEnable == TRUE) && (HifInfo->DmaOps != NULL) + && ((Port == MCR_WRDR0) || (Port == MCR_WRDR1))) { + /* only for data port */ +#ifdef MTK_DMA_BUF_MEMCPY_SUP + VOID *DmaVBuf = NULL, *DmaPBuf = NULL; +#endif /* MTK_DMA_BUF_MEMCPY_SUP */ + + /* 2.1 config DMA for data transmission */ + DmaConf.Count = count; + DmaConf.Dir = HIF_DMA_DIR_RX; + DmaConf.Src = HifInfo->HifRegPhyBase + SDIO_GEN3_CMD53_DATA; /* must be physical addr */ + +#ifdef MTK_DMA_BUF_MEMCPY_SUP + DmaConf.Dst = kalIOPhyAddrGet(Buf); /* must be physical addr */ + + /* TODO: use virt_to_phys() */ + if (DmaConf.Dst == NULL) { + ASSERT(count <= CFG_RX_MAX_PKT_SIZE); + + kalDmaBufGet(&DmaVBuf, &DmaPBuf); + DmaConf.Dst = (ULONG) DmaPBuf; + } +#else + /* + * http://kernelnewbies.org/KernelMemoryAllocation + * Since the cache-coherent mapping may be expensive, also a streaming allocation exists. + * + * This is a buffer for one-way communication, which means coherency is limited to + * flushing the data from the cache after a write finishes. The buffer has to be + * pre-allocated (e.g. using kmalloc()). DMA for it is set up with dma_map_single(). + * + * When the DMA is finished (e.g. when the device has sent an interrupt signaling end of + * DMA), call dma_unmap_single(). Between map and unmap, the device is in control of the + * buffer: if you write to the device, do it before dma_map_single(), if you read from + * it, do it after dma_unmap_single(). + */ + /* DMA_FROM_DEVICE invalidated (without writeback) the cache */ + /* TODO: if dst_off was not cacheline aligned? */ + + DmaConf.Dst = dma_map_single(HifInfo->Dev, Buf, count, DMA_FROM_DEVICE); + +#endif /* MTK_DMA_BUF_MEMCPY_SUP */ + + HifInfo->DmaOps->DmaConfig(HifInfo, &DmaConf); + /* 2.2 start DMA */ + HifInfo->DmaOps->DmaStart(HifInfo); + + /* 2.3 wait for DMA finish */ +#if (CONF_HIF_DMA_INT == 1) + if (wait_event_interruptible_timeout(HifInfo->HifDmaWaitq, HifInfo->HifDmaFinishFlag != 0, 1000) <= 0) { + if (HifInfo->DmaOps->DmaRegDump != NULL) + HifInfo->DmaOps->DmaRegDump(HifInfo); + DBGLOG(HAL, ERROR, "fatal error! reset DMA!\n"); + if (HifInfo->DmaOps->DmaReset != NULL) + HifInfo->DmaOps->DmaReset(HifInfo); + ret = FALSE; + goto DMA_DONE; + } + HifInfo->HifDmaFinishFlag = 0; +#else + { + ULONG PollTimeout = jiffies + HZ * 5; + do { + if (time_before(jiffies, PollTimeout)) { + /* Do nothing */ + /* not timeout, continue to poll */ + } else { + if (HifInfo->DmaOps->DmaRegDump != NULL) + HifInfo->DmaOps->DmaRegDump(HifInfo); + +#if (CONF_HIF_CONNSYS_DBG == 0) + DBGLOG(HAL, ERROR, "fatal error! reset DMA!\n"); + if (HifInfo->DmaOps->DmaReset != NULL) + HifInfo->DmaOps->DmaReset(HifInfo); + ret = FALSE; + goto DMA_DONE; +#else + /* + * Never break and just wait for response from HIF + * + * Because when we use ICE on CONNSYS, we will break CONSYS CPU and do debug, + * but maybe AP side continues to send packets to HIF, to prevent HIF buffer + * from being full and CONNSYS reset, never break here, just stuck in loop. + */ + DBGLOG(HAL, WARN, "DMA timeout 5s... (%lu %lu)\n", jiffies, PollTimeout); + WlanDmaFatalErr = 1; + +#endif /* CONF_HIF_CONNSYS_DBG */ + } + } while (!HifInfo->DmaOps->DmaPollIntr(HifInfo)); + } +#endif /* CONF_HIF_DMA_INT */ + + /* 2.4 ack DMA interrupt */ + HifInfo->DmaOps->DmaAckIntr(HifInfo); + HifInfo->DmaOps->DmaStop(HifInfo); + +#if (CONF_HIF_DMA_INT == 1) + enable_irq(HifInfo->HifDmaIRQ); +#endif + +DMA_DONE: +#ifdef MTK_DMA_BUF_MEMCPY_SUP + if (DmaVBuf != NULL) + kalMemCopy(Buf, DmaVBuf, count); +#else + dma_unmap_single(HifInfo->Dev, DmaConf.Dst, count, DMA_FROM_DEVICE); +#endif /* MTK_DMA_BUF_MEMCPY_SUP */ + + __enable_irq(); + my_sdio_enable(HifLock); + + /* move behind since clk_disable_unprepare can only be called in non-atomic context */ + HifInfo->DmaOps->DmaClockCtrl(HifInfo, FALSE); + + DBGLOG(HAL, TRACE, "DMA RX %s!\n", ret ? "OK" : "FAIL"); + } else +#endif /* CONF_MTK_AHB_DMA */ + { + /* PIO mode */ + u4DwNum = count >> 2; + p = (UINT_32 *) Buf; + + for (idx = 0; idx < u4DwNum; idx++) { + *p = readl((volatile UINT_32 *)(*g_pHifRegBaseAddr + SDIO_GEN3_CMD53_DATA)); + DBGLOG(HAL, LOUD, "idx = %d, val = 0x%08x\n", idx, *p); + p++; + } + + __enable_irq(); + my_sdio_enable(HifLock); + + DBGLOG(HAL, TRACE, "PIO RX OK!\n"); + } + + return ret; +} /* end of kalDevPortRead() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write device I/O port +* +* \param[in] GlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] Port I/O port offset +* \param[in] Size Length to be write +* \param[in] Buf Pointer to write buffer +* \param[in] MaxBufSize Length of the buffer valid to be accessed +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalDevPortWrite(IN P_GLUE_INFO_T GlueInfo, IN UINT_16 Port, IN UINT_32 Size, IN PUINT_8 Buf, IN UINT_32 MaxBufSize) +{ + GL_HIF_INFO_T *HifInfo; +#if (CONF_MTK_AHB_DMA == 1) + MTK_WCN_HIF_DMA_CONF DmaConf; +#endif /* CONF_MTK_AHB_DMA */ + UINT_32 idx, u4DwNum; + UINT_32 *p; + BOOLEAN ret = TRUE; + + sdio_gen3_cmd53_info info; + struct sdio_func *func = &g_sdio_func; + UINT_32 count; + + /* sanity check */ + if (WlanDmaFatalErr) { + DBGLOG(HAL, ERROR, "WlanDmaFatalErr: %d\n", WlanDmaFatalErr); + return FALSE; + } + + ASSERT(GlueInfo); + HifInfo = &GlueInfo->rHifInfo; + + ASSERT(Buf); + ASSERT(Size <= MaxBufSize); + + HifTxCnt++; + + /********** SDIO like operation **********/ + count = ALIGN_4(Size); + + /* 1. Setup command information */ + info.word = 0; + info.field.rw_flag = SDIO_GEN3_WRITE; + info.field.func_num = func->num; + + /* CMD53 port mode to write n-byte, if count >= block size => block mode, otherwise => byte mode */ + if (count >= func->cur_blksize) { /* block mode */ + info.field.block_mode = SDIO_GEN3_BLOCK_MODE; + info.field.count = count/func->cur_blksize; + if (count % func->cur_blksize > 0) + info.field.count++; + count = info.field.count * func->cur_blksize; + if (count > MaxBufSize) { + DBGLOG(HAL, ERROR, "blk mode count(%d->%d), MaxSz(%d)\n", Size, count, MaxBufSize); + ASSERT(0); + } + } else { /* byte mode */ + info.field.block_mode = SDIO_GEN3_BYTE_MODE; + info.field.count = count; + } + + info.field.op_mode = SDIO_GEN3_FIXED_PORT_MODE; /* fix mode */ + info.field.addr = Port; + + DBGLOG(HAL, TRACE, "writesb use_dma(%d), count(%d->%d), blk_size(%d), port(0x%x), CMD_SETUP(0x%08x)\n", + func->use_dma, Size, count, func->cur_blksize, Port, info.word); + +#if (CONF_MTK_AHB_DMA == 1) + if (func->use_dma && (HifInfo->fgDmaEnable == TRUE) && (HifInfo->DmaOps != NULL) && + (Port == MCR_WTDR1)) { + /* move forward since clk_prepare_enable can only be called in non-atomic context */ + HifInfo->DmaOps->DmaClockCtrl(HifInfo, TRUE); + } +#endif + + my_sdio_disable(HifLock); + __disable_irq(); + + writel(info.word, (volatile UINT_32 *)(*g_pHifRegBaseAddr + SDIO_GEN3_CMD_SETUP)); + wmb(); + + /* 2. Write CMD53 port */ +#if (CONF_MTK_AHB_DMA == 1) + if (func->use_dma && (HifInfo->fgDmaEnable == TRUE) && (HifInfo->DmaOps != NULL) && + (Port == MCR_WTDR1)) { + /* only for data port */ +#ifdef MTK_DMA_BUF_MEMCPY_SUP + VOID *DmaVBuf = NULL, *DmaPBuf = NULL; +#endif /* MTK_DMA_BUF_MEMCPY_SUP */ + + /* 2.1 config DMA for data transmission */ + DmaConf.Count = count; + DmaConf.Dir = HIF_DMA_DIR_TX; + DmaConf.Dst = HifInfo->HifRegPhyBase + SDIO_GEN3_CMD53_DATA; /* must be physical addr */ + +#ifdef MTK_DMA_BUF_MEMCPY_SUP + DmaConf.Src = kalIOPhyAddrGet(Buf); /* must be physical addr */ + + /* TODO: use virt_to_phys() */ + if (DmaConf.Src == NULL) { + ASSERT(count <= CFG_RX_MAX_PKT_SIZE); + + kalDmaBufGet(&DmaVBuf, &DmaPBuf); + DmaConf.Src = (ULONG) DmaPBuf; + + kalMemCopy(DmaVBuf, Buf, count); + } +#else + /* DMA_TO_DEVICE writeback the cache */ + DmaConf.Src = dma_map_single(HifInfo->Dev, Buf, count, DMA_TO_DEVICE); + +#endif /* MTK_DMA_BUF_MEMCPY_SUP */ + + HifInfo->DmaOps->DmaConfig(HifInfo, &DmaConf); + /* 2.2 start DMA */ + HifInfo->DmaOps->DmaStart(HifInfo); + + /* 2.3 wait for DMA finish */ +#if (CONF_HIF_DMA_INT == 1) + if (wait_event_interruptible_timeout(HifInfo->HifDmaWaitq, HifInfo->HifDmaFinishFlag != 0, 1000) <= 0) { + if (HifInfo->DmaOps->DmaRegDump != NULL) + HifInfo->DmaOps->DmaRegDump(HifInfo); + DBGLOG(HAL, ERROR, "fatal error! reset DMA!\n"); + if (HifInfo->DmaOps->DmaReset != NULL) + HifInfo->DmaOps->DmaReset(HifInfo); + ret = FALSE; + goto DMA_DONE; + } + HifInfo->HifDmaFinishFlag = 0; +#else + { + ULONG PollTimeout = jiffies + HZ * 5; + + do { + if (time_before(jiffies, PollTimeout)) { + /* Do nothing */ + /* not timeout, continue to poll */ + } else { + if (HifInfo->DmaOps->DmaRegDump != NULL) + HifInfo->DmaOps->DmaRegDump(HifInfo); + +#if (CONF_HIF_CONNSYS_DBG == 0) + DBGLOG(HAL, ERROR, "fatal error! reset DMA!\n"); + if (HifInfo->DmaOps->DmaReset != NULL) + HifInfo->DmaOps->DmaReset(HifInfo); + ret = FALSE; + goto DMA_DONE; +#else + DBGLOG(HAL, WARN, "DMA timeout 5s... (%lu %lu)\n", jiffies, PollTimeout); + WlanDmaFatalErr = 1; + +#endif /* CONF_HIF_CONNSYS_DBG */ + } + } while (!HifInfo->DmaOps->DmaPollIntr(HifInfo)); + } +#endif /* CONF_HIF_DMA_INT */ + + /* 2.4 ack DMA interrupt */ + HifInfo->DmaOps->DmaAckIntr(HifInfo); + HifInfo->DmaOps->DmaStop(HifInfo); + +#if (CONF_HIF_DMA_INT == 1) + enable_irq(HifInfo->HifDmaIRQ); +#endif + +DMA_DONE: +#ifndef MTK_DMA_BUF_MEMCPY_SUP + dma_unmap_single(HifInfo->Dev, DmaConf.Src, count, DMA_TO_DEVICE); +#endif /* MTK_DMA_BUF_MEMCPY_SUP */ + + __enable_irq(); + my_sdio_enable(HifLock); + + /* move behind since clk_disable_unprepare can only be called in non-atomic context */ + HifInfo->DmaOps->DmaClockCtrl(HifInfo, FALSE); + + DBGLOG(HAL, TRACE, "DMA TX %s!\n", ret ? "OK" : "FAIL"); + } else +#endif /* CONF_MTK_AHB_DMA */ + { + /* PIO mode */ + u4DwNum = count >> 2; + p = (UINT_32 *) Buf; + + for (idx = 0; idx < u4DwNum; idx++) { + writel(*p, (volatile UINT_32 *)(*g_pHifRegBaseAddr + SDIO_GEN3_CMD53_DATA)); + DBGLOG(HAL, LOUD, "idx = %d, val = 0x%08x\n", idx, *p); + p++; + } + + __enable_irq(); + my_sdio_enable(HifLock); + + DBGLOG(HAL, TRACE, "PIO TX OK!\n"); + } + + return ret; +} /* end of kalDevPortWrite() */ + +/******************************************************************************* +* P R I V A T E F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a SDIO interrupt callback function +* +* \param[in] func pointer to SDIO handle +* +* \return void +*/ +/*----------------------------------------------------------------------------*/ +static irqreturn_t HifAhbISR(IN int irq, IN void *arg) +{ + struct net_device *prNetDevice = (struct net_device *)arg; + GLUE_INFO_T *prGlueInfo; + + ASSERT(prNetDevice); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDevice)); + if (!prGlueInfo) + return IRQ_HANDLED; + + prGlueInfo->u8HifIntTime = sched_clock(); + prGlueInfo->IsrCnt++; + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + __disable_irq(); + return IRQ_HANDLED; + } + + __disable_irq(); + + /* lock 100ms to avoid suspend */ + /* MT6797 TODO */ + /* kalHifAhbKalWakeLockTimeout(GlueInfo); */ + + set_bit(GLUE_FLAG_INT_BIT, &prGlueInfo->ulFlag); + + /* when we got HIF interrupt, we wake up hif thread */ +#if CFG_SUPPORT_MULTITHREAD + wake_up_interruptible(&prGlueInfo->waitq_hif); +#else + wake_up_interruptible(&prGlueInfo->waitq); +#endif + + prGlueInfo->IsrPassCnt++; + return IRQ_HANDLED; +} + +#if (CONF_HIF_DMA_INT == 1) +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a SDIO interrupt callback function +* +* \param[in] func pointer to SDIO handle +* +* \return void +*/ +/*----------------------------------------------------------------------------*/ + +static irqreturn_t HifDmaISR(IN int irq, IN void *arg) +{ + struct net_device *prNetDevice = (struct net_device *)arg; + GLUE_INFO_T *prGlueInfo; + GL_HIF_INFO_T *prHifInfo; + + ASSERT(prNetDevice); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDevice)); + if (!prGlueInfo) + return IRQ_HANDLED; + + prHifInfo = &prGlueInfo->rHifInfo; + + /* disable interrupt */ + disable_irq_nosync(irq); + + set_bit(1, &prHifInfo->HifDmaFinishFlag); + + /* When we got DMA finish interrupt, we wake up hif thread */ + wake_up_interruptible(&prHifInfo->HifDmaWaitq); + + return IRQ_HANDLED; +} +#endif /* CONF_HIF_DMA_INT */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a SDIO probe function +* +* \param[in] func pointer to SDIO handle +* \param[in] id pointer to SDIO device id table +* +* \return void +*/ +/*----------------------------------------------------------------------------*/ + +static int HifAhbProbe(VOID) +{ + int ret = 0; + + DBGLOG(INIT, TRACE, "HifAhbProbe()\n"); + + /* power on WiFi TX PA 3.3V and HIF GDMA clock */ + mtk_wcn_consys_hw_wifi_paldo_ctrl(1); /* switch to HW mode */ + +#if (CONF_HIF_DEV_MISC == 1) + if (pfWlanProbe((PVOID) &MtkAhbDriver.this_device) != WLAN_STATUS_SUCCESS) { +#else + if (pfWlanProbe((PVOID) &HifAhbPDev->dev) != WLAN_STATUS_SUCCESS) { +#endif /* CONF_HIF_DEV_MISC */ + + pfWlanRemove(); + ret = -1; + } + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do module remove. +* +* \param[in] None +* +* \return The result of remove (WLAN_STATUS_SUCCESS = 0) +*/ +/*----------------------------------------------------------------------------*/ +static int HifAhbRemove(VOID) +{ + + pfWlanRemove(); + + mtk_wcn_consys_hw_wifi_paldo_ctrl(0); /* switch to SW mode */ + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function gets the TX count pass through HIF AHB bus. +* +* \param[in] None +* +* \return TX count +*/ +/*----------------------------------------------------------------------------*/ +static int HifAhbBusCntGet(VOID) +{ + return HifTxCnt; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function resets the TX count pass through HIF AHB bus. +* +* \param[in] None +* +* \return 0 +*/ +/*----------------------------------------------------------------------------*/ +static int HifAhbBusCntClr(VOID) +{ + HifTxCnt = 0; + return 0; +} + +static int hifAhbSetMpuProtect(BOOLEAN enable) +{ + kalSetEmiMpuProtection(gConEmiPhyBase, WIFI_EMI_MEM_SIZE, enable); + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function check the status of wifi driver +* +* \param[in] None +* +* \return 1: drv_own, 0: fw_own +*/ +/*----------------------------------------------------------------------------*/ +static int HifAhbIsWifiDrvOwn(VOID) +{ + return (wlanIsFwOwn() == FALSE) ? 1 : 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function configs the DMA TX/RX settings before any real TX/RX. +* +* \param[in] GlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] BurstLen 0(1DW), 1(4DW), 2(8DW), Others(Reserved) +* \param[in] PortId 0(TXD0), 1(TXD1), 2(RXD0), 3(RXD1), 4(WHISR enhance) +* \param[in] TransByte Should be 4-byte align. +* +* \return void +*/ +/*----------------------------------------------------------------------------*/ + +VOID glSetPowerState(IN GLUE_INFO_T *GlueInfo, IN UINT_32 ePowerMode) +{ + +} + +#if (CONF_HIF_DEV_MISC == 1) +/* no use */ +static ssize_t HifAhbMiscRead(IN struct file *Filp, OUT char __user *DstBuf, IN size_t Size, IN loff_t *Ppos) +{ + return 0; +} + +static ssize_t HifAhbMiscWrite(IN struct file *Filp, IN const char __user *SrcBuf, IN size_t Size, IN loff_t *Ppos) +{ + return 0; +} + +static int HifAhbMiscIoctl(IN struct file *Filp, IN unsigned int Cmd, IN unsigned long arg) +{ + return 0; +} + +static int HifAhbMiscOpen(IN struct inode *Inodep, IN struct file *Filp) +{ + return 0; +} + +static int HifAhbMiscClose(IN struct inode *Inodep, IN struct file *Filp) +{ + return 0; +} +#else + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called by OS platform device module. +* +* \param[in] PDev Pointer to the platform device structure. +* +* \return 0 +*/ +/*----------------------------------------------------------------------------*/ +static int HifAhbPltmProbe(IN struct platform_device *pDev) +{ + struct MTK_WCN_WMT_WLAN_CB_INFO rWmtCb; + + DBGLOG(INIT, INFO, "HifAhbPltmProbe\n"); + + HifAhbPDev = pDev; + +#if (CONF_HIF_PMIC_TEST == 1) + wmt_set_jtag_for_mcu(); + wmt_set_jtag_for_gps(); +#endif /* CONF_HIF_PMIC_TEST */ + kalMemZero(&rWmtCb, sizeof(struct MTK_WCN_WMT_WLAN_CB_INFO)); + /* Register WIFI probe/remove functions to WMT */ + rWmtCb.wlan_probe_cb = HifAhbProbe; + rWmtCb.wlan_remove_cb = HifAhbRemove; + rWmtCb.wlan_bus_cnt_get_cb = HifAhbBusCntGet; + rWmtCb.wlan_bus_cnt_clr_cb = HifAhbBusCntClr; + rWmtCb.wlan_emi_mpu_set_protection_cb = hifAhbSetMpuProtect; + rWmtCb.wlan_is_wifi_drv_own_cb = HifAhbIsWifiDrvOwn; + mtk_wcn_wmt_wlan_reg(&rWmtCb); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called by OS platform device module. +* +* \param[in] PDev Pointer to the platform device structure. +* +* \return 0 +*/ +/*----------------------------------------------------------------------------*/ +static int HifAhbPltmRemove(IN struct platform_device *pDev) +{ + mtk_wcn_wmt_wlan_unreg(); + return 0; +} + +#ifdef CONFIG_PM +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called by OS platform device module. +* +* \param[in] PDev Pointer to the platform device structure. +* \param[in] Message +* +* \return 0 +*/ +/*----------------------------------------------------------------------------*/ +static int HifAhbPltmSuspend(IN struct platform_device *pDev, pm_message_t message) +{ + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called by OS platform device module. +* +* \param[in] PDev Pointer to the platform device structure. +* +* \return 0 +*/ +/*----------------------------------------------------------------------------*/ +static int HifAhbPltmResume(IN struct platform_device *pDev) +{ + return 0; +} +#endif /* CONFIG_PM */ + +#endif /* CONF_HIF_DEV_MISC */ + +#if (CONF_HIF_LOOPBACK_AUTO == 1) +/*----------------------------------------------------------------------------*/ +/*! +* \brief Trigger to do HIF loopback test. +* +* \param[in] arg Pointer to the GLUE_INFO_T structure. +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifAhbLoopbkAuto(IN unsigned long arg) +{ + + P_GLUE_INFO_T GlueInfo = (P_GLUE_INFO_T) arg; + GL_HIF_INFO_T *HifInfo = &GlueInfo->rHifInfo; + + ASSERT(GlueInfo); + + DBGLOG(HAL, INFO, "Trigger to do loopback test...\n"); + + set_bit(GLUE_FLAG_HIF_LOOPBK_AUTO_BIT, &HifInfo->HifLoopbkFlg); + wake_up_interruptible(&HifInfo->HifWaitq); +} +#endif /* CONF_HIF_LOOPBACK_AUTO */ +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to dump hif ahb information for DE to debug. +* +* \param prGlueInfo Pointer of GLUE_INFO_T Data Structure +* \param u2ChipID Chip id +* +* return (none) +*/ +/*----------------------------------------------------------------------------*/ +void kalDumpAhbDebugInfo(P_GLUE_INFO_T prGlueInfo, UINT_16 u2ChipID) +{ + /* Only call this in hif_thread. + * Multi-thread operate HIF CR may cause HIF abnormal. + */ + + UINT_32 val; + UINT_32 u4InfraPseOffset = 0x0394; + + DBGLOG(HAL, ERROR, "HIF_DBGCR00:0x%08X HIF_DBGCR01:0x%08X\n", + CONNSYS_REG_READ(prGlueInfo->rHifInfo.HifRegBaseAddr, + CONN_HIF_DBGCR00), + CONNSYS_REG_READ(prGlueInfo->rHifInfo.HifRegBaseAddr, + CONN_HIF_DBGCR01)); + DBGLOG(HAL, ERROR, "HIF_DBGCR02:0x%08X HIF_DBGCR04:0x%08X\n", + CONNSYS_REG_READ(prGlueInfo->rHifInfo.HifRegBaseAddr, + CONN_HIF_DBGCR02), + CONNSYS_REG_READ(prGlueInfo->rHifInfo.HifRegBaseAddr, + CONN_HIF_DBGCR04)); + DBGLOG(HAL, ERROR, "HIF_DBGCR08:0x%08X HIF_DBGCR10:0x%08X\n", + CONNSYS_REG_READ(prGlueInfo->rHifInfo.HifRegBaseAddr, + CONN_HIF_DBGCR08), + CONNSYS_REG_READ(prGlueInfo->rHifInfo.HifRegBaseAddr, + CONN_HIF_DBGCR10)); + DBGLOG(HAL, ERROR, "HIF_DBGCR11:0x%08X HIF_DBGCR12:0x%08X\n", + CONNSYS_REG_READ(prGlueInfo->rHifInfo.HifRegBaseAddr, + CONN_HIF_DBGCR11), + CONNSYS_REG_READ(prGlueInfo->rHifInfo.HifRegBaseAddr, + CONN_HIF_DBGCR12)); + + /* SET INFRA AO REMAPPING PSE Client REG according to Chip ID */ + switch (u2ChipID) { + case 0x6797: + u4InfraPseOffset = 0x0340; + break; + case 0x6759: + case 0x6758: + case 0x6775: + u4InfraPseOffset = 0x0384; + break; + case 0x6771: + u4InfraPseOffset = 0x0394; + break; + default: + DBGLOG(HAL, WARN, "Using default offset 0x%04x for chip id 0x%04x\n", + u4InfraPseOffset, u2ChipID); + break; + } + if (u2ChipID == 0x6771) { + val = 0x800c; + CONNSYS_REG_WRITE(prGlueInfo->rHifInfo.InfraRegBaseAddr, + u4InfraPseOffset, val); + } else { + val = 0x800c << 16; + CONNSYS_REG_WRITE(prGlueInfo->rHifInfo.InfraRegBaseAddr, u4InfraPseOffset, + CONNSYS_REG_READ(prGlueInfo->rHifInfo.InfraRegBaseAddr, + u4InfraPseOffset) | val); + } + val = 0x6; + CONNSYS_REG_WRITE(prGlueInfo->rHifInfo.ConnCfgRegBaseAddr, + CONN_REMAP_PSE_CLIENT_DBGCR, val); + DBGLOG(HAL, ERROR, + "PSE Client debug CR: 0x%08x\n", + CONNSYS_REG_READ(prGlueInfo->rHifInfo.ConnCfgRegBaseAddr, + CONN_REMAP_PSE_CLIENT_DBGCR)); + + val = 0x3; + CONNSYS_REG_WRITE(prGlueInfo->rHifInfo.ConnCfgRegBaseAddr, + CONN_REMAP_PSE_CLIENT_DBGCR, val); + DBGLOG(HAL, ERROR, + "PSE Client debug CR: 0x%08x\n", + CONNSYS_REG_READ(prGlueInfo->rHifInfo.ConnCfgRegBaseAddr, + CONN_REMAP_PSE_CLIENT_DBGCR)); + + val = 0x4; + CONNSYS_REG_WRITE(prGlueInfo->rHifInfo.ConnCfgRegBaseAddr, + CONN_REMAP_PSE_CLIENT_DBGCR, val); + DBGLOG(HAL, ERROR, + "PSE Client debug CR: 0x%08x\n", + CONNSYS_REG_READ(prGlueInfo->rHifInfo.ConnCfgRegBaseAddr, + CONN_REMAP_PSE_CLIENT_DBGCR)); + + val = 0x12; + CONNSYS_REG_WRITE(prGlueInfo->rHifInfo.ConnCfgRegBaseAddr, + CONN_REMAP_PSE_CLIENT_DBGCR, val); + DBGLOG(HAL, ERROR, + "PSE Client debug CR: 0x%08x\n", + CONNSYS_REG_READ(prGlueInfo->rHifInfo.ConnCfgRegBaseAddr, + CONN_REMAP_PSE_CLIENT_DBGCR)); + + val = 0x17; + CONNSYS_REG_WRITE(prGlueInfo->rHifInfo.ConnCfgRegBaseAddr, + CONN_REMAP_PSE_CLIENT_DBGCR, val); + DBGLOG(HAL, ERROR, + "PSE Client debug CR: 0x%08x\n", + CONNSYS_REG_READ(prGlueInfo->rHifInfo.ConnCfgRegBaseAddr, + CONN_REMAP_PSE_CLIENT_DBGCR)); + +} + +#if defined(MT6797) +PUINT_8 glRemapConnsysAddr(P_GLUE_INFO_T prGlueInfo, UINT_32 consysAddr, UINT_32 remapLength) +{ + /* 0x180E0000 is the customized address and can be remaped to any connsys address */ + PUINT_8 pucRemapCrAddr = NULL; + GL_HIF_INFO_T *hifInfo = &prGlueInfo->rHifInfo; + UINT_32 u4ConfCrValue = 0; + + u4ConfCrValue = readl(hifInfo->confRegBaseAddr); + if ((u4ConfCrValue & 0xFFFF0000) != 0x180E0000) { + DBGLOG(HAL, ERROR, "remap CR is used by others, value is %u\n", u4ConfCrValue); + return NULL; + } + u4ConfCrValue &= 0xFFFF; /* don't touch low 16 bits, since it is used by others */ + u4ConfCrValue |= consysAddr; /* the start address in connsys side */ + writel(u4ConfCrValue, hifInfo->confRegBaseAddr); + pucRemapCrAddr = ioremap(DYNAMIC_REMAP_BASE, remapLength); + return pucRemapCrAddr; +} + +VOID glUnmapConnsysAddr(P_GLUE_INFO_T prGlueInfo, PUINT_8 remapAddr, UINT_32 consysAddr) +{ + UINT_32 u4ConfCrValue = 0; + GL_HIF_INFO_T *hifInfo = &prGlueInfo->rHifInfo; + + iounmap(remapAddr); + u4ConfCrValue = readl(hifInfo->confRegBaseAddr); + if ((u4ConfCrValue & 0xFFFF0000) != consysAddr) { + DBGLOG(HAL, ERROR, + "remap configure CR is changed during we are using! new value is %u\n", + u4ConfCrValue); + return; + } + u4ConfCrValue &= 0xFFFF; + u4ConfCrValue |= DYNAMIC_REMAP_BASE; + writel(u4ConfCrValue, hifInfo->confRegBaseAddr); +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/ahb_cqdma.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/ahb_cqdma.c new file mode 100644 index 0000000000000..fc4506cd7adb8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/ahb_cqdma.c @@ -0,0 +1,493 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/******************************************************************************* +* C O M P I L E 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 /* constant of kernel version */ + +#include /* bitops.h */ + +#include /* struct timer_list */ +#include /* jiffies */ +#include /* udelay and mdelay macro */ + +#if CONFIG_ANDROID +#ifdef CONFIG_WAKELOCK +#include +#else +#include +#endif +#endif + +#include /* IRQT_FALLING */ + +#include /* struct net_device, struct net_device_stats */ +#include /* for eth_type_trans() function */ +#include /* struct iw_statistics */ +#include +#include /* struct in_device */ + +#include /* struct iphdr */ + +#include /* for memcpy()/memset() function */ +#include /* for offsetof() macro */ + +#include /* The proc filesystem constants/structures */ + +#include /* for rtnl_lock() and rtnl_unlock() */ +#include /* kthread_should_stop(), kthread_run() */ +#include /* for copy_from_user() */ +#include /* for firmware download */ +#include + +#include /* for kfifo interface */ +#include /* for cdev interface */ + +#include /* for firmware download */ + +#include + +#include /* readw and writew */ + +#include +#include + +#if defined(CONFIG_MTK_CLKMGR) +#include +#else +#include +#endif /* defined(CONFIG_MTK_CLKMGR) */ + +#ifdef CONFIG_OF +#include +#endif + +#include "gl_os.h" +#include "hif.h" +#include "hif_cqdma.h" + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* #define DMA_DEBUG_SUP */ +#define DMA_TAG "CQDMA> " + +#ifdef DMA_DEBUG_SUP +#define DMA_DBG(_fmt, ...) pr_info(DMA_TAG _fmt, ##__VA_ARGS__) +#else +#define DMA_DBG(_fmt, ...) +#endif /* DMA_DEBUG_SUP */ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static VOID HifCqdmaConfig(IN GL_HIF_INFO_T *HifInfo, IN MTK_WCN_HIF_DMA_CONF *Conf); + +static VOID HifCqdmaStart(IN GL_HIF_INFO_T *HifInfo); + +static VOID HifCqdmaStop(IN GL_HIF_INFO_T *HifInfo); + +static BOOL HifCqdmaPollStart(IN GL_HIF_INFO_T *HifInfo); + +static BOOL HifCqdmaPollIntr(IN GL_HIF_INFO_T *HifInfo); + +static VOID HifCqdmaAckIntr(IN GL_HIF_INFO_T *HifInfo); + +static VOID HifCqdmaClockCtrl(IN GL_HIF_INFO_T *HifInfo, IN BOOL fgEnable); + +static VOID HifCqdmaRegDump(IN GL_HIF_INFO_T *HifInfo); + +static VOID HifCqdmaReset(IN GL_HIF_INFO_T *HifInfo); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +GL_HIF_DMA_OPS_T HifCqdmaOps = { + .DmaConfig = HifCqdmaConfig, + .DmaStart = HifCqdmaStart, + .DmaStop = HifCqdmaStop, + .DmaPollStart = HifCqdmaPollStart, + .DmaPollIntr = HifCqdmaPollIntr, + .DmaAckIntr = HifCqdmaAckIntr, + .DmaClockCtrl = HifCqdmaClockCtrl, + .DmaRegDump = HifCqdmaRegDump, + .DmaReset = HifCqdmaReset +}; + +/******************************************************************************* +* P U B L I C F U N C T I O N S +******************************************************************************** +*/ + +VOID HifDmaInit(GL_HIF_INFO_T *HifInfo) +{ + /* + * CQDMA H/W can access 36-bit physical address, set DMA_MASK to 36 bit + * to avoid bounce buffering when using DMA. + * (If the physical region of allocated DRAM memory is considered not + * reachable by the device, dma_map_single will return a bounce buffer + * from IOTLB, device can only perform DMA to the bounce buffer, kernel + * does the extra copy between bounce buffer and VA is needed.) + */ + dma_set_mask(HifInfo->Dev, DMA_BIT_MASK(36)); + + /* IO remap DMA register memory */ +#ifdef CONFIG_OF + HifInfo->DmaRegBaseAddr = (PUINT_8)of_iomap(HifInfo->Dev->of_node, 1); +#else + HifInfo->DmaRegBaseAddr = ioremap(CQ_DMA_HIF_BASE, CQ_DMA_HIF_LENGTH); +#endif + /* Assign DMA operators */ + HifInfo->DmaOps = &HifCqdmaOps; + + /* Enable DMA mode */ + HifInfo->fgDmaEnable = TRUE; + +#if !defined(CONFIG_MTK_CLKMGR) +#ifdef CONFIG_OF + HifInfo->clk_wifi_dma = devm_clk_get(HifInfo->Dev, "wifi-dma"); + if (IS_ERR(HifInfo->clk_wifi_dma)) { + DBGLOG(INIT, ERROR, "[CCF]Cannot get HIF DMA clock\n"); + /* return PTR_ERR(HifInfo->clk_wifi_dma); */ + } + DBGLOG(INIT, TRACE, "[CCF]HIF DMA clock = %p\n", HifInfo->clk_wifi_dma); +#endif +#endif + + DMA_DBG("HIF DMA init ok!\n"); +} + +VOID HifDmaUnInit(GL_HIF_INFO_T *HifInfo) +{ + iounmap(HifInfo->DmaRegBaseAddr); +} + +/******************************************************************************* +* P R I V A T E F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Config CQDMA TX/RX behavior. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* \param[in] Param Pointer to the settings. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifCqdmaConfig(IN GL_HIF_INFO_T *HifInfo, IN MTK_WCN_HIF_DMA_CONF *Conf) +{ + UINT_32 RegVal; + ULONG addr_h; + + /* Assign fixed value */ + Conf->Burst = HIF_CQDMA_BURST_8_8; + Conf->Fix_en = FALSE; + Conf->Connect = HIF_CQDMA_CONNECT_SET1; + + /* CQ_DMA_HIF_CON */ + DMA_DBG("Conf->Dir = %d\n", Conf->Dir); + + RegVal = HIF_DMAR_READL(HifInfo, CQ_DMA_HIF_CON); + RegVal &= ~(CDH_CR_FIX8 | CDH_CR_BURST_LEN | CDH_CR_WRAP_EN | CDH_CR_WADDR_FIX_EN | + CDH_CR_RADDR_FIX_EN | CDH_CR_FIX_EN | CDH_CR_RESIDUE); + RegVal |= CDH_CR_FIX8; + RegVal |= (((Conf->Burst << CDH_CR_BURST_LEN_OFFSET) & CDH_CR_BURST_LEN) | + ((Conf->Fix_en << CDH_CR_FIX_EN_OFFSET) & CDH_CR_FIX_EN)); + if (Conf->Dir == HIF_DMA_DIR_RX) + RegVal |= CDH_CR_RESIDUE; /* CQDMA fix length 8 byte align to 4 byte align */ + + HIF_DMAR_WRITEL(HifInfo, CQ_DMA_HIF_CON, RegVal); + DMA_DBG("CQ_DMA_HIF_CON = 0x%08x\n", RegVal); + + /* CQ_DMA_HIF_CONNECT */ + RegVal = HIF_DMAR_READL(HifInfo, CQ_DMA_HIF_CONNECT); + RegVal &= ~(CDH_CR_DIR | CDH_CR_CONNECT); + RegVal |= (((Conf->Dir << CDH_CR_DIR_OFFSET) & CDH_CR_DIR) | + ((Conf->Connect) & CDH_CR_CONNECT)); + HIF_DMAR_WRITEL(HifInfo, CQ_DMA_HIF_CONNECT, RegVal); + DMA_DBG("CQ_DMA_HIF_CONNECT = 0x%08x\n", RegVal); + + /* CQ_DMA_HIF_SRC_ADDR2 */ + /* ulong is 32 bit on ILP32, and 64 bit on LP64. So on 32-bit OS platform, + * right shift 32 to ulong is forbidden, we just right shift 16 twice to replace. + * For 32-bit address, it should be 0 to fill in ADDR2 register. + */ + addr_h = Conf->Src >> 16; + addr_h = addr_h >> 16; + HIF_DMAR_WRITEL(HifInfo, CQ_DMA_HIF_SRC_ADDR2, (UINT_32)addr_h); + DMA_DBG("CQ_DMA_HIF_SRC_ADDR2 = 0x%08x\n", (UINT_32)addr_h); + + /* CQ_DMA_HIF_SRC_ADDR */ + HIF_DMAR_WRITEL(HifInfo, CQ_DMA_HIF_SRC_ADDR, (UINT_32)Conf->Src); + DMA_DBG("CQ_DMA_HIF_SRC_ADDR = 0x%08x\n", (UINT_32)Conf->Src); + + /* CQ_DMA_HIF_DST_ADDR2 */ + /* ulong is 32 bit on ILP32, and 64 bit on LP64. So on 32-bit OS platform, + * right shift 32 to ulong is forbidden, we just right shift 16 twice to replace. + * For 32-bit address, it should be 0 to fill in ADDR2 register. + */ + addr_h = Conf->Dst >> 16; + addr_h = addr_h >> 16; + HIF_DMAR_WRITEL(HifInfo, CQ_DMA_HIF_DST_ADDR2, (UINT_32)addr_h); + DMA_DBG("CQ_DMA_HIF_DST_ADDR2 = 0x%08x\n", (UINT_32)addr_h); + + /* CQ_DMA_HIF_DST_ADDR */ + HIF_DMAR_WRITEL(HifInfo, CQ_DMA_HIF_DST_ADDR, (UINT_32)Conf->Dst); + DMA_DBG("CQ_DMA_HIF_DST_ADDR = 0x%08x\n", (UINT_32)Conf->Dst); + + /* CQ_DMA_HIF_LEN1 */ + HIF_DMAR_WRITEL(HifInfo, CQ_DMA_HIF_LEN1, (UINT_32)(Conf->Count & CDH_CR_LEN)); + DMA_DBG("CQ_DMA_HIF_LEN1 = %u\n", (UINT_32)(Conf->Count & CDH_CR_LEN)); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Start CQDMA TX/RX. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifCqdmaStart(IN GL_HIF_INFO_T *HifInfo) +{ + UINT_32 RegVal; + + /* Enable interrupt */ + RegVal = HIF_DMAR_READL(HifInfo, CQ_DMA_HIF_INT_EN); + HIF_DMAR_WRITEL(HifInfo, CQ_DMA_HIF_INT_EN, (RegVal | CDH_CR_INTEN_FLAG)); + + /* Start DMA */ + RegVal = HIF_DMAR_READL(HifInfo, CQ_DMA_HIF_EN); + HIF_DMAR_WRITEL(HifInfo, CQ_DMA_HIF_EN, (RegVal | CDH_CR_EN)); + + DMA_DBG("HIF DMA start...\n"); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop CQDMA TX/RX. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifCqdmaStop(IN GL_HIF_INFO_T *HifInfo) +{ + UINT_32 RegVal, LoopCnt; + + /* Disable interrupt */ + RegVal = HIF_DMAR_READL(HifInfo, CQ_DMA_HIF_INT_EN); + HIF_DMAR_WRITEL(HifInfo, CQ_DMA_HIF_INT_EN, (RegVal & ~(CDH_CR_INTEN_FLAG))); + + /* Confirm DMA is stopped */ + if (HifCqdmaPollStart(HifInfo)) { + RegVal = HIF_DMAR_READL(HifInfo, CQ_DMA_HIF_STOP); + HIF_DMAR_WRITEL(HifInfo, CQ_DMA_HIF_STOP, (RegVal | CDH_CR_STOP)); + + /* Polling START bit turn to 0 */ + LoopCnt = 0; + do { + if (LoopCnt++ > 10000) { + /* Stop DMA failed, try to reset DMA */ + HifCqdmaReset(HifInfo); + break; + } + } while (HifCqdmaPollStart(HifInfo)); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Poll CQDMA enable bit. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval TRUE DMA is running +* FALSE DMA is stopped +*/ +/*----------------------------------------------------------------------------*/ +static BOOL HifCqdmaPollStart(IN GL_HIF_INFO_T *HifInfo) +{ + UINT_32 RegVal; + + RegVal = HIF_DMAR_READL(HifInfo, CQ_DMA_HIF_EN); + return ((RegVal & CDH_CR_EN) != 0) ? TRUE : FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Poll CQDMA interrupt flag. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval TRUE DMA finish +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +static BOOL HifCqdmaPollIntr(IN GL_HIF_INFO_T *HifInfo) +{ + UINT_32 RegVal; + + RegVal = HIF_DMAR_READL(HifInfo, CQ_DMA_HIF_INT_FLAG); + return ((RegVal & CDH_CR_INT_FLAG) != 0) ? TRUE : FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Acknowledge CQDMA interrupt flag. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifCqdmaAckIntr(IN GL_HIF_INFO_T *HifInfo) +{ + UINT_32 RegVal; + + /* Write 0 to clear interrupt */ + RegVal = HIF_DMAR_READL(HifInfo, CQ_DMA_HIF_INT_FLAG); + HIF_DMAR_WRITEL(HifInfo, CQ_DMA_HIF_INT_FLAG, (RegVal & ~CDH_CR_INT_FLAG)); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Enable/disable CQDMA clock. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* \param[in] fgEnable TRUE: enable; FALSE: disable +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifCqdmaClockCtrl(IN GL_HIF_INFO_T *HifInfo, IN BOOL fgEnable) +{ +#if defined(CONFIG_MTK_CLKMGR) + if (fgEnable == TRUE) + enable_clock(MT_CG_PERI_APDMA, "WLAN"); + else + disable_clock(MT_CG_PERI_APDMA, "WLAN"); +#else +#if CONFIG_OF +{ + int ret = 0; + + if (IS_ERR_OR_NULL(HifInfo->clk_wifi_dma)) + return; + + if (fgEnable == TRUE) { + ret = clk_prepare_enable(HifInfo->clk_wifi_dma); + if (ret) + DBGLOG(HAL, WARN, "[CCF]clk_prepare_enable return %d\n", ret); + } else + clk_disable_unprepare(HifInfo->clk_wifi_dma); +} +#endif +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Dump CQDMA related registers when abnormal, such as DMA timeout. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifCqdmaRegDump(IN GL_HIF_INFO_T *HifInfo) +{ + UINT_32 RegVal[4], RegOffset, Length; + UINT_32 idx = 0; + + Length = ((CQ_DMA_HIF_LENGTH + 15) & ~15u); /* Dump 16 bytes alignment length */ + + for (RegOffset = 0; RegOffset < Length; RegOffset += 4) { + RegVal[idx] = HIF_DMAR_READL(HifInfo, RegOffset); + + if (idx++ >= 3) { + DBGLOG(HAL, INFO, DMA_TAG "DUMP32 ADDRESS: 0x%08x\n", CQ_DMA_HIF_BASE + RegOffset - 12); + DBGLOG(HAL, INFO, "\t%08x %08x %08x %08x\n", RegVal[0], RegVal[1], RegVal[2], RegVal[3]); + idx = 0; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Reset CQDMA. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifCqdmaReset(IN GL_HIF_INFO_T *HifInfo) +{ + UINT_32 RegVal, LoopCnt; + + /* Do warm reset: DMA will wait for current transaction finished */ + DBGLOG(HAL, INFO, DMA_TAG "do warm reset...\n"); + + /* Normally, we need to make sure that bit0 of CQ_DMA_HIF_EN is 1 here */ + + RegVal = HIF_DMAR_READL(HifInfo, CQ_DMA_HIF_RST); + HIF_DMAR_WRITEL(HifInfo, CQ_DMA_HIF_RST, (RegVal | CDH_CR_WARM_RST)); + + for (LoopCnt = 0; LoopCnt < 10000; LoopCnt++) { + if (!HifCqdmaPollStart(HifInfo)) + break; /* reset ok */ + } + + if (HifCqdmaPollStart(HifInfo)) { + /* Do hard reset if warm reset fails */ + DBGLOG(HAL, INFO, DMA_TAG "do hard reset...\n"); + RegVal = HIF_DMAR_READL(HifInfo, CQ_DMA_HIF_RST); + HIF_DMAR_WRITEL(HifInfo, CQ_DMA_HIF_RST, (RegVal | CDH_CR_HARD_RST)); + HIF_DMAR_WRITEL(HifInfo, CQ_DMA_HIF_RST, (RegVal & ~CDH_CR_HARD_RST)); + } +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/ahb_pdma.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/ahb_pdma.c new file mode 100644 index 0000000000000..09af0fb58f1e3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/ahb_pdma.c @@ -0,0 +1,457 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/******************************************************************************* +* C O M P I L E 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 /* constant of kernel version */ + +#include /* bitops.h */ + +#include /* struct timer_list */ +#include /* jiffies */ +#include /* udelay and mdelay macro */ + +#if CONFIG_ANDROID +#ifdef CONFIG_WAKELOCK +#include +#else +#include +#endif +#endif + +#include /* IRQT_FALLING */ + +#include /* struct net_device, struct net_device_stats */ +#include /* for eth_type_trans() function */ +#include /* struct iw_statistics */ +#include +#include /* struct in_device */ + +#include /* struct iphdr */ + +#include /* for memcpy()/memset() function */ +#include /* for offsetof() macro */ + +#include /* The proc filesystem constants/structures */ + +#include /* for rtnl_lock() and rtnl_unlock() */ +#include /* kthread_should_stop(), kthread_run() */ +#include /* for copy_from_user() */ +#include /* for firmware download */ +#include + +#include /* for kfifo interface */ +#include /* for cdev interface */ + +#include /* for firmware download */ + +#include + +#include /* readw and writew */ + +#include +#include + +#if defined(CONFIG_MTK_CLKMGR) +#include +#else +#include +#endif /* defined(CONFIG_MTK_CLKMGR) */ + +#ifdef CONFIG_OF +#include +#endif + +#include "gl_os.h" +#include "hif.h" +#include "hif_pdma.h" + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* #define DMA_DEBUG_SUP */ +#define DMA_TAG "PDMA> " + +#ifdef DMA_DEBUG_SUP +#define DMA_DBG(_fmt, ...) pr_info(DMA_TAG _fmt, ##__VA_ARGS__) +#else +#define DMA_DBG(_fmt, ...) +#endif /* DMA_DEBUG_SUP */ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static VOID HifPdmaConfig(IN GL_HIF_INFO_T *HifInfo, IN MTK_WCN_HIF_DMA_CONF *Conf); + +static VOID HifPdmaStart(IN GL_HIF_INFO_T *HifInfo); + +static VOID HifPdmaStop(IN GL_HIF_INFO_T *HifInfo); + +static BOOL HifPdmaPollStart(IN GL_HIF_INFO_T *HifInfo); + +static BOOL HifPdmaPollIntr(IN GL_HIF_INFO_T *HifInfo); + +static VOID HifPdmaAckIntr(IN GL_HIF_INFO_T *HifInfo); + +static VOID HifPdmaClockCtrl(IN GL_HIF_INFO_T *HifInfo, IN BOOL fgEnable); + +static VOID HifPdmaRegDump(IN GL_HIF_INFO_T *HifInfo); + +static VOID HifPdmaReset(IN GL_HIF_INFO_T *HifInfo); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +GL_HIF_DMA_OPS_T HifPdmaOps = { + .DmaConfig = HifPdmaConfig, + .DmaStart = HifPdmaStart, + .DmaStop = HifPdmaStop, + .DmaPollStart = HifPdmaPollStart, + .DmaPollIntr = HifPdmaPollIntr, + .DmaAckIntr = HifPdmaAckIntr, + .DmaClockCtrl = HifPdmaClockCtrl, + .DmaRegDump = HifPdmaRegDump, + .DmaReset = HifPdmaReset +}; + +/******************************************************************************* +* P U B L I C F U N C T I O N S +******************************************************************************** +*/ + +VOID HifDmaInit(GL_HIF_INFO_T *HifInfo) +{ + /* IO remap DMA register memory */ +#ifdef CONFIG_OF + HifInfo->DmaRegBaseAddr = (PUINT_8)of_iomap(HifInfo->Dev->of_node, 1); +#else + HifInfo->DmaRegBaseAddr = ioremap(AP_DMA_HIF_BASE, AP_DMA_HIF_0_LENGTH); +#endif + + /* Assign DMA operators */ + HifInfo->DmaOps = &HifPdmaOps; + + /* Enable DMA mode */ + HifInfo->fgDmaEnable = TRUE; + +#if !defined(CONFIG_MTK_CLKMGR) +#ifdef CONFIG_OF + HifInfo->clk_wifi_dma = devm_clk_get(HifInfo->Dev, "wifi-dma"); + if (IS_ERR(HifInfo->clk_wifi_dma)) { + DBGLOG(INIT, ERROR, "[CCF]Cannot get HIF DMA clock\n"); + /* return PTR_ERR(HifInfo->clk_wifi_dma); */ + } + DBGLOG(INIT, INFO, "[CCF]HIF DMA clock = %p\n", HifInfo->clk_wifi_dma); +#endif +#endif + + DMA_DBG("HIF DMA init ok!\n"); +} + +VOID HifDmaUnInit(GL_HIF_INFO_T *HifInfo) +{ + iounmap(HifInfo->DmaRegBaseAddr); +} + +/******************************************************************************* +* P R I V A T E F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Config PDMA TX/RX behavior. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* \param[in] Param Pointer to the settings. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifPdmaConfig(IN GL_HIF_INFO_T *HifInfo, IN MTK_WCN_HIF_DMA_CONF *Conf) +{ + UINT_32 RegVal; + + /* Assign fixed value */ + Conf->Burst = HIF_PDMA_BURST_4_4; /* vs. HIF_BURST_4DW */ + Conf->Fix_en = FALSE; + + /* AP_DMA_HIF_0_CON */ + DMA_DBG("Conf->Dir = %d\n", Conf->Dir); + + /* AP_DMA_HIF_0_CON */ + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_CON); + RegVal &= ~(ADH_CR_BURST_INCR | ADH_CR_BURST_LEN | ADH_CR_FIX_EN | ADH_CR_DIR); + RegVal |= (((Conf->Burst << ADH_CR_BURST_LEN_OFFSET) & ADH_CR_BURST_LEN) | + (Conf->Fix_en << ADH_CR_FIX_EN_OFFSET) | (Conf->Dir)); + RegVal |= ADH_CR_BURST_INCR; + + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_CON, RegVal); + DMA_DBG("AP_DMA_HIF_0_CON = 0x%08x\n", RegVal); + + /* AP_DMA_HIF_0_SRC_ADDR */ + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_SRC_ADDR, Conf->Src); + DMA_DBG("AP_DMA_HIF_0_SRC_ADDR = 0x%08lx\n", Conf->Src); + + /* AP_DMA_HIF_0_DST_ADDR */ + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_DST_ADDR, Conf->Dst); + DMA_DBG("AP_DMA_HIF_0_DST_ADDR = 0x%08lx\n", Conf->Dst); + + /* AP_DMA_HIF_0_LEN */ + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_LEN, (Conf->Count & ADH_CR_LEN)); + DMA_DBG("AP_DMA_HIF_0_LEN = %u\n", Conf->Count & ADH_CR_LEN); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Start PDMA TX/RX. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifPdmaStart(IN GL_HIF_INFO_T *HifInfo) +{ + UINT_32 RegVal; + + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_SRC_ADDR2); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_SRC_ADDR2, (RegVal | ADH_CR_SRC_ADDR2)); + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_DST_ADDR2); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_DST_ADDR2, (RegVal | ADH_CR_DST_ADDR2)); + + /* Enable interrupt */ + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_INT_EN); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_INT_EN, (RegVal | ADH_CR_INTEN_FLAG_0)); + + /* Start DMA */ + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_EN); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_EN, (RegVal | ADH_CR_EN)); + + DMA_DBG("HIF DMA start...\n"); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop PDMA TX/RX. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifPdmaStop(IN GL_HIF_INFO_T *HifInfo) +{ + UINT_32 RegVal, LoopCnt; + + /* Disable interrupt */ + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_INT_EN); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_INT_EN, (RegVal & ~(ADH_CR_INTEN_FLAG_0))); + + /* Confirm DMA is stopped */ + if (HifPdmaPollStart(HifInfo)) { + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_STOP); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_STOP, (RegVal | ADH_CR_STOP)); + + /* Polling START bit turn to 0 */ + LoopCnt = 0; + do { + if (LoopCnt++ > 10000) { + /* Stop DMA failed, try to reset DMA */ + HifPdmaReset(HifInfo); + break; + } + } while (HifPdmaPollStart(HifInfo)); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Poll PDMA enable bit. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval TRUE DMA is running +* FALSE DMA is stopped +*/ +/*----------------------------------------------------------------------------*/ +static BOOL HifPdmaPollStart(IN GL_HIF_INFO_T *HifInfo) +{ + UINT_32 RegVal; + + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_EN); + return ((RegVal & ADH_CR_EN) != 0) ? TRUE : FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Poll PDMA interrupt flag. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval TRUE DMA finish +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +static BOOL HifPdmaPollIntr(IN GL_HIF_INFO_T *HifInfo) +{ + UINT_32 RegVal; + + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_INT_FLAG); + return ((RegVal & ADH_CR_FLAG_0) != 0) ? TRUE : FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Acknowledge PDMA interrupt flag. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifPdmaAckIntr(IN GL_HIF_INFO_T *HifInfo) +{ + UINT_32 RegVal; + + /* Write 0 to clear interrupt */ + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_INT_FLAG); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_INT_FLAG, (RegVal & ~ADH_CR_FLAG_0)); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Enable/disable PDMA clock. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* \param[in] fgEnable TRUE: enable; FALSE: disable +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifPdmaClockCtrl(IN GL_HIF_INFO_T *HifInfo, IN BOOL fgEnable) +{ +#if defined(CONFIG_MTK_CLKMGR) + if (fgEnable == TRUE) + enable_clock(MT_CG_PERI_APDMA, "WLAN"); + else + disable_clock(MT_CG_PERI_APDMA, "WLAN"); +#else +#if CONFIG_OF +{ + int ret = 0; + + if (IS_ERR_OR_NULL(HifInfo->clk_wifi_dma)) + return; + + if (fgEnable == TRUE) { + ret = clk_prepare_enable(HifInfo->clk_wifi_dma); + if (ret) + DBGLOG(HAL, WARN, "[CCF]clk_prepare_enable return %d\n", ret); + } else + clk_disable_unprepare(HifInfo->clk_wifi_dma); +} +#endif +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Dump PDMA related registers when abnormal, such as DMA timeout. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifPdmaRegDump(IN GL_HIF_INFO_T *HifInfo) +{ + UINT_32 RegVal[4], RegOffset, Length; + UINT_32 idx = 0; + + Length = ((AP_DMA_HIF_0_LENGTH + 15) & ~15u); /* Dump 16 bytes alignment length */ + + for (RegOffset = 0; RegOffset < Length; RegOffset += 4) { + RegVal[idx] = HIF_DMAR_READL(HifInfo, RegOffset); + + if (idx++ >= 3) { + DBGLOG(HAL, INFO, DMA_TAG "DUMP32 ADDRESS: 0x%08x\n", AP_DMA_HIF_BASE + RegOffset - 12); + DBGLOG(HAL, INFO, "\t%08x %08x %08x %08x\n", RegVal[0], RegVal[1], RegVal[2], RegVal[3]); + idx = 0; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Reset PDMA. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifPdmaReset(IN GL_HIF_INFO_T *HifInfo) +{ + UINT_32 RegVal, LoopCnt; + + /* Do warm reset: DMA will wait for current transaction finished */ + DBGLOG(HAL, INFO, DMA_TAG "do warm reset...\n"); + + /* Normally, we need to make sure that bit0 of AP_DMA_HIF_0_EN is 1 here */ + + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_RST); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_RST, (RegVal | ADH_CR_WARM_RST)); + + for (LoopCnt = 0; LoopCnt < 10000; LoopCnt++) { + if (!HifPdmaPollStart(HifInfo)) + break; /* reset ok */ + } + + if (HifPdmaPollStart(HifInfo)) { + /* Do hard reset if warm reset fails */ + DBGLOG(HAL, INFO, DMA_TAG "do hard reset...\n"); + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_RST); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_RST, (RegVal | ADH_CR_HARD_RST)); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_RST, (RegVal & ~ADH_CR_HARD_RST)); + } +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/arm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/arm.c new file mode 100644 index 0000000000000..a6054f7eeebf5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/arm.c @@ -0,0 +1,24 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/****************************************************************************** +*[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. +******************************************************************************/ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/include/hif.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/include/hif.h new file mode 100644 index 0000000000000..917b4f3bf11eb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/include/hif.h @@ -0,0 +1,282 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/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 + */ + +#ifndef _HIF_H +#define _HIF_H + +#include "gl_typedef.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#define CONF_MTK_AHB_DMA 1 /* PIO mode is default mode if DMA is disabled */ + +#define CONF_HIF_DEV_MISC 0 /* register as misc device */ +#define CONF_HIF_LOOPBACK_AUTO 0 /* hif loopback test triggered by open() */ + /* only for development test */ + +#define CONF_HIF_PMIC_TEST 0 /* test purpose: power on CONNSYS */ +#define CONF_HIF_CONNSYS_DBG 0 /* test purpose: when you want to use ICE on CONNSYS */ + +#define CONF_HIF_DMA_INT 0 /* DMA interrupt mode */ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +extern phys_addr_t gConEmiPhyBase; + +extern INT_32 mtk_wcn_consys_hw_wifi_paldo_ctrl(UINT_32 enable); + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define HIF_MOD_NAME "AHB_SLAVE_HIF" + +/* Vary between projects, already replaced by device tree */ +/* default value is for MT6797 */ +#define HIF_DRV_BASE 0x180F0000 +#define HIF_DRV_LENGTH 0x1100 + +/* CONN HIF Debug CR */ +#define CONN_HIF_DBGCR00 0x0300 +#define CONN_HIF_DBGCR01 0x0304 +#define CONN_HIF_DBGCR02 0x0308 +#define CONN_HIF_DBGCR04 0x0310 +#define CONN_HIF_DBGCR08 0x0320 +#define CONN_HIF_DBGCR10 0x0328 +#define CONN_HIF_DBGCR11 0x032C +#define CONN_HIF_DBGCR12 0x0330 + +/* CONN REMAP CFG CR */ +#define CONN_REMAP_CONF_BASE 0x180E0000 +#define CONN_REMAP_CONF_LENGTH 0x0070 +#define CONN_REMAP_PSE_CLIENT_DBGCR 0x006c + +/* MT6797 REMAP CR */ +#define DYNAMIC_REMAP_CONF_BASE 0x10001340 +#define DYNAMIC_REMAP_CONF_LENGTH 0x4 +#define DYNAMIC_REMAP_BASE 0x180E0000 + +/* INFRA AO Debug CR */ +#define INFRA_AO_DRV_BASE 0x10001000 +#define INFRA_AO_DRV_LENGTH 0x1000 + +#define INFRA_TOPAXI_PROTECTEN 0x0220 +#define INFRA_TOPAXI_PROTECTEN_STA1 0x0228 +#define INFRA_REMAP_TABLE_PSE_CLIENT 0x0340 + +#define MT_WF_HIF_IRQ_ID 283 +#define MT_WF_HIF_DMA_IRQ_ID 97 /* AP_DMA_HIF0_IRQ */ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/* + * host interface's private data structure, which is attached to os glue + * layer info structure. + */ +typedef struct _GL_HIF_DMA_OPS_T GL_HIF_DMA_OPS_T; + +typedef struct _GL_HIF_INFO_T { + + /* General */ + struct device *Dev; /* struct device */ + + /* Control flag */ + BOOLEAN fgIntReadClear; + BOOLEAN fgMbxReadClear; + BOOLEAN fgDmaEnable; /* TRUE: DMA mode is used (default) */ + + /* HIF related */ + UINT_8 *HifRegBaseAddr; /* HIF register base */ + ULONG HifRegPhyBase; /* HIF register base physical addr */ + UINT_8 *ConnCfgRegBaseAddr; /* CONN remap config register base */ + UINT_8 *InfraRegBaseAddr; /* the AP infra remap configure CR base */ + UINT_32 *confRegBaseAddr; /* the connsys/ap remap configure CR base */ + UINT_32 HifIRQ; +#if (CONF_HIF_LOOPBACK_AUTO == 1) + struct timer_list HifTmrLoopbkFn; /* HIF loopback test trigger timer */ + wait_queue_head_t HifWaitq; + UINT_32 HifLoopbkFlg; + struct task_struct *HifTaskLoopbkFn; /* HIF loopback test task */ +#endif /* CONF_HIF_LOOPBACK_AUTO */ + + /* DMA related */ +#if (CONF_HIF_DMA_INT == 1) + wait_queue_head_t HifDmaWaitq; + ULONG HifDmaFinishFlag; + UINT_32 HifDmaIRQ; +#endif /* CONF_HIF_DMA_INT */ + + UINT_8 *DmaRegBaseAddr; /* DMA register base */ + GL_HIF_DMA_OPS_T *DmaOps; /* DMA Operators */ + +#if !defined(CONFIG_MTK_CLKMGR) + struct clk *clk_wifi_dma; +#endif +} GL_HIF_INFO_T, *P_GL_HIF_INFO_T; + +typedef enum _MTK_WCN_HIF_BURST_LEN { + HIF_BURST_1DW = 0, + HIF_BURST_4DW, + HIF_BURST_8DW +} MTK_WCN_HIF_BURST_LEN; + +typedef enum _MTK_WCN_HIF_TXRX_TARGET { + HIF_TARGET_TXD0 = 0, + HIF_TARGET_TXD1, + HIF_TARGET_RXD0, + HIF_TARGET_RXD1, + HIF_TARGET_WHISR +} MTK_WCN_HIF_TXRX_TARGET; + +typedef enum _MTK_WCN_HIF_DMA_DIR { + HIF_DMA_DIR_TX = 0, + HIF_DMA_DIR_RX +} MTK_WCN_HIF_DMA_DIR; + +typedef struct _MTK_WCN_HIF_DMA_CONF { + UINT_32 Count; + MTK_WCN_HIF_DMA_DIR Dir; + UINT_32 Burst; + UINT_32 Wsize; + UINT_32 Fix_en; + UINT_32 Ratio; + UINT_32 Connect; + ULONG Src; + ULONG Dst; +} MTK_WCN_HIF_DMA_CONF; + +struct _GL_HIF_DMA_OPS_T { /* DMA Operators */ + VOID (*DmaConfig)(GL_HIF_INFO_T *HifInfo, MTK_WCN_HIF_DMA_CONF *Conf); + + VOID (*DmaStart)(GL_HIF_INFO_T *HifInfo); + + VOID (*DmaStop)(GL_HIF_INFO_T *HifInfo); + + BOOL (*DmaPollStart)(GL_HIF_INFO_T *HifInfo); + + BOOL (*DmaPollIntr)(GL_HIF_INFO_T *HifInfo); + + VOID (*DmaAckIntr)(GL_HIF_INFO_T *HifInfo); + + VOID (*DmaClockCtrl)(GL_HIF_INFO_T *HifInfo, BOOL fgEnable); + + VOID (*DmaRegDump)(GL_HIF_INFO_T *HifInfo); + + VOID (*DmaReset)(GL_HIF_INFO_T *HifInfo); + +}; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/* PIO mode HIF register read/write */ +#define HIF_REG_READL(_hif, _addr) \ + sdio_cr_readl((_hif)->HifRegBaseAddr, _addr) + +#define HIF_REG_WRITEL(_hif, _addr, _val) \ + sdio_cr_writel(_val, (_hif)->HifRegBaseAddr, _addr) + +/* PIO mode DMA register read/write */ +#define HIF_DMAR_READL(_hif, _addr) \ + readl((volatile UINT_32 *)((_hif)->DmaRegBaseAddr + _addr)) + +#define HIF_DMAR_WRITEL(_hif, _addr, _val) \ + writel(_val, (volatile UINT_32 *)((_hif)->DmaRegBaseAddr + _addr)) + +#define my_sdio_disable(__lock) \ +{\ + spin_lock_bh(&__lock); \ +} + +#define my_sdio_enable(__lock) \ +{\ + spin_unlock_bh(&__lock); \ +} + +#define CONNSYS_REG_READ(base_addr, offset) \ + readl((PUINT_32)((PUINT_8)base_addr + offset)) +#define CONNSYS_REG_WRITE(base_addr, offset, _val) \ + writel(_val, (PUINT_32)((PUINT_8)base_addr + offset)) + +/******************************************************************************* +* 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 glResetHif(GLUE_INFO_T *GlueInfo); + +VOID glSetHifInfo(P_GLUE_INFO_T prGlueInfo, ULONG ulCookie); + +VOID glClearHifInfo(P_GLUE_INFO_T prGlueInfo); + +BOOLEAN glBusInit(PVOID pvData); + +VOID glBusRelease(PVOID pData); + +INT_32 glBusSetIrq(PVOID pvData, PVOID pfnIsr, PVOID pvCookie); + +VOID glBusFreeIrq(PVOID pvData, PVOID pvCookie); + +VOID glSetPowerState(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 ePowerMode); + +#if defined(MT6797) + +PUINT_8 glRemapConnsysAddr(P_GLUE_INFO_T prGlueInfo, UINT_32 consysAddr, UINT_32 remapLength); + +VOID glUnmapConnsysAddr(P_GLUE_INFO_T prGlueInfo, PUINT_8 remapAddr, UINT_32 consysAddr); + +#endif + +VOID HifDmaInit(GL_HIF_INFO_T *HifInfo); + +VOID HifDmaUnInit(GL_HIF_INFO_T *HifInfo); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _HIF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/include/hif_cqdma.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/include/hif_cqdma.h new file mode 100644 index 0000000000000..3b47cfb42b2cc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/include/hif_cqdma.h @@ -0,0 +1,181 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/sdio/include/hif.h#1 +*/ + +/* + * ! \file "hif_pdma.h" + * \brief MARCO, definition, structure for PDMA. + * + * MARCO, definition, structure for PDMA. + */ + +#ifndef _HIF_CQDMA_H +#define _HIF_CQDMA_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef enum _MTK_WCN_HIF_CQDMA_BURST_LEN { + HIF_CQDMA_BURST_1_8 = 0, + HIF_CQDMA_BURST_2_8, + HIF_CQDMA_BURST_3_8, + HIF_CQDMA_BURST_4_8, + HIF_CQDMA_BURST_5_8, + HIF_CQDMA_BURST_6_8, + HIF_CQDMA_BURST_7_8, + HIF_CQDMA_BURST_8_8 +} MTK_WCN_HIF_CQDMA_BURST_LEN; + +typedef enum _MTK_WCN_HIF_CQDMA_RSIZE { + HIF_CQDMA_RSIZE_0 = 0, /* transaction size is 1 byte */ + HIF_CQDMA_RSIZE_1, /* transaction size is 2 byte */ + HIF_CQDMA_RSIZE_2, /* transaction size is 4 byte */ + HIF_CQDMA_RSIZE_3 /* transaction size is 1 byte */ +} MTK_WCN_HIF_CQDMA_RSIZE; + +typedef enum _MTK_WCN_HIF_CQDMA_WSIZE { + HIF_CQDMA_WSIZE_0 = 0, /* transaction size is 1 byte */ + HIF_CQDMA_WSIZE_1, /* transaction size is 2 byte */ + HIF_CQDMA_WSIZE_2, /* transaction size is 4 byte */ + HIF_CQDMA_WSIZE_3 /* transaction size is 1 byte */ +} MTK_WCN_HIF_CQDMA_WSIZE; + +typedef enum _MTK_WCN_HIF_CQDMA_CONNECT { + HIF_CQDMA_CONNECT_NO = 0, /* no connect */ + HIF_CQDMA_CONNECT_SET1, /* connect set1 (req/ack) */ + HIF_CQDMA_CONNECT_SET2, /* connect set2 (req/ack) */ + HIF_CQDMA_CONNECT_SET3 /* connect set3 (req/ack) */ +} MTK_WCN_HIF_CQDMA_CONNECT; + + +#define CQ_DMA_HIF_BASE 0x11200180 + +#define CQ_DMA_HIF_INT_FLAG (0x0000) /* CQ_DMA_G_DMA_3_INT_FLAG */ +#define CQ_DMA_HIF_INT_EN (0x0004) /* CQ_DMA_G_DMA_3_INT_EN */ +#define CQ_DMA_HIF_EN (0x0008) /* CQ_DMA_G_DMA_3_EN */ +#define CQ_DMA_HIF_RST (0x000C) /* CQ_DMA_G_DMA_3_RST */ +#define CQ_DMA_HIF_STOP (0x0010) /* CQ_DMA_G_DMA_3_STOP */ +#define CQ_DMA_HIF_FLUSH (0x0014) /* CQ_DMA_G_DMA_3_FLUSH */ +#define CQ_DMA_HIF_CON (0x0018) /* CQ_DMA_G_DMA_3_CON */ +#define CQ_DMA_HIF_SRC_ADDR (0x001C) /* CQ_DMA_G_DMA_3_SRC_ADDR */ +#define CQ_DMA_HIF_DST_ADDR (0x0020) /* CQ_DMA_G_DMA_3_DST_ADDR */ +#define CQ_DMA_HIF_LEN1 (0x0024) /* CQ_DMA_G_DMA_3_LEN1 */ +#define CQ_DMA_HIF_LEN2 (0x0028) /* CQ_DMA_G_DMA_3_LEN2 */ +#define CQ_DMA_HIF_JUMP_ADDR (0x002C) /* CQ_DMA_G_DMA_3_JUMP_ADDR */ +#define CQ_DMA_HIF_INT_BUF_SIZE (0x0030) /* CQ_DMA_G_DMA_3_INT_BUF_SIZE */ +#define CQ_DMA_HIF_CONNECT (0x0034) /* CQ_DMA_G_DMA_3_CONNECT */ +#define CQ_DMA_HIF_DEBUG_STATUS (0x0050) /* CQ_DMA_G_DMA_3_DEBUG_STATUS */ + +#define CQ_DMA_HIF_SRC_ADDR2 (0x0060) /* CQ_DMA_G_DMA_3_SRC_ADDR2 */ +#define CQ_DMA_HIF_DST_ADDR2 (0x0064) /* CQ_DMA_G_DMA_3_DST_ADDR2 */ +#define CQ_DMA_HIF_JUMP_ADDR2 (0x0068) /* CQ_DMA_G_DMA_3_JUMP_ADDR2 */ + +#define CQ_DMA_HIF_LENGTH 0x006C + +/* CQ_DMA_HIF_INT_FLAG */ +#define CDH_CR_INT_FLAG BIT(0) + +/* CQ_DMA_HIF_INT_EN */ +#define CDH_CR_INTEN_FLAG BIT(0) + +/* CQ_DMA_HIF_EN */ +#define CDH_CR_EN BIT(0) + +/* CQ_DMA_HIF_RST */ +#define CDH_CR_HARD_RST BIT(1) +#define CDH_CR_WARM_RST BIT(0) + +/* CQ_DMA_HIF_STOP */ +#define CDH_CR_PAUSE BIT(1) +#define CDH_CR_STOP BIT(0) + +/* CQ_DMA_HIF_FLUSH */ +#define CDH_CR_FLUSH BIT(0) + +/* CQ_DMA_HIF_CON */ +#define CDH_CR_FIX8 BIT(31) +#define CDH_CR_FIX8_OFFSET 31 +#define CDH_CR_RSIZE BITS(28, 29) +#define CDH_CR_RSIZE_OFFSET 28 +#define CDH_CR_WSIZE BITS(24, 25) +#define CDH_CR_WSIZE_OFFSET 24 +#define CDH_CR_WRAP_SEL BIT(20) +#define CDH_CR_WRAP_SEL_OFFSET 20 +#define CDH_CR_BURST_LEN BITS(16, 18) +#define CDH_CR_BURST_LEN_OFFSET 16 +#define CDH_CR_WRAP_EN BIT(15) +#define CDH_CR_WRAP_EN_OFFSET 15 +#define CDH_CR_SLOW_CNT BITS(5, 14) +#define CDH_CR_RADDR_FIX_EN BIT(4) +#define CDH_CR_RADDR_FIX_EN_OFFSET 4 +#define CDH_CR_WADDR_FIX_EN BIT(3) +#define CDH_CR_WADDR_FIX_EN_OFFSET 3 +#define CDH_CR_SLOW_EN BIT(2) +#define CDH_CR_FIX_EN BIT(1) +#define CDH_CR_FIX_EN_OFFSET 1 +#define CDH_CR_RESIDUE BIT(0) + +/* CQ_DMA_HIF_CONNECT */ +#define CDH_CR_DIR BIT(2) +#define CDH_CR_DIR_OFFSET 2 +#define CDH_CR_CONNECT BITS(0, 1) + +/* CQ_DMA_HIF_LEN */ +#define CDH_CR_LEN BITS(0, 19) + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _HIF_CQDMA_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/include/hif_pdma.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/include/hif_pdma.h new file mode 100644 index 0000000000000..6cac412e80f22 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/include/hif_pdma.h @@ -0,0 +1,143 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/sdio/include/hif.h#1 +*/ + +/* + * ! \file "hif_pdma.h" + * \brief MARCO, definition, structure for PDMA. + * + * MARCO, definition, structure for PDMA. + */ + +#ifndef _HIF_PDMA_H +#define _HIF_PDMA_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef enum _MTK_WCN_HIF_PDMA_BURST_LEN { + HIF_PDMA_BURST_1_4 = 0, + HIF_PDMA_BURST_2_4, + HIF_PDMA_BURST_3_4, + HIF_PDMA_BURST_4_4 +} MTK_WCN_HIF_PDMA_BURST_LEN; + +/* reference to Everest_APDMA_Spec.doc */ +#define AP_DMA_HIF_BASE 0x11000080 + +#define AP_DMA_HIF_0_INT_FLAG (0x0000) +#define AP_DMA_HIF_0_INT_EN (0x0004) +#define AP_DMA_HIF_0_EN (0x0008) +#define AP_DMA_HIF_0_RST (0x000C) +#define AP_DMA_HIF_0_STOP (0x0010) +#define AP_DMA_HIF_0_FLUSH (0x0014) +#define AP_DMA_HIF_0_CON (0x0018) +#define AP_DMA_HIF_0_SRC_ADDR (0x001C) +#define AP_DMA_HIF_0_DST_ADDR (0x0020) +#define AP_DMA_HIF_0_LEN (0x0024) +#define AP_DMA_HIF_0_INT_BUF_SIZE (0x0038) +#define AP_DMA_HIF_0_DEBUG_STATUS (0x0050) + +#define AP_DMA_HIF_0_SRC_ADDR2 (0x0054) +#define AP_DMA_HIF_0_DST_ADDR2 (0x0058) + +#define AP_DMA_HIF_0_LENGTH 0x0080 + +/* AP_DMA_HIF_0_INT_FLAG */ +#define ADH_CR_FLAG_0 BIT(0) + +/* AP_DMA_HIF_0_INT_EN */ +#define ADH_CR_INTEN_FLAG_0 BIT(0) + +/* AP_DMA_HIF_0_EN */ +#define ADH_CR_EN BIT(0) + +/* AP_DMA_HIF_0_RST */ +#define ADH_CR_HARD_RST BIT(1) +#define ADH_CR_WARM_RST BIT(0) + +/* AP_DMA_HIF_0_STOP */ +#define ADH_CR_PAUSE BIT(1) +#define ADH_CR_STOP BIT(0) + +/* AP_DMA_HIF_0_FLUSH */ +#define ADH_CR_FLUSH BIT(0) + +/* AP_DMA_HIF_0_CON */ +#define ADH_CR_BURST_INCR BIT(31) +#define ADH_CR_BURST_INCR_OFFSET 31 +#define ADH_CR_BURST_LEN BITS(16, 17) +#define ADH_CR_BURST_LEN_OFFSET 16 +#define ADH_CR_SLOW_CNT BITS(5, 14) +#define ADH_CR_SLOW_EN BIT(2) +#define ADH_CR_FIX_EN BIT(1) +#define ADH_CR_FIX_EN_OFFSET 1 +#define ADH_CR_DIR BIT(0) + +/* AP_DMA_HIF_0_LEN */ +#define ADH_CR_LEN BITS(0, 19) + +/* AP_DMA_HIF_0_SRC_ADDR2 */ +#define ADH_CR_SRC_ADDR2 BIT(0) + +/* AP_DMA_HIF_0_DST_ADDR2 */ +#define ADH_CR_DST_ADDR2 BIT(0) + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _HIF_PDMA_H */ + +/* End of hif_gdma.h */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/include/sdio.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/include/sdio.h new file mode 100644 index 0000000000000..503e2f78fe533 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/include/sdio.h @@ -0,0 +1,319 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef MMC_SDIO_H +#define MMC_SDIO_H + +/* ======================= PART 1: ahb_sdioLike operation ======================== */ + +#include "gl_typedef.h" +#include "mt6630_reg.h" + +#define SDIO_GEN3_BASE (0x0) +#define SDIO_GEN3_CMD_SETUP (SDIO_GEN3_BASE+0x0) +#define SDIO_GEN3_CMD3_DATA (SDIO_GEN3_BASE+0x8) +#define SDIO_GEN3_CMD5_DATA (SDIO_GEN3_BASE+0xC) +#define SDIO_GEN3_CMD7_DATA (SDIO_GEN3_BASE+0x10) +#define SDIO_GEN3_CMD11_DATA (SDIO_GEN3_BASE+0x14) +#define SDIO_GEN3_CMD52_DATA (SDIO_GEN3_BASE+0x4) +#define SDIO_GEN3_CMD53_DATA (SDIO_GEN3_BASE+0x1000) + +enum SDIO_GEN3_RW_TYPE { + SDIO_GEN3_READ, + SDIO_GEN3_WRITE +}; +enum SDIO_GEN3_TRANS_MODE { + SDIO_GEN3_BYTE_MODE, + SDIO_GEN3_BLOCK_MODE +}; +enum SDIO_GEN3_OP_MODE { + SDIO_GEN3_FIXED_PORT_MODE, + SDIO_GEN3_INCREMENT_MODE +}; + +enum SDIO_GEN3_FUNCTION { + SDIO_GEN3_FUNCTION_0, + SDIO_GEN3_FUNCTION_WIFI, + SDIO_GEN3_FUNCTION_BT, +}; + +typedef struct _sdio_irq_info_tag { + BOOLEAN irq_assert; + ENHANCE_MODE_DATA_STRUCT_T irq_data; +} sdio_irq_info_t; + +typedef struct _sdio_intr_enhance_arg_tag { + unsigned char rxNum; + unsigned char totalBytes; +} sdio_intr_enhance_arg_t; + +typedef union _sdio_gen3_cmd52_info { + struct{ + UINT32 data : 8; /* data for write, dummy for read */ + UINT32 reserved_8:1; /* stuff */ + UINT32 addr : 17; /* register address */ + UINT32 reserved_26_27 : 2; /* raw flag / stuff */ + UINT32 func_num : 3; /* function number */ + UINT32 rw_flag : 1; /* read / write flag */ + } field; + UINT32 word; +} sdio_gen3_cmd52_info; + +typedef union _sdio_gen3_cmd53_info { + struct { + UINT32 count : 9; /* block count for block mode, byte count for byte mode */ + UINT32 addr : 17; /* register address */ + UINT32 op_mode :1; /* 1 for increment mode, 0 for port mode */ + UINT32 block_mode : 1; /* 1 for block mode, 0 for byte mode */ + UINT32 func_num : 3; /* function number */ + UINT32 rw_flag : 1; /* read / write flag */ + } field; + UINT32 word; +} sdio_gen3_cmd53_info; + +struct sdio_func; +extern struct sdio_func g_sdio_func; +extern spinlock_t HifLock; +extern spinlock_t HifSdioLock; +extern int sdioDisableRefCnt; +typedef void (sdio_irq_handler_t)(struct sdio_func *); + +struct sdio_func { + sdio_irq_handler_t *irq_handler; /* IRQ callback */ + sdio_irq_info_t irq_info; + unsigned int num; /* function number */ + unsigned cur_blksize; /* current block size */ + unsigned use_dma; +}; + +#define LEN_SDIO_TX_TERMINATOR 4 /*HW design spec*/ +#define LEN_SDIO_RX_TERMINATOR 4 + +#define SDIO_HOST_REGISTER_VALUE_MAX 0x014C + +#define LEN_SDIO_TX_AGG_WRAPPER(len) ALIGN_4BYTE((len) + LEN_SDIO_TX_TERMINATOR) + + +/*=================== Function Declaration =====================*/ + +int sdio_cccr_read(UINT32 addr, UINT_8 *value); +int sdio_cccr_write(UINT32 addr, UINT_8 value); +int sdio_cr_read(UINT32 addr, UINT32 *value); +int sdio_cr_write(UINT32 addr, UINT32 value); + +UINT_32 sdio_cr_readl(volatile UINT_8 *prHifBaseAddr, UINT_32 addr); +VOID sdio_cr_writel(UINT_32 value, volatile UINT_8 *prHifBaseAddr, UINT_32 addr); + +int sdio_open(void); +int sdio_close(void); + + +unsigned char ahb_sdio_f0_readb(struct sdio_func *func, unsigned int addr, int *err_ret); +void ahb_sdio_f0_writeb(struct sdio_func *func, unsigned char b, unsigned int addr, int *err_ret); +int ahb_sdio_enable_func(struct sdio_func *func); +int ahb_sdio_disable_func(struct sdio_func *func); +int ahb_sdio_set_block_size(struct sdio_func *func, unsigned blksz); +int ahb_sdio_claim_irq(struct sdio_func *func, sdio_irq_handler_t *handler); + +#define sdio_f0_readb(func, addr, err_ret) ahb_sdio_f0_readb((func), (addr), (err_ret)) +#define sdio_f0_writeb(func, b, addr, err_ret) ahb_sdio_f0_writeb((func), (b), (addr), (err_ret)) +#define sdio_enable_func(func) ahb_sdio_enable_func((func)) +#define sdio_disable_func(func) ahb_sdio_disable_func((func)) +#define sdio_set_block_size(func, blksz) ahb_sdio_set_block_size((func), (blksz)) +#define sdio_claim_irq(func, handler) ahb_sdio_claim_irq((func), (handler)) + +#define sdio_claim_host(__func) +#define sdio_release_host(__func) + +#define MY_SDIO_BLOCK_SIZE 512 /* it must be less than or eaqual to 512 */ + +extern UINT_8 **g_pHifRegBaseAddr; + +#define __disable_irq() \ +{ \ + unsigned long ulFlags;\ +\ + spin_lock_irqsave(&HifSdioLock, ulFlags); \ + if (!sdioDisableRefCnt) \ + writel(0x01, (UINT_32 *)(*g_pHifRegBaseAddr + 0x200));\ + sdioDisableRefCnt++; \ + spin_unlock_irqrestore(&HifSdioLock, ulFlags); \ +} +#define __enable_irq() \ +{ \ + unsigned long ulFlags;\ +\ + spin_lock_irqsave(&HifSdioLock, ulFlags); \ + if (sdioDisableRefCnt == 1) { \ + sdioDisableRefCnt = 0; \ + writel(0, (UINT_32 *)(*g_pHifRegBaseAddr + 0x200));\ + } else if (sdioDisableRefCnt > 0) \ + sdioDisableRefCnt--; \ + spin_unlock_irqrestore(&HifSdioLock, ulFlags); \ +} + +/* =========================== PART 2: mmc/sdio.h ============================ */ +/* Following are from include/linux/mmc/sdio.h */ + + +/* SDIO commands type argument response */ +#define SD_IO_SEND_OP_COND 5 /* bcr [23:0] OCR R4 */ +#define SD_IO_RW_DIRECT 52 /* ac [31:0] See below R5 */ +#define SD_IO_RW_EXTENDED 53 /* adtc [31:0] See below R5 */ + +/* + * SD_IO_RW_DIRECT argument format: + * + * [31] R/W flag + * [30:28] Function number + * [27] RAW flag + * [25:9] Register address + * [7:0] Data + */ + +/* + * SD_IO_RW_EXTENDED argument format: + * + * [31] R/W flag + * [30:28] Function number + * [27] Block mode + * [26] Increment address + * [25:9] Register address + * [8:0] Byte/block count + */ + +#define R4_MEMORY_PRESENT (1 << 27) + +/* + * SDIO status in R5 + * Type + * e : error bit + * s : status bit + * r : detected and set for the actual command response + * x : detected and set during command execution. the host must poll + * the card by sending status command in order to read these bits. + * Clear condition + * a : according to the card state + * b : always related to the previous command. Reception of + * a valid command will clear it (with a delay of one command) + * c : clear by read + */ + +#define R5_COM_CRC_ERROR (1 << 15) /* er, b */ +#define R5_ILLEGAL_COMMAND (1 << 14) /* er, b */ +#define R5_ERROR (1 << 11) /* erx, c */ +#define R5_FUNCTION_NUMBER (1 << 9) /* er, c */ +#define R5_OUT_OF_RANGE (1 << 8) /* er, c */ +#define R5_STATUS(x) (x & 0xCB00) +#define R5_IO_CURRENT_STATE(x) ((x & 0x3000) >> 12) /* s, b */ + +/* + * Card Common Control Registers (CCCR) + */ + +#define SDIO_CCCR_CCCR 0x00 + +#define SDIO_CCCR_REV_1_00 0 /* CCCR/FBR Version 1.00 */ +#define SDIO_CCCR_REV_1_10 1 /* CCCR/FBR Version 1.10 */ +#define SDIO_CCCR_REV_1_20 2 /* CCCR/FBR Version 1.20 */ + +#define SDIO_SDIO_REV_1_00 0 /* SDIO Spec Version 1.00 */ +#define SDIO_SDIO_REV_1_10 1 /* SDIO Spec Version 1.10 */ +#define SDIO_SDIO_REV_1_20 2 /* SDIO Spec Version 1.20 */ +#define SDIO_SDIO_REV_2_00 3 /* SDIO Spec Version 2.00 */ + +#define SDIO_CCCR_SD 0x01 + +#define SDIO_SD_REV_1_01 0 /* SD Physical Spec Version 1.01 */ +#define SDIO_SD_REV_1_10 1 /* SD Physical Spec Version 1.10 */ +#define SDIO_SD_REV_2_00 2 /* SD Physical Spec Version 2.00 */ + +#define SDIO_CCCR_IOEx 0x02 +#define SDIO_CCCR_IORx 0x03 + +#define SDIO_CCCR_IENx 0x04 /* Function/Master Interrupt Enable */ +#define SDIO_CCCR_INTx 0x05 /* Function Interrupt Pending */ + +#define SDIO_CCCR_ABORT 0x06 /* function abort/card reset */ + +#define SDIO_CCCR_IF 0x07 /* bus interface controls */ + +#define SDIO_BUS_WIDTH_1BIT 0x00 +#define SDIO_BUS_WIDTH_4BIT 0x02 +#define SDIO_BUS_ECSI 0x20 /* Enable continuous SPI interrupt */ +#define SDIO_BUS_SCSI 0x40 /* Support continuous SPI interrupt */ + +#define SDIO_BUS_ASYNC_INT 0x20 + +#define SDIO_BUS_CD_DISABLE 0x80 /* disable pull-up on DAT3 (pin 1) */ + +#define SDIO_CCCR_CAPS 0x08 + +#define SDIO_CCCR_CAP_SDC 0x01 /* can do CMD52 while data transfer */ +#define SDIO_CCCR_CAP_SMB 0x02 /* can do multi-block xfers (CMD53) */ +#define SDIO_CCCR_CAP_SRW 0x04 /* supports read-wait protocol */ +#define SDIO_CCCR_CAP_SBS 0x08 /* supports suspend/resume */ +#define SDIO_CCCR_CAP_S4MI 0x10 /* interrupt during 4-bit CMD53 */ +#define SDIO_CCCR_CAP_E4MI 0x20 /* enable ints during 4-bit CMD53 */ +#define SDIO_CCCR_CAP_LSC 0x40 /* low speed card */ +#define SDIO_CCCR_CAP_4BLS 0x80 /* 4 bit low speed card */ + +#define SDIO_CCCR_CIS 0x09 /* common CIS pointer (3 bytes) */ + +/* Following 4 regs are valid only if SBS is set */ +#define SDIO_CCCR_SUSPEND 0x0c +#define SDIO_CCCR_SELx 0x0d +#define SDIO_CCCR_EXECx 0x0e +#define SDIO_CCCR_READYx 0x0f + +#define SDIO_CCCR_BLKSIZE 0x10 + +#define SDIO_CCCR_POWER 0x12 + +#define SDIO_POWER_SMPC 0x01 /* Supports Master Power Control */ +#define SDIO_POWER_EMPC 0x02 /* Enable Master Power Control */ + +#define SDIO_CCCR_SPEED 0x13 + +#define SDIO_SPEED_SHS 0x01 /* Supports High-Speed mode */ +#define SDIO_SPEED_EHS 0x02 /* Enable High-Speed mode */ + +/* + * Function Basic Registers (FBR) + */ + +#define SDIO_FBR_BASE(f) ((f) * 0x100) /* base of function f's FBRs */ + +#define SDIO_FBR_STD_IF 0x00 + +#define SDIO_FBR_SUPPORTS_CSA 0x40 /* supports Code Storage Area */ +#define SDIO_FBR_ENABLE_CSA 0x80 /* enable Code Storage Area */ + +#define SDIO_FBR_STD_IF_EXT 0x01 + +#define SDIO_FBR_POWER 0x02 + +#define SDIO_FBR_POWER_SPS 0x01 /* Supports Power Selection */ +#define SDIO_FBR_POWER_EPS 0x02 /* Enable (low) Power Selection */ + +#define SDIO_FBR_CIS 0x09 /* CIS pointer (3 bytes) */ + + +#define SDIO_FBR_CSA 0x0C /* CSA pointer (3 bytes) */ + +#define SDIO_FBR_CSA_DATA 0x0F + +#define SDIO_FBR_BLKSIZE 0x10 /* block size (2 bytes) */ + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/sdio_bus_driver.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/sdio_bus_driver.c new file mode 100644 index 0000000000000..464ea6a33bda8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ahb_sdioLike/sdio_bus_driver.c @@ -0,0 +1,434 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Module Name: + * sdio_bus_driver.c + * + * Abstract: + * Provide SDIO-GEN3 based bus driver routines + * + */ +#include +#include +#include "gl_os.h" +#include "debug.h" +#include "sdio.h" + +/* ========================== SDIO Private Routines ============================= */ + +struct sdio_func g_sdio_func; + +int sdio_open(void) +{ + struct sdio_func *func = &g_sdio_func; + INT_32 ret = 0; + + func->num = SDIO_GEN3_FUNCTION_WIFI; + func->use_dma = 1;/* 1 for DMA mode, 0 for PIO mode */ + + /* function enable */ + sdio_claim_host(func); + ret = sdio_enable_func(func); + sdio_release_host(func); + if (ret) { + DBGLOG(HAL, ERROR, "Enable function failed, error %d\n", ret); + goto err; + } + + /* set block size */ + sdio_claim_host(func); + ret = sdio_set_block_size(func, MY_SDIO_BLOCK_SIZE); + sdio_release_host(func); + if (ret) { + DBGLOG(HAL, ERROR, "Set block size failed, error %d\n", ret); + goto err; + } + + /* register sdio irq */ + sdio_claim_host(func); + ret = sdio_claim_irq(func, NULL); /* Interrupt IRQ handler */ + sdio_release_host(func); + if (ret) { + DBGLOG(HAL, ERROR, "Claim irq failed, error %d\n", ret); + goto err; + } + +err: + return ret; +} + +int sdio_cccr_read(UINT_32 addr, UINT_8 *value) +{ + + INT_32 ret = 0; + struct sdio_func *dev_func = &g_sdio_func; + + sdio_claim_host(dev_func); + *value = sdio_f0_readb(dev_func, addr, &ret); + sdio_release_host(dev_func); + + return ret; +} + + +int sdio_cccr_write(UINT_32 addr, UINT_8 value) +{ + INT_32 ret = 0; + struct sdio_func *dev_func = &g_sdio_func; + + sdio_claim_host(dev_func); + sdio_f0_writeb(dev_func, value, addr, &ret); + sdio_release_host(dev_func); + + return ret; +} + + +/** + * sdio_cr_readl - read a 32 bit integer from HIF controller driver domain register + * @prHifBaseAddr: HIF host address virtual base + * @addr: HIF controller address to read + * + * Reads a 32 bit integer from the address space of HIF controller + * driver domain register in SDIO function via CMD53. + */ +UINT_32 sdio_cr_readl(volatile UINT_8 *prHifBaseAddr, UINT_32 addr) +{ + UINT_32 value; + sdio_gen3_cmd53_info info; + struct sdio_func *func = &g_sdio_func; + + /* 1. Setup command information */ + info.word = 0; + info.field.rw_flag = SDIO_GEN3_READ; + info.field.func_num = func->num; + info.field.block_mode = SDIO_GEN3_BYTE_MODE; + info.field.op_mode = SDIO_GEN3_FIXED_PORT_MODE; /* fix mode to read 4-byte CR */ + info.field.addr = addr; + info.field.count = 4; + + my_sdio_disable(HifLock); + __disable_irq(); + + writel(info.word, (volatile UINT_32 *)(prHifBaseAddr + SDIO_GEN3_CMD_SETUP)); + + /* 2. Read CMD53 port to retrieve SDIO function CR value */ + value = readl((volatile UINT_32 *)(prHifBaseAddr + SDIO_GEN3_CMD53_DATA)); + + __enable_irq(); + my_sdio_enable(HifLock); + + DBGLOG(HAL, TRACE, "readl f%d 0x%08x = 0x%08x\n", func->num, addr, value); + return value; +} + +/** + * sdio_cr_writel - write a 32 bit integer to HIF controller driver domain register + * @value: integer to write + * @prHifBaseAddr: HIF host address virtual base + * @addr: HIF controller address to write to + * + * Writes a 32 bit integer to the address space of HIF controller + * driver domain register in SDIO function via CMD53. + */ +VOID sdio_cr_writel(UINT_32 value, volatile UINT_8 *prHifBaseAddr, UINT_32 addr) +{ + sdio_gen3_cmd53_info info; + struct sdio_func *func = &g_sdio_func; + + /* 1. Setup command information */ + info.word = 0; + info.field.rw_flag = SDIO_GEN3_WRITE; + info.field.func_num = func->num; + info.field.block_mode = SDIO_GEN3_BYTE_MODE; + info.field.op_mode = SDIO_GEN3_FIXED_PORT_MODE; /* fix mode to write 4-byte CR */ + info.field.addr = addr; + info.field.count = 4; + + my_sdio_disable(HifLock); + __disable_irq(); + + writel(info.word, (volatile UINT_32 *)(prHifBaseAddr + SDIO_GEN3_CMD_SETUP)); + + /* 2. Write CMD53 port to set SDIO function CR value */ + writel(value, (volatile UINT_32 *)(prHifBaseAddr + SDIO_GEN3_CMD53_DATA)); + + __enable_irq(); + my_sdio_enable(HifLock); + + DBGLOG(HAL, TRACE, "writel f%d 0x%08x = 0x%08x\n", func->num, addr, value); +} + + +unsigned char ahb_sdio_f0_readb(struct sdio_func *func, unsigned int addr, + int *err_ret) +{ + unsigned char val; + sdio_gen3_cmd52_info info; + + info.word = 0; + /* CMD52 read 1-byte of func0 */ + + if (err_ret) + *err_ret = 0; + + /* 1. Setup command information */ + info.field.rw_flag = SDIO_GEN3_READ; + info.field.func_num = 0; + info.field.addr = addr; + + my_sdio_disable(HifLock); + __disable_irq(); + + writel(info.word, (volatile UINT_32 *)(SDIO_GEN3_CMD_SETUP + *g_pHifRegBaseAddr)); + val = readl((volatile UINT_32 *)(SDIO_GEN3_CMD52_DATA + *g_pHifRegBaseAddr)); + + __enable_irq(); + my_sdio_enable(HifLock); + + DBGLOG(HAL, TRACE, "readb f0 0x%08x = 0x%02x\n", addr, val); + return val; +} + +/** + * sdio_f0_writeb - write a single byte to SDIO function 0 + * @func: an SDIO function of the card + * @b: byte to write + * @addr: address to write to + * @err_ret: optional status value from transfer + * + * Writes a single byte to the address space of SDIO function 0. + * @err_ret will contain the status of the actual transfer. + * + * Only writes to the vendor specific CCCR registers (0xF0 - + * 0xFF) are permiited; @err_ret will be set to -EINVAL for * + * writes outside this range. + */ +void ahb_sdio_f0_writeb(struct sdio_func *func, unsigned char b, unsigned int addr, + int *err_ret) +{ + sdio_gen3_cmd52_info info; + + info.word = 0; + /* CMD52 write 1-byte of func0 */ + + if (err_ret) + *err_ret = 0; + + /* 1. Setup command information */ + info.field.rw_flag = SDIO_GEN3_WRITE; + info.field.func_num = 0; + info.field.addr = addr; + info.field.data = b; + + my_sdio_disable(HifLock); + __disable_irq(); + + writel(info.word, (volatile UINT_32 *)(SDIO_GEN3_CMD_SETUP + *g_pHifRegBaseAddr)); + writel(b, (volatile UINT_32 *)(SDIO_GEN3_CMD52_DATA + *g_pHifRegBaseAddr)); + + __enable_irq(); + my_sdio_enable(HifLock); + + DBGLOG(HAL, TRACE, "writeb f0 0x%08x = 0x%02x\n", addr, b); +} + + +/** + * sdio_enable_func - enables a SDIO function for usage + * @func: SDIO function to enable + * + * Powers up and activates a SDIO function so that register + * access is possible. + */ +int ahb_sdio_enable_func(struct sdio_func *func) +{ + int ret; + unsigned char reg; + + DBGLOG(HAL, TRACE, "SDIO: Enabling func%d...\n", func->num); + + reg = sdio_f0_readb(func, SDIO_CCCR_IOEx, &ret); + if (ret) + goto err; + + reg |= 1 << func->num; + + sdio_f0_writeb(func, reg, SDIO_CCCR_IOEx, &ret); + if (ret) + goto err; + + reg = sdio_f0_readb(func, SDIO_CCCR_IORx, &ret); + if (ret) + goto err; + + if (!(reg & (1 << func->num))) { + ret = -ETIME; + goto err; + } + + DBGLOG(HAL, TRACE, "SDIO: Enabled func%d\n", func->num); + return 0; + +err: + DBGLOG(HAL, TRACE, "SDIO: Failed to enable func%d\n", func->num); + return ret; +} + + +/** + * sdio_disable_func - disable a SDIO function + * @func: SDIO function to disable + * + * Powers down and deactivates a SDIO function. Register access + * to this function will fail until the function is reenabled. + */ +int ahb_sdio_disable_func(struct sdio_func *func) +{ + int ret; + unsigned char reg; + + DBGLOG(HAL, TRACE, "SDIO: Disabling func%d...\n", func->num); + + reg = sdio_f0_readb(func, SDIO_CCCR_IOEx, &ret); + if (ret) + goto err; + + reg &= ~(1 << func->num); + + sdio_f0_writeb(func, reg, SDIO_CCCR_IOEx, &ret); + if (ret) + goto err; + + DBGLOG(HAL, TRACE, "SDIO: Disabled func%d\n", func->num); + + return 0; + +err: + DBGLOG(HAL, TRACE, "SDIO: Failed to disable func%d\n", func->num); + return ret; +} + +/** + * sdio_set_block_size - set the block size of an SDIO function + * @func: SDIO function to change + * @blksz: new block size or 0 to use the default. + * + * The default block size is the largest supported by both the function + * and the host, with a maximum of 512 to ensure that arbitrarily sized + * data transfer use the optimal (least) number of commands. + * + * A driver may call this to override the default block size set by the + * core. This can be used to set a block size greater than the maximum + * that reported by the card; it is the driver's responsibility to ensure + * it uses a value that the card supports. + * + * Returns 0 on success, -EINVAL if the host does not support the + * requested block size, or -EIO (etc.) if one of the resultant FBR block + * size register writes failed. + * + */ +int ahb_sdio_set_block_size(struct sdio_func *func, unsigned blksz) +{ + int ret; + + sdio_f0_writeb(func, (blksz & 0xff), + SDIO_FBR_BASE(func->num) + SDIO_FBR_BLKSIZE, &ret); + + if (ret) + return ret; + + sdio_f0_writeb(func, ((blksz >> 8) & 0xff), + SDIO_FBR_BASE(func->num) + SDIO_FBR_BLKSIZE + 1, &ret); + + if (ret) + return ret; + + func->cur_blksize = blksz; + + return 0; +} + +/** + * sdio_claim_irq - claim the IRQ for a SDIO function + * @func: SDIO function + * @handler: IRQ handler callback + * + * Claim and activate the IRQ for the given SDIO function. The provided + * handler will be called when that IRQ is asserted. The host is always + * claimed already when the handler is called so the handler must not + * call sdio_claim_host() nor sdio_release_host(). + */ +int ahb_sdio_claim_irq(struct sdio_func *func, sdio_irq_handler_t *handler) +{ + int ret; + unsigned char reg = 0; + + DBGLOG(HAL, TRACE, "SDIO: Enabling IRQ for func%d...\n", func->num); + + if (func->irq_handler) { + DBGLOG(HAL, TRACE, "SDIO: IRQ for func%d already in use.\n", func->num); + return -EBUSY; + } + + reg = sdio_f0_readb(func, SDIO_CCCR_IENx, &ret); + if (ret) + return ret; + + reg |= 1 << func->num; + + reg |= 1; /* Master interrupt enable */ + + sdio_f0_writeb(func, reg, SDIO_CCCR_IENx, &ret); + if (ret) + return ret; + + func->irq_handler = handler; + + return ret; +} + +/** + * sdio_release_irq - release the IRQ for a SDIO function + * @func: SDIO function + * + * Disable and release the IRQ for the given SDIO function. + */ +int ahb_sdio_release_irq(struct sdio_func *func) +{ + int ret; + unsigned char reg = 0; + + DBGLOG(HAL, TRACE, "SDIO: Disabling IRQ for func%d...\n", func->num); + + if (func->irq_handler) + func->irq_handler = NULL; + + reg = sdio_f0_readb(func, SDIO_CCCR_IENx, &ret); + if (ret) + return ret; + + reg &= ~(1 << func->num); + + /* Disable master interrupt with the last function interrupt */ + if (!(reg & 0xFE)) + reg = 0; + + sdio_f0_writeb(func, reg, SDIO_CCCR_IENx, &ret); + if (ret) + return ret; + + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ehpi/arm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ehpi/arm.c new file mode 100644 index 0000000000000..d379c44eda0de --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ehpi/arm.c @@ -0,0 +1,506 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/ehpi/arm.c#1 +*/ + +/* + * ! \file "colibri.c" + * \brief Brief description. + * + * Detail description. + */ + +/****************************************************************************** +* C O M P I L E R F L A G S +******************************************************************************* +*/ +#if !defined(MCR_EHTCR) +#define MCR_EHTCR 0x0054 +#endif + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "colibri.h" +#include "wlan_lib.h" + +/******************************************************************************* +* 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 void __iomem *mt5931_mcr_base; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#if CFG_EHPI_FASTER_BUS_TIMING +#define EHPI_CONFIG MSC_CS(4, MSC_RBUFF_SLOW | \ + MSC_RRR(4) | \ + MSC_RDN(8) | \ + MSC_RDF(7) | \ + MSC_RBW_16 | \ + MSC_RT_VLIO) +#else +#define EHPI_CONFIG MSC_CS(4, MSC_RBUFF_SLOW | \ + MSC_RRR(7) | \ + MSC_RDN(13) | \ + MSC_RDF(12) | \ + MSC_RBW_16 | \ + MSC_RT_VLIO) +#endif /* CFG_EHPI_FASTER_BUS_TIMING */ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static VOID collibri_ehpi_reg_init(VOID); + +static VOID collibri_ehpi_reg_uninit(VOID); + +static VOID mt5931_ehpi_reg_init(VOID); + +static VOID mt5931_ehpi_reg_uninit(VOID); + +static void busSetIrq(void); + +static void busFreeIrq(void); + +static irqreturn_t glEhpiInterruptHandler(int irq, void *dev_id); + +#if DBG +static void initTrig(void); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will register sdio bus to the os +* +* \param[in] pfProbe Function pointer to detect card +* \param[in] pfRemove Function pointer to remove card +* +* \return The result of registering sdio bus +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS glRegisterBus(probe_card pfProbe, remove_card pfRemove) +{ + + ASSERT(pfProbe); + ASSERT(pfRemove); + + DBGLOG(INIT, INFO, "mtk_sdio: MediaTek eHPI WLAN driver\n"); + DBGLOG(INIT, INFO, "mtk_sdio: Copyright MediaTek Inc.\n"); + + if (pfProbe(NULL) != WLAN_STATUS_SUCCESS) { + pfRemove(); + return WLAN_STATUS_FAILURE; + } + + return WLAN_STATUS_SUCCESS; +} /* 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(); + + /* TODO: eHPI uninitialization */ + +} /* 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, ULONG ulCookie) +{ + P_GL_HIF_INFO_T prHif = NULL; + + ASSERT(prGlueInfo); + + prHif = &prGlueInfo->rHifInfo; + + /* fill some buffered information into prHif */ + prHif->mcr_addr_base = mt5931_mcr_base + EHPI_OFFSET_ADDR; + prHif->mcr_data_base = mt5931_mcr_base + EHPI_OFFSET_DATA; + +} /* 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; + + /* do something */ + prHif->mcr_addr_base = 0; + prHif->mcr_data_base = 0; + +} /* 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 DBG + initTrig(); +#endif + + /* 1. initialize eHPI control registers */ + collibri_ehpi_reg_init(); + + /* 2. memory remapping for MT5931 */ + mt5931_ehpi_reg_init(); + + return TRUE; +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus operation and release resources. +* +* \param[in] pvData A pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glBusRelease(PVOID pvData) +{ + /* 1. memory unmapping for MT5931 */ + mt5931_ehpi_reg_uninit(); + + /* 2. uninitialize eHPI control registers */ + collibri_ehpi_reg_uninit(); + +} /* 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) +{ + struct net_device *pDev = (struct net_device *)pvData; + int i4Status = 0; + + /* 1. enable GPIO pin as IRQ */ + busSetIrq(); + + /* 2. Specify IRQ number into net_device */ + pDev->irq = WLAN_STA_IRQ; + + /* 3. register ISR callback */ + + i4Status = request_irq(pDev->irq, + glEhpiInterruptHandler, + IRQF_DISABLED | IRQF_SHARED | IRQF_TRIGGER_FALLING, pDev->name, pvCookie); + + if (i4Status < 0) + DBGLOG(IRQ, ERROR, "request_irq(%d) failed\n", pDev->irq); + else + DBGLOG(IRQ, INFO, "request_irq(%d) success with dev_id(%x)\n", pDev->irq, (unsigned int)pvCookie); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus interrupt operation and disable interrupt handling for os. +* +* \param[in] pvData A pointer to struct net_device. +* \param[in] pvCookie Private data for pfnIsr function. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glBusFreeIrq(PVOID pvData, PVOID pvCookie) +{ + struct net_device *prDev = (struct net_device *)pvData; + + if (!prDev) { + DBGLOG(IRQ, INFO, "Invalid net_device context.\n"); + return; + } + + if (prDev->irq) { + disable_irq(prDev->irq); + free_irq(prDev->irq, pvCookie); + prDev->irq = 0; + } + + busFreeIrq(); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set power state +* +* \param[in] pvGlueInfo A pointer to GLUE_INFO_T +* \param[in] ePowerMode Power Mode Setting +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glSetPowerState(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 ePowerMode) +{ +} + +#if DBG +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setup the GPIO pin. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void setTrig(void) +{ + GPSR1 = (0x1UL << 8); +} /* end of setTrig() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Clear the GPIO pin. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void clearTrig(void) +{ + GPCR1 = (0x1UL << 8); +} /* end of clearTrig() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set a specified GPIO pin to H or L. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static void initTrig(void) +{ + set_GPIO_mode(GPIO40_FFDTR | GPIO_OUT); + clearTrig(); +} /* end of initTrig() */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function congifure platform-dependent interrupt triger type. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void busSetIrq(void) +{ +#if defined(WLAN_STA_IRQ_GPIO) + pxa_gpio_mode(WLAN_STA_IRQ_GPIO | GPIO_IN); + set_irq_type(WLAN_STA_IRQ, IRQT_FALLING); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function should restore settings changed by busSetIrq(). +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void busFreeIrq(void) +{ +#if defined(WLAN_STA_IRQ_GPIO) + pxa_gpio_mode(WLAN_STA_IRQ_GPIO | GPIO_OUT); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function configures colibri memory controller registers +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static VOID collibri_ehpi_reg_init(VOID) +{ + UINT_32 u4RegValue; + + /* 1. enable nCS as memory controller */ + pxa_gpio_mode(GPIO80_nCS_4_MD); + + /* 2. nCS<4> configuration */ + u4RegValue = MSC2; + u4RegValue &= ~MSC_CS(4, 0xFFFF); + u4RegValue |= EHPI_CONFIG; + MSC2 = u4RegValue; + + DBGLOG(INIT, INFO, "EHPI new MSC2:0x%08x\n", MSC2); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function restores colibri memory controller registers +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static VOID collibri_ehpi_reg_uninit(VOID) +{ + UINT_32 u4RegValue; + + /* 1. restore nCS<4> configuration */ + u4RegValue = MSC2; + u4RegValue &= ~MSC_CS(4, 0xFFFF); + MSC2 = u4RegValue; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function configures MT5931 mapped registers on colibri +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static VOID mt5931_ehpi_reg_init(VOID) +{ + struct resource *reso = NULL; + + /* 1. request memory regioin */ + reso = request_mem_region((unsigned long)MEM_MAPPED_ADDR, (unsigned long)MEM_MAPPED_LEN, (char *)MODULE_PREFIX); + if (!reso) { + DBGLOG(INIT, ERROR, "request_mem_region(0x%08X) failed.\n", MEM_MAPPED_ADDR); + return; + } + + /* 2. memory regioin remapping */ + mt5931_mcr_base = ioremap_nocache(MEM_MAPPED_ADDR, MEM_MAPPED_LEN); + if (!(mt5931_mcr_base)) { + release_mem_region(MEM_MAPPED_ADDR, MEM_MAPPED_LEN); + DBGLOG(INIT, ERROR, "ioremap_nocache(0x%08X) failed.\n", MEM_MAPPED_ADDR); + return; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function releases MT5931 mapped registers on colibri +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static VOID mt5931_ehpi_reg_uninit(VOID) +{ + iounmap(mt5931_mcr_base); + mt5931_mcr_base = NULL; + + release_mem_region(MEM_MAPPED_ADDR, MEM_MAPPED_LEN); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Callback for interrupt coming from device +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static irqreturn_t glEhpiInterruptHandler(int irq, void *dev_id) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) dev_id; + + ASSERT(prGlueInfo); + + if (!prGlueInfo) + return IRQ_HANDLED; + + /* 1. Running for ISR */ + wlanISR(prGlueInfo->prAdapter, TRUE); + + /* 1.1 Halt flag Checking */ + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) + return IRQ_HANDLED; + + /* 2. Flag marking for interrupt */ + set_bit(GLUE_FLAG_INT_BIT, &prGlueInfo->ulFlag); + + /* 3. wake up tx service thread */ + wake_up_interruptible(&prGlueInfo->waitq); + + return IRQ_HANDLED; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ehpi/colibri.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ehpi/colibri.c new file mode 100644 index 0000000000000..1b1c65c9b7363 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ehpi/colibri.c @@ -0,0 +1,506 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/ehpi/colibri.c#1 +*/ + +/* + * ! \file "colibri.c" + * \brief Brief description. + * + * Detail description. + */ + +/****************************************************************************** +* C O M P I L E R F L A G S +******************************************************************************* +*/ +#if !defined(MCR_EHTCR) +#define MCR_EHTCR 0x0054 +#endif + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "colibri.h" +#include "wlan_lib.h" + +/******************************************************************************* +* 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 void __iomem *mt5931_mcr_base; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#if CFG_EHPI_FASTER_BUS_TIMING +#define EHPI_CONFIG MSC_CS(4, MSC_RBUFF_SLOW | \ + MSC_RRR(4) | \ + MSC_RDN(8) | \ + MSC_RDF(7) | \ + MSC_RBW_16 | \ + MSC_RT_VLIO) +#else +#define EHPI_CONFIG MSC_CS(4, MSC_RBUFF_SLOW | \ + MSC_RRR(7) | \ + MSC_RDN(13) | \ + MSC_RDF(12) | \ + MSC_RBW_16 | \ + MSC_RT_VLIO) +#endif /* CFG_EHPI_FASTER_BUS_TIMING */ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static VOID collibri_ehpi_reg_init(VOID); + +static VOID collibri_ehpi_reg_uninit(VOID); + +static VOID mt5931_ehpi_reg_init(VOID); + +static VOID mt5931_ehpi_reg_uninit(VOID); + +static void busSetIrq(void); + +static void busFreeIrq(void); + +static irqreturn_t glEhpiInterruptHandler(int irq, void *dev_id); + +#if DBG +static void initTrig(void); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will register sdio bus to the os +* +* \param[in] pfProbe Function pointer to detect card +* \param[in] pfRemove Function pointer to remove card +* +* \return The result of registering sdio bus +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS glRegisterBus(probe_card pfProbe, remove_card pfRemove) +{ + + ASSERT(pfProbe); + ASSERT(pfRemove); + + DBGLOG(INIT, INFO, "mtk_sdio: MediaTek eHPI WLAN driver\n"); + DBGLOG(INIT, INFO, "mtk_sdio: Copyright MediaTek Inc.\n"); + + if (pfProbe(NULL) != WLAN_STATUS_SUCCESS) { + pfRemove(); + return WLAN_STATUS_FAILURE; + } + + return WLAN_STATUS_SUCCESS; +} /* 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(); + + /* TODO: eHPI uninitialization */ + +} /* 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, ULONG ulCookie) +{ + P_GL_HIF_INFO_T prHif = NULL; + + ASSERT(prGlueInfo); + + prHif = &prGlueInfo->rHifInfo; + + /* fill some buffered information into prHif */ + prHif->mcr_addr_base = mt5931_mcr_base + EHPI_OFFSET_ADDR; + prHif->mcr_data_base = mt5931_mcr_base + EHPI_OFFSET_DATA; + +} /* 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; + + /* do something */ + prHif->mcr_addr_base = 0; + prHif->mcr_data_base = 0; + +} /* 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 DBG + initTrig(); +#endif + + /* 1. initialize eHPI control registers */ + collibri_ehpi_reg_init(); + + /* 2. memory remapping for MT5931 */ + mt5931_ehpi_reg_init(); + + return TRUE; +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus operation and release resources. +* +* \param[in] pvData A pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glBusRelease(PVOID pvData) +{ + /* 1. memory unmapping for MT5931 */ + mt5931_ehpi_reg_uninit(); + + /* 2. uninitialize eHPI control registers */ + collibri_ehpi_reg_uninit(); + +} /* 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) +{ + struct net_device *pDev = (struct net_device *)pvData; + int i4Status = 0; + + /* 1. enable GPIO pin as IRQ */ + busSetIrq(); + + /* 2. Specify IRQ number into net_device */ + pDev->irq = WLAN_STA_IRQ; + + /* 3. register ISR callback */ + + i4Status = request_irq(pDev->irq, + glEhpiInterruptHandler, + IRQF_DISABLED | IRQF_SHARED | IRQF_TRIGGER_FALLING, pDev->name, pvCookie); + + if (i4Status < 0) + DBGLOG(INTR, ERROR, "request_irq(%d) failed\n", pDev->irq); + else + DBGLOG(INTR, INFO, "request_irq(%d) success with dev_id(%x)\n", pDev->irq, (unsigned int)pvCookie); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus interrupt operation and disable interrupt handling for os. +* +* \param[in] pvData A pointer to struct net_device. +* \param[in] pvCookie Private data for pfnIsr function. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glBusFreeIrq(PVOID pvData, PVOID pvCookie) +{ + struct net_device *prDev = (struct net_device *)pvData; + + if (!prDev) { + DBGLOG(IRQ, INFO, "Invalid net_device context.\n"); + return; + } + + if (prDev->irq) { + disable_irq(prDev->irq); + free_irq(prDev->irq, pvCookie); + prDev->irq = 0; + } + + busFreeIrq(); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set power state +* +* \param[in] pvGlueInfo A pointer to GLUE_INFO_T +* \param[in] ePowerMode Power Mode Setting +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glSetPowerState(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 ePowerMode) +{ +} + +#if DBG +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setup the GPIO pin. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void setTrig(void) +{ + GPSR1 = (0x1UL << 8); +} /* end of setTrig() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Clear the GPIO pin. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void clearTrig(void) +{ + GPCR1 = (0x1UL << 8); +} /* end of clearTrig() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set a specified GPIO pin to H or L. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static void initTrig(void) +{ + set_GPIO_mode(GPIO40_FFDTR | GPIO_OUT); + clearTrig(); +} /* end of initTrig() */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function congifure platform-dependent interrupt triger type. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void busSetIrq(void) +{ +#if defined(WLAN_STA_IRQ_GPIO) + pxa_gpio_mode(WLAN_STA_IRQ_GPIO | GPIO_IN); + set_irq_type(WLAN_STA_IRQ, IRQT_FALLING); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function should restore settings changed by busSetIrq(). +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void busFreeIrq(void) +{ +#if defined(WLAN_STA_IRQ_GPIO) + pxa_gpio_mode(WLAN_STA_IRQ_GPIO | GPIO_OUT); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function configures colibri memory controller registers +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static VOID collibri_ehpi_reg_init(VOID) +{ + UINT_32 u4RegValue; + + /* 1. enable nCS as memory controller */ + pxa_gpio_mode(GPIO80_nCS_4_MD); + + /* 2. nCS<4> configuration */ + u4RegValue = MSC2; + u4RegValue &= ~MSC_CS(4, 0xFFFF); + u4RegValue |= EHPI_CONFIG; + MSC2 = u4RegValue; + + DBGLOG(INIT, INFO, "EHPI new MSC2:0x%08x\n", MSC2); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function restores colibri memory controller registers +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static VOID collibri_ehpi_reg_uninit(VOID) +{ + UINT_32 u4RegValue; + + /* 1. restore nCS<4> configuration */ + u4RegValue = MSC2; + u4RegValue &= ~MSC_CS(4, 0xFFFF); + MSC2 = u4RegValue; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function configures MT5931 mapped registers on colibri +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static VOID mt5931_ehpi_reg_init(VOID) +{ + struct resource *reso = NULL; + + /* 1. request memory regioin */ + reso = request_mem_region((unsigned long)MEM_MAPPED_ADDR, (unsigned long)MEM_MAPPED_LEN, (char *)MODULE_PREFIX); + if (!reso) { + DBGLOG(INIT, ERROR, "request_mem_region(0x%08X) failed.\n", MEM_MAPPED_ADDR); + return; + } + + /* 2. memory regioin remapping */ + mt5931_mcr_base = ioremap_nocache(MEM_MAPPED_ADDR, MEM_MAPPED_LEN); + if (!(mt5931_mcr_base)) { + release_mem_region(MEM_MAPPED_ADDR, MEM_MAPPED_LEN); + DBGLOG(INIT, ERROR, "ioremap_nocache(0x%08X) failed.\n", MEM_MAPPED_ADDR); + return; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function releases MT5931 mapped registers on colibri +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static VOID mt5931_ehpi_reg_uninit(VOID) +{ + iounmap(mt5931_mcr_base); + mt5931_mcr_base = NULL; + + release_mem_region(MEM_MAPPED_ADDR, MEM_MAPPED_LEN); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Callback for interrupt coming from device +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static irqreturn_t glEhpiInterruptHandler(int irq, void *dev_id) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) dev_id; + + ASSERT(prGlueInfo); + + if (!prGlueInfo) + return IRQ_HANDLED; + + /* 1. Running for ISR */ + wlanISR(prGlueInfo->prAdapter, TRUE); + + /* 1.1 Halt flag Checking */ + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) + return IRQ_HANDLED; + + /* 2. Flag marking for interrupt */ + set_bit(GLUE_FLAG_INT_BIT, &prGlueInfo->ulFlag); + + /* 3. wake up tx service thread */ + wake_up_interruptible(&prGlueInfo->waitq); + + return IRQ_HANDLED; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ehpi/ehpi.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ehpi/ehpi.c new file mode 100644 index 0000000000000..c55674238655a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ehpi/ehpi.c @@ -0,0 +1,377 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/ehpi/ehpi.c#1 +*/ + +/* + * ! \file "ehpi.c" + * \brief Brief description. + * + * Detail description. + */ + +/****************************************************************************** +* C O M P I L E R F L A G S +******************************************************************************* +*/ +#if !defined(MCR_EHTCR) +#define MCR_EHTCR 0x0054 +#endif + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "colibri.h" +#include "wlan_lib.h" + +/******************************************************************************* +* 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 BOOL kalDevRegRead_impl(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Register, OUT PUINT_32 pu4Value); + +static BOOL kalDevRegWrite_impl(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Register, IN UINT_32 u4Value); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to read a 32 bit register value from device. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u4Register The register offset. +* \param[out] pu4Value Pointer to the 32-bit value of the register been read. +* +* \retval TRUE +* \retval FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOL kalDevRegRead(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Register, OUT PUINT_32 pu4Value) +{ + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + ASSERT(pu4Value); + + /* 0. acquire spinlock */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + /* 1. I/O stuff */ + kalDevRegRead_impl(prGlueInfo, u4Register, pu4Value); + + /* 2. release spin lock */ + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to write a 32 bit register value to device. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u4Register The register offset. +* \param[out] u4Value The 32-bit value of the register to be written. +* +* \retval TRUE +* \retval FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOL kalDevRegWrite(P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Register, IN UINT_32 u4Value) +{ + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + /* 0. acquire spinlock */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + /* 1. I/O stuff */ + kalDevRegWrite_impl(prGlueInfo, u4Register, u4Value); + + /* 2. release spin lock */ + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to read port data from device in unit of byte. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u2Port The register offset. +* \param[in] u2Len The number of byte to be read. +* \param[out] pucBuf Pointer to data buffer for read +* \param[in] u2ValidOutBufSize Length of the buffer valid to be accessed +* +* \retval TRUE +* \retval FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOL +kalDevPortRead(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_16 u2Port, IN UINT_16 u2Len, OUT PUINT_8 pucBuf, IN UINT_16 u2ValidOutBufSize) +{ + UINT_32 i; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + /* 0. acquire spinlock */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + /* 1. indicate correct length to HIFSYS if larger than 4-bytes */ + if (u2Len > 4) + kalDevRegWrite_impl(prGlueInfo, MCR_EHTCR, ALIGN_4(u2Len)); + + /* 2. address cycle */ +#if EHPI16 + writew(u2Port, prGlueInfo->rHifInfo.mcr_addr_base); +#elif EHPI8 + writew((u2Port & 0xFF), prGlueInfo->rHifInfo.mcr_addr_base); + writew(((u2Port & 0xFF00) >> 8), prGlueInfo->rHifInfo.mcr_addr_base); +#endif + + /* 3. data cycle */ + for (i = 0; i < ALIGN_4(u2Len); i += 4) { +#if EHPI16 + *((PUINT_16)&(pucBuf[i])) = (UINT_16) (readw(prGlueInfo->rHifInfo.mcr_data_base)&0xFFFF); + *((PUINT_16)&(pucBuf[i + 2])) = (UINT_16) (readw(prGlueInfo->rHifInfo.mcr_data_base)&0xFFFF); +#elif EHPI8 + *((PUINT_8)&(pucBuf[i])) = (UINT_8) (readw(prGlueInfo->rHifInfo.mcr_data_base)&0xFF); + *((PUINT_8)&(pucBuf[i + 1])) = (UINT_8) (readw(prGlueInfo->rHifInfo.mcr_data_base)&0xFF); + *((PUINT_8)&(pucBuf[i + 2])) = (UINT_8) (readw(prGlueInfo->rHifInfo.mcr_data_base)&0xFF); + *((PUINT_8)&(pucBuf[i + 3])) = (UINT_8) (readw(prGlueInfo->rHifInfo.mcr_data_base)&0xFF); +#endif + } + + /* 4. restore length to 4 if necessary */ + if (u2Len > 4) + kalDevRegWrite_impl(prGlueInfo, MCR_EHTCR, 4); + + /* 5. release spin lock */ + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to write port data to device in unit of byte. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u2Port The register offset. +* \param[in] u2Len The number of byte to be write. +* \param[out] pucBuf Pointer to data buffer for write +* \param[in] u2ValidOutBufSize Length of the buffer valid to be accessed +* +* \retval TRUE +* \retval FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOL +kalDevPortWrite(P_GLUE_INFO_T prGlueInfo, + IN UINT_16 u2Port, IN UINT_16 u2Len, IN PUINT_8 pucBuf, IN UINT_16 u2ValidInBufSize) +{ + UINT_32 i; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + /* 0. acquire spinlock */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + /* 1. indicate correct length to HIFSYS if larger than 4-bytes */ + if (u2Len > 4) + kalDevRegWrite_impl(prGlueInfo, MCR_EHTCR, ALIGN_4(u2Len)); + + /* 2. address cycle */ +#if EHPI16 + writew(u2Port, prGlueInfo->rHifInfo.mcr_addr_base); +#elif EHPI8 + writew((u2Port & 0xFF), prGlueInfo->rHifInfo.mcr_addr_base); + writew(((u2Port & 0xFF00) >> 8), prGlueInfo->rHifInfo.mcr_addr_base); +#endif + + /* 3. data cycle */ + for (i = 0; i < ALIGN_4(u2Len); i += 4) { +#if EHPI16 + writew((UINT_32) (*((PUINT_16)&(pucBuf[i]))), prGlueInfo->rHifInfo.mcr_data_base); + writew((UINT_32) (*((PUINT_16)&(pucBuf[i + 2]))), prGlueInfo->rHifInfo.mcr_data_base); +#elif EHPI8 + writew((UINT_32) (*((PUINT_8)&(pucBuf[i]))), prGlueInfo->rHifInfo.mcr_data_base); + writew((UINT_32) (*((PUINT_8)&(pucBuf[i + 1]))), prGlueInfo->rHifInfo.mcr_data_base); + writew((UINT_32) (*((PUINT_8)&(pucBuf[i + 2]))), prGlueInfo->rHifInfo.mcr_data_base); + writew((UINT_32) (*((PUINT_8)&(pucBuf[i + 3]))), prGlueInfo->rHifInfo.mcr_data_base); +#endif + } + + /* 4. restore length to 4 if necessary */ + if (u2Len > 4) + kalDevRegWrite_impl(prGlueInfo, MCR_EHTCR, 4); + + /* 5. release spin lock */ + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write device I/O port with single byte (for SDIO compatibility) +* +* \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 +* \param[in] u4ValidInBufSize Length of the buffer valid to be accessed +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +BOOL kalDevWriteWithSdioCmd52(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Addr, IN UINT_8 ucData) +{ + UINT_32 u4RegValue; + BOOLEAN bRet; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + /* 0. acquire spinlock */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + /* 1. there is no single byte access support for eHPI, use 4-bytes write-after-read approach instead */ + if (kalDevRegRead_impl(prGlueInfo, u4Addr, &u4RegValue) == TRUE) { + u4RegValue &= 0x00; + u4RegValue |= ucData; + + bRet = kalDevRegWrite_impl(prGlueInfo, u4Addr, u4RegValue); + } else { + bRet = FALSE; + } + + /* 2. release spin lock */ + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + return bRet; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to read a 32 bit register value from device +* without spin lock protection and dedicated for internal use +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u4Register The register offset. +* \param[out] pu4Value Pointer to the 32-bit value of the register been read. +* +* \retval TRUE +* \retval FALSE +*/ +/*----------------------------------------------------------------------------*/ +static BOOL kalDevRegRead_impl(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Register, OUT PUINT_32 pu4Value) +{ + ASSERT(prGlueInfo); + + /* 1. address cycle */ +#if EHPI16 + writew(u4Register, prGlueInfo->rHifInfo.mcr_addr_base); +#elif EHPI8 + writew((u4Register & 0xFF), prGlueInfo->rHifInfo.mcr_addr_base); + writew(((u4Register & 0xFF00) >> 8), prGlueInfo->rHifInfo.mcr_addr_base); +#endif + + /* 2. data cycle */ +#if EHPI16 + *pu4Value = (readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFFFF); + *pu4Value |= ((readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFFFF) << 16); +#elif EHPI8 + *pu4Value = (readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF); + *pu4Value |= ((readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF) << 8); + *pu4Value |= ((readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF) << 16); + *pu4Value |= ((readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF) << 24); +#endif + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to write a 32 bit register value to device. +* without spin lock protection and dedicated for internal use +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u4Register The register offset. +* \param[out] u4Value The 32-bit value of the register to be written. +* +* \retval TRUE +* \retval FALSE +*/ +/*----------------------------------------------------------------------------*/ +static BOOL kalDevRegWrite_impl(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Register, IN UINT_32 u4Value) +{ + ASSERT(prGlueInfo); + + /* 1. address cycle */ +#if EHPI16 + writew(u4Register, prGlueInfo->rHifInfo.mcr_addr_base); +#elif EHPI8 + writew((u4Register & 0xFF), prGlueInfo->rHifInfo.mcr_addr_base); + writew(((u4Register & 0xFF00) >> 8), prGlueInfo->rHifInfo.mcr_addr_base); +#endif + + /* 2. data cycle */ +#if EHPI16 + writew(u4Value, prGlueInfo->rHifInfo.mcr_data_base); + writew((u4Value & 0xFFFF0000) >> 16, prGlueInfo->rHifInfo.mcr_data_base); +#elif EHPI8 + writew((u4Value & 0x000000FF), prGlueInfo->rHifInfo.mcr_data_base); + writew((u4Value & 0x0000FF00) >> 8, prGlueInfo->rHifInfo.mcr_data_base); + writew((u4Value & 0x00FF0000) >> 16, prGlueInfo->rHifInfo.mcr_data_base); + writew((u4Value & 0xFF000000) >> 24, prGlueInfo->rHifInfo.mcr_data_base); +#endif + + return TRUE; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ehpi/include/colibri.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ehpi/include/colibri.h new file mode 100644 index 0000000000000..f224be61241df --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/ehpi/include/colibri.h @@ -0,0 +1,154 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/ehpi/include/colibri.h#1 +*/ + +/* + * ! \file "colibri.h" + * \brief This file contains colibri BSP configuration based on eHPI interface + * + * N/A + */ + +#ifndef _COLIBRI_H +#define _COLIBRI_H +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include +#include +#include +#include +#include + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define WLAN_STA_IRQ_GPIO 23 /* use SSP_EXTCLK as interrupt source */ +#define WLAN_STA_IRQ IRQ_GPIO(WLAN_STA_IRQ_GPIO) + +#define MSC_CS(cs, val) ((val)<<(((cs)&1)<<4)) + +#define MSC_RBUFF_SHIFT 15 +#define MSC_RBUFF(x) ((x)<. +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/ehpi/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 + */ + +#ifndef _HIF_H +#define _HIF_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 +******************************************************************************** +*/ + +/* host interface's private data structure, which is attached to os glue +** layer info structure. + */ +typedef struct _GL_HIF_INFO_T { + void __iomem *mcr_addr_base; + void __iomem *mcr_data_base; + BOOLEAN fgIntReadClear; + BOOLEAN fgMbxReadClear; +} GL_HIF_INFO_T, *P_GL_HIF_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 +******************************************************************************** +*/ + +WLAN_STATUS glRegisterBus(probe_card pfProbe, remove_card pfRemove); + +VOID glUnregisterBus(remove_card pfRemove); + +VOID glSetHifInfo(P_GLUE_INFO_T prGlueInfo, ULONG ulCookie); + +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/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/sdio/arm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/sdio/arm.c new file mode 100644 index 0000000000000..a6054f7eeebf5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/sdio/arm.c @@ -0,0 +1,24 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/****************************************************************************** +*[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. +******************************************************************************/ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/sdio/include/hif.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/sdio/include/hif.h new file mode 100644 index 0000000000000..7051f7d29e5a9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/sdio/include/hif.h @@ -0,0 +1,153 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/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 + */ + +#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, ULONG ulCookie); + +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/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/sdio/include/hif_sdio.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/sdio/include/hif_sdio.h new file mode 100644 index 0000000000000..d5574a7d1cdf7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/sdio/include/hif_sdio.h @@ -0,0 +1,211 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/sdio/include/hif_sdio.h#2 + */ + +/* + * ! \file "hif_sdio.h" + * \brief + */ + +#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:turn off debug msg and assert, 1:turn 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 (8) + +#define HIF_DEFAULT_BLK_SIZE (256) +#define HIF_DEFAULT_VENDOR (0x037A) + +/******************************************************************************* +* 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 ULONG MTK_WCN_HIF_SDIO_CLTCTX; + +/* Callback functions provided by client driver */ +typedef INT_32(*MTK_WCN_HIF_SDIO_PROBE)(MTK_WCN_HIF_SDIO_CLTCTX, const MTK_WCN_HIF_SDIO_FUNCINFO *prFuncInfo); +typedef INT_32(*MTK_WCN_HIF_SDIO_REMOVE)(MTK_WCN_HIF_SDIO_CLTCTX); +typedef INT_32(*MTK_WCN_HIF_SDIO_IRQ)(MTK_WCN_HIF_SDIO_CLTCTX); + +/* Function info provided by client driver */ +struct _MTK_WCN_HIF_SDIO_FUNCINFO { + UINT_16 manf_id; /* TPLMID_MANF: manufacturer ID */ + UINT_16 card_id; /* TPLMID_CARD: card ID */ + UINT_16 func_num; /* Function Number */ + UINT_16 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 */ + UINT_32 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 */ + INT_8 clt_idx; /* registered function table info element number (initial value is -1) */ + MTK_WCN_BOOL interrupted; /* TRUE: interrupted, FALSE: not interrupted */ + void *private_data_p; /* clt's private data pointer */ +} 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 */ + INT_8 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, /* generic error */ + HIF_SDIO_ERR_INVALID_PARAM, + HIF_SDIO_ERR_DUPLICATED, + HIF_SDIO_ERR_UNSUP_MANF_ID, + HIF_SDIO_ERR_UNSUP_CARD_ID, + HIF_SDIO_ERR_INVALID_FUNC_NUM, + HIF_SDIO_ERR_INVALID_BLK_SZ, +} 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) + +/*! + * \brief A debug print used to print debug messages while compiler flag HIF_SDIO_DEBUG on. + * + */ +#if HIF_SDIO_DEBUG +#define DPRINTK(fmt, args...) pr_debug("%s: " fmt, __func__, ## args) +#else +#define DPRINTK(fmt, args...) +#endif + +/*! + * \brief ASSERT function definition. + * + */ +#if HIF_SDIO_DEBUG +#define ASSERT(expr) \ + { \ + if (!(expr)) { \ + LOG_FUNC("assertion failed! %s[%d]: %s\n",\ + __func__, __LINE__, #expr); \ + panic("assert failed\n");\ + } \ + } +#else +#define 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 INT_32 mtk_wcn_hif_sdio_client_reg(const MTK_WCN_HIF_SDIO_CLTINFO *pinfo); + +extern INT_32 mtk_wcn_hif_sdio_client_unreg(const MTK_WCN_HIF_SDIO_CLTINFO *pinfo); + +extern INT_32 mtk_wcn_hif_sdio_readb(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT_32 offset, PUINT_8 pvb); + +extern INT_32 mtk_wcn_hif_sdio_writeb(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT_32 offset, UINT_8 vb); + +extern INT_32 mtk_wcn_hif_sdio_readl(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT_32 offset, PUINT_32 pvl); + +extern INT_32 mtk_wcn_hif_sdio_writel(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT_32 offset, UINT_32 vl); + +extern INT_32 mtk_wcn_hif_sdio_read_buf(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT_32 offset, PUINT_32 pbuf, UINT_32 len); + +extern INT_32 mtk_wcn_hif_sdio_write_buf(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT_32 offset, PUINT_32 pbuf, UINT_32 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/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/sdio/include/mtk_porting.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/sdio/include/mtk_porting.h new file mode 100644 index 0000000000000..01837758c05eb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/sdio/include/mtk_porting.h @@ -0,0 +1,55 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* porting layer */ +/* Android */ + +#ifndef _MTK_PORTING_H_ +#define _MTK_PORTING_H_ + +#include /* include stddef.h for NULL */ + +/* 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 INT_32(*MUTEX_DESTROY) (MTK_WCN_MUTEX mtx); +typedef INT_32(*MUTEX_LOCK) (MTK_WCN_MUTEX mtx); +typedef INT_32(*MUTEX_UNLOCK) (MTK_WCN_MUTEX mtx, unsigned long flags); +/* debug */ +typedef INT_32(*DBG_PRINT) (const char *str, ...); +typedef INT_32(*DBG_ASSERT) (INT_32 expr, const char *file, INT_32 line); +/* timer */ +typedef void (*MTK_WCN_TIMER_CB) (void); +typedef MTK_WCN_TIMER(*TIMER_CREATE) (const char *const name); +typedef INT_32(*TIMER_DESTROY) (MTK_WCN_TIMER tmr); +typedef INT_32(*TIMER_START) (MTK_WCN_TIMER tmr, UINT_32 timeout, MTK_WCN_TIMER_CB tmr_cb, void *param); +typedef INT_32(*TIMER_STOP) (MTK_WCN_TIMER tmr); +/* kernel lib */ +typedef void *(*SYS_MEMCPY) (void *dest, const void *src, UINT_32 n); +typedef void *(*SYS_MEMSET) (void *s, INT_32 c, UINT_32 n); +typedef INT_32(*SYS_SPRINTF) (char *str, const char *format, ...); + +#endif /* _MTK_PORTING_H_ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/sdio/sdio.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/sdio/sdio.c new file mode 100644 index 0000000000000..b1120d4402c97 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/sdio/sdio.c @@ -0,0 +1,1100 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/****************************************************************************** +*[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. +******************************************************************************/ + +/******************************************************************************* +* C O M P I L E 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 +#include +#include +#include /* sdio_readl(), etc */ +#include +#endif + +#include +#ifndef CONFIG_X86 +#include +#endif + +#if defined(MT6630) +#include "mt6630_reg.h" +#endif + +#if CFG_DBG_GPIO_PINS /* FIXME: move to platform or custom header */ +#include +#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" + +#define HIF_SDIO_ACCESS_RETRY_LIMIT 3 + +#if MTK_WCN_HIF_SDIO + +/* + * function prototypes + * + */ + +static INT_32 mtk_sdio_probe(MTK_WCN_HIF_SDIO_CLTCTX, const MTK_WCN_HIF_SDIO_FUNCINFO *); + +static INT_32 mtk_sdio_remove(MTK_WCN_HIF_SDIO_CLTCTX); +static INT_32 mtk_sdio_interrupt(MTK_WCN_HIF_SDIO_CLTCTX); + +/* + * sdio function info table + */ + +static MTK_WCN_HIF_SDIO_FUNCINFO funcInfo[] = { +#if defined(MT6630) + {MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x6630, 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(MT6630) + {SDIO_DEVICE(0x037a, 0x6630)}, /* 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 +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static probe_card pfWlanProbe; +static remove_card pfWlanRemove; + +#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 < ARRAY_SIZE(dbgPinSTP); ++i) { + if (dbgPinSTP[i] == GPIO_INVALID) + continue; + + /* DBGLOG(INIT, INFO, "[%s] %ld\n", __func__, 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 */ + } + DBGLOG(INIT, INFO, "[%s] initialization ok\n", __func__) +} + +void debug_gpio_deinit(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(dbgPinSTP); ++i) { + if (dbgPinSTP[i] == GPIO_INVALID) + continue; + + /* DBGLOG(INIT, INFO, "[%s] %ld\n", __func__, dbgPinSTP[i]); */ + mt_set_gpio_dir(dbgPinSTP[i], GPIO_DIR_IN); + } + + DBGLOG(INIT, INFO, "[%s] k\n", __func__); +} + +void mtk_wcn_stp_debug_gpio_assert(UINT_32 dwIndex, UINT_32 dwMethod) +{ + unsigned int i; + + if (dwIndex >= ARRAY_SIZE(dbgPinSTP)) + DBGLOG(INIT, INFO, "[%s] invalid dwIndex(%ld)\n", __func__, dwIndex); + return; + + if (dwIndex > IDX_STP_MAX) + DBGLOG(INIT, INFO, "[%s] dwIndex(%ld) > IDX_STP_MAX(%d)\n", __func__, dwIndex, IDX_STP_MAX); + + if (dbgPinSTP[dwIndex] == GPIO_INVALID) + 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; + } + +} +#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 INT_32 mtk_sdio_interrupt(MTK_WCN_HIF_SDIO_CLTCTX cltCtx) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 ret = 0; + + prGlueInfo = mtk_wcn_hif_sdio_get_drvdata(cltCtx); + + /* ASSERT(prGlueInfo); */ + + if (!prGlueInfo) + return -HIF_SDIO_ERR_FAIL; + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + ret = mtk_wcn_hif_sdio_writel(cltCtx, MCR_WHLPCR, WHLPCR_INT_EN_CLR); + return ret; + } + + ret = mtk_wcn_hif_sdio_writel(cltCtx, MCR_WHLPCR, WHLPCR_INT_EN_CLR); + + KAL_WAKE_LOCK(prGlueInfo->prAdapter, &prGlueInfo->rIntrWakeLock); + + set_bit(GLUE_FLAG_INT_BIT, &prGlueInfo->ulFlag); + + /* when we got sdio interrupt, we wake up the tx servie thread */ +#if CFG_SUPPORT_MULTITHREAD + wake_up_interruptible(&prGlueInfo->waitq_hif); +#else + wake_up_interruptible(&prGlueInfo->waitq); +#endif + + return ret; +} + +#else + +static unsigned int in_interrupt; + +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) + return; + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + sdio_writel(prGlueInfo->rHifInfo.func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, &ret); + return; + } + + sdio_writel(prGlueInfo->rHifInfo.func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, &ret); + +#if 0 + wlanISR(prGlueInfo->prAdapter, TRUE); + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) + /* Should stop now... skip pending interrupt */ + else + wlanIST(prGlueInfo->prAdapter); +#endif + + set_bit(GLUE_FLAG_INT_BIT, &prGlueInfo->ulFlag); + + /* when we got sdio interrupt, we wake up the tx servie thread */ +#if CFG_SUPPORT_MULTITHREAD + wake_up_interruptible(&prGlueInfo->waitq_hif); +#else + wake_up_interruptible(&prGlueInfo->waitq); +#endif +} +#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 INT_32 mtk_sdio_probe(MTK_WCN_HIF_SDIO_CLTCTX cltCtx, const MTK_WCN_HIF_SDIO_FUNCINFO *prFuncInfo) +{ + INT_32 ret = HIF_SDIO_ERR_SUCCESS; + + prFunc = prFuncInfo; + + if (pfWlanProbe((PVOID)&cltCtx) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "pfWlanProbe fail!call pfWlanRemove()\n"); + pfWlanRemove(); + ret = -(HIF_SDIO_ERR_FAIL); + } else { + DBGLOG(INIT, INFO, "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; + + DBGLOG(INIT, INFO, "mtk_sdio_probe()\n"); + + ASSERT(func); + ASSERT(id); + + for (i = 0; i < func->card->num_info; i++) + DBGLOG(INIT, INFO, "info[%d]: %s\n", i, func->card->info[i]); + + sdio_claim_host(func); + ret = sdio_enable_func(func); + sdio_release_host(func); + + if (ret) { + DBGLOG(INIT, ERROR, "sdio_enable_func failed!\n"); + goto out; + } + DBGLOG(INIT, INFO, "sdio_enable_func done!\n"); + + if (pfWlanProbe((PVOID) func) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, WARN, "pfWlanProbe fail!call pfWlanRemove()\n"); + pfWlanRemove(); + ret = -1; + } else { +#if CFG_DBG_GPIO_PINS + DBGLOG(INIT, INFO, "[%s] init debug gpio, 20100815\n", __func__); + /* Debug pins initialization */ + debug_gpio_init(); +#endif + } + +out: + DBGLOG(INIT, INFO, "mtk_sdio_probe() done(%d)\n", ret); + return ret; +} +#endif + +#if MTK_WCN_HIF_SDIO +static INT_32 mtk_sdio_remove(MTK_WCN_HIF_SDIO_CLTCTX cltCtx) +{ + INT_32 ret = HIF_SDIO_ERR_SUCCESS; + + DBGLOG(INIT, INFO, "pfWlanRemove done\n"); + pfWlanRemove(); + + return ret; +} +#else +static void mtk_sdio_remove(struct sdio_func *func) +{ + DBGLOG(INIT, INFO, "mtk_sdio_remove()\n"); + +#if CFG_DBG_GPIO_PINS + DBGLOG(INIT, INFO, "[%s] deinit debug gpio\n", __func__); + debug_gpio_deinit(); +#endif + + ASSERT(func); + pfWlanRemove(); + + sdio_claim_host(func); + sdio_disable_func(func); + sdio_release_host(func); + + DBGLOG(INIT, INFO, "mtk_sdio_remove() done\n"); +} +#endif + +#if (MTK_WCN_HIF_SDIO == 0) +static int mtk_sdio_suspend(struct device *pDev, pm_message_t state) +{ + DBGLOG(INIT, INFO, "mtk_sdio: mtk_sdio_suspend dev(0x%p)\n", pDev); + DBGLOG(INIT, INFO, "mtk_sdio: MediaTek SDIO WLAN driver\n"); + + return 0; +} + +int mtk_sdio_resume(struct device *pDev) +{ + DBGLOG(INIT, 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); + + DBGLOG(INIT, INFO, "mtk_sdio: MediaTek SDIO WLAN driver\n"); + DBGLOG(INIT, 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 + +} /* 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, ULONG ulCookie) +{ + 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 *) ulCookie); + mtk_wcn_hif_sdio_set_drvdata(prHif->cltCtx, prGlueInfo); + +#else + prHif->func = (struct sdio_func *)ulCookie; + + DBGLOG(INIT, LOUD, "prHif->func->dev = 0x%p\n", &prHif->func->dev); + DBGLOG(INIT, LOUD, "prHif->func->vendor = 0x%04X\n", prHif->func->vendor); + DBGLOG(INIT, LOUD, "prHif->func->device = 0x%04X\n", prHif->func->device); + DBGLOG(INIT, LOUD, "prHif->func->func = 0x%04X\n", prHif->func->num); + + sdio_set_drvdata(prHif->func, prGlueInfo); + + SET_NETDEV_DEV(prGlueInfo->prDevHandler, &prHif->func->dev); +#endif + +} /* 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; */ + +} /* 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) + DBGLOG(INIT, ERROR, "sdio_set_block_size 512 failed!\n"); + else + DBGLOG(INIT, INFO, "sdio_set_block_size 512 done!\n"); + + DBGLOG(INIT, LOUD, "param: func->cur_blksize(%d)\n", func->cur_blksize); + DBGLOG(INIT, LOUD, "param: func->max_blksize(%d)\n", func->max_blksize); + DBGLOG(INIT, LOUD, "param: func->card->host->max_blk_size(%d)\n", func->card->host->max_blk_size); + DBGLOG(INIT, LOUD, "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) +{ + +} /* 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; + + 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; + +#if (MTK_WCN_HIF_SDIO == 0) + sdio_claim_host(prHifInfo->func); + ret = sdio_claim_irq(prHifInfo->func, mtk_sdio_interrupt); + sdio_release_host(prHifInfo->func); +#else + mtk_wcn_hif_sdio_enable_irq(prHifInfo->cltCtx, 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) +{ + struct net_device *prNetDevice = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_GL_HIF_INFO_T prHifInfo = NULL; + + ASSERT(pvData); + prNetDevice = (struct net_device *)pvData; + prGlueInfo = (P_GLUE_INFO_T) pvCookie; + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(INTR, INFO, "%s no glue info\n", __func__); + return; + } + + prHifInfo = &prGlueInfo->rHifInfo; +#if (MTK_WCN_HIF_SDIO == 0) + sdio_claim_host(prHifInfo->func); + sdio_release_irq(prHifInfo->func); + sdio_release_host(prHifInfo->func); +#else + mtk_wcn_hif_sdio_enable_irq(prHifInfo->cltCtx, FALSE); +#endif + +} /* end of glBusreeIrq() */ + +BOOLEAN glIsReadClearReg(UINT_32 u4Address) +{ + switch (u4Address) { + case MCR_WHISR: + case MCR_WASR: + case MCR_D2HRM0R: + case MCR_D2HRM1R: + case MCR_WTQCR0: + case MCR_WTQCR1: + case MCR_WTQCR2: + case MCR_WTQCR3: + case MCR_WTQCR4: + case MCR_WTQCR5: + case MCR_WTQCR6: + case MCR_WTQCR7: + return TRUE; + + default: + return FALSE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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; + UINT_8 ucRetryCount = 0; + + ASSERT(prGlueInfo); + ASSERT(pu4Value); + + do { +#if MTK_WCN_HIF_SDIO + ret = mtk_wcn_hif_sdio_readl(prGlueInfo->rHifInfo.cltCtx, u4Register, (PUINT_32) pu4Value); +#else + /* + * checkpatch.pl maybe have bugs as it always reports + * SUSPECT_CODE_INDENT WARNING + */ + 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 || ucRetryCount) { + /* + * DBGLOG(HAL, ERROR, + * ("sdio_readl() addr: 0x%08x value: 0x%08x status: %x retry: %u\n", + * u4Register, (unsigned int)*pu4Value, (unsigned int)ret, ucRetryCount)); + */ + + if (glIsReadClearReg(u4Register) && (ucRetryCount == 0)) { + /* Read Snapshot CR instead */ + u4Register = MCR_WSR; + } + } + + ucRetryCount++; + if (ucRetryCount > HIF_SDIO_ACCESS_RETRY_LIMIT) + break; + } while (ret); + + if (ret) { + kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, + HIF_SDIO_ERR_DESC_STR "sdio_readl() reports error: %x retry: %u", ret, ucRetryCount); + DBGLOG(HAL, ERROR, "sdio_readl() reports error: %x retry: %u\n", ret, ucRetryCount); + } + + 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; + UINT_8 ucRetryCount = 0; + + ASSERT(prGlueInfo); + + do { +#if MTK_WCN_HIF_SDIO + ret = mtk_wcn_hif_sdio_writel(prGlueInfo->rHifInfo.cltCtx, u4Register, u4Value); +#else + /* + * checkpatch.pl maybe have bugs as it always reports + * SUSPECT_CODE_INDENT WARNING + */ + 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 || ucRetryCount) { + /* + * DBGLOG(HAL, ERROR, + * ("sdio_writel() addr: 0x%x status: %x retry: %u\n", u4Register, + * ret, ucRetryCount)); + */ + } + + ucRetryCount++; + if (ucRetryCount > HIF_SDIO_ACCESS_RETRY_LIMIT) + break; + + } while (ret); + + if (ret) { + kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, + HIF_SDIO_ERR_DESC_STR "sdio_writel() reports error: %x retry: %u", ret, ucRetryCount); + DBGLOG(HAL, ERROR, "sdio_writel() reports error: %x retry: %u\n", ret, ucRetryCount); + } + + 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_32 u4Len, OUT PUINT_8 pucBuf, IN UINT_32 u4ValidOutBufSize) +{ + P_GL_HIF_INFO_T prHifInfo = NULL; + PUINT_8 pucDst = NULL; + int count = u4Len; + int ret = 0; + int bNum = 0; + +#if (MTK_WCN_HIF_SDIO == 0) + struct sdio_func *prSdioFunc = NULL; +#endif + +#if DBG + DBGLOG(INIT, LOUD, "++kalDevPortRead++ buf:0x%p, port:0x%x, length:%d\n", pucBuf, u2Port, u4Len); +#endif + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + ASSERT(pucBuf); + pucDst = pucBuf; + + ASSERT(u4Len <= u4ValidOutBufSize); + +#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, (PUINT_32) pucDst, + ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz) * bNum); + } else { + ret = mtk_wcn_hif_sdio_read_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT_32) 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\n", 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_32 u4Len, IN PUINT_8 pucBuf, IN UINT_32 u4ValidInBufSize) +{ + P_GL_HIF_INFO_T prHifInfo = NULL; + PUINT_8 pucSrc = NULL; + int count = u4Len; + int ret = 0; + int bNum = 0; + +#if (MTK_WCN_HIF_SDIO == 0) + struct sdio_func *prSdioFunc = NULL; +#endif + +#if DBG + DBGLOG(INIT, LOUD, "++kalDevPortWrite++ buf:0x%p, port:0x%x, length:%d\n", pucBuf, u2Port, u2Len); +#endif + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + ASSERT(pucBuf); + pucSrc = pucBuf; + + ASSERT(u4Len <= u4ValidInBufSize); + +#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, + (PUINT_32) pucSrc, ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz) * bNum); + } else { /* byte mode */ + ret = mtk_wcn_hif_sdio_write_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT_32) 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\n", 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\n", ret); + } + + return (ret) ? FALSE : TRUE; + +} /* end of kalDevWriteWithSdioCmd52() */ + +VOID glSetPowerState(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 ePowerMode) +{ +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/sdio/x86.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/sdio/x86.c new file mode 100644 index 0000000000000..a6054f7eeebf5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/hif/sdio/x86.c @@ -0,0 +1,24 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/****************************************************************************** +*[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. +******************************************************************************/ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_ate_agent.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_ate_agent.h new file mode 100644 index 0000000000000..1360379c19ce7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_ate_agent.h @@ -0,0 +1,154 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ +/*! \file gl_ate_agent.h + * \brief This file includes private ioctl support. + */ + +#ifndef _GL_ATE_AGENT_H +#define _GL_ATE_AGENT_H +#if CFG_SUPPORT_QA_TOOL +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +extern UINT_32 u4RxStatSeqNum; + +#if CFG_SUPPORT_TX_BF +extern PFMU_PROFILE_TAG1 g_rPfmuTag1; +extern PFMU_PROFILE_TAG2 g_rPfmuTag2; +extern PFMU_DATA g_rPfmuData; +#endif +extern BOOLEAN g_bCaptureDone; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef struct _STA_REC_BF_UPD_ARGUMENT { + UINT_32 u4WlanId; + UINT_32 u4BssId; + UINT_32 u4PfmuId; + UINT_32 u4SuMu; + UINT_32 u4eTxBfCap; + UINT_32 u4NdpaRate; + UINT_32 u4NdpRate; + UINT_32 u4ReptPollRate; + UINT_32 u4TxMode; + UINT_32 u4Nc; + UINT_32 u4Nr; + UINT_32 u4Bw; + UINT_32 u4SpeIdx; + UINT_32 u4TotalMemReq; + UINT_32 u4MemReq20M; + UINT_32 au4MemRow[4]; + UINT_32 au4MemCol[4]; +} STA_REC_BF_UPD_ARGUMENT, *P_STA_REC_BF_UPD_ARGUMENT; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +int Set_ResetStatCounter_Proc(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetATE(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetATEDa(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetATESa(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetATEChannel(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetATETxPower0(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetATETxGi(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetATETxBw(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetATETxMode(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetATETxLength(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetATETxCount(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetATETxMcs(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetATEIpg(struct net_device *prNetDev, UINT_8 *prInBuf); + +#if CFG_SUPPORT_TX_BF +int Set_TxBfProfileTag_Help(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_InValid(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_PfmuIdx(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_BfType(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_DBW(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_SuMu(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_Mem(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_Matrix(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_SNR(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_SmartAnt(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_SeIdx(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_RmsdThrd(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_McsThrd(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_TimeOut(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_DesiredBW(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_DesiredNc(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_DesiredNr(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTagRead(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTagWrite(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_StaRecCmmUpdate(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_StaRecBfUpdate(struct net_device *prNetDev, UINT_8 *prInBuf); + +int Set_DevInfoUpdate(struct net_device *prNetDev, UINT_8 *prInBuf); + +int Set_BssInfoUpdate(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileDataRead(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileDataWrite(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_Trigger_Sounding_Proc(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_Stop_Sounding_Proc(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfTxApply(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfilePnRead(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfilePnWrite(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfManualAssoc(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfPfmuMemAlloc(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfPfmuMemRelease(struct net_device *prNetDev, UINT_8 *prInBuf); + +#if CFG_SUPPORT_MU_MIMO +int Set_MUGetInitMCS(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_MUCalInitMCS(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_MUCalLQ(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_MUGetLQ(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_MUSetSNROffset(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_MUSetZeroNss(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_MUSetSpeedUpLQ(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_MUSetMUTable(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_MUSetGroup(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_MUGetQD(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_MUSetEnable(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_MUSetGID_UP(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_MUTriggerTx(struct net_device *prNetDev, UINT_8 *prInBuf); +#endif +#endif + + +int WriteEfuse(struct net_device *prNetDev, UINT_8 *prInBuf); + + +int AteCmdSetHandle(struct net_device *prNetDev, UINT_8 *prInBuf, UINT_32 u4InBufLen); +#endif /*CFG_SUPPORT_QA_TOOL */ +#endif /* _GL_ATE_AGENT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_cfg80211.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_cfg80211.h new file mode 100644 index 0000000000000..b376e66dbba55 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_cfg80211.h @@ -0,0 +1,340 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_cfg80211.h#1 + */ + +/* + * ! \file gl_cfg80211.h + * \brief This file is for Portable Driver linux cfg80211 support. + */ + +#ifndef _GL_CFG80211_H +#define _GL_CFG80211_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#include +#include + +#include "gl_os.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#if CONFIG_NL80211_TESTMODE +#define NL80211_DRIVER_TESTMODE_VERSION 2 +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +#if CFG_SUPPORT_NFC_BEAM_PLUS + +typedef struct _NL80211_DRIVER_SET_NFC_PARAMS { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + UINT_32 NFC_Enable; + +} NL80211_DRIVER_SET_NFC_PARAMS, *P_NL80211_DRIVER_SET_NFC_PARAMS; + +#endif + +#if CONFIG_NL80211_TESTMODE + +typedef struct _NL80211_DRIVER_GET_STA_STATISTICS_PARAMS { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + UINT_32 u4Version; + UINT_32 u4Flag; + UINT_8 aucMacAddr[MAC_ADDR_LEN]; +} NL80211_DRIVER_GET_STA_STATISTICS_PARAMS, *P_NL80211_DRIVER_GET_STA_STATISTICS_PARAMS; + +typedef enum _ENUM_TESTMODE_LINK_DETECTION_ATTR { + NL80211_TESTMODE_LINK_INVALID = 0, + NL80211_TESTMODE_LINK_TX_FAIL_CNT, + NL80211_TESTMODE_LINK_TX_RETRY_CNT, + NL80211_TESTMODE_LINK_TX_MULTI_RETRY_CNT, + NL80211_TESTMODE_LINK_ACK_FAIL_CNT, + NL80211_TESTMODE_LINK_FCS_ERR_CNT, + NL80211_TESTMODE_LINK_TX_CNT, + NL80211_TESTMODE_LINK_RX_CNT, + + NL80211_TESTMODE_LINK_DETECT_NUM, +} ENUM_TESTMODE_LINK_DETECTION_ATTR; + +typedef enum _ENUM_TESTMODE_STA_STATISTICS_ATTR { + NL80211_TESTMODE_STA_STATISTICS_INVALID = 0, + NL80211_TESTMODE_STA_STATISTICS_VERSION, + NL80211_TESTMODE_STA_STATISTICS_MAC, + NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE, + NL80211_TESTMODE_STA_STATISTICS_FLAG, + + NL80211_TESTMODE_STA_STATISTICS_PER, + NL80211_TESTMODE_STA_STATISTICS_RSSI, + NL80211_TESTMODE_STA_STATISTICS_PHY_MODE, + NL80211_TESTMODE_STA_STATISTICS_TX_RATE, + + NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT, + NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT, + + NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME, + NL80211_TESTMODE_STA_STATISTICS_MAX_PROCESS_TIME, + NL80211_TESTMODE_STA_STATISTICS_AVG_HIF_PROCESS_TIME, + NL80211_TESTMODE_STA_STATISTICS_MAX_HIF_PROCESS_TIME, + + NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT, + NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT, + NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME, + + NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY, + + /* + * how many packages TX during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_ENQUEUE, + + /* + * how many packages this TX during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_STA_ENQUEUE, + + /* + * how many packages dequeue during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_DEQUEUE, + + /* + * how many packages this sta dequeue during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_STA_DEQUEUE, + + /* + * how many TC[0-3] resource back from firmware during + * statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_RB_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_NO_TC_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_USED_TC_PGCT_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_WANTED_TC_PGCT_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_PASS_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_TASK_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_AB_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_SW_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_TX_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_RX_CNT, + + + NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_NUM +} ENUM_TESTMODE_STA_STATISTICS_ATTR; + +#endif +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/* cfg80211 hooks */ +#if (KERNEL_VERSION(4, 12, 0) <= LINUX_VERSION_CODE) +int +mtk_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, enum nl80211_iftype type, struct vif_params *params); +#else +int +mtk_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, enum nl80211_iftype type, u32 *flags, struct vif_params *params); +#endif + +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, const u8 *mac, struct station_info *sinfo); + +int +mtk_cfg80211_get_link_statistics(struct wiphy *wiphy, struct net_device *ndev, u8 *mac, struct station_info *sinfo); + +int mtk_cfg80211_scan(struct wiphy *wiphy, + struct cfg80211_scan_request *request); + +#if CFG_SUPPORT_ABORT_SCAN +void mtk_cfg80211_abort_scan(struct wiphy *wiphy, struct wireless_dev *wdev); +#endif + +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_set_rekey_data(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_gtk_rekey_data *data); + +int mtk_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, + unsigned int duration, u64 *cookie); + +int mtk_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie); + +int mtk_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie); + +void mtk_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, + IN struct wireless_dev *wdev, + IN u16 frame_type, IN bool reg); + +int mtk_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie); + +#if CONFIG_NL80211_TESTMODE +int +mtk_cfg80211_testmode_get_sta_statistics(IN struct wiphy *wiphy, + IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo); + +int mtk_cfg80211_testmode_get_scan_done(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo); +int mtk_cfg80211_testmode_cmd(IN struct wiphy *wiphy, IN struct wireless_dev *wdev, IN void *data, IN int len); + +int mtk_cfg80211_testmode_sw_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); + +#if CFG_SUPPORT_PASSPOINT +int mtk_cfg80211_testmode_hs20_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_WAPI +int mtk_cfg80211_testmode_set_key_ext(IN struct wiphy *wiphy, IN void *data, IN int len); +#endif + +#if CFG_SUPPORT_NFC_BEAM_PLUS +int mtk_cfg80211_testmode_get_scan_done(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo); +#endif +#else +#error "Please ENABLE kernel config (CONFIG_NL80211_TESTMODE)" +#endif + +int +mtk_cfg80211_sched_scan_start(IN struct wiphy *wiphy, + IN struct net_device *ndev, IN struct cfg80211_sched_scan_request *request); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) +int mtk_cfg80211_sched_scan_stop(IN struct wiphy *wiphy, IN struct net_device *ndev); +#else +int mtk_cfg80211_sched_scan_stop(IN struct wiphy *wiphy, + IN struct net_device *ndev, IN UINT_64 reqid); +#endif + +int mtk_cfg80211_assoc(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_assoc_request *req); + +int +mtk_cfg80211_change_station(struct wiphy *wiphy, struct net_device *ndev, const u8 *mac, + struct station_parameters *params); + +int mtk_cfg80211_add_station(struct wiphy *wiphy, struct net_device *ndev, const u8 *mac, + struct station_parameters *params); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +int mtk_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, struct station_del_parameters *params); +#else +int mtk_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, const u8 *mac); +#endif + +int +mtk_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, bool initiator, const u8 *buf, size_t len); + +int mtk_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, const u8 *peer, + enum nl80211_tdls_operation oper); + +int mtk_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow); + +int mtk_cfg80211_resume(struct wiphy *wiphy); + +INT_32 mtk_cfg80211_process_str_cmd(P_GLUE_INFO_T prGlueInfo, PUINT_8 cmd, INT_32 len); + +int mtk_cfg80211_update_ft_ies(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_update_ft_ies_params *ftie); + +#if (defined(NL80211_ATTR_EXTERNAL_AUTH_SUPPORT) \ + || LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) +int mtk_cfg80211_external_auth(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_external_auth_params *params); +#endif +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _GL_CFG80211_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_hook_api.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_hook_api.h new file mode 100644 index 0000000000000..318fc85773013 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_hook_api.h @@ -0,0 +1,187 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ +/*! \file gl_hook_api.h + * \brief This file includes private ioctl support. + */ + +#ifndef _GL_HOOK_API_H +#define _GL_HOOK_API_H +#if CFG_SUPPORT_QA_TOOL +/******************************************************************************* +* C O M P I L E 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 +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +INT_32 MT_ATEStart(struct net_device *prNetDev, UINT_8 *prInBuf); +INT_32 MT_ICAPStart(struct net_device *prNetDev, UINT_8 *prInBuf); +INT_32 MT_ATEStop(struct net_device *prNetDev, UINT_8 *prInBuf); +INT_32 MT_ATEStartTX(struct net_device *prNetDev, UINT_8 *prInBuf); +INT_32 MT_ATEStopTX(struct net_device *prNetDev, UINT_8 *prInBuf); +INT_32 MT_ATEStartRX(struct net_device *prNetDev, UINT_8 *prInBuf); +INT_32 MT_ATEStopRX(struct net_device *prNetDev, UINT_8 *prInBuf); +INT_32 MT_ATESetChannel(struct net_device *prNetDev, UINT_32 u4SXIdx, UINT_32 u4SetFreq); +INT_32 MT_ATESetPreamble(struct net_device *prNetDev, UINT_32 u4Mode); +INT_32 MT_ATESetSystemBW(struct net_device *prNetDev, UINT_32 u4BW); +INT_32 MT_ATESetTxLength(struct net_device *prNetDev, UINT_32 u4TxLength); +INT_32 MT_ATESetTxCount(struct net_device *prNetDev, UINT_32 u4TxCount); +INT_32 MT_ATESetTxIPG(struct net_device *prNetDev, UINT_32 u4TxIPG); +INT_32 MT_ATESetTxPower0(struct net_device *prNetDev, UINT_32 u4TxPower0); +INT_32 MT_ATESetPerPacketBW(struct net_device *prNetDev, UINT_32 u4BW); +INT_32 MT_ATEPrimarySetting(struct net_device *prNetDev, UINT_32 u4PrimaryCh); +INT_32 MT_ATESetTxGi(struct net_device *prNetDev, UINT_32 u4SetTxGi); +INT_32 MT_ATESetTxPayLoad(struct net_device *prNetDev, UINT_32 u4Gen_payload_rule, UINT_8 ucPayload); +INT_32 MT_ATESetTxSTBC(struct net_device *prNetDev, UINT_32 u4Stbc); +INT_32 MT_ATESetTxPath(struct net_device *prNetDev, UINT_32 u4Tx_path); +INT_32 MT_ATESetTxVhtNss(struct net_device *prNetDev, UINT_32 u4VhtNss); +INT_32 MT_ATESetRate(struct net_device *prNetDev, UINT_32 u4Rate); +INT_32 MT_ATESetEncodeMode(struct net_device *prNetDev, UINT_32 u4Ldpc); +INT_32 MT_ATESetiBFEnable(struct net_device *prNetDev, UINT_32 u4iBF); +INT_32 MT_ATESeteBFEnable(struct net_device *prNetDev, UINT_32 u4eBF); +INT_32 MT_ATESetMACAddress(struct net_device *prNetDev, UINT_32 u4Type, UCHAR ucAddr[]); +INT_32 MT_ATELogOnOff(struct net_device *prNetDev, UINT_32 u4Type, UINT_32 u4On_off, UINT_32 u4Size); +INT_32 MT_ATEResetTXRXCounter(struct net_device *prNetDev); +INT_32 MT_ATESetDBDCBandIndex(struct net_device *prNetDev, UINT_32 u4BandIdx); +INT_32 MT_ATESetBand(struct net_device *prNetDev, INT_32 i4Band); +INT_32 MT_ATESetTxToneType(struct net_device *prNetDev, INT_32 i4ToneType); +INT_32 MT_ATESetTxToneBW(struct net_device *prNetDev, INT_32 i4ToneFreq); +INT_32 MT_ATESetTxToneDCOffset(struct net_device *prNetDev, INT_32 i4DcOffsetI, INT_32 i4DcOffsetQ); +INT_32 MT_ATESetDBDCTxTonePower(struct net_device *prNetDev, INT_32 i4AntIndex, INT_32 i4RF_Power, INT_32 i4Digi_Power); +INT_32 MT_ATEDBDCTxTone(struct net_device *prNetDev, INT_32 i4Control); +INT_32 MT_ATESetMacHeader(struct net_device *prNetDev, UINT_32 u2FrameCtrl, UINT_32 u2DurationID, UINT_32 u4SeqCtrl); +INT_32 MT_ATE_IRRSetADC(struct net_device *prNetDev, + UINT_32 u4WFIdx, + UINT_32 u4ChFreq, + UINT_32 u4BW, UINT_32 u4Sx, UINT_32 u4Band, UINT_32 u4RunType, UINT_32 u4FType); +INT_32 MT_ATE_IRRSetRxGain(struct net_device *prNetDev, + UINT_32 u4PgaLpfg, UINT_32 u4Lna, UINT_32 u4Band, UINT_32 u4WF_inx, UINT_32 u4Rfdgc); +INT_32 MT_ATE_IRRSetTTG(struct net_device *prNetDev, + UINT_32 u4TTGPwrIdx, UINT_32 u4ChFreq, UINT_32 u4FIToneFreq, UINT_32 u4Band); +INT_32 MT_ATE_IRRSetTrunOnTTG(struct net_device *prNetDev, UINT_32 u4TTGOnOff, UINT_32 u4Band, UINT_32 u4WF_inx); +INT_32 MT_ATE_TMRSetting(struct net_device *prNetDev, + UINT_32 u4Setting, UINT_32 u4Version, UINT_32 u4MPThres, UINT_32 u4MPIter); +INT_32 MT_ATERDDStart(struct net_device *prNetDev, UINT_8 *prInBuf); +INT_32 MT_ATERDDStop(struct net_device *prNetDev, UINT_8 *prInBuf); +INT_32 MT_ATEMPSSetSeqData(struct net_device *prNetDev, + UINT_32 u4TestNum, UINT_32 *pu4Phy, UINT_32 u4Band); +INT_32 MT_ATEMPSSetPayloadLength(struct net_device *prNetDev, + UINT_32 u4TestNum, UINT_32 *pu4Length, UINT_32 u4Band); +INT_32 MT_ATEMPSSetPacketCount(struct net_device *prNetDev, + UINT_32 u4TestNum, UINT_32 *pu4PktCnt, UINT_32 u4Band); +INT_32 MT_ATEMPSSetPowerGain(struct net_device *prNetDev, + UINT_32 u4TestNum, UINT_32 *pu4PwrGain, UINT_32 u4Band); +INT_32 MT_ATEMPSSetNss(struct net_device *prNetDev, + UINT_32 u4TestNum, UINT_32 *pu4Nss, UINT_32 u4Band); +INT_32 MT_ATEMPSSetPerpacketBW(struct net_device *prNetDev, + UINT_32 u4TestNum, UINT_32 *pu4PerPktBW, UINT_32 u4Band); + + +INT_32 MT_ATEWriteEfuse(struct net_device *prNetDev, UINT_16 u2Offset, UINT_16 u2Content); + + +#if CFG_SUPPORT_TX_BF +INT_32 TxBfProfileTag_InValid(struct net_device *prNetDev, P_PFMU_PROFILE_TAG1 prPfmuTag1, UINT_8 ucInValid); +INT_32 TxBfProfileTag_PfmuIdx(struct net_device *prNetDev, P_PFMU_PROFILE_TAG1 prPfmuTag1, UINT_8 ucProfileIdx); +INT_32 TxBfProfileTag_TxBfType(struct net_device *prNetDev, P_PFMU_PROFILE_TAG1 prPfmuTag1, UINT_8 ucBFType); +INT_32 TxBfProfileTag_DBW(struct net_device *prNetDev, P_PFMU_PROFILE_TAG1 prPfmuTag1, UINT_8 ucBW); +INT_32 TxBfProfileTag_SuMu(struct net_device *prNetDev, P_PFMU_PROFILE_TAG1 prPfmuTag1, UINT_8 ucSuMu); +INT_32 TxBfProfileTag_Mem(struct net_device *prNetDev, + P_PFMU_PROFILE_TAG1 prPfmuTag1, PUINT_8 aucMemAddrColIdx, PUINT_8 aucMemAddrRowIdx); +INT_32 TxBfProfileTag_Matrix(struct net_device *prNetDev, + P_PFMU_PROFILE_TAG1 prPfmuTag1, + UINT_8 ucNrow, + UINT_8 ucNcol, UINT_8 ucNgroup, UINT_8 ucLM, UINT_8 ucCodeBook, UINT_8 ucHtcExist); +INT_32 TxBfProfileTag_SNR(struct net_device *prNetDev, + P_PFMU_PROFILE_TAG1 prPfmuTag1, + UINT_8 ucSNR_STS0, UINT_8 ucSNR_STS1, UINT_8 ucSNR_STS2, UINT_8 ucSNR_STS3); +INT_32 TxBfProfileTag_SmtAnt(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucSmartAnt); +INT_32 TxBfProfileTag_SeIdx(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucSeIdx); +INT_32 TxBfProfileTag_RmsdThd(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucRmsdThrd); +INT_32 TxBfProfileTag_McsThd(struct net_device *prNetDev, + P_PFMU_PROFILE_TAG2 prPfmuTag2, PUINT_8 pMCSThLSS, PUINT_8 pMCSThSSS); +INT_32 TxBfProfileTag_TimeOut(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucTimeOut); +INT_32 TxBfProfileTag_DesiredBW(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucDesiredBW); +INT_32 TxBfProfileTag_DesiredNc(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucDesiredNc); +INT_32 TxBfProfileTag_DesiredNr(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucDesiredNr); +INT_32 TxBfProfileTagWrite(struct net_device *prNetDev, + P_PFMU_PROFILE_TAG1 prPfmuTag1, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 profileIdx); +INT_32 TxBfProfileTagRead(struct net_device *prNetDev, UINT_8 PfmuIdx, UINT_8 fgBFer); +INT_32 TxBfProfileDataRead(struct net_device *prNetDev, + UINT_8 profileIdx, UINT_8 fgBFer, UINT_8 subcarrierIdxMsb, UINT_8 subcarrierIdxLsb); +INT_32 TxBfProfileDataWrite(struct net_device *prNetDev, + UINT_8 profileIdx, + UINT_16 subcarrierIdx, UINT_16 au2Phi[6], UINT_8 aucPsi[6], UINT_8 aucDSnr[4] +); +INT_32 TxBfProfilePnRead(struct net_device *prNetDev, UINT_8 profileIdx); +INT_32 TxBfProfilePnWrite(struct net_device *prNetDev, UINT_8 ucProfileIdx, UINT_16 u2bw, UINT_16 au2XSTS[12]); + +INT_32 TxBfSounding(struct net_device *prNetDev, UINT_8 ucSuMu, /* 0/1/2/3 */ + UINT_8 ucNumSta, /* 00~04 */ + UINT_8 ucSndInterval, /* 00~FF */ + UINT_8 ucWLan0, /* 00~7F */ + UINT_8 ucWLan1, /* 00~7F */ + UINT_8 ucWLan2, /* 00~7F */ + + UINT_8 ucWLan3 /* 00~7F */ +); +INT_32 TxBfSoundingStop(struct net_device *prNetDev); +INT_32 TxBfTxApply(struct net_device *prNetDev, UINT_8 ucWlanId, UINT_8 fgETxBf, UINT_8 fgITxBf, UINT_8 fgMuTxBf); + +INT_32 TxBfManualAssoc(struct net_device *prNetDev, + UINT_8 aucMac[MAC_ADDR_LEN], + UINT_8 ucType, + UINT_8 ucWtbl, + UINT_8 ucOwnmac, + UINT_8 ucPhyMode, + UINT_8 ucBw, + UINT_8 ucNss, UINT_8 ucPfmuId, UINT_8 ucMarate, UINT_8 ucSpeIdx, UINT_8 ucRca2, UINT_8 ucRv); + +INT_32 TxBfPfmuMemAlloc(struct net_device *prNetDev, UINT_8 ucSuMuMode, UINT_8 ucWlanIdx); + +INT_32 TxBfPfmuMemRelease(struct net_device *prNetDev, UINT_8 ucWlanId); + +INT_32 DevInfoUpdate(struct net_device *prNetDev, UINT_8 ucOwnMacIdx, UINT_8 fgBand, UINT_8 aucMacAddr[MAC_ADDR_LEN]); + +INT_32 BssInfoUpdate(struct net_device *prNetDev, UINT_8 u4OwnMacIdx, UINT_8 u4BssIdx, UINT_8 u4BssId[MAC_ADDR_LEN]); + +INT_32 StaRecCmmUpdate(struct net_device *prNetDev, + UINT_8 ucWlanId, UINT_8 ucBssId, UINT_8 u4Aid, UINT_8 aucMacAddr[MAC_ADDR_LEN] +); + +INT_32 StaRecBfUpdate(struct net_device *prNetDev, + STA_REC_BF_UPD_ARGUMENT rStaRecBfUpdArg, UINT_8 aucMemRow[4], UINT_8 aucMemCol[4] +); + +#endif +#endif /*CFG_SUPPORT_QA_TOOL */ +#endif /* _GL_HOOK_API_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_kal.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_kal.h new file mode 100644 index 0000000000000..f01e351f4f8f3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_kal.h @@ -0,0 +1,1188 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_kal.h#2 +*/ + +/* + * ! \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. + */ + +#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 "gl_wext_priv.h" +#include "link.h" +#include "nic/mac.h" +#include "nic/wlan_def.h" +#include "wlan_lib.h" +#include "wlan_oid.h" + +#if CFG_ENABLE_BT_OVER_WIFI +#include "nic/bow.h" +#endif + +#include "linux/kallsyms.h" +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +#include +#else +#include +#endif + +#if DBG +extern int allocatedMemSize; +#endif + +extern struct delayed_work sched_workq; +#if CFG_MODIFY_TX_POWER_BY_BAT_VOLT +extern unsigned int wlan_bat_volt; +#endif +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* Define how many concurrent operation networks. */ +#define KAL_BSS_NUM 3 +#define KAL_P2P_NUM 1 + +#if CFG_SUPPORT_MULTITHREAD +#define GLUE_FLAG_TX_PROCESS (GLUE_FLAG_HALT | \ + GLUE_FLAG_SUB_MOD_MULTICAST | \ + GLUE_FLAG_TX_CMD_DONE | \ + GLUE_FLAG_TXREQ | \ + GLUE_FLAG_TIMEOUT | \ + GLUE_FLAG_FRAME_FILTER | \ + GLUE_FLAG_OID | \ + GLUE_FLAG_RX) + +#define GLUE_FLAG_HIF_PROCESS \ + (GLUE_FLAG_HALT | GLUE_FLAG_INT | GLUE_FLAG_HIF_TX | GLUE_FLAG_HIF_TX_CMD | GLUE_FLAG_HIF_FW_OWN | \ + GLUE_FLAG_HAL_MCR_RD | GLUE_FLAG_HAL_MCR_WR) + +#define GLUE_FLAG_RX_PROCESS (GLUE_FLAG_HALT | GLUE_FLAG_RX_TO_OS) +#else +/* All flags for single thread driver */ +#define GLUE_FLAG_TX_PROCESS 0xFFFFFFFF +#endif + +#if CFG_SUPPORT_SNIFFER +#define RADIOTAP_FIELD_TSFT BIT(0) +#define RADIOTAP_FIELD_FLAGS BIT(1) +#define RADIOTAP_FIELD_RATE BIT(2) +#define RADIOTAP_FIELD_CHANNEL BIT(3) +#define RADIOTAP_FIELD_ANT_SIGNAL BIT(5) +#define RADIOTAP_FIELD_ANT_NOISE BIT(6) +#define RADIOTAP_FIELD_ANT BIT(11) +#define RADIOTAP_FIELD_MCS BIT(19) +#define RADIOTAP_FIELD_AMPDU BIT(20) +#define RADIOTAP_FIELD_VHT BIT(21) +#define RADIOTAP_FIELD_VENDOR BIT(30) + +#define RADIOTAP_LEN_VHT 48 +#define RADIOTAP_FIELDS_VHT (RADIOTAP_FIELD_TSFT | \ + RADIOTAP_FIELD_FLAGS | \ + RADIOTAP_FIELD_RATE | \ + RADIOTAP_FIELD_CHANNEL | \ + RADIOTAP_FIELD_ANT_SIGNAL | \ + RADIOTAP_FIELD_ANT_NOISE | \ + RADIOTAP_FIELD_ANT | \ + RADIOTAP_FIELD_AMPDU | \ + RADIOTAP_FIELD_VHT | \ + RADIOTAP_FIELD_VENDOR) + +#define RADIOTAP_LEN_HT 36 +#define RADIOTAP_FIELDS_HT (RADIOTAP_FIELD_TSFT | \ + RADIOTAP_FIELD_FLAGS | \ + RADIOTAP_FIELD_RATE | \ + RADIOTAP_FIELD_CHANNEL | \ + RADIOTAP_FIELD_ANT_SIGNAL | \ + RADIOTAP_FIELD_ANT_NOISE | \ + RADIOTAP_FIELD_ANT | \ + RADIOTAP_FIELD_MCS | \ + RADIOTAP_FIELD_AMPDU | \ + RADIOTAP_FIELD_VENDOR) + +#define RADIOTAP_LEN_LEGACY 26 +#define RADIOTAP_FIELDS_LEGACY (RADIOTAP_FIELD_TSFT | \ + RADIOTAP_FIELD_FLAGS | \ + RADIOTAP_FIELD_RATE | \ + RADIOTAP_FIELD_CHANNEL | \ + RADIOTAP_FIELD_ANT_SIGNAL | \ + RADIOTAP_FIELD_ANT_NOISE | \ + RADIOTAP_FIELD_ANT | \ + RADIOTAP_FIELD_VENDOR) +#endif +#ifdef CFG_SUPPORT_DATA_STALL +#define REPORT_EVENT_INTERVAL 30 +#define EVENT_PER_HIGH_THRESHOLD 80 +#define EVENT_TX_LOW_RATE_THRESHOLD 20 +#define EVENT_RX_LOW_RATE_THRESHOLD 20 +#define TRAFFIC_RHRESHOLD 150 +#endif + +#if CFG_SUPPORT_REPORT_MISC +#define EXT_SRC_DHCP_BIT 1 +#define EXT_SRC_DISCONNCT_BIT 2 +#endif +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_SPIN_LOCK_CATEGORY_E { + SPIN_LOCK_FSM = 0, + +#if CFG_SUPPORT_MULTITHREAD + SPIN_LOCK_TX_PORT_QUE, + SPIN_LOCK_TX_CMD_QUE, + SPIN_LOCK_TX_CMD_DONE_QUE, + SPIN_LOCK_TC_RESOURCE, + SPIN_LOCK_RX_TO_OS_QUE, +#endif + + /* FIX ME */ + SPIN_LOCK_RX_QUE, + SPIN_LOCK_RX_FREE_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; + +typedef enum _ENUM_MUTEX_CATEGORY_E { + MUTEX_TX_CMD_CLEAR, + MUTEX_NUM +} ENUM_MUTEX_CATEGORY_E; + +/* event for assoc information update */ +typedef struct _EVENT_ASSOC_INFO { + UINT_8 ucAssocReq; /* 1 for assoc req, 0 for assoc rsp */ + UINT_8 ucReassoc; /* 0 for assoc, 1 for reassoc */ + UINT_16 u2Length; + PUINT_8 pucIe; +} EVENT_ASSOC_INFO, *P_EVENT_ASSOC_INFO; + +typedef enum _ENUM_KAL_NETWORK_TYPE_INDEX_T { + KAL_NETWORK_TYPE_AIS_INDEX = 0, +#if CFG_ENABLE_WIFI_DIRECT + KAL_NETWORK_TYPE_P2P_INDEX, +#endif +#if CFG_ENABLE_BT_OVER_WIFI + KAL_NETWORK_TYPE_BOW_INDEX, +#endif + KAL_NETWORK_TYPE_INDEX_NUM +} ENUM_KAL_NETWORK_TYPE_INDEX_T; + +typedef enum _ENUM_KAL_MEM_ALLOCATION_TYPE_E { + PHY_MEM_TYPE, /* physically continuous */ + VIR_MEM_TYPE, /* virtually continuous */ + MEM_TYPE_NUM +} ENUM_KAL_MEM_ALLOCATION_TYPE; + +#if CONFIG_ANDROID /* Defined in Android kernel source */ + +#ifdef CONFIG_WAKELOCK +typedef struct wake_lock KAL_WAKE_LOCK_T, *P_KAL_WAKE_LOCK_T; +#define KAL_WAKELOCK_DECLARE(_lock) \ + struct wake_lock _lock +#else +#define KAL_WAKE_LOCK_T struct wakeup_source +#define KAL_WAKELOCK_DECLARE(_lock) \ + struct wakeup_source _lock +#endif /*CONFIG_WAKELOCK*/ + +#else +typedef UINT_32 KAL_WAKE_LOCK_T, *P_KAL_WAKE_LOCK_T; +#define KAL_WAKELOCK_DECLARE(_lock) +#endif + +#if CFG_SUPPORT_AGPS_ASSIST +typedef enum _ENUM_MTK_AGPS_ATTR { + MTK_ATTR_AGPS_INVALID, + MTK_ATTR_AGPS_CMD, + MTK_ATTR_AGPS_DATA, + MTK_ATTR_AGPS_IFINDEX, + MTK_ATTR_AGPS_IFNAME, + MTK_ATTR_AGPS_MAX +} ENUM_MTK_CCX_ATTR; + +typedef enum _ENUM_AGPS_EVENT { + AGPS_EVENT_WLAN_ON, + AGPS_EVENT_WLAN_OFF, + AGPS_EVENT_WLAN_AP_LIST, +} ENUM_CCX_EVENT; +#ifdef CFG_SUPPORT_DATA_STALL +enum ENUM_VENDOR_DRIVER_EVENT { + EVENT_TEST_MODE, + EVENT_ARP_NO_RESPONSE, + EVENT_PER_HIGH, + EVENT_TX_LOW_RATE, + EVENT_RX_LOW_RATE +}; +#endif + +BOOLEAN kalIndicateAgpsNotify(P_ADAPTER_T prAdapter, UINT_8 cmd, PUINT_8 data, UINT_16 dataLen); +#endif /* CFG_SUPPORT_AGPS_ASSIST */ + +#if CFG_SUPPORT_SNIFFER +/* Vendor Namespace + * Bit Number 30 + * Required Alignment 2 bytes + */ +typedef struct _RADIOTAP_FIELD_VENDOR_T { + UINT_8 aucOUI[3]; + UINT_8 ucSubNamespace; + UINT_16 u2DataLen; + UINT_8 ucData; +} __packed RADIOTAP_FIELD_VENDOR_T, *P_RADIOTAP_FIELD_VENDOR_T; + +typedef struct _MONITOR_RADIOTAP_T { + /* radiotap header */ + UINT_8 ucItVersion; /* set to 0 */ + UINT_8 ucItPad; + UINT_16 u2ItLen; /* entire length */ + UINT_32 u4ItPresent; /* fields present */ + + /* TSFT + * Bit Number 0 + * Required Alignment 8 bytes + * Unit microseconds + */ + UINT_64 u8MacTime; + + /* Flags + * Bit Number 1 + */ + UINT_8 ucFlags; + + /* Rate + * Bit Number 2 + * Unit 500 Kbps + */ + UINT_8 ucRate; + + /* Channel + * Bit Number 3 + * Required Alignment 2 bytes + */ + UINT_16 u2ChFrequency; + UINT_16 u2ChFlags; + + /* Antenna signal + * Bit Number 5 + * Unit dBm + */ + UINT_8 ucAntennaSignal; + + /* Antenna noise + * Bit Number 6 + * Unit dBm + */ + UINT_8 ucAntennaNoise; + + /* Antenna + * Bit Number 11 + * Unit antenna index + */ + UINT_8 ucAntenna; + + /* MCS + * Bit Number 19 + * Required Alignment 1 byte + */ + UINT_8 ucMcsKnown; + UINT_8 ucMcsFlags; + UINT_8 ucMcsMcs; + + /* A-MPDU status + * Bit Number 20 + * Required Alignment 4 bytes + */ + UINT_32 u4AmpduRefNum; + UINT_16 u2AmpduFlags; + UINT_8 ucAmpduDelimiterCRC; + UINT_8 ucAmpduReserved; + + /* VHT + * Bit Number 21 + * Required Alignment 2 bytes + */ + UINT_16 u2VhtKnown; + UINT_8 ucVhtFlags; + UINT_8 ucVhtBandwidth; + UINT_8 aucVhtMcsNss[4]; + UINT_8 ucVhtCoding; + UINT_8 ucVhtGroupId; + UINT_16 u2VhtPartialAid; + + /* extension space */ + UINT_8 aucReserve[12]; +} __packed MONITOR_RADIOTAP_T, *P_MONITOR_RADIOTAP_T; +#endif + +struct KAL_HALT_CTRL_T { + struct semaphore lock; + struct task_struct *owner; + BOOLEAN fgHalt; + BOOLEAN fgHeldByKalIoctl; + OS_SYSTIME u4HoldStart; +}; + +enum VCORE_ACTION_T { + VCORE_ADD_HIGHER_REQ, + VCORE_DEC_HIGHER_REQ, + VCORE_RESTORE_DEF, + VCORE_SET_HIGHER, + VCORE_CLEAR_ALL_REQ, + VCORE_ACTION_MAX_NUM +}; +/******************************************************************************* +* P U B 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 KAL_SET_BIT(bitOffset, value) set_bit(bitOffset, &value) +#define KAL_CLR_BIT(bitOffset, value) clear_bit(bitOffset, &value) +#define KAL_TEST_AND_CLEAR_BIT(bitOffset, value) test_and_clear_bit(bitOffset, &value) +#define KAL_TEST_BIT(bitOffset, value) test_bit(bitOffset, &value) + +/*----------------------------------------------------------------------------*/ +/* Macros of getting current thread id */ +/*----------------------------------------------------------------------------*/ +#define KAL_GET_CURRENT_THREAD_ID() (current->pid) +#define KAL_GET_CURRENT_THREAD_NAME() (current->comm) + +/*----------------------------------------------------------------------------*/ +/* Macros of SPIN LOCK operations for using in Driver Layer */ +/*----------------------------------------------------------------------------*/ +#define KAL_SPIN_LOCK_DECLARATION() unsigned long __ulFlags + +#define KAL_ACQUIRE_SPIN_LOCK(_prAdapter, _rLockCategory) \ + kalAcquireSpinLock(((P_ADAPTER_T)_prAdapter)->prGlueInfo, _rLockCategory, &__ulFlags) + +#define KAL_RELEASE_SPIN_LOCK(_prAdapter, _rLockCategory) \ + kalReleaseSpinLock(((P_ADAPTER_T)_prAdapter)->prGlueInfo, _rLockCategory, __ulFlags) + +/*----------------------------------------------------------------------------*/ +/* Macros of MUTEX operations for using in Driver Layer */ +/*----------------------------------------------------------------------------*/ +#define KAL_ACQUIRE_MUTEX(_prAdapter, _rLockCategory) \ + kalAcquireMutex(((P_ADAPTER_T)_prAdapter)->prGlueInfo, _rLockCategory) + +#define KAL_RELEASE_MUTEX(_prAdapter, _rLockCategory) \ + kalReleaseMutex(((P_ADAPTER_T)_prAdapter)->prGlueInfo, _rLockCategory) + +/*----------------------------------------------------------------------------*/ +/* 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 for kernel related defines */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(4, 7, 0) <= CFG80211_VERSION_CODE +/** + * enum nl80211_band - Frequency band + * @NL80211_BAND_2GHZ: 2.4 GHz ISM band + * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz) + * @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 64.80 GHz) + * @NUM_NL80211_BANDS: number of bands, avoid using this in userspace + * since newer kernel versions may support more bands + */ +#define KAL_BAND_2GHZ NL80211_BAND_2GHZ +#define KAL_BAND_5GHZ NL80211_BAND_5GHZ +#define KAL_NUM_BANDS NUM_NL80211_BANDS +#else +#define KAL_BAND_2GHZ IEEE80211_BAND_2GHZ +#define KAL_BAND_5GHZ IEEE80211_BAND_5GHZ +#define KAL_NUM_BANDS IEEE80211_NUM_BANDS +#endif + +/*----------------------------------------------------------------------------*/ +/* Macros of wake_lock operations for using in Driver Layer */ +/*----------------------------------------------------------------------------*/ +#if CONFIG_ANDROID /* Defined in Android kernel source */ +#ifdef CONFIG_WAKELOCK +#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) + +#define KAL_WAKE_LOCK_ACTIVE(_prAdapter, _prWakeLock) \ + wake_lock_active(_prWakeLock) +#else +#define KAL_WAKE_LOCK_INIT(_prAdapter, _prWakeLock, _pcName) \ + wakeup_source_init(_prWakeLock, _pcName) + +#define KAL_WAKE_LOCK_DESTROY(_prAdapter, _prWakeLock) \ + wakeup_source_trash(_prWakeLock) + +#define KAL_WAKE_LOCK(_prAdapter, _prWakeLock) \ + __pm_stay_awake(_prWakeLock) + +#define KAL_WAKE_LOCK_TIMEOUT(_prAdapter, _prWakeLock, _u4Timeout) \ + __pm_wakeup_event(_prWakeLock, JIFFIES_TO_MSEC(_u4Timeout)) + +#define KAL_WAKE_UNLOCK(_prAdapter, _prWakeLock) \ + __pm_relax(_prWakeLock) + +#define KAL_WAKE_LOCK_ACTIVE(_prAdapter, _prWakeLock) \ + ((_prWakeLock)->active) +#endif /*CONFIG_WAKELOCK*/ + +#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) +#define KAL_WAKE_LOCK_ACTIVE(_prAdapter, _prWakeLock) FALSE +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Cache memory allocation +* +* \param[in] u4Size Required memory size. +* \param[in] eMemType Memory allocation type +*Ps. when mem type is set to virtual +*and size is smaller than one PAGE_SIZE, +*it will be forced to malloc a physical +*address. +* +* \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 { \ + if (u4Size > PAGE_SIZE) \ + pvAddr = vmalloc(u4Size); \ + else \ + pvAddr = kmalloc(u4Size, GFP_KERNEL); \ + } \ + if (pvAddr) { \ + allocatedMemSize += u4Size; \ + DBGLOG(INIT, INFO, "0x%p(%ld) allocated (%s:%s)\n", \ + pvAddr, (UINT_32)u4Size, __FILE__, __func__; \ + } \ + pvAddr; \ +}) +#else +#define kalMemAlloc(u4Size, eMemType) ({ \ + void *pvAddr; \ + if (eMemType == PHY_MEM_TYPE) { \ + pvAddr = kmalloc(u4Size, GFP_KERNEL); \ + } \ + else { \ + if (u4Size > PAGE_SIZE) \ + pvAddr = vmalloc(u4Size); \ + else \ + pvAddr = kmalloc(u4Size, GFP_KERNEL); \ + } \ + if (!pvAddr) \ + ASSERT_NOMEM(); \ + pvAddr; \ +}) +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Free allocated cache memory +* +* \param[in] pvAddr Required memory size. +* \param[in] eMemType Memory allocation type +* \param[in] u4Size Allocated memory size. +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +#if DBG +#define kalMemFree(pvAddr, eMemType, u4Size) \ +{ \ + if (pvAddr) { \ + allocatedMemSize -= u4Size; \ + DBGLOG(INIT, INFO, "0x%p(%ld) freed (%s:%s)\n", \ + pvAddr, (UINT_32)u4Size, __FILE__, __func__; \ + } \ + kvfree(pvAddr); \ + +} +#else +#define kalMemFree(pvAddr, eMemType, u4Size) \ +{ \ + kvfree(pvAddr); \ +} +#endif + +#define kalUdelay(u4USec) udelay(u4USec) + +#define kalMdelay(u4MSec) mdelay(u4MSec) +#define kalMsleep(u4MSec) msleep(u4MSec) +#define kalUsleep_range(u4MinUSec, u4MaxUSec) usleep_range(u4MinUSec, u4MaxUSec) + +/* 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) + +#if KERNEL_VERSION(4, 0, 0) <= LINUX_VERSION_CODE +#define strnicmp(s1, s2, n) strncasecmp(s1, s2, n) +#endif + +/* string operation */ +#define kalStrCpy(dest, src) strcpy(dest, src) +#define kalStrnCpy(dest, src, n) strncpy(dest, src, n) +#define kalStrCmp(ct, cs) strcmp(ct, cs) +#define kalStrnCmp(ct, cs, n) strncmp(ct, cs, n) +#define kalStrChr(s, c) strchr(s, c) +#define kalStrrChr(s, c) strrchr(s, c) +#define kalStrnChr(s, n, c) strnchr(s, n, c) +#define kalStrLen(s) strlen(s) +#define kalStrnLen(s, b) strnlen(s, b) +#define kalStrniCmp(ct, cs, n) strncasecmp(ct, cs, n) +/* + * #define kalStrtoul(cp, endp, base) simple_strtoul(cp, endp, base) + * #define kalStrtol(cp, endp, base) simple_strtol(cp, endp, base) + */ +#define kalkStrtou32(cp, base, resp) kstrtou32(cp, base, resp) +#define kalkStrtos32(cp, base, resp) kstrtos32(cp, base, resp) +#define kalSnprintf(buf, size, fmt, ...) snprintf(buf, size, fmt, __VA_ARGS__) +#define kalSprintf(buf, fmt, ...) sprintf(buf, fmt, __VA_ARGS__) +/* remove for AOSP */ +/* #define kalSScanf(buf, fmt, ...) sscanf(buf, fmt, __VA_ARGS__) */ +#define kalStrStr(ct, cs) strstr(ct, cs) +#define kalStrSep(s, ct) strsep(s, ct) +#define kalStrCat(dest, src) strcat(dest, src) + +/* defined for wince sdio driver only */ +#if defined(_HIF_SDIO) +#define kalDevSetPowerState(prGlueInfo, ePowerMode) glSetPowerState(prGlueInfo, ePowerMode) +#else +#define kalDevSetPowerState(prGlueInfo, ePowerMode) +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Notify OS with SendComplete event of the specific packet. Linux should +* free packets here. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pvPacket Pointer of Packet Handle +* \param[in] status Status Code for OS upper layer +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +#define kalSendComplete(prGlueInfo, pvPacket, status) \ + kalSendCompleteAndAwakeQueue(prGlueInfo, pvPacket) + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to locate the starting address of incoming ethernet +* frame for skb. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pvPacket Pointer of Packet Handle +* +* \return starting address of ethernet frame buffer. +*/ +/*----------------------------------------------------------------------------*/ +#define kalQueryBufferPointer(prGlueInfo, pvPacket) \ + ((PUINT_8)((struct sk_buff *)pvPacket)->data) + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to query the length of valid buffer which is accessible during +* port read/write. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pvPacket Pointer of Packet Handle +* +* \return starting address of ethernet frame buffer. +*/ +/*----------------------------------------------------------------------------*/ +#define kalQueryValidBufferLength(prGlueInfo, pvPacket) \ + ((UINT_32)((struct sk_buff *)pvPacket)->end - \ + (UINT_32)((struct sk_buff *)pvPacket)->data) + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to copy the entire frame from skb to the destination +* address in the input parameter. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pvPacket Pointer of Packet Handle +* \param[in] pucDestBuffer Destination Address +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +#define kalCopyFrame(prGlueInfo, pvPacket, pucDestBuffer) \ + do {struct sk_buff *skb = (struct sk_buff *)pvPacket; \ + memcpy(pucDestBuffer, skb->data, skb->len); } while (0) + +#define kalGetTimeTick() jiffies_to_msecs(jiffies) + +#define WLAN_TAG "[wlan]" +#define kalPrint(_Fmt...) pr_info(WLAN_TAG _Fmt) +/* pr_info_ratelimited usage: max 10 lines logs are printed per 5 seconds, + * the others are dropped if exceed the rate limit and print "xxx callbacks suppressed" for tips + */ +#define kalPrintLimited(_Fmt...) pr_info_ratelimited(WLAN_TAG _Fmt) + +#define kalBreakPoint() \ +do { \ + WARN_ON(1); \ + 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 SNPRINTF(buf, left_size, arg) \ +do {\ + INT_32 ret_val = snprintf((char *)(buf), left_size, PRINTF_ARG arg);\ +\ + if (ret_val <= 0)\ + break;\ + left_size -= ret_val;\ + buf += ret_val;\ +} while (0) +#define USEC_TO_SYSTIME(_usec) ((_usec) / USEC_PER_MSEC) +#define MSEC_TO_SYSTIME(_msec) (_msec) + +#define MSEC_TO_JIFFIES(_msec) msecs_to_jiffies(_msec) +#define JIFFIES_TO_MSEC(_jiffie) jiffies_to_msecs(_jiffie) + +#define KAL_HALT_LOCK_TIMEOUT_NORMAL_CASE 3000 /* 3s */ +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Routines in gl_kal.c */ +/*----------------------------------------------------------------------------*/ +VOID kalAcquireSpinLock(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, OUT PULONG plFlags); + +VOID kalReleaseSpinLock(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, IN ULONG ulFlags); + +VOID kalUpdateMACAddress(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucMacAddr); + +VOID kalAcquireMutex(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_MUTEX_CATEGORY_E rMutexCategory); + +VOID kalReleaseMutex(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_MUTEX_CATEGORY_E rMutexCategory); + +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); + +WLAN_STATUS kalRxIndicateOnePkt(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPkt); + +VOID +kalIndicateStatusAndComplete(IN P_GLUE_INFO_T prGlueInfo, IN WLAN_STATUS eStatus, IN PVOID pvBuf, IN UINT_32 u4BufLen); + +VOID +kalUpdateReAssocReqInfo(IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBody, IN UINT_32 u4FrameBodyLen, IN BOOLEAN fgReassocRequest); + +VOID kalUpdateReAssocRspInfo(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucFrameBody, IN UINT_32 u4FrameBodyLen); + +#if CFG_TX_FRAGMENT +BOOLEAN +kalQueryTxPacketHeader(IN P_GLUE_INFO_T prGlueInfo, + IN PVOID pvPacket, OUT PUINT_16 pu2EtherTypeLen, OUT PUINT_8 pucEthDestAddr); +#endif /* CFG_TX_FRAGMENT */ + +VOID kalSendCompleteAndAwakeQueue(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +VOID kalQueryTxChksumOffloadParam(IN PVOID pvPacket, OUT PUINT_8 pucFlag); + +VOID kalUpdateRxCSUMOffloadParam(IN PVOID pvPacket, IN ENUM_CSUM_RESULT_T eCSUM[]); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +BOOLEAN kalRetrieveNetworkAddress(IN P_GLUE_INFO_T prGlueInfo, IN OUT PARAM_MAC_ADDRESS *prMacAddr); + +VOID +kalReadyOnChannel(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, + IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_8 ucChannelNum, IN UINT_32 u4DurationMs); + +VOID +kalRemainOnChannelExpired(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_8 ucChannelNum); + +VOID +kalIndicateMgmtTxStatus(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, IN BOOLEAN fgIsAck, IN PUINT_8 pucFrameBuf, IN UINT_32 u4FrameLen); + +VOID kalIndicateRxMgmtFrame(IN P_GLUE_INFO_T prGlueInfo, IN P_SW_RFB_T prSwRfb); + +/*----------------------------------------------------------------------------*/ +/* Routines in interface - ehpi/sdio.c */ +/*----------------------------------------------------------------------------*/ +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_32 u2Len, OUT PUINT_8 pucBuf, IN UINT_32 u2ValidOutBufSize); + +BOOL +kalDevPortWrite(P_GLUE_INFO_T prGlueInfo, + IN UINT_16 u2Port, IN UINT_32 u2Len, IN PUINT_8 pucBuf, IN UINT_32 u2ValidInBufSize); + +#if defined(MT6631) +void kalDumpAhbDebugInfo(P_GLUE_INFO_T prGlueInfo, UINT_16 u2ChipID); +#endif + +/* dump WTBL settings in HW */ +VOID kalDumpWTBL(P_ADAPTER_T prAdapter); + +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 + +#if (CFG_SUPPORT_DEBUG_STATISTICS == 1) +UINT_8 kalGetPktEtherType(IN PUINT_8 pucPkt); +#endif + +BOOLEAN +kalQoSFrameClassifierAndPacketInfo(IN P_GLUE_INFO_T prGlueInfo, + IN P_NATIVE_PACKET prPacket, OUT P_TX_PACKET_INFO prTxPktInfo); + +BOOLEAN kalGetEthDestAddr(IN P_GLUE_INFO_T prGlueInfo, IN P_NATIVE_PACKET prPacket, OUT PUINT_8 pucEthDestAddr); + +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, 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 kalClearSecurityFramesByBssIdx(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucBssIndex); + +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 kalClearMgmtFramesByBssIdx(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucBssIndex); + +UINT_32 kalGetTxPendingFrameCount(IN P_GLUE_INFO_T prGlueInfo); + +UINT_32 kalGetTxPendingCmdCount(IN P_GLUE_INFO_T prGlueInfo); + +VOID kalClearCommandQueue(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); + +VOID kalSetResetConnEvent(P_GLUE_INFO_T pr); + +#if CFG_SUPPORT_REPORT_MISC +VOID kalSetReportMiscEvent(P_GLUE_INFO_T pr); +#endif + +#if CFG_SUPPORT_MULTITHREAD +VOID kalSetTxEvent2Hif(P_GLUE_INFO_T pr); + +VOID kalSetTxEvent2Rx(P_GLUE_INFO_T pr); + +VOID kalSetTxCmdEvent2Hif(P_GLUE_INFO_T pr); +#endif +/*----------------------------------------------------------------------------*/ +/* 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); + +#if CFG_SUPPORT_802_11W +/*----------------------------------------------------------------------------*/ +/* 802.11W */ +/*----------------------------------------------------------------------------*/ +UINT_32 kalGetMfpSetting(IN P_GLUE_INFO_T prGlueInfo); +UINT_8 kalGetRsnIeMfpCap(IN P_GLUE_INFO_T prGlueInfo); +#endif + +UINT_32 kalWriteToFile(const PUINT_8 pucPath, BOOLEAN fgDoAppend, PUINT_8 pucData, UINT_32 u4Size); + +UINT_32 kalCheckPath(const PUINT_8 pucPath); + +UINT_32 kalTrunkPath(const PUINT_8 pucPath); + +INT_32 kalReadToFile(const PUINT_8 pucPath, PUINT_8 pucData, UINT_32 u4Size, PUINT_32 pu4ReadSize); + +INT_32 kalRequestFirmware(const PUINT_8 pucPath, PUINT_8 pucData, UINT_32 u4Size, + PUINT_32 pu4ReadSize, struct device *dev); + +/*----------------------------------------------------------------------------*/ +/* 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); + +/*----------------------------------------------------------------------------*/ +/* Net device */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +kalHardStartXmit(struct sk_buff *prSkb, IN struct net_device *prDev, P_GLUE_INFO_T prGlueInfo, UINT_8 ucBssIndex); + +BOOLEAN +kalGetIPv4Address(IN struct net_device *prDev, + IN UINT_32 u4MaxNumOfAddr, OUT PUINT_8 pucIpv4Addrs, OUT PUINT_32 pu4NumOfIpv4Addr); + +BOOLEAN +kalGetIPv6Address(IN struct net_device *prDev, + IN UINT_32 u4MaxNumOfAddr, OUT PUINT_8 pucIpv6Addrs, OUT PUINT_32 pu4NumOfIpv6Addr); + +VOID kalSetNetAddressFromInterface(IN P_GLUE_INFO_T prGlueInfo, IN struct net_device *prDev, IN BOOLEAN fgSet); + +WLAN_STATUS kalResetStats(IN struct net_device *prDev); + +PVOID kalGetStats(IN struct net_device *prDev); + +VOID kalResetPacket(IN P_GLUE_INFO_T prGlueInfo, IN P_NATIVE_PACKET prPacket); + +#if CFG_SUPPORT_QA_TOOL +struct file *kalFileOpen(const char *path, int flags, int rights); + +VOID kalFileClose(struct file *file); + +UINT_32 kalFileRead(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size); +#endif + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN +/*----------------------------------------------------------------------------*/ +/* SDIO Read/Write Pattern Support */ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalSetSdioTestPattern(IN P_GLUE_INFO_T prGlueInfo, IN BOOLEAN fgEn, IN BOOLEAN fgRead); +#endif + +/*----------------------------------------------------------------------------*/ +/* PNO Support */ +/*----------------------------------------------------------------------------*/ +VOID kalSchedScanResults(IN P_GLUE_INFO_T prGlueInfo); + +VOID kalSchedScanStopped(IN P_GLUE_INFO_T prGlueInfo, BOOLEAN fgDriverTriggerd); + +VOID kalSetFwOwnEvent2Hif(P_GLUE_INFO_T pr); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +int tx_thread(void *data); + +#if CFG_SUPPORT_MULTITHREAD +int hif_thread(void *data); +int rx_thread(void *data); +#endif +UINT_64 kalGetBootTime(VOID); + +int kalMetInitProcfs(IN P_GLUE_INFO_T prGlueInfo); +int kalMetRemoveProcfs(void); +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG +BOOLEAN kalIsWakeupByWlan(P_ADAPTER_T prAdapter); +#endif +INT_32 kalHaltLock(UINT_32 waitMs); +INT_32 kalHaltTryLock(VOID); +VOID kalHaltUnlock(VOID); +VOID kalSetHalted(BOOLEAN fgHalt); +BOOLEAN kalIsHalted(VOID); + +INT_32 kalPerMonInit(IN P_GLUE_INFO_T prGlueInfo); +INT_32 kalPerMonDisable(IN P_GLUE_INFO_T prGlueInfo); +INT_32 kalPerMonEnable(IN P_GLUE_INFO_T prGlueInfo); +INT_32 kalPerMonStart(IN P_GLUE_INFO_T prGlueInfo); +INT_32 kalPerMonStop(IN P_GLUE_INFO_T prGlueInfo); +INT_32 kalPerMonDestroy(IN P_GLUE_INFO_T prGlueInfo); +VOID kalPerMonHandler(IN P_ADAPTER_T prAdapter, ULONG ulParam); +INT_32 kalBoostCpu(UINT_32 core_num); + +INT_32 kalSetCpuNumFreq(UINT_32 core_num, UINT_32 u4Freq); +INT_32 kalPerMonSetForceEnableFlag(UINT_8 uFlag); +INT_32 kalFbNotifierReg(IN P_GLUE_INFO_T prGlueInfo); +VOID kalFbNotifierUnReg(VOID); + +#if CFG_MODIFY_TX_POWER_BY_BAT_VOLT +INT_32 kalBatNotifierReg(IN P_GLUE_INFO_T prGlueInfo); +VOID kalSetTxPwrBackoffByBattVolt(P_ADAPTER_T prAdapter, BOOLEAN ucEnable); +VOID kalBatNotifierUnReg(VOID); +#endif + +UINT_8 kalGetEapolKeyType(P_NATIVE_PACKET prPacket); + +VOID nicConfigProcSetCamCfgWrite(BOOLEAN enabled); + +VOID kalSetEmiMpuProtection(phys_addr_t emiPhyBase, UINT_32 size, BOOLEAN enable); +BOOLEAN kalIsValidMacAddr(IN const UINT_8 *addr); + +BOOLEAN kalScanParseRandomMac( + IN P_GLUE_INFO_T prGlueInfo, + IN struct cfg80211_scan_request *request, + OUT UINT_8 *pucRandomMac); +BOOLEAN kalSchedScanParseRandomMac( + const struct net_device *ndev, + IN struct cfg80211_sched_scan_request *request); +VOID kalTakeVcoreAction(UINT_8 ucAction); + +VOID kalVcoreInitUninit(BOOLEAN fgInit); + +VOID kalMayChangeVcore(VOID); + +int kalExternalAuthRequest(IN struct _ADAPTER_T *prAdapter, IN uint8_t uBssIndex); + +void kalDumpHifCR(P_GLUE_INFO_T prGlueInfo); +#endif /* _GL_KAL_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_os.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_os.h new file mode 100644 index 0000000000000..ecd6be377d3bd --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_os.h @@ -0,0 +1,1003 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_os.h#4 + */ + +/* + * ! \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. + */ + +#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 512 /* packets */ +#define CFG_TX_START_NETIF_PER_QUEUE_THRESHOLD 128 /* packets */ + +#if defined(MT6630) +#define CHIP_NAME "MT6630" +#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) +#define GLUE_INFO_WSCIE_LENGTH 500 + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#ifdef CFG_CFG80211_VERSION +#define CFG80211_VERSION_CODE CFG_CFG80211_VERSION +#else +#define CFG80211_VERSION_CODE LINUX_VERSION_CODE +#endif + +#include /* constant of kernel version */ + +#include /* bitops.h */ + +#include /* struct timer_list */ +#include /* jiffies */ +#include /* udelay and mdelay macro */ + +#if CONFIG_ANDROID +#ifdef CONFIG_WAKELOCK +#include +#else +#include +#endif /*CONFIG_WAKELOCK*/ +#endif + +#include /* IRQT_FALLING */ + +#include /* struct net_device, struct net_device_stats */ +#include /* for eth_type_trans() function */ +#include /* struct iw_statistics */ +#include +#include /* struct in_device */ + +#include /* struct iphdr */ + +#include /* for memcpy()/memset() function */ +#include /* for offsetof() macro */ + +#include /* The proc filesystem constants/structures */ + +#include /* for rtnl_lock() and rtnl_unlock() */ +#include /* kthread_should_stop(), kthread_run() */ +#include /* for copy_from_user() */ +#include /* for firmware download */ +#include + +#include /* for kfifo interface */ +#include /* for cdev interface */ + +#include /* for firmware download */ + +#if defined(_HIF_SDIO) +#include +#include +#endif + +#include + +#include /* readw and writew */ + +#if WIRELESS_EXT > 12 +#include +#endif + +#include "version.h" +#include "config.h" + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#include +#include +#endif + +#include +#include +#include +#include + +#ifdef CONFIG_IPV6 +#include +#include +#include +#endif + +#if CFG_SUPPORT_PASSPOINT +#include +#endif /* CFG_SUPPORT_PASSPOINT */ + +#include "gl_typedef.h" +#include "typedef.h" +#include "queue.h" +#include "gl_kal.h" + +#include "hif.h" + +#if CFG_SUPPORT_TDLS +#include "tdls.h" +#endif + +#include "debug.h" + +#include "wlan_lib.h" +#include "wlan_oid.h" + +#if CFG_ENABLE_AEE_MSG +#include +#endif + +extern BOOLEAN fgIsBusAccessFailed; +extern UINT_8 g_aucNvram[]; + +/******************************************************************************* +* 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_MULTICAST BIT(7) +#define GLUE_FLAG_FRAME_FILTER BIT(8) +#define GLUE_FLAG_FRAME_FILTER_AIS BIT(9) + +#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_MULTICAST_BIT (7) +#define GLUE_FLAG_FRAME_FILTER_BIT (8) +#define GLUE_FLAG_FRAME_FILTER_AIS_BIT (9) + +#if CFG_SUPPORT_MULTITHREAD +#define GLUE_FLAG_RX BIT(10) +#define GLUE_FLAG_TX_CMD_DONE BIT(11) +#define GLUE_FLAG_HIF_TX BIT(12) +#define GLUE_FLAG_HIF_TX_CMD BIT(13) +#define GLUE_FLAG_RX_TO_OS BIT(14) +#define GLUE_FLAG_HIF_FW_OWN BIT(15) +#define GLUE_FLAG_HAL_MCR_RD BIT(16) +#define GLUE_FLAG_HAL_MCR_WR BIT(17) + +#define GLUE_FLAG_RX_BIT (10) +#define GLUE_FLAG_TX_CMD_DONE_BIT (11) +#define GLUE_FLAG_HIF_TX_BIT (12) +#define GLUE_FLAG_HIF_TX_CMD_BIT (13) +#define GLUE_FLAG_RX_TO_OS_BIT (14) +#define GLUE_FLAG_HIF_FW_OWN_BIT (15) +#define GLUE_FLAG_HAL_MCR_RD_BIT (16) +#define GLUE_FLAG_HAL_MCR_WR_BIT (17) +#endif +#define GLUE_FLAG_RESET_CONN_BIT (18) + +#if CFG_SUPPORT_REPORT_MISC +#define GLUE_FLAG_REPORT_MISC_BIT (19) +#endif + +#if CFG_SUPPORT_MULTITHREAD +#define GLUE_FLAG_HIF_PRT_HIF_DBG_INFO_BIT (20) +#endif + +#define GLUE_BOW_KFIFO_DEPTH (1024) +/* #define GLUE_BOW_DEVICE_NAME "MT6620 802.11 AMP" */ +#define GLUE_BOW_DEVICE_NAME "ampc0" + +#define WAKE_LOCK_RX_TIMEOUT 300 /* ms */ +#define WAKE_LOCK_THREAD_WAKEUP_TIMEOUT 50 /* ms */ +/*Full2Partial*/ +#define UPDATE_FULL_TO_PARTIAL_SCAN_TIMEOUT 60 /* s */ + +#define FULL_SCAN_MAX_CHANNEL_NUM 40 +#define FULL2PARTIALTHRESHOLD 3 + +#if CFG_SUPPORT_ABORT_SCAN +#define ABORT_SCAN_INTERVAl UPDATE_FULL_TO_PARTIAL_SCAN_TIMEOUT /* s */ +#define ABORT_SCAN_COUNT 2 +#endif +/******************************************************************************* +* 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; + UINT_8 ucRSNMfpCap; +#endif +} GL_WPA_INFO_T, *P_GL_WPA_INFO_T; + +#if CFG_SUPPORT_REPLAY_DETECTION +struct GL_REPLEY_PN_INFO { + UINT_8 auPN[16]; + BOOLEAN fgRekey; +}; +struct GL_DETECT_REPLAY_INFO { + UINT_8 ucCurKeyId; + UINT_8 ucKeyType; + struct GL_REPLEY_PN_INFO arReplayPNInfo[4]; +}; +#endif +typedef enum _ENUM_NET_DEV_IDX_T { + NET_DEV_WLAN_IDX = 0, + NET_DEV_P2P_IDX, + NET_DEV_BOW_IDX, + NET_DEV_NUM +} ENUM_NET_DEV_IDX_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_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 enum _ENUM_PKT_FLAG_T { + ENUM_PKT_802_11, /* 802.11 or non-802.11 */ + ENUM_PKT_802_3, /* 802.3 or ethernetII */ + ENUM_PKT_1X, /* 1x frame or not */ + ENUM_PKT_PROTECTED_1X, /* prtected 1x frame */ + ENUM_PKT_VLAN_EXIST, /* VLAN tag exist */ + ENUM_PKT_DHCP, /* DHCP frame */ + ENUM_PKT_ARP, /* ARP */ + ENUM_PKT_ICMP, /* ICMP */ + ENUM_PKT_TDLS, /* TDLS */ + ENUM_PKT_DNS, /* DNS */ + + ENUM_PKT_FLAG_NUM +} ENUM_PKT_FLAG_T; + +enum ENUM_WLAN_DRV_BUF_TYPE_T { + ENUM_BUF_TYPE_NVRAM, + ENUM_BUF_TYPE_DRV_CFG, + ENUM_BUF_TYPE_FW_CFG, + ENUM_BUF_TYPE_NUM +}; + + +typedef struct _GL_IO_REQ_T { + QUE_ENTRY_T rQueEntry; + /* wait_queue_head_t cmdwait_q; */ + BOOL fgRead; + BOOL fgWaitResp; + 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 + +struct FT_IES { + UINT_16 u2MDID; + struct IE_MOBILITY_DOMAIN_T *prMDIE; + struct IE_FAST_TRANSITION_T *prFTIE; + IE_TIMEOUT_INTERVAL_T *prTIE; + P_RSN_INFO_ELEM_T prRsnIE; + PUINT_8 pucIEBuf; + UINT_32 u4IeLength; +}; + +/* +* type definition of pointer to p2p structure +*/ +typedef struct _GL_P2P_INFO_T GL_P2P_INFO_T, *P_GL_P2P_INFO_T; + +struct GL_Channel_scan_info { + INT_8 cScanThreshold; + UINT_8 ucScanFlag; +}; + +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]; + + /* Mutex to protect interruptible section */ + struct mutex arMutex[MUTEX_NUM]; + + /* semaphore for ioctl */ + struct semaphore ioctl_sem; + + UINT_64 u8Cookie; + + ULONG ulFlag; /* GLUE_FLAG_XXX */ + UINT_32 u4PendFlag; + /* UINT_32 u4TimeoutFlag; */ + UINT_32 u4OidCompleteFlag; + UINT_32 u4ReadyFlag; /* check if card is ready */ + + UINT_32 u4OsMgmtFrameFilter; + + /* Number of pending frames, also used for debuging if any frame is + * missing during the process of unloading Driver. + * + * NOTE(Kevin): In Linux, we also use this variable as the threshold + * for manipulating the netif_stop(wake)_queue() func. + */ + INT_32 ai4TxPendingFrameNumPerQueue[HW_BSSID_NUM][CFG_MAX_TXQ_NUM]; + INT_32 i4TxPendingFrameNum; + INT_32 i4TxPendingSecurityFrameNum; + + /* Tx: for NetDev to BSS index mapping */ + NET_INTERFACE_INFO_T arNetInterfaceInfo[HW_BSSID_NUM]; + + /* Rx: for BSS index to NetDev mapping */ + /* P_NET_INTERFACE_INFO_T aprBssIdxToNetInterfaceInfo[HW_BSSID_NUM]; */ + + /* 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; +#if CFG_SUPPORT_REPLAY_DETECTION + struct GL_DETECT_REPLAY_INFO prDetRplyInfo; +#endif + + /* 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 */ + ENUM_ACPI_STATE_T 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_SUPPORT_MULTITHREAD + struct completion rHifHaltComp; /* indicate hif_thread halt complete */ + struct completion rRxHaltComp; /* indicate hif_thread halt complete */ + struct completion rHalRDMCRComp; + struct completion rHalWRMCRComp; + + UINT_32 u4TxThreadPid; + UINT_32 u4RxThreadPid; + UINT_32 u4HifThreadPid; +#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; + +#if CFG_SUPPORT_MULTITHREAD + wait_queue_head_t waitq_hif; + struct task_struct *hif_thread; + + wait_queue_head_t waitq_rx; + struct task_struct *rx_thread; + +#endif + + 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 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[GLUE_INFO_WSCIE_LENGTH]; /*for probe req */ + UINT_16 u2WSCIELen; + + /* NVRAM availability */ + BOOLEAN fgNvramAvailable; + + BOOLEAN fgMcrAccessAllowed; + + /* MAC Address Overridden by IOCTL */ + BOOLEAN fgIsMacAddrOverride; + PARAM_MAC_ADDRESS rMacAddrOverride; + + SET_TXPWR_CTRL_T rTxPwr; + + /* for cfg80211 scan done indication */ + struct cfg80211_scan_request *prScanRequest; + + /* for cfg80211 scheduled scan */ + struct cfg80211_sched_scan_request *prSchedScanRequest; + + /* to indicate registered or not */ + BOOLEAN fgIsRegistered; + + /* for cfg80211 connected indication */ + UINT_32 u4RspIeLength; + UINT_8 aucRspIe[CFG_CFG80211_IE_BUF_LEN]; + + UINT_32 u4ReqIeLength; + UINT_8 aucReqIe[CFG_CFG80211_IE_BUF_LEN]; + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN + BOOLEAN fgEnSdioTestPattern; + BOOLEAN fgSdioReadWriteMode; + BOOLEAN fgIsSdioTestInitialized; + UINT_8 aucSdioTestBuffer[256]; +#endif + + BOOLEAN fgIsInSuspendMode; + +#if CFG_SUPPORT_PASSPOINT + UINT_8 ucHotspotConfig; + BOOLEAN fgConnectHS20AP; + + BOOLEAN fgIsDad; + UINT_8 aucDADipv4[4]; + BOOLEAN fgIs6Dad; + UINT_8 aucDADipv6[16]; +#endif /* CFG_SUPPORT_PASSPOINT */ + + KAL_WAKE_LOCK_T rIntrWakeLock; + KAL_WAKE_LOCK_T rTimeoutWakeLock; + +#if CFG_MET_PACKET_TRACE_SUPPORT + BOOLEAN fgMetProfilingEn; + UINT_16 u2MetUdpPort; +#endif + +#if CFG_SUPPORT_SNIFFER + BOOLEAN fgIsEnableMon; + struct net_device *prMonDevHandler; + struct work_struct monWork; +#endif + + INT_32 i4RssiCache; + UINT_32 u4LinkSpeedCache; + + UINT_32 IsrCnt; + UINT_32 IsrPassCnt; + UINT_32 TaskIsrCnt; + + UINT_32 IsrAbnormalCnt; + UINT_32 IsrSoftWareCnt; + UINT_32 IsrTxCnt; + UINT_32 IsrRxCnt; + + UINT_64 u8SkbToDriver; + UINT_64 u8SkbFreed; + + UINT_32 u4Register; + UINT_32 u4RegValue; + PUINT_32 prRegValue; + + UINT_64 u8HifIntTime; + + /* save partial scan channel information */ + PARTIAL_SCAN_INFO rScanChannelInfo; + PUINT_8 pucScanChannel; + + /* Full2Partial */ + OS_SYSTIME u4LastFullScanTime; +#if CFG_SUPPORT_ABORT_SCAN + OS_SYSTIME u4LastNormalScanTime; + UINT_8 ucAbortScanCnt; +#endif + /* full scan or partial scan */ + struct GL_Channel_scan_info arChannelScanInfo[FULL_SCAN_MAX_CHANNEL_NUM]; + PARTIAL_SCAN_INFO rFullScanApChannel; + PUINT_8 pucFullScan2PartialChannel; + struct FT_IES rFtIeForTx; + struct cfg80211_ft_event_params rFtEventParam; + + /* FW Roaming */ + /* store the FW roaming enable state which FWK determines */ + /* if it's = 0, ignore the black/whitelists settings from FWK */ + UINT_32 u4FWRoamingEnable; +}; + +typedef irqreturn_t(*PFN_WLANISR) (int irq, void *dev_id, struct pt_regs *regs); + +typedef void (*PFN_LINUX_TIMER_FUNC) (unsigned long); + +/* generic sub module init/exit handler +* now, we only have one sub module, p2p +*/ +#if CFG_ENABLE_WIFI_DIRECT +typedef BOOLEAN(*SUB_MODULE_INIT) (P_GLUE_INFO_T prGlueInfo); +typedef BOOLEAN(*SUB_MODULE_EXIT) (P_GLUE_INFO_T prGlueInfo); + +typedef struct _SUB_MODULE_HANDLER { + SUB_MODULE_INIT subModInit; + SUB_MODULE_EXIT subModExit; + BOOLEAN fgIsInited; +} SUB_MODULE_HANDLER, *P_SUB_MODULE_HANDLER; + +#endif + +#if CONFIG_NL80211_TESTMODE + +enum TestModeCmdType { + TESTMODE_CMD_ID_SW_CMD = 1, + TESTMODE_CMD_ID_WAPI = 2, + TESTMODE_CMD_ID_HS20 = 3, + TESTMODE_CMD_ID_STR_CMD = 102, + NUM_OF_TESTMODE_CMD_ID +}; + +#if CFG_SUPPORT_PASSPOINT +enum Hs20CmdType { + HS20_CMD_ID_SET_BSSID_POOL = 0, + NUM_OF_HS20_CMD_ID +}; +#endif /* CFG_SUPPORT_PASSPOINT */ + +typedef struct _NL80211_DRIVER_TEST_MODE_PARAMS { + UINT_32 index; + UINT_32 buflen; +} NL80211_DRIVER_TEST_MODE_PARAMS, *P_NL80211_DRIVER_TEST_MODE_PARAMS; + +/*SW CMD */ +typedef struct _NL80211_DRIVER_SW_CMD_PARAMS { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + UINT_8 set; + UINT_32 adr; + UINT_32 data; +} NL80211_DRIVER_SW_CMD_PARAMS, *P_NL80211_DRIVER_SW_CMD_PARAMS; + +struct iw_encode_exts { + __u32 ext_flags; /*!< IW_ENCODE_EXT_* */ + __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /*!< LSB first */ + __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /*!< LSB first */ + __u8 addr[MAC_ADDR_LEN]; /* + * !< ff:ff:ff:ff:ff:ff for broadcast/multicast + * (group) keys or unicast address for + * individual keys + */ + __u16 alg; /* !< IW_ENCODE_ALG_* */ + __u16 key_len; + __u8 key[32]; +}; + +/*SET KEY EXT */ +typedef struct _NL80211_DRIVER_SET_KEY_EXTS { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + UINT_8 key_index; + UINT_8 key_len; + struct iw_encode_exts ext; +} NL80211_DRIVER_SET_KEY_EXTS, *P_NL80211_DRIVER_SET_KEY_EXTS; + +#if CFG_SUPPORT_PASSPOINT + +struct param_hs20_set_bssid_pool { + UINT_8 fgBssidPoolIsEnable; + UINT_8 ucNumBssidPool; + UINT_8 arBssidPool[8][ETH_ALEN]; +}; + +struct wpa_driver_hs20_data_s { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + enum Hs20CmdType CmdType; + struct param_hs20_set_bssid_pool hs20_set_bssid_pool; +}; + +#endif /* CFG_SUPPORT_PASSPOINT */ + +#endif + +typedef struct _NETDEV_PRIVATE_GLUE_INFO { + P_GLUE_INFO_T prGlueInfo; + UINT_8 ucBssIdx; +} NETDEV_PRIVATE_GLUE_INFO, *P_NETDEV_PRIVATE_GLUE_INFO; + +typedef struct _PACKET_PRIVATE_DATA { + /* tx/rx both use cb */ + QUE_ENTRY_T rQueEntry; /* 16byte total:16 */ + + UINT_8 ucBssIdx; /* 1byte */ + /* only rx use cb */ + BOOLEAN fgIsIndependentPkt; /* 1byte */ + /* only tx use cb */ + UINT_8 ucTid; /* 1byte */ + UINT_8 ucHeaderLen; /* 1byte */ + UINT_8 ucProfilingFlag; /* 1byte */ + UINT_8 ucSeqNo; /* 1byte */ + UINT_16 u2Flag; /* 2byte total:24 */ + + UINT_16 u2IpId; /* 2byte */ + UINT_16 u2FrameLen; /* 2byte */ + OS_SYSTIME rArrivalTime;/* 4byte total:32 */ + + UINT_64 u8ArriveTime; /* 8byte total:40 */ +} PACKET_PRIVATE_DATA, *P_PACKET_PRIVATE_DATA; + +typedef struct _PACKET_PRIVATE_RX_DATA { + UINT_64 u8IntTime; /* 8byte */ + UINT_64 u8RxTime; /* 8byte */ +} PACKET_PRIVATE_RX_DATA, *P_PACKET_PRIVATE_RX_DATA; + +/******************************************************************************* +* P U B 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() ULONG __ulFlags = 0 +#define GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, rLockCategory) \ + { \ + if (rLockCategory < SPIN_LOCK_NUM) \ + spin_lock_irqsave(&(prGlueInfo)->rSpinLock[rLockCategory], __ulFlags); \ + } +#define GLUE_RELEASE_SPIN_LOCK(prGlueInfo, rLockCategory) \ + { \ + if (rLockCategory < SPIN_LOCK_NUM) \ + spin_unlock_irqrestore(&(prGlueInfo->rSpinLock[rLockCategory]), __ulFlags); \ + } +#endif /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + +/*----------------------------------------------------------------------------*/ +/* Macros for accessing Reserved Fields of native packet */ +/*----------------------------------------------------------------------------*/ + +#define GLUE_GET_PKT_PRIVATE_DATA(_p) \ + ((P_PACKET_PRIVATE_DATA)(&(((struct sk_buff *)(_p))->cb[0]))) + +#define GLUE_GET_PKT_QUEUE_ENTRY(_p) \ + (&(GLUE_GET_PKT_PRIVATE_DATA(_p)->rQueEntry)) + +#define GLUE_GET_PKT_DESCRIPTOR(_prQueueEntry) \ + ((P_NATIVE_PACKET) (((ULONG)_prQueueEntry) - offsetof(struct sk_buff, cb[0]))) + +#define GLUE_SET_PKT_TID(_p, _tid) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucTid = (UINT_8)(_tid)) + +#define GLUE_GET_PKT_TID(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucTid) + +#define GLUE_GET_PKT_FLAG(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2Flag) + +#define GLUE_SET_PKT_FLAG(_p, _flag) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2Flag |= BIT(_flag)) + +#define GLUE_TEST_PKT_FLAG(_p, _flag) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2Flag & BIT(_flag)) + +#define GLUE_IS_PKT_FLAG_SET(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2Flag) + +#define GLUE_SET_PKT_BSS_IDX(_p, _ucBssIndex) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucBssIdx = (UINT_8)(_ucBssIndex)) + +#define GLUE_GET_PKT_BSS_IDX(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucBssIdx) + +#define GLUE_SET_PKT_HEADER_LEN(_p, _ucMacHeaderLen) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucHeaderLen = (UINT_8)(_ucMacHeaderLen)) + +#define GLUE_GET_PKT_HEADER_LEN(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucHeaderLen) + +#define GLUE_SET_PKT_FRAME_LEN(_p, _u2PayloadLen) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2FrameLen = (UINT_16)(_u2PayloadLen)) + +#define GLUE_GET_PKT_FRAME_LEN(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2FrameLen) + +#define GLUE_SET_PKT_ARRIVAL_TIME(_p, _rSysTime) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->rArrivalTime = (OS_SYSTIME)(_rSysTime)) + +#define GLUE_GET_PKT_ARRIVAL_TIME(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->rArrivalTime) + +#define GLUE_SET_PKT_IP_ID(_p, _u2IpId) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2IpId = (UINT_16)(_u2IpId)) + +#define GLUE_GET_PKT_IP_ID(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2IpId) + +#define GLUE_SET_PKT_SEQ_NO(_p, _ucSeqNo) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucSeqNo = (UINT_8)(_ucSeqNo)) + +#define GLUE_GET_PKT_SEQ_NO(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucSeqNo) + +#define GLUE_SET_PKT_FLAG_PROF_MET(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucProfilingFlag |= BIT(0)) + +#define GLUE_GET_PKT_IS_PROF_MET(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucProfilingFlag & BIT(0)) + +#define GLUE_GET_PKT_ETHER_DEST_ADDR(_p) \ + ((PUINT_8)&(((struct sk_buff *)(_p))->data)) + +/* 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_GET_INDEPENDENT_PKT(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->fgIsIndependentPkt) +#define GLUE_SET_INDEPENDENT_PKT(_p, _fgIsIndePkt) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->fgIsIndependentPkt = _fgIsIndePkt) + +#define GLUE_SET_PKT_XTIME(_p, _rSysTime) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u8ArriveTime = (UINT_64)(_rSysTime)) + +#define GLUE_GET_PKT_XTIME(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u8ArriveTime) + +#define GLUE_GET_PKT_PRIVATE_RX_DATA(_p) \ + ((P_PACKET_PRIVATE_RX_DATA)(&(((struct sk_buff *)(_p))->cb[24]))) + +#define GLUE_RX_SET_PKT_INT_TIME(_p, _rTime) \ + (GLUE_GET_PKT_PRIVATE_RX_DATA(_p)->u8IntTime = (UINT_64)(_rTime)) + +#define GLUE_RX_GET_PKT_INT_TIME(_p) \ + (GLUE_GET_PKT_PRIVATE_RX_DATA(_p)->u8IntTime) + +#define GLUE_RX_SET_PKT_RX_TIME(_p, _rTime) \ + (GLUE_GET_PKT_PRIVATE_RX_DATA(_p)->u8RxTime = (UINT_64)(_rTime)) + +#define GLUE_RX_GET_PKT_RX_TIME(_p) \ + (GLUE_GET_PKT_PRIVATE_RX_DATA(_p)->u8RxTime) + +#define GLUE_INC_REF_CNT(_refCount) atomic_inc((atomic_t *)&(_refCount)) +#define GLUE_DEC_REF_CNT(_refCount) atomic_dec((atomic_t *)&(_refCount)) +#define GLUE_GET_REF_CNT(_refCount) atomic_read((atomic_t *)&(_refCount)) + +#define DbgPrint(...) + +/*----------------------------------------------------------------------------*/ +/* Macros of Data Type Check */ +/*----------------------------------------------------------------------------*/ +/* Kevin: we don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + */ +static __KAL_INLINE__ VOID glPacketDataTypeCheck(VOID) +{ + + DATA_STRUCT_INSPECTING_ASSERT(sizeof(PACKET_PRIVATE_DATA) <= sizeof(((struct sk_buff *) 0)->cb)); + +} + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +#ifdef WLAN_INCLUDE_PROC +INT_32 procRemoveProcfs(VOID); + +INT_32 procCreateFsEntry(P_GLUE_INFO_T prGlueInfo); +INT_32 procInitFs(VOID); +INT_32 procUninitProcFs(VOID); +#endif /* WLAN_INCLUDE_PROC */ + +#if CFG_ENABLE_BT_OVER_WIFI +BOOLEAN glRegisterAmpc(P_GLUE_INFO_T prGlueInfo); + +BOOLEAN glUnregisterAmpc(P_GLUE_INFO_T prGlueInfo); +#endif + +P_GLUE_INFO_T wlanGetGlueInfo(VOID); + +UINT_16 wlanSelectQueue(struct net_device *dev, struct sk_buff *skb, + void *accel_priv, select_queue_fallback_t fallback); + +VOID wlanDebugInit(VOID); + +WLAN_STATUS wlanSetDebugLevel(IN UINT_32 u4DbgIdx, IN UINT_32 u4DbgMask); + +WLAN_STATUS wlanGetDebugLevel(IN UINT_32 u4DbgIdx, OUT PUINT_32 pu4DbgMask); + +VOID wlanSetSuspendMode(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgEnable); + +BOOLEAN wlanIsFwOwn(VOID); + +/******************************************************************************* +* E X T E R N A L F U N C T I O N S / V A R I A B L E +******************************************************************************** +*/ + +extern void wlanRegisterNotifier(void); +extern void wlanUnregisterNotifier(void); + + +typedef int (*set_p2p_mode) (struct net_device *netdev, PARAM_CUSTOM_P2P_SET_STRUCT_T p2pmode); +extern void register_set_p2p_mode_handler(set_p2p_mode handler); + +#if CFG_ENABLE_EARLY_SUSPEND +extern int glRegisterEarlySuspend(struct early_suspend *prDesc, + early_suspend_callback wlanSuspend, late_resume_callback wlanResume); + +extern int glUnregisterEarlySuspend(struct early_suspend *prDesc); +#endif + +#if CFG_MET_PACKET_TRACE_SUPPORT +VOID kalMetTagPacket(IN P_GLUE_INFO_T prGlueInfo, IN P_NATIVE_PACKET prPacket, IN ENUM_TX_PROFILING_TAG_T eTag); + +VOID kalMetInit(IN P_GLUE_INFO_T prGlueInfo); +#endif + +VOID wlanUpdateChannelTable(P_GLUE_INFO_T prGlueInfo); + +#ifdef FW_CFG_SUPPORT +INT_32 cfgCreateProcEntry(P_GLUE_INFO_T prGlueInfo); +INT_32 cfgRemoveProcEntry(void); +#endif + +typedef UINT_8 (*file_buf_handler) (PVOID ctx, const CHAR __user *buf, UINT_16 length); +extern VOID register_file_buf_handler(file_buf_handler handler, PVOID ctx, UINT_8 ucType); +extern void update_driver_loaded_status(uint8_t loaded); +#endif /* _GL_OS_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_p2p_ioctl.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_p2p_ioctl.h new file mode 100644 index 0000000000000..deba0157a210d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_p2p_ioctl.h @@ -0,0 +1,605 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * 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 + */ + +#ifndef _GL_P2P_IOCTL_H +#define _GL_P2P_IOCTL_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#include +#include +#endif + +#include "wlan_oid.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/* (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; + +typedef enum _ENUM_TESTMODE_AVAILABLE_CHAN_ATTR { + __NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_INVALID, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_2G_BASE_1, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_36, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_52, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_100, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_149, + __NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_AFTER_LAST, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_MAX = __NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_AFTER_LAST - 1 +} ENUM_TESTMODE_AVAILABLE_CHAN_ATTR; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +extern struct ieee80211_supported_band mtk_band_2ghz; +extern struct ieee80211_supported_band mtk_band_5ghz; +extern const UINT_32 mtk_cipher_suites[5]; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + +struct wireless_dev * +mtk_p2p_cfg80211_add_iface(struct wiphy *wiphy, + const char *name, + enum nl80211_iftype type, u32 *flags, struct vif_params *params); + +#if (KERNEL_VERSION(4, 12, 0) <= LINUX_VERSION_CODE) +int +mtk_p2p_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type, struct vif_params *params); +#else +int +mtk_p2p_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type, u32 *flags, struct vif_params *params); +#endif + +int mtk_p2p_cfg80211_del_iface(struct wiphy *wiphy, + struct wireless_dev *wdev); + +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_set_mgmt_key(struct wiphy *wiphy, struct net_device *dev, u8 key_index); + +int mtk_p2p_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, + const u8 *mac, struct station_info *sinfo); + +int mtk_p2p_cfg80211_scan(struct wiphy *wiphy, + 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, + struct wireless_dev *wdev, + enum nl80211_tx_power_setting type, int mbm); + +int mtk_p2p_cfg80211_get_txpower(struct wiphy *wiphy, + struct wireless_dev *wdev, + int *dbm); + +int mtk_p2p_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, + unsigned int duration, u64 *cookie); + +int mtk_p2p_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie); + +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_deauth(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_deauth_request *req); + +int mtk_p2p_cfg80211_disassoc(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_disassoc_request *req); + +int mtk_p2p_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ap_settings *settings); + +int mtk_p2p_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_beacon_data *info); + +int mtk_p2p_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie); + +int mtk_p2p_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie); + +int mtk_p2p_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, struct station_del_parameters *params); +#else +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, const u8 *mac); +#endif + +int mtk_p2p_cfg80211_set_channel(struct wiphy *wiphy, + struct cfg80211_chan_def *chandef); + +void mtk_p2p_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, + struct wireless_dev *wdev, + IN u16 frame_type, IN bool reg); + +int +mtk_p2p_cfg80211_set_bitrate_mask(IN struct wiphy *wiphy, + IN struct net_device *dev, + IN const u8 *peer, IN const struct cfg80211_bitrate_mask *mask); + +#if CONFIG_NL80211_TESTMODE + +int mtk_p2p_cfg80211_testmode_cmd(IN struct wiphy *wiphy, IN struct wireless_dev *wdev, IN void *data, IN int len); + +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); + +int mtk_p2p_cfg80211_testmode_hotspot_config_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); +#else +#error "Please ENABLE kernel config (CONFIG_NL80211_TESTMODE)" +#endif + +#endif + +/* I/O control handlers */ + +int +mtk_p2p_wext_get_priv(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_reconnect(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_auth(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_key(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_mlme_handler(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_powermode(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_get_powermode(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +/* Private Wireless I/O Controls takes use of iw_handler */ +int +mtk_p2p_wext_set_local_dev_info(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_provision_complete(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_start_stop_discovery(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_discovery_results(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_wsc_ie(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_connect_disconnect(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_password_ready(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_request_dev_info(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_invitation_indicate(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_invitation_status(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_pm_param(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_ps_profile(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_network_address(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_int(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +/* Private Wireless I/O Controls for IOC_SET_STRUCT/IOC_GET_STRUCT */ +int +mtk_p2p_wext_set_struct(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_get_struct(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +/* IOC_SET_STRUCT/IOC_GET_STRUCT: Service Discovery */ +int +mtk_p2p_wext_get_service_discovery_request(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_get_service_discovery_response(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_send_service_discovery_request(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_send_service_discovery_response(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_terminate_service_discovery_phase(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +#if CFG_SUPPORT_ANTI_PIRACY +int +mtk_p2p_wext_set_sec_check_request(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_get_sec_check_response(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); +#endif + +int +mtk_p2p_wext_set_noa_param(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_oppps_param(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_p2p_version(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_get_p2p_version(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +void mtk_p2p_wext_set_Multicastlist(IN P_GLUE_INFO_T prGlueInfo); + +#if CFG_SUPPORT_P2P_RSSI_QUERY +int +mtk_p2p_wext_get_rssi(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +struct iw_statistics *mtk_p2p_wext_get_wireless_stats(struct net_device *prDev); + +#endif + +int +mtk_p2p_wext_set_txpow(IN struct net_device *prDev, + IN struct iw_request_info *prIwrInfo, IN OUT union iwreq_data *prTxPow, IN char *pcExtra); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _GL_P2P_IOCTL_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_p2p_kal.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_p2p_kal.h new file mode 100644 index 0000000000000..b5a8a58fe12de --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_p2p_kal.h @@ -0,0 +1,230 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** 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. + */ + +#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 + +BOOLEAN kalP2pFuncGetChannelType(IN ENUM_CHNL_EXT_T rChnlSco, OUT enum nl80211_channel_type *channel_type); + +/******************************************************************************* +* 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); + +INT_32 mtk_Netdev_To_RoleIdx(P_GL_P2P_INFO_T prGlP2pInfo, struct net_device *ndev, PUINT_8 pucRoleIdx); + +UINT_8 kalP2PGetRole(IN P_GLUE_INFO_T prGlueInfo); + +#if 1 +VOID kalP2PSetRole(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRole); + +#else +VOID +kalP2PSetRole(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucResult, IN PUINT_8 pucSSID, IN UINT_8 ucSSIDLen, IN UINT_8 ucRole); +#endif + +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 UINT_8 ucRoleIndex, 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, IN BOOLEAN fgIsDevInterface, IN UINT_8 ucRoleIdx); + +VOID kalP2PIndicateMgmtTxStatus(IN P_GLUE_INFO_T prGlueInfo, IN P_MSDU_INFO_T prMsduInfo, IN BOOLEAN fgIsAck); + +VOID +kalP2PIndicateChannelExpired(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); + +VOID +kalP2PGCIndicateConnectionStatus(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucRoleIndex, + IN P_P2P_CONNECTION_REQ_INFO_T prP2pConnInfo, + IN PUINT_8 pucRxIEBuf, IN UINT_16 u2RxIELen, IN UINT_16 u2StatusReason, + IN WLAN_STATUS eStatus); + +VOID kalP2PGOIndicateStatus(IN P_GLUE_INFO_T prGlueInfo, IN BOOLEAN fgReady); + +VOID +kalP2PGOStationUpdate(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucRoleIndex, IN P_STA_RECORD_T prCliStaRec, IN BOOLEAN fgIsNew); + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + +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 + +INT_32 mtk_Netdev_To_RoleIdx(P_GL_P2P_INFO_T prGlP2pInfo, struct net_device *ndev, PUINT_8 pucRoleIdx); + +void kalP2pIndicateAcsResult(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucRoleIndex, + IN UINT_8 ucPrimaryCh, + IN UINT_8 ucSecondCh, + IN UINT_8 ucSeg0Ch, + IN UINT_8 ucSeg1Ch, + IN ENUM_MAX_BANDWIDTH_SETTING eChnlBw); + +#endif /* _GL_P2P_KAL_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_p2p_os.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_p2p_os.h new file mode 100644 index 0000000000000..c99112c4726fd --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_p2p_os.h @@ -0,0 +1,283 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: +//Department/DaVinci/TRUNK/MT6620_5931_WiFi_Driver/os/linux/include/gl_p2p_os.h#28 +*/ + +/* + * ! \file gl_p2p_os.h + * \brief List the external reference to OS for p2p GLUE Layer. + * + * In this file we define the data structure - GLUE_INFO_T to store those objects + * we acquired from OS - e.g. TIMER, SPINLOCK, NET DEVICE ... . And all the + * external reference (header file, extern func() ..) to OS for GLUE Layer should + * also list down here. + */ + +#ifndef _GL_P2P_OS_H +#define _GL_P2P_OS_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#include +#endif + +#include "wlan_oid.h" + + +/******************************************************************************* +* E X T E R N A L V A R I A B L E +******************************************************************************** +*/ +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_WIFI_DIRECT_CFG_80211 +extern const struct net_device_ops p2p_netdev_ops; +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define OID_SET_GET_STRUCT_LENGTH 4096 /* For SET_STRUCT/GET_STRUCT */ + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER +#define P2P_BLACKLIST_MAX_COUNT 32 +#endif +/******************************************************************************* +* 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 { + + /* P2P Device interface handle */ + struct net_device *prDevHandler; + + struct net_device *aprRoleHandler[KAL_P2P_NUM]; + + UINT_8 ucRoleInterfaceNum; + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + /* cfg80211 */ + struct wireless_dev *prWdev; + + struct cfg80211_scan_request *prScanRequest; + + UINT_64 u8Cookie; + + /* Generation for station list update. */ + INT_32 i4Generation; + + UINT_32 u4OsMgmtFrameFilter; + +#endif + + /* Device statistics */ + struct net_device_stats rNetDevStats; + + /* glue layer variables */ + /*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][560]; /* 0 for beacon, 1 for probe req, 2 for probe response */ + UINT_16 u2WSCIELen[3]; + +#if CFG_SUPPORT_WFD + UINT_8 aucWFDIE[400]; /* 0 for beacon, 1 for probe req, 2 for probe response */ + UINT_16 u2WFDIELen; + UINT_8 aucVenderIE[1024]; /* Save the other IE for prove resp, PLS DON'T COMMENT OUT, CROSSMOUNT */ + UINT_16 u2VenderIELen; +#endif + + UINT_8 ucOperatingChnl; + UINT_8 ucInvitationType; + + UINT_32 u4InvStatus; + + /* For SET_STRUCT/GET_STRUCT */ + UINT_8 aucOidBuf[OID_SET_GET_STRUCT_LENGTH]; + +#if 1 /* CFG_SUPPORT_ANTI_PIRACY */ + UINT_8 aucSecCheck[256]; + UINT_8 aucSecCheckRsp[256]; +#endif + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + /* Hotspot Client Management */ + /* + * dependent with #define P2P_MAXIMUM_CLIENT_COUNT 10, + * fix me to PARAM_MAC_ADDRESS aucblackMACList[P2P_MAXIMUM_CLIENT_COUNT]; + */ + PARAM_MAC_ADDRESS aucblackMACList[P2P_BLACKLIST_MAX_COUNT]; + UINT_8 ucMaxClients; +#endif + +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION + BOOLEAN fgEnableHotspotOptimization; + UINT_32 u4PsLevel; +#endif +}; + +#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; + /* Group 1 64 bytes */ + UINT_8 aucWfdLocalIp[4]; + UINT_16 WfdLifetimeAc2; /* Unit is 2 TU */ + UINT_16 WfdLifetimeAc3; /* Unit is 2 TU */ + UINT_16 WfdCounterThreshold; /* Unit is ms */ + UINT_8 aucReserved2[54]; + /* Group 3 64 bytes */ + UINT_8 aucReserved3[64]; + /* Group 3 64 bytes */ + UINT_8 aucReserved4[64]; +} NL80211_DRIVER_WFD_PARAMS, *P_NL80211_DRIVER_WFD_PARAMS; +#endif +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +BOOLEAN p2pLaunch(P_GLUE_INFO_T prGlueInfo); + +BOOLEAN p2pRemove(P_GLUE_INFO_T prGlueInfo); + +VOID p2pSetMode(IN BOOLEAN fgIsAPMode); + +BOOLEAN glRegisterP2P(P_GLUE_INFO_T prGlueInfo, const char *prDevName, BOOLEAN fgIsApMode); + +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 p2PFreeInfo(P_GLUE_INFO_T prGlueInfo); + +VOID p2pSetSuspendMode(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgEnable); + +BOOLEAN glP2pCreateWirelessDevice(P_GLUE_INFO_T prGlueInfo); + +VOID glP2pDestroyWirelessDevice(VOID); + +VOID p2pSetMulticastListWorkQueueWrapper(P_GLUE_INFO_T prGlueInfo); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_qa_agent.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_qa_agent.h new file mode 100644 index 0000000000000..9ed57b26d99c8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_qa_agent.h @@ -0,0 +1,228 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ +/*! \file gl_qa_agent.h + * \brief This file includes private ioctl support. + */ + +#ifndef _GL_QA_AGENT_H +#define _GL_QA_AGENT_H +#if CFG_SUPPORT_QA_TOOL +/******************************************************************************* +* C O M P I L E 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 +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#define HQA_CMD_MAGIC_NO 0x18142880 + +#if CFG_SUPPORT_TX_BF +#define HQA_BF_STR_SIZE 512 +#endif + +#define HQA_RX_STATISTIC_NUM 66 +#define MAX_EEPROM_BUFFER_SIZE 1200 + +#if 0 +typedef struct _PARAM_RX_STAT_T { + UINT_32 MacFCSErr; /* Y 0x820F_D014 */ + UINT_32 MacMdrdy; /* Y 0x820F_D030 */ + UINT_32 FCSErr_CCK; /* Y 0x8207_021C [15:00] */ + UINT_32 FCSErr_OFDM; /* Y 0x8207_021C [31:16] */ + UINT_32 CCK_PD; /* Y 0x8207_020C [15:00] */ + UINT_32 OFDM_PD; /* Y 0x8207_020C [15:00] */ + UINT_32 CCK_SIG_Err; /* Y 0x8207_0210 [31:16] */ + UINT_32 CCK_SFD_Err; /* Y 0x8207_0210 [15:00] */ + UINT_32 OFDM_SIG_Err; /* Y 0x8207_0214 [31:16] */ + UINT_32 OFDM_TAG_Err; /* Y 0x8207_0214 [15:00] */ + UINT_32 WB_RSSSI0; /* Y 0x8207_21A8 [23:16] */ + UINT_32 IB_RSSSI0; /* Y 0x8207_21A8 [31:24] */ + UINT_32 WB_RSSSI1; /* Y 0x8207_21A8 [07:00] */ + UINT_32 IB_RSSSI1; /* Y 0x8207_21A8 [15:08] */ + UINT_32 PhyMdrdyCCK; /* Y 0x8207_0220 [15:00] */ + UINT_32 PhyMdrdyOFDM; /* Y 0x8207_0220 [31:16] */ + UINT_32 DriverRxCount; /* Y FW Counter Band0 */ + UINT_32 RCPI0; /* Y RXV4 [07:00] */ + UINT_32 RCPI1; /* Y RXV4 [15:08] */ + UINT_32 FreqOffsetFromRX; /* Y RXV5 MISC1[24:00] OFDM:[11:00] CCK:[10:00] */ + UINT_32 RSSI0; /* N */ + UINT_32 RSSI1; /* N */ + UINT_32 rx_fifo_full; /* N */ + UINT_32 RxLenMismatch; /* N */ + UINT_32 MacFCSErr_band1; /* Y 0x820F_D214 */ + UINT_32 MacMdrdy_band1; /* Y 0x820F_D230 */ + /* Y RXV3 [23:16] (must set 0x8207066C[1:0] = 0x0 ~ 0x3) */ + UINT_32 FAGC_IB_RSSSI[4]; + /* Y RXV3 [31:24] (must set 0x8207066C[1:0] = 0x0 ~ 0x3) */ + UINT_32 FAGC_WB_RSSSI[4]; + /* Y 0x8207_21A8 [31:24] [15:08] 0x8207_29A8 [31:24] [15:08] */ + UINT_32 Inst_IB_RSSSI[4]; + /* Y 0x8207_21A8 [23:16] [07:00] 0x8207_29A8 [23:16] [07:00] */ + UINT_32 Inst_WB_RSSSI[4]; + UINT_32 ACIHitLow; /* Y 0x8207_21B0 [18] */ + UINT_32 ACIHitHigh; /* Y 0x8207_29B0 [18] */ + UINT_32 DriverRxCount1; /* Y FW Counter Band1 */ + UINT_32 RCPI2; /* Y RXV4 [23:16] */ + UINT_32 RCPI3; /* Y RXV4 [31:24] */ + UINT_32 RSSI2; /* N */ + UINT_32 RSSI3; /* N */ + UINT_32 SNR0; /* Y RXV5 (MISC1 >> 19) - 16 */ + UINT_32 SNR1; /* N */ + UINT_32 SNR2; /* N */ + UINT_32 SNR3; /* N */ + UINT_32 rx_fifo_full_band1; /* N */ + UINT_32 RxLenMismatch_band1; /* N */ + UINT_32 CCK_PD_band1; /* Y 0x8207_040C [15:00] */ + UINT_32 OFDM_PD_band1; /* Y 0x8207_040C [31:16] */ + UINT_32 CCK_SIG_Err_band1; /* Y 0x8207_0410 [31:16] */ + UINT_32 CCK_SFD_Err_band1; /* Y 0x8207_0410 [15:00] */ + UINT_32 OFDM_SIG_Err_band1; /* Y 0x8207_0414 [31:16] */ + UINT_32 OFDM_TAG_Err_band1; /* Y 0x8207_0414 [15:00] */ + UINT_32 PhyMdrdyCCK_band1; /* Y 0x8207_0420 [15:00] */ + UINT_32 PhyMdrdyOFDM_band1; /* Y 0x8207_0420 [31:16] */ + UINT_32 CCK_FCS_Err_band1; /* Y 0x8207_041C [15:00] */ + UINT_32 OFDM_FCS_Err_band1; /* Y 0x8207_041C [31:16] */ + UINT_32 MuPktCount; /* Y MT_ATEUpdateRxStatistic RXV1_2ND_CYCLE->GroupId */ +} PARAM_RX_STAT_T, *P_PARAM_RX_STAT_T; +#else +typedef struct _PARAM_RX_STAT_T { + UINT_32 MAC_FCS_Err; /* b0 */ + UINT_32 MAC_Mdrdy; /* b0 */ + UINT_32 FCSErr_CCK; + UINT_32 FCSErr_OFDM; + UINT_32 CCK_PD; + UINT_32 OFDM_PD; + UINT_32 CCK_SIG_Err; + UINT_32 CCK_SFD_Err; + UINT_32 OFDM_SIG_Err; + UINT_32 OFDM_TAG_Err; + UINT_32 WB_RSSI0; + UINT_32 IB_RSSI0; + UINT_32 WB_RSSI1; + UINT_32 IB_RSSI1; + UINT_32 PhyMdrdyCCK; + UINT_32 PhyMdrdyOFDM; + UINT_32 DriverRxCount; + UINT_32 RCPI0; + UINT_32 RCPI1; + UINT_32 FreqOffsetFromRX; + UINT_32 RSSI0; + UINT_32 RSSI1; /* insert new member here */ + UINT_32 OutOfResource; /* MT7615 begin here */ + UINT_32 LengthMismatchCount_B0; + UINT_32 MAC_FCS_Err1; /* b1 */ + UINT_32 MAC_Mdrdy1; /* b1 */ + UINT_32 FAGCRssiIBR0; + UINT_32 FAGCRssiIBR1; + UINT_32 FAGCRssiIBR2; + UINT_32 FAGCRssiIBR3; + UINT_32 FAGCRssiWBR0; + UINT_32 FAGCRssiWBR1; + UINT_32 FAGCRssiWBR2; + UINT_32 FAGCRssiWBR3; + + UINT_32 InstRssiIBR0; + UINT_32 InstRssiIBR1; + UINT_32 InstRssiIBR2; + UINT_32 InstRssiIBR3; + UINT_32 InstRssiWBR0; + UINT_32 InstRssiWBR1; + UINT_32 InstRssiWBR2; + UINT_32 InstRssiWBR3; + UINT_32 ACIHitLower; + UINT_32 ACIHitUpper; + UINT_32 DriverRxCount1; + UINT_32 RCPI2; + UINT_32 RCPI3; + UINT_32 RSSI2; + UINT_32 RSSI3; + UINT_32 SNR0; + UINT_32 SNR1; + UINT_32 SNR2; + UINT_32 SNR3; + UINT_32 OutOfResource1; + UINT_32 LengthMismatchCount_B1; + UINT_32 CCK_PD_Band1; + UINT_32 OFDM_PD_Band1; + UINT_32 CCK_SIG_Err_Band1; + UINT_32 CCK_SFD_Err_Band1; + UINT_32 OFDM_SIG_Err_Band1; + UINT_32 OFDM_TAG_Err_Band1; + UINT_32 PHY_CCK_MDRDY_Band1; + UINT_32 PHY_OFDM_MDRDY_Band1; + UINT_32 CCK_FCS_Err_Band1; + UINT_32 OFDM_FCS_Err_Band1; + UINT_32 MRURxCount; + UINT_32 SIGMCS; + UINT_32 SINR; + UINT_32 RXVRSSI; + UINT_32 Reserved[184]; + UINT_32 PHY_Mdrdy; + UINT_32 Noise_Floor; + UINT_32 AllLengthMismatchCount_B0; + UINT_32 AllLengthMismatchCount_B1; + UINT_32 AllMacMdrdy0; + UINT_32 AllMacMdrdy1; + UINT_32 AllFCSErr0; + UINT_32 AllFCSErr1; + UINT_32 RXOK0; + UINT_32 RXOK1; + UINT_32 PER0; + UINT_32 PER1; +} PARAM_RX_STAT_T, *P_PARAM_RX_STAT_T; +extern PARAM_RX_STAT_T g_HqaRxStat; +#endif + +typedef struct _HQA_CMD_FRAME { + UINT_32 MagicNo; + UINT_16 Type; + UINT_16 Id; + UINT_16 Length; + UINT_16 Sequence; + UCHAR Data[2048]; +} __packed HQA_CMD_FRAME; + +typedef INT_32(*HQA_CMD_HANDLER) (struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame); + +typedef struct _HQA_CMD_TABLE { + HQA_CMD_HANDLER *CmdSet; + UINT_32 CmdSetSize; + UINT_32 CmdOffset; +} HQA_CMD_TABLE; + +int HQA_CMDHandler(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame); + +int priv_qa_agent(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra); +#endif /*CFG_SUPPORT_QA_TOOL */ +#endif /* _GL_QA_AGENT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_rst.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_rst.h new file mode 100644 index 0000000000000..be87d4a7d22a1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_rst.h @@ -0,0 +1,180 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/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 +******************************************************************************** +*/ +#define RST_FLAG_CHIP_RESET 0 +#define RST_FLAG_DO_CORE_DUMP BIT(0) +#define RST_FLAG_PREVENT_POWER_OFF BIT(1) +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef enum _ENUM_RESET_STATUS_T { + RESET_FAIL, + RESET_SUCCESS +} ENUM_RESET_STATUS_T; + +typedef struct _RESET_STRUCT_T { + ENUM_RESET_STATUS_T rst_data; + struct work_struct rst_work; + struct work_struct rst_trigger_work; + UINT_32 rst_trigger_flag; +} RESET_STRUCT_T; + +#if CFG_CHIP_RESET_SUPPORT + +/* duplicated from wmt_exp.h for better driver isolation */ +enum ENUM_WMTDRV_TYPE { + WMTDRV_TYPE_BT = 0, + WMTDRV_TYPE_FM = 1, + WMTDRV_TYPE_GPS = 2, + WMTDRV_TYPE_WIFI = 3, + WMTDRV_TYPE_WMT = 4, + WMTDRV_TYPE_ANT = 5, + WMTDRV_TYPE_STP = 6, + WMTDRV_TYPE_SDIO1 = 7, + WMTDRV_TYPE_SDIO2 = 8, + WMTDRV_TYPE_LPBK = 9, + WMTDRV_TYPE_COREDUMP = 10, + WMTDRV_TYPE_MAX +}; + +enum ENUM_WMTMSG_TYPE { + 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 +}; + +typedef VOID(*PF_WMT_CB) (enum ENUM_WMTDRV_TYPE, /* Source driver type */ + enum ENUM_WMTDRV_TYPE, /* Destination driver type */ + enum ENUM_WMTMSG_TYPE, /* Message type */ + /* READ-ONLY buffer. Buffer is allocated and freed by WMT_drv. + * Client can't touch this buffer after this function return. + */ + PVOID, + UINT32 /* Buffer size in unit of byte */ + ); + +enum ENUM_WMTRSTMSG_TYPE { + WMTRSTMSG_RESET_START = 0x0, + WMTRSTMSG_RESET_END = 0x1, + WMTRSTMSG_RESET_END_FAIL = 0x2, + WMTRSTMSG_RESET_MAX, + WMTRSTMSG_RESET_INVALID = 0xff +}; +#endif + +struct MTK_WCN_WMT_WLAN_CB_INFO { + INT_32(*wlan_probe_cb) (VOID); + INT_32(*wlan_remove_cb) (VOID); + INT_32(*wlan_bus_cnt_get_cb) (VOID); + INT_32(*wlan_bus_cnt_clr_cb) (VOID); + INT_32(*wlan_emi_mpu_set_protection_cb) (BOOLEAN); + INT_32(*wlan_is_wifi_drv_own_cb) (VOID); +}; + +/******************************************************************************* +* E X T E R N A L F U N C T I O N S +******************************************************************************** +*/ + +#if CFG_CHIP_RESET_SUPPORT +extern int wifi_reset_start(VOID); +extern int wifi_reset_end(ENUM_RESET_STATUS_T); +extern INT_32 mtk_wcn_wmt_msgcb_unreg(enum ENUM_WMTDRV_TYPE eType); +extern INT_32 mtk_wcn_wmt_msgcb_reg(enum ENUM_WMTDRV_TYPE eType, PF_WMT_CB pCb); +extern INT_32 mtk_wcn_set_connsys_power_off_flag(INT_32 value); +extern INT_32 mtk_wcn_wmt_assert_timeout(enum ENUM_WMTDRV_TYPE type, UINT32 reason, INT_32 timeout); +extern INT_32 mtk_wcn_wmt_do_reset(enum ENUM_WMTDRV_TYPE type); +#endif + +extern UINT32 wmt_plat_read_cpupcr(VOID); +extern INT_32 mtk_wcn_wmt_wlan_reg(struct MTK_WCN_WMT_WLAN_CB_INFO *pWmtWlanCbInfo); +extern INT_32 mtk_wcn_wmt_wlan_unreg(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 +******************************************************************************** +*/ +#if CFG_CHIP_RESET_SUPPORT +#define GL_RESET_TRIGGER(_prAdapter, _u4Flags) \ + glResetTrigger(_prAdapter, (_u4Flags), (const PUINT_8)__FILE__, __LINE__) +#else +#define GL_RESET_TRIGGER(_prAdapter, _u4Flags) \ + DBGLOG(INIT, INFO, "DO NOT support chip reset\n") +#endif +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID glResetInit(VOID); + +VOID glResetUninit(VOID); + +VOID glSendResetRequest(VOID); + +BOOLEAN kalIsResetting(VOID); + +BOOLEAN kalIsResetTriggered(VOID); + +BOOLEAN glResetTrigger(P_ADAPTER_T prAdapter, UINT_32 u4RstFlag, const PUINT_8 pucFile, UINT_32 u4Line); + +UINT32 wlanPollingCpupcr(UINT32 u4Times, UINT32 u4Sleep); + +WLAN_STATUS wlanGetCpupcr(PUINT32 pu4Cpupcr); + +#endif /* _GL_RST_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_sec.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_sec.h new file mode 100644 index 0000000000000..eb387a7048fe0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_sec.h @@ -0,0 +1,36 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_sec.h#1 +*/ + +/* + * ! \file p2p_fsm.h + * \brief Declaration of functions and finite state machine for P2P Module. + * + * Declaration of functions and finite state machine for P2P Module. +*/ + +#ifndef _GL_SEC_H +#define _GL_SEC_H + +extern void handle_sec_msg_1(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_2(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_3(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_4(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_5(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_final(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); + +#endif /* _GL_SEC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_typedef.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_typedef.h new file mode 100644 index 0000000000000..96f6eb62634e5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_typedef.h @@ -0,0 +1,244 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/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. + */ + +#ifndef _GL_TYPEDEF_H +#define _GL_TYPEDEF_H + + +#include "config.h" + +#if CFG_ENABLE_EARLY_SUSPEND +#include +#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 CFG_ENABLE_EARLY_SUSPEND +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 int INT_32, *PINT_32, **PPINT_32; +typedef unsigned int UINT32, *PUINT32, **PPUINT32; +typedef signed long LONG, *PLONG, **PPLONG; +typedef signed long long INT_64, *PINT_64, **PPINT_64; + +/* Type definition for unsigned integers */ +typedef unsigned char UCHAR, *PUCHAR, **PPUCHAR; +typedef unsigned char UINT_8, *PUINT_8, **PPUINT_8, *P_UINT_8; +typedef unsigned short UINT_16, *PUINT_16, **PPUINT_16; +typedef unsigned int UINT_32, *PUINT_32, **PPUINT_32; +typedef unsigned long ULONG, *PULONG, **PPULONG; +typedef unsigned long long UINT_64, *PUINT_64, **PPUINT_64; + +typedef unsigned int OS_SYSTIME, *POS_SYSTIME, **PPOS_SYSTIME; + +/* Type definition of large integer (64bits) union to be comptaible with + * Windows definition, so we won't apply our own coding style to these data types. + * NOTE: LARGE_INTEGER must NOT be floating variable. + * : Check for big-endian compatibility. + */ +typedef union _LARGE_INTEGER { + struct { + UINT_32 LowPart; + INT_32 HighPart; + } u; + INT_64 QuadPart; +} LARGE_INTEGER, *PLARGE_INTEGER; + +typedef union _ULARGE_INTEGER { + struct { + UINT_32 LowPart; + UINT_32 HighPart; + } u; + UINT_64 QuadPart; +} ULARGE_INTEGER, *PULARGE_INTEGER; + +typedef INT_32(*probe_card) (PVOID pvData); +typedef VOID(*remove_card) (VOID); + +/******************************************************************************* +* P U B 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__ inline +#define __KAL_ATTRIB_PACKED__ __attribute__((__packed__)) +#define __KAL_ATTRIB_ALIGN_4__ __aligned(4) + +#ifndef BIT +#define BIT(n) (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) offsetof(_type, _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 NTOHS(_x) ntohs(_x) + +#define HTONS(_x) htons(_x) + +#define NTOHL(_x) ntohl(_x) + +#define HTONL(_x) htonl(_x) + +#else /* Big-Endian */ + +#define CONST_NTOHS(_x) + +#define CONST_HTONS(_x) + +#define NTOHS(_x) + +#define HTONS(_x) + +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _GL_TYPEDEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_vendor.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_vendor.h new file mode 100644 index 0000000000000..09c0b4a6a339a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_vendor.h @@ -0,0 +1,921 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _GL_VENDOR_H +#define _GL_VENDOR_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#include +#include +#include +#include + +#include "gl_os.h" + +#include "wlan_lib.h" +#include "gl_wext.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define GOOGLE_OUI 0x001A11 +#define OUI_QCA 0x001374 +#ifdef CFG_SUPPORT_DATA_STALL +#define OUI_MTK 0x000CE7 +#endif + +#define NL80211_VENDOR_SUBCMD_ACS 54 +#define NL80211_VENDOR_SUBCMD_GET_FEATURES 55 + +#define WIFI_VENDOR_ATTR_FEATURE_FLAGS 7 + +enum NL80211_VENDOR_FEATURES { + VENDOR_FEATURE_KEY_MGMT_OFFLOAD = 0, + VENDOR_FEATURE_SUPPORT_HW_MODE_ANY = 1, + VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS = 2, + VENDOR_FEATURE_P2P_LISTEN_OFFLOAD = 3, + VENDOR_FEATURE_OCE_STA = 4, + VENDOR_FEATURE_OCE_AP = 5, + VENDOR_FEATURE_OCE_STA_CFON = 6, + NUM_VENDOR_FEATURES /* keep last */ +}; + +typedef enum { + /* Don't use 0 as a valid subcommand */ + ANDROID_NL80211_SUBCMD_UNSPECIFIED, + + /* Define all vendor startup commands between 0x0 and 0x0FFF */ + ANDROID_NL80211_SUBCMD_WIFI_RANGE_START = 0x0001, + ANDROID_NL80211_SUBCMD_WIFI_RANGE_END = 0x0FFF, + + /* Define all GScan related commands between 0x1000 and 0x10FF */ + ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START = 0x1000, + ANDROID_NL80211_SUBCMD_GSCAN_RANGE_END = 0x10FF, + + /* Define all RTT related commands between 0x1100 and 0x11FF */ + ANDROID_NL80211_SUBCMD_RTT_RANGE_START = 0x1100, + ANDROID_NL80211_SUBCMD_RTT_RANGE_END = 0x11FF, + + ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START = 0x1200, + ANDROID_NL80211_SUBCMD_LSTATS_RANGE_END = 0x12FF, + + /* Define all Logger related commands between 0x1400 and 0x14FF */ + ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START = 0x1400, + ANDROID_NL80211_SUBCMD_DEBUG_RANGE_END = 0x14FF, + + /* Define all wifi offload related commands between 0x1600 and 0x16FF */ + ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START = 0x1600, + ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_END = 0x16FF, + + /* This is reserved for future usage */ + +} ANDROID_VENDOR_SUB_COMMAND; + +typedef enum { + WIFI_SUBCMD_GET_CHANNEL_LIST = ANDROID_NL80211_SUBCMD_WIFI_RANGE_START, + + WIFI_SUBCMD_GET_FEATURE_SET, /* 0x0002 */ + WIFI_SUBCMD_GET_FEATURE_SET_MATRIX, /* 0x0003 */ + WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI, /* 0x0004 */ + WIFI_SUBCMD_NODFS_SET, /* 0x0005 */ + WIFI_SUBCMD_SET_COUNTRY_CODE, /* 0x0006 */ + WIFI_SUBCMD_SET_RSSI_MONITOR, /* 0x0007 */ + + WIFI_SUBCMD_GET_ROAMING_CAPABILITIES, /* 0x0008 */ + WIFI_SUBCMD_CONFIG_ROAMING = 0x000a, /* 0x000a */ + WIFI_SUBCMD_ENABLE_ROAMING = 0x000b, /* 0x000b */ + WIFI_SUBCMD_SELECT_TX_POWER_SCENARIO, /* 0x000c */ + /* Add more sub commands here */ + +} WIFI_SUB_COMMAND; + +/* From supplicant */ +enum QCA_NL80211_VENDOR_SUBCMDS { + QCA_NL80211_VENDOR_SUBCMD_ROAMING = 0x0009, +}; + +typedef enum { + GSCAN_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START, + + GSCAN_SUBCMD_SET_CONFIG, /* 0x1001 */ + GSCAN_SUBCMD_SET_SCAN_CONFIG, /* 0x1002 */ + GSCAN_SUBCMD_ENABLE_GSCAN, /* 0x1003 */ + GSCAN_SUBCMD_GET_SCAN_RESULTS, /* 0x1004 */ + GSCAN_SUBCMD_SCAN_RESULTS, /* 0x1005 */ + + GSCAN_SUBCMD_SET_HOTLIST, /* 0x1006 */ + + GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG, /* 0x1007 */ + GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, /* 0x1008 */ + /* Add more sub commands here */ + +} GSCAN_SUB_COMMAND; + +typedef enum { + RTT_SUBCMD_SET_CONFIG = ANDROID_NL80211_SUBCMD_RTT_RANGE_START, + RTT_SUBCMD_CANCEL_CONFIG, + RTT_SUBCMD_GETCAPABILITY, +} RTT_SUB_COMMAND; + +typedef enum { + LSTATS_SUBCMD_GET_INFO = ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START, +} LSTATS_SUB_COMMAND; + +/* moved from wifi_logger.cpp */ +enum DEBUG_SUB_COMMAND { + LOGGER_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START, + LOGGER_GET_VER, + LOGGER_DRIVER_MEM_DUMP, +}; + +typedef enum { + WIFI_OFFLOAD_START_MKEEP_ALIVE = ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START, + WIFI_OFFLOAD_STOP_MKEEP_ALIVE, +} WIFI_OFFLOAD_SUB_COMMAND; + +typedef enum { + GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS, + GSCAN_EVENT_HOTLIST_RESULTS_FOUND, + GSCAN_EVENT_SCAN_RESULTS_AVAILABLE, + GSCAN_EVENT_FULL_SCAN_RESULTS, + RTT_EVENT_COMPLETE, + GSCAN_EVENT_COMPLETE_SCAN, + GSCAN_EVENT_HOTLIST_RESULTS_LOST, + WIFI_EVENT_RSSI_MONITOR, +#ifdef CFG_SUPPORT_DATA_STALL + WIFI_EVENT_DRIVER_ERROR +#endif +} WIFI_VENDOR_EVENT; +#ifdef CFG_SUPPORT_DATA_STALL +enum WIFI_DATA_STALL_ATTRIBUTE { + WIFI_ATTRIBUTE_ERROR_REASON = 0, +}; +#endif + +enum WIFI_P2P_VENDOR_EVENT { + WIFI_EVENT_ACS, +}; + +typedef enum { + WIFI_ATTRIBUTE_BAND = 1, + WIFI_ATTRIBUTE_NUM_CHANNELS, + WIFI_ATTRIBUTE_CHANNEL_LIST, + + WIFI_ATTRIBUTE_NUM_FEATURE_SET, + WIFI_ATTRIBUTE_FEATURE_SET, + WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, + WIFI_ATTRIBUTE_NODFS_VALUE, + WIFI_ATTRIBUTE_COUNTRY_CODE, + + WIFI_ATTRIBUTE_MAX_RSSI, + WIFI_ATTRIBUTE_MIN_RSSI, + WIFI_ATTRIBUTE_RSSI_MONITOR_START, + + WIFI_ATTRIBUTE_ROAMING_CAPABILITIES, + WIFI_ATTRIBUTE_ROAMING_BLACKLIST_NUM, + WIFI_ATTRIBUTE_ROAMING_BLACKLIST_BSSID, + WIFI_ATTRIBUTE_ROAMING_WHITELIST_NUM, + WIFI_ATTRIBUTE_ROAMING_WHITELIST_SSID, + WIFI_ATTRIBUTE_ROAMING_STATE + + +} WIFI_ATTRIBUTE; + +/* moved from wifi_logger.cpp */ +enum LOGGER_ATTRIBUTE { + LOGGER_ATTRIBUTE_DRIVER_VER, + LOGGER_ATTRIBUTE_FW_VER +}; + +typedef enum { + GSCAN_ATTRIBUTE_CAPABILITIES = 1, + + GSCAN_ATTRIBUTE_NUM_BUCKETS = 10, + GSCAN_ATTRIBUTE_BASE_PERIOD, + GSCAN_ATTRIBUTE_BUCKETS_BAND, + GSCAN_ATTRIBUTE_BUCKET_ID, + GSCAN_ATTRIBUTE_BUCKET_PERIOD, + GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS, + GSCAN_ATTRIBUTE_BUCKET_CHANNELS, + GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, + GSCAN_ATTRIBUTE_REPORT_THRESHOLD, + GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, + + GSCAN_ATTRIBUTE_ENABLE_FEATURE = 20, + GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, /* indicates no more results */ + GSCAN_ATTRIBUTE_FLUSH_FEATURE, /* Flush all the configs */ + GSCAN_ENABLE_FULL_SCAN_RESULTS, + GSCAN_ATTRIBUTE_REPORT_EVENTS, + /* Adaptive scan attributes */ + GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT, + GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD, + + GSCAN_ATTRIBUTE_NUM_OF_RESULTS = 30, + GSCAN_ATTRIBUTE_FLUSH_RESULTS, + GSCAN_ATTRIBUTE_SCAN_RESULTS, /* flat array of wifi_scan_result */ + GSCAN_ATTRIBUTE_SCAN_ID, /* indicates scan number */ + GSCAN_ATTRIBUTE_SCAN_FLAGS, /* indicates if scan was aborted */ + GSCAN_ATTRIBUTE_AP_FLAGS, /* flags on significant change event */ + GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK, + + GSCAN_ATTRIBUTE_SSID = 40, + GSCAN_ATTRIBUTE_BSSID, + GSCAN_ATTRIBUTE_CHANNEL, + GSCAN_ATTRIBUTE_RSSI, + GSCAN_ATTRIBUTE_TIMESTAMP, + GSCAN_ATTRIBUTE_RTT, + GSCAN_ATTRIBUTE_RTTSD, + + GSCAN_ATTRIBUTE_HOTLIST_BSSIDS = 50, + GSCAN_ATTRIBUTE_RSSI_LOW, + GSCAN_ATTRIBUTE_RSSI_HIGH, + GSCAN_ATTRIBUTE_HOTLIST_ELEM, + GSCAN_ATTRIBUTE_HOTLIST_FLUSH, + + GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE = 60, + GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, + GSCAN_ATTRIBUTE_MIN_BREACHING, + GSCAN_ATTRIBUTE_NUM_AP, + GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS, + GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + +} GSCAN_ATTRIBUTE; + +typedef enum { + RTT_ATTRIBUTE_CAPABILITIES = 1, + + RTT_ATTRIBUTE_TARGET_CNT = 10, + RTT_ATTRIBUTE_TARGET_INFO, + RTT_ATTRIBUTE_TARGET_MAC, + RTT_ATTRIBUTE_TARGET_TYPE, + RTT_ATTRIBUTE_TARGET_PEER, + RTT_ATTRIBUTE_TARGET_CHAN, + RTT_ATTRIBUTE_TARGET_PERIOD, + RTT_ATTRIBUTE_TARGET_NUM_BURST, + RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST, + RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM, + RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR, + RTT_ATTRIBUTE_TARGET_LCI, + RTT_ATTRIBUTE_TARGET_LCR, + RTT_ATTRIBUTE_TARGET_BURST_DURATION, + RTT_ATTRIBUTE_TARGET_PREAMBLE, + RTT_ATTRIBUTE_TARGET_BW, + RTT_ATTRIBUTE_RESULTS_COMPLETE = 30, + RTT_ATTRIBUTE_RESULTS_PER_TARGET, + RTT_ATTRIBUTE_RESULT_CNT, + RTT_ATTRIBUTE_RESULT +} RTT_ATTRIBUTE; + +typedef enum { + LSTATS_ATTRIBUTE_STATS = 2, +} LSTATS_ATTRIBUTE; + +typedef enum { + MKEEP_ALIVE_ATTRIBUTE_ID = 1, + MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN, + MKEEP_ALIVE_ATTRIBUTE_IP_PKT, + MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR, + MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR, + MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC +} WIFI_MKEEP_ALIVE_ATTRIBUTE; + +typedef enum { + WIFI_BAND_UNSPECIFIED, + WIFI_BAND_BG = 1, /* 2.4 GHz */ + WIFI_BAND_A = 2, /* 5 GHz without DFS */ + WIFI_BAND_A_DFS = 4, /* 5 GHz DFS only */ + WIFI_BAND_A_WITH_DFS = 6, /* 5 GHz with DFS */ + WIFI_BAND_ABG = 3, /* 2.4 GHz + 5 GHz; no DFS */ + WIFI_BAND_ABG_WITH_DFS = 7, /* 2.4 GHz + 5 GHz with DFS */ +} WIFI_BAND; + +typedef enum { + WIFI_SCAN_RESULTS_AVAILABLE, /* reported when REPORT_EVENTS_EACH_SCAN is set and a scan + * completes. WIFI_SCAN_THRESHOLD_NUM_SCANS or + * WIFI_SCAN_THRESHOLD_PERCENT can be reported instead if the + * reason for the event is available; however, at most one of + * these events should be reported per scan. If there are + * multiple buckets that were scanned this period and one has the + * EACH_SCAN flag set then this event should be preferred. + */ + WIFI_SCAN_THRESHOLD_NUM_SCANS, /* can be reported when REPORT_EVENTS_EACH_SCAN is not set and + * report_threshold_num_scans is reached. + */ + WIFI_SCAN_THRESHOLD_PERCENT, /* can be reported when REPORT_EVENTS_EACH_SCAN is not set and + * report_threshold_percent is reached. + */ + WIFI_SCAN_FAILED /* reported when currently executing gscans have failed. + * start_gscan will need to be called again in order to continue + * scanning. This is intended to indicate abnormal scan + * terminations (not those as a result of stop_gscan). + */ +} WIFI_SCAN_EVENT; + +#define REPORT_EVENTS_EACH_SCAN (1 << 0) +#define REPORT_EVENTS_FULL_RESULTS (1 << 1) +#define REPORT_EVENTS_NO_BATCH (1 << 2) + +#define GSCAN_MAX_REPORT_THRESHOLD 1024000 +#define GSCAN_MAX_CHANNELS 8 +#define GSCAN_MAX_BUCKETS 8 +#define MAX_HOTLIST_BSSIDS 16 +#define MAX_HOTLIST_SSIDS 16 +#define MAX_SIGNIFICANT_CHANGE_APS 16 +#define PSCAN_MAX_SCAN_CACHE_SIZE 16 +#define PSCAN_MAX_AP_CACHE_PER_SCAN 16 +#define PSCAN_VERSION 1 + +#define MAX_BUFFERED_GSCN_RESULTS 5 + +#define MAX_FW_ROAMING_BLACKLIST_SIZE 16 +#define MAX_FW_ROAMING_WHITELIST_SIZE 8 + +enum WIFI_VENDOR_ATTR_ACS { + WIFI_VENDOR_ATTR_ACS_CHANNEL_INVALID = 0, + WIFI_VENDOR_ATTR_ACS_PRIMARY_CHANNEL, + WIFI_VENDOR_ATTR_ACS_SECONDARY_CHANNEL, + WIFI_VENDOR_ATTR_ACS_HW_MODE, + WIFI_VENDOR_ATTR_ACS_HT_ENABLED, + WIFI_VENDOR_ATTR_ACS_HT40_ENABLED, + WIFI_VENDOR_ATTR_ACS_VHT_ENABLED, + WIFI_VENDOR_ATTR_ACS_CHWIDTH, + WIFI_VENDOR_ATTR_ACS_CH_LIST, + WIFI_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL, + WIFI_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL, + WIFI_VENDOR_ATTR_ACS_FREQ_LIST, + WIFI_VENDOR_ATTR_ACS_AFTER_LAST, + WIFI_VENDOR_ATTR_ACS_MAX = + WIFI_VENDOR_ATTR_ACS_AFTER_LAST - 1 +}; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef UINT_64 wifi_timestamp; /* In microseconds (us) */ +typedef UINT_64 wifi_timespan; /* In nanoseconds (ns) */ + +typedef UINT_8 mac_addr[6]; +typedef UINT_32 wifi_channel; /* Indicates channel frequency in MHz */ +typedef INT_32 wifi_rssi; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +#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 + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#if 1 +/* + * #define NLA_PUT(skb, attrtype, attrlen, data) \ + * do { \ + * if (unlikely(nla_put(skb, attrtype, attrlen, data) < 0)) \ + * goto nla_put_failure; \ + * } while (0) + * + * #define NLA_PUT_TYPE(skb, type, attrtype, value) \ + * do { \ + * type __tmp = value; \ + * NLA_PUT(skb, attrtype, sizeof(type), &__tmp); \ + * } while (0) + */ +#define NLA_PUT(skb, attrtype, attrlen, data) mtk_cfg80211_NLA_PUT(skb, attrtype, attrlen, data) + +#define NLA_PUT_TYPE(skb, type, attrtype, value) mtk_cfg80211_nla_put_type(skb, type, attrtype, value) + +#define NLA_PUT_U8(skb, attrtype, value) \ + NLA_PUT_TYPE(skb, NLA_PUT_DATE_U8, attrtype, value) + +#define NLA_PUT_U16(skb, attrtype, value) \ + NLA_PUT_TYPE(skb, NLA_PUT_DATE_U16, attrtype, value) + +#define NLA_PUT_U32(skb, attrtype, value) \ + NLA_PUT_TYPE(skb, NLA_PUT_DATE_U32, attrtype, value) + +#define NLA_PUT_U64(skb, attrtype, value) \ + NLA_PUT_TYPE(skb, NLA_PUT_DATE_U64, attrtype, value) + +#if (KERNEL_VERSION(4, 12, 0) <= LINUX_VERSION_CODE) +#define NLA_PARSE_NESTED(nlattr, maxtype, nla, policy) \ + nla_parse_nested(nlattr, maxtype, nla, policy, NULL) +#define NLA_PARSE(tb, maxtype, head, len, policy) \ + nla_parse(tb, maxtype, head, len, policy, NULL) +#else +#define NLA_PARSE_NESTED(nlattr, maxtype, nla, policy) \ + nla_parse_nested(nlattr, maxtype, nla, policy) +#define NLA_PARSE(tb, maxtype, head, len, policy) \ + nla_parse(tb, maxtype, head, len, policy) +#endif +#endif + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +typedef struct _PARAM_WIFI_GSCAN_GET_RESULT_PARAMS { + UINT_32 get_num; + UINT_8 flush; +} PARAM_WIFI_GSCAN_GET_RESULT_PARAMS, *P_PARAM_WIFI_GSCAN_GET_RESULT_PARAMS; + +typedef struct _PARAM_WIFI_GSCAN_ACTION_CMD_PARAMS { + UINT_8 ucPscanAct; + UINT_8 aucReserved[3]; +} PARAM_WIFI_GSCAN_ACTION_CMD_PARAMS, *P_PARAM_WIFI_GSCAN_ACTION_CMD_PARAMS; + +typedef struct _PARAM_WIFI_GSCAN_CAPABILITIES_STRUCT_T { + UINT_32 max_scan_cache_size; /* total space allocated for scan (in bytes) */ + UINT_32 max_scan_buckets; /* maximum number of channel buckets */ + UINT_32 max_ap_cache_per_scan; /* maximum number of APs that can be stored per scan */ + UINT_32 max_rssi_sample_size; /* number of RSSI samples used for averaging RSSI */ + UINT_32 max_scan_reporting_threshold; /* max possible report_threshold as described */ + /* in wifi_scan_cmd_params */ + UINT_32 max_hotlist_bssids; /* maximum number of entries for hotlist BSSIDs */ + UINT_32 max_hotlist_ssids; /* maximum number of entries for hotlist SSIDs */ + UINT_32 max_significant_wifi_change_aps; /* maximum number of entries for */ + /* significant wifi change APs */ + UINT_32 max_bssid_history_entries; /* number of BSSID/RSSI entries that device can hold */ + UINT_32 max_number_epno_networks; /* max number of epno entries */ + UINT_32 max_number_epno_networks_by_ssid; /* max number of epno entries if ssid is specified */ + UINT_32 max_number_of_white_listed_ssid; /* max number of white listed SSIDs, M target is 2 to 4 */ +} PARAM_WIFI_GSCAN_CAPABILITIES_STRUCT_T, *P_PARAM_WIFI_GSCAN_CAPABILITIES_STRUCT_T; + +typedef struct _PARAM_WIFI_GSCAN_CHANNEL_SPEC { + UINT_32 channel; /* frequency */ + UINT_32 dwellTimeMs; /* dwell time hint */ + UINT_32 passive; /* 0 => active, 1 => passive scan; ignored for DFS */ + /* Add channel class */ +} PARAM_WIFI_GSCAN_CHANNEL_SPEC, *P_PARAM_WIFI_GSCAN_CHANNEL_SPEC; + +typedef struct _PARAM_WIFI_GSCAN_BUCKET_SPEC { + UINT_32 bucket; /* bucket index, 0 based */ + WIFI_BAND band; /* when UNSPECIFIED, use channel list */ + UINT_32 period; /* desired period, in millisecond; if this is too */ + /* low, the firmware should choose to generate results as */ + /* fast as it can instead of failing the command */ + /* report_events semantics - + * This is a bit field; which defines following bits - + * REPORT_EVENTS_EACH_SCAN => report a scan completion event after scan. If this is not set + * then scan completion events should be reported if + * report_threshold_percent or report_threshold_num_scans is + * reached. + * REPORT_EVENTS_FULL_RESULTS => forward scan results (beacons/probe responses + IEs) + * in real time to HAL, in addition to completion events + * Note: To keep backward compatibility, fire completion + * events regardless of REPORT_EVENTS_EACH_SCAN. + * REPORT_EVENTS_NO_BATCH => controls if scans for this bucket should be placed in the + * history buffer + */ + UINT_8 report_events; + UINT_32 max_period; /* if max_period is non zero or different than period, then this bucket is + * an exponential backoff bucket and the scan period will grow exponentially + * as per formula: actual_period(N) = period * (base ^ (N/step_count)) + * to a maximum period of max_period + */ + UINT_32 step_count; /* for exponential back off bucket, number of scans to perform for a given period */ + + UINT_32 num_channels; + /* channels to scan; these may include DFS channels */ + /* Note that a given channel may appear in multiple buckets */ + PARAM_WIFI_GSCAN_CHANNEL_SPEC channels[GSCAN_MAX_CHANNELS]; +} PARAM_WIFI_GSCAN_BUCKET_SPEC, *P_PARAM_WIFI_GSCAN_BUCKET_SPEC; + +typedef struct _PARAM_WIFI_GSCAN_CMD_PARAMS { + UINT_32 base_period; /* base timer period in ms */ + UINT_32 max_ap_per_scan; /* number of APs to store in each scan in the */ + /* BSSID/RSSI history buffer (keep the highest RSSI APs) */ + UINT_32 report_threshold_percent; /* in %, when scan buffer is this much full, wake up AP */ + UINT_32 report_threshold_num_scans; + UINT_32 num_buckets; + PARAM_WIFI_GSCAN_BUCKET_SPEC buckets[GSCAN_MAX_BUCKETS]; +} PARAM_WIFI_GSCAN_CMD_PARAMS, *P_PARAM_WIFI_GSCAN_CMD_PARAMS; + +typedef struct _PARAM_WIFI_GSCAN_RESULT { + wifi_timestamp ts; /* time since boot (in microsecond) when the result was */ + /* retrieved */ + UINT_8 ssid[32 + 1]; /* null terminated */ + mac_addr bssid; + wifi_channel channel; /* channel frequency in MHz */ + wifi_rssi rssi; /* in db */ + wifi_timespan rtt; /* in nanoseconds */ + wifi_timespan rtt_sd; /* standard deviation in rtt */ + UINT_16 beacon_period; /* period advertised in the beacon */ + UINT_16 capability; /* capabilities advertised in the beacon */ + UINT_32 ie_length; /* size of the ie_data blob */ + UINT_8 ie_data[1]; /* blob of all the information elements found in the */ + /* beacon; this data should be a packed list of */ + /* wifi_information_element objects, one after the other. */ + /* other fields */ +} PARAM_WIFI_GSCAN_RESULT, *P_PARAM_WIFI_GSCAN_RESULT; + +typedef struct _PARAM_WIFI_GSCAN_RESULT_REPORT { + UINT_32 u4ScanId; + UINT_8 ucScanFlag; + UINT_8 ucReserved[3]; + UINT_32 u4BucketMask; + UINT_32 u4NumOfResults; + PARAM_WIFI_GSCAN_RESULT rResult[1]; +} PARAM_WIFI_GSCAN_RESULT_REPORT, *P_PARAM_WIFI_GSCAN_RESULT_REPORT; + +typedef struct _PARAM_WIFI_GSCAN_FULL_RESULT { + PARAM_WIFI_GSCAN_RESULT fixed; + UINT_32 u4BucketMask; /* scan chbucket bitmask */ + UINT_32 ie_length; /* byte length of Information Elements */ + UINT_8 ie_data[1]; /* IE data to follow */ +} PARAM_WIFI_GSCAN_FULL_RESULT, *P_PARAM_WIFI_GSCAN_FULL_RESULT; + +/* Significant wifi change */ +#if 0 + typedef struct _PARAM_WIFI_CHANGE_RESULT { + mac_addr bssid; /* BSSID */ + wifi_channel channel; /* channel frequency in MHz */ + UINT_32 num_rssi; /* number of rssi samples */ + wifi_rssi rssi[8]; /* RSSI history in db */ + } PARAM_WIFI_CHANGE_RESULT, *P_PARAM_WIFI_CHANGE_RESULT; +#endif + +typedef struct _PARAM_WIFI_CHANGE_RESULT { + UINT_16 flags; + UINT_16 channel; + mac_addr bssid; /* BSSID */ + INT_8 rssi[8]; /* RSSI history in db */ +} PARAM_WIFI_CHANGE_RESULT, *P_PARAM_WIFI_CHANGE_RESULT; + +typedef struct _PARAM_AP_THRESHOLD { + mac_addr bssid; /* AP BSSID */ + wifi_rssi low; /* low threshold */ + wifi_rssi high; /* high threshold */ + wifi_channel channel; /* channel hint */ +} PARAM_AP_THRESHOLD, *P_PARAM_AP_THRESHOLD; + +typedef struct _PARAM_WIFI_BSSID_HOTLIST { + UINT_32 lost_ap_sample_size; + UINT_32 num_ap; /* number of hotlist APs */ + PARAM_AP_THRESHOLD ap[MAX_HOTLIST_BSSIDS]; /* hotlist APs */ +} PARAM_WIFI_BSSID_HOTLIST, *P_PARAM_WIFI_BSSID_HOTLIST; + +typedef struct _PARAM_WIFI_SIGNIFICANT_CHANGE { + UINT_16 rssi_sample_size; /* number of samples for averaging RSSI */ + UINT_16 lost_ap_sample_size; /* number of samples to confirm AP loss */ + UINT_16 min_breaching; /* number of APs breaching threshold */ + UINT_16 num_ap; /* max 64 */ + PARAM_AP_THRESHOLD ap[MAX_SIGNIFICANT_CHANGE_APS]; +} PARAM_WIFI_SIGNIFICANT_CHANGE, *P_PARAM_WIFI_SIGNIFICANT_CHANGE; + +/* RTT Capabilities */ +typedef struct _PARAM_WIFI_RTT_CAPABILITIES { + UINT_8 rtt_one_sided_supported; /* if 1-sided rtt data collection is supported */ + UINT_8 rtt_ftm_supported; /* if ftm rtt data collection is supported */ + UINT_8 lci_support; /* if initiator supports LCI request. Applies to 2-sided RTT */ + UINT_8 lcr_support; /* if initiator supports LCR request. Applies to 2-sided RTT */ + UINT_8 preamble_support; /* bit mask indicates what preamble is supported by initiator */ + UINT_8 bw_support; /* bit mask indicates what BW is supported by initiator */ +} PARAM_WIFI_RTT_CAPABILITIES, *P_PARAM_WIFI_RTT_CAPABILITIES; + +/* channel operating width */ +typedef enum { + WIFI_CHAN_WIDTH_20 = 0, + WIFI_CHAN_WIDTH_40 = 1, + WIFI_CHAN_WIDTH_80 = 2, + WIFI_CHAN_WIDTH_160 = 3, + WIFI_CHAN_WIDTH_80P80 = 4, + WIFI_CHAN_WIDTH_5 = 5, + WIFI_CHAN_WIDTH_10 = 6, + WIFI_CHAN_WIDTH_INVALID = -1 +} WIFI_CHANNEL_WIDTH; + +/* channel information */ +typedef struct { + WIFI_CHANNEL_WIDTH width; + UINT_32 center_freq; + UINT_32 center_freq0; + UINT_32 center_freq1; +} WIFI_CHANNEL_INFO; + +/* channel statistics */ +typedef struct { + WIFI_CHANNEL_INFO channel; + UINT_32 on_time; + UINT_32 cca_busy_time; +} WIFI_CHANNEL_STAT; + +/* radio statistics */ +typedef struct { + UINT_32 radio; + UINT_32 on_time; + UINT_32 tx_time; + UINT_32 rx_time; + UINT_32 on_time_scan; + UINT_32 on_time_nbd; + UINT_32 on_time_gscan; + UINT_32 on_time_roam_scan; + UINT_32 on_time_pno_scan; + UINT_32 on_time_hs20; + UINT_32 num_channels; + WIFI_CHANNEL_STAT channels[]; +} WIFI_RADIO_STAT; + +/* wifi rate */ +typedef struct { + UINT_32 preamble:3; + UINT_32 nss:2; + UINT_32 bw:3; + UINT_32 rateMcsIdx:8; + + UINT_32 reserved:16; + UINT_32 bitrate; +} WIFI_RATE; + +/* per rate statistics */ +typedef struct { + WIFI_RATE rate; + UINT_32 tx_mpdu; + UINT_32 rx_mpdu; + UINT_32 mpdu_lost; + UINT_32 retries; + UINT_32 retries_short; + UINT_32 retries_long; +} WIFI_RATE_STAT; + +/*wifi_interface_link_layer_info*/ +typedef enum { + WIFI_DISCONNECTED = 0, + WIFI_AUTHENTICATING = 1, + WIFI_ASSOCIATING = 2, + WIFI_ASSOCIATED = 3, + WIFI_EAPOL_STARTED = 4, + WIFI_EAPOL_COMPLETED = 5, +} WIFI_CONNECTION_STATE; + +typedef enum { + WIFI_ROAMING_IDLE = 0, + WIFI_ROAMING_ACTIVE = 1, +} WIFI_ROAM_STATE; + +typedef enum { + WIFI_INTERFACE_STA = 0, + WIFI_INTERFACE_SOFTAP = 1, + WIFI_INTERFACE_IBSS = 2, + WIFI_INTERFACE_P2P_CLIENT = 3, + WIFI_INTERFACE_P2P_GO = 4, + WIFI_INTERFACE_NAN = 5, + WIFI_INTERFACE_MESH = 6, + WIFI_INTERFACE_UNKNOWN = -1 +} WIFI_INTERFACE_MODE; + +typedef struct { + WIFI_INTERFACE_MODE mode; + u8 mac_addr[6]; + WIFI_CONNECTION_STATE state; + WIFI_ROAM_STATE roaming; + u32 capabilities; + u8 ssid[33]; + u8 bssid[6]; + u8 ap_country_str[3]; + u8 country_str[3]; +} WIFI_INTERFACE_LINK_LAYER_INFO; + +/* access categories */ +typedef enum { + WIFI_AC_VO = 0, + WIFI_AC_VI = 1, + WIFI_AC_BE = 2, + WIFI_AC_BK = 3, + WIFI_AC_MAX = 4, +} WIFI_TRAFFIC_AC; + +/* wifi peer type */ +typedef enum { + WIFI_PEER_STA, + WIFI_PEER_AP, + WIFI_PEER_P2P_GO, + WIFI_PEER_P2P_CLIENT, + WIFI_PEER_NAN, + WIFI_PEER_TDLS, + WIFI_PEER_INVALID, +} WIFI_PEER_TYPE; + +/* per peer statistics */ +typedef struct { + WIFI_PEER_TYPE type; + UINT_8 peer_mac_address[6]; + UINT_32 capabilities; + UINT_32 num_rate; + WIFI_RATE_STAT rate_stats[]; +} WIFI_PEER_INFO; + +/* per access category statistics */ +typedef struct { + WIFI_TRAFFIC_AC ac; + UINT_32 tx_mpdu; + UINT_32 rx_mpdu; + UINT_32 tx_mcast; + + UINT_32 rx_mcast; + UINT_32 rx_ampdu; + UINT_32 tx_ampdu; + UINT_32 mpdu_lost; + UINT_32 retries; + UINT_32 retries_short; + UINT_32 retries_long; + UINT_32 contention_time_min; + UINT_32 contention_time_max; + UINT_32 contention_time_avg; + UINT_32 contention_num_samples; +} WIFI_WMM_AC_STAT; + +/* interface statistics */ +typedef struct { + WIFI_INTERFACE_LINK_LAYER_INFO info; + UINT_32 beacon_rx; + UINT_32 mgmt_rx; + UINT_32 mgmt_action_rx; + UINT_32 mgmt_action_tx; + wifi_rssi rssi_mgmt; + wifi_rssi rssi_data; + wifi_rssi rssi_ack; + WIFI_WMM_AC_STAT ac[WIFI_AC_MAX]; + UINT_32 num_peers; + WIFI_PEER_INFO peer_info[]; +} WIFI_IFACE_STAT; + + +typedef enum _ENUM_NLA_PUT_DATE_TYPE { + NLA_PUT_DATE_U8 = 0, + NLA_PUT_DATE_U16, + NLA_PUT_DATE_U32, + NLA_PUT_DATE_U64, +} ENUM_NLA_PUT_DATE_TYPE; + +/* RSSI Monitoring */ +typedef struct _PARAM_RSSI_MONITOR_T { + BOOLEAN enable; /* 1=Start, 0=Stop*/ + INT_8 max_rssi_value; + INT_8 min_rssi_value; + UINT_8 reserved[1]; +} PARAM_RSSI_MONITOR_T, *P_PARAM_RSSI_MONITOR_T; + +typedef struct { + UINT_8 version; + INT_8 rssi; + mac_addr BSSID; +} PARAM_RSSI_MONITOR_EVENT; + +/* Packet Keep Alive */ +typedef struct _PARAM_PACKET_KEEPALIVE_T { + BOOLEAN enable; /* 1=Start, 0=Stop*/ + UINT_8 index; + UINT_16 u2IpPktLen; + UINT_8 pIpPkt[256]; + mac_addr ucSrcMacAddr; + mac_addr ucDstMacAddr; + UINT_32 u4PeriodMsec; +} PARAM_PACKET_KEEPALIVE_T, *P_PARAM_PACKET_KEEPALIVE_T; + +struct PARAM_BSS_MAC_OUI { + uint8_t ucBssIndex; + uint8_t ucMacOui[MAC_OUI_LEN]; +}; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +int mtk_cfg80211_NLA_PUT(struct sk_buff *skb, int attrtype, int attrlen, const void *data); + +int mtk_cfg80211_nla_put_type(struct sk_buff *skb, ENUM_NLA_PUT_DATE_TYPE type, int attrtype, const void *value); + +int mtk_cfg80211_vendor_get_channel_list(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_country_code(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_get_gscan_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_scan_config(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_significant_change(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_hotlist(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_enable_scan(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_enable_full_scan_results(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_get_gscan_result(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_gscan_results(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len, BOOLEAN complete, BOOLEAN compValue); + +int mtk_cfg80211_vendor_get_rtt_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_llstats_get_info(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_rssi_monitoring(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_packet_keep_alive_start(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_packet_keep_alive_stop(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); +int mtk_cfg80211_vendor_get_version(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); +int mtk_cfg80211_vendor_set_tx_power_scenario(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); +int mtk_cfg80211_vendor_event_complete_scan(struct wiphy *wiphy, struct wireless_dev *wdev, + WIFI_SCAN_EVENT complete); +int mtk_cfg80211_vendor_event_scan_results_available(struct wiphy *wiphy, struct wireless_dev *wdev, UINT_32 num); + +int mtk_cfg80211_vendor_event_full_scan_results(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_GSCAN_FULL_RESULT pdata, UINT_32 data_len); + +int mtk_cfg80211_vendor_event_significant_change_results(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_CHANGE_RESULT pdata, UINT_32 data_len); + +int mtk_cfg80211_vendor_event_hotlist_ap_found(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_GSCAN_RESULT pdata, UINT_32 data_len); + +int mtk_cfg80211_vendor_event_hotlist_ap_lost(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_GSCAN_RESULT pdata, UINT_32 data_len); + +int mtk_cfg80211_vendor_event_rssi_beyond_range(struct wiphy *wiphy, struct wireless_dev *wdev, INT_32 rssi); + +int mtk_cfg80211_vendor_set_roaming_policy(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_get_roaming_capabilities(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); + +int mtk_cfg80211_vendor_config_roaming(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); + +int mtk_cfg80211_vendor_enable_roaming(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); +int mtk_cfg80211_vendor_get_supported_feature_set( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); +int mtk_cfg80211_vendor_set_scan_mac_oui(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); +int mtk_cfg80211_vendor_acs(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); + +int mtk_cfg80211_vendor_get_features(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); +int mtk_cfg80211_vendor_driver_memory_dump(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); +#ifdef CFG_SUPPORT_DATA_STALL +int mtk_cfg80211_vendor_event_driver_error(struct _ADAPTER_T *prAdapter, + enum ENUM_VENDOR_DRIVER_EVENT event, UINT_32 dataLen); +#endif +#endif /* _GL_VENDOR_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_wext.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_wext.h new file mode 100644 index 0000000000000..4c72cebe85eb4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_wext.h @@ -0,0 +1,431 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_wext.h#1 +*/ + +/* + * ! \file gl_wext.h + * \brief This file is for Portable Driver linux wireless extension support. + */ + +#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 +******************************************************************************** +*/ + +#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 + +/* 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 + +/******************************************************************************* +* 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 + +#define IW_AUTH_ALG_FT 0x00000008 +#define IW_AUTH_ALG_SAE 0x00000010 + +/******************************************************************************* +* 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 */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) +int std_wext_get_name(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_set_freq(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_get_freq(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_set_mode(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_get_mode(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_get_range(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_set_country(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_get_priv(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_set_ap(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_get_ap(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_set_mlme(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_set_scan(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_get_scan(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_set_essid(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_get_essid(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_get_rate(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_set_rts(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_get_rts(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_set_rts(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_set_txpow(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_get_txpow(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_set_encode(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_get_encode(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_set_power(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_get_power(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_SIOCSIWGENIE_Action(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_set_auth(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_set_encode_ext(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); + +int std_wext_SIOCSIWPMKSA_Action(struct net_device *prDev, + struct iw_request_info *prIwrInfo, union iwreq_data *wru, char *pcExtra); +#endif + +int wext_support_ioctl(IN struct net_device *prDev, IN struct ifreq *prIfReq, IN int i4Cmd); + +int +wext_set_rate(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN struct iw_param *prRate, IN char *pcExtra); + +void +wext_indicate_wext_event(IN P_GLUE_INFO_T prGlueInfo, + IN unsigned int u4Cmd, IN unsigned char *pucData, IN unsigned int u4DataLen); + +struct iw_statistics *wext_get_wireless_stats(struct net_device *prDev); + +BOOLEAN +wextSrchDesiredWPAIE(IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT PUINT_8 *ppucDesiredIE); + +#if CFG_SUPPORT_WPS +BOOLEAN +wextSrchDesiredWPSIE(IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT PUINT_8 *ppucDesiredIE); +#endif + +#if CFG_SUPPORT_PASSPOINT +BOOLEAN wextSrchDesiredHS20IE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE); + +BOOLEAN wextSrchDesiredInterworkingIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE); + +BOOLEAN wextSrchDesiredAdvProtocolIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE); + +BOOLEAN wextSrchDesiredRoamingConsortiumIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE); +#endif /* CFG_SUPPORT_PASSPOINT */ + +BOOLEAN wextSrchDesiredWAPIIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE); + +BOOLEAN wextSrchOkcAndPMKID(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucPMKID, OUT PUINT_8 okc); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* WIRELESS_EXT */ + +#endif /* _GL_WEXT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_wext_priv.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_wext_priv.h new file mode 100644 index 0000000000000..5634bdcf670de --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/include/gl_wext_priv.h @@ -0,0 +1,310 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_wext_priv.h#3 +*/ + +/* + * ! \file gl_wext_priv.h + * \brief This file includes private ioctl support. + */ + +#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 IOCTL_SET_DRIVER (SIOCIWFIRSTPRIV + 14) +#define IOCTL_GET_DRIVER (SIOCIWFIRSTPRIV + 15) + +#if CFG_SUPPORT_QA_TOOL +#define IOCTL_QA_TOOL_DAEMON (SIOCIWFIRSTPRIV + 16) +#define IOCTL_IWPRIV_ATE (SIOCIWFIRSTPRIV + 17) +#endif + +#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 + +#if CFG_SUPPORT_QA_TOOL +#define PRIV_QACMD_SET 29 +#endif + +#define PRIV_CMD_MET_PROFILING 33 + +/* wifi type: 11g, 11n, ... */ +#define PRIV_CMD_GET_WIFI_TYPE 34 + +/* 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 +#define OID_CUSTOM_TEST_ICAP_MODE 0xFFA0C913 + +/* 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 + +#if CFG_SUPPORT_LOWLATENCY_MODE +#define OID_CUSTOM_LOWLATENCY_MODE 0xFFA0CC00 +#endif + +#define OID_IPC_WIFI_LOG_UI 0xFFA0CC01 +#define OID_IPC_WIFI_LOG_LEVEL 0xFFA0CC02 + +#if CFG_SUPPORT_ANT_SWAP +#define OID_CUSTOM_QUERY_ANT_SWAP_CAPABILITY 0xFFA0CD00 +#endif + +/* Define magic key of test mode (Don't change it for future compatibity) */ +#define PRIV_CMD_TEST_MAGIC_KEY 2011 +#define PRIV_CMD_TEST_MAGIC_KEY_ICAP 2013 +/******************************************************************************* +* 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_set_driver(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); + +int priv_support_driver_cmd(IN struct net_device *prDev, IN OUT struct ifreq *prReq, IN int i4Cmd); + +INT_32 priv_driver_cmds(IN struct net_device *prNetDev, IN PCHAR pcCommand, IN INT_32 i4TotalLen); + +#if CFG_SUPPORT_QA_TOOL +int +priv_ate_set(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra); +#endif +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR +int kalGetRxRate(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_32 *pu4CurRate, IN UINT_32 *pu4MaxRate); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _GL_WEXT_PRIV_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/platform.c b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/platform.c new file mode 100644 index 0000000000000..939fe2260f560 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/linux/platform.c @@ -0,0 +1,473 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/platform.c#3 +*/ + +/* + * ! \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 + */ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#include +#include + +#include + +#include "gl_os.h" + +#if CFG_ENABLE_EARLY_SUSPEND +#include +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define WIFI_NVRAM_FILE_NAME "/mnt/vendor/nvdata/APCFG/APRDEB/WIFI" +#define WIFI_NVRAM_CUSTOM_NAME "/mnt/vendor/nvdata/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) +{ + struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; + struct net_device *prDev = ifa->ifa_dev->dev; + 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; + } +#if 0 /* CFG_SUPPORT_PASSPOINT */ + { + /* DBGLOG(REQ, INFO, "[netdev_event] IPV4_DAD is unlock now!!\n"); */ + prGlueInfo->fgIsDad = FALSE; + } +#endif /* CFG_SUPPORT_PASSPOINT */ + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + if (prGlueInfo == NULL) { + DBGLOG(REQ, INFO, "netdev_event: prGlueInfo is empty.\n"); + return NOTIFY_DONE; + } + + if (prGlueInfo->fgIsInSuspendMode == FALSE) { + /* + * DBGLOG(REQ, INFO, + * ("netdev_event: PARAM_MEDIA_STATE_DISCONNECTED. (%d)\n", prGlueInfo->eParamMediaStateIndicated)); + */ + return NOTIFY_DONE; + } + + kalSetNetAddressFromInterface(prGlueInfo, prDev, TRUE); + + return NOTIFY_DONE; + +} + +#if 0 /* CFG_SUPPORT_PASSPOINT */ +static int net6dev_event(struct notifier_block *nb, unsigned long notification, void *ptr) +{ + struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr; + struct net_device *prDev = ifa->idev->dev; + P_GLUE_INFO_T prGlueInfo = NULL; + + if (prDev == NULL) { + DBGLOG(REQ, INFO, "net6dev_event: device is empty.\n"); + return NOTIFY_DONE; + } + + if ((strncmp(prDev->name, "p2p", 3) != 0) && (strncmp(prDev->name, "wlan", 4) != 0)) { + DBGLOG(REQ, INFO, "net6dev_event: xxx\n"); + return NOTIFY_DONE; + } + + if (strncmp(prDev->name, "p2p", 3) == 0) { + /* because we store the address of prGlueInfo in p2p's private date of net device */ + /* *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->prP2PInfo->prDevHandler)) = prGlueInfo; */ + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + } else { /* wlan0 */ + prGlueInfo = (P_GLUE_INFO_T) netdev_priv(prDev); + } + + if (prGlueInfo == NULL) { + DBGLOG(REQ, INFO, "netdev_event: prGlueInfo is empty.\n"); + return NOTIFY_DONE; + } + /* DBGLOG(REQ, INFO, "[net6dev_event] IPV6_DAD is unlock now!!\n"); */ + prGlueInfo->fgIs6Dad = FALSE; + + return NOTIFY_DONE; +} +#endif /* CFG_SUPPORT_PASSPOINT */ + +static struct notifier_block inetaddr_notifier = { + .notifier_call = netdev_event, +}; + +#if 0 /* CFG_SUPPORT_PASSPOINT */ +static struct notifier_block inet6addr_notifier = { + .notifier_call = net6dev_event, +}; +#endif /* CFG_SUPPORT_PASSPOINT */ + +void wlanRegisterNotifier(void) +{ + register_inetaddr_notifier(&inetaddr_notifier); +#if 0 /* CFG_SUPPORT_PASSPOINT */ + register_inet6addr_notifier(&inet6addr_notifier); +#endif /* CFG_SUPPORT_PASSPOINT */ +} + +void wlanUnregisterNotifier(void) +{ + unregister_inetaddr_notifier(&inetaddr_notifier); +#if 0 /* CFG_SUPPORT_PASSPOINT */ + unregister_inetaddr_notifier(&inet6addr_notifier); +#endif /* CFG_SUPPORT_PASSPOINT */ +} + +#if CFG_ENABLE_EARLY_SUSPEND +/*----------------------------------------------------------------------------*/ +/*! +* \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 (wlanSuspend != NULL) + prDesc->suspend = wlanSuspend; + else { + DBGLOG(REQ, INFO, "glRegisterEarlySuspend wlanSuspend ERROR.\n"); + ret = -1; + } + + if (wlanResume != NULL) + prDesc->resume = wlanResume; + else { + DBGLOG(REQ, INFO, "glRegisterEarlySuspend wlanResume ERROR.\n"); + ret = -1; + } + + register_early_suspend(prDesc); + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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; +} +#endif + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \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; + loff_t pos; + char __user *p; + + 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, "[nvram_read] : failed to open!!\n"); + set_fs(old_fs); + return -1; + } + + do { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + if (fd->f_op == NULL) { +#else + if ((fd->f_op == NULL) || (fd->f_op->read == NULL)) { +#endif + DBGLOG(INIT, INFO, "[nvram_read] : f_op is NULL!!\n"); + break; + } + + if (fd->f_pos != offset) { + if (fd->f_op->llseek) { + if (fd->f_op->llseek(fd, offset, 0) != offset) { + DBGLOG(INIT, INFO, "[nvram_read] : failed to seek!!\n"); + break; + } + } else { + fd->f_pos = offset; + } + } + + p = (__force char __user *)buf; + pos = (loff_t)offset; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + retLen = __vfs_read(fd, p, len, &pos); +#else + retLen = fd->f_op->read(fd, buf, len, &fd->f_pos); +#endif + if (retLen < 0) + DBGLOG(INIT, ERROR, "[nvram_read] : read failed!! Error code: %d\n", retLen); + + } 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; + loff_t pos; + char __user *p; + + 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, "[nvram_write] : failed to open!!\n"); + return -1; + } + + do { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + if (fd->f_op == NULL) { +#else + if ((fd->f_op == NULL) || (fd->f_op->write == NULL)) { +#endif + DBGLOG(INIT, INFO, "[nvram_write] : f_op is NULL!!\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, "[nvram_write] : failed to seek!!\n"); + break; + } + } else { + fd->f_pos = offset; + } + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + p = (__force char __user *)buf; + pos = (loff_t)offset; + + retLen = __vfs_write(fd, p, len, &pos); +#else + retLen = fd->f_op->write(fd, buf, len, &fd->f_pos); +#endif + if (retLen < 0) + DBGLOG(INIT, ERROR, "[nvram_write] : write failed!! Error code: %d\n", retLen); + + } while (FALSE); + + filp_close(fd, NULL); + + set_fs(old_fs); + + return retLen; + +#else /* !CFG_SUPPORT_NVRAMS */ + + return -EIO; + +#endif +} +#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 (u4Offset + sizeof(unsigned short) >= CFG_FILE_WIFI_REC_SIZE) + return FALSE; + + kalMemCopy(pu2Data, &g_aucNvram[u4Offset], sizeof(unsigned short)); + return TRUE; + + +#if 0 + if (nvram_read(WIFI_NVRAM_FILE_NAME, + (char *)pu2Data, sizeof(unsigned short), u4Offset) != sizeof(unsigned short)) { + return FALSE; + } else { + return TRUE; + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 (u4Offset + sizeof(unsigned short) >= CFG_FILE_WIFI_REC_SIZE) + return FALSE; + + kalMemCopy(&g_aucNvram[u4Offset], &u2Data, sizeof(unsigned short)); + return TRUE; +#if 0 + if (nvram_write(WIFI_NVRAM_FILE_NAME, + (char *)&u2Data, sizeof(unsigned short), u4Offset) != sizeof(unsigned short)) { + return FALSE; + } else { + return TRUE; + } +#endif +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/version.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/version.h new file mode 100644 index 0000000000000..7f715ecc274d7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/os/version.h @@ -0,0 +1,99 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/version.h#1 +*/ + +/* + * ! \file "version.h" + * \brief Driver's version definition + */ + +#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(MT6630) +#define NIC_NAME "MT6630" +#elif defined(MT6631) +#define NIC_NAME "MT6631" +#endif +#endif + +/* NIC driver information */ +#define NIC_VENDOR "MediaTek Inc." +#define NIC_VENDOR_OUI {0x00, 0x0C, 0xE7} + +#define NIC_PRODUCT_NAME NIC_VENDOR " " NIC_NAME " Wireless LAN Adapter" +#define NIC_DRIVER_NAME NIC_VENDOR " " NIC_NAME " Wireless LAN Adapter Driver" + +/* 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 */ From eeb4c3d2f694f74c9044e3691dff8948aaef854b Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 22:00:43 +0800 Subject: [PATCH 17/32] Add files via upload --- .../wlan/core/gen3/include/CFG_Wifi_File.h | 371 ++ .../wlan/core/gen3/include/config.h | 977 ++++++ .../wlan/core/gen3/include/debug.h | 422 +++ .../wlan/core/gen3/include/fwcfg.h | 142 + .../wlan/core/gen3/include/link.h | 456 +++ .../wlan/core/gen3/include/mgmt/aa_fsm.h | 170 + .../wlan/core/gen3/include/mgmt/ais_fsm.h | 504 +++ .../wlan/core/gen3/include/mgmt/assoc.h | 98 + .../wlan/core/gen3/include/mgmt/auth.h | 121 + .../wlan/core/gen3/include/mgmt/bow_fsm.h | 152 + .../wlan/core/gen3/include/mgmt/bss.h | 200 ++ .../wlan/core/gen3/include/mgmt/cnm.h | 229 ++ .../wlan/core/gen3/include/mgmt/cnm_mem.h | 913 +++++ .../wlan/core/gen3/include/mgmt/cnm_scan.h | 124 + .../wlan/core/gen3/include/mgmt/cnm_timer.h | 223 ++ .../wlan/core/gen3/include/mgmt/hem_mbox.h | 281 ++ .../wlan/core/gen3/include/mgmt/hs20.h | 144 + .../wlan/core/gen3/include/mgmt/mib.h | 136 + .../wlan/core/gen3/include/mgmt/p2p_assoc.h | 65 + .../wlan/core/gen3/include/mgmt/p2p_bss.h | 71 + .../wlan/core/gen3/include/mgmt/p2p_dev.h | 222 ++ .../core/gen3/include/mgmt/p2p_dev_state.h | 60 + .../wlan/core/gen3/include/mgmt/p2p_fsm.h | 1235 +++++++ .../wlan/core/gen3/include/mgmt/p2p_func.h | 237 ++ .../wlan/core/gen3/include/mgmt/p2p_ie.h | 63 + .../wlan/core/gen3/include/mgmt/p2p_rlm.h | 82 + .../core/gen3/include/mgmt/p2p_rlm_obss.h | 78 + .../wlan/core/gen3/include/mgmt/p2p_role.h | 311 ++ .../core/gen3/include/mgmt/p2p_role_state.h | 66 + .../wlan/core/gen3/include/mgmt/p2p_scan.h | 80 + .../wlan/core/gen3/include/mgmt/p2p_state.h | 57 + .../wlan/core/gen3/include/mgmt/privacy.h | 284 ++ .../wlan/core/gen3/include/mgmt/qosmap.h | 65 + .../wlan/core/gen3/include/mgmt/rate.h | 88 + .../wlan/core/gen3/include/mgmt/rlm.h | 402 +++ .../wlan/core/gen3/include/mgmt/rlm_domain.h | 526 +++ .../wlan/core/gen3/include/mgmt/rlm_obss.h | 108 + .../core/gen3/include/mgmt/rlm_protection.h | 105 + .../core/gen3/include/mgmt/rlm_txpwr_init.h | 1213 +++++++ .../wlan/core/gen3/include/mgmt/roaming_fsm.h | 153 + .../wlan/core/gen3/include/mgmt/rsn.h | 244 ++ .../wlan/core/gen3/include/mgmt/scan.h | 818 +++++ .../wlan/core/gen3/include/mgmt/sec_fsm.h | 129 + .../wlan/core/gen3/include/mgmt/stats.h | 104 + .../wlan/core/gen3/include/mgmt/swcr.h | 206 ++ .../wlan/core/gen3/include/mgmt/tdls.h | 427 +++ .../wlan/core/gen3/include/mgmt/wapi.h | 91 + .../core/gen3/include/mgmt/wlan_typedef.h | 100 + .../wlan/core/gen3/include/mgmt/wmm.h | 195 ++ .../wlan/core/gen3/include/mgmt/wnm.h | 141 + .../wlan/core/gen3/include/nic/adapter.h | 1254 +++++++ .../wlan/core/gen3/include/nic/bow.h | 229 ++ .../wlan/core/gen3/include/nic/cmd_buf.h | 173 + .../wlan/core/gen3/include/nic/hal.h | 628 ++++ .../wlan/core/gen3/include/nic/hif_rx.h | 118 + .../wlan/core/gen3/include/nic/hif_tx.h | 128 + .../wlan/core/gen3/include/nic/mac.h | 2997 +++++++++++++++++ .../wlan/core/gen3/include/nic/mt6630_reg.h | 322 ++ .../wlan/core/gen3/include/nic/nic.h | 358 ++ .../wlan/core/gen3/include/nic/nic_rate.h | 122 + .../wlan/core/gen3/include/nic/nic_rx.h | 900 +++++ .../wlan/core/gen3/include/nic/nic_tx.h | 1352 ++++++++ .../wlan/core/gen3/include/nic/p2p.h | 334 ++ .../wlan/core/gen3/include/nic/p2p_cmd_buf.h | 79 + .../wlan/core/gen3/include/nic/p2p_mac.h | 402 +++ .../wlan/core/gen3/include/nic/p2p_nic.h | 75 + .../core/gen3/include/nic/p2p_nic_cmd_event.h | 84 + .../wlan/core/gen3/include/nic/que_mgt.h | 1060 ++++++ .../wlan/core/gen3/include/nic/wlan_def.h | 927 +++++ .../wlan/core/gen3/include/nic_cmd_event.h | 2551 ++++++++++++++ .../core/gen3/include/nic_init_cmd_event.h | 186 + .../wlan/core/gen3/include/p2p_precomp.h | 215 ++ .../wlan/core/gen3/include/p2p_typedef.h | 183 + .../wlan/core/gen3/include/precomp.h | 258 ++ .../wlan/core/gen3/include/pwr_mgt.h | 112 + .../wlan/core/gen3/include/queue.h | 195 ++ .../wlan/core/gen3/include/rftest.h | 395 +++ .../wlan/core/gen3/include/typedef.h | 167 + .../wlan/core/gen3/include/wlan_bow.h | 265 ++ .../wlan/core/gen3/include/wlan_lib.h | 1055 ++++++ .../wlan/core/gen3/include/wlan_oid.h | 2491 ++++++++++++++ .../wlan/core/gen3/include/wlan_p2p.h | 236 ++ 82 files changed, 33540 insertions(+) create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/CFG_Wifi_File.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/config.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/debug.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/fwcfg.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/link.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/aa_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/ais_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/assoc.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/auth.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/bow_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/bss.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/cnm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/cnm_mem.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/cnm_scan.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/cnm_timer.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/hem_mbox.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/hs20.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/mib.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_assoc.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_bss.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_dev.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_dev_state.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_func.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_ie.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_rlm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_rlm_obss.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_role.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_role_state.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_scan.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_state.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/privacy.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/qosmap.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rate.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rlm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rlm_domain.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rlm_obss.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rlm_protection.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rlm_txpwr_init.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/roaming_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rsn.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/scan.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/sec_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/stats.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/swcr.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/tdls.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/wapi.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/wlan_typedef.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/wmm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/wnm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/adapter.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/bow.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/cmd_buf.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/hal.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/hif_rx.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/hif_tx.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/mac.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/mt6630_reg.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/nic.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/nic_rate.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/nic_rx.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/nic_tx.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/p2p.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/p2p_cmd_buf.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/p2p_mac.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/p2p_nic.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/p2p_nic_cmd_event.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/que_mgt.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/wlan_def.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic_cmd_event.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic_init_cmd_event.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/p2p_precomp.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/p2p_typedef.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/precomp.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/pwr_mgt.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/queue.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/rftest.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/typedef.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/wlan_bow.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/wlan_lib.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/wlan_oid.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen3/include/wlan_p2p.h diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/CFG_Wifi_File.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/CFG_Wifi_File.h new file mode 100644 index 0000000000000..db98722425b93 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/CFG_Wifi_File.h @@ -0,0 +1,371 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * ! \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. + */ + +#ifndef _CFG_WIFI_FILE_H +#define _CFG_WIFI_FILE_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_typedef.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +/* duplicated from nic_cmd_event.h to avoid header dependency */ +typedef struct _TX_PWR_PARAM_T { + INT_8 cTxPwr2G4Cck; /* signed, in unit of 0.5dBm */ + INT_8 cTxPwr2G4Dsss; /* signed, in unit of 0.5dBm */ + INT_8 acReserved[2]; + + 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 _TX_AC_PWR_T { + INT_8 c11AcTxPwr_BPSK; + INT_8 c11AcTxPwr_QPSK; + INT_8 c11AcTxPwr_16QAM; + INT_8 c11AcTxPwr_MCS5_MCS6; + INT_8 c11AcTxPwr_MCS7; + INT_8 c11AcTxPwr_MCS8; + INT_8 c11AcTxPwr_MCS9; + INT_8 c11AcTxPwrVht40_OFFSET; + INT_8 c11AcTxPwrVht80_OFFSET; + INT_8 c11AcTxPwrVht160_OFFSET; + INT_8 acReverse[2]; +} TX_AC_PWR_T, *P_TX_AC_PWR_T; + +typedef struct _RSSI_PATH_COMPASATION_T { + INT_8 c2GRssiCompensation; + INT_8 c5GRssiCompensation; +} RSSI_PATH_COMPASATION_T, *P_RSSI_PATH_COMPASATION_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; + +#if CFG_SUPPORT_PCC +struct TXRX_STRONG_COMPENSATION_T { + UINT_8 fgRxRxStrongComensation; + INT_8 acTxPwrOffset_24G[14]; /* 2.4G TSSI per channel offset */ + INT_8 acTxPwrLoss_24G[14]; /* 2.4G TX path loss per channel compensation */ + INT_8 acRxCompensation_24G[14]; /* 2.4G RSSI per channel compensation */ + INT_8 acTxPwrOffset_5G_GRP[8]; /* 5G TSSI per channel offset */ + INT_8 acTxPwrLoss_5G_GRP[8]; /* 5G TX path loss per channel compensation */ + INT_8 acRxCompensation_5G[8]; /* 5G RSSI per channel compensation */ +} __KAL_ATTRIB_PACKED__; + +struct DPD_INFO { + INT_8 acDPDEnable; /* 2G DPD G0 Enable */ + INT_8 acDPDChannel1; /* 2G Ch1 DPD Value */ + INT_8 acDPDChannel2; /* 2G Ch2 DPD Value */ + INT_8 acDPDChannel3; /* 2G Ch3 DPD Value */ + INT_8 acDPDChannel4; /* 2G Ch4 DPD Value */ + INT_8 acDPDChannel5; /* 2G Ch5 DPD Value */ + INT_8 acDPDChannel6; /* 2G Ch6 DPD Value */ + INT_8 acDPDChannel7; /* 2G Ch7 DPD Value */ + INT_8 acDPDChannel8; /* 2G Ch8 DPD Value */ + INT_8 acDPDChannel9; /* 2G Ch9 DPD Value */ + INT_8 acDPDChannel10; /* 2G Ch10 DPD Value */ + INT_8 acDPDChannel11; /* 2G Ch11 DPD Value */ + INT_8 acDPDChannel12; /* 2G Ch12 DPD Value */ + INT_8 acDPDChannel13; /* 2G Ch13 DPD Value */ + INT_8 acDPDChannel14; /* 2G Ch14 DPD Value */ +} __KAL_ATTRIB_PACKED__; +#endif + +#if 0 +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; +#else + +typedef struct _AC_PWR_SETTING_STRUCT { + UINT_8 c11AcTxPwr_BPSK; + UINT_8 c11AcTxPwr_QPSK; + UINT_8 c11AcTxPwr_16QAM; + UINT_8 c11AcTxPwr_MCS5_MCS6; + UINT_8 c11AcTxPwr_MCS7; + UINT_8 c11AcTxPwr_MCS8; + UINT_8 c11AcTxPwr_MCS9; + UINT_8 c11AcTxPwr_Reserved; + UINT_8 c11AcTxPwrVht40_OFFSET; + UINT_8 c11AcTxPwrVht80_OFFSET; + UINT_8 c11AcTxPwrVht160_OFFSET; +} AC_PWR_SETTING_STRUCT, *P_AC_PWR_SETTING_STRUCT; + +typedef struct _BANDEDGE_5G_T { + UINT_8 uc5GBandEdgePwrUsed; + UINT_8 c5GBandEdgeMaxPwrOFDM20; + UINT_8 c5GBandEdgeMaxPwrOFDM40; + UINT_8 c5GBandEdgeMaxPwrOFDM80; + +} BANDEDGE_5G_T, *P_BANDEDGE_5G_T; + +typedef struct _NEW_EFUSE_MAPPING2NVRAM_T { + UINT_8 ucReverse1[8]; + UINT_16 u2Signature; + BANDEDGE_5G_T r5GBandEdgePwr; + UINT_8 ucReverse2[14]; + + /* 0x50 */ + UINT_8 aucChOffset[3]; + UINT_8 ucChannelOffsetVaild; + UINT_8 acAllChannelOffset; + UINT_8 aucChOffset3[11]; + + /* 0x60 */ + UINT_8 auc5GChOffset[8]; + UINT_8 uc5GChannelOffsetVaild; + UINT_8 aucChOffset4[7]; + + /* 0x70 */ + AC_PWR_SETTING_STRUCT r11AcTxPwr; + UINT_8 uc11AcTxPwrValid; + + UINT_8 ucReverse4[20]; + + /* 0x90 */ + AC_PWR_SETTING_STRUCT r11AcTxPwr2G; + UINT_8 uc11AcTxPwrValid2G; + + UINT_8 ucReverse5[40]; +} NEW_EFUSE_MAPPING2NVRAM_T, *P_NEW_EFUSE_MAPPING2NVRAM_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; +#if CFG_SUPPORT_NVRAM_5G + union { + NEW_EFUSE_MAPPING2NVRAM_T u; + UINT_8 aucEFUSE[144]; + } EfuseMapping; +#else + UINT_8 aucEFUSE[144]; +#endif + 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 ucRxDiversity; + RSSI_PATH_COMPASATION_T rRssiPathCompensation; + UINT_8 fgRssiCompensationVaildbit; + UINT_8 ucGpsDesense; + UINT_16 u2FeatureReserved; + UINT_8 aucPreTailReserved; + UINT_8 aucTailReserved[256 - 15]; +#if CFG_SUPPORT_PCC + /* support PCC feature */ + struct TXRX_STRONG_COMPENSATION_T rTxRxStrComp; /* Start addr 0x200, offset is 0x43 */ + /* support PCC feature */ + struct DPD_INFO rDPDInfo; /* Start addr 0x243, offset is 0xF */ + + /* support ANTSWAP feature */ + struct TXRX_STRONG_COMPENSATION_T rTxRxStrCompAnt1; /* Start addr 0x252, offset is 0x43 */ + /* support ANTSWAP feature */ + struct DPD_INFO rDPDInfoAnt1; + + UINT_8 aucTailPCCReserved[512-67-15-67-15]; /* Start addr 0x252, offset is 0x1AE */ +#endif +} MT6620_CFG_PARAM_STRUCT, *P_MT6620_CFG_PARAM_STRUCT, WIFI_CFG_PARAM_STRUCT, *P_WIFI_CFG_PARAM_STRUCT; + +#endif +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifndef DATA_STRUCT_INSPECTING_ASSERT +#define DATA_STRUCT_INSPECTING_ASSERT(expr) \ + {switch (0) {case 0: case (expr): default:; } } +#endif + +#define CFG_FILE_WIFI_REC_SIZE sizeof(WIFI_CFG_PARAM_STRUCT) +#if CFG_SUPPORT_PCC +#define EXTEND_NVRAM_SIZE 1024 +#else +#define EXTEND_NVRAM_SIZE 512 +#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 +******************************************************************************** +*/ +#ifndef _lint +/* We don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + * We'll need this to guarantee the same member order in different structures + * to simply handling effort in some functions. + */ +static __KAL_INLINE__ VOID nvramOffsetCheck(VOID) +{ + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part2OwnVersion) == 256); + +#if CFG_SUPPORT_PCC + DATA_STRUCT_INSPECTING_ASSERT(sizeof(WIFI_CFG_PARAM_STRUCT) == EXTEND_NVRAM_SIZE); +#else + DATA_STRUCT_INSPECTING_ASSERT(sizeof(WIFI_CFG_PARAM_STRUCT) == 512); +#endif +#if CFG_SUPPORT_NVRAM_5G + DATA_STRUCT_INSPECTING_ASSERT((OFFSET_OF(WIFI_CFG_PARAM_STRUCT, EfuseMapping) & 0x0001) == 0); +#else + DATA_STRUCT_INSPECTING_ASSERT((OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucEFUSE) & 0x0001) == 0); +#endif + DATA_STRUCT_INSPECTING_ASSERT((OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucRegSubbandInfo) & 0x0001) + == 0); +#if CFG_SUPPORT_PCC + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(WIFI_CFG_PARAM_STRUCT, ucRxDiversity) == 263); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(WIFI_CFG_PARAM_STRUCT, fgRssiCompensationVaildbit) == 266); + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2FeatureReserved) == 268); + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucTailReserved) == 271); + /*DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucTailPCCReserved) == 0x252);*/ +#endif +} +#endif + +#endif /* _CFG_WIFI_FILE_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/config.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/config.h new file mode 100644 index 0000000000000..0c009f56f22a6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/config.h @@ -0,0 +1,977 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/config.h#3 + */ + +/* + * ! \file "config.h" + * \brief This file includes the various configurable parameters for customers + * + * This file includes the configurable parameters except the parameters indicate the turning-on/off of some features + */ + +#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 +******************************************************************************** +*/ + +/******************************************************************************* +* 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 +#if defined(MT6631) +#define MTK_WCN_HIF_SDIO 0 +#else +#define MTK_WCN_HIF_SDIO 1 +#endif +#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 + +#define CFG_SUPPORT_MTK_ANDROID_KK 1 + +#define CFG_ENABLE_EARLY_SUSPEND 0 + +/* 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" +#else +#define CFG_FW_FILENAME "WIFI_RAM_CODE" +#endif + +#ifndef CFG_MET_PACKET_TRACE_SUPPORT +#define CFG_MET_PACKET_TRACE_SUPPORT 0 /*move to wlan/MAKEFILE */ +#endif + +/*------------------------------------------------------------------------------ + * Driver config + *------------------------------------------------------------------------------ + */ + +#ifndef LINUX +#define CFG_SUPPORT_CFG_FILE 0 +#else +#define CFG_SUPPORT_CFG_FILE 1 +#endif + +#define CFG_SUPPORT_802_11D 1 /* + * !< 1(default): Enable 802.11d + * 0: Disable + */ + +#define CFG_SUPPORT_RRM 0 /* Radio Reasource Measurement (802.11k) */ +#define CFG_SUPPORT_DFS 1 /* DFS (802.11h) */ + +#if (CFG_SUPPORT_DFS == 1) /* Add by Enlai */ +#define CFG_SUPPORT_QUIET 0 /* Quiet (802.11h) */ +#define CFG_SUPPORT_SPEC_MGMT 1 /* Spectrum Management (802.11h): TPC and DFS */ +#else +#define CFG_SUPPORT_QUIET 0 /* Quiet (802.11h) */ +#define CFG_SUPPORT_SPEC_MGMT 0 /* Spectrum Management (802.11h): TPC and DFS */ +#endif + +#define CFG_SUPPORT_RX_RDG 0 /* 11n feature. RX RDG capability */ +#define CFG_SUPPORT_MFB 0 /* 802.11n MCS Feedback responder */ +#define CFG_SUPPORT_RX_STBC 1 /* 802.11n RX STBC (1SS) */ +#define CFG_SUPPORT_RX_SGI 1 /* 802.11n RX short GI for both 20M and 40M BW */ +#define CFG_SUPPORT_RX_HT_GF 1 /* 802.11n RX HT green-field capability */ +#define CFG_SUPPORT_BFEE 1 +#define CFG_SUPPORT_WAPI 1 +#define CFG_SUPPORT_FCC_DYNAMIC_TX_PWR_ADJUST 0 /* Support FCC/CE Dynamic Tx Power Adjust */ + +/* Enable QA Tool Support */ +#define CFG_SUPPORT_QA_TOOL 1 + +/* Enable TX BF Support */ +#define CFG_SUPPORT_TX_BF 1 + +/* Enable MU MIMO Support */ +#define CFG_SUPPORT_MU_MIMO 1 + +#define CFG_SUPPORT_BUFFER_MODE 1 + +#define CFG_SUPPORT_LOWLATENCY_MODE 1 + +#define CFG_SUPPORT_ANT_SWAP 1 + +#define CFG_SUPPORT_OSHARE 1 + +/*------------------------------------------------------------------------------ + * 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_NATIVE_802_11 0 +#define CFG_TX_MAX_PKT_SIZE 1600 +#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 + +#endif + +#define CFG_BSS_DISAPPEAR_THRESOLD 20 /*unit: sec */ +#define CFG_MAX_NUM_OF_CHNL_INFO 50 +#define CFG_SELECT_BSS_BASE_ON_RSSI 0 + +/* 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 + *------------------------------------------------------------------------------ + */ +/* + * 1(default): Enable SDIO ISR & TX/RX status enhance mode + * 0: Disable + */ +#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: Enable SDIO TX enhance mode(Multiple frames in single BLOCK CMD) + * 0(default): Disable + */ +#define CFG_SDIO_TX_AGG 1 + +/* + * !< 0: Disable this limitation + * Others: Byte count limitation for a single SDIO write + */ +#define CFG_SDIO_TX_AGG_LIMIT 0 + +/* + * 1: Enable SDIO RX enhance mode(Multiple frames in single BLOCK CMD) + * 0(default): Disable + */ +#define CFG_SDIO_RX_AGG 1 + +#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 /* + * !< Setting the maximum RX aggregation number + * 0: no limited (16) + */ + +#ifdef WINDOWS_CE +#define CFG_SDIO_PATHRU_MODE 1 /* + * !< 1: Support pass through (PATHRU) mode + * 0: Disable + */ +#else +#define CFG_SDIO_PATHRU_MODE 0 /*!< 0: Always disable if WINDOWS_CE is not defined */ +#endif + +#define CFG_MAX_RX_ENHANCE_LOOP_COUNT 3 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Integration + *------------------------------------------------------------------------------ + */ +#define CFG_MULTI_ECOVER_SUPPORT 1 + +#define CFG_ENABLE_CAL_LOG 1 +#define CFG_REPORT_RFBB_VERSION 1 + +#define HW_BSSID_NUM 4 /* HW BSSID number by chip */ + +#define CFG_CHIP_RESET_SUPPORT 1 + +/*------------------------------------------------------------------------------ + * Flags for workaround + *------------------------------------------------------------------------------ + */ + +/*------------------------------------------------------------------------------ + * 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 */ + +/* Max Tx page count */ +#define CFG_MAX_TX_PAGE_COUNT 968 + +#if defined(MT6631) +#define MY_SDIO_BLOCK_SIZE 512 /* it must be less than or eaqual to 512 */ +/* should align the value to block size boundary for block mode transaction */ +#if CFG_SDIO_TX_AGG || CFG_TX_BUFFER_IS_SCATTER_LIST +#define CFG_COALESCING_BUFFER_SIZE ((NIC_TX_PAGE_SIZE * CFG_MAX_TX_PAGE_COUNT \ + + MY_SDIO_BLOCK_SIZE - 1) / MY_SDIO_BLOCK_SIZE * MY_SDIO_BLOCK_SIZE) +#else +#define CFG_COALESCING_BUFFER_SIZE ((CFG_TX_MAX_PKT_SIZE \ + + MY_SDIO_BLOCK_SIZE - 1) / MY_SDIO_BLOCK_SIZE * MY_SDIO_BLOCK_SIZE) +#endif /* CFG_SDIO_TX_AGG || CFG_TX_BUFFER_IS_SCATTER_LIST */ +#else +#if CFG_SDIO_TX_AGG || CFG_TX_BUFFER_IS_SCATTER_LIST +#define CFG_COALESCING_BUFFER_SIZE (NIC_TX_PAGE_SIZE * CFG_MAX_TX_PAGE_COUNT) +#else +#define CFG_COALESCING_BUFFER_SIZE (CFG_TX_MAX_PKT_SIZE) +#endif /* CFG_SDIO_TX_AGG || CFG_TX_BUFFER_IS_SCATTER_LIST */ +#endif +/*------------------------------------------------------------------------------ + * Flags and Parameters for TX path + *------------------------------------------------------------------------------ + */ + +/*! Maximum number of SW TX packet queue */ +#define CFG_TX_MAX_PKT_NUM 1024 + +/*! 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 27 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for RX path + *------------------------------------------------------------------------------ + */ + +/*------------------------------------------------------------------------------ +* CONFIG_TITLE : Move BA from FW to Driver +* OWNER : Puff Wen +* Description : Move BA from FW to Driver +*------------------------------------------------------------------------------ +*/ +#define CFG_M0VE_BA_TO_DRIVER 0 + +/*! 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 + +/*! Maximum buffer hold by QM, it should cover below two scenarios: + * + * - RX_PKT_DESTINATION_HOST + * the maximum packets queued in reordering buffer (consider all BA sessions concurrency): + * CFG_NUM_OF_RX_BA_AGREEMENTS * (WinSize - 1) = 8 * 67 = 536 + * + * - RX_PKT_DESTINATION_FORWARD + * the maximum packets queued in reordering buffer (consider two BA sessions concurrency for TGn AP 4.2.25) + * + + * the maximum pending forwarding count queued in TxQue (since the SwRfb consumed + * by forwarding frame will be freed in hif_thread until the corresponding MSDU is sent out, + * this may be blocked by hif_thread receiving procedure, we should reserve buffer here): + * 2 * (WinSize - 1) + QM_FWD_PKT_QUE_HIGH_THRESHOLD = 2 * 67 + 512 = 646 + * + */ +#define CFG_NUM_OF_QM_RX_PKT_NUM 646 + +/*! Maximum number of concurrent bubble timeout event */ +#define CFG_NUM_OF_BUBBLE_TIMEOUT_EVENT 1 + +/*! 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 */ +/* TODO: it should be 4096 under emulation mode */ +#define CFG_RX_MAX_PKT_SIZE (28 + 2312 + 12 /* HIF_RX_HEADER_T */) + +/*! 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 defined(MT6631) +/* should align the value to block size boundary for block mode transaction */ +#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 \ + + MY_SDIO_BLOCK_SIZE - 1) / MY_SDIO_BLOCK_SIZE * MY_SDIO_BLOCK_SIZE) +#else +#define CFG_RX_COALESCING_BUFFER_SIZE ((CFG_RX_MAX_PKT_SIZE \ + + MY_SDIO_BLOCK_SIZE - 1) / MY_SDIO_BLOCK_SIZE * MY_SDIO_BLOCK_SIZE) +#endif +#else +#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 +#endif + +/*! RX BA capability */ +/* Each STA needs 8 TID; Hotspot supports 10 Clients */ +#define CFG_NUM_OF_RX_BA_AGREEMENTS 80 +#if CFG_M0VE_BA_TO_DRIVER +#define CFG_RX_BA_MAX_WINSIZE 8 +#else +#define CFG_RX_BA_MAX_WINSIZE 16 +#endif +#define CFG_RX_BA_INC_SIZE 4 +#define CFG_RX_MAX_BA_TID_NUM 8 +#define CFG_RX_REORDERING_ENABLED 1 + +#define CFG_PF_ARP_NS_MAX_NUM 3 +#define CFG_RX_BA_REORDERING_ENHANCEMENT 1 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for CMD/RESPONSE + *------------------------------------------------------------------------------ + */ +#define CFG_RESPONSE_POLLING_TIMEOUT 105 +#define CFG_RESPONSE_CLEAR_RDY_TIMEOUT 100 +#define CFG_MCU_POWER_OFF_POLLING_CNT 5 +#define CFG_MCU_POWER_OFF_MAGIC_CODE 0xa0000001 +#define CFG_MCU_POWER_OFF_MAILBOX_INDEX 0x1 +#define CFG_MCU_POWER_OFF_SOFTINT_BIT 16 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Protocol Stack + *------------------------------------------------------------------------------ + */ +/*! Maximum number of BSS in the SCAN list */ +#define CFG_MAX_NUM_BSS_LIST 128 + +#define CFG_MAX_NUM_ROAM_BSS_LIST 64 + +#define CFG_MAX_COMMON_IE_BUF_LEN ((1500 * CFG_MAX_NUM_BSS_LIST) / 3) + +/*! Maximum size of Header buffer of each SCAN record */ +#define CFG_RAW_BUFFER_SIZE 1024 + +/*! Maximum size of IE buffer of each SCAN record */ +#define CFG_IE_BUFFER_SIZE 512 + +/*! Maximum number of STA records */ +#define CFG_MAX_NUM_STA_RECORD 32 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Power management + *------------------------------------------------------------------------------ + */ +#define CFG_ENABLE_FULL_PM 1 +#define CFG_ENABLE_WAKEUP_ON_LAN 0 +#define CFG_SUPPORT_WAKEUP_REASON_DEBUG 0 /* debug which packet wake up host */ + +#define CFG_MODIFY_TX_POWER_BY_BAT_VOLT 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 +/*------------------------------------------------------------------------------ + * Flags 1: drop all multicast packets when device suspend + * Flags 0: drop multicast packets except white list when device suspend + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_DROP_ALL_MC_PACKET 0 + +/*------------------------------------------------------------------------------ + * SAR table size. + *------------------------------------------------------------------------------ + */ +#define CFG_MAX_SAR_TABLE_SIZE 16 + +/*------------------------------------------------------------------------------ + * 802.11i RSN Pre-authentication PMKID cahce maximun number + *------------------------------------------------------------------------------ + */ +#define CFG_MAX_PMKID_CACHE 16 /* + * !< max number of PMKID cache + * 16(default) : The Max PMKID cache + */ +/*------------------------------------------------------------------------------ + * Auto Channel Selection maximun channel number + *------------------------------------------------------------------------------ + */ +#define MAX_CHN_NUM 39 /* CH1~CH14, CH36~CH48, CH52~CH64, CH100~CH144, CH149~CH165 */ +#define MAX_2G_BAND_CHN_NUM 14 +#define ACS_PRINT_BUFFER_LEN 200 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Ad-Hoc + *------------------------------------------------------------------------------ + */ +#define CFG_INIT_ADHOC_FREQ (2462000) +#define CFG_INIT_ADHOC_MODE AD_HOC_MODE_MIXED_11BG +#define CFG_INIT_ADHOC_BEACON_INTERVAL (100) +#define CFG_INIT_ADHOC_ATIM_WINDOW (0) + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Maximum Scan SSID number + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_SCHED_SCN_SSID_SETS 1 /* Sched Scan support hidden SSID */ +#if CFG_SUPPORT_SCHED_SCN_SSID_SETS +#define CFG_SCAN_HIDDEN_SSID_MAX_NUM (7) +#endif +#define CFG_SCAN_SSID_MAX_NUM (10) +#define CFG_SCAN_SSID_MATCH_MAX_NUM (16) + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Support Management Frame Debug + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_MGMT_FRAME_DEBUG 1 + +/*------------------------------------------------------------------------------ + * 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 32 +#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_RX_PKTS_DUMP 0 + +#define CFG_SUPPORT_STATISTICS 1 +#define CFG_SUPPORT_DEBUG_STATISTICS 0 + +#define CFG_FORCE_USE_20BW 0 + +#define CFG_SUPPORT_TRACE_TC4 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 + +#define CFG_ENABLE_FW_DIVIDED_DOWNLOAD 1 + +/* Vary between projects, already replaced by device tree */ +/* default value is for MT6630 */ +#define CFG_FW_LOAD_ADDRESS 0x00091400 +#define CFG_OVERRIDE_FW_START_ADDRESS 0 +#define CFG_FW_START_ADDRESS 0x00091400 + +/*------------------------------------------------------------------------------ + * 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_LIMIT_AIS_CHNL 1 + +#define CFG_BOW_SUPPORT_11N 1 + +#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 1 /*!< 0(default): Disable 802.11W */ +#endif +#else +#define CFG_ENABLE_WIFI_DIRECT 0 +#define CFG_SUPPORT_802_11W 0 /* Not support at WinXP */ +#endif + +#define CFG_SUPPORT_PERSISTENT_GROUP 0 + +#define CFG_TEST_WIFI_DIRECT_GO 0 + +#define CFG_TEST_ANDROID_DIRECT_GO 0 + +#define CFG_UNITEST_P2P 0 + +/* + * Enable cfg80211 option after Android 2.2(Froyo) is suggested, + * cfg80211 on linux 2.6.29 is not mature yet + */ +#define CFG_ENABLE_WIFI_DIRECT_CFG_80211 1 + +#define CFG_SUPPORT_HOTSPOT_OPTIMIZATION 0 +#define CFG_HOTSPOT_OPTIMIZATION_BEACON_INTERVAL 300 +#define CFG_HOTSPOT_OPTIMIZATION_DTIM 1 + +#define CFG_AUTO_CHANNEL_SEL_SUPPORT 1 + +#define CFG_SUPPORT_SOFTAP_WPA3 1 + + +#define CFG_SAP_LIMIT_AIS_CHNL 0 /* Restrict AIS operation channel in STA+SAP concurrent mode */ + +/*------------------------------------------------------------------------------ + * 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 500 + +/*------------------------------------------------------------------------------ + * Migration Option + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_ADHOC 1 +#define CFG_SUPPORT_AAA 1 + +#define CFG_SUPPORT_BCM 0 +#define CFG_SUPPORT_BCM_BWCS 0 +#define CFG_SUPPORT_BCM_BWCS_DEBUG 0 + +#define CFG_SUPPORT_RDD_TEST_MODE 0 + +#define CFG_SUPPORT_PWR_MGT 1 + +#define CFG_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_PNO 1 +#define CFG_SUPPORT_TDLS 1 + +#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_ROAMING_CTRL_BY_SUSPEND 0 +#define CFG_SUPPORT_SWCR 1 + +#define CFG_SUPPORT_ANTI_PIRACY 1 + +#define CFG_SUPPORT_OSC_SETTING 1 + +#define CFG_SUPPORT_P2P_RSSI_QUERY 0 + +#define CFG_SUPPORT_RSSI_DISCONNECT 1 + +#define CFG_SHOW_MACADDR_SOURCE 1 +#define CFG_SUPPORT_VO_ENTERPRISE 1 +#define CFG_SUPPORT_WMM_AC 1 +#if CFG_SUPPORT_VO_ENTERPRISE +#define CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT 1 +#define CFG_SUPPORT_802_11R 1 +#define CFG_SUPPORT_802_11V 1 +#define CFG_SUPPORT_802_11K 1 +#else +#define CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT 0 +#define CFG_SUPPORT_802_11R 0 +#define CFG_SUPPORT_802_11V 0 +#define CFG_SUPPORT_802_11K 0 +#endif +#define CFG_SUPPORT_OKC 1 + +#define CFG_SUPPORT_802_11V_TIMING_MEASUREMENT 0 +#if (CFG_SUPPORT_802_11V_TIMING_MEASUREMENT == 1 || CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT == 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 + +#define WNM_UNIT_TEST CFG_SUPPORT_802_11V +#define CFG_DRIVER_COMPOSE_ASSOC_REQ 1 +#define CFG_SUPPORT_802_11AC 1 +#define CFG_STRICT_CHECK_CAPINFO_PRIVACY 0 + +#define CFG_SUPPORT_WFD 1 +#define CFG_SUPPORT_WFD_COMPOSE_IE 1 + +#define CFG_SUPPORT_HOTSPOT_WPS_MANAGER 1 +#define CFG_SUPPORT_NFC_BEAM_PLUS 1 + +/* Refer to CONFIG_MTK_STAGE_SCAN */ +#define CFG_MTK_STAGE_SCAN 1 + +#define CFG_SUPPORT_MULTITHREAD 1 /* Enable driver support multicore */ + +#define CFG_SUPPORT_MTK_SYNERGY 1 + +#define CFG_SUPPORT_PWR_LIMIT_COUNTRY 1 + +#define CFG_SUPPORT_RN 1 +/*------------------------------------------------------------------------------ + * Flags of bus error tolerance + *------------------------------------------------------------------------------ + */ +#define CFG_FORCE_RESET_UNDER_BUS_ERROR 0 + +/*------------------------------------------------------------------------------ + * Build Date Code Integration + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_BUILD_DATE_CODE 0 + +/*------------------------------------------------------------------------------ + * Flags of SDIO test pattern support + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_SDIO_READ_WRITE_PATTERN 1 + +/*------------------------------------------------------------------------------ + * Flags of AIS passive scan support + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_AIS_PASSIVE_SCAN 0 + +/*------------------------------------------------------------------------------ + * Flags of 5G NVRAM SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_NVRAM_5G 1 + +/*------------------------------------------------------------------------------ + * Flags of Packet Lifetime Profiling Mechanism + *------------------------------------------------------------------------------ + */ +#define CFG_ENABLE_PKT_LIFETIME_PROFILE 1 +#define CFG_PRINT_PKT_LIFETIME_PROFILE 0 + +#define CFG_ENABLE_PER_STA_STATISTICS 1 + +/*------------------------------------------------------------------------------ + * Flags for prepare the FW compile flag + *------------------------------------------------------------------------------ + */ +#define COMPILE_FLAG0_GET_STA_LINK_STATUS (1<<0) +#define COMPILE_FLAG0_WFD_ENHANCEMENT_PROTECT (1<<1) + +/*------------------------------------------------------------------------------ + * Flags of Batch Scan SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_BATCH_SCAN 1 +#define CFG_BATCH_MAX_MSCAN 4 + +/*------------------------------------------------------------------------------ + * Flags of G-Scan SUPPORT and P-SCN SUPPORT, GSCN is one type of PSCN + *------------------------------------------------------------------------------ + */ + +#define CFG_SUPPORT_SCN_PSCN 1 + +#if CFG_SUPPORT_SCN_PSCN +#define CFG_SUPPORT_GSCN 0 /* GSCN not ready disabled here */ +#else +#define CFG_SUPPORT_GSCN 0 +#endif + +/*------------------------------------------------------------------------------ + * Flags of Sniffer SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_SNIFFER 1 + +#define CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE 1 + +#define CFG_IGNORE_INVALID_AUTH_TSN 0 + +/*------------------------------------------------------------------------------ + * Flags of Drop Packet Replay SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_REPLAY_DETECTION 1 + +/*------------------------------------------------------------------------------ + * Flags of driver delay calibration atfer efuse buffer mode CMD + *------------------------------------------------------------------------------ + */ + +#define CFG_EFUSE_BUFFER_MODE_DELAY_CAL 1 + + +/*------------------------------------------------------------------------------ + * Flags of driver EEPROM pages for QA tool + *------------------------------------------------------------------------------ + */ + +#define CFG_EEPROM_PAGE_ACCESS 0 + +#define CFG_FORCE_ENABLE_PERF_MONITOR 0 +/*------------------------------------------------------------------------------ + * Flags of driver support PCC feature + *------------------------------------------------------------------------------ + */ + +#define CFG_SUPPORT_PCC 1 + +/*------------------------------------------------------------------------------ + * Flags of driver support driver abort scan feature + *------------------------------------------------------------------------------ + */ + +#define CFG_SUPPORT_ABORT_SCAN 1 + +#define CFG_SUPPORT_REPORT_MISC 0 + +/*------------------------------------------------------------------------------ + * Flags of driver support scan random mac + *------------------------------------------------------------------------------ + */ +#if defined(MT6631) +#define CFG_SUPPORT_SCAN_RANDOM_MAC 1 +#else +#define CFG_SUPPORT_SCAN_RANDOM_MAC 0 +#endif +/*------------------------------------------------------------------------------ + * Need FW support + * If FW can support, then driver enables it. + *------------------------------------------------------------------------------ + */ +/* +#if defined(__LP64__) || defined(LP64) +#if defined(MT6631) +#define CFG_SUPPORT_DATA_STALL +#define CFG_SUPPORT_LINK_QUALITY_MONITOR +#endif +#endif +*/ +/*------------------------------------------------------------------------------ + * Link Quality Monitor + * Link quality monitor execution period base on performance monitor timer + *------------------------------------------------------------------------------ + */ +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR +#define CFG_LINK_QUALITY_MONITOR_UPDATE_INTERVAL 1000 +#endif +#ifdef FW_CFG_SUPPORT +#define CFG_SUPPORT_COEX_IOT_AP +#endif +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _CONFIG_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/debug.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/debug.h new file mode 100644 index 0000000000000..2b68a8be6dd8c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/debug.h @@ -0,0 +1,422 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/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. + */ + +#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 + +#define DBG_DISABLE_ALL_LOG 0 + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_typedef.h" + +extern UINT_8 aucDebugModule[]; +#ifdef CONFIG_LOG_TOO_MUCH_WARNING +extern void set_logtoomuch_enable(int value); +extern int get_logtoomuch_enable(void); +#endif +/******************************************************************************* +* 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) +#define DBG_LOG_LEVEL_OFF (DBG_CLASS_ERROR | DBG_CLASS_WARN | DBG_CLASS_INFO | DBG_CLASS_STATE) +#define DBG_LOG_LEVEL_DEFAULT (DBG_LOG_LEVEL_OFF | DBG_CLASS_EVENT | DBG_CLASS_TRACE) +#define DBG_LOG_LEVEL_EXTREME (DBG_LOG_LEVEL_DEFAULT | DBG_CLASS_LOUD | DBG_CLASS_TEMP) + + +#if defined(LINUX) +#define DBG_PRINTF_64BIT_DEC "lld" +#else /* Windows */ +#define DBG_PRINTF_64BIT_DEC "I64d" +#endif + +#define DBG_ALL_MODULE_IDX 0xFFFFFFFF + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Define debug module index */ +typedef enum _ENUM_DBG_MODULE_T { + DBG_INIT_IDX = 0, /* 0x00 */ /* For driver initial */ + DBG_HAL_IDX, /* 0x01 */ /* For HAL(HW) Layer */ + DBG_INTR_IDX, /* 0x02 */ /* For Interrupt */ + DBG_REQ_IDX, /* 0x03 */ + DBG_TX_IDX, /* 0x04 */ + DBG_RX_IDX, /* 0x05 */ + DBG_RFTEST_IDX, /* 0x06 */ /* For RF test mode */ + DBG_EMU_IDX, /* 0x07 */ /* Developer specific */ + + DBG_SW1_IDX, /* 0x08 */ /* Developer specific */ + DBG_SW2_IDX, /* 0x09 */ /* Developer specific */ + DBG_SW3_IDX, /* 0x0A */ /* Developer specific */ + DBG_SW4_IDX, /* 0x0B */ /* Developer specific */ + + DBG_HEM_IDX, /* 0x0C */ /* HEM */ + DBG_AIS_IDX, /* 0x0D */ /* AIS */ + DBG_RLM_IDX, /* 0x0E */ /* RLM */ + DBG_MEM_IDX, /* 0x0F */ /* RLM */ + DBG_CNM_IDX, /* 0x10 */ /* CNM */ + DBG_RSN_IDX, /* 0x11 */ /* RSN */ + DBG_BSS_IDX, /* 0x12 */ /* BSS */ + DBG_SCN_IDX, /* 0x13 */ /* SCN */ + DBG_SAA_IDX, /* 0x14 */ /* SAA */ + DBG_AAA_IDX, /* 0x15 */ /* AAA */ + DBG_P2P_IDX, /* 0x16 */ /* P2P */ + DBG_QM_IDX, /* 0x17 */ /* QUE_MGT */ + DBG_SEC_IDX, /* 0x18 */ /* SEC */ + DBG_BOW_IDX, /* 0x19 */ /* BOW */ + DBG_WAPI_IDX, /* 0x1A */ /* WAPI */ + DBG_ROAMING_IDX, /* 0x1B */ /* ROAMING */ + DBG_TDLS_IDX, /* 0x1C */ /* TDLS */ /* CFG_SUPPORT_TDLS */ + DBG_OID_IDX, + DBG_HS20_IDX, /* 0x1E */ /* HotSpot 2.0 */ + DBG_NIC_IDX, + DBG_WNM_IDX, + DBG_WMM_IDX, + DBG_MODULE_NUM /* Notice the XLOG check */ +} ENUM_DBG_MODULE_T; + +#if (CFG_SUPPORT_DEBUG_STATISTICS == 1) +enum PKT_TYPE { + PKT_RX, + PKT_TX, + PKT_TX_DONE +}; +#endif + +enum PKT_PHASE { + PHASE_XMIT_RCV, + PHASE_ENQ_QM, + PHASE_HIF_TX, +}; + +struct WLAN_DEBUG_INFO { + BOOLEAN fgVoE5_7Test:1; + BOOLEAN fgReserved:7; +}; + +enum DRV_STATUS_T { + UNSOL_BTM_REQ, + SOL_BTM_REQ, + NEIGHBOR_AP_REP, + SND_BTM_RSP, + CONNECT_AP, + JOIN_FAIL, + DISCONNECT_AP, + BEACON_TIMEOUT, + RCV_FW_ROAMING, + ROAMING_SCAN_START, + ROAMING_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 +******************************************************************************** +*/ +/* Debug print format string for the OS system time */ +#define OS_SYSTIME_DBG_FORMAT "0x%08x" + +/* Debug print argument for the OS system time */ +#define OS_SYSTIME_DBG_ARGUMENT(systime) (systime) + +/* Debug print format string for the MAC Address */ +#define MACSTR "%pM" +/* "%02x:%02x:%02x:%02x:%02x:%02x" */ + +/* Debug print argument for the MAC Address */ +#define MAC2STR(a) a +/* ((PUINT_8)a)[0], ((PUINT_8)a)[1], ((PUINT_8)a)[2], ((PUINT_8)a)[3], ((PUINT_8)a)[4], ((PUINT_8)a)[5] */ + +/* Debug print format string for the IPv4 Address */ +#define IPV4STR "%pI4" +/* "%u.%u.%u.%u" */ + +/* Debug print argument for the IPv4 Address */ +#define IPV4TOSTR(a) a +/* ((PUINT_8)a)[0], ((PUINT_8)a)[1], ((PUINT_8)a)[2], ((PUINT_8)a)[3] */ + +/* Debug print format string for the MAC Address */ +#define IPV6STR "%pI6" +/* "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x" */ + +/* Debug print argument for the MAC Address */ +#define IPV6TOSTR(a) a +/* + * ((PUINT_8)a)[0], ((PUINT_8)a)[1], ((PUINT_8)a)[2], ((PUINT_8)a)[3], \ + * ((PUINT_8)a)[4], ((PUINT_8)a)[5], ((PUINT_8)a)[6], ((PUINT_8)a)[7], \ + * ((PUINT_8)a)[8], ((PUINT_8)a)[9], ((PUINT_8)a)[10], ((PUINT_8)a)[11], \ + * ((PUINT_8)a)[12], ((PUINT_8)a)[13], ((PUINT_8)a)[14], ((PUINT_8)a)[15] + */ + +/* 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 kalPrint +#define LOG_FUNC_LIMITED kalPrintLimited + +/* If __FUNCTION__ is already defined by compiler, we just use it. */ +#define DEBUGFUNC(_Func) +/* + * Disabled due to AOSP + * #if defined(__FUNCTION__) + * #define DEBUGFUNC(_Func) + * #else + * #define DEBUGFUNC(_Func) static const char __FUNCTION__[] = _Func; + * #endif + */ + +#if DBG_DISABLE_ALL_LOG +#define DBGLOG(_Module, _Class, _Fmt) +#define DBGLOG_LIMITED(_Module, _Class, _Fmt) +#define DBGLOG_MEM8(_Module, _Class, _StartAddr, _Length) +#define DBGLOG_MEM32(_Module, _Class, _StartAddr, _Length) +#else +#define DBGLOG(_Module, _Class, _Fmt, ...) \ + do { \ + if ((aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) == 0) \ + break; \ + LOG_FUNC("%s:(" #_Module " " #_Class ") " _Fmt, __func__, ##__VA_ARGS__); \ + } while (0) + +#define DBGLOG_LIMITED(_Module, _Class, _Fmt, ...) \ + do { \ + if ((aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) == 0) \ + break; \ + LOG_FUNC_LIMITED("%s:(" #_Module " " #_Class ") " _Fmt, __func__, ##__VA_ARGS__); \ + } while (0) + +#define TOOL_PRINTLOG(_Module, _Class, _Fmt, ...) \ + do { \ + if ((aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) == 0) \ + break; \ + LOG_FUNC(_Fmt, ##__VA_ARGS__); \ + } while (0) + +#define DBGLOG_MEM8(_Module, _Class, _StartAddr, _Length) \ + do { \ + if (aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) { \ + LOG_FUNC("%s:(" #_Module " " #_Class ")\n", __func__); \ + dumpMemory8((PUINT_8)(_StartAddr), (UINT_32)(_Length)); \ + } \ + } while (0) + +#define DBGLOG_MEM32(_Module, _Class, _StartAddr, _Length) \ + do { \ + if (aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) { \ + LOG_FUNC("%s:(" #_Module " " #_Class ")\n", __func__); \ + dumpMemory32((PUINT_32)(_StartAddr), (UINT_32)(_Length)); \ + } \ + } while (0) +#endif + +#define DISP_STRING(_str) _str + +#undef ASSERT +#undef ASSERT_REPORT + +#if (BUILD_QA_DBG || DBG) +#ifdef _lint +#define ASSERT_NOMEM() +#define ASSERT(_exp) \ + do { \ + if (!(_exp)) { \ + do {} while (1); \ + } \ + } while (0) + +#define ASSERT_REPORT(_exp, _fmt) \ + do { \ + LOG_FUNC("Assertion failed: %s:%d (%s)\n", __FILE__, __LINE__, #_exp); \ + LOG_FUNC(_fmt); \ + if (!(_exp)) { \ + do {} while (1); \ + } \ + } while (0) +#elif defined(WINDOWS_CE) +#define ASSERT_NOMEM() +#define UNICODE_TEXT(_msg) TEXT(_msg) +#define ASSERT(_exp) \ + do { \ + if (!(_exp)) { \ + 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); \ + } \ + } while (0) + +#define ASSERT_REPORT(_exp, _fmt) \ + do { \ + if (!(_exp)) { \ + 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); \ + } \ + } while (0) +#else +#define ASSERT_NOMEM() \ + do { \ + LOG_FUNC("Alloate memory failed at %s:%d\n", __FILE__, __LINE__); \ + kalSendAeeWarning("Wlan_Gen3 No Mem", "Memory Alloate Failed %s:%d",\ + __FILE__, __LINE__); \ + } while (0) + +#define ASSERT(_exp) \ + do { \ + if (!(_exp)) { \ + LOG_FUNC("Assertion failed: %s:%d (%s)\n", __FILE__, __LINE__, #_exp); \ + kalBreakPoint(); \ + } \ + } while (0) + +#define ASSERT_REPORT(_exp, _fmt) \ + do { \ + if (!(_exp)) { \ + LOG_FUNC("Assertion failed: %s:%d (%s)\n", __FILE__, __LINE__, #_exp); \ + LOG_FUNC(_fmt); \ + kalBreakPoint(); \ + } \ + } while (0) +#endif /* WINDOWS_CE */ +#else +#define ASSERT_NOMEM() +#define ASSERT(_exp) \ + do { \ + if (!(_exp)) { \ + LOG_FUNC("Assertion failed: %s:%d (%s)\n", __FILE__, __LINE__, #_exp); \ + } \ + } while (0) + +#define ASSERT_REPORT(_exp, _fmt) +#endif /* BUILD_QA_DBG */ + +#define ASSERT_BREAK(_exp) \ +{ \ + if (!(_exp)) { \ + ASSERT(FALSE); \ + break; \ + } \ +} +/* The following macro is used for debugging packed structures. */ +#ifndef DATA_STRUCT_INSPECTING_ASSERT +#define DATA_STRUCT_INSPECTING_ASSERT(expr) \ +{ \ + switch (0) {case 0: case (expr): default:; } \ +} +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +VOID dumpMemory8(IN PUINT_8 pucStartAddr, IN UINT_32 u4Length); + +VOID dumpMemory32(IN PUINT_32 pu4StartAddr, IN UINT_32 u4Length); + +VOID wlanPrintFwLog(PUINT_8 pucLogContent, UINT_16 u2MsgSize, UINT_8 ucMsgType); + +VOID wlanFillTimestamp(P_ADAPTER_T prAdapter, PVOID pvPacket, UINT_8 ucPhase); +VOID wlanDbgLogLevelInit(VOID); +VOID wlanDbgLogLevelUninit(VOID); +UINT_32 wlanDbgLevelUiSupport(IN P_ADAPTER_T prAdapter, UINT_32 u4Version, UINT_32 ucModule); +UINT_32 wlanDbgGetLogLevelImpl(IN P_ADAPTER_T prAdapter, UINT_32 u4Version, UINT_32 ucModule); +VOID wlanDbgSetLogLevelImpl(IN P_ADAPTER_T prAdapter, UINT_32 u4Version, + UINT_32 u4Module, UINT_32 u4level); +VOID wlanDbgLevelSync(VOID); +BOOLEAN wlanDbgGetGlobalLogLevel(UINT_32 u4Module, UINT_32 *pu4Level); +BOOLEAN wlanDbgSetGlobalLogLevel(UINT_32 u4Module, UINT_32 u4Level); + +#if CFG_SUPPORT_MGMT_FRAME_DEBUG +VOID wlanMgmtFrameDebugReset(VOID); +VOID wlanMgmtFrameDebugAdd(IN PUINT_8 pucStartAddr, IN UINT_32 u4Length); +VOID wlanMgmtFrameDebugDump(VOID); +#endif + +VOID glNotifyDrvStatus(enum DRV_STATUS_T eDrvStatus, PVOID pvInfo); + +VOID wlanDebugTC4AndPktInit(VOID); +VOID wlanDebugTC4AndPktUninit(VOID); +#if (CFG_SUPPORT_DEBUG_STATISTICS == 1) +VOID wlanPktStatusDebugDumpInfo(P_ADAPTER_T prAdapter); +VOID wlanPktStatusDebugTraceInfoARP(UINT_8 status, UINT_8 eventType, UINT_16 u2ArpOpCode, PUINT_8 pucPkt); +VOID wlanPktStatusDebugTraceInfoIP(UINT_8 status, UINT_8 eventType, UINT_8 ucIpProto, UINT_16 u2IpId + , PUINT_8 pucPkt); +VOID wlanPktStatusDebugTraceInfo(UINT_8 status, UINT_8 eventType + , UINT_16 u2EtherType, UINT_8 ucIpProto, UINT_16 u2IpId, UINT_16 u2ArpOpCode, PUINT_8 pucPkt); +#endif +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _DEBUG_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/fwcfg.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/fwcfg.h new file mode 100644 index 0000000000000..737f3c92aef88 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/fwcfg.h @@ -0,0 +1,142 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _FWCFG_H +#define _FWCFG_H +#include "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 +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#ifdef FW_CFG_SUPPORT +#define MAX_CMD_ITEM_MAX 4 +#define MAX_CMD_NAME_MAX_LENGTH 32 +#define MAX_CMD_VALUE_MAX_LENGTH 32 + +#define MAX_CMD_TYPE_LENGTH 1 +#define MAX_CMD_RESERVE_LENGTH 1 +#define MAX_CMD_STRING_LENGTH 1 +#define MAX_CMD_VALUE_LENGTH 1 + +#define CMD_FORMAT_V1_LENGTH (MAX_CMD_NAME_MAX_LENGTH + \ + MAX_CMD_VALUE_MAX_LENGTH + MAX_CMD_TYPE_LENGTH + \ + MAX_CMD_STRING_LENGTH + MAX_CMD_VALUE_LENGTH + MAX_CMD_RESERVE_LENGTH) + +#define MAX_CMD_BUFFER_LENGTH (CMD_FORMAT_V1_LENGTH * MAX_CMD_ITEM_MAX) + +#define FW_CFG_FILE "/vendor/firmware/wifi_fw.cfg" +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +enum _CMD_VER_T { + CMD_VER_1, + CMD_VER_1_EXT +}; + +enum _CMD_TYPE_T { + CMD_TYPE_QUERY, + CMD_TYPE_SET +}; + +struct _CMD_FORMAT_V1_T { + UINT_8 itemType; + UINT_8 itemStringLength; + UINT_8 itemValueLength; + UINT_8 Reserved; + UINT_8 itemString[MAX_CMD_NAME_MAX_LENGTH]; + UINT_8 itemValue[MAX_CMD_VALUE_MAX_LENGTH]; +}; + +struct _CMD_HEADER_T { + enum _CMD_VER_T cmdVersion; + enum _CMD_TYPE_T cmdType; + UINT_8 itemNum; + UINT_16 cmdBufferLen; + UINT_8 buffer[MAX_CMD_BUFFER_LENGTH]; +}; + +struct WLAN_CFG_PARSE_STATE_S { + CHAR *ptr; + CHAR *text; + INT_32 nexttoken; + UINT_32 maxSize; +}; + +struct _FW_CFG { + PUINT_8 key; + PUINT_8 value; +}; +#ifdef CFG_SUPPORT_COEX_IOT_AP +#define COEX_ISSUE_TYPE_ID 1 +struct FwCfgForIotAP { + UINT_8 ucIotType; + UINT_8 aucIotApMacAddr[MAC_ADDR_LEN]; + UINT_8 ucMacAddrMask[MAC_ADDR_LEN]; + PUINT_8 aucEnableCmdString; + PUINT_8 aucDisableCmdString; +}; +#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 +******************************************************************************** +*/ + +INT_32 getFwCfgItemNum(void); + +PUINT_8 getFwCfgItemKey(UINT_8 i); + +PUINT_8 getFwCfgItemValue(UINT_8 i); + +void wlanCfgFwSetParam(PUINT_8 fwBuffer, PCHAR cmdStr, PCHAR value, int num, int type); + +WLAN_STATUS wlanCfgSetGetFw(IN P_ADAPTER_T prAdapter, const PCHAR fwBuffer, int cmdNum, enum _CMD_TYPE_T cmdType); + +WLAN_STATUS wlanFwCfgParse(IN P_ADAPTER_T prAdapter, PUINT_8 pucConfigBuf); + +WLAN_STATUS wlanFwArrayCfg(IN P_ADAPTER_T prAdpter); + +WLAN_STATUS wlanFwFileCfg(IN P_ADAPTER_T prAdpter); +#ifdef CFG_SUPPORT_COEX_IOT_AP +WLAN_STATUS wlanFWCfgForIotAP(IN P_ADAPTER_T prAdpter, UINT_8 aucBssid[]); +WLAN_STATUS wlanFWCfgForceDisIotAP(IN P_ADAPTER_T prAdapter); +#endif + +#endif +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/link.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/link.h new file mode 100644 index 0000000000000..031f58b1fd135 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/link.h @@ -0,0 +1,456 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/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. + */ + +#ifndef _LINK_H +#define _LINK_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_typedef.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* May cause page fault & unalignment issue (data abort) */ +#define INVALID_LINK_POISON1 ((VOID *) 0x00100101) + +/* Used to verify that nonbody uses non-initialized link entries. */ +#define INVALID_LINK_POISON2 ((VOID *) 0x00100201) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Simple Doubly Linked List Structures - Entry Part */ +typedef struct _LINK_ENTRY_T { + struct _LINK_ENTRY_T *prNext, *prPrev; +} LINK_ENTRY_T, *P_LINK_ENTRY_T; + +/* Simple Doubly Linked List Structures - List Part */ +typedef struct _LINK_T { + P_LINK_ENTRY_T prNext; + P_LINK_ENTRY_T prPrev; + UINT_32 u4NumElem; +} LINK_T, *P_LINK_T; + +struct LINK_MGMT { + LINK_T rUsingLink; + LINK_T rFreeLink; +}; +/******************************************************************************* +* P U B 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_MGMT_INIT(prLinkMgmt) \ + do { \ + LINK_INITIALIZE(&((struct LINK_MGMT *)prLinkMgmt)->rUsingLink); \ + LINK_INITIALIZE(&((struct LINK_MGMT *)prLinkMgmt)->rFreeLink); \ + } while (0) + +#define LINK_MGMT_GET_ENTRY(prLinkMgmt, prEntry, EntryType, memType) \ + do { \ + LINK_REMOVE_HEAD(&((struct LINK_MGMT *)prLinkMgmt)->rFreeLink, \ + prEntry, EntryType*); \ + if (!prEntry) \ + prEntry = kalMemAlloc(sizeof(EntryType), memType); \ + if (prEntry) {\ + kalMemZero(prEntry, sizeof(EntryType));\ + LINK_INSERT_TAIL(&((struct LINK_MGMT *)prLinkMgmt)->rUsingLink, &prEntry->rLinkEntry); \ + } \ + } while (0) + +#define LINK_MGMT_RETURN_ENTRY(prLinkMgmt, prEntry) \ + do {\ + if (!prEntry)\ + break;\ + LINK_REMOVE_KNOWN_ENTRY(&((struct LINK_MGMT *)prLinkMgmt)->rUsingLink, \ + prEntry); \ + LINK_INSERT_TAIL(&((struct LINK_MGMT *)prLinkMgmt)->rFreeLink, &prEntry->rLinkEntry); \ + } while (0) + +#define LINK_MGMT_UNINIT(prLinkMgmt, EntryType, memType) \ + do { \ + EntryType *prEntry = NULL; \ + P_LINK_T prFreeList = &((struct LINK_MGMT *)prLinkMgmt)->rFreeLink; \ + P_LINK_T prUsingList = &((struct LINK_MGMT *)prLinkMgmt)->rUsingLink; \ + LINK_REMOVE_HEAD(prFreeList, prEntry, EntryType *); \ + while (prEntry) { \ + kalMemFree(prEntry, memType, sizeof(EntryType)); \ + LINK_REMOVE_HEAD(prFreeList, prEntry, EntryType *); \ + } \ + LINK_REMOVE_HEAD(prUsingList, prEntry, EntryType *); \ + while (prEntry) { \ + kalMemFree(prEntry, memType, sizeof(EntryType)); \ + LINK_REMOVE_HEAD(prUsingList, prEntry, EntryType *); \ + } \ + } 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_ENTRY_IS_VALID(prEntry) \ + (((P_LINK_ENTRY_T)(prEntry))->prNext != (P_LINK_ENTRY_T)NULL && \ + ((P_LINK_ENTRY_T)(prEntry))->prNext != (P_LINK_ENTRY_T)INVALID_LINK_POISON1 && \ + ((P_LINK_ENTRY_T)(prEntry))->prPrev != (P_LINK_ENTRY_T)NULL && \ + ((P_LINK_ENTRY_T)(prEntry))->prPrev != (P_LINK_ENTRY_T)INVALID_LINK_POISON2) + +#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) ? \ + (_type *)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) ? \ + (_type *)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)--; \ + } + +/* Merge prSrcLink to prDstLink and put prSrcLink ahead of prDstLink */ +#define LINK_MERGE_TO_HEAD(prDstLink, prSrcLink) \ + { \ + if (!LINK_IS_EMPTY(prSrcLink)) { \ + linkMergeToHead((P_LINK_T)prDstLink, (P_LINK_T)prSrcLink); \ + (prDstLink)->u4NumElem += (prSrcLink)->u4NumElem; \ + LINK_INITIALIZE(prSrcLink); \ + } \ + } + +/* Merge prSrcLink to prDstLink and put prSrcLink at tail */ +#define LINK_MERGE_TO_TAIL(prDstLink, prSrcLink) \ + { \ + if (!LINK_IS_EMPTY(prSrcLink)) { \ + linkMergeToTail((P_LINK_T)prDstLink, (P_LINK_T)prSrcLink); \ + (prDstLink)->u4NumElem += (prSrcLink)->u4NumElem; \ + LINK_INITIALIZE(prSrcLink); \ + } \ + } + +/* 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 && (&prObj->rMember != (P_LINK_ENTRY_T)(prLink)); \ + prObj = LINK_ENTRY(prObj->rMember.prNext, _TYPE, rMember)) + +/* Iterate backwards over a link list of given type */ +#define LINK_FOR_EACH_ENTRY_PREV(prObj, prLink, rMember, _TYPE) \ + for (prObj = LINK_ENTRY((prLink)->prPrev, _TYPE, rMember); \ + &prObj->rMember != (P_LINK_ENTRY_T)(prLink); \ + prObj = LINK_ENTRY(prObj->rMember.prPrev, _TYPE, rMember)) + +/* Iterate over a link list of given type safe against removal of link entry */ +#define LINK_FOR_EACH_ENTRY_SAFE(prObj, prNextObj, prLink, rMember, _TYPE) \ + for (prObj = LINK_ENTRY((prLink)->prNext, _TYPE, rMember), \ + prNextObj = LINK_ENTRY(prObj->rMember.prNext, _TYPE, rMember); \ + &prObj->rMember != (P_LINK_ENTRY_T)(prLink); \ + prObj = prNextObj, \ + prNextObj = LINK_ENTRY(prNextObj->rMember.prNext, _TYPE, rMember)) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is only for internal link list manipulation. +* +* \param[in] prNew Pointer of new link head +* \param[in] prPrev Pointer of previous link head +* \param[in] prNext Pointer of next link head +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __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; + +} /* end of __linkAdd() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will add a new entry after the specified link head. +* +* \param[in] prNew New entry to be added +* \param[in] prHead Specified link head to add it after +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ VOID linkAdd(IN P_LINK_ENTRY_T prNew, IN P_LINK_T prLink) +{ + __linkAdd(prNew, (P_LINK_ENTRY_T) prLink, prLink->prNext); + +} /* end of linkAdd() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will add a new entry before the specified link head. +* +* \param[in] prNew New entry to be added +* \param[in] prHead Specified link head to add it before +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ VOID linkAddTail(IN P_LINK_ENTRY_T prNew, IN P_LINK_T prLink) +{ + __linkAdd(prNew, prLink->prPrev, (P_LINK_ENTRY_T) prLink); + +} /* end of linkAddTail() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is only for internal link list manipulation. +* +* \param[in] prPrev Pointer of previous link head +* \param[in] prNext Pointer of next link head +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ VOID __linkDel(IN P_LINK_ENTRY_T prPrev, IN P_LINK_ENTRY_T prNext) +{ + prNext->prPrev = prPrev; + prPrev->prNext = prNext; + +} /* end of __linkDel() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will delete a specified entry from link list. +* NOTE: the entry is in an initial state. +* +* \param prEntry Specified link head(entry) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ VOID linkDel(IN P_LINK_ENTRY_T prEntry) +{ + __linkDel(prEntry->prPrev, prEntry->prNext); + + LINK_ENTRY_INITIALIZE(prEntry); + +} /* end of linkDel() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will delete a specified entry from link list and then add it +* after the specified link head. +* +* \param[in] prEntry Specified link head(entry) +* \param[in] prOtherHead Another link head to add it after +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ VOID linkMove(IN P_LINK_ENTRY_T prEntry, IN P_LINK_T prLink) +{ + __linkDel(prEntry->prPrev, prEntry->prNext); + linkAdd(prEntry, prLink); + +} /* end of linkMove() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will delete a specified entry from link list and then add it +* before the specified link head. +* +* \param[in] prEntry Specified link head(entry) +* \param[in] prOtherHead Another link head to add it before +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ VOID linkMoveTail(IN P_LINK_ENTRY_T prEntry, IN P_LINK_T prLink) +{ + __linkDel(prEntry->prPrev, prEntry->prNext); + linkAddTail(prEntry, prLink); + +} /* end of linkMoveTail() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will merge source link to the tail of destination link. +* +* \param[in] prDst destination link +* \param[in] prSrc source link +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ VOID linkMergeToTail(P_LINK_T prDst, P_LINK_T prSrc) +{ + prSrc->prNext->prPrev = prDst->prPrev; + prSrc->prPrev->prNext = (P_LINK_ENTRY_T)prDst; + prDst->prPrev->prNext = prSrc->prNext; + prDst->prPrev = prSrc->prPrev; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will merge source link to the head of destination link. +* +* \param[in] prDst destination link +* \param[in] prSrc source link + +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ VOID linkMergeToHead(P_LINK_T prDst, P_LINK_T prSrc) +{ + prSrc->prNext->prPrev = (P_LINK_ENTRY_T)prDst; + prSrc->prPrev->prNext = prDst->prNext; + prDst->prNext->prPrev = prSrc->prPrev; + prDst->prNext = prSrc->prNext; +} + +#endif /* _LINK_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/aa_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/aa_fsm.h new file mode 100644 index 0000000000000..f766d16d66694 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/aa_fsm.h @@ -0,0 +1,170 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/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. + */ + +#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 */ + +#define JOIN_MAX_RETRY_OVERLOAD_RN 1 /* 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_EXTERNAL_AUTH, + 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; + +typedef enum _ENUM_AA_FRM_TYPE_T { + FRM_DISASSOC = 0, + FRM_DEAUTH +} ENUM_AA_FRM_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 +******************************************************************************** +*/ + +/******************************************************************************* +* 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 ULONG plParamPtr); + +VOID saaFsmRunEventRxRespTimeOut(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); + +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); + +VOID saaChkDeauthfrmParamHandler(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN P_STA_RECORD_T prStaRec); + +VOID +saaChkDisassocfrmParamHandler(IN P_ADAPTER_T prAdapter, + IN P_WLAN_DISASSOC_FRAME_T prDisassocFrame, IN P_STA_RECORD_T prStaRec, + IN P_SW_RFB_T prSwRfb); + +VOID +saaSendDisconnectMsgHandler(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_BSS_INFO_T prAisBssInfo, + IN ENUM_AA_FRM_TYPE_T eFrmType); + +VOID saaFsmRunEventFTContinue(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +void saaFsmRunEventExternalAuthDone(IN struct _ADAPTER_T *prAdapter, IN struct _MSG_HDR_T *prMsgHdr); + + +/*----------------------------------------------------------------------------*/ +/* Routines in aaa_fsm.c */ +/*----------------------------------------------------------------------------*/ +VOID aaaFsmRunEventRxAuth(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +WLAN_STATUS aaaFsmRunEventRxAssoc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +WLAN_STATUS +aaaFsmRunEventTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _AA_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/ais_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/ais_fsm.h new file mode 100644 index 0000000000000..a5688a93487f7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/ais_fsm.h @@ -0,0 +1,504 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/ais_fsm.h#2 + */ + +/* + * ! \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. + */ + +#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 5 /* 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 +#define AIS_SCN_DONE_TIMEOUT_SEC 30 /* 30 for 2.4G + 5G */ /* 5 */ + +#define AIS_AUTORN_MIN_INTERVAL 20 +#define AIS_BLACKLIST_TIMEOUT 15 /* seconds */ +#define AIS_WAIT_OKC_PMKID_SEC 1000 /* unit: ms */ + +/******************************************************************************* +* 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_JOIN_FAILURE, + AIS_STATE_IBSS_ALONE, + AIS_STATE_IBSS_MERGE, + AIS_STATE_NORMAL_TR, + AIS_STATE_DISCONNECTING, + AIS_STATE_REQ_REMAIN_ON_CHANNEL, + AIS_STATE_REMAIN_ON_CHANNEL, + AIS_STATE_COLLECT_ESS_INFO, + AIS_STATE_NUM +} ENUM_AIS_STATE_T; + +enum _BLACK_LIST_SOURCE { + AIS_BLACK_LIST_FROM_DRIVER = 1, + AIS_BLACK_LIST_FROM_FWK = 2, + + AIS_BLACK_LIST_MAX = 1 << 7 +}; + +/* reconnect level for determining if we should reconnect */ +typedef enum _ENUM_RECONNECT_LEVEL_T { + RECONNECT_LEVEL_MIN = 0, + RECONNECT_LEVEL_ROAMING_FAIL, /* roaming failed */ + RECONNECT_LEVEL_BEACON_TIMEOUT, /* driver beacon timeout */ + RECONNECT_LEVEL_USER_SET, /* user set connect or disassociate */ + RECONNECT_LEVEL_MAX +} ENUM_RECONNECT_LEVEL_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 ucBssIndex; + BOOLEAN fgIsMergeIn; /* TRUE: Merge In, FALSE: Merge Out */ + P_STA_RECORD_T prStaRec; +} MSG_AIS_IBSS_PEER_FOUND_T, *P_MSG_AIS_IBSS_PEER_FOUND_T; + +typedef enum _ENUM_AIS_REQUEST_TYPE_T { + AIS_REQUEST_SCAN, + AIS_REQUEST_RECONNECT, + AIS_REQUEST_ROAMING_SEARCH, + AIS_REQUEST_ROAMING_CONNECT, + AIS_REQUEST_REMAIN_ON_CHANNEL, + AIS_REQUEST_NUM +} ENUM_AIS_REQUEST_TYPE_T; + +typedef struct _AIS_REQ_HDR_T { + LINK_ENTRY_T rLinkEntry; + ENUM_AIS_REQUEST_TYPE_T eReqType; + /* temp save partial scan channel info */ + PUINT_8 pucChannelInfo; +} AIS_REQ_HDR_T, *P_AIS_REQ_HDR_T; + +typedef struct _AIS_REQ_CHNL_INFO { + ENUM_BAND_T eBand; + ENUM_CHNL_EXT_T eSco; + UINT_8 ucChannelNum; + UINT_32 u4DurationMs; + UINT_64 u8Cookie; +} AIS_REQ_CHNL_INFO, *P_AIS_REQ_CHNL_INFO; + +typedef struct _AIS_MGMT_TX_REQ_INFO_T { + BOOLEAN fgIsMgmtTxRequested; + P_MSDU_INFO_T prMgmtTxMsdu; + UINT_64 u8Cookie; +} AIS_MGMT_TX_REQ_INFO_T, *P_AIS_MGMT_TX_REQ_INFO_T; + +struct AIS_BLACKLIST_ITEM { + LINK_ENTRY_T rLinkEntry; + + UINT_8 aucBSSID[MAC_ADDR_LEN]; + UINT_16 u2DeauthReason; + UINT_16 u2AuthStatus; + UINT_8 ucCount; + UINT_8 ucSSIDLen; + UINT_8 aucSSID[32]; + OS_SYSTIME rAddTime; + UINT_64 u8DisapperTime; + UINT_8 blackListSource; +}; + +struct AIS_BEACON_TIMEOUT_BSS { + LINK_ENTRY_T rLinkEntry; + + UINT_64 u8Tsf; + UINT_64 u8AddTime; + UINT_8 ucReserved; + UINT_8 aucBSSID[MAC_ADDR_LEN]; + UINT_8 ucSSIDLen; + UINT_8 aucSSID[32]; +}; + +typedef struct _AIS_FSM_INFO_T { + ENUM_AIS_STATE_T ePreviousState; + ENUM_AIS_STATE_T eCurrentState; + + BOOLEAN fgTryScan; +#if CFG_SUPPORT_ABORT_SCAN + BOOLEAN fgIsScanning; +#endif + + 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; + + UINT_32 u4PostponeIndStartTime; + + TIMER_T rJoinTimeoutTimer; + + TIMER_T rChannelTimeoutTimer; + + TIMER_T rScanDoneTimer; + + TIMER_T rDeauthDoneTimer; + +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE + TIMER_T rSecModeChangeTimer; +#endif + TIMER_T rWaitOkcPMKTimer; + + UINT_8 ucSeqNumOfReqMsg; + UINT_8 ucSeqNumOfChReq; + UINT_8 ucSeqNumOfScanReq; + + UINT_32 u4ChGrantedInterval; + + UINT_8 ucConnTrialCount; + + UINT_8 ucScanSSIDNum; + PARAM_SSID_T arScanSSID[SCN_SSID_MAX_NUM]; + struct _PARAM_SCAN_RANDOM_MAC_ADDR_T rScanRandMacAddr; + + UINT_32 u4ScanIELength; + UINT_8 aucScanIEBuf[MAX_IE_LENGTH]; + + /* Pending Request List */ + LINK_T rPendingReqList; + + /* Join Request Timestamp */ + OS_SYSTIME rJoinReqTime; + + /* for cfg80211 REMAIN_ON_CHANNEL support */ + AIS_REQ_CHNL_INFO rChReqInfo; + + /* Mgmt tx related. */ + AIS_MGMT_TX_REQ_INFO_T rMgmtTxInfo; + + /* Packet filter for AIS module. */ + UINT_32 u4AisPacketFilter; + + /* for roaming target */ + PARAM_SSID_T rRoamingSSID; + + struct LINK_MGMT rBcnTimeout; + UINT_8 ucJoinFailCntAfterScan; + UINT_32 u4ScanUpdateIdx; + BOOLEAN fgAdjChnlScanIssued; +} AIS_FSM_INFO_T, *P_AIS_FSM_INFO_T; + +enum WNM_AIS_BSS_TRANSITION { + BSS_TRANSITION_NO_MORE_ACTION, + BSS_TRANSITION_REQ_ROAMING, + BSS_TRANSITION_DISASSOC, + BSS_TRANSITION_MAX_NUM +}; +struct MSG_AIS_BSS_TRANSITION_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucToken; + BOOLEAN fgNeedResponse; + UINT_8 ucValidityInterval; + enum WNM_AIS_BSS_TRANSITION eTransitionType; + UINT_16 u2CandListLen; + PUINT_8 pucCandList; +}; + +/******************************************************************************* +* P U B 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->prAisBssInfo->eConnectionState = (_eNewMediaState)) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID aisInitializeConnectionSettings(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo); + +VOID aisFsmInit(IN P_ADAPTER_T prAdapter); + +VOID aisFsmUninit(IN P_ADAPTER_T prAdapter); + +VOID aisFsmStateInit_JOIN(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc); + +BOOLEAN aisFsmStateInit_RetryJOIN(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +VOID aisFsmStateInit_IBSS_ALONE(IN P_ADAPTER_T prAdapter); + +VOID aisFsmStateInit_IBSS_MERGE(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc); + +VOID aisFsmStateAbort(IN P_ADAPTER_T prAdapter, UINT_8 ucReasonOfDisconnect, BOOLEAN fgDelayIndication); + +VOID aisFsmStateAbort_JOIN(IN P_ADAPTER_T prAdapter); + +VOID aisFsmStateAbort_SCAN(IN P_ADAPTER_T prAdapter); + +VOID aisFsmStateAbort_NORMAL_TR(IN P_ADAPTER_T prAdapter); + +VOID aisFsmStateAbort_IBSS(IN P_ADAPTER_T prAdapter); +#if 0 +VOID aisFsmSetChannelInfo(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_SCAN_REQ_V2 ScanReqMsg, + IN ENUM_AIS_STATE_T CurrentState); +#endif + +VOID aisFsmSteps(IN P_ADAPTER_T prAdapter, ENUM_AIS_STATE_T eNextState); + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Handling */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +#if CFG_SUPPORT_ABORT_SCAN +VOID AisFsmHandlePendingScan(IN P_ADAPTER_T prAdapter, + IN P_AIS_REQ_HDR_T prAisReq, + OUT ENUM_AIS_STATE_T *peNextState, + OUT PBOOLEAN pfgIsTransition); + +VOID AisFsmGenerateScanDoneMsg(IN P_ADAPTER_T prAdapter, IN ENUM_SCAN_STATUS eScanStatus); + +BOOLEAN AisFsmGetScanState(IN P_ADAPTER_T prAdapter); + +VOID AisFsmSetScanState(IN P_ADAPTER_T prAdapter, IN BOOLEAN bFlag); +#endif + +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); + +enum _ENUM_AIS_STATE_T aisFsmJoinCompleteAction(IN struct _ADAPTER_T *prAdapter, IN struct _MSG_HDR_T *prMsgHdr); + +VOID aisFsmRunEventFoundIBSSPeer(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID aisFsmRunEventRemainOnChannel(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID aisFsmRunEventCancelRemainOnChannel(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +/*----------------------------------------------------------------------------*/ +/* Handling for Ad-Hoc Network */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmCreateIBSS(IN P_ADAPTER_T prAdapter); + +VOID aisFsmMergeIBSS(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +/*----------------------------------------------------------------------------*/ +/* Handling of Incoming Mailbox Message from CNM */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventChGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +/*----------------------------------------------------------------------------*/ +/* Generating Outgoing Mailbox Message to CNM */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmReleaseCh(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* Event Indication */ +/*----------------------------------------------------------------------------*/ +VOID +aisIndicationOfMediaStateToHost(IN P_ADAPTER_T prAdapter, + ENUM_PARAM_MEDIA_STATE_T eConnectionState, BOOLEAN fgDelayIndication); + +VOID aisCheckPostponedDisconnTimeout(IN P_ADAPTER_T prAdapter, P_AIS_FSM_INFO_T prAisFsmInfo); + +VOID aisUpdateBssInfoForJOIN(IN P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, P_SW_RFB_T prAssocRspSwRfb); + +VOID aisUpdateBssInfoForCreateIBSS(IN P_ADAPTER_T prAdapter); + +VOID aisUpdateBssInfoForMergeIBSS(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +BOOLEAN aisValidateProbeReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_32 pu4ControlFlags); + +WLAN_STATUS +aisFsmRunEventMgmtFrameTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +/*----------------------------------------------------------------------------*/ +/* Disconnection Handling */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmDisconnect(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgDelayIndication); + +/*----------------------------------------------------------------------------*/ +/* Event Handling */ +/*----------------------------------------------------------------------------*/ +VOID aisBssBeaconTimeout(IN P_ADAPTER_T prAdapter); + +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE +VOID aisBssSecurityChanged(IN P_ADAPTER_T prAdapter); +#endif + +WLAN_STATUS +aisDeauthXmitComplete(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +#if CFG_SUPPORT_ROAMING +VOID aisFsmRunEventRoamingDiscovery(IN P_ADAPTER_T prAdapter, UINT_32 u4ReqScan); + +ENUM_AIS_STATE_T aisFsmRoamingScanResultsUpdate(IN P_ADAPTER_T prAdapter); + +VOID aisFsmRoamingDisconnectPrevAP(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prTargetStaRec); + +VOID aisUpdateBssInfoForRoamingAP(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prAssocRspSwRfb); +#endif /*CFG_SUPPORT_ROAMING */ + +/*----------------------------------------------------------------------------*/ +/* Timeout Handling */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventBGSleepTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr); + +VOID aisFsmRunEventIbssAloneTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr); + +VOID aisFsmRunEventJoinTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr); + +VOID aisFsmRunEventChannelTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr); + +VOID aisFsmRunEventDeauthTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr); + +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE +VOID aisFsmRunEventSecModeChangeTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr); +#endif + +/*----------------------------------------------------------------------------*/ +/* OID/IOCTL Handling */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmScanRequest(IN P_ADAPTER_T prAdapter, IN P_PARAM_SSID_T prSsid, IN PUINT_8 pucIe, IN UINT_32 u4IeLength); + +VOID +aisFsmScanRequestAdv(IN P_ADAPTER_T prAdapter, IN UINT_8 ucSsidNum, IN P_PARAM_SSID_T prSsid, + IN PUINT_8 pucIe, IN UINT_32 u4IeLength, IN UINT_8 ucSetChannel, + IN struct _PARAM_SCAN_RANDOM_MAC_ADDR_T *prScanRandMacAddr); + +/*----------------------------------------------------------------------------*/ +/* Internal State Checking */ +/*----------------------------------------------------------------------------*/ +struct _AIS_FSM_INFO_T *aisGetAisFsmInfo(IN struct _ADAPTER_T *prAdapter, IN uint8_t ucBssIndex); + +BOOLEAN aisFsmIsRequestPending(IN P_ADAPTER_T prAdapter, IN ENUM_AIS_REQUEST_TYPE_T eReqType, IN BOOLEAN bRemove); + +P_AIS_REQ_HDR_T aisFsmGetNextRequest(IN P_ADAPTER_T prAdapter); + +BOOLEAN aisFsmInsertRequest(IN P_ADAPTER_T prAdapter, IN ENUM_AIS_REQUEST_TYPE_T eReqType); + +VOID aisFsmFlushRequest(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS +aisFuncTxMgmtFrame(IN P_ADAPTER_T prAdapter, + IN P_AIS_MGMT_TX_REQ_INFO_T prMgmtTxReqInfo, IN P_MSDU_INFO_T prMgmtTxMsdu, IN UINT_64 u8Cookie); + +VOID aisFsmRunEventMgmtFrameTx(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID aisFuncValidateRxActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +enum _ENUM_AIS_STATE_T aisFsmStateSearchAction(IN struct _ADAPTER_T *prAdapter, UINT_8 ucPhase); +#if defined(CFG_TEST_MGMT_FSM) && (CFG_TEST_MGMT_FSM != 0) +VOID aisTest(VOID); +#endif /* CFG_TEST_MGMT_FSM */ + +VOID aisRemoveBlacklistBySource(P_ADAPTER_T prAdapter, enum _BLACK_LIST_SOURCE source); +struct AIS_BLACKLIST_ITEM *aisAddBlacklist(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc, + enum _BLACK_LIST_SOURCE source); +struct AIS_BLACKLIST_ITEM *aisAddBlacklistByBssid(P_ADAPTER_T prAdapter, UINT_8 aucBSSID[], + enum _BLACK_LIST_SOURCE source); +VOID aisRemoveBlackList(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc, enum _BLACK_LIST_SOURCE source); +VOID aisRemoveTimeoutBlacklist(P_ADAPTER_T prAdapter); +struct AIS_BLACKLIST_ITEM *aisQueryBlackList(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc); +struct AIS_BLACKLIST_ITEM *aisQueryBlackListByBssid(P_ADAPTER_T prAdapter, UINT_8 aucBSSID[]); +VOID aisRecordBeaconTimeout(P_ADAPTER_T prAdapter, P_BSS_INFO_T prAisBssInfo); +VOID aisRemoveBeaconTimeoutEntry(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc); +UINT_16 aisCalculateBlackListScore(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc); +VOID aisCollectNeighborAP(P_ADAPTER_T prAdapter, PUINT_8 pucApBuf, + UINT_16 u2ApBufLen, UINT_8 ucValidInterval); +VOID aisRunEventChnlUtilRsp(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr); + +VOID aisFsmRunEventBssTransition(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); +VOID aisFsmRunEventSetOkcPmk(IN P_ADAPTER_T prAdapter); + +VOID aisSendNeighborRequest(P_ADAPTER_T prAdapter); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _AIS_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/assoc.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/assoc.h new file mode 100644 index 0000000000000..8d149cf2c4fe2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/assoc.h @@ -0,0 +1,98 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/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. + */ + +#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); + +UINT_16 assocBuildCapabilityInfo(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +VOID assocGenerateMDIE(IN P_ADAPTER_T prAdapter, IN OUT P_MSDU_INFO_T prMsduInfo); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _ASSOC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/auth.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/auth.h new file mode 100644 index 0000000000000..b0a0b508dfc7b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/auth.h @@ -0,0 +1,121 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/auth.h#1 +*/ + +#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 UINT_8 uBssIndex, + 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_BSS_INFO_T prBssInfo, + 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 pu2StatusCode); + +UINT_32 authProcessRxAuthFrame(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN P_BSS_INFO_T prBssInfo, + OUT PUINT_16 pu2StatusCode); + +VOID authAddMDIE(IN P_ADAPTER_T prAdapter, IN OUT P_MSDU_INFO_T prMsduInfo); + +UINT_32 authCalculateRSNIELen(P_ADAPTER_T prAdapter, UINT_8 ucBssIdx, P_STA_RECORD_T prStaRec); + +VOID authAddRSNIE(IN P_ADAPTER_T prAdapter, IN OUT P_MSDU_INFO_T prMsduInfo); + +VOID authHandleFtIEs(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, P_IE_HDR_T prIEHdr); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _AUTH_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/bow_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/bow_fsm.h new file mode 100644 index 0000000000000..dddac8298eb5e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/bow_fsm.h @@ -0,0 +1,152 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/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. + */ + +#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 { + /* Channel Privilege */ + BOOLEAN fgIsChannelRequested; + BOOLEAN fgIsChannelGranted; + UINT_32 u4ChGrantedInterval; + + UINT_8 ucPrimaryChannel; + ENUM_BAND_T eBand; + UINT_16 u2BeaconInterval; + + P_STA_RECORD_T prTargetStaRec; + P_BSS_DESC_T prTargetBssDesc; /* For destination */ + + UINT_8 aucPeerAddress[6]; + UINT_8 ucBssIndex; /* Assume there is only 1 BSS for BOW */ + UINT_8 ucRole; /* Initiator or responder */ + UINT_8 ucAvailableAuthTypes; /* Used for AUTH_MODE_AUTO_SWITCH */ + + BOOLEAN fgSupportQoS; + + /* Sequence number of requested message. */ + UINT_8 ucSeqNumOfChReq; + UINT_8 ucSeqNumOfReqMsg; + UINT_8 ucSeqNumOfScnMsg; + UINT_8 ucSeqNumOfScanReq; + UINT_8 ucSeqNumOfCancelMsg; + + /* Timer */ + TIMER_T rStartingBeaconTimer; /* For device discovery time of each discovery request from user. */ + TIMER_T rChGrantedTimer; + + /* can be deleted? */ + TIMER_T rIndicationOfDisconnectTimer; + +} 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(_prBssInfo, _eNewMediaState) \ + (_prBssInfo->eConnectionState = (_eNewMediaState)) + /* (_prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX].eConnectionState = (_eNewMediaState)); */ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/bss.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/bss.h new file mode 100644 index 0000000000000..d7e2cf02f03f7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/bss.h @@ -0,0 +1,200 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** 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. + */ + +#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 +******************************************************************************** +*/ +#include "wlan_def.h" +extern const PUINT_8 apucNetworkType[NETWORK_TYPE_NUM]; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* Fixed value=4 for MT6630. + * It is the biggest index of this pointer array prAdapter->aprBssInfo[]. + */ +#define MAX_BSS_INDEX HW_BSSID_NUM +#define P2P_DEV_BSS_INDEX MAX_BSS_INDEX + +/* Define how many concurrent operation networks. */ +#define BSS_INFO_NUM KAL_BSS_NUM +#define BSS_P2P_NUM KAL_P2P_NUM + +#if (KAL_BSS_NUM > HW_BSSID_NUM) || (KAL_P2P_NUM > KAL_BSS_NUM) +#error Exceed HW capability (KAL_BSS_NUM or KAL_P2P_NUM)!! +#endif + +/* 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 IS_BSS_INDEX_VALID(_ucBssIndex) ((_ucBssIndex) <= P2P_DEV_BSS_INDEX) + +#define GET_BSS_INFO_BY_INDEX(_prAdapter, _ucBssIndex) \ + ((_prAdapter)->aprBssInfo[(_ucBssIndex)]) + +#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 UINT_8 uBssIndex, 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); + +VOID bssDumpBssInfo(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex); + +VOID bssDetermineApBssInfoPhyTypeSet(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsPureAp, OUT P_BSS_INFO_T prBssInfo); + +/*----------------------------------------------------------------------------*/ +/* 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 UINT_8 uBssIndex, IN PUINT_8 pucDestAddr, IN UINT_32 u4ControlFlags); + +WLAN_STATUS bssProcessProbeRequest(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID bssInitializeClientList(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo); + +VOID bssAddClient(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_STA_RECORD_T prStaRec); + +BOOLEAN bssRemoveClient(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_STA_RECORD_T prStaRec); + +P_STA_RECORD_T bssRemoveClientByMac(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN PUINT_8 pucMac); + +P_STA_RECORD_T bssGetClientByAddress(IN P_BSS_INFO_T prBssInfo, PUINT_8 pucMacAddr); + +P_STA_RECORD_T bssRemoveHeadClient(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo); + +UINT_32 bssGetClientCount(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo); + +VOID bssDumpClientList(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo); + +VOID bssCheckClientList(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo); + +/*----------------------------------------------------------------------------*/ +/* 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 UINT_8 uBssIndex); + +/*----------------------------------------------------------------------------*/ +/* 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 UINT_8 uBssIndex); + +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/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/cnm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/cnm.h new file mode 100644 index 0000000000000..9cb8126802ab8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/cnm.h @@ -0,0 +1,229 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * ! \file "cnm.h" + * \brief + */ + +#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_OFFCHNL_TX, + CH_REQ_TYPE_GO_START_BSS, + 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 ucBssIndex; + UINT_8 ucTokenID; + UINT_8 ucPrimaryChannel; + ENUM_CHNL_EXT_T eRfSco; + ENUM_BAND_T eRfBand; + ENUM_CHANNEL_WIDTH_T eRfChannelWidth; /* To support 80/160MHz bandwidth */ + UINT_8 ucRfCenterFreqSeg1; /* To support 80/160MHz bandwidth */ + UINT_8 ucRfCenterFreqSeg2; /* To support 80/160MHz bandwidth */ + ENUM_CH_REQ_TYPE_T eReqType; + UINT_32 u4MaxInterval; /* In unit of ms */ +} 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 ucBssIndex; + 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 ucBssIndex; + UINT_8 ucTokenID; + UINT_8 ucPrimaryChannel; + ENUM_CHNL_EXT_T eRfSco; + ENUM_BAND_T eRfBand; + ENUM_CHANNEL_WIDTH_T eRfChannelWidth; /* To support 80/160MHz bandwidth */ + UINT_8 ucRfCenterFreqSeg1; /* To support 80/160MHz bandwidth */ + UINT_8 ucRfCenterFreqSeg2; /* To support 80/160MHz bandwidth */ + 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 ucBssIndex; + UINT_8 ucTokenID; + UINT_8 ucPrimaryChannel; + ENUM_CHNL_EXT_T eRfSco; + ENUM_BAND_T eRfBand; + ENUM_CHANNEL_WIDTH_T eRfChannelWidth; /* To support 80/160MHz bandwidth */ + UINT_8 ucRfCenterFreqSeg1; /* To support 80/160MHz bandwidth */ + UINT_8 ucRfCenterFreqSeg2; /* To support 80/160MHz bandwidth */ + ENUM_CH_REQ_TYPE_T eReqType; +} MSG_CH_RECOVER_T, *P_MSG_CH_RECOVER_T; + +struct MSG_REQ_CH_UTIL { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_16 u2Duration; + UINT_16 u2ReturnMID; + UINT_8 ucChnlNum; + UINT_8 aucChnlList[100]; +}; + +struct MSG_CH_UTIL_RSP { + MSG_HDR_T rMsgHdr; + UINT_8 ucChnlNum; + UINT_8 aucChnlList[100]; + UINT_8 aucChUtil[100]; +}; + +typedef struct _CNM_INFO_T { + BOOLEAN fgChGranted; + UINT_8 ucBssIndex; + UINT_8 ucTokenID; + + UINT_16 u2ReturnMID; + TIMER_T rReqChnlUtilTimer; +} 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 +******************************************************************************** +*/ +#define CNM_CH_GRANTED_FOR_BSS(_prAdapter, _ucBssIndex) \ + ((_prAdapter)->rCnmInfo.fgChGranted && \ + (_prAdapter)->rCnmInfo.ucBssIndex == (_ucBssIndex)) + +/******************************************************************************* +* 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, UINT_8 ucBssIndex); + +BOOLEAN cnmBss40mBwPermittedForJoin(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex); + +BOOLEAN cnmBss80mBwPermitted(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex); + +UINT_8 cnmGetBssMaxBw(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex); + +P_BSS_INFO_T cnmGetBssInfoAndInit(P_ADAPTER_T prAdapter, ENUM_NETWORK_TYPE_T eNetworkType, BOOLEAN fgIsP2pDevice); + +VOID cnmFreeBssInfo(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); + +VOID cnmRunEventReqChnlUtilTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr); +VOID cnmHandleChannelUtilization(P_ADAPTER_T prAdapter, + struct EVENT_RSP_CHNL_UTILIZATION *prChnlUtil); +VOID cnmRequestChannelUtilization(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr); +BOOLEAN cnmChUtilIsRunning(P_ADAPTER_T prAdapter); + +BOOLEAN cnmSapIsActive(P_ADAPTER_T prAdapter); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#ifndef _lint +/* We don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + * We'll need this to guarantee the same member order in different structures + * to simply handling effort in some functions. + */ +static __KAL_INLINE__ VOID cnmMsgDataTypeCheck(VOID) +{ + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, rMsgHdr) == 0); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, rMsgHdr) == OFFSET_OF(MSG_CH_RECOVER_T, rMsgHdr)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, ucBssIndex) == OFFSET_OF(MSG_CH_RECOVER_T, ucBssIndex)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, ucTokenID) == OFFSET_OF(MSG_CH_RECOVER_T, ucTokenID)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, ucPrimaryChannel) == + OFFSET_OF(MSG_CH_RECOVER_T, ucPrimaryChannel)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, eRfSco) == OFFSET_OF(MSG_CH_RECOVER_T, eRfSco)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, eRfBand) == OFFSET_OF(MSG_CH_RECOVER_T, eRfBand)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, eReqType) == OFFSET_OF(MSG_CH_RECOVER_T, eReqType)); + +} +#endif /* _lint */ + +#endif /* _CNM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/cnm_mem.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/cnm_mem.h new file mode 100644 index 0000000000000..f5916191df7d3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/cnm_mem.h @@ -0,0 +1,913 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/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. + */ + +#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 +******************************************************************************** +*/ +#include "qosmap.h" +/******************************************************************************* +* 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 + +/* Define the argument of cnmStaFreeAllStaByNetwork when all station records + * will be free. No one will be free + */ +#define STA_REC_EXCLUDE_NONE CFG_STA_REC_NUM + +/******************************************************************************* +* 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; + +#if 0 +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; +#endif + +#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; + +#if CFG_SUPPORT_802_11W +/* AP PMF */ +struct AP_PMF_CFG { + BOOLEAN fgMfpc; + BOOLEAN fgMfpr; + BOOLEAN fgSha256; + BOOLEAN fgAPApplyPmfReq; + BOOLEAN fgBipKeyInstalled; +}; + +struct STA_PMF_CFG { + BOOLEAN fgMfpc; + BOOLEAN fgMfpr; + BOOLEAN fgSha256; + BOOLEAN fgSaeRequireMfp; + BOOLEAN fgApplyPmf; + BOOLEAN fgBipKeyInstalled; + + /* for certification 4.3.3.1, 4.3.3.2 TX unprotected deauth */ + BOOLEAN fgRxDeauthResp; + + /* For PMF SA query TX request retry a timer */ + /* record the start time of 1st SAQ request */ + UINT_32 u4SAQueryStart; + + UINT_32 u4SAQueryCount; + UINT_8 ucSAQueryTimedOut; /* retry more than 1000ms */ + TIMER_T rSAQueryTimer; + UINT_16 u2TransactionID; +}; +#endif + + +/* Define STA record structure */ +struct _STA_RECORD_T { + LINK_ENTRY_T rLinkEntry; + UINT_8 ucIndex; /* Not modify it except initializing */ + UINT_8 ucWlanIndex; /* WLAN table index */ + + UINT_8 ucBMCWlanIndex; /* The BSS STA Rx WLAN index, IBSS Rx BC WLAN table index, work at IBSS Open and WEP */ + + 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 ucBssIndex; /* BSS_INFO_I index */ + + UINT_8 ucStaState; /* STATE_1,2,3 */ + + UINT_8 ucPhyTypeSet; /* Available PHY Type Set of this peer + * (may deduced from received BSS_DESC_T) + */ + UINT_8 ucDesiredPhyTypeSet; /* The match result by AND operation of peer's + * PhyTypeSet and ours. + */ + BOOLEAN fgHasBasicPhyType; /* A flag to indicate a Basic Phy Type which + * is used to generate some Phy Attribute IE + * (e.g. capability, MIB) during association. + */ + UINT_8 ucNonHTBasicPhyType; /* The Basic Phy Type chosen among the + * ucDesiredPhyTypeSet. + */ + + UINT_16 u2HwDefaultFixedRateCode; + + 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_8 aucRxMcsBitmask[SUP_MCS_RX_BITMASK_OCTET_NUM]; + UINT_16 u2RxHighestSupportedRate; + UINT_32 u4TxRateInfo; + 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 */ +#if 1 /* CFG_SUPPORT_802_11AC */ + /*------------------------------------------------------------------------------------------*/ + /* 802.11ac VHT capabilities when (prStaRec->ucPhyTypeSet & PHY_TYPE_BIT_VHT) is true */ + /* They have the same definition with fields of information element */ + /*------------------------------------------------------------------------------------------*/ + UINT_32 u4VhtCapInfo; + UINT_16 u2VhtRxMcsMap; + UINT_16 u2VhtRxHighestSupportedDataRate; + UINT_16 u2VhtTxMcsMap; + UINT_16 u2VhtTxHighestSupportedDataRate; +#endif + UINT_8 ucRCPI; /* RCPI of peer */ + + UINT_8 ucDTIMPeriod; /* Target BSS's DTIM Period, we use this + * value for setup Listen Interval + * TODO(Kevin): TBD + */ + UINT_8 ucAuthAlgNum; /* For Infra/AP Mode, the Auth Algorithm Num used in Authentication(SAA/AAA) */ + UINT_8 ucAuthTranNum; /* For Infra/AP Mode, the Auth Transaction Number */ + 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) + */ + + BOOLEAN afgIsIgnoreAmsduDuplicate[TID_NUM + 1]; + +#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 */ + +#if CFG_SUPPORT_ADHOC + BOOLEAN fgAdhocRsnBcKeyExist[2]; /* + * Ad-hoc RSN Rx BC key exist flag, + * only reserved two entry for each peer + */ + UINT_8 ucAdhocRsnBcWlanIndex[2]; /* Ad-hoc RSN Rx BC wlan index */ +#endif + + BOOLEAN fgPortBlock; /* The 802.1x Port Control flag */ + + BOOLEAN fgTransmitKeyExist; /* Unicast key exist for this STA */ + + UINT_8 ucCurrentGtkId; /* The Current Group key ID */ + + BOOLEAN fgTxAmpduEn; /* Enable TX AMPDU for this Peer */ + BOOLEAN fgRxAmpduEn; /* Enable RX AMPDU for this Peer */ + + PUINT_8 pucAssocReqIe; + UINT_16 u2AssocReqIeLen; + + WIFI_WMM_AC_STAT_T arLinkStatistics[WMM_AC_INDEX_NUM]; /*link layer satatistics */ + + /*------------------------------------------------------------------------------------------*/ + /* 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) */ + + BOOLEAN afgAcmRequired[ACI_NUM]; +#if DSCP_SUPPORT + UINT_8 qosMapSet[64]; +#endif + /*------------------------------------------------------------------------------------------*/ + /* P2P related fields */ + /*------------------------------------------------------------------------------------------*/ +#if CFG_ENABLE_WIFI_DIRECT + UINT_8 u2DevNameLen; + UINT_8 aucDevName[WPS_ATTRI_MAX_LEN_DEVICE_NAME]; + + UINT_8 aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ + + UINT_16 u2ConfigMethods; + + UINT_8 ucDeviceCap; + + UINT_8 ucSecondaryDevTypeCount; + + DEVICE_TYPE_T rPrimaryDevTypeBE; + + DEVICE_TYPE_T arSecondaryDevTypeBE[P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT]; +#endif /* CFG_SUPPORT_P2P */ + + /*------------------------------------------------------------------------------------------*/ + /* QM related fields */ + /*------------------------------------------------------------------------------------------*/ + + UINT_8 ucFreeQuota; /* + * Per Sta flow controal. Valid when fgIsInPS is TRUE. + * Change it for per Queue flow control + */ + /* UINT_8 aucFreeQuotaPerQueue[NUM_OF_PER_STA_TX_QUEUES]; *//* used in future */ + UINT_8 ucFreeQuotaForDelivery; + UINT_8 ucFreeQuotaForNonDelivery; + + /*------------------------------------------------------------------------------------------*/ + /* TXM related fields */ + /*------------------------------------------------------------------------------------------*/ + PVOID aprTxDescTemplate[TX_DESC_TID_NUM]; + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE && CFG_ENABLE_PER_STA_STATISTICS + UINT_32 u4TotalTxPktsNumber; + UINT_32 u4TotalTxPktsTime; + UINT_32 u4TotalTxPktsHifTxTime; + + UINT_32 u4TotalRxPktsNumber; + UINT_32 u4MaxTxPktsTime; + UINT_32 u4MaxTxPktsHifTime; + + UINT_32 u4ThresholdCounter; + UINT_32 u4EnqueueCounter; + UINT_32 u4DeqeueuCounter; +#endif + +#if 1 + /*------------------------------------------------------------------------------------------*/ + /* To be removed, this is to make que_mgt compilation success only */ + /*------------------------------------------------------------------------------------------*/ + /* When this STA_REC is in use, set to TRUE. */ + BOOLEAN fgIsValid; + + /* TX key is ready */ + BOOLEAN fgIsTxKeyReady; + + /* When the STA is connected or TX key is ready */ + BOOLEAN fgIsTxAllowed; + + /* Per-STA Queues: [0] AC0, [1] AC1, [2] AC2, [3] AC3, [4] MGMT, [5] non-QoS */ + QUE_T arTxQueue[NUM_OF_PER_STA_TX_QUEUES]; + + /* 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 + UINT_8 ucTrafficDataType; /* 0: auto 1: data 2: video 3: voice */ + UINT_8 ucTxGfMode; /* 0: auto 1:Force enable 2: Force disable 3: enable by peer */ + UINT_8 ucTxSgiMode; /* 0: auto 1:Force enable 2: Force disable 3: enable by peer */ + UINT_8 ucTxStbcMode; /* 0: auto 1:Force enable 2: Force disable 3: enable by peer */ + UINT_32 u4FixedPhyRate; /* */ + UINT_16 u2MaxLinkSpeed; /* unit is 0.5 Mbps */ + UINT_16 u2MinLinkSpeed; + UINT_32 u4Flags; /* reserved for MTK Synergies */ + +#if CFG_SUPPORT_TDLS + BOOLEAN fgTdlsIsProhibited; /* TRUE: AP prohibits TDLS links */ + BOOLEAN fgTdlsIsChSwProhibited; /* TRUE: AP prohibits TDLS chan switch */ + + BOOLEAN flgTdlsIsInitiator; /* TRUE: the peer is the initiator */ + IE_HT_CAP_T rTdlsHtCap; /* temp to queue HT capability element */ + PARAM_KEY_T rTdlsKeyTemp; /* temp to queue the key information */ + UINT_8 ucTdlsIndex; +#endif /* CFG_SUPPORT_TDLS */ + UINT_16 u2MaxIdlePeriod; + UINT_8 ucIdleOption; + BOOLEAN fgSupportBTM; /* flag to indicate Capbility for Bss Transition Management */ +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + UINT_32 u4RxVector0; + UINT_32 u4RxVector1; + UINT_32 u4RxVector2; + UINT_32 u4RxVector3; + UINT_32 u4RxVector4; +#endif +#if CFG_SUPPORT_802_11W + /* AP PMF */ + struct STA_PMF_CFG rPmfCfg; +#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 required for this packet */ + BOOLEAN fgBIP; /* Set to true if BIP is used for this packet */ + UINT_8 ucFragTotalCount; + UINT_8 ucFragFinishedCount; + UINT_16 u2FragThreshold; /* Fragmentation threshold without WLAN Header & FCS */ + BOOLEAN fgFixedRate; /* If a fixed rate is used, set to TRUE. */ + UINT_8 ucFixedRateCode; /* The rate code copied to MAC TX Desc */ + UINT_8 ucFixedRateRetryLimit; /* The retry limit when a fixed rate is used */ + BOOLEAN fgIsBmcQueueEnd; /* Set to true if this packet is the end of BMC */ + + /* TXM: For flushing ACL frames */ + UINT_16 u2PalLLH; /* 802.11 PAL LLH */ + /* UINT_16 u2LLH; */ + UINT_16 u2ACLSeq; /* u2LLH+u2ACLSeq for AM HCI flush ACL frame */ + + /* TXM for retransmitting a flushed packet */ + BOOLEAN fgIsSnAssigned; + UINT_16 u2SequenceNumber; /* To remember the Sequence Control field of this MPDU */ + +} MSDU_INFO_T, *P_MSDU_INFO_T; +#endif + +#if 0 +/* nic_rx.h */ +typedef struct _SW_RFB_T { + + /* 4 ----------------MSDU_INFO and SW_RFB Common Fields------------------ */ + + LINK_ENTRY_T rLinkEntry; + PUINT_8 pucBuffer; /* Pointer to the associated buffer */ + + UINT_8 ucBufferSource; /* HIF TX0, HIF TX1, MAC RX, or MNG Pool */ + UINT_8 ucNetworkTypeIndex; /* Network type index that this TX packet is assocaited with */ + UINT_8 ucTC; /* 0 to 5 (used by HIF TX to increment the corresponding TC counter) */ + UINT_8 ucTID; /* Traffic Identification */ + + BOOLEAN fgIs802_11Frame; /* Set to TRUE for 802.11 frame */ + UINT_8 ucMacHeaderLength; + UINT_16 u2PayloadLength; + PUINT_8 pucMacHeader; /* 802.11 header */ + PUINT_8 pucPayload; /* 802.11 payload */ + + OS_SYSTIME rArrivalTime; /* System Timestamp (4) */ + P_STA_RECORD_T prStaRec; + +#if CFG_PROFILE_BUFFER_TRACING + ENUM_BUFFER_ACTIVITY_TYPE_T eActivity[2]; + UINT_32 rActivityTime[2]; +#endif +#if DBG && CFG_BUFFER_FREE_CHK + BOOLEAN fgBufferInSource; +#endif + + UINT_8 ucControlFlag; /* For specify some Control Flags, e.g. Basic Rate */ + + /* 4 -----------------------Non-Common ------------------------- */ + + /* For composing the HIF RX Header (TODO: move flags to ucControlFlag) */ + PUINT_8 pucHifRxPacket; /* Pointer to the Response packet to HIF RX0 or RX1 */ + UINT_16 u2HifRxPacketLength; + UINT_8 ucHeaderOffset; + UINT_8 ucHifRxPortIndex; + + UINT_16 u2SequenceControl; + BOOLEAN fgIsA4Frame; /* (For MAC RX packet parsing) set to TRUE if 4 addresses are present */ + BOOLEAN fgIsBAR; + BOOLEAN fgIsQoSData; + BOOLEAN fgIsAmsduSubframe; /* Set to TRUE for A-MSDU Subframe */ + + /* For HIF RX DMA Desc */ + BOOLEAN fgTUChecksumCheckRequired; + BOOLEAN fgIPChecksumCheckRequired; + UINT_8 ucEtherTypeOffset; + +} SW_RFB_T, *P_SW_RFB_T; +#endif + +typedef enum _ENUM_STA_REC_CMD_ACTION_T { + STA_REC_CMD_ACTION_STA = 0, + STA_REC_CMD_ACTION_BSS = 1, + STA_REC_CMD_ACTION_BSS_EXCLUDE_STA = 2 +} ENUM_STA_REC_CMD_ACTION_T, *P_ENUM_STA_REC_CMD_ACTION_T; + +#if CFG_SUPPORT_TDLS + +/* TDLS FSM */ +typedef struct _CMD_PEER_ADD_T { + + UINT_8 aucPeerMac[6]; + ENUM_STA_TYPE_T eStaType; +} CMD_PEER_ADD_T; + +typedef struct _CMD_PEER_UPDATE_HT_CAP_MCS_INFO_T { + UINT_8 arRxMask[SUP_MCS_RX_BITMASK_OCTET_NUM]; + UINT_16 u2RxHighest; + UINT_8 ucTxParams; + UINT_8 Reserved[3]; +} CMD_PEER_UPDATE_HT_CAP_MCS_INFO_T; + +typedef struct _CMD_PEER_UPDATE_VHT_CAP_MCS_INFO_T { + UINT_8 arRxMask[SUP_MCS_RX_BITMASK_OCTET_NUM]; +} CMD_PEER_UPDATE_VHT_CAP_MCS_INFO_T; + +typedef struct _CMD_PEER_UPDATE_HT_CAP_T { + UINT_16 u2CapInfo; + UINT_8 ucAmpduParamsInfo; + + /* 16 bytes MCS information */ + CMD_PEER_UPDATE_HT_CAP_MCS_INFO_T rMCS; + + UINT_16 u2ExtHtCapInfo; + UINT_32 u4TxBfCapInfo; + UINT_8 ucAntennaSelInfo; +} CMD_PEER_UPDATE_HT_CAP_T; + +typedef struct _CMD_PEER_UPDATE_VHT_CAP_T { + UINT_16 u2CapInfo; + /* 16 bytes MCS information */ + CMD_PEER_UPDATE_VHT_CAP_MCS_INFO_T rVMCS; + +} CMD_PEER_UPDATE_VHT_CAP_T; + +typedef struct _CMD_PEER_UPDATE_T { + + UINT_8 aucPeerMac[6]; + +#define CMD_PEER_UPDATE_SUP_CHAN_MAX 50 + UINT_8 aucSupChan[CMD_PEER_UPDATE_SUP_CHAN_MAX]; + + UINT_16 u2StatusCode; + +#define CMD_PEER_UPDATE_SUP_RATE_MAX 50 + UINT_8 aucSupRate[CMD_PEER_UPDATE_SUP_RATE_MAX]; + UINT_16 u2SupRateLen; + + UINT_8 UapsdBitmap; + UINT_8 UapsdMaxSp; /* MAX_SP */ + + UINT_16 u2Capability; +#define CMD_PEER_UPDATE_EXT_CAP_MAXLEN 5 + UINT_8 aucExtCap[CMD_PEER_UPDATE_EXT_CAP_MAXLEN]; + UINT_16 u2ExtCapLen; + + CMD_PEER_UPDATE_HT_CAP_T rHtCap; + CMD_PEER_UPDATE_VHT_CAP_T rVHtCap; + + BOOLEAN fgIsSupHt; + ENUM_STA_TYPE_T eStaType; + + /* TODO */ + /* So far, TDLS only a few of the parameters, the rest will be added in the future requiements */ + /* kernel 3.10 station paramenters */ + /* + * struct station_parameters { + * const u8 *supported_rates; + * struct net_device *vlan; + * u32 sta_flags_mask, sta_flags_set; + * u32 sta_modify_mask; + * int listen_interval; + * u16 aid; + * u8 supported_rates_len; + * u8 plink_action; + * u8 plink_state; + * const struct ieee80211_ht_cap *ht_capa; + * const struct ieee80211_vht_cap *vht_capa; + * u8 uapsd_queues; + * u8 max_sp; + * enum nl80211_mesh_power_mode local_pm; + * u16 capability; + * const u8 *ext_capab; + * u8 ext_capab_len; + * const u8 *supported_channels; + * u8 supported_channels_len; + * const u8 *supported_oper_classes; + * u8 supported_oper_classes_len; + * }; + */ + +} CMD_PEER_UPDATE_T; + +#endif + +#if CFG_DBG_MGT_BUF +struct MEM_TRACK { + LINK_ENTRY_T rLinkEntry; + UINT_16 u2CmdIdAndWhere; + PUINT_8 pucFileAndLine; +}; +#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 +******************************************************************************** +*/ + +#if CFG_DBG_MGT_BUF +#define cnmMgtPktAlloc(_prAdapter, _u4Length) \ + cnmPktAllocWrapper((_prAdapter), (_u4Length), (PUINT_8)__func__) + +#define cnmMgtPktFree(_prAdapter, _prMsduInfo) \ + cnmPktFreeWrapper((_prAdapter), (_prMsduInfo), (PUINT_8)__func__) + +#define cnmMemAlloc(_prAdapter, eRameType, u4Length) \ + cnmMemAllocX(_prAdapter, eRameType, u4Length, __FILE__ ":" STRLINE(__LINE__)) + +#define IS_FROM_BUF(_prAdapter, pucInfoBuffer) \ + (((PUINT_8)(pucInfoBuffer) >= (PUINT_8)_prAdapter->rMgtBufInfo.pucBuf) && \ + ((PUINT_8)(pucInfoBuffer) < (PUINT_8)_prAdapter->rMgtBufInfo.pucBuf + MGT_BUFFER_SIZE)) +#else +#define cnmMgtPktAlloc cnmPktAlloc +#define cnmMgtPktFree cnmPktFree +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +P_MSDU_INFO_T cnmPktAllocWrapper(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Length, IN PUINT_8 pucStr); + +VOID cnmPktFreeWrapper(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN PUINT_8 pucStr); + +P_MSDU_INFO_T cnmPktAlloc(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Length); + +VOID cnmPktFree(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +VOID cnmMemInit(IN P_ADAPTER_T prAdapter); + +#if CFG_DBG_MGT_BUF +PVOID cnmMemAllocX(IN P_ADAPTER_T prAdapter, IN ENUM_RAM_TYPE_T eRamType, IN UINT_32 u4Length, + PUINT_8 fileAndLine); +#else +PVOID cnmMemAlloc(IN P_ADAPTER_T prAdapter, IN ENUM_RAM_TYPE_T eRamType, IN UINT_32 u4Length); +#endif + +VOID cnmMemFree(IN P_ADAPTER_T prAdapter, IN PVOID pvMemory); + +VOID cnmStaRecInit(IN P_ADAPTER_T prAdapter); + +P_STA_RECORD_T +cnmStaRecAlloc(IN P_ADAPTER_T prAdapter, IN ENUM_STA_TYPE_T eStaType, IN UINT_8 ucBssIndex, IN PUINT_8 pucMacAddr); + +VOID cnmStaRecFree(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +VOID cnmStaFreeAllStaByNetwork(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex, UINT_8 ucStaRecIndexExcluded); + +P_STA_RECORD_T cnmGetStaRecByIndex(IN P_ADAPTER_T prAdapter, IN UINT_8 ucIndex); + +P_STA_RECORD_T cnmGetStaRecByAddress(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex, UINT_8 aucPeerMACAddress[]); + +VOID cnmStaRecChangeState(IN P_ADAPTER_T prAdapter, IN OUT P_STA_RECORD_T prStaRec, IN UINT_8 ucNewState); + +VOID cnmDumpStaRec(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIdx); + +VOID cnmDumpMemoryStatus(IN P_ADAPTER_T prAdapter); + +#if CFG_SUPPORT_TDLS +WLAN_STATUS /* TDLS_STATUS */ +cnmPeerAdd(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, PUINT_32 pu4SetInfoLen); + +WLAN_STATUS /* TDLS_STATUS */ +cnmPeerUpdate(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, PUINT_32 pu4SetInfoLen); + +P_STA_RECORD_T cnmGetTdlsPeerByAddress(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex, UINT_8 aucPeerMACAddress[]); +#endif +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#ifndef _lint +/* Kevin: we don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + * We'll need this for porting driver to different RTOS. + */ +static __KAL_INLINE__ VOID cnmMemDataTypeCheck(VOID) +{ +#if 0 + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, rLinkEntry) == 0); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, rLinkEntry) == OFFSET_OF(SW_RFB_T, rLinkEntry)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, pucBuffer) == OFFSET_OF(SW_RFB_T, pucBuffer)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucBufferSource) == OFFSET_OF(SW_RFB_T, ucBufferSource)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, pucMacHeader) == OFFSET_OF(SW_RFB_T, pucMacHeader)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucMacHeaderLength) == + OFFSET_OF(SW_RFB_T, ucMacHeaderLength)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, pucPayload) == OFFSET_OF(SW_RFB_T, pucPayload)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, u2PayloadLength) == OFFSET_OF(SW_RFB_T, u2PayloadLength)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, prStaRec) == OFFSET_OF(SW_RFB_T, prStaRec)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucNetworkTypeIndex) == + OFFSET_OF(SW_RFB_T, ucNetworkTypeIndex)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucTID) == OFFSET_OF(SW_RFB_T, ucTID)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, fgIs802_11Frame) == OFFSET_OF(SW_RFB_T, fgIs802_11Frame)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucControlFlag) == OFFSET_OF(SW_RFB_T, ucControlFlag)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, rArrivalTime) == OFFSET_OF(SW_RFB_T, rArrivalTime)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucTC) == OFFSET_OF(SW_RFB_T, ucTC)); + +#if CFG_PROFILE_BUFFER_TRACING + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, eActivity[0]) == OFFSET_OF(SW_RFB_T, eActivity[0])); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, rActivityTime[0]) == OFFSET_OF(SW_RFB_T, + rActivityTime[0])); +#endif + +#if DBG && CFG_BUFFER_FREE_CHK + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, fgBufferInSource) == OFFSET_OF(SW_RFB_T, + fgBufferInSource)); +#endif + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(STA_RECORD_T, rLinkEntry) == 0); + + return; +#endif +} +#endif /* _lint */ + +#endif /* _CNM_MEM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/cnm_scan.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/cnm_scan.h new file mode 100644 index 0000000000000..7b328276bd6d0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/cnm_scan.h @@ -0,0 +1,124 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: @(#) +*/ + +/*! \file "cnm_scan.h" + * \brief +*/ + +#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 54 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* The type of Scan Source */ +typedef enum _ENUM_SCN_REQ_SOURCE_T { + SCN_REQ_SOURCE_HEM = 0, + SCN_REQ_SOURCE_NET_FSM, + SCN_REQ_SOURCE_ROAMING, /* ROAMING Module is independent of AIS FSM */ + SCN_REQ_SOURCE_OBSS, /* 2.4G OBSS scan */ + SCN_REQ_SOURCE_NUM +} ENUM_SCN_REQ_SOURCE_T, *P_ENUM_SCN_REQ_SOURCE_T; + +typedef enum _ENUM_SCAN_PROFILE_T { + SCAN_PROFILE_FULL = 0, + SCAN_PROFILE_PARTIAL, + SCAN_PROFILE_VOIP, + SCAN_PROFILE_FULL_2G4, + SCAN_PROFILE_NUM +} ENUM_SCAN_PROFILE_T, *P_ENUM_SCAN_PROFILE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#if 0 +VOID cnmScanInit(VOID); + +VOID cnmScanRunEventScanRequest(IN P_MSG_HDR_T prMsgHdr); + +BOOLEAN cnmScanRunEventScanAbort(IN P_MSG_HDR_T prMsgHdr); + +VOID cnmScanProfileSelection(VOID); + +VOID cnmScanProcessStart(VOID); + +VOID cnmScanProcessStop(VOID); + +VOID cnmScanRunEventReqAISAbsDone(IN P_MSG_HDR_T prMsgHdr); + +VOID cnmScanRunEventCancelAISAbsDone(IN P_MSG_HDR_T prMsgHdr); + +VOID cnmScanPartialScanTimeout(UINT_32 u4Param); + +VOID cnmScanRunEventScnFsmComplete(IN P_MSG_HDR_T prMsgHdr); +#endif + +#endif /* _CNM_SCAN_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/cnm_timer.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/cnm_timer.h new file mode 100644 index 0000000000000..1163d0ef0a04c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/cnm_timer.h @@ -0,0 +1,223 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/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. + */ + +#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 +#undef USEC_PER_SEC +#define USEC_PER_SEC 1000000 + +#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 */ + +#define OBSS_SCAN_MIN_INTERVAL 10 /* In unit of 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 + +enum ENUM_TIMER_WAKELOCK_TYPE_T { + TIMER_WAKELOCK_AUTO, + TIMER_WAKELOCK_NONE, + TIMER_WAKELOCK_REQUEST, + TIMER_WAKELOCK_NUM +}; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef VOID(*PFN_MGMT_TIMEOUT_FUNC) (P_ADAPTER_T, ULONG); + +typedef struct _TIMER_T { + LINK_ENTRY_T rLinkEntry; + OS_SYSTIME rExpiredSysTime; + UINT_16 u2Minutes; + UINT_16 u2Reserved; + ULONG ulDataPtr; + PFN_MGMT_TIMEOUT_FUNC pfMgmtTimeOutFunc; + enum ENUM_TIMER_WAKELOCK_TYPE_T eType; + PUINT_8 pucFileAndLineForNextTimer; + PUINT_8 pucFileAndLineOwn; +} 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) * USEC_PER_SEC) / KAL_HZ) + +/* 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)) + +/* for debugging the timer abnoral issue */ +#define STRL(x) #x +#define STRLINE(x) STRL(x) +#define cnmTimerStartTimer(prAdapter, prTimer, u4TimeoutMs) \ + cnmTimerStartTimerx(prAdapter, prTimer, u4TimeoutMs, __FILE__ STRLINE(__LINE__)) +/******************************************************************************* +* 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 cnmTimerInitTimerOption(IN P_ADAPTER_T prAdapter, + IN P_TIMER_T prTimer, + IN PFN_MGMT_TIMEOUT_FUNC pfFunc, + IN ULONG ulDataPtr, + IN enum ENUM_TIMER_WAKELOCK_TYPE_T eType); + +VOID cnmTimerStopTimer(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer); + +VOID cnmTimerStartTimerx(IN P_ADAPTER_T prAdapter, + IN P_TIMER_T prTimer, IN UINT_32 u4TimeoutMs, IN PUINT_8 fileAndLine); + +VOID cnmTimerDoTimeOutCheck(IN P_ADAPTER_T prAdapter); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +static __KAL_INLINE__ INT_32 timerPendingTimer(IN P_TIMER_T prTimer) +{ + ASSERT(prTimer); + + return prTimer->rLinkEntry.prNext != NULL; +} + +static __KAL_INLINE__ VOID cnmTimerInitTimer(IN P_ADAPTER_T prAdapter, + IN P_TIMER_T prTimer, + IN PFN_MGMT_TIMEOUT_FUNC pfFunc, + IN ULONG ulDataPtr) +{ + cnmTimerInitTimerOption(prAdapter, prTimer, pfFunc, ulDataPtr, TIMER_WAKELOCK_AUTO); +} + +#endif /* _CNM_TIMER_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/hem_mbox.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/hem_mbox.h new file mode 100644 index 0000000000000..5dfd9b88032ec --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/hem_mbox.h @@ -0,0 +1,281 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/hem_mbox.h#3 +*/ + +/* + * ! \file hem_mbox.h + * \brief + */ + +#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_REQ_V3, /* AIS notify SCN for starting scan with random MAC address */ + 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_OID_SAA_FSM_CONTINUE, /* OID notify SAA to continue to do authentication/association fsm for FT */ + MID_OID_SAA_FSM_EXTERNAL_AUTH, /*OID notify SAA to handle external auth status*/ + 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 */ + + /*--------------------------------------------------*/ + /* AIS MGMT-TX Support */ + /*--------------------------------------------------*/ + MID_MNY_AIS_REMAIN_ON_CHANNEL, + MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL, + MID_MNY_AIS_MGMT_TX, + MID_MNY_CNM_REQ_CH_UTIL, + MID_CNM_AIS_RSP_CH_UTIL, + MID_MNY_CNM_SCAN_CONTINUE, + MID_WNM_AIS_BSS_TRANSITION, + MID_OID_WMM_TSPEC_OPERATE, + MID_RLM_RM_SCHEDULE, + MID_MNY_P2P_ACS, + MID_TOTAL_NUM +} ENUM_MSG_ID_T, *P_ENUM_MSG_ID_T; + +/* Message header of inter-components */ +struct _MSG_HDR_T { + LINK_ENTRY_T rLinkEntry; + ENUM_MSG_ID_T eMsgId; +}; + +typedef VOID(*PFN_MSG_HNDL_FUNC) (P_ADAPTER_T, P_MSG_HDR_T); + +typedef struct _MSG_HNDL_ENTRY { + ENUM_MSG_ID_T eMsgId; + PFN_MSG_HNDL_FUNC pfMsgHndl; +} MSG_HNDL_ENTRY_T, *P_MSG_HNDL_ENTRY_T; + +typedef enum _EUNM_MSG_SEND_METHOD_T { + MSG_SEND_METHOD_BUF = 0, /* + * Message is put in the queue and will be + * executed when mailbox is checked. + */ + MSG_SEND_METHOD_UNBUF /* + * The handler function is called immediately + * in the same context of the sender + */ +} EUNM_MSG_SEND_METHOD_T, *P_EUNM_MSG_SEND_METHOD_T; + +typedef enum _ENUM_MBOX_ID_T { + MBOX_ID_0 = 0, + MBOX_ID_TOTAL_NUM +} ENUM_MBOX_ID_T, *P_ENUM_MBOX_ID_T; + +/* Define Mailbox structure */ +typedef struct _MBOX_T { + LINK_T rLinkHead; +} MBOX_T, *P_MBOX_T; + +typedef struct _MSG_SAA_FSM_START_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + P_STA_RECORD_T prStaRec; +} MSG_SAA_FSM_START_T, *P_MSG_SAA_FSM_START_T; + +typedef struct _MSG_SAA_FSM_COMP_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + WLAN_STATUS rJoinStatus; + P_STA_RECORD_T prStaRec; + P_SW_RFB_T prSwRfb; +} MSG_SAA_FSM_COMP_T, *P_MSG_SAA_FSM_COMP_T; + +typedef struct _MSG_SAA_FSM_ABORT_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + P_STA_RECORD_T prStaRec; +} MSG_SAA_FSM_ABORT_T, *P_MSG_SAA_FSM_ABORT_T; + +typedef struct _MSG_CONNECTION_ABORT_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucNetTypeIndex; +} MSG_CONNECTION_ABORT_T, *P_MSG_CONNECTION_ABORT_T; + +typedef struct _MSG_REMAIN_ON_CHANNEL_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + ENUM_BAND_T eBand; + ENUM_CHNL_EXT_T eSco; + UINT_8 ucChannelNum; + UINT_32 u4DurationMs; + UINT_64 u8Cookie; +} MSG_REMAIN_ON_CHANNEL_T, *P_MSG_REMAIN_ON_CHANNEL_T; + +typedef struct _MSG_CANCEL_REMAIN_ON_CHANNEL_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_64 u8Cookie; +} MSG_CANCEL_REMAIN_ON_CHANNEL_T, *P_MSG_CANCEL_REMAIN_ON_CHANNEL_T; + +typedef struct _MSG_MGMT_TX_REQUEST_T { + MSG_HDR_T rMsgHdr; + P_MSDU_INFO_T prMgmtMsduInfo; + UINT_64 u8Cookie; /* For indication. */ + BOOLEAN fgNoneCckRate; + BOOLEAN fgIsWaitRsp; +} MSG_MGMT_TX_REQUEST_T, *P_MSG_MGMT_TX_REQUEST_T; + +struct MSG_SAA_FT_CONTINUE { + MSG_HDR_T rMsgHdr; + P_STA_RECORD_T prStaRec; + BOOLEAN fgFTRicRequest; /* if fgFTRicRequest is TRUE, then will do FT Resource Request Protocol */ +}; + +struct MSG_SAA_EXTERNAL_AUTH_DONE { + MSG_HDR_T rMsgHdr; + P_STA_RECORD_T prStaRec; + UINT_16 status; +}; + +/* specific message data types */ +typedef MSG_SAA_FSM_START_T MSG_JOIN_REQ_T, *P_MSG_JOIN_REQ_T; +typedef MSG_SAA_FSM_COMP_T MSG_JOIN_COMP_T, *P_MSG_JOIN_COMP_T; +typedef MSG_SAA_FSM_ABORT_T MSG_JOIN_ABORT_T, *P_MSG_JOIN_ABORT_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID mboxSetup(IN P_ADAPTER_T prAdapter, IN ENUM_MBOX_ID_T eMboxId); + +VOID +mboxSendMsg(IN P_ADAPTER_T prAdapter, + IN ENUM_MBOX_ID_T eMboxId, IN P_MSG_HDR_T prMsg, IN EUNM_MSG_SEND_METHOD_T eMethod); + +VOID mboxRcvAllMsg(IN P_ADAPTER_T prAdapter, IN ENUM_MBOX_ID_T eMboxId); + +VOID mboxInitialize(IN P_ADAPTER_T prAdapter); + +VOID mboxDestroy(IN P_ADAPTER_T prAdapter); + +VOID mboxDummy(IN P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _HEM_MBOX_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/hs20.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/hs20.h new file mode 100644 index 0000000000000..b002d51a52671 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/hs20.h @@ -0,0 +1,144 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file hs20.h + * \brief This file contains the function declaration for hs20.c. + */ + +#ifndef _HS20_H +#define _HS20_H + +#if CFG_SUPPORT_PASSPOINT +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************** + */ +#define BSSID_POOL_MAX_SIZE 8 +#define HS20_SIGMA_SCAN_RESULT_TIMEOUT 30 /* sec */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************** + */ + +#if CFG_ENABLE_GTK_FRAME_FILTER +/*For GTK Frame Filter*/ +typedef struct _IPV4_NETWORK_ADDRESS_LIST { + UINT_8 ucAddrCount; + IPV4_NETWORK_ADDRESS arNetAddr[1]; +} IPV4_NETWORK_ADDRESS_LIST, *P_IPV4_NETWORK_ADDRESS_LIST; +#endif + +/* Entry of BSSID Pool - For SIGMA Test */ +typedef struct _BSSID_ENTRY_T { + UINT_8 aucBSSID[MAC_ADDR_LEN]; +} BSSID_ENTRY_T, P_HS20_BSSID_POOL_ENTRY_T; + +struct _HS20_INFO_T { + /*Hotspot 2.0 Information */ + UINT_8 aucHESSID[MAC_ADDR_LEN]; + UINT_8 ucAccessNetworkOptions; + UINT_8 ucVenueGroup; /* VenueInfo - Group */ + UINT_8 ucVenueType; + UINT_8 ucHotspotConfig; + + /*Roaming Consortium Information */ + /* PARAM_HS20_ROAMING_CONSORTIUM_INFO rRCInfo; */ + + /*Hotspot 2.0 dummy AP Info */ + + /*Time Advertisement Information */ + /* UINT_32 u4UTCOffsetTime; */ + /* UINT_8 aucTimeZone[ELEM_MAX_LEN_TIME_ZONE]; */ + /* UINT_8 ucLenTimeZone; */ + + /* For SIGMA Test */ + /* BSSID Pool */ + BSSID_ENTRY_T arBssidPool[BSSID_POOL_MAX_SIZE]; + UINT_8 ucNumBssidPoolEntry; + BOOLEAN fgIsHS2SigmaMode; +}; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************** + */ + +/*For GTK Frame Filter*/ +#if DBG +#define FREE_IPV4_NETWORK_ADDR_LIST(_prAddrList) \ + { \ + UINT_32 u4Size = OFFSET_OF(IPV4_NETWORK_ADDRESS_LIST, arNetAddr) + \ + (((_prAddrList)->ucAddrCount) * sizeof(IPV4_NETWORK_ADDRESS)); \ + kalMemFree((_prAddrList), VIR_MEM_TYPE, u4Size); \ + (_prAddrList) = NULL; \ + } +#else +#define FREE_IPV4_NETWORK_ADDR_LIST(_prAddrList) \ + { \ + kalMemFree((_prAddrList), VIR_MEM_TYPE, 0); \ + (_prAddrList) = NULL; \ + } +#endif + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************** + */ +VOID hs20FillExtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo); + +VOID hs20FillProreqExtCapIE(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucIE); + +VOID hs20FillHS20IE(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucIE); + +UINT_32 hs20CalculateHS20RelatedIEForProbeReq(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucTargetBSSID); + +WLAN_STATUS hs20GenerateHS20RelatedIEForProbeReq(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucTargetBSSID, OUT PUINT_8 prIE); + +BOOLEAN hs20IsGratuitousArp(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prCurrSwRfb); + +BOOLEAN hs20IsUnsolicitedNeighborAdv(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prCurrSwRfb); + +#if CFG_ENABLE_GTK_FRAME_FILTER +BOOLEAN hs20IsForgedGTKFrame(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_SW_RFB_T prCurrSwRfb); +#endif + +BOOLEAN hs20IsUnsecuredFrame(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_SW_RFB_T prCurrSwRfb); + +BOOLEAN hs20IsFrameFilterEnabled(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo); + +WLAN_STATUS hs20SetBssidPool(IN P_ADAPTER_T prAdapter, IN PVOID pvBuffer, IN ENUM_KAL_NETWORK_TYPE_INDEX_T eNetTypeIdx); + +#endif /* CFG_SUPPORT_PASSPOINT */ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/mib.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/mib.h new file mode 100644 index 0000000000000..9cc9eeefd0c94 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/mib.h @@ -0,0 +1,136 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/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. + */ + +#ifndef _MIB_H +#define _MIB_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************** + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************** + */ +/* Entry in SMT AuthenticationAlgorithms Table: dot11AuthenticationAlgorithmsEntry */ +typedef struct _DOT11_AUTHENTICATION_ALGORITHMS_ENTRY { + BOOLEAN dot11AuthenticationAlgorithmsEnable; /* dot11AuthenticationAlgorithmsEntry 3 */ +} DOT11_AUTHENTICATION_ALGORITHMS_ENTRY, *P_DOT11_AUTHENTICATION_ALGORITHMS_ENTRY; + +/* Entry in SMT dot11RSNAConfigPairwiseCiphersTalbe Table: dot11RSNAConfigPairwiseCiphersEntry */ +typedef struct _DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY { + UINT_32 dot11RSNAConfigPairwiseCipher; /* dot11RSNAConfigPairwiseCiphersEntry 2 */ + BOOLEAN dot11RSNAConfigPairwiseCipherEnabled; /* dot11RSNAConfigPairwiseCiphersEntry 3 */ +} DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY, *P_DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY; + +/* Entry in SMT dot11RSNAConfigAuthenticationSuitesTalbe Table: dot11RSNAConfigAuthenticationSuitesEntry */ +typedef struct _DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY { + UINT_32 dot11RSNAConfigAuthenticationSuite; /* dot11RSNAConfigAuthenticationSuitesEntry 2 */ + BOOLEAN dot11RSNAConfigAuthenticationSuiteEnabled; /* dot11RSNAConfigAuthenticationSuitesEntry 3 */ +} DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY, *P_DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY; + +/* ----- IEEE 802.11 MIB Major sections ----- */ +typedef struct _IEEE_802_11_MIB_T { + /* dot11PrivacyTable (dot11smt 5) */ + UINT_8 dot11WEPDefaultKeyID; /* dot11PrivacyEntry 2 */ + BOOLEAN dot11TranmitKeyAvailable; + UINT_32 dot11WEPICVErrorCount; /* dot11PrivacyEntry 5 */ + UINT_32 dot11WEPExcludedCount; /* dot11PrivacyEntry 6 */ + + /* dot11RSNAConfigTable (dot11smt 8) */ + UINT_32 dot11RSNAConfigGroupCipher; /* dot11RSNAConfigEntry 4 */ + + /* dot11RSNAConfigPairwiseCiphersTable (dot11smt 9) */ + DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY dot11RSNAConfigPairwiseCiphersTable[MAX_NUM_SUPPORTED_CIPHER_SUITES]; + + /* dot11RSNAConfigAuthenticationSuitesTable (dot11smt 10) */ + DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY + dot11RSNAConfigAuthenticationSuitesTable[MAX_NUM_SUPPORTED_AKM_SUITES]; + +#if 0 /* SUPPORT_WAPI */ + BOOLEAN fgWapiKeyInstalled; + PARAM_WPI_KEY_T rWapiPairwiseKey[2]; + BOOLEAN fgPairwiseKeyUsed[2]; + UINT_8 ucWpiActivedPWKey; /* Must be 0 or 1, by wapi spec */ + PARAM_WPI_KEY_T rWapiGroupKey[2]; + BOOLEAN fgGroupKeyUsed[2]; +#endif +} IEEE_802_11_MIB_T, *P_IEEE_802_11_MIB_T; + +/* ------------------ IEEE 802.11 non HT PHY characteristics ---------------- */ +typedef const struct _NON_HT_PHY_ATTRIBUTE_T { + UINT_16 u2SupportedRateSet; + + BOOLEAN fgIsShortPreambleOptionImplemented; + + BOOLEAN fgIsShortSlotTimeOptionImplemented; +} NON_HT_PHY_ATTRIBUTE_T, *P_NON_HT_PHY_ATTRIBUTE_T; + +typedef const struct _NON_HT_ADHOC_MODE_ATTRIBUTE_T { + ENUM_PHY_TYPE_INDEX_T ePhyTypeIndex; + + UINT_16 u2BSSBasicRateSet; +} NON_HT_ADHOC_MODE_ATTRIBUTE_T, *P_NON_HT_ADHOC_MODE_ATTRIBUTE_T; + +typedef NON_HT_ADHOC_MODE_ATTRIBUTE_T NON_HT_AP_MODE_ATTRIBUTE_T; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************** + */ +extern NON_HT_PHY_ATTRIBUTE_T rNonHTPhyAttributes[]; +extern NON_HT_ADHOC_MODE_ATTRIBUTE_T rNonHTAdHocModeAttributes[]; +extern NON_HT_AP_MODE_ATTRIBUTE_T rNonHTApModeAttributes[]; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************** + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************** + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************** + */ + +#endif /* _MIB_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_assoc.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_assoc.h new file mode 100644 index 0000000000000..e1f44c252a945 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_assoc.h @@ -0,0 +1,65 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file p2p_assoc.h + * \brief This file contains the Wi-Fi Direct ASSOC REQ/RESP of + * IEEE 802.11 family for MediaTek 802.11 Wireless LAN Adapters. + */ + +#ifndef _P2P_ASSOC_H +#define _P2P_ASSOC_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************** + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************** + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************** + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************** + */ + +PUINT_8 p2pBuildReAssocReqFrameCommonIEs(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN PUINT_8 pucBuffer); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_bss.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_bss.h new file mode 100644 index 0000000000000..58a89922cc836 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_bss.h @@ -0,0 +1,71 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/mgmt/p2p_bss.h#2 +*/ + +/* + * ! \file "p2p_bss.h" + * \brief In this file we define the function prototype used in p2p BSS/IBSS. + * + * The file contains the function declarations and defines for used in BSS/IBSS. + */ + +#ifndef _P2P_BSS_H +#define _P2P_BSS_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +UINT_32 p2pGetTxProbRspIeTableSize(VOID); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_dev.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_dev.h new file mode 100644 index 0000000000000..3070dfa4a765f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_dev.h @@ -0,0 +1,222 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +typedef enum _ENUM_P2P_DEV_STATE_T { + P2P_DEV_STATE_IDLE = 0, + P2P_DEV_STATE_SCAN, + P2P_DEV_STATE_REQING_CHANNEL, + P2P_DEV_STATE_CHNL_ON_HAND, + P2P_DEV_STATE_OFF_CHNL_TX, /* Requesting Channel to Send Specific Frame. */ + P2P_DEV_STATE_NUM +} ENUM_P2P_DEV_STATE_T, *P_ENUM_P2P_DEV_STATE_T; + +/*-------------------- EVENT MESSAGE ---------------------*/ +typedef struct _MSG_P2P_SCAN_REQUEST_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucBssIdx; + ENUM_SCAN_TYPE_T eScanType; + P_P2P_SSID_STRUCT_T prSSID; + INT_32 i4SsidNum; + UINT_32 u4NumChannel; + PUINT_8 pucIEBuf; + UINT_32 u4IELen; + BOOLEAN fgIsAbort; + enum ENUM_SCAN_REASON eScanReason; + 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; + ENUM_CH_REQ_TYPE_T eChnlReqType; +} MSG_P2P_CHNL_REQUEST_T, *P_MSG_P2P_CHNL_REQUEST_T; + +typedef struct _MSG_P2P_MGMT_TX_REQUEST_T { + MSG_HDR_T rMsgHdr; + UINT_8 ucBssIdx; + P_MSDU_INFO_T prMgmtMsduInfo; + UINT_64 u8Cookie; /* For indication. */ + BOOLEAN fgNoneCckRate; + BOOLEAN fgIsOffChannel; + RF_CHANNEL_INFO_T rChannelInfo; /* Off channel TX. */ + ENUM_CHNL_EXT_T eChnlExt; + BOOLEAN fgIsWaitRsp; +} MSG_P2P_MGMT_TX_REQUEST_T, *P_MSG_P2P_MGMT_TX_REQUEST_T; + +#define P2P_DEV_EXTEND_CHAN_TIME 50 + +#if CFG_SUPPORT_WFD + +#define WFD_FLAGS_DEV_INFO_VALID BIT(0) /* 1. WFD_DEV_INFO, 2. WFD_CTRL_PORT, 3. WFD_MAT_TP. */ +#define WFD_FLAGS_SINK_INFO_VALID BIT(1) /* 1. WFD_SINK_STATUS, 2. WFD_SINK_MAC. */ +#define WFD_FLAGS_ASSOC_MAC_VALID BIT(2) /* 1. WFD_ASSOC_MAC. */ +#define WFD_FLAGS_EXT_CAPABILITY_VALID BIT(3) /* 1. WFD_EXTEND_CAPABILITY. */ + +struct _WFD_CFG_SETTINGS_T { + UINT_32 u4WfdCmdType; + UINT_8 ucWfdEnable; + UINT_8 ucWfdCoupleSinkStatus; + UINT_8 ucWfdSessionAvailable; /* 0: NA 1:Set 2:Clear */ + UINT_8 ucWfdSigmaMode; + UINT_16 u2WfdDevInfo; + UINT_16 u2WfdControlPort; + UINT_16 u2WfdMaximumTp; + UINT_16 u2WfdExtendCap; + UINT_8 aucWfdCoupleSinkAddress[MAC_ADDR_LEN]; + UINT_8 aucWfdAssociatedBssid[MAC_ADDR_LEN]; + UINT_8 aucWfdVideoIp[4]; + UINT_8 aucWfdAudioIp[4]; + UINT_16 u2WfdVideoPort; + UINT_16 u2WfdAudioPort; + UINT_32 u4WfdFlag; + UINT_32 u4WfdPolicy; + UINT_32 u4WfdState; + UINT_8 aucWfdSessionInformationIE[24 * 8]; + UINT_16 u2WfdSessionInformationIELen; + UINT_8 aucReserved1[2]; + UINT_8 aucWfdPrimarySinkMac[MAC_ADDR_LEN]; + UINT_8 aucWfdSecondarySinkMac[MAC_ADDR_LEN]; + UINT_32 u4WfdAdvancedFlag; + /* Group 1 64 bytes */ + UINT_8 aucWfdLocalIp[4]; + UINT_16 u2WfdLifetimeAc2; /* Unit is 2 TU */ + UINT_16 u2WfdLifetimeAc3; /* Unit is 2 TU */ + UINT_16 u2WfdCounterThreshold; /* Unit is ms */ + UINT_8 aucReverved2[54]; + /* Group 2 64 bytes */ + UINT_8 aucReverved3[64]; + /* Group 3 64 bytes */ + UINT_8 aucReverved4[64]; +}; + +#endif + +/*-------------------- P2P FSM ACTION STRUCT ---------------------*/ + +typedef struct _P2P_OFF_CHNL_TX_REQ_INFO_T { + LINK_ENTRY_T rLinkEntry; + P_MSDU_INFO_T prMgmtTxMsdu; + BOOLEAN fgNoneCckRate; + RF_CHANNEL_INFO_T rChannelInfo; /* Off channel TX. */ + ENUM_CHNL_EXT_T eChnlExt; + BOOLEAN fgIsWaitRsp; /* See if driver should keep at the same channel. */ +} P2P_OFF_CHNL_TX_REQ_INFO_T, *P_P2P_OFF_CHNL_TX_REQ_INFO_T; + +typedef struct _P2P_MGMT_TX_REQ_INFO_T { + LINK_T rP2pTxReqLink; + P_MSDU_INFO_T prMgmtTxMsdu; + BOOLEAN fgIsWaitRsp; +} P2P_MGMT_TX_REQ_INFO_T, *P_P2P_MGMT_TX_REQ_INFO_T; + +struct _P2P_DEV_FSM_INFO_T { + UINT_8 ucBssIndex; + /* State related. */ + ENUM_P2P_DEV_STATE_T eCurrentState; + + /* Channel related. */ + P2P_CHNL_REQ_INFO_T rChnlReqInfo; + + /* Scan related. */ + P2P_SCAN_REQ_INFO_T rScanReqInfo; + + /* Mgmt tx related. */ + P2P_MGMT_TX_REQ_INFO_T rMgmtTxInfo; + + /* FSM Timer */ + TIMER_T rP2pFsmTimeoutTimer; + + /* Packet filter for P2P module. */ + UINT_32 u4P2pPacketFilter; +}; + +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 + +struct MSG_P2P_ACS_REQUEST { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucRoleIdx; + BOOLEAN fgIsHtEnable; + BOOLEAN fgIsHt40Enable; + BOOLEAN fgIsVhtEnable; + ENUM_MAX_BANDWIDTH_SETTING eChnlBw; + enum P2P_VENDOR_ACS_HW_MODE eHwMode; + UINT_32 u4NumChannel; + RF_CHANNEL_INFO_T arChannelListInfo[1]; +}; + +/*========================= Initial ============================*/ + +UINT_8 p2pDevFsmInit(IN P_ADAPTER_T prAdapter); + +VOID p2pDevFsmUninit(IN P_ADAPTER_T prAdapter); + +/*========================= FUNCTIONs ============================*/ + +VOID +p2pDevFsmStateTransition(IN P_ADAPTER_T prAdapter, IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo, IN ENUM_P2P_DEV_STATE_T + eNextState); + +VOID p2pDevFsmRunEventAbort(IN P_ADAPTER_T prAdapter, IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo); + +VOID p2pDevFsmRunEventTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); + +/*================ Message Event =================*/ +VOID p2pDevFsmRunEventScanRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID +p2pDevFsmRunEventScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr, IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo); + +VOID p2pDevFsmRunEventChannelRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pDevFsmRunEventChannelAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID +p2pDevFsmRunEventChnlGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr, IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo); + +VOID p2pDevFsmRunEventMgmtTx(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +WLAN_STATUS +p2pDevFsmRunEventMgmtFrameTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T + rTxDoneStatus); + +VOID p2pDevFsmRunEventMgmtFrameRegister(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +/* /////////////////////////////// */ + +VOID p2pFsmRunEventScanRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventScanDone(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 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); + +#if CFG_SUPPORT_WFD +VOID p2pFsmRunEventWfdSettingUpdate(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_dev_state.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_dev_state.h new file mode 100644 index 0000000000000..580af8d128626 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_dev_state.h @@ -0,0 +1,60 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _P2P_DEV_STATE_H +#define _P2P_DEV_STATE_H + +BOOLEAN +p2pDevStateInit_IDLE(IN P_ADAPTER_T prAdapter, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, OUT P_ENUM_P2P_DEV_STATE_T peNextState); + +VOID p2pDevStateAbort_IDLE(IN P_ADAPTER_T prAdapter); + +BOOLEAN +p2pDevStateInit_REQING_CHANNEL(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucBssIdx, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, OUT P_ENUM_P2P_DEV_STATE_T peNextState); + +VOID +p2pDevStateAbort_REQING_CHANNEL(IN P_ADAPTER_T prAdapter, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, IN ENUM_P2P_DEV_STATE_T eNextState); + +VOID +p2pDevStateInit_CHNL_ON_HAND(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, + IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo); + +VOID +p2pDevStateAbort_CHNL_ON_HAND(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, + IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, + IN ENUM_P2P_DEV_STATE_T eNextState); + +VOID p2pDevStateInit_SCAN(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo); + +VOID p2pDevStateAbort_SCAN(IN P_ADAPTER_T prAdapter, IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo); + +BOOLEAN +p2pDevStateInit_OFF_CHNL_TX(IN P_ADAPTER_T prAdapter, + IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, + IN P_P2P_MGMT_TX_REQ_INFO_T prP2pMgmtTxInfo, OUT P_ENUM_P2P_DEV_STATE_T peNextState); + +VOID +p2pDevStateAbort_OFF_CHNL_TX(IN P_ADAPTER_T prAdapter, + IN P_P2P_MGMT_TX_REQ_INFO_T prP2pMgmtTxInfo, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, IN ENUM_P2P_DEV_STATE_T eNextState); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_fsm.h new file mode 100644 index 0000000000000..97baad0464ce8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_fsm.h @@ -0,0 +1,1235 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** 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. + */ + +#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; + +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; + + /* Auto channel selection related. */ + struct P2P_ACS_REQ_INFO rAcsReqInfo; + + /* 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; +}; + +/*---------------- Messages -------------------*/ + +/******************************************************************************* + * 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 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); + +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); + +/*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_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_CTWINDOW_DEFAULT 25 /* in TU=(1024usec) */ +/* P2P 3.1.2.1.3 - Find Phase */ +#define P2P_MAX_DISCOVERABLE_INTERVAL 8 /* 3 */ +#define P2P_MIN_DISCOVERABLE_INTERVAL 5 /* 1 */ +#define P2P_LISTEN_SCAN_UNIT 100 /* MS */ +/* FSM Time Related constrain. */ +#define P2P_SERACH_STATE_PERIOD_MS 1000 /* Deprecated. */ +#define P2P_GO_CHANNEL_STAY_INTERVAL 1000 +#define P2P_GO_NEGO_TIMEOUT_MS 500 +#define P2P_CONNECTION_TIMEOUT_SEC 120 +#define P2P_INVITAION_TIMEOUT_MS 500 /* Timeout Wait Invitation Resonse. */ +#define P2P_PROVISION_DISCOVERY_TIMEOUT_MS 500 /* Timeout Wait Provision Discovery Resonse. */ +/* 3 */ +/*#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.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 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_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 */ + +#if 0 +/* 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; +#endif + +/* 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.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; + +/* 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; + +/* 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 enum _ENUM_CONFIG_METHOD_SEL { + ENUM_CONFIG_METHOD_SEL_AUTO, + ENUM_CONFIG_METHOD_SEL_USER, + ENUM_CONFIG_METHOD_SEL_NUM +} ENUM_CONFIG_METHOD_SEL, *P_ENUM_CONFIG_METHOD_SEL; + +typedef enum _ENUM_P2P_FORMATION_POLICY { + ENUM_P2P_FORMATION_POLICY_AUTO = 0, + ENUM_P2P_FORMATION_POLICY_PASSIVE, /* Device would wait GO NEGO REQ instead of sending it actively. */ + ENUM_P2P_FORMATION_POLICY_NUM +} ENUM_P2P_FORMATION_POLICY, P_ENUM_P2P_FORMATION_POLICY; + +typedef enum _ENUM_P2P_INVITATION_POLICY { + ENUM_P2P_INVITATION_POLICY_USER = 0, + ENUM_P2P_INVITATION_POLICY_ACCEPT_FIRST, + ENUM_P2P_INVITATION_POLICY_DENY_ALL, + ENUM_P2P_INVITATION_POLICY_NUM +} ENUM_P2P_INVITATION_POLICY, P_ENUM_P2P_INVITATION_POLICY; + +/* 3 --------------- Data Structure for P2P Operation --------------- */ +/* 3 Session for CONNECTION SETTINGS of P2P */ +struct _P2P_CONNECTION_SETTINGS_T { + UINT_8 ucDevNameLen; + UINT_8 aucDevName[WPS_ATTRI_MAX_LEN_DEVICE_NAME]; + + DEVICE_TYPE_T rPrimaryDevTypeBE; + + ENUM_P2P_FORMATION_POLICY eFormationPolicy; /* Formation Policy. */ + + /*------------WSC Related Param---------------*/ + UINT_16 u2ConfigMethodsSupport; /* Preferred configure method. + * Some device may not have keypad. + */ + ENUM_CONFIG_METHOD_SEL eConfigMethodSelType; + UINT_16 u2TargetConfigMethod; /* Configure method selected by user or auto. */ + UINT_16 u2LocalConfigMethod; /* Configure method of target. */ + BOOLEAN fgIsPasswordIDRdy; + /*------------WSC Related Param---------------*/ + + UINT_8 ucClientConfigTimeout; + UINT_8 ucGoConfigTimeout; + + UINT_8 ucSecondaryDevTypeCount; +#if P2P_MAX_SUPPORTED_SEC_DEV_TYPE_COUNT + DEVICE_TYPE_T arSecondaryDevTypeBE[P2P_MAX_SUPPORTED_SEC_DEV_TYPE_COUNT]; +#endif + +#if 0 + UINT_8 ucRfChannelListCount; +#if P2P_MAX_SUPPORTED_CHANNEL_LIST_COUNT + UINT_8 aucChannelList[P2P_MAX_SUPPORTED_CHANNEL_LIST_COUNT]; /* + * Channel Numbering + * depends on 802.11mb + * Annex J. + */ + +#endif +#else + UINT_8 ucRfChannelListSize; +#if P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE + UINT_8 aucChannelEntriesField[P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE]; +#endif +#endif + + /* Go Intent */ + UINT_8 ucTieBreaker; + UINT_8 ucGoIntent; + + /* For Device Capability */ + BOOLEAN fgSupportServiceDiscovery; + BOOLEAN fgSupportClientDiscoverability; + BOOLEAN fgSupportConcurrentOperation; + BOOLEAN fgSupportInfraManaged; + BOOLEAN fgSupportInvitationProcedure; + + /* For Group Capability */ + BOOLEAN fgSupportPersistentP2PGroup; + BOOLEAN fgSupportIntraBSSDistribution; + BOOLEAN fgSupportCrossConnection; + BOOLEAN fgSupportPersistentReconnect; + + BOOLEAN fgP2pGroupLimit; + + BOOLEAN fgSupportOppPS; + UINT_16 u2CTWindow; + + BOOLEAN fgIsScanReqIssued; + BOOLEAN fgIsServiceDiscoverIssued; + + /*============ Target Device Connection Settings ============*/ + + /* Discover Target Device Info. */ + BOOLEAN fgIsDevId; + BOOLEAN fgIsDevType; + + /* Encryption mode of Target Device */ + ENUM_PARAM_AUTH_MODE_T eAuthMode; + + /* SSID + * 1. AP Mode, this is the desired SSID user specified. + * 2. Client Mode, this is the target SSID to be connected to. + */ + UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; + UINT_8 ucSSIDLen; + + /* Operating channel requested. */ + UINT_8 ucOperatingChnl; + ENUM_BAND_T eBand; + + /* Linten channel requested. */ + UINT_8 ucListenChnl; + + /* For device discover address/type. */ + UINT_8 aucTargetDevAddr[MAC_ADDR_LEN]; /* + * P2P Device Address, for P2P Device Discovery + * & P2P Connection. + */ + +#if CFG_ENABLE_WIFI_DIRECT + P_P2P_DEVICE_DESC_T prTargetP2pDesc; +#endif + + UINT_8 ucLastStatus; /* + * P2P FSM would append status attribute according to this + * field. + */ + +#if !CFG_DISABLE_DELAY_PROVISION_DISCOVERY + UINT_8 ucLastDialogToken; + UINT_8 aucIndicateDevAddr[MAC_ADDR_LEN]; +#endif + +#if 0 + UINT_8 ucTargetRfChannelListCount; +#if P2P_MAX_SUPPORTED_CHANNEL_LIST_COUNT + UINT_8 aucTargetChannelList[P2P_MAX_SUPPORTED_CHANNEL_LIST_COUNT]; /* + * Channel + * Numbering + * depends on + * 802.11mb Annex J. + */ +#endif +#endif +}; + +typedef enum _ENUM_P2P_IOCTL_T { + P2P_IOCTL_IDLE = 0, + P2P_IOCTL_DEV_DISCOVER, + P2P_IOCTL_INVITATION_REQ, + P2P_IOCTL_SERV_DISCOVER, + P2P_IOCTL_WAITING, + P2P_IOCTL_NUM +} ENUM_P2P_IOCTL_T; + +/*---------------- Service Discovery Related -------------------*/ +typedef enum _ENUM_SERVICE_TX_TYPE_T { + ENUM_SERVICE_TX_TYPE_BY_DA, + ENUM_SERVICE_TX_TYPE_BY_CHNL, + ENUM_SERVICE_TX_TYPE_NUM +} ENUM_SERVICE_TX_TYPE_T; + +typedef struct _SERVICE_DISCOVERY_FRAME_DATA_T { + QUE_ENTRY_T rQueueEntry; + P_MSDU_INFO_T prSDFrame; + ENUM_SERVICE_TX_TYPE_T eServiceType; + UINT_8 ucSeqNum; + union { + UINT_8 ucChannelNum; + UINT_8 aucPeerAddr[MAC_ADDR_LEN]; + } uTypeData; + BOOLEAN fgIsTxDoneIndicate; +} SERVICE_DISCOVERY_FRAME_DATA_T, *P_SERVICE_DISCOVERY_FRAME_DATA_T; + +struct _P2P_FSM_INFO_T_DEPRECATED { + /* P2P FSM State */ + ENUM_P2P_STATE_T eCurrentState; + + /* Channel */ + BOOLEAN fgIsChannelRequested; + + ENUM_P2P_STATE_T ePreviousState; + + ENUM_P2P_STATE_T eReturnState; /* + * Return state after current activity finished or + * abort. + */ + + UINT_8 aucTargetIfAddr[PARAM_MAC_ADDR_LEN]; + P_BSS_DESC_T prTargetBss; /* + * BSS of target P2P Device. For Connection/Service + * Discovery + */ + + P_STA_RECORD_T prTargetStaRec; + + BOOLEAN fgIsRsponseProbe; /* + * Indicate if P2P FSM can response probe + * request frame. + */ + + /* Sequence number of requested message. */ + UINT_8 ucSeqNumOfReqMsg; /* Used for SAA FSM request message. */ + + /* Channel Privilege */ + UINT_8 ucSeqNumOfChReq; /* Used for Channel Request message. */ + + UINT_8 ucSeqNumOfScnMsg; /* Used for SCAN FSM request message. */ + UINT_8 ucSeqNumOfCancelMsg; + + UINT_8 ucDialogToken; + UINT_8 ucRxDialogToken; + + /* Timer */ + TIMER_T rDeviceDiscoverTimer; /* + * For device discovery time of each discovery + * request from user. + */ + TIMER_T rOperationListenTimer; /* For Find phase under operational state. */ + TIMER_T rFSMTimer; /* + * A timer used for Action frame timeout usage. + */ + + TIMER_T rRejoinTimer; /* + * A timer used for Action frame timeout usage. + */ + + /* Flag to indicate Provisioning */ + BOOLEAN fgIsConnectionRequested; + + /* Current IOCTL. */ + ENUM_P2P_IOCTL_T eP2pIOCTL; + + UINT_8 ucAvailableAuthTypes; /* Used for AUTH_MODE_AUTO_SWITCH */ + + /*--------SERVICE DISCOVERY--------*/ + QUE_T rQueueGASRx; /* Input Request/Response. */ + QUE_T rQueueGASTx; /* Output Response. */ + P_SERVICE_DISCOVERY_FRAME_DATA_T prSDRequest; + UINT_8 ucVersionNum; /* GAS packet sequence number for...Action Frame? */ + UINT_8 ucGlobalSeqNum; /* Sequence Number of RX SD packet. */ + /*--------Service DISCOVERY--------*/ + + /*--------DEVICE DISCOVERY---------*/ + UINT_8 aucTargetGroupID[PARAM_MAC_ADDR_LEN]; + UINT_16 u2TargetGroupSsidLen; + UINT_8 aucTargetSsid[32]; + UINT_8 aucSearchingP2pDevice[PARAM_MAC_ADDR_LEN]; + UINT_8 ucDLToken; + /*----------------------------------*/ + + /* Indicating Peer Status. */ + UINT_32 u4Flags; + + /*Indicating current running mode. */ + BOOLEAN fgIsApMode; + + /*------------INVITATION------------*/ + ENUM_P2P_INVITATION_POLICY eInvitationRspPolicy; + /*----------------------------------*/ +}; + +struct _P2P_SPECIFIC_BSS_INFO_T { + /* For GO(AP) Mode - Compose TIM IE */ + UINT_16 u2SmallestAID; + UINT_16 u2LargestAID; + UINT_8 ucBitmapCtrl; + /* UINT_8 aucPartialVirtualBitmap[MAX_LEN_TIM_PARTIAL_BMP]; */ + + /* For GC/GO OppPS */ + BOOLEAN fgEnableOppPS; + UINT_16 u2CTWindow; + + /* For GC/GO NOA */ + UINT_8 ucNoAIndex; + UINT_8 ucNoATimingCount; /* Number of NoA Timing */ + NOA_TIMING_T arNoATiming[P2P_MAXIMUM_NOA_COUNT]; + + BOOLEAN fgIsNoaAttrExisted; + + /* For P2P Device */ + UINT_8 ucRegClass; /* Regulatory Class for channel. */ + UINT_8 ucListenChannel; /* + * Linten Channel only on channels 1, 6 and 11 + * in the 2.4 GHz. + */ + + UINT_8 ucPreferredChannel; /* + * Operating Channel, should be one of channel + * list in p2p connection settings. + */ + ENUM_CHNL_EXT_T eRfSco; + ENUM_BAND_T eRfBand; + + /* Extended Listen Timing. */ + UINT_16 u2AvailabilityPeriod; + UINT_16 u2AvailabilityInterval; + +#if 0 /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */ + UINT_16 u2IELenForBCN; + UINT_8 aucBeaconIECache[P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE + WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; + +/* UINT_16 u2IELenForProbeRsp; */ +/* UINT_8 aucProbeRspIECache[P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE + WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; */ + + UINT_16 u2IELenForAssocRsp; + UINT_8 aucAssocRspIECache[P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE + WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; + +#else + UINT_16 u2AttributeLen; + UINT_8 aucAttributesCache[P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; + + UINT_16 u2WscAttributeLen; + UINT_8 aucWscAttributesCache[WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; +#endif + UINT_8 aucGroupID[MAC_ADDR_LEN]; + UINT_16 u2GroupSsidLen; + UINT_8 aucGroupSsid[ELEM_MAX_LEN_SSID]; + + PARAM_CUSTOM_NOA_PARAM_STRUCT_T rNoaParam; + PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T rOppPsParam; + +#if 0 /* CL2055022 */ + UINT_16 u2WpaIeLen; + UINT_8 aucWpaIeBuffer[ELEM_HDR_LEN + ELEM_MAX_LEN_WPA]; +#endif +}; + +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 + ******************************************************************************** + */ + +/******************************************************************************* + * 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 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, IN P_BSS_INFO_T prP2pBssInfo); + +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 p2pFsmRunEventIOReqTimeout(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Param); + +VOID p2pFsmRunEventSearchPeriodTimeout(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Param); + +VOID p2pFsmRunEventFsmTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); + +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 UINT_8 ucBssIndex, IN P_STA_RECORD_T prStaRec); + +UINT_32 p2pCalculateP2P_IELenForAssocRsp(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN P_STA_RECORD_T prStaRec); + +UINT_32 p2pCalculateP2P_IELenForProbeReq(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, 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 UINT_8 ucBssIndex); + +UINT_32 p2pCalculateWSC_IELenForProbeResp(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN P_STA_RECORD_T prStaRec); + +UINT_32 +p2pAppendAttriStatus(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN + UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriCapability(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriGoIntent(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN + UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriCfgTimeout(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriGroupBssid(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriDeviceIDForBeacon(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 + pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriDeviceIDForProbeReq(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 + pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriDeviceIDForDeviceDiscoveryReq(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriListenChannel(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 + pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriIntendP2pIfAddr(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 + pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriChannelList(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize); + +UINT_32 p2pCalculateAttriLenChannelList(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +UINT_32 +p2pAppendAttriNoA(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN + UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriDeviceInfo(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize); + +UINT_32 p2pCalculateAttriLenDeviceInfo(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +UINT_32 +p2pAppendAttriGroupInfo(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize); + +UINT_32 p2pCalculateAttriLenGroupInfo(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +UINT_32 +p2pAppendAttriP2pGroupID(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriOperatingChannel(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 + pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriInvitationFlag(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 + pucBuf, IN UINT_16 u2BufSize); + +VOID +p2pGenerateWscIE(IN P_ADAPTER_T prAdapter, IN UINT_8 ucOuiType, IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN + PUINT_8 pucBuf, IN UINT_16 u2BufSize, IN APPEND_VAR_ATTRI_ENTRY_T arAppendAttriTable[], + IN UINT_32 u4AttriTableSize); + +UINT_32 +p2pAppendAttriWSCConfigMethod(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 + pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriWSCVersion(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriWSCGONegReqDevPasswordId(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN + PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriWSCGONegRspDevPasswordId(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN + PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +WLAN_STATUS +p2pGetWscAttriList(IN P_ADAPTER_T prAdapter, IN UINT_8 ucOuiType, IN PUINT_8 pucIE, IN UINT_16 u2IELength, OUT PPUINT_8 + ppucAttriList, OUT PUINT_16 pu2AttriListLen); + +WLAN_STATUS +p2pGetAttriList(IN P_ADAPTER_T prAdapter, IN UINT_8 ucOuiType, IN PUINT_8 pucIE, IN UINT_16 u2IELength, OUT PPUINT_8 + ppucAttriList, OUT PUINT_16 pu2AttriListLen); + +VOID p2pRunEventAAATxFail(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +WLAN_STATUS p2pRunEventAAASuccess(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +WLAN_STATUS p2pRunEventAAAComplete(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +WLAN_STATUS p2pSendProbeResponseFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +BOOLEAN p2pFsmRunEventRxProbeRequestFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID p2pFsmRunEventRxProbeResponseFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN P_BSS_DESC_T prBssDesc); + +WLAN_STATUS p2pRxPublicActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +WLAN_STATUS p2pRxActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID p2pFsmRunEventRxGroupNegotiationRspFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID p2pFsmRunEventRxGroupNegotiationCfmFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +#if 0 /* frog */ +BOOLEAN scanMatchFilterOfP2P(IN P_SW_RFB_T prSWRfb, IN PP_BSS_DESC_T pprBssDesc); +#endif /* frog */ + +VOID +p2pProcessEvent_UpdateNOAParam(IN P_ADAPTER_T prAdapter, UINT_8 ucNetTypeIndex, P_EVENT_UPDATE_NOA_PARAMS_T + prEventUpdateNoaParam); + +VOID p2pFuncCompleteIOCTL(IN P_ADAPTER_T prAdapter, IN WLAN_STATUS rWlanStatus); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************** + */ +#ifndef _lint +/* + * Kevin: we don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + * We'll need this for porting driver to different RTOS. + */ +static __KAL_INLINE__ VOID p2pDataTypeCheck(VOID) +{ + DATA_STRUCT_INSPECTING_ASSERT(sizeof(IE_P2P_T) == (2 + 4 + 1)); /* all UINT_8 */ + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRIBUTE_T) == (3 + 1)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_STATUS_T) == (3 + 1)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_REASON_T) == (3 + 1)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_CAPABILITY_T) == (3 + 2)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_DEV_ID_T) == (3 + 6)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_GO_INTENT_T) == (3 + 1)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_CFG_TIMEOUT_T) == (3 + 2)); +#if CID52_53_54 + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_LISTEN_CHANNEL_T) == (3 + 5)); +#else + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_LISTEN_CHANNEL_T) == (3 + 5)); +#endif + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_GROUP_BSSID_T) == (3 + 6)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_EXT_LISTEN_TIMING_T) == (3 + 4)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_INTENDED_IF_ADDR_T) == (3 + 6)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_MANAGEABILITY_T) == (3 + 1)); + + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_CHANNEL_T) == (3 + 4)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(CHANNEL_ENTRY_FIELD_T) == 3); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_NOA_T) == (3 + 3)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(NOA_DESCRIPTOR_T) == 13); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(DEVICE_TYPE_T) == 8); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_DEV_INFO_T) == (3 + 6 + 2 + 8 + 1 + 8)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(DEVICE_NAME_TLV_T) == (4 + 32)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_CLIENT_INFO_DESC_T) == (1 + 6 + 6 + 1 + 2 + 8 + 1 + 8)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_GROUP_INFO_T) == (3 + (1 + 6 + 6 + 1 + 2 + 8 + 1 + 8))); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_GROUP_ID_T) == (3 + 38)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_INTERFACE_T) == (3 + 13)); +#if CID52_53_54 + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_OPERATING_CHANNEL_T) == (3 + 5)); +#else + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_OPERATING_CHANNEL_T) == (3 + 5)); +#endif +} +#endif /* _lint */ + +#endif /* _P2P_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_func.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_func.h new file mode 100644 index 0000000000000..89c1b601ed21e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_func.h @@ -0,0 +1,237 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _P2P_FUNC_H +#define _P2P_FUNC_H + +#include "precomp.h" + +#define P2P_OFF_CHNL_TX_DEFAULT_TIME_MS 1000 + +/******************************************************************************* + * M A C R O S + ******************************************************************************** + */ +#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_SIZE(_fp) (P2P_ATTRI_HDR_LEN + WSC_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))) + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************** + */ + +VOID p2pFuncRequestScan(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo); + +VOID p2pFuncCancelScan(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo); + +VOID +p2pFuncUpdateBssInfoForJOIN(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc, IN P_STA_RECORD_T prStaRec, IN + P_BSS_INFO_T prP2pBssInfo, IN P_SW_RFB_T prAssocRspSwRfb); + +VOID p2pFuncAcquireCh(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo); + +VOID +p2pFuncDisconnect(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo, IN P_STA_RECORD_T prStaRec, IN BOOLEAN + fgSendDeauth, IN UINT_16 u2ReasonCode); + +P_BSS_INFO_T p2pFuncBSSIDFindBssInfo(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBSSID); + +/* //////////////////////////////// MT6630 CODE //////////////////////////////////// */ + +VOID p2pFuncGCJoin(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo, IN P_P2P_JOIN_INFO_T prP2pJoinInfo); + +VOID +p2pFuncStartGO(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, + IN P_P2P_CONNECTION_REQ_INFO_T prP2pConnReqInfo, + IN P_P2P_CHNL_REQ_INFO_T prP2pChnlReqInfo); + +VOID p2pFuncStopGO(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo); + +WLAN_STATUS p2pFuncRoleToBssIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucRoleIdx, OUT PUINT_8 pucBssIdx); + +VOID +p2pFuncSwitchOPMode(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo, IN ENUM_OP_MODE_T eOpMode, IN BOOLEAN + fgSyncToFW); + +VOID p2pFuncReleaseCh(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo); + +VOID p2pFuncSetChannel(IN P_ADAPTER_T prAdapter, IN UINT_8 ucRoleIdx, 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); + +WLAN_STATUS +p2pFuncTxMgmtFrame(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN P_MSDU_INFO_T prMgmtTxMsdu, IN BOOLEAN + fgNonCckRate); + +WLAN_STATUS +p2pFuncProcessBeacon(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_BSS_INFO_T prBssInfo, 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, IN BOOLEAN + fgIsApMode); + +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, IN BOOLEAN + fgIsDevInterface, IN UINT_8 ucRoleIdx); + +VOID p2pFuncValidateRxActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +BOOLEAN p2pFuncIsAPMode(IN P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings); + +VOID +p2pFuncParseBeaconIEs(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_BSS_INFO_T prBssInfo, 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_P2P_JOIN_INFO_T prP2pJoinInfo, 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); + +P_MSDU_INFO_T p2pFuncProcessP2pProbeRsp(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, 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 UINT_8 ucBssIndex, 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 UINT_8 ucBssIndex, 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 UINT_8 ucBssIndex, 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 UINT_8 ucBssIndex, IN P_STA_RECORD_T prStaRec); + +VOID p2pFuncGenerateP2p_IEForAssocRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +UINT_32 +p2pFuncCalculateP2P_IELen(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, 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_8 ucAttriID); + +UINT_32 wfdFuncCalculateWfdIELenForAssocRsp(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN P_STA_RECORD_T prStaRec); + +VOID wfdFuncGenerateWfdIEForAssocRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +UINT_32 p2pFuncCalculateP2P_IE_NoA(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, IN P_STA_RECORD_T prStaRec); + +VOID p2pFuncGenerateP2P_IE_NoA(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +UINT_8 p2pFunGetAcsBestCh(IN P_ADAPTER_T prAdapter, + IN ENUM_BAND_T eBand, + IN ENUM_MAX_BANDWIDTH_SETTING eChnlBw, + IN UINT_32 u4LteSafeChnMask_2G, + IN UINT_32 u4LteSafeChnMask_5G_1, + IN UINT_32 u4LteSafeChnMask_5G_2); + +void p2pFunProcessAcsReport(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucRoleIndex, + IN P_PARAM_GET_CHN_INFO prLteSafeChnInfo, + IN struct P2P_ACS_REQ_INFO *prAcsReqInfo); + +void p2pFunIndicateAcsResult(IN P_GLUE_INFO_T prGlueInfo, + IN struct P2P_ACS_REQ_INFO *prAcsReqInfo); + +void p2pFunCalAcsChnScores(IN P_ADAPTER_T prAdapter, + IN ENUM_BAND_T eBand); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_ie.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_ie.h new file mode 100644 index 0000000000000..9cdb46c539eb5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_ie.h @@ -0,0 +1,63 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#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 */ + +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; + +#endif + +UINT_32 p2pCalculate_IEForAssocReq(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN P_STA_RECORD_T prStaRec); + +VOID p2pGenerate_IEForAssocReq(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_rlm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_rlm.h new file mode 100644 index 0000000000000..7cf264ca5abe5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_rlm.h @@ -0,0 +1,82 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \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/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_rlm_obss.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_rlm_obss.h new file mode 100644 index 0000000000000..0fd7b306b7e22 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_rlm_obss.h @@ -0,0 +1,78 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/mgmt/p2p_rlm_obss.h#1 +*/ + +/*! \file "rlm_obss.h" + * \brief + */ + +#ifndef _P2P_RLM_OBSS_H +#define _P2P_RLM_OBSS_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************** + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************** + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************** + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************** + */ + +VOID rlmRspGenerateObssScanIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + +VOID rlmProcessPublicAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); + +VOID rlmProcessHtAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); + +VOID rlmHandleObssStatusEventPkt(P_ADAPTER_T prAdapter, P_EVENT_AP_OBSS_STATUS_T prObssStatus); + +UINT_8 rlmObssChnlLevel(P_BSS_INFO_T prBssInfo, ENUM_BAND_T eBand, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend); + +VOID rlmObssScanExemptionRsp(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_SW_RFB_T prSwRfb); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_role.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_role.h new file mode 100644 index 0000000000000..be52853a235a7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_role.h @@ -0,0 +1,311 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _P2P_ROLE_H +#define _P2P_ROLE_H + +#define P2P_JOIN_CH_REQUEST_INTERVAL 4000 + +#define P2P_ROLE_GET_STATISTICS_TIME 5000 + +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_ZERO_LEN, + ENUM_HIDDEN_SSID_ZERO_CONTENT, + ENUM_HIDDEN_SSID_NUM +} ENUM_HIDDEN_SSID_TYPE_T, *P_ENUM_HIDDEN_SSID_TYPE_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 _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; + +/* ////////////////////////////////// Message //////////////////////////////////////////////////// */ + +typedef struct _MSG_P2P_BEACON_UPDATE_T { + MSG_HDR_T rMsgHdr; + UINT_8 ucRoleIndex; + 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; + UINT_8 ucRoleIdx; +} 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_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 */ + UINT_8 ucRoleIdx; + 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 ucRoleIdx; + 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_START_AP_T { + MSG_HDR_T rMsgHdr; + UINT_32 u4DtimPeriod; + UINT_32 u4BcnInterval; + UINT_8 aucSsid[32]; + UINT_16 u2SsidLen; + ENUM_HIDDEN_SSID_TYPE_T eHiddenSsidType; + BOOLEAN fgIsPrivacy; + UINT_8 ucRoleIdx; + AP_CRYPTO_SETTINGS_T rEncryptionSettings; + INT_32 i4InactiveTimeout; +} MSG_P2P_START_AP_T, *P_MSG_P2P_START_AP_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; + +/* 3 --------------- WFA P2P Attributes Handler prototype --------------- */ +typedef UINT_32(*PFN_APPEND_ATTRI_FUNC) (P_ADAPTER_T, BOOLEAN, PUINT_16, PUINT_8, UINT_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_P2P_ROLE_STATE_T { + P2P_ROLE_STATE_IDLE = 0, + P2P_ROLE_STATE_SCAN, + P2P_ROLE_STATE_REQING_CHANNEL, + P2P_ROLE_STATE_AP_CHNL_DETECTION, /* Requesting Channel to Send Specific Frame. */ + P2P_ROLE_STATE_GC_JOIN, + P2P_ROLE_STATE_NUM +} ENUM_P2P_ROLE_STATE_T, *P_ENUM_P2P_ROLE_STATE_T; + +typedef enum _ENUM_P2P_CONNECTION_TYPE_T { + P2P_CONNECTION_TYPE_IDLE = 0, + P2P_CONNECTION_TYPE_GO, + P2P_CONNECTION_TYPE_GC, + P2P_CONNECTION_TYPE_PURE_AP, + P2P_CONNECTION_TYPE_NUM +} ENUM_P2P_CONNECTION_TYPE_T, *P_ENUM_P2P_CONNECTION_TYPE_T; + +typedef struct _P2P_JOIN_INFO_T { + UINT_8 ucSeqNumOfReqMsg; + UINT_8 ucAvailableAuthTypes; + P_STA_RECORD_T prTargetStaRec; + P_BSS_DESC_T prTargetBssDesc; + BOOLEAN fgIsJoinComplete; + /* For ASSOC Rsp. */ + UINT_32 u4BufLength; + UINT_8 aucIEBuf[MAX_IE_LENGTH]; +} P2P_JOIN_INFO_T, *P_P2P_JOIN_INFO_T; + +/* For STA & AP mode. */ +typedef struct _P2P_CONNECTION_REQ_INFO_T { + ENUM_P2P_CONNECTION_TYPE_T eConnRequest; + P2P_SSID_STRUCT_T rSsidStruct; + UINT_8 aucBssid[MAC_ADDR_LEN]; + + /* AP preferred channel. */ + RF_CHANNEL_INFO_T rChannelInfo; + ENUM_CHNL_EXT_T eChnlExt; + + /* For ASSOC Req. */ + UINT_32 u4BufLength; + UINT_8 aucIEBuf[MAX_IE_LENGTH]; +} P2P_CONNECTION_REQ_INFO_T, *P_P2P_CONNECTION_REQ_INFO_T; + +#define P2P_ROLE_INDEX_2_ROLE_FSM_INFO(_prAdapter, _RoleIndex) \ + ((_prAdapter)->rWifiVar.aprP2pRoleFsmInfo[_RoleIndex]) + +struct _P2P_ROLE_FSM_INFO_T { + UINT_8 ucRoleIndex; + + UINT_8 ucBssIndex; + + /* State related. */ + ENUM_P2P_ROLE_STATE_T eCurrentState; + + /* Channel related. */ + P2P_CHNL_REQ_INFO_T rChnlReqInfo; + + /* Scan related. */ + P2P_SCAN_REQ_INFO_T rScanReqInfo; + + /* Auto channel selection related. */ + struct P2P_ACS_REQ_INFO rAcsReqInfo; + + /* Auto channel selection related -- get lte safa channel from fw*/ + PARAM_GET_CHN_INFO rLteSafeChnInfo; + + /* FSM Timer */ + TIMER_T rP2pRoleFsmTimeoutTimer; + + /* Get statistics Timer */ + TIMER_T rP2pRoleFsmGetStatisticsTimer; + + /* Packet filter for P2P module. */ + UINT_32 u4P2pPacketFilter; + + /* GC Join related. */ + P2P_JOIN_INFO_T rJoinInfo; + + /* Connection related. */ + P2P_CONNECTION_REQ_INFO_T rConnReqInfo; + + /* Beacon Information. */ + P2P_BEACON_UPDATE_INFO_T rBeaconUpdateInfo; +}; + +/*========================= Initial ============================*/ + +UINT_8 p2pRoleFsmInit(IN P_ADAPTER_T prAdapter, IN UINT_8 ucRoleIdx); + +VOID p2pRoleFsmUninit(IN P_ADAPTER_T prAdapter, IN UINT_8 ucRoleIdx); + +/*================== Message Event ==================*/ + +VOID p2pRoleFsmRunEventAbort(IN P_ADAPTER_T prAdapter, IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo); + +VOID p2pRoleFsmRunEventStartAP(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pRoleFsmRunEventStopAP(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pRoleFsmRunEventScanRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID +p2pRoleFsmRunEventScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr, IN P_P2P_ROLE_FSM_INFO_T + prP2pRoleFsmInfo); + +VOID p2pRoleFsmRunEventJoinComplete(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pRoleFsmRunEventTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); + +VOID p2pRoleFsmRunEventBeaconTimeout(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo); + +WLAN_STATUS +p2pRoleFsmRunEventAAAComplete(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_BSS_INFO_T prP2pBssInfo); + +WLAN_STATUS +p2pRoleFsmRunEventAAASuccess(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_BSS_INFO_T prP2pBssInfo); + +VOID p2pRoleFsmRunEventAAATxFail(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_BSS_INFO_T prP2pBssInfo); + +VOID p2pRoleFsmRunEventConnectionRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pRoleFsmRunEventConnectionAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID +p2pRoleFsmRunEventChnlGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr, IN P_P2P_ROLE_FSM_INFO_T + prP2pRoleFsmInfo); + +WLAN_STATUS +p2pRoleFsmRunEventDeauthTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T + rTxDoneStatus); + +VOID p2pRoleFsmRunEventRxDeauthentication(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb); + +VOID p2pRoleFsmRunEventRxDisassociation(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb); + +/* //////////////////////// TO BE REFINE ///////////////////// */ +VOID p2pRoleFsmRunEventSwitchOPMode(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 p2pRoleFsmRunEventDissolve(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID +p2pProcessEvent_UpdateNOAParam(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, IN P_EVENT_UPDATE_NOA_PARAMS_T + prEventUpdateNoaParam); + +VOID p2pRoleFsmGetStaStatistics(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); +/*the same with gen4m */ +void p2pRoleFsmRunEventAcs(IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr); + +BOOL p2pRoleFsmIsAcsProcessing(IN P_ADAPTER_T prAdapter, + UINT_8 ucRoleIdx); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_role_state.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_role_state.h new file mode 100644 index 0000000000000..e2c76f8268871 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_role_state.h @@ -0,0 +1,66 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _P2P_ROLE_STATE_H +#define _P2P_ROLE_STATE_H + +VOID +p2pRoleStateInit_IDLE(IN P_ADAPTER_T prAdapter, + IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo, IN P_BSS_INFO_T prP2pBssInfo); + +VOID +p2pRoleStateAbort_IDLE(IN P_ADAPTER_T prAdapter, + IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo, IN P_P2P_CHNL_REQ_INFO_T prP2pChnlReqInfo); + +VOID p2pRoleStateInit_SCAN(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo); + +VOID p2pRoleStateAbort_SCAN(IN P_ADAPTER_T prAdapter, IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo); + +VOID +p2pRoleStateInit_REQING_CHANNEL(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo); + +VOID +p2pRoleStateAbort_REQING_CHANNEL(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pRoleBssInfo, + IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo, IN ENUM_P2P_ROLE_STATE_T eNextState); + +VOID +p2pRoleStateInit_AP_CHNL_DETECTION(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucBssIndex, + IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo, + IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo); + +VOID +p2pRoleStateAbort_AP_CHNL_DETECTION(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucBssIndex, + IN P_P2P_CONNECTION_REQ_INFO_T prP2pConnReqInfo, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, + IN P_P2P_SCAN_REQ_INFO_T prP2pScanReqInfo, IN ENUM_P2P_ROLE_STATE_T eNextState); + +VOID +p2pRoleStateInit_GC_JOIN(IN P_ADAPTER_T prAdapter, + IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo); + +VOID +p2pRoleStateAbort_GC_JOIN(IN P_ADAPTER_T prAdapter, + IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo, + IN P_P2P_JOIN_INFO_T prJoinInfo, IN ENUM_P2P_ROLE_STATE_T eNextState); + +VOID +p2pRoleStatePrepare_To_REQING_CHANNEL_STATE(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, + IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo, + OUT P_P2P_CHNL_REQ_INFO_T prChnlReqInfo); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_scan.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_scan.h new file mode 100644 index 0000000000000..fe3e1fb03686b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_scan.h @@ -0,0 +1,80 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** 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 + ******************************************************************************** + */ + +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_P2P_CONNECTION_REQ_INFO_T prConnReqInfo); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_state.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_state.h new file mode 100644 index 0000000000000..16ca4eba95a92 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/p2p_state.h @@ -0,0 +1,57 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _P2P_STATE_H +#define _P2P_STATE_H + +BOOLEAN +p2pStateInit_IDLE(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN P_BSS_INFO_T prP2pBssInfo, OUT P_ENUM_P2P_STATE_T peNextState); + +VOID p2pStateAbort_IDLE(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN ENUM_P2P_STATE_T eNextState); + +VOID p2pStateInit_SCAN(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo); + +VOID p2pStateAbort_SCAN(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN ENUM_P2P_STATE_T eNextState); + +VOID p2pStateInit_AP_CHANNEL_DETECT(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo); + +VOID +p2pStateAbort_AP_CHANNEL_DETECT(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo, IN ENUM_P2P_STATE_T eNextState); + +VOID +p2pStateInit_CHNL_ON_HAND(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo, IN P_P2P_FSM_INFO_T prP2pFsmInfo); + +VOID +p2pStateAbort_CHNL_ON_HAND(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_BSS_INFO_T prP2pBssInfo, IN ENUM_P2P_STATE_T eNextState); + +VOID +p2pStateAbort_REQING_CHANNEL(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN ENUM_P2P_STATE_T eNextState); + +VOID +p2pStateInit_GC_JOIN(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_BSS_INFO_T prP2pBssInfo, IN P_P2P_JOIN_INFO_T prJoinInfo, IN P_BSS_DESC_T prBssDesc); + +VOID +p2pStateAbort_GC_JOIN(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_P2P_JOIN_INFO_T prJoinInfo, IN ENUM_P2P_STATE_T eNextState); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/privacy.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/privacy.h new file mode 100644 index 0000000000000..c6d195864d7a4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/privacy.h @@ -0,0 +1,284 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/privacy.h#1 + */ + +/* + * ! \file privacy.h + * \brief This file contains the function declaration for privacy.c. + */ + +#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 CIPHER_SUITE_CCMP_W_CCX 9 +#define CIPHER_SUITE_GCMP 10 + +/* Todo:: Move to register */ + +#define WTBL_RESERVED_ENTRY 255 +#define WTBL_SIZE 32 /* + * Max wlan table size, the max+1 used for probe request,... mgmt frame + * sending use basic rate and no security + */ + +#define WTBL_ALLOC_FAIL WTBL_RESERVED_ENTRY +#define WTBL_DEFAULT_ENTRY 0 + +#define WTBL_STA_IDX_0 0 +#define WTBL_STA_IDX_MAX 17 +#define WTBL_IBSS_STA_IDX_MAX 7 + +#define WTBL_AIS_BIP_IDX 18 + +#define WTBL_IBSS_BC_IDX_0 9 + +#define WTBL_BC_IDX_0 19 +#define WTBL_BC_IDX_MAX 27 + +#define WTBL_AIS_DLS_MAX_IDX (WTBL_STA_IDX_MAX - 7) /* + * Reserved for DLS:end entry, Todo:: Max DLS entry + * define + */ + +#define WTBL_AIS_IBSS_NO_SEC_BC_IDX 28 /* Reserved for Ad-hoc No sec index */ +#define WTBL_AP_NO_SEC_BC_IDX 28 /* Reserved for AP mode No Sec index */ + +#define SEC_TX_KEY_COMMAND 1 +#define SEC_QUEUE_KEY_COMMAND 0 +#define SEC_DROP_KEY_COMMAND 2 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************** + */ +enum EAPOL_KEY_TYPE { + EAPOL_KEY_NOT_KEY = 0, + EAPOL_KEY_1_OF_4 = 1, + EAPOL_KEY_2_OF_4 = 2, + EAPOL_KEY_3_OF_4 = 3, + EAPOL_KEY_4_OF_4 = 4, + EAPOL_KEY_1_OF_2 = 5, + EAPOL_KEY_2_OF_2 = 6, +}; + +/* + * EAP Method Types as allocated by IANA: + * http://www.iana.org/assignments/eap-numbers + */ +typedef enum { + EAP_TYPE_NONE = 0, + EAP_TYPE_IDENTITY = 1 /* RFC 3748 */, + EAP_TYPE_NOTIFICATION = 2 /* RFC 3748 */, + EAP_TYPE_NAK = 3 /* Response only, RFC 3748 */, + EAP_TYPE_MD5 = 4, /* RFC 3748 */ + EAP_TYPE_OTP = 5 /* RFC 3748 */, + EAP_TYPE_GTC = 6, /* RFC 3748 */ + EAP_TYPE_TLS = 13 /* RFC 2716 */, + EAP_TYPE_LEAP = 17 /* Cisco proprietary */, + EAP_TYPE_SIM = 18 /* RFC 4186 */, + EAP_TYPE_TTLS = 21 /* RFC 5281 */, + EAP_TYPE_AKA = 23 /* RFC 4187 */, + EAP_TYPE_PEAP = 25 /* draft-josefsson-pppext-eap-tls-eap-06.txt */, + EAP_TYPE_MSCHAPV2 = 26 /* draft-kamath-pppext-eap-mschapv2-00.txt */, + EAP_TYPE_TLV = 33 /* draft-josefsson-pppext-eap-tls-eap-07.txt */, + EAP_TYPE_TNC = 38 /* TNC IF-T v1.0-r3; note: tentative assignment; + * type 38 has previously been allocated for + * EAP-HTTP Digest, (funk.com) */, + EAP_TYPE_FAST = 43 /* RFC 4851 */, + EAP_TYPE_PAX = 46 /* RFC 4746 */, + EAP_TYPE_PSK = 47 /* RFC 4764 */, + EAP_TYPE_SAKE = 48 /* RFC 4763 */, + EAP_TYPE_IKEV2 = 49 /* RFC 5106 */, + EAP_TYPE_AKA_PRIME = 50 /* RFC 5448 */, + EAP_TYPE_GPSK = 51 /* RFC 5433 */, + EAP_TYPE_PWD = 52 /* RFC 5931 */, + EAP_TYPE_EKE = 53 /* RFC 6124 */, + EAP_TYPE_EXPANDED = 254 /* RFC 3748 */ +} EapType; + + +/* SMI Network Management Private Enterprise Code for vendor specific types */ +enum { + EAP_VENDOR_IETF = 0, + EAP_VENDOR_MICROSOFT = 0x000137 /* Microsoft */, + EAP_VENDOR_WFA = 0x00372A /* Wi-Fi Alliance (moved to WBA) */, + EAP_VENDOR_HOSTAP = 39068 /* hostapd/wpa_supplicant project */, + EAP_VENDOR_WFA_NEW = 40808 /* Wi-Fi Alliance */ +}; + +#define EAP_VENDOR_TYPE_WSC 1 + +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 ucBssIndex); + +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); + +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); + +UINT_8 secGetBmcWlanIndex(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_T eNetType, IN P_STA_RECORD_T prStaRec); + +BOOLEAN secTransmitKeyExist(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +BOOLEAN secEnabledInAis(IN P_ADAPTER_T prAdapter); + +BOOL secPrivacySeekForEntry(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +VOID secPrivacyFreeForEntry(IN P_ADAPTER_T prAdapter, IN UINT_8 ucEntry); + +VOID secPrivacyFreeSta(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +enum EAPOL_KEY_TYPE secGetEapolKeyType(PUINT_8 pucPacket); +VOID secSetKeyCmdAction(P_BSS_INFO_T prBssInfo, UINT_8 ucEapolKeyType, UINT_8 ucAction); + +UINT_8 +secPrivacySeekForBcEntry(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN PUINT_8 pucAddr, IN UINT_8 ucStaIdx, IN + UINT_8 ucAlg, IN UINT_8 ucKeyId, IN UINT_8 ucCurrentKeyId, IN UINT_8 ucTxRx); + +UINT_8 secGetStaIdxByWlanIdx(P_ADAPTER_T prAdapter, UINT_8 ucWlanIdx); + +UINT_8 secGetBssIdxByWlanIdx(P_ADAPTER_T prAdapter, UINT_8 ucWlanIdx); + +UINT_8 secLookupStaRecIndexFromTA(P_ADAPTER_T prAdapter, PUINT_8 pucMacAddress); + +void secPrivacyDumpWTBL(IN P_ADAPTER_T prAdapter); + +BOOLEAN secCheckWTBLAssign(IN P_ADAPTER_T prAdapter); + +void secPrivacyDumpWTBL3(IN P_ADAPTER_T prAdapter, IN UINT_8 ucIndex); + +BOOLEAN secIsProtected1xFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +BOOLEAN secIsProtectedBss(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo); + +BOOLEAN tkipMicDecapsulate(IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucMicKey); + +UINT_8 secGetBssIdxByNetType(P_ADAPTER_T prAdapter); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************** + */ + +#endif /* _PRIVACY_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/qosmap.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/qosmap.h new file mode 100644 index 0000000000000..bd4f2c9f6a58d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/qosmap.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + */ +#ifndef _QOSMAP_H +#define _QOSMAP_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 +******************************************************************************** +*/ +#define DSCP_SUPPORT 1 +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +#if DSCP_SUPPORT +VOID handleQosMapConf(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +int qosHandleQosMapConfigure(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID qosMapSetInit(IN P_STA_RECORD_T prStaRec); + +VOID qosParseQosMapSet(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN PUINT_8 qosMapSet); + +UINT_8 getUpFromDscp(IN P_GLUE_INFO_T prGlueInfo, IN int type, IN int dscp); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _QOSMAP_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rate.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rate.h new file mode 100644 index 0000000000000..0690cc2758590 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rate.h @@ -0,0 +1,88 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/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. + */ + +#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 + ******************************************************************************** + */ +extern const UINT_8 aucDataRate[]; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************** + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************** + */ +/*----------------------------------------------------------------------------*/ +/* Routines in rate.c */ +/*----------------------------------------------------------------------------*/ +VOID +rateGetRateSetFromIEs(IN P_IE_SUPPORTED_RATE_T prIeSupportedRate, IN P_IE_EXT_SUPPORTED_RATE_T prIeExtSupportedRate, OUT + PUINT_16 pu2OperationalRateSet, OUT PUINT_16 pu2BSSBasicRateSet, + OUT PBOOLEAN pfgIsUnknownBSSBasicRate); + +VOID +rateGetDataRatesFromRateSet(IN UINT_16 u2OperationalRateSet, IN UINT_16 u2BSSBasicRateSet, OUT PUINT_8 pucDataRates, OUT + PUINT_8 pucDataRatesLen); + +BOOLEAN rateGetHighestRateIndexFromRateSet(IN UINT_16 u2RateSet, OUT PUINT_8 pucHighestRateIndex); + +BOOLEAN rateGetLowestRateIndexFromRateSet(IN UINT_16 u2RateSet, OUT PUINT_8 pucLowestRateIndex); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************** + */ + +#endif /* _RATE_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rlm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rlm.h new file mode 100644 index 0000000000000..15e8c253d3171 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rlm.h @@ -0,0 +1,402 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rlm.h#2 +*/ + +/* + * ! \file "rlm.h" + * \brief + */ + +#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 +******************************************************************************** +*/ + +extern BOOLEAN g_bIcapEnable; +extern BOOLEAN g_bCaptureDone; +extern UINT_16 g_u2DumpIndex; +#if CFG_SUPPORT_QA_TOOL +extern UINT_32 g_au4Offset[2][2]; +extern UINT_32 g_au4IQData[20][1024]; +extern UINT_32 g_au4I0Data[1][408000]; +extern UINT_32 g_au4Q0Data[1][408000]; +#endif +/******************************************************************************* +* 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 | 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 + +#if CFG_SUPPORT_BFEE +#define TX_BEAMFORMING_CAP_BFEE \ + (TXBF_RX_NDP_CAPABLE | \ + TXBF_EXPLICIT_COMPRESSED_FEEDBACK_IMMEDIATE_CAPABLE | \ + TXBF_MINIMAL_GROUPING_1_2_3_CAPABLE | \ + TXBF_COMPRESSED_TX_ANTENNANUM_4_SUPPORTED | \ + TXBF_CHANNEL_ESTIMATION_4STS_CAPABILITY) +#else +#define TX_BEAMFORMING_CAP_BFEE 0 +#endif + +#define ASEL_CAP_DEFAULT_VAL 0 + +/* Define bandwidth from user setting */ +#define CONFIG_BW_20_40M 0 +#define CONFIG_BW_20M 1 /* 20MHz only */ + +/* Radio Measurement Request Mode definition */ +#define RM_REQ_MODE_PARALLEL_BIT BIT(0) +#define RM_REQ_MODE_ENABLE_BIT BIT(1) +#define RM_REQ_MODE_REQUEST_BIT BIT(2) +#define RM_REQ_MODE_REPORT_BIT BIT(3) +#define RM_REQ_MODE_DURATION_MANDATORY_BIT BIT(4) +#define RM_REP_MODE_LATE BIT(0) +#define RM_REP_MODE_INCAPABLE BIT(1) +#define RM_REP_MODE_REFUSED BIT(2) + +/* Radio Measurement Report Frame Max Length */ +#define RM_REPORT_FRAME_MAX_LENGTH 1600 +#define RM_BCN_REPORT_SUB_ELEM_MAX_LENGTH 224 +/* beacon request mode definition */ +#define RM_BCN_REQ_PASSIVE_MODE 0 +#define RM_BCN_REQ_ACTIVE_MODE 1 +#define RM_BCN_REQ_TABLE_MODE 2 + +#define RLM_INVALID_POWER_LIMIT -127 /* dbm */ + +#define RLM_MAX_TX_PWR 20 /* dbm */ +#define RLM_MIN_TX_PWR 8 /* dbm */ + +#if CFG_SUPPORT_802_11AC +#if CFG_SUPPORT_BFEE +#define FIELD_VHT_CAP_INFO_BF \ + (VHT_CAP_INFO_SU_BEAMFORMEE_CAPABLE | \ + VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF_BEAMFORMER_ANTENNAS_4_SUPPOERTED) +#else +#define FIELD_VHT_CAP_INFO_BF 0 +#endif + +#define VHT_CAP_INFO_DEFAULT_VAL \ + (VHT_CAP_INFO_MAX_MPDU_LEN_3K | \ + (AMPDU_PARAM_MAX_AMPDU_LEN_1024K << VHT_CAP_INFO_MAX_AMPDU_LENGTH_OFFSET)) + +#define VHT_CAP_INFO_DEFAULT_HIGHEST_DATA_RATE 0 +#endif +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +struct SUB_ELEMENT_LIST { + struct SUB_ELEMENT_LIST *prNext; + struct SUB_ELEMENT_T rSubIE; +}; + +enum BCN_RM_STATE { + RM_NO_REQUEST, + RM_ON_GOING, + RM_WAITING, /*waiting normal scan done */ +}; + +enum RM_REQ_PRIORITY { + RM_PRI_BROADCAST, + RM_PRI_MULTICAST, + RM_PRI_UNICAST +}; + +struct NORMAL_SCAN_PARAMS { + PARAM_SSID_T arSSID[SCN_SSID_MAX_NUM]; + UINT_8 aucScanIEBuf[MAX_IE_LENGTH]; + UINT_32 u4IELen; + UINT_8 ucSsidNum; + BOOLEAN fgExist; + BOOLEAN fgFull2Partial; + struct _PARAM_SCAN_RANDOM_MAC_ADDR_T rScanRandMacAddr; +}; + +/* Beacon RM related parameters */ +struct BCN_RM_PARAMS { + BOOLEAN fgExistBcnReq; + enum BCN_RM_STATE eState; + struct NORMAL_SCAN_PARAMS rNormalScan; +}; + +struct RADIO_MEASUREMENT_REQ_PARAMS { + /* Remain Request Elements Length, started at prMeasElem. if it is 0, means RM is done */ + UINT_16 u2RemainReqLen; + UINT_16 u2ReqIeBufLen; + P_IE_MEASUREMENT_REQ_T prCurrMeasElem; + OS_SYSTIME rStartTime; + UINT_16 u2Repetitions; + PUINT_8 pucReqIeBuf; + enum RM_REQ_PRIORITY ePriority; + BOOLEAN fgRmIsOngoing; + BOOLEAN fgInitialLoop; + + struct BCN_RM_PARAMS rBcnRmParam; +}; + +struct RADIO_MEASUREMENT_REPORT_PARAMS { + UINT_16 u2ReportFrameLen; /* the total length of Measurement Report elements */ + PUINT_8 pucReportFrameBuff; + /* Variables to collect report */ + LINK_T rReportLink; /* a link to save received report entry */ + LINK_T rFreeReportLink; +}; + +#if CFG_SUPPORT_DFS +struct CHANNEL_SWITCH_ANNOUNCE_PARAMS { + BOOLEAN fgReadyToSwitch; + BOOLEAN fgHasSCOIE; + BOOLEAN fgHasWideBandIE; + UINT_8 ucNewChannel; + ENUM_CHNL_EXT_T eNewSCO; + UINT_8 ucNewVhtBw; + UINT_8 ucNewVhtS1; + UINT_8 ucNewVhtS2; +}; +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define RM_EXIST_REPORT(_prRmReportParam) \ + (((struct RADIO_MEASUREMENT_REPORT_PARAMS *)_prRmReportParam)->u2ReportFrameLen == \ + OFFSET_OF(ACTION_RM_REPORT_FRAME, aucInfoElem)) + +/* 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 || \ + IS_BSS_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) +#define RLM_NET_IS_11AC(_prBssInfo) \ + ((_prBssInfo)->ucPhyTypeSet & PHY_TYPE_SET_802_11AC) + +/* 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 rlmRspGenerateBssMaxIdlePeriodIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + +VOID rlmGenerateMTKOuiIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + +BOOLEAN rlmParseCheckMTKOuiIE(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuf, IN PUINT_32 pu4Cap); + +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); + +#if CFG_SUPPORT_TDLS +UINT_32 +rlmFillHtCapIEByParams(BOOLEAN fg40mAllowed, + BOOLEAN fgShortGIDisabled, + UINT_8 u8SupportRxSgi20, + UINT_8 u8SupportRxSgi40, UINT_8 u8SupportRxGf, ENUM_OP_MODE_T eCurrentOPMode, UINT_8 *pOutBuf); + +UINT_32 rlmFillHtCapIEByAdapter(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, UINT_8 *pOutBuf); + +UINT_32 rlmFillVhtCapIEByAdapter(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, UINT_8 *pOutBuf); + +#endif + +#if CFG_SUPPORT_802_11AC +VOID rlmReqGenerateVhtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + +VOID rlmRspGenerateVhtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + +VOID rlmRspGenerateVhtOpIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + +VOID rlmFillVhtOpIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo); +#endif + +#if CFG_SUPPORT_DFS +VOID rlmProcessSpecMgtAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); + +VOID +rlmSendOpModeNotificationFrame(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, UINT_8 ucChannelWidth, UINT_8 ucNss); + +#endif +VOID rlmProcessNeighborReportResonse(P_ADAPTER_T prAdapter, P_WLAN_ACTION_FRAME prAction, UINT_16 u2PacketLen); +VOID rlmTxNeighborReportRequest(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, struct SUB_ELEMENT_LIST *prSubIEs); + +VOID rlmGenerateRRMEnabledCapIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +VOID rlmGeneratePowerCapIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +VOID rlmProcessRadioMeasurementRequest(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); + +VOID rlmProcessLinkMeasurementRequest(P_ADAPTER_T prAdapter, P_WLAN_ACTION_FRAME prAction); + +VOID rlmProcessNeighborReportResonse(P_ADAPTER_T prAdapter, P_WLAN_ACTION_FRAME prAction, UINT_16 u2PacketLen); + +VOID rlmFillRrmCapa(PUINT_8 pucCapa); + +VOID rlmSetMaxTxPwrLimit(IN P_ADAPTER_T prAdapter, INT_8 cLimit, UINT_8 ucEnable); + +VOID rlmStartNextMeasurement(P_ADAPTER_T prAdapter, BOOLEAN fgNewStarted); + +BOOLEAN rlmBcnRmRunning(P_ADAPTER_T prAdapter); + +BOOLEAN rlmFillScanMsg(P_ADAPTER_T prAdapter, struct _MSG_SCN_SCAN_REQ_V3_T *prMsg); + +VOID rlmDoBeaconMeasurement(P_ADAPTER_T prAdapter, ULONG ulParam); + +VOID rlmTxNeighborReportRequest(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, struct SUB_ELEMENT_LIST *prSubIEs); + +VOID rlmTxRadioMeasurementReport(P_ADAPTER_T prAdapter); + +VOID rlmCancelRadioMeasurement(P_ADAPTER_T prAdapter); + +enum RM_REQ_PRIORITY rlmGetRmRequestPriority(PUINT_8 pucDestAddr); + +VOID rlmRunEventProcessNextRm(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr); + +VOID rlmScheduleNextRm(P_ADAPTER_T prAdapter); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#ifndef _lint +static __KAL_INLINE__ VOID rlmDataTypeCheck(VOID) +{ +} +#endif /* _lint */ + +#endif /* _RLM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rlm_domain.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rlm_domain.h new file mode 100644 index 0000000000000..9b4e56bf1d860 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rlm_domain.h @@ -0,0 +1,526 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rlm_domain.h#1 + */ + +/* + * ! \file "rlm_domain.h" + * \brief + */ + +#ifndef _RLM_DOMAIN_H +#define _RLM_DOMAIN_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define MAX_SUBBAND_NUM 6 +#define MAX_SUBBAND_NUM_5G 8 + +#define COUNTRY_CODE_NULL ((UINT_16)0x0) + +/* ISO/IEC 3166-1 two-character country codes */ + +#define COUNTRY_CODE_AD (((UINT_16) 'A' << 8) | (UINT_16) 'D') /* Andorra */ +#define COUNTRY_CODE_AE (((UINT_16) 'A' << 8) | (UINT_16) 'E') /* UAE */ +#define COUNTRY_CODE_AF (((UINT_16) 'A' << 8) | (UINT_16) 'F') /* Afghanistan */ +#define COUNTRY_CODE_AG (((UINT_16) 'A' << 8) | (UINT_16) 'G') /* Antigua & Barbuda */ +#define COUNTRY_CODE_AI (((UINT_16) 'A' << 8) | (UINT_16) 'I') /* Anguilla */ +#define COUNTRY_CODE_AL (((UINT_16) 'A' << 8) | (UINT_16) 'L') /* Albania */ +#define COUNTRY_CODE_AM (((UINT_16) 'A' << 8) | (UINT_16) 'M') /* Armenia */ +#define COUNTRY_CODE_AN (((UINT_16) 'A' << 8) | (UINT_16) 'N') /* Netherlands Antilles */ +#define COUNTRY_CODE_AO (((UINT_16) 'A' << 8) | (UINT_16) 'O') /* Angola */ +#define COUNTRY_CODE_AR (((UINT_16) 'A' << 8) | (UINT_16) 'R') /* Argentina */ +#define COUNTRY_CODE_AS (((UINT_16) 'A' << 8) | (UINT_16) 'S') /* American Samoa (USA) */ +#define COUNTRY_CODE_AT (((UINT_16) 'A' << 8) | (UINT_16) 'T') /* Austria */ +#define COUNTRY_CODE_AU (((UINT_16) 'A' << 8) | (UINT_16) 'U') /* Australia */ +#define COUNTRY_CODE_AW (((UINT_16) 'A' << 8) | (UINT_16) 'W') /* Aruba */ +#define COUNTRY_CODE_AZ (((UINT_16) 'A' << 8) | (UINT_16) 'Z') /* Azerbaijan */ +#define COUNTRY_CODE_BA (((UINT_16) 'B' << 8) | (UINT_16) 'A') /* Bosnia and Herzegovina */ +#define COUNTRY_CODE_BB (((UINT_16) 'B' << 8) | (UINT_16) 'B') /* Barbados */ +#define COUNTRY_CODE_BD (((UINT_16) 'B' << 8) | (UINT_16) 'D') /* Bangladesh */ +#define COUNTRY_CODE_BE (((UINT_16) 'B' << 8) | (UINT_16) 'E') /* Belgium */ +#define COUNTRY_CODE_BF (((UINT_16) 'B' << 8) | (UINT_16) 'F') /* Burkina Faso */ +#define COUNTRY_CODE_BG (((UINT_16) 'B' << 8) | (UINT_16) 'G') /* Bulgaria */ +#define COUNTRY_CODE_BH (((UINT_16) 'B' << 8) | (UINT_16) 'H') /* Bahrain */ +#define COUNTRY_CODE_BI (((UINT_16) 'B' << 8) | (UINT_16) 'I') /* Burundi */ +#define COUNTRY_CODE_BJ (((UINT_16) 'B' << 8) | (UINT_16) 'J') /* Benin */ +#define COUNTRY_CODE_BM (((UINT_16) 'B' << 8) | (UINT_16) 'M') /* Bermuda */ +#define COUNTRY_CODE_BN (((UINT_16) 'B' << 8) | (UINT_16) 'N') /* Brunei */ +#define COUNTRY_CODE_BO (((UINT_16) 'B' << 8) | (UINT_16) 'O') /* Bolivia */ +#define COUNTRY_CODE_BR (((UINT_16) 'B' << 8) | (UINT_16) 'R') /* Brazil */ +#define COUNTRY_CODE_BS (((UINT_16) 'B' << 8) | (UINT_16) 'S') /* Bahamas */ +#define COUNTRY_CODE_BT (((UINT_16) 'B' << 8) | (UINT_16) 'T') /* Bhutan */ +#define COUNTRY_CODE_BW (((UINT_16) 'B' << 8) | (UINT_16) 'W') /* Botswana */ +#define COUNTRY_CODE_BY (((UINT_16) 'B' << 8) | (UINT_16) 'Y') /* Belarus */ +#define COUNTRY_CODE_BZ (((UINT_16) 'B' << 8) | (UINT_16) 'Z') /* Belize */ +#define COUNTRY_CODE_CA (((UINT_16) 'C' << 8) | (UINT_16) 'A') /* Canada */ +#define COUNTRY_CODE_CD (((UINT_16) 'C' << 8) | (UINT_16) 'D') /* Congo. Democratic Republic of the */ +#define COUNTRY_CODE_CF (((UINT_16) 'C' << 8) | (UINT_16) 'F') /* Central African Republic */ +#define COUNTRY_CODE_CG (((UINT_16) 'C' << 8) | (UINT_16) 'G') /* Congo. Republic of the */ +#define COUNTRY_CODE_CH (((UINT_16) 'C' << 8) | (UINT_16) 'H') /* Switzerland */ +#define COUNTRY_CODE_CI (((UINT_16) 'C' << 8) | (UINT_16) 'I') /* Cote d'lvoire */ +#define COUNTRY_CODE_CK (((UINT_16) 'C' << 8) | (UINT_16) 'K') /* Cook Island */ +#define COUNTRY_CODE_CL (((UINT_16) 'C' << 8) | (UINT_16) 'L') /* Chile */ +#define COUNTRY_CODE_CM (((UINT_16) 'C' << 8) | (UINT_16) 'M') /* Cameroon */ +#define COUNTRY_CODE_CN (((UINT_16) 'C' << 8) | (UINT_16) 'N') /* China */ +#define COUNTRY_CODE_CO (((UINT_16) 'C' << 8) | (UINT_16) 'O') /* Columbia */ +#define COUNTRY_CODE_CR (((UINT_16) 'C' << 8) | (UINT_16) 'R') /* Costa Rica */ +#define COUNTRY_CODE_CU (((UINT_16) 'C' << 8) | (UINT_16) 'U') /* Cuba */ +#define COUNTRY_CODE_CV (((UINT_16) 'C' << 8) | (UINT_16) 'V') /* Cape Verde */ +#define COUNTRY_CODE_CX (((UINT_16) 'C' << 8) | (UINT_16) 'X') /* "Christmas Island(Australia) */ +#define COUNTRY_CODE_CY (((UINT_16) 'C' << 8) | (UINT_16) 'Y') /* Cyprus */ +#define COUNTRY_CODE_CZ (((UINT_16) 'C' << 8) | (UINT_16) 'Z') /* Czech */ +#define COUNTRY_CODE_DE (((UINT_16) 'D' << 8) | (UINT_16) 'E') /* Germany */ +#define COUNTRY_CODE_DJ (((UINT_16) 'D' << 8) | (UINT_16) 'J') /* Djibouti */ +#define COUNTRY_CODE_DK (((UINT_16) 'D' << 8) | (UINT_16) 'K') /* Denmark */ +#define COUNTRY_CODE_DM (((UINT_16) 'D' << 8) | (UINT_16) 'M') /* Dominica */ +#define COUNTRY_CODE_DO (((UINT_16) 'D' << 8) | (UINT_16) 'O') /* Dominican Republic */ +#define COUNTRY_CODE_DZ (((UINT_16) 'D' << 8) | (UINT_16) 'Z') /* Algeria */ +#define COUNTRY_CODE_EC (((UINT_16) 'E' << 8) | (UINT_16) 'C') /* Ecuador */ +#define COUNTRY_CODE_EE (((UINT_16) 'E' << 8) | (UINT_16) 'E') /* Estonia */ +#define COUNTRY_CODE_EG (((UINT_16) 'E' << 8) | (UINT_16) 'G') /* Egypt */ +#define COUNTRY_CODE_EH (((UINT_16) 'E' << 8) | (UINT_16) 'H') /* Western Sahara (Morocco) */ +#define COUNTRY_CODE_ER (((UINT_16) 'E' << 8) | (UINT_16) 'R') /* Eritrea */ +#define COUNTRY_CODE_ES (((UINT_16) 'E' << 8) | (UINT_16) 'S') /* Spain */ +#define COUNTRY_CODE_ET (((UINT_16) 'E' << 8) | (UINT_16) 'T') /* Ethiopia */ +#define COUNTRY_CODE_EU (((UINT_16) 'E' << 8) | (UINT_16) 'U') /* Europe */ +#define COUNTRY_CODE_FI (((UINT_16) 'F' << 8) | (UINT_16) 'I') /* Finland */ +#define COUNTRY_CODE_FJ (((UINT_16) 'F' << 8) | (UINT_16) 'J') /* Fiji */ +#define COUNTRY_CODE_FK (((UINT_16) 'F' << 8) | (UINT_16) 'K') /* Falkland Island */ +#define COUNTRY_CODE_FM (((UINT_16) 'F' << 8) | (UINT_16) 'M') /* Micronesia */ +#define COUNTRY_CODE_FO (((UINT_16) 'F' << 8) | (UINT_16) 'O') /* Faroe Island */ +#define COUNTRY_CODE_FR (((UINT_16) 'F' << 8) | (UINT_16) 'R') /* France */ +#define COUNTRY_CODE_FR (((UINT_16) 'F' << 8) | (UINT_16) 'R') /* Wallis and Futuna (France) */ +#define COUNTRY_CODE_GA (((UINT_16) 'G' << 8) | (UINT_16) 'A') /* Gabon */ +#define COUNTRY_CODE_GB (((UINT_16) 'G' << 8) | (UINT_16) 'B') /* United Kingdom */ +#define COUNTRY_CODE_GD (((UINT_16) 'G' << 8) | (UINT_16) 'D') /* Grenada */ +#define COUNTRY_CODE_GE (((UINT_16) 'G' << 8) | (UINT_16) 'E') /* Georgia */ +#define COUNTRY_CODE_GF (((UINT_16) 'G' << 8) | (UINT_16) 'F') /* French Guiana */ +#define COUNTRY_CODE_GG (((UINT_16) 'G' << 8) | (UINT_16) 'G') /* Guernsey */ +#define COUNTRY_CODE_GH (((UINT_16) 'G' << 8) | (UINT_16) 'H') /* Ghana */ +#define COUNTRY_CODE_GI (((UINT_16) 'G' << 8) | (UINT_16) 'I') /* Gibraltar */ +#define COUNTRY_CODE_GM (((UINT_16) 'G' << 8) | (UINT_16) 'M') /* Gambia */ +#define COUNTRY_CODE_GN (((UINT_16) 'G' << 8) | (UINT_16) 'N') /* Guinea */ +#define COUNTRY_CODE_GP (((UINT_16) 'G' << 8) | (UINT_16) 'P') /* Guadeloupe */ +#define COUNTRY_CODE_GQ (((UINT_16) 'G' << 8) | (UINT_16) 'Q') /* Equatorial Guinea */ +#define COUNTRY_CODE_GR (((UINT_16) 'G' << 8) | (UINT_16) 'R') /* Greece */ +#define COUNTRY_CODE_GT (((UINT_16) 'G' << 8) | (UINT_16) 'T') /* Guatemala */ +#define COUNTRY_CODE_GU (((UINT_16) 'G' << 8) | (UINT_16) 'U') /* Guam */ +#define COUNTRY_CODE_GW (((UINT_16) 'G' << 8) | (UINT_16) 'W') /* Guinea-Bissau */ +#define COUNTRY_CODE_GY (((UINT_16) 'G' << 8) | (UINT_16) 'Y') /* Guyana */ +#define COUNTRY_CODE_HK (((UINT_16) 'H' << 8) | (UINT_16) 'K') /* Hong Kong */ +#define COUNTRY_CODE_HN (((UINT_16) 'H' << 8) | (UINT_16) 'N') /* Honduras */ +#define COUNTRY_CODE_HR (((UINT_16) 'H' << 8) | (UINT_16) 'R') /* Croatia */ +#define COUNTRY_CODE_HT (((UINT_16) 'H' << 8) | (UINT_16) 'T') /* Haiti */ +#define COUNTRY_CODE_HU (((UINT_16) 'H' << 8) | (UINT_16) 'U') /* Hungary */ +#define COUNTRY_CODE_ID (((UINT_16) 'I' << 8) | (UINT_16) 'D') /* Indonesia */ +#define COUNTRY_CODE_IE (((UINT_16) 'I' << 8) | (UINT_16) 'E') /* Ireland */ +#define COUNTRY_CODE_IL (((UINT_16) 'I' << 8) | (UINT_16) 'L') /* Israel */ +#define COUNTRY_CODE_IM (((UINT_16) 'I' << 8) | (UINT_16) 'M') /* Isle of Man */ +#define COUNTRY_CODE_IN (((UINT_16) 'I' << 8) | (UINT_16) 'N') /* India */ +#define COUNTRY_CODE_IQ (((UINT_16) 'I' << 8) | (UINT_16) 'Q') /* Iraq */ +#define COUNTRY_CODE_IR (((UINT_16) 'I' << 8) | (UINT_16) 'R') /* Iran */ +#define COUNTRY_CODE_IS (((UINT_16) 'I' << 8) | (UINT_16) 'S') /* Iceland */ +#define COUNTRY_CODE_IT (((UINT_16) 'I' << 8) | (UINT_16) 'T') /* Italy */ +#define COUNTRY_CODE_JE (((UINT_16) 'J' << 8) | (UINT_16) 'E') /* Jersey */ +#define COUNTRY_CODE_JM (((UINT_16) 'J' << 8) | (UINT_16) 'M') /* Jameica */ +#define COUNTRY_CODE_JO (((UINT_16) 'J' << 8) | (UINT_16) 'O') /* Jordan */ +#define COUNTRY_CODE_JP (((UINT_16) 'J' << 8) | (UINT_16) 'P') /* Japan */ +#define COUNTRY_CODE_KE (((UINT_16) 'K' << 8) | (UINT_16) 'E') /* Kenya */ +#define COUNTRY_CODE_KG (((UINT_16) 'K' << 8) | (UINT_16) 'G') /* Kyrgyzstan */ +#define COUNTRY_CODE_KH (((UINT_16) 'K' << 8) | (UINT_16) 'H') /* Cambodia */ +#define COUNTRY_CODE_KI (((UINT_16) 'K' << 8) | (UINT_16) 'I') /* Kiribati */ +#define COUNTRY_CODE_KM (((UINT_16) 'K' << 8) | (UINT_16) 'M') /* Comoros */ +#define COUNTRY_CODE_KN (((UINT_16) 'K' << 8) | (UINT_16) 'N') /* Saint Kitts and Nevis */ +#define COUNTRY_CODE_KP (((UINT_16) 'K' << 8) | (UINT_16) 'P') /* North Korea */ +#define COUNTRY_CODE_KR (((UINT_16) 'K' << 8) | (UINT_16) 'R') /* South Korea */ +#define COUNTRY_CODE_KW (((UINT_16) 'K' << 8) | (UINT_16) 'W') /* Kuwait */ +#define COUNTRY_CODE_KY (((UINT_16) 'K' << 8) | (UINT_16) 'Y') /* Cayman Islands */ +#define COUNTRY_CODE_KZ (((UINT_16) 'K' << 8) | (UINT_16) 'Z') /* Kazakhstan */ +#define COUNTRY_CODE_LA (((UINT_16) 'L' << 8) | (UINT_16) 'A') /* Laos */ +#define COUNTRY_CODE_LB (((UINT_16) 'L' << 8) | (UINT_16) 'B') /* Lebanon */ +#define COUNTRY_CODE_LC (((UINT_16) 'L' << 8) | (UINT_16) 'C') /* Saint Lucia */ +#define COUNTRY_CODE_LI (((UINT_16) 'L' << 8) | (UINT_16) 'I') /* Liechtenstein */ +#define COUNTRY_CODE_LK (((UINT_16) 'L' << 8) | (UINT_16) 'K') /* Sri Lanka */ +#define COUNTRY_CODE_LR (((UINT_16) 'L' << 8) | (UINT_16) 'R') /* Liberia */ +#define COUNTRY_CODE_LS (((UINT_16) 'L' << 8) | (UINT_16) 'S') /* Lesotho */ +#define COUNTRY_CODE_LT (((UINT_16) 'L' << 8) | (UINT_16) 'T') /* Lithuania */ +#define COUNTRY_CODE_LU (((UINT_16) 'L' << 8) | (UINT_16) 'U') /* Luxemburg */ +#define COUNTRY_CODE_LV (((UINT_16) 'L' << 8) | (UINT_16) 'V') /* Latvia */ +#define COUNTRY_CODE_LY (((UINT_16) 'L' << 8) | (UINT_16) 'Y') /* Libya */ +#define COUNTRY_CODE_MA (((UINT_16) 'M' << 8) | (UINT_16) 'A') /* Morocco */ +#define COUNTRY_CODE_MC (((UINT_16) 'M' << 8) | (UINT_16) 'C') /* Monaco */ +#define COUNTRY_CODE_MD (((UINT_16) 'M' << 8) | (UINT_16) 'D') /* Moldova */ +#define COUNTRY_CODE_ME (((UINT_16) 'M' << 8) | (UINT_16) 'E') /* Montenegro */ +#define COUNTRY_CODE_MF (((UINT_16) 'M' << 8) | (UINT_16) 'F') /* + * Saint Martin / Sint Marteen + * (Added on window's list) + */ +#define COUNTRY_CODE_MG (((UINT_16) 'M' << 8) | (UINT_16) 'G') /* Madagascar */ +#define COUNTRY_CODE_MH (((UINT_16) 'M' << 8) | (UINT_16) 'H') /* Marshall Islands */ +#define COUNTRY_CODE_MK (((UINT_16) 'M' << 8) | (UINT_16) 'K') /* Macedonia */ +#define COUNTRY_CODE_ML (((UINT_16) 'M' << 8) | (UINT_16) 'L') /* Mali */ +#define COUNTRY_CODE_MM (((UINT_16) 'M' << 8) | (UINT_16) 'M') /* Myanmar */ +#define COUNTRY_CODE_MN (((UINT_16) 'M' << 8) | (UINT_16) 'N') /* Mongolia */ +#define COUNTRY_CODE_MO (((UINT_16) 'M' << 8) | (UINT_16) 'O') /* Macao */ +#define COUNTRY_CODE_MP (((UINT_16) 'M' << 8) | (UINT_16) 'P') /* + * Northern Mariana Islands (Rota Island. + * Saipan and Tinian Island) + */ +#define COUNTRY_CODE_MQ (((UINT_16) 'M' << 8) | (UINT_16) 'Q') /* Martinique (France) */ +#define COUNTRY_CODE_MR (((UINT_16) 'M' << 8) | (UINT_16) 'R') /* Mauritania */ +#define COUNTRY_CODE_MS (((UINT_16) 'M' << 8) | (UINT_16) 'S') /* Montserrat (UK) */ +#define COUNTRY_CODE_MT (((UINT_16) 'M' << 8) | (UINT_16) 'T') /* Malta */ +#define COUNTRY_CODE_MU (((UINT_16) 'M' << 8) | (UINT_16) 'U') /* Mauritius */ +#define COUNTRY_CODE_MV (((UINT_16) 'M' << 8) | (UINT_16) 'V') /* Maldives */ +#define COUNTRY_CODE_MW (((UINT_16) 'M' << 8) | (UINT_16) 'W') /* Malawi */ +#define COUNTRY_CODE_MX (((UINT_16) 'M' << 8) | (UINT_16) 'X') /* Mexico */ +#define COUNTRY_CODE_MY (((UINT_16) 'M' << 8) | (UINT_16) 'Y') /* Malaysia */ +#define COUNTRY_CODE_MZ (((UINT_16) 'M' << 8) | (UINT_16) 'Z') /* Mozambique */ +#define COUNTRY_CODE_NA (((UINT_16) 'N' << 8) | (UINT_16) 'A') /* Namibia */ +#define COUNTRY_CODE_NC (((UINT_16) 'N' << 8) | (UINT_16) 'C') /* New Caledonia */ +#define COUNTRY_CODE_NE (((UINT_16) 'N' << 8) | (UINT_16) 'E') /* Niger */ +#define COUNTRY_CODE_NF (((UINT_16) 'N' << 8) | (UINT_16) 'F') /* Norfolk Island */ +#define COUNTRY_CODE_NG (((UINT_16) 'N' << 8) | (UINT_16) 'G') /* Nigeria */ +#define COUNTRY_CODE_NI (((UINT_16) 'N' << 8) | (UINT_16) 'I') /* Nicaragua */ +#define COUNTRY_CODE_NL (((UINT_16) 'N' << 8) | (UINT_16) 'L') /* Netherlands */ +#define COUNTRY_CODE_NO (((UINT_16) 'N' << 8) | (UINT_16) 'O') /* Norway */ +#define COUNTRY_CODE_NP (((UINT_16) 'N' << 8) | (UINT_16) 'P') /* Nepal */ +#define COUNTRY_CODE_NR (((UINT_16) 'N' << 8) | (UINT_16) 'R') /* Nauru */ +#define COUNTRY_CODE_NU (((UINT_16) 'N' << 8) | (UINT_16) 'U') /* Niue */ +#define COUNTRY_CODE_NZ (((UINT_16) 'N' << 8) | (UINT_16) 'Z') /* New Zealand */ +#define COUNTRY_CODE_OM (((UINT_16) 'O' << 8) | (UINT_16) 'M') /* Oman */ +#define COUNTRY_CODE_PA (((UINT_16) 'P' << 8) | (UINT_16) 'A') /* Panama */ +#define COUNTRY_CODE_PE (((UINT_16) 'P' << 8) | (UINT_16) 'E') /* Peru */ +#define COUNTRY_CODE_PF (((UINT_16) 'P' << 8) | (UINT_16) 'F') /* "French Polynesia */ +#define COUNTRY_CODE_PG (((UINT_16) 'P' << 8) | (UINT_16) 'G') /* Papua New Guinea */ +#define COUNTRY_CODE_PH (((UINT_16) 'P' << 8) | (UINT_16) 'H') /* Philippines */ +#define COUNTRY_CODE_PK (((UINT_16) 'P' << 8) | (UINT_16) 'K') /* Pakistan */ +#define COUNTRY_CODE_PL (((UINT_16) 'P' << 8) | (UINT_16) 'L') /* Poland */ +#define COUNTRY_CODE_PM (((UINT_16) 'P' << 8) | (UINT_16) 'M') /* Saint Pierre and Miquelon */ +#define COUNTRY_CODE_PN (((UINT_16) 'P' << 8) | (UINT_16) 'N') /* Pitcairn Islands */ +#define COUNTRY_CODE_PR (((UINT_16) 'P' << 8) | (UINT_16) 'R') /* Puerto Rico (USA) */ +#define COUNTRY_CODE_PS (((UINT_16) 'P' << 8) | (UINT_16) 'S') /* Palestinian Authority */ +#define COUNTRY_CODE_PT (((UINT_16) 'P' << 8) | (UINT_16) 'T') /* Portugal */ +#define COUNTRY_CODE_PW (((UINT_16) 'P' << 8) | (UINT_16) 'W') /* Palau */ +#define COUNTRY_CODE_PY (((UINT_16) 'P' << 8) | (UINT_16) 'Y') /* Paraguay */ +#define COUNTRY_CODE_QA (((UINT_16) 'Q' << 8) | (UINT_16) 'A') /* Qatar */ +#define COUNTRY_CODE_RE (((UINT_16) 'R' << 8) | (UINT_16) 'E') /* Reunion (France) */ +#define COUNTRY_CODE_RKS (((UINT_16) 'R' << 8) | (UINT_16) 'K') /* Kosvo (Added on window's list) */ +#define COUNTRY_CODE_RO (((UINT_16) 'R' << 8) | (UINT_16) 'O') /* Romania */ +#define COUNTRY_CODE_RS (((UINT_16) 'R' << 8) | (UINT_16) 'S') /* Serbia */ +#define COUNTRY_CODE_RU (((UINT_16) 'R' << 8) | (UINT_16) 'U') /* Russia */ +#define COUNTRY_CODE_RW (((UINT_16) 'R' << 8) | (UINT_16) 'W') /* Rwanda */ +#define COUNTRY_CODE_SA (((UINT_16) 'S' << 8) | (UINT_16) 'A') /* Saudi Arabia */ +#define COUNTRY_CODE_SB (((UINT_16) 'S' << 8) | (UINT_16) 'B') /* Solomon Islands */ +#define COUNTRY_CODE_SC (((UINT_16) 'S' << 8) | (UINT_16) 'C') /* Seychelles */ +#define COUNTRY_CODE_SD (((UINT_16) 'S' << 8) | (UINT_16) 'D') /* Sudan */ +#define COUNTRY_CODE_SE (((UINT_16) 'S' << 8) | (UINT_16) 'E') /* Sweden */ +#define COUNTRY_CODE_SG (((UINT_16) 'S' << 8) | (UINT_16) 'G') /* Singapole */ +#define COUNTRY_CODE_SI (((UINT_16) 'S' << 8) | (UINT_16) 'I') /* Slovenia */ +#define COUNTRY_CODE_SK (((UINT_16) 'S' << 8) | (UINT_16) 'K') /* Slovakia */ +#define COUNTRY_CODE_SL (((UINT_16) 'S' << 8) | (UINT_16) 'L') /* Sierra Leone */ +#define COUNTRY_CODE_SM (((UINT_16) 'S' << 8) | (UINT_16) 'M') /* San Marino */ +#define COUNTRY_CODE_SN (((UINT_16) 'S' << 8) | (UINT_16) 'N') /* Senegal */ +#define COUNTRY_CODE_SO (((UINT_16) 'S' << 8) | (UINT_16) 'O') /* Somalia */ +#define COUNTRY_CODE_SR (((UINT_16) 'S' << 8) | (UINT_16) 'R') /* Suriname */ +#define COUNTRY_CODE_SS (((UINT_16) 'S' << 8) | (UINT_16) 'S') /* South_Sudan */ +#define COUNTRY_CODE_ST (((UINT_16) 'S' << 8) | (UINT_16) 'T') /* Sao Tome and Principe */ +#define COUNTRY_CODE_SV (((UINT_16) 'S' << 8) | (UINT_16) 'V') /* El Salvador */ +#define COUNTRY_CODE_SY (((UINT_16) 'S' << 8) | (UINT_16) 'Y') /* Syria */ +#define COUNTRY_CODE_SZ (((UINT_16) 'S' << 8) | (UINT_16) 'Z') /* Swaziland */ +#define COUNTRY_CODE_TC (((UINT_16) 'T' << 8) | (UINT_16) 'C') /* Turks and Caicos Islands (UK) */ +#define COUNTRY_CODE_TD (((UINT_16) 'T' << 8) | (UINT_16) 'D') /* Chad */ +#define COUNTRY_CODE_TF (((UINT_16) 'T' << 8) | (UINT_16) 'F') /* French Southern and Antarctic Lands */ +#define COUNTRY_CODE_TG (((UINT_16) 'T' << 8) | (UINT_16) 'G') /* Togo */ +#define COUNTRY_CODE_TH (((UINT_16) 'T' << 8) | (UINT_16) 'H') /* Thailand */ +#define COUNTRY_CODE_TJ (((UINT_16) 'T' << 8) | (UINT_16) 'J') /* Tajikistan */ +#define COUNTRY_CODE_TL (((UINT_16) 'T' << 8) | (UINT_16) 'L') /* East Timor */ +#define COUNTRY_CODE_TM (((UINT_16) 'T' << 8) | (UINT_16) 'M') /* Turkmenistan */ +#define COUNTRY_CODE_TN (((UINT_16) 'T' << 8) | (UINT_16) 'N') /* Tunisia */ +#define COUNTRY_CODE_TO (((UINT_16) 'T' << 8) | (UINT_16) 'O') /* Tonga */ +#define COUNTRY_CODE_TR (((UINT_16) 'T' << 8) | (UINT_16) 'R') /* Turkey */ +#define COUNTRY_CODE_TT (((UINT_16) 'T' << 8) | (UINT_16) 'T') /* Trinidad and Tobago */ +#define COUNTRY_CODE_TV (((UINT_16) 'T' << 8) | (UINT_16) 'V') /* Tuvalu */ +#define COUNTRY_CODE_TW (((UINT_16) 'T' << 8) | (UINT_16) 'W') /* Taiwan */ +#define COUNTRY_CODE_TZ (((UINT_16) 'T' << 8) | (UINT_16) 'Z') /* Tanzania */ +#define COUNTRY_CODE_UA (((UINT_16) 'U' << 8) | (UINT_16) 'A') /* Ukraine */ +#define COUNTRY_CODE_UG (((UINT_16) 'U' << 8) | (UINT_16) 'G') /* Ugnada */ +#define COUNTRY_CODE_US (((UINT_16) 'U' << 8) | (UINT_16) 'S') /* US */ +#define COUNTRY_CODE_UY (((UINT_16) 'U' << 8) | (UINT_16) 'Y') /* Uruguay */ +#define COUNTRY_CODE_UZ (((UINT_16) 'U' << 8) | (UINT_16) 'Z') /* Uzbekistan */ +#define COUNTRY_CODE_VA (((UINT_16) 'V' << 8) | (UINT_16) 'A') /* Vatican (Holy See) */ +#define COUNTRY_CODE_VC (((UINT_16) 'V' << 8) | (UINT_16) 'C') /* Saint Vincent and the Grenadines */ +#define COUNTRY_CODE_VE (((UINT_16) 'V' << 8) | (UINT_16) 'E') /* Venezuela */ +#define COUNTRY_CODE_VG (((UINT_16) 'V' << 8) | (UINT_16) 'G') /* British Virgin Islands */ +#define COUNTRY_CODE_VI (((UINT_16) 'V' << 8) | (UINT_16) 'I') /* US Virgin Islands */ +#define COUNTRY_CODE_VN (((UINT_16) 'V' << 8) | (UINT_16) 'N') /* Vietnam */ +#define COUNTRY_CODE_VU (((UINT_16) 'V' << 8) | (UINT_16) 'U') /* Vanuatu */ +#define COUNTRY_CODE_WS (((UINT_16) 'W' << 8) | (UINT_16) 'S') /* Samoa */ +#define COUNTRY_CODE_YE (((UINT_16) 'Y' << 8) | (UINT_16) 'E') /* Yemen */ +#define COUNTRY_CODE_YT (((UINT_16) 'Y' << 8) | (UINT_16) 'T') /* Mayotte (France) */ +#define COUNTRY_CODE_ZA (((UINT_16) 'Z' << 8) | (UINT_16) 'A') /* South Africa */ +#define COUNTRY_CODE_ZM (((UINT_16) 'Z' << 8) | (UINT_16) 'M') /* Zambia */ +#define COUNTRY_CODE_ZW (((UINT_16) 'Z' << 8) | (UINT_16) 'W') /* Zimbabwe */ + +/* dot11RegDomainsSupportValue */ +#define MIB_REG_DOMAIN_FCC 0x10 /* FCC (US) */ +#define MIB_REG_DOMAIN_IC 0x20 /* IC or DOC (Canada) */ +#define MIB_REG_DOMAIN_ETSI 0x30 /* ETSI (Europe) */ +#define MIB_REG_DOMAIN_SPAIN 0x31 /* Spain */ +#define MIB_REG_DOMAIN_FRANCE 0x32 /* France */ +#define MIB_REG_DOMAIN_JAPAN 0x40 /* MPHPT (Japan) */ +#define MIB_REG_DOMAIN_OTHER 0x00 /* other */ + +/* 2.4G */ +#define BAND_2G4_LOWER_BOUND 1 +#define BAND_2G4_UPPER_BOUND 14 +/* 5G SubBand FCC spec */ +#define UNII1_LOWER_BOUND 36 +#define UNII1_UPPER_BOUND 48 +#define UNII2A_LOWER_BOUND 52 +#define UNII2A_UPPER_BOUND 64 +#define UNII2C_LOWER_BOUND 100 +#define UNII2C_UPPER_BOUND 144 +#define UNII3_LOWER_BOUND 149 +#define UNII3_UPPER_BOUND 173 + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +#define POWER_LIMIT_TABLE_NULL 0xFFFF +#define MAX_TX_POWER 63 +#define MIN_TX_POWER -64 +#define MAX_CMD_SUPPORT_CHANNEL_NUM 64 + +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +typedef enum _ENUM_POWER_LIMIT_T { + PWR_LIMIT_CCK, + PWR_LIMIT_20M, + PWR_LIMIT_40M, + PWR_LIMIT_80M, + PWR_LIMIT_160M, + PWR_LIMIT_NUM +} ENUM_POWER_LIMIT_T, *P_ENUM_POWER_LIMIT_T; + +#endif + +typedef enum _ENUM_POWER_LIMIT_SUBBAND_T { + POWER_LIMIT_2G4, + POWER_LIMIT_UNII1, + POWER_LIMIT_UNII2A, + POWER_LIMIT_UNII2C, + POWER_LIMIT_UNII3, + POWER_LIMIT_SUBAND_NUM +} ENUM_POWER_LIMIT_SUBBAND_T, *P_ENUM_POWER_LIMIT_SUBBAND_T; + +/* Define channel offset in unit of 5MHz bandwidth */ +typedef enum _ENUM_CHNL_SPAN_T { + CHNL_SPAN_5 = 1, + CHNL_SPAN_10 = 2, + CHNL_SPAN_20 = 4, + CHNL_SPAN_40 = 8 +} ENUM_CHNL_SPAN_T, *P_ENUM_CHNL_SPAN_T; + +/* Define BSS operating bandwidth */ +typedef enum _ENUM_CHNL_BW_T { + CHNL_BW_20, + CHNL_BW_20_40, + CHNL_BW_10, + CHNL_BW_5 +} ENUM_CHNL_BW_T, *P_ENUM_CHNL_BW_T; + +/* In all bands, the first channel will be SCA and the second channel is SCB, + * then iteratively. + * Note the final channel will not be SCA. + */ +typedef struct _DOMAIN_SUBBAND_INFO { + /* Note1: regulation class depends on operation bandwidth and RF band. + * For example: 2.4GHz, 1~13, 20MHz ==> regulation class = 81 + * 2.4GHz, 1~13, SCA ==> regulation class = 83 + * 2.4GHz, 1~13, SCB ==> regulation class = 84 + * Note2: TX power limit is not specified here because path loss is unknown + */ + UINT_8 ucRegClass; /* Regulation class for 20MHz */ + UINT_8 ucBand; /* Type: ENUM_BAND_T */ + UINT_8 ucChannelSpan; /* Type: ENUM_CHNL_SPAN_T */ + UINT_8 ucFirstChannelNum; + UINT_8 ucNumChannels; + UINT_8 fgDfs; /* Type: BOOLEAN */ +} DOMAIN_SUBBAND_INFO, *P_DOMAIN_SUBBAND_INFO; + +/* Use it as all available channel list for STA */ +typedef struct _DOMAIN_INFO_ENTRY { + PUINT_16 pu2CountryGroup; + UINT_32 u4CountryNum; + + /* If different attributes, put them into different rSubBands. + * For example, DFS shall be used or not. + */ + DOMAIN_SUBBAND_INFO rSubBand[MAX_SUBBAND_NUM]; +} DOMAIN_INFO_ENTRY, *P_DOMAIN_INFO_ENTRY; + + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +typedef struct _CHANNEL_POWER_LIMIT { + UINT_8 ucCentralCh; + INT_8 cPwrLimitCCK; + INT_8 cPwrLimit20; + INT_8 cPwrLimit40; + INT_8 cPwrLimit80; + INT_8 cPwrLimit160; + UINT_8 ucFlag; + UINT_8 aucReserved[1]; +} CHANNEL_POWER_LIMIT, *P_CHANNEL_POWER_LIMIT; + +typedef struct _COUNTRY_CHANNEL_POWER_LIMIT { + UINT_8 aucCountryCode[2]; + UINT_8 ucCountryFlag; + UINT_8 ucChannelNum; + UINT_8 aucReserved[4]; + CHANNEL_POWER_LIMIT rChannelPowerLimit[80]; +} COUNTRY_CHANNEL_POWER_LIMIT, *P_COUNTRY_CHANNEL_POWER_LIMIT; + +#define CHANNEL_PWR_LIMIT(_channel, _pwrLimit_cck, _pwrLimit_bw20, \ + _pwrLimit_bw40, _pwrLimit_bw80, _pwrLimit_bw160, _ucFlag) \ + { \ + .ucCentralCh = (_channel), \ + .cPwrLimitCCK = (_pwrLimit_cck), \ + .cPwrLimit20 = (_pwrLimit_bw20), \ + .cPwrLimit40 = (_pwrLimit_bw40), \ + .cPwrLimit80 = (_pwrLimit_bw80), \ + .cPwrLimit160 = (_pwrLimit_bw160), \ + .ucFlag = (_ucFlag), \ + .aucReserved = {0} \ +} + +typedef struct _COUNTRY_POWER_LIMIT_TABLE_DEFAULT { + UINT_8 aucCountryCode[2]; + /* 0: ch 1 ~14 , 1: ch 36 ~48, 2: ch 52 ~64, 3: ch 100 ~144, 4: ch 149 ~165 */ + INT_8 aucPwrLimitSubBand[POWER_LIMIT_SUBAND_NUM]; + /* + * bit0: cPwrLimit2G4, bit1: cPwrLimitUnii1; bit2: cPwrLimitUnii2A; + * bit3: cPwrLimitUnii2C; bit4: cPwrLimitUnii3; mW: 0, mW\MHz : 1 + */ + UINT_8 ucPwrUnit; +} COUNTRY_POWER_LIMIT_TABLE_DEFAULT, *P_COUNTRY_POWER_LIMIT_TABLE_DEFAULT; + +typedef struct _COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION { + UINT_8 aucCountryCode[2]; + UINT_8 ucCentralCh; + INT_8 aucPwrLimit[PWR_LIMIT_NUM]; +} COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION, *P_COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION; + +typedef struct _SUBBAND_CHANNEL_T { + UINT_8 ucStartCh; + UINT_8 ucEndCh; + UINT_8 ucInterval; + UINT_8 ucReserved; +} SUBBAND_CHANNEL_T, *P_SUBBAND_CHANNEL_T; + +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define CAL_CH_OFFSET_80M(_PRIMARY_CH, _CENTRAL_CH) \ + (((_PRIMARY_CH - _CENTRAL_CH) + 6) >> 2) + +#define CAL_CH_OFFSET_160M(_PRIMARY_CH, _CENTRAL_CH) \ + (((_PRIMARY_CH - _CENTRAL_CH) + 14) >> 2) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +P_DOMAIN_INFO_ENTRY rlmDomainGetDomainInfo(P_ADAPTER_T prAdapter); + +VOID rlmDomainGetChnlList(P_ADAPTER_T prAdapter, + ENUM_BAND_T eSpecificBand, BOOLEAN fgNoDfs, + UINT_8 ucMaxChannelNum, PUINT_8 pucNumOfChannel, P_RF_CHANNEL_INFO_T paucChannelList); + +VOID rlmDomainGetDfsChnls(P_ADAPTER_T prAdapter, + UINT_8 ucMaxChannelNum, PUINT_8 pucNumOfChannel, P_RF_CHANNEL_INFO_T paucChannelList); + +VOID rlmDomainSendCmd(P_ADAPTER_T prAdapter); + +VOID rlmDomainSendDomainInfoCmd(P_ADAPTER_T prAdapter); + +VOID rlmDomainSendPassiveScanInfoCmd(P_ADAPTER_T prAdapter); + +BOOLEAN rlmDomainIsLegalChannel(P_ADAPTER_T prAdapter, ENUM_BAND_T eBand, UINT_8 ucChannel); + +UINT_32 rlmDomainSupOperatingClassIeFill(PUINT_8 pBuf); + +BOOLEAN rlmDomainCheckChannelEntryValid(P_ADAPTER_T prAdapter, UINT_8 ucCentralCh); + +UINT_8 rlmDomainGetCenterChannel(ENUM_BAND_T eBand, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend); + +BOOLEAN rlmDomainIsValidRfSetting(P_ADAPTER_T prAdapter, ENUM_BAND_T eBand, + UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend, + ENUM_CHANNEL_WIDTH_T eChannelWidth, UINT_8 ucChannelS1, UINT_8 ucChannelS2); + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +BOOLEAN +rlmDomainCheckPowerLimitValid(P_ADAPTER_T prAdapter, + COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION rPowerLimitTableConfiguration, + UINT_8 ucPwrLimitNum); + +VOID rlmDomainCheckCountryPowerLimitTable(P_ADAPTER_T prAdapter); + +UINT_16 rlmDomainPwrLimitDefaultTableDecision(P_ADAPTER_T prAdapter, UINT_16 u2CountryCode); + +VOID rlmDomainSendPwrLimitCmd(P_ADAPTER_T prAdapter); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _RLM_DOMAIN_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rlm_obss.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rlm_obss.h new file mode 100644 index 0000000000000..db6cdb747cce6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rlm_obss.h @@ -0,0 +1,108 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rlm_obss.h#1 +*/ + +/* + * ! \file "rlm_obss.h" + * \brief + */ + +#ifndef _RLM_OBSS_H +#define _RLM_OBSS_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define CHNL_LIST_SZ_2G 14 +#define CHNL_LIST_SZ_5G 14 + +#define CHNL_LEVEL0 0 +#define CHNL_LEVEL1 1 +#define CHNL_LEVEL2 2 + +#define AFFECTED_CHNL_OFFSET 5 + +/*#define OBSS_SCAN_MIN_INTERVAL 10 *//* In unit of sec */ + +#define PUBLIC_ACTION_MAX_LEN 200 /* In unit of byte */ + +/* P2P GO only */ +/* Define default OBSS Scan parameters (from MIB in spec.) */ +#define dot11OBSSScanPassiveDwell 20 +#define dot11OBSSScanActiveDwell 10 +#define dot11OBSSScanPassiveTotalPerChannel 200 +#define dot11OBSSScanActiveTotalPerChannel 20 +#define dot11BSSWidthTriggerScanInterval 300 /* Unit: sec */ +#define dot11BSSWidthChannelTransitionDelayFactor 5 +#define dot11OBSSScanActivityThreshold 25 + +#define OBSS_20_40M_TIMEOUT (dot11BSSWidthTriggerScanInterval + 10) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/* Control MAC PCO function */ +typedef enum _ENUM_SYS_PCO_PHASE_T { + SYS_PCO_PHASE_DISABLED = 0, + SYS_PCO_PHASE_20M, + SYS_PCO_PHASE_40M +} ENUM_SYS_PCO_PHASE_T, *P_ENUM_SYS_PCO_PHASE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID rlmObssInit(P_ADAPTER_T prAdapter); + +VOID rlmObssScanDone(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr); + +VOID rlmObssTriggerScan(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _RLM_OBSS_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rlm_protection.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rlm_protection.h new file mode 100644 index 0000000000000..cd72a2dbfa46a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rlm_protection.h @@ -0,0 +1,105 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rlm_protection.h#1 +*/ + +/* + * ! \file "rlm_protection.h" + * \brief + */ + +#ifndef _RLM_PROTECTION_H +#define _RLM_PROTECTION_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_SYS_PROTECT_MODE_T { + SYS_PROTECT_MODE_NONE = 0, /* Mode 0 */ + SYS_PROTECT_MODE_ERP, /* Mode 1 */ + SYS_PROTECT_MODE_NON_HT, /* Mode 2 */ + SYS_PROTECT_MODE_20M, /* Mode 3 */ + + SYS_PROTECT_MODE_NUM +} ENUM_SYS_PROTECT_MODE_T, *P_ENUM_SYS_PROTECT_MODE_T; + +/* This definition follows HT Protection field of HT Operation IE */ +typedef enum _ENUM_HT_PROTECT_MODE_T { + HT_PROTECT_MODE_NONE = 0, + HT_PROTECT_MODE_NON_MEMBER, + HT_PROTECT_MODE_20M, + HT_PROTECT_MODE_NON_HT, + + HT_PROTECT_MODE_NUM +} ENUM_HT_PROTECT_MODE_T, *P_ENUM_HT_PROTECT_MODE_T; + +typedef enum _ENUM_GF_MODE_T { + GF_MODE_NORMAL = 0, + GF_MODE_PROTECT, + GF_MODE_DISALLOWED, + + GF_MODE_NUM +} ENUM_GF_MODE_T, *P_ENUM_GF_MODE_T; + +typedef enum _ENUM_RIFS_MODE_T { + RIFS_MODE_NORMAL = 0, + RIFS_MODE_DISALLOWED, + + RIFS_MODE_NUM +} ENUM_RIFS_MODE_T, *P_ENUM_RIFS_MODE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _RLM_PROTECTION_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rlm_txpwr_init.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rlm_txpwr_init.h new file mode 100644 index 0000000000000..897646506c48e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rlm_txpwr_init.h @@ -0,0 +1,1213 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rlm_txpwr_init.h#1 +*/ + +/* + * ! \file "rlm_txpwr_init.h" + * \brief + */ + +#ifndef _RLM_TXPWR_INIT_H +#define _RLM_TXPWR_INIT_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/*Support Tx Power Range : 63~ -64 (unit : 0.5dBm)*/ + +#define PWR_LIMIT_2G4_IN_MW_MHZ BIT(0) +#define PWR_LIMIT_UNII1_IN_MW_MHZ BIT(1) +#define PWR_LIMIT_UNII2A_IN_MW_MHZ BIT(2) +#define PWR_LIMIT_UNII2C_IN_MW_MHZ BIT(3) +#define PWR_LIMIT_UNII3_IN_MW_MHZ BIT(4) + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +COUNTRY_POWER_LIMIT_TABLE_DEFAULT g_rRlmPowerLimitDefault[] = { + + {{'A', 'O'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'B', 'Z'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'B', 'J'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'B', 'T'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'B', 'O'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'B', 'I'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'C', 'M'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'C', 'F'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'T', 'D'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'K', 'M'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'C', 'D'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'C', 'G'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'C', 'I'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'D', 'J'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'G', 'Q'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'E', 'R'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'F', 'J'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'G', 'A'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'G', 'M'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'G', 'N'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'G', 'W'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'R', 'K'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'K', 'G'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'L', 'Y'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'M', 'G'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'M', 'L'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'N', 'R'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'N', 'C'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'T'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'C'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'L'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'B'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'O'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'R'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'Z'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'T', 'J'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'T', 'G'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'T', 'O'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'T', 'M'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'T', 'V'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'V', 'U'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'Y', 'E'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'A', 'S'} + , {60, 34, 46, 48, 60} + , 0} + , + {{'A', 'I'} + , {60, 34, 48, 60, 60} + , 0} + , + {{'B', 'M'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'C', 'A'} + , {60, 46, 48, 48, 60} + , 0} + , + {{'K', 'Y'} + , {60, 34, 48, 60, 60} + , 0} + , + {{'G', 'U'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'F', 'M'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'P', 'R'} + , {60, 34, 46, 48, 60} + , 0} + , + {{'U', 'S'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'V', 'I'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'A', 'R'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'A', 'U'} + , {63, 46, 46, 60, 63} + , 0} + , + {{'A', 'Z'} + , {40, 34, 48, 60, 60} + , 0} + , + {{'B', 'W'} + , {40, 46, 46, 60, 60} + , 0} + , + {{'K', 'H'} + , {40, 46, 46, 48, 60} + , 0} + , + {{'C', 'X'} + , {63, 46, 46, 60, 63} + , 0} + , + {{'C', 'O'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'C', 'R'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'E', 'C'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'G', 'D'} + , {40, 46, 46, 60, 60} + , 0} + , + {{'G', 'T'} + , {40, 34, 48, 48, 60} + , 0} + , + {{'H', 'K'} + , {63, 46, 46, 60, 63} + , 0} + , + {{'K', 'I'} + , {63, 46, 46, 60, 63} + , 0} + , + {{'L', 'B'} + , {40, 46, 46, 46, 46} + , 0} + , + {{'L', 'R'} + , {60, 46, 60, 63, 63} + , 0} + , + {{'M', 'N'} + , {46, 32, 46, 46, 58} + , 0} + , + {{'A', 'N'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'N', 'Z'} + , {63, 46, 60, 48, 63} + , 0} + , + {{'N', 'I'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'P', 'W'} + , {60, 60, 60, 60, 60} + , 0} + , + {{'P', 'Y'} + , {60, 46, 46, 48, 60} + , 0} + , + {{'P', 'E'} + , {54, 46, 48, 42, 48} + , 0} + , + {{'P', 'H'} + , {40, 46, 46, 48, 48} + , 0} + , + {{'W', 'S'} + , {40, 40, 40, 40, 60} + , 0} + , + {{'S', 'G'} + , {46, 46, 46, 60, 60} + , 0} + , + {{'L', 'K'} + , {46, 46, 46, 46, 46} + , 0} + , + {{'T', 'H'} + , {40, 46, 46, 60, 60} + , 0} + , + {{'T', 'T'} + , {60, 46, 46, 60, 60} + , 0} + , + {{'U', 'Y'} + , {63, 46, 46, 46, 46} + , 0} + , + {{'V', 'N'} + , {46, 46, 46, 60, 60} + , 0} + , + {{'A', 'W'} + , {60, 46, 60, 60, 63} + , 0} + , + {{'L', 'A'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'S', 'A'} + , {40, 46, 46, 60, 60} + , 0} + , + {{'A', 'E'} + , {40, 46, 46, 60, 46} + , 0} + , + {{'U', 'G'} + , {40, 46, 46, 48, 60} + , 0} + , + {{'M', 'M'} + , {40, 46, 46, 60, 60} + , 0} + , + {{'A', 'L'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'D', 'Z'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'A', 'D'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'A', 'T'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'B', 'Y'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'B', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'B', 'A'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'V', 'G'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'B', 'G'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'C', 'V'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'H', 'R'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'C', 'Y'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'C', 'Z'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'D', 'K'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'E', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'E', 'T'} + , {40, 40, 40, 40, 63} + , 0} + , + {{'F', 'I'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'F', 'R'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'G', 'F'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'P', 'F'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'T', 'F'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'G', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'D', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'G', 'H'} + , {40, 34, 48, 60, 63} + , 0} + , + {{'G', 'R'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'G', 'P'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'H', 'U'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'I', 'S'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'I', 'Q'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'I', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'I', 'T'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'K', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'L', 'V'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'L', 'S'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'L', 'I'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'L', 'T'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'L', 'U'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'K'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'T'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'Q'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'R'} + , {40, 46, 46, 46, 63} + , 0} + , + {{'M', 'U'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'Y', 'T'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'D'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'C'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'S'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'N', 'L'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'N', 'O'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'O', 'M'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'P', 'L'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'P', 'T'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'R', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'R', 'O'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'F'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'S', 'M'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'S', 'N'} + , {40, 40, 40, 60, 63} + , 0} + , + {{'R', 'S'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'S', 'K'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'S', 'I'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'Z', 'A'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'E', 'S'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'S', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'C', 'H'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'T', 'R'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'T', 'C'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'G', 'B'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'V', 'A'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'A', 'M'} + , {40, 40, 40, 63, 63} + , 0} + , + {{'I', 'L'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'K', 'W'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'M', 'A'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'N', 'E'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'T', 'N'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'E', 'H'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'N', 'P'} + , {60, 46, 46, 63, 60} + , 0} + , + {{'A', 'F'} + , {40, 46, 63, 63, 63} + , 0} + , + {{'A', 'G'} + , {40, 46, 48, 63, 54} + , 0} + , + {{'B', 'S'} + , {63, 46, 60, 63, 63} + , 0} + , + {{'B', 'H'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'B', 'B'} + , {40, 46, 48, 63, 54} + , 0} + , + {{'B', 'N'} + , {46, 46, 46, 63, 60} + , 0} + , + {{'C', 'L'} + , {40, 44, 44, 63, 44} + , 0} + , + {{'C', 'N'} + , {40, 46, 46, 63, 54} + , 0} + , + {{'E', 'G'} + , {40, 46, 46, 63, 46} + , 0} + , + {{'S', 'V'} + , {60, 34, 48, 63, 60} + , 0} + , + {{'I', 'N'} + , {60, 46, 46, 63, 60} + , 0} + , + {{'M', 'Y'} + , {54, 60, 60, 63, 60} + , 0} + , + {{'M', 'V'} + , {40, 46, 46, 63, 40} + , 0} + , + {{'P', 'A'} + , {60, 34, 48, 63, 60} + , 0} + , + {{'V', 'E'} + , {60, 46, 46, 63, 60} + , 0} + , + {{'Z', 'M'} + , {60, 46, 46, 63, 60} + , 0} + , + {{'J', 'O'} + , {40, 46, 63, 63, 46} + , 0} + , + {{'P', 'G'} + , {40, 46, 63, 63, 60} + , 0} + , + {{'B', 'F'} + , {40, 63, 63, 63, 60} + , 0} + , + {{'G', 'Y'} + , {60, 63, 63, 63, 60} + , 0} + , + {{'H', 'T'} + , {40, 63, 63, 63, 60} + , 0} + , + {{'H', 'N'} + , {60, 63, 63, 63, 60} + , 0} + , + {{'J', 'M'} + , {54, 63, 63, 63, 57} + , 0} + , + {{'M', 'O'} + , {40, 63, 63, 63, 40} + , 0} + , + {{'M', 'W'} + , {60, 63, 63, 63, 60} + , 0} + , + {{'P', 'K'} + , {40, 63, 63, 63, 40} + , 0} + , + {{'Q', 'A'} + , {40, 63, 63, 63, 40} + , 0} + , + {{'R', 'W'} + , {40, 63, 63, 63, 60} + , 0} + , + {{'K', 'N'} + , {40, 63, 63, 63, 60} + , 0} + , + {{'T', 'Z'} + , {40, 63, 63, 63, 40} + , 0} + , + {{'I', 'D'} + , {46, 63, 63, 63, 60} + , 0} + , + {{'N', 'G'} + , {40, 63, 46, 63, 60} + , 0} + , + {{'B', 'D'} + , {40, 46, 46, 60, 28} + , 0} + , + {{'B', 'R'} + , {52, 46, 46, 60, 60} + , 0} + , + {{'D', 'M'} + , {60, 34, 46, 48, 60} + , 0} + , + {{'D', 'O'} + , {63, 46, 46, 60, 63} + , 0} + , + {{'F', 'K'} + , {40, 46, 46, 60, 28} + , 0} + , + {{'K', 'Z'} + , {40, 34, 48, 60, 60} + , 0} + , + {{'M', 'X'} + , {60, 34, 48, 60, 63} + , 0} + , + {{'M', 'Z'} + , {40, 34, 46, 48, 60} + , 0} + , + {{'N', 'A'} + , {40, 34, 46, 48, 60} + , 0} + , + {{'R', 'U'} + , {40, 34, 48, 60, 60} + , 0} + , + {{'L', 'C'} + , {40, 34, 48, 48, 60} + , 0} + , + {{'V', 'C'} + , {40, 34, 46, 48, 60} + , 0} + , + {{'U', 'A'} + , {40, 46, 46, 46, 48} + , 0} + , + {{'U', 'Z'} + , {40, 48, 48, 48, 60} + , 0} + , + {{'Z', 'W'} + , {40, 34, 46, 48, 60} + , 0} + , + {{'M', 'P'} + , {60, 34, 46, 48, 60} + , 0} + , + {{'T', 'W'} + , {60, 63, 34, 48, 60} + , 0} + , + {{'C', 'K'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'C', 'U'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'T', 'L'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'F', 'O'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'G', 'I'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'G', 'G'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'I', 'R'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'I', 'M'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'J', 'E'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'K', 'P'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'M', 'H'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'N', 'U'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'N', 'F'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'P', 'S'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'P', 'N'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'P', 'M'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'S', 'S'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'S', 'D'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'S', 'Y'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'J', 'P'} + , {46, 46, 46, 60, 63} + , 0} + , + {{'K', 'R'} + , {46, 34, 46, 46, 46} + , PWR_LIMIT_UNII1_IN_MW_MHZ} + , + +/*Default*/ + {{0, 0} + , {63, 63, 63, 63, 63} + , 0} +}; + +COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION g_rRlmPowerLimitConfiguration[] = { + + {{'A', 'I'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'A', 'Z'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'B', 'W'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'G', 'D'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'L', 'B'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'L', 'R'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'W', 'S'} + , 165, {40, 40, 40, 40, 40} + } + , + {{'V', 'N'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'U', 'S'} + , 1, {38, 30, 60, 60, 60} + } + , + {{'U', 'S'} + , 3, {60, 60, 26, 60, 60} + } + , + {{'U', 'S'} + , 9, {60, 60, 26, 60, 60} + } + , + {{'U', 'S'} + , 11, {38, 30, 60, 60, 60} + } + , + {{'U', 'S'} + , 36, {34, 34, 34, 34, 34} + } + , + {{'U', 'S'} + , 38, {34, 34, 34, 34, 34} + } + , + {{'U', 'S'} + , 42, {34, 34, 34, 31, 34} + } + , + {{'U', 'S'} + , 58, {48, 48, 48, 31, 48} + } + , + {{'U', 'S'} + , 62, {48, 48, 34, 48, 48} + } + , + {{'U', 'S'} + , 64, {37, 37, 48, 48, 48} + } + , + {{'U', 'S'} + , 100, {37, 37, 48, 48, 48} + } + , + {{'U', 'S'} + , 102, {48, 48, 34, 48, 48} + } + , + {{'U', 'S'} + , 106, {48, 48, 48, 31, 48} + } + , + {{'U', 'S'} + , 155, {60, 60, 60, 31, 60} + } + , + {{'U', 'S'} + , 159, {60, 60, 34, 60, 60} + } + , + {{'U', 'S'} + , 165, {37, 37, 60, 60, 60} + } + , + +/*Default*/ + {{0, 0} + , 165, {63, 63, 63, 63, 63} + } +}; + +#if 0 +COUNTRY_CHANNEL_POWER_LIMIT g_rRlmCountryPowerLimitTable[] = { + { + {'A', 'O'} + , 0, 0, {0, 0, 0, 0} + , + { + CHANNEL_PWR_LIMIT(1, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(2, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(3, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(4, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(5, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(6, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(7, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(8, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(9, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(10, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(11, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(12, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(13, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(14, 40, 40, 40, 40, 40, 0), + + CHANNEL_PWR_LIMIT(36, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(38, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(40, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(42, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(44, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(46, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(48, 63, 63, 63, 63, 63, 0), + + CHANNEL_PWR_LIMIT(52, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(54, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(56, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(58, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(60, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(62, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(64, 63, 63, 63, 63, 63, 0), + + CHANNEL_PWR_LIMIT(100, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(102, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(104, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(106, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(108, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(110, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(112, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(114, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(116, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(118, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(120, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(122, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(124, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(126, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(128, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(130, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(132, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(134, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(136, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(138, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(140, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(142, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(144, 63, 63, 63, 63, 63, 0), + + CHANNEL_PWR_LIMIT(149, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(151, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(153, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(155, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(157, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(159, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(161, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(163, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(165, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(167, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(169, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(171, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(173, 63, 63, 63, 63, 63, 0) + } + } + , + { + /*Used to check the end of country entry */ + {0, 0} + , 0, 0, {0, 0, 0, 0} + , + { + /*Used to check the end of channel power limit */ + CHANNEL_PWR_LIMIT(ENDCH, 0, 0, 0, 0, 0, 0) + } + } /*end of CountryTable */ +}; +#endif +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#endif /* _RLM_TXPWR_INIT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/roaming_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/roaming_fsm.h new file mode 100644 index 0000000000000..de1f23016b4d9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/roaming_fsm.h @@ -0,0 +1,153 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: +*/ + +/* + * ! \file "roaming_fsm.h" + * \brief This file defines the FSM for Roaming MODULE. + * + * This file defines the FSM for Roaming MODULE. + */ + +#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 _CMD_ROAMING_TRANSIT_T { + UINT_16 u2Event; + UINT_16 u2Data; +} CMD_ROAMING_TRANSIT_T, *P_CMD_ROAMING_TRANSIT_T; + +typedef struct _CMD_ROAMING_CTRL_T { + UINT_8 fgEnable; + UINT_8 ucRcpiAdjustStep; + UINT_16 u2RcpiLowThr; + UINT_8 ucRoamingRetryLimit; + UINT_8 ucRoamingStableTimeout; +} CMD_ROAMING_CTRL_T, *P_CMD_ROAMING_CTRL_T; + + /**/ typedef enum _ENUM_ROAMING_STATE_T { + ROAMING_STATE_IDLE = 0, + ROAMING_STATE_DECISION, + ROAMING_STATE_DISCOVERY, + ROAMING_STATE_REQ_CAND_LIST, + 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; + + BOOLEAN fgDrvRoamingAllow; + TIMER_T rWaitCandidateTimer; +} 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_CMD_ROAMING_TRANSIT_T prTransit); + +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_CMD_ROAMING_TRANSIT_T prTransit); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _ROAMING_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rsn.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rsn.h new file mode 100644 index 0000000000000..198800f1d42d0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/rsn.h @@ -0,0 +1,244 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rsn.h#1 +*/ + +/* + * ! \file rsn.h + * \brief The wpa/rsn related define, macro and structure are described here. + */ + +#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 +#define RSN_CIPHER_SUITE_SAE 0x08AC0F00 +#define RSN_CIPHER_SUITE_OWE 0x12AC0F00 + +#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 +#define RSN_AKM_SUITE_FT_802_1X 0x03AC0F00 +#define RSN_AKM_SUITE_FT_PSK 0x04AC0F00 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) +#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03 +#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04 +#endif +/* Add AKM SUITE for OWE since kernel haven't defined it. */ +#define WLAN_AKM_SUITE_OWE 0x000FAC12 + +#if CFG_SUPPORT_802_11W +#define RSN_AKM_SUITE_802_1X_SHA256 0x05AC0F00 +#define RSN_AKM_SUITE_PSK_SHA256 0x06AC0F00 +#endif + +#define RSN_AKM_SUITE_SAE 0x08AC0F00 +#define RSN_AKM_SUITE_8021X_SUITE_B 0x0BAC0F00 +#define RSN_AKM_SUITE_8021X_SUITE_B_192 0x0CAC0F00 +#define RSN_AKM_SUITE_OWE 0x12AC0F00 + + +#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) + +#define ELEM_MAX_LEN_ASSOC_RSP_WSC_IE (32 - ELEM_HDR_LEN) +#define ELEM_MAX_LEN_TIMEOUT_IE (5) + +/******************************************************************************* +* 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 rsnIsSuitableBSS(IN P_ADAPTER_T prAdapter, IN P_RSN_INFO_T prBssRsnInfo); + +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); + +#if CFG_SUPPORT_AAA +void rsnParserCheckForRSNCCMPPSK(P_ADAPTER_T prAdapter, P_RSN_INFO_ELEM_T prIe, + P_STA_RECORD_T prStaRec, PUINT_16 pu2StatusCode); +#endif + +VOID rsnTkipHandleMICFailure(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta, IN BOOLEAN fgErrorKeyType); + +VOID rsnSelectPmkidCandidateList(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); + +VOID rsnUpdatePmkidCandidateList(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); + +BOOLEAN rsnSearchPmkidEntry(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBssid, OUT PUINT_32 pu4EntryIndex); + +BOOLEAN rsnCheckPmkidCandicate(IN P_ADAPTER_T prAdapter); + +VOID rsnCheckPmkidCache(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBss); + +VOID rsnGeneratePmkidIndication(IN P_ADAPTER_T prAdapter); + +VOID rsnIndicatePmkidCand(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); +#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, IN ULONG ulParamPtr); + +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); + +uint16_t rsnPmfCapableValidation(IN P_ADAPTER_T + prAdapter, IN P_BSS_INFO_T prBssInfo, + IN P_STA_RECORD_T prStaRec); + +void rsnPmfGenerateTimeoutIE(P_ADAPTER_T prAdapter, + P_MSDU_INFO_T prMsduInfo); + +void rsnApStartSaQuery(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec); + +void rsnApSaQueryAction(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb); + +#endif + +#if CFG_SUPPORT_AAA +VOID rsnGenerateWSCIEForAssocRsp(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); +#endif + +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE +BOOLEAN rsnCheckSecurityModeChanged(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_BSS_DESC_T prBssDesc); +#endif + +UINT_32 +rsnCalculateFTIELen(P_ADAPTER_T prAdapter, UINT_8 ucBssIdx, P_STA_RECORD_T prStaRec); + +VOID rsnGenerateFTIE(IN P_ADAPTER_T prAdapter, IN OUT P_MSDU_INFO_T prMsduInfo); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _RSN_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/scan.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/scan.h new file mode 100644 index 0000000000000..c7dc40de10a78 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/scan.h @@ -0,0 +1,818 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: @(#) + */ + +/* + * ! \file "scan.h" + * \brief + */ + +#ifndef _SCAN_H +#define _SCAN_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_vendor.h" +#include "cnm_timer.h" +/******************************************************************************* +* 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_ROAM_MAX_BUFFER_SIZE (CFG_MAX_NUM_ROAM_BSS_LIST * ALIGN_4(sizeof(ROAM_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 20 /* This is used by POLICY SMART WEAKEST, + * If exceed this value, remove weakest BSS_DESC_T + * with same SSID first in large network. + */ + +#define REMOVE_TIMEOUT_TWO_DAY (60*60*24*2) + +#if 1 +#define SCN_BSS_DESC_REMOVE_TIMEOUT_SEC 30 +#define SCN_BSS_DESC_STALE_SEC 10 /* 2.4G + 5G need 8.1s */ +#if CFG_ENABLE_WIFI_DIRECT +#if CFG_SUPPORT_WFD +#define SCN_BSS_DESC_STALE_SEC_WFD 20 /* For WFD scan need about 15s. */ +#endif +#endif + +#else +#define SCN_BSS_DESC_REMOVE_TIMEOUT_SEC 5 /* Second. */ + /* This is used by POLICY TIMEOUT, + * If exceed this value, remove timeout BSS_DESC_T. + */ + +#endif + +#define SCN_PROBE_DELAY_MSEC 0 + +#define SCN_ADHOC_BSS_DESC_TIMEOUT_SEC 5 /* Second. */ +#if CFG_ENABLE_WIFI_DIRECT +#if CFG_SUPPORT_WFD +#define SCN_ADHOC_BSS_DESC_TIMEOUT_SEC_WFD 20 /* Second. For WFD scan timeout. */ +#endif +#endif + +#define SCN_NLO_NETWORK_CHANNEL_NUM (4) + +#define SCAN_DONE_DIFFERENCE 3 +#define SCAN_DONE_TIMEOUT_THRESHOLD 3 +/*----------------------------------------------------------------------------*/ +/* 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) /* two probe req will be sent, wildcard and specified */ +#define SCAN_REQ_SSID_SPECIFIED_ONLY BIT(3) /* only a specified ssid probe request will be sent */ + +/*----------------------------------------------------------------------------*/ +/* Support Multiple SSID SCAN */ +/*----------------------------------------------------------------------------*/ +#define SCN_SSID_MAX_NUM CFG_SCAN_SSID_MAX_NUM +#define SCN_SSID_MATCH_MAX_NUM CFG_SCAN_SSID_MATCH_MAX_NUM + +#if CFG_SUPPORT_AGPS_ASSIST +#define SCN_AGPS_AP_LIST_MAX_NUM 32 +#endif + +#define SCN_BSS_JOIN_FAIL_CNT_RESET_SEC 15 +#define SCN_BSS_JOIN_FAIL_RESET_STEP 2 + +#if CFG_SUPPORT_BATCH_SCAN +/*----------------------------------------------------------------------------*/ +/* SCAN_BATCH_REQ */ +/*----------------------------------------------------------------------------*/ +#define SCAN_BATCH_REQ_START BIT(0) +#define SCAN_BATCH_REQ_STOP BIT(1) +#define SCAN_BATCH_REQ_RESULT BIT(2) +#endif + +#define SCAN_NLO_CHECK_SSID_ONLY 0x00000001 +#define SCAN_NLO_DEFAULT_INTERVAL 30000 +/* PNO min period 30s, max period 300s */ +#define SCAN_NLO_MIN_INTERVAL 30 +#define SCAN_NLO_MAX_INTERVAL 300 +#define SCN_BSS_JOIN_FAIL_THRESHOLD 4 +#define AIS_BSS_ADD_BLACKLIST_THRESHOLD 2 + +#define SWC_NUM_BSSID_THRESHOLD_DEFAULT 8 +#define SWC_RSSI_WINDSIZE_DEFAULT 8 +#define LOST_AP_WINDOW 16 +#define MAX_CHANNEL_NUM_PER_BUCKETS 8 + +/******************************************************************************* +* 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_FW_SCAN_STATE_T { + FW_SCAN_STATE_IDLE = 0, /* 0 */ + FW_SCAN_STATE_SCAN_START, /* 1 */ + FW_SCAN_STATE_REQ_CHANNEL, /* 2 */ + FW_SCAN_STATE_SET_CHANNEL, /* 3 */ + FW_SCAN_STATE_DELAYED_ACTIVE_PROB_REQ, /* 4 */ + FW_SCAN_STATE_ACTIVE_PROB_REQ, /* 5 */ + FW_SCAN_STATE_LISTEN, /* 6 */ + FW_SCAN_STATE_SCAN_DONE, /* 7 */ + FW_SCAN_STATE_NLO_START, /* 8 */ + FW_SCAN_STATE_NLO_HIT_CHECK, /* 9 */ + FW_SCAN_STATE_NLO_STOP, /* 10 */ + FW_SCAN_STATE_BATCH_START, /* 11 */ + FW_SCAN_STATE_BATCH_CHECK, /* 12 */ + FW_SCAN_STATE_BATCH_STOP, /* 13 */ + FW_SCAN_STATE_NUM /* 14 */ +} ENUM_FW_SCAN_STATE_T; + +typedef enum _ENUM_SCAN_CHANNEL_T { + SCAN_CHANNEL_FULL = 0, + SCAN_CHANNEL_2G4, + SCAN_CHANNEL_5G, + SCAN_CHANNEL_P2P_SOCIAL, + SCAN_CHANNEL_SPECIFIED, + SCAN_CHANNEL_NUM +} ENUM_SCAN_CHANNEL, *P_ENUM_SCAN_CHANNEL; + +typedef struct _MSG_SCN_FSM_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_32 u4Dummy; +} MSG_SCN_FSM_T, *P_MSG_SCN_FSM_T; + +typedef enum _ENUM_PSCAN_STATE_T { + PSCN_IDLE = 0, + PSCN_RESET, + PSCN_SCANNING, + PSCAN_STATE_T_NUM +} ENUM_PSCAN_STATE_T; + +/*----------------------------------------------------------------------------*/ +/* BSS Descriptors */ +/*----------------------------------------------------------------------------*/ +struct _BSS_DESC_T { + LINK_ENTRY_T rLinkEntry; + LINK_ENTRY_T rLinkEntryEss; + + 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; + BOOLEAN fgIsVHTPresent; + + 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_CHANNEL_WIDTH_T eChannelWidth; /*VHT operation ie */ + UINT_8 ucCenterFreqS1; + UINT_8 ucCenterFreqS2; + ENUM_BAND_T eBand; + + UINT_8 ucDTIMPeriod; + BOOLEAN fgDTIMPresent; + + 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; + BOOLEAN fgIsP2PReport; /* TRUE: report to upper layer */ + P_P2P_DEVICE_DESC_T prP2pDesc; + + UINT_8 aucIntendIfAddr[MAC_ADDR_LEN]; /* For IBSS, the SrcAddr is different from BSSID */ + /* UINT_8 ucDevCapabilityBitmap; *//* Device Capability Attribute. (P2P_DEV_CAPABILITY_XXXX) */ + /* UINT_8 ucGroupCapabilityBitmap; *//* Group Capability Attribute. (P2P_GROUP_CAPABILITY_XXXX) */ + + LINK_T rP2pDeviceList; + + /* P_LINK_T prP2pDeviceList; */ + + /* + * For + * 1. P2P Capability. + * 2. P2P Device ID. ( in aucSrcAddr[] ) + * 3. NOA (TODO:) + * 4. Extend Listen Timing. (Probe Rsp) (TODO:) + * 5. P2P Device Info. (Probe Rsp) + * 6. P2P Group Info. (Probe Rsp) + */ +#endif + + BOOLEAN fgIsIEOverflow; /* The received IE length exceed the maximum IE buffer size */ + UINT_16 u2RawLength; /* The byte count of aucRawBuf[] */ + UINT_16 u2IELength; /* The byte count of aucIEBuf[] */ + + ULARGE_INTEGER u8TimeStamp; /* Place u8TimeStamp before aucIEBuf[1] to force DW align */ + UINT_8 aucRawBuf[CFG_RAW_BUFFER_SIZE]; + UINT_8 aucIEBuf[CFG_IE_BUFFER_SIZE]; + UINT_8 ucJoinFailureCount; + UINT_16 u2JoinStatus; + OS_SYSTIME rJoinFailTime; + struct AIS_BLACKLIST_ITEM *prBlack; + UINT_16 u2StaCnt; + UINT_16 u2AvaliableAC; /* Available Admission Capacity */ + UINT_8 ucChnlUtilization; + UINT_8 ucSNR; + BOOLEAN fgSeenProbeResp; + BOOLEAN fgExsitBssLoadIE; + BOOLEAN fgMultiAnttenaAndSTBC; + BOOLEAN fgDeauthLastTime; + UINT_32 u4UpdateIdx; + INT_8 cPowerLimit; + UINT_8 aucRrmCap[5]; + /* fgRptCfg80211, rAddBssDescTime and u2ReturnLine are used to debug driver scan result didn't + ** update but cfg80211 scan result has updated issue, after find root cause, need to delete them + */ + BOOLEAN fgRptCfg80211; + UINT_16 u2ReturnLine; + OS_SYSTIME rAddBssDescTime; +}; + +struct _ROAM_BSS_DESC_T { + LINK_ENTRY_T rLinkEntry; + UINT_8 ucSSIDLen; + UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; + OS_SYSTIME rUpdateTime; +}; + +typedef struct _SCAN_PARAM_T { /* Used by SCAN FSM */ + /* Active or Passive */ + ENUM_SCAN_TYPE_T eScanType; + + /* Network Type */ + UINT_8 ucBssIndex; + + /* 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; + + /* TODO: Find Specific Device Type. */ +#endif /* CFG_SUPPORT_P2P */ + UINT_16 u2DefaultDwellTime; + UINT_16 u2ChannelDwellTime; + UINT_16 u2MinChannelDwellTime; + UINT_8 aucBSSID[MAC_ADDR_LEN]; + UINT_16 u2TimeoutValue; + + BOOLEAN fgIsObssScan; + UINT_8 ucScanVersion; + + /* Run time flags */ + UINT_16 u2ProbeDelayTime; + + /* channel information */ + ENUM_SCAN_CHANNEL eScanChannel; + UINT_8 ucChannelListNum; + RF_CHANNEL_INFO_T arChnlInfoList[MAXIMUM_OPERATION_CHANNEL_LIST]; + UINT_8 aucRandomMac[MAC_ADDR_LEN]; + UINT_8 ucScnFuncMask; + /* Feedback information */ + UINT_8 ucSeqNum; + + /* Information Element */ + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; + +} SCAN_PARAM_T, *P_SCAN_PARAM_T; + +typedef struct _NLO_PARAM_T { /* Used by SCAN FSM */ + UINT_8 ucSeqNum; + /* Network Type */ + UINT_8 ucBssIndex; + + /* NLO */ + BOOLEAN fgStopAfterIndication; + UINT_8 ucFastScanIteration; + UINT_16 u2FastScanPeriod; + UINT_16 u2SlowScanPeriod; + + /* Hidden SSID, Match Set SSID */ +#if CFG_SUPPORT_SCHED_SCN_SSID_SETS + UINT_8 ucSSIDNum; +#endif + UINT_8 ucMatchSSIDNum; + struct NLO_NETWORK rNLONetwork; + P_BSS_DESC_T aprPendingBssDescToInd[SCN_SSID_MATCH_MAX_NUM]; +} NLO_PARAM_T, *P_NLO_PARAM_T; + +typedef struct _SCAN_INFO_T { + ENUM_SCAN_STATE_T eCurrentState; /* Store the STATE variable of SCAN FSM */ + + OS_SYSTIME rLastScanCompletedTime; + + SCAN_PARAM_T rScanParam; + NLO_PARAM_T rNloParam; + + UINT_32 u4NumOfBssDesc; + + UINT_8 aucScanBuffer[SCN_MAX_BUFFER_SIZE]; + + LINK_T rBSSDescList; + + LINK_T rFreeBSSDescList; + + LINK_T rPendingMsgList; + + UINT_8 aucScanRoamBuffer[SCN_ROAM_MAX_BUFFER_SIZE]; + LINK_T rRoamFreeBSSDescList; + LINK_T rRoamBSSDescList; + + /* Sparse Channel Detection */ + BOOLEAN fgIsSparseChannelValid; + RF_CHANNEL_INFO_T rSparseChannel; + + /* NLO scanning state tracking */ + BOOLEAN fgNloScanning; +#if CFG_SUPPORT_SCN_PSCN + BOOLEAN fgPscnOngoing; + BOOLEAN fgGScnConfigSet; + BOOLEAN fgGScnParamSet; + BOOLEAN fgGScnAction; + P_CMD_SET_PSCAN_PARAM prPscnParam; + ENUM_PSCAN_STATE_T eCurrentPSCNState; +#endif +#if CFG_SUPPORT_GSCN + P_PARAM_WIFI_GSCAN_FULL_RESULT prGscnFullResult; +#endif + + TIMER_T rScanDoneTimer; + UINT_8 ucScanDoneTimeoutCnt; +} 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 ucBssIndex; + 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]; + UINT_16 u2ChannelDwellTime; /* ms unit */ + UINT_16 u2TimeoutValue; /* ms unit */ + UINT_16 u2MinChannelDwellTime; /* In TU. 1024us. */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; + 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 ucBssIndex; + 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. */ + UINT_16 u2TimeoutValue; /* ms unit */ + UINT_16 u2MinChannelDwellTime; /* In TU. 1024us. */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; + 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; +struct _MSG_SCN_SCAN_REQ_V3_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + UINT_8 ucBssIndex; + 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. */ + UINT_16 u2TimeoutValue; /* ms unit */ + UINT_16 u2MinChannelDwellTime; /* In TU. 1024us. */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; + UINT_8 aucRandomMac[MAC_ADDR_LEN]; + UINT_8 ucScnFuncMask; + 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]; +}; + + +typedef struct _MSG_SCN_SCAN_CANCEL_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + UINT_8 ucBssIndex; + BOOLEAN fgIsChannelExt; +} MSG_SCN_SCAN_CANCEL, *P_MSG_SCN_SCAN_CANCEL; + +typedef struct _tagOFFLOAD_NETWORK { + UINT_8 aucSsid[ELEM_MAX_LEN_SSID]; + UINT_8 ucSsidLen; + UINT_8 ucUnicastCipher; /* ENUM_NLO_CIPHER_ALGORITHM */ + UINT_16 u2AuthAlgo; /* ENUM_NLO_AUTH_ALGORITHM */ + UINT_8 aucChannelList[SCN_NLO_NETWORK_CHANNEL_NUM]; +} OFFLOAD_NETWORK, *P_OFFLOAD_NETWORK; + +typedef struct _MSG_SCN_NLO_REQ_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + BOOLEAN fgStopAfterIndication; + UINT_8 ucSeqNum; + UINT_8 ucBssIndex; + UINT_32 u4FastScanPeriod; + UINT_32 u4FastScanIterations; + UINT_32 u4SlowScanPeriod; + UINT_32 u4NumOfEntries; + OFFLOAD_NETWORK arNetwork[CFG_SCAN_SSID_MAX_NUM]; +} MSG_SCN_NLO_REQ, *P_MSG_SCN_NLO_REQ; + +typedef struct _MSG_SCN_NLO_CANCEL_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + UINT_8 ucBssIndex; +} MSG_SCN_NLO_CANCEL, *P_MSG_SCN_NLO_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 ucBssIndex; + ENUM_SCAN_STATUS eScanStatus; +} MSG_SCN_SCAN_DONE, *P_MSG_SCN_SCAN_DONE; + +#if CFG_SUPPORT_AGPS_ASSIST +typedef enum { + AGPS_PHY_A, + AGPS_PHY_B, + AGPS_PHY_G, +} AP_PHY_TYPE; + +typedef struct _AGPS_AP_INFO_T { + UINT_8 aucBSSID[MAC_ADDR_LEN]; + INT_16 i2ApRssi; /* -127..128 */ + UINT_16 u2Channel; /* 0..256 */ + AP_PHY_TYPE ePhyType; +} AGPS_AP_INFO_T, *P_AGPS_AP_INFO_T; + +typedef struct _AGPS_AP_LIST_T { + UINT_8 ucNum; + AGPS_AP_INFO_T arApInfo[SCN_AGPS_AP_LIST_MAX_NUM]; +} AGPS_AP_LIST_T, *P_AGPS_AP_LIST_T; +#endif + +typedef enum _ENUM_NLO_STATUS_T { + NLO_STATUS_FOUND = 0, + NLO_STATUS_CANCELLED, + NLO_STATUS_FAIL, + NLO_STATUS_BUSY, + NLO_STATUS_NUM +} ENUM_NLO_STATUS, *P_ENUM_NLO_STATUS; + +typedef struct _MSG_SCN_NLO_DONE_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + UINT_8 ucBssIndex; + ENUM_NLO_STATUS eNloStatus; +} MSG_SCN_NLO_DONE, *P_MSG_SCN_NLO_DONE; + +struct RM_BEACON_REPORT_PARAMS { + UINT_8 ucChannel; + UINT_8 ucRCPI; + UINT_8 ucRSNI; + UINT_8 ucAntennaID; + UINT_8 ucFrameInfo; + UINT_8 aucBcnFixedField[12]; +}; + +struct RM_MEASURE_REPORT_ENTRY { + LINK_ENTRY_T rLinkEntry; + /* should greater than sizeof(struct RM_BCN_REPORT) + + ** sizeof(IE_MEASUREMENT_REPORT_T) + RM_BCN_REPORT_SUB_ELEM_MAX_LENGTH + */ + UINT_8 aucMeasReport[260]; +}; + +/******************************************************************************* +* P U B 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 UINT_8 ucBssIndex); + +/* BSS-DESC State Change */ +VOID scanRemoveConnFlagOfBssDescByBssid(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]); + +/* 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); + +WLAN_STATUS scanAddScanResult(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc, IN P_SW_RFB_T prSwRfb); + +VOID scanReportBss2Cfg80211(IN P_ADAPTER_T prAdapter, IN ENUM_BSS_TYPE_T eBSSType, IN P_BSS_DESC_T SpecificprBssDesc); + +P_ROAM_BSS_DESC_T scanSearchRoamBssDescBySsid(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); +P_ROAM_BSS_DESC_T scanAllocateRoamBssDesc(IN P_ADAPTER_T prAdapter); +VOID scanAddToRoamBssDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); +VOID scanSearchBssDescOfRoamSsid(IN P_ADAPTER_T prAdapter); +VOID scanRemoveRoamBssDescsByTime(IN P_ADAPTER_T prAdapter, IN UINT_32 u4RemoveTime); +/*----------------------------------------------------------------------------*/ +/* 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); +VOID scnSendScanReqV3(IN P_ADAPTER_T prAdapter); + + +/*----------------------------------------------------------------------------*/ +/* RX Event Handling */ +/*----------------------------------------------------------------------------*/ +VOID scnEventScanDone(IN P_ADAPTER_T prAdapter, IN P_EVENT_SCAN_DONE prScanDone, BOOLEAN fgIsNewVersion); + +VOID scnEventNloDone(IN P_ADAPTER_T prAdapter, IN P_EVENT_NLO_DONE_T prNloDone); + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Handling */ +/*----------------------------------------------------------------------------*/ +VOID scnFsmMsgStart(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID scnFsmMsgAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID scnFsmHandleScanMsg(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_SCAN_REQ prScanReqMsg); + +VOID scnFsmHandleScanMsgV2(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_SCAN_REQ_V2 prScanReqMsg); +VOID scnFsmHandleScanMsgV3(IN P_ADAPTER_T prAdapter, IN struct _MSG_SCN_SCAN_REQ_V3_T *prScanReqMsg); + +VOID scnFsmRemovePendingMsg(IN P_ADAPTER_T prAdapter, IN UINT_8 ucSeqNum, IN UINT_8 ucBssIndex); + +VOID scnFsmNloMsgStart(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID scnFsmNloMsgAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID scnFsmHandleNloMsg(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_NLO_REQ prNloReqMsg); + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Generation */ +/*----------------------------------------------------------------------------*/ +VOID +scnFsmGenerateScanDoneMsg(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucSeqNum, IN UINT_8 ucBssIndex, IN ENUM_SCAN_STATUS eScanStatus); + +/*----------------------------------------------------------------------------*/ +/* Query for sparse channel */ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnQuerySparseChannel(IN P_ADAPTER_T prAdapter, P_ENUM_BAND_T prSparseBand, PUINT_8 pucSparseChannel); + +/*----------------------------------------------------------------------------*/ +/* OID/IOCTL Handling */ +/*----------------------------------------------------------------------------*/ +BOOLEAN +scnFsmSchedScanRequest(IN P_ADAPTER_T prAdapter, + IN P_PARAM_SCHED_SCAN_REQUEST prSchedScanRequest); + +BOOLEAN scnFsmSchedScanStopRequest(IN P_ADAPTER_T prAdapter); + +#if CFG_SUPPORT_PASSPOINT +P_BSS_DESC_T scanSearchBssDescByBssidAndLatestUpdateTime(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]); +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_AGPS_ASSIST +VOID scanReportScanResultToAgps(P_ADAPTER_T prAdapter); +#endif + +#if CFG_SUPPORT_SCN_PSCN +BOOLEAN scnFsmPSCNAction(IN P_ADAPTER_T prAdapter, IN ENUM_PSCAN_ACT_T ucPscanAct); + +BOOLEAN scnFsmPSCNSetParam(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_PARAM prCmdPscnParam); + +BOOLEAN scnFsmGSCNSetHotlist(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_PARAM prCmdPscnParam); + +BOOLEAN scnFsmPSCNAddSWCBssId(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_ADD_SWC_BSSID prCmdPscnAddSWCBssId); + +BOOLEAN scnFsmPSCNSetMacAddr(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_MAC_ADDR prCmdPscnSetMacAddr); + +BOOLEAN scnCombineParamsIntoPSCN(IN P_ADAPTER_T prAdapter, + IN P_CMD_NLO_REQ prCmdNloReq, + IN P_CMD_BATCH_REQ_T prCmdBatchReq, + IN P_CMD_GSCN_REQ_T prCmdGscnReq, + IN P_CMD_GSCN_SCN_COFIG_T prNewCmdGscnConfig, + IN BOOLEAN fgRemoveNLOfromPSCN, + IN BOOLEAN fgRemoveBatchSCNfromPSCN, IN BOOLEAN fgRemoveGSCNfromPSCN); + +VOID scnPSCNFsm(IN P_ADAPTER_T prAdapter, IN ENUM_PSCAN_STATE_T eNextPSCNState); +#endif + +#if CFG_SUPPORT_GSCN +BOOLEAN scnSetGSCNParam(IN P_ADAPTER_T prAdapter, IN P_PARAM_WIFI_GSCAN_CMD_PARAMS prCmdGscnParam); + +BOOLEAN scnSetGSCNConfig(IN P_ADAPTER_T prAdapter, IN P_CMD_GSCN_SCN_COFIG_T prCmdGscnScnConfig); + +BOOLEAN scnFsmGetGSCNResult(IN P_ADAPTER_T prAdapter, + IN P_CMD_GET_GSCAN_RESULT_T prGetGscnResultCmd, OUT PUINT_32 pu4SetInfoLen); + +BOOLEAN scnFsmGSCNResults(IN P_ADAPTER_T prAdapter, IN P_EVENT_GSCAN_RESULT_T prEventBuffer); +#endif + +VOID scnScanDoneTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr); + +VOID scanLogEssResult(P_ADAPTER_T prAdapter); +VOID scanInitEssResult(P_ADAPTER_T prAdapter); +P_BSS_DESC_T scanSearchBssDescByScoreForAis(P_ADAPTER_T prAdapter); +VOID scanGetCurrentEssChnlList(P_ADAPTER_T prAdapter); +VOID scanCollectBeaconReport(IN P_ADAPTER_T prAdapter, PUINT_8 pucIEBuf, + UINT_16 u2Length, PUINT_8 pucBssid, struct RM_BEACON_REPORT_PARAMS *prRepParams); +#endif /* _SCAN_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/sec_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/sec_fsm.h new file mode 100644 index 0000000000000..3d99d44abd1c8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/sec_fsm.h @@ -0,0 +1,129 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/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. + */ + +#ifndef _SEC_FSM_H +#define _SEC_FSM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/* TKIP CounterMeasure interval for Rejoin to Network. */ +#define COUNTER_MEASURE_TIMEOUT_INTERVAL_SEC 60 + +/* Timeout to wait the EAPoL Error Report frame Send out. */ +#define EAPOL_REPORT_SEND_TIMEOUT_INTERVAL_SEC 1 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef UINT_32 SEC_STATUS, *P_SEC_STATUS; + +#if 0 +/* WPA2 PMKID candicate structure */ +typedef struct _PMKID_CANDICATE_T { + UINT_8 aucBssid[MAC_ADDR_LEN]; /* MAC address */ + UINT_32 u4PreAuthFlags; +} PMKID_CANDICATE_T, *P_PMKID_CANDICATE_T; +#endif + +typedef SEC_STATUS(*PFN_SEC_FSM_STATE_HANDLER) (VOID); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define SEC_STATE_TRANSITION_FLAG fgIsTransition +#define SEC_NEXT_STATE_VAR eNextState + +#define SEC_STATE_TRANSITION(prAdapter, prSta, eFromState, eToState) \ + { secFsmTrans_ ## eFromState ## _to_ ## eToState(prAdapter, prSta); \ + SEC_NEXT_STATE_VAR = SEC_STATE_ ## eToState; \ + SEC_STATE_TRANSITION_FLAG = (BOOLEAN)TRUE; \ + } + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/*--------------------------------------------------------------*/ +/* Routines to handle the sec check */ +/*--------------------------------------------------------------*/ +/***** Routines in sec_fsm.c *****/ +VOID secFsmInit(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +VOID secFsmEventInit(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +VOID secFsmEventStart(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +VOID secFsmEventAbort(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +BOOLEAN secFsmEventPTKInstalled(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +VOID secFsmEvent2ndEapolTx(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +VOID secFsmEvent4ndEapolTxDone(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +VOID +secFsmEventEapolTxDone(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +VOID secFsmEventEapolTxTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); + +VOID +secFsmEventDeauthTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +VOID secFsmEventStartCounterMeasure(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +VOID secFsmEventEndOfCounterMeasure(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _SEC_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/stats.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/stats.h new file mode 100644 index 0000000000000..745854b6057bd --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/stats.h @@ -0,0 +1,104 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: stats.h#1 +*/ + +/* + * ! \file stats.h + * \brief This file includes statistics support. + */ + +/******************************************************************************* + * C O M P I L E 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 +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O D E C L A R A T I O N S +******************************************************************************** +*/ + +#include + +#if (CFG_SUPPORT_STATISTICS == 1) +#define STATS_RX_PKT_INFO_DISPLAY StatsRxPktInfoDisplay +#define STATS_TX_PKT_INFO_DISPLAY StatsTxPktInfoDisplay +#else +#define STATS_RX_PKT_INFO_DISPLAY(__Pkt__) +#define STATS_TX_PKT_INFO_DISPLAY(__Pkt__) +#endif /* CFG_SUPPORT_STATISTICS */ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E F U N C T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C F U N C T I O N S +******************************************************************************** +*/ + +#define STATS_TX_TIME_ARRIVE(__Skb__) \ +do { \ + UINT_64 __SysTime; \ + __SysTime = StatsEnvTimeGet(); /* us */ \ + GLUE_SET_PKT_XTIME(__Skb__, __SysTime); \ +} while (FALSE) + +UINT_64 StatsEnvTimeGet(VOID); + +VOID StatsEnvTxTime2Hif(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +VOID StatsEnvRxTime2Host(IN P_ADAPTER_T prAdapter, struct sk_buff *prSkb); + +VOID StatsResetTxRx(VOID); + +VOID StatsEnvSetPktDelay(IN UINT_8 ucTxOrRx, IN UINT_8 ucIpProto, IN UINT_16 u2UdpPort, UINT_32 u4DelayThreshold); + +VOID StatsEnvGetPktDelay(OUT PUINT_8 pucTxRxFlag, OUT PUINT_8 pucTxIpProto, OUT PUINT_16 pu2TxUdpPort, + OUT PUINT_32 pu4TxDelayThreshold, OUT PUINT_8 pucRxIpProto, + OUT PUINT_16 pu2RxUdpPort, OUT PUINT_32 pu4RxDelayThreshold); + +VOID StatsRxPktInfoDisplay(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); + +VOID StatsTxPktInfoDisplay(UINT_8 *pPkt); + +/* End of stats.h */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/swcr.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/swcr.h new file mode 100644 index 0000000000000..1e1dc7eefbbf7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/swcr.h @@ -0,0 +1,206 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/swcr.h#1 +*/ + +/*! \file "swcr.h" + * \brief +*/ + +#ifndef _SWCR_H +#define _SWCR_H + +#include "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 TEST_PS 1 + +#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) (ARRAY_SIZE(x)) + +#define SWCR_CR_NUM 7 + +#define SWCR_GET_RW_INDEX(action, rw, index) \ +do { \ + index = action & 0x7F; \ + rw = action >> 7; \ +} while (0) + +extern UINT_32 g_au4SwCr[]; /*: 0: command other: data */ + +typedef VOID(*PFN_SWCR_RW_T) (P_ADAPTER_T prAdapter, UINT_8 ucRead, UINT_16 u2Addr, UINT_32 *pu4Data); +typedef VOID(*PFN_CMD_RW_T) (P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1); + +typedef struct _SWCR_MAP_ENTRY_T { + UINT_16 u2Type; + PVOID u4Addr; +} SWCR_MAP_ENTRY_T, *P_SWCR_MAP_ENTRY_T; + +typedef struct _SWCR_MOD_MAP_ENTRY_T { + UINT_8 ucMapNum; + P_SWCR_MAP_ENTRY_T prSwCrMap; +} SWCR_MOD_MAP_ENTRY_T, *P_SWCR_MOD_MAP_ENTRY_T; + +typedef enum _ENUM_SWCR_DBG_TYPE_T { + SWCR_DBG_TYPE_ALL = 0, + SWCR_DBG_TYPE_TXRX, + SWCR_DBG_TYPE_RX_RATES, + SWCR_DBG_TYPE_PS, + SWCR_DBG_TYPE_NUM +} ENUM_SWCR_DBG_TYPE_T; + +typedef enum _ENUM_SWCR_DBG_ALL_T { + SWCR_DBG_ALL_TX_CNT = 0, + SWCR_DBG_ALL_TX_BCN_CNT, + SWCR_DBG_ALL_TX_FAILED_CNT, + SWCR_DBG_ALL_TX_RETRY_CNT, + SWCR_DBG_ALL_TX_AGING_TIMEOUT_CNT, + SWCR_DBG_ALL_TX_PS_OVERFLOW_CNT, + SWCR_DBG_ALL_TX_MGNT_DROP_CNT, + SWCR_DBG_ALL_TX_ERROR_CNT, + + SWCR_DBG_ALL_RX_CNT, + SWCR_DBG_ALL_RX_DROP_CNT, + SWCR_DBG_ALL_RX_DUP_DROP_CNT, + SWCR_DBG_ALL_RX_TYPE_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_CLASS_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_AMPDU_ERROR_DROP_CNT, + + SWCR_DBG_ALL_RX_STATUS_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_FORMAT_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_ICV_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_KEY_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_TKIP_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_MIC_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_BIP_ERROR_DROP_CNT, + + SWCR_DBG_ALL_RX_FCSERR_CNT, + SWCR_DBG_ALL_RX_FIFOFULL_CNT, + SWCR_DBG_ALL_RX_PFDROP_CNT, + + SWCR_DBG_ALL_PWR_PS_POLL_CNT, + SWCR_DBG_ALL_PWR_TRIGGER_NULL_CNT, + SWCR_DBG_ALL_PWR_BCN_IND_CNT, + SWCR_DBG_ALL_PWR_BCN_TIMEOUT_CNT, + SWCR_DBG_ALL_PWR_PM_STATE0, + SWCR_DBG_ALL_PWR_PM_STATE1, + SWCR_DBG_ALL_PWR_CUR_PS_PROF0, + SWCR_DBG_ALL_PWR_CUR_PS_PROF1, + + SWCR_DBG_ALL_AR_STA0_RATE, + SWCR_DBG_ALL_AR_STA0_BWGI, + SWCR_DBG_ALL_AR_STA0_RX_RATE_RCPI, + + SWCR_DBG_ALL_ROAMING_ENABLE, + SWCR_DBG_ALL_ROAMING_ROAM_CNT, + SWCR_DBG_ALL_ROAMING_INT_CNT, + + SWCR_DBG_ALL_BB_RX_MDRDY_CNT, + SWCR_DBG_ALL_BB_RX_FCSERR_CNT, + SWCR_DBG_ALL_BB_CCK_PD_CNT, + SWCR_DBG_ALL_BB_OFDM_PD_CNT, + SWCR_DBG_ALL_BB_CCK_SFDERR_CNT, + SWCR_DBG_ALL_BB_CCK_SIGERR_CNT, + SWCR_DBG_ALL_BB_OFDM_TAGERR_CNT, + SWCR_DBG_ALL_BB_OFDM_SIGERR_CNT, + + SWCR_DBG_ALL_NUM +} ENUM_SWCR_DBG_ALL_T; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* 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); + +#if CFG_SUPPORT_SWCR +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); +#if TEST_PS +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); +#endif +#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); +#endif +#endif +VOID swCtrlSwCr(P_ADAPTER_T prAdapter, UINT_8 ucRead, UINT_16 u2Addr, UINT_32 *pu4Data); + +/* Support Debug */ +VOID swCrDebugCheck(P_ADAPTER_T prAdapter, P_CMD_SW_DBG_CTRL_T prCmdSwCtrl); +VOID swCrDebugCheckTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr); +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); +#endif + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/tdls.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/tdls.h new file mode 100644 index 0000000000000..188f9ab0ca3b2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/tdls.h @@ -0,0 +1,427 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: include/tdls.h#1 +*/ + +/* + * ! \file "tdls.h" + * \brief This file contains the internal used in TDLS modules + * for MediaTek Inc. 802.11 Wireless LAN Adapters. + */ + +#ifndef _TDLS_H +#define _TDLS_H + +#if CFG_SUPPORT_TDLS + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#define TDLS_CFG_CMD_TEST + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/* assign station record idx for the packet */ +#define TDLSEX_STA_REC_IDX_GET(__prAdapter__, __MsduInfo__) \ +{ \ + STA_RECORD_T *__StaRec__; \ + __MsduInfo__->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; \ + __StaRec__ = cnmGetStaRecByAddress(__prAdapter__, \ + (UINT_8) NETWORK_TYPE_AIS_INDEX,\ + __MsduInfo__->aucEthDestAddr); \ + if ((__StaRec__ != NULL) && (IS_DLS_STA(__StaRec__))) \ + __MsduInfo__->ucStaRecIndex = __StaRec__->ucIndex; \ +} + +/* fill wiphy flag */ +#define TDLSEX_WIPHY_FLAGS_INIT(__fgFlag__) \ +{ \ + __fgFlag__ |= (WIPHY_FLAG_SUPPORTS_TDLS | WIPHY_FLAG_TDLS_EXTERNAL_SETUP);\ +} + +#define LR_TDLS_FME_FIELD_FILL(__Len) \ +{ \ + pPkt += __Len; \ + u4PktLen += __Len; \ +} + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +extern int wlanHardStartXmit(struct sk_buff *prSkb, struct net_device *prDev); + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/* Status code */ +#define TDLS_STATUS WLAN_STATUS + +#define TDLS_STATUS_SUCCESS WLAN_STATUS_SUCCESS +#define TDLS_STATUS_FAIL WLAN_STATUS_FAILURE +#define TDLS_STATUS_INVALID_LENGTH WLAN_STATUS_INVALID_LENGTH +#define TDLS_STATUS_RESOURCES WLAN_STATUS_RESOURCES +#define TDLS_FME_MAC_ADDR_LEN 6 +#define TDLS_EX_CAP_PEER_UAPSD BIT(0) +#define TDLS_EX_CAP_CHAN_SWITCH BIT(1) +#define TDLS_EX_CAP_TDLS BIT(2) +#define TDLS_CMD_PEER_UPDATE_EXT_CAP_MAXLEN 5 +#define TDLS_CMD_PEER_UPDATE_SUP_RATE_MAX 50 +#define TDLS_CMD_PEER_UPDATE_SUP_CHAN_MAX 50 + +#define MAXNUM_TDLS_PEER 4 + +/* command */ +typedef enum _TDLS_CMD_ID { + TDLS_CMD_TEST_TX_FRAME = 0x00, + TDLS_CMD_TEST_RCV_FRAME, + TDLS_CMD_TEST_PEER_ADD, + TDLS_CMD_TEST_PEER_UPDATE, + TDLS_CMD_TEST_DATA_FRAME, + TDLS_CMD_TEST_RCV_NULL +} TDLS_CMD_ID; + +/* protocol */ +#define TDLS_FRM_PROT_TYPE 0x890d + +/* payload specific type in the LLC/SNAP header */ +#define TDLS_FRM_PAYLOAD_TYPE 2 + +#define TDLS_FRM_CATEGORY 12 + +typedef enum _TDLS_FRM_ACTION_ID { + TDLS_FRM_ACTION_SETUP_REQ = 0x00, + TDLS_FRM_ACTION_SETUP_RSP, + TDLS_FRM_ACTION_CONFIRM, + TDLS_FRM_ACTION_TEARDOWN, + TDLS_FRM_ACTION_PTI, + TDLS_FRM_ACTION_CHAN_SWITCH_REQ, + TDLS_FRM_ACTION_CHAN_SWITCH_RSP, + TDLS_FRM_ACTION_PEER_PSM_REQ, + TDLS_FRM_ACTION_PEER_PSM_RSP, + TDLS_FRM_ACTION_PTI_RSP, + TDLS_FRM_ACTION_DISCOVERY_REQ, + TDLS_FRM_ACTION_DISCOVERY_RSP = 0x0e, + TDLS_FRM_ACTION_EVENT_TEAR_DOWN_TO_SUPPLICANT = 0x30 +} TDLS_FRM_ACTION_ID; + +/* 7.3.2.62 Link Identifier element */ +#define ELEM_ID_LINK_IDENTIFIER 101 + +typedef struct _IE_LINK_IDENTIFIER_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aBSSID[6]; + UINT_8 aInitiator[6]; + UINT_8 aResponder[6]; +} __KAL_ATTRIB_PACKED__ IE_LINK_IDENTIFIER_T; + +#define TDLS_LINK_IDENTIFIER_IE(__ie__) ((IE_LINK_IDENTIFIER_T *)(__ie__)) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef struct _STATION_PRARAMETERS { + const u8 *supported_rates; + struct net_device *vlan; + u32 sta_flags_mask, sta_flags_set; + u32 sta_modify_mask; + int listen_interval; + u16 aid; + u8 supported_rates_len; + u8 plink_action; + u8 plink_state; + const struct ieee80211_ht_cap *ht_capa; + const struct ieee80211_vht_cap *vht_capa; + u8 uapsd_queues; + u8 max_sp; + /* enum nl80211_mesh_power_mode local_pm; */ + u16 capability; + const u8 *ext_capab; + u8 ext_capab_len; +} STATION_PRARAMETERS, P_STATION_PRARAMETERS; + +/* test command use */ +typedef struct _PARAM_CUSTOM_TDLS_CMD_STRUCT_T { + + UINT_8 ucFmeType; /* TDLS_FRM_ACTION_ID */ + + UINT_8 ucToken; + UINT_8 ucCap; + + /* bit0: TDLS, bit1: Peer U-APSD Buffer, bit2: Channel Switching */ + + UINT_8 ucExCap; + + UINT_8 arSupRate[4]; + UINT_8 arSupChan[4]; + + UINT_32 u4Timeout; + + UINT_8 arRspAddr[TDLS_FME_MAC_ADDR_LEN]; + UINT_8 arBssid[TDLS_FME_MAC_ADDR_LEN]; + + /* Linux Kernel-3.10 */ + + struct ieee80211_ht_cap rHtCapa; + struct ieee80211_vht_cap rVhtCapa; + /* struct */ + STATION_PRARAMETERS rPeerInfo; + +} PARAM_CUSTOM_TDLS_CMD_STRUCT_T; + +typedef enum _ENUM_TDLS_LINK_OPER { + TDLS_DISCOVERY_REQ, + TDLS_SETUP, + TDLS_TEARDOWN, + TDLS_ENABLE_LINK, + TDLS_DISABLE_LINK +} ENUM_TDLS_LINK_OPER; + +typedef struct _TDLS_CMD_LINK_OPER_T { + + UINT_8 aucPeerMac[6]; + enum nl80211_tdls_operation oper; +} TDLS_CMD_LINK_OPER_T; + +typedef struct _TDLS_CMD_LINK_MGT_T { + + UINT_8 aucPeer[6]; + UINT_8 ucActionCode; + UINT_8 ucDialogToken; + UINT_16 u2StatusCode; + UINT_32 u4SecBufLen; + UINT_8 aucSecBuf[1000]; + +} TDLS_CMD_LINK_MGT_T; + +typedef struct _TDLS_CMD_PEER_ADD_T { + + UINT_8 aucPeerMac[6]; + ENUM_STA_TYPE_T eStaType; +} TDLS_CMD_PEER_ADD_T; + +typedef struct _TDLS_CMD_PEER_UPDATE_HT_CAP_MCS_INFO_T { + UINT_8 arRxMask[SUP_MCS_RX_BITMASK_OCTET_NUM]; + UINT_16 u2RxHighest; + UINT_8 ucTxParams; + UINT_8 Reserved[3]; +} TDLS_CMD_PEER_UPDATE_HT_CAP_MCS_INFO_T; + +typedef struct _TDLS_CMD_PEER_UPDATE_VHT_CAP_MCS_INFO_T { + UINT_8 arRxMask[SUP_MCS_RX_BITMASK_OCTET_NUM]; +} TDLS_CMD_PEER_UPDATE_VHT_CAP_MCS_INFO_T; + +typedef struct _TDLS_CMD_PEER_UPDATE_HT_CAP_T { + UINT_16 u2CapInfo; + UINT_8 ucAmpduParamsInfo; + + /* 16 bytes MCS information */ + TDLS_CMD_PEER_UPDATE_HT_CAP_MCS_INFO_T rMCS; + + UINT_16 u2ExtHtCapInfo; + UINT_32 u4TxBfCapInfo; + UINT_8 ucAntennaSelInfo; +} TDLS_CMD_PEER_UPDATE_HT_CAP_T; + +typedef struct _TDLS_CMD_PEER_UPDATE_VHT_CAP_T { + UINT_16 u2CapInfo; + /* 16 bytes MCS information */ + TDLS_CMD_PEER_UPDATE_VHT_CAP_MCS_INFO_T rVMCS; + +} TDLS_CMD_PEER_UPDATE_VHT_CAP_T; + +typedef struct _TDLS_CMD_PEER_UPDATE_T { + + UINT_8 aucPeerMac[6]; + + UINT_8 aucSupChan[TDLS_CMD_PEER_UPDATE_SUP_CHAN_MAX]; + + UINT_16 u2StatusCode; + + UINT_8 aucSupRate[TDLS_CMD_PEER_UPDATE_SUP_RATE_MAX]; + UINT_16 u2SupRateLen; + + UINT_8 UapsdBitmap; + UINT_8 UapsdMaxSp; /* MAX_SP */ + + UINT_16 u2Capability; + + UINT_8 aucExtCap[TDLS_CMD_PEER_UPDATE_EXT_CAP_MAXLEN]; + UINT_16 u2ExtCapLen; + + TDLS_CMD_PEER_UPDATE_HT_CAP_T rHtCap; + TDLS_CMD_PEER_UPDATE_VHT_CAP_T rVHtCap; + + BOOLEAN fgIsSupHt; + ENUM_STA_TYPE_T eStaType; + +} TDLS_CMD_PEER_UPDATE_T; + +/* Command to TDLS core module */ +typedef enum _TDLS_CMD_CORE_ID { + TDLS_CORE_CMD_TEST_NULL_RCV = 0x00 +} TDLS_CMD_CORE_ID; + +typedef struct _TDLS_CMD_CORE_TEST_NULL_RCV_T { + + UINT_32 u4PM; +} TDLS_CMD_CORE_TEST_NULL_RCV_T; + +typedef struct _TDLS_CMD_CORE_T { + + UINT_32 u4Command; + + UINT_8 aucPeerMac[6]; + +#define TDLS_CMD_CORE_RESERVED_SIZE 50 + union { + TDLS_CMD_CORE_TEST_NULL_RCV_T rCmdNullRcv; + UINT_8 Reserved[TDLS_CMD_CORE_RESERVED_SIZE]; + } Content; +} TDLS_CMD_CORE_T; + +typedef enum _TDLS_EVENT_HOST_ID { + TDLS_HOST_EVENT_TEAR_DOWN = 0x00, + TDLS_HOST_EVENT_TX_DONE +} TDLS_EVENT_HOST_ID; + +typedef enum _TDLS_EVENT_HOST_SUBID_TEAR_DOWN { + TDLS_HOST_EVENT_TD_PTI_TIMEOUT = 0x00, + TDLS_HOST_EVENT_TD_AGE_TIMEOUT, + TDLS_HOST_EVENT_TD_PTI_SEND_FAIL, + TDLS_HOST_EVENT_TD_PTI_SEND_MAX_FAIL, + TDLS_HOST_EVENT_TD_WRONG_NETWORK_IDX, + TDLS_HOST_EVENT_TD_NON_STATE3, + TDLS_HOST_EVENT_TD_LOST_TEAR_DOWN +} TDLS_EVENT_HOST_SUBID_TEAR_DOWN; + +typedef enum _TDLS_REASON_CODE { + TDLS_REASON_CODE_UNREACHABLE = 25, + TDLS_REASON_CODE_UNSPECIFIED = 26, + + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_UNKNOWN = 0x80, /* 128 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_WIFI_OFF = 0x81, /* 129 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_ROAMING = 0x82, /* 130 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_TIMEOUT = 0x83, /* 131 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_AGE_TIMEOUT = 0x84, /* 132 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_REKEY = 0x85, /* 133 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_SEND_FAIL = 0x86, /* 134 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_SEND_MAX_FAIL = 0x87, /* 135 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_WRONG_NETWORK_IDX = 0x88, /* 136 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_NON_STATE3 = 0x89, /* 137 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_TX_QUOTA_EMPTY = 0x8a, /* 138 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_LOST_TEAR_DOWN = 0x8b /* 139 */ +} TDLS_REASON_CODE; + +/******************************************************************************* +* P U B 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 +******************************************************************************** +*/ +UINT_32 TdlsFrameGeneralIeAppend(ADAPTER_T *prAdapter, STA_RECORD_T *prStaRec, UINT_8 *pPkt); + +WLAN_STATUS /* TDLS_STATUS */ + +TdlsDataFrameSend_TearDown(ADAPTER_T *prAdapter, + STA_RECORD_T *prStaRec, + UINT_8 *pPeerMac, + UINT_8 ucActionCode, + UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen); + +WLAN_STATUS /* TDLS_STATUS */ + +TdlsDataFrameSend_CONFIRM(ADAPTER_T *prAdapter, + STA_RECORD_T *prStaRec, + UINT_8 *pPeerMac, + UINT_8 ucActionCode, + UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen); + +WLAN_STATUS /* TDLS_STATUS */ + +TdlsDataFrameSend_SETUP_REQ(ADAPTER_T *prAdapter, + STA_RECORD_T *prStaRec, + UINT_8 *pPeerMac, + UINT_8 ucActionCode, + UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen); + +WLAN_STATUS /* TDLS_STATUS */ + +TdlsDataFrameSend_DISCOVERY_REQ(ADAPTER_T *prAdapter, + STA_RECORD_T *prStaRec, + UINT_8 *pPeerMac, + UINT_8 ucActionCode, + UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen); + +WLAN_STATUS /* TDLS_STATUS */ + +TdlsDataFrameSend_SETUP_RSP(ADAPTER_T *prAdapter, + STA_RECORD_T *prStaRec, + UINT_8 *pPeerMac, + UINT_8 ucActionCode, + UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen); + +WLAN_STATUS /* TDLS_STATUS */ + +TdlsDataFrameSend_DISCOVERY_RSP(ADAPTER_T *prAdapter, + STA_RECORD_T *prStaRec, + UINT_8 *pPeerMac, + UINT_8 ucActionCode, + UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen); + +UINT_32 TdlsexLinkOper(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, PUINT_32 pu4SetInfoLen); + +UINT_32 TdlsexLinkMgt(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, PUINT_32 pu4SetInfoLen); + +VOID TdlsexEventHandle(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +VOID TdlsEventTearDown(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +VOID TdlsBssExtCapParse(P_STA_RECORD_T prStaRec, P_UINT_8 pucIE); + +WLAN_STATUS +TdlsSendChSwControlCmd(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, PUINT_32 pu4SetInfoLen); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* CFG_SUPPORT_TDLS */ + +#endif /* _TDLS_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/wapi.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/wapi.h new file mode 100644 index 0000000000000..8e93f8db490fb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/wapi.h @@ -0,0 +1,91 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/wapi.h#1 +*/ + +/* + * ! \file wapi.h + * \brief The wapi related define, macro and structure are described here. + */ + +#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 +******************************************************************************** +*/ + +BOOLEAN wapiParseWapiIE(IN P_WAPI_INFO_ELEM_T prInfoElem, OUT P_WAPI_INFO_T prWapiInfo); + +BOOLEAN wapiPerformPolicySelection(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBss); + +/* BOOLEAN */ +/* wapiUpdateTxKeyIdx ( */ +/* IN P_STA_RECORD_T prStaRec, */ +/* IN UINT_8 ucWlanIdx */ +/* ); */ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif +#endif /* _WAPI_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/wlan_typedef.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/wlan_typedef.h new file mode 100644 index 0000000000000..fe09fbfca56bc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/wlan_typedef.h @@ -0,0 +1,100 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/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. + */ + +#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 struct _BSS_INFO_T P2P_DEV_INFO_T, *P_P2P_DEV_INFO_T; + +#if 0 /* Marked for MT6630 */ +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; +#endif + +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; +typedef struct _ROAM_BSS_DESC_T ROAM_BSS_DESC_T, *P_ROAM_BSS_DESC_T, **PP_ROAM_BSS_DESC_T; + +#if CFG_SUPPORT_PASSPOINT +typedef struct _HS20_INFO_T HS20_INFO_T, *P_HS20_INFO_T; +#endif /* CFG_SUPPORT_PASSPOINT */ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _WLAN_TYPEDEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/wmm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/wmm.h new file mode 100644 index 0000000000000..40f9009ecc350 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/wmm.h @@ -0,0 +1,195 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef WMM_HDR_H +#define WMM_HDR_H + +#define VENDOR_OUI_TYPE_TSRS 8 +#define VENDOR_OUI_TYPE_TSM 7 +#define VENDOR_OUI_TYPE_EDCALIFE 9 +#define WLAN_MAC_ACTION_ADDTS_LEN (WLAN_MAC_MGMT_HEADER_HTC_LEN + 66) +#define WLAN_MAC_ACTION_DELTS_LEN (WLAN_MAC_MGMT_HEADER_HTC_LEN + 7) +#define TSPEC_POLICY_CHECK_INTERVAL 2500 /* unit ms */ + +#define WMM_TS_STATUS_ADMISSION_ACCEPTED 0 +#define WMM_TS_STATUS_ADDTS_INVALID_PARAM 1 +#define WMM_TS_STATUS_ADDTS_REFUSED 3 +#define WMM_TS_STATUS_ASSOC_QOS_FAILED 0xc8 +#define WMM_TS_STATUS_POLICY_CONFIG_REFUSED 0xc9 +#define WMM_TS_STATUS_ASSOC_INSUFFICIENT_BANDWIDTH 0xca +#define WMM_TS_STATUS_ASSOC_INVALID_PARAM 0xcb + +#define CFG_SUPPORT_SOFT_ACM 1 /* do Admission Control in driver */ +/* +** In WMM, TSs are identified with TIDs values 0 through 7. Any TID may map onto any +** UP and thus onto any AC, however for each AC used between an RA and TA, only the +** following combinations are valid: +** No TS, One uplink TS, one Download link TS, one uplink and one uplink TS, one +** bi-directional TS. +** so maximum 8 TSs are allowed in a RA & TA context. +*/ +#define WMM_TSPEC_ID_NUM 8 + +/*WMM-2.2.11 WMM TSPEC IE*/ +#define ELEM_MAX_LEN_WMM_TSPEC 61 + +enum WMM_ADDTS_STATUS { + ADDTS_ACCEPTED = 0, + ADDTS_INVALID_PARAMS = 1, + ADDTS_REFUSED = 2 +}; + +enum TSPEC_OP_CODE { + TX_ADDTS_REQ, + RX_ADDTS_RSP, + TX_DELTS_REQ, + RX_DELTS_REQ, + DISC_DELTS_REQ, + UPDATE_TS_REQ +}; + +enum QOS_TS_STATE { + QOS_TS_INACTIVE, + QOS_TS_ACTIVE, + QOS_TS_SETUPING, + QOS_TS_STATE_MAX +}; + +enum TSPEC_DIR { + UPLINK_TS = 0, + DOWNLINK_TS = 1, + BI_DIR_TS = 3 +}; + +struct TSPEC_INFO { + TIMER_T rAddTsTimer; + UINT_8 ucToken; + BOOLEAN fgUapsd; + ENUM_ACI_T eAC:8; + enum TSPEC_DIR eDir:8; + enum QOS_TS_STATE eState:8; + /* debug information */ + UINT_16 u2MediumTime; + UINT_32 u4PhyRate; +}; + +struct TSM_TRIGGER_COND { + UINT_8 ucCondition; + UINT_8 ucAvgErrThreshold; + UINT_8 ucConsecutiveErr; + UINT_8 ucDelayThreshold; + UINT_8 ucMeasureCount; + /* In this time frame, for one condition, only once report is allowed */ + UINT_8 ucTriggerTimeout; +}; + +struct RM_TSM_REQ { + UINT_16 u2Duration; /* unit: TUs */ + UINT_8 aucPeerAddr[MAC_ADDR_LEN]; + UINT_8 ucToken; + UINT_8 ucTID; + UINT_8 ucACI; + UINT_8 ucB0Range; /* 2^(i-1)*ucB0Range =< delay < 2^i * ucB0Range */ + struct TSM_TRIGGER_COND rTriggerCond; +}; + +struct ACTIVE_RM_TSM_REQ { + LINK_ENTRY_T rLinkEntry; + struct RM_TSM_REQ *prTsmReq; + TIMER_T rTsmTimer; +}; + +#if CFG_SUPPORT_SOFT_ACM +struct SOFT_ACM_CTRL { + UINT_32 u4RemainTime; + UINT_32 u4AdmittedTime; + UINT_32 u4IntervalEndSec; + UINT_16 u2DeqNum; +}; +#endif + +struct WMM_INFO { + /* A TS is identified uniquely by its TID value within the context of the RA and TA + ** the index is TID for this array + */ + struct TSPEC_INFO arTsInfo[WMM_TSPEC_ID_NUM]; + LINK_T rActiveTsmReq; + OS_SYSTIME rTriggeredTsmRptTime; + TIMER_T rTsmTimer; +#if CFG_SUPPORT_SOFT_ACM + TIMER_T rAcmDeqTimer; + struct SOFT_ACM_CTRL arAcmCtrl[ACI_NUM]; /* 0 ~ 3, BE, BK, VI, VO */ +#endif +}; + +struct WMM_ADDTS_RSP_STEP_PARAM { + UINT_8 ucDlgToken; + UINT_8 ucStatusCode; + UINT_8 ucApsd; + enum TSPEC_DIR eDir:8; + UINT_16 u2EdcaLifeTime; + UINT_16 u2MediumTime; + UINT_32 u4PhyRate; +}; + +struct MSG_TS_OPERATE { + MSG_HDR_T rMsgHdr; + enum TSPEC_OP_CODE eOpCode; + UINT_8 ucTid; + PARAM_QOS_TSPEC rTspecParam; +}; + +#define WMM_TSINFO_TRAFFIC_TYPE(tsinfo) (tsinfo & BIT(0)) +#define WMM_TSINFO_TSID(tsinfo) ((tsinfo & BITS(1, 4)) >> 1) +#define WMM_TSINFO_DIR(tsinfo) ((tsinfo & BITS(5, 6)) >> 5) +#define WMM_TSINFO_AC(tsinfo) ((tsinfo & BITS(7, 8)) >> 7) +#define WMM_TSINFO_PSB(tsinfo) ((tsinfo & BIT(10)) >> 10) +#define WMM_TSINFO_UP(tsinfo) ((tsinfo & BITS(11, 13)) >> 11) + +#define TSM_TRIGGER_CONDITION_ALL BITS(0, 2) +#define TSM_TRIGGER_AVG BIT(0) +#define TSM_TRIGGER_CONSECUTIVE BIT(1) +#define TSM_TIRGGER_DELAY BIT(2) + +extern UINT_8 const aucUp2ACIMap[8]; +VOID wmmFillTsinfo(P_PARAM_QOS_TSINFO prTsInfo, P_UINT_8 pucTsInfo); +VOID wmmSetupTspecTimeOut(P_ADAPTER_T prAdapter, ULONG ulParam); +void wmmStartTsmMeasurement(P_ADAPTER_T prAdapter, ULONG ulParam); +VOID wmmRunEventTSOperate(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr); +BOOLEAN wmmParseQosAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); +BOOLEAN +wmmParseTspecIE(P_ADAPTER_T prAdapter, PUINT_8 pucIE, P_PARAM_QOS_TSPEC prTspec); +VOID +wmmTspecSteps(P_ADAPTER_T prAdapter, UINT_8 ucTid, + enum TSPEC_OP_CODE eOpCode, VOID *prStepParams); +UINT_8 wmmHasActiveTspec(struct WMM_INFO *prWmmInfo); +VOID wmmNotifyDisconnected(P_ADAPTER_T prAdapter); +void wmmComposeTsmRpt(P_ADAPTER_T prAdapter, P_CMD_INFO_T prCmdInfo, PUINT_8 pucEventBuf); +VOID wmmInit(IN P_ADAPTER_T prAdapter); +VOID wmmUnInit(IN P_ADAPTER_T prAdapter); +BOOLEAN wmmTsmIsOngoing(P_ADAPTER_T prAdapter); +VOID wmmNotifyDisconnected(P_ADAPTER_T prAdapter); +VOID wmmRemoveAllTsmMeasurement(P_ADAPTER_T prAdapter, BOOLEAN fgOnlyTriggered); +UINT_8 wmmCalculateUapsdSetting(P_ADAPTER_T prAdapter); +UINT_32 wmmDumpActiveTspecs(P_ADAPTER_T prAdapter, PUINT_8 pucBuffer, UINT_16 u2BufferLen); +#if CFG_SUPPORT_SOFT_ACM +BOOLEAN wmmAcmCanDequeue(P_ADAPTER_T prAdapter, UINT_8 ucAc, UINT_32 u4PktTxTime); +VOID wmmAcmTxStatistic(P_ADAPTER_T prAdapter, UINT_8 ucAc, UINT_32 u4Remain, UINT_16 u2DeqNum); + +UINT_32 +wmmCalculatePktUsedTime(P_BSS_INFO_T prBssInfo, P_STA_RECORD_T prStaRec, UINT_16 u2PktLen); +VOID wmmPrepareFastUsedTimeCal(P_ADAPTER_T prAdapter); +UINT_32 wmmFastCalPktUsedTime(struct WMM_INFO *prWmmInfo, UINT_8 ucAc, UINT_16 u2PktLen); +#endif /* CFG_SUPPORT_SOFT_ACM */ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/wnm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/wnm.h new file mode 100644 index 0000000000000..f8840cc2a1f87 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/mgmt/wnm.h @@ -0,0 +1,141 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** 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. + */ + +#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; + +struct BSS_TRANSITION_MGT_PARAM_T { + /* for Query */ + UINT_8 ucDialogToken; + UINT_8 ucQueryReason; + /* for Request */ + UINT_8 ucRequestMode; + UINT_16 u2DisassocTimer; + UINT_16 u2TermDuration; + UINT_8 aucTermTsf[8]; + UINT_8 ucSessionURLLen; + UINT_8 aucSessionURL[255]; + /* for Respone */ + BOOLEAN fgPendingResponse:1; + BOOLEAN fgUnsolicitedReq:1; + BOOLEAN fgReserved:6; + UINT_8 ucStatusCode; + UINT_8 ucTermDelay; + UINT_8 aucTargetBssid[MAC_ADDR_LEN]; + PUINT_8 pucOurNeighborBss; + UINT_16 u2OurNeighborBssLen; +}; + +/******************************************************************************* +* P U B 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 BTM_REQ_MODE_CAND_INCLUDED_BIT BIT(0) +#define BTM_REQ_MODE_ABRIDGED BIT(1) +#define BTM_REQ_MODE_DISC_IMM BIT(2) +#define BTM_REQ_MODE_BSS_TERM_INCLUDE BIT(3) +#define BTM_REQ_MODE_ESS_DISC_IMM BIT(4) + +#define BSS_TRANSITION_MGT_STATUS_ACCEPT 0 +#define BSS_TRANSITION_MGT_STATUS_UNSPECIFIED 1 +#define BSS_TRANSITION_MGT_STATUS_NEED_SCAN 2 +#define BSS_TRANSITION_MGT_STATUS_CAND_NO_CAPACITY 3 +#define BSS_TRANSITION_MGT_STATUS_TERM_UNDESIRED 4 +#define BSS_TRANSITION_MGT_STATUS_TERM_DELAY_REQUESTED 5 +#define BSS_TRANSITION_MGT_STATUS_CAND_LIST_PROVIDED 6 +#define BSS_TRANSITION_MGT_STATUS_CAND_NO_CANDIDATES 7 +#define BSS_TRANSITION_MGT_STATUS_LEAVING_ESS 8 + +/* 802.11v: define Transtion and Transition Query reasons */ +#define BSS_TRANSITION_BETTER_AP_FOUND 6 +#define BSS_TRANSITION_LOW_RSSI 16 +#define BSS_TRANSITION_INCLUDE_PREFER_CAND_LIST 19 +#define BSS_TRANSITION_LEAVING_ESS 20 + +/******************************************************************************* +* 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); + +#if WNM_UNIT_TEST +VOID wnmTimingMeasUnitTest1(P_ADAPTER_T prAdapter, UINT_8 ucStaRecIndex); +#endif + +VOID wnmRecvBTMRequest(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID wnmSendBTMQueryFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +VOID wnmSendBTMResponseFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +UINT_8 wnmGetBtmToken(VOID); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _WNM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/adapter.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/adapter.h new file mode 100644 index 0000000000000..fa8fa3cb64760 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/adapter.h @@ -0,0 +1,1254 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/adapter.h#5 + */ + +/* + * ! \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. + */ + +#ifndef _ADAPTER_H +#define _ADAPTER_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#if CFG_SUPPORT_PASSPOINT +#include "hs20.h" +#endif /* CFG_SUPPORT_PASSPOINT */ + +/******************************************************************************* +* 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; +struct ESS_SCAN_RESULT_T { + UINT_8 aucBSSID[MAC_ADDR_LEN]; + UINT_16 u2SSIDLen; + UINT_8 aucSSID[32]; +}; + +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; + + struct ESS_SCAN_RESULT_T arScanResultEss[CFG_MAX_NUM_BSS_LIST]; + UINT_32 u4ScanResultEssNum; + UINT_32 u4ScanDbgTimes1; + UINT_32 u4ScanDbgTimes2; + UINT_32 u4ScanDbgTimes3; + UINT_32 u4ScanDbgTimes4; + + /* 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[MAX_BSS_INDEX + 1]; + UINT_32 u4PowerSaveFlag[MAX_BSS_INDEX + 1]; + + /* 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; + + BOOLEAN fgEnSpecPwrMgt; +} 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]; + + ENUM_RECONNECT_LEVEL_T eReConnectLevel; + + 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; + + /* 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:1; + + BOOLEAN fgIsAdHocQoSEnable:1; + /* Indicates if OKC feature is enabled in wpa_supplicant for this ESS */ + BOOLEAN fgOkcEnabled:1; + /* Indicates that there's a PMKSA associated with this ESS + ** in supplicant to generate PMKID for each BSS + */ + BOOLEAN fgOkcPmksaReady:1; + /* CR1486, CR1640 */ + /* for WPS, disable the privacy check for AP selection policy */ + BOOLEAN fgPrivacyCheckDisable:1; + BOOLEAN fgIsScanReqIssued:1; + BOOLEAN fgIsConnReqIssued:1; + BOOLEAN fgIsDisconnectedByNonRequest:1; + + 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 *//* Not used */ + UINT_8 uc5GBandwidthMode; /* 20/40M or 20M only *//* Not used */ + +#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 + + /* 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; +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE + BOOLEAN fgSecModeChangeStartTimer; +#endif + struct LINK_MGMT rBlackList; + + UINT_8 *pucAssocIEs; + size_t assocIeLen; +} CONNECTION_SETTINGS_T, *P_CONNECTION_SETTINGS_T; + +struct _BSS_INFO_T { + + ENUM_NETWORK_TYPE_T eNetworkType; + + UINT_32 u4PrivateData; /* Private data parameter for each NETWORK type usage. */ + /* P2P network type has 3 network interface to distinguish. */ + + 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 fgIsInUse; /* For CNM to assign BSS_INFO */ + BOOLEAN fgIsNetActive; /* TRUE if this network has been activated */ + + UINT_8 ucBssIndex; /* BSS_INFO_T index */ + + 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 */ + + UINT_8 ucOwnMacIndex; /* Owned MAC index 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_8 ucBMCWlanIndex; /* For IBSS/AP Mode, BC/MC Tx wlan index, For STA, BC/MC Rx wlan index */ + + BOOLEAN fgTxBcKeyExist; /* Bc Transmit key exist or not */ + UINT_8 ucTxDefaultKeyID; /* Bc Transmit key ID */ + + UINT_8 ucCurrentGtkId; /* The Current Group key ID */ + + 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 */ + BOOLEAN fgDTIMPresent; + + 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_SW]; + + 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; + /*------------------------------------------------------------------------*/ + /* 802.11ac VHT operation IE when (prStaRec->ucPhyTypeSet & PHY_TYPE_BIT_VHT) */ + /* is true. They have the same definition with fields of */ + /* information element (EASON) */ + /*------------------------------------------------------------------------*/ +#if 1 /* CFG_SUPPORT_802_11AC */ + UINT_8 ucVhtChannelWidth; + UINT_8 ucVhtChannelFrequencyS1; + UINT_8 ucVhtChannelFrequencyS2; + UINT_16 u2VhtBasicMcsSet; +#endif + /*------------------------------------------------------------------------*/ + /* 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]; + + /* Set scanning MAC OUI */ + BOOLEAN fgIsScanOuiSet; + UINT_8 ucScanOui[MAC_OUI_LEN]; + + TIMER_T rObssScanTimer; + UINT_16 u2ObssScanInterval; /* in unit of sec */ + + BOOLEAN fgObssActionForcedTo20M; /* GO only */ + BOOLEAN fgObssBeaconForcedTo20M; /* GO only */ + + /*------------------------------------------------------------------------*/ + /* HW Related Fields (Kevin) */ + /*------------------------------------------------------------------------*/ + UINT_16 u2HwDefaultFixedRateCode; /* The default rate code copied to MAC TX Desc */ + UINT_16 u2HwLPWakeupGuardTimeUsec; + + UINT_8 ucBssFreeQuota; /* The value is updated from FW */ + +#if CFG_ENABLE_GTK_FRAME_FILTER + P_IPV4_NETWORK_ADDRESS_LIST prIpV4NetAddrList; +#endif + UINT_16 u2DeauthReason; + +#if CFG_SUPPORT_TDLS + BOOLEAN fgTdlsIsProhibited; + BOOLEAN fgTdlsIsChSwProhibited; +#endif +#if CFG_SUPPORT_PNO + BOOLEAN fgIsPNOEnable; + BOOLEAN fgIsNetRequestInActive; +#endif + + WIFI_WMM_AC_STAT_T arLinkStatistics[WMM_AC_INDEX_NUM]; /*link layer statistics */ + +#if CFG_SUPPORT_RN + OS_SYSTIME rConnTime; + BOOLEAN fgDisConnReassoc; +#endif + UINT_8 ucRoamSkipTimes; + BOOLEAN fgGoodRcpiArea; + BOOLEAN fgPoorRcpiArea; + UINT_8 ucKeyCmdAction; /* 0: will queue add key command, 1: send add key command, 2: drop command */ + BOOLEAN fgUnencryptedEapol; + UINT_32 u4CoexPhyRateLimit; + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + struct AP_PMF_CFG rApPmfCfg; +#endif +}; + +struct ESS_CHNL_INFO { + UINT_8 ucChannel; + UINT_8 ucUtilization; + UINT_8 ucApNum; +}; + +struct NEIGHBOR_AP_T { + LINK_ENTRY_T rLinkEntry; + UINT_8 aucBssid[MAC_ADDR_LEN]; + BOOLEAN fgHT:1; + BOOLEAN fgSameMD:1; + BOOLEAN fgRmEnabled:1; + BOOLEAN fgFromBtm:1; + BOOLEAN fgQoS:1; + UINT_8 ucReserved:3; + UINT_8 ucPreference; + UINT_8 ucChannel; + UINT_64 u8TermTsf; +}; + +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 ucTxWlanIndex; *//* Legacy wep, adhoc wep wpa Transmit key wlan index */ + + /* BOOLEAN fgKeyMaterialExist[4]; */ + /* UINT_8 aucKeyMaterial[32][4]; */ + +#if 0 + BOOLEAN fgWepWapiBcKeyExist; /* WEP WAPI BC key exist flag */ + UINT_8 ucWepWapiBcWlanIndex; /* WEP WAPI BC wlan index */ + + BOOLEAN fgRsnBcKeyExist[4]; /* RSN BC key exist flag, map to key id 0, 1, 2, 3 */ + UINT_8 ucRsnBcWlanIndex[4]; /* RSN BC wlan index, map to key id 0, 1, 2, 3 */ +#endif + + /* 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 ESS_CHNL_INFO arCurEssChnlInfo[CFG_MAX_NUM_OF_CHNL_INFO]; + UINT_8 ucCurEssChnlInfoNum; + LINK_T rCurEssLink; + struct BSS_TRANSITION_MGT_PARAM_T rBTMParam; + TIMER_T rBtmResponseTimer; + struct LINK_MGMT rNeighborApList; + OS_SYSTIME rNeiApRcvTime; + UINT_32 u4NeiApValidInterval; +#if CFG_SUPPORT_DFS + struct CHANNEL_SWITCH_ANNOUNCE_PARAMS rCsaParam; +#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 + +typedef struct _WLAN_TABLE_T { + UINT_8 ucUsed; + UINT_8 ucBssIndex; + UINT_8 ucKeyId; + UINT_8 ucPairwise; + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + UINT_8 ucStaIndex; +} WLAN_TABLE_T, *P_WLAN_TABLE_T; + +#if 1 /* DBG */ +typedef struct _HAL_WTBL_SEC_CONFIG_T { + BOOL fgRCA2; + BOOL fgRV; + BOOL fgIKV; + BOOL fgRKV; + BOOL fgRCID; + BOOL fgRCA1; + BOOL fgEvenPN; + UINT_8 ucKeyID; + UINT_8 ucMUARIdx; + UINT_8 ucCipherSuit; +} HAL_WTBL_SEC_CONFIG_T, *P_HAL_WTBL_SEC_CONFIG_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; + + /* memory should be matched with max of _BssIndex to avoid buffer overflow. */ + ENUM_PWR_STATE_T aePwrState[MAX_BSS_INDEX + 1]; + + BSS_INFO_T arBssInfoPool[BSS_INFO_NUM]; + + P2P_DEV_INFO_T rP2pDevInfo; + + 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; */ + + P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo; + + /* Currently we only support 2 p2p interface. */ + P_P2P_ROLE_FSM_INFO_T aprP2pRoleFsmInfo[BSS_P2P_NUM]; + + P_PARAM_GET_STA_STATISTICS prP2pQueryStaStatistics; + +#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 */ + + WLAN_TABLE_T arWtbl[WTBL_SIZE]; +#if DBG + HAL_WTBL_SEC_CONFIG_T arWtblCfg[WTBL_SIZE]; +#endif + + 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; + +#if CFG_SUPPORT_WFD + WFD_CFG_SETTINGS_T rWfdConfigureSettings; +#endif + +#if CFG_SLT_SUPPORT + SLT_INFO_T rSltInfo; +#endif + +#if CFG_SUPPORT_PASSPOINT + HS20_INFO_T rHS20Info; +#endif /* CFG_SUPPORT_PASSPOINT */ + UINT_8 aucMediatekOuiIE[64]; + UINT_16 u2MediatekOuiIELen; + + /* Feature Options */ + UINT_8 ucQoS; + + UINT_8 aucAifsN[WMM_AC_INDEX_NUM]; + UINT_8 aucCwMin[WMM_AC_INDEX_NUM]; + UINT_16 au2CwMax[WMM_AC_INDEX_NUM]; + UINT_16 au2TxOp[WMM_AC_INDEX_NUM]; + + UINT_8 ucStaHt; + UINT_8 ucStaVht; + UINT_8 ucApHt; + UINT_8 ucApVht; + UINT_16 u2ApMaxIdlePeriod; + UINT_8 ucApIdleOption; + UINT_8 ucP2pGoHt; + UINT_8 ucP2pGoVht; + UINT_8 ucP2pGcHt; + UINT_8 ucP2pGcVht; + + UINT_8 ucAmpduTx; + UINT_8 ucAmpduRx; + UINT_8 ucTspec; + UINT_8 ucUapsd; + UINT_8 ucStaUapsd; + UINT_8 ucApUapsd; + UINT_8 ucP2pUapsd; + + UINT_8 ucTxShortGI; + UINT_8 ucRxShortGI; + UINT_8 ucTxLdpc; + UINT_8 ucRxLdpc; + UINT_8 ucTxStbc; + UINT_8 ucRxStbc; + UINT_8 ucTxGf; + UINT_8 ucRxGf; + + UINT_8 ucTxopPsTx; + UINT_8 ucSigTaRts; + UINT_8 ucDynBwRts; + + UINT_8 ucStaHtBfee; + UINT_8 ucStaVhtBfee; + UINT_8 ucStaBfer; + UINT_8 ucStaVhtMuBfee; + + UINT_8 ucApWpsMode; + UINT_8 ucCert11nMode; + UINT_8 ucApChannel; + + UINT_8 ucApSco; + UINT_8 ucP2pGoSco; + + UINT_8 ucStaBandwidth; + UINT_8 ucSta5gBandwidth; + UINT_8 ucSta2gBandwidth; + UINT_8 ucAp5gBandwidth; + UINT_8 ucAp2gBandwidth; + UINT_8 ucP2p5gBandwidth; + UINT_8 ucP2p2gBandwidth; + + UINT_8 ucTxBaSize; + UINT_8 ucRxHtBaSize; + UINT_8 ucRxVhtBaSize; + + UINT_8 ucStaDisconnectDetectTh; + UINT_8 ucApDisconnectDetectTh; + UINT_8 ucP2pDisconnectDetectTh; + + UINT_8 ucThreadScheduling; + UINT_8 ucThreadPriority; + INT_8 cThreadNice; + + UINT_8 ucTcRestrict; + UINT_32 u4MaxTxDeQLimit; + UINT_8 ucAlwaysResetUsedRes; + + UINT_32 u4NetifStopTh; + UINT_32 u4NetifStartTh; + + PARAM_GET_CHN_INFO rChnLoadInfo; + +#if CFG_SUPPORT_MTK_SYNERGY + UINT_8 ucMtkOui; + UINT_32 u4MtkOuiCap; + UINT_8 aucMtkFeature[4]; +#endif + + UINT_32 u4HifIstLoopCount; + UINT_32 u4Rx2OsLoopCount; + UINT_32 u4HifTxloopCount; + UINT_32 u4HifTxDataloopCount; + UINT_32 u4TxRxLoopCount; + UINT_32 u4TxFromOsLoopCount; + + UINT_32 au4TcPageCount[TC_NUM]; + UINT_8 ucExtraTxDone; + UINT_8 ucTxDbg; + + UINT_8 ucCmdRsvResource; + UINT_32 u4MgmtQueueDelayTimeout; + + UINT_32 u4StatsLogTimeout; + UINT_32 u4StatsLogDuration; + UINT_8 ucDhcpTxDone; + UINT_8 ucArpTxDone; + UINT_8 ucIcmpTxDone; + PARAM_POWER_MODE ePowerMode; +#ifdef CFG_SUPPORT_DATA_STALL + UINT_32 u4PerHighThreshold; + UINT_32 u4TxLowRateThreshold; + UINT_32 u4RxLowRateThreshold; + UINT_32 u4ReportEventInterval; + UINT_32 u4TrafficThreshold; +#endif + +#ifdef CFG_SUPPORT_COEX_IOT_AP + UINT_8 ucEnCoexIotAP; +#endif +#if CFG_RX_BA_REORDERING_ENHANCEMENT + BOOLEAN fgEnableReportIndependentPkt; +#endif +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1) + UINT_8 ucEfuseBufferModeCal; +#endif + struct RADIO_MEASUREMENT_REQ_PARAMS rRmReqParams; + struct RADIO_MEASUREMENT_REPORT_PARAMS rRmRepParams; + + struct WMM_INFO rWmmInfo; + +} 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; + PUINT_8 pucFileAndLineFor1stNode; +} 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; + UINT_32 u4FwOwnVersionExtend; /*support version extended*/ + +} WIFI_VER_INFO_T, *P_WIFI_VER_INFO_T; + +#if CFG_ENABLE_WIFI_DIRECT +/* +* p2p function pointer structure +*/ + +typedef struct _P2P_FUNCTION_LINKER { + P2P_REMOVE prP2pRemove; + /* NIC_P2P_MEDIA_STATE_CHANGE prNicP2pMediaStateChange; */ + /* SCAN_UPDATE_P2P_DEVICE_DESC prScanUpdateP2pDeviceDesc; */ + /* P2P_FSM_RUN_EVENT_RX_PROBE_RESPONSE_FRAME prP2pFsmRunEventRxProbeResponseFrame; */ + P2P_GENERATE_P2P_IE prP2pGenerateWSC_IEForBeacon; + /* P2P_CALCULATE_WSC_IE_LEN_FOR_PROBE_RSP prP2pCalculateWSC_IELenForProbeRsp; */ + /* P2P_GENERATE_WSC_IE_FOR_PROBE_RSP prP2pGenerateWSC_IEForProbeRsp; */ + /* SCAN_REMOVE_P2P_BSS_DESC prScanRemoveP2pBssDesc; */ + /* P2P_HANDLE_SEC_CHECK_RSP prP2pHandleSecCheckRsp; */ + P2P_NET_REGISTER prP2pNetRegister; + P2P_NET_UNREGISTER prP2pNetUnregister; + P2P_CALCULATE_P2P_IE_LEN prP2pCalculateP2p_IELenForAssocReq; /* All IEs generated from supplicant. */ + P2P_GENERATE_P2P_IE prP2pGenerateP2p_IEForAssocReq; /* All IEs generated from supplicant. */ +} P2P_FUNCTION_LINKER, *P_P2P_FUNCTION_LINKER; + +#endif + +/* + * State Machine: + * -->STOP: No Tx/Rx traffic + * -->DISABLE: Screen is off + * -->RUNNING: Screen is on && Tx/Rx traffic is active + */ +struct PERF_MONITOR_T { + TIMER_T rPerfMonTimer; + ULONG ulPerfMonFlag; + ULONG ulLastTxBytes; + ULONG ulLastRxBytes; + ULONG ulP2PLastRxBytes; + ULONG ulP2PLastTxBytes; + ULONG ulThroughput; /* in bps */ + UINT32 u4UpdatePeriod; /* in ms */ + UINT32 u4TarPerfLevel; + UINT32 u4CurrPerfLevel; +}; + +#if CFG_SUPPORT_REPORT_MISC +struct REPORT_MISC_SET { + UINT_64 u8Ts; + enum ENUM_REPORT_MISC eQueryNum; + INT_32 i4Rssi; + struct EVENT_REPORT_MISC reportMisc; + ULONG ulExtSrcFlag; +}; +#endif +/* + * Major ADAPTER structure + * Major data structure for driver operation + */ +struct _ADAPTER_T { + UINT_16 u2ChipID; + UINT_8 ucRevID; + BOOLEAN fgIsReadRevID; + + 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 */ + BOOLEAN fgAllMulicastFilter; /* mDNS filter used by OS */ + + P_BSS_INFO_T aprBssInfo[HW_BSSID_NUM + 1]; + P_BSS_INFO_T prAisBssInfo; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + UINT_32 u4CSUMFlags; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + ENUM_BAND_T aePreferBand[BSS_INFO_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; + + /* Timer for restarting RFB setup procedure */ + TIMER_T rPacketDelaySetupTimer; + + P_SDIO_CTRL_T prSDIOCtrl; + + /* Buffer for Authentication Event */ + /* Move to glue layer and refine the kal function */ + /* Reference to rsnGeneratePmkidIndication function at rsn.c */ + UINT_8 aucIndicationEventBuffer[(CFG_MAX_PMKID_CACHE * 20) + 8]; + + UINT_32 u4IntStatus; + + ENUM_ACPI_STATE_T rAcpiState; + + BOOLEAN fgIsIntEnable; + BOOLEAN fgIsIntEnableWithLPOwnSet; + + BOOLEAN fgIsFwOwn; + BOOLEAN fgWiFiInSleepyState; + + OS_SYSTIME rLastOwnFailedLogTime; + UINT_32 u4OwnFailedCount; + UINT_32 u4OwnFailedLogCount; + + UINT_32 u4PwrCtrlBlockCnt; + + QUE_T rPendingCmdQueue; + +#if CFG_SUPPORT_MULTITHREAD + QUE_T rTxCmdQueue; + QUE_T rTxCmdDoneQueue; + QUE_T rTxP0Queue; + QUE_T rTxP1Queue; + QUE_T rRxQueue; +#endif + P_GLUE_INFO_T prGlueInfo; + + UINT_8 ucCmdSeqNum; + UINT_8 ucTxSeqNum; + /* PID bit map for each wlan-index. PID range: 1 ~ 127 */ + ULONG au8PidPool[WTBL_SIZE][(NIC_TX_DESC_DRIVER_PID_MAX+1)/__BITS_PER_LONG]; +#if 1 /* CFG_SUPPORT_WAPI */ + BOOLEAN fgUseWapi; +#endif + + /* RF Test flags */ + BOOLEAN fgTestMode; + BOOLEAN fgIcapMode; + + /* 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; + UINT_8 ucOidTimeoutCount; + + /* Root Timer for cnm_timer module */ + ROOT_TIMER rRootTimer; + + BOOLEAN fgIsChipNoAck; + + /* 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; + BOOLEAN fgEnCtiaMode; + + UINT_32 fgEnArpFilter; + + UINT_32 u4UapsdAcBmp; + + UINT_32 u4MaxSpLen; + + UINT_32 u4PsCurrentMeasureEn; + + /* Version Information */ + WIFI_VER_INFO_T rVerInfo; + + /* 5GHz support (from F/W) */ + BOOLEAN fgIsHw5GBandDisabled; + BOOLEAN fgEnable5GBand; + BOOLEAN fgIsEepromUsed; + BOOLEAN fgIsEfuseValid; + BOOLEAN fgIsEmbbededMacAddrValid; + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + BOOLEAN fgIsPowerLimitTableValid; +#endif + +#if CFG_SUPPORT_ANT_SWAP + BOOLEAN fgIsAntSwpSupport; +#endif + + /* Packet Forwarding Tracking */ + INT_32 i4PendingFwdFrameCount; + +#if CFG_SUPPORT_RDD_TEST_MODE + UINT_8 ucRddStatus; +#endif + + BOOL fgDisStaAgingTimeoutDetection; + + UINT_32 u4FwCompileFlag0; + UINT_32 u4FwCompileFlag1; + UINT_32 u4FwFeatureFlag0; + UINT_32 u4FwFeatureFlag1; + +#if CFG_SUPPORT_CFG_FILE + P_WLAN_CFG_T prWlanCfg; + WLAN_CFG_T rWlanCfg; +#endif + +#if CFG_M0VE_BA_TO_DRIVER + TIMER_T rMqmIdleRxBaDetectionTimer; + UINT_32 u4FlagBitmap; +#endif + + ULONG ulSuspendFlag; + struct PERF_MONITOR_T rPerMonitor; +/*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ + UINT_8 aucEepromVaule[16]; /* HQA CMD for Efuse Block size contents */ + UINT_32 u4FreeBlockNum; +/*#endif*/ + + UINT_32 u4QmRxBaMissTimeout; + BOOLEAN fgEnCfg80211Scan; +#if CFG_SUPPORT_ABORT_SCAN + BOOLEAN fgAbortScan; +#endif + struct WLAN_DEBUG_INFO rDebugInfo; +#if CFG_SUPPORT_OSHARE + BOOLEAN fgEnOshareMode; +#endif +#if CFG_DBG_MGT_BUF + LINK_T rMemTrackLink; +#endif +#if CFG_SUPPORT_REPORT_MISC + struct REPORT_MISC_SET rReportMiscSet; +#endif +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + /* link quality monitor */ + UINT_32 u4LastLinkQuality; + struct WIFI_LINK_QUALITY_INFO rLinkQualityInfo; + PARAM_GET_STA_STA_STATISTICS rQueryStaStatistics; + PARAM_802_11_STATISTICS_STRUCT_T rStat; + UINT_32 u4BufLen; +#endif +#ifdef CFG_SUPPORT_DATA_STALL + OS_SYSTIME tmReportinterval; +#endif +#ifdef CFG_SUPPORT_COEX_IOT_AP + BOOLEAN fgEnCts2Self; + UINT_8 ucPrevItem; +#endif +}; /* end of _ADAPTER_T */ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define PERF_MON_DISABLE_BIT (0) +#define PERF_MON_STOP_BIT (1) +#define PERF_MON_RUNNING_BIT (2) + +#define THROUGHPUT_L1_THRESHOLD (20*1024*1024) +#define THROUGHPUT_L2_THRESHOLD (60*1024*1024) +#define THROUGHPUT_L3_THRESHOLD (135*1024*1024) +#define THROUGHPUT_L4_THRESHOLD (180*1024*1024) + +#define SUSPEND_FLAG_FOR_WAKEUP_REASON (0) +#define SUSPEND_FLAG_CLEAR_WHEN_RESUME (1) + +/* Macros for argument _BssIndex */ +#define IS_NET_ACTIVE(_prAdapter, _BssIndex) \ + ((_prAdapter)->aprBssInfo[(_BssIndex)]->fgIsNetActive) + +/* Macros for argument _prBssInfo */ +#define IS_BSS_ACTIVE(_prBssInfo) ((_prBssInfo)->fgIsNetActive) + +#define IS_BSS_AIS(_prBssInfo) \ + ((_prBssInfo)->eNetworkType == NETWORK_TYPE_AIS) + +#define IS_BSS_INDEX_AIS(_prAdapter, _BssIndex) \ + ((IS_BSS_INDEX_VALID(_BssIndex) && \ + IS_BSS_AIS(GET_BSS_INFO_BY_INDEX(_prAdapter, _BssIndex)))) + +#define IS_BSS_P2P(_prBssInfo) \ + ((_prBssInfo)->eNetworkType == NETWORK_TYPE_P2P) + +#define IS_BSS_BOW(_prBssInfo) \ + ((_prBssInfo)->eNetworkType == NETWORK_TYPE_BOW) + +#define SET_NET_ACTIVE(_prAdapter, _BssIndex) \ + {(_prAdapter)->aprBssInfo[(_BssIndex)]->fgIsNetActive = TRUE; } + +#define UNSET_NET_ACTIVE(_prAdapter, _BssIndex) \ + {(_prAdapter)->aprBssInfo[(_BssIndex)]->fgIsNetActive = FALSE; } + +#define BSS_INFO_INIT(_prAdapter, _prBssInfo) \ + { UINT_8 _aucZeroMacAddr[] = NULL_MAC_ADDR; \ + \ + (_prBssInfo)->eConnectionState = PARAM_MEDIA_STATE_DISCONNECTED; \ + (_prBssInfo)->eConnectionStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; \ + (_prBssInfo)->eCurrentOPMode = OP_MODE_INFRASTRUCTURE; \ + (_prBssInfo)->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_RESERVED; \ + COPY_MAC_ADDR((_prBssInfo)->aucBSSID, _aucZeroMacAddr); \ + LINK_INITIALIZE(&((_prBssInfo)->rStaRecOfClientList)); \ + (_prBssInfo)->fgIsBeaconActivated = FALSE; \ + (_prBssInfo)->u2HwDefaultFixedRateCode = RATE_CCK_1M_LONG; \ + } + +/*----------------------------------------------------------------------------*/ +/* Macros for Power State */ +/*----------------------------------------------------------------------------*/ +#define SET_NET_PWR_STATE_IDLE(_prAdapter, _BssIndex) \ + {_prAdapter->rWifiVar.aePwrState[(_BssIndex)] = PWR_STATE_IDLE; } + +#define SET_NET_PWR_STATE_ACTIVE(_prAdapter, _BssIndex) \ + {_prAdapter->rWifiVar.aePwrState[(_BssIndex)] = PWR_STATE_ACTIVE; } + +#define SET_NET_PWR_STATE_PS(_prAdapter, _BssIndex) \ + {_prAdapter->rWifiVar.aePwrState[(_BssIndex)] = PWR_STATE_PS; } + +#define IS_NET_PWR_STATE_ACTIVE(_prAdapter, _BssIndex) \ + (_prAdapter->rWifiVar.aePwrState[(_BssIndex)] == PWR_STATE_ACTIVE) + +#define IS_NET_PWR_STATE_IDLE(_prAdapter, _BssIndex) \ + (_prAdapter->rWifiVar.aePwrState[(_BssIndex)] == PWR_STATE_IDLE) + +#define IS_SCN_PWR_STATE_ACTIVE(_prAdapter) \ + (_prAdapter->rWifiVar.rScanInfo.eScanPwrState == SCAN_PWR_STATE_ACTIVE) + +#define IS_SCN_PWR_STATE_IDLE(_prAdapter) \ + (_prAdapter->rWifiVar.rScanInfo.eScanPwrState == SCAN_PWR_STATE_IDLE) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _ADAPTER_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/bow.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/bow.h new file mode 100644 index 0000000000000..fa1738337dec0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/bow.h @@ -0,0 +1,229 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/bow.h#1 + */ + +#ifndef _BOW_H_ +#define _BOW_H_ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define BOWDEVNAME "bow0" + +#define MAX_BOW_NUMBER_OF_CHANNEL_2G4 14 +#define MAX_BOW_NUMBER_OF_CHANNEL_5G 4 +/* (MAX_BOW_NUMBER_OF_CHANNEL_2G4 + MAX_BOW_NUMBER_OF_CHANNEL_5G) */ +#define MAX_BOW_NUMBER_OF_CHANNEL 18 + +#define MAX_ACTIVITY_REPORT 2 +#define MAX_ACTIVITY_REPROT_TIME 660 + +#define ACTIVITY_REPORT_STATUS_SUCCESS 0 +#define ACTIVITY_REPORT_STATUS_FAILURE 1 +#define ACTIVITY_REPORT_STATUS_TIME_INVALID 2 +#define ACTIVITY_REPORT_STATUS_OTHERS 3 + +#define ACTIVITY_REPORT_SCHEDULE_UNKNOWN 0 /* Does not know the schedule of the interference */ +#define ACTIVITY_REPORT_SCHEDULE_KNOWN 1 + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef struct _BT_OVER_WIFI_COMMAND_HEADER_T { + UINT_8 ucCommandId; + UINT_8 ucSeqNumber; + UINT_16 u2PayloadLength; +} AMPC_COMMAND_HEADER_T, *P_AMPC_COMMAND_HEADER_T; + +typedef struct _BT_OVER_WIFI_COMMAND { + AMPC_COMMAND_HEADER_T rHeader; + UINT_8 aucPayload[0]; +} AMPC_COMMAND, *P_AMPC_COMMAND; + +typedef struct _BT_OVER_WIFI_EVENT_HEADER_T { + UINT_8 ucEventId; + UINT_8 ucSeqNumber; + UINT_16 u2PayloadLength; +} AMPC_EVENT_HEADER_T, *P_AMPC_EVENT_HEADER_T; + +typedef struct _BT_OVER_WIFI_EVENT { + AMPC_EVENT_HEADER_T rHeader; + UINT_8 aucPayload[0]; +} AMPC_EVENT, *P_AMPC_EVENT; + +typedef struct _CHANNEL_DESC_T { + UINT_8 ucChannelBand; + UINT_8 ucChannelNum; +} CHANNEL_DESC, P_CHANNEL_DESC; + +/* Command Structures */ +typedef struct _BOW_SETUP_CONNECTION { +/* Fixed to 2.4G */ + UINT_8 ucChannelNum; + UINT_8 ucReserved1; + UINT_8 aucPeerAddress[6]; + UINT_16 u2BeaconInterval; + UINT_8 ucTimeoutDiscovery; + UINT_8 ucTimeoutInactivity; + UINT_8 ucRole; + UINT_8 ucPAL_Capabilities; + INT_8 cMaxTxPower; + UINT_8 ucReserved2; + +/* Pending, for future BOW 5G supporting. */ +/* + * UINT_8 aucPeerAddress[6]; + * UINT_16 u2BeaconInterval; + * UINT_8 ucTimeoutDiscovery; + * UINT_8 ucTimeoutInactivity; + * UINT_8 ucRole; + * UINT_8 ucPAL_Capabilities; + * INT_8 cMaxTxPower; + * UINT_8 ucChannelListNum; + * CHANNEL_DESC arChannelList[1]; + */ +} BOW_SETUP_CONNECTION, *P_BOW_SETUP_CONNECTION; + +typedef struct _BOW_DESTROY_CONNECTION { + UINT_8 aucPeerAddress[6]; + UINT_8 aucReserved[2]; +} BOW_DESTROY_CONNECTION, *P_BOW_DESTROY_CONNECTION; + +typedef struct _BOW_SET_PTK { + UINT_8 aucPeerAddress[6]; + UINT_8 aucReserved[2]; + UINT_8 aucTemporalKey[16]; +} BOW_SET_PTK, *P_BOW_SET_PTK; + +typedef struct _BOW_READ_RSSI { + UINT_8 aucPeerAddress[6]; + UINT_8 aucReserved[2]; +} BOW_READ_RSSI, *P_BOW_READ_RSSI; + +typedef struct _BOW_READ_LINK_QUALITY { + UINT_8 aucPeerAddress[6]; + UINT_8 aucReserved[2]; +} BOW_READ_LINK_QUALITY, *P_BOW_READ_LINK_QUALITY; + +typedef struct _BOW_SHORT_RANGE_MODE { + UINT_8 aucPeerAddress[6]; + INT_8 cTxPower; + UINT_8 ucReserved; +} BOW_SHORT_RANGE_MODE, *P_BOW_SHORT_RANGE_MODE; + +/* Event Structures */ +typedef struct _BOW_COMMAND_STATUS { + UINT_8 ucStatus; + UINT_8 ucReserved[3]; +} BOW_COMMAND_STATUS, *P_BOW_COMMAND_STATUS; + +typedef struct _BOW_MAC_STATUS { + UINT_8 aucMacAddr[6]; + UINT_8 ucAvailability; + UINT_8 ucNumOfChannel; + CHANNEL_DESC arChannelList[MAX_BOW_NUMBER_OF_CHANNEL]; +} BOW_MAC_STATUS, *P_BOW_MAC_STATUS; + +typedef struct _BOW_LINK_CONNECTED { + CHANNEL_DESC rChannel; + UINT_8 aucReserved; + UINT_8 aucPeerAddress[6]; +} BOW_LINK_CONNECTED, *P_BOW_LINK_CONNECTED; + +typedef struct _BOW_LINK_DISCONNECTED { + UINT_8 ucReason; + UINT_8 aucReserved; + UINT_8 aucPeerAddress[6]; +} BOW_LINK_DISCONNECTED, *P_BOW_LINK_DISCONNECTED; + +typedef struct _BOW_RSSI { + INT_8 cRssi; + UINT_8 aucReserved[3]; +} BOW_RSSI, *P_BOW_RSSI; + +typedef struct _BOW_LINK_QUALITY { + UINT_8 ucLinkQuality; + UINT_8 aucReserved[3]; +} BOW_LINK_QUALITY, *P_BOW_LINK_QUALITY; + +typedef enum _ENUM_BOW_CMD_ID_T { + BOW_CMD_ID_GET_MAC_STATUS = 1, + BOW_CMD_ID_SETUP_CONNECTION, + BOW_CMD_ID_DESTROY_CONNECTION, + BOW_CMD_ID_SET_PTK, + BOW_CMD_ID_READ_RSSI, + BOW_CMD_ID_READ_LINK_QUALITY, + BOW_CMD_ID_SHORT_RANGE_MODE, + BOW_CMD_ID_GET_CHANNEL_LIST, +} ENUM_BOW_CMD_ID_T, *P_ENUM_BOW_CMD_ID_T; + +typedef enum _ENUM_BOW_EVENT_ID_T { + BOW_EVENT_ID_COMMAND_STATUS = 1, + BOW_EVENT_ID_MAC_STATUS, + BOW_EVENT_ID_LINK_CONNECTED, + BOW_EVENT_ID_LINK_DISCONNECTED, + BOW_EVENT_ID_RSSI, + BOW_EVENT_ID_LINK_QUALITY, + BOW_EVENT_ID_CHANNEL_LIST, + BOW_EVENT_ID_CHANNEL_SELECTED, +} ENUM_BOW_EVENT_ID_T, *P_ENUM_BOW_EVENT_ID_T; + +typedef enum _ENUM_BOW_DEVICE_STATE { + BOW_DEVICE_STATE_DISCONNECTED = 0, + BOW_DEVICE_STATE_DISCONNECTING, + BOW_DEVICE_STATE_ACQUIRING_CHANNEL, + BOW_DEVICE_STATE_STARTING, + BOW_DEVICE_STATE_SCANNING, + BOW_DEVICE_STATE_CONNECTING, + BOW_DEVICE_STATE_CONNECTED, + BOW_DEVICE_STATE_NUM +} ENUM_BOW_DEVICE_STATE, *P_ENUM_BOW_DEVICE_STATE; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#endif /*_BOW_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/cmd_buf.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/cmd_buf.h new file mode 100644 index 0000000000000..a1249913e8c8a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/cmd_buf.h @@ -0,0 +1,173 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** 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. + */ + +#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_MSDU_INFO_T prMsduInfo; /* only valid when it's a security/MGMT frame */ + P_NATIVE_PACKET prPacket; /* only valid when it's a security frame */ + + UINT_8 ucBssIndex; + 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 +******************************************************************************** +*/ +#if CFG_DBG_MGT_BUF +#define cmdBufAllocateCmdInfo(_prAdapter, u4Length) \ + cmdBufAllocateCmdInfoX(_prAdapter, u4Length, __FILE__ ":" STRLINE(__LINE__)) +#endif +/******************************************************************************* +* 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); + +#if CFG_DBG_MGT_BUF +P_CMD_INFO_T cmdBufAllocateCmdInfoX(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Length, PUINT_8 fileAndLine); +#else +P_CMD_INFO_T cmdBufAllocateCmdInfo(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Length); +#endif + +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); + +#if CFG_SUPPORT_TX_BF +WLAN_STATUS +wlanSendSetQueryExtCmd(IN P_ADAPTER_T prAdapter, + UINT_8 ucCID, + UINT_8 ucExtCID, + 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 + +VOID cmdBufDumpCmdQueue(P_QUE_T prQueue, CHAR *queName); +#if (CFG_SUPPORT_TRACE_TC4 == 1) +VOID wlanDebugTC4Init(VOID); +VOID wlanDebugTC4Uninit(VOID); +VOID wlanTraceReleaseTcRes(P_ADAPTER_T prAdapter, UINT_16 u2TxRlsCnt, UINT_16 u2Available); +VOID wlanTraceTxCmd(P_CMD_INFO_T prCmd); +VOID wlanDumpTcResAndTxedCmd(PUINT_8 pucBuf, UINT_32 maxLen); +#endif + +#if CFG_SUPPORT_MGMT_FRAME_DEBUG +VOID wlanMgmtFrameDebugInit(VOID); +VOID wlanMgmtFrameDebugUnInit(VOID); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _CMD_BUF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/hal.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/hal.h new file mode 100644 index 0000000000000..fb939dc7e2216 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/hal.h @@ -0,0 +1,628 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/hal.h#1 +*/ + +/*! + * \file "hal.h" + * \brief The declaration of hal functions + * + * N/A + */ + +#ifndef _HAL_H +#define _HAL_H + +#include +/******************************************************************************* +* C O M P I L E 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) \ + HAL_MCR_HIF_RD(_prAdapter, _u4Offset, _pu4Value) + +#define HAL_MCR_HIF_RD(_prAdapter, _u4Offset, _pu4Value) \ +do { \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (kalDevRegRead(_prAdapter->prGlueInfo, _u4Offset, _pu4Value) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, "HAL_MCR_RD access fail! 0x%x: 0x%x\n", \ + (UINT_32) (_u4Offset), *((PUINT_32) (_pu4Value))); \ + GL_RESET_TRIGGER(_prAdapter, RST_FLAG_CHIP_RESET); \ + } \ + } else { \ + DBGLOG(HAL, WARN, "ignore HAL_MCR_RD access! 0x%x\n", \ + (UINT_32) (_u4Offset)); \ + } \ +} while (0) + +#define HAL_MCR_WR(_prAdapter, _u4Offset, _u4Value) \ + HAL_MCR_HIF_WR(_prAdapter, _u4Offset, _u4Value) + +#define HAL_MCR_HIF_WR(_prAdapter, _u4Offset, _u4Value) \ +do { \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (kalDevRegWrite(_prAdapter->prGlueInfo, _u4Offset, _u4Value) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, "HAL_MCR_WR access fail! 0x%x: 0x%x\n", \ + (UINT_32) (_u4Offset), (UINT_32) (_u4Value)); \ + GL_RESET_TRIGGER(_prAdapter, RST_FLAG_CHIP_RESET); \ + } \ + } else { \ + DBGLOG(HAL, WARN, "ignore HAL_MCR_WR access! 0x%x: 0x%x\n", \ + (UINT_32) (_u4Offset), (UINT_32) (_u4Value)); \ + } \ +} while (0) + +#define HAL_PORT_RD(_prAdapter, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ +{ \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + UINT_32 i = 1; \ + while (kalDevPortRead(_prAdapter->prGlueInfo, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) == FALSE) {\ + if (i < 5) { \ + i++; \ + continue; \ + } \ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, "HAL_PORT_RD access fail! 0x%x\n", \ + (UINT_32) (_u4Port)); \ + GL_RESET_TRIGGER(_prAdapter, RST_FLAG_CHIP_RESET); \ + break; \ + } \ + } else { \ + DBGLOG(HAL, WARN, "ignore HAL_PORT_RD access! 0x%x\n", \ + (UINT_32) (_u4Port)); \ + } \ +} + +#define HAL_PORT_WR(_prAdapter, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ +{ \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + UINT_32 i = 1; \ + while (kalDevPortWrite(_prAdapter->prGlueInfo, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) == FALSE) {\ + if (i < 5) { \ + i++; \ + continue; \ + } \ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, "HAL_PORT_WR access fail! 0x%x\n", \ + (UINT_32) (_u4Port)); \ + GL_RESET_TRIGGER(_prAdapter, RST_FLAG_CHIP_RESET); \ + break; \ + } \ + } else { \ + DBGLOG(HAL, WARN, "ignore HAL_PORT_WR access! 0x%x\n", \ + (UINT_32) (_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", \ + (UINT_32)(_u4Port)); \ + } \ + else { \ + /* Todo:: Nothing*/ \ + } \ + } \ + else { \ + DBGLOG(HAL, WARN, "ignore HAL_BYTE_WR access! 0x%x\n", \ + (UINT_32) (_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) */ +/* + * Now rx_thread don't access hif register, so if someone call HAL_MCR_RD, + * no need to use spinlock to protect u4Register and prRegValue. + */ +#define HAL_MCR_RD(_prAdapter, _u4Offset, _pu4Value) \ +do { \ + if ((!_prAdapter->prGlueInfo->hif_thread) || !kalStrnCmp(current->comm, "hif_thread", 10)) { \ + HAL_MCR_HIF_RD(_prAdapter, _u4Offset, _pu4Value); \ + } else { \ + _prAdapter->prGlueInfo->u4Register = _u4Offset; \ + _prAdapter->prGlueInfo->prRegValue = _pu4Value; \ + KAL_WAKE_LOCK_TIMEOUT(_prAdapter, &_prAdapter->prGlueInfo->rTimeoutWakeLock, \ + MSEC_TO_JIFFIES(WAKE_LOCK_THREAD_WAKEUP_TIMEOUT)); \ + set_bit(GLUE_FLAG_HAL_MCR_RD_BIT, &_prAdapter->prGlueInfo->ulFlag); \ + wake_up_interruptible(&_prAdapter->prGlueInfo->waitq_hif); \ + wait_for_completion_interruptible(&_prAdapter->prGlueInfo->rHalRDMCRComp); \ + } \ +} while (0) + +#define HAL_MCR_HIF_RD(_prAdapter, _u4Offset, _pu4Value) \ +do { \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (kalIsResetting() || kalIsResetTriggered()) { \ + DBGLOG_LIMITED(HAL, WARN, "Whole chip reset %s !! ignore HAL_MCR_HIF_RD access!!\n", \ + kalIsResetting() ? "on-going" : "triggered"); \ + } else \ + kalDevRegRead(_prAdapter->prGlueInfo, _u4Offset, _pu4Value); \ +} while (0) + +#define HAL_MCR_WR(_prAdapter, _u4Offset, _u4Value) \ +do { \ + if ((!_prAdapter->prGlueInfo->hif_thread) || !kalStrnCmp(current->comm, "hif_thread", 10)) { \ + HAL_MCR_HIF_WR(_prAdapter, _u4Offset, _u4Value); \ + } else { \ + _prAdapter->prGlueInfo->u4Register = _u4Offset; \ + _prAdapter->prGlueInfo->u4RegValue = _u4Value; \ + KAL_WAKE_LOCK_TIMEOUT(_prAdapter, &_prAdapter->prGlueInfo->rTimeoutWakeLock, \ + MSEC_TO_JIFFIES(WAKE_LOCK_THREAD_WAKEUP_TIMEOUT)); \ + set_bit(GLUE_FLAG_HAL_MCR_WR_BIT, &_prAdapter->prGlueInfo->ulFlag); \ + wake_up_interruptible(&_prAdapter->prGlueInfo->waitq_hif); \ + wait_for_completion_interruptible(&_prAdapter->prGlueInfo->rHalWRMCRComp); \ + } \ +} while (0) + +#define HAL_MCR_HIF_WR(_prAdapter, _u4Offset, _u4Value) \ +do { \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (kalIsResetting() || kalIsResetTriggered()) {\ + DBGLOG_LIMITED(HAL, WARN, "Whole chip reset %s !! ignore HAL_MCR_HIF_WR access!!\n", \ + kalIsResetting() ? "on-going" : "triggered"); \ + } else \ + kalDevRegWrite(_prAdapter->prGlueInfo, _u4Offset, _u4Value); \ +} while (0) + +#define HAL_PORT_RD(_prAdapter, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ +do { \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (_prAdapter->fgIsFwOwn == TRUE) { \ + DBGLOG(HAL, ERROR, "Power control is FW own!! ignore HAL_PORT_RD access!!\n"); \ + } else { \ + if (kalIsResetting() || kalIsResetTriggered()) { \ + DBGLOG(HAL, WARN, "Whole chip reset %s !! ignore HAL_PORT_RD access!!\n", \ + kalIsResetting() ? "on-going" : "triggered"); \ + } else if (!kalDevPortRead(_prAdapter->prGlueInfo, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize)) \ + GL_RESET_TRIGGER(_prAdapter, RST_FLAG_DO_CORE_DUMP); \ + } \ +} while (0) + +#define HAL_PORT_WR(_prAdapter, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ +do { \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (_prAdapter->fgIsFwOwn == TRUE) { \ + DBGLOG(HAL, ERROR, "Power control is FW own!! ignore HAL_PORT_WR access!!\n"); \ + } else { \ + if (kalIsResetting() || kalIsResetTriggered()) { \ + DBGLOG(HAL, WARN, "Whole chip reset %s !! ignore HAL_PORT_WR access!!\n", \ + kalIsResetting() ? "on-going" : "triggered"); \ + } else if (!kalDevPortWrite(_prAdapter->prGlueInfo, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize)) \ + GL_RESET_TRIGGER(_prAdapter, RST_FLAG_DO_CORE_DUMP); \ + } \ +} while (0) + +/*Only call this in hif_thread. Multi-thread operate HIF CR may cause HIF abnormal.*/ +#define HAL_DUMP_AHB_INFO(prAdapter, u2ChipID) \ + kalDumpAhbDebugInfo(prAdapter->prGlueInfo, u2ChipID) + +#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, _u4Len, _pucBuf, _u4ValidBufSize) \ +{ \ + if ((_u4ValidBufSize - ALIGN_4(_u4Len)) >= sizeof(UINT_32)) { \ + /* Fill with single dword of zero as TX-aggregation termination */ \ + /* for block mode transaction that Tx-aggregation length may be less than block size */ \ + *(PUINT_32) (&((_pucBuf)[ALIGN_4(_u4Len)])) = 0; \ + } \ + HAL_PORT_WR(_prAdapter, \ + 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, pucRevId) \ +{ \ + UINT_32 u4Value = 0; \ + HAL_MCR_RD(_prAdapter, \ + MCR_WCIR, \ + &u4Value); \ + *pu2ChipId = (UINT_16)(u4Value & WCIR_CHIP_ID); \ + *pucRevId = (UINT_8)(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) << WHCR_OFFSET_MAX_HIF_RX_LEN_NUM) & 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, au2TxReleaseCount) \ +{ \ + UINT_32 u4Value = 0; \ + UINT_32 u4Reg = 0; \ + UINT_32 idx = 0; \ +\ + for (u4Reg = MCR_WTQCR0; u4Reg <= MCR_WTQCR7; u4Reg += 4) { \ + HAL_MCR_RD(_prAdapter, u4Reg, &u4Value); \ + au2TxReleaseCount[idx++] = u4Value & 0xffff; \ + au2TxReleaseCount[idx++] = (u4Value >> 16) & 0xffff; \ + u4Value = 0; \ + } \ +} + +#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_RECV_MAILBOX_RD_CLR_EN) : \ + (u4Value & ~WHCR_RECV_MAILBOX_RD_CLR_EN)); \ + prAdapter->prGlueInfo->rHifInfo.fgMbxReadClear = fgEnableReadClear;\ +} + +#define HAL_GET_MAILBOX_READ_CLEAR(prAdapter) (prAdapter->prGlueInfo->rHifInfo.fgMbxReadClear) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _HAL_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/hif_rx.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/hif_rx.h new file mode 100644 index 0000000000000..c5851899ddcdf --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/hif_rx.h @@ -0,0 +1,118 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/hif_rx.h#1 +*/ + +/* + * ! \file "hif_rx.h" + * \brief Provide HIF RX Header Information between F/W and Driver + * + * N/A + */ + +#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 +******************************************************************************** +*/ + +/******************************************************************************* +* P U B 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 __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. + */ +static __KAL_INLINE__ VOID hifDataTypeCheck(VOID) +{ +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/hif_tx.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/hif_tx.h new file mode 100644 index 0000000000000..6d93f37cb2e44 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/hif_tx.h @@ -0,0 +1,128 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/hif_tx.h#1 +*/ + +#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 (for short-header format) */ +/* DW 0, Byte 0,1 */ +#define HIF_TX_HDR_TX_BYTE_COUNT_MASK BITS(0, 15) + +/* DW 0, Byte 2 */ +#define HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK BITS(0, 6) +#define HIF_TX_HDR_IP_CSUM BIT(7) + +/* DW 0, Byte 3 */ +#define HIF_TX_HDR_TCP_CSUM BIT(0) +#define HIF_TX_HDR_QUEUE_IDX_MASK BITS(3, 6) +#define HIF_TX_HDR_QUEUE_IDX_OFFSET 3 +#define HIF_TX_HDR_PORT_IDX_MASK BIT(7) +#define HIF_TX_HDR_PORT_IDX_OFFSET 7 + +/******************************************************************************* +* 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_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 +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/* Kevin: we don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + */ +static __KAL_INLINE__ VOID hif_txDataTypeCheck(VOID); + +static __KAL_INLINE__ VOID hif_txDataTypeCheck(VOID) +{ + DATA_STRUCT_INSPECTING_ASSERT(sizeof(HIF_TX_HEADER_T) == 16); + +} + +#endif /*_HIF_TX_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/mac.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/mac.h new file mode 100644 index 0000000000000..182413bbeeb99 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/mac.h @@ -0,0 +1,2997 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/mac.h#1 + */ + +/* + * file "mac.h" + * brief Brief description. + * + * Detail description. + */ + +#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_OUI_LEN 3 + +#define MAC_ADDR_LOCAL_ADMIN BIT(1) + +#define ETH_P_IPV4 0x0800 +#define ETH_P_ARP 0x0806 +#define ETH_P_IPX 0x8137 /* Novell IPX */ +#define ETH_P_AARP 0x80F3 /* AppleTalk Address Resolution Protocol (AARP) */ +#define ETH_P_IPV6 0x86DD +#define ETH_P_VLAN 0x8100 + +#define IP_PRO_ICMP 0x01 +#define IP_PRO_UDP 0x11 +#define IP_PRO_TCP 0x06 + +#define UDP_PORT_DHCPS 0x43 +#define UDP_PORT_DHCPC 0x44 +#define UDP_PORT_DNS 0x35 + +#define ETH_P_1X 0x888E +#define ETH_P_PRE_1X 0x88C7 +#if CFG_SUPPORT_WAPI +#define ETH_WPI_1X 0x88B4 +#endif +#define ETH_PRO_TDLS 0x890d + +/* 802.3 Frame If Ether Type/Len <= 1500 */ +#define ETH_802_3_MAX_LEN 1500 + +/* IP Header definition */ +#define IP_VERSION_MASK BITS(4, 7) +#define IP_VERSION_OFFSET 4 +#define IP_VERSION_4 4 +#define IP_VERSION_6 6 + +#define IP_PROTOCOL_TCP 6 +#define IP_PROTOCOL_UDP 17 + +/* IPv4 Header definition */ +#define IPV4_HDR_TOS_OFFSET 1 +#define IPV4_HDR_TOS_PREC_MASK BITS(5, 7) +#define IPV4_HDR_TOS_PREC_OFFSET 5 +#define IPV4_HDR_IP_IDENTIFICATION_OFFSET 4 +#define IPV4_HDR_IP_PROTOCOL_OFFSET 9 +#define IPV4_HDR_IP_CSUM_OFFSET 10 +#define IPV4_HDR_IP_SRC_ADDR_OFFSET 12 +#define IPV4_HDR_IP_DST_ADDR_OFFSET 16 + +#define IPV4_HDR_LEN 20 +#define IPV4_ADDR_LEN 4 + +#define IPV6_HDR_IP_PROTOCOL_OFFSET 6 +#define IPV6_HDR_IP_SRC_ADDR_OFFSET 8 +#define IPV6_HDR_IP_DST_ADDR_OFFSET 24 +#define IPV6_HDR_IP_DST_ADDR_MAC_HIGH_OFFSET 32 +#define IPV6_HDR_IP_DST_ADDR_MAC_LOW_OFFSET 37 +#define IPV6_PROTOCOL_ICMPV6 0x3A + +#define IPV6_HDR_TC_PREC_OFFSET 1 +#define IPV6_HDR_TC_PREC_MASK BITS(1, 3) +#define IPV6_HDR_PROTOCOL_OFFSET 6 +#define IPV6_HDR_LEN 40 + +#define IPV6_ADDR_LEN 16 + +#define ICMPV6_TYPE_OFFSET 0 +#define ICMPV6_FLAG_OFFSET 4 +#define ICMPV6_TARGET_ADDR_OFFSET 8 +#define ICMPV6_TARGET_LL_ADDR_TYPE_OFFSET 24 +#define ICMPV6_TARGET_LL_ADDR_LEN_OFFSET 25 +#define ICMPV6_TARGET_LL_ADDR_TA_OFFSET 26 + +#define ICMPV6_FLAG_ROUTER_BIT BIT(7) +#define ICMPV6_FLAG_SOLICITED_BIT BIT(6) +#define ICMPV6_FLAG_OVERWRITE_BIT BIT(5) +#define ICMPV6_TYPE_NEIGHBOR_SOLICITATION 0x87 +#define ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT 0x88 + +#define TCP_HDR_TCP_CSUM_OFFSET 16 + +#define UDP_HDR_LEN 8 + +#define UDP_HDR_SRC_PORT_OFFSET 0 +#define UDP_HDR_DST_PORT_OFFSET 2 +#define UDP_HDR_UDP_CSUM_OFFSET 6 + +#define IP_PORT_BOOTP_SERVER 67 +#define IP_PORT_BOOTP_CLIENT 68 + +#define DHCP_MAGIC_NUMBER 0x63825363 + +#define ARP_OPERATION_OFFSET 6 +#define ARP_SNEDER_MAC_OFFSET 8 +#define ARP_SENDER_IP_OFFSET 14 +#define ARP_TARGET_MAC_OFFSET 18 +#define ARP_TARGET_IP_OFFSET 24 +#define ARP_OPERATION_REQUEST 0x0001 +#define ARP_OPERATION_RESPONSE 0x0002 + +#define ARP_PRO_REQ 1 +#define ARP_PRO_RSP 2 + +#define TDLS_ACTION_CODE_OFFSET 2 + +#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} + +#if 1 + +#define ETH_HLEN 14 +#define ETH_TYPE_LEN_OFFSET 12 + +#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 + +#define LOOK_AHEAD_LEN (ETH_HLEN + IP_HEADER_LEN + SOURCE_PORT_LEN) + +#endif +/* DHCP */ +#define NORMAL_DHCP_UDP_LEN 300 + +/* 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 + +#define ETHER_TYPE_LEN_OFFSET 12 + +/* 802.1Q (VLAN) */ +#define ETH_802_1Q_HEADER_LEN 4 + +/* 802.2 LLC/SNAP */ +#define ETH_LLC_OFFSET (ETHER_HEADER_LEN) +#define ETH_LLC_LEN 3 +#define ETH_LLC_DSAP_SNAP 0xAA +#define ETH_LLC_SSAP_SNAP 0xAA +#define ETH_LLC_CONTROL_UNNUMBERED_INFORMATION 0x03 +#define ETH_LLC \ + {ETH_LLC_DSAP_SNAP, ETH_LLC_SSAP_SNAP, ETH_LLC_CONTROL_UNNUMBERED_INFORMATION} + +/* Bluetooth SNAP */ +#define ETH_SNAP_OFFSET (ETHER_HEADER_LEN + ETH_LLC_LEN) +#define ETH_SNAP_LEN 5 +#define ETH_SNAP_OUI_LEN 3 +#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 ETH_SNAP_BT_SIG_OUI {ETH_SNAP_BT_SIG_OUI_0, ETH_SNAP_BT_SIG_OUI_1, ETH_SNAP_BT_SIG_OUI_2} + +#define BOW_PROTOCOL_ID_SECURITY_FRAME 0x0003 + +/* 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_VHT_PHY 126 /* BSS Selector - Clause 22. HT PHY */ +#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 + +/* 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 + +#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 */ +#define AUTH_ALGORITHM_NUM_SAE 3 /* WPA3 - SAE */ +/* 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_RADIO_MEASUREMENT BIT(12) +#define CAP_INFO_DSSS_OFDM BIT(13) +#define CAP_INFO_DELAYED_BLOCK_ACK BIT(14) +#define CAP_INFO_IMM_BLOCK_ACK BIT(15) +/* STA usage of CF-Pollable and CF-Poll Request subfields */ +/* STA: not CF-Pollable */ +#define CAP_CF_STA_NOT_POLLABLE 0x0000 +/* STA: CF-Pollable, not requesting on the CF-Polling list */ +#define CAP_CF_STA_NOT_ON_LIST CAP_INFO_CF_POLL_REQ +/* STA: CF-Pollable, requesting on the CF-Polling list */ +#define CAP_CF_STA_ON_LIST CAP_INFO_CF_POLLABLE +/* STA: CF-Pollable, requesting never to be polled */ +#define CAP_CF_STA_NEVER_POLLED (CAP_INFO_CF_POLLABLE | CAP_INFO_CF_POLL_REQ) + +/* AP usage of CF-Pollable and CF-Poll Request subfields */ +/* AP: No point coordinator (PC) */ +#define CAP_CF_AP_NO_PC 0x0000 +/* AP: PC at AP for delivery only (no polling) */ +#define CAP_CF_AP_DELIVERY_ONLY CAP_INFO_CF_POLL_REQ +/* AP: PC at AP for delivery and polling */ +#define CAP_CF_AP_DELIVERY_POLLING CAP_INFO_CF_POLLABLE + +/* 7.3.1.5 Current AP Address field */ +#define CURR_AP_ADDR_FIELD_LEN MAC_ADDR_LEN + +/* 7.3.1.6 Listen Interval field */ +#define LISTEN_INTERVAL_FIELD_LEN 2 + +/* 7.3.1.7 Reason Code field */ +#define REASON_CODE_FIELD_LEN 2 + +#define REASON_CODE_RESERVED 0 /* Reseved */ +#define REASON_CODE_UNSPECIFIED 1 /* Unspecified reason */ +#define REASON_CODE_PREV_AUTH_INVALID 2 /* Previous auth no longer valid */ +#define REASON_CODE_DEAUTH_LEAVING_BSS 3 /* Deauth because sending STA is leaving BSS */ +#define REASON_CODE_DISASSOC_INACTIVITY 4 /* Disassoc due to inactivity */ +#define REASON_CODE_DISASSOC_AP_OVERLOAD 5 /* Disassoc because AP is unable to handle all assoc STAs */ +#define REASON_CODE_CLASS_2_ERR 6 /* Class 2 frame rx from nonauth STA */ +#define REASON_CODE_CLASS_3_ERR 7 /* Class 3 frame rx from nonassoc STA */ +#define REASON_CODE_DISASSOC_LEAVING_BSS 8 /* Disassoc because sending STA is leaving BSS */ +#define REASON_CODE_ASSOC_BEFORE_AUTH 9 /* STA requesting (re)assoc is not auth with responding STA */ +#define REASON_CODE_DISASSOC_PWR_CAP_UNACCEPTABLE 10 /* + * Disassoc because the info in Power Capability is + * unacceptable + */ +#define REASON_CODE_DISASSOC_SUP_CHS_UNACCEPTABLE 11 /* + * Disassoc because the info in Supported Channels is + * unacceptable + */ +#define REASON_CODE_INVALID_INFO_ELEM 13 /* Invalid information element */ +#define REASON_CODE_MIC_FAILURE 14 /* MIC failure */ +#define REASON_CODE_4_WAY_HANDSHAKE_TIMEOUT 15 /* 4-way handshake timeout */ +#define REASON_CODE_GROUP_KEY_UPDATE_TIMEOUT 16 /* Group key update timeout */ +#define REASON_CODE_DIFFERENT_INFO_ELEM 17 /* + * Info element in 4-way handshake different from + * (Re-)associate request/Probe response/Beacon + */ +#define REASON_CODE_MULTICAST_CIPHER_NOT_VALID 18 /* Multicast Cipher is not valid */ +#define REASON_CODE_UNICAST_CIPHER_NOT_VALID 19 /* Unicast Cipher is not valid */ +#define REASON_CODE_AKMP_NOT_VALID 20 /* AKMP is not valid */ +#define REASON_CODE_UNSUPPORTED_RSNE_VERSION 21 /* Unsupported RSNE version */ +#define REASON_CODE_INVALID_RSNE_CAPABILITIES 22 /* Invalid RSNE Capabilities */ +#define REASON_CODE_IEEE_802_1X_AUTH_FAILED 23 /* IEEE 802.1X Authentication failed */ +#define REASON_CODE_CIPHER_REJECT_SEC_POLICY 24 /* Cipher suite rejected because of the security policy */ +#define REASON_CODE_DISASSOC_UNSPECIFIED_QOS 32 /* Disassoc for unspecified, QoS-related reason */ +#define REASON_CODE_DISASSOC_LACK_OF_BANDWIDTH 33 /* + * Disassoc because QAP lacks sufficient bandwidth + * for this QSTA + */ +#define REASON_CODE_DISASSOC_ACK_LOST_POOR_CHANNEL 34 /* + * Disassoc because of too many ACKs lost for AP transmissions + * and/or poor channel conditions + */ +#define REASON_CODE_DISASSOC_TX_OUTSIDE_TXOP_LIMIT 35 /* + * Disassoc because QSTA is transmitting outside the limits of + * its TXOPs + */ +#define REASON_CODE_PEER_WHILE_LEAVING 36 /* QSTA is leaving the QBSS or resetting */ +#define REASON_CODE_PEER_REFUSE_DLP 37 /* Peer does not want to use this mechanism */ +#define REASON_CODE_PEER_SETUP_REQUIRED 38 /* Frames received but a setup is reqired */ +#define REASON_CODE_PEER_TIME_OUT 39 /* Time out */ +#define REASON_CODE_PEER_CIPHER_UNSUPPORTED 45 /* Peer does not support the requested cipher suite */ +#define REASON_CODE_BEACON_TIMEOUT 100 /* for beacon timeout, defined by mediatek */ +/* 7.3.1.8 AID field */ +#define AID_FIELD_LEN 2 +#define AID_MASK BITS(0, 13) +#define AID_MSB BITS(14, 15) +#define AID_MIN_VALUE 1 +#define AID_MAX_VALUE 2007 + +/* 7.3.1.9 Status Code field */ +#define STATUS_CODE_FIELD_LEN 2 + +#define STATUS_CODE_RESERVED 0 /* Reserved - Used by TX Auth */ +#define STATUS_CODE_SUCCESSFUL 0 /* Successful */ +#define STATUS_CODE_UNSPECIFIED_FAILURE 1 /* Unspecified failure */ +#define STATUS_CODE_CAP_NOT_SUPPORTED 10 /* Cannot support all requested cap in the Cap Info field */ +#define STATUS_CODE_REASSOC_DENIED_WITHOUT_ASSOC 11 /* + * Reassoc denied due to inability to confirm that + * assoc exists + */ +#define STATUS_CODE_ASSOC_DENIED_OUTSIDE_STANDARD 12 /* Assoc denied due to reason outside the scope of this std. */ +#define STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED 13 /* + * Responding STA does not support the specified + * auth algorithm + */ +#define STATUS_CODE_AUTH_OUT_OF_SEQ 14 /* + * Rx an auth frame with auth transaction seq num + * out of expected seq + */ +#define STATUS_CODE_AUTH_REJECTED_CHAL_FAIL 15 /* Auth rejected because of challenge failure */ +#define STATUS_CODE_AUTH_REJECTED_TIMEOUT 16 /* + * Auth rejected due to timeout waiting for next frame + * in sequence + */ +#define STATUS_CODE_ASSOC_DENIED_AP_OVERLOAD 17 /* + * Assoc denied because AP is unable to handle additional + * assoc STAs + */ +#define STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED 18 /* + * Assoc denied due to requesting STA not supporting + * all of basic rates + */ +#define STATUS_CODE_ASSOC_DENIED_NO_SHORT_PREAMBLE 19 /* + * Assoc denied due to requesting STA not supporting short + * preamble + */ +#define STATUS_CODE_ASSOC_DENIED_NO_PBCC 20 /* Assoc denied due to requesting STA not supporting PBCC */ +#define STATUS_CODE_ASSOC_DENIED_NO_CH_AGILITY 21 /* + * Assoc denied due to requesting STA not supporting channel + * agility + */ +#define STATUS_CODE_ASSOC_REJECTED_NO_SPEC_MGT 22 /* Assoc rejected because Spectrum Mgt capability is required */ +#define STATUS_CODE_ASSOC_REJECTED_PWR_CAP 23 /* + * Assoc rejected because the info in Power Capability + * is unacceptable + */ +#define STATUS_CODE_ASSOC_REJECTED_SUP_CHS 24 /* + * Assoc rejected because the info in Supported Channels + * is unacceptable + */ +#define STATUS_CODE_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25 /* + * Assoc denied due to requesting STA not supporting + * short slot time + */ +#define STATUS_CODE_ASSOC_DENIED_NO_DSSS_OFDM 26 /* + * Assoc denied due to requesting STA not supporting + * DSSS-OFDM + */ +#if CFG_SUPPORT_802_11W +#define STATUS_CODE_ASSOC_REJECTED_TEMPORARILY 30 /* IEEE 802.11w, Assoc denied due to the SA query */ +#define STATUS_CODE_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31 /* + * IEEE 802.11w, Assoc denied due to the MFP select + * policy + */ +#endif +#define STATUS_CODE_UNSPECIFIED_QOS_FAILURE 32 /* Unspecified, QoS-related failure */ +#define STATUS_CODE_ASSOC_DENIED_BANDWIDTH 33 /* + * Assoc denied due to insufficient bandwidth to handle another + * QSTA + */ +#define STATUS_CODE_ASSOC_DENIED_POOR_CHANNEL 34 /* + * Assoc denied due to excessive frame loss rates and/or poor + * channel conditions + */ +#define STATUS_CODE_ASSOC_DENIED_NO_QOS_FACILITY 35 /* + * Assoc denied due to requesting STA not supporting QoS + * facility + */ +#define STATUS_CODE_REQ_DECLINED 37 /* Request has been declined */ +#define STATUS_CODE_REQ_INVALID_PARAMETER_VALUE 38 /* + * Request has not been successful as one or more parameters + * have invalid values + */ +#define STATUS_CODE_REQ_NOT_HONORED_TSPEC 39 /* + * TS not created because request cannot be honored. + * Suggested TSPEC provided. + */ +#define STATUS_CODE_INVALID_INFO_ELEMENT 40 /* Invalid information element */ +#define STATUS_CODE_INVALID_GROUP_CIPHER 41 /* Invalid group cipher */ +#define STATUS_CODE_INVALID_PAIRWISE_CIPHER 42 /* Invalid pairwise cipher */ +#define STATUS_CODE_INVALID_AKMP 43 /* Invalid AKMP */ +#define STATUS_CODE_UNSUPPORTED_RSN_IE_VERSION 44 /* Unsupported RSN information element version */ +#define STATUS_CODE_INVALID_RSN_IE_CAP 45 /* Invalid RSN information element capabilities */ +#define STATUS_CODE_CIPHER_SUITE_REJECTED 46 /* Cipher suite rejected because of security policy */ +#define STATUS_CODE_REQ_NOT_HONORED_TS_DELAY 47 /* + * TS not created because request cannot be honored. + * Attempt to create a TS later. + */ +#define STATUS_CODE_DIRECT_LINK_NOT_ALLOWED 48 /* Direct Link is not allowed in the BSS by policy */ +#define STATUS_CODE_DESTINATION_STA_NOT_PRESENT 49 /* Destination STA is not present within this QBSS */ +#define STATUS_CODE_DESTINATION_STA_NOT_QSTA 50 /* Destination STA is not a QSTA */ +#define STATUS_CODE_ASSOC_DENIED_LARGE_LIS_INTERVAL 51 /* Association denied because the ListenInterval is too large */ + +/* proprietary definition of reserved field of Status Code */ +#define STATUS_CODE_JOIN_FAILURE 0xFFF0 /* Join failure */ +#define STATUS_CODE_JOIN_TIMEOUT 0xFFF1 /* Join timeout */ +#define STATUS_CODE_AUTH_TIMEOUT 0xFFF2 /* Authentication timeout */ +#define STATUS_CODE_ASSOC_TIMEOUT 0xFFF3 /* (Re)Association timeout */ +#define STATUS_CODE_CCX_CCKM_REASSOC_FAILURE 0xFFF4 /* CCX CCKM reassociation failure */ + +/* 7.3.1.10 Timestamp field */ +#define TIMESTAMP_FIELD_LEN 8 + +/* 7.3.1.11 Category of Action field */ +#define CATEGORY_SPEC_MGT 0 +#define CATEGORY_QOS_ACTION 1 +/* QoS action */ +#define CATEGORY_DLS_ACTION 2 +/* Direct Link Protocol (DLP) action */ +#define CATEGORY_BLOCK_ACK_ACTION 3 +/* Block ack action */ +#define CATEGORY_PUBLIC_ACTION 4 +/* Public action */ +#define CATEGORY_RM_ACTION 5 +/* Radio measurement action */ +#define CATEGORY_FT_ACTION 6 +/* Fast BSS Transition */ +#define CATEGORY_HT_ACTION 7 +#if CFG_SUPPORT_802_11W +#define CATEGORY_SA_QUERY_ACTION 8 +#define CATEGORY_PROTECTED_DUAL_OF_PUBLIC_ACTION 9 +#endif +#define CATEGORY_WNM_ACTION 10 +/* 802.11v Wireless Network Management */ +#define CATEGORY_UNPROTECTED_WNM_ACTION 11 +/* 802.11v Wireless Network Management */ +#define CATEGORY_TDLS_ACTION 12 +/* Mesh */ +#define CATEGORY_MESH_ACTION 13 +/* Multihop */ +#define CATEGORY_MULTIHOP_ACTION 14 +/* Self-protected */ +#define CATEGORY_SELF_PROTECTED_ACTION 15 +#define CATEGORY_DMG_ACTION 16 +/* WME management notification */ +#define CATEGORY_WME_MGT_NOTIFICATION 17 +/* WME management notification */ +#define CATEGORY_FST_ACTION 18 +/* Robust AV Streaming */ +#define CATEGORY_ROBUST_AV_STREAMING_ACTION 19 +#define CATEGORY_UNPROTECTED_DMG_ACTION 20 +/* VHT action */ +#define CATEGORY_VHT_ACTION 21 +/* VHT action */ + +#if CFG_SUPPORT_802_11W +#define CATEGORY_VENDOR_SPECIFIC_ACTION_PROTECTED 126 +#endif +#define CATEGORY_VENDOR_SPECIFIC_ACTION 127 + +/* 7.3.1.14 Block Ack Parameter Set field */ +#define BA_PARAM_SET_ACK_POLICY_MASK BIT(1) +#define BA_PARAM_SET_ACK_POLICY_MASK_OFFSET 1 +#define BA_PARAM_SET_TID_MASK BITS(2, 5) +#define BA_PARAM_SET_TID_MASK_OFFSET 2 +#define BA_PARAM_SET_BUFFER_SIZE_MASK BITS(6, 15) +#define BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET 6 + +#define BA_PARAM_SET_ACK_POLICY_IMMEDIATE_BA 1 +#define BA_PARAM_SET_ACK_POLICY_DELAYED_BA 0 + +/* 3 Management frame body components (II): Information Elements. */ +/* 7.3.2 Element IDs of information elements */ +#define ELEM_HDR_LEN 2 + +#define ELEM_ID_SSID 0 /* SSID */ +#define ELEM_ID_SUP_RATES 1 /* Supported rates */ +#define ELEM_ID_FH_PARAM_SET 2 /* FH parameter set */ +#define ELEM_ID_DS_PARAM_SET 3 /* DS parameter set */ +#define ELEM_ID_CF_PARAM_SET 4 /* CF parameter set */ +#define ELEM_ID_TIM 5 /* TIM */ +#define ELEM_ID_IBSS_PARAM_SET 6 /* IBSS parameter set */ +#define ELEM_ID_COUNTRY_INFO 7 /* Country information */ +#define ELEM_ID_HOPPING_PATTERN_PARAM 8 /* Hopping pattern parameters */ +#define ELEM_ID_HOPPING_PATTERN_TABLE 9 /* Hopping pattern table */ +#define ELEM_ID_REQUEST 10 /* Request */ +#define ELEM_ID_BSS_LOAD 11 /* BSS load */ +#define ELEM_ID_EDCA_PARAM_SET 12 /* EDCA parameter set */ +#define ELEM_ID_TSPEC 13 /* Traffic specification (TSPEC) */ +#define ELEM_ID_TCLAS 14 /* Traffic classification (TCLAS) */ +#define ELEM_ID_SCHEDULE 15 /* Schedule */ +#define ELEM_ID_CHALLENGE_TEXT 16 /* Challenge text */ + +#define ELEM_ID_PWR_CONSTRAINT 32 /* Power constraint */ +#define ELEM_ID_PWR_CAP 33 /* Power capability */ +#define ELEM_ID_TPC_REQ 34 /* TPC request */ +#define ELEM_ID_TPC_REPORT 35 /* TPC report */ +#define ELEM_ID_SUP_CHS 36 /* Supported channels */ +#define ELEM_ID_CH_SW_ANNOUNCEMENT 37 /* Channel switch announcement */ +#define ELEM_ID_MEASUREMENT_REQ 38 /* Measurement request */ +#define ELEM_ID_MEASUREMENT_REPORT 39 /* Measurement report */ +#define ELEM_ID_QUIET 40 /* Quiet */ +#define ELEM_ID_IBSS_DFS 41 /* IBSS DFS */ +#define ELEM_ID_ERP_INFO 42 /* ERP information */ +#define ELEM_ID_TS_DELAY 43 /* TS delay */ +#define ELEM_ID_TCLAS_PROCESSING 44 /* TCLAS processing */ +#define ELEM_ID_HT_CAP 45 /* HT Capabilities subelement */ +#define ELEM_ID_QOS_CAP 46 /* QoS capability */ +#define ELEM_ID_RSN 48 /* RSN IE */ +#define ELEM_ID_EXTENDED_SUP_RATES 50 /* Extended supported rates */ +#define ELEM_ID_AP_CHANNEL_REPORT 51 /* AP Channel Report Element */ +#define ELEM_ID_NEIGHBOR_REPORT 52 /* Neighbor Report */ +#define ELEM_ID_MOBILITY_DOMAIN 54 /* Mobility Domain for 802.11R */ +#define ELEM_ID_FAST_TRANSITION 55 /* Fast Bss Transition for 802.11 R */ +#if CFG_SUPPORT_802_11W +#define ELEM_ID_TIMEOUT_INTERVAL 56 /* 802.11w SA Timeout interval */ +#endif +#define ELEM_ID_RESOURCE_INFO_CONTAINER 57 /* Resource Information Container for 802.11 R */ +#define ELEM_ID_SUP_OPERATING_CLASS 59 /* Supported Operating Classes */ + +#define ELEM_ID_HT_OP 61 /* HT Operation */ +#define ELEM_ID_SCO 62 /* Secondary Channel Offset */ +#define ELEM_ID_RRM_ENABLED_CAP 70 /* Radio Resource Management Enabled Capabilities */ +#define ELEM_ID_20_40_BSS_COEXISTENCE 72 /* 20/40 BSS Coexistence */ +#define ELEM_ID_20_40_INTOLERANT_CHNL_REPORT 73 /* 20/40 BSS Intolerant Channel Report */ +#define ELEM_ID_OBSS_SCAN_PARAMS 74 /* Overlapping BSS Scan Parameters */ +#define ELEM_ID_BSS_MAX_IDLE_PERIOD 90 /* AP Keep-Alive parameters */ +#define ELEM_ID_EXTENDED_CAP 127 /* Extended capabilities */ + +#define ELEM_ID_INTERWORKING 107 /* Interworking with External Network */ +#define ELEM_ID_ADVERTISEMENT_PROTOCOL 108 /* Advertisement Protocol */ +#define ELEM_ID_QOS_MAP_SET 110 /* QoS Map Set */ +#define ELEM_ID_ROAMING_CONSORTIUM 111 /* Roaming Consortium */ +#define ELEM_ID_EXTENDED_CAP 127 /* Extended capabilities */ + +#define ELEM_ID_VENDOR 221 /* Vendor specific IE */ +#define ELEM_ID_WPA ELEM_ID_VENDOR /* WPA IE */ +#define ELEM_ID_WMM ELEM_ID_VENDOR /* WMM IE */ +#define ELEM_ID_P2P ELEM_ID_VENDOR /* WiFi Direct */ +#define ELEM_ID_WSC ELEM_ID_VENDOR /* WSC IE */ + +#define ELEM_ID_VHT_CAP 191 /* VHT Capabilities subelement */ +#define ELEM_ID_VHT_OP 192 /* VHT Operation information */ +#define ELEM_ID_WIDE_BAND_CHANNEL_SWITCH 194 /* Wide Bandwidth Channel Switch */ +#define ELEM_ID_OP_MODE 199 /* Operation Mode Notification */ +#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 */ + +#define ELEM_MAX_LEN_SUPPORTED_CHANNELS 9 + +/* 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_TSM_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_TSM_REPORT 9 + +/* 7.3.2.25 RSN information element */ +#define ELEM_MAX_LEN_WPA 34 /* one pairwise, one AKM suite, one PMKID */ +#define ELEM_MAX_LEN_RSN 38 /* one pairwise, one AKM suite, one PMKID */ +#define ELEM_MAX_LEN_WAPI 38 /* one pairwise, one AKM suite, one BKID */ +#define ELEM_MAX_LEN_WSC 200 /* one pairwise, one AKM suite, one BKID */ + +#if CFG_SUPPORT_802_11W +#define ELEM_WPA_CAP_MFPR BIT(6) +#define ELEM_WPA_CAP_MFPC BIT(7) +#endif + +/* 7.3.2.27 Extended Capabilities information element */ +#define ELEM_EXT_CAP_20_40_COEXIST_SUPPORT BIT(0) +#define ELEM_EXT_CAP_PSMP_CAP BIT(4) +#define ELEM_EXT_CAP_SERVICE_INTERVAL_GRANULARITY BIT(5) +#define ELEM_EXT_CAP_SCHEDULE_PSMP BIT(6) + +#define ELEM_EXT_CAP_BSS_TRANSITION_BIT 19 +#define ELEM_EXT_CAP_UTC_TSF_OFFSET_BIT 27 +#define ELEM_EXT_CAP_INTERWORKING_BIT 31 +#define ELEM_EXT_CAP_QOSMAPSET_BIT 32 +#define ELEM_EXT_CAP_WNM_NOTIFICATION_BIT 46 +#define ELEM_EXT_CAP_OP_MODE_NOTIFICATION_BIT 62 + +#define ELEM_MAX_LEN_EXT_CAP (8) + +/* 7.3.2.30 TSPEC element */ +#define TS_INFO_TRAFFIC_TYPE_MASK BIT(0) /* WMM: 0 (Asynchronous TS of low-duty cycles) */ +#define TS_INFO_TID_OFFSET 1 +#define TS_INFO_TID_MASK BITS(1, 4) +#define TS_INFO_DIRECTION_OFFSET 5 +#define TS_INFO_DIRECTION_MASK BITS(5, 6) +#define TS_INFO_ACCESS_POLICY_OFFSET 7 +#define TS_INFO_ACCESS_POLICY_MASK BITS(7, 8) +#define TS_INFO_AGGREGATION_MASK BIT(9) /* WMM: 0 */ +#define TS_INFO_APSD_MASK BIT(10) +#define TS_INFO_UP_OFFSET 11 +#define TS_INFO_UP_MASK BITS(11, 13) +#define TS_INFO_ACK_POLICY_OFFSET 14 +#define TS_INFO_ACK_POLICY_MASK BITS(14, 15) +#define TS_INFO_SCHEDULE_MASK 16 + +/* 7.3.2.45 RRM Enabled Capbility element */ +#define ELEM_MAX_LEN_RRM_CAP 5 +#define RRM_CAP_INFO_LINK_MEASURE_BIT 0 +#define RRM_CAP_INFO_NEIGHBOR_REPORT_BIT 1 +#define RRM_CAP_INFO_REPEATED_MEASUREMENT 3 +#define RRM_CAP_INFO_BEACON_PASSIVE_MEASURE_BIT 4 +#define RRM_CAP_INFO_BEACON_ACTIVE_MEASURE_BIT 5 +#define RRM_CAP_INFO_BEACON_TABLE_BIT 6 +#define RRM_CAP_INFO_TSM_BIT 14 +#define RRM_CAP_INFO_RRM_BIT 17 + +/* 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 + +#define ELEM_MAX_LEN_VHT_CAP (14 - ELEM_HDR_LEN) /* sizeof(IE_VHT_CAP_T)-2 */ +/* 8.4.2.161 VHT Operation element */ +#define ELEM_MAX_LEN_VHT_OP (7 - ELEM_HDR_LEN) /* sizeof(IE_VHT_OP_T)-2 */ + +/* 8.4.2.160.3 VHT Supported MCS Set field*/ + +/* 8.4.2.160.2 VHT Capabilities Info field*/ +#define VHT_CAP_INFO_MAX_MPDU_LEN_3K 0 +#define VHT_CAP_INFO_MAX_MPDU_LEN_8K BIT(0) +#define VHT_CAP_INFO_MAX_MPDU_LEN_11K BIT(1) + +#define VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_SET_NONE 0 +#define VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_SET_160 BIT(2) +#define VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_SET_160_80P80 BIT(3) + +#define VHT_CAP_INFO_RX_LDPC BIT(4) +#define VHT_CAP_INFO_SHORT_GI_80 BIT(5) +#define VHT_CAP_INFO_SHORT_GI_160_80P80 BIT(6) +#define VHT_CAP_INFO_TX_STBC BIT(7) + +#define VHT_CAP_INFO_RX_STBC_NONE 0 +#define VHT_CAP_INFO_RX_STBC_ONE_STREAM BIT(8) +#define VHT_CAP_INFO_RX_STBC_TWO_STREAM BIT(9) +#define VHT_CAP_INFO_RX_STBC_THREE_STREAM BITS(8, 9) +#define VHT_CAP_INFO_RX_STBC_FOUR_STREAM BIT(10) + +#define VHT_CAP_INFO_SU_BEAMFORMER_CAPABLE BIT(11) +#define VHT_CAP_INFO_SU_BEAMFORMEE_CAPABLE BIT(12) + +#define VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF_BEAMFORMER_ANTENNAS_SUPPOERTED BITS(13, 15) +#define VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF_BEAMFORMER_ANTENNAS_4_SUPPOERTED BITS(13, 14) + +#define VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS BITS(16, 18) + +#define VHT_CAP_INFO_MU_BEAMFOMER_CAPABLE BIT(19) +#define VHT_CAP_INFO_MU_BEAMFOMEE_CAPABLE BIT(20) +#define VHT_CAP_INFO_VHT_TXOP_PS BIT(21) +#define VHT_CAP_INFO_HTC_VHT_CAPABLE BIT(22) + +#define VHT_CAP_INFO_MAX_AMPDU_LENGTH_OFFSET 23 + +#define VHT_CAP_INFO_VHT_LINK_ADAPTATION_CAPABLE_NOFEEDBACK 0 +#define VHT_CAP_INFO_VHT_LINK_ADAPTATION_CAPABLE_UNSOLICITED BITS(27) +#define VHT_CAP_INFO_VHT_LINK_ADAPTATION_CAPABLE_BOTH BITS(26, 27) + +#define VHT_CAP_INFO_RX_ANTENNA_PATTERN_CONSISTENCY BIT(28) +#define VHT_CAP_INFO_TX_ANTENNA_PATTERN_CONSISTENCY BIT(29) + +#define VHT_CAP_INFO_MCS_MAP_MCS7 0 +#define VHT_CAP_INFO_MCS_MAP_MCS8 BIT(0) +#define VHT_CAP_INFO_MCS_MAP_MCS9 (BIT(1) | ~BIT(0)) +#define VHT_CPA_INFO_MCS_NOT_SUPPORTED BITS(0, 1) + +#define VHT_CAP_INFO_MCS_1SS_OFFSET 0 +#define VHT_CAP_INFO_MCS_2SS_OFFSET 2 +#define VHT_CAP_INFO_MCS_3SS_OFFSET 4 +#define VHT_CAP_INFO_MCS_4SS_OFFSET 6 +#define VHT_CAP_INFO_MCS_5SS_OFFSET 8 +#define VHT_CAP_INFO_MCS_6SS_OFFSET 10 +#define VHT_CAP_INFO_MCS_7SS_OFFSET 12 +#define VHT_CAP_INFO_MCS_8SS_OFFSET 14 + +#define VHT_OP_CHANNEL_WIDTH_20_40 0 +#define VHT_OP_CHANNEL_WIDTH_80 1 +#define VHT_OP_CHANNEL_WIDTH_160 2 +#define VHT_OP_CHANNEL_WIDTH_80P80 3 + +/* 8.4.1.50 Operating Mode Field */ +#define VHT_OP_MODE_CHANNEL_WIDTH BITS(0, 1) +#define VHT_OP_MODE_RX_NSS BITS(4, 6) +#define VHT_OP_MODE_RX_NSS_TYPE BIT(7) + +#define VHT_OP_MODE_CHANNEL_WIDTH_20 0 +#define VHT_OP_MODE_CHANNEL_WIDTH_40 1 +#define VHT_OP_MODE_CHANNEL_WIDTH_80 2 +#define VHT_OP_MODE_CHANNEL_WIDTH_160_80P80 3 + +/* 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_MAX_AMPDU_LEN_128K BIT(2) +#define AMPDU_PARAM_MAX_AMPDU_LEN_256K (BIT(2) | BIT(0)) +#define AMPDU_PARAM_MAX_AMPDU_LEN_512K BITS(1, 2) +#define AMPDU_PARAM_MAX_AMPDU_LEN_1024K BITS(0, 2) + +#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 */ +#define TXBF_IMPLICIT_RX_CAPABLE BIT(0) +#define TXBF_RX_STAGGERED_SOUNDING_CAPABLE BIT(1) +#define TXBF_TX_STAGGERED_SOUNDING_CAPABLE BIT(2) +#define TXBF_RX_NDP_CAPABLE BIT(3) +#define TXBF_TX_NDP_CAPABLE BIT(4) +#define TXBF_IMPLICIT_TX_CAPABLE BIT(5) +#define TXBF_CALIBRATION_CAPABLE BITS(6, 7) +#define TXBF_EXPLICIT_CSI_TX_CAPABLE BIT(8) +#define TXBF_EXPLICIT_NONCOMPRESSED_TX_CAPABLE BIT(9) +#define TXBF_EXPLICIT_COMPRESSED_TX_CAPAB BIT(10) +#define TXBF_EXPLICIT_CSI_FEEDBACK_CAPABLE BITS(11, 12) +#define TXBF_EXPLICIT_NONCOMPRESSED_FEEDBACK_CAPABLE BITS(13, 14) + +#define TXBF_EXPLICIT_COMPRESSED_FEEDBACK_CAPABLE BITS(15, 16) +#define TXBF_EXPLICIT_COMPRESSED_FEEDBACK_IMMEDIATE_CAPABLE BIT(16) + +#define TXBF_MINIMAL_GROUPING_CAPABLE BITS(17, 18) +#define TXBF_MINIMAL_GROUPING_1_2_3_CAPABLE BITS(17, 18) + +#define TXBF_CSI_BFER_ANTENNANUM_SUPPORTED BITS(19, 20) +#define TXBF_NONCOMPRESSED_TX_ANTENNANUM_SUPPORTED BITS(21, 22) + +#define TXBF_COMPRESSED_TX_ANTENNANUM_SUPPORTED BITS(23, 24) +#define TXBF_COMPRESSED_TX_ANTENNANUM_4_SUPPORTED BITS(23, 24) + +#define TXBF_CSI_MAX_ROWS_BFER_SUPPORTED BITS(25, 26) + +#define TXBF_CHANNEL_ESTIMATION_CAPABILITY BITS(27, 28) +#define TXBF_CHANNEL_ESTIMATION_4STS_CAPABILITY BITS(27, 28) + +/* 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) + +/* 7.3.2.79 Bss max idle period element*/ +#define ELEM_MAX_LEN_BSS_MAX_IDLE_PERIOD (5 - ELEM_HDR_LEN) + + +/* 802.11u 7.3.2.92 Interworking IE */ +#define ELEM_MAX_LEN_INTERWORKING (11 - ELEM_HDR_LEN) + +/* 802.11u 7.3.2.93 Advertisement Protocol IE */ +#define ELEM_MAX_LEN_ADV_PROTOCOL (4 - ELEM_HDR_LEN) + +/* 802.11u 7.3.2.96 Roaming Consortium IE */ +#define ELEM_MAX_LEN_ROAMING_CONSORTIUM (19 - ELEM_HDR_LEN) + +#define IW_IE_LENGTH_ANO 1 +#define IW_IE_LENGTH_ANO_VENUE 3 +#define IW_IE_LENGTH_ANO_HESSID 7 +#define IW_IE_LENGTH_ANO_VENUE_HESSID 9 + +#if CFG_SUPPORT_PASSPOINT +/* HOTSPOT 2.0 Indication IE*/ +#define ELEM_MAX_LEN_HS20_INDICATION 5 +#define ELEM_MIN_LEN_HS20_INDICATION 4 + +/* Hotspot Configuration*/ +#define ELEM_HS_CONFIG_DGAF_DISABLED_MASK BIT(0) /* Downstream Group-Addressed Forwarding */ +#endif /* CFG_SUPPORT_PASSPOINT */ + +/* MTK Vendor Specific OUI */ +#define ELEM_MIN_LEN_MTK_OUI 7 +#define VENDOR_OUI_MTK { 0x00, 0x0C, 0xE7 } +#define MTK_SYNERGY_CAP_SUPPORT_24G_MCS89 BIT(3) +#define MTK_SYNERGY_CAP0 (MTK_SYNERGY_CAP_SUPPORT_24G_MCS89) +#define MTK_SYNERGY_CAP1 0x0 +#define MTK_SYNERGY_CAP2 0x0 +#define MTK_SYNERGY_CAP3 0x0 + +/* 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_QOS_MAP_CONFIGURE 4 /*Qos Map Configure*/ + +#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 */ +#define ACTION_DELTS_FRAME_LEN (24 + 7) /*category + action + WMM TSinfo:3 + reason:2*/ + +/* 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_WNM_BSS_TRANSITION_MANAGEMENT_QUERY 6 +#define ACTION_WNM_BSS_TRANSITION_MANAGEMENT_REQ 7 +#define ACTION_WNM_BSS_TRANSITION_MANAGEMENT_RSP 8 +#define ACTION_UNPROTECTED_WNM_TIMING_MEAS_LEN 12 + +/* 8.5.23.1 VHT Action */ +#define ACTION_VHT_COMPRESSED_BFEAMFORMING 0 +#define ACTION_GROUP_ID_MANAGEMENT 1 +#define ACTION_OPERATING_MODE_NOTIFICATION 2 + +/* 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 + +#if CFG_SUPPORT_PASSPOINT +#define VENDOR_OUI_TYPE_HS20 16 +#endif /* CFG_SUPPORT_PASSPOINT */ + +#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_CONTROL_TID_OFFSET 12 +#define CTRL_BAR_BAR_INFORMATION_OFFSET 18 +#define CTRL_BAR_BAR_INFORMATION_SSN_OFFSET 4 + +/* 802.11-2012, 8.5.7 Radio Measurement action fields, table 8-206 */ +#define RM_ACTION_NEIGHBOR_REQUEST 4 +#define RM_ACTION_REIGHBOR_RESPONSE 5 +#define RM_ACTION_RM_REQUEST 0 +#define RM_ACTION_RM_REPORT 1 +#define RM_ACTION_LM_REQUEST 2 +#define RM_ACTION_LM_REPORT 3 +#define RM_ACTION_NEIGHBOR_REQUEST 4 +#define RM_ACTION_REIGHBOR_RESPONSE 5 + +/******************************************************************************* +* 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; + +typedef struct _BOOTP_PROTOCOL_T { + UINT_8 ucOperation; + UINT_8 ucHdrType; + UINT_8 ucHdrLen; + UINT_8 ucHops; + UINT_32 u4TransId; + UINT_16 u2Seconds; + UINT_16 u2Flags; + UINT_32 u4CIAddr; + UINT_32 u4YIAddr; + UINT_32 u4SIAddr; + UINT_32 u4GIAddr; + UINT_8 aucCHAddr[16]; + UINT_8 aucServerName[64]; + UINT_8 aucFileName[128]; + UINT_8 aucOptions[0]; +} __KAL_ATTRIB_PACKED__ BOOTP_PROTOCOL_T, *P_BOOTP_PROTOCOL_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[0]; /* Variable size, should no more than 8 */ +} __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[0]; /* Variable size */ +} __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.19 Supported Channels element */ +typedef struct _IE_SUPPORTED_CHANNELS_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucChannelNum[ELEM_MAX_LEN_SUPPORTED_CHANNELS * 2]; +} __KAL_ATTRIB_PACKED__ IE_SUPPORTED_CHANNELS_T, *P_IE_SUPPORTED_CHANNELS_T; + +/* 7.3.2.20 Channel Switch Announcement element */ +typedef struct _IE_CHANNEL_SWITCH_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucChannelSwitchMode; + UINT_8 ucNewChannelNum; + UINT_8 ucChannelSwitchCount; +} __KAL_ATTRIB_PACKED__ IE_CHANNEL_SWITCH_T, *P_IE_CHANNEL_SWITCH_T; + +typedef struct _IE_TIMEOUT_INTERVAL_T { + UINT_8 ucId; + UINT_8 ucLength; +#define IE_TIMEOUT_INTERVAL_TYPE_RESERVED 0 +#define IE_TIMEOUT_INTERVAL_TYPE_REASSOC 1 +#define IE_TIMEOUT_INTERVAL_TYPE_KEY_LIFETIME 43200 +#define IE_TIMEOUT_INTERVAL_TYPE_ASSOC_COMEBACK 3 + UINT_8 ucType; + UINT_32 u4Value; +} __KAL_ATTRIB_PACKED__ IE_TIMEOUT_INTERVAL_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; + +/* 7.3.2.60 20/40 BSS Coexistence element */ +typedef struct _IE_SUP_OPERATING_CLASS_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucCur; + UINT_8 ucSup[255]; +} __KAL_ATTRIB_PACKED__ IE_SUP_OPERATING_CLASS_T, *P_IE_SUP_OPERATING_CLASS_T; + +/* 8.4.2.30 BSS Load element */ +struct __KAL_ATTRIB_PACKED__ IE_BSS_LOAD { + UINT_8 ucId; + UINT_8 ucLength; + UINT_16 u2StaCnt; + UINT_8 ucChnlUtilizaion; + UINT_16 u2AvailabeAC; +}; + +/* 8.4.2.81 Bss Max Idle Period */ +struct __KAL_ATTRIB_PACKED__ IE_BSS_MAX_IDLE_PERIOD_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_16 u2MaxIdlePeriod; /* unit is 1000 TUs, 1024ms */ + UINT_8 ucIdleOption; /* BIT(0) is now means Protected Keep-Alive Required, other bits are reserved */ +}; + +/* 8.4.2.39 Neighbor Report Element */ +struct __KAL_ATTRIB_PACKED__ IE_NEIGHBOR_REPORT_T { + UINT_8 ucId; /* Element ID */ + UINT_8 ucLength; /* Length */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* OUI */ + UINT_32 u4BSSIDInfo; /* Type */ + UINT_8 ucOperClass; /* Hotspot Configuration */ + UINT_8 ucChnlNumber; + UINT_8 ucPhyType; + UINT_8 aucSubElem[0]; +}; + +struct __KAL_ATTRIB_PACKED__ SUB_ELEMENT_T { + UINT_8 ucSubID; + UINT_8 ucLength; + UINT_8 aucOptInfo[1]; +}; + +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; + +struct __KAL_ATTRIB_PACKED__ RM_BCN_REPORT { + UINT_8 ucRegulatoryClass; + UINT_8 ucChannel; + UINT_8 aucStartTime[8]; + UINT_16 u2Duration; + UINT_8 ucReportInfo; + UINT_8 ucRCPI; + UINT_8 ucRSNI; + UINT_8 aucBSSID[MAC_ADDR_LEN]; + UINT_8 ucAntennaID; + UINT_8 aucParentTSF[4]; + UINT_8 aucOptElem[0]; +}; + +struct __KAL_ATTRIB_PACKED__ RM_TSM_REPORT { + UINT_64 u8ActualStartTime; + UINT_16 u2Duration; + UINT_8 aucPeerAddress[MAC_ADDR_LEN]; + UINT_8 ucTID; + UINT_8 ucReason; + UINT_32 u4TransmittedMsduCnt; + UINT_32 u4DiscardedMsduCnt; + UINT_32 u4FailedMsduCnt; + UINT_32 u4MultiRetryCnt; + UINT_32 u4CfPollLostCnt; + UINT_32 u4AvgQueDelay; + UINT_32 u4AvgDelay; + UINT_8 ucBin0Range; + UINT_32 u4Bin[6]; + UINT_8 aucOptSubElems[0]; +}; + +/* 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; + +/* 8.4.2.160.3 VHT Supported MCS Set field */ +typedef struct _VHT_SUPPORTED_MCS_FIELD { + UINT_16 u2RxMcsMap; + UINT_16 u2RxHighestSupportedDataRate; + UINT_16 u2TxMcsMap; + UINT_16 u2TxHighestSupportedDataRate; +} __KAL_ATTRIB_PACKED__ VHT_SUPPORTED_MCS_FIELD, *P_VHT_SUPPORTED_MCS_FIELD; + +typedef struct _IE_VHT_CAP_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_32 u4VhtCapInfo; + VHT_SUPPORTED_MCS_FIELD rVhtSupportedMcsSet; +} __KAL_ATTRIB_PACKED__ IE_VHT_CAP_T, *P_IE_VHT_CAP_T; + +/* 8.4.2.161 VHT Operation element */ +typedef struct _IE_VHT_OP_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucVhtOperation[3]; + UINT_16 u2VhtBasicMcsSet; +} __KAL_ATTRIB_PACKED__ IE_VHT_OP_T, *P_IE_VHT_OP_T; + +/* 8.4.2.22 Secondary Channel Offset element */ +typedef struct _IE_SECONDARY_OFFSET_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucSecondaryOffset; +} __KAL_ATTRIB_PACKED__ IE_SECONDARY_OFFSET_T, *P_IE_SECONDARY_OFFSET_T; + +/* 8.4.2.105 Mesh Channel Switch Parameters element */ +typedef struct _IE_MESH_CHANNEL_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucTimetoLive; + UINT_8 ucFlags; + UINT_16 u2ReasonCodes; + UINT_16 u2ProcedenceValue; +} __KAL_ATTRIB_PACKED__ IE_MESH_CHANNEL_T, *P_IE_MESH_CHANNEL_T; + +/* 8.4.2.163 Wide Bandwidth Channel Switch element */ +typedef struct _IE_WIDE_BAND_CHANNEL_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucNewChannelWidth; + UINT_8 ucChannelS1; + UINT_8 ucChannelS2; +} __KAL_ATTRIB_PACKED__ IE_WIDE_BAND_CHANNEL_T, *P_IE_WIDE_BAND_CHANNEL_T; + +/* 8.4.2.168 Operating Mode Notification element */ +typedef struct _IE_OP_MODE_NOTIFICATION_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucOpMode; +} __KAL_ATTRIB_PACKED__ IE_OP_MODE_NOTIFICATION_T, *P_IE_OP_MODE_NOTIFICATION_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; + +/* public Action frame format */ +typedef struct _WLAN_PUBLIC_VENDOR_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: should be 0x4 */ + UINT_8 ucAction; /* Action Value: should be 0x9 */ + UINT_8 ucOUI[3]; + UINT_8 ucSubType; + UINT_8 ucPubSubType; +} __KAL_ATTRIB_PACKED__ WLAN_PUBLIC_VENDOR_ACTION_FRAME, *P_WLAN_PUBLIC_VENDOR_ACTION_FRAME; + +/* 7.4.1.1 Spectrum Measurement Request frame format */ +typedef struct _ACTION_SM_REQ_FRAME { + /* ADDTS Request MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* ADDTS Request frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 aucInfoElem[1]; /* Information elements */ +} __KAL_ATTRIB_PACKED__ ACTION_SM_REQ_FRAME, *P_ACTION_SM_REQ_FRAME; + +/* 7.4.1.2 Spectrum Measurement Report frame format */ +typedef ACTION_SM_REQ_FRAME ACTION_SM_REPORT_FRAME, *P_ACTION_SM_REPORT_FRAME; + +/* 7.4.1.5 Channel Switch Announcement frame format */ +typedef struct _ACTION_CHANNEL_SWITCH_FRAME { + /* ADDTS Request MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* ADDTS Request frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 aucInfoElem[1]; /* Information elements */ +} __KAL_ATTRIB_PACKED__ ACTION_CHANNEL_SWITCH_FRAME, *P_ACTION_CHANNEL_SWITCH_FRAME; + +/* 7.4.2.1 ADDTS Request frame format */ +typedef struct _ACTION_ADDTS_REQ_FRAME { + /* ADDTS Request MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* ADDTS Request frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 aucInfoElem[1]; /* + * Information elements, such as + * TS Delay, and etc. + */ +} __KAL_ATTRIB_PACKED__ ACTION_ADDTS_REQ_FRAME, *P_ACTION_ADDTS_REQ_FRAME; + +/* 7.4.2.2 ADDTS Response frame format */ +typedef struct _ACTION_ADDTS_RSP_FRAME { + /* ADDTS Response MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* ADDTS Response frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 ucStatusCode; /* WMM Status Code is of one byte */ + UINT_8 aucInfoElem[1]; /* + * Information elements, such as + * TS Delay, and etc. + */ +} __KAL_ATTRIB_PACKED__ ACTION_ADDTS_RSP_FRAME, *P_ACTION_ADDTS_RSP_FRAME; + +/* 7.4.2.3 DELTS frame format */ +typedef struct _ACTION_DELTS_FRAME { + /* DELTS MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* DELTS frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 aucTsInfo[3]; /* TS Info */ +} __KAL_ATTRIB_PACKED__ ACTION_DELTS_FRAME, *P_ACTION_DELTS_FRAME; + +/* 7.4.2.3 QOSMAPSET CONFIGURATE frame format */ +struct _ACTION_QOS_MAP_CONFIGURE_FRAME { + /* QOSMAP CONFIGURE MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* DELTS frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t qosMapSet[1]; /* qosmapset IE */ +}; + +/* 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; + +/* 8.5.23.4 Operating Mode Notification frame format */ +typedef struct _ACTION_OP_MODE_NOTIFICATION_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 */ + /* Operating Mode Notification frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucOperatingMode; /* Operating Mode */ +} __KAL_ATTRIB_PACKED__ ACTION_OP_MODE_NOTIFICATION_FRAME, *P_ACTION_OP_MODE_NOTIFICATION_FRAME; + +/* 8.5.7.6/8.5.7.7 Neighbor Report Request/Response frame format */ +struct ACTION_NEIGHBOR_REPORT_FRAME { + /* Neighbor Report Request/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 */ + /* Neighbor Report Request/Response frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 aucInfoElem[1]; /* subelements */ +}; + +/* 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; + +#if CFG_SUPPORT_PASSPOINT +/* HS20 3.1 - HS 2.0 Indication Information Element */ +typedef struct _IE_HS20_INDICATION_T { + UINT_8 ucId; /* Element ID */ + UINT_8 ucLength; /* Length */ + UINT_8 aucOui[3]; /* OUI */ + UINT_8 ucType; /* Type */ + UINT_8 ucHotspotConfig; /* Hotspot Configuration */ +} __KAL_ATTRIB_PACKED__ IE_HS20_INDICATION_T, *P_IE_HS20_INDICATION_T; +#endif /* CFG_SUPPORT_PASSPOINT */ + +/* WAPI Information element format */ +typedef struct _WAPI_INFO_ELEM_T { + UCHAR ucElemId; + UCHAR ucLength; + UINT_16 u2Version; + UINT_16 u2AKMSuiteCount; + UINT_32 u4AKMSuite; + UINT_16 u2PairSuiteCount; + UINT_32 u4PairSuite; + UINT_32 u4GroupSuite; +} __KAL_ATTRIB_PACKED__ WAPI_INFO_ELEM_T, *P_WAPI_INFO_ELEM_T; + +/* Information Elements from MTK Synergies.*/ +typedef struct _IE_MTK_OUI_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucOui[3]; + UINT_8 aucCapability[4]; + UINT_8 aucInfoElem[1]; +} __KAL_ATTRIB_PACKED__ IE_MTK_OUI_T, *P_IE_MTK_OUI_T; + +struct __KAL_ATTRIB_PACKED__ SUB_IE_BSS_TERM_DURATION_T { + UINT_8 ucSubId; + UINT_8 ucLength; + UINT_8 aucTermTsf[8]; + UINT_16 u2Duration; +}; + +struct __KAL_ATTRIB_PACKED__ SUB_IE_BSS_CAND_PREFERENCE_T { + UINT_8 ucSubId; + UINT_8 ucLength; + UINT_8 ucPreference; +}; + +struct __KAL_ATTRIB_PACKED__ ACTION_BTM_QUERY_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 */ + /* BSS Coexistence Management frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + + UINT_8 ucDialogToken; + UINT_8 ucQueryReason; + PUINT_8 pucNeighborBss; +}; + +struct __KAL_ATTRIB_PACKED__ ACTION_BTM_REQ_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 */ + /* BSS Coexistence Management frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + + UINT_8 ucDialogToken; + UINT_8 ucRequestMode; + UINT_16 u2DisassocTimer; + UINT_8 ucValidityInterval; + UINT_8 aucOptInfo[0]; + /* Optional: Bss Termination Duration(0~12 bytes), + ** Session Information URL, Bss Transition Candidate List + */ +}; + +struct __KAL_ATTRIB_PACKED__ ACTION_BTM_RSP_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 */ + /* BSS Coexistence Management frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + + UINT_8 ucDialogToken; + UINT_8 ucStatusCode; + UINT_8 ucBssTermDelay; + UINT_8 aucOptInfo[0]; + /* Optional Target BSSID and Transition Candidate Entry list */ +}; + +struct __KAL_ATTRIB_PACKED__ IE_MOBILITY_DOMAIN_T { + UINT_8 ucId; /* Element ID = 54 */ + UINT_8 ucLength; /* Length is 3 */ + UINT_16 u2MDID; + UINT_8 ucBitMap; /* Bit 0: FT over DS; Bit 1: Resource Request Protocol Capbility, others: reserved */ +}; + +struct __KAL_ATTRIB_PACKED__ IE_FAST_TRANSITION_T { + UINT_8 ucId; /* Element ID = 55 */ + UINT_8 ucLength; /* Length is variable */ + UINT_8 ucMicCtrl; /* Bit 0 ~ Bit 7: reserved; Bit 8 ~ Bit 15: IE count used to calculate MIC, 0 means No MIC*/ + UINT_8 aucMic[16]; /* */ + UINT_8 aucANonce[32]; /* Nonce of R1KH */ + UINT_8 aucSNonce[32]; /* Nonce of S1KH */ + UINT_8 aucOptParam[0]; +}; + +struct __KAL_ATTRIB_PACKED__ SUB_IE_FAST_TRANSITION_T { + UINT_8 ucSubId; /* 0, 4-255: reserved; 1: R1KH-ID; 2: GTK; 3: R0KH-ID */ + UINT_8 ucLength; /* bytes, R1KH-ID: 6; GTK: 15-42; R0KH-ID: 1-48 */ + UINT_8 aucData[1]; +}; + +struct __KAL_ATTRIB_PACKED__ SUB_IE_GTK_T { + UINT_8 ucSubId; /* subId=2 */ + UINT_8 ucLength; /* length is 15-42 */ + UINT_16 u2KeyInfo; /* Bit0-Bit1: Key ID; Bit2-Bit15: reserved */ + UINT_8 ucKeyLength; + UINT_8 aucRsc[8]; + UINT_8 aucKey[5]; +}; + +/* 8.5.7.4 Link Measurement Request frame format */ +struct __KAL_ATTRIB_PACKED__ ACTION_LM_REQUEST_FRAME { + /* Link Measurement 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 */ + /* Link Measurement Request frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 ucTxPowerUsed; /* */ + UINT_8 ucTxPowerMax; /* */ + UINT_8 aucInfoElem[1]; /* subelements */ +}; + +/* 8.5.7.5 Link Measurement Report frame format */ +struct __KAL_ATTRIB_PACKED__ ACTION_LM_REPORT_FRAME { + /* Link Measurement Report 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 */ + /* Link Measurement Report frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 aucTpcReportIE[4]; /* */ + UINT_8 ucRxAntennaID; + UINT_8 ucTxAntennaID; + UINT_8 ucRCPI; + UINT_8 ucRSNI; + UINT_8 aucInfoElem[1]; /* subelements */ +}; + +struct __KAL_ATTRIB_PACKED__ IE_REQUEST_T { + UINT_8 ucId; /* ELEM_ID_REQUEST */ + UINT_8 ucLength; /* 0 to 237 */ + UINT_8 aucReqIds[0]; +}; + +struct __KAL_ATTRIB_PACKED__ IE_AP_CHNL_REPORT_T { + UINT_8 ucId; /* ELEM_ID_AP_CHANNEL_REPORT */ + UINT_8 ucLength; /* 1 to 237 */ + UINT_8 ucOpClass; + UINT_8 aucChnlList[0]; +}; + +struct __KAL_ATTRIB_PACKED__ SUB_IE_REPORTING_DETAIL_T { + UINT_8 ucSubID; /* 2 */ + UINT_8 ucLength; + /* 0: No fixed length fields or elemets. 1: all fixed length fields and requested IEs 2: */ + UINT_8 ucDetailValue; +}; + +struct __KAL_ATTRIB_PACKED__ IE_TSPEC_BODY { + UINT_8 aucTsInfo[3]; /* 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 */ +}; + +struct __KAL_ATTRIB_PACKED__ WMM_ACTION_TSPEC_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, value is 17 */ + UINT_8 ucAction; /* Action Value, value: 2, delts */ + UINT_8 ucDlgToken; + UINT_8 ucStatusCode; + UINT_8 aucInfoElem[1]; +}; + +#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 VHT_CAP_IE(fp) ((P_IE_VHT_CAP_T) fp) + +#define VHT_OP_IE(fp) ((P_IE_VHT_OP_T) fp) + +#define OBSS_SCAN_PARAM_IE(fp) ((P_IE_OBSS_SCAN_PARAM_T) fp) + +#define BSS_20_40_COEXIST_IE(fp) ((P_IE_20_40_COEXIST_T) fp) + +#define SUP_OPERATING_CLASS_IE(fp) ((P_IE_SUP_OPERATING_CLASS_T) fp) + +#define QUIET_IE(fp) ((P_IE_QUIET_T) fp) + +#define MTK_OUI_IE(fp) ((P_IE_MTK_OUI_T) fp) + +#define SUPPORTED_CHANNELS_IE(fp) ((P_IE_SUPPORTED_CHANNELS_T)fp) +#define TIMEOUT_INTERVAL_IE(fp) ((IE_TIMEOUT_INTERVAL_T *)fp) + +/* The macro to check if the MAC address is B/MCAST Address */ +#define IS_BMCAST_MAC_ADDR(_pucDestAddr) \ + ((BOOLEAN) (((PUINT_8)(_pucDestAddr))[0] & BIT(0))) + +/* The macro to check if the MAC address is UCAST Address */ +#define IS_UCAST_MAC_ADDR(_pucDestAddr) \ + ((BOOLEAN) !(((PUINT_8)(_pucDestAddr))[0] & BIT(0))) + +/* The macro to copy the MAC address */ +#define COPY_MAC_ADDR(_pucDestAddr, _pucSrcAddr) \ + kalMemCopy(_pucDestAddr, _pucSrcAddr, MAC_ADDR_LEN) + +/* The macro to check if two MAC addresses are equal */ +#define EQUAL_MAC_ADDR(_pucDestAddr, _pucSrcAddr) \ + (!kalMemCmp(_pucDestAddr, _pucSrcAddr, MAC_ADDR_LEN)) + +/* The macro to check if two MAC addresses are not equal */ +#define UNEQUAL_MAC_ADDR(_pucDestAddr, _pucSrcAddr) \ + (kalMemCmp(_pucDestAddr, _pucSrcAddr, MAC_ADDR_LEN)) + +/* The macro to check whether two SSIDs are equal */ +#define EQUAL_SSID(pucSsid1, ucSsidLen1, pucSsid2, ucSsidLen2) \ + ((ucSsidLen1 <= ELEM_MAX_LEN_SSID) && \ + (ucSsidLen2 <= ELEM_MAX_LEN_SSID) && \ + ((ucSsidLen1) == (ucSsidLen2)) && \ + !kalMemCmp(pucSsid1, pucSsid2, ucSsidLen1)) + +/* The macro to check whether two SSIDs are equal */ +#define UNEQUAL_SSID(pucSsid1, ucSsidLen1, pucSsid2, ucSsidLen2) \ + ((ucSsidLen1 > ELEM_MAX_LEN_SSID) || \ + (ucSsidLen2 > ELEM_MAX_LEN_SSID) || \ + ((ucSsidLen1) != (ucSsidLen2)) || \ + kalMemCmp(pucSsid1, pucSsid2, ucSsidLen1)) + +/* The macro to copy the SSID, the length of pucDestSsid should have at least 32 bytes */ +#define COPY_SSID(pucDestSsid, ucDestSsidLen, pucSrcSsid, ucSrcSsidLen) \ + do { \ + ucDestSsidLen = (ucSrcSsidLen > ELEM_MAX_LEN_SSID) \ + ? ELEM_MAX_LEN_SSID : ucSrcSsidLen; \ + if (ucDestSsidLen) { \ + kalMemCopy(pucDestSsid, pucSrcSsid, ucDestSsidLen); \ + } \ + } while (FALSE) + +/* The macro to copy the IE */ +#define COPY_IE(pucDestIE, pucSrcIE) \ + do { \ + kalMemCopy((PUINT_8)pucDestIE, \ + (PUINT_8)pucSrcIE,\ + IE_SIZE(pucSrcIE)); \ + } while (FALSE) + +#define IE_FOR_EACH(_pucIEsBuf, _u2IEsBufLen, _u2Offset) \ + for ((_u2Offset) = 0; \ + ((((_u2Offset) + 2) <= (_u2IEsBufLen)) && (((_u2Offset) + IE_SIZE(_pucIEsBuf)) <= (_u2IEsBufLen))); \ + (_u2Offset) += IE_SIZE(_pucIEsBuf), (_pucIEsBuf) += IE_SIZE(_pucIEsBuf)) + +#define SET_EXT_CAP(_aucField, _ucFieldLength, _ucBit) \ + do { \ + if ((_ucBit) < ((_ucFieldLength) * 8)) { \ + PUINT_8 aucExtCap = (PUINT_8)(_aucField); \ + ((aucExtCap)[(_ucBit) / 8]) |= BIT((_ucBit) % 8); \ + } \ + } while (FALSE) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _MAC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/mt6630_reg.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/mt6630_reg.h new file mode 100644 index 0000000000000..849c529d02d33 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/mt6630_reg.h @@ -0,0 +1,322 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/mt6630_reg.h#1 +*/ + +/* + * ! \file "mt6630_reg.h" + * \brief The common register definition of MT6630 + * + * N/A + */ + +#ifndef _MT6630_REG_H +#define _MT6630_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 MT6630 MCR Definition */ + +/* 2 Host Interface */ + +/* 4 CHIP ID Register */ +#define MCR_WCIR 0x0000 + +/* 4 HIF Low Power Control Register */ +#define MCR_WHLPCR 0x0004 + +/* 4 Control Status Register */ +#define MCR_WSDIOCSR 0x0008 + +/* 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 0x0020 + +/* 4 WLAN Software Interrupt Control Register */ +#define MCR_WSICR 0x0024 + +/* 4 WLAN TX Data Register 1 */ +#define MCR_WTDR1 0x0034 + +/* 4 WLAN RX Data Register 0 */ +#define MCR_WRDR0 0x0050 + +/* 4 WLAN RX Data Register 1 */ +#define MCR_WRDR1 0x0054 + +/* 4 Host to Device Send Mailbox 0 Register */ +#define MCR_H2DSM0R 0x0070 + +/* 4 Host to Device Send Mailbox 1 Register */ +#define MCR_H2DSM1R 0x0074 + +/* 4 Device to Host Receive Mailbox 0 Register */ +#define MCR_D2HRM0R 0x0078 + +/* 4 Device to Host Receive Mailbox 1 Register */ +#define MCR_D2HRM1R 0x007c + +/* 4 WLAN RX Packet Length Register */ +#define MCR_WRPLR 0x0090 + +/* 4 Test Mode Data Port */ +#define MCR_WTMDR 0x00B0 + +/* 4 Test Mode Control Register */ +#define MCR_WTMCR 0x00B4 + +/* 4 Test Mode Data Pattern Control Register #0 */ +#define MCR_WTMDPCR0 0x00B8 + +/* 4 Test Mode Data Pattern Control Register #1 */ +#define MCR_WTMDPCR1 0x00Bc + +/* 4 WLAN Packet Length Report Control Register */ +#define MCR_WPLRCR 0x00D4 + +/* 4 WLAN Snapshot Register */ +#define MCR_WSR 0x00D8 + +#if defined(MT6631) +/* 4 Abnormal Status Register2 */ +#define MCR_WASR2 0x00E0 +#endif + +/* 4 Clock Pad Macro IO Control Register */ +#define MCR_CLKIOCR 0x0100 + +/* 4 Command Pad Macro IO Control Register */ +#define MCR_CMDIOCR 0x0104 + +/* 4 Data 0 Pad Macro IO Control Register */ +#define MCR_DAT0IOCR 0x0108 + +/* 4 Data 1 Pad Macro IO Control Register */ +#define MCR_DAT1IOCR 0x010C + +/* 4 Data 2 Pad Macro IO Control Register */ +#define MCR_DAT2IOCR 0x0110 + +/* 4 Data 3 Pad Macro IO Control Register */ +#define MCR_DAT3IOCR 0x0114 + +/* 4 Clock Pad Macro Delay Chain Control Register */ +#define MCR_CLKDLYCR 0x0118 + +/* 4 Command Pad Macro Delay Chain Control Register */ +#define MCR_CMDDLYCR 0x011C + +/* 4 SDIO Output Data Delay Chain Control Register */ +#define MCR_ODATDLYCR 0x0120 + +/* 4 SDIO Input Data Delay Chain Control Register 1 */ +#define MCR_IDATDLYCR1 0x0124 + +/* 4 SDIO Input Data Delay Chain Control Register 2 */ +#define MCR_IDATDLYCR2 0x0128 + +/* 4 SDIO Input Data Latch Time Control Register */ +#define MCR_ILCHCR 0x012C + +/* 4 WLAN TXQ Count Register 0 */ +#define MCR_WTQCR0 0x0130 + +/* 4 WLAN TXQ Count Register 1 */ +#define MCR_WTQCR1 0x0134 + +/* 4 WLAN TXQ Count Register 2 */ +#define MCR_WTQCR2 0x0138 + +/* 4 WLAN TXQ Count Register 3 */ +#define MCR_WTQCR3 0x013C + +/* 4 WLAN TXQ Count Register 4 */ +#define MCR_WTQCR4 0x0140 + +/* 4 WLAN TXQ Count Register 5 */ +#define MCR_WTQCR5 0x0144 + +/* 4 WLAN TXQ Count Register 6 */ +#define MCR_WTQCR6 0x0148 + +/* 4 WLAN TXQ Count Register 7 */ +#define MCR_WTQCR7 0x014C + +/* #if CFG_SDIO_INTR_ENHANCE */ +typedef struct _ENHANCE_MODE_DATA_STRUCT_T { + UINT_32 u4WHISR; + union { + struct { + UINT_16 u2TQ0Cnt; + UINT_16 u2TQ1Cnt; + UINT_16 u2TQ2Cnt; + UINT_16 u2TQ3Cnt; + UINT_16 u2TQ4Cnt; + UINT_16 u2TQ5Cnt; + UINT_16 u2TQ6Cnt; + UINT_16 u2TQ7Cnt; + UINT_16 u2TQ8Cnt; + UINT_16 u2TQ9Cnt; + UINT_16 u2TQ10Cnt; + UINT_16 u2TQ11Cnt; + UINT_16 u2TQ12Cnt; + UINT_16 u2TQ13Cnt; + UINT_16 u2TQ14Cnt; + UINT_16 u2TQ15Cnt; + } u; + UINT_32 au4WTSR[8]; + } 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 0x00006630 +#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_DB_CMD7_RESELECT_DIS BIT(4) +#define WSDIOCSR_DB_WR_BUSY_EN BIT(3) +#define WSDIOCSR_DB_RD_BUSY_EN BIT(2) +#define WSDIOCSR_SDIO_INT_CTL BIT(1) +#define WSDIOCSR_SDIO_RE_INIT_EN BIT(0) + +/* 3 WHCR 0x000C */ +#define WHCR_RX_ENHANCE_MODE_EN BIT(16) +#define WHCR_MAX_HIF_RX_LEN_NUM BITS(8, 13) +#define WHCR_RPT_OWN_RX_PACKET_LEN BIT(3) +#define WHCR_RECV_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 8 + +/* 3 WHISR 0x0010 */ +#define WHISR_D2H_SW_INT BITS(8, 31) +#define WHISR_D2H_SW_ASSERT_INFO_INT BIT(31) +#define WHISR_FW_OWN_BACK_INT BIT(7) +#define WHISR_ABNORMAL_INT BIT(6) +#define WHISR_RX1_DONE_INT BIT(2) +#define WHISR_RX0_DONE_INT BIT(1) +#define WHISR_TX_DONE_INT BIT(0) + +/* 3 WHIER 0x0014 */ +#define WHIER_D2H_SW_INT BITS(8, 31) +#define WHIER_FW_OWN_BACK_INT_EN BIT(7) +#define WHIER_ABNORMAL_INT_EN BIT(6) +#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 0x0020 */ +#define WASR_FW_OWN_INVALID_ACCESS BIT(16) +#define WASR_RX1_UNDER_FLOW BIT(9) +#define WASR_RX0_UNDER_FLOW BIT(8) +#define WASR_TX1_OVER_FLOW BIT(1) + +/* 3 WSICR 0x0024 */ +#define WSICR_H2D_SW_INT_SET BITS(16, 31) + +/* 3 WRPLR 0x0090 */ +#define WRPLR_RX1_PACKET_LENGTH BITS(16, 31) +#define WRPLR_RX0_PACKET_LENGTH BITS(0, 15) + +/* 3 WTMCR 0x00b4 */ +#define WMTCR_TEST_MODE_FW_OWN BIT(24) +#define WMTCR_PRBS_INIT_VAL BITS(16, 23) +#define WMTCR_TEST_MODE_STATUS BIT(8) +#define WMTCR_TEST_MODE_SELECT BITS(0, 1) + +#endif /* _MT6628_REG_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/nic.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/nic.h new file mode 100644 index 0000000000000..da963809bf0bf --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/nic.h @@ -0,0 +1,358 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/nic.h#1 +*/ + +/* + * ! \file "nic.h" + * \brief The declaration of nic functions + * + * Detail description. + */ + +#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; + +typedef struct _ECO_INFO_T { + UINT_8 ucHwVer; + UINT_8 ucRomVer; + UINT_8 ucFactoryVer; +} ECO_INFO_T, *P_ECO_INFO_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; + +enum POWER_SAVE_CALLER_T { + PS_CALLER_COMMON = 0, + PS_CALLER_CTIA_MODE, + PS_CALLER_SW_WRITE, + PS_CALLER_CTIA, + PS_CALLER_P2P, + PS_CALLER_CAMCFG, + PS_CALLER_GPU, + PS_CALLER_NO_TIM, + PS_CALLER_MAX_NUM = 24 +}; + +#define PS_SYNC_WITH_FW BIT(31) + +enum ENUM_WMT_CHIPINFO_TYPE_T { + WMTCHIN_CHIPID = 0x0, + WMTCHIN_HWVER = WMTCHIN_CHIPID + 1, + WMTCHIN_MAPPINGHWVER = WMTCHIN_HWVER + 1, + WMTCHIN_FWVER = WMTCHIN_MAPPINGHWVER + 1, + WMTCHIN_IPVER = WMTCHIN_FWVER + 1, + WMTCHIN_MAX, +}; + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +extern UINT_32 mtk_wcn_wmt_ic_info_get(enum ENUM_WMT_CHIPINFO_TYPE_T type); + + +/******************************************************************************* +* P U B 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); + +UINT_16 nicGetChipID(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 + +VOID nicpmCheckAndTriggerDriverOwn(IN P_ADAPTER_T prAdapter); + +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 ucWlanIndex, IN UINT_8 ucSeqNum); + +P_MSDU_INFO_T nicGetPendingStaMMPDU(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIdx); + +VOID nicFreePendingTxMsduInfoByBssIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex); + +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 UINT_8 ucBssIndex, IN P_EVENT_CONNECTION_STATUS prConnectionStatus); + +WLAN_STATUS nicMediaJoinFailure(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN WLAN_STATUS rStatus); + +/* Utility function for channel number conversion */ +UINT_32 nicChannelNum2Freq(IN UINT_32 u4ChannelNum); + +UINT_32 nicFreq2ChannelNum(IN UINT_32 u4FreqInKHz); + +UINT_8 nicGetVhtS1(IN UINT_8 ucPrimaryChannel); + +/* firmware command wrapper */ + /* NETWORK (WIFISYS) */ +WLAN_STATUS nicActivateNetwork(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex); + +WLAN_STATUS nicDeactivateNetwork(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex); + + /* BSS-INFO */ +WLAN_STATUS nicUpdateBss(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex); + + /* BSS-INFO Indication (PM) */ +WLAN_STATUS nicPmIndicateBssCreated(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex); + +WLAN_STATUS nicPmIndicateBssConnected(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex); + +WLAN_STATUS nicPmIndicateBssAbort(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex); + + /* Beacon Template Update */ +WLAN_STATUS +nicUpdateBeaconIETemplate(IN P_ADAPTER_T prAdapter, + IN ENUM_IE_UPD_METHOD_T eIeUpdMethod, + IN UINT_8 ucBssIndex, IN UINT_16 u2Capability, IN PUINT_8 aucIe, IN UINT_16 u2IELen); + +WLAN_STATUS nicQmUpdateWmmParms(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex); + +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, UINT_8 ucBssIndex, PARAM_POWER_MODE ePwrMode, + BOOLEAN fgEnCmdEvent); + +VOID nicPowerSaveInfoMap(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN IN PARAM_POWER_MODE ePowerMode, + IN enum POWER_SAVE_CALLER_T ucCaller); + +WLAN_STATUS nicEnterCtiaMode(IN P_ADAPTER_T prAdapter, BOOLEAN fgEnterCtia, BOOLEAN fgEnCmdEvent); + +WLAN_STATUS nicEnterCtiaModeOfScan(IN P_ADAPTER_T prAdapter, BOOLEAN fgEnterCtia, BOOLEAN fgEnCmdEvent); +WLAN_STATUS nicEnterCtiaModeOfRoaming(IN P_ADAPTER_T prAdapter, BOOLEAN fgEnterCtia, BOOLEAN fgEnCmdEvent); +WLAN_STATUS nicEnterCtiaModeOfCAM(IN P_ADAPTER_T prAdapter, BOOLEAN fgEnterCtia, BOOLEAN fgEnCmdEvent); +WLAN_STATUS nicEnterCtiaModeOfBCNTimeout(IN P_ADAPTER_T prAdapter, BOOLEAN fgEnterCtia, BOOLEAN fgEnCmdEvent); +WLAN_STATUS nicEnterCtiaModeOfAutoTxPower(IN P_ADAPTER_T prAdapter, BOOLEAN fgEnterCtia, BOOLEAN fgEnCmdEvent); +WLAN_STATUS nicEnterCtiaModeOfFIFOFullNoAck(IN P_ADAPTER_T prAdapter, BOOLEAN fgEnterCtia, BOOLEAN fgEnCmdEvent); + +/*----------------------------------------------------------------------------*/ +/* Scan Result Processing */ +/*----------------------------------------------------------------------------*/ +UINT_32 +nicAddScanResult(IN P_ADAPTER_T prAdapter, + IN PARAM_MAC_ADDRESS rMacAddr, + IN P_PARAM_SSID_T prSsid, + IN UINT_16 u2CapInfo, + 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); + +/*----------------------------------------------------------------------------*/ +/* 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 UINT_8 ucBssIndex, IN P_EVENT_LINK_QUALITY_V2 prEventLinkQuality); + +VOID nicUpdateRSSI(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN INT_8 cRssi, IN INT_8 cLinkQuality); + +VOID nicUpdateLinkSpeed(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, 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 + +/*----------------------------------------------------------------------------*/ +/* Address Setting Apply */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicApplyNetworkAddress(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* ECO Version */ +/*----------------------------------------------------------------------------*/ +UINT_8 nicGetChipEcoVer(VOID); +BOOLEAN nicIsEcoVerEqualTo(UINT_8 ucEcoVer); +BOOLEAN nicIsEcoVerEqualOrLaterTo(UINT_8 ucEcoVer); + +/*----------------------------------------------------------------------------*/ +/* uApsd setting */ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS nicSetUapsdParam(IN P_ADAPTER_T prAdapter, + IN P_PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T prUapsdParams, + IN ENUM_NETWORK_TYPE_T eNetworkTypeIdx); + +#endif /* _NIC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/nic_rate.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/nic_rate.h new file mode 100644 index 0000000000000..528d929dc9f52 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/nic_rate.h @@ -0,0 +1,122 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/nic_rate.h#1 +*/ + +/* + * ! \file nic_rate.h + * \brief This file contains the rate utility function of + * IEEE 802.11 family for MediaTek 802.11 Wireless LAN Adapters. + */ + +#ifndef _NIC_RATE_H +#define _NIC_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 +******************************************************************************** +*/ + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +UINT_32 +nicGetPhyRateByMcsRate( + IN UINT_8 ucIdx, + IN UINT_8 ucBw, + IN UINT_8 ucGI + ); + +UINT_32 +nicGetHwRateByPhyRate( + IN UINT_8 ucIdx + ); + +WLAN_STATUS +nicSwIndex2RateIndex( + IN UINT_8 ucRateSwIndex, + OUT PUINT_8 pucRateIndex, + OUT PUINT_8 pucPreambleOption + ); + +WLAN_STATUS +nicRateIndex2RateCode( + IN UINT_8 ucPreambleOption, + IN UINT_8 ucRateIndex, + OUT PUINT_16 pu2RateCode + ); + +UINT_32 +nicRateCode2PhyRate( + IN UINT_16 u2RateCode, + IN UINT_8 ucBandwidth, + IN UINT_8 ucGI, + IN UINT_8 ucRateNss + ); + +UINT_32 +nicRateCode2DataRate( + IN UINT_16 u2RateCode, + IN UINT_8 ucBandwidth, + IN UINT_8 ucGI + ); + +BOOLEAN +nicGetRateIndexFromRateSetWithLimit( + IN UINT_16 u2RateSet, + IN UINT_32 u4PhyRateLimit, + IN BOOLEAN fgGetLowest, + OUT PUINT_8 pucRateSwIndex + ); + +#endif /* _NIC_RATE_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/nic_rx.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/nic_rx.h new file mode 100644 index 0000000000000..b1a2f2df5a916 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/nic_rx.h @@ -0,0 +1,900 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/nic_rx.h#1 + */ + +/* + * ! \file "nic_rx.h" + * \brief The declaration of the nic rx functions + */ + +#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 + +#define RX_RETURN_INDICATED_RFB_TIMEOUT_SEC 3 + +#if defined(_HIF_SDIO) && defined(WINDOWS_DDK) +/*! On XP, maximum Tx+Rx Statue <= 64-4(HISR)*/ +#define SDIO_MAXIMUM_RX_LEN_NUM 0 /*!< 0~15 (0: un-limited) */ +#else +#define SDIO_MAXIMUM_RX_LEN_NUM 0 /*!< 0~15 (0: un-limited) */ +#endif + +/* RXM Definitions */ +/* The payload format of a RX packet */ +#define RX_PAYLOAD_FORMAT_MSDU 0 +#define RX_PAYLOAD_FORMAT_FIRST_SUB_AMSDU 3 +#define RX_PAYLOAD_FORMAT_MIDDLE_SUB_AMSDU 2 +#define RX_PAYLOAD_FORMAT_LAST_SUB_AMSDU 1 + +/* HAL RX from hal_hw_def_rom.h */ +/*------------------------------------------------------------------------------ + * Cipher define + *------------------------------------------------------------------------------ +*/ +#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 CIPHER_SUITE_CCMP_W_CCX 9 +#define CIPHER_SUITE_GCMP 10 + +/*------------------------------------------------------------------------------ + * Bit fields for HW_MAC_RX_DESC_T + *------------------------------------------------------------------------------ +*/ + +/*! MAC RX DMA Descriptor */ +/* DW 0*/ +/* Word 0 */ +#define RX_STATUS_RX_BYTE_COUNT_MASK BITS(0, 16) +/* Word 1 */ +#define RX_STATUS_ETH_TYPE_OFFSET_MASK BITS(0, 6) +#define RX_STATUS_ETH_TYPE_OFFSET 0 +#define RX_STATUS_IP_CHKSUM BIT(7) +#define RX_STATUS_UDP_TCP_CHKSUM BIT(8) +#define RX_STATUS_GROUP_VLD_MASK BITS(9, 12) +#define RX_STATUS_GROUP_VLD_OFFSET 9 +#define RX_STATUS_PKT_TYPE_MASK BITS(13, 15) +#define RX_STATUS_PKT_TYPE_OFFSET 13 + +/* DW 1 */ +/* Byte 0 */ +#define RX_STATUS_HTC BIT(0) +#define RX_STATUS_UC2ME BIT(1) +#define RX_STATUS_MC_FRAME BIT(2) +#define RX_STATUS_BC_FRAME BIT(3) +#define RX_STATUS_BCN_WITH_BMC BIT(4) +#define RX_STATUS_BCN_WITH_UC BIT(5) +#define RX_STATUS_KEYID_MASK BITS(6, 7) +#define RX_STATUS_KEYID_OFFSET 6 + +/* Byte 1 */ +#define RX_STATUS_CHAN_FREQ_MASK BITS(0, 7) +/* Byte 2 */ +#define RX_STATUS_HEADER_LEN_MASK BITS(0, 5) +#define RX_STATUS_HEADER_OFFSET BIT(6) +#define RX_STATUS_HEADER_TRAN BIT(7) +/* Byte 3 */ +#define RX_STATUS_PAYLOAD_FORMAT_MASK BITS(0, 1) +#define RX_STATUS_PAYLOAD_FORMAT_OFFSET 0 +#define RX_STATUS_BSSID_MASK BITS(2, 7) +#define RX_STATUS_BSSID_OFFSET 2 + +/* DW 2 */ +/* Byte 1 */ +#define RX_STATUS_TID_MASK BITS(0, 3) +#define RX_STATUS_SEC_MASK BITS(4, 7) +#define RX_STATUS_SEC_OFFSET 4 +/* Byte 2-3 */ +#define RX_STATUS_SW_BIT BIT(0) +#define RX_STATUS_FLAG_FCS_ERROR BIT(1) +#define RX_STATUS_FLAG_CIPHER_MISMATCH BIT(2) +#define RX_STATUS_FLAG_CIPHER_LENGTH_MISMATCH BIT(3) +#define RX_STATUS_FLAG_ICV_ERROR BIT(4) +#define RX_STATUS_FLAG_TKIPMIC_ERROR BIT(5) +#define RX_STATUS_FLAG_LEN_MISMATCH BIT(6) +#define RX_STATUS_FLAG_DE_AMSDU_FAIL BIT(7) +#define RX_STATUS_FLAG_EXCEED_LEN BIT(8) +#define RX_STATUS_LLC_MIS BIT(9) +#define RX_STATUS_UDF_VLT BIT(10) +#define RX_STATUS_FRAG BIT(11) +#define RX_STATUS_NULL BIT(12) +#define RX_STATUS_DATA BIT(13) +#define RX_STATUS_AMPDU_SUB_FRAME BIT(14) +#define RX_STATUS_AMPDU_FORMAT BIT(15) +#define PAYLOAD_FORMAT_IS_MSDU_FRAME 0 +#define RX_STATUS_FLAG_ERROR_MASK (RX_STATUS_FLAG_FCS_ERROR | RX_STATUS_FLAG_ICV_ERROR | \ + RX_STATUS_FLAG_CIPHER_LENGTH_MISMATCH) /* No TKIP MIC error */ + +/* DW 3 */ +#define RX_STATUS_RXV_SEQ_NO_MASK BITS(0, 7) +#define RX_STATUS_TCL BIT(8) +#define RX_STATUS_CLS BIT(11) +#define RX_STATUS_OFLD_MASK BITS(12, 13) +#define RX_STATUS_OFLD_OFFSET 12 +#define RX_STATUS_EAPOL_PACKET BIT(12) +#define RX_STATUS_ARP_NS_PACKET BIT(13) +#define RX_STATUS_TDLS_PACKET BITS(12, 13) +#define RX_STATUS_MGC BIT(14) +#define RX_STATUS_WOL_MASK BITS(15, 19) +#define RX_STATUS_WOL_OFFSET 15 +#define RX_STATUS_CLS_BITMAP_MASK BITS(20, 29) +#define RX_STATUS_CLS_BITMAP_OFFSET 20 +#define RX_STATUS_PF_MODE_BLACK_LIST BIT(30) +#define RX_STATUS_PF_STS_CHECKED BIT(31) + +/* DW 12 */ +#define RX_STATUS_FRAG_NUM_MASK BITS(0, 3) +#define RX_STATUS_SEQ_NUM_MASK BITS(4, 15) +#define RX_STATUS_SEQ_NUM_OFFSET 4 + +#define RX_STATUS_GROUP1_VALID BIT(0) +#define RX_STATUS_GROUP2_VALID BIT(1) +#define RX_STATUS_GROUP3_VALID BIT(2) +#define RX_STATUS_GROUP4_VALID BIT(3) + +#define RX_STATUS_FIXED_LEN 16 + +#define RX_STATUS_CHAN_FREQ_MASK_FOR_BY_PASS_MPDE BITS(0, 7) +#define RX_STATUS_FLAG_FCS_ERROR_FOR_BY_PASS_MODE BIT(16) + +/* Timing Measurement Report */ +/* DW0 Word 1 */ +#define RX_TMR_TOA_VALID BIT(11) +#define RX_TMR_TOD_VALID BIT(10) +#define RX_TMR_TYPE_MASK BITS(8, 9) +#define RX_TMR_TYPE_OFFSET 8 +#define RX_TMR_SUBTYPE_MASK BITS(4, 7) +#define RX_TMR_SUBTYPE_OFFSET 4 + +/* DW0 Byte 1*/ +#define RX_TMR_TM_FAILED BIT(2) +#define RX_TMR_NOISY_CHAN BIT(1) +#define RX_TMR_RESPONDER BIT(0) + +/* TBD */ +#define DMA_OWN_TO_HW BIT(0) +#define DMA_OWN_TO_FW_PENDING BIT(1) +#define STATUS_IS_OWN_TO_FW(flag) (((flag) & DMA_OWN_TO_HW) ? FALSE : TRUE) +#define STATUS_IS_FW_PENDING(flag) (((flag) & DMA_OWN_TO_FW_PENDING) ? TRUE : FALSE) + +/* DW 2 */ +#define RX_STATUS_PACKET_LENGTH_MASK BITS(0, 16) + +#define RX_STATUS_HEADER_TRAN_MASK BIT(7) +#define RX_STATUS_HEADER_TRAN_OFFSET 7 +#define RX_STATUS_HEADER_TRAN_BSS0_MASK BIT(6) +#define RX_STATUS_HEADER_TRAN_BSS0_OFFSET 6 +#define RX_STATUS_HEADER_TRAN_BSS1_MASK BIT(7) +#define RX_STATUS_HEADER_TRAN_BSS1_OFFSET 7 + +/* DW 4 */ +#define RX_STATUS_MATCH_PACKET BIT(4) + +#define RX_STATUS_HEADER_OFFSET_MASK 0xC0 +#define RX_STATUS_HEADER_OFFSET_OFFSET 6 + +/*------------------------------------------------------------------------------ + * Bit fields for HW_RX_VECTOR_DESC_T + *------------------------------------------------------------------------------ +*/ +/* DW 2 */ +#define RX_VECTOR_FOR_BA_ACK BIT(7) + +/*! HIF RX DMA Descriptor */ +/* DW 2 */ +#define HIF_RX_DESC_BUFFER_LEN BITS(0, 15) +#define HIF_RX_DESC_ETHER_TYPE_OFFSET_MASK BITS(16, 23) +#define HIF_RX_DESC_ETHER_TYPE_OFFSET_OFFSET 16 +#define HIF_RX_DESC_IP_CHKSUM_CHECK BIT(24) +#define HIF_RX_DESC_TCP_UDP_CHKSUM_CHECK BIT(25) + +#define HIF_RX_DATA_QUEUE 0 +#define HIF_RX_EVENT_QUEUE 1 + +/*------------------------------------------------------------------------------ + * Bit fields for PHY Vector + *------------------------------------------------------------------------------ +*/ + +/* RX Vector, 1st Cycle */ +#define RX_VT_RX_RATE_AC_MASK BITS(0, 3) +#define RX_VT_RX_RATE_MASK BITS(0, 6) +#define RX_VT_RX_RATE_OFFSET 0 +#define RX_VT_STBC_MASK BITS(7, 8) +#define RX_VT_STBC_OFFSET 7 +#define RX_VT_LDPC BIT(9) +#define RX_VT_NESS_MASK BITS(10, 11) +#define RX_VT_NESS_OFFSET 10 +#define RX_VT_RX_MODE_MASK BITS(12, 14) +#define RX_VT_RX_MODE_OFFSET 12 +#define RX_VT_RX_MODE_VHT BIT(14) +#define RX_VT_FR_MODE_MASK BITS(15, 16) +#define RX_VT_FR_MODE_OFFSET 15 +#define RX_VT_TXOP_PS_NOT_ALLOWED BIT(17) +#define RX_VT_AGGREGATION BIT(18) +#define RX_VT_SHORT_GI BIT(19) +#define RX_VT_SMOOTH BIT(20) +#define RX_VT_NO_SOUNDING BIT(21) +#define RX_VT_SOUNDING BIT(21) +#define RX_VT_SHORT_GI_NSYM BIT(22) +#define RX_VT_CODING_MASK BITS(23, 24) +#define RX_VT_CODING_OFFSET 23 +#define RX_VT_BEAMFORMED BIT(29) +#define RX_VT_GROUPID_0_MASK BITS(30, 31) +#define RX_VT_GROUPID_0_OFFSET 30 + +#define RX_VT_RX_RATE_1M 0x0 +#define RX_VT_RX_RATE_2M 0x1 +#define RX_VT_RX_RATE_5M 0x2 +#define RX_VT_RX_RATE_11M 0x3 +#define RX_VT_RX_RATE_6M 0xB +#define RX_VT_RX_RATE_9M 0xF +#define RX_VT_RX_RATE_12M 0xA +#define RX_VT_RX_RATE_18M 0xE +#define RX_VT_RX_RATE_24M 0x9 +#define RX_VT_RX_RATE_36M 0xD +#define RX_VT_RX_RATE_48M 0x8 +#define RX_VT_RX_RATE_54M 0xC + +#define RX_VT_RX_RATE_MCS0 0 +#define RX_VT_RX_RATE_MCS1 1 +#define RX_VT_RX_RATE_MCS2 2 +#define RX_VT_RX_RATE_MCS3 3 +#define RX_VT_RX_RATE_MCS4 4 +#define RX_VT_RX_RATE_MCS5 5 +#define RX_VT_RX_RATE_MCS6 6 +#define RX_VT_RX_RATE_MCS7 7 +#define RX_VT_RX_RATE_MCS32 32 + +#define RX_VT_LEGACY_CCK 0 +#define RX_VT_LEGACY_OFDM 1 +#define RX_VT_MIXED_MODE 2 +#define RX_VT_GREEN_MODE 3 +#define RX_VT_VHT_MODE 4 + +#define RX_VT_LG20_HT20 0 +#define RX_VT_DL40_HT40 1 +#define RX_VT_U20 2 +#define RX_VT_L20 3 + +#define RX_VT_FR_MODE_20 0 +#define RX_VT_FR_MODE_40 1 +#define RX_VT_FR_MODE_80 2 +#define RX_VT_FR_MODE_160 3 + +#define RX_VT_CCK_SHORT_PREAMBLE BIT(2) + +/* RX Vector, 2nd Cycle */ +#define RX_VT_RX_LEN_HT_MASK BITS(0, 15) +#define RX_VT_RX_LEN_LEACY_MASK BITS(0, 11) +#define RX_VT_RX_LEN_VHT_MASK BITS(0, 20) +#define RX_VT_GROUPID_1_MASK BITS(21, 24) +#define RX_VT_GROUPID_1_OFFSET 21 +#define RX_VT_NSTS_MASK BITS(25, 27) +#define RX_VT_NSTS_OFFSET 25 +#define RX_VT_AID_0_MASK BITS(28, 31) +#define RX_VT_AID_0_OFFSET 28 +#define RX_VT_GROUP_ID_MASK BITS(21, 26) +#define RX_VT_GROUP_ID_OFFSET 21 + + +/* RX Vector, 3rd Cycle */ +#define RX_VT_AID_1_MASK BITS(0, 4) +#define RX_VT_AID_1_OFFSET 0 +#define RX_VT_SEL_ANT BIT(7) +#define RX_VT_RCPI_MASK BITS(8, 15) +#define RX_VT_RCPI_OFFSET 8 +#define RX_VT_OFDM_FREQ_TRANS_DET BIT(5) +#define RX_VT_FAGC0_EQ_CAL BIT(16) + +/* RX Vector, 4th Cycle */ +#define RX_VT_IB_RSSI_MASK BITS(0, 7) +#define RX_VT_WB_RSSI_MASK BITS(8, 15) +#define RX_VT_WB_RSSI_OFFSET 8 + +/* RX Vector, 6th Cycle */ +#define RX_VT_NF0_MASK BITS(0, 7) +#define RX_VT_NF0_OFFSET 0 + +/* RX Vector Group 2, the 1st cycle */ +#define RX_VT_CCK_LQ BITS(4, 10) +#define RX_VT_OFDM_LQ_BPSK BITS(4, 9) +#define RX_VT_LQ_OFFSET 4 +#define RX_VT_PRIM_ITFR_ENV BIT(0) +#define RX_VT_SEC_ITFR_ENV BIT(1) +#define RX_VT_SEC40_ITFR_ENV BIT(2) + +/* RX Vector Group 2, the 2nd cycle */ +#define RX_VT_DYNA_BW_IN_NON_HT_DYNA BIT(29) +#define RX_VT_CH_BW_IN_NON_HT_CBW40 BIT(30) +#define RX_VT_CH_BW_IN_NON_HT_CBW80 BIT(31) +#define RX_VT_CH_BW_IN_NON_HT_CBW160 BITS(30, 31) + +/* RX Data Type */ +#define RX_DATA_TYPE_RX_VECTOR 0 +#define RX_DATA_TYPE_RX_DATA 1 +#define RX_DATA_TYPE_RX_EVM 2 +#define RX_DATA_TYPE_RX_AMBI 3 +#define RX_DATA_TYPE_RX_BT 4 + +/******************************************************************************* +* 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, +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + RX_DUPICATE_DROP_COUNT,/* for get link quality feature*/ +#endif +#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; + +/* Used for MAC RX */ +typedef enum _ENUM_MAC_RX_PKT_TYPE_T { + RX_PKT_TYPE_TX_STATUS = 0, + RX_PKT_TYPE_RX_VECTOR, + RX_PKT_TYPE_RX_DATA, + RX_PKT_TYPE_DUP_RFB, + RX_PKT_TYPE_TM_REPORT, + RX_PKT_TYPE_SW_DEFINED = 7 +} ENUM_MAC_RX_PKT_TYPE_T; + +typedef enum _ENUM_MAC_RX_GROUP_VLD_T { + RX_GROUP_VLD_1 = 0, + RX_GROUP_VLD_2, + RX_GROUP_VLD_3, + RX_GROUP_VLD_4, + RX_GROUP_VLD_NUM +} ENUM_MAC_RX_GROUP_VLD_T; + +typedef enum _ENUM_MAC_GI_INFO_T { + MAC_GI_NORMAL = 0, + MAC_GI_SHORT +} ENUM_MAC_GI_INFO_T, *P_ENUM_MAC_GI_INFO_T; + +#define RXM_RXD_PKT_TYPE_SW_BITMAP 0xE00F +#define RXM_RXD_PKT_TYPE_SW_EVENT 0xE000 +#define RXM_RXD_PKT_TYPE_SW_FRAME 0xE001 + +/* AMPDU data frame with no errors including FC/FM/I/T/LM/DAF/EL/LLC-MIS/ UDFVLT and Class 3 error */ +#define RXS_DW2_AMPDU_nERR_BITMAP 0xFFBF +#define RXS_DW2_AMPDU_nERR_VALUE 0x0000 +/* no error including FC/FM/I/T/LM/DAF/EL/LLC-MIS/ UDFVLT */ +#define RXS_DW2_RX_nERR_BITMAP 0x07F8 +#define RXS_DW2_RX_nERR_VALUE 0x0000 +/* Non-Data frames */ +#define RXS_DW2_RX_nDATA_BITMAP 0x3000 +#define RXS_DW2_RX_nDATA_VALUE 0x2000 +/* Claas Error */ +#define RXS_DW2_RX_CLASSERR_BITMAP 0x0001 +#define RXS_DW2_RX_CLASSERR_VALUE 0x0001 +/* Fragmentation */ +#define RXS_DW2_RX_FRAG_BITMAP 0x3800 +#define RXS_DW2_RX_FRAG_VALUE 0x0800 + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/*! A data structure which is identical with MAC RX DMA Descriptor */ +typedef struct _HW_MAC_RX_DESC_T { + UINT_16 u2RxByteCount; /* DW 0 */ + UINT_16 u2PktTYpe; + UINT_8 ucMatchPacket; /* DW 1 */ + UINT_8 ucChanFreq; + UINT_8 ucHeaderLen; + UINT_8 ucBssid; + UINT_8 ucWlanIdx; /* DW 2 */ + UINT_8 ucTidSecMode; + UINT_16 u2StatusFlag; + UINT_32 u4PatternFilterInfo; /* DW 3 */ +} HW_MAC_RX_DESC_T, *P_HW_MAC_RX_DESC_T; + +typedef struct _HW_MAC_RX_STS_GROUP_1_T { + UINT_8 aucPN[16]; +} HW_MAC_RX_STS_GROUP_1_T, *P_HW_MAC_RX_STS_GROUP_1_T; + +typedef struct _HW_MAC_RX_STS_GROUP_2_T { + UINT_32 u4Timestamp; /* DW 12 */ + UINT_32 u4CRC; /* DW 13 */ +} HW_MAC_RX_STS_GROUP_2_T, *P_HW_MAC_RX_STS_GROUP_2_T; + +typedef struct _HW_MAC_RX_STS_GROUP_4_T { + /* For HDR_TRAN */ + UINT_16 u2FrameCtl; /* DW 4 */ + UINT_8 aucTA[6]; /* DW 4~5 */ + UINT_16 u2SeqFrag; /* DW 6 */ + UINT_16 u2Qos; /* DW 6 */ + UINT_32 u4HTC; /* DW 7 */ +} HW_MAC_RX_STS_GROUP_4_T, *P_HW_MAC_RX_STS_GROUP_4_T; + +typedef struct _HW_MAC_RX_STS_GROUP_3_T { + /*! RX Vector Info */ + UINT_32 u4RxVector[6]; /* DW 14~19 */ +} HW_MAC_RX_STS_GROUP_3_T, *P_HW_MAC_RX_STS_GROUP_3_T; + +typedef struct _HW_MAC_RX_TMRI_PKT_FORMAT_T { + UINT_8 ucPID; + UINT_8 ucStatus; + UINT_16 u2PktTYpe; + UINT_32 u4Reserved[2]; + UINT_32 u4ToA; + UINT_32 u4ToD; +} HW_MAC_RX_TMRI_PKT_FORMAT_T, *P_HW_MAC_RX_TMRI_PKT_FORMAT_T; + +typedef struct _HW_MAC_RX_TMRR_PKT_FORMAT_T { + UINT_8 ucVtSeq; + UINT_8 ucStatus; + UINT_16 u2PktTYpe; + UINT_8 aucTALow[2]; + UINT_16 u2SnField; + UINT_8 aucTAHigh[4]; + UINT_32 u4ToA; + UINT_32 u4ToD; +} HW_MAC_RX_TMRR_PKT_FORMAT_T, *P_HW_MAC_RX_TMRR_PKT_FORMAT_T; + +/*! A data structure which is identical with MAC RX Vector DMA Descriptor */ +typedef struct _HW_RX_VECTOR_DESC_T { + UINT_8 aucTA[6]; /* DW 0~1 */ + UINT_8 ucRxVtSeqNo; + /*! RX Vector Info */ + UINT_32 u4RxVector[9]; /* DW 2~10 */ + +} HW_RX_VECTOR_DESC_T, *P_HW_RX_VECTOR_DESC_T; + +struct _SW_RFB_T { + QUE_ENTRY_T rQueEntry; + PVOID pvPacket; /*!< ptr to rx Packet Descriptor */ + PUINT_8 pucRecvBuff; /*!< ptr to receive data buffer */ + + /* add fot mt6630 */ + UINT_8 ucGroupVLD; + UINT_16 u2RxStatusOffst; + P_HW_MAC_RX_DESC_T prRxStatus; + P_HW_MAC_RX_STS_GROUP_1_T prRxStatusGroup1; + P_HW_MAC_RX_STS_GROUP_2_T prRxStatusGroup2; + P_HW_MAC_RX_STS_GROUP_3_T prRxStatusGroup3; + P_HW_MAC_RX_STS_GROUP_4_T prRxStatusGroup4; + + /* rx data information */ + PVOID pvHeader; + UINT_16 u2PacketLen; + UINT_16 u2HeaderLen; + + PUINT_8 pucPayload; + UINT_16 u2PayloadLength; + + P_STA_RECORD_T prStaRec; + + UINT_8 ucPacketType; + + /* rx sta record */ + UINT_8 ucWlanIdx; + UINT_8 ucStaRecIdx; + + BOOLEAN fgReorderBuffer; + BOOLEAN fgDataFrame; + BOOLEAN fgFragFrame; + /* duplicate detection */ + UINT_16 u2FrameCtrl; + UINT_16 u2SequenceControl; + UINT_16 u2SSN; + UINT_8 ucTid; + + ENUM_CSUM_RESULT_T aeCSUM[CSUM_TYPE_NUM]; + ENUM_RX_PKT_DESTINATION_T eDst; + ENUM_TRAFFIC_CLASS_INDEX_T eTC; /* only valid when eDst == FORWARD */ + UINT_64 rIntTime; +}; + +/*! 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 + +#if CFG_SUPPORT_SNIFFER + UINT_32 u4AmpduRefNum; +#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); + +typedef struct _EMU_MAC_RATE_INFO_T { + UINT_8 ucPhyRateCode; + UINT_32 u4PhyRate[4][2]; +} EMU_MAC_RATE_INFO_T, *P_EMU_MAC_RATE_INFO_T; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define RATE_INFO(_RateCode, _Bw20, _Bw20SGI, _Bw40, _BW40SGI, _Bw80, _Bw80SGI, _Bw160, _Bw160SGI) \ + { \ + .ucPhyRateCode = (_RateCode), \ + .u4PhyRate[RX_VT_FR_MODE_20][MAC_GI_NORMAL] = (_Bw20), \ + .u4PhyRate[RX_VT_FR_MODE_20][MAC_GI_SHORT] = (_Bw20SGI), \ + .u4PhyRate[RX_VT_FR_MODE_40][MAC_GI_NORMAL] = (_Bw40), \ + .u4PhyRate[RX_VT_FR_MODE_40][MAC_GI_SHORT] = (_BW40SGI), \ + .u4PhyRate[RX_VT_FR_MODE_80][MAC_GI_NORMAL] = (_Bw80), \ + .u4PhyRate[RX_VT_FR_MODE_80][MAC_GI_SHORT] = (_Bw80SGI), \ + .u4PhyRate[RX_VT_FR_MODE_160][MAC_GI_NORMAL] = (_Bw160), \ + .u4PhyRate[RX_VT_FR_MODE_160][MAC_GI_SHORT] = (_Bw160SGI), \ + } + +#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)) + +/*------------------------------------------------------------------------------ + * MACRO for HW_MAC_RX_DESC_T + *------------------------------------------------------------------------------ +*/ +/* DW 0 */ +#define HAL_RX_STATUS_GET_RX_BYTE_CNT(_prHwMacRxDesc) ((_prHwMacRxDesc)->u2RxByteCount) +#define HAL_RX_STATUS_GET_ETH_TYPE_OFFSET(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2PktTYpe & RX_STATUS_ETH_TYPE_OFFSET_MASK) >> RX_STATUS_ETH_TYPE_OFFSET) +#define HAL_RX_STATUS_GET_GROUP_VLD(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2PktTYpe & RX_STATUS_GROUP_VLD_MASK) >> RX_STATUS_GROUP_VLD_OFFSET) +#define HAL_RX_STATUS_GET_PKT_TYPE(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2PktTYpe & RX_STATUS_PKT_TYPE_MASK) >> RX_STATUS_PKT_TYPE_OFFSET) + +/* DW 1 */ +#define HAL_RX_STATUS_IS_HTC_EXIST(_prHwMacRxDesc) (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_HTC)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_UC2ME(_prHwMacRxDesc) (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_UC2ME)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_MC(_prHwMacRxDesc) (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_MC_FRAME)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_BC(_prHwMacRxDesc) (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_BC_FRAME)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_BCN_WITH_BMC(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_BCN_WITH_BMC)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_BCN_WITH_UC(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_BCN_WITH_UC)?TRUE:FALSE) +#define HAL_RX_STATUS_GET_KEY_ID(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_KEYID_MASK) >> RX_STATUS_KEYID_OFFSET) +#define HAL_RX_STATUS_GET_CHAN_FREQ(_prHwMacRxDesc) \ + ((_prHwMacRxDesc)->ucChanFreq) +#define HAL_RX_STATUS_GET_HEADER_LEN(_prHwMacRxDesc) ((_prHwMacRxDesc)->ucHeaderLen & RX_STATUS_HEADER_LEN_MASK) +#define HAL_RX_STATUS_IS_HEADER_OFFSET(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucHeaderLen & RX_STATUS_HEADER_OFFSET)?TRUE:FALSE) +#define HAL_RX_STATUS_GET_HEADER_OFFSET(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucHeaderLen & RX_STATUS_HEADER_OFFSET) ? 2 : 0) +#define HAL_RX_STATUS_IS_HEADER_TRAN(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucHeaderLen & RX_STATUS_HEADER_TRAN)?TRUE:FALSE) +#define HAL_RX_STATUS_GET_HEADER_TRAN(_prHwMacRxDesc) HAL_RX_STATUS_IS_HEADER_TRAN(_prHwMacRxDesc) +#define HAL_RX_STATUS_GET_PAYLOAD_FORMAT(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucBssid & RX_STATUS_PAYLOAD_FORMAT_MASK) >> RX_STATUS_PAYLOAD_FORMAT_OFFSET) +#define HAL_RX_STATUS_GET_BSSID(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucBssid & RX_STATUS_BSSID_MASK) >> RX_STATUS_BSSID_OFFSET) + +/* DW 2 */ +#define HAL_RX_STATUS_GET_WLAN_IDX(_prHwMacRxDesc) ((_prHwMacRxDesc)->ucWlanIdx) +#define HAL_RX_STATUS_GET_TID(_prHwMacRxDesc) (((_prHwMacRxDesc)->ucTidSecMode & RX_STATUS_TID_MASK)) +#define HAL_RX_STATUS_GET_SEC_MODE(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucTidSecMode & RX_STATUS_SEC_MASK) >> RX_STATUS_SEC_OFFSET) +#define HAL_RX_STATUS_GET_SW_BIT(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_SW_BIT)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_FCS_ERROR(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_FCS_ERROR)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_CIPHER_MISMATCH(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_CIPHER_MISMATCH)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_CLM_ERROR(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_CIPHER_LENGTH_MISMATCH)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_ICV_ERROR(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_ICV_ERROR)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_TKIP_MIC_ERROR(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_TKIPMIC_ERROR) > 0?TRUE:FALSE) +#define HAL_RX_STATUS_IS_ERROR(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_ERROR_MASK)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_LEN_MISMATCH(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_LEN_MISMATCH)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_DE_AMSDU_FAIL(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_DE_AMSDU_FAIL)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_EXCEED_LEN(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_EXCEED_LEN)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_LLC_MIS(_prHwMacRxDesc) (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_LLC_MIS)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_UDF_VLT(_prHwMacRxDesc) (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_UDF_VLT)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_FRAG(_prHwMacRxDesc) (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FRAG)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_NULL(_prHwMacRxDesc) (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_NULL)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_DATA(_prHwMacRxDesc) (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_DATA)?FALSE:TRUE) +#define HAL_RX_STATUS_IS_AMPDU_SUB_FRAME(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_AMPDU_SUB_FRAME)?FALSE:TRUE) +#define HAL_RX_STATUS_IS_AMPDU_FORMAT(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_AMPDU_FORMAT)?FALSE:TRUE) + +/* DW 3 */ +#define HAL_RX_STATUS_IS_RV_VALID(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_RXV_SEQ_NO_MASK)?TRUE:FALSE) +#define HAL_RX_STATUS_GET_RXV_SEQ_NO(_prHwMacRxDesc) \ + ((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_RXV_SEQ_NO_MASK) +#define HAL_RX_STATUS_GET_TCL(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_TCL)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_CLS(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_CLS)?TRUE:FALSE) +#define HAL_RX_STATUS_GET_OFLD(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_OFLD_MASK) >> RX_STATUS_OFLD_OFFSET) +#define HAL_RX_STATUS_IS_MGC(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_MGC)?TRUE:FALSE) +#define HAL_RX_STATUS_GET_WOL(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_WOL_MASK) >> RX_STATUS_WOL_OFFSET) +#define HAL_RX_STATUS_GET_CLS_BITMAP(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_CLS_BITMAP_MASK) >> RX_STATUS_CLS_BITMAP_OFFSET) +#define HAL_RX_STATUS_IS_PF_BLACK_LIST(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_PF_MODE_BLACK_LIST)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_PF_CHECKED(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_PF_STS_CHECKED)?TRUE:FALSE) + +/* DW 4~7 */ +#define HAL_RX_STATUS_GET_FRAME_CTL_FIELD(_prHwMacRxStsGroup4) ((_prHwMacRxStsGroup4)->u2FrameCtl) +#define HAL_RX_STATUS_GET_TA(_prHwMacRxStsGroup4, pucTA) \ +{\ + kalMemCopy(pucTA, &(_prHwMacRxStsGroup4)->aucTA[0], 6); \ +} +#define HAL_RX_STATUS_GET_SEQ_FRAG_NUM(_prHwMacRxStsGroup4) ((_prHwMacRxStsGroup4)->u2SeqFrag) +#define HAL_RX_STATUS_GET_QOS_CTL_FIELD(_prHwMacRxStsGroup4) ((_prHwMacRxStsGroup4)->u2Qos) + +#define HAL_RX_STATUS_GET_SEQFrag_NUM(_prHwMacRxStsGroup4) ((_prHwMacRxStsGroup4)->u2SeqFrag) +#define HAL_RX_STATUS_GET_HTC(_prHwMacRxStsGroup4) ((_prHwMacRxStsGroup4)->u4HTC) + +/* DW 8~11 */ +#define HAL_RX_STATUS_GET_RSC(_prHwMacRxStsGroup1, pucRSC) \ +{\ + kalMemCopy(pucRSC, &(_prHwMacRxStsGroup1)->aucPN[0], 6); \ +} + +#define HAL_RX_STATUS_GET_PN(_prHwMacRxStsGroup1, pucPN) \ +{\ + kalMemCopy(pucPN, &(_prHwMacRxStsGroup1)->aucPN[0], 16); \ +} + +/* DW 12~13 */ +#define HAL_RX_STATUS_GET_TIMESTAMP(_prHwMacRxStsGroup2, _ucIdx) ((_prHwMacRxStsGroup2)->u4Timestamp) +#define HAL_RX_STATUS_GET_FCS32(_prHwMacRxStsGroup2) ((_prHwMacRxStsGroup2)->u4CRC) + +/* DW 14~19 */ +#define HAL_RX_STATUS_GET_RX_VECTOR(_prHwMacRxStsGroup3, _ucIdx) ((_prHwMacRxStsGroup3)->u4RxVector[_ucIdx]) + +#define HAL_RX_STATUS_GET_RCPI(_prHwMacRxStsGroup3) \ + (((_prHwMacRxStsGroup3)->u4RxVector[2] & RX_VT_RCPI_MASK) >> RX_VT_RCPI_OFFSET) + +/* TBD */ +#define HAL_RX_STATUS_GET_RX_PACKET_LEN(_prHwMacRxDesc) +#define HAL_RX_STATUS_IS_MATCH_PACKET(_prHwMacRxDesc) + +#define HAL_RX_STATUS_GET_CHNL_NUM(_prHwMacRxDesc) \ + ((((_prHwMacRxDesc)->ucChanFreq) > HW_CHNL_NUM_MAX_4G_5G) ? \ + (((_prHwMacRxDesc)->ucChanFreq) - HW_CHNL_NUM_MAX_4G_5G) : \ + ((_prHwMacRxDesc)->ucChanFreq)) + +/* To do: support more bands other than 2.4G and 5G */ +#define HAL_RX_STATUS_GET_RF_BAND(_prHwMacRxDesc) \ + ((((_prHwMacRxDesc)->ucChanFreq) <= HW_CHNL_NUM_MAX_2G4) ? \ + BAND_2G4 : BAND_5G) + +/*------------------------------------------------------------------------------ + * MACRO for HW_RX_VECTOR_DESC_T + *------------------------------------------------------------------------------ +*/ +#define HAL_RX_VECTOR_GET_TA(_prHwRxVector, pucTA) \ +{\ + kalMemCopy(pucTA, &(_prHwRxVector)->aucTA[0], 6); \ +} + +#define HAL_RX_VECTOR_GET_SEQ_NO(_prHwRxVector) ((_prHwRxVector)->ucRxVtSeqNo & RX_STATUS_RXV_SEQ_NO_MASK) +#define HAL_RX_VECTOR_IS_FOR_BA_ACK(_prHwRxVector) (((_prHwRxVector)->ucRxVtSeqNo & RX_VECTOR_FOR_BA_ACK)?TRUE:FALSE) +#define HAL_RX_VECTOR_GET_RX_VECTOR(_prHwRxVector, _ucIdx) ((_prHwRxVector)->u4RxVector[_ucIdx]) + +/*------------------------------------------------------------------------------ + * MACRO for Frame Type Decision + *------------------------------------------------------------------------------ +*/ +/* TO-DO: Add QoS Data + CF-ACK, QoS Data + CF-POLL, QoS Data + CF-ACK + CF-POLL + * if we support contention-free service in the future? + */ +#define RXM_IS_QOS_DATA_FRAME(_u2FrameCtrl) \ + (((_u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_QOS_DATA) ? TRUE : FALSE) + +#define RXM_IS_DATA_FRAME(_u2FrameCtrl) \ + (((_u2FrameCtrl & MASK_FC_TYPE) == MAC_FRAME_TYPE_DATA) ? TRUE : FALSE) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +VOID nicRxInitialize(IN P_ADAPTER_T prAdapter); + +VOID nicRxUninitialize(IN P_ADAPTER_T prAdapter); + +VOID nicRxProcessRFBs(IN P_ADAPTER_T prAdapter); + +#if !CFG_SDIO_INTR_ENHANCE +VOID nicRxReceiveRFBs(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS nicRxReadBuffer(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb); + +#else +VOID nicRxSDIOReceiveRFBs(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS +nicRxEnhanceReadBuffer(IN P_ADAPTER_T prAdapter, + IN UINT_32 u4DataPort, IN UINT_16 u2RxLength, IN OUT P_SW_RFB_T prSwRfb); +#endif /* CFG_SDIO_INTR_ENHANCE */ + +#if CFG_SDIO_RX_AGG +VOID nicRxSDIOAggReceiveRFBs(IN P_ADAPTER_T prAdapter); +#endif + +WLAN_STATUS nicRxSetupRFB(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prRfb); + +VOID nicRxReturnRFB(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prRfb); + +VOID nicProcessRxInterrupt(IN P_ADAPTER_T prAdapter); + +VOID nicRxProcessPktWithoutReorder(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID nicRxProcessForwardPkt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID nicRxProcessGOBroadcastPkt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID nicRxFillRFB(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb); + +P_SW_RFB_T nicRxDefragMPDU(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSWRfb, OUT P_QUE_T prReturnedQue); + +BOOLEAN nicRxIsDuplicateFrame(IN OUT P_SW_RFB_T prSwRfb); + +#if CFG_SUPPORT_SNIFFER +VOID nicRxProcessMonitorPacket(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb); +#endif + +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 */ + +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); + +VOID nicRxMgmtNoWTBLHandling(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); +#endif /* _NIC_RX_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/nic_tx.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/nic_tx.h new file mode 100644 index 0000000000000..40520b16dce96 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/nic_tx.h @@ -0,0 +1,1352 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/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. + */ + +#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 MAC_TX_RESERVED_FIELD 0 + +#define NIC_TX_RESOURCE_POLLING_TIMEOUT 256 +#define NIC_TX_RESOURCE_POLLING_DELAY_MSEC 50 + +#define NIC_TX_CMD_INFO_RESERVED_COUNT 4 + +/* Maximum buffer count for individual HIF TCQ */ +#define NIC_TX_PAGE_COUNT_TC0 (NIC_TX_BUFF_COUNT_TC0 * NIC_TX_MAX_PAGE_PER_FRAME) +#define NIC_TX_PAGE_COUNT_TC1 (NIC_TX_BUFF_COUNT_TC1 * NIC_TX_MAX_PAGE_PER_FRAME) +#define NIC_TX_PAGE_COUNT_TC2 (NIC_TX_BUFF_COUNT_TC2 * NIC_TX_MAX_PAGE_PER_FRAME) +#define NIC_TX_PAGE_COUNT_TC3 (NIC_TX_BUFF_COUNT_TC3 * NIC_TX_MAX_PAGE_PER_FRAME) +#define NIC_TX_PAGE_COUNT_TC4 (NIC_TX_BUFF_COUNT_TC4 * NIC_TX_MAX_PAGE_PER_FRAME) +#define NIC_TX_PAGE_COUNT_TC5 (NIC_TX_BUFF_COUNT_TC5 * NIC_TX_MAX_PAGE_PER_FRAME) + +#define NIC_TX_BUFF_COUNT_TC0 1 +#define NIC_TX_BUFF_COUNT_TC1 36 +#define NIC_TX_BUFF_COUNT_TC2 1 +#define NIC_TX_BUFF_COUNT_TC3 1 +#define NIC_TX_BUFF_COUNT_TC4 2 +#define NIC_TX_BUFF_COUNT_TC5 1 + +#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 8 +#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) + +#define NIC_TX_INIT_PAGE_COUNT_TC0 (NIC_TX_INIT_BUFF_COUNT_TC0 * NIC_TX_MAX_PAGE_PER_FRAME) +#define NIC_TX_INIT_PAGE_COUNT_TC1 (NIC_TX_INIT_BUFF_COUNT_TC1 * NIC_TX_MAX_PAGE_PER_FRAME) +#define NIC_TX_INIT_PAGE_COUNT_TC2 (NIC_TX_INIT_BUFF_COUNT_TC2 * NIC_TX_MAX_PAGE_PER_FRAME) +#define NIC_TX_INIT_PAGE_COUNT_TC3 (NIC_TX_INIT_BUFF_COUNT_TC3 * NIC_TX_MAX_PAGE_PER_FRAME) +#define NIC_TX_INIT_PAGE_COUNT_TC4 (NIC_TX_INIT_BUFF_COUNT_TC4 * NIC_TX_MAX_PAGE_PER_FRAME) +#define NIC_TX_INIT_PAGE_COUNT_TC5 (NIC_TX_INIT_BUFF_COUNT_TC5 * NIC_TX_MAX_PAGE_PER_FRAME) + +#endif + +#define NIC_TX_ENABLE_SECOND_HW_QUEUE 0 + +/* 4 TODO: The following values shall be got from FW by query CMD */ +/*------------------------------------------------------------------------*/ +/* Resource Management related information */ +/*------------------------------------------------------------------------*/ +#define NIC_TX_PAGE_SIZE_IS_POWER_OF_2 TRUE +#define NIC_TX_PAGE_SIZE_IN_POWER_OF_2 7 +#define NIC_TX_PAGE_SIZE 128 /* in unit of bytes */ + +/* For development only */ +#define NIC_TX_MAX_SIZE_PER_FRAME 1532 /* calculated by MS native 802.11 format */ +#define NIC_TX_MAX_PAGE_PER_FRAME \ + ((NIC_TX_DESC_AND_PADDING_LENGTH + NIC_TX_DESC_HEADER_PADDING_LENGTH + \ + NIC_TX_MAX_SIZE_PER_FRAME + NIC_TX_PAGE_SIZE - 1) / NIC_TX_PAGE_SIZE) + +/*------------------------------------------------------------------------*/ +/* Tx descriptor related information */ +/*------------------------------------------------------------------------*/ + +/* Frame Buffer +* |<--Tx Descriptor-->|<--Tx descriptor padding-->|<--802.3/802.11 Header-->|<--Header padding-->|<--Payload-->| +*/ + +/* Tx descriptor length by format (TXD.FT) */ +#define NIC_TX_DESC_LONG_FORMAT_LENGTH_DW 7 /* in unit of double word */ +#define NIC_TX_DESC_LONG_FORMAT_LENGTH DWORD_TO_BYTE(NIC_TX_DESC_LONG_FORMAT_LENGTH_DW) +#define NIC_TX_DESC_SHORT_FORMAT_LENGTH_DW 2 /* in unit of double word */ +#define NIC_TX_DESC_SHORT_FORMAT_LENGTH DWORD_TO_BYTE(NIC_TX_DESC_SHORT_FORMAT_LENGTH_DW) + +/* Tx descriptor padding length (DMA.MICR.TXDSCR_PAD) */ +#define NIC_TX_DESC_PADDING_LENGTH_DW 0 /* in unit of double word */ +#define NIC_TX_DESC_PADDING_LENGTH DWORD_TO_BYTE(NIC_TX_DESC_PADDING_LENGTH_DW) + +#define NIC_TX_DESC_AND_PADDING_LENGTH (NIC_TX_DESC_LONG_FORMAT_LENGTH + NIC_TX_DESC_PADDING_LENGTH) + +/* Tx header padding (TXD.HeaderPadding) */ +/* Warning!! To use MAC header padding, every Tx packet must be decomposed */ +#define NIC_TX_DESC_HEADER_PADDING_LENGTH 0 /* in unit of bytes */ + +#define NIC_TX_DEFAULT_WLAN_INDEX 31 /* For Tx packets to peer who has no WLAN table index. */ + +#define NIC_TX_DESC_PID_INVALID 0 +#define NIC_TX_DESC_DRIVER_PID_MIN 1 +#define NIC_TX_DESC_DRIVER_PID_MAX 127 +#define NIC_TX_DESC_PID_RESERVED_FOR_MGMT 10 /* Reserve PID number for MGMT/Security frames */ + +#if defined(MT6630) || defined(MT6631) +#define NIC_TX_DATA_DEFAULT_RETRY_COUNT_LIMIT 30 +#else +#define NIC_TX_DATA_DEFAULT_RETRY_COUNT_LIMIT 7 +#endif +#define NIC_TX_MGMT_DEFAULT_RETRY_COUNT_LIMIT 30 + +#define NIC_TX_AC_BE_REMAINING_TX_TIME TX_DESC_TX_TIME_NO_LIMIT /* in unit of ms */ +#define NIC_TX_AC_BK_REMAINING_TX_TIME TX_DESC_TX_TIME_NO_LIMIT /* in unit of ms */ +#define NIC_TX_AC_VO_REMAINING_TX_TIME TX_DESC_TX_TIME_NO_LIMIT /* in unit of ms */ +#define NIC_TX_AC_VI_REMAINING_TX_TIME TX_DESC_TX_TIME_NO_LIMIT /* in unit of ms */ + +/*------------------------------------------------------------------------*/ +/* Tx descriptor field related information */ +/*------------------------------------------------------------------------*/ +/* DW 0 */ +#define TX_DESC_TX_BYTE_COUNT_MASK BITS(0, 15) +#define TX_DESC_TX_BYTE_COUNT_OFFSET 0 + +#define TX_DESC_ETHER_TYPE_OFFSET_MASK BITS(0, 6) +#define TX_DESC_ETHER_TYPE_OFFSET_OFFSET 0 +#define TX_DESC_IP_CHKSUM_OFFLOAD BIT(7) +#define TX_DESC_TCP_UDP_CHKSUM_OFFLOAD BIT(0) +#define TX_DESC_USB_NEXT_VLD BIT(1) +#define TX_DESC_USB_TX_BURST BIT(2) +#define TX_DESC_QUEUE_INDEX_MASK BITS(3, 6) +#define TX_DESC_QUEUE_INDEX_OFFSET 3 +#define TX_DESC_PORT_INDEX BIT(7) +#define TX_DESC_PORT_INDEX_OFFSET 7 + +#define PORT_INDEX_LMAC 0 +#define PORT_INDEX_MCU 1 + +/* DW 1 */ +#define TX_DESC_WLAN_INDEX_MASK BITS(0, 7) +#define TX_DESC_WLAN_INDEX_OFFSET 0 + +#define TX_DESC_HEADER_FORMAT_MASK BITS(5, 6) +#define TX_DESC_HEADER_FORMAT_OFFSET 5 + +#define HEADER_FORMAT_NON_802_11 0 /* Non-802.11 */ +#define HEADER_FORMAT_COMMAND 1 /* Command */ +#define HEADER_FORMAT_802_11_NORMAL_MODE 2 /* 802.11 (normal mode) */ +#define HEADER_FORMAT_802_11_ENHANCE_MODE 3 /* 802.11 (Enhancement mode) */ +#define HEADER_FORMAT_802_11_MASK BIT(1) + +#define TX_DESC_NON_802_11_MORE_DATA BIT(0) +#define TX_DESC_NON_802_11_EOSP BIT(1) +#define TX_DESC_NON_802_11_REMOVE_VLAN BIT(2) +#define TX_DESC_NON_802_11_VLAN_FIELD BIT(3) +#define TX_DESC_NON_802_11_ETHERNET_II BIT(4) +#define TX_DESC_NOR_802_11_HEADER_LENGTH_MASK BITS(0, 4) +#define TX_DESC_NOR_802_11_HEADER_LENGTH_OFFSET 0 +#define TX_DESC_ENH_802_11_EOSP BIT(1) +#define TX_DESC_ENH_802_11_AMSDU BIT(2) + +#define TX_DESC_FORMAT BIT(7) +#define TX_DESC_SHORT_FORMAT 0 +#define TX_DESC_LONG_FORMAT 1 +#define TX_DESC_HEADER_PADDING_LENGTH_MASK BITS(0, 1) +#define TX_DESC_HEADER_PADDING_LENGTH_OFFSET 0 +#define TX_DESC_HEADER_PADDING_MODE BIT(2) +#define TX_DESC_NO_ACK BIT(3) +#define TX_DESC_TID_MASK BITS(4, 6) +#define TX_DESC_TID_OFFSET 4 +#define TX_DESC_TID_NUM 8 +#define TX_DESC_PROTECTED_FRAME BIT(7) + +#define TX_DESC_PACKET_TYPE_MASK BITS(0, 1) /* SW Field */ +#define TX_DESC_PACKET_TYPE_OFFSET 0 +#define TX_DESC_OWN_MAC_MASK BITS(2, 7) +#define TX_DESC_OWN_MAC_OFFSET 2 + +/* DW 2 */ +#define TX_DESC_SUB_TYPE_MASK BITS(0, 3) +#define TX_DESC_SUB_TYPE_OFFSET 0 +#define TX_DESC_TYPE_MASK BITS(4, 5) +#define TX_DESC_TYPE_OFFSET 4 +#define TX_DESC_NDP BIT(6) +#define TX_DESC_NDPA BIT(7) + +#define TX_DESC_SOUNDING BIT(0) +#define TX_DESC_FORCE_RTS_CTS BIT(1) +#define TX_DESC_BROADCAST_MULTICAST BIT(2) +#define TX_DESC_BIP_PROTECTED BIT(3) +#define TX_DESC_DURATION_FIELD_CONTROL BIT(4) +#define TX_DESC_HTC_EXISTS BIT(5) +#define TX_DESC_FRAGMENT_MASK BITS(6, 7) +#define TX_DESC_FRAGMENT_OFFSET 6 +#define FRAGMENT_FISRT_PACKET 1 +#define FRAGMENT_MIDDLE_PACKET 2 +#define FRAGMENT_LAST_PACKET 3 + +#define TX_DESC_REMAINING_MAX_TX_TIME BITS(0, 7) +#define TX_DESC_TX_TIME_NO_LIMIT 0 +/* Unit of life time calculation of Tx descriptor */ +#define TX_DESC_LIFE_TIME_UNIT_IN_POWER_OF_2 5 +#define TX_DESC_LIFE_TIME_UNIT POWER_OF_2(TX_DESC_LIFE_TIME_UNIT_IN_POWER_OF_2) +#define TX_DESC_POWER_OFFSET_MASK BITS(0, 4) +#define TX_DESC_BA_DISABLE BIT(5) +#define TX_DESC_TIMING_MEASUREMENT BIT(6) +#define TX_DESC_FIXED_RATE BIT(7) + +/* DW 3 */ +#define TX_DESC_SW_RESERVED_MASK BITS(0, 5) +#define TX_DESC_SW_RESERVED_OFFSET 0 +#define TX_DESC_TX_COUNT_MASK BITS(6, 10) +#define TX_DESC_TX_COUNT_OFFSET 6 +#define TX_DESC_TX_COUNT_NO_ATTEMPT 0 +#define TX_DESC_TX_COUNT_NO_LIMIT 31 +#define TX_DESC_REMAINING_TX_COUNT_MASK BITS(11, 15) +#define TX_DESC_REMAINING_TX_COUNT_OFFSET 11 +#define TX_DESC_SEQUENCE_NUMBER BITS(0, 11) +#define TX_DESC_HW_RESERVED_MASK BITS(12, 13) +#define TX_DESC_HW_RESERVED_OFFSET 12 +#define TX_DESC_PN_IS_VALID BIT(14) +#define TX_DESC_SN_IS_VALID BIT(15) + +/* DW 4 */ +#define TX_DESC_PN_PART1 BITS(0, 31) + +/* DW 5 */ +#define TX_DESC_PACKET_ID BIT(0, 7) +#define TX_DESC_TX_STATUS_FORMAT BIT(0) +#define TX_DESC_TX_STATUS_FORMAT_OFFSET 0 +#define TX_DESC_TX_STATUS_TO_MCU BIT(1) +#define TX_DESC_TX_STATUS_TO_HOST BIT(2) +#define TX_DESC_DA_SOURCE BIT(3) +#define TX_DESC_BAR_SSN_CONTROL BIT(4) +#define TX_DESC_POWER_MANAGEMENT_CONTROL BIT(5) +#define TX_DESC_PN_PART2 BITS(0, 15) + + /* DW 6 *//* FR = 1 */ +#define TX_DESC_FIXED_RATE_MODE BIT(0) +#define TX_DESC_ANTENNA_INDEX_MASK BITS(2, 7) +#define TX_DESC_ANTENNA_INDEX_OFFSET 2 + +#define TX_DESC_BANDWIDTH_MASK BITS(0, 2) +#define TX_DESC_SPATIAL_EXTENSION BIT(3) +#define TX_DESC_ANTENNA_PRIORITY BITS(4, 6) +#define TX_DESC_DYNAMIC_BANDWIDTH BIT(7) + +#define TX_DESC_EXPLICIT_BEAMFORMING BIT(0) +#define TX_DESC_IMPLICIT_BEAMFORMING BIT(1) +#define TX_DESC_FIXDE_RATE_MASK BITS(2, 13) +#define TX_DESC_FIXDE_RATE_OFFSET 2 +#define TX_DESC_LDPC BIT(14) +#define TX_DESC_GUARD_INTERVAL BIT(15) + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE +#define NIC_TX_TIME_THRESHOLD 100 /* in unit of ms */ +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + /* 3 *//* Session for TX QUEUES */ +/* The definition in this ENUM is used to categorize packet's Traffic Class according + * to the their TID(User Priority). + * In order to achieve QoS goal, a particular TC should not block the process of + * another packet with different TC. + * In current design we will have 5 categories(TCs) of SW resource. + */ +/* HIF Tx interrupt status queue index*/ +typedef enum _ENUM_HIF_TX_INDEX_T { + HIF_TX_AC0_INDEX = 0, /* HIF TX: AC0 packets */ + HIF_TX_AC1_INDEX, /* HIF TX: AC1 packets */ + HIF_TX_AC2_INDEX, /* HIF TX: AC2 packets */ + HIF_TX_AC3_INDEX, /* HIF TX: AC3 packets */ + HIF_TX_AC4_INDEX, /* HIF TX: AC4 packets */ + HIF_TX_AC5_INDEX, /* HIF TX: AC5 packets */ + HIF_TX_AC6_INDEX, /* HIF TX: AC6 packets */ + HIF_TX_BMC_INDEX, /* HIF TX: BMC packets */ + HIF_TX_BCN_INDEX, /* HIF TX: BCN packets */ + HIF_TX_AC10_INDEX, /* HIF TX: AC10 packets */ + HIF_TX_AC11_INDEX, /* HIF TX: AC11 packets */ + HIF_TX_AC12_INDEX, /* HIF TX: AC12 packets */ + HIF_TX_AC13_INDEX, /* HIF TX: AC13 packets */ + HIF_TX_AC14_INDEX, /* HIF TX: AC14 packets */ + HIF_TX_FFA_INDEX, /* HIF TX: free-for-all */ + HIF_TX_CPU_INDEX, /* HIF TX: CPU */ + HIF_TX_NUM /* Maximum number of HIF TX port. */ +} ENUM_HIF_TX_INDEX_T; + +/* LMAC Tx queue index */ +typedef enum _ENUM_MAC_TXQ_INDEX_T { + MAC_TXQ_AC0_INDEX = 0, + MAC_TXQ_AC1_INDEX, + MAC_TXQ_AC2_INDEX, + MAC_TXQ_AC3_INDEX, + MAC_TXQ_AC4_INDEX, + MAC_TXQ_AC5_INDEX, + MAC_TXQ_AC6_INDEX, + MAC_TXQ_BMC_INDEX, + MAC_TXQ_BCN_INDEX, + MAC_TXQ_AC10_INDEX, + MAC_TXQ_AC11_INDEX, + MAC_TXQ_AC12_INDEX, + MAC_TXQ_AC13_INDEX, + MAC_TXQ_AC14_INDEX, + MAC_TXQ_NUM +} ENUM_MAC_TXQ_INDEX_T; + +/* MCU quque index */ +typedef enum _ENUM_MCU_Q_INDEX_T { + MCU_Q0_INDEX = 0, + MCU_Q1_INDEX, + MCU_Q2_INDEX, + MCU_Q3_INDEX, + MCU_Q_NUM +} ENUM_MCU_Q_INDEX_T; + +/* Tc Resource index */ +typedef enum _ENUM_TRAFFIC_CLASS_INDEX_T { + /*First HW queue */ + TC0_INDEX = 0, /* HIF TX: AC0 packets */ + TC1_INDEX, /* HIF TX: AC1 packets */ + TC2_INDEX, /* HIF TX: AC2 packets */ + TC3_INDEX, /* HIF TX: AC3 packets */ + TC4_INDEX, /* HIF TX: CPU packets */ + TC5_INDEX, /* HIF TX: AC4 packets */ + + /* Second HW queue */ +#if NIC_TX_ENABLE_SECOND_HW_QUEUE + TC6_INDEX, /* HIF TX: AC10 packets */ + TC7_INDEX, /* HIF TX: AC11 packets */ + TC8_INDEX, /* HIF TX: AC12 packets */ + TC9_INDEX, /* HIF TX: AC13 packets */ + TC10_INDEX, /* HIF TX: AC14 packets */ +#endif + + TC_NUM /* Maximum number of Traffic Classes. */ +} ENUM_TRAFFIC_CLASS_INDEX_T; + +/* per-Network Tc Resource index */ +typedef enum _ENUM_NETWORK_TC_RESOURCE_INDEX_T { + /* QoS Data frame, WMM AC index */ + NET_TC_WMM_AC_BE_INDEX = 0, + NET_TC_WMM_AC_BK_INDEX, + NET_TC_WMM_AC_VI_INDEX, + NET_TC_WMM_AC_VO_INDEX, + /* Mgmt frame */ + NET_TC_MGMT_INDEX, + /* nonQoS / non StaRec frame (BMC/non-associated frame) */ + NET_TC_NON_STAREC_NON_QOS_INDEX, + + NET_TC_NUM +} ENUM_NETWORK_TC_RESOURCE_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 enum _ENUM_FIX_BW_T { + FIX_BW_NO_FIXED = 0, + FIX_BW_20 = 4, + FIX_BW_40, + FIX_BW_80, + FIX_BW_160, + FIX_BW_NUM +} ENUM_FIX_BW_T; + +typedef enum _ENUM_MSDU_OPTION_T { + MSDU_OPT_NO_ACK = BIT(0), + MSDU_OPT_NO_AGGREGATE = BIT(1), + MSDU_OPT_TIMING_MEASURE = BIT(2), + MSDU_OPT_RCPI_NOISE_STATUS = BIT(3), + + /* Option by Frame Format */ + /* Non-80211 */ + MSDU_OPT_MORE_DATA = BIT(4), + MSDU_OPT_REMOVE_VLAN = BIT(5), /* Remove VLAN tag if exists */ + + /* 80211-enhanced */ + MSDU_OPT_AMSDU = BIT(6), + + /* 80211-enhanced & Non-80211 */ + MSDU_OPT_EOSP = BIT(7), + + /* Beamform */ + MSDU_OPT_NDP = BIT(8), + MSDU_OPT_NDPA = BIT(9), + MSDU_OPT_SOUNDING = BIT(10), + + /* Protection */ + MSDU_OPT_FORCE_RTS = BIT(11), + + /* Security */ + MSDU_OPT_BIP = BIT(12), + MSDU_OPT_PROTECTED_FRAME = BIT(13), + + /* SW Field */ + MSDU_OPT_SW_DURATION = BIT(14), + MSDU_OPT_SW_PS_BIT = BIT(15), + MSDU_OPT_SW_HTC = BIT(16), + MSDU_OPT_SW_BAR_SN = BIT(17), + + /* Manual Mode */ + MSDU_OPT_MANUAL_FIRST_BIT = BIT(18), + + MSDU_OPT_MANUAL_LIFE_TIME = MSDU_OPT_MANUAL_FIRST_BIT, + MSDU_OPT_MANUAL_RETRY_LIMIT = BIT(19), + MSDU_OPT_MANUAL_POWER_OFFSET = BIT(20), + MSDU_OPT_MANUAL_TX_QUE = BIT(21), + MSDU_OPT_MANUAL_SN = BIT(22), + + MSDU_OPT_MANUAL_LAST_BIT = MSDU_OPT_MANUAL_SN +} ENUM_MSDU_OPTION_T; + +typedef enum _ENUM_MSDU_CONTROL_FLAG_T { + MSDU_CONTROL_FLAG_FORCE_TX = BIT(0) +} ENUM_MSDU_CONTROL_FLAG_T; + +typedef enum _ENUM_MSDU_RATE_MODE_T { + MSDU_RATE_MODE_AUTO = 0, + MSDU_RATE_MODE_MANUAL_DESC, + /* The following rate mode is not implemented yet */ + /* DON'T use!!! */ + MSDU_RATE_MODE_MANUAL_CR +} ENUM_MSDU_RATE_MODE_T; + +typedef struct _TX_TCQ_STATUS_T { + /* HIF reported page count delta */ + UINT_16 au2TxDonePageCount[TC_NUM]; /* other TC */ + UINT_16 au2PreUsedPageCount[TC_NUM]; + UINT_16 u2AvaliablePageCount; /* FFA */ + UINT_8 ucNextTcIdx; /* For round-robin distribute free page count */ + + /* distributed page count */ + UINT_16 au2FreePageCount[TC_NUM]; + UINT_16 au2MaxNumOfPage[TC_NUM]; + + /* buffer count */ + UINT_16 au2FreeBufferCount[TC_NUM]; + UINT_16 au2MaxNumOfBuffer[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; + + UINT_32 u4PageSize; + + UINT_32 u4TotalPageNum; + + UINT_32 u4TotalTxRsvPageNum; + +/* 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_TYPE_T { + TX_PACKET_TYPE_DATA = 0, + TX_PACKET_TYPE_MGMT, + /* TX_PACKET_TYPE_1X, */ + X_PACKET_TYPE_NUM +} ENUM_TX_PACKET_TYPE_T, *P_ENUM_TX_PACKET_TYPE_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; + +/* TX Call Back Function */ +typedef WLAN_STATUS(*PFN_TX_DONE_HANDLER) (IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE +typedef struct _PKT_PROFILE_T { + BOOLEAN fgIsValid; +#if CFG_PRINT_PKT_LIFETIME_PROFILE + BOOLEAN fgIsPrinted; + UINT_16 u2IpSn; + UINT_16 u2RtpSn; + UINT_8 ucTcxFreeCount; +#endif + OS_SYSTIME rHardXmitArrivalTimestamp; + OS_SYSTIME rEnqueueTimestamp; + OS_SYSTIME rDequeueTimestamp; + OS_SYSTIME rHifTxDoneTimestamp; +} PKT_PROFILE_T, *P_PKT_PROFILE_T; +#endif +/* TX transactions could be divided into 4 kinds: + * + * 1) 802.1X / Bluetooth-over-Wi-Fi Security Frames + * [CMD_INFO_T] - [prPacket] - in skb or NDIS_PACKET form + * + * 2) MMPDU + * [CMD_INFO_T] - [prPacket] - [MSDU_INFO_T] - [prPacket] - direct buffer for frame body + * + * 3) Command Packets + * [CMD_INFO_T] - [pucInfoBuffer] - direct buffer for content of command packet + * + * 4) Normal data frame + * [MSDU_INFO_T] - [prPacket] - in skb or NDIS_PACKET form + */ + +/* PS_FORWARDING_TYPE_NON_PS means that the receiving STA is in Active Mode +* from the perspective of host driver (maybe not synchronized with FW --> SN is needed) +*/ + +struct _MSDU_INFO_T { + QUE_ENTRY_T rQueEntry; + P_NATIVE_PACKET prPacket; /* Pointer to packet buffer */ + + ENUM_TX_PACKET_SRC_T eSrc; /* specify OS/FORWARD packet */ + UINT_8 ucUserPriority; /* QoS parameter, convert to TID */ + + /* For composing TX descriptor header */ + UINT_8 ucDhcpArpFlag; /* 1: DHCP|ARP Data */ + UINT_8 ucTC; /* Traffic Class: 0~4 (HIF TX0), 5 (HIF TX1) */ + UINT_8 ucPacketType; /* 0: Data, 1: Management Frame */ + UINT_8 ucStaRecIndex; /* STA_REC index */ + UINT_8 ucBssIndex; /* BSS_INFO_T index */ + UINT_8 ucWlanIndex; /* Wlan entry index */ + + BOOLEAN fgIs802_1x; /* TRUE: 802.1x frame */ + BOOLEAN fgIs802_11; /* TRUE: 802.11 header is present */ + BOOLEAN fgIs802_3; /* TRUE: 802.3 frame */ + BOOLEAN fgIsVlanExists; /* TRUE: VLAN tag is exists */ + UINT_8 ucEapolKeyType; /* 1: 1/4; 2: 2/4; 3: 3/4; 4: 4/4 */ + + /* BOOLEAN fgIsBIP; *//* Management Frame Protection */ + /* BOOLEAN fgIsBasicRate; *//* Force Basic Rate Transmission */ + /* BOOLEAN fgIsMoreData; *//* More data */ + /* BOOLEAN fgIsEOSP; *//* End of service period */ + + /* Special Option */ + UINT_32 u4Option; /* Special option in bitmask, no ACK, etc... */ + INT_8 cPowerOffset; /* Per-packet power offset, in 2's complement */ + UINT_16 u2SwSN; /* SW assigned sequence number */ + UINT_8 ucRetryLimit; /* The retry limit */ + UINT_32 u4RemainingLifetime; /* Remaining lifetime, unit:ms */ + + /* Control flag */ + UINT_8 ucControlFlag; /* Control flag in bitmask */ + + /* Fixed Rate Option */ + UINT_8 ucRateMode; /* Rate mode: AUTO, MANUAL_DESC, MANUAL_CR */ + UINT_32 u4FixedRateOption; /* The rate option, rate code, GI, etc... */ + + BOOLEAN fgIsTXDTemplateValid; /* There is a valid Tx descriptor for this packet */ + + /* flattened from PACKET_INFO_T */ + UINT_8 ucMacHeaderLength; /* MAC header legth */ + UINT_8 ucLlcLength; /* w/o EtherType */ + UINT_16 u2FrameLength; /* Total frame length */ + UINT_8 aucEthDestAddr[MAC_ADDR_LEN]; /* Ethernet Destination Address */ + UINT_8 ucPageCount; /* Required page count for this MSDU */ + + /* for TX done tracking */ + UINT_8 ucTxSeqNum; /* MGMT frame serial number */ + UINT_8 ucPID; /* PID */ + PFN_TX_DONE_HANDLER pfTxDoneHandler; /* Tx done handler */ + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + PKT_PROFILE_T rPktProfile; +#endif + + /* To be removed */ + UINT_8 ucFormatID; /* 0: MAUI, Linux, Windows NDIS 5.1 */ + /* 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 */ + /* TRUE means this is the last packet of the burst for (STA, TID) */ + /* BOOLEAN fgIsBurstEnd; */ +#if CFG_M0VE_BA_TO_DRIVER + UINT_8 ucTID; +#endif + +#if CFG_SUPPORT_MULTITHREAD + /* Compose TxDesc in tx_thread and place here */ + UINT_8 aucTxDescBuffer[NIC_TX_DESC_AND_PADDING_LENGTH]; +#endif + UINT_16 u2CookieLen; + PUINT_8 pucCookie; +}; + +/*!A data structure which is identical with HW MAC TX DMA Descriptor */ +typedef struct _HW_MAC_TX_DESC_T { + /* DW 0 */ + UINT_16 u2TxByteCount; + UINT_8 ucEtherOffset; /* Ether-Type Offset, IP checksum offload */ + UINT_8 ucPortIdx_QueueIdx; /* UDP/TCP checksum offload, USB NextVLD/TxBURST, Queue index, Port index */ + /* DW 1 */ + UINT_8 ucWlanIdx; + UINT_8 ucHeaderFormat; /* Header format, TX descriptor format */ + UINT_8 ucHeaderPadding; /* Header padding, no ACK, TID, Protect frame */ + UINT_8 ucOwnMAC; + + /* Long Format, the following structure is for long format ONLY */ + /* DW 2 */ + UINT_8 ucType_SubType; /* Type, Sub-type, NDP, NDPA */ + UINT_8 ucFrag; /* Sounding, force RTS/CTS, BMC, BIP, Duration, HTC exist, Fragment */ + UINT_8 ucRemainingMaxTxTime; + UINT_8 ucPowerOffset; /* Power offset, Disable BA, Timing measurement, Fixed rate */ + /* DW 3 */ + UINT_16 u2TxCountLimit; /* TX count limit */ + UINT_16 u2SN; /* SN, HW own, PN valid, SN valid */ + /* DW 4 */ + UINT_32 u4PN1; + /* DW 5 */ + UINT_8 ucPID; + UINT_8 ucTxStatus; /* TXS format, TXS to mcu, TXS to host, DA source, BAR SSN, Power management */ + UINT_16 u2PN2; + /* DW 6 */ + UINT_8 ucAntID; /* Fixed rate, Antenna ID */ + UINT_8 ucBandwidth; /* Bandwidth, Spatial Extension, Antenna priority, Dynamic bandwidth */ + UINT_16 u2FixedRate; /* Explicit/implicit beamforming, Fixed rate table, LDPC, GI */ +} HW_MAC_TX_DESC_T, *P_HW_MAC_TX_DESC_T, **PP_HW_MAC_TX_DESC_T; + +typedef struct _TX_RESOURCE_CONTROL_T { + /* HW TX queue definition */ + UINT_8 ucDestPortIndex; + UINT_8 ucDestQueueIndex; + /* HIF Interrupt status index */ + UINT_8 ucHifTxQIndex; +} TX_RESOURCE_CONTROL_T, *PTX_RESOURCE_CONTROL_T; + +typedef struct _TX_TC_TRAFFIC_SETTING_T { + UINT_8 ucTxDescLength; + UINT_32 u4RemainingTxTime; + UINT_8 ucTxCountLimit; +} TX_TC_TRAFFIC_SETTING_T, P_TX_TC_TRAFFIC_SETTING_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 TX_INC_CNT(prTxCtrl, eCounter) \ + {((P_TX_CTRL_T)prTxCtrl)->au4Statistics[eCounter]++; } + +#define TX_ADD_CNT(prTxCtrl, eCounter, u8Amount) \ + {((P_TX_CTRL_T)prTxCtrl)->au4Statistics[eCounter] += (UINT_32)u8Amount; } + +#define TX_GET_CNT(prTxCtrl, eCounter) \ + (((P_TX_CTRL_T)prTxCtrl)->au4Statistics[eCounter]) + +#define TX_RESET_ALL_CNTS(prTxCtrl) \ + {kalMemZero(&prTxCtrl->au4Statistics[0], sizeof(prTxCtrl->au4Statistics)); } +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + +#if CFG_PRINT_PKT_LIFETIME_PROFILE +#define PRINT_PKT_PROFILE(_pkt_profile, _note) \ +{ \ + if (!(_pkt_profile)->fgIsPrinted) { \ + DBGLOG(TX, TRACE, "X[%lu] E[%lu] D[%lu] HD[%lu] B[%d] RTP[%d] %s\n", \ + (UINT_32)((_pkt_profile)->rHardXmitArrivalTimestamp), \ + (UINT_32)((_pkt_profile)->rEnqueueTimestamp), \ + (UINT_32)((_pkt_profile)->rDequeueTimestamp), \ + (UINT_32)((_pkt_profile)->rHifTxDoneTimestamp), \ + (UINT_8)((_pkt_profile)->ucTcxFreeCount), \ + (UINT_16)((_pkt_profile)->u2RtpSn), \ + (_note))); \ + (_pkt_profile)->fgIsPrinted = TRUE; \ + } \ +} +#else +#define PRINT_PKT_PROFILE(_pkt_profile, _note) +#endif + +#define CHK_PROFILES_DELTA(_pkt1, _pkt2, _delta) \ + (CHECK_FOR_TIMEOUT((_pkt1)->rHardXmitArrivalTimestamp, (_pkt2)->rHardXmitArrivalTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt1)->rEnqueueTimestamp, (_pkt2)->rEnqueueTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt1)->rDequeueTimestamp, (_pkt2)->rDequeueTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt1)->rHifTxDoneTimestamp, (_pkt2)->rHifTxDoneTimestamp, (_delta))) + +#define CHK_PROFILE_DELTA(_pkt, _delta) \ + (CHECK_FOR_TIMEOUT((_pkt)->rEnqueueTimestamp, (_pkt)->rHardXmitArrivalTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt)->rDequeueTimestamp, (_pkt)->rEnqueueTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt)->rHifTxDoneTimestamp, (_pkt)->rDequeueTimestamp, (_delta))) +#endif + +/*------------------------------------------------------------------------------ + * MACRO for MSDU_INFO + *------------------------------------------------------------------------------ + */ +#define TX_SET_MMPDU nicTxSetMngPacket +#define TX_SET_DATA_PACKET nicTxSetDataPacket + +/*------------------------------------------------------------------------------ + * MACRO for HW_MAC_TX_DESC_T + *------------------------------------------------------------------------------ + */ +#define TX_DESC_GET_FIELD(_rHwMacTxDescField, _mask, _offset) \ + (((_rHwMacTxDescField) & (_mask)) >> (_offset)) +#define TX_DESC_SET_FIELD(_rHwMacTxDescField, _value, _mask, _offset) \ +{ \ + (_rHwMacTxDescField) &= ~(_mask); \ + (_rHwMacTxDescField) |= (((_value) << (_offset)) & (_mask)); \ +} + +#define HAL_MAC_TX_DESC_SET_DW(_prHwMacTxDesc, _ucOffsetInDw, _ucLengthInDw, _pucValueAddr) \ + kalMemCopy((PUINT_32)(_prHwMacTxDesc) + (_ucOffsetInDw), \ + (PUINT_8)(_pucValueAddr), DWORD_TO_BYTE(_ucLengthInDw)) +#define HAL_MAC_TX_DESC_GET_DW(_prHwMacTxDesc, _ucOffsetInDw, _ucLengthInDw, _pucValueAddr) \ + kalMemCopy((PUINT_8)(_pucValueAddr), \ + (PUINT_32)(_prHwMacTxDesc) + (_ucOffsetInDw), DWORD_TO_BYTE(_ucLengthInDw)) + +/* DW 0 */ +#define HAL_MAC_TX_DESC_GET_TX_BYTE_COUNT(_prHwMacTxDesc) ((_prHwMacTxDesc)->u2TxByteCount) +#define HAL_MAC_TX_DESC_SET_TX_BYTE_COUNT(_prHwMacTxDesc, _u2TxByteCount) \ + (((_prHwMacTxDesc)->u2TxByteCount) = ((UINT_16)_u2TxByteCount)) + +#define HAL_MAC_TX_DESC_GET_ETHER_TYPE_OFFSET(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucEtherOffset, \ + TX_DESC_ETHER_TYPE_OFFSET_MASK, TX_DESC_ETHER_TYPE_OFFSET_OFFSET) +#define HAL_MAC_TX_DESC_SET_ETHER_TYPE_OFFSET(_prHwMacTxDesc, _ucEtherTypeOffset) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucEtherOffset), \ + ((UINT_8)_ucEtherTypeOffset), TX_DESC_ETHER_TYPE_OFFSET_MASK, TX_DESC_ETHER_TYPE_OFFSET_OFFSET) + +#define HAL_MAC_TX_DESC_IS_IP_CHKSUM_ENABLED(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucEtherOffset & TX_DESC_IP_CHKSUM_OFFLOAD)?FALSE:TRUE) +#define HAL_MAC_TX_DESC_SET_IP_CHKSUM(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucEtherOffset |= TX_DESC_IP_CHKSUM_OFFLOAD) +#define HAL_MAC_TX_DESC_UNSET_IP_CHKSUM(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucEtherOffset &= ~TX_DESC_IP_CHKSUM_OFFLOAD) + +#define HAL_MAC_TX_DESC_IS_TCP_UDP_CHKSUM_ENABLED(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPortIdx_QueueIdx & TX_DESC_TCP_UDP_CHKSUM_OFFLOAD)?FALSE:TRUE) +#define HAL_MAC_TX_DESC_SET_TCP_UDP_CHKSUM(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPortIdx_QueueIdx |= TX_DESC_TCP_UDP_CHKSUM_OFFLOAD) +#define HAL_MAC_TX_DESC_UNSET_TCP_UDP_CHKSUM(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPortIdx_QueueIdx &= ~TX_DESC_TCP_UDP_CHKSUM_OFFLOAD) + +#define HAL_MAC_TX_DESC_IS_USB_NEXT_VLD_ENABLED(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucEtherOffset & TX_DESC_USB_NEXT_VLD)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_USB_NEXT_VLD(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucEtherOffset |= TX_DESC_USB_NEXT_VLD) +#define HAL_MAC_TX_DESC_UNSET_USB_NEXT_VLD(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucEtherOffset &= ~TX_DESC_USB_NEXT_VLD) + +#define HAL_MAC_TX_DESC_IS_USB_TX_BURST_ENABLED(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPortIdx_QueueIdx & TX_DESC_USB_TX_BURST)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_USB_TX_BURST(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPortIdx_QueueIdx |= TX_DESC_USB_TX_BURST) +#define HAL_MAC_TX_DESC_UNSET_USB_TX_BURST(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPortIdx_QueueIdx &= ~TX_DESC_USB_TX_BURST) + +#define HAL_MAC_TX_DESC_GET_QUEUE_INDEX(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucPortIdx_QueueIdx, TX_DESC_QUEUE_INDEX_MASK, TX_DESC_QUEUE_INDEX_OFFSET) +#define HAL_MAC_TX_DESC_SET_QUEUE_INDEX(_prHwMacTxDesc, _ucQueueIndex) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucPortIdx_QueueIdx), \ + ((UINT_8)_ucQueueIndex), TX_DESC_QUEUE_INDEX_MASK, TX_DESC_QUEUE_INDEX_OFFSET) + +#define HAL_MAC_TX_DESC_GET_PORT_INDEX(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucPortIdx_QueueIdx, TX_DESC_PORT_INDEX, TX_DESC_PORT_INDEX_OFFSET) +#define HAL_MAC_TX_DESC_SET_PORT_INDEX(_prHwMacTxDesc, _ucPortIndex) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucPortIdx_QueueIdx), \ + ((UINT_8)_ucPortIndex), TX_DESC_PORT_INDEX, TX_DESC_PORT_INDEX_OFFSET) + +/* DW 1 */ +#define HAL_MAC_TX_DESC_GET_WLAN_INDEX(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucWlanIdx) +#define HAL_MAC_TX_DESC_SET_WLAN_INDEX(_prHwMacTxDesc, _ucWlanIdx) \ + (((_prHwMacTxDesc)->ucWlanIdx) = (_ucWlanIdx)) + +#define HAL_MAC_TX_DESC_IS_LONG_FORMAT(_prHwMacTxDesc) (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_FORMAT)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_LONG_FORMAT(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_FORMAT) +#define HAL_MAC_TX_DESC_SET_SHORT_FORMAT(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_FORMAT) + +#define HAL_MAC_TX_DESC_GET_HEADER_FORMAT(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucHeaderFormat, \ + TX_DESC_HEADER_FORMAT_MASK, TX_DESC_HEADER_FORMAT_OFFSET) +#define HAL_MAC_TX_DESC_SET_HEADER_FORMAT(_prHwMacTxDesc, _ucHdrFormat) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucHeaderFormat), \ + ((UINT_8)_ucHdrFormat), TX_DESC_HEADER_FORMAT_MASK, TX_DESC_HEADER_FORMAT_OFFSET) + +/* HF = 0x00, 802.11 normal mode */ +#define HAL_MAC_TX_DESC_IS_MORE_DATA(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_NON_802_11_MORE_DATA)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_MORE_DATA(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_NON_802_11_MORE_DATA) +#define HAL_MAC_TX_DESC_UNSET_MORE_DATA(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_NON_802_11_MORE_DATA) + +#define HAL_MAC_TX_DESC_IS_REMOVE_VLAN(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_NON_802_11_REMOVE_VLAN)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_REMOVE_VLAN(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_NON_802_11_REMOVE_VLAN) +#define HAL_MAC_TX_DESC_UNSET_REMOVE_VLAN(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_NON_802_11_REMOVE_VLAN) + +#define HAL_MAC_TX_DESC_IS_VLAN(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_NON_802_11_VLAN_FIELD)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_VLAN(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_NON_802_11_VLAN_FIELD) +#define HAL_MAC_TX_DESC_UNSET_VLAN(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_NON_802_11_VLAN_FIELD) + +#define HAL_MAC_TX_DESC_IS_ETHERNET_II(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_NON_802_11_ETHERNET_II)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_ETHERNET_II(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_NON_802_11_ETHERNET_II) +#define HAL_MAC_TX_DESC_UNSET_ETHERNET_II(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_NON_802_11_ETHERNET_II) + +/* HF = 0x00/0x11, 802.11 normal/enhancement mode */ +#define HAL_MAC_TX_DESC_IS_EOSP(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_NON_802_11_EOSP)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_EOSP(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_NON_802_11_EOSP) +#define HAL_MAC_TX_DESC_UNSET_EOSP(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_NON_802_11_EOSP) + +/* HF = 0x11, 802.11 enhancement mode */ +#define HAL_MAC_TX_DESC_IS_AMSDU(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_ENH_802_11_AMSDU)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_AMSDU(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_ENH_802_11_AMSDU) +#define HAL_MAC_TX_DESC_UNSET_AMSDU(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_ENH_802_11_AMSDU) + +/* HF = 0x10, non-802.11 */ +#define HAL_MAC_TX_DESC_GET_802_11_HEADER_LENGTH(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucHeaderFormat, \ + TX_DESC_NOR_802_11_HEADER_LENGTH_MASK, TX_DESC_NOR_802_11_HEADER_LENGTH_OFFSET) +#define HAL_MAC_TX_DESC_SET_802_11_HEADER_LENGTH(_prHwMacTxDesc, _ucHdrLength) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucHeaderFormat), \ + ((UINT_8)_ucHdrLength), TX_DESC_NOR_802_11_HEADER_LENGTH_MASK, TX_DESC_NOR_802_11_HEADER_LENGTH_OFFSET) + +#define HAL_MAC_TX_DESC_GET_HEADER_PADDING(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucHeaderPadding, \ + TX_DESC_HEADER_PADDING_LENGTH_MASK, TX_DESC_HEADER_PADDING_LENGTH_OFFSET) +#define HAL_MAC_TX_DESC_SET_HEADER_PADDING(_prHwMacTxDesc, _ucHdrPadding) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucHeaderPadding), \ + ((UINT_8)_ucHdrPadding), TX_DESC_HEADER_PADDING_LENGTH_MASK, TX_DESC_HEADER_PADDING_LENGTH_OFFSET) + +#define HAL_MAC_TX_DESC_IS_HEADER_PADDING_IN_THE_HEAD(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderPadding & TX_DESC_HEADER_PADDING_MODE)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_HEADER_PADDING_IN_THE_HEAD(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderPadding |= TX_DESC_HEADER_PADDING_MODE) +#define HAL_MAC_TX_DESC_SET_HEADER_PADDING_IN_THE_TAIL(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderPadding &= ~TX_DESC_HEADER_PADDING_MODE) + +#define HAL_MAC_TX_DESC_IS_NO_ACK(_prHwMacTxDesc) (((_prHwMacTxDesc)->ucHeaderPadding & TX_DESC_NO_ACK)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_NO_ACK(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucHeaderPadding |= TX_DESC_NO_ACK) +#define HAL_MAC_TX_DESC_UNSET_NO_ACK(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucHeaderPadding &= ~TX_DESC_NO_ACK) + +#define HAL_MAC_TX_DESC_GET_TID(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucHeaderPadding, TX_DESC_TID_MASK, TX_DESC_TID_OFFSET) +#define HAL_MAC_TX_DESC_SET_TID(_prHwMacTxDesc, _ucTID) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucHeaderPadding), ((UINT_8)_ucTID), TX_DESC_TID_MASK, TX_DESC_TID_OFFSET) + +#define HAL_MAC_TX_DESC_IS_PROTECTION(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderPadding & TX_DESC_PROTECTED_FRAME)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_PROTECTION(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderPadding |= TX_DESC_PROTECTED_FRAME) +#define HAL_MAC_TX_DESC_UNSET_PROTECTION(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderPadding &= ~TX_DESC_PROTECTED_FRAME) + +#define HAL_MAC_TX_DESC_GET_OWN_MAC_INDEX(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucOwnMAC, TX_DESC_OWN_MAC_MASK, TX_DESC_OWN_MAC_OFFSET) +#define HAL_MAC_TX_DESC_SET_OWN_MAC_INDEX(_prHwMacTxDesc, _ucOwnMacIdx) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucOwnMAC), ((UINT_8)_ucOwnMacIdx), \ + TX_DESC_OWN_MAC_MASK, TX_DESC_OWN_MAC_OFFSET) + +/* DW 2 */ +#define HAL_MAC_TX_DESC_GET_SUB_TYPE(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucType_SubType, TX_DESC_SUB_TYPE_MASK, TX_DESC_SUB_TYPE_OFFSET) +#define HAL_MAC_TX_DESC_SET_SUB_TYPE(_prHwMacTxDesc, _ucSubType) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucType_SubType), \ + ((UINT_8)_ucSubType), TX_DESC_SUB_TYPE_MASK, TX_DESC_SUB_TYPE_OFFSET) + +#define HAL_MAC_TX_DESC_GET_TYPE(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucType_SubType, TX_DESC_TYPE_MASK, TX_DESC_TYPE_OFFSET) +#define HAL_MAC_TX_DESC_SET_TYPE(_prHwMacTxDesc, _ucType) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucType_SubType), ((UINT_8)_ucType), TX_DESC_TYPE_MASK, TX_DESC_TYPE_OFFSET) + +#define HAL_MAC_TX_DESC_IS_NDP(_prHwMacTxDesc) (((_prHwMacTxDesc)->ucType_SubType & TX_DESC_NDP)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_NDP(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucType_SubType |= TX_DESC_NDP) +#define HAL_MAC_TX_DESC_UNSET_NDP(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucType_SubType &= ~TX_DESC_NDP) + +#define HAL_MAC_TX_DESC_IS_NDPA(_prHwMacTxDesc) (((_prHwMacTxDesc)->ucType_SubType & TX_DESC_NDPA)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_NDPA(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucType_SubType |= TX_DESC_NDPA) +#define HAL_MAC_TX_DESC_UNSET_NDPA(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucType_SubType &= ~TX_DESC_NDPA) + +#define HAL_MAC_TX_DESC_IS_SOUNDING_FRAME(_prHwMacTxDesc) (((_prHwMacTxDesc)->ucFrag & TX_DESC_SOUNDING)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_SOUNDING_FRAME(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucFrag |= TX_DESC_SOUNDING) +#define HAL_MAC_TX_DESC_UNSET_SOUNDING_FRAME(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucFrag &= ~TX_DESC_SOUNDING) + +#define HAL_MAC_TX_DESC_IS_FORCE_RTS_CTS_EN(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucFrag & TX_DESC_FORCE_RTS_CTS)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_FORCE_RTS_CTS(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucFrag |= TX_DESC_FORCE_RTS_CTS) +#define HAL_MAC_TX_DESC_UNSET_FORCE_RTS_CTS(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucFrag &= ~TX_DESC_FORCE_RTS_CTS) + +#define HAL_MAC_TX_DESC_IS_BMC(_prHwMacTxDesc) (((_prHwMacTxDesc)->ucFrag & TX_DESC_BROADCAST_MULTICAST)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_BMC(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucFrag |= TX_DESC_BROADCAST_MULTICAST) +#define HAL_MAC_TX_DESC_UNSET_BMC(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucFrag &= ~TX_DESC_BROADCAST_MULTICAST) + +#define HAL_MAC_TX_DESC_IS_BIP(_prHwMacTxDesc) (((_prHwMacTxDesc)->ucFrag & TX_DESC_BIP_PROTECTED)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_BIP(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucFrag |= TX_DESC_BIP_PROTECTED) +#define HAL_MAC_TX_DESC_UNSET_BIP(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucFrag &= ~TX_DESC_BIP_PROTECTED) + +#define HAL_MAC_TX_DESC_IS_DURATION_CONTROL_BY_SW(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucFrag & TX_DESC_DURATION_FIELD_CONTROL)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_DURATION_CONTROL_BY_SW(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucFrag |= TX_DESC_DURATION_FIELD_CONTROL) +#define HAL_MAC_TX_DESC_SET_DURATION_CONTROL_BY_HW(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucFrag &= ~TX_DESC_DURATION_FIELD_CONTROL) + +#define HAL_MAC_TX_DESC_IS_HTC_EXIST(_prHwMacTxDesc) (((_prHwMacTxDesc)->ucFrag & TX_DESC_HTC_EXISTS)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_HTC_EXIST(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucFrag |= TX_DESC_HTC_EXISTS) +#define HAL_MAC_TX_DESC_UNSET_HTC_EXIST(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucFrag &= ~TX_DESC_HTC_EXISTS) + +#define HAL_MAC_TX_DESC_IS_FRAG_PACKET(_prHwMacTxDesc) (((_prHwMacTxDesc)->ucFrag & TX_DESC_FRAGMENT_MASK)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_GET_FRAG_PACKET_POS(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucFrag, TX_DESC_FRAGMENT_MASK, TX_DESC_FRAGMENT_OFFSET) +#define HAL_MAC_TX_DESC_SET_FRAG_PACKET_POS(_prHwMacTxDesc, _ucFragPos) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucFrag), \ + ((UINT_8)_ucFragPos), TX_DESC_FRAGMENT_MASK, TX_DESC_FRAGMENT_OFFSET) + +/* For driver */ +/* in unit of 32TU */ +#define HAL_MAC_TX_DESC_GET_REMAINING_LIFE_TIME(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucRemainingMaxTxTime) +#define HAL_MAC_TX_DESC_SET_REMAINING_LIFE_TIME(_prHwMacTxDesc, _ucLifeTime) \ + ((_prHwMacTxDesc)->ucRemainingMaxTxTime = (_ucLifeTime)) +/* in unit of ms (minimal value is about 40ms) */ +#define HAL_MAC_TX_DESC_GET_REMAINING_LIFE_TIME_IN_MS(_prHwMacTxDesc) \ + (TU_TO_MSEC(HAL_MAC_TX_DESC_GET_REMAINING_LIFE_TIME(_prHwMacTxDesc) << TX_DESC_LIFE_TIME_UNIT_IN_POWER_OF_2)) +#define HAL_MAC_TX_DESC_SET_REMAINING_LIFE_TIME_IN_MS(_prHwMacTxDesc, _u4LifeTimeMs) \ + { \ + UINT_32 u4LifeTimeInUnit = \ + ((MSEC_TO_USEC(_u4LifeTimeMs) / USEC_PER_TU) >> TX_DESC_LIFE_TIME_UNIT_IN_POWER_OF_2); \ + if (u4LifeTimeInUnit >= BIT(8)) { \ + u4LifeTimeInUnit = BITS(0, 7); \ + } \ + else if ((_u4LifeTimeMs != TX_DESC_TX_TIME_NO_LIMIT) \ + && (u4LifeTimeInUnit == TX_DESC_TX_TIME_NO_LIMIT)) { \ + u4LifeTimeInUnit = 1; \ + } \ + HAL_MAC_TX_DESC_SET_REMAINING_LIFE_TIME(_prHwMacTxDesc, (UINT_8)u4LifeTimeInUnit); \ + } + +#define HAL_MAC_TX_DESC_GET_POWER_OFFSET(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucPowerOffset, TX_DESC_POWER_OFFSET_MASK, 0) +#define HAL_MAC_TX_DESC_SET_POWER_OFFSET(_prHwMacTxDesc, _ucPowerOffset) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucPowerOffset), ((UINT_8)_ucPowerOffset), TX_DESC_POWER_OFFSET_MASK, 0) + +#define HAL_MAC_TX_DESC_IS_BA_DISABLE(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPowerOffset & TX_DESC_BA_DISABLE)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_BA_DISABLE(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucPowerOffset |= TX_DESC_BA_DISABLE) +#define HAL_MAC_TX_DESC_SET_BA_ENABLE(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucPowerOffset &= ~TX_DESC_BA_DISABLE) + +#define HAL_MAC_TX_DESC_IS_TIMING_MEASUREMENT(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPowerOffset & TX_DESC_TIMING_MEASUREMENT)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_TIMING_MEASUREMENT(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset |= TX_DESC_TIMING_MEASUREMENT) +#define HAL_MAC_TX_DESC_UNSET_TIMING_MEASUREMENT(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset &= ~TX_DESC_TIMING_MEASUREMENT) + +#define HAL_MAC_TX_DESC_IS_FIXED_RATE_ENABLE(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPowerOffset & TX_DESC_FIXED_RATE)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_FIXED_RATE_ENABLE(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucPowerOffset |= TX_DESC_FIXED_RATE) +#define HAL_MAC_TX_DESC_SET_FIXED_RATE_DISABLE(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucPowerOffset &= ~TX_DESC_FIXED_RATE) + +/* DW 3 */ +#define HAL_MAC_TX_DESC_GET_SW_RESERVED(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->u2TxCountLimit, \ + TX_DESC_SW_RESERVED_MASK, TX_DESC_SW_RESERVED_OFFSET) +#define HAL_MAC_TX_DESC_SET_SW_RESERVED(_prHwMacTxDesc, _ucSwReserved) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2TxCountLimit), \ + ((UINT_8)_ucSwReserved), TX_DESC_SW_RESERVED_MASK, TX_DESC_SW_RESERVED_OFFSET) +#define HAL_MAC_TX_DESC_GET_TX_COUNT(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->u2TxCountLimit, \ + TX_DESC_TX_COUNT_MASK, TX_DESC_TX_COUNT_OFFSET) +#define HAL_MAC_TX_DESC_SET_TX_COUNT(_prHwMacTxDesc, _ucTxCountLimit) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2TxCountLimit), \ + ((UINT_8)_ucTxCountLimit), TX_DESC_TX_COUNT_MASK, TX_DESC_TX_COUNT_OFFSET) +#define HAL_MAC_TX_DESC_GET_REMAINING_TX_COUNT(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->u2TxCountLimit, \ + TX_DESC_REMAINING_TX_COUNT_MASK, TX_DESC_REMAINING_TX_COUNT_OFFSET) +#define HAL_MAC_TX_DESC_SET_REMAINING_TX_COUNT(_prHwMacTxDesc, _ucTxCountLimit) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2TxCountLimit), ((UINT_8)_ucTxCountLimit), \ + TX_DESC_REMAINING_TX_COUNT_MASK, TX_DESC_REMAINING_TX_COUNT_OFFSET) +#define HAL_MAC_TX_DESC_GET_SEQUENCE_NUMBER(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->u2SN, TX_DESC_SEQUENCE_NUMBER, 0) +#define HAL_MAC_TX_DESC_SET_SEQUENCE_NUMBER(_prHwMacTxDesc, _u2SN) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2SN), ((UINT_16)_u2SN), TX_DESC_SEQUENCE_NUMBER, 0) +#define HAL_MAC_TX_DESC_SET_HW_RESERVED(_prHwMacTxDesc, _ucHwReserved) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2SN), ((UINT_8)_ucHwReserved), \ + TX_DESC_HW_RESERVED_MASK, TX_DESC_HW_RESERVED_OFFSET) +#define HAL_MAC_TX_DESC_IS_TXD_SN_VALID(_prHwMacTxDesc) (((_prHwMacTxDesc)->u2SN & TX_DESC_SN_IS_VALID)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_TXD_SN_VALID(_prHwMacTxDesc) ((_prHwMacTxDesc)->u2SN |= TX_DESC_SN_IS_VALID) +#define HAL_MAC_TX_DESC_SET_TXD_SN_INVALID(_prHwMacTxDesc) ((_prHwMacTxDesc)->u2SN &= ~TX_DESC_SN_IS_VALID) + +#define HAL_MAC_TX_DESC_IS_TXD_PN_VALID(_prHwMacTxDesc) (((_prHwMacTxDesc)->u2SN & TX_DESC_PN_IS_VALID)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_TXD_PN_VALID(_prHwMacTxDesc) ((_prHwMacTxDesc)->u2SN |= TX_DESC_PN_IS_VALID) +#define HAL_MAC_TX_DESC_SET_TXD_PN_INVALID(_prHwMacTxDesc) ((_prHwMacTxDesc)->u2SN &= ~TX_DESC_PN_IS_VALID) + +#define HAL_MAC_TX_DESC_ASSIGN_SN_BY_SW(_prHwMacTxDesc, _u2SN) \ +{ \ + HAL_MAC_TX_DESC_SET_SEQUENCE_NUMBER(_prHwMacTxDesc, _u2SN); \ + HAL_MAC_TX_DESC_SET_TXD_SN_VALID(_prHwMacTxDesc); \ +} +#define HAL_MAC_TX_DESC_ASSIGN_SN_BY_HW(_prHwMacTxDesc) \ +{ \ + HAL_MAC_TX_DESC_SET_SEQUENCE_NUMBER(_prHwMacTxDesc, 0); \ + HAL_MAC_TX_DESC_SET_TXD_SN_INVALID(_prHwMacTxDesc); \ +} + +/* DW 4 */ +#define HAL_MAC_TX_DESC_GET_PN(_prHwMacTxDesc, _u4PN_0_31, _u2PN_32_47) \ +{ \ + ((UINT_32)_u4PN_0_31) = (_prHwMacTxDesc)->u4PN1; \ + ((UINT_16)_u2PN_32_47) = (_prHwMacTxDesc)->u2PN2; \ +} +#define HAL_MAC_TX_DESC_SET_PN(_prHwMacTxDesc, _u4PN_0_31, _u2PN_32_47) \ +{ \ + (_prHwMacTxDesc)->u4PN1 = ((UINT_32)_u4PN_0_31); \ + (_prHwMacTxDesc)->u2PN2 = ((UINT_16)_u2PN_32_47); \ +} + +#define HAL_MAC_TX_DESC_ASSIGN_PN_BY_SW(_prHwMacTxDesc, _u4PN_0_31, _u2PN_32_47) \ +{ \ + HAL_MAC_TX_DESC_SET_PN(_prHwMacTxDesc, _u4PN_0_31, _u2PN_32_47); \ + HAL_MAC_TX_DESC_SET_TXD_PN_VALID(_prHwMacTxDesc); \ +} +#define HAL_MAC_TX_DESC_ASSIGN_PSN_BY_HW(_prHwMacTxDesc) \ +{ \ + HAL_MAC_TX_DESC_SET_PN(_prHwMacTxDesc, 0, 0); \ + HAL_MAC_TX_DESC_SET_TXD_PN_INVALID(_prHwMacTxDesc); \ +} + +/* DW 5 */ +#define HAL_MAC_TX_DESC_GET_PID(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPID) +#define HAL_MAC_TX_DESC_SET_PID(_prHwMacTxDesc, _ucPID) \ + (((_prHwMacTxDesc)->ucPID) = (_ucPID)) + +#define HAL_MAC_TX_DESC_GET_TXS_FORMAT(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucTxStatus, TX_DESC_TX_STATUS_FORMAT, TX_DESC_TX_STATUS_FORMAT_OFFSET) +#define HAL_MAC_TX_DESC_SET_TXS_FORMAT(_prHwMacTxDesc, _ucTXSFormat) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucTxStatus), \ + ((UINT_8)_ucTXSFormat), TX_DESC_TX_STATUS_FORMAT, TX_DESC_TX_STATUS_FORMAT_OFFSET) + +#define HAL_MAC_TX_DESC_IS_TXS_TO_MCU(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucTxStatus & TX_DESC_TX_STATUS_TO_MCU)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_TXS_TO_MCU(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucTxStatus |= TX_DESC_TX_STATUS_TO_MCU) +#define HAL_MAC_TX_DESC_UNSET_TXS_TO_MCU(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucTxStatus &= ~TX_DESC_TX_STATUS_TO_MCU) + +#define HAL_MAC_TX_DESC_IS_TXS_TO_HOST(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucTxStatus & TX_DESC_TX_STATUS_TO_HOST)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_TXS_TO_HOST(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucTxStatus |= TX_DESC_TX_STATUS_TO_HOST) +#define HAL_MAC_TX_DESC_UNSET_TXS_TO_HOST(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucTxStatus &= ~TX_DESC_TX_STATUS_TO_HOST) + +#define HAL_MAC_TX_DESC_IS_DA_FROM_WTBL(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPowerOffset & TX_DESC_DA_SOURCE)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_DA_FROM_WTBL(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucPowerOffset |= TX_DESC_DA_SOURCE) +#define HAL_MAC_TX_DESC_SET_DA_FROM_MSDU(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucPowerOffset &= ~TX_DESC_DA_SOURCE) + +#define HAL_MAC_TX_DESC_IS_SW_BAR_SSN(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPowerOffset & TX_DESC_BAR_SSN_CONTROL)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_SW_BAR_SSN(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset |= TX_DESC_BAR_SSN_CONTROL) +#define HAL_MAC_TX_DESC_SET_HW_BAR_SSN(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset &= ~TX_DESC_BAR_SSN_CONTROL) + +#define HAL_MAC_TX_DESC_IS_SW_PM_CONTROL(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPowerOffset & TX_DESC_POWER_MANAGEMENT_CONTROL)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_SW_PM_CONTROL(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset |= TX_DESC_POWER_MANAGEMENT_CONTROL) +#define HAL_MAC_TX_DESC_SET_HW_PM_CONTROL(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset &= ~TX_DESC_POWER_MANAGEMENT_CONTROL) + +/* DW 6 */ +#define HAL_MAC_TX_DESC_IS_CR_FIXED_RATE_MODE(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucAntID & TX_DESC_FIXED_RATE_MODE)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_FIXED_RATE_MODE_TO_DESC(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucAntID &= ~TX_DESC_FIXED_RATE_MODE) +#define HAL_MAC_TX_DESC_SET_FIXED_RATE_MODE_TO_CR(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucAntID |= TX_DESC_FIXED_RATE_MODE) + +#define HAL_MAC_TX_DESC_SET_FR_ANTENNA_ID(_prHwMacTxDesc, _ucAntId) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucAntID), ((UINT_8)_ucAntId), TX_DESC_ANTENNA_INDEX_MASK, 2) + +#define HAL_MAC_TX_DESC_SET_FR_BW(_prHwMacTxDesc, ucBw) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucBandwidth), ((UINT_8)ucBw), TX_DESC_BANDWIDTH_MASK, 0) + +#define HAL_MAC_TX_DESC_SET_FR_SPE_EN(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucBandwidth |= TX_DESC_BANDWIDTH_MASK) + +#define HAL_MAC_TX_DESC_SET_FR_ANTENNA_PRIORITY(_prHwMacTxDesc, _ucAntPri) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucBandwidth), ((UINT_8)_ucAntPri), TX_DESC_ANTENNA_PRIORITY, 4) + +#define HAL_MAC_TX_DESC_SET_FR_DYNAMIC_BW_RTS(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucBandwidth |= TX_DESC_DYNAMIC_BANDWIDTH) + +#define HAL_MAC_TX_DESC_SET_FR_ETX_BF(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2FixedRate |= TX_DESC_EXPLICIT_BEAMFORMING) + +#define HAL_MAC_TX_DESC_SET_FR_ITX_BF(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2FixedRate |= TX_DESC_IMPLICIT_BEAMFORMING) + +#define HAL_MAC_TX_DESC_SET_FR_RATE(_prHwMacTxDesc, _u2RatetoFixed) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2FixedRate), ((UINT_8)_u2RatetoFixed), TX_DESC_FIXDE_RATE_MASK, 2) + +#define HAL_MAC_TX_DESC_SET_FR_LDPC(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2FixedRate |= TX_DESC_LDPC) + +#define HAL_MAC_TX_DESC_SET_FR_SHORT_GI(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2FixedRate |= TX_DESC_GUARD_INTERVAL) + +#define HAL_MAC_TX_DESC_SET_FR_NORMAL_GI(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2FixedRate &= ~TX_DESC_GUARD_INTERVAL) + +#define HAL_MAC_TX_DESC_SET_FIX_RATE(_BssInfo) \ + (((_BssInfo->u2HwDefaultFixedRateCode << 2) & TX_DESC_FIXDE_RATE_MASK) << 16) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID nicTxInitialize(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS nicTxAcquireResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC, IN UINT_8 ucPageCount); + +WLAN_STATUS nicTxPollingResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC); + +BOOLEAN nicTxReleaseResource(IN P_ADAPTER_T prAdapter, IN UINT_16 *au2TxRlsCnt); + +BOOLEAN nicTxReleaseTCResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC, IN UINT_16 u2ReleasePageCnt); + +VOID nicTxReleaseMsduResource(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead); + +WLAN_STATUS nicTxResetResource(IN P_ADAPTER_T prAdapter); + +UINT_16 nicTxGetResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC); + +UINT_8 nicTxGetFrameResourceType(IN UINT_8 eFrameType, IN P_MSDU_INFO_T prMsduInfo); + +UINT_8 nicTxGetCmdResourceType(IN P_CMD_INFO_T prCmdInfo); + +VOID +nicTxFillDesc(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, OUT PUINT_8 prTxDescBuffer, OUT PUINT_8 pucTxDescLength); + +VOID +nicTxComposeSecurityFrameDesc(IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, OUT PUINT_8 prTxDescBuffer, OUT PUINT_8 pucTxDescLength); + +WLAN_STATUS nicTxMsduInfoList(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead); + +#if CFG_SUPPORT_MULTITHREAD +WLAN_STATUS nicTxMsduInfoListMthread(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead); + +UINT_32 nicTxMsduQueueMthread(IN P_ADAPTER_T prAdapter); +#endif + +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, IN BOOLEAN fgProcTxDoneHandler); + +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); + +WLAN_STATUS nicTxInitResetResource(IN P_ADAPTER_T prAdapter); +#endif + +WLAN_STATUS nicTxEnqueueMsdu(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +UINT_8 nicTxGetWlanIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, IN UINT_8 ucStaRecIdx); + +BOOLEAN nicTxIsMgmtResourceEnough(IN P_ADAPTER_T prAdapter); + +UINT_32 nicTxGetFreeCmdCount(IN P_ADAPTER_T prAdapter); + +UINT_8 nicTxGetPageCount(IN UINT_32 u4FrameLength, IN BOOLEAN fgIncludeDesc); + +UINT_8 nicTxGetCmdPageCount(IN P_CMD_INFO_T prCmdInfo); + +WLAN_STATUS nicTxGenerateDescTemplate(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +VOID nicTxFreeDescTemplate(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +VOID +nicTxSetMngPacket(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN UINT_8 ucBssIndex, + IN UINT_8 ucStaRecIndex, + IN UINT_8 ucMacHeaderLength, + IN UINT_16 u2FrameLength, IN PFN_TX_DONE_HANDLER pfTxDoneHandler, IN UINT_8 ucRateMode); + +VOID +nicTxSetDataPacket(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN UINT_8 ucBssIndex, + IN UINT_8 ucStaRecIndex, + IN UINT_8 ucMacHeaderLength, + IN UINT_16 u2FrameLength, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler, + IN UINT_8 ucRateMode, + IN ENUM_TX_PACKET_SRC_T eSrc, IN UINT_8 ucTID, IN BOOLEAN fgIs802_11Frame, IN BOOLEAN fgIs1xFrame); + +VOID nicTxFillDescByPktOption(IN P_MSDU_INFO_T prMsduInfo, IN P_HW_MAC_TX_DESC_T prTxDesc); + +VOID nicTxConfigPktOption(IN P_MSDU_INFO_T prMsduInfo, IN UINT_32 u4OptionMask, IN BOOLEAN fgSetOption); + +VOID nicTxFillDescByPktControl(P_MSDU_INFO_T prMsduInfo, P_HW_MAC_TX_DESC_T prTxDesc); + +VOID nicTxConfigPktControlFlag(IN P_MSDU_INFO_T prMsduInfo, IN UINT_8 ucControlFlagMask, IN BOOLEAN fgSetFlag); + +VOID nicTxSetPktLifeTime(IN P_MSDU_INFO_T prMsduInfo, IN UINT_32 u4TxLifeTimeInMs); + +VOID nicTxSetPktRetryLimit(IN P_MSDU_INFO_T prMsduInfo, IN UINT_8 ucRetryLimit); + +VOID nicTxSetPktPowerOffset(IN P_MSDU_INFO_T prMsduInfo, IN INT_8 cPowerOffset); + +VOID nicTxSetPktSequenceNumber(IN P_MSDU_INFO_T prMsduInfo, IN UINT_16 u2SN); + +VOID nicTxSetPktMacTxQue(IN P_MSDU_INFO_T prMsduInfo, IN UINT_8 ucMacTxQue); + +VOID +nicTxSetPktFixedRateOptionFull(IN P_MSDU_INFO_T prMsduInfo, + IN UINT_16 u2RateCode, + IN UINT_8 ucBandwidth, + IN BOOLEAN fgShortGI, + IN BOOLEAN fgLDPC, + IN BOOLEAN fgDynamicBwRts, + IN BOOLEAN fgSpatialExt, + IN BOOLEAN fgEtxBeamforming, + IN BOOLEAN fgItxBeamforming, IN UINT_8 ucAntennaIndex, IN UINT_8 ucAntennaPriority); + +VOID +nicTxSetPktFixedRateOption(IN P_MSDU_INFO_T prMsduInfo, + IN UINT_16 u2RateCode, + IN UINT_8 ucBandwidth, IN BOOLEAN fgShortGI, IN BOOLEAN fgDynamicBwRts); + +VOID nicTxSetPktLowestFixedRate(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +VOID nicTxSetPktMoreData(IN P_MSDU_INFO_T prCurrentMsduInfo, IN BOOLEAN fgSetMoreDataBit); + +VOID nicTxSetPktEOSP(IN P_MSDU_INFO_T prCurrentMsduInfo, IN BOOLEAN fgSetEOSPBit); + +UINT_8 nicTxAssignPID(IN P_ADAPTER_T prAdapter, IN UINT_8 ucWlanIndex); + +WLAN_STATUS +nicTxDummyTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +VOID nicTxUpdateBssDefaultRate(IN P_BSS_INFO_T prBssInfo); + +VOID nicTxUpdateStaRecDefaultRate(IN P_STA_RECORD_T prStaRec); + +VOID +nicTxPrintMetRTP(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN P_NATIVE_PACKET prPacket, IN UINT_32 u4PacketLen, IN BOOLEAN bFreeSkb); + +VOID nicTxProcessTxDoneEvent(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); + +VOID nicTxChangeDataPortByAc(P_STA_RECORD_T prStaRec, UINT_8 ucAci, BOOLEAN fgToMcu); + +VOID nicTxHandleRoamingDone(P_ADAPTER_T prAdapter, P_STA_RECORD_T prOldStaRec, P_STA_RECORD_T prNewStaRec); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _NIC_TX_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/p2p.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/p2p.h new file mode 100644 index 0000000000000..5a93184431824 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/p2p.h @@ -0,0 +1,334 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/nic/p2p.h#3 + */ + +#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 + +/* Device Capability Definition. */ +#define P2P_MAXIMUM_CLIENT_COUNT 10 +#define P2P_MAXIMUM_NOA_COUNT 8 + +#define P2P_MAX_AKM_SUITES 2 + +#define P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE 51 /* Contains 6 sub-band. */ + +/* Memory Size Definition. */ +#define P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE 768 +#define WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE 300 + +#define P2P_WILDCARD_SSID "DIRECT-" + +/* Device Charactoristic. */ +#define P2P_AP_CHNL_HOLD_TIME_MS 5000 /* 1000 is too short , the deauth would block in the queue */ +#define P2P_DEFAULT_LISTEN_CHANNEL 1 + +#define AP_DEFAULT_CHANNEL_2G 6 +#define AP_DEFAULT_CHANNEL_5G 36 + +/******************************************************************************* + * M A C R O S + ******************************************************************************** + */ + +#define p2pChangeMediaState(_prAdapter, _prP2pBssInfo, _eNewMediaState) \ + (_prP2pBssInfo->eConnectionState = (_eNewMediaState)) + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************** + */ + +/* if driver need wait for a longger time when do p2p connection */ +typedef enum _ENUM_P2P_CONNECT_STATE_T { + P2P_CNN_NORMAL = 0, + P2P_CNN_GO_NEG_REQ, + P2P_CNN_GO_NEG_RESP, + P2P_CNN_GO_NEG_CONF, + P2P_CNN_INVITATION_REQ, + P2P_CNN_INVITATION_RESP, + P2P_CNN_DEV_DISC_REQ, + P2P_CNN_DEV_DISC_RESP, + P2P_CNN_PROV_DISC_REQ, + P2P_CNN_PROV_DISC_RES +} ENUM_P2P_CNN_STATE_T, *P_ENUM_P2P_CNN_STATE_T; + +struct _P2P_INFO_T { + UINT_32 u4DeviceNum; + ENUM_P2P_CNN_STATE_T eConnState; + EVENT_P2P_DEV_DISCOVER_RESULT_T arP2pDiscoverResult[CFG_MAX_NUM_BSS_LIST]; + PUINT_8 pucCurrIePtr; + UINT_32 u4EapWscDoneTxTime; + BOOL fgWaitEapFailure; + UINT_8 aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN]; /* A common pool for IE of all scan results. */ + UINT_8 ucExtendChanFlag; +}; + +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; + +typedef struct _P2P_SSID_STRUCT_T { + UINT_8 aucSsid[32]; + UINT_8 ucSsidLen; +} P2P_SSID_STRUCT_T, *P_P2P_SSID_STRUCT_T; + +enum ENUM_SCAN_REASON { + SCAN_REASON_UNKNOWN = 0, + SCAN_REASON_CONNECT, + SCAN_REASON_STARTAP, + SCAN_REASON_ACS, + SCAN_REASON_NUM, +}; + +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]; + UINT_8 ucSsidNum; + enum ENUM_SCAN_REASON eScanReason; + P2P_SSID_STRUCT_T arSsidStruct[SCN_SSID_MAX_NUM]; /* Currently we can only take one SSID scan request */ +} P2P_SCAN_REQ_INFO_T, *P_P2P_SCAN_REQ_INFO_T; + +enum P2P_VENDOR_ACS_HW_MODE { + P2P_VENDOR_ACS_HW_MODE_11B, + P2P_VENDOR_ACS_HW_MODE_11G, + P2P_VENDOR_ACS_HW_MODE_11A, + P2P_VENDOR_ACS_HW_MODE_11AD, + P2P_VENDOR_ACS_HW_MODE_11ANY +}; + +struct P2P_ACS_REQ_INFO { + UINT_8 ucRoleIdx; + BOOLEAN fgIsProcessing; + BOOLEAN fgIsHtEnable; + BOOLEAN fgIsHt40Enable; + BOOLEAN fgIsVhtEnable; + ENUM_MAX_BANDWIDTH_SETTING eChnlBw; + enum P2P_VENDOR_ACS_HW_MODE eHwMode; + UINT_32 u4LteSafeChnMask_2G; + UINT_32 u4LteSafeChnMask_5G_1; + UINT_32 u4LteSafeChnMask_5G_2; + + /* output only */ + UINT_8 ucPrimaryCh; + UINT_8 ucSecondCh; + UINT_8 ucCenterFreqS1; + UINT_8 ucCenterFreqS2; +}; + +typedef struct _P2P_CHNL_REQ_INFO_T { + LINK_T rP2pChnlReqLink; + BOOLEAN fgIsChannelRequested; + UINT_8 ucSeqNumOfChReq; + UINT_64 u8Cookie; + UINT_8 ucReqChnlNum; + ENUM_BAND_T eBand; + ENUM_CHNL_EXT_T eChnlSco; + UINT_8 ucOriChnlNum; + ENUM_CHANNEL_WIDTH_T eChannelWidth; /*VHT operation ie */ + UINT_8 ucCenterFreqS1; + UINT_8 ucCenterFreqS2; + ENUM_BAND_T eOriBand; + ENUM_CHNL_EXT_T eOriChnlSco; + UINT_32 u4MaxInterval; + ENUM_CH_REQ_TYPE_T eChnlReqType; +#if CFG_SUPPORT_NFC_BEAM_PLUS + UINT_32 NFC_BEAM; /*NFC Beam + Indication */ +#endif +} P2P_CHNL_REQ_INFO_T, *P_P2P_CHNL_REQ_INFO_T; + +/* Glubal Connection Settings. */ +struct _P2P_CONNECTION_SETTINGS_T { + UINT_8 ucRfChannelListSize; +#if P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE + UINT_8 aucChannelEntriesField[P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE]; +#endif + + BOOLEAN fgIsApMode; +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + BOOLEAN fgIsWPSMode; +#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; + +struct _P2P_SPECIFIC_BSS_INFO_T { + /* For GO(AP) Mode - Compose TIM IE */ + UINT_16 u2SmallestAID; + UINT_16 u2LargestAID; + UINT_8 ucBitmapCtrl; + /* UINT_8 aucPartialVirtualBitmap[MAX_LEN_TIM_PARTIAL_BMP]; */ + + /* For GC/GO OppPS */ + BOOLEAN fgEnableOppPS; + UINT_16 u2CTWindow; + + /* For GC/GO NOA */ + UINT_8 ucNoAIndex; + UINT_8 ucNoATimingCount; /* Number of NoA Timing */ + NOA_TIMING_T arNoATiming[P2P_MAXIMUM_NOA_COUNT]; + + BOOLEAN fgIsNoaAttrExisted; + + /* For P2P Device */ + UINT_8 ucRegClass; /* Regulatory Class for channel. */ + UINT_8 ucListenChannel; /* + * Linten Channel only on channels 1, 6 and 11 + * in the 2.4 GHz. + */ + + UINT_8 ucPreferredChannel; /* + * Operating Channel, should be one of channel + * list in p2p connection settings. + */ + ENUM_CHNL_EXT_T eRfSco; + ENUM_BAND_T eRfBand; + + /* Extended Listen Timing. */ + UINT_16 u2AvailabilityPeriod; + UINT_16 u2AvailabilityInterval; + + UINT_16 u2AttributeLen; + UINT_8 aucAttributesCache[P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; + + UINT_16 u2WscAttributeLen; + UINT_8 aucWscAttributesCache[WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; + + UINT_8 aucGroupID[MAC_ADDR_LEN]; + UINT_16 u2GroupSsidLen; + UINT_8 aucGroupSsid[ELEM_MAX_LEN_SSID]; + + PARAM_CUSTOM_NOA_PARAM_STRUCT_T rNoaParam; + PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T rOppPsParam; + + UINT_32 u4KeyMgtSuiteCount; + UINT_32 au4KeyMgtSuite[P2P_MAX_AKM_SUITES]; + + UINT_16 u2WpaIeLen; + UINT_8 aucWpaIeBuffer[ELEM_HDR_LEN + ELEM_MAX_LEN_WPA]; +}; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************** + */ + +#endif /*_P2P_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/p2p_cmd_buf.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/p2p_cmd_buf.h new file mode 100644 index 0000000000000..9e9079270013a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/p2p_cmd_buf.h @@ -0,0 +1,79 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** 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. + */ + +#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, IN UINT_8 ucCID, IN UINT_8 ucBssIdx, + IN BOOLEAN fgSetQuery, IN BOOLEAN fgNeedResp, IN BOOLEAN fgIsOid, + IN PFN_CMD_DONE_HANDLER pfCmdDoneHandler, IN PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + IN UINT_32 u4SetQueryInfoLen, IN PUINT_8 pucInfoBuffer, + OUT PVOID pvSetQueryBuffer, IN UINT_32 u4SetQueryBufferLen); + +#endif /* _P2P_CMD_BUF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/p2p_mac.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/p2p_mac.h new file mode 100644 index 0000000000000..fd69d372af59d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/p2p_mac.h @@ -0,0 +1,402 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * ! \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 + ******************************************************************************** + */ + +/* --------------- 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 + +/* --------------- 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 */ +#define P2P_ATTRI_MAX_LEN_LISTEN_CHANNEL 5 /* 6 */ +#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_MAXIMUM_ATTRIBUTE_LEN 251 + +/* 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.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) +/* Action frame categories (IEEE 802.11-2007, 7.3.1.11, Table 7-24) */ +#define WLAN_ACTION_SPECTRUM_MGMT 0 +#define WLAN_ACTION_QOS 1 +#define WLAN_ACTION_DLS 2 +#define WLAN_ACTION_BLOCK_ACK 3 +#define WLAN_ACTION_PUBLIC 4 +#define WLAN_ACTION_RADIO_MEASUREMENT 5 +#define WLAN_ACTION_FT 6 +#define WLAN_ACTION_HT 7 +#define WLAN_ACTION_SA_QUERY 8 +#define WLAN_ACTION_PROTECTED_DUAL 9 +#define WLAN_ACTION_WNM 10 +#define WLAN_ACTION_UNPROTECTED_WNM 11 +#define WLAN_ACTION_TDLS 12 +#define WLAN_ACTION_SELF_PROTECTED 15 +#define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */ +#define WLAN_ACTION_VENDOR_SPECIFIC 127 +#define P2P_IE_VENDOR_TYPE 0x506f9a09 +#define WFD_IE_VENDOR_TYPE 0x506f9a0a + +/* Public action codes */ +#define WLAN_PA_20_40_BSS_COEX 0 +#define WLAN_PA_VENDOR_SPECIFIC 9 +#define WLAN_PA_GAS_INITIAL_REQ 10 +#define WLAN_PA_GAS_INITIAL_RESP 11 +#define WLAN_PA_GAS_COMEBACK_REQ 12 +#define WLAN_PA_GAS_COMEBACK_RESP 13 +#define WLAN_TDLS_DISCOVERY_RESPONSE 14 + +/* P2P public action frames */ +typedef enum p2p_action_frame_type { + P2P_GO_NEG_REQ = 0, + P2P_GO_NEG_RESP = 1, + P2P_GO_NEG_CONF = 2, + P2P_INVITATION_REQ = 3, + P2P_INVITATION_RESP = 4, + P2P_DEV_DISC_REQ = 5, + P2P_DEV_DISC_RESP = 6, + P2P_PROV_DISC_REQ = 7, + P2P_PROV_DISC_RESP = 8 +} ENUM_P2P_ACTION_TYPE; +/* --------------- 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 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; + +/* 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.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.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; + +/* 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.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 _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; + +enum p2p_attr_id { + P2P_ATTR_STATE = 0, +}; + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/p2p_nic.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/p2p_nic.h new file mode 100644 index 0000000000000..30791d640d0fb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/p2p_nic.h @@ -0,0 +1,75 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** 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 UINT_8 ucBssIndex, IN P_EVENT_CONNECTION_STATUS prConnectionStatus); + +VOID +nicRxAddP2pDevice(IN P_ADAPTER_T prAdapter, IN P_EVENT_P2P_DEV_DISCOVER_RESULT_T prP2pResult, IN PUINT_8 pucRxIEBuf, IN + UINT_16 u2RxIELength); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/p2p_nic_cmd_event.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/p2p_nic_cmd_event.h new file mode 100644 index 0000000000000..ae70f31ea2dc6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/p2p_nic_cmd_event.h @@ -0,0 +1,84 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/nic/p2p_nic_cmd_event.h#1 +*/ + +/*! \file p2p_nic_cmd_event.h + * \brief + */ + +#ifndef _P2P_NIC_CMD_EVENT_H +#define _P2P_NIC_CMD_EVENT_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************** + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************** + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************** + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************** + */ + +typedef struct _EVENT_P2P_DEV_DISCOVER_RESULT_T { +/* UINT_8 aucCommunicateAddr[MAC_ADDR_LEN]; // Deprecated. */ + UINT_8 aucDeviceAddr[MAC_ADDR_LEN]; /* Device Address. */ + UINT_8 aucInterfaceAddr[MAC_ADDR_LEN]; /* Device Address. */ + UINT_8 ucDeviceCapabilityBitmap; + UINT_8 ucGroupCapabilityBitmap; + UINT_16 u2ConfigMethod; /* Configure Method. */ + P2P_DEVICE_TYPE_T rPriDevType; + UINT_8 ucSecDevTypeNum; + P2P_DEVICE_TYPE_T arSecDevType[2]; + UINT_16 u2NameLength; + UINT_8 aucName[32]; + PUINT_8 pucIeBuf; + UINT_16 u2IELength; + UINT_8 aucBSSID[MAC_ADDR_LEN]; + /* TODO: Service Information or PasswordID valid? */ +} EVENT_P2P_DEV_DISCOVER_RESULT_T, *P_EVENT_P2P_DEV_DISCOVER_RESULT_T; + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/que_mgt.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/que_mgt.h new file mode 100644 index 0000000000000..769e06b64c0e2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/que_mgt.h @@ -0,0 +1,1060 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/que_mgt.h#2 +*/ + +/* + * ! \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. + */ + +#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 + ******************************************************************************** + */ +extern UINT_8 g_arTdlsLink[MAXNUM_TDLS_PEER]; +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************** + */ + +/* Queue Manager Features */ +#define QM_BURST_END_INFO_ENABLED 0 /* 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_FAST_TC_RESOURCE_CTRL 1 /* 1: To fast adjust resource for EMPTY TC (assigned resource is 0) */ +#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 + */ +#define QM_TC_RESOURCE_EMPTY_COUNTER 1 /* 1: Count times of TC resource empty happened */ + +/* 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 0 +#define QM_MIN_RESERVED_TC1_RESOURCE 1 +#define QM_MIN_RESERVED_TC2_RESOURCE 0 +#define QM_MIN_RESERVED_TC3_RESOURCE 0 +#define QM_MIN_RESERVED_TC4_RESOURCE 2 /* Resource for TC4 is not adjustable */ +#define QM_MIN_RESERVED_TC5_RESOURCE 0 + +#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 + +#define QM_EXTRA_RESERVED_RESOURCE_WHEN_BUSY 0 + +#define QM_AVERAGE_TC_RESOURCE 6 + +#define QM_ACTIVE_TC_NUM TC_NUM + +#define QM_MGMT_QUEUED_THRESHOLD 6 +#define QM_CMD_RESERVED_THRESHOLD 4 +#define QM_MGMT_QUEUED_TIMEOUT 1000 /* ms */ + +#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] MGMT, [5] non-QoS */ +/* Per-Type Queues: [0] BMCAST */ +#define NUM_OF_PER_STA_TX_QUEUES 6 +#define NUM_OF_PER_TYPE_TX_QUEUES 1 + +/* TX Queue Index */ +/* Per-Type */ +#define TX_QUEUE_INDEX_BMCAST 0 +#define TX_QUEUE_INDEX_NO_STA_REC 0 + +/* Per-STA */ +#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_MGMT 4 +#define TX_QUEUE_INDEX_NON_QOS 5 + +#define QM_DEFAULT_USER_PRIORITY 0 + +#define QM_STA_FORWARD_COUNT_UNLIMITED 0xFFFFFFFF + +/* Pending Forwarding Frame Threshold: + * + * A conservative estimated value, to reserve enough free MSDU resource for OS packet, + * rather than full consumed by the pending forwarding frame. + * + * Indeed, even if network subqueue is not stopped when no MSDU resource, the new arriving + * skb will be queued in prGlueInfo->rTxQueue and not be dropped. + */ +#define QM_FWD_PKT_QUE_HIGH_THRESHOLD (CFG_TX_MAX_PKT_NUM - CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD) + +/* Pending Forwarding Frame Threshold for Low Priority Packet (BE/BK) + * + * For TGn AP 4.2.25 STEP 6, 11n STA transmits RTP1_BE and RTP2_VI streams to legacy STA, + * the bandwidth is full and large amounts of forwarding packets are pending in driver, we should + * drop the packet by priority, retain VI as much as possible. + */ +#define QM_FWD_PKT_QUE_LOW_THRESHOLD (QM_FWD_PKT_QUE_HIGH_THRESHOLD / 2) + +#define QM_RECENT_SSN_CACHE_NUM 10 +#define QM_INVALID_SSN 65535 + + +/* 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 DEFAULT_QM_RX_BA_ENTRY_MISS_TIMEOUT_MS (200) +#define SHORT_QM_RX_BA_ENTRY_MISS_TIMEOUT_MS (50) + +#if CFG_RX_BA_REORDERING_ENHANCEMENT +#define QM_RX_MAX_FW_DROP_SSN_SIZE 8 +#define QM_SSN_MASK 0xFFF0 +#endif + +#if CFG_M0VE_BA_TO_DRIVER +/* MQM internal control bitmap per-bit usage (for operations on g_prMqm->u4FlagBitmap) */ +#define MQM_FLAG_TSPEC_NEGO_ADD_IN_PROGRESS 0 +#define MQM_FLAG_IDLE_TX_BA_TIMER_STARTED 1 +#define MQM_FLAG_IDLE_RX_BA_TIMER_STARTED 2 + +#define MQM_IDLE_RX_BA_DETECTION 0 +#define MQM_IDLE_RX_BA_CHECK_INTERVAL 5000 /* in msec */ +#define MQM_DEL_IDLE_RXBA_THRESHOLD_BK 6 +#define MQM_DEL_IDLE_RXBA_THRESHOLD_BE 12 +#define MQM_DEL_IDLE_RXBA_THRESHOLD_VI 6 +#define MQM_DEL_IDLE_RXBA_THRESHOLD_VO 6 + +/* For indicating whether the role when generating a DELBA message */ +#define DELBA_ROLE_INITIATOR TRUE +#define DELBA_ROLE_RECIPIENT FALSE + +#define MQM_SET_FLAG(_Bitmap, _flag) { (_Bitmap) |= (BIT((_flag))); } +#define MQM_CLEAR_FLAG(_Bitmap, _flag) { (_Bitmap) &= (~BIT((_flag))); } +#define MQM_CHECK_FLAG(_Bitmap, _flag) ((_Bitmap) & (BIT((_flag)))) + +typedef enum _ENUM_BA_RESET_SEL_T { + MAC_ADDR_TID_MATCH = 0, + MAC_ADDR_MATCH, + ALWAYS_MATCH, + MATCH_NUM +} ENUM_BA_RESET_SEL_T; + +#endif + +/******************************************************************************* + * 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; +#if CFG_RX_BA_REORDERING_ENHANCEMENT + QUE_T rNoNeedWaitQue; +#endif + UINT_16 u2WinStart; + UINT_16 u2WinEnd; + UINT_16 u2WinSize; + + /* For identifying the RX BA agreement */ + UINT_8 ucStaRecIdx; + UINT_8 ucTid; + + BOOLEAN fgIsWaitingForPktWithSsn; + + TIMER_T rReorderBubbleTimer; + UINT_16 u2FirstBubbleSn; + BOOLEAN fgHasBubble; + +#if CFG_M0VE_BA_TO_DRIVER + UINT_8 ucStatus; + UINT_8 ucIdleCount; + UINT_16 u2SnapShotSN; +#endif + UINT_16 au2RecentSsn[QM_RECENT_SSN_CACHE_NUM]; + UINT_8 ucLastSlot; + /* UINT_8 ucTxBufferSize; */ + /* BOOL fgIsAcConstrain; */ + /* BOOL fgIsBaEnabled; */ +} RX_BA_ENTRY_T, *P_RX_BA_ENTRY_T; + +typedef UINT_32(*PFN_DEQUEUE_FUNCTION) (IN P_ADAPTER_T prAdapter, OUT P_QUE_T prQue, IN UINT_8 ucTC, IN UINT_32 + u4CurrentQuota, IN UINT_32 u4TotalQuota); + +/* 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 resource used count for a STA with respect to a TC index */ + UINT_32 au4ResourceUsedCount[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]; + + /* For TC5 only */ + BOOLEAN fgGlobalQFirst; + UINT_32 u4GlobalResourceUsedCount; +#endif + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + UINT_32 au4AverageQueLen[TC_NUM]; + UINT_32 au4CurrentTcResource[TC_NUM]; + UINT_32 au4MinReservedTcResource[TC_NUM]; /* The minimum amount of resource no matter busy or idle */ + UINT_32 au4GuaranteedTcResource[TC_NUM]; /* The minimum amount of resource when extremely busy */ + + UINT_32 u4TimeToAdjustTcResource; + UINT_32 u4TimeToUpdateQueLen; + + UINT_32 u4QueLenMovingAverage; + UINT_32 u4ExtraReservedTcResource; + UINT_32 u4ResidualTcResource; + + /* + * 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; + +#if QM_FAST_TC_RESOURCE_CTRL + BOOLEAN fgTcResourceFastReaction; +#endif + +#endif + +#if QM_DEBUG_COUNTER + UINT_32 au4QmDebugCounters[QM_DBG_CNT_NUM]; +#endif + + UINT_32 u4TxAllowedStaCount; + +#if QM_TC_RESOURCE_EMPTY_COUNTER + UINT_32 au4QmTcResourceEmptyCounter[MAX_BSS_INDEX + 1][TC_NUM]; + UINT_32 au4DequeueNoTcResourceCounter[TC_NUM]; + /* + * how many page count back during statistics intervals + */ + UINT_32 au4QmTcResourceBackCounter[TC_NUM]; + /* + * how many page count used to TX frame during statistics intervals + */ + UINT_32 au4QmTcUsedPageCounter[TC_NUM]; + UINT_32 au4QmTcWantedPageCounter[TC_NUM]; + + UINT_32 u4EnqueueCounter; + UINT_32 u4DequeueCounter; +#endif + + UINT_32 u4MaxForwardBuffer; + UINT_32 u4MaxForwardBufferForLowUP; + + OS_SYSTIME rLastTxPktDumpTime; +} 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 ucBssIndex; + UINT_8 ucIsAbsent; + 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; + UINT_8 ucIsInPs; + 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; + +typedef struct _EVENT_CHECK_REORDER_BUBBLE_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 ucTid; +} EVENT_CHECK_REORDER_BUBBLE_T, *P_EVENT_CHECK_REORDER_BUBBLE_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; + +typedef struct _WMM_AC_PARAM_T { + UINT_8 ucAciAifsn; + UINT_8 ucEcw; + UINT_16 u2TxopLimit; +} WMM_AC_PARAM_T, *P_WMM_AC_PARAM_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 */ +#if 1 + WMM_AC_PARAM_T arAcParam[4]; +#else + 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]; +#endif +} 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. */ + UINT_8 ucIsACMSet; +} 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; + +/* WMM QOS user priority from 802.1D/802.11e */ +enum ENUM_WMM_UP_T { + WMM_UP_BE_INDEX = 0, + WMM_UP_BK_INDEX, + WMM_UP_RESV_INDEX, + WMM_UP_EE_INDEX, + WMM_UP_CL_INDEX, + WMM_UP_VI_INDEX, + WMM_UP_VO_INDEX, + WMM_UP_NC_INDEX, + WMM_UP_INDEX_NUM +}; + +/* Used for CMD Queue Operation */ +typedef enum _ENUM_FRAME_ACTION_T { + FRAME_ACTION_DROP_PKT = 0, + FRAME_ACTION_QUEUE_PKT, + FRAME_ACTION_TX_PKT, + FRAME_ACTION_NUM +} ENUM_FRAME_ACTION_T; + +typedef enum _ENUM_FRAME_TYPE_IN_CMD_Q_T { + FRAME_TYPE_802_1X = 0, + FRAME_TYPE_MMPDU, + FRAME_TYPE_NUM +} ENUM_FRAME_TYPE_IN_CMD_Q_T; + +typedef enum _ENUM_FREE_QUOTA_MODET_T { + FREE_QUOTA_UPDATE_MODE_INIT = 0, + FREE_QUOTA_UPDATE_MODE_OVERWRITE, + FREE_QUOTA_UPDATE_MODE_INCREASE, + FREE_QUOTA_UPDATE_MODE_DECREASE +} ENUM_FREE_QUOTA_MODET_T, *P_ENUM_FREE_QUOTA_MODET_T; + +typedef struct _CMD_UPDATE_WMM_PARMS_T { + AC_QUE_PARMS_T arACQueParms[AC_NUM]; + UINT_8 ucBssIndex; + 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; + +#if CFG_M0VE_BA_TO_DRIVER +/* The status of an TX/RX BA entry in FW (NEGO means the negotiation process is in progress) */ +typedef enum _ENUM_BA_ENTRY_STATUS_T { + BA_ENTRY_STATUS_INVALID = 0, + BA_ENTRY_STATUS_NEGO, + BA_ENTRY_STATUS_ACTIVE, + BA_ENTRY_STATUS_DELETING +} ENUM_BA_ENTRY_STATUS_T, *P_ENUM_BA_ENTRY_STATUS_T; +#endif + +#if CFG_RX_BA_REORDERING_ENHANCEMENT +typedef enum _ENUM_NO_NEED_WATIT_DROP_REASON_T { + PACKET_DROP_BY_FW = 0, + PACKET_DROP_BY_DRIVER, + PACKET_DROP_BY_INDEPENDENT_PKT +} ENUM_NO_NEED_WATIT_DROP_REASON_T, *P_ENUM_NO_NEED_WATIT_DROP_REASON_T; + +typedef struct _NO_NEED_WAIT_PKT_T { + QUE_ENTRY_T rQueEntry; + UINT_16 u2SSN; + ENUM_NO_NEED_WATIT_DROP_REASON_T eDropReason; +} NO_NEED_WAIT_PKT_T, *P_NO_NEED_WAIT_PKT_T; + +typedef struct _EVENT_PACKET_DROP_BY_FW_T { + UINT_16 u2Length; + UINT_16 u2Reserved1; /* Must be filled with 0x0001 (EVENT Packet) */ + UINT_8 ucEID; + UINT_8 ucSeqNum; + UINT_8 aucReserved2[2]; + UINT_8 ucStaRecIdx; + UINT_8 ucTid; + UINT_16 u2StartSSN; + UINT_8 au1BitmapSSN[QM_RX_MAX_FW_DROP_SSN_SIZE]; +} EVENT_PACKET_DROP_BY_FW_T, *P_EVENT_PACKET_DROP_BY_FW_T; +#endif +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************** + */ + +#define 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) + +#if 0 +#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); \ + } +#else +#define QM_TX_SET_MSDU_INFO_FOR_DATA_PACKET( \ + _prMsduInfo, \ + _ucTC, \ + _ucPacketType, \ + _ucFormatID, \ + _fgIs802_1x, \ + _fgIs802_11, \ + _ucPsForwardingType \ + ) \ + { \ + ASSERT(_prMsduInfo); \ + (_prMsduInfo)->ucTC = (_ucTC); \ + (_prMsduInfo)->ucPacketType = (_ucPacketType); \ + (_prMsduInfo)->ucFormatID = (_ucFormatID); \ + (_prMsduInfo)->fgIs802_1x = (_fgIs802_1x); \ + (_prMsduInfo)->fgIs802_11 = (_fgIs802_11); \ + (_prMsduInfo)->ucPsForwardingType = (_ucPsForwardingType); \ + } +#endif + +#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)] >> (_prAdapter)->rQM.u4QueLenMovingAverage)) +#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 + +#if CFG_RX_BA_REORDERING_ENHANCEMENT +#define QM_GET_PREVIOUS_SSN(_u2CurrSSN) \ + ((UINT_16) (_u2CurrSSN == 0 ? (MAX_SEQ_NO_COUNT - 1) : (_u2CurrSSN - 1))) +#define QM_GET_DROP_BY_FW_SSN(_u2SSN) \ + ((UINT_16) (_u2SSN >>= 4)) +#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 P_STA_RECORD_T prStaRec); + +VOID qmUpdateStaRec(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +/*----------------------------------------------------------------------------*/ +/* 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); + +#if CFG_SUPPORT_MULTITHREAD +P_MSDU_INFO_T qmDequeueTxPacketsMthread(IN P_ADAPTER_T prAdapter, IN P_TX_TCQ_STATUS_T prTcqStatus); + +BOOLEAN +qmAdjustTcQuotasMthread(IN P_ADAPTER_T prAdapter, OUT P_TX_TCQ_ADJUST_T prTcqAdjust, IN P_TX_TCQ_STATUS_T prTcqStatus); +#endif + +BOOLEAN 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); + +VOID qmDoAdaptiveTcResourceCtrl(IN P_ADAPTER_T prAdapter); + +VOID qmCheckForFastTcResourceCtrl(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTc); + +#endif + +VOID qmDetermineStaRecIndex(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +UINT_32 +qmDequeueTxPacketsFromPerStaQueues(IN P_ADAPTER_T prAdapter, OUT P_QUE_T prQue, IN UINT_8 ucTC, IN UINT_32 + u4CurrentQuota, IN UINT_32 u4TotalQuota); + +VOID +qmDequeueTxPacketsFromPerTypeQueues(IN P_ADAPTER_T prAdapter, OUT P_QUE_T prQue, IN UINT_8 ucTC, IN UINT_32 + u4CurrentQuota, IN UINT_32 u4TotalQuota); + +UINT_32 +qmDequeueTxPacketsFromGlobalQueue(IN P_ADAPTER_T prAdapter, OUT P_QUE_T prQue, IN UINT_8 ucTC, IN UINT_32 + u4CurrentQuota, IN UINT_32 u4TotalQuota); + +VOID +qmSetStaRecTxAllowed(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN BOOLEAN fgIsTxAllowed); + +/*----------------------------------------------------------------------------*/ +/* 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); +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR +VOID +qmInsertFallWithinReorderPkt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, + IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue); +#else +VOID +qmInsertFallWithinReorderPkt(IN P_SW_RFB_T prSwRfb, + IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue); +#endif + +VOID qmInsertFallAheadReorderPkt(IN P_SW_RFB_T prSwRfb, IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue); + +VOID qmPopOutDueToFallWithin(IN P_ADAPTER_T prAdapter, IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue); + +VOID qmPopOutDueToFallAhead(IN P_ADAPTER_T prAdapter, IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue); + +VOID qmHandleReorderBubbleTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); + +VOID qmHandleEventCheckReorderBubble(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); + +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); + +#if CFG_RX_BA_REORDERING_ENHANCEMENT +VOID qmInsertNoNeedWaitPkt(IN P_SW_RFB_T prSwRfb, IN ENUM_NO_NEED_WATIT_DROP_REASON_T eDropReason); + +VOID qmHandleEventDropByFW(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); + +VOID qmHandleNoNeedWaitPktList(IN P_RX_BA_ENTRY_T prReorderQueParm); + +P_NO_NEED_WAIT_PKT_T qmSearchNoNeedWaitPktBySSN(IN P_RX_BA_ENTRY_T prReorderQueParm, IN UINT_32 u2SSN); + +BOOLEAN qmIsIndependentPkt(IN P_SW_RFB_T prSwRfb); + +VOID qmRemoveAllNoNeedWaitPkt(IN P_RX_BA_ENTRY_T prReorderQueParm); + +VOID qmDumpNoNeedWaitPkt(IN P_RX_BA_ENTRY_T prReorderQueParm); +#endif + +VOID mqmProcessAssocRsp(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength); + +VOID mqmProcessBcn(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength); + +BOOLEAN +mqmParseEdcaParameters(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength, IN + BOOLEAN fgForceOverride); + +BOOLEAN mqmCompareEdcaParameters(IN P_IE_WMM_PARAM_T prIeWmmParam, IN P_BSS_INFO_T prBssInfo); + +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); + +UINT_32 +mqmFillWmmInfoIE(P_UINT_8 pucOutBuf, BOOLEAN fgSupportUAPSD, UINT_8 ucBmpDeliveryAC, UINT_8 ucBmpTriggerAC, UINT_8 + ucUapsdSp); + +UINT_32 +mqmGenerateWmmInfoIEByStaRec(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_STA_RECORD_T prStaRec, P_UINT_8 + pucOutBuf); + +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); + +#if CFG_SUPPORT_TDLS + +UINT_32 mqmGenerateWmmParamIEByParam(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, PUINT_8 pOutBuf); +#endif + +ENUM_FRAME_ACTION_T qmGetFrameAction(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucBssIndex, IN UINT_8 ucStaRecIdx, IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_FRAME_TYPE_IN_CMD_Q_T eFrameType, IN UINT_16 u2FrameLength); + +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 qmFreeAllByBssIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex); + +UINT_32 qmGetRxReorderQueuedBufferCount(IN P_ADAPTER_T prAdapter); + +VOID qmDumpQueueStatus(IN P_ADAPTER_T prAdapter); + +#if CFG_M0VE_BA_TO_DRIVER +VOID +mqmSendDelBaFrame(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsInitiator, IN P_STA_RECORD_T prStaRec, IN UINT_32 u4Tid, IN + UINT_32 u4ReasonCode); + +WLAN_STATUS +mqmCallbackAddBaRspSent(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +VOID mqmTimeoutCheckIdleRxBa(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); + +VOID +mqmRxModifyBaEntryStatus(IN P_ADAPTER_T prAdapter, IN P_RX_BA_ENTRY_T prRxBaEntry, IN ENUM_BA_ENTRY_STATUS_T eStatus); + +VOID mqmHandleAddBaReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID mqmHandleBaActionFrame(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); +#endif + +#if ARP_MONITER_ENABLE +VOID qmDetectArpNoResponse(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); +VOID qmResetArpDetect(VOID); +VOID qmHandleRxArpPackets(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); +VOID qmHandleRxDhcpPackets(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); +#endif +#ifdef CFG_SUPPORT_REPLAY_DETECTION +BOOLEAN qmHandleRxReplay(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); +#endif + +VOID qmMoveStaTxQueue(P_STA_RECORD_T prSrcStaRec, P_STA_RECORD_T prDstStaRec); +VOID qmHandleDelTspec(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, ENUM_ACI_T eAci); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************** + */ + +#if QM_TEST_MODE +extern QUE_MGT_T g_rQM; +#endif +extern const UINT_8 aucTid2ACI[TX_DESC_TID_NUM]; +extern const UINT_8 arNetwork2TcResource[HW_BSSID_NUM + 1][NET_TC_NUM]; + +#endif /* _QUE_MGT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/wlan_def.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/wlan_def.h new file mode 100644 index 0000000000000..8dad86378d01a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic/wlan_def.h @@ -0,0 +1,927 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/wlan_def.h#1 + */ + +/* + * ! \file "wlan_def.h" + * \brief This file includes the basic definition of WLAN + */ + +#ifndef _WLAN_DEF_H +#define _WLAN_DEF_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************** + */ +/* disconnect reason */ +#define DISCONNECT_REASON_CODE_RESERVED 0 +#define DISCONNECT_REASON_CODE_RADIO_LOST 1 +#define DISCONNECT_REASON_CODE_DEAUTHENTICATED 2 +#define DISCONNECT_REASON_CODE_DISASSOCIATED 3 +#define DISCONNECT_REASON_CODE_NEW_CONNECTION 4 +#define DISCONNECT_REASON_CODE_REASSOCIATION 5 +#define DISCONNECT_REASON_CODE_ROAMING 6 + +/* The rate definitions */ +#define TX_MODE_CCK 0x00 +#define TX_MODE_OFDM 0x40 +#define TX_MODE_HT_MM 0x80 +#define TX_MODE_HT_GF 0xC0 +#define TX_MODE_VHT 0x100 + +#define RATE_CCK_SHORT_PREAMBLE 0x4 + +#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_MCS8 0x8 +#define PHY_RATE_MCS9 0x9 +#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 | PHY_RATE_6M) +#define RATE_OFDM_9M (TX_MODE_OFDM | PHY_RATE_9M) +#define RATE_OFDM_12M (TX_MODE_OFDM | PHY_RATE_12M) +#define RATE_OFDM_18M (TX_MODE_OFDM | PHY_RATE_18M) +#define RATE_OFDM_24M (TX_MODE_OFDM | PHY_RATE_24M) +#define RATE_OFDM_36M (TX_MODE_OFDM | PHY_RATE_36M) +#define RATE_OFDM_48M (TX_MODE_OFDM | PHY_RATE_48M) +#define RATE_OFDM_54M (TX_MODE_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_VHT_MCS_0 (TX_MODE_VHT | PHY_RATE_MCS0) +#define RATE_VHT_MCS_1 (TX_MODE_VHT | PHY_RATE_MCS1) +#define RATE_VHT_MCS_2 (TX_MODE_VHT | PHY_RATE_MCS2) +#define RATE_VHT_MCS_3 (TX_MODE_VHT | PHY_RATE_MCS3) +#define RATE_VHT_MCS_4 (TX_MODE_VHT | PHY_RATE_MCS4) +#define RATE_VHT_MCS_5 (TX_MODE_VHT | PHY_RATE_MCS5) +#define RATE_VHT_MCS_6 (TX_MODE_VHT | PHY_RATE_MCS6) +#define RATE_VHT_MCS_7 (TX_MODE_VHT | PHY_RATE_MCS7) +#define RATE_VHT_MCS_8 (TX_MODE_VHT | PHY_RATE_MCS8) +#define RATE_VHT_MCS_9 (TX_MODE_VHT | PHY_RATE_MCS9) + +#define RATE_NSTS_MASK BITS(9, 10) +#define RATE_NSTS_OFFSET 9 +#define RATE_TX_MODE_MASK BITS(6, 8) +#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(2) +#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 27 + +/* 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) */ +#define PHY_TYPE_BIT_VHT BIT(PHY_TYPE_VHT_INDEX) /* HT PHY (clause 22) */ + +/* 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) + +#define PHY_TYPE_SET_802_11AC (PHY_TYPE_BIT_VHT) + +#define PHY_TYPE_SET_802_11ANAC (PHY_TYPE_BIT_OFDM | \ + PHY_TYPE_BIT_HT | \ + PHY_TYPE_BIT_VHT) + +#define PHY_TYPE_SET_802_11ABGNAC (PHY_TYPE_BIT_OFDM | \ + PHY_TYPE_BIT_HR_DSSS | \ + PHY_TYPE_BIT_ERP | \ + PHY_TYPE_BIT_HT | \ + PHY_TYPE_BIT_VHT) + +/* Rate set bit definitions */ +#define RATE_SET_BIT_1M BIT(RATE_1M_SW_INDEX) /* Bit 0: 1M */ +#define RATE_SET_BIT_2M BIT(RATE_2M_SW_INDEX) /* Bit 1: 2M */ +#define RATE_SET_BIT_5_5M BIT(RATE_5_5M_SW_INDEX) /* Bit 2: 5.5M */ +#define RATE_SET_BIT_11M BIT(RATE_11M_SW_INDEX) /* Bit 3: 11M */ +#define RATE_SET_BIT_22M BIT(RATE_22M_SW_INDEX) /* Bit 4: 22M */ +#define RATE_SET_BIT_33M BIT(RATE_33M_SW_INDEX) /* Bit 5: 33M */ +#define RATE_SET_BIT_6M BIT(RATE_6M_SW_INDEX) /* Bit 6: 6M */ +#define RATE_SET_BIT_9M BIT(RATE_9M_SW_INDEX) /* Bit 7: 9M */ +#define RATE_SET_BIT_12M BIT(RATE_12M_SW_INDEX) /* Bit 8: 12M */ +#define RATE_SET_BIT_18M BIT(RATE_18M_SW_INDEX) /* Bit 9: 18M */ +#define RATE_SET_BIT_24M BIT(RATE_24M_SW_INDEX) /* Bit 10: 24M */ +#define RATE_SET_BIT_36M BIT(RATE_36M_SW_INDEX) /* Bit 11: 36M */ +#define RATE_SET_BIT_48M BIT(RATE_48M_SW_INDEX) /* Bit 12: 48M */ +#define RATE_SET_BIT_54M BIT(RATE_54M_SW_INDEX) /* Bit 13: 54M */ +#define RATE_SET_BIT_VHT_PHY BIT(RATE_VHT_PHY_SW_INDEX) /* Bit 14: BSS Selector */ +#define RATE_SET_BIT_HT_PHY BIT(RATE_HT_PHY_SW_INDEX) /* Bit 15: 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 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) +#define AUTH_TYPE_SAE BIT(AUTH_ALGORITHM_NUM_SAE) +/* Authentication Retry Limit */ +#define TX_AUTH_ASSOCI_RETRY_LIMIT 2 +#define TX_AUTH_ASSOCI_RETRY_LIMIT_FOR_ROAMING 1 + +/* WMM-2.2.1 WMM Information Element */ +#define ELEM_MAX_LEN_WMM_INFO 7 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************** + */ +typedef UINT_16 PHY_TYPE, *P_PHY_TYPE; +typedef UINT_8 RCPI, *P_RCPI; +typedef UINT_8 ALC_VAL, *P_ALC_VAL; + +typedef enum _ENUM_HW_BSSID_T { + BSSID_0 = 0, + BSSID_1, + BSSID_2, + BSSID_3, + 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; + +typedef enum _ENUM_NETWORK_TYPE_T { + NETWORK_TYPE_AIS, + NETWORK_TYPE_P2P, + NETWORK_TYPE_BOW, + NETWORK_TYPE_MBSS, + NETWORK_TYPE_NUM +} ENUM_NETWORK_TYPE_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, + STA_ROLE_MAX_INDEX +} ENUM_STA_ROLE_INDEX_T; + +#define STA_ROLE_INDEX_NUM (STA_ROLE_MAX_INDEX - STA_ROLE_BASE_INDEX) + +/* 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_VHT_INDEX, /* HT PHY (clause 22) */ + PHY_TYPE_INDEX_NUM /* 6 */ +} ENUM_PHY_TYPE_INDEX_T, *P_ENUM_PHY_TYPE_INDEX_T; + +typedef enum _ENUM_SW_RATE_INDEX_T { + RATE_1M_SW_INDEX = 0, /* 1M */ + RATE_2M_SW_INDEX, /* 2M */ + RATE_5_5M_SW_INDEX, /* 5.5M */ + RATE_11M_SW_INDEX, /* 11M */ + RATE_22M_SW_INDEX, /* 22M */ + RATE_33M_SW_INDEX, /* 33M */ + RATE_6M_SW_INDEX, /* 6M */ + RATE_9M_SW_INDEX, /* 9M */ + RATE_12M_SW_INDEX, /* 12M */ + RATE_18M_SW_INDEX, /* 18M */ + RATE_24M_SW_INDEX, /* 24M */ + RATE_36M_SW_INDEX, /* 36M */ + RATE_48M_SW_INDEX, /* 48M */ + RATE_54M_SW_INDEX, /* 54M */ + RATE_VHT_PHY_SW_INDEX, /* BSS Selector - VHT PHY */ + RATE_HT_PHY_SW_INDEX, /* BSS Selector - HT PHY */ + RATE_NUM_SW /* 16 */ +} ENUM_SW_RATE_INDEX_T, *P_ENUM_SW_RATE_INDEX_T; + +typedef enum _ENUM_CCK_RATE_INDEX_T { + RATE_1M_INDEX = 0, /* 1M */ + RATE_2M_INDEX, /* 2M */ + RATE_5_5M_INDEX, /* 5.5M */ + RATE_11M_INDEX, /* 11M */ + CCK_RATE_NUM /* 4 */ +} ENUM_CCK_RATE_INDEX_T, *P_ENUM_CCK_RATE_INDEX_T; + +typedef enum _ENUM_OFDM_RATE_INDEX_T { + RATE_6M_INDEX = 0, /* 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 */ + OFDM_RATE_NUM /* 8 */ +} ENUM_OFDM_RATE_INDEX_T, *P_ENUM_OFDM_RATE_INDEX_T; + +typedef enum _ENUM_HT_RATE_INDEX_T { + HT_RATE_MCS32_INDEX = 0, + HT_RATE_MCS0_INDEX, + 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_MCS8_INDEX, + HT_RATE_MCS9_INDEX, + HT_RATE_MCS10_INDEX, + HT_RATE_MCS11_INDEX, + HT_RATE_MCS12_INDEX, + HT_RATE_MCS13_INDEX, + HT_RATE_MCS14_INDEX, + HT_RATE_MCS15_INDEX, + HT_RATE_NUM /* 9 */ +} ENUM_HT_RATE_INDEX_T, *P_ENUM_HT_RATE_INDEX_T; + +typedef enum _ENUM_VHT_RATE_INDEX_T { + VHT_RATE_MCS0_INDEX = 0, + VHT_RATE_MCS1_INDEX, + VHT_RATE_MCS2_INDEX, + VHT_RATE_MCS3_INDEX, + VHT_RATE_MCS4_INDEX, + VHT_RATE_MCS5_INDEX, + VHT_RATE_MCS6_INDEX, + VHT_RATE_MCS7_INDEX, + VHT_RATE_MCS8_INDEX, + VHT_RATE_MCS9_INDEX, + VHT_RATE_NUM /* 10 */ +} ENUM_VHT_RATE_INDEX_T, *P_ENUM_VHT_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_OFDM_MODE, + PREAMBLE_HT_MIXED_MODE, + PREAMBLE_HT_GREEN_FIELD, + PREAMBLE_VHT_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_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; + +typedef enum _ENUM_CHANNEL_WIDTH_T { + CW_20_40MHZ = 0, + CW_80MHZ = 1, + CW_160MHZ = 2, + CW_80P80MHZ = 3 +} ENUM_CHANNEL_WIDTH_T, *P_ENUM_CHANNEL_WIDTH_P; + +/* 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; + enum nl80211_dfs_state eDFS; +} RF_CHANNEL_INFO_T, *P_RF_CHANNEL_INFO_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 enum _ENUM_AR_SS_T { + AR_SS_NULL = 0, + AR_SS_1, + AR_SS_2, + AR_SS_3, + AR_SS_4, + AR_SS_NUM +} ENUM_AR_SS_T, P_ENUM_AR_SS_T; + +typedef enum _ENUM_MAC_BANDWIDTH_T { + MAC_BW_20 = 0, + MAC_BW_40, + MAC_BW_80, + MAC_BW_160 +} ENUM_MAC_BANDWIDTH_T, *P_ENUM_MAC_BANDWIDTH_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, UINT_8, 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_802_11AC, + PHY_CONFIG_802_11ANAC, + PHY_CONFIG_802_11ABGNAC, + PHY_CONFIG_NUM /* 12 */ +} 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 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)->ucBssIndex == prAdapter->prAisBssInfo->ucBssIndex) +#define IS_STA_IN_P2P(_prStaRec) (prAdapter->aprBssInfo[(_prStaRec)->ucBssIndex]->eNetworkType == \ + NETWORK_TYPE_P2P) +#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 12 /* max number of supported AKM suites */ +#else +#define MAX_NUM_SUPPORTED_AKM_SUITES 8 /* 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 + ******************************************************************************** + */ + +/******************************************************************************* + * 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_BE24(_memAddr_p, _value_p) \ + { \ + PUINT_8 __cp = (PUINT_8)(_memAddr_p); \ + *(PUINT_32)(_value_p) = ((UINT_8)__cp[0] << 16) | ((UINT_8)__cp[1] << 8) | ((UINT_8)__cp[2]); \ + } + +#define WLAN_GET_FIELD_BE32(_memAddr_p, _value_p) \ + { \ + PUINT_8 __cp = (PUINT_8)(_memAddr_p); \ + *(PUINT_32)(_value_p) = ((UINT_32)__cp[0] << 24) | \ + ((UINT_32)__cp[1] << 16) | ((UINT_32)__cp[2] << 8) | \ + ((UINT_32)__cp[3]); \ + } + +#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); \ + } + +#define WLAN_SET_FIELD_BE24(_memAddr_p, _value) \ + { \ + PUINT_8 __cp = (PUINT_8)(_memAddr_p); \ + __cp[0] = (UINT_8)((_value) >> 16); \ + __cp[1] = (UINT_8)((_value) >> 8); \ + __cp[2] = (UINT_8)(_value); \ + } + +#define WLAN_SET_FIELD_BE32(_memAddr_p, _value) \ + { \ + PUINT_8 __cp = (PUINT_8)(_memAddr_p); \ + __cp[0] = (UINT_8)((_value) >> 24); \ + __cp[1] = (UINT_8)((_value) >> 16); \ + __cp[2] = (UINT_8)((_value) >> 8); \ + __cp[3] = (UINT_8)(_value); \ + } + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************** + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************** + */ + +#endif /* _WLAN_DEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic_cmd_event.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic_cmd_event.h new file mode 100644 index 0000000000000..03f82e28dcbf6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic_cmd_event.h @@ -0,0 +1,2551 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/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. + */ + +#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 +******************************************************************************** +*/ +#include "gl_vendor.h" +#include "gl_qa_agent.h" +#include "cnm_scan.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define CMD_PQ_ID (0x8000) +#define CMD_PACKET_TYPE_ID (0xA0) + +#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 + +/*CMD_POWER_OFFSET_T , follow 5G sub-band*/ +/* #define MAX_SUBBAND_NUM 8 */ +/* */ +/* */ +/* */ +/* */ + +#define SCN_PSCAN_SWC_RSSI_WIN_MAX 75 +#define SCN_PSCAN_SWC_MAX_NUM 8 +#define SCN_PSCAN_HOTLIST_REPORT_MAX_NUM 8 + +#if CFG_SUPPORT_QA_TOOL +#define IQ_FILE_LINE_OFFSET 18 +#define IQ_FILE_IQ_STR_LEN 8 +#define RTN_IQ_DATA_LEN 1024 /* return 1k per packet */ + +#define MCAST_WCID_TO_REMOVE 0 + +/* Network type */ +#define NETWORK_INFRA BIT(16) +#define NETWORK_P2P BIT(17) +#define NETWORK_IBSS BIT(18) +#define NETWORK_MESH BIT(19) +#define NETWORK_BOW BIT(20) +#define NETWORK_WDS BIT(21) + +/* Station role */ +#define STA_TYPE_STA BIT(0) +#define STA_TYPE_AP BIT(1) +#define STA_TYPE_ADHOC BIT(2) +#define STA_TYPE_TDLS BIT(3) +#define STA_TYPE_WDS BIT(4) + +/* Connection type */ +#define CONNECTION_INFRA_STA (STA_TYPE_STA|NETWORK_INFRA) +#define CONNECTION_INFRA_AP (STA_TYPE_AP|NETWORK_INFRA) +#define CONNECTION_P2P_GC (STA_TYPE_STA|NETWORK_P2P) +#define CONNECTION_P2P_GO (STA_TYPE_AP|NETWORK_P2P) +#define CONNECTION_MESH_STA (STA_TYPE_STA|NETWORK_MESH) +#define CONNECTION_MESH_AP (STA_TYPE_AP|NETWORK_MESH) +#define CONNECTION_IBSS_ADHOC (STA_TYPE_ADHOC|NETWORK_IBSS) +#define CONNECTION_TDLS (STA_TYPE_STA|NETWORK_INFRA|STA_TYPE_TDLS) +#define CONNECTION_WDS (STA_TYPE_WDS|NETWORK_WDS) + +/*#define ICAP_CONTENT_ADC 0x10000006*/ +/*#define ICAP_CONTENT_TOAE 0x7*/ +/*#define ICAP_CONTENT_SPECTRUM 0xB*/ +#define ICAP_CONTENT_RBIST 0x10 +#define ICAP_CONTENT_DCOC 0x20 +/*#define ICAP_CONTENT_FIIQ 0x48*/ +/*#define ICAP_CONTENT_FDIQ 0x49*/ +#define ICAP_CONTENT_ADC 0 +#define ICAP_CONTENT_TOAE 1 +#define ICAP_CONTENT_FIIQ 2 +#define ICAP_CONTENT_FDIQ 3 +#define ICAP_CONTENT_SPECTRUM 4 + + +#if CFG_SUPPORT_BUFFER_MODE + + +typedef struct _CMD_EFUSE_BUFFER_MODE_1_T { + UINT_8 ucSourceMode; + UINT_8 ucCount; + UINT_8 ucCmdType; + UINT_8 ucReserved; + UINT_8 aBinContent[EFUSE_CONTENT_SIZE_1]; +} CMD_EFUSE_BUFFER_MODE_1_T, *P_CMD_EFUSE_BUFFER_MODE_1_T; + +typedef struct _CMD_EFUSE_BUFFER_MODE_T { + UINT_8 ucSourceMode; + UINT_8 ucCount; + UINT_8 ucReserved[2]; + BIN_CONTENT_T aBinContent[EFUSE_CONTENT_SIZE]; +} CMD_EFUSE_BUFFER_MODE_T, *P_CMD_EFUSE_BUFFER_MODE_T; + + +/*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ +typedef struct _CMD_ACCESS_EFUSE_T { + UINT_32 u4Address; + UINT_32 u4Valid; + UINT_8 aucData[16]; +} CMD_ACCESS_EFUSE_T, *P_CMD_ACCESS_EFUSE_T; + +typedef struct _CMD_EFUSE_FREE_BLOCK_T { + UINT_8 ucGetFreeBlock; + UINT_8 aucReserved[3]; +} CMD_EFUSE_FREE_BLOCK_T, *P_CMD_EFUSE_FREE_BLOCK_T; + +/*#endif*/ + +#endif /* CFG_SUPPORT_BUFFER_MODE */ + +/* +* Definitions for extension CMD_ID +*/ +typedef enum _ENUM_EXT_CMD_ID_T { + EXT_CMD_ID_EFUSE_ACCESS = 0x01, + EXT_CMD_ID_RF_REG_ACCESS = 0x02, + EXT_CMD_ID_EEPROM_ACCESS = 0x03, + EXT_CMD_ID_RF_TEST = 0x04, + EXT_CMD_ID_RADIO_ON_OFF_CTRL = 0x05, + EXT_CMD_ID_WIFI_RX_DISABLE = 0x06, + EXT_CMD_ID_PM_STATE_CTRL = 0x07, + EXT_CMD_ID_CHANNEL_SWITCH = 0x08, + EXT_CMD_ID_NIC_CAPABILITY = 0x09, + EXT_CMD_ID_AP_PWR_SAVING_CLEAR = 0x0A, + EXT_CMD_ID_SET_WTBL2_RATETABLE = 0x0B, + EXT_CMD_ID_GET_WTBL_INFORMATION = 0x0C, + EXT_CMD_ID_ASIC_INIT_UNINIT_CTRL = 0x0D, + EXT_CMD_ID_MULTIPLE_REG_ACCESS = 0x0E, + EXT_CMD_ID_AP_PWR_SAVING_CAPABILITY = 0x0F, + EXT_CMD_ID_SECURITY_ADDREMOVE_KEY = 0x10, + EXT_CMD_ID_SET_TX_POWER_CONTROL = 0x11, + EXT_CMD_ID_SET_THERMO_CALIBRATION = 0x12, + EXT_CMD_ID_FW_LOG_2_HOST = 0x13, + EXT_CMD_ID_AP_PWR_SAVING_START = 0x14, + EXT_CMD_ID_MCC_OFFLOAD_START = 0x15, + EXT_CMD_ID_MCC_OFFLOAD_STOP = 0x16, + EXT_CMD_ID_LED = 0x17, + EXT_CMD_ID_PACKET_FILTER = 0x18, + EXT_CMD_ID_COEXISTENCE = 0x19, + EXT_CMD_ID_PWR_MGT_BIT_WIFI = 0x1B, + EXT_CMD_ID_GET_TX_POWER = 0x1C, + EXT_CMD_ID_BF_ACTION = 0x1E, + + EXT_CMD_ID_WMT_CMD_OVER_WIFI = 0x20, + EXT_CMD_ID_EFUSE_BUFFER_MODE = 0x21, + EXT_CMD_ID_OFFLOAD_CTRL = 0x22, + EXT_CMD_ID_THERMAL_PROTECT = 0x23, + EXT_CMD_ID_CLOCK_SWITCH_DISABLE = 0x24, + EXT_CMD_ID_STAREC_UPDATE = 0x25, + EXT_CMD_ID_BSSINFO_UPDATE = 0x26, + EXT_CMD_ID_EDCA_SET = 0x27, + EXT_CMD_ID_SLOT_TIME_SET = 0x28, + EXT_CMD_ID_DEVINFO_UPDATE = 0x2A, + EXT_CMD_ID_NOA_OFFLOAD_CTRL = 0x2B, + EXT_CMD_ID_GET_SENSOR_RESULT = 0x2C, + EXT_CMD_ID_TMR_CAL = 0x2D, + EXT_CMD_ID_WAKEUP_OPTION = 0x2E, + EXT_CMD_ID_OBTW = 0x2F, + + EXT_CMD_ID_GET_TX_STATISTICS = 0x30, + EXT_CMD_ID_AC_QUEUE_CONTROL = 0x31, + EXT_CMD_ID_WTBL_UPDATE = 0x32, + EXT_CMD_ID_BCN_UPDATE = 0x33, + + EXT_CMD_ID_DRR_CTRL = 0x36, + EXT_CMD_ID_BSSGROUP_CTRL = 0x37, + EXT_CMD_ID_VOW_FEATURE_CTRL = 0x38, + EXT_CMD_ID_PKT_PROCESSOR_CTRL = 0x39, + EXT_CMD_ID_PALLADIUM = 0x3A, +#if CFG_SUPPORT_MU_MIMO + EXT_CMD_ID_MU_CTRL = 0x40, +#endif /* CFG_SUPPORT_MU_MIMO */ + + EXT_CMD_ID_EFUSE_FREE_BLOCK = 0x4F + +} ENUM_EXT_CMD_ID_T, *P_ENUM_EXT_CMD_ID_T; + +typedef enum _NDIS_802_11_WEP_STATUS { + Ndis802_11WEPEnabled, + Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, + Ndis802_11WEPDisabled, + Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, + Ndis802_11WEPKeyAbsent, + Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, + Ndis802_11WEPNotSupported, + Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, + Ndis802_11TKIPEnable, + Ndis802_11Encryption2Enabled = Ndis802_11TKIPEnable, + Ndis802_11Encryption2KeyAbsent, + Ndis802_11AESEnable, + Ndis802_11Encryption3Enabled = Ndis802_11AESEnable, + Ndis802_11CCMP256Enable, + Ndis802_11GCMP128Enable, + Ndis802_11GCMP256Enable, + Ndis802_11Encryption3KeyAbsent, + Ndis802_11TKIPAESMix, + Ndis802_11Encryption4Enabled = Ndis802_11TKIPAESMix, /* TKIP or AES mix */ + Ndis802_11Encryption4KeyAbsent, + Ndis802_11GroupWEP40Enabled, + Ndis802_11GroupWEP104Enabled, +#ifdef WAPI_SUPPORT + Ndis802_11EncryptionSMS4Enabled, /* WPI SMS4 support */ +#endif /* WAPI_SUPPORT */ +} NDIS_802_11_WEP_STATUS, *PNDIS_802_11_WEP_STATUS, NDIS_802_11_ENCRYPTION_STATUS, *PNDIS_802_11_ENCRYPTION_STATUS; + +#if CFG_SUPPORT_MU_MIMO +enum { + /* debug commands */ + MU_SET_ENABLE = 0, + MU_GET_ENABLE, + MU_SET_MUPROFILE_ENTRY, + MU_GET_MUPROFILE_ENTRY, + MU_SET_GROUP_TBL_ENTRY, + MU_GET_GROUP_TBL_ENTRY, + MU_SET_CLUSTER_TBL_ENTRY, + MU_GET_CLUSTER_TBL_ENTRY, + MU_SET_GROUP_USER_THRESHOLD, + MU_GET_GROUP_USER_THRESHOLD, + MU_SET_GROUP_NSS_THRESHOLD, + MU_GET_GROUP_NSS_THRESHOLD, + MU_SET_TXREQ_MIN_TIME, + MU_GET_TXREQ_MIN_TIME, + MU_SET_SU_NSS_CHECK, + MU_GET_SU_NSS_CHECK, + MU_SET_CALC_INIT_MCS, + MU_GET_CALC_INIT_MCS, + MU_SET_TXOP_DEFAULT, + MU_GET_TXOP_DEFAULT, + MU_SET_SU_LOSS_THRESHOLD, + MU_GET_SU_LOSS_THRESHOLD, + MU_SET_MU_GAIN_THRESHOLD, + MU_GET_MU_GAIN_THRESHOLD, + MU_SET_SECONDARY_AC_POLICY, + MU_GET_SECONDARY_AC_POLICY, + MU_SET_GROUP_TBL_DMCS_MASK, + MU_GET_GROUP_TBL_DMCS_MASK, + MU_SET_MAX_GROUP_SEARCH_CNT, + MU_GET_MAX_GROUP_SEARCH_CNT, + MU_GET_MU_PROFILE_TX_STATUS_CNT, + MU_SET_TRIGGER_MU_TX, + /* F/W flow test commands */ + MU_SET_TRIGGER_GID_MGMT_FRAME, + /* HQA commands */ + MU_HQA_SET_STA_PARAM, + MU_HQA_SET_ENABLE, + MU_HQA_SET_SNR_OFFSET, + MU_HQA_SET_ZERO_NSS, + MU_HQA_SET_SPEED_UP_LQ, + MU_HQA_SET_GROUP, + MU_HQA_SET_MU_TABLE, + MU_HQA_SET_CALC_LQ, + MU_HQA_GET_CALC_LQ, + MU_HQA_SET_CALC_INIT_MCS, + MU_HQA_GET_CALC_INIT_MCS, + MU_HQA_GET_QD, +}; +#endif /* CFG_SUPPORT_MU_MIMO */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +typedef enum _ENUM_CMD_ID_T { + CMD_ID_TEST_CTRL = 0x01, /* 0x01 (Set) */ + CMD_ID_BASIC_CONFIG, /* 0x02 (Set) */ + CMD_ID_SCAN_REQ_V2, /* 0x03 (Set) */ + CMD_ID_NIC_POWER_CTRL, /* 0x04 (Set) */ + CMD_ID_POWER_SAVE_MODE, /* 0x05 (Set) */ + CMD_ID_LINK_ATTRIB, /* 0x06 (Set) */ + CMD_ID_ADD_REMOVE_KEY, /* 0x07 (Set) */ + CMD_ID_DEFAULT_KEY_ID, /* 0x08 (Set) */ + CMD_ID_INFRASTRUCTURE, /* 0x09 (Set) */ + CMD_ID_SET_RX_FILTER, /* 0x0a (Set) */ + CMD_ID_DOWNLOAD_BUF, /* 0x0b (Set) */ + CMD_ID_WIFI_START, /* 0x0c (Set) */ + CMD_ID_CMD_BT_OVER_WIFI, /* 0x0d (Set) */ + CMD_ID_SET_MEDIA_CHANGE_DELAY_TIME, /* 0x0e (Set) */ + CMD_ID_SET_DOMAIN_INFO, /* 0x0f (Set) */ + CMD_ID_SET_IP_ADDRESS, /* 0x10 (Set) */ + CMD_ID_BSS_ACTIVATE_CTRL, /* 0x11 (Set) */ + CMD_ID_SET_BSS_INFO, /* 0x12 (Set) */ + CMD_ID_UPDATE_STA_RECORD, /* 0x13 (Set) */ + CMD_ID_REMOVE_STA_RECORD, /* 0x14 (Set) */ + CMD_ID_INDICATE_PM_BSS_CREATED, /* 0x15 (Set) */ + CMD_ID_INDICATE_PM_BSS_CONNECTED, /* 0x16 (Set) */ + CMD_ID_INDICATE_PM_BSS_ABORT, /* 0x17 (Set) */ + CMD_ID_UPDATE_BEACON_CONTENT, /* 0x18 (Set) */ + CMD_ID_SET_BSS_RLM_PARAM, /* 0x19 (Set) */ + CMD_ID_SCAN_REQ, /* 0x1a (Set) */ + CMD_ID_SCAN_CANCEL, /* 0x1b (Set) */ + CMD_ID_CH_PRIVILEGE, /* 0x1c (Set) */ + CMD_ID_UPDATE_WMM_PARMS, /* 0x1d (Set) */ + CMD_ID_SET_WMM_PS_TEST_PARMS, /* 0x1e (Set) */ + CMD_ID_TX_AMPDU, /* 0x1f (Set) */ + CMD_ID_ADDBA_REJECT, /* 0x20 (Set) */ + CMD_ID_SET_PS_PROFILE_ADV, /* 0x21 (Set) */ + CMD_ID_SET_RAW_PATTERN, /* 0x22 (Set) */ + CMD_ID_CONFIG_PATTERN_FUNC, /* 0x23 (Set) */ + CMD_ID_SET_TX_PWR, /* 0x24 (Set) */ + CMD_ID_SET_PWR_PARAM, /* 0x25 (Set) */ + CMD_ID_P2P_ABORT, /* 0x26 (Set) */ + + /* SLT commands */ + 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 ) */ + + CMD_ID_ROAMING_TRANSIT = 0x30, /* 0x30 (Set) */ + CMD_ID_SET_PHY_PARAM, /* 0x31 (Set) */ + CMD_ID_SET_NOA_PARAM, /* 0x32 (Set) */ + CMD_ID_SET_OPPPS_PARAM, /* 0x33 (Set) */ + CMD_ID_SET_UAPSD_PARAM, /* 0x34 (Set) */ + CMD_ID_SET_SIGMA_STA_SLEEP, /* 0x35 (Set) */ + CMD_ID_SET_EDGE_TXPWR_LIMIT, /* 0x36 (Set) */ + CMD_ID_SET_DEVICE_MODE, /* 0x37 (Set) */ + CMD_ID_SET_TXPWR_CTRL, /* 0x38 (Set) */ + CMD_ID_SET_AUTOPWR_CTRL, /* 0x39 (Set) */ + CMD_ID_SET_WFD_CTRL, /* 0x3a (Set) */ + CMD_ID_SET_NLO_REQ, /* 0x3b (Set) */ + CMD_ID_SET_NLO_CANCEL, /* 0x3c (Set) */ + CMD_ID_SET_GTK_REKEY_DATA, /* 0x3d (Set) */ + CMD_ID_ROAMING_CONTROL, /* 0x3e (Set) */ +/* CFG_M0VE_BA_TO_DRIVER */ + CMD_ID_RESET_BA_SCOREBOARD = 0x3f, /* 0x3f (Set) */ + CMD_ID_SET_EDGE_TXPWR_LIMIT_5G = 0x40, /* 0x40 (Set) */ + CMD_ID_SET_CHANNEL_PWR_OFFSET, /* 0x41 (Set) */ + CMD_ID_SET_80211AC_TX_PWR, /* 0x42 (Set) */ + CMD_ID_SET_PATH_COMPASATION, /* 0x43 (Set) */ + + CMD_ID_SET_BATCH_REQ = 0x47, /* 0x47 (Set) */ + CMD_ID_SET_NVRAM_SETTINGS, /* 0x48 (Set) */ + CMD_ID_SET_COUNTRY_POWER_LIMIT, /* 0x49 (Set) */ + + CMD_ID_SET_SUSPEND_MODE = 0x58, /* 0x58 (Set) */ + CMD_ID_SET_RRM_CAPABILITY = 0x59, /* 0x59 (Set) */ + CMD_ID_SET_MAX_TXPWR_LIMIT = 0x5A, /* 0x5A (Set) */ + CMD_ID_REQ_CHNL_UTILIZATION = 0x5C, /* 0x5C (Get) */ + CMD_ID_SET_TSM_STATISTICS_REQUEST = 0x5E, + CMD_ID_GET_TSM_STATISTICS = 0x5F, + /* CFG_SUPPORT_GSCN */ + CMD_ID_GET_PSCAN_CAPABILITY = 0x60, /* 0x60 (Set) */ + CMD_ID_SET_PSCAN_ENABLE, /* 0x61 (Set) */ + CMD_ID_SET_PSCAN_PARAM, /* 0x62 (Set) */ + CMD_ID_SET_GSCAN_ADD_HOTLIST_BSSID, /* 0x63 (Set) */ + CMD_ID_SET_GSCAN_ADD_SWC_BSSID, /* 0x64 (Set) */ + CMD_ID_SET_GSCAN_MAC_ADDR, /* 0x65 (Set) */ + CMD_ID_GET_GSCAN_RESULT, /* 0x66 (Get) */ + CMD_ID_UPDATE_AC_PARMS = 0x6A, /* 0x6A (Set) */ +#if CFG_SUPPORT_FCC_DYNAMIC_TX_PWR_ADJUST + CMD_ID_SET_FCC_TX_PWR_CERT = 0x6F, /* 0x6F (Set) */ +#endif +#if FW_CFG_SUPPORT + CMD_ID_GET_SET_CUSTOMER_CFG = 0x70, /* 0x70(Set) */ +#endif + + CMD_ID_TDLS_PS = 0x75, /* 0x75 (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_STA_STATISTICS = 0x85, /* 0x85 (Query) */ + + CMD_ID_GET_LTE_CHN = 0x87, /* 0x87 (Query) */ + CMD_ID_GET_CHN_LOADING = 0x88, /* 0x88 (Query) */ + CMD_ID_GET_REPORT_MISC = 0x8A, /* 0x88 (Query) */ + CMD_ID_ENABLE_LOW_LATENCEY_MODE = 0x8B, /* 0x8B (Set) */ +#if CFG_SUPPORT_OSHARE + CMD_ID_SET_OSHARE_MODE = 0x8C, +#endif + CMD_ID_WIFI_LOG_LEVEL = 0x8D, /* 0x8D (Set / Query) */ + CMD_ID_GET_FW_INFO = 0x90, /* 0x90 (Query) */ + CMD_ID_WFC_KEEP_ALIVE = 0xA0, /* 0xa0(Set) */ + CMD_ID_RSSI_MONITOR = 0xA1, /* 0xa1(Set) */ + CMD_ID_ACCESS_REG = 0xC0, /* 0xc0 (Set / Query) */ + CMD_ID_MAC_MCAST_ADDR, /* 0xc1 (Set / Query) */ + CMD_ID_802_11_PMKID, /* 0xc2 (Set / Query) */ + CMD_ID_ACCESS_EEPROM, /* 0xc3 (Set / Query) */ + CMD_ID_SW_DBG_CTRL, /* 0xc4 (Set / Query) */ + CMD_ID_SEC_CHECK, /* 0xc5 (Set / Query) */ + CMD_ID_DUMP_MEM, /* 0xc6 (Query) */ + CMD_ID_RESOURCE_CONFIG, /* 0xc7 (Set / Query) */ +#if CFG_SUPPORT_QA_TOOL + CMD_ID_ACCESS_RX_STAT, /* 0xc8 (Query) */ +#endif /* CFG_SUPPORT_QA_TOOL */ + CMD_ID_CHIP_CONFIG = 0xCA, /* 0xca (Set / Query) */ + CMD_ID_STATS_LOG = 0xCB, /* 0xcb (Set) */ + CMD_ID_SET_SAR_ENABLE = 0xCC, +#if CFG_MODIFY_TX_POWER_BY_BAT_VOLT + CMD_ID_TX_POWER_BACKOFF = 0xCD, +#endif + CMD_ID_SET_RDD_CH = 0xE1, +#if CFG_SUPPORT_QA_TOOL + CMD_ID_LAYER_0_EXT_MAGIC_NUM = 0xED, /* magic number for Extending MT6630 original CMD header */ +#endif /* CFG_SUPPORT_QA_TOOL */ + CMD_ID_SET_BWCS = 0xF1, + CMD_ID_SET_OSC = 0xF2, + + CMD_ID_GET_BUILD_DATE_CODE = 0xF8, /* 0xf8 (Query) */ + CMD_ID_GET_BSS_INFO = 0xF9, /* 0xF9 (Query) */ + CMD_ID_SET_HOTSPOT_OPTIMIZATION = 0xFA, /* 0xFA (Set) */ + CMD_ID_SET_TDLS_CH_SW = 0xFB, + CMD_ID_SET_MONITOR = 0xFC, /* 0xFC (Set) */ + CMD_ID_END +} ENUM_CMD_ID_T, *P_ENUM_CMD_ID_T; + +typedef enum _ENUM_EVENT_ID_T { + EVENT_ID_NIC_CAPABILITY = 0x01, /* 0x01 (Query) */ + EVENT_ID_LINK_QUALITY, /* 0x02 (Query / Unsolicited) */ + EVENT_ID_STATISTICS, /* 0x03 (Query) */ + EVENT_ID_MIC_ERR_INFO, /* 0x04 (Unsolicited) */ + EVENT_ID_ACCESS_REG, /* 0x05 (Query - CMD_ID_ACCESS_REG) */ + EVENT_ID_ACCESS_EEPROM, /* 0x06 (Query - CMD_ID_ACCESS_EEPROM) */ + EVENT_ID_SLEEPY_INFO, /* 0x07 (Unsolicited) */ + EVENT_ID_BT_OVER_WIFI, /* 0x08 (Unsolicited) */ + EVENT_ID_TEST_STATUS, /* 0x09 (Query - CMD_ID_TEST_CTRL) */ + EVENT_ID_RX_ADDBA, /* 0x0a (Unsolicited) */ + EVENT_ID_RX_DELBA, /* 0x0b (Unsolicited) */ + EVENT_ID_ACTIVATE_STA_REC, /* 0x0c (Response) */ + EVENT_ID_SCAN_DONE, /* 0x0d (Unsoiicited) */ + EVENT_ID_RX_FLUSH, /* 0x0e (Unsolicited) */ + EVENT_ID_TX_DONE, /* 0x0f (Unsolicited) */ + EVENT_ID_CH_PRIVILEGE, /* 0x10 (Unsolicited) */ + EVENT_ID_BSS_ABSENCE_PRESENCE, /* 0x11 (Unsolicited) */ + EVENT_ID_STA_CHANGE_PS_MODE, /* 0x12 (Unsolicited) */ + EVENT_ID_BSS_BEACON_TIMEOUT, /* 0x13 (Unsolicited) */ + EVENT_ID_UPDATE_NOA_PARAMS, /* 0x14 (Unsolicited) */ + EVENT_ID_AP_OBSS_STATUS, /* 0x15 (Unsolicited) */ + EVENT_ID_STA_UPDATE_FREE_QUOTA, /* 0x16 (Unsolicited) */ + EVENT_ID_SW_DBG_CTRL, /* 0x17 (Query - CMD_ID_SW_DBG_CTRL) */ + EVENT_ID_ROAMING_STATUS, /* 0x18 (Unsolicited) */ + EVENT_ID_STA_AGING_TIMEOUT, /* 0x19 (Unsolicited) */ + EVENT_ID_SEC_CHECK_RSP, /* 0x1a (Query - CMD_ID_SEC_CHECK) */ + EVENT_ID_SEND_DEAUTH, /* 0x1b (Unsolicited) */ + EVENT_ID_UPDATE_RDD_STATUS, /* 0x1c (Unsolicited) */ + EVENT_ID_UPDATE_BWCS_STATUS, /* 0x1d (Unsolicited) */ + EVENT_ID_UPDATE_BCM_DEBUG, /* 0x1e (Unsolicited) */ + EVENT_ID_RX_ERR, /* 0x1f (Unsolicited) */ + EVENT_ID_DUMP_MEM = 0x20, /* 0x20 (Query - CMD_ID_DUMP_MEM) */ + EVENT_ID_STA_STATISTICS, /* 0x21 (Query ) */ + EVENT_ID_STA_STATISTICS_UPDATE, /* 0x22 (Unsolicited) */ + EVENT_ID_NLO_DONE, /* 0x23 (Unsoiicited) */ + EVENT_ID_ADD_PKEY_DONE, /* 0x24 (Unsoiicited) */ + EVENT_ID_ICAP_DONE, /* 0x25 (Unsoiicited) */ + EVENT_ID_RESOURCE_CONFIG = 0x26, /* 0x26 (Query - CMD_ID_RESOURCE_CONFIG) */ + EVENT_ID_DEBUG_MSG = 0x27, /* 0x27 (Unsoiicited) */ + EVENT_ID_RTT_CALIBR_DONE = 0x28, /* 0x28 (Unsoiicited) */ + EVENT_ID_RTT_UPDATE_RANGE = 0x29, /* 0x29 (Unsoiicited) */ + EVENT_ID_CHECK_REORDER_BUBBLE = 0x2a, /* 0x2a (Unsoiicited) */ + EVENT_ID_BATCH_RESULT = 0x2b, /* 0x2b (Query) */ + /* CFG_SUPPORT_GSCN */ + EVENT_ID_GSCAN_CAPABILITY = 0x30, + EVENT_ID_GSCAN_SCAN_COMPLETE = 0x31, + EVENT_ID_GSCAN_FULL_RESULT = 0x32, + EVENT_ID_GSCAN_SIGNIFICANT_CHANGE = 0x33, + EVENT_ID_GSCAN_GEOFENCE_FOUND = 0x34, + EVENT_ID_GSCAN_SCAN_AVAILABLE = 0x35, + EVENT_ID_GSCAN_RESULT = 0x36, + + EVENT_ID_UART_ACK = 0x40, /* 0x40 (Unsolicited) */ + EVENT_ID_UART_NAK, /* 0x41 (Unsolicited) */ + EVENT_ID_GET_CHIPID, /* 0x42 (Query - CMD_ID_GET_CHIPID) */ + EVENT_ID_SLT_STATUS, /* 0x43 (Query - CMD_ID_SET_SLTINFO) */ + EVENT_ID_CHIP_CONFIG, /* 0x44 (Query - CMD_ID_CHIP_CONFIG) */ + EVENT_ID_GET_TSM_STATISTICS = 0x47, + +#if CFG_SUPPORT_QA_TOOL + EVENT_ID_ACCESS_RX_STAT, /* 0x45 (Query - CMD_ID_ACCESS_RX_STAT) */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +#if CFG_SUPPORT_TX_BF + EVENT_ID_PFMU_TAG_READ = 0x46, + EVENT_ID_PFMU_DATA_READ = 0x47, +#endif + + EVENT_ID_RDD_SEND_PULSE = 0x50, + +#if CFG_RX_BA_REORDERING_ENHANCEMENT + EVENT_ID_BA_FW_DROP_SN = 0x51, +#endif + +#if CFG_SUPPORT_MU_MIMO + EVENT_ID_MU_GET_QD = 0x53, + EVENT_ID_MU_GET_LQ = 0x54, +#endif + + EVENT_ID_RSP_CHNL_UTILIZATION = 0x59, /* 0x59 (Query - CMD_ID_REQ_CHNL_UTILIZATION) */ + + EVENT_ID_TDLS = 0x80, /* TDLS event_id */ + EVENT_ID_REPORT_MISC = 0x8A, /* Report_misc event_id */ + EVENT_ID_WIFI_LOG_LEVEL = 0x8D, + EVENT_ID_UPDATE_FW_INFO = 0x90, /* 0x90 (Unsolicited) */ + EVENT_ID_RSSI_MONITOR = 0xA1, + + EVENT_ID_BUILD_DATE_CODE = 0xF8, + EVENT_ID_GET_AIS_BSS_INFO = 0xF9, + EVENT_ID_DEBUG_CODE = 0xFB, + EVENT_ID_RFTEST_READY = 0xFC, /* 0xFC */ + EVENT_ID_END +} ENUM_EVENT_ID_T, *P_ENUM_EVENT_ID_T; +enum ENUM_SCN_FUNC_MASK { + ENUM_SCN_RANDOM_MAC_EN = (1 << 0), +}; + +#define CMD_ID_SET_PSCN_ADD_HOTLIST_BSSID CMD_ID_SET_GSCAN_ADD_HOTLIST_BSSID /* 0x45 (Set) */ +#define CMD_ID_SET_PSCN_ADD_SW_BSSID CMD_ID_SET_GSCAN_ADD_SWC_BSSID /* 0x46 (Set) */ +#define CMD_ID_SET_PSCN_MAC_ADDR CMD_ID_SET_GSCAN_MAC_ADDR /* 0x65 (Set) */ /* 0x47 (Set) */ +#define CMD_ID_SET_PSCN_ENABLE CMD_ID_SET_PSCAN_ENABLE + +#define NLO_CHANNEL_TYPE_SPECIFIED 0 +#define NLO_CHANNEL_TYPE_DUAL_BAND 1 +#define NLO_CHANNEL_TYPE_2G4_ONLY 2 +#define NLO_CHANNEL_TYPE_5G_ONLY 3 + +/******************************************************************************* +* 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; /* Max value is over 2048 */ + UINT_16 u2PQ_ID; /* Must be 0x8000 (Port1, Queue 0) */ + UINT_8 ucCID; + UINT_8 ucPktTypeID; /* Must be 0x20 (CMD Packet) */ + UINT_8 ucSetQuery; + UINT_8 ucSeqNum; + + 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 u2PacketLength; + UINT_16 u2PacketType; /* Must be filled with 0xE000 (EVENT Packet) */ + UINT_8 ucEID; + UINT_8 ucSeqNum; + UINT_8 aucReserved[2]; + + UINT_8 aucBuffer[0]; +} WIFI_EVENT_T, *P_WIFI_EVENT_T; + +/* CMD_ID_TEST_CTRL */ +typedef struct _CMD_TEST_CTRL_T { + UINT_8 ucAction; + UINT_8 aucReserved[3]; + union { + UINT_32 u4OpMode; + UINT_32 u4ChannelFreq; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + } u; +} CMD_TEST_CTRL_T, *P_CMD_TEST_CTRL_T; + +/* EVENT_TEST_STATUS */ +typedef struct _PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T { + UINT_32 u4PktSentStatus; + UINT_32 u4PktSentCount; + UINT_16 u2AvgAlc; + UINT_8 ucCckGainControl; + UINT_8 ucOfdmGainControl; +} PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T, *P_PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T; + +typedef struct _PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T { + UINT_32 u4IntRxOk; /*!< number of packets that Rx ok from interrupt */ + UINT_32 u4IntCrcErr; /*!< number of packets that CRC error from interrupt */ + UINT_32 u4IntShort; /*!< number of packets that is short preamble from interrupt */ + UINT_32 u4IntLong; /*!< number of packets that is long preamble from interrupt */ + UINT_32 u4PauRxPktCount; /*!< number of packets that Rx ok from PAU */ + UINT_32 u4PauCrcErrCount; /*!< number of packets that CRC error from PAU */ + UINT_32 u4PauRxFifoFullCount; /*!< number of packets that is short preamble from PAU */ + UINT_32 u4PauCCACount; /*!< CCA rising edge count */ +} PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T, *P_PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T; + +typedef union _EVENT_TEST_STATUS { + PARAM_MTK_WIFI_TEST_STRUCT_T rATInfo; +/* PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T rTxStatus; */ +/* PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T rRxStatus; */ +} EVENT_TEST_STATUS, *P_EVENT_TEST_STATUS; + +/* CMD_BUILD_CONNECTION */ +typedef struct _CMD_BUILD_CONNECTION { + UINT_8 ucInfraMode; + UINT_8 ucAuthMode; + UINT_8 ucEncryptStatus; + UINT_8 ucSsidLen; + UINT_8 aucSsid[PARAM_MAX_LEN_SSID]; + UINT_8 aucBssid[PARAM_MAC_ADDR_LEN]; + + /* Ad-hoc mode */ + UINT_16 u2BeaconPeriod; + UINT_16 u2ATIMWindow; + UINT_8 ucJoinOnly; + UINT_8 ucReserved; + UINT_32 u4FreqInKHz; + + /* for faster connection */ + UINT_8 aucScanResult[0]; +} CMD_BUILD_CONNECTION, *P_CMD_BUILD_CONNECTION; + +/* CMD_ADD_REMOVE_KEY */ +typedef struct _CMD_802_11_KEY { + UINT_8 ucAddRemove; + UINT_8 ucTxKey; + UINT_8 ucKeyType; + UINT_8 ucIsAuthenticator; + UINT_8 aucPeerAddr[6]; + UINT_8 ucBssIdx; + UINT_8 ucAlgorithmId; + UINT_8 ucKeyId; + UINT_8 ucKeyLen; + UINT_8 ucWlanIndex; + UINT_8 ucMgmtProtection; + UINT_8 aucKeyMaterial[32]; + UINT_8 aucKeyRsc[16]; +} CMD_802_11_KEY, *P_CMD_802_11_KEY; + +/* CMD_ID_DEFAULT_KEY_ID */ +typedef struct _CMD_DEFAULT_KEY { + UINT_8 ucBssIdx; + UINT_8 ucKeyId; + UINT_8 ucUnicast; + UINT_8 ucMulticast; +} CMD_DEFAULT_KEY, *P_CMD_DEFAULT_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 { + UINT_32 u4BSSIDInfoCount; + P_PMKID_ENTRY_T arPMKIDInfo[1]; +} CMD_802_11_PMKID, *P_CMD_802_11_PMKID; + +typedef struct _CMD_GTK_REKEY_DATA_T { + UINT_8 aucKek[16]; + UINT_8 aucKck[16]; + UINT_8 aucReplayCtr[8]; +} CMD_GTK_REKEY_DATA_T, *P_CMD_GTK_REKEY_DATA_T; + +/* CMD_BASIC_CONFIG */ +typedef struct _CMD_CSUM_OFFLOAD_T { + UINT_16 u2RxChecksum; /* bit0: IP, bit1: UDP, bit2: TCP */ + UINT_16 u2TxChecksum; /* bit0: IP, bit1: UDP, bit2: TCP */ +} CMD_CSUM_OFFLOAD_T, *P_CMD_CSUM_OFFLOAD_T; + +typedef struct _CMD_BASIC_CONFIG_T { + UINT_8 ucNative80211; + UINT_8 aucReserved[3]; + + CMD_CSUM_OFFLOAD_T rCsumOffload; +} CMD_BASIC_CONFIG_T, *P_CMD_BASIC_CONFIG_T; + +/* CMD_MAC_MCAST_ADDR */ +typedef struct _CMD_MAC_MCAST_ADDR { + UINT_32 u4NumOfGroupAddr; + UINT_8 ucBssIndex; + UINT_8 aucReserved[3]; + PARAM_MAC_ADDRESS arAddress[MAX_NUM_GROUP_ADDR]; +} CMD_MAC_MCAST_ADDR, *P_CMD_MAC_MCAST_ADDR, EVENT_MAC_MCAST_ADDR, *P_EVENT_MAC_MCAST_ADDR; + +/* CMD_ACCESS_EEPROM */ +typedef struct _CMD_ACCESS_EEPROM { + UINT_16 u2Offset; + UINT_16 u2Data; +} CMD_ACCESS_EEPROM, *P_CMD_ACCESS_EEPROM, EVENT_ACCESS_EEPROM, *P_EVENT_ACCESS_EEPROM; + +typedef struct _CMD_CUSTOM_NOA_PARAM_STRUCT_T { + UINT_32 u4NoaDurationMs; + UINT_32 u4NoaIntervalMs; + UINT_32 u4NoaCount; +} CMD_CUSTOM_NOA_PARAM_STRUCT_T, *P_CMD_CUSTOM_NOA_PARAM_STRUCT_T; + +typedef struct _CMD_CUSTOM_OPPPS_PARAM_STRUCT_T { + UINT_32 u4CTwindowMs; +} CMD_CUSTOM_OPPPS_PARAM_STRUCT_T, *P_CMD_CUSTOM_OPPPS_PARAM_STRUCT_T; + +typedef struct _CMD_CUSTOM_UAPSD_PARAM_STRUCT_T { + UINT_8 fgEnAPSD; + UINT_8 fgEnAPSD_AcBe; + UINT_8 fgEnAPSD_AcBk; + UINT_8 fgEnAPSD_AcVo; + UINT_8 fgEnAPSD_AcVi; + UINT_8 ucMaxSpLen; + UINT_8 aucResv[2]; +} CMD_CUSTOM_UAPSD_PARAM_STRUCT_T, *P_CMD_CUSTOM_UAPSD_PARAM_STRUCT_T; + +struct CMD_SET_MAX_TXPWR_LIMIT { + UINT_8 ucMaxTxPwrLimitEnable; + INT_8 cMaxTxPwr; /* in unit of 0.5 dBm */ + INT_8 cMinTxPwr; /* in unit of 0.5 dBm */ + UINT_8 ucReserved; +}; + +struct CMD_SET_RRM_CAPABILITY { + UINT_8 ucDot11RadioMeasurementEnabled; + UINT_8 aucCapabilities[5]; + UINT_8 aucReserved[2]; +}; + +#if CFG_M0VE_BA_TO_DRIVER +typedef struct _CMD_RESET_BA_SCOREBOARD_T { + UINT_8 ucflag; + UINT_8 ucTID; + UINT_8 aucMacAddr[PARAM_MAC_ADDR_LEN]; +} CMD_RESET_BA_SCOREBOARD_T, *P_CMD_RESET_BA_SCOREBOARD_T; +#endif + + +struct TXPWR_LIMIT_SAR_T { + UINT_8 acTxPwrLimit2G; /* Channel 1~14, Unit: 0.5dBm*/ + UINT_8 acTxPwrLimit5G[4]; /* UNII 1~4 */ +}; + +struct CMD_SAR_ENABLE_T { + UINT_8 u1SAREnable; /*0 : disable , 1 : enable */ + UINT_8 u1CmdVersion; + UINT_8 reserved[2]; + struct TXPWR_LIMIT_SAR_T rTxPwrLmtSar[2];/*0 : main ant , 1 : auxiliary ant */ + /* need 2 group sar parameter for ant0 and ant1 if support antenna swap.*/ +}; + +/* 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_T { + UINT_16 u2ProductID; + UINT_16 u2FwVersion; + UINT_16 u2DriverVersion; + UINT_8 ucHw5GBandDisabled; + UINT_8 ucEepromUsed; + UINT_8 aucMacAddr[6]; + UINT_8 ucEndianOfMacAddrNumber; + UINT_8 ucHwNotSupportAC; + + UINT_8 ucRfVersion; + UINT_8 ucPhyVersion; + UINT_8 ucRfCalFail; + UINT_8 ucBbCalFail; + UINT_8 aucDateCode[16]; + UINT_32 u4FeatureFlag0; + UINT_32 u4FeatureFlag1; + UINT_32 u4CompileFlag0; + UINT_32 u4CompileFlag1; + UINT_8 aucFwVerExtend[4]; + UINT_8 ucAntSwapEn; + UINT_8 aucReserved0[59]; +} EVENT_NIC_CAPABILITY_T, *P_EVENT_NIC_CAPABILITY_T; + +/* 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; + +/* event of add key done for port control */ +typedef struct _EVENT_ADD_KEY_DONE_INFO { + UINT_8 ucBSSIndex; + UINT_8 ucReserved; + UINT_8 aucStaAddr[6]; +} EVENT_ADD_KEY_DONE_INFO, *P_EVENT_ADD_KEY_DONE_INFO; + +typedef struct _EVENT_PMKID_CANDIDATE_LIST_T { + UINT_32 u4Version; /*!< Version */ + UINT_32 u4NumCandidates; /*!< How many candidates follow */ + PARAM_PMKID_CANDIDATE_T arCandidateList[1]; +} EVENT_PMKID_CANDIDATE_LIST_T, *P_EVENT_PMKID_CANDIDATE_LIST_T; + +typedef struct _EVENT_CMD_RESULT { + UINT_8 ucCmdID; + UINT_8 ucStatus; + UINT_8 aucReserved[2]; +} EVENT_CMD_RESULT, *P_EVENT_CMD_RESULT; + +/* CMD_ID_ACCESS_REG & EVENT_ID_ACCESS_REG */ +typedef struct _CMD_ACCESS_REG { + UINT_32 u4Address; + UINT_32 u4Data; +} CMD_ACCESS_REG, *P_CMD_ACCESS_REG; + +/* CMD_DUMP_MEMORY */ +typedef struct _CMD_DUMP_MEM { + UINT_32 u4Address; + UINT_32 u4Length; + UINT_32 u4RemainLength; +#if CFG_SUPPORT_QA_TOOL + UINT_32 u4IcapContent; +#endif /* CFG_SUPPORT_QA_TOOL */ + 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; +#if CFG_SUPPORT_QA_TOOL + UINT_32 eIcapContent; +#endif /* CFG_SUPPORT_QA_TOOL */ + UINT_8 ucFragNum; + UINT_8 aucBuffer[1]; +} EVENT_DUMP_MEM_T, *P_EVENT_DUMP_MEM_T; + +#if CFG_SUPPORT_QA_TOOL +typedef struct _CMD_ACCESS_RX_STAT { + UINT_32 u4SeqNum; + UINT_32 u4TotalNum; + PARAM_RX_STAT_T rRxStat; +} CMD_ACCESS_RX_STAT, *P_CMD_ACCESS_RX_STAT; + +typedef struct _EVENT_ACCESS_RX_STAT { + UINT_32 u4SeqNum; + UINT_32 u4TotalNum; + UINT_32 au4Buffer[1]; +} EVENT_ACCESS_RX_STAT, *P_EVENT_ACCESS_RX_STAT; + +#if CFG_SUPPORT_TX_BF +typedef union _CMD_TXBF_ACTION_T { + PROFILE_TAG_READ_T rProfileTagRead; + PROFILE_TAG_WRITE_T rProfileTagWrite; + PROFILE_DATA_READ_T rProfileDataRead; + PROFILE_DATA_WRITE_T rProfileDataWrite; + PROFILE_PN_READ_T rProfilePnRead; + PROFILE_PN_WRITE_T rProfilePnWrite; + TX_BF_SOUNDING_START_T rTxBfSoundingStart; + TX_BF_SOUNDING_STOP_T rTxBfSoundingStop; + TX_BF_TX_APPLY_T rTxBfTxApply; + TX_BF_PFMU_MEM_ALLOC_T rTxBfPfmuMemAlloc; + TX_BF_PFMU_MEM_RLS_T rTxBfPfmuMemRls; +} CMD_TXBF_ACTION_T, *P_CMD_TXBF_ACTION_T; + +#define CMD_DEVINFO_UPDATE_HDR_SIZE 8 +typedef struct _CMD_DEV_INFO_UPDATE_T { + UINT_8 ucOwnMacIdx; + UINT_8 ucReserve; + UINT_16 u2TotalElementNum; + UINT_8 ucAppendCmdTLV; + UINT_8 aucReserve[3]; + UINT_8 aucBuffer[0]; + /* CMD_DEVINFO_ACTIVE_T rCmdDevInfoActive; */ +} CMD_DEV_INFO_UPDATE_T, *P_CMD_DEV_INFO_UPDATE_T; + +#define CMD_BSSINFO_UPDATE_HDR_SIZE 8 +typedef struct _CMD_BSS_INFO_UPDATE_T { + UINT_8 ucBssIndex; + UINT_8 ucReserve; + UINT_16 u2TotalElementNum; + UINT_32 u4Reserve; + /* CMD_BSSINFO_BASIC_T rCmdBssInfoBasic; */ + UINT_8 aucBuffer[0]; +} CMD_BSS_INFO_UPDATE_T, *P_CMD_BSS_INFO_UPDATE_T; + +/* STA record command */ +#define CMD_STAREC_UPDATE_HDR_SIZE 8 +typedef struct _CMD_STAREC_UPDATE_T { + UINT_8 ucBssIndex; + UINT_8 ucWlanIdx; + UINT_16 u2TotalElementNum; + UINT_32 u4Reserve; + UINT_8 aucBuffer[0]; +} CMD_STAREC_UPDATE_T, *P_CMD_STAREC_UPDATE_T; + +typedef struct _EVENT_PFMU_TAG_READ_T { + PFMU_PROFILE_TAG1 ru4TxBfPFMUTag1; + PFMU_PROFILE_TAG2 ru4TxBfPFMUTag2; +} EVENT_PFMU_TAG_READ_T, *P_EVENT_PFMU_TAG_READ_T; + +#if CFG_SUPPORT_MU_MIMO +typedef struct _EVENT_HQA_GET_QD { + UINT_32 u4EventId; + UINT_32 au4RawData[14]; +} EVENT_HQA_GET_QD, *P_EVENT_HQA_GET_QD; + +typedef struct _EVENT_HQA_GET_MU_CALC_LQ { + UINT_32 u4EventId; + MU_STRUCT_LQ_REPORT rEntry; +} EVENT_HQA_GET_MU_CALC_LQ, *P_EVENT_HQA_GET_MU_CALC_LQ; + +typedef struct _EVENT_SHOW_GROUP_TBL_ENTRY { + UINT_32 u4EventId; + UINT_8 index; + UINT_8 numUser:2; + UINT_8 BW:2; + UINT_8 NS0:2; + UINT_8 NS1:2; + /* UINT_8 NS2:1; */ + /* UINT_8 NS3:1; */ + UINT_8 PFIDUser0; + UINT_8 PFIDUser1; + /* UINT_8 PFIDUser2; */ + /* UINT_8 PFIDUser3; */ + BOOLEAN fgIsShortGI; + BOOLEAN fgIsUsed; + BOOLEAN fgIsDisable; + UINT_8 initMcsUser0:4; + UINT_8 initMcsUser1:4; + /* UINT_8 initMcsUser2:4; */ + /* UINT_8 initMcsUser3:4; */ + UINT_8 dMcsUser0:4; + UINT_8 dMcsUser1:4; + /* UINT_8 dMcsUser2:4; */ + /* UINT_8 dMcsUser3:4; */ +} EVENT_SHOW_GROUP_TBL_ENTRY, *P_EVENT_SHOW_GROUP_TBL_ENTRY; + +typedef union _CMD_MUMIMO_ACTION_T { + UINT_8 ucMuMimoCategory; + UINT_8 aucRsv[3]; + union { + MU_GET_CALC_INIT_MCS_T rMuGetCalcInitMcs; + MU_SET_INIT_MCS_T rMuSetInitMcs; + MU_SET_CALC_LQ_T rMuSetCalcLq; + MU_GET_LQ_T rMuGetLq; + MU_SET_SNR_OFFSET_T rMuSetSnrOffset; + MU_SET_ZERO_NSS_T rMuSetZeroNss; + MU_SPEED_UP_LQ_T rMuSpeedUpLq; + MU_SET_MU_TABLE_T rMuSetMuTable; + MU_SET_GROUP_T rMuSetGroup; + MU_GET_QD_T rMuGetQd; + MU_SET_ENABLE_T rMuSetEnable; + MU_SET_GID_UP_T rMuSetGidUp; + MU_TRIGGER_MU_TX_T rMuTriggerMuTx; + } unMuMimoParam; +} CMD_MUMIMO_ACTION_T, *P_CMD_MUMIMO_ACTION_T; +#endif /* CFG_SUPPORT_MU_MIMO */ +#endif /* CFG_SUPPORT_TX_BF */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +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; +typedef struct _CMD_GET_FW_INFO_T { + UINT_8 ucValue; +} CMD_GET_FW_INFO_T, *P_CMD_GET_FW_INFO_T; + +typedef struct _CMD_CHIP_CONFIG_T { + UINT_16 u2Id; + UINT_8 ucType; + UINT_8 ucRespType; + UINT_16 u2MsgSize; + UINT_8 aucReserved0[2]; + UINT_8 aucCmd[CHIP_CONFIG_RESP_SIZE]; +} CMD_CHIP_CONFIG_T, *P_CMD_CHIP_CONFIG_T; + +/* 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 ucBssIndex; + UINT_8 ucPsProfile; + UINT_8 aucReserved[2]; +} CMD_PS_PROFILE_T, *P_CMD_PS_PROFILE_T; + +/* EVENT_LINK_QUALITY */ +#if 1 +typedef struct _LINK_QUALITY_ { + INT_8 cRssi; /* AIS Network. */ + INT_8 cLinkQuality; + UINT_16 u2LinkSpeed; /* TX rate1 */ + UINT_8 ucMediumBusyPercentage; /* Read clear */ + UINT_8 ucIsLQ0Rdy; /* Link Quality BSS0 Ready. */ +} LINK_QUALITY, *P_LINK_QUALITY; + +typedef struct _EVENT_LINK_QUALITY_V2 { + LINK_QUALITY rLq[BSSID_NUM]; +} EVENT_LINK_QUALITY_V2, *P_EVENT_LINK_QUALITY_V2; + +typedef struct _EVENT_LINK_QUALITY { + INT_8 cRssi; + INT_8 cLinkQuality; + UINT_16 u2LinkSpeed; + UINT_8 ucMediumBusyPercentage; +} EVENT_LINK_QUALITY, *P_EVENT_LINK_QUALITY; +#endif + +#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; +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + LARGE_INTEGER rMdrdyCnt; + LARGE_INTEGER rChnlIdleCnt; +#endif +} EVENT_STATISTICS, *P_EVENT_STATISTICS; + +/* EVENT_ID_FW_SLEEPY_NOTIFY */ +typedef struct _EVENT_SLEEPY_INFO_T { + UINT_8 ucSleepyState; + UINT_8 aucReserved[3]; +} EVENT_SLEEPY_INFO_T, *P_EVENT_SLEEPY_INFO_T; + +typedef struct _EVENT_ACTIVATE_STA_REC_T { + UINT_8 aucMacAddr[6]; + UINT_8 ucStaRecIdx; + UINT_8 ucBssIndex; +} EVENT_ACTIVATE_STA_REC_T, *P_EVENT_ACTIVATE_STA_REC_T; + +typedef struct _EVENT_DEACTIVATE_STA_REC_T { + UINT_8 ucStaRecIdx; + UINT_8 aucReserved[3]; +} EVENT_DEACTIVATE_STA_REC_T, *P_EVENT_DEACTIVATE_STA_REC_T; + +/* CMD_BT_OVER_WIFI */ +typedef struct _CMD_BT_OVER_WIFI { + UINT_8 ucAction; /* 0: query, 1: setup, 2: destroy */ + UINT_8 ucChannelNum; + PARAM_MAC_ADDRESS rPeerAddr; + UINT_16 u2BeaconInterval; + UINT_8 ucTimeoutDiscovery; + UINT_8 ucTimeoutInactivity; + UINT_8 ucRole; + UINT_8 PAL_Capabilities; + UINT_8 cMaxTxPower; + UINT_8 ucChannelBand; + UINT_8 ucReserved[1]; +} CMD_BT_OVER_WIFI, *P_CMD_BT_OVER_WIFI; + +/* EVENT_BT_OVER_WIFI */ +typedef struct _EVENT_BT_OVER_WIFI { + UINT_8 ucLinkStatus; + UINT_8 ucSelectedChannel; + INT_8 cRSSI; + UINT_8 ucReserved[1]; +} EVENT_BT_OVER_WIFI, *P_EVENT_BT_OVER_WIFI; + +/* Same with DOMAIN_SUBBAND_INFO */ +typedef struct _CMD_SUBBAND_INFO { + UINT_8 ucRegClass; + UINT_8 ucBand; + UINT_8 ucChannelSpan; + UINT_8 ucFirstChannelNum; + UINT_8 ucNumChannels; + UINT_8 aucReserved[3]; +} CMD_SUBBAND_INFO, *P_CMD_SUBBAND_INFO; + +/* CMD_SET_DOMAIN_INFO */ +typedef struct _CMD_SET_DOMAIN_INFO_T { + UINT_16 u2CountryCode; + UINT_16 u2IsSetPassiveScan; + CMD_SUBBAND_INFO rSubBand[6]; + + UINT_8 uc2G4Bandwidth; /* CONFIG_BW_20_40M or CONFIG_BW_20M */ + UINT_8 uc5GBandwidth; /* CONFIG_BW_20_40M or CONFIG_BW_20M */ + UINT_8 aucReserved[2]; +} CMD_SET_DOMAIN_INFO_T, *P_CMD_SET_DOMAIN_INFO_T; + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +/* CMD_SET_PWR_LIMIT_TABLE */ +typedef struct _CMD_CHANNEL_POWER_LIMIT { + UINT_8 ucCentralCh; + INT_8 cPwrLimitCCK; + INT_8 cPwrLimit20; + INT_8 cPwrLimit40; + INT_8 cPwrLimit80; + INT_8 cPwrLimit160; + UINT_8 ucFlag; + UINT_8 aucReserved[1]; +} CMD_CHANNEL_POWER_LIMIT, *P_CMD_CHANNEL_POWER_LIMIT; + +typedef struct _CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T { + UINT_16 u2CountryCode; + UINT_8 ucCountryFlag; + UINT_8 ucNum; + UINT_8 aucReserved[4]; + CMD_CHANNEL_POWER_LIMIT rChannelPowerLimit[1]; +} CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T, *P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T; + +#endif + +/* CMD_SET_IP_ADDRESS */ +typedef struct _IPV4_NETWORK_ADDRESS { + UINT_8 aucIpAddr[4]; +} IPV4_NETWORK_ADDRESS, *P_IPV4_NETWORK_ADDRESS; + +typedef struct _CMD_SET_NETWORK_ADDRESS_LIST { + UINT_8 ucBssIndex; + 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 u2PatternOffset; + 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_8 ucWlanIndex; + UINT_8 ucTxCount; + UINT_16 u2TxRate; + UINT_8 ucFlag; + UINT_8 au4Reserved2[3]; + UINT_32 au4Reserved3; +} EVENT_TX_DONE_T, *P_EVENT_TX_DONE_T; + +typedef struct _CMD_BSS_ACTIVATE_CTRL { + UINT_8 ucBssIndex; + UINT_8 ucActive; + UINT_8 ucNetworkType; + UINT_8 ucOwnMacAddrIndex; + UINT_8 aucBssMacAddr[6]; + UINT_8 ucBMCWlanIndex; + UINT_8 ucReserved; +} CMD_BSS_ACTIVATE_CTRL, *P_CMD_BSS_ACTIVATE_CTRL; + +typedef struct _CMD_SET_BSS_RLM_PARAM_T { + UINT_8 ucBssIndex; + 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 ucVhtChannelWidth; + UINT_8 ucVhtChannelFrequencyS1; + UINT_8 ucVhtChannelFrequencyS2; + UINT_16 u2VhtBasicMcsSet; +} CMD_SET_BSS_RLM_PARAM_T, *P_CMD_SET_BSS_RLM_PARAM_T; + +typedef struct _CMD_SET_BSS_INFO { + UINT_8 ucBssIndex; + 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_16 u2HwDefaultFixedRateCode; + UINT_8 ucNonHTBasicPhyType; /* For Slot Time and CWmin */ + UINT_8 ucAuthMode; + UINT_8 ucEncStatus; + UINT_8 ucPhyTypeSet; + UINT_8 ucWapiMode; + UINT_8 ucIsApMode; + UINT_8 ucBMCWlanIndex; + UINT_8 ucHiddenSsidMode; + UINT_8 ucDisconnectDetectTh; + UINT_32 u4PrivateData; + CMD_SET_BSS_RLM_PARAM_T rBssRlmParam; +} CMD_SET_BSS_INFO, *P_CMD_SET_BSS_INFO; + +typedef enum _ENUM_RTS_POLICY_T { + RTS_POLICY_AUTO, + RTS_POLICY_STATIC_BW, + RTS_POLICY_DYNAMIC_BW, + RTS_POLICY_LEGACY, + RTS_POLICY_NO_RTS +} ENUM_RTS_POLICY; + +typedef struct _CMD_UPDATE_STA_RECORD_T { + UINT_8 ucStaIndex; + UINT_8 ucStaType; + /* This field should assign at create and keep consistency for update usage */ + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + + UINT_16 u2AssocId; + UINT_16 u2ListenInterval; + UINT_8 ucBssIndex; /* This field should assign at create and keep consistency for update usage */ + 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 aucReserved1[1]; + + UINT_8 aucRxMcsBitmask[10]; + UINT_16 u2RxHighestSupportedRate; + UINT_32 u4TxRateInfo; + + UINT_16 u2HtCapInfo; + UINT_16 u2HtExtendedCap; + UINT_32 u4TxBeamformingCap; + + UINT_8 ucAmpduParam; + 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 ucWlanIndex; /* This field should assign at create and keep consistency for update usage */ + UINT_8 ucBMCWlanIndex; /* This field should assign at create and keep consistency for update usage */ + + UINT_32 u4VhtCapInfo; + UINT_16 u2VhtRxMcsMap; + UINT_16 u2VhtRxHighestSupportedDataRate; + UINT_16 u2VhtTxMcsMap; + UINT_16 u2VhtTxHighestSupportedDataRate; + UINT_8 ucRtsPolicy; /* 0: auto 1: Static BW 2: Dynamic BW 3: Legacy 7: WoRts */ + UINT_8 aucReserved2[1]; + + UINT_8 ucTrafficDataType; /* 0: auto 1: data 2: video 3: voice */ + UINT_8 ucTxGfMode; + UINT_8 ucTxSgiMode; + UINT_8 ucTxStbcMode; + UINT_16 u2HwDefaultFixedRateCode; + UINT_8 ucTxAmpdu; + UINT_8 ucRxAmpdu; + UINT_32 u4FixedPhyRate; /* */ + UINT_16 u2MaxLinkSpeed; /* unit is 0.5 Mbps */ + UINT_16 u2MinLinkSpeed; + + UINT_32 u4Flags; + + UINT_8 ucTxBaSize; + UINT_8 ucRxBaSize; + UINT_16 u2KeepAliveDuration; /* unit is 1s */ + UINT_8 ucKeepAliveOption; /* only bit0 is used now */ + UINT_8 aucReserved4[27]; +} CMD_UPDATE_STA_RECORD_T, *P_CMD_UPDATE_STA_RECORD_T; + +typedef struct _CMD_REMOVE_STA_RECORD_T { + UINT_8 ucActionType; + UINT_8 ucStaIndex; + UINT_8 ucBssIndex; + UINT_8 ucReserved; +} CMD_REMOVE_STA_RECORD_T, *P_CMD_REMOVE_STA_RECORD_T; + +typedef struct _CMD_INDICATE_PM_BSS_CREATED_T { + UINT_8 ucBssIndex; + 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 ucBssIndex; + 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 ucBssIndex; + UINT_8 aucReserved[3]; +} CMD_INDICATE_PM_BSS_ABORT, *P_CMD_INDICATE_PM_BSS_ABORT; + +typedef struct _CMD_BEACON_TEMPLATE_UPDATE { +/* 0: update randomly, 1: update all, 2: delete all (1 and 2 will update directly without search) */ + UINT_8 ucUpdateMethod; + UINT_8 ucBssIndex; + UINT_8 aucReserved[2]; + UINT_16 u2Capability; + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; +} CMD_BEACON_TEMPLATE_UPDATE, *P_CMD_BEACON_TEMPLATE_UPDATE; + +typedef struct _CMD_SET_WMM_PS_TEST_STRUCT_T { + UINT_8 ucBssIndex; + UINT_8 bmfgApsdEnAc; /* b0~3: trigger-en AC0~3. b4~7: delivery-en AC0~3 */ + UINT_8 ucIsEnterPsAtOnce; /* enter PS immediately without 5 second guard after connected */ + UINT_8 ucIsDisableUcTrigger; /* not to trigger UC on beacon TIM is matched (under U-APSD) */ +} CMD_SET_WMM_PS_TEST_STRUCT_T, *P_CMD_SET_WMM_PS_TEST_STRUCT_T; + +typedef struct _GSCN_CHANNEL_INFO_T { + UINT_8 ucBand; + UINT_8 ucChannelNumber; /* Channel Number */ + UINT_8 ucPassive; /* 0 => active, 1 => passive scan; ignored for DFS */ + UINT_8 aucReserved[1]; + + UINT_32 u4DwellTimeMs; /* dwell time hint */ + /* Add channel class */ +} GSCN_CHANNEL_INFO_T, *P_GSCN_CHANNEL_INFO_T; + +typedef struct _GSCAN_BUCKET_T { + UINT_16 u2BucketIndex; /* bucket index, 0 based */ + UINT_8 ucBucketFreqMultiple; /* desired period, in millisecond; + * if this is too low, the firmware should choose to generate + * results as fast as it can instead of failing the command + */ + /* report_events semantics - + * This is a bit field; which defines following bits - + * REPORT_EVENTS_EACH_SCAN => report a scan completion event after scan. If this is not set + * then scan completion events should be reported if + * report_threshold_percent or report_threshold_num_scans is + * reached. + * REPORT_EVENTS_FULL_RESULTS => forward scan results (beacons/probe responses + IEs) + * in real time to HAL, in addition to completion events + * Note: To keep backward compatibility, fire completion + * events regardless of REPORT_EVENTS_EACH_SCAN. + * REPORT_EVENTS_NO_BATCH => controls if scans for this bucket should be placed in the + * history buffer + */ + UINT_8 ucReportFlag; + UINT_8 ucMaxBucketFreqMultiple; /* max_period / base_period */ + UINT_8 ucStepCount; + UINT_8 ucNumChannels; + UINT_8 aucReserved[1]; + WIFI_BAND eBand; /* when UNSPECIFIED, use channel list */ + GSCN_CHANNEL_INFO_T arChannelList[GSCAN_MAX_CHANNELS]; /* channels to scan; these may include DFS channels */ +} GSCAN_BUCKET_T, *P_GSCAN_BUCKET_T; + +typedef struct _CMD_GSCN_REQ_T { + UINT_8 ucFlags; + UINT_8 ucNumScnToCache; + UINT_8 aucReserved[2]; + UINT_32 u4BufferThreshold; + UINT_32 u4BasePeriod; /* base timer period in ms */ + UINT_32 u4NumBuckets; + UINT_32 u4MaxApPerScan; /* number of APs to store in each scan in the */ + /* BSSID/RSSI history buffer (keep the highest RSSI APs) */ + GSCAN_BUCKET_T arBucket[GSCAN_MAX_BUCKETS]; +} CMD_GSCN_REQ_T, *P_CMD_GSCN_REQ_T; + +typedef struct _CMD_GSCN_SCN_COFIG_T { + UINT_8 ucNumApPerScn; /* GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN */ + UINT_32 u4BufferThreshold; /* GSCAN_ATTRIBUTE_REPORT_THRESHOLD */ + UINT_32 u4NumScnToCache; /* GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE */ +} CMD_GSCN_SCN_COFIG_T, *P_CMD_GSCN_SCN_COFIG_T; + +typedef struct _CMD_GET_GSCAN_RESULT { + UINT_8 ucVersion; + UINT_8 aucReserved[2]; + UINT_8 ucFlush; + UINT_32 u4Num; +} CMD_GET_GSCAN_RESULT_T, *P_CMD_GET_GSCAN_RESULT_T; + +/* 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; + +enum _CMD_SCAN_REQ_VER_E { + CMD_SCAN_REQ_VER_1 = 1, + CMD_SCAN_REQ_VER_2, + CMD_SCAN_REQ_VER_3, + CMD_SCAN_REQ_VER_4, + CMD_SCAN_REQ_VER_MAX, +}; +enum _SCAN_REQ_MSG_VER_E { + SCAN_REQ_MSG_VER_1 = 1, + SCAN_REQ_MSG_VER_2, + SCAN_REQ_MSG_VER_3, + SCAN_REQ_MSG_VER_MAX, +}; + +typedef struct _CMD_SCAN_REQ_T { + UINT_8 ucSeqNum; + UINT_8 ucBssIndex; + UINT_8 ucScanType; + UINT_8 ucSSIDType; /* BIT(0) wildcard / BIT(1) P2P-wildcard / BIT(2) specific */ + UINT_8 ucSSIDLength; + UINT_8 ucNumProbeReq; + UINT_16 u2ChannelMinDwellTime; + UINT_16 u2ChannelDwellTime; + UINT_16 u2TimeoutValue; + UINT_8 aucSSID[32]; + UINT_8 ucChannelType; + UINT_8 ucChannelListNum; + UINT_8 aucReserved[2]; + 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 ucBssIndex; + UINT_8 ucScanType; + UINT_8 ucSSIDType; + UINT_8 ucSSIDNum; + UINT_8 ucNumProbeReq; + UINT_8 ucReserved; + UINT_8 ucStructVersion; + PARAM_SSID_T arSSID[CFG_SCAN_SSID_MAX_NUM]; + UINT_16 u2ProbeDelayTime; + UINT_16 u2ChannelMinDwellTime; + UINT_16 u2ChannelDwellTime; + UINT_16 u2TimeoutValue; + UINT_8 aucBSSID[MAC_ADDR_LEN]; + UINT_8 ucChannelType; + UINT_8 ucChannelListNum; + CHANNEL_INFO_T arChannelList[MAXIMUM_OPERATION_CHANNEL_LIST]; + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; +} CMD_SCAN_REQ_V2, *P_CMD_SCAN_REQ_V2; +struct _CMD_SCAN_REQ_V3_T { + UINT_8 ucSeqNum; + UINT_8 ucBssIndex; + UINT_8 ucScanType; + UINT_8 ucSSIDType; + UINT_8 ucSSIDNum; + UINT_8 ucNumProbeReq; + UINT_8 ucReserved; + UINT_8 ucStructVersion; + PARAM_SSID_T arSSID[CFG_SCAN_SSID_MAX_NUM]; + UINT_16 u2ProbeDelayTime; + UINT_16 u2ChannelMinDwellTime; + UINT_16 u2ChannelDwellTime; + UINT_16 u2TimeoutValue; + UINT_8 aucBSSID[MAC_ADDR_LEN]; + UINT_8 aucRandomMac[MAC_ADDR_LEN]; + UINT_8 ucScnFuncMask; + UINT_8 ucChannelType; + UINT_8 ucChannelListNum; + CHANNEL_INFO_T arChannelList[MAXIMUM_OPERATION_CHANNEL_LIST]; + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; +}; + + +typedef struct _CMD_SCAN_CANCEL_T { + UINT_8 ucSeqNum; + UINT_8 ucIsExtChannel; /* For P2P channel extension. */ + UINT_8 aucReserved[2]; +} CMD_SCAN_CANCEL, *P_CMD_SCAN_CANCEL; + +/* 20150107 Daniel Added complete channels number in the scan done event */ +/* before*/ +/* + * typedef struct _EVENT_SCAN_DONE_T { + * UINT_8 ucSeqNum; + * UINT_8 ucSparseChannelValid; + * CHANNEL_INFO_T rSparseChannel; + * } EVENT_SCAN_DONE, *P_EVENT_SCAN_DONE; + */ +/* after */ +typedef struct _EVENT_SCAN_DONE_T { + UINT_8 ucSeqNum; + UINT_8 ucSparseChannelValid; + CHANNEL_INFO_T rSparseChannel; + /*scan done version #2 */ + UINT_8 ucCompleteChanCount; + UINT_8 ucCurrentState; + UINT_8 ucScanDoneVersion; + /*scan done version #3 */ + UINT_8 ucReserved; + UINT_32 u4ScanDurBcnCnt; + UINT_8 fgIsPNOenabled; + UINT_8 aucReserving[3]; +} EVENT_SCAN_DONE, *P_EVENT_SCAN_DONE; + +#if CFG_SUPPORT_BATCH_SCAN +typedef struct _CMD_BATCH_REQ_T { + UINT_8 ucSeqNum; + UINT_8 ucNetTypeIndex; + UINT_8 ucCmd; /* Start/ Stop */ + UINT_8 ucMScan; /* an integer number of scans per batch */ + UINT_8 ucBestn; /* an integer number of the max AP to remember per scan */ + UINT_8 ucRtt; /* + * an integer number of highest-strength AP for which we'd + * like approximate distance reported + */ + UINT_8 ucChannel; /* channels */ + UINT_8 ucChannelType; + UINT_8 ucChannelListNum; + UINT_8 aucReserved[3]; + UINT_32 u4Scanfreq; /* an integer number of seconds between scans */ + CHANNEL_INFO_T arChannelList[32]; /* channels */ +} CMD_BATCH_REQ_T, *P_CMD_BATCH_REQ_T; + +typedef struct _EVENT_BATCH_RESULT_ENTRY_T { + UINT_8 aucBssid[MAC_ADDR_LEN]; + UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; + UINT_8 ucSSIDLen; + INT_8 cRssi; + UINT_32 ucFreq; + UINT_32 u4Age; + UINT_32 u4Dist; + UINT_32 u4Distsd; +} EVENT_BATCH_RESULT_ENTRY_T, *P_EVENT_BATCH_RESULT_ENTRY_T; + +typedef struct _EVENT_BATCH_RESULT_T { + UINT_8 ucScanCount; + UINT_8 aucReserved[3]; + EVENT_BATCH_RESULT_ENTRY_T arBatchResult[12]; /* Must be the same with SCN_BATCH_STORE_MAX_NUM */ +} EVENT_BATCH_RESULT_T, *P_EVENT_BATCH_RESULT_T; +#endif + +typedef struct _CMD_CH_PRIVILEGE_T { + UINT_8 ucBssIndex; + UINT_8 ucTokenID; + UINT_8 ucAction; + UINT_8 ucPrimaryChannel; + UINT_8 ucRfSco; + UINT_8 ucRfBand; + UINT_8 ucRfChannelWidth; /* To support 80/160MHz bandwidth */ + UINT_8 ucRfCenterFreqSeg1; /* To support 80/160MHz bandwidth */ + UINT_8 ucRfCenterFreqSeg2; /* To support 80/160MHz bandwidth */ + UINT_8 ucReqType; + UINT_8 aucReserved[2]; + UINT_32 u4MaxInterval; /* In unit of ms */ +} CMD_CH_PRIVILEGE_T, *P_CMD_CH_PRIVILEGE_T; + +typedef struct _CMD_TX_PWR_T { + INT_8 cTxPwr2G4Cck; /* signed, in unit of 0.5dBm */ + INT_8 cTxPwr2G4Dsss; /* signed, in unit of 0.5dBm */ + INT_8 acReserved[2]; + + 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_TX_AC_PWR_T { + INT_8 ucBand; +#if 0 + INT_8 c11AcTxPwr_BPSK; + INT_8 c11AcTxPwr_QPSK; + INT_8 c11AcTxPwr_16QAM; + INT_8 c11AcTxPwr_MCS5_MCS6; + INT_8 c11AcTxPwr_MCS7; + INT_8 c11AcTxPwr_MCS8; + INT_8 c11AcTxPwr_MCS9; + INT_8 c11AcTxPwrVht40_OFFSET; + INT_8 c11AcTxPwrVht80_OFFSET; + INT_8 c11AcTxPwrVht160_OFFSET; +#else + AC_PWR_SETTING_STRUCT rAcPwr; +#endif +} CMD_TX_AC_PWR_T, *P_CMD_TX_AC_PWR_T; + +typedef struct _CMD_RSSI_PATH_COMPASATION_T { + INT_8 c2GRssiCompensation; + INT_8 c5GRssiCompensation; +} CMD_RSSI_PATH_COMPASATION_T, *P_CMD_RSSI_PATH_COMPASATION_T; +typedef struct _CMD_5G_PWR_OFFSET_T { + INT_8 cOffsetBand0; /* 4.915-4.980G */ + INT_8 cOffsetBand1; /* 5.000-5.080G */ + INT_8 cOffsetBand2; /* 5.160-5.180G */ + INT_8 cOffsetBand3; /* 5.200-5.280G */ + INT_8 cOffsetBand4; /* 5.300-5.340G */ + INT_8 cOffsetBand5; /* 5.500-5.580G */ + INT_8 cOffsetBand6; /* 5.600-5.680G */ + INT_8 cOffsetBand7; /* 5.700-5.825G */ +} CMD_5G_PWR_OFFSET_T, *P_CMD_5G_PWR_OFFSET_T; + +typedef struct _CMD_PWR_PARAM_T { + UINT_32 au4Data[28]; + UINT_32 u4RefValue1; + UINT_32 u4RefValue2; +} CMD_PWR_PARAM_T, *P_CMD_PWR_PARAM_T; + +typedef struct _CMD_PHY_PARAM_T { + UINT_8 aucData[144]; /* eFuse content */ +} CMD_PHY_PARAM_T, *P_CMD_PHY_PARAM_T; + +typedef struct _CMD_AUTO_POWER_PARAM_T { + UINT_8 ucType; /* 0: Disable 1: Enalbe 0x10: Change parameters */ + UINT_8 ucBssIndex; + 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; + +/*for WMMAC, CMD_ID_UPDATE_AC_PARAMS*/ +typedef struct _CMD_UPDATE_AC_PARAMS_T { + UINT_8 ucAcIndex; /*0 ~3, from AC0 to AC3*/ + UINT_8 ucBssIdx; /*no use*/ + UINT_16 u2MediumTime; /*if 0, disable ACM for ACx specified by ucAcIndex, otherwise in unit of 32us*/ + UINT_32 u4PhyRate; /* rate to be used to tx packet with priority ucAcIndex , unit: bps */ + UINT_16 u2EDCALifeTime; /* msdu life time for this TC, unit: 2TU */ + UINT_8 ucRetryCount; /* if we use fix rate to tx packets, should tell firmware the limited retries */ + UINT_8 aucReserved[5]; +} CMD_UPDATE_AC_PARAMS_T, *P_CMD_UPDATE_AC_PARAMS_T; +/* S56 Traffic Stream Metrics */ +typedef struct _CMD_SET_TSM_STATISTICS_REQUEST_T { + UINT_8 ucEnabled; /* 0, disable; 1, enable; */ + UINT_8 ucBssIdx; /* always AIS Bss index now */ + UINT_8 ucAcIndex; /* wmm ac index, the statistics should be on this TC */ + UINT_8 ucTid; + UINT_8 aucPeerAddr[MAC_ADDR_LEN]; /* packet to the target address to be mesured */ + UINT_8 ucBin0Range; + UINT_8 aucReserved[3]; + + /* if this variable is 0, followed variables are meaningless + ** only report once for a same trigger condition in this time frame + */ + UINT_8 ucTriggerCondition; /* for triggered mode: bit(0):average, bit(1):consecutive, bit(2):delay */ + UINT_8 ucAvgErrThreshold; + UINT_8 ucConsecutiveErrThreshold; + UINT_8 ucDelayThreshold; + UINT_8 ucMeasureCount; + UINT_8 ucTriggerTimeout; /* unit: 100 TU*/ +} CMD_SET_TSM_STATISTICS_REQUEST_T, *P_CMD_SET_TSM_STATISTICS_REQUEST_T; + +typedef struct _CMD_GET_TSM_STATISTICS_T { + UINT_8 ucBssIdx; /* always AIS Bss now */ + UINT_8 ucAcIndex; /* wmm ac index, the statistics should be on this TC or TS */ + UINT_8 ucTid; /* */ + UINT_8 aucPeerAddr[MAC_ADDR_LEN]; /* indicating the RA for the measured frames */ + UINT_8 ucReportReason; /* for triggered mode: bit(0):average, bit(1):consecutive, bit(2):delay */ + UINT_16 u2Reserved; + + UINT_32 u4PktTxDoneOK; + UINT_32 u4PktDiscard; /* u2PktTotal - u2PktTxDoneOK */ + UINT_32 u4PktFail; /* failed count for exceeding retry limit */ + UINT_32 u4PktRetryTxDoneOK; + UINT_32 u4PktQosCfPollLost; + + /* 802.11k - Average Packet Transmission delay for all packets per this TC or TS */ + UINT_32 u4AvgPktTxDelay; + /* 802.11k - Average Packet Queue Delay */ + UINT_32 u4AvgPktQueueDelay; + UINT_64 u8StartTime; /* represented by TSF */ + /* sum of packets whose packet tx delay is less than Bi (i=0~6) range value(unit: TU) */ + UINT_32 au4PktCntBin[6]; +} CMD_GET_TSM_STATISTICS_T, *P_CMD_GET_TSM_STATISTICS_T; + +typedef struct _CMD_MAX_TXPWR_LIMIT_T { + UINT_8 ucMaxTxPwrLimitEnable; + UINT_8 ucMaxTxPwr; + UINT_8 ucReserved[2]; +} CMD_MAX_TXPWR_LIMIT_T, *P_CMD_MAX_TXPWR_LIMIT_T; + +typedef struct _EVENT_CH_PRIVILEGE_T { + UINT_8 ucBssIndex; + UINT_8 ucTokenID; + UINT_8 ucStatus; + UINT_8 ucPrimaryChannel; + UINT_8 ucRfSco; + UINT_8 ucRfBand; + UINT_8 ucRfChannelWidth; /* To support 80/160MHz bandwidth */ + UINT_8 ucRfCenterFreqSeg1; /* To support 80/160MHz bandwidth */ + UINT_8 ucRfCenterFreqSeg2; /* To support 80/160MHz bandwidth */ + UINT_8 ucReqType; + UINT_8 aucReserved[2]; + 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 ucBssIndex; + UINT_8 ucReasonCode; + UINT_8 aucReserved[2]; +} EVENT_BSS_BEACON_TIMEOUT_T, *P_EVENT_BSS_BEACON_TIMEOUT_T; + +typedef struct _EVENT_STA_AGING_TIMEOUT_T { + UINT_8 ucStaRecIdx; + UINT_8 aucReserved[3]; +} EVENT_STA_AGING_TIMEOUT_T, *P_EVENT_STA_AGING_TIMEOUT_T; + +typedef struct _EVENT_NOA_TIMING_T { + UINT_8 ucIsInUse; /* 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 ucBssIndex; + UINT_8 aucReserved[2]; + UINT_8 ucEnableOppPS; + 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 ucBssIndex; + 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 _EVENT_DEBUG_MSG_T { + UINT_16 u2DebugMsgId; + UINT_8 ucMsgType; + UINT_8 ucFlags; /* unused */ + UINT_32 u4Value; /* memory addre or ... */ + UINT_16 u2MsgSize; + UINT_8 aucReserved0[2]; + UINT_8 aucMsg[1]; +} EVENT_DEBUG_MSG_T, *P_EVENT_DEBUG_MSG_T; + +typedef struct _CMD_EDGE_TXPWR_LIMIT_T { + INT_8 cBandEdgeMaxPwrCCK; + INT_8 cBandEdgeMaxPwrOFDM20; + INT_8 cBandEdgeMaxPwrOFDM40; + INT_8 cBandEdgeMaxPwrOFDM80; +} CMD_EDGE_TXPWR_LIMIT_T, *P_CMD_EDGE_TXPWR_LIMIT_T; + +typedef struct _CMD_POWER_OFFSET_T { + UINT_8 ucBand; /*1:2.4G ; 2:5G */ + UINT_8 ucSubBandOffset[MAX_SUBBAND_NUM_5G]; /*the max num subband is 5G, devide with 8 subband */ + UINT_8 aucReverse[3]; + +} CMD_POWER_OFFSET_T, *P_CMD_POWER_OFFSET_T; + +typedef struct _CMD_NVRAM_SETTING_T { + + WIFI_CFG_PARAM_STRUCT rNvramSettings; + +} CMD_NVRAM_SETTING_T, *P_CMD_NVRAM_SETTING_T; + +#if CFG_SUPPORT_TDLS +typedef struct _CMD_TDLS_CH_SW_T { + BOOLEAN fgIsTDLSChSwProhibit; +} CMD_TDLS_CH_SW_T, *P_CMD_TDLS_CH_SW_T; +#endif + +typedef struct _CMD_SET_DEVICE_MODE_T { + UINT_16 u2ChipID; + UINT_16 u2Mode; +} CMD_SET_DEVICE_MODE_T, *P_CMD_SET_DEVICE_MODE_T; + +#if CFG_SUPPORT_RDD_TEST_MODE +typedef struct _CMD_RDD_CH_T { + UINT_8 ucRddTestMode; + UINT_8 ucRddShutCh; + UINT_8 ucRddStartCh; + UINT_8 ucRddStopCh; + UINT_8 ucRddDfs; + UINT_8 ucReserved; + UINT_8 ucReserved1; + UINT_8 ucReserved2; +} CMD_RDD_CH_T, *P_CMD_RDD_CH_T; + +typedef struct _EVENT_RDD_STATUS_T { + UINT_8 ucRddStatus; + UINT_8 aucReserved[3]; +} EVENT_RDD_STATUS_T, *P_EVENT_RDD_STATUS_T; +#endif + +typedef struct _EVENT_ICAP_STATUS_T { + UINT_8 ucRddStatus; + UINT_8 aucReserved[3]; + UINT_32 u4StartAddress; + UINT_32 u4IcapSieze; +#if CFG_SUPPORT_QA_TOOL + UINT_32 u4IcapContent; +#endif /* CFG_SUPPORT_QA_TOOL */ +} EVENT_ICAP_STATUS_T, *P_EVENT_ICAP_STATUS_T; + +#if CFG_SUPPORT_QA_TOOL +typedef struct _ADC_BUS_FMT_T { + UINT_32 u4Dcoc0Q:14; /* [13:0] */ + UINT_32 u4Dcoc0I:14; /* [27:14] */ + UINT_32 u4DbgData1:4; /* [31:28] */ + + UINT_32 u4Dcoc1Q:14; /* [45:32] */ + UINT_32 u4Dcoc1I:14; /* [46:59] */ + UINT_32 u4DbgData2:4; /* [63:60] */ + + UINT_32 u4DbgData3; /* [95:64] */ +} ADC_BUS_FMT_T, *P_ADC_BUS_FMT_T; +#if 0 +typedef struct _IQC_BUS_FMT_T { + INT_32 u4Iqc0Q:12; /* [11:0] */ + INT_32 u4Iqc0I:12; /* [23:12] */ + INT_32 u4Na1:8; /* [31:24] */ + + INT_32 u4Iqc1Q:12; /* [43:32] */ + INT_32 u4Iqc1I:12; /* [55:44] */ + INT_32 u4Na2:8; /* [63:56] */ + + INT_32 u4Na3; /* [95:64] */ +} IQC_BUS_FMT_T, *P_IQC_BUS_FMT_T; +#endif +typedef struct _IQC_BUS_FMT_T { + INT_32 u4Iqc0Q:11; /* [10:0] */ + INT_32 u4Na1:5; /* [15:11] */ + INT_32 u4Iqc0I:11; /* [26:16] */ + INT_32 u4Na2:5; /* [31:27] */ +} IQC_BUS_FMT_T, *P_IQC_BUS_FMT_T; + +typedef struct _IQC_160_BUS_FMT_T { + INT_32 u4Iqc0Q1:12; /* [11:0] */ + INT_32 u4Iqc0I1:12; /* [23:12] */ + UINT_32 u4Iqc0Q0P1:8; /* [31:24] */ + + INT_32 u4Iqc0Q0P2:4; /* [35:32] */ + INT_32 u4Iqc0I0:12; /* [47:36] */ + INT_32 u4Iqc1Q1:12; /* [59:48] */ + UINT_32 u4Iqc1I1P1:4; /* [63:60] */ + + INT_32 u4Iqc1I1P2:8; /* [71:64] */ + INT_32 u4Iqc1Q0:12; /* [83:72] */ + INT_32 u4Iqc1I0:12; /* [95:84] */ +} IQC_160_BUS_FMT_T, *P_IQC_160_BUS_FMT_T; + +typedef struct _SPECTRUM_BUS_FMT_T { + INT_32 u4DcocQ:12; /* [11:0] */ + INT_32 u4DcocI:12; /* [23:12] */ + INT_32 u4LpfGainIdx:4; /* [27:24] */ + INT_32 u4LnaGainIdx:2; /* [29:28] */ + INT_32 u4AssertData:2; /* [31:30] */ +} SPECTRUM_BUS_FMT_T, *P_SPECTRUM_BUS_FMT_T; +#if 0 +typedef struct _PACKED_ADC_BUS_FMT_T { + UINT_32 u4AdcQ0T2:4; /* [19:16] */ + UINT_32 u4AdcQ0T1:4; /* [11:8] */ + UINT_32 u4AdcQ0T0:4; /* [3:0] */ + + UINT_32 u4AdcI0T2:4; /* [23:20] */ + UINT_32 u4AdcI0T1:4; /* [15:12] */ + UINT_32 u4AdcI0T0:4; /* [7:4] */ + + UINT_32 u4AdcQ0T5:4; /* [43:40] */ + UINT_32 u4AdcQ0T4:4; /* [35:32] */ + UINT_32 u4AdcQ0T3:4; /* [27:24] */ + + UINT_32 u4AdcI0T5:4; /* [47:44] */ + UINT_32 u4AdcI0T4:4; /* [39:36] */ + UINT_32 u4AdcI0T3:4; /* [31:28] */ + + UINT_32 u4AdcQ1T2:4; /* [19:16] */ + UINT_32 u4AdcQ1T1:4; /* [11:8] */ + UINT_32 u4AdcQ1T0:4; /* [3:0] */ + + UINT_32 u4AdcI1T2:4; /* [23:20] */ + UINT_32 u4AdcI1T1:4; /* [15:12] */ + UINT_32 u4AdcI1T0:4; /* [7:4] */ + + UINT_32 u4AdcQ1T5:4; /* [43:40] */ + UINT_32 u4AdcQ1T4:4; /* [35:32] */ + UINT_32 u4AdcQ1T3:4; /* [27:24] */ + + UINT_32 u4AdcI1T5:4; /* [47:44] */ + UINT_32 u4AdcI1T4:4; /* [39:36] */ + UINT_32 u4AdcI1T3:4; /* [31:28] */ +} PACKED_ADC_BUS_FMT_T, *P_PACKED_ADC_BUS_FMT_T; +#endif +typedef struct _PACKED_ADC_BUS_FMT_T { + UINT_32 u4AdcQ0T0:11; /* [10:0] */ + UINT_32 u4AdcI0T0:11; /* [21:11] */ + UINT_32 u4AdcRSSI:7; /* [28:22] */ + UINT_32 u4VLD:1; /* [29:29] */ + UINT_32 u4Na2:2; /* [31:30] */ +} PACKED_ADC_BUS_FMT_T, *P_PACKED_ADC_BUS_FMT_T; + + +typedef union _ICAP_BUS_FMT { + ADC_BUS_FMT_T rAdcBusData; /* 12 bytes */ + IQC_BUS_FMT_T rIqcBusData; /* 12 bytes */ + IQC_160_BUS_FMT_T rIqc160BusData; /* 12 bytes */ + SPECTRUM_BUS_FMT_T rSpectrumBusData; /* 4 bytes */ + PACKED_ADC_BUS_FMT_T rPackedAdcBusData; /* 12 bytes */ +} ICAP_BUS_FMT, *P_ICAP_BUS_FMT; +#endif /* CFG_SUPPORT_QA_TOOL */ + +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; + +typedef enum _ENUM_NLO_CIPHER_ALGORITHM { + NLO_CIPHER_ALGO_NONE = 0x00, + NLO_CIPHER_ALGO_WEP40 = 0x01, + NLO_CIPHER_ALGO_TKIP = 0x02, + NLO_CIPHER_ALGO_CCMP = 0x04, + NLO_CIPHER_ALGO_WEP104 = 0x05, + NLO_CIPHER_ALGO_WPA_USE_GROUP = 0x100, + NLO_CIPHER_ALGO_RSN_USE_GROUP = 0x100, + NLO_CIPHER_ALGO_WEP = 0x101, +} ENUM_NLO_CIPHER_ALGORITHM, *P_ENUM_NLO_CIPHER_ALGORITHM; + +typedef enum _ENUM_NLO_AUTH_ALGORITHM { + NLO_AUTH_ALGO_80211_OPEN = 1, + NLO_AUTH_ALGO_80211_SHARED_KEY = 2, + NLO_AUTH_ALGO_WPA = 3, + NLO_AUTH_ALGO_WPA_PSK = 4, + NLO_AUTH_ALGO_WPA_NONE = 5, + NLO_AUTH_ALGO_RSNA = 6, + NLO_AUTH_ALGO_RSNA_PSK = 7, +} ENUM_NLO_AUTH_ALGORITHM, *P_ENUM_NLO_AUTH_ALGORITHM; + +#if CFG_SUPPORT_REPORT_MISC +enum ENUM_REPORT_MISC { + REPORT_AUTHASSOC_START = 0x01, + REPORT_AUTHASSOC_END, + REPORT_4WAYHS_START, + REPORT_4WAYHS_END, + REPORT_DHCP_START, + REPORT_DHCP_END, +}; +#endif + +struct NLO_SSID_MATCH_SETS { + INT_8 cRssiThresold; + UINT_8 ucSSIDLength; + UINT_8 aucSSID[32]; +}; + +struct NLO_NETWORK { + UINT_8 ucChannelType; /* 0: specific channel; 1: dual band; 2: 2.4G; 3: 5G; 3*/ + UINT_8 ucChnlNum; + UINT_8 aucChannel[94]; + struct NLO_SSID_MATCH_SETS arMatchSets[16]; +}; + +typedef struct _CMD_NLO_REQ { + UINT_8 ucSeqNum; + UINT_8 ucBssIndex; + UINT_8 fgStopAfterIndication; + UINT_8 ucFastScanIteration; + UINT_16 u2FastScanPeriod; + UINT_16 u2SlowScanPeriod; + UINT_8 ucEntryNum; + UINT_8 ucFlag; /* BIT(0) Check cipher */ + UINT_16 u2IELen; + struct NLO_NETWORK rNLONetwork; + UINT_8 aucIE[0]; +} CMD_NLO_REQ, *P_CMD_NLO_REQ; + +typedef struct _CMD_NLO_CANCEL_T { + UINT_8 ucSeqNum; + UINT_8 ucBssIndex; + UINT_8 aucReserved[2]; +} CMD_NLO_CANCEL, *P_CMD_NLO_CANCEL; + +typedef struct _EVENT_NLO_DONE_T { + UINT_8 ucSeqNum; + UINT_8 ucStatus; + UINT_8 aucReserved[2]; +} EVENT_NLO_DONE_T, *P_EVENT_NLO_DONE_T; + +#if CFG_SUPPORT_BUILD_DATE_CODE +typedef struct _CMD_GET_BUILD_DATE_CODE { + UINT_8 aucReserved[4]; +} CMD_GET_BUILD_DATE_CODE, *P_CMD_GET_BUILD_DATE_CODE; + +typedef struct _EVENT_BUILD_DATE_CODE { + UINT_8 aucDateCode[16]; +} EVENT_BUILD_DATE_CODE, *P_EVENT_BUILD_DATE_CODE; +#endif + +typedef struct _CMD_GET_STA_STATISTICS_T { + UINT_8 ucIndex; + UINT_8 ucFlags; + UINT_8 ucReadClear; + UINT_8 ucLlsReadClear; + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + UINT_8 aucReserved1[2]; + UINT_8 aucReserved2[16]; +} CMD_GET_STA_STATISTICS_T, *P_CMD_GET_STA_STATISTICS_T; + +/* per access category statistics */ +typedef struct _WIFI_WMM_AC_STAT_GET_FROM_FW_T { + UINT_32 u4TxFailMsdu; + UINT_32 u4TxRetryMsdu; +} WIFI_WMM_AC_STAT_GET_FROM_FW_T, *P_WIFI_WMM_AC_STAT_GET_FROM_FW_T; + +/* CFG_SUPPORT_WFD */ +typedef struct _EVENT_STA_STATISTICS_T { + UINT_8 ucVersion; + UINT_8 aucReserved1[3]; + UINT_32 u4Flags; /* Bit0: valid */ + + UINT_8 ucStaRecIdx; + UINT_8 ucNetworkTypeIndex; + UINT_8 ucWTEntry; + UINT_8 aucReserved4[1]; + + UINT_8 ucMacAddr[MAC_ADDR_LEN]; + UINT_8 ucPer; /* base: 128 */ + UINT_8 ucRcpi; + + UINT_32 u4PhyMode; /* SGI BW */ + UINT_16 u2LinkSpeed; /* unit is 0.5 Mbits */ + UINT_8 ucLinkQuality; + UINT_8 ucLinkReserved; + + UINT_32 u4TxCount; + UINT_32 u4TxFailCount; + UINT_32 u4TxLifeTimeoutCount; + UINT_32 u4TxDoneAirTime; + UINT_32 u4TransmitCount; /* Transmit in the air (wtbl) */ + UINT_32 u4TransmitFailCount; /* Transmit without ack/ba in the air (wtbl) */ + + WIFI_WMM_AC_STAT_GET_FROM_FW_T arLinkStatistics[AC_NUM]; /*link layer statistics */ + + UINT_8 aucReserved[24]; +} EVENT_STA_STATISTICS_T, *P_EVENT_STA_STATISTICS_T; + + +typedef struct _EVENT_LTE_SAFE_CHN_T { + UINT_8 ucVersion; + UINT_8 aucReserved[3]; + UINT_32 u4Flags; /* Bit0: valid */ + LTE_SAFE_CHN_INFO_T rLteSafeChn; +} EVENT_LTE_SAFE_CHN_T, *P_EVENT_LTE_SAFE_CHN_T; + + +#if CFG_SUPPORT_SNIFFER +typedef struct _CMD_MONITOR_SET_INFO_T { + UINT_8 ucEnable; + UINT_8 ucBand; + UINT_8 ucPriChannel; + UINT_8 ucSco; + UINT_8 ucChannelWidth; + UINT_8 ucChannelS1; + UINT_8 ucChannelS2; + UINT_8 aucResv[9]; +} CMD_MONITOR_SET_INFO_T, *P_CMD_MONITOR_SET_INFO_T; +#endif + +typedef struct _CMD_STATS_LOG_T { + UINT_32 u4DurationInMs; + UINT_8 aucReserved[32]; +} CMD_STATS_LOG_T, *P_CMD_STATS_LOG_T; + +typedef struct _EVENT_GSCAN_CAPABILITY_T { + UINT_8 ucVersion; + UINT_8 aucReserved1[3]; + UINT_32 u4MaxScanCacheSize; + UINT_32 u4MaxScanBuckets; + UINT_32 u4MaxApCachePerScan; + UINT_32 u4MaxRssiSampleSize; + UINT_32 u4MaxScanReportingThreshold; + UINT_32 u4MaxHotlistAps; + UINT_32 u4MaxSignificantWifiChangeAps; + UINT_32 au4Reserved[4]; +} EVENT_GSCAN_CAPABILITY_T, *P_EVENT_GSCAN_CAPABILITY_T; + +typedef struct _EVENT_GSCAN_SCAN_AVAILABLE_T { + UINT_16 u2Num; + UINT_8 aucReserved[2]; +} EVENT_GSCAN_SCAN_AVAILABLE_T, *P_EVENT_GSCAN_SCAN_AVAILABLE_T; + +typedef struct _EVENT_GSCAN_SCAN_COMPLETE_T { + UINT_8 ucScanState; + UINT_8 aucReserved[3]; +} EVENT_GSCAN_SCAN_COMPLETE_T, *P_EVENT_GSCAN_SCAN_COMPLETE_T; + +typedef struct WIFI_GSCAN_RESULT { + UINT_64 u8Ts; /* Time of discovery */ + UINT_8 arSsid[ELEM_MAX_LEN_SSID + 1]; /* null terminated */ + UINT_8 arMacAddr[6]; /* BSSID */ + UINT_32 u4Channel; /* channel frequency in MHz */ + INT_32 i4Rssi; /* in db */ + UINT_64 u8Rtt; /* in nanoseconds */ + UINT_64 u8RttSd; /* standard deviation in rtt */ + UINT_16 u2BeaconPeriod; /* units are Kusec */ + UINT_16 u2Capability; /* Capability information */ + UINT_32 u4IeLength; /* byte length of Information Elements */ + UINT_8 ucIeData[1]; /* IE data to follow */ +} WIFI_GSCAN_RESULT_T, *P_WIFI_GSCAN_RESULT_T; + +typedef struct _EVENT_GSCAN_RESULT_T { + UINT_8 ucVersion; + UINT_8 aucReserved[3]; + UINT_16 u2ScanId; + UINT_16 u2ScanFlags; + UINT_16 u2NumOfResults; + WIFI_GSCAN_RESULT_T rResult[1]; +} EVENT_GSCAN_RESULT_T, *P_EVENT_GSCAN_RESULT_T; + +typedef struct _EVENT_GSCAN_FULL_RESULT_T { + WIFI_GSCAN_RESULT_T rResult; + UINT_32 u4BucketMask; /* scan chbucket bitmask */ + UINT_32 u4IeLength; /* byte length of Information Elements */ + UINT_8 ucIeData[1]; /* IE data to follow */ +} EVENT_GSCAN_FULL_RESULT_T, *P_EVENT_GSCAN_FULL_RESULT_T; + +typedef struct GSCAN_SWC_NET { + UINT_16 u2Flags; + UINT_16 u2Channel; + UINT_8 arBssid[6]; + INT_8 aicRssi[SCN_PSCAN_SWC_RSSI_WIN_MAX]; +} GSCAN_SWC_NET_T, P_GSCAN_SWC_NET_T; + +typedef struct _EVENT_GSCAN_SIGNIFICANT_CHANGE_T { + UINT_8 ucVersion; + UINT_8 aucReserved[3]; + GSCAN_SWC_NET_T arNet[SCN_PSCAN_SWC_MAX_NUM]; +} EVENT_GSCAN_SIGNIFICANT_CHANGE_T, *P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T; + +typedef struct _EVENT_GSCAN_GEOFENCE_FOUND_T { + UINT_8 ucVersion; + UINT_8 aucReserved[3]; + WIFI_GSCAN_RESULT_T rResult[SCN_PSCAN_HOTLIST_REPORT_MAX_NUM]; +} EVENT_GSCAN_GEOFENCE_FOUND_T, *P_EVENT_GSCAN_GEOFENCE_FOUND_T; + +typedef struct _CMD_SET_PSCAN_PARAM { + UINT_8 ucVersion; + CMD_NLO_REQ rCmdNloReq; + CMD_BATCH_REQ_T rCmdBatchReq; + CMD_GSCN_REQ_T rCmdGscnReq; + BOOLEAN fgNLOScnEnable; + BOOLEAN fgBatchScnEnable; + BOOLEAN fgGScnEnable; + UINT_32 u4BasePeriod; +#if defined(MT6631) + UINT_8 ucScnFuncMask; +#endif +} CMD_SET_PSCAN_PARAM, *P_CMD_SET_PSCAN_PARAM; + +typedef struct _CMD_SET_PSCAN_ADD_HOTLIST_BSSID { + UINT_8 aucMacAddr[6]; + UINT_8 ucFlags; + UINT_8 aucReserved[5]; +} CMD_SET_PSCAN_ADD_HOTLIST_BSSID, *P_CMD_SET_PSCAN_ADD_HOTLIST_BSSID; + +typedef struct _CMD_SET_PSCAN_ADD_SWC_BSSID { + INT_32 i4RssiLowThreshold; + INT_32 i4RssiHighThreshold; + UINT_8 aucMacAddr[6]; + UINT_8 aucReserved[6]; +} CMD_SET_PSCAN_ADD_SWC_BSSID, *P_CMD_SET_PSCAN_ADD_SWC_BSSID; + +typedef struct _CMD_SET_PSCAN_MAC_ADDR { + UINT_8 ucVersion; + UINT_8 ucFlags; + UINT_8 aucMacAddr[6]; + UINT_8 aucReserved[8]; +} CMD_SET_PSCAN_MAC_ADDR, *P_CMD_SET_PSCAN_MAC_ADDR; + +struct CMD_TDLS_PS_T { + UINT_8 ucIsEnablePs; /* 0: disable tdls power save; 1: enable tdls power save */ + UINT_8 aucReserved[3]; +}; + +typedef struct _CMD_SUSPEND_MODE_SETTING_T { + UINT_8 ucBssIndex; + UINT_8 fIsEnableSuspendMode; + UINT_8 ucReserved[2]; +} CMD_SUSPEND_MODE_SETTING_T, *P_CMD_SUSPEND_MODE_SETTING_T; + +typedef struct _EVENT_UPDATE_FW_INFO_T { + UINT_8 ucVersion; + UINT_8 aucReserved1[3]; /* 4 byte alignment */ + UINT_32 u4Flags; + UINT_32 au4PhyRateLimit[HW_BSSID_NUM+1]; + UINT_32 au4Reserved2[36]; +} EVENT_UPDATE_FW_INFO_T, *P_EVENT_UPDATE_FW_INFO_T; + +struct CMD_REQ_CHNL_UTILIZATION { + UINT_16 u2MeasureDuration; + UINT_8 ucChannelNum; + UINT_8 aucChannelList[48]; + UINT_8 aucReserved[13]; +}; + +struct EVENT_RSP_CHNL_UTILIZATION { + UINT_8 ucChannelNum; + UINT_8 aucChannelMeasureList[48]; + UINT_8 aucReserved0[15]; + UINT_8 aucChannelUtilization[48]; + UINT_8 aucReserved1[16]; + UINT_8 aucChannelBusyTime[48]; + UINT_8 aucReserved2[16]; +}; + +#if CFG_SUPPORT_LOWLATENCY_MODE +struct LOWLATENCY_MODE_SETTING { + UINT_8 fgEnable; + UINT_8 aucReserved[7]; +}; + +struct CMD_LOWLATENCY_MODE_HEADER { + UINT_8 ucVersion; + UINT_8 ucType; + UINT_8 ucMagicCode; + UINT_8 ucBufferLen; + struct LOWLATENCY_MODE_SETTING rSetting; +}; +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + +struct CMD_EVENT_LOG_LEVEL { + UINT_32 u4Version; + UINT_32 u4LogLevel; + UINT_8 aucReserved[3]; +}; + +#if CFG_MODIFY_TX_POWER_BY_BAT_VOLT +struct CMD_TX_PWR_BACKOFF { + UINT_8 ucEnable; /* enable decreased tx power or not */ + UINT_8 ucBackoffPwr; /* tx power dec step */ +}; +#endif + +#if CFG_SUPPORT_REPORT_MISC +struct EVENT_REPORT_MISC { + UINT_8 ucFwVerMajor; + UINT_8 ucFwVerMinor; + UINT_16 u2FwVerBeta; + UINT_32 u4MdrdyCnt; + UINT_32 u4RxMpduCnt; + UINT_32 u4ChannelIdleCnt; + INT_8 cRssi; +}; +#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 nicCmdEventQueryMcrRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +#if CFG_SUPPORT_QA_TOOL +VOID nicCmdEventQueryRxStatistics(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +UINT_32 TsfRawData2IqFmt(P_EVENT_DUMP_MEM_T prEventDumpMem); + +INT_32 GetIQData(INT_32 **prIQAry, UINT_32 *prDataLen, UINT_32 u4IQ, UINT_32 u4GetWf1); + +#if CFG_SUPPORT_TX_BF +VOID nicCmdEventPfmuDataRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventPfmuTagRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +#endif /* CFG_SUPPORT_TX_BF */ +#if CFG_SUPPORT_MU_MIMO +VOID nicCmdEventGetQd(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +VOID nicCmdEventGetCalcLq(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +VOID nicCmdEventGetCalcInitMcs(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +#endif /* CFG_SUPPORT_MU_MIMO */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +VOID nicEventQueryMemDump(IN P_ADAPTER_T prAdapter, 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 nicCmdEventQueryChipConfig(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 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); + +VOID nicCmdEventSetStopSchedScan(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 nicOidCmdEnterRFTestTimeout(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +#if CFG_SUPPORT_BUILD_DATE_CODE +VOID nicCmdEventBuildDateCode(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +#endif + +VOID nicCmdEventQueryStaStatistics(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + + +VOID nicCmdEventQueryLteSafeChn(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + + +#if CFG_SUPPORT_BATCH_SCAN +VOID nicCmdEventBatchScanResult(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +#endif + +#ifdef FW_CFG_SUPPORT +VOID nicCmdEventQueryCfgRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +#endif +VOID nicEventUpdateFwInfo(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); + +#if CFG_SUPPORT_REPLAY_DETECTION +VOID nicCmdEventSetAddKey(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +VOID nicOidCmdTimeoutSetAddKey(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); +#endif + +#if CFG_SUPPORT_REPORT_MISC +VOID nicCmdEventReportMisc(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +#endif +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _NIC_CMD_EVENT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic_init_cmd_event.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic_init_cmd_event.h new file mode 100644 index 0000000000000..3ad59d709ee35 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/nic_init_cmd_event.h @@ -0,0 +1,186 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/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. + */ + +#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]) + +#define INIT_CMD_PQ_ID (0x8000) +#define INIT_CMD_PACKET_TYPE_ID (0xA0) + +#define INIT_CMD_PDA_PQ_ID (0xC000) +#define INIT_CMD_PDA_PACKET_TYPE_ID (0xA0) + +typedef enum _ENUM_INIT_CMD_ID { + INIT_CMD_ID_DOWNLOAD_CONFIG = 1, + INIT_CMD_ID_WIFI_START, + INIT_CMD_ID_ACCESS_REG, + INIT_CMD_ID_QUERY_PENDING_ERROR, + INIT_CMD_ID_PATCH_START, + INIT_CMD_ID_PATCH_WRITE, + INIT_CMD_ID_PATCH_FINISH, + INIT_CMD_ID_NUM +} 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 ucPktTypeID; /* Must be 0x20 (CMD Packet) */ + UINT_8 ucReserved; + UINT_8 ucSeqNum; + + UINT_8 aucBuffer[0]; +} INIT_WIFI_CMD_T, *P_INIT_WIFI_CMD_T; + +typedef struct _INIT_HIF_TX_HEADER_T { + UINT_16 u2TxByteCount; /* Max value is over 2048 */ + UINT_16 u2PQ_ID; /* Must be 0x8000 (Port1, Queue 0) */ + + INIT_WIFI_CMD_T rInitWifiCmd; +} INIT_HIF_TX_HEADER_T, *P_INIT_HIF_TX_HEADER_T; + +#define DOWNLOAD_CONFIG_ENCRYPTION_MODE BIT(0) +#if defined(MT6631) +#define DOWNLOAD_CONFIG_ENCRYPT_IDX_MASK BITS(1, 2) +#define DOWNLOAD_CONFIG_ENCRYPT_IDX_OFFSET 1 +#endif +#define DOWNLOAD_CONFIG_RESET_OPTION BIT(3) +#define DOWNLOAD_CONFIG_ACK_OPTION BIT(31) +typedef struct _INIT_CMD_DOWNLOAD_CONFIG { + UINT_32 u4Address; + UINT_32 u4Length; + UINT_32 u4DataMode; +} INIT_CMD_DOWNLOAD_CONFIG, *P_INIT_CMD_DOWNLOAD_CONFIG; + +#define START_OVERRIDE_START_ADDRESS BIT(0) +#define START_DELAY_CALIBRATION BIT(1) +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_16 u2PacketType; /* Must be filled with 0xE000 (EVENT Packet) */ + UINT_8 ucEID; + UINT_8 ucSeqNum; + UINT_8 aucReserved[2]; + + 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, others: failure */ + /* 1: rejected by invalid param */ + /* 2: rejected by incorrect CRC */ + /* 3: rejected by decryption failure */ + /* 4: unknown CMD */ + /* 5: timeout */ + UINT_8 aucReserved[3]; +#if defined(MT6631) + UINT_16 u2PseFid; + UINT_8 ucKeyIndex; + UINT_8 aucReserved1; + INIT_CMD_DOWNLOAD_CONFIG rSrc; +#endif +} INIT_EVENT_CMD_RESULT, *P_INIT_EVENT_CMD_RESULT, INIT_EVENT_PENDING_ERROR, *P_INIT_EVENT_PENDING_ERROR; + +typedef struct _INIT_EVENT_ACCESS_REG { + UINT_32 u4Address; + UINT_32 u4Data; +} INIT_EVENT_ACCESS_REG, *P_INIT_EVENT_ACCESS_REG; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _NIC_INIT_CMD_EVENT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/p2p_precomp.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/p2p_precomp.h new file mode 100644 index 0000000000000..99980c9dbb300 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/p2p_precomp.h @@ -0,0 +1,215 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** 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" + +#include "nic_rate.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" + +#include "mt6630_reg.h" + +#include "rlm.h" +#include "rlm_domain.h" +#include "rlm_protection.h" +#include "rlm_obss.h" +#include "rate.h" +#include "wnm.h" + +#include "aa_fsm.h" + +#include "cnm_timer.h" +#include "que_mgt.h" +#include "wmm.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 "rftest.h" + +#include "rsn.h" +#include "sec_fsm.h" + +#if CFG_SUPPORT_WAPI +#include "wapi.h" +#endif + +/*------------------------------------------------------------------------------ + * NVRAM structure + *------------------------------------------------------------------------------ + */ +#include "CFG_Wifi_File.h" + +#include "gl_p2p_kal.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /*_P2P_PRECOMP_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/p2p_typedef.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/p2p_typedef.h new file mode 100644 index 0000000000000..f0bbd15372fb2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/p2p_typedef.h @@ -0,0 +1,183 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/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_DEV_FSM_INFO_T P2P_DEV_FSM_INFO_T, *P_P2P_DEV_FSM_INFO_T; + +typedef struct _P2P_ROLE_FSM_INFO_T P2P_ROLE_FSM_INFO_T, *P_P2P_ROLE_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 UINT_8 ucBssIndex, IN P_STA_RECORD_T prStaRec); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /*CFG_ENABLE_WIFI_DIRECT */ + +#endif /* _P2P_TYPEDEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/precomp.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/precomp.h new file mode 100644 index 0000000000000..5f14c2b706aed --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/precomp.h @@ -0,0 +1,258 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/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. + */ + +#ifndef _PRECOMP_H +#define _PRECOMP_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +#ifdef __GNUC__ +#if (DBG == 0) +#pragma GCC diagnostic ignored "-Wformat" +#endif +#endif + +/******************************************************************************* +* 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 "bss.h" + +#include "nic_rate.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 "wlan_lib.h" +#include "wlan_oid.h" +#include "wlan_bow.h" + +#if CFG_ENABLE_WIFI_DIRECT +#include "wlan_p2p.h" +#endif + +#include "hal.h" + +#include "mt6630_reg.h" + +#include "rlm.h" +#include "rlm_domain.h" +#include "rlm_protection.h" +#include "rlm_obss.h" +#include "rate.h" +#include "wnm.h" + +#include "qosmap.h" + +#include "aa_fsm.h" + +#include "cnm_timer.h" + +#include "que_mgt.h" + +#include "wmm.h" +#if CFG_ENABLE_BT_OVER_WIFI +#include "bow.h" +#include "bow_fsm.h" +#endif + +#include "pwr_mgt.h" + +#if (CFG_SUPPORT_STATISTICS == 1) +#include "stats.h" +#endif /* CFG_SUPPORT_STATISTICS */ + +#include "cnm.h" +/* Dependency: aa_fsm.h (ENUM_AA_STATE_T), p2p_fsm.h (WPS_ATTRI_MAX_LEN_DEVICE_NAME) */ +#include "cnm_mem.h" +#include "cnm_scan.h" + +#if CFG_ENABLE_WIFI_DIRECT +#include "p2p_rlm_obss.h" +#include "p2p_bss.h" +#include "p2p.h" + +#include "p2p_rlm.h" +#include "p2p_assoc.h" +#include "p2p_ie.h" +#include "p2p_role.h" + +#include "p2p_func.h" +#include "p2p_scan.h" +#include "p2p_dev.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" + +#include "rsn.h" +#include "sec_fsm.h" + +#if CFG_SUPPORT_WAPI +#include "wapi.h" +#endif + +/*------------------------------------------------------------------------------ + * NVRAM structure + *------------------------------------------------------------------------------ + */ +#include "CFG_Wifi_File.h" + +/*------------------------------------------------------------------------------ + * Others + *------------------------------------------------------------------------------ + */ +#if CFG_ENABLE_WIFI_DIRECT +#include "gl_p2p_kal.h" +#endif + +#if CFG_SUPPORT_TDLS +#include "tdls.h" +#endif + +#if CFG_SUPPORT_QA_TOOL +#include "gl_qa_agent.h" +#endif + +#include "gl_rst.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 /* _PRECOMP_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/pwr_mgt.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/pwr_mgt.h new file mode 100644 index 0000000000000..dd1fa1853e288 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/pwr_mgt.h @@ -0,0 +1,112 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/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. + */ + +#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) \ + { \ + nicpmSetDriverOwn(_prAdapter); \ + /* Increase Block to Enter Low Power Semaphore count */ \ + GLUE_INC_REF_CNT(_prAdapter->u4PwrCtrlBlockCnt); \ + } + +#define RECLAIM_POWER_CONTROL_TO_PM(_prAdapter, _fgEnableGINT_in_IST) \ + { \ + ASSERT(_prAdapter->u4PwrCtrlBlockCnt != 0); \ + /* Decrease Block to Enter Low Power Semaphore count */ \ + GLUE_DEC_REF_CNT(_prAdapter->u4PwrCtrlBlockCnt); \ + if (_prAdapter->fgWiFiInSleepyState && (_prAdapter->u4PwrCtrlBlockCnt == 0)) { \ + nicpmSetFWOwn(_prAdapter, _fgEnableGINT_in_IST); \ + } \ + } +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _PWR_MGT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/queue.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/queue.h new file mode 100644 index 0000000000000..27bd8e6d6bb4e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/queue.h @@ -0,0 +1,195 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/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. + */ + +#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 MAXNUM_TDLS_PEER 4 + +#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); \ + } \ + } + +#define QUEUE_CONCATENATE_QUEUES_HEAD(prDestQueue, prSrcQueue) \ + { \ + ASSERT(prDestQueue); \ + ASSERT(prSrcQueue); \ + if (prSrcQueue->u4NumElem > 0) { \ + ((prSrcQueue)->prTail)->prNext = (prDestQueue)->prHead; \ + (prDestQueue)->prHead = (prSrcQueue)->prHead; \ + ((prDestQueue)->u4NumElem) += ((prSrcQueue)->u4NumElem); \ + if ((prDestQueue)->prTail == NULL) { \ + (prDestQueue)->prTail = (prSrcQueue)->prTail; \ + } \ + QUEUE_INITIALIZE(prSrcQueue); \ + } \ + } + +/******************************************************************************* +* E X T E R N A L D A T A +******************************************************************************** +*/ +extern UINT_8 g_arTdlsLink[MAXNUM_TDLS_PEER]; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _QUEUE_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/rftest.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/rftest.h new file mode 100644 index 0000000000000..58c4c01feb36f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/rftest.h @@ -0,0 +1,395 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/rftest.h#1 +*/ + +/* + * ! \file "rftest.h" + * \brief definitions for RF Productino test + * + */ + +#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, + RF_AT_FUNCID_PWR_DETECTOR, + RF_AT_FUNCID_WBRSSI_IBSSI, + + /* 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, + RF_AT_FUNCID_SET_TA, + RF_AT_FUNCID_SET_RX_MATCH_RULE, + + /*80211AC & Jmode */ + RF_AT_FUNCID_SET_CBW = 71, + RF_AT_FUNCID_SET_DBW, + RF_AT_FUNCID_SET_PRIMARY_CH, + RF_AT_FUNCID_SET_ENCODE_MODE, + RF_AT_FUNCID_SET_J_MODE, + + /*ICAP command */ + RF_AT_FUNCID_SET_ICAP_CONTENT = 80, + RF_AT_FUNCID_SET_ICAP_MODE, + RF_AT_FUNCID_SET_ICAP_STARTCAP, + RF_AT_FUNCID_SET_ICAP_SIZE = 83, +#if CFG_SUPPORT_QA_TOOL + RF_AT_FUNCID_SET_ICAP_TRIGGER_OFFSET, +#else + RF_AT_FUNCID_SET_ICAP_TRIGGER_EVENT, +#endif + RF_AT_FUNCID_QUERY_ICAP_DUMP_FILE = 85, +#if CFG_SUPPORT_QA_TOOL + /* 2G 5G Band */ + RF_AT_FUNCID_SET_BAND = 90, + + /* Reset Counter */ + RF_AT_FUNCID_RESETTXRXCOUNTER = 91, + + /* FAGC RSSI Path */ + RF_AT_FUNCID_FAGC_RSSI_PATH = 92, + + /* Set RX Filter Packet Length */ + RF_AT_FUNCID_RX_FILTER_PKT_LEN = 93, + + /* Tone */ + RF_AT_FUNCID_SET_TONE_RF_GAIN = 96, + RF_AT_FUNCID_SET_TONE_DIGITAL_GAIN = 97, + RF_AT_FUNCID_SET_TONE_TYPE = 98, + RF_AT_FUNCID_SET_TONE_DC_OFFSET = 99, + RF_AT_FUNCID_SET_TONE_BW = 100, + + /* MT6632 Add */ + RF_AT_FUNCID_SET_MAC_HEADER = 101, + RF_AT_FUNCID_SET_SEQ_CTRL = 102, + RF_AT_FUNCID_SET_PAYLOAD = 103, + RF_AT_FUNCID_SET_DBDC_BAND_IDX = 104, + RF_AT_FUNCID_SET_BYPASS_CAL_STEP = 105, + + /* Set RX Path */ + RF_AT_FUNCID_SET_RX_PATH = 106, + + /* Set Frequency Offset */ + RF_AT_FUNCID_SET_FRWQ_OFFSET = 107, + + /* Get Frequency Offset */ + RF_AT_FUNCID_GET_FREQ_OFFSET = 108, + + /* Set RXV Debug Index */ + RF_AT_FUNCID_SET_RXV_INDEX = 109, + + /* Set Test Mode DBDC Enable */ + RF_AT_FUNCID_SET_DBDC_ENABLE = 110, + + /* Get Test Mode DBDC Enable */ + RF_AT_FUNCID_GET_DBDC_ENABLE = 111, + + /* Set ICAP Ring Capture */ + RF_AT_FUNCID_SET_ICAP_RING = 112, + + /* Set TX Path */ + RF_AT_FUNCID_SET_TX_PATH = 113, + + /* Set Nss */ + RF_AT_FUNCID_SET_NSS = 114, + + /* Set TX Antenna Mask */ + RF_AT_FUNCID_SET_ANTMASK = 115, + + /* TMR set command */ + RF_AT_FUNCID_SET_TMR_ROLE = 116, + RF_AT_FUNCID_SET_TMR_MODULE = 117, + RF_AT_FUNCID_SET_TMR_DBM = 118, + RF_AT_FUNCID_SET_TMR_ITER = 119, + + /* Set ADC For IRR Feature */ + RF_AT_FUNCID_SET_ADC = 120, + + /* Set RX Gain For IRR Feature */ + RF_AT_FUNCID_SET_RX_GAIN = 121, + + /* Set TTG For IRR Feature */ + RF_AT_FUNCID_SET_TTG = 122, + + /* Set TTG ON/OFF For IRR Feature */ + RF_AT_FUNCID_TTG_ON_OFF = 123, + + /* Set TSSI for QA Tool Setting */ + RF_AT_FUNCID_SET_TSSI = 124, + + /* Set Recal Cal Step */ + RF_AT_FUNCID_SET_RECAL_CAL_STEP = 125, + + /* Set iBF/eBF enable */ + RF_AT_FUNCID_SET_IBF_ENABLE = 126, + RF_AT_FUNCID_SET_EBF_ENABLE = 127, + + /* Set MPS Setting */ + RF_AT_FUNCID_SET_MPS_SIZE = 128, + RF_AT_FUNCID_SET_MPS_SEQ_DATA = 129, + RF_AT_FUNCID_SET_MPS_PAYLOAD_LEN = 130, + RF_AT_FUNCID_SET_MPS_PKT_CNT = 131, + RF_AT_FUNCID_SET_MPS_PWR_GAIN = 132, + RF_AT_FUNCID_SET_MPS_NSS = 133, + RF_AT_FUNCID_SET_MPS_PACKAGE_BW = 134 +#endif +} 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_ICAP, + RF_AT_COMMAND_RDD, + RF_AT_COMMAND_CH_SWITCH_FOR_ICAP, + RF_AT_COMMAND_RESET_DUMP_NAME, + RF_AT_COMMAND_SINGLE_TONE, + RF_AT_COMMAND_RDD_OFF, + 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_11AC, + RF_AT_PREAMBLE_NUM +} ENUM_RF_AT_PREAMBLE_T; + +/* Ack Policy */ +typedef enum _ENUM_RF_AT_ACK_POLICY_T { + RF_AT_ACK_POLICY_NORMAL = 0, + RF_AT_ACK_POLICY_NOACK, + RF_AT_ACK_POLICY_NOEXPLICTACK, + RF_AT_ACK_POLICY_BLOCKACK, + RF_AT_ACK_POLICY_NUM +} ENUM_RF_AT_ACK_POLICY_T; + +typedef enum _ENUM_RF_AUTOTEST_STATE_T { + RF_AUTOTEST_STATE_STANDBY = 0, + RF_AUTOTEST_STATE_TX, + RF_AUTOTEST_STATE_RX, + RF_AUTOTEST_STATE_RESET, + RF_AUTOTEST_STATE_OUTPUT_POWER, + RF_AUTOTEST_STATE_LOCA_FREQUENCY, + RF_AUTOTEST_STATE_CARRIER_SUPRRESION, + RF_AUTOTEST_STATE_NUM +} ENUM_RF_AUTOTEST_STATE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +WLAN_STATUS rftestSetATInfo(IN P_ADAPTER_T prAdapter, UINT_32 u4FuncIndex, UINT_32 u4FuncData); + +WLAN_STATUS +rftestQueryATInfo(IN P_ADAPTER_T prAdapter, + UINT_32 u4FuncIndex, UINT_32 u4FuncData, OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen); + +WLAN_STATUS rftestSetFrequency(IN P_ADAPTER_T prAdapter, IN UINT_32 u4FreqInKHz, IN PUINT_32 pu4SetInfoLen); + +#endif /* _RFTEST_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/typedef.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/typedef.h new file mode 100644 index 0000000000000..1d513bf1c03ae --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/typedef.h @@ -0,0 +1,167 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/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. + */ + +#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) +#if CFG_SUPPORT_ABORT_SCAN +#define WLAN_STATUS_ABORT_SCAN ((WLAN_STATUS) 0x00000001L) +#endif +#define WLAN_STATUS_PENDING ((WLAN_STATUS) 0x00000103L) +#define WLAN_STATUS_NOT_ACCEPTED ((WLAN_STATUS) 0x00010003L) + +#define WLAN_STATUS_MEDIA_CONNECT ((WLAN_STATUS) 0x4001000BL) +#define WLAN_STATUS_MEDIA_DISCONNECT ((WLAN_STATUS) 0x4001000CL) +#define WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY ((WLAN_STATUS) 0x4001000DL) +#define WLAN_STATUS_MEDIA_SPECIFIC_INDICATION ((WLAN_STATUS) 0x40010012L) + +#define WLAN_STATUS_SCAN_COMPLETE ((WLAN_STATUS) 0x60010001L) +#define WLAN_STATUS_MSDU_OK ((WLAN_STATUS) 0x60010002L) + +/* TODO(Kevin): double check if 0x60010001 & 0x60010002 is proprietary */ +#define WLAN_STATUS_ROAM_OUT_FIND_BEST ((WLAN_STATUS) 0x60010101L) +#define WLAN_STATUS_ROAM_DISCOVERY ((WLAN_STATUS) 0x60010102L) + +#define WLAN_STATUS_FAILURE ((WLAN_STATUS) 0xC0000001L) +#define WLAN_STATUS_RESOURCES ((WLAN_STATUS) 0xC000009AL) +#define WLAN_STATUS_NOT_SUPPORTED ((WLAN_STATUS) 0xC00000BBL) + +#define WLAN_STATUS_MULTICAST_FULL ((WLAN_STATUS) 0xC0010009L) +#define WLAN_STATUS_INVALID_PACKET ((WLAN_STATUS) 0xC001000FL) +#define WLAN_STATUS_ADAPTER_NOT_READY ((WLAN_STATUS) 0xC0010011L) +#define WLAN_STATUS_NOT_INDICATING ((WLAN_STATUS) 0xC0010013L) +#define WLAN_STATUS_INVALID_LENGTH ((WLAN_STATUS) 0xC0010014L) +#define WLAN_STATUS_INVALID_DATA ((WLAN_STATUS) 0xC0010015L) +#define WLAN_STATUS_BUFFER_TOO_SHORT ((WLAN_STATUS) 0xC0010016L) +#define WLAN_STATUS_BWCS_UPDATE ((WLAN_STATUS) 0xC0010017L) + +#define WLAN_STATUS_JOIN_FAILURE ((WLAN_STATUS) 0xc0010018L) + +#define WLAN_STATUS_BSS_CH_SWITCH ((WLAN_STATUS) 0xc0010019L) + +/* NIC status flags */ +#define ADAPTER_FLAG_HW_ERR 0x00400000 + +/******************************************************************************* +* 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 WLAN configuration */ +typedef struct _WLAN_CFG_T WLAN_CFG_T, *P_WLAN_CFG_T; + +/* Type definition for WLAN configuration entry */ +typedef struct _WLAN_CFG_ENTRY_T WLAN_CFG_ENTRY_T, *P_WLAN_CFG_ENTRY_T; + +/* Type definition for WLAN configuration callback */ +typedef WLAN_STATUS(*WLAN_CFG_SET_CB) (P_ADAPTER_T prAdapter, + PUINT_8 pucKey, PUINT_8 pucValue, PVOID pPrivate, UINT_32 u4Flags); + +/* Type definition for STA_RECORD_T structure to handle the connectivity and packet reception + * for a particular STA. + */ +typedef struct _STA_RECORD_T STA_RECORD_T, *P_STA_RECORD_T, **PP_STA_RECORD_T; + +/* CMD_INFO_T is used by Glue Layer to send a cluster of Command(OID) information to + * the TX Path to reduce the parameters of a function call. + */ +typedef struct _CMD_INFO_T CMD_INFO_T, *P_CMD_INFO_T; + +/* Following typedef should be removed later, because Glue Layer should not + * be aware of following data type. + */ +typedef struct _SW_RFB_T SW_RFB_T, *P_SW_RFB_T, **PP_SW_RFB_T; + +typedef struct _MSDU_INFO_T MSDU_INFO_T, *P_MSDU_INFO_T; + +typedef struct _REG_ENTRY_T REG_ENTRY_T, *P_REG_ENTRY_T; + +/* IST handler definition */ +typedef VOID(*IST_EVENT_FUNCTION) (P_ADAPTER_T); + +/* Type definition for function pointer of timer handler */ +typedef VOID(*PFN_TIMER_CALLBACK) (IN P_GLUE_INFO_T); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _TYPEDEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/wlan_bow.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/wlan_bow.h new file mode 100644 index 0000000000000..e497838b7d6f1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/wlan_bow.h @@ -0,0 +1,265 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/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. + */ + +#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 + +extern UINT_32 g_arBowRevPalPacketTime[32]; + +/******************************************************************************* +* 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, + IN UINT_8 ucBssIdx, + 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); + +UINT_8 bowInit(IN P_ADAPTER_T prAdapter); + +VOID bowUninit(IN P_ADAPTER_T prAdapter); + +VOID wlanbowCmdTimeoutHandler(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +VOID bowStopping(IN P_ADAPTER_T prAdapter); + +VOID bowStarting(IN P_ADAPTER_T prAdapter); + +VOID bowAssignSsid(IN PUINT_8 pucSsid, IN PUINT_8 pucSsidLen); + +BOOLEAN bowValidateProbeReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_32 pu4ControlFlags); + +VOID bowSendBeacon(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr); + +VOID bowResponderScan(IN P_ADAPTER_T prAdapter); + +VOID bowResponderScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID bowResponderCancelScan(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsChannelExtention); + +VOID bowResponderJoin(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc); + +VOID bowFsmRunEventJoinComplete(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID +bowIndicationOfMediaStateToHost(IN P_ADAPTER_T prAdapter, + ENUM_PARAM_MEDIA_STATE_T eConnectionState, BOOLEAN fgDelayIndication); + +VOID bowRunEventAAATxFail(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +WLAN_STATUS bowRunEventAAAComplete(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +WLAN_STATUS bowRunEventRxDeAuth(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb); + +VOID bowDisconnectLink(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +BOOLEAN bowValidateAssocReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu2StatusCode); + +BOOLEAN +bowValidateAuth(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, IN PP_STA_RECORD_T pprStaRec, OUT PUINT_16 pu2StatusCode); + +VOID bowRunEventChGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID bowRequestCh(IN P_ADAPTER_T prAdapter); + +VOID bowReleaseCh(IN P_ADAPTER_T prAdapter); + +VOID bowChGrantedTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); + +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 * pprBowTable); + +BOOLEAN +bowGetBowTableEntryByPeerAddress(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6], OUT PUINT_8 pucBowTableIdx); + +BOOLEAN bowGetBowTableFreeEntry(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucBowTableIdx); + +ENUM_BOW_DEVICE_STATE bowGetBowTableState(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6]); + +BOOLEAN bowSetBowTableState(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6], IN ENUM_BOW_DEVICE_STATE eState); + +BOOLEAN bowSetBowTableContent(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBowTableIdx, IN P_BOW_TABLE_T prBowTable); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif +#endif /* _WLAN_BOW_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/wlan_lib.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/wlan_lib.h new file mode 100644 index 0000000000000..78d7a25b62e59 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/wlan_lib.h @@ -0,0 +1,1055 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/wlan_lib.h#3 + */ + +/* + * ! \file "wlan_lib.h" + * \brief The declaration of the functions of the wlanAdpater objects + * + * Detail description. + */ + +#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" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define MAX_NUM_GROUP_ADDR 32 /* max number of group addresses */ + +#define TX_CS_TCP_UDP_GEN BIT(1) +#define TX_CS_IP_GEN BIT(0) + +#define CSUM_OFFLOAD_EN_TX_TCP BIT(0) +#define CSUM_OFFLOAD_EN_TX_UDP BIT(1) +#define CSUM_OFFLOAD_EN_TX_IP BIT(2) +#define CSUM_OFFLOAD_EN_RX_TCP BIT(3) +#define CSUM_OFFLOAD_EN_RX_UDP BIT(4) +#define CSUM_OFFLOAD_EN_RX_IPv4 BIT(5) +#define CSUM_OFFLOAD_EN_RX_IPv6 BIT(6) +#define CSUM_OFFLOAD_EN_TX_MASK BITS(0, 2) +#define CSUM_OFFLOAD_EN_ALL BITS(0, 6) + +/* TCP, UDP, IP Checksum */ +#define RX_CS_TYPE_UDP BIT(7) +#define RX_CS_TYPE_TCP BIT(6) +#define RX_CS_TYPE_IPv6 BIT(5) +#define RX_CS_TYPE_IPv4 BIT(4) + +#define RX_CS_STATUS_UDP BIT(3) +#define RX_CS_STATUS_TCP BIT(2) +#define RX_CS_STATUS_IP BIT(0) + +#define CSUM_NOT_SUPPORTED 0x0 + +#define TXPWR_USE_PDSLOPE 0 + +/* NVRAM error code definitions */ +#define NVRAM_ERROR_VERSION_MISMATCH BIT(1) +#define NVRAM_ERROR_INVALID_TXPWR BIT(2) +#define NVRAM_ERROR_INVALID_DPD BIT(3) +#define NVRAM_ERROR_INVALID_MAC_ADDR BIT(4) +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY +#define NVRAM_POWER_LIMIT_TABLE_INVALID BIT(5) +#endif + +#define NUM_TC_RESOURCE_TO_STATISTICS 4 + +#define WLAN_CFG_ARGV_MAX 8 +#define WLAN_CFG_ENTRY_NUM_MAX 128 +#define WLAN_CFG_KEY_LEN_MAX 32 /* include \x00 EOL */ +#define WLAN_CFG_VALUE_LEN_MAX 32 /* include \x00 EOL */ +#define WLAN_CFG_FLAG_SKIP_CB BIT(0) +#define WLAN_CFG_FILE_BUF_SIZE 2048 + +#define WLAN_CFG_SET_CHIP_LEN_MAX 10 +#define WLAN_CFG_SET_DEBUG_LEVEL_LEN_MAX 10 +#define WLAN_CFG_SET_SW_CTRL_LEN_MAX 10 + +#define WLAN_OID_TIMEOUT_THRESHOLD 2000 /* OID timeout (in ms) */ + +#define WLAN_OID_TIMEOUT_THRESHOLD_IN_RESETTING 300 /* OID timeout during chip-resetting (in ms) */ + +#define WLAN_OID_NO_ACK_THRESHOLD 3 + +#define WLAN_TX_THREAD_TASK_PRIORITY 0 /* If not setting the priority, 0 is the default */ +#define WLAN_TX_THREAD_TASK_NICE (-10) /* If not setting the nice, -10 is the default */ + +#define WLAN_TX_STATS_LOG_TIMEOUT 30000 +#define WLAN_TX_STATS_LOG_DURATION 1500 + +#if defined(MT6631) +#define WIFI_EMI_MEM_SIZE (512 * 1024) +#endif +/******************************************************************************* +* 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 enum _ENUM_FEATURE_OPTION_T { + FEATURE_DISABLED, + FEATURE_ENABLED, + FEATURE_FORCE_ENABLED +} ENUM_FEATURE_OPTION_T, *P_ENUM_FEATURE_OPTION_T; + +/* This enum is for later added feature options which use command reserved field as option switch */ +typedef enum _ENUM_FEATURE_OPTION_IN_CMD_T { + FEATURE_OPT_CMD_AUTO, + FEATURE_OPT_CMD_DISABLED, + FEATURE_OPT_CMD_ENABLED, + FEATURE_OPT_CMD_FORCE_ENABLED +} ENUM_FEATURE_OPTION_IN_CMD_T, *P_ENUM_FEATURE_OPTION_IN_CMD_T; + +#define DEBUG_MSG_SIZE_MAX 1200 +enum { + DEBUG_MSG_ID_UNKNOWN = 0x00, + DEBUG_MSG_ID_PRINT = 0x01, + DEBUG_MSG_ID_FWLOG = 0x02, + DEBUG_MSG_ID_END +}; + +enum { + DEBUG_MSG_TYPE_UNKNOWN = 0x00, + DEBUG_MSG_TYPE_MEM8 = 0x01, + DEBUG_MSG_TYPE_MEM32 = 0x02, + DEBUG_MSG_TYPE_ASCII = 0x03, + DEBUG_MSG_TYPE_BINARY = 0x04, + DEBUG_MSG_TYPE_END +}; + +#define CHIP_CONFIG_RESP_SIZE 320 +enum { + CHIP_CONFIG_TYPE_WO_RESPONSE = 0x00, + CHIP_CONFIG_TYPE_MEM8 = 0x01, + CHIP_CONFIG_TYPE_MEM32 = 0x02, + CHIP_CONFIG_TYPE_ASCII = 0x03, + CHIP_CONFIG_TYPE_BINARY = 0x04, + CHIP_CONFIG_TYPE_DRV_PASSTHROUGH = 0x05, + CHIP_CONFIG_TYPE_END +}; + +typedef struct _SET_TXPWR_CTRL_T { + INT_8 c2GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0 */ + INT_8 c2GHotspotPwrOffset; + INT_8 c2GP2pPwrOffset; + INT_8 c2GBowPwrOffset; + INT_8 c5GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0 */ + INT_8 c5GHotspotPwrOffset; + INT_8 c5GP2pPwrOffset; + INT_8 c5GBowPwrOffset; + UINT_8 ucConcurrencePolicy; /* + * TX power policy when concurrence + * in the same channel + * 0: Highest power has priority + * 1: Lowest power has priority + */ + INT_8 acReserved1[3]; /* Must be zero */ + + /* Power limit by channel for all data rates */ + INT_8 acTxPwrLimit2G[14]; /* Channel 1~14, Unit: 0.5dBm */ + INT_8 acTxPwrLimit5G[4]; /* UNII 1~4 */ + INT_8 acReserved2[2]; /* Must be zero */ +} SET_TXPWR_CTRL_T, *P_SET_TXPWR_CTRL_T; + +typedef enum _ENUM_NVRAM_MTK_FEATURE_T { + MTK_FEATURE_2G_256QAM_DISABLED = 0, + MTK_FEATURE_NUM +} ENUM_NVRAM_MTK_FEATURES_T, *P_ENUM_NVRAM_MTK_FEATURES_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- */ +#if 1 + UINT_16 u2Part1OwnVersion; + UINT_16 u2Part1PeerVersion; +#endif + 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; + RSSI_PATH_COMPASATION_T rRssiPathCompasation; + UINT_8 ucRssiPathCompasationUsed; + /* NVRAM - MP Data -END- */ + + /* NVRAM - Functional Data -START- */ + UINT_8 uc2G4BwFixed20M; + UINT_8 uc5GBwFixed20M; + UINT_8 ucEnable5GBand; + UINT_8 ucGpsDesense; + UINT_8 ucRxDiversity; + /* NVRAM - Functional Data -END- */ + + P_NEW_EFUSE_MAPPING2NVRAM_T prOldEfuseMapping; + UINT_8 aucNvram[EXTEND_NVRAM_SIZE]; + P_WIFI_CFG_PARAM_STRUCT prNvramSettings; + +} REG_INFO_T, *P_REG_INFO_T; + +#if defined(MT6631) +/* for divided firmware download */ +typedef struct _FWDL_SECTION_INFO_T { + UINT_32 u4Offset; + UINT_8 ucKIdx; + UINT_8 ucEnc; + UINT_16 u2Reserved; + 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_16 u2MajorNumber; + UINT_16 u2MinorNumber; + UINT_32 u4ChipInfo; + UINT_32 u4Reserved; + FWDL_SECTION_INFO_T arSection[]; +} FIRMWARE_DIVIDED_DOWNLOAD_T, *P_FIRMWARE_DIVIDED_DOWNLOAD_T; + +#else + +/* for divided firmware download */ +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; +#endif + + +typedef struct _PARAM_MCR_RW_STRUCT_T { + UINT_32 u4McrOffset; + UINT_32 u4McrData; +} PARAM_MCR_RW_STRUCT_T, *P_PARAM_MCR_RW_STRUCT_T; + +/* per access category statistics */ +typedef struct _WIFI_WMM_AC_STAT_T { + UINT_32 u4TxMsdu; + UINT_32 u4RxMsdu; + UINT_32 u4TxDropMsdu; + UINT_32 u4TxFailMsdu; + UINT_32 u4TxRetryMsdu; +} WIFI_WMM_AC_STAT_T, *P_WIFI_WMM_AC_STAT_T; + +typedef struct _PARAM_GET_STA_STATISTICS { + /* Per-STA statistic */ + UINT_8 ucInvalid; + UINT_8 ucVersion; + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + + UINT_32 u4LinkScore; + UINT_32 u4Flag; + + UINT_8 ucReadClear; + UINT_8 ucLlsReadClear; + + /* From driver */ + UINT_32 u4TxTotalCount; + UINT_32 u4TxExceedThresholdCount; + + UINT_32 u4TxMaxTime; + UINT_32 u4TxAverageProcessTime; + + UINT_32 u4TxMaxHifTime; + UINT_32 u4TxAverageHifTime; + + UINT_32 u4RxTotalCount; + + + /* + * How many packages Enqueue/Deqeue during statistics interval + */ + UINT_32 u4EnqueueCounter; + UINT_32 u4DequeueCounter; + + UINT_32 u4EnqueueStaCounter; + UINT_32 u4DequeueStaCounter; + + UINT_32 IsrCnt; + UINT_32 IsrPassCnt; + UINT_32 TaskIsrCnt; + + UINT_32 IsrAbnormalCnt; + UINT_32 IsrSoftWareCnt; + UINT_32 IsrRxCnt; + UINT_32 IsrTxCnt; + + + UINT_32 au4TcResourceEmptyCount[NUM_TC_RESOURCE_TO_STATISTICS]; + UINT_32 au4DequeueNoTcResource[NUM_TC_RESOURCE_TO_STATISTICS]; + UINT_32 au4TcResourceBackCount[NUM_TC_RESOURCE_TO_STATISTICS]; + UINT_32 au4TcResourceUsedPageCount[NUM_TC_RESOURCE_TO_STATISTICS]; + UINT_32 au4TcResourceWantedPageCount[NUM_TC_RESOURCE_TO_STATISTICS]; + + UINT_32 au4TcQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + + /* From FW */ + UINT_8 ucPer; /* base: 128 */ + UINT_8 ucRcpi; + UINT_32 u4PhyMode; + UINT_16 u2LinkSpeed; /* unit is 0.5 Mbits */ + + UINT_32 u4TxFailCount; + UINT_32 u4TxLifeTimeoutCount; + + UINT_32 u4TxAverageAirTime; + UINT_32 u4TransmitCount; /* Transmit in the air (wtbl) */ + UINT_32 u4TransmitFailCount; /* Transmit without ack/ba in the air (wtbl) */ + + WIFI_WMM_AC_STAT_T arLinkStatistics[AC_NUM]; /*link layer statistics */ + + /* Global queue management statistic */ + UINT_32 au4TcAverageQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + UINT_32 au4TcCurrentQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + + /* Reserved fields */ + UINT_8 au4Reserved[32]; +} PARAM_GET_STA_STA_STATISTICS, *P_PARAM_GET_STA_STATISTICS; + +typedef struct _PARAM_GET_BSS_STATISTICS { + /* Per-STA statistic */ + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + + UINT_32 u4Flag; + + UINT_8 ucReadClear; + + UINT_8 ucLlsReadClear; + + UINT_8 ucBssIndex; + + /* From driver */ + UINT_32 u4TxTotalCount; + UINT_32 u4TxExceedThresholdCount; + + UINT_32 u4TxMaxTime; + UINT_32 u4TxAverageProcessTime; + + UINT_32 u4RxTotalCount; + + UINT_32 au4TcResourceEmptyCount[NUM_TC_RESOURCE_TO_STATISTICS]; + UINT_32 au4TcQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + + /* From FW */ + UINT_8 ucPer; /* base: 128 */ + UINT_8 ucRcpi; + UINT_32 u4PhyMode; + UINT_16 u2LinkSpeed; /* unit is 0.5 Mbits */ + + UINT_32 u4TxFailCount; + UINT_32 u4TxLifeTimeoutCount; + + UINT_32 u4TxAverageAirTime; + UINT_32 u4TransmitCount; /* Transmit in the air (wtbl) */ + UINT_32 u4TransmitFailCount; /* Transmit without ack/ba in the air (wtbl) */ + + WIFI_WMM_AC_STAT_T arLinkStatistics[AC_NUM]; /*link layer statistics */ + + /* Global queue management statistic */ + UINT_32 au4TcAverageQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + UINT_32 au4TcCurrentQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + + /* Reserved fields */ + UINT_8 au4Reserved[32]; /* insufficient for LLS?? */ +} PARAM_GET_BSS_STATISTICS, *P_PARAM_GET_BSS_STATISTICS; + +typedef struct _NET_INTERFACE_INFO_T { + UINT_8 ucBssIndex; + PVOID pvNetInterface; +} NET_INTERFACE_INFO_T, *P_NET_INTERFACE_INFO_T; + +#if 0 +typedef struct _SEC_FRAME_INFO_T { + BOOLEAN fgIsProtected; +#if CFG_SUPPORT_MULTITHREAD + /* Compose TxDesc in tx_thread and place here */ + UINT_8 ucTxDescBuffer[DWORD_TO_BYTE(7)]; +#endif +} SEC_FRAME_INFO_T, *P_SEC_FRAME_INFO_T; +#endif + +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_BIP_ERROR, + TX_RESULT_UNSPECIFIED_ERROR, + TX_RESULT_DROPPED_IN_DRIVER = 32, + TX_RESULT_DROPPED_IN_FW, + TX_RESULT_QUEUE_CLEARANCE, + TX_RESULT_NUM +} ENUM_TX_RESULT_CODE_T, *P_ENUM_TX_RESULT_CODE_T; + +/* enum of BEACON_TIMEOUT_REASON */ +enum _ENUM_PM_BEACON_TIME_OUT_REACON_CODE_T { + BEACON_TIMEOUT_DUE_2_HW_BEACON_LOST_NONADHOC, + BEACON_TIMEOUT_DUE_2_HW_BEACON_LOST_ADHOC, + BEACON_TIMEOUT_DUE_2_HW_TSF_DRIFT, + BEACON_TIMEOUT_DUE_2_NULL_FRAME_THRESHOLD, + BEACON_TIMEOUT_DUE_2_AGING_THRESHOLD, + BEACON_TIMEOUT_DUE_2_BSSID_BEACON_PEIROD_NOT_ILLIGAL, + BEACON_TIMEOUT_DUE_2_CONNECTION_FAIL, + BEACON_TIMEOUT_DUE_2_ALLOCAT_NULL_PKT_FAIL_THRESHOLD, + BEACON_TIMEOUT_DUE_2_NO_TX_DONE_EVENT, + BEACON_TIMEOUT_DUE_2_UNSPECIF_REASON, + BEACON_TIMEOUT_DUE_2_SET_CHIP, + BEACON_TIMEOUT_DUE_2_KEEP_SCAN_AP_MISS_CHECK_FAIL, + BEACON_TIMEOUT_DUE_2_KEEP_UNCHANGED_LOW_RSSI_CHECK_FAIL, + BEACON_TIMEOUT_DUE_2_NULL_FRAME_LIFE_TIMEOUT, + BEACON_TIMEOUT_DUE_2_APR_NO_RESPONSE, + BEACON_TIMEOUT_DUE_2_NUM +}; + +struct _WLAN_CFG_ENTRY_T { + UINT_8 aucKey[WLAN_CFG_KEY_LEN_MAX]; + UINT_8 aucValue[WLAN_CFG_VALUE_LEN_MAX]; + WLAN_CFG_SET_CB pfSetCb; + PVOID pPrivate; + UINT_32 u4Flags; +}; + +struct _WLAN_CFG_T { + UINT_32 u4WlanCfgEntryNumMax; + UINT_32 u4WlanCfgKeyLenMax; + UINT_32 u4WlanCfgValueLenMax; + WLAN_CFG_ENTRY_T arWlanCfgBuf[WLAN_CFG_ENTRY_NUM_MAX]; +}; + +typedef enum _ENUM_MAX_BANDWIDTH_SETTING_T { + MAX_BW_20MHZ = 0, + MAX_BW_40MHZ, + MAX_BW_80MHZ, + MAX_BW_160MHZ, + MAX_BW_80_80_MHZ, + MAX_BW_UNKNOWN +} ENUM_MAX_BANDWIDTH_SETTING, *P_ENUM_MAX_BANDWIDTH_SETTING_T; + +typedef struct _TX_PACKET_INFO { + UINT_8 ucPriorityParam; + UINT_32 u4PacketLen; + UINT_8 aucEthDestAddr[MAC_ADDR_LEN]; + UINT_16 u2Flag; + +#if 0 + BOOLEAN fgIs1X; + BOOLEAN fgIsPAL; + BOOLEAN fgIs802_3; + BOOLEAN fgIsVlanExists; + BOOLEAN fgIsDhcp; + BOOLEAN fgIsArp; +#endif +} TX_PACKET_INFO, *P_TX_PACKET_INFO; + +typedef enum _ENUM_TX_PROFILING_TAG_T { + TX_PROF_TAG_OS_TO_DRV = 0, + TX_PROF_TAG_DRV_ENQUE, + TX_PROF_TAG_DRV_DEQUE, + TX_PROF_TAG_DRV_TX_DONE, + TX_PROF_TAG_MAC_TX_DONE +} ENUM_TX_PROFILING_TAG_T, *P_ENUM_TX_PROFILING_TAG_T; +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR +/* for link quality monitor */ +struct WIFI_LINK_QUALITY_INFO { + UINT_32 u4CurTxRate; /* Tx rate for DATA packet */ + UINT_64 u8TxTotalCount; /* Tx total accumulated count */ + UINT_64 u8TxRetryCount; + UINT_64 u8TxFailCount; + UINT_64 u8TxRtsFailCount; + UINT_64 u8TxAckFailCount; + + UINT_32 u4CurRxRate; /* Rx rate for DATA packet */ + UINT_64 u8RxTotalCount; /* Rx total accumulated count */ + UINT_32 u4RxDupCount; + UINT_64 u8RxErrCount; + + UINT_32 u4CurTxPer; + UINT_64 u8MdrdyCount; + UINT_64 u8IdleSlotCount; + UINT_64 u8DiffIdleSlotCount; + + UINT_32 u4PhyMode; + UINT_16 u2LinkSpeed; + + UINT_64 u8LastTxTotalCount; + UINT_32 u8LastTxFailCount; + UINT_64 u8LastIdleSlotCount; +}; +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define BUILD_SIGN(ch0, ch1, ch2, ch3) \ + ((UINT_32)(UINT_8)(ch0) | ((UINT_32)(UINT_8)(ch1) << 8) | \ + ((UINT_32)(UINT_8)(ch2) << 16) | ((UINT_32)(UINT_8)(ch3) << 24)) + +#if defined(MT6631) +#define MTK_WIFI_SIGNATURE BUILD_SIGN('M', 'T', 'K', 'E') +#else +#define MTK_WIFI_SIGNATURE BUILD_SIGN('M', 'T', 'K', 'W') +#endif + +#define IS_FEATURE_ENABLED(_ucFeature) \ + (((_ucFeature) == FEATURE_ENABLED) || ((_ucFeature) == FEATURE_FORCE_ENABLED)) +#define IS_FEATURE_FORCE_ENABLED(_ucFeature) ((_ucFeature) == FEATURE_FORCE_ENABLED) +#define IS_FEATURE_DISABLED(_ucFeature) ((_ucFeature) == FEATURE_DISABLED) + +/* This macro is for later added feature options which use command reserved field as option switch */ +/* 0: AUTO + * 1: Disabled + * 2: Enabled + * 3: Force disabled + */ +#define FEATURE_OPT_IN_COMMAND(_ucFeature) ((_ucFeature) + 1) + +/******************************************************************************* +* 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); + +#if CFG_SUPPORT_MULTITHREAD +WLAN_STATUS wlanSendCommandMthread(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +WLAN_STATUS wlanTxCmdMthread(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS wlanTxCmdDoneMthread(IN P_ADAPTER_T prAdapter); + +VOID wlanClearTxCommandQueue(IN P_ADAPTER_T prAdapter); + +VOID wlanClearTxCommandDoneQueue(IN P_ADAPTER_T prAdapter); + +VOID wlanClearDataQueue(IN P_ADAPTER_T prAdapter); + +VOID wlanClearRxToOsQueue(IN P_ADAPTER_T prAdapter); +#endif + +VOID wlanReleaseCommand(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +VOID wlanReleasePendingOid(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); + +VOID wlanReleasePendingCMDbyBssIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex); + +VOID wlanReturnPacketDelaySetupTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); + +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); + +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 + +WLAN_STATUS +wlanImageSectionConfig(IN P_ADAPTER_T prAdapter, IN UINT_32 u4DestAddr, IN UINT_32 u4ImgSecSize, IN BOOLEAN fgReset, + IN UINT_8 ucEnc, IN UINT_8 ucKIdx); + +WLAN_STATUS wlanImageSectionDownload(IN P_ADAPTER_T prAdapter, IN UINT_32 u4ImgSecSize, IN PUINT_8 pucImgSecBuf); + +VOID +wlanFwDvdDwnloadHandler(IN P_ADAPTER_T prAdapter, + IN P_FIRMWARE_DIVIDED_DOWNLOAD_T prFwHead, IN PVOID pvFwImageMapFile, + OUT WLAN_STATUS *u4Status); + +VOID +wlanFwDwnloadHandler(IN P_ADAPTER_T prAdapter, + IN UINT_32 u4FwImgLength, IN PVOID pvFwImageMapFile, OUT WLAN_STATUS *u4Status); + +#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); + +WLAN_STATUS wlanUpdateBasicConfig(IN P_ADAPTER_T prAdapter); + +BOOLEAN wlanQueryTestMode(IN P_ADAPTER_T prAdapter); + +BOOLEAN wlanProcessTxFrame(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prPacket); + +/* 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 + +/*----------------------------------------------------------------------------*/ +/* 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_STRUCT_T prMcrRdInfo); + +/*----------------------------------------------------------------------------*/ +/* Loading Manufacture Data */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanLoadManufactureData(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo); + +/*----------------------------------------------------------------------------*/ +/* Media Stream Mode */ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanResetMediaStreamMode(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* Timer Timeout Check (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanTimerTimeoutCheck(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Check (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanProcessMboxMessage(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* TX Pending Packets Handling (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanEnqueueTxPacket(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prNativePacket); + +WLAN_STATUS wlanFlushTxPendingPackets(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS wlanTxPendingPackets(IN P_ADAPTER_T prAdapter, IN OUT PBOOLEAN pfgHwAccess); + +/*----------------------------------------------------------------------------*/ +/* Low Power Acquire/Release (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanAcquirePowerControl(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS wlanReleasePowerControl(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* Pending Packets Number Reporting (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +UINT_32 wlanGetTxPendingFrameCount(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* ACPI state inquiry (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +ENUM_ACPI_STATE_T wlanGetAcpiState(IN P_ADAPTER_T prAdapter); + +VOID wlanSetAcpiState(IN P_ADAPTER_T prAdapter, IN ENUM_ACPI_STATE_T ePowerState); + +VOID wlanDefTxPowerCfg(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* get ECO version from Revision ID register (for Win32) */ +/*----------------------------------------------------------------------------*/ +UINT_8 wlanGetEcoVersion(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* set preferred band configuration corresponding to network type */ +/*----------------------------------------------------------------------------*/ +VOID wlanSetPreferBandByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_BAND_T eBand, IN UINT_8 ucBssIndex); + +/*----------------------------------------------------------------------------*/ +/* get currently operating channel information */ +/*----------------------------------------------------------------------------*/ +UINT_8 wlanGetChannelNumberByNetwork(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex); + +/*----------------------------------------------------------------------------*/ +/* check for system configuration to generate message on scan list */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanCheckSystemConfiguration(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* query bss statistics information from driver and firmware */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryBssStatistics(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +/*----------------------------------------------------------------------------*/ +/* dump per-BSS statistics */ +/*----------------------------------------------------------------------------*/ +VOID wlanDumpBssStatistics(IN P_ADAPTER_T prAdapter, UINT_8 ucBssIndex); + +/*----------------------------------------------------------------------------*/ +/* query sta statistics information from driver and firmware */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryStaStatistics(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS wlanQueryStaStatistics(IN P_ADAPTER_T prAdapter, IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen, BOOLEAN fgIsOid); +WLAN_STATUS +wlanQueryStatistics(IN P_ADAPTER_T prAdapter, IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen, BOOLEAN fgIsOid); +/*----------------------------------------------------------------------------*/ +/* query NIC resource information from chip and reset Tx resource for normal operation */ +/*----------------------------------------------------------------------------*/ +VOID wlanQueryNicResourceInformation(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* GET/SET BSS index mapping for network interfaces */ +/*----------------------------------------------------------------------------*/ +VOID wlanBindNetInterface(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucNetInterfaceIndex, IN PVOID pvNetInterface); + +VOID wlanBindBssIdxToNetInterface(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucBssIndex, IN PVOID pvNetInterface); + +UINT_8 wlanGetBssIdxByNetInterface(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvNetInterface); + +PVOID wlanGetNetInterfaceByBssIdx(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucBssIndex); + +uint8_t wlanGetBssIdx(struct net_device *ndev); + +/* for windows as windows glue cannot see through P_ADAPTER_T */ +UINT_8 wlanGetAisBssIndex(IN P_ADAPTER_T prAdapter); + +VOID wlanInitFeatureOption(IN P_ADAPTER_T prAdapter); + +VOID wlanCfgSetSwCtrl(IN P_ADAPTER_T prAdapter); + +VOID wlanCfgSetChip(IN P_ADAPTER_T prAdapter); + +VOID wlanGetFwInfo(IN P_ADAPTER_T prAdapter); + +VOID wlanCfgSetDebugLevel(IN P_ADAPTER_T prAdapter); + +VOID wlanCfgSetCountryCode(IN P_ADAPTER_T prAdapter); + +P_WLAN_CFG_ENTRY_T wlanCfgGetEntry(IN P_ADAPTER_T prAdapter, const PCHAR pucKey); + +WLAN_STATUS +wlanCfgGet(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, PCHAR pucValue, PCHAR pucValueDef, UINT_32 u4Flags); + +UINT_32 wlanCfgGetUint32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, UINT_32 u4ValueDef); + +INT_32 wlanCfgGetInt32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, INT_32 i4ValueDef); + +WLAN_STATUS wlanCfgSetUint32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, UINT_32 u4Value); + +WLAN_STATUS wlanCfgSet(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, PCHAR pucValue, UINT_32 u4Flags); + +WLAN_STATUS +wlanCfgSetCb(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, WLAN_CFG_SET_CB pfSetCb, void *pPrivate, UINT_32 u4Flags); + +WLAN_STATUS wlanCfgInit(IN P_ADAPTER_T prAdapter, PUINT_8 pucConfigBuf, UINT_32 u4ConfigBufLen, UINT_32 u4Flags); + +WLAN_STATUS wlanCfgParseArgument(CHAR *cmdLine, INT_32 *argc, CHAR *argv[]); + +INT_32 wlanHexToNum(CHAR c); +INT_32 wlanHexToByte(PCHAR hex); + +INT_32 wlanHwAddrToBin(PCHAR txt, UINT_8 *addr); + +BOOLEAN wlanIsChipNoAck(IN P_ADAPTER_T prAdapter); + +VOID wlanTxProfilingTagPacket(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prPacket, IN ENUM_TX_PROFILING_TAG_T eTag); + +VOID wlanTxProfilingTagMsdu(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_PROFILING_TAG_T eTag); +VOID wlanTxLifetimeTagPacketQue(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead, + IN ENUM_TX_PROFILING_TAG_T eTag); + +/*----------------------------------------------------------------------------*/ +/* update per-AC statistics for LLS */ +/*----------------------------------------------------------------------------*/ +VOID wlanUpdateTxStatistics(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, BOOLEAN fgTxDrop); + +VOID wlanUpdateRxStatistics(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +WLAN_STATUS wlanTriggerStatsLog(IN P_ADAPTER_T prAdapter, IN UINT_32 u4DurationInMs); + +WLAN_STATUS wlanDhcpTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +WLAN_STATUS wlanArpTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +WLAN_STATUS wlanIcmpTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +WLAN_STATUS wlanTdlsTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +WLAN_STATUS wlanDnsTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +VOID wlanReleasePendingCmdById(P_ADAPTER_T prAdapter, UINT_8 ucCid); + +UINT_32 wlanDecimalStr2Hexadecimals(PUINT_8 pucDecimalStr, PUINT_16 pu2Out); + +WLAN_STATUS wlanCfgParse(IN P_ADAPTER_T prAdapter, PUINT_8 pucConfigBuf, UINT_32 u4ConfigBufLen); +UINT_32 +wlanQueryLteSafeChannel(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucRoleIndex); + +UINT_8 +wlanGetChannelIndex(IN UINT_8 channel); +extern INT_32 wlanUpdateDfsChannelTable(P_GLUE_INFO_T prGlueInfo, UINT_8 ucCurrChNo); +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR +/* link quality monitor */ +void wlanLinkQualityMonitor(P_GLUE_INFO_T prGlueInfo); +void wlanFinishCollectingLinkQuality(P_GLUE_INFO_T prGlueInfo); +UINT_32 wlanGetStaIdxByWlanIdx(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucIndex, OUT UINT_8 *pucStaIdx); +#endif + +#if CFG_SUPPORT_REPORT_MISC +UINT_32 wlanExtSrcReportMisc(P_GLUE_INFO_T prGlueInfo); +#endif + +#endif /* _WLAN_LIB_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/wlan_oid.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/wlan_oid.h new file mode 100644 index 0000000000000..943545417089c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/wlan_oid.h @@ -0,0 +1,2491 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/wlan_oid.h#4 + */ + +/* + * ! \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. + */ + +#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 +******************************************************************************** +*/ +#include "cnm_scan.h" + +/******************************************************************************* +* 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_INITIAL_DBM (-50) +#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 0xF0000000 +#define PARAM_PACKET_FILTER_PROBE_REQ 0x80000000 +#define PARAM_PACKET_FILTER_ACTION_FRAME 0x40000000 +#define PARAM_PACKET_FILTER_AUTH 0x20000000 +#define PARAM_PACKET_FILTER_ASSOC_REQ 0x10000000 + +#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 + +#if CFG_SUPPORT_BUFFER_MODE + +/* For MT6632,6630 */ +#define EFUSE_CONTENT_BUFFER_START 0x03A +#define EFUSE_CONTENT_BUFFER_END 0x1D9 +#define EFUSE_CONTENT_SIZE_1 (EFUSE_CONTENT_BUFFER_END - EFUSE_CONTENT_BUFFER_START + 1) +#define EFUSE_CONTENT_SIZE 16 + +#define EFUSE_BLOCK_SIZE 16 +#define EEPROM_SIZE 1184 +#endif /* CFG_SUPPORT_BUFFER_MODE */ + +#if CFG_SUPPORT_TX_BF +#define TXBF_CMD_NEED_TO_RESPONSE(u4TxBfCmdId) (u4TxBfCmdId == BF_PFMU_TAG_READ || \ + u4TxBfCmdId == BF_PROFILE_READ) +#endif /* CFG_SUPPORT_TX_BF */ +#define MU_CMD_NEED_TO_RESPONSE(u4MuCmdId) (u4MuCmdId == MU_GET_CALC_INIT_MCS || \ + u4MuCmdId == MU_HQA_GET_QD || \ + u4MuCmdId == MU_HQA_GET_CALC_LQ) + +#if CFG_SUPPORT_MU_MIMO +/* @NITESH: MACROS For Init MCS calculation (MU Metric Table) */ +#define NUM_MUT_FEC 2 +#define NUM_MUT_MCS 10 +#define NUM_MUT_NR_NUM 3 +#define NUM_MUT_INDEX 8 + +#define NUM_OF_USER 2 +#define NUM_OF_MODUL 5 +#endif /* CFG_SUPPORT_MU_MIMO */ + +#if CFG_SUPPORT_LOWLATENCY_MODE +#define LOWLATENCY_MODE_MAGIC_CODE 0x86 +#define LOWLATENCY_MODE_CMD_V1 0x1 + +#define GED_EVENT_GAS (1 << 4) +#define GED_EVENT_NETWORK (1 << 11) +#define GED_EVENT_DOPT_WIFI_SCAN (1 << 12) +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + +/******************************************************************************* +* 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_NON_RSN_FT, /* Fast Bss Transition in a Non FT */ + 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_WPA2_FT, /* Fast Bss Transition for 802.1x */ + AUTH_MODE_WPA2_FT_PSK, /* Fast Bss Transition for WPA2 PSK */ + AUTH_MODE_WPA3_SAE, + AUTH_MODE_WPA3_OWE, + 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; + +typedef struct _PARAM_CONNECT_T { + UINT_32 u4SsidLen; /*!< SSID length in bytes. Zero length is broadcast(any) SSID */ + UINT_8 *pucSsid; + UINT_8 *pucBssid; + UINT_32 u4CenterFreq; +} PARAM_CONNECT_T, *P_PARAM_CONNECT_T; + +struct PARAM_EXTERNAL_AUTH { + UINT_8 bssid[PARAM_MAC_ADDR_LEN]; + UINT_16 status; + UINT_8 ucBssIdx; +}; + +/* 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_DISCONNECT_PREV, + 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_FT_AUTH_STATUS, + 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_16 u2CapInfo; + 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 */ + UINT_8 ucBssIdx; + UINT_8 ucCipher; +} 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 */ + UINT_8 ucBssIdx; +} PARAM_REMOVE_KEY_T, *P_PARAM_REMOVE_KEY_T; + +/*! \brief Default key */ +typedef struct _PARAM_DEFAULT_KEY_T { + UINT_8 ucKeyID; + UINT_8 ucUnicast; + UINT_8 ucMulticast; + UINT_8 ucBssIdx; +} PARAM_DEFAULT_KEY_T, *P_PARAM_DEFAULT_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; + +typedef struct _PARAM_POWER_MODE_T { + UINT_8 ucBssIdx; + PARAM_POWER_MODE ePowerMode; +} PARAM_POWER_MODE_T, *P_PARAM_POWER_MODE_T; + +#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[CFG_MAX_PMKID_CACHE]; +} PARAM_PMKID_CANDIDATE_LIST_T, *P_PARAM_PMKID_CANDIDATE_LIST_T; +/* #endif */ + +#define NL80211_KCK_LEN 16 +#define NL80211_KEK_LEN 16 +#define NL80211_REPLAY_CTR_LEN 8 + +typedef struct _PARAM_GTK_REKEY_DATA { + UINT_8 aucKek[NL80211_KEK_LEN]; + UINT_8 aucKck[NL80211_KCK_LEN]; + UINT_8 aucReplayCtr[NL80211_REPLAY_CTR_LEN]; +} PARAM_GTK_REKEY_DATA, *P_PARAM_GTK_REKEY_DATA; + +typedef struct _PARAM_CUSTOM_MCR_RW_STRUCT_T { + UINT_32 u4McrOffset; + UINT_32 u4McrData; +} PARAM_CUSTOM_MCR_RW_STRUCT_T, *P_PARAM_CUSTOM_MCR_RW_STRUCT_T; + +#if CFG_SUPPORT_QA_TOOL +#if CFG_SUPPORT_BUFFER_MODE +typedef struct _BIN_CONTENT_T { + UINT_16 u2Addr; + UINT_8 ucValue; + UINT_8 ucReserved; +} BIN_CONTENT_T, *P_BIN_CONTENT_T; + +typedef struct _PARAM_CUSTOM_EFUSE_BUFFER_MODE_T { + UINT_8 ucSourceMode; + UINT_8 ucCount; + UINT_8 ucReserved[2]; + BIN_CONTENT_T aBinContent[EFUSE_CONTENT_SIZE]; +} PARAM_CUSTOM_EFUSE_BUFFER_MODE_T, *P_PARAM_CUSTOM_EFUSE_BUFFER_MODE_T; + +typedef struct _PARAM_CUSTOM_EFUSE_BUFFER_MODE_1_T { + UINT_8 ucSourceMode; + UINT_8 ucCount; + UINT_8 ucCmdType; + UINT_8 ucReserved; + UINT_8 aBinContent[EFUSE_CONTENT_SIZE_1]; +} PARAM_CUSTOM_EFUSE_BUFFER_MODE_1_T, *P_PARAM_CUSTOM_EFUSE_BUFFER_MODE_1_T; + + +/*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ +typedef struct _PARAM_CUSTOM_ACCESS_EFUSE_T { + UINT_32 u4Address; + UINT_32 u4Valid; + UINT_8 aucData[16]; +} PARAM_CUSTOM_ACCESS_EFUSE_T, *P_PARAM_CUSTOM_ACCESS_EFUSE_T; + + +typedef struct _PARAM_CUSTOM_EFUSE_FREE_BLOCK_T { + UINT_8 ucGetFreeBlock; + UINT_8 aucReserved[3]; +} PARAM_CUSTOM_EFUSE_FREE_BLOCK_T, *P_PARAM_CUSTOM_EFUSE_FREE_BLOCK_T; + +/*#endif*/ + +#endif /* CFG_SUPPORT_BUFFER_MODE */ + +typedef struct _PARAM_CUSTOM_ACCESS_RX_STAT { + UINT_32 u4SeqNum; + UINT_32 u4TotalNum; +} PARAM_CUSTOM_ACCESS_RX_STAT, *P_PARAM_CUSTOM_ACCESS_RX_STAT; + +/* Ext DevInfo Tag */ +typedef enum _EXT_ENUM_DEVINFO_TAG_HANDLE_T { + DEV_INFO_ACTIVE = 0, + DEV_INFO_BSSID, + DEV_INFO_MAX_NUM +} EXT_ENUM_TAG_DEVINFO_HANDLE_T; + +/* STA record TLV tag */ +typedef enum _EXT_ENUM_STAREC_TAG_HANDLE_T { + STA_REC_BASIC = 0, + STA_REC_RA, + STA_REC_RA_COMMON_INFO, + STA_REC_RA_UPDATE, + STA_REC_BF, + STA_REC_MAUNAL_ASSOC, + STA_REC_BA = 6, + STA_REC_MAX_NUM +} EXT_ENUM_TAG_STAREC_HANDLE_T; + +#if CFG_SUPPORT_TX_BF +typedef enum _BF_ACTION_CATEGORY { + BF_SOUNDING_OFF = 0, + BF_SOUNDING_ON, + BF_HW_CTRL, + BF_DATA_PACKET_APPLY, + BF_PFMU_MEM_ALLOCATE, + BF_PFMU_MEM_RELEASE, + BF_PFMU_TAG_READ, + BF_PFMU_TAG_WRITE, + BF_PROFILE_READ, + BF_PROFILE_WRITE, + BF_PN_READ, + BF_PN_WRITE, + BF_PFMU_MEM_ALLOC_MAP_READ +} BF_ACTION_CATEGORY; + +enum { + DEVINFO_ACTIVE = 0, + DEVINFO_MAX_NUM = 1, +}; + +enum { + DEVINFO_ACTIVE_FEATURE = (1 << DEVINFO_ACTIVE), + DEVINFO_MAX_NUM_FEATURE = (1 << DEVINFO_MAX_NUM) +}; + +enum { + BSS_INFO_OWN_MAC = 0, + BSS_INFO_BASIC = 1, + BSS_INFO_RF_CH = 2, + BSS_INFO_PM = 3, + BSS_INFO_UAPSD = 4, + BSS_INFO_ROAM_DETECTION = 5, + BSS_INFO_LQ_RM = 6, + BSS_INFO_EXT_BSS = 7, + BSS_INFO_BROADCAST_INFO = 8, + BSS_INFO_SYNC_MODE = 9, + BSS_INFO_MAX_NUM +}; + +typedef union _PFMU_PROFILE_TAG1 { + struct { + UINT_32 ucProfileID:7; /* [6:0] : 0 ~ 63 */ + UINT_32 ucTxBf:1; /* [7] : 0: iBF, 1: eBF */ + UINT_32 ucDBW:2; /* [9:8] : 0/1/2/3: DW20/40/80/160NC */ + UINT_32 ucSU_MU:1; /* [10] : 0:SU, 1: MU */ + UINT_32 ucInvalidProf:1; /* [11] : 0:default, 1: This profile number is invalid by SW */ + UINT_32 ucRMSD:3; /* [14:12] : RMSD value from CE */ + UINT_32 ucMemAddr1ColIdx:3; /* [17 : 15] : column index : 0 ~ 5 */ + UINT_32 ucMemAddr1RowIdx:6; /* [23 : 18] : row index : 0 ~ 63 */ + UINT_32 ucMemAddr2ColIdx:3; /* [26 : 24] : column index : 0 ~ 5 */ + UINT_32 ucMemAddr2RowIdx:5; /* [31 : 27] : row index : 0 ~ 63 */ + UINT_32 ucMemAddr2RowIdxMsb:1; /* [32] : MSB of row index */ + UINT_32 ucMemAddr3ColIdx:3; /* [35 : 33] : column index : 0 ~ 5 */ + UINT_32 ucMemAddr3RowIdx:6; /* [41 : 36] : row index : 0 ~ 63 */ + UINT_32 ucMemAddr4ColIdx:3; /* [44 : 42] : column index : 0 ~ 5 */ + UINT_32 ucMemAddr4RowIdx:6; /* [50 : 45] : row index : 0 ~ 63 */ + UINT_32 ucReserved:1; /* [51] : Reserved */ + UINT_32 ucNrow:2; /* [53 : 52] : Nrow */ + UINT_32 ucNcol:2; /* [55 : 54] : Ncol */ + UINT_32 ucNgroup:2; /* [57 : 56] : Ngroup */ + UINT_32 ucLM:2; /* [59 : 58] : 0/1/2 */ + UINT_32 ucCodeBook:2; /* [61:60] : Code book */ + UINT_32 ucHtcExist:1; /* [62] : HtcExist */ + UINT_32 ucReserved1:1; /* [63] : Reserved */ + UINT_32 ucSNR_STS0:8; /* [71:64] : SNR_STS0 */ + UINT_32 ucSNR_STS1:8; /* [79:72] : SNR_STS1 */ + UINT_32 ucSNR_STS2:8; /* [87:80] : SNR_STS2 */ + UINT_32 ucSNR_STS3:8; /* [95:88] : SNR_STS3 */ + UINT_32 ucIBfLnaIdx:8; /* [103:96] : iBF LNA index */ + } rField; + UINT_32 au4RawData[4]; +} PFMU_PROFILE_TAG1, *P_PFMU_PROFILE_TAG1; + +typedef union _PFMU_PROFILE_TAG2 { + struct { + UINT_32 u2SmartAnt:12; /* [11:0] : Smart Ant config */ + UINT_32 ucReserved0:3; /* [14:12] : Reserved */ + UINT_32 ucSEIdx:5; /* [19:15] : SE index */ + UINT_32 ucRMSDThd:3; /* [22:20] : RMSD Threshold */ + UINT_32 ucReserved1:1; /* [23] : Reserved */ + UINT_32 ucMCSThL1SS:4; /* [27:24] : MCS TH long 1SS */ + UINT_32 ucMCSThS1SS:4; /* [31:28] : MCS TH short 1SS */ + UINT_32 ucMCSThL2SS:4; /* [35:32] : MCS TH long 2SS */ + UINT_32 ucMCSThS2SS:4; /* [39:36] : MCS TH short 2SS */ + UINT_32 ucMCSThL3SS:4; /* [43:40] : MCS TH long 3SS */ + UINT_32 ucMCSThS3SS:4; /* [47:44] : MCS TH short 3SS */ + UINT_32 uciBfTimeOut:8; /* [55:48] : iBF timeout limit */ + UINT_32 ucReserved2:8; /* [63:56] : Reserved */ + UINT_32 ucReserved3:8; /* [71:64] : Reserved */ + UINT_32 ucReserved4:8; /* [79:72] : Reserved */ + UINT_32 uciBfDBW:2; /* [81:80] : iBF desired DBW 0/1/2/3 : BW20/40/80/160NC */ + UINT_32 uciBfNcol:2; /* [83:82] : iBF desired Ncol = 1 ~ 3 */ + UINT_32 uciBfNrow:2; /* [85:84] : iBF desired Nrow = 1 ~ 4 */ + UINT_32 u2Reserved5:10; /* [95:86] : Reserved */ + } rField; + UINT_32 au4RawData[3]; +} PFMU_PROFILE_TAG2, *P_PFMU_PROFILE_TAG2; + +typedef union _PFMU_DATA { + struct { + UINT_32 u2Phi11:9; + UINT_32 ucPsi21:7; + UINT_32 u2Phi21:9; + UINT_32 ucPsi31:7; + UINT_32 u2Phi31:9; + UINT_32 ucPsi41:7; + UINT_32 u2Phi22:9; + UINT_32 ucPsi32:7; + UINT_32 u2Phi32:9; + UINT_32 ucPsi42:7; + UINT_32 u2Phi33:9; + UINT_32 ucPsi43:7; + UINT_32 u2dSNR00:4; + UINT_32 u2dSNR01:4; + UINT_32 u2dSNR02:4; + UINT_32 u2dSNR03:4; + UINT_32 u2Reserved:16; + } rField; + UINT_32 au4RawData[5]; +} PFMU_DATA, *P_PFMU_DATA; + +typedef struct _PROFILE_TAG_READ_T { + UINT_8 ucTxBfCategory; + UINT_8 ucProfileIdx; + BOOLEAN fgBfer; + UINT_8 ucRsv; +} PROFILE_TAG_READ_T, *P_PROFILE_TAG_READ_T; + +typedef struct _PROFILE_TAG_WRITE_T { + UINT_8 ucTxBfCategory; + UINT_8 ucPfmuId; + UINT_8 ucBuffer[28]; +} PROFILE_TAG_WRITE_T, *P_PROFILE_TAG_WRITE_T; + +typedef struct _PROFILE_DATA_READ_T { + UINT_8 ucTxBfCategory; + UINT_8 ucPfmuIdx; + BOOLEAN fgBFer; + UINT_8 ucReserved[3]; + UINT_8 ucSubCarrIdxLsb; + UINT_8 ucSubCarrIdxMsb; +} PROFILE_DATA_READ_T, *P_PROFILE_DATA_READ_T; + +typedef struct _PROFILE_DATA_WRITE_T { + UINT_8 ucTxBfCategory; + UINT_8 ucPfmuIdx; + UINT_8 u2SubCarrIdxLsb; + UINT_8 u2SubCarrIdxMsb; + PFMU_DATA rTxBfPfmuData; +} PROFILE_DATA_WRITE_T, *P_PROFILE_DATA_WRITE_T; + +typedef struct _PROFILE_PN_READ_T { + UINT_8 ucTxBfCategory; + UINT_8 ucPfmuIdx; + UINT_8 ucReserved[2]; +} PROFILE_PN_READ_T, *P_PROFILE_PN_READ_T; + +typedef struct _PROFILE_PN_WRITE_T { + UINT_8 ucTxBfCategory; + UINT_8 ucPfmuIdx; + UINT_16 u2bw; + UINT_8 ucBuf[32]; +} PROFILE_PN_WRITE_T, *P_PROFILE_PN_WRITE_T; + +typedef enum _BF_SOUNDING_MODE { + SU_SOUNDING = 0, + MU_SOUNDING, + SU_PERIODIC_SOUNDING, + MU_PERIODIC_SOUNDING +} BF_SOUNDING_MODE; + +typedef struct _EXT_CMD_ETXBf_SND_PERIODIC_TRIGGER_CTRL_T { + UINT_8 ucCmdCategoryID; + UINT_8 ucSuMuSndMode; + UINT_8 ucWlanIdx; + UINT_32 u4SoundingInterval; /* By ms */ +} EXT_CMD_ETXBf_SND_PERIODIC_TRIGGER_CTRL_T, *P_EXT_CMD_ETXBf_SND_PERIODIC_TRIGGER_CTRL_T; + +typedef struct _EXT_CMD_ETXBf_MU_SND_PERIODIC_TRIGGER_CTRL_T { + UINT_8 ucCmdCategoryID; + UINT_8 ucSuMuSndMode; + UINT_8 ucWlanId[4]; + UINT_8 ucStaNum; + UINT_32 u4SoundingInterval; /* By ms */ +} EXT_CMD_ETXBf_MU_SND_PERIODIC_TRIGGER_CTRL_T, *P_EXT_CMD_ETXBf_MU_SND_PERIODIC_TRIGGER_CTRL_T; + +/* Device information (Tag0) */ +typedef struct _CMD_DEVINFO_ACTIVE_T { + UINT_16 u2Tag; /* Tag = 0x00 */ + UINT_16 u2Length; + UINT_8 ucActive; + UINT_8 ucBandNum; + UINT_8 aucOwnMacAddr[6]; + UINT_8 aucReserve[4]; +} CMD_DEVINFO_ACTIVE_T, *P_CMD_DEVINFO_ACTIVE_T; + +typedef struct _BSSINFO_BASIC_T { + /* Basic BSS information (Tag1) */ + UINT_16 u2Tag; /* Tag = 0x01 */ + UINT_16 u2Length; + UINT_32 u4NetworkType; + UINT_8 ucActive; + UINT_8 ucReserve0; + UINT_16 u2BcnInterval; + UINT_8 aucBSSID[6]; + UINT_8 ucWmmIdx; + UINT_8 ucDtimPeriod; + UINT_8 ucBcMcWlanidx; /* indicate which wlan-idx used for MC/BC transmission. */ + UINT_8 ucCipherSuit; + UINT_8 acuReserve[6]; +} CMD_BSSINFO_BASIC_T, *P_CMD_BSSINFO_BASIC_T; + +typedef struct _TXBF_PFMU_STA_INFO { + UINT_16 u2PfmuId; /* 0xFFFF means no access right for PFMU */ + UINT_8 fgSU_MU; /* 0 : SU, 1 : MU */ + UINT_8 fgETxBfCap; /* 0 : ITxBf, 1 : ETxBf */ + UINT_8 ucSoundingPhy; /* 0: legacy, 1: OFDM, 2: HT, 4: VHT */ + UINT_8 ucNdpaRate; + UINT_8 ucNdpRate; + UINT_8 ucReptPollRate; + UINT_8 ucTxMode; /* 0: legacy, 1: OFDM, 2: HT, 4: VHT */ + UINT_8 ucNc; + UINT_8 ucNr; + UINT_8 ucCBW; /* 0 : 20M, 1 : 40M, 2 : 80M, 3 : 80 + 80M */ + UINT_8 ucTotMemRequire; + UINT_8 ucMemRequire20M; + UINT_8 ucMemRow0; + UINT_8 ucMemCol0; + UINT_8 ucMemRow1; + UINT_8 ucMemCol1; + UINT_8 ucMemRow2; + UINT_8 ucMemCol2; + UINT_8 ucMemRow3; + UINT_8 ucMemCol3; + UINT_16 u2SmartAnt; + UINT_8 ucSEIdx; + UINT_8 uciBfTimeOut; + UINT_8 uciBfDBW; + UINT_8 uciBfNcol; + UINT_8 uciBfNrow; + UINT_8 aucReserved[3]; +} TXBF_PFMU_STA_INFO, *P_TXBF_PFMU_STA_INFO; + +typedef struct _STA_REC_UPD_ENTRY_T { + TXBF_PFMU_STA_INFO rTxBfPfmuStaInfo; + UINT_8 aucAddr[PARAM_MAC_ADDR_LEN]; + UINT_8 ucAid; + UINT_8 ucRsv; +} STA_REC_UPD_ENTRY_T, *P_STA_REC_UPD_ENTRY_T; + +typedef struct _STAREC_COMMON_T { + /* Basic STA record (Group0) */ + UINT_16 u2Tag; /* Tag = 0x00 */ + UINT_16 u2Length; + UINT_32 u4ConnectionType; + UINT_8 ucConnectionState; + UINT_8 ucIsQBSS; + UINT_16 u2AID; + UINT_8 aucPeerMacAddr[6]; + UINT_16 u2Reserve1; +} CMD_STAREC_COMMON_T, *P_CMD_STAREC_COMMON_T; + +typedef struct _CMD_STAREC_BF { + UINT_16 u2Tag; /* Tag = 0x02 */ + UINT_16 u2Length; + TXBF_PFMU_STA_INFO rTxBfPfmuInfo; + UINT_8 ucReserved[3]; +} CMD_STAREC_BF, *P_CMD_STAREC_BF; + +/* QA tool: maunal assoc */ +typedef struct _CMD_MANUAL_ASSOC_STRUCT_T { + /* + * UINT_8 ucBssIndex; + * UINT_8 ucWlanIdx; + * UINT_16 u2TotalElementNum; + * UINT_32 u4Reserve; + */ + /* extension */ + UINT_16 u2Tag; /* Tag = 0x05 */ + UINT_16 u2Length; + UINT_8 aucMac[MAC_ADDR_LEN]; + UINT_8 ucType; + UINT_8 ucWtbl; + UINT_8 ucOwnmac; + UINT_8 ucMode; + UINT_8 ucBw; + UINT_8 ucNss; + UINT_8 ucPfmuId; + UINT_8 ucMarate; + UINT_8 ucSpeIdx; + UINT_8 ucaid; +} CMD_MANUAL_ASSOC_STRUCT_T, *P_CMD_MANUAL_ASSOC_STRUCT_T; + +typedef struct _TX_BF_SOUNDING_START_T { + union { + EXT_CMD_ETXBf_SND_PERIODIC_TRIGGER_CTRL_T rExtCmdExtBfSndPeriodicTriggerCtrl; + EXT_CMD_ETXBf_MU_SND_PERIODIC_TRIGGER_CTRL_T rExtCmdExtBfMuSndPeriodicTriggerCtrl; + } rTxBfSounding; +} TX_BF_SOUNDING_START_T, *P_TX_BF_SOUNDING_START_T; + +typedef struct _TX_BF_SOUNDING_STOP_T { + UINT_8 ucTxBfCategory; + UINT_8 ucSndgStop; + UINT_8 ucReserved[2]; +} TX_BF_SOUNDING_STOP_T, *P_TX_BF_SOUNDING_STOP_T; + +typedef struct _TX_BF_TX_APPLY_T { + UINT_8 ucTxBfCategory; + UINT_8 ucWlanId; + UINT_8 fgETxBf; + UINT_8 fgITxBf; + UINT_8 fgMuTxBf; + UINT_8 ucReserved[3]; +} TX_BF_TX_APPLY_T, *P_TX_BF_TX_APPLY_T; + +typedef struct _TX_BF_PFMU_MEM_ALLOC_T { + UINT_8 ucTxBfCategory; + UINT_8 ucSuMuMode; + UINT_8 ucWlanIdx; + UINT_8 ucReserved; +} TX_BF_PFMU_MEM_ALLOC_T, *P_TX_BF_PFMU_MEM_ALLOC_T; + +typedef struct _TX_BF_PFMU_MEM_RLS_T { + UINT_8 ucTxBfCategory; + UINT_8 ucWlanId; + UINT_8 ucReserved[2]; +} TX_BF_PFMU_MEM_RLS_T, *P_TX_BF_PFMU_MEM_RLS_T; + +typedef union _PARAM_CUSTOM_TXBF_ACTION_STRUCT_T { + PROFILE_TAG_READ_T rProfileTagRead; + PROFILE_TAG_WRITE_T rProfileTagWrite; + PROFILE_DATA_READ_T rProfileDataRead; + PROFILE_DATA_WRITE_T rProfileDataWrite; + PROFILE_PN_READ_T rProfilePnRead; + PROFILE_PN_WRITE_T rProfilePnWrite; + TX_BF_SOUNDING_START_T rTxBfSoundingStart; + TX_BF_SOUNDING_STOP_T rTxBfSoundingStop; + TX_BF_TX_APPLY_T rTxBfTxApply; + TX_BF_PFMU_MEM_ALLOC_T rTxBfPfmuMemAlloc; + TX_BF_PFMU_MEM_RLS_T rTxBfPfmuMemRls; +} PARAM_CUSTOM_TXBF_ACTION_STRUCT_T, *P_PARAM_CUSTOM_TXBF_ACTION_STRUCT_T; + +typedef struct _PARAM_CUSTOM_STA_REC_UPD_STRUCT_T { + UINT_8 ucBssIndex; + UINT_8 ucWlanIdx; + UINT_16 u2TotalElementNum; + UINT_8 ucAppendCmdTLV; + UINT_8 ucMuarIdx; + UINT_8 aucReserve[2]; + UINT_32 *prStaRec; + CMD_STAREC_BF rCmdStaRecBf; +} PARAM_CUSTOM_STA_REC_UPD_STRUCT_T, *P_PARAM_CUSTOM_STA_REC_UPD_STRUCT_T; + +typedef struct _BSSINFO_ARGUMENT_T { + UCHAR OwnMacIdx; + UINT_8 ucBssIndex; + UINT_8 Bssid[PARAM_MAC_ADDR_LEN]; + UINT_8 ucBcMcWlanIdx; + UINT_8 ucPeerWlanIdx; + UINT_32 NetworkType; + UINT_32 u4ConnectionType; + UINT_8 CipherSuit; + UINT_8 Active; + UINT_8 WmmIdx; + UINT_32 u4BssInfoFeature; + UINT_8 aucBuffer[0]; +} BSSINFO_ARGUMENT_T, *P_BSSINFO_ARGUMENT_T; + +typedef struct _PARAM_CUSTOM_PFMU_TAG_READ_STRUCT_T { + PFMU_PROFILE_TAG1 ru4TxBfPFMUTag1; + PFMU_PROFILE_TAG2 ru4TxBfPFMUTag2; +} PARAM_CUSTOM_PFMU_TAG_READ_STRUCT_T, *P_PARAM_CUSTOM_PFMU_TAG_READ_STRUCT_T; + +#if CFG_SUPPORT_MU_MIMO +typedef struct _PARAM_CUSTOM_SHOW_GROUP_TBL_ENTRY_STRUCT_T { + UINT_32 u4EventId; + UINT_8 index; + UINT_8 numUser:2; + UINT_8 BW:2; + UINT_8 NS0:2; + UINT_8 NS1:2; + /* UINT_8 NS2:1; */ + /* UINT_8 NS3:1; */ + UINT_8 PFIDUser0; + UINT_8 PFIDUser1; + /* UINT_8 PFIDUser2; */ + /* UINT_8 PFIDUser3; */ + BOOLEAN fgIsShortGI; + BOOLEAN fgIsUsed; + BOOLEAN fgIsDisable; + UINT_8 initMcsUser0:4; + UINT_8 initMcsUser1:4; + /* UINT_8 initMcsUser2:4; */ + /* UINT_8 initMcsUser3:4; */ + UINT_8 dMcsUser0:4; + UINT_8 dMcsUser1:4; + /* UINT_8 dMcsUser2:4; */ + /* UINT_8 dMcsUser3:4; */ +} PARAM_CUSTOM_SHOW_GROUP_TBL_ENTRY_STRUCT_T, *P_PARAM_CUSTOM_SHOW_GROUP_TBL_ENTRY_STRUCT_T; + +typedef struct _PARAM_CUSTOM_GET_QD_STRUCT_T { + UINT_32 u4EventId; + UINT_32 au4RawData[14]; +} PARAM_CUSTOM_GET_QD_STRUCT_T, *P_PARAM_CUSTOM_GET_QD_STRUCT_T; + +typedef struct _MU_STRUCT_LQ_REPORT { + int lq_report[NUM_OF_USER][NUM_OF_MODUL]; +} MU_STRUCT_LQ_REPORT, *P_MU_STRUCT_LQ_REPORT; + +typedef struct _PARAM_CUSTOM_GET_MU_CALC_LQ_STRUCT_T { + UINT_32 u4EventId; + MU_STRUCT_LQ_REPORT rEntry; +} PARAM_CUSTOM_GET_MU_CALC_LQ_STRUCT_T, *P_PARAM_CUSTOM_GET_MU_CALC_LQ_STRUCT_T; + +typedef struct _MU_GET_CALC_INIT_MCS_T { + UINT_8 ucgroupIdx; + UINT_8 ucRsv[3]; +} MU_GET_CALC_INIT_MCS_T, *P_MU_GET_CALC_INIT_MCS_T; + +typedef struct _MU_SET_INIT_MCS_T { + UINT_8 ucNumOfUser; /* zero-base : 0~3: means 1~2 users */ + UINT_8 ucBandwidth; /* zero-base : 0:20 hz 1:40 hz 2: 80 hz 3: 160 */ + UINT_8 ucNssOfUser0; /* zero-base : 0~1 means uesr0 use 1~2 ss , if no use keep 0 */ + UINT_8 ucNssOfUser1; /* zero-base : 0~1 means uesr0 use 1~2 ss , if no use keep 0 */ + UINT_8 ucPfMuIdOfUser0; /* zero-base : for now, uesr0 use pf mu id 0 */ + UINT_8 ucPfMuIdOfUser1; /* zero-base : for now, uesr1 use pf mu id 1 */ + UINT_8 ucNumOfTxer; /* 0~3: mean use 1~4 anntain, for now, should fix 3 */ + UINT_8 ucSpeIndex; /*add new field to fill¡§special extension index¡¨which replace reserve */ + UINT_32 u4GroupIndex; /* 0~ :the index of group table entry for calculation */ +} MU_SET_INIT_MCS_T, *P_MU_SET_INIT_MCS_T; + +typedef struct _MU_SET_CALC_LQ_T { + UINT_8 ucNumOfUser; /* zero-base : 0~3: means 1~2 users */ + UINT_8 ucBandwidth; /* zero-base : 0:20 hz 1:40 hz 2: 80 hz 3: 160 */ + UINT_8 ucNssOfUser0; /* zero-base : 0~1 means uesr0 use 1~2 ss , if no use keep 0 */ + UINT_8 ucNssOfUser1; /* zero-base : 0~1 means uesr0 use 1~2 ss , if no use keep 0 */ + UINT_8 ucPfMuIdOfUser0; /* zero-base : for now, uesr0 use pf mu id 0 */ + UINT_8 ucPfMuIdOfUser1; /* zero-base : for now, uesr1 use pf mu id 1 */ + UINT_8 ucNumOfTxer; /* 0~3: mean use 1~4 anntain, for now, should fix 3 */ + UINT_8 ucSpeIndex; /*add new field to fill¡§special extension index¡¨which replace reserve */ + UINT_32 u4GroupIndex; /* 0~ :the index of group table entry for calculation */ +} MU_SET_CALC_LQ_T, *P_MU_SET_CALC_LQ_T; + +typedef struct _MU_GET_LQ_T { + UINT_8 ucType; + UINT_8 ucRsv[3]; +} MU_GET_LQ_T, *P_MU_GET_LQ_T; + +typedef struct _MU_SET_SNR_OFFSET_T { + UINT_8 ucVal; + UINT_8 ucRsv[3]; +} MU_SET_SNR_OFFSET_T, *P_MU_SET_SNR_OFFSET_T; + +typedef struct _MU_SET_ZERO_NSS_T { + UINT_8 ucVal; + UINT_8 ucRsv[3]; +} MU_SET_ZERO_NSS_T, *P_MU_SET_ZERO_NSS_T; + +typedef struct _MU_SPEED_UP_LQ_T { + UINT_32 u4Val; +} MU_SPEED_UP_LQ_T, *P_MU_SPEED_UP_LQ_T; + +typedef struct _MU_SET_MU_TABLE_T { + /* UINT_16 u2Type; */ + /* UINT_32 u4Length; */ + UINT_8 aucMetricTable[NUM_MUT_NR_NUM * NUM_MUT_FEC * NUM_MUT_MCS * NUM_MUT_INDEX]; +} MU_SET_MU_TABLE_T, *P_MU_SET_MU_TABLE_T; + +typedef struct _MU_SET_GROUP_T { + UINT_32 u4GroupIndex; /* Group Table Idx */ + UINT_32 u4NumOfUser; + UINT_32 u4User0Ldpc; + UINT_32 u4User1Ldpc; + UINT_32 u4ShortGI; + UINT_32 u4Bw; + UINT_32 u4User0Nss; + UINT_32 u4User1Nss; + UINT_32 u4GroupId; + UINT_32 u4User0UP; + UINT_32 u4User1UP; + UINT_32 u4User0MuPfId; + UINT_32 u4User1MuPfId; + UINT_32 u4User0InitMCS; + UINT_32 u4User1InitMCS; + UINT_8 aucUser0MacAddr[PARAM_MAC_ADDR_LEN]; + UINT_8 aucUser1MacAddr[PARAM_MAC_ADDR_LEN]; +} MU_SET_GROUP_T, *P_MU_SET_GROUP_T; + +typedef struct _MU_GET_QD_T { + UINT_8 ucSubcarrierIndex; + /* UINT_32 u4Length; */ + /* UINT_8 *prQd; */ +} MU_GET_QD_T, *P_MU_GET_QD_T; + +typedef struct _MU_SET_ENABLE_T { + UINT_8 ucVal; + UINT_8 ucRsv[3]; +} MU_SET_ENABLE_T, *P_MU_SET_ENABLE_T; + +typedef struct _MU_SET_GID_UP_T { + UINT_32 au4Gid[2]; + UINT_32 au4Up[4]; +} MU_SET_GID_UP_T, *P_MU_SET_GID_UP_T; + +typedef struct _MU_TRIGGER_MU_TX_T { + UINT_8 fgIsRandomPattern; /* is random pattern or not */ + UINT_32 u4MsduPayloadLength0; /* payload length of the MSDU for user 0 */ + UINT_32 u4MsduPayloadLength1; /* payload length of the MSDU for user 1 */ + UINT_32 u4MuPacketCount; /* MU TX count */ + UINT_32 u4NumOfSTAs; /* number of user in the MU TX */ + UINT_8 aucMacAddrs[2][6]; /* MAC address of users*/ +} MU_TRIGGER_MU_TX_T, *P_MU_TRIGGER_MU_TX_T; + +typedef struct _PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T { + UINT_8 ucMuMimoCategory; + UINT_8 aucRsv[3]; + union { + MU_GET_CALC_INIT_MCS_T rMuGetCalcInitMcs; + MU_SET_INIT_MCS_T rMuSetInitMcs; + MU_SET_CALC_LQ_T rMuSetCalcLq; + MU_GET_LQ_T rMuGetLq; + MU_SET_SNR_OFFSET_T rMuSetSnrOffset; + MU_SET_ZERO_NSS_T rMuSetZeroNss; + MU_SPEED_UP_LQ_T rMuSpeedUpLq; + MU_SET_MU_TABLE_T rMuSetMuTable; + MU_SET_GROUP_T rMuSetGroup; + MU_GET_QD_T rMuGetQd; + MU_SET_ENABLE_T rMuSetEnable; + MU_SET_GID_UP_T rMuSetGidUp; + MU_TRIGGER_MU_TX_T rMuTriggerMuTx; + } unMuMimoParam; +} PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T, *P_PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T; +#endif /* CFG_SUPPORT_MU_MIMO */ +#endif /* CFG_SUPPORT_TX_BF */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +typedef struct _PARAM_CUSTOM_MEM_DUMP_STRUCT_T { + UINT_32 u4Address; + UINT_32 u4Length; + UINT_32 u4RemainLength; +#if CFG_SUPPORT_QA_TOOL + UINT_32 u4IcapContent; +#endif /* CFG_SUPPORT_QA_TOOL */ + UINT_8 ucFragNum; +} PARAM_CUSTOM_MEM_DUMP_STRUCT_T, *P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T; + +typedef struct _PARAM_CUSTOM_SW_CTRL_STRUCT_T { + UINT_32 u4Id; + UINT_32 u4Data; +} PARAM_CUSTOM_SW_CTRL_STRUCT_T, *P_PARAM_CUSTOM_SW_CTRL_STRUCT_T; + +typedef struct _PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T { + UINT_16 u2Id; + UINT_8 ucType; + UINT_8 ucRespType; + UINT_16 u2MsgSize; + UINT_8 aucReserved0[2]; + UINT_8 aucCmd[CHIP_CONFIG_RESP_SIZE]; +} PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T, *P_PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T; + +typedef struct _PARAM_CUSTOM_KEY_CFG_STRUCT_T { + UINT_8 aucKey[WLAN_CFG_KEY_LEN_MAX]; + UINT_8 aucValue[WLAN_CFG_VALUE_LEN_MAX]; +} PARAM_CUSTOM_KEY_CFG_STRUCT_T, *P_PARAM_CUSTOM_KEY_CFG_STRUCT_T; + +typedef struct _PARAM_CUSTOM_EEPROM_RW_STRUCT_T { + UINT_8 ucEepromMethod; /* For read only read: 1, query size: 0 */ + UINT_8 ucEepromIndex; + UINT_8 reserved; + UINT_16 u2EepromData; +} PARAM_CUSTOM_EEPROM_RW_STRUCT_T, *P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T, + PARAM_CUSTOM_NVRAM_RW_STRUCT_T, *P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T; + +typedef struct _PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T { + UINT_8 bmfgApsdEnAc; /* b0~3: trigger-en AC0~3. b4~7: delivery-en AC0~3 */ + UINT_8 ucIsEnterPsAtOnce; /* enter PS immediately without 5 second guard after connected */ + UINT_8 ucIsDisableUcTrigger; /* not to trigger UC on beacon TIM is matched (under U-APSD) */ + UINT_8 reserved; +} PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T, *P_PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T; + +typedef struct _PARAM_CUSTOM_NOA_PARAM_STRUCT_T { + UINT_32 u4NoaDurationMs; + UINT_32 u4NoaIntervalMs; + UINT_32 u4NoaCount; + UINT_8 ucBssIdx; +} PARAM_CUSTOM_NOA_PARAM_STRUCT_T, *P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T; + +typedef struct _PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T { + UINT_32 u4CTwindowMs; + UINT_8 ucBssIdx; +} PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T, *P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T; + +typedef struct _PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T { + UINT_8 ucBssIdx; + UINT_8 fgEnAPSD; + UINT_8 fgEnAPSD_AcBe; + UINT_8 fgEnAPSD_AcBk; + UINT_8 fgEnAPSD_AcVo; + UINT_8 fgEnAPSD_AcVi; + UINT_8 ucMaxSpLen; + UINT_8 aucResv[2]; +} PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T, *P_PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T; + +typedef struct _PARAM_CUSTOM_P2P_SET_STRUCT_T { + UINT_32 u4Enable; + UINT_32 u4Mode; +} PARAM_CUSTOM_P2P_SET_STRUCT_T, *P_PARAM_CUSTOM_P2P_SET_STRUCT_T; + +typedef enum _ENUM_CFG_SRC_TYPE_T { + CFG_SRC_TYPE_EEPROM, + CFG_SRC_TYPE_NVRAM, + CFG_SRC_TYPE_UNKNOWN, + CFG_SRC_TYPE_NUM +} ENUM_CFG_SRC_TYPE_T, *P_ENUM_CFG_SRC_TYPE_T; + +typedef enum _ENUM_EEPROM_TYPE_T { + EEPROM_TYPE_NO, + EEPROM_TYPE_PRESENT, + EEPROM_TYPE_NUM +} ENUM_EEPROM_TYPE_T, *P_ENUM_EEPROM_TYPE_T; + +typedef struct _PARAM_QOS_TSINFO { + UINT_8 ucTrafficType; /* Traffic Type: 1 for isochronous 0 for asynchronous */ + UINT_8 ucTid; /* TSID: must be between 8 ~ 15 */ + UINT_8 ucDirection; /* direction */ + UINT_8 ucAccessPolicy; /* access policy */ + UINT_8 ucAggregation; /* aggregation */ + UINT_8 ucApsd; /* APSD */ + UINT_8 ucuserPriority; /* user priority */ + UINT_8 ucTsInfoAckPolicy; /* TSINFO ACK policy */ + UINT_8 ucSchedule; /* Schedule */ +} PARAM_QOS_TSINFO, *P_PARAM_QOS_TSINFO; + +typedef struct _PARAM_QOS_TSPEC { + PARAM_QOS_TSINFO rTsInfo; /* TS info field */ + UINT_16 u2NominalMSDUSize; /* nominal MSDU size */ + UINT_16 u2MaxMSDUsize; /* maximum MSDU size */ + UINT_32 u4MinSvcIntv; /* minimum service interval */ + UINT_32 u4MaxSvcIntv; /* maximum service interval */ + UINT_32 u4InactIntv; /* inactivity interval */ + UINT_32 u4SpsIntv; /* suspension interval */ + UINT_32 u4SvcStartTime; /* service start time */ + UINT_32 u4MinDataRate; /* minimum Data rate */ + UINT_32 u4MeanDataRate; /* mean data rate */ + UINT_32 u4PeakDataRate; /* peak data rate */ + UINT_32 u4MaxBurstSize; /* maximum burst size */ + UINT_32 u4DelayBound; /* delay bound */ + UINT_32 u4MinPHYRate; /* minimum PHY rate */ + UINT_16 u2Sba; /* surplus bandwidth allowance */ + UINT_16 u2MediumTime; /* medium time */ + UINT_8 ucDialogToken; +} 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; + LARGE_INTEGER rMdrdyCnt; + LARGE_INTEGER rChnlIdleCnt; +} PARAM_802_11_STATISTICS_STRUCT_T, *P_PARAM_802_11_STATISTICS_STRUCT_T; + +/* Linux Network Device Statistics Struct */ +typedef struct _PARAM_LINUX_NETDEV_STATISTICS_T { + UINT_32 u4RxPackets; + UINT_32 u4TxPackets; + UINT_32 u4RxBytes; + UINT_32 u4TxBytes; + UINT_32 u4RxErrors; + UINT_32 u4TxErrors; + UINT_32 u4Multicast; +} PARAM_LINUX_NETDEV_STATISTICS_T, *P_PARAM_LINUX_NETDEV_STATISTICS_T; + +typedef struct _PARAM_MTK_WIFI_TEST_STRUCT_T { + UINT_32 u4FuncIndex; + UINT_32 u4FuncData; + UINT_32 u4FuncData2; /*FW don't support*/ +} PARAM_MTK_WIFI_TEST_STRUCT_T, *P_PARAM_MTK_WIFI_TEST_STRUCT_T; + +/* 802.11 Media stream constraints */ +typedef enum _ENUM_MEDIA_STREAM_MODE { + ENUM_MEDIA_STREAM_OFF, + ENUM_MEDIA_STREAM_ON +} ENUM_MEDIA_STREAM_MODE, *P_ENUM_MEDIA_STREAM_MODE; + +/* for NDIS 5.1 Media Streaming Change */ +typedef struct _PARAM_MEDIA_STREAMING_INDICATION { + PARAM_STATUS_INDICATION_T rStatus; + ENUM_MEDIA_STREAM_MODE eMediaStreamMode; +} PARAM_MEDIA_STREAMING_INDICATION, *P_PARAM_MEDIA_STREAMING_INDICATION; + +#define PARAM_PROTOCOL_ID_DEFAULT 0x00 +#define PARAM_PROTOCOL_ID_TCP_IP 0x02 +#define PARAM_PROTOCOL_ID_IPX 0x06 +#define PARAM_PROTOCOL_ID_NBF 0x07 +#define PARAM_PROTOCOL_ID_MAX 0x0F +#define PARAM_PROTOCOL_ID_MASK 0x0F + +/* for NDIS OID_GEN_NETWORK_LAYER_ADDRESSES */ +typedef struct _PARAM_NETWORK_ADDRESS_IP { + UINT_16 sin_port; + UINT_32 in_addr; + UINT_8 sin_zero[8]; +} PARAM_NETWORK_ADDRESS_IP, *P_PARAM_NETWORK_ADDRESS_IP; + +typedef struct _PARAM_NETWORK_ADDRESS { + UINT_16 u2AddressLength; /* length in bytes of Address[] in this */ + UINT_16 u2AddressType; /* type of this address (PARAM_PROTOCOL_ID_XXX above) */ + UINT_8 aucAddress[1]; /* actually AddressLength bytes long */ +} PARAM_NETWORK_ADDRESS, *P_PARAM_NETWORK_ADDRESS; + +/* The following is used with OID_GEN_NETWORK_LAYER_ADDRESSES to set network layer addresses on an interface */ + +typedef struct _PARAM_NETWORK_ADDRESS_LIST { + UINT_8 ucBssIdx; + UINT_32 u4AddressCount; /* number of addresses following */ + UINT_16 u2AddressType; /* type of this address (NDIS_PROTOCOL_ID_XXX above) */ + PARAM_NETWORK_ADDRESS arAddress[1]; /* actually AddressCount elements long */ +} PARAM_NETWORK_ADDRESS_LIST, *P_PARAM_NETWORK_ADDRESS_LIST; + +#if CFG_SLT_SUPPORT + +#define FIXED_BW_LG20 0x0000 +#define FIXED_BW_UL20 0x2000 +#define FIXED_BW_DL40 0x3000 + +#define FIXED_EXT_CHNL_U20 0x4000 /* For AGG register. */ +#define FIXED_EXT_CHNL_L20 0xC000 /* For AGG regsiter. */ + +typedef enum _ENUM_MTK_LP_TEST_MODE_T { + ENUM_MTK_LP_TEST_NORMAL, + ENUM_MTK_LP_TEST_GOLDEN_SAMPLE, + ENUM_MTK_LP_TEST_DUT, + ENUM_MTK_LP_TEST_MODE_NUM +} ENUM_MTK_LP_TEST_MODE_T, *P_ENUM_MTK_LP_TEST_MODE_T; + +typedef enum _ENUM_MTK_SLT_FUNC_IDX_T { + ENUM_MTK_SLT_FUNC_DO_NOTHING, + ENUM_MTK_SLT_FUNC_INITIAL, + ENUM_MTK_SLT_FUNC_RATE_SET, + ENUM_MTK_SLT_FUNC_LP_SET, + ENUM_MTK_SLT_FUNC_NUM +} ENUM_MTK_SLT_FUNC_IDX_T, *P_ENUM_MTK_SLT_FUNC_IDX_T; + +typedef struct _PARAM_MTK_SLT_LP_TEST_STRUCT_T { + ENUM_MTK_LP_TEST_MODE_T rLpTestMode; + UINT_32 u4BcnRcvNum; +} PARAM_MTK_SLT_LP_TEST_STRUCT_T, *P_PARAM_MTK_SLT_LP_TEST_STRUCT_T; + +typedef struct _PARAM_MTK_SLT_TR_TEST_STRUCT_T { + ENUM_PARAM_NETWORK_TYPE_T rNetworkType; /* Network Type OFDM5G or OFDM2.4G */ + UINT_32 u4FixedRate; /* Fixed Rate including BW */ +} PARAM_MTK_SLT_TR_TEST_STRUCT_T, *P_PARAM_MTK_SLT_TR_TEST_STRUCT_T; + +typedef struct _PARAM_MTK_SLT_INITIAL_STRUCT_T { + UINT_8 aucTargetMacAddr[PARAM_MAC_ADDR_LEN]; + UINT_16 u2SiteID; +} PARAM_MTK_SLT_INITIAL_STRUCT_T, *P_PARAM_MTK_SLT_INITIAL_STRUCT_T; + +typedef struct _PARAM_MTK_SLT_TEST_STRUCT_T { + ENUM_MTK_SLT_FUNC_IDX_T rSltFuncIdx; + UINT_32 u4Length; /* + * Length of structure, + * including myself + */ + UINT_32 u4FuncInfoLen; /* + * Include following content + * field and myself + */ + union { + PARAM_MTK_SLT_INITIAL_STRUCT_T rMtkInitTest; + PARAM_MTK_SLT_LP_TEST_STRUCT_T rMtkLpTest; + PARAM_MTK_SLT_TR_TEST_STRUCT_T rMtkTRTest; + } unFuncInfoContent; + +} PARAM_MTK_SLT_TEST_STRUCT_T, *P_PARAM_MTK_SLT_TEST_STRUCT_T; + +#endif + +/*--------------------------------------------------------------*/ +/*! \brief For Fixed Rate Configuration (Registry) */ +/*--------------------------------------------------------------*/ +typedef enum _ENUM_REGISTRY_FIXED_RATE_T { + FIXED_RATE_NONE, + FIXED_RATE_1M, + FIXED_RATE_2M, + FIXED_RATE_5_5M, + FIXED_RATE_11M, + FIXED_RATE_6M, + FIXED_RATE_9M, + FIXED_RATE_12M, + FIXED_RATE_18M, + FIXED_RATE_24M, + FIXED_RATE_36M, + FIXED_RATE_48M, + FIXED_RATE_54M, + FIXED_RATE_MCS0_20M_800NS, + FIXED_RATE_MCS1_20M_800NS, + FIXED_RATE_MCS2_20M_800NS, + FIXED_RATE_MCS3_20M_800NS, + FIXED_RATE_MCS4_20M_800NS, + FIXED_RATE_MCS5_20M_800NS, + FIXED_RATE_MCS6_20M_800NS, + FIXED_RATE_MCS7_20M_800NS, + FIXED_RATE_MCS0_20M_400NS, + FIXED_RATE_MCS1_20M_400NS, + FIXED_RATE_MCS2_20M_400NS, + FIXED_RATE_MCS3_20M_400NS, + FIXED_RATE_MCS4_20M_400NS, + FIXED_RATE_MCS5_20M_400NS, + FIXED_RATE_MCS6_20M_400NS, + FIXED_RATE_MCS7_20M_400NS, + FIXED_RATE_MCS0_40M_800NS, + FIXED_RATE_MCS1_40M_800NS, + FIXED_RATE_MCS2_40M_800NS, + FIXED_RATE_MCS3_40M_800NS, + FIXED_RATE_MCS4_40M_800NS, + FIXED_RATE_MCS5_40M_800NS, + FIXED_RATE_MCS6_40M_800NS, + FIXED_RATE_MCS7_40M_800NS, + FIXED_RATE_MCS32_800NS, + FIXED_RATE_MCS0_40M_400NS, + FIXED_RATE_MCS1_40M_400NS, + FIXED_RATE_MCS2_40M_400NS, + FIXED_RATE_MCS3_40M_400NS, + FIXED_RATE_MCS4_40M_400NS, + FIXED_RATE_MCS5_40M_400NS, + FIXED_RATE_MCS6_40M_400NS, + FIXED_RATE_MCS7_40M_400NS, + FIXED_RATE_MCS32_400NS, + FIXED_RATE_NUM +} ENUM_REGISTRY_FIXED_RATE_T, *P_ENUM_REGISTRY_FIXED_RATE_T; + +typedef enum _ENUM_BT_CMD_T { + BT_CMD_PROFILE = 0, + BT_CMD_UPDATE, + BT_CMD_NUM +} ENUM_BT_CMD_T; + +typedef enum _ENUM_BT_PROFILE_T { + BT_PROFILE_CUSTOM = 0, + BT_PROFILE_SCO, + BT_PROFILE_ACL, + BT_PROFILE_MIXED, + BT_PROFILE_NO_CONNECTION, + BT_PROFILE_NUM +} ENUM_BT_PROFILE_T; + +typedef struct _PTA_PROFILE_T { + ENUM_BT_PROFILE_T eBtProfile; + union { + UINT_8 aucBTPParams[BT_PROFILE_PARAM_LEN]; + /* + * 0: sco reserved slot time, + * 1: sco idle slot time, + * 2: acl throughput, + * 3: bt tx power, + * 4: bt rssi + * 5: VoIP interval + * 6: BIT(0) Use this field, BIT(1) 0 apply single/ 1 dual PTA setting. + */ + UINT_32 au4Btcr[4]; + } u; +} PTA_PROFILE_T, *P_PTA_PROFILE_T; + +typedef struct _PTA_IPC_T { + UINT_8 ucCmd; + UINT_8 ucLen; + union { + PTA_PROFILE_T rProfile; + UINT_8 aucBTPParams[BT_PROFILE_PARAM_LEN]; + } u; +} PARAM_PTA_IPC_T, *P_PARAM_PTA_IPC_T, PTA_IPC_T, *P_PTA_IPC_T; + +/*--------------------------------------------------------------*/ +/*! \brief CFG80211 Scan Request Container */ +/*--------------------------------------------------------------*/ +typedef struct _PARAM_SCAN_REQUEST_EXT_T { + PARAM_SSID_T rSsid; + UINT_32 u4IELength; + PUINT_8 pucIE; +} PARAM_SCAN_REQUEST_EXT_T, *P_PARAM_SCAN_REQUEST_EXT_T; +struct _PARAM_SCAN_RANDOM_MAC_ADDR_T { + UINT_8 aucRandomMac[MAC_ADDR_LEN]; + UINT_8 ucScnFuncMask; +}; +typedef struct _PARAM_SCAN_REQUEST_ADV_T { + UINT_32 u4SsidNum; + PARAM_SSID_T rSsid[CFG_SCAN_SSID_MAX_NUM]; + UINT_32 u4IELength; + PUINT_8 pucIE; + /* partial scan temp save request info */ + UINT_8 ucSetChannel; + struct _PARAM_SCAN_RANDOM_MAC_ADDR_T rScanRandomMacAddr; +} PARAM_SCAN_REQUEST_ADV_T, *P_PARAM_SCAN_REQUEST_ADV_T; + +/*--------------------------------------------------------------*/ +/*! \brief CFG80211 Scheduled Scan Request Container */ +/*--------------------------------------------------------------*/ +typedef struct _PARAM_SCHED_SCAN_REQUEST_T { +#if CFG_SUPPORT_SCHED_SCN_SSID_SETS + UINT_32 u4SsidNum; /* passed in the probe_reqs */ + PARAM_SSID_T arSsid[CFG_SCAN_HIDDEN_SSID_MAX_NUM]; + UINT_32 u4MatchSsidNum; /* matched for a scan request */ + PARAM_SSID_T arMatchSsid[CFG_SCAN_SSID_MATCH_MAX_NUM]; +#else + UINT_32 u4SsidNum; + PARAM_SSID_T arSsid[CFG_SCAN_SSID_MATCH_MAX_NUM]; +#endif + INT_8 acRssiThresold[CFG_SCAN_SSID_MATCH_MAX_NUM]; + UINT_32 u4IELength; + PUINT_8 pucIE; + UINT_16 u2ScanInterval; /* in milliseconds */ + UINT_8 ucChnlNum; + PUINT_8 pucChannels; + UINT_8 ucScnFuncMask; +} PARAM_SCHED_SCAN_REQUEST, *P_PARAM_SCHED_SCAN_REQUEST; + +#if CFG_SUPPORT_PASSPOINT +typedef struct _PARAM_HS20_SET_BSSID_POOL { + BOOLEAN fgIsEnable; + UINT_8 ucNumBssidPool; + PARAM_MAC_ADDRESS arBSSID[8]; +} PARAM_HS20_SET_BSSID_POOL, *P_PARAM_HS20_SET_BSSID_POOL; + +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_SNIFFER +typedef struct _PARAM_CUSTOM_MONITOR_SET_STRUCT_T { + UINT_8 ucEnable; + UINT_8 ucBand; + UINT_8 ucPriChannel; + UINT_8 ucSco; + UINT_8 ucChannelWidth; + UINT_8 ucChannelS1; + UINT_8 ucChannelS2; + UINT_8 aucResv[9]; +} PARAM_CUSTOM_MONITOR_SET_STRUCT_T, *P_PARAM_CUSTOM_MONITOR_SET_STRUCT_T; +#endif + +#if defined(MT6797) +extern UINT_8 **g_pHifRegBaseAddr; +#endif + +/*--------------------------------------------------------------*/ +/*! \brief PSCN Scan Request Container */ +/*--------------------------------------------------------------*/ + +typedef struct _CMD_GET_PSCAN_CAPABILITY { + /*TBD*/ +} CMD_GET_GSCAN_CAPABILITY, *P_CMD_GET_GSCAN_CAPABILITY; + +typedef enum _ENUM_PSCAN_ACT_T { + PSCAN_ACT_DISABLE = 0, + PSCAN_ACT_ENABLE, + PSCAN_ACT_SUSPEND, + PSCAN_ACT_CLEAR +} ENUM_PSCAN_ACT_T, *P_ENUM_PSCAN_ACT_T; + +typedef struct _CMD_SET_PSCAN_ENABLE { + UINT_8 ucPscanAct; + UINT_8 aucReserved[3]; +} CMD_SET_PSCAN_ENABLE, *P_CMD_SET_PSCAN_ENABLE; + + +/*--------------------------------------------------------------*/ +/*! \brief MTK Auto Channel Selection related Container */ +/*--------------------------------------------------------------*/ +typedef struct _LTE_SAFE_CHN_INFO_T { + UINT_32 au4SafeChannelBitmask[5]; /* NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_MAX */ +} LTE_SAFE_CHN_INFO_T, *P_CMD_LTE_SAFE_CHN_INFO_T; + +typedef struct _PARAM_CHN_LOAD_INFO { + /* Per-CHN Load */ + UINT_8 ucChannel; + UINT_16 u2APNum; + UINT_16 u2APNumScore; + UINT_8 aucReserved[3]; +} PARAM_CHN_LOAD_INFO, *P_PARAM_CHN_LOAD_INFO; + +typedef struct _PARAM_GET_CHN_INFO { + UINT_8 ucRoleIndex; + LTE_SAFE_CHN_INFO_T rLteSafeChnList; + PARAM_CHN_LOAD_INFO rEachChnLoad[MAX_CHN_NUM]; + UINT_8 aucReserved[3]; +} PARAM_GET_CHN_INFO, *P_PARAM_GET_CHN_INFO; + +typedef struct _PARAM_PREFER_CHN_INFO { + UINT_8 ucChannel; + UINT_16 u2APNumScore; + UINT_8 ucReserved; +} PARAM_PREFER_CHN_INFO, *P_PARAM_PREFER_CHN_INFO; + + + +/* use to save partial scan channel information */ +typedef struct _PARTIAL_SCAN_INFO_T { + UINT_8 ucChannelListNum; + RF_CHANNEL_INFO_T arChnlInfoList[MAXIMUM_OPERATION_CHANNEL_LIST]; +} PARTIAL_SCAN_INFO, *P_PARTIAL_SCAN_INFO; + +#if CFG_SUPPORT_OSHARE +/* OSHARE Mode */ +#define MAX_OSHARE_MODE_LENGTH 64 +#define OSHARE_MODE_MAGIC_CODE 0x18 +#define OSHARE_MODE_CMD_V1 0x1 + +struct OSHARE_MODE_T { + UINT_8 cmdVersion; /* CMD version = OSHARE_MODE_CMD_V1 */ + UINT_8 cmdType; /* 1-set 0-query */ + UINT_8 magicCode; /* It's like CRC, OSHARE_MODE_MAGIC_CODE */ + UINT_8 cmdBufferLen; /* buffer length <= 64 */ + UINT_8 buffer[MAX_OSHARE_MODE_LENGTH]; +}; + +struct OSHARE_MODE_SETTING_V1_T { + UINT_8 osharemode; /* 0: disable, 1:Enable */ + UINT_8 reserved[7]; +}; +#endif + +struct PARAM_WIFI_LOG_LEVEL_UI { + UINT_32 u4Version; + UINT_32 u4Module; + UINT_32 u4Enable; +}; + +struct PARAM_WIFI_LOG_LEVEL { + UINT_32 u4Version; + UINT_32 u4Module; + UINT_32 u4Level; +}; + +struct PARAM_GET_WIFI_TYPE { + struct net_device *prNetDev; + uint8_t arWifiTypeName[8]; +}; + +enum ENUM_WIFI_LOG_LEVEL_VERSION_T { + ENUM_WIFI_LOG_LEVEL_VERSION_V1 = 1, + ENUM_WIFI_LOG_LEVEL_VERSION_NUM +}; + +enum ENUM_WIFI_LOG_LEVEL_T { + ENUM_WIFI_LOG_LEVEL_OFF = 0, + ENUM_WIFI_LOG_LEVEL_DEFAULT, + ENUM_WIFI_LOG_LEVEL_EXTREME, + ENUM_WIFI_LOG_LEVEL_NUM +}; + +enum ENUM_WIFI_LOG_MODULE_T { + ENUM_WIFI_LOG_MODULE_DRIVER = 0, + ENUM_WIFI_LOG_MODULE_FW, + ENUM_WIFI_LOG_MODULE_NUM, +}; + +enum ENUM_WIFI_LOG_LEVEL_SUPPORT_T { + ENUM_WIFI_LOG_LEVEL_SUPPORT_DISABLE = 0, + ENUM_WIFI_LOG_LEVEL_SUPPORT_ENABLE, + ENUM_WIFI_LOG_LEVEL_SUPPORT_NUM +}; +/* link quality monitor */ +struct PARAM_GET_LINK_QUALITY_INFO { + UINT_8 ucBssIdx; + struct WIFI_LINK_QUALITY_INFO *prLinkQualityInfo; +}; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +WLAN_STATUS +wlanoidQueryAntSwapCapability(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +/******************************************************************************* +* 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 +wlanoidSetBssidListScanAdv(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 +wlanoidSetConnect(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 +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 +wlanoidRssiMonitor(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +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); + +#if CFG_SUPPORT_QA_TOOL +#if CFG_SUPPORT_BUFFER_MODE +WLAN_STATUS wlanoidSetEfusBufferMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +/*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ +WLAN_STATUS +wlanoidQueryProcessAccessEfuseRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryProcessAccessEfuseWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryEfuseFreeBlock(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +/*#endif*/ + +#endif /* CFG_SUPPORT_BUFFER_MODE */ +WLAN_STATUS +wlanoidQueryRxStatistics(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidBssInfoBasic(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidDevInfoActive(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidManualAssoc(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +#if CFG_SUPPORT_TX_BF +WLAN_STATUS +wlanoidTxBfAction(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen); +WLAN_STATUS wlanoidMuMimoAction(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen); +WLAN_STATUS wlanoidStaRecUpdate(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen); +WLAN_STATUS wlanoidStaRecBFUpdate(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen); +#endif /* CFG_SUPPORT_TX_BF */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +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 +wlanoidSetChipConfig(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryChipConfig(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetKeyCfg(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 +wlanoidRftestSetTestIcapMode(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_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 + +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBT(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryBT(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetTxPower(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +#if CFG_ENABLE_WIFI_DIRECT +WLAN_STATUS +wlanoidSetP2pMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +WLAN_STATUS +wlanoidSetDefaultKey(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetGtkRekeyData(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetStartSchedScan(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetStopSchedScan(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +#if CFG_SUPPORT_ABORT_SCAN +WLAN_STATUS +wlanoidSetAbortScan(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +#if CFG_M0VE_BA_TO_DRIVER +WLAN_STATUS wlanoidResetBAScoreboard(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen); +#endif + +#if CFG_SUPPORT_BATCH_SCAN +WLAN_STATUS +wlanoidSetBatchScanReq(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryBatchScanResult(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); +#endif + +#if CFG_SUPPORT_PASSPOINT +WLAN_STATUS +wlanoidSetHS20Info(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetInterworkingInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetRoamingConsortiumIEInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetHS20BssidPool(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_SNIFFER +WLAN_STATUS wlanoidSetMonitor(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +#if CFG_SUPPORT_RSSI_DISCONNECT +WLAN_STATUS +wlanoidQueryRssiDisconnect(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); +#endif + +#if CFG_SUPPORT_GSCN +WLAN_STATUS +wlanoidSetGSCNAction(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetGSCNParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetGSCNConfig(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidGetGSCNResult(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +WLAN_STATUS +wlanoidSetPacketFilter(P_ADAPTER_T prAdapter, UINT_32 u4PacketFilter, + BOOLEAN fgIsOid, PVOID pvSetBuffer, UINT_32 u4SetBufferLen); + +WLAN_STATUS +wlanoidNotifyFwSuspend(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidPacketKeepAlive(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + + +#if FW_CFG_SUPPORT +WLAN_STATUS wlanoidQueryCfgRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS wlanoidSetFwParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +WLAN_STATUS +wlanoidDisableTdlsPs(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS wlanoidSetDrvRoamingPolicy(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidUpdateFtIes(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSync11kCapabilities(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSendNeighborRequest(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS wlanoidSendBTMQuery(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS wlanoidPktProcessIT( + P_ADAPTER_T prAdapter, PVOID pvBuffer, UINT_32 u4BufferLen, PUINT_32 pu4InfoLen); + +WLAN_STATUS +wlanoidFwEventIT(P_ADAPTER_T prAdapter, PVOID pvBuffer, UINT_32 u4BufferLen, PUINT_32 pu4InfoLen); + +WLAN_STATUS wlanoidTspecOperation( + IN P_ADAPTER_T prAdapter, IN PVOID pvBuffer, IN UINT_32 u4BufferLen, OUT PUINT_32 pu4InfoLen); + +WLAN_STATUS +wlanoidDumpUapsdSetting(P_ADAPTER_T prAdapter, PVOID pvBuffer, UINT_32 u4BufferLen, + PUINT_32 pu4InfoLen); + +#if CFG_SUPPORT_LOWLATENCY_MODE +WLAN_STATUS wlanoidSetLowLatencyMode(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + +#if CFG_SUPPORT_OSHARE +WLAN_STATUS +wlanoidSetOshareMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +WLAN_STATUS +wlanoidQueryWifiLogLevelSupport(IN P_ADAPTER_T prAdapter, + OUT PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryWifiLogLevel(IN P_ADAPTER_T prAdapter, + OUT PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetWifiLogLevel(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidEnableRoaming(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidConfigRoaming(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +WLAN_STATUS +wlanoidSetScanMacOui(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidStopApRole(IN P_ADAPTER_T prAdapter, + IN void *pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT UINT_32 *pu4SetInfoLen); + +WLAN_STATUS +wlanoidSendSarEnable(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +uint32_t +wlanoidGetWifiType(IN P_ADAPTER_T prAdapter, + IN void *pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT UINT_32 *pu4SetInfoLen); + +uint32_t +wlanoidExternalAuthDone(IN struct _ADAPTER_T *prAdapter, + IN void *pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT UINT_32 *pu4SetInfoLen); +WLAN_STATUS +wlanoidSetP2pRandomMac(P_ADAPTER_T prAdapter, void *pvSetBuffer, + UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR +UINT_32 wlanoidGetLinkQualityInfo(IN P_ADAPTER_T prAdapter, + IN void *pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT UINT_32 *pu4SetInfoLen); +#endif + +WLAN_STATUS +wlanoidSendSarEnable(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, + PUINT_32 pu4SetInfoLen); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _WLAN_OID_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/wlan_p2p.h b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/wlan_p2p.h new file mode 100644 index 0000000000000..4f6563dbd9f21 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen3/include/wlan_p2p.h @@ -0,0 +1,236 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify it under the terms of the +* GNU General Public License version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** 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. + */ + +#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 */ + UINT_8 ucBssIdx; /* for specific P2P BSS interface. */ + UINT_8 ucCipher; +} P2P_PARAM_KEY_T, *P_P2P_PARAM_KEY_T; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/*--------------------------------------------------------------*/ +/* Routines to handle command */ +/*--------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAddP2PKey(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetRemoveP2PKey(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetNetworkAddress(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetP2PMulticastList(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +/*--------------------------------------------------------------*/ +/* Service Discovery Subroutines */ +/*--------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendP2PSDRequest(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSendP2PSDResponse(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidGetP2PSDRequest(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidGetP2PSDResponse(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 puQueryInfoLen); + +WLAN_STATUS +wlanoidSetP2PTerminateSDPhase(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +#if CFG_SUPPORT_ANTI_PIRACY +WLAN_STATUS +wlanoidSetSecCheckRequest(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidGetSecCheckResponse(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); +#endif + +WLAN_STATUS +wlanoidSetNoaParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetOppPsParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetUApsdParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryP2pPowerSaveProfile(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetP2pPowerSaveProfile(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetP2pSetNetworkAddress(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryP2pOpChannel(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryP2pVersion(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetP2pSupplicantVersion(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER +WLAN_STATUS +wlanoidSetP2pWPSmode(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); +#endif + +#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 */ From 5cb1bea2a79810ee26eec1d588e5d43ba59fde9c Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 22:07:02 +0800 Subject: [PATCH 18/32] Add files via upload --- .../connectivity/wlan/core/gen4m/Android.mk | 19 + .../connectivity/wlan/core/gen4m/Makefile | 738 + .../connectivity/wlan/core/gen4m/Makefile.ce | 269 + .../wlan/core/gen4m/Makefile.none | 217 + .../wlan/core/gen4m/Makefile.openwrt | 654 + .../connectivity/wlan/core/gen4m/Makefile.x86 | 218 + .../core/gen4m/chips/common/cmm_asic_connac.c | 1868 ++ .../gen4m/chips/common/cmm_asic_connac2x.c | 1813 ++ .../wlan/core/gen4m/chips/common/dbg_connac.c | 2259 +++ .../core/gen4m/chips/common/dbg_connac2x.c | 2737 +++ .../wlan/core/gen4m/chips/common/fw_dl.c | 2567 +++ .../wlan/core/gen4m/chips/connac/connac.c | 389 + .../core/gen4m/chips/connac2x2/connac2x2.c | 445 + .../wlan/core/gen4m/chips/mt6632/mt6632.c | 495 + .../wlan/core/gen4m/chips/mt7663/mt7663.c | 321 + .../wlan/core/gen4m/chips/mt7668/mt7668.c | 571 + .../wlan/core/gen4m/chips/mt7915/dbg_mt7915.c | 967 + .../wlan/core/gen4m/chips/mt7915/mt7915.c | 599 + .../wlan/core/gen4m/chips/mt7961/dbg_mt7961.c | 833 + .../gen4m/chips/mt7961/hal_dmashdl_mt7961.c | 411 + .../wlan/core/gen4m/chips/mt7961/mt7961.c | 662 + .../wlan/core/gen4m/chips/soc3_0/dbg_soc3_0.c | 2085 ++ .../gen4m/chips/soc3_0/hal_dmashdl_soc3_0.c | 480 + .../wlan/core/gen4m/chips/soc3_0/soc3_0.c | 4882 +++++ .../wlan/core/gen4m/common/debug.c | 916 + .../wlan/core/gen4m/common/dump.c | 461 + .../wlan/core/gen4m/common/wlan_bow.c | 3222 +++ .../wlan/core/gen4m/common/wlan_he.c | 104 + .../wlan/core/gen4m/common/wlan_lib.c | 12448 ++++++++++++ .../wlan/core/gen4m/common/wlan_oid.c | 16474 ++++++++++++++++ .../wlan/core/gen4m/common/wlan_p2p.c | 1739 ++ .../wlan/core/gen4m/dvt/dvt_common.c | 1196 ++ .../wlan/core/gen4m/dvt/dvt_dmashdl.c | 1133 ++ .../wlan/core/gen4m/nic/cmd_buf.c | 321 + .../connectivity/wlan/core/gen4m/nic/nic.c | 4867 +++++ .../wlan/core/gen4m/nic/nic_cmd_event.c | 5459 +++++ .../wlan/core/gen4m/nic/nic_ext_cmd_event.c | 482 + .../wlan/core/gen4m/nic/nic_pwr_mgt.c | 424 + .../wlan/core/gen4m/nic/nic_rate.c | 1181 ++ .../connectivity/wlan/core/gen4m/nic/nic_rx.c | 4409 +++++ .../wlan/core/gen4m/nic/nic_rxd_v1.c | 568 + .../wlan/core/gen4m/nic/nic_rxd_v2.c | 594 + .../connectivity/wlan/core/gen4m/nic/nic_tx.c | 5473 +++++ .../wlan/core/gen4m/nic/nic_txd_v1.c | 765 + .../wlan/core/gen4m/nic/nic_txd_v2.c | 818 + .../wlan/core/gen4m/nic/nic_umac.c | 458 + .../wlan/core/gen4m/nic/p2p_nic.c | 283 + .../wlan/core/gen4m/nic/que_mgt.c | 8363 ++++++++ .../core/gen4m/wlan_service/agent/agent.c | 5272 +++++ .../glue/hal/gen4m/operation_gen4m.c | 2931 +++ .../wlan_service/glue/hal/include/operation.h | 486 + .../wlan_service/glue/hal/include/test_mac.h | 32 + .../glue/hal/jedi/operation_jedi.c | 2185 ++ .../wlan_service/glue/hal/jedi/test_dmac.c | 131 + .../wlan_service/glue/hal/jedi/test_fmac.c | 6 + .../glue/osal/gen4m/net_adaption_gen4m.c | 414 + .../glue/osal/gen4m/sys_adaption_gen4m.c | 98 + .../glue/osal/include/net_adaption.h | 1733 ++ .../glue/osal/include/sys_adaption.h | 342 + .../glue/osal/jedi/net_adaption_jedi.c | 3696 ++++ .../glue/osal/jedi/sys_adaption_jedi.c | 179 + .../core/gen4m/wlan_service/include/agent.h | 344 + .../service/include/service_test.h | 282 + .../service/include/test_engine.h | 98 + .../gen4m/wlan_service/service/service_test.c | 2479 +++ .../gen4m/wlan_service/service/test_engine.c | 2902 +++ 66 files changed, 122267 insertions(+) create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/Android.mk create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/Makefile create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/Makefile.ce create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/Makefile.none create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/Makefile.openwrt create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/Makefile.x86 create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/common/cmm_asic_connac.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/common/cmm_asic_connac2x.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/common/dbg_connac.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/common/dbg_connac2x.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/common/fw_dl.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/connac/connac.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/connac2x2/connac2x2.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt6632/mt6632.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7663/mt7663.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7668/mt7668.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7915/dbg_mt7915.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7915/mt7915.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7961/dbg_mt7961.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7961/hal_dmashdl_mt7961.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7961/mt7961.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/soc3_0/dbg_soc3_0.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/soc3_0/hal_dmashdl_soc3_0.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/soc3_0/soc3_0.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/debug.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/dump.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/wlan_bow.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/wlan_he.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/wlan_lib.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/wlan_oid.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/wlan_p2p.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/dvt/dvt_common.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/dvt/dvt_dmashdl.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/cmd_buf.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_cmd_event.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_ext_cmd_event.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_pwr_mgt.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_rate.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_rx.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_rxd_v1.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_rxd_v2.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_tx.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_txd_v1.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_txd_v2.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_umac.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/p2p_nic.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/que_mgt.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/agent/agent.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/hal/gen4m/operation_gen4m.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/hal/include/operation.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/hal/include/test_mac.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/hal/jedi/operation_jedi.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/hal/jedi/test_dmac.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/hal/jedi/test_fmac.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/osal/gen4m/net_adaption_gen4m.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/osal/gen4m/sys_adaption_gen4m.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/osal/include/net_adaption.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/osal/include/sys_adaption.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/osal/jedi/net_adaption_jedi.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/osal/jedi/sys_adaption_jedi.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/include/agent.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/service/include/service_test.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/service/include/test_engine.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/service/service_test.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/service/test_engine.c diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/Android.mk b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/Android.mk new file mode 100644 index 0000000000000..6b8056233bdbe --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/Android.mk @@ -0,0 +1,19 @@ +LOCAL_PATH := $(call my-dir) + +ifeq ($(MTK_WLAN_SUPPORT), yes) + +include $(CLEAR_VARS) +LOCAL_MODULE := wlan_drv_gen4m.ko +LOCAL_PROPRIETARY_MODULE := true +LOCAL_MODULE_OWNER := mtk +LOCAL_REQUIRED_MODULES := wmt_chrdev_wifi.ko + +include $(MTK_KERNEL_MODULE) + +WIFI_NAME := wlan_drv_gen4m +WIFI_OPTS := CONFIG_MTK_COMBO_WIFI_HIF=$(WIFI_HIF) MODULE_NAME=$(WIFI_NAME) MTK_COMBO_CHIP=$(WIFI_CHIP) WLAN_CHIP_ID=$(WLAN_CHIP_ID) MTK_ANDROID_WMT=$(WIFI_WMT) WIFI_ENABLE_GCOV=$(WIFI_ENABLE_GCOV) WIFI_IP_SET=$(WIFI_IP_SET) MTK_ANDROID_EMI=$(WIFI_EMI) +WIFI_OPTS += MTK_WLAN_SERVICE=yes + +$(linked_module): OPTS += $(WIFI_OPTS) + +endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/Makefile b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/Makefile new file mode 100644 index 0000000000000..b194a779ea3f8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/Makefile @@ -0,0 +1,738 @@ +MTK_PLATFORM := $(subst ",,$(CONFIG_MTK_PLATFORM)) +# --------------------------------------------------- +# OS option +# --------------------------------------------------- +os=$(CONFIG_MTK_SUPPORT_OS) + +ifeq ($(os),) +os=linux +endif + +ccflags-y += -Wno-unused-value +ccflags-y += -Wno-unused-result +ccflags-y += -Wno-format +ccflags-y += -Wno-parentheses + +ifeq ($(os), none) +ccflags-y += -I/usr/include/ +ccflags-y += -DCFG_VIRTUAL_OS +ccflags-y += -DCFG_REMIND_IMPLEMENT +endif + +ifndef TOP + TOP := $(srctree)/.. +endif +$(info os option: $(os)) +# --------------------------------------------------- +# ALPS Setting +# --------------------------------------------------- +ifneq ($(KERNEL_OUT),) + ccflags-y += -imacros $(KERNEL_OUT)/include/generated/autoconf.h +endif + +ifeq ($(KBUILD_MODPOST_FAIL_ON_WARNINGS),) + # Force build fail on modpost warning + KBUILD_MODPOST_FAIL_ON_WARNINGS=y +endif + +DRIVER_BUILD_DATE=$(shell date +%Y%m%d%H%M%S) +ccflags-y += -DDRIVER_BUILD_DATE='"$(DRIVER_BUILD_DATE)"' +# --------------------------------------------------- +# Compile Options +# --------------------------------------------------- +WLAN_CHIP_LIST:=-UMT6620 -UMT6628 -UMT5931 -UMT6630 -UMT6632 -UMT7663 -UCONNAC -UCONNAC2X2 -UUT_TEST_MODE -UMT7915 -USOC3_0 -UMT7961 +# '-D' and '-U' options are processed in the order they are given on the command line. +# All '-imacros file' and '-include file' options are processed after all '-D' and '-U' options. +ccflags-y += $(WLAN_CHIP_LIST) + +ifeq ($(MTK_COMBO_CHIP),) +MTK_COMBO_CHIP = MT6632 +endif + +$(info $$MTK_PLATFORM is [${MTK_PLATFORM}]) +$(info $$WLAN_CHIP_ID is [${WLAN_CHIP_ID}]) + +ifneq ($(CONFIG_MTK_EMI),) +ccflags-y += -DCONFIG_MTK_EMI=1 +endif + +ifneq ($(CONFIG_MEDIATEK_EMI),) +ccflags-y += -DCONFIG_MTK_EMI=1 +endif + +ifeq ($(WLAN_CHIP_ID),) +WLAN_CHIP_ID=$(word 1, $(MTK_COMBO_CHIP)) +endif + +ccflags-y += -DCFG_SUPPORT_DEBUG_FS=0 +ccflags-y += -DWLAN_INCLUDE_PROC +ccflags-y += -DCFG_SUPPORT_AGPS_ASSIST=0 +ccflags-y += -DCFG_SUPPORT_TSF_USING_BOOTTIME=1 +ccflags-y += -DARP_MONITER_ENABLE=1 +ccflags-y += -Werror +#ccflags-y:=$(filter-out -U$(WLAN_CHIP_ID),$(ccflags-y)) +#ccflags-y += -DLINUX -D$(WLAN_CHIP_ID) +#workaround: also needed for none LINUX system +# because some of common part code is surrounded with this flag +ccflags-y += -DLINUX + +ifneq ($(filter MT6632,$(MTK_COMBO_CHIP)),) +ccflags-y:=$(filter-out -UMT6632,$(ccflags-y)) +ccflags-y += -DMT6632 +endif + +ifneq ($(filter MT7668,$(MTK_COMBO_CHIP)),) +ccflags-y:=$(filter-out -UMT7668,$(ccflags-y)) +ccflags-y += -DMT7668 +endif + +ifneq ($(filter MT7663,$(MTK_COMBO_CHIP)),) +ccflags-y:=$(filter-out -UMT7663,$(ccflags-y)) +ccflags-y += -DMT7663 +endif + +ifneq ($(filter CONNAC,$(MTK_COMBO_CHIP)),) +ccflags-y:=$(filter-out -UCONNAC,$(ccflags-y)) +ccflags-y += -DCONNAC +endif + +ifneq ($(filter CONNAC2X2,$(MTK_COMBO_CHIP)),) +ccflags-y:=$(filter-out -UCONNAC2X2,$(ccflags-y)) +ccflags-y += -DCONNAC2X2 +endif + +ifneq ($(findstring MT7915,$(MTK_COMBO_CHIP)),) +ccflags-y:=$(filter-out -UMT7915,$(ccflags-y)) +ccflags-y += -DMT7915 +CONFIG_MTK_WIFI_CONNAC2X=y +CONFIG_MTK_WIFI_11AX_SUPPORT=y +CONFIG_MTK_WIFI_TWT_SUPPORT=y +CONFIG_NUM_OF_WFDMA_RX_RING=5 +CONFIG_NUM_OF_WFDMA_TX_RING=1 +endif + +ifneq ($(findstring 3_0,$(MTK_COMBO_CHIP)),) +ccflags-y:=$(filter-out -USOC3_0,$(ccflags-y)) +ccflags-y += -DSOC3_0 +CONFIG_MTK_WIFI_CONNAC2X=y +CONFIG_MTK_WIFI_11AX_SUPPORT=y +CONFIG_MTK_WIFI_TWT_SUPPORT=y +CONFIG_NUM_OF_WFDMA_RX_RING=3 +CONFIG_NUM_OF_WFDMA_TX_RING=0 +CONFIG_MTK_WIFI_CONNINFRA_SUPPORT=y +CONFIG_MTK_WIFI_CONNAC2X_2x2=y +ccflags-y += -DCFG_POWER_ON_DOWNLOAD_EMI_ROM_PATCH=1 +ccflags-y += -DCFG_DOWNLOAD_DYN_MEMORY_MAP=1 +ccflags-y += -DCFG_ROM_PATCH_NO_SEM_CTRL=1 +ccflags-y += -DCFG_ANDORID_CONNINFRA_SUPPORT=1 +else +ccflags-y += -DCFG_ANDORID_CONNINFRA_SUPPORT=0 +endif + +ifneq ($(findstring MT7961,$(MTK_COMBO_CHIP)),) +ccflags-y:=$(filter-out -UMT7961,$(ccflags-y)) +ccflags-y += -DMT7961 +CONFIG_MTK_WIFI_CONNAC2X=y +CONFIG_MTK_WIFI_11AX_SUPPORT=y +CONFIG_MTK_WIFI_TWT_SUPPORT=y +CONFIG_NUM_OF_WFDMA_RX_RING=5 +CONFIG_NUM_OF_WFDMA_TX_RING=1 +endif + +ifneq ($(filter 6873, $(WLAN_CHIP_ID)),) + ccflags-y += -DCFG_ENABLE_HOST_BUS_TIMEOUT=1 +else + ccflags-y += -DCFG_ENABLE_HOST_BUS_TIMEOUT=0 +endif + +ifeq ($(CONFIG_MTK_WIFI_CONNAC2X), y) + ccflags-y += -DCFG_SUPPORT_CONNAC2X=1 +else + ccflags-y += -DCFG_SUPPORT_CONNAC2X=0 +endif + +ifeq ($(CONFIG_MTK_WIFI_CONNAC2X_2x2), y) + ccflags-y += -DCFG_SUPPORT_CONNAC2X_2x2=1 +else + ccflags-y += -DCFG_SUPPORT_CONNAC2X_2x2=0 +endif + +ifeq ($(CONFIG_MTK_WIFI_11AX_SUPPORT), y) + ccflags-y += -DCFG_SUPPORT_802_11AX=1 +else + ccflags-y += -DCFG_SUPPORT_802_11AX=0 +endif + +ifeq ($(CONFIG_MTK_WIFI_TWT_SUPPORT), y) + ccflags-y += -DCFG_SUPPORT_TWT=1 +else + ccflags-y += -DCFG_SUPPORT_TWT=0 +endif + +ifneq ($(CONFIG_NUM_OF_WFDMA_TX_RING),) + ccflags-y += -DCONFIG_NUM_OF_WFDMA_TX_RING=$(CONFIG_NUM_OF_WFDMA_TX_RING) +endif + +ifneq ($(CONFIG_NUM_OF_WFDMA_RX_RING),) + ccflags-y += -DCONFIG_NUM_OF_WFDMA_RX_RING=$(CONFIG_NUM_OF_WFDMA_RX_RING) +endif + +ifeq ($(WIFI_ENABLE_GCOV), y) + GCOV_PROFILE := y +endif + +ccflags-y += -DCFG_DRIVER_INITIAL_RUNNING_MODE=3 + +ifneq ($(filter 6765, $(WLAN_CHIP_ID)),) + ccflags-y += -DCFG_SUPPORT_DUAL_STA=0 +else ifeq ($(CONFIG_MTK_TC10_FEATURE), y) + ccflags-y += -DCFG_SUPPORT_DUAL_STA=0 +else + ccflags-y += -DCFG_SUPPORT_DUAL_STA=1 +endif + +ifneq ($(filter 6779, $(WLAN_CHIP_ID)),) + ccflags-y += -DCFG_FORCE_AP1NSS +endif + +ifeq ($(MTK_ANDROID_WMT), y) + ccflags-y += -DCFG_MTK_ANDROID_WMT=1 + WMT_SUPPORT := y +else ifneq ($(filter MT6632,$(MTK_COMBO_CHIP)),) + ccflags-y += -DCFG_MTK_ANDROID_WMT=1 + WMT_SUPPORT := y +else + ccflags-y += -DCFG_MTK_ANDROID_WMT=0 + WMT_SUPPORT := n +endif + +ifeq ($(CONFIG_MTK_WIFI_CONNINFRA_SUPPORT), y) + ccflags-y += -DCFG_SUPPORT_CONNINFRA=1 + ccflags-y += -DCFG_SUPPORT_PRE_ON_PHY_ACTION=1 + ccflags-y += -I$(TOP)/vendor/mediatek/kernel_modules/connectivity/conninfra/include + ccflags-y += -DCFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT=1 + ifneq ($(CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH),) + ccflags-y += -I$(TOP)/vendor/mediatek/kernel_modules/connectivity/conninfra/include + ccflags-y += -I$(TOP)/vendor/mediatek/kernel_modules/connectivity/conninfra/platform/include + ccflags-y += -I$(TOP)/vendor/mediatek/kernel_modules/connectivity/conninfra/base/include + ccflags-y += -I$(TOP)/vendor/mediatek/kernel_modules/connectivity/conninfra/debug_utility + ccflags-y += -I$(TOP)/vendor/mediatek/kernel_modules/connectivity/conninfra/debug_utility/include + ccflags-y += -I$(TOP)/vendor/mediatek/kernel_modules/connectivity/conninfra/debug_utility/connsyslog + ccflags-y += -I$(TOP)/vendor/mediatek/kernel_modules/connectivity/conninfra/debug_utility/coredump + ccflags-y += -I$(TOP)/vendor/mediatek/kernel_modules/connectivity/conninfra/debug_utility/coredump/platform/include + ccflags-y += -I$(TOP)/vendor/mediatek/kernel_modules/connectivity/wlan/adaptor + endif +else + ccflags-y += -DCFG_SUPPORT_CONNINFRA=0 + ccflags-y += -DCFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT=0 + ccflags-y += -DCFG_SUPPORT_PRE_ON_PHY_ACTION=0 + ifeq ($(WMT_SUPPORT), y) + ccflags-y += -I$(TOP)/vendor/mediatek/kernel_modules/connectivity/common/common_main/include + ccflags-y += -I$(TOP)/vendor/mediatek/kernel_modules/connectivity/common/common_main/linux/include + ifeq ($(CONFIG_MTK_CONN_LTE_IDC_SUPPORT),y) + ccflags-y += -DWMT_IDC_SUPPORT=1 + else + ccflags-y += -DWMT_IDC_SUPPORT=0 + endif + ccflags-y += -DMTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + endif +endif + +ifeq ($(MTK_ANDROID_EMI), y) + ccflags-y += -DCFG_MTK_ANDROID_EMI=1 +else + ccflags-y += -DCFG_MTK_ANDROID_EMI=0 +endif + +ifneq ($(WIFI_IP_SET),) + ccflags-y += -DCFG_WIFI_IP_SET=$(WIFI_IP_SET) +else + ccflags-y += -DCFG_WIFI_IP_SET=1 +endif + +ifneq ($(filter MTK_WCN_REMOVE_KERNEL_MODULE,$(KBUILD_SUBDIR_CCFLAGS)),) + ccflags-y += -DCFG_BUILT_IN_DRIVER=1 +else + ccflags-y += -DCFG_BUILT_IN_DRIVER=0 +endif + +ifneq ($(findstring UT_TEST_MODE,$(MTK_COMBO_CHIP)),) +ccflags-y:=$(filter-out -UUT_TEST_MODE,$(ccflags-y)) +ccflags-y += -DUT_TEST_MODE +endif + +CONFIG_MTK_WIFI_MCC_SUPPORT=y +ifeq ($(CONFIG_MTK_WIFI_MCC_SUPPORT), y) + ccflags-y += -DCFG_SUPPORT_CHNL_CONFLICT_REVISE=0 +else + ccflags-y += -DCFG_SUPPORT_CHNL_CONFLICT_REVISE=1 +endif + +ifeq ($(CONFIG_MTK_AEE_FEATURE), y) + ccflags-y += -DCFG_SUPPORT_AEE=1 +else + ccflags-y += -DCFG_SUPPORT_AEE=0 +endif + +# Disable ASSERT() for user load, enable for others +ifneq ($(TARGET_BUILD_VARIANT),user) + ccflags-y += -DBUILD_QA_DBG=1 +else + ccflags-y += -DBUILD_QA_DBG=0 +endif + +ifeq ($(CONFIG_MTK_COMBO_WIFI),y) + ccflags-y += -DCFG_WPS_DISCONNECT=1 +endif + +ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), sdio) + ccflags-y += -D_HIF_SDIO=1 +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), pcie) + ccflags-y += -D_HIF_PCIE=1 +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), usb) + ccflags-y += -D_HIF_USB=1 +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), axi) + ccflags-y += -D_HIF_AXI=1 +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), ut) + # Increase frame size to 2048 because of 'cfg80211_connect_result' exceed stack size + ccflags-y += -D_HIF_UT=1 -Wno-unused-function -Wno-unused-variable -Wframe-larger-than=2048 +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), none) + ccflags-y += -D_HIF_NONE=1 +else + $(error Unsuppoted HIF=$(CONFIG_MTK_COMBO_WIFI_HIF)!!) +endif + +ifneq ($(CFG_CFG80211_VERSION),) +VERSION_STR = $(subst \",,$(subst ., , $(subst -, ,$(subst v,,$(CFG_CFG80211_VERSION))))) +$(info VERSION_STR=$(VERSION_STR)) +X = $(firstword $(VERSION_STR)) +Y = $(word 2 ,$(VERSION_STR)) +Z = $(word 3 ,$(VERSION_STR)) +VERSION := $(shell echo "$$(( $X * 65536 + $Y * 256 + $Z))" ) +ccflags-y += -DCFG_CFG80211_VERSION=$(VERSION) +$(info DCFG_CFG80211_VERSION=$(VERSION)) +endif + + +ifeq ($(CONFIG_MTK_PASSPOINT_R2_SUPPORT), y) + ccflags-y += -DCFG_SUPPORT_PASSPOINT=1 + ccflags-y += -DCFG_HS20_DEBUG=1 + ccflags-y += -DCFG_ENABLE_GTK_FRAME_FILTER=1 +else + ccflags-y += -DCFG_SUPPORT_PASSPOINT=0 + ccflags-y += -DCFG_HS20_DEBUG=0 + ccflags-y += -DCFG_ENABLE_GTK_FRAME_FILTER=0 +endif + +MTK_MET_PROFILING_SUPPORT = yes +ifeq ($(MTK_MET_PROFILING_SUPPORT), yes) + ccflags-y += -DCFG_MET_PACKET_TRACE_SUPPORT=1 +else + ccflags-y += -DCFG_MET_PACKET_TRACE_SUPPORT=0 +endif + +MTK_MET_TAG_SUPPORT = no +ifeq ($(MTK_MET_TAG_SUPPORT), yes) + ccflags-y += -DMET_USER_EVENT_SUPPORT + ccflags-y += -DCFG_MET_TAG_SUPPORT=1 +else + ccflags-y += -DCFG_MET_TAG_SUPPORT=0 +endif + +MTK_TC3_SUPPORT = no +ifeq ($(MTK_TC3_SUPPORT), yes) + ccflags-y += -DCFG_TC3_FEATURE=1 + ccflags-y += -DCFG_P2P_CONNECT_ALL_BSS=1 + ccflags-y += -DCFG_P2P_DEFAULT_CLIENT_COUNT=1 + ccflags-y += -DCFG_P2P_SCAN_REPORT_ALL_BSS=1 +else + ccflags-y += -DCFG_TC3_FEATURE=0 +endif + +ifeq ($(CONFIG_MTK_TC10_FEATURE), y) + ccflags-y += -DCFG_TC10_FEATURE=1 +else + ccflags-y += -DCFG_TC10_FEATURE=0 +endif + +ifeq ($(CONFIG_MTK_TC1_FEATURE), y) + ccflags-y += -I$(srctree)/drivers/misc/mediatek/tc1_interface + ccflags-y += -DCFG_TC1_FEATURE=1 +else + ccflags-y += -DCFG_TC1_FEATURE=0 +endif + +ifeq ($(MODULE_NAME),) + MODULE_NAME := wlan_$(shell echo $(strip $(WLAN_CHIP_ID)) | tr A-Z a-z)_$(CONFIG_MTK_COMBO_WIFI_HIF) +endif + +ccflags-y += -DDBG=0 +ccflags-y += -I$(src)/os -I$(src)/os/$(os)/include +ccflags-y += -I$(src)/include -I$(src)/include/nic -I$(src)/include/mgmt -I$(src)/include/chips +ifeq ($(CFG_SUPPORT_WIFI_SYSDVT), 1) +ccflags-y += -I$(src)/include/dvt +endif +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/performance/include/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/emi/$(MTK_PLATFORM) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/emi/submodule +ccflags-y += -I$(srctree)/drivers/misc/mediatek/connectivity/common +ccflags-y += -I$(srctree)/drivers/devfreq/ +ccflags-y += -I$(srctree)/net + +ifeq ($(CONFIG_MTK_MCIF_WIFI_SUPPORT), y) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/mddp/include/ +ccflags-y += -DCFG_MTK_MCIF_WIFI_SUPPORT=1 +ifeq ($(CONFIG_MTK_MDDP_WH_SUPPORT), y) +ccflags-y += -DCFG_MTK_MDDP_WH_SUPPORT=1 +else +ccflags-y += -DCFG_MTK_MDDP_WH_SUPPORT=0 +endif +else +ccflags-y += -DCFG_MTK_MCIF_WIFI_SUPPORT=0 +ccflags-y += -DCFG_MTK_MDDP_WH_SUPPORT=0 +endif + +ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), sdio) +ccflags-y += -I$(src)/os/$(os)/hif/sdio/include +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), pcie) +ccflags-y += -I$(src)/os/$(os)/hif/common/include +ccflags-y += -I$(src)/os/$(os)/hif/pcie/include +ifneq ($(findstring 3_0,$(MTK_COMBO_CHIP)),) +ccflags-y += -I$(src)/include/chips/coda/soc3_0 +endif +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), axi) +ccflags-y += -I$(src)/os/$(os)/hif/common/include +ccflags-y += -I$(src)/os/$(os)/hif/axi/include +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), usb) +ccflags-y += -I$(src)/os/$(os)/hif/usb/include +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), ut) +ccflags-y += -I$(src)/test -I$(src)/test/lib/include -I$(src)/test/testcases -I$(src)/test/lib/hif +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), none) +ccflags-y += -I$(src)/os/$(os)/hif/none/include +endif + +ifneq ($(PLATFORM_FLAGS), ) + ccflags-y += $(PLATFORM_FLAGS) +endif + +ifeq ($(CONFIG_MTK_WIFI_ONLY),$(filter $(CONFIG_MTK_WIFI_ONLY),m y)) +obj-$(CONFIG_MTK_WIFI_ONLY) += $(MODULE_NAME).o +else +obj-$(CONFIG_MTK_COMBO_WIFI) += $(MODULE_NAME).o +#obj-y += $(MODULE_NAME).o +endif + +ifeq ($(CONFIG_WLAN_DRV_BUILD_IN),y) +$(warning $(MODULE_NAME) build-in boot.img) +obj-y += $(MODULE_NAME).o +ccflags-y += -DCONFIG_WLAN_DRV_BUILD_IN=1 +else +$(warning $(MODULE_NAME) is kernel module) +obj-m += $(MODULE_NAME).o +ccflags-y += -DCONFIG_WLAN_DRV_BUILD_IN=0 +endif + +# --------------------------------------------------- +# Directory List +# --------------------------------------------------- +COMMON_DIR := common/ +OS_DIR := os/$(os)/ +HIF_COMMON_DIR := $(OS_DIR)hif/common/ +ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), sdio) +HIF_DIR := os/$(os)/hif/sdio/ +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), pcie) +HIF_DIR := os/$(os)/hif/pcie/ +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), axi) +HIF_DIR := os/$(os)/hif/axi/ +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), usb) +HIF_DIR := os/$(os)/hif/usb/ +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), ut) +HIF_DIR := test/lib/hif/ +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), none) +HIF_DIR := os/$(os)/hif/none/ +endif +NIC_DIR := nic/ +MGMT_DIR := mgmt/ +CHIPS := chips/ +CHIPS_CMM := $(CHIPS)common/ + +ifneq ($(WLAN_CHIP_ID),) +PLAT_DIR := os/$(os)/plat/mt$(WLAN_CHIP_ID)/ +endif +SYSDVT_DIR := dvt/ + +# --------------------------------------------------- +# Objects List +# --------------------------------------------------- + +COMMON_OBJS := $(COMMON_DIR)dump.o \ + $(COMMON_DIR)wlan_lib.o \ + $(COMMON_DIR)wlan_oid.o \ + $(COMMON_DIR)wlan_bow.o \ + $(COMMON_DIR)debug.o + +NIC_OBJS := $(NIC_DIR)nic.o \ + $(NIC_DIR)nic_tx.o \ + $(NIC_DIR)nic_txd_v1.o \ + $(NIC_DIR)nic_rxd_v1.o \ + $(NIC_DIR)nic_rx.o \ + $(NIC_DIR)nic_pwr_mgt.o \ + $(NIC_DIR)nic_rate.o \ + $(NIC_DIR)cmd_buf.o \ + $(NIC_DIR)que_mgt.o \ + $(NIC_DIR)nic_cmd_event.o \ + $(NIC_DIR)nic_umac.o + +ifeq ($(os), none) +OS_OBJS := $(OS_DIR)gl_dependent.o \ + $(OS_DIR)gl_init.o \ + $(OS_DIR)gl_kal.o \ + $(OS_DIR)gl_ate_agent.o \ + $(OS_DIR)gl_qa_agent.o +else +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_ate_agent.o \ + $(OS_DIR)gl_qa_agent.o \ + $(OS_DIR)gl_hook_api.o \ + $(OS_DIR)gl_rst.o \ + $(OS_DIR)gl_cfg80211.o \ + $(OS_DIR)gl_proc.o \ + $(OS_DIR)gl_sys.o \ + $(OS_DIR)gl_vendor.o \ + $(OS_DIR)platform.o +endif + +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)reg_rule.o \ + $(MGMT_DIR)rlm_obss.o \ + $(MGMT_DIR)rlm_protection.o \ + $(MGMT_DIR)rrm.o \ + $(MGMT_DIR)rsn.o \ + $(MGMT_DIR)saa_fsm.o \ + $(MGMT_DIR)scan.o \ + $(MGMT_DIR)scan_fsm.o \ + $(MGMT_DIR)scan_cache.o \ + $(MGMT_DIR)swcr.o \ + $(MGMT_DIR)roaming_fsm.o \ + $(MGMT_DIR)tkip_mic.o \ + $(MGMT_DIR)hs20.o \ + $(MGMT_DIR)tdls.o \ + $(MGMT_DIR)wnm.o \ + $(MGMT_DIR)qosmap.o \ + $(MGMT_DIR)ap_selection.o \ + $(MGMT_DIR)wmm.o \ + $(MGMT_DIR)mddp.o \ + +# --------------------------------------------------- +# Chips Objects List +# --------------------------------------------------- +MGMT_OBJS += $(MGMT_DIR)stats.o + + +CHIPS_OBJS += $(CHIPS_CMM)cmm_asic_connac.o +CHIPS_OBJS += $(CHIPS_CMM)dbg_connac.o +ifeq ($(CONFIG_MTK_WIFI_CONNAC2X), y) +CHIPS_OBJS += $(CHIPS_CMM)dbg_connac2x.o +endif + +ifeq ($(CONFIG_MTK_WIFI_CONNAC2X), y) +CHIPS_OBJS += $(CHIPS_CMM)cmm_asic_connac2x.o +NIC_OBJS += $(NIC_DIR)nic_ext_cmd_event.o \ + $(NIC_DIR)nic_txd_v2.o \ + $(NIC_DIR)nic_rxd_v2.o +endif +CHIPS_OBJS += $(CHIPS_CMM)fw_dl.o + +ifneq ($(filter MT6632,$(MTK_COMBO_CHIP)),) +CHIPS_OBJS += $(CHIPS)mt6632/mt6632.o +endif +ifneq ($(filter MT7668,$(MTK_COMBO_CHIP)),) +CHIPS_OBJS += $(CHIPS)mt7668/mt7668.o +endif +ifneq ($(filter MT7663,$(MTK_COMBO_CHIP)),) +CHIPS_OBJS += $(CHIPS)mt7663/mt7663.o +endif +ifneq ($(filter CONNAC,$(MTK_COMBO_CHIP)),) +CHIPS_OBJS += $(CHIPS)connac/connac.o +endif +ifneq ($(filter CONNAC2X2,$(MTK_COMBO_CHIP)),) +CHIPS_OBJS += $(CHIPS)connac2x2/connac2x2.o +endif +ifneq ($(findstring MT7915,$(MTK_COMBO_CHIP)),) +CHIPS_OBJS += $(CHIPS)mt7915/mt7915.o +CHIPS_OBJS += $(CHIPS)mt7915/dbg_mt7915.o +endif +ifneq ($(findstring 3_0,$(MTK_COMBO_CHIP)),) +CHIPS_OBJS += $(CHIPS)soc3_0/soc3_0.o +CHIPS_OBJS += $(CHIPS)soc3_0/dbg_soc3_0.o +CHIPS_OBJS += $(CHIPS)soc3_0/hal_dmashdl_soc3_0.o +endif +ifneq ($(findstring MT7961,$(MTK_COMBO_CHIP)),) +CHIPS_OBJS += $(CHIPS)mt7961/mt7961.o +CHIPS_OBJS += $(CHIPS)mt7961/dbg_mt7961.o +CHIPS_OBJS += $(CHIPS)mt7961/hal_dmashdl_mt7961.o +endif + +# --------------------------------------------------- +# P2P Objects List +# --------------------------------------------------- + +COMMON_OBJS += $(COMMON_DIR)wlan_p2p.o + +NIC_OBJS += $(NIC_DIR)p2p_nic.o + +ifneq ($(os), none) +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 +endif + +MGMT_OBJS += $(MGMT_DIR)p2p_dev_fsm.o\ + $(MGMT_DIR)p2p_dev_state.o\ + $(MGMT_DIR)p2p_role_fsm.o\ + $(MGMT_DIR)p2p_role_state.o\ + $(MGMT_DIR)p2p_func.o\ + $(MGMT_DIR)p2p_scan.o\ + $(MGMT_DIR)p2p_ie.o\ + $(MGMT_DIR)p2p_rlm.o\ + $(MGMT_DIR)p2p_assoc.o\ + $(MGMT_DIR)p2p_bss.o\ + $(MGMT_DIR)p2p_rlm_obss.o\ + $(MGMT_DIR)p2p_fsm.o + +MGMT_OBJS += $(MGMT_DIR)wapi.o + +# --------------------------------------------------- +# HE Objects List +# --------------------------------------------------- + +COMMON_OBJS += $(COMMON_DIR)wlan_he.o + +ifeq ($(CONFIG_MTK_WIFI_11AX_SUPPORT), y) +MGMT_OBJS += $(MGMT_DIR)he_ie.o \ + $(MGMT_DIR)he_rlm.o +endif + +ifeq ($(CONFIG_MTK_WIFI_TWT_SUPPORT), y) +MGMT_OBJS += $(MGMT_DIR)twt_req_fsm.o \ + $(MGMT_DIR)twt.o \ + $(MGMT_DIR)twt_planner.o +endif + +ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), sdio) +HIF_OBJS := $(HIF_DIR)arm.o \ + $(HIF_DIR)sdio.o \ + $(HIF_DIR)hal_api.o \ + $(HIF_DIR)sdio_test_driver_core.o \ + $(HIF_DIR)sdio_test_driver_ops.o +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), pcie) +HIF_OBJS := $(HIF_COMMON_DIR)hal_pdma.o \ + $(HIF_COMMON_DIR)kal_pdma.o \ + $(HIF_COMMON_DIR)dbg_pdma.o \ + $(HIF_DIR)pcie.o +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), axi) +HIF_OBJS := $(HIF_COMMON_DIR)hal_pdma.o \ + $(HIF_COMMON_DIR)kal_pdma.o \ + $(HIF_COMMON_DIR)dbg_pdma.o \ + $(HIF_DIR)axi.o +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), usb) +HIF_OBJS := $(HIF_DIR)usb.o \ + $(HIF_DIR)hal_api.o +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), ut) +HIF_OBJS := $(HIF_DIR)ut.o \ + $(HIF_DIR)hal_api.o +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), none) +HIF_OBJS := $(HIF_DIR)none.o +endif +# --------------------------------------------------- +# Platform Objects List +# --------------------------------------------------- +ifneq ($(PLAT_DIR),) + +PLAT_PRIV_C = $(src)/$(PLAT_DIR)plat_priv.c + +# search path (out of kernel tree) +IS_EXIST_PLAT_PRIV_C := $(wildcard $(PLAT_PRIV_C)) +# search path (build-in kernel tree) +IS_EXIST_PLAT_PRIV_C += $(wildcard $(srctree)/$(PLAT_PRIV_C)) + +ifneq ($(strip $(IS_EXIST_PLAT_PRIV_C)),) +PLAT_OBJS := $(PLAT_DIR)plat_priv.o +$(MODULE_NAME)-objs += $(PLAT_OBJS) +endif +endif + +# --------------------------------------------------- +# System Dvt Objects List +# --------------------------------------------------- +ifeq ($(CFG_SUPPORT_WIFI_SYSDVT), 1) +SYSDVT_OBJS += $(SYSDVT_DIR)dvt_common.o + +ifeq ($(CFG_SUPPORT_DMASHDL_SYSDVT), 1) +SYSDVT_OBJS += $(SYSDVT_DIR)dvt_dmashdl.o +endif +endif + +# --------------------------------------------------- +# Service git List +# --------------------------------------------------- +SERVICE_DIR := wlan_service/ + +ifneq ($(findstring wlan_service,$(MTK_WLAN_SERVICE_PATH)),) +MTK_WLAN_SERVICE=yes +SERVICE_DIR := $(MTK_WLAN_SERVICE_PATH) +$(info SERVICE_DIR is [{$(MTK_WLAN_SERVICE_PATH)}]) +endif + +ifeq ($(MTK_WLAN_SERVICE), yes) +ccflags-y += -DCONFIG_WLAN_SERVICE=1 +ccflags-y += -DCONFIG_TEST_ENGINE_OFFLOAD=1 +ccflags-y += -I$(src)/$(SERVICE_DIR)include +ccflags-y += -I$(src)/$(SERVICE_DIR)service/include +ccflags-y += -I$(src)/$(SERVICE_DIR)glue/osal/include +ccflags-y += -I$(src)/$(SERVICE_DIR)glue/hal/include +$(info $$CCFLAG is [{$(ccflags-y)}]) +SERVICE_OBJS := $(SERVICE_DIR)agent/agent.o \ + $(SERVICE_DIR)service/service_test.o \ + $(SERVICE_DIR)service/test_engine.o \ + $(SERVICE_DIR)glue/osal/gen4m/sys_adaption_gen4m.o \ + $(SERVICE_DIR)glue/osal/gen4m/net_adaption_gen4m.o \ + $(SERVICE_DIR)glue/hal/gen4m/operation_gen4m.o +$(MODULE_NAME)-objs += $(SERVICE_OBJS) +$(info $$MTK_WLAN_SERVICE is [{$(SERVICE_OBJS)}]) +else +ccflags-y += -DCONFIG_WLAN_SERVICE=0 +ccflags-y += -DCONFIG_TEST_ENGINE_OFFLOAD=0 +endif + +$(MODULE_NAME)-objs += $(COMMON_OBJS) +$(MODULE_NAME)-objs += $(NIC_OBJS) +$(MODULE_NAME)-objs += $(OS_OBJS) +$(MODULE_NAME)-objs += $(HIF_OBJS) +$(MODULE_NAME)-objs += $(MGMT_OBJS) +$(MODULE_NAME)-objs += $(CHIPS_OBJS) +$(MODULE_NAME)-objs += $(SYSDVT_OBJS) + +ifneq ($(findstring UT_TEST_MODE,$(MTK_COMBO_CHIP)),) +include $(src)/test/ut.make +endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/Makefile.ce b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/Makefile.ce new file mode 100644 index 0000000000000..eb4cbd0b5bbda --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/Makefile.ce @@ -0,0 +1,269 @@ +# Makefile for MT76x8 combo driver + +############################################################## +# Common settings +############################################################## +export MTK_COMBO_CHIP=MT6632 +export HIF=usb +export CONFIG_MTK_WIFI_ONLY=m +export CONFIG_MTK_COMBO=m +export CONFIG_MTK_COMBO_WIFI=m +export CONFIG_MTK_COMBO_COMM=m +export CONFIG_MTK_COMBO_COMM_UART=m +export CONFIG_MTK_COMBO_COMM_SDIO=m +export CONFIG_MT_WIFI_CHRDEV=m +WIFI_TARGET := mt76x8 + +ifeq ($(HIF),) + HIF=usb +endif + +export CONFIG_MTK_COMBO_WIFI_HIF=$(HIF) +MODULE_NAME := wlan_$(WIFI_TARGET)_$(HIF) + + +############################################################## +# Platform specific +############################################################## +# Set default platform +PLATFORM = MT53XX + +ifeq ($(PLATFORM),) +PLATFORM = MT53XX +endif + +#- - - - -- - - - - - - - - - +# MT53XX start +#- - - - -- - - - - - - - - - +ifeq ($(PLATFORM),MT53XX) + +# Sets DRIVER_PARTIAL_BUILD to y to compile driver only, otherwise set to n +DRIVER_PARTIAL_BUILD=n +# Set if 64 bit platform +64BIT_MODE=true +export WIFI_TARGET +TARGET = LINUX + +ifeq ($(DRIVER_PARTIAL_BUILD),y) +# *****For driver partial build***** +LINUX_ROOT ?= $(word 1, $(subst /apollo/,/apollo /, $(shell pwd -L))) +# Modify the build parameters below to fit your build +SYSBUILD_NAME=m-base +RELEASE_NAME=mediatek/mt5891_eu_64 +KERNEL_VER=3.18 +KERNEL_CONFIG=mt5891_android_smp_mod_defconfig +ifeq ($(64BIT_MODE),true) +export 64BIT_MODE=true +export KERNEL_64BIT=true +export TOOL_CHAIN_64BIT=4.9.3 +endif +# +LINUX_SRC=$(LINUX_ROOT)/../android/$(SYSBUILD_NAME)/out/mediatek_linux/output/$(RELEASE_NAME)/rel/obj/kernel/linux_core/kernel/linux-$(KERNEL_VER)/$(KERNEL_CONFIG)_modules +OBJ_ROOT ?= $(LINUX_ROOT)/../android/$(SYSBUILD_NAME)/out/mediatek_linux/output/$(RELEASE_NAME)/rel/obj +export KERNEL_OBJ_ROOT=$(LINUX_SRC)/../.. +else +# *****For system auto build***** +LINUX_SRC=$(KERNEL_OBJ_ROOT)/$(KERNEL_VER)/$(KERNEL_CONFIG)_modules +# overwrite $(OUT_STA_KO) for MT53XX platform +OUT_STA_KO = $(OBJ_ROOT)/third_party/source/wlan/mtk/$(WIFI_TARGET)/$(MODULE_NAME).ko +endif + +include $(LINUX_ROOT)/linux_mts/mak/toolchain.mak +ifeq ($(CROSS_COMPILE),) +CROSS_COMPILE=/mtkoss/gnuarm/vfp_4.5.1_2.6.27_cortex-a9-rhel4/i686/bin/armv7a-mediatek451_001_vfp-linux-gnueabi- +endif +ifeq "$(CC)" "gcc" +CC ?= $(CROSS_COMPILE)gcc +endif +$(warning =============================================) +$(warning wifi driver LINUX_SRC=$(LINUX_SRC)) +$(warning CROSS_COMPILE=$(CROSS_COMPILE)) +$(warning =============================================) + +DRIVER_DIR=$(LINUX_ROOT)/third_party/source/wlan/mtk/$(WIFI_TARGET) + +endif +#- - - - -- - - - - - - - - - +# MT53XX end +#- - - - -- - - - - - - - - - + + +############################################################## +# Compile options +############################################################## +#/***** Common part ******/ + +# Define maximum different channels supported for ieee80211_iface_combination setting. +CFG_NUM_DIFFERENT_CHANNELS_STA=1 +CFG_NUM_DIFFERENT_CHANNELS_P2P=1 + +# Define initial driver running mode. +# 0=RUNNING_P2P_MODE, 1=RUNNING_AP_MODE, 2=RUNNING_DUAL_AP_MODE, 3=RUNNING_P2P_AP_MODE +CFG_DRIVER_INITIAL_RUNNING_MODE=3 + +# Define to enable Android wake_lock +CFG_ENABLE_WAKE_LOCK=0 + +CFG_DEFAULT_DBG_LEVEL=0xF + +CFG_TX_DIRECT_USB=0 + +CFG_RX_DIRECT_USB=0 + +CFG_USB_REQ_TX_DATA_FFA_CNT=6 + +CFG_USB_REQ_TX_DATA_CNT=2 + +CFG_USB_REQ_RX_DATA_CNT=4 + +CFG_ENABLE_EFUSE_MAC_ADDR=1 + +# Report all bss networks to cfg80211 when do p2p scan +CFG_P2P_SCAN_REPORT_ALL_BSS=0 + +# Support to change sta, p2p, ap interface names +# y: enable, n: disable +# eg. insmod wlan_mt76x8_usb.ko sta=wlan p2p=p2p ap=ap +CFG_DRIVER_INF_NAME_CHANGE=n + +# 1: Enable SDIO RX Tasklet De-Aggregation +# 0: Disable (default) +CFG_SDIO_RX_AGG_TASKLET=0 + +#CFG_SUPPORT_SINGLE_SKU_LOCAL_DB=0 + +#/***** Platform dependent part ******/ +ifeq ($(PLATFORM),MT53XX) +CFG_SUPPORT_ROAMING=0 +endif + +# For wpa_supplicant w/o MTK priv lib +# y: enable, n: disable +CFG_ANDROID_AOSP_PRIV_CMD=n + +#/***** Manage configs into compile options ******/ +ifneq ($(CFG_NUM_DIFFERENT_CHANNELS_STA),) +PLATFORM_FLAGS += -DCFG_NUM_DIFFERENT_CHANNELS_STA=$(CFG_NUM_DIFFERENT_CHANNELS_STA) +endif + +ifneq ($(CFG_NUM_DIFFERENT_CHANNELS_P2P),) +PLATFORM_FLAGS += -DCFG_NUM_DIFFERENT_CHANNELS_P2P=$(CFG_NUM_DIFFERENT_CHANNELS_P2P) +endif + +ifneq ($(CFG_DRIVER_INITIAL_RUNNING_MODE),) +PLATFORM_FLAGS += -DCFG_DRIVER_INITIAL_RUNNING_MODE=$(CFG_DRIVER_INITIAL_RUNNING_MODE) +endif + +ifneq ($(CFG_ENABLE_WAKE_LOCK),) +PLATFORM_FLAGS += -DCFG_ENABLE_WAKE_LOCK=$(CFG_ENABLE_WAKE_LOCK) +endif + +ifneq ($(CFG_DEFAULT_DBG_LEVEL),) +PLATFORM_FLAGS += -DCFG_DEFAULT_DBG_LEVEL=$(CFG_DEFAULT_DBG_LEVEL) +endif + +ifneq ($(CFG_TX_DIRECT_USB),) +PLATFORM_FLAGS += -DCFG_TX_DIRECT_USB=$(CFG_TX_DIRECT_USB) +endif + +ifneq ($(CFG_RX_DIRECT_USB),) +PLATFORM_FLAGS += -DCFG_RX_DIRECT_USB=$(CFG_RX_DIRECT_USB) +endif + +ifneq ($(CFG_USB_REQ_TX_DATA_FFA_CNT),) +PLATFORM_FLAGS += -DCFG_USB_REQ_TX_DATA_FFA_CNT=$(CFG_USB_REQ_TX_DATA_FFA_CNT) +endif + +ifneq ($(CFG_USB_REQ_TX_DATA_CNT),) +PLATFORM_FLAGS += -DCFG_USB_REQ_TX_DATA_CNT=$(CFG_USB_REQ_TX_DATA_CNT) +endif + +ifneq ($(CFG_USB_REQ_RX_DATA_CNT),) +PLATFORM_FLAGS += -DCFG_USB_REQ_RX_DATA_CNT=$(CFG_USB_REQ_RX_DATA_CNT) +endif + +ifneq ($(CFG_ENABLE_EFUSE_MAC_ADDR),) +PLATFORM_FLAGS += -DCFG_ENABLE_EFUSE_MAC_ADDR=$(CFG_ENABLE_EFUSE_MAC_ADDR) +endif + +ifeq ($(CFG_DRIVER_INF_NAME_CHANGE), y) +PLATFORM_FLAGS += -DCFG_DRIVER_INF_NAME_CHANGE +endif + +ifneq ($(CFG_P2P_SCAN_REPORT_ALL_BSS),) +PLATFORM_FLAGS += -DCFG_P2P_SCAN_REPORT_ALL_BSS=$(CFG_P2P_SCAN_REPORT_ALL_BSS) +endif + +ifneq ($(CFG_SUPPORT_ROAMING),) +PLATFORM_FLAGS += -DCFG_SUPPORT_ROAMING=$(CFG_SUPPORT_ROAMING) +endif + +ifeq ($(CFG_ANDROID_AOSP_PRIV_CMD), y) +PLATFORM_FLAGS += -DCFG_ANDROID_AOSP_PRIV_CMD +endif + +ifneq ($(CFG_SDIO_RX_AGG_TASKLET),) +PLATFORM_FLAGS += -DCFG_SDIO_RX_AGG_TASKLET=$(CFG_SDIO_RX_AGG_TASKLET) +endif + +############################################################## +# Compile settings +############################################################## + +all: driver + +driver: + +cd $(DRIVER_DIR) && make -C $(LINUX_SRC) M=$(DRIVER_DIR) MODULE_NAME=$(MODULE_NAME) PLATFORM_FLAGS="$(PLATFORM_FLAGS)" modules +ifeq ($(PLATFORM),MT53XX) +ifeq ($(DRIVER_PARTIAL_BUILD), y) + @cd $(DRIVER_DIR) && $(CROSS_COMPILE)strip --strip-unneeded $(MODULE_NAME).ko +else +ifneq ($(ANDROID),true) + if [ ! -d $(THIRDPARTY_LIB_ROOT)/wlan/$(KERNEL_VER_FOR_3RD)/mtk/$(WIFI_TARGET) ]; then \ + mkdir -p $(THIRDPARTY_LIB_ROOT)/wlan/$(KERNEL_VER_FOR_3RD)/mtk/$(WIFI_TARGET)/; \ + fi + cp -f $(OUT_STA_KO) $(THIRDPARTY_LIB_ROOT)/wlan/$(KERNEL_VER_FOR_3RD)/mtk/$(WIFI_TARGET)/$(MODULE_NAME).ko +else +ifeq "$(BUILD_CFG)" "debug" + echo "ANDROID_VERSION=$(ANDROID_VERSION)" + if [ ! -d $(LINUX_ROOT)/../android/$(ANDROID_VERSION)/vendor/mediatek/open/hardware/prebuilt/wifi/$(ANDROID_IC_SETTING)/dbg ]; then \ + mkdir -p $(LINUX_ROOT)/../android/$(ANDROID_VERSION)/vendor/mediatek/open/hardware/prebuilt/wifi/$(ANDROID_IC_SETTING)/dbg; \ + fi + cp -f $(OUT_STA_KO) $(LINUX_ROOT)/../android/$(ANDROID_VERSION)/vendor/mediatek/open/hardware/prebuilt/wifi/$(ANDROID_IC_SETTING)/dbg/$(MODULE_NAME).ko + + if [ -d $(OUTPUT_ROOT)/basic/modules ]; then \ + cp -f $(OUT_STA_KO) $(OUTPUT_ROOT)/basic/modules/wlan.ko; \ + fi +else + if [ ! -d $(LINUX_ROOT)/../android/$(ANDROID_VERSION)/vendor/mediatek/open/hardware/prebuilt/wifi/$(ANDROID_IC_SETTING) ]; then \ + mkdir -p $(LINUX_ROOT)/../android/$(ANDROID_VERSION)/vendor/mediatek/open/hardware/prebuilt/wifi/$(ANDROID_IC_SETTING); \ + fi + cp -f $(OUT_STA_KO) $(LINUX_ROOT)/../android/$(ANDROID_VERSION)/vendor/mediatek/open/hardware/prebuilt/wifi/$(ANDROID_IC_SETTING)/$(MODULE_NAME).ko + + if [ -d $(OUTPUT_ROOT)/basic/modules ]; then \ + cp -f $(OUT_STA_KO) $(OUTPUT_ROOT)/basic/modules/wlan.ko; \ + fi +endif +endif +endif +endif +# @cd $(DRIVER_DIR) && cp $(MODULES_NAME)_$(HIF).ko $(MODULES_NAME).ko + +#common: +# +cd $(COMMON_DIR) && make -C $(LINUX_SRC) M=$(COMMON_DIR) modules +# @cat $(COMMON_DIR)/Module.symvers >> $(LINUX_SRC)/Module.symvers + +clean: driver_clean + +#symvers_clean: driver_clean +# @cp $(LINUX_SRC)/Module.symvers.original $(LINUX_SRC)/Module.symvers + +driver_clean: + cd $(DRIVER_DIR) && make -C $(LINUX_SRC) M=$(DRIVER_DIR) MODULE_NAME=$(MODULE_NAME) clean + if [ -e $(DRIVER_DIR)/$(MODULE_NAME).ko ]; then rm $(DRIVER_DIR)/$(MODULE_NAME).ko; fi; + +#common_clean: +# cd $(COMMON_DIR) && make -C $(LINUX_SRC) M=$(COMMON_DIR) clean + +.PHONY: all clean driver driver_clean + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/Makefile.none b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/Makefile.none new file mode 100644 index 0000000000000..77b8ecd2f6a29 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/Makefile.none @@ -0,0 +1,217 @@ +# Makefile.none: Makefile for build without linux kernel only gcc +# hif = virtual, empty hif +# Examples: +# - Default=wlan_mt6632_virtual: +# make -f Makefile.none +# - wlan_mt7663_virtual: +# make -f Makefile.none MTK_COMBO_CHIP=MT7663 +# Note: Chip ID must be uppercase. E.g., MT7663 + +src=$(shell pwd) +DRIVER_DIR=$(src) +# compiler choosing +#CROSS_CC = /mtkoss/gcc-arm-none-eabi/6-2017q2 +#CC_INCLUDE := $(CROSS_CC)/arm-none-eabi/include +#CC_BIN := $(CROSS_CC)/bin/ +#BIN_PREFIX := arm-none-eabi- +CC := $(CC_BIN)$(BIN_PREFIX)gcc + +# CFLAGS initial +# by pass undefined reference for linker +#CFLAGS := -Wl,--warn-unresolved-symbols +#CFLAGS := -Wfatal-errors -Wall +#CFLAGS := -Wall +CFLAGS := -Wl,--warn-once +#-Wimplicit -O -Wstrict-aliasing=2 +#CFLAGS += -Wshadow # Local variable is shadow by other local var +# CFG_REMIND_IMPLEMENT: +# flag for change header file prototype to define +# to remind user of driver who port this driver to other os +# need to implement the function +CFLAGS += -DCFG_REMIND_IMPLEMENT +CFLAGS += -DCFG_VIRTUAL_OS + +# default include path for standard library +# refer to the define in Linux Makefile +# LINUX_SRC=/lib/modules/$(shell uname -r)/build +# /lib is server dependent +# /usr/include should be fine +CFLAGS += -I$(CC_INCLUDE) +#CFLAGS += -I/usr/include + +# Build driver default option +hif := none +MTK_COMBO_CHIP := MT6632 + +export MTK_COMBO_CHIP +export CONFIG_MTK_COMBO_PLATFORM=x86 +export CONFIG_MTK_WIFI_ONLY=m +export CONFIG_MTK_COMBO=m +export CONFIG_MTK_COMBO_WIFI=m +export CONFIG_MTK_COMBO_COMM=m +export CONFIG_MTK_COMBO_COMM_UART=m +export CONFIG_MTK_COMBO_COMM_SDIO=m +export CONFIG_MT_WIFI_CHRDEV=m +#export MTK_WLAN_SERVICE_PATH=../../wlan_service/ + +MODULES_NAME := wlan_$(shell echo $(word 1, $(MTK_COMBO_CHIP)) | tr A-Z a-z) + +export CONFIG_MTK_COMBO_WIFI_HIF=$(hif) + +export CONFIG_MTK_COMBO_PLAT_PATH=x86 + +export CONFIG_MTK_SUPPORT_OS=none + +# leverage Makefile for common build option +include Makefile + +############################################################## +# Compile options +############################################################## +#/***** Common part ******/ + +# Define maximum different channels supported for ieee80211_iface_combination setting. +#CFG_NUM_DIFFERENT_CHANNELS_STA=1 +#CFG_NUM_DIFFERENT_CHANNELS_P2P=1 + +# Define initial driver running mode. +# 0=RUNNING_P2P_MODE, 1=RUNNING_AP_MODE, 2=RUNNING_DUAL_AP_MODE, 3=RUNNING_P2P_AP_MODE +#CFG_DRIVER_INITIAL_RUNNING_MODE=3 + +# Define to enable Android wake_lock +#CFG_ENABLE_WAKE_LOCK=0 + +# For wpa_supplicant w/o MTK priv lib +# y: enable, n: disable +CFG_ANDROID_AOSP_PRIV_CMD=n + +#CFG_DEFAULT_DBG_LEVEL=0xF + +CFG_TX_DIRECT_USB=1 + +CFG_RX_DIRECT_USB=1 + +CFG_USB_REQ_TX_DATA_FFA_CNT=10 + +CFG_USB_REQ_TX_DATA_CNT=2 + +CFG_USB_REQ_RX_DATA_CNT=2 + +#CFG_SUPPORT_DFS_MASTER=1 + +#CFG_SUPPORT_SINGLE_SKU_LOCAL_DB=0 + +# Report all bss networks to cfg80211 when do p2p scan +CFG_P2P_SCAN_REPORT_ALL_BSS=0 + +# Support to change sta, p2p, ap interface names +# y: enable, n: disable +# eg. insmod wlan_mt76x8_usb.ko sta=wlan p2p=p2p ap=ap +CFG_DRIVER_INF_NAME_CHANGE=n + +# Support firmware auto roaming +#CFG_SUPPORT_ROAMING=0 + +ifeq ($(CFG_ANDROID_AOSP_PRIV_CMD), y) +PLATFORM_FLAGS += -DCFG_ANDROID_AOSP_PRIV_CMD +endif + +# 1: Enable SDIO RX Tasklet De-Aggregation +# 0: Disable (default) +CFG_SDIO_RX_AGG_TASKLET=0 + +#/***** Manage configs into compile options ******/ +ifneq ($(CFG_NUM_DIFFERENT_CHANNELS_STA),) +PLATFORM_FLAGS += -DCFG_NUM_DIFFERENT_CHANNELS_STA=$(CFG_NUM_DIFFERENT_CHANNELS_STA) +endif + +ifneq ($(CFG_NUM_DIFFERENT_CHANNELS_P2P),) +PLATFORM_FLAGS += -DCFG_NUM_DIFFERENT_CHANNELS_P2P=$(CFG_NUM_DIFFERENT_CHANNELS_P2P) +endif + +ifneq ($(CFG_DRIVER_INITIAL_RUNNING_MODE),) +PLATFORM_FLAGS += -DCFG_DRIVER_INITIAL_RUNNING_MODE=$(CFG_DRIVER_INITIAL_RUNNING_MODE) +endif + +ifneq ($(CFG_ENABLE_WAKE_LOCK),) +PLATFORM_FLAGS += -DCFG_ENABLE_WAKE_LOCK=$(CFG_ENABLE_WAKE_LOCK) +endif + +ifneq ($(CFG_DEFAULT_DBG_LEVEL),) +PLATFORM_FLAGS += -DCFG_DEFAULT_DBG_LEVEL=$(CFG_DEFAULT_DBG_LEVEL) +endif + +ifneq ($(CFG_TX_DIRECT_USB),) +PLATFORM_FLAGS += -DCFG_TX_DIRECT_USB=$(CFG_TX_DIRECT_USB) +endif + +ifneq ($(CFG_RX_DIRECT_USB),) +PLATFORM_FLAGS += -DCFG_RX_DIRECT_USB=$(CFG_RX_DIRECT_USB) +endif + +ifneq ($(CFG_USB_REQ_TX_DATA_FFA_CNT),) +PLATFORM_FLAGS += -DCFG_USB_REQ_TX_DATA_FFA_CNT=$(CFG_USB_REQ_TX_DATA_FFA_CNT) +endif + +ifneq ($(CFG_USB_REQ_TX_DATA_CNT),) +PLATFORM_FLAGS += -DCFG_USB_REQ_TX_DATA_CNT=$(CFG_USB_REQ_TX_DATA_CNT) +endif + +ifneq ($(CFG_USB_REQ_RX_DATA_CNT),) +PLATFORM_FLAGS += -DCFG_USB_REQ_RX_DATA_CNT=$(CFG_USB_REQ_RX_DATA_CNT) +endif + +ifneq ($(CFG_SUPPORT_ROAMING),) +PLATFORM_FLAGS += -DCFG_SUPPORT_ROAMING=$(CFG_SUPPORT_ROAMING) +endif + +ifneq ($(CFG_SUPPORT_DFS_MASTER),) +PLATFORM_FLAGS += -DCFG_SUPPORT_DFS_MASTER=$(CFG_SUPPORT_DFS_MASTER) +endif + +ifneq ($(CFG_SUPPORT_SINGLE_SKU_LOCAL_DB),) +PLATFORM_FLAGS += -DCFG_SUPPORT_SINGLE_SKU_LOCAL_DB=$(CFG_SUPPORT_SINGLE_SKU_LOCAL_DB) +endif + +ifeq ($(CFG_DRIVER_INF_NAME_CHANGE), y) +PLATFORM_FLAGS += -DCFG_DRIVER_INF_NAME_CHANGE +endif + +ifneq ($(CFG_P2P_SCAN_REPORT_ALL_BSS),) +PLATFORM_FLAGS += -DCFG_P2P_SCAN_REPORT_ALL_BSS=$(CFG_P2P_SCAN_REPORT_ALL_BSS) +endif + +ifneq ($(CFG_SDIO_RX_AGG_TASKLET),) +PLATFORM_FLAGS += -DCFG_SDIO_RX_AGG_TASKLET=$(CFG_SDIO_RX_AGG_TASKLET) +endif + +ifeq ($(CONFIG_MTK_COMBO_PLATFORM), x86) +PLATFORM_FLAGS += -DCFG_BUILD_X86_PLATFORM +endif + +CFLAGS += $(ccflags-y) +CFLAGS += $(PLATFORM_FLAGS) + +OBJS = $($(MODULE_NAME)-objs) +TARGET = $(MODULES_NAME)_$(hif) + +$(info flags: $(CFLAGS)) +$(info CC: $(CC)) +$(info target: $(TARGET)) + +REBUILDABLES = $(OBJS) $(TARGET) + +all : $(TARGET) + @echo build pass + +$(TARGET) : $(OBJS) + @${CC} $(OBJS) $(CFLAGS) -o $@ +%.o : %.c + @echo [CC] $@ + @$(CC) -g -o $@ -c $< $(CFLAGS) + +clean : + @rm -f $(REBUILDABLES) + @echo clean + +.PHONY: clean all diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/Makefile.openwrt b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/Makefile.openwrt new file mode 100644 index 0000000000000..cefa9742fde41 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/Makefile.openwrt @@ -0,0 +1,654 @@ +# --------------------------------------------------- +# OS option +# --------------------------------------------------- +os=$(CONFIG_MTK_SUPPORT_OS) + +ifeq ($(os),) +os=linux +endif + +ifeq ($(os), none) +ccflags-y += -I/usr/include/ +ccflags-y += -DCFG_VIRTUAL_OS +ccflags-y += -DCFG_REMIND_IMPLEMENT +endif + +$(info os option: $(os)) +# --------------------------------------------------- +# ALPS Setting +# --------------------------------------------------- +ifneq ($(KERNEL_OUT),) + ccflags-y += -imacros $(KERNEL_OUT)/include/generated/autoconf.h +endif + +ifeq ($(KBUILD_MODPOST_FAIL_ON_WARNINGS),) + # Force build fail on modpost warning + KBUILD_MODPOST_FAIL_ON_WARNINGS=y +endif + +DRIVER_BUILD_DATE=$(shell date +%Y%m%d%H%M%S) +ccflags-y += -DDRIVER_BUILD_DATE='"$(DRIVER_BUILD_DATE)"' +# --------------------------------------------------- +# Compile Options +# --------------------------------------------------- + +#Bring up Openwrt Platform ==================================================== +ifeq ($(CONFIG_SUPPORT_OPENWRT),y) +ifeq ($(hif),) + hif=pcie +endif +WIFI_DRV_PATH := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))/.. +CONFIG_MTK_COMBO_WIFI_HIF=$(hif) +else +ifeq ($(CONFIG_DEFAULTS_KERNEL_4_4),y) +WIFI_DRV_PATH = drivers/net/wireless/mediatek +else +WIFI_DRV_PATH = drivers/net/wireless +endif +endif + +ccflags-y := -I$(WIFI_DRV_PATH)/gen4m/include \ + -I$(WIFI_DRV_PATH)/gen4m/os \ + -I$(WIFI_DRV_PATH)/gen4m/os/linux/include \ + -I$(WIFI_DRV_PATH)/gen4m/include/nic \ + -I$(WIFI_DRV_PATH)/gen4m/include/mgmt \ + -I$(WIFI_DRV_PATH)/gen4m/include/chips \ + -I$(WIFI_DRV_PATH)/gen4m/include/dvt \ + +MODULE_NAME = gen4m +SRC_DIR = ../gen4m + +ifeq ($(CONFIG_SUPPORT_OPENWRT),y) +ccflags-y += -DCONFIG_SUPPORT_OPENWRT +obj-m += $(MODULE_NAME).o +else +obj-$(CONFIG_GEN4M_SUPPORT) += $(MODULE_NAME).o +endif +#============================================================================== + +WLAN_CHIP_LIST:=-UMT6620 -UMT6628 -UMT5931 -UMT6630 -UMT6632 -UMT7663 -UCONNAC -UCONNAC2X2 -UUT_TEST_MODE -UMT7915 -USOC3_0 -UMT7961 +# '-D' and '-U' options are processed in the order they are given on the command line. +# All '-imacros file' and '-include file' options are processed after all '-D' and '-U' options. +ccflags-y += $(WLAN_CHIP_LIST) + +ifeq ($(MTK_COMBO_CHIP),) +MTK_COMBO_CHIP = MT7915 +endif + +$(info $$MTK_PLATFORM is [${MTK_PLATFORM}]) +$(info $$WLAN_CHIP_ID is [${WLAN_CHIP_ID}]) + +ifeq ($(WLAN_CHIP_ID),) +WLAN_CHIP_ID=$(word 1, $(MTK_COMBO_CHIP)) +endif + +ccflags-y += -DCFG_SUPPORT_DEBUG_FS=0 +ccflags-y += -DWLAN_INCLUDE_PROC +ccflags-y += -DCFG_SUPPORT_AGPS_ASSIST=0 +ccflags-y += -DCFG_SUPPORT_TSF_USING_BOOTTIME=1 +ccflags-y += -DARP_MONITER_ENABLE=1 +ccflags-y += -Werror +#ccflags-y:=$(filter-out -U$(WLAN_CHIP_ID),$(ccflags-y)) +#ccflags-y += -DLINUX -D$(WLAN_CHIP_ID) +#workaround: also needed for none LINUX system +# because some of common part code is surrounded with this flag +ccflags-y += -DLINUX + +ifneq ($(filter MT6632,$(MTK_COMBO_CHIP)),) +ccflags-y:=$(filter-out -UMT6632,$(ccflags-y)) +ccflags-y += -DMT6632 +endif + +ifneq ($(filter MT7668,$(MTK_COMBO_CHIP)),) +ccflags-y:=$(filter-out -UMT7668,$(ccflags-y)) +ccflags-y += -DMT7668 +endif + +ifneq ($(filter MT7663,$(MTK_COMBO_CHIP)),) +ccflags-y:=$(filter-out -UMT7663,$(ccflags-y)) +ccflags-y += -DMT7663 +endif + +ifneq ($(filter CONNAC,$(MTK_COMBO_CHIP)),) +ccflags-y:=$(filter-out -UCONNAC,$(ccflags-y)) +ccflags-y += -DCONNAC +endif + +ifneq ($(filter CONNAC2X2,$(MTK_COMBO_CHIP)),) +ccflags-y:=$(filter-out -UCONNAC2X2,$(ccflags-y)) +ccflags-y += -DCONNAC2X2 +endif + +ifneq ($(findstring MT7915,$(MTK_COMBO_CHIP)),) +ccflags-y:=$(filter-out -UMT7915,$(ccflags-y)) +ccflags-y += -DMT7915 +CONFIG_MTK_WIFI_CONNAC2X=y +CONFIG_MTK_WIFI_11AX_SUPPORT=y +CONFIG_MTK_WIFI_TWT_SUPPORT=y +endif + +ifneq ($(findstring 3_0,$(MTK_COMBO_CHIP)),) +ccflags-y:=$(filter-out -USOC3_0,$(ccflags-y)) +ccflags-y += -DSOC3_0 +CONFIG_MTK_WIFI_CONNAC2X=y +CONFIG_MTK_WIFI_11AX_SUPPORT=y +CONFIG_MTK_WIFI_TWT_SUPPORT=y +endif + +ifneq ($(findstring MT7961,$(MTK_COMBO_CHIP)),) +ccflags-y:=$(filter-out -UMT7961,$(ccflags-y)) +ccflags-y += -DMT7961 +CONFIG_MTK_WIFI_CONNAC2X=y +CONFIG_MTK_WIFI_11AX_SUPPORT=y +CONFIG_MTK_WIFI_TWT_SUPPORT=y +endif + +ifeq ($(CONFIG_MTK_WIFI_CONNAC2X), y) + ccflags-y += -DCFG_SUPPORT_CONNAC2X=1 +else + ccflags-y += -DCFG_SUPPORT_CONNAC2X=0 +endif + +ifeq ($(CONFIG_MTK_WIFI_11AX_SUPPORT), y) + ccflags-y += -DCFG_SUPPORT_802_11AX=1 +else + ccflags-y += -DCFG_SUPPORT_802_11AX=0 +endif + +ifeq ($(CONFIG_MTK_WIFI_TWT_SUPPORT), y) + ccflags-y += -DCFG_SUPPORT_TWT=1 +else + ccflags-y += -DCFG_SUPPORT_TWT=0 +endif + +ifeq ($(WIFI_ENABLE_GCOV), y) +GCOV_PROFILE := y +endif + +ifeq ($(MTK_ANDROID_WMT), y) + ccflags-y += -DCFG_MTK_ANDROID_WMT=1 +else ifneq ($(filter MT6632,$(MTK_COMBO_CHIP)),) + ccflags-y += -DCFG_MTK_ANDROID_WMT=1 +else + ccflags-y += -DCFG_MTK_ANDROID_WMT=0 +endif + +ifeq ($(MTK_ANDROID_EMI), y) + ccflags-y += -DCFG_MTK_ANDROID_EMI=1 +else + ccflags-y += -DCFG_MTK_ANDROID_EMI=0 +endif + +ifneq ($(WIFI_IP_SET),) + ccflags-y += -DCFG_WIFI_IP_SET=$(WIFI_IP_SET) +else + ccflags-y += -DCFG_WIFI_IP_SET=1 +endif + +ifneq ($(filter MTK_WCN_REMOVE_KERNEL_MODULE,$(KBUILD_SUBDIR_CCFLAGS)),) + ccflags-y += -DCFG_BUILT_IN_DRIVER=1 +else + ccflags-y += -DCFG_BUILT_IN_DRIVER=0 +endif + +ifneq ($(findstring UT_TEST_MODE,$(MTK_COMBO_CHIP)),) +ccflags-y:=$(filter-out -UUT_TEST_MODE,$(ccflags-y)) +ccflags-y += -DUT_TEST_MODE +endif + +CONFIG_MTK_WIFI_MCC_SUPPORT=y +ifeq ($(CONFIG_MTK_WIFI_MCC_SUPPORT), y) + ccflags-y += -DCFG_SUPPORT_CHNL_CONFLICT_REVISE=0 +else + ccflags-y += -DCFG_SUPPORT_CHNL_CONFLICT_REVISE=1 +endif + +ifeq ($(CONFIG_MTK_AEE_FEATURE), y) + ccflags-y += -DCFG_SUPPORT_AEE=1 +else + ccflags-y += -DCFG_SUPPORT_AEE=0 +endif + +# Disable ASSERT() for user load, enable for others +ifneq ($(TARGET_BUILD_VARIANT),user) + ccflags-y += -DBUILD_QA_DBG=1 +else + ccflags-y += -DBUILD_QA_DBG=0 +endif + +ifeq ($(CONFIG_MTK_COMBO_WIFI),y) + ccflags-y += -DCFG_WPS_DISCONNECT=1 +endif + +ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), sdio) + ccflags-y += -D_HIF_SDIO=1 +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), pcie) + ccflags-y += -D_HIF_PCIE=1 +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), usb) + ccflags-y += -D_HIF_USB=1 +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), axi) + ccflags-y += -D_HIF_AXI=1 +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), ut) + # Increase frame size to 2048 because of 'cfg80211_connect_result' exceed stack size + ccflags-y += -D_HIF_UT=1 -Wno-unused-function -Wno-unused-variable -Wframe-larger-than=2048 +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), none) + ccflags-y += -D_HIF_NONE=1 +else + $(error Unsuppoted HIF=$(CONFIG_MTK_COMBO_WIFI_HIF)!!) +endif + +ifeq ($(CONFIG_MTK_WIFI_POWER_ON_DOWNLOAD_EMI_ROM_PATCH), y) + ccflags-y += -DCFG_POWER_ON_DOWNLOAD_EMI_ROM_PATCH=1 +else + ccflags-y += -DCFG_POWER_ON_DOWNLOAD_EMI_ROM_PATCH=0 +endif + +ifeq ($(CONFIG_MTK_WIFI_DOWNLOAD_DYN_MEMORY_MAP), y) + ccflags-y += -DCFG_DOWNLOAD_DYN_MEMORY_MAP=1 +else + ccflags-y += -DCFG_DOWNLOAD_DYN_MEMORY_MAP=0 +endif + +ifeq ($(CONFIG_MTK_WIFI_ROM_PATCH_NO_SEM_CTRL), y) + ccflags-y += -DCFG_ROM_PATCH_NO_SEM_CTRL=1 +else + ccflags-y += -DCFG_ROM_PATCH_NO_SEM_CTRL=0 +endif + +ifneq ($(CFG_CFG80211_VERSION),) +VERSION_STR = $(subst \",,$(subst ., , $(subst -, ,$(subst v,,$(CFG_CFG80211_VERSION))))) +$(info VERSION_STR=$(VERSION_STR)) +X = $(firstword $(VERSION_STR)) +Y = $(word 2 ,$(VERSION_STR)) +Z = $(word 3 ,$(VERSION_STR)) +VERSION := $(shell echo "$$(( $X * 65536 + $Y * 256 + $Z))" ) +ccflags-y += -DCFG_CFG80211_VERSION=$(VERSION) +$(info DCFG_CFG80211_VERSION=$(VERSION)) +endif + + +ifeq ($(CONFIG_MTK_PASSPOINT_R2_SUPPORT), y) + ccflags-y += -DCFG_SUPPORT_PASSPOINT=1 + ccflags-y += -DCFG_HS20_DEBUG=1 + ccflags-y += -DCFG_ENABLE_GTK_FRAME_FILTER=1 +else + ccflags-y += -DCFG_SUPPORT_PASSPOINT=0 + ccflags-y += -DCFG_HS20_DEBUG=0 + ccflags-y += -DCFG_ENABLE_GTK_FRAME_FILTER=0 +endif + +MTK_MET_PROFILING_SUPPORT = yes +ifeq ($(MTK_MET_PROFILING_SUPPORT), yes) + ccflags-y += -DCFG_MET_PACKET_TRACE_SUPPORT=1 +else + ccflags-y += -DCFG_MET_PACKET_TRACE_SUPPORT=0 +endif + +MTK_MET_TAG_SUPPORT = no +ifeq ($(MTK_MET_TAG_SUPPORT), yes) + ccflags-y += -DMET_USER_EVENT_SUPPORT + ccflags-y += -DCFG_MET_TAG_SUPPORT=1 +else + ccflags-y += -DCFG_MET_TAG_SUPPORT=0 +endif + +ifeq ($(CONFIG_MTK_TC10_FEATURE), y) + ccflags-y += -DCFG_TC10_FEATURE=1 +else + ccflags-y += -DCFG_TC10_FEATURE=0 +endif + +ifeq ($(CONFIG_MTK_TC1_FEATURE), y) + ccflags-y += -I$(srctree)/drivers/misc/mediatek/tc1_interface + ccflags-y += -DCFG_TC1_FEATURE=1 +else + ccflags-y += -DCFG_TC1_FEATURE=0 +endif + +ccflags-y += -DDBG=0 +ccflags-y += -I$(src)/os -I$(src)/os/$(os)/include +ccflags-y += -I$(src)/include -I$(src)/include/nic -I$(src)/include/mgmt -I$(src)/include/chips +ifeq ($(CFG_SUPPORT_WIFI_SYSDVT), 1) +ccflags-y += -I$(src)/include/dvt +endif +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/performance/include/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/emi/$(MTK_PLATFORM) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/emi/submodule +ccflags-y += -I$(srctree)/drivers/devfreq/ +ccflags-y += -I$(srctree)/net + +ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), sdio) +ccflags-y += -I$(src)/os/$(os)/hif/sdio/include +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), pcie) +ccflags-y += -I$(src)/os/$(os)/hif/common/include +ccflags-y += -I$(src)/os/$(os)/hif/pcie/include +ifneq ($(findstring 3_0,$(MTK_COMBO_CHIP)),) +ccflags-y += -I$(src)/include/chips/coda/soc3_0 +endif +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), axi) +ccflags-y += -I$(src)/os/$(os)/hif/common/include +ccflags-y += -I$(src)/os/$(os)/hif/axi/include +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), usb) +ccflags-y += -I$(src)/os/$(os)/hif/usb/include +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), ut) +ccflags-y += -I$(src)/test -I$(src)/test/lib/include -I$(src)/test/testcases -I$(src)/test/lib/hif +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), none) +ccflags-y += -I$(src)/os/$(os)/hif/none/include +endif + +ifneq ($(PLATFORM_FLAGS), ) + ccflags-y += $(PLATFORM_FLAGS) +endif + +ifeq ($(CONFIG_MTK_WIFI_ONLY),$(filter $(CONFIG_MTK_WIFI_ONLY),m y)) +obj-$(CONFIG_MTK_WIFI_ONLY) += $(MODULE_NAME).o +else +obj-$(CONFIG_MTK_COMBO_WIFI) += $(MODULE_NAME).o +#obj-y += $(MODULE_NAME).o +endif + +ifeq ($(CONFIG_WLAN_DRV_BUILD_IN),y) +$(warning $(MODULE_NAME) build-in boot.img) +obj-y += $(MODULE_NAME).o +else +$(warning $(MODULE_NAME) is kernel module) +obj-m += $(MODULE_NAME).o +endif + +# --------------------------------------------------- +# Directory List +# --------------------------------------------------- +COMMON_DIR := common/ +OS_DIR := os/$(os)/ +HIF_COMMON_DIR := $(OS_DIR)hif/common/ +ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), sdio) +HIF_DIR := os/$(os)/hif/sdio/ +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), pcie) +HIF_DIR := os/$(os)/hif/pcie/ +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), axi) +HIF_DIR := os/$(os)/hif/axi/ +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), usb) +HIF_DIR := os/$(os)/hif/usb/ +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), ut) +HIF_DIR := test/lib/hif/ +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), none) +HIF_DIR := os/$(os)/hif/none/ +endif +NIC_DIR := nic/ +MGMT_DIR := mgmt/ +CHIPS := chips/ +CHIPS_CMM := $(CHIPS)common/ + +ifneq ($(MTK_PLATFORM),) +PLAT_DIR := os/$(os)/plat/$(MTK_PLATFORM)/ +endif +SYSDVT_DIR := dvt/ + +# --------------------------------------------------- +# Objects List +# --------------------------------------------------- + +COMMON_OBJS := $(COMMON_DIR)dump.o \ + $(COMMON_DIR)wlan_lib.o \ + $(COMMON_DIR)wlan_oid.o \ + $(COMMON_DIR)wlan_bow.o \ + $(COMMON_DIR)debug.o + +NIC_OBJS := $(NIC_DIR)nic.o \ + $(NIC_DIR)nic_tx.o \ + $(NIC_DIR)nic_txd_v1.o \ + $(NIC_DIR)nic_rxd_v1.o \ + $(NIC_DIR)nic_rx.o \ + $(NIC_DIR)nic_pwr_mgt.o \ + $(NIC_DIR)nic_rate.o \ + $(NIC_DIR)cmd_buf.o \ + $(NIC_DIR)que_mgt.o \ + $(NIC_DIR)nic_cmd_event.o \ + $(NIC_DIR)nic_umac.o + +ifeq ($(os), none) +OS_OBJS := $(OS_DIR)gl_dependent.o \ + $(OS_DIR)gl_init.o \ + $(OS_DIR)gl_kal.o \ + $(OS_DIR)gl_ate_agent.o \ + $(OS_DIR)gl_qa_agent.o +else +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_ate_agent.o \ + $(OS_DIR)gl_qa_agent.o \ + $(OS_DIR)gl_hook_api.o \ + $(OS_DIR)gl_rst.o \ + $(OS_DIR)gl_cfg80211.o \ + $(OS_DIR)gl_proc.o \ + $(OS_DIR)gl_vendor.o \ + $(OS_DIR)platform.o +endif + +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)reg_rule.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)scan_cache.o \ + $(MGMT_DIR)swcr.o \ + $(MGMT_DIR)roaming_fsm.o \ + $(MGMT_DIR)tkip_mic.o \ + $(MGMT_DIR)hs20.o \ + $(MGMT_DIR)tdls.o \ + $(MGMT_DIR)wnm.o \ + $(MGMT_DIR)qosmap.o \ + $(MGMT_DIR)ap_selection.o \ + $(MGMT_DIR)wmm.o + +# --------------------------------------------------- +# Chips Objects List +# --------------------------------------------------- +MGMT_OBJS += $(MGMT_DIR)stats.o + + +CHIPS_OBJS += $(CHIPS_CMM)cmm_asic_connac.o +CHIPS_OBJS += $(CHIPS_CMM)dbg_connac.o +ifeq ($(CONFIG_MTK_WIFI_CONNAC2X), y) +CHIPS_OBJS += $(CHIPS_CMM)dbg_connac2x.o +endif + +ifeq ($(CONFIG_MTK_WIFI_CONNAC2X), y) +CHIPS_OBJS += $(CHIPS_CMM)cmm_asic_connac2x.o +NIC_OBJS += $(NIC_DIR)nic_ext_cmd_event.o \ + $(NIC_DIR)nic_txd_v2.o \ + $(NIC_DIR)nic_rxd_v2.o +endif +CHIPS_OBJS += $(CHIPS_CMM)fw_dl.o + +ifneq ($(filter MT6632,$(MTK_COMBO_CHIP)),) +CHIPS_OBJS += $(CHIPS)mt6632/mt6632.o +endif +ifneq ($(filter MT7668,$(MTK_COMBO_CHIP)),) +CHIPS_OBJS += $(CHIPS)mt7668/mt7668.o +endif +ifneq ($(filter MT7663,$(MTK_COMBO_CHIP)),) +CHIPS_OBJS += $(CHIPS)mt7663/mt7663.o +endif +ifneq ($(filter CONNAC,$(MTK_COMBO_CHIP)),) +CHIPS_OBJS += $(CHIPS)connac/connac.o +endif +ifneq ($(filter CONNAC2X2,$(MTK_COMBO_CHIP)),) +CHIPS_OBJS += $(CHIPS)connac2x2/connac2x2.o +endif +ifneq ($(findstring MT7915,$(MTK_COMBO_CHIP)),) +CHIPS_OBJS += $(CHIPS)mt7915/mt7915.o +CHIPS_OBJS += $(CHIPS)mt7915/dbg_mt7915.o +endif +ifneq ($(findstring 3_0,$(MTK_COMBO_CHIP)),) +CHIPS_OBJS += $(CHIPS)soc3_0/soc3_0.o +endif +ifneq ($(findstring MT7961,$(MTK_COMBO_CHIP)),) +CHIPS_OBJS += $(CHIPS)mt7961/mt7961.o +endif + +# --------------------------------------------------- +# P2P Objects List +# --------------------------------------------------- + +COMMON_OBJS += $(COMMON_DIR)wlan_p2p.o + +NIC_OBJS += $(NIC_DIR)p2p_nic.o + +ifneq ($(os), none) +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 +endif + +MGMT_OBJS += $(MGMT_DIR)p2p_dev_fsm.o\ + $(MGMT_DIR)p2p_dev_state.o\ + $(MGMT_DIR)p2p_role_fsm.o\ + $(MGMT_DIR)p2p_role_state.o\ + $(MGMT_DIR)p2p_func.o\ + $(MGMT_DIR)p2p_scan.o\ + $(MGMT_DIR)p2p_ie.o\ + $(MGMT_DIR)p2p_rlm.o\ + $(MGMT_DIR)p2p_assoc.o\ + $(MGMT_DIR)p2p_bss.o\ + $(MGMT_DIR)p2p_rlm_obss.o\ + $(MGMT_DIR)p2p_fsm.o + +MGMT_OBJS += $(MGMT_DIR)wapi.o + +# --------------------------------------------------- +# HE Objects List +# --------------------------------------------------- + +COMMON_OBJS += $(COMMON_DIR)wlan_he.o + +ifeq ($(CONFIG_MTK_WIFI_11AX_SUPPORT), y) +MGMT_OBJS += $(MGMT_DIR)he_ie.o \ + $(MGMT_DIR)he_rlm.o +endif + +ifeq ($(CONFIG_MTK_WIFI_TWT_SUPPORT), y) +MGMT_OBJS += $(MGMT_DIR)twt_req_fsm.o \ + $(MGMT_DIR)twt.o \ + $(MGMT_DIR)twt_planner.o +endif + +ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), sdio) +HIF_OBJS := $(HIF_DIR)arm.o \ + $(HIF_DIR)sdio.o \ + $(HIF_DIR)hal_api.o \ + $(HIF_DIR)sdio_test_driver_core.o \ + $(HIF_DIR)sdio_test_driver_ops.o +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), pcie) +HIF_OBJS := $(HIF_COMMON_DIR)hal_pdma.o \ + $(HIF_COMMON_DIR)kal_pdma.o \ + $(HIF_COMMON_DIR)dbg_pdma.o \ + $(HIF_DIR)pcie.o +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), axi) +HIF_OBJS := $(HIF_COMMON_DIR)hal_pdma.o \ + $(HIF_COMMON_DIR)kal_pdma.o \ + $(HIF_COMMON_DIR)dbg_pdma.o \ + $(HIF_DIR)axi.o +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), usb) +HIF_OBJS := $(HIF_DIR)usb.o \ + $(HIF_DIR)hal_api.o +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), ut) +HIF_OBJS := $(HIF_DIR)ut.o \ + $(HIF_DIR)hal_api.o +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), none) +HIF_OBJS := $(HIF_DIR)none.o +endif +# --------------------------------------------------- +# Platform Objects List +# --------------------------------------------------- +ifneq ($(MTK_PLATFORM),) + +PLAT_PRIV_C = $(src)/$(PLAT_DIR)plat_priv.c + +# search path (out of kernel tree) +IS_EXIST_PLAT_PRIV_C := $(wildcard $(PLAT_PRIV_C)) +# search path (build-in kernel tree) +IS_EXIST_PLAT_PRIV_C += $(wildcard $(srctree)/$(PLAT_PRIV_C)) + +ifneq ($(strip $(IS_EXIST_PLAT_PRIV_C)),) +PLAT_OBJS := $(PLAT_DIR)plat_priv.o +$(MODULE_NAME)-objs += $(PLAT_OBJS) +endif +endif + +# --------------------------------------------------- +# System Dvt Objects List +# --------------------------------------------------- +ifeq ($(CFG_SUPPORT_WIFI_SYSDVT), 1) +SYSDVT_OBJS += $(SYSDVT_DIR)dvt_common.o + +ifeq ($(CFG_SUPPORT_DMASHDL_SYSDVT), 1) +SYSDVT_OBJS += $(SYSDVT_DIR)dvt_dmashdl.o +endif +endif + +# --------------------------------------------------- +# Service git List +# --------------------------------------------------- +SERVICE_DIR := wlan_service/ + +ifneq ($(findstring wlan_service,$(MTK_WLAN_SERVICE_PATH)),) +MTK_WLAN_SERVICE=yes +SERVICE_DIR := $(MTK_WLAN_SERVICE_PATH) +$(info SERVICE_DIR is [{$(MTK_WLAN_SERVICE_PATH)}]) +endif + +ifeq ($(MTK_WLAN_SERVICE), yes) +ccflags-y += -DCONFIG_WLAN_SERVICE=1 +ccflags-y += -DCONFIG_TEST_ENGINE_OFFLOAD=1 +ccflags-y += -I$(src)/$(SERVICE_DIR)include +ccflags-y += -I$(src)/$(SERVICE_DIR)service/include +ccflags-y += -I$(src)/$(SERVICE_DIR)glue/osal/include +ccflags-y += -I$(src)/$(SERVICE_DIR)glue/hal/include +$(info $$CCFLAG is [{$(ccflags-y)}]) +SERVICE_OBJS := $(SERVICE_DIR)agent/agent.o \ + $(SERVICE_DIR)service/service_test.o \ + $(SERVICE_DIR)service/test_engine.o \ + $(SERVICE_DIR)glue/osal/gen4m/sys_adaption_gen4m.o \ + $(SERVICE_DIR)glue/osal/gen4m/net_adaption_gen4m.o \ + $(SERVICE_DIR)glue/hal/gen4m/operation_gen4m.o +$(MODULE_NAME)-objs += $(SERVICE_OBJS) +$(info $$MTK_WLAN_SERVICE is [{$(SERVICE_OBJS)}]) +else +ccflags-y += -DCONFIG_WLAN_SERVICE=0 +ccflags-y += -DCONFIG_TEST_ENGINE_OFFLOAD=0 +endif + +$(MODULE_NAME)-objs += $(COMMON_OBJS) +$(MODULE_NAME)-objs += $(NIC_OBJS) +$(MODULE_NAME)-objs += $(OS_OBJS) +$(MODULE_NAME)-objs += $(HIF_OBJS) +$(MODULE_NAME)-objs += $(MGMT_OBJS) +$(MODULE_NAME)-objs += $(CHIPS_OBJS) +$(MODULE_NAME)-objs += $(SYSDVT_OBJS) + +ifneq ($(findstring UT_TEST_MODE,$(MTK_COMBO_CHIP)),) +include $(src)/test/ut.make +endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/Makefile.x86 b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/Makefile.x86 new file mode 100644 index 0000000000000..6d5423f7b0b06 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/Makefile.x86 @@ -0,0 +1,218 @@ +# Makefile.x86: Makefile for Linux PC +# You can build specific .ko name by assiging the "MTK_COMBO_CHIP" and "hif" parameters +# hif = pcie or sdio or usb +# Examples: +# - Default=wlan_mt6632_pcie.ko: +# make -f Makefile.x86 +# - wlan_mt7663_usb.ko: +# make -f Makefile.x86 MTK_COMBO_CHIP=MT7663 hif=usb +# Note: Chip ID must be uppercase. E.g., MT7663 + +LINUX_SRC=/lib/modules/$(shell uname -r)/build + +export CONFIG_MTK_COMBO_PLATFORM=x86 +export MTK_COMBO_CHIP=MT6632 + +PWD=$(shell pwd) +DRIVER_DIR=$(PWD) + +export CONFIG_MTK_WIFI_ONLY=m +export CONFIG_MTK_COMBO=m +export CONFIG_MTK_COMBO_WIFI=m +export CONFIG_MTK_COMBO_COMM=m +export CONFIG_MTK_COMBO_COMM_UART=m +export CONFIG_MTK_COMBO_COMM_SDIO=m +export CONFIG_MT_WIFI_CHRDEV=m +ifneq (,$(wildcard ../../wlan_service/)) +export MTK_WLAN_SERVICE_PATH=../../wlan_service/ +endif +ifneq ($(BACKPORTED_KERNEL_VERSION),) +export CFG_CFG80211_VERSION ?= $(BACKPORTED_KERNEL_VERSION) +endif + +# pcie | sdio | usb | ut +ifeq ($(hif),) + hif=pcie +endif + +MODULES_NAME := wlan_$(shell echo $(word 1, $(MTK_COMBO_CHIP)) | tr A-Z a-z) + +export CONFIG_MTK_COMBO_WIFI_HIF=$(hif) + +export CONFIG_MTK_COMBO_PLAT_PATH=x86 + +#need to support these 3 CONFIG_ in Android.mk::Begin +export CONFIG_MTK_WIFI_POWER_ON_DOWNLOAD_EMI_ROM_PATCH=$(wifi_pwron_emi_patch_dl) + +export CONFIG_MTK_WIFI_DOWNLOAD_DYN_MEMORY_MAP=$(wifi_dl_dyn_mem_map) + +export CONFIG_MTK_WIFI_ROM_PATCH_NO_SEM_CTRL=$(wifi_rom_patch_no_sem_ctrl) +#need to support these 3 CONFIG_ in Android.mk::End + +############################################################## +# Compile options +############################################################## +#/***** Common part ******/ + +# Define maximum different channels supported for ieee80211_iface_combination setting. +#CFG_NUM_DIFFERENT_CHANNELS_STA=1 +#CFG_NUM_DIFFERENT_CHANNELS_P2P=1 + +# Define initial driver running mode. +# 0=RUNNING_P2P_MODE, 1=RUNNING_AP_MODE, 2=RUNNING_DUAL_AP_MODE, 3=RUNNING_P2P_AP_MODE +#CFG_DRIVER_INITIAL_RUNNING_MODE=3 + +# Define to enable Android wake_lock +#CFG_ENABLE_WAKE_LOCK=0 + +# For wpa_supplicant w/o MTK priv lib +# y: enable, n: disable +CFG_ANDROID_AOSP_PRIV_CMD=n + +#CFG_DEFAULT_DBG_LEVEL=0xF + +CFG_TX_DIRECT_USB=1 + +CFG_RX_DIRECT_USB=1 + +CFG_USB_REQ_TX_DATA_FFA_CNT=10 + +CFG_USB_REQ_TX_DATA_CNT=2 + +CFG_USB_REQ_RX_DATA_CNT=2 + +CFG_SYS_DVT_SUPPORT=0 + +CFG_SYS_DVT_DMASCHDL_SUPPORT=0 + +#CFG_SUPPORT_DFS_MASTER=1 + +#CFG_SUPPORT_SINGLE_SKU_LOCAL_DB=0 + +# Report all bss networks to cfg80211 when do p2p scan +CFG_P2P_SCAN_REPORT_ALL_BSS=0 + +# Support to change sta, p2p, ap interface names +# y: enable, n: disable +# eg. insmod wlan_mt76x8_usb.ko sta=wlan p2p=p2p ap=ap +CFG_DRIVER_INF_NAME_CHANGE=n + +# Support firmware auto roaming +#CFG_SUPPORT_ROAMING=0 + +ifeq ($(CFG_ANDROID_AOSP_PRIV_CMD), y) +PLATFORM_FLAGS += -DCFG_ANDROID_AOSP_PRIV_CMD +endif + +# 1: Enable SDIO RX Tasklet De-Aggregation +# 0: Disable (default) +CFG_SDIO_RX_AGG_TASKLET=0 + +# CFG_WIFI_WORKAROUND_HWITS00012836_WTBL_SEARCH_FAIL +ifeq ($(MTK_COMBO_CHIP), soc3_0) +CFG_WIFI_WORKAROUND_HWITS00012836_WTBL_SEARCH_FAIL=1 +endif + +#/***** Manage configs into compile options ******/ +ifneq ($(CFG_DFS_CHSW_FORCE_BW20),) +PLATFORM_FLAGS += -DCFG_DFS_CHSW_FORCE_BW20=$(CFG_DFS_CHSW_FORCE_BW20) +endif + +ifneq ($(CFG_NUM_DIFFERENT_CHANNELS_STA),) +PLATFORM_FLAGS += -DCFG_NUM_DIFFERENT_CHANNELS_STA=$(CFG_NUM_DIFFERENT_CHANNELS_STA) +endif + +ifneq ($(CFG_NUM_DIFFERENT_CHANNELS_P2P),) +PLATFORM_FLAGS += -DCFG_NUM_DIFFERENT_CHANNELS_P2P=$(CFG_NUM_DIFFERENT_CHANNELS_P2P) +endif + +ifneq ($(CFG_DRIVER_INITIAL_RUNNING_MODE),) +PLATFORM_FLAGS += -DCFG_DRIVER_INITIAL_RUNNING_MODE=$(CFG_DRIVER_INITIAL_RUNNING_MODE) +endif + +ifneq ($(CFG_ENABLE_WAKE_LOCK),) +PLATFORM_FLAGS += -DCFG_ENABLE_WAKE_LOCK=$(CFG_ENABLE_WAKE_LOCK) +endif + +ifneq ($(CFG_DEFAULT_DBG_LEVEL),) +PLATFORM_FLAGS += -DCFG_DEFAULT_DBG_LEVEL=$(CFG_DEFAULT_DBG_LEVEL) +endif + +ifneq ($(CFG_TX_DIRECT_USB),) +PLATFORM_FLAGS += -DCFG_TX_DIRECT_USB=$(CFG_TX_DIRECT_USB) +endif + +ifneq ($(CFG_RX_DIRECT_USB),) +PLATFORM_FLAGS += -DCFG_RX_DIRECT_USB=$(CFG_RX_DIRECT_USB) +endif + +ifneq ($(CFG_USB_REQ_TX_DATA_FFA_CNT),) +PLATFORM_FLAGS += -DCFG_USB_REQ_TX_DATA_FFA_CNT=$(CFG_USB_REQ_TX_DATA_FFA_CNT) +endif + +ifneq ($(CFG_USB_REQ_TX_DATA_CNT),) +PLATFORM_FLAGS += -DCFG_USB_REQ_TX_DATA_CNT=$(CFG_USB_REQ_TX_DATA_CNT) +endif + +ifneq ($(CFG_USB_REQ_RX_DATA_CNT),) +PLATFORM_FLAGS += -DCFG_USB_REQ_RX_DATA_CNT=$(CFG_USB_REQ_RX_DATA_CNT) +endif + +ifneq ($(CFG_SUPPORT_ROAMING),) +PLATFORM_FLAGS += -DCFG_SUPPORT_ROAMING=$(CFG_SUPPORT_ROAMING) +endif + +ifneq ($(CFG_SUPPORT_DFS_MASTER),) +PLATFORM_FLAGS += -DCFG_SUPPORT_DFS_MASTER=$(CFG_SUPPORT_DFS_MASTER) +endif + +ifneq ($(CFG_SUPPORT_SINGLE_SKU_LOCAL_DB),) +PLATFORM_FLAGS += -DCFG_SUPPORT_SINGLE_SKU_LOCAL_DB=$(CFG_SUPPORT_SINGLE_SKU_LOCAL_DB) +endif + +ifeq ($(CFG_DRIVER_INF_NAME_CHANGE), y) +PLATFORM_FLAGS += -DCFG_DRIVER_INF_NAME_CHANGE +endif + +ifneq ($(CFG_SYS_DVT_SUPPORT),) +ifeq ($(CFG_SYS_DVT_SUPPORT), 0) +# Check dependency +CFG_SYS_DVT_DMASCHDL_SUPPORT=0 +endif +PLATFORM_FLAGS += -DCFG_SUPPORT_WIFI_SYSDVT=$(CFG_SYS_DVT_SUPPORT) +export CFG_SUPPORT_WIFI_SYSDVT=$(CFG_SYS_DVT_SUPPORT) +ifneq ($(CFG_SYS_DVT_DMASCHDL_SUPPORT),) +PLATFORM_FLAGS += -DCFG_SUPPORT_DMASHDL_SYSDVT=$(CFG_SYS_DVT_DMASCHDL_SUPPORT) +export CFG_SUPPORT_DMASHDL_SYSDVT=$(CFG_SYS_DVT_DMASCHDL_SUPPORT) +endif +endif + +ifneq ($(CFG_P2P_SCAN_REPORT_ALL_BSS),) +PLATFORM_FLAGS += -DCFG_P2P_SCAN_REPORT_ALL_BSS=$(CFG_P2P_SCAN_REPORT_ALL_BSS) +endif + +ifneq ($(CFG_SDIO_RX_AGG_TASKLET),) +PLATFORM_FLAGS += -DCFG_SDIO_RX_AGG_TASKLET=$(CFG_SDIO_RX_AGG_TASKLET) +endif + +# CFG_WIFI_WORKAROUND_HWITS00012836_WTBL_SEARCH_FAIL +ifeq ($(MTK_COMBO_CHIP), soc3_0) +PLATFORM_FLAGS += -DCFG_WIFI_WORKAROUND_HWITS00012836_WTBL_SEARCH_FAIL=$(CFG_WIFI_WORKAROUND_HWITS00012836_WTBL_SEARCH_FAIL) +endif + +ifeq ($(CONFIG_MTK_COMBO_PLATFORM), x86) +PLATFORM_FLAGS += -DCFG_BUILD_X86_PLATFORM +endif + +all: driver + +driver: + +cd $(DRIVER_DIR) && make -C $(LINUX_SRC) M=$(DRIVER_DIR) PLATFORM_FLAGS="$(PLATFORM_FLAGS)" modules + @cd $(DRIVER_DIR) && cp $(MODULES_NAME)_$(hif).ko $(MODULES_NAME).ko + +clean: driver_clean + +driver_clean: + cd $(DRIVER_DIR) && make -C $(LINUX_SRC) M=$(DRIVER_DIR) clean + +.PHONY: all clean driver driver_clean diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/common/cmm_asic_connac.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/common/cmm_asic_connac.c new file mode 100644 index 0000000000000..1a416cb3f7b08 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/common/cmm_asic_connac.c @@ -0,0 +1,1868 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file connac.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. + */ + +/******************************************************************************* + * C O M P I L E 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 + ******************************************************************************* + */ + + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +#if defined(_HIF_USB) +/* + * USB Endpoint OUT/DMA Scheduler Group Mapping (HW Define) + * EP#4 / Group0 (DATA) + * EP#5 / Group1 (DATA) + * EP#6 / Group2 (DATA) + * EP#7 / Group3 (DATA) + * EP#9 / Group4 (DATA) + * EP#8 / Group15 (CMD) + */ +uint8_t arAcQIdx2GroupId[MAC_TXQ_NUM] = { + GROUP0_INDEX, /* MAC_TXQ_AC0_INDEX */ + GROUP1_INDEX, /* MAC_TXQ_AC1_INDEX */ + GROUP2_INDEX, /* MAC_TXQ_AC2_INDEX */ + GROUP3_INDEX, /* MAC_TXQ_AC3_INDEX */ + + GROUP4_INDEX, /* MAC_TXQ_AC10_INDEX */ + GROUP4_INDEX, /* MAC_TXQ_AC11_INDEX */ + GROUP4_INDEX, /* MAC_TXQ_AC12_INDEX */ + GROUP4_INDEX, /* MAC_TXQ_AC13_INDEX */ + + GROUP4_INDEX, /* MAC_TXQ_AC20_INDEX */ + GROUP4_INDEX, /* MAC_TXQ_AC21_INDEX */ + GROUP4_INDEX, /* MAC_TXQ_AC22_INDEX */ + GROUP4_INDEX, /* MAC_TXQ_AC23_INDEX */ + + GROUP4_INDEX, /* MAC_TXQ_AC30_INDEX */ + GROUP4_INDEX, /* MAC_TXQ_AC31_INDEX */ + GROUP4_INDEX, /* MAC_TXQ_AC32_INDEX */ + GROUP4_INDEX, /* MAC_TXQ_AC33_INDEX */ + + GROUP4_INDEX, /* MAC_TXQ_ALTX_0_INDEX */ + GROUP4_INDEX, /* MAC_TXQ_BMC_0_INDEX */ + GROUP4_INDEX, /* MAC_TXQ_BCN_0_INDEX */ + GROUP4_INDEX, /* MAC_TXQ_PSMP_0_INDEX */ + + GROUP5_INDEX, /* Reserved */ + GROUP5_INDEX, /* Reserved */ + GROUP5_INDEX, /* Reserved */ + GROUP5_INDEX, /* Reserved */ + + GROUP5_INDEX, /* Reserved */ + GROUP5_INDEX, /* Reserved */ +}; +#endif /* _HIF_USB */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +#if defined(_HIF_USB) +#define USB_DMA_SHDL_GROUP_DEF_SEQUENCE_ORDER 0xFFFEFFFF +#define USB_DMA_SHDL_GROUP_DEF_MIN_QUOTA 0x3 +#define USB_DMA_SHDL_GROUP_DEF_MAX_QUOTA 0x1FF +#define USB_ACCESS_RETRY_LIMIT 1 +#endif /* _HIF_USB */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +void asicCapInit(IN struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo; + struct mt66xx_chip_info *prChipInfo; + struct BUS_INFO *prBusInfo = NULL; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + prChipInfo = prAdapter->chip_info; + prBusInfo = prChipInfo->bus_info; + + prChipInfo->u2HifTxdSize = 0; + prChipInfo->u2TxInitCmdPort = 0; + prChipInfo->u2TxFwDlPort = 0; + prChipInfo->fillHifTxDesc = NULL; + prChipInfo->u4ExtraTxByteCount = 0; + prChipInfo->asicFillInitCmdTxd = asicFillInitCmdTxd; + prChipInfo->asicFillCmdTxd = asicFillCmdTxd; + prChipInfo->u2CmdTxHdrSize = sizeof(struct WIFI_CMD); + prChipInfo->u2RxSwPktBitMap = RXM_RXD_PKT_TYPE_SW_BITMAP; + prChipInfo->u2RxSwPktEvent = RXM_RXD_PKT_TYPE_SW_EVENT; + prChipInfo->u2RxSwPktFrame = RXM_RXD_PKT_TYPE_SW_FRAME; + asicInitTxdHook(prChipInfo->prTxDescOps); + asicInitRxdHook(prChipInfo->prRxDescOps); +#if (CFG_SUPPORT_MSP == 1) + prChipInfo->asicRxProcessRxvforMSP = asicRxProcessRxvforMSP; +#endif /* CFG_SUPPORT_MSP == 1 */ + prChipInfo->asicRxGetRcpiValueFromRxv = asicRxGetRcpiValueFromRxv; +#if (CFG_SUPPORT_PERF_IND == 1) + prChipInfo->asicRxPerfIndProcessRXV = asicRxPerfIndProcessRXV; +#endif +#if (CFG_CHIP_RESET_SUPPORT == 1) && (CFG_WMT_RESET_API_SUPPORT == 0) + prChipInfo->rst_L0_notify_step2 = conn1_rst_L0_notify_step2; +#endif +#if CFG_SUPPORT_WIFI_SYSDVT + prAdapter->u2TxTest = TX_TEST_UNLIMITIED; + prAdapter->u2TxTestCount = 0; + prAdapter->ucTxTestUP = TX_TEST_UP_UNDEF; +#endif /* CFG_SUPPORT_WIFI_SYSDVT */ + + switch (prGlueInfo->u4InfType) { +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + case MT_DEV_INF_PCIE: + case MT_DEV_INF_AXI: + prChipInfo->u2TxInitCmdPort = TX_RING_FWDL_IDX_3; + prChipInfo->u2TxFwDlPort = TX_RING_FWDL_IDX_3; + prChipInfo->ucPacketFormat = TXD_PKT_FORMAT_TXD; + prChipInfo->u4HifDmaShdlBaseAddr = PCIE_HIF_DMASHDL_BASE; + + HAL_MCR_WR(prAdapter, CONN_HIF_ON_IRQ_ENA, BIT(0)); + break; +#endif /* _HIF_PCIE */ +#if defined(_HIF_USB) + case MT_DEV_INF_USB: + prChipInfo->u2HifTxdSize = USB_HIF_TXD_LEN; + prChipInfo->fillHifTxDesc = fillUsbHifTxDesc; + prChipInfo->u2TxInitCmdPort = USB_DATA_BULK_OUT_EP8; + prChipInfo->u2TxFwDlPort = USB_DATA_BULK_OUT_EP4; + prChipInfo->ucPacketFormat = TXD_PKT_FORMAT_TXD_PAYLOAD; + prChipInfo->u4ExtraTxByteCount = + EXTRA_TXD_SIZE_FOR_TX_BYTE_COUNT; + prChipInfo->u4HifDmaShdlBaseAddr = USB_HIF_DMASHDL_BASE; + if (prBusInfo->DmaShdlInit) + prBusInfo->DmaShdlInit(prAdapter); + asicUdmaTxTimeoutEnable(prAdapter); + asicUdmaRxFlush(prAdapter, FALSE); + asicPdmaHifReset(prAdapter, TRUE); + break; +#endif /* _HIF_USB */ +#if defined(_HIF_SDIO) + case MT_DEV_INF_SDIO: + prChipInfo->ucPacketFormat = TXD_PKT_FORMAT_TXD_PAYLOAD; + prChipInfo->u4ExtraTxByteCount = + EXTRA_TXD_SIZE_FOR_TX_BYTE_COUNT; + break; +#endif /* _HIF_SDIO */ + default: + break; + } +} + +uint32_t asicGetFwDlInfo(struct ADAPTER *prAdapter, + char *pcBuf, int i4TotalLen) +{ + struct TAILER_COMMON_FORMAT_T *prComTailer; + uint32_t u4Offset = 0; + uint8_t aucBuf[32]; + + prComTailer = &prAdapter->rVerInfo.rCommonTailer; + + kalMemZero(aucBuf, sizeof(aucBuf)); + kalMemCopy(aucBuf, prComTailer->aucRamVersion, + sizeof(prComTailer->aucRamVersion)); + u4Offset += snprintf(pcBuf + u4Offset, i4TotalLen - u4Offset, + "Tailer Ver[%u:%u] %s (%s) info %u:E%u\n", + prComTailer->ucFormatVer, + prComTailer->ucFormatFlag, + aucBuf, + prComTailer->aucRamBuiltDate, + prComTailer->ucChipInfo, + prComTailer->ucEcoCode + 1); + + if (prComTailer->ucFormatFlag) { + u4Offset += snprintf(pcBuf + u4Offset, i4TotalLen - u4Offset, + "Release manifest: %s\n", + prAdapter->rVerInfo.aucReleaseManifest); + } + return u4Offset; +} + +uint32_t asicGetChipID(struct ADAPTER *prAdapter) +{ + struct mt66xx_chip_info *prChipInfo; + uint32_t u4ChipID = 0; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + ASSERT(prChipInfo); + + /* Compose chipID from chip ip version + * + * BIT(30, 31) : Coding type, 00: compact, 01: index table + * BIT(24, 29) : IP config (6 bits) + * BIT(8, 23) : IP version + * BIT(0, 7) : A die info + */ + + u4ChipID = (0x0 << 30) | + ((prChipInfo->u4ChipIpConfig & 0x3F) << 24) | + ((prChipInfo->u4ChipIpVersion & 0xF0000000) >> 8) | + ((prChipInfo->u4ChipIpVersion & 0x000F0000) >> 0) | + ((prChipInfo->u4ChipIpVersion & 0x00000F00) << 4) | + ((prChipInfo->u4ChipIpVersion & 0x0000000F) << 8) | + (prChipInfo->u2ADieChipVersion & 0xFF); + + log_dbg(HAL, INFO, "ChipID = [0x%08x]\n", u4ChipID); + return u4ChipID; +} + +void asicEnableFWDownload(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnable) +{ + struct GLUE_INFO *prGlueInfo; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + + switch (prGlueInfo->u4InfType) { +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + case MT_DEV_INF_PCIE: + case MT_DEV_INF_AXI: + { + union WPDMA_GLO_CFG_STRUCT GloCfg; + + kalDevRegRead(prGlueInfo, WPDMA_GLO_CFG, &GloCfg.word); + + GloCfg.field_conn.bypass_dmashdl_txring3 = fgEnable; + + kalDevRegWrite(prGlueInfo, WPDMA_GLO_CFG, GloCfg.word); + } + break; +#endif /* _HIF_PCIE */ + +#if defined(_HIF_USB) + case MT_DEV_INF_USB: + { + uint32_t u4Value = 0; + + ASSERT(prAdapter); + + HAL_MCR_RD(prAdapter, CONNAC_UDMA_TX_QSEL, &u4Value); + + if (fgEnable) + u4Value |= FW_DL_EN; + else + u4Value &= ~FW_DL_EN; + + HAL_MCR_WR(prAdapter, CONNAC_UDMA_TX_QSEL, u4Value); + } + break; +#endif /* _HIF_USB */ + + default: + break; + } +} + +void fillNicTxDescAppend(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + OUT uint8_t *prTxDescBuffer) +{ + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + union HW_MAC_TX_DESC_APPEND *prHwTxDescAppend; + + /* Fill TxD append */ + prHwTxDescAppend = (union HW_MAC_TX_DESC_APPEND *) + prTxDescBuffer; + kalMemZero(prHwTxDescAppend, prChipInfo->txd_append_size); +} + +void fillNicTxDescAppendWithCR4(IN struct ADAPTER + *prAdapter, IN struct MSDU_INFO *prMsduInfo, + OUT uint8_t *prTxDescBuffer) +{ + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + union HW_MAC_TX_DESC_APPEND *prHwTxDescAppend; + + /* Fill TxD append */ + prHwTxDescAppend = (union HW_MAC_TX_DESC_APPEND *) + prTxDescBuffer; + kalMemZero(prHwTxDescAppend, prChipInfo->txd_append_size); + prHwTxDescAppend->CR4_APPEND.u2PktFlags = + HIF_PKT_FLAGS_CT_INFO_APPLY_TXD; + prHwTxDescAppend->CR4_APPEND.ucBssIndex = + prMsduInfo->ucBssIndex; +} + +void fillTxDescAppendByHost(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN uint16_t u4MsduId, + IN phys_addr_t rDmaAddr, IN uint32_t u4Idx, + IN u_int8_t fgIsLast, + OUT uint8_t *pucBuffer) +{ + union HW_MAC_TX_DESC_APPEND *prHwTxDescAppend; + struct TXD_PTR_LEN *prPtrLen; + + prHwTxDescAppend = (union HW_MAC_TX_DESC_APPEND *) ( + pucBuffer + NIC_TX_DESC_LONG_FORMAT_LENGTH); + prHwTxDescAppend->CONNAC_APPEND.au2MsduId[u4Idx] = + u4MsduId | TXD_MSDU_ID_VLD; + prPtrLen = &prHwTxDescAppend->CONNAC_APPEND.arPtrLen[u4Idx >> 1]; + if ((u4Idx & 1) == 0) { + prPtrLen->u4Ptr0 = rDmaAddr; + prPtrLen->u2Len0 = prMsduInfo->u2FrameLength | TXD_LEN_ML; + if (fgIsLast) + prPtrLen->u2Len0 |= TXD_LEN_AL; + } else { + prPtrLen->u4Ptr1 = rDmaAddr; + prPtrLen->u2Len1 = prMsduInfo->u2FrameLength | TXD_LEN_ML; + if (fgIsLast) + prPtrLen->u2Len1 |= TXD_LEN_AL; + } +} + +void fillTxDescAppendByHostV2(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN uint16_t u4MsduId, + IN phys_addr_t rDmaAddr, IN uint32_t u4Idx, + IN u_int8_t fgIsLast, + OUT uint8_t *pucBuffer) +{ + union HW_MAC_TX_DESC_APPEND *prHwTxDescAppend; + struct TXD_PTR_LEN *prPtrLen; + uint64_t u8Addr = (uint64_t)rDmaAddr; + + prHwTxDescAppend = (union HW_MAC_TX_DESC_APPEND *) + (pucBuffer + NIC_TX_DESC_LONG_FORMAT_LENGTH); + prHwTxDescAppend->CONNAC_APPEND.au2MsduId[u4Idx] = + u4MsduId | TXD_MSDU_ID_VLD; + prPtrLen = &prHwTxDescAppend->CONNAC_APPEND.arPtrLen[u4Idx >> 1]; + + if ((u4Idx & 1) == 0) { + prPtrLen->u4Ptr0 = (uint32_t)u8Addr; + prPtrLen->u2Len0 = + (prMsduInfo->u2FrameLength & TXD_LEN_MASK_V2) | + ((u8Addr >> TXD_ADDR2_OFFSET) & TXD_ADDR2_MASK); + prPtrLen->u2Len0 |= TXD_LEN_ML_V2; + } else { + prPtrLen->u4Ptr1 = (uint32_t)u8Addr; + prPtrLen->u2Len1 = + (prMsduInfo->u2FrameLength & TXD_LEN_MASK_V2) | + ((u8Addr >> TXD_ADDR2_OFFSET) & TXD_ADDR2_MASK); + prPtrLen->u2Len1 |= TXD_LEN_ML_V2; + } +} + +void fillTxDescAppendByCR4(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN uint16_t u4MsduId, + IN phys_addr_t rDmaAddr, IN uint32_t u4Idx, + IN u_int8_t fgIsLast, + OUT uint8_t *pucBuffer) +{ + union HW_MAC_TX_DESC_APPEND *prHwTxDescAppend; + + prHwTxDescAppend = (union HW_MAC_TX_DESC_APPEND *) + (pucBuffer + NIC_TX_DESC_LONG_FORMAT_LENGTH); + prHwTxDescAppend->CR4_APPEND.u2MsduToken = u4MsduId; + prHwTxDescAppend->CR4_APPEND.ucBufNum = u4Idx + 1; + prHwTxDescAppend->CR4_APPEND.au4BufPtr[u4Idx] = rDmaAddr; + prHwTxDescAppend->CR4_APPEND.au2BufLen[u4Idx] = + prMsduInfo->u2FrameLength; +} + +void fillTxDescTxByteCount(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + void *prTxDesc) +{ + struct mt66xx_chip_info *prChipInfo; + uint32_t u4TxByteCount = NIC_TX_DESC_LONG_FORMAT_LENGTH; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + ASSERT(prTxDesc); + + prChipInfo = prAdapter->chip_info; + u4TxByteCount += prMsduInfo->u2FrameLength; + + if (prMsduInfo->ucPacketType == TX_PACKET_TYPE_DATA) + u4TxByteCount += prChipInfo->u4ExtraTxByteCount; + + /* Calculate Tx byte count */ + HAL_MAC_TX_DESC_SET_TX_BYTE_COUNT( + (struct HW_MAC_TX_DESC *)prTxDesc, u4TxByteCount); +} + +void fillTxDescTxByteCountWithCR4(IN struct ADAPTER + *prAdapter, IN struct MSDU_INFO *prMsduInfo, + void *prTxDesc) +{ + struct mt66xx_chip_info *prChipInfo; + uint32_t u4TxByteCount = NIC_TX_DESC_LONG_FORMAT_LENGTH; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + ASSERT(prTxDesc); + + prChipInfo = prAdapter->chip_info; + u4TxByteCount += prMsduInfo->u2FrameLength; + + if (prMsduInfo->ucPacketType == TX_PACKET_TYPE_DATA) + u4TxByteCount += prChipInfo->txd_append_size; + + /* Calculate Tx byte count */ + HAL_MAC_TX_DESC_SET_TX_BYTE_COUNT( + (struct HW_MAC_TX_DESC *)prTxDesc, u4TxByteCount); +} + +#if defined(_HIF_PCIE) || defined(_HIF_AXI) +void asicPcieDmaShdlInit(IN struct ADAPTER *prAdapter) +{ + uint32_t u4BaseAddr, u4MacVal = 0; + struct mt66xx_chip_info *prChipInfo; + struct BUS_INFO *prBusInfo; + uint32_t u4FreePageCnt = 0; + + ASSERT(prAdapter); + + prChipInfo = prAdapter->chip_info; + prBusInfo = prChipInfo->bus_info; + u4BaseAddr = prChipInfo->u4HifDmaShdlBaseAddr; + + HAL_MCR_RD(prAdapter, + CONN_HIF_DMASHDL_PACKET_MAX_SIZE(u4BaseAddr), &u4MacVal); + u4MacVal &= ~(PLE_PKT_MAX_SIZE_MASK | PSE_PKT_MAX_SIZE_MASK); + u4MacVal |= PLE_PKT_MAX_SIZE_NUM(0x1); + u4MacVal |= PSE_PKT_MAX_SIZE_NUM(0x18); /* 0x18 * 128 = 3K */ + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_PACKET_MAX_SIZE(u4BaseAddr), u4MacVal); + + u4MacVal = + (CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP1_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP2_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP3_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP4_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP5_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP6_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP7_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP8_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP9_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP10_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP11_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP12_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP13_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP14_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP15_REFILL_DISABLE_MASK); + /* Always use group 1 if we support 2 Data TxRing */ + if (prBusInfo->tx_ring0_data_idx != prBusInfo->tx_ring1_data_idx) { + u4MacVal &= + ~CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP1_REFILL_DISABLE_MASK; + } + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_REFILL_CONTROL(u4BaseAddr), u4MacVal); + + /* Always use group 1 if we support 2 TxRing for data */ + if (prBusInfo->tx_ring0_data_idx != prBusInfo->tx_ring1_data_idx) { + /* HW has no gruantee to switch Quota at runtime */ + /* Just separate equally. */ + HAL_MCR_RD(prAdapter, + CONN_HIF_DMASHDL_STATUS_RD(u4BaseAddr), &u4FreePageCnt); + u4FreePageCnt = (u4FreePageCnt & DMASHDL_FREE_PG_CNT_MASK) + >> DMASHDL_FREE_PG_CNT_OFFSET; + u4MacVal = DMASHDL_MIN_QUOTA_NUM(0x3); + u4MacVal |= DMASHDL_MAX_QUOTA_NUM(0xFFF); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP0_CTRL(u4BaseAddr), u4MacVal); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP1_CTRL(u4BaseAddr), u4MacVal); + /* Wmm1: group 1, others group 0 */ + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_Q_MAP0(u4BaseAddr), 0x11110000); + } else { + u4MacVal = DMASHDL_MIN_QUOTA_NUM(0x3); + u4MacVal |= DMASHDL_MAX_QUOTA_NUM(0xFFF); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP0_CTRL(u4BaseAddr), u4MacVal); + u4MacVal = 0; + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP1_CTRL(u4BaseAddr), u4MacVal); + } + + u4MacVal = 0; + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP2_CTRL(u4BaseAddr), u4MacVal); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP3_CTRL(u4BaseAddr), u4MacVal); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP4_CTRL(u4BaseAddr), u4MacVal); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP5_CTRL(u4BaseAddr), u4MacVal); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP6_CTRL(u4BaseAddr), u4MacVal); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP7_CTRL(u4BaseAddr), u4MacVal); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP8_CTRL(u4BaseAddr), u4MacVal); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP9_CTRL(u4BaseAddr), u4MacVal); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP10_CTRL(u4BaseAddr), u4MacVal); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP11_CTRL(u4BaseAddr), u4MacVal); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP12_CTRL(u4BaseAddr), u4MacVal); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP13_CTRL(u4BaseAddr), u4MacVal); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP14_CTRL(u4BaseAddr), u4MacVal); +} + +void asicPdmaLoopBackConfig(struct GLUE_INFO *prGlueInfo, u_int8_t fgEnable) +{ + union WPDMA_GLO_CFG_STRUCT GloCfg; + uint32_t word = 1; + + kalDevRegRead(prGlueInfo, WPDMA_GLO_CFG, &GloCfg.word); + + GloCfg.field_conn.bypass_dmashdl_txring3 = 1; + GloCfg.field_conn.pdma_addr_ext_en = 0; + GloCfg.field_conn.omit_rx_info = 1; + GloCfg.field_conn.omit_tx_info = 1; + GloCfg.field_conn.multi_dma_en = 0; + GloCfg.field_conn.pdma_addr_ext_en = 0; + GloCfg.field_conn.tx_dma_en = 1; + GloCfg.field_conn.rx_dma_en = 1; + GloCfg.field_conn.multi_dma_en = 0; + + kalDevRegWrite(prGlueInfo, WPDMA_FIFO_TEST_MOD, word); + kalDevRegWrite(prGlueInfo, WPDMA_GLO_CFG, GloCfg.word); +} + +#if CFG_MTK_MCIF_WIFI_SUPPORT +static void configPdmaRxRingThreshold(struct GLUE_INFO *prGlueInfo) +{ + uint32_t u4OldVal = 0, u4NewVal = 0; + + if (!prGlueInfo) + return; + + /* Config RX ring0 & ring1 */ + kalDevRegRead(prGlueInfo, WPDMA_PAUSE_RX_Q_TH10, &u4OldVal); + u4NewVal += (WPDMA_PAUSE_RX_Q_TH0 << WPDMA_PAUSE_RX_Q_TH0_SHFT); + u4NewVal += (WPDMA_PAUSE_RX_Q_TH1 << WPDMA_PAUSE_RX_Q_TH1_SHFT); + kalDevRegWrite(prGlueInfo, WPDMA_PAUSE_RX_Q_TH10, u4NewVal); + DBGLOG(HAL, TRACE, "RX_RING[0, 1] TH(0x%x) from 0x%x to 0x%x\n", + WPDMA_PAUSE_RX_Q_TH10, u4OldVal, u4NewVal); + + /* Config RX ring2 & ring3 */ + u4OldVal = u4NewVal = 0; + kalDevRegRead(prGlueInfo, WPDMA_PAUSE_RX_Q_TH32, &u4OldVal); + u4NewVal += (WPDMA_PAUSE_RX_Q_TH2 << WPDMA_PAUSE_RX_Q_TH2_SHFT); + u4NewVal += (WPDMA_PAUSE_RX_Q_TH3 << WPDMA_PAUSE_RX_Q_TH3_SHFT); + kalDevRegWrite(prGlueInfo, WPDMA_PAUSE_RX_Q_TH32, u4NewVal); + DBGLOG(HAL, TRACE, "RX_RING[2, 3] TH(0x%x) from 0x%x to 0x%x\n", + WPDMA_PAUSE_RX_Q_TH32, u4OldVal, u4NewVal); +} +#endif + +void asicPdmaIntMaskConfig(struct GLUE_INFO *prGlueInfo, + u_int8_t fgEnable) +{ + struct BUS_INFO *prBusInfo = + prGlueInfo->prAdapter->chip_info->bus_info; + union WPDMA_INT_MASK IntMask; + + kalDevRegRead(prGlueInfo, WPDMA_INT_MSK, &IntMask.word); + + if (fgEnable == TRUE) { + IntMask.field.rx_done_0 = 1; + IntMask.field.rx_done_1 = 1; + IntMask.field.tx_done = + BIT(prBusInfo->tx_ring_fwdl_idx) | + BIT(prBusInfo->tx_ring_cmd_idx) | + BIT(prBusInfo->tx_ring0_data_idx) | + BIT(prBusInfo->tx_ring1_data_idx); + IntMask.field_conn.tx_coherent = 0; + IntMask.field_conn.rx_coherent = 0; + IntMask.field_conn.tx_dly_int = 0; + IntMask.field_conn.rx_dly_int = 0; + IntMask.field_conn.mcu2host_sw_int_ena = 1; + } else { + IntMask.field_conn.rx_done_0 = 0; + IntMask.field_conn.rx_done_1 = 0; + IntMask.field_conn.tx_done = 0; + IntMask.field_conn.tx_coherent = 0; + IntMask.field_conn.rx_coherent = 0; + IntMask.field_conn.tx_dly_int = 0; + IntMask.field_conn.rx_dly_int = 0; + IntMask.field_conn.mcu2host_sw_int_ena = 0; + } + + kalDevRegWrite(prGlueInfo, WPDMA_INT_MSK, IntMask.word); +} + +void asicPdmaConfig(struct GLUE_INFO *prGlueInfo, u_int8_t fgEnable, + bool fgResetHif) +{ + struct BUS_INFO *prBusInfo = + prGlueInfo->prAdapter->chip_info->bus_info; + union WPDMA_GLO_CFG_STRUCT GloCfg; + uint32_t u4Val = 0; + + asicPdmaIntMaskConfig(prGlueInfo, fgEnable); + kalDevRegRead(prGlueInfo, WPDMA_GLO_CFG, &GloCfg.word); + + if (fgEnable == TRUE) { + GloCfg.field_conn.tx_dma_en = 1; + GloCfg.field_conn.rx_dma_en = 1; + GloCfg.field_conn.pdma_bt_size = 3; + GloCfg.field_conn.pdma_addr_ext_en = + (prBusInfo->u4DmaMask > 32) ? 1 : 0; + GloCfg.field_conn.tx_wb_ddone = 1; + GloCfg.field_conn.multi_dma_en = 2; + GloCfg.field_conn.fifo_little_endian = 1; + GloCfg.field_conn.clk_gate_dis = 1; + } else { + GloCfg.field_conn.tx_dma_en = 0; + GloCfg.field_conn.rx_dma_en = 0; + } + + kalDevRegWrite(prGlueInfo, WPDMA_GLO_CFG, GloCfg.word); + kalDevRegWrite(prGlueInfo, WPDMA_PAUSE_TX_Q, 0); + kalDevRegWrite(prGlueInfo, MCU2HOST_SW_INT_ENA, + ERROR_DETECT_MASK); + + /* Set PDMA APSRC_ACK CR */ + kalDevRegRead(prGlueInfo, WPDMA_APSRC_ACK_LOCK_SLPPROT, &u4Val); + kalDevRegWrite(prGlueInfo, WPDMA_APSRC_ACK_LOCK_SLPPROT, + u4Val | BIT(4)); + + if (fgEnable) { + kalDevRegWrite(prGlueInfo, WPDMA_PAUSE_TX_Q, 0); +#if CFG_MTK_MCIF_WIFI_SUPPORT + configPdmaRxRingThreshold(prGlueInfo); +#endif + } else { + halWpdmaWaitIdle(prGlueInfo, 100, 1000); + /* Reset DMA Index */ + kalDevRegWrite(prGlueInfo, WPDMA_RST_PTR, 0xFFFFFFFF); +#if CFG_MTK_MCIF_WIFI_SUPPORT + if (fgResetHif) { + halEnableSlpProt(prGlueInfo); + halHifRst(prGlueInfo); + halDisableSlpProt(prGlueInfo); + } +#endif + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is used to update DmaSchdl max quota. + * + * @param prAdapter + * @param u2Port, the TxRing number + * @param u4MaxQuota, the desired max quota for the TxRing. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +uint32_t asicUpdatTxRingMaxQuota(IN struct ADAPTER *prAdapter, + IN uint16_t u2Port, IN uint32_t u4MaxQuota) +{ + struct GLUE_INFO *prGlueInfo; + uint32_t u4BaseAddr, u4GroupIdx; + uint32_t u4MacVal = 0, u4SrcCnt, u4RsvCnt, u4TxRingBitmap = 0; + +#define DMASHDL_MAX_QUOTA (DMASHDL_MAX_QUOTA_MASK >> DMASHDL_MAX_QUOTA_OFFSET) + ASSERT(prAdapter); + if (u4MaxQuota > DMASHDL_MAX_QUOTA) + u4MaxQuota = DMASHDL_MAX_QUOTA; +#undef DMASHDL_MAX_QUOTA + + prGlueInfo = prAdapter->prGlueInfo; + u4BaseAddr = prAdapter->chip_info->u4HifDmaShdlBaseAddr; + + /* The mapping must be equal to CONN_HIF_DMASHDL_Q_MAP0 + * in asicPcieDmaShdlInit. + */ + switch (u2Port) { + case TX_RING_DATA0_IDX_0: + u4GroupIdx = 0; + break; + case TX_RING_DATA1_IDX_1: + u4GroupIdx = 1; + break; + default: + return WLAN_STATUS_NOT_ACCEPTED; + } + + /* Step 1. Pause the TxRing */ + kalDevRegRead(prGlueInfo, WPDMA_PAUSE_TX_Q, &u4TxRingBitmap); + kalDevRegWrite(prGlueInfo, WPDMA_PAUSE_TX_Q, + u4TxRingBitmap | + (BIT(u2Port) << WPDMA_PAUSE_TX_Q_RINGIDX_OFFSET)); + + /* Step 2. Check MaxQuota >= rsv_cnt + src_cnt */ + HAL_MCR_RD(prAdapter, + CONN_HIF_DMASHDL_STATUS_RD_GP0(u4BaseAddr) + 4*u4GroupIdx, + &u4MacVal); + u4SrcCnt = (u4MacVal & DMASHDL_SRC_CNT_MASK) >> DMASHDL_SRC_CNT_OFFSET; + u4RsvCnt = (u4MacVal & DMASHDL_RSV_CNT_MASK) >> DMASHDL_RSV_CNT_OFFSET; + + /* BE CAREFUL! Caller must call this function again until + * WLAN_STATUS_SUCCESS or unlock the TxRing by itself. + */ + if (u4MaxQuota < u4SrcCnt+u4RsvCnt) { + DBGLOG(HAL, INFO, + "WmmQuota,CannotUpdateNow,Port,%u,Grp,%u,reqMax,%u,src,%u,rsv,%u\n", + u2Port, u4GroupIdx, u4MaxQuota, u4SrcCnt, u4RsvCnt); + return WLAN_STATUS_PENDING; + } + + /* Step 3. Update MaxQuota */ + HAL_MCR_RD(prAdapter, + CONN_HIF_DMASHDL_GROUP0_CTRL(u4BaseAddr) + 4*u4GroupIdx, + &u4MacVal); + u4MacVal &= ~(DMASHDL_MAX_QUOTA_NUM(0xFFF)); + u4MacVal |= DMASHDL_MAX_QUOTA_NUM(u4MaxQuota); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP0_CTRL(u4BaseAddr) + 4*u4GroupIdx, + u4MacVal); + + /* Step 4. Unlock the TxRing */ + kalDevRegWrite(prGlueInfo, WPDMA_PAUSE_TX_Q, + u4TxRingBitmap & + (~(BIT(u2Port) << WPDMA_PAUSE_TX_Q_RINGIDX_OFFSET))); + + return WLAN_STATUS_SUCCESS; +} + + +void asicEnableInterrupt(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + + ASSERT(prAdapter); + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + enable_irq(prHifInfo->u4IrqId); +} + +void asicDisableInterrupt(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + + ASSERT(prAdapter); + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + disable_irq_nosync(prHifInfo->u4IrqId); +} + +void asicLowPowerOwnRead(IN struct ADAPTER *prAdapter, + OUT u_int8_t *pfgResult) +{ + uint32_t u4RegValue = 0; + + HAL_MCR_RD(prAdapter, CONN_HIF_ON_LPCTL, &u4RegValue); + *pfgResult = (u4RegValue & PCIE_LPCR_HOST_SET_OWN) == 0 ? + TRUE : FALSE; +} + +void asicLowPowerOwnSet(IN struct ADAPTER *prAdapter, + OUT u_int8_t *pfgResult) +{ + uint32_t u4RegValue = 0; + + HAL_MCR_WR(prAdapter, CONN_HIF_ON_LPCTL, + PCIE_LPCR_HOST_SET_OWN); + HAL_MCR_RD(prAdapter, CONN_HIF_ON_LPCTL, &u4RegValue); + *pfgResult = (u4RegValue & PCIE_LPCR_HOST_SET_OWN) == 1; +} + +void asicLowPowerOwnClear(IN struct ADAPTER *prAdapter, + OUT u_int8_t *pfgResult) +{ + uint32_t u4RegValue = 0; + + HAL_MCR_WR(prAdapter, CONN_HIF_ON_LPCTL, + PCIE_LPCR_HOST_CLR_OWN); + HAL_MCR_RD(prAdapter, CONN_HIF_ON_LPCTL, &u4RegValue); + *pfgResult = (u4RegValue & PCIE_LPCR_HOST_SET_OWN) == 0; +} + +#if defined(_HIF_PCIE) +void asicLowPowerOwnClearPCIe(IN struct ADAPTER *prAdapter, + OUT u_int8_t *pfgResult) +{ + struct GLUE_INFO *prGlueInfo; + struct GL_HIF_INFO *prHif = NULL; + + prGlueInfo = prAdapter->prGlueInfo; + prHif = &prGlueInfo->rHifInfo; + + pci_write_config_byte(prHif->pdev, + PCIE_DOORBELL_PUSH, + CR_PCIE_CFG_CLEAR_OWN); +} +#endif + +void asicWakeUpWiFi(IN struct ADAPTER *prAdapter) +{ + u_int8_t fgResult; + + ASSERT(prAdapter); + + HAL_LP_OWN_RD(prAdapter, &fgResult); + + if (fgResult) { + prAdapter->fgIsFwOwn = FALSE; + DBGLOG(HAL, WARN, + "Already DriverOwn, set flag only\n"); + } + else + HAL_LP_OWN_CLR(prAdapter, &fgResult); +} + +bool asicIsValidRegAccess(IN struct ADAPTER *prAdapter, IN uint32_t u4Register) +{ + uint32_t au4ExcludeRegs[] = { CONN_HIF_ON_LPCTL }; + uint32_t u4Idx, u4Size = sizeof(au4ExcludeRegs) / sizeof(uint32_t); + + if (wlanIsChipNoAck(prAdapter)) + return false; + + /* driver can access all consys registers on driver own */ + if (!prAdapter->fgIsFwOwn) + return true; + + /* only own control register can be accessed on fw own */ + for (u4Idx = 0; u4Idx < u4Size; u4Idx++) { + if (u4Register == au4ExcludeRegs[u4Idx]) + return true; + } + + return false; +} + +void asicGetMailboxStatus(IN struct ADAPTER *prAdapter, + OUT uint32_t *pu4Val) +{ + uint32_t u4RegValue = 0; + + HAL_MCR_RD(prAdapter, + CONN_MCU_CONFG_ON_HOST_MAILBOX_WF_ADDR, &u4RegValue); + *pu4Val = u4RegValue; +} + +void asicSetDummyReg(struct GLUE_INFO *prGlueInfo) +{ + kalDevRegWrite(prGlueInfo, CONN_DUMMY_CR, PDMA_DUMMY_MAGIC_NUM); +} + +void asicCheckDummyReg(struct GLUE_INFO *prGlueInfo) +{ + struct GL_HIF_INFO *prHifInfo; + struct ADAPTER *prAdapter; + uint32_t u4Value = 0; + uint32_t u4Idx; + + prAdapter = prGlueInfo->prAdapter; + prHifInfo = &prGlueInfo->rHifInfo; + kalDevRegRead(prGlueInfo, CONN_DUMMY_CR, &u4Value); + DBGLOG(HAL, TRACE, "Check sleep mode DummyReg[0x%x]\n", u4Value); + if (u4Value != PDMA_DUMMY_RESET_VALUE) + return; + + for (u4Idx = 0; u4Idx < NUM_OF_TX_RING; u4Idx++) + prHifInfo->TxRing[u4Idx].TxSwUsedIdx = 0; + DBGLOG(HAL, TRACE, "Weakup from sleep mode\n"); + + if (halWpdmaGetRxDmaDoneCnt(prGlueInfo, RX_RING_EVT_IDX_1)) { + DBGLOG(HAL, TRACE, "Force to read RX event\n"); + prAdapter->u4NoMoreRfb |= BIT(RX_RING_EVT_IDX_1); + } + if (halWpdmaGetRxDmaDoneCnt(prGlueInfo, RX_RING_DATA_IDX_0)) { + DBGLOG(HAL, TRACE, "Force to read RX data\n"); + prAdapter->u4NoMoreRfb |= BIT(RX_RING_DATA_IDX_0); + } + /* Write sleep mode magic num to dummy reg */ + asicSetDummyReg(prGlueInfo); +} + +void asicPdmaTxRingExtCtrl( + struct GLUE_INFO *prGlueInfo, + struct RTMP_TX_RING *tx_ring, + uint32_t index) +{ + struct BUS_INFO *prBusInfo; + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + uint32_t phy_addr_ext = 0, ext_offset = 0; + struct RTMP_DMACB *prTxCell; + + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + prTxCell = &tx_ring->Cell[0]; + +#ifdef CONFIG_PHYS_ADDR_T_64BIT + phy_addr_ext = (((uint64_t)prTxCell->AllocPa >> + DMA_BITS_OFFSET) & DMA_HIGHER_4BITS_MASK); +#endif + ext_offset = index * MT_RINGREG_EXT_DIFF; + + tx_ring->hw_desc_base_ext = + prBusInfo->host_tx_ring_ext_ctrl_base + ext_offset; + + HAL_MCR_WR(prAdapter, tx_ring->hw_desc_base_ext, + phy_addr_ext); +} + +void asicPdmaRxRingExtCtrl( + struct GLUE_INFO *prGlueInfo, + struct RTMP_RX_RING *rx_ring, + uint32_t index) +{ + struct BUS_INFO *prBusInfo; + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + uint32_t phy_addr_ext = 0, ext_offset = 0; + + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + +#ifdef CONFIG_PHYS_ADDR_T_64BIT + phy_addr_ext = (((uint64_t)rx_ring->Cell[0].AllocPa >> + DMA_BITS_OFFSET) & DMA_HIGHER_4BITS_MASK); +#endif + ext_offset = index * MT_RINGREG_EXT_DIFF; + rx_ring->hw_desc_base_ext = + prBusInfo->host_rx_ring_ext_ctrl_base + ext_offset; + + HAL_MCR_WR(prAdapter, rx_ring->hw_desc_base_ext, + phy_addr_ext); +} +#endif /* _HIF_PCIE || _HIF_AXI */ + +#if defined(_HIF_USB) +/* DMS Scheduler Init */ +void asicUsbDmaShdlGroupInit(IN struct ADAPTER *prAdapter, + uint32_t u4RefillGroup) +{ + uint32_t u4BaseAddr, u4MacVal = 0; + struct mt66xx_chip_info *prChipInfo; + uint32_t u4CfgVal = 0; + + ASSERT(prAdapter); + + prChipInfo = prAdapter->chip_info; + u4BaseAddr = prChipInfo->u4HifDmaShdlBaseAddr; + + HAL_MCR_RD(prAdapter, + CONN_HIF_DMASHDL_PACKET_MAX_SIZE(u4BaseAddr), &u4MacVal); + u4MacVal &= ~(PLE_PKT_MAX_SIZE_MASK | PSE_PKT_MAX_SIZE_MASK); + u4MacVal |= PLE_PKT_MAX_SIZE_NUM(0x1); + u4MacVal |= PSE_PKT_MAX_SIZE_NUM(0x8); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_PACKET_MAX_SIZE(u4BaseAddr), u4MacVal); + + u4RefillGroup |= + (CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP2_REFILL_PRIORITY_MASK + | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP3_REFILL_PRIORITY_MASK); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_REFILL_CONTROL(u4BaseAddr), u4RefillGroup); + + /* Use "User program group sequence order" by default.[16]1'b0 */ + HAL_MCR_RD(prAdapter, + CONN_HIF_DMASHDL_PAGE_SETTING(u4BaseAddr), &u4MacVal); + u4MacVal &= USB_DMA_SHDL_GROUP_DEF_SEQUENCE_ORDER; + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_PAGE_SETTING(u4BaseAddr), u4MacVal); + +#if CFG_SUPPORT_CFG_FILE + u4CfgVal = wlanCfgGetUint32(prAdapter, + "DmaShdlGroup1MinQuota", + USB_DMA_SHDL_GROUP_DEF_MIN_QUOTA); + u4MacVal = DMASHDL_MIN_QUOTA_NUM(u4CfgVal); + u4CfgVal = wlanCfgGetUint32(prAdapter, + "DmaShdlGroup1MaxQuota", + USB_DMA_SHDL_GROUP_DEF_MAX_QUOTA); + u4MacVal |= DMASHDL_MAX_QUOTA_NUM(u4CfgVal); +#else /* CFG_SUPPORT_CFG_FILE */ + u4MacVal = DMASHDL_MIN_QUOTA_NUM( + USB_DMA_SHDL_GROUP_DEF_MIN_QUOTA); + u4MacVal |= DMASHDL_MAX_QUOTA_NUM( + USB_DMA_SHDL_GROUP_DEF_MAX_QUOTA); +#endif /* !CFG_SUPPORT_CFG_FILE */ + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP1_CTRL(u4BaseAddr), u4MacVal); + +#if CFG_SUPPORT_CFG_FILE + u4CfgVal = wlanCfgGetUint32(prAdapter, + "DmaShdlGroup0MinQuota", + USB_DMA_SHDL_GROUP_DEF_MIN_QUOTA); + u4MacVal = DMASHDL_MIN_QUOTA_NUM(u4CfgVal); + u4CfgVal = wlanCfgGetUint32(prAdapter, + "DmaShdlGroup0MaxQuota", + USB_DMA_SHDL_GROUP_DEF_MAX_QUOTA); + u4MacVal |= DMASHDL_MAX_QUOTA_NUM(u4CfgVal); +#else /* CFG_SUPPORT_CFG_FILE */ + u4MacVal = DMASHDL_MIN_QUOTA_NUM( + USB_DMA_SHDL_GROUP_DEF_MIN_QUOTA); + u4MacVal |= DMASHDL_MAX_QUOTA_NUM( + USB_DMA_SHDL_GROUP_DEF_MAX_QUOTA); +#endif /* !CFG_SUPPORT_CFG_FILE */ + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP0_CTRL(u4BaseAddr), u4MacVal); + +#if CFG_SUPPORT_CFG_FILE + u4CfgVal = wlanCfgGetUint32(prAdapter, + "DmaShdlGroup2MinQuota", + USB_DMA_SHDL_GROUP_DEF_MIN_QUOTA); + u4MacVal = DMASHDL_MIN_QUOTA_NUM(u4CfgVal); + u4CfgVal = wlanCfgGetUint32(prAdapter, + "DmaShdlGroup2MaxQuota", + USB_DMA_SHDL_GROUP_DEF_MAX_QUOTA); + u4MacVal |= DMASHDL_MAX_QUOTA_NUM(u4CfgVal); +#else /* CFG_SUPPORT_CFG_FILE */ + u4MacVal = DMASHDL_MIN_QUOTA_NUM( + USB_DMA_SHDL_GROUP_DEF_MIN_QUOTA); + u4MacVal |= DMASHDL_MAX_QUOTA_NUM( + USB_DMA_SHDL_GROUP_DEF_MAX_QUOTA); +#endif /* !CFG_SUPPORT_CFG_FILE */ + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP2_CTRL(u4BaseAddr), u4MacVal); + +#if CFG_SUPPORT_CFG_FILE + u4CfgVal = wlanCfgGetUint32(prAdapter, + "DmaShdlGroup3MinQuota", + USB_DMA_SHDL_GROUP_DEF_MIN_QUOTA); + u4MacVal = DMASHDL_MIN_QUOTA_NUM(u4CfgVal); + u4CfgVal = wlanCfgGetUint32(prAdapter, + "DmaShdlGroup3MaxQuota", + USB_DMA_SHDL_GROUP_DEF_MAX_QUOTA); + u4MacVal |= DMASHDL_MAX_QUOTA_NUM(u4CfgVal); +#else /* CFG_SUPPORT_CFG_FILE */ + u4MacVal = DMASHDL_MIN_QUOTA_NUM( + USB_DMA_SHDL_GROUP_DEF_MIN_QUOTA); + u4MacVal |= DMASHDL_MAX_QUOTA_NUM( + USB_DMA_SHDL_GROUP_DEF_MAX_QUOTA); +#endif /* !CFG_SUPPORT_CFG_FILE */ + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP3_CTRL(u4BaseAddr), u4MacVal); + +#if CFG_SUPPORT_CFG_FILE + u4CfgVal = wlanCfgGetUint32(prAdapter, + "DmaShdlGroup4MinQuota", + USB_DMA_SHDL_GROUP_DEF_MIN_QUOTA); + u4MacVal = DMASHDL_MIN_QUOTA_NUM(u4CfgVal); + u4CfgVal = wlanCfgGetUint32(prAdapter, + "DmaShdlGroup4MaxQuota", + USB_DMA_SHDL_GROUP_DEF_MAX_QUOTA); + u4MacVal |= DMASHDL_MAX_QUOTA_NUM(u4CfgVal); +#else /* CFG_SUPPORT_CFG_FILE */ + u4MacVal = DMASHDL_MIN_QUOTA_NUM( + USB_DMA_SHDL_GROUP_DEF_MIN_QUOTA); + u4MacVal |= DMASHDL_MAX_QUOTA_NUM( + USB_DMA_SHDL_GROUP_DEF_MAX_QUOTA); +#endif /* !CFG_SUPPORT_CFG_FILE */ + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP4_CTRL(u4BaseAddr), u4MacVal); + + u4MacVal = ((arAcQIdx2GroupId[MAC_TXQ_AC0_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE0_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC1_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE1_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC2_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE2_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC3_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE3_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC10_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE4_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC11_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE5_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC12_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE6_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC13_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE7_MAPPING)); + HAL_MCR_WR(prAdapter, CONN_HIF_DMASHDL_Q_MAP0(u4BaseAddr), + u4MacVal); + + u4MacVal = ((arAcQIdx2GroupId[MAC_TXQ_AC20_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE8_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC21_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE9_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC22_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE10_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC23_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE11_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC30_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE12_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC31_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE13_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC32_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE14_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC33_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE15_MAPPING)); + HAL_MCR_WR(prAdapter, CONN_HIF_DMASHDL_Q_MAP1(u4BaseAddr), + u4MacVal); + + u4MacVal = ((arAcQIdx2GroupId[MAC_TXQ_ALTX_0_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE16_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_BMC_0_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE17_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_BCN_0_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE18_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_PSMP_0_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE19_MAPPING)); + HAL_MCR_WR(prAdapter, CONN_HIF_DMASHDL_Q_MAP2(u4BaseAddr), + u4MacVal); +} + +void asicUsbDmaShdlInit(IN struct ADAPTER *prAdapter) +{ + uint32_t u4BaseAddr, u4MacVal; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + + prChipInfo = prAdapter->chip_info; + u4BaseAddr = prChipInfo->u4HifDmaShdlBaseAddr; + + /* + * Enable refill control group 0, 1, 2, 3, 4. + * Keep all group low refill priority to prevent low + * group starvation if we have high group. + */ + u4MacVal = + (CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP5_REFILL_DISABLE_MASK + | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP6_REFILL_DISABLE_MASK + | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP7_REFILL_DISABLE_MASK + | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP8_REFILL_DISABLE_MASK + | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP9_REFILL_DISABLE_MASK + | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP10_REFILL_DISABLE_MASK + | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP11_REFILL_DISABLE_MASK + | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP12_REFILL_DISABLE_MASK + | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP13_REFILL_DISABLE_MASK + | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP14_REFILL_DISABLE_MASK + | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP15_REFILL_DISABLE_MASK); + + asicUsbDmaShdlGroupInit(prAdapter, u4MacVal); + + /* + * HIF Scheduler Setting + * Group15(CMD) is highest priority. + */ + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_SHDL_SET0(u4BaseAddr), 0x6501234f); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_SHDL_SET1(u4BaseAddr), 0xedcba987); + + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_OPTIONAL_CONTROL(u4BaseAddr), 0x7004801c); +} + +u_int8_t asicUsbSuspend(IN struct ADAPTER *prAdapter, + IN struct GLUE_INFO *prGlueInfo) +{ + uint32_t u4Value; + uint32_t count = 0; + int32_t ret = 0; + struct BUS_INFO *prBusInfo; + + DBGLOG(HAL, INFO, "%s ---->\n", __func__); + prBusInfo = prAdapter->chip_info->bus_info; + + /* Disable PDMA TX */ + HAL_MCR_RD(prAdapter, PDMA_IF_MISC, &u4Value); + u4Value &= ~PDMA_IF_MISC_TX_ENABLE_MASK; + HAL_MCR_WR(prAdapter, PDMA_IF_MISC, u4Value); + + /* Set PDMA Debug flag */ + u4Value = 0x00000116; + HAL_MCR_WR(prAdapter, PDMA_DEBUG_EN, u4Value); + /* Polling PDMA_dmashdl_request done */ + while (count < PDMA_TX_IDLE_WAIT_COUNT) { + HAL_MCR_RD(prAdapter, PDMA_DEBUG_STATUS, &u4Value); + DBGLOG(HAL, INFO, "%s: 0x%08x = 0x%08x\n", __func__, + PDMA_DEBUG_STATUS, u4Value); + if (!(u4Value & PDMA_DEBUG_DMASHDL_REQUEST_DONE_MASK) + && (count >= 3)) + break; + mdelay(1); + count++; + } + + if (count >= PDMA_TX_IDLE_WAIT_COUNT) { + DBGLOG(HAL, ERROR, + "%s:: 2.2 suspend fail, enable PDMA TX again.\n", + __func__); + /* Enable PDMA TX again */ + HAL_MCR_RD(prAdapter, PDMA_IF_MISC, &u4Value); + u4Value |= PDMA_IF_MISC_TX_ENABLE_MASK; + HAL_MCR_WR(prAdapter, PDMA_IF_MISC, u4Value); + return FALSE; + } + + u4Value = 0x00000101; + HAL_MCR_WR(prAdapter, PDMA_DEBUG_EN, u4Value); + count = 0; + while (count < PDMA_TX_IDLE_WAIT_COUNT) { + HAL_MCR_RD(prAdapter, PDMA_DEBUG_STATUS, &u4Value); + DBGLOG(HAL, INFO, "%s:: 0x%08x = 0x%08x\n", + __func__, PDMA_DEBUG_STATUS, u4Value); + if ((u4Value == PDMA_DEBUG_TX_STATUS_MASK) + && (count >= 3)) { + DBGLOG(HAL, ERROR, "%s:: PDMA Tx idle~\n", __func__); + break; + } + DBGLOG(HAL, ERROR, "%s:: PDMA Tx busy.....\n", __func__); + count++; + } + + if (count >= PDMA_TX_IDLE_WAIT_COUNT) { + DBGLOG(HAL, ERROR, + "%s:: 2.4 suspend fail, enable PDMA TX again.\n", + __func__); + /* Enable PDMA TX again */ + HAL_MCR_RD(prAdapter, PDMA_IF_MISC, &u4Value); + u4Value |= PDMA_IF_MISC_TX_ENABLE_MASK; + HAL_MCR_WR(prAdapter, PDMA_IF_MISC, u4Value); + return FALSE; + } + + prGlueInfo->rHifInfo.state = USB_STATE_SUSPEND; + halDisableInterrupt(prGlueInfo->prAdapter); + halTxCancelAllSending(prGlueInfo->prAdapter); + + ret = usb_control_msg(prGlueInfo->rHifInfo.udev, + usb_sndctrlpipe(prGlueInfo->rHifInfo.udev, 0), + VND_REQ_FEATURE_SET, + prBusInfo->u4device_vender_request_out, + FEATURE_SET_WVALUE_SUSPEND, 0, + NULL, 0, + VENDOR_TIMEOUT_MS); + if (ret) { + DBGLOG(HAL, ERROR, + "%s:: VendorRequest FeatureSetResume ERROR:", __func__); + DBGLOG(HAL, ERROR, + " %x, enable PDMA TX again.\n", (unsigned int)ret); + /* Enable PDMA TX again */ + HAL_MCR_RD(prAdapter, PDMA_IF_MISC, &u4Value); + u4Value |= PDMA_IF_MISC_TX_ENABLE_MASK; + HAL_MCR_WR(prAdapter, PDMA_IF_MISC, u4Value); + DBGLOG(HAL, INFO, "%s <----\n", __func__); + return FALSE; + } + DBGLOG(HAL, INFO, "%s <----\n", __func__); + return TRUE; +} + +uint8_t asicUsbEventEpDetected(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct BUS_INFO *prBusInfo = NULL; + int32_t ret = 0; + uint8_t ucRetryCount = 0; + u_int8_t ucEp5Disable = FALSE; + + ASSERT(FALSE == 0); + prGlueInfo = prAdapter->prGlueInfo; + prHifInfo = &prGlueInfo->rHifInfo; + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + + if (prHifInfo->fgEventEpDetected == FALSE) { + prHifInfo->fgEventEpDetected = TRUE; + do { + ret = mtk_usb_vendor_request(prGlueInfo, 0, + prBusInfo->u4device_vender_request_in, + VND_REQ_EP5_IN_INFO, + 0, 0, &ucEp5Disable, + sizeof(ucEp5Disable)); + if (ret || ucRetryCount) + DBGLOG(HAL, ERROR, + "usb_control_msg() status: %x retry: %u\n", + (unsigned int)ret, ucRetryCount); + ucRetryCount++; + if (ucRetryCount > USB_ACCESS_RETRY_LIMIT) + break; + } while (ret); + + if (ret) { + kalSendAeeWarning(HIF_USB_ERR_TITLE_STR, + HIF_USB_ERR_DESC_STR + "USB() reports error: %x retry: %u", + ret, ucRetryCount); + DBGLOG(HAL, ERROR, + "usb_readl() reports error: %x retry: %u\n", ret, + ucRetryCount); + } else { + DBGLOG(HAL, INFO, + "%s: Get ucEp5Disable = %d\n", __func__, + ucEp5Disable); + if (ucEp5Disable) + prHifInfo->eEventEpType = EVENT_EP_TYPE_DATA_EP; + } + } + if (prHifInfo->eEventEpType == EVENT_EP_TYPE_DATA_EP) + return USB_DATA_EP_IN; + else + return USB_EVENT_EP_IN; +} + +void asicUdmaTxTimeoutEnable(IN struct ADAPTER *prAdapter) +{ + struct BUS_INFO *prBusInfo; + uint32_t u4Value; + + prBusInfo = prAdapter->chip_info->bus_info; + HAL_MCR_RD(prAdapter, prBusInfo->u4UdmaWlCfg_1_Addr, + &u4Value); + u4Value &= ~UDMA_WLCFG_1_TX_TIMEOUT_LIMIT_MASK; + u4Value |= UDMA_WLCFG_1_TX_TIMEOUT_LIMIT( + prBusInfo->u4UdmaTxTimeout); + HAL_MCR_WR(prAdapter, prBusInfo->u4UdmaWlCfg_1_Addr, + u4Value); + + HAL_MCR_RD(prAdapter, prBusInfo->u4UdmaWlCfg_0_Addr, + &u4Value); + u4Value |= UDMA_WLCFG_0_TX_TIMEOUT_EN_MASK; + HAL_MCR_WR(prAdapter, prBusInfo->u4UdmaWlCfg_0_Addr, + u4Value); +} + +void asicUdmaRxFlush(IN struct ADAPTER *prAdapter, + IN u_int8_t bEnable) +{ + struct BUS_INFO *prBusInfo; + uint32_t u4Value; + + prBusInfo = prAdapter->chip_info->bus_info; + + HAL_MCR_RD(prAdapter, prBusInfo->u4UdmaWlCfg_0_Addr, + &u4Value); + if (bEnable) + u4Value |= UDMA_WLCFG_0_RX_FLUSH_MASK; + else + u4Value &= ~UDMA_WLCFG_0_RX_FLUSH_MASK; + HAL_MCR_WR(prAdapter, prBusInfo->u4UdmaWlCfg_0_Addr, + u4Value); +} + +void asicPdmaHifReset(IN struct ADAPTER *prAdapter, + IN u_int8_t bRelease) +{ + uint32_t u4Value; + + HAL_MCR_RD(prAdapter, PDMA_HIF_RESET, &u4Value); + if (bRelease) + u4Value |= DPMA_HIF_LOGIC_RESET_MASK; + else + u4Value &= ~DPMA_HIF_LOGIC_RESET_MASK; + HAL_MCR_WR(prAdapter, PDMA_HIF_RESET, u4Value); +} + +void fillUsbHifTxDesc(IN uint8_t **pDest, + IN uint16_t *pInfoBufLen) +{ + /*USB TX Descriptor (4 bytes)*/ + /* BIT[15:0] - TX Bytes Count + * (Not including USB TX Descriptor and 4-bytes zero padding. + */ + kalMemZero((void *)*pDest, sizeof(uint32_t)); + kalMemCopy((void *)*pDest, (void *) pInfoBufLen, + sizeof(uint16_t)); +} +#endif /* _HIF_USB */ + +static void asicFillInitCmdTxdInfo( + struct ADAPTER *prAdapter, + struct WIFI_CMD_INFO *prCmdInfo, + u_int8_t *pucSeqNum) +{ + struct INIT_HIF_TX_HEADER *prInitHifTxHeader; + struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES + *prInitHifTxHeaderPending; + uint32_t u4TxdLen = + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES); + + prInitHifTxHeaderPending = + (struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES *) + (prCmdInfo->pucInfoBuffer); + prInitHifTxHeader = (struct INIT_HIF_TX_HEADER *) + (prCmdInfo->pucInfoBuffer + u4TxdLen); + + prInitHifTxHeaderPending->u2TxByteCount = prCmdInfo->u2InfoBufLen; + if (!prCmdInfo->ucCID) { + prInitHifTxHeaderPending->u2PQ_ID = + INIT_CMD_PDA_PQ_ID; + prInitHifTxHeaderPending->ucHeaderFormat = + INIT_CMD_PDA_PACKET_TYPE_ID; + prInitHifTxHeaderPending->ucPktFt = + INIT_PKT_FT_PDA_FWDL; + } else { + prInitHifTxHeaderPending->u2PQ_ID = + INIT_CMD_PQ_ID; + prInitHifTxHeaderPending->ucHeaderFormat = + INIT_CMD_PACKET_TYPE_ID; + prInitHifTxHeaderPending->ucPktFt = + INIT_PKT_FT_CMD; + } + + prInitHifTxHeader->rInitWifiCmd.ucCID = prCmdInfo->ucCID; + prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = prCmdInfo->ucPktTypeID; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = + nicIncreaseCmdSeqNum(prAdapter); + prInitHifTxHeader->u2TxByteCount = + prInitHifTxHeaderPending->u2TxByteCount - u4TxdLen; + + if (pucSeqNum) + *pucSeqNum = prInitHifTxHeader->rInitWifiCmd.ucSeqNum; + + DBGLOG_LIMITED(INIT, INFO, "TX CMD: ID[0x%02X] SEQ[%u] LEN[%u]\n", + prInitHifTxHeader->rInitWifiCmd.ucCID, + prInitHifTxHeader->rInitWifiCmd.ucSeqNum, + prInitHifTxHeader->u2TxByteCount); +} + +static void asicFillCmdTxdInfo( + struct ADAPTER *prAdapter, + struct WIFI_CMD_INFO *prCmdInfo, + u_int8_t *pucSeqNum) +{ + struct WIFI_CMD *prWifiCmd; + + prWifiCmd = (struct WIFI_CMD *)prCmdInfo->pucInfoBuffer; + + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = + CMD_PQ_ID; + prWifiCmd->ucHeaderFormat = + CMD_PACKET_TYPE_ID; + prWifiCmd->ucPktFt = + TXD_PKT_FT_CMD; + + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucExtenCID = prCmdInfo->ucExtCID; + prWifiCmd->ucPktTypeID = prCmdInfo->ucPktTypeID; + prWifiCmd->ucSetQuery = prCmdInfo->ucSetQuery; + prWifiCmd->ucSeqNum = nicIncreaseCmdSeqNum(prAdapter); + prWifiCmd->ucS2DIndex = S2D_INDEX_CMD_H2N_H2C; + prWifiCmd->u2Length = + prWifiCmd->u2TxByteCount + - (uint16_t) OFFSET_OF(struct WIFI_CMD, u2Length); + + if (pucSeqNum) + *pucSeqNum = prWifiCmd->ucSeqNum; + + DBGLOG_LIMITED(INIT, INFO, + "TX CMD: ID[0x%02X] SEQ[%u] SET[%u] LEN[%u]\n", + prWifiCmd->ucCID, prWifiCmd->ucSeqNum, + prWifiCmd->ucSetQuery, prWifiCmd->u2Length); +} + + +void asicFillInitCmdTxd( + struct ADAPTER *prAdapter, + struct WIFI_CMD_INFO *prCmdInfo, + uint16_t *pu2BufInfoLen, + u_int8_t *pucSeqNum, + void **pCmdBuf) +{ + struct INIT_HIF_TX_HEADER *prInitHifTxHeader; + + prInitHifTxHeader = (struct INIT_HIF_TX_HEADER *) + (prCmdInfo->pucInfoBuffer + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES)); + + if (!prCmdInfo->ucCID) { + *pu2BufInfoLen += sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES); + prCmdInfo->u2InfoBufLen = *pu2BufInfoLen; + } + asicFillInitCmdTxdInfo(prAdapter, prCmdInfo, pucSeqNum); + + if (pCmdBuf) + *pCmdBuf = prInitHifTxHeader->rInitWifiCmd.aucBuffer; +} + +void asicFillCmdTxd( + struct ADAPTER *prAdapter, + struct WIFI_CMD_INFO *prCmdInfo, + u_int8_t *pucSeqNum, + void **pCmdBuf) +{ + struct WIFI_CMD *prWifiCmd; + + prWifiCmd = (struct WIFI_CMD *)prCmdInfo->pucInfoBuffer; + asicFillCmdTxdInfo(prAdapter, prCmdInfo, pucSeqNum); + + if (pCmdBuf) + *pCmdBuf = &prWifiCmd->aucBuffer[0]; +} + +void asicInitTxdHook( + struct TX_DESC_OPS_T *prTxDescOps) +{ + ASSERT(prTxDescOps); + prTxDescOps->nic_txd_long_format_op = nic_txd_v1_long_format_op; + prTxDescOps->nic_txd_tid_op = nic_txd_v1_tid_op; + prTxDescOps->nic_txd_queue_idx_op = nic_txd_v1_queue_idx_op; +#if (CFG_TCP_IP_CHKSUM_OFFLOAD == 1) + prTxDescOps->nic_txd_chksum_op = nic_txd_v1_chksum_op; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD == 1 */ + prTxDescOps->nic_txd_header_format_op = nic_txd_v1_header_format_op; + prTxDescOps->nic_txd_fill_by_pkt_option = + nic_txd_v1_fill_by_pkt_option; + prTxDescOps->nic_txd_compose = nic_txd_v1_compose; + prTxDescOps->nic_txd_compose_security_frame = + nic_txd_v1_compose_security_frame; + prTxDescOps->nic_txd_set_pkt_fixed_rate_option_full = + nic_txd_v1_set_pkt_fixed_rate_option_full; + prTxDescOps->nic_txd_set_pkt_fixed_rate_option = + nic_txd_v1_set_pkt_fixed_rate_option; + prTxDescOps->nic_txd_set_hw_amsdu_template = + nic_txd_v1_set_hw_amsdu_template; + prTxDescOps->nic_txd_change_data_port_by_ac = + nic_txd_v1_change_data_port_by_ac; +} + +void asicInitRxdHook( + struct RX_DESC_OPS_T *prRxDescOps) +{ + ASSERT(prRxDescOps); + prRxDescOps->nic_rxd_get_rx_byte_count = nic_rxd_v1_get_rx_byte_count; + prRxDescOps->nic_rxd_get_pkt_type = nic_rxd_v1_get_packet_type; + prRxDescOps->nic_rxd_get_wlan_idx = nic_rxd_v1_get_wlan_idx; + prRxDescOps->nic_rxd_get_sec_mode = nic_rxd_v1_get_sec_mode; + prRxDescOps->nic_rxd_get_sw_class_error_bit = + nic_rxd_v1_get_sw_class_error_bit; + prRxDescOps->nic_rxd_get_ch_num = nic_rxd_v1_get_ch_num; + prRxDescOps->nic_rxd_get_rf_band = nic_rxd_v1_get_rf_band; + prRxDescOps->nic_rxd_get_tcl = nic_rxd_v1_get_tcl; + prRxDescOps->nic_rxd_get_ofld = nic_rxd_v1_get_ofld; + prRxDescOps->nic_rxd_fill_rfb = nic_rxd_v1_fill_rfb; + prRxDescOps->nic_rxd_sanity_check = nic_rxd_v1_sanity_check; +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG + prRxDescOps->nic_rxd_check_wakeup_reason = + nic_rxd_v1_check_wakeup_reason; +#endif /* CFG_SUPPORT_WAKEUP_REASON_DEBUG */ +} + +#if (CFG_SUPPORT_MSP == 1) +void asicRxProcessRxvforMSP( + IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prRetSwRfb) +{ + struct HW_MAC_RX_STS_GROUP_3 *prGroup3; + + if (prRetSwRfb->ucStaRecIdx >= CFG_STA_REC_NUM) { + DBGLOG(RX, LOUD, + "prRetSwRfb->ucStaRecIdx(%d) >= CFG_STA_REC_NUM(%d)\n", + prRetSwRfb->ucStaRecIdx, CFG_STA_REC_NUM); + return; + } + prGroup3 = + (struct HW_MAC_RX_STS_GROUP_3 *)prRetSwRfb->prRxStatusGroup3; + if (prRetSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_3)) { + prAdapter->arStaRec[ + prRetSwRfb->ucStaRecIdx].u4RxVector0 = + HAL_RX_VECTOR_GET_RX_VECTOR( + prGroup3, 0); + + prAdapter->arStaRec[ + prRetSwRfb->ucStaRecIdx].u4RxVector1 = + HAL_RX_VECTOR_GET_RX_VECTOR( + prGroup3, 1); + + prAdapter->arStaRec[ + prRetSwRfb->ucStaRecIdx].u4RxVector2 = + HAL_RX_VECTOR_GET_RX_VECTOR( + prGroup3, 2); + + prAdapter->arStaRec[ + prRetSwRfb->ucStaRecIdx].u4RxVector3 = + HAL_RX_VECTOR_GET_RX_VECTOR( + prGroup3, 3); + + prAdapter->arStaRec[ + prRetSwRfb->ucStaRecIdx].u4RxVector4 = + HAL_RX_VECTOR_GET_RX_VECTOR( + prGroup3, 4); + } +} +#endif /* CFG_SUPPORT_MSP */ + +uint8_t asicRxGetRcpiValueFromRxv( + IN uint8_t ucRcpiMode, + IN struct SW_RFB *prSwRfb) +{ + uint8_t ucRcpi0, ucRcpi1; + uint8_t ucRcpiValue = 0; + struct HW_MAC_RX_STS_GROUP_3 *prGroup3; + + ASSERT(prSwRfb); + + if (ucRcpiMode >= RCPI_MODE_NUM) { + DBGLOG(RX, WARN, + "Rcpi Mode=%d is invalid for getting uint8_t value from RXV\n", + ucRcpiMode); + return 0; + } + + prGroup3 = (struct HW_MAC_RX_STS_GROUP_3 *)prSwRfb->prRxStatusGroup3; + ucRcpi0 = HAL_RX_STATUS_GET_RCPI0(prGroup3); + ucRcpi1 = HAL_RX_STATUS_GET_RCPI1(prGroup3); + + switch (ucRcpiMode) { + case RCPI_MODE_WF0: + ucRcpiValue = ucRcpi0; + break; + + case RCPI_MODE_WF1: + ucRcpiValue = ucRcpi1; + break; + + case RCPI_MODE_WF2: + case RCPI_MODE_WF3: + DBGLOG(RX, WARN, + "Rcpi Mode = %d is invalid for", ucRcpiMode); + DBGLOG(RX, WARN, + " device with only 2 antenna, use default rcpi0\n"); + ucRcpiValue = ucRcpi0; + break; + + case RCPI_MODE_AVG: /*Not recommended for CBW80+80*/ + if (ucRcpi0 <= RCPI_HIGH_BOUND && + ucRcpi1 <= RCPI_HIGH_BOUND) + ucRcpiValue = (ucRcpi0 + ucRcpi1) / 2; + else + ucRcpiValue = ucRcpi0 <= RCPI_HIGH_BOUND ? + (ucRcpi0) : (ucRcpi1); + break; + + case RCPI_MODE_MAX: + if (ucRcpi0 <= RCPI_HIGH_BOUND && + ucRcpi1 <= RCPI_HIGH_BOUND) + ucRcpiValue = + (ucRcpi0 > ucRcpi1) ? + (ucRcpi0) : (ucRcpi1); + else + ucRcpiValue = ucRcpi0 <= RCPI_HIGH_BOUND ? + (ucRcpi0) : (ucRcpi1); + break; + + case RCPI_MODE_MIN: + ucRcpiValue = + (ucRcpi0 < ucRcpi1) ? (ucRcpi0) : (ucRcpi1); + break; + + default: + break; + } + + if (ucRcpiValue < RCPI_MEASUREMENT_NOT_AVAILABLE) + return ucRcpiValue; + + DBGLOG(RX, ERROR, + "Invalid ucRcpiValue: %d\n", ucRcpiValue); + return 0; +} + +#if (CFG_SUPPORT_PERF_IND == 1) +void asicRxPerfIndProcessRXV(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint8_t ucBssIndex) +{ + /* This Feature First MP on Lafite*/ + struct HW_MAC_RX_STS_GROUP_3 *prRxStatusGroup3; + uint8_t ucRxRate; + uint8_t ucRxMode; + uint8_t ucMcs; + uint8_t ucFrMode; + uint8_t ucShortGI, ucGroupid, ucMu, ucNsts = 1; + uint32_t u4PhyRate; + uint8_t ucRCPI0 = 0, ucRCPI1 = 0; + /* Rate + * Bit Number 2 + * Unit 500 Kbps + */ + uint16_t u2Rate = 0; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + if (ucBssIndex >= BSSID_NUM) + return; + + /* can't parse radiotap info if no rx vector */ + if (((prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_2)) == 0) + || ((prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_3)) == 0)) { + return; + } + + prRxStatusGroup3 = prSwRfb->prRxStatusGroup3; + + ucRxMode = (((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_RX_MODE_MASK) >> RX_VT_RX_MODE_OFFSET); + + /* RATE & NSS */ + if ((ucRxMode == RX_VT_LEGACY_CCK) + || (ucRxMode == RX_VT_LEGACY_OFDM)) { + /* Bit[2:0] for Legacy CCK, Bit[3:0] for Legacy OFDM */ + ucRxRate = (HAL_RX_VECTOR_GET_RX_VECTOR( + prRxStatusGroup3, 0) & RX_VT_RX_RATE_AC_MASK); + u2Rate = nicGetHwRateByPhyRate(ucRxRate); + } else { + ucMcs = (HAL_RX_VECTOR_GET_RX_VECTOR( + prRxStatusGroup3, 0) & RX_VT_RX_RATE_AC_MASK); + ucNsts = ((HAL_RX_VECTOR_GET_RX_VECTOR( + prRxStatusGroup3, 1) & + RX_VT_NSTS_MASK) >> RX_VT_NSTS_OFFSET); + ucGroupid = ((HAL_RX_VECTOR_GET_RX_VECTOR( + prRxStatusGroup3, 1) & + RX_VT_GROUP_ID_MASK) >> RX_VT_GROUP_ID_OFFSET); + + if (ucNsts == 0) + ucNsts = 1; + + if (ucGroupid && ucGroupid != 63) + ucMu = 1; + else { + ucMu = 0; + ucNsts += 1; + } + + /* VHTA1 B0-B1 */ + ucFrMode = ((HAL_RX_VECTOR_GET_RX_VECTOR( + prRxStatusGroup3, 0) & + RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET); + ucShortGI = (HAL_RX_VECTOR_GET_RX_VECTOR( + prRxStatusGroup3, 0) & + RX_VT_SHORT_GI) ? 1 : 0; /* VHTA2 B0 */ + + if ((ucMcs > PHY_RATE_MCS9) || + (ucFrMode > RX_VT_FR_MODE_160) || + (ucShortGI > MAC_GI_SHORT)) + return; + + /* ucRate(500kbs) = u4PhyRate(100kbps) */ + u4PhyRate = nicGetPhyRateByMcsRate(ucMcs, ucFrMode, + ucShortGI); + u2Rate = u4PhyRate / 5; + + } + + /* RCPI */ + ucRCPI0 = HAL_RX_STATUS_GET_RCPI0(prRxStatusGroup3); + ucRCPI1 = HAL_RX_STATUS_GET_RCPI1(prRxStatusGroup3); + + + /* Record peak rate to Traffic Indicator*/ + if (u2Rate > prAdapter->prGlueInfo + ->PerfIndCache.u2CurRxRate[ucBssIndex]) { + prAdapter->prGlueInfo->PerfIndCache. + u2CurRxRate[ucBssIndex] = u2Rate; + prAdapter->prGlueInfo->PerfIndCache. + ucCurRxNss[ucBssIndex] = ucNsts; + prAdapter->prGlueInfo->PerfIndCache. + ucCurRxRCPI0[ucBssIndex] = ucRCPI0; + prAdapter->prGlueInfo->PerfIndCache. + ucCurRxRCPI1[ucBssIndex] = ucRCPI1; + } +} +#endif + + +#if (CFG_CHIP_RESET_SUPPORT == 1) && (CFG_WMT_RESET_API_SUPPORT == 0) +u_int8_t conn1_rst_L0_notify_step2(void) +{ + typedef int (*p_bt_fun_type) (void); + p_bt_fun_type bt_func; + char *bt_func_name = "WF_rst_L0_notify_BT_step2"; + + DBGLOG(INIT, STATE, "[SER][L0] %s\n", bt_func_name); + bt_func = (p_bt_fun_type)(uintptr_t) GLUE_LOOKUP_FUN(bt_func_name); + if (bt_func) + bt_func(); + else { + DBGLOG(INIT, WARN, "[SER][L0] %s does not exist\n", + bt_func_name); + return FALSE; + } + return TRUE; +} +#endif + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/common/cmm_asic_connac2x.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/common/cmm_asic_connac2x.c new file mode 100644 index 0000000000000..83056ea273008 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/common/cmm_asic_connac2x.c @@ -0,0 +1,1813 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file cmm_asic_connac2x.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. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +#if (CFG_SUPPORT_CONNAC2X == 1) + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "coda/mt7915/wf_wfdma_host_dma0.h" +#include "coda/mt7915/wf_wfdma_host_dma1.h" + + +#include "precomp.h" +#include "wlan_lib.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define CONNAC2X_HIF_DMASHDL_BASE 0x52000000 + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +#define USB_ACCESS_RETRY_LIMIT 1 + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +void asicConnac2xCapInit( + struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo; + struct mt66xx_chip_info *prChipInfo; + struct BUS_INFO *prBusInfo = NULL; + uint32_t u4HostWpdamBase = 0; + + ASSERT(prAdapter); + if (prAdapter->chip_info->is_support_wfdma1) + u4HostWpdamBase = CONNAC2X_HOST_WPDMA_1_BASE; + else + u4HostWpdamBase = CONNAC2X_HOST_WPDMA_0_BASE; + + prGlueInfo = prAdapter->prGlueInfo; + prChipInfo = prAdapter->chip_info; + prBusInfo = prChipInfo->bus_info; + + prChipInfo->u2HifTxdSize = 0; + prChipInfo->u2TxInitCmdPort = 0; + prChipInfo->u2TxFwDlPort = 0; + prChipInfo->fillHifTxDesc = NULL; + prChipInfo->u2CmdTxHdrSize = sizeof(struct CONNAC2X_WIFI_CMD); + prChipInfo->asicFillInitCmdTxd = asicConnac2xFillInitCmdTxd; + prChipInfo->asicFillCmdTxd = asicConnac2xFillCmdTxd; + prChipInfo->u2RxSwPktBitMap = CONNAC2X_RX_STATUS_PKT_TYPE_SW_BITMAP; + prChipInfo->u2RxSwPktEvent = CONNAC2X_RX_STATUS_PKT_TYPE_SW_EVENT; + prChipInfo->u2RxSwPktFrame = CONNAC2X_RX_STATUS_PKT_TYPE_SW_FRAME; + prChipInfo->u4ExtraTxByteCount = 0; + asicConnac2xInitTxdHook(prChipInfo->prTxDescOps); + asicConnac2xInitRxdHook(prChipInfo->prRxDescOps); +#if (CFG_SUPPORT_MSP == 1) + prChipInfo->asicRxProcessRxvforMSP = asicConnac2xRxProcessRxvforMSP; +#endif /* CFG_SUPPORT_MSP == 1 */ + prChipInfo->asicRxGetRcpiValueFromRxv = + asicConnac2xRxGetRcpiValueFromRxv; +#if (CFG_SUPPORT_PERF_IND == 1) + prChipInfo->asicRxPerfIndProcessRXV = asicConnac2xRxPerfIndProcessRXV; +#endif +#if (CFG_CHIP_RESET_SUPPORT == 1) && (CFG_WMT_RESET_API_SUPPORT == 0) + prChipInfo->rst_L0_notify_step2 = conn2_rst_L0_notify_step2; +#endif +#if CFG_SUPPORT_WIFI_SYSDVT + prAdapter->u2TxTest = TX_TEST_UNLIMITIED; + prAdapter->u2TxTestCount = 0; + prAdapter->ucTxTestUP = TX_TEST_UP_UNDEF; +#endif /* CFG_SUPPORT_WIFI_SYSDVT */ + +#if (CFG_SUPPORT_802_11AX == 1) + if (fgEfuseCtrlAxOn == 1) { + prAdapter->fgEnShowHETrigger = FALSE; + heRlmInitHeHtcACtrlOMAndUPH(prAdapter); + } +#endif + + switch (prGlueInfo->u4InfType) { +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + case MT_DEV_INF_PCIE: + case MT_DEV_INF_AXI: + + prChipInfo->u2TxInitCmdPort = + TX_RING_CMD_IDX_2; /* Ring17 for CMD */ + prChipInfo->u2TxFwDlPort = + TX_RING_FWDL_IDX_3; /* Ring16 for FWDL */ + prChipInfo->ucPacketFormat = TXD_PKT_FORMAT_TXD; + prChipInfo->u4HifDmaShdlBaseAddr = CONNAC2X_HIF_DMASHDL_BASE; + prChipInfo->rx_event_port = WFDMA1_RX_RING_IDX_0; + + HAL_MCR_WR(prAdapter, + CONNAC2X_BN0_IRQ_ENA_ADDR, + BIT(0)); + + if (prChipInfo->is_support_asic_lp) { + HAL_MCR_WR(prAdapter, + CONNAC2X_WPDMA_MCU2HOST_SW_INT_MASK + (u4HostWpdamBase), + BITS(0, 15)); + } + break; +#endif /* _HIF_PCIE */ +#if defined(_HIF_USB) + case MT_DEV_INF_USB: + prChipInfo->u2HifTxdSize = USB_HIF_TXD_LEN; + prChipInfo->fillHifTxDesc = fillUsbHifTxDesc; + prChipInfo->u2TxInitCmdPort = USB_DATA_BULK_OUT_EP8; + prChipInfo->u2TxFwDlPort = USB_DATA_BULK_OUT_EP4; + if (prChipInfo->is_support_wacpu) + prChipInfo->ucPacketFormat = TXD_PKT_FORMAT_TXD; + else + prChipInfo->ucPacketFormat = + TXD_PKT_FORMAT_TXD_PAYLOAD; + prChipInfo->u4ExtraTxByteCount = + EXTRA_TXD_SIZE_FOR_TX_BYTE_COUNT; + prChipInfo->u4HifDmaShdlBaseAddr = USB_HIF_DMASHDL_BASE; + if (prBusInfo->DmaShdlInit) + prBusInfo->DmaShdlInit(prAdapter); + +#if (CFG_ENABLE_FW_DOWNLOAD == 1) + prChipInfo->asicEnableFWDownload = asicConnac2xEnableUsbFWDL; +#endif /* CFG_ENABLE_FW_DOWNLOAD == 1 */ + if (prChipInfo->asicUsbInit) + prChipInfo->asicUsbInit(prAdapter, prChipInfo); + asicConnac2xUdmaRxFlush(prAdapter, FALSE); + break; +#endif /* _HIF_USB */ + default: + break; + } +} + +static void asicConnac2xFillInitCmdTxdInfo( + struct ADAPTER *prAdapter, + struct WIFI_CMD_INFO *prCmdInfo, + u_int8_t *pucSeqNum) +{ + struct INIT_HIF_TX_HEADER *prInitHifTxHeader; + struct HW_MAC_CONNAC2X_TX_DESC *prInitHifTxHeaderPadding; + uint32_t u4TxdLen = sizeof(struct HW_MAC_CONNAC2X_TX_DESC); + + prInitHifTxHeaderPadding = + (struct HW_MAC_CONNAC2X_TX_DESC *) (prCmdInfo->pucInfoBuffer); + prInitHifTxHeader = (struct INIT_HIF_TX_HEADER *) + (prCmdInfo->pucInfoBuffer + u4TxdLen); + + HAL_MAC_CONNAC2X_TXD_SET_TX_BYTE_COUNT(prInitHifTxHeaderPadding, + prCmdInfo->u2InfoBufLen); + if (!prCmdInfo->ucCID) + HAL_MAC_CONNAC2X_TXD_SET_PKT_FORMAT(prInitHifTxHeaderPadding, + INIT_PKT_FT_PDA_FWDL) + else + HAL_MAC_CONNAC2X_TXD_SET_PKT_FORMAT(prInitHifTxHeaderPadding, + INIT_PKT_FT_CMD) + HAL_MAC_CONNAC2X_TXD_SET_HEADER_FORMAT(prInitHifTxHeaderPadding, + HEADER_FORMAT_COMMAND); + prInitHifTxHeader->rInitWifiCmd.ucCID = prCmdInfo->ucCID; + prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = prCmdInfo->ucPktTypeID; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = + nicIncreaseCmdSeqNum(prAdapter); + prInitHifTxHeader->u2TxByteCount = + prCmdInfo->u2InfoBufLen - u4TxdLen; + + if (pucSeqNum) + *pucSeqNum = prInitHifTxHeader->rInitWifiCmd.ucSeqNum; + + DBGLOG(INIT, TRACE, "TX CMD: ID[0x%02X] SEQ[%u] LEN[%u]\n", + prInitHifTxHeader->rInitWifiCmd.ucCID, + prInitHifTxHeader->rInitWifiCmd.ucSeqNum, + prCmdInfo->u2InfoBufLen); +} + + +static void asicConnac2xFillCmdTxdInfo( + struct ADAPTER *prAdapter, + struct WIFI_CMD_INFO *prCmdInfo, + u_int8_t *pucSeqNum) +{ + struct CONNAC2X_WIFI_CMD *prWifiCmd; + uint32_t u4TxdLen = sizeof(struct HW_MAC_CONNAC2X_TX_DESC); + + prWifiCmd = (struct CONNAC2X_WIFI_CMD *)prCmdInfo->pucInfoBuffer; + + HAL_MAC_CONNAC2X_TXD_SET_TX_BYTE_COUNT( + (struct HW_MAC_CONNAC2X_TX_DESC *)prWifiCmd, + prCmdInfo->u2InfoBufLen); + HAL_MAC_CONNAC2X_TXD_SET_PKT_FORMAT( + (struct HW_MAC_CONNAC2X_TX_DESC *)prWifiCmd, + INIT_PKT_FT_CMD); + HAL_MAC_CONNAC2X_TXD_SET_HEADER_FORMAT( + (struct HW_MAC_CONNAC2X_TX_DESC *)prWifiCmd, + HEADER_FORMAT_COMMAND); + + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucExtenCID = prCmdInfo->ucExtCID; + prWifiCmd->ucPktTypeID = prCmdInfo->ucPktTypeID; + prWifiCmd->ucSetQuery = prCmdInfo->ucSetQuery; + prWifiCmd->ucSeqNum = nicIncreaseCmdSeqNum(prAdapter); + prWifiCmd->ucS2DIndex = prCmdInfo->ucS2DIndex; + prWifiCmd->u2Length = prCmdInfo->u2InfoBufLen - u4TxdLen; + + if (pucSeqNum) + *pucSeqNum = prWifiCmd->ucSeqNum; + + if (aucDebugModule[DBG_TX_IDX] & DBG_CLASS_TRACE) + DBGLOG(TX, TRACE, + "TX CMD: ID[0x%02X] SEQ[%u] SET[%u] LEN[%u]\n", + prWifiCmd->ucCID, prWifiCmd->ucSeqNum, + prWifiCmd->ucSetQuery, prCmdInfo->u2InfoBufLen); + else + DBGLOG_LIMITED(TX, INFO, + "TX CMD: ID[0x%02X] SEQ[%u] SET[%u] LEN[%u]\n", + prWifiCmd->ucCID, prWifiCmd->ucSeqNum, + prWifiCmd->ucSetQuery, prCmdInfo->u2InfoBufLen); +} + +void asicConnac2xFillInitCmdTxd( + struct ADAPTER *prAdapter, + struct WIFI_CMD_INFO *prCmdInfo, + u_int16_t *pu2BufInfoLen, + u_int8_t *pucSeqNum, OUT void **pCmdBuf) +{ + struct INIT_HIF_TX_HEADER *prInitHifTxHeader; + uint32_t u4TxdLen = sizeof(struct HW_MAC_CONNAC2X_TX_DESC); + + /* We don't need to append TXD while sending fw frames. */ + if (!prCmdInfo->ucCID && pCmdBuf) + *pCmdBuf = prCmdInfo->pucInfoBuffer; + else { + prInitHifTxHeader = (struct INIT_HIF_TX_HEADER *) + (prCmdInfo->pucInfoBuffer + u4TxdLen); + asicConnac2xFillInitCmdTxdInfo( + prAdapter, + prCmdInfo, + pucSeqNum); + if (pCmdBuf) + *pCmdBuf = + &prInitHifTxHeader->rInitWifiCmd.aucBuffer[0]; + } +} + +void asicConnac2xWfdmaDummyCrRead( + struct ADAPTER *prAdapter, + u_int8_t *pfgResult) +{ + u_int32_t u4RegValue = 0; + + HAL_MCR_RD(prAdapter, + CONNAC2X_WFDMA_DUMMY_CR, + &u4RegValue); + *pfgResult = (u4RegValue & + CONNAC2X_WFDMA_NEED_REINIT_BIT) + == 0 ? TRUE : FALSE; +} + + +void asicConnac2xWfdmaDummyCrWrite( + struct ADAPTER *prAdapter) +{ + u_int32_t u4RegValue = 0; + + HAL_MCR_RD(prAdapter, + CONNAC2X_WFDMA_DUMMY_CR, + &u4RegValue); + u4RegValue |= CONNAC2X_WFDMA_NEED_REINIT_BIT; + + HAL_MCR_WR(prAdapter, + CONNAC2X_WFDMA_DUMMY_CR, + u4RegValue); +} +void asicConnac2xWfdmaReInit( + struct ADAPTER *prAdapter) +{ + u_int8_t fgResult; + struct BUS_INFO *prBusInfo = prAdapter->chip_info->bus_info; + + /*WFDMA re-init flow after chip deep sleep*/ + asicConnac2xWfdmaDummyCrRead(prAdapter, &fgResult); + if (fgResult) { +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + +#if 0 /* Original Driver re-init Host WFDAM flow */ + DBGLOG(INIT, INFO, "WFDMA host sw-reinit due to deep sleep\n"); + halWpdmaInitRing(prAdapter->prGlueInfo, false); +#else /* Do Driver re-init Host WFDMA flow with FW bk/sr solution */ + { + struct GL_HIF_INFO *prHifInfo; + uint32_t u4Idx; + + DBGLOG(INIT, TRACE, "WFDMA reinit after bk/sr(deep sleep)\n"); + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + for (u4Idx = 0; u4Idx < NUM_OF_TX_RING; u4Idx++) { + prHifInfo->TxRing[u4Idx].TxSwUsedIdx = 0; + prHifInfo->TxRing[u4Idx].u4UsedCnt = 0; + prHifInfo->TxRing[u4Idx].TxCpuIdx = 0; + } + + if (halWpdmaGetRxDmaDoneCnt(prAdapter->prGlueInfo, + WFDMA1_RX_RING_IDX_0)) { + prAdapter->u4NoMoreRfb |= BIT(WFDMA1_RX_RING_IDX_0); + } + } +#endif + /* Write sleep mode magic num to dummy reg */ + if (prBusInfo->setDummyReg) + prBusInfo->setDummyReg(prAdapter->prGlueInfo); + +#endif /* _HIF_PCIE */ + asicConnac2xWfdmaDummyCrWrite(prAdapter); + } +} + +void asicConnac2xFillCmdTxd( + struct ADAPTER *prAdapter, + struct WIFI_CMD_INFO *prCmdInfo, + u_int8_t *pucSeqNum, + void **pCmdBuf) +{ + struct CONNAC2X_WIFI_CMD *prWifiCmd; + + /* 2. Setup common CMD Info Packet */ + prWifiCmd = (struct CONNAC2X_WIFI_CMD *)prCmdInfo->pucInfoBuffer; + asicConnac2xFillCmdTxdInfo(prAdapter, prCmdInfo, pucSeqNum); + if (pCmdBuf) + *pCmdBuf = &prWifiCmd->aucBuffer[0]; +} + +#if defined(_HIF_PCIE) || defined(_HIF_AXI) +uint32_t asicConnac2xWfdmaCfgAddrGet( + struct GLUE_INFO *prGlueInfo, + u_int8_t ucDmaIdx) +{ + struct BUS_INFO *prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + + if (ucDmaIdx == 0) + return CONNAC2X_WPDMA_GLO_CFG(prBusInfo->host_dma0_base); + else + return CONNAC2X_WPDMA_GLO_CFG(prBusInfo->host_dma1_base); +} + +uint32_t asicConnac2xWfdmaIntRstDtxPtrAddrGet( + struct GLUE_INFO *prGlueInfo, + u_int8_t ucDmaIdx) +{ + struct BUS_INFO *prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + + if (ucDmaIdx == 0) + return CONNAC2X_WPDMA_RST_DTX_PTR(prBusInfo->host_dma0_base); + else + return CONNAC2X_WPDMA_RST_DTX_PTR(prBusInfo->host_dma1_base); +} + +uint32_t asicConnac2xWfdmaIntRstDrxPtrAddrGet( + struct GLUE_INFO *prGlueInfo, + u_int8_t ucDmaIdx) +{ + struct BUS_INFO *prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + + if (ucDmaIdx == 0) + return CONNAC2X_WPDMA_RST_DRX_PTR(prBusInfo->host_dma0_base); + else + return CONNAC2X_WPDMA_RST_DRX_PTR(prBusInfo->host_dma1_base); +} + +uint32_t asicConnac2xWfdmaHifRstAddrGet( + struct GLUE_INFO *prGlueInfo, + u_int8_t ucDmaIdx) +{ + struct BUS_INFO *prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + + if (ucDmaIdx == 0) + return CONNAC2X_WPDMA_HIF_RST(prBusInfo->host_dma0_base); + else + return CONNAC2X_WPDMA_HIF_RST(prBusInfo->host_dma1_base); +} + +static void asicConnac2xWfdmaControl( + struct GLUE_INFO *prGlueInfo, + u_int8_t ucDmaIdx, + u_int8_t enable) +{ + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + union WPDMA_GLO_CFG_STRUCT GloCfg; + uint32_t u4DmaCfgCr; + uint32_t u4DmaRstDtxPtrCr; + uint32_t u4DmaRstDrxPtrCr; + + ASSERT(ucDmaIdx < CONNAC2X_WFDMA_COUNT); + u4DmaCfgCr = asicConnac2xWfdmaCfgAddrGet(prGlueInfo, ucDmaIdx); + u4DmaRstDtxPtrCr = + asicConnac2xWfdmaIntRstDtxPtrAddrGet(prGlueInfo, ucDmaIdx); + u4DmaRstDrxPtrCr = + asicConnac2xWfdmaIntRstDrxPtrAddrGet(prGlueInfo, ucDmaIdx); + + HAL_MCR_RD(prAdapter, u4DmaCfgCr, &GloCfg.word); + if (enable == TRUE) { + GloCfg.field_conn2x.pdma_bt_size = 3; + GloCfg.field_conn2x.tx_wb_ddone = 1; + GloCfg.field_conn2x.fifo_little_endian = 1; + GloCfg.field_conn2x.clk_gate_dis = 1; + GloCfg.field_conn2x.omit_tx_info = 1; + if (ucDmaIdx == 1) + GloCfg.field_conn2x.omit_rx_info = 1; + GloCfg.field_conn2x.csr_disp_base_ptr_chain_en = 1; + GloCfg.field_conn2x.omit_rx_info_pfet2 = 1; + } else { + GloCfg.field_conn2x.tx_dma_en = 0; + GloCfg.field_conn2x.rx_dma_en = 0; + GloCfg.field_conn2x.csr_disp_base_ptr_chain_en = 0; + GloCfg.field_conn2x.omit_tx_info = 0; + GloCfg.field_conn2x.omit_rx_info = 0; + GloCfg.field_conn2x.omit_rx_info_pfet2 = 0; + } + HAL_MCR_WR(prAdapter, u4DmaCfgCr, GloCfg.word); + + if (!enable) { + asicConnac2xWfdmaWaitIdle(prGlueInfo, ucDmaIdx, 100, 1000); + /* Reset DMA Index */ + HAL_MCR_WR(prAdapter, u4DmaRstDtxPtrCr, 0xFFFFFFFF); + HAL_MCR_WR(prAdapter, u4DmaRstDrxPtrCr, 0xFFFFFFFF); + } +} + +void asicConnac2xWpdmaConfig( + struct GLUE_INFO *prGlueInfo, + u_int8_t enable, + bool fgResetHif) +{ + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + union WPDMA_GLO_CFG_STRUCT GloCfg[CONNAC2X_WFDMA_COUNT] = {0}; + uint32_t u4DmaCfgCr; + uint32_t idx; + struct mt66xx_chip_info *chip_info = prAdapter->chip_info; + + for (idx = 0; idx < CONNAC2X_WFDMA_COUNT; idx++) { + if (!chip_info->is_support_wfdma1 && idx) + break; + asicConnac2xWfdmaControl(prGlueInfo, idx, enable); + u4DmaCfgCr = asicConnac2xWfdmaCfgAddrGet(prGlueInfo, idx); + HAL_MCR_RD(prAdapter, u4DmaCfgCr, &GloCfg[idx].word); + } + + if (enable) { + for (idx = 0; idx < CONNAC2X_WFDMA_COUNT; idx++) { + if (!chip_info->is_support_wfdma1 && idx) + break; + u4DmaCfgCr = + asicConnac2xWfdmaCfgAddrGet(prGlueInfo, idx); + GloCfg[idx].field_conn2x.tx_dma_en = 1; + GloCfg[idx].field_conn2x.rx_dma_en = 1; + HAL_MCR_WR(prAdapter, u4DmaCfgCr, GloCfg[idx].word); + } + } +} + +u_int8_t asicConnac2xWfdmaWaitIdle( + struct GLUE_INFO *prGlueInfo, + u_int8_t index, + uint32_t round, + uint32_t wait_us) +{ + uint32_t i = 0; + uint32_t u4RegAddr = 0; + union WPDMA_GLO_CFG_STRUCT GloCfg; + struct BUS_INFO *prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + + if (index == 0) + u4RegAddr = prBusInfo->host_dma0_base; + else if (index == 1) + u4RegAddr = prBusInfo->host_dma1_base; + else { + DBGLOG(HAL, ERROR, "Unknown wfdma index(=%d)\n", index); + return FALSE; + } + + do { + HAL_MCR_RD(prAdapter, u4RegAddr, &GloCfg.word); + if ((GloCfg.field.TxDMABusy == 0) && + (GloCfg.field.RxDMABusy == 0)) { + DBGLOG(HAL, TRACE, "==> DMAIdle, GloCfg=0x%x\n", + GloCfg.word); + return TRUE; + } + kalUdelay(wait_us); + } while ((i++) < round); + + DBGLOG(HAL, INFO, "==> DMABusy, GloCfg=0x%x\n", GloCfg.word); + + return FALSE; +} + +void asicConnac2xWfdmaTxRingExtCtrl( + struct GLUE_INFO *prGlueInfo, + struct RTMP_TX_RING *tx_ring, + u_int32_t index) +{ + struct BUS_INFO *prBusInfo; + uint32_t ext_offset = 0; + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + struct mt66xx_chip_info *prChipInfo; + + prChipInfo = prGlueInfo->prAdapter->chip_info; + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + + if (index == TX_RING_CMD_IDX_2) + ext_offset = prBusInfo->tx_ring_cmd_idx * 4; + else if (index == TX_RING_FWDL_IDX_3) + ext_offset = prBusInfo->tx_ring_fwdl_idx * 4; + else if (prChipInfo->is_support_wacpu) { + if (index == TX_RING_DATA0_IDX_0) + ext_offset = prBusInfo->tx_ring0_data_idx * 4; + if (index == TX_RING_DATA1_IDX_1) + ext_offset = prBusInfo->tx_ring1_data_idx * 4; + if (index == TX_RING_WA_CMD_IDX_4) + ext_offset = prBusInfo->tx_ring_wa_cmd_idx * 4; + } else + ext_offset = index * 4; + + tx_ring->hw_desc_base_ext = + prBusInfo->host_tx_ring_ext_ctrl_base + ext_offset; + HAL_MCR_WR(prAdapter, tx_ring->hw_desc_base_ext, + CONNAC2X_TX_RING_DISP_MAX_CNT); +} + +void asicConnac2xWfdmaRxRingExtCtrl( + struct GLUE_INFO *prGlueInfo, + struct RTMP_RX_RING *rx_ring, + u_int32_t index) +{ + struct BUS_INFO *prBusInfo; + uint32_t ext_offset; + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + + if (index >= WFDMA1_RX_RING_IDX_0) { + ext_offset = (index - WFDMA1_RX_RING_IDX_0) * 4; + rx_ring->hw_desc_base_ext = + prBusInfo->host_wfdma1_rx_ring_ext_ctrl_base + + ext_offset; + } else { + ext_offset = index * 4; + rx_ring->hw_desc_base_ext = + prBusInfo->host_rx_ring_ext_ctrl_base + ext_offset; + } + + HAL_MCR_WR(prAdapter, rx_ring->hw_desc_base_ext, + CONNAC2X_RX_RING_DISP_MAX_CNT); +} + +void asicConnac2xWfdmaManualPrefetch( + struct GLUE_INFO *prGlueInfo) +{ + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + u_int32_t val = 0; + + HAL_MCR_RD(prAdapter, WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR, &val); + /* disable prefetch offset calculation auto-mode */ + val &= + ~WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN_MASK; + HAL_MCR_WR(prAdapter, WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR, val); + + HAL_MCR_RD(prAdapter, WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR, &val); + /* disable prefetch offset calculation auto-mode */ + val &= + ~WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN_MASK; + HAL_MCR_WR(prAdapter, WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR, val); + + + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_ADDR, 0x00000004); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_ADDR, 0x00400004); + + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_EXT_CTRL_ADDR, 0x00800004); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_EXT_CTRL_ADDR, 0x00c00004); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_EXT_CTRL_ADDR, 0x01000004); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_EXT_CTRL_ADDR, 0x01400004); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_EXT_CTRL_ADDR, 0x01800004); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_EXT_CTRL_ADDR, 0x01c00004); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_EXT_CTRL_ADDR, 0x02000004); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_EXT_CTRL_ADDR, 0x02400004); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_EXT_CTRL_ADDR, 0x02800004); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_EXT_CTRL_ADDR, 0x02c00004); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_EXT_CTRL_ADDR, 0x03000004); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_EXT_CTRL_ADDR, 0x03400004); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_EXT_CTRL_ADDR, 0x03800004); + + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_EXT_CTRL_ADDR, 0x03c00004); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_EXT_CTRL_ADDR, 0x04000004); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_EXT_CTRL_ADDR, 0x04400004); + + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_ADDR, 0x04800004); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_ADDR, 0x04c00004); + + /* reset dma idx */ + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR, 0xFFFFFFFF); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR, 0xFFFFFFFF); +} + +void asicConnac2xEnablePlatformIRQ(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + + ASSERT(prAdapter); + + prAdapter->fgIsIntEnable = TRUE; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + enable_irq(prHifInfo->u4IrqId); +} + +void asicConnac2xDisablePlatformIRQ(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + + ASSERT(prAdapter); + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + disable_irq_nosync(prHifInfo->u4IrqId); + + prAdapter->fgIsIntEnable = FALSE; +} + +void asicConnac2xEnableExtInterrupt( + struct ADAPTER *prAdapter) +{ + + union WPDMA_INT_MASK IntMask; + + prAdapter->fgIsIntEnable = TRUE; + + IntMask.word = 0; + IntMask.field_conn2x_ext.wfdma0_rx_done_0 = 1; + IntMask.field_conn2x_ext.wfdma0_rx_done_1 = 1; + IntMask.field_conn2x_ext.wfdma0_rx_done_2 = 1; + IntMask.field_conn2x_ext.wfdma0_rx_done_3 = 1; + IntMask.field_conn2x_ext.wfdma1_rx_done_0 = 1; + IntMask.field_conn2x_ext.wfdma1_rx_done_1 = 1; + IntMask.field_conn2x_ext.wfdma1_rx_done_2 = 1; + + IntMask.field_conn2x_ext.wfdma1_tx_done_0 = 1; + /*IntMask.field_conn2x_ext.wfdma1_tx_done_1 = 1;*/ + IntMask.field_conn2x_ext.wfdma1_tx_done_16 = 1; + IntMask.field_conn2x_ext.wfdma1_tx_done_17 = 1; + IntMask.field_conn2x_ext.wfdma1_tx_done_18 = 1; + IntMask.field_conn2x_ext.wfdma1_tx_done_19 = 1; + IntMask.field_conn2x_ext.wfdma1_tx_done_20 = 1; + + IntMask.field_conn2x_ext.wfdma0_rx_coherent = 0; + IntMask.field_conn2x_ext.wfdma0_tx_coherent = 0; + IntMask.field_conn2x_ext.wfdma1_rx_coherent = 0; + IntMask.field_conn2x_ext.wfdma1_tx_coherent = 0; + + IntMask.field_conn2x_ext.wfdma1_mcu2host_sw_int_en = 1; + + HAL_MCR_WR(prAdapter, + CONNAC2X_WPDMA_EXT_INT_MASK(CONNAC2X_HOST_EXT_CONN_HIF_WRAP), + IntMask.word); + HAL_MCR_RD(prAdapter, + CONNAC2X_WPDMA_EXT_INT_MASK(CONNAC2X_HOST_EXT_CONN_HIF_WRAP), + &IntMask.word); + DBGLOG(HAL, TRACE, "%s [0x%08x]\n", __func__, IntMask.word); + + if (prAdapter->chip_info->is_support_wfdma1) { + /* WFDMA issue workaround : + * enable TX RX priority interrupt sel 7c025298/7c02529c + * to force writeback clear int_stat + */ + HAL_MCR_WR(prAdapter, + (CONNAC2X_HOST_WPDMA_1_BASE + 0x29c), 0x000f00ff); + HAL_MCR_WR(prAdapter, + (CONNAC2X_HOST_WPDMA_1_BASE + 0x298), 0xf); + } +} /* end of nicEnableInterrupt() */ + +void asicConnac2xDisableExtInterrupt( + struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo = NULL; + union WPDMA_INT_MASK IntMask; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + + IntMask.word = 0; + + HAL_MCR_WR(prAdapter, + CONNAC2X_WPDMA_EXT_INT_MASK(CONNAC2X_HOST_EXT_CONN_HIF_WRAP), + IntMask.word); + HAL_MCR_RD(prAdapter, + CONNAC2X_WPDMA_EXT_INT_MASK(CONNAC2X_HOST_EXT_CONN_HIF_WRAP), + &IntMask.word); + + prAdapter->fgIsIntEnable = FALSE; + + DBGLOG(HAL, TRACE, "%s\n", __func__); + +} + +void asicConnac2xProcessTxInterrupt(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + union WPDMA_INT_STA_STRUCT rIntrStatus; + + rIntrStatus = (union WPDMA_INT_STA_STRUCT)prHifInfo->u4IntStatus; + if (rIntrStatus.field_conn2x_ext.wfdma1_tx_done_16) + halWpdmaProcessCmdDmaDone(prAdapter->prGlueInfo, + TX_RING_FWDL_IDX_3); + + if (rIntrStatus.field_conn2x_ext.wfdma1_tx_done_17) + halWpdmaProcessCmdDmaDone(prAdapter->prGlueInfo, + TX_RING_CMD_IDX_2); + + if (rIntrStatus.field_conn2x_ext.wfdma1_tx_done_20) + halWpdmaProcessCmdDmaDone(prAdapter->prGlueInfo, + TX_RING_WA_CMD_IDX_4); + + if (rIntrStatus.field_conn2x_ext.wfdma1_tx_done_18) { + halWpdmaProcessDataDmaDone(prAdapter->prGlueInfo, + TX_RING_DATA0_IDX_0); + + kalSetTxEvent2Hif(prAdapter->prGlueInfo); + } + + if (rIntrStatus.field_conn2x_ext.wfdma1_tx_done_19) { + halWpdmaProcessDataDmaDone(prAdapter->prGlueInfo, + TX_RING_DATA1_IDX_1); + + kalSetTxEvent2Hif(prAdapter->prGlueInfo); + } + +} + +void asicConnac2xLowPowerOwnRead( + struct ADAPTER *prAdapter, + u_int8_t *pfgResult) +{ + struct mt66xx_chip_info *prChipInfo; + + prChipInfo = prAdapter->chip_info; + + if (prChipInfo->is_support_asic_lp) { + u_int32_t u4RegValue; + + HAL_MCR_RD(prAdapter, + CONNAC2X_BN0_LPCTL_ADDR, + &u4RegValue); + *pfgResult = (u4RegValue & + PCIE_LPCR_AP_HOST_OWNER_STATE_SYNC) + == 0 ? TRUE : FALSE; + } else + *pfgResult = TRUE; +} + +void asicConnac2xLowPowerOwnSet( + struct ADAPTER *prAdapter, + u_int8_t *pfgResult) +{ + struct mt66xx_chip_info *prChipInfo; + + prChipInfo = prAdapter->chip_info; + + if (prChipInfo->is_support_asic_lp) { + u_int32_t u4RegValue; + + HAL_MCR_WR(prAdapter, + CONNAC2X_BN0_LPCTL_ADDR, + PCIE_LPCR_HOST_SET_OWN); + HAL_MCR_RD(prAdapter, + CONNAC2X_BN0_LPCTL_ADDR, + &u4RegValue); + *pfgResult = (u4RegValue & + PCIE_LPCR_AP_HOST_OWNER_STATE_SYNC) == 0x4; + } else + *pfgResult = TRUE; +} + +void asicConnac2xLowPowerOwnClear( + struct ADAPTER *prAdapter, + u_int8_t *pfgResult) +{ + struct mt66xx_chip_info *prChipInfo; + + prChipInfo = prAdapter->chip_info; + + if (prChipInfo->is_support_asic_lp) { + u_int32_t u4RegValue; + + HAL_MCR_WR(prAdapter, + CONNAC2X_BN0_LPCTL_ADDR, + PCIE_LPCR_HOST_CLR_OWN); + HAL_MCR_RD(prAdapter, + CONNAC2X_BN0_LPCTL_ADDR, + &u4RegValue); + *pfgResult = (u4RegValue & + PCIE_LPCR_AP_HOST_OWNER_STATE_SYNC) == 0; + } else + *pfgResult = TRUE; +} + +void asicConnac2xProcessSoftwareInterrupt( + struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo; + struct GL_HIF_INFO *prHifInfo; + struct ERR_RECOVERY_CTRL_T *prErrRecoveryCtrl; + uint32_t u4Status = 0; + uint32_t u4HostWpdamBase = 0; + + if (prAdapter->prGlueInfo == NULL) { + DBGLOG(HAL, ERROR, "prGlueInfo is NULL\n"); + return; + } + + prGlueInfo = prAdapter->prGlueInfo; + prHifInfo = &prGlueInfo->rHifInfo; + prErrRecoveryCtrl = &prHifInfo->rErrRecoveryCtl; + + if (prAdapter->chip_info->is_support_wfdma1) + u4HostWpdamBase = CONNAC2X_HOST_WPDMA_1_BASE; + else + u4HostWpdamBase = CONNAC2X_HOST_WPDMA_0_BASE; + + kalDevRegRead(prGlueInfo, + CONNAC2X_WPDMA_MCU2HOST_SW_INT_STA(u4HostWpdamBase), + &u4Status); + + prErrRecoveryCtrl->u4BackupStatus = u4Status; + if (u4Status & ERROR_DETECT_MASK) { + prErrRecoveryCtrl->u4Status = u4Status; + kalDevRegWrite(prGlueInfo, + CONNAC2X_WPDMA_MCU2HOST_SW_INT_STA(u4HostWpdamBase), + u4Status); + halHwRecoveryFromError(prAdapter); + } else { + kalDevRegWrite(prGlueInfo, + CONNAC2X_WPDMA_MCU2HOST_SW_INT_STA(u4HostWpdamBase), + u4Status); + DBGLOG(HAL, ERROR, "undefined SER status[0x%x].\n", u4Status); + } +} + + +void asicConnac2xSoftwareInterruptMcu( + struct ADAPTER *prAdapter, u_int32_t intrBitMask) +{ + struct GLUE_INFO *prGlueInfo; + uint32_t u4McuWpdamBase = 0; + + if (prAdapter == NULL || prAdapter->prGlueInfo == NULL) { + DBGLOG(HAL, ERROR, "prAdapter or prGlueInfo is NULL\n"); + return; + } + + prGlueInfo = prAdapter->prGlueInfo; + if (prAdapter->chip_info->is_support_wfdma1) + u4McuWpdamBase = CONNAC2X_MCU_WPDMA_1_BASE; + else + u4McuWpdamBase = CONNAC2X_MCU_WPDMA_0_BASE; + kalDevRegWrite(prGlueInfo, + CONNAC2X_WPDMA_HOST2MCU_SW_INT_SET(u4McuWpdamBase), + intrBitMask); +} + + +void asicConnac2xHifRst( + struct GLUE_INFO *prGlueInfo) +{ + uint32_t u4HifRstCr; + + u4HifRstCr = asicConnac2xWfdmaHifRstAddrGet(prGlueInfo, 0); + /* Reset dmashdl and wpdma */ + kalDevRegWrite(prGlueInfo, u4HifRstCr, 0x00000000); + kalDevRegWrite(prGlueInfo, u4HifRstCr, 0x00000030); + + u4HifRstCr = asicConnac2xWfdmaHifRstAddrGet(prGlueInfo, 1); + /* Reset dmashdl and wpdma */ + kalDevRegWrite(prGlueInfo, u4HifRstCr, 0x00000000); + kalDevRegWrite(prGlueInfo, u4HifRstCr, 0x00000030); +} + +void asicConnac2xReadExtIntStatus( + struct ADAPTER *prAdapter, + uint32_t *pu4IntStatus) +{ + uint32_t u4RegValue = 0; + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + struct BUS_INFO *prBusInfo = prAdapter->chip_info->bus_info; + + *pu4IntStatus = 0; + + HAL_MCR_RD(prAdapter, + CONNAC2X_WPDMA_EXT_INT_STA( + prBusInfo->host_ext_conn_hif_wrap_base), + &u4RegValue); + + if (HAL_IS_CONNAC2X_EXT_RX_DONE_INTR(u4RegValue, + prBusInfo->host_int_rxdone_bits)) + *pu4IntStatus |= WHISR_RX0_DONE_INT; + + if (HAL_IS_CONNAC2X_EXT_TX_DONE_INTR(u4RegValue, + prBusInfo->host_int_txdone_bits)) + *pu4IntStatus |= WHISR_TX_DONE_INT; + + if (u4RegValue & CONNAC_MCU_SW_INT) + *pu4IntStatus |= WHISR_D2H_SW_INT; + + prHifInfo->u4IntStatus = u4RegValue; + + /* clear interrupt */ + HAL_MCR_WR(prAdapter, + CONNAC2X_WPDMA_EXT_INT_STA( + prBusInfo->host_ext_conn_hif_wrap_base), + u4RegValue); +} + +void asicConnac2xProcessRxInterrupt( + struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + union WPDMA_INT_STA_STRUCT rIntrStatus; + + rIntrStatus = (union WPDMA_INT_STA_STRUCT)prHifInfo->u4IntStatus; + if (rIntrStatus.field_conn2x_ext.wfdma1_rx_done_0) + halRxReceiveRFBs(prAdapter, WFDMA1_RX_RING_IDX_0, FALSE); + if (rIntrStatus.field_conn2x_ext.wfdma1_rx_done_1) + halRxReceiveRFBs(prAdapter, WFDMA1_RX_RING_IDX_1, FALSE); + if (rIntrStatus.field_conn2x_ext.wfdma1_rx_done_2) + halRxReceiveRFBs(prAdapter, WFDMA1_RX_RING_IDX_2, FALSE); + if (rIntrStatus.field_conn2x_ext.wfdma0_rx_done_0) + halRxReceiveRFBs(prAdapter, RX_RING_DATA_IDX_0, TRUE); + if (rIntrStatus.field_conn2x_ext.wfdma0_rx_done_1) + halRxReceiveRFBs(prAdapter, RX_RING_EVT_IDX_1, TRUE); + if (rIntrStatus.field_conn2x_ext.wfdma0_rx_done_2) + halRxReceiveRFBs(prAdapter, WFDMA0_RX_RING_IDX_2, TRUE); + if (rIntrStatus.field_conn2x_ext.wfdma0_rx_done_3) + halRxReceiveRFBs(prAdapter, WFDMA0_RX_RING_IDX_3, TRUE); +} +#endif /* _HIF_PCIE */ + +#if defined(_HIF_USB) +/* + * tx_ring config + * 1.1tx_ring_ext_ctrl + * 7c025600[31:0]: 0x00800004 (ring 0 BASE_PTR & max_cnt for EP4) + * 7c025604[31:0]: 0x00c00004 (ring 1 BASE_PTR & max_cnt for EP5) + * 7c025608[31:0]: 0x01000004 (ring 2 BASE_PTR & max_cnt for EP6) + * 7c02560c[31:0]: 0x01400004 (ring 3 BASE_PTR & max_cnt for EP7) + * 7c025610[31:0]: 0x01800004 (ring 4 BASE_PTR & max_cnt for EP9) + * 7c025640[31:0]: 0x02800004 (ring 16 BASE_PTR & max_cnt for EP4/FWDL) + * 7c025644[31:0]: 0x02c00004 (ring 17 BASE_PTR & max_cnt for EP8/WMCPU) + * 7c025650[31:0]: 0x03800004 (ring 20 BASE_PTR & max_cnt for EP8/WACPU) + * + * WFDMA_GLO_CFG Setting + * 2.1 WFDMA_GLO_CFG: 7c025208[28][27]=2'b11; + * 2.2 WFDMA_GLO_CFG: 7c025208[20]=1'b1; + * 2.3 WFDMA_GLO_CFG: 7c025208[9]=1'b1; + * + * 3. trx_dma_en: + * 3.1 WFDMA_GLO_CFG: 7c025208[2][0]=1'b1; + */ +void asicConnac2xWfdmaInitForUSB( + struct ADAPTER *prAdapter, + struct mt66xx_chip_info *prChipInfo) +{ + struct BUS_INFO *prBusInfo; + uint32_t idx; + uint32_t u4WfdmaAddr, u4WfdmaCr; + + prBusInfo = prChipInfo->bus_info; + + if (prChipInfo->is_support_wfdma1) { + u4WfdmaAddr = + CONNAC2X_TX_RING_EXT_CTRL_BASE(CONNAC2X_HOST_WPDMA_1_BASE); + } else { + u4WfdmaAddr = + CONNAC2X_TX_RING_EXT_CTRL_BASE(CONNAC2X_HOST_WPDMA_0_BASE); + } + /* + * HOST_DMA1_WPDMA_TX_RING0_EXT_CTRL ~ HOST_DMA1_WPDMA_TX_RING4_EXT_CTRL + */ + for (idx = 0; idx < USB_TX_EPOUT_NUM; idx++) { + HAL_MCR_RD(prAdapter, u4WfdmaAddr + (idx*4), &u4WfdmaCr); + u4WfdmaCr &= ~CONNAC2X_WFDMA_DISP_MAX_CNT_MASK; + u4WfdmaCr |= CONNAC2X_TX_RING_DISP_MAX_CNT; + u4WfdmaCr &= ~CONNAC2X_WFDMA_DISP_BASE_PTR_MASK; + u4WfdmaCr |= (0x008 + 0x4 * idx)<<20; + HAL_MCR_WR(prAdapter, u4WfdmaAddr + (idx*4), u4WfdmaCr); + } + + /* HOST_DMA1_WPDMA_TX_RING16_EXT_CTRL_ADDR */ + HAL_MCR_RD(prAdapter, u4WfdmaAddr + 0x40, &u4WfdmaCr); + u4WfdmaCr &= ~CONNAC2X_WFDMA_DISP_MAX_CNT_MASK; + u4WfdmaCr |= CONNAC2X_TX_RING_DISP_MAX_CNT; + u4WfdmaCr &= ~CONNAC2X_WFDMA_DISP_BASE_PTR_MASK; + u4WfdmaCr |= 0x02800000; + HAL_MCR_WR(prAdapter, u4WfdmaAddr + 0x40, u4WfdmaCr); + + /* HOST_DMA1_WPDMA_TX_RING17_EXT_CTRL_ADDR */ + HAL_MCR_RD(prAdapter, u4WfdmaAddr + 0x44, &u4WfdmaCr); + u4WfdmaCr &= ~CONNAC2X_WFDMA_DISP_MAX_CNT_MASK; + u4WfdmaCr |= CONNAC2X_TX_RING_DISP_MAX_CNT; + u4WfdmaCr &= ~CONNAC2X_WFDMA_DISP_BASE_PTR_MASK; + u4WfdmaCr |= 0x02c00000; + HAL_MCR_WR(prAdapter, u4WfdmaAddr + 0x44, u4WfdmaCr); + + + if (prChipInfo->is_support_wacpu) { + /* HOST_DMA1_WPDMA_TX_RING20_EXT_CTRL_ADDR */ + HAL_MCR_RD(prAdapter, u4WfdmaAddr + 0x50, &u4WfdmaCr); + u4WfdmaCr &= ~CONNAC2X_WFDMA_DISP_MAX_CNT_MASK; + u4WfdmaCr |= CONNAC2X_TX_RING_DISP_MAX_CNT; + u4WfdmaCr &= ~CONNAC2X_WFDMA_DISP_BASE_PTR_MASK; + u4WfdmaCr |= 0x03800000; + HAL_MCR_WR(prAdapter, u4WfdmaAddr + 0x50, u4WfdmaCr); + } + + if (prChipInfo->is_support_wfdma1) { + u4WfdmaAddr = + CONNAC2X_WPDMA_GLO_CFG(CONNAC2X_HOST_WPDMA_1_BASE); + HAL_MCR_RD(prAdapter, u4WfdmaAddr, &u4WfdmaCr); + u4WfdmaCr |= + (CONNAC2X_WPDMA1_GLO_CFG_OMIT_TX_INFO | + CONNAC2X_WPDMA1_GLO_CFG_OMIT_RX_INFO | + CONNAC2X_WPDMA1_GLO_CFG_FW_DWLD_Bypass_dmashdl | + CONNAC2X_WPDMA1_GLO_CFG_RX_DMA_EN | + CONNAC2X_WPDMA1_GLO_CFG_TX_DMA_EN); + HAL_MCR_WR(prAdapter, u4WfdmaAddr, u4WfdmaCr); + + /* Enable WFDMA0 RX for receiving data frame */ + u4WfdmaAddr = + CONNAC2X_WPDMA_GLO_CFG(CONNAC2X_HOST_WPDMA_0_BASE); + HAL_MCR_RD(prAdapter, u4WfdmaAddr, &u4WfdmaCr); + u4WfdmaCr |= + (CONNAC2X_WPDMA1_GLO_CFG_RX_DMA_EN); + HAL_MCR_WR(prAdapter, u4WfdmaAddr, u4WfdmaCr); + } else { + u4WfdmaAddr = + CONNAC2X_WPDMA_GLO_CFG(CONNAC2X_HOST_WPDMA_0_BASE); + HAL_MCR_RD(prAdapter, u4WfdmaAddr, &u4WfdmaCr); + u4WfdmaCr &= ~(CONNAC2X_WPDMA1_GLO_CFG_OMIT_RX_INFO); + u4WfdmaCr |= + (CONNAC2X_WPDMA1_GLO_CFG_OMIT_TX_INFO | + CONNAC2X_WPDMA1_GLO_CFG_OMIT_RX_INFO_PFET2 | + CONNAC2X_WPDMA1_GLO_CFG_FW_DWLD_Bypass_dmashdl | + CONNAC2X_WPDMA1_GLO_CFG_RX_DMA_EN | + CONNAC2X_WPDMA1_GLO_CFG_TX_DMA_EN); + HAL_MCR_WR(prAdapter, u4WfdmaAddr, u4WfdmaCr); + + } + + prChipInfo->is_support_dma_shdl = wlanCfgGetUint32(prAdapter, + "DmaShdlEnable", + FEATURE_ENABLED); + if (!prChipInfo->is_support_dma_shdl) { + /* + * To disable 0x7C0252B0[6] DMASHDL + */ + if (prChipInfo->is_support_wfdma1) { + u4WfdmaAddr = CONNAC2X_WPDMA_GLO_CFG_EXT0( + CONNAC2X_HOST_WPDMA_1_BASE); + } else { + u4WfdmaAddr = CONNAC2X_WPDMA_GLO_CFG_EXT0( + CONNAC2X_HOST_WPDMA_0_BASE); + } + HAL_MCR_RD(prAdapter, u4WfdmaAddr, &u4WfdmaCr); + u4WfdmaCr &= ~CONNAC2X_WPDMA1_GLO_CFG_EXT0_TX_DMASHDL_EN; + HAL_MCR_WR(prAdapter, u4WfdmaAddr, u4WfdmaCr); + + /* + * [28]DMASHDL_BYPASS + * DMASHDL host ask and quota control function bypass + * 0: Disable + * 1: Enable + */ + u4WfdmaAddr = CONNAC2X_HOST_DMASHDL_SW_CONTROL( + CONNAC2X_HOST_DMASHDL); + HAL_MCR_RD(prAdapter, u4WfdmaAddr, &u4WfdmaCr); + u4WfdmaCr |= CONNAC2X_HIF_DMASHDL_BYPASS_EN; + HAL_MCR_WR(prAdapter, u4WfdmaAddr, u4WfdmaCr); + } + + if (prChipInfo->asicUsbInit_ic_specific) + prChipInfo->asicUsbInit_ic_specific(prAdapter, prChipInfo); +} + +static void asicConnac2xUsbRxEvtEP4Setting( + struct ADAPTER *prAdapter, + u_int8_t fgEnable) +{ + struct GLUE_INFO *prGlueInfo; + struct BUS_INFO *prBusInfo; + uint32_t u4Value = 0; + uint32_t u4WfdmaValue = 0; + uint32_t i = 0; + uint32_t dma_base; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + prBusInfo = prAdapter->chip_info->bus_info; + if (prAdapter->chip_info->is_support_wfdma1) + dma_base = CONNAC2X_HOST_WPDMA_1_BASE; + else + dma_base = CONNAC2X_HOST_WPDMA_0_BASE; + HAL_MCR_RD(prAdapter, CONNAC2X_WFDMA_HOST_CONFIG_ADDR, &u4WfdmaValue); + if (fgEnable) + u4WfdmaValue |= CONNAC2X_WFDMA_HOST_CONFIG_USB_RXEVT_EP4_EN; + else + u4WfdmaValue &= ~CONNAC2X_WFDMA_HOST_CONFIG_USB_RXEVT_EP4_EN; + do { + HAL_MCR_RD(prAdapter, CONNAC2X_WPDMA_GLO_CFG(dma_base), + &u4Value); + if ((u4Value & CONNAC2X_WPDMA1_GLO_CFG_RX_DMA_BUSY) == 0) { + u4Value &= ~CONNAC2X_WPDMA1_GLO_CFG_RX_DMA_EN; + HAL_MCR_WR(prAdapter, CONNAC2X_WPDMA_GLO_CFG(dma_base), + u4Value); + break; + } + kalUdelay(1000); + } while ((i++) < 100); + if (i > 100) + DBGLOG(HAL, ERROR, "WFDMA1 RX keep busy....\n"); + else { + HAL_MCR_WR(prAdapter, + CONNAC2X_WFDMA_HOST_CONFIG_ADDR, + u4WfdmaValue); + HAL_MCR_RD(prAdapter, CONNAC2X_WPDMA_GLO_CFG(dma_base), + &u4Value); + u4Value |= CONNAC2X_WPDMA1_GLO_CFG_RX_DMA_EN; + HAL_MCR_WR(prAdapter, CONNAC2X_WPDMA_GLO_CFG(dma_base), + u4Value); + } +} + + +uint8_t asicConnac2xUsbEventEpDetected(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct BUS_INFO *prBusInfo = NULL; + int32_t ret = 0; + uint8_t ucRetryCount = 0; + u_int8_t ucEp5Disable = FALSE; + + ASSERT(FALSE == 0); + prGlueInfo = prAdapter->prGlueInfo; + prHifInfo = &prGlueInfo->rHifInfo; + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + + if (prHifInfo->fgEventEpDetected == FALSE) { + prHifInfo->fgEventEpDetected = TRUE; + do { + ret = mtk_usb_vendor_request(prGlueInfo, 0, + prBusInfo->u4device_vender_request_in, + VND_REQ_EP5_IN_INFO, + 0, 0, &ucEp5Disable, + sizeof(ucEp5Disable)); + if (ret || ucRetryCount) + DBGLOG(HAL, ERROR, + "usb_control_msg() status: %x retry: %u\n", + (unsigned int)ret, ucRetryCount); + ucRetryCount++; + if (ucRetryCount > USB_ACCESS_RETRY_LIMIT) + break; + } while (ret); + + if (ret) { + kalSendAeeWarning(HIF_USB_ERR_TITLE_STR, + HIF_USB_ERR_DESC_STR + "USB() reports error: %x retry: %u", + ret, ucRetryCount); + DBGLOG(HAL, ERROR, + "usb_readl() reports error: %x retry: %u\n", ret, + ucRetryCount); + } else { + DBGLOG(HAL, INFO, + "%s: Get ucEp5Disable = %d\n", __func__, + ucEp5Disable); + if (ucEp5Disable) + prHifInfo->eEventEpType = EVENT_EP_TYPE_DATA_EP; + } + + if (prHifInfo->eEventEpType == EVENT_EP_TYPE_DATA_EP) + asicConnac2xUsbRxEvtEP4Setting(prAdapter, TRUE); + else + asicConnac2xUsbRxEvtEP4Setting(prAdapter, FALSE); + } + + if (prHifInfo->eEventEpType == EVENT_EP_TYPE_DATA_EP) + return USB_DATA_EP_IN; + else + return USB_EVENT_EP_IN; +} + +void asicConnac2xEnableUsbCmdTxRing( + struct ADAPTER *prAdapter, + u_int8_t ucDstRing) +{ + struct GLUE_INFO *prGlueInfo; + struct BUS_INFO *prBusInfo; + uint32_t u4Value = 0; + uint32_t u4WfdmaValue = 0; + uint32_t i = 0; + uint32_t dma_base; + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + prBusInfo = prAdapter->chip_info->bus_info; + if (prAdapter->chip_info->is_support_wfdma1) + dma_base = CONNAC2X_HOST_WPDMA_1_BASE; + else + dma_base = CONNAC2X_HOST_WPDMA_0_BASE; + + HAL_MCR_RD(prAdapter, CONNAC2X_WFDMA_HOST_CONFIG_ADDR, &u4WfdmaValue); + u4WfdmaValue &= ~CONNAC2X_WFDMA_HOST_CONFIG_USB_CMDPKT_DST_MASK; + u4WfdmaValue |= CONNAC2X_WFDMA_HOST_CONFIG_USB_CMDPKT_DST(ucDstRing); + do { + HAL_MCR_RD(prAdapter, CONNAC2X_WPDMA_GLO_CFG(dma_base), + &u4Value); + if ((u4Value & CONNAC2X_WPDMA1_GLO_CFG_TX_DMA_BUSY) == 0) { + u4Value &= ~CONNAC2X_WPDMA1_GLO_CFG_TX_DMA_EN; + HAL_MCR_WR(prAdapter, CONNAC2X_WPDMA_GLO_CFG(dma_base), + u4Value); + break; + } + kalUdelay(1000); + } while ((i++) < 100); + if (i > 100) + DBGLOG(HAL, ERROR, "WFDMA1 TX keep busy....\n"); + else { + HAL_MCR_WR(prAdapter, + CONNAC2X_WFDMA_HOST_CONFIG_ADDR, + u4WfdmaValue); + HAL_MCR_RD(prAdapter, CONNAC2X_WPDMA_GLO_CFG(dma_base), + &u4Value); + u4Value |= CONNAC2X_WPDMA1_GLO_CFG_TX_DMA_EN; + HAL_MCR_WR(prAdapter, CONNAC2X_WPDMA_GLO_CFG(dma_base), + u4Value); + } +} + +#if CFG_ENABLE_FW_DOWNLOAD +void asicConnac2xEnableUsbFWDL( + struct ADAPTER *prAdapter, + u_int8_t fgEnable) +{ + struct GLUE_INFO *prGlueInfo; + struct BUS_INFO *prBusInfo; + struct mt66xx_chip_info *prChipInfo; + + uint32_t u4Value = 0; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + prChipInfo = prAdapter->chip_info; + prBusInfo = prChipInfo->bus_info; + + HAL_MCR_RD(prAdapter, prBusInfo->u4UdmaTxQsel, &u4Value); + if (fgEnable) { + u4Value |= FW_DL_EN; + } else { + u4Value &= ~FW_DL_EN; + } + + HAL_MCR_WR(prAdapter, prBusInfo->u4UdmaTxQsel, u4Value); + + if (prChipInfo->is_support_wacpu) { + /* command packet forward to TX ring 17 (WMCPU) or + * TX ring 20 (WACPU) + */ + asicConnac2xEnableUsbCmdTxRing(prAdapter, + fgEnable ? CONNAC2X_USB_CMDPKT2WM : + CONNAC2X_USB_CMDPKT2WA); + } +} +#endif /* CFG_ENABLE_FW_DOWNLOAD */ +u_int8_t asicConnac2xUsbResume(IN struct ADAPTER *prAdapter, + IN struct GLUE_INFO *prGlueInfo) +{ + uint8_t count = 0; + struct mt66xx_chip_info *prChipInfo = NULL; + + prChipInfo = prAdapter->chip_info; + +#if 0 /* enable it if need to do bug fixing by vender request */ + /* NOTE: USB bus may not really do suspend and resume*/ + ret = usb_control_msg(prGlueInfo->rHifInfo.udev, + usb_sndctrlpipe(prGlueInfo->rHifInfo.udev, 0), + VND_REQ_FEATURE_SET, + prBusInfo->u4device_vender_request_out, + FEATURE_SET_WVALUE_RESUME, 0, NULL, 0, + VENDOR_TIMEOUT_MS); + if (ret) + DBGLOG(HAL, ERROR, + "VendorRequest FeatureSetResume ERROR: %x\n", + (unsigned int)ret); +#endif + + glUsbSetState(&prGlueInfo->rHifInfo, USB_STATE_PRE_RESUME); + + /* reinit USB because LP could clear WFDMA's CR */ + if (prChipInfo->is_support_asic_lp && prChipInfo->asicUsbInit) + prChipInfo->asicUsbInit(prAdapter, prChipInfo); + + /* To trigger CR4 path */ + wlanSendDummyCmd(prGlueInfo->prAdapter, FALSE); + halEnableInterrupt(prGlueInfo->prAdapter); + + /* using inband cmd to inform FW instead of vendor request */ + /* All Resume operations move to FW */ + halUSBPreResumeCmd(prGlueInfo->prAdapter); + + while (prGlueInfo->rHifInfo.state != USB_STATE_LINK_UP) { + if (count > 50) { + DBGLOG(HAL, ERROR, "pre_resume timeout\n"); + break; + } + msleep(20); + count++; + } + + DBGLOG(HAL, STATE, "pre_resume event check(count %d)\n", count); + + wlanResumePmHandle(prGlueInfo); + + return TRUE; +} + +void asicConnac2xUdmaRxFlush( + struct ADAPTER *prAdapter, + u_int8_t bEnable) +{ + struct BUS_INFO *prBusInfo; + uint32_t u4Value; + + prBusInfo = prAdapter->chip_info->bus_info; + + HAL_MCR_RD(prAdapter, prBusInfo->u4UdmaWlCfg_0_Addr, + &u4Value); + if (bEnable) + u4Value |= UDMA_WLCFG_0_RX_FLUSH_MASK; + else + u4Value &= ~UDMA_WLCFG_0_RX_FLUSH_MASK; + HAL_MCR_WR(prAdapter, prBusInfo->u4UdmaWlCfg_0_Addr, + u4Value); +} + +uint16_t asicConnac2xUsbRxByteCount( + struct ADAPTER *prAdapter, + struct BUS_INFO *prBusInfo, + uint8_t *pRXD) +{ + + uint16_t u2RxByteCount; + uint8_t ucPacketType; + + ucPacketType = HAL_MAC_CONNAC2X_RX_STATUS_GET_PKT_TYPE( + (struct HW_MAC_CONNAC2X_RX_DESC *)pRXD); + u2RxByteCount = HAL_MAC_CONNAC2X_RX_STATUS_GET_RX_BYTE_CNT( + (struct HW_MAC_CONNAC2X_RX_DESC *)pRXD); + + /* According to Barry's rule, it can be summarized as below formula: + * 1. Event packet (including WIFI packet sent by MCU) + -> RX padding for 4B alignment + * 2. WIFI packet from UMAC + * -> RX padding for 8B alignment first, + then extra 4B padding + */ + if (ucPacketType == RX_PKT_TYPE_RX_DATA) + u2RxByteCount = ALIGN_8(u2RxByteCount) + + LEN_USB_RX_PADDING_CSO; + else + u2RxByteCount = ALIGN_4(u2RxByteCount); + + return u2RxByteCount; +} + +#endif /* _HIF_USB */ + +void fillConnac2xTxDescTxByteCount( + struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + void *prTxDesc) +{ + struct mt66xx_chip_info *prChipInfo; + uint32_t u4TxByteCount = NIC_TX_DESC_LONG_FORMAT_LENGTH; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + ASSERT(prTxDesc); + + prChipInfo = prAdapter->chip_info; + u4TxByteCount += prMsduInfo->u2FrameLength; + + if (prMsduInfo->ucPacketType == TX_PACKET_TYPE_DATA) + u4TxByteCount += prChipInfo->u4ExtraTxByteCount; + + /* Calculate Tx byte count */ + HAL_MAC_CONNAC2X_TXD_SET_TX_BYTE_COUNT( + (struct HW_MAC_CONNAC2X_TX_DESC *)prTxDesc, u4TxByteCount); +} + +void fillConnac2xTxDescAppendWithWaCpu( + struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + uint8_t *prTxDescBuffer) +{ + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + union HW_MAC_TX_DESC_APPEND *prHwTxDescAppend; + + /* Fill TxD append */ + prHwTxDescAppend = (union HW_MAC_TX_DESC_APPEND *) + prTxDescBuffer; + kalMemZero(prHwTxDescAppend, prChipInfo->txd_append_size); + prHwTxDescAppend->CR4_APPEND.u2PktFlags = + HIF_PKT_FLAGS_CT_INFO_APPLY_TXD; + prHwTxDescAppend->CR4_APPEND.ucBssIndex = + prMsduInfo->ucBssIndex; + prHwTxDescAppend->CR4_APPEND.ucWtblIndex = + prMsduInfo->ucWlanIndex; +} + +void fillConnac2xTxDescAppendByWaCpu( + struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + uint16_t u4MsduId, + dma_addr_t rDmaAddr, + uint32_t u4Idx, + u_int8_t fgIsLast, + uint8_t *pucBuffer) +{ + union HW_MAC_TX_DESC_APPEND *prHwTxDescAppend; + + prHwTxDescAppend = (union HW_MAC_TX_DESC_APPEND *) + (pucBuffer + NIC_TX_DESC_LONG_FORMAT_LENGTH); + prHwTxDescAppend->CR4_APPEND.u2MsduToken = u4MsduId; + prHwTxDescAppend->CR4_APPEND.ucBufNum = u4Idx + 1; + prHwTxDescAppend->CR4_APPEND.au4BufPtr[u4Idx] = rDmaAddr; + prHwTxDescAppend->CR4_APPEND.au2BufLen[u4Idx] = + prMsduInfo->u2FrameLength; +} + +void fillTxDescTxByteCountWithWaCpu( + struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + void *prTxDesc) +{ + struct mt66xx_chip_info *prChipInfo; + uint32_t u4TxByteCount = NIC_TX_DESC_LONG_FORMAT_LENGTH; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + ASSERT(prTxDesc); + + prChipInfo = prAdapter->chip_info; + u4TxByteCount += prMsduInfo->u2FrameLength; + + if (prMsduInfo->ucPacketType == TX_PACKET_TYPE_DATA) + u4TxByteCount += prChipInfo->txd_append_size; + + /* Calculate Tx byte count */ + HAL_MAC_CONNAC2X_TXD_SET_TX_BYTE_COUNT( + (struct HW_MAC_CONNAC2X_TX_DESC *)prTxDesc, u4TxByteCount); +} + +void asicConnac2xInitTxdHook( + struct TX_DESC_OPS_T *prTxDescOps) +{ + ASSERT(prTxDescOps); + prTxDescOps->nic_txd_long_format_op = nic_txd_v2_long_format_op; + prTxDescOps->nic_txd_tid_op = nic_txd_v2_tid_op; + prTxDescOps->nic_txd_queue_idx_op = nic_txd_v2_queue_idx_op; +#if (CFG_TCP_IP_CHKSUM_OFFLOAD == 1) + prTxDescOps->nic_txd_chksum_op = nic_txd_v2_chksum_op; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD == 1 */ + prTxDescOps->nic_txd_header_format_op = nic_txd_v2_header_format_op; + prTxDescOps->nic_txd_fill_by_pkt_option = nic_txd_v2_fill_by_pkt_option; + prTxDescOps->nic_txd_compose = nic_txd_v2_compose; + prTxDescOps->nic_txd_compose_security_frame = + nic_txd_v2_compose_security_frame; + prTxDescOps->nic_txd_set_pkt_fixed_rate_option_full = + nic_txd_v2_set_pkt_fixed_rate_option_full; + prTxDescOps->nic_txd_set_pkt_fixed_rate_option = + nic_txd_v2_set_pkt_fixed_rate_option; + prTxDescOps->nic_txd_set_hw_amsdu_template = + nic_txd_v2_set_hw_amsdu_template; +} + +void asicConnac2xInitRxdHook( + struct RX_DESC_OPS_T *prRxDescOps) +{ + ASSERT(prRxDescOps); + prRxDescOps->nic_rxd_get_rx_byte_count = nic_rxd_v2_get_rx_byte_count; + prRxDescOps->nic_rxd_get_pkt_type = nic_rxd_v2_get_packet_type; + prRxDescOps->nic_rxd_get_wlan_idx = nic_rxd_v2_get_wlan_idx; + prRxDescOps->nic_rxd_get_sec_mode = nic_rxd_v2_get_sec_mode; + prRxDescOps->nic_rxd_get_sw_class_error_bit = + nic_rxd_v2_get_sw_class_error_bit; + prRxDescOps->nic_rxd_get_ch_num = nic_rxd_v2_get_ch_num; + prRxDescOps->nic_rxd_get_rf_band = nic_rxd_v2_get_rf_band; + prRxDescOps->nic_rxd_get_tcl = nic_rxd_v2_get_tcl; + prRxDescOps->nic_rxd_get_ofld = nic_rxd_v2_get_ofld; + prRxDescOps->nic_rxd_fill_rfb = nic_rxd_v2_fill_rfb; + prRxDescOps->nic_rxd_sanity_check = nic_rxd_v2_sanity_check; + prRxDescOps->nic_rxd_check_wakeup_reason = + nic_rxd_v2_check_wakeup_reason; +} + +#if (CFG_SUPPORT_MSP == 1) +void asicConnac2xRxProcessRxvforMSP(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prRetSwRfb) { + struct HW_MAC_RX_STS_GROUP_3_V2 *prGroup3; + + if (prRetSwRfb->ucStaRecIdx >= CFG_STA_REC_NUM) { + DBGLOG(RX, LOUD, + "prRetSwRfb->ucStaRecIdx(%d) >= CFG_STA_REC_NUM(%d)\n", + prRetSwRfb->ucStaRecIdx, CFG_STA_REC_NUM); + return; + } + + prGroup3 = + (struct HW_MAC_RX_STS_GROUP_3_V2 *)prRetSwRfb->prRxStatusGroup3; + if (prRetSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_3)) { + /* P-RXV1[0:31] */ + prAdapter->arStaRec[ + prRetSwRfb->ucStaRecIdx].u4RxVector0 = + CONNAC2X_HAL_RX_VECTOR_GET_RX_VECTOR(prGroup3, 0); + prAdapter->arStaRec[ + prRetSwRfb->ucStaRecIdx].u4RxVector4 = + CONNAC2X_HAL_RX_VECTOR_GET_RX_VECTOR(prGroup3, 1); + } else { + prAdapter->arStaRec[ + prRetSwRfb->ucStaRecIdx].u4RxVector0 = 0; + prAdapter->arStaRec[ + prRetSwRfb->ucStaRecIdx].u4RxVector4 = 0; + } + + if (prRetSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_5)) { + /* C-B-0[0:31] */ + prAdapter->arStaRec[ + prRetSwRfb->ucStaRecIdx].u4RxVector1 = + CONNAC2X_HAL_RX_VECTOR_GET_RX_VECTOR( + prRetSwRfb->prRxStatusGroup5, 0); + /* C-B-1[0:31] */ + prAdapter->arStaRec[ + prRetSwRfb->ucStaRecIdx].u4RxVector2 = + CONNAC2X_HAL_RX_VECTOR_GET_RX_VECTOR( + prRetSwRfb->prRxStatusGroup5, 2); + /* C-B-2[0:31] */ + prAdapter->arStaRec[ + prRetSwRfb->ucStaRecIdx].u4RxVector3 = + CONNAC2X_HAL_RX_VECTOR_GET_RX_VECTOR( + prRetSwRfb->prRxStatusGroup5, 4); + /* C-B-3[0:31] */ + prAdapter->arStaRec[ + prRetSwRfb->ucStaRecIdx].u4RxVector4 = + CONNAC2X_HAL_RX_VECTOR_GET_RX_VECTOR( + prRetSwRfb->prRxStatusGroup5, 6); + } else { + prAdapter->arStaRec[ + prRetSwRfb->ucStaRecIdx].u4RxVector1 = 0; + prAdapter->arStaRec[ + prRetSwRfb->ucStaRecIdx].u4RxVector2 = 0; + prAdapter->arStaRec[ + prRetSwRfb->ucStaRecIdx].u4RxVector3 = 0; + } +} +#endif /* CFG_SUPPORT_MSP == 1 */ + +uint8_t asicConnac2xRxGetRcpiValueFromRxv( + IN uint8_t ucRcpiMode, + IN struct SW_RFB *prSwRfb) +{ + uint8_t ucRcpi0, ucRcpi1, ucRcpi2, ucRcpi3; + uint8_t ucRcpiValue = 0; + /* falcon IP donot have this field 'ucRxNum' */ + /* uint8_t ucRxNum; */ + + ASSERT(prSwRfb); + + if (ucRcpiMode >= RCPI_MODE_NUM) { + DBGLOG(RX, WARN, + "Rcpi Mode = %d is invalid for getting uint8_t value from RXV\n", + ucRcpiMode); + return 0; + } + + ucRcpi0 = HAL_RX_STATUS_GET_RCPI0( + (struct HW_MAC_RX_STS_GROUP_3_V2 *) + prSwRfb->prRxStatusGroup3); + ucRcpi1 = HAL_RX_STATUS_GET_RCPI1( + (struct HW_MAC_RX_STS_GROUP_3_V2 *) + prSwRfb->prRxStatusGroup3); + ucRcpi2 = HAL_RX_STATUS_GET_RCPI2( + (struct HW_MAC_RX_STS_GROUP_3_V2 *) + prSwRfb->prRxStatusGroup3); + ucRcpi3 = HAL_RX_STATUS_GET_RCPI3( + (struct HW_MAC_RX_STS_GROUP_3_V2 *) + prSwRfb->prRxStatusGroup3); + + /*If Rcpi is not available, set it to zero*/ + if (ucRcpi0 == RCPI_MEASUREMENT_NOT_AVAILABLE) + ucRcpi0 = RCPI_LOW_BOUND; + if (ucRcpi1 == RCPI_MEASUREMENT_NOT_AVAILABLE) + ucRcpi1 = RCPI_LOW_BOUND; + DBGLOG(RX, TRACE, "RCPI WF0:%d WF1:%d WF2:%d WF3:%d\n", + ucRcpi0, ucRcpi1, ucRcpi2, ucRcpi3); + + switch (ucRcpiMode) { + case RCPI_MODE_WF0: + ucRcpiValue = ucRcpi0; + break; + + case RCPI_MODE_WF1: + ucRcpiValue = ucRcpi1; + break; + + case RCPI_MODE_WF2: + ucRcpiValue = ucRcpi2; + break; + + case RCPI_MODE_WF3: + ucRcpiValue = ucRcpi3; + break; + + case RCPI_MODE_AVG: /*Not recommended for CBW80+80*/ + ucRcpiValue = (ucRcpi0 + ucRcpi1) / 2; + break; + + case RCPI_MODE_MAX: + ucRcpiValue = + (ucRcpi0 > ucRcpi1) ? (ucRcpi0) : (ucRcpi1); + break; + + case RCPI_MODE_MIN: + ucRcpiValue = + (ucRcpi0 < ucRcpi1) ? (ucRcpi0) : (ucRcpi1); + break; + + default: + break; + } + + return ucRcpiValue; +} + +#if (CFG_SUPPORT_PERF_IND == 1) +void asicConnac2xRxPerfIndProcessRXV(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint8_t ucBssIndex) +{ + struct HW_MAC_RX_STS_GROUP_3 *prRxStatusGroup3; + uint8_t ucRCPI0 = 0, ucRCPI1 = 0; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + /* REMOVE DATA RATE Parsing Logic:Workaround only for 6885*/ + /* Since MT6885 can not get Rx Data Rate dur to RXV HW Bug*/ + + if (ucBssIndex >= BSSID_NUM) + return; + + /* can't parse radiotap info if no rx vector */ + if (((prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_2)) == 0) + || ((prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_3)) == 0)) { + return; + } + + prRxStatusGroup3 = prSwRfb->prRxStatusGroup3; + + /* RCPI */ + ucRCPI0 = HAL_RX_STATUS_GET_RCPI0(prRxStatusGroup3); + ucRCPI1 = HAL_RX_STATUS_GET_RCPI1(prRxStatusGroup3); + + /* Record peak rate to Traffic Indicator*/ + prAdapter->prGlueInfo->PerfIndCache. + ucCurRxRCPI0[ucBssIndex] = ucRCPI0; + prAdapter->prGlueInfo->PerfIndCache. + ucCurRxRCPI1[ucBssIndex] = ucRCPI1; + +} +#endif + +#if (CFG_CHIP_RESET_SUPPORT == 1) && (CFG_WMT_RESET_API_SUPPORT == 0) +u_int8_t conn2_rst_L0_notify_step2(void) +{ + if (glGetRstReason() == RST_BT_TRIGGER) { + typedef void (*p_bt_fun_type) (void); + p_bt_fun_type bt_func; + char *bt_func_name = "WF_rst_L0_notify_BT_step2"; + + bt_func = (p_bt_fun_type)(uintptr_t) + GLUE_LOOKUP_FUN(bt_func_name); + if (bt_func) { + bt_func(); + } else { + DBGLOG(INIT, WARN, "[SER][L0] %s does not exist\n", + bt_func_name); + return FALSE; + } + } else { + /* if wifi trigger, then wait bt ready notify */ + DBGLOG(INIT, WARN, "[SER][L0] not support..\n"); + } + + return TRUE; +} +#endif + +#endif /* CFG_SUPPORT_CONNAC2X == 1 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/common/dbg_connac.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/common/dbg_connac.c new file mode 100644 index 0000000000000..9289fb52440cf --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/common/dbg_connac.c @@ -0,0 +1,2259 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** + *[File] dbg_connac.c + *[Version] v1.0 + *[Revision Date] 2015-09-08 + *[Author] + *[Description] + * The program provides WIFI MAC Debug APIs + *[Copyright] + * Copyright (C) 2015 MediaTek Incorporation. All Rights Reserved. + ******************************************************************************/ + +/******************************************************************************* + * C O M P I L E 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 "pse.h" +#include "wf_ple.h" +#include "host_csr.h" +#include "dma_sch.h" +#include "mt_dmac.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 (CFG_SUPPORT_RA_GEN == 0) +static char *RATE_TBLE[] = {"B", "G", "N", "N_2SS", "AC", "AC_2SS", "N/A"}; +#else +static char *RATE_TBLE[] = {"B", "G", "N", "N_2SS", "AC", "AC_2SS", "BG", + "N/A"}; +static char *RA_STATUS_TBLE[] = {"INVALID", "POWER_SAVING", "SLEEP", "STANDBY", + "RUNNING", "N/A"}; +static char *LT_MODE_TBLE[] = {"RSSI", "LAST_RATE", "TRACKING", "N/A"}; +static char *SGI_UNSP_STATE_TBLE[] = {"INITIAL", "PROBING", "SUCCESS", + "FAILURE", "N/A"}; +static char *BW_STATE_TBLE[] = {"UNCHANGED", "DOWN", "N/A"}; +#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 + ******************************************************************************* + */ + +void halShowPseInfo(IN struct ADAPTER *prAdapter) +{ +#define BUF_SIZE 512 + + uint32_t pse_buf_ctrl = 0, pg_sz, pg_num; + uint32_t pse_stat = 0, pg_flow_ctrl[16] = {0}; + uint32_t fpg_cnt, ffa_cnt, fpg_head, fpg_tail; + uint32_t max_q, min_q, rsv_pg, used_pg; + uint32_t i, page_offset, addr, value = 0, pos = 0; + uint32_t txd_payload_info[16] = {0}; + char *buf; + + HAL_MCR_RD(prAdapter, PSE_PBUF_CTRL, &pse_buf_ctrl); + HAL_MCR_RD(prAdapter, PSE_QUEUE_EMPTY, &pse_stat); + HAL_MCR_RD(prAdapter, PSE_FREEPG_CNT, &pg_flow_ctrl[0]); + HAL_MCR_RD(prAdapter, PSE_FREEPG_HEAD_TAIL, &pg_flow_ctrl[1]); + HAL_MCR_RD(prAdapter, PSE_PG_HIF0_GROUP, &pg_flow_ctrl[2]); + HAL_MCR_RD(prAdapter, PSE_HIF0_PG_INFO, &pg_flow_ctrl[3]); + HAL_MCR_RD(prAdapter, PSE_PG_HIF1_GROUP, &pg_flow_ctrl[4]); + HAL_MCR_RD(prAdapter, PSE_HIF1_PG_INFO, &pg_flow_ctrl[5]); + HAL_MCR_RD(prAdapter, PSE_PG_CPU_GROUP, &pg_flow_ctrl[6]); + HAL_MCR_RD(prAdapter, PSE_CPU_PG_INFO, &pg_flow_ctrl[7]); + HAL_MCR_RD(prAdapter, PSE_PG_LMAC0_GROUP, &pg_flow_ctrl[8]); + HAL_MCR_RD(prAdapter, PSE_LMAC0_PG_INFO, &pg_flow_ctrl[9]); + HAL_MCR_RD(prAdapter, PSE_PG_LMAC1_GROUP, &pg_flow_ctrl[10]); + HAL_MCR_RD(prAdapter, PSE_LMAC1_PG_INFO, &pg_flow_ctrl[11]); + HAL_MCR_RD(prAdapter, PSE_PG_LMAC2_GROUP, &pg_flow_ctrl[12]); + HAL_MCR_RD(prAdapter, PSE_LMAC2_PG_INFO, &pg_flow_ctrl[13]); + HAL_MCR_RD(prAdapter, PSE_PG_PLE_GROUP, &pg_flow_ctrl[14]); + HAL_MCR_RD(prAdapter, PSE_PLE_PG_INFO, &pg_flow_ctrl[15]); + + /* Configuration Info */ + DBGLOG(HAL, INFO, "PSE Configuration Info:\n"); + + HAL_MCR_RD(prAdapter, PSE_GC, &value); + DBGLOG(HAL, INFO, "\tGC(0x82068000): 0x%08x\n", value); + HAL_MCR_RD(prAdapter, PSE_INT_STS, &value); + DBGLOG(HAL, INFO, "\tINT_STS(0x82068024): 0x%08x\n", value); + HAL_MCR_RD(prAdapter, PSE_INT_ERR_STS, &value); + DBGLOG(HAL, INFO, "\tINT_ERR_STS(0x82068028): 0x%08x\n", value); + + DBGLOG(HAL, INFO, "\tPacket Buffer Control(0x82068014): 0x%08x\n", + pse_buf_ctrl); + pg_sz = (pse_buf_ctrl & (0x1 << 31)) >> 31; + DBGLOG(HAL, INFO, + "\t\tPage Size=%d(%d bytes per page)\n", + pg_sz, (pg_sz == 1 ? 256 : 128)); + page_offset = (pse_buf_ctrl & 0x3FFFFFF) >> 17; + DBGLOG(HAL, INFO, + "\t\tPage Offset=%d(in unit of 2KB)\n", page_offset); + pg_num = (pse_buf_ctrl & PSE_TOTAL_PAGE_NUM_MASK); + DBGLOG(HAL, INFO, "\t\tAvailable Total Page=%d pages\n", pg_num); + /* Page Flow Control */ + DBGLOG(HAL, INFO, "PSE Page Flow Control:\n"); + + DBGLOG(HAL, INFO, + "\tFree page counter(0x82068100): 0x%08x\n", pg_flow_ctrl[0]); + fpg_cnt = pg_flow_ctrl[0] & 0xfff; + DBGLOG(HAL, INFO, + "\t\tThe toal page number of free=0x%03x\n", fpg_cnt); + ffa_cnt = (pg_flow_ctrl[0] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe free page numbers of free for all=0x%03x\n", ffa_cnt); + DBGLOG(HAL, INFO, + "\tFree page head and tail(0x82068104): 0x%08x\n", + pg_flow_ctrl[1]); + fpg_head = pg_flow_ctrl[1] & 0xfff; + fpg_tail = (pg_flow_ctrl[1] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe tail/head page of free page list=0x%03x/0x%03x\n", + fpg_tail, fpg_head); + DBGLOG(HAL, INFO, + "\tReserved page counter of HIF0 group(0x82068110): 0x%08x\n", + pg_flow_ctrl[2]); + DBGLOG(HAL, INFO, + "\tHIF0 group page status(0x82068114): 0x%08x\n", + pg_flow_ctrl[3]); + min_q = pg_flow_ctrl[2] & 0xfff; + max_q = (pg_flow_ctrl[2] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of HIF0 group=0x%03x/0x%03x\n", + max_q, min_q); + rsv_pg = pg_flow_ctrl[3] & 0xfff; + used_pg = (pg_flow_ctrl[3] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of HIF0 group=0x%03x/0x%03x\n", + used_pg, rsv_pg); + DBGLOG(HAL, INFO, + "\tReserved page counter of HIF1 group(0x82068118): 0x%08x\n", + pg_flow_ctrl[4]); + DBGLOG(HAL, INFO, + "\tHIF1 group page status(0x8206811c): 0x%08x\n", + pg_flow_ctrl[5]); + min_q = pg_flow_ctrl[4] & 0xfff; + max_q = (pg_flow_ctrl[4] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of HIF1 group=0x%03x/0x%03x\n", + max_q, min_q); + rsv_pg = pg_flow_ctrl[5] & 0xfff; + used_pg = (pg_flow_ctrl[5] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of HIF1 group=0x%03x/0x%03x\n", + used_pg, rsv_pg); + DBGLOG(HAL, INFO, + "\tReserved page counter of CPU group(0x82068150): 0x%08x\n", + pg_flow_ctrl[6]); + DBGLOG(HAL, INFO, + "\tCPU group page status(0x82068154): 0x%08x\n", + pg_flow_ctrl[7]); + min_q = pg_flow_ctrl[6] & 0xfff; + max_q = (pg_flow_ctrl[6] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of CPU group=0x%03x/0x%03x\n", + max_q, min_q); + rsv_pg = pg_flow_ctrl[7] & 0xfff; + used_pg = (pg_flow_ctrl[7] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of CPU group=0x%03x/0x%03x\n", + used_pg, rsv_pg); + DBGLOG(HAL, INFO, + "\tReserved page counter of LMAC0 group(0x82068170): 0x%08x\n", + pg_flow_ctrl[8]); + DBGLOG(HAL, INFO, + "\tLMAC0 group page status(0x82068174): 0x%08x\n", + pg_flow_ctrl[9]); + min_q = pg_flow_ctrl[8] & 0xfff; + max_q = (pg_flow_ctrl[8] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of LMAC0 group=0x%03x/0x%03x\n", + max_q, min_q); + rsv_pg = pg_flow_ctrl[9] & 0xfff; + used_pg = (pg_flow_ctrl[9] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of LMAC0 group=0x%03x/0x%03x\n", + used_pg, rsv_pg); + DBGLOG(HAL, INFO, + "\tReserved page counter of LMAC1 group(0x82068178): 0x%08x\n", + pg_flow_ctrl[10]); + DBGLOG(HAL, INFO, + "\tLMAC1 group page status(0x8206817c): 0x%08x\n", + pg_flow_ctrl[11]); + min_q = pg_flow_ctrl[10] & 0xfff; + max_q = (pg_flow_ctrl[10] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of LMAC1 group=0x%03x/0x%03x\n", + max_q, min_q); + rsv_pg = pg_flow_ctrl[11] & 0xfff; + used_pg = (pg_flow_ctrl[11] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of LMAC1 group=0x%03x/0x%03x\n", + used_pg, rsv_pg); + DBGLOG(HAL, INFO, + "\tReserved page counter of LMAC2 group(0x82068180): 0x%08x\n", + pg_flow_ctrl[12]); + DBGLOG(HAL, INFO, + "\tLMAC2 group page status(0x82068184): 0x%08x\n", + pg_flow_ctrl[13]); + min_q = pg_flow_ctrl[12] & 0xfff; + max_q = (pg_flow_ctrl[12] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of LMAC2 group=0x%03x/0x%03x\n", + max_q, min_q); + rsv_pg = pg_flow_ctrl[13] & 0xfff; + used_pg = (pg_flow_ctrl[13] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of LMAC2 group=0x%03x/0x%03x\n", + used_pg, rsv_pg); + DBGLOG(HAL, INFO, + "\tReserved page counter of PLE group(0x82068190): 0x%08x\n", + pg_flow_ctrl[14]); + DBGLOG(HAL, INFO, + "\tPLE group page status(0x82068194): 0x%08x\n", + pg_flow_ctrl[15]); + min_q = pg_flow_ctrl[14] & 0xfff; + max_q = (pg_flow_ctrl[14] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of PLE group=0x%03x/0x%03x\n", + max_q, min_q); + rsv_pg = pg_flow_ctrl[15] & 0xfff; + used_pg = (pg_flow_ctrl[15] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of PLE group=0x%03x/0x%03x\n", + used_pg, rsv_pg); + /* Queue Empty Status */ + DBGLOG(HAL, INFO, "PSE Queue Empty Status:\n"); + DBGLOG(HAL, INFO, + "\tQUEUE_EMPTY(0x820680b0): 0x%08x\n", pse_stat); + DBGLOG(HAL, INFO, + "\t\tCPU Q0/1/2/3 empty=%d/%d/%d/%d\n", + pse_stat & 0x1, ((pse_stat & 0x2) >> 1), + ((pse_stat & 0x4) >> 2), ((pse_stat & 0x8) >> 3)); + DBGLOG(HAL, INFO, + "\t\tHIF Q0/1/2/3 empty=%d/%d/%d/%d\n", + ((pse_stat & (0x1 << 16)) >> 16), + ((pse_stat & (0x1 << 17)) >> 17), + ((pse_stat & (0x1 << 18)) >> 18), + ((pse_stat & (0x1 << 19)) >> 19)); + DBGLOG(HAL, INFO, + "\t\tLMAC TX Q empty=%d\n", + ((pse_stat & (0x1 << 24)) >> 24)); + DBGLOG(HAL, INFO, + "\t\tRLS_Q empty=%d\n", + ((pse_stat & (0x1 << 31)) >> 31)); + DBGLOG(HAL, INFO, "Nonempty Q info:\n"); + + for (i = 0; i < 31; i++) { + if (((pse_stat & (0x1 << i)) >> i) == 0) { + uint32_t hfid, tfid, pktcnt, fl_que_ctrl[3] = {0}; + + if (i < 4) { + DBGLOG(HAL, INFO, + "\tCPU Q%d: ", i); + fl_que_ctrl[0] |= (0x1 << 14); + fl_que_ctrl[0] |= (i << 8); + } else if (i == 16) { + DBGLOG(HAL, INFO, "\tHIF Q0: "); + fl_que_ctrl[0] |= (0x0 << 14); + fl_que_ctrl[0] |= (0x0 << 8); + } else if (i == 17) { + DBGLOG(HAL, INFO, "\tHIF Q1: "); + fl_que_ctrl[0] |= (0x0 << 14); + fl_que_ctrl[0] |= (0x1 << 8); + } else if (i == 18) { + DBGLOG(HAL, INFO, "\tHIF Q2: "); + fl_que_ctrl[0] |= (0x0 << 14); + fl_que_ctrl[0] |= (0x10 << 8); + } else if (i == 19) { + DBGLOG(HAL, INFO, "\tHIF Q3: "); + fl_que_ctrl[0] |= (0x0 << 14); + fl_que_ctrl[0] |= (0x11 << 8); + } else if (i == 24) { + DBGLOG(HAL, INFO, "\tLMAC TX Q: "); + fl_que_ctrl[0] |= (0x2 << 14); + fl_que_ctrl[0] |= (0x0 << 8); + } else if (i == 31) { + DBGLOG(HAL, INFO, "\tRLS Q: "); + fl_que_ctrl[0] |= (0x3 << 14); + fl_que_ctrl[0] |= (i << 8); + } else + continue; + + fl_que_ctrl[0] |= (0x1 << 31); + HAL_MCR_WR(prAdapter, PSE_FL_QUE_CTRL_0, + fl_que_ctrl[0]); + HAL_MCR_RD(prAdapter, PSE_FL_QUE_CTRL_2, + &fl_que_ctrl[1]); + HAL_MCR_RD(prAdapter, PSE_FL_QUE_CTRL_3, + &fl_que_ctrl[2]); + hfid = fl_que_ctrl[1] & 0xfff; + tfid = (fl_que_ctrl[1] & 0xfff0000) >> 16; + pktcnt = fl_que_ctrl[2] & 0xfff; + DBGLOG(HAL, INFO, + "tail/head fid = 0x%03x/0x%03x, pkt cnt = %x\n", + tfid, hfid, pktcnt); + halGetPsePayload(prAdapter, hfid, txd_payload_info); + } + } + + buf = (char *) kalMemAlloc(BUF_SIZE, VIR_MEM_TYPE); + if (buf) { + kalMemZero(buf, BUF_SIZE); + pos = 0; + for (i = 0; i < PSE_PEEK_CR_NUM; i++) { + addr = PSE_PEEK_CR_0 + PSE_PEEK_CR_OFFSET * i; + HAL_MCR_RD(prAdapter, addr, &value); + pos += kalSnprintf(buf + pos, 40, + "PSE_PEEK_CR_%u[0x%08x/0x%08x] ", + i, addr, value); + } + DBGLOG(HAL, INFO, "%s\n", buf); + + kalMemZero(buf, BUF_SIZE); + pos = 0; + for (i = 0; i < PSE_ENDEQ_NUM; i++) { + addr = PSE_ENQ_0 + PSE_ENDEQ_OFFSET * i; + HAL_MCR_RD(prAdapter, addr, &value); + pos += kalSnprintf(buf + pos, 40, + "PSE_ENQ_%u[0x%08x/0x%08x] ", + i, addr, value); + } + DBGLOG(HAL, INFO, "%s\n", buf); + + kalMemZero(buf, BUF_SIZE); + pos = 0; + for (i = 0; i < PSE_ENDEQ_NUM; i++) { + addr = PSE_DEQ_0 + PSE_ENDEQ_OFFSET * i; + HAL_MCR_RD(prAdapter, addr, &value); + pos += kalSnprintf(buf + pos, 40, + "PSE_DEQ_%u[0x%08x/0x%08x] ", + i, addr, value); + } + DBGLOG(HAL, INFO, "%s\n", buf); + + kalMemFree(buf, VIR_MEM_TYPE, BUF_SIZE); + } + + for (i = 0; i < 320; i++) { + HAL_MCR_WR(prAdapter, PSE_RL_BUF_CTRL_0, i); + HAL_MCR_RD(prAdapter, PSE_RL_BUF_CTRL_1, &value); + + /* Check valid FID */ + if (((value & 0xFFF000) >> 12) == 0xFFF) + continue; + /* Check HIF 1 group */ + else if (((value & 0xE00) >> 9) != 0x1) + continue; + + halGetPsePayload(prAdapter, i, txd_payload_info); + } + +#undef BUF_SIZE +} + +#define UMAC_FID_FAULT 0xFFF +static int8_t *sta_ctrl_reg[] = {"ENABLE", "*DISABLE", "*PAUSE"}; +static struct EMPTY_QUEUE_INFO Queue_Empty_info[] = { + {"CPU Q0", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_0}, + {"CPU Q1", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_1}, + {"CPU Q2", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_2}, + {"CPU Q3", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_3}, + {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, + {"ALTX Q0", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_ALTX_0}, + {"BMC Q0", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_BMC_0}, + {"BCN Q0", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_BNC_0}, + {"PSMP Q0", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_PSMP_0}, + {"ALTX Q1", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_ALTX_1}, + {"BMC Q1", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_BMC_1}, + {"BCN Q1", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_BNC_1}, + {"PSMP Q1", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_PSMP_1}, + {"NAF Q", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_NAF}, + {"NBCN Q", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_NBCN}, + {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, + {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, + {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, + {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, + {"RLS Q", ENUM_PLE_CTRL_PSE_PORT_3, ENUM_UMAC_PLE_CTRL_P3_Q_0X1E}, + {"RLS2 Q", ENUM_PLE_CTRL_PSE_PORT_3, ENUM_UMAC_PLE_CTRL_P3_Q_0X1F} +}; + +void halShowPleInfo(IN struct ADAPTER *prAdapter, + u_int8_t fgDumpTxd) +{ +#define BUF_SIZE 1024 + + uint32_t ple_buf_ctrl[3] = {0}, pg_sz, pg_num, bit_field_1, bit_field_2; + uint32_t ple_stat[17] = {0}, pg_flow_ctrl[6] = {0}; + uint32_t sta_pause[4] = {0}, dis_sta_map[4] = {0}; + uint32_t fpg_cnt, ffa_cnt, fpg_head, fpg_tail, hif_max_q, hif_min_q; + uint32_t rpg_hif, upg_hif, cpu_max_q, cpu_min_q, rpg_cpu, upg_cpu; + uint32_t i, j, addr, value = 0, pos = 0; + uint32_t txd_info[16] = {0}; + char *buf; + + HAL_MCR_RD(prAdapter, PLE_PBUF_CTRL, &ple_buf_ctrl[0]); + HAL_MCR_RD(prAdapter, PLE_RELEASE_CTRL, &ple_buf_ctrl[1]); + HAL_MCR_RD(prAdapter, PLE_HIF_REPORT, &ple_buf_ctrl[2]); + HAL_MCR_RD(prAdapter, PLE_QUEUE_EMPTY, &ple_stat[0]); + HAL_MCR_RD(prAdapter, PLE_AC0_QUEUE_EMPTY_0, &ple_stat[1]); + HAL_MCR_RD(prAdapter, PLE_AC0_QUEUE_EMPTY_1, &ple_stat[2]); + HAL_MCR_RD(prAdapter, PLE_AC0_QUEUE_EMPTY_2, &ple_stat[3]); + HAL_MCR_RD(prAdapter, PLE_AC0_QUEUE_EMPTY_3, &ple_stat[4]); + HAL_MCR_RD(prAdapter, PLE_AC1_QUEUE_EMPTY_0, &ple_stat[5]); + HAL_MCR_RD(prAdapter, PLE_AC1_QUEUE_EMPTY_1, &ple_stat[6]); + HAL_MCR_RD(prAdapter, PLE_AC1_QUEUE_EMPTY_2, &ple_stat[7]); + HAL_MCR_RD(prAdapter, PLE_AC1_QUEUE_EMPTY_3, &ple_stat[8]); + HAL_MCR_RD(prAdapter, PLE_AC2_QUEUE_EMPTY_0, &ple_stat[9]); + HAL_MCR_RD(prAdapter, PLE_AC2_QUEUE_EMPTY_1, &ple_stat[10]); + HAL_MCR_RD(prAdapter, PLE_AC2_QUEUE_EMPTY_2, &ple_stat[11]); + HAL_MCR_RD(prAdapter, PLE_AC2_QUEUE_EMPTY_3, &ple_stat[12]); + HAL_MCR_RD(prAdapter, PLE_AC3_QUEUE_EMPTY_0, &ple_stat[13]); + HAL_MCR_RD(prAdapter, PLE_AC3_QUEUE_EMPTY_1, &ple_stat[14]); + HAL_MCR_RD(prAdapter, PLE_AC3_QUEUE_EMPTY_2, &ple_stat[15]); + HAL_MCR_RD(prAdapter, PLE_AC3_QUEUE_EMPTY_3, &ple_stat[16]); + HAL_MCR_RD(prAdapter, PLE_FREEPG_CNT, &pg_flow_ctrl[0]); + HAL_MCR_RD(prAdapter, PLE_FREEPG_HEAD_TAIL, &pg_flow_ctrl[1]); + HAL_MCR_RD(prAdapter, PLE_PG_HIF_GROUP, &pg_flow_ctrl[2]); + HAL_MCR_RD(prAdapter, PLE_HIF_PG_INFO, &pg_flow_ctrl[3]); + HAL_MCR_RD(prAdapter, PLE_PG_CPU_GROUP, &pg_flow_ctrl[4]); + HAL_MCR_RD(prAdapter, PLE_CPU_PG_INFO, &pg_flow_ctrl[5]); + HAL_MCR_RD(prAdapter, DIS_STA_MAP0, &dis_sta_map[0]); + HAL_MCR_RD(prAdapter, DIS_STA_MAP1, &dis_sta_map[1]); + HAL_MCR_RD(prAdapter, DIS_STA_MAP2, &dis_sta_map[2]); + HAL_MCR_RD(prAdapter, DIS_STA_MAP3, &dis_sta_map[3]); + HAL_MCR_RD(prAdapter, STATION_PAUSE0, &sta_pause[0]); + HAL_MCR_RD(prAdapter, STATION_PAUSE1, &sta_pause[1]); + HAL_MCR_RD(prAdapter, STATION_PAUSE2, &sta_pause[2]); + HAL_MCR_RD(prAdapter, STATION_PAUSE3, &sta_pause[3]); + /* Configuration Info */ + DBGLOG(HAL, INFO, "PLE Configuration Info:\n"); + + HAL_MCR_RD(prAdapter, PLE_GC, &value); + DBGLOG(HAL, INFO, "\tGC(0x82060000): 0x%08x\n", value); + HAL_MCR_RD(prAdapter, PLE_INT_STS, &value); + DBGLOG(HAL, INFO, "\tINT_STS(0x82060024): 0x%08x\n", value); + HAL_MCR_RD(prAdapter, PLE_INT_ERR_STS, &value); + DBGLOG(HAL, INFO, "\tINT_ERR_STS(0x82060028): 0x%08x\n", value); + HAL_MCR_RD(prAdapter, PLE_QUEUE_CMD_ERR_STS, &value); + DBGLOG(HAL, INFO, "\tQUEUE_CMD_ERR_STS(0x82060550): 0x%08x\n", value); + + DBGLOG(HAL, INFO, + "\tPacket Buffer Control(0x82060014): 0x%08x\n", + ple_buf_ctrl[0]); + pg_sz = (ple_buf_ctrl[0] & (0x1 << 31)) >> 31; + DBGLOG(HAL, INFO, + "\t\tPage Size=%d(%d bytes per page)\n", + pg_sz, (pg_sz == 1 ? 128 : 64)); + DBGLOG(HAL, INFO, + "\t\tPage Offset=%d(in unit of 2KB)\n", + (ple_buf_ctrl[0] & (0xf << 17)) >> 17); + pg_num = (ple_buf_ctrl[0] & 0xfff); + DBGLOG(HAL, INFO, + "\t\tTotal Page=%d pages\n", (ple_buf_ctrl[0] & 0xfff)); + DBGLOG(HAL, INFO, + "\tRelease Control(0x82060030): 0x%08x\n", ple_buf_ctrl[1]); + bit_field_1 = (ple_buf_ctrl[1] & 0x1f); + bit_field_2 = ((ple_buf_ctrl[1] & (0x3 << 6)) >> 6); + DBGLOG(HAL, INFO, + "\t\tNormalTx Release Pid/Qid=%d/%d\n", + bit_field_2, bit_field_1); + bit_field_1 = ((ple_buf_ctrl[1] & (0x1f << 8)) >> 8); + bit_field_2 = ((ple_buf_ctrl[1] & (0x3 << 14)) >> 14); + DBGLOG(HAL, INFO, + "\t\tDropTx Release Pid/Qid=%d/%d\n", bit_field_2, bit_field_1); + bit_field_1 = ((ple_buf_ctrl[1] & (0x1f << 16)) >> 16); + bit_field_2 = ((ple_buf_ctrl[1] & (0x3 << 22)) >> 22); + DBGLOG(HAL, INFO, + "\t\tBCN0 Release Pid/Qid=%d/%d\n", bit_field_2, bit_field_1); + bit_field_1 = ((ple_buf_ctrl[1] & (0x1f << 24)) >> 24); + bit_field_2 = ((ple_buf_ctrl[1] & (0x3 << 30)) >> 30); + DBGLOG(HAL, INFO, + "\t\tBCN1 Release Pid/Qid=%d/%d\n", bit_field_2, bit_field_1); + DBGLOG(HAL, INFO, + "\tHIF Report Control(0x82060034): 0x%08x\n", ple_buf_ctrl[2]); + bit_field_1 = ((ple_buf_ctrl[2] & (0x1 << 1)) >> 1); + DBGLOG(HAL, INFO, + "\t\tHostReportQSel/HostReportDisable=%d/%d\n", + (ple_buf_ctrl[2] & 0x1), bit_field_1); + /* Page Flow Control */ + DBGLOG(HAL, INFO, "PLE Page Flow Control:\n"); + DBGLOG(HAL, INFO, + "\tFree page counter(0x82060100): 0x%08x\n", pg_flow_ctrl[0]); + fpg_cnt = pg_flow_ctrl[0] & 0xfff; + DBGLOG(HAL, INFO, + "\t\tThe toal page number of free=0x%03x\n", fpg_cnt); + ffa_cnt = (pg_flow_ctrl[0] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe free page numbers of free for all=0x%03x\n", ffa_cnt); + DBGLOG(HAL, INFO, + "\tFree page head and tail(0x82060104): 0x%08x\n", + pg_flow_ctrl[1]); + fpg_head = pg_flow_ctrl[1] & 0xfff; + fpg_tail = (pg_flow_ctrl[1] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe tail/head page of free page list=0x%03x/0x%03x\n", + fpg_tail, fpg_head); + DBGLOG(HAL, INFO, + "\tReserved page counter of HIF group(0x82060110): 0x%08x\n", + pg_flow_ctrl[2]); + DBGLOG(HAL, INFO, + "\tHIF group page status(0x82060114): 0x%08x\n", + pg_flow_ctrl[3]); + hif_min_q = pg_flow_ctrl[2] & 0xfff; + hif_max_q = (pg_flow_ctrl[2] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of HIF group=0x%03x/0x%03x\n", + hif_max_q, hif_min_q); + rpg_hif = pg_flow_ctrl[3] & 0xfff; + upg_hif = (pg_flow_ctrl[3] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of HIF group=0x%03x/0x%03x\n", + upg_hif, rpg_hif); + DBGLOG(HAL, INFO, + "\tReserved page counter of CPU group(0x82060150): 0x%08x\n", + pg_flow_ctrl[4]); + DBGLOG(HAL, INFO, + "\tCPU group page status(0x82060154): 0x%08x\n", + pg_flow_ctrl[5]); + cpu_min_q = pg_flow_ctrl[4] & 0xfff; + cpu_max_q = (pg_flow_ctrl[4] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of CPU group=0x%03x/0x%03x\n", + cpu_max_q, cpu_min_q); + rpg_cpu = pg_flow_ctrl[5] & 0xfff; + upg_cpu = (pg_flow_ctrl[5] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of CPU group=0x%03x/0x%03x\n", + upg_cpu, rpg_cpu); + + if (((ple_stat[0] & (0x1 << 24)) >> 24) == 0) { + DBGLOG(HAL, INFO, + "\tAC0_QUEUE_EMPTY0(0x82060300): 0x%08x\n", + ple_stat[1]); + DBGLOG(HAL, INFO, + "\tAC1_QUEUE_EMPTY0(0x82060310): 0x%08x\n", + ple_stat[5]); + DBGLOG(HAL, INFO, + "\tAC2_QUEUE_EMPTY0(0x82060320): 0x%08x\n", + ple_stat[9]); + DBGLOG(HAL, INFO, + "\tAC3_QUEUE_EMPTY0(0x82060330): 0x%08x\n", + ple_stat[13]); + + for (j = 0; j < 16; j = j + 4) { + if (j % 4 == 0) + DBGLOG(HAL, INFO, "\tNonempty AC%d Q of STA#:", + j / 4); + + for (i = 0; i < 32; i++) { + if (((ple_stat[j + 1] & (0x1 << i)) >> i) == 0) + DBGLOG(HAL, INFO, "%d ", + i + (j % 4) * 32); + } + } + + DBGLOG(HAL, INFO, "\n"); + } + + DBGLOG(HAL, INFO, "Nonempty Q info:\n"); + + for (i = 0; i < 31; i++) { + if (((ple_stat[0] & (0x1 << i)) >> i) == 0) { + uint32_t hfid, tfid, pktcnt, fl_que_ctrl[3] = {0}; + + if (Queue_Empty_info[i].QueueName != NULL) { + DBGLOG(HAL, INFO, "\t%s: ", + Queue_Empty_info[i].QueueName); + fl_que_ctrl[0] |= (0x1 << 31); + fl_que_ctrl[0] |= + (Queue_Empty_info[i].Portid << 14); + fl_que_ctrl[0] |= + (Queue_Empty_info[i].Queueid << 8); + } else + continue; + + HAL_MCR_WR(prAdapter, + PLE_FL_QUE_CTRL_0, fl_que_ctrl[0]); + HAL_MCR_RD(prAdapter, + PLE_FL_QUE_CTRL_2, &fl_que_ctrl[1]); + HAL_MCR_RD(prAdapter, + PLE_FL_QUE_CTRL_3, &fl_que_ctrl[2]); + hfid = fl_que_ctrl[1] & 0xfff; + tfid = (fl_que_ctrl[1] & 0xfff0000) >> 16; + pktcnt = fl_que_ctrl[2] & 0xfff; + DBGLOG(HAL, INFO, + "tail/head fid = 0x%03x/0x%03x, pkt cnt = %x\n", + tfid, hfid, pktcnt); + } + } + + for (j = 0; j < 16; j = j + 4) { /* show AC Q info */ + for (i = 0; i < 32; i++) { + if (((ple_stat[j + 1] & (0x1 << i)) >> i) == 0) { + uint32_t hfid, tfid, pktcnt, + ac_num = j / 4, ctrl = 0; + uint32_t sta_num = i + (j % 4) * 32, + fl_que_ctrl[3] = {0}; + + DBGLOG(HAL, INFO, "\tSTA%d AC%d: ", + sta_num, ac_num); + fl_que_ctrl[0] |= (0x1 << 31); + fl_que_ctrl[0] |= (0x2 << 14); + fl_que_ctrl[0] |= (ac_num << 8); + fl_que_ctrl[0] |= sta_num; + HAL_MCR_WR(prAdapter, + PLE_FL_QUE_CTRL_0, fl_que_ctrl[0]); + HAL_MCR_RD(prAdapter, + PLE_FL_QUE_CTRL_2, &fl_que_ctrl[1]); + HAL_MCR_RD(prAdapter, + PLE_FL_QUE_CTRL_3, &fl_que_ctrl[2]); + hfid = fl_que_ctrl[1] & 0xfff; + tfid = (fl_que_ctrl[1] & 0xfff0000) >> 16; + pktcnt = fl_que_ctrl[2] & 0xfff; + DBGLOG(HAL, INFO, + "tail/head fid = 0x%03x/0x%03x, pkt cnt = %x", + tfid, hfid, pktcnt); + if (fgDumpTxd) { + halGetPleTxdInfo(prAdapter, + hfid, txd_info); + halDumpTxdInfo(prAdapter, txd_info); + } + if (((sta_pause[j % 4] & 0x1 << i) >> i) == 1) + ctrl = 2; + + if (((dis_sta_map[j % 4] & 0x1 << i) >> i) == 1) + ctrl = 1; + + DBGLOG(HAL, INFO, " ctrl = %s", + sta_ctrl_reg[ctrl]); + } + } + } + + buf = (char *) kalMemAlloc(BUF_SIZE, VIR_MEM_TYPE); + if (buf) { + kalMemZero(buf, BUF_SIZE); + for (i = 0; i < PLE_PEEK_CR_NUM; i++) { + addr = PLE_PEEK_CR_0 + PLE_PEEK_CR_OFFSET * i; + HAL_MCR_RD(prAdapter, addr, &value); + pos += kalSnprintf(buf + pos, 40, + "PLE_PEEK_CR_%u[0x%08x/0x%08x]%s", + i, addr, value, + i == (PLE_PEEK_CR_NUM - 1) ? "\n" : ", "); + } + DBGLOG(HAL, INFO, "%s\n", buf); + kalMemFree(buf, VIR_MEM_TYPE, BUF_SIZE); + } + +#undef BUF_SIZE +} + +void halShowDmaschInfo(IN struct ADAPTER *prAdapter) +{ + struct mt66xx_chip_info *prChipInfo; + uint32_t value = 0; + uint32_t ple_pkt_max_sz; + uint32_t pse_pkt_max_sz; + uint32_t max_quota; + uint32_t min_quota; + uint32_t rsv_cnt; + uint32_t src_cnt; + uint32_t pse_rsv_cnt = 0; + uint32_t pse_src_cnt = 0; + uint32_t odd_group_pktin_cnt = 0; + uint32_t odd_group_ask_cnt = 0; + uint32_t pktin_cnt; + uint32_t ask_cnt; + uint32_t total_src_cnt = 0; + uint32_t total_rsv_cnt = 0; + uint32_t ffa_cnt; + uint32_t free_pg_cnt; + uint32_t Group_Mapping_Q[16] = {0}; + uint32_t qmapping_addr = MT_HIF_DMASHDL_Q_MAP0; + uint32_t status_addr = MT_HIF_DMASHDL_STATUS_RD_GP0; + uint32_t quota_addr = MT_HIF_DMASHDL_GROUP0_CTRL; + uint32_t pkt_cnt_addr = MT_HIF_DMASHDLRD_GP_PKT_CNT_0; + uint32_t mapping_mask = 0xf; + uint32_t mapping_offset = 0; + uint32_t mapping_qidx; + uint32_t groupidx = 0; + uint8_t idx = 0; + u_int8_t pktin_int_refill_ena; + u_int8_t pdma_add_int_refill_ena; + u_int8_t ple_add_int_refill_ena; + u_int8_t ple_sub_ena; + u_int8_t hif_ask_sub_ena; + u_int8_t ple_txd_gt_max_size_flag_clr; + uint32_t ple_rpg_hif; + uint32_t ple_upg_hif; + uint32_t pse_rpg_hif = 0; + uint32_t pse_upg_hif = 0; + uint8_t is_mismatch = FALSE; + uint32_t u4BaseAddr; + + prChipInfo = prAdapter->chip_info; + u4BaseAddr = prChipInfo->u4HifDmaShdlBaseAddr; + for (mapping_qidx = 0; mapping_qidx < 32; mapping_qidx++) { + uint32_t mapping_group; + + idx = 0; + + if (mapping_qidx == 0) { + qmapping_addr = MT_HIF_DMASHDL_Q_MAP0; + mapping_mask = 0xf; + mapping_offset = 0; + } else if ((mapping_qidx % 8) == 0) { + qmapping_addr += 0x4; + mapping_mask = 0xf; + mapping_offset = 0; + } else { + mapping_offset += 4; + mapping_mask = 0xf << mapping_offset; + } + + HAL_MCR_RD(prAdapter, qmapping_addr, &value); + mapping_group = (value & mapping_mask) >> mapping_offset; + Group_Mapping_Q[mapping_group] |= 1 << mapping_qidx; + } + + DBGLOG(HAL, INFO, "Dma scheduler info:\n"); + HAL_MCR_RD(prAdapter, MT_HIF_DMASHDL_CTRL_SIGNAL, &value); + pktin_int_refill_ena = + (value & DMASHDL_PKTIN_INT_REFILL_ENA) ? TRUE : FALSE; + pdma_add_int_refill_ena = + (value & DMASHDL_PDMA_ADD_INT_REFILL_ENA) ? TRUE : FALSE; + ple_add_int_refill_ena = + (value & DMASHDL_PLE_ADD_INT_REFILL_ENA) ? TRUE : FALSE; + ple_sub_ena = (value & DMASHDL_PLE_SUB_ENA) ? TRUE : FALSE; + hif_ask_sub_ena = (value & DMASHDL_HIF_ASK_SUB_ENA) ? TRUE : FALSE; + ple_txd_gt_max_size_flag_clr = + (value & DMASHDL_PLE_TXD_GT_MAX_SIZE_FLAG_CLR) ? TRUE : FALSE; + DBGLOG(HAL, INFO, "DMASHDL Ctrl Signal(0x5000A018): 0x%08x\n", value); + DBGLOG(HAL, INFO, "\tple_txd_gt_max_size_flag_clr(BIT0) = %d\n", + ple_txd_gt_max_size_flag_clr); + DBGLOG(HAL, INFO, "\thif_ask_sub_ena(BIT16) = %d\n", hif_ask_sub_ena); + DBGLOG(HAL, INFO, "\tple_sub_ena(BIT17) = %d\n", ple_sub_ena); + DBGLOG(HAL, INFO, "\tple_add_int_refill_ena(BIT29) = %d\n", + ple_add_int_refill_ena); + DBGLOG(HAL, INFO, "\tpdma_add_int_refill_ena(BIT30) = %d\n", + pdma_add_int_refill_ena); + DBGLOG(HAL, INFO, "\tpktin_int_refill(BIT31)_ena = %d\n", + pktin_int_refill_ena); + HAL_MCR_RD(prAdapter, MT_HIF_DMASHDL_PKT_MAX_SIZE, &value); + ple_pkt_max_sz = GET_PLE_PKT_MAX_SIZE_NUM(value); + pse_pkt_max_sz = GET_PSE_PKT_MAX_SIZE_NUM(value); + DBGLOG(HAL, INFO, + "DMASHDL Packet_max_size(0x5000A01c): 0x%08x\n", value); + DBGLOG(HAL, INFO, + "PLE/PSE packet max size=0x%03x/0x%03x\n", + ple_pkt_max_sz, pse_pkt_max_sz); + HAL_MCR_RD(prAdapter, MT_HIF_DMASHDL_ERROR_FLAG_CTRL, &value); + DBGLOG(HAL, INFO, "DMASHDL ERR FLAG CTRL(0x5000A09c): 0x%08x\n", value); + HAL_MCR_RD(prAdapter, MT_HIF_DMASHDL_STATUS_RD, &value); + ffa_cnt = (value & DMASHDL_FFA_CNT_MASK) >> DMASHDL_FFA_CNT_OFFSET; + free_pg_cnt = (value & DMASHDL_FREE_PG_CNT_MASK) >> + DMASHDL_FREE_PG_CNT_OFFSET; + DBGLOG(HAL, INFO, "DMASHDL Status_RD(0x5000A100): 0x%08x\n", value); + DBGLOG(HAL, INFO, + "free page cnt = 0x%03x, ffa cnt = 0x%03x\n", + free_pg_cnt, ffa_cnt); + HAL_MCR_RD(prAdapter, + CONN_HIF_DMASHDL_REFILL_CONTROL(u4BaseAddr), &value); + DBGLOG(HAL, INFO, + "DMASHDL ReFill Control(0x5000A010): 0x%08x\n", value); + + for (groupidx = 0; groupidx < 16; groupidx++) { + DBGLOG(HAL, INFO, "Group %d info:", groupidx); + HAL_MCR_RD(prAdapter, status_addr, &value); + rsv_cnt = (value & DMASHDL_RSV_CNT_MASK) >> + DMASHDL_RSV_CNT_OFFSET; + src_cnt = (value & DMASHDL_SRC_CNT_MASK) >> + DMASHDL_SRC_CNT_OFFSET; + DBGLOG(HAL, INFO, + "\tDMASHDL Status_RD_GP%d(0x%08x): 0x%08x\n", + groupidx, status_addr, value); + HAL_MCR_RD(prAdapter, quota_addr, &value); + max_quota = (value & DMASHDL_MAX_QUOTA_MASK) >> + DMASHDL_MAX_QUOTA_OFFSET; + min_quota = (value & DMASHDL_MIN_QUOTA_MASK) >> + DMASHDL_MIN_QUOTA_OFFSET; + DBGLOG(HAL, INFO, + "\tDMASHDL Group%d control(0x%08x): 0x%08x\n", + groupidx, quota_addr, value); + + if ((groupidx & 0x1) == 0) { + HAL_MCR_RD(prAdapter, pkt_cnt_addr, &value); + DBGLOG(HAL, INFO, + "\tDMASHDL RD_group_pkt_cnt_%d(0x%08x): 0x%08x\n", + groupidx / 2, pkt_cnt_addr, value); + odd_group_pktin_cnt = GET_ODD_GROUP_PKT_IN_CNT(value); + odd_group_ask_cnt = GET_ODD_GROUP_ASK_CNT(value); + pktin_cnt = GET_EVEN_GROUP_PKT_IN_CNT(value); + ask_cnt = GET_EVEN_GROUP_ASK_CNT(value); + } else { + pktin_cnt = odd_group_pktin_cnt; + ask_cnt = odd_group_ask_cnt; + } + + DBGLOG(HAL, INFO, + "\trsv_cnt = 0x%03x, src_cnt = 0x%03x\n", + rsv_cnt, src_cnt); + DBGLOG(HAL, INFO, + "\tmax/min quota = 0x%03x/ 0x%03x\n", + max_quota, min_quota); + DBGLOG(HAL, INFO, + "\tpktin_cnt = 0x%02x, ask_cnt = 0x%02x", + pktin_cnt, ask_cnt); + + if (hif_ask_sub_ena && pktin_cnt != ask_cnt) { + DBGLOG(HAL, INFO, ", mismatch!"); + is_mismatch = TRUE; + } + + /* Group15 is for PSE */ + if (groupidx == 15 && Group_Mapping_Q[groupidx] == 0) { + pse_src_cnt = src_cnt; + pse_rsv_cnt = rsv_cnt; + break; + } + + DBGLOG(HAL, INFO, "\tMapping Qidx: 0x%x", + Group_Mapping_Q[groupidx]); + + total_src_cnt += src_cnt; + total_rsv_cnt += rsv_cnt; + status_addr = status_addr + 4; + quota_addr = quota_addr + 4; + + if (groupidx & 0x1) + pkt_cnt_addr = pkt_cnt_addr + 4; + } + + DBGLOG(HAL, INFO, "\nCounter Check:\n"); + HAL_MCR_RD(prAdapter, PLE_HIF_PG_INFO, &value); + ple_rpg_hif = value & 0xfff; + ple_upg_hif = (value & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "PLE:\n\tThe used/reserved pages of PLE HIF group=0x%03x/0x%03x\n", + ple_upg_hif, ple_rpg_hif); + HAL_MCR_RD(prAdapter, PSE_HIF1_PG_INFO, &value); + pse_rpg_hif = value & 0xfff; + pse_upg_hif = (value & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "PSE:\n\tThe used/reserved pages of PSE HIF group=0x%03x/0x%03x\n", + pse_upg_hif, pse_rpg_hif); + DBGLOG(HAL, INFO, + "DMASHDL:\n\tThe total used pages of group0~14=0x%03x", + total_src_cnt); + + if (ple_upg_hif != total_src_cnt) { + DBGLOG(HAL, INFO, ", mismatch!"); + is_mismatch = TRUE; + } + + DBGLOG(HAL, INFO, "\n"); + DBGLOG(HAL, INFO, + "\tThe total reserved pages of group0~14=0x%03x\n", + total_rsv_cnt); + DBGLOG(HAL, INFO, + "\tThe total ffa pages of group0~14=0x%03x\n", + ffa_cnt); + DBGLOG(HAL, INFO, + "\tThe total free pages of group0~14=0x%03x", free_pg_cnt); + + if (free_pg_cnt != total_rsv_cnt + ffa_cnt) { + DBGLOG(HAL, INFO, + ", mismatch(total_rsv_cnt + ffa_cnt in DMASHDL)"); + is_mismatch = TRUE; + } + + if (free_pg_cnt != ple_rpg_hif) { + DBGLOG(HAL, INFO, ", mismatch(reserved pages in PLE)"); + is_mismatch = TRUE; + } + + DBGLOG(HAL, INFO, "\n"); + DBGLOG(HAL, INFO, "\tThe used pages of group15=0x%03x", pse_src_cnt); + + if (pse_upg_hif != pse_src_cnt) { + DBGLOG(HAL, INFO, ", mismatch!"); + is_mismatch = TRUE; + } + + DBGLOG(HAL, INFO, "\n"); + DBGLOG(HAL, INFO, + "\tThe reserved pages of group15=0x%03x", pse_rsv_cnt); + + if (pse_rpg_hif != pse_rsv_cnt) { + DBGLOG(HAL, INFO, ", mismatch!"); + is_mismatch = TRUE; + } + + DBGLOG(HAL, INFO, "\n"); + + if (!is_mismatch) + DBGLOG(HAL, INFO, "DMASHDL: no counter mismatch\n"); +} + +void haldumpMacInfo(struct ADAPTER *prAdapter) +{ + uint32_t i = 0, j = 0; + uint32_t value = 0, index = 0, flag = 0, queue = 0; + + DBGLOG(HAL, INFO, "Print 0x820F3190 5*20 times\n"); + for (i = 0; i < 5; i++) { + for (j = 0; j < 20; j++) { + HAL_MCR_RD(prAdapter, 0x820F3190, &value); + DBGLOG(HAL, INFO, "0x820F3190: 0x%08x\n", value); + } + kalMdelay(1); + } + + for (j = 0; j < 20; j++) { + HAL_MCR_RD(prAdapter, 0x820FD020, &value); + DBGLOG(HAL, INFO, "slot idle: 0x820FD020: 0x%08x\n", value); + HAL_MCR_RD(prAdapter, 0x820F4128, &value); + DBGLOG(HAL, INFO, + "TX state machine/CCA: 0x820F4128 = 0x%08x\n", value); + HAL_MCR_RD(prAdapter, 0x820F20D0, &value); + DBGLOG(HAL, INFO, + "AGG state machine band0: 0x820F20D0 = 0x%08x\n", value); + HAL_MCR_RD(prAdapter, 0x820F20D4, &value); + DBGLOG(HAL, INFO, + "AGG state machine band1: 0x820F20D4 = 0x%08x\n", value); + /* 1: empty, 0: non-empty */ + HAL_MCR_RD(prAdapter, 0x82060220, &value); + DBGLOG(HAL, INFO, "queue empty: 0x82060220: 0x%08x\n", value); + HAL_MCR_RD(prAdapter, 0x820603EC, &value); + DBGLOG(HAL, INFO, + "PLE MACTX CurState: 0x820603EC: 0x%08x\n", value); + kalMdelay(1); + } + + HAL_MCR_RD(prAdapter, 0x820F4124, &value); + DBGLOG(HAL, INFO, "TXV count: 0x820F4124 = %08x\n", value); + + /* Band 0 TXV1-TXV7 */ + for (j = 0x820F4130; j < 0x820F4148; j += 4) { + HAL_MCR_RD(prAdapter, j, &value); + DBGLOG(HAL, INFO, "0x%08x: 0x%08x\n", j, value); + kalMdelay(1); + } + + /* Band 1 TXV1-TXV7 */ + for (j = 0x820F414C; j < 0x820F4164; j += 4) { + HAL_MCR_RD(prAdapter, j, &value); + DBGLOG(HAL, INFO, "0x%08x: 0x%08x\n", j, value); + kalMdelay(1); + } + + HAL_MCR_RD(prAdapter, 0x820F409C, &value); + DBGLOG(HAL, INFO, "Dump CR: 0x820F409C = %08x\n", value); + + HAL_MCR_RD(prAdapter, 0x820F409C, &value); + DBGLOG(HAL, INFO, "Dump CR: 0x820F409C = %08x\n", value); + + HAL_MCR_RD(prAdapter, 0x820F3080, &value); + DBGLOG(HAL, INFO, "Dump CR: 0x820F3080 = %08x\n", value); + + DBGLOG(HAL, INFO, "Dump ARB CR: 820F3000~820F33FF\n"); + for (index = 0x820f3000; index < 0x820f33ff; index += 4) { + HAL_MCR_RD(prAdapter, index, &value); + DBGLOG(HAL, INFO, "0x%08x: 0x%08x\n", index, value); + } + + DBGLOG(HAL, INFO, "Dump AGG CR: 820F000~820F21FF\n"); + for (index = 0x820f2000; index < 0x820f21ff; index += 4) { + HAL_MCR_RD(prAdapter, index, &value); + DBGLOG(HAL, INFO, "0x%08x: 0x%08x\n", index, value); + } + + DBGLOG(HAL, INFO, "Dump TRB\n"); + HAL_MCR_WR(prAdapter, 0x80025104, 0x02020202); + flag = 0x01010000; + for (i = 0; i < 64; i++) { + HAL_MCR_WR(prAdapter, 0x80025108, flag); + HAL_MCR_RD(prAdapter, 0x820f0024, &value); + DBGLOG(HAL, INFO, "write flag = 0x%08x, 0x820f0024: 0x%08x\n", + flag, value); + flag += 0x02020202; + } + + DBGLOG(HAL, INFO, "Dump ARB\n"); + for (i = 0; i < 20; i++) { + HAL_MCR_RD(prAdapter, 0x802f3190, &value); + DBGLOG(HAL, INFO, "0x802f3190: 0x%08x\n", value); + } + + HAL_MCR_WR(prAdapter, 0x820f082C, 0xf); + HAL_MCR_WR(prAdapter, 0x80025100, 0x1f); + HAL_MCR_WR(prAdapter, 0x80025104, 0x04040404); + + HAL_MCR_WR(prAdapter, 0x80025108, 0x41414040); + HAL_MCR_RD(prAdapter, 0x820f0024, &value); + DBGLOG(HAL, INFO, "0x820f0024: 0x%08x\n", value); + HAL_MCR_RD(prAdapter, 0x820f20d0, &value); + DBGLOG(HAL, INFO, "0x820f20d0: 0x%08x\n", value); + HAL_MCR_RD(prAdapter, 0x820f20d4, &value); + DBGLOG(HAL, INFO, "0x820f20d4: 0x%08x\n", value); + + queue = 0; + flag = 0x00000101; + for (i = 0; i < 25; i++) { + HAL_MCR_WR(prAdapter, 0x820f3060, queue); + flag = 0x00000101; + for (j = 0; j < 8; j++) { + HAL_MCR_WR(prAdapter, 0x80025108, flag); + HAL_MCR_RD(prAdapter, 0x820f0024, &value); + DBGLOG(HAL, INFO, + "write queue = 0x%08x flag = 0x%08x, 0x820f0024: 0x%08x\n", + queue, flag, value); + flag += 0x02020202; + } + queue += 0x01010101; + } + + queue = 0x01010000; + flag = 0x04040505; + HAL_MCR_WR(prAdapter, 0x820f3060, queue); + for (i = 0; i < 3; i++) { + HAL_MCR_WR(prAdapter, 0x80025108, flag); + HAL_MCR_RD(prAdapter, 0x820f0024, &value); + DBGLOG(HAL, INFO, "write flag = 0x%08x, 0x820f0024: 0x%08x\n", + flag, value); + flag += 0x02020202; + } + + flag = 0x00000101; + HAL_MCR_WR(prAdapter, 0x820f3060, 0); /* BSSID = 0 */ + for (i = 0; i < 128; i++) { + HAL_MCR_WR(prAdapter, 0x80025108, flag); + HAL_MCR_RD(prAdapter, 0x820f0024, &value); + DBGLOG(HAL, INFO, "write flag = 0x%08x, 0x820f0024: 0x%08x\n", + flag, value); + flag += 0x02020202; + } + + DBGLOG(HAL, INFO, "Dump AGG\n"); + HAL_MCR_WR(prAdapter, 0x80025104, 0x05050505); + flag = 0x01010000; + for (i = 0; i < 64; i++) { + HAL_MCR_WR(prAdapter, 0x80025108, flag); + HAL_MCR_RD(prAdapter, 0x820f0024, &value); + DBGLOG(HAL, INFO, "write flag = 0x%08x, 0x820f0024: 0x%08x\n", + flag, value); + flag += 0x02020202; + } + + DBGLOG(HAL, INFO, "Dump DMA\n"); + HAL_MCR_WR(prAdapter, 0x80025104, 0x06060606); + flag = 0x01010000; + for (i = 0; i < 64; i++) { + HAL_MCR_WR(prAdapter, 0x80025108, flag); + HAL_MCR_RD(prAdapter, 0x820f0024, &value); + DBGLOG(HAL, INFO, "write flag = 0x%08x, 0x820f0024: 0x%08x\n", + flag, value); + flag += 0x02020202; + } + + DBGLOG(HAL, INFO, "Dump TMAC\n"); + HAL_MCR_WR(prAdapter, 0x80025104, 0x07070707); + flag = 0x01010000; + for (i = 0; i < 33; i++) { + HAL_MCR_WR(prAdapter, 0x80025108, flag); + HAL_MCR_RD(prAdapter, 0x820f0024, &value); + DBGLOG(HAL, INFO, "write flag = 0x%08x, 0x820f0024: 0x%08x\n", + flag, value); + flag += 0x02020202; + } + + DBGLOG(HAL, TRACE, "Dump extra ARB\n"); + HAL_MCR_WR(prAdapter, 0x820f082C, 0xf); + HAL_MCR_WR(prAdapter, 0x80025100, 0x1f); + HAL_MCR_WR(prAdapter, 0x80025104, 0x04040404); + HAL_MCR_WR(prAdapter, 0x80025108, 0x7c7c6d6d); + HAL_MCR_RD(prAdapter, 0x820f0024, &value); + DBGLOG(HAL, TRACE, "Read 0x820f0024: 0x%08x\n", value); + + DBGLOG(HAL, TRACE, " -> check UMAC busy\n"); + HAL_MCR_WR(prAdapter, 0x80025108, 0x40404141); + for (i = 0; i < 30; i++) { + HAL_MCR_RD(prAdapter, 0x820f0024, &value); + DBGLOG(HAL, TRACE, " Read 0x820f0024: 0x%08x\n", value); + } + HAL_MCR_WR(prAdapter, 0x80025108, 0xe0e0e5e5); + for (i = 0; i < 30; i++) { + HAL_MCR_RD(prAdapter, 0x820f0024, &value); + DBGLOG(HAL, TRACE, " Read 0x820f0024: 0x%08x\n", value); + } + + DBGLOG(HAL, TRACE, " -> check txq_num\n"); + HAL_MCR_WR(prAdapter, 0x80025108, 0x4d4d3131); + for (i = 0; i < 30; i++) { + HAL_MCR_RD(prAdapter, 0x820f0024, &value); + DBGLOG(HAL, TRACE, " Read 0x820f0024: 0x%08x\n", value); + } + + DBGLOG(HAL, TRACE, " -> check station pause\n"); + HAL_MCR_RD(prAdapter, 0x82060360, &value); + DBGLOG(HAL, TRACE, " Read 0x82060360: 0x%08x\n", value); + HAL_MCR_RD(prAdapter, 0x82060364, &value); + DBGLOG(HAL, TRACE, " Read 0x82060364: 0x%08x\n", value); + HAL_MCR_RD(prAdapter, 0x82060368, &value); + DBGLOG(HAL, TRACE, " Read 0x82060368: 0x%08x\n", value); + HAL_MCR_RD(prAdapter, 0x8206036C, &value); + DBGLOG(HAL, TRACE, " Read 0x8206036C: 0x%08x\n", value); +} + +static char *q_idx_mcu_str[] = {"RQ0", "RQ1", "RQ2", "RQ3", "Invalid"}; +static char *pkt_ft_str[] = {"cut_through", "store_forward", + "cmd", "PDA_FW_Download"}; +static char *hdr_fmt_str[] = { + "Non-80211-Frame", + "Command-Frame", + "Normal-80211-Frame", + "enhanced-80211-Frame", +}; +static char *p_idx_str[] = {"LMAC", "MCU"}; +static char *q_idx_lmac_str[] = {"WMM0_AC0", "WMM0_AC1", "WMM0_AC2", "WMM0_AC3", + "WMM1_AC0", "WMM1_AC1", "WMM1_AC2", "WMM1_AC3", + "WMM2_AC0", "WMM2_AC1", "WMM2_AC2", "WMM2_AC3", + "WMM3_AC0", "WMM3_AC1", "WMM3_AC2", "WMM3_AC3", + "Band0_ALTX", "Band0_BMC", "Band0_BNC", "Band0_PSMP", + "Band1_ALTX", "Band1_BMC", "Band1_BNC", "Band1_PSMP", + "Invalid"}; + +void halGetPsePayload(IN struct ADAPTER *prAdapter, uint32_t fid, + uint32_t *result) +{ + uint32_t i = 0, target = 0, remap = 0, remain = 0; + + DBGLOG(HAL, INFO, "Dump fid=%u PSE payload\n", fid); + target = PSE_PAYLOAD_BASE + (fid << 16); + remain = (target & 0xFFFF); + HAL_MCR_RD(prAdapter, CONN_HIF_ON_ADDR_REMAP1, &remap); + remap = (remap & 0xFFFF0000) + (target >> 16); + HAL_MCR_WR(prAdapter, CONN_HIF_ON_ADDR_REMAP1, remap); + for (i = 0; i < 16; i++) + HAL_MCR_RD(prAdapter, (AP2CONN_ADDR_MAP0 + remain + (i * 4)), + &result[i]); + dumpMemory32(result, 64); +} + +void halGetPleTxdInfo(IN struct ADAPTER *prAdapter, uint32_t fid, + uint32_t *result) +{ + uint32_t i = 0, target = 0, remap = 0, remain = 0; + + DBGLOG(HAL, INFO, "Dump fid=%u PLE TXD\n", fid); + target = PLE_PAYLOAD_BASE + (fid << 16); + remain = (target & 0xFFFF); + HAL_MCR_RD(prAdapter, CONN_HIF_ON_ADDR_REMAP1, &remap); + remap = (remap & 0xFFFF0000) + (target >> 16); + HAL_MCR_WR(prAdapter, CONN_HIF_ON_ADDR_REMAP1, remap); + for (i = 0; i < 16; i++) + HAL_MCR_RD(prAdapter, (AP2CONN_ADDR_MAP0 + remain + (i * 4)), + &result[i]); + dumpMemory32(result, 64); +} + +void halDumpTxdInfo(IN struct ADAPTER *prAdapter, uint32_t *tmac_info) +{ + struct TMAC_TXD_S *txd_s; + struct TMAC_TXD_0 *txd_0; + struct TMAC_TXD_1 *txd_1; + uint8_t q_idx = 0; + + txd_s = (struct TMAC_TXD_S *)tmac_info; + txd_0 = &txd_s->TxD0; + txd_1 = &txd_s->TxD1; + + DBGLOG(HAL, INFO, "TMAC_TXD Fields:\n"); + DBGLOG(HAL, INFO, "\tTMAC_TXD_0:\n"); + DBGLOG(HAL, INFO, "\t\tPortID=%d(%s)\n", + txd_0->p_idx, p_idx_str[txd_0->p_idx]); + + if (txd_0->p_idx == P_IDX_LMAC) + q_idx = txd_0->q_idx % 0x18; + else + q_idx = ((txd_0->q_idx == TxQ_IDX_MCU_PDA) ? + txd_0->q_idx : (txd_0->q_idx % 0x4)); + + DBGLOG(HAL, INFO, "\t\tQueID=0x%x(%s %s)\n", txd_0->q_idx, + (txd_0->p_idx == P_IDX_LMAC ? "LMAC" : "MCU"), + txd_0->p_idx == P_IDX_LMAC ? + q_idx_lmac_str[q_idx] : q_idx_mcu_str[q_idx]); + DBGLOG(HAL, INFO, "\t\tTxByteCnt=%d\n", txd_0->TxByteCount); + DBGLOG(HAL, INFO, "\t\tIpChkSumOffload=%d\n", txd_0->IpChkSumOffload); + DBGLOG(HAL, INFO, "\t\tUdpTcpChkSumOffload=%d\n", + txd_0->UdpTcpChkSumOffload); + DBGLOG(HAL, INFO, "\t\tEthTypeOffset=%d\n", txd_0->EthTypeOffset); + + DBGLOG(HAL, INFO, "\tTMAC_TXD_1:\n"); + DBGLOG(HAL, INFO, "\t\twlan_idx=%d\n", txd_1->wlan_idx); + DBGLOG(HAL, INFO, "\t\tHdrFmt=%d(%s)\n", + txd_1->hdr_format, hdr_fmt_str[txd_1->hdr_format]); + DBGLOG(HAL, INFO, "\t\tHdrInfo=0x%x\n", txd_1->hdr_info); + + switch (txd_1->hdr_format) { + case TMI_HDR_FT_NON_80211: + DBGLOG(HAL, INFO, + "\t\t\tMRD=%d, EOSP=%d, RMVL=%d, VLAN=%d, ETYP=%d\n", + txd_1->hdr_info & (1 << TMI_HDR_INFO_0_BIT_MRD), + txd_1->hdr_info & (1 << TMI_HDR_INFO_0_BIT_EOSP), + txd_1->hdr_info & (1 << TMI_HDR_INFO_0_BIT_RMVL), + txd_1->hdr_info & (1 << TMI_HDR_INFO_0_BIT_VLAN), + txd_1->hdr_info & (1 << TMI_HDR_INFO_0_BIT_ETYP)); + break; + + case TMI_HDR_FT_CMD: + DBGLOG(HAL, INFO, "\t\t\tRsvd=0x%x\n", txd_1->hdr_info); + break; + + case TMI_HDR_FT_NOR_80211: + DBGLOG(HAL, INFO, "\t\t\tHeader Len=%d(WORD)\n", + txd_1->hdr_info & TMI_HDR_INFO_2_MASK_LEN); + break; + + case TMI_HDR_FT_ENH_80211: + DBGLOG(HAL, INFO, "\t\t\tEOSP=%d, AMS=%d\n", + txd_1->hdr_info & (1 << TMI_HDR_INFO_3_BIT_EOSP), + txd_1->hdr_info & (1 << TMI_HDR_INFO_3_BIT_AMS)); + break; + } + + DBGLOG(HAL, INFO, "\t\tTxDFormatType=%d(%s format)\n", txd_1->ft, + (txd_1->ft == TMI_FT_LONG ? + "Long - 8 DWORD" : "Short - 3 DWORD")); + DBGLOG(HAL, INFO, "\t\ttxd_len=%d page(%d DW)\n", + txd_1->txd_len == 0 ? 1 : 2, (txd_1->txd_len + 1) * 16); + DBGLOG(HAL, INFO, + "\t\tHdrPad=%d(Padding Mode: %s, padding bytes: %d)\n", + txd_1->hdr_pad, + ((txd_1->hdr_pad & (TMI_HDR_PAD_MODE_TAIL << 1)) ? + "tail" : "head"), (txd_1->hdr_pad & 0x1 ? 2 : 0)); + DBGLOG(HAL, INFO, "\t\tUNxV=%d\n", txd_1->UNxV); + DBGLOG(HAL, INFO, "\t\tamsdu=%d\n", txd_1->amsdu); + DBGLOG(HAL, INFO, "\t\tTID=%d\n", txd_1->tid); + DBGLOG(HAL, INFO, "\t\tpkt_ft=%d(%s)\n", + txd_1->pkt_ft, pkt_ft_str[txd_1->pkt_ft]); + DBGLOG(HAL, INFO, "\t\town_mac=%d\n", txd_1->OwnMacAddr); + + if (txd_s->TxD1.ft == TMI_FT_LONG) { + struct TMAC_TXD_L *txd_l = (struct TMAC_TXD_L *)tmac_info; + struct TMAC_TXD_2 *txd_2 = &txd_l->TxD2; + struct TMAC_TXD_3 *txd_3 = &txd_l->TxD3; + struct TMAC_TXD_4 *txd_4 = &txd_l->TxD4; + struct TMAC_TXD_5 *txd_5 = &txd_l->TxD5; + struct TMAC_TXD_6 *txd_6 = &txd_l->TxD6; + + DBGLOG(HAL, INFO, "\tTMAC_TXD_2:\n"); + DBGLOG(HAL, INFO, "\t\tsub_type=%d\n", txd_2->sub_type); + DBGLOG(HAL, INFO, "\t\tfrm_type=%d\n", txd_2->frm_type); + DBGLOG(HAL, INFO, "\t\tNDP=%d\n", txd_2->ndp); + DBGLOG(HAL, INFO, "\t\tNDPA=%d\n", txd_2->ndpa); + DBGLOG(HAL, INFO, "\t\tSounding=%d\n", txd_2->sounding); + DBGLOG(HAL, INFO, "\t\tRTS=%d\n", txd_2->rts); + DBGLOG(HAL, INFO, "\t\tbc_mc_pkt=%d\n", txd_2->bc_mc_pkt); + DBGLOG(HAL, INFO, "\t\tBIP=%d\n", txd_2->bip); + DBGLOG(HAL, INFO, "\t\tDuration=%d\n", txd_2->duration); + DBGLOG(HAL, INFO, "\t\tHE(HTC Exist)=%d\n", txd_2->htc_vld); + DBGLOG(HAL, INFO, "\t\tFRAG=%d\n", txd_2->frag); + DBGLOG(HAL, INFO, "\t\tReamingLife/MaxTx time=%d\n", + txd_2->max_tx_time); + DBGLOG(HAL, INFO, "\t\tpwr_offset=%d\n", txd_2->pwr_offset); + DBGLOG(HAL, INFO, "\t\tba_disable=%d\n", txd_2->ba_disable); + DBGLOG(HAL, INFO, "\t\ttiming_measure=%d\n", + txd_2->timing_measure); + DBGLOG(HAL, INFO, "\t\tfix_rate=%d\n", txd_2->fix_rate); + DBGLOG(HAL, INFO, "\tTMAC_TXD_3:\n"); + DBGLOG(HAL, INFO, "\t\tNoAck=%d\n", txd_3->no_ack); + DBGLOG(HAL, INFO, "\t\tPF=%d\n", txd_3->protect_frm); + DBGLOG(HAL, INFO, "\t\ttx_cnt=%d\n", txd_3->tx_cnt); + DBGLOG(HAL, INFO, "\t\tremain_tx_cnt=%d\n", + txd_3->remain_tx_cnt); + DBGLOG(HAL, INFO, "\t\tsn=%d\n", txd_3->sn); + DBGLOG(HAL, INFO, "\t\tpn_vld=%d\n", txd_3->pn_vld); + DBGLOG(HAL, INFO, "\t\tsn_vld=%d\n", txd_3->sn_vld); + DBGLOG(HAL, INFO, "\tTMAC_TXD_4:\n"); + DBGLOG(HAL, INFO, "\t\tpn_low=0x%x\n", txd_4->pn_low); + DBGLOG(HAL, INFO, "\tTMAC_TXD_5:\n"); + DBGLOG(HAL, INFO, "\t\ttx_status_2_host=%d\n", + txd_5->tx_status_2_host); + DBGLOG(HAL, INFO, "\t\ttx_status_2_mcu=%d\n", + txd_5->tx_status_2_mcu); + DBGLOG(HAL, INFO, "\t\ttx_status_fmt=%d\n", + txd_5->tx_status_fmt); + + if (txd_5->tx_status_2_host || txd_5->tx_status_2_mcu) + DBGLOG(HAL, INFO, "\t\tpid=%d\n", txd_5->pid); + + if (txd_2->fix_rate) + DBGLOG(HAL, INFO, + "\t\tda_select=%d\n", txd_5->da_select); + + DBGLOG(HAL, INFO, "\t\tpwr_mgmt=0x%x\n", txd_5->pwr_mgmt); + DBGLOG(HAL, INFO, "\t\tpn_high=0x%x\n", txd_5->pn_high); + + if (txd_2->fix_rate) { + DBGLOG(HAL, INFO, "\tTMAC_TXD_6:\n"); + DBGLOG(HAL, INFO, "\t\tfix_rate_mode=%d\n", + txd_6->fix_rate_mode); + DBGLOG(HAL, INFO, "\t\tGI=%d(%s)\n", txd_6->gi, + (txd_6->gi == 0 ? "LONG" : "SHORT")); + DBGLOG(HAL, INFO, "\t\tldpc=%d(%s)\n", txd_6->ldpc, + (txd_6->ldpc == 0 ? "BCC" : "LDPC")); + DBGLOG(HAL, INFO, "\t\tTxBF=%d\n", txd_6->TxBF); + DBGLOG(HAL, INFO, "\t\ttx_rate=0x%x\n", txd_6->tx_rate); + DBGLOG(HAL, INFO, "\t\tant_id=%d\n", txd_6->ant_id); + DBGLOG(HAL, INFO, "\t\tdyn_bw=%d\n", txd_6->dyn_bw); + DBGLOG(HAL, INFO, "\t\tbw=%d\n", txd_6->bw); + } + } +} + +void halShowLitePleInfo(IN struct ADAPTER *prAdapter) +{ + uint32_t pg_flow_ctrl[6] = {0}; + uint32_t rpg_hif, upg_hif, i, j; + uint32_t ple_stat[17] = {0}; + uint32_t sta_pause[4] = {0}; + uint32_t dis_sta_map[4] = {0}; + + HAL_MCR_RD(prAdapter, PLE_HIF_PG_INFO, &pg_flow_ctrl[3]); + rpg_hif = pg_flow_ctrl[3] & 0xfff; + upg_hif = (pg_flow_ctrl[3] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of HIF group=0x%03x/0x%03x\n", + upg_hif, rpg_hif); + + HAL_MCR_RD(prAdapter, PLE_QUEUE_EMPTY, &ple_stat[0]); + HAL_MCR_RD(prAdapter, PLE_AC0_QUEUE_EMPTY_0, &ple_stat[1]); + HAL_MCR_RD(prAdapter, PLE_AC0_QUEUE_EMPTY_1, &ple_stat[2]); + HAL_MCR_RD(prAdapter, PLE_AC0_QUEUE_EMPTY_2, &ple_stat[3]); + HAL_MCR_RD(prAdapter, PLE_AC0_QUEUE_EMPTY_3, &ple_stat[4]); + HAL_MCR_RD(prAdapter, PLE_AC1_QUEUE_EMPTY_0, &ple_stat[5]); + HAL_MCR_RD(prAdapter, PLE_AC1_QUEUE_EMPTY_1, &ple_stat[6]); + HAL_MCR_RD(prAdapter, PLE_AC1_QUEUE_EMPTY_2, &ple_stat[7]); + HAL_MCR_RD(prAdapter, PLE_AC1_QUEUE_EMPTY_3, &ple_stat[8]); + HAL_MCR_RD(prAdapter, PLE_AC2_QUEUE_EMPTY_0, &ple_stat[9]); + HAL_MCR_RD(prAdapter, PLE_AC2_QUEUE_EMPTY_1, &ple_stat[10]); + HAL_MCR_RD(prAdapter, PLE_AC2_QUEUE_EMPTY_2, &ple_stat[11]); + HAL_MCR_RD(prAdapter, PLE_AC2_QUEUE_EMPTY_3, &ple_stat[12]); + HAL_MCR_RD(prAdapter, PLE_AC3_QUEUE_EMPTY_0, &ple_stat[13]); + HAL_MCR_RD(prAdapter, PLE_AC3_QUEUE_EMPTY_1, &ple_stat[14]); + HAL_MCR_RD(prAdapter, PLE_AC3_QUEUE_EMPTY_2, &ple_stat[15]); + HAL_MCR_RD(prAdapter, PLE_AC3_QUEUE_EMPTY_3, &ple_stat[16]); + + HAL_MCR_RD(prAdapter, STATION_PAUSE0, &sta_pause[0]); + HAL_MCR_RD(prAdapter, STATION_PAUSE1, &sta_pause[1]); + HAL_MCR_RD(prAdapter, STATION_PAUSE2, &sta_pause[2]); + HAL_MCR_RD(prAdapter, STATION_PAUSE3, &sta_pause[3]); + + HAL_MCR_RD(prAdapter, DIS_STA_MAP0, &dis_sta_map[0]); + HAL_MCR_RD(prAdapter, DIS_STA_MAP1, &dis_sta_map[1]); + HAL_MCR_RD(prAdapter, DIS_STA_MAP2, &dis_sta_map[2]); + HAL_MCR_RD(prAdapter, DIS_STA_MAP3, &dis_sta_map[3]); + + for (j = 0; j < 16; j = j + 4) { /* show AC Q info */ + for (i = 0; i < 32; i++) { + if (((ple_stat[j + 1] & (0x1 << i)) >> i) == 0) { + uint32_t hfid, tfid, pktcnt, + ac_num = j / 4, ctrl = 0; + uint32_t sta_num = i + (j % 4) * 32, + fl_que_ctrl[3] = {0}; + fl_que_ctrl[0] |= (0x1 << 31); + fl_que_ctrl[0] |= (0x2 << 14); + fl_que_ctrl[0] |= (ac_num << 8); + fl_que_ctrl[0] |= sta_num; + HAL_MCR_WR(prAdapter, + PLE_FL_QUE_CTRL_0, fl_que_ctrl[0]); + HAL_MCR_RD(prAdapter, + PLE_FL_QUE_CTRL_2, &fl_que_ctrl[1]); + HAL_MCR_RD(prAdapter, + PLE_FL_QUE_CTRL_3, &fl_que_ctrl[2]); + hfid = fl_que_ctrl[1] & 0xfff; + tfid = (fl_que_ctrl[1] & 0xfff << 16) >> 16; + pktcnt = fl_que_ctrl[2] & 0xfff; + + if (((sta_pause[j % 4] & 0x1 << i) >> i) == 1) + ctrl = 2; + if (((dis_sta_map[j % 4] & 0x1 << i) >> i) == 1) + ctrl = 1; + DBGLOG(HAL, INFO, + "STA%d AC%d:", + sta_num, ac_num); + DBGLOG(HAL, INFO, + " tail/head fid = 0x%03x/0x%03x,", + tfid, hfid); + DBGLOG(HAL, INFO, + " pkt cnt = %x ctrl = %s\n", + pktcnt, sta_ctrl_reg[ctrl]); + } + } + } +} + +void halShowTxdInfo( + struct ADAPTER *prAdapter, + u_int32_t fid) +{ + uint32_t txd_info[16] = {0}; + + halGetPleTxdInfo(prAdapter, fid, txd_info); + halDumpTxdInfo(prAdapter, txd_info); +} + +int32_t halShowStatInfo(struct ADAPTER *prAdapter, + IN char *pcCommand, IN int i4TotalLen, + struct PARAM_HW_WLAN_INFO *prHwWlanInfo, + struct PARAM_GET_STA_STATISTICS *prQueryStaStatistics, + u_int8_t fgResetCnt, uint32_t u4StatGroup) +{ + int32_t i4BytesWritten = 0; + int32_t rRssi; + uint16_t u2LinkSpeed; + uint32_t u4Per, u4RxPer[ENUM_BAND_NUM], u4AmpduPer[ENUM_BAND_NUM], + u4InstantPer; + uint8_t ucDbdcIdx, ucSkipAr, ucStaIdx, ucNss; + static uint32_t u4TotalTxCnt, u4TotalFailCnt; + static uint32_t u4Rate1TxCnt, u4Rate1FailCnt; + static uint32_t au4RxMpduCnt[ENUM_BAND_NUM] = {0}; + static uint32_t au4FcsError[ENUM_BAND_NUM] = {0}; + static uint32_t au4RxFifoCnt[ENUM_BAND_NUM] = {0}; + static uint32_t au4AmpduTxSfCnt[ENUM_BAND_NUM] = {0}; + static uint32_t au4AmpduTxAckSfCnt[ENUM_BAND_NUM] = {0}; + struct RX_CTRL *prRxCtrl; + uint32_t u4InstantRxPer[ENUM_BAND_NUM]; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + int16_t i2Wf0AvgPwr = 0, i2Wf1AvgPwr = 0; + uint32_t u4BufLen = 0; +#if (CFG_SUPPORT_RA_GEN == 1) + uint8_t ucRaTableNum = sizeof(RATE_TBLE) / sizeof(char *); + uint8_t ucRaStatusNum = sizeof(RA_STATUS_TBLE) / sizeof(char *); + uint8_t ucRaLtModeNum = sizeof(LT_MODE_TBLE) / sizeof(char *); + uint8_t ucRaSgiUnSpStateNum = sizeof(SGI_UNSP_STATE_TBLE) / + sizeof(char *); + uint8_t ucRaBwStateNum = sizeof(BW_STATE_TBLE) / sizeof(char *); + uint8_t ucAggRange[AGG_RANGE_SEL_NUM] = {0}; + uint32_t u4RangeCtrl_0, u4RangeCtrl_1; + enum AGG_RANGE_TYPE_T eRangeType = ENUM_AGG_RANGE_TYPE_TX; +#endif + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + struct PARAM_LINK_SPEED_EX rLinkSpeed; + + ucSkipAr = prQueryStaStatistics->ucSkipAr; + prRxCtrl = &prAdapter->rRxCtrl; + ucNss = prAdapter->rWifiVar.ucNSS; + + if (ucSkipAr) { +#if (CFG_SUPPORT_RA_GEN == 1) + u4TotalTxCnt += prQueryStaStatistics->u4TransmitCount; + u4TotalFailCnt += prQueryStaStatistics->u4TransmitFailCount; + u4Rate1TxCnt += prQueryStaStatistics->u4Rate1TxCnt; + u4Rate1FailCnt += prQueryStaStatistics->u4Rate1FailCnt; + + u4Per = (u4Rate1TxCnt == 0) ? + (0) : (1000 * (u4Rate1FailCnt) / (u4Rate1TxCnt)); + u4InstantPer = (prQueryStaStatistics->u4Rate1TxCnt == 0) ? + (0) : (1000 * (prQueryStaStatistics->u4Rate1FailCnt) / + (prQueryStaStatistics->u4Rate1TxCnt)); +#else + u4TotalTxCnt += prHwWlanInfo->rWtblTxCounter.u2CurBwTxCnt + + prHwWlanInfo->rWtblTxCounter.u2OtherBwTxCnt; + u4TotalFailCnt += prHwWlanInfo->rWtblTxCounter.u2CurBwFailCnt + + prHwWlanInfo->rWtblTxCounter.u2OtherBwFailCnt; + u4Rate1TxCnt += prHwWlanInfo->rWtblTxCounter.u2Rate1TxCnt; + u4Rate1FailCnt += prHwWlanInfo->rWtblTxCounter.u2Rate1FailCnt; + u4Per = (prHwWlanInfo->rWtblTxCounter.u2Rate1TxCnt == 0) ? + (0) : (1000 * u4Rate1FailCnt / u4Rate1TxCnt); + u4InstantPer = + (prHwWlanInfo->rWtblTxCounter.u2Rate1TxCnt == 0) ? (0) : + (1000 * (prHwWlanInfo->rWtblTxCounter.u2Rate1FailCnt) / + (prHwWlanInfo->rWtblTxCounter.u2Rate1TxCnt)); +#endif + } else { + u4Per = (prQueryStaStatistics->u4Rate1TxCnt == 0) ? + (0) : (1000 * (prQueryStaStatistics->u4Rate1FailCnt) / + (prQueryStaStatistics->u4Rate1TxCnt)); + u4InstantPer = (prQueryStaStatistics->ucPer == 0) ? + (0) : (prQueryStaStatistics->ucPer); + } + + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; ucDbdcIdx++) { + au4RxMpduCnt[ucDbdcIdx] += + prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4RxMpduCnt; + au4FcsError[ucDbdcIdx] += + prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4FcsError; + au4RxFifoCnt[ucDbdcIdx] += + prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4RxFifoFull; + au4AmpduTxSfCnt[ucDbdcIdx] += + prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4AmpduTxSfCnt; + au4AmpduTxAckSfCnt[ucDbdcIdx] += + prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4AmpduTxAckSfCnt; + + u4RxPer[ucDbdcIdx] = + ((au4RxMpduCnt[ucDbdcIdx] + au4FcsError[ucDbdcIdx]) == 0) ? + (0) : (1000 * au4FcsError[ucDbdcIdx] / + (au4RxMpduCnt[ucDbdcIdx] + + au4FcsError[ucDbdcIdx])); + + u4AmpduPer[ucDbdcIdx] = + (au4AmpduTxSfCnt[ucDbdcIdx] == 0) ? + (0) : (1000 * (au4AmpduTxSfCnt[ucDbdcIdx] - + au4AmpduTxAckSfCnt[ucDbdcIdx]) / + au4AmpduTxSfCnt[ucDbdcIdx]); + + u4InstantRxPer[ucDbdcIdx] = + ((prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4RxMpduCnt + + prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4FcsError) + == 0) ? (0) : (1000 * prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].u4FcsError / + (prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4RxMpduCnt + + prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4FcsError)); + } + + rRssi = RCPI_TO_dBm(prQueryStaStatistics->ucRcpi); + u2LinkSpeed = (prQueryStaStatistics->u2LinkSpeed == 0) ? 0 : + prQueryStaStatistics->u2LinkSpeed / 2; + + /* =========== Group 0x0001 =========== */ + if (u4StatGroup & 0x0001) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "\n----- STA Stat (Group 0x01) -----\n"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CurrTemperature", " = ", + prQueryStaStatistics->ucTemperature); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Tx Total cnt", " = ", + ucSkipAr ? (u4TotalTxCnt) : + (prQueryStaStatistics->u4TransmitCount)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Tx Fail Cnt", " = ", + ucSkipAr ? (u4TotalFailCnt) : + (prQueryStaStatistics->u4TransmitFailCount)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Rate1 Tx Cnt", " = ", + ucSkipAr ? (u4Rate1TxCnt) : + (prQueryStaStatistics->u4Rate1TxCnt)); + + if (ucSkipAr) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d, PER = %d.%1d%%, instant PER = %d.%1d%%\n", + "Rate1 Fail Cnt", " = ", + u4Rate1FailCnt, u4Per/10, u4Per%10, + u4InstantPer/10, u4InstantPer%10); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d, PER = %d.%1d%%, instant PER = %d%%\n", + "Rate1 Fail Cnt", " = ", + prQueryStaStatistics->u4Rate1FailCnt, + u4Per/10, u4Per%10, u4InstantPer); + + if ((ucSkipAr) && (fgResetCnt)) { + u4TotalTxCnt = 0; + u4TotalFailCnt = 0; + u4Rate1TxCnt = 0; + u4Rate1FailCnt = 0; + } + } + + /* =========== Group 0x0002 =========== */ + if (u4StatGroup & 0x0002) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "----- MIB Info (Group 0x02) -----\n"); + + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; ucDbdcIdx++) { + if (prAdapter->rWifiVar.fgDbDcModeEn) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "[DBDC_%d] :\n", ucDbdcIdx); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RX Success", " = ", + au4RxMpduCnt[ucDbdcIdx]); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d, PER = %d.%1d%%, instant PER = %d.%1d%%\n", + "RX with CRC", " = ", au4FcsError[ucDbdcIdx], + u4RxPer[ucDbdcIdx] / 10, + u4RxPer[ucDbdcIdx] % 10, + u4InstantRxPer[ucDbdcIdx] / 10, + u4InstantRxPer[ucDbdcIdx] % 10); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RX drop FIFO full", " = ", + au4RxFifoCnt[ucDbdcIdx]); + + if (!prAdapter->rWifiVar.fgDbDcModeEn) + break; + } + + if (fgResetCnt) { + kalMemZero(au4RxMpduCnt, sizeof(au4RxMpduCnt)); + kalMemZero(au4FcsError, sizeof(au4RxMpduCnt)); + kalMemZero(au4RxFifoCnt, sizeof(au4RxMpduCnt)); + kalMemZero(au4AmpduTxSfCnt, sizeof(au4RxMpduCnt)); + kalMemZero(au4AmpduTxAckSfCnt, sizeof(au4RxMpduCnt)); + } + } + + /* =========== Group 0x0004 =========== */ + if (u4StatGroup & 0x0004) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "----- Last Rx Info (Group 0x04) -----\n"); + + /* get Beacon RSSI */ + ucBssIndex = secGetBssIdxByWlanIdx + (prAdapter, (uint8_t)(prHwWlanInfo->u4Index)); + + rStatus = kalIoctlByBssIdx(prAdapter->prGlueInfo, + wlanoidQueryRssi, &rLinkSpeed, + sizeof(rLinkSpeed), TRUE, TRUE, TRUE, + &u4BufLen, ucBssIndex); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "unable to retrieve rssi\n"); + if (ucBssIndex < BSSID_NUM) + rRssi = rLinkSpeed.rLq[ucBssIndex].cRssi; + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + 1; +#if (CFG_SUPPORT_RA_GEN == 0) + rStatus = kalIoctl(prAdapter->prGlueInfo, + wlanoidQuerySwCtrlRead, &rSwCtrlInfo, + sizeof(rSwCtrlInfo), TRUE, TRUE, TRUE, + &u4BufLen); +#endif + DBGLOG(REQ, LOUD, "rStatus %u, rSwCtrlInfo.u4Data 0x%x\n", + rStatus, rSwCtrlInfo.u4Data); + if (rStatus == WLAN_STATUS_SUCCESS) { + i2Wf0AvgPwr = rSwCtrlInfo.u4Data & 0xFFFF; + i2Wf1AvgPwr = (rSwCtrlInfo.u4Data >> 16) & 0xFFFF; + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d %d\n", "NOISE", " = ", + i2Wf0AvgPwr, i2Wf1AvgPwr); + } + + /* Last RX Rate */ + i4BytesWritten += nicGetRxRateInfo(prAdapter, + pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + (uint8_t)(prHwWlanInfo->u4Index)); + + /* Last RX RSSI */ + i4BytesWritten += nicRxGetLastRxRssi(prAdapter, + pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + (uint8_t)(prHwWlanInfo->u4Index)); + + /* Last TX Resp RSSI */ + if (ucNss > 2) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d %d %d %d\n", + "Tx Response RSSI", " = ", + RCPI_TO_dBm( + prHwWlanInfo->rWtblRxCounter.ucRxRcpi0), + RCPI_TO_dBm( + prHwWlanInfo->rWtblRxCounter.ucRxRcpi1), + RCPI_TO_dBm( + prHwWlanInfo->rWtblRxCounter.ucRxRcpi2), + RCPI_TO_dBm( + prHwWlanInfo->rWtblRxCounter.ucRxRcpi3)); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d %d\n", "Tx Response RSSI", " = ", + RCPI_TO_dBm( + prHwWlanInfo->rWtblRxCounter.ucRxRcpi0), + RCPI_TO_dBm( + prHwWlanInfo->rWtblRxCounter.ucRxRcpi1)); + + /* Last Beacon RSSI */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Beacon RSSI", " = ", rRssi); + } + + /* =========== Group 0x0008 =========== */ + if (u4StatGroup & 0x0008) { + /* TxV */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "----- Last TX Info (Group 0x08) -----\n"); + + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; ucDbdcIdx++) { + if (prAdapter->rWifiVar.fgDbDcModeEn) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "[DBDC_%d] :\n", ucDbdcIdx); + + i4BytesWritten += nicTxGetVectorInfo( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + &prQueryStaStatistics->rTxVector[ucDbdcIdx]); + + if (prQueryStaStatistics->rTxVector[ucDbdcIdx] + .u4TxV[0] == 0xFFFFFFFF) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Chip Out TX Power", + " = ", "N/A"); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%ld.%1ld dBm\n", + "Chip Out TX Power", " = ", + TX_VECTOR_GET_TX_PWR( + &prQueryStaStatistics->rTxVector[ + ucDbdcIdx]) >> 1, + 5 * (TX_VECTOR_GET_TX_PWR( + &prQueryStaStatistics->rTxVector[ + ucDbdcIdx]) % 2)); + + if (!prAdapter->rWifiVar.fgDbDcModeEn) + break; + } + } + + /* =========== Group 0x0010 =========== */ + if (u4StatGroup & 0x0010) { + /* RX Reorder */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "----- RX Reorder (Group 0x10) -----\n"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%llu\n", "Rx reorder miss", " = ", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_MISS_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%llu\n", "Rx reorder within", " = ", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_WITHIN_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%llu\n", "Rx reorder ahead", " = ", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_AHEAD_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%llu\n", "Rx reorder behind", " = ", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_BEHIND_COUNT)); + } + + /* =========== Group 0x0020 =========== */ + if (u4StatGroup & 0x0020) { + /* RA info */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "----- RA Info (Group 0x20) -----\n"); + + /* Last TX Rate */ + i4BytesWritten += nicGetTxRateInfo( + pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + FALSE, prHwWlanInfo, prQueryStaStatistics); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%-20s%s%d\n", "LinkSpeed", + " = ", u2LinkSpeed); + + if (!prQueryStaStatistics->ucSkipAr) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "RateTable", " = ", +#if (CFG_SUPPORT_RA_GEN == 1) + prQueryStaStatistics->ucArTableIdx < + (ucRaTableNum - 1) ? + RATE_TBLE[prQueryStaStatistics->ucArTableIdx] : + RATE_TBLE[ucRaTableNum - 1]); +#else + prQueryStaStatistics->ucArTableIdx < 6 ? + RATE_TBLE[prQueryStaStatistics->ucArTableIdx] : + RATE_TBLE[6]); +#endif + + if (wlanGetStaIdxByWlanIdx(prAdapter, + (uint8_t)(prHwWlanInfo->u4Index), &ucStaIdx) == + WLAN_STATUS_SUCCESS) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "2G Support 256QAM TX", + " = ", +#if (CFG_SUPPORT_RA_GEN == 1) + ((prAdapter->arStaRec[ucStaIdx].u4Flags + & MTK_SYNERGY_CAP_SUPPORT_24G_MCS89) || + (prQueryStaStatistics-> + ucDynamicGband256QAMState == 2)) ? + 1 : 0); +#else + (prAdapter->arStaRec[ucStaIdx].u4Flags & + MTK_SYNERGY_CAP_SUPPORT_24G_MCS89) ? + 1 : 0); +#endif + } + +#if (CFG_SUPPORT_RA_GEN == 0) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d%%\n", "Rate1 instantPer", " = ", + u4InstantPer); +#endif + + if (prQueryStaStatistics->ucAvePer == 0xFF) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Train Down", " = ", + "N/A"); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Train Up", " = ", + "N/A"); + } else { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d -> %d\n", "Train Down", + " = ", + (uint16_t) + (prQueryStaStatistics->u2TrainDown + & BITS(0, 7)), + (uint16_t) + ((prQueryStaStatistics->u2TrainDown >> + 8) & BITS(0, 7))); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d -> %d\n", "Train Up", " = ", + (uint16_t) + (prQueryStaStatistics->u2TrainUp + & BITS(0, 7)), + (uint16_t) + ((prQueryStaStatistics->u2TrainUp >> 8) + & BITS(0, 7))); + } + + if (prQueryStaStatistics->fgIsForceTxStream == 0) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Force Tx Stream", + " = ", "N/A"); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Force Tx Stream", " = ", + prQueryStaStatistics-> + fgIsForceTxStream); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Force SE off", " = ", + prQueryStaStatistics->fgIsForceSeOff); + +#if (CFG_SUPPORT_RA_GEN == 1) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "LtMode", " = ", + prQueryStaStatistics->ucLowTrafficMode < + (ucRaLtModeNum - 1) ? + LT_MODE_TBLE[prQueryStaStatistics-> + ucLowTrafficMode] : + LT_MODE_TBLE[ucRaLtModeNum - 1]); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "SgiState", " = ", + prQueryStaStatistics->ucDynamicSGIState < + (ucRaSgiUnSpStateNum - 1) ? + SGI_UNSP_STATE_TBLE[prQueryStaStatistics-> + ucDynamicSGIState] : + SGI_UNSP_STATE_TBLE[ucRaSgiUnSpStateNum - 1]); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "BwState", " = ", + prQueryStaStatistics->ucDynamicBWState < + (ucRaBwStateNum - 1) ? + BW_STATE_TBLE[prQueryStaStatistics-> + ucDynamicBWState] : + BW_STATE_TBLE[ucRaBwStateNum - 1]); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "NonSpState", " = ", + prQueryStaStatistics->ucDynamicSGIState < + (ucRaSgiUnSpStateNum - 1) ? + SGI_UNSP_STATE_TBLE[prQueryStaStatistics-> + ucVhtNonSpRateState] : + SGI_UNSP_STATE_TBLE[ucRaSgiUnSpStateNum - 1]); +#endif + } + +#if (CFG_SUPPORT_RA_GEN == 1) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RunningCnt", " = ", + prQueryStaStatistics->u2RaRunningCnt); + + prQueryStaStatistics->ucRaStatus &= ~0x80; + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Status", " = ", + prQueryStaStatistics->ucRaStatus < (ucRaStatusNum - 1) ? + RA_STATUS_TBLE[prQueryStaStatistics->ucRaStatus] : + RA_STATUS_TBLE[ucRaStatusNum - 1]); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "MaxAF", " = ", + prHwWlanInfo->rWtblPeerCap.ucAmpduFactor); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s0x%x\n", "SpeIdx", " = ", + prHwWlanInfo->rWtblPeerCap.ucSpatialExtensionIndex); +#endif + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CBRN", " = ", + prHwWlanInfo->rWtblPeerCap.ucChangeBWAfterRateN); + + /* Rate1~Rate8 */ + i4BytesWritten += nicGetTxRateInfo( + pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + TRUE, prHwWlanInfo, prQueryStaStatistics); + } + + /* =========== Group 0x0040 =========== */ + if (u4StatGroup & 0x0040) { +#if (CFG_SUPPORT_RA_GEN == 1) + u4RangeCtrl_0 = prQueryStaStatistics->u4AggRangeCtrl_0; + u4RangeCtrl_1 = prQueryStaStatistics->u4AggRangeCtrl_1; + eRangeType = (enum AGG_RANGE_TYPE_T) + prQueryStaStatistics->ucRangeType; + + ucAggRange[0] = (((u4RangeCtrl_0) & AGG_RANGE_SEL_0_MASK) >> + AGG_RANGE_SEL_0_OFFSET); + ucAggRange[1] = (((u4RangeCtrl_0) & AGG_RANGE_SEL_1_MASK) >> + AGG_RANGE_SEL_1_OFFSET); + ucAggRange[2] = (((u4RangeCtrl_0) & AGG_RANGE_SEL_2_MASK) >> + AGG_RANGE_SEL_2_OFFSET); + ucAggRange[3] = (((u4RangeCtrl_0) & AGG_RANGE_SEL_3_MASK) >> + AGG_RANGE_SEL_3_OFFSET); + ucAggRange[4] = (((u4RangeCtrl_1) & AGG_RANGE_SEL_4_MASK) >> + AGG_RANGE_SEL_4_OFFSET); + ucAggRange[5] = (((u4RangeCtrl_1) & AGG_RANGE_SEL_5_MASK) >> + AGG_RANGE_SEL_5_OFFSET); + ucAggRange[6] = (((u4RangeCtrl_1) & AGG_RANGE_SEL_6_MASK) >> + AGG_RANGE_SEL_6_OFFSET); + + /* Tx Agg */ + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s%s%s", "------ ", + (eRangeType) ? ( + (eRangeType == ENUM_AGG_RANGE_TYPE_TRX) ? + ("TRX") : ("RX")) : ("TX"), + " AGG (Group 0x40) -----\n"); + + if (eRangeType == ENUM_AGG_RANGE_TYPE_TRX) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-6s%8d%5d%1s%2d%5d%1s%2d%5d%3s", + " TX :", ucAggRange[0] + 1, + ucAggRange[0] + 2, "~", ucAggRange[1] + 1, + ucAggRange[1] + 2, "~", ucAggRange[2] + 1, + ucAggRange[2] + 2, "~64\n"); + + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; + ucDbdcIdx++) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "DBDC%d:", ucDbdcIdx); + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%8d%8d%8d%8d\n", + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].au2TxRangeAmpduCnt[ + 0], + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].au2TxRangeAmpduCnt[ + 1], + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].au2TxRangeAmpduCnt[ + 2], + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].au2TxRangeAmpduCnt[ + 3]); + + if (!prAdapter->rWifiVar.fgDbDcModeEn) + break; + } + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-6s%8d%5d%1s%2d%5d%1s%2d%5d%3s", + " RX :", ucAggRange[3] + 1, + ucAggRange[3] + 2, "~", ucAggRange[4] + 1, + ucAggRange[4] + 2, "~", ucAggRange[5] + 1, + ucAggRange[5] + 2, "~64\n"); + + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; + ucDbdcIdx++) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "DBDC%d:", ucDbdcIdx); + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%8d%8d%8d%8d\n", + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].au2TxRangeAmpduCnt[ + 4], + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].au2TxRangeAmpduCnt[ + 5], + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].au2TxRangeAmpduCnt[ + 6], + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].au2TxRangeAmpduCnt[ + 7]); + + if (!prAdapter->rWifiVar.fgDbDcModeEn) + break; + } + } else { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-6s%8d%5d%1s%2d%5d%1s%2d%5d%1s%2d%5d%1s%2d%5d%1s%2d%5d%1s%2d%5d%3s", + "Range:", ucAggRange[0] + 1, + ucAggRange[0] + 2, "~", ucAggRange[1] + 1, + ucAggRange[1] + 2, "~", ucAggRange[2] + 1, + ucAggRange[2] + 2, "~", ucAggRange[3] + 1, + ucAggRange[3] + 2, "~", ucAggRange[4] + 1, + ucAggRange[4] + 2, "~", ucAggRange[5] + 1, + ucAggRange[5] + 2, "~", ucAggRange[6] + 1, + ucAggRange[6] + 2, "~64\n"); + + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; + ucDbdcIdx++) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "DBDC%d:", ucDbdcIdx); + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%8d%8d%8d%8d%8d%8d%8d%8d\n", + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].au2TxRangeAmpduCnt[ + 0], + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].au2TxRangeAmpduCnt[ + 1], + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].au2TxRangeAmpduCnt[ + 2], + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].au2TxRangeAmpduCnt[ + 3], + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].au2TxRangeAmpduCnt[ + 4], + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].au2TxRangeAmpduCnt[ + 5], + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].au2TxRangeAmpduCnt[ + 6], + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].au2TxRangeAmpduCnt[ + 7]); + + if (!prAdapter->rWifiVar.fgDbDcModeEn) + break; + } + } +#else + /* Tx Agg */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "------ TX AGG (Group 0x40) -----\n"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-12s%s", "Range:", + "1 2~5 6~15 16~22 23~33 34~49 50~57 58~64\n"); + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; ucDbdcIdx++) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "DBDC%d:", ucDbdcIdx); + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%7d%8d%9d%9d%9d%9d%9d%9d\n", + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].au2TxRangeAmpduCnt[ + 0], + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].au2TxRangeAmpduCnt[ + 1], + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].au2TxRangeAmpduCnt[ + 2], + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].au2TxRangeAmpduCnt[ + 3], + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].au2TxRangeAmpduCnt[ + 4], + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].au2TxRangeAmpduCnt[ + 5], + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].au2TxRangeAmpduCnt[ + 6], + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].au2TxRangeAmpduCnt[ + 7]); + if (!prAdapter->rWifiVar.fgDbDcModeEn) + break; + } +#endif + } + + return i4BytesWritten; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/common/dbg_connac2x.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/common/dbg_connac2x.c new file mode 100644 index 0000000000000..8883c79b85ea3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/common/dbg_connac2x.c @@ -0,0 +1,2737 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** + *[File] dbg_connac2x.c + *[Version] v1.0 + *[Revision Date] 2019-04-09 + *[Author] + *[Description] + * The program provides WIFI FALCON MAC Debug APIs + *[Copyright] + * Copyright (C) 2015 MediaTek Incorporation. All Rights Reserved. + ******************************************************************************/ + +#if (CFG_SUPPORT_CONNAC2X == 1) +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" +#include "mt_dmac.h" +#include "wf_ple.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#if defined(MT7915) +#define WTBL_VER 1 +#elif defined(SOC3_0) +#define WTBL_VER 2 +#else +#define WTBL_VER 3 +#endif + +/******************************************************************************* + * 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 char *RATE_V2_HW_TX_MODE_STR[] = { + "CCK", "OFDM", "MM", "GF", "VHT", "PLR", + "N/A", "N/A", "HE_SU", "HE_ER", "HE_TRIG", "HE_MU"}; + +static char *RATE_TBLE[] = {"B", "G", "N", "N_2SS", "AC", "AC_2SS", "BG", + "HE", "HE_2SS", "N/A"}; + +static char *RA_STATUS_TBLE[] = {"INVALID", "POWER_SAVING", "SLEEP", "STANDBY", + "RUNNING", "N/A"}; + +#if 0 +static char *LT_MODE_TBLE[] = {"RSSI", "LAST_RATE", "TRACKING", "N/A"}; + +static char *SGI_UNSP_STATE_TBLE[] = {"INITIAL", "PROBING", "SUCCESS", + "FAILURE", "N/A"}; + +static char *BW_STATE_TBLE[] = {"UNCHANGED", "DOWN", "N/A"}; +#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 + ******************************************************************************* + */ + +static void connac2x_dump_tmac_info( + struct ADAPTER *prAdapter, + uint8_t *tmac_info) +{ + static const char * const pkt_ft_str[] = { + "cut_through", + "store_forward", + "cmd", + "PDA_FW_Download" + }; + + static const char * const hdr_fmt_str[] = { + "Non-80211-Frame", + "Command-Frame", + "Normal-80211-Frame", + "enhanced-80211-Frame", + }; + struct HW_MAC_CONNAC2X_TX_DESC *txd = + (struct HW_MAC_CONNAC2X_TX_DESC *)tmac_info; + + DBGLOG(HAL, INFO, "TMAC_TXD Fields:\n"); + DBGLOG(HAL, INFO, "\tTMAC_TXD_0:\n"); + + /* DW0 */ + /* TX Byte Count [15:0] */ + DBGLOG(HAL, INFO, "\t\tTxByteCnt = %d\n", + ((txd->u4DW0 & CONNAC2X_TX_DESC_TX_BYTE_COUNT_MASK) >> + CONNAC2X_TX_DESC_TX_BYTE_COUNT_OFFSET)); + + /* PKT_FT: Packet Format [24:23] */ + DBGLOG(HAL, INFO, "\t\tpkt_ft = %d(%s)\n", + ((txd->u4DW0 & CONNAC2X_TX_DESC_PACKET_FORMAT_MASK) >> + CONNAC2X_TX_DESC_PACKET_FORMAT_OFFSET), + pkt_ft_str[((txd->u4DW0 & CONNAC2X_TX_DESC_PACKET_FORMAT_MASK) >> + CONNAC2X_TX_DESC_PACKET_FORMAT_OFFSET)]); + + /* Q_IDX [31:25] */ + DBGLOG(HAL, INFO, "\t\tQueID =0x%x\n", + ((txd->u4DW0 & CONNAC2X_TX_DESC_QUEUE_INDEX_MASK) >> + CONNAC2X_TX_DESC_QUEUE_INDEX_OFFSET)); + + DBGLOG(HAL, INFO, "\tTMAC_TXD_1:\n"); + /* DW1 */ + /* WLAN Indec [9:0] */ + DBGLOG(HAL, INFO, "\t\tWlan Index = %d\n", + ((txd->u4DW1 & CONNAC2X_TX_DESC_WLAN_INDEX_MASK) >> + CONNAC2X_TX_DESC_WLAN_INDEX_OFFSET)); + + /* HF: Header Format [17:16] */ + DBGLOG(HAL, INFO, "\t\tHdrFmt = %d(%s)\n", + ((txd->u4DW1 & CONNAC2X_TX_DESC_HEADER_FORMAT_MASK) >> + CONNAC2X_TX_DESC_HEADER_FORMAT_OFFSET), + hdr_fmt_str[((txd->u4DW1 & CONNAC2X_TX_DESC_HEADER_FORMAT_MASK) >> + CONNAC2X_TX_DESC_HEADER_FORMAT_OFFSET)]); + + switch ((txd->u4DW1 & CONNAC2X_TX_DESC_HEADER_FORMAT_MASK) >> + CONNAC2X_TX_DESC_HEADER_FORMAT_OFFSET) { + case TMI_HDR_FT_NON_80211: + /* MRD [11], EOSP [12], RMVL [13], VLAN [14], ETYPE [15] */ + DBGLOG(HAL, INFO, + "\t\t\tMRD = %d, EOSP = %d, RMVL = %d, VLAN = %d, ETYP = %d\n", + (txd->u4DW1 & CONNAC2X_TX_DESC_NON_802_11_MORE_DATA) ? 1 : 0, + (txd->u4DW1 & CONNAC2X_TX_DESC_NON_802_11_EOSP) ? 1 : 0, + (txd->u4DW1 & CONNAC2X_TX_DESC_NON_802_11_REMOVE_VLAN) ? 1 : 0, + (txd->u4DW1 & CONNAC2X_TX_DESC_NON_802_11_VLAN_FIELD) ? 1 : 0, + (txd->u4DW1 & CONNAC2X_TX_DESC_NON_802_11_ETHERNET_II) ? 1 : 0); + break; + + case TMI_HDR_FT_NOR_80211: + /* HEADER_LENGTH [15:11] */ + DBGLOG(HAL, INFO, "\t\t\tHeader Len = %d(WORD)\n", + ((txd->u4DW1 & CONNAC2X_TX_DESC_NOR_802_11_HEADER_LENGTH_MASK) + >> CONNAC2X_TX_DESC_NOR_802_11_HEADER_LENGTH_OFFSET)); + break; + + case TMI_HDR_FT_ENH_80211: + /* EOSP [12], AMS [13] */ + DBGLOG(HAL, INFO, "\t\t\tEOSP = %d, AMS = %d\n", + (txd->u4DW1 & CONNAC2X_TX_DESC_ENH_802_11_EOSP) ? 1 : 0, + (txd->u4DW1 & CONNAC2X_TX_DESC_ENH_802_11_AMSDU) ? 1 : 0); + break; + } + + /* Header Padding [19:18] */ + DBGLOG(HAL, INFO, "\t\tHdrPad Mode = %d\n", + (txd->u4DW1 & CONNAC2X_TX_DESC_HEADER_PADDING_MODE) ? 1 : 0); + DBGLOG(HAL, INFO, "\t\tHdrPad Len = %d\n", + ((txd->u4DW1 & CONNAC2X_TX_DESC_HEADER_PADDING_LENGTH_MASK) >> + CONNAC2X_TX_DESC_HEADER_PADDING_LENGTH_OFFSET)); + + /* TID [22:20] */ + DBGLOG(HAL, INFO, "\t\tTID = %d\n", + ((txd->u4DW1 & CONNAC2X_TX_DESC_TID_MASK) >> + CONNAC2X_TX_DESC_TID_OFFSET)); + + /* UtxB/AMSDU_C/AMSDU [23] */ + DBGLOG(HAL, INFO, "\t\tamsdu = %d\n", + ((txd->u4DW1 & CONNAC2X_TX_DESC_TXD_UTXB_AMSDU_MASK) ? 1 : 0)); + + /* OM [29:24] */ + DBGLOG(HAL, INFO, "\t\town_mac = %d\n", + ((txd->u4DW1 & CONNAC2X_TX_DESC_OWN_MAC_MASK) >> + CONNAC2X_TX_DESC_OWN_MAC_OFFSET)); + + /* FT [31] */ + DBGLOG(HAL, INFO, "\t\tTxDFormatType = %d\n", + (txd->u4DW1 & CONNAC2X_TX_DESC_FORMAT) ? 1 : 0); + + DBGLOG(HAL, INFO, "\tTMAC_TXD_2:\n"); + /* DW2 */ + /* Subtype [3:0] */ + DBGLOG(HAL, INFO, "\t\tsub_type = %d\n", + ((txd->u4DW2 & CONNAC2X_TX_DESC_SUB_TYPE_MASK) >> + CONNAC2X_TX_DESC_SUB_TYPE_OFFSET)); + + /* Type[5:4] */ + DBGLOG(HAL, INFO, "\t\tfrm_type = %d\n", + ((txd->u4DW2 & CONNAC2X_TX_DESC_TYPE_MASK) >> + CONNAC2X_TX_DESC_TYPE_OFFSET)); + + /* NDP [6] */ + DBGLOG(HAL, INFO, "\t\tNDP = %d\n", + ((txd->u4DW2 & CONNAC2X_TX_DESC_NDP) ? 1 : 0)); + + /* NDPA [7] */ + DBGLOG(HAL, INFO, "\t\tNDPA = %d\n", + ((txd->u4DW2 & CONNAC2X_TX_DESC_NDPA) ? 1 : 0)); + + /* SD [8] */ + DBGLOG(HAL, INFO, "\t\tSounding = %d\n", + ((txd->u4DW2 & CONNAC2X_TX_DESC_SOUNDING) ? 1 : 0)); + + /* RTS [9] */ + DBGLOG(HAL, INFO, "\t\tRTS = %d\n", + ((txd->u4DW2 & CONNAC2X_TX_DESC_FORCE_RTS_CTS) ? 1 : 0)); + + /* BM [10] */ + DBGLOG(HAL, INFO, "\t\tbc_mc_pkt = %d\n", + ((txd->u4DW2 & CONNAC2X_TX_DESC_BROADCAST_MULTICAST) ? 1 : 0)); + + /* B [11] */ + DBGLOG(HAL, INFO, "\t\tBIP = %d\n", + ((txd->u4DW2 & CONNAC2X_TX_DESC_BIP_PROTECTED) ? 1 : 0)); + + /* DU [12] */ + DBGLOG(HAL, INFO, "\t\tDuration = %d\n", + ((txd->u4DW2 & CONNAC2X_TX_DESC_DURATION_FIELD_CONTROL) ? 1 : 0)); + + /* HE [13] */ + DBGLOG(HAL, INFO, "\t\tHE(HTC Exist) = %d\n", + ((txd->u4DW2 & CONNAC2X_TX_DESC_HTC_EXISTS) ? 1 : 0)); + + /* FRAG [15:14] */ + DBGLOG(HAL, INFO, "\t\tFRAG = %d\n", + ((txd->u4DW2 & CONNAC2X_TX_DESC_FRAGMENT_MASK) >> + CONNAC2X_TX_DESC_FRAGMENT_OFFSET)); + + /* Remaining Life Time [23:16]*/ + DBGLOG(HAL, INFO, "\t\tReamingLife/MaxTx time = %d\n", + ((txd->u4DW2 & CONNAC2X_TX_DESC_REMAINING_MAX_TX_TIME_MASK) >> + CONNAC2X_TX_DESC_REMAINING_MAX_TX_TIME_OFFSET)); + + /* Power Offset [29:24] */ + DBGLOG(HAL, INFO, "\t\tpwr_offset = %d\n", + ((txd->u4DW2 & CONNAC2X_TX_DESC_POWER_OFFSET_MASK) >> + CONNAC2X_TX_DESC_POWER_OFFSET_OFFSET)); + + /* FRM [30] */ + DBGLOG(HAL, INFO, "\t\tfix rate mode = %d\n", + (txd->u4DW2 & CONNAC2X_TX_DESC_FIXED_RATE_MODE) ? 1 : 0); + + /* FR[31] */ + DBGLOG(HAL, INFO, "\t\tfix rate = %d\n", + (txd->u4DW2 & CONNAC2X_TX_DESC_FIXED_RATE) ? 1 : 0); + + DBGLOG(HAL, INFO, "\tTMAC_TXD_3:\n"); + /* DW3 */ + /* NA [0] */ + DBGLOG(HAL, INFO, "\t\tNoAck = %d\n", + (txd->u4DW3 & CONNAC2X_TX_DESC_NO_ACK) ? 1 : 0); + + /* PF [1] */ + DBGLOG(HAL, INFO, "\t\tPF = %d\n", + (txd->u4DW3 & CONNAC2X_TX_DESC_PROTECTED_FRAME) ? 1 : 0); + + /* EMRD [2] */ + DBGLOG(HAL, INFO, "\t\tEMRD = %d\n", + (txd->u4DW3 & CONNAC2X_TX_DESC_EXTEND_MORE_DATA) ? 1 : 0); + + /* EEOSP [3] */ + DBGLOG(HAL, INFO, "\t\tEEOSP = %d\n", + (txd->u4DW3 & CONNAC2X_TX_DESC_EXTEND_EOSP) ? 1 : 0); + + /* DAS [4] */ + DBGLOG(HAL, INFO, "\t\tda_select = %d\n", + (txd->u4DW3 & CONNAC2X_TX_DESC_DA_SOURCE) ? 1 : 0); + + /* TM [5] */ + DBGLOG(HAL, INFO, "\t\ttm = %d\n", + (txd->u4DW3 & CONNAC2X_TX_DESC_TIMING_MEASUREMENT) ? 1 : 0); + + /* TX Count [10:6] */ + DBGLOG(HAL, INFO, "\t\ttx_cnt = %d\n", + ((txd->u4DW3 & CONNAC2X_TX_DESC_TX_COUNT_MASK) >> + CONNAC2X_TX_DESC_TX_COUNT_OFFSET)); + + /* Remaining TX Count [15:11] */ + DBGLOG(HAL, INFO, "\t\tremain_tx_cnt = %d\n", + ((txd->u4DW3 & CONNAC2X_TX_DESC_REMAINING_TX_COUNT_MASK) >> + CONNAC2X_TX_DESC_REMAINING_TX_COUNT_OFFSET)); + + /* SN [27:16] */ + DBGLOG(HAL, INFO, "\t\tsn = %d\n", + ((txd->u4DW3 & CONNAC2X_TX_DESC_SEQUENCE_NUMBER_MASK) >> + CONNAC2X_TX_DESC_SEQUENCE_NUMBER_MASK_OFFSET)); + + /* BA_DIS [28] */ + DBGLOG(HAL, INFO, "\t\tba dis = %d\n", + (txd->u4DW3 & CONNAC2X_TX_DESC_BA_DISABLE) ? 1 : 0); + + /* Power Management [29] */ + DBGLOG(HAL, INFO, "\t\tpwr_mgmt = 0x%x\n", + (txd->u4DW3 & CONNAC2X_TX_DESC_POWER_MANAGEMENT_CONTROL) ? 1 : 0); + + /* PN_VLD [30] */ + DBGLOG(HAL, INFO, "\t\tpn_vld = %d\n", + (txd->u4DW3 & CONNAC2X_TX_DESC_PN_IS_VALID) ? 1 : 0); + + /* SN_VLD [31] */ + DBGLOG(HAL, INFO, "\t\tsn_vld = %d\n", + (txd->u4DW3 & CONNAC2X_TX_DESC_SN_IS_VALID) ? 1 : 0); + + /* DW4 */ + DBGLOG(HAL, INFO, "\tTMAC_TXD_4:\n"); + + /* PN_LOW [31:0] */ + DBGLOG(HAL, INFO, "\t\tpn_low = 0x%x\n", txd->u4PN1); + + /* DW5 */ + DBGLOG(HAL, INFO, "\tTMAC_TXD_5:\n"); + + /* PN_HIGH [31:16] */ + DBGLOG(HAL, INFO, "\t\tpn_high = 0x%x\n", txd->u2PN2); + + /* PID [7:0] */ + DBGLOG(HAL, INFO, "\t\tpid = %d\n", + (txd->u2DW5_0 & CONNAC2X_TX_DESC_PACKET_ID_MASK) >> + CONNAC2X_TX_DESC_PACKET_ID_OFFSET); + + /* TXSFM [8] */ + DBGLOG(HAL, INFO, "\t\ttx_status_fmt = %d\n", + (txd->u2DW5_0 & CONNAC2X_TX_DESC_TX_STATUS_FORMAT) ? 1 : 0); + + /* TXS2M [9] */ + DBGLOG(HAL, INFO, "\t\ttx_status_2_mcu = %d\n", + (txd->u2DW5_0 & CONNAC2X_TX_DESC_TX_STATUS_TO_MCU) ? 1 : 0); + + /* TXS2H [10] */ + DBGLOG(HAL, INFO, "\t\ttx_status_2_host = %d\n", + (txd->u2DW5_0 & CONNAC2X_TX_DESC_TX_STATUS_TO_HOST) ? 1 : 0); + + /* DW6 */ + DBGLOG(HAL, INFO, "\tTMAC_TXD_6:\n"); + if (txd->u4DW2 & CONNAC2X_TX_DESC_FIXED_RATE) { + /* Fixed BandWidth mode [2:0] */ + DBGLOG(HAL, INFO, "\t\tbw = %d\n", + (txd->u4DW6 & CONNAC2X_TX_DESC_BANDWIDTH_MASK) >> + CONNAC2X_TX_DESC_BANDWIDTH_OFFSET); + + /* DYN_BW [3] */ + DBGLOG(HAL, INFO, "\t\tdyn_bw = %d\n", + (txd->u4DW6 & CONNAC2X_TX_DESC_DYNAMIC_BANDWIDTH) + ? 1 : 0); + + /* ANT_ID [7:4] */ + DBGLOG(HAL, INFO, "\t\tant_id = %d\n", + (txd->u4DW6 & CONNAC2X_TX_DESC_ANTENNA_INDEX_MASK) >> + CONNAC2X_TX_DESC_ANTENNA_INDEX_OFFSET); + + /* SPE_IDX_SEL [10] */ + DBGLOG(HAL, INFO, "\t\tspe idx sel = %d\n", + (txd->u4DW6 & CONNAC2X_TX_DESC_SPE_IDX_SEL) ? 1 : 0); + + /* LDPC [11] */ + DBGLOG(HAL, INFO, "\t\tldpc = %d\n", + (txd->u4DW6 & CONNAC2X_TX_DESC_LDPC) ? 1 : 0); + + /* HELTF Type[13:12] */ + DBGLOG(HAL, INFO, "\t\tHELTF Type = %d\n", + (txd->u4DW6 & CONNAC2X_TX_DESC_HE_LTF_MASK) >> + CONNAC2X_TX_DESC_HE_LTF_OFFSET); + + /* GI Type [15:14] */ + DBGLOG(HAL, INFO, "\t\tGI = %d\n", + (txd->u4DW6 & CONNAC2X_TX_DESC_GI_TYPE) >> + CONNAC2X_TX_DESC_GI_TYPE_OFFSET); + + /* Rate to be Fixed [29:16] */ + DBGLOG(HAL, INFO, "\t\ttx_rate = 0x%x\n", + (txd->u4DW6 & CONNAC2X_TX_DESC_FIXDE_RATE_MASK) >> + CONNAC2X_TX_DESC_FIXDE_RATE_OFFSET); + } + + /* TXEBF [30] */ + DBGLOG(HAL, INFO, "\t\ttxebf = %d\n", + (txd->u4DW6 & CONNAC2X_TX_DESC_TXE_BF) ? 1 : 0); + + /* TXIBF [31] */ + DBGLOG(HAL, INFO, "\t\ttxibf = %d\n", + (txd->u4DW6 & CONNAC2X_TX_DESC_TXI_BF) ? 1 : 0); + + /* DW7 */ + DBGLOG(HAL, INFO, "\tTMAC_TXD_7:\n"); + + /* TXD Arrival Time [9:0] */ + DBGLOG(HAL, INFO, "\t\tarrival time = %d\n", + txd->u4DW7 & CONNAC2X_TX_DESC_TXD_ARRIVAL_TIME_MASK); + + /* HW_AMSDU_CAP [10] */ + DBGLOG(HAL, INFO, "\t\thw amsdu cap = %d\n", + (txd->u4DW7 & CONNAC2X_TX_DESC_HW_AMSDU) ? 1 : 0); + + /* SPE_IDX [15:11] */ + if (txd->u4DW2 & CONNAC2X_TX_DESC_FIXED_RATE) + DBGLOG(HAL, INFO, "\t\tspe_idx = 0x%x\n", + ((txd->u4DW7 & CONNAC2X_TX_DESC_SPE_EXT_IDX_MASK) >> + CONNAC2X_TX_DESC_SPE_EXT_IDX_OFFSET)); + + /* PSE_FID [27:16], Indicate frame ID in PSE for this TXD */ + DBGLOG(HAL, INFO, "\t\tpse_fid = 0x%x\n", + ((txd->u4DW7 & CONNAC2X_TX_DESC_PSE_FID_MASK) >> + CONNAC2X_TX_DESC_PSE_FID_OFFSET)); + + /* Subtype [19:16], HW reserved, PP use only */ + DBGLOG(HAL, INFO, "\t\tpp_sub_type=%d\n", + ((txd->u4DW7 & CONNAC2X_TX_DESC7_SUB_TYPE_MASK) >> + CONNAC2X_TX_DESC7_SUB_TYPE_OFFSET)); + + /* Type [21:20], HW reserved, PP use only */ + DBGLOG(HAL, INFO, "\t\tpp_type=%d\n", + ((txd->u4DW7 & CONNAC2X_TX_DESC7_TYPE_MASK) >> + CONNAC2X_TX_DESC7_TYPE_OFFSET)); + + /* CTXD_CNT [25:23], overwritten with PSE_FID by PP */ + DBGLOG(HAL, INFO, "\t\tctxd cnt=0x%x\n", + ((txd->u4DW7 & CONNAC2X_TX_DESC_CTXD_CNT_MASK) >> + CONNAC2X_TX_DESC_CTXD_CNT_OFFSET)); + + /* CTXD [26], overwritten with PSE_FID by PP */ + DBGLOG(HAL, INFO, "\t\tctxd = %d\n", + (txd->u4DW7 & CONNAC2X_TX_DESC_CTXD) ? 1 : 0); + + /* I [28] */ + DBGLOG(HAL, INFO, "\t\ti = %d\n", + (txd->u4DW7 & CONNAC2X_TX_DESC_IP_CHKSUM_OFFLOAD) ? 1 : 0); + + /* UT [29] */ + DBGLOG(HAL, INFO, "\t\tUT = %d\n", + (txd->u4DW7 & CONNAC2X_TX_DESC_TCP_UDP_CHKSUM_OFFLOAD) ? 1 : 0); + + /* TXDLEN [31:30] */ + DBGLOG(HAL, INFO, "\t\ttxd len= %d\n", + ((txd->u4DW7 & CONNAC2X_TX_DESC_TXD_LENGTH_MASK) >> + CONNAC2X_TX_DESC_TXD_LENGTH_OFFSET)); +} + +static void connac2x_event_dump_txd_mem( + struct ADAPTER *prAdapter, + struct CMD_INFO *prCmdInfo, + uint8_t *pucEventBuf) + +{ + struct EXT_CMD_EVENT_DUMP_MEM_T *prEventDumpMem; + uint8_t data[DUMP_MEM_SIZE]; + uint32_t i = 0; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + kalMemZero(data, sizeof(data)); + prEventDumpMem = (struct EXT_CMD_EVENT_DUMP_MEM_T *)(pucEventBuf); + kalMemCopy(data, prEventDumpMem->ucData, sizeof(data)); + for (i = 0; i < DUMP_MEM_SIZE; i = i + 4) + DBGLOG(HAL, INFO, "DW%02d: 0x%02x%02x%02x%02x\n", + i / 4, + data[i + 3], + data[i + 2], + data[i + 1], + data[i] + ); + connac2x_dump_tmac_info(prAdapter, &data[0]); +} + +void connac2x_show_txd_Info( + struct ADAPTER *prAdapter, + u_int32_t fid) +{ + struct EXT_CMD_EVENT_DUMP_MEM_T CmdMemDump; + u_int32_t Addr = 0; + u_int32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DBGLOG(HAL, INFO, "inShowTXDINFO fid=%d 0x%x\n", fid, fid); + + if (fid >= UMAC_FID_FAULT) + return; + + Addr = 0xa << 28 | fid << 16; /* TXD addr: 0x{a}{fid}{0000}*/ + + kalMemSet(&CmdMemDump, 0, sizeof(struct EXT_CMD_EVENT_DUMP_MEM_T)); + + CmdMemDump.u4MemAddr = Addr; + rWlanStatus = wlanSendSetQueryExtCmd( + prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, EXT_CMD_ID_DUMP_MEM, + FALSE, /* Query Bit: True->write False->read*/ + TRUE, + FALSE, + connac2x_event_dump_txd_mem, + nicOidCmdTimeoutCommon, + sizeof(struct EXT_CMD_EVENT_DUMP_MEM_T), + (u_int8_t *)(&CmdMemDump), + NULL, + 0); +} + +static u_int8_t connac2x_wtbl_get_sgi_info( + struct fwtbl_lmac_struct *pWtbl) +{ + if (!pWtbl) + return FALSE; + + switch (pWtbl->trx_cap.wtbl_d9.field.fcap) { + case BW_20: + return ((pWtbl->trx_cap.wtbl_d2.field.he) ? + (pWtbl->trx_cap.wtbl_d7.field.g2_he) : + (pWtbl->trx_cap.wtbl_d7.field.g2)); + case BW_40: + return ((pWtbl->trx_cap.wtbl_d2.field.he) ? + (pWtbl->trx_cap.wtbl_d7.field.g4_he) : + (pWtbl->trx_cap.wtbl_d7.field.g4)); + case BW_80: + return ((pWtbl->trx_cap.wtbl_d2.field.he) ? + (pWtbl->trx_cap.wtbl_d7.field.g8_he) : + (pWtbl->trx_cap.wtbl_d7.field.g8)); + case BW_160: + return ((pWtbl->trx_cap.wtbl_d2.field.he) ? + (pWtbl->trx_cap.wtbl_d7.field.g16_he) : + (pWtbl->trx_cap.wtbl_d7.field.g16)); + default: + return FALSE; + } +} + +static u_int8_t connac2x_wtbl_get_ldpc_info( + struct fwtbl_lmac_struct *pWtbl) +{ + if (!pWtbl) + return FALSE; + + if (pWtbl->trx_cap.wtbl_d2.field.he) + return pWtbl->trx_cap.wtbl_d4.field.ldpc_he; + else if (pWtbl->trx_cap.wtbl_d2.field.vht) + return pWtbl->trx_cap.wtbl_d4.field.ldpc_vht; + else + return pWtbl->trx_cap.wtbl_d4.field.ldpc_ht; +} + +static int32_t connac2x_wtbl_rate_to_string( + char *pcCommand, + int i4TotalLen, + uint8_t TxRx, + struct fwtbl_lmac_struct *pWtbl) +{ + uint8_t i, txmode, rate, stbc; + uint8_t nss, gi; + int32_t i4BytesWritten = 0; + uint16_t arTxRate[8]; + + arTxRate[0] = pWtbl->auto_rate_tb.wtbl_d10.field.rate1; + arTxRate[1] = pWtbl->auto_rate_tb.wtbl_d10.field.rate2; + arTxRate[2] = pWtbl->auto_rate_tb.wtbl_d11.field.rate3; + arTxRate[3] = pWtbl->auto_rate_tb.wtbl_d11.field.rate4; + arTxRate[4] = pWtbl->auto_rate_tb.wtbl_d12.field.rate5; + arTxRate[5] = pWtbl->auto_rate_tb.wtbl_d12.field.rate6; + arTxRate[6] = pWtbl->auto_rate_tb.wtbl_d13.field.rate7; + arTxRate[7] = pWtbl->auto_rate_tb.wtbl_d13.field.rate8; + for (i = 0; i < AUTO_RATE_NUM; i++) { + + txmode = CONNAC2X_HW_TX_RATE_TO_MODE(arTxRate[i]); + if (txmode >= ENUM_TX_MODE_NUM) + txmode = ENUM_TX_MODE_NUM - 1; + rate = HW_TX_RATE_TO_MCS(arTxRate[i]); + nss = CONNAC2X_HW_TX_RATE_TO_NSS(arTxRate[i]) + 1; + stbc = CONNAC2X_HW_TX_RATE_TO_STBC(arTxRate[i]); + gi = connac2x_wtbl_get_sgi_info(pWtbl); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRateIdx[%d] ", i); + + if (pWtbl->trx_cap.wtbl_d9.field.rate_idx == i) { + if (TxRx == 0) + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "[Last RX Rate] "); + else + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "[Last TX Rate] "); + } else + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", " "); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + rate < 4 ? HW_TX_RATE_CCK_STR[rate] : + HW_TX_RATE_CCK_STR[4]); + else if (txmode == TX_RATE_MODE_OFDM) + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + nicHwRateOfdmStr(rate)); + else if ((txmode == TX_RATE_MODE_HTMIX) || + (txmode == TX_RATE_MODE_HTGF)) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "MCS%d, ", rate); + else { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s%d_MCS%d, ", stbc ? "NSTS" : "NSS", + nss, rate); + } + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + (pWtbl->trx_cap.wtbl_d9.field.fcap < 4) ? + HW_TX_RATE_BW[pWtbl->trx_cap.wtbl_d9.field.fcap] : + HW_TX_RATE_BW[4]); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + rate < 4 ? "LP" : "SP"); + else if (txmode == TX_RATE_MODE_OFDM) + ; + else if (txmode >= TX_RATE_MODE_HTMIX + && txmode <= TX_RATE_MODE_PLR) + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + gi == 0 ? "LGI" : "SGI"); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", gi == 0 ? "SGI" : + (gi == 1 ? "MGI" : "LGI")); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s%s %s\n", + RATE_V2_HW_TX_MODE_STR[txmode], stbc ? "STBC" : " ", + connac2x_wtbl_get_ldpc_info(pWtbl) == 0 ? "BCC" : "LDPC"); + } + + return i4BytesWritten; +} + +static int32_t connac2x_dump_helper_wtbl_info( + struct ADAPTER *prAdapter, + char *pcCommand, + int i4TotalLen, + struct fwtbl_lmac_struct *pWtbl, + uint32_t u4Index) +{ + int32_t i4BytesWritten = 0; + uint8_t aucPA[MAC_ADDR_LEN]; + uint8_t u1BeamChgDw5 = 0, u1Dw3NewContent = 1; + uint8_t u1Dw5SR_R_Old = 0, u1Dw9NewContent = 1; + uint8_t u1Dw30Rssi = 1; + + if (!pcCommand) { + DBGLOG(HAL, ERROR, "%s: pcCommand is NULL.\n", + __func__); + return i4BytesWritten; + } + + if ((WTBL_VER == 1) && (wlanGetEcoVersion(prAdapter) < ECO_VER_2)) { + u1BeamChgDw5 = 1; + u1Dw3NewContent = 0; + u1Dw5SR_R_Old = 1; + u1Dw9NewContent = 0; + u1Dw30Rssi = 0; + } else if ((WTBL_VER == 2) && + (wlanGetEcoVersion(prAdapter) < ECO_VER_2)) { + u1Dw3NewContent = 0; + u1Dw30Rssi = 0; + } + + aucPA[0] = + pWtbl->peer_basic_info.wtbl_d1.field.addr_0 & 0xff; + aucPA[1] = + ((pWtbl->peer_basic_info.wtbl_d1.field.addr_0 & + 0xff00) >> 8); + aucPA[2] = + ((pWtbl->peer_basic_info.wtbl_d1.field.addr_0 & + 0xff0000) >> 16); + aucPA[3] = + ((pWtbl->peer_basic_info.wtbl_d1.field.addr_0 & + 0xff000000) >> 24); + aucPA[4] = + pWtbl->peer_basic_info.wtbl_d0.field.addr_4 & 0xff; + aucPA[5] = + pWtbl->peer_basic_info.wtbl_d0.field.addr_5 & 0xff; + + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, "%s", + "\n\nwtbl:\n"); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Dump WTBL info of WLAN_IDX = %d\n", + u4Index); + /* DW0~DW1 */ + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tADDR="MACSTR"\n", + MAC2STR(aucPA)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tKID/RCID/RV/WPI:%d/%d/%d/%d\n", + pWtbl->peer_basic_info.wtbl_d0.field.muar_idx, + pWtbl->peer_basic_info.wtbl_d0.field.fd, + pWtbl->peer_basic_info.wtbl_d0.field.td, + pWtbl->peer_basic_info.wtbl_d0.field.rc_a1, + pWtbl->peer_basic_info.wtbl_d0.field.rc_a2); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tKID:%d/RCID:%d/RKV:NA/RV:%d/IKV:NA/WPI_FLAG:%d\n", + pWtbl->peer_basic_info.wtbl_d0.field.kid, + pWtbl->peer_basic_info.wtbl_d0.field.rc_id, + pWtbl->peer_basic_info.wtbl_d0.field.rv, + pWtbl->peer_basic_info.wtbl_d0.field.wpi_flg); + /* DW2 */ + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tAID12/GID_SU/SPP_EN/WPI_EVEN/AAD_OM:%d/%d/%d/%d/%d\n", + pWtbl->trx_cap.wtbl_d2.field.aid12, + pWtbl->trx_cap.wtbl_d2.field.gid_su, + pWtbl->trx_cap.wtbl_d2.field.spp_en, + pWtbl->trx_cap.wtbl_d2.field.wpi_even, + pWtbl->trx_cap.wtbl_d2.field.aad_om); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tCipher/IGTK:%d/%d\n", + pWtbl->trx_cap.wtbl_d2.field.cipher_suit, + pWtbl->trx_cap.wtbl_d2.field.cipher_suit_igtk); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tSW/UL/TXPS/QoS/MESH:%d/%d/%d/%d/%d\n", + pWtbl->trx_cap.wtbl_d2.field.sw, + pWtbl->trx_cap.wtbl_d2.field.ul, + pWtbl->trx_cap.wtbl_d2.field.tx_ps, + pWtbl->trx_cap.wtbl_d2.field.qos, + pWtbl->trx_cap.wtbl_d2.field.mesh); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tHT/VHT/HE/LDPC[HT/VHT/HE]:%d/%d/%d/%d/%d/%d\n", + pWtbl->trx_cap.wtbl_d2.field.ht, + pWtbl->trx_cap.wtbl_d2.field.vht, + pWtbl->trx_cap.wtbl_d2.field.he, + pWtbl->trx_cap.wtbl_d4.field.ldpc_ht, + pWtbl->trx_cap.wtbl_d4.field.ldpc_vht, + pWtbl->trx_cap.wtbl_d4.field.ldpc_he); + /* DW3 */ + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tWMMQ/RXD_DUP_M/VLAN2ETH/BEAM_CHG:%d/%d/%d/%d\n", + pWtbl->trx_cap.wtbl_d3.field.wmm_q, + pWtbl->trx_cap.wtbl_d3.field.rxd_dup_mode, + pWtbl->trx_cap.wtbl_d3.field.vlan_2e_th, + (u1BeamChgDw5 > 0) ? (pWtbl->trx_cap.wtbl_d5.field.beam_chg) : + (pWtbl->trx_cap.wtbl_d3.field_v2.beam_chg)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tPFMU_IDX/RIBF/TBF[HT/VHT/HE]:%d/%d/%d/%d/%d\n", + pWtbl->trx_cap.wtbl_d3.field.pfmu_index, + pWtbl->trx_cap.wtbl_d3.field.ribf, + pWtbl->trx_cap.wtbl_d3.field.tebf, + pWtbl->trx_cap.wtbl_d3.field.tebf_vht, + pWtbl->trx_cap.wtbl_d3.field.tebf_he); + + if (u1Dw3NewContent > 0) + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tBA_M/ULPF_IDX/ULPF/IGN_FBK:%d/%d/%d/%d\n", + pWtbl->trx_cap.wtbl_d3.field_v2.ba_mode, + pWtbl->trx_cap.wtbl_d3.field_v2.ulpf_index, + pWtbl->trx_cap.wtbl_d3.field_v2.ulpf, + pWtbl->trx_cap.wtbl_d3.field_v2.ign_fbk); + /* DW4 */ + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tANT_ID0/1/2/3/4/5/6/7:%d/%d/%d/%d/%d/%d/%d/%d\n", + pWtbl->trx_cap.wtbl_d4.field.ant_id_sts0, + pWtbl->trx_cap.wtbl_d4.field.ant_id_sts1, + pWtbl->trx_cap.wtbl_d4.field.ant_id_sts2, + pWtbl->trx_cap.wtbl_d4.field.ant_id_sts3, + pWtbl->trx_cap.wtbl_d4.field.ant_id_sts4, + pWtbl->trx_cap.wtbl_d4.field.ant_id_sts5, + pWtbl->trx_cap.wtbl_d4.field.ant_id_sts6, + pWtbl->trx_cap.wtbl_d4.field.ant_id_sts7); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tCASCAD/DIS_RHTR/ALL_ACK/DROP/ACK_EN:%d/%d/%d/%d/%d\n", + pWtbl->trx_cap.wtbl_d4.field.cascad, + pWtbl->trx_cap.wtbl_d4.field.dis_rhtr, + pWtbl->trx_cap.wtbl_d4.field.all_ack, + pWtbl->trx_cap.wtbl_d4.field.drop, + pWtbl->trx_cap.wtbl_d4.field.ack_en); + /* DW5 */ + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tAF/AFHE/RTS/SMPS/DYNBW/MMSS:%d/%d/%d/%d/%d/%d\n", + pWtbl->trx_cap.wtbl_d5.field.af, + pWtbl->trx_cap.wtbl_d5.field.af_he, + pWtbl->trx_cap.wtbl_d5.field.rts, + pWtbl->trx_cap.wtbl_d5.field.smps, + pWtbl->trx_cap.wtbl_d5.field.dyn_bw, + pWtbl->trx_cap.wtbl_d5.field.mmss); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tUSR/SR_R/SR_A/MPDU_SZ/PE:%d/%d/%d/%d/%d\n", + pWtbl->trx_cap.wtbl_d5.field.usr, + (u1Dw5SR_R_Old > 0) ? (pWtbl->trx_cap.wtbl_d5.field.sr_r) : + (pWtbl->trx_cap.wtbl_d5.field_v2.sr_r), + pWtbl->trx_cap.wtbl_d5.field.sr_abort, + pWtbl->trx_cap.wtbl_d5.field.mpdu_size, + pWtbl->trx_cap.wtbl_d5.field.pe); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tTXPWR_OFST/DOPPL/TXOP_PS_CAP:%d/%d/%d\n", + pWtbl->trx_cap.wtbl_d5.field.tx_power_offset, + pWtbl->trx_cap.wtbl_d5.field.doppl, + pWtbl->trx_cap.wtbl_d5.field.txop_ps_cap); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tDU_I_PSM/I_PSM/PSM/SKIP_TX:%d/%d/%d/%d\n", + pWtbl->trx_cap.wtbl_d5.field.du_i_psm, + pWtbl->trx_cap.wtbl_d5.field.i_psm, + pWtbl->trx_cap.wtbl_d5.field.psm, + pWtbl->trx_cap.wtbl_d5.field.skip_tx); + /* DW6 */ + if (pWtbl->trx_cap.wtbl_d2.field.qos) + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tBaWinSize TID0/1/2/3/4/5/6/7:%d/%d/%d/%d/%d/%d/%d/%d\n", + (uint32_t) + (pWtbl->trx_cap.wtbl_d6.field.ba_win_size_tid0), + (uint32_t) + (pWtbl->trx_cap.wtbl_d6.field.ba_win_size_tid1), + (uint32_t) + (pWtbl->trx_cap.wtbl_d6.field.ba_win_size_tid2), + (uint32_t) + (pWtbl->trx_cap.wtbl_d6.field.ba_win_size_tid3), + (uint32_t) + (pWtbl->trx_cap.wtbl_d6.field.ba_win_size_tid4), + (uint32_t) + (pWtbl->trx_cap.wtbl_d6.field.ba_win_size_tid5), + (uint32_t) + (pWtbl->trx_cap.wtbl_d6.field.ba_win_size_tid6), + (uint32_t) + (pWtbl->trx_cap.wtbl_d6.field.ba_win_size_tid7)); + /* DW7 */ + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tCBRN/DBNSS_EN/BAFEN/RDGBA/R:%d/%d/%d/%d/%d\n", + pWtbl->trx_cap.wtbl_d7.field.cb_rn, + pWtbl->trx_cap.wtbl_d7.field.dbnss_en, + pWtbl->trx_cap.wtbl_d7.field.bafen, + pWtbl->trx_cap.wtbl_d7.field.rdg_ba, + pWtbl->trx_cap.wtbl_d7.field.r); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tG2/G4/G8/G16/SPE:%d/%d/%d/%d/%d\n", + pWtbl->trx_cap.wtbl_d7.field.g2, + pWtbl->trx_cap.wtbl_d7.field.g4, + pWtbl->trx_cap.wtbl_d7.field.g8, + pWtbl->trx_cap.wtbl_d7.field.g16, + pWtbl->trx_cap.wtbl_d7.field.spe_idx); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tHE[G2/G4/G8/G16]:%d/%d/%d/%d\n", + pWtbl->trx_cap.wtbl_d7.field.g2_he, + pWtbl->trx_cap.wtbl_d7.field.g4_he, + pWtbl->trx_cap.wtbl_d7.field.g8_he, + pWtbl->trx_cap.wtbl_d7.field.g16_he); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tLTF[G2/G4/G8/G16]:%d/%d/%d/%d\n", + pWtbl->trx_cap.wtbl_d7.field.g2_ltf, + pWtbl->trx_cap.wtbl_d7.field.g4_ltf, + pWtbl->trx_cap.wtbl_d7.field.g8_ltf, + pWtbl->trx_cap.wtbl_d7.field.g16_ltf); + /* DW8 */ + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tCHK_PER/P_AID:%d/%d\n", + pWtbl->trx_cap.wtbl_d8.field.chk_per, + pWtbl->trx_cap.wtbl_d8.field.partial_aid); + /* DW9 */ + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tFCAP/PRITX[DCM/ER160/ERSU]:%d/%d/%d/%d\n", + pWtbl->trx_cap.wtbl_d9.field.fcap, + pWtbl->trx_cap.wtbl_d9.field.pritx_dcm, + pWtbl->trx_cap.wtbl_d9.field.pritx_er160, + pWtbl->trx_cap.wtbl_d9.field.pritx_ersu); + + if (u1Dw9NewContent > 0) + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tPRITX[SW_M/PLR]:%d/%d\n", + pWtbl->trx_cap.wtbl_d9.field_v2.pritx_sw_mode, + pWtbl->trx_cap.wtbl_d9.field_v2.pritx_plr); + + if (u1Dw30Rssi > 0) + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRSSI = %d %d %d %d\n", + RCPI_TO_dBm(pWtbl->rx_stat.wtbl_d30.field_v2.resp_rcpi_0), + RCPI_TO_dBm(pWtbl->rx_stat.wtbl_d30.field_v2.resp_rcpi_1), + RCPI_TO_dBm(pWtbl->rx_stat.wtbl_d30.field_v2.resp_rcpi_2), + RCPI_TO_dBm(pWtbl->rx_stat.wtbl_d30.field_v2.resp_rcpi_3)); + else + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRSSI = %d %d %d %d\n", + RCPI_TO_dBm(pWtbl->rx_stat.wtbl_d29.field.resp_rcpi_0), + RCPI_TO_dBm(pWtbl->rx_stat.wtbl_d29.field.resp_rcpi_1), + RCPI_TO_dBm(pWtbl->rx_stat.wtbl_d29.field.resp_rcpi_2), + RCPI_TO_dBm(pWtbl->rx_stat.wtbl_d29.field.resp_rcpi_3)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s", "\tRate Info\n"); + + i4BytesWritten += connac2x_wtbl_rate_to_string( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, 1, pWtbl); + + return i4BytesWritten; +} + +static void connac2x_print_wtbl_info( + struct ADAPTER *prAdapter, + int32_t idx) +{ + struct mt66xx_chip_info *prChipInfo; + int32_t start_idx, end_idx; + uint32_t wtbl_offset, addr; + uint32_t u4Value = 0; + uint32_t wtbl_lmac_baseaddr; + unsigned char *wtbl_raw_dw = NULL; + struct fwtbl_lmac_struct *pwtbl; + unsigned char myaddr[6]; + uint16_t txrate[8], rate_idx, txmode, mcs, nss, stbc; + uint8_t u1BeamChgDw5 = 0, u1Dw3NewContent = 1; + uint8_t u1WtblSize = 0; + + prChipInfo = prAdapter->chip_info; + if ((idx >= 0) && (idx < prAdapter->ucWtblEntryNum)) + start_idx = end_idx = idx; + else { + start_idx = 0; + end_idx = prAdapter->ucWtblEntryNum - 1; + } + + if ((WTBL_VER == 1) && (wlanGetEcoVersion(prAdapter) < ECO_VER_2)) { + u1WtblSize = sizeof(struct fwtbl_lmac_struct); + u1BeamChgDw5 = 1; + u1Dw3NewContent = 0; + } else if ((WTBL_VER == 2) && + (wlanGetEcoVersion(prAdapter) < ECO_VER_2)) { + u1WtblSize = sizeof(struct fwtbl_lmac_struct); + u1Dw3NewContent = 0; + } else { + u1WtblSize = + sizeof(struct fwtbl_lmac_struct) - sizeof(uint32_t); + } + + for (idx = start_idx; idx <= end_idx; idx++) { + /* LMAC */ + CONNAC2X_LWTBL_CONFIG(prAdapter, + prChipInfo->u4LmacWtblDUAddr, idx); + wtbl_lmac_baseaddr = CONNAC2X_LWTBL_IDX2BASE( + prChipInfo->u4LmacWtblDUAddr, idx, 0); + HAL_MCR_RD(prAdapter, prChipInfo->u4LmacWtblDUAddr, + &u4Value); + + LOG_FUNC("\n\tLMAC WTBL Addr: group: 0x%x=0x%x addr: 0x%x\n", + prChipInfo->u4LmacWtblDUAddr, + u4Value, + wtbl_lmac_baseaddr); + + wtbl_raw_dw = (unsigned char *)kalMemAlloc( + sizeof(struct fwtbl_lmac_struct), VIR_MEM_TYPE); + if (!wtbl_raw_dw) { + DBGLOG(REQ, ERROR, "WTBL PRN : Memory alloc failed\n"); + return; + } + /* Read LWTBL Entries */ + for (wtbl_offset = 0; wtbl_offset < + sizeof(struct fwtbl_lmac_struct); + wtbl_offset += 4) { + addr = wtbl_lmac_baseaddr + wtbl_offset; + HAL_MCR_RD(prAdapter, addr, + &u4Value); + kalMemCopy( + (uint32_t *)&wtbl_raw_dw[wtbl_offset], + &u4Value, sizeof(uint32_t)); + } + pwtbl = (struct fwtbl_lmac_struct *)wtbl_raw_dw; + kalMemMove(&myaddr[0], + (unsigned char *)&pwtbl->peer_basic_info, 4); + myaddr[0] = + pwtbl->peer_basic_info.wtbl_d1.field.addr_0 & + 0xff; + myaddr[1] = + ((pwtbl->peer_basic_info.wtbl_d1.field.addr_0 & + 0xff00) >> + 8); + myaddr[2] = + ((pwtbl->peer_basic_info.wtbl_d1.field.addr_0 & + 0xff0000) >> + 16); + myaddr[3] = + ((pwtbl->peer_basic_info.wtbl_d1.field.addr_0 & + 0xff000000) >> + 24); + myaddr[4] = + pwtbl->peer_basic_info.wtbl_d0.field.addr_4 & + 0xff; + myaddr[5] = + pwtbl->peer_basic_info.wtbl_d0.field.addr_5 & + 0xff; + LOG_FUNC( + "\n\tLWTBL DW 0,1:\n" + "\tAddr: %x:%x:%x:%x:%x:%x(D0[B0~15], D1[B0~31])\n" + "\tMUAR_Idx(D0[B16~21]):%d\n" + "\tRCA1:%d\n" + "\tKID:%d\n" + "\tRCID:%d\n" + "\tFROM_DS:%d\n" + "\tTO_DS:%d\n" + "\tRV:%d\n" + "\tRCA2:%d\n" + "\tWPI_FLAG:%d\n", + myaddr[0], myaddr[1], myaddr[2], myaddr[3], + myaddr[4], myaddr[5], + pwtbl->peer_basic_info.wtbl_d0.field.muar_idx, + pwtbl->peer_basic_info.wtbl_d0.field.rc_a1, + pwtbl->peer_basic_info.wtbl_d0.field.kid, + pwtbl->peer_basic_info.wtbl_d0.field.rc_id, + pwtbl->peer_basic_info.wtbl_d0.field.fd, + pwtbl->peer_basic_info.wtbl_d0.field.td, + pwtbl->peer_basic_info.wtbl_d0.field.rv, + pwtbl->peer_basic_info.wtbl_d0.field.rc_a2, + pwtbl->peer_basic_info.wtbl_d0.field.wpi_flg); + + LOG_FUNC( + "\n\tLWTBL DW 2\n" + "\tAID12:%d\n" + "\tGID_SU:%d\n" + "\tSPP_EN:%d\n" + "\tWPI_EVEN:%d\n" + "\tAAD_OM:%d\n" + "\tCIPHER_SUITE:%d\n" + "\tCIPHER_SUITE_IGTK:%d\n" + "\tRSVD:%d\n" + "\tSW:%d\n" + "\tUL:%d\n" + "\tPOWER_SAVE:%d\n" + "\tQOS:%d\n" + "\tHT:%d\n" + "\tVHT:%d\n" + "\tHE:%d\n" + "\tMESH:%d\n", + pwtbl->trx_cap.wtbl_d2.field.aid12, + pwtbl->trx_cap.wtbl_d2.field.gid_su, + pwtbl->trx_cap.wtbl_d2.field.spp_en, + pwtbl->trx_cap.wtbl_d2.field.wpi_even, + pwtbl->trx_cap.wtbl_d2.field.aad_om, + pwtbl->trx_cap.wtbl_d2.field.cipher_suit, + pwtbl->trx_cap.wtbl_d2.field.cipher_suit_igtk, + pwtbl->trx_cap.wtbl_d2.field.rsvd, + pwtbl->trx_cap.wtbl_d2.field.sw, + pwtbl->trx_cap.wtbl_d2.field.ul, + pwtbl->trx_cap.wtbl_d2.field.tx_ps, + pwtbl->trx_cap.wtbl_d2.field.qos, + pwtbl->trx_cap.wtbl_d2.field.ht, + pwtbl->trx_cap.wtbl_d2.field.vht, + pwtbl->trx_cap.wtbl_d2.field.he, + pwtbl->trx_cap.wtbl_d2.field.mesh); + + if (u1Dw3NewContent > 0) + LOG_FUNC( + "\n\tLWTBL DW 3\n" + "\tWMM_Q:%d\n" + "\tRXD_DUP_MODE:%d\n" + "\tVLAN2ETH:%d\n" + "\tBEAM_CHG:%d\n" + "\tBA_MODE:%d\n" + "\tPFMU_IDX:%d\n" + "\tULPF_IDX:%d\n" + "\tRIBF:%d\n" + "\tULPF:%d\n" + "\tIGN_FBK:%d\n" + "\tTEBF:%d\n" + "\tTEBF_VHT:%d\n" + "\tTEBF_HE:%d\n", + pwtbl->trx_cap.wtbl_d3.field.wmm_q, + pwtbl->trx_cap.wtbl_d3.field.rxd_dup_mode, + pwtbl->trx_cap.wtbl_d3.field.vlan_2e_th, + pwtbl->trx_cap.wtbl_d3.field_v2.beam_chg, + pwtbl->trx_cap.wtbl_d3.field_v2.ba_mode, + pwtbl->trx_cap.wtbl_d3.field.pfmu_index, + pwtbl->trx_cap.wtbl_d3.field_v2.ulpf_index, + pwtbl->trx_cap.wtbl_d3.field.ribf, + pwtbl->trx_cap.wtbl_d3.field_v2.ulpf, + pwtbl->trx_cap.wtbl_d3.field_v2.ign_fbk, + pwtbl->trx_cap.wtbl_d3.field.tebf, + pwtbl->trx_cap.wtbl_d3.field.tebf_vht, + pwtbl->trx_cap.wtbl_d3.field.tebf_he); + else { + if (u1BeamChgDw5 > 0) + LOG_FUNC( + "\n\tLWTBL DW 3\n" + "\tWMM_Q:%d\n" + "\tRXD_DUP_MODE:%d\n" + "\tVLAN2ETH:%d\n" + "\tPFMU_IDX:%d\n" + "\tRIBF:%d\n" + "\tTEBF:%d\n" + "\tTEBF_VHT:%d\n" + "\tTEBF_HE:%d\n", + pwtbl->trx_cap.wtbl_d3.field.wmm_q, + pwtbl->trx_cap.wtbl_d3.field.rxd_dup_mode, + pwtbl->trx_cap.wtbl_d3.field.vlan_2e_th, + pwtbl->trx_cap.wtbl_d3.field.pfmu_index, + pwtbl->trx_cap.wtbl_d3.field.ribf, + pwtbl->trx_cap.wtbl_d3.field.tebf, + pwtbl->trx_cap.wtbl_d3.field.tebf_vht, + pwtbl->trx_cap.wtbl_d3.field.tebf_he); + else + LOG_FUNC( + "\n\tLWTBL DW 3\n" + "\tWMM_Q:%d\n" + "\tRXD_DUP_MODE:%d\n" + "\tVLAN2ETH:%d\n" + "\tBEAM_CHG:%d\n" + "\tPFMU_IDX:%d\n" + "\tRIBF:%d\n" + "\tTEBF:%d\n" + "\tTEBF_VHT:%d\n" + "\tTEBF_HE:%d\n", + pwtbl->trx_cap.wtbl_d3.field.wmm_q, + pwtbl->trx_cap.wtbl_d3.field.rxd_dup_mode, + pwtbl->trx_cap.wtbl_d3.field.vlan_2e_th, + pwtbl->trx_cap.wtbl_d3.field_v2.beam_chg, + pwtbl->trx_cap.wtbl_d3.field.pfmu_index, + pwtbl->trx_cap.wtbl_d3.field.ribf, + pwtbl->trx_cap.wtbl_d3.field.tebf, + pwtbl->trx_cap.wtbl_d3.field.tebf_vht, + pwtbl->trx_cap.wtbl_d3.field.tebf_he); + } + + LOG_FUNC( + "\n\tLWTBL DW 4\n" + "\tANT_ID_STS0:%d\n" + "\tANT_ID_STS1:%d\n" + "\tANT_ID_STS2:%d\n" + "\tANT_ID_STS3:%d\n" + "\tANT_ID_STS4:%d\n" + "\tANT_ID_STS5:%d\n" + "\tANT_ID_STS6:%d\n" + "\tANT_ID_STS7:%d\n" + "\tCASCAD:%d\n" + "\tLDPC_HT:%d\n" + "\tLDPC_VHT:%d\n" + "\tLDPC_HE:%d\n" + "\tDIS_RTHR:%d\n" + "\tALL_ACK:%d\n" + "\tDROP:%d\n" + "\tACK_EN:%d\n", + pwtbl->trx_cap.wtbl_d4.field.ant_id_sts0, + pwtbl->trx_cap.wtbl_d4.field.ant_id_sts1, + pwtbl->trx_cap.wtbl_d4.field.ant_id_sts2, + pwtbl->trx_cap.wtbl_d4.field.ant_id_sts3, + pwtbl->trx_cap.wtbl_d4.field.ant_id_sts4, + pwtbl->trx_cap.wtbl_d4.field.ant_id_sts5, + pwtbl->trx_cap.wtbl_d4.field.ant_id_sts6, + pwtbl->trx_cap.wtbl_d4.field.ant_id_sts7, + pwtbl->trx_cap.wtbl_d4.field.cascad, + pwtbl->trx_cap.wtbl_d4.field.ldpc_ht, + pwtbl->trx_cap.wtbl_d4.field.ldpc_vht, + pwtbl->trx_cap.wtbl_d4.field.ldpc_he, + pwtbl->trx_cap.wtbl_d4.field.dis_rhtr, + pwtbl->trx_cap.wtbl_d4.field.all_ack, + pwtbl->trx_cap.wtbl_d4.field.drop, + pwtbl->trx_cap.wtbl_d4.field.ack_en); + + if (u1BeamChgDw5 > 0) + LOG_FUNC( + "\n\tLWTBL DW 5\n" + "\tAF:%d\n" + "\tAF_HE:%d\n" + "\tRTS:%d\n" + "\tSMPS:%d\n" + "\tDYN_BW:%d\n" + "\tMMSS:%d\n" + "\tUSR:%d\n" + "\tSR_R:%d\n" + "\tBEAM_CHG:%d\n" + "\tSR_ABORT:%d\n" + "\tTX_POWER_OFFSET:%d\n" + "\tMPDU_SIZE:%d\n" + "\tPE:%d\n" + "\tDOPPL:%d\n" + "\tTXOP_PS_CAP:%d\n" + "\tDONOT_UPDATE_I_PSM:%d\n" + "\tI_PSM:%d\n" + "\tPSM:%d\n" + "\tSKIP_TX:%d\n", + pwtbl->trx_cap.wtbl_d5.field.af, + pwtbl->trx_cap.wtbl_d5.field.af_he, + pwtbl->trx_cap.wtbl_d5.field.rts, + pwtbl->trx_cap.wtbl_d5.field.smps, + pwtbl->trx_cap.wtbl_d5.field.dyn_bw, + pwtbl->trx_cap.wtbl_d5.field.mmss, + pwtbl->trx_cap.wtbl_d5.field.usr, + pwtbl->trx_cap.wtbl_d5.field.sr_r, + pwtbl->trx_cap.wtbl_d5.field.beam_chg, + pwtbl->trx_cap.wtbl_d5.field.sr_abort, + pwtbl->trx_cap.wtbl_d5.field.tx_power_offset, + pwtbl->trx_cap.wtbl_d5.field.mpdu_size, + pwtbl->trx_cap.wtbl_d5.field.pe, + pwtbl->trx_cap.wtbl_d5.field.doppl, + pwtbl->trx_cap.wtbl_d5.field.txop_ps_cap, + pwtbl->trx_cap.wtbl_d5.field.du_i_psm, + pwtbl->trx_cap.wtbl_d5.field.i_psm, + pwtbl->trx_cap.wtbl_d5.field.psm, + pwtbl->trx_cap.wtbl_d5.field.skip_tx); + else + LOG_FUNC( + "\n\tLWTBL DW 5\n" + "\tAF:%d\n" + "\tAF_HE:%d\n" + "\tRTS:%d\n" + "\tSMPS:%d\n" + "\tDYN_BW:%d\n" + "\tMMSS:%d\n" + "\tUSR:%d\n" + "\tSR_R:%d\n" + "\tSR_ABORT:%d\n" + "\tTX_POWER_OFFSET:%d\n" + "\tMPDU_SIZE:%d\n" + "\tPE:%d\n" + "\tDOPPL:%d\n" + "\tTXOP_PS_CAP:%d\n" + "\tDONOT_UPDATE_I_PSM:%d\n" + "\tI_PSM:%d\n" + "\tPSM:%d\n" + "\tSKIP_TX:%d\n", + pwtbl->trx_cap.wtbl_d5.field.af, + pwtbl->trx_cap.wtbl_d5.field.af_he, + pwtbl->trx_cap.wtbl_d5.field.rts, + pwtbl->trx_cap.wtbl_d5.field.smps, + pwtbl->trx_cap.wtbl_d5.field.dyn_bw, + pwtbl->trx_cap.wtbl_d5.field.mmss, + pwtbl->trx_cap.wtbl_d5.field.usr, + pwtbl->trx_cap.wtbl_d5.field_v2.sr_r, + pwtbl->trx_cap.wtbl_d5.field.sr_abort, + pwtbl->trx_cap.wtbl_d5.field.tx_power_offset, + pwtbl->trx_cap.wtbl_d5.field.mpdu_size, + pwtbl->trx_cap.wtbl_d5.field.pe, + pwtbl->trx_cap.wtbl_d5.field.doppl, + pwtbl->trx_cap.wtbl_d5.field.txop_ps_cap, + pwtbl->trx_cap.wtbl_d5.field.du_i_psm, + pwtbl->trx_cap.wtbl_d5.field.i_psm, + pwtbl->trx_cap.wtbl_d5.field.psm, + pwtbl->trx_cap.wtbl_d5.field.skip_tx); + + LOG_FUNC( + "\n\tLWTBL DW 6\n" + "\tTID0 BA_WIN_SIZE:%d\n" + "\tTID1 BA_WIN_SIZE:%d\n" + "\tTID2 BA_WIN_SIZE:%d\n" + "\tTID3 BA_WIN_SIZE:%d\n" + "\tTID4 BA_WIN_SIZE:%d\n" + "\tTID5 BA_WIN_SIZE:%d\n" + "\tTID6 BA_WIN_SIZE:%d\n" + "\tTID7 BA_WIN_SIZE:%d\n", + pwtbl->trx_cap.wtbl_d6.field.ba_win_size_tid0, + pwtbl->trx_cap.wtbl_d6.field.ba_win_size_tid1, + pwtbl->trx_cap.wtbl_d6.field.ba_win_size_tid2, + pwtbl->trx_cap.wtbl_d6.field.ba_win_size_tid3, + pwtbl->trx_cap.wtbl_d6.field.ba_win_size_tid4, + pwtbl->trx_cap.wtbl_d6.field.ba_win_size_tid5, + pwtbl->trx_cap.wtbl_d6.field.ba_win_size_tid6, + pwtbl->trx_cap.wtbl_d6.field.ba_win_size_tid7); + + + LOG_FUNC( + "\n\tLWTBL DW 7\n" + "\tCBRN:%d\n" + "\tDBNSS_EN:%d\n" + "\tBAF_EN:%d\n" + "\tRDGBA:%d\n" + "\tR:%d\n" + "\tSPE_IDX:%d\n" + "\tG2:%d\n" + "\tG4:%d\n" + "\tG8:%d\n" + "\tG16:%d\n" + "\tG2_LTF:%d\n" + "\tG4_LTF:%d\n" + "\tG8_LTF:%d\n" + "\tG16_LTF:%d\n" + "\tG2_HE:%d\n" + "\tG4_HE:%d\n" + "\tG8_HE:%d\n" + "\tG16_HE:%d\n", + pwtbl->trx_cap.wtbl_d7.field.cb_rn, + pwtbl->trx_cap.wtbl_d7.field.dbnss_en, + pwtbl->trx_cap.wtbl_d7.field.bafen, + pwtbl->trx_cap.wtbl_d7.field.rdg_ba, + pwtbl->trx_cap.wtbl_d7.field.r, + pwtbl->trx_cap.wtbl_d7.field.spe_idx, + pwtbl->trx_cap.wtbl_d7.field.g2, + pwtbl->trx_cap.wtbl_d7.field.g4, + pwtbl->trx_cap.wtbl_d7.field.g8, + pwtbl->trx_cap.wtbl_d7.field.g16, + pwtbl->trx_cap.wtbl_d7.field.g2_ltf, + pwtbl->trx_cap.wtbl_d7.field.g4_ltf, + pwtbl->trx_cap.wtbl_d7.field.g8_ltf, + pwtbl->trx_cap.wtbl_d7.field.g16_ltf, + pwtbl->trx_cap.wtbl_d7.field.g2_he, + pwtbl->trx_cap.wtbl_d7.field.g4_he, + pwtbl->trx_cap.wtbl_d7.field.g8_he, + pwtbl->trx_cap.wtbl_d7.field.g16_he); + + LOG_FUNC( + "\n\tLWTBL DW 9\n" + "\tFCAP:0x%x\n" + "\tFCAP_20_40_MHZ:%d\n" + "\tFCAP_20_TO_160_MHZ:%d\n" + "\tFCAP_20_TO_80_MHZ:%d\n", + pwtbl->trx_cap.wtbl_d9.field.fcap, + ((pwtbl->trx_cap.wtbl_d9.field.fcap) & + (BIT(0))), + pwtbl->trx_cap.wtbl_d9.field.fcap, + (((pwtbl->trx_cap.wtbl_d9.field.fcap) & + (BIT(1))) >> 1)); + + /* Rate Info (DW10~13) */ + LOG_FUNC("Rate Info (DW10~13):"); + txrate[0] = pwtbl->auto_rate_tb.wtbl_d10.field.rate1; + txrate[1] = pwtbl->auto_rate_tb.wtbl_d10.field.rate2; + txrate[2] = pwtbl->auto_rate_tb.wtbl_d11.field.rate3; + txrate[3] = pwtbl->auto_rate_tb.wtbl_d11.field.rate4; + txrate[4] = pwtbl->auto_rate_tb.wtbl_d12.field.rate5; + txrate[5] = pwtbl->auto_rate_tb.wtbl_d12.field.rate6; + txrate[6] = pwtbl->auto_rate_tb.wtbl_d13.field.rate7; + txrate[7] = pwtbl->auto_rate_tb.wtbl_d13.field.rate8; + + for (rate_idx = 0; rate_idx < 8; rate_idx++) { + txmode = (((txrate[rate_idx]) & + (0xf << 6)) >> 6); + mcs = ((txrate[rate_idx]) & + (0x3f)); + nss = (((txrate[rate_idx]) & + (0x7 << 10)) >> 10) + 1; + stbc = (((txrate[rate_idx]) & + (0x1 << 13)) >> 13); + + if (!(rate_idx%2)) + LOG_FUNC("LWTBL DW %d\n", + (rate_idx/2)+10); + + if (txmode == TX_RATE_MODE_CCK) + LOG_FUNC( + "\tRate%d(0x%x):TxMode=%d(%s) TxRate=%d(%s) Nsts=%d STBC=%d\n", + rate_idx + 1, + txrate[rate_idx], + txmode, + (txmode < ENUM_TX_MODE_NUM ? + RATE_V2_HW_TX_MODE_STR[txmode] : "N/A"), + mcs, + mcs < 4 ? HW_TX_RATE_CCK_STR[mcs] : + HW_TX_RATE_CCK_STR[4], + nss, stbc); + else if (txmode == TX_RATE_MODE_OFDM) + LOG_FUNC( + "\tRate%d(0x%x):TxMode=%d(%s) TxRate=%d(%s) Nsts=%d STBC=%d\n", + rate_idx + 1, + txrate[rate_idx], + txmode, + (txmode < ENUM_TX_MODE_NUM ? + RATE_V2_HW_TX_MODE_STR[txmode] : "N/A"), + mcs, + nicHwRateOfdmStr(mcs), + nss, stbc); + else + LOG_FUNC( + "\tRate%d(0x%x):TxMode=%d(%s) TxRate=%d(MCS%d) Nsts=%d STBC=%d\n", + rate_idx + 1, + txrate[rate_idx], + txmode, + (txmode < ENUM_TX_MODE_NUM ? + RATE_V2_HW_TX_MODE_STR[txmode] : "N/A"), + mcs, + mcs, + nss, stbc); + } + LOG_FUNC("\n"); + + /* Show LWTBL RAW Data */ + for (wtbl_offset = 0; wtbl_offset < u1WtblSize; + wtbl_offset += 4) { + kalMemCopy(&u4Value, + (uint32_t *)&wtbl_raw_dw[wtbl_offset], + sizeof(uint32_t)); + LOG_FUNC( + "\tDW%02d: %02x %02x %02x %02x\n", + wtbl_offset / 4, + (u4Value & 0xff000000) >> 24, + (u4Value & 0xff0000) >> 16, + (u4Value & 0xff00) >> 8, + u4Value & 0xff); + } + LOG_FUNC("\n"); + kalMemFree(wtbl_raw_dw, VIR_MEM_TYPE, + sizeof(struct fwtbl_lmac_struct)); + } +} + +int32_t connac2x_show_wtbl_info( + struct ADAPTER *prAdapter, + uint32_t u4Index, + char *pcCommand, + int i4TotalLen) +{ + struct mt66xx_chip_info *prChipInfo; + uint32_t u4Value = 0; + uint32_t wtbl_lmac_baseaddr; + uint32_t wtbl_offset, addr; + unsigned char *wtbl_raw_dw = NULL; + struct fwtbl_lmac_struct *pwtbl; + int32_t i4BytesWritten = 0; + + prChipInfo = prAdapter->chip_info; + DBGLOG(REQ, INFO, "WTBL : index = %d\n", u4Index); + + wtbl_raw_dw = (unsigned char *)kalMemAlloc( + sizeof(struct fwtbl_lmac_struct), VIR_MEM_TYPE); + if (!wtbl_raw_dw) { + DBGLOG(REQ, ERROR, "WTBL : Memory alloc failed\n"); + return 0; + } + + /* LMAC */ + CONNAC2X_LWTBL_CONFIG(prAdapter, prChipInfo->u4LmacWtblDUAddr, u4Index); + wtbl_lmac_baseaddr = CONNAC2X_LWTBL_IDX2BASE( + prChipInfo->u4LmacWtblDUAddr, u4Index, 0); + HAL_MCR_RD(prAdapter, prChipInfo->u4LmacWtblDUAddr, + &u4Value); + + DBGLOG(REQ, INFO, "LMAC WTBL Addr: group: 0x%x=0x%x addr: 0x%x\n", + prChipInfo->u4LmacWtblDUAddr, + u4Value, + wtbl_lmac_baseaddr); + + /* Read LWTBL Entries */ + for (wtbl_offset = 0; wtbl_offset < + sizeof(struct fwtbl_lmac_struct); + wtbl_offset += 4) { + addr = wtbl_lmac_baseaddr + wtbl_offset; + HAL_MCR_RD(prAdapter, addr, + &u4Value); + kalMemCopy( + (uint32_t *)&wtbl_raw_dw[wtbl_offset], + &u4Value, sizeof(uint32_t)); + } + + pwtbl = (struct fwtbl_lmac_struct *)wtbl_raw_dw; + i4BytesWritten = connac2x_dump_helper_wtbl_info( + prAdapter, + pcCommand, + i4TotalLen, + pwtbl, + u4Index); + + kalMemFree(wtbl_raw_dw, VIR_MEM_TYPE, + sizeof(struct fwtbl_lmac_struct)); + + connac2x_print_wtbl_info(prAdapter, u4Index); + return i4BytesWritten; +} + +int32_t connac2x_show_umac_wtbl_info( + struct ADAPTER *prAdapter, + uint32_t u4Index, + char *pcCommand, + int i4TotalLen) +{ + struct mt66xx_chip_info *prChipInfo; + int32_t i4BytesWritten = 0; + uint8_t keytbl[32] = {0}; + uint8_t keytbl2[32] = {0}; + uint16_t x; + uint32_t *dest_cpy = (uint32_t *)keytbl; + uint32_t sizeInDW = 8; + uint32_t u4SrcAddr = 0; + uint32_t u4Value = 0; + uint32_t wtbl_offset, addr; + uint32_t wtbl_umac_baseaddr; + unsigned char *wtbl_raw_dw = NULL; + struct fwtbl_umac_struct *puwtbl; + unsigned long long pn = 0; + + prChipInfo = prAdapter->chip_info; + /* UMAC */ + CONNAC2X_UWTBL_CONFIG(prAdapter, prChipInfo->u4UmacWtblDUAddr, u4Index); + wtbl_umac_baseaddr = CONNAC2X_UWTBL_IDX2BASE( + prChipInfo->u4UmacWtblDUAddr, u4Index, 0); + HAL_MCR_RD(prAdapter, prChipInfo->u4UmacWtblDUAddr, &u4Value); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "UMAC WTBL Addr: group: 0x%x=0x%x addr: 0x%x\n", + prChipInfo->u4UmacWtblDUAddr, + u4Value, + wtbl_umac_baseaddr); + + wtbl_raw_dw = (unsigned char *)kalMemAlloc( + sizeof(struct fwtbl_umac_struct), VIR_MEM_TYPE); + if (!wtbl_raw_dw) { + DBGLOG(REQ, ERROR, "WTBL : Memory alloc failed\n"); + return 0; + } + /* Read UWTBL Entries */ + for (wtbl_offset = 0; wtbl_offset < + sizeof(struct fwtbl_umac_struct); + wtbl_offset += 4) { + addr = wtbl_umac_baseaddr + wtbl_offset; + HAL_MCR_RD(prAdapter, addr, + &u4Value); + kalMemCopy( + (uint32_t *)&wtbl_raw_dw[wtbl_offset], + &u4Value, sizeof(uint32_t)); + } + puwtbl = (struct fwtbl_umac_struct *)wtbl_raw_dw; + pn = ((pn || (puwtbl->serial_no.wtbl_d1.field.pn1) << 5) + || puwtbl->serial_no.wtbl_d0.field.pn0); + /* UMAC WTBL DW 0,1 */ + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "UWTBL DW 0,1\n\tpn:%d\n\tcom_sn:%d\n", + pn, + puwtbl->serial_no.wtbl_d1.field.com_sn); + + /* UMAC WTBL DW 5 */ + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "UWTBL DW 5\n" + "\tKey_loc0:%d\n" + "\tKey_loc1:%d\n" + "\tQoS:%d\n" + "\tHT:%d\n" + "\tHW_AMSDU_CFG:%d\n", + puwtbl->klink_amsdu.wtbl_d5.field.key_loc0, + puwtbl->klink_amsdu.wtbl_d5.field.key_loc1, + puwtbl->klink_amsdu.wtbl_d5.field.qos, + puwtbl->klink_amsdu.wtbl_d5.field.ht, + puwtbl->klink_amsdu.wtbl_d6.field.hw_amsdu_cfg); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n\nkeyloc0:%d\n", + puwtbl->klink_amsdu.wtbl_d5.field.key_loc0); + + if (puwtbl->klink_amsdu.wtbl_d5.field.key_loc0 != + (CONNAC2X_WTBL_KEY_LINK_DW_KEY_LOC0_MASK >> + CONNAC2X_WTBL_KEY_LINK_DW_KEY_LOC0_OFFSET)) { + /* will write new value WTBL_UMAC_TOP_BASE */ + CONNAC2X_KEYTBL_CONFIG(prAdapter, prChipInfo->u4UmacWtblDUAddr, + puwtbl->klink_amsdu.wtbl_d5.field.key_loc0); + u4SrcAddr = CONNAC2X_KEYTBL_IDX2BASE( + prChipInfo->u4UmacWtblDUAddr, + puwtbl->klink_amsdu.wtbl_d5.field.key_loc0, 0); + + HAL_MCR_RD(prAdapter, prChipInfo->u4UmacWtblDUAddr, + &u4Value); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "KEY WTBL Addr: group:0x%x=0x%x addr: 0x%x\n", + prChipInfo->u4UmacWtblDUAddr, + u4Value, + u4SrcAddr); + + /* Read Entries */ + while (sizeInDW--) { + HAL_MCR_RD(prAdapter, u4SrcAddr, &u4Value); + kalMemCopy(dest_cpy, &u4Value, sizeof(uint32_t)); + dest_cpy++; + u4SrcAddr += 4; + } + + for (x = 0; x < 8; x++) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "DW%02d: %02x %02x %02x %02x\n", + x, + keytbl[x * 4 + 3], + keytbl[x * 4 + 2], + keytbl[x * 4 + 1], + keytbl[x * 4]); + } + } + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nkeyloc1:%d\n", + puwtbl->klink_amsdu.wtbl_d5.field.key_loc1); + + if (puwtbl->klink_amsdu.wtbl_d5.field.key_loc1 != + (CONNAC2X_WTBL_KEY_LINK_DW_KEY_LOC1_MASK >> + CONNAC2X_WTBL_KEY_LINK_DW_KEY_LOC1_OFFSET)) { + dest_cpy = (uint32_t *)keytbl2; + sizeInDW = 8; + + /* will write new value WF_WTBLON_TOP_WDUCR_ADDR */ + CONNAC2X_KEYTBL_CONFIG(prAdapter, prChipInfo->u4UmacWtblDUAddr, + puwtbl->klink_amsdu.wtbl_d5.field.key_loc1); + u4SrcAddr = CONNAC2X_KEYTBL_IDX2BASE( + prChipInfo->u4UmacWtblDUAddr, + puwtbl->klink_amsdu.wtbl_d5.field.key_loc1, 0); + + HAL_MCR_RD(prAdapter, prChipInfo->u4UmacWtblDUAddr, + &u4Value); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "KEY WTBL Addr: group:0x%x=0x%x addr: 0x%x\n", + prChipInfo->u4UmacWtblDUAddr, + u4Value, + u4SrcAddr); + + /* Read Entries */ + while (sizeInDW--) { + HAL_MCR_RD(prAdapter, u4SrcAddr, &u4Value); + kalMemCopy(dest_cpy, &u4Value, sizeof(uint32_t)); + dest_cpy++; + u4SrcAddr += 4; + } + + for (x = 0; x < 8; x++) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "DW%02d: %02x %02x %02x %02x\n", + x, + keytbl2[x * 4 + 3], + keytbl2[x * 4 + 2], + keytbl2[x * 4 + 1], + keytbl2[x * 4]); + } + } + kalMemFree(wtbl_raw_dw, VIR_MEM_TYPE, + sizeof(struct fwtbl_umac_struct)); + + return i4BytesWritten; +} + +int32_t connac2x_show_rx_rate_info( + struct ADAPTER *prAdapter, + char *pcCommand, + int32_t i4TotalLen, + uint8_t ucStaIdx) +{ + int32_t i4BytesWritten = 0; + uint32_t txmode, rate, frmode, sgi, nsts, ldpc, stbc, groupid, mu; + uint32_t u4RxVector0 = 0, u4RxVector1 = 0, u4RxVector2 = 0; + + /* Group3 PRXV1[0:31] */ + u4RxVector0 = prAdapter->arStaRec[ucStaIdx].u4RxVector0; + /* Group5 C-B-0[0:31] */ + u4RxVector1 = prAdapter->arStaRec[ucStaIdx].u4RxVector1; + /* Group5 C-B-1[0:31] */ + u4RxVector2 = prAdapter->arStaRec[ucStaIdx].u4RxVector2; + + DBGLOG(REQ, LOUD, "****** P-RXVector1 = 0x%08x ******\n", + u4RxVector0); + DBGLOG(REQ, LOUD, "****** C-RXVector1 = 0x%08x ******\n", + u4RxVector1); + DBGLOG(REQ, LOUD, "****** C-RXVector2 = 0x%08x ******\n", + u4RxVector2); + + /* P-RXV1 */ + rate = (u4RxVector0 & CONNAC2X_RX_VT_RX_RATE_MASK) + >> CONNAC2X_RX_VT_RX_RATE_OFFSET; + nsts = ((u4RxVector0 & CONNAC2X_RX_VT_NSTS_MASK) + >> CONNAC2X_RX_VT_NSTS_OFFSET); + ldpc = u4RxVector0 & CONNAC2X_RX_VT_LDPC; + + /* C-B-0 */ + stbc = (u4RxVector1 & CONNAC2X_RX_VT_STBC_MASK) + >> CONNAC2X_RX_VT_STBC_OFFSET; + txmode = (u4RxVector1 & CONNAC2X_RX_VT_RX_MODE_MASK) + >> CONNAC2X_RX_VT_RX_MODE_OFFSET; + frmode = (u4RxVector1 & CONNAC2X_RX_VT_FR_MODE_MASK) + >> CONNAC2X_RX_VT_FR_MODE_OFFSET; + sgi = (u4RxVector1 & CONNAC2X_RX_VT_SHORT_GI_MASK) + >> CONNAC2X_RX_VT_SHORT_GI_OFFSET; + /* C-B-1 */ + groupid = (u4RxVector2 & CONNAC2X_RX_VT_GROUP_ID_MASK) + >> CONNAC2X_RX_VT_GROUP_ID_OFFSET; + + if (groupid && groupid != 63) { + mu = 1; + } else { + mu = 0; + nsts += 1; + } + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%-20s%s", "Last RX Rate", " = "); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + rate < 4 ? HW_TX_RATE_CCK_STR[rate] : + (rate < 8 ? HW_TX_RATE_CCK_STR[rate - 4] : + HW_TX_RATE_CCK_STR[4])); + else if (txmode == TX_RATE_MODE_OFDM) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + nicHwRateOfdmStr(rate)); + else if ((txmode == TX_RATE_MODE_HTMIX) || + (txmode == TX_RATE_MODE_HTGF)) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "MCS%d, ", rate); + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s%d_MCS%d, ", + stbc == 1 ? "NSTS" : "NSS", nsts, rate); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + frmode < 4 ? HW_TX_RATE_BW[frmode] : HW_TX_RATE_BW[4]); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + rate < 4 ? "LP" : "SP"); + else if (txmode == TX_RATE_MODE_OFDM) + ; + else if (txmode == TX_RATE_MODE_HTMIX || + txmode == TX_RATE_MODE_HTGF || + txmode == TX_RATE_MODE_VHT) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + sgi == 0 ? "LGI" : "SGI"); + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + sgi == 0 ? "SGI" : (sgi == 1 ? "MGI" : "LGI")); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s", stbc == 0 ? "" : "STBC, "); + + if (mu) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, %s, %s (%d)\n", + txmode < ENUM_TX_MODE_NUM ? + HW_TX_MODE_STR[txmode] : "N/A", + ldpc == 0 ? "BCC" : "LDPC", "MU", groupid); + } else { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, %s\n", + txmode < ENUM_TX_MODE_NUM ? + HW_TX_MODE_STR[txmode] : "N/A", + ldpc == 0 ? "BCC" : "LDPC"); + } + + return i4BytesWritten; +} + +int32_t connac2x_show_rx_rssi_info( + struct ADAPTER *prAdapter, + char *pcCommand, + int32_t i4TotalLen, + uint8_t ucStaIdx) +{ + int32_t i4RSSI0 = 0, i4RSSI1 = 0, i4RSSI2 = 0, i4RSSI3 = 0; + int32_t i4BytesWritten = 0; + uint32_t u4CRxv4th = 0; + + /* Group5 C-B-3[0:31] */ + u4CRxv4th = prAdapter->arStaRec[ucStaIdx].u4RxVector4; + + DBGLOG(REQ, LOUD, "****** C-RXVector4th cycle = 0x%08x ******\n", + u4CRxv4th); + + i4RSSI0 = RCPI_TO_dBm((u4CRxv4th & CONNAC2X_RX_VT_RCPI0_MASK) >> + CONNAC2X_RX_VT_RCPI0_OFFSET); + i4RSSI1 = RCPI_TO_dBm((u4CRxv4th & CONNAC2X_RX_VT_RCPI1_MASK) >> + CONNAC2X_RX_VT_RCPI1_OFFSET); + + if (prAdapter->rWifiVar.ucNSS > 2) { + i4RSSI2 = RCPI_TO_dBm((u4CRxv4th & CONNAC2X_RX_VT_RCPI2_MASK) >> + CONNAC2X_RX_VT_RCPI2_OFFSET); + i4RSSI3 = RCPI_TO_dBm((u4CRxv4th & CONNAC2X_RX_VT_RCPI3_MASK) >> + CONNAC2X_RX_VT_RCPI3_OFFSET); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%-20s%s%d %d %d %d\n", + "Last RX Data RSSI", " = ", + i4RSSI0, i4RSSI1, i4RSSI2, i4RSSI3); + } else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%-20s%s%d %d\n", + "Last RX Data RSSI", " = ", i4RSSI0, i4RSSI1); + + return i4BytesWritten; +} + +int32_t connac2x_show_stat_info( + struct ADAPTER *prAdapter, + char *pcCommand, + int32_t i4TotalLen, + struct PARAM_HW_WLAN_INFO *prHwWlanInfo, + struct PARAM_GET_STA_STATISTICS *prQueryStaStatistics, + uint8_t fgResetCnt, + uint32_t u4StatGroup) +{ + int32_t i4BytesWritten = 0; + int32_t rRssi; + uint16_t u2LinkSpeed, u2Idx = 0; + uint32_t u4Per, u4RxPer[ENUM_BAND_NUM], u4TxMpduPer[ENUM_BAND_NUM], + u4InstantPer; + uint8_t ucDbdcIdx, ucSkipAr, ucStaIdx, ucNss; + static uint32_t u4TotalTxCnt[CFG_STAT_DBG_PEER_NUM] = {0}; + static uint32_t u4TotalFailCnt[CFG_STAT_DBG_PEER_NUM] = {0}; + static uint32_t u4Rate1TxCnt[CFG_STAT_DBG_PEER_NUM] = {0}; + static uint32_t u4Rate1FailCnt[CFG_STAT_DBG_PEER_NUM] = {0}; + static uint32_t au4RxMpduCnt[ENUM_BAND_NUM] = {0}; + static uint32_t au4FcsError[ENUM_BAND_NUM] = {0}; + static uint32_t au4RxFifoCnt[ENUM_BAND_NUM] = {0}; + static uint32_t au4AmpduTxSfCnt[ENUM_BAND_NUM] = {0}; + static uint32_t au4AmpduTxAckSfCnt[ENUM_BAND_NUM] = {0}; + struct RX_CTRL *prRxCtrl; + uint32_t u4InstantRxPer[ENUM_BAND_NUM]; + uint32_t u4InstantTxMpduPer[ENUM_BAND_NUM]; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + int16_t i2Wf0AvgPwr = 0, i2Wf1AvgPwr = 0; + uint32_t u4BufLen = 0; + uint8_t ucRaTableNum = sizeof(RATE_TBLE) / sizeof(char *); + uint8_t ucRaStatusNum = sizeof(RA_STATUS_TBLE) / sizeof(char *); + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + struct PARAM_LINK_SPEED_EX rLinkSpeed; + +#if 0 + uint8_t ucRaLtModeNum = sizeof(LT_MODE_TBLE) / sizeof(char *); + uint8_t ucRaSgiUnSpStateNum = sizeof(SGI_UNSP_STATE_TBLE) / + sizeof(char *); + uint8_t ucRaBwStateNum = sizeof(BW_STATE_TBLE) / sizeof(char *); +#endif + uint8_t aucAggRange[AGG_RANGE_SEL_NUM]; + uint32_t au4RangeCtrl[AGG_RANGE_SEL_4BYTE_NUM]; + enum AGG_RANGE_TYPE_T eRangeType = ENUM_AGG_RANGE_TYPE_TX; + + ucSkipAr = prQueryStaStatistics->ucSkipAr; + prRxCtrl = &prAdapter->rRxCtrl; + ucNss = prAdapter->rWifiVar.ucNSS; + + if (ucSkipAr) { + u2Idx = nicGetStatIdxInfo(prAdapter, + (uint8_t)(prHwWlanInfo->u4Index)); + + if (u2Idx == 0xFFFF) + return i4BytesWritten; + } + + if (ucSkipAr) { + u4TotalTxCnt[u2Idx] += prQueryStaStatistics->u4TransmitCount; + u4TotalFailCnt[u2Idx] += prQueryStaStatistics-> + u4TransmitFailCount; + u4Rate1TxCnt[u2Idx] += prQueryStaStatistics->u4Rate1TxCnt; + u4Rate1FailCnt[u2Idx] += prQueryStaStatistics->u4Rate1FailCnt; + } + + if (ucSkipAr) { + u4Per = (u4Rate1TxCnt[u2Idx] == 0) ? + (0) : (1000 * (u4Rate1FailCnt[u2Idx]) / + (u4Rate1TxCnt[u2Idx])); + + u4InstantPer = (prQueryStaStatistics->u4Rate1TxCnt == 0) ? + (0) : (1000 * (prQueryStaStatistics->u4Rate1FailCnt) / + (prQueryStaStatistics->u4Rate1TxCnt)); + } else { + u4Per = (prQueryStaStatistics->u4Rate1TxCnt == 0) ? + (0) : (1000 * (prQueryStaStatistics->u4Rate1FailCnt) / + (prQueryStaStatistics->u4Rate1TxCnt)); + + u4InstantPer = (prQueryStaStatistics->ucPer == 0) ? + (0) : (prQueryStaStatistics->ucPer); + } + + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; ucDbdcIdx++) { + au4RxMpduCnt[ucDbdcIdx] += g_arMibInfo[ucDbdcIdx].u4RxMpduCnt; + au4FcsError[ucDbdcIdx] += g_arMibInfo[ucDbdcIdx].u4FcsError; + au4RxFifoCnt[ucDbdcIdx] += g_arMibInfo[ucDbdcIdx].u4RxFifoFull; + au4AmpduTxSfCnt[ucDbdcIdx] += + g_arMibInfo[ucDbdcIdx].u4AmpduTxSfCnt; + au4AmpduTxAckSfCnt[ucDbdcIdx] += + g_arMibInfo[ucDbdcIdx].u4AmpduTxAckSfCnt; + + u4RxPer[ucDbdcIdx] = + ((au4RxMpduCnt[ucDbdcIdx] + au4FcsError[ucDbdcIdx]) == 0) ? + (0) : (1000 * au4FcsError[ucDbdcIdx] / + (au4RxMpduCnt[ucDbdcIdx] + + au4FcsError[ucDbdcIdx])); + + u4TxMpduPer[ucDbdcIdx] = + (au4AmpduTxSfCnt[ucDbdcIdx] == 0) ? + (0) : (1000 * (au4AmpduTxSfCnt[ucDbdcIdx] - + au4AmpduTxAckSfCnt[ucDbdcIdx]) / + au4AmpduTxSfCnt[ucDbdcIdx]); + + u4InstantRxPer[ucDbdcIdx] = + ((prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4RxMpduCnt + + prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4FcsError) + == 0) ? + (0) : (1000 * prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].u4FcsError / + (prQueryStaStatistics->rMibInfo[ucDbdcIdx]. + u4RxMpduCnt + + prQueryStaStatistics->rMibInfo[ucDbdcIdx]. + u4FcsError)); + u4InstantTxMpduPer[ucDbdcIdx] = + (prQueryStaStatistics->rMibInfo[ucDbdcIdx]. + u4AmpduTxSfCnt == 0) ? + (0) : (1000 * + (prQueryStaStatistics->rMibInfo[ucDbdcIdx]. + u4AmpduTxSfCnt - + prQueryStaStatistics->rMibInfo[ucDbdcIdx]. + u4AmpduTxAckSfCnt) / + prQueryStaStatistics->rMibInfo[ucDbdcIdx]. + u4AmpduTxSfCnt); + } + + rRssi = RCPI_TO_dBm(prQueryStaStatistics->ucRcpi); + u2LinkSpeed = (prQueryStaStatistics->u2LinkSpeed == 0) ? 0 : + prQueryStaStatistics->u2LinkSpeed / 2; + + if (ucSkipAr) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d(%d)\n", "\nWlanIdx(BackupIdx)", " = ", + prHwWlanInfo->u4Index, u2Idx); + } else { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "\nWlanIdx", " = ", + prHwWlanInfo->u4Index); + } + + /* =========== Group 0x0001 =========== */ + if (u4StatGroup & 0x0001) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "----- STA Stat (Group 0x01) -----\n"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CurrTemperature", " = ", + prQueryStaStatistics->ucTemperature); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Tx Total cnt", " = ", + ucSkipAr ? (u4TotalTxCnt[u2Idx]) : + (prQueryStaStatistics->u4TransmitCount)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Tx Fail Cnt", " = ", + ucSkipAr ? (u4TotalFailCnt[u2Idx]) : + (prQueryStaStatistics->u4TransmitFailCount)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Rate1 Tx Cnt", " = ", + ucSkipAr ? (u4Rate1TxCnt[u2Idx]) : + (prQueryStaStatistics->u4Rate1TxCnt)); + + if (ucSkipAr) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d, PER = %d.%1d%%, instant PER = %d.%1d%%\n", + "Rate1 Fail Cnt", " = ", + u4Rate1FailCnt[u2Idx], u4Per/10, u4Per%10, + u4InstantPer/10, u4InstantPer%10); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d, PER = %d.%1d%%, instant PER = %d%%\n", + "Rate1 Fail Cnt", " = ", + prQueryStaStatistics->u4Rate1FailCnt, + u4Per/10, u4Per%10, u4InstantPer); + + if ((ucSkipAr) && (fgResetCnt)) { + u4TotalTxCnt[u2Idx] = 0; + u4TotalFailCnt[u2Idx] = 0; + u4Rate1TxCnt[u2Idx] = 0; + u4Rate1FailCnt[u2Idx] = 0; + } + } + + /* =========== Group 0x0002 =========== */ + if (u4StatGroup & 0x0002) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "----- MIB Info (Group 0x02) -----\n"); + + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; ucDbdcIdx++) { + if (prAdapter->rWifiVar.fgDbDcModeEn) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "[DBDC_%d] :\n", ucDbdcIdx); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RX Success", " = ", + au4RxMpduCnt[ucDbdcIdx]); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d, PER = %d.%1d%%, instant PER = %d.%1d%%\n", + "RX with CRC", " = ", au4FcsError[ucDbdcIdx], + u4RxPer[ucDbdcIdx]/10, u4RxPer[ucDbdcIdx]%10, + u4InstantRxPer[ucDbdcIdx]/10, + u4InstantRxPer[ucDbdcIdx]%10); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RX drop FIFO full", " = ", + au4RxFifoCnt[ucDbdcIdx]); +#if 0 + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "TX MPDU Success", " = ", + au4AmpduTxAckSfCnt[ucDbdcIdx]); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d, PER = %d.%1d%%, instant PER = %d.%1d%%\n", + "TX MPDU Fail", " = ", + au4AmpduTxSfCnt[ucDbdcIdx] - + au4AmpduTxAckSfCnt[ucDbdcIdx], + u4TxMpduPer[ucDbdcIdx]/10, + u4TxMpduPer[ucDbdcIdx]%10, + u4InstantTxMpduPer[ucDbdcIdx]/10, + u4InstantTxMpduPer[ucDbdcIdx]%10); +#endif + if (!prAdapter->rWifiVar.fgDbDcModeEn) + break; + } + + if (fgResetCnt) { + kalMemZero(au4RxMpduCnt, sizeof(au4RxMpduCnt)); + kalMemZero(au4FcsError, sizeof(au4RxMpduCnt)); + kalMemZero(au4RxFifoCnt, sizeof(au4RxMpduCnt)); + kalMemZero(au4AmpduTxSfCnt, sizeof(au4RxMpduCnt)); + kalMemZero(au4AmpduTxAckSfCnt, sizeof(au4RxMpduCnt)); + } + } + + /* =========== Group 0x0004 =========== */ + if (u4StatGroup & 0x0004) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "----- Last Rx Info (Group 0x04) -----\n"); + + /* get Beacon RSSI */ + ucBssIndex = secGetBssIdxByWlanIdx + (prAdapter, (uint8_t)(prHwWlanInfo->u4Index)); + + rStatus = kalIoctlByBssIdx(prAdapter->prGlueInfo, + wlanoidQueryRssi, + &rLinkSpeed, sizeof(rLinkSpeed), + TRUE, TRUE, TRUE, + &u4BufLen, ucBssIndex); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "unable to retrieve rssi\n"); + + if (IS_BSS_INDEX_VALID(ucBssIndex)) + rRssi = rLinkSpeed.rLq[ucBssIndex].cRssi; + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + 1; +#if 0 + rStatus = kalIoctl(prAdapter->prGlueInfo, + wlanoidQuerySwCtrlRead, &rSwCtrlInfo, + sizeof(rSwCtrlInfo), TRUE, TRUE, TRUE, + &u4BufLen); +#endif + DBGLOG(REQ, LOUD, "rStatus %u, rSwCtrlInfo.u4Data 0x%x\n", + rStatus, rSwCtrlInfo.u4Data); + if (rStatus == WLAN_STATUS_SUCCESS) { + i2Wf0AvgPwr = rSwCtrlInfo.u4Data & 0xFFFF; + i2Wf1AvgPwr = (rSwCtrlInfo.u4Data >> 16) & 0xFFFF; + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d %d\n", "NOISE", " = ", + i2Wf0AvgPwr, i2Wf1AvgPwr); + } + +#ifndef SOC3_0 + /* Last RX Rate */ + i4BytesWritten += nicGetRxRateInfo(prAdapter, + pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + (uint8_t)(prHwWlanInfo->u4Index)); +#endif + /* Last RX RSSI */ + i4BytesWritten += nicRxGetLastRxRssi(prAdapter, + pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + (uint8_t)(prHwWlanInfo->u4Index)); + + /* Last TX Resp RSSI */ + if (ucNss > 2) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d %d %d %d\n", + "Tx Response RSSI", " = ", + RCPI_TO_dBm( + prHwWlanInfo->rWtblRxCounter.ucRxRcpi0), + RCPI_TO_dBm( + prHwWlanInfo->rWtblRxCounter.ucRxRcpi1), + RCPI_TO_dBm( + prHwWlanInfo->rWtblRxCounter.ucRxRcpi2), + RCPI_TO_dBm( + prHwWlanInfo->rWtblRxCounter.ucRxRcpi3)); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d %d\n", "Tx Response RSSI", " = ", + RCPI_TO_dBm( + prHwWlanInfo->rWtblRxCounter.ucRxRcpi0), + RCPI_TO_dBm( + prHwWlanInfo->rWtblRxCounter.ucRxRcpi1)); + + /* Last Beacon RSSI */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Beacon RSSI", " = ", rRssi); + } + + /* =========== Group 0x0008 =========== */ + if (u4StatGroup & 0x0008) { + /* TxV */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "----- Last TX Info (Group 0x08) -----\n"); + + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; ucDbdcIdx++) { + int8_t txpwr, pos_txpwr; + + txpwr = TX_VECTOR_GET_TX_PWR( + &prQueryStaStatistics->rTxVector[ucDbdcIdx]); + + if (prAdapter->rWifiVar.fgDbDcModeEn) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "[DBDC_%d] :\n", ucDbdcIdx); + + i4BytesWritten += nicTxGetVectorInfo( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + &prQueryStaStatistics->rTxVector[ucDbdcIdx]); + + if (prQueryStaStatistics->rTxVector[ucDbdcIdx] + .u4TxV[0] == 0xFFFFFFFF) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Chip Out TX Power", + " = ", "N/A"); + else { + pos_txpwr = (txpwr < 0) ? + (~txpwr + 1) : (txpwr); + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%c%d.%1d dBm\n", + "Chip Out TX Power", " = ", + (txpwr < 0) ? '-' : '+', + (pos_txpwr / 2), + 5 * (pos_txpwr % 2)); + } + + if (!prAdapter->rWifiVar.fgDbDcModeEn) + break; + } + } + + /* =========== Group 0x0010 =========== */ + if (u4StatGroup & 0x0010) { + /* RX Reorder */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "----- RX Reorder (Group 0x10) -----\n"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%lu\n", "Rx reorder miss", " = ", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_MISS_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%lu\n", "Rx reorder within", " = ", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_WITHIN_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%lu\n", "Rx reorder ahead", " = ", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_AHEAD_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%lu\n", "Rx reorder behind", " = ", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_BEHIND_COUNT)); + } + + /* =========== Group 0x0020 =========== */ + if (u4StatGroup & 0x0020) { + /* RA info */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "----- RA Info (Group 0x20) -----\n"); +#if 0 + /* Last TX Rate */ + i4BytesWritten += nicGetTxRateInfo( + pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + FALSE, prHwWlanInfo, prQueryStaStatistics); +#endif + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%-20s%s%d\n", "LinkSpeed", + " = ", u2LinkSpeed); + + if (!prQueryStaStatistics->ucSkipAr) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "RateTable", " = ", + prQueryStaStatistics->ucArTableIdx < + (ucRaTableNum - 1) ? + RATE_TBLE[ + prQueryStaStatistics->ucArTableIdx] : + RATE_TBLE[ucRaTableNum - 1]); + + if (wlanGetStaIdxByWlanIdx(prAdapter, + (uint8_t)(prHwWlanInfo->u4Index), &ucStaIdx) == + WLAN_STATUS_SUCCESS){ + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "2G Support 256QAM TX", + " = ", + ((prAdapter->arStaRec[ucStaIdx].u4Flags + & MTK_SYNERGY_CAP_SUPPORT_24G_MCS89) || + (prQueryStaStatistics-> + ucDynamicGband256QAMState == 2)) ? + 1 : 0); + } +#if 0 + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d%%\n", "Rate1 instantPer", " = ", + u4InstantPer); +#endif + if (prQueryStaStatistics->ucAvePer == 0xFF) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Train Down", " = ", + "N/A"); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Train Up", " = ", + "N/A"); + } else { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d -> %d\n", "Train Down", + " = ", + (uint16_t) + (prQueryStaStatistics->u2TrainDown + & BITS(0, 7)), + (uint16_t) + ((prQueryStaStatistics->u2TrainDown >> + 8) & BITS(0, 7))); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d -> %d\n", "Train Up", " = ", + (uint16_t) + (prQueryStaStatistics->u2TrainUp + & BITS(0, 7)), + (uint16_t) + ((prQueryStaStatistics->u2TrainUp >> 8) + & BITS(0, 7))); + } + + if (prQueryStaStatistics->fgIsForceTxStream == 0) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Force Tx Stream", + " = ", "N/A"); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Force Tx Stream", " = ", + prQueryStaStatistics-> + fgIsForceTxStream); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Force SE off", " = ", + prQueryStaStatistics->fgIsForceSeOff); +#if 0 + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s%d%s%d%s%d%s%d\n", "TxQuality", " = ", + "KEEP_", prQueryStaStatistics->aucTxQuality[0], + ", UP_", prQueryStaStatistics->aucTxQuality[1], + ", DOWN_", prQueryStaStatistics-> + aucTxQuality[2], + ", BWUP_", prQueryStaStatistics-> + aucTxQuality[3]); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "UpPenalty", " = ", + prQueryStaStatistics->ucTxRateUpPenalty); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "LtMode", " = ", + prQueryStaStatistics->ucLowTrafficMode < + (ucRaLtModeNum - 1) ? + LT_MODE_TBLE[prQueryStaStatistics-> + ucLowTrafficMode] : + LT_MODE_TBLE[ucRaLtModeNum - 1]); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "LtCnt", " = ", + prQueryStaStatistics->ucLowTrafficCount); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "LtDashBoard", " = ", + prQueryStaStatistics->ucLowTrafficDashBoard); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "SgiState", " = ", + prQueryStaStatistics->ucDynamicSGIState < + (ucRaSgiUnSpStateNum - 1) ? + SGI_UNSP_STATE_TBLE[prQueryStaStatistics-> + ucDynamicSGIState] : + SGI_UNSP_STATE_TBLE[ucRaSgiUnSpStateNum - 1]); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "SgiScore", " = ", + prQueryStaStatistics->ucDynamicSGIScore); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "BwState", " = ", + prQueryStaStatistics->ucDynamicBWState < + (ucRaBwStateNum - 1) ? + BW_STATE_TBLE[prQueryStaStatistics-> + ucDynamicBWState] : + BW_STATE_TBLE[ucRaBwStateNum - 1]); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "NonSpState", " = ", + prQueryStaStatistics->ucDynamicSGIState < + (ucRaSgiUnSpStateNum - 1) ? + SGI_UNSP_STATE_TBLE[prQueryStaStatistics-> + ucVhtNonSpRateState] : + SGI_UNSP_STATE_TBLE[ucRaSgiUnSpStateNum - 1]); +#endif + } + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RunningCnt", " = ", + prQueryStaStatistics->u2RaRunningCnt); + + prQueryStaStatistics->ucRaStatus &= ~0x80; + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Status", " = ", + prQueryStaStatistics->ucRaStatus < (ucRaStatusNum - 1) ? + RA_STATUS_TBLE[prQueryStaStatistics->ucRaStatus] : + RA_STATUS_TBLE[ucRaStatusNum - 1]); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "MaxAF", " = ", + prHwWlanInfo->rWtblPeerCap.ucAmpduFactor); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s0x%x\n", "SpeIdx", " = ", + prHwWlanInfo->rWtblPeerCap.ucSpatialExtensionIndex); +#if 0 + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CBRN", " = ", + prHwWlanInfo->rWtblPeerCap.ucChangeBWAfterRateN); +#endif + /* Rate1~Rate8 */ + i4BytesWritten += nicGetTxRateInfo( + pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + TRUE, prHwWlanInfo, prQueryStaStatistics); + } + + /* =========== Group 0x0040 =========== */ + if (u4StatGroup & 0x0040) { + uint8_t ucIdx, ucInt; + + au4RangeCtrl[0] = prQueryStaStatistics->u4AggRangeCtrl_0; + au4RangeCtrl[1] = prQueryStaStatistics->u4AggRangeCtrl_1; + au4RangeCtrl[2] = prQueryStaStatistics->u4AggRangeCtrl_2; + au4RangeCtrl[3] = prQueryStaStatistics->u4AggRangeCtrl_3; + + eRangeType = (enum AGG_RANGE_TYPE_T) + prQueryStaStatistics->ucRangeType; + + for (ucIdx = 0; ucIdx < AGG_RANGE_SEL_NUM; ucIdx++) { + ucInt = ucIdx >> 2; + if (ucIdx % 4 == 0) + aucAggRange[ucIdx] = + ((au4RangeCtrl[ucInt] & + AGG_RANGE_SEL_0_MASK) >> + AGG_RANGE_SEL_0_OFFSET); + else if (ucIdx % 4 == 1) + aucAggRange[ucIdx] = + ((au4RangeCtrl[ucInt] & + AGG_RANGE_SEL_1_MASK) >> + AGG_RANGE_SEL_1_OFFSET); + else if (ucIdx % 4 == 2) + aucAggRange[ucIdx] = + ((au4RangeCtrl[ucInt] & + AGG_RANGE_SEL_2_MASK) >> + AGG_RANGE_SEL_2_OFFSET); + else if (ucIdx % 4 == 3) + aucAggRange[ucIdx] = + ((au4RangeCtrl[ucInt] & + AGG_RANGE_SEL_3_MASK) >> + AGG_RANGE_SEL_3_OFFSET); + } + + /* Tx Agg */ + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s%s%s", "------ ", + (eRangeType > ENUM_AGG_RANGE_TYPE_TX) ? ( + (eRangeType == ENUM_AGG_RANGE_TYPE_TRX) ? + ("TRX") : ("RX")) : ("TX"), + " AGG (Group 0x40) -----\n"); + + if (eRangeType == ENUM_AGG_RANGE_TYPE_TRX) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-6s%8d%5d%1s%2d%5d%1s%2d%5d%1s%2d%5d%1s%2d%5d%1s%2d%5d%1s%2d%5d%3s", + " TX :", aucAggRange[0] + 1, + aucAggRange[0] + 2, "~", aucAggRange[1] + 1, + aucAggRange[1] + 2, "~", aucAggRange[2] + 1, + aucAggRange[2] + 2, "~", aucAggRange[3] + 1, + aucAggRange[3] + 2, "~", aucAggRange[4] + 1, + aucAggRange[4] + 2, "~", aucAggRange[5] + 1, + aucAggRange[5] + 2, "~", aucAggRange[6] + 1, + aucAggRange[6] + 2, "~256\n"); + + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; + ucDbdcIdx++) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "DBDC%d:", ucDbdcIdx); + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%8d%8d%8d%8d%8d%8d%8d%8d\n", + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[0], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[1], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[2], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[3], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[4], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[5], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[6], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[7]); + + if (!prAdapter->rWifiVar.fgDbDcModeEn) + break; + } + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-6s%8d%5d%1s%2d%5d%1s%2d%5d%1s%2d%5d%1s%2d%5d%1s%2d%5d%1s%2d%5d%3s", + " RX :", aucAggRange[7] + 1, + aucAggRange[7] + 2, "~", aucAggRange[8] + 1, + aucAggRange[8] + 2, "~", aucAggRange[9] + 1, + aucAggRange[9] + 2, "~", aucAggRange[10] + 1, + aucAggRange[10] + 2, "~", aucAggRange[11] + 1, + aucAggRange[11] + 2, "~", aucAggRange[12] + 1, + aucAggRange[12] + 2, "~", aucAggRange[13] + 1, + aucAggRange[13] + 2, "~256\n"); + + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; + ucDbdcIdx++) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "DBDC%d:", ucDbdcIdx); + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%8d%8d%8d%8d%8d%8d%8d%8d\n", + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[8], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[9], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[10], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[11], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[12], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[13], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[14], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[15]); + + if (!prAdapter->rWifiVar.fgDbDcModeEn) + break; + } + } else { + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; + ucDbdcIdx++) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "DBDC%d:\n", ucDbdcIdx); + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-6s%8d%6d%1s%2d%6d%1s%2d%6d%1s%2d%6d%1s%2d%6d%1s%2d%6d%1s%2d%6d%1s%2d\n", + "Range:", aucAggRange[0] + 1, + aucAggRange[0] + 2, "~", + aucAggRange[1] + 1, + aucAggRange[1] + 2, "~", + aucAggRange[2] + 1, + aucAggRange[2] + 2, "~", + aucAggRange[3] + 1, + aucAggRange[3] + 2, "~", + aucAggRange[4] + 1, + aucAggRange[4] + 2, "~", + aucAggRange[5] + 1, + aucAggRange[5] + 2, "~", + aucAggRange[6] + 1, + aucAggRange[6] + 2, "~", + aucAggRange[7] + 1); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%14d%9d%9d%9d%9d%9d%9d%9d\n", + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[0], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[1], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[2], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[3], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[4], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[5], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[6], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[7]); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-6s%4d%1s%2d%5d%1s%2d%5d%1s%2d%5d%1s%2d%5d%1s%2d%5d%1s%2d%5d%1s%2d%5d%3s", + "Range:", aucAggRange[7] + 2, "~", + aucAggRange[8] + 1, + aucAggRange[8] + 2, "~", + aucAggRange[9] + 1, + aucAggRange[9] + 2, "~", + aucAggRange[10] + 1, + aucAggRange[10] + 2, "~", + aucAggRange[11] + 1, + aucAggRange[11] + 2, "~", + aucAggRange[12] + 1, + aucAggRange[12] + 2, "~", + aucAggRange[13] + 1, + aucAggRange[13] + 2, "~", + aucAggRange[14] + 1, + aucAggRange[14] + 2, "~256\n"); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%14d%9d%9d%9d%9d%9d%9d%9d\n", + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[8], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[9], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[10], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[11], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[12], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[13], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[14], + g_arMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[15]); + + if (!prAdapter->rWifiVar.fgDbDcModeEn) + break; + } + } + } + + kalMemZero(g_arMibInfo, sizeof(g_arMibInfo)); + + return i4BytesWritten; +} + +#endif /* CFG_SUPPORT_CONNAC2X */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/common/fw_dl.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/common/fw_dl.c new file mode 100644 index 0000000000000..922367738f924 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/common/fw_dl.c @@ -0,0 +1,2567 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file fw_dl.c + */ + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" + +/******************************************************************************* + * C O N S T A N T 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 S + ******************************************************************************* + */ + +#if CFG_ENABLE_FW_DOWNLOAD +uint32_t wlanGetDataMode(IN struct ADAPTER *prAdapter, + IN enum ENUM_IMG_DL_IDX_T eDlIdx, IN uint8_t ucFeatureSet) +{ + uint32_t u4DataMode = 0; + + if (ucFeatureSet & FW_FEATURE_SET_ENCRY) { + u4DataMode |= DOWNLOAD_CONFIG_RESET_OPTION; + u4DataMode |= (ucFeatureSet & + FW_FEATURE_SET_KEY_MASK); + u4DataMode |= DOWNLOAD_CONFIG_ENCRYPTION_MODE; + if (ucFeatureSet & FW_FEATURE_ENCRY_MODE) + u4DataMode |= DOWNLOAD_CONFIG_ENCRY_MODE_SEL; + } + + if (eDlIdx == IMG_DL_IDX_CR4_FW) + u4DataMode |= DOWNLOAD_CONFIG_WORKING_PDA_OPTION; + +#if CFG_ENABLE_FW_DOWNLOAD_ACK + u4DataMode |= DOWNLOAD_CONFIG_ACK_OPTION; /* ACK needed */ +#endif + return u4DataMode; +} + +void wlanGetHarvardFwInfo(IN struct ADAPTER *prAdapter, + IN uint8_t u4SecIdx, IN enum ENUM_IMG_DL_IDX_T eDlIdx, + OUT uint32_t *pu4Addr, OUT uint32_t *pu4Len, + OUT uint32_t *pu4DataMode, OUT u_int8_t *pfgIsEMIDownload, + OUT u_int8_t *pfgIsNotDownload) +{ + struct TAILER_FORMAT_T *prTailer; + + if (eDlIdx == IMG_DL_IDX_N9_FW) + prTailer = &prAdapter->rVerInfo.rN9tailer[u4SecIdx]; + else + prTailer = &prAdapter->rVerInfo.rCR4tailer[u4SecIdx]; + + *pu4Addr = prTailer->addr; + *pu4Len = (prTailer->len + LEN_4_BYTE_CRC); + *pu4DataMode = wlanGetDataMode(prAdapter, eDlIdx, + prTailer->feature_set); + *pfgIsEMIDownload = FALSE; + *pfgIsNotDownload = FALSE; +} + +void wlanGetConnacFwInfo(IN struct ADAPTER *prAdapter, + IN uint8_t u4SecIdx, IN enum ENUM_IMG_DL_IDX_T eDlIdx, + OUT uint32_t *pu4Addr, OUT uint32_t *pu4Len, + OUT uint32_t *pu4DataMode, OUT u_int8_t *pfgIsEMIDownload, + OUT u_int8_t *pfgIsNotDownload) +{ + struct TAILER_REGION_FORMAT_T *prTailer = + &prAdapter->rVerInfo.rRegionTailers[u4SecIdx]; + + *pu4Addr = prTailer->u4Addr; + *pu4Len = prTailer->u4Len; + *pu4DataMode = wlanGetDataMode(prAdapter, eDlIdx, + prTailer->ucFeatureSet); + *pfgIsEMIDownload = prTailer->ucFeatureSet & + DOWNLOAD_CONFIG_EMI; + *pfgIsNotDownload = prTailer->ucFeatureSet & + FW_FEATURE_NOT_DOWNLOAD; +} + +#if CFG_SUPPORT_COMPRESSION_FW_OPTION +void wlanImageSectionGetCompressFwInfo(IN struct ADAPTER + *prAdapter, IN void *pvFwImageMapFile, + IN uint32_t u4FwImageFileLength, IN uint8_t ucTotSecNum, + IN uint8_t ucCurSecNum, IN enum ENUM_IMG_DL_IDX_T eDlIdx, + OUT uint32_t *pu4Addr, OUT uint32_t *pu4Len, + OUT uint32_t *pu4DataMode, OUT uint32_t *pu4BlockSize, + OUT uint32_t *pu4CRC, OUT uint32_t *pu4UncompressedLength) +{ + struct FW_IMAGE_TAILER_T_2 *prFwHead; + struct TAILER_FORMAT_T_2 *prTailer; + uint8_t aucBuf[32]; + + prFwHead = (struct FW_IMAGE_TAILER_T_2 *) + (pvFwImageMapFile + u4FwImageFileLength - sizeof( + struct FW_IMAGE_TAILER_T_2)); + if (ucTotSecNum == 1) + prTailer = &prFwHead->dlm_info; + else + prTailer = &prFwHead->ilm_info; + + prTailer = &prTailer[ucCurSecNum]; + + *pu4Addr = prTailer->addr; + *pu4Len = (prTailer->len); + *pu4BlockSize = (prTailer->block_size); + *pu4CRC = (prTailer->crc); + *pu4UncompressedLength = (prTailer->real_size); + *pu4DataMode = wlanGetDataMode(prAdapter, eDlIdx, + prTailer->feature_set); + + /* Dump image information */ + if (ucCurSecNum == 0) { + DBGLOG(INIT, INFO, + "%s INFO: chip_info[%u:E%u] feature[0x%02X]\n", + (eDlIdx == IMG_DL_IDX_N9_FW) ? "N9" : "CR4", + prTailer->chip_info, + prTailer->eco_code, prTailer->feature_set); + kalMemZero(aucBuf, 32); + kalStrnCpy(aucBuf, prTailer->ram_version, + sizeof(prTailer->ram_version)); + DBGLOG(INIT, INFO, "date[%s] version[%s]\n", + prTailer->ram_built_date, aucBuf); + } + /* Backup to FW version info */ + if (eDlIdx == IMG_DL_IDX_N9_FW) { + kalMemCopy(&prAdapter->rVerInfo.rN9Compressedtailer, + prTailer, sizeof(struct TAILER_FORMAT_T_2)); + prAdapter->rVerInfo.fgIsN9CompressedFW = TRUE; + } else { + kalMemCopy(&prAdapter->rVerInfo.rCR4Compressedtailer, + prTailer, sizeof(struct TAILER_FORMAT_T_2)); + prAdapter->rVerInfo.fgIsCR4CompressedFW = TRUE; + } +} +#endif + +void wlanImageSectionGetPatchInfo(IN struct ADAPTER + *prAdapter, + IN void *pvFwImageMapFile, IN uint32_t u4FwImageFileLength, + OUT uint32_t *pu4StartOffset, OUT uint32_t *pu4Addr, + OUT uint32_t *pu4Len, + OUT uint32_t *pu4DataMode) +{ + struct PATCH_FORMAT_T *prPatchFormat; + uint8_t aucBuffer[32]; + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + + prPatchFormat = (struct PATCH_FORMAT_T *) pvFwImageMapFile; + + *pu4StartOffset = offsetof(struct PATCH_FORMAT_T, + ucPatchImage); + *pu4Addr = prChipInfo->patch_addr; + *pu4Len = u4FwImageFileLength - offsetof(struct + PATCH_FORMAT_T, ucPatchImage); + *pu4DataMode = wlanGetDataMode(prAdapter, IMG_DL_IDX_PATCH, + 0); + + /* Dump image information */ + kalMemZero(aucBuffer, 32); + kalStrnCpy(aucBuffer, prPatchFormat->aucPlatform, 4); + DBGLOG(INIT, INFO, + "PATCH INFO: platform[%s] HW/SW ver[0x%04X] ver[0x%04X]\n", + aucBuffer, prPatchFormat->u4SwHwVersion, + prPatchFormat->u4PatchVersion); + + kalStrnCpy(aucBuffer, prPatchFormat->aucBuildDate, 16); + DBGLOG(INIT, INFO, "date[%s]\n", aucBuffer); + + /* Backup to FW version info */ + kalMemCopy(&prAdapter->rVerInfo.rPatchHeader, prPatchFormat, + sizeof(struct PATCH_FORMAT_T)); +} + +void wlanImageSectionGetPatchInfoV2(IN struct ADAPTER + *prAdapter, + IN void *pvFwImageMapFile, IN uint32_t u4FwImageFileLength, + OUT uint32_t *pu4DataMode, + struct patch_dl_target *target) +{ + struct PATCH_FORMAT_V2_T *prPatchFormat; + uint8_t aucBuffer[32]; + struct PATCH_GLO_DESC *glo_desc; + struct PATCH_SEC_MAP *sec_map; + uint8_t *img_ptr; + uint32_t num_of_region, i; + + /* patch header */ + img_ptr = pvFwImageMapFile; + prPatchFormat = (struct PATCH_FORMAT_V2_T *)img_ptr; + + /* Dump image information */ + kalMemZero(aucBuffer, 32); + kalStrnCpy(aucBuffer, prPatchFormat->aucPlatform, 4); + DBGLOG(INIT, INFO, + "PATCH INFO: platform[%s] HW/SW ver[0x%04X] ver[0x%04X]\n", + aucBuffer, prPatchFormat->u4SwHwVersion, + prPatchFormat->u4PatchVersion); + + kalStrnCpy(aucBuffer, prPatchFormat->aucBuildDate, 16); + DBGLOG(INIT, INFO, "date[%s]\n", aucBuffer); + + /* Backup to FW version info */ + kalMemCopy(&prAdapter->rVerInfo.rPatchHeader, prPatchFormat, + sizeof(struct PATCH_FORMAT_T)); + + /* global descriptor */ + img_ptr += sizeof(struct PATCH_FORMAT_V2_T); + glo_desc = (struct PATCH_GLO_DESC *)img_ptr; + num_of_region = be2cpu32(glo_desc->section_num); + DBGLOG(INIT, INFO, + "\tPatch ver: 0x%x, Section num: 0x%x, subsys: 0x%x\n", + glo_desc->patch_ver, + num_of_region, + be2cpu32(glo_desc->subsys)); + + if (num_of_region < 0) { + DBGLOG(INIT, WARN, "parse patch failed! num_of_region < 0.\n"); + return; + } + + /* section map */ + img_ptr += sizeof(struct PATCH_GLO_DESC); + + target->num_of_region = num_of_region; + target->patch_region = (struct patch_dl_buf *)kalMemAlloc( + num_of_region * sizeof(struct patch_dl_buf), PHY_MEM_TYPE); + + if (!target->patch_region) { + DBGLOG(INIT, WARN, + "parse patch failed!No memory to allocate.\n"); + return; + } + + for (i = 0; i < num_of_region; i++) { + struct patch_dl_buf *region; + uint32_t section_type; + + region = &target->patch_region[i]; + sec_map = (struct PATCH_SEC_MAP *)img_ptr; + img_ptr += sizeof(struct PATCH_SEC_MAP); + + section_type = be2cpu32(sec_map->section_type); + DBGLOG(INIT, INFO, + "\tSection %d: type = 0x%x, offset = 0x%x, size = 0x%x\n", + i, section_type, be2cpu32(sec_map->section_offset), + be2cpu32(sec_map->section_size)); + + if ((section_type & PATCH_SEC_TYPE_MASK) == + PATCH_SEC_TYPE_BIN_INFO) { + region->img_dest_addr = + be2cpu32(sec_map->bin_info_spec.dl_addr); + region->img_size = + be2cpu32(sec_map->bin_info_spec.dl_size); + region->img_ptr = pvFwImageMapFile + + be2cpu32(sec_map->section_offset); + + DBGLOG(INIT, INFO, + "\tTarget address: 0x%x, length: 0x%x\n", + region->img_dest_addr, region->img_size); + } else { + region->img_ptr = NULL; + DBGLOG(INIT, INFO, "\tNot binary\n"); + } + } + *pu4DataMode = wlanGetDataMode(prAdapter, IMG_DL_IDX_PATCH, 0); +} + +uint32_t wlanDownloadSection(IN struct ADAPTER *prAdapter, + IN uint32_t u4Addr, IN uint32_t u4Len, + IN uint32_t u4DataMode, IN uint8_t *pucStartPtr, + IN enum ENUM_IMG_DL_IDX_T eDlIdx) +{ + uint32_t u4ImgSecSize, u4Offset; + uint8_t *pucSecBuf; + + if (wlanImageSectionConfig(prAdapter, u4Addr, u4Len, + u4DataMode, eDlIdx) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "Firmware download configuration failed!\n"); + return WLAN_STATUS_FAILURE; + } + + for (u4Offset = 0; u4Offset < u4Len; + u4Offset += CMD_PKT_SIZE_FOR_IMAGE) { + if (u4Offset + CMD_PKT_SIZE_FOR_IMAGE < u4Len) + u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; + else + u4ImgSecSize = u4Len - u4Offset; + + pucSecBuf = (uint8_t *) pucStartPtr + u4Offset; + if (wlanImageSectionDownload(prAdapter, u4ImgSecSize, + pucSecBuf) != + WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "Firmware scatter download failed!\n"); + return WLAN_STATUS_FAILURE; + } + } + + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanDownloadSectionV2(IN struct ADAPTER *prAdapter, + IN uint32_t u4DataMode, + IN enum ENUM_IMG_DL_IDX_T eDlIdx, + struct patch_dl_target *target) +{ + uint32_t u4ImgSecSize, u4Offset; + uint8_t *pucSecBuf; + uint32_t num_of_region, i; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + + num_of_region = target->num_of_region; + if (num_of_region < 0) { + DBGLOG(INIT, ERROR, + "Firmware download num_of_region < 0 !\n"); + u4Status = WLAN_STATUS_FAILURE; + goto out; + } + + + for (i = 0; i < num_of_region; i++) { + struct patch_dl_buf *region; + + region = &target->patch_region[i]; + if (region->img_ptr == NULL) + continue; + + /* 2. config PDA */ + if (wlanImageSectionConfig(prAdapter, region->img_dest_addr, + region->img_size, u4DataMode, eDlIdx) != + WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "Firmware download configuration failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + goto out; + } + + /* 3. image scatter */ + for (u4Offset = 0; u4Offset < region->img_size; + u4Offset += CMD_PKT_SIZE_FOR_IMAGE) { + if (u4Offset + CMD_PKT_SIZE_FOR_IMAGE < + region->img_size) + u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; + else + u4ImgSecSize = region->img_size - u4Offset; + + pucSecBuf = (uint8_t *) region->img_ptr + u4Offset; + if (wlanImageSectionDownload(prAdapter, u4ImgSecSize, + pucSecBuf) != + WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "Firmware scatter download failed!\n"); + return WLAN_STATUS_FAILURE; + } + } + } + +out: + kalMemFree(target->patch_region, PHY_MEM_TYPE, + num_of_region * sizeof(struct patch_dl_buf)); + target->patch_region = NULL; + target->num_of_region = 0; + return u4Status; +} + +uint32_t wlanDownloadEMISection(IN struct ADAPTER + *prAdapter, IN uint32_t u4DestAddr, + IN uint32_t u4Len, IN uint8_t *pucStartPtr) +{ +#if CFG_MTK_ANDROID_EMI + uint8_t __iomem *pucEmiBaseAddr = NULL; + uint32_t u4Offset = u4DestAddr & WIFI_EMI_ADDR_MASK; + + if (!gConEmiPhyBase) { +#if (CFG_SUPPORT_CONNINFRA == 1) + conninfra_get_phy_addr( + (unsigned int *)&gConEmiPhyBase, + (unsigned int *)&gConEmiSize); +#endif + + if (!gConEmiPhyBase) { + DBGLOG(INIT, ERROR, + "Consys emi memory address gConEmiPhyBase invalid\n"); + return WLAN_STATUS_FAILURE; + } + } + + request_mem_region(gConEmiPhyBase, gConEmiSize, "WIFI-EMI"); + kalSetEmiMpuProtection(gConEmiPhyBase, false); + pucEmiBaseAddr = ioremap_nocache(gConEmiPhyBase, gConEmiSize); + DBGLOG_LIMITED(INIT, INFO, + "EmiPhyBase:0x%llx offset:0x%x, ioremap region 0x%lX @ 0x%lX\n", + (uint64_t)gConEmiPhyBase, u4Offset, gConEmiSize, pucEmiBaseAddr); + if (!pucEmiBaseAddr) { + DBGLOG(INIT, ERROR, "ioremap failed\n"); + return WLAN_STATUS_FAILURE; + } + + kalMemCopy((pucEmiBaseAddr + u4Offset), pucStartPtr, u4Len); + + kalSetEmiMpuProtection(gConEmiPhyBase, true); + iounmap(pucEmiBaseAddr); + release_mem_region(gConEmiPhyBase, gConEmiSize); +#endif /* CFG_MTK_ANDROID_EMI */ + return WLAN_STATUS_SUCCESS; +} + +#if CFG_SUPPORT_COMPRESSION_FW_OPTION +u_int8_t wlanImageSectionCheckFwCompressInfo( + IN struct ADAPTER *prAdapter, + IN void *pvFwImageMapFile, IN uint32_t u4FwImageFileLength, + IN enum ENUM_IMG_DL_IDX_T eDlIdx) +{ + uint8_t ucCompression; + struct FW_IMAGE_TAILER_CHECK *prCheckInfo; + + if (eDlIdx == IMG_DL_IDX_PATCH) + return FALSE; + + prCheckInfo = (struct FW_IMAGE_TAILER_CHECK *) + (pvFwImageMapFile + u4FwImageFileLength - sizeof( + struct FW_IMAGE_TAILER_CHECK)); + DBGLOG(INIT, INFO, "feature_set %d\n", + prCheckInfo->feature_set); + ucCompression = (uint8_t)((prCheckInfo->feature_set & + COMPRESSION_OPTION_MASK) + >> COMPRESSION_OPTION_OFFSET); + DBGLOG(INIT, INFO, "Compressed Check INFORMATION %d\n", + ucCompression); + if (ucCompression == 1) { + DBGLOG(INIT, INFO, "Compressed FW\n"); + return TRUE; + } + return FALSE; +} + +uint32_t wlanCompressedImageSectionDownloadStage( + IN struct ADAPTER *prAdapter, IN void *pvFwImageMapFile, + IN uint32_t u4FwImageFileLength, IN uint8_t ucSectionNumber, + IN enum ENUM_IMG_DL_IDX_T eDlIdx, + OUT uint8_t *pucIsCompressed, + OUT struct INIT_CMD_WIFI_DECOMPRESSION_START *prFwImageInFo) +{ + uint32_t i; + int32_t i4TotalLen; + uint32_t u4FileOffset = 0; + uint32_t u4StartOffset = 0; + uint32_t u4DataMode = 0; + uint32_t u4Addr, u4Len, u4BlockSize, u4CRC; + uint32_t u4UnCompressedLength; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + uint8_t *pucStartPtr; + uint32_t u4offset = 0, u4ChunkSize; + u_int8_t fgIsDynamicMemMap = FALSE; + /* 3a. parse file header for decision of + * divided firmware download or not + */ + if (wlanImageSectionCheckFwCompressInfo(prAdapter, + pvFwImageMapFile, + u4FwImageFileLength, + eDlIdx) == TRUE) { + for (i = 0; i < ucSectionNumber; ++i) { + wlanImageSectionGetCompressFwInfo(prAdapter, + pvFwImageMapFile, + u4FwImageFileLength, ucSectionNumber, i, eDlIdx, + &u4Addr, &u4Len, &u4DataMode, + &u4BlockSize, &u4CRC, &u4UnCompressedLength); + u4offset = 0; + if (i == 0) { + prFwImageInFo->u4BlockSize = u4BlockSize; + prFwImageInFo->u4Region1Address = u4Addr; + prFwImageInFo->u4Region1CRC = u4CRC; + prFwImageInFo->u4Region1length = + u4UnCompressedLength; + } else { + prFwImageInFo->u4Region2Address = u4Addr; + prFwImageInFo->u4Region2CRC = u4CRC; + prFwImageInFo->u4Region2length = + u4UnCompressedLength; + } + i4TotalLen = u4Len; + DBGLOG(INIT, INFO, + "DL Offset[%u] addr[0x%08x] len[%u] datamode[0x%08x]\n", + u4FileOffset, u4Addr, u4Len, u4DataMode); + DBGLOG(INIT, INFO, "DL BLOCK[%u] COMlen[%u] CRC[%u]\n", + u4BlockSize, u4UnCompressedLength, u4CRC); + pucStartPtr = + (uint8_t *) pvFwImageMapFile + u4StartOffset; + while (i4TotalLen) { + u4ChunkSize = *((unsigned int *)(pucStartPtr + + u4FileOffset)); + u4FileOffset += 4; + DBGLOG(INIT, INFO, + "Downloaded Length %d! Addr %x\n", + i4TotalLen, u4Addr + u4offset); + DBGLOG(INIT, INFO, + "u4ChunkSize Length %d!\n", + u4ChunkSize); + + u4Status = wlanDownloadSection(prAdapter, + u4Addr + u4offset, + u4ChunkSize, + u4DataMode, + pvFwImageMapFile + u4FileOffset, + eDlIdx); + /* escape from loop if any + * pending error occurs + */ + if (u4Status == WLAN_STATUS_FAILURE) + break; + + i4TotalLen -= u4ChunkSize; + u4offset += u4BlockSize; + u4FileOffset += u4ChunkSize; + if (i4TotalLen < 0) { + DBGLOG(INIT, ERROR, + "Firmware scatter download failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } + } + } + *pucIsCompressed = TRUE; + } else { + u4Status = wlanImageSectionDownloadStage(prAdapter, + pvFwImageMapFile, u4FwImageFileLength, + ucSectionNumber, eDlIdx, &fgIsDynamicMemMap); + *pucIsCompressed = FALSE; + } + return u4Status; +} +#endif + +uint32_t wlanImageSectionDownloadStage( + IN struct ADAPTER *prAdapter, IN void *pvFwImageMapFile, + IN uint32_t u4FwImageFileLength, IN uint8_t ucSectionNumber, + IN enum ENUM_IMG_DL_IDX_T eDlIdx, OUT u_int8_t *pfgIsDynamicMemMap) +{ + uint32_t u4SecIdx, u4Offset = 0; + uint32_t u4Addr, u4Len, u4DataMode = 0; + u_int8_t fgIsEMIDownload = FALSE; + u_int8_t fgIsNotDownload = FALSE; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + struct patch_dl_target target; + struct PATCH_FORMAT_T *prPatchHeader; + struct FWDL_OPS_T *prFwDlOps; + + *pfgIsDynamicMemMap = FALSE; + prFwDlOps = prChipInfo->fw_dl_ops; + + /* 3a. parse file header for decision of + * divided firmware download or not + */ + if (eDlIdx == IMG_DL_IDX_PATCH) { + prPatchHeader = pvFwImageMapFile; + if (prPatchHeader->u4PatchVersion == PATCH_VERSION_MAGIC_NUM) { + wlanImageSectionGetPatchInfoV2(prAdapter, + pvFwImageMapFile, + u4FwImageFileLength, + &u4DataMode, + &target); + DBGLOG_LIMITED(INIT, INFO, + "FormatV2 num_of_regoin[%d] datamode[0x%08x]\n", + target.num_of_region, u4DataMode); + } else { + wlanImageSectionGetPatchInfo(prAdapter, + pvFwImageMapFile, + u4FwImageFileLength, + &u4Offset, &u4Addr, + &u4Len, &u4DataMode); + DBGLOG_LIMITED(INIT, INFO, + "FormatV1 DL Offset[%u] addr[0x%08x] len[%u] datamode[0x%08x]\n", + u4Offset, u4Addr, u4Len, u4DataMode); + } + + if (prPatchHeader->u4PatchVersion == PATCH_VERSION_MAGIC_NUM) + u4Status = wlanDownloadSectionV2(prAdapter, + u4DataMode, eDlIdx, &target); + else +/* For dynamic memory map::Begin */ +#if (CFG_DOWNLOAD_DYN_MEMORY_MAP == 1) + { + u4Status = prFwDlOps->downloadByDynMemMap( + prAdapter, u4Addr, u4Len, + pvFwImageMapFile + + u4Offset, + eDlIdx); + *pfgIsDynamicMemMap = TRUE; + } +#else + u4Status = wlanDownloadSection( + prAdapter, + u4Addr, + u4Len, + u4DataMode, + pvFwImageMapFile + + u4Offset, + eDlIdx); +#endif +/* For dynamic memory map::End */ + } else { + for (u4SecIdx = 0; u4SecIdx < ucSectionNumber; + u4SecIdx++, u4Offset += u4Len) { + prChipInfo->fw_dl_ops->getFwInfo(prAdapter, u4SecIdx, + eDlIdx, &u4Addr, + &u4Len, &u4DataMode, &fgIsEMIDownload, + &fgIsNotDownload); + + DBGLOG(INIT, TRACE, + "DL Offset[%u] addr[0x%08x] len[%u] datamode[0x%08x]\n", + u4Offset, u4Addr, u4Len, u4DataMode); + + if (fgIsNotDownload) + continue; + else if (fgIsEMIDownload) + u4Status = wlanDownloadEMISection(prAdapter, + u4Addr, u4Len, + pvFwImageMapFile + u4Offset); +/* For dynamic memory map:: Begin */ +#if (CFG_DOWNLOAD_DYN_MEMORY_MAP == 1) + else if ((u4DataMode & + DOWNLOAD_CONFIG_ENCRYPTION_MODE) == 0) { + /* Non-encrypted F/W region, + * use dynamic memory mapping for download + */ + *pfgIsDynamicMemMap = TRUE; + u4Status = prFwDlOps->downloadByDynMemMap( + prAdapter, + u4Addr, + u4Len, + pvFwImageMapFile + u4Offset, + eDlIdx); + } +#endif +/* For dynamic memory map:: End */ + else + u4Status = wlanDownloadSection(prAdapter, + u4Addr, u4Len, + u4DataMode, + pvFwImageMapFile + u4Offset, eDlIdx); + + /* escape from loop if any pending error occurs */ + if (u4Status == WLAN_STATUS_FAILURE) + break; + } + } + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to confirm the status of + * previously patch semaphore control + * + * @param prAdapter Pointer to the Adapter structure. + * ucCmdSeqNum Sequence number of previous firmware scatter + * + * @return WLAN_STATUS_SUCCESS + * WLAN_STATUS_FAILURE + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanPatchRecvSemaResp(IN struct ADAPTER *prAdapter, + IN uint8_t ucCmdSeqNum, OUT uint8_t *pucPatchStatus) +{ + struct mt66xx_chip_info *prChipInfo; + uint8_t *aucBuffer; + uint32_t u4EventSize; + struct INIT_WIFI_EVENT *prInitEvent; + struct INIT_EVENT_CMD_RESULT *prEventCmdResult; + uint32_t u4RxPktLength; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) + return WLAN_STATUS_FAILURE; + + u4EventSize = prChipInfo->rxd_size + prChipInfo->init_event_size + + sizeof(struct INIT_EVENT_CMD_RESULT); + aucBuffer = kalMemAlloc(u4EventSize, PHY_MEM_TYPE); + if (aucBuffer == NULL) { + DBGLOG(INIT, ERROR, "Alloc CMD buffer failed\n"); + return WLAN_STATUS_FAILURE; + } + + if (nicRxWaitResponse(prAdapter, 0, aucBuffer, u4EventSize, + &u4RxPktLength) != WLAN_STATUS_SUCCESS) { + + DBGLOG(INIT, WARN, "Wait patch semaphore response fail\n"); + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + return WLAN_STATUS_FAILURE; + } + + prInitEvent = (struct INIT_WIFI_EVENT *) + (aucBuffer + prChipInfo->rxd_size); + if (prInitEvent == NULL) { + DBGLOG(INIT, ERROR, "prInitEvent is NULL\n"); + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + return WLAN_STATUS_FAILURE; + } + if (prInitEvent->ucEID != INIT_EVENT_ID_PATCH_SEMA_CTRL) { + DBGLOG(INIT, WARN, "Unexpected EVENT ID, get 0x%0x\n", + prInitEvent->ucEID); + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + return WLAN_STATUS_FAILURE; + } + + if (prInitEvent->ucSeqNum != ucCmdSeqNum) { + DBGLOG(INIT, WARN, "Unexpected SeqNum %d, %d\n", + ucCmdSeqNum, prInitEvent->ucSeqNum); + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + return WLAN_STATUS_FAILURE; + } + + prEventCmdResult = (struct INIT_EVENT_CMD_RESULT *) + prInitEvent->aucBuffer; + + *pucPatchStatus = prEventCmdResult->ucStatus; + + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to check the patch semaphore control. + * + * @param prAdapter Pointer to the Adapter structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanPatchSendSemaControl(IN struct ADAPTER + *prAdapter, OUT uint8_t *pucSeqNum) +{ + struct mt66xx_chip_info *prChipInfo; + struct CMD_INFO *prCmdInfo; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + struct INIT_CMD_PATCH_SEMA_CONTROL *prPatchSemaControl; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + DEBUGFUNC("wlanImagePatchSemaphoreCheck"); + + /* 1. Allocate CMD Info Packet and its Buffer. */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES) + + sizeof(struct INIT_CMD_PATCH_SEMA_CONTROL)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prCmdInfo->u2InfoBufLen = sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES) + + sizeof(struct INIT_CMD_PATCH_SEMA_CONTROL); + + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + INIT_CMD_ID_PATCH_SEMAPHORE_CONTROL, + INIT_CMD_PDA_PACKET_TYPE_ID, + pucSeqNum, FALSE, + (void **)&prPatchSemaControl, TRUE, 0, S2D_INDEX_CMD_H2N); + + kalMemZero(prPatchSemaControl, + sizeof(struct INIT_CMD_PATCH_SEMA_CONTROL)); + + /* Setup DOWNLOAD_BUF */ + kalMemZero(prPatchSemaControl, + sizeof(struct INIT_CMD_PATCH_SEMA_CONTROL)); + prPatchSemaControl->ucGetSemaphore = PATCH_GET_SEMA_CONTROL; + + /* 4. Send FW_Download command */ + if (nicTxInitCmd(prAdapter, prCmdInfo, + prChipInfo->u2TxInitCmdPort) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "Fail to transmit image download command\n"); + } + /* 5. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + +u_int8_t wlanPatchIsDownloaded(IN struct ADAPTER *prAdapter) +{ + uint8_t ucSeqNum, ucPatchStatus; + uint32_t rStatus; + uint32_t u4Count; + + ucPatchStatus = PATCH_STATUS_NO_SEMA_NEED_PATCH; + u4Count = 0; + + while (ucPatchStatus == PATCH_STATUS_NO_SEMA_NEED_PATCH) { + if (u4Count) + kalMdelay(100); + + rStatus = wlanPatchSendSemaControl(prAdapter, &ucSeqNum); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, WARN, + "Send patch SEMA control CMD failed!!\n"); + break; + } + + rStatus = wlanPatchRecvSemaResp(prAdapter, ucSeqNum, + &ucPatchStatus); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, WARN, + "Recv patch SEMA control EVT failed!!\n"); + break; + } + + u4Count++; + + if (u4Count > 50) { + DBGLOG(INIT, WARN, "Patch status check timeout!!\n"); + break; + } + } + + if (ucPatchStatus == PATCH_STATUS_NO_NEED_TO_PATCH) + return TRUE; + else + return FALSE; +} + +uint32_t wlanPatchSendComplete(IN struct ADAPTER *prAdapter) +{ + struct CMD_INFO *prCmdInfo; + uint8_t ucTC, ucCmdSeqNum; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + struct mt66xx_chip_info *prChipInfo; + struct INIT_CMD_PATCH_FINISH *prPatchFinish; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + /* 1. Allocate CMD Info Packet and its Buffer. */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES) + + sizeof(struct INIT_CMD_PATCH_FINISH)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + kalMemZero(prCmdInfo->pucInfoBuffer, + sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES) + + sizeof(struct INIT_CMD_PATCH_FINISH)); + prCmdInfo->u2InfoBufLen = sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES) + + sizeof(struct INIT_CMD_PATCH_FINISH); + +#if (CFG_USE_TC4_RESOURCE_FOR_INIT_CMD == 1) + /* 2. Always use TC4 (TC4 as CPU) */ + ucTC = TC4_INDEX; +#else + /* 2. Use TC0's resource to send patch finish command. + * Only TC0 is allowed because SDIO HW always reports + * MCU's TXQ_CNT at TXQ0_CNT in CR4 architecutre) + */ + ucTC = TC0_INDEX; +#endif + + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + INIT_CMD_ID_PATCH_FINISH, + INIT_CMD_PACKET_TYPE_ID, + &ucCmdSeqNum, + FALSE, + (void **)&prPatchFinish, TRUE, 0, S2D_INDEX_CMD_H2N); + + prPatchFinish->ucCheckCrc = 0; + + /* 5. Seend WIFI start command */ + while (1) { + /* 5.1 Acquire TX Resource */ + if (nicTxAcquireResource(prAdapter, ucTC, + nicTxGetPageCount(prAdapter, + prCmdInfo->u2InfoBufLen, TRUE), + TRUE) == 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"); + goto exit; + } + continue; + } + /* 5.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo, + prChipInfo->u2TxInitCmdPort) != + WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "Fail to transmit WIFI start command\n"); + goto exit; + } + + break; + }; + + DBGLOG(INIT, INFO, + "PATCH FINISH CMD send, waiting for RSP\n"); + + /* kalMdelay(10000); */ + + u4Status = wlanConfigWifiFuncStatus(prAdapter, ucCmdSeqNum); + + if (u4Status != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "PATCH FINISH EVT failed\n"); + else + DBGLOG(INIT, INFO, "PATCH FINISH EVT success!!\n"); + +exit: + /* 6. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + +#if (CFG_DOWNLOAD_DYN_MEMORY_MAP == 1) +uint32_t wlanPatchDynMemMapSendComplete(IN struct ADAPTER *prAdapter) +{ + struct CMD_INFO *prCmdInfo; + uint8_t ucTC, ucCmdSeqNum; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + struct mt66xx_chip_info *prChipInfo; + struct INIT_CMD_PATCH_FINISH *prPatchFinish; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + /* 1. Allocate CMD Info Packet and its Buffer. */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES) + + sizeof(struct INIT_CMD_PATCH_FINISH)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + + return WLAN_STATUS_FAILURE; + } + + kalMemZero(prCmdInfo->pucInfoBuffer, + sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES) + + sizeof(struct INIT_CMD_PATCH_FINISH)); + + prCmdInfo->u2InfoBufLen = sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES) + + sizeof(struct INIT_CMD_PATCH_FINISH); + +#if (CFG_USE_TC4_RESOURCE_FOR_INIT_CMD == 1) + /* 2. Always use TC4 (TC4 as CPU) */ + ucTC = TC4_INDEX; +#else + /* 2. Use TC0's resource to send patch finish command. + * Only TC0 is allowed because SDIO HW always reports + * MCU's TXQ_CNT at TXQ0_CNT in CR4 architecutre) + */ + ucTC = TC0_INDEX; +#endif + + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + INIT_CMD_ID_DYN_MEM_MAP_PATCH_FINISH, + INIT_CMD_PACKET_TYPE_ID, + &ucCmdSeqNum, + FALSE, + (void **)&prPatchFinish, TRUE, 0, S2D_INDEX_CMD_H2N); + + prPatchFinish->ucCheckCrc = 0; + + /* 5. Seend WIFI start command */ + while (1) { + /* 5.1 Acquire TX Resource */ + if (nicTxAcquireResource(prAdapter, ucTC, + nicTxGetPageCount(prAdapter, + prCmdInfo->u2InfoBufLen, TRUE), + TRUE) == 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"); + goto exit; + } + continue; + } + /* 5.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo, + prChipInfo->u2TxInitCmdPort) != + WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "Fail to transmit WIFI start command\n"); + goto exit; + } + + break; + }; + + DBGLOG(INIT, INFO, + "PATCH FINISH CMD send, waiting for RSP\n"); + + /* kalMdelay(10000); */ + + u4Status = wlanConfigWifiFuncStatus(prAdapter, ucCmdSeqNum); + + if (u4Status != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "PATCH FINISH EVT failed\n"); + else + DBGLOG(INIT, INFO, "PATCH FINISH EVT success!!\n"); + +exit: + /* 6. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to configure FWDL parameters + * + * @param prAdapter Pointer to the Adapter structure. + * u4DestAddr Address of destination address + * u4ImgSecSize Length of the firmware block + * fgReset should be set to TRUE if this is the 1st configuration + * + * @return WLAN_STATUS_SUCCESS + * WLAN_STATUS_FAILURE + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanImageSectionConfig( + IN struct ADAPTER *prAdapter, + IN uint32_t u4DestAddr, IN uint32_t u4ImgSecSize, + IN uint32_t u4DataMode, + IN enum ENUM_IMG_DL_IDX_T eDlIdx) +{ + struct CMD_INFO *prCmdInfo; + struct INIT_CMD_DOWNLOAD_CONFIG *prInitCmdDownloadConfig; + uint8_t ucTC, ucCmdSeqNum; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + DEBUGFUNC("wlanImageSectionConfig"); + + if (u4ImgSecSize == 0) + return WLAN_STATUS_SUCCESS; + /* 1. Allocate CMD Info Packet and its Buffer. */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES) + + sizeof(struct INIT_CMD_DOWNLOAD_CONFIG)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prCmdInfo->u2InfoBufLen = sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES) + + sizeof(struct INIT_CMD_DOWNLOAD_CONFIG); + +#if (CFG_USE_TC4_RESOURCE_FOR_INIT_CMD == 1) + /* 2. Use TC4's resource to download image. (TC4 as CPU) */ + ucTC = TC4_INDEX; +#else + /* 2. Use TC0's resource to send init_cmd. + * Only TC0 is allowed because SDIO HW always reports + * MCU's TXQ_CNT at TXQ0_CNT in CR4 architecutre) + */ + ucTC = TC0_INDEX; +#endif + + if (eDlIdx == IMG_DL_IDX_PATCH) { + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + INIT_CMD_ID_PATCH_START, + INIT_CMD_PACKET_TYPE_ID, + &ucCmdSeqNum, + FALSE, + (void **)&prInitCmdDownloadConfig, + TRUE, 0, S2D_INDEX_CMD_H2N); + } else { + NIC_FILL_CMD_TX_HDR( + prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + INIT_CMD_ID_DOWNLOAD_CONFIG, + INIT_CMD_PACKET_TYPE_ID, + &ucCmdSeqNum, + FALSE, + (void **)&prInitCmdDownloadConfig, + TRUE, 0, S2D_INDEX_CMD_H2N); + } + + prInitCmdDownloadConfig->u4Address = u4DestAddr; + prInitCmdDownloadConfig->u4Length = u4ImgSecSize; + prInitCmdDownloadConfig->u4DataMode = u4DataMode; + + /* 6. Send FW_Download command */ + while (1) { + /* 6.1 Acquire TX Resource */ + if (nicTxAcquireResource(prAdapter, ucTC, + nicTxGetPageCount(prAdapter, + prCmdInfo->u2InfoBufLen, TRUE), + TRUE) == 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"); + goto exit; + } + continue; + } + /* 6.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo, + prChipInfo->u2TxInitCmdPort) != + WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "Fail to transmit image download command\n"); + goto exit; + } + + break; + }; + +#if CFG_ENABLE_FW_DOWNLOAD_ACK + /* 7. Wait for INIT_EVENT_ID_CMD_RESULT */ + u4Status = wlanConfigWifiFuncStatus(prAdapter, ucCmdSeqNum); +#endif + +exit: + /* 8. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to download FW image. + * + * @param prAdapter Pointer to the Adapter structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanImageSectionDownload(IN struct ADAPTER + *prAdapter, IN uint32_t u4ImgSecSize, + IN uint8_t *pucImgSecBuf) +{ + struct CMD_INFO *prCmdInfo; + uint8_t *prBuf; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + ASSERT(pucImgSecBuf); + ASSERT(u4ImgSecSize <= CMD_PKT_SIZE_FOR_IMAGE); + + DEBUGFUNC("wlanImageSectionDownload"); + + prChipInfo = prAdapter->chip_info; + + if (u4ImgSecSize == 0) + return WLAN_STATUS_SUCCESS; + /* 1. Allocate CMD Info Packet and its Buffer. */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES) + + u4ImgSecSize); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* + * For falcon WFDMA, driver doesn't need to append TXD. + * For old project/talos, + * TXD length will be included in asicFillInitCmdTxd. + */ + prCmdInfo->u2InfoBufLen = (uint16_t) u4ImgSecSize; + + /* 2. Setup common CMD Info Packet */ + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + 0, INIT_CMD_PDA_PACKET_TYPE_ID, + NULL, FALSE, (void **)&prBuf, TRUE, 0, S2D_INDEX_CMD_H2N); + + /* 3. Setup DOWNLOAD_BUF */ + kalMemCopy(prBuf, pucImgSecBuf, u4ImgSecSize); + + /* 4. Send FW_Download command */ + if (nicTxInitCmd(prAdapter, prCmdInfo, + prChipInfo->u2TxFwDlPort) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "Fail to transmit image download command\n"); + } + /* 5. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to confirm previously firmware + * download is done without error + * + * @param prAdapter Pointer to the Adapter structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanImageQueryStatus(IN struct ADAPTER *prAdapter) +{ + struct mt66xx_chip_info *prChipInfo; + struct CMD_INFO *prCmdInfo; + uint8_t *aucBuffer; + uint32_t u4EventSize; + uint32_t u4RxPktLength; + struct INIT_WIFI_EVENT *prInitEvent; + struct INIT_EVENT_CMD_RESULT *prEventPendingError; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + uint8_t ucTC, ucCmdSeqNum; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + DEBUGFUNC("wlanImageQueryStatus"); + + /* 1. Allocate CMD Info Packet and it Buffer. */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + u4EventSize = prChipInfo->rxd_size + prChipInfo->init_event_size + + sizeof(struct INIT_EVENT_CMD_RESULT); + aucBuffer = kalMemAlloc(u4EventSize, PHY_MEM_TYPE); + if (aucBuffer == NULL) { + DBGLOG(INIT, ERROR, "Alloc CMD buffer failed\n"); + return WLAN_STATUS_FAILURE; + } + + kalMemZero(prCmdInfo->pucInfoBuffer, + sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES)); + prCmdInfo->u2InfoBufLen = sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES); + +#if (CFG_USE_TC4_RESOURCE_FOR_INIT_CMD == 1) + /* 2. Always use TC4 */ + ucTC = TC4_INDEX; +#else + /* 2. Use TC0's resource to send init_cmd + * Only TC0 is allowed because SDIO HW always reports + * CPU's TXQ_CNT at TXQ0_CNT in CR4 architecutre) + */ + ucTC = TC0_INDEX; +#endif + + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + INIT_CMD_ID_QUERY_PENDING_ERROR, + INIT_CMD_PACKET_TYPE_ID, + &ucCmdSeqNum, FALSE, NULL, TRUE, 0, S2D_INDEX_CMD_H2N); + + /* 5. Send command */ + while (1) { + /* 5.1 Acquire TX Resource */ + if (nicTxAcquireResource(prAdapter, ucTC, + nicTxGetPageCount(prAdapter, + prCmdInfo->u2InfoBufLen, TRUE), + TRUE) == WLAN_STATUS_RESOURCES) { + if (nicTxPollingResource(prAdapter, + ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "Fail to get TX resource return within timeout\n"); + break; + } + continue; + + } + /* 5.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo, + prChipInfo->u2TxInitCmdPort) != + WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "Fail to transmit image download command\n"); + } + + break; + }; + + /* 6. Wait for INIT_EVENT_ID_PENDING_ERROR */ + do { + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + } else if (nicRxWaitResponse(prAdapter, 0, + aucBuffer, u4EventSize, + &u4RxPktLength) != + WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + } else { + prInitEvent = (struct INIT_WIFI_EVENT *) + (aucBuffer + prChipInfo->rxd_size); + if (prInitEvent == NULL) { + DBGLOG(INIT, ERROR, "prInitEvent is NULL\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } + + /* EID / SeqNum check */ + if (prInitEvent->ucEID != INIT_EVENT_ID_PENDING_ERROR) + u4Status = WLAN_STATUS_FAILURE; + else if (prInitEvent->ucSeqNum != ucCmdSeqNum) + u4Status = WLAN_STATUS_FAILURE; + else { + prEventPendingError = + (struct INIT_EVENT_CMD_RESULT *) + prInitEvent->aucBuffer; + /* 0 for download success */ + if (prEventPendingError->ucStatus != 0) + u4Status = WLAN_STATUS_FAILURE; + else + u4Status = WLAN_STATUS_SUCCESS; + } + } + } while (FALSE); + + /* 7. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanConfigWifiFuncStatus(IN struct ADAPTER + *prAdapter, IN uint8_t ucCmdSeqNum) +{ + struct mt66xx_chip_info *prChipInfo; + uint8_t *aucBuffer; + uint32_t u4EventSize; + struct INIT_WIFI_EVENT *prInitEvent; + struct INIT_EVENT_CMD_RESULT *prEventCmdResult; + uint32_t u4RxPktLength; + uint32_t u4Status; + uint8_t ucPortIdx = IMG_DL_STATUS_PORT_IDX; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + u4EventSize = prChipInfo->init_evt_rxd_size + + prChipInfo->init_event_size + + sizeof(struct INIT_EVENT_CMD_RESULT); + aucBuffer = kalMemAlloc(u4EventSize, PHY_MEM_TYPE); + if (aucBuffer == NULL) { + DBGLOG(INIT, ERROR, "Alloc CMD buffer failed\n"); + return WLAN_STATUS_FAILURE; + } + + do { + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + } else if (nicRxWaitResponse(prAdapter, ucPortIdx, + aucBuffer, u4EventSize, + &u4RxPktLength) != + WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + } else { + prInitEvent = (struct INIT_WIFI_EVENT *) + (aucBuffer + prChipInfo->init_evt_rxd_size); + + /* EID / SeqNum check */ + if (prInitEvent->ucEID != INIT_EVENT_ID_CMD_RESULT) + u4Status = WLAN_STATUS_FAILURE; + else if (prInitEvent->ucSeqNum != ucCmdSeqNum) + u4Status = WLAN_STATUS_FAILURE; + else { + prEventCmdResult = + (struct INIT_EVENT_CMD_RESULT *) + prInitEvent->aucBuffer; + + /* 0 for download success */ + if (prEventCmdResult->ucStatus != 0) { + DBGLOG(INIT, ERROR, + "Start CMD failed, status[%u]\n", + prEventCmdResult->ucStatus); +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + if (prEventCmdResult->ucStatus == + WIFI_FW_DECOMPRESSION_FAILED) + DBGLOG(INIT, ERROR, + "Start Decompression CMD failed, status[%u]\n", + prEventCmdResult->ucStatus); +#endif + u4Status = WLAN_STATUS_FAILURE; + } else { + u4Status = WLAN_STATUS_SUCCESS; + } + } + } + } while (FALSE); + + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + + return u4Status; +} + +uint32_t wlanConfigWifiFunc(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnable, IN uint32_t u4StartAddress, + IN uint8_t ucPDA) +{ + struct CMD_INFO *prCmdInfo; + struct INIT_CMD_WIFI_START *prInitCmdWifiStart; + uint8_t ucTC, ucCmdSeqNum; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + DEBUGFUNC("wlanConfigWifiFunc"); + + /* 1. Allocate CMD Info Packet and its Buffer. */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES) + + sizeof(struct INIT_CMD_WIFI_START)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + kalMemZero(prCmdInfo->pucInfoBuffer, + sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES) + + sizeof(struct INIT_CMD_WIFI_START)); + prCmdInfo->u2InfoBufLen = sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES) + + sizeof(struct INIT_CMD_WIFI_START); + +#if (CFG_USE_TC4_RESOURCE_FOR_INIT_CMD == 1) + /* 2. Always use TC4 (TC4 as CPU) */ + ucTC = TC4_INDEX; +#else + /* 2. Use TC0's resource to send init_cmd. + * Only TC0 is allowed because SDIO HW always reports + * CPU's TXQ_CNT at TXQ0_CNT in CR4 architecutre) + */ + ucTC = TC0_INDEX; +#endif + + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + INIT_CMD_ID_WIFI_START, + INIT_CMD_PACKET_TYPE_ID, + &ucCmdSeqNum, + FALSE, + (void **)&prInitCmdWifiStart, + TRUE, 0, S2D_INDEX_CMD_H2N); + + prInitCmdWifiStart->u4Override = 0; + if (fgEnable) + prInitCmdWifiStart->u4Override |= + START_OVERRIDE_START_ADDRESS; + + /* 5G cal until send efuse buffer mode CMD */ +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1) + if (prAdapter->fgIsSupportDelayCal == TRUE) + prInitCmdWifiStart->u4Override |= START_DELAY_CALIBRATION; +#endif + + if (ucPDA == PDA_CR4) + prInitCmdWifiStart->u4Override |= START_WORKING_PDA_OPTION; + + prInitCmdWifiStart->u4Address = u4StartAddress; + + /* 5. Seend WIFI start command */ + while (1) { + /* 5.1 Acquire TX Resource */ + if (nicTxAcquireResource(prAdapter, ucTC, + nicTxGetPageCount(prAdapter, + prCmdInfo->u2InfoBufLen, TRUE), + TRUE) == 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"); + goto exit; + } + continue; + } + /* 5.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo, + prChipInfo->u2TxInitCmdPort) + != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "Fail to transmit WIFI start command\n"); + goto exit; + } + + break; + }; + + DBGLOG(INIT, INFO, "FW_START CMD send, waiting for RSP\n"); + + u4Status = wlanConfigWifiFuncStatus(prAdapter, ucCmdSeqNum); + + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "FW_START EVT failed\n"); +#if (CFG_SUPPORT_CONNINFRA == 0) + GL_RESET_TRIGGER(prAdapter, RST_FLAG_CHIP_RESET); +#else + GL_RESET_TRIGGER(prAdapter, RST_FLAG_WF_RESET); +#endif + } else { + DBGLOG(INIT, INFO, "FW_START EVT success!!\n"); + +#if defined(_HIF_PCIE) + if (ucPDA == PDA_CR4 && prChipInfo->is_support_wacpu) + prChipInfo->rx_event_port = WFDMA1_RX_RING_IDX_1; +#endif /* _HIF_PCIE */ + + } + +exit: + /* 6. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + +#if (CFG_DOWNLOAD_DYN_MEMORY_MAP == 1) +uint32_t wlanRamCodeDynMemMapSendComplete(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnable, IN uint32_t u4StartAddress, + IN uint8_t ucPDA) +{ + struct CMD_INFO *prCmdInfo; + struct INIT_CMD_WIFI_START *prInitCmdWifiStart; + uint8_t ucTC, ucCmdSeqNum; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + DEBUGFUNC("wlanConfigWifiFunc"); + + /* 1. Allocate CMD Info Packet and its Buffer. */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES) + + sizeof(struct INIT_CMD_WIFI_START)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + kalMemZero(prCmdInfo->pucInfoBuffer, + sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES) + + sizeof(struct INIT_CMD_WIFI_START)); + + prCmdInfo->u2InfoBufLen = sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES) + + sizeof(struct INIT_CMD_WIFI_START); + +#if (CFG_USE_TC4_RESOURCE_FOR_INIT_CMD == 1) + /* 2. Always use TC4 (TC4 as CPU) */ + ucTC = TC4_INDEX; +#else + /* 2. Use TC0's resource to send init_cmd. + * Only TC0 is allowed because SDIO HW always reports + * CPU's TXQ_CNT at TXQ0_CNT in CR4 architecutre) + */ + ucTC = TC0_INDEX; +#endif + + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + INIT_CMD_ID_DYN_MEM_MAP_FW_FINISH, + INIT_CMD_PACKET_TYPE_ID, + &ucCmdSeqNum, + FALSE, + (void **)&prInitCmdWifiStart, + TRUE, 0, S2D_INDEX_CMD_H2N); + + prInitCmdWifiStart->u4Override = 0; + if (fgEnable) + prInitCmdWifiStart->u4Override |= + START_OVERRIDE_START_ADDRESS; + + /* 5G cal until send efuse buffer mode CMD */ +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1) + if (prAdapter->fgIsSupportDelayCal == TRUE) + prInitCmdWifiStart->u4Override |= START_DELAY_CALIBRATION; +#endif + + if (ucPDA == PDA_CR4) + prInitCmdWifiStart->u4Override |= START_WORKING_PDA_OPTION; + + prInitCmdWifiStart->u4Address = u4StartAddress; + + /* 5. Seend WIFI start command */ + while (1) { + /* 5.1 Acquire TX Resource */ + if (nicTxAcquireResource(prAdapter, ucTC, + nicTxGetPageCount(prAdapter, + prCmdInfo->u2InfoBufLen, TRUE), + TRUE) == 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"); + goto exit; + } + continue; + } + /* 5.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo, + prChipInfo->u2TxInitCmdPort) + != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "Fail to transmit WIFI start command\n"); + goto exit; + } + + break; + }; + if (prAdapter->chip_info->checkbushang) + prAdapter->chip_info->checkbushang((void *) prAdapter, FALSE); + + DBGLOG(INIT, INFO, "FW_START CMD send, waiting for RSP\n"); + + if (ucPDA == PDA_CR4 && prChipInfo->is_support_wacpu) { + prChipInfo->rx_event_port = WFDMA1_RX_RING_IDX_1; + /* workaround for harrier powerOnCal too long issue + * skip FW start event, fw ready bit check can cover this. + */ + return WLAN_STATUS_SUCCESS; + } + + u4Status = wlanConfigWifiFuncStatus(prAdapter, ucCmdSeqNum); + + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "FW_START EVT failed\n"); +#if (CFG_SUPPORT_CONNINFRA == 0) + GL_RESET_TRIGGER(prAdapter, RST_FLAG_CHIP_RESET); +#else + GL_RESET_TRIGGER(prAdapter, RST_FLAG_WF_RESET); +#endif + } + else + DBGLOG(INIT, INFO, "FW_START EVT success!!\n"); + +exit: + /* 6. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} +#endif + +#if CFG_SUPPORT_COMPRESSION_FW_OPTION +uint32_t +wlanCompressedFWConfigWifiFunc(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnable, + IN uint32_t u4StartAddress, IN uint8_t ucPDA, + IN struct INIT_CMD_WIFI_DECOMPRESSION_START *prFwImageInFo) +{ + struct CMD_INFO *prCmdInfo; + struct INIT_CMD_WIFI_DECOMPRESSION_START *prInitCmdWifiStart; + uint8_t ucTC, ucCmdSeqNum; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + DEBUGFUNC("wlanConfigWifiFunc"); + /* 1. Allocate CMD Info Packet and its Buffer. */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES) + + sizeof(struct INIT_CMD_WIFI_DECOMPRESSION_START)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + kalMemZero(prCmdInfo->pucInfoBuffer, + sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES) + + sizeof(struct INIT_CMD_WIFI_DECOMPRESSION_START)); + prCmdInfo->u2InfoBufLen = + sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES) + + sizeof(struct INIT_CMD_WIFI_DECOMPRESSION_START); + + /* 2. Always use TC0 */ + ucTC = TC0_INDEX; + + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + INIT_CMD_ID_DECOMPRESSED_WIFI_START, + INIT_CMD_PACKET_TYPE_ID, + &ucCmdSeqNum, + FALSE, + &prInitCmdWifiStart, TRUE, 0, S2D_INDEX_CMD_H2N); + + prInitCmdWifiStart->u4Override = 0; + if (fgEnable) + prInitCmdWifiStart->u4Override |= + START_OVERRIDE_START_ADDRESS; + + /* 5G cal until send efuse buffer mode CMD */ +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1) + if (prAdapter->fgIsSupportDelayCal == TRUE) + prInitCmdWifiStart->u4Override |= START_DELAY_CALIBRATION; +#endif + if (ucPDA == PDA_CR4) + prInitCmdWifiStart->u4Override |= START_WORKING_PDA_OPTION; + +#if CFG_COMPRESSION_DEBUG + prInitCmdWifiStart->u4Override |= START_CRC_CHECK; +#endif +#if CFG_DECOMPRESSION_TMP_ADDRESS + prInitCmdWifiStart->u4Override |= + CHANGE_DECOMPRESSION_TMP_ADDRESS; + prInitCmdWifiStart->u4DecompressTmpAddress = 0xE6000; +#endif + prInitCmdWifiStart->u4Address = u4StartAddress; + prInitCmdWifiStart->u4Region1Address = + prFwImageInFo->u4Region1Address; + prInitCmdWifiStart->u4Region1CRC = + prFwImageInFo->u4Region1CRC; + prInitCmdWifiStart->u4BlockSize = + prFwImageInFo->u4BlockSize; + prInitCmdWifiStart->u4Region1length = + prFwImageInFo->u4Region1length; + prInitCmdWifiStart->u4Region2Address = + prFwImageInFo->u4Region2Address; + prInitCmdWifiStart->u4Region2CRC = + prFwImageInFo->u4Region2CRC; + prInitCmdWifiStart->u4Region2length = + prFwImageInFo->u4Region2length; + + while (1) { + /* 5.1 Acquire TX Resource */ + if (nicTxAcquireResource(prAdapter, ucTC, + nicTxGetPageCount(prAdapter, + prCmdInfo->u2InfoBufLen, TRUE), + TRUE) == WLAN_STATUS_RESOURCES) { + if (nicTxPollingResource(prAdapter, + ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "Fail to get TX resource return within timeout\n"); + break; + } + continue; + + } + /* 5.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo, + prChipInfo->u2TxInitCmdPort) + != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "Fail to transmit WIFI start command\n"); + } + + break; + }; + + DBGLOG(INIT, INFO, "FW_START CMD send, waiting for RSP\n"); + + u4Status = wlanConfigWifiFuncStatus(prAdapter, ucCmdSeqNum); + + if (u4Status != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "FW_START EVT failed\n"); + else + DBGLOG(INIT, INFO, "FW_START EVT success!!\n"); + + + /* 6. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} +#endif +#if 0 +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is used to generate CRC32 checksum + * + * @param buf Pointer to the data. + * @param len data length + * + * @return crc32 value + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanCRC32(uint8_t *buf, uint32_t len) +{ + uint32_t i, crc32 = 0xFFFFFFFF; + const uint32_t 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 + +uint32_t wlanGetHarvardTailerInfo(IN struct ADAPTER + *prAdapter, IN void *prFwBuffer, IN uint32_t u4FwSize, + IN uint32_t ucTotSecNum, IN enum ENUM_IMG_DL_IDX_T eDlIdx) +{ + struct TAILER_FORMAT_T *prTailers; + uint8_t *pucStartPtr; + uint32_t u4SecIdx; + uint8_t aucBuf[32]; + + pucStartPtr = prFwBuffer + u4FwSize - sizeof( + struct TAILER_FORMAT_T) * ucTotSecNum; + if (eDlIdx == IMG_DL_IDX_N9_FW) { + kalMemCopy(&prAdapter->rVerInfo.rN9tailer, pucStartPtr, + sizeof(struct TAILER_FORMAT_T) * ucTotSecNum); + prTailers = prAdapter->rVerInfo.rN9tailer; + } else { + kalMemCopy(&prAdapter->rVerInfo.rCR4tailer, pucStartPtr, + sizeof(struct TAILER_FORMAT_T) * ucTotSecNum); + prTailers = prAdapter->rVerInfo.rCR4tailer; + } + + for (u4SecIdx = 0; u4SecIdx < ucTotSecNum; u4SecIdx++) { + /* Dump image information */ + DBGLOG(INIT, INFO, + "%s Section[%d]: chip_info[%u:E%u] feature[0x%02X]\n", + (eDlIdx == IMG_DL_IDX_N9_FW) ? "N9" : "CR4", u4SecIdx, + prTailers[u4SecIdx].chip_info, + prTailers[u4SecIdx].eco_code + 1, + prTailers[u4SecIdx].feature_set); + + kalMemZero(aucBuf, 32); + kalStrnCpy(aucBuf, prTailers[u4SecIdx].ram_version, + sizeof(prTailers[u4SecIdx].ram_version)); + DBGLOG(INIT, INFO, "date[%s] version[%s]\n", + prTailers[u4SecIdx].ram_built_date, aucBuf); + } + + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanGetConnacTailerInfo(IN struct ADAPTER + *prAdapter, IN void *prFwBuffer, + IN uint32_t u4FwSize, IN enum ENUM_IMG_DL_IDX_T eDlIdx) +{ + struct WIFI_VER_INFO *prVerInfo = &prAdapter->rVerInfo; + struct TAILER_COMMON_FORMAT_T *prComTailer; + struct TAILER_REGION_FORMAT_T *prRegTailer; + uint8_t *pucImgPtr; + uint8_t *pucTailertPtr; + uint8_t *pucStartPtr; + uint32_t u4SecIdx; + uint8_t aucBuf[32]; + + pucImgPtr = prFwBuffer; + pucStartPtr = prFwBuffer + u4FwSize - + sizeof(struct TAILER_COMMON_FORMAT_T); + prComTailer = (struct TAILER_COMMON_FORMAT_T *) pucStartPtr; + kalMemCopy(&prVerInfo->rCommonTailer, prComTailer, + sizeof(struct TAILER_COMMON_FORMAT_T)); + + kalMemZero(aucBuf, 32); + kalStrnCpy(aucBuf, prComTailer->aucRamVersion, + sizeof(prComTailer->aucRamVersion)); + + /* Dump image information */ + DBGLOG(INIT, INFO, + "%s: chip_info[%u:E%u] region_num[%d] date[%s] version[%s]\n", + (eDlIdx == IMG_DL_IDX_N9_FW) ? "N9" : "CR4", + prComTailer->ucChipInfo, + prComTailer->ucEcoCode + 1, + prComTailer->ucRegionNum, + prComTailer->aucRamBuiltDate, + aucBuf); + + if (prComTailer->ucRegionNum > MAX_FWDL_SECTION_NUM) { + DBGLOG(INIT, INFO, + "Regions number[%d] > max section number[%d]\n", + prComTailer->ucRegionNum, MAX_FWDL_SECTION_NUM); + return WLAN_STATUS_FAILURE; + } + + pucStartPtr -= (prComTailer->ucRegionNum * + sizeof(struct TAILER_REGION_FORMAT_T)); + pucTailertPtr = pucStartPtr; + for (u4SecIdx = 0; u4SecIdx < prComTailer->ucRegionNum; u4SecIdx++) { + prRegTailer = (struct TAILER_REGION_FORMAT_T *) pucStartPtr; + kalMemCopy(&prVerInfo->rRegionTailers[u4SecIdx], + prRegTailer, sizeof(struct TAILER_REGION_FORMAT_T)); + + /* Dump image information */ + DBGLOG(INIT, TRACE, + "Region[%d]: addr[0x%08X] feature[0x%02X] size[%u]\n", + u4SecIdx, prRegTailer->u4Addr, + prRegTailer->ucFeatureSet, prRegTailer->u4Len); + DBGLOG(INIT, TRACE, + "uncompress_crc[0x%08X] uncompress_size[0x%08X] block_size[0x%08X]\n", + prRegTailer->u4CRC, prRegTailer->u4RealSize, + prRegTailer->u4BlockSize); + pucImgPtr += prRegTailer->u4Len; + pucStartPtr += sizeof(struct TAILER_REGION_FORMAT_T); + } + + if (prComTailer->ucFormatFlag && pucImgPtr < pucTailertPtr) + fwDlGetReleaseInfoSection(prAdapter, pucImgPtr); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is used to extract the wifi ram code start address + * + * @param prVerInfo Pointer to the P_WIFI_VER_INFO_T structure. + * + * @return addr The ram code entry address. + * 0: use firmware defaut setting + * others: use it as the start address + */ +/*----------------------------------------------------------------------------*/ + +uint32_t wlanDetectRamEntry(IN struct WIFI_VER_INFO + *prVerInfo) +{ + uint32_t addr = 0; + uint32_t u4SecIdx; + struct TAILER_COMMON_FORMAT_T *prComTailer = + &prVerInfo->rCommonTailer; + struct TAILER_REGION_FORMAT_T *prRegTailer; + + for (u4SecIdx = 0; u4SecIdx < prComTailer->ucRegionNum; + u4SecIdx++) { + prRegTailer = &(prVerInfo->rRegionTailers[u4SecIdx]); + + if (prRegTailer->ucFeatureSet & + DOWNLOAD_CONFIG_VALID_RAM_ENTRY) { + addr = prRegTailer->u4Addr; + break; + } + } + + return addr; +} + +uint32_t wlanHarvardFormatDownload(IN struct ADAPTER + *prAdapter, IN enum ENUM_IMG_DL_IDX_T eDlIdx) +{ + uint32_t u4FwSize = 0; + void *prFwBuffer = NULL; + uint32_t rDlStatus = 0; + uint32_t rCfgStatus = 0; + uint32_t ucTotSecNum; + uint8_t ucPDA; +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + u_int8_t fgIsCompressed = FALSE; + struct INIT_CMD_WIFI_DECOMPRESSION_START rFwImageInFo; +#else + u_int8_t fgIsDynamicMemMap = FALSE; +#endif + + if (eDlIdx == IMG_DL_IDX_N9_FW) { + ucTotSecNum = N9_FWDL_SECTION_NUM; + ucPDA = PDA_N9; + } else { + ucTotSecNum = CR4_FWDL_SECTION_NUM; + ucPDA = PDA_CR4; + } + + kalFirmwareImageMapping(prAdapter->prGlueInfo, &prFwBuffer, + &u4FwSize, eDlIdx); + if (prFwBuffer == NULL) { + DBGLOG(INIT, WARN, "FW[%u] load error!\n", eDlIdx); + return WLAN_STATUS_FAILURE; + } + + wlanGetHarvardTailerInfo(prAdapter, prFwBuffer, u4FwSize, + ucTotSecNum, eDlIdx); +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + rDlStatus = wlanCompressedImageSectionDownloadStage( + prAdapter, prFwBuffer, u4FwSize, ucTotSecNum, + eDlIdx, &fgIsCompressed, &rFwImageInFo); + if (eDlIdx == IMG_DL_IDX_CR4_FW) + prAdapter->fgIsCr4FwDownloaded = TRUE; + if (fgIsCompressed == TRUE) + rCfgStatus = wlanCompressedFWConfigWifiFunc(prAdapter, + FALSE, 0, ucPDA, &rFwImageInFo); + else + rCfgStatus = wlanConfigWifiFunc(prAdapter, FALSE, 0, ucPDA); +#else + rDlStatus = wlanImageSectionDownloadStage(prAdapter, + prFwBuffer, u4FwSize, ucTotSecNum, eDlIdx, + &fgIsDynamicMemMap); + if (eDlIdx == IMG_DL_IDX_CR4_FW) + prAdapter->fgIsCr4FwDownloaded = TRUE; + rCfgStatus = wlanConfigWifiFunc(prAdapter, FALSE, 0, ucPDA); +#endif + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, NULL, + prFwBuffer); + + if ((rDlStatus != WLAN_STATUS_SUCCESS) + || (rCfgStatus != WLAN_STATUS_SUCCESS)) + return WLAN_STATUS_FAILURE; + + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanConnacFormatDownload(IN struct ADAPTER + *prAdapter, IN enum ENUM_IMG_DL_IDX_T eDlIdx) +{ + void *prFwBuffer = NULL; + uint32_t u4FwSize = 0; + uint32_t ram_entry = 0; + uint32_t rDlStatus = 0; + uint32_t rCfgStatus = 0; + uint8_t ucRegionNum; + uint8_t ucPDA; + u_int8_t fgIsDynamicMemMap = FALSE; + + kalFirmwareImageMapping(prAdapter->prGlueInfo, &prFwBuffer, + &u4FwSize, eDlIdx); + if (prFwBuffer == NULL) { + DBGLOG(INIT, WARN, "FW[%u] load error!\n", eDlIdx); + return WLAN_STATUS_FAILURE; + } + + if (wlanGetConnacTailerInfo(prAdapter, prFwBuffer, u4FwSize, + eDlIdx) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, WARN, "Get tailer info error!\n"); + rDlStatus = WLAN_STATUS_FAILURE; + goto exit; + } + + if (prAdapter->chip_info->checkbushang) { + if (prAdapter->chip_info->checkbushang((void *) prAdapter, + TRUE) != 0) { + DBGLOG(INIT, WARN, "Check bus hang failed.\n"); + rDlStatus = WLAN_STATUS_FAILURE; + goto exit; + } + } + + ucRegionNum = prAdapter->rVerInfo.rCommonTailer.ucRegionNum; + ucPDA = (eDlIdx == IMG_DL_IDX_N9_FW) ? PDA_N9 : PDA_CR4; + + rDlStatus = wlanImageSectionDownloadStage(prAdapter, + prFwBuffer, u4FwSize, ucRegionNum, eDlIdx, + &fgIsDynamicMemMap); + + ram_entry = wlanDetectRamEntry(&prAdapter->rVerInfo); + +/* To support dynamic memory map for WiFi RAM code download::Begin */ +#if (CFG_DOWNLOAD_DYN_MEMORY_MAP == 1) + if (fgIsDynamicMemMap) + rCfgStatus = wlanRamCodeDynMemMapSendComplete(prAdapter, + (ram_entry == 0) ? FALSE : TRUE, + ram_entry, ucPDA); + else + rCfgStatus = wlanConfigWifiFunc(prAdapter, + (ram_entry == 0) ? FALSE : TRUE, + ram_entry, ucPDA); +#else + rCfgStatus = wlanConfigWifiFunc(prAdapter, + (ram_entry == 0) ? FALSE : TRUE, + ram_entry, ucPDA); +#endif +/* To support dynamic memory map for WiFi RAM code download::End */ + +exit: + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, NULL, + prFwBuffer); + + if ((rDlStatus != WLAN_STATUS_SUCCESS) + || (rCfgStatus != WLAN_STATUS_SUCCESS)) + return WLAN_STATUS_FAILURE; + + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanDownloadFW(IN struct ADAPTER *prAdapter) +{ + uint32_t rStatus = 0; + u_int8_t fgReady; + struct mt66xx_chip_info *prChipInfo; + struct FWDL_OPS_T *prFwDlOps; +#if (CFG_SUPPORT_CONNINFRA == 1) + uint32_t rPccifstatus = 0; +#endif + + if (!prAdapter) + return WLAN_STATUS_FAILURE; + + prChipInfo = prAdapter->chip_info; + prFwDlOps = prChipInfo->fw_dl_ops; + + DBGLOG(INIT, INFO, + "wlanDownloadFW:: Check ready_bits(=0x%x)\n", + prChipInfo->sw_ready_bits); + HAL_WIFI_FUNC_READY_CHECK(prAdapter, + prChipInfo->sw_ready_bits, &fgReady); + + if (fgReady) { + DBGLOG(INIT, INFO, + "Wi-Fi is already ON!, turn off before FW DL!\n"); + + if (wlanPowerOffWifi(prAdapter) != WLAN_STATUS_SUCCESS) + return WLAN_STATUS_FAILURE; + + nicpmWakeUpWiFi(prAdapter); + HAL_HIF_INIT(prAdapter); + } + + HAL_ENABLE_FWDL(prAdapter, TRUE); + + if (prFwDlOps->downloadPatch) + prFwDlOps->downloadPatch(prAdapter); + + if (prFwDlOps->phyAction) + prFwDlOps->phyAction(prAdapter); + + if (prChipInfo->coantVFE28En) + prChipInfo->coantVFE28En(prAdapter); + + DBGLOG(INIT, INFO, "FW download Start\n"); +#if (CFG_SUPPORT_CONNINFRA == 1) + if (prChipInfo->coexpccifon) { + rPccifstatus = prChipInfo->coexpccifon(); + if (rPccifstatus != 0) + DBGLOG(INIT, WARN, "pccif on fail\n"); + } +#endif + + if (prFwDlOps->downloadFirmware) { + rStatus = prFwDlOps->downloadFirmware(prAdapter, + IMG_DL_IDX_N9_FW); + if ((prChipInfo->is_support_cr4 || prChipInfo->is_support_wacpu) + && rStatus == WLAN_STATUS_SUCCESS) + rStatus = prFwDlOps->downloadFirmware(prAdapter, + IMG_DL_IDX_CR4_FW); + } else { + DBGLOG(INIT, WARN, "Without downlaod firmware Ops\n"); +#if (CFG_SUPPORT_CONNINFRA == 1) + if (prChipInfo->coexpccifoff) { + prChipInfo->coexpccifoff(); + DBGLOG(INIT, TRACE, "pccif off\n"); + } +#endif + } + DBGLOG(INIT, TRACE, "FW download End\n"); + + HAL_ENABLE_FWDL(prAdapter, FALSE); + + + return rStatus; +} + +uint32_t wlanDownloadPatch(IN struct ADAPTER *prAdapter) +{ + uint32_t u4FwSize = 0; + void *prFwBuffer = NULL; + uint32_t u4Status; +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + uint8_t ucIsCompressed; +#else + u_int8_t fgIsDynamicMemMap = FALSE; +#endif + if (!prAdapter) + return WLAN_STATUS_FAILURE; + + + DBGLOG(INIT, INFO, "Patch download start\n"); + + prAdapter->rVerInfo.fgPatchIsDlByDrv = FALSE; + + kalFirmwareImageMapping(prAdapter->prGlueInfo, &prFwBuffer, + &u4FwSize, IMG_DL_IDX_PATCH); + if (prFwBuffer == NULL) { + DBGLOG(INIT, WARN, "FW[%u] load error!\n", + IMG_DL_IDX_PATCH); + return WLAN_STATUS_FAILURE; + } + +#if (CFG_ROM_PATCH_NO_SEM_CTRL == 0) +#pragma message("ROM code supports SEM-CTRL for ROM patch download") + if (wlanPatchIsDownloaded(prAdapter)) { + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, NULL, + prFwBuffer); + DBGLOG(INIT, INFO, "No need to download patch\n"); + return WLAN_STATUS_SUCCESS; + } +#else +#pragma message("ROM code supports no SEM-CTRL for ROM patch download") +#endif + + /* Patch DL */ + do { +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + u4Status = wlanCompressedImageSectionDownloadStage( + prAdapter, prFwBuffer, u4FwSize, 1, + IMG_DL_IDX_PATCH, &ucIsCompressed, NULL); +#else + u4Status = wlanImageSectionDownloadStage( + prAdapter, prFwBuffer, u4FwSize, 1, IMG_DL_IDX_PATCH, + &fgIsDynamicMemMap); +#endif + +/* Dynamic memory map::Begin */ +#if (CFG_DOWNLOAD_DYN_MEMORY_MAP == 1) + if (u4Status == WLAN_STATUS_SUCCESS) + wlanPatchDynMemMapSendComplete(prAdapter); + else if (u4Status == WLAN_STATUS_NOT_ACCEPTED) + u4Status = WLAN_STATUS_SUCCESS; /* already download*/ +#else + wlanPatchSendComplete(prAdapter); +#endif +/* Dynamic memory map::End */ + + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, NULL, + prFwBuffer); + + prAdapter->rVerInfo.fgPatchIsDlByDrv = TRUE; + } while (0); + + DBGLOG(INIT, INFO, "Patch download end[%d].\n", u4Status); + + return u4Status; +} + +uint32_t wlanGetPatchInfo(IN struct ADAPTER *prAdapter) +{ + uint32_t u4FwSize = 0; + void *prFwBuffer = NULL; + uint32_t u4StartOffset, u4Addr, u4Len, u4DataMode; + + if (!prAdapter) + return WLAN_STATUS_FAILURE; + + kalFirmwareImageMapping(prAdapter->prGlueInfo, &prFwBuffer, + &u4FwSize, IMG_DL_IDX_PATCH); + if (prFwBuffer == NULL) { + DBGLOG(INIT, WARN, "FW[%u] load error!\n", + IMG_DL_IDX_PATCH); + return WLAN_STATUS_FAILURE; + } + + wlanImageSectionGetPatchInfo(prAdapter, prFwBuffer, + u4FwSize, &u4StartOffset, + &u4Addr, &u4Len, &u4DataMode); + + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, NULL, + prFwBuffer); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t fwDlGetFwdlInfo(struct ADAPTER *prAdapter, + char *pcBuf, int i4TotalLen) +{ + struct WIFI_VER_INFO *prVerInfo = &prAdapter->rVerInfo; + struct FWDL_OPS_T *prFwDlOps; + uint32_t u4Offset = 0; + uint8_t aucBuf[32], aucDate[32]; + + prFwDlOps = prAdapter->chip_info->fw_dl_ops; + + kalMemZero(aucBuf, sizeof(aucBuf)); + kalStrnCpy(aucBuf, prVerInfo->aucFwBranchInfo, sizeof(aucBuf) - 1); + kalMemZero(aucDate, sizeof(aucDate)); + kalStrnCpy(aucDate, prVerInfo->aucFwDateCode, sizeof(aucDate) - 1); + + u4Offset += snprintf(pcBuf + u4Offset, + i4TotalLen - u4Offset, + "\nN9 FW version %s-%u.%u.%u[DEC] (%s)\n", + aucBuf, + (uint32_t)(prVerInfo->u2FwOwnVersion >> 8), + (uint32_t)(prVerInfo->u2FwOwnVersion & BITS(0, 7)), + prVerInfo->ucFwBuildNumber, aucDate); + + if (prFwDlOps->getFwDlInfo) + u4Offset += prFwDlOps->getFwDlInfo(prAdapter, + pcBuf + u4Offset, + i4TotalLen - u4Offset); + + if (!prVerInfo->fgPatchIsDlByDrv) { + u4Offset += snprintf(pcBuf + u4Offset, + i4TotalLen - u4Offset, + "MCU patch is not downloaded by wlan driver, read patch info\n"); +#if (CFG_MTK_ANDROID_WMT == 0) + wlanGetPatchInfo(prAdapter); +#endif + } + + kalMemZero(aucBuf, sizeof(aucBuf)); + kalMemZero(aucDate, sizeof(aucDate)); + kalStrnCpy(aucBuf, prVerInfo->rPatchHeader.aucPlatform, + sizeof(aucBuf) - 1); + kalStrnCpy(aucDate, prVerInfo->rPatchHeader.aucBuildDate, + sizeof(aucDate) - 1); + u4Offset += snprintf(pcBuf + u4Offset, + i4TotalLen - u4Offset, + "Patch platform %s version 0x%04X %s\n", + aucBuf, prVerInfo->rPatchHeader.u4PatchVersion, + aucDate); + + u4Offset += snprintf(pcBuf + u4Offset, i4TotalLen - u4Offset, + "Drv version %u.%u[DEC]\n", + (uint32_t)(prVerInfo->u2FwPeerVersion >> 8), + (uint32_t)(prVerInfo->u2FwPeerVersion & BITS(0, 7))); + return u4Offset; +} + +void fwDlGetReleaseInfoSection(struct ADAPTER *prAdapter, uint8_t *pucStartPtr) +{ + struct HEADER_RELEASE_INFO *prFirstInfo; + struct HEADER_RELEASE_INFO *prRelInfo; + uint8_t *pucCurPtr = pucStartPtr + RELEASE_INFO_SEPARATOR_LEN; + uint16_t u2Len = 0, u2Offset = 0; + uint8_t ucManifestExist = 0; + + prFirstInfo = (struct HEADER_RELEASE_INFO *)pucCurPtr; + DBGLOG(INIT, TRACE, "Release info tag[%u] len[%u]\n", + prFirstInfo->ucTag, prFirstInfo->u2Len); + + pucCurPtr += sizeof(struct HEADER_RELEASE_INFO); + while (u2Offset < prFirstInfo->u2Len) { + prRelInfo = (struct HEADER_RELEASE_INFO *)pucCurPtr; + DBGLOG(INIT, TRACE, + "Release info tag[%u] len[%u] padding[%u]\n", + prRelInfo->ucTag, prRelInfo->u2Len, + prRelInfo->ucPaddingLen); + + pucCurPtr += sizeof(struct HEADER_RELEASE_INFO); + switch (prRelInfo->ucTag) { + case 0x01: + fwDlGetReleaseManifest(prAdapter, prRelInfo, pucCurPtr); + ucManifestExist = 1; + break; + case 0x02: + if (!ucManifestExist) + fwDlGetReleaseManifest(prAdapter, + prRelInfo, pucCurPtr); + break; + default: + DBGLOG(INIT, WARN, "Not support release info tag[%u]\n", + prRelInfo->ucTag); + } + + u2Len = prRelInfo->u2Len + prRelInfo->ucPaddingLen; + pucCurPtr += u2Len; + u2Offset += u2Len + sizeof(struct HEADER_RELEASE_INFO); + } +} + +void fwDlGetReleaseManifest(struct ADAPTER *prAdapter, + struct HEADER_RELEASE_INFO *prRelInfo, + uint8_t *pucStartPtr) +{ + kalMemZero(&prAdapter->rVerInfo.aucReleaseManifest, + sizeof(prAdapter->rVerInfo.aucReleaseManifest)); + kalMemCopy(&prAdapter->rVerInfo.aucReleaseManifest, + pucStartPtr, prRelInfo->u2Len); + DBGLOG(INIT, INFO, "Release manifest: %s\n", + prAdapter->rVerInfo.aucReleaseManifest); +} + +#endif /* CFG_ENABLE_FW_DOWNLOAD */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/connac/connac.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/connac/connac.c new file mode 100644 index 0000000000000..fc418cdb9c668 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/connac/connac.c @@ -0,0 +1,389 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file connac.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. + */ + +#ifdef CONNAC + +/******************************************************************************* + * C O M P I L E 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 "connac.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +uint8_t *apucConnacFwName[] = { + (uint8_t *) CFG_FW_FILENAME "_soc1_0", + NULL +}; + +struct ECO_INFO connac_eco_table[] = { + /* HW version, ROM version, Factory version */ + {0x00, 0x00, 0xA, 0x1}, /* E1 */ + {0x00, 0x00, 0x0, 0x0} /* End of table */ +}; + +#if defined(_HIF_PCIE) || defined(_HIF_AXI) +struct PCIE_CHIP_CR_MAPPING connac_bus2chip_cr_mapping[] = { + /* chip addr, bus addr, range */ + {0x80000000, 0x00002000, 0x00001000}, /* MCU_CFG */ + + {0x50000000, 0x00004000, 0x00004000}, /* CONN_HIF (PDMA) */ + {0x50002000, 0x00005000, 0x00001000}, /* CONN_HIF (Reserved) */ + {0x5000A000, 0x00006000, 0x00001000}, /* CONN_HIF (DMASHDL) */ + {0x000E0000, 0x00007000, 0x00001000}, /* CONN_HIF_ON (HOST_CSR) */ + + {0x82060000, 0x00008000, 0x00004000}, /* WF_UMAC_TOP (PLE) */ + {0x82068000, 0x0000C000, 0x00002000}, /* WF_UMAC_TOP (PSE) */ + {0x8206C000, 0x0000E000, 0x00002000}, /* WF_UMAC_TOP (PP) */ + {0x82070000, 0x00010000, 0x00010000}, /* WF_PHY */ + {0x820F0000, 0x00020000, 0x00010000}, /* WF_LMAC_TOP */ + {0x820E0000, 0x00030000, 0x00010000}, /* WF_LMAC_TOP (WF_WTBL) */ + + {0x81000000, 0x00050000, 0x00010000}, /* BTSYS_OFF */ + {0x80070000, 0x00060000, 0x00010000}, /* GPSSYS */ + {0x40000000, 0x00070000, 0x00010000}, /* WF_SYSRAM */ + {0x00300000, 0x00080000, 0x00010000}, /* MCU_SYSRAM */ + + {0x80010000, 0x000A1000, 0x00001000}, /* CONN_MCU_DMA */ + {0x80030000, 0x000A2000, 0x00001000}, /* CONN_MCU_BTIF0 */ + {0x81030000, 0x000A3000, 0x00001000}, /* CONN_MCU_CFG_ON */ + {0x80050000, 0x000A4000, 0x00001000}, /* CONN_UART_PTA */ + {0x81040000, 0x000A5000, 0x00001000}, /* CONN_MCU_CIRQ */ + {0x81050000, 0x000A6000, 0x00001000}, /* CONN_MCU_GPT */ + {0x81060000, 0x000A7000, 0x00001000}, /* CONN_PTA */ + {0x81080000, 0x000A8000, 0x00001000}, /* CONN_MCU_WDT */ + {0x81090000, 0x000A9000, 0x00001000}, /* CONN_MCU_PDA */ + {0x810A0000, 0x000AA000, 0x00001000}, /* CONN_RDD_AHB_WRAP0 */ + {0x810B0000, 0x000AB000, 0x00001000}, /* BTSYS_ON */ + {0x810C0000, 0x000AC000, 0x00001000}, /* CONN_RBIST_TOP */ + {0x810D0000, 0x000AD000, 0x00001000}, /* CONN_RDD_AHB_WRAP0 */ + {0x820D0000, 0x000AE000, 0x00001000}, /* WFSYS_ON */ + {0x60000000, 0x000AF000, 0x00001000}, /* CONN_MCU_PDA */ + + {0x80020000, 0x000B0000, 0x00010000}, /* CONN_TOP_MISC_OFF */ + {0x81020000, 0x000C0000, 0x00010000}, /* CONN_TOP_MISC_ON */ + + {0x0, 0x0, 0x0} +}; +#endif /* _HIF_PCIE || _HIF_AXI */ + +void connacConstructFirmwarePrio(struct GLUE_INFO *prGlueInfo, + uint8_t **apucNameTable, uint8_t **apucName, + uint8_t *pucNameIdx, uint8_t ucMaxNameIdx) +{ + uint8_t ucIdx = 0; + uint8_t aucFlavor[2] = {0}; + int ret = 0; + + kalGetFwFlavor(&aucFlavor[0]); + for (ucIdx = 0; apucConnacFwName[ucIdx]; ucIdx++) { + if ((*pucNameIdx + 3) >= ucMaxNameIdx) { + /* the table is not large enough */ + DBGLOG(INIT, ERROR, + "kalFirmwareImageMapping >> file name array is not enough.\n"); + ASSERT(0); + continue; + } + + /* Type 1. WIFI_RAM_CODE_soc1_0_1_1.bin */ + ret = kalSnprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, + "%s_%u%s_%u.bin", + apucConnacFwName[ucIdx], + CFG_WIFI_IP_SET, + aucFlavor, + wlanGetEcoVersion( + prGlueInfo->prAdapter)); + if (ret >= 0 && ret < CFG_FW_NAME_MAX_LEN) + (*pucNameIdx) += 1; + else + DBGLOG(INIT, ERROR, + "[%u] kalSnprintf failed, ret: %d\n", + __LINE__, ret); + + /* Type 2. WIFI_RAM_CODE_soc1_0_1_1 */ + ret = kalSnprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, + "%s_%u%s_%u", + apucConnacFwName[ucIdx], + CFG_WIFI_IP_SET, + aucFlavor, + wlanGetEcoVersion( + prGlueInfo->prAdapter)); + if (ret >= 0 && ret < CFG_FW_NAME_MAX_LEN) + (*pucNameIdx) += 1; + else + DBGLOG(INIT, ERROR, + "[%u] kalSnprintf failed, ret: %d\n", + __LINE__, ret); + + /* Type 3. WIFI_RAM_CODE_soc1_0 */ + ret = kalSnprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s", + apucConnacFwName[ucIdx]); + if (ret >= 0 && ret < CFG_FW_NAME_MAX_LEN) + (*pucNameIdx) += 1; + else + DBGLOG(INIT, ERROR, + "[%u] kalSnprintf failed, ret: %d\n", + __LINE__, ret); + + /* Type 4. WIFI_RAM_CODE_soc1_0.bin */ + ret = kalSnprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s.bin", + apucConnacFwName[ucIdx]); + if (ret >= 0 && ret < CFG_FW_NAME_MAX_LEN) + (*pucNameIdx) += 1; + else + DBGLOG(INIT, ERROR, + "[%u] kalSnprintf failed, ret: %d\n", + __LINE__, ret); + } +} + +void connacConstructPatchName(struct GLUE_INFO *prGlueInfo, + uint8_t **apucName, uint8_t *pucNameIdx) +{ + int ret = 0; + + ret = kalSnprintf(apucName[(*pucNameIdx)], + CFG_FW_NAME_MAX_LEN, "mtsoc1_0_patch_e%x_hdr.bin", + wlanGetEcoVersion(prGlueInfo->prAdapter)); + if (ret < 0 || ret >= CFG_FW_NAME_MAX_LEN) + DBGLOG(INIT, ERROR, "kalSnprintf failed, ret: %d\n", ret); +} + +struct BUS_INFO connac_bus_info = { +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + .top_cfg_base = CONNAC_TOP_CFG_BASE, + .host_tx_ring_base = MT_TX_RING_BASE, + .host_tx_ring_ext_ctrl_base = MT_TX_RING_BASE_EXT, + .host_tx_ring_cidx_addr = MT_TX_RING_CIDX, + .host_tx_ring_didx_addr = MT_TX_RING_DIDX, + .host_tx_ring_cnt_addr = MT_TX_RING_CNT, + + .host_rx_ring_base = MT_RX_RING_BASE, + .host_rx_ring_ext_ctrl_base = MT_RX_RING_BASE_EXT, + .host_rx_ring_cidx_addr = MT_RX_RING_CIDX, + .host_rx_ring_didx_addr = MT_RX_RING_DIDX, + .host_rx_ring_cnt_addr = MT_RX_RING_CNT, + .bus2chip = connac_bus2chip_cr_mapping, + .tx_ring_fwdl_idx = 3, + .tx_ring_cmd_idx = 15, + .tx_ring0_data_idx = 0, + .tx_ring1_data_idx = 0, /* no used */ + .fw_own_clear_addr = WPDMA_INT_STA, + .fw_own_clear_bit = WPDMA_FW_CLR_OWN_INT, + .max_static_map_addr = 0x00040000, + .fgCheckDriverOwnInt = FALSE, + .u4DmaMask = 36, + + .pdmaSetup = asicPdmaConfig, + .updateTxRingMaxQuota = NULL, + .enableInterrupt = asicEnableInterrupt, + .disableInterrupt = asicDisableInterrupt, + .lowPowerOwnRead = asicLowPowerOwnRead, + .lowPowerOwnSet = asicLowPowerOwnSet, + .lowPowerOwnClear = asicLowPowerOwnClear, + .wakeUpWiFi = asicWakeUpWiFi, + .isValidRegAccess = asicIsValidRegAccess, + .getMailboxStatus = asicGetMailboxStatus, + .setDummyReg = asicSetDummyReg, + .checkDummyReg = asicCheckDummyReg, + .tx_ring_ext_ctrl = asicPdmaTxRingExtCtrl, + .rx_ring_ext_ctrl = asicPdmaRxRingExtCtrl, + .hifRst = NULL, + .initPcieInt = NULL, + .DmaShdlInit = asicPcieDmaShdlInit, + .setPdmaIntMask = asicPdmaIntMaskConfig, +#endif /* _HIF_PCIE || _HIF_AXI */ +#if defined(_HIF_USB) + .u4UdmaWlCfg_0_Addr = CONNAC_UDMA_WLCFG_0, + .u4UdmaWlCfg_1_Addr = CONNAC_UDMA_WLCFG_1, + .u4UdmaWlCfg_0 = + (UDMA_WLCFG_0_TX_EN(1) | + UDMA_WLCFG_0_RX_EN(1) | + UDMA_WLCFG_0_RX_MPSZ_PAD0(1) | + UDMA_WLCFG_0_1US_TIMER_EN(1)), + .u4device_vender_request_in = DEVICE_VENDOR_REQUEST_IN, + .u4device_vender_request_out = DEVICE_VENDOR_REQUEST_OUT, + .asicUsbSuspend = NULL, + .asicUsbResume = NULL, + .asicUsbEventEpDetected = NULL, + .asicUsbRxByteCount = NULL, + .DmaShdlInit = asicUsbDmaShdlInit, +#endif /* _HIF_USB */ +}; + +struct FWDL_OPS_T connac_fw_dl_ops = { + .constructFirmwarePrio = connacConstructFirmwarePrio, + .constructPatchName = connacConstructPatchName, +#if !CFG_MTK_ANDROID_WMT + .downloadPatch = wlanDownloadPatch, +#endif + .downloadFirmware = wlanConnacFormatDownload, + .downloadByDynMemMap = NULL, + .getFwInfo = wlanGetConnacFwInfo, + .getFwDlInfo = asicGetFwDlInfo, + .phyAction = NULL, +}; + +struct TX_DESC_OPS_T connacTxDescOps = { + .fillNicAppend = fillNicTxDescAppend, + .fillHifAppend = fillTxDescAppendByHostV2, + .fillTxByteCount = fillTxDescTxByteCount, +}; + +struct RX_DESC_OPS_T connacRxDescOps = { +}; + +#if CFG_SUPPORT_QA_TOOL +struct ATE_OPS_T connacAteOps = { + .setICapStart = connacSetICapStart, + .getICapStatus = connacGetICapStatus, + .getICapIQData = connacGetICapIQData, + .getRbistDataDumpEvent = nicExtEventICapIQData, +}; +#endif + +struct CHIP_DBG_OPS connac_debug_ops = { +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + .showPdmaInfo = halShowPdmaInfo, + .showPseInfo = halShowPseInfo, + .showPleInfo = halShowPleInfo, + .showTxdInfo = halShowTxdInfo, + .showCsrInfo = halShowHostCsrInfo, + .showDmaschInfo = halShowDmaschInfo, + .dumpMacInfo = haldumpMacInfo, +#else + .showPdmaInfo = NULL, + .showPseInfo = NULL, + .showPleInfo = NULL, + .showTxdInfo = NULL, + .showCsrInfo = NULL, + .showDmaschInfo = NULL, + .dumpMacInfo = NULL, +#endif + .showWtblInfo = NULL, + .showHifInfo = NULL, + .printHifDbgInfo = halPrintHifDbgInfo, + .show_stat_info = halShowStatInfo, +}; + +struct mt66xx_chip_info mt66xx_chip_info_connac = { + .bus_info = &connac_bus_info, + .fw_dl_ops = &connac_fw_dl_ops, + .prTxDescOps = &connacTxDescOps, + .prRxDescOps = &connacRxDescOps, +#if CFG_SUPPORT_QA_TOOL + .prAteOps = &connacAteOps, +#endif + .prDebugOps = &connac_debug_ops, + + .chip_id = CONNAC_CHIP_ID, + .should_verify_chip_id = FALSE, + .sw_sync0 = CONNAC_SW_SYNC0, + .sw_ready_bits = WIFI_FUNC_NO_CR4_READY_BITS, + .sw_ready_bit_offset = CONNAC_SW_SYNC0_RDY_OFFSET, + .patch_addr = CONNAC_PATCH_START_ADDR, + .is_support_cr4 = FALSE, + .txd_append_size = CONNAC_TX_DESC_APPEND_LENGTH, + .rxd_size = CONNAC_RX_DESC_LENGTH, + .init_evt_rxd_size = CONNAC_INIT_EVT_RX_DESC_LENGTH, + .pse_header_length = NIC_TX_PSE_HEADER_LENGTH, + .init_event_size = CONNAC_RX_INIT_EVENT_LENGTH, + .event_hdr_size = CONNAC_RX_EVENT_HDR_LENGTH, + .eco_info = connac_eco_table, + .isNicCapV1 = FALSE, + .is_support_efuse = FALSE, + + /* IP info, should be overwrite by getNicCapabalityV2 */ + .u4ChipIpVersion = CONNAC_CHIP_IP_VERSION, + .u4ChipIpConfig = CONNAC_CHIP_IP_CONFIG, + .u2ADieChipVersion = CONNAC_CHIP_ADIE_INFO, + .asicCapInit = asicCapInit, + .asicEnableFWDownload = asicEnableFWDownload, + .asicGetChipID = asicGetChipID, + .downloadBufferBin = NULL, + .is_support_hw_amsdu = FALSE, + .ucMaxSwAmsduNum = 4, + .ucMaxSwapAntenna = 2, + .workAround = 0, + + .top_hcr = TOP_HCR, + .top_hvr = TOP_HVR, + .top_fvr = TOP_FVR, + .custom_oid_interface_version = MTK_CUSTOM_OID_INTERFACE_VERSION, + .em_interface_version = MTK_EM_INTERFACE_VERSION, +}; + +struct mt66xx_hif_driver_data mt66xx_driver_data_connac = { + .chip_info = &mt66xx_chip_info_connac, +}; + +#endif /* CONNAC */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/connac2x2/connac2x2.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/connac2x2/connac2x2.c new file mode 100644 index 0000000000000..436dc442ee703 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/connac2x2/connac2x2.c @@ -0,0 +1,445 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file connac.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. + */ + +#ifdef CONNAC2X2 + +/******************************************************************************* + * C O M P I L E 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 "connac2x2.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +uint8_t *apucConnac2x2FwName[] = { + (uint8_t *) CFG_FW_FILENAME "_soc2_0", + NULL +}; + +struct ECO_INFO connac2x2_eco_table[] = { + /* HW version, ROM version, Factory version */ + {0x00, 0x00, 0xA, 0x1}, /* E1 */ + {0x00, 0x00, 0x0, 0x0} /* End of table */ +}; + +#if defined(_HIF_PCIE) || defined(_HIF_AXI) +struct PCIE_CHIP_CR_MAPPING connac2x2_bus2chip_cr_mapping[] = { + /* chip addr, bus addr, range */ + {0x80000000, 0x00002000, 0x00001000}, /* MCU_CFG */ + + {0x50000000, 0x00004000, 0x00004000}, /* CONN_HIF (PDMA) */ + {0x50002000, 0x00005000, 0x00001000}, /* CONN_HIF (Reserved) */ + {0x5000A000, 0x00006000, 0x00001000}, /* CONN_HIF (DMASHDL) */ + {0x000E0000, 0x00007000, 0x00001000}, /* CONN_HIF_ON (HOST_CSR) */ + + {0x82060000, 0x00008000, 0x00004000}, /* WF_UMAC_TOP (PLE) */ + {0x82068000, 0x0000C000, 0x00002000}, /* WF_UMAC_TOP (PSE) */ + {0x8206C000, 0x0000E000, 0x00002000}, /* WF_UMAC_TOP (PP) */ + {0x82070000, 0x00010000, 0x00010000}, /* WF_PHY */ + {0x820F0000, 0x00020000, 0x00010000}, /* WF_LMAC_TOP */ + {0x820E0000, 0x00030000, 0x00010000}, /* WF_LMAC_TOP (WF_WTBL) */ + + {0x81000000, 0x00050000, 0x00010000}, /* BTSYS_OFF */ + {0x80070000, 0x00060000, 0x00010000}, /* GPSSYS */ + {0x40000000, 0x00070000, 0x00010000}, /* WF_SYSRAM */ + {0x00300000, 0x00080000, 0x00010000}, /* MCU_SYSRAM */ + + {0x80010000, 0x000A1000, 0x00001000}, /* CONN_MCU_DMA */ + {0x80030000, 0x000A2000, 0x00001000}, /* CONN_MCU_BTIF0 */ + {0x81030000, 0x000A3000, 0x00001000}, /* CONN_MCU_CFG_ON */ + {0x80050000, 0x000A4000, 0x00001000}, /* CONN_UART_PTA */ + {0x81040000, 0x000A5000, 0x00001000}, /* CONN_MCU_CIRQ */ + {0x81050000, 0x000A6000, 0x00001000}, /* CONN_MCU_GPT */ + {0x81060000, 0x000A7000, 0x00001000}, /* CONN_PTA */ + {0x81080000, 0x000A8000, 0x00001000}, /* CONN_MCU_WDT */ + {0x81090000, 0x000A9000, 0x00001000}, /* CONN_MCU_PDA */ + {0x810A0000, 0x000AA000, 0x00001000}, /* CONN_RDD_AHB_WRAP0 */ + {0x810B0000, 0x000AB000, 0x00001000}, /* BTSYS_ON */ + {0x810C0000, 0x000AC000, 0x00001000}, /* CONN_RBIST_TOP */ + {0x810D0000, 0x000AD000, 0x00001000}, /* CONN_RDD_AHB_WRAP0 */ + {0x820D0000, 0x000AE000, 0x00001000}, /* WFSYS_ON */ + {0x60000000, 0x000AF000, 0x00001000}, /* CONN_MCU_PDA */ + + {0x80020000, 0x000B0000, 0x00010000}, /* CONN_TOP_MISC_OFF */ + {0x81020000, 0x000C0000, 0x00010000}, /* CONN_TOP_MISC_ON */ + + {0x0, 0x0, 0x0} +}; +#endif /* _HIF_PCIE || _HIF_AXI */ + +void connac2x2ShowHifInfo(IN struct ADAPTER *prAdapter) +{ + uint32_t u4Value = 0; + + /* conn2ap axi master sleep info */ + HAL_MCR_RD(prAdapter, 0xBC010, &u4Value); + DBGLOG(HAL, INFO, + "Conn2ap axi master sleep prot info: 0x%08x\n", u4Value); + + /* conn_mcu2ap axi master sleep info */ + HAL_MCR_RD(prAdapter, 0xBC014, &u4Value); + DBGLOG(HAL, INFO, + "Conn_mcu2ap axi master sleep info: 0x%08x\n", u4Value); + + /* conn2ap axi gals bus info */ + HAL_MCR_RD(prAdapter, 0xBC018, &u4Value); + DBGLOG(HAL, INFO, "Conn2ap axi gals bus info: 0x%08x\n", u4Value); + + /* conn2ap mux4to1 debug info */ + HAL_MCR_RD(prAdapter, 0xBC01C, &u4Value); + DBGLOG(HAL, INFO, "Conn2ap mux4to1 debug info: 0x%08x\n", u4Value); + + /* conn_hif_off bus busy info */ + HAL_MCR_RD(prAdapter, 0xBC020, &u4Value); + DBGLOG(HAL, INFO, "Conn_hif_off bus busy info: 0x%08x\n", u4Value); + + /* conn_hif_on misc info */ + HAL_MCR_RD(prAdapter, 0x0713C, &u4Value); + DBGLOG(HAL, INFO, "Conn_hif_on misc info: 0x%08x\n", u4Value); + + /* conn_on_host debug flag */ + HAL_MCR_RD(prAdapter, 0xC1144, &u4Value); + DBGLOG(HAL, INFO, "Conn_on_host debug flag: 0x%08x\n", u4Value); +} + +void connac2x2ConstructFirmwarePrio(struct GLUE_INFO *prGlueInfo, + uint8_t **apucNameTable, uint8_t **apucName, + uint8_t *pucNameIdx, uint8_t ucMaxNameIdx) +{ + uint8_t ucIdx = 0; + uint8_t aucFlavor[2] = {0}; + int ret = 0; + + kalGetFwFlavor(&aucFlavor[0]); + for (ucIdx = 0; apucConnac2x2FwName[ucIdx]; ucIdx++) { + if ((*pucNameIdx + 3) >= ucMaxNameIdx) { + /* the table is not large enough */ + DBGLOG(INIT, ERROR, + "kalFirmwareImageMapping >> file name array is not enough.\n"); + ASSERT(0); + continue; + } + + /* Type 1. WIFI_RAM_CODE_soc1_0_1_1.bin */ + ret = kalSnprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, + "%s_%u%s_%u.bin", + apucConnac2x2FwName[ucIdx], + CFG_WIFI_IP_SET, + aucFlavor, + wlanGetEcoVersion( + prGlueInfo->prAdapter)); + if (ret >= 0 && ret < CFG_FW_NAME_MAX_LEN) + (*pucNameIdx) += 1; + else + DBGLOG(INIT, ERROR, + "[%u] kalSnprintf failed, ret: %d\n", + __LINE__, ret); + + /* Type 2. WIFI_RAM_CODE_soc1_0_1_1 */ + ret = kalSnprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, + "%s_%u%s_%u", + apucConnac2x2FwName[ucIdx], + CFG_WIFI_IP_SET, + aucFlavor, + wlanGetEcoVersion( + prGlueInfo->prAdapter)); + if (ret >= 0 && ret < CFG_FW_NAME_MAX_LEN) + (*pucNameIdx) += 1; + else + DBGLOG(INIT, ERROR, + "[%u] kalSnprintf failed, ret: %d\n", + __LINE__, ret); + + /* Type 3. WIFI_RAM_CODE_soc1_0 */ + ret = kalSnprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s", + apucConnac2x2FwName[ucIdx]); + if (ret >= 0 && ret < CFG_FW_NAME_MAX_LEN) + (*pucNameIdx) += 1; + else + DBGLOG(INIT, ERROR, + "[%u] kalSnprintf failed, ret: %d\n", + __LINE__, ret); + + /* Type 4. WIFI_RAM_CODE_soc1_0.bin */ + ret = kalSnprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s.bin", + apucConnac2x2FwName[ucIdx]); + if (ret >= 0 && ret < CFG_FW_NAME_MAX_LEN) + (*pucNameIdx) += 1; + else + DBGLOG(INIT, ERROR, + "[%u] kalSnprintf failed, ret: %d\n", + __LINE__, ret); + } +} + +void connac2x2ConstructPatchName(struct GLUE_INFO *prGlueInfo, + uint8_t **apucName, uint8_t *pucNameIdx) +{ + int ret = 0; + + ret = kalSnprintf(apucName[(*pucNameIdx)], + CFG_FW_NAME_MAX_LEN, "mtsoc1_0_patch_e%x_hdr.bin", + wlanGetEcoVersion(prGlueInfo->prAdapter)); + if (ret < 0 || ret >= CFG_FW_NAME_MAX_LEN) + DBGLOG(INIT, ERROR, "kalSnprintf failed, ret: %d\n", ret); +} + +void connac2x2wlanCalDebugCmd(uint32_t cmd, uint32_t para) +{ + DBGLOG(RFTEST, INFO, "Cal CMD: (%d, %d) -> WMT reset\n", cmd, para); + mtk_wcn_wmt_do_reset_only(WMTDRV_TYPE_WIFI); + /* wait for reset done */ + fgIsResetting = TRUE; + do { + kalMsleep(500); + } while (kalIsResetting()); +} + +struct BUS_INFO connac2x2_bus_info = { +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + .top_cfg_base = CONNAC2X2_TOP_CFG_BASE, + .host_tx_ring_base = MT_TX_RING_BASE, + .host_tx_ring_ext_ctrl_base = MT_TX_RING_BASE_EXT, + .host_tx_ring_cidx_addr = MT_TX_RING_CIDX, + .host_tx_ring_didx_addr = MT_TX_RING_DIDX, + .host_tx_ring_cnt_addr = MT_TX_RING_CNT, + + .host_rx_ring_base = MT_RX_RING_BASE, + .host_rx_ring_ext_ctrl_base = MT_RX_RING_BASE_EXT, + .host_rx_ring_cidx_addr = MT_RX_RING_CIDX, + .host_rx_ring_didx_addr = MT_RX_RING_DIDX, + .host_rx_ring_cnt_addr = MT_RX_RING_CNT, + .bus2chip = connac2x2_bus2chip_cr_mapping, + .tx_ring_fwdl_idx = 3, + .tx_ring_cmd_idx = 15, + .tx_ring0_data_idx = 0, + /* Make sure your HIF_TX_MSDU_TOKEN_NUM is larger enough + * to support max HW(or SW) AMSDU number. + */ + .tx_ring1_data_idx = 1, + .fw_own_clear_addr = WPDMA_INT_STA, + .fw_own_clear_bit = WPDMA_FW_CLR_OWN_INT, + .max_static_map_addr = 0x000E0000, + .fgCheckDriverOwnInt = FALSE, + .u4DmaMask = 36, + + .pdmaSetup = asicPdmaConfig, + .updateTxRingMaxQuota = asicUpdatTxRingMaxQuota, + .enableInterrupt = asicEnableInterrupt, + .disableInterrupt = asicDisableInterrupt, + .lowPowerOwnRead = asicLowPowerOwnRead, + .lowPowerOwnSet = asicLowPowerOwnSet, + .lowPowerOwnClear = asicLowPowerOwnClear, + .wakeUpWiFi = asicWakeUpWiFi, + .isValidRegAccess = asicIsValidRegAccess, + .getMailboxStatus = asicGetMailboxStatus, + .setDummyReg = asicSetDummyReg, + .checkDummyReg = asicCheckDummyReg, + .tx_ring_ext_ctrl = asicPdmaTxRingExtCtrl, + .rx_ring_ext_ctrl = asicPdmaRxRingExtCtrl, + .hifRst = NULL, + .initPcieInt = NULL, + .DmaShdlInit = asicPcieDmaShdlInit, + .setPdmaIntMask = asicPdmaIntMaskConfig, +#endif /* _HIF_PCIE || _HIF_AXI */ +#if defined(_HIF_USB) + .u4UdmaWlCfg_0_Addr = CONNAC_UDMA_WLCFG_0, + .u4UdmaWlCfg_1_Addr = CONNAC_UDMA_WLCFG_1, + .u4UdmaWlCfg_0 = + (UDMA_WLCFG_0_TX_EN(1) | + UDMA_WLCFG_0_RX_EN(1) | + UDMA_WLCFG_0_RX_MPSZ_PAD0(1) | + UDMA_WLCFG_0_1US_TIMER_EN(1)), + .u4device_vender_request_in = DEVICE_VENDOR_REQUEST_IN, + .u4device_vender_request_out = DEVICE_VENDOR_REQUEST_OUT, + .asicUsbSuspend = NULL, + .asicUsbResume = NULL, + .asicUsbEventEpDetected = NULL, + .asicUsbRxByteCount = NULL, + .DmaShdlInit = NULL, /* for owner to hook */ +#endif /* _HIF_USB */ +}; + +struct FWDL_OPS_T connac2x2_fw_dl_ops = { + .constructFirmwarePrio = connac2x2ConstructFirmwarePrio, + .constructPatchName = connac2x2ConstructPatchName, +#if !CFG_MTK_ANDROID_WMT + .downloadPatch = wlanDownloadPatch, +#endif + .downloadFirmware = wlanConnacFormatDownload, + .downloadByDynMemMap = NULL, + .getFwInfo = wlanGetConnacFwInfo, + .getFwDlInfo = asicGetFwDlInfo, + .phyAction = NULL, +}; + +struct TX_DESC_OPS_T connac2x2TxDescOps = { + .fillNicAppend = fillNicTxDescAppend, + .fillHifAppend = fillTxDescAppendByHostV2, + .fillTxByteCount = fillTxDescTxByteCount, +}; + +struct RX_DESC_OPS_T connac2x2RxDescOps = { +}; + +#if CFG_SUPPORT_QA_TOOL +struct ATE_OPS_T connac2x2AteOps = { + .setICapStart = connacSetICapStart, + .getICapStatus = connacGetICapStatus, + .getICapIQData = connacGetICapIQData, + .getRbistDataDumpEvent = nicExtEventICapIQData, +}; +#endif + +struct CHIP_DBG_OPS connac2x2_debug_ops = { +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + .showPdmaInfo = halShowPdmaInfo, + .showPseInfo = halShowPseInfo, + .showPleInfo = halShowPleInfo, + .showTxdInfo = halShowTxdInfo, + .showCsrInfo = halShowHostCsrInfo, + .showDmaschInfo = halShowDmaschInfo, + .dumpMacInfo = haldumpMacInfo, + .showHifInfo = connac2x2ShowHifInfo, +#else + .showPdmaInfo = NULL, + .showPseInfo = NULL, + .showPleInfo = NULL, + .showTxdInfo = NULL, + .showCsrInfo = NULL, + .showDmaschInfo = NULL, + .dumpMacInfo = NULL, + .showHifInfo = NULL, +#endif + .showWtblInfo = NULL, + .printHifDbgInfo = halPrintHifDbgInfo, + .show_stat_info = halShowStatInfo, +}; + +struct mt66xx_chip_info mt66xx_chip_info_connac2x2 = { + .bus_info = &connac2x2_bus_info, + .fw_dl_ops = &connac2x2_fw_dl_ops, + .prTxDescOps = &connac2x2TxDescOps, + .prRxDescOps = &connac2x2RxDescOps, +#if CFG_SUPPORT_QA_TOOL + .prAteOps = &connac2x2AteOps, +#endif + .prDebugOps = &connac2x2_debug_ops, + + .chip_id = CONNAC2X2_CHIP_ID, + .should_verify_chip_id = FALSE, + .sw_sync0 = CONNAC2X2_SW_SYNC0, + .sw_ready_bits = WIFI_FUNC_NO_CR4_READY_BITS, + .sw_ready_bit_offset = CONNAC2X2_SW_SYNC0_RDY_OFFSET, + .patch_addr = CONNAC2X2_PATCH_START_ADDR, + .is_support_cr4 = FALSE, + .txd_append_size = CONNAC2X2_TX_DESC_APPEND_LENGTH, + .rxd_size = CONNAC2X2_RX_DESC_LENGTH, + .init_evt_rxd_size = CONNAC2X2_RX_DESC_LENGTH, + .pse_header_length = NIC_TX_PSE_HEADER_LENGTH, + .init_event_size = CONNAC2X2_RX_INIT_EVENT_LENGTH, + .event_hdr_size = CONNAC2X2_RX_EVENT_HDR_LENGTH, + .eco_info = connac2x2_eco_table, + .isNicCapV1 = FALSE, + .is_support_efuse = FALSE, + + /* IP info, should be overwrite by getNicCapabalityV2 */ + .u4ChipIpVersion = CONNAC_CHIP_IP_VERSION, + .u4ChipIpConfig = CONNAC_CHIP_IP_CONFIG, + .u2ADieChipVersion = CONNAC_CHIP_ADIE_INFO, + .asicCapInit = asicCapInit, + .asicEnableFWDownload = asicEnableFWDownload, + .asicGetChipID = asicGetChipID, + .downloadBufferBin = NULL, + .is_support_hw_amsdu = TRUE, + .ucMaxSwAmsduNum = 0, + /* Driver uses SOC to decide to use connac or connac2x2 configs + * But sometimes one SOC may use connac2x2 on 1x1 chip + * So we have to update the related configs for compatibility + */ + .ucMaxSwapAntenna = 2, + .workAround = 0, + + .top_hcr = TOP_HCR, + .top_hvr = TOP_HVR, + .top_fvr = TOP_FVR, + .custom_oid_interface_version = MTK_CUSTOM_OID_INTERFACE_VERSION, + .em_interface_version = MTK_EM_INTERFACE_VERSION, + + .calDebugCmd = connac2x2wlanCalDebugCmd, +}; + +struct mt66xx_hif_driver_data mt66xx_driver_data_connac2x2 = { + .chip_info = &mt66xx_chip_info_connac2x2, +}; + +#endif /* CONNAC2X2 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt6632/mt6632.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt6632/mt6632.c new file mode 100644 index 0000000000000..5acd7153add85 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt6632/mt6632.c @@ -0,0 +1,495 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file mt6632.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. + */ + +/******************************************************************************* + * C O M P I L E 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 "mt6632.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +struct ECO_INFO mt6632_eco_table[] = { + /* HW version, ROM version, Factory version, Eco version */ + {0x00, 0x00, 0xA, 0x1}, /* E1 */ + {0x00, 0x00, 0xA, 0x2}, /* E2 */ + {0x10, 0x10, 0xA, 0x3}, /* E3 */ + + {0x00, 0x00, 0x0, 0x0} /* End of table */ +}; + +#if defined(_HIF_PCIE) +struct PCIE_CHIP_CR_MAPPING mt6632_bus2chip_cr_mapping[] = { + /* chip addr, bus addr, range */ + {0x82060000, 0x00008000, 0x00000450}, /* WF_PLE */ + {0x82068000, 0x0000c000, 0x00000450}, /* WF_PSE */ + {0x8206c000, 0x0000e000, 0x00000300}, /* PP */ + {0x820d0000, 0x00020000, 0x00000200}, /* WF_AON */ + {0x820f0000, 0x00020200, 0x00000400}, /* WF_CFG */ + {0x820f0800, 0x00020600, 0x00000200}, /* WF_CFGOFF */ + {0x820f1000, 0x00020800, 0x00000200}, /* WF_TRB */ + {0x820f2000, 0x00020a00, 0x00000200}, /* WF_AGG */ + {0x820f3000, 0x00020c00, 0x00000400}, /* WF_ARB */ + {0x820f4000, 0x00021000, 0x00000200}, /* WF_TMAC */ + {0x820f5000, 0x00021200, 0x00000400}, /* WF_RMAC */ + {0x820f6000, 0x00021600, 0x00000200}, /* WF_SEC */ + {0x820f7000, 0x00021800, 0x00000200}, /* WF_DMA */ + + {0x820f8000, 0x00022000, 0x00001000}, /* WF_PF */ + {0x820f9000, 0x00023000, 0x00000400}, /* WF_WTBLON */ + {0x820f9800, 0x00023400, 0x00000200}, /* WF_WTBLOFF */ + + {0x820fa000, 0x00024000, 0x00000200}, /* WF_ETBF */ + {0x820fb000, 0x00024200, 0x00000400}, /* WF_LPON */ + {0x820fc000, 0x00024600, 0x00000200}, /* WF_INT */ + {0x820fd000, 0x00024800, 0x00000400}, /* WF_MIB */ + + {0x820fe000, 0x00025000, 0x00002000}, /* WF_MU */ + + {0x820e0000, 0x00030000, 0x00010000}, /* WF_WTBL */ + + {0x80020000, 0x00000000, 0x00002000}, /* TOP_CFG */ + {0x80000000, 0x00002000, 0x00002000}, /* MCU_CFG */ + {0x50000000, 0x00004000, 0x00004000}, /* PDMA_CFG */ + {0xA0000000, 0x00008000, 0x00008000}, /* PSE_CFG */ + {0x82070000, 0x00010000, 0x00010000}, /* WF_PHY */ + + {0x0, 0x0, 0x0} +}; +#endif /* _HIF_PCIE */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +void mt6632CapInit(IN struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + prChipInfo = prAdapter->chip_info; + + prChipInfo->u2HifTxdSize = 0; + prChipInfo->u2TxInitCmdPort = 0; + prChipInfo->u2TxFwDlPort = 0; + prChipInfo->fillHifTxDesc = NULL; + prChipInfo->ucPacketFormat = TXD_PKT_FORMAT_TXD; + prChipInfo->u4ExtraTxByteCount = 0; + prChipInfo->asicFillInitCmdTxd = asicFillInitCmdTxd; + prChipInfo->asicFillCmdTxd = asicFillCmdTxd; + prChipInfo->u2CmdTxHdrSize = sizeof(struct WIFI_CMD); + prChipInfo->u2RxSwPktBitMap = RXM_RXD_PKT_TYPE_SW_BITMAP; + prChipInfo->u2RxSwPktEvent = RXM_RXD_PKT_TYPE_SW_EVENT; + prChipInfo->u2RxSwPktFrame = RXM_RXD_PKT_TYPE_SW_FRAME; + asicInitTxdHook(prChipInfo->prTxDescOps); + asicInitRxdHook(prChipInfo->prRxDescOps); +#if CFG_SUPPORT_WIFI_SYSDVT + prAdapter->u2TxTest = TX_TEST_UNLIMITIED; + prAdapter->u2TxTestCount = 0; + prAdapter->ucTxTestUP = TX_TEST_UP_UNDEF; +#endif /* CFG_SUPPORT_WIFI_SYSDVT */ + + switch (prGlueInfo->u4InfType) { +#if defined(_HIF_PCIE) + case MT_DEV_INF_PCIE: + prChipInfo->u2TxInitCmdPort = TX_RING_FWDL_IDX_3; + prChipInfo->u2TxFwDlPort = TX_RING_FWDL_IDX_3; + break; +#endif /* _HIF_PCIE */ +#if defined(_HIF_USB) + case MT_DEV_INF_USB: + prChipInfo->u2TxInitCmdPort = USB_DATA_BULK_OUT_EP8; + prChipInfo->u2TxFwDlPort = USB_DATA_BULK_OUT_EP8; + break; +#endif /* _HIF_USB */ + default: + break; + } +} + +uint32_t mt6632GetFwDlInfo(struct ADAPTER *prAdapter, + char *pcBuf, int i4TotalLen) +{ + struct WIFI_VER_INFO *prVerInfo = &prAdapter->rVerInfo; +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + struct TAILER_FORMAT_T_2 *prTailer; +#else + struct TAILER_FORMAT_T *prTailer; +#endif + uint32_t u4Offset = 0; + uint8_t aucBuf[32]; + +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + prTailer = &prVerInfo->rN9Compressedtailer; +#else + prTailer = &prVerInfo->rN9tailer[0]; +#endif + kalMemZero(aucBuf, 32); + kalMemCopy(aucBuf, prTailer->ram_version, 10); + u4Offset += snprintf(pcBuf + u4Offset, i4TotalLen - u4Offset, + "N9 tailer version %s (%s) info %u:E%u\n", + aucBuf, prTailer->ram_built_date, prTailer->chip_info, + prTailer->eco_code + 1); + +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + prTailer = &prVerInfo->rCR4Compressedtailer; +#else + prTailer = &prVerInfo->rCR4tailer[0]; +#endif + kalMemZero(aucBuf, 32); + kalMemCopy(aucBuf, prTailer->ram_version, 10); + u4Offset += snprintf(pcBuf + u4Offset, i4TotalLen - u4Offset, + "CR4 tailer version %s (%s) info %u:E%u\n", + aucBuf, prTailer->ram_built_date, prTailer->chip_info, + prTailer->eco_code + 1); + + return u4Offset; +} + +#if defined(_HIF_PCIE) + +void mt6632PdmaConfig(struct GLUE_INFO *prGlueInfo, u_int8_t enable, + bool fgResetHif) +{ + struct BUS_INFO *prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + union WPDMA_GLO_CFG_STRUCT GloCfg; + union WPDMA_INT_MASK IntMask; + + kalDevRegRead(prGlueInfo, WPDMA_GLO_CFG, &GloCfg.word); + + kalDevRegRead(prGlueInfo, WPDMA_INT_MSK, &IntMask.word); + + if (enable == TRUE) { + GloCfg.field.EnableTxDMA = 1; + GloCfg.field.EnableRxDMA = 1; + GloCfg.field.EnTXWriteBackDDONE = 1; + GloCfg.field.WPDMABurstSIZE = 3; + GloCfg.field.omit_tx_info = 1; + GloCfg.field.fifo_little_endian = 1; + GloCfg.field.multi_dma_en = 3; + GloCfg.field.clk_gate_dis = 1; + + IntMask.field.rx_done_0 = 1; + IntMask.field.rx_done_1 = 1; + IntMask.field.tx_done = BIT(prBusInfo->tx_ring_fwdl_idx) | + BIT(prBusInfo->tx_ring_cmd_idx) | + BIT(prBusInfo->tx_ring0_data_idx)| + BIT(prBusInfo->tx_ring1_data_idx); + } else { + GloCfg.field.EnableRxDMA = 0; + GloCfg.field.EnableTxDMA = 0; + GloCfg.field.multi_dma_en = 2; + + IntMask.field.rx_done_0 = 0; + IntMask.field.rx_done_1 = 0; + IntMask.field.tx_done = 0; + } + + kalDevRegWrite(prGlueInfo, WPDMA_INT_MSK, IntMask.word); + + kalDevRegWrite(prGlueInfo, WPDMA_GLO_CFG, GloCfg.word); +} + +void mt6632LowPowerOwnRead(IN struct ADAPTER *prAdapter, + OUT u_int8_t *pfgResult) +{ + uint32_t u4RegValue; + + HAL_MCR_RD(prAdapter, WPDMA_INT_STA, &u4RegValue); + *pfgResult = ((u4RegValue & WPDMA_FW_CLR_OWN_INT) ? TRUE : FALSE); +} + +void mt6632LowPowerOwnSet(IN struct ADAPTER *prAdapter, OUT u_int8_t *pfgResult) +{ + uint32_t u4RegValue; + + HAL_MCR_WR(prAdapter, CFG_PCIE_LPCR_HOST, PCIE_LPCR_HOST_SET_OWN); + HAL_MCR_RD(prAdapter, CFG_PCIE_LPCR_HOST, &u4RegValue); + *pfgResult = (u4RegValue == 0); +} + +void mt6632LowPowerOwnClear(IN struct ADAPTER *prAdapter, + OUT u_int8_t *pfgResult) +{ + uint32_t u4RegValue; + + HAL_MCR_WR(prAdapter, CFG_PCIE_LPCR_HOST, PCIE_LPCR_HOST_CLR_OWN); + HAL_MCR_RD(prAdapter, CFG_PCIE_LPCR_HOST, &u4RegValue); + *pfgResult = (u4RegValue == 0); +} + +void mt6632EnableInterrupt(IN struct ADAPTER *prAdapter) +{ + struct BUS_INFO *prBusInfo = prAdapter->chip_info->bus_info; + union WPDMA_INT_MASK IntMask; + + HAL_MCR_RD(prAdapter, WPDMA_INT_MSK, &IntMask.word); + + IntMask.field.rx_done_0 = 1; + IntMask.field.rx_done_1 = 1; + IntMask.field.tx_done = BIT(prBusInfo->tx_ring_fwdl_idx) | + BIT(prBusInfo->tx_ring_cmd_idx) | + BIT(prBusInfo->tx_ring0_data_idx)| + BIT(prBusInfo->tx_ring1_data_idx); + IntMask.field.tx_coherent = 0; + IntMask.field.rx_coherent = 0; + IntMask.field.tx_dly_int = 0; + IntMask.field.rx_dly_int = 0; + IntMask.field.fw_clr_own = 1; + + HAL_MCR_WR(prAdapter, WPDMA_INT_MSK, IntMask.word); + + DBGLOG(HAL, TRACE, "%s [0x%08x]\n", __func__, IntMask.word); +} + +void mt6632DisableInterrupt(IN struct ADAPTER *prAdapter) +{ + union WPDMA_INT_MASK IntMask; + + ASSERT(prAdapter); + + IntMask.word = 0; + + HAL_MCR_WR(prAdapter, WPDMA_INT_MSK, IntMask.word); + HAL_MCR_RD(prAdapter, WPDMA_INT_MSK, &IntMask.word); + + DBGLOG(HAL, TRACE, "%s\n", __func__); +} + +void mt6632WakeUpWiFi(IN struct ADAPTER *prAdapter) +{ + u_int8_t fgResult; + + ASSERT(prAdapter); + + HAL_LP_OWN_RD(prAdapter, &fgResult); + + if (fgResult) + prAdapter->fgIsFwOwn = FALSE; + else + HAL_LP_OWN_CLR(prAdapter, &fgResult); +} +#endif /* _HIF_PCIE */ + +struct BUS_INFO mt6632_bus_info = { +#if defined(_HIF_PCIE) + .top_cfg_base = MT6632_TOP_CFG_BASE, + .host_tx_ring_base = MT_TX_RING_BASE, + .host_tx_ring_ext_ctrl_base = MT_TX_RING_BASE_EXT, + .host_tx_ring_cidx_addr = MT_TX_RING_CIDX, + .host_tx_ring_didx_addr = MT_TX_RING_DIDX, + .host_tx_ring_cnt_addr = MT_TX_RING_CNT, + + .host_rx_ring_base = MT_RX_RING_BASE, + .host_rx_ring_ext_ctrl_base = MT_RX_RING_BASE_EXT, + .host_rx_ring_cidx_addr = MT_RX_RING_CIDX, + .host_rx_ring_didx_addr = MT_RX_RING_DIDX, + .host_rx_ring_cnt_addr = MT_RX_RING_CNT, + .bus2chip = mt6632_bus2chip_cr_mapping, + .tx_ring_fwdl_idx = 3, + .tx_ring_cmd_idx = 2, + .tx_ring0_data_idx = 0, + .tx_ring1_data_idx = 0, /* no used */ + .fw_own_clear_addr = WPDMA_INT_STA, + .fw_own_clear_bit = WPDMA_FW_CLR_OWN_INT, + .max_static_map_addr = 0x00040000, + .fgCheckDriverOwnInt = TRUE, + .u4DmaMask = 32, + + .pdmaSetup = mt6632PdmaConfig, + .updateTxRingMaxQuota = NULL, + .enableInterrupt = mt6632EnableInterrupt, + .disableInterrupt = mt6632DisableInterrupt, + .lowPowerOwnRead = mt6632LowPowerOwnRead, + .lowPowerOwnSet = mt6632LowPowerOwnSet, + .lowPowerOwnClear = mt6632LowPowerOwnClear, + .wakeUpWiFi = mt6632WakeUpWiFi, + .isValidRegAccess = NULL, + .getMailboxStatus = NULL, + .setDummyReg = NULL, + .checkDummyReg = NULL, + .tx_ring_ext_ctrl = asicPdmaTxRingExtCtrl, + .rx_ring_ext_ctrl = asicPdmaRxRingExtCtrl, + .hifRst = NULL, + .initPcieInt = NULL, + .DmaShdlInit = NULL, +#endif /* _HIF_PCIE */ +#if defined(_HIF_USB) + .u4UdmaWlCfg_0_Addr = UDMA_WLCFG_0, + .u4UdmaWlCfg_1_Addr = UDMA_WLCFG_1, + .u4UdmaWlCfg_0 = + (UDMA_WLCFG_0_TX_EN(1) | UDMA_WLCFG_0_RX_EN(1) | + UDMA_WLCFG_0_RX_MPSZ_PAD0(1)), + .u4device_vender_request_in = DEVICE_VENDOR_REQUEST_IN, + .u4device_vender_request_out = DEVICE_VENDOR_REQUEST_OUT, + .asicUsbSuspend = NULL, + .asicUsbResume = NULL, + .asicUsbEventEpDetected = NULL, + .asicUsbRxByteCount = NULL, + .DmaShdlInit = NULL, +#endif /* _HIF_USB */ +#if defined(_HIF_SDIO) + .halTxGetFreeResource = NULL, + .halTxReturnFreeResource = NULL, + .halRestoreTxResource = NULL, + .halUpdateTxDonePendingCount = NULL, +#endif /* _HIF_SDIO */ +}; + +struct FWDL_OPS_T mt6632_fw_dl_ops = { + .constructFirmwarePrio = NULL, + .downloadPatch = NULL, + .downloadFirmware = wlanHarvardFormatDownload, + .downloadByDynMemMap = NULL, + .getFwInfo = wlanGetHarvardFwInfo, + .getFwDlInfo = mt6632GetFwDlInfo, + .phyAction = NULL, +}; + +struct TX_DESC_OPS_T mt6632TxDescOps = { + .fillNicAppend = fillNicTxDescAppendWithCR4, + .fillHifAppend = fillTxDescAppendByCR4, + .fillTxByteCount = fillTxDescTxByteCountWithCR4, +}; + +struct RX_DESC_OPS_T mt6632RxDescOps = { +}; + +#if CFG_SUPPORT_QA_TOOL +struct ATE_OPS_T mt6632AteOps = { + .setICapStart = mt6632SetICapStart, + .getICapStatus = mt6632GetICapStatus, + .getICapIQData = commonGetICapIQData, + .getRbistDataDumpEvent = nicExtEventQueryMemDump, +}; +#endif + +struct CHIP_DBG_OPS mt6632_debug_ops = { + .showPdmaInfo = NULL, + .showPseInfo = NULL, + .showPleInfo = NULL, + .showTxdInfo = NULL, + .showCsrInfo = NULL, + .showDmaschInfo = NULL, + .dumpMacInfo = NULL, + .showWtblInfo = NULL, + .showHifInfo = NULL, + .printHifDbgInfo = NULL, +}; + +/* Litien code refine to support multi chip */ +struct mt66xx_chip_info mt66xx_chip_info_mt6632 = { + .bus_info = &mt6632_bus_info, + .fw_dl_ops = &mt6632_fw_dl_ops, + .prTxDescOps = &mt6632TxDescOps, + .prRxDescOps = &mt6632RxDescOps, +#if CFG_SUPPORT_QA_TOOL + .prAteOps = &mt6632AteOps, +#endif + .prDebugOps = &mt6632_debug_ops, + + .chip_id = MT6632_CHIP_ID, + .should_verify_chip_id = TRUE, + .sw_sync0 = MT6632_SW_SYNC0, + .sw_ready_bits = WIFI_FUNC_READY_BITS, + .sw_ready_bit_offset = MT6632_SW_SYNC0_RDY_OFFSET, + .patch_addr = MT6632_PATCH_START_ADDR, + .is_support_cr4 = TRUE, + .txd_append_size = MT6632_TX_DESC_APPEND_LENGTH, + .rxd_size = MT6632_RX_DESC_LENGTH, + .init_evt_rxd_size = MT6632_RX_DESC_LENGTH, + .pse_header_length = NIC_TX_PSE_HEADER_LENGTH, + .init_event_size = MT6632_RX_INIT_EVENT_LENGTH, + .event_hdr_size = MT6632_RX_EVENT_HDR_LENGTH, + .eco_info = mt6632_eco_table, + .isNicCapV1 = TRUE, + .is_support_efuse = TRUE, + + .asicCapInit = mt6632CapInit, + .asicEnableFWDownload = NULL, + .asicGetChipID = NULL, + .downloadBufferBin = wlanDownloadBufferBin, + .features = 0, + .is_support_hw_amsdu = FALSE, + .ucMaxSwAmsduNum = 0, + .ucMaxSwapAntenna = 0, + .workAround = 0, + + .top_hcr = TOP_HCR, + .top_hvr = TOP_HVR, + .top_fvr = TOP_FVR, +}; + +struct mt66xx_hif_driver_data mt66xx_driver_data_mt6632 = { + .chip_info = &mt66xx_chip_info_mt6632, +}; diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7663/mt7663.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7663/mt7663.c new file mode 100644 index 0000000000000..d5da69ecb4b4b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7663/mt7663.c @@ -0,0 +1,321 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file mt7663.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. + */ + +#ifdef MT7663 + +/******************************************************************************* + * C O M P I L E 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 "mt7663.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#if defined(_HIF_PCIE) +static void mt7663InitPcieInt(struct GLUE_INFO *prGlueInfo) +{ + HAL_MCR_WR(prGlueInfo->prAdapter, MT_PCIE_IRQ_ENABLE, 1); +} +#endif /* _HIF_PCIE */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +struct ECO_INFO mt7663_eco_table[] = { + /* HW version, ROM version, Factory version */ + {0x00, 0x00, 0x0A, 0x01}, /* E1 */ + {0x10, 0x01, 0x0A, 0x02}, /* E2 */ + {0x00, 0x00, 0x00, 0x00} /* End of table */ +}; + +#if defined(_HIF_PCIE) +struct PCIE_CHIP_CR_MAPPING mt7663_bus2chip_cr_mapping[] = { + /* chip addr, bus addr, range */ + {0x80000000, 0x00002000, 0x00001000}, /* MCU_CFG */ + + {0x50000000, 0x00004000, 0x00004000}, /* CONN_HIF (PDMA) */ + {0x50002000, 0x00005000, 0x00001000}, /* CONN_HIF (Reserved) */ + {0x5000A000, 0x00006000, 0x00001000}, /* CONN_HIF (DMASHDL) */ + {0x000E0000, 0x00007000, 0x00001000}, /* CONN_HIF_ON (HOST_CSR) */ + + {0x82060000, 0x00008000, 0x00004000}, /* WF_UMAC_TOP (PLE) */ + {0x82068000, 0x0000C000, 0x00002000}, /* WF_UMAC_TOP (PSE) */ + {0x8206C000, 0x0000E000, 0x00002000}, /* WF_UMAC_TOP (PP) */ + {0x82070000, 0x00010000, 0x00010000}, /* WF_PHY */ + {0x820F0000, 0x00020000, 0x00010000}, /* WF_LMAC_TOP */ + {0x820E0000, 0x00030000, 0x00010000}, /* WF_LMAC_TOP (WF_WTBL) */ + + {0x81000000, 0x00050000, 0x00010000}, /* BTSYS_OFF */ + {0x80070000, 0x00060000, 0x00010000}, /* GPSSYS */ + {0x40000000, 0x00070000, 0x00010000}, /* WF_SYSRAM */ + {0x00300000, 0x00080000, 0x00010000}, /* MCU_SYSRAM */ + + {0x80010000, 0x000A1000, 0x00001000}, /* CONN_MCU_DMA */ + {0x80030000, 0x000A2000, 0x00001000}, /* CONN_MCU_BTIF0 */ + {0x81030000, 0x000A3000, 0x00001000}, /* CONN_MCU_CFG_ON */ + {0x80050000, 0x000A4000, 0x00001000}, /* CONN_UART_PTA */ + {0x81040000, 0x000A5000, 0x00001000}, /* CONN_MCU_CIRQ */ + {0x81050000, 0x000A6000, 0x00001000}, /* CONN_MCU_GPT */ + {0x81060000, 0x000A7000, 0x00001000}, /* CONN_PTA */ + {0x81080000, 0x000A8000, 0x00001000}, /* CONN_MCU_WDT */ + {0x81090000, 0x000A9000, 0x00001000}, /* CONN_MCU_PDA */ + {0x810A0000, 0x000AA000, 0x00001000}, /* CONN_RDD_AHB_WRAP0 */ + {0x810B0000, 0x000AB000, 0x00001000}, /* BTSYS_ON */ + {0x810C0000, 0x000AC000, 0x00001000}, /* CONN_RBIST_TOP */ + {0x810D0000, 0x000AD000, 0x00001000}, /* CONN_RDD_AHB_WRAP0 */ + {0x820D0000, 0x000AE000, 0x00001000}, /* WFSYS_ON */ + {0x60000000, 0x000AF000, 0x00001000}, /* CONN_MCU_PDA */ + + {0x80020000, 0x000B0000, 0x00010000}, /* CONN_TOP_MISC_OFF */ + {0x81020000, 0x000C0000, 0x00010000}, /* CONN_TOP_MISC_ON */ + {0x7c030000, 0x000F0000, 0x00010000}, /* CONN_TOP_MISC_ON */ + + {0x0, 0x0, 0x0} +}; +#endif /* _HIF_PCIE */ + +struct BUS_INFO mt7663_bus_info = { +#if defined(_HIF_PCIE) + .top_cfg_base = MT7663_TOP_CFG_BASE, + .host_tx_ring_base = MT_TX_RING_BASE, + .host_tx_ring_ext_ctrl_base = MT_TX_RING_BASE_EXT, + .host_tx_ring_cidx_addr = MT_TX_RING_CIDX, + .host_tx_ring_didx_addr = MT_TX_RING_DIDX, + .host_tx_ring_cnt_addr = MT_TX_RING_CNT, + + .host_rx_ring_base = MT_RX_RING_BASE, + .host_rx_ring_ext_ctrl_base = MT_RX_RING_BASE_EXT, + .host_rx_ring_cidx_addr = MT_RX_RING_CIDX, + .host_rx_ring_didx_addr = MT_RX_RING_DIDX, + .host_rx_ring_cnt_addr = MT_RX_RING_CNT, + .bus2chip = mt7663_bus2chip_cr_mapping, + .tx_ring_fwdl_idx = 3, + .tx_ring_cmd_idx = 15, + .tx_ring0_data_idx = 0, + .tx_ring1_data_idx = 0, + .fw_own_clear_addr = WPDMA_INT_STA, + .fw_own_clear_bit = WPDMA_FW_CLR_OWN_INT, + .max_static_map_addr = 0x00040000, + .fgCheckDriverOwnInt = FALSE, + .u4DmaMask = 36, + + .pdmaSetup = asicPdmaConfig, + .updateTxRingMaxQuota = NULL, + .enableInterrupt = asicEnableInterrupt, + .disableInterrupt = asicDisableInterrupt, + .lowPowerOwnRead = asicLowPowerOwnRead, + .lowPowerOwnSet = asicLowPowerOwnSet, + .lowPowerOwnClear = asicLowPowerOwnClearPCIe, + .wakeUpWiFi = asicWakeUpWiFi, + .isValidRegAccess = NULL, + .getMailboxStatus = asicGetMailboxStatus, + .setDummyReg = asicSetDummyReg, + .checkDummyReg = asicCheckDummyReg, + .tx_ring_ext_ctrl = asicPdmaTxRingExtCtrl, + .rx_ring_ext_ctrl = asicPdmaRxRingExtCtrl, + .hifRst = NULL, + .initPcieInt = mt7663InitPcieInt, + .DmaShdlInit = asicPcieDmaShdlInit, +#endif /* _HIF_PCIE */ +#if defined(_HIF_USB) + .u4UdmaWlCfg_0_Addr = CONNAC_UDMA_WLCFG_0, + .u4UdmaWlCfg_1_Addr = CONNAC_UDMA_WLCFG_1, + .u4UdmaWlCfg_0 = + (UDMA_WLCFG_0_TX_EN(1) | + UDMA_WLCFG_0_RX_EN(1) | + UDMA_WLCFG_0_RX_MPSZ_PAD0(1) | + UDMA_WLCFG_0_1US_TIMER_EN(1)), + .u4UdmaTxTimeout = UDMA_TX_TIMEOUT_LIMIT, + .u4device_vender_request_in = DEVICE_VENDOR_REQUEST_IN, + .u4device_vender_request_out = DEVICE_VENDOR_REQUEST_OUT, + .asicUsbSuspend = asicUsbSuspend, + .asicUsbResume = NULL, + .asicUsbEventEpDetected = asicUsbEventEpDetected, + .asicUsbRxByteCount = NULL, + .DmaShdlInit = asicUsbDmaShdlInit, +#endif /* _HIF_USB */ +#if defined(_HIF_SDIO) + .halTxGetFreeResource = halTxGetFreeResource_v1, + .halTxReturnFreeResource = halTxReturnFreeResource_v1, + .halRestoreTxResource = halRestoreTxResource_v1, + .halUpdateTxDonePendingCount = halUpdateTxDonePendingCount_v1, +#endif /* _HIF_SDIO */ +}; + +struct FWDL_OPS_T mt7663_fw_dl_ops = { + .constructFirmwarePrio = NULL, + .downloadPatch = wlanDownloadPatch, + .downloadFirmware = wlanConnacFormatDownload, + .downloadByDynMemMap = NULL, + .getFwInfo = wlanGetConnacFwInfo, + .getFwDlInfo = asicGetFwDlInfo, + .phyAction = NULL, +}; + +struct TX_DESC_OPS_T mt7663TxDescOps = { + .fillNicAppend = fillNicTxDescAppend, + .fillHifAppend = fillTxDescAppendByHostV2, + .fillTxByteCount = fillTxDescTxByteCount, +}; + +struct RX_DESC_OPS_T mt7663RxDescOps = { +}; + +#if CFG_SUPPORT_QA_TOOL +struct ATE_OPS_T mt7663AteOps = { + .setICapStart = connacSetICapStart, + .getICapStatus = connacGetICapStatus, + .getICapIQData = connacGetICapIQData, + .getRbistDataDumpEvent = nicExtEventICapIQData, +}; +#endif + +struct CHIP_DBG_OPS mt7663_debug_ops = { +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + .showPdmaInfo = halShowPdmaInfo, + .showCsrInfo = halShowHostCsrInfo, +#else + .showPdmaInfo = NULL, + .showCsrInfo = NULL, +#endif + .showPseInfo = halShowPseInfo, + .showPleInfo = halShowPleInfo, + .showTxdInfo = halShowTxdInfo, + .showDmaschInfo = halShowDmaschInfo, + .dumpMacInfo = haldumpMacInfo, + .showWtblInfo = NULL, + .showHifInfo = NULL, + .printHifDbgInfo = halPrintHifDbgInfo, +}; + +/* Litien code refine to support multi chip */ +struct mt66xx_chip_info mt66xx_chip_info_mt7663 = { + .bus_info = &mt7663_bus_info, + .fw_dl_ops = &mt7663_fw_dl_ops, + .prTxDescOps = &mt7663TxDescOps, + .prRxDescOps = &mt7663RxDescOps, +#if CFG_SUPPORT_QA_TOOL + .prAteOps = &mt7663AteOps, +#endif + .prDebugOps = &mt7663_debug_ops, + + .chip_id = MT7663_CHIP_ID, + .should_verify_chip_id = FALSE, + .sw_sync0 = MT7663_SW_SYNC0, + .sw_ready_bits = WIFI_FUNC_NO_CR4_READY_BITS, + .sw_ready_bit_offset = MT7663_SW_SYNC0_RDY_OFFSET, + .patch_addr = MT7663_PATCH_START_ADDR, + .is_support_cr4 = FALSE, + .txd_append_size = MT7663_TX_DESC_APPEND_LENGTH, + .rxd_size = MT7663_RX_DESC_LENGTH, + .init_evt_rxd_size = MT7663_RX_DESC_LENGTH, + .pse_header_length = NIC_TX_PSE_HEADER_LENGTH, + .init_event_size = MT7663_RX_INIT_EVENT_LENGTH, + .event_hdr_size = MT7663_RX_EVENT_HDR_LENGTH, + .eco_info = mt7663_eco_table, + .isNicCapV1 = FALSE, + .is_support_efuse = TRUE, + + .asicCapInit = asicCapInit, + .asicEnableFWDownload = asicEnableFWDownload, + .asicGetChipID = NULL, + .downloadBufferBin = wlanConnacDownloadBufferBin, + .is_support_hw_amsdu = TRUE, + .ucMaxSwAmsduNum = 0, + .workAround = 0, + .prTxPwrLimitFile = "TxPwrLimit_MT76x3.dat", + .ucTxPwrLimitBatchSize = 16, + + .top_hcr = TOP_HCR, + .top_hvr = TOP_HVR, + .top_fvr = TOP_FVR, + .ucMaxSwapAntenna = 0, +}; + +struct mt66xx_hif_driver_data mt66xx_driver_data_mt7663 = { + .chip_info = &mt66xx_chip_info_mt7663, +}; + +#endif /* MT7663 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7668/mt7668.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7668/mt7668.c new file mode 100644 index 0000000000000..c865d6703ab37 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7668/mt7668.c @@ -0,0 +1,571 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file mt7668.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. + */ + +/******************************************************************************* + * C O M P I L E 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 "mt7668.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +struct ECO_INFO mt7668_eco_table[] = { + /* HW version, ROM version, Factory version, Eco version */ + {0x00, 0x00, 0xA, 0x1}, /* E1 */ + {0x10, 0x01, 0xB, 0x2}, /* E2 */ + {0x11, 0x01, 0xB, 0x2}, /* E2 */ + {0x00, 0x00, 0x0, 0x0} /* End of table */ +}; + +#if defined(_HIF_PCIE) +struct PCIE_CHIP_CR_MAPPING mt7668_bus2chip_cr_mapping[] = { + /* chip addr, bus addr, range */ + {0x82060000, 0x00008000, 0x00000450}, /* WF_PLE */ + {0x82068000, 0x0000c000, 0x00000450}, /* WF_PSE */ + {0x8206c000, 0x0000e000, 0x00000300}, /* PP */ + {0x820d0000, 0x00020000, 0x00000200}, /* WF_AON */ + {0x820f0000, 0x00020200, 0x00000400}, /* WF_CFG */ + {0x820f0800, 0x00020600, 0x00000200}, /* WF_CFGOFF */ + {0x820f1000, 0x00020800, 0x00000200}, /* WF_TRB */ + {0x820f2000, 0x00020a00, 0x00000200}, /* WF_AGG */ + {0x820f3000, 0x00020c00, 0x00000400}, /* WF_ARB */ + {0x820f4000, 0x00021000, 0x00000200}, /* WF_TMAC */ + {0x820f5000, 0x00021200, 0x00000400}, /* WF_RMAC */ + {0x820f6000, 0x00021600, 0x00000200}, /* WF_SEC */ + {0x820f7000, 0x00021800, 0x00000200}, /* WF_DMA */ + + {0x820f8000, 0x00022000, 0x00001000}, /* WF_PF */ + {0x820f9000, 0x00023000, 0x00000400}, /* WF_WTBLON */ + {0x820f9800, 0x00023400, 0x00000200}, /* WF_WTBLOFF */ + + {0x820fa000, 0x00024000, 0x00000200}, /* WF_ETBF */ + {0x820fb000, 0x00024200, 0x00000400}, /* WF_LPON */ + {0x820fc000, 0x00024600, 0x00000200}, /* WF_INT */ + {0x820fd000, 0x00024800, 0x00000400}, /* WF_MIB */ + + {0x820fe000, 0x00025000, 0x00002000}, /* WF_MU */ + + {0x820e0000, 0x00030000, 0x00010000}, /* WF_WTBL */ + + {0x80020000, 0x00000000, 0x00002000}, /* TOP_CFG */ + {0x80000000, 0x00002000, 0x00002000}, /* MCU_CFG */ + {0x50000000, 0x00004000, 0x00004000}, /* PDMA_CFG */ + {0xA0000000, 0x00008000, 0x00008000}, /* PSE_CFG */ + {0x82070000, 0x00010000, 0x00010000}, /* WF_PHY */ + + {0x0, 0x0, 0x0} +}; +#endif /* _HIF_PCIE */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +void +mt7668ConstructFirmwarePrio(struct GLUE_INFO *prGlueInfo, + uint8_t **apucNameTable, uint8_t **apucName, + uint8_t *pucNameIdx, uint8_t ucMaxNameIdx) +{ + struct mt66xx_chip_info *prChipInfo = prGlueInfo->prAdapter->chip_info; + uint32_t chip_id = prChipInfo->chip_id; + uint8_t sub_idx = 0; + + for (sub_idx = 0; apucNameTable[sub_idx]; sub_idx++) { + if (((*pucNameIdx) + 3) < ucMaxNameIdx) { + /* Type 1. WIFI_RAM_CODE_MTxxxx.bin */ + snprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s%x.bin", + apucNameTable[sub_idx], chip_id); + (*pucNameIdx) += 1; + + /* Type 2. WIFI_RAM_CODE_MTxxxx */ + snprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s%x", + apucNameTable[sub_idx], chip_id); + (*pucNameIdx) += 1; + + /* Type 3. WIFI_RAM_CODE_MTxxxx_Ex.bin */ + snprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s%x_E%u.bin", + apucNameTable[sub_idx], chip_id, + wlanGetEcoVersion( + prGlueInfo->prAdapter)); + (*pucNameIdx) += 1; + + /* Type 4. WIFI_RAM_CODE_MTxxxx_Ex */ + snprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s%x_E%u", + apucNameTable[sub_idx], chip_id, + wlanGetEcoVersion( + prGlueInfo->prAdapter)); + (*pucNameIdx) += 1; + } else { + /* the table is not large enough */ + DBGLOG(INIT, ERROR, + "kalFirmwareImageMapping >> file name array is not enough.\n"); + ASSERT(0); + } + } +} + +void mt7668CapInit(IN struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + prChipInfo = prAdapter->chip_info; + + prChipInfo->u2HifTxdSize = 0; + prChipInfo->u2TxInitCmdPort = 0; + prChipInfo->u2TxFwDlPort = 0; + prChipInfo->fillHifTxDesc = NULL; + prChipInfo->ucPacketFormat = TXD_PKT_FORMAT_TXD; + prChipInfo->u4ExtraTxByteCount = 0; + prChipInfo->asicFillInitCmdTxd = asicFillInitCmdTxd; + prChipInfo->asicFillCmdTxd = asicFillCmdTxd; + prChipInfo->u2CmdTxHdrSize = sizeof(struct WIFI_CMD); + prChipInfo->u2RxSwPktBitMap = RXM_RXD_PKT_TYPE_SW_BITMAP; + prChipInfo->u2RxSwPktEvent = RXM_RXD_PKT_TYPE_SW_EVENT; + prChipInfo->u2RxSwPktFrame = RXM_RXD_PKT_TYPE_SW_FRAME; + asicInitTxdHook(prChipInfo->prTxDescOps); + asicInitRxdHook(prChipInfo->prRxDescOps); +#if CFG_SUPPORT_WIFI_SYSDVT + prAdapter->u2TxTest = TX_TEST_UNLIMITIED; + prAdapter->u2TxTestCount = 0; + prAdapter->ucTxTestUP = TX_TEST_UP_UNDEF; +#endif /* CFG_SUPPORT_WIFI_SYSDVT */ + + switch (prGlueInfo->u4InfType) { +#if defined(_HIF_PCIE) + case MT_DEV_INF_PCIE: + prChipInfo->u2TxInitCmdPort = TX_RING_FWDL_IDX_3; + prChipInfo->u2TxFwDlPort = TX_RING_FWDL_IDX_3; + break; +#endif /* _HIF_PCIE */ +#if defined(_HIF_USB) + case MT_DEV_INF_USB: + prChipInfo->u2TxInitCmdPort = USB_DATA_BULK_OUT_EP8; + prChipInfo->u2TxFwDlPort = USB_DATA_BULK_OUT_EP8; + break; +#endif /* _HIF_USB */ + default: + break; + } +} + +uint32_t mt7668GetFwDlInfo(struct ADAPTER *prAdapter, + char *pcBuf, int i4TotalLen) +{ + struct WIFI_VER_INFO *prVerInfo = &prAdapter->rVerInfo; +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + struct TAILER_FORMAT_T_2 *prTailer; +#else + struct TAILER_FORMAT_T *prTailer; +#endif + uint32_t u4Offset = 0; + uint8_t aucBuf[32]; + +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + prTailer = &prVerInfo->rN9Compressedtailer; +#else + prTailer = &prVerInfo->rN9tailer[0]; +#endif + kalMemZero(aucBuf, 32); + kalMemCopy(aucBuf, prTailer->ram_version, 10); + u4Offset += snprintf(pcBuf + u4Offset, i4TotalLen - u4Offset, + "N9 tailer version %s (%s) info %u:E%u\n", + aucBuf, prTailer->ram_built_date, prTailer->chip_info, + prTailer->eco_code + 1); + +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + prTailer = &prVerInfo->rCR4Compressedtailer; +#else + prTailer = &prVerInfo->rCR4tailer[0]; +#endif + kalMemZero(aucBuf, 32); + kalMemCopy(aucBuf, prTailer->ram_version, 10); + u4Offset += snprintf(pcBuf + u4Offset, i4TotalLen - u4Offset, + "CR4 tailer version %s (%s) info %u:E%u\n", + aucBuf, prTailer->ram_built_date, prTailer->chip_info, + prTailer->eco_code + 1); + + return u4Offset; +} + +#if defined(_HIF_PCIE) + +void mt7668PdmaConfig(struct GLUE_INFO *prGlueInfo, u_int8_t enable, + bool fgResetHif) +{ + struct BUS_INFO *prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + union WPDMA_GLO_CFG_STRUCT GloCfg; + union WPDMA_INT_MASK IntMask; + + kalDevRegRead(prGlueInfo, WPDMA_GLO_CFG, &GloCfg.word); + + kalDevRegRead(prGlueInfo, WPDMA_INT_MSK, &IntMask.word); + + if (enable == TRUE) { + /*0x4208 = 5440_1E70*/ + GloCfg.field_1.EnableTxDMA = 1; + GloCfg.field_1.EnableRxDMA = 1; + + GloCfg.field_1.WPDMABurstSIZE = 3; + GloCfg.field_1.EnTXWriteBackDDONE = 1; + + GloCfg.field_1.tx_bt_size = 1; + GloCfg.field_1.multi_dma_en = 3; + GloCfg.field_1.fifo_little_endian = 1; + + GloCfg.field_1.tx_bt_size_bit21 = 1; + GloCfg.field_1.first_token = 1; + GloCfg.field_1.omit_tx_info = 1; + GloCfg.field_1.reserve_30 = 1; + + IntMask.field.rx_done_0 = 1; + IntMask.field.rx_done_1 = 1; + IntMask.field.tx_done = BIT(prBusInfo->tx_ring_fwdl_idx) | + BIT(prBusInfo->tx_ring_cmd_idx) | + BIT(prBusInfo->tx_ring0_data_idx)| + BIT(prBusInfo->tx_ring1_data_idx); + IntMask.field.tx_dly_int = 0; + } else { + GloCfg.field_1.EnableRxDMA = 0; + GloCfg.field_1.EnableTxDMA = 0; + + IntMask.field.rx_done_0 = 0; + IntMask.field.rx_done_1 = 0; + IntMask.field.tx_done = 0; + IntMask.field.tx_dly_int = 0; + } + + kalDevRegWrite(prGlueInfo, WPDMA_INT_MSK, IntMask.word); + kalDevRegWrite(prGlueInfo, WPDMA_GLO_CFG, GloCfg.word); + + + /* new PDMA */ + /* 0x4260 = 0000_0005 */ + kalDevRegWrite(prGlueInfo, WPDMA_PAUSE_RX_Q_TH10, 0x5); + + /* 0x4500 = 0000_0001*/ + kalDevRegWrite(prGlueInfo, MT_WPDMA_GLO_CFG_1, 0x1); + + /* 0x4510 = 000F_0000*/ + kalDevRegWrite(prGlueInfo, MT_WPDMA_TX_PRE_CFG, 0xF0000); + + /* 0x4520 = 0F7F_0000 */ + kalDevRegWrite(prGlueInfo, MT_WPDMA_RX_PRE_CFG, 0xF7F0000); + + /* 0x4530 = 0EA6_0026 */ + kalDevRegWrite(prGlueInfo, MT_WPDMA_ABT_CFG, 0x0EA60026); + + /* 0x4534 = E4E4_E4E4*/ + kalDevRegWrite(prGlueInfo, MT_WPDMA_ABT_CFG1, 0xE4E4E4E4); + +} + +void mt7668LowPowerOwnRead(IN struct ADAPTER *prAdapter, + OUT u_int8_t *pfgResult) +{ + uint32_t u4RegValue; + + HAL_MCR_RD(prAdapter, WPDMA_INT_STA, &u4RegValue); + *pfgResult = ((u4RegValue & WPDMA_FW_CLR_OWN_INT) ? TRUE : FALSE); +} + +void mt7668LowPowerOwnSet(IN struct ADAPTER *prAdapter, OUT u_int8_t *pfgResult) +{ + uint32_t u4RegValue; + + HAL_MCR_WR(prAdapter, CFG_PCIE_LPCR_HOST, PCIE_LPCR_HOST_SET_OWN); + HAL_MCR_RD(prAdapter, CFG_PCIE_LPCR_HOST, &u4RegValue); + *pfgResult = (u4RegValue == 0); +} + +void mt7668LowPowerOwnClear(IN struct ADAPTER *prAdapter, + OUT u_int8_t *pfgResult) +{ + uint32_t u4RegValue; + + HAL_MCR_WR(prAdapter, CFG_PCIE_LPCR_HOST, PCIE_LPCR_HOST_CLR_OWN); + HAL_MCR_RD(prAdapter, CFG_PCIE_LPCR_HOST, &u4RegValue); + *pfgResult = (u4RegValue == 0); +} +void mt7668EnableInterrupt(IN struct ADAPTER *prAdapter) +{ + struct BUS_INFO *prBusInfo = prAdapter->chip_info->bus_info; + union WPDMA_INT_MASK IntMask; + + HAL_MCR_RD(prAdapter, WPDMA_INT_MSK, &IntMask.word); + + IntMask.field.rx_done_0 = 1; + IntMask.field.rx_done_1 = 1; + IntMask.field.tx_done = BIT(prBusInfo->tx_ring_fwdl_idx) | + BIT(prBusInfo->tx_ring_cmd_idx) | + BIT(prBusInfo->tx_ring0_data_idx)| + BIT(prBusInfo->tx_ring1_data_idx); + IntMask.field.tx_coherent = 0; + IntMask.field.rx_coherent = 0; + IntMask.field.tx_dly_int = 0; + IntMask.field.rx_dly_int = 0; + IntMask.field.fw_clr_own = 1; + + HAL_MCR_WR(prAdapter, WPDMA_INT_MSK, IntMask.word); + + DBGLOG(HAL, TRACE, "%s [0x%08x]\n", __func__, IntMask.word); +} + +void mt7668DisableInterrupt(IN struct ADAPTER *prAdapter) +{ + union WPDMA_INT_MASK IntMask; + + ASSERT(prAdapter); + + IntMask.word = 0; + + HAL_MCR_WR(prAdapter, WPDMA_INT_MSK, IntMask.word); + HAL_MCR_RD(prAdapter, WPDMA_INT_MSK, &IntMask.word); + + DBGLOG(HAL, TRACE, "%s\n", __func__); +} + +void mt7668WakeUpWiFi(IN struct ADAPTER *prAdapter) +{ + u_int8_t fgResult; + + ASSERT(prAdapter); + + HAL_LP_OWN_RD(prAdapter, &fgResult); + + if (fgResult) + prAdapter->fgIsFwOwn = FALSE; + else + HAL_LP_OWN_CLR(prAdapter, &fgResult); +} +#endif /* _HIF_PCIE */ + +struct BUS_INFO mt7668_bus_info = { +#if defined(_HIF_PCIE) + .top_cfg_base = MT7668_TOP_CFG_BASE, + .host_tx_ring_base = MT_TX_RING_BASE, + .host_tx_ring_ext_ctrl_base = MT_TX_RING_BASE_EXT, + .host_tx_ring_cidx_addr = MT_TX_RING_CIDX, + .host_tx_ring_didx_addr = MT_TX_RING_DIDX, + .host_tx_ring_cnt_addr = MT_TX_RING_CNT, + + .host_rx_ring_base = MT_RX_RING_BASE, + .host_rx_ring_ext_ctrl_base = MT_RX_RING_BASE_EXT, + .host_rx_ring_cidx_addr = MT_RX_RING_CIDX, + .host_rx_ring_didx_addr = MT_RX_RING_DIDX, + .host_rx_ring_cnt_addr = MT_RX_RING_CNT, + .bus2chip = mt7668_bus2chip_cr_mapping, + .tx_ring_fwdl_idx = 3, + .tx_ring_cmd_idx = 2, + .tx_ring0_data_idx = 0, + .tx_ring1_data_idx = 0, + .fw_own_clear_addr = WPDMA_INT_STA, + .fw_own_clear_bit = WPDMA_FW_CLR_OWN_INT, + .max_static_map_addr = 0x00040000, + .fgCheckDriverOwnInt = FALSE, + .u4DmaMask = 32, + + .pdmaSetup = mt7668PdmaConfig, + .updateTxRingMaxQuota = NULL, + .enableInterrupt = mt7668EnableInterrupt, + .disableInterrupt = mt7668DisableInterrupt, + .lowPowerOwnRead = mt7668LowPowerOwnRead, + .lowPowerOwnSet = mt7668LowPowerOwnSet, + .lowPowerOwnClear = mt7668LowPowerOwnClear, + .wakeUpWiFi = mt7668WakeUpWiFi, + .isValidRegAccess = NULL, + .getMailboxStatus = NULL, + .setDummyReg = NULL, + .checkDummyReg = NULL, + .tx_ring_ext_ctrl = asicPdmaTxRingExtCtrl, + .rx_ring_ext_ctrl = asicPdmaRxRingExtCtrl, + .hifRst = NULL, + .initPcieInt = NULL, + .DmaShdlInit = NULL, +#endif /* _HIF_PCIE */ +#if defined(_HIF_USB) + .u4UdmaWlCfg_0_Addr = UDMA_WLCFG_0, + .u4UdmaWlCfg_1_Addr = UDMA_WLCFG_1, + .u4UdmaWlCfg_0 = + (UDMA_WLCFG_0_TX_EN(1) | UDMA_WLCFG_0_RX_EN(1) | + UDMA_WLCFG_0_RX_MPSZ_PAD0(1)), + .u4device_vender_request_in = DEVICE_VENDOR_REQUEST_IN, + .u4device_vender_request_out = DEVICE_VENDOR_REQUEST_OUT, + .asicUsbSuspend = NULL, + .asicUsbResume = NULL, + .asicUsbEventEpDetected = NULL, + .asicUsbRxByteCount = NULL, + .DmaShdlInit = NULL, +#endif /* _HIF_USB */ +#if defined(_HIF_SDIO) + .halTxGetFreeResource = NULL, + .halTxReturnFreeResource = NULL, + .halRestoreTxResource = NULL, + .halUpdateTxDonePendingCount = NULL, +#endif /* _HIF_SDIO */ +}; + +struct FWDL_OPS_T mt7668_fw_dl_ops = { + .constructFirmwarePrio = mt7668ConstructFirmwarePrio, + .downloadPatch = wlanDownloadPatch, + .downloadFirmware = wlanHarvardFormatDownload, + .downloadByDynMemMap = NULL, + .getFwInfo = wlanGetHarvardFwInfo, + .getFwDlInfo = mt7668GetFwDlInfo, + .phyAction = NULL, +}; + +struct TX_DESC_OPS_T mt7668TxDescOps = { + .fillNicAppend = fillNicTxDescAppendWithCR4, + .fillHifAppend = fillTxDescAppendByCR4, + .fillTxByteCount = fillTxDescTxByteCountWithCR4, +}; + +struct RX_DESC_OPS_T mt7668RxDescOps = { +}; + +#if CFG_SUPPORT_QA_TOOL +struct ATE_OPS_T mt7668AteOps = { + .setICapStart = mt6632SetICapStart, + .getICapStatus = mt6632GetICapStatus, + .getICapIQData = commonGetICapIQData, + .getRbistDataDumpEvent = nicExtEventQueryMemDump, +}; +#endif + +struct CHIP_DBG_OPS mt7668_debug_ops = { + .showPdmaInfo = NULL, + .showPseInfo = NULL, + .showPleInfo = NULL, + .showTxdInfo = NULL, + .showCsrInfo = NULL, + .showDmaschInfo = NULL, + .dumpMacInfo = NULL, + .showWtblInfo = NULL, + .showHifInfo = NULL, + .printHifDbgInfo = NULL, +}; + +/* Litien code refine to support multi chip */ +struct mt66xx_chip_info mt66xx_chip_info_mt7668 = { + .bus_info = &mt7668_bus_info, + .fw_dl_ops = &mt7668_fw_dl_ops, + .prTxDescOps = &mt7668TxDescOps, + .prRxDescOps = &mt7668RxDescOps, +#if CFG_SUPPORT_QA_TOOL + .prAteOps = &mt7668AteOps, +#endif + .prDebugOps = &mt7668_debug_ops, + + .chip_id = MT7668_CHIP_ID, + .should_verify_chip_id = TRUE, + .sw_sync0 = MT7668_SW_SYNC0, + .sw_ready_bits = WIFI_FUNC_READY_BITS, + .sw_ready_bit_offset = MT7668_SW_SYNC0_RDY_OFFSET, + .patch_addr = MT7668_PATCH_START_ADDR, + .is_support_cr4 = TRUE, + .txd_append_size = MT7668_TX_DESC_APPEND_LENGTH, + .rxd_size = MT7668_RX_DESC_LENGTH, + .init_evt_rxd_size = MT7668_RX_DESC_LENGTH, + .pse_header_length = NIC_TX_PSE_HEADER_LENGTH, + .init_event_size = MT7668_RX_INIT_EVENT_LENGTH, + .event_hdr_size = MT7668_RX_EVENT_HDR_LENGTH, + .eco_info = mt7668_eco_table, + .isNicCapV1 = TRUE, + .is_support_efuse = TRUE, + + .asicCapInit = mt7668CapInit, + .asicEnableFWDownload = NULL, + .asicGetChipID = NULL, + .downloadBufferBin = wlanDownloadBufferBin, + .features = 0, + .is_support_hw_amsdu = FALSE, + .ucMaxSwAmsduNum = 0, + .ucMaxSwapAntenna = 0, + .workAround = 0, + .prTxPwrLimitFile = "TxPwrLimit_MT76x8.dat", + .ucTxPwrLimitBatchSize = 32, + + .top_hcr = TOP_HCR, + .top_hvr = TOP_HVR, + .top_fvr = TOP_FVR, +}; + +struct mt66xx_hif_driver_data mt66xx_driver_data_mt7668 = { + .chip_info = &mt66xx_chip_info_mt7668, +}; + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7915/dbg_mt7915.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7915/dbg_mt7915.c new file mode 100644 index 0000000000000..9867b2fd8d7d0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7915/dbg_mt7915.c @@ -0,0 +1,967 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** + *[File] dbg_mt7915.c + *[Version] v1.0 + *[Revision Date] 2019-04-09 + *[Author] + *[Description] + * The program provides WIFI FALCON MAC Debug APIs + *[Copyright] + * Copyright (C) 2015 MediaTek Incorporation. All Rights Reserved. + ******************************************************************************/ + +#ifdef MT7915 +/******************************************************************************* + * C O M P I L E 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 "coda/mt7915/wf_ple_top.h" +#include "coda/mt7915/wf_pse_top.h" +#include "precomp.h" +#include "mt_dmac.h" +#include "wf_ple.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 struct EMPTY_QUEUE_INFO ple_queue_empty_info[] = { + {"CPU Q0", MCU_Q0_INDEX, ENUM_UMAC_CTX_Q_0}, + {"CPU Q1", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_1}, + {"CPU Q2", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_2}, + {"CPU Q3", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_3}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, /* 4~7 not defined */ + {"ALTX Q0", ENUM_UMAC_LMAC_PORT_2, + ENUM_UMAC_LMAC_PLE_TX_Q_ALTX_0}, /* Q16 */ + {"BMC Q0", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_BMC_0}, + {"BCN Q0", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_BNC_0}, + {"PSMP Q0", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_PSMP_0}, + {"ALTX Q1", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_ALTX_1}, + {"BMC Q1", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_BMC_1}, + {"BCN Q1", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_BNC_1}, + {"PSMP Q1", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_PSMP_1}, + {"NAF Q", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_NAF}, + {"NBCN Q", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_NBCN}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, /* 18~29 not defined */ + {"RLS Q", ENUM_PLE_CTRL_PSE_PORT_3, ENUM_UMAC_PLE_CTRL_P3_Q_0X1E}, + {"RLS2 Q", ENUM_PLE_CTRL_PSE_PORT_3, ENUM_UMAC_PLE_CTRL_P3_Q_0X1F} }; + +static struct EMPTY_QUEUE_INFO pse_queue_empty_info[] = { + {"CPU Q0", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_0}, + {"CPU Q1", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_1}, + {"CPU Q2", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_2}, + {"CPU Q3", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_3}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, /* 4~7 not defined */ + {"HIF Q0", ENUM_UMAC_HIF_PORT_0, 0}, /* Q8 */ + {"HIF Q1", ENUM_UMAC_HIF_PORT_0, 1}, + {"HIF Q2", ENUM_UMAC_HIF_PORT_0, 2}, + {"HIF Q3", ENUM_UMAC_HIF_PORT_0, 3}, + {"HIF Q4", ENUM_UMAC_HIF_PORT_0, 4}, + {"HIF Q5", ENUM_UMAC_HIF_PORT_0, 5}, + {NULL, 0, 0}, + {NULL, 0, 0}, /* 14~15 not defined */ + {"LMAC Q", ENUM_UMAC_LMAC_PORT_2, 0}, + {"MDP TX Q", ENUM_UMAC_LMAC_PORT_2, 1}, + {"MDP RX Q", ENUM_UMAC_LMAC_PORT_2, 2}, + {"SEC TX Q", ENUM_UMAC_LMAC_PORT_2, 3}, + {"SEC RX Q", ENUM_UMAC_LMAC_PORT_2, 4}, + {"SFD_PARK Q", ENUM_UMAC_LMAC_PORT_2, 5}, + {"MDP_TXIOC Q", ENUM_UMAC_LMAC_PORT_2, 6}, + {"MDP_RXIOC Q", ENUM_UMAC_LMAC_PORT_2, 7}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, /* 24~30 not defined */ + {"RLS Q", ENUM_PLE_CTRL_PSE_PORT_3, ENUM_UMAC_PLE_CTRL_P3_Q_0X1F} }; + +static u_int8_t *sta_ctrl_reg[] = {"ENABLE", "DISABLE", "PAUSE"}; + +static struct EMPTY_QUEUE_INFO ple_txcmd_queue_empty_info[] = { + {"AC00Q", ENUM_UMAC_LMAC_PORT_2, 0x40}, + {"AC01Q", ENUM_UMAC_LMAC_PORT_2, 0x41}, + {"AC02Q", ENUM_UMAC_LMAC_PORT_2, 0x42}, + {"AC03Q", ENUM_UMAC_LMAC_PORT_2, 0x43}, + {"AC10Q", ENUM_UMAC_LMAC_PORT_2, 0x44}, + {"AC11Q", ENUM_UMAC_LMAC_PORT_2, 0x45}, + {"AC12Q", ENUM_UMAC_LMAC_PORT_2, 0x46}, + {"AC13Q", ENUM_UMAC_LMAC_PORT_2, 0x47}, + {"AC20Q", ENUM_UMAC_LMAC_PORT_2, 0x48}, + {"AC21Q", ENUM_UMAC_LMAC_PORT_2, 0x49}, + {"AC22Q", ENUM_UMAC_LMAC_PORT_2, 0x4a}, + {"AC23Q", ENUM_UMAC_LMAC_PORT_2, 0x4b}, + {"AC30Q", ENUM_UMAC_LMAC_PORT_2, 0x4c}, + {"AC31Q", ENUM_UMAC_LMAC_PORT_2, 0x4d}, + {"AC32Q", ENUM_UMAC_LMAC_PORT_2, 0x4e}, + {"AC33Q", ENUM_UMAC_LMAC_PORT_2, 0x4f}, + {"ALTX Q0", ENUM_UMAC_LMAC_PORT_2, 0x50}, + {"TF Q0", ENUM_UMAC_LMAC_PORT_2, 0x51}, + {"TWT TSF-TF Q0", ENUM_UMAC_LMAC_PORT_2, 0x52}, + {"TWT DL Q0", ENUM_UMAC_LMAC_PORT_2, 0x53}, + {"TWT UL Q0", ENUM_UMAC_LMAC_PORT_2, 0x54}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 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 + ******************************************************************************* + */ +void mt7915_show_ple_info( + struct ADAPTER *prAdapter, + u_int8_t fgDumpTxd) +{ + u_int32_t ple_buf_ctrl, pg_sz, pg_num; + u_int32_t ple_stat[25] = {0}, pg_flow_ctrl[8] = {0}; + u_int32_t sta_pause[6] = {0}, dis_sta_map[6] = {0}; + u_int32_t fpg_cnt, ffa_cnt, fpg_head, fpg_tail, hif_max_q, hif_min_q; + u_int32_t rpg_hif, upg_hif, cpu_max_q, cpu_min_q, rpg_cpu, upg_cpu; + u_int32_t i, j; + u_int32_t ple_txcmd_stat; + + HAL_MCR_RD(prAdapter, WF_PLE_TOP_PBUF_CTRL_ADDR, &ple_buf_ctrl); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_QUEUE_EMPTY_ADDR, &ple_stat[0]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC0_QUEUE_EMPTY0_ADDR, &ple_stat[1]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC0_QUEUE_EMPTY1_ADDR, &ple_stat[2]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC0_QUEUE_EMPTY2_ADDR, &ple_stat[3]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC0_QUEUE_EMPTY3_ADDR, &ple_stat[4]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC0_QUEUE_EMPTY4_ADDR, &ple_stat[5]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC0_QUEUE_EMPTY5_ADDR, &ple_stat[6]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC1_QUEUE_EMPTY0_ADDR, &ple_stat[7]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC1_QUEUE_EMPTY1_ADDR, &ple_stat[8]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC1_QUEUE_EMPTY2_ADDR, &ple_stat[9]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC1_QUEUE_EMPTY3_ADDR, &ple_stat[10]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC1_QUEUE_EMPTY4_ADDR, &ple_stat[11]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC1_QUEUE_EMPTY5_ADDR, &ple_stat[12]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC2_QUEUE_EMPTY0_ADDR, &ple_stat[13]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC2_QUEUE_EMPTY1_ADDR, &ple_stat[14]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC2_QUEUE_EMPTY2_ADDR, &ple_stat[15]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC2_QUEUE_EMPTY3_ADDR, &ple_stat[16]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC2_QUEUE_EMPTY4_ADDR, &ple_stat[17]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC2_QUEUE_EMPTY5_ADDR, &ple_stat[18]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC3_QUEUE_EMPTY0_ADDR, &ple_stat[19]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC3_QUEUE_EMPTY1_ADDR, &ple_stat[20]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC3_QUEUE_EMPTY2_ADDR, &ple_stat[21]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC3_QUEUE_EMPTY3_ADDR, &ple_stat[22]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC3_QUEUE_EMPTY4_ADDR, &ple_stat[23]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC3_QUEUE_EMPTY5_ADDR, &ple_stat[24]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR, + &ple_txcmd_stat); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_FREEPG_CNT_ADDR, &pg_flow_ctrl[0]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_FREEPG_HEAD_TAIL_ADDR, + &pg_flow_ctrl[1]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_PG_HIF_GROUP_ADDR, &pg_flow_ctrl[2]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_HIF_PG_INFO_ADDR, &pg_flow_ctrl[3]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_PG_CPU_GROUP_ADDR, &pg_flow_ctrl[4]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_CPU_PG_INFO_ADDR, &pg_flow_ctrl[5]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_PG_HIF_TXCMD_GROUP_ADDR, + &pg_flow_ctrl[6]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_HIF_TXCMD_PG_INFO_ADDR, + &pg_flow_ctrl[7]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_DIS_STA_MAP0_ADDR, &dis_sta_map[0]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_DIS_STA_MAP1_ADDR, &dis_sta_map[1]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_DIS_STA_MAP2_ADDR, &dis_sta_map[2]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_DIS_STA_MAP3_ADDR, &dis_sta_map[3]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_DIS_STA_MAP4_ADDR, &dis_sta_map[4]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_DIS_STA_MAP5_ADDR, &dis_sta_map[5]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_STATION_PAUSE0_ADDR, &sta_pause[0]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_STATION_PAUSE1_ADDR, &sta_pause[1]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_STATION_PAUSE2_ADDR, &sta_pause[2]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_STATION_PAUSE3_ADDR, &sta_pause[3]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_STATION_PAUSE4_ADDR, &sta_pause[4]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_STATION_PAUSE5_ADDR, &sta_pause[5]); + /* Configuration Info */ + DBGLOG(HAL, INFO, "PLE Configuration Info:\n"); + + DBGLOG(HAL, INFO, "\tPacket Buffer Control(0x%08x): 0x%08x\n", + WF_PLE_TOP_PBUF_CTRL_ADDR, + ple_buf_ctrl); + pg_sz = (ple_buf_ctrl & WF_PLE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_MASK) >> + WF_PLE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_SHFT; + DBGLOG(HAL, INFO, "\t\tPage Size=%d(%d bytes per page)\n", pg_sz, + (pg_sz == 1 ? 128 : 64)); + DBGLOG(HAL, INFO, "\t\tPage Offset=%d(in unit of 2KB)\n", + (ple_buf_ctrl & WF_PLE_TOP_PBUF_CTRL_PBUF_OFFSET_MASK) >> + WF_PLE_TOP_PBUF_CTRL_PBUF_OFFSET_SHFT); + pg_num = (ple_buf_ctrl & WF_PLE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_MASK) >> + WF_PLE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_SHFT; + DBGLOG(HAL, INFO, "\t\tTotal Page=%d pages\n", pg_num); + + /* Page Flow Control */ + DBGLOG(HAL, INFO, "PLE Page Flow Control:\n"); + DBGLOG(HAL, INFO, "\tFree page counter(0x%08x): 0x%08x\n", + WF_PLE_TOP_FREEPG_CNT_ADDR, + pg_flow_ctrl[0]); + fpg_cnt = (pg_flow_ctrl[0] & WF_PLE_TOP_FREEPG_CNT_FREEPG_CNT_MASK) >> + WF_PLE_TOP_FREEPG_CNT_FREEPG_CNT_SHFT; + DBGLOG(HAL, INFO, "\t\tThe toal page number of free=0x%03x\n", fpg_cnt); + ffa_cnt = (pg_flow_ctrl[0] & WF_PLE_TOP_FREEPG_CNT_FFA_CNT_MASK) >> + WF_PLE_TOP_FREEPG_CNT_FFA_CNT_SHFT; + DBGLOG(HAL, INFO, "\t\tThe free page numbers of free for all=0x%03x\n", + ffa_cnt); + DBGLOG(HAL, INFO, "\tFree page head and tail(0x%08x): 0x%08x\n", + WF_PLE_TOP_FREEPG_HEAD_TAIL_ADDR, + pg_flow_ctrl[1]); + fpg_head = (pg_flow_ctrl[1] & + WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_MASK) >> + WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_SHFT; + fpg_tail = (pg_flow_ctrl[1] & + WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_MASK) >> + WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe tail/head page of free page list=0x%03x/0x%03x\n", + fpg_tail, fpg_head); + DBGLOG(HAL, INFO, + "\tReserved page counter of HIF group(0x%08x): 0x%08x\n", + WF_PLE_TOP_PG_HIF_GROUP_ADDR, + pg_flow_ctrl[2]); + DBGLOG(HAL, INFO, "\tHIF group page status(0x%08x): 0x%08x\n", + WF_PLE_TOP_HIF_PG_INFO_ADDR, + pg_flow_ctrl[3]); + hif_min_q = (pg_flow_ctrl[2] & + WF_PLE_TOP_PG_HIF_GROUP_HIF_MIN_QUOTA_MASK) >> + WF_PLE_TOP_PG_HIF_GROUP_HIF_MIN_QUOTA_SHFT; + hif_max_q = (pg_flow_ctrl[2] & + WF_PLE_TOP_PG_HIF_GROUP_HIF_MAX_QUOTA_MASK) >> + WF_PLE_TOP_PG_HIF_GROUP_HIF_MAX_QUOTA_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of HIF group=0x%03x/0x%03x\n", + hif_max_q, hif_min_q); + rpg_hif = (pg_flow_ctrl[3] & WF_PLE_TOP_HIF_PG_INFO_HIF_RSV_CNT_MASK) >> + WF_PLE_TOP_HIF_PG_INFO_HIF_RSV_CNT_SHFT; + upg_hif = (pg_flow_ctrl[3] & WF_PLE_TOP_HIF_PG_INFO_HIF_SRC_CNT_MASK) >> + WF_PLE_TOP_HIF_PG_INFO_HIF_SRC_CNT_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of HIF group=0x%03x/0x%03x\n", + upg_hif, rpg_hif); + + DBGLOG(HAL, INFO, + "\tReserved page counter of HIF_TXCMD group(0x%08x): 0x%08x\n", + WF_PLE_TOP_PG_HIF_WMTXD_GROUP_ADDR, + pg_flow_ctrl[6]); + DBGLOG(HAL, INFO, "\tHIF_TXCMD group page status(0x%08x): 0x%08x\n", + WF_PLE_TOP_HIF_WMTXD_PG_INFO_ADDR, + pg_flow_ctrl[7]); + cpu_min_q = (pg_flow_ctrl[6] & + WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MIN_QUOTA_MASK) >> + WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MIN_QUOTA_SHFT; + cpu_max_q = (pg_flow_ctrl[6] & + WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MAX_QUOTA_MASK) >> + WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MAX_QUOTA_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of HIF_TXCMD group=0x%03x/0x%03x\n", + cpu_max_q, cpu_min_q); + rpg_cpu = (pg_flow_ctrl[7] & + WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_SRC_CNT_MASK) >> + WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_SRC_CNT_SHFT; + upg_cpu = (pg_flow_ctrl[7] & + WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_RSV_CNT_MASK) >> + WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_RSV_CNT_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of HIF_TXCMD group=0x%03x/0x%03x\n", + upg_cpu, rpg_cpu); + + DBGLOG(HAL, INFO, + "\tReserved page counter of CPU group(0x%08x): 0x%08x\n", + WF_PLE_TOP_PG_CPU_GROUP_ADDR, + pg_flow_ctrl[4]); + DBGLOG(HAL, INFO, "\tCPU group page status(0x%08x): 0x%08x\n", + WF_PLE_TOP_CPU_PG_INFO_ADDR, + pg_flow_ctrl[5]); + cpu_min_q = (pg_flow_ctrl[4] & + WF_PLE_TOP_PG_CPU_GROUP_CPU_MIN_QUOTA_MASK) >> + WF_PLE_TOP_PG_CPU_GROUP_CPU_MIN_QUOTA_SHFT; + cpu_max_q = (pg_flow_ctrl[4] & + WF_PLE_TOP_PG_CPU_GROUP_CPU_MAX_QUOTA_MASK) >> + WF_PLE_TOP_PG_CPU_GROUP_CPU_MAX_QUOTA_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of CPU group=0x%03x/0x%03x\n", + cpu_max_q, cpu_min_q); + rpg_cpu = (pg_flow_ctrl[5] & WF_PLE_TOP_CPU_PG_INFO_CPU_RSV_CNT_MASK) >> + WF_PLE_TOP_CPU_PG_INFO_CPU_RSV_CNT_SHFT; + upg_cpu = (pg_flow_ctrl[5] & WF_PLE_TOP_CPU_PG_INFO_CPU_SRC_CNT_MASK) >> + WF_PLE_TOP_CPU_PG_INFO_CPU_SRC_CNT_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of CPU group=0x%03x/0x%03x\n", + upg_cpu, rpg_cpu); + + if ((ple_stat[0] & WF_PLE_TOP_QUEUE_EMPTY_ALL_AC_EMPTY_MASK) == 0) { + for (j = 0; j < 24; j = j + 6) { + if (j % 6 == 0) { + DBGLOG(HAL, INFO, + "\tNonempty AC%d Q of STA#: ", j / 6); + } + + for (i = 0; i < 32; i++) { + if (((ple_stat[j + 1] & (0x1 << i)) >> i) == + 0) { + DBGLOG(HAL, INFO, "%d ", + i + (j % 6) * 32); + } + } + } + + DBGLOG(HAL, INFO, "\n"); + } + + DBGLOG(HAL, INFO, "Nonempty Q info:\n"); + + for (i = 0; i < 31; i++) { + if (((ple_stat[0] & (0x1 << i)) >> i) == 0) { + uint32_t hfid, tfid, pktcnt, fl_que_ctrl[3] = {0}; + + if (ple_queue_empty_info[i].QueueName != NULL) { + DBGLOG(HAL, INFO, "\t%s: ", + ple_queue_empty_info[i].QueueName); + fl_que_ctrl[0] |= + WF_PLE_TOP_FL_QUE_CTRL_0_EXECUTE_MASK; + fl_que_ctrl[0] |= + (ple_queue_empty_info[i].Portid + << WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_SHFT); + fl_que_ctrl[0] |= + (ple_queue_empty_info[i].Queueid + << WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_SHFT); + } else + continue; + + HAL_MCR_WR(prAdapter, WF_PLE_TOP_FL_QUE_CTRL_0_ADDR, + fl_que_ctrl[0]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_FL_QUE_CTRL_2_ADDR, + &fl_que_ctrl[1]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_FL_QUE_CTRL_3_ADDR, + &fl_que_ctrl[2]); + hfid = (fl_que_ctrl[1] & + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_SHFT; + tfid = (fl_que_ctrl[1] & + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_SHFT; + pktcnt = + (fl_que_ctrl[2] & + WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_SHFT; + DBGLOG(HAL, INFO, + "tail/head fid = 0x%03x/0x%03x, pkt cnt = 0x%03x\n", + tfid, hfid, pktcnt); + if (pktcnt > 0 && fgDumpTxd) + connac2x_show_txd_Info( + prAdapter, hfid); + } + } + + for (j = 0; j < 24; j = j + 6) { /* show AC Q info */ + for (i = 0; i < 32; i++) { + if (((ple_stat[j + 1] & (0x1 << i)) >> i) == 0) { + uint32_t hfid, tfid, pktcnt, ac_num = j / 6, + ctrl = 0; + uint32_t sta_num = i + (j % 6) * 32, + fl_que_ctrl[3] = {0}; + uint32_t wmmidx = 0; + + DBGLOG(HAL, INFO, "\tSTA%d AC%d: ", sta_num, + ac_num); + + fl_que_ctrl[0] |= + WF_PLE_TOP_FL_QUE_CTRL_0_EXECUTE_MASK; + fl_que_ctrl[0] |= + (ENUM_UMAC_LMAC_PORT_2 + << WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_SHFT); + fl_que_ctrl[0] |= + (ac_num + << WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_SHFT); + fl_que_ctrl[0] |= + (sta_num + << WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_WLANID_SHFT); + HAL_MCR_WR(prAdapter, + WF_PLE_TOP_FL_QUE_CTRL_0_ADDR, + fl_que_ctrl[0]); + HAL_MCR_RD(prAdapter, + WF_PLE_TOP_FL_QUE_CTRL_2_ADDR, + &fl_que_ctrl[1]); + HAL_MCR_RD(prAdapter, + WF_PLE_TOP_FL_QUE_CTRL_3_ADDR, + &fl_que_ctrl[2]); + hfid = (fl_que_ctrl[1] & + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_SHFT; + tfid = (fl_que_ctrl[1] & + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_SHFT; + + pktcnt = + (fl_que_ctrl[2] & + WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_SHFT; + DBGLOG(HAL, INFO, + "tail/head fid = 0x%03x/0x%03x, pkt cnt = %x", + tfid, hfid, pktcnt); + + if (((sta_pause[j % 6] & 0x1 << i) >> i) == 1) + ctrl = 2; + + if (((dis_sta_map[j % 6] & 0x1 << i) >> i) == 1) + ctrl = 1; + + DBGLOG(HAL, INFO, " ctrl = %s", + sta_ctrl_reg[ctrl]); + DBGLOG(HAL, INFO, " (wmmidx=%d)\n", + wmmidx); + if (pktcnt > 0 && fgDumpTxd) + connac2x_show_txd_Info( + prAdapter, hfid); + } + } + } + + if (~ple_txcmd_stat) { + DBGLOG(HAL, INFO, "Nonempty TXCMD Q info:\n"); + for (i = 0; i < 31; i++) { + if (((ple_txcmd_stat & (0x1 << i)) >> i) == 0) { + uint32_t hfid, tfid; + uint32_t pktcnt, fl_que_ctrl[3] = {0}; + + if (ple_txcmd_queue_empty_info[i].QueueName != + NULL) { + DBGLOG(HAL, INFO, "\t%s: ", + ple_txcmd_queue_empty_info[i] + .QueueName); + fl_que_ctrl[0] |= + WF_PLE_TOP_FL_QUE_CTRL_0_EXECUTE_MASK; + fl_que_ctrl[0] |= + (ple_txcmd_queue_empty_info[i] + .Portid + << WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_SHFT); + fl_que_ctrl[0] |= + (ple_txcmd_queue_empty_info[i] + .Queueid + << WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_SHFT); + } else + continue; + + HAL_MCR_WR(prAdapter, + WF_PLE_TOP_FL_QUE_CTRL_0_ADDR, + fl_que_ctrl[0]); + HAL_MCR_RD(prAdapter, + WF_PLE_TOP_FL_QUE_CTRL_2_ADDR, + &fl_que_ctrl[1]); + HAL_MCR_RD(prAdapter, + WF_PLE_TOP_FL_QUE_CTRL_3_ADDR, + &fl_que_ctrl[2]); + hfid = (fl_que_ctrl[1] & + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_SHFT; + tfid = (fl_que_ctrl[1] & + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_SHFT; + pktcnt = + (fl_que_ctrl[2] & + WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_SHFT; + DBGLOG(HAL, INFO, "tail/head fid ="); + DBGLOG(HAL, INFO, "0x%03x/0x%03x,", tfid, hfid); + DBGLOG(HAL, INFO, "pkt cnt = 0x%03x\n", pktcnt); + } + } + } +} + +void mt7915_show_pse_info( + struct ADAPTER *prAdapter) +{ + u_int32_t pse_buf_ctrl, pg_sz, pg_num; + u_int32_t pse_stat, pg_flow_ctrl[20] = {0}; + u_int32_t fpg_cnt, ffa_cnt, fpg_head, fpg_tail; + u_int32_t max_q, min_q, rsv_pg, used_pg; + u_int32_t i; + + HAL_MCR_RD(prAdapter, WF_PSE_TOP_PBUF_CTRL_ADDR, &pse_buf_ctrl); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_QUEUE_EMPTY_ADDR, &pse_stat); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_FREEPG_CNT_ADDR, &pg_flow_ctrl[0]); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_FREEPG_HEAD_TAIL_ADDR, + &pg_flow_ctrl[1]); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_PG_HIF0_GROUP_ADDR, &pg_flow_ctrl[2]); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_HIF0_PG_INFO_ADDR, &pg_flow_ctrl[3]); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_PG_HIF1_GROUP_ADDR, &pg_flow_ctrl[4]); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_HIF1_PG_INFO_ADDR, &pg_flow_ctrl[5]); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_PG_CPU_GROUP_ADDR, &pg_flow_ctrl[6]); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_CPU_PG_INFO_ADDR, &pg_flow_ctrl[7]); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_PG_LMAC0_GROUP_ADDR, &pg_flow_ctrl[8]); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_LMAC0_PG_INFO_ADDR, &pg_flow_ctrl[9]); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_PG_LMAC1_GROUP_ADDR, + &pg_flow_ctrl[10]); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_LMAC1_PG_INFO_ADDR, &pg_flow_ctrl[11]); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_PG_LMAC2_GROUP_ADDR, + &pg_flow_ctrl[12]); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_LMAC2_PG_INFO_ADDR, &pg_flow_ctrl[13]); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_PG_PLE_GROUP_ADDR, &pg_flow_ctrl[14]); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_PLE_PG_INFO_ADDR, &pg_flow_ctrl[15]); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_PG_LMAC3_GROUP_ADDR, + &pg_flow_ctrl[16]); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_LMAC3_PG_INFO_ADDR, &pg_flow_ctrl[17]); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_PG_MDP_GROUP_ADDR, &pg_flow_ctrl[18]); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_MDP_PG_INFO_ADDR, &pg_flow_ctrl[19]); + /* Configuration Info */ + DBGLOG(HAL, INFO, "PSE Configuration Info:\n"); + DBGLOG(HAL, INFO, "\tPacket Buffer Control(0x%08x): 0x%08x\n", + WF_PSE_TOP_PBUF_CTRL_ADDR, + pse_buf_ctrl); + pg_sz = (pse_buf_ctrl & WF_PSE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_MASK) >> + WF_PSE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_SHFT; + DBGLOG(HAL, INFO, "\t\tPage Size=%d(%d bytes per page)\n", pg_sz, + (pg_sz == 1 ? 256 : 128)); + DBGLOG(HAL, INFO, "\t\tPage Offset=%d(in unit of 64KB)\n", + (pse_buf_ctrl & WF_PSE_TOP_PBUF_CTRL_PBUF_OFFSET_MASK) >> + WF_PSE_TOP_PBUF_CTRL_PBUF_OFFSET_SHFT); + pg_num = (pse_buf_ctrl & WF_PSE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_MASK) >> + WF_PSE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_SHFT; + DBGLOG(HAL, INFO, "\t\tTotal page numbers=%d pages\n", pg_num); + /* Page Flow Control */ + DBGLOG(HAL, INFO, "PSE Page Flow Control:\n"); + DBGLOG(HAL, INFO, "\tFree page counter(0x%08x): 0x%08x\n", + WF_PSE_TOP_FREEPG_CNT_ADDR, + pg_flow_ctrl[0]); + fpg_cnt = (pg_flow_ctrl[0] & WF_PSE_TOP_FREEPG_CNT_FREEPG_CNT_MASK) >> + WF_PSE_TOP_FREEPG_CNT_FREEPG_CNT_SHFT; + DBGLOG(HAL, INFO, "\t\tThe toal page number of free=0x%03x\n", fpg_cnt); + ffa_cnt = (pg_flow_ctrl[0] & WF_PSE_TOP_FREEPG_CNT_FFA_CNT_MASK) >> + WF_PSE_TOP_FREEPG_CNT_FFA_CNT_SHFT; + DBGLOG(HAL, INFO, "\t\tThe free page numbers of free for all=0x%03x\n", + ffa_cnt); + DBGLOG(HAL, INFO, "\tFree page head and tail(0x%08x): 0x%08x\n", + WF_PSE_TOP_FREEPG_HEAD_TAIL_ADDR, + pg_flow_ctrl[1]); + fpg_head = (pg_flow_ctrl[1] & + WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_MASK) >> + WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_SHFT; + fpg_tail = (pg_flow_ctrl[1] & + WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_MASK) >> + WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe tail/head page of free page list=0x%03x/0x%03x\n", + fpg_tail, fpg_head); + DBGLOG(HAL, INFO, + "\tReserved page counter of HIF0 group(0x%08x): 0x%08x\n", + WF_PSE_TOP_PG_HIF0_GROUP_ADDR, + pg_flow_ctrl[2]); + DBGLOG(HAL, INFO, "\tHIF0 group page status(0x%08x): 0x%08x\n", + WF_PSE_TOP_HIF0_PG_INFO_ADDR, + pg_flow_ctrl[3]); + min_q = (pg_flow_ctrl[2] & + WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MIN_QUOTA_MASK) >> + WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MIN_QUOTA_SHFT; + max_q = (pg_flow_ctrl[2] & + WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MAX_QUOTA_MASK) >> + WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MAX_QUOTA_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of HIF0 group=0x%03x/0x%03x\n", + max_q, min_q); + rsv_pg = + (pg_flow_ctrl[3] & WF_PSE_TOP_HIF0_PG_INFO_HIF0_RSV_CNT_MASK) >> + WF_PSE_TOP_HIF0_PG_INFO_HIF0_RSV_CNT_SHFT; + used_pg = + (pg_flow_ctrl[3] & WF_PSE_TOP_HIF0_PG_INFO_HIF0_SRC_CNT_MASK) >> + WF_PSE_TOP_HIF0_PG_INFO_HIF0_SRC_CNT_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of HIF0 group=0x%03x/0x%03x\n", + used_pg, rsv_pg); + DBGLOG(HAL, INFO, + "\tReserved page counter of HIF1 group(0x%08x): 0x%08x\n", + WF_PSE_TOP_PG_HIF1_GROUP_ADDR, + pg_flow_ctrl[4]); + DBGLOG(HAL, INFO, "\tHIF1 group page status(0x%08x): 0x%08x\n", + WF_PSE_TOP_HIF1_PG_INFO_ADDR, + pg_flow_ctrl[5]); + min_q = (pg_flow_ctrl[4] & + WF_PSE_TOP_PG_HIF1_GROUP_HIF1_MIN_QUOTA_MASK) >> + WF_PSE_TOP_PG_HIF1_GROUP_HIF1_MIN_QUOTA_SHFT; + max_q = (pg_flow_ctrl[4] & + WF_PSE_TOP_PG_HIF1_GROUP_HIF1_MAX_QUOTA_MASK) >> + WF_PSE_TOP_PG_HIF1_GROUP_HIF1_MAX_QUOTA_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of HIF1 group=0x%03x/0x%03x\n", + max_q, min_q); + rsv_pg = + (pg_flow_ctrl[5] & WF_PSE_TOP_HIF1_PG_INFO_HIF1_RSV_CNT_MASK) >> + WF_PSE_TOP_HIF1_PG_INFO_HIF1_RSV_CNT_SHFT; + used_pg = + (pg_flow_ctrl[5] & WF_PSE_TOP_HIF1_PG_INFO_HIF1_SRC_CNT_MASK) >> + WF_PSE_TOP_HIF1_PG_INFO_HIF1_SRC_CNT_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of HIF1 group=0x%03x/0x%03x\n", + used_pg, rsv_pg); + DBGLOG(HAL, INFO, + "\tReserved page counter of CPU group(0x%08x): 0x%08x\n", + WF_PSE_TOP_PG_CPU_GROUP_ADDR, + pg_flow_ctrl[6]); + DBGLOG(HAL, INFO, "\tCPU group page status(0x%08x): 0x%08x\n", + WF_PSE_TOP_CPU_PG_INFO_ADDR, + pg_flow_ctrl[7]); + min_q = (pg_flow_ctrl[6] & + WF_PSE_TOP_PG_CPU_GROUP_CPU_MIN_QUOTA_MASK) >> + WF_PSE_TOP_PG_CPU_GROUP_CPU_MIN_QUOTA_SHFT; + max_q = (pg_flow_ctrl[6] & + WF_PSE_TOP_PG_CPU_GROUP_CPU_MAX_QUOTA_MASK) >> + WF_PSE_TOP_PG_CPU_GROUP_CPU_MAX_QUOTA_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of CPU group=0x%03x/0x%03x\n", + max_q, min_q); + rsv_pg = (pg_flow_ctrl[7] & WF_PSE_TOP_CPU_PG_INFO_CPU_RSV_CNT_MASK) >> + WF_PSE_TOP_CPU_PG_INFO_CPU_RSV_CNT_SHFT; + used_pg = (pg_flow_ctrl[7] & WF_PSE_TOP_CPU_PG_INFO_CPU_SRC_CNT_MASK) >> + WF_PSE_TOP_CPU_PG_INFO_CPU_SRC_CNT_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of CPU group=0x%03x/0x%03x\n", + used_pg, rsv_pg); + DBGLOG(HAL, INFO, + "\tReserved page counter of LMAC0 group(0x%08x): 0x%08x\n", + WF_PSE_TOP_PG_LMAC0_GROUP_ADDR, + pg_flow_ctrl[8]); + DBGLOG(HAL, INFO, "\tLMAC0 group page status(0x%08x): 0x%08x\n", + WF_PSE_TOP_LMAC0_PG_INFO_ADDR, + pg_flow_ctrl[9]); + min_q = (pg_flow_ctrl[8] & + WF_PSE_TOP_PG_LMAC0_GROUP_LMAC0_MIN_QUOTA_MASK) >> + WF_PSE_TOP_PG_LMAC0_GROUP_LMAC0_MIN_QUOTA_SHFT; + max_q = (pg_flow_ctrl[8] & + WF_PSE_TOP_PG_LMAC0_GROUP_LMAC0_MAX_QUOTA_MASK) >> + WF_PSE_TOP_PG_LMAC0_GROUP_LMAC0_MAX_QUOTA_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of LMAC0 group=0x%03x/0x%03x\n", + max_q, min_q); + rsv_pg = (pg_flow_ctrl[9] & + WF_PSE_TOP_LMAC0_PG_INFO_LMAC0_RSV_CNT_MASK) >> + WF_PSE_TOP_LMAC0_PG_INFO_LMAC0_RSV_CNT_SHFT; + used_pg = (pg_flow_ctrl[9] & + WF_PSE_TOP_LMAC0_PG_INFO_LMAC0_SRC_CNT_MASK) >> + WF_PSE_TOP_LMAC0_PG_INFO_LMAC0_SRC_CNT_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of LMAC0 group=0x%03x/0x%03x\n", + used_pg, rsv_pg); + DBGLOG(HAL, INFO, + "\tReserved page counter of LMAC1 group(0x%08x): 0x%08x\n", + WF_PSE_TOP_PG_LMAC1_GROUP_ADDR, + pg_flow_ctrl[10]); + DBGLOG(HAL, INFO, "\tLMAC1 group page status(0x%08x): 0x%08x\n", + WF_PSE_TOP_LMAC1_PG_INFO_ADDR, + pg_flow_ctrl[11]); + min_q = (pg_flow_ctrl[10] & + WF_PSE_TOP_PG_LMAC1_GROUP_LMAC1_MIN_QUOTA_MASK) >> + WF_PSE_TOP_PG_LMAC1_GROUP_LMAC1_MIN_QUOTA_SHFT; + max_q = (pg_flow_ctrl[10] & + WF_PSE_TOP_PG_LMAC1_GROUP_LMAC1_MAX_QUOTA_MASK) >> + WF_PSE_TOP_PG_LMAC1_GROUP_LMAC1_MAX_QUOTA_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of LMAC1 group=0x%03x/0x%03x\n", + max_q, min_q); + rsv_pg = (pg_flow_ctrl[11] & + WF_PSE_TOP_LMAC1_PG_INFO_LMAC1_RSV_CNT_MASK) >> + WF_PSE_TOP_LMAC1_PG_INFO_LMAC1_RSV_CNT_SHFT; + used_pg = (pg_flow_ctrl[11] & + WF_PSE_TOP_LMAC1_PG_INFO_LMAC1_SRC_CNT_MASK) >> + WF_PSE_TOP_LMAC1_PG_INFO_LMAC1_SRC_CNT_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of LMAC1 group=0x%03x/0x%03x\n", + used_pg, rsv_pg); + DBGLOG(HAL, INFO, + "\tReserved page counter of LMAC2 group(0x%08x): 0x%08x\n", + WF_PSE_TOP_PG_LMAC2_GROUP_ADDR, + pg_flow_ctrl[11]); + DBGLOG(HAL, INFO, "\tLMAC2 group page status(0x%08x): 0x%08x\n", + WF_PSE_TOP_LMAC2_PG_INFO_ADDR, + pg_flow_ctrl[12]); + min_q = (pg_flow_ctrl[12] & + WF_PSE_TOP_PG_LMAC2_GROUP_LMAC2_MIN_QUOTA_MASK) >> + WF_PSE_TOP_PG_LMAC2_GROUP_LMAC2_MIN_QUOTA_SHFT; + max_q = (pg_flow_ctrl[12] & + WF_PSE_TOP_PG_LMAC2_GROUP_LMAC2_MAX_QUOTA_MASK) >> + WF_PSE_TOP_PG_LMAC2_GROUP_LMAC2_MAX_QUOTA_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of LMAC2 group=0x%03x/0x%03x\n", + max_q, min_q); + rsv_pg = (pg_flow_ctrl[13] & + WF_PSE_TOP_LMAC2_PG_INFO_LMAC2_RSV_CNT_MASK) >> + WF_PSE_TOP_LMAC2_PG_INFO_LMAC2_RSV_CNT_SHFT; + used_pg = (pg_flow_ctrl[13] & + WF_PSE_TOP_LMAC2_PG_INFO_LMAC2_SRC_CNT_MASK) >> + WF_PSE_TOP_LMAC2_PG_INFO_LMAC2_SRC_CNT_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of LMAC2 group=0x%03x/0x%03x\n", + used_pg, rsv_pg); + DBGLOG(HAL, INFO, + "\tReserved page counter of LMAC3 group(0x%08x): 0x%08x\n", + WF_PSE_TOP_PG_LMAC3_GROUP_ADDR, + pg_flow_ctrl[16]); + DBGLOG(HAL, INFO, "\tLMAC3 group page status(0x%08x): 0x%08x\n", + WF_PSE_TOP_LMAC3_PG_INFO_ADDR, + pg_flow_ctrl[17]); + min_q = (pg_flow_ctrl[16] & + WF_PSE_TOP_PG_LMAC3_GROUP_LMAC3_MIN_QUOTA_MASK) >> + WF_PSE_TOP_PG_LMAC3_GROUP_LMAC3_MIN_QUOTA_SHFT; + max_q = (pg_flow_ctrl[16] & + WF_PSE_TOP_PG_LMAC3_GROUP_LMAC3_MAX_QUOTA_MASK) >> + WF_PSE_TOP_PG_LMAC3_GROUP_LMAC3_MAX_QUOTA_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of LMAC3 group=0x%03x/0x%03x\n", + max_q, min_q); + rsv_pg = (pg_flow_ctrl[17] & + WF_PSE_TOP_LMAC3_PG_INFO_LMAC3_RSV_CNT_MASK) >> + WF_PSE_TOP_LMAC3_PG_INFO_LMAC3_RSV_CNT_SHFT; + used_pg = (pg_flow_ctrl[17] & + WF_PSE_TOP_LMAC3_PG_INFO_LMAC3_SRC_CNT_MASK) >> + WF_PSE_TOP_LMAC3_PG_INFO_LMAC3_SRC_CNT_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of LMAC3 group=0x%03x/0x%03x\n", + used_pg, rsv_pg); + DBGLOG(HAL, INFO, + "\tReserved page counter of PLE group(0x%08x): 0x%08x\n", + WF_PSE_TOP_PG_PLE_GROUP_ADDR, + pg_flow_ctrl[14]); + DBGLOG(HAL, INFO, "\tPLE group page status(0x%08x): 0x%08x\n", + WF_PSE_TOP_PLE_PG_INFO_ADDR, + pg_flow_ctrl[15]); + min_q = (pg_flow_ctrl[14] & + WF_PSE_TOP_PG_PLE_GROUP_PLE_MIN_QUOTA_MASK) >> + WF_PSE_TOP_PG_PLE_GROUP_PLE_MIN_QUOTA_SHFT; + max_q = (pg_flow_ctrl[14] & + WF_PSE_TOP_PG_PLE_GROUP_PLE_MAX_QUOTA_MASK) >> + WF_PSE_TOP_PG_PLE_GROUP_PLE_MAX_QUOTA_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of PLE group=0x%03x/0x%03x\n", + max_q, min_q); + rsv_pg = (pg_flow_ctrl[15] & WF_PSE_TOP_PLE_PG_INFO_PLE_RSV_CNT_MASK) >> + WF_PSE_TOP_PLE_PG_INFO_PLE_RSV_CNT_SHFT; + used_pg = + (pg_flow_ctrl[15] & WF_PSE_TOP_PLE_PG_INFO_PLE_SRC_CNT_MASK) >> + WF_PSE_TOP_PLE_PG_INFO_PLE_SRC_CNT_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of PLE group=0x%03x/0x%03x\n", + used_pg, rsv_pg); + DBGLOG(HAL, INFO, + "\tReserved page counter of MDP group(0x%08x): 0x%08x\n", + WF_PSE_TOP_PG_MDP_GROUP_ADDR, + pg_flow_ctrl[18]); + DBGLOG(HAL, INFO, "\tMDP group page status(0x%08x): 0x%08x\n", + WF_PSE_TOP_MDP_PG_INFO_ADDR, + pg_flow_ctrl[19]); + min_q = (pg_flow_ctrl[18] & + WF_PSE_TOP_PG_MDP_GROUP_MDP_MIN_QUOTA_MASK) >> + WF_PSE_TOP_PG_MDP_GROUP_MDP_MIN_QUOTA_SHFT; + max_q = (pg_flow_ctrl[18] & + WF_PSE_TOP_PG_MDP_GROUP_MDP_MAX_QUOTA_MASK) >> + WF_PSE_TOP_PG_MDP_GROUP_MDP_MAX_QUOTA_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of MDP group=0x%03x/0x%03x\n", + max_q, min_q); + rsv_pg = (pg_flow_ctrl[19] & WF_PSE_TOP_MDP_PG_INFO_MDP_RSV_CNT_MASK) >> + WF_PSE_TOP_MDP_PG_INFO_MDP_RSV_CNT_SHFT; + used_pg = + (pg_flow_ctrl[19] & WF_PSE_TOP_MDP_PG_INFO_MDP_SRC_CNT_MASK) >> + WF_PSE_TOP_MDP_PG_INFO_MDP_SRC_CNT_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of MDP group=0x%03x/0x%03x\n", + used_pg, rsv_pg); + /* Queue Empty Status */ + DBGLOG(HAL, INFO, "PSE Queue Empty Status:\n"); + DBGLOG(HAL, INFO, "\tQUEUE_EMPTY(0x%08x): 0x%08x\n", + WF_PSE_TOP_QUEUE_EMPTY_ADDR, + pse_stat); + DBGLOG(HAL, INFO, "\t\tCPU Q0/1/2/3 empty=%d/%d/%d/%d\n", + (pse_stat & WF_PSE_TOP_QUEUE_EMPTY_CPU_Q0_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_CPU_Q0_EMPTY_SHFT, + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_CPU_Q1_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_CPU_Q1_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_CPU_Q2_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_CPU_Q2_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_CPU_Q3_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_CPU_Q3_EMPTY_SHFT)); + DBGLOG(HAL, INFO, "\t\tHIF Q0/1/2/3/4/5 empty=%d/%d/%d/%d/%d/%d\n", + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_0_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_0_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_1_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_1_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_2_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_2_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_3_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_3_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_4_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_4_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_5_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_5_EMPTY_SHFT)); + DBGLOG(HAL, INFO, "\t\tLMAC TX Q empty=%d\n", + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_LMAC_TX_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_LMAC_TX_QUEUE_EMPTY_SHFT)); + DBGLOG(HAL, INFO, "\t\tMDP TX Q/RX Q empty=%d/%d\n", + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_MDP_TX_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_MDP_TX_QUEUE_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_MDP_RX_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_MDP_RX_QUEUE_EMPTY_SHFT)); + DBGLOG(HAL, INFO, "\t\tSEC TX Q/RX Q empty=%d/%d\n", + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_SEC_TX_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_SEC_TX_QUEUE_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_SEC_RX_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_SEC_RX_QUEUE_EMPTY_SHFT)); + DBGLOG(HAL, INFO, "\t\tSFD PARK Q empty=%d\n", + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_SFD_PARK_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_SFD_PARK_QUEUE_EMPTY_SHFT)); + DBGLOG(HAL, INFO, "\t\tMDP TXIOC Q/RXIOC Q empty=%d/%d\n", + ((pse_stat & + WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC_QUEUE_EMPTY_SHFT), + ((pse_stat & + WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC_QUEUE_EMPTY_SHFT)); + DBGLOG(HAL, INFO, "\t\tRLS Q empty=%d\n", + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_RLS_Q_EMTPY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_RLS_Q_EMTPY_SHFT)); + DBGLOG(HAL, INFO, "Nonempty Q info:\n"); + + for (i = 0; i < 31; i++) { + if (((pse_stat & (0x1 << i)) >> i) == 0) { + uint32_t hfid, tfid, pktcnt, fl_que_ctrl[3] = {0}; + + if (pse_queue_empty_info[i].QueueName != NULL) { + DBGLOG(HAL, INFO, "\t%s: ", + pse_queue_empty_info[i].QueueName); + fl_que_ctrl[0] |= + WF_PSE_TOP_FL_QUE_CTRL_0_EXECUTE_MASK; + fl_que_ctrl[0] |= + (pse_queue_empty_info[i].Portid + << WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_SHFT); + fl_que_ctrl[0] |= + (pse_queue_empty_info[i].Queueid + << WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_SHFT); + } else + continue; + + fl_que_ctrl[0] |= (0x1 << 31); + HAL_MCR_WR(prAdapter, WF_PSE_TOP_FL_QUE_CTRL_0_ADDR, + fl_que_ctrl[0]); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_FL_QUE_CTRL_2_ADDR, + &fl_que_ctrl[1]); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_FL_QUE_CTRL_3_ADDR, + &fl_que_ctrl[2]); + hfid = (fl_que_ctrl[1] & + WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_MASK) >> + WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_SHFT; + tfid = (fl_que_ctrl[1] & + WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_MASK) >> + WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_SHFT; + pktcnt = + (fl_que_ctrl[2] & + WF_PSE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_MASK) >> + WF_PSE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_SHFT; + DBGLOG(HAL, INFO, + "tail/head fid = 0x%03x/0x%03x, pkt cnt = 0x%03x\n", + tfid, hfid, pktcnt); + } + } +} +#endif /* MT7915 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7915/mt7915.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7915/mt7915.c new file mode 100644 index 0000000000000..923600ad25ac2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7915/mt7915.c @@ -0,0 +1,599 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file mt7915.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. +*/ + +#ifdef MT7915 + +/******************************************************************************* +* C O M P I L E 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 "mt7915.h" +#include "coda/mt7915/wf_cr_sw_def.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define CONN_MCU_CONFG_BASE 0x88000000 +#define CONN_MCU_CONFG_COM_REG0_ADDR (CONN_MCU_CONFG_BASE + 0x200) + +#define PATCH_SEMAPHORE_COMM_REG 0 +#define PATCH_SEMAPHORE_COMM_REG_PATCH_DONE 1 /* bit0 is for patch. */ +/******************************************************************************* +* M A 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 U B L I C D A T A +******************************************************************************** +*/ +struct ECO_INFO mt7915_eco_table[] = { + /* HW version, ROM version, Factory version */ + {0x00, 0x00, 0xA, 0x1}, /* E1 */ + {0x10, 0x01, 0xA, 0x2}, /* E2 */ + {0x00, 0x00, 0x0} /* End of table */ +}; + +#if defined(_HIF_PCIE) +struct PCIE_CHIP_CR_MAPPING mt7915_bus2chip_cr_mapping[] = { + /* chip addr, bus addr, range */ + {0x54000000, 0x02000, 0x1000}, /* WFDMA PCIE0 MCU DMA0 */ + {0x55000000, 0x03000, 0x1000}, /* WFDMA PCIE0 MCU DMA1 */ + {0x56000000, 0x04000, 0x1000}, /* WFDMA reserved */ + {0x57000000, 0x05000, 0x1000}, /* WFDMA MCU wrap CR */ + {0x58000000, 0x06000, 0x1000}, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */ + {0x59000000, 0x07000, 0x1000}, /* WFDMA PCIE1 MCU DMA1 */ + {0x820c0000, 0x08000, 0x4000}, /* WF_UMAC_TOP (PLE) */ + {0x820c8000, 0x0c000, 0x2000}, /* WF_UMAC_TOP (PSE) */ + {0x820cc000, 0x0e000, 0x2000}, /* WF_UMAC_TOP (PP) */ + {0x820e0000, 0x20000, 0x0400}, /* WF_LMAC_TOP BN0 (WF_CFG) */ + {0x820e1000, 0x20400, 0x0200}, /* WF_LMAC_TOP BN0 (WF_TRB) */ + {0x820e2000, 0x20800, 0x0400}, /* WF_LMAC_TOP BN0 (WF_AGG) */ + {0x820e3000, 0x20c00, 0x0400}, /* WF_LMAC_TOP BN0 (WF_ARB) */ + {0x820e4000, 0x21000, 0x0400}, /* WF_LMAC_TOP BN0 (WF_TMAC) */ + {0x820e5000, 0x21400, 0x0800}, /* WF_LMAC_TOP BN0 (WF_RMAC) */ + {0x820ce000, 0x21c00, 0x0200}, /* WF_LMAC_TOP (WF_SEC) */ + {0x820e7000, 0x21e00, 0x0200}, /* WF_LMAC_TOP BN0 (WF_DMA) */ + {0x820cf000, 0x22000, 0x1000}, /* WF_LMAC_TOP (WF_PF) */ + {0x820e9000, 0x23400, 0x0200}, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */ + {0x820ea000, 0x24000, 0x0200}, /* WF_LMAC_TOP BN0 (WF_ETBF) */ + {0x820eb000, 0x24200, 0x0400}, /* WF_LMAC_TOP BN0 (WF_LPON) */ + {0x820ec000, 0x24600, 0x0200}, /* WF_LMAC_TOP BN0 (WF_INT) */ + {0x820ed000, 0x24800, 0x0800}, /* WF_LMAC_TOP BN0 (WF_MIB) */ + {0x820ca000, 0x26000, 0x2000}, /* WF_LMAC_TOP BN0 (WF_MUCOP) */ + {0x820d0000, 0x30000, 0x10000}, /* WF_LMAC_TOP (WF_WTBLON) */ + {0x40000000, 0x70000, 0x10000}, /* WF_UMAC_SYSRAM */ + {0x00400000, 0x80000, 0x10000}, /* WF_MCU_SYSRAM */ + {0x00410000, 0x90000, 0x10000}, /* WF_MCU_SYSRAM (configure register) */ + {0x820f0000, 0xa0000, 0x0400}, /* WF_LMAC_TOP BN1 (WF_CFG) */ + {0x820f1000, 0xa0600, 0x0200}, /* WF_LMAC_TOP BN1 (WF_TRB) */ + {0x820f2000, 0xa0800, 0x0400}, /* WF_LMAC_TOP BN1 (WF_AGG) */ + {0x820f3000, 0xa0c00, 0x0400}, /* WF_LMAC_TOP BN1 (WF_ARB) */ + {0x820f4000, 0xa1000, 0x0400}, /* WF_LMAC_TOP BN1 (WF_TMAC) */ + {0x820f5000, 0xa1400, 0x0800}, /* WF_LMAC_TOP BN1 (WF_RMAC) */ + {0x820f7000, 0xa1e00, 0x0200}, /* WF_LMAC_TOP BN1 (WF_DMA) */ + {0x820f9000, 0xa3400, 0x0200}, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */ + {0x820fa000, 0xa4000, 0x0200}, /* WF_LMAC_TOP BN1 (WF_ETBF) */ + {0x820fb000, 0xa4200, 0x0400}, /* WF_LMAC_TOP BN1 (WF_LPON) */ + {0x820fc000, 0xa4600, 0x0200}, /* WF_LMAC_TOP BN1 (WF_INT) */ + {0x820fd000, 0xa4800, 0x0800}, /* WF_LMAC_TOP BN1 (WF_MIB) */ + {0x820cc000, 0xa5000, 0x2000}, /* WF_LMAC_TOP BN1 (WF_MUCOP) */ + {0x820c4000, 0xa8000, 0x4000}, /* WF_LMAC_TOP BN1 (WF_MUCOP) */ + {0x820b0000, 0xae000, 0x1000}, /* [APB2] WFSYS_ON */ + {0x80020000, 0xb0000, 0x10000}, /* WF_TOP_MISC_OFF */ + {0x81020000, 0xc0000, 0x10000}, /* WF_TOP_MISC_ON */ + {0x7c020000, 0xd0000, 0x10000}, /* CONN_INFRA, wfdma */ + {0x7c060000, 0xe0000, 0x10000}, /* CONN_INFRA, conn_host_csr_top */ + {0x7c000000, 0xf0000, 0x10000}, /* CONN_INFRA */ + {0x000f0000, 0xf0000, 0x10000}, + {0x000e0000, 0xe0000, 0x10000}, + {0x0, 0x0, 0x0} +}; +#endif /* _HIF_PCIE */ + +#if defined(_HIF_USB) +uint16_t wlanHarrierUsbRxByteCount( + struct ADAPTER *prAdapter, + struct BUS_INFO *prBusInfo, + uint8_t *pRXD) +{ + uint16_t u2RxByteCount; + uint8_t ucPacketType; + + ucPacketType = HAL_MAC_CONNAC2X_RX_STATUS_GET_PKT_TYPE( + (struct HW_MAC_CONNAC2X_RX_DESC *)pRXD); + u2RxByteCount = HAL_MAC_CONNAC2X_RX_STATUS_GET_RX_BYTE_CNT( + (struct HW_MAC_CONNAC2X_RX_DESC *)pRXD); + + /* According to Barry's rule, it can be summarized as below formula: + * 1. Event packet (including WIFI packet sent by MCU) + -> RX padding for 4B alignment + * 2. WIFI packet from UMAC + * E1: + * case 1. In case byte length = + 128*N-7 ~ 128*N -> RX padding for 4B alignment + * case 2. RX padding for 8B alignment first, + then extra 4B padding + * E2: + * RX padding for 8B alignment + 4B CSO + */ + if (nicIsEcoVerEqualOrLaterTo(prAdapter, ECO_VER_2)) { + if (ucPacketType == RX_PKT_TYPE_RX_DATA) { + u2RxByteCount = ALIGN_8(u2RxByteCount) + + LEN_USB_RX_PADDING_CSO; + } else { + u2RxByteCount = ALIGN_4(u2RxByteCount); + } + } else { + if ((ucPacketType == RX_PKT_TYPE_RX_DATA) && + (u2RxByteCount & BITS(0, 6)) != 0 && + (u2RxByteCount & BITS(0, 6)) < 121) + u2RxByteCount = ALIGN_8(u2RxByteCount) + + LEN_USB_RX_PADDING_CSO; + else { + u2RxByteCount = ALIGN_4(u2RxByteCount); + } + } + + return u2RxByteCount; +} +#endif /* defined(_HIF_USB) */ + +#if defined(_HIF_PCIE) +static void wlanHarrierInitPcieInt( + struct GLUE_INFO *prGlueInfo) +{ + uint32_t u4MacVal; + + /* Backup original setting */ + HAL_MCR_RD(prGlueInfo->prAdapter, + 0xF11AC, + &u4MacVal); + + /* + * To set 0x74030188 = 0x000000FF + * 1. set 0xF11AC = 0x7403 + * 2. set 0xE0188 = 0x000000FF + */ + HAL_MCR_WR(prGlueInfo->prAdapter, + 0xF11AC, + 0x7403); + HAL_MCR_WR(prGlueInfo->prAdapter, + 0xE0188, + 0x000000FF); + + /* Recovery original setting */ + HAL_MCR_WR(prGlueInfo->prAdapter, + 0xF11AC, + u4MacVal); +} + +static bool mt7915WfdmaAllocRxRing( + struct GLUE_INFO *prGlueInfo, + bool fgAllocMem) +{ + if (!halWpdmaAllocRxRing(prGlueInfo, WFDMA0_RX_RING_IDX_2, + RX_RING1_SIZE, RXD_SIZE, RX_BUFFER_AGGRESIZE, + fgAllocMem)) { + DBGLOG(HAL, ERROR, "AllocWfdmaRxRing fail\n"); + return false; + } + if (!halWpdmaAllocRxRing(prGlueInfo, WFDMA0_RX_RING_IDX_3, + RX_RING1_SIZE, RXD_SIZE, RX_BUFFER_AGGRESIZE, + fgAllocMem)) { + DBGLOG(HAL, ERROR, "AllocWfdmaRxRing fail\n"); + return false; + } + if (!halWpdmaAllocRxRing(prGlueInfo, WFDMA1_RX_RING_IDX_0, + RX_RING1_SIZE, RXD_SIZE, RX_BUFFER_AGGRESIZE, + fgAllocMem)) { + DBGLOG(HAL, ERROR, "AllocWfdmaRxRing fail\n"); + return false; + } + if (!halWpdmaAllocRxRing(prGlueInfo, WFDMA1_RX_RING_IDX_1, + RX_RING_SIZE, RXD_SIZE, RX_BUFFER_AGGRESIZE, + fgAllocMem)) { + DBGLOG(HAL, ERROR, "AllocWfdmaRxRing fail\n"); + return false; + } + if (!halWpdmaAllocRxRing(prGlueInfo, WFDMA1_RX_RING_IDX_2, + RX_RING_SIZE, RXD_SIZE, RX_BUFFER_AGGRESIZE, + fgAllocMem)) { + DBGLOG(HAL, ERROR, "AllocWfdmaRxRing fail\n"); + return false; + } + return true; +} + +#endif /* _HIF_PCIE */ + +void mt7915DumpSerDummyCR( + struct ADAPTER *prAdapter) +{ + uint32_t u4MacVal; + + DBGLOG(HAL, INFO, "%s\n", __func__); + + DBGLOG(HAL, INFO, "=====Dump Start====\n"); + + HAL_MCR_RD(prAdapter, WF_SW_DEF_CR_SER_STATUS_ADDR, &u4MacVal); + DBGLOG(HAL, INFO, "SER STATUS[0x%08x]: 0x%08x\n", + WF_SW_DEF_CR_SER_STATUS_ADDR, u4MacVal); + + HAL_MCR_RD(prAdapter, WF_SW_DEF_CR_PLE_STATUS_ADDR, &u4MacVal); + DBGLOG(HAL, INFO, "PLE STATUS[0x%08x]: 0x%08x\n", + WF_SW_DEF_CR_PLE_STATUS_ADDR, u4MacVal); + + HAL_MCR_RD(prAdapter, WF_SW_DEF_CR_PLE1_STATUS_ADDR, &u4MacVal); + DBGLOG(HAL, INFO, "PLE1 STATUS[0x%08x]: 0x%08x\n", + WF_SW_DEF_CR_PLE1_STATUS_ADDR, u4MacVal); + + HAL_MCR_RD(prAdapter, WF_SW_DEF_CR_PLE_AMSDU_STATUS_ADDR, &u4MacVal); + DBGLOG(HAL, INFO, "PLE AMSDU STATUS[0x%08x]: 0x%08x\n", + WF_SW_DEF_CR_PLE_AMSDU_STATUS_ADDR, u4MacVal); + + HAL_MCR_RD(prAdapter, WF_SW_DEF_CR_PSE_STATUS_ADDR, &u4MacVal); + DBGLOG(HAL, INFO, "PSE STATUS[0x%08x]: 0x%08x\n", + WF_SW_DEF_CR_PSE_STATUS_ADDR, u4MacVal); + + HAL_MCR_RD(prAdapter, WF_SW_DEF_CR_PSE1_STATUS_ADDR, &u4MacVal); + DBGLOG(HAL, INFO, "PSE1 STATUS[0x%08x]: 0x%08x\n", + WF_SW_DEF_CR_PSE1_STATUS_ADDR, u4MacVal); + + HAL_MCR_RD(prAdapter, WF_SW_DEF_CR_LAMC_WISR6_BN0_STATUS_ADDR, + &u4MacVal); + DBGLOG(HAL, INFO, "LMAC WISR6 BN0 STATUS[0x%08x]: 0x%08x\n", + WF_SW_DEF_CR_LAMC_WISR6_BN0_STATUS_ADDR, u4MacVal); + + HAL_MCR_RD(prAdapter, WF_SW_DEF_CR_LAMC_WISR6_BN1_STATUS_ADDR, + &u4MacVal); + DBGLOG(HAL, INFO, "LMAC WISR6 BN1 STATUS[0x%08x]: 0x%08x\n", + WF_SW_DEF_CR_LAMC_WISR6_BN1_STATUS_ADDR, u4MacVal); + + HAL_MCR_RD(prAdapter, WF_SW_DEF_CR_LAMC_WISR7_BN0_STATUS_ADDR, + &u4MacVal); + DBGLOG(HAL, INFO, "LMAC WISR7 BN0 STATUS[0x%08x]: 0x%08x\n", + WF_SW_DEF_CR_LAMC_WISR7_BN0_STATUS_ADDR, u4MacVal); + + HAL_MCR_RD(prAdapter, WF_SW_DEF_CR_LAMC_WISR7_BN1_STATUS_ADDR, + &u4MacVal); + DBGLOG(HAL, INFO, "LMAC WISR7 BN1 STATUS[0x%08x]: 0x%08x\n", + WF_SW_DEF_CR_LAMC_WISR7_BN1_STATUS_ADDR, u4MacVal); + + DBGLOG(HAL, INFO, "=====Dump End====\n"); + +} + +/* check capability of chip depends on different ECO version */ +void mt7915CheckAsicCap( + struct ADAPTER *prAdapter) +{ + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + + /* check capability of chip depends on different ECO version */ + if (nicIsEcoVerEqualTo(prAdapter, ECO_VER_1)) { + /* FALCON: DW 18~33 for harrier E1, + * DW 18~35 for harrier E2 of Group5. + */ + prChipInfo->group5_size = + sizeof(struct HW_MAC_RX_STS_HARRIER_E1_GROUP_5); + + /* MT7915U E1 cannot support CS0 RX. */ + prAdapter->u4CSUMFlags = CSUM_OFFLOAD_EN_TX_MASK; + } +} + +#if defined(_HIF_USB) +void mt7915Connac2xWfdmaInitForUSB( + struct ADAPTER *prAdapter, + struct mt66xx_chip_info *prChipInfo) +{ + uint32_t u4WfdmaCr; + + /* 7915U E1 Workaround. TODO: check chip version */ + /* Driver need to write rx ring cpu index for receiving data */ + HAL_MCR_WR(prAdapter, + CONNAC2X_RX_RING_CIDX(CONNAC2X_HOST_WPDMA_0_BASE), 0x1); + + /* enable RX CSO option bit for E2 RX padding, only work after E2 */ + HAL_MCR_RD(prAdapter, + CONNAC2X_WFDMA_HOST_CONFIG_ADDR, &u4WfdmaCr); + u4WfdmaCr |= CONNAC2X_WFDMA_RX_CSO_OPTION; + HAL_MCR_WR(prAdapter, + CONNAC2X_WFDMA_HOST_CONFIG_ADDR, u4WfdmaCr); +} +#endif + +struct BUS_INFO mt7915_bus_info = { +#if defined(_HIF_PCIE) + .top_cfg_base = MT7915_TOP_CFG_BASE, + /* host_dma0 for TXP */ + .host_dma0_base = CONNAC2X_HOST_WPDMA_0_BASE, + /* host_dma1 for TXD and host cmd to WX_CPU */ + .host_dma1_base = CONNAC2X_HOST_WPDMA_1_BASE, + .host_ext_conn_hif_wrap_base = CONNAC2X_HOST_EXT_CONN_HIF_WRAP, + .host_int_status_addr = + CONNAC2X_WPDMA_EXT_INT_STA(CONNAC2X_HOST_EXT_CONN_HIF_WRAP), + .host_int_txdone_bits = (CONNAC2X_EXT_WFDMA1_TX_DONE_INT0 + | CONNAC2X_EXT_WFDMA1_TX_DONE_INT1 + | CONNAC2X_EXT_WFDMA1_TX_DONE_INT2 + | CONNAC2X_EXT_WFDMA1_TX_DONE_INT16 + | CONNAC2X_EXT_WFDMA1_TX_DONE_INT17 + | CONNAC2X_EXT_WFDMA1_TX_DONE_INT18 + | CONNAC2X_EXT_WFDMA1_TX_DONE_INT19 + | CONNAC2X_EXT_WFDMA1_TX_DONE_INT20), + .host_int_rxdone_bits = (CONNAC2X_EXT_WFDMA1_RX_DONE_INT0 + | CONNAC2X_EXT_WFDMA1_RX_DONE_INT1 + | CONNAC2X_EXT_WFDMA1_RX_DONE_INT2 + | CONNAC2X_EXT_WFDMA0_RX_DONE_INT0 + | CONNAC2X_EXT_WFDMA0_RX_DONE_INT1 + ), + .host_tx_ring_base = + CONNAC2X_TX_RING_BASE(CONNAC2X_HOST_WPDMA_1_BASE), + .host_tx_ring_ext_ctrl_base = + CONNAC2X_TX_RING_EXT_CTRL_BASE(CONNAC2X_HOST_WPDMA_1_BASE), + .host_tx_ring_cidx_addr = + CONNAC2X_TX_RING_CIDX(CONNAC2X_HOST_WPDMA_1_BASE), + .host_tx_ring_didx_addr = + CONNAC2X_TX_RING_DIDX(CONNAC2X_HOST_WPDMA_1_BASE), + .host_tx_ring_cnt_addr = + CONNAC2X_TX_RING_CNT(CONNAC2X_HOST_WPDMA_1_BASE), + + .host_rx_ring_base = + CONNAC2X_RX_RING_BASE(CONNAC2X_HOST_WPDMA_0_BASE), + .host_rx_ring_ext_ctrl_base = + CONNAC2X_RX_RING_EXT_CTRL_BASE(CONNAC2X_HOST_WPDMA_0_BASE), + .host_rx_ring_cidx_addr = + CONNAC2X_RX_RING_CIDX(CONNAC2X_HOST_WPDMA_0_BASE), + .host_rx_ring_didx_addr = + CONNAC2X_RX_RING_DIDX(CONNAC2X_HOST_WPDMA_0_BASE), + .host_rx_ring_cnt_addr = + CONNAC2X_RX_RING_CNT(CONNAC2X_HOST_WPDMA_0_BASE), + + .host_wfdma1_rx_ring_base = + CONNAC2X_WFDMA1_RX_RING_BASE(CONNAC2X_HOST_WPDMA_1_BASE), + .host_wfdma1_rx_ring_cidx_addr = + CONNAC2X_WFDMA1_RX_RING_CIDX(CONNAC2X_HOST_WPDMA_1_BASE), + .host_wfdma1_rx_ring_didx_addr = + CONNAC2X_WFDMA1_RX_RING_DIDX(CONNAC2X_HOST_WPDMA_1_BASE), + .host_wfdma1_rx_ring_cnt_addr = + CONNAC2X_WFDMA1_RX_RING_CNT(CONNAC2X_HOST_WPDMA_1_BASE), + .host_wfdma1_rx_ring_ext_ctrl_base = + CONNAC2X_WFDMA1_RX_RING_EXT_CTRL_BASE( + CONNAC2X_HOST_WPDMA_1_BASE), + + .bus2chip = mt7915_bus2chip_cr_mapping, + .max_static_map_addr = 0x000f0000, + .tx_ring_fwdl_idx = CONNAC2X_FWDL_TX_RING_IDX, + .tx_ring_cmd_idx = CONNAC2X_CMD_TX_RING_IDX, + .tx_ring_wa_cmd_idx = CONNAC2X_CMD_TX_WA_RING_IDX, + .tx_ring0_data_idx = CONNAC2X_DATA0_TXD_IDX, + .tx_ring1_data_idx = CONNAC2X_DATA1_TXD_IDX, + .fw_own_clear_addr = CONNAC2X_BN0_IRQ_STAT_ADDR, + .fw_own_clear_bit = PCIE_LPCR_FW_CLR_OWN, + + .fgCheckDriverOwnInt = FALSE, + .u4DmaMask = 32, + + .pdmaSetup = asicConnac2xWpdmaConfig, + .enableInterrupt = asicConnac2xEnableExtInterrupt, + .disableInterrupt = asicConnac2xDisableExtInterrupt, + .processTxInterrupt = asicConnac2xProcessTxInterrupt, + .tx_ring_ext_ctrl = asicConnac2xWfdmaTxRingExtCtrl, + .rx_ring_ext_ctrl = asicConnac2xWfdmaRxRingExtCtrl, + /* null wfdmaManualPrefetch if want to disable manual mode */ + .wfdmaManualPrefetch = asicConnac2xWfdmaManualPrefetch, + .lowPowerOwnRead = asicConnac2xLowPowerOwnRead, + .lowPowerOwnSet = asicConnac2xLowPowerOwnSet, + .lowPowerOwnClear = asicConnac2xLowPowerOwnClear, + .wakeUpWiFi = asicWakeUpWiFi, + .processSoftwareInterrupt = asicConnac2xProcessSoftwareInterrupt, + .softwareInterruptMcu = asicConnac2xSoftwareInterruptMcu, + .hifRst = asicConnac2xHifRst, + .processRxInterrupt = asicConnac2xProcessRxInterrupt, + .initPcieInt = wlanHarrierInitPcieInt, + .devReadIntStatus = asicConnac2xReadExtIntStatus, + .DmaShdlInit = NULL, + .wfdmaAllocRxRing = mt7915WfdmaAllocRxRing, +#endif /* _HIF_PCIE */ +#if defined(_HIF_USB) + .u4UdmaWlCfg_0_Addr = CONNAC2X_UDMA_WLCFG_0, + .u4UdmaWlCfg_1_Addr = CONNAC2X_UDMA_WLCFG_1, + .u4UdmaTxQsel = CONNAC2X_UDMA_TX_QSEL, + .u4device_vender_request_in = DEVICE_VENDOR_REQUEST_IN_CONNAC2, + .u4device_vender_request_out = DEVICE_VENDOR_REQUEST_OUT_CONNAC2, + .u4usb_tx_cmd_queue_mask = USB_TX_CMD_QUEUE_MASK, + .u4UdmaWlCfg_0 = + (CONNAC2X_UDMA_WLCFG_0_WL_TX_EN(1) | + CONNAC2X_UDMA_WLCFG_0_WL_RX_EN(1) | + CONNAC2X_UDMA_WLCFG_0_WL_RX_MPSZ_PAD0(1) | + CONNAC2X_UDMA_WLCFG_0_TICK_1US_EN(1)), + .u4UdmaTxTimeout = CONNAC2X_UDMA_TX_TIMEOUT_LIMIT, + .u4SuspendVer = SUSPEND_V2, + .asicUsbSuspend = NULL, /*asicUsbSuspend*/ + .asicUsbResume = asicConnac2xUsbResume, + .asicUsbEventEpDetected = asicConnac2xUsbEventEpDetected, + .asicUsbRxByteCount = wlanHarrierUsbRxByteCount, + .DmaShdlInit = NULL, +#endif /* _HIF_USB */ +#if defined(_HIF_SDIO) + .halTxGetFreeResource = halTxGetFreeResource_v1, + .halTxReturnFreeResource = halTxReturnFreeResource_v1, + .halRestoreTxResource = halRestoreTxResource_v1, + .halUpdateTxDonePendingCount = halUpdateTxDonePendingCount_v1, +#endif /* _HIF_SDIO */ +}; + +#if CFG_ENABLE_FW_DOWNLOAD +struct FWDL_OPS_T mt7915_fw_dl_ops = { + .constructFirmwarePrio = NULL, + .downloadPatch = wlanDownloadPatch, + .downloadFirmware = wlanConnacFormatDownload, + .downloadByDynMemMap = NULL, + .getFwInfo = wlanGetConnacFwInfo, + .getFwDlInfo = asicGetFwDlInfo, + .phyAction = NULL, +}; +#endif /* CFG_ENABLE_FW_DOWNLOAD */ + +struct TX_DESC_OPS_T mt7915TxDescOps = { + .fillNicAppend = fillConnac2xTxDescAppendWithWaCpu, + .fillHifAppend = fillConnac2xTxDescAppendByWaCpu, + .fillTxByteCount = fillTxDescTxByteCountWithWaCpu, +}; + +struct RX_DESC_OPS_T mt7915RxDescOps = { +}; + + +struct CHIP_DBG_OPS mt7915_debug_ops = { + .showPdmaInfo = NULL, + .showPseInfo = mt7915_show_pse_info, + .showPleInfo = mt7915_show_ple_info, + .showTxdInfo = connac2x_show_txd_Info, + .showWtblInfo = connac2x_show_wtbl_info, + .showUmacFwtblInfo = connac2x_show_umac_wtbl_info, + .showCsrInfo = NULL, + .showDmaschInfo = NULL, + .dumpMacInfo = NULL, + .showHifInfo = NULL, + .printHifDbgInfo = NULL, + .show_rx_rate_info = connac2x_show_rx_rate_info, + .show_rx_rssi_info = connac2x_show_rx_rssi_info, + .show_stat_info = connac2x_show_stat_info, +}; + +/* Litien code refine to support multi chip */ +struct mt66xx_chip_info mt66xx_chip_info_mt7915 = { + .bus_info = &mt7915_bus_info, +#if CFG_ENABLE_FW_DOWNLOAD + .fw_dl_ops = &mt7915_fw_dl_ops, +#endif /* CFG_ENABLE_FW_DOWNLOAD */ + .prDebugOps = &mt7915_debug_ops, + .prTxDescOps = &mt7915TxDescOps, + .prRxDescOps = &mt7915RxDescOps, + .chip_id = MT7915_CHIP_ID, + .should_verify_chip_id = FALSE, + .sw_sync0 = MT7915_SW_SYNC0, + .sw_ready_bits = WIFI_FUNC_READY_BITS, + .sw_ready_bit_offset = MT7915_SW_SYNC0_RDY_OFFSET, + .patch_addr = MT7915_PATCH_START_ADDR, + .is_support_cr4 = FALSE, + .is_support_wacpu = TRUE, + .txd_append_size = MT7915_TX_DESC_APPEND_LENGTH, + .rxd_size = MT7915_RX_DESC_LENGTH, + .init_evt_rxd_size = MT7915_RX_DESC_LENGTH, + .pse_header_length = CONNAC2X_NIC_TX_PSE_HEADER_LENGTH, + .init_event_size = CONNAC2X_RX_INIT_EVENT_LENGTH, + .eco_info = mt7915_eco_table, + .isNicCapV1 = FALSE, + .top_hcr = CONNAC2X_TOP_HCR, + .top_hvr = CONNAC2X_TOP_HVR, + .top_fvr = CONNAC2X_TOP_FVR, + .arb_ac_mode_addr = MT7915_ARB_AC_MODE_ADDR, + .asicCapInit = asicConnac2xCapInit, +#if defined(_HIF_USB) + .asicUsbInit = asicConnac2xWfdmaInitForUSB, + .asicUsbInit_ic_specific = mt7915Connac2xWfdmaInitForUSB, + .u4SerUsbMcuEventAddr = WF_SW_DEF_CR_USB_MCU_EVENT_ADD, + .u4SerUsbHostAckAddr = WF_SW_DEF_CR_USB_HOST_ACK_ADDR, +#endif + .asicDumpSerDummyCR = mt7915DumpSerDummyCR, +#if CFG_ENABLE_FW_DOWNLOAD + .asicEnableFWDownload = NULL, +#endif /* CFG_ENABLE_FW_DOWNLOAD */ + .asicGetChipID = NULL, + .downloadBufferBin = wlanConnacDownloadBufferBin, + .is_support_hw_amsdu = TRUE, + .is_support_asic_lp = TRUE, + .is_support_wfdma1 = TRUE, + .asicWfdmaReInit = asicConnac2xWfdmaReInit, + .asicWfdmaReInit_handshakeInit = asicConnac2xWfdmaDummyCrWrite, + .group5_size = sizeof(struct HW_MAC_RX_STS_GROUP_5), + .wlanCheckAsicCap = mt7915CheckAsicCap, + .u4LmacWtblDUAddr = CONNAC2X_WIFI_LWTBL_BASE, + .u4UmacWtblDUAddr = CONNAC2X_WIFI_UWTBL_BASE, + .cmd_max_pkt_size = CFG_TX_MAX_PKT_SIZE, /* size 1600 */ +}; + +struct mt66xx_hif_driver_data mt66xx_driver_data_mt7915 = { + .chip_info = &mt66xx_chip_info_mt7915, +}; + +#endif /* MT7915 */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7961/dbg_mt7961.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7961/dbg_mt7961.c new file mode 100644 index 0000000000000..5864507cfa1d4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7961/dbg_mt7961.c @@ -0,0 +1,833 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** + *[File] dbg_mt7961.c + *[Version] v1.0 + *[Revision Date] 2019-04-09 + *[Author] + *[Description] + * The program provides WIFI FALCON MAC Debug APIs + *[Copyright] + * Copyright (C) 2015 MediaTek Incorporation. All Rights Reserved. + ******************************************************************************/ + +#ifdef MT7961 +/******************************************************************************* + * C O M P I L E 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 "coda/mt7961/wf_ple_top.h" +#include "coda/mt7961/wf_pse_top.h" +#include "precomp.h" +#include "mt_dmac.h" +#include "wf_ple.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +struct pse_group_info { + char name[8]; + u_int32_t quota_addr; + u_int32_t pg_info_addr; +}; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +static struct EMPTY_QUEUE_INFO ple_queue_empty_info[] = { + {"CPU Q0", MCU_Q0_INDEX, ENUM_UMAC_CTX_Q_0}, + {"CPU Q1", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_1}, + {"CPU Q2", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_2}, + {"CPU Q3", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_3}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, /* 4~7 not defined */ + {"ALTX Q0", ENUM_UMAC_LMAC_PORT_2, + ENUM_UMAC_LMAC_PLE_TX_Q_ALTX_0}, /* Q16 */ + {"BMC Q0", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_BMC_0}, + {"BCN Q0", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_BNC_0}, + {"PSMP Q0", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_PSMP_0}, + {"ALTX Q1", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_ALTX_1}, + {"BMC Q1", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_BMC_1}, + {"BCN Q1", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_BNC_1}, + {"PSMP Q1", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_PSMP_1}, + {"NAF Q", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_NAF}, + {"NBCN Q", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_NBCN}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, /* 18~29 not defined */ + {"RLS Q", ENUM_PLE_CTRL_PSE_PORT_3, ENUM_UMAC_PLE_CTRL_P3_Q_0X1E}, + {"RLS2 Q", ENUM_PLE_CTRL_PSE_PORT_3, ENUM_UMAC_PLE_CTRL_P3_Q_0X1F} }; + +static struct EMPTY_QUEUE_INFO pse_queue_empty_info[] = { + {"CPU Q0", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_0}, + {"CPU Q1", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_1}, + {"CPU Q2", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_2}, + {"CPU Q3", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_3}, + {"HIF Q8", ENUM_UMAC_HIF_PORT_0, 8}, + {"HIF Q9", ENUM_UMAC_HIF_PORT_0, 9}, + {"HIF Q10", ENUM_UMAC_HIF_PORT_0, 10}, + {"HIF Q11", ENUM_UMAC_HIF_PORT_0, 11}, + {"HIF Q0", ENUM_UMAC_HIF_PORT_0, 0}, /*bit 8*/ + {"HIF Q1", ENUM_UMAC_HIF_PORT_0, 1}, + {"HIF Q2", ENUM_UMAC_HIF_PORT_0, 2}, + {"HIF Q3", ENUM_UMAC_HIF_PORT_0, 3}, + {"HIF Q4", ENUM_UMAC_HIF_PORT_0, 4}, + {"HIF Q5", ENUM_UMAC_HIF_PORT_0, 5}, + {"HIF Q6", ENUM_UMAC_HIF_PORT_0, 6}, + {"HIF Q7", ENUM_UMAC_HIF_PORT_0, 7}, + {"LMAC Q", ENUM_UMAC_LMAC_PORT_2, 0}, /*bit 16*/ + {"MDP TX Q", ENUM_UMAC_LMAC_PORT_2, 1}, + {"MDP RX Q", ENUM_UMAC_LMAC_PORT_2, 2}, + {"SEC TX Q", ENUM_UMAC_LMAC_PORT_2, 3}, + {"SEC RX Q", ENUM_UMAC_LMAC_PORT_2, 4}, + {"SFD_PARK Q", ENUM_UMAC_LMAC_PORT_2, 5}, + {"MDP_TXIOC Q", ENUM_UMAC_LMAC_PORT_2, 6}, + {"MDP_RXIOC Q", ENUM_UMAC_LMAC_PORT_2, 7}, + {"MDP_TX1 Q", ENUM_UMAC_LMAC_PORT_2, 17}, /*bit 24*/ + {"SEC_TX1 Q", ENUM_UMAC_LMAC_PORT_2, 19}, + {"MDP_TXIOC1 Q", ENUM_UMAC_LMAC_PORT_2, 22}, + {"MDP_RXIOC1 Q", ENUM_UMAC_LMAC_PORT_2, 23}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, /* 28~30 not defined */ + {"RLS Q", ENUM_PLE_CTRL_PSE_PORT_3, ENUM_UMAC_PLE_CTRL_P3_Q_0X1F} }; + +static u_int8_t *sta_ctrl_reg[] = {"ENABLE", "DISABLE", "PAUSE"}; + +#if 0 +static struct EMPTY_QUEUE_INFO ple_txcmd_queue_empty_info[] = { + {"AC00Q", ENUM_UMAC_LMAC_PORT_2, 0x40}, + {"AC01Q", ENUM_UMAC_LMAC_PORT_2, 0x41}, + {"AC02Q", ENUM_UMAC_LMAC_PORT_2, 0x42}, + {"AC03Q", ENUM_UMAC_LMAC_PORT_2, 0x43}, + {"AC10Q", ENUM_UMAC_LMAC_PORT_2, 0x44}, + {"AC11Q", ENUM_UMAC_LMAC_PORT_2, 0x45}, + {"AC12Q", ENUM_UMAC_LMAC_PORT_2, 0x46}, + {"AC13Q", ENUM_UMAC_LMAC_PORT_2, 0x47}, + {"AC20Q", ENUM_UMAC_LMAC_PORT_2, 0x48}, + {"AC21Q", ENUM_UMAC_LMAC_PORT_2, 0x49}, + {"AC22Q", ENUM_UMAC_LMAC_PORT_2, 0x4a}, + {"AC23Q", ENUM_UMAC_LMAC_PORT_2, 0x4b}, + {"AC30Q", ENUM_UMAC_LMAC_PORT_2, 0x4c}, + {"AC31Q", ENUM_UMAC_LMAC_PORT_2, 0x4d}, + {"AC32Q", ENUM_UMAC_LMAC_PORT_2, 0x4e}, + {"AC33Q", ENUM_UMAC_LMAC_PORT_2, 0x4f}, + {"ALTX Q0", ENUM_UMAC_LMAC_PORT_2, 0x50}, + {"TF Q0", ENUM_UMAC_LMAC_PORT_2, 0x51}, + {"TWT TSF-TF Q0", ENUM_UMAC_LMAC_PORT_2, 0x52}, + {"TWT DL Q0", ENUM_UMAC_LMAC_PORT_2, 0x53}, + {"TWT UL Q0", ENUM_UMAC_LMAC_PORT_2, 0x54}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0} }; +#endif + + + +struct pse_group_info pse_group[] = { + {"HIF0", WF_PSE_TOP_PG_HIF0_GROUP_ADDR, WF_PSE_TOP_HIF0_PG_INFO_ADDR}, + {"HIF1", WF_PSE_TOP_PG_HIF1_GROUP_ADDR, WF_PSE_TOP_HIF1_PG_INFO_ADDR}, + {"HIF2", WF_PSE_TOP_PG_HIF2_GROUP_ADDR, WF_PSE_TOP_HIF2_PG_INFO_ADDR}, + {"CPU", WF_PSE_TOP_PG_CPU_GROUP_ADDR, WF_PSE_TOP_CPU_PG_INFO_ADDR}, + {"PLE", WF_PSE_TOP_PG_PLE_GROUP_ADDR, WF_PSE_TOP_PLE_PG_INFO_ADDR}, + {"PLE1", WF_PSE_TOP_PG_PLE1_GROUP_ADDR, WF_PSE_TOP_PLE1_PG_INFO_ADDR}, + {"LMAC0", WF_PSE_TOP_PG_LMAC0_GROUP_ADDR, + WF_PSE_TOP_LMAC0_PG_INFO_ADDR}, + {"LMAC1", WF_PSE_TOP_PG_LMAC1_GROUP_ADDR, + WF_PSE_TOP_LMAC1_PG_INFO_ADDR}, + {"LMAC2", WF_PSE_TOP_PG_LMAC2_GROUP_ADDR, + WF_PSE_TOP_LMAC2_PG_INFO_ADDR}, + {"LMAC3", WF_PSE_TOP_PG_LMAC3_GROUP_ADDR, + WF_PSE_TOP_LMAC3_PG_INFO_ADDR}, + {"MDP", WF_PSE_TOP_PG_MDP_GROUP_ADDR, WF_PSE_TOP_MDP_PG_INFO_ADDR}, + {"MDP1", WF_PSE_TOP_PG_MDP1_GROUP_ADDR, WF_PSE_TOP_MDP1_PG_INFO_ADDR}, + {"MDP2", WF_PSE_TOP_PG_MDP2_GROUP_ADDR, WF_PSE_TOP_MDP2_PG_INFO_ADDR}, +}; + +/******************************************************************************* + * M A 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 mt7961_show_ple_info( + struct ADAPTER *prAdapter, + u_int8_t fgDumpTxd) +{ + u_int32_t ple_buf_ctrl, pg_sz, pg_num; + u_int32_t ple_stat[25] = {0}, pg_flow_ctrl[8] = {0}; + u_int32_t sta_pause[6] = {0}, dis_sta_map[6] = {0}; + u_int32_t fpg_cnt, ffa_cnt, fpg_head, fpg_tail, hif_max_q, hif_min_q; + u_int32_t rpg_hif, upg_hif, cpu_max_q, cpu_min_q, rpg_cpu, upg_cpu; + u_int32_t i, j; +#if 0 + u_int32_t ple_txcmd_stat; +#endif + + HAL_MCR_RD(prAdapter, WF_PLE_TOP_PBUF_CTRL_ADDR, &ple_buf_ctrl); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_QUEUE_EMPTY_ADDR, &ple_stat[0]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC0_QUEUE_EMPTY0_ADDR, &ple_stat[1]); +#if 0 + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC0_QUEUE_EMPTY1_ADDR, &ple_stat[2]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC0_QUEUE_EMPTY2_ADDR, &ple_stat[3]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC0_QUEUE_EMPTY3_ADDR, &ple_stat[4]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC0_QUEUE_EMPTY4_ADDR, &ple_stat[5]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC0_QUEUE_EMPTY5_ADDR, &ple_stat[6]); +#endif + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC1_QUEUE_EMPTY0_ADDR, &ple_stat[7]); +#if 0 + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC1_QUEUE_EMPTY1_ADDR, &ple_stat[8]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC1_QUEUE_EMPTY2_ADDR, &ple_stat[9]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC1_QUEUE_EMPTY3_ADDR, &ple_stat[10]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC1_QUEUE_EMPTY4_ADDR, &ple_stat[11]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC1_QUEUE_EMPTY5_ADDR, &ple_stat[12]); +#endif + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC2_QUEUE_EMPTY0_ADDR, &ple_stat[13]); +#if 0 + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC2_QUEUE_EMPTY1_ADDR, &ple_stat[14]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC2_QUEUE_EMPTY2_ADDR, &ple_stat[15]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC2_QUEUE_EMPTY3_ADDR, &ple_stat[16]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC2_QUEUE_EMPTY4_ADDR, &ple_stat[17]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC2_QUEUE_EMPTY5_ADDR, &ple_stat[18]); +#endif + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC3_QUEUE_EMPTY0_ADDR, &ple_stat[19]); +#if 0 + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC3_QUEUE_EMPTY1_ADDR, &ple_stat[20]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC3_QUEUE_EMPTY2_ADDR, &ple_stat[21]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC3_QUEUE_EMPTY3_ADDR, &ple_stat[22]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC3_QUEUE_EMPTY4_ADDR, &ple_stat[23]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC3_QUEUE_EMPTY5_ADDR, &ple_stat[24]); +#endif +#if 0 + HAL_MCR_RD(prAdapter, WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR, + &ple_txcmd_stat); +#endif + HAL_MCR_RD(prAdapter, WF_PLE_TOP_FREEPG_CNT_ADDR, &pg_flow_ctrl[0]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_FREEPG_HEAD_TAIL_ADDR, + &pg_flow_ctrl[1]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_PG_HIF_GROUP_ADDR, &pg_flow_ctrl[2]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_HIF_PG_INFO_ADDR, &pg_flow_ctrl[3]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_PG_CPU_GROUP_ADDR, &pg_flow_ctrl[4]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_CPU_PG_INFO_ADDR, &pg_flow_ctrl[5]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_PG_HIF_TXCMD_GROUP_ADDR, + &pg_flow_ctrl[6]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_HIF_TXCMD_PG_INFO_ADDR, + &pg_flow_ctrl[7]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_DIS_STA_MAP0_ADDR, &dis_sta_map[0]); +#if 0 + HAL_MCR_RD(prAdapter, WF_PLE_TOP_DIS_STA_MAP1_ADDR, &dis_sta_map[1]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_DIS_STA_MAP2_ADDR, &dis_sta_map[2]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_DIS_STA_MAP3_ADDR, &dis_sta_map[3]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_DIS_STA_MAP4_ADDR, &dis_sta_map[4]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_DIS_STA_MAP5_ADDR, &dis_sta_map[5]); +#endif + HAL_MCR_RD(prAdapter, WF_PLE_TOP_STATION_PAUSE0_ADDR, &sta_pause[0]); +#if 0 + HAL_MCR_RD(prAdapter, WF_PLE_TOP_STATION_PAUSE1_ADDR, &sta_pause[1]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_STATION_PAUSE2_ADDR, &sta_pause[2]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_STATION_PAUSE3_ADDR, &sta_pause[3]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_STATION_PAUSE4_ADDR, &sta_pause[4]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_STATION_PAUSE5_ADDR, &sta_pause[5]); +#endif + /* Configuration Info */ + DBGLOG(HAL, INFO, "PLE Configuration Info:\n"); + + DBGLOG(HAL, INFO, "\tPacket Buffer Control(0x%08x): 0x%08x\n", + WF_PLE_TOP_PBUF_CTRL_ADDR, + ple_buf_ctrl); + pg_sz = (ple_buf_ctrl & WF_PLE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_MASK) >> + WF_PLE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_SHFT; + DBGLOG(HAL, INFO, "\t\tPage Size=%d(%d bytes per page)\n", pg_sz, + (pg_sz == 1 ? 128 : 64)); + DBGLOG(HAL, INFO, "\t\tPage Offset=%d(in unit of 2KB)\n", + (ple_buf_ctrl & WF_PLE_TOP_PBUF_CTRL_PBUF_OFFSET_MASK) >> + WF_PLE_TOP_PBUF_CTRL_PBUF_OFFSET_SHFT); + pg_num = (ple_buf_ctrl & WF_PLE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_MASK) >> + WF_PLE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_SHFT; + DBGLOG(HAL, INFO, "\t\tTotal Page=%d pages\n", pg_num); + + /* Page Flow Control */ + DBGLOG(HAL, INFO, "PLE Page Flow Control:\n"); + DBGLOG(HAL, INFO, "\tFree page counter(0x%08x): 0x%08x\n", + WF_PLE_TOP_FREEPG_CNT_ADDR, + pg_flow_ctrl[0]); + fpg_cnt = (pg_flow_ctrl[0] & WF_PLE_TOP_FREEPG_CNT_FREEPG_CNT_MASK) >> + WF_PLE_TOP_FREEPG_CNT_FREEPG_CNT_SHFT; + DBGLOG(HAL, INFO, "\t\tThe toal page number of free=0x%03x\n", fpg_cnt); + ffa_cnt = (pg_flow_ctrl[0] & WF_PLE_TOP_FREEPG_CNT_FFA_CNT_MASK) >> + WF_PLE_TOP_FREEPG_CNT_FFA_CNT_SHFT; + DBGLOG(HAL, INFO, "\t\tThe free page numbers of free for all=0x%03x\n", + ffa_cnt); + DBGLOG(HAL, INFO, "\tFree page head and tail(0x%08x): 0x%08x\n", + WF_PLE_TOP_FREEPG_HEAD_TAIL_ADDR, + pg_flow_ctrl[1]); + fpg_head = (pg_flow_ctrl[1] & + WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_MASK) >> + WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_SHFT; + fpg_tail = (pg_flow_ctrl[1] & + WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_MASK) >> + WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe tail/head page of free page list=0x%03x/0x%03x\n", + fpg_tail, fpg_head); + DBGLOG(HAL, INFO, + "\tReserved page counter of HIF group(0x%08x): 0x%08x\n", + WF_PLE_TOP_PG_HIF_GROUP_ADDR, + pg_flow_ctrl[2]); + DBGLOG(HAL, INFO, "\tHIF group page status(0x%08x): 0x%08x\n", + WF_PLE_TOP_HIF_PG_INFO_ADDR, + pg_flow_ctrl[3]); + hif_min_q = (pg_flow_ctrl[2] & + WF_PLE_TOP_PG_HIF_GROUP_HIF_MIN_QUOTA_MASK) >> + WF_PLE_TOP_PG_HIF_GROUP_HIF_MIN_QUOTA_SHFT; + hif_max_q = (pg_flow_ctrl[2] & + WF_PLE_TOP_PG_HIF_GROUP_HIF_MAX_QUOTA_MASK) >> + WF_PLE_TOP_PG_HIF_GROUP_HIF_MAX_QUOTA_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of HIF group=0x%03x/0x%03x\n", + hif_max_q, hif_min_q); + rpg_hif = (pg_flow_ctrl[3] & WF_PLE_TOP_HIF_PG_INFO_HIF_RSV_CNT_MASK) >> + WF_PLE_TOP_HIF_PG_INFO_HIF_RSV_CNT_SHFT; + upg_hif = (pg_flow_ctrl[3] & WF_PLE_TOP_HIF_PG_INFO_HIF_SRC_CNT_MASK) >> + WF_PLE_TOP_HIF_PG_INFO_HIF_SRC_CNT_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of HIF group=0x%03x/0x%03x\n", + upg_hif, rpg_hif); + + DBGLOG(HAL, INFO, + "\tReserved page counter of HIF_TXCMD group(0x%08x): 0x%08x\n", + WF_PLE_TOP_PG_HIF_WMTXD_GROUP_ADDR, + pg_flow_ctrl[6]); + DBGLOG(HAL, INFO, "\tHIF_TXCMD group page status(0x%08x): 0x%08x\n", + WF_PLE_TOP_HIF_WMTXD_PG_INFO_ADDR, + pg_flow_ctrl[7]); + cpu_min_q = (pg_flow_ctrl[6] & + WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MIN_QUOTA_MASK) >> + WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MIN_QUOTA_SHFT; + cpu_max_q = (pg_flow_ctrl[6] & + WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MAX_QUOTA_MASK) >> + WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MAX_QUOTA_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of HIF_TXCMD group=0x%03x/0x%03x\n", + cpu_max_q, cpu_min_q); + rpg_cpu = (pg_flow_ctrl[7] & + WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_SRC_CNT_MASK) >> + WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_SRC_CNT_SHFT; + upg_cpu = (pg_flow_ctrl[7] & + WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_RSV_CNT_MASK) >> + WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_RSV_CNT_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of HIF_TXCMD group=0x%03x/0x%03x\n", + upg_cpu, rpg_cpu); + + DBGLOG(HAL, INFO, + "\tReserved page counter of CPU group(0x%08x): 0x%08x\n", + WF_PLE_TOP_PG_CPU_GROUP_ADDR, + pg_flow_ctrl[4]); + DBGLOG(HAL, INFO, "\tCPU group page status(0x%08x): 0x%08x\n", + WF_PLE_TOP_CPU_PG_INFO_ADDR, + pg_flow_ctrl[5]); + cpu_min_q = (pg_flow_ctrl[4] & + WF_PLE_TOP_PG_CPU_GROUP_CPU_MIN_QUOTA_MASK) >> + WF_PLE_TOP_PG_CPU_GROUP_CPU_MIN_QUOTA_SHFT; + cpu_max_q = (pg_flow_ctrl[4] & + WF_PLE_TOP_PG_CPU_GROUP_CPU_MAX_QUOTA_MASK) >> + WF_PLE_TOP_PG_CPU_GROUP_CPU_MAX_QUOTA_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of CPU group=0x%03x/0x%03x\n", + cpu_max_q, cpu_min_q); + rpg_cpu = (pg_flow_ctrl[5] & WF_PLE_TOP_CPU_PG_INFO_CPU_RSV_CNT_MASK) >> + WF_PLE_TOP_CPU_PG_INFO_CPU_RSV_CNT_SHFT; + upg_cpu = (pg_flow_ctrl[5] & WF_PLE_TOP_CPU_PG_INFO_CPU_SRC_CNT_MASK) >> + WF_PLE_TOP_CPU_PG_INFO_CPU_SRC_CNT_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of CPU group=0x%03x/0x%03x\n", + upg_cpu, rpg_cpu); + + if ((ple_stat[0] & WF_PLE_TOP_QUEUE_EMPTY_ALL_AC_EMPTY_MASK) == 0) { + for (j = 0; j < 24; j = j + 6) { + if (j % 6 == 0) { + DBGLOG(HAL, INFO, + "\tNonempty AC%d Q of STA#: ", j / 6); + } + + for (i = 0; i < 32; i++) { + if (((ple_stat[j + 1] & (0x1 << i)) >> i) == + 0) { + DBGLOG(HAL, INFO, "%d ", + i + (j % 6) * 32); + } + } + } + + DBGLOG(HAL, INFO, "\n"); + } + + DBGLOG(HAL, INFO, "Nonempty Q info:\n"); + + for (i = 0; i < 31; i++) { + if (((ple_stat[0] & (0x1 << i)) >> i) == 0) { + uint32_t hfid, tfid, pktcnt, fl_que_ctrl[3] = {0}; + + if (ple_queue_empty_info[i].QueueName != NULL) { + DBGLOG(HAL, INFO, "\t%s: ", + ple_queue_empty_info[i].QueueName); + fl_que_ctrl[0] |= + WF_PLE_TOP_FL_QUE_CTRL_0_EXECUTE_MASK; + fl_que_ctrl[0] |= + (ple_queue_empty_info[i].Portid + << WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_SHFT); + fl_que_ctrl[0] |= + (ple_queue_empty_info[i].Queueid + << WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_SHFT); + } else + continue; + + HAL_MCR_WR(prAdapter, WF_PLE_TOP_FL_QUE_CTRL_0_ADDR, + fl_que_ctrl[0]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_FL_QUE_CTRL_2_ADDR, + &fl_que_ctrl[1]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_FL_QUE_CTRL_3_ADDR, + &fl_que_ctrl[2]); + hfid = (fl_que_ctrl[1] & + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_SHFT; + tfid = (fl_que_ctrl[1] & + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_SHFT; + pktcnt = + (fl_que_ctrl[2] & + WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_SHFT; + DBGLOG(HAL, INFO, + "tail/head fid = 0x%03x/0x%03x, pkt cnt = 0x%03x\n", + tfid, hfid, pktcnt); + if (pktcnt > 0 && fgDumpTxd) + connac2x_show_txd_Info( + prAdapter, hfid); + } + } + + for (j = 0; j < 24; j = j + 6) { /* show AC Q info */ + for (i = 0; i < 32; i++) { + if (((ple_stat[j + 1] & (0x1 << i)) >> i) == 0) { + uint32_t hfid, tfid, pktcnt, ac_num = j / 6, + ctrl = 0; + uint32_t sta_num = i + (j % 6) * 32, + fl_que_ctrl[3] = {0}; + uint32_t wmmidx = 0; + + DBGLOG(HAL, INFO, "\tSTA%d AC%d: ", sta_num, + ac_num); + + fl_que_ctrl[0] |= + WF_PLE_TOP_FL_QUE_CTRL_0_EXECUTE_MASK; + fl_que_ctrl[0] |= + (ENUM_UMAC_LMAC_PORT_2 + << WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_SHFT); + fl_que_ctrl[0] |= + (ac_num + << WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_SHFT); + fl_que_ctrl[0] |= + (sta_num + << WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_WLANID_SHFT); + HAL_MCR_WR(prAdapter, + WF_PLE_TOP_FL_QUE_CTRL_0_ADDR, + fl_que_ctrl[0]); + HAL_MCR_RD(prAdapter, + WF_PLE_TOP_FL_QUE_CTRL_2_ADDR, + &fl_que_ctrl[1]); + HAL_MCR_RD(prAdapter, + WF_PLE_TOP_FL_QUE_CTRL_3_ADDR, + &fl_que_ctrl[2]); + hfid = (fl_que_ctrl[1] & + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_SHFT; + tfid = (fl_que_ctrl[1] & + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_SHFT; + + pktcnt = + (fl_que_ctrl[2] & + WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_SHFT; + DBGLOG(HAL, INFO, + "tail/head fid = 0x%03x/0x%03x, pkt cnt = %x", + tfid, hfid, pktcnt); + + if (((sta_pause[j % 6] & 0x1 << i) >> i) == 1) + ctrl = 2; + + if (((dis_sta_map[j % 6] & 0x1 << i) >> i) == 1) + ctrl = 1; + + DBGLOG(HAL, INFO, " ctrl = %s", + sta_ctrl_reg[ctrl]); + DBGLOG(HAL, INFO, " (wmmidx=%d)\n", + wmmidx); + if (pktcnt > 0 && fgDumpTxd) + connac2x_show_txd_Info( + prAdapter, hfid); + } + } + } +#if 0 + if (~ple_txcmd_stat) { + DBGLOG(HAL, INFO, "Nonempty TXCMD Q info:\n"); + for (i = 0; i < 31; i++) { + if (((ple_txcmd_stat & (0x1 << i)) >> i) == 0) { + uint32_t hfid, tfid; + uint32_t pktcnt, fl_que_ctrl[3] = {0}; + + if (ple_txcmd_queue_empty_info[i].QueueName != + NULL) { + DBGLOG(HAL, INFO, "\t%s: ", + ple_txcmd_queue_empty_info[i] + .QueueName); + fl_que_ctrl[0] |= + WF_PLE_TOP_FL_QUE_CTRL_0_EXECUTE_MASK; + fl_que_ctrl[0] |= + (ple_txcmd_queue_empty_info[i] + .Portid + << WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_SHFT); + fl_que_ctrl[0] |= + (ple_txcmd_queue_empty_info[i] + .Queueid + << WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_SHFT); + } else + continue; + + HAL_MCR_WR(prAdapter, + WF_PLE_TOP_FL_QUE_CTRL_0_ADDR, + fl_que_ctrl[0]); + HAL_MCR_RD(prAdapter, + WF_PLE_TOP_FL_QUE_CTRL_2_ADDR, + &fl_que_ctrl[1]); + HAL_MCR_RD(prAdapter, + WF_PLE_TOP_FL_QUE_CTRL_3_ADDR, + &fl_que_ctrl[2]); + hfid = (fl_que_ctrl[1] & + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_SHFT; + tfid = (fl_que_ctrl[1] & + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_SHFT; + pktcnt = + (fl_que_ctrl[2] & + WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_SHFT; + DBGLOG(HAL, INFO, "tail/head fid ="); + DBGLOG(HAL, INFO, "0x%03x/0x%03x,", tfid, hfid); + DBGLOG(HAL, INFO, "pkt cnt = 0x%03x\n", pktcnt); + } + } + } +#endif +} + +void mt7961_show_pse_info( + struct ADAPTER *prAdapter) +{ + u_int32_t pse_buf_ctrl, pg_sz, pg_num; + u_int32_t pse_stat; + u_int32_t fpg_cnt, ffa_cnt, fpg_head, fpg_tail; + u_int32_t max_q, min_q, rsv_pg, used_pg; + u_int32_t i, group_cnt; + u_int32_t group_quota, group_info, freepg_cnt, freepg_head_tail; + struct pse_group_info *group; + char *str; + + HAL_MCR_RD(prAdapter, WF_PSE_TOP_PBUF_CTRL_ADDR, &pse_buf_ctrl); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_QUEUE_EMPTY_ADDR, &pse_stat); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_FREEPG_CNT_ADDR, &freepg_cnt); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_FREEPG_HEAD_TAIL_ADDR, + &freepg_head_tail); + + /* Configuration Info */ + DBGLOG(HAL, INFO, "PSE Configuration Info:\n"); + DBGLOG(HAL, INFO, "\tPacket Buffer Control(0x%08x): 0x%08x\n", + WF_PSE_TOP_PBUF_CTRL_ADDR, + pse_buf_ctrl); + pg_sz = (pse_buf_ctrl & WF_PSE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_MASK) >> + WF_PSE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_SHFT; + DBGLOG(HAL, INFO, "\t\tPage Size=%d(%d bytes per page)\n", pg_sz, + (pg_sz == 1 ? 256 : 128)); + DBGLOG(HAL, INFO, "\t\tPage Offset=%d(in unit of 64KB)\n", + (pse_buf_ctrl & WF_PSE_TOP_PBUF_CTRL_PBUF_OFFSET_MASK) >> + WF_PSE_TOP_PBUF_CTRL_PBUF_OFFSET_SHFT); + pg_num = (pse_buf_ctrl & WF_PSE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_MASK) >> + WF_PSE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_SHFT; + DBGLOG(HAL, INFO, "\t\tTotal page numbers=%d pages\n", pg_num); + /* Page Flow Control */ + DBGLOG(HAL, INFO, "PSE Page Flow Control:\n"); + DBGLOG(HAL, INFO, "\tFree page counter(0x%08x): 0x%08x\n", + WF_PSE_TOP_FREEPG_CNT_ADDR, freepg_cnt); + fpg_cnt = (freepg_cnt & WF_PSE_TOP_FREEPG_CNT_FREEPG_CNT_MASK) >> + WF_PSE_TOP_FREEPG_CNT_FREEPG_CNT_SHFT; + DBGLOG(HAL, INFO, "\t\tThe toal page number of free=0x%03x\n", fpg_cnt); + ffa_cnt = (freepg_cnt & WF_PSE_TOP_FREEPG_CNT_FFA_CNT_MASK) >> + WF_PSE_TOP_FREEPG_CNT_FFA_CNT_SHFT; + DBGLOG(HAL, INFO, "\t\tThe free page numbers of free for all=0x%03x\n", + ffa_cnt); + DBGLOG(HAL, INFO, "\tFree page head and tail(0x%08x): 0x%08x\n", + WF_PSE_TOP_FREEPG_HEAD_TAIL_ADDR, freepg_head_tail); + fpg_head = (freepg_head_tail & + WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_MASK) >> + WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_SHFT; + fpg_tail = (freepg_head_tail & + WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_MASK) >> + WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe tail/head page of free page list=0x%03x/0x%03x\n", + fpg_tail, fpg_head); + + group_cnt = sizeof(pse_group) / sizeof(struct pse_group_info); + for (i = 0; i < group_cnt; i++) { + group = &pse_group[i]; + HAL_MCR_RD(prAdapter, group->quota_addr, &group_quota); + HAL_MCR_RD(prAdapter, group->pg_info_addr, &group_info); + + DBGLOG(HAL, INFO, + "\tReserved page counter of %s group(0x%08x): 0x%08x\n", + group->name, group->quota_addr, group_quota); + DBGLOG(HAL, INFO, "\t%s group page status(0x%08x): 0x%08x\n", + group->name, group->pg_info_addr, group_info); + min_q = (group_quota & + WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MIN_QUOTA_MASK) >> + WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MIN_QUOTA_SHFT; + max_q = (group_quota & + WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MAX_QUOTA_MASK) >> + WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MAX_QUOTA_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of %s group=0x%03x/0x%03x\n", + group->name, max_q, min_q); + rsv_pg = + (group_info & WF_PSE_TOP_HIF0_PG_INFO_HIF0_RSV_CNT_MASK) >> + WF_PSE_TOP_HIF0_PG_INFO_HIF0_RSV_CNT_SHFT; + used_pg = + (group_info & WF_PSE_TOP_HIF0_PG_INFO_HIF0_SRC_CNT_MASK) >> + WF_PSE_TOP_HIF0_PG_INFO_HIF0_SRC_CNT_SHFT; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of %s group=0x%03x/0x%03x\n", + group->name, used_pg, rsv_pg); + } + + /* Queue Empty Status */ + DBGLOG(HAL, INFO, "PSE Queue Empty Status:\n"); + DBGLOG(HAL, INFO, "\tQUEUE_EMPTY(0x%08x): 0x%08x\n", + WF_PSE_TOP_QUEUE_EMPTY_ADDR, + pse_stat); + DBGLOG(HAL, INFO, "\t\tCPU Q0/1/2/3 empty=%d/%d/%d/%d\n", + (pse_stat & WF_PSE_TOP_QUEUE_EMPTY_CPU_Q0_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_CPU_Q0_EMPTY_SHFT, + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_CPU_Q1_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_CPU_Q1_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_CPU_Q2_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_CPU_Q2_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_CPU_Q3_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_CPU_Q3_EMPTY_SHFT)); + str = "\t\tHIF Q0/1/2/3/4/5/6/7/8/9/10/11"; + DBGLOG(HAL, INFO, + "%s empty=%d/%d/%d/%d/%d/%d/%d/%d/%d/%d/%d/%d\n", str, + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_0_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_0_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_1_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_1_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_2_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_2_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_3_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_3_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_4_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_4_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_5_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_5_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_6_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_6_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_7_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_7_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_8_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_8_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_9_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_9_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_10_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_10_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_11_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_11_EMPTY_SHFT)); + DBGLOG(HAL, INFO, "\t\tLMAC TX Q empty=%d\n", + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_LMAC_TX_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_LMAC_TX_QUEUE_EMPTY_SHFT)); + DBGLOG(HAL, INFO, "\t\tMDP TX Q/RX Q empty=%d/%d\n", + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_MDP_TX_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_MDP_TX_QUEUE_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_MDP_RX_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_MDP_RX_QUEUE_EMPTY_SHFT)); + DBGLOG(HAL, INFO, "\t\tSEC TX Q/RX Q empty=%d/%d\n", + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_SEC_TX_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_SEC_TX_QUEUE_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_SEC_RX_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_SEC_RX_QUEUE_EMPTY_SHFT)); + DBGLOG(HAL, INFO, "\t\tSFD PARK Q empty=%d\n", + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_SFD_PARK_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_SFD_PARK_QUEUE_EMPTY_SHFT)); + DBGLOG(HAL, INFO, "\t\tMDP TXIOC Q/RXIOC Q empty=%d/%d\n", + ((pse_stat & + WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC_QUEUE_EMPTY_SHFT), + ((pse_stat & + WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC_QUEUE_EMPTY_SHFT)); + DBGLOG(HAL, INFO, "\t\tMDP TX1 Q empty=%d\n", + ((pse_stat & + WF_PSE_TOP_QUEUE_EMPTY_MDP_TX1_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_MDP_TX1_QUEUE_EMPTY_SHFT)); + DBGLOG(HAL, INFO, "\t\tSEC TX1 Q empty=%d\n", + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_SEC_TX1_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_SEC_TX1_QUEUE_EMPTY_SHFT)); + DBGLOG(HAL, INFO, "\t\tMDP TXIOC1 Q/RXIOC1 Q empty=%d/%d\n", + ((pse_stat & + WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC1_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC1_QUEUE_EMPTY_SHFT), + ((pse_stat & + WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC1_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC1_QUEUE_EMPTY_SHFT)); + DBGLOG(HAL, INFO, "\t\tRLS Q empty=%d\n", + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_RLS_Q_EMTPY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_RLS_Q_EMTPY_SHFT)); + DBGLOG(HAL, INFO, "Nonempty Q info:\n"); + + for (i = 0; i < 31; i++) { + if (((pse_stat & (0x1 << i)) >> i) == 0) { + uint32_t hfid, tfid, pktcnt, fl_que_ctrl[3] = {0}; + + if (pse_queue_empty_info[i].QueueName != NULL) { + DBGLOG(HAL, INFO, "\t%s: ", + pse_queue_empty_info[i].QueueName); + fl_que_ctrl[0] |= + WF_PSE_TOP_FL_QUE_CTRL_0_EXECUTE_MASK; + fl_que_ctrl[0] |= + (pse_queue_empty_info[i].Portid + << WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_SHFT); + fl_que_ctrl[0] |= + (pse_queue_empty_info[i].Queueid + << WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_SHFT); + } else + continue; + + fl_que_ctrl[0] |= (0x1 << 31); + HAL_MCR_WR(prAdapter, WF_PSE_TOP_FL_QUE_CTRL_0_ADDR, + fl_que_ctrl[0]); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_FL_QUE_CTRL_2_ADDR, + &fl_que_ctrl[1]); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_FL_QUE_CTRL_3_ADDR, + &fl_que_ctrl[2]); + hfid = (fl_que_ctrl[1] & + WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_MASK) >> + WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_SHFT; + tfid = (fl_que_ctrl[1] & + WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_MASK) >> + WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_SHFT; + pktcnt = + (fl_que_ctrl[2] & + WF_PSE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_MASK) >> + WF_PSE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_SHFT; + DBGLOG(HAL, INFO, + "tail/head fid = 0x%03x/0x%03x, pkt cnt = 0x%03x\n", + tfid, hfid, pktcnt); + } + } +} +#endif /* MT7961 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7961/hal_dmashdl_mt7961.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7961/hal_dmashdl_mt7961.c new file mode 100644 index 0000000000000..8a3ead51f43d9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7961/hal_dmashdl_mt7961.c @@ -0,0 +1,411 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2019 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file hal_dmashdl_mt7961.c +* \brief DMASHDL HAL API for MT7961 +* +* This file contains all routines which are exported + from MediaTek 802.11 Wireless LAN driver stack to GLUE Layer. +*/ + +#ifdef MT7961 +#if defined(_HIF_PCIE) || defined(_HIF_AXI) || defined(_HIF_USB) + +/******************************************************************************* +* C O M P I L E 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 "mt7961.h" +#include "coda/mt7961/wf_hif_dmashdl_top.h" +#include "hal_dmashdl_mt7961.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +struct MT7961_DMASHDL_CFG rMT7961DmashdlCfg = { + .fgSlotArbiterEn = MT7961_DMASHDL_SLOT_ARBITER_EN, + + .u2PktPleMaxPage = MT7961_DMASHDL_PKT_PLE_MAX_PAGE, + + .u2PktPseMaxPage = MT7961_DMASHDL_PKT_PSE_MAX_PAGE, + + .afgRefillEn = { + MT7961_DMASHDL_GROUP_0_REFILL_EN, + MT7961_DMASHDL_GROUP_1_REFILL_EN, + MT7961_DMASHDL_GROUP_2_REFILL_EN, + MT7961_DMASHDL_GROUP_3_REFILL_EN, + MT7961_DMASHDL_GROUP_4_REFILL_EN, + MT7961_DMASHDL_GROUP_5_REFILL_EN, + MT7961_DMASHDL_GROUP_6_REFILL_EN, + MT7961_DMASHDL_GROUP_7_REFILL_EN, + MT7961_DMASHDL_GROUP_8_REFILL_EN, + MT7961_DMASHDL_GROUP_9_REFILL_EN, + MT7961_DMASHDL_GROUP_10_REFILL_EN, + MT7961_DMASHDL_GROUP_11_REFILL_EN, + MT7961_DMASHDL_GROUP_12_REFILL_EN, + MT7961_DMASHDL_GROUP_13_REFILL_EN, + MT7961_DMASHDL_GROUP_14_REFILL_EN, + MT7961_DMASHDL_GROUP_15_REFILL_EN, + }, + + .au2MaxQuota = { + MT7961_DMASHDL_GROUP_0_MAX_QUOTA, + MT7961_DMASHDL_GROUP_1_MAX_QUOTA, + MT7961_DMASHDL_GROUP_2_MAX_QUOTA, + MT7961_DMASHDL_GROUP_3_MAX_QUOTA, + MT7961_DMASHDL_GROUP_4_MAX_QUOTA, + MT7961_DMASHDL_GROUP_5_MAX_QUOTA, + MT7961_DMASHDL_GROUP_6_MAX_QUOTA, + MT7961_DMASHDL_GROUP_7_MAX_QUOTA, + MT7961_DMASHDL_GROUP_8_MAX_QUOTA, + MT7961_DMASHDL_GROUP_9_MAX_QUOTA, + MT7961_DMASHDL_GROUP_10_MAX_QUOTA, + MT7961_DMASHDL_GROUP_11_MAX_QUOTA, + MT7961_DMASHDL_GROUP_12_MAX_QUOTA, + MT7961_DMASHDL_GROUP_13_MAX_QUOTA, + MT7961_DMASHDL_GROUP_14_MAX_QUOTA, + MT7961_DMASHDL_GROUP_15_MAX_QUOTA, + }, + + .au2MinQuota = { + MT7961_DMASHDL_GROUP_0_MIN_QUOTA, + MT7961_DMASHDL_GROUP_1_MIN_QUOTA, + MT7961_DMASHDL_GROUP_2_MIN_QUOTA, + MT7961_DMASHDL_GROUP_3_MIN_QUOTA, + MT7961_DMASHDL_GROUP_4_MIN_QUOTA, + MT7961_DMASHDL_GROUP_5_MIN_QUOTA, + MT7961_DMASHDL_GROUP_6_MIN_QUOTA, + MT7961_DMASHDL_GROUP_7_MIN_QUOTA, + MT7961_DMASHDL_GROUP_8_MIN_QUOTA, + MT7961_DMASHDL_GROUP_9_MIN_QUOTA, + MT7961_DMASHDL_GROUP_10_MIN_QUOTA, + MT7961_DMASHDL_GROUP_11_MIN_QUOTA, + MT7961_DMASHDL_GROUP_12_MIN_QUOTA, + MT7961_DMASHDL_GROUP_13_MIN_QUOTA, + MT7961_DMASHDL_GROUP_14_MIN_QUOTA, + MT7961_DMASHDL_GROUP_15_MIN_QUOTA, + }, + + .aucQueue2Group = { + MT7961_DMASHDL_QUEUE_0_TO_GROUP, + MT7961_DMASHDL_QUEUE_1_TO_GROUP, + MT7961_DMASHDL_QUEUE_2_TO_GROUP, + MT7961_DMASHDL_QUEUE_3_TO_GROUP, + MT7961_DMASHDL_QUEUE_4_TO_GROUP, + MT7961_DMASHDL_QUEUE_5_TO_GROUP, + MT7961_DMASHDL_QUEUE_6_TO_GROUP, + MT7961_DMASHDL_QUEUE_7_TO_GROUP, + MT7961_DMASHDL_QUEUE_8_TO_GROUP, + MT7961_DMASHDL_QUEUE_9_TO_GROUP, + MT7961_DMASHDL_QUEUE_10_TO_GROUP, + MT7961_DMASHDL_QUEUE_11_TO_GROUP, + MT7961_DMASHDL_QUEUE_12_TO_GROUP, + MT7961_DMASHDL_QUEUE_13_TO_GROUP, + MT7961_DMASHDL_QUEUE_14_TO_GROUP, + MT7961_DMASHDL_QUEUE_15_TO_GROUP, + MT7961_DMASHDL_QUEUE_16_TO_GROUP, + MT7961_DMASHDL_QUEUE_17_TO_GROUP, + MT7961_DMASHDL_QUEUE_18_TO_GROUP, + MT7961_DMASHDL_QUEUE_19_TO_GROUP, + MT7961_DMASHDL_QUEUE_20_TO_GROUP, + MT7961_DMASHDL_QUEUE_21_TO_GROUP, + MT7961_DMASHDL_QUEUE_22_TO_GROUP, + MT7961_DMASHDL_QUEUE_23_TO_GROUP, + MT7961_DMASHDL_QUEUE_24_TO_GROUP, + MT7961_DMASHDL_QUEUE_25_TO_GROUP, + MT7961_DMASHDL_QUEUE_26_TO_GROUP, + MT7961_DMASHDL_QUEUE_27_TO_GROUP, + MT7961_DMASHDL_QUEUE_28_TO_GROUP, + MT7961_DMASHDL_QUEUE_29_TO_GROUP, + MT7961_DMASHDL_QUEUE_30_TO_GROUP, + MT7961_DMASHDL_QUEUE_31_TO_GROUP, + }, + + .aucPriority2Group = { + MT7961_DMASHDL_PRIORITY0_GROUP, + MT7961_DMASHDL_PRIORITY1_GROUP, + MT7961_DMASHDL_PRIORITY2_GROUP, + MT7961_DMASHDL_PRIORITY3_GROUP, + MT7961_DMASHDL_PRIORITY4_GROUP, + MT7961_DMASHDL_PRIORITY5_GROUP, + MT7961_DMASHDL_PRIORITY6_GROUP, + MT7961_DMASHDL_PRIORITY7_GROUP, + MT7961_DMASHDL_PRIORITY8_GROUP, + MT7961_DMASHDL_PRIORITY9_GROUP, + MT7961_DMASHDL_PRIORITY10_GROUP, + MT7961_DMASHDL_PRIORITY11_GROUP, + MT7961_DMASHDL_PRIORITY12_GROUP, + MT7961_DMASHDL_PRIORITY13_GROUP, + MT7961_DMASHDL_PRIORITY14_GROUP, + MT7961_DMASHDL_PRIORITY15_GROUP, + }, +}; + +void mt7961HalDmashdlSetPlePktMaxPage(struct ADAPTER *prAdapter, + uint16_t u2MaxPage) +{ + uint32_t u4Val; + + HAL_MCR_RD(prAdapter, WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR, &u4Val); + + u4Val &= ~WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PLE_PACKET_MAX_SIZE_MASK; + u4Val |= (u2MaxPage << + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PLE_PACKET_MAX_SIZE_SHFT) & + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PLE_PACKET_MAX_SIZE_MASK; + + HAL_MCR_WR(prAdapter, WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR, u4Val); +} + +void mt7961HalDmashdlSetPsePktMaxPage(struct ADAPTER *prAdapter, + uint16_t u2MaxPage) +{ + uint32_t u4Val; + + HAL_MCR_RD(prAdapter, WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR, &u4Val); + + u4Val &= ~WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PSE_PACKET_MAX_SIZE_MASK; + u4Val |= (u2MaxPage << + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PSE_PACKET_MAX_SIZE_SHFT) & + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PSE_PACKET_MAX_SIZE_MASK; + + HAL_MCR_WR(prAdapter, WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR, u4Val); +} + +void mt7961HalDmashdlSetRefill(struct ADAPTER *prAdapter, uint8_t ucGroup, + u_int8_t fgEnable) +{ + uint32_t u4Val, u4Mask; + + if (ucGroup >= ENUM_MT7961_DMASHDL_GROUP_NUM) + ASSERT(0); + + u4Mask = WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP0_REFILL_DISABLE_MASK + << ucGroup; + + HAL_MCR_RD(prAdapter, WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR, &u4Val); + + if (fgEnable) + u4Val &= ~u4Mask; + else + u4Val |= u4Mask; + + HAL_MCR_WR(prAdapter, WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR, u4Val); +} + +void mt7961HalDmashdlSetMaxQuota(struct ADAPTER *prAdapter, uint8_t ucGroup, + uint16_t u2MaxQuota) +{ + uint32_t u4Addr, u4Val; + + if (ucGroup >= ENUM_MT7961_DMASHDL_GROUP_NUM) + ASSERT(0); + + u4Addr = WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_ADDR + (ucGroup << 2); + + HAL_MCR_RD(prAdapter, u4Addr, &u4Val); + + u4Val &= ~WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_GROUP0_MAX_QUOTA_MASK; + u4Val |= (u2MaxQuota << + WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_GROUP0_MAX_QUOTA_SHFT) & + WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_GROUP0_MAX_QUOTA_MASK; + + HAL_MCR_WR(prAdapter, u4Addr, u4Val); +} + +void mt7961HalDmashdlSetMinQuota(struct ADAPTER *prAdapter, uint8_t ucGroup, + uint16_t u2MinQuota) +{ + uint32_t u4Addr, u4Val; + + if (ucGroup >= ENUM_MT7961_DMASHDL_GROUP_NUM) + ASSERT(0); + + u4Addr = WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_ADDR + (ucGroup << 2); + + HAL_MCR_RD(prAdapter, u4Addr, &u4Val); + + u4Val &= ~WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_GROUP0_MIN_QUOTA_MASK; + u4Val |= (u2MinQuota << + WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_GROUP0_MIN_QUOTA_SHFT) & + WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_GROUP0_MIN_QUOTA_MASK; + + HAL_MCR_WR(prAdapter, u4Addr, u4Val); +} + +void mt7961HalDmashdlSetQueueMapping(struct ADAPTER *prAdapter, uint8_t ucQueue, + uint8_t ucGroup) +{ + uint32_t u4Addr, u4Val, u4Mask, u4Shft; + + if (ucQueue >= 32) + ASSERT(0); + + if (ucGroup >= ENUM_MT7961_DMASHDL_GROUP_NUM) + ASSERT(0); + + u4Addr = WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR + + ((ucQueue >> 3) << 2); + u4Mask = WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE0_MAPPING_MASK << + ((ucQueue % 8) << 2); + u4Shft = (ucQueue % 8) << 2; + + HAL_MCR_RD(prAdapter, u4Addr, &u4Val); + + u4Val &= ~u4Mask; + u4Val |= (ucGroup << u4Shft) & u4Mask; + + HAL_MCR_WR(prAdapter, u4Addr, u4Val); +} + +void mt7961HalDmashdlSetSlotArbiter(struct ADAPTER *prAdapter, + u_int8_t fgEnable) +{ + uint32_t u4Val; + + HAL_MCR_RD(prAdapter, WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR, &u4Val); + + if (fgEnable) + u4Val |= + WF_HIF_DMASHDL_TOP_PAGE_SETTING_GROUP_SEQUENCE_ORDER_TYPE_MASK; + else + u4Val &= + ~WF_HIF_DMASHDL_TOP_PAGE_SETTING_GROUP_SEQUENCE_ORDER_TYPE_MASK; + + HAL_MCR_WR(prAdapter, WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR, u4Val); +} + +void mt7961HalDmashdlSetUserDefinedPriority(struct ADAPTER *prAdapter, + uint8_t ucPriority, uint8_t ucGroup) +{ + uint32_t u4Addr, u4Val, u4Mask, u4Shft; + + ASSERT(ucPriority < 16); + ASSERT(ucGroup < ENUM_MT7961_DMASHDL_GROUP_NUM); + + u4Addr = WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_ADDR + + ((ucPriority >> 3) << 2); + u4Mask = WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY0_GROUP_MASK + << ((ucPriority % 8) << 2); + u4Shft = (ucPriority % 8) << 2; + + HAL_MCR_RD(prAdapter, u4Addr, &u4Val); + + u4Val &= ~u4Mask; + u4Val |= (ucGroup << u4Shft) & u4Mask; + + HAL_MCR_WR(prAdapter, u4Addr, u4Val); +} + +void mt7961DmashdlInit(struct ADAPTER *prAdapter) +{ + uint32_t idx; + + mt7961HalDmashdlSetPlePktMaxPage(prAdapter, + rMT7961DmashdlCfg.u2PktPleMaxPage); + + mt7961HalDmashdlSetPsePktMaxPage(prAdapter, + rMT7961DmashdlCfg.u2PktPseMaxPage); + + for (idx = 0; idx < ENUM_MT7961_DMASHDL_GROUP_NUM; idx++) { + mt7961HalDmashdlSetRefill(prAdapter, idx, + rMT7961DmashdlCfg.afgRefillEn[idx]); + + mt7961HalDmashdlSetMaxQuota(prAdapter, idx, + rMT7961DmashdlCfg.au2MaxQuota[idx]); + + mt7961HalDmashdlSetMinQuota(prAdapter, idx, + rMT7961DmashdlCfg.au2MinQuota[idx]); + } + + for (idx = 0; idx < 32; idx++) + mt7961HalDmashdlSetQueueMapping(prAdapter, idx, + rMT7961DmashdlCfg.aucQueue2Group[idx]); + + for (idx = 0; idx < 16; idx++) + mt7961HalDmashdlSetUserDefinedPriority(prAdapter, idx, + rMT7961DmashdlCfg.aucPriority2Group[idx]); + + mt7961HalDmashdlSetSlotArbiter(prAdapter, + rMT7961DmashdlCfg.fgSlotArbiterEn); +} + +#endif /* defined(_HIF_PCIE) || defined(_HIF_AXI) || defined(_HIF_USB) */ +#endif /* MT7961 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7961/mt7961.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7961/mt7961.c new file mode 100644 index 0000000000000..f14853245709b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/mt7961/mt7961.c @@ -0,0 +1,662 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file mt7961.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. +*/ + +#ifdef MT7961 + +/******************************************************************************* +* C O M P I L E 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 "coda/mt7961/wf_wfdma_host_dma0.h" +#include "coda/mt7961/wf_cr_sw_def.h" +#include "precomp.h" +#include "mt7961.h" +#include "hal_dmashdl_mt7961.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define CONN_MCU_CONFG_BASE 0x88000000 +#define CONN_MCU_CONFG_COM_REG0_ADDR (CONN_MCU_CONFG_BASE + 0x200) + +#define PATCH_SEMAPHORE_COMM_REG 0 +#define PATCH_SEMAPHORE_COMM_REG_PATCH_DONE 1 /* bit0 is for patch. */ + +#define SW_WORKAROUND_FOR_WFDMA_ISSUE_HWITS00009838 1 + +#define RX_DATA_RING_BASE_IDX 2 + +/******************************************************************************* +* M A 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 U B L I C D A T A +******************************************************************************** +*/ + +struct ECO_INFO mt7961_eco_table[] = { + /* HW version, ROM version, Factory version */ + {0x00, 0x00, 0xA, 0x1}, /* E1 */ + {0x00, 0x00, 0x0, 0x0} /* End of table */ +}; + +#if defined(_HIF_PCIE) || defined(_HIF_AXI) +struct PCIE_CHIP_CR_MAPPING mt7961_bus2chip_cr_mapping[] = { + /* chip addr, bus addr, range */ + {0x54000000, 0x02000, 0x1000}, /* WFDMA PCIE0 MCU DMA0 */ + {0x55000000, 0x03000, 0x1000}, /* WFDMA PCIE0 MCU DMA1 */ + {0x56000000, 0x04000, 0x1000}, /* WFDMA reserved */ + {0x57000000, 0x05000, 0x1000}, /* WFDMA MCU wrap CR */ + {0x58000000, 0x06000, 0x1000}, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */ + {0x59000000, 0x07000, 0x1000}, /* WFDMA PCIE1 MCU DMA1 */ + {0x820c0000, 0x08000, 0x4000}, /* WF_UMAC_TOP (PLE) */ + {0x820c8000, 0x0c000, 0x2000}, /* WF_UMAC_TOP (PSE) */ + {0x820cc000, 0x0e000, 0x2000}, /* WF_UMAC_TOP (PP) */ + {0x820e0000, 0x20000, 0x0400}, /* WF_LMAC_TOP BN0 (WF_CFG) */ + {0x820e1000, 0x20400, 0x0200}, /* WF_LMAC_TOP BN0 (WF_TRB) */ + {0x820e2000, 0x20800, 0x0400}, /* WF_LMAC_TOP BN0 (WF_AGG) */ + {0x820e3000, 0x20c00, 0x0400}, /* WF_LMAC_TOP BN0 (WF_ARB) */ + {0x820e4000, 0x21000, 0x0400}, /* WF_LMAC_TOP BN0 (WF_TMAC) */ + {0x820e5000, 0x21400, 0x0800}, /* WF_LMAC_TOP BN0 (WF_RMAC) */ + {0x820ce000, 0x21c00, 0x0200}, /* WF_LMAC_TOP (WF_SEC) */ + {0x820e7000, 0x21e00, 0x0200}, /* WF_LMAC_TOP BN0 (WF_DMA) */ + {0x820cf000, 0x22000, 0x1000}, /* WF_LMAC_TOP (WF_PF) */ + {0x820e9000, 0x23400, 0x0200}, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */ + {0x820ea000, 0x24000, 0x0200}, /* WF_LMAC_TOP BN0 (WF_ETBF) */ + {0x820eb000, 0x24200, 0x0400}, /* WF_LMAC_TOP BN0 (WF_LPON) */ + {0x820ec000, 0x24600, 0x0200}, /* WF_LMAC_TOP BN0 (WF_INT) */ + {0x820ed000, 0x24800, 0x0800}, /* WF_LMAC_TOP BN0 (WF_MIB) */ + {0x820ca000, 0x26000, 0x2000}, /* WF_LMAC_TOP BN0 (WF_MUCOP) */ + {0x820d0000, 0x30000, 0x10000}, /* WF_LMAC_TOP (WF_WTBLON) */ + {0x40000000, 0x70000, 0x10000}, /* WF_UMAC_SYSRAM */ + {0x00400000, 0x80000, 0x10000}, /* WF_MCU_SYSRAM */ + {0x00410000, 0x90000, 0x10000}, /* WF_MCU_SYSRAM (configure register) */ + {0x820f0000, 0xa0000, 0x0400}, /* WF_LMAC_TOP BN1 (WF_CFG) */ + {0x820f1000, 0xa0600, 0x0200}, /* WF_LMAC_TOP BN1 (WF_TRB) */ + {0x820f2000, 0xa0800, 0x0400}, /* WF_LMAC_TOP BN1 (WF_AGG) */ + {0x820f3000, 0xa0c00, 0x0400}, /* WF_LMAC_TOP BN1 (WF_ARB) */ + {0x820f4000, 0xa1000, 0x0400}, /* WF_LMAC_TOP BN1 (WF_TMAC) */ + {0x820f5000, 0xa1400, 0x0800}, /* WF_LMAC_TOP BN1 (WF_RMAC) */ + {0x820f7000, 0xa1e00, 0x0200}, /* WF_LMAC_TOP BN1 (WF_DMA) */ + {0x820f9000, 0xa3400, 0x0200}, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */ + {0x820fa000, 0xa4000, 0x0200}, /* WF_LMAC_TOP BN1 (WF_ETBF) */ + {0x820fb000, 0xa4200, 0x0400}, /* WF_LMAC_TOP BN1 (WF_LPON) */ + {0x820fc000, 0xa4600, 0x0200}, /* WF_LMAC_TOP BN1 (WF_INT) */ + {0x820fd000, 0xa4800, 0x0800}, /* WF_LMAC_TOP BN1 (WF_MIB) */ + {0x820cc000, 0xa5000, 0x2000}, /* WF_LMAC_TOP BN1 (WF_MUCOP) */ + {0x820c4000, 0xa8000, 0x4000}, /* WF_LMAC_TOP BN1 (WF_MUCOP) */ + {0x820b0000, 0xae000, 0x1000}, /* [APB2] WFSYS_ON */ + {0x80020000, 0xb0000, 0x10000}, /* WF_TOP_MISC_OFF */ + {0x81020000, 0xc0000, 0x10000}, /* WF_TOP_MISC_ON */ + {0x7c020000, 0xd0000, 0x10000}, /* CONN_INFRA, wfdma */ + {0x7c060000, 0xe0000, 0x10000}, /* CONN_INFRA, conn_host_csr_top */ + {0x7c000000, 0xf0000, 0x10000}, /* CONN_INFRA */ +}; + +static void mt7961EnableInterrupt( + struct ADAPTER *prAdapter) +{ + union WPDMA_INT_MASK IntMask; + + prAdapter->fgIsIntEnable = TRUE; + + HAL_MCR_RD(prAdapter, + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR, &IntMask.word); + IntMask.word = 0; + IntMask.field_conn2x_single.wfdma0_rx_done_0 = 1; + IntMask.field_conn2x_single.wfdma0_rx_done_2 = 1; + IntMask.field_conn2x_single.wfdma0_rx_done_3 = 1; + IntMask.field_conn2x_single.wfdma0_rx_done_4 = 1; + IntMask.field_conn2x_single.wfdma0_rx_done_5 = 1; + IntMask.field_conn2x_single.wfdma0_tx_done_0 = 1; + IntMask.field_conn2x_single.wfdma0_tx_done_16 = 1; + IntMask.field_conn2x_single.wfdma0_tx_done_17 = 1; + IntMask.field_conn2x_single.wfdma0_mcu2host_sw_int_en = 1; + + IntMask.field_conn2x_single.wfdma0_rx_coherent = 0; + IntMask.field_conn2x_single.wfdma0_tx_coherent = 0; + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR, IntMask.word); + + DBGLOG(HAL, TRACE, "%s [0x%08x]\n", __func__, IntMask.word); +} /* end of nicEnableInterrupt() */ + +static void mt7961DisableInterrupt( + struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo = NULL; + union WPDMA_INT_MASK IntMask; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + + IntMask.word = 0; + + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR, IntMask.word); + HAL_MCR_RD(prAdapter, + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR, &IntMask.word); + + prAdapter->fgIsIntEnable = FALSE; + + DBGLOG(HAL, TRACE, "%s\n", __func__); +} + +static uint8_t mt7961SetRxRingHwAddr( + struct RTMP_RX_RING *prRxRing, + struct BUS_INFO *prBusInfo, + uint32_t u4SwRingIdx) +{ + uint32_t offset = 0; + + /* + * RX_RING_EVT_IDX_1 (RX_Ring0) - Rx Event + * RX_RING_DATA_IDX_0 (RX_Ring2) - Band0 Rx Data + * WFDMA0_RX_RING_IDX_2 (RX_Ring3) - Band1 Rx Data + * WFDMA0_RX_RING_IDX_3 (RX_Ring4) - Band0 Tx Free Done Event + * WFDMA1_RX_RING_IDX_0 (RX_Ring5) - Band1 Tx Free Done Event + */ + switch (u4SwRingIdx) { + case RX_RING_EVT_IDX_1: + offset = 0; + break; + case RX_RING_DATA_IDX_0: + offset = RX_DATA_RING_BASE_IDX * MT_RINGREG_DIFF; + break; + case WFDMA0_RX_RING_IDX_2: + case WFDMA0_RX_RING_IDX_3: + case WFDMA1_RX_RING_IDX_0: + offset = (u4SwRingIdx + 1) * MT_RINGREG_DIFF; + break; + default: + return FALSE; + } + + prRxRing->hw_desc_base = prBusInfo->host_rx_ring_base + offset; + prRxRing->hw_cidx_addr = prBusInfo->host_rx_ring_cidx_addr + offset; + prRxRing->hw_didx_addr = prBusInfo->host_rx_ring_didx_addr + offset; + prRxRing->hw_cnt_addr = prBusInfo->host_rx_ring_cnt_addr + offset; + + return TRUE; +} + +static bool mt7961LiteWfdmaAllocRxRing( + struct GLUE_INFO *prGlueInfo, + bool fgAllocMem) +{ + /* Band1 Data Rx path */ + if (!halWpdmaAllocRxRing(prGlueInfo, + WFDMA0_RX_RING_IDX_2, RX_RING0_SIZE, + RXD_SIZE, CFG_RX_MAX_PKT_SIZE, fgAllocMem)) { + DBGLOG(HAL, ERROR, "AllocRxRing[0] fail\n"); + return false; + } + /* Band0 Tx Free Done Event */ + if (!halWpdmaAllocRxRing(prGlueInfo, + WFDMA0_RX_RING_IDX_3, RX_RING1_SIZE, + RXD_SIZE, RX_BUFFER_AGGRESIZE, fgAllocMem)) { + DBGLOG(HAL, ERROR, "AllocRxRing[1] fail\n"); + return false; + } + /* Band1 Tx Free Done Event */ + if (!halWpdmaAllocRxRing(prGlueInfo, + WFDMA1_RX_RING_IDX_0, RX_RING1_SIZE, + RXD_SIZE, RX_BUFFER_AGGRESIZE, fgAllocMem)) { + DBGLOG(HAL, ERROR, "AllocRxRing[1] fail\n"); + return false; + } + return true; +} + +static void mt7961Connac2xProcessTxInterrupt( + struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + union WPDMA_INT_STA_STRUCT rIntrStatus; + + rIntrStatus = (union WPDMA_INT_STA_STRUCT)prHifInfo->u4IntStatus; + if (rIntrStatus.field_conn2x_single.wfdma0_tx_done_16) + halWpdmaProcessCmdDmaDone( + prAdapter->prGlueInfo, TX_RING_FWDL_IDX_3); + + if (rIntrStatus.field_conn2x_single.wfdma0_tx_done_17) + halWpdmaProcessCmdDmaDone( + prAdapter->prGlueInfo, TX_RING_CMD_IDX_2); + + if (rIntrStatus.field_conn2x_single.wfdma0_tx_done_0) { + halWpdmaProcessDataDmaDone( + prAdapter->prGlueInfo, TX_RING_DATA0_IDX_0); + kalSetTxEvent2Hif(prAdapter->prGlueInfo); + } +} + +static void mt7961Connac2xProcessRxInterrupt( + struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + union WPDMA_INT_STA_STRUCT rIntrStatus; + + rIntrStatus = (union WPDMA_INT_STA_STRUCT)prHifInfo->u4IntStatus; + if (rIntrStatus.field_conn2x_single.wfdma0_rx_done_0) + halRxReceiveRFBs(prAdapter, RX_RING_EVT_IDX_1, FALSE); + + if (rIntrStatus.field_conn2x_single.wfdma0_rx_done_2) + halRxReceiveRFBs(prAdapter, RX_RING_DATA_IDX_0, TRUE); + + if (rIntrStatus.field_conn2x_single.wfdma0_rx_done_3) + halRxReceiveRFBs(prAdapter, WFDMA0_RX_RING_IDX_2, TRUE); + + if (rIntrStatus.field_conn2x_single.wfdma0_rx_done_4) + halRxReceiveRFBs(prAdapter, WFDMA0_RX_RING_IDX_3, TRUE); + + if (rIntrStatus.field_conn2x_single.wfdma0_rx_done_5) + halRxReceiveRFBs(prAdapter, WFDMA1_RX_RING_IDX_0, TRUE); +} + +static void mt7961Connac2xWfdmaManualPrefetch( + struct GLUE_INFO *prGlueInfo) +{ + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + u_int32_t val = 0; + + HAL_MCR_RD(prAdapter, WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR, &val); + /* disable prefetch offset calculation auto-mode */ + val &= + ~WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN_MASK; + HAL_MCR_WR(prAdapter, WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR, val); + + HAL_MCR_WR(prAdapter, WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_ADDR, + 0x00000004); + HAL_MCR_WR(prAdapter, WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_ADDR, + 0x00400004); + HAL_MCR_WR(prAdapter, WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_ADDR, + 0x00800004); + HAL_MCR_WR(prAdapter, WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_EXT_CTRL_ADDR, + 0x00c00004); + HAL_MCR_WR(prAdapter, WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_EXT_CTRL_ADDR, + 0x01000004); + + HAL_MCR_WR(prAdapter, WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_ADDR, + 0x01400004); + HAL_MCR_WR(prAdapter, WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_ADDR, + 0x01800004); + HAL_MCR_WR(prAdapter, WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_ADDR, + 0x01c00004); + + HAL_MCR_WR(prAdapter, WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_ADDR, + 0x02000004); + HAL_MCR_WR(prAdapter, WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_EXT_CTRL_ADDR, + 0x02400004); + HAL_MCR_WR(prAdapter, WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_EXT_CTRL_ADDR, + 0x02800004); + HAL_MCR_WR(prAdapter, WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_EXT_CTRL_ADDR, + 0x02c00004); + + HAL_MCR_WR(prAdapter, WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_EXT_CTRL_ADDR, + 0x03400004); + HAL_MCR_WR(prAdapter, WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_EXT_CTRL_ADDR, + 0x03800004); + + /* reset dma idx */ + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR, 0xFFFFFFFF); +} + +static void mt7961ReadIntStatus( + struct ADAPTER *prAdapter, + uint32_t *pu4IntStatus) +{ + uint32_t u4RegValue; + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + struct BUS_INFO *prBusInfo = prAdapter->chip_info->bus_info; + + *pu4IntStatus = 0; + + HAL_MCR_RD(prAdapter, + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR, &u4RegValue); + + if (HAL_IS_CONNAC2X_EXT_RX_DONE_INTR(u4RegValue, + prBusInfo->host_int_rxdone_bits)) + *pu4IntStatus |= WHISR_RX0_DONE_INT; + + if (HAL_IS_CONNAC2X_EXT_TX_DONE_INTR(u4RegValue, + prBusInfo->host_int_txdone_bits)) + *pu4IntStatus |= WHISR_TX_DONE_INT; + + if (u4RegValue & CONNAC_MCU_SW_INT) + *pu4IntStatus |= WHISR_D2H_SW_INT; + + prHifInfo->u4IntStatus = u4RegValue; + + /* clear interrupt */ + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR, u4RegValue); +} + +#endif /*_HIF_PCIE || _HIF_AXI */ + +#if defined(_HIF_USB) +void mt7961Connac2xWfdmaInitForUSB( + struct ADAPTER *prAdapter, + struct mt66xx_chip_info *prChipInfo) +{ + HAL_MCR_WR(prAdapter, 0x74000004, 0); + HAL_MCR_WR(prAdapter, 0x74000014, 0); + HAL_MCR_WR(prAdapter, 0x74000300, 0); +} + +#endif + +void mt7961DumpSerDummyCR( + struct ADAPTER *prAdapter) +{ + uint32_t u4MacVal; + + DBGLOG(HAL, INFO, "%s\n", __func__); + + DBGLOG(HAL, INFO, "=====Dump Start====\n"); + + HAL_MCR_RD(prAdapter, WF_SW_DEF_CR_SER_STATUS_ADDR, &u4MacVal); + DBGLOG(HAL, INFO, "SER STATUS[0x%08x]: 0x%08x\n", + WF_SW_DEF_CR_SER_STATUS_ADDR, u4MacVal); + + HAL_MCR_RD(prAdapter, WF_SW_DEF_CR_PLE_STATUS_ADDR, &u4MacVal); + DBGLOG(HAL, INFO, "PLE STATUS[0x%08x]: 0x%08x\n", + WF_SW_DEF_CR_PLE_STATUS_ADDR, u4MacVal); + + HAL_MCR_RD(prAdapter, WF_SW_DEF_CR_PLE1_STATUS_ADDR, &u4MacVal); + DBGLOG(HAL, INFO, "PLE1 STATUS[0x%08x]: 0x%08x\n", + WF_SW_DEF_CR_PLE1_STATUS_ADDR, u4MacVal); + + HAL_MCR_RD(prAdapter, WF_SW_DEF_CR_PLE_AMSDU_STATUS_ADDR, &u4MacVal); + DBGLOG(HAL, INFO, "PLE AMSDU STATUS[0x%08x]: 0x%08x\n", + WF_SW_DEF_CR_PLE_AMSDU_STATUS_ADDR, u4MacVal); + + HAL_MCR_RD(prAdapter, WF_SW_DEF_CR_PSE_STATUS_ADDR, &u4MacVal); + DBGLOG(HAL, INFO, "PSE STATUS[0x%08x]: 0x%08x\n", + WF_SW_DEF_CR_PSE_STATUS_ADDR, u4MacVal); + + HAL_MCR_RD(prAdapter, WF_SW_DEF_CR_PSE1_STATUS_ADDR, &u4MacVal); + DBGLOG(HAL, INFO, "PSE1 STATUS[0x%08x]: 0x%08x\n", + WF_SW_DEF_CR_PSE1_STATUS_ADDR, u4MacVal); + + HAL_MCR_RD(prAdapter, WF_SW_DEF_CR_LAMC_WISR6_BN0_STATUS_ADDR, + &u4MacVal); + DBGLOG(HAL, INFO, "LMAC WISR6 BN0 STATUS[0x%08x]: 0x%08x\n", + WF_SW_DEF_CR_LAMC_WISR6_BN0_STATUS_ADDR, u4MacVal); + + HAL_MCR_RD(prAdapter, WF_SW_DEF_CR_LAMC_WISR6_BN1_STATUS_ADDR, + &u4MacVal); + DBGLOG(HAL, INFO, "LMAC WISR6 BN1 STATUS[0x%08x]: 0x%08x\n", + WF_SW_DEF_CR_LAMC_WISR6_BN1_STATUS_ADDR, u4MacVal); + + HAL_MCR_RD(prAdapter, WF_SW_DEF_CR_LAMC_WISR7_BN0_STATUS_ADDR, + &u4MacVal); + DBGLOG(HAL, INFO, "LMAC WISR7 BN0 STATUS[0x%08x]: 0x%08x\n", + WF_SW_DEF_CR_LAMC_WISR7_BN0_STATUS_ADDR, u4MacVal); + + HAL_MCR_RD(prAdapter, WF_SW_DEF_CR_LAMC_WISR7_BN1_STATUS_ADDR, + &u4MacVal); + DBGLOG(HAL, INFO, "LMAC WISR7 BN1 STATUS[0x%08x]: 0x%08x\n", + WF_SW_DEF_CR_LAMC_WISR7_BN1_STATUS_ADDR, u4MacVal); + + DBGLOG(HAL, INFO, "=====Dump End====\n"); + +} + + +struct BUS_INFO mt7961_bus_info = { +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + .top_cfg_base = MT7961_TOP_CFG_BASE, + + /* host_dma0 for TXP */ + .host_dma0_base = WF_WFDMA_HOST_DMA0_BASE, + .host_int_status_addr = WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR, + + .host_int_txdone_bits = + (CONNAC2X_WFDMA_TX_DONE_INT0 | CONNAC2X_WFDMA_TX_DONE_INT1 | + CONNAC2X_WFDMA_TX_DONE_INT2 | CONNAC2X_WFDMA_TX_DONE_INT3 | + CONNAC2X_WFDMA_TX_DONE_INT4 | CONNAC2X_WFDMA_TX_DONE_INT5 | + CONNAC2X_WFDMA_TX_DONE_INT6 | CONNAC2X_WFDMA_TX_DONE_INT16 | + CONNAC2X_WFDMA_TX_DONE_INT17), + .host_int_rxdone_bits = + (CONNAC2X_WFDMA_RX_DONE_INT0 | CONNAC2X_WFDMA_RX_DONE_INT0 | + CONNAC2X_WFDMA_RX_DONE_INT2 | CONNAC2X_WFDMA_RX_DONE_INT3 | + CONNAC2X_WFDMA_RX_DONE_INT4 | CONNAC2X_WFDMA_RX_DONE_INT5), + + .host_tx_ring_base = WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL0_ADDR, + .host_tx_ring_ext_ctrl_base = + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_ADDR, + .host_tx_ring_cidx_addr = WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL2_ADDR, + .host_tx_ring_didx_addr = WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL3_ADDR, + .host_tx_ring_cnt_addr = WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_ADDR, + + .host_rx_ring_base = WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL0_ADDR, + .host_rx_ring_ext_ctrl_base = + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_ADDR, + .host_rx_ring_cidx_addr = WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL2_ADDR, + .host_rx_ring_didx_addr = WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL3_ADDR, + .host_rx_ring_cnt_addr = WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_ADDR, + + .bus2chip = mt7961_bus2chip_cr_mapping, + .max_static_map_addr = 0x000f0000, + + .tx_ring_fwdl_idx = CONNAC2X_FWDL_TX_RING_IDX, + .tx_ring_cmd_idx = CONNAC2X_CMD_TX_RING_IDX, + .tx_ring0_data_idx = 0, + .tx_ring1_data_idx = 1, + .fw_own_clear_addr = CONNAC2X_BN0_IRQ_STAT_ADDR, + .fw_own_clear_bit = PCIE_LPCR_FW_CLR_OWN, + .fgCheckDriverOwnInt = FALSE, + .u4DmaMask = 32, + .pdmaSetup = asicConnac2xWpdmaConfig, + .enableInterrupt = mt7961EnableInterrupt, + .disableInterrupt = mt7961DisableInterrupt, + .processTxInterrupt = mt7961Connac2xProcessTxInterrupt, + .processRxInterrupt = mt7961Connac2xProcessRxInterrupt, + .tx_ring_ext_ctrl = asicConnac2xWfdmaTxRingExtCtrl, + .rx_ring_ext_ctrl = asicConnac2xWfdmaRxRingExtCtrl, + /* null wfdmaManualPrefetch if want to disable manual mode */ + .wfdmaManualPrefetch = mt7961Connac2xWfdmaManualPrefetch, + .lowPowerOwnRead = asicConnac2xLowPowerOwnRead, + .lowPowerOwnSet = asicConnac2xLowPowerOwnSet, + .lowPowerOwnClear = asicConnac2xLowPowerOwnClear, + .wakeUpWiFi = asicWakeUpWiFi, + .processSoftwareInterrupt = asicConnac2xProcessSoftwareInterrupt, + .softwareInterruptMcu = asicConnac2xSoftwareInterruptMcu, + .hifRst = asicConnac2xHifRst, + + .initPcieInt = NULL, /* Todo: check if enable INT on driver side */ + .devReadIntStatus = mt7961ReadIntStatus, + .DmaShdlInit = mt7961DmashdlInit, + .setRxRingHwAddr = mt7961SetRxRingHwAddr, + .wfdmaAllocRxRing = mt7961LiteWfdmaAllocRxRing, +#endif /*_HIF_PCIE || _HIF_AXI */ + +#if defined(_HIF_USB) + .u4UdmaWlCfg_0_Addr = CONNAC2X_UDMA_WLCFG_0, + .u4UdmaWlCfg_1_Addr = CONNAC2X_UDMA_WLCFG_1, + .u4UdmaWlCfg_0 = + (CONNAC2X_UDMA_WLCFG_0_WL_TX_EN(1) | + CONNAC2X_UDMA_WLCFG_0_WL_RX_EN(1) | + CONNAC2X_UDMA_WLCFG_0_WL_RX_MPSZ_PAD0(1) | + CONNAC2X_UDMA_WLCFG_0_TICK_1US_EN(1)), + .u4UdmaTxQsel = CONNAC2X_UDMA_TX_QSEL, + .u4device_vender_request_in = DEVICE_VENDOR_REQUEST_IN_CONNAC2, + .u4device_vender_request_out = DEVICE_VENDOR_REQUEST_OUT_CONNAC2, + .asicUsbEventEpDetected = asicConnac2xUsbEventEpDetected, + .asicUsbRxByteCount = asicConnac2xUsbRxByteCount, + .DmaShdlInit = mt7961DmashdlInit, +#endif +}; + +#if CFG_ENABLE_FW_DOWNLOAD +struct FWDL_OPS_T mt7961_fw_dl_ops = { + .constructFirmwarePrio = NULL, + .constructPatchName = NULL, + .downloadPatch = wlanDownloadPatch, + .downloadFirmware = wlanConnacFormatDownload, + .getFwInfo = wlanGetConnacFwInfo, + .getFwDlInfo = asicGetFwDlInfo, + .phyAction = NULL, +}; +#endif /* CFG_ENABLE_FW_DOWNLOAD */ + +struct TX_DESC_OPS_T mt7961TxDescOps = { + .fillNicAppend = fillNicTxDescAppend, + .fillHifAppend = fillTxDescAppendByHostV2, + .fillTxByteCount = fillConnac2xTxDescTxByteCount, +}; + +struct RX_DESC_OPS_T mt7961RxDescOps = {}; + +struct CHIP_DBG_OPS mt7961DebugOps = { + .showPdmaInfo = NULL, + .showPseInfo = mt7961_show_pse_info, + .showPleInfo = mt7961_show_ple_info, + .showTxdInfo = connac2x_show_txd_Info, + .showWtblInfo = connac2x_show_wtbl_info, + .showUmacFwtblInfo = connac2x_show_umac_wtbl_info, + .showCsrInfo = NULL, + .showDmaschInfo = NULL, + .dumpMacInfo = NULL, + .showHifInfo = NULL, + .printHifDbgInfo = NULL, + .show_rx_rate_info = connac2x_show_rx_rate_info, + .show_rx_rssi_info = connac2x_show_rx_rssi_info, + .show_stat_info = connac2x_show_stat_info, +}; + +/* Litien code refine to support multi chip */ +struct mt66xx_chip_info mt66xx_chip_info_mt7961 = { + .bus_info = &mt7961_bus_info, +#if CFG_ENABLE_FW_DOWNLOAD + .fw_dl_ops = &mt7961_fw_dl_ops, +#endif /* CFG_ENABLE_FW_DOWNLOAD */ + .prTxDescOps = &mt7961TxDescOps, + .prRxDescOps = &mt7961RxDescOps, + .prDebugOps = &mt7961DebugOps, + .chip_id = MT7961_CHIP_ID, + .should_verify_chip_id = FALSE, + .sw_sync0 = MT7961_SW_SYNC0, + .sw_ready_bits = WIFI_FUNC_NO_CR4_READY_BITS, + .sw_ready_bit_offset = MT7961_SW_SYNC0_RDY_OFFSET, + .patch_addr = MT7961_PATCH_START_ADDR, + .is_support_cr4 = FALSE, + .is_support_wacpu = FALSE, + .txd_append_size = MT7961_TX_DESC_APPEND_LENGTH, + .rxd_size = MT7961_RX_DESC_LENGTH, + .init_evt_rxd_size = MT7961_RX_DESC_LENGTH, + .pse_header_length = CONNAC2X_NIC_TX_PSE_HEADER_LENGTH, + .init_event_size = CONNAC2X_RX_INIT_EVENT_LENGTH, + .eco_info = mt7961_eco_table, + .isNicCapV1 = FALSE, + .top_hcr = CONNAC2X_TOP_HCR, + .top_hvr = CONNAC2X_TOP_HVR, + .top_fvr = CONNAC2X_TOP_FVR, + .arb_ac_mode_addr = MT7961_ARB_AC_MODE_ADDR, + .asicCapInit = asicConnac2xCapInit, +#if CFG_ENABLE_FW_DOWNLOAD + .asicEnableFWDownload = NULL, +#endif /* CFG_ENABLE_FW_DOWNLOAD */ + .asicDumpSerDummyCR = mt7961DumpSerDummyCR, + .downloadBufferBin = wlanConnacDownloadBufferBin, + .is_support_hw_amsdu = TRUE, + .is_support_asic_lp = TRUE, + .is_support_wfdma1 = FALSE, + .asicWfdmaReInit = asicConnac2xWfdmaReInit, + .asicWfdmaReInit_handshakeInit = asicConnac2xWfdmaDummyCrWrite, +#if defined(_HIF_USB) + .asicUsbInit = asicConnac2xWfdmaInitForUSB, + .asicUsbInit_ic_specific = mt7961Connac2xWfdmaInitForUSB, + .u4SerUsbMcuEventAddr = WF_SW_DEF_CR_USB_MCU_EVENT_ADD, + .u4SerUsbHostAckAddr = WF_SW_DEF_CR_USB_HOST_ACK_ADDR, +#endif + .group5_size = sizeof(struct HW_MAC_RX_STS_GROUP_5), + .u4LmacWtblDUAddr = MT7961_WIFI_LWTBL_BASE, + .u4UmacWtblDUAddr = MT7961_WIFI_UWTBL_BASE, + .cmd_max_pkt_size = CFG_TX_MAX_PKT_SIZE, /* size 1600 */ +}; + +struct mt66xx_hif_driver_data mt66xx_driver_data_mt7961 = { + .chip_info = &mt66xx_chip_info_mt7961, +}; + +#endif /* MT7961 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/soc3_0/dbg_soc3_0.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/soc3_0/dbg_soc3_0.c new file mode 100644 index 0000000000000..dfad6ae807a3a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/soc3_0/dbg_soc3_0.c @@ -0,0 +1,2085 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** + *[File] dbg_soc3_0.c + *[Version] v1.0 + *[Revision Date] 2019-09-09 + *[Author] + *[Description] + * The program provides WIFI FALCON MAC Debug APIs + *[Copyright] + * Copyright (C) 2015 MediaTek Incorporation. All Rights Reserved. + ******************************************************************************/ + +#ifdef SOC3_0 +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "coda/soc3_0/wf_ple_top.h" +#include "coda/soc3_0/wf_pse_top.h" +#include "coda/soc3_0/wf_wfdma_host_dma0.h" +#include "coda/soc3_0/wf_wfdma_host_dma1.h" +#include "coda/soc3_0/wf_hif_dmashdl_top.h" +#include "precomp.h" +#include "mt_dmac.h" +#include "wf_ple.h" +#include "hal_dmashdl_soc3_0.h" +#include "soc3_0.h" +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/* TODO : need to Merge related API with non-driver base */ +#define WFSYS_SUPPORT_BUS_HANG_READ_FROM_DRIVER_BASE 1 + +/* define WFDMA CODA here */ +#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING0_CTRL0_ADDR \ + (CONNAC2X_MCU_WPDMA_0_BASE + 0x300) +#define WF_WFDMA_MCU_DMA1_WPDMA_TX_RING0_CTRL0_ADDR \ + (CONNAC2X_MCU_WPDMA_1_BASE + 0x300) +#define WF_WFDMA_MCU_DMA1_WPDMA_TX_RING1_CTRL0_ADDR \ + (CONNAC2X_MCU_WPDMA_1_BASE + 0x310) +#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING0_CTRL0_ADDR \ + (CONNAC2X_MCU_WPDMA_0_BASE + 0x500) +#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING1_CTRL0_ADDR \ + (CONNAC2X_MCU_WPDMA_0_BASE + 0x510) +#define WF_WFDMA_MCU_DMA1_WPDMA_RX_RING0_CTRL0_ADDR \ + (CONNAC2X_MCU_WPDMA_1_BASE + 0x500) +#define WF_WFDMA_MCU_DMA1_WPDMA_RX_RING1_CTRL0_ADDR \ + (CONNAC2X_MCU_WPDMA_1_BASE + 0x510) +#define WF_WFDMA_MCU_DMA1_WPDMA_RX_RING2_CTRL0_ADDR \ + (CONNAC2X_MCU_WPDMA_1_BASE + 0x520) + +/* define PLE/PSE FSM CR here */ +#define WF_PLE_FSM_PEEK_CR_00 (WF_PLE_TOP_BASE + 0x03D0) +#define WF_PLE_FSM_PEEK_CR_01 (WF_PLE_TOP_BASE + 0x03D4) +#define WF_PLE_FSM_PEEK_CR_02 (WF_PLE_TOP_BASE + 0x03D8) +#define WF_PLE_FSM_PEEK_CR_03 (WF_PLE_TOP_BASE + 0x03DC) +#define WF_PLE_FSM_PEEK_CR_04 (WF_PLE_TOP_BASE + 0x03E0) +#define WF_PLE_FSM_PEEK_CR_05 (WF_PLE_TOP_BASE + 0x03E4) +#define WF_PLE_FSM_PEEK_CR_06 (WF_PLE_TOP_BASE + 0x03E8) +#define WF_PLE_FSM_PEEK_CR_07 (WF_PLE_TOP_BASE + 0x03EC) +#define WF_PLE_FSM_PEEK_CR_08 (WF_PLE_TOP_BASE + 0x03F0) +#define WF_PLE_FSM_PEEK_CR_09 (WF_PLE_TOP_BASE + 0x03F4) +#define WF_PLE_FSM_PEEK_CR_10 (WF_PLE_TOP_BASE + 0x03F8) +#define WF_PLE_FSM_PEEK_CR_11 (WF_PLE_TOP_BASE + 0x03FC) + +#define WF_PSE_FSM_PEEK_CR_00 (WF_PSE_TOP_BASE + 0x03D0) +#define WF_PSE_FSM_PEEK_CR_01 (WF_PSE_TOP_BASE + 0x03D4) +#define WF_PSE_FSM_PEEK_CR_02 (WF_PSE_TOP_BASE + 0x03D8) +#define WF_PSE_FSM_PEEK_CR_03 (WF_PSE_TOP_BASE + 0x03DC) +#define WF_PSE_FSM_PEEK_CR_04 (WF_PSE_TOP_BASE + 0x03E0) +#define WF_PSE_FSM_PEEK_CR_05 (WF_PSE_TOP_BASE + 0x03E4) +#define WF_PSE_FSM_PEEK_CR_06 (WF_PSE_TOP_BASE + 0x03E8) +#define WF_PSE_FSM_PEEK_CR_07 (WF_PSE_TOP_BASE + 0x03EC) +#define WF_PSE_FSM_PEEK_CR_08 (WF_PSE_TOP_BASE + 0x03F0) +#define WF_PSE_FSM_PEEK_CR_09 (WF_PSE_TOP_BASE + 0x03F4) + +#if WFSYS_SUPPORT_BUS_HANG_READ_FROM_DRIVER_BASE +/* define for read Driver Base CR */ +#define CONNAC2X_MCU_WPDMA_0_DRIVER_BASE 0x18402000 +#define CONNAC2X_MCU_WPDMA_1_DRIVER_BASE 0x18403000 +#define CONNAC2X_HOST_WPDMA_0_DRIVER_BASE 0x18024000 +#define CONNAC2X_HOST_WPDMA_1_DRIVER_BASE 0x18025000 + +#define CONNAC2X_HOST_EXT_CONN_HIF_WRAP_DRIVER_BASE 0x18027000 +#define CONNAC2X_MCU_INT_CONN_HIF_WRAP_DRIVER_BASE 0x18405000 + +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL0_ADDR_DRIVER_BASE \ + (CONNAC2X_HOST_WPDMA_1_DRIVER_BASE + 0x300) /* 5300 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL1_ADDR_DRIVER_BASE \ + (CONNAC2X_HOST_WPDMA_1_DRIVER_BASE + 0x304) /* 5304 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL0_ADDR_DRIVER_BASE \ + (CONNAC2X_HOST_WPDMA_1_DRIVER_BASE + 0x400) /* 5400 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL0_ADDR_DRIVER_BASE \ + (CONNAC2X_HOST_WPDMA_1_DRIVER_BASE + 0x380) /* 5380 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL0_ADDR_DRIVER_BASE \ + (CONNAC2X_HOST_WPDMA_1_DRIVER_BASE + 0x410) /* 5410 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL0_ADDR_DRIVER_BASE \ + (CONNAC2X_HOST_WPDMA_1_DRIVER_BASE + 0x420) /* 5420 */ + +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL0_ADDR_DRIVER_BASE \ + (CONNAC2X_HOST_WPDMA_0_DRIVER_BASE + 0x500) /* 4500 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL0_ADDR_DRIVER_BASE \ + (CONNAC2X_HOST_WPDMA_0_DRIVER_BASE + 0x510) /* 4510 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL0_ADDR_DRIVER_BASE \ + (CONNAC2X_HOST_WPDMA_0_DRIVER_BASE + 0x520) /* 4520 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL0_ADDR_DRIVER_BASE \ + (CONNAC2X_HOST_WPDMA_0_DRIVER_BASE + 0x530) /* 4530 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL0_ADDR_DRIVER_BASE \ + (CONNAC2X_HOST_WPDMA_1_DRIVER_BASE + 0x500) /* 5500 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL0_ADDR_DRIVER_BASE \ + (CONNAC2X_HOST_WPDMA_0_DRIVER_BASE + 0x540) /* 4540 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL0_ADDR_DRIVER_BASE \ + (CONNAC2X_HOST_WPDMA_0_DRIVER_BASE + 0x550) /* 4550 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL0_ADDR_DRIVER_BASE \ + (CONNAC2X_HOST_WPDMA_0_DRIVER_BASE + 0x560) /* 4560 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL0_ADDR_DRIVER_BASE \ + (CONNAC2X_HOST_WPDMA_0_DRIVER_BASE + 0x570) /* 4570 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL0_ADDR_DRIVER_BASE \ + (CONNAC2X_HOST_WPDMA_1_DRIVER_BASE + 0x510) /* 5510 */ + +#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING0_CTRL0_ADDR_DRIVER_BASE \ + (CONNAC2X_MCU_WPDMA_0_DRIVER_BASE + 0x300) +#define WF_WFDMA_MCU_DMA1_WPDMA_TX_RING0_CTRL0_ADDR_DRIVER_BASE \ + (CONNAC2X_MCU_WPDMA_0_DRIVER_BASE + 0x300) +#define WF_WFDMA_MCU_DMA1_WPDMA_TX_RING1_CTRL0_ADDR_DRIVER_BASE \ + (CONNAC2X_MCU_WPDMA_1_DRIVER_BASE + 0x310) +#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING0_CTRL0_ADDR_DRIVER_BASE \ + (CONNAC2X_MCU_WPDMA_1_DRIVER_BASE + 0x500) +#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING1_CTRL0_ADDR_DRIVER_BASE \ + (CONNAC2X_MCU_WPDMA_0_DRIVER_BASE + 0x510) +#define WF_WFDMA_MCU_DMA1_WPDMA_RX_RING0_CTRL0_ADDR_DRIVER_BASE \ + (CONNAC2X_MCU_WPDMA_1_DRIVER_BASE + 0x500) +#define WF_WFDMA_MCU_DMA1_WPDMA_RX_RING1_CTRL0_ADDR_DRIVER_BASE \ + (CONNAC2X_MCU_WPDMA_1_DRIVER_BASE + 0x510) +#define WF_WFDMA_MCU_DMA1_WPDMA_RX_RING2_CTRL0_ADDR_DRIVER_BASE \ + (CONNAC2X_MCU_WPDMA_1_DRIVER_BASE + 0x520) + +#endif /* WFSYS_SUPPORT_BUS_HANG_READ_FROM_DRIVER_BASE */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +struct pse_group_info { + char name[20]; + u_int32_t quota_addr; + u_int32_t pg_info_addr; +}; + +struct wfdma_group_info { + char name[20]; + u_int32_t hw_desc_base; +}; + +enum _ENUM_WFDMA_TYPE_T { + WFDMA_TYPE_HOST = 0, + WFDMA_TYPE_WM +}; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +static struct EMPTY_QUEUE_INFO ple_queue_empty_info[] = { + {"CPU Q0", MCU_Q0_INDEX, ENUM_UMAC_CTX_Q_0}, + {"CPU Q1", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_1}, + {"CPU Q2", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_2}, + {"CPU Q3", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_3}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, /* 4~7 not defined */ + {"ALTX Q0", ENUM_UMAC_LMAC_PORT_2, + ENUM_UMAC_LMAC_PLE_TX_Q_ALTX_0}, /* Q16 */ + {"BMC Q0", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_BMC_0}, + {"BCN Q0", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_BNC_0}, + {"PSMP Q0", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_PSMP_0}, + {"ALTX Q1", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_ALTX_1}, + {"BMC Q1", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_BMC_1}, + {"BCN Q1", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_BNC_1}, + {"PSMP Q1", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_PSMP_1}, + {"NAF Q", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_NAF}, + {"NBCN Q", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_NBCN}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, /* 18~29 not defined */ + {"RLS Q", ENUM_PLE_CTRL_PSE_PORT_3, ENUM_UMAC_PLE_CTRL_P3_Q_0X1E}, + {"RLS2 Q", ENUM_PLE_CTRL_PSE_PORT_3, ENUM_UMAC_PLE_CTRL_P3_Q_0X1F} }; + +static struct EMPTY_QUEUE_INFO pse_queue_empty_info[] = { + {"CPU Q0", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_0}, + {"CPU Q1", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_1}, + {"CPU Q2", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_2}, + {"CPU Q3", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_3}, + {"HIF Q8", ENUM_UMAC_HIF_PORT_0, 8}, + {"HIF Q9", ENUM_UMAC_HIF_PORT_0, 9}, + {"HIF Q10", ENUM_UMAC_HIF_PORT_0, 10}, + {"HIF Q11", ENUM_UMAC_HIF_PORT_0, 11}, + {"HIF Q0", ENUM_UMAC_HIF_PORT_0, 0}, /*bit 8*/ + {"HIF Q1", ENUM_UMAC_HIF_PORT_0, 1}, + {"HIF Q2", ENUM_UMAC_HIF_PORT_0, 2}, + {"HIF Q3", ENUM_UMAC_HIF_PORT_0, 3}, + {"HIF Q4", ENUM_UMAC_HIF_PORT_0, 4}, + {"HIF Q5", ENUM_UMAC_HIF_PORT_0, 5}, + {"HIF Q6", ENUM_UMAC_HIF_PORT_0, 6}, + {"HIF Q7", ENUM_UMAC_HIF_PORT_0, 7}, + {"LMAC Q", ENUM_UMAC_LMAC_PORT_2, 0}, /*bit 16*/ + {"MDP TX Q", ENUM_UMAC_LMAC_PORT_2, 1}, + {"MDP RX Q", ENUM_UMAC_LMAC_PORT_2, 2}, + {"SEC TX Q", ENUM_UMAC_LMAC_PORT_2, 3}, + {"SEC RX Q", ENUM_UMAC_LMAC_PORT_2, 4}, + {"SFD_PARK Q", ENUM_UMAC_LMAC_PORT_2, 5}, + {"MDP_TXIOC Q", ENUM_UMAC_LMAC_PORT_2, 6}, + {"MDP_RXIOC Q", ENUM_UMAC_LMAC_PORT_2, 7}, + {"MDP_TX1 Q", ENUM_UMAC_LMAC_PORT_2, 17}, /*bit 24*/ + {"SEC_TX1 Q", ENUM_UMAC_LMAC_PORT_2, 19}, + {"MDP_TXIOC1 Q", ENUM_UMAC_LMAC_PORT_2, 22}, + {"MDP_RXIOC1 Q", ENUM_UMAC_LMAC_PORT_2, 23}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, /* 28~30 not defined */ + {"RLS Q", ENUM_PLE_CTRL_PSE_PORT_3, ENUM_UMAC_PLE_CTRL_P3_Q_0X1F} }; + +static u_int8_t *sta_ctrl_reg[] = {"ENABLE", "DISABLE", "PAUSE"}; + +#if 0 +static struct EMPTY_QUEUE_INFO ple_txcmd_queue_empty_info[] = { + {"AC00Q", ENUM_UMAC_LMAC_PORT_2, 0x40}, + {"AC01Q", ENUM_UMAC_LMAC_PORT_2, 0x41}, + {"AC02Q", ENUM_UMAC_LMAC_PORT_2, 0x42}, + {"AC03Q", ENUM_UMAC_LMAC_PORT_2, 0x43}, + {"AC10Q", ENUM_UMAC_LMAC_PORT_2, 0x44}, + {"AC11Q", ENUM_UMAC_LMAC_PORT_2, 0x45}, + {"AC12Q", ENUM_UMAC_LMAC_PORT_2, 0x46}, + {"AC13Q", ENUM_UMAC_LMAC_PORT_2, 0x47}, + {"AC20Q", ENUM_UMAC_LMAC_PORT_2, 0x48}, + {"AC21Q", ENUM_UMAC_LMAC_PORT_2, 0x49}, + {"AC22Q", ENUM_UMAC_LMAC_PORT_2, 0x4a}, + {"AC23Q", ENUM_UMAC_LMAC_PORT_2, 0x4b}, + {"AC30Q", ENUM_UMAC_LMAC_PORT_2, 0x4c}, + {"AC31Q", ENUM_UMAC_LMAC_PORT_2, 0x4d}, + {"AC32Q", ENUM_UMAC_LMAC_PORT_2, 0x4e}, + {"AC33Q", ENUM_UMAC_LMAC_PORT_2, 0x4f}, + {"ALTX Q0", ENUM_UMAC_LMAC_PORT_2, 0x50}, + {"TF Q0", ENUM_UMAC_LMAC_PORT_2, 0x51}, + {"TWT TSF-TF Q0", ENUM_UMAC_LMAC_PORT_2, 0x52}, + {"TWT DL Q0", ENUM_UMAC_LMAC_PORT_2, 0x53}, + {"TWT UL Q0", ENUM_UMAC_LMAC_PORT_2, 0x54}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0}, + {NULL, 0, 0} }; +#endif + +struct pse_group_info pse_group[] = { + {"HIF0(TX data)", WF_PSE_TOP_PG_HIF0_GROUP_ADDR, + WF_PSE_TOP_HIF0_PG_INFO_ADDR}, + {"HIF1(Talos CMD)", WF_PSE_TOP_PG_HIF1_GROUP_ADDR, + WF_PSE_TOP_HIF1_PG_INFO_ADDR}, +#if 0 + {"HIF2", WF_PSE_TOP_PG_HIF2_GROUP_ADDR, + WF_PSE_TOP_HIF2_PG_INFO_ADDR}, +#endif + {"CPU(I/O r/w)", WF_PSE_TOP_PG_CPU_GROUP_ADDR, + WF_PSE_TOP_CPU_PG_INFO_ADDR}, + {"PLE(host report)", WF_PSE_TOP_PG_PLE_GROUP_ADDR, + WF_PSE_TOP_PLE_PG_INFO_ADDR}, + {"PLE1(SPL report)", WF_PSE_TOP_PG_PLE1_GROUP_ADDR, + WF_PSE_TOP_PLE1_PG_INFO_ADDR}, + {"LMAC0(RX data)", WF_PSE_TOP_PG_LMAC0_GROUP_ADDR, + WF_PSE_TOP_LMAC0_PG_INFO_ADDR}, + {"LMAC1(RX_VEC)", WF_PSE_TOP_PG_LMAC1_GROUP_ADDR, + WF_PSE_TOP_LMAC1_PG_INFO_ADDR}, + {"LMAC2(TXS)", WF_PSE_TOP_PG_LMAC2_GROUP_ADDR, + WF_PSE_TOP_LMAC2_PG_INFO_ADDR}, + {"LMAC3(TXCMD/RXRPT)", WF_PSE_TOP_PG_LMAC3_GROUP_ADDR, + WF_PSE_TOP_LMAC3_PG_INFO_ADDR}, + {"MDP", WF_PSE_TOP_PG_MDP_GROUP_ADDR, + WF_PSE_TOP_MDP_PG_INFO_ADDR}, +#if 0 + {"MDP1", WF_PSE_TOP_PG_MDP1_GROUP_ADDR, + WF_PSE_TOP_MDP1_PG_INFO_ADDR}, + {"MDP2", WF_PSE_TOP_PG_MDP2_GROUP_ADDR, + WF_PSE_TOP_MDP2_PG_INFO_ADDR}, +#endif +}; + +struct wfdma_group_info wfmda_host_tx_group[] = { + {"P1T0:AP DATA0", WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL0_ADDR}, + {"P1T1:AP DATA1", WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL0_ADDR}, + {"P1T16:FWDL", WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL0_ADDR}, + {"P1T17:AP CMD", WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL0_ADDR}, + {"P1T8:MD DATA", WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL0_ADDR}, + {"P1T18:MD CMD", WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL0_ADDR}, +}; + +struct wfdma_group_info wfmda_host_rx_group[] = { + {"P0R0:AP DATA0", WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL0_ADDR}, + {"P0R1:AP DATA1", WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL0_ADDR}, + {"P0R2:AP TDONE0", WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL0_ADDR}, + {"P0R3:AP TDONE1", WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL0_ADDR}, + {"P1R0:AP EVENT", WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL0_ADDR}, + {"P0R4:MD DATA0", WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL0_ADDR}, + {"P0R5:MD DATA1", WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL0_ADDR}, + {"P0R6:MD TDONE0", WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL0_ADDR}, + {"P0R7:MD TDONE1", WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL0_ADDR}, + {"P1R1:MD EVENT", WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL0_ADDR}, +}; + +struct wfdma_group_info wfmda_wm_tx_group[] = { + {"P0T0:DATA", WF_WFDMA_MCU_DMA0_WPDMA_TX_RING0_CTRL0_ADDR}, + {"P1T0:AP EVENT", WF_WFDMA_MCU_DMA1_WPDMA_TX_RING0_CTRL0_ADDR}, + {"P1T1:MD EVENT", WF_WFDMA_MCU_DMA1_WPDMA_TX_RING1_CTRL0_ADDR}, +}; + +struct wfdma_group_info wfmda_wm_rx_group[] = { + {"P0R0:DATA", WF_WFDMA_MCU_DMA0_WPDMA_RX_RING0_CTRL0_ADDR}, + {"P0R1:TXDONE", WF_WFDMA_MCU_DMA0_WPDMA_RX_RING1_CTRL0_ADDR}, + {"P1R0:FWDL", WF_WFDMA_MCU_DMA1_WPDMA_RX_RING0_CTRL0_ADDR}, + {"P1R1:AP CMD", WF_WFDMA_MCU_DMA1_WPDMA_RX_RING1_CTRL0_ADDR}, + {"P1R2:MD CMD", WF_WFDMA_MCU_DMA1_WPDMA_RX_RING2_CTRL0_ADDR}, +}; + +#if WFSYS_SUPPORT_BUS_HANG_READ_FROM_DRIVER_BASE +struct wfdma_group_info wfmda_host_tx_group_driver_base[] = { + {"P1T0:AP DATA0", + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL0_ADDR_DRIVER_BASE}, + {"P1T1:AP DATA1", + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL0_ADDR_DRIVER_BASE}, + {"P1T16:FWDL", + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL0_ADDR_DRIVER_BASE}, + {"P1T17:AP CMD", + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL0_ADDR_DRIVER_BASE}, + {"P1T8:MD DATA", + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL0_ADDR_DRIVER_BASE}, + {"P1T18:MD CMD", + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL0_ADDR_DRIVER_BASE}, +}; + +struct wfdma_group_info wfmda_host_rx_group_driver_base[] = { + {"P0R0:AP DATA0", + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL0_ADDR_DRIVER_BASE}, + {"P0R1:AP DATA1", + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL0_ADDR_DRIVER_BASE}, + {"P0R2:AP TDONE0", + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL0_ADDR_DRIVER_BASE}, + {"P0R3:AP TDONE1", + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL0_ADDR_DRIVER_BASE}, + {"P1R0:AP EVENT", + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL0_ADDR_DRIVER_BASE}, + {"P0R4:MD DATA0", + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL0_ADDR_DRIVER_BASE}, + {"P0R5:MD DATA1", + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL0_ADDR_DRIVER_BASE}, + {"P0R6:MD TDONE0", + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL0_ADDR_DRIVER_BASE}, + {"P0R7:MD TDONE1", + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL0_ADDR_DRIVER_BASE}, + {"P1R1:MD EVENT", + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL0_ADDR_DRIVER_BASE}, +}; + +struct wfdma_group_info wfmda_wm_tx_group_driver_base[] = { + {"P0T0:DATA", + WF_WFDMA_MCU_DMA0_WPDMA_TX_RING0_CTRL0_ADDR_DRIVER_BASE}, + {"P1T0:AP EVENT", + WF_WFDMA_MCU_DMA1_WPDMA_TX_RING0_CTRL0_ADDR_DRIVER_BASE}, + {"P1T1:MD EVENT", + WF_WFDMA_MCU_DMA1_WPDMA_TX_RING1_CTRL0_ADDR_DRIVER_BASE}, +}; + +struct wfdma_group_info wfmda_wm_rx_group_driver_base[] = { + {"P0R0:DATA", + WF_WFDMA_MCU_DMA0_WPDMA_RX_RING0_CTRL0_ADDR_DRIVER_BASE}, + {"P0R1:TXDONE", + WF_WFDMA_MCU_DMA0_WPDMA_RX_RING1_CTRL0_ADDR_DRIVER_BASE}, + {"P1R0:FWDL", + WF_WFDMA_MCU_DMA1_WPDMA_RX_RING0_CTRL0_ADDR_DRIVER_BASE}, + {"P1R1:AP CMD", + WF_WFDMA_MCU_DMA1_WPDMA_RX_RING1_CTRL0_ADDR_DRIVER_BASE}, + {"P1R2:MD CMD", + WF_WFDMA_MCU_DMA1_WPDMA_RX_RING2_CTRL0_ADDR_DRIVER_BASE}, +}; +#endif /* WFSYS_SUPPORT_BUS_HANG_READ_FROM_DRIVER_BASE */ + +/******************************************************************************* + * M A 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 soc3_0_show_ple_info( + struct ADAPTER *prAdapter, + u_int8_t fgDumpTxd) +{ + u_int32_t int_n9_err = 0; + u_int32_t int_n9_err1 = 0; + u_int32_t ple_buf_ctrl = 0, pg_sz, pg_num; + u_int32_t ple_stat[25] = {0}, pg_flow_ctrl[10] = {0}; + u_int32_t sta_pause[6] = {0}, dis_sta_map[6] = {0}; + u_int32_t fpg_cnt, ffa_cnt, fpg_head, fpg_tail, hif_max_q, hif_min_q; + u_int32_t rpg_hif, upg_hif, cpu_max_q, cpu_min_q, rpg_cpu, upg_cpu; + u_int32_t i, j; + u_int32_t ple_peek[12] = {0}; + u_int32_t ple_empty = 0; + u_int32_t ple_txd_empty = 0; + +#if 0 + u_int32_t ple_txcmd_stat; +#endif + + HAL_MCR_RD(prAdapter, WF_PLE_TOP_INT_N9_ERR_STS_ADDR, &int_n9_err); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR, &int_n9_err1); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_QUEUE_EMPTY_ADDR, &ple_empty); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR, &ple_txd_empty); + + HAL_MCR_RD(prAdapter, WF_PLE_TOP_PBUF_CTRL_ADDR, &ple_buf_ctrl); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_QUEUE_EMPTY_ADDR, &ple_stat[0]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC0_QUEUE_EMPTY0_ADDR, &ple_stat[1]); +#if 0 + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC0_QUEUE_EMPTY1_ADDR, &ple_stat[2]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC0_QUEUE_EMPTY2_ADDR, &ple_stat[3]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC0_QUEUE_EMPTY3_ADDR, &ple_stat[4]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC0_QUEUE_EMPTY4_ADDR, &ple_stat[5]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC0_QUEUE_EMPTY5_ADDR, &ple_stat[6]); +#endif + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC1_QUEUE_EMPTY0_ADDR, &ple_stat[7]); +#if 0 + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC1_QUEUE_EMPTY1_ADDR, &ple_stat[8]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC1_QUEUE_EMPTY2_ADDR, &ple_stat[9]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC1_QUEUE_EMPTY3_ADDR, &ple_stat[10]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC1_QUEUE_EMPTY4_ADDR, &ple_stat[11]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC1_QUEUE_EMPTY5_ADDR, &ple_stat[12]); +#endif + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC2_QUEUE_EMPTY0_ADDR, &ple_stat[13]); +#if 0 + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC2_QUEUE_EMPTY1_ADDR, &ple_stat[14]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC2_QUEUE_EMPTY2_ADDR, &ple_stat[15]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC2_QUEUE_EMPTY3_ADDR, &ple_stat[16]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC2_QUEUE_EMPTY4_ADDR, &ple_stat[17]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC2_QUEUE_EMPTY5_ADDR, &ple_stat[18]); +#endif + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC3_QUEUE_EMPTY0_ADDR, &ple_stat[19]); +#if 0 + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC3_QUEUE_EMPTY1_ADDR, &ple_stat[20]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC3_QUEUE_EMPTY2_ADDR, &ple_stat[21]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC3_QUEUE_EMPTY3_ADDR, &ple_stat[22]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC3_QUEUE_EMPTY4_ADDR, &ple_stat[23]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_AC3_QUEUE_EMPTY5_ADDR, &ple_stat[24]); +#endif +#if 0 + HAL_MCR_RD(prAdapter, WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR, + &ple_txcmd_stat); +#endif + HAL_MCR_RD(prAdapter, WF_PLE_TOP_FREEPG_CNT_ADDR, &pg_flow_ctrl[0]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_FREEPG_HEAD_TAIL_ADDR, + &pg_flow_ctrl[1]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_PG_HIF_GROUP_ADDR, &pg_flow_ctrl[2]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_HIF_PG_INFO_ADDR, &pg_flow_ctrl[3]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_PG_CPU_GROUP_ADDR, &pg_flow_ctrl[4]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_CPU_PG_INFO_ADDR, &pg_flow_ctrl[5]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_PG_HIF_TXCMD_GROUP_ADDR, + &pg_flow_ctrl[6]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_HIF_TXCMD_PG_INFO_ADDR, + &pg_flow_ctrl[7]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_PG_HIF_WMTXD_GROUP_ADDR, + &pg_flow_ctrl[8]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_HIF_WMTXD_PG_INFO_ADDR, + &pg_flow_ctrl[9]); + + HAL_MCR_RD(prAdapter, WF_PLE_TOP_DIS_STA_MAP0_ADDR, &dis_sta_map[0]); +#if 0 + HAL_MCR_RD(prAdapter, WF_PLE_TOP_DIS_STA_MAP1_ADDR, &dis_sta_map[1]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_DIS_STA_MAP2_ADDR, &dis_sta_map[2]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_DIS_STA_MAP3_ADDR, &dis_sta_map[3]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_DIS_STA_MAP4_ADDR, &dis_sta_map[4]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_DIS_STA_MAP5_ADDR, &dis_sta_map[5]); +#endif + HAL_MCR_RD(prAdapter, WF_PLE_TOP_STATION_PAUSE0_ADDR, &sta_pause[0]); +#if 0 + HAL_MCR_RD(prAdapter, WF_PLE_TOP_STATION_PAUSE1_ADDR, &sta_pause[1]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_STATION_PAUSE2_ADDR, &sta_pause[2]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_STATION_PAUSE3_ADDR, &sta_pause[3]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_STATION_PAUSE4_ADDR, &sta_pause[4]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_STATION_PAUSE5_ADDR, &sta_pause[5]); +#endif + + HAL_MCR_RD(prAdapter, WF_PLE_FSM_PEEK_CR_00, &ple_peek[0]); + HAL_MCR_RD(prAdapter, WF_PLE_FSM_PEEK_CR_01, &ple_peek[1]); + HAL_MCR_RD(prAdapter, WF_PLE_FSM_PEEK_CR_02, &ple_peek[2]); + HAL_MCR_RD(prAdapter, WF_PLE_FSM_PEEK_CR_03, &ple_peek[3]); + HAL_MCR_RD(prAdapter, WF_PLE_FSM_PEEK_CR_04, &ple_peek[4]); + HAL_MCR_RD(prAdapter, WF_PLE_FSM_PEEK_CR_05, &ple_peek[5]); + HAL_MCR_RD(prAdapter, WF_PLE_FSM_PEEK_CR_06, &ple_peek[6]); + HAL_MCR_RD(prAdapter, WF_PLE_FSM_PEEK_CR_07, &ple_peek[7]); + HAL_MCR_RD(prAdapter, WF_PLE_FSM_PEEK_CR_08, &ple_peek[8]); + HAL_MCR_RD(prAdapter, WF_PLE_FSM_PEEK_CR_09, &ple_peek[9]); + HAL_MCR_RD(prAdapter, WF_PLE_FSM_PEEK_CR_10, &ple_peek[10]); + HAL_MCR_RD(prAdapter, WF_PLE_FSM_PEEK_CR_11, &ple_peek[11]); + + /* Error Status Info */ + DBGLOG(HAL, INFO, + "PLE Error Status(0x%08x):0x%08x,Error Status1(0x%08x):0x%08x\n", + WF_PLE_TOP_INT_N9_ERR_STS_ADDR, int_n9_err, + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR, int_n9_err1); + + /* FSM PEEK CR */ + DBGLOG(HAL, INFO, + "00(0x%08x):0x%08x,01(0x%08x):0x%08x,02(0x%08x):0x%08x,03(0x%08x):0x%08x,04(0x%08x):0x%08x,05(0x%08x):0x%08x,", + WF_PLE_FSM_PEEK_CR_00, ple_peek[0], + WF_PLE_FSM_PEEK_CR_01, ple_peek[1], + WF_PLE_FSM_PEEK_CR_02, ple_peek[2], + WF_PLE_FSM_PEEK_CR_03, ple_peek[3], + WF_PLE_FSM_PEEK_CR_04, ple_peek[4], + WF_PLE_FSM_PEEK_CR_05, ple_peek[5]); + + DBGLOG(HAL, INFO, + "06(0x%08x):0x%08x,07(0x%08x):0x%08x,08(0x%08x):0x%08x,09(0x%08x):0x%08x,10(0x%08x):0x%08x,11(0x%08x):0x%08x\n", + WF_PLE_FSM_PEEK_CR_06, ple_peek[6], + WF_PLE_FSM_PEEK_CR_07, ple_peek[7], + WF_PLE_FSM_PEEK_CR_08, ple_peek[8], + WF_PLE_FSM_PEEK_CR_09, ple_peek[9], + WF_PLE_FSM_PEEK_CR_10, ple_peek[10], + WF_PLE_FSM_PEEK_CR_11, ple_peek[11]); + + /* Configuration Info */ + + pg_sz = (ple_buf_ctrl & WF_PLE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_MASK) >> + WF_PLE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_SHFT; + pg_num = (ple_buf_ctrl & WF_PLE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_MASK) >> + WF_PLE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_SHFT; + + DBGLOG(HAL, INFO, + "Buffer Control(0x%08x):0x%08x,Page Size=%d, Page Offset=%d, Total Page=%d\n", + WF_PLE_TOP_PBUF_CTRL_ADDR, + ple_buf_ctrl, + pg_sz, + (ple_buf_ctrl & WF_PLE_TOP_PBUF_CTRL_PBUF_OFFSET_MASK) >> + WF_PLE_TOP_PBUF_CTRL_PBUF_OFFSET_SHFT, + pg_num); + + /* Flow-Control: Page Flow Control */ + fpg_cnt = (pg_flow_ctrl[0] & WF_PLE_TOP_FREEPG_CNT_FREEPG_CNT_MASK) >> + WF_PLE_TOP_FREEPG_CNT_FREEPG_CNT_SHFT; + ffa_cnt = (pg_flow_ctrl[0] & WF_PLE_TOP_FREEPG_CNT_FFA_CNT_MASK) >> + WF_PLE_TOP_FREEPG_CNT_FFA_CNT_SHFT; + + DBGLOG(HAL, INFO, + "Free page counter(0x%08x):0x%08x,The toal page number of free=0x%03x,The free page numbers of free for all=0x%03x\n", + WF_PLE_TOP_FREEPG_CNT_ADDR, + pg_flow_ctrl[0], fpg_cnt, ffa_cnt); + + /* PLE tail / head FID */ + fpg_head = (pg_flow_ctrl[1] & + WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_MASK) >> + WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_SHFT; + fpg_tail = (pg_flow_ctrl[1] & + WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_MASK) >> + WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_SHFT; + DBGLOG(HAL, INFO, + "Free page tail/head FID(0x%08x):0x%08x,The tail/head page of free page list=0x%03x/0x%03x\n", + WF_PLE_TOP_FREEPG_HEAD_TAIL_ADDR, + pg_flow_ctrl[1], fpg_tail, fpg_head); + + /* Flow-Control: Show PLE HIF Group information */ + DBGLOG(HAL, INFO, + "Reserved page counter of HIF group(0x%08x):0x%08x,status(0x%08x):0x%08x\n", + WF_PLE_TOP_PG_HIF_GROUP_ADDR, pg_flow_ctrl[2], + WF_PLE_TOP_HIF_PG_INFO_ADDR, pg_flow_ctrl[3]); + + hif_min_q = (pg_flow_ctrl[2] & + WF_PLE_TOP_PG_HIF_GROUP_HIF_MIN_QUOTA_MASK) >> + WF_PLE_TOP_PG_HIF_GROUP_HIF_MIN_QUOTA_SHFT; + hif_max_q = (pg_flow_ctrl[2] & + WF_PLE_TOP_PG_HIF_GROUP_HIF_MAX_QUOTA_MASK) >> + WF_PLE_TOP_PG_HIF_GROUP_HIF_MAX_QUOTA_SHFT; + DBGLOG(HAL, TRACE, + "\tThe max/min quota pages of HIF group=0x%03x/0x%03x\n", + hif_max_q, hif_min_q); + rpg_hif = (pg_flow_ctrl[3] & WF_PLE_TOP_HIF_PG_INFO_HIF_RSV_CNT_MASK) >> + WF_PLE_TOP_HIF_PG_INFO_HIF_RSV_CNT_SHFT; + upg_hif = (pg_flow_ctrl[3] & WF_PLE_TOP_HIF_PG_INFO_HIF_SRC_CNT_MASK) >> + WF_PLE_TOP_HIF_PG_INFO_HIF_SRC_CNT_SHFT; + DBGLOG(HAL, TRACE, + "\tThe used/reserved pages of HIF group=0x%03x/0x%03x\n", + upg_hif, rpg_hif); + + /* Flow-Control: Show PLE CPU Group information */ + DBGLOG(HAL, INFO, + "Reserved page counter of CPU group(0x%08x):0x%08x,status(0x%08x):0x%08x\n", + WF_PLE_TOP_PG_CPU_GROUP_ADDR, pg_flow_ctrl[4], + WF_PLE_TOP_CPU_PG_INFO_ADDR, pg_flow_ctrl[5]); + + cpu_min_q = (pg_flow_ctrl[4] & + WF_PLE_TOP_PG_CPU_GROUP_CPU_MIN_QUOTA_MASK) >> + WF_PLE_TOP_PG_CPU_GROUP_CPU_MIN_QUOTA_SHFT; + cpu_max_q = (pg_flow_ctrl[4] & + WF_PLE_TOP_PG_CPU_GROUP_CPU_MAX_QUOTA_MASK) >> + WF_PLE_TOP_PG_CPU_GROUP_CPU_MAX_QUOTA_SHFT; + DBGLOG(HAL, TRACE, + "\tThe max/min quota pages of CPU group=0x%03x/0x%03x\n", + cpu_max_q, cpu_min_q); + rpg_cpu = (pg_flow_ctrl[5] & WF_PLE_TOP_CPU_PG_INFO_CPU_RSV_CNT_MASK) >> + WF_PLE_TOP_CPU_PG_INFO_CPU_RSV_CNT_SHFT; + upg_cpu = (pg_flow_ctrl[5] & WF_PLE_TOP_CPU_PG_INFO_CPU_SRC_CNT_MASK) >> + WF_PLE_TOP_CPU_PG_INFO_CPU_SRC_CNT_SHFT; + DBGLOG(HAL, TRACE, + "\tThe used/reserved pages of CPU group=0x%03x/0x%03x\n", + upg_cpu, rpg_cpu); + + /* Flow-Control: Show PLE WMTXD Group information */ + DBGLOG(HAL, INFO, + "Reserved page counter of HIF_WMTXD group(0x%08x):0x%08x,status(0x%08x):0x%08x\n", + WF_PLE_TOP_PG_HIF_WMTXD_GROUP_ADDR, pg_flow_ctrl[8], + WF_PLE_TOP_HIF_WMTXD_PG_INFO_ADDR, pg_flow_ctrl[9]); + cpu_min_q = (pg_flow_ctrl[8] & + WF_PLE_TOP_PG_HIF_WMTXD_GROUP_HIF_WMTXD_MIN_QUOTA_MASK) >> + WF_PLE_TOP_PG_HIF_WMTXD_GROUP_HIF_WMTXD_MIN_QUOTA_SHFT; + cpu_max_q = (pg_flow_ctrl[8] & + WF_PLE_TOP_PG_HIF_WMTXD_GROUP_HIF_WMTXD_MAX_QUOTA_MASK) >> + WF_PLE_TOP_PG_HIF_WMTXD_GROUP_HIF_WMTXD_MAX_QUOTA_SHFT; + DBGLOG(HAL, TRACE, + "\tThe max/min quota pages of HIF_WMTXD group=0x%03x/0x%03x\n", + cpu_max_q, cpu_min_q); + rpg_cpu = (pg_flow_ctrl[9] & + WF_PLE_TOP_HIF_WMTXD_PG_INFO_HIF_WMTXD_RSV_CNT_MASK) >> + WF_PLE_TOP_HIF_WMTXD_PG_INFO_HIF_WMTXD_RSV_CNT_SHFT; + upg_cpu = (pg_flow_ctrl[9] & + WF_PLE_TOP_HIF_WMTXD_PG_INFO_HIF_WMTXD_SRC_CNT_MASK) >> + WF_PLE_TOP_HIF_WMTXD_PG_INFO_HIF_WMTXD_SRC_CNT_SHFT; + DBGLOG(HAL, TRACE, + "\tThe used/reserved pages of HIF_WMTXD group=0x%03x/0x%03x\n", + upg_cpu, rpg_cpu); + + /* Flow-Control: Show PLE TXCMD Group information */ + DBGLOG(HAL, INFO, + "Reserved page counter of HIF_TXCMD group(0x%08x):0x%08x,status(0x%08x):0x%08x\n", + WF_PLE_TOP_PG_HIF_TXCMD_GROUP_ADDR, pg_flow_ctrl[6], + WF_PLE_TOP_HIF_TXCMD_PG_INFO_ADDR, pg_flow_ctrl[7]); + cpu_min_q = (pg_flow_ctrl[6] & + WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MIN_QUOTA_MASK) >> + WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MIN_QUOTA_SHFT; + cpu_max_q = (pg_flow_ctrl[6] & + WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MAX_QUOTA_MASK) >> + WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MAX_QUOTA_SHFT; + DBGLOG(HAL, TRACE, + "\t\tThe max/min quota pages of HIF_TXCMD group=0x%03x/0x%03x\n", + cpu_max_q, cpu_min_q); + rpg_cpu = (pg_flow_ctrl[7] & + WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_SRC_CNT_MASK) >> + WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_SRC_CNT_SHFT; + upg_cpu = (pg_flow_ctrl[7] & + WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_RSV_CNT_MASK) >> + WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_RSV_CNT_SHFT; + DBGLOG(HAL, TRACE, + "\t\tThe used/reserved pages of HIF_TXCMD group=0x%03x/0x%03x\n", + upg_cpu, rpg_cpu); + + if ((ple_stat[0] & WF_PLE_TOP_QUEUE_EMPTY_ALL_AC_EMPTY_MASK) == 0) { + for (j = 0; j < 24; j = j + 6) { + if (j % 6 == 0) { + DBGLOG(HAL, INFO, + "\tNonempty AC%d Q of STA#: ", j / 6); + } + + for (i = 0; i < 32; i++) { + if (((ple_stat[j + 1] & (0x1 << i)) >> i) == + 0) { + DBGLOG(HAL, INFO, "%d ", + i + (j % 6) * 32); + } + } + } + DBGLOG(HAL, INFO, ", "); + } + + /* Queue Empty Status */ + DBGLOG(HAL, INFO, + "QUEUE_EMPTY(0x%08x):0x%08xTXD QUEUE_EMPTY(0x%08x):0x%08x\n", + WF_PLE_TOP_QUEUE_EMPTY_ADDR, ple_empty, + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR, ple_txd_empty); + + /* Nonempty Queue Status */ + DBGLOG(HAL, INFO, "Nonempty Q info:"); + + for (i = 0; i < 31; i++) { + if (((ple_stat[0] & (0x1 << i)) >> i) == 0) { + uint32_t hfid, tfid, pktcnt, fl_que_ctrl[3] = {0}; + + if (ple_queue_empty_info[i].QueueName != NULL) { + DBGLOG(HAL, INFO, "\t%s: ", + ple_queue_empty_info[i].QueueName); + fl_que_ctrl[0] |= + WF_PLE_TOP_FL_QUE_CTRL_0_EXECUTE_MASK; + fl_que_ctrl[0] |= + (ple_queue_empty_info[i].Portid + << WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_SHFT); + fl_que_ctrl[0] |= + (ple_queue_empty_info[i].Queueid + << WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_SHFT); + } else + continue; + + HAL_MCR_WR(prAdapter, WF_PLE_TOP_FL_QUE_CTRL_0_ADDR, + fl_que_ctrl[0]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_FL_QUE_CTRL_2_ADDR, + &fl_que_ctrl[1]); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_FL_QUE_CTRL_3_ADDR, + &fl_que_ctrl[2]); + hfid = (fl_que_ctrl[1] & + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_SHFT; + tfid = (fl_que_ctrl[1] & + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_SHFT; + pktcnt = + (fl_que_ctrl[2] & + WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_SHFT; + DBGLOG(HAL, INFO, + "tail/head fid = 0x%03x/0x%03x, pkt cnt = 0x%03x\n", + tfid, hfid, pktcnt); + if (pktcnt > 0 && fgDumpTxd) + connac2x_show_txd_Info( + prAdapter, hfid); + } + } + + for (j = 0; j < 24; j = j + 6) { /* show AC Q info */ + for (i = 0; i < 32; i++) { + if (((ple_stat[j + 1] & (0x1 << i)) >> i) == 0) { + uint32_t hfid, tfid, pktcnt, ac_num = j / 6, + ctrl = 0; + uint32_t sta_num = i + (j % 6) * 32, + fl_que_ctrl[3] = {0}; + uint32_t wmmidx = 0; + + DBGLOG(HAL, INFO, "\tSTA%d AC%d: ", sta_num, + ac_num); + + fl_que_ctrl[0] |= + WF_PLE_TOP_FL_QUE_CTRL_0_EXECUTE_MASK; + fl_que_ctrl[0] |= + (ENUM_UMAC_LMAC_PORT_2 + << WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_SHFT); + fl_que_ctrl[0] |= + (ac_num + << WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_SHFT); + fl_que_ctrl[0] |= + (sta_num + << WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_WLANID_SHFT); + HAL_MCR_WR(prAdapter, + WF_PLE_TOP_FL_QUE_CTRL_0_ADDR, + fl_que_ctrl[0]); + HAL_MCR_RD(prAdapter, + WF_PLE_TOP_FL_QUE_CTRL_2_ADDR, + &fl_que_ctrl[1]); + HAL_MCR_RD(prAdapter, + WF_PLE_TOP_FL_QUE_CTRL_3_ADDR, + &fl_que_ctrl[2]); + hfid = (fl_que_ctrl[1] & + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_SHFT; + tfid = (fl_que_ctrl[1] & + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_SHFT; + + pktcnt = + (fl_que_ctrl[2] & + WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_SHFT; + DBGLOG(HAL, INFO, + "tail/head fid = 0x%03x/0x%03x, pkt cnt = %x", + tfid, hfid, pktcnt); + + if (((sta_pause[j % 6] & 0x1 << i) >> i) == 1) + ctrl = 2; + + if (((dis_sta_map[j % 6] & 0x1 << i) >> i) == 1) + ctrl = 1; + + DBGLOG(HAL, INFO, " ctrl = %s", + sta_ctrl_reg[ctrl]); + DBGLOG(HAL, INFO, " (wmmidx=%d)\n", + wmmidx); + if (pktcnt > 0 && fgDumpTxd) + connac2x_show_txd_Info( + prAdapter, hfid); + } + } + } +#if 0 + if (~ple_txcmd_stat) { + DBGLOG(HAL, INFO, "Nonempty TXCMD Q info:\n"); + for (i = 0; i < 31; i++) { + if (((ple_txcmd_stat & (0x1 << i)) >> i) == 0) { + uint32_t hfid, tfid; + uint32_t pktcnt, fl_que_ctrl[3] = {0}; + + if (ple_txcmd_queue_empty_info[i].QueueName != + NULL) { + DBGLOG(HAL, INFO, "\t%s: ", + ple_txcmd_queue_empty_info[i] + .QueueName); + fl_que_ctrl[0] |= + WF_PLE_TOP_FL_QUE_CTRL_0_EXECUTE_MASK; + fl_que_ctrl[0] |= + (ple_txcmd_queue_empty_info[i] + .Portid + << WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_SHFT); + fl_que_ctrl[0] |= + (ple_txcmd_queue_empty_info[i] + .Queueid + << WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_SHFT); + } else + continue; + + HAL_MCR_WR(prAdapter, + WF_PLE_TOP_FL_QUE_CTRL_0_ADDR, + fl_que_ctrl[0]); + HAL_MCR_RD(prAdapter, + WF_PLE_TOP_FL_QUE_CTRL_2_ADDR, + &fl_que_ctrl[1]); + HAL_MCR_RD(prAdapter, + WF_PLE_TOP_FL_QUE_CTRL_3_ADDR, + &fl_que_ctrl[2]); + hfid = (fl_que_ctrl[1] & + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_SHFT; + tfid = (fl_que_ctrl[1] & + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_SHFT; + pktcnt = + (fl_que_ctrl[2] & + WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_MASK) >> + WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_SHFT; + DBGLOG(HAL, INFO, "tail/head fid ="); + DBGLOG(HAL, INFO, "0x%03x/0x%03x,", tfid, hfid); + DBGLOG(HAL, INFO, "pkt cnt = 0x%03x\n", pktcnt); + } + } + } +#endif +} + +void soc3_0_show_pse_info( + struct ADAPTER *prAdapter) +{ + u_int32_t int_n9_err = 0; + u_int32_t int_n9_err1 = 0; + u_int32_t pse_buf_ctrl = 0; + u_int32_t pg_sz = 0; + u_int32_t pg_num = 0; + u_int32_t pse_stat = 0; + u_int32_t pse_stat_mask = 0; + u_int32_t fpg_cnt, ffa_cnt, fpg_head, fpg_tail; + u_int32_t max_q, min_q, rsv_pg, used_pg; + u_int32_t i, group_cnt; + u_int32_t group_quota = 0; + u_int32_t group_info = 0; + u_int32_t freepg_cnt = 0; + u_int32_t freepg_head_tail = 0; + struct pse_group_info *group; + char *str; + u_int32_t pse_peek[10] = {0}; + + HAL_MCR_RD(prAdapter, WF_PSE_TOP_PBUF_CTRL_ADDR, &pse_buf_ctrl); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_QUEUE_EMPTY_ADDR, &pse_stat); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR, &pse_stat_mask); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_FREEPG_CNT_ADDR, &freepg_cnt); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_FREEPG_HEAD_TAIL_ADDR, + &freepg_head_tail); + + HAL_MCR_RD(prAdapter, WF_PSE_TOP_INT_N9_ERR_STS_ADDR, &int_n9_err); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_INT_N9_ERR1_STS_ADDR, &int_n9_err1); + + HAL_MCR_RD(prAdapter, WF_PSE_FSM_PEEK_CR_00, &pse_peek[0]); + HAL_MCR_RD(prAdapter, WF_PSE_FSM_PEEK_CR_01, &pse_peek[1]); + HAL_MCR_RD(prAdapter, WF_PSE_FSM_PEEK_CR_02, &pse_peek[2]); + HAL_MCR_RD(prAdapter, WF_PSE_FSM_PEEK_CR_03, &pse_peek[3]); + HAL_MCR_RD(prAdapter, WF_PSE_FSM_PEEK_CR_04, &pse_peek[4]); + HAL_MCR_RD(prAdapter, WF_PSE_FSM_PEEK_CR_05, &pse_peek[5]); + HAL_MCR_RD(prAdapter, WF_PSE_FSM_PEEK_CR_06, &pse_peek[6]); + HAL_MCR_RD(prAdapter, WF_PSE_FSM_PEEK_CR_07, &pse_peek[7]); + HAL_MCR_RD(prAdapter, WF_PSE_FSM_PEEK_CR_08, &pse_peek[8]); + HAL_MCR_RD(prAdapter, WF_PSE_FSM_PEEK_CR_09, &pse_peek[9]); + + /* Error Status Info */ + DBGLOG(HAL, INFO, + "PSE Error Status(0x%08x):0x%08x,PSE Error 1 Status(0x%08x):0x%08x\n", + WF_PSE_TOP_INT_N9_ERR_STS_ADDR, int_n9_err, + WF_PSE_TOP_INT_N9_ERR1_STS_ADDR, int_n9_err1); + + DBGLOG(HAL, INFO, + "00(0x%08x):0x%08x,01(0x%08x):0x%08x02(0x%08x):0x%08x,03(0x%08x):0x%08x04(0x%08x):0x%08x,05(0x%08x):0x%08x\n", + WF_PSE_FSM_PEEK_CR_00, pse_peek[0], + WF_PSE_FSM_PEEK_CR_01, pse_peek[1], + WF_PSE_FSM_PEEK_CR_02, pse_peek[2], + WF_PSE_FSM_PEEK_CR_03, pse_peek[3], + WF_PSE_FSM_PEEK_CR_04, pse_peek[4], + WF_PSE_FSM_PEEK_CR_05, pse_peek[5]); + + DBGLOG(HAL, INFO, + "06(0x%08x):0x%08x,07(0x%08x):0x%08x08(0x%08x):0x%08x,09(0x%08x):0x%08x\n", + WF_PSE_FSM_PEEK_CR_06, pse_peek[6], + WF_PSE_FSM_PEEK_CR_07, pse_peek[7], + WF_PSE_FSM_PEEK_CR_08, pse_peek[8], + WF_PSE_FSM_PEEK_CR_09, pse_peek[9]); + + /* Configuration Info */ + pg_sz = (pse_buf_ctrl & WF_PSE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_MASK) >> + WF_PSE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_SHFT; + pg_num = (pse_buf_ctrl & WF_PSE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_MASK) >> + WF_PSE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_SHFT; + + DBGLOG(HAL, INFO, + "Packet Buffer Control(0x%08x): 0x%08x,Page Size=%d, Page Offset=%d, Total page=%d\n", + WF_PSE_TOP_PBUF_CTRL_ADDR, + pse_buf_ctrl, pg_sz, + ((pse_buf_ctrl & WF_PSE_TOP_PBUF_CTRL_PBUF_OFFSET_MASK) >> + WF_PSE_TOP_PBUF_CTRL_PBUF_OFFSET_SHFT), + pg_num); + + /* Page Flow Control */ + fpg_cnt = (freepg_cnt & WF_PSE_TOP_FREEPG_CNT_FREEPG_CNT_MASK) >> + WF_PSE_TOP_FREEPG_CNT_FREEPG_CNT_SHFT; + + ffa_cnt = (freepg_cnt & WF_PSE_TOP_FREEPG_CNT_FFA_CNT_MASK) >> + WF_PSE_TOP_FREEPG_CNT_FFA_CNT_SHFT; + + + DBGLOG(HAL, INFO, + "Free page counter(0x%08x): 0x%08x,The toal page number of free=0x%03x,The free page numbers of free for all=0x%03x\n", + WF_PSE_TOP_FREEPG_CNT_ADDR, freepg_cnt, + fpg_cnt, ffa_cnt); + + /* PLE tail / head FID */ + fpg_head = (freepg_head_tail & + WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_MASK) >> + WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_SHFT; + fpg_tail = (freepg_head_tail & + WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_MASK) >> + WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_SHFT; + + DBGLOG(HAL, INFO, + "Free page tail/head(0x%08x): 0x%08x,The tail/head page of free page list=0x%03x/0x%03x\n", + WF_PSE_TOP_FREEPG_HEAD_TAIL_ADDR, freepg_head_tail, + fpg_tail, fpg_head); + + /*Each Group page status */ + group_cnt = sizeof(pse_group) / sizeof(struct pse_group_info); + for (i = 0; i < group_cnt; i++) { + group = &pse_group[i]; + HAL_MCR_RD(prAdapter, group->quota_addr, &group_quota); + HAL_MCR_RD(prAdapter, group->pg_info_addr, &group_info); + + DBGLOG(HAL, INFO, + "Reserved page counter of %s group(0x%08x):0x%08x,status(0x%08x):0x%08x\n", + group->name, group->quota_addr, group_quota, + group->pg_info_addr, group_info); + min_q = (group_quota & + WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MIN_QUOTA_MASK) >> + WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MIN_QUOTA_SHFT; + max_q = (group_quota & + WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MAX_QUOTA_MASK) >> + WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MAX_QUOTA_SHFT; + DBGLOG(HAL, TRACE, + "\tThe max/min quota pages of %s group=0x%03x/0x%03x\n", + group->name, max_q, min_q); + rsv_pg = + (group_info & WF_PSE_TOP_HIF0_PG_INFO_HIF0_RSV_CNT_MASK) >> + WF_PSE_TOP_HIF0_PG_INFO_HIF0_RSV_CNT_SHFT; + used_pg = + (group_info & WF_PSE_TOP_HIF0_PG_INFO_HIF0_SRC_CNT_MASK) >> + WF_PSE_TOP_HIF0_PG_INFO_HIF0_SRC_CNT_SHFT; + DBGLOG(HAL, TRACE, + "\tThe used/reserved pages of %s group=0x%03x/0x%03x\n", + group->name, used_pg, rsv_pg); + } + + /* Queue Empty Status */ + DBGLOG(HAL, INFO, + "QUEUE_EMPTY(0x%08x):0x%08x,QUEUE_EMPTY_MASK(0x%08x):0x%08x\n", + WF_PSE_TOP_QUEUE_EMPTY_ADDR, pse_stat, + WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR, pse_stat_mask); + + DBGLOG(HAL, TRACE, "\t\tCPU Q0/1/2/3 empty=%d/%d/%d/%d\n", + (pse_stat & WF_PSE_TOP_QUEUE_EMPTY_CPU_Q0_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_CPU_Q0_EMPTY_SHFT, + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_CPU_Q1_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_CPU_Q1_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_CPU_Q2_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_CPU_Q2_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_CPU_Q3_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_CPU_Q3_EMPTY_SHFT)); + str = "\t\tHIF Q0/1/2/3/4/5/6/7/8/9/10/11"; + DBGLOG(HAL, TRACE, + "%s empty=%d/%d/%d/%d/%d/%d/%d/%d/%d/%d/%d/%d\n", str, + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_0_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_0_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_1_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_1_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_2_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_2_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_3_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_3_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_4_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_4_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_5_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_5_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_6_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_6_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_7_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_7_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_8_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_8_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_9_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_9_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_10_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_10_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_HIF_11_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_HIF_11_EMPTY_SHFT)); + DBGLOG(HAL, TRACE, "\t\tLMAC TX Q empty=%d\n", + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_LMAC_TX_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_LMAC_TX_QUEUE_EMPTY_SHFT)); + DBGLOG(HAL, TRACE, "\t\tMDP TX Q/RX Q empty=%d/%d\n", + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_MDP_TX_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_MDP_TX_QUEUE_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_MDP_RX_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_MDP_RX_QUEUE_EMPTY_SHFT)); + DBGLOG(HAL, TRACE, "\t\tSEC TX Q/RX Q empty=%d/%d\n", + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_SEC_TX_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_SEC_TX_QUEUE_EMPTY_SHFT), + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_SEC_RX_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_SEC_RX_QUEUE_EMPTY_SHFT)); + DBGLOG(HAL, TRACE, "\t\tSFD PARK Q empty=%d\n", + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_SFD_PARK_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_SFD_PARK_QUEUE_EMPTY_SHFT)); + DBGLOG(HAL, TRACE, "\t\tMDP TXIOC Q/RXIOC Q empty=%d/%d\n", + ((pse_stat & + WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC_QUEUE_EMPTY_SHFT), + ((pse_stat & + WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC_QUEUE_EMPTY_SHFT)); + DBGLOG(HAL, TRACE, "\t\tMDP TX1 Q empty=%d\n", + ((pse_stat & + WF_PSE_TOP_QUEUE_EMPTY_MDP_TX1_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_MDP_TX1_QUEUE_EMPTY_SHFT)); + DBGLOG(HAL, TRACE, "\t\tSEC TX1 Q empty=%d\n", + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_SEC_TX1_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_SEC_TX1_QUEUE_EMPTY_SHFT)); + DBGLOG(HAL, TRACE, "\t\tMDP TXIOC1 Q/RXIOC1 Q empty=%d/%d\n", + ((pse_stat & + WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC1_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC1_QUEUE_EMPTY_SHFT), + ((pse_stat & + WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC1_QUEUE_EMPTY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC1_QUEUE_EMPTY_SHFT)); + DBGLOG(HAL, TRACE, "\t\tRLS Q empty=%d\n", + ((pse_stat & WF_PSE_TOP_QUEUE_EMPTY_RLS_Q_EMTPY_MASK) >> + WF_PSE_TOP_QUEUE_EMPTY_RLS_Q_EMTPY_SHFT)); + + /* Nonempty Queue Status */ + DBGLOG(HAL, INFO, "Nonempty Q info:"); + for (i = 0; i < 31; i++) { + if (((pse_stat & (0x1 << i)) >> i) == 0) { + uint32_t hfid, tfid, pktcnt, fl_que_ctrl[3] = {0}; + + if (pse_queue_empty_info[i].QueueName != NULL) { + DBGLOG(HAL, INFO, "\t%s: ", + pse_queue_empty_info[i].QueueName); + fl_que_ctrl[0] |= + WF_PSE_TOP_FL_QUE_CTRL_0_EXECUTE_MASK; + fl_que_ctrl[0] |= + (pse_queue_empty_info[i].Portid + << WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_SHFT); + fl_que_ctrl[0] |= + (pse_queue_empty_info[i].Queueid + << WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_SHFT); + } else + continue; + + fl_que_ctrl[0] |= (0x1 << 31); + HAL_MCR_WR(prAdapter, WF_PSE_TOP_FL_QUE_CTRL_0_ADDR, + fl_que_ctrl[0]); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_FL_QUE_CTRL_2_ADDR, + &fl_que_ctrl[1]); + HAL_MCR_RD(prAdapter, WF_PSE_TOP_FL_QUE_CTRL_3_ADDR, + &fl_que_ctrl[2]); + hfid = (fl_que_ctrl[1] & + WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_MASK) >> + WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_SHFT; + tfid = (fl_que_ctrl[1] & + WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_MASK) >> + WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_SHFT; + pktcnt = + (fl_que_ctrl[2] & + WF_PSE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_MASK) >> + WF_PSE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_SHFT; + DBGLOG(HAL, INFO, + "tail/head fid = 0x%03x/0x%03x, pkt cnt = 0x%03x\n", + tfid, hfid, pktcnt); + } + } +} + +static void DumpPPDebugCr(struct ADAPTER *prAdapter) +{ + uint32_t ReadRegValue[4]; + uint32_t u4Value[4] = {0}; + + /* 0x820CC0F0 : PP DBG_CTRL */ + ReadRegValue[0] = 0x820CC0F0; + HAL_MCR_RD(prAdapter, ReadRegValue[0], &u4Value[0]); + + /* 0x820CC0F8 : PP DBG_CS0 */ + ReadRegValue[1] = 0x820CC0F8; + HAL_MCR_RD(prAdapter, ReadRegValue[1], &u4Value[1]); + + /* 0x820CC0FC : PP DBG_CS1 */ + ReadRegValue[2] = 0x820CC0FC; + HAL_MCR_RD(prAdapter, ReadRegValue[2], &u4Value[2]); + + /* 0x820CC100 : PP DBG_CS2 */ + ReadRegValue[3] = 0x820CC100; + HAL_MCR_RD(prAdapter, ReadRegValue[3], &u4Value[3]); + + DBGLOG(HAL, INFO, + "PP[0x%08x]=0x%08x,[0x%08x]=0x%08x,[0x%08x]=0x%08x,[0x%08x]=0x%08x,", + ReadRegValue[0], u4Value[0], + ReadRegValue[1], u4Value[1], + ReadRegValue[2], u4Value[2], + ReadRegValue[3], u4Value[3]); +} + +void show_wfdma_interrupt_info( + IN struct ADAPTER *prAdapter, + IN enum _ENUM_WFDMA_TYPE_T enum_wfdma_type) +{ + uint32_t idx; + uint32_t u4hostBaseCrAddr; + uint32_t u4DmaCfgCrAddr = 0; + uint32_t u4DmaCfgCrAddrByWFDMA[CONNAC2X_WFDMA_COUNT]; + uint32_t u4RegValue = 0; + uint32_t u4RegValueByWFDMA[CONNAC2X_WFDMA_COUNT] = {0}; + + /* Dump Interrupt Status info */ + if (enum_wfdma_type == WFDMA_TYPE_HOST) { + /* Dump Global Status CR only in WFMDA HOST*/ + u4hostBaseCrAddr = CONNAC2X_HOST_EXT_CONN_HIF_WRAP; + + u4DmaCfgCrAddr = CONNAC2X_WPDMA_EXT_INT_STA(u4hostBaseCrAddr); + HAL_MCR_RD(prAdapter, u4DmaCfgCrAddr, &u4RegValue); + } + + /* Dump PDMA Status CR */ + for (idx = 0; idx < CONNAC2X_WFDMA_COUNT; idx++) { + + if (enum_wfdma_type == WFDMA_TYPE_HOST) + u4hostBaseCrAddr = idx ? + CONNAC2X_HOST_WPDMA_1_BASE : + CONNAC2X_HOST_WPDMA_0_BASE; + else + u4hostBaseCrAddr = idx ? + CONNAC2X_MCU_WPDMA_1_BASE : + CONNAC2X_MCU_WPDMA_0_BASE; + + u4DmaCfgCrAddrByWFDMA[idx] = + CONNAC2X_WPDMA_INT_STA(u4hostBaseCrAddr); + + HAL_MCR_RD(prAdapter, + u4DmaCfgCrAddrByWFDMA[idx], &u4RegValueByWFDMA[idx]); + } + + DBGLOG(INIT, INFO, + "G_INT_S(0x%08x):0x%08x,W_%d(0x%08x):0x%08x, W_%d(0x%08x):0x%08x\n", + u4DmaCfgCrAddr, u4RegValue, + 0, u4DmaCfgCrAddrByWFDMA[0], u4RegValueByWFDMA[0], + 1, u4DmaCfgCrAddrByWFDMA[1], u4RegValueByWFDMA[1]); + + /* Dump Interrupt Enable Info */ + if (enum_wfdma_type == WFDMA_TYPE_HOST) { + + /* Dump Global Enable CR */ + u4hostBaseCrAddr = CONNAC2X_HOST_EXT_CONN_HIF_WRAP; + + u4DmaCfgCrAddr = CONNAC2X_WPDMA_EXT_INT_MASK(u4hostBaseCrAddr); + + HAL_MCR_RD(prAdapter, u4DmaCfgCrAddr, &u4RegValue); + } + + /* Dump PDMA Enable CR */ + for (idx = 0; idx < CONNAC2X_WFDMA_COUNT; idx++) { + + if (enum_wfdma_type == WFDMA_TYPE_HOST) + u4hostBaseCrAddr = idx ? + CONNAC2X_HOST_WPDMA_1_BASE : + CONNAC2X_HOST_WPDMA_0_BASE; + else + u4hostBaseCrAddr = idx ? + CONNAC2X_MCU_WPDMA_1_BASE : + CONNAC2X_MCU_WPDMA_0_BASE; + + u4DmaCfgCrAddrByWFDMA[idx] = + CONNAC2X_WPDMA_INT_MASK(u4hostBaseCrAddr); + + HAL_MCR_RD(prAdapter, + u4DmaCfgCrAddrByWFDMA[idx], &u4RegValueByWFDMA[idx]); + } + + DBGLOG(INIT, INFO, + "G_INT_E(0x%08x):0x%08x,W_%d(0x%08x):0x%08x, W_%d(0x%08x):0x%08x\n", + u4DmaCfgCrAddr, u4RegValue, + 0, u4DmaCfgCrAddrByWFDMA[0], u4RegValueByWFDMA[0], + 1, u4DmaCfgCrAddrByWFDMA[1], u4RegValueByWFDMA[1]); +} + +void show_wfdma_glo_info( + IN struct ADAPTER *prAdapter, + IN enum _ENUM_WFDMA_TYPE_T enum_wfdma_type) +{ + uint32_t idx; + uint32_t u4hostBaseCrAddr; + uint32_t u4DmaCfgCrAddr = 0; + union WPDMA_GLO_CFG_STRUCT GloCfgValue; + + for (idx = 0; idx < CONNAC2X_WFDMA_COUNT; idx++) { + + if (enum_wfdma_type == WFDMA_TYPE_HOST) + u4hostBaseCrAddr = idx ? + CONNAC2X_HOST_WPDMA_1_BASE : + CONNAC2X_HOST_WPDMA_0_BASE; + else + u4hostBaseCrAddr = idx ? + CONNAC2X_MCU_WPDMA_1_BASE : + CONNAC2X_MCU_WPDMA_0_BASE; + + u4DmaCfgCrAddr = CONNAC2X_WPDMA_GLO_CFG(u4hostBaseCrAddr); + + HAL_MCR_RD(prAdapter, u4DmaCfgCrAddr, &GloCfgValue.word); + + DBGLOG(INIT, INFO, + "WFDMA_%d GLO(0x%08x):0x%08x,EN T/R=(%d/%d), Busy T/R=(%d/%d)\n", + idx, u4DmaCfgCrAddr, GloCfgValue.word, + GloCfgValue.field_conn2x.tx_dma_en, + GloCfgValue.field_conn2x.rx_dma_en, + GloCfgValue.field_conn2x.tx_dma_busy, + GloCfgValue.field_conn2x.rx_dma_busy); + } + +} + +void show_wfdma_ring_info( + IN struct ADAPTER *prAdapter, + IN enum _ENUM_WFDMA_TYPE_T enum_wfdma_type) +{ + + uint32_t idx; + uint32_t group_cnt; + uint32_t u4DmaCfgCrAddr = 0; + struct wfdma_group_info *group; + uint32_t u4_hw_desc_base_value = 0; + uint32_t u4_hw_cnt_value = 0; + uint32_t u4_hw_cidx_value = 0; + uint32_t u4_hw_didx_value = 0; + uint32_t queue_cnt; + + /* Dump All TX Ring Info */ + DBGLOG(HAL, INFO, "----------- TX Ring Config -----------\n"); + DBGLOG(HAL, INFO, "%4s %16s %8s %10s %6s %6s %6s %6s\n", + "Idx", "Attr", "Reg", "Base", "Cnt", "CIDX", "DIDX", "QCnt"); + + /* Dump TX Ring */ + if (enum_wfdma_type == WFDMA_TYPE_HOST) + group_cnt = sizeof(wfmda_host_tx_group) / + sizeof(struct wfdma_group_info); + else + group_cnt = sizeof(wfmda_wm_tx_group) / + sizeof(struct wfdma_group_info); + + for (idx = 0; idx < group_cnt; idx++) { + if (enum_wfdma_type == WFDMA_TYPE_HOST) + group = &wfmda_host_tx_group[idx]; + else + group = &wfmda_wm_tx_group[idx]; + + u4DmaCfgCrAddr = group->hw_desc_base; + + HAL_MCR_RD(prAdapter, u4DmaCfgCrAddr, &u4_hw_desc_base_value); + HAL_MCR_RD(prAdapter, u4DmaCfgCrAddr+0x04, &u4_hw_cnt_value); + HAL_MCR_RD(prAdapter, u4DmaCfgCrAddr+0x08, &u4_hw_cidx_value); + HAL_MCR_RD(prAdapter, u4DmaCfgCrAddr+0x0c, &u4_hw_didx_value); + + queue_cnt = (u4_hw_cidx_value >= u4_hw_didx_value) ? + (u4_hw_cidx_value - u4_hw_didx_value) : + (u4_hw_cidx_value - u4_hw_didx_value + u4_hw_cnt_value); + + DBGLOG(HAL, INFO, "%4d %16s %8x %10x %6x %6x %6x %6x\n", + idx, + group->name, + u4DmaCfgCrAddr, u4_hw_desc_base_value, + u4_hw_cnt_value, u4_hw_cidx_value, + u4_hw_didx_value, queue_cnt); + + } + + /* Dump All RX Ring Info */ + DBGLOG(HAL, INFO, "----------- RX Ring Config -----------\n"); + DBGLOG(HAL, INFO, "%4s %16s %8s %10s %6s %6s %6s %6s\n", + "Idx", "Attr", "Reg", "Base", "Cnt", "CIDX", "DIDX", "QCnt"); + + /* Dump RX Ring */ + if (enum_wfdma_type == WFDMA_TYPE_HOST) + group_cnt = sizeof(wfmda_host_rx_group) / + sizeof(struct wfdma_group_info); + else + group_cnt = sizeof(wfmda_wm_rx_group) / + sizeof(struct wfdma_group_info); + + for (idx = 0; idx < group_cnt; idx++) { + if (enum_wfdma_type == WFDMA_TYPE_HOST) + group = &wfmda_host_rx_group[idx]; + else + group = &wfmda_wm_rx_group[idx]; + + u4DmaCfgCrAddr = group->hw_desc_base; + + HAL_MCR_RD(prAdapter, u4DmaCfgCrAddr, &u4_hw_desc_base_value); + HAL_MCR_RD(prAdapter, u4DmaCfgCrAddr+0x04, &u4_hw_cnt_value); + HAL_MCR_RD(prAdapter, u4DmaCfgCrAddr+0x08, &u4_hw_cidx_value); + HAL_MCR_RD(prAdapter, u4DmaCfgCrAddr+0x0c, &u4_hw_didx_value); + + queue_cnt = (u4_hw_didx_value > u4_hw_cidx_value) ? + (u4_hw_didx_value - u4_hw_cidx_value - 1) : + (u4_hw_didx_value - u4_hw_cidx_value + + u4_hw_cnt_value - 1); + + DBGLOG(HAL, INFO, "%4d %16s %8x %10x %6x %6x %6x %6x\n", + idx, + group->name, + u4DmaCfgCrAddr, u4_hw_desc_base_value, + u4_hw_cnt_value, u4_hw_cidx_value, + u4_hw_didx_value, queue_cnt); + } + +} + +static void dump_wfdma_dbg_value( + IN struct ADAPTER *prAdapter, + IN enum _ENUM_WFDMA_TYPE_T enum_wfdma_type, + IN uint32_t wfdma_idx) +{ +#define BUF_SIZE 1024 + + uint32_t pdma_base_cr; + uint32_t set_debug_flag_value; + char *buf; + uint32_t pos = 0; + uint32_t set_debug_cr, get_debug_cr, get_debug_value = 0; + + if (enum_wfdma_type == WFDMA_TYPE_HOST) { + if (wfdma_idx == 0) + pdma_base_cr = CONNAC2X_HOST_WPDMA_0_BASE; + else + pdma_base_cr = CONNAC2X_HOST_WPDMA_1_BASE; + } else { + if (wfdma_idx == 0) + pdma_base_cr = CONNAC2X_MCU_WPDMA_0_BASE; + else + pdma_base_cr = CONNAC2X_MCU_WPDMA_1_BASE; + } + + buf = (char *) kalMemAlloc(BUF_SIZE, VIR_MEM_TYPE); + if (!buf) { + DBGLOG(HAL, ERROR, "Mem allocation failed.\n"); + return; + } + set_debug_cr = pdma_base_cr + 0x124; + get_debug_cr = pdma_base_cr + 0x128; + kalMemZero(buf, BUF_SIZE); + pos += kalSnprintf(buf + pos, 50, + "set_debug_cr:0x%08x get_debug_cr:0x%08x; ", + set_debug_cr, get_debug_cr); + for (set_debug_flag_value = 0x100; set_debug_flag_value <= 0x112; + set_debug_flag_value++) { + HAL_MCR_WR(prAdapter, set_debug_cr, set_debug_flag_value); + HAL_MCR_RD(prAdapter, get_debug_cr, &get_debug_value); + pos += kalSnprintf(buf + pos, 40, "Set:0x%03x, result=0x%08x%s", + set_debug_flag_value, + get_debug_value, + set_debug_flag_value == 0x112 ? "\n" : "; "); + } + DBGLOG(HAL, INFO, "%s", buf); + kalMemFree(buf, VIR_MEM_TYPE, BUF_SIZE); +} + +void show_wfdma_dbg_flag_log( + IN struct ADAPTER *prAdapter, + IN enum _ENUM_WFDMA_TYPE_T enum_wfdma_type) +{ + dump_wfdma_dbg_value(prAdapter, enum_wfdma_type, 0); + dump_wfdma_dbg_value(prAdapter, enum_wfdma_type, 1); +} + +void show_wfdma_dbg_log( + IN struct ADAPTER *prAdapter, + IN enum _ENUM_WFDMA_TYPE_T enum_wfdma_type) +{ + /* Dump Host WFMDA info */ + DBGLOG(HAL, TRACE, "WFMDA Configuration:\n"); + show_wfdma_interrupt_info(prAdapter, enum_wfdma_type); + show_wfdma_glo_info(prAdapter, enum_wfdma_type); + show_wfdma_ring_info(prAdapter, enum_wfdma_type); +} + +void soc3_0_show_wfdma_info(IN struct ADAPTER *prAdapter) +{ + /* dump WFDMA info by host or WM*/ + show_wfdma_dbg_log(prAdapter, WFDMA_TYPE_HOST); + show_wfdma_dbg_log(prAdapter, WFDMA_TYPE_WM); + + /* dump debug flag CR by host or WM*/ + show_wfdma_dbg_flag_log(prAdapter, WFDMA_TYPE_HOST); + show_wfdma_dbg_flag_log(prAdapter, WFDMA_TYPE_WM); + + DumpPPDebugCr(prAdapter); +} + +void soc3_0_show_wfdma_info_by_type(IN struct ADAPTER *prAdapter, + IN bool bShowWFDMA_type) +{ + if (bShowWFDMA_type) { + show_wfdma_dbg_log(prAdapter, WFDMA_TYPE_WM); + show_wfdma_dbg_flag_log(prAdapter, WFDMA_TYPE_WM); + } else { + show_wfdma_dbg_log(prAdapter, WFDMA_TYPE_HOST); + show_wfdma_dbg_flag_log(prAdapter, WFDMA_TYPE_HOST); + } +} + +void soc3_0_show_dmashdl_info(IN struct ADAPTER *prAdapter) +{ + uint32_t value = 0; + uint8_t idx; + uint32_t rsv_cnt = 0; + uint32_t src_cnt = 0; + uint32_t total_src_cnt = 0; + uint32_t total_rsv_cnt = 0; + uint32_t ffa_cnt = 0; + uint32_t free_pg_cnt = 0; + uint32_t ple_rpg_hif; + uint32_t ple_upg_hif; + uint8_t is_mismatch = FALSE; + + DBGLOG(HAL, INFO, "DMASHDL info:\n"); + + mt6885HalDmashdlGetRefill(prAdapter); + mt6885HalDmashdlGetPktMaxPage(prAdapter); + + HAL_MCR_RD(prAdapter, WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR, &value); + DBGLOG(HAL, INFO, "DMASHDL ERR FLAG CTRL(0x%08x): 0x%08x\n", + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR, value); + + for (idx = 0; idx < ENUM_MT6885_DMASHDL_GROUP_2; idx++) { + DBGLOG(HAL, INFO, "Group %d info:\n", idx); + mt6885HalDmashdlGetGroupControl(prAdapter, idx); + rsv_cnt = mt6885HalDmashdlGetRsvCount(prAdapter, idx); + src_cnt = mt6885HalDmashdlGetSrcCount(prAdapter, idx); + mt6885HalDmashdlGetPKTCount(prAdapter, idx); + total_src_cnt += src_cnt; + total_rsv_cnt += rsv_cnt; + } + HAL_MCR_RD(prAdapter, WF_HIF_DMASHDL_TOP_STATUS_RD_ADDR, &value); + ffa_cnt = (value & WF_HIF_DMASHDL_TOP_STATUS_RD_FFA_CNT_MASK) >> + WF_HIF_DMASHDL_TOP_STATUS_RD_FFA_CNT_SHFT; + free_pg_cnt = (value & + WF_HIF_DMASHDL_TOP_STATUS_RD_FREE_PAGE_CNT_MASK) >> + WF_HIF_DMASHDL_TOP_STATUS_RD_FREE_PAGE_CNT_SHFT; + DBGLOG(HAL, INFO, "\tDMASHDL Status_RD(0x%08x): 0x%08x\n", + WF_HIF_DMASHDL_TOP_STATUS_RD_ADDR, value); + DBGLOG(HAL, INFO, "\tfree page cnt = 0x%03x, ffa cnt = 0x%03x\n", + free_pg_cnt, ffa_cnt); + + DBGLOG(HAL, INFO, "\nDMASHDL Counter Check:\n"); + HAL_MCR_RD(prAdapter, WF_PLE_TOP_HIF_PG_INFO_ADDR, &value); + ple_rpg_hif = (value & WF_PLE_TOP_HIF_PG_INFO_HIF_RSV_CNT_MASK) >> + WF_PLE_TOP_HIF_PG_INFO_HIF_RSV_CNT_SHFT; + ple_upg_hif = (value & WF_PLE_TOP_HIF_PG_INFO_HIF_SRC_CNT_MASK) >> + WF_PLE_TOP_HIF_PG_INFO_HIF_SRC_CNT_SHFT; + DBGLOG(HAL, INFO, + "\tPLE:The used/reserved pages of PLE HIF group=0x%03x/0x%03x\n", + ple_upg_hif, ple_rpg_hif); + DBGLOG(HAL, INFO, + "\tDMASHDL:The total used pages of group0~14=0x%03x\n", + total_src_cnt); + + if (ple_upg_hif != total_src_cnt) { + DBGLOG(HAL, INFO, + "\tPLE used pages & total used pages mismatch!\n"); + is_mismatch = TRUE; + } + + DBGLOG(HAL, INFO, + "\tThe total reserved pages of group0~14=0x%03x\n", + total_rsv_cnt); + DBGLOG(HAL, INFO, + "\tThe total ffa pages of group0~14=0x%03x\n", + ffa_cnt); + DBGLOG(HAL, INFO, + "\tThe total free pages of group0~14=0x%03x\n", + free_pg_cnt); + + if (free_pg_cnt != total_rsv_cnt + ffa_cnt) { + DBGLOG(HAL, INFO, + "\tmismatch(total_rsv_cnt + ffa_cnt in DMASHDL)\n"); + is_mismatch = TRUE; + } + + if (free_pg_cnt != ple_rpg_hif) { + DBGLOG(HAL, INFO, "\tmismatch(reserved pages in PLE)\n"); + is_mismatch = TRUE; + } + + + if (!is_mismatch) + DBGLOG(HAL, INFO, "DMASHDL: no counter mismatch\n"); +} + +void soc3_0_dump_mac_info(IN struct ADAPTER *prAdapter) +{ +#define BUF_SIZE 1024 +#define CR_COUNT 12 +#define LOOP_COUNT 30 + + uint32_t i = 0, j = 0, pos = 0; + uint32_t value = 0; + uint32_t cr_band0[] = { + 0x820ED020, + 0x820E4120, + 0x820E4128, + 0x820E22F0, + 0x820E22F4, + 0x820E22F8, + 0x820E22FC, + 0x820E3190, + 0x820C0220, + 0x820C0114, + 0x820C0154, + 0x820E0024 + }; + uint32_t cr_band1[] = { + 0x820FD020, + 0x820F4120, + 0x820F4128, + 0x820F22F0, + 0x820F22F4, + 0x820F22F8, + 0x820F22FC, + 0x820F3190, + 0x820C0220, + 0x820C0114, + 0x820C0154, + 0x820F0024 + }; + + char *buf = (char *) kalMemAlloc(BUF_SIZE, VIR_MEM_TYPE); + + DBGLOG(HAL, INFO, "Dump for band0\n"); + HAL_MCR_WR(prAdapter, 0x7C006100, 0x1F); + HAL_MCR_WR(prAdapter, 0x7C006104, 0x07070707); + HAL_MCR_WR(prAdapter, 0x7C006108, 0x0A0A0909); + HAL_MCR_RD(prAdapter, 0x820D0000, &value); + DBGLOG(HAL, INFO, "Dump CR: 0x820D0000 = 0x%08x\n", value); + HAL_MCR_RD(prAdapter, 0x820E3080, &value); + DBGLOG(HAL, INFO, "Dump CR: 0x820E3080 = 0x%08x\n", value); + HAL_MCR_RD(prAdapter, 0x820C0028, &value); + DBGLOG(HAL, INFO, "Dump CR: 0x820C0028 = 0x%08x\n", value); + HAL_MCR_RD(prAdapter, 0x820C8028, &value); + DBGLOG(HAL, INFO, "Dump CR: 0x820C8028 = 0x%08x\n", value); + HAL_MCR_RD(prAdapter, 0x820C8030, &value); + DBGLOG(HAL, INFO, "Dump CR: 0x820C8030 = 0x%08x\n", value); + /* Band 0 TXV_C and TXV_P */ + for (i = 0x820E412C; i < 0x820E4160; i += 4) { + HAL_MCR_RD(prAdapter, i, &value); + DBGLOG(HAL, INFO, "Dump CR: 0x%08x = 0x%08x\n", i, value); + kalMdelay(1); + } + HAL_MCR_RD(prAdapter, 0x820E206C, &value); + DBGLOG(HAL, INFO, "Dump CR: 0x820E206C = 0x%08x\n", value); + + if (buf) { + kalMemZero(buf, BUF_SIZE); + for (i = 0; i < LOOP_COUNT; i++) { + for (j = 0; j < CR_COUNT; j++) { + HAL_MCR_RD(prAdapter, cr_band0[j], &value); + pos += kalSnprintf(buf + pos, 25, + "0x%08x = 0x%08x%s", cr_band0[j], value, + j == CR_COUNT - 1 ? ";" : ","); + } + DBGLOG(HAL, INFO, "Dump CR: %s\n", buf); + pos = 0; + kalMdelay(1); + } + } + + DBGLOG(HAL, INFO, "Dump for band1\n"); + HAL_MCR_WR(prAdapter, 0x7C006400, 0x1F); + HAL_MCR_WR(prAdapter, 0x7C006404, 0x07070707); + HAL_MCR_WR(prAdapter, 0x7C006408, 0x0A0A0909); + HAL_MCR_RD(prAdapter, 0x820D0000, &value); + DBGLOG(HAL, INFO, "Dump CR: 0x820D0000 = 0x%08x\n", value); + HAL_MCR_RD(prAdapter, 0x820F3080, &value); + DBGLOG(HAL, INFO, "Dump CR: 0x820F3080 = 0x%08x\n", value); + HAL_MCR_RD(prAdapter, 0x820C0028, &value); + DBGLOG(HAL, INFO, "Dump CR: 0x820C0028 = 0x%08x\n", value); + HAL_MCR_RD(prAdapter, 0x820C8028, &value); + DBGLOG(HAL, INFO, "Dump CR: 0x820C8028 = 0x%08x\n", value); + HAL_MCR_RD(prAdapter, 0x820C8030, &value); + DBGLOG(HAL, INFO, "Dump CR: 0x820C8030 = 0x%08x\n", value); + /* Band 0 TXV_C and TXV_P */ + for (i = 0x820F412C; i < 0x820F4160; i += 4) { + HAL_MCR_RD(prAdapter, i, &value); + DBGLOG(HAL, INFO, "Dump CR: 0x%08x = 0x%08x\n", i, value); + kalMdelay(1); + } + HAL_MCR_RD(prAdapter, 0x820F206C, &value); + DBGLOG(HAL, INFO, "Dump CR: 0x820F206C = 0x%08x\n", value); + + if (buf) { + kalMemZero(buf, BUF_SIZE); + for (i = 0; i < LOOP_COUNT; i++) { + for (j = 0; j < CR_COUNT; j++) { + HAL_MCR_RD(prAdapter, cr_band1[j], &value); + pos += kalSnprintf(buf + pos, 25, + "0x%08x = 0x%08x%s", cr_band1[j], value, + j == CR_COUNT - 1 ? ";" : ","); + } + DBGLOG(HAL, INFO, "Dump CR: %s\n", buf); + pos = 0; + kalMdelay(1); + } + } + + if (buf) + kalMemFree(buf, VIR_MEM_TYPE, BUF_SIZE); +} + +#if WFSYS_SUPPORT_BUS_HANG_READ_FROM_DRIVER_BASE +void show_wfdma_interrupt_info_without_adapter( + IN enum _ENUM_WFDMA_TYPE_T enum_wfdma_type) +{ + uint32_t idx; + uint32_t u4hostBaseCrAddr = 0; + uint32_t u4DmaCfgCrAddr = 0; + uint32_t u4DmaCfgCrAddrByWFDMA[CONNAC2X_WFDMA_COUNT]; + uint32_t u4RegValue = 0; + uint32_t u4RegValueByWFDMA[CONNAC2X_WFDMA_COUNT] = {0}; + + /* Dump Interrupt Status info */ + if (enum_wfdma_type == WFDMA_TYPE_HOST) { + /* Dump Global Status CR only in WFMDA HOST*/ + u4hostBaseCrAddr = CONNAC2X_HOST_EXT_CONN_HIF_WRAP_DRIVER_BASE; + + u4DmaCfgCrAddr = CONNAC2X_WPDMA_EXT_INT_STA(u4hostBaseCrAddr); + wf_ioremap_read(u4DmaCfgCrAddr, &u4RegValue); + } + + /* Dump PDMA Status CR */ + for (idx = 0; idx < CONNAC2X_WFDMA_COUNT; idx++) { + + if (enum_wfdma_type == WFDMA_TYPE_HOST) + u4hostBaseCrAddr = idx ? + CONNAC2X_HOST_WPDMA_1_DRIVER_BASE : + CONNAC2X_HOST_WPDMA_0_DRIVER_BASE; + else + u4hostBaseCrAddr = idx ? + CONNAC2X_MCU_WPDMA_1_DRIVER_BASE : + CONNAC2X_MCU_WPDMA_0_DRIVER_BASE; + + u4DmaCfgCrAddrByWFDMA[idx] = + CONNAC2X_WPDMA_INT_STA(u4hostBaseCrAddr); + + wf_ioremap_read(u4DmaCfgCrAddrByWFDMA[idx], + &u4RegValueByWFDMA[idx]); + } + + DBGLOG(INIT, INFO, + "G_INT_S(0x%08x):0x%08x,W_%d(0x%08x):0x%08x, W_%d(0x%08x):0x%08x\n", + u4DmaCfgCrAddr, u4RegValue, + 0, u4DmaCfgCrAddrByWFDMA[0], u4RegValueByWFDMA[0], + 1, u4DmaCfgCrAddrByWFDMA[1], u4RegValueByWFDMA[1]); + + /* Dump Interrupt Enable Info */ + if (enum_wfdma_type == WFDMA_TYPE_HOST) { + + /* Dump Global Enable CR */ + u4hostBaseCrAddr = CONNAC2X_HOST_EXT_CONN_HIF_WRAP_DRIVER_BASE; + + u4DmaCfgCrAddr = CONNAC2X_WPDMA_EXT_INT_MASK(u4hostBaseCrAddr); + + wf_ioremap_read(u4DmaCfgCrAddr, &u4RegValue); + } + + /* Dump PDMA Enable CR */ + for (idx = 0; idx < CONNAC2X_WFDMA_COUNT; idx++) { + + if (enum_wfdma_type == WFDMA_TYPE_HOST) + u4hostBaseCrAddr = idx ? + CONNAC2X_HOST_WPDMA_1_DRIVER_BASE : + CONNAC2X_HOST_WPDMA_0_DRIVER_BASE; + else + u4hostBaseCrAddr = idx ? + CONNAC2X_MCU_WPDMA_1_DRIVER_BASE : + CONNAC2X_MCU_WPDMA_0_DRIVER_BASE; + + u4DmaCfgCrAddrByWFDMA[idx] = + CONNAC2X_WPDMA_INT_MASK(u4hostBaseCrAddr); + + wf_ioremap_read(u4DmaCfgCrAddrByWFDMA[idx], + &u4RegValueByWFDMA[idx]); + } + + DBGLOG(INIT, INFO, + "G_INT_E(0x%08x):0x%08x,W_%d(0x%08x):0x%08x, W_%d(0x%08x):0x%08x\n", + u4DmaCfgCrAddr, u4RegValue, + 0, u4DmaCfgCrAddrByWFDMA[0], u4RegValueByWFDMA[0], + 1, u4DmaCfgCrAddrByWFDMA[1], u4RegValueByWFDMA[1]); +} + +void show_wfdma_glo_info_without_adapter( + IN enum _ENUM_WFDMA_TYPE_T enum_wfdma_type) +{ + uint32_t idx; + uint32_t u4hostBaseCrAddr = 0; + uint32_t u4DmaCfgCrAddr = 0; + union WPDMA_GLO_CFG_STRUCT GloCfgValue; + + for (idx = 0; idx < CONNAC2X_WFDMA_COUNT; idx++) { + + if (enum_wfdma_type == WFDMA_TYPE_HOST) + u4hostBaseCrAddr = idx ? + CONNAC2X_HOST_WPDMA_1_DRIVER_BASE : + CONNAC2X_HOST_WPDMA_0_DRIVER_BASE; + else + u4hostBaseCrAddr = idx ? + CONNAC2X_MCU_WPDMA_1_DRIVER_BASE : + CONNAC2X_MCU_WPDMA_0_DRIVER_BASE; + + u4DmaCfgCrAddr = CONNAC2X_WPDMA_GLO_CFG(u4hostBaseCrAddr); + + wf_ioremap_read(u4DmaCfgCrAddr, &GloCfgValue.word); + + DBGLOG(INIT, INFO, + "WFDMA_%d GLO(0x%08x):0x%08x,EN T/R=(%d/%d), Busy T/R=(%d/%d)\n", + idx, u4DmaCfgCrAddr, GloCfgValue.word, + GloCfgValue.field_conn2x.tx_dma_en, + GloCfgValue.field_conn2x.rx_dma_en, + GloCfgValue.field_conn2x.tx_dma_busy, + GloCfgValue.field_conn2x.rx_dma_busy); + } + +} + +void show_wfdma_ring_info_without_adapter( + IN enum _ENUM_WFDMA_TYPE_T enum_wfdma_type) +{ + + uint32_t idx = 0; + uint32_t group_cnt = 0; + uint32_t u4DmaCfgCrAddr; + struct wfdma_group_info *group; + uint32_t u4_hw_desc_base_value = 0; + uint32_t u4_hw_cnt_value = 0; + uint32_t u4_hw_cidx_value = 0; + uint32_t u4_hw_didx_value = 0; + uint32_t queue_cnt; + + /* Dump All TX Ring Info */ + DBGLOG(HAL, TRACE, "----------- TX Ring Config -----------\n"); + DBGLOG(HAL, TRACE, "%4s %16s %8s %10s %6s %6s %6s %6s\n", + "Idx", "Attr", "Reg", "Base", "Cnt", "CIDX", "DIDX", "QCnt"); + + /* Dump TX Ring */ + if (enum_wfdma_type == WFDMA_TYPE_HOST) + group_cnt = sizeof(wfmda_host_tx_group_driver_base) / + sizeof(struct wfdma_group_info); + else + group_cnt = sizeof(wfmda_wm_tx_group_driver_base) / + sizeof(struct wfdma_group_info); + + for (idx = 0; idx < group_cnt; idx++) { + if (enum_wfdma_type == WFDMA_TYPE_HOST) + group = &wfmda_host_tx_group_driver_base[idx]; + else + group = &wfmda_wm_tx_group_driver_base[idx]; + + u4DmaCfgCrAddr = group->hw_desc_base; + + wf_ioremap_read(u4DmaCfgCrAddr, &u4_hw_desc_base_value); + wf_ioremap_read(u4DmaCfgCrAddr+0x04, &u4_hw_cnt_value); + wf_ioremap_read(u4DmaCfgCrAddr+0x08, &u4_hw_cidx_value); + wf_ioremap_read(u4DmaCfgCrAddr+0x0c, &u4_hw_didx_value); + + queue_cnt = (u4_hw_cidx_value >= u4_hw_didx_value) ? + (u4_hw_cidx_value - u4_hw_didx_value) : + (u4_hw_cidx_value - u4_hw_didx_value + u4_hw_cnt_value); + + DBGLOG(HAL, INFO, "%4d %16s %8x %10x %6x %6x %6x %6x\n", + idx, + group->name, + u4DmaCfgCrAddr, u4_hw_desc_base_value, + u4_hw_cnt_value, u4_hw_cidx_value, + u4_hw_didx_value, queue_cnt); + + } + + /* Dump All RX Ring Info */ + DBGLOG(HAL, TRACE, "----------- RX Ring Config -----------\n"); + DBGLOG(HAL, TRACE, "%4s %16s %8s %10s %6s %6s %6s %6s\n", + "Idx", "Attr", "Reg", "Base", "Cnt", "CIDX", "DIDX", "QCnt"); + + /* Dump RX Ring */ + if (enum_wfdma_type == WFDMA_TYPE_HOST) + group_cnt = sizeof(wfmda_host_rx_group_driver_base) / + sizeof(struct wfdma_group_info); + else + group_cnt = sizeof(wfmda_wm_rx_group_driver_base) / + sizeof(struct wfdma_group_info); + + for (idx = 0; idx < group_cnt; idx++) { + if (enum_wfdma_type == WFDMA_TYPE_HOST) + group = &wfmda_host_rx_group_driver_base[idx]; + else + group = &wfmda_wm_rx_group_driver_base[idx]; + + u4DmaCfgCrAddr = group->hw_desc_base; + + wf_ioremap_read(u4DmaCfgCrAddr, &u4_hw_desc_base_value); + wf_ioremap_read(u4DmaCfgCrAddr+0x04, &u4_hw_cnt_value); + wf_ioremap_read(u4DmaCfgCrAddr+0x08, &u4_hw_cidx_value); + wf_ioremap_read(u4DmaCfgCrAddr+0x0c, &u4_hw_didx_value); + + queue_cnt = (u4_hw_didx_value > u4_hw_cidx_value) ? + (u4_hw_didx_value - u4_hw_cidx_value - 1) : + (u4_hw_didx_value - u4_hw_cidx_value + + u4_hw_cnt_value - 1); + + DBGLOG(HAL, INFO, "%4d %16s %8x %10x %6x %6x %6x %6x\n", + idx, + group->name, + u4DmaCfgCrAddr, u4_hw_desc_base_value, + u4_hw_cnt_value, u4_hw_cidx_value, + u4_hw_didx_value, queue_cnt); + } + +} + +static void dump_dbg_value_without_adapter( + IN uint32_t pdma_base_cr, + IN uint32_t set_value, + IN uint32_t isMandatoryDump) +{ + uint32_t set_debug_cr = 0; + uint32_t get_debug_cr = 0; + uint32_t get_debug_value = 0; + + set_debug_cr = pdma_base_cr + 0x124; + get_debug_cr = pdma_base_cr + 0x128; + + wf_ioremap_write(set_debug_cr, set_value); + wf_ioremap_read(get_debug_cr, &get_debug_value); + + if (isMandatoryDump == 1) { + DBGLOG(INIT, INFO, "set(0x%08x):0x%08x, get(0x%08x):0x%08x,", + set_debug_cr, set_value, + get_debug_cr, get_debug_value); + } else { + DBGLOG(INIT, TRACE, "set(0x%08x):0x%08x, get(0x%08x):0x%08x,", + set_debug_cr, set_value, + get_debug_cr, get_debug_value); + } +} + +static void dump_wfdma_dbg_value_without_adapter( + IN enum _ENUM_WFDMA_TYPE_T enum_wfdma_type, + IN uint32_t wfdma_idx, + IN uint32_t isMandatoryDump) +{ + uint32_t pdma_base_cr = 0; + uint32_t set_debug_flag_value = 0; + + if (enum_wfdma_type == WFDMA_TYPE_HOST) { + if (wfdma_idx == 0) + pdma_base_cr = CONNAC2X_HOST_WPDMA_0_DRIVER_BASE; + else + pdma_base_cr = CONNAC2X_HOST_WPDMA_1_DRIVER_BASE; + } else{ + if (wfdma_idx == 0) + pdma_base_cr = CONNAC2X_MCU_WPDMA_0_DRIVER_BASE; + else + pdma_base_cr = CONNAC2X_MCU_WPDMA_1_DRIVER_BASE; + } + + set_debug_flag_value = 0x100; + dump_dbg_value_without_adapter(pdma_base_cr, + set_debug_flag_value, isMandatoryDump); + + set_debug_flag_value = 0x101; + dump_dbg_value_without_adapter(pdma_base_cr, + set_debug_flag_value, isMandatoryDump); + + set_debug_flag_value = 0x102; + dump_dbg_value_without_adapter(pdma_base_cr, + set_debug_flag_value, isMandatoryDump); + + set_debug_flag_value = 0x103; + dump_dbg_value_without_adapter(pdma_base_cr, + set_debug_flag_value, isMandatoryDump); + + set_debug_flag_value = 0x104; + dump_dbg_value_without_adapter(pdma_base_cr, + set_debug_flag_value, isMandatoryDump); + + set_debug_flag_value = 0x105; + dump_dbg_value_without_adapter(pdma_base_cr, + set_debug_flag_value, isMandatoryDump); + + set_debug_flag_value = 0x107; + dump_dbg_value_without_adapter(pdma_base_cr, + set_debug_flag_value, isMandatoryDump); + + set_debug_flag_value = 0x10A; + dump_dbg_value_without_adapter(pdma_base_cr, + set_debug_flag_value, isMandatoryDump); + + set_debug_flag_value = 0x10D; + dump_dbg_value_without_adapter(pdma_base_cr, + set_debug_flag_value, isMandatoryDump); + + set_debug_flag_value = 0x10E; + dump_dbg_value_without_adapter(pdma_base_cr, + set_debug_flag_value, isMandatoryDump); + + set_debug_flag_value = 0x10F; + dump_dbg_value_without_adapter(pdma_base_cr, + set_debug_flag_value, isMandatoryDump); + + set_debug_flag_value = 0x110; + dump_dbg_value_without_adapter(pdma_base_cr, + set_debug_flag_value, isMandatoryDump); + + set_debug_flag_value = 0x111; + dump_dbg_value_without_adapter(pdma_base_cr, + set_debug_flag_value, isMandatoryDump); + + set_debug_flag_value = 0x112; + dump_dbg_value_without_adapter(pdma_base_cr, + set_debug_flag_value, isMandatoryDump); + +} + +static void show_wfdma_dbg_flag_log_without_adapter( + IN enum _ENUM_WFDMA_TYPE_T enum_wfdma_type, + IN uint32_t isMandatoryDump) +{ + dump_wfdma_dbg_value_without_adapter( + enum_wfdma_type, 0, isMandatoryDump); + dump_wfdma_dbg_value_without_adapter( + enum_wfdma_type, 1, isMandatoryDump); +} + +static void show_wfdma_dbg_log_without_adapter( + IN enum _ENUM_WFDMA_TYPE_T enum_wfdma_type) +{ + /* Dump Host WFMDA info */ + DBGLOG(HAL, TRACE, "WFMDA Configuration:\n"); + show_wfdma_interrupt_info_without_adapter(enum_wfdma_type); + show_wfdma_glo_info_without_adapter(enum_wfdma_type); + show_wfdma_ring_info_without_adapter(enum_wfdma_type); +} + +/* bIsHostDMA = 1 (how Host PDMA) else (WM PDMA) */ +void soc3_0_show_wfdma_info_by_type_without_adapter( + IN bool bShowWFDMA_type) +{ + if (bShowWFDMA_type) { + show_wfdma_dbg_log_without_adapter(WFDMA_TYPE_WM); + show_wfdma_dbg_flag_log_without_adapter(WFDMA_TYPE_WM, TRUE); + } else { + show_wfdma_dbg_log_without_adapter(WFDMA_TYPE_HOST); + show_wfdma_dbg_flag_log_without_adapter(WFDMA_TYPE_HOST, TRUE); + } +} + +#endif /* WFSYS_SUPPORT_BUS_HANG_READ_FROM_DRIVER_BASE */ + +#endif /* SOC3_0 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/soc3_0/hal_dmashdl_soc3_0.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/soc3_0/hal_dmashdl_soc3_0.c new file mode 100644 index 0000000000000..fa94b6d19e836 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/soc3_0/hal_dmashdl_soc3_0.c @@ -0,0 +1,480 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +/*! \file hal_dmashdl_mt6885.c +* \brief DMASHDL HAL API for MT6885 +* +* This file contains all routines which are exported + from MediaTek 802.11 Wireless LAN driver stack to GLUE Layer. +*/ + +#ifdef SOC3_0 +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + +/******************************************************************************* +* C O M P I L E 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 "soc3_0.h" +#include "coda/soc3_0/wf_hif_dmashdl_top.h" +#include "hal_dmashdl_soc3_0.h" +#include "dma_sch.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +struct MT6885_DMASHDL_CFG rMT6885DmashdlCfg = { + .fgSlotArbiterEn = MT6885_DMASHDL_SLOT_ARBITER_EN, + + .u2PktPleMaxPage = MT6885_DMASHDL_PKT_PLE_MAX_PAGE, + + .u2PktPseMaxPage = MT6885_DMASHDL_PKT_PSE_MAX_PAGE, + + .afgRefillEn = { + MT6885_DMASHDL_GROUP_0_REFILL_EN, + MT6885_DMASHDL_GROUP_1_REFILL_EN, + MT6885_DMASHDL_GROUP_2_REFILL_EN, + MT6885_DMASHDL_GROUP_3_REFILL_EN, + MT6885_DMASHDL_GROUP_4_REFILL_EN, + MT6885_DMASHDL_GROUP_5_REFILL_EN, + MT6885_DMASHDL_GROUP_6_REFILL_EN, + MT6885_DMASHDL_GROUP_7_REFILL_EN, + MT6885_DMASHDL_GROUP_8_REFILL_EN, + MT6885_DMASHDL_GROUP_9_REFILL_EN, + MT6885_DMASHDL_GROUP_10_REFILL_EN, + MT6885_DMASHDL_GROUP_11_REFILL_EN, + MT6885_DMASHDL_GROUP_12_REFILL_EN, + MT6885_DMASHDL_GROUP_13_REFILL_EN, + MT6885_DMASHDL_GROUP_14_REFILL_EN, + MT6885_DMASHDL_GROUP_15_REFILL_EN, + }, + + .au2MaxQuota = { + MT6885_DMASHDL_GROUP_0_MAX_QUOTA, + MT6885_DMASHDL_GROUP_1_MAX_QUOTA, + MT6885_DMASHDL_GROUP_2_MAX_QUOTA, + MT6885_DMASHDL_GROUP_3_MAX_QUOTA, + MT6885_DMASHDL_GROUP_4_MAX_QUOTA, + MT6885_DMASHDL_GROUP_5_MAX_QUOTA, + MT6885_DMASHDL_GROUP_6_MAX_QUOTA, + MT6885_DMASHDL_GROUP_7_MAX_QUOTA, + MT6885_DMASHDL_GROUP_8_MAX_QUOTA, + MT6885_DMASHDL_GROUP_9_MAX_QUOTA, + MT6885_DMASHDL_GROUP_10_MAX_QUOTA, + MT6885_DMASHDL_GROUP_11_MAX_QUOTA, + MT6885_DMASHDL_GROUP_12_MAX_QUOTA, + MT6885_DMASHDL_GROUP_13_MAX_QUOTA, + MT6885_DMASHDL_GROUP_14_MAX_QUOTA, + MT6885_DMASHDL_GROUP_15_MAX_QUOTA, + }, + + .au2MinQuota = { + MT6885_DMASHDL_GROUP_0_MIN_QUOTA, + MT6885_DMASHDL_GROUP_1_MIN_QUOTA, + MT6885_DMASHDL_GROUP_2_MIN_QUOTA, + MT6885_DMASHDL_GROUP_3_MIN_QUOTA, + MT6885_DMASHDL_GROUP_4_MIN_QUOTA, + MT6885_DMASHDL_GROUP_5_MIN_QUOTA, + MT6885_DMASHDL_GROUP_6_MIN_QUOTA, + MT6885_DMASHDL_GROUP_7_MIN_QUOTA, + MT6885_DMASHDL_GROUP_8_MIN_QUOTA, + MT6885_DMASHDL_GROUP_9_MIN_QUOTA, + MT6885_DMASHDL_GROUP_10_MIN_QUOTA, + MT6885_DMASHDL_GROUP_11_MIN_QUOTA, + MT6885_DMASHDL_GROUP_12_MIN_QUOTA, + MT6885_DMASHDL_GROUP_13_MIN_QUOTA, + MT6885_DMASHDL_GROUP_14_MIN_QUOTA, + MT6885_DMASHDL_GROUP_15_MIN_QUOTA, + }, + + .aucQueue2Group = { + MT6885_DMASHDL_QUEUE_0_TO_GROUP, + MT6885_DMASHDL_QUEUE_1_TO_GROUP, + MT6885_DMASHDL_QUEUE_2_TO_GROUP, + MT6885_DMASHDL_QUEUE_3_TO_GROUP, + MT6885_DMASHDL_QUEUE_4_TO_GROUP, + MT6885_DMASHDL_QUEUE_5_TO_GROUP, + MT6885_DMASHDL_QUEUE_6_TO_GROUP, + MT6885_DMASHDL_QUEUE_7_TO_GROUP, + MT6885_DMASHDL_QUEUE_8_TO_GROUP, + MT6885_DMASHDL_QUEUE_9_TO_GROUP, + MT6885_DMASHDL_QUEUE_10_TO_GROUP, + MT6885_DMASHDL_QUEUE_11_TO_GROUP, + MT6885_DMASHDL_QUEUE_12_TO_GROUP, + MT6885_DMASHDL_QUEUE_13_TO_GROUP, + MT6885_DMASHDL_QUEUE_14_TO_GROUP, + MT6885_DMASHDL_QUEUE_15_TO_GROUP, + MT6885_DMASHDL_QUEUE_16_TO_GROUP, + MT6885_DMASHDL_QUEUE_17_TO_GROUP, + MT6885_DMASHDL_QUEUE_18_TO_GROUP, + MT6885_DMASHDL_QUEUE_19_TO_GROUP, + MT6885_DMASHDL_QUEUE_20_TO_GROUP, + MT6885_DMASHDL_QUEUE_21_TO_GROUP, + MT6885_DMASHDL_QUEUE_22_TO_GROUP, + MT6885_DMASHDL_QUEUE_23_TO_GROUP, + MT6885_DMASHDL_QUEUE_24_TO_GROUP, + MT6885_DMASHDL_QUEUE_25_TO_GROUP, + MT6885_DMASHDL_QUEUE_26_TO_GROUP, + MT6885_DMASHDL_QUEUE_27_TO_GROUP, + MT6885_DMASHDL_QUEUE_28_TO_GROUP, + MT6885_DMASHDL_QUEUE_29_TO_GROUP, + MT6885_DMASHDL_QUEUE_30_TO_GROUP, + MT6885_DMASHDL_QUEUE_31_TO_GROUP, + }, + + .aucPriority2Group = { + MT6885_DMASHDL_PRIORITY0_GROUP, + MT6885_DMASHDL_PRIORITY1_GROUP, + MT6885_DMASHDL_PRIORITY2_GROUP, + MT6885_DMASHDL_PRIORITY3_GROUP, + MT6885_DMASHDL_PRIORITY4_GROUP, + MT6885_DMASHDL_PRIORITY5_GROUP, + MT6885_DMASHDL_PRIORITY6_GROUP, + MT6885_DMASHDL_PRIORITY7_GROUP, + MT6885_DMASHDL_PRIORITY8_GROUP, + MT6885_DMASHDL_PRIORITY9_GROUP, + MT6885_DMASHDL_PRIORITY10_GROUP, + MT6885_DMASHDL_PRIORITY11_GROUP, + MT6885_DMASHDL_PRIORITY12_GROUP, + MT6885_DMASHDL_PRIORITY13_GROUP, + MT6885_DMASHDL_PRIORITY14_GROUP, + MT6885_DMASHDL_PRIORITY15_GROUP, + }, +}; + +void mt6885HalDmashdlSetPlePktMaxPage(struct ADAPTER *prAdapter, + uint16_t u2MaxPage) +{ + uint32_t u4Val = 0; + + HAL_MCR_RD(prAdapter, WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR, &u4Val); + + u4Val &= ~WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PLE_PACKET_MAX_SIZE_MASK; + u4Val |= (u2MaxPage << + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PLE_PACKET_MAX_SIZE_SHFT) & + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PLE_PACKET_MAX_SIZE_MASK; + + HAL_MCR_WR(prAdapter, WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR, u4Val); +} + +void mt6885HalDmashdlSetPsePktMaxPage(struct ADAPTER *prAdapter, + uint16_t u2MaxPage) +{ + uint32_t u4Val = 0; + + HAL_MCR_RD(prAdapter, WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR, &u4Val); + + u4Val &= ~WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PSE_PACKET_MAX_SIZE_MASK; + u4Val |= (u2MaxPage << + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PSE_PACKET_MAX_SIZE_SHFT) & + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PSE_PACKET_MAX_SIZE_MASK; + + HAL_MCR_WR(prAdapter, WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR, u4Val); +} + +void mt6885HalDmashdlGetPktMaxPage(struct ADAPTER *prAdapter) +{ + uint32_t u4Val = 0; + uint32_t ple_pkt_max_sz; + uint32_t pse_pkt_max_sz; + + HAL_MCR_RD(prAdapter, WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR, &u4Val); + + ple_pkt_max_sz = (u4Val & + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PLE_PACKET_MAX_SIZE_MASK)>> + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PLE_PACKET_MAX_SIZE_SHFT; + pse_pkt_max_sz = (u4Val & + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PSE_PACKET_MAX_SIZE_MASK)>> + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PSE_PACKET_MAX_SIZE_SHFT; + + DBGLOG(HAL, INFO, "DMASHDL PLE_PACKET_MAX_SIZE (0x%08x): 0x%08x\n", + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR, u4Val); + DBGLOG(HAL, INFO, "PLE/PSE packet max size=0x%03x/0x%03x\n", + ple_pkt_max_sz, pse_pkt_max_sz); + +} +void mt6885HalDmashdlSetRefill(struct ADAPTER *prAdapter, uint8_t ucGroup, + u_int8_t fgEnable) +{ + uint32_t u4Mask; + uint32_t u4Val = 0; + + if (ucGroup >= ENUM_MT6885_DMASHDL_GROUP_NUM) + ASSERT(0); + + u4Mask = WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP0_REFILL_DISABLE_MASK + << ucGroup; + + HAL_MCR_RD(prAdapter, WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR, &u4Val); + + if (fgEnable) + u4Val &= ~u4Mask; + else + u4Val |= u4Mask; + + HAL_MCR_WR(prAdapter, WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR, u4Val); +} + +void mt6885HalDmashdlGetRefill(struct ADAPTER *prAdapter) +{ + uint32_t u4Val = 0; + + HAL_MCR_RD(prAdapter, WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR, &u4Val); + DBGLOG(HAL, INFO, "DMASHDL ReFill Control (0x%08x): 0x%08x\n", + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR, u4Val); +} + +void mt6885HalDmashdlSetMaxQuota(struct ADAPTER *prAdapter, uint8_t ucGroup, + uint16_t u2MaxQuota) +{ + uint32_t u4Addr; + uint32_t u4Val = 0; + + if (ucGroup >= ENUM_MT6885_DMASHDL_GROUP_NUM) + ASSERT(0); + + u4Addr = WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_ADDR + (ucGroup << 2); + + HAL_MCR_RD(prAdapter, u4Addr, &u4Val); + + u4Val &= ~WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_GROUP0_MAX_QUOTA_MASK; + u4Val |= (u2MaxQuota << + WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_GROUP0_MAX_QUOTA_SHFT) & + WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_GROUP0_MAX_QUOTA_MASK; + + HAL_MCR_WR(prAdapter, u4Addr, u4Val); +} + +void mt6885HalDmashdlSetMinQuota(struct ADAPTER *prAdapter, uint8_t ucGroup, + uint16_t u2MinQuota) +{ + uint32_t u4Addr; + uint32_t u4Val = 0; + + if (ucGroup >= ENUM_MT6885_DMASHDL_GROUP_NUM) + ASSERT(0); + + u4Addr = WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_ADDR + (ucGroup << 2); + + HAL_MCR_RD(prAdapter, u4Addr, &u4Val); + + u4Val &= ~WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_GROUP0_MIN_QUOTA_MASK; + u4Val |= (u2MinQuota << + WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_GROUP0_MIN_QUOTA_SHFT) & + WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_GROUP0_MIN_QUOTA_MASK; + + HAL_MCR_WR(prAdapter, u4Addr, u4Val); +} + +void mt6885HalDmashdlGetGroupControl(struct ADAPTER *prAdapter, uint8_t ucGroup) +{ + uint32_t u4Addr; + uint32_t u4Val = 0; + uint32_t max_quota; + uint32_t min_quota; + + u4Addr = WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_ADDR + (ucGroup << 2); + + HAL_MCR_RD(prAdapter, u4Addr, &u4Val); + + max_quota = GET_DMASHDL_MAX_QUOTA_NUM(u4Val); + min_quota = GET_DMASHDL_MIN_QUOTA_NUM(u4Val); + DBGLOG(HAL, INFO, "\tDMASHDL Group%d control(0x%08x): 0x%08x\n", + ucGroup, u4Addr, u4Val); + DBGLOG(HAL, INFO, "\tmax/min quota = 0x%03x/ 0x%03x\n", + max_quota, min_quota); + +} +void mt6885HalDmashdlSetQueueMapping(struct ADAPTER *prAdapter, uint8_t ucQueue, + uint8_t ucGroup) +{ + uint32_t u4Addr, u4Mask, u4Shft; + uint32_t u4Val = 0; + + if (ucQueue >= 32) + ASSERT(0); + + if (ucGroup >= ENUM_MT6885_DMASHDL_GROUP_NUM) + ASSERT(0); + + u4Addr = WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR + + ((ucQueue >> 3) << 2); + u4Mask = WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE0_MAPPING_MASK << + ((ucQueue % 8) << 2); + u4Shft = (ucQueue % 8) << 2; + + HAL_MCR_RD(prAdapter, u4Addr, &u4Val); + + u4Val &= ~u4Mask; + u4Val |= (ucGroup << u4Shft) & u4Mask; + + HAL_MCR_WR(prAdapter, u4Addr, u4Val); +} + +void mt6885HalDmashdlSetSlotArbiter(struct ADAPTER *prAdapter, + u_int8_t fgEnable) +{ + uint32_t u4Val = 0; + + HAL_MCR_RD(prAdapter, WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR, &u4Val); + + if (fgEnable) + u4Val |= + WF_HIF_DMASHDL_TOP_PAGE_SETTING_GROUP_SEQUENCE_ORDER_TYPE_MASK; + else + u4Val &= + ~WF_HIF_DMASHDL_TOP_PAGE_SETTING_GROUP_SEQUENCE_ORDER_TYPE_MASK; + + HAL_MCR_WR(prAdapter, WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR, u4Val); +} + +void mt6885HalDmashdlSetUserDefinedPriority(struct ADAPTER *prAdapter, + uint8_t ucPriority, uint8_t ucGroup) +{ + uint32_t u4Addr, u4Mask, u4Shft; + uint32_t u4Val = 0; + + ASSERT(ucPriority < 16); + ASSERT(ucGroup < ENUM_MT6885_DMASHDL_GROUP_NUM); + + u4Addr = WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_ADDR + + ((ucPriority >> 3) << 2); + u4Mask = WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY0_GROUP_MASK + << ((ucPriority % 8) << 2); + u4Shft = (ucPriority % 8) << 2; + + HAL_MCR_RD(prAdapter, u4Addr, &u4Val); + + u4Val &= ~u4Mask; + u4Val |= (ucGroup << u4Shft) & u4Mask; + + HAL_MCR_WR(prAdapter, u4Addr, u4Val); +} + +uint32_t mt6885HalDmashdlGetRsvCount(struct ADAPTER *prAdapter, uint8_t ucGroup) +{ + uint32_t u4Addr; + uint32_t u4Val = 0; + uint32_t rsv_cnt = 0; + + u4Addr = WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_ADDR + (ucGroup << 2); + + HAL_MCR_RD(prAdapter, u4Addr, &u4Val); + + rsv_cnt = (u4Val & WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_RSV_CNT_MASK) >> + WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_RSV_CNT_SHFT; + + DBGLOG(HAL, INFO, "\tDMASHDL Status_RD_GP%d(0x%08x): 0x%08x\n", + ucGroup, u4Addr, u4Val); + DBGLOG(HAL, TRACE, "\trsv_cnt = 0x%03x\n", rsv_cnt); + return rsv_cnt; +} + +uint32_t mt6885HalDmashdlGetSrcCount(struct ADAPTER *prAdapter, uint8_t ucGroup) +{ + uint32_t u4Addr; + uint32_t u4Val = 0; + uint32_t src_cnt = 0; + + u4Addr = WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_ADDR + (ucGroup << 2); + + HAL_MCR_RD(prAdapter, u4Addr, &u4Val); + + src_cnt = (u4Val & WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_SRC_CNT_MASK) >> + WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_SRC_CNT_SHFT; + + DBGLOG(HAL, TRACE, "\tsrc_cnt = 0x%03x\n", src_cnt); + return src_cnt; +} + +void mt6885HalDmashdlGetPKTCount(struct ADAPTER *prAdapter, uint8_t ucGroup) +{ + uint32_t u4Addr; + uint32_t u4Val = 0; + uint32_t pktin_cnt = 0; + uint32_t ask_cnt = 0; + + if ((ucGroup & 0x1) == 0) + u4Addr = WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_ADDR + + (ucGroup << 1); + else + u4Addr = WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_ADDR + + ((ucGroup-1) << 1); + + HAL_MCR_RD(prAdapter, u4Addr, &u4Val); + DBGLOG(HAL, INFO, "\tDMASHDL RD_group_pkt_cnt_%d(0x%08x): 0x%08x\n", + ucGroup / 2, u4Addr, u4Val); + if ((ucGroup & 0x1) == 0) { + pktin_cnt = GET_EVEN_GROUP_PKT_IN_CNT(u4Val); + ask_cnt = GET_EVEN_GROUP_ASK_CNT(u4Val); + } else { + pktin_cnt = GET_ODD_GROUP_PKT_IN_CNT(u4Val); + ask_cnt = GET_ODD_GROUP_ASK_CNT(u4Val); + } + DBGLOG(HAL, INFO, "\tpktin_cnt = 0x%02x, ask_cnt = 0x%02x", + pktin_cnt, ask_cnt); +} + +void mt6885DmashdlInit(struct ADAPTER *prAdapter) +{ + uint32_t idx; + + mt6885HalDmashdlSetPlePktMaxPage(prAdapter, + rMT6885DmashdlCfg.u2PktPleMaxPage); + + for (idx = 0; idx < ENUM_MT6885_DMASHDL_GROUP_NUM; idx++) { + mt6885HalDmashdlSetRefill(prAdapter, idx, + rMT6885DmashdlCfg.afgRefillEn[idx]); + + mt6885HalDmashdlSetMaxQuota(prAdapter, idx, + rMT6885DmashdlCfg.au2MaxQuota[idx]); + + mt6885HalDmashdlSetMinQuota(prAdapter, idx, + rMT6885DmashdlCfg.au2MinQuota[idx]); + } + + for (idx = 0; idx < 32; idx++) + mt6885HalDmashdlSetQueueMapping(prAdapter, idx, + rMT6885DmashdlCfg.aucQueue2Group[idx]); + + for (idx = 0; idx < 16; idx++) + mt6885HalDmashdlSetUserDefinedPriority(prAdapter, idx, + rMT6885DmashdlCfg.aucPriority2Group[idx]); + + mt6885HalDmashdlSetSlotArbiter(prAdapter, + rMT6885DmashdlCfg.fgSlotArbiterEn); +} + +#endif /* defined(_HIF_PCIE) || defined(_HIF_AXI) */ +#endif /* SOC3_0*/ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/soc3_0/soc3_0.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/soc3_0/soc3_0.c new file mode 100644 index 0000000000000..d25a945f1a5a3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/chips/soc3_0/soc3_0.c @@ -0,0 +1,4882 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file soc3_0.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. +*/ + +#ifdef SOC3_0 + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#define CFG_SUPPORT_VCODE_VDFS 1 + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "coda/soc3_0/wf_wfdma_host_dma0.h" +#include "coda/soc3_0/wf_wfdma_host_dma1.h" + +#if (CFG_SUPPORT_CONNINFRA == 1) +#include "coda/soc3_0/conn_infra_cfg.h" +#endif + +#include "precomp.h" +#include "gl_rst.h" +#include "soc3_0.h" +#include "hal_dmashdl_soc3_0.h" +#include +#include +#include +#include +#if (CFG_SUPPORT_VCODE_VDFS == 1) +#include +#endif /*#ifndef CFG_BUILD_X86_PLATFORM*/ + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH +#include "fw_log_wifi.h" +#endif /* CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH */ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define CONN_MCU_CONFG_BASE 0x88000000 +#define CONN_MCU_CONFG_COM_REG0_ADDR (CONN_MCU_CONFG_BASE + 0x200) + +#define PATCH_SEMAPHORE_COMM_REG 0 +#define PATCH_SEMAPHORE_COMM_REG_PATCH_DONE 1 /* bit0 is for patch. */ + +#define SW_WORKAROUND_FOR_WFDMA_ISSUE_HWITS00009838 1 + +#define SOC3_0_FILE_NAME_TOTAL 8 +#define SOC3_0_FILE_NAME_MAX 64 +/* this is workaround for AXE, do not sync back to trunk*/ + +#if (CFG_SUPPORT_CONNINFRA == 1) +static struct sub_drv_ops_cb g_conninfra_wf_cb; +#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_POWER_ON_DOWNLOAD_EMI_ROM_PATCH == 1) +static uint8_t *soc3_0_apucFwName[] = { + (uint8_t *) CFG_FW_FILENAME "_MT", + NULL +}; + +static uint8_t *soc3_0_apucCr4FwName[] = { + (uint8_t *) CFG_CR4_FW_FILENAME "_MT", + NULL +}; +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +#if CFG_MTK_ANDROID_EMI + phys_addr_t gConEmiPhyBase; + unsigned long long gConEmiSize; + +#if (CFG_SUPPORT_PRE_ON_PHY_ACTION == 1) +u_int8_t *gEmiCalResult; +u_int32_t gEmiCalSize; +u_int32_t gEmiCalOffset; +bool gEmiCalUseEmiData; +struct wireless_dev *grWdev; +#endif /* (CFG_SUPPORT_PRE_ON_PHY_ACTION == 1) */ + +#endif + +#if (CFG_SUPPORT_VCODE_VDFS == 1) +static struct pm_qos_request wifi_req; +#endif + +bool gCoAntVFE28En = FALSE; + +uint8_t *apucsoc3_0FwName[] = { + (uint8_t *) CFG_FW_FILENAME "_soc3_0", + NULL +}; + +struct ECO_INFO soc3_0_eco_table[] = { + /* HW version, ROM version, Factory version */ + {0x00, 0x00, 0xA, 0x1}, /* E1 */ + {0x00, 0x00, 0x0, 0x0} /* End of table */ +}; + +#if defined(_HIF_PCIE) +struct PCIE_CHIP_CR_MAPPING soc3_0_bus2chip_cr_mapping[] = { + /* chip addr, bus addr, range */ + {0x54000000, 0x02000, 0x1000}, /* WFDMA PCIE0 MCU DMA0 */ + {0x55000000, 0x03000, 0x1000}, /* WFDMA PCIE0 MCU DMA1 */ + {0x56000000, 0x04000, 0x1000}, /* WFDMA reserved */ + {0x57000000, 0x05000, 0x1000}, /* WFDMA MCU wrap CR */ + {0x58000000, 0x06000, 0x1000}, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */ + {0x59000000, 0x07000, 0x1000}, /* WFDMA PCIE1 MCU DMA1 */ + {0x820c0000, 0x08000, 0x4000}, /* WF_UMAC_TOP (PLE) */ + {0x820c8000, 0x0c000, 0x2000}, /* WF_UMAC_TOP (PSE) */ + {0x820cc000, 0x0e000, 0x2000}, /* WF_UMAC_TOP (PP) */ + {0x820e0000, 0x20000, 0x0400}, /* WF_LMAC_TOP BN0 (WF_CFG) */ + {0x820e1000, 0x20400, 0x0200}, /* WF_LMAC_TOP BN0 (WF_TRB) */ + {0x820e2000, 0x20800, 0x0400}, /* WF_LMAC_TOP BN0 (WF_AGG) */ + {0x820e3000, 0x20c00, 0x0400}, /* WF_LMAC_TOP BN0 (WF_ARB) */ + {0x820e4000, 0x21000, 0x0400}, /* WF_LMAC_TOP BN0 (WF_TMAC) */ + {0x820e5000, 0x21400, 0x0800}, /* WF_LMAC_TOP BN0 (WF_RMAC) */ + {0x820ce000, 0x21c00, 0x0200}, /* WF_LMAC_TOP (WF_SEC) */ + {0x820e7000, 0x21e00, 0x0200}, /* WF_LMAC_TOP BN0 (WF_DMA) */ + {0x820cf000, 0x22000, 0x1000}, /* WF_LMAC_TOP (WF_PF) */ + {0x820e9000, 0x23400, 0x0200}, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */ + {0x820ea000, 0x24000, 0x0200}, /* WF_LMAC_TOP BN0 (WF_ETBF) */ + {0x820eb000, 0x24200, 0x0400}, /* WF_LMAC_TOP BN0 (WF_LPON) */ + {0x820ec000, 0x24600, 0x0200}, /* WF_LMAC_TOP BN0 (WF_INT) */ + {0x820ed000, 0x24800, 0x0800}, /* WF_LMAC_TOP BN0 (WF_MIB) */ + {0x820ca000, 0x26000, 0x2000}, /* WF_LMAC_TOP BN0 (WF_MUCOP) */ + {0x820d0000, 0x30000, 0x10000}, /* WF_LMAC_TOP (WF_WTBLON) */ + {0x40000000, 0x70000, 0x10000}, /* WF_UMAC_SYSRAM */ + {0x00400000, 0x80000, 0x10000}, /* WF_MCU_SYSRAM */ + {0x00410000, 0x90000, 0x10000}, /* WF_MCU_SYSRAM (configure register) */ + {0x820f0000, 0xa0000, 0x0400}, /* WF_LMAC_TOP BN1 (WF_CFG) */ + {0x820f1000, 0xa0600, 0x0200}, /* WF_LMAC_TOP BN1 (WF_TRB) */ + {0x820f2000, 0xa0800, 0x0400}, /* WF_LMAC_TOP BN1 (WF_AGG) */ + {0x820f3000, 0xa0c00, 0x0400}, /* WF_LMAC_TOP BN1 (WF_ARB) */ + {0x820f4000, 0xa1000, 0x0400}, /* WF_LMAC_TOP BN1 (WF_TMAC) */ + {0x820f5000, 0xa1400, 0x0800}, /* WF_LMAC_TOP BN1 (WF_RMAC) */ + {0x820f7000, 0xa1e00, 0x0200}, /* WF_LMAC_TOP BN1 (WF_DMA) */ + {0x820f9000, 0xa3400, 0x0200}, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */ + {0x820fa000, 0xa4000, 0x0200}, /* WF_LMAC_TOP BN1 (WF_ETBF) */ + {0x820fb000, 0xa4200, 0x0400}, /* WF_LMAC_TOP BN1 (WF_LPON) */ + {0x820fc000, 0xa4600, 0x0200}, /* WF_LMAC_TOP BN1 (WF_INT) */ + {0x820fd000, 0xa4800, 0x0800}, /* WF_LMAC_TOP BN1 (WF_MIB) */ + {0x820c4000, 0xa8000, 0x4000}, /* WF_LMAC_TOP (WF_UWTBL) */ + {0x820b0000, 0xae000, 0x1000}, /* [APB2] WFSYS_ON */ + {0x80020000, 0xb0000, 0x10000}, /* WF_TOP_MISC_OFF */ + {0x81020000, 0xc0000, 0x10000}, /* WF_TOP_MISC_ON */ + {0x7c500000, 0x50000, 0x10000}, /* CONN_INFRA, dyn mem map */ + {0x7c020000, 0xd0000, 0x10000}, /* CONN_INFRA, wfdma */ + {0x7c060000, 0xe0000, 0x10000}, /* CONN_INFRA, conn_host_csr_top */ + {0x7c000000, 0xf0000, 0x10000}, /* CONN_INFRA */ + {0x0, 0x0, 0x0} /* End */ +}; +#elif defined(_HIF_AXI) +struct PCIE_CHIP_CR_MAPPING soc3_0_bus2chip_cr_mapping[] = { + /* chip addr, bus addr, range */ + {0x54000000, 0x402000, 0x1000}, /* WFDMA PCIE0 MCU DMA0 */ + {0x55000000, 0x403000, 0x1000}, /* WFDMA PCIE0 MCU DMA1 */ + {0x56000000, 0x404000, 0x1000}, /* WFDMA reserved */ + {0x57000000, 0x405000, 0x1000}, /* WFDMA MCU wrap CR */ + {0x58000000, 0x406000, 0x1000}, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */ + {0x59000000, 0x407000, 0x1000}, /* WFDMA PCIE1 MCU DMA1 */ + {0x820c0000, 0x408000, 0x4000}, /* WF_UMAC_TOP (PLE) */ + {0x820c8000, 0x40c000, 0x2000}, /* WF_UMAC_TOP (PSE) */ + {0x820cc000, 0x40e000, 0x2000}, /* WF_UMAC_TOP (PP) */ + {0x820e0000, 0x420000, 0x0400}, /* WF_LMAC_TOP BN0 (WF_CFG) */ + {0x820e1000, 0x420400, 0x0200}, /* WF_LMAC_TOP BN0 (WF_TRB) */ + {0x820e2000, 0x420800, 0x0400}, /* WF_LMAC_TOP BN0 (WF_AGG) */ + {0x820e3000, 0x420c00, 0x0400}, /* WF_LMAC_TOP BN0 (WF_ARB) */ + {0x820e4000, 0x421000, 0x0400}, /* WF_LMAC_TOP BN0 (WF_TMAC) */ + {0x820e5000, 0x421400, 0x0800}, /* WF_LMAC_TOP BN0 (WF_RMAC) */ + {0x820ce000, 0x421c00, 0x0200}, /* WF_LMAC_TOP (WF_SEC) */ + {0x820e7000, 0x421e00, 0x0200}, /* WF_LMAC_TOP BN0 (WF_DMA) */ + {0x820cf000, 0x422000, 0x1000}, /* WF_LMAC_TOP (WF_PF) */ + {0x820e9000, 0x423400, 0x0200}, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */ + {0x820ea000, 0x424000, 0x0200}, /* WF_LMAC_TOP BN0 (WF_ETBF) */ + {0x820eb000, 0x424200, 0x0400}, /* WF_LMAC_TOP BN0 (WF_LPON) */ + {0x820ec000, 0x424600, 0x0200}, /* WF_LMAC_TOP BN0 (WF_INT) */ + {0x820ed000, 0x424800, 0x0800}, /* WF_LMAC_TOP BN0 (WF_MIB) */ + {0x820ca000, 0x426000, 0x2000}, /* WF_LMAC_TOP BN0 (WF_MUCOP) */ + {0x820d0000, 0x430000, 0x10000}, /* WF_LMAC_TOP (WF_WTBLON) */ + {0x40000000, 0x470000, 0x10000}, /* WF_UMAC_SYSRAM */ + {0x00400000, 0x480000, 0x10000}, /* WF_MCU_SYSRAM */ + {0x00410000, 0x490000, 0x10000}, /* WF_MCU_SYSRAM (config register) */ + {0x820f0000, 0x4a0000, 0x0400}, /* WF_LMAC_TOP BN1 (WF_CFG) */ + {0x820f1000, 0x4a0600, 0x0200}, /* WF_LMAC_TOP BN1 (WF_TRB) */ + {0x820f2000, 0x4a0800, 0x0400}, /* WF_LMAC_TOP BN1 (WF_AGG) */ + {0x820f3000, 0x4a0c00, 0x0400}, /* WF_LMAC_TOP BN1 (WF_ARB) */ + {0x820f4000, 0x4a1000, 0x0400}, /* WF_LMAC_TOP BN1 (WF_TMAC) */ + {0x820f5000, 0x4a1400, 0x0800}, /* WF_LMAC_TOP BN1 (WF_RMAC) */ + {0x820f7000, 0x4a1e00, 0x0200}, /* WF_LMAC_TOP BN1 (WF_DMA) */ + {0x820f9000, 0x4a3400, 0x0200}, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */ + {0x820fa000, 0x4a4000, 0x0200}, /* WF_LMAC_TOP BN1 (WF_ETBF) */ + {0x820fb000, 0x4a4200, 0x0400}, /* WF_LMAC_TOP BN1 (WF_LPON) */ + {0x820fc000, 0x4a4600, 0x0200}, /* WF_LMAC_TOP BN1 (WF_INT) */ + {0x820fd000, 0x4a4800, 0x0800}, /* WF_LMAC_TOP BN1 (WF_MIB) */ + {0x820c4000, 0x4a8000, 0x4000}, /* WF_LMAC_TOP (WF_UWTBL) */ + {0x820b0000, 0x4ae000, 0x1000}, /* [APB2] WFSYS_ON */ + {0x80020000, 0x4b0000, 0x10000}, /* WF_TOP_MISC_OFF */ + {0x81020000, 0x4c0000, 0x10000}, /* WF_TOP_MISC_ON */ + {0x7c500000, 0x500000, 0x10000}, /* CONN_INFRA, dyn mem map */ + {0x7c020000, 0x20000, 0x10000}, /* CONN_INFRA, wfdma */ + {0x7c060000, 0x60000, 0x10000}, /* CONN_INFRA, conn_host_csr_top */ + {0x7c000000, 0x00000, 0x10000}, /* CONN_INFRA, conn_infra_on */ + {0x0, 0x0, 0x0} /* End */ +}; +#endif + +static bool soc3_0WfdmaAllocRxRing( + struct GLUE_INFO *prGlueInfo, + bool fgAllocMem) +{ + if (!halWpdmaAllocRxRing(prGlueInfo, WFDMA0_RX_RING_IDX_2, + RX_RING1_SIZE, RXD_SIZE, RX_BUFFER_AGGRESIZE, + fgAllocMem)) { + DBGLOG(HAL, ERROR, "AllocWfdmaRxRing fail\n"); + return false; + } + if (!halWpdmaAllocRxRing(prGlueInfo, WFDMA0_RX_RING_IDX_3, + RX_RING1_SIZE, RXD_SIZE, RX_BUFFER_AGGRESIZE, + fgAllocMem)) { + DBGLOG(HAL, ERROR, "AllocWfdmaRxRing fail\n"); + return false; + } + if (!halWpdmaAllocRxRing(prGlueInfo, WFDMA1_RX_RING_IDX_0, + RX_RING1_SIZE, RXD_SIZE, RX_BUFFER_AGGRESIZE, + fgAllocMem)) { + DBGLOG(HAL, ERROR, "AllocWfdmaRxRing fail\n"); + return false; + } + return true; +} + +static void soc3_0asicConnac2xInterruptSettings( + struct ADAPTER *prAdapter, + IN u_int8_t enable) +{ + union soc3_0_WPDMA_INT_MASK IntMask; + ASSERT(prAdapter); + + if (enable) { + IntMask.word = 0; + + IntMask.field_wfdma0_ena.wfdma0_rx_done_0 = 1; + IntMask.field_wfdma0_ena.wfdma0_rx_done_1 = 1; + IntMask.field_wfdma0_ena.wfdma0_rx_done_2 = 1; + IntMask.field_wfdma0_ena.wfdma0_rx_done_3 = 1; + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR, IntMask.word); + + IntMask.word = 0; + + IntMask.field_wfdma1_ena.wfdma1_tx_done_0 = 1; + IntMask.field_wfdma1_ena.wfdma1_tx_done_1 = 1; + IntMask.field_wfdma1_ena.wfdma1_tx_done_16 = 1; + IntMask.field_wfdma1_ena.wfdma1_tx_done_17 = 1; + IntMask.field_wfdma1_ena.wfdma1_rx_done_0 = 1; + IntMask.field_wfdma1_ena.wfdma1_mcu2host_sw_int_en = 1; + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR, IntMask.word); + } else { + + IntMask.word = 0; + IntMask.field_wfdma0_ena.wfdma0_rx_done_0 = 1; + IntMask.field_wfdma0_ena.wfdma0_rx_done_1 = 1; + IntMask.field_wfdma0_ena.wfdma0_rx_done_2 = 1; + IntMask.field_wfdma0_ena.wfdma0_rx_done_3 = 1; + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR, IntMask.word); + + IntMask.word = 0; + IntMask.field_wfdma1_ena.wfdma1_tx_done_0 = 1; + IntMask.field_wfdma1_ena.wfdma1_tx_done_1 = 1; + IntMask.field_wfdma1_ena.wfdma1_tx_done_16 = 1; + IntMask.field_wfdma1_ena.wfdma1_tx_done_17 = 1; + IntMask.field_wfdma1_ena.wfdma1_rx_done_0 = 1; + IntMask.field_wfdma1_ena.wfdma1_mcu2host_sw_int_en = 1; + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR, IntMask.word); + } + +} + +static void soc3_0asicConnac2xWfdmaControl( + struct GLUE_INFO *prGlueInfo, + u_int8_t ucDmaIdx, + u_int8_t enable) +{ + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + union WPDMA_GLO_CFG_STRUCT GloCfg; + uint32_t u4DmaCfgCr; + uint32_t u4DmaRstDtxPtrCr; + uint32_t u4DmaRstDrxPtrCr; + + ASSERT(ucDmaIdx < CONNAC2X_WFDMA_COUNT); + u4DmaCfgCr = asicConnac2xWfdmaCfgAddrGet(prGlueInfo, ucDmaIdx); + u4DmaRstDtxPtrCr = + asicConnac2xWfdmaIntRstDtxPtrAddrGet(prGlueInfo, ucDmaIdx); + u4DmaRstDrxPtrCr = + asicConnac2xWfdmaIntRstDrxPtrAddrGet(prGlueInfo, ucDmaIdx); + + HAL_MCR_RD(prAdapter, u4DmaCfgCr, &GloCfg.word); + if (enable == TRUE) { + GloCfg.field_conn2x.pdma_bt_size = 3; + GloCfg.field_conn2x.tx_wb_ddone = 1; + GloCfg.field_conn2x.fifo_little_endian = 1; + GloCfg.field_conn2x.clk_gate_dis = 1; + GloCfg.field_conn2x.omit_tx_info = 1; + if (ucDmaIdx == 1) + GloCfg.field_conn2x.omit_rx_info = 1; + GloCfg.field_conn2x.csr_disp_base_ptr_chain_en = 1; + GloCfg.field_conn2x.omit_rx_info_pfet2 = 1; + } else { + GloCfg.field_conn2x.tx_dma_en = 0; + GloCfg.field_conn2x.rx_dma_en = 0; + GloCfg.field_conn2x.csr_disp_base_ptr_chain_en = 0; + GloCfg.field_conn2x.omit_tx_info = 0; + GloCfg.field_conn2x.omit_rx_info = 0; + GloCfg.field_conn2x.omit_rx_info_pfet2 = 0; + } + HAL_MCR_WR(prAdapter, u4DmaCfgCr, GloCfg.word); + + if (!enable) { + asicConnac2xWfdmaWaitIdle(prGlueInfo, ucDmaIdx, 100, 1000); + /* Reset DMA Index */ + HAL_MCR_WR(prAdapter, u4DmaRstDtxPtrCr, 0xFFFFFFFF); + HAL_MCR_WR(prAdapter, u4DmaRstDrxPtrCr, 0xFFFFFFFF); + } +} + +void soc3_0asicConnac2xWpdmaConfig( + struct GLUE_INFO *prGlueInfo, + u_int8_t enable, + bool fgResetHif) +{ + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + union WPDMA_GLO_CFG_STRUCT GloCfg[CONNAC2X_WFDMA_COUNT] = {0}; + uint32_t u4DmaCfgCr = 0; + uint32_t idx = 0; + struct mt66xx_chip_info *chip_info = prAdapter->chip_info; + + for (idx = 0; idx < CONNAC2X_WFDMA_COUNT; idx++) { + if (!chip_info->is_support_wfdma1 && idx) + break; + soc3_0asicConnac2xWfdmaControl(prGlueInfo, idx, enable); + u4DmaCfgCr = asicConnac2xWfdmaCfgAddrGet(prGlueInfo, idx); + HAL_MCR_RD(prAdapter, u4DmaCfgCr, &GloCfg[idx].word); + } + + /* set interrupt Mask */ + soc3_0asicConnac2xInterruptSettings(prAdapter, enable); + + if (enable) { + for (idx = 0; idx < CONNAC2X_WFDMA_COUNT; idx++) { + if (!chip_info->is_support_wfdma1 && idx) + break; + u4DmaCfgCr = + asicConnac2xWfdmaCfgAddrGet(prGlueInfo, idx); + GloCfg[idx].field_conn2x.tx_dma_en = 1; + GloCfg[idx].field_conn2x.rx_dma_en = 1; + HAL_MCR_WR(prAdapter, u4DmaCfgCr, GloCfg[idx].word); + } + } +} + +void soc3_0ReadExtIntStatus( + struct ADAPTER *prAdapter, + uint32_t *pu4IntStatus) +{ + uint32_t u4RegValue = 0; + uint32_t ap_write_value = 0; + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + struct BUS_INFO *prBusInfo = prAdapter->chip_info->bus_info; + + *pu4IntStatus = 0; + + HAL_MCR_RD(prAdapter, + CONNAC2X_WPDMA_EXT_INT_STA( + prBusInfo->host_ext_conn_hif_wrap_base), + &u4RegValue); + + if (HAL_IS_CONNAC2X_EXT_RX_DONE_INTR(u4RegValue, + prBusInfo->host_int_rxdone_bits)) { + *pu4IntStatus |= WHISR_RX0_DONE_INT; + ap_write_value |= (u4RegValue & + prBusInfo->host_int_rxdone_bits); + } + + if (HAL_IS_CONNAC2X_EXT_TX_DONE_INTR(u4RegValue, + prBusInfo->host_int_txdone_bits)) { + ap_write_value |= (u4RegValue & + prBusInfo->host_int_txdone_bits); + *pu4IntStatus |= WHISR_TX_DONE_INT; + } + + if (u4RegValue & CONNAC_MCU_SW_INT) { + *pu4IntStatus |= WHISR_D2H_SW_INT; + ap_write_value |= (u4RegValue & CONNAC_MCU_SW_INT); + } + + prHifInfo->u4IntStatus = u4RegValue; + + /* clear interrupt */ + HAL_MCR_WR(prAdapter, + CONNAC2X_WPDMA_EXT_INT_STA( + prBusInfo->host_ext_conn_hif_wrap_base), + ap_write_value); + +} + +void soc3_0asicConnac2xProcessTxInterrupt(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + union WPDMA_INT_STA_STRUCT rIntrStatus; + + rIntrStatus = (union WPDMA_INT_STA_STRUCT)prHifInfo->u4IntStatus; + if (rIntrStatus.field_conn2x_ext.wfdma1_tx_done_16) + halWpdmaProcessCmdDmaDone(prAdapter->prGlueInfo, + TX_RING_FWDL_IDX_3); + + if (rIntrStatus.field_conn2x_ext.wfdma1_tx_done_17) + halWpdmaProcessCmdDmaDone(prAdapter->prGlueInfo, + TX_RING_CMD_IDX_2); + + if (rIntrStatus.field_conn2x_ext.wfdma1_tx_done_0) { + halWpdmaProcessDataDmaDone(prAdapter->prGlueInfo, + TX_RING_DATA0_IDX_0); + + kalSetTxEvent2Hif(prAdapter->prGlueInfo); + } + + if (rIntrStatus.field_conn2x_ext.wfdma1_tx_done_1) { + halWpdmaProcessDataDmaDone(prAdapter->prGlueInfo, + TX_RING_DATA1_IDX_1); + + kalSetTxEvent2Hif(prAdapter->prGlueInfo); + } + +} + +void soc3_0asicConnac2xProcessRxInterrupt( + struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + union WPDMA_INT_STA_STRUCT rIntrStatus; + + rIntrStatus = (union WPDMA_INT_STA_STRUCT)prHifInfo->u4IntStatus; + if (rIntrStatus.field_conn2x_ext.wfdma1_rx_done_0 || + (prAdapter->u4NoMoreRfb & BIT(WFDMA1_RX_RING_IDX_0))) + halRxReceiveRFBs(prAdapter, WFDMA1_RX_RING_IDX_0, FALSE); + + if (rIntrStatus.field_conn2x_ext.wfdma0_rx_done_0 || + (prAdapter->u4NoMoreRfb & BIT(RX_RING_DATA_IDX_0))) + halRxReceiveRFBs(prAdapter, RX_RING_DATA_IDX_0, TRUE); + + if (rIntrStatus.field_conn2x_ext.wfdma0_rx_done_1 || + (prAdapter->u4NoMoreRfb & BIT(RX_RING_EVT_IDX_1))) + halRxReceiveRFBs(prAdapter, RX_RING_EVT_IDX_1, TRUE); + + if (rIntrStatus.field_conn2x_ext.wfdma0_rx_done_2 || + (prAdapter->u4NoMoreRfb & BIT(WFDMA0_RX_RING_IDX_2))) + halRxReceiveRFBs(prAdapter, WFDMA0_RX_RING_IDX_2, TRUE); + + if (rIntrStatus.field_conn2x_ext.wfdma0_rx_done_3 || + (prAdapter->u4NoMoreRfb & BIT(WFDMA0_RX_RING_IDX_3))) + halRxReceiveRFBs(prAdapter, WFDMA0_RX_RING_IDX_3, TRUE); +} + +static void soc3_0SetMDRXRingPriorityInterrupt(struct ADAPTER *prAdapter) +{ + u_int32_t val = 0; + + HAL_MCR_RD(prAdapter, + WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_ADDR, &val); + val |= BITS(4, 7); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_ADDR, val); + HAL_MCR_RD(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_ADDR, &val); + val |= BIT(1); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_ADDR, val); +} + +void soc3_0asicConnac2xWfdmaManualPrefetch( + struct GLUE_INFO *prGlueInfo) +{ + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + u_int32_t val = 0; + + HAL_MCR_RD(prAdapter, WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR, &val); + /* disable prefetch offset calculation auto-mode */ + val &= + ~WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN_MASK; + HAL_MCR_WR(prAdapter, WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR, val); + + HAL_MCR_RD(prAdapter, WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR, &val); + /* disable prefetch offset calculation auto-mode */ + val &= + ~WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN_MASK; + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR, val); + + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_ADDR, 0x00000004); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_ADDR, 0x00400004); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_ADDR, 0x00800004); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_ADDR, 0x00c00004); + + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_EXT_CTRL_ADDR, 0x01000004); + + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_EXT_CTRL_ADDR, 0x01400004); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_EXT_CTRL_ADDR, 0x01800004); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_EXT_CTRL_ADDR, 0x01c00004); + + /* HIF_DMA1_TX*/ + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_EXT_CTRL_ADDR, 0x02400004); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_EXT_CTRL_ADDR, 0x02800004); +#if (SW_WORKAROUND_FOR_WFDMA_ISSUE_HWITS00009838 == 1) + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_EXT_CTRL_ADDR, 0x02c00004); +#endif + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_EXT_CTRL_ADDR, 0x03000004); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_EXT_CTRL_ADDR, 0x03400004); +#if (SW_WORKAROUND_FOR_WFDMA_ISSUE_HWITS00009838 == 1) + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_EXT_CTRL_ADDR, 0x03800004); +#endif + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_EXT_CTRL_ADDR, 0x03c00004); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_EXT_CTRL_ADDR, 0x04000004); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_EXT_CTRL_ADDR, 0x04400004); +#if (SW_WORKAROUND_FOR_WFDMA_ISSUE_HWITS00009838 == 1) + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_EXT_CTRL_ADDR, 0x04800004); +#endif + + /* HIF_DMA1_RX*/ + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_EXT_CTRL_ADDR, 0x04C00004); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_EXT_CTRL_ADDR, 0x05000004); + +#if (SW_WORKAROUND_FOR_WFDMA_ISSUE_HWITS00009838 == 1) + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_EXT_CTRL_ADDR, 0x05400004); +#endif + + soc3_0SetMDRXRingPriorityInterrupt(prAdapter); + + /* reset dma idx */ + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR, 0xFFFFFFFF); + HAL_MCR_WR(prAdapter, + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR, 0xFFFFFFFF); + +#if defined(_HIF_AXI) + /*Bypass BID check*/ + soc3_0_WfdmaAxiCtrl(prAdapter); +#endif + +} + +void soc3_0_WfdmaAxiCtrl( + struct ADAPTER *prAdapter) +{ + uint32_t u4Val = 0; + + HAL_MCR_RD(prAdapter, WFDMA_AXI0_R2A_CTRL_0, &u4Val); + u4Val |= BID_CHK_BYP_EN_MASK; + HAL_MCR_WR(prAdapter, WFDMA_AXI0_R2A_CTRL_0, u4Val); + +} + +void soc3_0_ConstructPatchName(struct GLUE_INFO *prGlueInfo, + uint8_t **apucName, uint8_t *pucNameIdx) +{ + int ret = 0; + uint8_t aucFlavor[2] = {0}; + + kalGetFwFlavor(&aucFlavor[0]); + + ret = kalSnprintf(apucName[(*pucNameIdx)], + SOC3_0_FILE_NAME_MAX, + "soc3_0_patch_wmmcu_%u%s_%x_hdr.bin", + CFG_WIFI_IP_SET, + aucFlavor, + wlanGetEcoVersion(prGlueInfo->prAdapter)); + + if (ret < 0 || ret >= CFG_FW_NAME_MAX_LEN) + DBGLOG(INIT, ERROR, "kalSnprintf failed, ret: %d\n", ret); +} + +struct BUS_INFO soc3_0_bus_info = { +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + .top_cfg_base = SOC3_0_TOP_CFG_BASE, + + /* host_dma0 for TXP */ + .host_dma0_base = CONNAC2X_HOST_WPDMA_0_BASE, + /* host_dma1 for TXD and host cmd to WX_CPU */ + .host_dma1_base = CONNAC2X_HOST_WPDMA_1_BASE, + .host_ext_conn_hif_wrap_base = CONNAC2X_HOST_EXT_CONN_HIF_WRAP, + .host_int_status_addr = + CONNAC2X_WPDMA_EXT_INT_STA(CONNAC2X_HOST_EXT_CONN_HIF_WRAP), + + .host_int_txdone_bits = (CONNAC2X_EXT_WFDMA1_TX_DONE_INT0 + | CONNAC2X_EXT_WFDMA1_TX_DONE_INT1 + | CONNAC2X_EXT_WFDMA1_TX_DONE_INT2 + | CONNAC2X_EXT_WFDMA1_TX_DONE_INT3 + | CONNAC2X_EXT_WFDMA1_TX_DONE_INT4 + | CONNAC2X_EXT_WFDMA1_TX_DONE_INT5 + | CONNAC2X_EXT_WFDMA1_TX_DONE_INT6 + | CONNAC2X_EXT_WFDMA1_TX_DONE_INT16 + | CONNAC2X_EXT_WFDMA1_TX_DONE_INT17), + .host_int_rxdone_bits = (CONNAC2X_EXT_WFDMA1_RX_DONE_INT0 + | CONNAC2X_EXT_WFDMA0_RX_DONE_INT0 + | CONNAC2X_EXT_WFDMA0_RX_DONE_INT1 + | CONNAC2X_EXT_WFDMA0_RX_DONE_INT2 + | CONNAC2X_EXT_WFDMA0_RX_DONE_INT3 + ), + + .host_tx_ring_base = + CONNAC2X_TX_RING_BASE(CONNAC2X_HOST_WPDMA_1_BASE), + .host_tx_ring_ext_ctrl_base = + CONNAC2X_TX_RING_EXT_CTRL_BASE(CONNAC2X_HOST_WPDMA_1_BASE), + .host_tx_ring_cidx_addr = + CONNAC2X_TX_RING_CIDX(CONNAC2X_HOST_WPDMA_1_BASE), + .host_tx_ring_didx_addr = + CONNAC2X_TX_RING_DIDX(CONNAC2X_HOST_WPDMA_1_BASE), + .host_tx_ring_cnt_addr = + CONNAC2X_TX_RING_CNT(CONNAC2X_HOST_WPDMA_1_BASE), + + .host_rx_ring_base = + CONNAC2X_RX_RING_BASE(CONNAC2X_HOST_WPDMA_0_BASE), + .host_rx_ring_ext_ctrl_base = + CONNAC2X_RX_RING_EXT_CTRL_BASE(CONNAC2X_HOST_WPDMA_0_BASE), + .host_rx_ring_cidx_addr = + CONNAC2X_RX_RING_CIDX(CONNAC2X_HOST_WPDMA_0_BASE), + .host_rx_ring_didx_addr = + CONNAC2X_RX_RING_DIDX(CONNAC2X_HOST_WPDMA_0_BASE), + .host_rx_ring_cnt_addr = + CONNAC2X_RX_RING_CNT(CONNAC2X_HOST_WPDMA_0_BASE), + + .host_wfdma1_rx_ring_base = + CONNAC2X_WFDMA1_RX_RING_BASE(CONNAC2X_HOST_WPDMA_1_BASE), + .host_wfdma1_rx_ring_cidx_addr = + CONNAC2X_WFDMA1_RX_RING_CIDX(CONNAC2X_HOST_WPDMA_1_BASE), + .host_wfdma1_rx_ring_didx_addr = + CONNAC2X_WFDMA1_RX_RING_DIDX(CONNAC2X_HOST_WPDMA_1_BASE), + .host_wfdma1_rx_ring_cnt_addr = + CONNAC2X_WFDMA1_RX_RING_CNT(CONNAC2X_HOST_WPDMA_1_BASE), + .host_wfdma1_rx_ring_ext_ctrl_base = + CONNAC2X_WFDMA1_RX_RING_EXT_CTRL_BASE( + CONNAC2X_HOST_WPDMA_1_BASE), + + .bus2chip = soc3_0_bus2chip_cr_mapping, +#if defined(_HIF_PCIE) + .max_static_map_addr = 0x000f0000, +#elif defined(_HIF_AXI) + .max_static_map_addr = 0x00700000, +#endif + .tx_ring_fwdl_idx = CONNAC2X_FWDL_TX_RING_IDX, + .tx_ring_cmd_idx = CONNAC2X_CMD_TX_RING_IDX, + .tx_ring0_data_idx = 0, + .tx_ring1_data_idx = 1, + .fw_own_clear_addr = CONNAC2X_BN0_IRQ_STAT_ADDR, + .fw_own_clear_bit = PCIE_LPCR_FW_CLR_OWN, + .fgCheckDriverOwnInt = FALSE, + .u4DmaMask = 32, + .pdmaSetup = soc3_0asicConnac2xWpdmaConfig, + .enableInterrupt = asicConnac2xEnablePlatformIRQ, + .disableInterrupt = asicConnac2xDisablePlatformIRQ, + + .processTxInterrupt = soc3_0asicConnac2xProcessTxInterrupt, + .processRxInterrupt = soc3_0asicConnac2xProcessRxInterrupt, + .tx_ring_ext_ctrl = asicConnac2xWfdmaTxRingExtCtrl, + .rx_ring_ext_ctrl = asicConnac2xWfdmaRxRingExtCtrl, + /* null wfdmaManualPrefetch if want to disable manual mode */ + .wfdmaManualPrefetch = soc3_0asicConnac2xWfdmaManualPrefetch, + .lowPowerOwnRead = asicConnac2xLowPowerOwnRead, + .lowPowerOwnSet = asicConnac2xLowPowerOwnSet, + .lowPowerOwnClear = asicConnac2xLowPowerOwnClear, + .wakeUpWiFi = asicWakeUpWiFi, + .processSoftwareInterrupt = asicConnac2xProcessSoftwareInterrupt, + .softwareInterruptMcu = asicConnac2xSoftwareInterruptMcu, + .hifRst = asicConnac2xHifRst, + + .initPcieInt = NULL, + .devReadIntStatus = soc3_0ReadExtIntStatus, + .DmaShdlInit = mt6885DmashdlInit, + .wfdmaAllocRxRing = soc3_0WfdmaAllocRxRing, +#endif /*_HIF_PCIE || _HIF_AXI */ +}; + +#if CFG_ENABLE_FW_DOWNLOAD +struct FWDL_OPS_T soc3_0_fw_dl_ops = { +#if (CFG_POWER_ON_DOWNLOAD_EMI_ROM_PATCH == 1) + .constructFirmwarePrio = soc3_0_ConstructFirmwarePrio, +#else + .constructFirmwarePrio = NULL, +#endif + .constructPatchName = soc3_0_ConstructPatchName, + .downloadPatch = wlanDownloadPatch, + .downloadFirmware = wlanConnacFormatDownload, +#if (CFG_DOWNLOAD_DYN_MEMORY_MAP == 1) + .downloadByDynMemMap = soc3_0_DownloadByDynMemMap, +#else + .downloadByDynMemMap = NULL, +#endif + .getFwInfo = wlanGetConnacFwInfo, + .getFwDlInfo = asicGetFwDlInfo, +#if (CFG_SUPPORT_PRE_ON_PHY_ACTION == 1) + .phyAction = soc3_0_wlanPhyAction, +#else + .phyAction = NULL, +#endif +}; +#endif /* CFG_ENABLE_FW_DOWNLOAD */ + +struct TX_DESC_OPS_T soc3_0_TxDescOps = { + .fillNicAppend = fillNicTxDescAppend, + .fillHifAppend = fillTxDescAppendByHostV2, + .fillTxByteCount = fillConnac2xTxDescTxByteCount, +}; + +struct RX_DESC_OPS_T soc3_0_RxDescOps = { +}; + +struct CHIP_DBG_OPS soc3_0_debug_ops = { + .showPdmaInfo = soc3_0_show_wfdma_info, + .showPseInfo = soc3_0_show_pse_info, + .showPleInfo = soc3_0_show_ple_info, + .showTxdInfo = connac2x_show_txd_Info, + .showWtblInfo = connac2x_show_wtbl_info, + .showUmacFwtblInfo = connac2x_show_umac_wtbl_info, + .showCsrInfo = NULL, + .showDmaschInfo = soc3_0_show_dmashdl_info, + .dumpMacInfo = soc3_0_dump_mac_info, + .showHifInfo = NULL, + .printHifDbgInfo = NULL, + .show_rx_rate_info = connac2x_show_rx_rate_info, + .show_rx_rssi_info = connac2x_show_rx_rssi_info, + .show_stat_info = connac2x_show_stat_info, +}; + +#if CFG_SUPPORT_QA_TOOL +struct ATE_OPS_T soc3_0_AteOps = { + /*ICapStart phase out , wlan_service instead*/ + .setICapStart = connacSetICapStart, + /*ICapStatus phase out , wlan_service instead*/ + .getICapStatus = connacGetICapStatus, + /*CapIQData phase out , wlan_service instead*/ + .getICapIQData = connacGetICapIQData, + .getRbistDataDumpEvent = nicExtEventICapIQData, + .icapRiseVcoreClockRate = soc3_0_icapRiseVcoreClockRate, + .icapDownVcoreClockRate = soc3_0_icapDownVcoreClockRate +}; +#endif + + +/* Litien code refine to support multi chip */ +struct mt66xx_chip_info mt66xx_chip_info_soc3_0 = { + .bus_info = &soc3_0_bus_info, +#if CFG_ENABLE_FW_DOWNLOAD + .fw_dl_ops = &soc3_0_fw_dl_ops, +#endif /* CFG_ENABLE_FW_DOWNLOAD */ +#if CFG_SUPPORT_QA_TOOL + .prAteOps = &soc3_0_AteOps, +#endif /*CFG_SUPPORT_QA_TOOL*/ + .prDebugOps = &soc3_0_debug_ops, + .prTxDescOps = &soc3_0_TxDescOps, + .prRxDescOps = &soc3_0_RxDescOps, + .chip_id = SOC3_0_CHIP_ID, + .should_verify_chip_id = FALSE, + .sw_sync0 = SOC3_0_SW_SYNC0, + .sw_ready_bits = WIFI_FUNC_NO_CR4_READY_BITS, + .sw_ready_bit_offset = SOC3_0_SW_SYNC0_RDY_OFFSET, + .patch_addr = SOC3_0_PATCH_START_ADDR, + .is_support_cr4 = FALSE, + .is_support_wacpu = FALSE, + .txd_append_size = SOC3_0_TX_DESC_APPEND_LENGTH, + .rxd_size = SOC3_0_RX_DESC_LENGTH, + .init_evt_rxd_size = SOC3_0_RX_DESC_LENGTH, + .pse_header_length = CONNAC2X_NIC_TX_PSE_HEADER_LENGTH, + .init_event_size = CONNAC2X_RX_INIT_EVENT_LENGTH, + .eco_info = soc3_0_eco_table, + .isNicCapV1 = FALSE, + .top_hcr = CONNAC2X_TOP_HCR, + .top_hvr = CONNAC2X_TOP_HVR, + .top_fvr = CONNAC2X_TOP_FVR, + .arb_ac_mode_addr = SOC3_0_ARB_AC_MODE_ADDR, + .custom_oid_interface_version = MTK_CUSTOM_OID_INTERFACE_VERSION, + .em_interface_version = MTK_EM_INTERFACE_VERSION, + .asicCapInit = asicConnac2xCapInit, +#if CFG_ENABLE_FW_DOWNLOAD + .asicEnableFWDownload = NULL, +#endif /* CFG_ENABLE_FW_DOWNLOAD */ + .asicGetChipID = asicGetChipID, + .downloadBufferBin = NULL, + .is_support_hw_amsdu = TRUE, + .is_support_asic_lp = TRUE, + .is_support_wfdma1 = TRUE, + .is_support_nvram_fragment = TRUE, + .asicWfdmaReInit = asicConnac2xWfdmaReInit, + .asicWfdmaReInit_handshakeInit = asicConnac2xWfdmaDummyCrWrite, + .group5_size = sizeof(struct HW_MAC_RX_STS_GROUP_5), + .u4LmacWtblDUAddr = CONNAC2X_WIFI_LWTBL_BASE, + .u4UmacWtblDUAddr = CONNAC2X_WIFI_UWTBL_BASE, + .wmmcupwron = hifWmmcuPwrOn, + .wmmcupwroff = hifWmmcuPwrOff, +#if (CFG_POWER_ON_DOWNLOAD_EMI_ROM_PATCH == 1) + .pwrondownload = soc3_0_wlanPowerOnDownload, +#else + .pwrondownload = NULL, +#endif + .triggerfwassert = soc3_0_Trigger_fw_assert, + .dumpwfsyscpupcr = soc3_0_DumpWfsyscpupcr, + + .coantSetWiFi = wlanCoAntWiFi, + .coantSetMD = wlanCoAntMD, + .coantVFE28En = wlanCoAntVFE28En, + .coantVFE28Dis = wlanCoAntVFE28Dis, +#if (CFG_SUPPORT_CONNINFRA == 1) + .coexpccifon = wlanConnacPccifon, + .coexpccifoff = wlanConnacPccifoff, + .trigger_wholechiprst = soc3_0_Trigger_whole_chip_rst, + .sw_interrupt_handler = soc3_0_Sw_interrupt_handler, + .conninra_cb_register = soc3_0_Conninfra_cb_register, +#endif +#if (CFG_SUPPORT_PRE_ON_PHY_ACTION == 1) + .getCalResult = soc3_0_wlanGetCalResult, + .calDebugCmd = soc3_0_wlanCalDebugCmd, +#endif + .checkbushang = soc3_0_CheckBusHang, + .dumpBusHangCr = soc3_0_DumpBusHangCr, + .cmd_max_pkt_size = CFG_TX_MAX_PKT_SIZE, /* size 1600 */ +}; + +struct mt66xx_hif_driver_data mt66xx_driver_data_soc3_0 = { + .chip_info = &mt66xx_chip_info_soc3_0, +}; + +#if (CFG_DOWNLOAD_DYN_MEMORY_MAP == 1) +uint32_t soc3_0_DownloadByDynMemMap(IN struct ADAPTER *prAdapter, + IN uint32_t u4Addr, IN uint32_t u4Len, + IN uint8_t *pucStartPtr, IN enum ENUM_IMG_DL_IDX_T eDlIdx) +{ +#if 0 + uint32_t u4Val = 0; + uint32_t u4Idx = 0; + uint32_t u4NonZeroMemCnt = 0; +#endif +#if defined(_HIF_AXI) + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; +#endif + +#if defined(_HIF_PCIE) + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; +#endif + + if ((eDlIdx == IMG_DL_IDX_PATCH) || (eDlIdx == IMG_DL_IDX_N9_FW)) { +/*#pragma message("wlanDownloadSectionByDynMemMap()::SOC3_0")*/ +#if defined(_HIF_AXI) + /* AXI workable version by bytes of u4Len in one movement */ + /* for PCIe WLAN drv, use 0x7C000000 based; + * for AXI, also use 0x7C000000 based + */ + HAL_MCR_WR(prAdapter, + CONN_INFRA_CFG_AP2WF_REMAP_1_ADDR, + u4Addr); + +#if 0 + if (eDlIdx == IMG_DL_IDX_PATCH) { + do { + u4Val = 0; + + kalMemCopy( + (void *)&u4Val, + (void *)( + prHifInfo->CSRBaseAddress+ + 0x500000+(u4Idx * 4)), + 4); + + if (u4Val != 0) + u4NonZeroMemCnt++; + } while (u4Idx++ < 20); + + if (u4NonZeroMemCnt != 0) { + DBGLOG(INIT, WARN, + "[MJ]ROM patch exists(%d)!\n", + u4NonZeroMemCnt); + + return WLAN_STATUS_NOT_ACCEPTED; + } + } +#endif + + memcpy_toio((void *)(prHifInfo->CSRBaseAddress+0x500000), + (void *)pucStartPtr, u4Len); +#endif + +#if defined(_HIF_PCIE) + HAL_MCR_RD(prAdapter, + CONN_INFRA_CFG_PCIE2AP_REMAP_2_ADDR, &u4Val); + + DBGLOG(INIT, WARN, "[MJ]ORIG(0x%08x) = 0x%08x\n", + CONN_INFRA_CFG_PCIE2AP_REMAP_2_ADDR, u4Val); + + /* + * 0x18=0x7C + * 0x18001120[31:0] = 0x00100000 + * 0x18500000 (AP) is 0x00100000(MCU) + * 0x18001198[31:16] = 0x1850 + * 0x18001198 = 0x1850|Value[15:0] + + u4Val = ((~BITS(31,16) & u4Val) | ((0x1850) << 16)); + */ + + /* this hard code is verified with DE for SOC3_0 */ + u4Val = CONN_INFRA_CFG_PCIE2AP_REMAP_2_ADDR_DE_HARDCODE; + + HAL_MCR_WR(prAdapter, + CONN_INFRA_CFG_PCIE2AP_REMAP_2_ADDR, u4Val); + + HAL_MCR_RD(prAdapter, + CONN_INFRA_CFG_PCIE2AP_REMAP_2_ADDR, &u4Val); + + DBGLOG(INIT, WARN, "[MJ]NEW(0x%08x) = 0x%08x\n", + CONN_INFRA_CFG_PCIE2AP_REMAP_2_ADDR, u4Val); + +#if 1 + /* PCIe workable version by bytes of u4Len in one movement */ + /* for PCIe WLAN drv, use 0x7C000000 based; + * for AXI, use 0x18000000 based + */ + HAL_MCR_WR(prAdapter, + CONN_INFRA_CFG_AP2WF_REMAP_1_ADDR, + u4Addr); + +#if 0 + if (eDlIdx == IMG_DL_IDX_PATCH) { + do { + u4Val = 0; + + HAL_MCR_RD(prAdapter, + (CONN_INFRA_CFG_AP2WF_BUS_ADDR + + (u4Idx * 4)), &u4Val); + + if (u4Val != 0) + u4NonZeroMemCnt++; + } while (u4Idx++ < 20); + + if (u4NonZeroMemCnt != 0) { + DBGLOG(INIT, WARN, + "[MJ]ROM patch exists(%d)!\n", + u4NonZeroMemCnt); + + return WLAN_STATUS_NOT_ACCEPTED; + } + } +#endif + + /* because + * soc3_0_bus2chip_cr_mapping = + * {0x7c500000, 0x50000, 0x10000} + */ + kalMemCopy((void *)(prHifInfo->CSRBaseAddress+0x50000), + (void *)pucStartPtr, u4Len); +#else + /* PCIe workable version by 4 bytes in one movement */ + /* for PCIe WLAN drv, use 0x7C000000 based; + * for AXI, use 0x18000000 based + */ + HAL_MCR_WR(prAdapter, + CONN_INFRA_CFG_AP2WF_REMAP_1_ADDR, + u4Addr); + + for (u4Offset = 0; u4Len > 0; u4Offset += u4RemapSize) { + if (u4Len > 4) + u4RemapSize = 4; + else + u4RemapSize = u4Len; + + u4Len -= u4RemapSize; + + HAL_MCR_WR(prAdapter, + (CONN_INFRA_CFG_AP2WF_BUS_ADDR + u4Offset), + (uint32_t) + (*(uint32_t *)((uint8_t *)pucStartPtr + u4Offset))); + + HAL_MCR_RD(prAdapter, + (CONN_INFRA_CFG_AP2WF_BUS_ADDR + u4Offset), &u4Val); + + /* You can uncomment it to see what is downloaded + *if (u4Idx++ < 20) { + *DBGLOG(INIT, WARN, "[MJ]0x%08x(%08x) = 0x%08x\n", + *(0x7C500000 + u4Offset), u4Val, + *(uint32_t)(*(uint32_t *) + *((uint8_t *)pucStartPtr + u4Offset))); + *} + */ + } +#endif +#endif /* _HIF_PCIE */ + } else { + return WLAN_STATUS_NOT_SUPPORTED; + } + + return WLAN_STATUS_SUCCESS; +} +#endif +void soc3_0_DumpWfsyscpupcr(struct ADAPTER *prAdapter) +{ +#define CPUPCR_LOG_NUM 5 +#define CPUPCR_BUF_SZ 50 + + uint32_t i = 0; + uint32_t var_pc = 0; + uint32_t var_lp = 0; + uint64_t log_sec = 0; + uint64_t log_nsec = 0; + char log_buf_pc[CPUPCR_LOG_NUM][CPUPCR_BUF_SZ]; + char log_buf_lp[CPUPCR_LOG_NUM][CPUPCR_BUF_SZ]; + + if (prAdapter == NULL) + return; + + for (i = 0; i < CPUPCR_LOG_NUM; i++) { + log_sec = local_clock(); + log_nsec = do_div(log_sec, 1000000000)/1000; + HAL_MCR_RD(prAdapter, WFSYS_CPUPCR_ADDR, &var_pc); + HAL_MCR_RD(prAdapter, WFSYS_LP_ADDR, &var_lp); + + kalSnprintf(log_buf_pc[i], CPUPCR_BUF_SZ, "%llu.%06llu/0x%08x;", + log_sec, + log_nsec, + var_pc); + + kalSnprintf(log_buf_lp[i], CPUPCR_BUF_SZ, "%llu.%06llu/0x%08x;", + log_sec, + log_nsec, + var_lp); + } + + DBGLOG(HAL, INFO, "wm pc=%s%s%s%s%s\n", + log_buf_pc[0], + log_buf_pc[1], + log_buf_pc[2], + log_buf_pc[3], + log_buf_pc[4]); + + DBGLOG(HAL, INFO, "wm lp=%s%s%s%s%s\n", + log_buf_lp[0], + log_buf_lp[1], + log_buf_lp[2], + log_buf_lp[3], + log_buf_lp[4]); +} + +void soc3_0_CrRead(struct ADAPTER *prAdapter, size_t addr, unsigned int *val) +{ + if (prAdapter == NULL) + wf_ioremap_read(addr, val); + else + HAL_MCR_RD(prAdapter, (addr|0x64000000), val); +} + +void soc3_0_CrWrite(struct ADAPTER *prAdapter, + phys_addr_t addr, unsigned int val) +{ + if (prAdapter == NULL) + wf_ioremap_write(addr, val); + else + HAL_MCR_WR(prAdapter, (addr|0x64000000), val); +} + +void soc3_0_DumpWfsysdebugflag(void) +{ + uint32_t i = 0, u4Value = 0; + uint32_t RegValue = 0; + + if (conninfra_reg_readable() && !conninfra_is_bus_hang()) { + /* bpll_rdy/wpll_rdy */ + wf_ioremap_read(0x18001810, &u4Value); + DBGLOG(HAL, INFO, + "Bus hang dump: 0x18001810 = 0x%08x\n", u4Value); + /* hclk_sw_rdy */ + wf_ioremap_read(0x1800180C, &u4Value); + DBGLOG(HAL, INFO, + "Bus hang dump: 0x1800180C = 0x%08x\n", u4Value); + } + + /* wf_top_cfg_on_dbg */ + RegValue = 0x00100000; + wf_ioremap_write(0x18060094, RegValue); + wf_ioremap_read(0x1806021C, &u4Value); + DBGLOG(HAL, INFO, + "Bus hang dump: 0x1806021C = 0x%08x after 0x%08x\n", + u4Value, RegValue); + + RegValue = 0x000F0001; + for (i = 0; i < 15; i++) { + wf_ioremap_write(0x18060128, RegValue); + wf_ioremap_read(0x18060148, &u4Value); + DBGLOG(HAL, INFO, + "Bus hang dump: 0x18060148 = 0x%08x after 0x%08x\n", + u4Value, RegValue); + RegValue -= 0x10000; + } + RegValue = 0x00030002; + for (i = 0; i < 3; i++) { + wf_ioremap_write(0x18060128, RegValue); + wf_ioremap_read(0x18060148, &u4Value); + DBGLOG(HAL, INFO, + "Bus hang dump: 0x18060148 = 0x%08x after 0x%08x\n", + u4Value, RegValue); + RegValue -= 0x10000; + } + RegValue = 0x00040003; + for (i = 0; i < 4; i++) { + wf_ioremap_write(0x18060128, RegValue); + wf_ioremap_read(0x18060148, &u4Value); + DBGLOG(HAL, INFO, + "Bus hang dump: 0x18060148 = 0x%08x after 0x%08x\n", + u4Value, RegValue); + RegValue -= 0x10000; + } + +} + +void soc3_0_DumpWfsysInfo(void) +{ + int value = 0; + int value_2 = 0; + int i; + + for (i = 0; i < 5; i++) { + wf_ioremap_read(0x18060204, &value); + wf_ioremap_read(0x18060208, &value_2); + DBGLOG(HAL, INFO, + "MCU PC: 0x%08x, MCU LP: 0x%08x\n", value, value_2); + } +} +int soc3_0_Trigger_fw_assert(void) +{ + int ret = 0; + int value = 0; + uint32_t waitRet = 0; + struct ADAPTER *prAdapter = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *)wiphy_priv(wlanGetWiphy()); + prAdapter = prGlueInfo->prAdapter; + + soc3_0_CheckBusHang(NULL, FALSE); + if (g_IsWfsysBusHang == TRUE) { + DBGLOG(HAL, INFO, + "Already trigger conninfra whole chip reset.\n"); + return 0; + } + DBGLOG(HAL, INFO, "Trigger fw assert start.\n"); + wf_ioremap_read(WF_TRIGGER_AP2CONN_EINT, &value); + value &= 0xFFFFFF7F; + ret = wf_ioremap_write(WF_TRIGGER_AP2CONN_EINT, value); + waitRet = wait_for_completion_timeout(&g_triggerComp, + MSEC_TO_JIFFIES(WIFI_TRIGGER_ASSERT_TIMEOUT)); + if (waitRet > 0) { + /* Case 1: No timeout. */ + soc3_0_DumpWfsysInfo(); + DBGLOG(INIT, INFO, "Trigger assert successfully.\n"); + } else { + /* Case 2: timeout */ + DBGLOG(INIT, ERROR, + "Trigger assert more than 2 seconds, need to trigger rst self\n"); + soc3_0_DumpWfsysInfo(); + soc3_0_DumpWfsysdebugflag(); + g_IsTriggerTimeout = TRUE; +#if (CFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT == 1) + if (!prAdapter->prGlueInfo->u4ReadyFlag) + g_IsNeedWaitCoredump = TRUE; +#endif + } +#if (CFG_SUPPORT_CONNINFRA == 1) + kalSetRstEvent(); +#endif + wf_ioremap_read(WF_TRIGGER_AP2CONN_EINT, &value); + value |= 0x80; + ret = wf_ioremap_write(WF_TRIGGER_AP2CONN_EINT, value); + + return ret; +} + +void soc3_0_CheckBusHangUT(void) +{ +#define BUS_HANG_UT_WAIT_COUNT 30 + + struct ADAPTER *prAdapter = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t count = 0; + uint32_t u4Value = 0; + uint32_t RegValue = 0; + + prGlueInfo = (struct GLUE_INFO *)wiphy_priv(wlanGetWiphy()); + prAdapter = prGlueInfo->prAdapter; + + HAL_MCR_RD(prAdapter, 0x7c00162c, &u4Value); + RegValue = u4Value | BIT(0); + HAL_MCR_WR(prAdapter, 0x7c00162c, RegValue); + + while (count < BUS_HANG_UT_WAIT_COUNT) { + HAL_MCR_RD(prAdapter, 0x7c00162c, &u4Value); + DBGLOG(HAL, INFO, "%s: 0x7c00162c = 0x%08x\n", + __func__, u4Value); + + if ((u4Value&BIT(3)) == BIT(3)) { + DBGLOG(HAL, ERROR, "%s: 0x7c00162c = 0x%08x\n", + __func__, u4Value); + break; + } + count++; + } + + /* Trigger Hang */ + HAL_MCR_RD(prAdapter, 0x7c060000, &u4Value); +} + +static void soc3_0_DumpMemory32(uint32_t *pu4StartAddr, + uint32_t u4Count, char *info) +{ +#define ONE_LINE_MAX_COUNT 16 +#define TMP_BUF_SZ 20 + uint32_t i, endCount; + char buf[ONE_LINE_MAX_COUNT*10]; + char tmp[TMP_BUF_SZ] = {'\0'}; + + ASSERT(pu4StartAddr); + + LOG_FUNC("[Host_CSR] %s, Count(%d)\n", info, u4Count); + + while (u4Count > 0) { + + kalSnprintf(buf, TMP_BUF_SZ, "%08x", pu4StartAddr[0]); + + if (u4Count > ONE_LINE_MAX_COUNT) + endCount = ONE_LINE_MAX_COUNT; + else + endCount = u4Count; + + for (i = 1; i < endCount; i++) { + kalSnprintf(tmp, TMP_BUF_SZ, " %08x", pu4StartAddr[i]); + strncat(buf, tmp, strlen(tmp)); + } + + LOG_FUNC("%s\n", buf); + + if (u4Count > ONE_LINE_MAX_COUNT) { + u4Count -= ONE_LINE_MAX_COUNT; + pu4StartAddr += ONE_LINE_MAX_COUNT; + } else + u4Count = 0; + } +} + +static uint32_t soc3_0_DumpHwDebugFlagSub(struct ADAPTER *prAdapter, + uint32_t RegValue) +{ + uint32_t u4Cr; + uint32_t u4Value = 0; + + u4Cr = 0x1806009C; + soc3_0_CrWrite(prAdapter, u4Cr, RegValue); + + u4Cr = 0x1806021C; + soc3_0_CrRead(prAdapter, u4Cr, &u4Value); + + return u4Value; +} + +static void soc3_0_DumpHwDebugFlag(struct ADAPTER *prAdapter) +{ +#define HANG_HW_FLAG_NUM 7 + + uint32_t u4Cr; + uint32_t RegValue = 0; + uint32_t log[HANG_HW_FLAG_NUM]; + + DBGLOG(HAL, LOUD, + "Host_CSR - dump all HW Debug flag"); + + u4Cr = 0x18060094; + RegValue = 0x00139CE7; + soc3_0_CrWrite(prAdapter, u4Cr, RegValue); + + log[0] = soc3_0_DumpHwDebugFlagSub(prAdapter, 0x366CD932); + log[1] = soc3_0_DumpHwDebugFlagSub(prAdapter, 0x36AD5A34); + log[2] = soc3_0_DumpHwDebugFlagSub(prAdapter, 0x36EDDB36); + log[3] = soc3_0_DumpHwDebugFlagSub(prAdapter, 0x3972E54A); + log[4] = soc3_0_DumpHwDebugFlagSub(prAdapter, 0x39B3664C); + log[5] = soc3_0_DumpHwDebugFlagSub(prAdapter, 0x7C387060); + log[6] = soc3_0_DumpHwDebugFlagSub(prAdapter, 0x7C78F162); + + soc3_0_DumpMemory32(log, HANG_HW_FLAG_NUM, "HW Debug flag"); +} + +static void soc3_0_DumpPcLrLog(struct ADAPTER *prAdapter) +{ +#define HANG_PC_LOG_NUM 32 + uint32_t u4Cr, u4Index, i; + uint32_t u4Value = 0; + uint32_t RegValue = 0; + uint32_t log[HANG_PC_LOG_NUM]; + + DBGLOG(HAL, LOUD, + "Host_CSR - dump PC log / LR log"); + + memset(log, 0, HANG_PC_LOG_NUM); + + /* PC log + * dbg_pc_log_sel Write 0x1806_0090 [7:2] 6'h20 + * choose 33th pc log buffer to read current pc log buffer index + * read pc from host CR Read 0x1806_0204 [21:17] + * read current pc log buffer index + * dbg_pc_log_sel Write 0x1806_0090 [7:2] index + * set pc log buffer index to read pc log + * read pc from host CR Read 0x1806_0204 [31:0] + * read pc log of the specific index + */ + + u4Cr = 0x18060090; + soc3_0_CrRead(prAdapter, u4Cr, &u4Value); + RegValue = (0x20<<2) | (u4Value&BITS(0, 1)) | (u4Value&BITS(8, 31)); + soc3_0_CrWrite(prAdapter, u4Cr, RegValue); + + u4Cr = 0x18060204; + soc3_0_CrRead(prAdapter, u4Cr, &u4Value); + u4Index = (u4Value&BITS(17, 21)) >> 17; + + for (i = 0; i < HANG_PC_LOG_NUM; i++) { + + u4Index++; + + if (u4Index == HANG_PC_LOG_NUM) + u4Index = 0; + + u4Cr = 0x18060090; + soc3_0_CrRead(prAdapter, u4Cr, &u4Value); + RegValue = (u4Index<<2) | (u4Value&BITS(0, 1)) | + (u4Value&BITS(8, 31)); + soc3_0_CrWrite(prAdapter, u4Cr, RegValue); + + u4Cr = 0x18060204; + soc3_0_CrRead(prAdapter, u4Cr, &log[i]); + } + + /* restore */ + u4Cr = 0x18060090; + soc3_0_CrRead(prAdapter, u4Cr, &u4Value); + RegValue = (0x3F<<2) | (u4Value&BITS(0, 1)) | (u4Value&BITS(8, 31)); + soc3_0_CrWrite(prAdapter, u4Cr, RegValue); + + soc3_0_DumpMemory32(log, HANG_PC_LOG_NUM, "PC log"); + + /* GPR log */ + + u4Cr = 0x18060090; + soc3_0_CrRead(prAdapter, u4Cr, &u4Value); + RegValue = (0x20<<8) | (u4Value&BITS(0, 7)) | (u4Value&BITS(14, 31)); + soc3_0_CrWrite(prAdapter, u4Cr, RegValue); + + u4Cr = 0x18060208; + soc3_0_CrRead(prAdapter, u4Cr, &u4Value); + u4Index = (u4Value&BITS(17, 21)) >> 17; + + for (i = 0; i < HANG_PC_LOG_NUM; i++) { + + u4Index++; + + if (u4Index == HANG_PC_LOG_NUM) + u4Index = 0; + + u4Cr = 0x18060090; + soc3_0_CrRead(prAdapter, u4Cr, &u4Value); + RegValue = (u4Index<<8) | (u4Value&BITS(0, 7)) | + (u4Value&BITS(14, 31)); + soc3_0_CrWrite(prAdapter, u4Cr, RegValue); + + u4Cr = 0x18060208; + soc3_0_CrRead(prAdapter, u4Cr, &log[i]); + } + + /* restore */ + u4Cr = 0x18060090; + soc3_0_CrRead(prAdapter, u4Cr, &u4Value); + RegValue = (0x3F<<8) | (u4Value&BITS(0, 7)) | (u4Value&BITS(14, 31)); + soc3_0_CrWrite(prAdapter, u4Cr, RegValue); + + soc3_0_DumpMemory32(log, HANG_PC_LOG_NUM, "GPR log"); +} + +static void soc3_0_DumpN10CoreReg(struct ADAPTER *prAdapter) +{ +#define HANG_N10_CORE_LOG_NUM 38 + uint32_t u4Cr, i; + uint32_t u4Value = 0; + uint32_t RegValue = 0; + uint32_t log[HANG_N10_CORE_LOG_NUM]; + + DBGLOG(HAL, LOUD, + "Host_CSR - read N10 core register"); + + memset(log, 0, HANG_N10_CORE_LOG_NUM); + +/* +* [31:26]: gpr_index_sel (set different sets of gpr) = 0 +* [13:8]: gpr buffer index setting +* (set as 0x3F to select the current selected GPR) +*/ + u4Cr = 0x18060090; + soc3_0_CrRead(prAdapter, u4Cr, &u4Value); + + u4Value = (0x3F<<8) | (u4Value&BITS(0, 7)) | (u4Value&BITS(14, 31)); + + for (i = 0; i < HANG_N10_CORE_LOG_NUM; i++) { + + RegValue = (i<<26) | (u4Value&BITS(0, 25)); + + u4Cr = 0x18060090; + soc3_0_CrWrite(prAdapter, u4Cr, RegValue); + + u4Cr = 0x18060208; + soc3_0_CrRead(prAdapter, u4Cr, &log[i]); + } + + /* restore */ + u4Cr = 0x18060090; + RegValue = (30<<26) | (u4Value&BITS(0, 25)); + soc3_0_CrWrite(prAdapter, u4Cr, RegValue); + + soc3_0_DumpMemory32(log, HANG_N10_CORE_LOG_NUM, "N10 core register"); +} + +static void soc3_0_DumpOtherCr(struct ADAPTER *prAdapter) +{ +#define HANG_MAIL_BOX_LOG_NUM 2 +#define HANG_DUMMY_CR_LOG_NUM 4 +#define HANG_OTHER_LOG_TOTAL (HANG_MAIL_BOX_LOG_NUM+HANG_DUMMY_CR_LOG_NUM) + + uint32_t u4Cr, i; + uint32_t log[HANG_OTHER_LOG_TOTAL]; + + DBGLOG(HAL, LOUD, + "Host_CSR - mailbox and other CRs"); + + memset(log, 0, HANG_OTHER_LOG_TOTAL); + + u4Cr = 0x18060260; + for (i = 0; i < HANG_MAIL_BOX_LOG_NUM; i++) { + soc3_0_CrRead(prAdapter, u4Cr, &log[i]); + u4Cr += 0x04; + } + + u4Cr = 0x180602f0; + for (i = HANG_MAIL_BOX_LOG_NUM; i < HANG_OTHER_LOG_TOTAL; i++) { + soc3_0_CrRead(prAdapter, u4Cr, &log[i]); + u4Cr += 0x04; + } + + soc3_0_DumpMemory32(log, HANG_OTHER_LOG_TOTAL, "mailbox and other CRs"); +} + +static void soc3_0_DumpSpecifiedWfTop(struct ADAPTER *prAdapter) +{ +#define HANG_TOP_LOG_NUM 2 + + uint32_t u4Cr; + uint32_t u4Value = 0; + uint32_t RegValue = 0; + uint32_t log[HANG_TOP_LOG_NUM]; + + DBGLOG(HAL, LOUD, + "Host_CSR - specified WF TOP monflg on"); + + memset(log, 0, HANG_TOP_LOG_NUM); + +/* 0x1806009C[28]=1 write enable wf_mcu_misc */ + + u4Cr = 0x1806009C; + soc3_0_CrRead(prAdapter, u4Cr, &u4Value); + RegValue = u4Value | BIT(28); + soc3_0_CrWrite(prAdapter, u4Cr, RegValue); + +/* 0x1806009C[27:0]=0xC387060 write select {FLAG_4[9:2],FLAG_27[9:2]} */ + + u4Cr = 0x1806009C; + soc3_0_CrRead(prAdapter, u4Cr, &u4Value); + RegValue = 0xC387060 | (u4Value&BITS(28, 31)); + soc3_0_CrWrite(prAdapter, u4Cr, RegValue); + +/* 0x18060094[20]=1 write enable wf_monflg_on */ + + u4Cr = 0x18060094; + soc3_0_CrRead(prAdapter, u4Cr, &u4Value); + RegValue = u4Value | BIT(20); + soc3_0_CrWrite(prAdapter, u4Cr, RegValue); + +/* 0x18060094[19:0]=0x39CE7 write select wf_mcusys_dbg */ + + u4Cr = 0x18060094; + soc3_0_CrRead(prAdapter, u4Cr, &u4Value); + RegValue = 0x39CE7 | (u4Value&BITS(20, 31)); + soc3_0_CrWrite(prAdapter, u4Cr, RegValue); + +/* 0x1806_021c[31:0] Read get {FLAG_4[9:2],FLAG_27[9:2]} */ + + u4Cr = 0x1806021c; + soc3_0_CrRead(prAdapter, u4Cr, &log[0]); + +/* 0x1806009C[27:0]=0xC78F162 write select {FlAG_23[7:0],FlAG_6[9:2]} */ + + u4Cr = 0x1806009C; + soc3_0_CrRead(prAdapter, u4Cr, &u4Value); + RegValue = 0xC78F162 | (u4Value&BITS(28, 31)); + soc3_0_CrWrite(prAdapter, u4Cr, RegValue); + + +/* 0x1806_021c[31:0] Read get {FlAG_23[7:0],FlAG_6[9:2]} */ + + u4Cr = 0x1806021c; + soc3_0_CrRead(prAdapter, u4Cr, &log[1]); + + soc3_0_DumpMemory32(log, HANG_TOP_LOG_NUM, + "specified WF TOP monflg on"); +} + + +/* check wsys bus hang or not */ +/* return = TRUE (bus is hang), FALSE (bus is not hang) */ +/* write 0x18060128 = 0x000B0001 */ +/* read and check 0x18060148 bit[9:8] */ +/* if [9:8]=2'b00 (wsys not hang), others is hang */ + +static int IsWsysBusHang(struct ADAPTER *prAdapter) +{ + uint32_t u4Value = 0; + uint32_t u4WriteDebugValue; + + u4WriteDebugValue = 0x000B0001; + soc3_0_CrWrite(prAdapter, 0x18060128, u4WriteDebugValue); + soc3_0_CrRead(prAdapter, 0x18060148, &u4Value); + + u4Value &= BITS(8, 9); + return u4Value; +} /* soc3_0_IsWsysBusHang */ + +#if 0 +/* PP CR: 0x820CCXXX remap to Base + 0x40e000 */ +static void DumpPPDebugCr(struct ADAPTER *prAdapter) +{ + uint32_t ReadRegValue[4]; + uint32_t u4Value[4]; + + /* 0x820CC0F0 : PP DBG_CTRL */ + ReadRegValue[0] = 0x820CC0F0; + HAL_MCR_RD(prAdapter, ReadRegValue[0], &u4Value[0]); + + /* 0x820CC0F8 : PP DBG_CS0 */ + ReadRegValue[1] = 0x820CC0F8; + HAL_MCR_RD(prAdapter, ReadRegValue[1], &u4Value[1]); + + /* 0x820CC0FC : PP DBG_CS1 */ + ReadRegValue[2] = 0x820CC0FC; + HAL_MCR_RD(prAdapter, ReadRegValue[2], &u4Value[2]); + + /* 0x820CC100 : PP DBG_CS2 */ + ReadRegValue[3] = 0x820CC100; + HAL_MCR_RD(prAdapter, ReadRegValue[3], &u4Value[3]); + + DBGLOG(HAL, INFO, + "PP[0x%08x]=0x%08x,[0x%08x]=0x%08x,[0x%08x]=0x%08x,[0x%08x]=0x%08x,", + ReadRegValue[0], u4Value[0], + ReadRegValue[1], u4Value[1], + ReadRegValue[2], u4Value[2], + ReadRegValue[3], u4Value[3]); +} + +/* PP CR: 0x820CCXXX remap to Base + 0x40e000 */ +static void DumpPPDebugCr_without_adapter(void) +{ + uint32_t ReadRegValue[4]; + uint32_t u4Value[4]; + + /* 0x820CC0F0 : PP DBG_CTRL */ + ReadRegValue[0] = 0x1840E0F0; + wf_ioremap_read(ReadRegValue[0], &u4Value[0]); + + /* 0x820CC0F8 : PP DBG_CS0 */ + ReadRegValue[1] = 0x1840E0F8; + wf_ioremap_read(ReadRegValue[1], &u4Value[1]); + + /* 0x820CC0FC : PP DBG_CS1 */ + ReadRegValue[2] = 0x1840E0FC; + wf_ioremap_read(ReadRegValue[2], &u4Value[2]); + + /* 0x820CC100 : PP DBG_CS2 */ + ReadRegValue[3] = 0x1840E100; + wf_ioremap_read(ReadRegValue[3], &u4Value[3]); + + DBGLOG(HAL, INFO, + "PP[0x%08x]=0x%08x,[0x%08x]=0x%08x,[0x%08x]=0x%08x,[0x%08x]=0x%08x,", + ReadRegValue[0], u4Value[0], + ReadRegValue[1], u4Value[1], + ReadRegValue[2], u4Value[2], + ReadRegValue[3], u4Value[3]); +} +#endif + +/* need to dump AXI Master related CR 0x1802750C ~ 0x18027530*/ +static void DumpAXIMasterDebugCr(struct ADAPTER *prAdapter) +{ +#define AXI_MASTER_DUMP_CR_START 0x1802750C +#define AXI_MASTER_DUMP_CR_NUM 9 + + uint32_t ReadRegValue = 0; + uint32_t u4Value[AXI_MASTER_DUMP_CR_NUM] = {0}; + uint32_t i; + + ReadRegValue = AXI_MASTER_DUMP_CR_START; + for (i = 0 ; i < AXI_MASTER_DUMP_CR_NUM; i++) { + ReadRegValue += 4; + soc3_0_CrRead(prAdapter, ReadRegValue, &u4Value[i]); + } + + soc3_0_DumpMemory32(u4Value, + AXI_MASTER_DUMP_CR_NUM, + "HW AXI BUS debug CR start[0x1802750C]"); + +} /* soc3_0_DumpAXIMasterDebugCr */ + +/* Dump Flow : */ +/* 1) dump WFDMA / AXI Master CR */ +/* 2) check wsys bus is hang */ +/* - if not hang dump WM WFDMA & PP CR */ +void soc3_0_DumpWFDMACr(struct ADAPTER *prAdapter) +{ + /* Dump Host side WFDMACR */ + bool bShowWFDMA_type = FALSE; + int32_t ret = 0; + + if (prAdapter == NULL) + soc3_0_show_wfdma_info_by_type_without_adapter(bShowWFDMA_type); + else + soc3_0_show_wfdma_info_by_type(prAdapter, bShowWFDMA_type); + + DumpAXIMasterDebugCr(prAdapter); + + ret = IsWsysBusHang(prAdapter); + /* ret =0 is readable, wsys not bus hang */ + #if 0 /* TODO */ + if (ret == 0) { + bShowWFDMA_type = TRUE; + if (prAdapter == NULL) { + soc3_0_show_wfdma_info_by_type_without_adapter( + bShowWFDMA_type); + + DumpPPDebugCr_without_adapter(); + } else { + soc3_0_show_wfdma_info_by_type(prAdapter, + bShowWFDMA_type); + + DumpPPDebugCr(prAdapter); + } + } else { + DBGLOG(HAL, INFO, + "Wifi bus hang(0x%08x), can't dump wsys CR\n", ret); + } + #endif + +} /* soc3_0_DumpWFDMAHostCr */ + +static void soc3_0_DumpHostCr(struct ADAPTER *prAdapter) +{ + soc3_0_DumpWfsyscpupcr(prAdapter); /* first dump */ + soc3_0_DumpPcLrLog(prAdapter); + soc3_0_DumpN10CoreReg(prAdapter); + soc3_0_DumpOtherCr(prAdapter); + soc3_0_DumpHwDebugFlag(prAdapter); + soc3_0_DumpSpecifiedWfTop(prAdapter); + soc3_0_DumpWFDMACr(prAdapter); +} /* soc3_0_DumpHostCr */ + +void soc3_0_DumpBusHangCr(struct ADAPTER *prAdapter) +{ + conninfra_is_bus_hang(); + soc3_0_DumpHostCr(prAdapter); +} + +int soc3_0_CheckBusHang(void *adapter, uint8_t ucWfResetEnable) +{ + int ret = 1; + int conninfra_read_ret = 0; + int conninfra_hang_ret = 0; + uint8_t conninfra_reset = FALSE; + uint32_t u4Cr = 0; + uint32_t u4Value = 0; + uint32_t RegValue = 0; + struct ADAPTER *prAdapter = (struct ADAPTER *) adapter; + + if (prAdapter == NULL) + DBGLOG(HAL, INFO, "prAdapter NULL\n"); + + do { +/* +* 1. Check "AP2CONN_INFRA ON step is ok" +* & Check "AP2CONN_INFRA OFF step is ok" +*/ + conninfra_read_ret = conninfra_reg_readable(); + + if (!conninfra_read_ret) { + DBGLOG(HAL, ERROR, + "conninfra_reg_readable fail(%d)\n", + conninfra_read_ret); + + conninfra_hang_ret = conninfra_is_bus_hang(); + + if (conninfra_hang_ret > 0) { + conninfra_reset = TRUE; + + DBGLOG(HAL, ERROR, + "conninfra_is_bus_hang, Chip reset\n"); + } else { + /* + * not readable, but no_hang or rst_ongoing + * => no reset and return fail + */ + ucWfResetEnable = FALSE; + } + + break; + } + + if ((prAdapter != NULL) && (prAdapter->fgIsFwDownloaded)) { +/* +* 2. Check MCU wake up and setting mux sel done CR (mailbox) +* - 0x1806_0260[31] should be 1'b1 (FW view 0x8900_0100[31]) +*/ + + u4Cr = 0x18060260; + soc3_0_CrRead(prAdapter, u4Cr, &u4Value); + + if ((u4Value&BIT(31)) != BIT(31)) { + DBGLOG(HAL, ERROR, + "Bus hang check: 0x%08x = 0x%08x\n", + u4Cr, u4Value); + break; + } + +/* +* 3. Check wf_mcusys bus hang irq status (need set debug ctrl enable first, +* ref sheet "Debug ctrl setting") +* - if(bus hang), then +* a) WF MCU: wf_mcusys_vdnr_timeout_irq_b, FW: Trigger subssy reset / +* Whole Chip Reset(conn2ap hang) +* b) Driver dump CRs of sheet "Debug ctrl setting" +* +* Write Address : 0x1806_009c[6:0] , Data : 0x60 default 0x00 +* Write Address : 0x1806_009c[28] , Data : 0x1 default 0x0 +* (wf_mcu_dbg enable) +* Write Address : 0x1806_0094[4:0] , Data : 0x7 default 0x0 +* (switch monflg mux) +* Write Address : 0x1806_0094[20] , Data : 0x1 default 0x1 +* (enable wf monflg debug) +* Read Address : 0x1806_021c[0] shoulde be 1'b0 +*/ + + u4Cr = 0x1806009c; + soc3_0_CrRead(prAdapter, u4Cr, &u4Value); + RegValue = (u4Value&BITS(7, 31)) | 0x60; + RegValue = RegValue | BIT(28); + soc3_0_CrWrite(prAdapter, u4Cr, RegValue); + + u4Cr = 0x18060094; + soc3_0_CrRead(prAdapter, u4Cr, &u4Value); + RegValue = (u4Value&BITS(5, 31)) | 0x7; + RegValue = RegValue | BIT(20); + soc3_0_CrWrite(prAdapter, u4Cr, RegValue); + + u4Cr = 0x1806021c; + soc3_0_CrRead(prAdapter, u4Cr, &u4Value); + + if ((u4Value&BIT(0)) == BIT(0)) { + DBGLOG(HAL, ERROR, + "Bus hang check: 0x%08x = 0x%08x\n", + u4Cr, u4Value); + + u4Cr = 0x1806009c; + soc3_0_CrRead(prAdapter, u4Cr, &u4Value); + DBGLOG(HAL, ERROR, + "Bus hang check: 0x%08x = 0x%08x\n", + u4Cr, u4Value); + + u4Cr = 0x18060094; + soc3_0_CrRead(prAdapter, u4Cr, &u4Value); + DBGLOG(HAL, ERROR, + "Bus hang check: 0x%08x = 0x%08x\n", + u4Cr, u4Value); + break; + } + } else { + DBGLOG(HAL, INFO, + "Before fgIsFwDownloaded\n"); + } + +/* +* 4. Check conn2wf sleep protect +* - 0x1800_1620[3] (sleep protect enable ready), should be 1'b0 +*/ + u4Cr = 0x18001620; + soc3_0_CrRead(prAdapter, u4Cr, &u4Value); + + if ((u4Value&BIT(3)) == BIT(3)) { + DBGLOG(HAL, ERROR, + "Bus hang check: 0x%08x = 0x%08x\n", + u4Cr, u4Value); + + u4Cr = 0x18060010; + soc3_0_CrRead(prAdapter, u4Cr, &u4Value); + + DBGLOG(HAL, ERROR, + "Bus hang check: 0x%08x = 0x%08x\n", + u4Cr, u4Value); + + u4Cr = 0x180600f0; + soc3_0_CrRead(prAdapter, u4Cr, &u4Value); + + DBGLOG(HAL, ERROR, + "Bus hang check: 0x%08x = 0x%08x\n", + u4Cr, u4Value); + break; + } + +/* +* 5. check wfsys bus clock +* - 0x1806_0000[15] , 1: means bus no clock, 0: ok +*/ + u4Cr = 0x18060000; + soc3_0_CrRead(prAdapter, u4Cr, &u4Value); + + if ((u4Value&BIT(15)) == BIT(15)) { + DBGLOG(HAL, ERROR, + "Bus hang check: 0x%08x = 0x%08x\n", + u4Cr, u4Value); + break; + } + + DBGLOG(HAL, TRACE, "Bus hang check: Done\n"); + + ret = 0; + } while (FALSE); + + if (ret > 0) { + + /* check again for dump log */ + conninfra_is_bus_hang(); + + if ((conninfra_hang_ret != CONNINFRA_ERR_RST_ONGOING) && + (conninfra_hang_ret != CONNINFRA_INFRA_BUS_HANG) && + (conninfra_hang_ret != + CONNINFRA_AP2CONN_RX_SLP_PROT_ERR) && + (conninfra_hang_ret != + CONNINFRA_AP2CONN_TX_SLP_PROT_ERR) && + (conninfra_hang_ret != CONNINFRA_AP2CONN_CLK_ERR)) + soc3_0_DumpHostCr(prAdapter); + + if (conninfra_reset) { + g_IsWfsysBusHang = TRUE; + conninfra_trigger_whole_chip_rst(CONNDRV_TYPE_WIFI, + "bus hang"); + } else if (ucWfResetEnable) { + g_IsWfsysBusHang = TRUE; + conninfra_trigger_whole_chip_rst(CONNDRV_TYPE_WIFI, + "wifi bus hang"); + } + } + + return ret; +} + +void soc3_0_DumpBusHangdebuglog(void) +{ + uint32_t u4Value = 0; + uint32_t RegValue; + + RegValue = 0x00020002; + wf_ioremap_write(0x18060128, RegValue); + wf_ioremap_read(0x18060148, &u4Value); + DBGLOG(HAL, INFO, + "dump: 0x18060148 = 0x%08x after 0x%08x\n", + u4Value, RegValue); + wf_ioremap_read(0x18001a00, &u4Value); + DBGLOG(HAL, INFO, + "dump: 0x18001a00 = 0x%08x\n", u4Value); + wf_ioremap_read(0x1800c00c, &u4Value); + DBGLOG(HAL, INFO, + "dump: 0x1800c00c = 0x%08x\n", u4Value); + +} +void soc3_0_DumpPwrStatedebuglog(void) +{ + uint32_t u4Value = 0; + + wf_ioremap_read(0x18070400, &u4Value); + DBGLOG(HAL, INFO, + "dump: 0x18070400 = 0x%08x\n", u4Value); + wf_ioremap_read(0x18071400, &u4Value); + DBGLOG(HAL, INFO, + "dump: 0x18071400 = 0x%08x\n", u4Value); + wf_ioremap_read(0x18072400, &u4Value); + DBGLOG(HAL, INFO, + "dump: 0x18072400 = 0x%08x\n", u4Value); + wf_ioremap_read(0x18073400, &u4Value); + DBGLOG(HAL, INFO, + "dump: 0x18073400 = 0x%08x\n", u4Value); + wf_ioremap_read(0x180602cc, &u4Value); + DBGLOG(HAL, INFO, + "dump: 0x180602cc = 0x%08x\n", u4Value); + wf_ioremap_read(0x18000110, &u4Value); + DBGLOG(HAL, INFO, + "dump: 0x18000110 = 0x%08x\n", u4Value); + wf_ioremap_read(0x184c0880, &u4Value); + DBGLOG(HAL, INFO, + "dump: 0x184c0880 = 0x%08x\n", u4Value); + wf_ioremap_read(0x184c08d0, &u4Value); + DBGLOG(HAL, INFO, + "dump: 0x184c08d0 = 0x%08x\n", u4Value); +} + +int wf_pwr_on_consys_mcu(void) +{ + int check; + int value = 0; + int ret = 0; + int conninfra_hang_ret = 0; + unsigned int polling_count; + + DBGLOG(INIT, INFO, "wmmcu power-on start.\n"); + /* Wakeup conn_infra off write 0x180601A4[0] = 1'b1 */ + wf_ioremap_read(CONN_INFRA_WAKEUP_WF_ADDR, &value); + value |= 0x00000001; + wf_ioremap_write(CONN_INFRA_WAKEUP_WF_ADDR, value); + + /* Check AP2CONN slpprot ready + * (polling "10 times" and each polling interval is "1ms") + * Address: 0x1806_0184[5] + * Data: 1'b0 + * Action: polling + */ + wf_ioremap_read(CONN_INFRA_ON2OFF_SLP_PROT_ACK_ADDR, &value); + check = 0; + polling_count = 0; + while ((value & 0x00000020) != 0) { + if (polling_count > 10) { + check = -1; + ret = -1; + break; + } + udelay(1000); + wf_ioremap_read(CONN_INFRA_ON2OFF_SLP_PROT_ACK_ADDR, &value); + polling_count++; + } + if (check != 0) { + DBGLOG(INIT, ERROR, "Polling AP2CONN slpprot ready fail.\n"); + return ret; + } + + /* Check CONNSYS version ID + * (polling "10 times" and each polling interval is "1ms") + * Address: 0x1800_1000[31:0] + * Data: 0x2001_0000 + * Action: polling + */ + wf_ioremap_read(CONN_HW_VER_ADDR, &value); + check = 0; + polling_count = 0; + while (value != kalGetConnsysVerId()) { + if (polling_count > 10) { + check = -1; + ret = -1; + break; + } + udelay(1000); + wf_ioremap_read(CONN_HW_VER_ADDR, &value); + polling_count++; + } + if (check != 0) { + DBGLOG(INIT, ERROR, "Polling CONNSYS version ID fail.\n"); + return ret; + } + soc3_0_DumpBusHangdebuglog(); + + /* Assert CONNSYS WM CPU SW reset write 0x18000010[0] = 1'b0*/ + wf_ioremap_read(WFSYS_CPU_SW_RST_B_ADDR, &value); + value &= 0xFFFFFFFE; + wf_ioremap_write(WFSYS_CPU_SW_RST_B_ADDR, value); + + /* bus clock ctrl */ + conninfra_bus_clock_ctrl(CONNDRV_TYPE_WIFI, CONNINFRA_BUS_CLOCK_ALL, 1); + /* Turn on wfsys_top_on + * 0x18000000[31:16] = 0x57460000, + * 0x18000000[7] = 1'b1 + */ + wf_ioremap_read(WFSYS_ON_TOP_PWR_CTL_ADDR, &value); + value &= 0x0000FF7F; + value |= 0x57460080; + wf_ioremap_write(WFSYS_ON_TOP_PWR_CTL_ADDR, value); + /* Polling wfsys_rgu_off_hreset_rst_b + * (polling "10 times" and each polling interval is "0.5ms") + * Address: 0x1806_02CC[2] (TOP_DBG_DUMMY_3_CONNSYS_PWR_STATUS[2]) + * Data: 1'b1 + * Action: polling + */ + + wf_ioremap_read(TOP_DBG_DUMMY_3_CONNSYS_PWR_STATUS_ADDR, &value); + check = 0; + polling_count = 0; + while ((value & 0x00000004) == 0) { + if (polling_count > 10) { + check = -1; + ret = -1; + break; + } + udelay(500); + wf_ioremap_read(TOP_DBG_DUMMY_3_CONNSYS_PWR_STATUS_ADDR, + &value); + polling_count++; + } + if (check != 0) { + DBGLOG(INIT, ERROR, + "Polling wfsys rgu off fail. (0x%x)\n", + value); + return ret; + } + + if (!conninfra_reg_readable()) { + DBGLOG(HAL, ERROR, + "conninfra_reg_readable fail\n"); + + conninfra_hang_ret = conninfra_is_bus_hang(); + + if (conninfra_hang_ret > 0) { + + DBGLOG(HAL, ERROR, + "conninfra_is_bus_hang, Chip reset\n"); + } + return -1; + } + /* Turn off "conn_infra to wfsys"/ wfsys to conn_infra" bus + * sleep protect 0x18001620[0] = 1'b0 + */ + wf_ioremap_read(CONN_INFRA_WF_SLP_CTRL_R_ADDR, &value); + value &= 0xFFFFFFFE; + wf_ioremap_write(CONN_INFRA_WF_SLP_CTRL_R_ADDR, value); + /* Polling WF_SLP_CTRL ready + * (polling "100 times" and each polling interval is "0.5ms") + * Address: 0x1800_1620[3] (CONN_INFRA_WF_SLP_CTRL_R_OFFSET[3]) + * Data: 1'b0 + * Action: polling + */ + wf_ioremap_read(CONN_INFRA_WF_SLP_CTRL_R_ADDR, &value); + check = 0; + polling_count = 0; + while ((value & 0x00000008) != 0) { + if (polling_count > 100) { + check = -1; + ret = -1; + break; + } + udelay(500); + wf_ioremap_read(CONN_INFRA_WF_SLP_CTRL_R_ADDR, &value); + polling_count++; + DBGLOG(INIT, ERROR, "WF_SLP_CTRL (0x%x) (%d)\n", + value, + polling_count); + } + if (check != 0) { + DBGLOG(INIT, ERROR, + "Polling WFSYS TO CONNINFRA SLEEP PROTECT fail. (0x%x)\n", + value); + return ret; + } + /* Turn off "wf_dma to conn_infra" bus sleep protect + * 0x18001624[0] = 1'b0 + */ + wf_ioremap_read(CONN_INFRA_WFDMA_SLP_CTRL_R_ADDR, &value); + value &= 0xFFFFFFFE; + wf_ioremap_write(CONN_INFRA_WFDMA_SLP_CTRL_R_ADDR, value); + /* Polling wfsys_rgu_off_hreset_rst_b + * (polling "100 times" and each polling interval is "0.5ms") + * Address: 0x1800_1624[3] (CONN_INFRA_WFDMA_SLP_CTRL_R_OFFSET[3]) + * Data: 1'b0 + * Action: polling + */ + wf_ioremap_read(CONN_INFRA_WFDMA_SLP_CTRL_R_ADDR, &value); + check = 0; + polling_count = 0; + while ((value & 0x00000008) != 0) { + if (polling_count > 100) { + check = -1; + ret = -1; + break; + } + udelay(500); + wf_ioremap_read(CONN_INFRA_WFDMA_SLP_CTRL_R_ADDR, &value); + polling_count++; + DBGLOG(INIT, ERROR, "WFDMA_SLP_CTRL (0x%x) (%d)\n", + value, + polling_count); + } + if (check != 0) { + DBGLOG(INIT, ERROR, + "Polling WFDMA TO CONNINFRA SLEEP PROTECT RDY fail. (0x%x)\n", + value); + return ret; + } + + /*WF_VDNR_EN_ADDR 0x1800_E06C[0] =1'b1*/ + wf_ioremap_read(WF_VDNR_EN_ADDR, &value); + value |= 0x00000001; + wf_ioremap_write(WF_VDNR_EN_ADDR, value); + + /* Check WFSYS version ID (Polling) */ + wf_ioremap_read(WFSYS_VERSION_ID_ADDR, &value); + check = 0; + polling_count = 0; + while (value != WFSYS_VERSION_ID) { + if (polling_count > 10) { + check = -1; + ret = -1; + break; + } + udelay(500); + wf_ioremap_read(WFSYS_VERSION_ID_ADDR, &value); + polling_count++; + } + if (check != 0) { + DBGLOG(INIT, ERROR, "Polling CONNSYS version ID fail.\n"); + return ret; + } + + /* Setup CONNSYS firmware in EMI */ +#if (CFG_POWER_ON_DOWNLOAD_EMI_ROM_PATCH == 1) + soc3_0_wlanPowerOnInit(ENUM_WLAN_POWER_ON_DOWNLOAD_EMI); +#endif + + /* Default value update 2: EMI entry address */ + wf_ioremap_write(CONN_CFG_AP2WF_REMAP_1_ADDR, CONN_MCU_CONFG_HS_BASE); + wf_ioremap_write(WF_DYNAMIC_BASE+MCU_EMI_ENTRY_OFFSET, 0x00000000); + wf_ioremap_write(WF_DYNAMIC_BASE+WF_EMI_ENTRY_OFFSET, 0x00000000); + + /* Reset WFSYS semaphore 0x18000018[0] = 1'b0 */ + wf_ioremap_read(WFSYS_SW_RST_B_ADDR, &value); + value &= 0xFFFFFFFE; + wf_ioremap_write(WFSYS_SW_RST_B_ADDR, value); + + /* De-assert WFSYS CPU SW reset 0x18000010[0] = 1'b1 */ + wf_ioremap_read(WFSYS_CPU_SW_RST_B_ADDR, &value); + value |= 0x00000001; + wf_ioremap_write(WFSYS_CPU_SW_RST_B_ADDR, value); + + /* Check CONNSYS power-on completion + * Polling "100 times" and each polling interval is "0.5ms" + * Polling 0x81021604[31:0] = 0x00001D1E + */ + wf_ioremap_read(WF_ROM_CODE_INDEX_ADDR, &value); + check = 0; + polling_count = 0; + while (value != CONNSYS_ROM_DONE_CHECK) { + if (polling_count > 100) { + check = -1; + ret = -1; + break; + } + udelay(1000); + wf_ioremap_read(WF_ROM_CODE_INDEX_ADDR, &value); + polling_count++; + } + if (check != 0) { + soc3_0_DumpWfsysInfo(); + soc3_0_DumpPwrStatedebuglog(); + soc3_0_DumpWfsysdebugflag(); + DBGLOG(INIT, ERROR, + "Check CONNSYS power-on completion fail.\n"); + return ret; + } + + conninfra_config_setup(); + + /* bus clock ctrl */ + conninfra_bus_clock_ctrl(CONNDRV_TYPE_WIFI, CONNINFRA_BUS_CLOCK_ALL, 0); + + /* Disable conn_infra off domain force on 0x180601A4[0] = 1'b0 */ + wf_ioremap_read(CONN_INFRA_WAKEUP_WF_ADDR, &value); + value &= 0xFFFFFFFE; + wf_ioremap_write(CONN_INFRA_WAKEUP_WF_ADDR, value); + DBGLOG(INIT, INFO, "wmmcu power-on done.\n"); + return ret; +} + +int wf_pwr_off_consys_mcu(void) +{ +#define MAX_WAIT_COREDUMP_COUNT 10 + + int check; + int value = 0; + int ret = 0; + int conninfra_hang_ret = 0; + int polling_count; + int retryCount = 0; + +#if (CFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT == 1) + while (g_IsNeedWaitCoredump) { + kalMsleep(100); + retryCount++; + if (retryCount >= MAX_WAIT_COREDUMP_COUNT) { + DBGLOG(INIT, WARN, + "Coredump spend long time, retryCount = %d\n", + retryCount); + } + } +#endif + + DBGLOG(INIT, INFO, "wmmcu power-off start.\n"); + /* Wakeup conn_infra off write 0x180601A4[0] = 1'b1 */ + wf_ioremap_read(CONN_INFRA_WAKEUP_WF_ADDR, &value); + value |= 0x00000001; + wf_ioremap_write(CONN_INFRA_WAKEUP_WF_ADDR, value); + + /* Check AP2CONN slpprot ready + * (polling "10 times" and each polling interval is "1ms") + * Address: 0x1806_0184[5] + * Data: 1'b0 + * Action: polling + */ + wf_ioremap_read(CONN_INFRA_ON2OFF_SLP_PROT_ACK_ADDR, &value); + check = 0; + polling_count = 0; + while ((value & 0x00000020) != 0) { + if (polling_count > 10) { + check = -1; + ret = -1; + break; + } + udelay(1000); + wf_ioremap_read(CONN_INFRA_ON2OFF_SLP_PROT_ACK_ADDR, &value); + polling_count++; + } + if (check != 0) { + DBGLOG(INIT, ERROR, "Polling AP2CONN slpprot ready fail.\n"); + return ret; + } + + if (!conninfra_reg_readable()) { + DBGLOG(HAL, ERROR, + "conninfra_reg_readable fail\n"); + + conninfra_hang_ret = conninfra_is_bus_hang(); + + if (conninfra_hang_ret > 0) { + + DBGLOG(HAL, ERROR, + "conninfra_is_bus_hang, Chip reset\n"); + } + return -1; + } + + /* Check CONNSYS version ID + * (polling "10 times" and each polling interval is "1ms") + * Address: 0x1800_1000[31:0] + * Data: 0x2001_0000 + * Action: polling + */ + wf_ioremap_read(CONN_HW_VER_ADDR, &value); + check = 0; + polling_count = 0; + while (value != kalGetConnsysVerId()) { + if (polling_count > 10) { + check = -1; + ret = -1; + break; + } + udelay(1000); + wf_ioremap_read(CONN_HW_VER_ADDR, &value); + polling_count++; + } + if (check != 0) { + DBGLOG(INIT, ERROR, "Polling CONNSYS version ID fail.\n"); + return ret; + } + + /* mask wf2conn slpprot idle + * 0x1800F004[0] = 1'b1 + */ + wf_ioremap_read(WF2CONN_SLPPROT_IDLE_ADDR, &value); + value |= 0x00000001; + wf_ioremap_write(WF2CONN_SLPPROT_IDLE_ADDR, value); + + /* Turn on "conn_infra to wfsys"/ wfsys to conn_infra" bus sleep protect + * 0x18001620[0] = 1'b1 + */ + wf_ioremap_read(CONN_INFRA_WF_SLP_CTRL_R_ADDR, &value); + value |= 0x00000001; + wf_ioremap_write(CONN_INFRA_WF_SLP_CTRL_R_ADDR, value); + + /* Polling WF_SLP_CTRL ready + * (polling "100 times" and each polling interval is "0.5ms") + * Address: 0x1800_1620[3] (CONN_INFRA_WF_SLP_CTRL_R_OFFSET[3]) + * Data: 1'b1 + * Action: polling + */ + wf_ioremap_read(CONN_INFRA_WF_SLP_CTRL_R_ADDR, &value); + check = 0; + polling_count = 0; + while ((value & 0x00000008) == 0) { + if (polling_count > 100) { + check = -1; + ret = -1; + break; + } + udelay(500); + wf_ioremap_read(CONN_INFRA_WF_SLP_CTRL_R_ADDR, &value); + polling_count++; + DBGLOG(INIT, ERROR, "WF_SLP_CTRL (0x%x) (%d)\n", + value, + polling_count); + } + if (check != 0) { + DBGLOG(INIT, ERROR, + "Polling WFSYS TO CONNINFRA SLEEP PROTECT fail. (0x%x)\n", + value); + soc3_0_DumpWfsysInfo(); + soc3_0_DumpWfsysdebugflag(); + } + /* Turn off "wf_dma to conn_infra" bus sleep protect + * 0x18001624[0] = 1'b1 + */ + wf_ioremap_read(CONN_INFRA_WFDMA_SLP_CTRL_R_ADDR, &value); + value |= 0x00000001; + wf_ioremap_write(CONN_INFRA_WFDMA_SLP_CTRL_R_ADDR, value); + + /* Polling wfsys_rgu_off_hreset_rst_b + * (polling "100 times" and each polling interval is "0.5ms") + * Address: 0x1800_1624[3] (CONN_INFRA_WFDMA_SLP_CTRL_R_OFFSET[3]) + * Data: 1'b1 + * Action: polling + */ + wf_ioremap_read(CONN_INFRA_WFDMA_SLP_CTRL_R_ADDR, &value); + check = 0; + polling_count = 0; + while ((value & 0x00000008) == 0) { + if (polling_count > 100) { + check = -1; + ret = -1; + break; + } + udelay(500); + wf_ioremap_read(CONN_INFRA_WFDMA_SLP_CTRL_R_ADDR, &value); + polling_count++; + DBGLOG(INIT, ERROR, "WFDMA_SLP_CTRL (0x%x) (%d)\n", + value, + polling_count); + } + if (check != 0) { + DBGLOG(INIT, ERROR, + "Polling WFDMA TO CONNINFRA SLEEP PROTECT RDY fail. (0x%x)\n", + value); + soc3_0_DumpWfsysInfo(); + soc3_0_DumpWfsysdebugflag(); + } + + /* Reset WFSYS semaphore 0x18000018[0] = 1'b0 */ + wf_ioremap_read(WFSYS_SW_RST_B_ADDR, &value); + value &= 0xFFFFFFFE; + wf_ioremap_write(WFSYS_SW_RST_B_ADDR, value); + + /* bus clock ctrl */ + conninfra_bus_clock_ctrl(CONNDRV_TYPE_WIFI, CONNINFRA_BUS_CLOCK_ALL, 0); + + /* Turn off wfsys_top_on + * 0x18000000[31:16] = 0x57460000, + * 0x18000000[7] = 1'b0 + */ + wf_ioremap_read(WFSYS_ON_TOP_PWR_CTL_ADDR, &value); + value &= 0x0000FF7F; + value |= 0x57460000; + wf_ioremap_write(WFSYS_ON_TOP_PWR_CTL_ADDR, value); + /* Polling wfsys_rgu_off_hreset_rst_b + * (polling "10 times" and each polling interval is "0.5ms") + * Address: 0x1806_02CC[2] (TOP_DBG_DUMMY_3_CONNSYS_PWR_STATUS[2]) + * Data: 1'b0 + * Action: polling + */ + + wf_ioremap_read(TOP_DBG_DUMMY_3_CONNSYS_PWR_STATUS_ADDR, &value); + check = 0; + polling_count = 0; + while ((value & 0x00000004) != 0) { + if (polling_count > 10) { + check = -1; + ret = -1; + break; + } + udelay(500); + wf_ioremap_read(TOP_DBG_DUMMY_3_CONNSYS_PWR_STATUS_ADDR, + &value); + polling_count++; + } + if (check != 0) { + DBGLOG(INIT, ERROR, + "Polling wfsys rgu off fail. (0x%x)\n", + value); + return ret; + } + + /* unmask wf2conn slpprot idle + * 0x1800F004[0] = 1'b0 + */ + wf_ioremap_read(WF2CONN_SLPPROT_IDLE_ADDR, &value); + value &= 0xFFFFFFFE; + wf_ioremap_write(WF2CONN_SLPPROT_IDLE_ADDR, value); + + /* Toggle WFSYS EMI request 0x18001c14[0] = 1'b1 -> 1'b0 */ + wf_ioremap_read(CONN_INFRA_WFSYS_EMI_REQ_ADDR, &value); + value |= 0x00000001; + wf_ioremap_write(CONN_INFRA_WFSYS_EMI_REQ_ADDR, value); + value &= 0xFFFFFFFE; + wf_ioremap_write(CONN_INFRA_WFSYS_EMI_REQ_ADDR, value); + + /*Disable A-die top_ck_en (use common API)(clear driver & FW resource)*/ + conninfra_adie_top_ck_en_off(CONNSYS_ADIE_CTL_FW_WIFI); + + soc3_0_DumpBusHangdebuglog(); + /* Disable conn_infra off domain force on 0x180601A4[0] = 1'b0 */ + wf_ioremap_read(CONN_INFRA_WAKEUP_WF_ADDR, &value); + value &= 0xFFFFFFFE; + wf_ioremap_write(CONN_INFRA_WAKEUP_WF_ADDR, value); + return ret; +} + +int hifWmmcuPwrOn(void) +{ + int ret = 0; + uint32_t u4Value = 0; + +#if (CFG_SUPPORT_CONNINFRA == 1) + /* conninfra power on */ + if (!kalIsWholeChipResetting()) { + ret = conninfra_pwr_on(CONNDRV_TYPE_WIFI); + if (ret == CONNINFRA_ERR_RST_ONGOING) { + DBGLOG(INIT, ERROR, + "Conninfra is doing whole chip reset.\n"); + return ret; + } + if (ret != 0) { + DBGLOG(INIT, ERROR, + "Conninfra pwr on fail.\n"); + return ret; + } + } +#endif + /* wf driver power on */ + ret = wf_pwr_on_consys_mcu(); + if (ret != 0) + return ret; + + /* set FW own after power on consys mcu to + * keep Driver/FW/HW state sync + */ + wf_ioremap_read(CONN_HOST_CSR_TOP_BASE_ADDR + 0x0010, + &u4Value); + + if ((u4Value & BIT(2)) != BIT(2)) { + DBGLOG(INIT, INFO, "0x%08x = 0x%08x, Set FW Own\n", + CONN_HOST_CSR_TOP_BASE_ADDR + 0x0010, + u4Value); + + wf_ioremap_write(CONN_HOST_CSR_TOP_BASE_ADDR + 0x0010, + PCIE_LPCR_HOST_SET_OWN); + } + + DBGLOG(INIT, INFO, + "hifWmmcuPwrOn done\n"); + + return ret; +} + +void wlanCoAntVFE28En(IN struct ADAPTER *prAdapter) +{ + struct WIFI_CFG_PARAM_STRUCT *prNvramSettings; + struct REG_INFO *prRegInfo; + u_int8_t fgCoAnt; + + if (g_NvramFsm != NVRAM_STATE_READY) { + DBGLOG(INIT, INFO, "CoAntVFE28 NVRAM Not ready\n"); + return; + } + + ASSERT(prAdapter); + prRegInfo = &prAdapter->prGlueInfo->rRegInfo; + ASSERT(prRegInfo); + prNvramSettings = prRegInfo->prNvramSettings; + ASSERT(prNvramSettings); + + fgCoAnt = prNvramSettings->ucSupportCoAnt; + + if (fgCoAnt) { + if (gCoAntVFE28En == FALSE) { +#if (KERNEL_VERSION(4, 15, 0) <= CFG80211_VERSION_CODE) + regmap_write(g_regmap, + MT6359_LDO_VFE28_OP_EN_SET, 0x1 << 8); + regmap_write(g_regmap, + MT6359_LDO_VFE28_OP_CFG_CLR, 0x1 << 8); +#else + KERNEL_pmic_ldo_vfe28_lp(8, 0, 1, 0); +#endif + DBGLOG(INIT, INFO, "CoAntVFE28 PMIC Enable\n"); + gCoAntVFE28En = TRUE; + } else { + DBGLOG(INIT, INFO, "CoAntVFE28 PMIC Already Enable\n"); + } + } else { + DBGLOG(INIT, INFO, "Not Support CoAnt Enable\n"); + } +} + +void wlanCoAntVFE28Dis(void) +{ + if (gCoAntVFE28En == TRUE) { +#if (KERNEL_VERSION(4, 15, 0) <= CFG80211_VERSION_CODE) + regmap_write(g_regmap, MT6359_LDO_VFE28_OP_EN_CLR, 0x1 << 8); + regmap_write(g_regmap, MT6359_LDO_VFE28_OP_CFG_CLR, 0x1 << 8); + regmap_write(g_regmap, MT6359_LDO_VFE28_OP_CFG_CLR, 0x1 << 8); +#else + KERNEL_pmic_ldo_vfe28_lp(8, 0, 0, 0); +#endif + DBGLOG(INIT, INFO, "CoAntVFE28 PMIC Disable\n"); + gCoAntVFE28En = FALSE; + } else { + DBGLOG(INIT, INFO, "CoAntVFE28 PMIC Already Disable\n"); + } +} + +void wlanCoAntWiFi(void) +{ + u_int32 u4GPIO10 = 0x0; + + wf_ioremap_read(0x100053a0, &u4GPIO10); + u4GPIO10 |= 0x20000; + wf_ioremap_write(0x100053a0, u4GPIO10); + +} + +void wlanCoAntMD(void) +{ + u_int32 u4GPIO10 = 0x0; + + wf_ioremap_read(0x100053a0, &u4GPIO10); + u4GPIO10 |= 0x10000; + wf_ioremap_write(0x100053a0, u4GPIO10); + +} + + +#if (CFG_SUPPORT_CONNINFRA == 1) +int wlanConnacPccifon(void) +{ + int ret = 0; + + /*reset WiFi power on status to MD*/ + wf_ioremap_write(0x10003314, 0x00); + /*set WiFi power on status to MD*/ + wf_ioremap_write(0x10003314, 0x01); + /* + *Ccif4 (ccif_md2conn_wf): + *write cg gate 0x1000_10C0[28] & [29] (write 1 set) + *write cg gate 0x1000_10C4[28] & [29] (write 1 clear) + *Connsys/AP is used bit 28,md is used bit 29 + *default value is 0,clk enable + *Set cg must set both bit[28] [29], and clk turn off + *Clr cg set either bit[28][29], and clk turn on + + *Enable PCCIF4 clock + *HW auto control, so no need to turn on or turn off + *wf_ioremap_read(0x100010c4, ®); + *reg |= BIT(28); + *ret = wf_ioremap_write(0x100010c4,reg); + */ + return ret; +} + +int wlanConnacPccifoff(void) +{ + int ret = 0; + + /*reset WiFi power on status to MD*/ + ret = wf_ioremap_write(0x10003314, 0x00); + /*reset WiFi power on status to MD*/ + ret = wf_ioremap_write(0x1024c014, 0x0ff); + + /* + *Ccif4 (ccif_md2conn_wf): + *write cg gate 0x1000_10C0[28] & [29] (write 1 set) + *write cg gate 0x1000_10C4[28] & [29] (write 1 clear) + *Connsys/AP is used bit 28, md is used bit 29 + *default value is 0, clk enable + *Set cg must set both bit[28] [29], and clk turn off + *Clr cg set either bit[28][29], and clk turn on + + *Disable PCCIF4 clock + *HW auto control, so no need to turn on or turn off + *wf_ioremap_read(0x100010c0, ®); + *reg |= BIT(28); + *ret = wf_ioremap_write(0x100010c0,reg); + */ + return ret; +} +#endif + +int hifWmmcuPwrOff(void) +{ + int ret = 0; + /* wf driver power off */ + ret = wf_pwr_off_consys_mcu(); + if (ret != 0) + return ret; +#if (CFG_SUPPORT_CONNINFRA == 1) + /* + * conninfra power off sequence + * conninfra will do conninfra power off self during whole chip reset. + */ + if (!kalIsWholeChipResetting()) { + ret = conninfra_pwr_off(CONNDRV_TYPE_WIFI); + if (ret != 0) + return ret; + } +#endif + return ret; +} +#if (CFG_SUPPORT_CONNINFRA == 1) +int soc3_0_Trigger_whole_chip_rst(char *reason) +{ + return conninfra_trigger_whole_chip_rst(CONNDRV_TYPE_WIFI, reason); +} +void soc3_0_Sw_interrupt_handler(struct ADAPTER *prAdapter) +{ + int value = 0; + struct GL_HIF_INFO *prHifInfo = NULL; + + ASSERT(prAdapter); + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + if (!conninfra_reg_readable_no_lock()) { + DBGLOG(HAL, ERROR, + "conninfra_reg_readable fail\n"); + disable_irq_nosync(prHifInfo->u4IrqId_1); +#if (CFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT == 1) + g_eWfRstSource = WF_RST_SOURCE_FW; + if (!prAdapter->prGlueInfo->u4ReadyFlag) + g_IsNeedWaitCoredump = TRUE; +#endif + DBGLOG(HAL, ERROR, + "FW trigger assert(0x%x).\n", value); + fgIsResetting = TRUE; + update_driver_reset_status(fgIsResetting); + kalSetRstEvent(); + return; + } + HAL_MCR_WR(prAdapter, + CONN_INFRA_CFG_AP2WF_REMAP_1_ADDR, + CONN_MCU_CONFG_HS_BASE); + HAL_MCR_RD(prAdapter, + (CONN_INFRA_CFG_AP2WF_BUS_ADDR + 0xc0), + &value); + + DBGLOG(HAL, TRACE, "SW INT happened!!!!!(0x%x)\n", value); + HAL_MCR_WR(prAdapter, + (CONN_INFRA_CFG_AP2WF_BUS_ADDR + 0xc8), + value); + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + if (value & BIT(0)) + fw_log_wifi_irq_handler(); +#endif + + if (value & BIT(1)) { + if (kalIsResetting()) { +#if (CFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT == 1) + g_eWfRstSource = WF_RST_SOURCE_DRIVER; + if (!prAdapter->prGlueInfo->u4ReadyFlag) + g_IsNeedWaitCoredump = TRUE; +#endif + DBGLOG(HAL, ERROR, + "Wi-Fi Driver trigger, need do complete(0x%x).\n", + value); + complete(&g_triggerComp); + } else { +#if (CFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT == 1) + g_eWfRstSource = WF_RST_SOURCE_FW; + if (!prAdapter->prGlueInfo->u4ReadyFlag) + g_IsNeedWaitCoredump = TRUE; +#endif + DBGLOG(HAL, ERROR, + "FW trigger assert(0x%x).\n", value); + fgIsResetting = TRUE; + update_driver_reset_status(fgIsResetting); + kalSetRstEvent(); + } + } + if (value & BIT(2)) { +#if (CFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT == 1) + g_eWfRstSource = WF_RST_SOURCE_FW; + if (!prAdapter->prGlueInfo->u4ReadyFlag) + g_IsNeedWaitCoredump = TRUE; +#endif + DBGLOG(HAL, ERROR, + "FW trigger whole chip reset(0x%x).\n", value); + fgIsResetting = TRUE; + update_driver_reset_status(fgIsResetting); + g_IsWfsysBusHang = TRUE; + kalSetRstEvent(); + } + if (value & BIT(3)) { +#if (CFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT == 1) + g_eWfRstSource = WF_RST_SOURCE_FW; + if (!prAdapter->prGlueInfo->u4ReadyFlag) + g_IsNeedWaitCoredump = TRUE; +#endif + g_fgRstRecover = TRUE; + fgIsResetting = TRUE; + update_driver_reset_status(fgIsResetting); + kalSetRstEvent(); + } +} + +void soc3_0_Conninfra_cb_register(void) +{ + g_conninfra_wf_cb.rst_cb.pre_whole_chip_rst = + glRstwlanPreWholeChipReset; + g_conninfra_wf_cb.rst_cb.post_whole_chip_rst = + glRstwlanPostWholeChipReset; + +#if (CFG_SUPPORT_PRE_ON_PHY_ACTION == 1) + /* Register conninfra call back */ + g_conninfra_wf_cb.pre_cal_cb.pwr_on_cb = soc3_0_wlanPreCalPwrOn; + g_conninfra_wf_cb.pre_cal_cb.do_cal_cb = soc3_0_wlanPreCal; + update_pre_cal_status(0); +#endif /* (CFG_SUPPORT_PRE_ON_PHY_ACTION == 1) */ + + conninfra_sub_drv_ops_register(CONNDRV_TYPE_WIFI, + &g_conninfra_wf_cb); +} +#endif +void soc3_0_icapRiseVcoreClockRate(void) +{ + + + int value = 0; + + /*2 update Clork Rate*/ + /*0x1000123C[20]=1,218Mhz*/ + wf_ioremap_read(WF_CONN_INFA_BUS_CLOCK_RATE, &value); + value |= 0x00010000; + wf_ioremap_write(WF_CONN_INFA_BUS_CLOCK_RATE, value); +#if (CFG_SUPPORT_VCODE_VDFS == 1) + /*Enable VCore to 0.725*/ + + /*init*/ + if (!pm_qos_request_active(&wifi_req)) + pm_qos_add_request(&wifi_req, PM_QOS_VCORE_OPP, + PM_QOS_VCORE_OPP_DEFAULT_VALUE); + + /*update Vcore*/ + pm_qos_update_request(&wifi_req, 0); + + DBGLOG(HAL, STATE, "icapRiseVcoreClockRate done\n"); +#else + DBGLOG(HAL, STATE, "icapRiseVcoreClockRate skip\n"); +#endif /*#ifndef CFG_BUILD_X86_PLATFORM*/ +} + +void soc3_0_icapDownVcoreClockRate(void) +{ + + + int value = 0; + + /*2 update Clork Rate*/ + /*0x1000123C[20]=0,156Mhz*/ + wf_ioremap_read(WF_CONN_INFA_BUS_CLOCK_RATE, &value); + value &= ~(0x00010000); + wf_ioremap_write(WF_CONN_INFA_BUS_CLOCK_RATE, value); +#if (CFG_SUPPORT_VCODE_VDFS == 1) + + /*init*/ + if (!pm_qos_request_active(&wifi_req)) + pm_qos_add_request(&wifi_req, PM_QOS_VCORE_OPP, + PM_QOS_VCORE_OPP_DEFAULT_VALUE); + + /*restore to default Vcore*/ + pm_qos_update_request(&wifi_req, + PM_QOS_VCORE_OPP_DEFAULT_VALUE); + + /*disable VCore to normal setting*/ + DBGLOG(HAL, STATE, "icapDownVcoreClockRate done!\n"); +#else + DBGLOG(HAL, STATE, "icapDownVcoreClockRate skip\n"); + +#endif /*#ifndef CFG_BUILD_X86_PLATFORM*/ + +} + +#if (CFG_POWER_ON_DOWNLOAD_EMI_ROM_PATCH == 1) +#pragma message("SOC3_0::CFG_POWER_ON_DOWNLOAD_EMI_ROM_PATCH == 1") +void soc3_0_ConstructFirmwarePrio(struct GLUE_INFO *prGlueInfo, + uint8_t **apucNameTable, uint8_t **apucName, + uint8_t *pucNameIdx, uint8_t ucMaxNameIdx) +{ + int ret = 0; + uint8_t ucIdx = 0; + uint8_t aucFlavor[2] = {0}; + + kalGetFwFlavor(&aucFlavor[0]); + + for (ucIdx = 0; apucsoc3_0FwName[ucIdx]; ucIdx++) { + if ((*pucNameIdx + 3) >= ucMaxNameIdx) { + /* the table is not large enough */ + DBGLOG(INIT, ERROR, + "kalFirmwareImageMapping >> file name array is not enough.\n"); + ASSERT(0); + continue; + } + + /* Type 1. WIFI_RAM_CODE_soc1_0_1_1 */ + ret = kalSnprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s_%u%s_%u", + apucsoc3_0FwName[ucIdx], + CFG_WIFI_IP_SET, + aucFlavor, + wlanGetEcoVersion( + prGlueInfo->prAdapter)); + if (ret >= 0 && ret < CFG_FW_NAME_MAX_LEN) + (*pucNameIdx) += 1; + else + DBGLOG(INIT, ERROR, + "[%u] kalSnprintf failed, ret: %d\n", + __LINE__, ret); + + /* Type 2. WIFI_RAM_CODE_soc1_0_1_1.bin */ + ret = kalSnprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s_%u%s_%u.bin", + apucsoc3_0FwName[ucIdx], + CFG_WIFI_IP_SET, + aucFlavor, + wlanGetEcoVersion( + prGlueInfo->prAdapter)); + if (ret >= 0 && ret < CFG_FW_NAME_MAX_LEN) + (*pucNameIdx) += 1; + else + DBGLOG(INIT, ERROR, + "[%u] kalSnprintf failed, ret: %d\n", + __LINE__, ret); + + /* Type 3. WIFI_RAM_CODE_soc1_0 */ + ret = kalSnprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s", + apucsoc3_0FwName[ucIdx]); + if (ret >= 0 && ret < CFG_FW_NAME_MAX_LEN) + (*pucNameIdx) += 1; + else + DBGLOG(INIT, ERROR, + "[%u] kalSnprintf failed, ret: %d\n", + __LINE__, ret); + + /* Type 4. WIFI_RAM_CODE_soc1_0.bin */ + ret = kalSnprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s.bin", + apucsoc3_0FwName[ucIdx]); + if (ret >= 0 && ret < CFG_FW_NAME_MAX_LEN) + (*pucNameIdx) += 1; + else + DBGLOG(INIT, ERROR, + "[%u] kalSnprintf failed, ret: %d\n", + __LINE__, ret); + } +} + +void * +soc3_0_kalFirmwareImageMapping( + IN struct GLUE_INFO *prGlueInfo, + OUT void **ppvMapFileBuf, + OUT uint32_t *pu4FileLength, + IN enum ENUM_IMG_DL_IDX_T eDlIdx) +{ + uint8_t **apucNameTable = NULL; + uint8_t *apucName[SOC3_0_FILE_NAME_TOTAL + + 1]; /* extra +1, for the purpose of + * detecting the end of the array + */ + uint8_t idx = 0, max_idx, + aucNameBody[SOC3_0_FILE_NAME_TOTAL][SOC3_0_FILE_NAME_MAX], + sub_idx = 0; + struct mt66xx_chip_info *prChipInfo = + prGlueInfo->prAdapter->chip_info; + /* uint32_t chip_id = prChipInfo->chip_id; */ + uint8_t aucFlavor[2] = {0}; + + DEBUGFUNC("kalFirmwareImageMapping"); + + ASSERT(prGlueInfo); + ASSERT(ppvMapFileBuf); + ASSERT(pu4FileLength); + + *ppvMapFileBuf = NULL; + *pu4FileLength = 0; + kalGetFwFlavor(&aucFlavor[0]); + + do { + /* <0.0> Get FW name prefix table */ + switch (eDlIdx) { + case IMG_DL_IDX_N9_FW: + apucNameTable = soc3_0_apucFwName; + break; + + case IMG_DL_IDX_CR4_FW: + apucNameTable = soc3_0_apucCr4FwName; + break; + + case IMG_DL_IDX_PATCH: + break; + + case IMG_DL_IDX_MCU_ROM_EMI: + break; + + case IMG_DL_IDX_WIFI_ROM_EMI: + break; + + default: + ASSERT(0); + break; + } + + /* <0.2> Construct FW name */ + memset(apucName, 0, sizeof(apucName)); + + /* magic number 1: reservation for detection + * of the end of the array + */ + max_idx = (sizeof(apucName) / sizeof(uint8_t *)) - 1; + + idx = 0; + apucName[idx] = (uint8_t *)(aucNameBody + idx); + + if (eDlIdx == IMG_DL_IDX_PATCH) { + /* construct the file name for patch */ + /* soc3_0_patch_wmmcu_1_1_hdr.bin */ + if (prChipInfo->fw_dl_ops->constructPatchName) + prChipInfo->fw_dl_ops->constructPatchName( + prGlueInfo, apucName, &idx); + else + kalSnprintf(apucName[idx], SOC3_0_FILE_NAME_MAX, + "soc3_0_patch_wmmcu_1_%x_hdr.bin", + wlanGetEcoVersion( + prGlueInfo->prAdapter)); + idx += 1; + } else if (eDlIdx == IMG_DL_IDX_MCU_ROM_EMI) { + /* construct the file name for MCU ROM EMI */ + /* soc3_0_ram_wmmcu_1_1_hdr.bin */ + kalSnprintf(apucName[idx], SOC3_0_FILE_NAME_MAX, + "soc3_0_ram_wmmcu_%u%s_%x_hdr.bin", + CFG_WIFI_IP_SET, + aucFlavor, + wlanGetEcoVersion( + prGlueInfo->prAdapter)); + + idx += 1; + } else if (eDlIdx == IMG_DL_IDX_WIFI_ROM_EMI) { + /* construct the file name for WiFi ROM EMI */ + /* soc3_0_ram_wifi_1_1_hdr.bin */ + kalSnprintf(apucName[idx], SOC3_0_FILE_NAME_MAX, + "soc3_0_ram_wifi_%u%s_%x_hdr.bin", + CFG_WIFI_IP_SET, + aucFlavor, + wlanGetEcoVersion( + prGlueInfo->prAdapter)); + + idx += 1; + } else { + for (sub_idx = 0; sub_idx < max_idx; sub_idx++) + apucName[sub_idx] = + (uint8_t *)(aucNameBody + sub_idx); + + if (prChipInfo->fw_dl_ops->constructFirmwarePrio) + prChipInfo->fw_dl_ops->constructFirmwarePrio( + prGlueInfo, apucNameTable, apucName, + &idx, max_idx); + else + kalConstructDefaultFirmwarePrio( + prGlueInfo, apucNameTable, apucName, + &idx, max_idx); + } + + /* let the last pointer point to NULL + * so that we can detect the end of the array in + * kalFirmwareOpen(). + */ + apucName[idx] = NULL; + + apucNameTable = apucName; + + /* <1> Open firmware */ + if (kalFirmwareOpen(prGlueInfo, + apucNameTable) != WLAN_STATUS_SUCCESS) + break; + { + uint32_t u4FwSize = 0; + void *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; +} + +uint32_t soc3_0_wlanImageSectionDownloadStage( + IN struct ADAPTER *prAdapter, IN void *pvFwImageMapFile, + IN uint32_t u4FwImageFileLength, IN uint8_t ucSectionNumber, + IN enum ENUM_IMG_DL_IDX_T eDlIdx) +{ + uint32_t u4SecIdx, u4Offset = 0; + uint32_t u4Addr, u4Len, u4DataMode = 0; + u_int8_t fgIsEMIDownload = FALSE; + u_int8_t fgIsNotDownload = FALSE; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + struct patch_dl_target target; + struct PATCH_FORMAT_T *prPatchHeader; + struct ROM_EMI_HEADER *prRomEmiHeader; + struct FWDL_OPS_T *prFwDlOps; + + prFwDlOps = prChipInfo->fw_dl_ops; + + /* 3a. parse file header for decision of + * divided firmware download or not + */ + if (eDlIdx == IMG_DL_IDX_PATCH) { + prPatchHeader = pvFwImageMapFile; + if (prPatchHeader->u4PatchVersion == PATCH_VERSION_MAGIC_NUM) { + wlanImageSectionGetPatchInfoV2(prAdapter, + pvFwImageMapFile, + u4FwImageFileLength, + &u4DataMode, + &target); + DBGLOG(INIT, INFO, + "FormatV2 num_of_regoin[%d] datamode[0x%08x]\n", + target.num_of_region, u4DataMode); + } else { + wlanImageSectionGetPatchInfo(prAdapter, + pvFwImageMapFile, + u4FwImageFileLength, + &u4Offset, &u4Addr, + &u4Len, &u4DataMode); + DBGLOG(INIT, INFO, + "FormatV1 DL Offset[%u] addr[0x%08x] len[%u] datamode[0x%08x]\n", + u4Offset, u4Addr, u4Len, u4DataMode); + } + + if (prPatchHeader->u4PatchVersion == PATCH_VERSION_MAGIC_NUM) + u4Status = wlanDownloadSectionV2(prAdapter, + u4DataMode, eDlIdx, &target); + else +/* For dynamic memory map::Begin */ +#if (CFG_DOWNLOAD_DYN_MEMORY_MAP == 1) + u4Status = prFwDlOps->downloadByDynMemMap( + prAdapter, u4Addr, u4Len, + pvFwImageMapFile + + u4Offset, + eDlIdx); +#else + u4Status = wlanDownloadSection( + prAdapter, + u4Addr, + u4Len, + u4DataMode, + pvFwImageMapFile + + u4Offset, + eDlIdx); +#endif +/* For dynamic memory map::End */ +#if (CFG_SUPPORT_CONNINFRA == 1) + /* Set datecode to EMI */ + wlanDownloadEMISection(prAdapter, + WMMCU_ROM_PATCH_DATE_ADDR, + DATE_CODE_SIZE, prPatchHeader->aucBuildDate); +#endif + + } else if ((eDlIdx == IMG_DL_IDX_MCU_ROM_EMI) || + (eDlIdx == IMG_DL_IDX_WIFI_ROM_EMI)) { + prRomEmiHeader = (struct ROM_EMI_HEADER *)pvFwImageMapFile; + + DBGLOG(INIT, INFO, + "DL %s ROM EMI %s\n", + (eDlIdx == IMG_DL_IDX_MCU_ROM_EMI) ? + "MCU":"WiFi", + (char *)prRomEmiHeader->ucDateTime); + + u4Addr = prRomEmiHeader->u4PatchAddr; + + u4Len = u4FwImageFileLength - sizeof(struct ROM_EMI_HEADER); + + u4Offset = sizeof(struct ROM_EMI_HEADER); + + u4Status = wlanDownloadEMISection(prAdapter, + u4Addr, u4Len, + pvFwImageMapFile + u4Offset); +#if (CFG_SUPPORT_CONNINFRA == 1) + /* Set datecode to EMI */ + if (eDlIdx == IMG_DL_IDX_MCU_ROM_EMI) + wlanDownloadEMISection(prAdapter, + WMMCU_MCU_ROM_EMI_DATE_ADDR, + DATE_CODE_SIZE, prRomEmiHeader->ucDateTime); + else + wlanDownloadEMISection(prAdapter, + WMMCU_WIFI_ROM_EMI_DATE_ADDR, + DATE_CODE_SIZE, prRomEmiHeader->ucDateTime); +#endif + } else { + for (u4SecIdx = 0; u4SecIdx < ucSectionNumber; + u4SecIdx++, u4Offset += u4Len) { + prChipInfo->fw_dl_ops->getFwInfo(prAdapter, u4SecIdx, + eDlIdx, &u4Addr, + &u4Len, &u4DataMode, &fgIsEMIDownload, + &fgIsNotDownload); + + DBGLOG(INIT, INFO, + "DL Offset[%u] addr[0x%08x] len[%u] datamode[0x%08x]\n", + u4Offset, u4Addr, u4Len, u4DataMode); + + if (fgIsNotDownload) + continue; + else if (fgIsEMIDownload) + u4Status = wlanDownloadEMISection(prAdapter, + u4Addr, u4Len, + pvFwImageMapFile + u4Offset); +/* For dynamic memory map:: Begin */ +#if (CFG_DOWNLOAD_DYN_MEMORY_MAP == 1) + else if ((u4DataMode & + DOWNLOAD_CONFIG_ENCRYPTION_MODE) == 0) { + /* Non-encrypted F/W region, + * use dynamic memory mapping for download + */ + u4Status = prFwDlOps->downloadByDynMemMap( + prAdapter, + u4Addr, + u4Len, + pvFwImageMapFile + u4Offset, + eDlIdx); + } +#endif +/* For dynamic memory map:: End */ + else + u4Status = wlanDownloadSection(prAdapter, + u4Addr, u4Len, + u4DataMode, + pvFwImageMapFile + u4Offset, eDlIdx); + + /* escape from loop if any pending error occurs */ + if (u4Status == WLAN_STATUS_FAILURE) + break; + } + } + + return u4Status; +} + +/* WiFi power on download MCU/WiFi ROM EMI + ROM patch */ +/*----------------------------------------------------------------------------*/ +/*! + * \brief Wlan power on download function. This function prepare the job + * during power on stage: + * [1]Download MCU + WiFi ROM EMI + * [2]Download ROM patch + * + * \retval 0 Success + * \retval negative value Failed + */ +/*----------------------------------------------------------------------------*/ +uint32_t soc3_0_wlanPowerOnDownload( + IN struct ADAPTER *prAdapter, + IN uint8_t ucDownloadItem) +{ + uint32_t u4FwSize = 0; + void *prFwBuffer = NULL; + uint32_t u4Status; +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + uint8_t ucIsCompressed; +#endif + if (!prAdapter) + return WLAN_STATUS_FAILURE; + + + DBGLOG_LIMITED(INIT, INFO, + "Power on download start(%d)\n", ucDownloadItem); + + switch (ucDownloadItem) { + case ENUM_WLAN_POWER_ON_DOWNLOAD_EMI: + /* Download MCU ROM EMI*/ + soc3_0_kalFirmwareImageMapping(prAdapter->prGlueInfo, + &prFwBuffer, &u4FwSize, IMG_DL_IDX_MCU_ROM_EMI); + + if (prFwBuffer == NULL) { + DBGLOG(INIT, WARN, "FW[%u] load error!\n", + IMG_DL_IDX_MCU_ROM_EMI); + return WLAN_STATUS_FAILURE; + } + + u4Status = soc3_0_wlanImageSectionDownloadStage( + prAdapter, prFwBuffer, u4FwSize, 1, + IMG_DL_IDX_MCU_ROM_EMI); + + kalFirmwareImageUnmapping( + prAdapter->prGlueInfo, NULL, prFwBuffer); + + DBGLOG_LIMITED(INIT, INFO, "Power on download mcu ROM EMI %s\n", + (u4Status == WLAN_STATUS_SUCCESS) ? "pass" : "failed"); + + /* Download WiFi ROM EMI*/ + if (u4Status == WLAN_STATUS_SUCCESS) { + soc3_0_kalFirmwareImageMapping(prAdapter->prGlueInfo, + &prFwBuffer, &u4FwSize, + IMG_DL_IDX_WIFI_ROM_EMI); + + if (prFwBuffer == NULL) { + DBGLOG(INIT, WARN, "FW[%u] load error!\n", + IMG_DL_IDX_WIFI_ROM_EMI); + return WLAN_STATUS_FAILURE; + } + + u4Status = soc3_0_wlanImageSectionDownloadStage( + prAdapter, prFwBuffer, u4FwSize, 1, + IMG_DL_IDX_WIFI_ROM_EMI); + + kalFirmwareImageUnmapping( + prAdapter->prGlueInfo, NULL, prFwBuffer); + + DBGLOG_LIMITED(INIT, INFO, + "Power on download WiFi ROM EMI %s\n", + (u4Status == WLAN_STATUS_SUCCESS) + ? "pass" : "failed"); + } + + break; + + case ENUM_WLAN_POWER_ON_DOWNLOAD_ROM_PATCH: + prAdapter->rVerInfo.fgPatchIsDlByDrv = FALSE; + + soc3_0_kalFirmwareImageMapping(prAdapter->prGlueInfo, + &prFwBuffer, &u4FwSize, IMG_DL_IDX_PATCH); + + if (prFwBuffer == NULL) { + DBGLOG(INIT, WARN, "FW[%u] load error!\n", + IMG_DL_IDX_PATCH); + return WLAN_STATUS_FAILURE; + } + +#if (CFG_ROM_PATCH_NO_SEM_CTRL == 0) +#pragma message("ROM code supports SEM-CTRL for ROM patch download") + if (wlanPatchIsDownloaded(prAdapter)) { + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, NULL, + prFwBuffer); + DBGLOG_LIMITED(INIT, INFO, + "No need to download patch\n"); + return WLAN_STATUS_SUCCESS; + } +#else +#pragma message("ROM code supports no SEM-CTRL for ROM patch download") +#endif + + /* Patch DL */ +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + u4Status = wlanCompressedImageSectionDownloadStage( + prAdapter, prFwBuffer, u4FwSize, 1, + IMG_DL_IDX_PATCH, &ucIsCompressed, NULL); +#else + u4Status = soc3_0_wlanImageSectionDownloadStage( + prAdapter, prFwBuffer, u4FwSize, 1, IMG_DL_IDX_PATCH); +#endif + +/* Dynamic memory map::Begin */ +#if (CFG_DOWNLOAD_DYN_MEMORY_MAP == 1) + if (u4Status == WLAN_STATUS_SUCCESS) + wlanPatchDynMemMapSendComplete(prAdapter); + else if (u4Status == WLAN_STATUS_NOT_ACCEPTED) + u4Status = WLAN_STATUS_SUCCESS; /* already download*/ +#else + wlanPatchSendComplete(prAdapter); +#endif +/* Dynamic memory map::End */ + + kalFirmwareImageUnmapping( + prAdapter->prGlueInfo, NULL, prFwBuffer); + + prAdapter->rVerInfo.fgPatchIsDlByDrv = TRUE; + + break; + + default: + return WLAN_STATUS_NOT_SUPPORTED; + } + + DBGLOG_LIMITED(INIT, INFO, "Power on download end[%d].\n", u4Status); + + return u4Status; +} + +/* WiFi power on init for MCU/WiFi ROM EMI + ROM patch download */ +/*----------------------------------------------------------------------------*/ +/*! + * \brief Wlan power on init function. This function do the job in the + * power on stage, they are: + * [1]Download MCU + WiFi ROM EMI + * [2]Download ROM patch + * + * It is to simulate wlanProbe() with the minimum effort to complete + * ROM EMI + ROM patch download. + * + * \retval 0 Success + * \retval negative value Failed + */ +/*----------------------------------------------------------------------------*/ +int32_t soc3_0_wlanPowerOnInit( + enum ENUM_WLAN_POWER_ON_DOWNLOAD eDownloadItem) +{ +/* +* pvData data passed by bus driver init function +* _HIF_EHPI: NULL +* _HIF_SDIO: sdio bus driver handle +* see hifAxiProbe() for more detail... +* pfWlanProbe((void *)prPlatDev, +* (void *)prPlatDev->id_entry->driver_data) +*/ + void *pvData; + void *pvDriverData = (void *)&mt66xx_driver_data_soc3_0; + + int32_t i4Status = 0; + enum ENUM_POWER_ON_INIT_FAIL_REASON { + BUS_INIT_FAIL = 0, + NET_CREATE_FAIL, + BUS_SET_IRQ_FAIL, + ALLOC_ADAPTER_MEM_FAIL, + DRIVER_OWN_FAIL, + INIT_ADAPTER_FAIL, + INIT_HIFINFO_FAIL, + ROM_PATCH_DOWNLOAD_FAIL, + POWER_ON_INIT_DONE, + FAIL_REASON_NUM + } eFailReason; + uint32_t i = 0, j = 0; + int32_t i4DevIdx = 0; + struct wireless_dev *prWdev = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct mt66xx_chip_info *prChipInfo; + struct FWDL_OPS_T *prFwDlOps; + + DBGLOG(INIT, INFO, "wlanPowerOnInit::begin\n"); + + eFailReason = FAIL_REASON_NUM; + + do { + prChipInfo = ((struct mt66xx_hif_driver_data *)pvDriverData) + ->chip_info; + pvData = (void *)prChipInfo->pdev; + + if (eDownloadItem == ENUM_WLAN_POWER_ON_DOWNLOAD_EMI) { + if (fgSimplifyResetFlow) { + prGlueInfo = (struct GLUE_INFO *) + wiphy_priv(wlanGetWiphy()); + prAdapter = prGlueInfo->prAdapter; + + if (prChipInfo->pwrondownload) { + DBGLOG_LIMITED(INIT, INFO, + "[Wi-Fi PWR On] EMI download Start\n"); + + if (prChipInfo->pwrondownload( + prAdapter, eDownloadItem) + != WLAN_STATUS_SUCCESS) + i4Status = + -ROM_PATCH_DOWNLOAD_FAIL; + + DBGLOG_LIMITED(INIT, INFO, + "[Wi-Fi PWR On] EMI download End\n"); + } + } else { + prWdev = wlanNetCreate(pvData, pvDriverData); + + if (prWdev == NULL) { + DBGLOG(INIT, ERROR, + "[Wi-Fi PWR On] No memory for dev and its private\n"); + + i4Status = -NET_CREATE_FAIL; + } else { + /* Set the ioaddr to HIF Info */ + prGlueInfo = (struct GLUE_INFO *) + wiphy_priv(prWdev->wiphy); + + prAdapter = prGlueInfo->prAdapter; + + if (prChipInfo->pwrondownload) { + DBGLOG_LIMITED(INIT, INFO, + "[Wi-Fi PWR On] EMI download Start\n"); + + if (prChipInfo->pwrondownload( + prAdapter, eDownloadItem) + != WLAN_STATUS_SUCCESS) { + i4Status = + -ROM_PATCH_DOWNLOAD_FAIL; + } + + DBGLOG_LIMITED(INIT, INFO, + "[Wi-Fi PWR On] EMI download End\n"); + } + + wlanWakeLockUninit(prGlueInfo); + } + + wlanNetDestroy(prWdev); + } + + return i4Status; + } + + /* [1]Copy from wlanProbe()::Begin */ + /* 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 + */ + + /* Remember to call glBusRelease() in wlanPowerOnDeinit() */ + if (glBusInit(pvData) == FALSE) { + DBGLOG(INIT, ERROR, + "[Wi-Fi PWR On] glBusInit() fail\n"); + + i4Status = -EIO; + + eFailReason = BUS_INIT_FAIL; + + break; + } + +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanDebugTC4Init(); +#endif + + /* Create network device, Adapter, KalInfo, + * prDevHandler(netdev) + */ + prWdev = wlanNetCreate(pvData, pvDriverData); + + if (prWdev == NULL) { + DBGLOG(INIT, ERROR, + "[Wi-Fi PWR On] No memory for dev and its private\n"); + + i4Status = -ENOMEM; + + eFailReason = NET_CREATE_FAIL; + + break; + } + + /* Set the ioaddr to HIF Info */ + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(prWdev->wiphy); + + /* Should we need this??? to be conti... */ + gPrDev = prGlueInfo->prDevHandler; + + /* Setup IRQ */ + i4Status = glBusSetIrq(prWdev->netdev, NULL, prGlueInfo); + + if (i4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "[Wi-Fi PWR On] Set IRQ error\n"); + + eFailReason = BUS_SET_IRQ_FAIL; + + break; + } + + prGlueInfo->i4DevIdx = i4DevIdx; + + prAdapter = prGlueInfo->prAdapter; + /* [1]Copy from wlanProbe()::End */ + + /* [2]Copy from wlanProbe()->wlanOnPreAdapterStart()::Begin */ + /* Init Chip Capability */ + prChipInfo = prAdapter->chip_info; + + if (prChipInfo->asicCapInit) + prChipInfo->asicCapInit(prAdapter); + + /* Trigger the action of switching Pwr state to drv_own */ + prAdapter->fgIsFwOwn = TRUE; + + nicpmWakeUpWiFi(prAdapter); + /* [2]Copy from wlanProbe()->wlanOnPreAdapterStart()::End */ + + /* [3]Copy from + * wlanProbe() + * ->wlanAdapterStart() + * ->wlanOnPreAllocAdapterMem()::Begin + */ +#if 0 /* Sample's gen4m code base doesn't support */ + prAdapter->u4HifDbgFlag = 0; + prAdapter->u4HifChkFlag = 0; + prAdapter->u4TxHangFlag = 0; + prAdapter->u4NoMoreRfb = 0; +#endif + + prAdapter->u4OwnFailedCount = 0; + prAdapter->u4OwnFailedLogCount = 0; + +#if 0 /* Sample's gen4m code base doesn't support */ + prAdapter->fgEnHifDbgInfo = TRUE; +#endif + + /* Additional with chip reset optimize*/ + prAdapter->ucCmdSeqNum = 0; + prAdapter->u4PwrCtrlBlockCnt = 0; + + QUEUE_INITIALIZE(&(prAdapter->rPendingCmdQueue)); +#if CFG_SUPPORT_MULTITHREAD + QUEUE_INITIALIZE(&prAdapter->rTxCmdQueue); + QUEUE_INITIALIZE(&prAdapter->rTxCmdDoneQueue); +#if CFG_FIX_2_TX_PORT + QUEUE_INITIALIZE(&prAdapter->rTxP0Queue); + QUEUE_INITIALIZE(&prAdapter->rTxP1Queue); +#else + for (i = 0; i < BSS_DEFAULT_NUM; i++) + for (j = 0; j < TX_PORT_NUM; j++) + QUEUE_INITIALIZE(&prAdapter->rTxPQueue[i][j]); +#endif + QUEUE_INITIALIZE(&prAdapter->rRxQueue); + QUEUE_INITIALIZE(&prAdapter->rTxDataDoneQueue); +#endif + + /* reset fgIsBusAccessFailed */ + fgIsBusAccessFailed = FALSE; + + /* Allocate mandatory resource for TX/RX */ + if (nicAllocateAdapterMemory(prAdapter) + != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "[Wi-Fi PWR On] nicAllocateAdapterMemory Error!\n"); + + i4Status = -ENOMEM; + + eFailReason = ALLOC_ADAPTER_MEM_FAIL; +/* +*#if CFG_ENABLE_KEYWORD_EXCEPTION_MECHANISM & 0 +* mtk_wcn_wmt_assert_keyword(WMTDRV_TYPE_WIFI, +* "[Wi-Fi PWR On] nicAllocateAdapterMemory Error!"); +*#endif +*/ + break; + } + + /* should we need this? to be conti... */ + prAdapter->u4OsPacketFilter = PARAM_PACKET_FILTER_SUPPORTED; + + /* WLAN driver acquire LP own */ + DBGLOG(INIT, TRACE, "[Wi-Fi PWR On] Acquiring LP-OWN\n"); + + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + DBGLOG(INIT, TRACE, "[Wi-Fi PWR On] Acquiring LP-OWN-end\n"); + + if (prAdapter->fgIsFwOwn == TRUE) { + DBGLOG(INIT, ERROR, + "[Wi-Fi PWR On] nicpmSetDriverOwn() failed!\n"); + + eFailReason = DRIVER_OWN_FAIL; +/* +*#if CFG_ENABLE_KEYWORD_EXCEPTION_MECHANISM & 0 +* mtk_wcn_wmt_assert_keyword(WMTDRV_TYPE_WIFI, +* "[Wi-Fi PWR On] nicpmSetDriverOwn() failed!"); +*#endif +*/ + break; + } + + /* Initialize the Adapter: + * verify chipset ID, HIF init... + * the code snippet just do the copy thing + */ + if (nicInitializeAdapter(prAdapter) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "[Wi-Fi PWR On] nicInitializeAdapter failed!\n"); + + eFailReason = INIT_ADAPTER_FAIL; + + break; + } + + /* Do the post NIC init adapter: + * copy only the mandatory task + * in wlanOnPostNicInitAdapter(prAdapter, FALSE)::Begin + */ + nicInitSystemService(prAdapter, FALSE); + + /* Initialize Tx */ + nicTxInitialize(prAdapter); + + /* Initialize Rx */ + nicRxInitialize(prAdapter); + /* Do the post NIC init adapter: + * copy only the mandatory task + * in wlanOnPostNicInitAdapter(prAdapter, FALSE)::End + */ + + /* HIF SW info initialize */ + if (!halHifSwInfoInit(prAdapter)) { + DBGLOG(INIT, ERROR, + "[Wi-Fi PWR On] halHifSwInfoInit failed!\n"); + + eFailReason = INIT_HIFINFO_FAIL; + + break; + } + + /* Enable HIF cut-through to N9 mode */ + HAL_ENABLE_FWDL(prAdapter, TRUE); + + wlanSetChipEcoInfo(prAdapter); + + /* should we open it, to be conti */ + /* wlanOnPostInitHifInfo(prAdapter); */ + + /* Disable interrupt, download is done by polling mode only */ + nicDisableInterrupt(prAdapter); + + /* Initialize Tx Resource to fw download state */ + nicTxInitResetResource(prAdapter); + + /* MCU ROM EMI + + * WiFi ROM EMI + ROM patch download goes over here::Begin + */ + /* assiggned in wlanNetCreate() */ + prChipInfo = prAdapter->chip_info; + + /* It is configured in mt66xx_chip_info_connac2x2.fw_dl_ops */ + prFwDlOps = prChipInfo->fw_dl_ops; + + /* No need to check F/W ready bit, + * since we are downloading MCU ROM EMI + * + WiFi ROM EMI + ROM patch + */ + /* + *DBGLOG(INIT, INFO, + * "wlanDownloadFW:: Check ready_bits(=0x%x)\n", + * prChipInfo->sw_ready_bits); + * + *HAL_WIFI_FUNC_READY_CHECK(prAdapter, + * prChipInfo->sw_ready_bits, &fgReady); + */ + + if (prChipInfo->pwrondownload) { + HAL_ENABLE_FWDL(prAdapter, TRUE); + + DBGLOG_LIMITED(INIT, INFO, + "[Wi-Fi PWR On] download Start\n"); + + if (prChipInfo->pwrondownload(prAdapter, eDownloadItem) + != WLAN_STATUS_SUCCESS) { + eFailReason = ROM_PATCH_DOWNLOAD_FAIL; + + HAL_ENABLE_FWDL(prAdapter, FALSE); + + break; + } + + DBGLOG_LIMITED(INIT, INFO, + "[Wi-Fi PWR On] download End\n"); + + HAL_ENABLE_FWDL(prAdapter, FALSE); + } + /* MCU ROM EMI + WiFi ROM EMI + * + ROM patch download goes over here::End + */ + + eFailReason = POWER_ON_INIT_DONE; + /* [3]Copy from wlanProbe() + * ->wlanAdapterStart() + * ->wlanOnPreAllocAdapterMem()::End + */ + } while (FALSE); + + switch (eFailReason) { + case BUS_INIT_FAIL: + break; + + case NET_CREATE_FAIL: +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanDebugTC4Uninit(); /* Uninit for TC4 debug */ +#endif + + /* We should call this, although nothing is inside */ + glBusRelease(pvData); + + break; + + case BUS_SET_IRQ_FAIL: +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanDebugTC4Uninit(); /* Uninit for TC4 debug */ +#endif + + /* We should call this, although nothing is inside */ + glBusRelease(pvData); + + wlanWakeLockUninit(prGlueInfo); + + wlanNetDestroy(prWdev); + + break; + + case ALLOC_ADAPTER_MEM_FAIL: + case DRIVER_OWN_FAIL: + case INIT_ADAPTER_FAIL: + /* Should we set Onwership to F/W for advanced debug??? + * to be conti... + */ + /* nicpmSetFWOwn(prAdapter, FALSE); */ + + glBusFreeIrq(prWdev->netdev, + *((struct GLUE_INFO **)netdev_priv(prWdev->netdev))); + +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanDebugTC4Uninit(); /* Uninit for TC4 debug */ +#endif + + /* We should call this, although nothing is inside */ + glBusRelease(pvData); + + wlanWakeLockUninit(prGlueInfo); + + wlanNetDestroy(prWdev); + + break; + + case INIT_HIFINFO_FAIL: + nicRxUninitialize(prAdapter); + + nicTxRelease(prAdapter, FALSE); + + /* System Service Uninitialization */ + nicUninitSystemService(prAdapter); + + /* Should we set Onwership to F/W for advanced debug??? + * to be conti... + */ + /* nicpmSetFWOwn(prAdapter, FALSE); */ + + glBusFreeIrq(prWdev->netdev, + *((struct GLUE_INFO **)netdev_priv(prWdev->netdev))); + +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanDebugTC4Uninit(); /* Uninit for TC4 debug */ +#endif + + /* We should call this, although nothing is inside */ + glBusRelease(pvData); + + wlanWakeLockUninit(prGlueInfo); + + wlanNetDestroy(prWdev); + + break; + + case ROM_PATCH_DOWNLOAD_FAIL: + case POWER_ON_INIT_DONE: + HAL_ENABLE_FWDL(prAdapter, FALSE); + + nicRxUninitialize(prAdapter); + + nicTxRelease(prAdapter, FALSE); + + /* System Service Uninitialization */ + nicUninitSystemService(prAdapter); + + /* Should we set Onwership to F/W for advanced debug??? + * to be conti... + */ + /* nicpmSetFWOwn(prAdapter, FALSE); */ + + glBusFreeIrq(prWdev->netdev, + *((struct GLUE_INFO **)netdev_priv(prWdev->netdev))); + +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanDebugTC4Uninit(); /* Uninit for TC4 debug */ +#endif + + /* We should call this, although nothing is inside */ + glBusRelease(pvData); + + wlanWakeLockUninit(prGlueInfo); + + wlanNetDestroy(prWdev); + + break; + + default: + break; + } + + DBGLOG(INIT, INFO, "wlanPowerOnInit::end\n"); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Wlan power on deinit function. This function revert whatever + * has been altered in the + * power on stage to restore to the most original state. + * + * \param[in] void + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +/* +*static void wlanPowerOnDeinit(void) +*{ +* +*} +*/ +#endif + +#if (CFG_SUPPORT_PRE_ON_PHY_ACTION == 1) +uint32_t soc3_0_wlanAccessCalibrationEMI( + struct INIT_EVENT_PHY_ACTION_RSP *pCalEvent, + uint8_t backupEMI) +{ + uint32_t u4Status = WLAN_STATUS_FAILURE; + +#if CFG_MTK_ANDROID_EMI + uint8_t __iomem *pucEmiBaseAddr = NULL; + + conninfra_get_phy_addr( + (unsigned int *)&gConEmiPhyBase, + (unsigned int *)&gConEmiSize); + + if (!gConEmiPhyBase) { + DBGLOG(INIT, ERROR, + "gConEmiPhyBase invalid\n"); + return u4Status; + } + + request_mem_region(gConEmiPhyBase, gConEmiSize, "WIFI-EMI"); + kalSetEmiMpuProtection(gConEmiPhyBase, false); + pucEmiBaseAddr = ioremap_nocache(gConEmiPhyBase, gConEmiSize); + DBGLOG(INIT, INFO, + "backupEMI(%d),gConEmiPhyBase(0x%x),gConEmiSize(0x%X),pucEmiBaseAddr(0x%x)\n", + backupEMI, gConEmiPhyBase, gConEmiSize, pucEmiBaseAddr); + + do { + if (!pucEmiBaseAddr) { + DBGLOG(INIT, ERROR, "ioremap_nocache failed\n"); + break; + } + + if (backupEMI == TRUE) { + if (gEmiCalResult != NULL) { + kalMemFree(gEmiCalResult, + VIR_MEM_TYPE, + gEmiCalSize); + gEmiCalResult = NULL; + } + + gEmiCalOffset = pCalEvent->u4EmiAddress & + WIFI_EMI_ADDR_MASK; + gEmiCalSize = pCalEvent->u4EmiLength; + + if (gEmiCalSize == 0) { + DBGLOG(INIT, ERROR, "gEmiCalSize 0\n"); + break; + } + + gEmiCalResult = kalMemAlloc(gEmiCalSize, VIR_MEM_TYPE); + + if (gEmiCalResult == NULL) { + DBGLOG(INIT, ERROR, + "gEmiCalResult kalMemAlloc NULL\n"); + break; + } + + memcpy_fromio(gEmiCalResult, + (pucEmiBaseAddr + gEmiCalOffset), + gEmiCalSize); + + u4Status = WLAN_STATUS_SUCCESS; + break; + } + + /* else, put calibration data to EMI */ + + if (gEmiCalResult == NULL) { + DBGLOG(INIT, ERROR, "gEmiCalResult NULL\n"); + break; + } + + if (gEmiCalUseEmiData == TRUE) { + DBGLOG(INIT, INFO, "No Write back to EMI\n"); + break; + } + + memcpy_toio((pucEmiBaseAddr + gEmiCalOffset), + gEmiCalResult, + gEmiCalSize); + + u4Status = WLAN_STATUS_SUCCESS; + } while (FALSE); + + kalSetEmiMpuProtection(gConEmiPhyBase, true); + iounmap(pucEmiBaseAddr); + release_mem_region(gConEmiPhyBase, gConEmiSize); +#endif /* CFG_MTK_ANDROID_EMI */ + return u4Status; +} + +uint32_t soc3_0_wlanRcvPhyActionRsp(struct ADAPTER *prAdapter, + uint8_t ucCmdSeqNum) +{ + struct mt66xx_chip_info *prChipInfo; + uint8_t *aucBuffer; + uint32_t u4EventSize; + struct INIT_WIFI_EVENT *prInitEvent; + struct HAL_PHY_ACTION_TLV_HEADER *prPhyTlvHeader; + struct HAL_PHY_ACTION_TLV *prPhyTlv; + struct INIT_EVENT_PHY_ACTION_RSP *prPhyEvent; + uint32_t u4RxPktLength; + uint32_t u4Status = WLAN_STATUS_FAILURE; + uint8_t ucPortIdx = IMG_DL_STATUS_PORT_IDX; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + u4EventSize = prChipInfo->rxd_size + + prChipInfo->init_event_size + + sizeof(struct HAL_PHY_ACTION_TLV_HEADER) + + sizeof(struct HAL_PHY_ACTION_TLV) + + sizeof(struct INIT_EVENT_PHY_ACTION_RSP); + aucBuffer = kalMemAlloc(u4EventSize, PHY_MEM_TYPE); + if (aucBuffer == NULL) { + DBGLOG(INIT, ERROR, "kalMemAlloc failed\n"); + return WLAN_STATUS_FAILURE; + } + + do { + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + DBGLOG(INIT, ERROR, "kalIsCardRemoved failed\n"); + break; + } + + if (nicRxWaitResponse(prAdapter, ucPortIdx, + aucBuffer, u4EventSize, + &u4RxPktLength) != + WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "nicRxWaitResponse failed\n"); + break; + } + + prInitEvent = (struct INIT_WIFI_EVENT *) + (aucBuffer + prChipInfo->rxd_size); + + /* EID / SeqNum check */ + if (prInitEvent->ucEID != INIT_EVENT_ID_PHY_ACTION) { + DBGLOG(INIT, ERROR, + "INIT_EVENT_ID_PHY_ACTION failed\n"); + break; + } + + if (prInitEvent->ucSeqNum != ucCmdSeqNum) { + DBGLOG(INIT, ERROR, "ucCmdSeqNum failed\n"); + break; + } + + prPhyTlvHeader = (struct HAL_PHY_ACTION_TLV_HEADER *) + prInitEvent->aucBuffer; + + if (prPhyTlvHeader->u4MagicNum != HAL_PHY_ACTION_MAGIC_NUM) { + DBGLOG(INIT, ERROR, + "HAL_PHY_ACTION_MAGIC_NUM failed\n"); + break; + } + + prPhyTlv = + (struct HAL_PHY_ACTION_TLV *)prPhyTlvHeader->aucBuffer; + + prPhyEvent = (struct INIT_EVENT_PHY_ACTION_RSP *) + prPhyTlv->aucBuffer; + + if (prPhyTlv->u2Tag == HAL_PHY_ACTION_TAG_CAL) { + + DBGLOG(INIT, INFO, + "HAL_PHY_ACTION_TAG_CAL ucEvent[0x%x]status[0x%x]emiAddr[0x%x]emiLen[0x%x]\n", + prPhyEvent->ucEvent, + prPhyEvent->ucStatus, + prPhyEvent->u4EmiAddress, + prPhyEvent->u4EmiLength); + + if ((prPhyEvent->ucEvent == + HAL_PHY_ACTION_CAL_FORCE_CAL_RSP && + prPhyEvent->ucStatus == + HAL_PHY_ACTION_STATUS_SUCCESS) || + (prPhyEvent->ucEvent == + HAL_PHY_ACTION_CAL_USE_BACKUP_RSP && + prPhyEvent->ucStatus == + HAL_PHY_ACTION_STATUS_RECAL)) { + + /* read from EMI, backup in driver */ + soc3_0_wlanAccessCalibrationEMI(prPhyEvent, + TRUE); + } + + u4Status = WLAN_STATUS_SUCCESS; + } else if (prPhyTlv->u2Tag == HAL_PHY_ACTION_TAG_FEM) { + + DBGLOG(INIT, INFO, + "HAL_PHY_ACTION_TAG_FEM status[0x%x]\n", + prPhyEvent->ucStatus); + + u4Status = WLAN_STATUS_SUCCESS; + } + } while (FALSE); + + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + return u4Status; +} + +void soc3_0_wlanGetEpaElnaFromNvram( + uint8_t **pu1DataPointer, + uint32_t *pu4DataLen) +{ +#define MAX_NVRAM_READY_COUNT 10 + + /* ePA /eLNA */ + uint8_t index; + uint8_t u1TypeID; + uint8_t u1LenLSB; + uint8_t u1LenMSB; + uint32_t u4NvramStartOffset = 0, u4NvramOffset = 0; + uint8_t *pu1Addr; + struct WIFI_NVRAM_TAG_FORMAT *prTagDataCurr; + int retryCount = 0; + + while (g_NvramFsm != NVRAM_STATE_READY) { + kalMsleep(100); + retryCount++; + + if (retryCount > MAX_NVRAM_READY_COUNT) { + DBGLOG(INIT, WARN, "g_NvramFsm != NVRAM_STATE_READY\n"); + return; + } + } + + /* Get NVRAM Start Addr */ + pu1Addr = (uint8_t *)(struct WIFI_CFG_PARAM_STRUCT *)&g_aucNvram[0]; + + /* Shift to NVRAM Tag */ + u4NvramOffset = OFFSET_OF(struct WIFI_CFG_PARAM_STRUCT, ucTypeID0); + prTagDataCurr = + (struct WIFI_NVRAM_TAG_FORMAT *)(pu1Addr + + u4NvramOffset); + + /* Shift to NVRAM Tag 7 - 9, r2G4Cmm, r5GCmm , rSys*/ + for (index = 0; index <= 10; index++) { + u1TypeID = prTagDataCurr->u1NvramTypeID; + u1LenLSB = prTagDataCurr->u1NvramTypeLenLsb; + u1LenMSB = prTagDataCurr->u1NvramTypeLenMsb; + + /*sanity check*/ + if ((u1TypeID == 0) && + (u1LenLSB == 0) && (u1LenMSB == 0)) { + DBGLOG(INIT, WARN, "TVL is Null\n"); + break; + } + + /*check Type ID is exist on NVRAM*/ + if (u1TypeID == 7) { + u4NvramStartOffset = u4NvramOffset; + DBGLOG(INIT, TRACE, + "NVRAM tag(%d) exist! current idx:%d, ofst %x\n", + u1TypeID, index, u4NvramStartOffset); + } + + if (u1TypeID == 10) + break; + + u4NvramOffset += sizeof(struct WIFI_NVRAM_TAG_FORMAT); + u4NvramOffset += (u1LenMSB << 8) | (u1LenLSB); + + /*get the nex TLV format*/ + prTagDataCurr = (struct WIFI_NVRAM_TAG_FORMAT *) + (pu1Addr + u4NvramOffset); + + + DBGLOG(INIT, TRACE, + "(%d)CurOfs[0x%08X]:Next(%d)Len:%d\n", + index, + u4NvramOffset, + u1TypeID, + (u1LenMSB << 8) | (u1LenLSB)); + + } + + *pu1DataPointer = pu1Addr + u4NvramStartOffset; + *pu4DataLen = u4NvramOffset - u4NvramStartOffset; + + DBGLOG_MEM8(INIT, TRACE, *pu1DataPointer, *pu4DataLen); + DBGLOG(INIT, TRACE, + "NVRAM datapointer %x tag7 ofst %x tag7-9 Len %x\n", + *pu1DataPointer, u4NvramStartOffset, *pu4DataLen); + +} + +uint32_t soc3_0_wlanSendPhyAction(struct ADAPTER *prAdapter, + uint16_t u2Tag, + uint8_t ucCalCmd) +{ + struct CMD_INFO *prCmdInfo; + uint8_t ucTC, ucCmdSeqNum; + uint32_t u4CmdSize; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + struct mt66xx_chip_info *prChipInfo; + struct HAL_PHY_ACTION_TLV_HEADER *prPhyTlvHeader; + struct HAL_PHY_ACTION_TLV *prPhyTlv; + struct INIT_CMD_PHY_ACTION_CAL *prPhyCal; + + uint8_t *u1EpaELnaDataPointer = NULL; + uint32_t u4EpaELnaDataSize = 0; + + uint32_t u4Cr = 0; + uint32_t u4Value = 0; + + DBGLOG(INIT, INFO, "SendPhyAction begin\n"); + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + soc3_0_wlanGetEpaElnaFromNvram(&u1EpaELnaDataPointer, + &u4EpaELnaDataSize); + + if (u1EpaELnaDataPointer == NULL) { + DBGLOG(INIT, ERROR, "Get u1EpaELnaDataPointer failed\n"); + return WLAN_STATUS_FAILURE; + } + + /* 1. Allocate CMD Info Packet and its Buffer. */ + if (u2Tag == HAL_PHY_ACTION_TAG_FEM) { + u4CmdSize = sizeof(struct HAL_PHY_ACTION_TLV_HEADER) + + sizeof(struct HAL_PHY_ACTION_TLV) + + u4EpaELnaDataSize; + } else { + u4CmdSize = sizeof(struct HAL_PHY_ACTION_TLV_HEADER) + + sizeof(struct HAL_PHY_ACTION_TLV) + + sizeof(struct INIT_CMD_PHY_ACTION_CAL); + } + + if (ucCalCmd == HAL_PHY_ACTION_CAL_FORCE_CAL_REQ) { + u4CmdSize += sizeof(struct HAL_PHY_ACTION_TLV); + u4CmdSize += u4EpaELnaDataSize; + } + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES) + + u4CmdSize); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "cmdBufAllocateCmdInfo failed\n"); + return WLAN_STATUS_FAILURE; + } + + prCmdInfo->u2InfoBufLen = sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES) + + u4CmdSize; + +#if (CFG_USE_TC4_RESOURCE_FOR_INIT_CMD == 1) + /* 2. Always use TC4 (TC4 as CPU) */ + ucTC = TC4_INDEX; +#else + /* 2. Use TC0's resource to send patch finish command. + * Only TC0 is allowed because SDIO HW always reports + * MCU's TXQ_CNT at TXQ0_CNT in CR4 architecutre) + */ + ucTC = TC0_INDEX; +#endif + + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + INIT_CMD_ID_PHY_ACTION, + INIT_CMD_PACKET_TYPE_ID, + &ucCmdSeqNum, + FALSE, + (void **)&prPhyTlvHeader, + TRUE, 0, S2D_INDEX_CMD_H2N); + + /*process TLV Header Part1 */ + prPhyTlvHeader->u4MagicNum = HAL_PHY_ACTION_MAGIC_NUM; + prPhyTlvHeader->ucVersion = HAL_PHY_ACTION_VERSION; + + if (u2Tag == HAL_PHY_ACTION_TAG_FEM) { + /*process TLV Header Part2 */ + prPhyTlvHeader->ucTagNums = 1; + prPhyTlvHeader->u2BufLength = + sizeof(struct HAL_PHY_ACTION_TLV) + + u4EpaELnaDataSize; + + /*process TLV Content*/ + prPhyTlv = + (struct HAL_PHY_ACTION_TLV *)prPhyTlvHeader->aucBuffer; + prPhyTlv->u2Tag = u2Tag; + prPhyTlv->u2BufLength = u4EpaELnaDataSize; + kalMemCopy(prPhyTlv->aucBuffer, + u1EpaELnaDataPointer, u4EpaELnaDataSize); + + } else if (ucCalCmd == HAL_PHY_ACTION_CAL_FORCE_CAL_REQ) { + /*process TLV Header Part2 */ + prPhyTlvHeader->ucTagNums = 2; /* Add HAL_PHY_ACTION_TAG_FEM */ + prPhyTlvHeader->u2BufLength = + sizeof(struct HAL_PHY_ACTION_TLV) + + u4EpaELnaDataSize + sizeof(struct HAL_PHY_ACTION_TLV) + + sizeof(struct INIT_CMD_PHY_ACTION_CAL); + + /*process TLV Content*/ + /*TAG HAL_PHY_ACTION_TAG_CAL*/ + prPhyTlv = + (struct HAL_PHY_ACTION_TLV *)prPhyTlvHeader->aucBuffer; + prPhyTlv->u2Tag = HAL_PHY_ACTION_TAG_CAL; + prPhyTlv->u2BufLength = sizeof(struct INIT_CMD_PHY_ACTION_CAL); + prPhyCal = + (struct INIT_CMD_PHY_ACTION_CAL *)prPhyTlv->aucBuffer; + prPhyCal->ucCmd = ucCalCmd; + + /*TAG HAL_PHY_ACTION_TAG_FEM*/ + prPhyTlv = + (struct HAL_PHY_ACTION_TLV *) + (prPhyTlvHeader->aucBuffer + + sizeof(struct HAL_PHY_ACTION_TLV) + + sizeof(struct INIT_CMD_PHY_ACTION_CAL)); + prPhyTlv->u2Tag = HAL_PHY_ACTION_TAG_FEM; + prPhyTlv->u2BufLength = u4EpaELnaDataSize; + kalMemCopy(prPhyTlv->aucBuffer, + u1EpaELnaDataPointer, u4EpaELnaDataSize); + + } else { + /*process TLV Header Part2 */ + prPhyTlvHeader->ucTagNums = 1; + prPhyTlvHeader->u2BufLength = + sizeof(struct HAL_PHY_ACTION_TLV) + + sizeof(struct INIT_CMD_PHY_ACTION_CAL); + + /*process TLV Content*/ + prPhyTlv = + (struct HAL_PHY_ACTION_TLV *)prPhyTlvHeader->aucBuffer; + prPhyTlv->u2Tag = u2Tag; + prPhyTlv->u2BufLength = sizeof(struct INIT_CMD_PHY_ACTION_CAL); + prPhyCal = + (struct INIT_CMD_PHY_ACTION_CAL *)prPhyTlv->aucBuffer; + prPhyCal->ucCmd = ucCalCmd; + } + + DBGLOG_MEM8(INIT, TRACE, prPhyTlvHeader, u4CmdSize); + + /* 5. Seend WIFI start command */ + while (1) { + + /* 5.1 Acquire TX Resource */ + if (nicTxAcquireResource(prAdapter, ucTC, + nicTxGetPageCount(prAdapter, + prCmdInfo->u2InfoBufLen, TRUE), + TRUE) == WLAN_STATUS_RESOURCES) { + if (nicTxPollingResource(prAdapter, + ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "nicTxPollingResource failed\n"); + goto exit; + } + continue; + } + + /* 5.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo, + prChipInfo->u2TxInitCmdPort) != + WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "nicTxInitCmd failed\n"); + goto exit; + } + + break; + }; + + u4Status = soc3_0_wlanRcvPhyActionRsp(prAdapter, ucCmdSeqNum); + + /* Debug FW Own */ + u4Cr = 0x180600f0; + soc3_0_CrRead(prAdapter, u4Cr, &u4Value); + + if (u4Status != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, WARN, + "SendPhyAction failed: 0x%08x = 0x%08x\n", + u4Cr, u4Value); + else + DBGLOG(INIT, INFO, + "SendPhyAction success: 0x%08x = 0x%08x\n", + u4Cr, u4Value); + +exit: + /* 6. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + +uint32_t soc3_0_wlanPhyAction(IN struct ADAPTER *prAdapter) +{ + uint32_t u4Status = WLAN_STATUS_SUCCESS; + + /* Setup calibration data from backup file */ + if (soc3_0_wlanAccessCalibrationEMI(NULL, FALSE) == + WLAN_STATUS_SUCCESS) + u4Status = soc3_0_wlanSendPhyAction(prAdapter, + HAL_PHY_ACTION_TAG_CAL, + HAL_PHY_ACTION_CAL_USE_BACKUP_REQ); + else + u4Status = soc3_0_wlanSendPhyAction(prAdapter, + HAL_PHY_ACTION_TAG_CAL, + HAL_PHY_ACTION_CAL_FORCE_CAL_REQ); + + return u4Status; +} + +int soc3_0_wlanPreCalPwrOn(void) +{ +#define MAX_PRE_ON_COUNT 5 + + int retryCount = 0; + uint32_t u4Value = 0; + void *pvData = NULL; + void *pvDriverData = NULL; + + enum ENUM_POWER_ON_INIT_FAIL_REASON { + NET_CREATE_FAIL, + BUS_SET_IRQ_FAIL, + ALLOC_ADAPTER_MEM_FAIL, + DRIVER_OWN_FAIL, + INIT_ADAPTER_FAIL, + INIT_HIFINFO_FAIL, + ROM_PATCH_DOWNLOAD_FAIL, + POWER_ON_INIT_DONE + } eFailReason; + uint32_t i = 0, j = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct mt66xx_chip_info *prChipInfo; + + if (get_wifi_process_status() || + get_wifi_powered_status()) + return CONNINFRA_CB_RET_CAL_FAIL_POWER_OFF; + + update_pre_cal_status(1); + + while (g_u4WlanInitFlag == 0) { + DBGLOG(INIT, WARN, + "g_u4WlanInitFlag(%d) retryCount(%d)", + g_u4WlanInitFlag, + retryCount); + + kalMsleep(100); + retryCount++; + + if (retryCount > MAX_PRE_ON_COUNT) { + update_pre_cal_status(0); + return CONNINFRA_CB_RET_CAL_FAIL_POWER_OFF; + } + } + + /* wf driver power on */ + if (wf_pwr_on_consys_mcu() != 0) { + update_pre_cal_status(0); + return CONNINFRA_CB_RET_CAL_FAIL_POWER_OFF; + } + + /* Download patch and send PHY action */ + do { + retryCount = 0; + while (g_prPlatDev == NULL) { + DBGLOG(INIT, WARN, + "g_prPlatDev(0x%x) retryCount(%d)", + g_prPlatDev, + retryCount); + + kalMsleep(100); + retryCount++; + + if (retryCount > MAX_PRE_ON_COUNT) { + update_pre_cal_status(0); + return CONNINFRA_CB_RET_CAL_FAIL_POWER_OFF; + } + } + + pvDriverData = (void *)&mt66xx_driver_data_soc3_0; + prChipInfo = ((struct mt66xx_hif_driver_data *) + pvDriverData)->chip_info; + pvData = (void *)prChipInfo->pdev; + +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanDebugTC4Init(); +#endif + + /* Create network device, Adapter, KalInfo, + * prDevHandler(netdev) + */ + grWdev = wlanNetCreate(pvData, pvDriverData); + + if (grWdev == NULL) { + DBGLOG(INIT, ERROR, "wlanNetCreate Error\n"); + eFailReason = NET_CREATE_FAIL; + break; + } + + /* Set the ioaddr to HIF Info */ + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(grWdev->wiphy); + + /* Should we need this??? to be conti... */ + gPrDev = prGlueInfo->prDevHandler; + + /* Setup IRQ */ + if (glBusSetIrq(grWdev->netdev, NULL, prGlueInfo) + != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "glBusSetIrq error\n"); + eFailReason = BUS_SET_IRQ_FAIL; + break; + } + + prGlueInfo->i4DevIdx = 0; + prAdapter = prGlueInfo->prAdapter; + prChipInfo = prAdapter->chip_info; + + if (prChipInfo->asicCapInit != NULL) + prChipInfo->asicCapInit(prAdapter); + + nicpmWakeUpWiFi(prAdapter); + + prAdapter->u4OwnFailedCount = 0; + prAdapter->u4OwnFailedLogCount = 0; + + /* Additional with chip reset optimize*/ + prAdapter->ucCmdSeqNum = 0; + + QUEUE_INITIALIZE(&(prAdapter->rPendingCmdQueue)); +#if CFG_SUPPORT_MULTITHREAD + QUEUE_INITIALIZE(&prAdapter->rTxCmdQueue); + QUEUE_INITIALIZE(&prAdapter->rTxCmdDoneQueue); +#if CFG_FIX_2_TX_PORT + QUEUE_INITIALIZE(&prAdapter->rTxP0Queue); + QUEUE_INITIALIZE(&prAdapter->rTxP1Queue); +#else + for (i = 0; i < BSS_DEFAULT_NUM; i++) + for (j = 0; j < TX_PORT_NUM; j++) + QUEUE_INITIALIZE(&prAdapter->rTxPQueue[i][j]); +#endif + QUEUE_INITIALIZE(&prAdapter->rRxQueue); + QUEUE_INITIALIZE(&prAdapter->rTxDataDoneQueue); +#endif + + /* reset fgIsBusAccessFailed */ + fgIsBusAccessFailed = FALSE; + + /* Allocate mandatory resource for TX/RX */ + if (nicAllocateAdapterMemory(prAdapter) != + WLAN_STATUS_SUCCESS) { + + DBGLOG(INIT, ERROR, + "nicAllocateAdapterMemory Error!\n"); + eFailReason = ALLOC_ADAPTER_MEM_FAIL; + break; + } + + /* should we need this? to be conti... */ + prAdapter->u4OsPacketFilter = PARAM_PACKET_FILTER_SUPPORTED; + + /* Initialize the Adapter: + * verify chipset ID, HIF init... + * the code snippet just do the copy thing + */ + if (nicInitializeAdapter(prAdapter) != WLAN_STATUS_SUCCESS) { + + DBGLOG(INIT, ERROR, + "nicInitializeAdapter failed!\n"); + eFailReason = INIT_ADAPTER_FAIL; + break; + } + + nicInitSystemService(prAdapter, FALSE); + + /* Initialize Tx */ + nicTxInitialize(prAdapter); + + /* Initialize Rx */ + nicRxInitialize(prAdapter); + + /* HIF SW info initialize */ + if (!halHifSwInfoInit(prAdapter)) { + + DBGLOG(INIT, ERROR, + "halHifSwInfoInit failed!\n"); + eFailReason = INIT_HIFINFO_FAIL; + break; + } + + /* Enable HIF cut-through to N9 mode */ + HAL_ENABLE_FWDL(prAdapter, TRUE); + + /* Disable interrupt, download is done by polling mode only */ + nicDisableInterrupt(prAdapter); + + /* Initialize Tx Resource to fw download state */ + nicTxInitResetResource(prAdapter); + + if (prChipInfo->pwrondownload) { + if (prChipInfo->pwrondownload(prAdapter, + ENUM_WLAN_POWER_ON_DOWNLOAD_ROM_PATCH) + != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "pwrondownload failed!\n"); + eFailReason = ROM_PATCH_DOWNLOAD_FAIL; + break; + } + } + + soc3_0_wlanSendPhyAction(prAdapter, + HAL_PHY_ACTION_TAG_FEM, + 0); + + eFailReason = POWER_ON_INIT_DONE; + } while (FALSE); + + switch (eFailReason) { + case NET_CREATE_FAIL: +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanDebugTC4Uninit(); /* Uninit for TC4 debug */ +#endif + break; + + case BUS_SET_IRQ_FAIL: +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanDebugTC4Uninit(); /* Uninit for TC4 debug */ +#endif + wlanWakeLockUninit(prGlueInfo); + wlanNetDestroy(grWdev); + break; + + case ALLOC_ADAPTER_MEM_FAIL: + case DRIVER_OWN_FAIL: + case INIT_ADAPTER_FAIL: + glBusFreeIrq(grWdev->netdev, + *((struct GLUE_INFO **) netdev_priv(grWdev->netdev))); + +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanDebugTC4Uninit(); /* Uninit for TC4 debug */ +#endif + + wlanWakeLockUninit(prGlueInfo); + + if (eFailReason != ALLOC_ADAPTER_MEM_FAIL) + nicReleaseAdapterMemory(prAdapter); + + wlanNetDestroy(grWdev); + break; + + case INIT_HIFINFO_FAIL: + nicRxUninitialize(prAdapter); + nicTxRelease(prAdapter, FALSE); + + /* System Service Uninitialization */ + nicUninitSystemService(prAdapter); + + glBusFreeIrq(grWdev->netdev, + *((struct GLUE_INFO **)netdev_priv(grWdev->netdev))); + +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanDebugTC4Uninit(); /* Uninit for TC4 debug */ +#endif + + wlanWakeLockUninit(prGlueInfo); + nicReleaseAdapterMemory(prAdapter); + wlanNetDestroy(grWdev); + break; + + case ROM_PATCH_DOWNLOAD_FAIL: + HAL_ENABLE_FWDL(prAdapter, FALSE); + halHifSwInfoUnInit(prGlueInfo); + nicRxUninitialize(prAdapter); + nicTxRelease(prAdapter, FALSE); + + /* System Service Uninitialization */ + nicUninitSystemService(prAdapter); + + glBusFreeIrq(grWdev->netdev, + *((struct GLUE_INFO **)netdev_priv(grWdev->netdev))); + +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanDebugTC4Uninit(); /* Uninit for TC4 debug */ +#endif + + wlanWakeLockUninit(prGlueInfo); + nicReleaseAdapterMemory(prAdapter); + wlanNetDestroy(grWdev); + break; + + case POWER_ON_INIT_DONE: + /* pre-cal release resouce */ + break; + } + + DBGLOG(INIT, INFO, + "soc3_0_wlanPreCalPwrOn end(%d)\n", + eFailReason); + + if (eFailReason != POWER_ON_INIT_DONE) { + + /* set FW own after power on consys mcu to + * keep Driver/FW/HW state sync + */ + wf_ioremap_read(CONN_HOST_CSR_TOP_BASE_ADDR + 0x0010, + &u4Value); + + if ((u4Value & BIT(2)) != BIT(2)) { + DBGLOG(INIT, INFO, "0x%08x = 0x%08x, Set FW Own\n", + CONN_HOST_CSR_TOP_BASE_ADDR + 0x0010, + u4Value); + + wf_ioremap_write(CONN_HOST_CSR_TOP_BASE_ADDR + 0x0010, + PCIE_LPCR_HOST_SET_OWN); + } + + update_pre_cal_status(0); + return CONNINFRA_CB_RET_CAL_FAIL_POWER_OFF; + } + + return CONNINFRA_CB_RET_CAL_PASS_POWER_OFF; +} + +int soc3_0_wlanPreCal(void) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4Value = 0; + + if (get_pre_cal_status() == 0) + return CONNINFRA_CB_RET_CAL_FAIL_POWER_OFF; + + if (g_u4WlanInitFlag == 0) { + DBGLOG(INIT, WARN, + "g_u4WlanInitFlag(%d)", + g_u4WlanInitFlag); + + update_pre_cal_status(0); + return CONNINFRA_CB_RET_CAL_FAIL_POWER_OFF; + } + + DBGLOG(INIT, INFO, "PreCal begin\n"); + + /* Set the ioaddr to HIF Info */ + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(grWdev->wiphy); + prAdapter = prGlueInfo->prAdapter; + nicpmWakeUpWiFi(prAdapter); + + /* Disable interrupt, download is done by polling mode only */ + nicDisableInterrupt(prAdapter); + + soc3_0_wlanSendPhyAction(prAdapter, + HAL_PHY_ACTION_TAG_CAL, + HAL_PHY_ACTION_CAL_FORCE_CAL_REQ); + + HAL_ENABLE_FWDL(prAdapter, FALSE); + halHifSwInfoUnInit(prGlueInfo); + nicRxUninitialize(prAdapter); + nicTxRelease(prAdapter, FALSE); + + /* System Service Uninitialization */ + nicUninitSystemService(prAdapter); + + glBusFreeIrq(grWdev->netdev, + *((struct GLUE_INFO **)netdev_priv(grWdev->netdev))); + +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanDebugTC4Uninit(); /* Uninit for TC4 debug */ +#endif + + wlanWakeLockUninit(prGlueInfo); + nicReleaseAdapterMemory(prAdapter); + wlanNetDestroy(grWdev); + + /* set FW own after power on consys mcu to + * keep Driver/FW/HW state sync + */ + wf_ioremap_read(CONN_HOST_CSR_TOP_BASE_ADDR + 0x0010, + &u4Value); + + if ((u4Value & BIT(2)) != BIT(2)) { + DBGLOG(INIT, INFO, "0x%08x = 0x%08x, Set FW Own\n", + CONN_HOST_CSR_TOP_BASE_ADDR + 0x0010, + u4Value); + + wf_ioremap_write(CONN_HOST_CSR_TOP_BASE_ADDR + 0x0010, + PCIE_LPCR_HOST_SET_OWN); + } + + wf_pwr_off_consys_mcu(); + + DBGLOG(INIT, INFO, "PreCal end\n"); + + update_pre_cal_status(0); + + return CONNINFRA_CB_RET_CAL_PASS_POWER_OFF; +} + +uint8_t *soc3_0_wlanGetCalResult(uint32_t *prCalSize) +{ + *prCalSize = gEmiCalSize; + + return gEmiCalResult; +} + +void soc3_0_wlanCalDebugCmd(uint32_t cmd, uint32_t para) +{ + switch (cmd) { + case 0: + if (gEmiCalResult != NULL) { + kalMemFree(gEmiCalResult, + VIR_MEM_TYPE, + gEmiCalSize); + gEmiCalResult = NULL; + } + break; + + case 1: + if (para == 1) + gEmiCalUseEmiData = TRUE; + else + gEmiCalUseEmiData = FALSE; + break; + } + + DBGLOG(RFTEST, INFO, "gEmiCalResult(0x%x), gEmiCalUseEmiData(%d)\n", + gEmiCalResult, gEmiCalUseEmiData); +} + +#endif /* (CFG_SUPPORT_PRE_ON_PHY_ACTION == 1) */ + +#endif /* soc3_0 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/debug.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/debug.c new file mode 100644 index 0000000000000..d69e4bcfd34b0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/debug.c @@ -0,0 +1,916 @@ +#include "precomp.h" + + +#if (CFG_SUPPORT_STATISTICS == 1) + +#define WAKE_MAX_CMD_EVENT_NUM 20 +#define WAKE_STR_BUFFER_LEN (60 + 20 * WAKE_MAX_CMD_EVENT_NUM) + +struct WAKE_CMD_T { + uint8_t ucCmdId; + uint8_t ucFlagIsUesd; + uint16_t u2Cnt; +}; + +struct WAKE_EVENT_T { + uint8_t ucEventId; + uint8_t ucFlagIsUesd; + uint16_t u2Cnt; +}; + +struct WAKE_INFO_T { + struct WAKE_CMD_T arCmd[WAKE_MAX_CMD_EVENT_NUM]; + uint8_t ucCmdCnt; + uint32_t u4TotalCmd; + + struct WAKE_EVENT_T arEvent[WAKE_MAX_CMD_EVENT_NUM]; + uint8_t ucEventCnt; + uint32_t u4TotalEvent; + + uint32_t au4TxDataCnt[WLAN_WAKE_MAX_NUM]; + uint32_t u4TxCnt; + uint32_t au4RxDataCnt[WLAN_WAKE_MAX_NUM]; + uint32_t u4RxCnt; +}; + +static struct WAKE_INFO_T *gprWakeInfoStatics; +static uint8_t aucStr[WAKE_STR_BUFFER_LEN]; +#endif + +#if (CFG_SUPPORT_TRACE_TC4 == 1) +struct COMMAND { + uint8_t ucCID; + u_int8_t fgSetQuery; + u_int8_t fgNeedResp; + uint8_t ucCmdSeqNum; +}; + +struct SECURITY_FRAME { + uint16_t u2EthType; + uint16_t u2Reserved; +}; + +struct MGMT_FRAME { + uint16_t u2FrameCtl; + uint16_t u2DurationID; +}; + +struct TC_RES_RELEASE_ENTRY { + uint64_t u8RelaseTime; + uint32_t u4RelCID; + uint32_t u4Tc4RelCnt; + uint32_t u4AvailableTc4; +}; + +struct CMD_TRACE_ENTRY { + uint64_t u8TxTime; + enum COMMAND_TYPE eCmdType; + union { + struct COMMAND rCmd; + struct SECURITY_FRAME rSecFrame; + struct MGMT_FRAME rMgmtFrame; + } u; +}; + +#define TC_RELEASE_TRACE_BUF_MAX_NUM 100 +#define TXED_CMD_TRACE_BUF_MAX_NUM 100 + +static struct TC_RES_RELEASE_ENTRY *gprTcReleaseTraceBuffer; +static struct CMD_TRACE_ENTRY *gprCmdTraceEntry; +void wlanDebugTC4Init(void) +{ + /* debug for command/tc4 resource begin */ + gprTcReleaseTraceBuffer = + kalMemAlloc(TC_RELEASE_TRACE_BUF_MAX_NUM * sizeof( + struct TC_RES_RELEASE_ENTRY), PHY_MEM_TYPE); + kalMemZero(gprTcReleaseTraceBuffer, + TC_RELEASE_TRACE_BUF_MAX_NUM * sizeof(struct + TC_RES_RELEASE_ENTRY)); + gprCmdTraceEntry = kalMemAlloc(TXED_CMD_TRACE_BUF_MAX_NUM * + sizeof(struct CMD_TRACE_ENTRY), + PHY_MEM_TYPE); + kalMemZero(gprCmdTraceEntry, + TXED_CMD_TRACE_BUF_MAX_NUM * sizeof(struct + CMD_TRACE_ENTRY)); + /* debug for command/tc4 resource end */ +} + +void wlanDebugTC4Uninit(void) +{ + /* debug for command/tc4 resource begin */ + kalMemFree(gprTcReleaseTraceBuffer, PHY_MEM_TYPE, + TC_RELEASE_TRACE_BUF_MAX_NUM * sizeof(struct + TC_RES_RELEASE_ENTRY)); + kalMemFree(gprCmdTraceEntry, PHY_MEM_TYPE, + TXED_CMD_TRACE_BUF_MAX_NUM * sizeof(struct + CMD_TRACE_ENTRY)); + /* debug for command/tc4 resource end */ +} + +void wlanTraceTxCmd(struct CMD_INFO *prCmd) +{ + static uint16_t u2CurEntry; + struct CMD_TRACE_ENTRY *prCurCmd = + &gprCmdTraceEntry[u2CurEntry]; + + prCurCmd->u8TxTime = sched_clock(); + prCurCmd->eCmdType = prCmd->eCmdType; + if (prCmd->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) { + struct WLAN_MAC_MGMT_HEADER *prMgmt = (struct + WLAN_MAC_MGMT_HEADER *)prCmd->prMsduInfo->prPacket; + + prCurCmd->u.rMgmtFrame.u2FrameCtl = prMgmt->u2FrameCtrl; + prCurCmd->u.rMgmtFrame.u2DurationID = prMgmt->u2Duration; + } else if (prCmd->eCmdType == COMMAND_TYPE_SECURITY_FRAME || + prCmd->eCmdType == COMMAND_TYPE_DATA_FRAME) { + uint8_t *pucPkt = (uint8_t *)((struct sk_buff *) + prCmd->prPacket)->data; + + prCurCmd->u.rSecFrame.u2EthType = + (pucPkt[ETH_TYPE_LEN_OFFSET] << 8) | + (pucPkt[ETH_TYPE_LEN_OFFSET + 1]); + } else { + prCurCmd->u.rCmd.ucCID = prCmd->ucCID; + prCurCmd->u.rCmd.ucCmdSeqNum = prCmd->ucCmdSeqNum; + prCurCmd->u.rCmd.fgNeedResp = prCmd->fgNeedResp; + prCurCmd->u.rCmd.fgSetQuery = prCmd->fgSetQuery; + } + u2CurEntry++; + if (u2CurEntry == TC_RELEASE_TRACE_BUF_MAX_NUM) + u2CurEntry = 0; +} + +void wlanTraceReleaseTcRes(struct ADAPTER *prAdapter, + uint32_t u4TxRlsCnt, uint32_t u4Available) +{ + static uint16_t u2CurEntry; + struct TC_RES_RELEASE_ENTRY *prCurBuf = + &gprTcReleaseTraceBuffer[u2CurEntry]; + + prCurBuf->u8RelaseTime = sched_clock(); + prCurBuf->u4Tc4RelCnt = u4TxRlsCnt; + prCurBuf->u4AvailableTc4 = u4Available; + u2CurEntry++; + if (u2CurEntry == TXED_CMD_TRACE_BUF_MAX_NUM) + u2CurEntry = 0; +} + +void wlanDumpTcResAndTxedCmd(uint8_t *pucBuf, + uint32_t maxLen) +{ + uint16_t i = 0; + struct TC_RES_RELEASE_ENTRY *prTcRel = + gprTcReleaseTraceBuffer; + struct CMD_TRACE_ENTRY *prCmd = gprCmdTraceEntry; + + if (pucBuf) { + int bufLen = 0; + + for (; i < TXED_CMD_TRACE_BUF_MAX_NUM / 2; i++) { + bufLen = snprintf(pucBuf, maxLen, + "%d: Time %llu, Type %d, Content %08x; %d: Time %llu, Type %d, Content %08x\n", + i * 2, prCmd[i * 2].u8TxTime, + prCmd[i * 2].eCmdType, + *(uint32_t *) + (&prCmd[i * 2].u.rCmd.ucCID), + i * 2 + 1, + prCmd[i * 2 + 1].u8TxTime, + prCmd[i * 2 + 1].eCmdType, + *(uint32_t *) + (&prCmd[i * 2 + 1].u.rCmd.ucCID)); + if (bufLen <= 0) + break; + pucBuf += bufLen; + maxLen -= bufLen; + } + for (i = 0; i < TC_RELEASE_TRACE_BUF_MAX_NUM / 2; i++) { + bufLen = snprintf(pucBuf, maxLen, + "%d: Time %llu, Tc4Cnt %d, Free %d, CID %08x; %d: Time %llu, Tc4Cnt %d, Free %d CID %08x\n", + i * 2, prTcRel[i * 2].u8RelaseTime, + prTcRel[i * 2].u4Tc4RelCnt, + prTcRel[i * 2].u4AvailableTc4, + prTcRel[i * 2].u4RelCID, + i * 2 + 1, + prTcRel[i * 2 + 1].u8RelaseTime, + prTcRel[i * 2 + 1].u4Tc4RelCnt, + prTcRel[i * 2 + 1].u4AvailableTc4, + prTcRel[i * 2 + 1].u4RelCID); + if (bufLen <= 0) + break; + pucBuf += bufLen; + maxLen -= bufLen; + } + } else { + for (; i < TXED_CMD_TRACE_BUF_MAX_NUM / 4; i++) { + LOG_FUNC( + "%d: Time %llu, Type %d, Content %08x; %d: Time %llu, Type %d, Content %08x; ", + i * 4, prCmd[i * 4].u8TxTime, + prCmd[i * 4].eCmdType, + *(uint32_t *)(&prCmd[i * 4].u.rCmd.ucCID), + i * 4 + 1, prCmd[i * 4 + 1].u8TxTime, + prCmd[i * 4 + 1].eCmdType, + *(uint32_t *)(&prCmd[i * 4 + 1].u.rCmd.ucCID)); + LOG_FUNC( + "%d: Time %llu, Type %d, Content %08x; %d: Time %llu, Type %d, Content %08x\n", + i * 4 + 2, prCmd[i * 4 + 2].u8TxTime, + prCmd[i * 4 + 2].eCmdType, + *(uint32_t *)(&prCmd[i * 4 + 2].u.rCmd.ucCID), + i * 4 + 3, prCmd[i * 4 + 3].u8TxTime, + prCmd[i * 4 + 3].eCmdType, + *(uint32_t *)(&prCmd[i * 4 + 3].u.rCmd.ucCID)); + } + for (i = 0; i < TC_RELEASE_TRACE_BUF_MAX_NUM / 4; i++) { + LOG_FUNC( + "%d: Time %llu, Tc4Cnt %d, Free %d, CID %08x; %d: Time %llu, Tc4Cnt %d, Free %d, CID %08x;", + i * 4, prTcRel[i * 4].u8RelaseTime, + prTcRel[i * 4].u4Tc4RelCnt, + prTcRel[i * 4].u4AvailableTc4, + prTcRel[i * 4].u4RelCID, + i * 4 + 1, prTcRel[i * 4 + 1].u8RelaseTime, + prTcRel[i * 4 + 1].u4Tc4RelCnt, + prTcRel[i * 4 + 1].u4AvailableTc4, + prTcRel[i * 4 + 1].u4RelCID); + LOG_FUNC( + "%d: Time %llu, Tc4Cnt %d, Free %d, CID %08x; %d: Time %llu, Tc4Cnt %d, Free %d, CID %08x\n", + i * 4 + 2, prTcRel[i * 4 + 2].u8RelaseTime, + prTcRel[i * 4 + 2].u4Tc4RelCnt, + prTcRel[i * 4 + 2].u4AvailableTc4, + prTcRel[i * 4 + 2].u4RelCID, + i * 4 + 3, prTcRel[i * 4 + 3].u8RelaseTime, + prTcRel[i * 4 + 3].u4Tc4RelCnt, + prTcRel[i * 4 + 3].u4AvailableTc4, + prTcRel[i * 4 + 3].u4RelCID); + } + } +} +#endif + + +#if (CFG_SUPPORT_STATISTICS == 1) + +void wlanWakeStaticsInit(void) +{ + gprWakeInfoStatics = + kalMemAlloc(WAKE_MAX_CMD_EVENT_NUM * sizeof( + struct WAKE_INFO_T), PHY_MEM_TYPE); + if (gprWakeInfoStatics != NULL) + kalMemZero(gprWakeInfoStatics, + WAKE_MAX_CMD_EVENT_NUM * sizeof(struct + WAKE_INFO_T)); +} + +void wlanWakeStaticsUninit(void) +{ + if (gprWakeInfoStatics != NULL) + kalMemFree(gprWakeInfoStatics, PHY_MEM_TYPE, + WAKE_MAX_CMD_EVENT_NUM * sizeof(struct WAKE_INFO_T)); +} + +uint32_t wlanWakeLogCmd(uint8_t ucCmdId) +{ + int i = 0; + int j = 0; + + if ((gprWakeInfoStatics == NULL) || (wlan_fb_power_down != TRUE)) + return 1; + + for (i = 0; i < WAKE_MAX_CMD_EVENT_NUM; i++) { + if ((gprWakeInfoStatics->arCmd[i].ucFlagIsUesd == TRUE) + && (gprWakeInfoStatics->arCmd[i].ucCmdId == ucCmdId)) { + /*old item ++*/ + gprWakeInfoStatics->arCmd[i].u2Cnt++; + gprWakeInfoStatics->u4TotalCmd++; + break; + } + } + + if (i >= WAKE_MAX_CMD_EVENT_NUM) { + /*add new item*/ + for (j = 0; j < WAKE_MAX_CMD_EVENT_NUM; j++) { + if (gprWakeInfoStatics->arCmd[j].ucFlagIsUesd != TRUE) { + gprWakeInfoStatics->ucCmdCnt++; + gprWakeInfoStatics->arCmd[j].ucCmdId = ucCmdId; + gprWakeInfoStatics->arCmd[j].u2Cnt++; + gprWakeInfoStatics->u4TotalCmd++; + gprWakeInfoStatics->arCmd[j].ucFlagIsUesd + = TRUE; + break; + } + } + + if (j >= WAKE_MAX_CMD_EVENT_NUM) { + DBGLOG_LIMITED(OID, WARN, + "Wake cmd over flow %d-0x%02x\n", + WAKE_MAX_CMD_EVENT_NUM, ucCmdId); + } + } + return 0; +} + +uint32_t wlanWakeLogEvent(uint8_t ucEventId) +{ + int i = 0; + int j = 0; + + if ((gprWakeInfoStatics == NULL) || (wlan_fb_power_down != TRUE)) + return 1; + + for (i = 0; i < WAKE_MAX_CMD_EVENT_NUM; i++) { + if ((gprWakeInfoStatics->arEvent[i].ucFlagIsUesd == TRUE) + && + (gprWakeInfoStatics->arEvent[i].ucEventId == ucEventId)) { + /*old item ++*/ + gprWakeInfoStatics->arEvent[i].u2Cnt++; + gprWakeInfoStatics->u4TotalEvent++; + break; + } + } + + if (i >= WAKE_MAX_CMD_EVENT_NUM) { + /*add new item*/ + for (j = 0; j < WAKE_MAX_CMD_EVENT_NUM; j++) { + if (gprWakeInfoStatics->arEvent[j].ucFlagIsUesd + != TRUE) { + gprWakeInfoStatics->ucEventCnt++; + gprWakeInfoStatics->arEvent[j].ucEventId + = ucEventId; + gprWakeInfoStatics->arEvent[j].u2Cnt++; + gprWakeInfoStatics->u4TotalEvent++; + gprWakeInfoStatics->arEvent[j].ucFlagIsUesd + = TRUE; + break; + } + } + + if (j >= WAKE_MAX_CMD_EVENT_NUM) { + DBGLOG(OID, WARN, + "Wake event over flow %d-0x%02x\n", + WAKE_MAX_CMD_EVENT_NUM, ucEventId); + } + } + return 0; +} + +void wlanLogTxData(enum WAKE_DATA_TYPE dataType) +{ + if ((gprWakeInfoStatics != NULL) && (wlan_fb_power_down == TRUE)) { + gprWakeInfoStatics->au4TxDataCnt[dataType]++; + gprWakeInfoStatics->u4TxCnt++; + } +} + +void wlanLogRxData(enum WAKE_DATA_TYPE dataType) +{ + if ((gprWakeInfoStatics != NULL) && (wlan_fb_power_down == TRUE)) { + gprWakeInfoStatics->au4RxDataCnt[dataType]++; + gprWakeInfoStatics->u4RxCnt++; + } +} + +static void wlanWakeStaticsClear(void) +{ + if (gprWakeInfoStatics != NULL) { + kalMemZero(gprWakeInfoStatics, + WAKE_MAX_CMD_EVENT_NUM * sizeof(struct + WAKE_INFO_T)); + } +} + +uint32_t wlanWakeDumpRes(void) +{ + uint8_t i = 0; + uint8_t flag = 0; + char *pos = NULL; + char *end = NULL; + int ret = 0; + + if ((gprWakeInfoStatics == NULL) + || (wlan_fb_power_down != TRUE)) { + wlanWakeStaticsClear(); + return 1; + } + + /*Log Style: one line log or human friendly log.*/ +#if 1 + kalMemZero(&aucStr[0], sizeof(uint8_t)*WAKE_STR_BUFFER_LEN); + pos = &aucStr[0]; + end = &aucStr[0] + WAKE_STR_BUFFER_LEN - 1; + + if (gprWakeInfoStatics->ucCmdCnt > 0) { + flag = 1; + ret = snprintf(pos, (end - pos + 1), "CMD(%u:%u)= ", + gprWakeInfoStatics->ucCmdCnt, + gprWakeInfoStatics->u4TotalCmd); + if (ret < 0 || ret >= (end - pos + 1)) + return 1; + pos += ret; + + for (i = 0; i < gprWakeInfoStatics->ucCmdCnt; i++) { + ret = snprintf(pos, (end - pos + 1), "0x%02x-%d ", + gprWakeInfoStatics->arCmd[i].ucCmdId, + gprWakeInfoStatics->arCmd[i].u2Cnt); + if (ret < 0 || ret >= (end - pos + 1)) + return 1; + pos += ret; + } + } + + if (gprWakeInfoStatics->ucEventCnt > 0) { + flag = 1; + ret = snprintf(pos, (end - pos + 1), "EVENT(%u:%u)= ", + gprWakeInfoStatics->ucEventCnt, + gprWakeInfoStatics->u4TotalEvent); + if (ret < 0 || ret >= (end - pos + 1)) + return 1; + pos += ret; + + for (i = 0; i < gprWakeInfoStatics->ucEventCnt; i++) { + ret = snprintf(pos, (end - pos + 1), "0x%02x-%d ", + gprWakeInfoStatics->arEvent[i].ucEventId, + gprWakeInfoStatics->arEvent[i].u2Cnt); + if (ret < 0 || ret >= (end - pos + 1)) + return 1; + pos += ret; + } + } + + if (gprWakeInfoStatics->u4TxCnt > 0) { + flag = 1; + ret = snprintf(pos, (end - pos + 1), + "TX(%u)=%u-%u-%u-%u-%u-%u ", + gprWakeInfoStatics->u4TxCnt, + gprWakeInfoStatics->au4TxDataCnt[WLAN_WAKE_ARP], + gprWakeInfoStatics->au4TxDataCnt[WLAN_WAKE_IPV4], + gprWakeInfoStatics->au4TxDataCnt[WLAN_WAKE_IPV6], + gprWakeInfoStatics->au4TxDataCnt[WLAN_WAKE_1X], + gprWakeInfoStatics->au4TxDataCnt[WLAN_WAKE_TDLS], + gprWakeInfoStatics->au4TxDataCnt[WLAN_WAKE_OTHER]); + + if (ret < 0 || ret >= (end - pos + 1)) + return 1; + pos += ret; + } + + if (gprWakeInfoStatics->u4RxCnt > 0) { + flag = 1; + ret = snprintf(pos, (end - pos + 1), + "RX(%u)=%u-%u-%u-%u-%u-%u ", + gprWakeInfoStatics->u4RxCnt, + gprWakeInfoStatics->au4RxDataCnt[WLAN_WAKE_ARP], + gprWakeInfoStatics->au4RxDataCnt[WLAN_WAKE_IPV4], + gprWakeInfoStatics->au4RxDataCnt[WLAN_WAKE_IPV6], + gprWakeInfoStatics->au4RxDataCnt[WLAN_WAKE_1X], + gprWakeInfoStatics->au4RxDataCnt[WLAN_WAKE_TDLS], + gprWakeInfoStatics->au4RxDataCnt[WLAN_WAKE_OTHER]); + if (ret < 0 || ret >= (end - pos + 1)) + return 1; + pos += ret; + } + + if (flag != 0) + DBGLOG(OID, INFO, "[WLAN-LP] %s\n", (char *)&aucStr[0]); +#else + /*1.dump cmd*/ + if (gprWakeInfoStatics->ucCmdCnt > 0) { + kalMemZero(&aucStr[0], sizeof(uint8_t)*WAKE_STR_BUFFER_LEN); + pos = &aucStr[0]; + end = &aucStr[0] + WAKE_STR_BUFFER_LEN - 1; + for (i = 0; i < gprWakeInfoStatics->ucCmdCnt; i++) { + + ret = snprintf(pos, end - pos, " 0x%02x ", + gprWakeInfoStatics->arCmd[i].ucCmdId); + if (ret < 0 || ret >= end - pos) + return 1; + pos += ret; + } + DBGLOG(OID, INFO, "[LP-CMD-ID-%u][%s]\n", + gprWakeInfoStatics->ucCmdCnt, (char *)&aucStr[0]); + + kalMemZero(&aucStr[0], sizeof(uint8_t)*WAKE_STR_BUFFER_LEN); + pos = &aucStr[0]; + end = &aucStr[0] + WAKE_STR_BUFFER_LEN - 1; + for (i = 0; i < gprWakeInfoStatics->ucCmdCnt; i++) { + + ret = snprintf(pos, end - pos, " %u ", + gprWakeInfoStatics->arCmd[i].u2Cnt); + if (ret < 0 || ret >= end - pos) + return 1; + pos += ret; + } + DBGLOG(OID, INFO, "[LP-CMD-CNT-%u][%s]\n", + gprWakeInfoStatics->u4TotalCmd, (char *)&aucStr[0]); + } + + /*2.dump event*/ + if (gprWakeInfoStatics->ucCmdCnt > 0) { + + kalMemZero(&aucStr[0], sizeof(uint8_t)*WAKE_STR_BUFFER_LEN); + pos = &aucStr[0]; + end = &aucStr[0] + WAKE_STR_BUFFER_LEN - 1; + for (i = 0; i < gprWakeInfoStatics->ucEventCnt; i++) { + + ret = snprintf(pos, end - pos, " 0x%02x ", + gprWakeInfoStatics->arEvent[i].ucEventId); + if (ret < 0 || ret >= end - pos) + return 1; + pos += ret; + } + DBGLOG(OID, INFO, "[LP-EVENT-ID-%u][%s]\n", + gprWakeInfoStatics->ucEventCnt, (char *)&aucStr[0]); + + kalMemZero(&aucStr[0], sizeof(uint8_t)*WAKE_STR_BUFFER_LEN); + pos = &aucStr[0]; + end = &aucStr[0] + WAKE_STR_BUFFER_LEN - 1; + for (i = 0; i < gprWakeInfoStatics->ucEventCnt; i++) { + + ret = snprintf(pos, end - pos, " %u ", + gprWakeInfoStatics->arEvent[i].u2Cnt); + if (ret < 0 || ret >= end - pos) { + end[-1] = '\0'; + return 1; + } + pos += ret; + } + DBGLOG(OID, INFO, "[LP-EVENT-CNT-%u][%s]\n", + gprWakeInfoStatics->u4TotalEvent, (char *)&aucStr[0]); + } + + /*3.dump tx/rx data*/ + if (gprWakeInfoStatics->u4TxCnt > 0) { + DBGLOG(OID, INFO, "[LP-EVENT-TX-%u][%u-%u-%u-%u-%u-%u]\n", + gprWakeInfoStatics->u4TxCnt, + gprWakeInfoStatics->au4TxDataCnt[WLAN_WAKE_ARP], + gprWakeInfoStatics->au4TxDataCnt[WLAN_WAKE_IPV4], + gprWakeInfoStatics->au4TxDataCnt[WLAN_WAKE_IPV6], + gprWakeInfoStatics->au4TxDataCnt[WLAN_WAKE_1X], + gprWakeInfoStatics->au4TxDataCnt[WLAN_WAKE_TDLS], + gprWakeInfoStatics->au4TxDataCnt[WLAN_WAKE_OTHER]); + } + + if (gprWakeInfoStatics->u4RxCnt > 0) { + DBGLOG(OID, INFO, "[LP-EVENT-RX-%u][%u-%u-%u-%u-%u-%u]\n", + gprWakeInfoStatics->u4RxCnt, + gprWakeInfoStatics->au4RxDataCnt[WLAN_WAKE_ARP], + gprWakeInfoStatics->au4RxDataCnt[WLAN_WAKE_IPV4], + gprWakeInfoStatics->au4RxDataCnt[WLAN_WAKE_IPV6], + gprWakeInfoStatics->au4RxDataCnt[WLAN_WAKE_1X], + gprWakeInfoStatics->au4RxDataCnt[WLAN_WAKE_TDLS], + gprWakeInfoStatics->au4RxDataCnt[WLAN_WAKE_OTHER]); + } +#endif + wlanWakeStaticsClear(); + return 0; +} + +#endif + +uint32_t wlanSetDriverDbgLevel(IN uint32_t u4DbgIdx, IN uint32_t u4DbgMask) +{ + uint32_t u4Idx; + uint32_t fgStatus = WLAN_STATUS_SUCCESS; + + if (u4DbgIdx == DBG_ALL_MODULE_IDX) { + for (u4Idx = 0; u4Idx < DBG_MODULE_NUM; u4Idx++) + aucDebugModule[u4Idx] = (uint8_t) u4DbgMask; + LOG_FUNC("Set ALL DBG module log level to [0x%02x]\n", + u4DbgMask); + } else if (u4DbgIdx < DBG_MODULE_NUM) { + aucDebugModule[u4DbgIdx] = (uint8_t) u4DbgMask; + LOG_FUNC("Set DBG module[%u] log level to [0x%02x]\n", + u4DbgIdx, u4DbgMask); + } else { + fgStatus = WLAN_STATUS_FAILURE; + } + + if (fgStatus == WLAN_STATUS_SUCCESS) + wlanDriverDbgLevelSync(); + + return fgStatus; +} + +uint32_t wlanGetDriverDbgLevel(IN uint32_t u4DbgIdx, OUT uint32_t *pu4DbgMask) +{ + if (u4DbgIdx < DBG_MODULE_NUM) { + *pu4DbgMask = aucDebugModule[u4DbgIdx]; + return WLAN_STATUS_SUCCESS; + } + + return WLAN_STATUS_FAILURE; +} + +uint32_t wlanDbgLevelUiSupport(IN struct ADAPTER *prAdapter, uint32_t u4Version, + uint32_t ucModule) +{ + uint32_t u4Enable = ENUM_WIFI_LOG_LEVEL_SUPPORT_DISABLE; + + switch (u4Version) { + case ENUM_WIFI_LOG_LEVEL_VERSION_V1: + switch (ucModule) { + case ENUM_WIFI_LOG_MODULE_DRIVER: + u4Enable = ENUM_WIFI_LOG_LEVEL_SUPPORT_ENABLE; + break; + case ENUM_WIFI_LOG_MODULE_FW: + u4Enable = ENUM_WIFI_LOG_LEVEL_SUPPORT_ENABLE; + break; + } + break; + default: + break; + } + + return u4Enable; +} + +uint32_t wlanDbgGetLogLevelImpl(IN struct ADAPTER *prAdapter, + uint32_t u4Version, uint32_t ucModule) +{ + uint32_t u4Level = ENUM_WIFI_LOG_LEVEL_DEFAULT; + + switch (u4Version) { + case ENUM_WIFI_LOG_LEVEL_VERSION_V1: + wlanDbgGetGlobalLogLevel(ucModule, &u4Level); + break; + default: + break; + } + + return u4Level; +} + +void wlanDbgSetLogLevelImpl(IN struct ADAPTER *prAdapter, + uint32_t u4Version, uint32_t u4Module, uint32_t u4level) +{ + uint32_t u4DriverLevel = ENUM_WIFI_LOG_LEVEL_DEFAULT; + uint32_t u4FwLevel = ENUM_WIFI_LOG_LEVEL_DEFAULT; + + if (u4level >= ENUM_WIFI_LOG_LEVEL_NUM) + return; + + switch (u4Version) { + case ENUM_WIFI_LOG_LEVEL_VERSION_V1: + wlanDbgSetGlobalLogLevel(u4Module, u4level); + switch (u4Module) { + case ENUM_WIFI_LOG_MODULE_DRIVER: + { + uint32_t u4DriverLogMask; + + if (u4level == ENUM_WIFI_LOG_LEVEL_DEFAULT) + u4DriverLogMask = DBG_LOG_LEVEL_DEFAULT; + else if (u4level == ENUM_WIFI_LOG_LEVEL_MORE) + u4DriverLogMask = DBG_LOG_LEVEL_MORE; + else + u4DriverLogMask = DBG_LOG_LEVEL_EXTREME; + + wlanSetDriverDbgLevel(DBG_ALL_MODULE_IDX, + (u4DriverLogMask & DBG_CLASS_MASK)); + } + break; + case ENUM_WIFI_LOG_MODULE_FW: + { + struct CMD_EVENT_LOG_UI_INFO cmd; + + kalMemZero(&cmd, + sizeof(struct CMD_EVENT_LOG_UI_INFO)); + cmd.ucVersion = u4Version; + cmd.ucLogLevel = u4level; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_LOG_UI_INFO, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_EVENT_LOG_UI_INFO), + (uint8_t *)&cmd, + NULL, + 0); + } + break; + default: + break; + } + break; + default: + break; + } + + wlanDbgGetGlobalLogLevel(ENUM_WIFI_LOG_MODULE_DRIVER, &u4DriverLevel); + wlanDbgGetGlobalLogLevel(ENUM_WIFI_LOG_MODULE_FW, &u4FwLevel); +#if KERNEL_VERSION(4, 14, 0) >= LINUX_VERSION_CODE +#if (CFG_BUILT_IN_DRIVER == 0) && (CFG_MTK_ANDROID_WMT == 1) + /* + * The function definition of get_logtoomuch_enable() and + * set_logtoomuch_enable of Android O0 or lower version are different + * from that of Android O1 or higher version. Wlan driver supports .ko + * module from Android O1. Use CFG_BUILT_IN_DRIVER to distinguish + * Android version higher than O1 instead. + */ + if ((u4DriverLevel > ENUM_WIFI_LOG_LEVEL_DEFAULT || + u4FwLevel > ENUM_WIFI_LOG_LEVEL_DEFAULT) && + get_logtoomuch_enable()) { + DBGLOG(OID, TRACE, + "Disable printk to much. driver: %d, fw: %d\n", + u4DriverLevel, + u4FwLevel); + set_logtoomuch_enable(0); + } +#endif +#endif /* KERNEL_VERSION(4, 14, 0) >= LINUX_VERSION_CODE */ +} + +u_int8_t wlanDbgGetGlobalLogLevel(uint32_t u4Module, uint32_t *pu4Level) +{ + if (u4Module != ENUM_WIFI_LOG_MODULE_DRIVER && + u4Module != ENUM_WIFI_LOG_MODULE_FW) + return FALSE; + + *pu4Level = au4LogLevel[u4Module]; + return TRUE; +} + +u_int8_t wlanDbgSetGlobalLogLevel(uint32_t u4Module, uint32_t u4Level) +{ + if (u4Module != ENUM_WIFI_LOG_MODULE_DRIVER && + u4Module != ENUM_WIFI_LOG_MODULE_FW) + return FALSE; + + au4LogLevel[u4Module] = u4Level; + return TRUE; +} + +void wlanDriverDbgLevelSync(void) +{ + uint8_t i = 0; + uint32_t u4Mask = DBG_CLASS_MASK; + uint32_t u4DriverLogLevel = ENUM_WIFI_LOG_LEVEL_DEFAULT; + + /* get the lowest level as module's level */ + for (i = 0; i < DBG_MODULE_NUM; i++) + u4Mask &= aucDebugModule[i]; + + if ((u4Mask & DBG_LOG_LEVEL_EXTREME) == DBG_LOG_LEVEL_EXTREME) + u4DriverLogLevel = ENUM_WIFI_LOG_LEVEL_EXTREME; + else if ((u4Mask & DBG_LOG_LEVEL_MORE) == DBG_LOG_LEVEL_MORE) + u4DriverLogLevel = ENUM_WIFI_LOG_LEVEL_MORE; + else + u4DriverLogLevel = ENUM_WIFI_LOG_LEVEL_DEFAULT; + + wlanDbgSetGlobalLogLevel(ENUM_WIFI_LOG_MODULE_DRIVER, u4DriverLogLevel); +} + +static void +firmwareHexDump(const uint8_t *pucPreFix, + int32_t i4PreFixType, + int32_t i4RowSize, int32_t i4GroupSize, + const void *pvBuf, size_t len, u_int8_t fgAscii) +{ +#define OLD_KBUILD_MODNAME KBUILD_MODNAME +#undef KBUILD_MODNAME +#define KBUILD_MODNAME "wlan_mt6632_fw" + + const uint8_t *pucPtr = pvBuf; + int32_t i, i4LineLen, i4Remaining = len; + uint8_t ucLineBuf[32 * 3 + 2 + 32 + 1]; + + if (i4RowSize != 16 && i4RowSize != 32) + i4RowSize = 16; + + for (i = 0; i < len; i += i4RowSize) { + i4LineLen = min(i4Remaining, i4RowSize); + i4Remaining -= i4RowSize; + + /* use kernel API */ + hex_dump_to_buffer(pucPtr + i, i4LineLen, i4RowSize, + i4GroupSize, + ucLineBuf, sizeof(ucLineBuf), fgAscii); + + switch (i4PreFixType) { + case DUMP_PREFIX_ADDRESS: + pr_info("%s%p: %s\n", + pucPreFix, pucPtr + i, ucLineBuf); + break; + case DUMP_PREFIX_OFFSET: + pr_info("%s%.8x: %s\n", pucPreFix, i, ucLineBuf); + break; + default: + pr_info("%s%s\n", pucPreFix, ucLineBuf); + break; + } + } +#undef KBUILD_MODNAME +#define KBUILD_MODNAME OLD_KBUILD_MODNAME +} + +void wlanPrintFwLog(uint8_t *pucLogContent, + uint16_t u2MsgSize, uint8_t ucMsgType, + const uint8_t *pucFmt, ...) +{ +#define OLD_KBUILD_MODNAME KBUILD_MODNAME +#define OLD_LOG_FUNC LOG_FUNC +#undef KBUILD_MODNAME +#undef LOG_FUNC +#define KBUILD_MODNAME "wlan_mt6632_fw" +#define LOG_FUNC pr_info +#define DBG_LOG_BUF_SIZE 128 + + int8_t aucLogBuffer[DBG_LOG_BUF_SIZE]; + int32_t err; + va_list args; + + if (u2MsgSize > DEBUG_MSG_SIZE_MAX - 1) { + LOG_FUNC("Firmware Log Size(%d) is too large, type %d\n", + u2MsgSize, ucMsgType); + return; + } + switch (ucMsgType) { + case DEBUG_MSG_TYPE_ASCII: { + uint8_t *pucChr; + + pucLogContent[u2MsgSize] = '\0'; + + /* skip newline */ + pucChr = kalStrChr(pucLogContent, '\0'); + if (*(pucChr - 1) == '\n') + *(pucChr - 1) = '\0'; + + LOG_FUNC("%s\n", pucLogContent); + } + break; + case DEBUG_MSG_TYPE_DRIVER: + /* Only 128 Bytes is available to print in driver */ + va_start(args, pucFmt); + err = vsnprintf(aucLogBuffer, sizeof(aucLogBuffer) - 1, pucFmt, + args); + va_end(args); + aucLogBuffer[DBG_LOG_BUF_SIZE - 1] = '\0'; + if (err >= 0) + LOG_FUNC("%s\n", aucLogBuffer); + break; + case DEBUG_MSG_TYPE_MEM8: + firmwareHexDump("fw data:", DUMP_PREFIX_ADDRESS, + 16, 1, pucLogContent, u2MsgSize, true); + break; + default: + firmwareHexDump("fw data:", DUMP_PREFIX_ADDRESS, + 16, 4, pucLogContent, u2MsgSize, true); + break; + } + +#undef KBUILD_MODNAME +#undef LOG_FUNC +#define KBUILD_MODNAME OLD_KBUILD_MODNAME +#define LOG_FUNC OLD_LOG_FUNC +#undef OLD_KBUILD_MODNAME +#undef OLD_LOG_FUNC +} + +/* Begin: Functions used to breakdown packet jitter, for test case VoE 5.7 */ +static void wlanSetBE32(uint32_t u4Val, uint8_t *pucBuf) +{ + uint8_t *littleEn = (uint8_t *)&u4Val; + + pucBuf[0] = littleEn[3]; + pucBuf[1] = littleEn[2]; + pucBuf[2] = littleEn[1]; + pucBuf[3] = littleEn[0]; +} + +void wlanFillTimestamp(struct ADAPTER *prAdapter, void *pvPacket, + uint8_t ucPhase) +{ + struct sk_buff *skb = (struct sk_buff *)pvPacket; + uint8_t *pucEth = NULL; + uint32_t u4Length = 0; + uint8_t *pucUdp = NULL; + struct timeval tval; + + if (!prAdapter || !prAdapter->rDebugInfo.fgVoE5_7Test || !skb) + return; + pucEth = skb->data; + u4Length = skb->len; + if (u4Length < 200 || + ((pucEth[ETH_TYPE_LEN_OFFSET] << 8) | + (pucEth[ETH_TYPE_LEN_OFFSET + 1])) != ETH_P_IPV4) + return; + if (pucEth[ETH_HLEN+9] != IP_PRO_UDP) + return; + pucUdp = &pucEth[ETH_HLEN+28]; + if (kalStrnCmp(pucUdp, "1345678", 7)) + return; + do_gettimeofday(&tval); + switch (ucPhase) { + case PHASE_XMIT_RCV: /* xmit */ + pucUdp += 20; + break; + case PHASE_ENQ_QM: /* enq */ + pucUdp += 28; + break; + case PHASE_HIF_TX: /* tx */ + pucUdp += 36; + break; + } + wlanSetBE32(tval.tv_sec, pucUdp); + wlanSetBE32(tval.tv_usec, pucUdp+4); +} +/* End: Functions used to breakdown packet jitter, for test case VoE 5.7 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/dump.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/dump.c new file mode 100644 index 0000000000000..3d45a210bbc5b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/dump.c @@ -0,0 +1,461 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: common/dump.c + */ + +/*! \file "dump.c" + * \brief Provide memory dump function for debugging. + * + * Provide memory dump function for debugging. + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to dump a segment of memory in bytes. + * + * \param[in] pucStartAddr Pointer to the starting address of the memory + * to be dumped. + * \param[in] u4Length Length of the memory to be dumped. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void dumpMemory8(IN uint8_t *pucStartAddr, + IN uint32_t u4Length) +{ + ASSERT(pucStartAddr); + + LOG_FUNC("DUMP8 ADDRESS: %p, Length: %d\n", pucStartAddr, + u4Length); + +#define case16 "(%p) %02x %02x %02x %02x %02x %02x %02x %02x" \ + " - %02x %02x %02x %02x %02x %02x %02x %02x\n" + +#define case07 "(%p) %02x %02x %02x %02x %02x %02x %02x\n" + +#define case08 "(%p) %02x %02x %02x %02x %02x %02x %02x %02x\n" + +#define case09 "(%p) %02x %02x %02x %02x %02x %02x %02x %02x" \ + " - %02x\n" + +#define case10 "(%p) %02x %02x %02x %02x %02x %02x %02x %02x" \ + " - %02x %02x\n" + +#define case11 "(%p) %02x %02x %02x %02x %02x %02x %02x %02x" \ + " - %02x %02x %02x\n" + +#define case12 "(%p) %02x %02x %02x %02x %02x %02x %02x %02x" \ + " - %02x %02x %02x %02x\n" + +#define case13 "(%p) %02x %02x %02x %02x %02x %02x %02x %02x" \ + " - %02x %02x %02x %02x %02x\n" + +#define case14 "(%p) %02x %02x %02x %02x %02x %02x %02x %02x" \ + " - %02x %02x %02x %02x %02x %02x\n" + +#define case15 "(%p) %02x %02x %02x %02x %02x %02x %02x %02x" \ + " - %02x %02x %02x %02x %02x %02x %02x\n" + + while (u4Length > 0) { + if (u4Length >= 16) { + LOG_FUNC + (case16, + pucStartAddr, pucStartAddr[0], pucStartAddr[1], + pucStartAddr[2], pucStartAddr[3], pucStartAddr[4], + pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8], pucStartAddr[9], pucStartAddr[10], + pucStartAddr[11], pucStartAddr[12], + pucStartAddr[13], pucStartAddr[14], + pucStartAddr[15]); + u4Length -= 16; + pucStartAddr += 16; + } else { + switch (u4Length) { + case 1: + LOG_FUNC("(%p) %02x\n", pucStartAddr, + pucStartAddr[0]); + break; + case 2: + LOG_FUNC("(%p) %02x %02x\n", pucStartAddr, + pucStartAddr[0], pucStartAddr[1]); + break; + case 3: + LOG_FUNC("(%p) %02x %02x %02x\n", + pucStartAddr, pucStartAddr[0], + pucStartAddr[1], pucStartAddr[2]); + break; + case 4: + LOG_FUNC("(%p) %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], + pucStartAddr[2], pucStartAddr[3]); + break; + case 5: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], + pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4]); + break; + case 6: + LOG_FUNC + ("(%p) %02x %02x %02x %02x %02x %02x\n", + pucStartAddr, pucStartAddr[0], + pucStartAddr[1], pucStartAddr[2], + pucStartAddr[3], pucStartAddr[4], + pucStartAddr[5]); + break; + case 7: + LOG_FUNC + (case07, + pucStartAddr, pucStartAddr[0], + pucStartAddr[1], pucStartAddr[2], + pucStartAddr[3], pucStartAddr[4], + pucStartAddr[5], pucStartAddr[6]); + break; + case 8: + LOG_FUNC + (case08, + pucStartAddr, pucStartAddr[0], + pucStartAddr[1], pucStartAddr[2], + pucStartAddr[3], pucStartAddr[4], + pucStartAddr[5], pucStartAddr[6], + pucStartAddr[7]); + break; + case 9: + LOG_FUNC + (case09, + pucStartAddr, pucStartAddr[0], + pucStartAddr[1], pucStartAddr[2], + pucStartAddr[3], pucStartAddr[4], + pucStartAddr[5], pucStartAddr[6], + pucStartAddr[7], pucStartAddr[8]); + break; + case 10: + LOG_FUNC + (case10, + 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 + (case11, + 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 + (case12, + 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 + (case13, + 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 + (case14, + 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: + default: + LOG_FUNC + (case15, + 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; + } + u4Length = 0; + } + } +} /* 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 uint32_t *pu4StartAddr, + IN uint32_t u4Length) +{ + uint8_t *pucAddr; + + ASSERT(pu4StartAddr); + + LOG_FUNC("DUMP32 ADDRESS: %p, Length: %d\n", pu4StartAddr, + u4Length); + + if (IS_NOT_ALIGN_4((unsigned long)pu4StartAddr)) { + uint32_t u4ProtrudeLen = + sizeof(uint32_t) - ((unsigned long)pu4StartAddr % 4); + + u4ProtrudeLen = + ((u4Length < u4ProtrudeLen) ? u4Length : u4ProtrudeLen); + LOG_FUNC("pu4StartAddr is not at DW boundary.\n"); + pucAddr = (uint8_t *) &pu4StartAddr[0]; + + switch (u4ProtrudeLen) { + case 1: + LOG_FUNC("(%p) %02x------\n", pu4StartAddr, pucAddr[0]); + break; + case 2: + LOG_FUNC("(%p) %02x%02x----\n", pu4StartAddr, + pucAddr[1], pucAddr[0]); + break; + case 3: + LOG_FUNC("(%p) %02x%02x%02x--\n", pu4StartAddr, + pucAddr[2], pucAddr[1], pucAddr[0]); + break; + default: + break; + } + + u4Length -= u4ProtrudeLen; + pu4StartAddr = (uint32_t *) + ((unsigned long)pu4StartAddr + u4ProtrudeLen); + } + + while (u4Length > 0) { + if (u4Length >= 16) { + LOG_FUNC("(%p) %08x %08x %08x %08x\n", + pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], + pu4StartAddr[2], pu4StartAddr[3]); + pu4StartAddr += 4; + u4Length -= 16; + } else { + switch (u4Length) { + case 1: + pucAddr = (uint8_t *) &pu4StartAddr[0]; + LOG_FUNC("(%p) ------%02x\n", + pu4StartAddr, pucAddr[0]); + break; + case 2: + pucAddr = (uint8_t *) &pu4StartAddr[0]; + LOG_FUNC("(%p) ----%02x%02x\n", pu4StartAddr, + pucAddr[1], pucAddr[0]); + break; + case 3: + pucAddr = (uint8_t *) &pu4StartAddr[0]; + LOG_FUNC("(%p) --%02x%02x%02x\n", pu4StartAddr, + pucAddr[2], pucAddr[1], pucAddr[0]); + break; + case 4: + LOG_FUNC("(%p) %08x\n", pu4StartAddr, + pu4StartAddr[0]); + break; + case 5: + pucAddr = (uint8_t *) &pu4StartAddr[1]; + LOG_FUNC("(%p) %08x ------%02x\n", pu4StartAddr, + pu4StartAddr[0], pucAddr[0]); + break; + case 6: + pucAddr = (uint8_t *) &pu4StartAddr[1]; + LOG_FUNC("(%p) %08x ----%02x%02x\n", + pu4StartAddr, pu4StartAddr[0], + pucAddr[1], pucAddr[0]); + break; + case 7: + pucAddr = (uint8_t *) &pu4StartAddr[1]; + LOG_FUNC("(%p) %08x --%02x%02x%02x\n", + pu4StartAddr, pu4StartAddr[0], + pucAddr[2], pucAddr[1], pucAddr[0]); + break; + case 8: + LOG_FUNC("(%p) %08x %08x\n", pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1]); + break; + case 9: + pucAddr = (uint8_t *) &pu4StartAddr[2]; + LOG_FUNC("(%p) %08x %08x ------%02x\n", + pu4StartAddr, pu4StartAddr[0], + pu4StartAddr[1], pucAddr[0]); + break; + case 10: + pucAddr = (uint8_t *) &pu4StartAddr[2]; + LOG_FUNC("(%p) %08x %08x ----%02x%02x\n", + pu4StartAddr, pu4StartAddr[0], + pu4StartAddr[1], pucAddr[1], + pucAddr[0]); + break; + case 11: + pucAddr = (uint8_t *) &pu4StartAddr[2]; + LOG_FUNC("(%p) %08x %08x --%02x%02x%02x\n", + pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], + pucAddr[2], pucAddr[1], pucAddr[0]); + break; + case 12: + LOG_FUNC("(%p) %08x %08x %08x\n", + pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], + pu4StartAddr[2]); + break; + case 13: + pucAddr = (uint8_t *) &pu4StartAddr[3]; + LOG_FUNC("(%p) %08x %08x %08x ------%02x\n", + pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], + pu4StartAddr[2], pucAddr[0]); + break; + case 14: + pucAddr = (uint8_t *) &pu4StartAddr[3]; + LOG_FUNC("(%p) %08x %08x %08x ----%02x%02x\n", + pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], + pu4StartAddr[2], + pucAddr[1], pucAddr[0]); + break; + case 15: + default: + pucAddr = (uint8_t *) &pu4StartAddr[3]; + LOG_FUNC("(%p) %08x %08x %08x --%02x%02x%02x\n", + pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], + pu4StartAddr[2], + pucAddr[2], pucAddr[1], pucAddr[0]); + break; + } + u4Length = 0; + } + } +} /* end of dumpMemory32() */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/wlan_bow.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/wlan_bow.c new file mode 100644 index 0000000000000..d5be1871e0381 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/wlan_bow.c @@ -0,0 +1,3222 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + +/****************************************************************************** +* C O M P I L E R F L A G S +******************************************************************************* +*/ + +/****************************************************************************** +* E X T E R N A L R E F E R E N C E S +******************************************************************************* +*/ +#include "precomp.h" + +#if CFG_ENABLE_BT_OVER_WIFI + +/****************************************************************************** +* C O N S T A N T S +******************************************************************************* +*/ + +/****************************************************************************** +* D A T A T Y P E S +******************************************************************************* +*/ + +/****************************************************************************** +* P U B L I C D A T A +******************************************************************************* +*/ + +#if 1 /* Marked for MT6630 */ +static uint32_t g_u4LinkCount; +static uint32_t g_u4Beaconing; +static struct BOW_TABLE arBowTable[CFG_BOW_PHYSICAL_LINK_NUM]; +#endif + +/****************************************************************************** +* P R I V A T E D A T A +******************************************************************************* +*/ + +const struct BOW_CMD 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 +******************************************************************************* +*/ + +#if 1 /* Marked for MT6630 */ +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSendSetQueryBowCmd(IN struct ADAPTER *prAdapter, + IN uint8_t ucCID, + IN uint8_t ucBssIdx, + IN u_int8_t fgSetQuery, + IN u_int8_t fgNeedResp, + IN PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + IN PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + IN uint32_t u4SetQueryInfoLen, IN uint8_t *pucInfoBuffer, IN uint8_t ucSeqNumber) +{ + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + u_int8_t *pWifiCmdBufAddr; + struct mt66xx_chip_info *prChipInfo; + uint16_t cmd_size; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + prChipInfo = prAdapter->chip_info; + ASSERT(prGlueInfo); + + DBGLOG(REQ, TRACE, "Command ID = 0x%08X\n", ucCID); + + cmd_size = prChipInfo->u2CmdTxHdrSize + u4SetQueryInfoLen; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, cmd_size); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->u2InfoBufLen = cmd_size; + prCmdInfo->pfCmdDoneHandler = pfCmdDoneHandler; + prCmdInfo->pfCmdTimeoutHandler = pfCmdTimeoutHandler; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = ucCID; + prCmdInfo->fgSetQuery = fgSetQuery; + prCmdInfo->fgNeedResp = fgNeedResp; + prCmdInfo->u4SetInfoLen = u4SetQueryInfoLen; + prCmdInfo->pvInformationBuffer = NULL; + prCmdInfo->u4InformationBufferLength = 0; + prCmdInfo->u4PrivateData = (uint32_t) ucSeqNumber; + + /* Setup WIFI_CMD (no payload) */ + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + prCmdInfo->ucCID, + CMD_PACKET_TYPE_ID, + &prCmdInfo->ucCmdSeqNum, + prCmdInfo->fgSetQuery, + &pWifiCmdBufAddr, FALSE, 0, S2D_INDEX_CMD_H2N); + + if (u4SetQueryInfoLen > 0 && pucInfoBuffer != NULL) + kalMemCopy(pWifiCmdBufAddr, pucInfoBuffer, u4SetQueryInfoLen); + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (struct QUE_ENTRY *) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + return WLAN_STATUS_PENDING; +} + +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +uint32_t wlanbowHandleCommand(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd) +{ +#if 1 /* Marked for MT6630 */ + uint32_t retval = WLAN_STATUS_FAILURE; + uint16_t i; + + ASSERT(prAdapter); + + for (i = 0; i < sizeof(arBowCmdTable) / sizeof(struct BOW_CMD); i++) { + if ((arBowCmdTable[i].uCmdID == prCmd->rHeader.ucCommandId) && arBowCmdTable[i].pfCmdHandle) { + retval = arBowCmdTable[i].pfCmdHandle(prAdapter, prCmd); + break; + } + } + + return retval; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +uint32_t bowCmdGetMacStatus(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd) +{ +#if 1 /* Marked for MT6630 */ + struct BT_OVER_WIFI_EVENT *prEvent; + struct BOW_MAC_STATUS *prMacStatus; + uint8_t idx = 0; + uint8_t ucPrimaryChannel; + enum ENUM_BAND eBand; + enum ENUM_CHNL_EXT eBssSCO; + uint8_t ucNumOfChannel = 0; /* MAX_BOW_NUMBER_OF_CHANNEL; */ + + struct RF_CHANNEL_INFO 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 = (struct BT_OVER_WIFI_EVENT *) kalMemAlloc((sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct BOW_MAC_STATUS)), VIR_MEM_TYPE); + + prEvent->rHeader.ucEventId = BOW_EVENT_ID_MAC_STATUS; + prEvent->rHeader.ucSeqNumber = prCmd->rHeader.ucSeqNumber; + prEvent->rHeader.u2PayloadLength = sizeof(struct BOW_MAC_STATUS); + + /* fill event body */ + prMacStatus = (struct BOW_MAC_STATUS *) (prEvent->aucPayload); + kalMemZero(prMacStatus, sizeof(struct 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)) { + DBGLOG(BOW, EVENT, "bowCmdGetMacStatus, Get preferred channel.\n"); + + prMacStatus->ucNumOfChannel = 1; + prMacStatus->arChannelList[0].ucChannelBand = eBand; + prMacStatus->arChannelList[0].ucChannelNum = ucPrimaryChannel; + } else { + DBGLOG(BOW, EVENT, + "bowCmdGetMacStatus, Get channel list. Current number of channel, %d.\n", ucNumOfChannel); + + rlmDomainGetChnlList(prAdapter, BAND_2G4, FALSE, 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, FALSE, + 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; + + } + } + + 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, %x, %x.\n", + prMacStatus->ucNumOfChannel, prMacStatus->arChannelList[0].ucChannelBand); + DBGLOG(BOW, EVENT, + "prMacStatus->arChannelList, %x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x.\n", + prMacStatus->arChannelList[0].ucChannelNum, + prMacStatus->arChannelList[1].ucChannelNum, + prMacStatus->arChannelList[2].ucChannelNum, + prMacStatus->arChannelList[3].ucChannelNum, + prMacStatus->arChannelList[4].ucChannelNum, + prMacStatus->arChannelList[5].ucChannelNum, + prMacStatus->arChannelList[6].ucChannelNum, + prMacStatus->arChannelList[7].ucChannelNum, + prMacStatus->arChannelList[8].ucChannelNum, + prMacStatus->arChannelList[9].ucChannelNum, + prMacStatus->arChannelList[10].ucChannelNum, + prMacStatus->arChannelList[11].ucChannelNum, + prMacStatus->arChannelList[12].ucChannelNum, + prMacStatus->arChannelList[13].ucChannelNum, + prMacStatus->arChannelList[14].ucChannelNum, + prMacStatus->arChannelList[15].ucChannelNum, + prMacStatus->arChannelList[16].ucChannelNum, prMacStatus->arChannelList[17].ucChannelNum); + + DBGLOG(BOW, 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]); + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct BOW_MAC_STATUS))); + + return WLAN_STATUS_SUCCESS; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +uint32_t bowCmdSetupConnection(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd) +{ +#if 1 /* Marked for MT6630 */ + struct BOW_SETUP_CONNECTION *prBowSetupConnection; + struct CMD_BT_OVER_WIFI rCmdBtOverWifi; + struct BOW_FSM_INFO *prBowFsmInfo; + struct BOW_TABLE rBowTable; + + uint8_t ucBowTableIdx = 0; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowSetupConnection = (struct BOW_SETUP_CONNECTION *) &(prCmd->aucPayload[0]); + + /* parameter size check */ + if (prCmd->rHeader.u2PayloadLength != sizeof(struct 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; + + 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); + + /* 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.eState = BOW_DEVICE_STATE_NUM; /* Just initiate */ + 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); + + DBGLOG(BOW, EVENT, "bowStarting, g_u4LinkCount, %x.\n", g_u4LinkCount); + + if (g_u4LinkCount == 1) { + DBGLOG(BOW, EVENT, "bowStarting, cnmTimerInitTimer.\n"); + DBGLOG(BOW, EVENT, "prBowFsmInfo->u2BeaconInterval, %d.\n", prBowFsmInfo->u2BeaconInterval); + + cnmTimerInitTimer(prAdapter, + &prBowFsmInfo->rStartingBeaconTimer, + (PFN_MGMT_TIMEOUT_FUNC) bowSendBeacon, (unsigned long) NULL); + + cnmTimerInitTimer(prAdapter, + &prBowFsmInfo->rChGrantedTimer, + (PFN_MGMT_TIMEOUT_FUNC) bowChGrantedTimeout, (unsigned long) NULL); + + /* Reset Global Variable */ + g_u4Beaconing = 0; + + DBGLOG(BOW, EVENT, "bowCmdSetupConnection, g_u4LinkCount, %x.\n", g_u4LinkCount); + DBGLOG(BOW, EVENT, "kalInitBowDevice, bow0\n"); + +#if CFG_BOW_SEPARATE_DATA_PATH + kalInitBowDevice(prAdapter->prGlueInfo, BOWDEVNAME); +#endif + + /*Active BoW Network */ + SET_NET_ACTIVE(prAdapter, prBowFsmInfo->ucBssIndex); + SET_NET_PWR_STATE_ACTIVE(prAdapter, prBowFsmInfo->ucBssIndex); + nicActivateNetwork(prAdapter, prBowFsmInfo->ucBssIndex); + + } + + 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; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +uint32_t bowCmdDestroyConnection(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd) +{ +#if 1 /* Marked for MT6630 */ + struct BOW_DESTROY_CONNECTION *prBowDestroyConnection; + struct CMD_BT_OVER_WIFI rCmdBtOverWifi; + struct BOW_FSM_INFO *prBowFsmInfo; + + uint8_t ucIdx; + + 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(struct 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 = (struct BOW_DESTROY_CONNECTION *) &(prCmd->aucPayload[0]); + + if (!bowCheckBowTableIfVaild(prAdapter, prBowDestroyConnection->aucPeerAddress)) { + DBGLOG(BOW, EVENT, "bowCmdDestroyConnection, bowCheckIfVaild, not accepted.\n"); + return WLAN_STATUS_NOT_ACCEPTED; + } + + 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]); + + /* fill CMD_BT_OVER_WIFI */ + rCmdBtOverWifi.ucAction = 2; + COPY_MAC_ADDR(rCmdBtOverWifi.rPeerAddr, prBowDestroyConnection->aucPeerAddress); + COPY_MAC_ADDR(prBowFsmInfo->aucPeerAddress, prBowDestroyConnection->aucPeerAddress); + + 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]); + + 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]); + } + + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_SUCCESS); + + return wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + prBowFsmInfo->ucBssIndex, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, + sizeof(struct CMD_BT_OVER_WIFI), + (uint8_t *)&rCmdBtOverWifi, prCmd->rHeader.ucSeqNumber); + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +uint32_t bowCmdSetPTK(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd) +{ +#if 1 /* Marked for MT6630 */ + struct BOW_SET_PTK *prBowSetPTK; + struct CMD_802_11_KEY rCmdKey; + struct BOW_FSM_INFO *prBowFsmInfo; + struct STA_RECORD *prStaRec = NULL; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + /* parameter size check */ + if (prCmd->rHeader.u2PayloadLength != sizeof(struct BOW_SET_PTK)) + return WLAN_STATUS_INVALID_LENGTH; + + prBowSetPTK = (struct BOW_SET_PTK *) &(prCmd->aucPayload[0]); + + 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)); + + 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.ucBssIdx = prBowFsmInfo->ucBssIndex; /* BT Over Wi-Fi */ + rCmdKey.ucAlgorithmId = CIPHER_SUITE_CCMP; /* AES */ + rCmdKey.ucKeyId = 0; + rCmdKey.ucKeyLen = 16; /* AES = 128bit */ + kalMemCopy(rCmdKey.aucKeyMaterial, prBowSetPTK->aucTemporalKey, 16); + + /* BT Over Wi-Fi */ + prStaRec = cnmGetStaRecByAddress(prAdapter, prBowFsmInfo->ucBssIndex, prBowSetPTK->aucPeerAddress); + rCmdKey.ucWlanIndex = prStaRec->ucWlanIndex; + + 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]); + + return wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_ADD_REMOVE_KEY, + prBowFsmInfo->ucBssIndex, + TRUE, + FALSE, + wlanbowCmdEventSetCommon, + wlanbowCmdTimeoutHandler, + sizeof(struct CMD_802_11_KEY), (uint8_t *)&rCmdKey, prCmd->rHeader.ucSeqNumber); +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +uint32_t bowCmdReadRSSI(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd) +{ +#if 1 /* Marked for MT6630 */ + struct BOW_READ_RSSI *prBowReadRSSI; + struct BOW_FSM_INFO *prBowFsmInfo; + + ASSERT(prAdapter); + + if (prAdapter->fgIsEnableLpdvt) + return WLAN_STATUS_NOT_SUPPORTED; + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + /* parameter size check */ + if (prCmd->rHeader.u2PayloadLength != sizeof(struct BOW_READ_RSSI)) + return WLAN_STATUS_INVALID_LENGTH; + + prBowReadRSSI = (struct BOW_READ_RSSI *) &(prCmd->aucPayload[0]); + + return wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + prBowFsmInfo->ucBssIndex, + FALSE, + TRUE, + wlanbowCmdEventReadRssi, + wlanbowCmdTimeoutHandler, 0, NULL, prCmd->rHeader.ucSeqNumber); + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +uint32_t bowCmdReadLinkQuality(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd) +{ +#if 1 /* Marked for MT6630 */ + struct BOW_READ_LINK_QUALITY *prBowReadLinkQuality; + struct BOW_FSM_INFO *prBowFsmInfo; + + ASSERT(prAdapter); + + if (prAdapter->fgIsEnableLpdvt) + return WLAN_STATUS_NOT_SUPPORTED; + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + /* parameter size check */ + if (prCmd->rHeader.u2PayloadLength != sizeof(struct BOW_READ_LINK_QUALITY *)) + return WLAN_STATUS_INVALID_LENGTH; + + prBowReadLinkQuality = (struct BOW_READ_LINK_QUALITY *) &(prCmd->aucPayload[0]); + + return wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + prBowFsmInfo->ucBssIndex, + FALSE, + TRUE, + wlanbowCmdEventReadLinkQuality, + wlanbowCmdTimeoutHandler, 0, NULL, prCmd->rHeader.ucSeqNumber); + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +uint32_t bowCmdShortRangeMode(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd) +{ +#if 1 /* Marked for MT6630 */ + struct BOW_SHORT_RANGE_MODE *prBowShortRangeMode; + struct CMD_TX_PWR rTxPwrParam; + + ASSERT(prAdapter); + + DBGLOG(BOW, EVENT, "bowCmdShortRangeMode.\n"); + + prBowShortRangeMode = (struct BOW_SHORT_RANGE_MODE *) &(prCmd->aucPayload[0]); + + /* parameter size check */ + if (prCmd->rHeader.u2PayloadLength != sizeof(struct 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; + } + + 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]); + + 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) { + DBGLOG(BOW, EVENT, "bowCmdShortRangeMode, %x.\n", WLAN_STATUS_SUCCESS); + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_SUCCESS); + return WLAN_STATUS_SUCCESS; + } + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_FAILURE); + return WLAN_STATUS_FAILURE; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +uint32_t bowCmdGetChannelList(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd) +{ + ASSERT(prAdapter); + + /* not supported yet */ + return WLAN_STATUS_FAILURE; +} + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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 struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd, IN uint8_t ucEventBuf) +{ + struct BT_OVER_WIFI_EVENT *prEvent; + struct BOW_COMMAND_STATUS *prBowCmdStatus; + + ASSERT(prAdapter); + + /* fill event header */ + prEvent = (struct BT_OVER_WIFI_EVENT *) kalMemAlloc((sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct BOW_COMMAND_STATUS)), VIR_MEM_TYPE); + prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; + prEvent->rHeader.ucSeqNumber = prCmd->rHeader.ucSeqNumber; + prEvent->rHeader.u2PayloadLength = sizeof(struct BOW_COMMAND_STATUS); + + /* fill event body */ + prBowCmdStatus = (struct BOW_COMMAND_STATUS *) (prEvent->aucPayload); + kalMemZero(prBowCmdStatus, sizeof(struct BOW_COMMAND_STATUS)); + + prBowCmdStatus->ucStatus = ucEventBuf; + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct 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 struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct BT_OVER_WIFI_EVENT *prEvent; + struct BOW_COMMAND_STATUS *prBowCmdStatus; + + ASSERT(prAdapter); + + /* fill event header */ + prEvent = (struct BT_OVER_WIFI_EVENT *) kalMemAlloc((sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct BOW_COMMAND_STATUS)), VIR_MEM_TYPE); + prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; + prEvent->rHeader.ucSeqNumber = (uint8_t) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(struct BOW_COMMAND_STATUS); + + /* fill event body */ + prBowCmdStatus = (struct BOW_COMMAND_STATUS *) (prEvent->aucPayload); + kalMemZero(prBowCmdStatus, sizeof(struct BOW_COMMAND_STATUS)); + + prBowCmdStatus->ucStatus = BOWCMD_STATUS_SUCCESS; + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct 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 struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct BT_OVER_WIFI_EVENT *prEvent; + struct BOW_LINK_CONNECTED *prBowLinkConnected; + struct BOW_FSM_INFO *prBowFsmInfo; + struct BSS_INFO *prBssInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + /* fill event header */ + prEvent = (struct BT_OVER_WIFI_EVENT *) kalMemAlloc((sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct BOW_LINK_CONNECTED)), VIR_MEM_TYPE); + prEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_CONNECTED; + prEvent->rHeader.ucSeqNumber = (uint8_t) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(struct BOW_LINK_CONNECTED); + + /* fill event body */ + prBowLinkConnected = (struct BOW_LINK_CONNECTED *) (prEvent->aucPayload); + kalMemZero(prBowLinkConnected, sizeof(struct BOW_LINK_CONNECTED)); + prBowLinkConnected->rChannel.ucChannelNum = prBssInfo->ucPrimaryChannel; + prBowLinkConnected->rChannel.ucChannelBand = prBssInfo->eBand; + COPY_MAC_ADDR(prBowLinkConnected->aucPeerAddress, prBowFsmInfo->aucPeerAddress); + + 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); + + /*Indicate Event to PAL */ + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct 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 struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct BT_OVER_WIFI_EVENT *prEvent; + struct BOW_LINK_DISCONNECTED *prBowLinkDisconnected; + struct BOW_FSM_INFO *prBowFsmInfo; + struct BOW_TABLE rBowTable; + uint8_t ucBowTableIdx; + enum ENUM_BOW_DEVICE_STATE eFsmState; + u_int8_t 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 = (struct BT_OVER_WIFI_EVENT *) kalMemAlloc((sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct BOW_LINK_DISCONNECTED)), VIR_MEM_TYPE); + prEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_DISCONNECTED; + if ((prCmdInfo->u4PrivateData)) + prEvent->rHeader.ucSeqNumber = (uint8_t) prCmdInfo->u4PrivateData; + else + prEvent->rHeader.ucSeqNumber = 0; + + prEvent->rHeader.u2PayloadLength = sizeof(struct BOW_LINK_DISCONNECTED); + + /* fill event body */ + prBowLinkDisconnected = (struct BOW_LINK_DISCONNECTED *) (prEvent->aucPayload); + kalMemZero(prBowLinkDisconnected, sizeof(struct BOW_LINK_DISCONNECTED)); + prBowLinkDisconnected->ucReason = 0x0; + COPY_MAC_ADDR(prBowLinkDisconnected->aucPeerAddress, prBowFsmInfo->aucPeerAddress); + + 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); + + /*Indicate BoW event to PAL */ +#if 0 + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct BOW_LINK_DISCONNECTED))); +#endif + + /* set to disconnected status */ + prBowFsmInfo->prTargetStaRec = + cnmGetStaRecByAddress(prAdapter, prBowFsmInfo->ucBssIndex, 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; + DBGLOG(BOW, EVENT, + "wlanbowCmdEventLinkDisconnected, bowGetBowTableState, %x.\n", + bowGetBowTableState(prAdapter, prBowLinkDisconnected->aucPeerAddress)); + authSendDeauthFrame(prAdapter, NULL, prBowFsmInfo->prTargetStaRec, + (struct SW_RFB *) 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; + rBowTable.ucAcquireID = 0; /* Just initiate */ + bowSetBowTableContent(prAdapter, ucBowTableIdx, &rBowTable); + + /*Indicate BoW event to PAL */ + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct 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 struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct BT_OVER_WIFI_EVENT *prEvent; + struct BOW_COMMAND_STATUS *prBowCmdStatus; + struct WIFI_CMD *prWifiCmd; + struct CMD_BT_OVER_WIFI *prCmdBtOverWifi; + struct BOW_FSM_INFO *prBowFsmInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + /* restore original command for rPeerAddr */ + prWifiCmd = (struct WIFI_CMD *) (prCmdInfo->pucInfoBuffer); + prCmdBtOverWifi = (struct CMD_BT_OVER_WIFI *) (prWifiCmd->aucBuffer); + + /* fill event header */ + prEvent = (struct BT_OVER_WIFI_EVENT *) kalMemAlloc((sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct BOW_COMMAND_STATUS)), VIR_MEM_TYPE); + prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; + prEvent->rHeader.ucSeqNumber = (uint8_t) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(struct BOW_COMMAND_STATUS); + + /* fill event body */ + prBowCmdStatus = (struct BOW_COMMAND_STATUS *) (prEvent->aucPayload); + kalMemZero(prBowCmdStatus, sizeof(struct BOW_COMMAND_STATUS)); + prBowCmdStatus->ucStatus = BOWCMD_STATUS_SUCCESS; + + /*Indicate BoW event to PAL */ + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct 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 struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct LINK_QUALITY *prLinkQuality; + struct BT_OVER_WIFI_EVENT *prEvent; + struct BOW_LINK_QUALITY *prBowLinkQuality; + + ASSERT(prAdapter); + + prLinkQuality = (struct LINK_QUALITY *) pucEventBuf; + + /* fill event header */ + prEvent = (struct BT_OVER_WIFI_EVENT *) kalMemAlloc((sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct BOW_LINK_QUALITY)), VIR_MEM_TYPE); + prEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_QUALITY; + prEvent->rHeader.ucSeqNumber = (uint8_t) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(struct BOW_LINK_QUALITY); + + /* fill event body */ + prBowLinkQuality = (struct BOW_LINK_QUALITY *) (prEvent->aucPayload); + kalMemZero(prBowLinkQuality, sizeof(struct BOW_LINK_QUALITY)); + prBowLinkQuality->ucLinkQuality = (uint8_t) prLinkQuality->cLinkQuality; + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct 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 struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct LINK_QUALITY *prLinkQuality; + struct BT_OVER_WIFI_EVENT *prEvent; + struct BOW_RSSI *prBowRssi; + + ASSERT(prAdapter); + + prLinkQuality = (struct LINK_QUALITY *) pucEventBuf; + + /* fill event header */ + prEvent = (struct BT_OVER_WIFI_EVENT *) kalMemAlloc((sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct BOW_LINK_QUALITY)), VIR_MEM_TYPE); + prEvent->rHeader.ucEventId = BOW_EVENT_ID_RSSI; + prEvent->rHeader.ucSeqNumber = (uint8_t) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(struct BOW_RSSI); + + /* fill event body */ + prBowRssi = (struct BOW_RSSI *) (prEvent->aucPayload); + kalMemZero(prBowRssi, sizeof(struct BOW_RSSI)); + prBowRssi->cRssi = (int8_t) prLinkQuality->cRssi; + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct 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 struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo) +{ + struct BT_OVER_WIFI_EVENT *prEvent; + struct BOW_COMMAND_STATUS *prBowCmdStatus; + + ASSERT(prAdapter); + + /* fill event header */ + prEvent = (struct BT_OVER_WIFI_EVENT *) kalMemAlloc((sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct BOW_COMMAND_STATUS)), VIR_MEM_TYPE); + prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; + prEvent->rHeader.ucSeqNumber = (uint8_t) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(struct BOW_COMMAND_STATUS); + + /* fill event body */ + prBowCmdStatus = (struct BOW_COMMAND_STATUS *) (prEvent->aucPayload); + kalMemZero(prBowCmdStatus, sizeof(struct BOW_COMMAND_STATUS)); + + prBowCmdStatus->ucStatus = BOWCMD_STATUS_TIMEOUT; /* timeout */ + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct BOW_COMMAND_STATUS))); + +} + +/* Bruce, 20140224 */ +uint8_t bowInit(IN struct ADAPTER *prAdapter) +{ + struct BSS_INFO *prBowBssInfo; + struct BOW_FSM_INFO *prBowFsmInfo; + + ASSERT(prAdapter); + + prBowBssInfo = cnmGetBssInfoAndInit(prAdapter, NETWORK_TYPE_BOW, TRUE); + + /*Initiate BSS_INFO_T - common part -move from bowstarting */ + BSS_INFO_INIT(prAdapter, prBowBssInfo); + + prBowBssInfo->eCurrentOPMode = OP_MODE_BOW; + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowFsmInfo->ucBssIndex = prBowBssInfo->ucBssIndex; + + /* Setup Own MAC & BSSID */ + COPY_MAC_ADDR(prBowBssInfo->aucOwnMacAddr, prAdapter->rWifiVar.aucDeviceAddress); + COPY_MAC_ADDR(prBowBssInfo->aucBSSID, prAdapter->rWifiVar.aucDeviceAddress); + + return prBowBssInfo->ucBssIndex; +} + +/* Bruce, 20140224 */ +void bowUninit(IN struct ADAPTER *prAdapter) +{ + struct BSS_INFO *prBowBssInfo; + struct BOW_FSM_INFO *prBowFsmInfo; + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + cnmFreeBssInfo(prAdapter, prBowBssInfo); +} + +void bowStopping(IN struct ADAPTER *prAdapter) +{ + struct BOW_FSM_INFO *prBowFsmInfo; + struct BSS_INFO *prBowBssInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + 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]); + DBGLOG(BOW, EVENT, "BoW Stoping,[%d,%d]\n", g_u4LinkCount, g_u4Beaconing); + + if (g_u4LinkCount == 0) { + /*Stop beaconing */ + GLUE_DEC_REF_CNT(g_u4Beaconing); + + /*Deactive BoW network */ + /* prBowBssInfo->fgIsNetActive = FALSE; */ + /* prBowBssInfo->fgIsBeaconActivated = FALSE; */ + nicPmIndicateBssAbort(prAdapter, prBowBssInfo->ucBssIndex); + bowChangeMediaState(prBowBssInfo, MEDIA_STATE_DISCONNECTED); + nicUpdateBss(prAdapter, prBowBssInfo->ucBssIndex); + /*temp solution for FW hal_pwr_mgt.c#3037 ASSERT */ + nicDeactivateNetwork(prAdapter, prBowBssInfo->ucBssIndex); + SET_NET_PWR_STATE_IDLE(prAdapter, prBowBssInfo->ucBssIndex); + UNSET_NET_ACTIVE(prAdapter, prBowBssInfo->ucBssIndex); + + } + +} + +void bowStarting(IN struct ADAPTER *prAdapter) +{ + struct BOW_FSM_INFO *prBowFsmInfo; + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if (g_u4LinkCount == 1) { + DBGLOG(BOW, EVENT, "BoW Starting.\n"); + DBGLOG(BOW, EVENT, "BoW channel granted.\n"); + + /* 3 <1> Update BSS_INFO_T per Network Basis */ + /* 4 <1.1> Setup Operation Mode */ + + /* Bruce, 20140224 */ + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + /* 4 <1.2> Setup SSID */ + prBssInfo->ucSSIDLen = BOW_SSID_LEN; + bowAssignSsid(prBssInfo->aucSSID, prBssInfo->aucOwnMacAddr); + + 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]); + + /* 4 <1.3> Clear current AP's STA_RECORD_T and current AID */ + prBssInfo->prStaRecOfAP = (struct STA_RECORD *) NULL; + prBssInfo->u2AssocId = 0; + + /* 4 <1.4> Setup Channel, Band and Phy Attributes */ + prBssInfo->ucPrimaryChannel = prBowFsmInfo->ucPrimaryChannel; + if (prBowFsmInfo->eBand == BAND_2G4) + prBssInfo->eBand = BAND_2G4; + else + prBssInfo->eBand = BAND_5G; + +#if CFG_BOW_SUPPORT_11N + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11BGN; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; + + prBssInfo->ucNonHTBasicPhyType = (uint8_t) + rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].ePhyTypeIndex; + prBssInfo->u2BSSBasicRateSet = rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].u2BSSBasicRateSet; + + prBssInfo->u2OperationalRateSet = + rNonHTPhyAttributes[prBssInfo->ucNonHTBasicPhyType].u2SupportedRateSet; + + rateGetDataRatesFromRateSet(prBssInfo->u2OperationalRateSet, + prBssInfo->u2BSSBasicRateSet, + prBssInfo->aucAllSupportedRates, &prBssInfo->ucAllSupportedRatesLen); + +#else + if (prBssInfo->eBand == BAND_2G4) { + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11BG; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; + + /* RATE_SET_ERP; */ + prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_ERP; + prBssInfo->u2OperationalRateSet = RATE_SET_ERP; + prBssInfo->ucNonHTBasicPhyType = PHY_TYPE_ERP_INDEX; + } else { + /* Depend on eBand */ + /* prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11BG; */ + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + /* prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; */ + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11A; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_11A; + + /* RATE_SET_ERP; */ + /* prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_ERP; */ + /* prBssInfo->u2OperationalRateSet = RATE_SET_ERP; */ + + /* RATE_SET_ERP; */ + prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_OFDM; + prBssInfo->u2OperationalRateSet = RATE_SET_OFDM; + prBssInfo->ucNonHTBasicPhyType = PHY_TYPE_OFDM_INDEX; + } + +#endif + prBssInfo->fgErpProtectMode = FALSE; + + /* 4 <1.5> Setup MIB for current BSS */ + prBssInfo->u2BeaconInterval = prBowFsmInfo->u2BeaconInterval; + prBssInfo->ucDTIMPeriod = DOT11_DTIM_PERIOD_DEFAULT; + prBssInfo->u2ATIMWindow = 0; + prBssInfo->ucBeaconTimeoutCount = 0; + if (prBowFsmInfo->fgSupportQoS) { + prAdapter->rWifiVar.ucQoS = TRUE; + prBssInfo->fgIsQBSS = TRUE; + } + + /* 3 <2> Update BSS_INFO_T common part */ +#if CFG_SUPPORT_AAA + bssInitForAP(prAdapter, prBssInfo, TRUE); + nicQmUpdateWmmParms(prAdapter, prBssInfo->ucBssIndex); +#endif /* CFG_SUPPORT_AAA */ + prBssInfo->fgIsNetActive = TRUE; + prBssInfo->fgIsBeaconActivated = TRUE; + + /* 3 <3> Set MAC HW */ + + 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]); + + /* 4 <3.1> use command packets to inform firmware */ + rlmBssInitForAPandIbss(prAdapter, prBssInfo); + nicUpdateBss(prAdapter, prBssInfo->ucBssIndex); + + /* 4 <3.2> Update AdHoc PM parameter */ + nicPmIndicateBssCreated(prAdapter, prBssInfo->ucBssIndex); + + /* 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 + { + uint32_t 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); + + DBGLOG(BOW, EVENT, "BoW Starting,[%d,%d]\n", g_u4LinkCount, g_u4Beaconing); + DBGLOG(BOW, EVENT, "bowStarting, g_u4LinkCount, %x.\n", g_u4LinkCount); + + /*Start beaconing */ + if (g_u4Beaconing < 1) { + GLUE_INC_REF_CNT(g_u4Beaconing); + bssSendBeaconProbeResponse(prAdapter, prBssInfo->ucBssIndex, NULL, 0); + cnmTimerStartTimer(prAdapter, &prBowFsmInfo->rStartingBeaconTimer, prBowFsmInfo->u2BeaconInterval); + } +#if 0 + /*Responder: Start to scan Initiator */ + if (prBowFsmInfo->ucRole == BOW_RESPONDER) { + DBGLOG(BOW, EVENT, "bowStarting responder, start scan result searching.\n"); + cnmTimerStopTimer(prAdapter, &prBowFsmInfo->rChGrantedTimer); + bowReleaseCh(prAdapter); + bowResponderScan(prAdapter); + } + /*Initiator: Request channel, wait for responder */ + /* else + * bowRequestCh(prAdapter); + */ +#endif + + /* wlanBindBssIdxToNetInterface(prAdapter->prGlueInfo, NET_DEV_BOW_IDX, prBssInfo->ucBssIndex); */ + +} + +void bowAssignSsid(IN uint8_t *pucSsid, IN uint8_t *puOwnMacAddr) +{ + uint8_t i; + uint8_t 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; + } + +} + +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t bowValidateProbeReq(IN struct ADAPTER *prAdapter, IN struct SW_RFB *prSwRfb, OUT uint32_t *pu4ControlFlags) +{ +#if 1 /* Marked for MT6630 */ + + struct WLAN_MAC_MGMT_HEADER *prMgtHdr; + struct BOW_FSM_INFO *prBowFsmInfo; + struct BSS_INFO *prBssInfo; + struct IE_SSID *prIeSsid = (struct IE_SSID *) NULL; + uint8_t *pucIE; + uint16_t u2IELength; + uint16_t u2Offset = 0; + u_int8_t fgReplyProbeResp = FALSE; + + ASSERT(prSwRfb); + ASSERT(pu4ControlFlags); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + +#if 0 + DBGLOG(BOW, EVENT, "bowValidateProbeReq.\n"); +#endif + + /* 4 <1> Parse Probe Req IE and Get IE ptr (SSID, Supported Rate IE, ...) */ + prMgtHdr = (struct WLAN_MAC_MGMT_HEADER *) prSwRfb->pvHeader; + + u2IELength = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen; + pucIE = (uint8_t *) (((unsigned long) prSwRfb->pvHeader) + prSwRfb->u2HeaderLen); + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (IE_ID(pucIE) == ELEM_ID_SSID) { + if ((!prIeSsid) && (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) + prIeSsid = (struct IE_SSID *) pucIE; + break; + } + } /* end of IE_FOR_EACH */ + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (IE_ID(pucIE) == ELEM_ID_SSID) { + if ((!prIeSsid) && (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) + prIeSsid = (struct IE_SSID *) 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; +#else + return 0; +#endif +} + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Media Disconnect" to HOST +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void bowSendBeacon(IN struct ADAPTER *prAdapter, IN unsigned long ulParamPtr) +{ + struct BOW_FSM_INFO *prBowFsmInfo; + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if ((g_u4Beaconing != 0) && (g_u4LinkCount > 0) + && (g_u4LinkCount < CFG_BOW_PHYSICAL_LINK_NUM)) { + /* Send beacon */ + bssSendBeaconProbeResponse(prAdapter, prBowFsmInfo->ucBssIndex, NULL, 0); + cnmTimerStartTimer(prAdapter, &prBowFsmInfo->rStartingBeaconTimer, prBowFsmInfo->u2BeaconInterval); + } else { + DBGLOG(BOW, EVENT, "BoW Send Beacon,[%d,%d]\n", g_u4LinkCount, g_u4Beaconing); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Media Disconnect" to HOST +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void bowResponderScan(IN struct ADAPTER *prAdapter) +{ + struct BOW_FSM_INFO *prBowFsmInfo; + struct MSG_SCN_SCAN_REQ *prScanReqMsg; + struct BSS_INFO *prBssInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + DBGLOG(BOW, EVENT, "bowResponderScan.\n"); + DBGLOG(BOW, EVENT, "BOW SCAN [REQ:%d]\n", prBowFsmInfo->ucSeqNumOfScanReq + 1); + + prScanReqMsg = (struct MSG_SCN_SCAN_REQ *) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(struct 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->ucBssIndex = prBowFsmInfo->ucBssIndex; + 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, (struct MSG_HDR *) 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 */ + +} + +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +void bowResponderScanDone(IN struct ADAPTER *prAdapter, IN struct MSG_HDR *prMsgHdr) +{ +#if 1 /* Marked for MT6630 */ + struct MSG_SCN_SCAN_DONE *prScanDoneMsg; + struct BOW_FSM_INFO *prBowFsmInfo; + struct BSS_DESC *prBssDesc; + uint8_t ucSeqNumOfCompMsg; + struct CONNECTION_SETTINGS *prConnSettings; + enum ENUM_BOW_DEVICE_STATE eFsmState; + enum ENUM_SCAN_STATUS eScanStatus; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prConnSettings = + aisGetConnSettings(prAdapter, AIS_DEFAULT_INDEX); + prScanDoneMsg = (struct MSG_SCN_SCAN_DONE *) prMsgHdr; + eFsmState = bowGetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress); + + ucSeqNumOfCompMsg = prScanDoneMsg->ucSeqNum; + eScanStatus = prScanDoneMsg->eScanStatus; + + cnmMemFree(prAdapter, prMsgHdr); + + DBGLOG(BOW, EVENT, "bowResponderScanDone.\n"); + DBGLOG(BOW, EVENT, "BOW SCAN [DONE:%d]\n", ucSeqNumOfCompMsg); + + if (eScanStatus == SCAN_STATUS_CANCELLED) { + DBGLOG(BOW, EVENT, "BOW SCAN [CANCELLED:%d]\n", ucSeqNumOfCompMsg); + if (eFsmState == BOW_DEVICE_STATE_DISCONNECTING) { + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + prBowFsmInfo->ucBssIndex, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, 0, NULL, 0); + } + return; + } else if (eFsmState == BOW_DEVICE_STATE_DISCONNECTED) { + /* bowDisconnectLink(prAdapter, NULL, TX_RESULT_SUCCESS); */ + return; + } else if (ucSeqNumOfCompMsg != prBowFsmInfo->ucSeqNumOfScanReq) { + DBGLOG(BOW, EVENT, "Sequence no. of BOW Responder scan done is not matched.\n"); + return; + } + prConnSettings->fgIsScanReqIssued = FALSE; + prBssDesc = scanSearchBssDescByBssid(prAdapter, prBowFsmInfo->aucPeerAddress); + DBGLOG(BOW, EVENT, "End scan result searching.\n"); + DBGLOG(BOW, EVENT, "prBowFsmInfo->aucPeerAddress: [" MACSTR "]\n", MAC2STR(prBowFsmInfo->aucPeerAddress)); + + /*Initiator is FOUND */ + if (prBssDesc != NULL) { /* (prBssDesc->aucBSSID != NULL)) */ + 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"); + + /*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; +#endif /* Marked for MT6630 */ +} + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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 struct ADAPTER *prAdapter, IN u_int8_t fgIsChannelExtention) +{ + + struct MSG_SCN_SCAN_CANCEL *prScanCancel = (struct MSG_SCN_SCAN_CANCEL *) NULL; + struct BOW_FSM_INFO *prBowFsmInfo = (struct BOW_FSM_INFO *) NULL; + + DEBUGFUNC("bowResponderCancelScan()"); + + do { + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if (TRUE) { + DBGLOG(BOW, EVENT, "BOW SCAN [CANCEL:%d]\n", prBowFsmInfo->ucSeqNumOfScanReq); + + /* There is a channel privilege on hand. */ + + DBGLOG(BOW, TRACE, "BOW Cancel Scan\n"); + + prScanCancel = + (struct MSG_SCN_SCAN_CANCEL *) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(struct MSG_SCN_SCAN_CANCEL)); + if (!prScanCancel) { + /* Buffer not enough, can not cancel scan request. */ + DBGLOG(BOW, TRACE, "Buffer not enough, can not cancel scan.\n"); + ASSERT(FALSE); + break; + } + + prScanCancel->rMsgHdr.eMsgId = MID_BOW_SCN_SCAN_CANCEL; + prScanCancel->ucBssIndex = prBowFsmInfo->ucBssIndex; + prScanCancel->ucSeqNum = prBowFsmInfo->ucSeqNumOfScanReq; +#if CFG_ENABLE_WIFI_DIRECT + prScanCancel->fgIsChannelExt = fgIsChannelExtention; +#endif + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *) 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 struct ADAPTER *prAdapter, IN struct BSS_DESC *prBssDesc) +{ + struct BOW_FSM_INFO *prBowFsmInfo; + struct BSS_INFO *prBssInfo; + struct CONNECTION_SETTINGS *prConnSettings; + struct STA_RECORD *prStaRec; + struct MSG_SAA_FSM_START *prJoinReqMsg; + + ASSERT(prBssDesc); + ASSERT(prAdapter); + + DBGLOG(BOW, EVENT, "Starting bowResponderJoin.\n"); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + prConnSettings = aisGetConnSettings(prAdapter, AIS_DEFAULT_INDEX); + + /* 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, prBssInfo->ucBssIndex, prBssDesc); + + prBowFsmInfo->prTargetStaRec = prStaRec; + + /* 4 <3> Update ucAvailableAuthTypes which we can choice during SAA */ + prStaRec->fgIsReAssoc = FALSE; + prBowFsmInfo->ucAvailableAuthTypes = (uint8_t) 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 & (uint8_t) AUTH_TYPE_OPEN_SYSTEM) { + + DBGLOG(BOW, LOUD, "JOIN INIT: Try to do Authentication with AuthType == OPEN_SYSTEM.\n"); + prBowFsmInfo->ucAvailableAuthTypes &= ~(uint8_t) AUTH_TYPE_OPEN_SYSTEM; + + prStaRec->ucAuthAlgNum = (uint8_t) 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); + DBGLOG(BOW, EVENT, "bowResponderJoin, SSID %s.\n", prBssDesc->aucSSID); + DBGLOG(BOW, EVENT, "bowResponderJoin, SSID %s.\n", prConnSettings->aucSSID); + } + /* 4 <6> Send a Msg to trigger SAA to start JOIN process. */ + prJoinReqMsg = (struct MSG_SAA_FSM_START *) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(struct MSG_SAA_FSM_START)); + 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; + + DBGLOG(BOW, EVENT, "prStaRec->eStaType, %x.\n", prStaRec->eStaType); + DBGLOG(BOW, EVENT, "BoW trigger SAA [" MACSTR "]\n", MAC2STR(prStaRec->aucMacAddr)); + + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *) prJoinReqMsg, MSG_SEND_METHOD_BUF); + +} + +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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 struct ADAPTER *prAdapter, IN struct MSG_HDR *prMsgHdr) +{ +#if 1 /* Marked for MT6630 */ + + struct MSG_SAA_FSM_COMP *prJoinCompMsg; + struct BOW_FSM_INFO *prBowFsmInfo; + struct STA_RECORD *prStaRec; + struct SW_RFB *prAssocRspSwRfb; + struct WLAN_ASSOC_RSP_FRAME *prAssocRspFrame = (struct WLAN_ASSOC_RSP_FRAME *) NULL; + uint16_t u2IELength; + uint8_t *pucIE; + struct BSS_INFO *prBowBssInfo; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + prJoinCompMsg = (struct MSG_SAA_FSM_COMP *) prMsgHdr; + prStaRec = prJoinCompMsg->prStaRec; + + 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); + + 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 = (struct WLAN_ASSOC_RSP_FRAME *) prAssocRspSwRfb->pvHeader; + + u2IELength = + (uint16_t) ((prAssocRspSwRfb->u2PacketLen - + prAssocRspSwRfb->u2HeaderLen) - + (OFFSET_OF(struct WLAN_ASSOC_RSP_FRAME, aucInfoElem[0]) - WLAN_MAC_MGMT_HEADER_LEN)); + pucIE = prAssocRspFrame->aucInfoElem; + + prStaRec->eStaType = STA_TYPE_BOW_AP; + prStaRec->u2DesiredNonHTRateSet &= prBowBssInfo->u2OperationalRateSet; + prStaRec->ucDesiredPhyTypeSet = prStaRec->ucPhyTypeSet & prBowBssInfo->ucPhyTypeSet; +#if CFG_BOW_RATE_LIMITATION + /* 4 <1.2>Update Rate Set */ + /*Limit Rate Set to 24M, 48M, 54M */ + prStaRec->u2DesiredNonHTRateSet &= (RATE_SET_BIT_24M | RATE_SET_BIT_48M | RATE_SET_BIT_54M); + /*If peer cannot support the above rate set, fix on the available highest rate */ + if (prStaRec->u2DesiredNonHTRateSet == 0) { + uint8_t ucHighestRateIndex; + + if (rateGetHighestRateIndexFromRateSet + (prBowBssInfo->u2OperationalRateSet, &ucHighestRateIndex)) { + prStaRec->u2DesiredNonHTRateSet = BIT(ucHighestRateIndex); + } + } +#endif + + /* 4 <1.1> Change FW's Media State immediately. */ + bowChangeMediaState(prBowBssInfo, + 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, prBowBssInfo->ucBssIndex); + DBGLOG(BOW, EVENT, "Finish bowUpdateBssInfoForJOIN.\n"); + + /* 4 <1.4> Activate current AP's STA_RECORD_T in Driver. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + DBGLOG(BOW, EVENT, "bowFsmRunEventJoinComplete, qmActivateStaRec.\n"); + + /* 4 <1.7> Set the Next State of BOW FSM */ + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + prBowFsmInfo->ucBssIndex, + 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 + DBGLOG(BOW, EVENT, "Start bowfsmRunEventJoinComplete -- Join failed.\n"); + DBGLOG(BOW, EVENT, "BoW trigger SAA REJOIN\n"); + } + } + + cnmMemFree(prAdapter, prMsgHdr); + +#endif /* Marked for MT6630 */ +} + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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 struct ADAPTER *prAdapter, + IN enum ENUM_PARAM_MEDIA_STATE eConnectionState, IN u_int8_t fgDelayIndication) +{ + struct EVENT_CONNECTION_STATUS rEventConnStatus; + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_INFO *prBssInfo; + struct BOW_FSM_INFO *prBowFsmInfo; + + prConnSettings = aisGetConnSettings(prAdapter, AIS_DEFAULT_INDEX); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + /* 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 == 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 = (uint8_t) eConnectionState; + + if (eConnectionState == MEDIA_STATE_CONNECTED) { + rEventConnStatus.ucReasonOfDisconnect = DISCONNECT_REASON_CODE_RESERVED; + + if (prBssInfo->eCurrentOPMode == OP_MODE_BOW) { + rEventConnStatus.ucInfraMode = (uint8_t) NET_TYPE_INFRA; + rEventConnStatus.u2AID = prBssInfo->u2AssocId; + rEventConnStatus.u2ATIMWindow = 0; + } else if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + rEventConnStatus.ucInfraMode = (uint8_t) 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 = (uint8_t) PARAM_NETWORK_TYPE_DS; + break; + + case PHY_TYPE_ERP_INDEX: + rEventConnStatus.ucNetworkType = (uint8_t) PARAM_NETWORK_TYPE_OFDM24; + break; + + case PHY_TYPE_OFDM_INDEX: + rEventConnStatus.ucNetworkType = (uint8_t) PARAM_NETWORK_TYPE_OFDM5; + break; + + default: + ASSERT(0); + rEventConnStatus.ucNetworkType = (uint8_t) PARAM_NETWORK_TYPE_DS; + break; + } + } else { + + rEventConnStatus.ucReasonOfDisconnect = prBssInfo->ucReasonOfDisconnect; + + } + + /* 4 <2> Indication */ + nicMediaStateChange(prAdapter, prBssInfo->ucBssIndex, &rEventConnStatus); + prBssInfo->eConnectionStateIndicated = eConnectionState; + } else { + /* NOTE: Only delay the Indication of Disconnect Event */ + ASSERT(eConnectionState == 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)); + } + +} + +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Event of Tx Fail of AAA Module. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void bowRunEventAAATxFail(IN struct ADAPTER *prAdapter, IN struct STA_RECORD *prStaRec) +{ +#if 1 /* Marked for MT6630 */ + struct BSS_INFO *prBssInfo; + struct BOW_FSM_INFO *prBowFsmInfo; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + DBGLOG(BOW, EVENT, "bowRunEventAAATxFail , bssRemoveStaRecFromClientList.\n"); + DBGLOG(BOW, EVENT, "BoW AAA TxFail, target state %d\n", prStaRec->ucStaState + 1); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + bssRemoveClient(prAdapter, prBssInfo, prStaRec); + + return; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Event of Successful Completion of AAA Module. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +uint32_t bowRunEventAAAComplete(IN struct ADAPTER *prAdapter, IN struct STA_RECORD *prStaRec) +{ +#if 1 /* Marked for MT6630 */ + struct BSS_INFO *prBssInfo; + struct BOW_FSM_INFO *prBowFsmInfo; + + ASSERT(prStaRec); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + DBGLOG(BOW, STATE, "bowRunEventAAAComplete, cnmStaRecChangeState, STA_STATE_3.\n"); + DBGLOG(BOW, EVENT, "BoW AAA complete [" MACSTR "]\n", MAC2STR(prStaRec->aucMacAddr)); + + /*Update BssInfo to connected */ + bowChangeMediaState(prBssInfo, MEDIA_STATE_CONNECTED); + nicUpdateBss(prAdapter, prBowFsmInfo->ucBssIndex); + + /*Update StaRec to State3 */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + /*Connected */ + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + prBowFsmInfo->ucBssIndex, + TRUE, FALSE, wlanbowCmdEventLinkConnected, wlanbowCmdTimeoutHandler, 0, NULL, 0); + + return WLAN_STATUS_SUCCESS; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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) +*/ +/*----------------------------------------------------------------------------*/ + +uint32_t bowRunEventRxDeAuth(IN struct ADAPTER *prAdapter, IN struct STA_RECORD *prStaRec, IN struct SW_RFB *prSwRfb) +{ +#if 1 /* Marked for MT6630 */ + struct BSS_INFO *prBowBssInfo; + struct BOW_FSM_INFO *prBowFsmInfo; + enum ENUM_BOW_DEVICE_STATE eFsmState; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + if (!IS_STA_BOW_TYPE(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 (prStaRec->ucStaState == STA_STATE_3) { + /* 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, + prBowFsmInfo->ucBssIndex, + TRUE, + FALSE, wlanbowCmdEventLinkDisconnected, wlanbowCmdTimeoutHandler, 0, NULL, 0); + + return WLAN_STATUS_SUCCESS; + } + + return WLAN_STATUS_NOT_ACCEPTED; + +#else + return 0; +#endif +} + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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 struct ADAPTER *prAdapter, IN struct MSDU_INFO *prMsduInfo, IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + struct BOW_FSM_INFO *prBowFsmInfo; + struct STA_RECORD *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); */ + 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 + if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) + wlanLoadManufactureData(prAdapter, kalGetConfiguration(prAdapter->prGlueInfo)); + else + DBGLOG(REQ, WARN, "%s: load manufacture data fail\n", __func__); + +#endif + /*Uninit BoW Interface */ +#if CFG_BOW_SEPARATE_DATA_PATH + kalUninitBowDevice(prAdapter->prGlueInfo); +#endif + } +} + +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t bowValidateAssocReq(IN struct ADAPTER *prAdapter, IN struct SW_RFB *prSwRfb, OUT uint16_t *pu2StatusCode) +{ +#if 1 /* Marked for MT6630 */ + + u_int8_t fgReplyAssocResp = FALSE; + struct BSS_INFO *prBowBssInfo; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + struct BOW_FSM_INFO *prBowFsmInfo; + struct WLAN_ASSOC_REQ_FRAME *prAssocReqFrame = (struct WLAN_ASSOC_REQ_FRAME *) NULL; + OS_SYSTIME rCurrentTime; + static OS_SYSTIME rLastRejectAssocTime; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + prAssocReqFrame = (struct WLAN_ASSOC_REQ_FRAME *) prSwRfb->pvHeader; + *pu2StatusCode = STATUS_CODE_REQ_DECLINED; + + 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]); + + /*Assoc Accept */ + while (EQUAL_MAC_ADDR(prAssocReqFrame->aucSrcAddr, prBowFsmInfo->aucPeerAddress)) { + DBGLOG(BOW, EVENT, "bowValidateAssocReq, return wlanbowCmdEventLinkConnected.\n"); + + /*Update StaRec */ + prStaRec = cnmGetStaRecByAddress(prAdapter, prBowFsmInfo->ucBssIndex, 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 available highest rate */ + if (prStaRec->u2DesiredNonHTRateSet == 0) { + uint8_t ucHighestRateIndex; + + if (rateGetHighestRateIndexFromRateSet(prBowBssInfo->u2OperationalRateSet, &ucHighestRateIndex)) + prStaRec->u2DesiredNonHTRateSet = BIT(ucHighestRateIndex); + else { + /*If no available rate is found, DECLINE the association */ + *pu2StatusCode = STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED; + break; + } + } +#endif + + /*Update BssInfo to FW */ + bowChangeMediaState(prBowBssInfo, MEDIA_STATE_CONNECTED); + nicUpdateBss(prAdapter, prStaRec->ucBssIndex); + + /*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; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t +bowValidateAuth(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, IN struct STA_RECORD **pprStaRec, OUT uint16_t *pu2StatusCode) +{ +#if 1 /* Marked for MT6630 */ + u_int8_t fgReplyAuth = FALSE; + struct BSS_INFO *prBowBssInfo; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + struct BOW_FSM_INFO *prBowFsmInfo; + struct WLAN_AUTH_FRAME *prAuthFrame = (struct WLAN_AUTH_FRAME *) NULL; + OS_SYSTIME rCurrentTime; + static OS_SYSTIME rLastRejectAuthTime; + + /* TODO(Kevin): Call BoW functions to check .. + * 1. Check we are BoW now. + * 2. Check we can accept connection from thsi peer + * 3. Check Black List here. + */ + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + prAuthFrame = (struct WLAN_AUTH_FRAME *) prSwRfb->pvHeader; + + 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]); + + prStaRec = cnmGetStaRecByAddress(prAdapter, prBowFsmInfo->ucBssIndex, prAuthFrame->aucSrcAddr); + if (!prStaRec) { + DBGLOG(BOW, EVENT, "bowValidateAuth, cnmStaRecAlloc.\n"); + prStaRec = cnmStaRecAlloc(prAdapter, + STA_TYPE_BOW_CLIENT, prBowFsmInfo->ucBssIndex, prAuthFrame->aucSrcAddr); + + /* TODO(Kevin): Error handling of allocation of struct STA_RECORD for + * exhausted case and do removal of unused struct STA_RECORD. + */ + 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); + DBGLOG(BOW, EVENT, "bowValidateAuth, cnmStaRecChangeState.\n"); + } else { + prSwRfb->ucStaRecIdx = prStaRec->ucIndex; + DBGLOG(BOW, EVENT, "bowValidateAuth, prStaRec->ucIndex, %x.\n", prStaRec->ucIndex); + bssRemoveClient(prAdapter, prBowBssInfo, prStaRec); + } + + if (EQUAL_MAC_ADDR(prAuthFrame->aucSrcAddr, prBowFsmInfo->aucPeerAddress)) { + DBGLOG(BOW, EVENT, "bowValidateAuth, prStaRec->eStaType, %x.\n", prStaRec->eStaType); + DBGLOG(BOW, EVENT, "bowValidateAuth, prStaRec->ucBssIndex, %x.\n", prStaRec->ucBssIndex); + + /* 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); + *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; + } + } + + DBGLOG(BOW, EVENT, "bowValidateAuth, fgReplyAuth, %x.\n", fgReplyAuth); + return fgReplyAuth; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is invoked when CNM granted channel privilege +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +void bowRunEventChGrant(IN struct ADAPTER *prAdapter, IN struct MSG_HDR *prMsgHdr) +{ +#if 1 /* Marked for MT6630 */ + struct BSS_INFO *prBowBssInfo; + struct BOW_FSM_INFO *prBowFsmInfo; + struct MSG_CH_GRANT *prMsgChGrant; + uint8_t ucTokenID; + uint32_t u4GrantInterval; + enum ENUM_BOW_DEVICE_STATE eFsmState; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + prMsgChGrant = (struct MSG_CH_GRANT *) prMsgHdr; + ucTokenID = prMsgChGrant->ucTokenID; + u4GrantInterval = prMsgChGrant->u4GrantInterval; + + /* 1. free message */ + cnmMemFree(prAdapter, prMsgHdr); + prBowFsmInfo->fgIsChannelGranted = TRUE; + + DBGLOG(BOW, EVENT, "Entering bowRunEventChGrant.\n"); + + eFsmState = bowGetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress); + + /*Release channel */ + if ((!prBowFsmInfo->fgIsChannelRequested) || + (prBowFsmInfo->ucSeqNumOfChReq != ucTokenID) || + (eFsmState == BOW_DEVICE_STATE_DISCONNECTED) || (eFsmState == BOW_DEVICE_STATE_DISCONNECTING)) { + DBGLOG(BOW, EVENT, "BoW Channel [GIVE UP:%d]\n", ucTokenID); + DBGLOG(BOW, EVENT, "[Requested:%d][ucSeqNumOfChReq:%d][eFsmState:%d]\n", + prBowFsmInfo->fgIsChannelRequested, prBowFsmInfo->ucSeqNumOfChReq, eFsmState); + 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 */ + + DBGLOG(BOW, EVENT, "BoW Channel [GRANTED:%d].\n", ucTokenID); + + 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, prBowFsmInfo->ucBssIndex); + bowReleaseCh(prAdapter); + } + + return; +#endif /* Marked for MT6630 */ +} /* end of aisFsmRunEventChGrant() */ + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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 struct ADAPTER *prAdapter) +{ + struct BOW_FSM_INFO *prBowFsmInfo; + struct MSG_CH_REQ *prMsgChReq; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if (prBowFsmInfo->fgIsChannelGranted == FALSE) { + + DBGLOG(BOW, EVENT, "BoW channel [REQUEST:%d], %d, %d.\n", + prBowFsmInfo->ucSeqNumOfChReq + 1, prBowFsmInfo->ucPrimaryChannel, prBowFsmInfo->eBand); + + prMsgChReq = (struct MSG_CH_REQ *) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(struct MSG_CH_REQ)); + + if (!prMsgChReq) { + ASSERT(0); /* Can't indicate CNM for channel acquiring */ + return; + } + + prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; + prMsgChReq->ucBssIndex = prBowFsmInfo->ucBssIndex; + prMsgChReq->ucTokenID = ++prBowFsmInfo->ucSeqNumOfChReq; + prMsgChReq->eReqType = CH_REQ_TYPE_JOIN; +#if 0 + prMsgChReq->u4MaxInterval = BOW_JOIN_CH_REQUEST_INTERVAL; +#else + prMsgChReq->u4MaxInterval = 1; +#endif + /* prBowFsmInfo->prTargetBssDesc->ucChannelNum; */ + prMsgChReq->ucPrimaryChannel = prBowFsmInfo->ucPrimaryChannel; + /* prBowFsmInfo->prTargetBssDesc->eSco; */ + prMsgChReq->eRfSco = CHNL_EXT_SCN; + /* prBowFsmInfo->prTargetBssDesc->eBand; */ + prMsgChReq->eRfBand = prBowFsmInfo->eBand; + + /* FIXME : where to call cnmGetDbdcCapability in BOW? */ + /*prMsgChReq->eDBDCBand = (prAdapter->aprBssInfo[prMsgChReq->ucBssIndex])->eDBDCBand;*/ + prMsgChReq->eDBDCBand = ENUM_BAND_AUTO; + + /* To do: check if 80/160MHz bandwidth is needed here */ + prMsgChReq->eRfChannelWidth = 0; + prMsgChReq->ucRfCenterFreqSeg1 = 0; + prMsgChReq->ucRfCenterFreqSeg2 = 0; + + prBowFsmInfo->fgIsChannelRequested = TRUE; + + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *) 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 struct ADAPTER *prAdapter) +{ + struct BOW_FSM_INFO *prBowFsmInfo; + struct MSG_CH_ABORT *prMsgChAbort; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if (prBowFsmInfo->fgIsChannelGranted != FALSE || prBowFsmInfo->fgIsChannelRequested != FALSE) { + DBGLOG(BOW, EVENT, + "BoW channel [RELEASE:%d] %d, %d.\n", prBowFsmInfo->ucSeqNumOfChReq, + prBowFsmInfo->ucPrimaryChannel, prBowFsmInfo->eBand); + + prBowFsmInfo->fgIsChannelRequested = FALSE; + prBowFsmInfo->fgIsChannelGranted = FALSE; + + /* 1. return channel privilege to CNM immediately */ + prMsgChAbort = (struct MSG_CH_ABORT *) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(struct MSG_CH_ABORT)); + if (!prMsgChAbort) { + ASSERT(0); /* Can't release Channel to CNM */ + return; + } + + prMsgChAbort->rMsgHdr.eMsgId = MID_MNY_CNM_CH_ABORT; + prMsgChAbort->ucBssIndex = prBowFsmInfo->ucBssIndex; + prMsgChAbort->ucTokenID = prBowFsmInfo->ucSeqNumOfChReq; + + /* FIXME : where to call cnmGetDbdcCapability in BOW? */ + /*prMsgChAbort->eDBDCBand = (prAdapter->aprBssInfo[prMsgChAbort->ucBssIndex])->eDBDCBand;*/ + prMsgChAbort->eDBDCBand = ENUM_BAND_AUTO; + + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *) prMsgChAbort, MSG_SEND_METHOD_BUF); + } + +} /* end of aisFsmReleaseCh() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Media Disconnect" to HOST +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void bowChGrantedTimeout(IN struct ADAPTER *prAdapter, IN unsigned long ulParamPtr) +{ + struct BOW_FSM_INFO *prBowFsmInfo; + enum ENUM_BOW_DEVICE_STATE eFsmState; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + DBGLOG(BOW, EVENT, "BoW Channel [TIMEOUT]\n"); + +#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 +} + +#endif /* Marked for MT6630 */ + +u_int8_t bowNotifyAllLinkDisconnected(IN struct ADAPTER *prAdapter) +{ +#if 1 /* Marked for MT6630 */ + + uint8_t ucBowTableIdx = 0; + struct CMD_INFO rCmdInfo; + struct BOW_FSM_INFO *prBowFsmInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + kalMemZero(&rCmdInfo, sizeof(struct CMD_INFO)); + + while (ucBowTableIdx < CFG_BOW_PHYSICAL_LINK_NUM) { + if (arBowTable[ucBowTableIdx].fgIsValid) { + COPY_MAC_ADDR(prAdapter->rWifiVar.rBowFsmInfo.aucPeerAddress, + arBowTable[ucBowTableIdx].aucPeerAddress); + 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); +#if 1 + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + prBowFsmInfo->ucBssIndex, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, 0, NULL, 0); +#else + wlanbowCmdEventLinkDisconnected(prAdapter, &rCmdInfo, NULL); +#endif + } + + ucBowTableIdx += 1; + } + + return TRUE; + +#else + return 0; +#endif +} + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Bluetooth-over-Wi-Fi state from glue layer +* +* \param[in] +* prGlueInfo +* rPeerAddr +* \return +* ENUM_BOW_DEVICE_STATE +*/ +/*----------------------------------------------------------------------------*/ + +u_int8_t bowCheckBowTableIfVaild(IN struct ADAPTER *prAdapter, IN uint8_t aucPeerAddress[6]) +{ + uint8_t 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)) { + + 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); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + return TRUE; + } + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + return FALSE; +} + +u_int8_t bowGetBowTableContent(IN struct ADAPTER *prAdapter, IN uint8_t ucBowTableIdx, OUT struct BOW_TABLE *prBowTable) +{ + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + if (arBowTable[ucBowTableIdx].fgIsValid) { + + DBGLOG(BOW, EVENT, + "bowGetBowTableContent, arBowTable[idx].fgIsValid, %x, %x.\n", + ucBowTableIdx, arBowTable[ucBowTableIdx].fgIsValid); + DBGLOG(BOW, EVENT, "GET State [%d]\n", arBowTable[ucBowTableIdx].eState); + 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; +} + +u_int8_t bowSetBowTableContent(IN struct ADAPTER *prAdapter, IN uint8_t ucBowTableIdx, IN struct BOW_TABLE *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); */ + + DBGLOG(BOW, EVENT, "SET State [%d]\n", arBowTable[ucBowTableIdx].eState); + DBGLOG(BOW, EVENT, + "kalCheckBowifVaild, arBowTable[ucBowTableIdx].fgIsValid, %x, %x.\n", ucBowTableIdx, + arBowTable[ucBowTableIdx].fgIsValid); + + return TRUE; + +} + +u_int8_t +bowGetBowTableEntryByPeerAddress(IN struct ADAPTER *prAdapter, IN uint8_t aucPeerAddress[6], OUT uint8_t *pucBowTableIdx) +{ + uint8_t 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)) { + + 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); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + *pucBowTableIdx = idx; + + return TRUE; + } + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + return FALSE; +} + +u_int8_t bowGetBowTableFreeEntry(IN struct ADAPTER *prAdapter, OUT uint8_t *pucBowTableIdx) +{ + uint8_t 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) { + DBGLOG(BOW, EVENT, + "bowGetBowTableFreeEntry, arBowTable[idx].fgIsValid, %x, %x.\n", + idx, arBowTable[idx].fgIsValid); + *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 ENUM_BOW_DEVICE_STATE bowGetBowTableState(IN struct ADAPTER *prAdapter, IN uint8_t aucPeerAddress[6]) +{ + uint8_t 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)) { + DBGLOG(BOW, EVENT, + "bowGetState, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, + aucPeerAddress[0], aucPeerAddress[1], aucPeerAddress[2], + aucPeerAddress[3], aucPeerAddress[4], aucPeerAddress[5]); + DBGLOG(BOW, EVENT, + "bowGetState, arBowTable[idx].aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", + idx, arBowTable[idx].aucPeerAddress[0], + arBowTable[idx].aucPeerAddress[1], + arBowTable[idx].aucPeerAddress[2], + arBowTable[idx].aucPeerAddress[3], + arBowTable[idx].aucPeerAddress[4], arBowTable[idx].aucPeerAddress[5]); + DBGLOG(BOW, EVENT, + "bowGetState, arBowTable[idx].fgIsValid, %x, %x.\n", idx, arBowTable[idx].fgIsValid); + DBGLOG(BOW, EVENT, + "bowGetState, arBowTable[idx].eState;, %x, %x.\n", idx, arBowTable[idx].eState); + DBGLOG(BOW, EVENT, "GET State [%d]\n", arBowTable[idx].eState); + + 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; +} + +u_int8_t bowSetBowTableState(IN struct ADAPTER *prAdapter, IN uint8_t aucPeerAddress[6], IN enum ENUM_BOW_DEVICE_STATE eState) +{ + uint8_t ucBowTableIdx; + + if (bowGetBowTableEntryByPeerAddress(prAdapter, aucPeerAddress, &ucBowTableIdx)) { + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + arBowTable[ucBowTableIdx].eState = eState; + DBGLOG(BOW, EVENT, "SET State [%d]\n", eState); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + kalSetBowState(prAdapter->prGlueInfo, eState, aucPeerAddress); + return TRUE; + } + return FALSE; +} + +#endif + +#endif /* Marked for MT6630 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/wlan_he.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/wlan_he.c new file mode 100644 index 0000000000000..8666c1b9e5e50 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/wlan_he.c @@ -0,0 +1,104 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file wlan_he.c +* \brief This file contains the HE(802.11ax) processing routines 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" + +#if (CFG_SUPPORT_802_11AX == 1) +/****************************************************************************** +* 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 /* CFG_SUPPORT_802_11AX == 1 */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/wlan_lib.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/wlan_lib.c new file mode 100644 index 0000000000000..84c7a4f035416 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/wlan_lib.c @@ -0,0 +1,12448 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/*! \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. + */ + + +/******************************************************************************* + * C O M P I L E 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" +#if CFG_MTK_MCIF_WIFI_SUPPORT +#include "mddp.h" +#endif + +/******************************************************************************* + * 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 uint8_t aucPriorityParam2TC[] = { + TC1_INDEX, + TC0_INDEX, + TC0_INDEX, + TC1_INDEX, + TC2_INDEX, + TC2_INDEX, + TC3_INDEX, + TC3_INDEX +}; + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +struct CODE_MAPPING { + uint32_t u4RegisterValue; + int32_t u4TxpowerOffset; +}; + +struct NVRAM_TAG_FRAGMENT_GROUP { + uint8_t u1StartTagID; + uint8_t u1EndTagID; +}; + +struct NVRAM_FRAGMENT_RANGE { + uint32_t startOfs; + uint32_t endOfs; +}; + + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +u_int8_t fgIsBusAccessFailed = FALSE; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +/* data rate mapping table for CCK */ +struct cckDataRateMappingTable_t { + uint32_t rate[4]; +} g_rCckDataRateMappingTable = { + {10, 20, 55, 110} +}; +/* data rate mapping table for OFDM */ +struct ofdmDataRateMappingTable_t { + uint32_t rate[8]; +} g_rOfdmDataRateMappingTable = { + {60, 90, 120, 180, 240, 360, 480, 540} +}; +/* data rate mapping table for 802.11n and 802.11ac */ +struct dataRateMappingTable_t { + struct nsts_t { + struct bw_t { + struct sgi_t { + uint32_t rate[10]; + } sgi[2]; + } bw[4]; + } nsts[3]; +} g_rDataRateMappingTable = { +{ { { { { /* 20MHz */ + { /* no SGI */ + {65, 130, 195, 260, 390, 520, 585, 650, 780, 867} + }, + { /* SGI */ + {72, 144, 217, 289, 433, 578, 650, 722, 867, 963} + } +} }, +{ + { /* 40MHz */ + { /* no SGI */ + {135, 270, 405, 540, 810, 1080, 1215, 1350, 1620, 1800} + }, + { /* SGI */ + {150, 300, 450, 600, 900, 1200, 1350, 1500, 1800, 2000} + } +} }, +{ + { /* 80MHz */ + { /* no SGI */ + {293, 585, 878, 1170, 1755, 2340, 2633, 2925, 3510, 3900} + }, + { /* SGI */ + {325, 650, 975, 1300, 1950, 2600, 2925, 3250, 3900, 4333} + } +} }, +{ + { /* 160MHz */ + { /* no SGI */ + {585, 1170, 1755, 2340, 3510, 4680, 5265, 5850, 7020, 7800} + }, + { /* SGI */ + {650, 1300, 1950, 2600, 3900, 5200, 5850, 6500, 7800, 8667} + } +} } } }, +{ { { + { /* 20MHz */ + { /* no SGI */ + {130, 260, 390, 520, 780, 1040, 1170, 1300, 1560, 1733} + }, + { /* SGI */ + {144, 289, 433, 578, 867, 1156, 1303, 1444, 1733, 1927} + } +} }, +{ + { /* 40MHz */ + { /* no SGI */ + {270, 540, 810, 1080, 1620, 2160, 2430, 2700, 3240, 3600} + }, + { /* SGI */ + {300, 600, 900, 1200, 1800, 2400, 2700, 3000, 3600, 4000} + } +} }, +{ + { /* 80MHz */ + { /* no SGI */ + {585, 1170, 1755, 2340, 3510, 4680, 5265, 5850, 7020, 7800} + }, + { /* SGI */ + {650, 1300, 1950, 2600, 3900, 5200, 5850, 6500, 7800, 8667} + } +} }, +{ + { /* 160MHz */ + { /* no SGI */ + {1170, 2340, 3510, 4680, 7020, 9360, 10530, 11700, 14040, 15600} + }, + { /* SGI */ + {1300, 2600, 3900, 5200, 7800, 10400, 11700, 13000, 15600, 17333} + } +} } } }, +{ { { + { /* 20MHz */ + { /* no SGI */ + {195, 390, 585, 780, 1170, 1560, 1755, 1950, 2340, 2600} + }, + { /* SGI */ + {217, 433, 650, 867, 1300, 1733, 1950, 2167, 2600, 2889} + } +} }, +{ + { /* 40MHz */ + { /* no SGI */ + {405, 810, 1215, 1620, 2430, 3240, 3645, 4050, 4860, 5400} + }, + { /* SGI */ + {450, 900, 1350, 1800, 2700, 3600, 4050, 4500, 5400, 6000} + } +} }, +{ + { /* 80MHz */ + { /* no SGI */ + {878, 1755, 2633, 3510, 5265, 7020, 0, 8775, 10530, 11700} + }, + { /* SGI */ + {975, 1950, 2925, 3900, 5850, 7800, 0, 9750, 11700, 13000} + } +} }, +{ + { /* 160MHz */ + { /* no SGI */ + {1755, 3510, 5265, 7020, 10530, 14040, 15795, 17550, 21060, 23400} + }, + { /* SGI */ + {1950, 3900, 5850, 7800, 11700, 15600, 17550, 19500, 23400, 26000} + } +} } } } } +}; + +/* data rate mapping table for ax */ +struct axDataRateMappingTable_t { + struct axNsts_t { + struct axBw_t { + struct axGi_t { + uint32_t rate[12]; + } gi[3]; + } bw[4]; + } nsts[4]; +} g_rAxDataRateMappingTable = { +{ { { { { /* 20MHz */ + { /* HE GI 0.8 */ + {86, 172, 258, 344, 516, 688, 774, 860, 1032, 1147, 1290, 1434} + }, + { /* HE GI 1.6 */ + {81, 163, 244, 325, 488, 650, 731, 813, 975, 1083, 1219, 1354} + }, + { /* HE GI 3.2 */ + {73, 146, 219, 293, 439, 585, 658, 731, 878, 975, 1097, 1219} + } +} }, +{ + { /* 40MHz */ + { /* HE GI 0.8 */ + {172, 344, 516, 688, 1032, 1376, 1549, 1721, 2065, 2294, 2581, 2868} + }, + { /* HE GI 1.6 */ + {163, 325, 488, 650, 975, 1300, 1463, 1625, 1950, 2167, 2438, 2708} + }, + { /* HE GI 3.2 */ + {146, 293, 439, 585, 878, 1170, 1316, 1463, 1755, 1950, 2194, 2438} + } +} }, +{ + { /* 80MHz */ + { /* HE GI 0.8 */ + {360, 721, 1081, 1441, 2162, 2882, 3243, 3603, 4324, 4804, 5404, 6005} + }, + { /* HE GI 1.6 */ + {340, 681, 1021, 1361, 2042, 2722, 3063, 3403, 4083, 4537, 5104, 5671} + }, + { /* HE GI 3.2 */ + {306, 613, 919, 1225, 1838, 2450, 2756, 3063, 3675, 4083, 4594, 5104} + } +} }, +{ + { /* 160MHz */ + { /* HE GI 0.8 */ + {721, 1441, 2162, 2882, 4324, 5765, 6485, 7206, 8647, 9608, 10809, + 12010} + }, + { /* HE GI 1.6 */ + {681, 1361, 2042, 2722, 4083, 5444, 6125, 6806, 8167, 9074, 10208, + 11343} + }, + { /* HE GI 3.2 */ + {613, 1225, 1838, 2450, 3675, 4900, 5513, 6125, 7350, 8167, 9188, 10208} + } +} } } }, +{ { { + { /* 20MHz */ + { /* HE GI 0.8 */ + {172, 344, 516, 688, 1032, 1376, 1549, 1721, 2065, 2294, 2581, 2868} + }, + { /* HE GI 1.6 */ + {163, 352, 488, 650, 975, 1300, 1463, 1625, 1950, 2167, 2438, 2708} + }, + { /* HE GI 3.2 */ + {146, 293, 439, 585, 878, 1170, 1316, 1463, 1755, 1950, 2194, 2438} + } +} }, +{ + { /* 40MHz */ + { /* HE GI 0.8 */ + {344, 688, 1032, 1376, 2065, 2753, 3097, 3441, 4129, 4588, 5162, 5735} + }, + { /* HE GI 1.6 */ + {325, 650, 975, 1300, 1950, 2600, 2925, 3250, 3900, 4333, 4875, 5417} + }, + { /* HE GI 3.2 */ + {293, 585, 878, 1170, 1755, 2340, 2633, 2925, 3510, 3900, 4388, 4875} + } +} }, +{ + { /* 80MHz */ + { /* HE GI 0.8 */ + {721, 1441, 2162, 2882, 4324, 5765, 6485, 7206, 8647, 9608, 10809, + 12010} + }, + { /* HE GI 1.6 */ + {681, 1361, 2042, 2722, 4083, 5444, 6125, 6806, 8167, 9074, 10208, + 11343} + }, + { /* HE GI 3.2 */ + {613, 1225, 1838, 2450, 3675, 4900, 5513, 6125, 7350, 8167, 9188, 10208} + } +} }, +{ + { /* 160MHz */ + { /* HE GI 0.8 */ + {1441, 2882, 4324, 5765, 8647, 11529, 12971, 14412, 17294, 19216, 21618, + 24020} + }, + { /* HE GI 1.6 */ + {1361, 2722, 4083, 5444, 8167, 10889, 12250, 13611, 16333, 18148, 20417, + 22685} + }, + { /* HE GI 3.2 */ + {1225, 2450, 3675, 4900, 7350, 9800, 11025, 12250, 14700, 16333, 18375, + 20417} + } +} } } }, +{ { { + { /* 20MHz */ + { /* HE GI 0.8 */ + {258, 516, 774, 1032, 1549, 2065, 2323, 2581, 3097, 3441, 3871, 4301} + }, + { /* HE GI 1.6 */ + {244, 488, 721, 975, 1463, 1950, 2194, 2438, 2925, 3250, 3656, 4063} + }, + { /* HE GI 3.2 */ + {219, 439, 658, 878, 1316, 1755, 1974, 2194, 2633, 2925, 3291, 3656} + } +} }, +{ + { /* 40MHz */ + { /* HE GI 0.8 */ + {516, 1032, 1549, 2065, 3097, 4129, 4646, 5162, 6194, 6882, 7743, 8603} + }, + { /* HE GI 1.6 */ + {488, 975, 1463, 1950, 2925, 3900, 4388, 4875, 5850, 6500, 7313, 8125} + }, + { /* HE GI 3.2 */ + {439, 878, 1316, 1755, 2633, 3510, 3949, 4388, 5265, 5850, 6581, 7313} + } +} }, +{ + { /* 80MHz */ + { /* HE GI 0.8 */ + {1081, 2162, 3243, 4324, 6485, 8647, 9728, 10809, 12971, 14412, 16213, + 18015} + }, + { /* HE GI 1.6 */ + {1021, 2042, 3063, 4083, 6125, 8167, 9188, 10208, 12250, 13611, 15313, + 17014} + }, + { /* HE GI 3.2 */ + {919, 1838, 2756, 3675, 5513, 7350, 8269, 9188, 11025, 12250, 13781, + 15313} + } +} }, +{ + { /* 160MHz */ + { /* HE GI 0.8 */ + {2162, 4324, 6485, 8647, 12971, 17294, 19456, 21618, 25941, 28824, + 32426, 36029} + }, + { /* HE GI 1.6 */ + {1042, 4083, 6125, 8167, 12250, 16333, 18375, 20417, 24500, 27222, + 30625, 34028} + }, + { /* HE GI 3.2 */ + {1838, 3675, 5513, 7350, 11025, 14700, 16538, 18375, 22050, 24500, + 27563, 30625} + } +} } } }, +{ { { + { /* 20MHz */ + { /* HE GI 0.8 */ + {344, 688, 1032, 1376, 2065, 2753, 3097, 3441, 4129, 4588, 5162, 5735} + }, + { /* HE GI 1.6 */ + {325, 650, 975, 1300, 1950, 2600, 2925, 3250, 3900, 4333, 4875, 5417} + }, + { /* HE GI 3.2 */ + {293, 585, 878, 1170, 1755, 2340, 2633, 2925, 3510, 3900, 4388, 4875} + } +} }, +{ + { /* 40MHz */ + { /* HE GI 0.8 */ + {688, 1376, 2065, 2753, 4129, 5506, 6194, 6882, 8259, 9176, 10324, + 11471} + }, + { /* HE GI 1.6 */ + {650, 1300, 1950, 2600, 3900, 5200, 5850, 6500, 7800, 8667, 9750, 10833} + }, + { /* HE GI 3.2 */ + {585, 1170, 1755, 2340, 3510, 4680, 5265, 5850, 7020, 7800, 8775, 9750} + } +} }, +{ + { /* 80MHz */ + { /* HE GI 0.8 */ + {1441, 2882, 4324, 5765, 8647, 11529, 12971, 14412, 17294, 19216, 21618, + 24020} + }, + { /* HE GI 1.6 */ + {1361, 2722, 4083, 5444, 8167, 10889, 12250, 13611, 16333, 18148, 20417, + 22685} + }, + { /* HE GI 3.2 */ + {1225, 2450, 3675, 4900, 7350, 9800, 11025, 12250, 14700, 16333, 18375, + 20417} + } +} }, +{ + { /* 160MHz */ + { /* HE GI 0.8 */ + {2882, 5765, 8647, 11529, 17294, 23059, 25941, 28824, 34588, 38431, + 43235, 48039} + }, + { /* HE GI 1.6 */ + {2722, 5444, 8167, 10889, 16333, 21778, 24500, 27222, 32667, 36296, + 40833, 45370} + }, + { /* HE GI 3.2 */ + {2450, 4900, 7350, 9800, 14700, 19600, 22050, 24500, 29400, 32667, + 36750, 40833} + } +} } } } } +}; + +struct PARAM_CUSTOM_KEY_CFG_STRUCT g_rEmCfgBk[WLAN_CFG_REC_ENTRY_NUM_MAX]; + + +struct PARAM_CUSTOM_KEY_CFG_STRUCT g_rDefaulteSetting[] = { + /*format : + *: { + * "firmware config parameter", + * "firmware config value", + * "Operation:default 0" + * } + */ + {"AdapScan", "0x0", WLAN_CFG_DEFAULT}, +#if CFG_SUPPORT_IOT_AP_BLACKLIST + /*Fill Iot AP blacklist here*/ +#endif +#if CFG_TC3_FEATURE + {"ScreenOnBeaconTimeoutCount", "20"}, + {"ScreenOffBeaconTimeoutCount", "10"}, + {"AgingPeriod", "0x19"}, + {"DropPacketsIPV4Low", "0x1"}, + {"DropPacketsIPV6Low", "0x1"}, + {"Sta2gBw", "1"}, +#endif +}; + +/******************************************************************************* + * 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, + 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, +}; + +#define TX_RATE_MODE_CCK 0 +#define TX_RATE_MODE_OFDM 1 +#define TX_RATE_MODE_HTMIX 2 +#define TX_RATE_MODE_HTGF 3 +#define TX_RATE_MODE_VHT 4 +#define NVRAM_TAG_HDR_SIZE 3 /*ID+Len MSB+Len LSB*/ + +/******************************************************************************* + * M A 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wlanIsHandlerNeedHwAccess(IN PFN_OID_HANDLER_FUNC + pfnOidHandler, IN u_int8_t fgSetInfo) +{ + PFN_OID_HANDLER_FUNC *apfnOidHandlerWOHwAccess; + uint32_t i; + uint32_t 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 struct ADAPTER *prAdapter) +{ + DEBUGFUNC("wlanCardEjected"); + /* INITLOG(("\n")); */ + + ASSERT(prAdapter); + + /* mark that the card is being ejected, NDIS will shut us down soon */ + nicTxRelease(prAdapter, FALSE); + +} /* wlanCardEjected */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to check driver ready state + * + * \param[in] prGlueInfo Pointer to the GlueInfo structure. + * + * \retval TRUE Driver is ready for kernel access + * \retval FALSE Driver is not ready + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wlanIsDriverReady(IN struct GLUE_INFO *prGlueInfo) +{ + return prGlueInfo && prGlueInfo->u4ReadyFlag && !kalIsResetting(); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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. + */ +/*----------------------------------------------------------------------------*/ +struct ADAPTER *wlanAdapterCreate(IN struct GLUE_INFO + *prGlueInfo) +{ + struct ADAPTER *prAdpater = (struct ADAPTER *) NULL; + + DEBUGFUNC("wlanAdapterCreate"); + + do { + prAdpater = (struct ADAPTER *) kalMemAlloc(sizeof( + struct ADAPTER), 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(struct ADAPTER)); + 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 struct ADAPTER *prAdapter) +{ + if (!prAdapter) + return; + + scanLogCacheFlushAll(prAdapter, + &(prAdapter->rWifiVar.rScanInfo.rScanLogCache), + LOG_SCAN_D2D); + + kalMemFree(prAdapter, VIR_MEM_TYPE, sizeof(struct ADAPTER)); +} + +void wlanOnPreAllocAdapterMem(IN struct ADAPTER *prAdapter, + IN const u_int8_t bAtResetFlow) +{ + uint32_t i = 0, j = 0; + + DBGLOG(INIT, TRACE, "start.\n"); + + if (!bAtResetFlow) { + /* 4 <0> Reset variables in ADAPTER_T */ + /* prAdapter->fgIsFwOwn = TRUE; */ + prAdapter->fgIsEnterD3ReqIssued = FALSE; + prAdapter->ucHwBssIdNum = BSS_DEFAULT_NUM; + prAdapter->ucWmmSetNum = BSS_DEFAULT_NUM; + prAdapter->ucP2PDevBssIdx = BSS_DEFAULT_NUM; + prAdapter->ucWtblEntryNum = WTBL_SIZE; + prAdapter->ucTxDefaultWlanIndex = prAdapter->ucWtblEntryNum - 1; + + prAdapter->u4HifDbgFlag = 0; + prAdapter->u4HifChkFlag = 0; + prAdapter->u4TxHangFlag = 0; + prAdapter->u4NoMoreRfb = 0; + + /* Initialize rWlanInfo */ + kalMemSet(&(prAdapter->rWlanInfo), 0, + sizeof(struct WLAN_INFO)); + + /* Initialize aprBssInfo[]. + * Important: index shall be same + * when mapping between aprBssInfo[] + * and arBssInfoPool[].rP2pDevInfo + * is indexed to final one. + */ + for (i = 0; i < MAX_BSSID_NUM; i++) + prAdapter->aprBssInfo[i] = + &prAdapter->rWifiVar.arBssInfoPool[i]; + prAdapter->aprBssInfo[prAdapter->ucP2PDevBssIdx] = + &prAdapter->rWifiVar.rP2pDevInfo; + } else { + /* need to reset these values after the reset flow */ + prAdapter->u4NoMoreRfb = 0; + } + + prAdapter->u4OwnFailedCount = 0; + prAdapter->u4OwnFailedLogCount = 0; + prAdapter->fgEnHifDbgInfo = true; + prAdapter->ucCmdSeqNum = 0; + prAdapter->u4PwrCtrlBlockCnt = 0; + + if (bAtResetFlow) { + for (i = 0; i < (prAdapter->ucHwBssIdNum + 1); i++) + UNSET_NET_ACTIVE(prAdapter, i); + } + + QUEUE_INITIALIZE(&(prAdapter->rPendingCmdQueue)); +#if CFG_SUPPORT_MULTITHREAD + QUEUE_INITIALIZE(&prAdapter->rTxCmdQueue); + QUEUE_INITIALIZE(&prAdapter->rTxCmdDoneQueue); +#if CFG_FIX_2_TX_PORT + QUEUE_INITIALIZE(&prAdapter->rTxP0Queue); + QUEUE_INITIALIZE(&prAdapter->rTxP1Queue); +#else + for (i = 0; i < BSS_DEFAULT_NUM; i++) + for (j = 0; j < TX_PORT_NUM; j++) + QUEUE_INITIALIZE(&prAdapter->rTxPQueue[i][j]); +#endif + QUEUE_INITIALIZE(&prAdapter->rRxQueue); + QUEUE_INITIALIZE(&prAdapter->rTxDataDoneQueue); +#endif + + /* 4 <0.1> reset fgIsBusAccessFailed */ + fgIsBusAccessFailed = FALSE; +} + +void wlanOnPostNicInitAdapter(IN struct ADAPTER *prAdapter, + IN struct REG_INFO *prRegInfo, + IN const u_int8_t bAtResetFlow) +{ + DBGLOG(INIT, TRACE, "start.\n"); + + /* 4 <2.1> Initialize System Service (MGMT Memory pool and + * STA_REC) + */ + nicInitSystemService(prAdapter, bAtResetFlow); + + if (!bAtResetFlow) { + + /* 4 <2.2> Initialize Feature Options */ + wlanInitFeatureOption(prAdapter); +#if CFG_SUPPORT_MTK_SYNERGY +#if 0 /* u2FeatureReserved is 0 on 6765 */ + if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) { + if (prRegInfo->prNvramSettings->u2FeatureReserved & + BIT(MTK_FEATURE_2G_256QAM_DISABLED)) + prAdapter->rWifiVar.aucMtkFeature[0] &= + ~(MTK_SYNERGY_CAP_SUPPORT_24G_MCS89); + } +#endif +#endif + + /* 4 <2.3> Overwrite debug level settings */ + wlanCfgSetDebugLevel(prAdapter); + + /* 4 <3> Initialize Tx */ + nicTxInitialize(prAdapter); + } /* end of bAtResetFlow == FALSE */ + + /* 4 <4> Initialize Rx */ + nicRxInitialize(prAdapter); +} + +#if CFG_SUPPORT_NCHO + +uint32_t wlanNchoSetFWEnable(IN struct ADAPTER *prAdapter, IN uint8_t fgEnable) +{ + char cmd[NCHO_CMD_MAX_LENGTH] = { 0 }; + uint32_t status = WLAN_STATUS_FAILURE; + + kalSnprintf(cmd, sizeof(cmd), "%s %d", + FW_CFG_KEY_NCHO_ENABLE, fgEnable); + status = wlanFwCfgParse(prAdapter, cmd); + if (status != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, WARN, "set disable fail %d\n", status); + return status; +} + +uint32_t wlanNchoSetFWRssiTrigger(IN struct ADAPTER *prAdapter, + IN int32_t i4RoamTriggerRssi) +{ + char cmd[NCHO_CMD_MAX_LENGTH] = { 0 }; + uint32_t status = WLAN_STATUS_FAILURE; + + kalSnprintf(cmd, sizeof(cmd), "%s %d", + FW_CFG_KEY_NCHO_ROAM_RCPI, dBm_TO_RCPI(i4RoamTriggerRssi)); + status = wlanFwCfgParse(prAdapter, cmd); + if (status != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, WARN, "set roam rcpi fail %d\n", status); + return status; +} + +uint32_t wlanNchoSetFWScanPeriod(IN struct ADAPTER *prAdapter, + IN uint32_t u4RoamScanPeriod) +{ + char cmd[NCHO_CMD_MAX_LENGTH] = { 0 }; + uint32_t status = WLAN_STATUS_FAILURE; + + kalSnprintf(cmd, sizeof(cmd), "%s %d", + FW_CFG_KEY_NCHO_SCAN_PERIOD, u4RoamScanPeriod); + status = wlanFwCfgParse(prAdapter, cmd); + if (status != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, WARN, "set scan period fail %d\n", status); + return status; +} + +void wlanNchoInit(IN struct ADAPTER *prAdapter, IN uint8_t fgFwSync) +{ + uint8_t sync = fgFwSync && prAdapter->rNchoInfo.fgNCHOEnabled; + + /* NCHO Initialization */ + prAdapter->rNchoInfo.fgNCHOEnabled = 0; + prAdapter->rNchoInfo.eBand = NCHO_BAND_AUTO; + prAdapter->rNchoInfo.fgChGranted = FALSE; + prAdapter->rNchoInfo.fgIsSendingAF = FALSE; + prAdapter->rNchoInfo.u4RoamScanControl = 0; + prAdapter->rNchoInfo.rRoamScnChnl.ucChannelListNum = 0; + prAdapter->rNchoInfo.rAddRoamScnChnl.ucChannelListNum = 0; + prAdapter->rNchoInfo.eDFSScnMode = NCHO_DFS_SCN_ENABLE1; + prAdapter->rNchoInfo.i4RoamTrigger = -75; + prAdapter->rNchoInfo.i4RoamDelta = 10; + prAdapter->rNchoInfo.u4RoamScanPeriod = ROAMING_DISCOVER_TIMEOUT_SEC; + prAdapter->rNchoInfo.u4ScanChannelTime = 50; + prAdapter->rNchoInfo.u4ScanHomeTime = 120; + prAdapter->rNchoInfo.u4ScanHomeawayTime = 120; + prAdapter->rNchoInfo.u4ScanNProbes = 2; + prAdapter->rNchoInfo.u4WesMode = 0; + prAdapter->rAddRoamScnChnl.ucChannelListNum = 0; + + /* sync with FW to let FW reset params */ + if (sync) + wlanNchoSetFWEnable(prAdapter, 0); +} + +#endif + +void wlanOnPostFirmwareReady(IN struct ADAPTER *prAdapter, + IN struct REG_INFO *prRegInfo) +{ + DBGLOG(INIT, TRACE, "start.\n"); + /* OID timeout timer initialize */ + cnmTimerInitTimer(prAdapter, + &prAdapter->rOidTimeoutTimer, + (PFN_MGMT_TIMEOUT_FUNC) wlanReleasePendingOid, + (unsigned long) NULL); + + prAdapter->ucOidTimeoutCount = 0; + + prAdapter->fgIsChipNoAck = FALSE; + + /* Return Indicated Rfb list timer */ + cnmTimerInitTimer(prAdapter, + &prAdapter->rPacketDelaySetupTimer, + (PFN_MGMT_TIMEOUT_FUNC) + wlanReturnPacketDelaySetupTimeout, + (unsigned long) NULL); + + /* Power state initialization */ + prAdapter->fgWiFiInSleepyState = FALSE; + prAdapter->rAcpiState = ACPI_STATE_D0; + +#if 0 + /* 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; +#else + if (prAdapter->rWifiVar.fgDisOnlineScan == 0) + prAdapter->fgEnOnlineScan = TRUE; + else + prAdapter->fgEnOnlineScan = FALSE; + + /* Beacon lost detection option */ + if (prAdapter->rWifiVar.fgDisBcnLostDetection != 0) + prAdapter->fgDisBcnLostDetection = TRUE; +#endif + + /* 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->u4PsCurrentMeasureEn = + prRegInfo->u4PsCurrentMeasureEn; +#if 0 + prAdapter->fgEnArpFilter = prRegInfo->fgEnArpFilter; + prAdapter->u4UapsdAcBmp = prRegInfo->u4UapsdAcBmp; + prAdapter->u4MaxSpLen = prRegInfo->u4MaxSpLen; +#else + prAdapter->fgEnArpFilter = + prAdapter->rWifiVar.fgEnArpFilter; + prAdapter->u4UapsdAcBmp = prAdapter->rWifiVar.u4UapsdAcBmp; + prAdapter->u4MaxSpLen = prAdapter->rWifiVar.u4MaxSpLen; +#endif + DBGLOG(INIT, TRACE, + "[1] fgEnArpFilter:0x%x, u4UapsdAcBmp:0x%x, u4MaxSpLen:0x%x", + prAdapter->fgEnArpFilter, prAdapter->u4UapsdAcBmp, + prAdapter->u4MaxSpLen); + + prAdapter->fgEnCtiaPowerMode = FALSE; + +#endif + /* QA_TOOL and ICAP info struct */ + prAdapter->rIcapInfo.eIcapState = ICAP_STATE_INIT; + prAdapter->rIcapInfo.u2DumpIndex = 0; + prAdapter->rIcapInfo.u4CapNode = 0; + + /* MGMT Initialization */ + nicInitMGMT(prAdapter, prRegInfo); + +#if CFG_SUPPORT_NCHO + wlanNchoInit(prAdapter, FALSE); +#endif + + /* Enable WZC Disassociation */ + prAdapter->rWifiVar.fgSupportWZCDisassociation = TRUE; + + /* Apply Rate Setting */ + if ((enum ENUM_REGISTRY_FIXED_RATE) (prRegInfo->u4FixedRate) + < FIXED_RATE_NUM) + prAdapter->rWifiVar.eRateSetting = + (enum ENUM_REGISTRY_FIXED_RATE) + (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 0 /* Marked for MT6630 */ +#if 1 /* set PM parameters */ + { +#if CFG_SUPPORT_PWR_MGT + prAdapter->u4PowerMode = prRegInfo->u4PowerMode; +#if CFG_ENABLE_WIFI_DIRECT + prAdapter->rWlanInfo. + arPowerSaveMode[NETWORK_TYPE_P2P_INDEX].ucNetTypeIndex + = NETWORK_TYPE_P2P_INDEX; + prAdapter->rWlanInfo. + arPowerSaveMode[NETWORK_TYPE_P2P_INDEX].ucPsProfile + = ENUM_PSP_FAST_SWITCH; +#endif +#else + prAdapter->u4PowerMode = ENUM_PSP_CONTINUOUS_ACTIVE; +#endif + + nicConfigPowerSaveProfile(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, + prAdapter->u4PowerMode, FALSE); + } + +#endif +#endif + +#if CFG_SUPPORT_DYNAMIC_PWR_LIMIT + /* dynamic tx power control initialization */ + /* note: call this API before loading NVRAM */ + txPwrCtrlInit(prAdapter); +#endif + + /* Check hardware 5g band support */ + if (prAdapter->fgIsHw5GBandDisabled) + prAdapter->fgEnable5GBand = FALSE; + else + prAdapter->fgEnable5GBand = TRUE; + +#if CFG_SUPPORT_NVRAM + /* load manufacture data */ + if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) + wlanLoadManufactureData(prAdapter, prRegInfo); + else + DBGLOG(INIT, WARN, "%s: load manufacture data fail\n", + __func__); +#endif + +#if 0 + /* Update Auto rate parameters in FW */ + nicRlmArUpdateParms(prAdapter, prRegInfo->u4ArSysParam0, + prRegInfo->u4ArSysParam1, + prRegInfo->u4ArSysParam2, + prRegInfo->u4ArSysParam3); +#endif + + /* Default QM RX BA timeout */ + prAdapter->u4QmRxBaMissTimeout = + QM_RX_BA_ENTRY_MISS_TIMEOUT_MS; + +#if CFG_SUPPORT_LOWLATENCY_MODE + wlanAdapterStartForLowLatency(prAdapter); +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ +#if CFG_SUPPORT_DYNAMIC_PWR_LIMIT + /* dynamic tx power control load configuration */ + /* note: call this API after loading NVRAM */ + txPwrCtrlLoadConfig(prAdapter); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanAdapterStart(IN struct ADAPTER *prAdapter, + IN struct REG_INFO *prRegInfo, + IN const u_int8_t bAtResetFlow) +{ + uint32_t u4Status = WLAN_STATUS_SUCCESS; + enum ENUM_ADAPTER_START_FAIL_REASON { + ALLOC_ADAPTER_MEM_FAIL, + DRIVER_OWN_FAIL, + INIT_ADAPTER_FAIL, + INIT_HIFINFO_FAIL, + SET_CHIP_ECO_INFO_FAIL, + RAM_CODE_DOWNLOAD_FAIL, + WAIT_FIRMWARE_READY_FAIL, + FAIL_REASON_MAX + } eFailReason; + + ASSERT(prAdapter); + + DEBUGFUNC("wlanAdapterStart"); + + eFailReason = FAIL_REASON_MAX; + + wlanOnPreAllocAdapterMem(prAdapter, bAtResetFlow); + + do { + if (!bAtResetFlow) { + u4Status = nicAllocateAdapterMemory(prAdapter); + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "nicAllocateAdapterMemory Error!\n"); + u4Status = WLAN_STATUS_FAILURE; + eFailReason = ALLOC_ADAPTER_MEM_FAIL; +#if CFG_ENABLE_KEYWORD_EXCEPTION_MECHANISM + mtk_wcn_wmt_assert_keyword(WMTDRV_TYPE_WIFI, + "[Wi-Fi On] nicAllocateAdapterMemory Error!"); +#endif + break; + } + + prAdapter->u4OsPacketFilter + = PARAM_PACKET_FILTER_SUPPORTED; + } + /* set FALSE after wifi init flow or reset (not reinit WFDMA) */ + prAdapter->fgIsFwDownloaded = FALSE; + + DBGLOG(INIT, INFO, + "wlanAdapterStart(): Acquiring LP-OWN\n"); + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + DBGLOG(INIT, INFO, + "wlanAdapterStart(): Acquiring LP-OWN-end\n"); + +#if (CFG_ENABLE_FULL_PM == 0) + nicpmSetDriverOwn(prAdapter); +#endif + + if (prAdapter->fgIsFwOwn == TRUE) { + DBGLOG(INIT, ERROR, "nicpmSetDriverOwn() failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + eFailReason = DRIVER_OWN_FAIL; +#if CFG_ENABLE_KEYWORD_EXCEPTION_MECHANISM + mtk_wcn_wmt_assert_keyword(WMTDRV_TYPE_WIFI, + "[Wi-Fi On] nicpmSetDriverOwn() failed!"); +#endif + break; + } + +#if CFG_MTK_MCIF_WIFI_SUPPORT + setMddpSupportRegister(prAdapter); +#endif + + if (!bAtResetFlow) { + /* 4 <1> Initialize the Adapter */ + u4Status = nicInitializeAdapter(prAdapter); + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "nicInitializeAdapter failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + eFailReason = INIT_ADAPTER_FAIL; + break; + } + } + + wlanOnPostNicInitAdapter(prAdapter, prRegInfo, bAtResetFlow); + + /* 4 <5> HIF SW info initialize */ + if (!halHifSwInfoInit(prAdapter)) { + DBGLOG(INIT, ERROR, "halHifSwInfoInit failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + eFailReason = INIT_HIFINFO_FAIL; + break; + } + + /* 4 <6> Enable HIF cut-through to N9 mode, not visiting CR4 */ + HAL_ENABLE_FWDL(prAdapter, TRUE); + + /* 4 <7> Get ECO Version */ + if (wlanSetChipEcoInfo(prAdapter) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "wlanSetChipEcoInfo failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + eFailReason = SET_CHIP_ECO_INFO_FAIL; + break; + } + + /* recheck Asic capability depends on ECO version */ + wlanCheckAsicCap(prAdapter); + +#if CFG_ENABLE_FW_DOWNLOAD + /* 4 <8> FW/patch download */ + + /* 1. disable interrupt, download is done by polling mode only + */ + nicDisableInterrupt(prAdapter); + + /* 2. Initialize Tx Resource to fw download state */ + nicTxInitResetResource(prAdapter); + + u4Status = wlanDownloadFW(prAdapter); + if (u4Status != WLAN_STATUS_SUCCESS) { + eFailReason = RAM_CODE_DOWNLOAD_FAIL; +#if CFG_ENABLE_KEYWORD_EXCEPTION_MECHANISM + mtk_wcn_wmt_assert_keyword(WMTDRV_TYPE_WIFI, + "[Wi-Fi On] [Ram code download fail!]"); +#endif + break; + } +#endif + + DBGLOG(INIT, INFO, "Waiting for Ready bit..\n"); + + /* 4 <9> check Wi-Fi FW asserts ready bit */ + u4Status = wlanCheckWifiFunc(prAdapter, TRUE); + + if (u4Status == WLAN_STATUS_SUCCESS) { +#if defined(_HIF_SDIO) + uint32_t *pu4WHISR = NULL; + uint16_t au2TxCount[16]; + + pu4WHISR = (uint32_t *)kalMemAlloc(sizeof(uint32_t), + PHY_MEM_TYPE); + if (!pu4WHISR) { + DBGLOG(INIT, ERROR, + "Allocate pu4WHISR fail\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } + /* 1. reset interrupt status */ + HAL_READ_INTR_STATUS(prAdapter, sizeof(uint32_t), + (uint8_t *)pu4WHISR); + if (HAL_IS_TX_DONE_INTR(*pu4WHISR)) + HAL_READ_TX_RELEASED_COUNT(prAdapter, + au2TxCount); + + if (pu4WHISR) + kalMemFree(pu4WHISR, PHY_MEM_TYPE, + sizeof(uint32_t)); +#endif + /* Set FW download success flag */ + prAdapter->fgIsFwDownloaded = TRUE; + + /* 2. query & reset TX Resource for normal operation */ + wlanQueryNicResourceInformation(prAdapter); + +#if (CFG_SUPPORT_NIC_CAPABILITY == 1) + if (!bAtResetFlow) { + /* 2.9 Workaround for Capability + *CMD packet lost issue + */ + wlanSendDummyCmd(prAdapter, TRUE); + + /* 3. query for NIC capability */ + if (prAdapter->chip_info->isNicCapV1) + wlanQueryNicCapability(prAdapter); + + /* 4. query for NIC capability V2 */ + u4Status = wlanQueryNicCapabilityV2(prAdapter); + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, WARN, + "wlanQueryNicCapabilityV2 failed.\n"); + RECLAIM_POWER_CONTROL_TO_PM( + prAdapter, FALSE); + eFailReason = WAIT_FIRMWARE_READY_FAIL; + break; + } + + /* 5. reset TX Resource for normal operation + * based on the information reported from + * CMD_NicCapabilityV2 + */ + wlanUpdateNicResourceInformation(prAdapter); + + wlanPrintVersion(prAdapter); + } +#endif + + /* 6. update basic configuration */ + wlanUpdateBasicConfig(prAdapter); + + if (!bAtResetFlow) { + uint32_t u4Idx = 0; + + /* 7. Override network address */ + wlanUpdateNetworkAddress(prAdapter); + + /* 8. Apply Network Address */ + nicApplyNetworkAddress(prAdapter); + + /* 9. indicate disconnection + * as default status + */ + for (u4Idx = 0; u4Idx < KAL_AIS_NUM; u4Idx++) + kalIndicateStatusAndComplete( + prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, + NULL, 0, + u4Idx); + } + } + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + + if (u4Status != WLAN_STATUS_SUCCESS) { + eFailReason = WAIT_FIRMWARE_READY_FAIL; + break; + } + + if (!bAtResetFlow) + wlanOnPostFirmwareReady(prAdapter, prRegInfo); + else { +#if CFG_SUPPORT_NVRAM + /* load manufacture data */ + if (kalIsConfigurationExist(prAdapter->prGlueInfo) + == TRUE) + wlanLoadManufactureData(prAdapter, prRegInfo); + else + DBGLOG(INIT, WARN, + "%s: load manufacture data fail\n", __func__); +#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); + /* init SER module */ + nicSerInit(prAdapter); + } else { + prAdapter->u4HifDbgFlag |= DEG_HIF_DEFAULT_DUMP; + halPrintHifDbgInfo(prAdapter); + DBGLOG(INIT, WARN, "Fail reason: %d\n", eFailReason); + + /* Don't do error handling in chip reset flow, leave it to + * coming wlanRemove for full clean + */ + if (!bAtResetFlow) { + /* release allocated memory */ + switch (eFailReason) { + case WAIT_FIRMWARE_READY_FAIL: + case RAM_CODE_DOWNLOAD_FAIL: + case SET_CHIP_ECO_INFO_FAIL: + case INIT_HIFINFO_FAIL: + nicRxUninitialize(prAdapter); + nicTxRelease(prAdapter, FALSE); + /* System Service Uninitialization */ + nicUninitSystemService(prAdapter); + /* fallthrough */ + case INIT_ADAPTER_FAIL: + /* fallthrough */ + case DRIVER_OWN_FAIL: + nicReleaseAdapterMemory(prAdapter); + break; + case ALLOC_ADAPTER_MEM_FAIL: + default: + break; + } + } + } + + if (prAdapter->chip_info->checkbushang) + prAdapter->chip_info->checkbushang((void *) prAdapter, TRUE); + + return u4Status; +} /* wlanAdapterStart */ + +void wlanOffClearAllQueues(IN struct ADAPTER *prAdapter) +{ + DBGLOG(INIT, INFO, "wlanOffClearAllQueues(): start.\n"); + + /* Release all CMD/MGMT/SEC frame in command queue */ + kalClearCommandQueue(prAdapter->prGlueInfo); + + /* Release all CMD in pending command queue */ + wlanClearPendingCommandQueue(prAdapter); + +#if CFG_SUPPORT_MULTITHREAD + + /* Flush all items in queues for multi-thread */ + wlanClearTxCommandQueue(prAdapter); + + wlanClearTxCommandDoneQueue(prAdapter); + + wlanClearDataQueue(prAdapter); + + wlanClearRxToOsQueue(prAdapter); + +#endif +} + +void wlanOffUninitNicModule(IN struct ADAPTER *prAdapter, + IN const u_int8_t bAtResetFlow) +{ + DBGLOG(INIT, INFO, "wlanOffUninitNicModule(): start.\n"); + nicRxUninitialize(prAdapter); + + nicTxRelease(prAdapter, FALSE); + + if (!bAtResetFlow) { + /* MGMT - unitialization */ + nicUninitMGMT(prAdapter); + + /* System Service Uninitialization */ + nicUninitSystemService(prAdapter); +#if CFG_SUPPORT_DYNAMIC_PWR_LIMIT + /* dynamic tx power control uninitialization */ + txPwrCtrlUninit(prAdapter); +#endif + nicReleaseAdapterMemory(prAdapter); + +#if defined(_HIF_SPI) + /* Note: restore the SPI Mode Select from 32 bit to default */ + nicRestoreSpiDefMode(prAdapter); +#endif + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Uninitialize the adapter + * + * \param prAdapter Pointer of Adapter Data Structure + * + * \retval WLAN_STATUS_SUCCESS: Success + * \retval WLAN_STATUS_FAILURE: Failed + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanAdapterStop(IN struct ADAPTER *prAdapter, + IN const u_int8_t bAtResetFlow) +{ + uint32_t u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + + wlanOffClearAllQueues(prAdapter); + + /* Hif power off wifi */ + if (prAdapter->rAcpiState == ACPI_STATE_D0 && + !wlanIsChipNoAck(prAdapter) + && !kalIsCardRemoved(prAdapter->prGlueInfo)) { + wlanPowerOffWifi(prAdapter); + } + + halHifSwInfoUnInit(prAdapter->prGlueInfo); + wlanOffUninitNicModule(prAdapter, bAtResetFlow); + + 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wlanISR(IN struct ADAPTER *prAdapter, + IN u_int8_t 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 struct ADAPTER *prAdapter, bool fgEnInt) +{ + uint32_t u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + if (prAdapter->fgIsFwOwn == FALSE) { + u4Status = nicProcessIST(prAdapter); + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, INFO, "Fail: nicProcessIST! status [%x]\n", + u4Status); + } +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + if (KAL_WAKE_LOCK_ACTIVE(prAdapter, + prAdapter->prGlueInfo->rIntrWakeLock)) + KAL_WAKE_UNLOCK(prAdapter, + prAdapter->prGlueInfo->rIntrWakeLock); +#endif + } + + if (fgEnInt) + nicEnableInterrupt(prAdapter); + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + + +} + +void wlanClearPendingInterrupt(IN struct ADAPTER *prAdapter) +{ + uint32_t i; + + i = 0; + while (i < CFG_IST_LOOP_COUNT + && nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) { + i++; + }; +} + +void wlanCheckAsicCap(IN struct ADAPTER *prAdapter) +{ + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + + prChipInfo = prAdapter->chip_info; + + if (prChipInfo->wlanCheckAsicCap) + prChipInfo->wlanCheckAsicCap(prAdapter); +} + +uint32_t wlanCheckWifiFunc(IN struct ADAPTER *prAdapter, + IN u_int8_t fgRdyChk) +{ + u_int8_t fgResult, fgTimeout; + uint32_t u4Result = 0, u4Status, u4StartTime, u4CurTime; + const uint32_t ready_bits = + prAdapter->chip_info->sw_ready_bits; + + u4StartTime = kalGetTimeTick(); + fgTimeout = FALSE; + +#if defined(_HIF_USB) + if (prAdapter->prGlueInfo->rHifInfo.state == + USB_STATE_LINK_DOWN) + return WLAN_STATUS_FAILURE; +#endif + + while (TRUE) { + DBGLOG_LIMITED(INIT, TRACE, + "Check ready_bits(=0x%x)\n", ready_bits); + if (fgRdyChk) + HAL_WIFI_FUNC_READY_CHECK(prAdapter, + ready_bits /* WIFI_FUNC_READY_BITS */, + &fgResult); + else { + HAL_WIFI_FUNC_OFF_CHECK(prAdapter, + ready_bits /* WIFI_FUNC_READY_BITS */, + &fgResult); +#if defined(_HIF_USB) || defined(_HIF_SDIO) + if (nicProcessIST(prAdapter) != + WLAN_STATUS_NOT_INDICATING) + DBGLOG_LIMITED(INIT, INFO, + "Handle pending interrupt\n"); +#endif /* _HIF_USB or _HIF_SDIO */ + } + u4CurTime = kalGetTimeTick(); + + if (CHECK_FOR_TIMEOUT(u4CurTime, u4StartTime, + CFG_RESPONSE_POLLING_TIMEOUT * + CFG_RESPONSE_POLLING_DELAY)) { + + fgTimeout = TRUE; + } + + if (fgResult) { + if (fgRdyChk) + DBGLOG_LIMITED(INIT, INFO, + "Ready bit asserted\n"); + else + DBGLOG_LIMITED(INIT, INFO, + "Wi-Fi power off done!\n"); + + u4Status = WLAN_STATUS_SUCCESS; + + break; + } else if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + + break; + } else if (fgTimeout) { + HAL_WIFI_FUNC_GET_STATUS(prAdapter, u4Result); + DBGLOG(INIT, ERROR, + "Waiting for %s: Timeout, Status=0x%08x\n", + fgRdyChk ? "ready bit" : "power off", u4Result); +#if CFG_ENABLE_KEYWORD_EXCEPTION_MECHANISM + mtk_wcn_wmt_assert_keyword(WMTDRV_TYPE_WIFI, + "[Wi-Fi] [Read WCIR_WLAN_READY fail!]"); +#else + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP | + RST_FLAG_PREVENT_POWER_OFF); +#endif + u4Status = WLAN_STATUS_FAILURE; + break; + } + kalMsleep(CFG_RESPONSE_POLLING_DELAY); + + } + + return u4Status; +} + +uint32_t wlanPowerOffWifi(IN struct ADAPTER *prAdapter) +{ + uint32_t rStatus; + /* Hif power off wifi */ + rStatus = halHifPowerOffWifi(prAdapter); + prAdapter->fgIsCr4FwDownloaded = FALSE; + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanProcessCommandQueue(IN struct ADAPTER + *prAdapter, IN struct QUE *prCmdQue) +{ + uint32_t rStatus; + struct QUE rTempCmdQue, rMergeCmdQue, rStandInCmdQue; + struct QUE *prTempCmdQue, *prMergeCmdQue, *prStandInCmdQue; + struct QUE_ENTRY *prQueueEntry; + struct CMD_INFO *prCmdInfo; + struct MSDU_INFO *prMsduInfo; + enum ENUM_FRAME_ACTION 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, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) 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: + case COMMAND_TYPE_DATA_FRAME: + /* inquire with QM */ + prMsduInfo = prCmdInfo->prMsduInfo; + + eFrameAction = qmGetFrameAction(prAdapter, + prMsduInfo->ucBssIndex, + prMsduInfo->ucStaRecIndex, + NULL, FRAME_TYPE_802_1X, + prCmdInfo->u2InfoBufLen); + break; + + case COMMAND_TYPE_MANAGEMENT_FRAME: + /* inquire with QM */ + prMsduInfo = prCmdInfo->prMsduInfo; + + eFrameAction = qmGetFrameAction(prAdapter, + prMsduInfo->ucBssIndex, + prMsduInfo->ucStaRecIndex, + prMsduInfo, FRAME_TYPE_MMPDU, + prMsduInfo->u2FrameLength); + break; + + default: + ASSERT(0); + break; + } +#if (CFG_SUPPORT_STATISTICS == 1) + wlanWakeLogCmd(prCmdInfo->ucCID); +#endif + /* 4 <3> handling upon dequeue result */ + if (eFrameAction == FRAME_ACTION_DROP_PKT) { + DBGLOG(INIT, INFO, + "DROP CMD TYPE[%u] ID[0x%02X] SEQ[%u]\n", + prCmdInfo->eCmdType, prCmdInfo->ucCID, + prCmdInfo->ucCmdSeqNum); + wlanReleaseCommand(prAdapter, prCmdInfo, + TX_RESULT_DROPPED_IN_DRIVER); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } else if (eFrameAction == FRAME_ACTION_QUEUE_PKT) { + DBGLOG(INIT, TRACE, + "QUE back CMD TYPE[%u] ID[0x%02X] SEQ[%u]\n", + prCmdInfo->eCmdType, prCmdInfo->ucCID, + prCmdInfo->ucCmdSeqNum); + + QUEUE_INSERT_TAIL(prMergeCmdQue, prQueueEntry); + } else if (eFrameAction == FRAME_ACTION_TX_PKT) { + /* 4 <4> Send the command */ +#if CFG_SUPPORT_MULTITHREAD + rStatus = wlanSendCommandMthread(prAdapter, prCmdInfo); + + if (rStatus == WLAN_STATUS_RESOURCES) { + /* no more TC4 resource for further + * transmission + */ + DBGLOG(INIT, WARN, + "NO Res CMD TYPE[%u] ID[0x%02X] SEQ[%u]\n", + prCmdInfo->eCmdType, prCmdInfo->ucCID, + prCmdInfo->ucCmdSeqNum); + + prAdapter->u4HifDbgFlag |= DEG_HIF_ALL; + kalSetHifDbgEvent(prAdapter->prGlueInfo); + + QUEUE_INSERT_TAIL(prMergeCmdQue, prQueueEntry); + + /* + * We reserve one TC4 resource for CMD + * specially, only break checking the left tx + * request if no resource for true CMD. + */ + if ((prCmdInfo->eCmdType != + COMMAND_TYPE_SECURITY_FRAME) && + (prCmdInfo->eCmdType != + COMMAND_TYPE_MANAGEMENT_FRAME) && + (prCmdInfo->eCmdType != + COMMAND_TYPE_DATA_FRAME)) + break; + } else if (rStatus == WLAN_STATUS_PENDING) { + /* Do nothing */ + /* Do nothing */ + } else if (rStatus == WLAN_STATUS_SUCCESS) { + prAdapter->fgEnHifDbgInfo = true; + } else { + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) + prQueueEntry; + + if (prCmdInfo->fgIsOid) { + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4SetInfoLen, + rStatus); + } + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + +#else + rStatus = wlanSendCommand(prAdapter, prCmdInfo); + + if (rStatus == WLAN_STATUS_RESOURCES) { + /* no more TC4 resource for further + * transmission + */ + + DBGLOG(INIT, WARN, + "NO Resource for CMD TYPE[%u] ID[0x%02X] SEQ[%u]\n", + prCmdInfo->eCmdType, prCmdInfo->ucCID, + prCmdInfo->ucCmdSeqNum); + + 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 { + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) + 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); + } +#endif + } else { + ASSERT(0); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + + /* 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); + +#if CFG_SUPPORT_MULTITHREAD + kalSetTxCmdEvent2Hif(prAdapter->prGlueInfo); +#endif + + return WLAN_STATUS_SUCCESS; +} /* end of wlanProcessCommandQueue() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will take CMD_INFO_T which carry some information of + * incoming OID and notify the NIC_TX to send CMD. + * + * \param prAdapter Pointer of Adapter Data Structure + * \param prCmdInfo Pointer of P_CMD_INFO_T + * + * \retval WLAN_STATUS_SUCCESS : CMD was written to HIF and be freed(CMD Done) + * immediately. + * \retval WLAN_STATUS_RESOURCE : No resource for current command, need to wait + * for previous + * frame finishing their transmission. + * \retval WLAN_STATUS_FAILURE : Get failure while access HIF or been + * rejected. + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanSendCommand(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo) +{ + struct TX_CTRL *prTxCtrl; + uint8_t ucTC; /* "Traffic Class" SW(Driver) resource + * classification + */ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + prTxCtrl = &prAdapter->rTxCtrl; + + do { + /* <0> card removal check */ + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + rStatus = WLAN_STATUS_FAILURE; + break; + } + + /* <1.1> Assign Traffic Class(TC) */ + ucTC = nicTxGetCmdResourceType(prCmdInfo); + + /* <1.2> Check if pending packet or resource was exhausted */ + rStatus = nicTxAcquireResource(prAdapter, ucTC, + nicTxGetCmdPageCount(prAdapter, prCmdInfo), + TRUE); + if (rStatus == WLAN_STATUS_RESOURCES) { + DBGLOG(INIT, INFO, "NO Resource:%d\n", ucTC); + break; + } + GLUE_INC_REF_CNT(prAdapter->rHifStats.u4CmdInCount); + /* <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; + } + + } while (FALSE); + + return rStatus; +} /* end of wlanSendCommand() */ + +#if CFG_SUPPORT_MULTITHREAD + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will take CMD_INFO_T which carry some information of + * incoming OID and notify the NIC_TX to send CMD. + * + * \param prAdapter Pointer of Adapter Data Structure + * \param prCmdInfo Pointer of P_CMD_INFO_T + * + * \retval WLAN_STATUS_SUCCESS : CMD was written to HIF and be freed(CMD Done) + * immediately. + * \retval WLAN_STATUS_RESOURCE : No resource for current command, need to wait + * for previous + * frame finishing their transmission. + * \retval WLAN_STATUS_FAILURE : Get failure while access HIF or been + * rejected. + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanSendCommandMthread(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo) +{ + struct TX_CTRL *prTxCtrl; + uint8_t ucTC; /* "Traffic Class" SW(Driver) resource + * classification + */ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue; + +#if CFG_DBG_MGT_BUF + struct MEM_TRACK *prMemTrack = NULL; +#endif + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + prTxCtrl = &prAdapter->rTxCtrl; + +#if CFG_DBG_MGT_BUF + if (prCmdInfo->pucInfoBuffer && + !IS_FROM_BUF(prAdapter, prCmdInfo->pucInfoBuffer)) + prMemTrack = + (struct MEM_TRACK *) + ((uint8_t *)prCmdInfo->pucInfoBuffer - + sizeof(struct MEM_TRACK)); +#endif + + prTempCmdQue = &rTempCmdQue; + QUEUE_INITIALIZE(prTempCmdQue); + + do { + /* <0> card removal check */ + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + rStatus = WLAN_STATUS_FAILURE; + break; + } + /* <1> Normal case of sending CMD Packet */ + /* <1.1> Assign Traffic Class(TC) */ + ucTC = nicTxGetCmdResourceType(prCmdInfo); + + /* <1.2> Check if pending packet or resource was exhausted */ + rStatus = nicTxAcquireResource(prAdapter, ucTC, + nicTxGetCmdPageCount(prAdapter, prCmdInfo), + TRUE); + if (rStatus == WLAN_STATUS_RESOURCES) { +#if 0 + DBGLOG(INIT, WARN, + "%s: NO Resource for CMD TYPE[%u] ID[0x%02X] SEQ[%u] TC[%u]\n", + __func__, prCmdInfo->eCmdType, prCmdInfo->ucCID, + prCmdInfo->ucCmdSeqNum, ucTC); +#endif + break; + } + + /* Process to pending command queue firest */ + if ((!prCmdInfo->fgSetQuery) || (prCmdInfo->fgNeedResp)) { + /* command packet which needs further handling upon + * response + */ + /* + * KAL_ACQUIRE_SPIN_LOCK(prAdapter, + * SPIN_LOCK_CMD_PENDING); + * QUEUE_INSERT_TAIL(&(prAdapter->rPendingCmdQueue), + * (struct QUE_ENTRY *)prCmdInfo); + * KAL_RELEASE_SPIN_LOCK(prAdapter, + * SPIN_LOCK_CMD_PENDING); + */ + } + +#if CFG_DBG_MGT_BUF + if (prMemTrack) { + prMemTrack->u2CmdIdAndWhere &= 0x00FF; + prMemTrack->u2CmdIdAndWhere |= 0x0100; + } +#endif + + QUEUE_INSERT_TAIL(prTempCmdQue, + (struct QUE_ENTRY *) prCmdInfo); + + /* <1.4> Set Pending in response to Query Command/Need Response + */ + if (rStatus == WLAN_STATUS_SUCCESS) { + if ((!prCmdInfo->fgSetQuery) || + (prCmdInfo->fgNeedResp) || + (prCmdInfo->eCmdType == + COMMAND_TYPE_SECURITY_FRAME || + prCmdInfo->eCmdType == + COMMAND_TYPE_DATA_FRAME)) { + rStatus = WLAN_STATUS_PENDING; + } + } + } while (FALSE); + + GLUE_ADD_REF_CNT(prTempCmdQue->u4NumElem, + prAdapter->rHifStats.u4CmdInCount); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); + QUEUE_CONCATENATE_QUEUES(&(prAdapter->rTxCmdQueue), + prTempCmdQue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); + + return rStatus; +} /* end of wlanSendCommandMthread() */ + +void wlanTxCmdDoneCb(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo) +{ + KAL_SPIN_LOCK_DECLARATION(); + + if ((!prCmdInfo->fgSetQuery) || (prCmdInfo->fgNeedResp)) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + QUEUE_INSERT_TAIL(&prAdapter->rPendingCmdQueue, + (struct QUE_ENTRY *) prCmdInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + } +} + +uint32_t wlanTxCmdMthread(IN struct ADAPTER *prAdapter) +{ + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue; + struct QUE rTempCmdDoneQue; + struct QUE *prTempCmdDoneQue; + struct QUE_ENTRY *prQueueEntry; + struct CMD_INFO *prCmdInfo; + /* P_CMD_ACCESS_REG prCmdAccessReg; + * P_CMD_ACCESS_REG prEventAccessReg; + * UINT_32 u4Address; + */ + uint32_t u4TxDoneQueueSize; +#if CFG_DBG_MGT_BUF + struct MEM_TRACK *prMemTrack = NULL; +#endif + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + if (halIsHifStateSuspend(prAdapter)) { + DBGLOG(TX, WARN, "Suspend TxCmdMthread\n"); + return WLAN_STATUS_SUCCESS; + } + + prTempCmdQue = &rTempCmdQue; + QUEUE_INITIALIZE(prTempCmdQue); + + prTempCmdDoneQue = &rTempCmdDoneQue; + QUEUE_INITIALIZE(prTempCmdDoneQue); + + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_TX_CMD_CLEAR); + + /* TX Command Queue */ + /* 4 <1> Move whole list of CMD_INFO to temp queue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, &prAdapter->rTxCmdQueue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); + + /* 4 <2> Dequeue from head and check it is able to be sent */ + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + prCmdInfo->pfHifTxCmdDoneCb = wlanTxCmdDoneCb; +#if CFG_DBG_MGT_BUF + if (prCmdInfo->pucInfoBuffer && + !IS_FROM_BUF(prAdapter, + prCmdInfo->pucInfoBuffer)) + prMemTrack = + (struct MEM_TRACK *) + ((uint8_t *)prCmdInfo->pucInfoBuffer - + sizeof(struct MEM_TRACK)); +#endif + + if ((!prCmdInfo->fgSetQuery) || (prCmdInfo->fgNeedResp)) { +#if CFG_DBG_MGT_BUF + if (prMemTrack) { + prMemTrack->u2CmdIdAndWhere &= 0x00FF; + prMemTrack->u2CmdIdAndWhere |= 0x0200; + } +#endif + } else { +#if CFG_DBG_MGT_BUF + if (prMemTrack) { + prMemTrack->u2CmdIdAndWhere &= 0x00FF; + prMemTrack->u2CmdIdAndWhere |= 0x0300; + } +#endif + QUEUE_INSERT_TAIL(prTempCmdDoneQue, prQueueEntry); + } + + if (nicTxCmd(prAdapter, prCmdInfo, TC4_INDEX) + != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, WARN, "nicTxCmd returns error\n"); + + /* DBGLOG(INIT, INFO, "==> TX CMD QID: %d (Q:%d)\n", + * prCmdInfo->ucCID, prTempCmdQue->u4NumElem)); + */ + + GLUE_DEC_REF_CNT(prAdapter->prGlueInfo->i4TxPendingCmdNum); + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); + QUEUE_CONCATENATE_QUEUES(&prAdapter->rTxCmdDoneQueue, + prTempCmdDoneQue); + u4TxDoneQueueSize = prAdapter->rTxCmdDoneQueue.u4NumElem; + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); + + KAL_RELEASE_MUTEX(prAdapter, MUTEX_TX_CMD_CLEAR); + + /* call tx thread to work */ + if (u4TxDoneQueueSize > 0) + kalSetTxCmdDoneEvent(prAdapter->prGlueInfo); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanTxCmdDoneMthread(IN struct ADAPTER *prAdapter) +{ + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue; + struct QUE_ENTRY *prQueueEntry; + struct CMD_INFO *prCmdInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + if (halIsHifStateSuspend(prAdapter)) { + DBGLOG(TX, WARN, "Suspend TxCmdDoneMthread\n"); + return WLAN_STATUS_SUCCESS; + } + + prTempCmdQue = &rTempCmdQue; + QUEUE_INITIALIZE(prTempCmdQue); + + /* 4 <1> Move whole list of CMD_INFO to temp queue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, &prAdapter->rTxCmdDoneQueue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); + + /* 4 <2> Dequeue from head and check it is able to be sent */ + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + + if (prCmdInfo->pfCmdDoneHandler) + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, + prCmdInfo->pucInfoBuffer); + /* Not pending cmd, free it after TX succeed! */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to clear all commands in TX command queue + * \param prAdapter Pointer of Adapter Data Structure + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +void wlanClearTxCommandQueue(IN struct ADAPTER *prAdapter) +{ + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue = &rTempCmdQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + QUEUE_INITIALIZE(prTempCmdQue); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, &prAdapter->rTxCmdQueue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + + if (prCmdInfo->pfCmdTimeoutHandler) + prCmdInfo->pfCmdTimeoutHandler(prAdapter, prCmdInfo); + else + wlanReleaseCommand(prAdapter, prCmdInfo, + TX_RESULT_QUEUE_CLEARANCE); + + /* Release Tx resource for CMD which resource is allocated but + * not used + */ + nicTxReleaseResource_PSE(prAdapter, + nicTxGetCmdResourceType(prCmdInfo), + nicTxGetCmdPageCount(prAdapter, prCmdInfo), TRUE); + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to clear OID commands in TX command queue + * \param prAdapter Pointer of Adapter Data Structure + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +void wlanClearTxOidCommand(IN struct ADAPTER *prAdapter) +{ + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue = &rTempCmdQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + QUEUE_INITIALIZE(prTempCmdQue); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); + + QUEUE_MOVE_ALL(prTempCmdQue, &prAdapter->rTxCmdQueue); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + + if (prCmdInfo->fgIsOid) { + DBGLOG(OID, INFO, + "Clear pending OID CMD ID[0x%02X] SEQ[%u]\n", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + if (prCmdInfo->pfCmdTimeoutHandler) + prCmdInfo->pfCmdTimeoutHandler(prAdapter, + prCmdInfo); + else + wlanReleaseCommand(prAdapter, prCmdInfo, + TX_RESULT_QUEUE_CLEARANCE); + + /* Release Tx resource for CMD which resource is + * allocated but not used + */ + nicTxReleaseResource_PSE(prAdapter, + nicTxGetCmdResourceType(prCmdInfo), + nicTxGetCmdPageCount(prAdapter, prCmdInfo), + TRUE); + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + } else { + QUEUE_INSERT_TAIL(&prAdapter->rTxCmdQueue, + prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to clear all commands in TX command done queue + * \param prAdapter Pointer of Adapter Data Structure + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +void wlanClearTxCommandDoneQueue(IN struct ADAPTER + *prAdapter) +{ + struct QUE rTempCmdDoneQue; + struct QUE *prTempCmdDoneQue = &rTempCmdDoneQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + QUEUE_INITIALIZE(prTempCmdDoneQue); + + /* 4 <1> Move whole list of CMD_INFO to temp queue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); + QUEUE_MOVE_ALL(prTempCmdDoneQue, + &prAdapter->rTxCmdDoneQueue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); + + /* 4 <2> Dequeue from head and check it is able to be sent */ + QUEUE_REMOVE_HEAD(prTempCmdDoneQue, prQueueEntry, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + + if (prCmdInfo->pfCmdDoneHandler) + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, + prCmdInfo->pucInfoBuffer); + /* Not pending cmd, free it after TX succeed! */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + QUEUE_REMOVE_HEAD(prTempCmdDoneQue, prQueueEntry, + struct QUE_ENTRY *); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to clear all buffer in port 0/1 queue + * \param prAdapter Pointer of Adapter Data Structure + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +void wlanClearDataQueue(IN struct ADAPTER *prAdapter) +{ + if (HAL_IS_TX_DIRECT()) + nicTxDirectClearHifQ(prAdapter); + else { +#if CFG_FIX_2_TX_PORT + struct QUE qDataPort0, qDataPort1; + struct QUE *prDataPort0, *prDataPort1; + struct MSDU_INFO *prMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + prDataPort0 = &qDataPort0; + prDataPort1 = &qDataPort1; + + QUEUE_INITIALIZE(prDataPort0); + QUEUE_INITIALIZE(prDataPort1); + + /* <1> Move whole list of CMD_INFO to temp queue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + QUEUE_MOVE_ALL(prDataPort0, &prAdapter->rTxP0Queue); + QUEUE_MOVE_ALL(prDataPort1, &prAdapter->rTxP1Queue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + + /* <2> Release Tx resource */ + nicTxReleaseMsduResource(prAdapter, + (struct MSDU_INFO *) QUEUE_GET_HEAD(prDataPort0)); + nicTxReleaseMsduResource(prAdapter, + (struct MSDU_INFO *) QUEUE_GET_HEAD(prDataPort1)); + + /* <3> Return sk buffer */ + nicTxReturnMsduInfo(prAdapter, (struct MSDU_INFO *) + QUEUE_GET_HEAD(prDataPort0)); + nicTxReturnMsduInfo(prAdapter, (struct MSDU_INFO *) + QUEUE_GET_HEAD(prDataPort1)); + + /* <4> Clear pending MSDU info in data done queue */ + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); + while (QUEUE_IS_NOT_EMPTY(&prAdapter->rTxDataDoneQueue)) { + QUEUE_REMOVE_HEAD(&prAdapter->rTxDataDoneQueue, + prMsduInfo, struct MSDU_INFO *); + if (prMsduInfo == NULL) { + DBGLOG(TX, WARN, "prMsduInfo is NULL\n"); + break; + } + nicTxFreePacket(prAdapter, prMsduInfo, FALSE); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } + KAL_RELEASE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); +#else + + struct QUE qDataPort[BSS_DEFAULT_NUM][TX_PORT_NUM]; + struct QUE *prDataPort[BSS_DEFAULT_NUM][TX_PORT_NUM]; + struct MSDU_INFO *prMsduInfo; + int32_t i, j; + + KAL_SPIN_LOCK_DECLARATION(); + + for (i = 0; i < BSS_DEFAULT_NUM; i++) { + for (j = 0; j < TX_PORT_NUM; j++) { + prDataPort[i][j] = &qDataPort[i][j]; + QUEUE_INITIALIZE(prDataPort[i][j]); + } + } + + /* <1> Move whole list of CMD_INFO to temp queue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + for (i = 0; i < BSS_DEFAULT_NUM; i++) { + for (j = 0; j < TX_PORT_NUM; j++) { + QUEUE_MOVE_ALL(prDataPort[i][j], + &prAdapter->rTxPQueue[i][j]); + kalTraceEvent("Move TxPQueue%d_%d %d", i, j, + prDataPort[i][j]->u4NumElem); + } + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + + /* <2> Return sk buffer */ + for (i = 0; i < BSS_DEFAULT_NUM; i++) { + for (j = 0; j < TX_PORT_NUM; j++) { + nicTxReleaseMsduResource(prAdapter, + (struct MSDU_INFO *) + QUEUE_GET_HEAD(prDataPort[i][j])); + nicTxReturnMsduInfo(prAdapter, + (struct MSDU_INFO *) + QUEUE_GET_HEAD(prDataPort[i][j])); + } + } + + /* <3> Clear pending MSDU info in data done queue */ + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); + while (QUEUE_IS_NOT_EMPTY(&prAdapter->rTxDataDoneQueue)) { + QUEUE_REMOVE_HEAD(&prAdapter->rTxDataDoneQueue, + prMsduInfo, struct MSDU_INFO *); + + nicTxFreePacket(prAdapter, prMsduInfo, FALSE); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } + KAL_RELEASE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); +#endif + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to clear all buffer in port 0/1 queue + * \param prAdapter Pointer of Adapter Data Structure + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +void wlanClearRxToOsQueue(IN struct ADAPTER *prAdapter) +{ + struct QUE rTempRxQue; + struct QUE *prTempRxQue = &rTempRxQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + QUEUE_INITIALIZE(prTempRxQue); + + /* 4 <1> Move whole list of CMD_INFO to temp queue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); + QUEUE_MOVE_ALL(prTempRxQue, &prAdapter->rRxQueue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); + + /* 4 <2> Remove all skbuf */ + QUEUE_REMOVE_HEAD(prTempRxQue, prQueueEntry, + struct QUE_ENTRY *); + while (prQueueEntry) { + kalRxIndicateOnePkt(prAdapter->prGlueInfo, + (void *) GLUE_GET_PKT_DESCRIPTOR(prQueueEntry)); + QUEUE_REMOVE_HEAD(prTempRxQue, prQueueEntry, + struct QUE_ENTRY *); + } + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to clear all commands in pending command queue + * \param prAdapter Pointer of Adapter Data Structure + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +void wlanClearPendingCommandQueue(IN struct ADAPTER *prAdapter) +{ + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue = &rTempCmdQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + QUEUE_INITIALIZE(prTempCmdQue); + + ASSERT(prAdapter); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + QUEUE_MOVE_ALL(prTempCmdQue, &prAdapter->rPendingCmdQueue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + + if (prCmdInfo->pfCmdTimeoutHandler) + prCmdInfo->pfCmdTimeoutHandler(prAdapter, prCmdInfo); + else + wlanReleaseCommand(prAdapter, prCmdInfo, + TX_RESULT_QUEUE_CLEARANCE); + + nicTxCancelSendingCmd(prAdapter, prCmdInfo); + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + * \param rTxDoneStatus Tx done status + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void wlanReleaseCommand(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + struct TX_CTRL *prTxCtrl; + struct MSDU_INFO *prMsduInfo; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prTxCtrl = &prAdapter->rTxCtrl; + + switch (prCmdInfo->eCmdType) { + case COMMAND_TYPE_GENERAL_IOCTL: + case COMMAND_TYPE_NETWORK_IOCTL: + DBGLOG(INIT, INFO, + "Free CMD: ID[0x%x] SeqNum[%u] OID[%u]\n", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum, + prCmdInfo->fgIsOid); + + if (prCmdInfo->fgIsOid) { + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4SetInfoLen, + WLAN_STATUS_FAILURE); + } + break; + + case COMMAND_TYPE_SECURITY_FRAME: + case COMMAND_TYPE_MANAGEMENT_FRAME: + case COMMAND_TYPE_DATA_FRAME: + prMsduInfo = prCmdInfo->prMsduInfo; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME || + prCmdInfo->eCmdType == COMMAND_TYPE_DATA_FRAME) { + kalSecurityFrameSendComplete(prAdapter->prGlueInfo, + prCmdInfo->prPacket, + WLAN_STATUS_FAILURE); + /* Avoid skb multiple free */ + prMsduInfo->prPacket = NULL; + } + + DBGLOG(INIT, INFO, + "Free %s Frame: B[%u]W:P[%u:%u]TS[%u]STA[%u]RSP[%u]CS[%u]\n", + prCmdInfo->eCmdType == + COMMAND_TYPE_MANAGEMENT_FRAME ? "MGMT" : "DATA/SEC", + prMsduInfo->ucBssIndex, + prMsduInfo->ucWlanIndex, + prMsduInfo->ucPID, + prMsduInfo->ucTxSeqNum, + prMsduInfo->ucStaRecIndex, + prMsduInfo->pfTxDoneHandler ? TRUE : FALSE, + prCmdInfo->ucCmdSeqNum); + + /* invoke callbacks */ + if (prMsduInfo->pfTxDoneHandler != NULL) + prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, + rTxDoneStatus); + + if (prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) + GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum); + + cnmMgtPktFree(prAdapter, prMsduInfo); + break; + + default: + ASSERT(0); + break; + } + +} /* 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 struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr) +{ + struct QUE *prCmdQue; + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue = &rTempCmdQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("wlanReleasePendingOid"); + + ASSERT(prAdapter); + + do { + if (ulParamPtr == 1) + break; + + if (prAdapter->ucOidTimeoutCount >= + WLAN_OID_NO_ACK_THRESHOLD) { + if (!prAdapter->fgIsChipNoAck) { + DBGLOG(INIT, WARN, + "No response from chip for %u times, set NoAck flag!\n", + prAdapter->ucOidTimeoutCount); +#if 0 + glSetRstReason(RST_OID_TIMEOUT); + GL_RESET_TRIGGER(prAdapter, + RST_FLAG_CHIP_RESET); +#endif + } + + if (prAdapter->ucOidTimeoutCount >= + WLAN_OID_NO_ACK_THRESHOLD) { + if (!prAdapter->fgIsChipNoAck) { + DBGLOG(INIT, WARN, + "No response from chip for %u times, set NoAck flag!\n", + prAdapter->ucOidTimeoutCount); + } + + prAdapter->fgIsChipNoAck = TRUE; + } + + prAdapter->u4HifDbgFlag |= DEG_HIF_ALL; + kalSetHifDbgEvent(prAdapter->prGlueInfo); + } + } while (FALSE); + + do { +#if CFG_SUPPORT_MULTITHREAD + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_TX_CMD_CLEAR); +#endif + /* 1: Clear pending OID in glue layer command queue */ + kalOidCmdClearance(prAdapter->prGlueInfo); + +#if CFG_SUPPORT_MULTITHREAD + /* Clear pending OID in main_thread to hif_thread command queue + */ + wlanClearTxOidCommand(prAdapter); +#endif + + /* 2: 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, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + + if (prCmdInfo->fgIsOid) { + DBGLOG(OID, INFO, + "Clear pending OID CMD ID[0x%02X] SEQ[%u] buf[0x%p]\n", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum, + prCmdInfo->pucInfoBuffer); + + if (prCmdInfo->pfCmdTimeoutHandler) { + prCmdInfo->pfCmdTimeoutHandler( + prAdapter, prCmdInfo); + } else { + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + 0, WLAN_STATUS_FAILURE); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_CMD_PENDING); + nicTxCancelSendingCmd(prAdapter, prCmdInfo); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, + SPIN_LOCK_CMD_PENDING); + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } else { + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + + /* 3: Clear pending OID queued in pvOidEntry with REQ_FLAG_OID + * set + */ + kalOidClearance(prAdapter->prGlueInfo); + +#if CFG_SUPPORT_MULTITHREAD + KAL_RELEASE_MUTEX(prAdapter, MUTEX_TX_CMD_CLEAR); +#endif + } while (FALSE); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will search the CMD Queue to look for the pending + * CMD/OID for specific + * NETWORK TYPE and compelete it immediately when system request a reset. + * + * \param prAdapter ointer of Adapter Data Structure + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void wlanReleasePendingCMDbyBssIdx(IN struct ADAPTER + *prAdapter, IN uint8_t ucBssIndex) +{ +#if 0 + struct QUE *prCmdQue; + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue = &rTempCmdQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) 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, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + + DBGLOG(P2P, TRACE, "Pending CMD for BSS:%d\n", + prCmdInfo->ucBssIndex); + + if (prCmdInfo->ucBssIndex == ucBssIndex) { + if (prCmdInfo->pfCmdTimeoutHandler) { + prCmdInfo->pfCmdTimeoutHandler( + prAdapter, prCmdInfo); + } else if (prCmdInfo->fgIsOid) { + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + 0, WLAN_STATUS_FAILURE); + } + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } else { + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + + } while (FALSE); +#endif + + +} /* wlanReleasePendingCMDbyBssIdx */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Return the indicated packet buffer and reallocate one to the RFB + * + * \param prAdapter Pointer of Adapter Data Structure + * \param pvPacket Pointer of returned packet + * + * \retval WLAN_STATUS_SUCCESS: Success + * \retval WLAN_STATUS_FAILURE: Failed + */ +/*----------------------------------------------------------------------------*/ +void wlanReturnPacketDelaySetupTimeout(IN struct ADAPTER + *prAdapter, IN unsigned long ulParamPtr) +{ + struct RX_CTRL *prRxCtrl; + struct SW_RFB *prSwRfb = NULL; + + KAL_SPIN_LOCK_DECLARATION(); + uint32_t status = WLAN_STATUS_SUCCESS; + struct QUE *prQueList; + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + prQueList = &prRxCtrl->rIndicatedRfbList; + DBGLOG(RX, WARN, "%s: IndicatedRfbList num = %u\n", + __func__, prQueList->u4NumElem); + + while (QUEUE_IS_NOT_EMPTY(&prRxCtrl->rIndicatedRfbList)) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rIndicatedRfbList, prSwRfb, + struct SW_RFB *); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + if (prSwRfb) { + status = nicRxSetupRFB(prAdapter, prSwRfb); + nicRxReturnRFB(prAdapter, prSwRfb); + } else { + log_dbg(RX, WARN, "prSwRfb == NULL\n"); + break; + } + + if (status != WLAN_STATUS_SUCCESS) + break; + } + + if (status != WLAN_STATUS_SUCCESS) { + DBGLOG(RX, WARN, "Restart ReturnIndicatedRfb Timer (%u)\n", + RX_RETURN_INDICATED_RFB_TIMEOUT_SEC); + /* restart timer */ + cnmTimerStartTimer(prAdapter, + &prAdapter->rPacketDelaySetupTimer, + SEC_TO_MSEC(RX_RETURN_INDICATED_RFB_TIMEOUT_SEC)); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct ADAPTER *prAdapter, + IN void *pvPacket) +{ + struct RX_CTRL *prRxCtrl; + struct SW_RFB *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)) { + /*Todo:: nothing */ + /*Todo:: nothing */ + } +#endif + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rIndicatedRfbList, prSwRfb, + struct SW_RFB *); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + if (!prSwRfb) { + DBGLOG(RX, WARN, "No free SwRfb!\n"); + return; + } + + if (nicRxSetupRFB(prAdapter, prSwRfb)) { + DBGLOG(RX, WARN, + "Cannot allocate packet buffer for SwRfb!\n"); + if (!timerPendingTimer( + &prAdapter->rPacketDelaySetupTimer)) { + DBGLOG(RX, WARN, + "Start ReturnIndicatedRfb Timer (%u)\n", + RX_RETURN_INDICATED_RFB_TIMEOUT_SEC); + cnmTimerStartTimer(prAdapter, + &prAdapter->rPacketDelaySetupTimer, + SEC_TO_MSEC(RX_RETURN_INDICATED_RFB_TIMEOUT_SEC)); + } + } + 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. + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanQueryInformation(IN struct ADAPTER *prAdapter, + IN PFN_OID_HANDLER_FUNC pfnOidQryHandler, + IN void *pvInfoBuf, IN uint32_t u4InfoBufLen, + OUT uint32_t *pu4QryInfoLen) +{ + uint32_t status = WLAN_STATUS_FAILURE; + + ASSERT(prAdapter); + ASSERT(pu4QryInfoLen); + + /* ignore any OID request after connected, under PS current measurement + * mode + */ + if (prAdapter->u4PsCurrentMeasureEn && + aisGetConnectedBssInfo(prAdapter)) { + /* note: return WLAN_STATUS_FAILURE or + * WLAN_STATUS_SUCCESS for blocking OIDs during current + * measurement ?? + */ + return WLAN_STATUS_SUCCESS; + } +#if 1 + /* most OID handler will just queue a command packet */ + status = pfnOidQryHandler(prAdapter, pvInfoBuf, + u4InfoBufLen, pu4QryInfoLen); +#else + if (wlanIsHandlerNeedHwAccess(pfnOidQryHandler, FALSE)) { + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + /* Reset sleepy state */ + if (prAdapter->fgWiFiInSleepyState == TRUE) + prAdapter->fgWiFiInSleepyState = FALSE; + + status = pfnOidQryHandler(prAdapter, pvInfoBuf, + u4InfoBufLen, pu4QryInfoLen); + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + } else + status = pfnOidQryHandler(prAdapter, pvInfoBuf, + u4InfoBufLen, pu4QryInfoLen); +#endif + + return status; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is a required function that allows bound protocol + * drivers, or NDIS, to request changes in the state information that + * the miniport maintains for particular object identifiers, such as + * changes in multicast addresses. + * + * \param[IN] prAdapter Pointer to the Glue info structure. + * \param[IN] pfnOidSetHandler Points to the OID set handlers. + * \param[IN] pvInfoBuf Points to a buffer containing the OID-specific data + * for the set. + * \param[IN] u4InfoBufLen Specifies the number of bytes at prSetBuffer. + * \param[OUT] pu4SetInfoLen Points to the number of bytes it read or is needed. + * + * \retval WLAN_STATUS_xxx Different WLAN_STATUS code returned by different + * handlers. + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanSetInformation(IN struct ADAPTER *prAdapter, + IN PFN_OID_HANDLER_FUNC pfnOidSetHandler, + IN void *pvInfoBuf, IN uint32_t u4InfoBufLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t status = WLAN_STATUS_FAILURE; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* ignore any OID request after connected, under PS current measurement + * mode + */ + if (prAdapter->u4PsCurrentMeasureEn && + aisGetConnectedBssInfo(prAdapter)) { + /* note: return WLAN_STATUS_FAILURE or WLAN_STATUS_SUCCESS + * for blocking OIDs during current measurement ?? + */ + return WLAN_STATUS_SUCCESS; + } +#if 1 + /* most OID handler will just queue a command packet + * for power state transition OIDs, handler will acquire power control + * by itself + */ + status = pfnOidSetHandler(prAdapter, pvInfoBuf, + u4InfoBufLen, pu4SetInfoLen); +#else + if (wlanIsHandlerNeedHwAccess(pfnOidSetHandler, TRUE)) { + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + /* Reset sleepy state */ + if (prAdapter->fgWiFiInSleepyState == TRUE) + prAdapter->fgWiFiInSleepyState = FALSE; + + status = pfnOidSetHandler(prAdapter, pvInfoBuf, + u4InfoBufLen, pu4SetInfoLen); + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + } else { + status = pfnOidSetHandler(prAdapter, pvInfoBuf, + u4InfoBufLen, pu4SetInfoLen); + } +#endif + + return status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct ADAPTER *prAdapter, + IN u_int8_t 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 struct ADAPTER *prAdapter, + IN u_int8_t fgEnableBroadcast) +{ + ASSERT(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is called to send out CMD_ID_DUMMY command packet + * + * \param[IN] prAdapter Pointer to the Adapter structure. + * + * \return WLAN_STATUS_SUCCESS + * \return WLAN_STATUS_FAILURE + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanSendDummyCmd(IN struct ADAPTER *prAdapter, + IN u_int8_t fgIsReqTxRsrc) +{ + uint32_t status = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + prChipInfo = prAdapter->chip_info; + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + prChipInfo->u2CmdTxHdrSize); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = (uint16_t) prChipInfo->u2CmdTxHdrSize; + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->pfCmdTimeoutHandler = NULL; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_DUMMY_RSV; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->ucCmdSeqNum = 0; + prCmdInfo->u4SetInfoLen = 0; + + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + prCmdInfo->ucCID, + CMD_PACKET_TYPE_ID, + &prCmdInfo->ucCmdSeqNum, + prCmdInfo->fgSetQuery, NULL, FALSE, 0, S2D_INDEX_CMD_H2N); + + if (fgIsReqTxRsrc) { + if (wlanSendCommand(prAdapter, + prCmdInfo) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "Fail to transmit CMD_ID_DUMMY command\n"); + status = WLAN_STATUS_FAILURE; + } + } else { + if (nicTxCmd(prAdapter, prCmdInfo, + TC4_INDEX) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "Fail to transmit CMD_ID_DUMMY command\n"); + status = WLAN_STATUS_FAILURE; + } + } + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanSendNicPowerCtrlCmd(IN struct ADAPTER + *prAdapter, IN uint8_t ucPowerMode) +{ + uint32_t status = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + uint8_t ucTC; + struct CMD_NIC_POWER_CTRL *pNicPwrCtrl; + struct mt66xx_chip_info *prChipInfo; + uint16_t cmd_size; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + prChipInfo = prAdapter->chip_info; + + /* 1. Prepare CMD */ + cmd_size = + prChipInfo->u2CmdTxHdrSize + sizeof(struct CMD_NIC_POWER_CTRL); + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, cmd_size); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); +#if CFG_ENABLE_KEYWORD_EXCEPTION_MECHANISM + mtk_wcn_wmt_assert_keyword(WMTDRV_TYPE_WIFI, + "[Wi-Fi Off] Allocate CMD_INFO_T ==> FAILED."); +#endif + return WLAN_STATUS_FAILURE; + } + + /* 2.2 Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = cmd_size; + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->pfCmdTimeoutHandler = NULL; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_NIC_POWER_CTRL; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->u4SetInfoLen = sizeof(struct CMD_NIC_POWER_CTRL); + + /* 2.3 Setup WIFI_CMD_T */ + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, prCmdInfo->ucCID, + CMD_PACKET_TYPE_ID, + &prCmdInfo->ucCmdSeqNum, + prCmdInfo->fgSetQuery, + &pNicPwrCtrl, FALSE, 0, S2D_INDEX_CMD_H2N); + + kalMemZero(pNicPwrCtrl, sizeof(struct CMD_NIC_POWER_CTRL)); + pNicPwrCtrl->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, + nicTxGetCmdPageCount(prAdapter, prCmdInfo), TRUE) + == 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; + prAdapter->fgIsChipNoAck = TRUE; + break; + } + continue; + } + break; + }; + + /* 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"); +#if CFG_ENABLE_KEYWORD_EXCEPTION_MECHANISM + mtk_wcn_wmt_assert_keyword(WMTDRV_TYPE_WIFI, + "[Wi-Fi Off] Fail to transmit CMD_NIC_POWER_CTRL command"); +#endif + status = WLAN_STATUS_FAILURE; + } + + /* 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) + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wlanIsHandlerAllowedInRFTest(IN PFN_OID_HANDLER_FUNC pfnOidHandler, + IN u_int8_t fgSetInfo) +{ + PFN_OID_HANDLER_FUNC *apfnOidHandlerAllowedInRFTest; + uint32_t i; + uint32_t 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; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to get the chip information + * + * @param prAdapter Pointer to the Adapter structure. + * + * @return + */ +/*----------------------------------------------------------------------------*/ + +uint32_t wlanSetChipEcoInfo(IN struct ADAPTER *prAdapter) +{ + uint32_t hw_version = 0, sw_version = 0; + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + uint32_t chip_id = prChipInfo->chip_id; + /* WLAN_STATUS status; */ + uint32_t u4Status = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanSetChipEcoInfo.\n"); + + if (wlanAccessRegister(prAdapter, + prChipInfo->top_hvr, &hw_version, 0, 0) != + WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "wlanSetChipEcoInfo >> get TOP_HVR failed.\n"); + u4Status = WLAN_STATUS_FAILURE; + } else if (wlanAccessRegister(prAdapter, + prChipInfo->top_fvr, &sw_version, 0, 0) != + WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "wlanSetChipEcoInfo >> get TOP_FVR failed.\n"); + u4Status = WLAN_STATUS_FAILURE; + } else { + /* success */ + nicSetChipHwVer((uint8_t)(GET_HW_VER(hw_version) & 0xFF)); + nicSetChipFactoryVer((uint8_t)((GET_HW_VER(hw_version) >> 8) & + 0xF)); + nicSetChipSwVer((uint8_t)GET_FW_VER(sw_version)); + + /* Assign current chip version */ + prAdapter->chip_info->eco_ver = nicGetChipEcoVer(prAdapter); + } + + DBGLOG(INIT, INFO, + "Chip ID[%04X] Version[E%u] HW[0x%08x] SW[0x%08x]\n", + chip_id, prAdapter->chip_info->eco_ver, hw_version, + sw_version); + + return u4Status; +} + +#if (CFG_ENABLE_FW_DOWNLOAD == 1) +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to read/write a certain N9 + * register by inband command in blocking mode in ROM code stage + * + * @param prAdapter Pointer to the Adapter structure. + * u4DestAddr Address of destination address + * u4ImgSecSize Length of the firmware block + * fgReset should be set to TRUE if this is the 1st configuration + * + * @return WLAN_STATUS_SUCCESS + * WLAN_STATUS_FAILURE + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanAccessRegister(IN struct ADAPTER *prAdapter, + IN uint32_t u4Addr, IN uint32_t *pru4Result, + IN uint32_t u4Data, + IN uint8_t ucSetQuery) +{ + struct mt66xx_chip_info *prChipInfo; + struct CMD_INFO *prCmdInfo; + struct INIT_WIFI_EVENT *prInitEvent; + struct INIT_CMD_ACCESS_REG *prInitCmdAccessReg; + struct INIT_EVENT_ACCESS_REG *prInitEventAccessReg; + uint8_t ucTC, ucCmdSeqNum; + uint16_t cmd_size; + uint8_t *aucBuffer; + uint32_t u4EventSize; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + DEBUGFUNC("wlanAccessRegister"); + + /* 1. Allocate CMD Info Packet and its Buffer. */ + cmd_size = sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES) + + sizeof(struct INIT_CMD_ACCESS_REG); + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, cmd_size); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + u4EventSize = prChipInfo->init_evt_rxd_size + + prChipInfo->init_event_size + + sizeof(struct INIT_EVENT_ACCESS_REG); + aucBuffer = kalMemAlloc(u4EventSize, PHY_MEM_TYPE); + if (!aucBuffer) { + log_dbg(INIT, ERROR, "memory not enough for aucBuffer\n"); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + return WLAN_STATUS_FAILURE; + } + + prCmdInfo->u2InfoBufLen = cmd_size; + +#if (CFG_USE_TC4_RESOURCE_FOR_INIT_CMD == 1) + /* 2. Use TC4's resource to download image. (TC4 as CPU) */ + ucTC = TC4_INDEX; +#else + /* 2. Use TC0's resource to download image. + * Only TC0 is allowed because SDIO HW always reports + * MCU's TXQ_CNT at TXQ0_CNT in CR4 architecutre) + */ + ucTC = TC0_INDEX; +#endif + + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + INIT_CMD_ID_ACCESS_REG, + INIT_CMD_PACKET_TYPE_ID, + &ucCmdSeqNum, + FALSE, + (void **)&prInitCmdAccessReg, + TRUE, 0, S2D_INDEX_CMD_H2N); + + /* 5. Setup CMD_ACCESS_REG */ + prInitCmdAccessReg->ucSetQuery = ucSetQuery; + prInitCmdAccessReg->u4Address = u4Addr; + prInitCmdAccessReg->u4Data = u4Data; + + /* 6. Send CMD_ACCESS_REG command */ + while (1) { + /* 6.1 Acquire TX Resource */ + if (nicTxAcquireResource + (prAdapter, ucTC, nicTxGetPageCount(prAdapter, + prCmdInfo->u2InfoBufLen, TRUE), TRUE) + == 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"); + goto exit; + } + continue; + } + + /* 6.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo, + prChipInfo->u2TxInitCmdPort) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "Fail to transmit image download command\n"); + goto exit; + } + + break; + }; + + /* 7. Wait for INIT_EVENT_ID_CMD_RESULT */ + u4Status = wlanAccessRegisterStatus(prAdapter, ucCmdSeqNum, ucSetQuery, + aucBuffer, u4EventSize); + if (ucSetQuery == 0) { + prInitEvent = (struct INIT_WIFI_EVENT *) + (aucBuffer + prChipInfo->init_evt_rxd_size); + prInitEventAccessReg = (struct INIT_EVENT_ACCESS_REG *) + prInitEvent->aucBuffer; + + if (!prInitEventAccessReg) { + DBGLOG(INIT, ERROR, + "prInitEventAccessReg == NULL\n"); + u4Status = WLAN_STATUS_FAILURE; + goto exit; + } + + if (prInitEventAccessReg->u4Address != u4Addr) { + DBGLOG(INIT, ERROR, + "Event reports address incorrect. 0x%08x, 0x%08x.\n", + u4Addr, prInitEventAccessReg->u4Address); + u4Status = WLAN_STATUS_FAILURE; + } + *pru4Result = prInitEventAccessReg->u4Data; + } + +exit: + /* 8. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to get the response of INIT_CMD_ACCESS_REG +* +* @param prAdapter Pointer to the Adapter structure. +* ucCmdSeqNum Sequence number of previous firmware scatter +* ucSetQuery Read or write +* prEvent the pointer of buffer to store the response +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +uint32_t wlanAccessRegisterStatus(IN struct ADAPTER *prAdapter, + IN uint8_t ucCmdSeqNum, + IN uint8_t ucSetQuery, IN void *prEvent, + IN uint32_t u4EventLen) +{ + struct mt66xx_chip_info *prChipInfo; + struct INIT_WIFI_EVENT *prInitEvent; + uint32_t u4RxPktLength; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + uint8_t ucPortIdx = IMG_DL_STATUS_PORT_IDX; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + do { + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + } else if (nicRxWaitResponse(prAdapter, ucPortIdx, prEvent, + u4EventLen, &u4RxPktLength) != WLAN_STATUS_SUCCESS) { + GL_RESET_TRIGGER(prAdapter, + RST_FLAG_DO_CORE_DUMP | + RST_FLAG_PREVENT_POWER_OFF); + u4Status = WLAN_STATUS_FAILURE; + } else { + prInitEvent = (struct INIT_WIFI_EVENT *) + (prEvent + prChipInfo->init_evt_rxd_size); + + /* EID / SeqNum check */ + if (((prInitEvent->ucEID != INIT_EVENT_ID_CMD_RESULT) && + (ucSetQuery == 1)) || + ((prInitEvent->ucEID != INIT_EVENT_ID_ACCESS_REG) + && (ucSetQuery == 0))) { + GL_RESET_TRIGGER(prAdapter, + RST_FLAG_DO_CORE_DUMP | + RST_FLAG_PREVENT_POWER_OFF); + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "wlanAccessRegisterStatus: incorrect ucEID. ucSetQuery = 0x%x\n", + ucSetQuery); + } else if (prInitEvent->ucSeqNum != ucCmdSeqNum) { + u4Status = WLAN_STATUS_FAILURE; + GL_RESET_TRIGGER(prAdapter, + RST_FLAG_DO_CORE_DUMP | + RST_FLAG_PREVENT_POWER_OFF); + DBGLOG(INIT, ERROR, + "wlanAccessRegisterStatus: incorrect ucCmdSeqNum. = 0x%x\n", + ucCmdSeqNum); + } else { + } + } + } while (FALSE); + + return u4Status; +} +#endif /* CFG_ENABLE_FW_DOWNLOAD == 1 */ + +/*----------------------------------------------------------------------------*/ +/*! + * @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) + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanProcessQueuedSwRfb(IN struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfbListHead) +{ + struct SW_RFB *prSwRfb, *prNextSwRfb; + struct TX_CTRL *prTxCtrl; + struct RX_CTRL *prRxCtrl; + struct STA_RECORD *prStaRec; + + ASSERT(prAdapter); + ASSERT(prSwRfbListHead); + + prTxCtrl = &prAdapter->rTxCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + + prSwRfb = prSwRfbListHead; + + do { + /* save next first */ + prNextSwRfb = (struct SW_RFB *) QUEUE_GET_NEXT_ENTRY(( + struct QUE_ENTRY *) prSwRfb); + + switch (prSwRfb->eDst) { + case RX_PKT_DESTINATION_HOST: + prStaRec = cnmGetStaRecByIndex(prAdapter, + prSwRfb->ucStaRecIdx); + if (prStaRec && IS_STA_IN_AIS(prStaRec)) { +#if ARP_MONITER_ENABLE + qmHandleRxArpPackets(prAdapter, prSwRfb); +#endif + } + + 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) + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanProcessQueuedMsduInfo(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wlanoidTimeoutCheck(IN struct ADAPTER *prAdapter, + IN PFN_OID_HANDLER_FUNC pfnOidHandler) +{ + PFN_OID_HANDLER_FUNC *apfnOidHandlerWOTimeoutCheck; + uint32_t i; + uint32_t u4NumOfElem; + uint32_t u4OidTimeout; + + apfnOidHandlerWOTimeoutCheck = apfnOidWOTimeoutCheck; + u4NumOfElem = sizeof(apfnOidWOTimeoutCheck) / sizeof( + PFN_OID_HANDLER_FUNC); + + for (i = 0; i < u4NumOfElem; i++) { + if (apfnOidHandlerWOTimeoutCheck[i] == pfnOidHandler) + return FALSE; + } + + /* Decrease OID timeout threshold if chip NoAck/resetting */ + if (wlanIsChipNoAck(prAdapter)) { + u4OidTimeout = WLAN_OID_TIMEOUT_THRESHOLD_IN_RESETTING; + DBGLOG(INIT, INFO, + "Decrease OID timeout to %ums due to NoACK/CHIP-RESET\n", + u4OidTimeout); + } else { + u4OidTimeout = WLAN_OID_TIMEOUT_THRESHOLD; + } + + /* Set OID timer for timeout check */ + cnmTimerStartTimer(prAdapter, + &(prAdapter->rOidTimeoutTimer), u4OidTimeout); + + 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 struct ADAPTER *prAdapter) +{ + ASSERT(prAdapter); + + cnmTimerStopTimer(prAdapter, &(prAdapter->rOidTimeoutTimer)); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to override network address + * if NVRAM has a valid value + * + * @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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanUpdateNetworkAddress(IN struct ADAPTER + *prAdapter) +{ + const uint8_t aucZeroMacAddr[] = NULL_MAC_ADDR; + uint8_t rMacAddr[PARAM_MAC_ADDR_LEN]; + uint32_t u4SysTime; + + DEBUGFUNC("wlanUpdateNetworkAddress"); + + ASSERT(prAdapter); + + if (kalRetrieveNetworkAddress(prAdapter->prGlueInfo, rMacAddr) == FALSE + || IS_BMCAST_MAC_ADDR(rMacAddr) + || EQUAL_MAC_ADDR(aucZeroMacAddr, rMacAddr)) { + /* eFUSE has a valid address, don't do anything */ + if (prAdapter->fgIsEmbbededMacAddrValid == TRUE) { +#if CFG_SHOW_MACADDR_SOURCE + DBGLOG(INIT, INFO, "Using embedded MAC address"); +#endif + return WLAN_STATUS_SUCCESS; + } +#if CFG_SHOW_MACADDR_SOURCE + DBGLOG(INIT, INFO, + "Using dynamically generated MAC address"); +#endif + /* dynamic generate */ + u4SysTime = (uint32_t) 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 + } + +#if WLAN_INCLUDE_SYS + sysMacAddrOverride(rMacAddr); +#endif + + COPY_MAC_ADDR(prAdapter->rWifiVar.aucMacAddress, rMacAddr); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to update basic configuration into 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanUpdateBasicConfig(IN struct ADAPTER *prAdapter) +{ + struct CMD_INFO *prCmdInfo; + struct CMD_BASIC_CONFIG *prCmdBasicConfig; + uint32_t rResult; + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; + struct mt66xx_chip_info *prChipInfo; + uint16_t cmd_size; + + DEBUGFUNC("wlanUpdateBasicConfig"); + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + cmd_size = prChipInfo->u2CmdTxHdrSize + sizeof(struct CMD_BASIC_CONFIG); + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, cmd_size); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* compose CMD_BUILD_CONNECTION cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = cmd_size; + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->pfCmdTimeoutHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_BASIC_CONFIG; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->u4SetInfoLen = sizeof(struct CMD_BASIC_CONFIG); + + /* Setup WIFI_CMD_T */ + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + prCmdInfo->ucCID, + CMD_PACKET_TYPE_ID, + &prCmdInfo->ucCmdSeqNum, + prCmdInfo->fgSetQuery, + &prCmdBasicConfig, FALSE, 0, S2D_INDEX_CMD_H2N); + + /* configure CMD_BASIC_CONFIG */ + kalMemZero(prCmdBasicConfig, + sizeof(struct CMD_BASIC_CONFIG)); + prCmdBasicConfig->ucNative80211 = 0; + prCmdBasicConfig->rCsumOffload.u2RxChecksum = 0; + prCmdBasicConfig->rCsumOffload.u2TxChecksum = 0; + prCmdBasicConfig->ucCtrlFlagAssertPath = + prWifiVar->ucCtrlFlagAssertPath; + prCmdBasicConfig->ucCtrlFlagDebugLevel = + prWifiVar->ucCtrlFlagDebugLevel; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + if (prAdapter->fgIsSupportCsumOffload) { + 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 + + rResult = wlanSendCommand(prAdapter, prCmdInfo); + + if (rResult != WLAN_STATUS_SUCCESS) { + kalEnqueueCommand(prAdapter->prGlueInfo, + (struct QUE_ENTRY *) prCmdInfo); + + return WLAN_STATUS_PENDING; + } + 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wlanQueryTestMode(IN struct ADAPTER *prAdapter) +{ + ASSERT(prAdapter); + + return prAdapter->fgTestMode; +} + +u_int8_t wlanProcessTxFrame(IN struct ADAPTER *prAdapter, + IN void *prPacket) +{ + uint32_t u4SysTime; + uint8_t ucMacHeaderLen; + struct TX_PACKET_INFO rTxPacketInfo; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + ASSERT(prPacket); + prChipInfo = prAdapter->chip_info; + + if (kalQoSFrameClassifierAndPacketInfo( + prAdapter->prGlueInfo, prPacket, &rTxPacketInfo)) { + + /* Save the value of Priority Parameter */ + GLUE_SET_PKT_TID(prPacket, rTxPacketInfo.ucPriorityParam); + + if (rTxPacketInfo.u2Flag) { + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_1X)) { + struct STA_RECORD *prStaRec; + + DBGLOG(RSN, INFO, "T1X len=%d\n", + rTxPacketInfo.u4PacketLen); + + prStaRec = cnmGetStaRecByAddress(prAdapter, + GLUE_GET_PKT_BSS_IDX(prPacket), + rTxPacketInfo.aucEthDestAddr); + + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_1X); + /* + * if (secIsProtected1xFrame(prAdapter, + * prStaRec) && + * !kalIs24Of4Packet(prPacket)) + * GLUE_SET_PKT_FLAG(prPacket, + * ENUM_PKT_PROTECTED_1X); + */ + } + + if (rTxPacketInfo.u2Flag & + BIT(ENUM_PKT_NON_PROTECTED_1X)) + GLUE_SET_PKT_FLAG(prPacket, + ENUM_PKT_NON_PROTECTED_1X); + + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_802_3)) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_802_3); + + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_VLAN_EXIST) + && FEAT_SUP_LLC_VLAN_TX(prChipInfo)) + GLUE_SET_PKT_FLAG(prPacket, + ENUM_PKT_VLAN_EXIST); + + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_DHCP)) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_DHCP); + + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_ARP)) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_ARP); + + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_ICMP)) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_ICMP); + + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_TDLS)) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_TDLS); + + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_DNS)) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_DNS); + + } + + ucMacHeaderLen = ETHER_HEADER_LEN; + + /* 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, + (uint16_t) rTxPacketInfo.u4PacketLen); + + /* Save the value of Arrival Time */ + u4SysTime = (OS_SYSTIME) kalGetTimeTick(); + GLUE_SET_PKT_ARRIVAL_TIME(prPacket, u4SysTime); + + return TRUE; + } + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wlanProcessSecurityFrame(IN struct ADAPTER + *prAdapter, IN void *prPacket) +{ + struct CMD_INFO *prCmdInfo; + struct STA_RECORD *prStaRec; + uint8_t ucBssIndex; + uint32_t u4PacketLen; + uint8_t aucEthDestAddr[PARAM_MAC_ADDR_LEN]; + struct MSDU_INFO *prMsduInfo; + uint8_t ucStaRecIndex; + + ASSERT(prAdapter); + ASSERT(prPacket); + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, 0); + + /* Get MSDU_INFO for TxDone */ + prMsduInfo = cnmPktAlloc(prAdapter, 0); + + u4PacketLen = (uint32_t) GLUE_GET_PKT_FRAME_LEN(prPacket); + + if (prCmdInfo && prMsduInfo) { + ucBssIndex = GLUE_GET_PKT_BSS_IDX(prPacket); + + kalGetEthDestAddr(prAdapter->prGlueInfo, prPacket, + aucEthDestAddr); + + prStaRec = cnmGetStaRecByAddress(prAdapter, ucBssIndex, + aucEthDestAddr); + + prCmdInfo->eCmdType = COMMAND_TYPE_SECURITY_FRAME; + prCmdInfo->u2InfoBufLen = (uint16_t) u4PacketLen; + prCmdInfo->prPacket = prPacket; + prCmdInfo->prMsduInfo = prMsduInfo; + prCmdInfo->pfCmdDoneHandler = wlanSecurityFrameTxDone; + prCmdInfo->pfCmdTimeoutHandler = + wlanSecurityAndCmdDataFrameTxTimeout; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + + if (prStaRec) + ucStaRecIndex = prStaRec->ucIndex; + else + ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; + + /* Fill-up MSDU_INFO */ + nicTxSetDataPacket(prAdapter, prMsduInfo, ucBssIndex, + ucStaRecIndex, 0, u4PacketLen, + nicTxDummyTxDone, MSDU_RATE_MODE_AUTO, + TX_PACKET_OS, 0, FALSE, TRUE); + + prMsduInfo->prPacket = prPacket; + /* No Tx descriptor template for MMPDU */ + prMsduInfo->fgIsTXDTemplateValid = FALSE; + + if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_PROTECTED_1X)) + nicTxConfigPktOption(prMsduInfo, + MSDU_OPT_PROTECTED_FRAME, TRUE); +#if CFG_SUPPORT_MULTITHREAD + nicTxComposeSecurityFrameDesc(prAdapter, prCmdInfo, + prMsduInfo->aucTxDescBuffer, NULL); +#endif + + kalEnqueueCommand(prAdapter->prGlueInfo, + (struct QUE_ENTRY *) prCmdInfo); + + GLUE_SET_EVENT(prAdapter->prGlueInfo); + + return TRUE; + } + DBGLOG(RSN, INFO, + "Failed to alloc CMD/MGMT INFO for 1X frame!!\n"); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + cnmPktFree(prAdapter, prMsduInfo); + + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to send data frame via firmware and queued + * into command queue + * + * @param prAdapter Pointer of Adapter Data Structure + * @param prPacket Pointer of native packet + * + * @return TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanProcessCmdDataFrame(IN struct ADAPTER + *prAdapter, IN void *prPacket) +{ + struct CMD_INFO *prCmdInfo; + struct MSDU_INFO *prMsduInfo; + + ASSERT(prAdapter); + ASSERT(prPacket); + + /* Allocate command buffer */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, 0); + if (!prCmdInfo) { + DBGLOG_LIMITED(TX, INFO, + "Failed to alloc CMD buffer for data frame!!\n"); + return WLAN_STATUS_RESOURCES; + } + + /* Get MSDU_INFO buffer */ + prMsduInfo = cnmPktAlloc(prAdapter, 0); + if (!prMsduInfo) { + DBGLOG_LIMITED(TX, INFO, + "Failed to alloc MSDU Info for data frame!!\n"); + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + return WLAN_STATUS_RESOURCES; + } + + /* Fill-up MSDU_INFO and TxD*/ + if (!nicTxFillMsduInfo(prAdapter, prMsduInfo, prPacket) || + !nicTxProcessCmdDataPacket(prAdapter, prMsduInfo)) { + + kalSendComplete(prAdapter->prGlueInfo, prPacket, + WLAN_STATUS_INVALID_PACKET); + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + cnmPktFree(prAdapter, prMsduInfo); + + return WLAN_STATUS_INVALID_PACKET; + } + + /* Prepare command and enqueue */ + prCmdInfo->eCmdType = COMMAND_TYPE_DATA_FRAME; + prCmdInfo->u2InfoBufLen = prMsduInfo->u2FrameLength; + prCmdInfo->pucInfoBuffer = NULL; + prCmdInfo->prPacket = prMsduInfo->prPacket; + prCmdInfo->prMsduInfo = prMsduInfo; + prCmdInfo->pfCmdDoneHandler = wlanCmdDataFrameTxDone; + prCmdInfo->pfCmdTimeoutHandler = wlanSecurityAndCmdDataFrameTxTimeout; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->ucCmdSeqNum = prMsduInfo->ucTxSeqNum; + + DBGLOG(TX, INFO, + "DPP EN-Q MSDU[0x%p] SEQ[%u] BSS[%u] STA[%u] Len[%u]to CMD Q\n", + prMsduInfo, + prMsduInfo->ucTxSeqNum, + prMsduInfo->ucBssIndex, + prMsduInfo->ucStaRecIndex, + prMsduInfo->u2FrameLength); + + kalEnqueueCommand(prAdapter->prGlueInfo, + (struct QUE_ENTRY *) prCmdInfo); + + GLUE_SET_EVENT(prAdapter->prGlueInfo); + + return WLAN_STATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + struct MSDU_INFO *prMsduInfo = prCmdInfo->prMsduInfo; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (GET_BSS_INFO_BY_INDEX(prAdapter, + prMsduInfo->ucBssIndex)->eNetworkType == + NETWORK_TYPE_AIS + && + aisGetAisSpecBssInfo(prAdapter, + prMsduInfo->ucBssIndex)->fgCounterMeasure) { + struct STA_RECORD *prSta = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucBssIndex); + + if (prSta) { + kalMsleep(10); + if (authSendDeauthFrame(prAdapter, + GET_BSS_INFO_BY_INDEX(prAdapter, + prMsduInfo->ucBssIndex), prSta, + (struct SW_RFB *) NULL, + REASON_CODE_MIC_FAILURE, + (PFN_TX_DONE_HANDLER) NULL + /* secFsmEventDeauthTxDone left upper + * layer handle the 60 timer + */ + ) != WLAN_STATUS_SUCCESS) { + ASSERT(FALSE); + } + /* secFsmEventEapolTxDone(prAdapter, prSta, + * TX_RESULT_SUCCESS); + */ + } + } + + kalSecurityFrameSendComplete(prAdapter->prGlueInfo, + prCmdInfo->prPacket, WLAN_STATUS_SUCCESS); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called when command data frame 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 wlanCmdDataFrameTxDone(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + 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 wlanSecurityAndCmdDataFrameTxTimeout(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *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 struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + u_int8_t fgKeepCurrOne = FALSE; + uint32_t i; + struct WLAN_INFO *prWlanInfo; + struct PARAM_BSSID_EX *prCurrBssid; + + ASSERT(prAdapter); + prWlanInfo = &(prAdapter->rWlanInfo); + + prCurrBssid = aisGetCurrBssId(prAdapter, + ucBssIndex); + + /* clear scanning result */ + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo, + ucBssIndex) == + MEDIA_STATE_CONNECTED) { + + for (i = 0; i < prWlanInfo->u4ScanResultNum; i++) { + + if (EQUAL_MAC_ADDR( + prCurrBssid->arMacAddress, + prWlanInfo->arScanResult[i].arMacAddress)) { + fgKeepCurrOne = TRUE; + + if (i != 0) { + /* copy structure */ + kalMemCopy( + &(prWlanInfo->arScanResult[0]), + &(prWlanInfo->arScanResult[i]), + OFFSET_OF(struct PARAM_BSSID_EX, + aucIEs)); + } + + if (prWlanInfo->arScanResult[i].u4IELength > 0) { + if (prWlanInfo->apucScanResultIEs[i] != + &(prWlanInfo->aucScanIEBuf[0])) { + + /* move IEs to head */ + kalMemCopy(prWlanInfo->aucScanIEBuf, + prWlanInfo->apucScanResultIEs[i], + prWlanInfo->arScanResult[i] + .u4IELength); + } + + /* modify IE pointer */ + prWlanInfo->apucScanResultIEs[0] = + &(prWlanInfo->aucScanIEBuf[0]); + + } else { + prWlanInfo->apucScanResultIEs[0] = NULL; + } + + break; + } /* if */ + } /* for */ + } + + if (fgKeepCurrOne == TRUE) { + prWlanInfo->u4ScanResultNum = 1; + prWlanInfo->u4ScanIEBufferUsage = + ALIGN_4(prWlanInfo->arScanResult[0].u4IELength); + } else { + prWlanInfo->u4ScanResultNum = 0; + prWlanInfo->u4ScanIEBufferUsage = 0; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called when AIS received a beacon timeout event + * + * @param prAdapter Pointer of Adapter Data Structure + * @param arBSSID MAC address of the specified BSS + * + * @return none + */ +/*----------------------------------------------------------------------------*/ +void wlanClearBssInScanningResult(IN struct ADAPTER + *prAdapter, IN uint8_t *arBSSID) +{ + uint32_t i, j, u4IELength = 0, u4IEMoveLength; + uint8_t *pucIEPtr; + struct WLAN_INFO *prWlanInfo; + + ASSERT(prAdapter); + prWlanInfo = &(prAdapter->rWlanInfo); + + /* clear scanning result */ + i = 0; + while (1) { + if (i >= prWlanInfo->u4ScanResultNum) + break; + + if (EQUAL_MAC_ADDR(arBSSID, + prWlanInfo->arScanResult[i].arMacAddress)) { + /* backup current IE length */ + u4IELength = + ALIGN_4(prWlanInfo->arScanResult[i].u4IELength); + pucIEPtr = prWlanInfo->apucScanResultIEs[i]; + + /* removed from middle */ + for (j = i + 1; j < prWlanInfo->u4ScanResultNum; j++) { + kalMemCopy(&(prWlanInfo->arScanResult[j - 1]), + &(prWlanInfo->arScanResult[j]), + OFFSET_OF(struct PARAM_BSSID_EX, + aucIEs)); + + prWlanInfo->apucScanResultIEs[j - 1] = + prWlanInfo->apucScanResultIEs[j]; + } + + prWlanInfo->u4ScanResultNum--; + + /* remove IE buffer if needed := move rest of IE buffer + */ + if (u4IELength > 0) { + u4IEMoveLength = prWlanInfo->u4ScanIEBufferUsage + - (((unsigned long) pucIEPtr) + + u4IELength + - ((unsigned long) + (&(prWlanInfo->aucScanIEBuf[0])))); + + kalMemCopy(pucIEPtr, + (uint8_t *) (((unsigned long) + pucIEPtr) + u4IELength), + u4IEMoveLength); + + prWlanInfo->u4ScanIEBufferUsage -= + u4IELength; + + /* correction of pointers to IE buffer */ + for (j = 0; j < prWlanInfo->u4ScanResultNum; + j++) { + if (prWlanInfo->apucScanResultIEs[j] > + pucIEPtr) { + prWlanInfo->apucScanResultIEs[j] = + (uint8_t *)((unsigned long) + (prWlanInfo->apucScanResultIEs[j]) - + u4IELength); + } + } + } + } + + i++; + } +} + +#if CFG_TEST_WIFI_DIRECT_GO +void wlanEnableP2pFunction(IN struct ADAPTER *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, + (struct MSG_HDR *) prMsgFuncSwitch, MSG_SEND_METHOD_BUF); +#endif + +} + +void wlanEnableATGO(IN struct ADAPTER *prAdapter) +{ + + struct MSG_P2P_CONNECTION_REQUEST *prMsgConnReq = + (struct MSG_P2P_CONNECTION_REQUEST *) NULL; + uint8_t aucTargetDeviceID[MAC_ADDR_LEN] = { 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF }; + + prMsgConnReq = + (struct MSG_P2P_CONNECTION_REQUEST *) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(struct MSG_P2P_CONNECTION_REQUEST)); + 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, + (struct MSG_HDR *) prMsgConnReq, MSG_SEND_METHOD_BUF); + +} +#endif + +void wlanPrintVersion(IN struct ADAPTER *prAdapter) +{ + uint8_t aucBuf[512]; + + kalMemZero(aucBuf, 512); + +#if CFG_ENABLE_FW_DOWNLOAD + fwDlGetFwdlInfo(prAdapter, aucBuf, 512); +#endif + DBGLOG(SW4, INFO, "%s", aucBuf); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanQueryNicCapability(IN struct ADAPTER + *prAdapter) +{ + struct mt66xx_chip_info *prChipInfo; + uint8_t aucZeroMacAddr[] = NULL_MAC_ADDR; + struct CMD_INFO *prCmdInfo; + uint32_t u4RxPktLength; + uint8_t *aucBuffer; + uint32_t u4EventSize; + struct WIFI_EVENT *prEvent; + struct EVENT_NIC_CAPABILITY *prEventNicCapability; + uint16_t cmd_size; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + DEBUGFUNC("wlanQueryNicCapability"); + + /* 1. Allocate CMD Info Packet and its Buffer */ + cmd_size = prChipInfo->u2CmdTxHdrSize + + sizeof(struct EVENT_NIC_CAPABILITY); + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, cmd_size); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + u4EventSize = prChipInfo->rxd_size + prChipInfo->event_hdr_size + + sizeof(struct EVENT_NIC_CAPABILITY); + aucBuffer = kalMemAlloc(u4EventSize, PHY_MEM_TYPE); + if (!aucBuffer) { + DBGLOG(INIT, ERROR, "Not enough memory for aucBuffer\n"); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + return WLAN_STATUS_FAILURE; + } + + /* compose CMD_BUILD_CONNECTION cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = cmd_size; + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_GET_NIC_CAPABILITY; + prCmdInfo->fgSetQuery = FALSE; + prCmdInfo->fgNeedResp = TRUE; + prCmdInfo->u4SetInfoLen = 0; + + /* Setup WIFI_CMD_T */ + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + prCmdInfo->ucCID, + CMD_PACKET_TYPE_ID, + &prCmdInfo->ucCmdSeqNum, + prCmdInfo->fgSetQuery, + NULL, FALSE, 0, S2D_INDEX_CMD_H2N); + + wlanSendCommand(prAdapter, prCmdInfo); + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + while (TRUE) { + if (nicRxWaitResponse(prAdapter, 1, aucBuffer, u4EventSize, + &u4RxPktLength) != WLAN_STATUS_SUCCESS) { + + DBGLOG(INIT, WARN, "%s: wait for event failed!\n", + __func__); + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + return WLAN_STATUS_FAILURE; + } + /* header checking .. */ + if (NIC_RX_GET_U2_SW_PKT_TYPE(aucBuffer) + != prChipInfo->u2RxSwPktEvent) { + DBGLOG(INIT, WARN, + "%s: skip unexpected Rx pkt type[0x%04x]\n", + __func__, NIC_RX_GET_U2_SW_PKT_TYPE(aucBuffer)); + continue; + } + + prEvent = (struct WIFI_EVENT *) + (aucBuffer + prChipInfo->rxd_size); + prEventNicCapability = + (struct EVENT_NIC_CAPABILITY *)prEvent->aucBuffer; + + if (prEvent->ucEID != EVENT_ID_NIC_CAPABILITY) { + DBGLOG(INIT, WARN, + "%s: skip unexpected event ID[0x%02x]\n", + __func__, prEvent->ucEID); + continue; + } else { + break; + } + } + + prEventNicCapability = (struct EVENT_NIC_CAPABILITY *) ( + prEvent->aucBuffer); + + prAdapter->rVerInfo.u2FwProductID = + prEventNicCapability->u2ProductID; + kalMemCopy(prAdapter->rVerInfo.aucFwBranchInfo, + prEventNicCapability->aucBranchInfo, 4); + prAdapter->rVerInfo.u2FwOwnVersion = + prEventNicCapability->u2FwVersion; + prAdapter->rVerInfo.ucFwBuildNumber = + prEventNicCapability->ucFwBuildNumber; + kalMemCopy(prAdapter->rVerInfo.aucFwDateCode, + prEventNicCapability->aucDateCode, 16); + prAdapter->rVerInfo.u2FwPeerVersion = + prEventNicCapability->u2DriverVersion; + prAdapter->fgIsHw5GBandDisabled = + (u_int8_t)prEventNicCapability->ucHw5GBandDisabled; + prAdapter->fgIsEepromUsed = + (u_int8_t)prEventNicCapability->ucEepromUsed; + prAdapter->fgIsEmbbededMacAddrValid = + (u_int8_t)(!IS_BMCAST_MAC_ADDR( + prEventNicCapability->aucMacAddr) && + !EQUAL_MAC_ADDR(aucZeroMacAddr, + prEventNicCapability->aucMacAddr)); + + COPY_MAC_ADDR(prAdapter->rWifiVar.aucPermanentAddress, + prEventNicCapability->aucMacAddr); + COPY_MAC_ADDR(prAdapter->rWifiVar.aucMacAddress, + prEventNicCapability->aucMacAddr); + + prAdapter->rWifiVar.ucStaVht &= + (!(prEventNicCapability->ucHwNotSupportAC)); + prAdapter->rWifiVar.ucApVht &= + (!(prEventNicCapability->ucHwNotSupportAC)); + prAdapter->rWifiVar.ucP2pGoVht &= + (!(prEventNicCapability->ucHwNotSupportAC)); + prAdapter->rWifiVar.ucP2pGcVht &= + (!(prEventNicCapability->ucHwNotSupportAC)); + prAdapter->rWifiVar.ucHwNotSupportAC = + prEventNicCapability->ucHwNotSupportAC; + + prAdapter->u4FwCompileFlag0 = + prEventNicCapability->u4CompileFlag0; + prAdapter->u4FwCompileFlag1 = + prEventNicCapability->u4CompileFlag1; + prAdapter->u4FwFeatureFlag0 = + prEventNicCapability->u4FeatureFlag0; + prAdapter->u4FwFeatureFlag1 = + prEventNicCapability->u4FeatureFlag1; + + if (prEventNicCapability->ucHwSetNss1x1) + prAdapter->rWifiVar.ucNSS = 1; + +#if CFG_SUPPORT_DBDC + if (prEventNicCapability->ucHwNotSupportDBDC) + prAdapter->rWifiVar.eDbdcMode = ENUM_DBDC_MODE_DISABLED; +#endif + if (prEventNicCapability->ucHwBssIdNum > 0 + && prEventNicCapability->ucHwBssIdNum <= MAX_BSSID_NUM) { + prAdapter->ucHwBssIdNum = + prEventNicCapability->ucHwBssIdNum; + prAdapter->ucP2PDevBssIdx = prAdapter->ucHwBssIdNum; + /* v1 event does not report WmmSetNum, + * Assume it is the same as HwBssNum + */ + prAdapter->ucWmmSetNum = + prEventNicCapability->ucHwBssIdNum; + prAdapter->aprBssInfo[prAdapter->ucP2PDevBssIdx] = + &prAdapter->rWifiVar.rP2pDevInfo; + } + +#if CFG_ENABLE_CAL_LOG + DBGLOG(INIT, TRACE, + "RF CAL FAIL = (%d),BB CAL FAIL = (%d)\n", + prEventNicCapability->ucRfCalFail, + prEventNicCapability->ucBbCalFail); +#endif + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + + return WLAN_STATUS_SUCCESS; +} + +#if TXPWR_USE_PDSLOPE + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param prAdapter Pointer of Adapter Data Structure + * + * @return WLAN_STATUS_SUCCESS + * WLAN_STATUS_FAILURE + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanQueryPdMcr(IN struct ADAPTER *prAdapter, + struct PARAM_MCR_RW_STRUCT *prMcrRdInfo) +{ + struct mt66xx_chip_info *prChipInfo; + struct CMD_INFO *prCmdInfo; + uint32_t u4RxPktLength; + uint8_t *aucBuffer; + uint32_t u4EventSize; + struct WIFI_EVENT *prEvent; + struct CMD_ACCESS_REG *prCmdMcrQuery; + uint16_t u2PacketType; + uint16_t cmd_size; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + /* 1. Allocate CMD Info Packet and its Buffer */ + cmd_size = prChipInfo->u2CmdTxHdrSize + sizeof(struct CMD_ACCESS_REG); + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, cmd_size); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + u4EventSize = prChipInfo->rxd_size + prChipInfo->event_hdr_size + + struct CMD_ACCESS_REG; + aucBuffer = kalMemAlloc(u4EventSize, PHY_MEM_TYPE); + + /* compose CMD_BUILD_CONNECTION cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = cmd_size; + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_ACCESS_REG; + prCmdInfo->fgSetQuery = FALSE; + prCmdInfo->fgNeedResp = TRUE; + prCmdInfo->u4SetInfoLen = sizeof(struct CMD_ACCESS_REG); + + /* Setup WIFI_CMD_T */ + NIC_FILL_CMD_TX_HDR( + prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + prCmdInfo->ucCID, + CMD_PACKET_TYPE_ID, + &prCmdInfo->ucCmdSeqNum, + prCmdInfo->fgSetQuery, + &prCmdMcrQuery, FALSE, 0, S2D_INDEX_CMD_H2N); + kalMemCopy(prCmdMcrQuery, prMcrRdInfo, + sizeof(struct CMD_ACCESS_REG)); + + wlanSendCommand(prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + if (nicRxWaitResponse(prAdapter, 1, aucBuffer, u4EventSize, + &u4RxPktLength) != WLAN_STATUS_SUCCESS) { + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + return WLAN_STATUS_FAILURE; + } + /* header checking .. */ + u2PacketType = NIC_RX_GET_PKT_TYPE(aucBuffer); + if (u2PacketType != RX_PKT_TYPE_SW_DEFINED) { + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + return WLAN_STATUS_FAILURE; + } + + prEvent = (struct WIFI_EVENT *) + (aucBuffer + prChipInfo->rxd_size); + if (prEvent->ucEID != EVENT_ID_ACCESS_REG) { + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + return WLAN_STATUS_FAILURE; + } + + prCmdMcrQuery = (struct CMD_ACCESS_REG *) ( + prEvent->aucBuffer); + prMcrRdInfo->u4McrOffset = prCmdMcrQuery->u4Address; + prMcrRdInfo->u4McrData = prCmdMcrQuery->u4Data; + + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + + return WLAN_STATUS_SUCCESS; +} + +static int32_t wlanIntRound(int32_t 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 int32_t wlanCal6628EfuseForm(IN struct ADAPTER + *prAdapter, int32_t au4Input) +{ + + struct PARAM_MCR_RW_STRUCT rMcrRdInfo; + int32_t au4PdSlope, au4TxPwrOffset, au4TxPwrOffset_Round; + int8_t 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_t) au4TxPwrOffset_Round; + + return au4TxPwrOffset_Round; +} + +#endif + +#define NVRAM_OFS(elment) OFFSET_OF(struct WIFI_CFG_PARAM_STRUCT, elment) + +uint32_t wlanGetMiniTxPower(IN struct ADAPTER *prAdapter, + IN enum ENUM_BAND eBand, + IN enum ENUM_PHY_MODE_TYPE ePhyMode, + OUT int8_t *pTxPwr) +{ +#ifdef SOC3_0 + struct REG_INFO *prRegInfo; + struct WIFI_CFG_PARAM_STRUCT *prNvramSettings; + uint8_t *pu1Addr; + int8_t bandIdx = 0; + + int8_t minTxPwr = 0x7F; + int8_t nvTxPwr = 0; + uint32_t rateIdx = 0; + uint32_t startOfs = 0; + uint32_t endOfs = 0; + + struct NVRAM_FRAGMENT_RANGE arRange[2][PHY_MODE_TYPE_NUM] = { + /*BAND2G4*/ + { + /*CCK*/ + {NVRAM_OFS(r2G4Pwr.uc2G4TxPwrCck1M), + NVRAM_OFS(r2G4Pwr.uc2G4TxPwrCck11M)}, + /*OFDM*/ + {NVRAM_OFS(r2G4Pwr.uc2G4TxPwrOfdm6M), + NVRAM_OFS(r2G4Pwr.uc2G4TxPwrOfdm54M)}, + /*HT20*/ + {NVRAM_OFS(r2G4Pwr.uc2G4TxPwrHt20Mcs0), + NVRAM_OFS(r2G4Pwr.uc2G4TxPwrHt20Mcs7)}, + /*HT40*/ + {NVRAM_OFS(r2G4Pwr.uc2G4TxPwrHt40Mcs0), + NVRAM_OFS(r2G4Pwr.uc2G4TxPwrHt40Mcs32)}, + /*VHT20*/ + {NVRAM_OFS(r2G4Pwr.uc2G4TxPwrVht20Mcs0), + NVRAM_OFS(r2G4Pwr.uc2G4TxPwrVht20Mcs9)}, + /*VHT40*/ + {NVRAM_OFS(r2G4Pwr.uc2G4TxPwrVht40Mcs0), + NVRAM_OFS(r2G4Pwr.uc2G4TxPwrVht40Mcs9)}, + /*VHT80*/ + {0, 0}, + /*SU20*/ + {NVRAM_OFS(r2G4Pwr.uc2G4TxPwrRU242Mcs0), + NVRAM_OFS(r2G4Pwr.uc2G4TxPwrRU242Mcs11)}, + /*SU40*/ + {NVRAM_OFS(r2G4Pwr.uc2G4TxPwrRU484Mcs0), + NVRAM_OFS(r2G4Pwr.uc2G4TxPwrRU484Mcs11)}, + /*SU80*/ + {0, 0}, + /*RU26*/ + {NVRAM_OFS(r2G4Pwr.uc2G4TxPwrRU26Mcs0), + NVRAM_OFS(r2G4Pwr.uc2G4TxPwrRU26Mcs11)}, + /*RU52*/ + {NVRAM_OFS(r2G4Pwr.uc2G4TxPwrRU52Mcs0), + NVRAM_OFS(r2G4Pwr.uc2G4TxPwrRU52Mcs11)}, + /*RU106*/ + {NVRAM_OFS(r2G4Pwr.uc2G4TxPwrRU106Mcs0), + NVRAM_OFS(r2G4Pwr.uc2G4TxPwrRU106Mcs11)}, + /*RU242*/ + {NVRAM_OFS(r2G4Pwr.uc2G4TxPwrRU242Mcs0), + NVRAM_OFS(r2G4Pwr.uc2G4TxPwrRU242Mcs11)}, + /*RU484*/ + {NVRAM_OFS(r2G4Pwr.uc2G4TxPwrRU484Mcs0), + NVRAM_OFS(r2G4Pwr.uc2G4TxPwrRU484Mcs11)}, + /*RU996*/ + {0, 0}, + }, + /*BAND5G*/ + { + /*CCK*/ + {0, 0}, + /*OFDM*/ + {NVRAM_OFS(r5GPwr.uc5GTxPwrOfdm6M), + NVRAM_OFS(r5GPwr.uc5GTxPwrOfdm54M)}, + /*HT20*/ + {NVRAM_OFS(r5GPwr.uc5GTxPwrHt20Mcs0), + NVRAM_OFS(r5GPwr.uc5GTxPwrHt20Mcs7)}, + /*HT40*/ + {NVRAM_OFS(r5GPwr.uc5GTxPwrHt40Mcs0), + NVRAM_OFS(r5GPwr.uc5GTxPwrHt40Mcs32)}, + /*VHT20*/ + {NVRAM_OFS(r5GPwr.uc5GTxPwrVht20Mcs0), + NVRAM_OFS(r5GPwr.uc5GTxPwrVht20Mcs9)}, + /*VHT40*/ + {NVRAM_OFS(r5GPwr.uc5GTxPwrVht40Mcs0), + NVRAM_OFS(r5GPwr.uc5GTxPwrVht40Mcs9)}, + /*VHT80*/ + {NVRAM_OFS(r5GPwr.uc5GTxPwrVht80Mcs0), + NVRAM_OFS(r5GPwr.uc5GTxPwrVht80Mcs9)}, + /*SU20*/ + {NVRAM_OFS(r5GPwr.uc5GTxPwrRU242Mcs0), + NVRAM_OFS(r5GPwr.uc5GTxPwrRU242Mcs11)}, + /*SU40*/ + {NVRAM_OFS(r5GPwr.uc5GTxPwrRU484Mcs0), + NVRAM_OFS(r5GPwr.uc5GTxPwrRU484Mcs11)}, + /*SU80*/ + {NVRAM_OFS(r5GPwr.uc5GTxPwrRU996Mcs0), + NVRAM_OFS(r5GPwr.uc5GTxPwrRU996Mcs11)}, + /*RU26*/ + {NVRAM_OFS(r5GPwr.uc5GTxPwrRU26Mcs0), + NVRAM_OFS(r5GPwr.uc5GTxPwrRU26Mcs11)}, + /*RU52*/ + {NVRAM_OFS(r5GPwr.uc5GTxPwrRU52Mcs0), + NVRAM_OFS(r5GPwr.uc5GTxPwrRU52Mcs11)}, + /*RU106*/ + {NVRAM_OFS(r5GPwr.uc5GTxPwrRU106Mcs0), + NVRAM_OFS(r5GPwr.uc5GTxPwrRU106Mcs11)}, + /*RU242*/ + {NVRAM_OFS(r5GPwr.uc5GTxPwrRU242Mcs0), + NVRAM_OFS(r5GPwr.uc5GTxPwrRU242Mcs11)}, + /*RU484*/ + {NVRAM_OFS(r5GPwr.uc5GTxPwrRU484Mcs0), + NVRAM_OFS(r5GPwr.uc5GTxPwrRU484Mcs11)}, + /*RU996*/ + {NVRAM_OFS(r5GPwr.uc5GTxPwrRU996Mcs0), + NVRAM_OFS(r5GPwr.uc5GTxPwrRU996Mcs11)}, + } + }; + + ASSERT(prAdapter); + prRegInfo = &prAdapter->prGlueInfo->rRegInfo; + + ASSERT(prRegInfo); + prNvramSettings = prRegInfo->prNvramSettings; + ASSERT(prNvramSettings); + + if (prAdapter->prGlueInfo->fgNvramAvailable == FALSE) { + DBGLOG(INIT, WARN, "check Nvram fail\n"); + return WLAN_STATUS_NOT_ACCEPTED; + } + + if (eBand == BAND_2G4) + bandIdx = 0; + else if (eBand == BAND_5G) + bandIdx = 1; + else { + DBGLOG(INIT, WARN, "check Band fail(%d)\n", + eBand); + return WLAN_STATUS_NOT_ACCEPTED; + } + if (ePhyMode >= PHY_MODE_TYPE_NUM || ePhyMode < 0) { + DBGLOG(INIT, WARN, "check phy mode fail(%d)\n", + ePhyMode); + return WLAN_STATUS_NOT_ACCEPTED; + } + + startOfs = arRange[bandIdx][ePhyMode].startOfs; + endOfs = arRange[bandIdx][ePhyMode].endOfs; + + + /*NVRAM start addreess :0*/ + pu1Addr = (uint8_t *)&prNvramSettings->u2Part1OwnVersion; + + for (rateIdx = startOfs; rateIdx <= endOfs; rateIdx++) { + nvTxPwr = *(pu1Addr + rateIdx); + + if (nvTxPwr < minTxPwr) + minTxPwr = nvTxPwr; + } + + /*NVRAM resolution is S6.1 format*/ + *pTxPwr = minTxPwr >> 1; + + DBGLOG(INIT, INFO, "Band[%s],PhyMode[%d],get mini txpwr=%d\n", + (eBand == BAND_2G4)?"2G4":"5G", + ePhyMode, + *pTxPwr); + + return WLAN_STATUS_SUCCESS; +#else + DBGLOG(INIT, WARN, "Not supported!"); + return WLAN_STATUS_NOT_SUPPORTED; +#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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanLoadManufactureData(IN struct ADAPTER + *prAdapter, IN struct REG_INFO *prRegInfo) +{ + +#if CFG_SUPPORT_RDD_TEST_MODE + struct CMD_RDD_CH rRddParam; +#endif + uint8_t index = 0; + uint8_t *pu1Addr; + uint8_t u1TypeID; + uint8_t u1LenLSB; + uint8_t u1LenMSB; + uint8_t fgSupportFragment = FALSE; + uint32_t u4NvramStartOffset = 0, u4NvramOffset = 0; + uint32_t u4NvramFragmentSize = 0; + struct CMD_NVRAM_FRAGMENT *prCmdNvramFragment; + struct WIFI_NVRAM_TAG_FORMAT *prTagDataCurr; + struct CMD_NVRAM_SETTING *prCmdNvramSettings; + + if (prRegInfo == NULL) { + DBGLOG(INIT, ERROR, "prRegInfo = NULL"); + return WLAN_STATUS_FAILURE; + } + ASSERT(prAdapter); + + fgSupportFragment = prAdapter->chip_info->is_support_nvram_fragment; + + + /* 1. Version Check */ + if (prAdapter->prGlueInfo->fgNvramAvailable == TRUE) { + prAdapter->rVerInfo.u2Part1CfgOwnVersion = + prRegInfo->prNvramSettings->u2Part1OwnVersion; + prAdapter->rVerInfo.u2Part1CfgPeerVersion = + prRegInfo->prNvramSettings->u2Part1PeerVersion; + prAdapter->rVerInfo.u2Part2CfgOwnVersion = 0; + /* prRegInfo->prNvramSettings->u2Part2OwnVersion; */ + prAdapter->rVerInfo.u2Part2CfgPeerVersion = 0; + /* prRegInfo->prNvramSettings->u2Part2PeerVersion; */ + } + + /* 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; + + /* 5. Get 16-bits Country Code and Bandwidth */ + prAdapter->rWifiVar.u2CountryCode = + (((uint16_t) prRegInfo->au2CountryCode[0]) << 8) | ((( + uint16_t) prRegInfo->au2CountryCode[1]) & BITS(0, 7)); + + /* 6. Set domain and channel information to chip */ + rlmDomainSendCmd(prAdapter); + + /* Update supported channel list in channel table */ + wlanUpdateChannelTable(prAdapter->prGlueInfo); + + /* 9. Send the full Parameters of NVRAM to FW */ + + /*NVRAM Parameter fragment, if NVRAM length is over 2048 bytes*/ + /*Driver will split NVRAM by TLV Group ,each TX CMD is 1564 bytes*/ + if (fgSupportFragment) { + prCmdNvramFragment = (struct CMD_NVRAM_FRAGMENT *)kalMemAlloc( + sizeof(struct CMD_NVRAM_FRAGMENT), + VIR_MEM_TYPE); + if (prCmdNvramFragment == NULL) { + DBGLOG(INIT, ERROR, + "prCmdNvramFragment allocate fail\n"); + return WLAN_STATUS_FAILURE; + } + + u4NvramStartOffset = 0; + pu1Addr = (uint8_t *) + &prRegInfo->prNvramSettings->u2Part1OwnVersion; + + prTagDataCurr = + (struct WIFI_NVRAM_TAG_FORMAT *)(pu1Addr + + OFFSET_OF(struct WIFI_CFG_PARAM_STRUCT, ucTypeID0)); + u1TypeID = prTagDataCurr->u1NvramTypeID; + u1LenLSB = prTagDataCurr->u1NvramTypeLenLsb; + u1LenMSB = prTagDataCurr->u1NvramTypeLenMsb; + u4NvramOffset += + OFFSET_OF(struct WIFI_CFG_PARAM_STRUCT, ucTypeID0); + + DBGLOG(INIT, TRACE, + "NVRAM-Frag Startofs[0x%08X]ID[%d][0x%08X]Len:%d\n" + , u4NvramStartOffset + , u1TypeID + , u4NvramOffset + , (u1LenMSB << 8) | (u1LenLSB)); + + while (1) { + + kalMemZero(prCmdNvramFragment, + sizeof(struct CMD_NVRAM_FRAGMENT)); + + u4NvramOffset += NVRAM_TAG_HDR_SIZE; + u4NvramOffset += (u1LenMSB << 8) | (u1LenLSB); + u4NvramFragmentSize = u4NvramOffset-u4NvramStartOffset; + + DBGLOG(INIT, TRACE, + "NVRAM Fragement(%d)Startofs[0x%08X]ID[%d]Len:%d\n", + index, u4NvramStartOffset, + u1TypeID, u4NvramFragmentSize); + + kalMemCopy(prCmdNvramFragment, + (pu1Addr + u4NvramStartOffset), + u4NvramFragmentSize); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_NVRAM_SETTINGS, + TRUE, + FALSE, + FALSE, NULL, NULL, + sizeof(struct CMD_NVRAM_FRAGMENT), + (uint8_t *) prCmdNvramFragment, NULL, 0); + + /*update the next Fragment group start offset*/ + u4NvramStartOffset = u4NvramOffset; + index++; + + /*get the nex TLV format*/ + prTagDataCurr = (struct WIFI_NVRAM_TAG_FORMAT *) + (pu1Addr + u4NvramOffset); + + u1TypeID = prTagDataCurr->u1NvramTypeID; + u1LenLSB = prTagDataCurr->u1NvramTypeLenLsb; + u1LenMSB = prTagDataCurr->u1NvramTypeLenMsb; + + /*sanity check*/ + if ((u1TypeID == 0) && + (u1LenLSB == 0) && (u1LenMSB == 0)) { + DBGLOG(INIT, INFO, + "TLV is Null, last index = %d\n", + index); + break; + } + } + + kalMemFree(prCmdNvramFragment, VIR_MEM_TYPE, + sizeof(struct CMD_NVRAM_FRAGMENT)); + + } else { + + prCmdNvramSettings = (struct CMD_NVRAM_SETTING *)kalMemAlloc( + sizeof(struct CMD_NVRAM_SETTING), + VIR_MEM_TYPE); + + kalMemCopy(&prCmdNvramSettings->rNvramSettings, + &prRegInfo->prNvramSettings->u2Part1OwnVersion, + sizeof(struct CMD_NVRAM_SETTING)); + ASSERT(sizeof(struct WIFI_CFG_PARAM_STRUCT) == 2048); + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_NVRAM_SETTINGS, + TRUE, + FALSE, + FALSE, NULL, NULL, + sizeof(*prCmdNvramSettings), + (uint8_t *) prCmdNvramSettings, NULL, 0); + kalMemFree(prCmdNvramSettings, VIR_MEM_TYPE, + sizeof(struct CMD_NVRAM_SETTING)); + } + + + wlanNvramSetState(NVRAM_STATE_SEND_TO_FW); + + 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wlanResetMediaStreamMode(IN struct ADAPTER + *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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanTimerTimeoutCheck(IN struct ADAPTER *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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanProcessMboxMessage(IN struct ADAPTER + *prAdapter) +{ + uint32_t i; + + ASSERT(prAdapter); + + for (i = 0; i < MBOX_ID_TOTAL_NUM; i++) + mboxRcvAllMsg(prAdapter, (enum ENUM_MBOX_ID) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanEnqueueTxPacket(IN struct ADAPTER *prAdapter, + IN void *prNativePacket) +{ + struct TX_CTRL *prTxCtrl; + struct MSDU_INFO *prMsduInfo; + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + + prMsduInfo = cnmPktAlloc(prAdapter, 0); + + if (!prMsduInfo) + return WLAN_STATUS_RESOURCES; + + if (nicTxFillMsduInfo(prAdapter, prMsduInfo, + prNativePacket)) { + /* prMsduInfo->eSrc = TX_PACKET_OS; */ + + /* Tx profiling */ + wlanTxProfilingTagMsdu(prAdapter, prMsduInfo, + TX_PROF_TAG_DRV_ENQUE); + + /* enqueue to QM */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; + } + kalSendComplete(prAdapter->prGlueInfo, prNativePacket, + WLAN_STATUS_INVALID_PACKET); + + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + + return WLAN_STATUS_INVALID_PACKET; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to flush pending TX packets in CORE + * + * @param prAdapter Pointer of Adapter Data Structure + * + * @return WLAN_STATUS_SUCCESS + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanFlushTxPendingPackets(IN struct ADAPTER *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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanTxPendingPackets(IN struct ADAPTER *prAdapter, + IN OUT u_int8_t *pfgHwAccess) +{ + struct TX_CTRL *prTxCtrl; + struct MSDU_INFO *prMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + +#if !CFG_SUPPORT_MULTITHREAD + ASSERT(pfgHwAccess); +#endif + + /* <1> dequeue packet by txDequeuTxPackets() */ +#if CFG_SUPPORT_MULTITHREAD + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + prMsduInfo = qmDequeueTxPacketsMthread(prAdapter, + &prTxCtrl->rTc); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); +#else + 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); +#endif + if (prMsduInfo != NULL) { + if (kalIsCardRemoved(prAdapter->prGlueInfo) == FALSE) { +#if !CFG_SUPPORT_MULTITHREAD + /* <2> Acquire LP-OWN if necessary */ + if (*pfgHwAccess == FALSE) { + *pfgHwAccess = TRUE; + + wlanAcquirePowerControl(prAdapter); + } +#endif + /* <3> send packets */ +#if CFG_SUPPORT_MULTITHREAD + nicTxMsduInfoListMthread(prAdapter, prMsduInfo); +#else + nicTxMsduInfoList(prAdapter, prMsduInfo); +#endif + /* <4> update TC by txAdjustTcQuotas() */ + nicTxAdjustTcq(prAdapter); + } else + wlanProcessQueuedMsduInfo(prAdapter, prMsduInfo); + } + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanAcquirePowerControl(IN struct ADAPTER *prAdapter) +{ + ASSERT(prAdapter); + + /* DBGLOG(INIT, INFO, ("Acquire Power Ctrl\n")); */ + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanReleasePowerControl(IN struct ADAPTER *prAdapter) +{ + ASSERT(prAdapter); + + /* DBGLOG(INIT, INFO, ("Release Power Ctrl\n")); */ + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanGetTxPendingFrameCount(IN struct ADAPTER *prAdapter) +{ + struct TX_CTRL *prTxCtrl; + uint32_t u4Num; + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + u4Num = kalGetTxPendingFrameCount(prAdapter->prGlueInfo) + + (uint32_t) GLUE_GET_REF_CNT( + 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 ENUM_ACPI_STATE wlanGetAcpiState(IN struct ADAPTER *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 struct ADAPTER *prAdapter, + IN enum ENUM_ACPI_STATE ePowerState) +{ + ASSERT(prAdapter); + ASSERT(ePowerState <= ACPI_STATE_D3); + + prAdapter->rAcpiState = ePowerState; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is to query ECO version from HIFSYS CR + * + * @param prAdapter Pointer of Adapter Data Structure + * + * @return zero Unable to retrieve ECO version information + * non-zero ECO version (1-based) + */ +/*----------------------------------------------------------------------------*/ +uint8_t wlanGetEcoVersion(IN struct ADAPTER *prAdapter) +{ + uint8_t ucEcoVersion; + + ASSERT(prAdapter); + +#if CFG_MULTI_ECOVER_SUPPORT + ucEcoVersion = nicGetChipEcoVer(prAdapter); + DBGLOG(INIT, TRACE, "%s: %u\n", __func__, ucEcoVersion); + return ucEcoVersion; +#else + if (nicVerifyChipID(prAdapter) == TRUE) + return prAdapter->ucRevID + 1; + else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 ucBssIndex BSS Info Index + * + * @return none + */ +/*----------------------------------------------------------------------------*/ +void wlanSetPreferBandByNetwork(IN struct ADAPTER *prAdapter, + IN enum ENUM_BAND eBand, IN uint8_t ucBssIndex) +{ + ASSERT(prAdapter); + ASSERT(eBand <= BAND_NUM); + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + + /* 1. set prefer band according to network type */ + prAdapter->aePreferBand[ucBssIndex] = eBand; + + /* 2. remove buffered BSS descriptors correspondingly */ + if (eBand == BAND_2G4) + scanRemoveBssDescByBandAndNetwork(prAdapter, BAND_5G, + ucBssIndex); + else if (eBand == BAND_5G) + scanRemoveBssDescByBandAndNetwork(prAdapter, BAND_2G4, + ucBssIndex); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is to + * get channel information corresponding to specified network type + * + * @param prAdapter Pointer of Adapter Data Structure + * @param ucBssIndex BSS Info Index + * + * @return channel number + */ +/*----------------------------------------------------------------------------*/ +uint8_t wlanGetChannelNumberByNetwork(IN struct ADAPTER + *prAdapter, IN uint8_t ucBssIndex) +{ + struct BSS_INFO *prBssInfo; + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + return prBssInfo->ucPrimaryChannel; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanCheckSystemConfiguration(IN struct ADAPTER + *prAdapter) +{ +#if (CFG_NVRAM_EXISTENCE_CHECK == 1) || (CFG_SW_NVRAM_VERSION_CHECK == 1) + const uint8_t aucZeroMacAddr[] = NULL_MAC_ADDR; + u_int8_t fgIsConfExist = TRUE; + u_int8_t fgGenErrMsg = FALSE; + struct REG_INFO *prRegInfo = NULL; +#if 0 + const uint8_t aucBCAddr[] = BC_MAC_ADDR; + struct WLAN_BEACON_FRAME *prBeacon = NULL; + struct IE_SSID *prSsid = NULL; + uint32_t u4ErrCode = 0; + uint8_t aucErrMsg[32]; + struct PARAM_SSID rSsid; + struct PARAM_802_11_CONFIG rConfiguration; + uint8_t rSupportedRates[PARAM_MAX_LEN_RATES_EX]; +#endif +#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 (prRegInfo == NULL) { + DBGLOG(INIT, ERROR, "prRegInfo = NULL"); + return WLAN_STATUS_FAILURE; + } + +#if (CFG_SUPPORT_PWR_LIMIT_COUNTRY == 1) + if (fgIsConfExist == TRUE + && (prAdapter->rVerInfo.u2Part1CfgPeerVersion > + CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part2CfgPeerVersion > + CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part1CfgOwnVersion < + CFG_DRV_PEER_VERSION + || prAdapter->rVerInfo.u2Part2CfgOwnVersion < + CFG_DRV_PEER_VERSION/* NVRAM */ + || prAdapter->rVerInfo.u2FwPeerVersion > CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2FwOwnVersion < CFG_DRV_PEER_VERSION + || (prAdapter->fgIsEmbbededMacAddrValid == FALSE && + (IS_BMCAST_MAC_ADDR(prRegInfo->aucMacAddr) + || EQUAL_MAC_ADDR(aucZeroMacAddr, prRegInfo->aucMacAddr))) + || prAdapter->fgIsPowerLimitTableValid == FALSE)) + fgGenErrMsg = TRUE; +#else + if (fgIsConfExist == TRUE + && (prAdapter->rVerInfo.u2Part1CfgPeerVersion > + CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part2CfgPeerVersion > + CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part1CfgOwnVersion < + CFG_DRV_PEER_VERSION + || prAdapter->rVerInfo.u2Part2CfgOwnVersion < + CFG_DRV_PEER_VERSION/* NVRAM */ + || prAdapter->rVerInfo.u2FwPeerVersion > CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2FwOwnVersion < CFG_DRV_PEER_VERSION + || (prAdapter->fgIsEmbbededMacAddrValid == FALSE && + (IS_BMCAST_MAC_ADDR(prRegInfo->aucMacAddr) + || EQUAL_MAC_ADDR(aucZeroMacAddr, prRegInfo->aucMacAddr))) + )) + fgGenErrMsg = TRUE; +#endif +#endif +#if 0/* remove NVRAM WARNING in scan result */ + if (fgGenErrMsg == TRUE) { + prBeacon = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, + sizeof(struct WLAN_BEACON_FRAME) + + sizeof(struct IE_SSID)); + + /* initialization */ + kalMemZero(prBeacon, sizeof(struct WLAN_BEACON_FRAME) + + sizeof(struct IE_SSID)); + + /* 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 = (struct IE_SSID *) (&prBeacon->aucInfoElem[0]); + prSsid->ucId = ELEM_ID_SSID; + + /* rConfiguration initialization */ + rConfiguration.u4Length = sizeof(struct + PARAM_802_11_CONFIG); + rConfiguration.u4BeaconPeriod = 100; + rConfiguration.u4ATIMWindow = 1; + rConfiguration.u4DSConfig = 2412; + rConfiguration.rFHConfig.u4Length = sizeof( + struct PARAM_802_11_CONFIG_FH); + + /* rSupportedRates initialization */ + kalMemZero(rSupportedRates, + (sizeof(uint8_t) * PARAM_MAX_LEN_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, + (uint8_t) (strlen(NVRAM_ERR_MSG))); + + kalIndicateBssInfo(prAdapter->prGlueInfo, + (uint8_t *) prBeacon, + OFFSET_OF(struct WLAN_BEACON_FRAME, + aucInfoElem) + OFFSET_OF( + struct IE_SSID, 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(struct WLAN_BEACON_FRAME, + aucInfoElem) + OFFSET_OF( + struct IE_SSID, aucSSID) + + prSsid->ucLength - + WLAN_MAC_MGMT_HEADER_LEN, + (uint8_t *) ((unsigned long) (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 ((prAdapter->rVerInfo.u2Part1CfgPeerVersion > + CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part2CfgPeerVersion > + CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part1CfgOwnVersion < + CFG_DRV_PEER_VERSION + || prAdapter->rVerInfo.u2Part2CfgOwnVersion < + CFG_DRV_PEER_VERSION /* NVRAM */ + || prAdapter->rVerInfo.u2FwPeerVersion > + CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2FwOwnVersion < + CFG_DRV_PEER_VERSION)) + u4ErrCode |= NVRAM_ERROR_VERSION_MISMATCH; + + if (prAdapter->fgIsEmbbededMacAddrValid == FALSE + && (IS_BMCAST_MAC_ADDR(prRegInfo->aucMacAddr) + || EQUAL_MAC_ADDR(aucZeroMacAddr, + prRegInfo->aucMacAddr))) { + u4ErrCode |= NVRAM_ERROR_INVALID_MAC_ADDR; + } +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + if (prAdapter->fgIsPowerLimitTableValid == FALSE) + u4ErrCode |= NVRAM_POWER_LIMIT_TABLE_INVALID; +#endif + if (u4ErrCode != 0) { + sprintf(aucErrMsg, VER_ERR_MSG, + (unsigned int)u4ErrCode); + COPY_SSID(prSsid->aucSSID, prSsid->ucLength, aucErrMsg, + (uint8_t) (strlen(aucErrMsg))); + + kalIndicateBssInfo(prAdapter->prGlueInfo, + (uint8_t *) prBeacon, + OFFSET_OF(struct WLAN_BEACON_FRAME, + aucInfoElem) + OFFSET_OF( + struct IE_SSID, 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(struct WLAN_BEACON_FRAME, + aucInfoElem) + + OFFSET_OF(struct IE_SSID, + aucSSID) + prSsid->ucLength - + WLAN_MAC_MGMT_HEADER_LEN, + (uint8_t *) ((unsigned long) (prBeacon) + + WLAN_MAC_MGMT_HEADER_LEN)); + } + } +#endif + + if (fgGenErrMsg == TRUE) + cnmMemFree(prAdapter, prBeacon); +#endif + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidQueryBssStatistics(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + struct PARAM_GET_BSS_STATISTICS *prQueryBssStatistics; + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint32_t rResult = WLAN_STATUS_FAILURE; + uint8_t ucBssIndex; + enum ENUM_WMM_ACI eAci; + + DEBUGFUNC("wlanoidQueryBssStatistics"); + + do { + ASSERT(pvQueryBuffer); + + /* 4 1. Sanity test */ + if ((prAdapter == NULL) || (pu4QueryInfoLen == NULL)) + break; + + if ((u4QueryBufferLen) && (pvQueryBuffer == NULL)) + break; + + if (u4QueryBufferLen < + sizeof(struct PARAM_GET_BSS_STATISTICS *)) { + *pu4QueryInfoLen = + sizeof(struct PARAM_GET_BSS_STATISTICS *); + rResult = WLAN_STATUS_BUFFER_TOO_SHORT; + break; + } + + prQueryBssStatistics = (struct PARAM_GET_BSS_STATISTICS *) + pvQueryBuffer; + *pu4QueryInfoLen = sizeof(struct PARAM_GET_BSS_STATISTICS); + + ucBssIndex = prQueryBssStatistics->ucBssIndex; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (prBssInfo) { /*AIS*/ + if (prBssInfo->eCurrentOPMode == + OP_MODE_INFRASTRUCTURE) { + struct WIFI_WMM_AC_STAT *prQueryLss = NULL; + struct WIFI_WMM_AC_STAT *prStaLss = NULL; + struct WIFI_WMM_AC_STAT *prBssLss = NULL; + + prQueryLss = prQueryBssStatistics->arLinkStatistics; + prBssLss = prBssInfo->arLinkStatistics; + prStaRec = prBssInfo->prStaRecOfAP; + if (prStaRec) { + prStaLss = prStaRec->arLinkStatistics; + for (eAci = 0; + eAci < WMM_AC_INDEX_NUM; eAci++) { + prQueryLss[eAci].u4TxMsdu = + prStaLss[eAci].u4TxMsdu; + prQueryLss[eAci].u4RxMsdu = + prStaLss[eAci].u4RxMsdu; + prQueryLss[eAci].u4TxDropMsdu = + prStaLss[eAci].u4TxDropMsdu + + prBssLss[eAci].u4TxDropMsdu; + prQueryLss[eAci].u4TxFailMsdu = + prStaLss[eAci].u4TxFailMsdu; + prQueryLss[eAci].u4TxRetryMsdu = + prStaLss[eAci].u4TxRetryMsdu; + } + } + } + rResult = WLAN_STATUS_SUCCESS; + + /*P2P */ + /* TODO */ + + /*BOW*/ + /* TODO */ + } + + } while (FALSE); + + return rResult; + +} + +void wlanDumpBssStatistics(IN struct ADAPTER *prAdapter, + uint8_t ucBssIdx) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + enum ENUM_WMM_ACI eAci; + struct WIFI_WMM_AC_STAT arLLStats[WMM_AC_INDEX_NUM]; + uint8_t ucIdx; + + if (ucBssIdx > prAdapter->ucHwBssIdNum) { + DBGLOG(SW4, INFO, "Invalid BssInfo index[%u], skip dump!\n", + ucBssIdx); + return; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + if (!prBssInfo) { + DBGLOG(SW4, INFO, "Invalid BssInfo index[%u], skip dump!\n", + ucBssIdx); + return; + } + /* <1> fill per-BSS statistics */ +#if 0 + /*AIS*/ if (prBssInfo->eCurrentOPMode == + OP_MODE_INFRASTRUCTURE) { + prStaRec = prBssInfo->prStaRecOfAP; + if (prStaRec) { + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prBssInfo->arLinkStatistics[eAci].u4TxMsdu + = prStaRec->arLinkStatistics[eAci] + .u4TxMsdu; + prBssInfo->arLinkStatistics[eAci].u4RxMsdu + = prStaRec->arLinkStatistics[eAci] + .u4RxMsdu; + prBssInfo->arLinkStatistics[eAci].u4TxDropMsdu + += prStaRec->arLinkStatistics[eAci] + .u4TxDropMsdu; + prBssInfo->arLinkStatistics[eAci].u4TxFailMsdu + = prStaRec->arLinkStatistics[eAci] + .u4TxFailMsdu; + prBssInfo->arLinkStatistics[eAci].u4TxRetryMsdu + = prStaRec->arLinkStatistics[eAci] + .u4TxRetryMsdu; + } + } + } +#else + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + arLLStats[eAci].u4TxMsdu = + prBssInfo->arLinkStatistics[eAci].u4TxMsdu; + arLLStats[eAci].u4RxMsdu = + prBssInfo->arLinkStatistics[eAci].u4RxMsdu; + arLLStats[eAci].u4TxDropMsdu = + prBssInfo->arLinkStatistics[eAci].u4TxDropMsdu; + arLLStats[eAci].u4TxFailMsdu = + prBssInfo->arLinkStatistics[eAci].u4TxFailMsdu; + arLLStats[eAci].u4TxRetryMsdu = + prBssInfo->arLinkStatistics[eAci].u4TxRetryMsdu; + } + + for (ucIdx = 0; ucIdx < CFG_STA_REC_NUM; ucIdx++) { + prStaRec = cnmGetStaRecByIndex(prAdapter, ucIdx); + if (!prStaRec) + continue; + if (prStaRec->ucBssIndex != ucBssIdx) + continue; + /* now the valid sta_rec is valid */ + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + arLLStats[eAci].u4TxMsdu += + prStaRec->arLinkStatistics[eAci].u4TxMsdu; + arLLStats[eAci].u4RxMsdu += + prStaRec->arLinkStatistics[eAci].u4RxMsdu; + arLLStats[eAci].u4TxDropMsdu += + prStaRec->arLinkStatistics[eAci].u4TxDropMsdu; + arLLStats[eAci].u4TxFailMsdu += + prStaRec->arLinkStatistics[eAci].u4TxFailMsdu; + arLLStats[eAci].u4TxRetryMsdu += + prStaRec->arLinkStatistics[eAci].u4TxRetryMsdu; + } + } +#endif + + /* <2>Dump BSS statistics */ + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + DBGLOG(SW4, INFO, + "LLS BSS[%u] %s: T[%06u] R[%06u] T_D[%06u] T_F[%06u]\n", + prBssInfo->ucBssIndex, apucACI2Str[eAci], + arLLStats[eAci].u4TxMsdu, + arLLStats[eAci].u4RxMsdu, arLLStats[eAci].u4TxDropMsdu, + arLLStats[eAci].u4TxFailMsdu); + } +} + +void wlanDumpAllBssStatistics(IN struct ADAPTER *prAdapter) +{ + struct BSS_INFO *prBssInfo; + /* ENUM_WMM_ACI_T eAci; */ + uint32_t ucIdx; + + /* wlanUpdateAllBssStatistics(prAdapter); */ + + for (ucIdx = 0; ucIdx < prAdapter->ucHwBssIdNum; ucIdx++) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucIdx); + if (!IS_BSS_ACTIVE(prBssInfo)) { + DBGLOG(SW4, TRACE, + "Invalid BssInfo index[%u], skip dump!\n", + ucIdx); + continue; + } + + wlanDumpBssStatistics(prAdapter, ucIdx); + } +} + +uint32_t +wlanoidQueryStaStatistics(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + if (ucBssIndex == AIS_DEFAULT_INDEX && + !CHECK_FOR_TIMEOUT(kalGetTimeTick(), + prAdapter->u4LastLinkQuality, + SEC_TO_MSEC(CFG_LQ_MONITOR_FREQUENCY))) { + kalMemCopy((struct PARAM_GET_STA_STATISTICS *)pvQueryBuffer, + &prAdapter->rQueryStaStatistics, + sizeof(struct PARAM_GET_STA_STATISTICS)); + return WLAN_STATUS_SUCCESS; + } else + return wlanQueryStaStatistics(prAdapter, pvQueryBuffer, + u4QueryBufferLen, pu4QueryInfoLen, TRUE); +#else + return wlanQueryStaStatistics(prAdapter, pvQueryBuffer, + u4QueryBufferLen, pu4QueryInfoLen, TRUE); +#endif +} + +uint32_t +wlanQueryStaStatistics(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen, + u_int8_t fgIsOid) +{ + uint32_t rResult = WLAN_STATUS_FAILURE; + struct STA_RECORD *prStaRec, *prTempStaRec; + struct PARAM_GET_STA_STATISTICS *prQueryStaStatistics; + uint8_t ucStaRecIdx; + struct QUE_MGT *prQM; + struct CMD_GET_STA_STATISTICS rQueryCmdStaStatistics; + uint8_t ucIdx; + enum ENUM_WMM_ACI eAci; + + DEBUGFUNC("wlanoidQueryStaStatistics"); + + if (prAdapter == NULL) + return WLAN_STATUS_FAILURE; + prQM = &prAdapter->rQM; + + if (prAdapter->fgIsEnableLpdvt) + return WLAN_STATUS_NOT_SUPPORTED; + + do { + ASSERT(pvQueryBuffer); + + /* 4 1. Sanity test */ + if (pu4QueryInfoLen == NULL) + break; + + if ((u4QueryBufferLen) && (pvQueryBuffer == NULL)) + break; + + if (u4QueryBufferLen < + sizeof(struct PARAM_GET_STA_STATISTICS)) { + *pu4QueryInfoLen = + sizeof(struct PARAM_GET_STA_STATISTICS); + rResult = WLAN_STATUS_BUFFER_TOO_SHORT; + break; + } + + prQueryStaStatistics = (struct PARAM_GET_STA_STATISTICS *) + pvQueryBuffer; + *pu4QueryInfoLen = sizeof(struct PARAM_GET_STA_STATISTICS); + + /* 4 5. Get driver global QM counter */ +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + for (ucIdx = TC0_INDEX; ucIdx <= TC3_INDEX; ucIdx++) { + prQueryStaStatistics->au4TcAverageQueLen[ucIdx] = + prQM->au4AverageQueLen[ucIdx]; + prQueryStaStatistics->au4TcCurrentQueLen[ucIdx] = + prQM->au4CurrentTcResource[ucIdx]; + } +#endif + + /* 4 2. Get StaRec by MAC address */ + prStaRec = NULL; + + for (ucStaRecIdx = 0; ucStaRecIdx < CFG_STA_REC_NUM; + ucStaRecIdx++) { + prTempStaRec = &(prAdapter->arStaRec[ucStaRecIdx]); + if (prTempStaRec->fgIsValid && + prTempStaRec->fgIsInUse) { + if (EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, + prQueryStaStatistics->aucMacAddr)) { + prStaRec = prTempStaRec; + break; + } + } + } + + if (!prStaRec) { + rResult = WLAN_STATUS_INVALID_DATA; + break; + } + + prQueryStaStatistics->u4Flag |= BIT(0); + +#if CFG_ENABLE_PER_STA_STATISTICS + /* 4 3. Get driver statistics */ + prQueryStaStatistics->u4TxTotalCount = + prStaRec->u4TotalTxPktsNumber; + prQueryStaStatistics->u4RxTotalCount = + prStaRec->u4TotalRxPktsNumber; + prQueryStaStatistics->u4TxExceedThresholdCount = + prStaRec->u4ThresholdCounter; + prQueryStaStatistics->u4TxMaxTime = + prStaRec->u4MaxTxPktsTime; + prQueryStaStatistics->u4TxMaxHifTime = + prStaRec->u4MaxTxPktsHifTime; + + if (prStaRec->u4TotalTxPktsNumber) { + prQueryStaStatistics->u4TxAverageProcessTime = + (prStaRec->u4TotalTxPktsTime / + prStaRec->u4TotalTxPktsNumber); + prQueryStaStatistics->u4TxAverageHifTime = + prStaRec->u4TotalTxPktsHifTxTime / + prStaRec->u4TotalTxPktsNumber; + } else + prQueryStaStatistics->u4TxAverageProcessTime = 0; + + /*link layer statistics */ + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prQueryStaStatistics->arLinkStatistics[eAci].u4TxMsdu = + prStaRec->arLinkStatistics[eAci].u4TxMsdu; + prQueryStaStatistics->arLinkStatistics[eAci].u4RxMsdu = + prStaRec->arLinkStatistics[eAci].u4RxMsdu; + prQueryStaStatistics->arLinkStatistics[ + eAci].u4TxDropMsdu = + prStaRec->arLinkStatistics[eAci].u4TxDropMsdu; + } + + for (ucIdx = TC0_INDEX; ucIdx <= TC3_INDEX; ucIdx++) { + prQueryStaStatistics->au4TcResourceEmptyCount[ucIdx] = + prQM->au4QmTcResourceEmptyCounter[ + prStaRec->ucBssIndex][ucIdx]; + /* Reset */ + prQM->au4QmTcResourceEmptyCounter[ + prStaRec->ucBssIndex][ucIdx] = 0; + prQueryStaStatistics->au4TcResourceBackCount[ucIdx] = + prQM->au4QmTcResourceBackCounter[ucIdx]; + prQM->au4QmTcResourceBackCounter[ucIdx] = 0; + prQueryStaStatistics->au4DequeueNoTcResource[ucIdx] + = prQM->au4DequeueNoTcResourceCounter[ucIdx]; + prQM->au4DequeueNoTcResourceCounter[ucIdx] = 0; + prQueryStaStatistics->au4TcResourceUsedPageCount[ucIdx] + = prQM->au4QmTcUsedPageCounter[ucIdx]; + prQM->au4QmTcUsedPageCounter[ucIdx] = 0; + prQueryStaStatistics->au4TcResourceWantedPageCount[ + ucIdx] = prQM->au4QmTcWantedPageCounter[ucIdx]; + prQM->au4QmTcWantedPageCounter[ucIdx] = 0; + } + + prQueryStaStatistics->u4EnqueueCounter = + prQM->u4EnqueueCounter; + prQueryStaStatistics->u4EnqueueStaCounter = + prStaRec->u4EnqueueCounter; + + prQueryStaStatistics->u4DequeueCounter = + prQM->u4DequeueCounter; + prQueryStaStatistics->u4DequeueStaCounter = + prStaRec->u4DeqeueuCounter; + + prQueryStaStatistics->IsrCnt = + prAdapter->prGlueInfo->IsrCnt; + prQueryStaStatistics->IsrPassCnt = + prAdapter->prGlueInfo->IsrPassCnt; + prQueryStaStatistics->TaskIsrCnt = + prAdapter->prGlueInfo->TaskIsrCnt; + + prQueryStaStatistics->IsrAbnormalCnt = + prAdapter->prGlueInfo->IsrAbnormalCnt; + prQueryStaStatistics->IsrSoftWareCnt = + prAdapter->prGlueInfo->IsrSoftWareCnt; + prQueryStaStatistics->IsrRxCnt = + prAdapter->prGlueInfo->IsrRxCnt; + prQueryStaStatistics->IsrTxCnt = + prAdapter->prGlueInfo->IsrTxCnt; + + /* 4 4.1 Reset statistics */ + if (prQueryStaStatistics->ucReadClear) { + prStaRec->u4ThresholdCounter = 0; + prStaRec->u4TotalTxPktsNumber = 0; + prStaRec->u4TotalTxPktsHifTxTime = 0; + + prStaRec->u4TotalTxPktsTime = 0; + prStaRec->u4TotalRxPktsNumber = 0; + prStaRec->u4MaxTxPktsTime = 0; + prStaRec->u4MaxTxPktsHifTime = 0; + prQM->u4EnqueueCounter = 0; + prQM->u4DequeueCounter = 0; + prStaRec->u4EnqueueCounter = 0; + prStaRec->u4DeqeueuCounter = 0; + + prAdapter->prGlueInfo->IsrCnt = 0; + prAdapter->prGlueInfo->IsrPassCnt = 0; + prAdapter->prGlueInfo->TaskIsrCnt = 0; + + prAdapter->prGlueInfo->IsrAbnormalCnt = 0; + prAdapter->prGlueInfo->IsrSoftWareCnt = 0; + prAdapter->prGlueInfo->IsrRxCnt = 0; + prAdapter->prGlueInfo->IsrTxCnt = 0; + } + /*link layer statistics */ + if (prQueryStaStatistics->ucLlsReadClear) { + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prStaRec->arLinkStatistics[eAci].u4TxMsdu = 0; + prStaRec->arLinkStatistics[eAci].u4RxMsdu = 0; + prStaRec->arLinkStatistics[eAci].u4TxDropMsdu + = 0; + } + } +#endif + + for (ucIdx = TC0_INDEX; ucIdx <= TC3_INDEX; ucIdx++) + prQueryStaStatistics->au4TcQueLen[ucIdx] = + prStaRec->aprTargetQueue[ucIdx]->u4NumElem; + + rResult = WLAN_STATUS_SUCCESS; + + /* 4 6. Ensure FW supports get station link status */ + rQueryCmdStaStatistics.ucIndex = prStaRec->ucIndex; + COPY_MAC_ADDR(rQueryCmdStaStatistics.aucMacAddr, + prQueryStaStatistics->aucMacAddr); + rQueryCmdStaStatistics.ucReadClear = + prQueryStaStatistics->ucReadClear; + rQueryCmdStaStatistics.ucLlsReadClear = + prQueryStaStatistics->ucLlsReadClear; + rQueryCmdStaStatistics.ucResetCounter = + prQueryStaStatistics->ucResetCounter; + + rResult = wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STA_STATISTICS, + FALSE, + TRUE, + fgIsOid, + nicCmdEventQueryStaStatistics, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_GET_STA_STATISTICS), + (uint8_t *)&rQueryCmdStaStatistics, + pvQueryBuffer, u4QueryBufferLen); + + if ((!fgIsOid) && (rResult == WLAN_STATUS_PENDING)) + rResult = WLAN_STATUS_SUCCESS; + + prQueryStaStatistics->u4Flag |= BIT(1); + + } while (FALSE); + + return rResult; +} /* wlanoidQueryP2pVersion */ + +uint32_t +wlanQueryStatistics(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen, IN uint8_t fgIsOid) +{ + struct PARAM_802_11_STATISTICS_STRUCT rStatistics; + + DEBUGFUNC("wlanQueryStatistics"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(struct PARAM_802_11_STATISTICS_STRUCT); + + 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(uint32_t); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(struct + PARAM_802_11_STATISTICS_STRUCT)) { + DBGLOG(REQ, WARN, "Too short length %u\n", + u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + struct PARAM_802_11_STATISTICS_STRUCT *prStatistics; + + *pu4QueryInfoLen = sizeof(struct + PARAM_802_11_STATISTICS_STRUCT); + prStatistics = (struct PARAM_802_11_STATISTICS_STRUCT *) + pvQueryBuffer; + + prStatistics->u4Length = sizeof(struct + PARAM_802_11_STATISTICS_STRUCT); + prStatistics->rTransmittedFragmentCount = + prAdapter->rStatStruct.rTransmittedFragmentCount; + prStatistics->rMulticastTransmittedFrameCount = + prAdapter->rStatStruct.rMulticastTransmittedFrameCount; + prStatistics->rFailedCount = + prAdapter->rStatStruct.rFailedCount; + prStatistics->rRetryCount = + prAdapter->rStatStruct.rRetryCount; + prStatistics->rMultipleRetryCount = + prAdapter->rStatStruct.rMultipleRetryCount; + prStatistics->rRTSSuccessCount = + prAdapter->rStatStruct.rRTSSuccessCount; + prStatistics->rRTSFailureCount = + prAdapter->rStatStruct.rRTSFailureCount; + prStatistics->rACKFailureCount = + prAdapter->rStatStruct.rACKFailureCount; + prStatistics->rFrameDuplicateCount = + prAdapter->rStatStruct.rFrameDuplicateCount; + prStatistics->rReceivedFragmentCount = + prAdapter->rStatStruct.rReceivedFragmentCount; + prStatistics->rMulticastReceivedFrameCount = + prAdapter->rStatStruct.rMulticastReceivedFrameCount; + prStatistics->rFCSErrorCount = + prAdapter->rStatStruct.rFCSErrorCount; + prStatistics->rTKIPLocalMICFailures.QuadPart = 0; + prStatistics->rTKIPICVErrors.QuadPart = 0; + prStatistics->rTKIPCounterMeasuresInvoked.QuadPart = 0; + prStatistics->rTKIPReplays.QuadPart = 0; + prStatistics->rCCMPFormatErrors.QuadPart = 0; + prStatistics->rCCMPReplays.QuadPart = 0; + prStatistics->rCCMPDecryptErrors.QuadPart = 0; + prStatistics->rFourWayHandshakeFailures.QuadPart = 0; + prStatistics->rWEPUndecryptableCount.QuadPart = 0; + prStatistics->rWEPICVErrorCount.QuadPart = 0; + prStatistics->rDecryptSuccessCount.QuadPart = 0; + prStatistics->rDecryptFailureCount.QuadPart = 0; + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + fgIsOid, + nicCmdEventQueryStatistics, + nicOidCmdTimeoutCommon, + sizeof(struct PARAM_802_11_STATISTICS_STRUCT), + (uint8_t *)&rStatistics, + pvQueryBuffer, u4QueryBufferLen); + +} /* wlanQueryStatistics */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is to query Nic resource information + * + * @param prAdapter Pointer of Adapter Data Structure + * + * @return WLAN_STATUS_SUCCESS + */ +/*----------------------------------------------------------------------------*/ +void wlanQueryNicResourceInformation(IN struct ADAPTER *prAdapter) +{ + /* 3 1. Get Nic resource information from FW */ + + /* 3 2. Setup resource parameter */ + + /* 3 3. Reset Tx resource */ + nicTxResetResource(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is to query Nic resource information + * + * @param prAdapter Pointer of Adapter Data Structure + * + * @return WLAN_STATUS_SUCCESS + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanQueryNicCapabilityV2(IN struct ADAPTER *prAdapter) +{ + struct CMD_INFO *prCmdInfo; + uint32_t u4RxPktLength; + uint8_t *prEventBuff; + struct WIFI_EVENT *prEvent; + struct mt66xx_chip_info *prChipInfo; + uint32_t chip_id; + uint32_t u4Time; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + chip_id = prChipInfo->chip_id; + + ASSERT(prAdapter); + + /* Get Nic resource information from FW */ + if (!prChipInfo->isNicCapV1 + || (prAdapter->u4FwFeatureFlag0 & + FEATURE_FLAG0_NIC_CAPABILITY_V2)) { + + DBGLOG(INIT, INFO, "Support NIC_CAPABILITY_V2 feature\n"); + + /* + * send NIC_CAPABILITY_V2 query cmd + */ + + /* 1. Allocate CMD Info Packet and its Buffer */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + prChipInfo->u2CmdTxHdrSize); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, + "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* compose CMD_BUILD_CONNECTION cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = prChipInfo->u2CmdTxHdrSize; + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_GET_NIC_CAPABILITY_V2; + prCmdInfo->fgSetQuery = FALSE; + prCmdInfo->fgNeedResp = TRUE; + prCmdInfo->u4SetInfoLen = 0; + + /* Setup WIFI_CMD_T */ + NIC_FILL_CMD_TX_HDR( + prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + prCmdInfo->ucCID, + CMD_PACKET_TYPE_ID, + &prCmdInfo->ucCmdSeqNum, + prCmdInfo->fgSetQuery, + NULL, FALSE, 0, S2D_INDEX_CMD_H2N); + + wlanSendCommand(prAdapter, prCmdInfo); + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + /* + * receive nic_capability_v2 event + */ + + /* allocate event buffer */ + prEventBuff = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, + CFG_RX_MAX_PKT_SIZE); + if (!prEventBuff) { + DBGLOG(INIT, WARN, "%s: event buffer alloc failed!\n", + __func__); + return WLAN_STATUS_FAILURE; + } + + /* get event */ + u4Time = kalGetTimeTick(); + while (TRUE) { + if (nicRxWaitResponse(prAdapter, + 1, + prEventBuff, + CFG_RX_MAX_PKT_SIZE, + &u4RxPktLength) + != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, WARN, + "%s: wait for event failed!\n", + __func__); + + /* free event buffer */ + cnmMemFree(prAdapter, prEventBuff); + + return WLAN_STATUS_FAILURE; + } + + if (CHECK_FOR_TIMEOUT(kalGetTimeTick(), u4Time, + MSEC_TO_SYSTIME(3000))) { + DBGLOG(HAL, ERROR, + "Query nic capability timeout\n"); + return WLAN_STATUS_FAILURE; + } + + /* header checking .. */ + if ((NIC_RX_GET_U2_SW_PKT_TYPE(prEventBuff) & + prChipInfo->u2RxSwPktBitMap) != + prChipInfo->u2RxSwPktEvent) { + DBGLOG(INIT, WARN, + "%s: skip unexpected Rx pkt type[0x%04x]\n", + __func__, + NIC_RX_GET_U2_SW_PKT_TYPE(prEventBuff)); + + continue; + } + + prEvent = (struct WIFI_EVENT *) + (prEventBuff + prChipInfo->rxd_size); + if (prEvent->ucEID != EVENT_ID_NIC_CAPABILITY_V2) { + DBGLOG(INIT, WARN, + "%s: skip unexpected event ID[0x%02x]\n", + __func__, prEvent->ucEID); + + continue; + } else { + /* hit */ + break; + } + + } + + /* + * parsing elemens + */ + + nicCmdEventQueryNicCapabilityV2(prAdapter, + prEvent->aucBuffer); + + /* + * free event buffer + */ + cnmMemFree(prAdapter, prEventBuff); + } + + /* Fill capability for different Chip version */ + if (chip_id == HQA_CHIP_ID_6632) { + /* 6632 only */ + prAdapter->fgIsSupportBufferBinSize16Byte = TRUE; + prAdapter->fgIsSupportDelayCal = FALSE; + prAdapter->fgIsSupportGetFreeEfuseBlockCount = FALSE; + prAdapter->fgIsSupportQAAccessEfuse = FALSE; + prAdapter->fgIsSupportPowerOnSendBufferModeCMD = FALSE; + prAdapter->fgIsSupportGetTxPower = FALSE; + } else { + prAdapter->fgIsSupportBufferBinSize16Byte = FALSE; + prAdapter->fgIsSupportDelayCal = TRUE; + prAdapter->fgIsSupportGetFreeEfuseBlockCount = TRUE; + prAdapter->fgIsSupportQAAccessEfuse = TRUE; + prAdapter->fgIsSupportPowerOnSendBufferModeCMD = TRUE; + prAdapter->fgIsSupportGetTxPower = TRUE; + } + + return WLAN_STATUS_SUCCESS; +} + +void wlanSetNicResourceParameters(IN struct ADAPTER + *prAdapter) +{ + uint8_t string[128], idx; + uint32_t u4share; + uint32_t u4MaxPageCntPerFrame = + prAdapter->rTxCtrl.u4MaxPageCntPerFrame; + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + struct QUE_MGT *prQM = &prAdapter->rQM; +#endif + + /* + * Use the settings in config file first, + * else, use the settings reported from firmware. + */ + + + /* + * 1. assign free page count for each TC + */ + + /* 1 1. update free page count in TC control: MCU and LMAC */ + prWifiVar->au4TcPageCount[TC4_INDEX] = + prAdapter->nicTxReousrce.u4CmdTotalResource * + u4MaxPageCntPerFrame; /* MCU */ + + u4share = prAdapter->nicTxReousrce.u4DataTotalResource / + (TC_NUM - 1); /* LMAC. Except TC_4, which is MCU */ + for (idx = TC0_INDEX; idx < TC_NUM; idx++) { + if (idx != TC4_INDEX) + prWifiVar->au4TcPageCount[idx] = u4share * + u4MaxPageCntPerFrame; + } + + /* 1 2. if there is remaings, give them to TC_3, which is VO */ + prWifiVar->au4TcPageCount[TC3_INDEX] += + (prAdapter->nicTxReousrce.u4DataTotalResource % + (TC_NUM - 1)) * u4MaxPageCntPerFrame; + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + /* + * 2. assign guaranteed page count for each TC + */ + + /* 2 1. update guaranteed page count in QM */ + for (idx = 0; idx < TC_NUM; idx++) + prQM->au4GuaranteedTcResource[idx] = + prWifiVar->au4TcPageCount[idx]; +#endif + + +#if CFG_SUPPORT_CFG_FILE + /* + * 3. Use the settings in config file first, + * else, use the settings reported from firmware. + */ + + /* 3 1. update for free page count */ + for (idx = 0; idx < TC_NUM; idx++) { + + /* construct prefix: Tc0Page, Tc1Page... */ + memset(string, 0, sizeof(string) / sizeof(uint8_t)); + kalSnprintf(string, sizeof(string) / sizeof(uint8_t), + "Tc%xPage", idx); + + /* update the final value */ + prWifiVar->au4TcPageCount[idx] = + (uint32_t) wlanCfgGetUint32(prAdapter, string, + prWifiVar->au4TcPageCount[idx]); + } + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + /* 3 2. update for guaranteed page count */ + for (idx = 0; idx < TC_NUM; idx++) { + + /* construct prefix: Tc0Grt, Tc1Grt... */ + memset(string, 0, sizeof(string) / sizeof(uint8_t)); + kalSnprintf(string, sizeof(string) / sizeof(uint8_t), + "Tc%xGrt", idx); + + /* update the final value */ + prQM->au4GuaranteedTcResource[idx] = + (uint32_t) wlanCfgGetUint32(prAdapter, string, + prQM->au4GuaranteedTcResource[idx]); + } +#endif /* end of #if QM_ADAPTIVE_TC_RESOURCE_CTRL */ + +#endif /* end of #if CFG_SUPPORT_CFG_FILE */ +} + + +#if CFG_SUPPORT_IOT_AP_BLACKLIST +void wlanCfgDumpIotApRule(IN struct ADAPTER *prAdapter) +{ + uint8_t ucRuleIdx; + struct WLAN_IOT_AP_RULE_T *prIotApRule; + + ASSERT(prAdapter); + for (ucRuleIdx = 0; ucRuleIdx < CFG_IOT_AP_RULE_MAX_CNT; ucRuleIdx++) { + prIotApRule = &prAdapter->rIotApRule[ucRuleIdx]; + if (!prIotApRule->u2MatchFlag) + continue; + DBGLOG(INIT, TRACE, "IOTAP%d is valid rule\n", ucRuleIdx); + DBGLOG(INIT, TRACE, "IOTAP%d Flag:0x%X Ver:0x%X\n", + ucRuleIdx, prIotApRule->u2MatchFlag, + prIotApRule->ucVersion); + DBGLOG(INIT, TRACE, "IOTAP%d OUI:%02X:%02X:%02X\n", + ucRuleIdx, + prIotApRule->aVendorOui[0], + prIotApRule->aVendorOui[1], + prIotApRule->aVendorOui[2]); + DBGLOG(INIT, TRACE, "IOTAP%d Data:"MACSTR" Mask:"MACSTR"\n", + ucRuleIdx, MAC2STR(prIotApRule->aVendorData), + MAC2STR(prIotApRule->aVendorDataMask)); + DBGLOG(INIT, TRACE, "IOTAP%d aBssid:"MACSTR" Mask:"MACSTR"\n", + ucRuleIdx, MAC2STR(prIotApRule->aBssid), + MAC2STR(prIotApRule->aBssidMask)); + DBGLOG(INIT, TRACE, "IOTAP%d NSS:%X HT:%X Band:%X Act:%X\n", + ucRuleIdx, prIotApRule->ucNss, + prIotApRule->ucHtType, + prIotApRule->ucBand, + prIotApRule->ucAction); + } +} + + +void wlanCfgLoadIotApRule(IN struct ADAPTER *prAdapter) +{ + uint8_t ucCnt; + uint8_t *pOffset; + uint8_t *pCurTok; + uint8_t ucTokId; + uint8_t *pNexTok; + uint8_t ucStatus; + uint8_t aucCfgKey[WLAN_CFG_KEY_LEN_MAX]; + uint8_t aucCfgVal[WLAN_CFG_VALUE_LEN_MAX]; + struct WLAN_IOT_AP_RULE_T *prIotApRule = NULL; + int8_t aucEleSize[] = { + sizeof(prIotApRule->ucVersion), + sizeof(prIotApRule->aVendorOui), + sizeof(prIotApRule->aVendorData), + sizeof(prIotApRule->aVendorDataMask), + sizeof(prIotApRule->aBssid), + sizeof(prIotApRule->aBssidMask), + sizeof(prIotApRule->ucNss), + sizeof(prIotApRule->ucHtType), + sizeof(prIotApRule->ucBand), + sizeof(prIotApRule->ucAction) + }; + + ASSERT(prAdapter); + ASSERT(prAdapter->rIotApRule); + + DBGLOG(INIT, INFO, "IOTAP: Start Parsing Rules\n"); + for (ucCnt = 0; ucCnt < CFG_IOT_AP_RULE_MAX_CNT; ucCnt++) { + prIotApRule = &prAdapter->rIotApRule[ucCnt]; + kalMemSet(prIotApRule, '\0', sizeof(struct WLAN_IOT_AP_RULE_T)); + kalMemSet(aucCfgVal, '\0', WLAN_CFG_VALUE_LEN_MAX); + kalMemSet(aucCfgKey, '\0', WLAN_CFG_KEY_LEN_MAX); + pOffset = (uint8_t *)prIotApRule + + OFFSET_OF(struct WLAN_IOT_AP_RULE_T, ucVersion); + pCurTok = &aucCfgVal[0]; + pNexTok = &aucCfgVal[0]; + kalSprintf(aucCfgKey, "IOTAP%d", ucCnt); + ucStatus = wlanCfgGet(prAdapter, aucCfgKey, aucCfgVal, NULL, 0); + /*Skip empty rule*/ + if (ucStatus != WLAN_STATUS_SUCCESS) + continue; + + /*Rule String Check*/ + ucStatus = 0; + while (*pCurTok != '\0') { + if (*pCurTok == ':') + ucStatus++; + else if (wlanHexToNum(*pCurTok) == -1) { + ucStatus = -EINVAL; + break; + } + pCurTok++; + } + if (ucStatus != WLAN_IOT_AP_FG_MAX-1) { + DBGLOG(INIT, INFO, + "Invalid rule IOTAP%d with status %d\n", + ucCnt, ucStatus); + continue; + } + + for (ucTokId = 0; ucTokId < WLAN_IOT_AP_FG_MAX; ucTokId++) { + pCurTok = kalStrSep((char **)&pNexTok, ":"); + if (pCurTok) + ucStatus = wlanHexToArrayR(pCurTok, pOffset, + aucEleSize[ucTokId]); + else { + DBGLOG(INIT, TRACE, + "Invalid Tok IOTAP%d\n", ucCnt); + continue; + } + DBGLOG(INIT, TRACE, + "IOTAP%d tok:%d Str:%s status:%d len:%d flag:0x%x\n", + ucCnt, ucTokId, pCurTok, ucStatus, + aucEleSize[ucTokId], prIotApRule->u2MatchFlag); + + if (ucStatus) { + prIotApRule->u2MatchFlag |= BIT(ucTokId); + /*Record vendor data length*/ + if (ucTokId == WLAN_IOT_AP_FG_DATA) + prIotApRule->ucDataLen = ucStatus; + if (ucTokId == WLAN_IOT_AP_FG_DATA_MASK) + prIotApRule->ucDataMaskLen = ucStatus; + } + pOffset += aucEleSize[ucTokId]; + } + /*Rule Check*/ + if (prIotApRule->ucDataMaskLen && + prIotApRule->ucDataMaskLen != prIotApRule->ucDataLen) + prIotApRule->u2MatchFlag = 0; + if (prIotApRule->ucAction >= WLAN_IOT_AP_ACT_MAX) + prIotApRule->u2MatchFlag = 0; + if (prIotApRule->u2MatchFlag == 0) + DBGLOG(INIT, INFO, "Invalid Rule IOTAP%d\n", ucCnt); + } + +} +#endif + + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is to re-assign tx resource based on firmware's report + * + * @param prAdapter Pointer of Adapter Data Structure + * + * @return WLAN_STATUS_SUCCESS + */ +/*----------------------------------------------------------------------------*/ +void wlanUpdateNicResourceInformation(IN struct ADAPTER + *prAdapter) +{ + /* + * 3 1. Query TX resource + */ + + /* information is not got from firmware, use default value */ + if (prAdapter->fgIsNicTxReousrceValid != TRUE) + return; + + /* 3 2. Setup resource parameters */ + if (prAdapter->nicTxReousrce.txResourceInit) + prAdapter->nicTxReousrce.txResourceInit(prAdapter); + else + wlanSetNicResourceParameters(prAdapter);/* 6632, 7668 ways*/ + + /* 3 3. Reset Tx resource */ + nicTxResetResource(prAdapter); + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + /* 3 4. Reset QM resource */ + qmResetTcControlResource( + prAdapter); /*CHIAHSUAN, TBD, NO PLE YET*/ +#endif + + halTxResourceResetHwTQCounter(prAdapter); +} + + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is to SET network interface index for a network + * interface. + * A network interface is a TX/RX data port hooked to OS. + * + * @param prGlueInfo Pointer of prGlueInfo Data Structure + * @param ucNetInterfaceIndex Index of network interface + * @param ucBssIndex Index of BSS + * + * @return VOID + */ +/*----------------------------------------------------------------------------*/ +void wlanBindNetInterface(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucNetInterfaceIndex, + IN void *pvNetInterface) +{ + struct NET_INTERFACE_INFO *prNetIfInfo; + + prNetIfInfo = + &prGlueInfo->arNetInterfaceInfo[ucNetInterfaceIndex]; + + prNetIfInfo->pvNetInterface = pvNetInterface; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is to SET BSS index for a network interface. + * A network interface is a TX/RX data port hooked to OS. + * + * @param prGlueInfo Pointer of prGlueInfo Data Structure + * @param ucNetInterfaceIndex Index of network interface + * @param ucBssIndex Index of BSS + * + * @return VOID + */ +/*----------------------------------------------------------------------------*/ +void wlanBindBssIdxToNetInterface(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucBssIndex, + IN void *pvNetInterface) +{ + struct NET_INTERFACE_INFO *prNetIfInfo; + + if (ucBssIndex >= prGlueInfo->prAdapter->ucHwBssIdNum) { + DBGLOG(INIT, ERROR, + "Array index out of bound, ucBssIndex=%u\n", ucBssIndex); + return; + } + + DBGLOG(INIT, LOUD, + "ucBssIndex = %d, pvNetInterface = %p\n", + ucBssIndex, pvNetInterface); + + prNetIfInfo = &prGlueInfo->arNetInterfaceInfo[ucBssIndex]; + + prNetIfInfo->ucBssIndex = ucBssIndex; + prNetIfInfo->pvNetInterface = pvNetInterface; + /* prGlueInfo->aprBssIdxToNetInterfaceInfo[ucBssIndex] = prNetIfInfo; */ +} + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is to GET BSS index for a network interface. + * A network interface is a TX/RX data port hooked to OS. + * + * @param prGlueInfo Pointer of prGlueInfo Data Structure + * @param ucNetInterfaceIndex Index of network interface + * + * @return UINT_8 Index of BSS + */ +/*----------------------------------------------------------------------------*/ +uint8_t wlanGetBssIdxByNetInterface(IN struct GLUE_INFO + *prGlueInfo, IN void *pvNetInterface) +{ + uint8_t ucIdx = 0; + + ASSERT(prGlueInfo); + + for (ucIdx = 0; ucIdx < prGlueInfo->prAdapter->ucHwBssIdNum; + ucIdx++) { + if (prGlueInfo->arNetInterfaceInfo[ucIdx].pvNetInterface == + pvNetInterface) + break; + } + + return ucIdx; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is to GET network interface for a BSS. + * A network interface is a TX/RX data port hooked to OS. + * + * @param prGlueInfo Pointer of prGlueInfo Data Structure + * @param ucBssIndex Index of BSS + * + * @return PVOID pointer of network interface structure + */ +/*----------------------------------------------------------------------------*/ +void *wlanGetNetInterfaceByBssIdx(IN struct GLUE_INFO + *prGlueInfo, IN uint8_t ucBssIndex) +{ + return prGlueInfo->arNetInterfaceInfo[ucBssIndex].pvNetInterface; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is to initialize WLAN feature options + * + * @param prAdapter Pointer of ADAPTER_T + * + * @return none + */ +/*----------------------------------------------------------------------------*/ +void wlanInitFeatureOption(IN struct ADAPTER *prAdapter) +{ + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + struct QUE_MGT *prQM = &prAdapter->rQM; +#endif + uint32_t u4TxHifRes = 0, u4Idx = 0; + uint32_t u4PlatformBoostCpuTh = 1; + + /* Feature options will be filled by config file */ + + prWifiVar->fgEnDefaultIotApRule = (uint8_t) wlanCfgGetUint32(prAdapter, + "EnDefaultIotApRule", + FEATURE_ENABLED); + + prWifiVar->ucQoS = (uint8_t) wlanCfgGetUint32(prAdapter, "Qos", + FEATURE_ENABLED); + + prWifiVar->ucStaHt = (uint8_t) wlanCfgGetUint32(prAdapter, "StaHT", + FEATURE_ENABLED); + prWifiVar->ucStaVht = (uint8_t) wlanCfgGetUint32(prAdapter, "StaVHT", + FEATURE_ENABLED); + +#if (CFG_SUPPORT_802_11AX == 1) + if (fgEfuseCtrlAxOn == 1) { + prWifiVar->ucStaHe = (uint8_t) + wlanCfgGetUint32(prAdapter, "StaHE", FEATURE_ENABLED); + prWifiVar->ucApHe = (uint8_t) + wlanCfgGetUint32(prAdapter, "ApHE", FEATURE_ENABLED); + prWifiVar->ucP2pGoHe = (uint8_t) + wlanCfgGetUint32(prAdapter, "P2pGoHE", + FEATURE_DISABLED); + prWifiVar->ucP2pGcHe = (uint8_t) + wlanCfgGetUint32(prAdapter, "P2pGcHE", + FEATURE_DISABLED); + + prWifiVar->ucApSelAxWeight = (uint8_t) + wlanCfgGetUint32(prAdapter, "ApSelAxWeight", AX_SEL_DEF_WEIGHT); + + prWifiVar->ucApSelAxScoreDiv = (uint8_t) + wlanCfgGetUint32(prAdapter, "ApSelAxScoreDiv", + AX_SEL_DEF_DIVIDER); + } +#endif + + prWifiVar->ucApHt = (uint8_t) wlanCfgGetUint32(prAdapter, "ApHT", + FEATURE_ENABLED); +#if CFG_TC1_FEATURE + prWifiVar->ucApVht = (uint8_t) wlanCfgGetUint32(prAdapter, "ApVHT", + FEATURE_FORCE_ENABLED); +#else + prWifiVar->ucApVht = (uint8_t) wlanCfgGetUint32(prAdapter, "ApVHT", + FEATURE_ENABLED); +#endif + + prWifiVar->ucP2pGoHt = (uint8_t) wlanCfgGetUint32(prAdapter, "P2pGoHT", + FEATURE_ENABLED); + prWifiVar->ucP2pGoVht = (uint8_t) wlanCfgGetUint32(prAdapter, + "P2pGoVHT", FEATURE_ENABLED); + + prWifiVar->ucP2pGcHt = (uint8_t) wlanCfgGetUint32(prAdapter, "P2pGcHT", + FEATURE_ENABLED); + prWifiVar->ucP2pGcVht = (uint8_t) wlanCfgGetUint32(prAdapter, + "P2pGcVHT", FEATURE_ENABLED); + + prWifiVar->ucAmpduRx = (uint8_t) wlanCfgGetUint32(prAdapter, "AmpduRx", + FEATURE_ENABLED); + prWifiVar->ucAmpduTx = (uint8_t) wlanCfgGetUint32(prAdapter, "AmpduTx", + FEATURE_ENABLED); + + prWifiVar->ucAmsduInAmpduRx = (uint8_t) wlanCfgGetUint32(prAdapter, + "AmsduInAmpduRx", FEATURE_ENABLED); + prWifiVar->ucAmsduInAmpduTx = (uint8_t) wlanCfgGetUint32(prAdapter, + "AmsduInAmpduTx", FEATURE_ENABLED); + prWifiVar->ucHtAmsduInAmpduRx = (uint8_t) wlanCfgGetUint32(prAdapter, + "HtAmsduInAmpduRx", FEATURE_ENABLED); + prWifiVar->ucHtAmsduInAmpduTx = (uint8_t) wlanCfgGetUint32(prAdapter, + "HtAmsduInAmpduTx", FEATURE_ENABLED); + prWifiVar->ucVhtAmsduInAmpduRx = (uint8_t) wlanCfgGetUint32(prAdapter, + "VhtAmsduInAmpduRx", FEATURE_ENABLED); + prWifiVar->ucVhtAmsduInAmpduTx = (uint8_t) wlanCfgGetUint32(prAdapter, + "VhtAmsduInAmpduTx", FEATURE_ENABLED); + + prWifiVar->ucTspec = (uint8_t) wlanCfgGetUint32(prAdapter, "Tspec", + FEATURE_DISABLED); + + prWifiVar->ucUapsd = (uint8_t) wlanCfgGetUint32(prAdapter, "Uapsd", + FEATURE_ENABLED); + prWifiVar->ucStaUapsd = (uint8_t) wlanCfgGetUint32(prAdapter, + "StaUapsd", FEATURE_DISABLED); + prWifiVar->ucApUapsd = (uint8_t) wlanCfgGetUint32(prAdapter, + "ApUapsd", FEATURE_DISABLED); + prWifiVar->ucP2pUapsd = (uint8_t) wlanCfgGetUint32(prAdapter, + "P2pUapsd", FEATURE_ENABLED); +#if (CFG_ENABLE_WIFI_DIRECT && CFG_MTK_ANDROID_WMT) + prWifiVar->u4RegP2pIfAtProbe = (uint8_t) wlanCfgGetUint32(prAdapter, + "RegP2pIfAtProbe", FEATURE_ENABLED); +#else + prWifiVar->u4RegP2pIfAtProbe = (uint8_t) wlanCfgGetUint32(prAdapter, + "RegP2pIfAtProbe", FEATURE_DISABLED); +#endif + prWifiVar->ucP2pShareMacAddr = (uint8_t) wlanCfgGetUint32(prAdapter, + "P2pShareMacAddr", FEATURE_DISABLED); + + prWifiVar->ucTxShortGI = (uint8_t) wlanCfgGetUint32(prAdapter, "SgiTx", + FEATURE_ENABLED); + prWifiVar->ucRxShortGI = (uint8_t) wlanCfgGetUint32(prAdapter, "SgiRx", + FEATURE_ENABLED); + + prWifiVar->ucTxLdpc = (uint8_t) wlanCfgGetUint32(prAdapter, "LdpcTx", + FEATURE_ENABLED); + prWifiVar->ucRxLdpc = (uint8_t) wlanCfgGetUint32(prAdapter, "LdpcRx", + FEATURE_ENABLED); + + prWifiVar->ucTxStbc = (uint8_t) wlanCfgGetUint32(prAdapter, "StbcTx", + FEATURE_ENABLED); + prWifiVar->ucRxStbc = (uint8_t) wlanCfgGetUint32(prAdapter, "StbcRx", + FEATURE_ENABLED); + prWifiVar->ucRxStbcNss = (uint8_t) wlanCfgGetUint32(prAdapter, + "StbcRxNss", 1); + + prWifiVar->ucTxGf = (uint8_t) wlanCfgGetUint32(prAdapter, "GfTx", + FEATURE_ENABLED); + prWifiVar->ucRxGf = (uint8_t) wlanCfgGetUint32(prAdapter, "GfRx", + FEATURE_ENABLED); + + prWifiVar->ucMCS32 = (uint8_t) wlanCfgGetUint32(prAdapter, "MCS32", + FEATURE_ENABLED); + +#if (CFG_SUPPORT_802_11AX == 1) + if (fgEfuseCtrlAxOn == 1) { + prWifiVar->ucHeAmsduInAmpduRx = (uint8_t) wlanCfgGetUint32(prAdapter, + "HeAmsduInAmpduRx", FEATURE_ENABLED); + prWifiVar->ucHeAmsduInAmpduTx = (uint8_t) wlanCfgGetUint32(prAdapter, + "HeAmsduInAmpduTx", FEATURE_ENABLED); + prWifiVar->ucTrigMacPadDur = (uint8_t) wlanCfgGetUint32(prAdapter, + "TrigMacPadDur", HE_CAP_TRIGGER_PAD_DURATION_16); + } +#endif + +#if (CFG_SUPPORT_TWT == 1) + prWifiVar->ucTWTRequester = (uint8_t) + wlanCfgGetUint32(prAdapter, "TWTRequester", FEATURE_ENABLED); + prWifiVar->ucTWTResponder = (uint8_t) + wlanCfgGetUint32(prAdapter, "TWTResponder", FEATURE_DISABLED); + prWifiVar->ucTWTStaBandBitmap = (uint8_t) + wlanCfgGetUint32(prAdapter, + "TWTStaBandBitmap", + BAND_2G4|BAND_5G); +#endif + + prWifiVar->ucSigTaRts = (uint8_t) wlanCfgGetUint32(prAdapter, + "SigTaRts", FEATURE_DISABLED); + prWifiVar->ucDynBwRts = (uint8_t) wlanCfgGetUint32(prAdapter, + "DynBwRts", FEATURE_DISABLED); + prWifiVar->ucTxopPsTx = (uint8_t) wlanCfgGetUint32(prAdapter, + "TxopPsTx", FEATURE_DISABLED); + + prWifiVar->ucStaHtBfee = (uint8_t) wlanCfgGetUint32(prAdapter, + "StaHTBfee", FEATURE_DISABLED); + prWifiVar->ucStaVhtBfee = (uint8_t) wlanCfgGetUint32(prAdapter, + "StaVHTBfee", FEATURE_ENABLED); + prWifiVar->ucStaVhtMuBfee = (uint8_t)wlanCfgGetUint32(prAdapter, + "StaVHTMuBfee", FEATURE_ENABLED); + prWifiVar->ucStaHtBfer = (uint8_t) wlanCfgGetUint32(prAdapter, + "StaHTBfer", FEATURE_DISABLED); + prWifiVar->ucStaVhtBfer = (uint8_t) wlanCfgGetUint32(prAdapter, + "StaVHTBfer", FEATURE_DISABLED); + +#if (CFG_SUPPORT_802_11AX == 1) + if (fgEfuseCtrlAxOn == 1) { + prWifiVar->ucStaHeBfee = (uint8_t) wlanCfgGetUint32(prAdapter, + "StaHEBfee", FEATURE_ENABLED); + } +#endif + + /* 0: disabled + * 1: Tx done event to driver + * 2: Tx status to FW only + */ + prWifiVar->ucDataTxDone = (uint8_t) wlanCfgGetUint32( + prAdapter, "DataTxDone", 0); + prWifiVar->ucDataTxRateMode = (uint8_t) wlanCfgGetUint32( + prAdapter, "DataTxRateMode", + DATA_RATE_MODE_AUTO); + prWifiVar->u4DataTxRateCode = wlanCfgGetUint32( + prAdapter, "DataTxRateCode", 0x0); + + prWifiVar->ucApWpsMode = (uint8_t) wlanCfgGetUint32( + prAdapter, "ApWpsMode", 0); + DBGLOG(INIT, TRACE, "ucApWpsMode = %u\n", prWifiVar->ucApWpsMode); + + prWifiVar->ucThreadScheduling = (uint8_t) wlanCfgGetUint32( + prAdapter, "ThreadSched", 0); + prWifiVar->ucThreadPriority = (uint8_t) wlanCfgGetUint32( + prAdapter, "ThreadPriority", + WLAN_THREAD_TASK_PRIORITY); + prWifiVar->cThreadNice = (int8_t) wlanCfgGetInt32( + prAdapter, "ThreadNice", + WLAN_THREAD_TASK_NICE); + + prAdapter->rQM.u4MaxForwardBufferCount = (uint32_t) wlanCfgGetUint32( + prAdapter, "ApForwardBufferCnt", + QM_FWD_PKT_QUE_THRESHOLD); + + /* AP channel setting + * 0: auto + */ + prWifiVar->ucApChannel = (uint8_t) wlanCfgGetUint32( + prAdapter, "ApChannel", 0); + + /* + * 0: SCN + * 1: SCA + * 2: RES + * 3: SCB + */ + prWifiVar->ucApSco = (uint8_t) wlanCfgGetUint32( + prAdapter, "ApSco", 0); + prWifiVar->ucP2pGoSco = (uint8_t) wlanCfgGetUint32( + prAdapter, "P2pGoSco", 0); + + /* Max bandwidth setting + * 0: 20Mhz + * 1: 40Mhz + * 2: 80Mhz + * 3: 160Mhz + * 4: 80+80Mhz + * Note: For VHT STA, BW 80Mhz is a must! + */ + prWifiVar->ucStaBandwidth = (uint8_t) wlanCfgGetUint32( + prAdapter, "StaBw", MAX_BW_160MHZ); + prWifiVar->ucSta2gBandwidth = (uint8_t) wlanCfgGetUint32( + prAdapter, "Sta2gBw", MAX_BW_20MHZ); + prWifiVar->ucSta5gBandwidth = (uint8_t) wlanCfgGetUint32( + prAdapter, "Sta5gBw", MAX_BW_80MHZ); + /* GC,GO */ + prWifiVar->ucP2p2gBandwidth = (uint8_t) wlanCfgGetUint32( + prAdapter, "P2p2gBw", MAX_BW_20MHZ); + prWifiVar->ucP2p5gBandwidth = (uint8_t) wlanCfgGetUint32( + prAdapter, "P2p5gBw", MAX_BW_80MHZ); + prWifiVar->ucApBandwidth = (uint8_t) wlanCfgGetUint32( + prAdapter, "ApBw", MAX_BW_160MHZ); + prWifiVar->ucAp2gBandwidth = (uint8_t) wlanCfgGetUint32( + prAdapter, "Ap2gBw", MAX_BW_20MHZ); + prWifiVar->ucAp5gBandwidth = (uint8_t) wlanCfgGetUint32( + prAdapter, "Ap5gBw", MAX_BW_80MHZ); + prWifiVar->ucApChnlDefFromCfg = (uint8_t) wlanCfgGetUint32( + prAdapter, "ApChnlDefFromCfg", FEATURE_ENABLED); + prWifiVar->ucApAllowHtVhtTkip = (uint8_t) wlanCfgGetUint32( + prAdapter, "ApAllowHtVhtTkip", + FEATURE_DISABLED); + + prWifiVar->ucNSS = (uint8_t) wlanCfgGetUint32 + (prAdapter, "Nss", 2); +#ifdef CFG_FORCE_AP1NSS + prWifiVar->ucAp5gNSS = (uint8_t)wlanCfgGetUint32 + (prAdapter, "Ap5gNss", 1); + prWifiVar->ucAp2gNSS = (uint8_t) wlanCfgGetUint32 + (prAdapter, "Ap2gNss", 1); +#else + prWifiVar->ucAp5gNSS = (uint8_t)wlanCfgGetUint32 + (prAdapter, "Ap5gNss", 2); + prWifiVar->ucAp2gNSS = (uint8_t) wlanCfgGetUint32 + (prAdapter, "Ap2gNss", 2); +#endif + prWifiVar->ucGo5gNSS = (uint8_t) wlanCfgGetUint32 + (prAdapter, "Go5gNss", 2); + prWifiVar->ucGo2gNSS = (uint8_t) wlanCfgGetUint32 + (prAdapter, "Go2gNss", 2); + + /* Max Rx MPDU length setting + * 0: 3k + * 1: 8k + * 2: 11k + */ + prWifiVar->ucRxMaxMpduLen = (uint8_t) wlanCfgGetUint32( + prAdapter, "RxMaxMpduLen", + VHT_CAP_INFO_MAX_MPDU_LEN_3K); + /* Max Tx AMSDU in AMPDU length *in BYTES* */ + prWifiVar->u4TxMaxAmsduInAmpduLen = wlanCfgGetUint32( + prAdapter, "TxMaxAmsduInAmpduLen", + 8192); + + prWifiVar->ucTcRestrict = (uint8_t) wlanCfgGetUint32( + prAdapter, "TcRestrict", 0xFF); + /* Max Tx dequeue limit: 0 => auto */ + prWifiVar->u4MaxTxDeQLimit = (uint32_t) wlanCfgGetUint32( + prAdapter, "MaxTxDeQLimit", 0x0); + prWifiVar->ucAlwaysResetUsedRes = (uint32_t) wlanCfgGetUint32( + prAdapter, "AlwaysResetUsedRes", 0x0); + +#if CFG_SUPPORT_MTK_SYNERGY + prWifiVar->ucMtkOui = (uint8_t) wlanCfgGetUint32( + prAdapter, "MtkOui", FEATURE_ENABLED); + prWifiVar->u4MtkOuiCap = (uint32_t) wlanCfgGetUint32( + prAdapter, "MtkOuiCap", 0); + prWifiVar->aucMtkFeature[0] = 0xff; + prWifiVar->aucMtkFeature[1] = 0xff; + prWifiVar->aucMtkFeature[2] = 0xff; + prWifiVar->aucMtkFeature[3] = 0xff; + prWifiVar->ucGbandProbe256QAM = (uint8_t) wlanCfgGetUint32( + prAdapter, "Probe256QAM", + FEATURE_ENABLED); +#endif +#if CFG_SUPPORT_VHT_IE_IN_2G + prWifiVar->ucVhtIeIn2g = (uint8_t) wlanCfgGetUint32( + prAdapter, "VhtIeIn2G", FEATURE_ENABLED); +#endif + prWifiVar->ucCmdRsvResource = (uint8_t) wlanCfgGetUint32( + prAdapter, "TxCmdRsv", + QM_CMD_RESERVED_THRESHOLD); + prWifiVar->u4MgmtQueueDelayTimeout = + (uint32_t) wlanCfgGetUint32(prAdapter, "TxMgmtQueTO", + QM_MGMT_QUEUED_TIMEOUT); /* ms */ + + /* Performance related */ + prWifiVar->u4HifIstLoopCount = (uint32_t) wlanCfgGetUint32( + prAdapter, "IstLoop", + CFG_IST_LOOP_COUNT); + prWifiVar->u4Rx2OsLoopCount = (uint32_t) wlanCfgGetUint32( + prAdapter, "Rx2OsLoop", 4); + prWifiVar->u4HifTxloopCount = (uint32_t) wlanCfgGetUint32( + prAdapter, "HifTxLoop", 1); + prWifiVar->u4TxFromOsLoopCount = (uint32_t) wlanCfgGetUint32( + prAdapter, "OsTxLoop", 1); + prWifiVar->u4TxRxLoopCount = (uint32_t) wlanCfgGetUint32( + prAdapter, "Rx2ReorderLoop", 1); + prWifiVar->u4TxIntThCount = (uint32_t) wlanCfgGetUint32( + prAdapter, "IstTxTh", + HIF_IST_TX_THRESHOLD); + + prWifiVar->u4NetifStopTh = (uint32_t) wlanCfgGetUint32( + prAdapter, "NetifStopTh", + CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD); + prWifiVar->u4NetifStartTh = (uint32_t) wlanCfgGetUint32( + prAdapter, "NetifStartTh", + CFG_TX_START_NETIF_PER_QUEUE_THRESHOLD); + prWifiVar->ucTxBaSize = (uint8_t) wlanCfgGetUint32( + prAdapter, "TxBaSize", 64); + prWifiVar->ucRxHtBaSize = (uint8_t) wlanCfgGetUint32( + prAdapter, "RxHtBaSize", 64); + prWifiVar->ucRxVhtBaSize = (uint8_t) wlanCfgGetUint32( + prAdapter, "RxVhtBaSize", 64); +#if (CFG_SUPPORT_802_11AX == 1) + if (fgEfuseCtrlAxOn == 1) { + prWifiVar->u2RxHeBaSize = (uint8_t) + wlanCfgGetUint32(prAdapter, "RxHeBaSize", 256); + prWifiVar->u2TxHeBaSize = (uint8_t) + wlanCfgGetUint32(prAdapter, "TxHeBaSize", 256); + } +#endif + +#if CFG_SUPPORT_SMART_GEAR + prWifiVar->ucSGCfg = (uint8_t) wlanCfgGetUint32( + prAdapter, "SGCfg", FEATURE_ENABLED); + /* 2.4G default is WF0 when enable SG SISO mode*/ + prWifiVar->ucSG24GFavorANT = (uint8_t) wlanCfgGetUint32( + prAdapter, "SG24GFavorANT", + FEATURE_DISABLED); + /* 5G default is WF1 when enable SG SISO mode*/ + prWifiVar->ucSG5GFavorANT = (uint8_t) wlanCfgGetUint32( + prAdapter, "SG5GFavorANT", + FEATURE_ENABLED); +#endif + /* Tx Buffer Management */ + prWifiVar->ucExtraTxDone = (uint32_t) wlanCfgGetUint32( + prAdapter, "ExtraTxDone", 1); + prWifiVar->ucTxDbg = (uint32_t) wlanCfgGetUint32(prAdapter, "TxDbg", 0); + + kalMemZero(prWifiVar->au4TcPageCount, + sizeof(prWifiVar->au4TcPageCount)); + + prWifiVar->au4TcPageCount[TC0_INDEX] = (uint32_t) wlanCfgGetUint32( + prAdapter, "Tc0Page", + NIC_TX_PAGE_COUNT_TC0); + prWifiVar->au4TcPageCount[TC1_INDEX] = (uint32_t) wlanCfgGetUint32( + prAdapter, "Tc1Page", + NIC_TX_PAGE_COUNT_TC1); + prWifiVar->au4TcPageCount[TC2_INDEX] = (uint32_t) wlanCfgGetUint32( + prAdapter, "Tc2Page", + NIC_TX_PAGE_COUNT_TC2); + prWifiVar->au4TcPageCount[TC3_INDEX] = (uint32_t) wlanCfgGetUint32( + prAdapter, "Tc3Page", + NIC_TX_PAGE_COUNT_TC3); + prWifiVar->au4TcPageCount[TC4_INDEX] = (uint32_t) wlanCfgGetUint32( + prAdapter, "Tc4Page", + NIC_TX_PAGE_COUNT_TC4); + prWifiVar->ucTxMsduQueue = (uint32_t) wlanCfgGetUint32( + prAdapter, "NicTxMsduQueue", 0); + + prWifiVar->ucTxMsduQueueInit = prWifiVar->ucTxMsduQueue; + + /* 1 resource for AC_BK(TC0_INDEX), AC_BE(TC1_INDEX) */ + /* 2 resource for AC_VI(TC2_INDEX) */ + /* 4 resource for AC_VO(TC3_INDEX) */ + /* 1 resource for MGMT(TC4_INDEX) & TC_NUM */ + u4TxHifRes = (uint32_t) wlanCfgGetUint32( + prAdapter, "TxHifResCtl", 0x00114211); + prWifiVar->u4TxHifRes = u4TxHifRes; + for (u4Idx = 0; u4Idx < TX_PORT_NUM && u4TxHifRes; u4Idx++) { + prAdapter->au4TxHifResCtl[u4Idx] = u4TxHifRes & BITS(0, 3); + u4TxHifRes = u4TxHifRes >> 4; + } + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + prQM->au4MinReservedTcResource[TC0_INDEX] = (uint32_t) wlanCfgGetUint32( + prAdapter, "Tc0MinRsv", + QM_MIN_RESERVED_TC0_RESOURCE); + prQM->au4MinReservedTcResource[TC1_INDEX] = (uint32_t) wlanCfgGetUint32( + prAdapter, "Tc1MinRsv", + QM_MIN_RESERVED_TC1_RESOURCE); + prQM->au4MinReservedTcResource[TC2_INDEX] = (uint32_t) wlanCfgGetUint32( + prAdapter, "Tc2MinRsv", + QM_MIN_RESERVED_TC2_RESOURCE); + prQM->au4MinReservedTcResource[TC3_INDEX] = (uint32_t) wlanCfgGetUint32( + prAdapter, "Tc3MinRsv", + QM_MIN_RESERVED_TC3_RESOURCE); + prQM->au4MinReservedTcResource[TC4_INDEX] = (uint32_t) wlanCfgGetUint32( + prAdapter, "Tc4MinRsv", + QM_MIN_RESERVED_TC4_RESOURCE); + + prQM->au4GuaranteedTcResource[TC0_INDEX] = (uint32_t) wlanCfgGetUint32( + prAdapter, "Tc0Grt", + QM_GUARANTEED_TC0_RESOURCE); + prQM->au4GuaranteedTcResource[TC1_INDEX] = + (uint32_t) wlanCfgGetUint32(prAdapter, "Tc1Grt", + QM_GUARANTEED_TC1_RESOURCE); + prQM->au4GuaranteedTcResource[TC2_INDEX] = + (uint32_t) wlanCfgGetUint32(prAdapter, "Tc2Grt", + QM_GUARANTEED_TC2_RESOURCE); + prQM->au4GuaranteedTcResource[TC3_INDEX] = (uint32_t) wlanCfgGetUint32( + prAdapter, "Tc3Grt", + QM_GUARANTEED_TC3_RESOURCE); + prQM->au4GuaranteedTcResource[TC4_INDEX] = (uint32_t) wlanCfgGetUint32( + prAdapter, "Tc4Grt", + QM_GUARANTEED_TC4_RESOURCE); + + prQM->u4TimeToAdjustTcResource = (uint32_t) wlanCfgGetUint32( + prAdapter, "TcAdjustTime", + QM_INIT_TIME_TO_ADJUST_TC_RSC); + prQM->u4TimeToUpdateQueLen = (uint32_t) wlanCfgGetUint32( + prAdapter, "QueLenUpdateTime", + QM_INIT_TIME_TO_UPDATE_QUE_LEN); + prQM->u4QueLenMovingAverage = (uint32_t) wlanCfgGetUint32( + prAdapter, "QueLenMovingAvg", + QM_QUE_LEN_MOVING_AVE_FACTOR); + prQM->u4ExtraReservedTcResource = (uint32_t) wlanCfgGetUint32( + prAdapter, "TcExtraRsv", + QM_EXTRA_RESERVED_RESOURCE_WHEN_BUSY); +#endif + + /* Stats log */ + prWifiVar->u4StatsLogTimeout = (uint32_t) wlanCfgGetUint32( + prAdapter, "StatsLogTO", + WLAN_TX_STATS_LOG_TIMEOUT); + prWifiVar->u4StatsLogDuration = (uint32_t) wlanCfgGetUint32( + prAdapter, "StatsLogDur", + WLAN_TX_STATS_LOG_DURATION); + + prWifiVar->ucDhcpTxDone = (uint8_t) wlanCfgGetUint32( + prAdapter, "DhcpTxDone", 1); + prWifiVar->ucArpTxDone = (uint8_t) wlanCfgGetUint32( + prAdapter, "ArpTxDone", 1); + + prWifiVar->ucMacAddrOverride = (uint8_t) wlanCfgGetInt32( + prAdapter, "MacOverride", 0); + if (wlanCfgGet(prAdapter, "MacAddr", prWifiVar->aucMacAddrStr, + "00:0c:e7:66:32:e1", 0)) + DBGLOG(INIT, TRACE, "get MacAddr fail, use defaul\n"); + + prWifiVar->ucCtiaMode = (uint8_t) wlanCfgGetUint32( + prAdapter, "CtiaMode", 0); + + /* Combine ucTpTestMode and ucSigmaTestMode in one flag */ + /* ucTpTestMode == 0, for normal driver */ + /* ucTpTestMode == 1, for pure throughput test mode (ex: RvR) */ + /* ucTpTestMode == 2, for sigma TGn/TGac/PMF */ + /* ucTpTestMode == 3, for sigma WMM PS */ + prWifiVar->ucTpTestMode = (uint8_t) wlanCfgGetUint32( + prAdapter, "TpTestMode", 0); + +#if 0 + prWifiVar->ucSigmaTestMode = (uint8_t) wlanCfgGetUint32( + prAdapter, "SigmaTestMode", 0); +#endif + +#if CFG_SUPPORT_DBDC + prWifiVar->eDbdcMode = (uint8_t) wlanCfgGetUint32( + prAdapter, "DbdcMode", + ENUM_DBDC_MODE_DYNAMIC); +#endif /*CFG_SUPPORT_DBDC*/ +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1) + prWifiVar->ucEfuseBufferModeCal = (uint8_t) wlanCfgGetUint32( + prAdapter, "EfuseBufferModeCal", 0); +#endif + prWifiVar->ucCalTimingCtrl = (uint8_t) wlanCfgGetUint32( + prAdapter, "CalTimingCtrl", + 0 /* power on full cal */); + prWifiVar->ucWow = (uint8_t) wlanCfgGetUint32( + prAdapter, "Wow", FEATURE_DISABLED); + prWifiVar->ucOffload = (uint8_t) wlanCfgGetUint32( + prAdapter, "Offload", FEATURE_DISABLED); + prWifiVar->ucAdvPws = (uint8_t) wlanCfgGetUint32( + prAdapter, "AdvPws", FEATURE_ENABLED); + prWifiVar->ucWowOnMdtim = (uint8_t) wlanCfgGetUint32( + prAdapter, "WowOnMdtim", 1); + prWifiVar->ucWowOffMdtim = (uint8_t) wlanCfgGetUint32( + prAdapter, "WowOffMdtim", 3); + +#if CFG_WOW_SUPPORT + prAdapter->rWowCtrl.fgWowEnable = (uint8_t) wlanCfgGetUint32( + prAdapter, "WowEnable", + FEATURE_ENABLED); + prAdapter->rWowCtrl.ucScenarioId = (uint8_t) wlanCfgGetUint32( + prAdapter, "WowScenarioId", 0); + prAdapter->rWowCtrl.ucBlockCount = (uint8_t) wlanCfgGetUint32( + prAdapter, "WowPinCnt", 1); + prAdapter->rWowCtrl.astWakeHif[0].ucWakeupHif = + (uint8_t) wlanCfgGetUint32( + prAdapter, "WowHif", + ENUM_HIF_TYPE_GPIO); + prAdapter->rWowCtrl.astWakeHif[0].ucGpioPin = + (uint8_t) wlanCfgGetUint32(prAdapter, "WowGpioPin", 0xFF); + prAdapter->rWowCtrl.astWakeHif[0].ucTriggerLvl = + (uint8_t) wlanCfgGetUint32(prAdapter, "WowTriigerLevel", 3); + prAdapter->rWowCtrl.astWakeHif[0].u4GpioInterval = + wlanCfgGetUint32(prAdapter, "GpioInterval", 0); +#endif + + /* SW Test Mode: Mainly used for Sigma */ + prWifiVar->u4SwTestMode = (uint8_t) wlanCfgGetUint32( + prAdapter, "SwTestMode", + ENUM_SW_TEST_MODE_NONE); + prWifiVar->ucCtrlFlagAssertPath = (uint8_t) wlanCfgGetUint32( + prAdapter, "AssertPath", + DBG_ASSERT_PATH_DEFAULT); + prWifiVar->ucCtrlFlagDebugLevel = (uint8_t) wlanCfgGetUint32( + prAdapter, "AssertLevel", + DBG_ASSERT_CTRL_LEVEL_DEFAULT); + prWifiVar->u4ScanCtrl = (uint8_t) wlanCfgGetUint32( + prAdapter, "ScanCtrl", + SCN_CTRL_DEFAULT_SCAN_CTRL); + prWifiVar->ucScanChannelListenTime = (uint8_t) wlanCfgGetUint32( + prAdapter, "ScnChListenTime", 0); + + /* Wake lock related configuration */ + prWifiVar->u4WakeLockRxTimeout = wlanCfgGetUint32( + prAdapter, "WakeLockRxTO", + WAKE_LOCK_RX_TIMEOUT); + prWifiVar->u4WakeLockThreadWakeup = wlanCfgGetUint32( + prAdapter, "WakeLockThreadTO", + WAKE_LOCK_THREAD_WAKEUP_TIMEOUT); + + prWifiVar->ucSmartRTS = (uint8_t) wlanCfgGetUint32( + prAdapter, "SmartRTS", 0); + prWifiVar->ePowerMode = (enum PARAM_POWER_MODE) wlanCfgGetUint32( + prAdapter, "PowerSave", + Param_PowerModeMax); + +#if 1 + /* add more cfg from RegInfo */ + prWifiVar->u4UapsdAcBmp = (uint32_t) wlanCfgGetUint32( + prAdapter, "UapsdAcBmp", 0); + prWifiVar->u4MaxSpLen = (uint32_t) wlanCfgGetUint32( + prAdapter, "MaxSpLen", 0); + prWifiVar->fgDisOnlineScan = (uint32_t) wlanCfgGetUint32( + prAdapter, "DisOnlineScan", 0); + prWifiVar->fgDisBcnLostDetection = (uint32_t) wlanCfgGetUint32( + prAdapter, "DisBcnLostDetection", 0); + prWifiVar->fgDisRoaming = (uint32_t) wlanCfgGetUint32( + prAdapter, "DisRoaming", 0); + prWifiVar->u4AisRoamingNumber = (uint32_t) wlanCfgGetUint32( + prAdapter, "AisRoamingNumber", + KAL_AIS_NUM); + prWifiVar->fgEnArpFilter = (uint32_t) wlanCfgGetUint32( + prAdapter, "EnArpFilter", + FEATURE_ENABLED); +#endif + + /* Driver Flow Control Dequeue Quota. Now is only used by DBDC */ + prWifiVar->uDeQuePercentEnable = + (uint8_t) wlanCfgGetUint32(prAdapter, "DeQuePercentEnable", 1); + prWifiVar->u4DeQuePercentVHT80Nss1 = + (uint32_t) wlanCfgGetUint32(prAdapter, "DeQuePercentVHT80NSS1", + QM_DEQUE_PERCENT_VHT80_NSS1); + prWifiVar->u4DeQuePercentVHT40Nss1 = + (uint32_t) wlanCfgGetUint32(prAdapter, "DeQuePercentVHT40NSS1", + QM_DEQUE_PERCENT_VHT40_NSS1); + prWifiVar->u4DeQuePercentVHT20Nss1 = + (uint32_t) wlanCfgGetUint32(prAdapter, "DeQuePercentVHT20NSS1", + QM_DEQUE_PERCENT_VHT20_NSS1); + prWifiVar->u4DeQuePercentHT40Nss1 = + (uint32_t) wlanCfgGetUint32(prAdapter, "DeQuePercentHT40NSS1", + QM_DEQUE_PERCENT_HT40_NSS1); + prWifiVar->u4DeQuePercentHT20Nss1 = + (uint32_t) wlanCfgGetUint32(prAdapter, "DeQuePercentHT20NSS1", + QM_DEQUE_PERCENT_HT20_NSS1); + + /* Support TDLS 5.5.4.2 optional case */ + prWifiVar->fgTdlsBufferSTASleep = (u_int8_t) wlanCfgGetUint32(prAdapter, + "TdlsBufferSTASleep", FEATURE_DISABLED); + /* Support USB Whole chip reset recover */ + prWifiVar->fgChipResetRecover = (u_int8_t) wlanCfgGetUint32(prAdapter, + "ChipResetRecover", FEATURE_DISABLED); + + prWifiVar->u4PerfMonUpdatePeriod = + (uint32_t) wlanCfgGetUint32(prAdapter, "PerfMonPeriod", + PERF_MON_UPDATE_INTERVAL); + + prWifiVar->u4PerfMonTpTh[0] = + (uint32_t) wlanCfgGetUint32(prAdapter, "PerfMonLv1", 20); + prWifiVar->u4PerfMonTpTh[1] = + (uint32_t) wlanCfgGetUint32(prAdapter, "PerfMonLv2", 50); + prWifiVar->u4PerfMonTpTh[2] = + (uint32_t) wlanCfgGetUint32(prAdapter, "PerfMonLv3", 100); + prWifiVar->u4PerfMonTpTh[3] = + (uint32_t) wlanCfgGetUint32(prAdapter, "PerfMonLv4", 180); + prWifiVar->u4PerfMonTpTh[4] = + (uint32_t) wlanCfgGetUint32(prAdapter, "PerfMonLv5", 250); + prWifiVar->u4PerfMonTpTh[5] = + (uint32_t) wlanCfgGetUint32(prAdapter, "PerfMonLv6", 300); + prWifiVar->u4PerfMonTpTh[6] = + (uint32_t) wlanCfgGetUint32(prAdapter, "PerfMonLv7", 400); + prWifiVar->u4PerfMonTpTh[7] = + (uint32_t) wlanCfgGetUint32(prAdapter, "PerfMonLv8", 500); + prWifiVar->u4PerfMonTpTh[8] = + (uint32_t) wlanCfgGetUint32(prAdapter, "PerfMonLv9", 600); + prWifiVar->u4PerfMonTpTh[9] = + (uint32_t) wlanCfgGetUint32(prAdapter, "PerfMonLv10", 700); + + u4PlatformBoostCpuTh = kalGetCpuBoostThreshold(); + prWifiVar->u4BoostCpuTh = + (uint32_t) wlanCfgGetUint32(prAdapter, "BoostCpuTh", + u4PlatformBoostCpuTh); + + prWifiVar->u4PerfMonPendingTh = (uint8_t)wlanCfgGetUint32(prAdapter, + "PerfMonPendingTh", 80); + + prWifiVar->u4PerfMonUsedTh = (uint8_t)wlanCfgGetUint32(prAdapter, + "PerfMonUsedTh", 80); + + /* for SER */ + prWifiVar->fgEnableSer = (uint8_t)wlanCfgGetUint32(prAdapter, + "SerEnable", FEATURE_ENABLED); + + prWifiVar->fgRstRecover = (uint8_t) wlanCfgGetUint32(prAdapter, + "RstRecover", FEATURE_DISABLED); + /* + * For Certification purpose,forcibly set + * "Compressed Steering Number of Beamformer Antennas Supported" to our + * own capability. + */ + prWifiVar->fgForceSTSNum = (uint8_t)wlanCfgGetUint32( + prAdapter, "ForceSTSNum", 0); +#if CFG_SUPPORT_IDC_CH_SWITCH + prWifiVar->ucChannelSwtichColdownTime = (uint8_t) wlanCfgGetUint32( + prAdapter, "CSACdTime", 60);/*Second*/ + prWifiVar->fgCrossBandSwitchEn = (uint8_t) wlanCfgGetUint32( + prAdapter, "SapCrossBandSwitchEn", 0); +#endif +#if CFG_SUPPORT_PERF_IND + prWifiVar->fgPerfIndicatorEn = (uint8_t) wlanCfgGetUint32( + prAdapter, "PerfIndicatorEn", 1); +#endif +#if CFG_SUPPORT_SPE_IDX_CONTROL + prWifiVar->ucSpeIdxCtrl = (uint8_t) wlanCfgGetUint32( + prAdapter, "SpeIdxCtrl", 2); +#endif + +#if CFG_SUPPORT_LOWLATENCY_MODE + prWifiVar->ucLowLatencyModeScan = (uint32_t) wlanCfgGetUint32( + prAdapter, "LowLatencyModeScan", FEATURE_ENABLED); + prWifiVar->ucLowLatencyModeReOrder = (uint32_t) wlanCfgGetUint32( + prAdapter, "LowLatencyModeReOrder", FEATURE_ENABLED); + prWifiVar->ucLowLatencyModePower = (uint32_t) wlanCfgGetUint32( + prAdapter, "LowLatencyModePower", FEATURE_DISABLED); + prWifiVar->ucLowLatencyPacketPriority = (uint32_t) wlanCfgGetUint32( + prAdapter, "LowLatencyPacketPriority", BITS(0, 1)); + prWifiVar->ucLowLatencyCmdData = (uint8_t) wlanCfgGetUint32( + prAdapter, "LowLatencyCmdData", FEATURE_ENABLED); + prWifiVar->ucLowLatencyCmdDataAllPacket = (uint8_t) wlanCfgGetUint32( + prAdapter, "LowLatencyCmdDataAllPacket", FEATURE_DISABLED); +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + +#if CFG_SUPPORT_SPE_IDX_CONTROL + prWifiVar->ucSpeIdxCtrl = (uint8_t) wlanCfgGetUint32( + prAdapter, "SpeIdxCtrl", 2); +#endif + + prWifiVar->u4MTU = wlanCfgGetUint32(prAdapter, "MTU", 0); + +#if CFG_SUPPORT_RX_GRO + prWifiVar->ucGROFlushTimeout = (uint32_t) wlanCfgGetUint32( + prAdapter, "GROFlushTimeout", 1); + prWifiVar->ucGROEnableTput = (uint32_t) wlanCfgGetUint32( + prAdapter, "GROEnableTput", 6250000); +#endif + prWifiVar->ucMsduReportTimeout = + (uint8_t) wlanCfgGetUint32(prAdapter, + "MsduReportTimeout", NIC_MSDU_REPORT_DUMP_TIMEOUT); + +#if CFG_SUPPORT_DATA_STALL + prWifiVar->u4PerHighThreshole = (uint32_t) wlanCfgGetUint32( + prAdapter, "PerHighThreshole", + EVENT_PER_HIGH_THRESHOLD); + prWifiVar->u4TxLowRateThreshole = (uint32_t) wlanCfgGetUint32( + prAdapter, "TxLowRateThreshole", + EVENT_TX_LOW_RATE_THRESHOLD); + prWifiVar->u4RxLowRateThreshole = (uint32_t) wlanCfgGetUint32( + prAdapter, "RxLowRateThreshole", + EVENT_RX_LOW_RATE_THRESHOLD); + prWifiVar->u4ReportEventInterval = (uint32_t) wlanCfgGetUint32( + prAdapter, "ReportEventInterval", + REPORT_EVENT_INTERVAL); + prWifiVar->u4TrafficThreshold = (uint32_t) wlanCfgGetUint32( + prAdapter, "TrafficThreshold", + TRAFFIC_RHRESHOLD); +#endif + +#if CFG_SUPPORT_HE_ER + prWifiVar->u4ExtendedRange = (uint32_t) wlanCfgGetUint32( + prAdapter, "ExtendedRange", + FEATURE_ENABLED); +#endif + +#if (CFG_SUPPORT_P2PGO_ACS == 1) + prWifiVar->ucP2pGoACS = (uint32_t) wlanCfgGetUint32( + prAdapter, "P2pGoACSEnable", + FEATURE_DISABLED); + DBGLOG(INIT, TRACE, + "P2pGoACSEnable Setting:ACS Enable[%d]\n", + prAdapter->rWifiVar.ucP2pGoACS); + +#endif + + prWifiVar->fgReuseRSNIE = (uint32_t) wlanCfgGetUint32( + prAdapter, "ReuseRSNIE", + FEATURE_DISABLED); + +#if CFG_MTK_MCIF_WIFI_SUPPORT + wlanCfgSetUint32(prAdapter, "MddpSupport", FEATURE_ENABLED); +#endif + + prWifiVar->u4DiscoverTimeout = (uint32_t) wlanCfgGetUint32( + prAdapter, "DiscoverTimeout", ROAMING_DISCOVER_TIMEOUT_SEC); + + prWifiVar->u4InactiveTimeout = (uint32_t) wlanCfgGetUint32( + prAdapter, "InactiveTimeout", ROAMING_INACTIVE_TIMEOUT_SEC); + +#if ARP_MONITER_ENABLE + prWifiVar->uArpMonitorNumber = (uint32_t) wlanCfgGetUint32( + prAdapter, "ArpMonitorNumber", 20); + prWifiVar->uArpMonitorRxPktNum = (uint32_t) wlanCfgGetUint32( + prAdapter, "ArpMonitorRxPktNum", 0); +#endif /* ARP_MONITER_ENABLE */ + + prWifiVar->fgSapCheckPmkidInDriver = (uint32_t) wlanCfgGetUint32( + prAdapter, "SapCheckPmkidInDriver", FEATURE_ENABLED); +} + +void wlanCfgSetSwCtrl(IN struct ADAPTER *prAdapter) +{ + uint32_t i = 0; + int8_t aucKey[WLAN_CFG_VALUE_LEN_MAX]; + int8_t aucValue[WLAN_CFG_VALUE_LEN_MAX]; + + const int8_t acDelim[] = " "; + int8_t *pcPtr = NULL; + int8_t *pcDupValue = NULL; + uint32_t au4Values[2] = {}; + uint32_t u4TokenCount = 0; + uint32_t u4BufLen = 0; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + int32_t u4Ret = 0; + + for (i = 0; i < WLAN_CFG_SET_SW_CTRL_LEN_MAX; i++) { + kalMemZero(aucValue, WLAN_CFG_VALUE_LEN_MAX); + kalMemZero(aucKey, WLAN_CFG_VALUE_LEN_MAX); + kalSprintf(aucKey, "SwCtrl%d", i); + + /* get nothing */ + if (wlanCfgGet(prAdapter, aucKey, aucValue, "", + 0) != WLAN_STATUS_SUCCESS) + continue; + if (!kalStrCmp(aucValue, "")) + continue; + + pcDupValue = aucValue; + u4TokenCount = 0; + + while ((pcPtr = kalStrSep((char **)(&pcDupValue), acDelim)) + != NULL) { + + if (!kalStrCmp(pcPtr, "")) + continue; + + /* au4Values[u4TokenCount] = kalStrtoul(pcPtr, NULL, 0); + */ + u4Ret = kalkStrtou32(pcPtr, 0, + &(au4Values[u4TokenCount])); + if (u4Ret) + DBGLOG(INIT, LOUD, + "parse au4Values error u4Ret=%d\n", + u4Ret); + u4TokenCount++; + + /* Only need 2 tokens */ + if (u4TokenCount >= 2) + break; + } + + if (u4TokenCount != 2) + continue; + + rSwCtrlInfo.u4Id = au4Values[0]; + rSwCtrlInfo.u4Data = au4Values[1]; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + } +} + +void wlanCfgSetChip(IN struct ADAPTER *prAdapter) +{ + uint32_t i = 0; + int8_t aucKey[WLAN_CFG_VALUE_LEN_MAX]; + int8_t aucValue[WLAN_CFG_VALUE_LEN_MAX]; + + uint32_t u4BufLen = 0; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct PARAM_CUSTOM_CHIP_CONFIG_STRUCT rChipConfigInfo; + + for (i = 0; i < WLAN_CFG_SET_CHIP_LEN_MAX; i++) { + kalMemZero(aucValue, WLAN_CFG_VALUE_LEN_MAX); + kalMemZero(aucKey, WLAN_CFG_VALUE_LEN_MAX); + kalSnprintf(aucKey, sizeof(aucKey), "SetChip%d", i); + + /* get nothing */ + if (wlanCfgGet(prAdapter, aucKey, aucValue, "", + 0) != WLAN_STATUS_SUCCESS) + continue; + if (!kalStrCmp(aucValue, "")) + continue; + + kalMemZero(&rChipConfigInfo, sizeof(rChipConfigInfo)); + + rChipConfigInfo.ucType = CHIP_CONFIG_TYPE_WO_RESPONSE; + rChipConfigInfo.u2MsgSize = kalStrnLen(aucValue, + WLAN_CFG_VALUE_LEN_MAX); + kalStrnCpy(rChipConfigInfo.aucCmd, aucValue, + CHIP_CONFIG_RESP_SIZE); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetChipConfig, + &rChipConfigInfo, sizeof(rChipConfigInfo), + FALSE, FALSE, TRUE, &u4BufLen); + } +} + +#if (CFG_SUPPORT_CONNINFRA == 1) +/* Send kernel time to FW */ +void wlanCfgSetChipSyncTime(IN struct ADAPTER *prAdapter) +{ + struct timeval time; + unsigned int second, usecond; + + int8_t aucKey[WLAN_CFG_VALUE_LEN_MAX]; + int8_t aucValue[WLAN_CFG_VALUE_LEN_MAX]; + + uint32_t u4BufLen = 0; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct PARAM_CUSTOM_CHIP_CONFIG_STRUCT rChipConfigInfo; + + do_gettimeofday(&time); + second = (unsigned int)time.tv_sec; /* UTC time second unit */ + usecond = (unsigned int)time.tv_usec; /* UTC time microsecond unit */ + + kalMemZero(aucValue, WLAN_CFG_VALUE_LEN_MAX); + kalMemZero(aucKey, WLAN_CFG_VALUE_LEN_MAX); + kalSnprintf(aucKey, sizeof(aucKey), "SetChip"); + kalSnprintf(aucValue, sizeof(aucValue), + "SyncTime %u %u", second, usecond); + + DBGLOG(INIT, INFO, + "Sync kernel time, key=%s, value=%s", + aucKey, aucValue); + + kalMemZero(&rChipConfigInfo, sizeof(rChipConfigInfo)); + + rChipConfigInfo.ucType = CHIP_CONFIG_TYPE_WO_RESPONSE; + rChipConfigInfo.u2MsgSize = kalStrnLen(aucValue, + WLAN_CFG_VALUE_LEN_MAX); + kalStrnCpy(rChipConfigInfo.aucCmd, aucValue, + CHIP_CONFIG_RESP_SIZE); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetChipConfig, + &rChipConfigInfo, sizeof(rChipConfigInfo), + FALSE, FALSE, TRUE, &u4BufLen); +} +#endif /* CFG_SUPPORT_CONNINFRA */ + +void wlanCfgSetDebugLevel(IN struct ADAPTER *prAdapter) +{ + uint32_t i = 0; + int8_t aucKey[WLAN_CFG_VALUE_LEN_MAX]; + int8_t aucValue[WLAN_CFG_VALUE_LEN_MAX]; + const int8_t acDelim[] = " "; + int8_t *pcDupValue; + int8_t *pcPtr = NULL; + + uint32_t au4Values[2] = {0}; + uint32_t u4TokenCount = 0; + uint32_t u4DbgIdx = 0; + uint32_t u4DbgMask = 0; + int32_t u4Ret = 0; + + for (i = 0; i < WLAN_CFG_SET_DEBUG_LEVEL_LEN_MAX; i++) { + kalMemZero(aucValue, WLAN_CFG_VALUE_LEN_MAX); + kalMemZero(aucKey, WLAN_CFG_VALUE_LEN_MAX); + kalSprintf(aucKey, "DbgLevel%d", i); + + /* get nothing */ + if (wlanCfgGet(prAdapter, aucKey, aucValue, "", + 0) != WLAN_STATUS_SUCCESS) + continue; + if (!kalStrCmp(aucValue, "")) + continue; + + pcDupValue = aucValue; + u4TokenCount = 0; + + while ((pcPtr = kalStrSep((char **)(&pcDupValue), + acDelim)) != NULL) { + + if (!kalStrCmp(pcPtr, "")) + continue; + + /* au4Values[u4TokenCount] = + * kalStrtoul(pcPtr, NULL, 0); + */ + u4Ret = kalkStrtou32(pcPtr, 0, + &(au4Values[u4TokenCount])); + if (u4Ret) + DBGLOG(INIT, LOUD, + "parse au4Values error u4Ret=%d\n", + u4Ret); + u4TokenCount++; + + /* Only need 2 tokens */ + if (u4TokenCount >= 2) + break; + } + + if (u4TokenCount != 2) + continue; + + u4DbgIdx = au4Values[0]; + u4DbgMask = au4Values[1]; + + /* DBG level special control */ + if (u4DbgIdx == 0xFFFFFFFF) { + wlanSetDriverDbgLevel(DBG_ALL_MODULE_IDX, u4DbgMask); + DBGLOG(INIT, INFO, + "Set ALL DBG module log level to [0x%02x]!", + (uint8_t) u4DbgMask); + } else if (u4DbgIdx == 0xFFFFFFFE) { + wlanDebugInit(); + DBGLOG(INIT, INFO, + "Reset ALL DBG module log level to DEFAULT!"); + } else if (u4DbgIdx < DBG_MODULE_NUM) { + wlanSetDriverDbgLevel(u4DbgIdx, u4DbgMask); + DBGLOG(INIT, INFO, + "Set DBG module[%u] log level to [0x%02x]!", + u4DbgIdx, (uint8_t) u4DbgMask); + } + } +} + +void wlanCfgSetCountryCode(IN struct ADAPTER *prAdapter) +{ + int8_t aucValue[WLAN_CFG_VALUE_LEN_MAX]; + + /* Apply COUNTRY Config */ + if (wlanCfgGet(prAdapter, "Country", aucValue, "", + 0) == WLAN_STATUS_SUCCESS) { + prAdapter->rWifiVar.u2CountryCode = + (((uint16_t) aucValue[0]) << 8) | + ((uint16_t) aucValue[1]); + + DBGLOG(INIT, TRACE, "u2CountryCode=0x%04x\n", + prAdapter->rWifiVar.u2CountryCode); + + if (regd_is_single_sku_en()) { + rlmDomainOidSetCountry(prAdapter, aucValue, 2); + return; + } + + /* Force to re-search country code in regulatory domains */ + prAdapter->prDomainInfo = NULL; + rlmDomainSendCmd(prAdapter); + + /* Update supported channel list in channel table based on + * current country domain + */ + wlanUpdateChannelTable(prAdapter->prGlueInfo); + } +} + +#if CFG_SUPPORT_CFG_FILE + +struct WLAN_CFG_ENTRY *wlanCfgGetEntry(IN struct ADAPTER *prAdapter, + const int8_t *pucKey, + uint32_t u4Flags) +{ + + struct WLAN_CFG_ENTRY *prWlanCfgEntry; + struct WLAN_CFG *prWlanCfg = NULL; + struct WLAN_CFG_REC *prWlanCfgRec = NULL; + struct WLAN_CFG *prWlanCfgEm = NULL; + uint32_t i, u32MaxNum; + + if (u4Flags == WLAN_CFG_REC) { + prWlanCfgRec = prAdapter->prWlanCfgRec; + u32MaxNum = WLAN_CFG_REC_ENTRY_NUM_MAX; + ASSERT(prWlanCfgRec); + } else if (u4Flags == WLAN_CFG_EM) { + prWlanCfgEm = prAdapter->prWlanCfgEm; + u32MaxNum = WLAN_CFG_REC_ENTRY_NUM_MAX; + ASSERT(prWlanCfgEm); + } else { + prWlanCfg = prAdapter->prWlanCfg; + u32MaxNum = WLAN_CFG_ENTRY_NUM_MAX; + ASSERT(prWlanCfg); + } + + + ASSERT(pucKey); + + prWlanCfgEntry = NULL; + + for (i = 0; i < u32MaxNum; i++) { + if (u4Flags == WLAN_CFG_REC) + prWlanCfgEntry = &prWlanCfgRec->arWlanCfgBuf[i]; + else if (u4Flags == WLAN_CFG_EM) + prWlanCfgEntry = &prWlanCfgEm->arWlanCfgBuf[i]; + else + prWlanCfgEntry = &prWlanCfg->arWlanCfgBuf[i]; + + if (prWlanCfgEntry->aucKey[0] != '\0') { + if (kalStrnCmp(pucKey, prWlanCfgEntry->aucKey, + WLAN_CFG_KEY_LEN_MAX - 1) == 0) + return prWlanCfgEntry; + } + } + + return NULL; + +} + +uint32_t wlanCfgGetTotalCfgNum( + IN struct ADAPTER *prAdapter, uint32_t flag) +{ + uint32_t i = 0; + struct WLAN_CFG_ENTRY *prWlanCfgEntry; + uint32_t count = 0; + + for (i = 0; i < WLAN_CFG_REC_ENTRY_NUM_MAX; i++) { + prWlanCfgEntry = wlanCfgGetEntryByIndex(prAdapter, i, flag); + + if ((!prWlanCfgEntry) || (prWlanCfgEntry->aucKey[0] == '\0')) + break; + + count++; + } + return count; +} + + +struct WLAN_CFG_ENTRY *wlanCfgGetEntryByIndex( + IN struct ADAPTER *prAdapter, const uint8_t ucIdx, + uint32_t flag) +{ + + struct WLAN_CFG_ENTRY *prWlanCfgEntry; + struct WLAN_CFG *prWlanCfg; + struct WLAN_CFG_REC *prWlanCfgRec; + struct WLAN_CFG *prWlanCfgEm; + + + prWlanCfg = prAdapter->prWlanCfg; + prWlanCfgRec = prAdapter->prWlanCfgRec; + prWlanCfgEm = prAdapter->prWlanCfgEm; + + ASSERT(prWlanCfg); + ASSERT(prWlanCfgRec); + ASSERT(prWlanCfgEm); + + + prWlanCfgEntry = NULL; + + if (flag == WLAN_CFG_REC) + prWlanCfgEntry = &prWlanCfgRec->arWlanCfgBuf[ucIdx]; + else if (flag == WLAN_CFG_EM) + prWlanCfgEntry = &prWlanCfgEm->arWlanCfgBuf[ucIdx]; + else + prWlanCfgEntry = &prWlanCfg->arWlanCfgBuf[ucIdx]; + + if (prWlanCfgEntry->aucKey[0] != '\0') { + DBGLOG(INIT, LOUD, "get Index(%d) saved key %s\n", ucIdx, + prWlanCfgEntry->aucKey); + return prWlanCfgEntry; + } + + DBGLOG(INIT, TRACE, + "wifi config there is no entry at index(%d)\n", ucIdx); + return NULL; + +} + + + +uint32_t wlanCfgGet(IN struct ADAPTER *prAdapter, + const int8_t *pucKey, int8_t *pucValue, int8_t *pucValueDef, + uint32_t u4Flags) +{ + + struct WLAN_CFG_ENTRY *prWlanCfgEntry; + + ASSERT(pucValue); + + /* Find the exist */ + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey, u4Flags); + + if (prWlanCfgEntry) { + kalStrnCpy(pucValue, prWlanCfgEntry->aucValue, + WLAN_CFG_VALUE_LEN_MAX - 1); + return WLAN_STATUS_SUCCESS; + } + if (pucValueDef) + kalStrnCpy(pucValue, pucValueDef, + WLAN_CFG_VALUE_LEN_MAX - 1); + return WLAN_STATUS_FAILURE; + + +} + +void wlanCfgRecordValue(IN struct ADAPTER *prAdapter, + const int8_t *pucKey, uint32_t u4Value) +{ + struct WLAN_CFG_ENTRY *prWlanCfgEntry; + uint8_t aucBuf[WLAN_CFG_VALUE_LEN_MAX]; + + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey, WLAN_CFG_REC); + + kalMemZero(aucBuf, sizeof(aucBuf)); + + kalSnprintf(aucBuf, WLAN_CFG_VALUE_LEN_MAX, "0x%x", + (unsigned int)u4Value); + + wlanCfgSet(prAdapter, pucKey, aucBuf, WLAN_CFG_REC); +} + + + +uint32_t wlanCfgGetUint32(IN struct ADAPTER *prAdapter, + const int8_t *pucKey, uint32_t u4ValueDef) +{ + struct WLAN_CFG_ENTRY *prWlanCfgEntry; + struct WLAN_CFG *prWlanCfg; + uint32_t u4Value; + int32_t u4Ret; + + prWlanCfg = prAdapter->prWlanCfg; + + ASSERT(prWlanCfg); + + u4Value = u4ValueDef; + /* Find the exist */ + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey, WLAN_CFG_DEFAULT); + + if (prWlanCfgEntry) { + /* u4Ret = kalStrtoul(prWlanCfgEntry->aucValue, NULL, 0); */ + u4Ret = kalkStrtou32(prWlanCfgEntry->aucValue, 0, &u4Value); + if (u4Ret) + DBGLOG(INIT, LOUD, "parse aucValue error u4Ret=%d\n", + u4Ret); + } + + wlanCfgRecordValue(prAdapter, pucKey, u4Value); + + return u4Value; +} + +int32_t wlanCfgGetInt32(IN struct ADAPTER *prAdapter, + const int8_t *pucKey, int32_t i4ValueDef) +{ + struct WLAN_CFG_ENTRY *prWlanCfgEntry; + struct WLAN_CFG *prWlanCfg; + int32_t i4Value = 0; + int32_t i4Ret = 0; + + prWlanCfg = prAdapter->prWlanCfg; + + ASSERT(prWlanCfg); + + i4Value = i4ValueDef; + /* Find the exist */ + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey, WLAN_CFG_DEFAULT); + + if (prWlanCfgEntry) { + /* i4Ret = kalStrtol(prWlanCfgEntry->aucValue, NULL, 0); */ + i4Ret = kalkStrtos32(prWlanCfgEntry->aucValue, 0, &i4Value); + if (i4Ret) + DBGLOG(INIT, LOUD, "parse aucValue error i4Ret=%d\n", + i4Ret); + } + + wlanCfgRecordValue(prAdapter, pucKey, (uint32_t)i4Value); + + return i4Value; +} + +uint32_t wlanCfgSet(IN struct ADAPTER *prAdapter, + const int8_t *pucKey, int8_t *pucValue, uint32_t u4Flags) +{ + + struct WLAN_CFG_ENTRY *prWlanCfgEntry; + struct WLAN_CFG *prWlanCfg = NULL; + struct WLAN_CFG *prWlanCfgEm = NULL; + struct WLAN_CFG_REC *prWlanCfgRec = NULL; + uint32_t u4EntryIndex; + uint32_t i; + uint8_t ucExist; + + + ASSERT(pucKey); + + DBGLOG(INIT, LOUD, "[%s]:[%s] OP:%d\n", pucKey, pucValue, u4Flags); + + /* Find the exist */ + ucExist = 0; + if (u4Flags == WLAN_CFG_REC) { + prWlanCfgEntry = + wlanCfgGetEntry(prAdapter, pucKey, WLAN_CFG_REC); + prWlanCfgRec = prAdapter->prWlanCfgRec; + ASSERT(prWlanCfgRec); + } else if (u4Flags == WLAN_CFG_EM) { + prWlanCfgEntry = + wlanCfgGetEntry(prAdapter, pucKey, WLAN_CFG_EM); + prWlanCfgEm = prAdapter->prWlanCfgEm; + ASSERT(prWlanCfgEm); + } else { + prWlanCfgEntry = + wlanCfgGetEntry(prAdapter, pucKey, WLAN_CFG_DEFAULT); + prWlanCfg = prAdapter->prWlanCfg; + ASSERT(prWlanCfg); + } + + if (!prWlanCfgEntry) { + /* Find the empty */ + for (i = 0; i < WLAN_CFG_ENTRY_NUM_MAX; i++) { + if (u4Flags == WLAN_CFG_REC) + prWlanCfgEntry = &prWlanCfgRec->arWlanCfgBuf[i]; + else if (u4Flags == WLAN_CFG_EM) + prWlanCfgEntry = &prWlanCfgEm->arWlanCfgBuf[i]; + else + prWlanCfgEntry = &prWlanCfg->arWlanCfgBuf[i]; + + if (prWlanCfgEntry->aucKey[0] == '\0') + break; + } + + u4EntryIndex = i; + if (u4EntryIndex < WLAN_CFG_ENTRY_NUM_MAX) { + if (u4Flags == WLAN_CFG_REC) + prWlanCfgEntry = + &prWlanCfgRec->arWlanCfgBuf[u4EntryIndex]; + else if (u4Flags == WLAN_CFG_EM) + prWlanCfgEntry = + &prWlanCfgEm->arWlanCfgBuf[u4EntryIndex]; + else + prWlanCfgEntry = + &prWlanCfg->arWlanCfgBuf[u4EntryIndex]; + kalMemZero(prWlanCfgEntry, + sizeof(struct WLAN_CFG_ENTRY)); + } else { + prWlanCfgEntry = NULL; + DBGLOG(INIT, ERROR, + "wifi config there is no empty entry\n"); + } + } /* !prWlanCfgEntry */ + else + ucExist = 1; + + if (prWlanCfgEntry) { + if (ucExist == 0) { + kalStrnCpy(prWlanCfgEntry->aucKey, pucKey, + WLAN_CFG_KEY_LEN_MAX - 1); + prWlanCfgEntry->aucKey[WLAN_CFG_KEY_LEN_MAX - 1] = '\0'; + } + if (pucValue && pucValue[0] != '\0') { + kalStrnCpy(prWlanCfgEntry->aucValue, pucValue, + WLAN_CFG_VALUE_LEN_MAX - 1); + prWlanCfgEntry->aucValue[WLAN_CFG_VALUE_LEN_MAX - 1] = + '\0'; + + if (ucExist) { + if (prWlanCfgEntry->pfSetCb) + prWlanCfgEntry->pfSetCb(prAdapter, + prWlanCfgEntry->aucKey, + prWlanCfgEntry->aucValue, + prWlanCfgEntry->pPrivate, 0); + } + } else { + /* Call the pfSetCb if value is empty ? */ + /* remove the entry if value is empty */ + kalMemZero(prWlanCfgEntry, + sizeof(struct WLAN_CFG_ENTRY)); + } + + } + /* prWlanCfgEntry */ + if (prWlanCfgEntry) { + return WLAN_STATUS_SUCCESS; + } + if (pucKey) + DBGLOG(INIT, ERROR, "Set wifi config error key \'%s\'\n", + pucKey); + + if (pucValue) + DBGLOG(INIT, ERROR, "Set wifi config error value \'%s\'\n", + pucValue); + + return WLAN_STATUS_FAILURE; + + +} + +uint32_t +wlanCfgSetCb(IN struct ADAPTER *prAdapter, + const int8_t *pucKey, WLAN_CFG_SET_CB pfSetCb, + void *pPrivate, uint32_t u4Flags) +{ + + struct WLAN_CFG_ENTRY *prWlanCfgEntry; + struct WLAN_CFG *prWlanCfg; + + prWlanCfg = prAdapter->prWlanCfg; + ASSERT(prWlanCfg); + + /* Find the exist */ + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey, FALSE); + + if (prWlanCfgEntry) { + prWlanCfgEntry->pfSetCb = pfSetCb; + prWlanCfgEntry->pPrivate = pPrivate; + } + + if (prWlanCfgEntry) + return WLAN_STATUS_SUCCESS; + else + return WLAN_STATUS_FAILURE; + +} + +uint32_t wlanCfgSetUint32(IN struct ADAPTER *prAdapter, + const int8_t *pucKey, uint32_t u4Value) +{ + + struct WLAN_CFG *prWlanCfg; + uint8_t aucBuf[WLAN_CFG_VALUE_LEN_MAX]; + + prWlanCfg = prAdapter->prWlanCfg; + + ASSERT(prWlanCfg); + + kalMemZero(aucBuf, sizeof(aucBuf)); + + kalSnprintf(aucBuf, WLAN_CFG_VALUE_LEN_MAX, "0x%x", + (unsigned int)u4Value); + + return wlanCfgSet(prAdapter, pucKey, aucBuf, WLAN_CFG_DEFAULT); +} + +enum { + STATE_EOF = 0, + STATE_TEXT = 1, + STATE_NEWLINE = 2 +}; + +struct WLAN_CFG_PARSE_STATE_S { + int8_t *ptr; + int8_t *text; +#if CFG_SUPPORT_EASY_DEBUG + uint32_t textsize; +#endif + int32_t nexttoken; + uint32_t maxSize; +}; + +int32_t wlanCfgFindNextToken(struct WLAN_CFG_PARSE_STATE_S + *state) +{ + int8_t *x = state->ptr; + int8_t *s; + + if (state->nexttoken) { + int32_t t = state->nexttoken; + + state->nexttoken = 0; + return t; + } + + for (;;) { + switch (*x) { + case 0: + state->ptr = x; + return STATE_EOF; + case '\n': + x++; + state->ptr = x; + return STATE_NEWLINE; + case ' ': + case ',': + /*case ':': should not including : , mac addr would be fail*/ + case '\t': + case '\r': + x++; + continue; + case '#': + while (*x && (*x != '\n')) + x++; + if (*x == '\n') { + state->ptr = x + 1; + return STATE_NEWLINE; + } + state->ptr = x; + return STATE_EOF; + + default: + goto text; + } + } + +textdone: + state->ptr = x; + *s = 0; + return STATE_TEXT; +text: + state->text = s = x; +textresume: + for (;;) { + switch (*x) { + case 0: + goto textdone; + case ' ': + case ',': + /* case ':': */ + case '\t': + case '\r': + x++; + goto textdone; + case '\n': + state->nexttoken = STATE_NEWLINE; + x++; + goto textdone; + case '"': + x++; + for (;;) { + switch (*x) { + case 0: + /* unterminated quoted thing */ + state->ptr = x; + return STATE_EOF; + case '"': + x++; + goto textresume; + default: + *s++ = *x++; + } + } + break; + case '\\': + x++; + switch (*x) { + case 0: + goto textdone; + case 'n': + *s++ = '\n'; + break; + case 'r': + *s++ = '\r'; + break; + case 't': + *s++ = '\t'; + break; + case '\\': + *s++ = '\\'; + break; + case '\r': + /* \ -> line continuation */ + if (x[1] != '\n') { + x++; + continue; + } + case '\n': + /* \ -> line continuation */ + x++; + /* eat any extra whitespace */ + while ((*x == ' ') || (*x == '\t')) + x++; + continue; + default: + /* unknown escape -- just copy */ + *s++ = *x++; + } + continue; + default: + *s++ = *x++; +#if CFG_SUPPORT_EASY_DEBUG + state->textsize++; +#endif + } + } + return STATE_EOF; +} + +uint32_t wlanCfgParseArgument(int8_t *cmdLine, + int32_t *argc, int8_t *argv[]) +{ + struct WLAN_CFG_PARSE_STATE_S state; + int8_t **args; + int32_t nargs; + + if (cmdLine == NULL || argc == NULL || argv == NULL) { + DBGLOG(INIT, ERROR, "parameter is NULL: %p, %p, %p\n", + cmdLine, argc, argv); + return WLAN_STATUS_FAILURE; + } + args = argv; + nargs = 0; + state.ptr = cmdLine; + state.nexttoken = 0; + state.maxSize = 0; +#if CFG_SUPPORT_EASY_DEBUG + state.textsize = 0; +#endif + + if (kalStrnLen(cmdLine, 512) >= 512) { + DBGLOG(INIT, ERROR, "cmdLine >= 512\n"); + return WLAN_STATUS_FAILURE; + } + + for (;;) { + switch (wlanCfgFindNextToken(&state)) { + case STATE_EOF: + goto exit; + case STATE_NEWLINE: + goto exit; + case STATE_TEXT: + if (nargs < WLAN_CFG_ARGV_MAX) + args[nargs++] = state.text; + break; + } + } + +exit: + *argc = nargs; + return WLAN_STATUS_SUCCESS; +} + +#if CFG_WOW_SUPPORT +uint32_t wlanCfgParseArgumentLong(int8_t *cmdLine, + int32_t *argc, int8_t *argv[]) +{ + struct WLAN_CFG_PARSE_STATE_S state; + int8_t **args; + int32_t nargs; + + if (cmdLine == NULL || argc == NULL || argv == NULL) { + DBGLOG(INIT, ERROR, "parameter is NULL: %p, %p, %p\n", + cmdLine, argc, argv); + return WLAN_STATUS_FAILURE; + } + args = argv; + nargs = 0; + state.ptr = cmdLine; + state.nexttoken = 0; + state.maxSize = 0; +#if CFG_SUPPORT_EASY_DEBUG + state.textsize = 0; +#endif + + if (kalStrnLen(cmdLine, 512) >= 512) { + DBGLOG(INIT, ERROR, "cmdLine >= 512\n"); + return WLAN_STATUS_FAILURE; + } + + for (;;) { + switch (wlanCfgFindNextToken(&state)) { + case STATE_EOF: + goto exit; + case STATE_NEWLINE: + goto exit; + case STATE_TEXT: + if (nargs < WLAN_CFG_ARGV_MAX_LONG) + args[nargs++] = state.text; + break; + } + } + +exit: + *argc = nargs; + return WLAN_STATUS_SUCCESS; +} +#endif + +uint32_t +wlanCfgParseAddEntry(IN struct ADAPTER *prAdapter, + uint8_t *pucKeyHead, uint8_t *pucKeyTail, + uint8_t *pucValueHead, uint8_t *pucValueTail) +{ + + uint8_t aucKey[WLAN_CFG_KEY_LEN_MAX]; + uint8_t aucValue[WLAN_CFG_VALUE_LEN_MAX]; + uint32_t u4Len; + + kalMemZero(aucKey, sizeof(aucKey)); + kalMemZero(aucValue, sizeof(aucValue)); + + if ((pucKeyHead == NULL) + || (pucValueHead == NULL) + ) + return WLAN_STATUS_FAILURE; + + if (pucKeyTail) { + if (pucKeyHead > pucKeyTail) + return WLAN_STATUS_FAILURE; + u4Len = pucKeyTail - pucKeyHead + 1; + } else + u4Len = kalStrnLen(pucKeyHead, WLAN_CFG_KEY_LEN_MAX - 1); + + if (u4Len >= WLAN_CFG_KEY_LEN_MAX) + u4Len = WLAN_CFG_KEY_LEN_MAX - 1; + + kalStrnCpy(aucKey, pucKeyHead, u4Len); + + if (pucValueTail) { + if (pucValueHead > pucValueTail) + return WLAN_STATUS_FAILURE; + u4Len = pucValueTail - pucValueHead + 1; + } else + u4Len = kalStrnLen(pucValueHead, + WLAN_CFG_VALUE_LEN_MAX - 1); + + if (u4Len >= WLAN_CFG_VALUE_LEN_MAX) + u4Len = WLAN_CFG_VALUE_LEN_MAX - 1; + + kalStrnCpy(aucValue, pucValueHead, u4Len); + + return wlanCfgSet(prAdapter, aucKey, aucValue, WLAN_CFG_DEFAULT); +} + +enum { + WAIT_KEY_HEAD = 0, + WAIT_KEY_TAIL, + WAIT_VALUE_HEAD, + WAIT_VALUE_TAIL, + WAIT_COMMENT_TAIL +}; + +#if CFG_SUPPORT_EASY_DEBUG + +uint32_t wlanCfgParseToFW(int8_t **args, int8_t *args_size, + uint8_t nargs, int8_t *buffer, uint8_t times) +{ + uint8_t *data = NULL; + char ch; + int32_t i = 0, j = 0; + uint32_t bufferindex = 0, base = 0; + uint32_t sum = 0, startOffset = 0; + struct CMD_FORMAT_V1 cmd_v1; + + memset(&cmd_v1, 0, sizeof(struct CMD_FORMAT_V1)); + +#if 0 + cmd_v1.itemType = kalAtoi(*args[ED_ITEMTYPE_SITE]); +#else + cmd_v1.itemType = ITEM_TYPE_DEC; +#endif + if (buffer == NULL || + args_size[ED_STRING_SITE] == 0 || + args_size[ED_VALUE_SITE] == 0 || + (cmd_v1.itemType < ITEM_TYPE_DEC + || cmd_v1.itemType > ITEM_TYPE_STR)) { + DBGLOG(INIT, ERROR, "cfg args wrong\n"); + return WLAN_STATUS_FAILURE; + } + + cmd_v1.itemStringLength = args_size[ED_STRING_SITE]; + strncpy(cmd_v1.itemString, args[ED_STRING_SITE], + cmd_v1.itemStringLength); + DBGLOG(INIT, INFO, "itemString:"); + for (i = 0; i < cmd_v1.itemStringLength; i++) + DBGLOG(INIT, INFO, "%c", cmd_v1.itemString[i]); + DBGLOG(INIT, INFO, "\n"); + + DBGLOG(INIT, INFO, "cmd_v1.itemType = %d\n", + cmd_v1.itemType); + if (cmd_v1.itemType == ITEM_TYPE_DEC + || cmd_v1.itemType == ITEM_TYPE_HEX) { + data = args[ED_VALUE_SITE]; + + switch (cmd_v1.itemType) { + case ITEM_TYPE_DEC: + base = 10; + startOffset = 0; + break; + case ITEM_TYPE_HEX: + ch = *data; + if (args_size[ED_VALUE_SITE] < 3 || ch != '0') { + DBGLOG(INIT, WARN, + "Hex args must have prefix '0x'\n"); + return WLAN_STATUS_FAILURE; + } + + data++; + ch = *data; + if (ch != 'x' && ch != 'X') { + DBGLOG(INIT, WARN, + "Hex args must have prefix '0x'\n"); + return WLAN_STATUS_FAILURE; + } + data++; + base = 16; + startOffset = 2; + break; + } + + for (j = args_size[ED_VALUE_SITE] - 1 - startOffset; j >= 0; + j--) { + sum = sum * base + kalAtoi(*data); + DBGLOG(INIT, WARN, "size:%d data[%d]=%u, sum=%u\n", + args_size[ED_VALUE_SITE], j, + kalAtoi(*data), sum); + + data++; + } + + bufferindex = 0; + do { + cmd_v1.itemValue[bufferindex++] = sum & 0xFF; + sum = sum >> 8; + } while (sum > 0); + cmd_v1.itemValueLength = bufferindex; + } else if (cmd_v1.itemType == ITEM_TYPE_STR) { + cmd_v1.itemValueLength = args_size[ED_VALUE_SITE]; + strncpy(cmd_v1.itemValue, args[ED_VALUE_SITE], + cmd_v1.itemValueLength); + } + + DBGLOG(INIT, INFO, "Length = %d itemValue:", + cmd_v1.itemValueLength); + for (i = cmd_v1.itemValueLength - 1; i >= 0; i--) + DBGLOG(INIT, ERROR, "%d,", cmd_v1.itemValue[i]); + DBGLOG(INIT, INFO, "\n"); + memcpy(((struct CMD_FORMAT_V1 *)buffer) + times, &cmd_v1, + sizeof(struct CMD_FORMAT_V1)); + + return WLAN_STATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is to send WLAN feature options to firmware + * + * @param prAdapter Pointer of ADAPTER_T + * + * @return none + */ +/*----------------------------------------------------------------------------*/ +void wlanFeatureToFw(IN struct ADAPTER *prAdapter, uint32_t u4Flag) +{ + + struct WLAN_CFG_ENTRY *prWlanCfgEntry; + uint32_t i; + struct CMD_HEADER rCmdV1Header; + uint32_t rStatus; + struct CMD_FORMAT_V1 rCmd_v1; + uint8_t ucTimes = 0; + + + + rCmdV1Header.cmdType = CMD_TYPE_SET; + rCmdV1Header.cmdVersion = CMD_VER_1; + rCmdV1Header.cmdBufferLen = 0; + rCmdV1Header.itemNum = 0; + + kalMemSet(rCmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); + kalMemSet(&rCmd_v1, 0, sizeof(struct CMD_FORMAT_V1)); + + + prWlanCfgEntry = NULL; + + for (i = 0; i < WLAN_CFG_ENTRY_NUM_MAX; i++) { + + prWlanCfgEntry = wlanCfgGetEntryByIndex(prAdapter, i, u4Flag); + + if (prWlanCfgEntry) { + + rCmd_v1.itemType = ITEM_TYPE_STR; + + + /*send string format to firmware */ + rCmd_v1.itemStringLength = kalStrLen( + prWlanCfgEntry->aucKey); + if (rCmd_v1.itemStringLength > MAX_CMD_NAME_MAX_LENGTH) + continue; + kalMemZero(rCmd_v1.itemString, MAX_CMD_NAME_MAX_LENGTH); + kalMemCopy(rCmd_v1.itemString, prWlanCfgEntry->aucKey, + rCmd_v1.itemStringLength); + + + rCmd_v1.itemValueLength = kalStrLen( + prWlanCfgEntry->aucValue); + if (rCmd_v1.itemValueLength > MAX_CMD_VALUE_MAX_LENGTH) + continue; + kalMemZero(rCmd_v1.itemValue, MAX_CMD_VALUE_MAX_LENGTH); + kalMemCopy(rCmd_v1.itemValue, prWlanCfgEntry->aucValue, + rCmd_v1.itemValueLength); + + + + DBGLOG(INIT, TRACE, + "Send key word (%s) WITH (%s) to firmware\n", + rCmd_v1.itemString, rCmd_v1.itemValue); + + kalMemCopy(((struct CMD_FORMAT_V1 *)rCmdV1Header.buffer) + + ucTimes, + &rCmd_v1, sizeof(struct CMD_FORMAT_V1)); + + + ucTimes++; + rCmdV1Header.cmdBufferLen += + sizeof(struct CMD_FORMAT_V1); + rCmdV1Header.itemNum += ucTimes; + + if (ucTimes == MAX_CMD_ITEM_MAX) { + /* Send to FW */ + rCmdV1Header.itemNum = ucTimes; + + rStatus = wlanSendSetQueryCmd( + /* prAdapter */ + prAdapter, + /* 0x70 */ + CMD_ID_GET_SET_CUSTOMER_CFG, + /* fgSetQuery */ + TRUE, + /* fgNeedResp */ + FALSE, + /* fgIsOid */ + FALSE, + /* pfCmdDoneHandler*/ + NULL, + /* pfCmdTimeoutHandler */ + NULL, + /* u4SetQueryInfoLen */ + sizeof(struct CMD_HEADER), + /* pucInfoBuffer */ + (uint8_t *)&rCmdV1Header, + /* pvSetQueryBuffer */ + NULL, + /* u4SetQueryBufferLen */ + 0); + + if (rStatus == WLAN_STATUS_FAILURE) + DBGLOG(INIT, INFO, + "[Fail]kalIoctl wifiSefCFG fail 0x%x\n", + rStatus); + + DBGLOG(INIT, TRACE, + "kalIoctl wifiSefCFG num:%d\n", ucTimes); + kalMemSet(rCmdV1Header.buffer, 0, + MAX_CMD_BUFFER_LENGTH); + rCmdV1Header.cmdBufferLen = 0; + ucTimes = 0; + } + + + } else { + break; + } + } + + + if (ucTimes != 0) { + /* Send to FW */ + rCmdV1Header.itemNum = ucTimes; + + rStatus = wlanSendSetQueryCmd( + prAdapter, /* prAdapter */ + CMD_ID_GET_SET_CUSTOMER_CFG, /* 0x70 */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler*/ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct CMD_HEADER), /* u4SetQueryInfoLen */ + (uint8_t *)&rCmdV1Header,/* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0); /* u4SetQueryBufferLen */ + + if (rStatus == WLAN_STATUS_FAILURE) + DBGLOG(INIT, INFO, + "[Fail]kalIoctl wifiSefCFG fail 0x%x\n", + rStatus); + + DBGLOG(INIT, TRACE, + "cmdV1Header.itemNum:%d, kalIoctl wifiSefCFG num:%d\n", + rCmdV1Header.itemNum, + ucTimes); + kalMemSet(rCmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); + rCmdV1Header.cmdBufferLen = 0; + ucTimes = 0; + } + +#if CFG_SUPPORT_SMART_GEAR + /*Send Event, Notify Fwks*/ + #if CFG_SUPPORT_DATA_STALL + if (prAdapter->rWifiVar.ucSGCfg == 0x00) { + enum ENUM_VENDOR_DRIVER_EVENT eEvent = EVENT_SG_DISABLE; + + KAL_REPORT_ERROR_EVENT(prAdapter, + eEvent, (uint16_t)sizeof(u_int8_t), + 0, + TRUE); + } + #endif /* CFG_SUPPORT_DATA_STALL */ +#endif + +} + +uint32_t wlanCfgParse(IN struct ADAPTER *prAdapter, + uint8_t *pucConfigBuf, uint32_t u4ConfigBufLen, + u_int8_t isFwConfig) +{ + struct WLAN_CFG_PARSE_STATE_S state; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int8_t **ppcArgs; + int32_t i4Nargs; + int8_t arcArgv_size[WLAN_CFG_ARGV_MAX]; + uint8_t ucTimes = 0; + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER rCmdV1Header; + int8_t ucTmp[WLAN_CFG_VALUE_LEN_MAX]; + uint8_t i; + + uint8_t *pucCurrBuf = ucTmp; + uint32_t u4CurrSize = ARRAY_SIZE(ucTmp); + uint32_t u4RetSize = 0; + + rCmdV1Header.cmdType = CMD_TYPE_SET; + rCmdV1Header.cmdVersion = CMD_VER_1; + rCmdV1Header.cmdBufferLen = 0; + kalMemSet(rCmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); + + if (pucConfigBuf == NULL) { + DBGLOG(INIT, ERROR, "pucConfigBuf is NULL\n"); + return WLAN_STATUS_FAILURE; + } + if (kalStrnLen(pucConfigBuf, 4000) >= 4000) { + DBGLOG(INIT, ERROR, "pucConfigBuf >= 4000\n"); + return WLAN_STATUS_FAILURE; + } + if (u4ConfigBufLen == 0) + return WLAN_STATUS_FAILURE; + + ppcArgs = apcArgv; + i4Nargs = 0; + state.ptr = pucConfigBuf; + state.nexttoken = 0; + state.textsize = 0; + state.maxSize = u4ConfigBufLen; + DBGLOG(INIT, INFO, "wlanCfgParse()\n"); + + for (;;) { + switch (wlanCfgFindNextToken(&state)) { + case STATE_EOF: + if (i4Nargs < 2) + goto exit; + + DBGLOG(INIT, INFO, "STATE_EOF\n"); + + /* 3 parmeter mode transforation */ + if (i4Nargs == 3 && !isFwConfig && + arcArgv_size[0] == 1) { + + /* parsing and transfer the format + * Format 1:Dec 2.Hex 3.String + */ + + kalMemZero(ucTmp, WLAN_CFG_VALUE_LEN_MAX); + pucCurrBuf = ucTmp; + u4CurrSize = ARRAY_SIZE(ucTmp); + + if ((*ppcArgs[0] == '2') && + (*(ppcArgs[2]) != '0') && + (*(ppcArgs[2] + 1) != 'x')) { + DBGLOG(INIT, WARN, + "config file got a hex format\n" + ); + kalSnprintf(pucCurrBuf, u4CurrSize, + "0x%s", ppcArgs[2]); + } else { + kalSnprintf(pucCurrBuf, u4CurrSize, + "%s", ppcArgs[2]); + } + DBGLOG(INIT, WARN, + "[3 parameter mode][%s],[%s],[%s]\n", + ppcArgs[0], ppcArgs[1], ucTmp); + wlanCfgParseAddEntry(prAdapter, ppcArgs[1], + NULL, ucTmp, NULL); + kalMemSet(arcArgv_size, 0, WLAN_CFG_ARGV_MAX); + kalMemSet(apcArgv, 0, + WLAN_CFG_ARGV_MAX * sizeof(int8_t *)); + i4Nargs = 0; + goto exit; + + } + + wlanCfgParseAddEntry(prAdapter, ppcArgs[0], NULL, + ppcArgs[1], NULL); + + if (isFwConfig) { + uint32_t ret; + + ret = wlanCfgParseToFW(ppcArgs, arcArgv_size, + i4Nargs, + rCmdV1Header.buffer, + ucTimes); + if (ret == WLAN_STATUS_SUCCESS) { + ucTimes++; + rCmdV1Header.cmdBufferLen += + sizeof(struct CMD_FORMAT_V1); + } + } + + goto exit; + + + case STATE_NEWLINE: + if (i4Nargs < 2) + break; + + DBGLOG(INIT, INFO, "STATE_NEWLINE\n"); +#if 1 + /* 3 parmeter mode transforation */ + if (i4Nargs == 3 && !isFwConfig && + arcArgv_size[0] == 1) { + /* parsing and transfer the format + * Format 1:Dec 2.Hex 3.String + */ + kalMemZero(ucTmp, WLAN_CFG_VALUE_LEN_MAX); + pucCurrBuf = ucTmp; + u4CurrSize = ARRAY_SIZE(ucTmp); + + if ((*ppcArgs[0] == '2') && + (*(ppcArgs[2]) != '0') && + (*(ppcArgs[2] + 1) != 'x')) { + DBGLOG(INIT, WARN, + "config file got a hex format\n"); + kalSnprintf(pucCurrBuf, u4CurrSize, + "0x%s", ppcArgs[2]); + + } else { + kalSnprintf(pucCurrBuf, u4CurrSize, + "%s", ppcArgs[2]); + } + + + DBGLOG(INIT, WARN, + "[3 parameter mode][%s],[%s],[%s]\n", + ppcArgs[0], ppcArgs[1], ucTmp); + wlanCfgParseAddEntry(prAdapter, ppcArgs[1], + NULL, ucTmp, NULL); + kalMemSet(arcArgv_size, 0, WLAN_CFG_ARGV_MAX); + kalMemSet(apcArgv, 0, + WLAN_CFG_ARGV_MAX * sizeof(int8_t *)); + i4Nargs = 0; + break; + + } +#if 1 + /*combine the argument to save in temp*/ + pucCurrBuf = ucTmp; + u4CurrSize = ARRAY_SIZE(ucTmp); + + kalMemZero(ucTmp, WLAN_CFG_VALUE_LEN_MAX); + + if (i4Nargs == 2) { + /* no space for it, driver can't accept space in + * the end of the line + */ + /* ToDo: skip the space when parsing */ + kalSnprintf(pucCurrBuf, u4CurrSize, "%s", + ppcArgs[1]); + } else { + for (i = 1; i < i4Nargs; i++) { + if (u4CurrSize <= 1) { + DBGLOG(INIT, ERROR, + "write to pucCurrBuf out of bound, i=%d\n", + i); + break; + } + u4RetSize = kalScnprintf(pucCurrBuf, + u4CurrSize, "%s ", + ppcArgs[i]); + pucCurrBuf += u4RetSize; + u4CurrSize -= u4RetSize; + } + } + + DBGLOG(INIT, WARN, + "Save to driver temp buffer as [%s]\n", + ucTmp); + wlanCfgParseAddEntry(prAdapter, ppcArgs[0], NULL, ucTmp, + NULL); +#else + wlanCfgParseAddEntry(prAdapter, ppcArgs[0], NULL, + ppcArgs[1], NULL); +#endif + + if (isFwConfig) { + + uint32_t ret; + + ret = wlanCfgParseToFW(ppcArgs, arcArgv_size, + i4Nargs, rCmdV1Header.buffer, ucTimes); + if (ret == WLAN_STATUS_SUCCESS) { + ucTimes++; + rCmdV1Header.cmdBufferLen += + sizeof(struct CMD_FORMAT_V1); + } + + if (ucTimes == MAX_CMD_ITEM_MAX) { + /* Send to FW */ + rCmdV1Header.itemNum = ucTimes; + rStatus = wlanSendSetQueryCmd( + /* prAdapter */ + prAdapter, + /* 0x70 */ + CMD_ID_GET_SET_CUSTOMER_CFG, + /* fgSetQuery */ + TRUE, + /* fgNeedResp */ + FALSE, + /* fgIsOid */ + FALSE, + /* pfCmdDoneHandler*/ + NULL, + /* pfCmdTimeoutHandler */ + NULL, + /* u4SetQueryInfoLen */ + sizeof(struct CMD_HEADER), + /* pucInfoBuffer */ + (uint8_t *) &rCmdV1Header, + /* pvSetQueryBuffer */ + NULL, + /* u4SetQueryBufferLen */ + 0); + + if (rStatus == WLAN_STATUS_FAILURE) + DBGLOG(INIT, INFO, + "kalIoctl wifiSefCFG fail 0x%x\n", + rStatus); + DBGLOG(INIT, INFO, + "kalIoctl wifiSefCFG num:%d X\n", + ucTimes); + kalMemSet(rCmdV1Header.buffer, 0, + MAX_CMD_BUFFER_LENGTH); + rCmdV1Header.cmdBufferLen = 0; + ucTimes = 0; + } + + } + +#endif + kalMemSet(arcArgv_size, 0, WLAN_CFG_ARGV_MAX); + kalMemSet(apcArgv, 0, + WLAN_CFG_ARGV_MAX * sizeof(int8_t *)); + i4Nargs = 0; + break; + + case STATE_TEXT: + if (i4Nargs >= 0 && i4Nargs < WLAN_CFG_ARGV_MAX) { + ppcArgs[i4Nargs++] = state.text; + arcArgv_size[i4Nargs - 1] = state.textsize; + state.textsize = 0; + DBGLOG(INIT, INFO, + " nargs= %d STATE_TEXT = %s, SIZE = %d\n", + i4Nargs - 1, ppcArgs[i4Nargs - 1], + arcArgv_size[i4Nargs - 1]); + } + break; + } + } + +exit: + if (ucTimes != 0 && isFwConfig) { + /* Send to FW */ + rCmdV1Header.itemNum = ucTimes; + + DBGLOG(INIT, INFO, "cmdV1Header.itemNum:%d\n", + rCmdV1Header.itemNum); + rStatus = wlanSendSetQueryCmd( + prAdapter, /* prAdapter */ + CMD_ID_GET_SET_CUSTOMER_CFG, /* 0x70 */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler*/ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct CMD_HEADER), /* u4SetQueryInfoLen */ + (uint8_t *) &rCmdV1Header, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus == WLAN_STATUS_FAILURE) + DBGLOG(INIT, WARN, "kalIoctl wifiSefCFG fail 0x%x\n", + rStatus); + + DBGLOG(INIT, WARN, "kalIoctl wifiSefCFG num:%d X\n", + ucTimes); + kalMemSet(rCmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); + rCmdV1Header.cmdBufferLen = 0; + ucTimes = 0; + } + return WLAN_STATUS_SUCCESS; +} + +#else +uint32_t wlanCfgParse(IN struct ADAPTER *prAdapter, + uint8_t *pucConfigBuf, uint32_t u4ConfigBufLen) +{ + + struct WLAN_CFG_PARSE_STATE_S state; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int8_t **args; + int32_t nargs; + + if (pucConfigBuf == NULL) { + DBGLOG(INIT, ERROR, "pucConfigBuf is NULL\n"); + return WLAN_STATUS_FAILURE; + } + if (kalStrnLen(pucConfigBuf, 4000) >= 4000) { + DBGLOG(INIT, ERROR, "pucConfigBuf >= 4000\n"); + return WLAN_STATUS_FAILURE; + } + if (u4ConfigBufLen == 0) + return WLAN_STATUS_FAILURE; + args = apcArgv; + nargs = 0; + state.ptr = pucConfigBuf; + state.nexttoken = 0; + state.maxSize = u4ConfigBufLen; + + for (;;) { + switch (wlanCfgFindNextToken(&state)) { + case STATE_EOF: + if (nargs > 1) + wlanCfgParseAddEntry(prAdapter, args[0], NULL, + args[1], NULL); + goto exit; + case STATE_NEWLINE: + if (nargs > 1) + wlanCfgParseAddEntry(prAdapter, args[0], NULL, + args[1], NULL); + /*args[0] is parameter, args[1] is the value*/ + nargs = 0; + break; + case STATE_TEXT: + if (nargs < WLAN_CFG_ARGV_MAX) + args[nargs++] = state.text; + break; + } + } + +exit: + return WLAN_STATUS_SUCCESS; + +#if 0 + /* Old version */ + uint32_t i; + uint8_t c; + uint8_t *pbuf; + uint8_t ucState; + uint8_t *pucKeyTail = NULL; + uint8_t *pucKeyHead = NULL; + uint8_t *pucValueHead = NULL; + uint8_t *pucValueTail = NULL; + + ucState = WAIT_KEY_HEAD; + pbuf = pucConfigBuf; + + for (i = 0; i < u4ConfigBufLen; i++) { + c = pbuf[i]; + if (c == '\r' || c == '\n') { + + if (ucState == WAIT_VALUE_TAIL) { + /* Entry found */ + if (pucValueHead) + wlanCfgParseAddEntry(prAdapter, + pucKeyHead, pucKeyTail, + pucValueHead, pucValueTail); + } + ucState = WAIT_KEY_HEAD; + pucKeyTail = NULL; + pucKeyHead = NULL; + pucValueHead = NULL; + pucValueTail = NULL; + + } else if (c == '=') { + if (ucState == WAIT_KEY_TAIL) { + pucKeyTail = &pbuf[i - 1]; + ucState = WAIT_VALUE_HEAD; + } + } else if (c == ' ' || c == '\t') { + if (ucState == WAIT_KEY_TAIL) { + pucKeyTail = &pbuf[i - 1]; + ucState = WAIT_VALUE_HEAD; + } + } else { + + if (c == '#') { + /* comments */ + if (ucState == WAIT_KEY_HEAD) + ucState = WAIT_COMMENT_TAIL; + else if (ucState == WAIT_VALUE_TAIL) + pucValueTail = &pbuf[i]; + + } else { + if (ucState == WAIT_KEY_HEAD) { + pucKeyHead = &pbuf[i]; + pucKeyTail = &pbuf[i]; + ucState = WAIT_KEY_TAIL; + } else if (ucState == WAIT_VALUE_HEAD) { + pucValueHead = &pbuf[i]; + pucValueTail = &pbuf[i]; + ucState = WAIT_VALUE_TAIL; + } else if (ucState == WAIT_VALUE_TAIL) + pucValueTail = &pbuf[i]; + } + } + + } /* for */ + + if (ucState == WAIT_VALUE_TAIL) { + /* Entry found */ + if (pucValueTail) + wlanCfgParseAddEntry(prAdapter, pucKeyHead, pucKeyTail, + pucValueHead, pucValueTail); + } +#endif + + return WLAN_STATUS_SUCCESS; +} +#endif + + +uint32_t wlanCfgInit(IN struct ADAPTER *prAdapter, + uint8_t *pucConfigBuf, uint32_t u4ConfigBufLen, + uint32_t u4Flags) +{ + struct WLAN_CFG *prWlanCfg; + struct WLAN_CFG_REC *prWlanCfgRec; + struct WLAN_CFG *prWlanCfgEm; + + /* P_WLAN_CFG_ENTRY_T prWlanCfgEntry; */ + prAdapter->prWlanCfg = &prAdapter->rWlanCfg; + prWlanCfg = prAdapter->prWlanCfg; + + prAdapter->prWlanCfgRec = &prAdapter->rWlanCfgRec; + prWlanCfgRec = prAdapter->prWlanCfgRec; + + prAdapter->prWlanCfgEm = &prAdapter->rWlanCfgEm; + prWlanCfgEm = prAdapter->prWlanCfgEm; + + kalMemZero(prWlanCfg, sizeof(struct WLAN_CFG)); + ASSERT(prWlanCfg); + + kalMemZero(prWlanCfgEm, sizeof(struct WLAN_CFG)); + ASSERT(prWlanCfgEm); + + prWlanCfg->u4WlanCfgEntryNumMax = WLAN_CFG_ENTRY_NUM_MAX; + prWlanCfg->u4WlanCfgKeyLenMax = WLAN_CFG_KEY_LEN_MAX; + prWlanCfg->u4WlanCfgValueLenMax = WLAN_CFG_VALUE_LEN_MAX; + + prWlanCfgRec->u4WlanCfgEntryNumMax = + WLAN_CFG_REC_ENTRY_NUM_MAX; + prWlanCfgRec->u4WlanCfgKeyLenMax = + WLAN_CFG_KEY_LEN_MAX; + prWlanCfgRec->u4WlanCfgValueLenMax = + WLAN_CFG_VALUE_LEN_MAX; + + prWlanCfgEm->u4WlanCfgEntryNumMax = WLAN_CFG_ENTRY_NUM_MAX; + prWlanCfgEm->u4WlanCfgKeyLenMax = WLAN_CFG_KEY_LEN_MAX; + prWlanCfgEm->u4WlanCfgValueLenMax = WLAN_CFG_VALUE_LEN_MAX; + + + DBGLOG(INIT, INFO, "Init wifi config len %u max entry %u\n", + u4ConfigBufLen, prWlanCfg->u4WlanCfgEntryNumMax); +#if DBG + /* self test */ + wlanCfgSet(prAdapter, "ConfigValid", "0x123", WLAN_CFG_DEFAULT); + if (wlanCfgGetUint32(prAdapter, "ConfigValid", WLAN_CFG_DEFAULT) + != 0x123) + DBGLOG(INIT, INFO, "wifi config error %u\n", __LINE__); + + wlanCfgSet(prAdapter, "ConfigValid", "1", WLAN_CFG_DEFAULT); + if (wlanCfgGetUint32(prAdapter, "ConfigValid", WLAN_CFG_DEFAULT) != 1) + DBGLOG(INIT, INFO, "wifi config error %u\n", __LINE__); + +#endif + /*load default value because kalMemZero in this function*/ + wlanLoadDefaultCustomerSetting(prAdapter); + + /* Parse the pucConfigBuf */ + if (pucConfigBuf && (u4ConfigBufLen > 0)) +#if CFG_SUPPORT_EASY_DEBUG + wlanCfgParse(prAdapter, pucConfigBuf, u4ConfigBufLen, + FALSE); +#else + wlanCfgParse(prAdapter, pucConfigBuf, u4ConfigBufLen); +#endif + return WLAN_STATUS_SUCCESS; +} + +#endif /* CFG_SUPPORT_CFG_FILE */ + +int32_t wlanHexToNum(int8_t c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; +} + +int32_t wlanHexToByte(int8_t *hex) +{ + int32_t a, b; + + a = wlanHexToNum(*hex++); + if (a < 0) + return -1; + b = wlanHexToNum(*hex++); + if (b < 0) + return -1; + return (a << 4) | b; +} + +int32_t wlanHexToArray(int8_t *hexString, int8_t *hexArray, uint8_t arrayLen) +{ + int8_t index = 0; + uint8_t converted = 0; + int strLen = strlen(hexString); + int8_t result; + + for (index = strLen-1; + converted < min(arrayLen*2, strLen); index--) { + if ((strLen-converted) >= 2) { + index--; + result = wlanHexToByte(hexString+index); + converted += 2; + } else { + result = wlanHexToNum(*(hexString+index)); + converted++; + } + if (result == -1) + return 0; + hexArray[(converted-1)/2] = result; + } + return converted; +} + +int32_t wlanHexToArrayR(int8_t *hexString, int8_t *hexArray, uint8_t arrayLen) +{ + int8_t converted = 0; + int len = strlen(hexString)/2; + int8_t result; + + len = arrayLen < len ? arrayLen : len; + if (*(hexString+1) == '\0') { + result = wlanHexToNum(*(hexString)); + if (result != -1) { + hexArray[converted] = result; + converted++; + } + } else { + for (converted = 0; converted < len; converted++) { + result = wlanHexToByte(hexString + converted*2); + hexArray[converted] = result; + } + } + return converted; +} + + + +int32_t wlanHwAddrToBin(int8_t *txt, uint8_t *addr) +{ + int32_t i; + int8_t *pos = txt; + + for (i = 0; i < 6; i++) { + int32_t a, b; + + while (*pos == ':' || *pos == '.' || *pos == '-') + pos++; + + a = wlanHexToNum(*pos++); + if (a < 0) + return -1; + b = wlanHexToNum(*pos++); + if (b < 0) + return -1; + *addr++ = (a << 4) | b; + } + + return pos - txt; +} + +u_int8_t wlanIsChipNoAck(IN struct ADAPTER *prAdapter) +{ + u_int8_t fgIsNoAck; + + fgIsNoAck = prAdapter->fgIsChipNoAck +#if CFG_CHIP_RESET_SUPPORT + || kalIsResetting() +#endif + || fgIsBusAccessFailed; + + return fgIsNoAck; +} + +u_int8_t wlanIsChipRstRecEnabled(IN struct ADAPTER + *prAdapter) +{ + return prAdapter->rWifiVar.fgChipResetRecover; +} + +u_int8_t wlanIsChipAssert(IN struct ADAPTER *prAdapter) +{ + return prAdapter->rWifiVar.fgChipResetRecover + && prAdapter->fgIsChipAssert; +} + +void wlanChipRstPreAct(IN struct ADAPTER *prAdapter) +{ + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + int32_t i4BssIdx; + uint32_t u4ClientCount = 0; + struct STA_RECORD *prCurrStaRec = (struct STA_RECORD *) + NULL; + struct STA_RECORD *prNextCurrStaRec = (struct STA_RECORD *) + NULL; + struct LINK *prClientList; + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_CHIP_RST); + if (prAdapter->fgIsChipAssert) { + KAL_RELEASE_MUTEX(prAdapter, MUTEX_CHIP_RST); + return; + } + prAdapter->fgIsChipAssert = TRUE; + KAL_RELEASE_MUTEX(prAdapter, MUTEX_CHIP_RST); + + for (i4BssIdx = 0; i4BssIdx < prAdapter->ucHwBssIdNum; + i4BssIdx++) { + prBssInfo = prAdapter->aprBssInfo[i4BssIdx]; + + if (!prBssInfo->fgIsInUse) + continue; + + if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) { + + if (kalGetMediaStateIndicated(prGlueInfo, + i4BssIdx) == + MEDIA_STATE_CONNECTED) + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0, + i4BssIdx); + } else if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) { + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + u4ClientCount = bssGetClientCount(prAdapter, + prBssInfo); + if (u4ClientCount == 0) + continue; + + prClientList = &prBssInfo->rStaRecOfClientList; + LINK_FOR_EACH_ENTRY_SAFE(prCurrStaRec, + prNextCurrStaRec, prClientList, + rLinkEntry, struct STA_RECORD) { + if (!prCurrStaRec) + break; + kalP2PGOStationUpdate( + prAdapter->prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData, + prCurrStaRec, FALSE); + LINK_REMOVE_KNOWN_ENTRY(prClientList, + &prCurrStaRec->rLinkEntry); + } + } else if (prBssInfo->eCurrentOPMode == + OP_MODE_INFRASTRUCTURE) { + if (prBssInfo->prStaRecOfAP == NULL) + continue; +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) + kalP2PGCIndicateConnectionStatus(prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData, + NULL, NULL, 0, 0, + WLAN_STATUS_MEDIA_DISCONNECT); +#else + kalP2PGCIndicateConnectionStatus(prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData, + NULL, NULL, 0, 0); +#endif + prBssInfo->prStaRecOfAP = NULL; + + } + } + } +} + +#if CFG_ENABLE_PER_STA_STATISTICS +void wlanTxLifetimeUpdateStaStats(IN struct ADAPTER + *prAdapter, IN struct MSDU_INFO *prMsduInfo) +{ + struct STA_RECORD *prStaRec; + uint32_t u4DeltaTime; + uint32_t u4DeltaHifTxTime; + struct PKT_PROFILE *prPktProfile = &prMsduInfo->rPktProfile; +#if 0 + struct QUE_MGT *prQM = &prAdapter->rQM; + uint32_t u4PktPrintPeriod = 0; +#endif + + prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + + if (prStaRec) { + u4DeltaTime = (uint32_t) (prPktProfile->rHifTxDoneTimestamp - + prPktProfile->rHardXmitArrivalTimestamp); + u4DeltaHifTxTime = (uint32_t) ( + prPktProfile->rHifTxDoneTimestamp - + prPktProfile->rDequeueTimestamp); + + /* Update StaRec statistics */ + prStaRec->u4TotalTxPktsNumber++; + prStaRec->u4TotalTxPktsTime += u4DeltaTime; + prStaRec->u4TotalTxPktsHifTxTime += u4DeltaHifTxTime; + + if (u4DeltaTime > prStaRec->u4MaxTxPktsTime) + prStaRec->u4MaxTxPktsTime = u4DeltaTime; + + if (u4DeltaHifTxTime > prStaRec->u4MaxTxPktsHifTime) + prStaRec->u4MaxTxPktsHifTime = u4DeltaHifTxTime; + + if (u4DeltaTime >= NIC_TX_TIME_THRESHOLD) + prStaRec->u4ThresholdCounter++; + +#if 0 + if (u4PktPrintPeriod && + (prStaRec->u4TotalTxPktsNumber >= u4PktPrintPeriod)) { + DBGLOG(TX, INFO, "[%u]N[%u]A[%u]M[%u]T[%u]E[%4u]\n", + prStaRec->ucIndex, + prStaRec->u4TotalTxPktsNumber, + prStaRec->u4TotalTxPktsTime, + prStaRec->u4MaxTxPktsTime, + prStaRec->u4ThresholdCounter, + prQM->au4QmTcResourceEmptyCounter[ + prStaRec->ucBssIndex][TC2_INDEX]); + + prStaRec->u4TotalTxPktsNumber = 0; + prStaRec->u4TotalTxPktsTime = 0; + prStaRec->u4MaxTxPktsTime = 0; + prStaRec->u4ThresholdCounter = 0; + prQM->au4QmTcResourceEmptyCounter[ + prStaRec->ucBssIndex][TC2_INDEX] = 0; + } +#endif + } +} +#endif + +u_int8_t wlanTxLifetimeIsProfilingEnabled( + IN struct ADAPTER *prAdapter) +{ + u_int8_t fgEnabled = TRUE; +#if CFG_SUPPORT_WFD + struct WFD_CFG_SETTINGS *prWfdCfgSettings = + (struct WFD_CFG_SETTINGS *) NULL; + + prWfdCfgSettings = + &prAdapter->rWifiVar.rWfdConfigureSettings; + + if (prWfdCfgSettings->ucWfdEnable > 0) + fgEnabled = TRUE; +#endif + + return fgEnabled; +} + +u_int8_t wlanTxLifetimeIsTargetMsdu(IN struct ADAPTER + *prAdapter, IN struct MSDU_INFO *prMsduInfo) +{ + u_int8_t fgResult = TRUE; + +#if 0 + switch (prMsduInfo->ucTID) { + /* BK */ + case 1: + case 2: + + /* BE */ + case 0: + case 3: + fgResult = FALSE; + break; + /* VI */ + case 4: + case 5: + + /* VO */ + case 6: + case 7: + fgResult = TRUE; + break; + default: + break; + } +#endif + return fgResult; +} + +void wlanTxLifetimeTagPacket(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_PROFILING_TAG eTag) +{ + struct PKT_PROFILE *prPktProfile = &prMsduInfo->rPktProfile; + + if (!wlanTxLifetimeIsProfilingEnabled(prAdapter)) + return; + + switch (eTag) { + case TX_PROF_TAG_OS_TO_DRV: + /* arrival time is tagged in wlanProcessTxFrame */ + break; + + case TX_PROF_TAG_DRV_ENQUE: + /* Reset packet profile */ + prPktProfile->fgIsValid = FALSE; + if (wlanTxLifetimeIsTargetMsdu(prAdapter, prMsduInfo)) { + /* Enable packet lifetime profiling */ + prPktProfile->fgIsValid = TRUE; + + /* Packet arrival time at kernel Hard Xmit */ + prPktProfile->rHardXmitArrivalTimestamp = + GLUE_GET_PKT_ARRIVAL_TIME(prMsduInfo->prPacket); + + /* Packet enqueue time */ + prPktProfile->rEnqueueTimestamp = (OS_SYSTIME) + kalGetTimeTick(); + } + break; + + case TX_PROF_TAG_DRV_DEQUE: + if (prPktProfile->fgIsValid) + prPktProfile->rDequeueTimestamp = (OS_SYSTIME) + kalGetTimeTick(); + break; + + case TX_PROF_TAG_DRV_TX_DONE: + if (prPktProfile->fgIsValid) { + prPktProfile->rHifTxDoneTimestamp = (OS_SYSTIME) + kalGetTimeTick(); +#if CFG_ENABLE_PER_STA_STATISTICS + wlanTxLifetimeUpdateStaStats(prAdapter, prMsduInfo); +#endif + } + break; + default: + break; + } +} + +void wlanTxProfilingTagPacket(IN struct ADAPTER *prAdapter, + IN void *prPacket, + IN enum ENUM_TX_PROFILING_TAG eTag) +{ + if (!prPacket) + return; + +#if CFG_MET_PACKET_TRACE_SUPPORT + kalMetTagPacket(prAdapter->prGlueInfo, prPacket, eTag); +#endif + + switch (eTag) { + case TX_PROF_TAG_OS_TO_DRV: + kalTraceEvent("Xmit id=0x%04x sn=%d", + GLUE_GET_PKT_IP_ID(prPacket), + GLUE_GET_PKT_SEQ_NO(prPacket)); + break; + case TX_PROF_TAG_DRV_ENQUE: + kalTraceEvent("Enq id=0x%04x sn=%d", + GLUE_GET_PKT_IP_ID(prPacket), + GLUE_GET_PKT_SEQ_NO(prPacket)); + break; + case TX_PROF_TAG_DRV_FREE: + kalTraceEvent("Cmpl id=0x%04x sn=%d", + GLUE_GET_PKT_IP_ID(prPacket), + GLUE_GET_PKT_SEQ_NO(prPacket)); + break; + default: + break; + } +} + +void wlanTxProfilingTagMsdu(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_PROFILING_TAG eTag) +{ + wlanTxLifetimeTagPacket(prAdapter, prMsduInfo, eTag); + + if (prMsduInfo->eSrc == TX_PACKET_OS) { + /* only profile packets from OS */ + wlanTxProfilingTagPacket(prAdapter, prMsduInfo->prPacket, eTag); + } +} + +void wlanUpdateTxStatistics(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN u_int8_t fgTxDrop) +{ + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + enum ENUM_WMM_ACI eAci = WMM_AC_BE_INDEX; + struct QUE_MGT *prQM = &prAdapter->rQM; + OS_SYSTIME rCurTime; + + eAci = aucTid2ACI[prMsduInfo->ucUserPriority]; + + prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + + if (eAci >= 0 && eAci < WMM_AC_INDEX_NUM) { + if (prStaRec) { + if (fgTxDrop) + prStaRec->arLinkStatistics[eAci].u4TxDropMsdu++; + else + prStaRec->arLinkStatistics[eAci].u4TxMsdu++; + } else { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prMsduInfo->ucBssIndex); + + if (fgTxDrop) + prBssInfo->arLinkStatistics[eAci]. + u4TxDropMsdu++; + else + prBssInfo->arLinkStatistics[eAci].u4TxMsdu++; + } + } + + /* Trigger FW stats log every 20s */ + rCurTime = (OS_SYSTIME) kalGetTimeTick(); + + DBGLOG(INIT, LOUD, "CUR[%u] LAST[%u] TO[%u]\n", rCurTime, + prQM->rLastTxPktDumpTime, + CHECK_FOR_TIMEOUT(rCurTime, prQM->rLastTxPktDumpTime, + MSEC_TO_SYSTIME( + prAdapter->rWifiVar.u4StatsLogTimeout))); + + if (CHECK_FOR_TIMEOUT(rCurTime, prQM->rLastTxPktDumpTime, + MSEC_TO_SYSTIME( + prAdapter->rWifiVar.u4StatsLogTimeout))) { + + wlanTriggerStatsLog(prAdapter, + prAdapter->rWifiVar.u4StatsLogDuration); + wlanDumpAllBssStatistics(prAdapter); + + prQM->rLastTxPktDumpTime = rCurTime; + } +} + +void wlanUpdateRxStatistics(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct STA_RECORD *prStaRec; + enum ENUM_WMM_ACI eAci = WMM_AC_BE_INDEX; + + eAci = aucTid2ACI[prSwRfb->ucTid]; + + prStaRec = cnmGetStaRecByIndex(prAdapter, + prSwRfb->ucStaRecIdx); + if (prStaRec && eAci >= 0 && eAci < WMM_AC_INDEX_NUM) + prStaRec->arLinkStatistics[eAci].u4RxMsdu++; +} + +uint32_t wlanTriggerStatsLog(IN struct ADAPTER *prAdapter, + IN uint32_t u4DurationInMs) +{ + struct CMD_STATS_LOG rStatsLogCmd; + uint32_t rResult; + + if (prAdapter->fgIsEnableLpdvt) + return WLAN_STATUS_NOT_SUPPORTED; + + kalMemZero(&rStatsLogCmd, sizeof(struct CMD_STATS_LOG)); + + rStatsLogCmd.u4DurationInMs = u4DurationInMs; + + rResult = wlanSendSetQueryCmd(prAdapter, CMD_ID_STATS_LOG, TRUE, FALSE, + FALSE, nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_STATS_LOG), + (uint8_t *) &rStatsLogCmd, NULL, 0); + + return rResult; +} + +uint32_t +wlanPktTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + OS_SYSTIME rCurrent = kalGetTimeTick(); + struct PKT_PROFILE *prPktProfile = &prMsduInfo->rPktProfile; + + uint8_t *apucPktType[ENUM_PKT_FLAG_NUM] = { + (uint8_t *) DISP_STRING("INVALID"), + (uint8_t *) DISP_STRING("802_3"), + (uint8_t *) DISP_STRING("1X"), + (uint8_t *) DISP_STRING("PROTECTED_1X"), + (uint8_t *) DISP_STRING("NON_PROTECTED_1X"), + (uint8_t *) DISP_STRING("VLAN_EXIST"), + (uint8_t *) DISP_STRING("DHCP"), + (uint8_t *) DISP_STRING("ARP"), + (uint8_t *) DISP_STRING("ICMP"), + (uint8_t *) DISP_STRING("TDLS"), + (uint8_t *) DISP_STRING("DNS") + }; + if (prMsduInfo->ucPktType >= ENUM_PKT_FLAG_NUM) + prMsduInfo->ucPktType = 0; + + if (prPktProfile->fgIsValid && + ((prMsduInfo->ucPktType == ENUM_PKT_ARP) || + (prMsduInfo->ucPktType == ENUM_PKT_DHCP))) { + if (rCurrent - prPktProfile->rHardXmitArrivalTimestamp > 2000) { + DBGLOG(TX, INFO, + "valid %d; ArriveDrv %u, Enq %u, Deq %u, LeaveDrv %u, TxDone %u\n", + prPktProfile->fgIsValid, + prPktProfile->rHardXmitArrivalTimestamp, + prPktProfile->rEnqueueTimestamp, + prPktProfile->rDequeueTimestamp, + prPktProfile->rHifTxDoneTimestamp, rCurrent); + + if (prMsduInfo->ucPktType == ENUM_PKT_ARP) + prAdapter->prGlueInfo->fgTxDoneDelayIsARP = + TRUE; + prAdapter->prGlueInfo->u4ArriveDrvTick = + prPktProfile->rHardXmitArrivalTimestamp; + prAdapter->prGlueInfo->u4EnQueTick = + prPktProfile->rEnqueueTimestamp; + prAdapter->prGlueInfo->u4DeQueTick = + prPktProfile->rDequeueTimestamp; + prAdapter->prGlueInfo->u4LeaveDrvTick = + prPktProfile->rHifTxDoneTimestamp; + prAdapter->prGlueInfo->u4CurrTick = rCurrent; + prAdapter->prGlueInfo->u8CurrTime = sched_clock(); + } + } + + DBGLOG_LIMITED(TX, INFO, + "TX DONE, Type[%s] Tag[0x%08x] WIDX:PID[%u:%u] Status[%u], SeqNo: %d\n", + apucPktType[prMsduInfo->ucPktType], prMsduInfo->u4TxDoneTag, + prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, rTxDoneStatus, + prMsduInfo->ucTxSeqNum); + + if (prMsduInfo->ucPktType == ENUM_PKT_1X) + p2pRoleFsmNotifyEapolTxStatus(prAdapter, + prMsduInfo->ucBssIndex, + prMsduInfo->eEapolKeyType, + rTxDoneStatus); + +#if CFG_SUPPORT_TDLS + if (prMsduInfo->ucPktType == ENUM_PKT_TDLS) + TdlsHandleTxDoneStatus(prAdapter, rTxDoneStatus); +#endif /* CFG_SUPPORT_TDLS */ + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_ASSERT_DUMP +void wlanCorDumpTimerInit(IN struct ADAPTER *prAdapter, + u_int8_t fgIsResetN9) +{ + if (fgIsResetN9) { + cnmTimerInitTimer(prAdapter, + &prAdapter->rN9CorDumpTimer, + (PFN_MGMT_TIMEOUT_FUNC) wlanN9CorDumpTimeOut, + (unsigned long) NULL); + + } else { + cnmTimerInitTimer(prAdapter, + &prAdapter->rCr4CorDumpTimer, + (PFN_MGMT_TIMEOUT_FUNC) wlanCr4CorDumpTimeOut, + (unsigned long) NULL); + } +} + +void wlanCorDumpTimerReset(IN struct ADAPTER *prAdapter, + u_int8_t fgIsResetN9) +{ + + if (prAdapter->fgN9AssertDumpOngoing + || prAdapter->fgCr4AssertDumpOngoing) { + + if (fgIsResetN9) { + cnmTimerStopTimer(prAdapter, + &prAdapter->rN9CorDumpTimer); + cnmTimerStartTimer(prAdapter, + &prAdapter->rN9CorDumpTimer, 5000); + } else { + cnmTimerStopTimer(prAdapter, + &prAdapter->rCr4CorDumpTimer); + cnmTimerStartTimer(prAdapter, + &prAdapter->rCr4CorDumpTimer, 5000); + } + } else { + DBGLOG(INIT, INFO, + "Cr4, N9 CorDump Is not ongoing, ignore timer reset\n"); + } +} + +void wlanN9CorDumpTimeOut(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr) +{ + + if (prAdapter->fgN9CorDumpFileOpend) { + DBGLOG(INIT, INFO, "\n[DUMP_N9]====N9 ASSERT_END====\n"); + prAdapter->fgN9AssertDumpOngoing = FALSE; + kalCloseCorDumpFile(TRUE); + prAdapter->fgN9CorDumpFileOpend = FALSE; + } + + /* Trigger RESET */ + glSetRstReason(RST_FW_ASSERT); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_CHIP_RESET); + +} + +void wlanCr4CorDumpTimeOut(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr) +{ + + if (prAdapter->fgCr4CorDumpFileOpend) { + DBGLOG(INIT, INFO, "\n[DUMP_Cr4]====Cr4 ASSERT_END====\n"); + prAdapter->fgCr4AssertDumpOngoing = FALSE; + kalCloseCorDumpFile(FALSE); + prAdapter->fgCr4CorDumpFileOpend = FALSE; + } + + /* Trigger RESET */ + glSetRstReason(RST_FW_ASSERT); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_CHIP_RESET); +} +#endif + +u_int8_t +wlanGetWlanIdxByAddress(IN struct ADAPTER *prAdapter, + IN uint8_t *pucAddr, OUT uint8_t *pucIndex) +{ + uint8_t ucStaRecIdx; + struct STA_RECORD *prTempStaRec; + + for (ucStaRecIdx = 0; ucStaRecIdx < CFG_STA_REC_NUM; + ucStaRecIdx++) { + prTempStaRec = &(prAdapter->arStaRec[ucStaRecIdx]); + if (pucAddr) { + if (prTempStaRec->fgIsInUse && + EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, + pucAddr)) { + *pucIndex = prTempStaRec->ucWlanIndex; + return TRUE; + } + } else { + if (prTempStaRec->fgIsInUse + && prTempStaRec->ucStaState == STA_STATE_3) { + *pucIndex = prTempStaRec->ucWlanIndex; + return TRUE; + } + } + } + return FALSE; +} + + +uint8_t * +wlanGetStaAddrByWlanIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucIndex) +{ + struct WLAN_TABLE *prWtbl; + + ASSERT(prAdapter); + prWtbl = prAdapter->rWifiVar.arWtbl; + if (ucIndex < WTBL_SIZE) { + if (prWtbl[ucIndex].ucUsed && prWtbl[ucIndex].ucPairwise) + return &prWtbl[ucIndex].aucMacAddr[0]; + } + return NULL; +} + +void +wlanNotifyFwSuspend(struct GLUE_INFO *prGlueInfo, + struct net_device *prDev, u_int8_t fgSuspend) +{ + uint32_t rStatus; + uint32_t u4SetInfoLen; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = + (struct NETDEV_PRIVATE_GLUE_INFO *) NULL; + struct CMD_SUSPEND_MODE_SETTING rSuspendCmd; + + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prDev); + + if (prNetDevPrivate->prGlueInfo != prGlueInfo) + DBGLOG(REQ, WARN, "%s: unexpected prGlueInfo(0x%p)!\n", + __func__, prNetDevPrivate->prGlueInfo); + + rSuspendCmd.ucBssIndex = prNetDevPrivate->ucBssIdx; + rSuspendCmd.ucEnableSuspendMode = fgSuspend; + + if (prGlueInfo->prAdapter->rWifiVar.ucWow + && prGlueInfo->prAdapter->rWowCtrl.fgWowEnable) { + /* cfg enable + wow enable => Wow On mdtim*/ + rSuspendCmd.ucMdtim = + prGlueInfo->prAdapter->rWifiVar.ucWowOnMdtim; + DBGLOG(REQ, INFO, "mdtim [1]\n"); + } else if (prGlueInfo->prAdapter->rWifiVar.ucWow + && !prGlueInfo->prAdapter->rWowCtrl.fgWowEnable) { + if (prGlueInfo->prAdapter->rWifiVar.ucAdvPws) { + /* cfg enable + wow disable + adv pws enable + * => Wow Off mdtim + */ + rSuspendCmd.ucMdtim = + prGlueInfo->prAdapter->rWifiVar.ucWowOffMdtim; + DBGLOG(REQ, INFO, "mdtim [2]\n"); + } + } else if (!prGlueInfo->prAdapter->rWifiVar.ucWow) { + if (prGlueInfo->prAdapter->rWifiVar.ucAdvPws) { + /* cfg disable + adv pws enable => MT6632 case + * => Wow Off mdtim + */ + rSuspendCmd.ucMdtim = + prGlueInfo->prAdapter->rWifiVar.ucWowOffMdtim; + DBGLOG(REQ, INFO, "mdtim [3]\n"); + } + } + + /* When FW receive command, it check connection state to decide apply + * setting or not + */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidNotifyFwSuspend, + (void *)&rSuspendCmd, + sizeof(rSuspendCmd), + FALSE, + FALSE, + TRUE, + &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, INFO, "wlanNotifyFwSuspend fail\n"); +} + +uint32_t +wlanGetStaIdxByWlanIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucIndex, OUT uint8_t *pucStaIdx) +{ + struct WLAN_TABLE *prWtbl; + + ASSERT(prAdapter); + prWtbl = prAdapter->rWifiVar.arWtbl; + + if (ucIndex < WTBL_SIZE) { + if (prWtbl[ucIndex].ucUsed && prWtbl[ucIndex].ucPairwise) { + *pucStaIdx = prWtbl[ucIndex].ucStaIndex; + return WLAN_STATUS_SUCCESS; + } + } + return WLAN_STATUS_FAILURE; +} + +struct wiphy *wlanGetWiphy(void) +{ + if (gprWdev[0]) + return gprWdev[0]->wiphy; + + return NULL; +} + +struct net_device *wlanGetNetDev(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucBssIndex) +{ + if (!prGlueInfo) + return NULL; + + /* AIS */ + if (ucBssIndex < KAL_AIS_NUM && gprWdev[ucBssIndex]) + return gprWdev[ucBssIndex]->netdev; + + /* P2P */ + if (ucBssIndex < BSS_DEFAULT_NUM) { + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + struct GL_P2P_INFO *prGlueP2pInfo = + (struct GL_P2P_INFO *) NULL; + + prBssInfo = + GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, + ucBssIndex); + + if (prBssInfo && IS_BSS_P2P(prBssInfo)) { + prGlueP2pInfo = + prGlueInfo->prP2PInfo[prBssInfo->u4PrivateData]; + if (prGlueP2pInfo) + return prGlueP2pInfo->prDevHandler; + } + } + + return NULL; +} + +uint8_t wlanGetBssIdx(struct net_device *ndev) +{ + if (ndev) { + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate + = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(ndev); + + DBGLOG(REQ, LOUD, + "ucBssIndex = %d, ndev(%p)\n", + prNetDevPrivate->ucBssIdx, + ndev); + + return prNetDevPrivate->ucBssIdx; + } + + DBGLOG(REQ, LOUD, + "ucBssIndex = 0xff, ndev(%p)\n", + ndev); + + return 0xff; +} + +u_int8_t wlanIsAisDev(struct net_device *prDev) +{ + uint32_t u4Idx = 0; + + for (u4Idx = 0; u4Idx < KAL_AIS_NUM; u4Idx++) + if (prDev == gprWdev[u4Idx]->netdev) + return TRUE; + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to query LTE safe channels. + * + * \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_PENDING + * \retval WLAN_STATUS_FAILURE + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanQueryLteSafeChannel(IN struct ADAPTER *prAdapter, + IN uint8_t ucRoleIndex) +{ + uint32_t rResult = WLAN_STATUS_FAILURE; + struct CMD_GET_LTE_SAFE_CHN rQuery_LTE_SAFE_CHN; + struct PARAM_GET_CHN_INFO *prQueryLteChn; + + DBGLOG(P2P, TRACE, "[ACS] Get safe LTE Channels\n"); + + do { + if (!prAdapter) + break; + + prQueryLteChn = kalMemAlloc(sizeof(struct PARAM_GET_CHN_INFO), + VIR_MEM_TYPE); + if (!prQueryLteChn) + break; + + kalMemZero(prQueryLteChn, sizeof(struct PARAM_GET_CHN_INFO)); + prQueryLteChn->ucRoleIndex = ucRoleIndex; + + /* Get LTE safe channel list */ + wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LTE_CHN, + FALSE, + TRUE, + FALSE, /* Query ID */ + nicCmdEventQueryLteSafeChn, /* The handler to receive + * firmware notification + */ + nicOidCmdTimeoutCommon, + sizeof(struct CMD_GET_LTE_SAFE_CHN), + (uint8_t *)&rQuery_LTE_SAFE_CHN, + prQueryLteChn, + 0); + rResult = WLAN_STATUS_SUCCESS; + } while (FALSE); + + return rResult; +} /* wlanoidQueryLteSafeChannel */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Add dirtiness to neighbor channels of a BSS to estimate channel + * quality. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] prBssDesc Pointer to the BSS description. + * \param[in] u4Dirtiness Expected dirtiness value. + * \param[in] ucCentralChannel Central channel of the given BSS. + * \param[in] ucCoveredRange With ucCoveredRange and ucCentralChannel, + * all the affected channels can be enumerated. + */ +/*----------------------------------------------------------------------------*/ +static void +wlanAddDirtinessToAffectedChannels(struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc, + uint32_t u4Dirtiness, + uint8_t ucCentralChannel, + uint8_t ucCoveredRange) +{ + uint8_t ucIdx, ucStart, ucEnd; + u_int8_t bIs5GChl = ucCentralChannel > 14; + uint8_t ucLeftNeighborChannel, ucRightNeighborChannel, + ucLeftNeighborChannel2 = 0, ucRightNeighborChannel2 = 0, + ucLeftestCoveredChannel, ucRightestCoveredChannel; + struct PARAM_GET_CHN_INFO *prGetChnLoad = & + (prAdapter->rWifiVar.rChnLoadInfo); + + ucLeftestCoveredChannel = ucCentralChannel > ucCoveredRange + ? + ucCentralChannel - ucCoveredRange : 1; + + ucLeftNeighborChannel = ucLeftestCoveredChannel ? + ucLeftestCoveredChannel - 1 : 0; + + /* align leftest covered ch and left neighbor ch to valid 5g ch */ + if (bIs5GChl) { + ucLeftestCoveredChannel += 2; + ucLeftNeighborChannel -= 1; + } else { + /* we select the nearest 2 ch to the leftest covered ch as left + * neighbor chs + */ + ucLeftNeighborChannel2 = ucLeftNeighborChannel > 1 ? + ucLeftNeighborChannel - 1 : 0; + } + + /* handle corner cases of 5g ch*/ + if (ucLeftestCoveredChannel > 14 + && ucLeftestCoveredChannel <= 36) { + ucLeftestCoveredChannel = 36; + ucLeftNeighborChannel = 0; + } else if (ucLeftestCoveredChannel > 64 + && ucLeftestCoveredChannel <= 100) { + ucLeftestCoveredChannel = 100; + ucLeftNeighborChannel = 0; + } else if (ucLeftestCoveredChannel > 144 && + ucLeftestCoveredChannel <= 149) { + ucLeftestCoveredChannel = 149; + ucLeftNeighborChannel = 0; + } + + /* + * because ch 14 is 12MHz away to ch13, we must shift the leftest + * covered ch and left neighbor ch when central ch is ch 14 + */ + if (ucCentralChannel == 14) { + ucLeftestCoveredChannel = 13; + ucLeftNeighborChannel = 12; + ucLeftNeighborChannel2 = 11; + } + + ucRightestCoveredChannel = ucCentralChannel + + ucCoveredRange; + ucRightNeighborChannel = ucRightestCoveredChannel + 1; + + /* align rightest covered ch and right neighbor ch to valid 5g ch */ + if (bIs5GChl) { + ucRightestCoveredChannel -= 2; + ucRightNeighborChannel += 1; + } else { + /* we select the nearest 2 ch to the rightest covered ch as + * right neighbor ch + */ + ucRightNeighborChannel2 = ucRightNeighborChannel < 13 ? + ucRightNeighborChannel + 1 : 0; + } + + /* handle corner cases */ + if (ucRightestCoveredChannel >= 14 + && ucRightestCoveredChannel < 36) { + if (ucRightestCoveredChannel == 14) { + ucRightestCoveredChannel = 13; + ucRightNeighborChannel = 14; + } else { + ucRightestCoveredChannel = 14; + ucRightNeighborChannel = 0; + } + + ucRightNeighborChannel2 = 0; + } else if (ucRightestCoveredChannel >= 64 + && ucRightestCoveredChannel < 100) { + ucRightestCoveredChannel = 64; + ucRightNeighborChannel = 0; + } else if (ucRightestCoveredChannel >= 144 && + ucRightestCoveredChannel < 149) { + ucRightestCoveredChannel = 144; + ucRightNeighborChannel = 0; + } else if (ucRightestCoveredChannel >= 165) { + ucRightestCoveredChannel = 165; + ucRightNeighborChannel = 0; + } + + log_dbg(SCN, TEMP, "central ch %u\n", ucCentralChannel); + + ucStart = wlanGetChannelIndex(ucLeftestCoveredChannel); + ucEnd = wlanGetChannelIndex(ucRightestCoveredChannel); + if (ucStart >= MAX_CHN_NUM || ucEnd >= MAX_CHN_NUM) { + DBGLOG(SCN, ERROR, "Invalid ch idx of start %u, or end %u\n", + ucStart, ucEnd); + return; + } + + for (ucIdx = ucStart; ucIdx <= ucEnd; ucIdx++) { + prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtiness += + u4Dirtiness; + log_dbg(SCN, TEMP, "Add dirtiness %d, to covered ch %d\n", + u4Dirtiness, + prGetChnLoad->rEachChnLoad[ucIdx].ucChannel); + } + + if (ucLeftNeighborChannel != 0) { + ucIdx = wlanGetChannelIndex(ucLeftNeighborChannel); + + if (ucIdx < MAX_CHN_NUM) { + prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtiness += + (u4Dirtiness >> 1); + log_dbg(SCN, TEMP, + "Add dirtiness %d, to neighbor ch %d\n", + u4Dirtiness >> 1, + prGetChnLoad->rEachChnLoad[ucIdx].ucChannel); + } + } + + if (ucRightNeighborChannel != 0) { + ucIdx = wlanGetChannelIndex(ucRightNeighborChannel); + if (ucIdx < MAX_CHN_NUM) { + prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtiness += + (u4Dirtiness >> 1); + log_dbg(SCN, TEMP, + "Add dirtiness %d, to neighbor ch %d\n", + u4Dirtiness >> 1, + prGetChnLoad->rEachChnLoad[ucIdx].ucChannel); + } + } + + if (bIs5GChl) + return; + + /* Only necesaary for 2.5G */ + if (ucLeftNeighborChannel2 != 0) { + ucIdx = wlanGetChannelIndex(ucLeftNeighborChannel2); + if (ucIdx < MAX_CHN_NUM) { + prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtiness += + (u4Dirtiness >> 1); + log_dbg(SCN, TEMP, + "Add dirtiness %d, to neighbor ch %d\n", + u4Dirtiness >> 1, + prGetChnLoad->rEachChnLoad[ucIdx].ucChannel); + } + } + + if (ucRightNeighborChannel2 != 0) { + ucIdx = wlanGetChannelIndex(ucRightNeighborChannel2); + if (ucIdx < MAX_CHN_NUM) { + prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtiness += + (u4Dirtiness >> 1); + log_dbg(SCN, TEMP, + "Add dirtiness %d, to neighbor ch %d\n", + u4Dirtiness >> 1, + prGetChnLoad->rEachChnLoad[ucIdx].ucChannel); + } + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief For a scanned BSS, add dirtiness to the channels 1)around its primary + * channels and 2) in its working BW to represent the quality degrade. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] prBssDesc Pointer to the BSS description. + * \param[in] u4Dirtiness Expected dirtiness value. + * \param[in] bIsIndexOne True means index 1, False means index 2. + */ +/*----------------------------------------------------------------------------*/ +static void +wlanCalculateChannelDirtiness(IN struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc, uint32_t u4Dirtiness, + u_int8_t bIsIndexOne) +{ + uint8_t ucCoveredRange = 0, ucCentralChannel = 0, + ucCentralChannel2 = 0; + + if (bIsIndexOne) { + DBGLOG(SCN, TEMP, "Process dirtiness index 1\n"); + ucCentralChannel = prBssDesc->ucChannelNum; + ucCoveredRange = 2; + } else { + DBGLOG(SCN, TEMP, "Process dirtiness index 2, "); + switch (prBssDesc->eChannelWidth) { + case CW_20_40MHZ: + if (prBssDesc->eSco == CHNL_EXT_SCA) { + DBGLOG(SCN, TEMP, "BW40\n"); + ucCentralChannel = prBssDesc->ucChannelNum + 2; + ucCoveredRange = 4; + } else if (prBssDesc->eSco == CHNL_EXT_SCB) { + DBGLOG(SCN, TEMP, "BW40\n"); + ucCentralChannel = prBssDesc->ucChannelNum - 2; + ucCoveredRange = 4; + } else { + DBGLOG(SCN, TEMP, "BW20\n"); + ucCentralChannel = prBssDesc->ucChannelNum; + ucCoveredRange = 2; + } + break; + case CW_80MHZ: + DBGLOG(SCN, TEMP, "BW80\n"); + ucCentralChannel = prBssDesc->ucCenterFreqS1; + ucCoveredRange = 8; + break; + case CW_160MHZ: + DBGLOG(SCN, TEMP, "BW160\n"); + ucCentralChannel = prBssDesc->ucCenterFreqS1; + ucCoveredRange = 16; + break; + case CW_80P80MHZ: + DBGLOG(SCN, TEMP, "BW8080\n"); + ucCentralChannel = prBssDesc->ucCenterFreqS1; + ucCentralChannel2 = prBssDesc->ucCenterFreqS2; + ucCoveredRange = 8; + break; + default: + ucCentralChannel = prBssDesc->ucChannelNum; + ucCoveredRange = 2; + break; + }; + } + + wlanAddDirtinessToAffectedChannels(prAdapter, prBssDesc, + u4Dirtiness, + ucCentralChannel, ucCoveredRange); + + /* 80 + 80 secondary 80 case */ + if (bIsIndexOne || ucCentralChannel2 == 0) + return; + + wlanAddDirtinessToAffectedChannels(prAdapter, prBssDesc, + u4Dirtiness, + ucCentralChannel2, ucCoveredRange); +} + +void +wlanInitChnLoadInfoChannelList(IN struct ADAPTER *prAdapter) +{ + uint8_t ucIdx = 0; + struct PARAM_GET_CHN_INFO *prGetChnLoad = & + (prAdapter->rWifiVar.rChnLoadInfo); + + for (ucIdx = 0; ucIdx < MAX_CHN_NUM; ucIdx++) + prGetChnLoad->rEachChnLoad[ucIdx].ucChannel = + wlanGetChannelNumFromIndex(ucIdx); +} + +uint32_t +wlanCalculateAllChannelDirtiness(IN struct ADAPTER + *prAdapter) +{ + uint32_t rResult = WLAN_STATUS_SUCCESS; + int32_t i4Rssi = 0; + struct BSS_DESC *prBssDesc = NULL; + uint32_t u4Dirtiness = 0; + struct LINK *prBSSDescList = + &(prAdapter->rWifiVar.rScanInfo.rBSSDescList); + + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, + struct BSS_DESC) { + i4Rssi = RCPI_TO_dBm(prBssDesc->ucRCPI); + + if (i4Rssi >= ACS_AP_RSSI_LEVEL_HIGH) + u4Dirtiness = ACS_DIRTINESS_LEVEL_HIGH; + else if (i4Rssi >= ACS_AP_RSSI_LEVEL_LOW) + u4Dirtiness = ACS_DIRTINESS_LEVEL_MID; + else + u4Dirtiness = ACS_DIRTINESS_LEVEL_LOW; + + DBGLOG(SCN, TEMP, "Found an AP(%s), primary ch %d\n", + prBssDesc->aucSSID, prBssDesc->ucChannelNum); + + /* dirtiness index1 */ + wlanCalculateChannelDirtiness(prAdapter, prBssDesc, + u4Dirtiness, TRUE); + + /* dirtiness index2 */ + wlanCalculateChannelDirtiness(prAdapter, prBssDesc, + u4Dirtiness >> 1, FALSE); + } + + return rResult; +} + +uint8_t +wlanGetChannelIndex(IN uint8_t channel) +{ + uint8_t ucIdx = MAX_CHN_NUM - 1; + + if (channel <= 14) + ucIdx = channel - 1; + else if (channel >= 36 && channel <= 64) + ucIdx = 14 + (channel - 36) / 4; + else if (channel >= 100 && channel <= 144) + ucIdx = 14 + 8 + (channel - 100) / 4; + else if (channel >= 149 && channel <= 165) + ucIdx = 14 + 8 + 12 + (channel - 149) / 4; + + return ucIdx; +} + +/*---------------------------------------------------------------------*/ +/*! + * \brief Get ch index by the given ch num; the reverse function of + * wlanGetChannelIndex + * + * \param[in] ucIdx Channel index + * \param[out] ucChannel Channel number + */ +/*---------------------------------------------------------------------*/ + +uint8_t +wlanGetChannelNumFromIndex(IN uint8_t ucIdx) +{ + uint8_t ucChannel = 0; + + if (ucIdx >= 34) + ucChannel = ((ucIdx - 34) << 2) + 149; + else if (ucIdx >= 22) + ucChannel = ((ucIdx - 22) << 2) + 100; + else if (ucIdx >= 14) + ucChannel = ((ucIdx - 14) << 2) + 36; + else + ucChannel = ucIdx + 1; + + return ucChannel; +} + +void +wlanSortChannel(IN struct ADAPTER *prAdapter, +IN enum ENUM_CHNL_SORT_POLICY ucSortType) +{ + struct PARAM_GET_CHN_INFO *prChnLoadInfo = & + (prAdapter->rWifiVar.rChnLoadInfo); + int8_t ucIdx = 0, ucRoot = 0, ucChild = 0; +#if (CFG_SUPPORT_P2PGO_ACS == 1) + uint8_t i = 0, ucBandIdx = 0, ucNumOfChannel = 0, uc2gChNum = 0; + struct RF_CHANNEL_INFO aucChannelList[MAX_CHN_NUM] = { { 0 } }; +#endif + struct PARAM_CHN_RANK_INFO rChnRankInfo; + /* prepare unsorted ch rank list */ +#if (CFG_SUPPORT_P2PGO_ACS == 1) + if (ucSortType == CHNL_SORT_POLICY_BY_CH_DOMAIN) { + for (ucBandIdx = BAND_2G4; ucBandIdx <= BAND_5G; ucBandIdx++) { + rlmDomainGetChnlList(prAdapter, + ucBandIdx, + TRUE, + MAX_CHN_NUM, + &ucNumOfChannel, + aucChannelList); + DBGLOG(SCN, TRACE, "[ACS]Band=%d, Channel Number=%d\n", + ucBandIdx, + ucNumOfChannel); + for (i = 0; i < ucNumOfChannel; i++) { + ucIdx = + wlanGetChannelIndex( + aucChannelList[i].ucChannelNum); + prChnLoadInfo-> + rChnRankList[uc2gChNum+i].ucChannel = + prChnLoadInfo-> + rEachChnLoad[ucIdx].ucChannel; + prChnLoadInfo-> + rChnRankList[uc2gChNum+i].u4Dirtiness = + prChnLoadInfo-> + rEachChnLoad[ucIdx].u4Dirtiness; + DBGLOG(SCN, TRACE, "[ACS]Ch=%d eIdx=%d,Cidx[%d]", + aucChannelList[i].ucChannelNum, + ucIdx, + uc2gChNum+i); + DBGLOG(SCN, TRACE, "[ACS]ChR[%d],eCh[%d]\n", + prChnLoadInfo-> + rChnRankList[uc2gChNum+i].ucChannel, + prChnLoadInfo-> + rEachChnLoad[ucIdx].ucChannel); + } + uc2gChNum = uc2gChNum+ucNumOfChannel; + } + /*Set the reset idx to invalid value*/ + for (i = uc2gChNum; i < MAX_CHN_NUM; i++) { + prChnLoadInfo-> + rChnRankList[i].u4Dirtiness = 0xFFFFFFFF; + prChnLoadInfo-> + rChnRankList[i].ucChannel = 0xFF; + DBGLOG(SCN, TRACE, "uc2gChNum=%d,[ACS]Chn=%d,D=%x\n", + uc2gChNum, + prChnLoadInfo-> + rChnRankList[i].ucChannel, + prChnLoadInfo-> + rChnRankList[i].u4Dirtiness); + } + } else +#endif + { + for (ucIdx = 0; ucIdx < MAX_CHN_NUM; ++ucIdx) { + prChnLoadInfo-> + rChnRankList[ucIdx].ucChannel = + prChnLoadInfo-> + rEachChnLoad[ucIdx].ucChannel; + prChnLoadInfo-> + rChnRankList[ucIdx].u4Dirtiness = + prChnLoadInfo-> + rEachChnLoad[ucIdx].u4Dirtiness; + } + } + /* heapify ch rank list */ + for (ucIdx = MAX_CHN_NUM / 2 - 1; ucIdx >= 0; --ucIdx) { + for (ucRoot = ucIdx; ucRoot * 2 + 1 < MAX_CHN_NUM; + ucRoot = ucChild) { + ucChild = ucRoot * 2 + 1; + /* Coverity check*/ + if (ucChild < 0 || ucChild >= MAX_CHN_NUM || + ucRoot < 0 || ucRoot >= MAX_CHN_NUM) + break; + if (ucChild < MAX_CHN_NUM - 1 && prChnLoadInfo-> + rChnRankList[ucChild + 1].u4Dirtiness > + prChnLoadInfo->rChnRankList[ucChild].u4Dirtiness) + ucChild += 1; + if (prChnLoadInfo->rChnRankList[ucChild].u4Dirtiness <= + prChnLoadInfo->rChnRankList[ucRoot].u4Dirtiness) + break; + DBGLOG(SCN, TRACE, "[ACS]root Chn=%d,D=%x\n", + prChnLoadInfo-> + rChnRankList[ucRoot].ucChannel, + prChnLoadInfo-> + rChnRankList[ucRoot].u4Dirtiness); + DBGLOG(SCN, TRACE, "[ACS]child Chn=%d,D=%x\n", + prChnLoadInfo-> + rChnRankList[ucChild].ucChannel, + prChnLoadInfo-> + rChnRankList[ucChild].u4Dirtiness); + kalMemCopy(&rChnRankInfo, + &(prChnLoadInfo->rChnRankList[ucChild]), + sizeof(struct PARAM_CHN_RANK_INFO)); + kalMemCopy(&prChnLoadInfo->rChnRankList[ucChild], + &prChnLoadInfo->rChnRankList[ucRoot], + sizeof(struct PARAM_CHN_RANK_INFO)); + kalMemCopy(&prChnLoadInfo->rChnRankList[ucRoot], + &rChnRankInfo, + sizeof(struct PARAM_CHN_RANK_INFO)); + DBGLOG(SCN, TRACE, + "[ACS]After root uChn=%d,D=%x\n", + prChnLoadInfo-> + rChnRankList[ucRoot].ucChannel, + prChnLoadInfo-> + rChnRankList[ucRoot].u4Dirtiness); + DBGLOG(SCN, TRACE, + "[ACS]AFter child Chn=%d,D=%x\n", + prChnLoadInfo-> + rChnRankList[ucChild].ucChannel, + prChnLoadInfo-> + rChnRankList[ucChild].u4Dirtiness); + } + } + /* sort ch rank list */ + for (ucIdx = MAX_CHN_NUM - 1; ucIdx > 0; ucIdx--) { + rChnRankInfo = prChnLoadInfo->rChnRankList[0]; + prChnLoadInfo->rChnRankList[0] = + prChnLoadInfo->rChnRankList[ucIdx]; + prChnLoadInfo->rChnRankList[ucIdx] = rChnRankInfo; + for (ucRoot = 0; ucRoot * 2 + 1 < ucIdx; ucRoot = ucChild) { + ucChild = ucRoot * 2 + 1; + /* Coverity check*/ + if (ucChild < 0 || ucChild >= MAX_CHN_NUM || + ucRoot < 0 || ucRoot >= MAX_CHN_NUM) + break; + if (ucChild < ucIdx - 1 && prChnLoadInfo-> + rChnRankList[ucChild + 1].u4Dirtiness > + prChnLoadInfo->rChnRankList[ucChild].u4Dirtiness) + ucChild += 1; + if (prChnLoadInfo->rChnRankList[ucChild].u4Dirtiness <= + prChnLoadInfo->rChnRankList[ucRoot].u4Dirtiness) + break; + DBGLOG(SCN, TRACE, + "[ACS]root ChNum=%d D=%x", + prChnLoadInfo-> + rChnRankList[ucRoot].ucChannel, + prChnLoadInfo-> + rChnRankList[ucRoot].u4Dirtiness); + DBGLOG(SCN, TRACE, "[ACS]child ChNum=%d D=%x\n", + prChnLoadInfo-> + rChnRankList[ucChild].ucChannel, + prChnLoadInfo-> + rChnRankList[ucChild].u4Dirtiness); + kalMemCopy(&rChnRankInfo, + &(prChnLoadInfo->rChnRankList[ucChild]), + sizeof(struct PARAM_CHN_RANK_INFO)); + kalMemCopy(&prChnLoadInfo->rChnRankList[ucChild], + &prChnLoadInfo->rChnRankList[ucRoot], + sizeof(struct PARAM_CHN_RANK_INFO)); + kalMemCopy(&prChnLoadInfo->rChnRankList[ucRoot], + &rChnRankInfo, + sizeof(struct PARAM_CHN_RANK_INFO)); + DBGLOG(SCN, TRACE, + "[ACS]New root ChNum=%d D=%x", + prChnLoadInfo-> + rChnRankList[ucRoot].ucChannel, + prChnLoadInfo-> + rChnRankList[ucRoot].u4Dirtiness); + + DBGLOG(SCN, TRACE, + "[ACS]New child ChNum=%d D=%x", + prChnLoadInfo-> + rChnRankList[ucChild].ucChannel, + prChnLoadInfo-> + rChnRankList[ucChild].u4Dirtiness); + } + } + + for (ucIdx = 0; ucIdx < MAX_CHN_NUM; ++ucIdx) { + DBGLOG(SCN, TRACE, "[ACS]channel=%d,dirtiness=%d\n", + prChnLoadInfo->rChnRankList[ucIdx].ucChannel, + prChnLoadInfo->rChnRankList[ucIdx].u4Dirtiness); + } + +} + +#if ((CFG_SISO_SW_DEVELOP == 1) || (CFG_SUPPORT_SPE_IDX_CONTROL == 1)) +uint8_t +wlanGetAntPathType(IN struct ADAPTER *prAdapter, + IN enum ENUM_WF_PATH_FAVOR_T eWfPathFavor) +{ + uint8_t ucFianlWfPathType = eWfPathFavor; +#if (CFG_SUPPORT_SPE_IDX_CONTROL == 1) + uint8_t ucNss = prAdapter->rWifiVar.ucNSS; + uint8_t ucSpeIdxCtrl = prAdapter->rWifiVar.ucSpeIdxCtrl; + + if (ucNss <= 2) { + if (ucSpeIdxCtrl == 0) + ucFianlWfPathType = ENUM_WF_0_ONE_STREAM_PATH_FAVOR; + else if (ucSpeIdxCtrl == 1) + ucFianlWfPathType = ENUM_WF_1_ONE_STREAM_PATH_FAVOR; + else if (ucSpeIdxCtrl == 2) { + if (ucNss > 1) + ucFianlWfPathType = + ENUM_WF_0_1_DUP_STREAM_PATH_FAVOR; + else + ucFianlWfPathType = ENUM_WF_NON_FAVOR; + } else + ucFianlWfPathType = ENUM_WF_NON_FAVOR; + } +#endif + return ucFianlWfPathType; +} + +uint8_t +wlanAntPathFavorSelect(IN struct ADAPTER *prAdapter, + IN enum ENUM_WF_PATH_FAVOR_T eWfPathFavor) +{ + uint8_t ucRetValSpeIdx = 0x18; +#if (CFG_SUPPORT_SPE_IDX_CONTROL == 1) + uint8_t ucNss = prAdapter->rWifiVar.ucNSS; + + if (ucNss <= 2) { + if ((eWfPathFavor == ENUM_WF_NON_FAVOR) || + (eWfPathFavor == ENUM_WF_0_ONE_STREAM_PATH_FAVOR) || + (eWfPathFavor == ENUM_WF_0_1_TWO_STREAM_PATH_FAVOR)) + ucRetValSpeIdx = ANTENNA_WF0; + else if (eWfPathFavor == ENUM_WF_0_1_DUP_STREAM_PATH_FAVOR) + ucRetValSpeIdx = 0x18; + else if (eWfPathFavor == ENUM_WF_1_ONE_STREAM_PATH_FAVOR) + ucRetValSpeIdx = ANTENNA_WF1; + else + ucRetValSpeIdx = ANTENNA_WF0; + } +#endif + return ucRetValSpeIdx; +} +#endif + +uint8_t +wlanGetSpeIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN enum ENUM_WF_PATH_FAVOR_T eWfPathFavor) +{ + uint8_t ucRetValSpeIdx = 0; +#if ((CFG_SISO_SW_DEVELOP == 1) || (CFG_SUPPORT_SPE_IDX_CONTROL == 1)) + struct BSS_INFO *prBssInfo; + enum ENUM_BAND eBand = BAND_NULL; + + if (ucBssIndex > prAdapter->ucHwBssIdNum) { + DBGLOG(SW4, INFO, "Invalid BssInfo index[%u], skip dump!\n", + ucBssIndex); + return ucRetValSpeIdx; + } + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + /* + * if DBDC enable return 0, else depend 2.4G/5G & support WF path + * retrun accurate value + */ + if (!prAdapter->rWifiVar.fgDbDcModeEn) { + if (prBssInfo->fgIsGranted) + eBand = prBssInfo->eBandGranted; + else + eBand = prBssInfo->eBand; + + if (eBand == BAND_2G4) { + if (IS_WIFI_2G4_SISO(prAdapter)) { + if (IS_WIFI_2G4_WF0_SUPPORT(prAdapter)) + ucRetValSpeIdx = ANTENNA_WF0; + else + ucRetValSpeIdx = ANTENNA_WF1; + } else { + if (IS_WIFI_SMART_GEAR_SUPPORT_WF0_SISO( + prAdapter)) + ucRetValSpeIdx = ANTENNA_WF0; + else if (IS_WIFI_SMART_GEAR_SUPPORT_WF1_SISO( + prAdapter)) + ucRetValSpeIdx = ANTENNA_WF1; + else + ucRetValSpeIdx = wlanAntPathFavorSelect( + prAdapter, eWfPathFavor); + } + } else if (eBand == BAND_5G) { + if (IS_WIFI_5G_SISO(prAdapter)) { + if (IS_WIFI_5G_WF0_SUPPORT(prAdapter)) + ucRetValSpeIdx = ANTENNA_WF0; + else + ucRetValSpeIdx = ANTENNA_WF1; + } else { + if (IS_WIFI_SMART_GEAR_SUPPORT_WF0_SISO( + prAdapter)) + ucRetValSpeIdx = ANTENNA_WF0; + else if (IS_WIFI_SMART_GEAR_SUPPORT_WF1_SISO( + prAdapter)) + ucRetValSpeIdx = ANTENNA_WF1; + else + ucRetValSpeIdx = wlanAntPathFavorSelect( + prAdapter, eWfPathFavor); + } + } else + ucRetValSpeIdx = wlanAntPathFavorSelect(prAdapter, + eWfPathFavor); + } + DBGLOG(INIT, INFO, "SpeIdx:%d,D:%d,G=%d,B=%d,Bss=%d\n", + ucRetValSpeIdx, prAdapter->rWifiVar.fgDbDcModeEn, + prBssInfo->fgIsGranted, eBand, ucBssIndex); +#endif + return ucRetValSpeIdx; +} + +uint8_t +wlanGetSupportNss(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + struct BSS_INFO *prBssInfo; + struct AIS_FSM_INFO *prAisFsmInfo; +#if CFG_SUPPORT_IOT_AP_BLACKLIST + struct BSS_DESC *prBssDesc; +#endif + + uint8_t ucRetValNss = prAdapter->rWifiVar.ucNSS; +#if CFG_SISO_SW_DEVELOP + enum ENUM_BAND eBand = BAND_NULL; +#endif + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + if (IS_BSS_APGO(prBssInfo)) { + if (p2pFuncIsAPMode( + prAdapter->rWifiVar.prP2PConnSettings + [prBssInfo->u4PrivateData])) { + if (prBssInfo->eBand == BAND_2G4) + ucRetValNss = prAdapter->rWifiVar.ucAp2gNSS; + else if (prBssInfo->eBand == BAND_5G) + ucRetValNss = prAdapter->rWifiVar.ucAp5gNSS; + } else { + if (prBssInfo->eBand == BAND_2G4) + ucRetValNss = prAdapter->rWifiVar.ucGo2gNSS; + else if (prBssInfo->eBand == BAND_5G) + ucRetValNss = prAdapter->rWifiVar.ucGo5gNSS; + } + } +#if CFG_SUPPORT_IOT_AP_BLACKLIST + else if (IS_BSS_AIS(prBssInfo) && prAisFsmInfo != NULL) { + prBssDesc = prAisFsmInfo->prTargetBssDesc; + if (prBssDesc != NULL && + bssGetIotApAction(prAdapter, + prBssDesc) == WLAN_IOT_AP_DBDC_1SS) { + DBGLOG(SW4, INFO, "Use 1x1 due to DBDC blacklist\n"); + ucRetValNss = 1; + } else if (prAdapter->rWifiVar.fgSta1NSS) { + DBGLOG(SW4, INFO, "Use 1x1 due to FWK cmd\n"); + ucRetValNss = 1; + } + } +#endif + + if (ucRetValNss > prAdapter->rWifiVar.ucNSS) + ucRetValNss = prAdapter->rWifiVar.ucNSS; + +#if CFG_SISO_SW_DEVELOP + if (ucBssIndex > prAdapter->ucHwBssIdNum) { + DBGLOG(SW4, INFO, "Invalid BssInfo index[%u], skip dump!\n", + ucBssIndex); + return ucRetValNss; + } + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + /* + * depend 2.4G/5G support SISO/MIMO + * retrun accurate value + */ + if (prBssInfo->fgIsGranted) + eBand = prBssInfo->eBandGranted; + else + eBand = prBssInfo->eBand; + + if ((eBand == BAND_2G4) && IS_WIFI_2G4_SISO(prAdapter)) + ucRetValNss = 1; + else if ((eBand == BAND_5G) && IS_WIFI_5G_SISO(prAdapter)) + ucRetValNss = 1; + DBGLOG(INIT, TRACE, "Nss=%d,G=%d,B=%d,Bss=%d\n", + ucRetValNss, prBssInfo->fgIsGranted, eBand, ucBssIndex); +#endif + + return ucRetValNss; +} + +#if CFG_SUPPORT_LOWLATENCY_MODE +/*----------------------------------------------------------------------------*/ +/*! + * \brief This is a private routine, which is used to initialize the variables + * for low latency mode. + * + * \param prAdapter Pointer of Adapter Data Structure + * + * \retval WLAN_STATUS_SUCCESS: Success + * \retval WLAN_STATUS_FAILURE: Failed + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanAdapterStartForLowLatency(IN struct ADAPTER *prAdapter) +{ + uint32_t u4Status = WLAN_STATUS_SUCCESS; + + /* Default disable low latency mode */ + prAdapter->fgEnLowLatencyMode = FALSE; + + /* Default enable scan */ + prAdapter->fgEnCfg80211Scan = TRUE; + + /* Default disable duplicate detect */ + prAdapter->fgEnTxDupDetect = FALSE; + prAdapter->fgTxDupCertificate = FALSE; + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This is a private routine, which is used to initialize the variables + * for low latency mode. + * + * \param prAdapter Pointer of Adapter Data Structure + * + * \retval WLAN_STATUS_SUCCESS: Success + * \retval WLAN_STATUS_FAILURE: Failed + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanProbeSuccessForLowLatency(IN struct ADAPTER *prAdapter) +{ + DBGLOG(INIT, INFO, "LowLatency(ProbeOn)\n"); + + /* Reset certificate flag and query capability from firmware */ + prAdapter->fgTxDupCertificate = FALSE; + wlanSetLowLatencyCommand(prAdapter, + FALSE, + prAdapter->fgEnTxDupDetect, + TRUE); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This is a private routine, which is used to initialize the variables + * for low latency mode. + * + * \param prAdapter Pointer of Adapter Data Structure + * + * \retval WLAN_STATUS_SUCCESS: Success + * \retval WLAN_STATUS_FAILURE: Failed + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanConnectedForLowLatency(IN struct ADAPTER *prAdapter) +{ + uint32_t u4Events; + + /* Query setting from wifi adaptor module */ + u4Events = get_low_latency_mode(); + + /* Set low latency mode */ + DBGLOG(AIS, INFO, "LowLatency(Connected) event:0x%x\n", u4Events); + wlanSetLowLatencyMode(prAdapter, u4Events); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set enable/disable low latency mode to FW + * + * \param[in] prAdapter A pointer to the Adapter structure. + * + * \retval WLAN_STATUS_SUCCESS + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanSetLowLatencyCommand( + IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnLowLatencyMode, + IN u_int8_t fgEnTxDupDetect, + IN u_int8_t fgTxDupCertQuery) +{ + struct CMD_LOW_LATENCY_MODE_HEADER rModeHeader; + + rModeHeader.ucVersion = LOW_LATENCY_MODE_CMD_V2; + rModeHeader.ucType = 0; + rModeHeader.ucMagicCode = LOW_LATENCY_MODE_MAGIC_CODE; + rModeHeader.ucBufferLen = sizeof(struct LOW_LATENCY_MODE_SETTING); + rModeHeader.rSetting.fgEnable = fgEnLowLatencyMode; + rModeHeader.rSetting.fgTxDupDetect = fgEnTxDupDetect; + rModeHeader.rSetting.fgTxDupCertQuery = fgTxDupCertQuery; + + DBGLOG(AIS, INFO, + "Send Dpp Cmd to FW:en=%d, dup_Det=%d, CertQuery=%d\n", + fgEnLowLatencyMode, fgEnTxDupDetect, fgTxDupCertQuery); + + wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_LOW_LATENCY_MODE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + TRUE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct CMD_LOW_LATENCY_MODE_HEADER), + (uint8_t *)&rModeHeader, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + return WLAN_STATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to enable/disable low latency mode + * \param[in] prAdapter A pointer to the Adapter structure. + * \param[in] pvSetBuffer A pointer to the buffer that holds the + * OID-specific data to be set. + * \param[in] u4SetBufferLen The number of bytes the set buffer. + * \param[out] pu4SetInfoLen Points to the number of bytes it read or is + * needed + * \retval WLAN_STATUS_SUCCESS + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanSetLowLatencyMode( + IN struct ADAPTER *prAdapter, + IN uint32_t u4Events) +{ + u_int8_t fgEnMode = FALSE; /* Low Latency Mode */ + u_int8_t fgEnScan = FALSE; /* Scan management */ + u_int8_t fgEnPM = FALSE; /* Power management */ + u_int8_t fgEnTxDupDetect = FALSE; /* Tx Dup Detect */ + uint32_t u4PowerFlag; + struct PARAM_POWER_MODE_ rPowerMode; + struct WIFI_VAR *prWifiVar = NULL; + struct BSS_INFO *prAisBssInfo; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + DEBUGFUNC("wlanSetLowLatencyMode"); + + ASSERT(prAdapter); + + prAisBssInfo = + aisGetAisBssInfo(prAdapter, ucBssIndex); + if (!prAisBssInfo) { + DBGLOG(OID, ERROR, "prAisBssInfo = NULL\n"); + return WLAN_STATUS_FAILURE; + } + + /* Initialize */ + prWifiVar = &prAdapter->rWifiVar; + DBGLOG(OID, INFO, + "LowLatency(gaming/DPP) event - gas:0x%x, net:0x%x, whitelist:0x%x, txdup:0x%x, scan=%u, reorder=%u, power=%u, cmd data=%u\n", + (u4Events & GED_EVENT_GAS), + (u4Events & GED_EVENT_NETWORK), + (u4Events & GED_EVENT_DOPT_WIFI_SCAN), + (u4Events & GED_EVENT_TX_DUP_DETECT), + (uint32_t)prWifiVar->ucLowLatencyModeScan, + (uint32_t)prWifiVar->ucLowLatencyModeReOrder, + (uint32_t)prWifiVar->ucLowLatencyModePower, + (uint32_t)prWifiVar->ucLowLatencyCmdData); + + rPowerMode.ucBssIdx = prAisBssInfo->ucBssIndex; + u4PowerFlag = prAdapter->rWlanInfo.u4PowerSaveFlag[rPowerMode.ucBssIdx]; + + /* Enable/disable low latency mode decision: + * + * Enable if it's GAS and network event + * and the Glue media state is connected. + */ + if ((u4Events & GED_EVENT_GAS) != 0 + && (u4Events & GED_EVENT_NETWORK) != 0 + && MEDIA_STATE_CONNECTED + == kalGetMediaStateIndicated(prAdapter->prGlueInfo, + prAisBssInfo->ucBssIndex)) + fgEnMode = TRUE; /* It will enable low latency mode */ + + /* Enable/disable scan management decision: + * + * Enable if it will enable low latency mode. + * Or, enable if it is a white list event. + */ + if (fgEnMode != TRUE || (u4Events & GED_EVENT_DOPT_WIFI_SCAN) != 0) + fgEnScan = TRUE; /* It will enable scan management */ + + /* Enable/disable power management decision: + */ + if (BIT(PS_CALLER_GPU) & u4PowerFlag) + fgEnPM = TRUE; + else + fgEnPM = FALSE; + + /* Debug log for the actions */ + if (fgEnMode != prAdapter->fgEnLowLatencyMode + || fgEnScan != prAdapter->fgEnCfg80211Scan + || fgEnPM != fgEnMode) { + DBGLOG(OID, INFO, + "LowLatency(gaming/DPP) change (m:%d,s:%d,PM:%d,F:0x%x)\n", + fgEnMode, fgEnScan, fgEnPM, u4PowerFlag); + } + + /* Scan management: + * + * Disable/enable scan + */ + if ((prWifiVar->ucLowLatencyModeScan == FEATURE_ENABLED) && + (fgEnScan != prAdapter->fgEnCfg80211Scan)) + prAdapter->fgEnCfg80211Scan = fgEnScan; + + if ((prWifiVar->ucLowLatencyModeReOrder == FEATURE_ENABLED) && + (fgEnMode != prAdapter->fgEnLowLatencyMode)) { + prAdapter->fgEnLowLatencyMode = fgEnMode; + + /* Queue management: + * + * Change QM RX BA timeout if the gaming mode state changed + */ + if (fgEnMode) { + prAdapter->u4QmRxBaMissTimeout + = QM_RX_BA_ENTRY_MISS_TIMEOUT_MS_SHORT; + } else { + prAdapter->u4QmRxBaMissTimeout + = QM_RX_BA_ENTRY_MISS_TIMEOUT_MS; + } + } + + /* Power management: + * + * Set power saving mode profile to FW + * + * Do if 1. the power saving caller including GPU + * and 2. it will disable low latency mode. + * Or, do if 1. the power saving caller is not including GPU + * and 2. it will enable low latency mode. + */ + if ((prWifiVar->ucLowLatencyModePower == FEATURE_ENABLED) && + (fgEnPM != fgEnMode)) { + if (fgEnMode == TRUE) + rPowerMode.ePowerMode = Param_PowerModeCAM; + else + rPowerMode.ePowerMode = Param_PowerModeFast_PSP; + + nicConfigPowerSaveProfile(prAdapter, rPowerMode.ucBssIdx, + rPowerMode.ePowerMode, FALSE, PS_CALLER_GPU); + + #if CFG_SUPPORT_SMART_GEAR + wlandioSetSGStatus(prAdapter, + fgEnMode, 0x00, 0x00); + DBGLOG(OID, INFO, + "[SG] SmartGear (%d) for gaming mode\n", + fgEnMode); + #endif + + } + + DBGLOG(OID, INFO, + "LowLatency(gaming) fgEnMode=[%d]\n", fgEnMode); + + /* Force RTS to protect game packet */ + wlanSetForceRTS(prAdapter, fgEnMode); + + /* Tx Duplicate Detect management: + * + * Disable/enable tx duplicate detect + */ + if ((u4Events & GED_EVENT_TX_DUP_DETECT) != 0) + fgEnTxDupDetect = TRUE; + + DBGLOG(OID, INFO, + "EnTxDupDetect: Orig:[%d], New:[%d], CmdData:[%d], Cert:[%d]\n", + prAdapter->fgEnTxDupDetect, + fgEnTxDupDetect, + prAdapter->rWifiVar.ucLowLatencyCmdData, + prAdapter->fgTxDupCertificate); + + if (prAdapter->fgEnTxDupDetect != fgEnTxDupDetect) { + + prAdapter->fgEnTxDupDetect = fgEnTxDupDetect; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + if (prAdapter->fgIsSupportCsumOffload) { + if (prAdapter->fgEnTxDupDetect) { + /* Disable csum offload for command data */ + prAdapter->prGlueInfo-> + prDevHandler->features &= + ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); + } else { + /* Enable csum offload for cut-through data */ + prAdapter->prGlueInfo-> + prDevHandler->features |= + (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); + } + } + DBGLOG(OID, INFO, "Checksum offload: [%llu]\n", + prAdapter->prGlueInfo->prDevHandler->features); +#endif + /* Send command to firmware */ + wlanSetLowLatencyCommand(prAdapter, + prAdapter->fgEnLowLatencyMode, + prAdapter->fgEnTxDupDetect, + FALSE); + } + + return WLAN_STATUS_SUCCESS; +} + +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + +#if CFG_SUPPORT_EASY_DEBUG + +void wlanCfgFwSetParam(uint8_t *fwBuffer, char *cmdStr, char *value, int num, + int type) +{ + struct CMD_FORMAT_V1 *cmd = (struct CMD_FORMAT_V1 *)fwBuffer + num; + + kalMemSet(cmd, 0, sizeof(struct CMD_FORMAT_V1)); + cmd->itemType = type; + + cmd->itemStringLength = strlen(cmdStr); + if (cmd->itemStringLength > MAX_CMD_NAME_MAX_LENGTH) + cmd->itemStringLength = MAX_CMD_NAME_MAX_LENGTH; + + /* here will not ensure the end will be '\0' */ + kalMemCopy(cmd->itemString, cmdStr, cmd->itemStringLength); + + cmd->itemValueLength = strlen(value); + if (cmd->itemValueLength > MAX_CMD_VALUE_MAX_LENGTH) + cmd->itemValueLength = MAX_CMD_VALUE_MAX_LENGTH; + + /* here will not ensure the end will be '\0' */ + kalMemCopy(cmd->itemValue, value, cmd->itemValueLength); +} + +uint32_t wlanCfgSetGetFw(IN struct ADAPTER *prAdapter, const char *fwBuffer, + int cmdNum, enum CMD_TYPE cmdType) +{ + struct CMD_HEADER *pcmdV1Header = NULL; + + pcmdV1Header = (struct CMD_HEADER *) + kalMemAlloc(sizeof(struct CMD_HEADER), VIR_MEM_TYPE); + + if (pcmdV1Header == NULL) + return WLAN_STATUS_FAILURE; + + kalMemSet(pcmdV1Header->buffer, 0, MAX_CMD_BUFFER_LENGTH); + pcmdV1Header->cmdType = cmdType; + pcmdV1Header->cmdVersion = CMD_VER_1_EXT; + pcmdV1Header->itemNum = cmdNum; + pcmdV1Header->cmdBufferLen = cmdNum * sizeof(struct CMD_FORMAT_V1); + kalMemCopy(pcmdV1Header->buffer, fwBuffer, pcmdV1Header->cmdBufferLen); + + wlanSendSetQueryCmd(prAdapter, CMD_ID_GET_SET_CUSTOMER_CFG, + TRUE, FALSE, FALSE, + NULL, NULL, + sizeof(struct CMD_HEADER), + (uint8_t *) pcmdV1Header, + NULL, 0); + kalMemFree(pcmdV1Header, VIR_MEM_TYPE, sizeof(struct CMD_HEADER)); + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanFwCfgParse(IN struct ADAPTER *prAdapter, uint8_t *pucConfigBuf) +{ + /* here return a list should be better */ + char *saveptr1, *saveptr2; + char *cfgItems = pucConfigBuf; + uint8_t cmdNum = 0; + + uint8_t *cmdBuffer = kalMemAlloc(MAX_CMD_BUFFER_LENGTH, VIR_MEM_TYPE); + + if (cmdBuffer == 0) { + DBGLOG(INIT, INFO, "omega, cmd buffer return fail!"); + return WLAN_STATUS_FAILURE; + } + kalMemSet(cmdBuffer, 0, MAX_CMD_BUFFER_LENGTH); + + while (1) { + char *keyStr = NULL; + char *valueStr = NULL; + char *cfgEntry = kalStrtokR(cfgItems, "\n\r", &saveptr1); + + if (!cfgEntry) { + if (cmdNum) + wlanCfgSetGetFw(prAdapter, cmdBuffer, cmdNum, + CMD_TYPE_SET); + + if (cmdBuffer) + kalMemFree(cmdBuffer, VIR_MEM_TYPE, + MAX_CMD_BUFFER_LENGTH); + + return WLAN_STATUS_SUCCESS; + } + cfgItems = NULL; + + keyStr = kalStrtokR(cfgEntry, " \t", &saveptr2); + valueStr = kalStrtokR(NULL, "\0", &saveptr2); + + /* maybe a blank line, but with some tab or whitespace */ + if (!keyStr) + continue; + + /* here take '#' at the beginning of line as comment */ + if (keyStr[0] == '#') + continue; + + /* remove the \t " " at the beginning of the valueStr */ + while (valueStr && (*valueStr == '\t' || *valueStr == ' ')) + valueStr++; + + if (keyStr && valueStr) { + wlanCfgFwSetParam(cmdBuffer, keyStr, valueStr, cmdNum, + 1); + cmdNum++; + if (cmdNum == MAX_CMD_ITEM_MAX) { + wlanCfgSetGetFw(prAdapter, cmdBuffer, + MAX_CMD_ITEM_MAX, CMD_TYPE_SET); + kalMemSet(cmdBuffer, 0, MAX_CMD_BUFFER_LENGTH); + cmdNum = 0; + } + } else { + /* here will not to try send the cmd has been parsed, + * but not sent yet + */ + if (cmdBuffer) + kalMemFree(cmdBuffer, VIR_MEM_TYPE, + MAX_CMD_BUFFER_LENGTH); + return WLAN_STATUS_FAILURE; + } + } +} +#endif /* CFG_SUPPORT_EASY_DEBUG */ + +int32_t wlanGetFileContent(struct ADAPTER *prAdapter, + const uint8_t *pcFileName, uint8_t *pucBuf, + uint32_t u4MaxFileLen, uint32_t *pu4ReadFileLen, u_int8_t bReqFw) +{ + if (bReqFw) + return kalRequestFirmware(pcFileName, pucBuf, + u4MaxFileLen, pu4ReadFileLen, + prAdapter->prGlueInfo->prDev); + + return kalReadToFile(pcFileName, pucBuf, + u4MaxFileLen, pu4ReadFileLen); +} + +void wlanReleasePendingCmdById(struct ADAPTER *prAdapter, uint8_t ucCid) +{ + struct QUE *prCmdQue; + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue = &rTempCmdQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + DBGLOG(OID, INFO, "Remove pending Cmd: CID %d\n", ucCid); + + /* 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, struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + if (prCmdInfo->ucCID != ucCid) { + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + continue; + } + + if (prCmdInfo->pfCmdTimeoutHandler) { + prCmdInfo->pfCmdTimeoutHandler(prAdapter, prCmdInfo); + } else if (prCmdInfo->fgIsOid) { + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, 0, + WLAN_STATUS_FAILURE); + } + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); +} + +/* Translate Decimals string to Hex +** The result will be put in a 2bytes variable. +** Integer part will occupy the left most 3 bits, and decimal part is in the +** left 13 bits +** Integer part can be parsed by kstrtou16, decimal part should be translated by +** mutiplying +** 16 and then pick integer part. +** For example +*/ +uint32_t wlanDecimalStr2Hexadecimals(uint8_t *pucDecimalStr, uint16_t *pu2Out) +{ + uint8_t aucDecimalStr[32] = {0}; + uint8_t *pucDecimalPart = NULL; + uint8_t *tmp = NULL; + uint32_t u4Result = 0; + uint32_t u4Ret = 0; + uint32_t u4Degree = 0; + uint32_t u4Remain = 0; + uint8_t ucAccuracy = 4; /* Hex decimals accuarcy is 4 bytes */ + uint32_t u4Base = 1; + + if (!pu2Out || !pucDecimalStr) + return 1; + + while (*pucDecimalStr == '0') + pucDecimalStr++; + kalStrnCpy(aucDecimalStr, pucDecimalStr, sizeof(aucDecimalStr) - 1); + aucDecimalStr[31] = 0; + pucDecimalPart = strchr(aucDecimalStr, '.'); + if (!pucDecimalPart) { + DBGLOG(INIT, INFO, "No decimal part, ori str %s\n", + pucDecimalStr); + goto integer_part; + } + *pucDecimalPart++ = 0; + /* get decimal degree */ + tmp = pucDecimalPart + strlen(pucDecimalPart); + do { + if (tmp == pucDecimalPart) { + DBGLOG(INIT, INFO, + "Decimal part are all 0, ori str %s\n", + pucDecimalStr); + goto integer_part; + } + tmp--; + } while (*tmp == '0'); + + *(++tmp) = 0; + u4Degree = (uint32_t)(tmp - pucDecimalPart); + /* if decimal part is not 0, translate it to hexadecimal decimals */ + /* Power(10, degree) */ + for (; u4Remain < u4Degree; u4Remain++) + u4Base *= 10; + + while (*pucDecimalPart == '0') + pucDecimalPart++; + + u4Ret = kalkStrtou32(pucDecimalPart, 0, &u4Remain); + if (u4Ret) { + DBGLOG(INIT, ERROR, "Parse decimal str %s error, degree %u\n", + pucDecimalPart, u4Degree); + return u4Ret; + } + + do { + u4Remain *= 16; + u4Result |= (u4Remain / u4Base) << ((ucAccuracy-1) * 4); + u4Remain %= u4Base; + ucAccuracy--; + } while (u4Remain && ucAccuracy > 0); + /* Each Hex Decimal byte was left shift more than 3 bits, so need + ** right shift 3 bits at last + ** For example, mmmnnnnnnnnnnnnn. + ** mmm is integer part, n represents decimals part. + ** the left most 4 n are shift 9 bits. But in for loop, we shift 12 bits + **/ + u4Result >>= 3; + u4Remain = 0; + +integer_part: + u4Ret = kalkStrtou32(aucDecimalStr, 0, &u4Remain); + u4Result |= u4Remain << 13; + + if (u4Ret) + DBGLOG(INIT, ERROR, "Parse integer str %s error\n", + aucDecimalStr); + else { + *pu2Out = u4Result & 0xffff; + DBGLOG(INIT, TRACE, "Result 0x%04x\n", *pu2Out); + } + return u4Ret; +} + +uint64_t wlanGetSupportedFeatureSet(IN struct GLUE_INFO *prGlueInfo) +{ + uint64_t u8FeatureSet = WIFI_HAL_FEATURE_SET; + struct REG_INFO *prRegInfo; + + prRegInfo = &(prGlueInfo->rRegInfo); + if ((prRegInfo != NULL) && (prRegInfo->ucSupport5GBand)) + u8FeatureSet |= WIFI_FEATURE_INFRA_5G; + + return u8FeatureSet; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is a wrapper to send power-saving mode command +* when AIS enter wow, and send WOW command +* Also let GC/GO/AP enter deactivate state to enter TOP sleep +* +* @param prGlueInfo Pointer of prGlueInfo Data Structure +* +* @return VOID +*/ +/*----------------------------------------------------------------------------*/ +void wlanSuspendPmHandle(struct GLUE_INFO *prGlueInfo) +{ +#if CFG_WOW_SUPPORT + /* 1) wifi cfg "Wow" is true */ + /* 2) wow is enable */ + /* 3) WIfI connected => execute WOW flow */ + if (prGlueInfo->prAdapter->rWifiVar.ucWow && + prGlueInfo->prAdapter->rWowCtrl.fgWowEnable) { + if (kalGetMediaStateIndicated(prGlueInfo, + AIS_DEFAULT_INDEX) == + MEDIA_STATE_CONNECTED) { + DBGLOG(HAL, EVENT, "enter WOW flow\n"); + kalWowProcess(prGlueInfo, TRUE); + } + + /* else: do nothing, and FW enter LMAC sleep */ + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to restore power-saving mode command when leave wow +* But ignore GC/GO/AP role +* +* @param prGlueInfo Pointer of prGlueInfo Data Structure +* +* @return VOID +*/ +/*----------------------------------------------------------------------------*/ +void wlanResumePmHandle(struct GLUE_INFO *prGlueInfo) +{ +#if CFG_WOW_SUPPORT + if (prGlueInfo->prAdapter->rWifiVar.ucWow) { + DBGLOG(HAL, EVENT, "leave WOW flow\n"); + kalWowProcess(prGlueInfo, FALSE); + } +#endif +} + +static uint32_t wlanHwRateOfdmNum(uint16_t ofdm_idx) +{ + switch (ofdm_idx) { + case 11: /* 6M */ + return g_rOfdmDataRateMappingTable.rate[0]; + case 15: /* 9M */ + return g_rOfdmDataRateMappingTable.rate[1]; + case 10: /* 12M */ + return g_rOfdmDataRateMappingTable.rate[2]; + case 14: /* 18M */ + return g_rOfdmDataRateMappingTable.rate[3]; + case 9: /* 24M */ + return g_rOfdmDataRateMappingTable.rate[4]; + case 13: /* 36M */ + return g_rOfdmDataRateMappingTable.rate[5]; + case 8: /* 48M */ + return g_rOfdmDataRateMappingTable.rate[6]; + case 12: /* 54M */ + return g_rOfdmDataRateMappingTable.rate[7]; + default: + return 0; + } +} + +int wlanQueryRateByTable(uint32_t txmode, uint32_t rate, + uint32_t frmode, uint32_t sgi, uint32_t nsts, + uint32_t *pu4CurRate, uint32_t *pu4MaxRate) +{ + uint32_t u4CurRate, u4MaxRate; + uint8_t ucMaxSize; + + if (txmode == TX_RATE_MODE_CCK) { /* 11B */ + ucMaxSize = ARRAY_SIZE(g_rCckDataRateMappingTable.rate); + if (rate >= ucMaxSize) { + DBGLOG(SW4, ERROR, "rate error for CCK: %u\n", rate); + return -1; + } + u4CurRate = g_rCckDataRateMappingTable.rate[rate]; + u4MaxRate = g_rCckDataRateMappingTable.rate[ucMaxSize - 1]; + } else if (txmode == TX_RATE_MODE_OFDM) { /* 11G */ + u4CurRate = wlanHwRateOfdmNum(rate); + if (u4CurRate == 0) { + DBGLOG(SW4, ERROR, "rate error for OFDM\n"); + return -1; + } + ucMaxSize = ARRAY_SIZE(g_rOfdmDataRateMappingTable.rate); + u4MaxRate = g_rOfdmDataRateMappingTable.rate[ucMaxSize - 1]; + } else if ((txmode == TX_RATE_MODE_HTMIX) || + (txmode == TX_RATE_MODE_HTGF)) { /* 11N */ + if (rate >= 8 && rate <= 15) { + rate -= 8; + } else if (rate >= 16 && rate <= 23) { + rate -= 16; + } else if (rate < 0 || rate > 23) { + DBGLOG(SW4, ERROR, "rate error for 11N: %u\n", + rate); + return -1; + } + if (frmode > 1) { + DBGLOG(SW4, ERROR, + "frmode error for 11N: %u\n", + frmode); + return -1; + } + u4CurRate = g_rDataRateMappingTable.nsts[nsts - 1].bw[frmode] + .sgi[sgi].rate[rate]; + ucMaxSize = 8; + u4MaxRate = g_rDataRateMappingTable.nsts[nsts - 1].bw[frmode] + .sgi[sgi].rate[ucMaxSize - 1]; + } else if (txmode == TX_RATE_MODE_HE_SU) { /* AX */ + if ((nsts == 0) || (nsts >= 5)) { + DBGLOG(SW4, ERROR, "nsts error: %u\n", nsts); + return -1; + } + if (frmode > 3) { + DBGLOG(SW4, ERROR, + "frmode error for 11AX: %u\n", + frmode); + return -1; + } + u4CurRate = g_rAxDataRateMappingTable.nsts[nsts - 1] + .bw[frmode].gi[sgi].rate[rate]; + ucMaxSize = ARRAY_SIZE(g_rAxDataRateMappingTable.nsts[nsts - 1] + .bw[frmode].gi[sgi].rate); + u4MaxRate = g_rAxDataRateMappingTable.nsts[nsts - 1] + .bw[frmode].gi[sgi].rate[ucMaxSize - 1]; + } else { /* 11AC */ + if ((nsts == 0) || (nsts >= 4)) { + DBGLOG(SW4, ERROR, "nsts error: %u\n", nsts); + return -1; + } + if (frmode > 3) { + DBGLOG(SW4, ERROR, + "frmode error for 11AC: %u\n", + frmode); + return -1; + } + u4CurRate = g_rDataRateMappingTable.nsts[nsts - 1] + .bw[frmode].sgi[sgi].rate[rate]; + ucMaxSize = ARRAY_SIZE(g_rDataRateMappingTable.nsts[nsts - 1] + .bw[frmode].sgi[sgi].rate); + u4MaxRate = g_rDataRateMappingTable.nsts[nsts - 1] + .bw[frmode].sgi[sgi].rate[ucMaxSize - 1]; + } + *pu4CurRate = u4CurRate; + *pu4MaxRate = u4MaxRate; + return 0; +} + +#if defined(CFG_REPORT_MAX_TX_RATE) && (CFG_REPORT_MAX_TX_RATE == 1) +int wlanGetMaxTxRate(IN struct ADAPTER *prAdapter, + IN void *prBssPtr, IN struct STA_RECORD *prStaRec, + OUT uint32_t *pu4CurRate, OUT uint32_t *pu4MaxRate) +{ + struct BSS_INFO *prBssInfo; + uint8_t ucPhyType, ucTxMode = 0, ucMcsIdx = 0, ucSgi = 0; + uint8_t ucBw = 0, ucAPBwPermitted = 0, ucNss = 0, ucApNss = 0; + uint8_t ucOffset = (MAX_BW_80MHZ - CW_80MHZ); + struct BSS_DESC *prBssDesc = NULL; + + *pu4CurRate = 0; + *pu4MaxRate = 0; + prBssInfo = (struct BSS_INFO *) prBssPtr; + + /* get tx mode and MCS index */ + ucPhyType = prBssInfo->ucPhyTypeSet; + + DBGLOG(SW4, TRACE, + "ucPhyType: 0x%x\n", + ucPhyType); + +#if (CFG_SUPPORT_802_11AX == 1) + if (ucPhyType & PHY_TYPE_SET_802_11AX) + ucTxMode = TX_RATE_MODE_HE_SU; + else +#endif + if (ucPhyType & PHY_TYPE_SET_802_11AC) + ucTxMode = TX_RATE_MODE_VHT; + else if (ucPhyType & PHY_TYPE_SET_802_11N) + ucTxMode = TX_RATE_MODE_HTMIX; + else if (ucPhyType & PHY_TYPE_SET_802_11G) { + ucTxMode = TX_RATE_MODE_OFDM; + ucMcsIdx = 12; + } else if (ucPhyType & PHY_TYPE_SET_802_11A) { + ucTxMode = TX_RATE_MODE_OFDM; + ucMcsIdx = 12; + } else if (ucPhyType & PHY_TYPE_SET_802_11B) + ucTxMode = TX_RATE_MODE_CCK; + else { + DBGLOG(SW4, ERROR, + "unknown wifi type, prBssInfo->ucPhyTypeSet: %u\n", + ucPhyType); + goto errhandle; + } + + /* get bandwidth */ + ucBw = cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex); + prBssDesc = aisGetTargetBssDesc(prAdapter, prBssInfo->ucBssIndex); + if (prBssDesc) { + ucAPBwPermitted = MAX_BW_160MHZ; + if (prBssDesc->eChannelWidth == CW_20_40MHZ) { + if ((prBssDesc->eSco == CHNL_EXT_SCA) + || (prBssDesc->eSco == CHNL_EXT_SCB)) + ucAPBwPermitted = MAX_BW_40MHZ; + else + ucAPBwPermitted = MAX_BW_20MHZ; + } else { + ucAPBwPermitted = prBssDesc->eChannelWidth + ucOffset; + } + if ((ucAPBwPermitted < MAX_BW_20MHZ) || + (ucAPBwPermitted > MAX_BW_80_80_MHZ)) { + DBGLOG(SW4, ERROR, + "unknown band width: %u\n", ucAPBwPermitted); + goto errhandle; + } else if (ucAPBwPermitted == MAX_BW_80_80_MHZ) + ucAPBwPermitted = MAX_BW_160MHZ; + } else { + DBGLOG(SW4, ERROR, "prBssDesc is null\n"); + goto errhandle; + } + if (ucAPBwPermitted < ucBw) + ucBw = ucAPBwPermitted; + + /* get Short GI Tx capability */ + if ((prStaRec->u2HtCapInfo & HT_CAP_INFO_SHORT_GI_20M) == + HT_CAP_INFO_SHORT_GI_20M) { + DBGLOG(RLM, TRACE, "HT_CAP_INFO_SHORT_GI_20M\n"); + ucSgi = 1; + } + if ((prStaRec->u2HtCapInfo & HT_CAP_INFO_SHORT_GI_40M) == + HT_CAP_INFO_SHORT_GI_40M) { + DBGLOG(RLM, TRACE, "HT_CAP_INFO_SHORT_GI_40M\n"); + ucSgi = 1; + } +#if CFG_SUPPORT_802_11AC + if ((prStaRec->u4VhtCapInfo & VHT_CAP_INFO_SHORT_GI_80) == + VHT_CAP_INFO_SHORT_GI_80) { + DBGLOG(RLM, TRACE, "VHT_CAP_INFO_SHORT_GI_80\n"); + ucSgi = 1; + } + if ((prStaRec->u4VhtCapInfo & VHT_CAP_INFO_SHORT_GI_160_80P80) == + VHT_CAP_INFO_SHORT_GI_160_80P80) { + DBGLOG(RLM, TRACE, "VHT_CAP_INFO_SHORT_GI_160_80P80\n"); + ucSgi = 1; + } +#endif + + if (ucTxMode == TX_RATE_MODE_HE_SU) { + DBGLOG(SW4, TRACE, "TX_RATE_MODE_HE_SU\n"); + ucSgi = 0; + } + + /* get antenna number */ + ucNss = wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex); + if (prBssDesc) { + ucApNss = bssGetRxNss(prAdapter, prBssDesc); + if (ucApNss > 0 && ucApNss < ucNss) + ucNss = ucApNss; + } + if ((ucNss < 1) && (ucNss > 3)) { + DBGLOG(RLM, ERROR, "error ucNss: %u\n", ucNss); + goto errhandle; + } + + DBGLOG(SW4, TRACE, + "txmode=[%u], mcs idx=[%u], bandwidth=[%u], sgi=[%u], nsts=[%u]\n", + ucTxMode, ucMcsIdx, ucBw, ucSgi, ucNss + ); + + if (wlanQueryRateByTable(ucTxMode, ucMcsIdx, ucBw, ucSgi, + ucNss, pu4CurRate, pu4MaxRate) < 0) + goto errhandle; + + DBGLOG(SW4, TRACE, + "*pu4CurRate=[%u], *pu4MaxRate=[%u]\n", + *pu4CurRate, *pu4MaxRate); + + return 0; + +errhandle: + DBGLOG(SW4, ERROR, + "txmode=[%u], mcs idx=[%u], bandwidth=[%u], sgi=[%u], nsts=[%u]\n", + ucTxMode, ucMcsIdx, ucBw, ucSgi, ucNss); + return -1; +} +#endif /* CFG_REPORT_MAX_TX_RATE */ + +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR +int wlanGetRxRate(IN struct GLUE_INFO *prGlueInfo, + OUT uint32_t *pu4CurRate, OUT uint32_t *pu4MaxRate) +{ + struct ADAPTER *prAdapter; + uint32_t rxmode = 0, rate = 0, frmode = 0, sgi = 0, nss = 0; + uint32_t u4RxVector0 = 0, u4RxVector1 = 0; + uint8_t ucWlanIdx, ucStaIdx; + int rv; + struct STA_RECORD *prStaRec; + + *pu4CurRate = 0; + *pu4MaxRate = 0; + prAdapter = prGlueInfo->prAdapter; + + prStaRec = aisGetStaRecOfAP(prAdapter, AIS_DEFAULT_INDEX); + if (prStaRec) { + ucWlanIdx = prStaRec->ucWlanIndex; + } else { + DBGLOG(SW4, ERROR, "prStaRecOfAP is null\n"); + goto errhandle; + } + + if (wlanGetStaIdxByWlanIdx(prAdapter, ucWlanIdx, &ucStaIdx) == + WLAN_STATUS_SUCCESS) { + u4RxVector0 = prAdapter->arStaRec[ucStaIdx].u4RxVector0; + u4RxVector1 = prAdapter->arStaRec[ucStaIdx].u4RxVector1; + if ((u4RxVector0 == 0) && (u4RxVector1 == 0)) { + /* soc3_0 known issue */ + DBGLOG(SW4, TRACE, "u4RxVector0 or u4RxVector1 is 0\n"); + goto errhandle; + } + } else { + DBGLOG(SW4, ERROR, "wlanGetStaIdxByWlanIdx fail\n"); + goto errhandle; + } + + rxmode = (u4RxVector0 & RX_VT_RX_MODE_MASK) >> RX_VT_RX_MODE_OFFSET; + rate = (u4RxVector0 & RX_VT_RX_RATE_MASK) >> RX_VT_RX_RATE_OFFSET; + frmode = (u4RxVector0 & RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET; + nss = ((u4RxVector0 & RX_VT_NUM_RX_MASK) >> RX_VT_NUM_RX_OFFSET); + sgi = u4RxVector0 & RX_VT_SHORT_GI; + + /*0 means 1R, 1 means 2R ...*/ + nss += 1; + sgi = (sgi == 0) ? 0 : 1; + if (frmode >= 4) { + DBGLOG(SW4, ERROR, "frmode error: %u\n", frmode); + goto errhandle; + } + + DBGLOG(SW4, TRACE, + "rxmode=%u rate=%u bandwidth=%u sgi=%u nss=%u\n", + rxmode, rate, frmode, sgi, nss); + + rv = wlanQueryRateByTable(rxmode, rate, frmode, sgi, nss, + pu4CurRate, pu4MaxRate); + if (rv < 0) + goto errhandle; + + return 0; + +errhandle: + /* soc3_0 known issue */ + DBGLOG(SW4, TRACE, + "u4RxVector0=[%x], u4RxVector1=[%x], rxmode=[%u], rate=[%u], frmode=[%u], sgi=[%u], nss=[%u]\n", + u4RxVector0, u4RxVector1, rxmode, rate, frmode, sgi, nss + ); + return -1; +} + +uint32_t wlanLinkQualityMonitor(struct GLUE_INFO *prGlueInfo, bool bFgIsOid) +{ + struct ADAPTER *prAdapter; + struct WIFI_LINK_QUALITY_INFO *prLinkQualityInfo = NULL; + struct PARAM_GET_STA_STATISTICS *prQueryStaStatistics; + struct PARAM_802_11_STATISTICS_STRUCT *prStat; + uint32_t u4BufLen = 0; + uint8_t arBssid[PARAM_MAC_ADDR_LEN]; + uint32_t u4Status = WLAN_STATUS_FAILURE; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + if (kalGetMediaStateIndicated(prGlueInfo, + ucBssIndex) != + MEDIA_STATE_CONNECTED) { + /* not connected */ + DBGLOG(SW4, ERROR, "not yet connected\n"); + return u4Status; + } + + prAdapter = prGlueInfo->prAdapter; + if (prAdapter == NULL) { + DBGLOG(SW4, ERROR, "prAdapter is null\n"); + return u4Status; + } + + /* Completely record the Link quality and store the current time */ + prAdapter->u4LastLinkQuality = kalGetTimeTick(); + DBGLOG(NIC, TRACE, "LastLinkQuality:%u\n", + prAdapter->u4LastLinkQuality); + + kalMemZero(arBssid, MAC_ADDR_LEN); + SET_IOCTL_BSSIDX(prGlueInfo->prAdapter, ucBssIndex); + wlanQueryInformation(prAdapter, wlanoidQueryBssid, + &arBssid[0], sizeof(arBssid), &u4BufLen); + + /* send cmd to firmware */ + prQueryStaStatistics = &(prAdapter->rQueryStaStatistics); + prStat = &(prAdapter->rStat); + kalMemZero(prQueryStaStatistics, + sizeof(struct PARAM_GET_STA_STATISTICS)); + kalMemZero(prStat, sizeof(struct PARAM_802_11_STATISTICS_STRUCT)); + COPY_MAC_ADDR(prQueryStaStatistics->aucMacAddr, arBssid); + prQueryStaStatistics->ucReadClear = TRUE; + u4Status = wlanQueryStaStatistics(prAdapter, + prQueryStaStatistics, + sizeof(struct PARAM_GET_STA_STATISTICS), + &(prAdapter->u4BufLen), + FALSE); + u4Status = wlanQueryStatistics(prAdapter, + prStat, + sizeof(struct PARAM_802_11_STATISTICS_STRUCT), + &(prAdapter->u4BufLen), + FALSE); + + if (bFgIsOid == FALSE) + u4Status = WLAN_STATUS_SUCCESS; + + if ((bFgIsOid == TRUE) || (prAdapter->u4LastLinkQuality <= 0)) + return u4Status; + + prLinkQualityInfo = &(prAdapter->rLinkQualityInfo); + +#if CFG_SUPPORT_DATA_STALL + wlanCustomMonitorFunction(prAdapter, prLinkQualityInfo, ucBssIndex); +#endif + + DBGLOG(SW4, INFO, + "Link Quality: Tx(rate:%u, total:%lu, retry:%lu, fail:%lu, RTS fail:%lu, ACK fail:%lu), Rx(rate:%u, total:%lu, dup:%u, error:%lu), PER(%u), Congestion(idle slot:%lu, diff:%lu, AwakeDur:%u)\n", + prLinkQualityInfo->u4CurTxRate, /* current tx link speed */ + prLinkQualityInfo->u8TxTotalCount, /* tx total packages */ + prLinkQualityInfo->u8TxRetryCount, /* tx retry count */ + prLinkQualityInfo->u8TxFailCount, /* tx fail count */ + prLinkQualityInfo->u8TxRtsFailCount, /* tx RTS fail count */ + prLinkQualityInfo->u8TxAckFailCount, /* tx ACK fail count */ + prLinkQualityInfo->u4CurRxRate, /* current rx link speed */ + prLinkQualityInfo->u8RxTotalCount, /* rx total packages */ + prLinkQualityInfo->u4RxDupCount, /* rx duplicate package count */ + prLinkQualityInfo->u8RxErrCount, /* rx fcs fail count */ + prLinkQualityInfo->u4CurTxPer, /* current Tx PER */ + /* congestion stats */ + prLinkQualityInfo->u8IdleSlotCount, /* idle slot */ + prLinkQualityInfo->u8DiffIdleSlotCount, /* idle slot diff */ + prLinkQualityInfo->u4HwMacAwakeDuration + ); + + return u4Status; +} + +void wlanFinishCollectingLinkQuality(struct GLUE_INFO *prGlueInfo) +{ + struct ADAPTER *prAdapter; + struct WIFI_LINK_QUALITY_INFO *prLinkQualityInfo = NULL; + uint32_t u4CurRxRate, u4MaxRxRate; + uint64_t u8TxFailCntDif, u8TxTotalCntDif; + + prAdapter = prGlueInfo->prAdapter; + if (prAdapter == NULL) { + DBGLOG(SW4, ERROR, "prAdapter is null\n"); + return; + } + + /* prepare to set/get statistics from BSSInfo's rLinkQualityInfo */ + prLinkQualityInfo = &(prAdapter->rLinkQualityInfo); + + /* Calculate current tx PER */ + u8TxTotalCntDif = (prLinkQualityInfo->u8TxTotalCount > + prLinkQualityInfo->u8LastTxTotalCount) ? + (prLinkQualityInfo->u8TxTotalCount - + prLinkQualityInfo->u8LastTxTotalCount) : 0; + u8TxFailCntDif = (prLinkQualityInfo->u8TxFailCount > + prLinkQualityInfo->u8LastTxFailCount) ? + (prLinkQualityInfo->u8TxFailCount - + prLinkQualityInfo->u8LastTxFailCount) : 0; + if (u8TxTotalCntDif >= u8TxFailCntDif) + prLinkQualityInfo->u4CurTxPer = (u8TxTotalCntDif == 0) ? 0 : + ((uint32_t)(u8TxFailCntDif * 100) / + (uint32_t)u8TxTotalCntDif); + else + prLinkQualityInfo->u4CurTxPer = 0; + + /* Calculate idle slot diff */ + if (prLinkQualityInfo->u8IdleSlotCount < + prLinkQualityInfo->u8LastIdleSlotCount) { + prLinkQualityInfo->u8DiffIdleSlotCount = 0; + DBGLOG(NIC, WARN, "idle slot is error\n"); + } else + prLinkQualityInfo->u8DiffIdleSlotCount = + prLinkQualityInfo->u8IdleSlotCount - + prLinkQualityInfo->u8LastIdleSlotCount; + + /* get current rx rate */ + if (wlanGetRxRate(prGlueInfo, &u4CurRxRate, &u4MaxRxRate) < 0) + prLinkQualityInfo->u4CurRxRate = 0; + else + prLinkQualityInfo->u4CurRxRate = u4CurRxRate; + + prLinkQualityInfo->u8LastTxTotalCount = + prLinkQualityInfo->u8TxTotalCount; + prLinkQualityInfo->u8LastTxFailCount = + prLinkQualityInfo->u8TxFailCount; + prLinkQualityInfo->u8LastIdleSlotCount = + prLinkQualityInfo->u8IdleSlotCount; +} +#endif /* CFG_SUPPORT_LINK_QUALITY_MONITOR */ + +#if CFG_SUPPORT_DATA_STALL +void wlanCustomMonitorFunction(struct ADAPTER *prAdapter, + struct WIFI_LINK_QUALITY_INFO *prLinkQualityInfo, uint8_t ucBssIdx) +{ + uint64_t u8TxTotalCntDif; + + u8TxTotalCntDif = (prLinkQualityInfo->u8TxTotalCount > + prLinkQualityInfo->u8LastTxTotalCount) ? + (prLinkQualityInfo->u8TxTotalCount - + prLinkQualityInfo->u8LastTxTotalCount) : 0; + + /* Add custom monitor here */ + if (u8TxTotalCntDif >= prAdapter->rWifiVar.u4TrafficThreshold) { + if (prLinkQualityInfo->u4CurTxRate < + prAdapter->rWifiVar.u4TxLowRateThreshole) + KAL_REPORT_ERROR_EVENT(prAdapter, + EVENT_TX_LOW_RATE, + (uint16_t)sizeof(uint32_t), + ucBssIdx, + FALSE); + else if (prLinkQualityInfo->u4CurRxRate < + prAdapter->rWifiVar.u4RxLowRateThreshole) + KAL_REPORT_ERROR_EVENT(prAdapter, + EVENT_RX_LOW_RATE, + (uint16_t)sizeof(uint32_t), + ucBssIdx, + FALSE); + else if (prLinkQualityInfo->u4CurTxPer > + prAdapter->rWifiVar.u4PerHighThreshole) + KAL_REPORT_ERROR_EVENT(prAdapter, + EVENT_PER_HIGH, + (uint16_t)sizeof(uint32_t), + ucBssIdx, + FALSE); + } +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set enable/disable force RTS mode to FW + * + * \param[in] prAdapter A pointer to the Adapter structure. + * + * \retval WLAN_STATUS_SUCCESS + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanSetForceRTS( + IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnForceRTS) +{ + struct CMD_SET_FORCE_RTS rForceRts; + + rForceRts.ucForceRtsEn = fgEnForceRTS; + rForceRts.ucRtsPktNum = 0; + DBGLOG(REQ, INFO, "fgEnForceRTS = %d\n", + fgEnForceRTS); + wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_FORCE_RTS, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct CMD_SET_FORCE_RTS), + (uint8_t *)&rForceRts, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + return WLAN_STATUS_SUCCESS; +} + +void +wlanLoadDefaultCustomerSetting(IN struct ADAPTER * + prAdapter) +{ + + uint8_t ucItemNum, i; + + /* default setting*/ + ucItemNum = (sizeof(g_rDefaulteSetting) / sizeof( + struct PARAM_CUSTOM_KEY_CFG_STRUCT)); + + DBGLOG(INIT, STATE, "Default firmware setting %d item\n", + ucItemNum); + + + for (i = 0; i < ucItemNum; i++) { + wlanCfgSet(prAdapter, + g_rDefaulteSetting[i].aucKey, + g_rDefaulteSetting[i].aucValue, + g_rDefaulteSetting[i].u4Flag); + DBGLOG(INIT, TRACE, "%s with %s\n", + g_rDefaulteSetting[i].aucKey, + g_rDefaulteSetting[i].aucValue); + } + + +#if 1 + /*If need to re-parsing , included wlanInitFeatureOption*/ + wlanInitFeatureOption(prAdapter); +#endif +} +/*wlan on*/ +void +wlanResoreEmCfgSetting(IN struct ADAPTER * + prAdapter) +{ + uint32_t i; + + for (i = 0; i < WLAN_CFG_ENTRY_NUM_MAX; i++) { + + if (g_rEmCfgBk[i].aucKey[0] == '\0') + continue; + + wlanCfgSet(prAdapter, g_rEmCfgBk[i].aucKey, + g_rEmCfgBk[i].aucValue, WLAN_CFG_EM); + + DBGLOG(INIT, STATE, + "cfg restore:(%s,%s) op:%d\n", + g_rEmCfgBk[i].aucKey, + g_rEmCfgBk[i].aucValue, + g_rEmCfgBk[i].u4Flag); + + } + +} + +/*wlan off*/ +void +wlanBackupEmCfgSetting(IN struct ADAPTER * + prAdapter) +{ + uint32_t i; + struct WLAN_CFG_ENTRY *prWlanCfgEntry = NULL; + + kalMemZero(&g_rEmCfgBk, sizeof(g_rEmCfgBk)); + + for (i = 0; i < WLAN_CFG_ENTRY_NUM_MAX; i++) { + prWlanCfgEntry = + wlanCfgGetEntryByIndex(prAdapter, i, WLAN_CFG_EM); + + if ((!prWlanCfgEntry) || (prWlanCfgEntry->aucKey[0] == '\0')) + break; + + + kalStrnCpy(g_rEmCfgBk[i].aucKey, prWlanCfgEntry->aucKey, + WLAN_CFG_KEY_LEN_MAX - 1); + prWlanCfgEntry->aucKey[WLAN_CFG_KEY_LEN_MAX - 1] = '\0'; + + kalStrnCpy(g_rEmCfgBk[i].aucValue, prWlanCfgEntry->aucValue, + WLAN_CFG_VALUE_LEN_MAX - 1); + prWlanCfgEntry->aucValue[WLAN_CFG_VALUE_LEN_MAX - 1] = '\0'; + + + g_rEmCfgBk[i].u4Flag = WLAN_CFG_EM; + + DBGLOG(INIT, STATE, + "cfg backup:(%s,%s) op:%d\n", + g_rEmCfgBk[i].aucKey, + g_rEmCfgBk[i].aucValue, + g_rEmCfgBk[i].u4Flag); + + } + + +} + +void +wlanCleanAllEmCfgSetting(IN struct ADAPTER * + prAdapter) +{ + uint32_t i; + struct WLAN_CFG_ENTRY *prWlanCfgEntry = NULL; + + for (i = 0; i < WLAN_CFG_ENTRY_NUM_MAX; i++) { + prWlanCfgEntry = + wlanCfgGetEntryByIndex(prAdapter, i, WLAN_CFG_EM); + + if ((!prWlanCfgEntry) || (prWlanCfgEntry->aucKey[0] == '\0')) + break; + + DBGLOG(INIT, STATE, + "cfg clean:(%s,%s) op:%d\n", + prWlanCfgEntry->aucKey, + prWlanCfgEntry->aucValue, + prWlanCfgEntry->u4Flags); + + kalMemZero(prWlanCfgEntry, sizeof(struct WLAN_CFG_ENTRY)); + + } +} + +u_int8_t wlanWfdEnabled(struct ADAPTER *prAdapter) +{ +#if CFG_SUPPORT_WFD + if (prAdapter) + return prAdapter->rWifiVar.rWfdConfigureSettings.ucWfdEnable; +#endif + return FALSE; +} + +int wlanChipConfig(struct ADAPTER *prAdapter, + char *pcCommand, int i4TotalLen) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + int32_t i4BytesWritten = 0; + uint32_t u4BufLen = 0; + uint32_t u2MsgSize = 0; + uint32_t u4CmdLen = 0; + struct PARAM_CUSTOM_CHIP_CONFIG_STRUCT rChipConfigInfo = {0}; + + if (prAdapter == NULL) { + DBGLOG(REQ, ERROR, "prAdapter null"); + return -1; + } + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + + u4CmdLen = kalStrnLen(pcCommand, i4TotalLen); + + rChipConfigInfo.ucType = CHIP_CONFIG_TYPE_ASCII; + rChipConfigInfo.u2MsgSize = u4CmdLen; + kalStrnCpy(rChipConfigInfo.aucCmd, pcCommand, + CHIP_CONFIG_RESP_SIZE - 1); + rChipConfigInfo.aucCmd[CHIP_CONFIG_RESP_SIZE - 1] = '\0'; + rStatus = kalIoctl(prAdapter->prGlueInfo, wlanoidQueryChipConfig, + &rChipConfigInfo, sizeof(rChipConfigInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "%s: kalIoctl ret=%d\n", __func__, + rStatus); + return -1; + } + rChipConfigInfo.aucCmd[CHIP_CONFIG_RESP_SIZE - 1] = '\0'; + + /* Check respType */ + u2MsgSize = rChipConfigInfo.u2MsgSize; + DBGLOG(REQ, INFO, "%s: RespTyep %u\n", __func__, + rChipConfigInfo.ucRespType); + DBGLOG(REQ, INFO, "%s: u2MsgSize %u\n", __func__, + rChipConfigInfo.u2MsgSize); + + if (rChipConfigInfo.ucRespType != CHIP_CONFIG_TYPE_ASCII) { + DBGLOG(REQ, WARN, "only return as ASCII"); + return -1; + } + if (u2MsgSize > sizeof(rChipConfigInfo.aucCmd)) { + DBGLOG(REQ, INFO, "%s: u2MsgSize error ret=%u\n", + __func__, rChipConfigInfo.u2MsgSize); + return -1; + } + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%s", + rChipConfigInfo.aucCmd); + return i4BytesWritten; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/wlan_oid.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/wlan_oid.c new file mode 100644 index 0000000000000..a040d12344bd9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/wlan_oid.c @@ -0,0 +1,16474 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/common + * /wlan_oid.c#11 + */ + +/*! \file wlanoid.c + * \brief This file contains the WLAN OID processing routines of Windows + * 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" +#include "mgmt/rsn.h" +#include "debug.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 + ****************************************************************************** + */ +#if DBG && 0 +static void SetRCID(u_int8_t fgOneTb3, u_int8_t *fgRCID); +#endif + +#if CFG_SLT_SUPPORT +static void SetTestChannel(uint8_t *pucPrimaryChannel); +#endif + +/****************************************************************************** + * F U N C T I O N S + ****************************************************************************** + */ +static void setApUapsdEnable(struct ADAPTER *prAdapter, + u_int8_t enable) +{ + struct PARAM_CUSTOM_UAPSD_PARAM_STRUCT rUapsdParams; + uint32_t u4SetInfoLen = 0; + uint8_t ucBssIdx; + + /* FIX ME: Add p2p role index selection */ + if (p2pFuncRoleToBssIdx( + prAdapter, 0, &ucBssIdx) != WLAN_STATUS_SUCCESS) + return; + + DBGLOG(OID, INFO, "setApUapsdEnable: %d, ucBssIdx: %d\n", + enable, ucBssIdx); + + rUapsdParams.ucBssIdx = ucBssIdx; + + if (enable) { + prAdapter->rWifiVar.ucApUapsd = TRUE; + rUapsdParams.fgEnAPSD = 1; + rUapsdParams.fgEnAPSD_AcBe = 1; + rUapsdParams.fgEnAPSD_AcBk = 1; + rUapsdParams.fgEnAPSD_AcVi = 1; + rUapsdParams.fgEnAPSD_AcVo = 1; + /* default: 0, do not limit delivery pkt number */ + rUapsdParams.ucMaxSpLen = 0; + } else { + prAdapter->rWifiVar.ucApUapsd = FALSE; + rUapsdParams.fgEnAPSD = 0; + rUapsdParams.fgEnAPSD_AcBe = 0; + rUapsdParams.fgEnAPSD_AcBk = 0; + rUapsdParams.fgEnAPSD_AcVi = 0; + rUapsdParams.fgEnAPSD_AcVo = 0; + /* default: 0, do not limit delivery pkt number */ + rUapsdParams.ucMaxSpLen = 0; + } + wlanoidSetUApsdParam(prAdapter, + &rUapsdParams, + sizeof(struct PARAM_CUSTOM_UAPSD_PARAM_STRUCT), + &u4SetInfoLen); +} + +#if CFG_ENABLE_STATISTICS_BUFFERING +static u_int8_t IsBufferedStatisticsUsable( + struct ADAPTER *prAdapter) +{ + ASSERT(prAdapter); + + if (prAdapter->fgIsStatValid == TRUE && + (kalGetTimeTick() - prAdapter->rStatUpdateTime) <= + CFG_STATISTICS_VALID_CYCLE) + return TRUE; + else + return FALSE; +} +#endif + +#if DBG && 0 +static void SetRCID(u_int8_t fgOneTb3, u_int8_t *fgRCID) +{ + if (fgOneTb3) + *fgRCID = 0; + else + *fgRCID = 1; +} +#endif + +#if CFG_SLT_SUPPORT +static void SetTestChannel(uint8_t *pucPrimaryChannel) +{ + if (*pucPrimaryChannel < 5) + *pucPrimaryChannel = 8; + else if (*pucPrimaryChannel > 10) + *pucPrimaryChannel = 3; +} +#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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryNetworkTypesSupported(IN struct ADAPTER + *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + uint32_t u4NumItem = 0; + enum ENUM_PARAM_NETWORK_TYPE + eSupportedNetworks[PARAM_NETWORK_TYPE_NUM]; + struct PARAM_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 = + (uint32_t) OFFSET_OF(struct PARAM_NETWORK_TYPE_LIST, + eNetworkType) + + (u4NumItem * sizeof(enum ENUM_PARAM_NETWORK_TYPE)); + + if (u4QueryBufferLen < *pu4QueryInfoLen) + return WLAN_STATUS_INVALID_LENGTH; + + prSupported = (struct PARAM_NETWORK_TYPE_LIST *) + pvQueryBuffer; + prSupported->NumberOfItems = u4NumItem; + kalMemCopy(prSupported->eNetworkType, eSupportedNetworks, + u4NumItem * sizeof(enum ENUM_PARAM_NETWORK_TYPE)); + + DBGLOG(REQ, TRACE, "NDIS supported network type list: %u\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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryNetworkTypeInUse(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + /* TODO: need to check the OID handler content again!! */ + + enum ENUM_PARAM_NETWORK_TYPE rCurrentNetworkTypeInUse = + PARAM_NETWORK_TYPE_OFDM24; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + DEBUGFUNC("wlanoidQueryNetworkTypeInUse"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(enum + ENUM_PARAM_NETWORK_TYPE)) { + *pu4QueryInfoLen = sizeof(enum ENUM_PARAM_NETWORK_TYPE); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo, + ucBssIndex) == + MEDIA_STATE_CONNECTED) + rCurrentNetworkTypeInUse = (enum ENUM_PARAM_NETWORK_TYPE) ( + prAdapter->rWlanInfo.ucNetworkType[ucBssIndex]); + else + rCurrentNetworkTypeInUse = (enum ENUM_PARAM_NETWORK_TYPE) ( + prAdapter->rWlanInfo.ucNetworkTypeInUse); + + *(enum ENUM_PARAM_NETWORK_TYPE *) pvQueryBuffer = + rCurrentNetworkTypeInUse; + *pu4QueryInfoLen = sizeof(enum ENUM_PARAM_NETWORK_TYPE); + + 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetNetworkTypeInUse(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + /* TODO: need to check the OID handler content again!! */ + + enum ENUM_PARAM_NETWORK_TYPE eNewNetworkType; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidSetNetworkTypeInUse"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(enum ENUM_PARAM_NETWORK_TYPE)) { + *pu4SetInfoLen = sizeof(enum ENUM_PARAM_NETWORK_TYPE); + return WLAN_STATUS_INVALID_LENGTH; + } + + eNewNetworkType = *(enum ENUM_PARAM_NETWORK_TYPE *) + pvSetBuffer; + *pu4SetInfoLen = sizeof(enum ENUM_PARAM_NETWORK_TYPE); + + DBGLOG(REQ, INFO, "New network type: %d mode\n", + eNewNetworkType); + + switch (eNewNetworkType) { + + case PARAM_NETWORK_TYPE_DS: + prAdapter->rWlanInfo.ucNetworkTypeInUse = + (uint8_t) PARAM_NETWORK_TYPE_DS; + break; + + case PARAM_NETWORK_TYPE_OFDM5: + prAdapter->rWlanInfo.ucNetworkTypeInUse = + (uint8_t) PARAM_NETWORK_TYPE_OFDM5; + break; + + case PARAM_NETWORK_TYPE_OFDM24: + prAdapter->rWlanInfo.ucNetworkTypeInUse = + (uint8_t) PARAM_NETWORK_TYPE_OFDM24; + break; + + case PARAM_NETWORK_TYPE_AUTOMODE: + prAdapter->rWlanInfo.ucNetworkTypeInUse = + (uint8_t) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryBssid(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint8_t ucBssIndex = 0; + struct PARAM_BSSID_EX *prCurrBssid; + + 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); + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + + prCurrBssid = aisGetCurrBssId(prAdapter, + ucBssIndex); + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo, + ucBssIndex) == + MEDIA_STATE_CONNECTED) + kalMemCopy(pvQueryBuffer, + prCurrBssid->arMacAddress, + MAC_ADDR_LEN); + else if (aisGetOPMode(prAdapter, ucBssIndex) == + NET_TYPE_IBSS) { + uint8_t aucTemp[PARAM_MAC_ADDR_LEN]; /*!< BSSID */ + + COPY_MAC_ADDR(aucTemp, + prCurrBssid->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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryBssidList(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + struct GLUE_INFO *prGlueInfo; + uint32_t i, u4BssidListExLen; + struct PARAM_BSSID_LIST_EX *prList; + struct PARAM_BSSID_EX *prBssidEx; + uint8_t *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(struct PARAM_BSSID_LIST_EX); + + *pu4QueryInfoLen = u4BssidListExLen; + + if (u4QueryBufferLen < *pu4QueryInfoLen) + return WLAN_STATUS_INVALID_LENGTH; + + /* Clear the buffer */ + kalMemZero(pvQueryBuffer, u4BssidListExLen); + + prList = (struct PARAM_BSSID_LIST_EX *) pvQueryBuffer; + cp = (uint8_t *) &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 = (struct PARAM_BSSID_EX *) cp; + + /* copy structure */ + kalMemCopy(prBssidEx, + &(prAdapter->rWlanInfo.arScanResult[i]), + OFFSET_OF(struct PARAM_BSSID_EX, 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetBssidListScan(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct PARAM_SSID *prSsid; + struct PARAM_SSID rSsid; + uint8_t ucBssIndex = 0; + + DEBUGFUNC("wlanoidSetBssidListScan()"); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in set BSSID list scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (prAdapter->fgTestMode) { + DBGLOG(OID, WARN, "didn't support Scan in test mode\n"); + return WLAN_STATUS_FAILURE; + } + + ASSERT(pu4SetInfoLen); + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + + DBGLOG(REQ, LOUD, "ucBssIndex %d\n", ucBssIndex); + + *pu4SetInfoLen = 0; + + if (prAdapter->fgIsRadioOff) { + DBGLOG(OID, WARN, + "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + 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->prRegInfo->u4RddTestMode) { + if (prAdapter->fgEnOnlineScan && prAdapter->ucRddStatus) { + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo, + ucBssIndex) + != MEDIA_STATE_CONNECTED) + aisFsmScanRequest(prAdapter, prSsid, NULL, 0, + ucBssIndex); + else + return WLAN_STATUS_FAILURE; + } else + return WLAN_STATUS_FAILURE; + } else +#endif + { + if (prAdapter->fgEnOnlineScan == TRUE) + aisFsmScanRequest(prAdapter, prSsid, NULL, 0, + ucBssIndex); + else if (kalGetMediaStateIndicated(prAdapter->prGlueInfo, + ucBssIndex) != + MEDIA_STATE_CONNECTED) + aisFsmScanRequest(prAdapter, prSsid, NULL, 0, + ucBssIndex); + else + return WLAN_STATUS_FAILURE; + } + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetBssidListScanExt(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct PARAM_SCAN_REQUEST_EXT *prScanRequest; + struct PARAM_SSID *prSsid; + uint8_t *pucIe; + uint32_t u4IeLength; + uint8_t ucBssIndex = 0; + + DEBUGFUNC("wlanoidSetBssidListScanExt()"); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in set BSSID list scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (prAdapter->fgTestMode) { + DBGLOG(OID, WARN, "didn't support Scan in test mode\n"); + return WLAN_STATUS_FAILURE; + } + + ASSERT(pu4SetInfoLen); + *pu4SetInfoLen = 0; + + if (u4SetBufferLen != sizeof(struct PARAM_SCAN_REQUEST_EXT)) + return WLAN_STATUS_INVALID_LENGTH; + + if (prAdapter->fgIsRadioOff) { + DBGLOG(OID, WARN, + "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + DBGLOG(OID, TRACE, "ScanEX\n"); + if (pvSetBuffer != NULL && u4SetBufferLen != 0) { + prScanRequest = (struct PARAM_SCAN_REQUEST_EXT *) + pvSetBuffer; + prSsid = &(prScanRequest->rSsid); + pucIe = prScanRequest->pucIE; + u4IeLength = prScanRequest->u4IELength; + ucBssIndex = prScanRequest->ucBssIndex; + } else { + prScanRequest = NULL; + prSsid = NULL; + pucIe = NULL; + u4IeLength = 0; + } + +#if CFG_SUPPORT_RDD_TEST_MODE + if (prAdapter->prGlueInfo->prRegInfo->u4RddTestMode) { + if (prAdapter->fgEnOnlineScan && prAdapter->ucRddStatus) { + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo, + ucBssIndex) + != MEDIA_STATE_CONNECTED) + aisFsmScanRequest(prAdapter, prSsid, + pucIe, u4IeLength, + ucBssIndex); + else + return WLAN_STATUS_FAILURE; + } else + return WLAN_STATUS_FAILURE; + } else +#endif + { + if (prAdapter->fgEnOnlineScan == TRUE) + aisFsmScanRequest(prAdapter, prSsid, pucIe, u4IeLength, + ucBssIndex); + else if (kalGetMediaStateIndicated(prAdapter->prGlueInfo, + ucBssIndex) != + MEDIA_STATE_CONNECTED) + aisFsmScanRequest(prAdapter, prSsid, pucIe, u4IeLength, + ucBssIndex); + else + return WLAN_STATUS_FAILURE; + } + + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetBssidListScanWithIE */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to request the driver to perform + * scanning with attaching information elements(IEs) specified from user + * space and multiple SSID + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetBssidListScanAdv(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct PARAM_SCAN_REQUEST_ADV *prScanRequest; + uint8_t ucBssIndex = 0; + + DEBUGFUNC("wlanoidSetBssidListScanAdv()"); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in set BSSID list scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (prAdapter->fgTestMode) { + DBGLOG(OID, WARN, "didn't support Scan in test mode\n"); + return WLAN_STATUS_FAILURE; + } + + ASSERT(pu4SetInfoLen); + *pu4SetInfoLen = 0; + + if (u4SetBufferLen != sizeof(struct PARAM_SCAN_REQUEST_ADV)) + return WLAN_STATUS_INVALID_LENGTH; + else if (pvSetBuffer == NULL) + return WLAN_STATUS_INVALID_DATA; + + if (prAdapter->fgIsRadioOff) { + DBGLOG(OID, WARN, + "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + prScanRequest = (struct PARAM_SCAN_REQUEST_ADV *) pvSetBuffer; + ucBssIndex = prScanRequest->ucBssIndex; +#if CFG_SUPPORT_RDD_TEST_MODE + if (prAdapter->prGlueInfo->prRegInfo->u4RddTestMode) { + if (prAdapter->fgEnOnlineScan && prAdapter->ucRddStatus) { + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo, + ucBssIndex) + != MEDIA_STATE_CONNECTED) { + aisFsmScanRequestAdv(prAdapter, prScanRequest); + } else + return WLAN_STATUS_FAILURE; + } else + return WLAN_STATUS_FAILURE; + } else +#endif + { + if (prAdapter->fgEnOnlineScan == TRUE) { + aisFsmScanRequestAdv(prAdapter, prScanRequest); + } else if (kalGetMediaStateIndicated(prAdapter->prGlueInfo, + ucBssIndex) + != MEDIA_STATE_CONNECTED) { + aisFsmScanRequestAdv(prAdapter, prScanRequest); + } else + return WLAN_STATUS_FAILURE; + } + cnmTimerStartTimer(prAdapter, + aisGetScanDoneTimer(prAdapter, ucBssIndex), + SEC_TO_MSEC(AIS_SCN_DONE_TIMEOUT_SEC)); + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetBssidListScanAdv */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetBssid(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct GLUE_INFO *prGlueInfo; + uint8_t *pAddr; + uint32_t i; + int32_t i4Idx = -1; + struct MSG_AIS_ABORT *prAisAbortMsg; + uint8_t ucReasonOfDisconnect; + struct CONNECTION_SETTINGS *prConnSettings; + struct PARAM_BSSID_EX *prCurrBssid; + uint8_t ucBssIndex = 0; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + + DBGLOG(REQ, LOUD, "ucBssIndex %d\n", ucBssIndex); + + prConnSettings = + aisGetConnSettings(prAdapter, ucBssIndex); + + prCurrBssid = aisGetCurrBssId(prAdapter, + ucBssIndex); + + *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 = (uint8_t *) pvSetBuffer; + + /* re-association check */ + if (kalGetMediaStateIndicated(prGlueInfo, ucBssIndex) == + MEDIA_STATE_CONNECTED) { + if (EQUAL_MAC_ADDR( + prCurrBssid->arMacAddress, pAddr)) { + kalSetMediaStateIndicated(prGlueInfo, + MEDIA_STATE_TO_BE_INDICATED, + ucBssIndex); + ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_REASSOCIATION; + } else { + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0, + ucBssIndex); + ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_NEW_CONNECTION; + } + } else { + ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_NEW_CONNECTION; + } + + /* check if any scanned result matchs with the BSSID */ + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + if (EQUAL_MAC_ADDR( + prAdapter->rWlanInfo.arScanResult[i].arMacAddress, pAddr)) { + i4Idx = (int32_t) i; + break; + } + } + + /* prepare message to AIS */ + if (prConnSettings->eOPMode == + NET_TYPE_IBSS + || prConnSettings->eOPMode == + NET_TYPE_DEDICATED_IBSS) { + /* IBSS *//* beacon period */ + prConnSettings->u2BeaconPeriod = + prAdapter->rWlanInfo.u2BeaconPeriod; + prConnSettings->u2AtimWindow = + prAdapter->rWlanInfo.u2AtimWindow; + } + + /* Set Connection Request Issued Flag */ + prConnSettings->eConnectionPolicy = + CONNECT_BY_BSSID; + + /* Send AIS Abort Message */ + prAisAbortMsg = (struct MSG_AIS_ABORT *) cnmMemAlloc( + prAdapter, RAM_TYPE_MSG, sizeof(struct MSG_AIS_ABORT)); + if (!prAisAbortMsg) { + DBGLOG(REQ, ERROR, "Fail in allocating AisAbortMsg.\n"); + return WLAN_STATUS_FAILURE; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; + prAisAbortMsg->ucReasonOfDisconnect = ucReasonOfDisconnect; + + /* Update the information to CONNECTION_SETTINGS_T */ + prConnSettings->ucSSIDLen = 0; + prConnSettings->aucSSID[0] = '\0'; + COPY_MAC_ADDR(prConnSettings->aucBSSID, pAddr); + + if (EQUAL_MAC_ADDR(prCurrBssid->arMacAddress, pAddr)) + prAisAbortMsg->fgDelayIndication = TRUE; + else + prAisAbortMsg->fgDelayIndication = FALSE; + prAisAbortMsg->ucBssIndex = ucBssIndex; + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetSsid(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct GLUE_INFO *prGlueInfo; + struct PARAM_SSID *pParamSsid; + uint32_t i; + int32_t i4Idx = -1, i4MaxRSSI = INT_MIN; + struct MSG_AIS_ABORT *prAisAbortMsg; + u_int8_t fgIsValidSsid = TRUE; + struct CONNECTION_SETTINGS *prConnSettings; + struct PARAM_BSSID_EX *prCurrBssid; + uint8_t ucBssIndex = 0; + + 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(struct PARAM_SSID) + || u4SetBufferLen > sizeof(struct PARAM_SSID)) + 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 = (struct PARAM_SSID *) pvSetBuffer; + + if (pParamSsid->u4SsidLen > 32) + return WLAN_STATUS_INVALID_LENGTH; + + prGlueInfo = prAdapter->prGlueInfo; + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + + prConnSettings = + aisGetConnSettings(prAdapter, ucBssIndex); + prCurrBssid = aisGetCurrBssId(prAdapter, + ucBssIndex); + + /* prepare for CMD_BUILD_CONNECTION & CMD_GET_CONNECTION_STATUS */ + /* re-association check */ + if (kalGetMediaStateIndicated(prGlueInfo, ucBssIndex) == + MEDIA_STATE_CONNECTED) { + if (EQUAL_SSID(prCurrBssid->rSsid.aucSsid, + prCurrBssid->rSsid.u4SsidLen, + pParamSsid->aucSsid, pParamSsid->u4SsidLen)) { + kalSetMediaStateIndicated(prGlueInfo, + MEDIA_STATE_TO_BE_INDICATED, + ucBssIndex); + } else + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0, + ucBssIndex); + } + /* check if any scanned result matchs with the SSID */ + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + uint8_t *aucSsid = + prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid; + uint8_t ucSsidLength = (uint8_t) + prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen; + int32_t i4RSSI = prAdapter->rWlanInfo.arScanResult[i].rRssi; + + if (EQUAL_SSID(aucSsid, ucSsidLength, pParamSsid->aucSsid, + pParamSsid->u4SsidLen) && + i4RSSI >= i4MaxRSSI) { + i4Idx = (int32_t) i; + i4MaxRSSI = i4RSSI; + } + } + + /* prepare message to AIS */ + if (prConnSettings->eOPMode == + NET_TYPE_IBSS + || prConnSettings->eOPMode == + NET_TYPE_DEDICATED_IBSS) { + /* IBSS *//* beacon period */ + prConnSettings->u2BeaconPeriod = + prAdapter->rWlanInfo.u2BeaconPeriod; + prConnSettings->u2AtimWindow = + prAdapter->rWlanInfo.u2AtimWindow; + } + + if (prAdapter->rWifiVar.fgSupportWZCDisassociation) { + if (pParamSsid->u4SsidLen == ELEM_MAX_LEN_SSID) { + fgIsValidSsid = FALSE; + + for (i = 0; i < ELEM_MAX_LEN_SSID; i++) { + if (!((pParamSsid->aucSsid[i] > 0) + && (pParamSsid->aucSsid[i] <= 0x1F))) { + fgIsValidSsid = TRUE; + break; + } + } + } + } + + /* Set Connection Request Issued Flag */ + if (fgIsValidSsid) { + if (pParamSsid->u4SsidLen) + prConnSettings->eConnectionPolicy = + CONNECT_BY_SSID_BEST_RSSI; + else + /* wildcard SSID */ + prConnSettings->eConnectionPolicy = + CONNECT_BY_SSID_ANY; + } + + /* Send AIS Abort Message */ + prAisAbortMsg = (struct MSG_AIS_ABORT *) cnmMemAlloc( + prAdapter, RAM_TYPE_MSG, sizeof(struct MSG_AIS_ABORT)); + if (!prAisAbortMsg) { + DBGLOG(REQ, ERROR, "Fail in allocating AisAbortMsg.\n"); + return WLAN_STATUS_FAILURE; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; + prAisAbortMsg->ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_NEW_CONNECTION; + COPY_SSID(prConnSettings->aucSSID, + prConnSettings->ucSSIDLen, + pParamSsid->aucSsid, (uint8_t) pParamSsid->u4SsidLen); + + if (EQUAL_SSID( + prCurrBssid->rSsid.aucSsid, + prCurrBssid->rSsid.u4SsidLen, + pParamSsid->aucSsid, pParamSsid->u4SsidLen)) { + prAisAbortMsg->fgDelayIndication = TRUE; + } else { + /* Update the information to CONNECTION_SETTINGS_T */ + prAisAbortMsg->fgDelayIndication = FALSE; + } + + prAisAbortMsg->ucBssIndex = ucBssIndex; + + DBGLOG(SCN, INFO, "ucBssIndex %d, SSID %s\n", + ucBssIndex, + HIDE(prConnSettings->aucSSID)); + + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prAisAbortMsg, MSG_SEND_METHOD_BUF); + + return WLAN_STATUS_SUCCESS; + +} /* end of wlanoidSetSsid() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine will initiate the join procedure to attempt + * to associate with the new BSS, base on given SSID, BSSID, and + * freqency. + * If the target connecting BSS is in the same ESS as current connected + * BSS, roaming will be performed. + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetConnect(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct GLUE_INFO *prGlueInfo; + struct PARAM_CONNECT *pParamConn; + struct CONNECTION_SETTINGS *prConnSettings; + uint32_t i; + struct MSG_AIS_ABORT *prAisAbortMsg; + u_int8_t fgIsValidSsid = TRUE; + u_int8_t fgEqualSsid = FALSE; + u_int8_t fgEqualBssid = FALSE; + const uint8_t aucZeroMacAddr[] = NULL_MAC_ADDR; + uint8_t ucBssIndex = 0; + struct PARAM_BSSID_EX *prCurrBssid; + + 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(struct PARAM_CONNECT)) + 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; + } + prAisAbortMsg = (struct MSG_AIS_ABORT *) cnmMemAlloc( + prAdapter, RAM_TYPE_MSG, sizeof(struct MSG_AIS_ABORT)); + if (!prAisAbortMsg) { + DBGLOG(REQ, ERROR, "Fail in allocating AisAbortMsg.\n"); + return WLAN_STATUS_FAILURE; + } + prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; + + pParamConn = (struct PARAM_CONNECT *) pvSetBuffer; + + ucBssIndex = pParamConn->ucBssIdx; + + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + prCurrBssid = aisGetCurrBssId(prAdapter, + ucBssIndex); + + if (pParamConn->u4SsidLen > 32) { + cnmMemFree(prAdapter, prAisAbortMsg); + DBGLOG(OID, WARN, "SsidLen [%d] is invalid!\n", + pParamConn->u4SsidLen); + return WLAN_STATUS_INVALID_LENGTH; + } else if (!pParamConn->pucBssid && !pParamConn->pucSsid) { + cnmMemFree(prAdapter, prAisAbortMsg); + DBGLOG(OID, WARN, "Bssid or ssid is invalid!\n"); + return WLAN_STATUS_INVALID_LENGTH; + } + + prGlueInfo = prAdapter->prGlueInfo; + kalMemZero(prConnSettings->aucSSID, + sizeof(prConnSettings->aucSSID)); + prConnSettings->ucSSIDLen = 0; + kalMemZero(prConnSettings->aucBSSID, + sizeof(prConnSettings->aucBSSID)); + kalMemZero(prConnSettings->aucBSSIDHint, + sizeof(prConnSettings->aucBSSIDHint)); + prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_ANY; + prConnSettings->fgIsConnByBssidIssued = FALSE; + + if (pParamConn->pucSsid) { + prConnSettings->eConnectionPolicy = + CONNECT_BY_SSID_BEST_RSSI; + COPY_SSID(prConnSettings->aucSSID, + prConnSettings->ucSSIDLen, pParamConn->pucSsid, + (uint8_t) pParamConn->u4SsidLen); + if (EQUAL_SSID(prCurrBssid->rSsid.aucSsid, + prCurrBssid->rSsid.u4SsidLen, + pParamConn->pucSsid, pParamConn->u4SsidLen)) + fgEqualSsid = TRUE; + } + if (pParamConn->pucBssid) { + if (!EQUAL_MAC_ADDR(aucZeroMacAddr, pParamConn->pucBssid) + && IS_UCAST_MAC_ADDR(pParamConn->pucBssid)) { + prConnSettings->eConnectionPolicy = CONNECT_BY_BSSID; + prConnSettings->fgIsConnByBssidIssued = TRUE; + COPY_MAC_ADDR(prConnSettings->aucBSSID, + pParamConn->pucBssid); + if (EQUAL_MAC_ADDR( + prCurrBssid->arMacAddress, + pParamConn->pucBssid)) + fgEqualBssid = TRUE; + } else + DBGLOG(INIT, INFO, "wrong bssid " MACSTR "to connect\n", + MAC2STR(pParamConn->pucBssid)); + } else if (pParamConn->pucBssidHint) { + if (!EQUAL_MAC_ADDR(aucZeroMacAddr, pParamConn->pucBssidHint) + && IS_UCAST_MAC_ADDR(pParamConn->pucBssidHint)) { + if (ucBssIndex < + prAdapter->rWifiVar.u4AisRoamingNumber) { + prConnSettings->eConnectionPolicy = + CONNECT_BY_BSSID_HINT; + COPY_MAC_ADDR(prConnSettings->aucBSSIDHint, + pParamConn->pucBssidHint); +#if CFG_TC3_FEATURE + if (EQUAL_MAC_ADDR( + prCurrBssid->arMacAddress, + pParamConn->pucBssidHint)) + fgEqualBssid = TRUE; +#endif + + } else { + prConnSettings->eConnectionPolicy = + CONNECT_BY_BSSID; + prConnSettings->fgIsConnByBssidIssued = TRUE; + COPY_MAC_ADDR(prConnSettings->aucBSSID, + pParamConn->pucBssidHint); + if (EQUAL_MAC_ADDR( + prCurrBssid->arMacAddress, + pParamConn->pucBssidHint)) + fgEqualBssid = TRUE; + DBGLOG(INIT, INFO, + "Force to use bssid (%d)", ucBssIndex); + } + } + } else + DBGLOG(INIT, INFO, "No Bssid set\n"); + prConnSettings->u4FreqInKHz = pParamConn->u4CenterFreq; + + /* prepare for CMD_BUILD_CONNECTION & CMD_GET_CONNECTION_STATUS */ + /* re-association check */ + if (kalGetMediaStateIndicated(prGlueInfo, + ucBssIndex) == + MEDIA_STATE_CONNECTED) { + if (fgEqualSsid) { + prAisAbortMsg->ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_ROAMING; + if (fgEqualBssid) { + kalSetMediaStateIndicated(prGlueInfo, + MEDIA_STATE_TO_BE_INDICATED, + ucBssIndex); + prAisAbortMsg->ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_REASSOCIATION; + } + } else { + DBGLOG(INIT, INFO, "DisBySsid\n"); + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0, + ucBssIndex); + prAisAbortMsg->ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_NEW_CONNECTION; + cnmMemFree(prAdapter, prAisAbortMsg); + /* reject this connect to avoid to install key fail */ + return WLAN_STATUS_FAILURE; + } + } else + prAisAbortMsg->ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_NEW_CONNECTION; +#if 0 + /* check if any scanned result matchs with the SSID */ + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + uint8_t *aucSsid = + prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid; + uint8_t ucSsidLength = (uint8_t) + prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen; + int32_t i4RSSI = prAdapter->rWlanInfo.arScanResult[i].rRssi; + + if (EQUAL_SSID(aucSsid, ucSsidLength, pParamConn->pucSsid, + pParamConn->u4SsidLen) && + i4RSSI >= i4MaxRSSI) { + i4Idx = (int32_t) i; + i4MaxRSSI = i4RSSI; + } + if (EQUAL_MAC_ADDR( + prAdapter->rWlanInfo.arScanResult[i].arMacAddress, pAddr)) { + i4Idx = (int32_t) i; + break; + } + } +#endif + /* prepare message to AIS */ + if (prConnSettings->eOPMode == NET_TYPE_IBSS + || prConnSettings->eOPMode == NET_TYPE_DEDICATED_IBSS) { + /* IBSS *//* beacon period */ + prConnSettings->u2BeaconPeriod = + prAdapter->rWlanInfo.u2BeaconPeriod; + prConnSettings->u2AtimWindow = + prAdapter->rWlanInfo.u2AtimWindow; + } + + if (prAdapter->rWifiVar.fgSupportWZCDisassociation) { + if (pParamConn->u4SsidLen == ELEM_MAX_LEN_SSID) { + fgIsValidSsid = FALSE; + + if (pParamConn->pucSsid) { + for (i = 0; i < ELEM_MAX_LEN_SSID; i++) { + if (!((pParamConn->pucSsid[i] > 0) && + (pParamConn->pucSsid[i] <= 0x1F))) { + fgIsValidSsid = TRUE; + break; + } + } + } else { + DBGLOG(INIT, ERROR, + "pParamConn->pucSsid is NULL\n"); + } + } + } + + if (fgEqualSsid || fgEqualBssid) + prAisAbortMsg->fgDelayIndication = TRUE; + else + /* Update the information to CONNECTION_SETTINGS_T */ + prAisAbortMsg->fgDelayIndication = FALSE; + prAisAbortMsg->ucBssIndex = ucBssIndex; + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prAisAbortMsg, MSG_SEND_METHOD_BUF); + + DBGLOG(INIT, INFO, + "ucBssIndex %d, ssid %s, bssid " MACSTR + ", bssid_hint " MACSTR ", conn policy %d, disc reason %d\n", + ucBssIndex, + HIDE(prConnSettings->aucSSID), + MAC2STR(prConnSettings->aucBSSID), + MAC2STR(prConnSettings->aucBSSIDHint), + prConnSettings->eConnectionPolicy, + prAisAbortMsg->ucReasonOfDisconnect); + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetConnect */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQuerySsid(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + struct PARAM_SSID *prAssociatedSsid; + struct PARAM_BSSID_EX *prCurrBssid; + uint8_t ucBssIndex = 0; + + DEBUGFUNC("wlanoidQuerySsid"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + + *pu4QueryInfoLen = sizeof(struct PARAM_SSID); + + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prAssociatedSsid = (struct PARAM_SSID *) pvQueryBuffer; + + kalMemZero(prAssociatedSsid->aucSsid, + sizeof(prAssociatedSsid->aucSsid)); + + prCurrBssid = aisGetCurrBssId(prAdapter, + ucBssIndex); + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo, + ucBssIndex) == + MEDIA_STATE_CONNECTED) { + prAssociatedSsid->u4SsidLen = + prCurrBssid->rSsid.u4SsidLen; + + if (prAssociatedSsid->u4SsidLen) { + kalMemCopy(prAssociatedSsid->aucSsid, + prCurrBssid->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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryInfrastructureMode(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + struct CONNECTION_SETTINGS *prConnSettings; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + DEBUGFUNC("wlanoidQueryInfrastructureMode"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + prConnSettings = + aisGetConnSettings(prAdapter, ucBssIndex); + + *pu4QueryInfoLen = sizeof(enum ENUM_PARAM_OP_MODE); + + if (u4QueryBufferLen < sizeof(enum ENUM_PARAM_OP_MODE)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *(enum ENUM_PARAM_OP_MODE *) pvQueryBuffer = + prConnSettings->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 (*(enum ENUM_PARAM_OP_MODE *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetInfrastructureMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct GLUE_INFO *prGlueInfo; + struct PARAM_OP_MODE *pOpMode; + enum ENUM_PARAM_OP_MODE eOpMode; + /* P_WLAN_TABLE_T prWlanTable; */ +#if CFG_SUPPORT_802_11W + struct AIS_SPECIFIC_BSS_INFO *prAisSpecBssInfo; +#endif + /* UINT_8 i; */ + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_INFO *prAisBssInfo; + uint8_t ucBssIndex = 0; + + DEBUGFUNC("wlanoidSetInfrastructureMode"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prGlueInfo = prAdapter->prGlueInfo; + + if (u4SetBufferLen < sizeof(struct PARAM_OP_MODE)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + 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; + } + + pOpMode = (struct PARAM_OP_MODE *) pvSetBuffer; + + ucBssIndex = pOpMode->ucBssIdx; + prAisSpecBssInfo = + aisGetAisSpecBssInfo(prAdapter, ucBssIndex); + prConnSettings = + aisGetConnSettings(prAdapter, ucBssIndex); + prAisBssInfo = + aisGetAisBssInfo(prAdapter, ucBssIndex); + + eOpMode = pOpMode->eOpMode; + /* 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. */ + prConnSettings->eOPMode = eOpMode; + + prConnSettings->fgWapiMode = FALSE; + +#if CFG_SUPPORT_802_11W + prAisSpecBssInfo->fgMgmtProtection = + FALSE; + prAisSpecBssInfo->fgBipKeyInstalled = + FALSE; +#endif + +#if 0 /* STA record remove at AIS_ABORT nicUpdateBss and DISCONNECT */ + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) + cnmStaFreeAllStaByNetwork(prAdapter, + prBssInfo->ucBssIndex, 0); + } +#endif + + /* Clean up the Tx key flag */ + if (prAisBssInfo != NULL) { + prAisBssInfo->fgBcDefaultKeyExist = FALSE; + prAisBssInfo->ucBcDefaultKeyIdx = 0xFF; + } + + /* prWlanTable = prAdapter->rWifiVar.arWtbl; */ + /* prWlanTable[prAisBssInfo->ucBMCWlanIndex].ucKeyId = 0; */ + + DBGLOG(RSN, LOUD, "ucBssIndex %d\n", ucBssIndex); + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryAuthMode(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + DEBUGFUNC("wlanoidQueryAuthMode"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(enum ENUM_PARAM_AUTH_MODE); + + if (u4QueryBufferLen < sizeof(enum ENUM_PARAM_AUTH_MODE)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + *(enum ENUM_PARAM_AUTH_MODE *) pvQueryBuffer = + aisGetAuthMode(prAdapter, ucBssIndex); + +#if DBG + switch (*(enum ENUM_PARAM_AUTH_MODE *) 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", + *(enum ENUM_PARAM_AUTH_MODE *) pvQueryBuffer); + break; + } +#endif + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryAuthMode */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set the IEEE 802.11 authentication mode + * to the driver. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. + * \param[in] u4SetBufferLen The length of the set buffer. + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed + * due to invalid length of the set buffer, returns + * the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_DATA + * \retval WLAN_STATUS_INVALID_LENGTH + * \retval WLAN_STATUS_ADAPTER_NOT_READY + * \retval WLAN_STATUS_NOT_ACCEPTED + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetAuthMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct GLUE_INFO *prGlueInfo; + /* UINT_32 i, u4AkmSuite; */ + /* P_DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY prEntry; */ + struct CONNECTION_SETTINGS *prConnSettings; + uint8_t ucBssIndex = 0; + + DEBUGFUNC("wlanoidSetAuthMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + prGlueInfo = prAdapter->prGlueInfo; + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + + DBGLOG(REQ, LOUD, "ucBssIndex %d\n", ucBssIndex); + + prConnSettings = + aisGetConnSettings(prAdapter, ucBssIndex); + + *pu4SetInfoLen = sizeof(enum ENUM_PARAM_AUTH_MODE); + + if (u4SetBufferLen < sizeof(enum ENUM_PARAM_AUTH_MODE)) + 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 (*(enum ENUM_PARAM_AUTH_MODE *) pvSetBuffer >= + AUTH_MODE_NUM) { + DBGLOG(REQ, TRACE, "Invalid auth mode %d\n", + *(enum ENUM_PARAM_AUTH_MODE *) pvSetBuffer); + return WLAN_STATUS_INVALID_DATA; + } + + switch (*(enum ENUM_PARAM_AUTH_MODE *) pvSetBuffer) { + case AUTH_MODE_WPA_OSEN: + case AUTH_MODE_WPA: + case AUTH_MODE_WPA_PSK: + case AUTH_MODE_WPA2: + case AUTH_MODE_WPA2_PSK: + case AUTH_MODE_WPA2_FT: + case AUTH_MODE_WPA2_FT_PSK: + case AUTH_MODE_WPA3_SAE: + case AUTH_MODE_WPA3_OWE: + /* infrastructure mode only */ + if (prConnSettings->eOPMode != + NET_TYPE_INFRA) + return WLAN_STATUS_NOT_ACCEPTED; + break; + + case AUTH_MODE_WPA_NONE: + /* ad hoc mode only */ + if (prConnSettings->eOPMode != + NET_TYPE_IBSS) + return WLAN_STATUS_NOT_ACCEPTED; + break; + + default: + break; + } + + /* Save the new authentication mode. */ + prConnSettings->eAuthMode = * + (enum ENUM_PARAM_AUTH_MODE *) pvSetBuffer; + +#if 1 /* DBG */ + switch (prConnSettings->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; + + case AUTH_MODE_WPA3_SAE: + DBGLOG(RSN, INFO, "New auth mode: SAE\n"); + break; + + default: + DBGLOG(RSN, TRACE, "New auth mode: unknown (%d)\n", + prConnSettings->eAuthMode); + } +#endif + +#if 0 + if (prConnSettings->eAuthMode >= + AUTH_MODE_WPA) { + switch (prConnSettings->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 + } +#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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryPrivacyFilter(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryPrivacyFilter"); + + ASSERT(prAdapter); + + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(enum ENUM_PARAM_PRIVACY_FILTER); + + if (u4QueryBufferLen < sizeof(enum + ENUM_PARAM_PRIVACY_FILTER)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + *(enum ENUM_PARAM_PRIVACY_FILTER *) pvQueryBuffer = + prAdapter->rWlanInfo.ePrivacyFilter; + +#if DBG + switch (*(enum ENUM_PARAM_PRIVACY_FILTER *) 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", + *(enum ENUM_PARAM_AUTH_MODE *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetPrivacyFilter(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct GLUE_INFO *prGlueInfo; + + DEBUGFUNC("wlanoidSetPrivacyFilter"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + prGlueInfo = prAdapter->prGlueInfo; + + *pu4SetInfoLen = sizeof(enum ENUM_PARAM_PRIVACY_FILTER); + + if (u4SetBufferLen < sizeof(enum ENUM_PARAM_PRIVACY_FILTER)) + 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 (*(enum ENUM_PARAM_PRIVACY_FILTER *) pvSetBuffer >= + PRIVACY_FILTER_NUM) { + DBGLOG(REQ, TRACE, "Invalid privacy filter %d\n", + *(enum ENUM_PARAM_PRIVACY_FILTER *) pvSetBuffer); + return WLAN_STATUS_INVALID_DATA; + } + + switch (*(enum ENUM_PARAM_PRIVACY_FILTER *) pvSetBuffer) { + default: + break; + } + + /* Save the new authentication mode. */ + prAdapter->rWlanInfo.ePrivacyFilter = + *(enum ENUM_PARAM_PRIVACY_FILTER) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetReloadDefaults(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + enum ENUM_PARAM_NETWORK_TYPE eNetworkType; + uint32_t u4Len; + struct mt66xx_chip_info *prChipInfo; + uint16_t cmd_size; + struct CONNECTION_SETTINGS *prConnSettings; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + DEBUGFUNC("wlanoidSetReloadDefaults"); + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + ASSERT(pu4SetInfoLen); + + prConnSettings = + aisGetConnSettings(prAdapter, ucBssIndex); + + *pu4SetInfoLen = sizeof(enum ENUM_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 (*(enum ENUM_RELOAD_DEFAULTS *) pvSetBuffer) { + case ENUM_RELOAD_WEP_KEYS: + /* Reload available default WEP keys from the permanent + * storage. + */ + prConnSettings->eAuthMode = + AUTH_MODE_OPEN; + /* ENUM_ENCRYPTION_DISABLED; */ + prConnSettings->eEncStatus = + ENUM_ENCRYPTION1_KEY_ABSENT; + { + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + struct CMD_802_11_KEY *prCmdKey; + uint8_t aucBCAddr[] = BC_MAC_ADDR; + + prGlueInfo = prAdapter->prGlueInfo; + cmd_size = prChipInfo->u2CmdTxHdrSize + + sizeof(struct CMD_802_11_KEY); + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, cmd_size); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, + "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* compose CMD_802_11_KEY cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->u2InfoBufLen = cmd_size; + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_ADD_REMOVE_KEY; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->u4SetInfoLen = + sizeof(struct PARAM_REMOVE_KEY); + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + + /* Setup WIFI_CMD_T */ + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + prCmdInfo->ucCID, + CMD_PACKET_TYPE_ID, + &prCmdInfo->ucCmdSeqNum, + prCmdInfo->fgSetQuery, + &prCmdKey, FALSE, 0, S2D_INDEX_CMD_H2N); + + kalMemZero((uint8_t *) prCmdKey, + sizeof(struct 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, + (struct QUE_ENTRY *) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; + } + + break; + + default: + DBGLOG(REQ, TRACE, "Invalid reload option %d\n", + *(enum ENUM_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 +uint8_t keyBuffer[sizeof(struct PARAM_KEY) + + 16 /* LEGACY_KEY_MAX_LEN */]; +uint8_t aucBCAddr[] = BC_MAC_ADDR; +#endif +uint32_t +wlanoidSetAddWep(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ +#ifndef LINUX + uint8_t keyBuffer[sizeof(struct PARAM_KEY) + + 16 /* LEGACY_KEY_MAX_LEN */]; + uint8_t aucBCAddr[] = BC_MAC_ADDR; +#endif + struct PARAM_WEP *prNewWepKey; + struct PARAM_KEY *prParamKey = (struct PARAM_KEY *) + keyBuffer; + uint32_t u4KeyId, u4SetLen; + uint8_t ucBssIndex = 0; + + DEBUGFUNC("wlanoidSetAddWep"); + + ASSERT(prAdapter); + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + + DBGLOG(REQ, LOUD, "ucBssIndex %d\n", ucBssIndex); + + *pu4SetInfoLen = OFFSET_OF(struct PARAM_WEP, + aucKeyMaterial); + + if (u4SetBufferLen < OFFSET_OF(struct PARAM_WEP, + 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 = (struct PARAM_WEP *) pvSetBuffer; + + /* Verify the total buffer for minimum length. */ + if (u4SetBufferLen < OFFSET_OF(struct PARAM_WEP, + aucKeyMaterial) + prNewWepKey->u4KeyLength) { + DBGLOG(REQ, WARN, + "Invalid total buffer length (%d) than minimum length (%d)\n", + (uint8_t) u4SetBufferLen, + (uint8_t) OFFSET_OF(struct PARAM_WEP, aucKeyMaterial)); + + *pu4SetInfoLen = OFFSET_OF(struct PARAM_WEP, + 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", + (uint8_t) prNewWepKey->u4Length, + (uint8_t) 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", + (uint8_t) 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", + (uint8_t) 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->ucBssIdx = ucBssIndex; + + if (prParamKey->u4KeyLength == WEP_40_LEN) + prParamKey->ucCipher = CIPHER_SUITE_WEP40; + else if (prParamKey->u4KeyLength == WEP_104_LEN) + prParamKey->ucCipher = CIPHER_SUITE_WEP104; + else if (prParamKey->u4KeyLength == WEP_128_LEN) + prParamKey->ucCipher = CIPHER_SUITE_WEP128; + + prParamKey->u4Length = OFFSET_OF( + struct PARAM_KEY, aucKeyMaterial) + prNewWepKey->u4KeyLength; + + wlanoidSetAddKey(prAdapter, (void *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetRemoveWep(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t u4KeyId, u4SetLen; + struct PARAM_REMOVE_KEY rRemoveKey; + uint8_t aucBCAddr[] = BC_MAC_ADDR; + uint8_t ucBssIndex = 0; + + DEBUGFUNC("wlanoidSetRemoveWep"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + + DBGLOG(REQ, LOUD, "ucBssIndex %d\n", ucBssIndex); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + u4KeyId = *(uint32_t *) pvSetBuffer; + + /* Dump PARAM_WEP content. */ + DBGLOG(REQ, INFO, "Set: Dump PARAM_KEY_INDEX content\n"); + DBGLOG(REQ, INFO, "Index : %u\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: %u\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 %u\n", u4KeyId); + return WLAN_STATUS_INVALID_DATA; + } + + rRemoveKey.u4Length = sizeof(struct PARAM_REMOVE_KEY); + rRemoveKey.u4KeyIndex = *(uint32_t *) pvSetBuffer; + rRemoveKey.ucBssIdx = ucBssIndex; + kalMemCopy(rRemoveKey.arBSSID, aucBCAddr, MAC_ADDR_LEN); + + wlanoidSetRemoveKey(prAdapter, (void *)&rRemoveKey, + sizeof(struct PARAM_REMOVE_KEY), &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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetAddKey(IN struct ADAPTER *prAdapter, IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, OUT uint32_t *pu4SetInfoLen) +{ + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + struct PARAM_KEY *prNewKey; + struct CMD_802_11_KEY *prCmdKey; + struct BSS_INFO *prBssInfo; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecBssInfo; + struct STA_RECORD *prStaRec = NULL; + u_int8_t fgNoHandshakeSec = FALSE; + struct mt66xx_chip_info *prChipInfo; + uint16_t cmd_size; +#if CFG_SUPPORT_TDLS + struct STA_RECORD *prTmpStaRec; +#endif + + DBGLOG_LIMITED(RSN, TRACE, "wlanoidSetAddKey\n"); + DBGLOG(REQ, LOUD, "\n"); + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + prChipInfo = prAdapter->chip_info; + + DBGLOG_LIMITED(RSN, TRACE, "wlanoidSetAddKey\n"); + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(RSN, 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 = (struct PARAM_KEY *) pvSetBuffer; + /* Verify the key structure length. */ + if (prNewKey->u4Length > u4SetBufferLen) { + DBGLOG_LIMITED(RSN, WARN, + "Invalid key structure length (%d) greater than total buffer length (%d)\n", + (uint8_t) prNewKey->u4Length, (uint8_t) u4SetBufferLen); + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_INVALID_LENGTH; + } + /* Verify the key material length for key material buffer */ + if (prNewKey->u4KeyLength > prNewKey->u4Length - + OFFSET_OF(struct PARAM_KEY, aucKeyMaterial)) { + DBGLOG_LIMITED(RSN, WARN, "Invalid key material length (%d)\n", + (uint8_t) 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_LIMITED(RSN, TRACE, + "Set: Dump PARAM_KEY content, Len: 0x%08x, BSSID: " + MACSTR + ", KeyIdx: 0x%08x, KeyLen: 0x%08x, Cipher: %d, Material:\n", + prNewKey->u4Length, MAC2STR(prNewKey->arBSSID), + prNewKey->u4KeyIndex, prNewKey->u4KeyLength, + prNewKey->ucCipher); + DBGLOG_MEM8(RSN, TRACE, prNewKey->aucKeyMaterial, + prNewKey->u4KeyLength); + DBGLOG(RSN, TRACE, "Key RSC:\n"); + DBGLOG_MEM8(RSN, TRACE, &prNewKey->rKeyRSC, sizeof(uint64_t)); + + prGlueInfo = prAdapter->prGlueInfo; + prAisSpecBssInfo = + aisGetAisSpecBssInfo(prAdapter, prNewKey->ucBssIdx); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prNewKey->ucBssIdx); + if (!prBssInfo) { + DBGLOG_LIMITED(REQ, INFO, "BSS Info not exist !!\n"); + return WLAN_STATUS_SUCCESS; + } + /* Tx Rx KeyType addr + * STA, GC: + * case1: 1 1 0 BC addr (no sta record of AP at this moment) WEP, + * notice: tx at default key setting WEP key now save to BSS_INFO + * case2: 0 1 0 BSSID (sta record of AP) RSN BC key + * case3: 1 1 1 AP addr (sta record of AP) RSN STA key + * + * GO: + * case1: 1 1 0 BSSID (no sta record) WEP -- Not support + * case2: 1 0 0 BSSID (no sta record) RSN BC key + * case3: 1 1 1 STA addr STA key + */ + if (prNewKey->ucCipher == CIPHER_SUITE_WEP40 || + prNewKey->ucCipher == CIPHER_SUITE_WEP104 || + prNewKey->ucCipher == CIPHER_SUITE_WEP128) { + /* check if the key no need handshake, then save to bss wep key + * for global usage + */ + fgNoHandshakeSec = TRUE; + } + if (fgNoHandshakeSec) { +#if DBG + if (IS_BSS_AIS(prBssInfo)) { + if (aisGetAuthMode(prAdapter, prNewKey->ucBssIdx) + >= AUTH_MODE_WPA && + aisGetAuthMode(prAdapter, prNewKey->ucBssIdx) != + AUTH_MODE_WPA_NONE) { + DBGLOG_LIMITED(RSN, WARN, + "Set wep at not open/shared setting\n"); + return WLAN_STATUS_SUCCESS; + } + } +#endif + } + if ((prNewKey->u4KeyIndex & IS_UNICAST_KEY) == IS_UNICAST_KEY) { + prStaRec = cnmGetStaRecByAddress(prAdapter, + prBssInfo->ucBssIndex, prNewKey->arBSSID); + if (!prStaRec) { /* Already disconnected ? */ + DBGLOG_LIMITED(REQ, INFO, + "[wlan] Not set the peer key while disconnect\n"); + return WLAN_STATUS_SUCCESS; + } + } + cmd_size = prChipInfo->u2CmdTxHdrSize + sizeof(struct CMD_802_11_KEY); + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, cmd_size); + if (!prCmdInfo) { + DBGLOG_LIMITED(INIT, ERROR, + "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* compose CMD_802_11_KEY cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->u2InfoBufLen = cmd_size; +#if CFG_SUPPORT_REPLAY_DETECTION + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetAddKey; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutSetAddKey; +#else + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; +#endif + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_ADD_REMOVE_KEY; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->u4SetInfoLen = u4SetBufferLen; + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + /* Setup WIFI_CMD_T */ + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + prCmdInfo->ucCID, + CMD_PACKET_TYPE_ID, + &prCmdInfo->ucCmdSeqNum, + prCmdInfo->fgSetQuery, &prCmdKey, FALSE, 0, S2D_INDEX_CMD_H2N); + kalMemZero(prCmdKey, sizeof(struct 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; + /* Copy the addr of the key */ + if ((prNewKey->u4KeyIndex & IS_UNICAST_KEY) == IS_UNICAST_KEY) { + if (prStaRec) { + /* Overwrite the fgNoHandshakeSec in case */ + fgNoHandshakeSec = FALSE; /* Legacy 802.1x wep case ? */ + /* ASSERT(FALSE); */ + } + } else { + if (!IS_BSS_ACTIVE(prBssInfo)) + DBGLOG_LIMITED(REQ, INFO, + "[wlan] BSS info (%d) not active yet!", + prNewKey->ucBssIdx); + } + prCmdKey->ucBssIdx = prBssInfo->ucBssIndex; + prCmdKey->ucKeyId = (uint8_t) (prNewKey->u4KeyIndex & 0xff); + /* Note: the key length may not correct for WPA-None */ + prCmdKey->ucKeyLen = (uint8_t) prNewKey->u4KeyLength; + kalMemCopy(prCmdKey->aucKeyMaterial, + (uint8_t *)prNewKey->aucKeyMaterial, prCmdKey->ucKeyLen); + if (prNewKey->ucCipher) { + prCmdKey->ucAlgorithmId = prNewKey->ucCipher; + if (IS_BSS_AIS(prBssInfo)) { +#if CFG_SUPPORT_802_11W + if (prCmdKey->ucAlgorithmId == CIPHER_SUITE_BIP) { + if (prCmdKey->ucKeyId >= 4) { + struct AIS_SPECIFIC_BSS_INFO + *prAisSpecBssInfo; + + prAisSpecBssInfo = + aisGetAisSpecBssInfo(prAdapter, + prNewKey->ucBssIdx); + prAisSpecBssInfo->fgBipKeyInstalled = + TRUE; + } + } +#endif + if (prCmdKey->ucAlgorithmId == CIPHER_SUITE_TKIP) { + /* Todo:: Support AP mode defragment */ + /* for pairwise key only */ + if ((prNewKey->u4KeyIndex & BITS(30, 31)) == + ((IS_UNICAST_KEY) | (IS_TRANSMIT_KEY))) { + kalMemCopy( + prAisSpecBssInfo->aucRxMicKey, + &prCmdKey->aucKeyMaterial[16], + MIC_KEY_LEN); + kalMemCopy( + prAisSpecBssInfo->aucTxMicKey, + &prCmdKey->aucKeyMaterial[24], + MIC_KEY_LEN); + } + } + } else { +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if ((prCmdKey->ucKeyId >= 4 && prCmdKey->ucKeyId <= 5) + && (prCmdKey->ucAlgorithmId == CIPHER_SUITE_BIP)) { + DBGLOG_LIMITED(RSN, INFO, "AP mode set BIP\n"); + prBssInfo->rApPmfCfg.fgBipKeyInstalled = TRUE; + } +#endif + } + } else { /* Legacy windows NDIS no cipher info */ +#if 0 + 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 (IS_BSS_AIS(prBssInfo)) { +#if CFG_SUPPORT_802_11W + if (prCmdKey->ucKeyId >= 4) { + struct AIS_SPECIFIC_BSS_INFO + *prAisSpecBssInfo; + + prCmdKey->ucAlgorithmId = + CIPHER_SUITE_BIP; + prAisSpecBssInfo = + &prAdapter->rWifiVar + .rAisSpecificBssInfo; + prAisSpecBssInfo + ->fgBipKeyInstalled = + TRUE; + } else +#endif + { + prCmdKey->ucAlgorithmId = CIPHER_SUITE_CCMP; + if (rsnCheckPmkidCandicate(prAdapter)) { + DBGLOG(RSN, TRACE, + "Add key: Prepare a timer to indicate candidate PMKID\n"); + cnmTimerStopTimer(prAdapter, + &prAisSpecBssInfo + ->rPreauthenticationTimer); + cnmTimerStartTimer(prAdapter, + &prAisSpecBssInfo + ->rPreauthenticationTimer, + SEC_TO_MSEC( + WAIT_TIME_IND_PMKID_CANDICATE_SEC)); + } + } + } + } + } else if (prNewKey->u4KeyLength == 32) { + if (IS_BSS_AIS(prBssInfo)) { + if (prAdapter->rWifiVar.rConnSettings.eAuthMode + == AUTH_MODE_WPA_NONE) { + if (prAdapter->rWifiVar.rConnSettings + .eEncStatus == + ENUM_ENCRYPTION2_ENABLED) { + prCmdKey->ucAlgorithmId = + CIPHER_SUITE_TKIP; + } else if (prAdapter->rWifiVar + .rConnSettings.eEncStatus == + ENUM_ENCRYPTION3_ENABLED) { + prCmdKey->ucAlgorithmId = + CIPHER_SUITE_CCMP; + prCmdKey->ucKeyLen = + CCMP_KEY_LEN; + } + } else { + prCmdKey->ucAlgorithmId = + CIPHER_SUITE_TKIP; + kalMemCopy( + prAdapter->rWifiVar + .rAisSpecificBssInfo + .aucRxMicKey, + &prCmdKey->aucKeyMaterial[16], + MIC_KEY_LEN); + kalMemCopy( + prAdapter->rWifiVar + .rAisSpecificBssInfo + .aucTxMicKey, + &prCmdKey->aucKeyMaterial[24], + MIC_KEY_LEN); + if (0 /* Todo::GCMP & GCMP-BIP ? */) { + if (rsnCheckPmkidCandicate(prAdapter)) { + DBGLOG(RSN, TRACE, + "Add key: Prepare a timer to indicate candidate PMKID\n"); + cnmTimerStopTimer(prAdapter, + &prAisSpecBssInfo-> + rPreauthenticationTimer); + cnmTimerStartTimer(prAdapter, + &prAisSpecBssInfo-> + rPreauthenticationTimer, + SEC_TO_MSEC( + WAIT_TIME_IND_PMKID_CANDICATE_SEC)); + } + } else { + prCmdKey->ucAlgorithmId = CIPHER_SUITE_TKIP; + } + } +} +#endif + } + { +#if CFG_SUPPORT_TDLS + prTmpStaRec = cnmGetStaRecByAddress(prAdapter, + prBssInfo->ucBssIndex, prNewKey->arBSSID); + if (prTmpStaRec) { + if (IS_DLS_STA(prTmpStaRec)) { + prStaRec = prTmpStaRec; + + /*128 ,TODO GCMP 256 */ + prCmdKey->ucAlgorithmId = CIPHER_SUITE_CCMP; + + kalMemCopy(prCmdKey->aucPeerAddr, + prStaRec->aucMacAddr, MAC_ADDR_LEN); + } + } +#endif + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if (prCmdKey->ucAlgorithmId == CIPHER_SUITE_BIP) { + if (prCmdKey->ucIsAuthenticator) { + DBGLOG_LIMITED(RSN, INFO, + "Authenticator BIP bssid:%d\n", + prBssInfo->ucBssIndex); + + prCmdKey->ucWlanIndex = + secPrivacySeekForBcEntry(prAdapter, + prBssInfo->ucBssIndex, + prBssInfo->aucOwnMacAddr, + STA_REC_INDEX_NOT_FOUND, + prCmdKey->ucAlgorithmId, + prCmdKey->ucKeyId); + } else { + if (prBssInfo->prStaRecOfAP) { + prCmdKey->ucWlanIndex = + secPrivacySeekForBcEntry(prAdapter, + prBssInfo->ucBssIndex, + prBssInfo->prStaRecOfAP + ->aucMacAddr, + prBssInfo->prStaRecOfAP + ->ucIndex, + prCmdKey->ucAlgorithmId, + prCmdKey->ucKeyId); + } + } + + DBGLOG_LIMITED(RSN, INFO, "BIP BC wtbl index:%d\n", + prCmdKey->ucWlanIndex); + } else +#endif + if (1) { + if (prStaRec) { + if (prCmdKey->ucKeyType) { /* RSN STA */ + struct WLAN_TABLE *prWtbl; + + prWtbl = prAdapter->rWifiVar.arWtbl; + prWtbl[prStaRec->ucWlanIndex].ucKeyId = + prCmdKey->ucKeyId; + prCmdKey->ucWlanIndex = + prStaRec->ucWlanIndex; + + /* wait for CMD Done ? */ + prStaRec->fgTransmitKeyExist = TRUE; + + kalMemCopy(prCmdKey->aucPeerAddr, + prNewKey->arBSSID, + MAC_ADDR_LEN); +#if CFG_SUPPORT_802_11W + /* AP PMF */ + DBGLOG_LIMITED(RSN, INFO, + "Assign client PMF flag = %d\n", + prStaRec->rPmfCfg.fgApplyPmf); + prCmdKey->ucMgmtProtection = + prStaRec->rPmfCfg.fgApplyPmf; +#endif + } else { + ASSERT(FALSE); + } + } else { /* Overwrite the old one for AP and STA WEP */ + if (prBssInfo->prStaRecOfAP) { + DBGLOG_LIMITED(RSN, INFO, "AP REC\n"); + prCmdKey->ucWlanIndex = + secPrivacySeekForBcEntry( + prAdapter, + prBssInfo->ucBssIndex, + prBssInfo->prStaRecOfAP + ->aucMacAddr, + prBssInfo->prStaRecOfAP + ->ucIndex, + prCmdKey->ucAlgorithmId, + prCmdKey->ucKeyId); + kalMemCopy(prCmdKey->aucPeerAddr, + prBssInfo->prStaRecOfAP + ->aucMacAddr, + MAC_ADDR_LEN); + } else { + DBGLOG_LIMITED(RSN, INFO, + "!AP && !STA REC\n"); + prCmdKey->ucWlanIndex = + secPrivacySeekForBcEntry( + prAdapter, + prBssInfo->ucBssIndex, + prBssInfo->aucOwnMacAddr, + STA_REC_INDEX_NOT_FOUND, + prCmdKey->ucAlgorithmId, + prCmdKey->ucKeyId); + kalMemCopy(prCmdKey->aucPeerAddr, + prBssInfo->aucOwnMacAddr, + MAC_ADDR_LEN); + } + if (prCmdKey->ucKeyId >= MAX_KEY_NUM) { + DBGLOG_LIMITED(RSN, ERROR, + "prCmdKey->ucKeyId [%u] overrun\n", + prCmdKey->ucKeyId); + return WLAN_STATUS_FAILURE; + } + if (fgNoHandshakeSec) { + /* WEP: STA and AP */ + prBssInfo->wepkeyWlanIdx = + prCmdKey->ucWlanIndex; + prBssInfo->wepkeyUsed[ + prCmdKey->ucKeyId] = TRUE; + } else if (!prBssInfo->prStaRecOfAP) { + /* AP WPA/RSN */ + prBssInfo->ucBMCWlanIndexS[ + prCmdKey->ucKeyId] = + prCmdKey->ucWlanIndex; + prBssInfo->ucBMCWlanIndexSUsed[ + prCmdKey->ucKeyId] = TRUE; + } else { + /* STA WPA/RSN, should not have tx but + * no sta record + */ + prBssInfo->ucBMCWlanIndexS[ + prCmdKey->ucKeyId] = + prCmdKey->ucWlanIndex; + prBssInfo->ucBMCWlanIndexSUsed[ + prCmdKey->ucKeyId] = TRUE; + DBGLOG_LIMITED(RSN, INFO, + "BMCWlanIndex kid = %d, index = %d\n", + prCmdKey->ucKeyId, + prCmdKey->ucWlanIndex); + } + if (prCmdKey->ucTxKey) { /* */ + prBssInfo->fgBcDefaultKeyExist = TRUE; + prBssInfo->ucBcDefaultKeyIdx = + prCmdKey->ucKeyId; + } + } + } + } +#if 1 + DBGLOG_LIMITED(RSN, INFO, "Add key to wlanIdx %d,BSS=%d," MACSTR + "Tx=%d,type=%d,Auth=%d,cipher=%d,keyid=%d,keylen=%d\n", + prCmdKey->ucWlanIndex, prCmdKey->ucBssIdx, + MAC2STR(prCmdKey->aucPeerAddr), prCmdKey->ucTxKey, + prCmdKey->ucKeyType, prCmdKey->ucIsAuthenticator, + prCmdKey->ucAlgorithmId, prCmdKey->ucKeyId, + prCmdKey->ucKeyLen); + DBGLOG_MEM8(RSN, INFO, prCmdKey->aucKeyMaterial, prCmdKey->ucKeyLen); + if (prCmdKey->ucKeyId < MAX_KEY_NUM) { + DBGLOG_LIMITED(RSN, INFO, "wepkeyUsed=%d,wepkeyWlanIdx=%d\n", + prBssInfo->wepkeyUsed[prCmdKey->ucKeyId], + prBssInfo->wepkeyWlanIdx); + + DBGLOG_LIMITED(RSN, INFO, + "ucBMCWlanIndexSUsed=%d,ucBMCWlanIndexS=%d\n", + prBssInfo->ucBMCWlanIndexSUsed[prCmdKey->ucKeyId], + prBssInfo->ucBMCWlanIndexS[prCmdKey->ucKeyId]); + } +#endif + prAisSpecBssInfo->ucKeyAlgorithmId = prCmdKey->ucAlgorithmId; + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (struct QUE_ENTRY *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetRemoveKey(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + struct PARAM_REMOVE_KEY *prRemovedKey; + struct CMD_802_11_KEY *prCmdKey; + struct WLAN_TABLE *prWlanTable; + struct STA_RECORD *prStaRec = NULL; + struct BSS_INFO *prBssInfo; + /* UINT_8 i = 0; */ + u_int8_t fgRemoveWepKey = FALSE; + uint32_t ucRemoveBCKeyAtIdx = WTBL_RESERVED_ENTRY; + uint32_t u4KeyIndex; + struct mt66xx_chip_info *prChipInfo; + uint16_t cmd_size; + + DEBUGFUNC("wlanoidSetRemoveKey"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + prChipInfo = prAdapter->chip_info; + + *pu4SetInfoLen = sizeof(struct PARAM_REMOVE_KEY); + + if (u4SetBufferLen < sizeof(struct PARAM_REMOVE_KEY)) + 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 = (struct PARAM_REMOVE_KEY *) pvSetBuffer; + + prGlueInfo = prAdapter->prGlueInfo; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prRemovedKey->ucBssIdx); + ASSERT(prBssInfo); + + u4KeyIndex = prRemovedKey->u4KeyIndex & 0x000000FF; +#if CFG_SUPPORT_802_11W + ASSERT(u4KeyIndex < MAX_KEY_NUM + 2); +#else + /* ASSERT(prCmdKey->ucKeyId < MAX_KEY_NUM); */ +#endif + + if (u4KeyIndex >= 4) { + DBGLOG(RSN, INFO, "Remove bip key Index : 0x%08x\n", + u4KeyIndex); + return WLAN_STATUS_SUCCESS; + } + + /* Clean up the Tx key flag */ + if (prRemovedKey->u4KeyIndex & IS_UNICAST_KEY) { + prStaRec = cnmGetStaRecByAddress(prAdapter, + prRemovedKey->ucBssIdx, prRemovedKey->arBSSID); + if (!prStaRec) + return WLAN_STATUS_SUCCESS; + } else { + if (u4KeyIndex == prBssInfo->ucBcDefaultKeyIdx) + prBssInfo->fgBcDefaultKeyExist = FALSE; + } + + if (!prStaRec) { + if (prBssInfo->wepkeyUsed[u4KeyIndex] == TRUE) + fgRemoveWepKey = TRUE; + + if (fgRemoveWepKey) { + DBGLOG(RSN, INFO, "Remove wep key id = %d", u4KeyIndex); + prBssInfo->wepkeyUsed[u4KeyIndex] = FALSE; + if (prBssInfo->fgBcDefaultKeyExist && + prBssInfo->ucBcDefaultKeyIdx == u4KeyIndex) { + prBssInfo->fgBcDefaultKeyExist = FALSE; + prBssInfo->ucBcDefaultKeyIdx = 0xff; + } + ASSERT(prBssInfo->wepkeyWlanIdx < WTBL_SIZE); + ucRemoveBCKeyAtIdx = prBssInfo->wepkeyWlanIdx; + } else { + DBGLOG(RSN, INFO, "Remove group key id = %d", + u4KeyIndex); + + if (prBssInfo->ucBMCWlanIndexSUsed[u4KeyIndex]) { + if (prBssInfo->fgBcDefaultKeyExist && + prBssInfo->ucBcDefaultKeyIdx == + u4KeyIndex) { + prBssInfo->fgBcDefaultKeyExist = FALSE; + prBssInfo->ucBcDefaultKeyIdx = 0xff; + } + if (u4KeyIndex != 0) + ASSERT(prBssInfo->ucBMCWlanIndexS[ + u4KeyIndex] < WTBL_SIZE); + ucRemoveBCKeyAtIdx = + prBssInfo->ucBMCWlanIndexS[u4KeyIndex]; + } + } + + if (ucRemoveBCKeyAtIdx >= WTBL_SIZE) + return WLAN_STATUS_SUCCESS; + } + + cmd_size = prChipInfo->u2CmdTxHdrSize + sizeof(struct CMD_802_11_KEY); + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, cmd_size); + /* Dump PARAM_REMOVE_KEY content. */ + DBGLOG(RSN, INFO, "PARAM_REMOVE_KEY: BSSID(" MACSTR + "), BSS_INDEX (%d), Length(0x%08x), Key Index(0x%08x, %d) ucRemoveBCKeyAtIdx = %d\n", + MAC2STR(prRemovedKey->arBSSID), + prRemovedKey->ucBssIdx, + prRemovedKey->u4Length, prRemovedKey->u4KeyIndex, u4KeyIndex, + ucRemoveBCKeyAtIdx); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prWlanTable = prAdapter->rWifiVar.arWtbl; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prRemovedKey->ucBssIdx); + + /* compose CMD_802_11_KEY cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + /* prCmdInfo->ucBssIndex = prRemovedKey->ucBssIdx; */ + prCmdInfo->u2InfoBufLen = cmd_size; + 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->u4SetInfoLen = sizeof(struct PARAM_REMOVE_KEY); + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + + /* Setup WIFI_CMD_T */ + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + prCmdInfo->ucCID, + CMD_PACKET_TYPE_ID, + &prCmdInfo->ucCmdSeqNum, + prCmdInfo->fgSetQuery, &prCmdKey, FALSE, 0, S2D_INDEX_CMD_H2N); + + kalMemZero((uint8_t *) prCmdKey, + sizeof(struct CMD_802_11_KEY)); + + prCmdKey->ucAddRemove = 0; /* Remove */ + prCmdKey->ucKeyId = (uint8_t) u4KeyIndex; + kalMemCopy(prCmdKey->aucPeerAddr, + (uint8_t *) prRemovedKey->arBSSID, MAC_ADDR_LEN); + prCmdKey->ucBssIdx = prRemovedKey->ucBssIdx; + + if (prStaRec) { + prCmdKey->ucKeyType = 1; + prCmdKey->ucWlanIndex = prStaRec->ucWlanIndex; + prStaRec->fgTransmitKeyExist = FALSE; + } else if (ucRemoveBCKeyAtIdx < WTBL_SIZE) { + prCmdKey->ucWlanIndex = ucRemoveBCKeyAtIdx; + } else { + ASSERT(FALSE); + } + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, + (struct QUE_ENTRY *) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; +} /* wlanoidSetRemoveKey */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set the default key + * + * \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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetDefaultKey(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + struct PARAM_DEFAULT_KEY *prDefaultKey; + struct CMD_DEFAULT_KEY *prCmdDefaultKey; + struct BSS_INFO *prBssInfo; + u_int8_t fgSetWepKey = FALSE; + uint8_t ucWlanIndex = WTBL_RESERVED_ENTRY; + struct mt66xx_chip_info *prChipInfo; + uint16_t cmd_size; + + DEBUGFUNC("wlanoidSetDefaultKey"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + prChipInfo = prAdapter->chip_info; + + 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; + } + + prDefaultKey = (struct PARAM_DEFAULT_KEY *) pvSetBuffer; + + *pu4SetInfoLen = u4SetBufferLen; + + /* Dump PARAM_DEFAULT_KEY_T content. */ + DBGLOG(RSN, INFO, + "ucBssIndex %d, Key Index : %d, Unicast Key : %d, Multicast Key : %d\n", + prDefaultKey->ucBssIdx, + prDefaultKey->ucKeyID, prDefaultKey->ucUnicast, + prDefaultKey->ucMulticast); + + /* prWlanTable = prAdapter->rWifiVar.arWtbl; */ + prGlueInfo = prAdapter->prGlueInfo; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prDefaultKey->ucBssIdx); + + DBGLOG(RSN, INFO, "WlanIdx = %d\n", + prBssInfo->wepkeyWlanIdx); + + if (prDefaultKey->ucMulticast) { + ASSERT(prBssInfo); + if (prBssInfo->prStaRecOfAP) { /* Actually GC not have wep */ + if (prBssInfo->wepkeyUsed[prDefaultKey->ucKeyID]) { + prBssInfo->ucBcDefaultKeyIdx = + prDefaultKey->ucKeyID; + prBssInfo->fgBcDefaultKeyExist = TRUE; + ucWlanIndex = prBssInfo->wepkeyWlanIdx; + } else { + if (prDefaultKey->ucUnicast) { + DBGLOG(RSN, ERROR, + "Set STA Unicast default key"); + return WLAN_STATUS_SUCCESS; + } + ASSERT(FALSE); + } + } else { /* For AP mode only */ + + if (prBssInfo->wepkeyUsed[prDefaultKey->ucKeyID] + == TRUE) + fgSetWepKey = TRUE; + + if (fgSetWepKey) { + ucWlanIndex = prBssInfo->wepkeyWlanIdx; + } else { + if (!prBssInfo->ucBMCWlanIndexSUsed[ + prDefaultKey->ucKeyID]) { + DBGLOG(RSN, ERROR, + "Set AP wep default but key not exist!"); + return WLAN_STATUS_SUCCESS; + } + ucWlanIndex = prBssInfo->ucBMCWlanIndexS[ + prDefaultKey->ucKeyID]; + } + prBssInfo->ucBcDefaultKeyIdx = prDefaultKey->ucKeyID; + prBssInfo->fgBcDefaultKeyExist = TRUE; + } + if (ucWlanIndex > WTBL_SIZE) { + DBGLOG(RSN, ERROR, "ucWlanIndex = %d, wepUsed = %d\n", + ucWlanIndex, + prBssInfo->wepkeyUsed[prDefaultKey->ucKeyID]); + return WLAN_STATUS_FAILURE; + } + + } else { + DBGLOG(RSN, ERROR, + "Check the case set unicast default key!"); + ASSERT(FALSE); + } + + cmd_size = prChipInfo->u2CmdTxHdrSize + sizeof(struct CMD_DEFAULT_KEY); + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, cmd_size); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* compose CMD_802_11_KEY cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->u2InfoBufLen = cmd_size; + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_DEFAULT_KEY_ID; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->u4SetInfoLen = u4SetBufferLen; + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + + /* Setup WIFI_CMD_T */ + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + prCmdInfo->ucCID, + CMD_PACKET_TYPE_ID, + &prCmdInfo->ucCmdSeqNum, + prCmdInfo->fgSetQuery, + &prCmdDefaultKey, FALSE, 0, S2D_INDEX_CMD_H2N); + kalMemZero(prCmdDefaultKey, sizeof(struct CMD_DEFAULT_KEY)); + + prCmdDefaultKey->ucBssIdx = prDefaultKey->ucBssIdx; + prCmdDefaultKey->ucKeyId = prDefaultKey->ucKeyID; + prCmdDefaultKey->ucWlanIndex = ucWlanIndex; + prCmdDefaultKey->ucMulticast = prDefaultKey->ucMulticast; + + DBGLOG(RSN, INFO, + "CMD_ID_DEFAULT_KEY_ID (%d) with wlan idx = %d\n", + prDefaultKey->ucKeyID, ucWlanIndex); + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, + (struct QUE_ENTRY *) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; +} /* wlanoidSetDefaultKey */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryEncryptionStatus(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + u_int8_t fgTransmitKeyAvailable = TRUE; + enum ENUM_WEP_STATUS eEncStatus = 0; + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_INFO *prAisBssInfo; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + DEBUGFUNC("wlanoidQueryEncryptionStatus"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + prConnSettings = + aisGetConnSettings(prAdapter, ucBssIndex); + prAisBssInfo = + aisGetAisBssInfo(prAdapter, ucBssIndex); + + *pu4QueryInfoLen = sizeof(enum ENUM_WEP_STATUS); + + fgTransmitKeyAvailable = + prAisBssInfo->fgBcDefaultKeyExist; + + switch (prConnSettings->eEncStatus) { + case ENUM_ENCRYPTION4_ENABLED: + if (fgTransmitKeyAvailable) + eEncStatus = ENUM_ENCRYPTION4_ENABLED; + else + eEncStatus = ENUM_ENCRYPTION4_KEY_ABSENT; + break; + + case ENUM_ENCRYPTION3_ENABLED: + if (fgTransmitKeyAvailable) + eEncStatus = ENUM_ENCRYPTION3_ENABLED; + else + eEncStatus = ENUM_ENCRYPTION3_KEY_ABSENT; + break; + + case ENUM_ENCRYPTION2_ENABLED: + if (fgTransmitKeyAvailable) { + eEncStatus = ENUM_ENCRYPTION2_ENABLED; + break; + } + eEncStatus = ENUM_ENCRYPTION2_KEY_ABSENT; + break; + + case ENUM_ENCRYPTION1_ENABLED: + if (fgTransmitKeyAvailable) + eEncStatus = ENUM_ENCRYPTION1_ENABLED; + else + eEncStatus = ENUM_ENCRYPTION1_KEY_ABSENT; + break; + + case ENUM_ENCRYPTION_DISABLED: + eEncStatus = ENUM_ENCRYPTION_DISABLED; + break; + + default: + DBGLOG(REQ, ERROR, "Unknown Encryption Status Setting:%d\n", + prConnSettings->eEncStatus); + } + +#if DBG + DBGLOG(REQ, INFO, + "Encryption status: %d Return:%d\n", + prConnSettings->eEncStatus, eEncStatus); +#endif + + *(enum ENUM_WEP_STATUS *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetEncryptionStatus(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct GLUE_INFO *prGlueInfo; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + enum ENUM_WEP_STATUS eEewEncrypt; + struct CONNECTION_SETTINGS *prConnSettings; + uint8_t ucBssIndex = 0; + + DEBUGFUNC("wlanoidSetEncryptionStatus"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prGlueInfo = prAdapter->prGlueInfo; + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + + DBGLOG(REQ, LOUD, "ucBssIndex %d\n", ucBssIndex); + + prConnSettings = + aisGetConnSettings(prAdapter, ucBssIndex); + + *pu4SetInfoLen = sizeof(enum ENUM_WEP_STATUS); + + /* 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 = *(enum ENUM_WEP_STATUS *) pvSetBuffer; + DBGLOG(REQ, INFO, "ENCRYPTION_STATUS %d\n", eEewEncrypt); + + switch (eEewEncrypt) { + case ENUM_ENCRYPTION_DISABLED: /* Disable WEP, TKIP, AES */ + DBGLOG(RSN, INFO, "Disable Encryption\n"); + secSetCipherSuite(prAdapter, + CIPHER_FLAG_WEP40 | CIPHER_FLAG_WEP104 | + CIPHER_FLAG_WEP128, + ucBssIndex); + break; + + case ENUM_ENCRYPTION1_ENABLED: /* Enable WEP. Disable TKIP, AES */ + DBGLOG(RSN, INFO, "Enable Encryption1\n"); + secSetCipherSuite(prAdapter, + CIPHER_FLAG_WEP40 | CIPHER_FLAG_WEP104 | + CIPHER_FLAG_WEP128, + ucBssIndex); + break; + + case ENUM_ENCRYPTION2_ENABLED: /* Enable WEP, TKIP. Disable AES */ + secSetCipherSuite(prAdapter, + CIPHER_FLAG_WEP40 | CIPHER_FLAG_WEP104 | + CIPHER_FLAG_WEP128 | CIPHER_FLAG_TKIP, + ucBssIndex); + DBGLOG(RSN, INFO, "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, + ucBssIndex); + DBGLOG(RSN, INFO, "Enable Encryption3\n"); + break; + + case ENUM_ENCRYPTION4_ENABLED: /* Eanble GCMP256 */ + secSetCipherSuite(prAdapter, + CIPHER_FLAG_CCMP | CIPHER_FLAG_GCMP256, + ucBssIndex); + DBGLOG(RSN, INFO, "Enable Encryption4\n"); + break; + + default: + DBGLOG(RSN, INFO, "Unacceptible encryption status: %d\n", + *(enum ENUM_WEP_STATUS *) pvSetBuffer); + + rStatus = WLAN_STATUS_NOT_SUPPORTED; + } + + if (rStatus == WLAN_STATUS_SUCCESS) { + /* Save the new encryption status. */ + prConnSettings->eEncStatus = * + (enum ENUM_WEP_STATUS *) pvSetBuffer; + } + + return rStatus; +} /* wlanoidSetEncryptionStatus */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryCapability(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_CAPABILITY *prCap; + struct PARAM_AUTH_ENCRYPTION + *prAuthenticationEncryptionSupported; + + DEBUGFUNC("wlanoidQueryCapability"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = 4 * sizeof(uint32_t) + 14 * sizeof( + struct PARAM_AUTH_ENCRYPTION); + + if (u4QueryBufferLen < *pu4QueryInfoLen) + return WLAN_STATUS_INVALID_LENGTH; + + prCap = (struct PARAM_CAPABILITY *) pvQueryBuffer; + + prCap->u4Length = *pu4QueryInfoLen; + prCap->u4Version = 2; /* WPA2 */ + prCap->u4NoOfAuthEncryptPairsSupported = 15; + + 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; + + prAuthenticationEncryptionSupported[14].eAuthModeSupported + = AUTH_MODE_WPA2_PSK; + prAuthenticationEncryptionSupported[14].eEncryptStatusSupported + = ENUM_ENCRYPTION4_ENABLED; + + return WLAN_STATUS_SUCCESS; + +} /* wlanoidQueryCapability */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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 status + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetPmkid(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct PARAM_PMKID *prPmkid; + + DBGLOG(REQ, INFO, "wlanoidSetPmkid\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = u4SetBufferLen; + prPmkid = (struct PARAM_PMKID *) pvSetBuffer; + if (u4SetBufferLen < sizeof(struct PARAM_PMKID)) + return WLAN_STATUS_INVALID_DATA; + return rsnSetPmkid(prAdapter, prPmkid); +} /* wlanoidSetPmkid */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to delete the PMKID in the PMK cache. + * + * \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 status + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidDelPmkid(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct PARAM_PMKID *prPmkid; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = u4SetBufferLen; + prPmkid = (struct PARAM_PMKID *) pvSetBuffer; + + if (u4SetBufferLen < sizeof(struct PARAM_PMKID)) + return WLAN_STATUS_INVALID_DATA; + return rsnDelPmkid(prAdapter, prPmkid); +} /* wlanoidDelPmkid */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to delete all the PMKIDs in the PMK cache. + * + * \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 status + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidFlushPmkid(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint8_t ucBssIndex = 0; + + ASSERT(prAdapter); + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + + return rsnFlushPmkid(prAdapter, ucBssIndex); +} /* wlanoidFlushPmkid */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQuerySupportedRates(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint8_t eRate[PARAM_MAX_LEN_RATES] = { + /* 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(uint8_t) * + PARAM_MAX_LEN_RATES_EX); + + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + kalMemCopy(pvQueryBuffer, (void *) &eRate, + (sizeof(uint8_t) * PARAM_MAX_LEN_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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryDesiredRates(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + DEBUGFUNC("wlanoidQueryDesiredRates"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = (sizeof(uint8_t) * + PARAM_MAX_LEN_RATES_EX); + + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + kalMemCopy(pvQueryBuffer, + (void *) &(prAdapter->rWlanInfo.eDesiredRates), + (sizeof(uint8_t) * PARAM_MAX_LEN_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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetDesiredRates(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t i; + + DEBUGFUNC("wlanoidSetDesiredRates"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < (sizeof(uint8_t) * + PARAM_MAX_LEN_RATES)) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = (sizeof(uint8_t) * PARAM_MAX_LEN_RATES); + + if (u4SetBufferLen < (sizeof(uint8_t) * + PARAM_MAX_LEN_RATES)) + return WLAN_STATUS_INVALID_LENGTH; + + kalMemCopy((void *) &(prAdapter->rWlanInfo.eDesiredRates), + pvSetBuffer, (sizeof(uint8_t) * PARAM_MAX_LEN_RATES)); + + prAdapter->rWlanInfo.eLinkAttr.ucDesiredRateLen = + PARAM_MAX_LEN_RATES; + for (i = 0; i < PARAM_MAX_LEN_RATES; i++) + prAdapter->rWlanInfo.eLinkAttr.u2DesiredRate[i] = + (uint16_t) (prAdapter->rWlanInfo.eDesiredRates[i]); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_LINK_ATTRIB, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_LINK_ATTRIB), + (uint8_t *) &(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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryMaxFrameSize(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + DEBUGFUNC("wlanoidQueryMaxFrameSize"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(uint32_t)) { + *pu4QueryInfoLen = sizeof(uint32_t); + return WLAN_STATUS_INVALID_LENGTH; + } + + *(uint32_t *) pvQueryBuffer = ETHERNET_MAX_PKT_SZ - + ETHERNET_HEADER_SZ; + *pu4QueryInfoLen = sizeof(uint32_t); + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryMaxTotalSize(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + DEBUGFUNC("wlanoidQueryMaxTotalSize"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(uint32_t)) { + *pu4QueryInfoLen = sizeof(uint32_t); + return WLAN_STATUS_INVALID_LENGTH; + } + + *(uint32_t *) pvQueryBuffer = ETHERNET_MAX_PKT_SZ; + *pu4QueryInfoLen = sizeof(uint32_t); + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryVendorId(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { +#if DBG + uint8_t *cp; +#endif + DEBUGFUNC("wlanoidQueryVendorId"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(uint32_t)) { + *pu4QueryInfoLen = sizeof(uint32_t); + return WLAN_STATUS_INVALID_LENGTH; + } + + kalMemCopy(pvQueryBuffer, prAdapter->aucMacAddress, 3); + *((uint8_t *) pvQueryBuffer + 3) = 1; + *pu4QueryInfoLen = sizeof(uint32_t); + +#if DBG + cp = (uint8_t *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryRssi(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + struct PARAM_LINK_SPEED_EX *prLinkSpeed; + struct LINK_SPEED_EX_ *prLq; + + DEBUGFUNC("wlanoidQueryRssi"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) + return WLAN_STATUS_NOT_SUPPORTED; + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (prAdapter->fgIsEnableLpdvt) + return WLAN_STATUS_NOT_SUPPORTED; + + *pu4QueryInfoLen = sizeof(struct PARAM_LINK_SPEED_EX); + prLq = &prAdapter->rLinkQuality.rLq[ucBssIndex]; + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(REQ, WARN, "Too short length %u\n", + u4QueryBufferLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo, + ucBssIndex) == + MEDIA_STATE_DISCONNECTED) { + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (prLq->fgIsLinkQualityValid == TRUE && + (kalGetTimeTick() - prLq->rLinkQualityUpdateTime) <= + CFG_LINK_QUALITY_VALID_PERIOD) { + prLinkSpeed = (struct PARAM_LINK_SPEED_EX *) pvQueryBuffer; + + prLinkSpeed->rLq[ucBssIndex]. + u2LinkSpeed = prLq->u2LinkSpeed * 5000; + prLinkSpeed->rLq[ucBssIndex].cRssi = prLq->cRssi; + + DBGLOG(REQ, TRACE, "ucBssIdx = %d, rate = %u, signal = %d\n", + ucBssIndex, + prLinkSpeed->rLq[ucBssIndex].u2LinkSpeed, + prLinkSpeed->rLq[ucBssIndex].cRssi); + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryRssiTrigger(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *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(int32_t); + + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(REQ, WARN, "Too short length %u\n", + u4QueryBufferLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + *(int32_t *) pvQueryBuffer = + prAdapter->rWlanInfo.rRssiTriggerValue; + DBGLOG(REQ, INFO, "RSSI trigger: %d dBm\n", + *(int32_t *) 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 + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetRssiTrigger(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + int32_t rRssiTriggerValue; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + DEBUGFUNC("wlanoidSetRssiTrigger"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(int32_t); + rRssiTriggerValue = *(int32_t *) 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 == (int32_t) ( + prAdapter->rLinkQuality.rLq[ucBssIndex].cRssi)) { + prAdapter->rWlanInfo.eRssiTriggerType = + ENUM_RSSI_TRIGGER_TRIGGERED; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (void *) &prAdapter->rWlanInfo.rRssiTriggerValue, + sizeof(int32_t), + ucBssIndex); + } else if (rRssiTriggerValue < (int32_t) ( + prAdapter->rLinkQuality.rLq[ucBssIndex].cRssi)) + prAdapter->rWlanInfo.eRssiTriggerType = + ENUM_RSSI_TRIGGER_GREATER; + else if (rRssiTriggerValue > (int32_t) ( + prAdapter->rLinkQuality.rLq[ucBssIndex].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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetCurrentLookahead(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + DEBUGFUNC("wlanoidSetCurrentLookahead"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(uint32_t)) { + *pu4SetInfoLen = sizeof(uint32_t); + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = sizeof(uint32_t); + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetCurrentLookahead */ + +/*----------------------------------------------------------------------------*/ +/*! \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryStatistics(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + DEBUGFUNC("wlanoidQueryStatistics"); + DBGLOG(REQ, LOUD, "\n"); + + return wlanQueryStatistics(prAdapter, pvQueryBuffer, u4QueryBufferLen, + pu4QueryInfoLen, TRUE); +} /* wlanoidQueryStatistics */ + +uint32_t +wlanoidQueryBugReport(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + DEBUGFUNC("wlanoidQueryBugReport"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(struct EVENT_BUG_REPORT); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(uint32_t); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(struct + EVENT_BUG_REPORT)) { + DBGLOG(OID, WARN, "Too short length %u\n", + u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_BUG_REPORT, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryBugReport, + nicOidCmdTimeoutCommon, + 0, NULL, pvQueryBuffer, u4QueryBufferLen); +} /* wlanoidQueryBugReport */ + +/*----------------------------------------------------------------------------*/ +/*! \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryMediaStreamMode(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + DEBUGFUNC("wlanoidQueryMediaStreamMode"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(enum ENUM_MEDIA_STREAM_MODE); + + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + *(enum 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetMediaStreamMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + enum ENUM_MEDIA_STREAM_MODE eStreamMode; + + DEBUGFUNC("wlanoidSetMediaStreamMode"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(enum ENUM_MEDIA_STREAM_MODE)) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = sizeof(enum ENUM_MEDIA_STREAM_MODE); + + eStreamMode = *(enum 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(struct CMD_LINK_ATTRIB), + (uint8_t *) &(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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryPermanentAddr(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryCurrentAddr(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + 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; + + COPY_MAC_ADDR(pvQueryBuffer, + prAdapter->rWifiVar.aucMacAddress); + *pu4QueryInfoLen = MAC_ADDR_LEN; + + return WLAN_STATUS_SUCCESS; +} /* 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 + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryLinkSpeed(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + DEBUGFUNC("wlanoidQueryLinkSpeed"); + + return wlanQueryLinkSpeed(prAdapter, pvQueryBuffer, u4QueryBufferLen, + pu4QueryInfoLen, TRUE); +} + +uint32_t +wlanQueryLinkSpeed(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen, IN uint8_t fgIsOid) +{ + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + struct LINK_SPEED_EX_ *prLq; + + DEBUGFUNC("wlanQueryLinkSpeed"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (prAdapter->fgIsEnableLpdvt) + return WLAN_STATUS_NOT_SUPPORTED; + + *pu4QueryInfoLen = sizeof(uint32_t); + + if (u4QueryBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + prLq = &prAdapter->rLinkQuality.rLq[ucBssIndex]; + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo, + ucBssIndex) != + MEDIA_STATE_CONNECTED) { + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (prLq->fgIsLinkRateValid == TRUE && + (kalGetTimeTick() - prLq->rLinkRateUpdateTime) <= + CFG_LINK_QUALITY_VALID_PERIOD) { + /* change to unit of 100bps */ + *(uint32_t *) pvQueryBuffer = + prLq->u2LinkSpeed * 5000; + return WLAN_STATUS_SUCCESS; + } else { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + fgIsOid, + nicCmdEventQueryLinkSpeed, + nicOidCmdTimeoutCommon, 0, NULL, + pvQueryBuffer, u4QueryBufferLen); + } +} /* end of wlanoidQueryLinkSpeed() */ + +uint32_t +wlanoidQueryLinkSpeedEx(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + OS_SYSTIME rUpdateDeltaTime; + struct PARAM_LINK_SPEED_EX *pu4LinkSpeed; + struct LINK_SPEED_EX_ *prLq; + DEBUGFUNC("wlanoidQueryLinkSpeedEx"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (prAdapter->fgIsEnableLpdvt) + return WLAN_STATUS_NOT_SUPPORTED; + + *pu4QueryInfoLen = sizeof(struct PARAM_LINK_SPEED_EX); + + if (u4QueryBufferLen < sizeof(struct PARAM_LINK_SPEED_EX)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + prLq = &prAdapter->rLinkQuality.rLq[ucBssIndex]; + rUpdateDeltaTime = kalGetTimeTick() - prLq->rLinkRateUpdateTime; + if (IS_BSS_INDEX_AIS(prAdapter, ucBssIndex) && + prLq->fgIsLinkRateValid == TRUE && + rUpdateDeltaTime <= CFG_LQ_MONITOR_FREQUENCY) { + pu4LinkSpeed = (struct PARAM_LINK_SPEED_EX *) (pvQueryBuffer); + pu4LinkSpeed->rLq[ucBssIndex].cRssi = prLq->cRssi; + pu4LinkSpeed->rLq[ucBssIndex].u2LinkSpeed = prLq->u2LinkSpeed; + + /* change to unit of 100bps */ + pu4LinkSpeed->rLq[ucBssIndex].u2LinkSpeed *= 5000; + return WLAN_STATUS_SUCCESS; + } else { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryLinkSpeedEx, + nicOidCmdTimeoutCommon, 0, NULL, + pvQueryBuffer, u4QueryBufferLen); + } +} + +#if defined(CFG_REPORT_MAX_TX_RATE) && (CFG_REPORT_MAX_TX_RATE == 1) +uint32_t +wlanoidQueryMaxLinkSpeed(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + uint32_t u4CurRate = 0, u4MaxRate = 0; + uint32_t rv = WLAN_STATUS_FAILURE; + uint8_t ucBssIndex; + struct STA_RECORD *prStaRecOfAP; + struct BSS_INFO *prBssInfo; + struct PARAM_LINK_SPEED_EX *prLinkSpeed; + + DEBUGFUNC("wlanoidQueryMaxLinkSpeed"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (prAdapter->fgIsEnableLpdvt) + return WLAN_STATUS_NOT_SUPPORTED; + + *pu4QueryInfoLen = sizeof(uint32_t); + + if (u4QueryBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + prStaRecOfAP = aisGetStaRecOfAP(prAdapter, ucBssIndex); + prBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + prLinkSpeed = (struct PARAM_LINK_SPEED_EX *)pvQueryBuffer; + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo, ucBssIndex) != + MEDIA_STATE_CONNECTED || prStaRecOfAP == NULL) { + rv = WLAN_STATUS_ADAPTER_NOT_READY; + } else { + if (wlanGetMaxTxRate(prAdapter, prBssInfo, prStaRecOfAP, + &u4CurRate, &u4MaxRate) >= 0) { + u4MaxRate = u4MaxRate * 1000; + prLinkSpeed->rLq[ucBssIndex].u2LinkSpeed = u4MaxRate; + rv = WLAN_STATUS_SUCCESS; + } + } + return rv; +} +#endif /* CFG_REPORT_MAX_TX_RATE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief extend command packet generation utility +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] ucCID Command ID +* \param[in] ucExtCID Extend 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 +*/ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanSendSetQueryExtCmd( + struct ADAPTER *prAdapter, + uint8_t ucCID, + uint8_t ucExtCID, + u_int8_t fgSetQuery, + u_int8_t fgNeedResp, + u_int8_t fgIsOid, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + uint32_t u4SetQueryInfoLen, + uint8_t *pucInfoBuffer, + void *pvSetQueryBuffer, + uint32_t u4SetQueryBufferLen) +{ + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + uint8_t *pucCmdBuf; + struct mt66xx_chip_info *prChipInfo; + uint16_t cmd_size; + + prGlueInfo = prAdapter->prGlueInfo; + prChipInfo = prAdapter->chip_info; + cmd_size = prChipInfo->u2CmdTxHdrSize + u4SetQueryInfoLen; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, cmd_size); + + DEBUGFUNC("wlanSendSetQueryCmd"); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T FAILED ID[0x%x]\n", + ucCID); + return WLAN_STATUS_FAILURE; + } + + /* Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->u2InfoBufLen = cmd_size; + prCmdInfo->pfCmdDoneHandler = pfCmdDoneHandler; + prCmdInfo->pfCmdTimeoutHandler = pfCmdTimeoutHandler; + prCmdInfo->fgIsOid = fgIsOid; + prCmdInfo->ucCID = ucCID; + prCmdInfo->fgSetQuery = fgSetQuery; + prCmdInfo->fgNeedResp = fgNeedResp; + prCmdInfo->u4SetInfoLen = u4SetQueryInfoLen; + prCmdInfo->pvInformationBuffer = pvSetQueryBuffer; + prCmdInfo->u4InformationBufferLength = u4SetQueryBufferLen; + + /* Setup WIFI_CMD_T (no payload) */ + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + prCmdInfo->ucCID, + CMD_PACKET_TYPE_ID, + &prCmdInfo->ucCmdSeqNum, + prCmdInfo->fgSetQuery, + &pucCmdBuf, FALSE, ucExtCID, S2D_INDEX_CMD_H2N); + if (u4SetQueryInfoLen > 0 && pucInfoBuffer != NULL) + kalMemCopy(pucCmdBuf, pucInfoBuffer, u4SetQueryInfoLen); + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (struct QUE_ENTRY *) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + return WLAN_STATUS_PENDING; +} + +#if CFG_SUPPORT_QA_TOOL +#if CFG_SUPPORT_BUFFER_MODE +uint32_t +wlanoidSetEfusBufferMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE + *prSetEfuseBufModeInfo; + struct CMD_EFUSE_BUFFER_MODE *prCmdSetEfuseBufModeInfo = + NULL; + PFN_CMD_DONE_HANDLER pfCmdDoneHandler; + uint32_t u4EfuseContentSize, u4QueryInfoLen; + u_int8_t fgSetQuery, fgNeedResp; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidSetEfusBufferMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + /* get the buffer mode info */ + prSetEfuseBufModeInfo = + (struct PARAM_CUSTOM_EFUSE_BUFFER_MODE *) pvSetBuffer; + + /* copy command header */ + prCmdSetEfuseBufModeInfo = (struct CMD_EFUSE_BUFFER_MODE *) + kalMemAlloc(sizeof(struct CMD_EFUSE_BUFFER_MODE), + VIR_MEM_TYPE); + if (prCmdSetEfuseBufModeInfo == NULL) + return WLAN_STATUS_FAILURE; + kalMemZero(prCmdSetEfuseBufModeInfo, + sizeof(struct CMD_EFUSE_BUFFER_MODE)); + prCmdSetEfuseBufModeInfo->ucSourceMode = + prSetEfuseBufModeInfo->ucSourceMode; + prCmdSetEfuseBufModeInfo->ucCount = + prSetEfuseBufModeInfo->ucCount; + prCmdSetEfuseBufModeInfo->ucCmdType = + prSetEfuseBufModeInfo->ucCmdType; + prCmdSetEfuseBufModeInfo->ucReserved = + prSetEfuseBufModeInfo->ucReserved; + + /* decide content size and SetQuery / NeedResp flag */ + if (prAdapter->fgIsSupportBufferBinSize16Byte == TRUE) { + u4EfuseContentSize = sizeof(struct BIN_CONTENT) * + EFUSE_CONTENT_SIZE; + pfCmdDoneHandler = nicCmdEventSetCommon; + fgSetQuery = TRUE; + fgNeedResp = FALSE; + } else { +#if (CFG_FW_Report_Efuse_Address == 1) + u4EfuseContentSize = (prAdapter->u4EfuseEndAddress) - + (prAdapter->u4EfuseStartAddress) + 1; +#else + u4EfuseContentSize = EFUSE_CONTENT_BUFFER_SIZE; +#endif + pfCmdDoneHandler = NULL; + fgSetQuery = FALSE; + fgNeedResp = TRUE; + } + + u4QueryInfoLen = OFFSET_OF(struct CMD_EFUSE_BUFFER_MODE, + aBinContent) + u4EfuseContentSize; + + if (u4SetBufferLen < u4QueryInfoLen) { + kalMemFree(prCmdSetEfuseBufModeInfo, VIR_MEM_TYPE, + sizeof(struct CMD_EFUSE_BUFFER_MODE)); + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = u4QueryInfoLen; + kalMemCopy(prCmdSetEfuseBufModeInfo->aBinContent, + prSetEfuseBufModeInfo->aBinContent, + u4EfuseContentSize); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_EFUSE_BUFFER_MODE, + fgSetQuery, + fgNeedResp, + TRUE, + pfCmdDoneHandler, + nicOidCmdTimeoutCommon, + u4QueryInfoLen, + (uint8_t *) (prCmdSetEfuseBufModeInfo), + pvSetBuffer, u4SetBufferLen); + + kalMemFree(prCmdSetEfuseBufModeInfo, VIR_MEM_TYPE, + sizeof(struct CMD_EFUSE_BUFFER_MODE)); + + return rWlanStatus; +} + +uint32_t +wlanoidConnacSetEfusBufferMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE_CONNAC_T + *prSetEfuseBufModeInfo; + struct CMD_EFUSE_BUFFER_MODE_CONNAC_T + *prCmdSetEfuseBufModeInfo = NULL; + uint32_t u4EfuseContentSize, u4QueryInfoLen; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidSetEfusBufferMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + DBGLOG(OID, INFO, "u4SetBufferLen = %d\n", u4SetBufferLen); + /* get the buffer mode info */ + prSetEfuseBufModeInfo = + (struct PARAM_CUSTOM_EFUSE_BUFFER_MODE_CONNAC_T *) pvSetBuffer; + + /* copy command header */ + prCmdSetEfuseBufModeInfo = (struct CMD_EFUSE_BUFFER_MODE_CONNAC_T *) + kalMemAlloc(sizeof(struct CMD_EFUSE_BUFFER_MODE_CONNAC_T), + VIR_MEM_TYPE); + if (prCmdSetEfuseBufModeInfo == NULL) + return WLAN_STATUS_FAILURE; + kalMemZero(prCmdSetEfuseBufModeInfo, + sizeof(struct CMD_EFUSE_BUFFER_MODE_CONNAC_T)); + prCmdSetEfuseBufModeInfo->ucSourceMode = + prSetEfuseBufModeInfo->ucSourceMode; + prCmdSetEfuseBufModeInfo->ucContentFormat = + prSetEfuseBufModeInfo->ucContentFormat; + prCmdSetEfuseBufModeInfo->u2Count = + prSetEfuseBufModeInfo->u2Count; + + u4EfuseContentSize = prCmdSetEfuseBufModeInfo->u2Count; + + u4QueryInfoLen = OFFSET_OF(struct + CMD_EFUSE_BUFFER_MODE_CONNAC_T, + aBinContent) + u4EfuseContentSize; + + if (u4SetBufferLen < u4QueryInfoLen) { + kalMemFree(prCmdSetEfuseBufModeInfo, VIR_MEM_TYPE, + sizeof(struct CMD_EFUSE_BUFFER_MODE_CONNAC_T)); + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = u4QueryInfoLen; + kalMemCopy(prCmdSetEfuseBufModeInfo->aBinContent, + prSetEfuseBufModeInfo->aBinContent, + u4EfuseContentSize); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_EFUSE_BUFFER_MODE, + FALSE, + TRUE, + TRUE, + NULL, + nicOidCmdTimeoutCommon, + u4QueryInfoLen, + (uint8_t *) (prCmdSetEfuseBufModeInfo), + pvSetBuffer, u4SetBufferLen); + + kalMemFree(prCmdSetEfuseBufModeInfo, VIR_MEM_TYPE, + sizeof(struct CMD_EFUSE_BUFFER_MODE_CONNAC_T)); + + return rWlanStatus; +} + +/*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to read efuse content. + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryProcessAccessEfuseRead(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_ACCESS_EFUSE *prSetAccessEfuseInfo; + struct CMD_ACCESS_EFUSE rCmdSetAccessEfuse; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryProcessAccessEfuseRead"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_ACCESS_EFUSE)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prSetAccessEfuseInfo = (struct PARAM_CUSTOM_ACCESS_EFUSE *) + pvSetBuffer; + + kalMemSet(&rCmdSetAccessEfuse, 0, + sizeof(struct CMD_ACCESS_EFUSE)); + + rCmdSetAccessEfuse.u4Address = + prSetAccessEfuseInfo->u4Address; + rCmdSetAccessEfuse.u4Valid = prSetAccessEfuseInfo->u4Valid; + + + DBGLOG(INIT, INFO, + "MT6632 : wlanoidQueryProcessAccessEfuseRead, address=%d\n", + rCmdSetAccessEfuse.u4Address); + + kalMemCopy(rCmdSetAccessEfuse.aucData, + prSetAccessEfuseInfo->aucData, + sizeof(uint8_t) * 16); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_EFUSE_ACCESS, + FALSE, /* Query Bit: True->write False->read */ + TRUE, + TRUE, + NULL, /* No Tx done function wait until fw ack */ + nicOidCmdTimeoutCommon, + sizeof(struct CMD_ACCESS_EFUSE), + (uint8_t *) (&rCmdSetAccessEfuse), pvSetBuffer, + u4SetBufferLen); + + return rWlanStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to write efuse content. + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryProcessAccessEfuseWrite(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_ACCESS_EFUSE *prSetAccessEfuseInfo; + struct CMD_ACCESS_EFUSE rCmdSetAccessEfuse; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryProcessAccessEfuseWrite"); + DBGLOG(INIT, INFO, + "MT6632 : wlanoidQueryProcessAccessEfuseWrite\n"); + + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_ACCESS_EFUSE)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prSetAccessEfuseInfo = (struct PARAM_CUSTOM_ACCESS_EFUSE *) + pvSetBuffer; + + kalMemSet(&rCmdSetAccessEfuse, 0, + sizeof(struct CMD_ACCESS_EFUSE)); + + rCmdSetAccessEfuse.u4Address = + prSetAccessEfuseInfo->u4Address; + rCmdSetAccessEfuse.u4Valid = prSetAccessEfuseInfo->u4Valid; + + DBGLOG(INIT, INFO, + "MT6632 : wlanoidQueryProcessAccessEfuseWrite, address=%d\n", + rCmdSetAccessEfuse.u4Address); + + + kalMemCopy(rCmdSetAccessEfuse.aucData, + prSetAccessEfuseInfo->aucData, + sizeof(uint8_t) * 16); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_EFUSE_ACCESS, + TRUE, /* Query Bit: True->write False->read*/ + TRUE, + TRUE, + NULL, /* No Tx done function wait until fw ack */ + nicOidCmdTimeoutCommon, + sizeof(struct CMD_ACCESS_EFUSE), + (uint8_t *) (&rCmdSetAccessEfuse), pvSetBuffer, + u4SetBufferLen); + + return rWlanStatus; +} + + + + +uint32_t +wlanoidQueryEfuseFreeBlock(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_EFUSE_FREE_BLOCK + *prGetEfuseFreeBlockInfo; + struct CMD_EFUSE_FREE_BLOCK rCmdGetEfuseFreeBlock; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryEfuseFreeBlock"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct + PARAM_CUSTOM_EFUSE_FREE_BLOCK); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_EFUSE_FREE_BLOCK)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prGetEfuseFreeBlockInfo = (struct + PARAM_CUSTOM_EFUSE_FREE_BLOCK *) pvSetBuffer; + + kalMemSet(&rCmdGetEfuseFreeBlock, 0, + sizeof(struct CMD_EFUSE_FREE_BLOCK)); + + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_EFUSE_FREE_BLOCK, + FALSE, /* Query Bit: True->write False->read */ + TRUE, + TRUE, + NULL, /* No Tx done function wait until fw ack */ + nicOidCmdTimeoutCommon, + sizeof(struct CMD_EFUSE_FREE_BLOCK), + (uint8_t *) (&rCmdGetEfuseFreeBlock), pvSetBuffer, + u4SetBufferLen); + + return rWlanStatus; +} + +uint32_t +wlanoidQueryGetTxPower(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_GET_TX_POWER *prGetTxPowerInfo; + struct CMD_GET_TX_POWER rCmdGetTxPower; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryGetTxPower"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CUSTOM_GET_TX_POWER *); + + if (u4SetBufferLen < sizeof(struct PARAM_CUSTOM_GET_TX_POWER + *)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prGetTxPowerInfo = (struct PARAM_CUSTOM_GET_TX_POWER *) + pvSetBuffer; + + kalMemSet(&rCmdGetTxPower, 0, + sizeof(struct CMD_GET_TX_POWER)); + + rCmdGetTxPower.ucTxPwrType = EXT_EVENT_TARGET_TX_POWER; + rCmdGetTxPower.ucCenterChannel = + prGetTxPowerInfo->ucCenterChannel; + rCmdGetTxPower.ucDbdcIdx = prGetTxPowerInfo->ucDbdcIdx; + rCmdGetTxPower.ucBand = prGetTxPowerInfo->ucBand; + + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_GET_TX_POWER, + FALSE, /* Query Bit: True->write False->read*/ + TRUE, + TRUE, + NULL, /* No Tx done function wait until fw ack */ + nicOidCmdTimeoutCommon, + sizeof(struct CMD_GET_TX_POWER), + (uint8_t *) (&rCmdGetTxPower), + pvSetBuffer, u4SetBufferLen); + + return rWlanStatus; +} + + +/*#endif*/ + +#endif /* CFG_SUPPORT_BUFFER_MODE */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to query RX statistics. + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryRxStatistics(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_CUSTOM_ACCESS_RX_STAT *prRxStatistics; + struct CMD_ACCESS_RX_STAT *prCmdAccessRxStat; + struct CMD_ACCESS_RX_STAT rCmdAccessRxStat; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + /* UINT_32 u4MemSize = PARAM_MEM_DUMP_MAX_SIZE; */ + uint32_t u4SeqNum = 0; + uint32_t u4TotalNum = 0; + + prCmdAccessRxStat = &rCmdAccessRxStat; + + DEBUGFUNC("wlanoidQueryRxStatistics"); + DBGLOG(INIT, LOUD, "\n"); + + DBGLOG(INIT, ERROR, "MT6632 : wlanoidQueryRxStatistics\n"); + + prRxStatistics = (struct PARAM_CUSTOM_ACCESS_RX_STAT *) + pvQueryBuffer; + + *pu4QueryInfoLen = 8 + prRxStatistics->u4TotalNum; + + u4SeqNum = prRxStatistics->u4SeqNum; + u4TotalNum = prRxStatistics->u4TotalNum; + + do { + prCmdAccessRxStat->u4SeqNum = u4SeqNum; + prCmdAccessRxStat->u4TotalNum = u4TotalNum; + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_RX_STAT, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryRxStatistics, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_ACCESS_RX_STAT), + (uint8_t *) prCmdAccessRxStat, pvQueryBuffer, + u4QueryBufferLen); + } while (FALSE); + + return rStatus; +} + +#if CFG_SUPPORT_TX_BF + +uint32_t +wlanoidStaRecUpdate(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct CMD_STAREC_UPDATE *prStaRecUpdateInfo; + struct STAREC_COMMON *prStaRecCmm; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidStaRecUpdate"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct STAREC_COMMON); + if (u4SetBufferLen < sizeof(struct STAREC_COMMON)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prStaRecUpdateInfo = + (struct CMD_STAREC_UPDATE *) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, (CMD_STAREC_UPDATE_HDR_SIZE + + u4SetBufferLen)); + if (!prStaRecUpdateInfo) { + DBGLOG(INIT, ERROR, + "Allocate P_CMD_DEV_INFO_UPDATE_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* fix me: configurable ucBssIndex */ + prStaRecCmm = (struct STAREC_COMMON *) pvSetBuffer; + prStaRecUpdateInfo->ucBssIndex = 0; + prStaRecUpdateInfo->ucWlanIdx = prStaRecCmm->u2Reserve1; + prStaRecUpdateInfo->u2TotalElementNum = 1; + kalMemCopy(prStaRecUpdateInfo->aucBuffer, pvSetBuffer, + u4SetBufferLen); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_STAREC_UPDATE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + (CMD_STAREC_UPDATE_HDR_SIZE + u4SetBufferLen), + (uint8_t *) prStaRecUpdateInfo, NULL, 0); + + cnmMemFree(prAdapter, prStaRecUpdateInfo); + + return rWlanStatus; +} + +uint32_t +wlanoidStaRecBFUpdate(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct CMD_STAREC_UPDATE *prStaRecUpdateInfo; + struct CMD_STAREC_BF *prStaRecBF; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidStaRecBFUpdate"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct CMD_STAREC_BF); + if (u4SetBufferLen < sizeof(struct CMD_STAREC_BF)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prStaRecUpdateInfo = + (struct CMD_STAREC_UPDATE *) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, (CMD_STAREC_UPDATE_HDR_SIZE + + u4SetBufferLen)); + if (!prStaRecUpdateInfo) { + DBGLOG(INIT, ERROR, + "Allocate P_CMD_DEV_INFO_UPDATE_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* fix me: configurable ucBssIndex */ + prStaRecBF = (struct CMD_STAREC_BF *) pvSetBuffer; + prStaRecUpdateInfo->ucBssIndex = prStaRecBF->ucReserved[0]; + prStaRecUpdateInfo->ucWlanIdx = prStaRecBF->ucReserved[1]; + prStaRecUpdateInfo->u2TotalElementNum = 1; + kalMemCopy(prStaRecUpdateInfo->aucBuffer, pvSetBuffer, + u4SetBufferLen); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_STAREC_UPDATE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + (CMD_STAREC_UPDATE_HDR_SIZE + u4SetBufferLen), + (uint8_t *) prStaRecUpdateInfo, NULL, 0); + + cnmMemFree(prAdapter, prStaRecUpdateInfo); + + return rWlanStatus; +} + +uint32_t +wlanoidBssInfoBasic(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct CMD_BSS_INFO_UPDATE *prBssInfoUpdateBasic; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct BSSINFO_BASIC *prBssinfoBasic = NULL; + + DEBUGFUNC("wlanoidManualAssoc"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct BSSINFO_BASIC); + if (u4SetBufferLen < sizeof(struct BSSINFO_BASIC)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prBssInfoUpdateBasic = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + (CMD_BSSINFO_UPDATE_HDR_SIZE + u4SetBufferLen)); + if (!prBssInfoUpdateBasic) { + DBGLOG(INIT, ERROR, + "Allocate P_CMD_DEV_INFO_UPDATE_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + if (pvSetBuffer == NULL) { + prBssInfoUpdateBasic->ucBssIndex = 0; + DBGLOG(RFTEST, INFO, + "prBssInfoUpdateBasic->ucBssIndex=0(default)\n"); + } else { + prBssinfoBasic = + (struct BSSINFO_BASIC *)(pvSetBuffer); + prBssInfoUpdateBasic->ucBssIndex = + prBssinfoBasic->ucBcMcWlanidx; + DBGLOG(RFTEST, INFO, + "prBssInfoUpdateBasic->ucBssIndex =%d\n", + prBssInfoUpdateBasic->ucBssIndex); + } + prBssInfoUpdateBasic->u2TotalElementNum = 1; + kalMemCopy(prBssInfoUpdateBasic->aucBuffer, pvSetBuffer, + u4SetBufferLen); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_BSSINFO_UPDATE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + (CMD_BSSINFO_UPDATE_HDR_SIZE + u4SetBufferLen), + (uint8_t *) prBssInfoUpdateBasic, NULL, 0); + + cnmMemFree(prAdapter, prBssInfoUpdateBasic); + + return rWlanStatus; +} + +uint32_t +wlanoidDevInfoActive(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct CMD_DEV_INFO_UPDATE *prDevInfoUpdateActive; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct CMD_DEVINFO_ACTIVE *prCmdDevinfoActive = NULL; + + DEBUGFUNC("wlanoidManualAssoc"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct CMD_DEVINFO_ACTIVE); + if (u4SetBufferLen < sizeof(struct CMD_DEVINFO_ACTIVE)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prDevInfoUpdateActive = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + (CMD_DEVINFO_UPDATE_HDR_SIZE + u4SetBufferLen)); + if (!prDevInfoUpdateActive) { + DBGLOG(INIT, ERROR, + "Allocate P_CMD_DEV_INFO_UPDATE_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* fix me: configurable ucOwnMacIdx */ + if (pvSetBuffer == NULL) { + prDevInfoUpdateActive->ucOwnMacIdx = 0; + DBGLOG(RFTEST, INFO, + "prDevInfoUpdateActive->ucOwnMacIdx = 0(default)\n"); + } else { + prCmdDevinfoActive = + (struct CMD_DEVINFO_ACTIVE *)pvSetBuffer; + prDevInfoUpdateActive->ucOwnMacIdx = + prCmdDevinfoActive->aucReserve[0]; + DBGLOG(RFTEST, INFO, + "prDevInfoUpdateActive->ucOwnMacIdx = %d\n", + prDevInfoUpdateActive->ucOwnMacIdx); + } + prDevInfoUpdateActive->ucAppendCmdTLV = 0; + prDevInfoUpdateActive->u2TotalElementNum = 1; + kalMemCopy(prDevInfoUpdateActive->aucBuffer, pvSetBuffer, + u4SetBufferLen); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_DEVINFO_UPDATE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + (CMD_DEVINFO_UPDATE_HDR_SIZE + u4SetBufferLen), + (uint8_t *) prDevInfoUpdateActive, NULL, 0); + + cnmMemFree(prAdapter, prDevInfoUpdateActive); + + return rWlanStatus; +} + +uint32_t +wlanoidManualAssoc(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct CMD_STAREC_UPDATE *prStaRecManualAssoc; + struct CMD_MANUAL_ASSOC_STRUCT *prManualAssoc; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidManualAssoc"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct CMD_STAREC_UPDATE); + if (u4SetBufferLen < sizeof(struct CMD_STAREC_UPDATE)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prStaRecManualAssoc = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + (CMD_STAREC_UPDATE_HDR_SIZE + u4SetBufferLen)); + if (!prStaRecManualAssoc) { + DBGLOG(INIT, ERROR, + "Allocate P_CMD_STAREC_UPDATE_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prManualAssoc = (struct CMD_MANUAL_ASSOC_STRUCT *) + pvSetBuffer; + prStaRecManualAssoc->ucWlanIdx = prManualAssoc->ucWtbl; + prStaRecManualAssoc->ucBssIndex = prManualAssoc->ucOwnmac; + prStaRecManualAssoc->u2TotalElementNum = 1; + kalMemCopy(prStaRecManualAssoc->aucBuffer, pvSetBuffer, + u4SetBufferLen); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_STAREC_UPDATE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + (CMD_STAREC_UPDATE_HDR_SIZE + u4SetBufferLen), + (uint8_t *) prStaRecManualAssoc, NULL, 0); + + cnmMemFree(prAdapter, prStaRecManualAssoc); + + return rWlanStatus; +} + +struct TXBF_CMD_DONE_HANDLER { + uint32_t u4TxBfCmdId; + void (*pFunc)(struct ADAPTER *, struct CMD_INFO *, + uint8_t *); +}; + +struct TXBF_CMD_DONE_HANDLER rTxBfCmdDoneHandler[] = { + {BF_SOUNDING_OFF, nicCmdEventSetCommon}, + {BF_SOUNDING_ON, nicCmdEventSetCommon}, + {BF_DATA_PACKET_APPLY, nicCmdEventSetCommon}, + {BF_PFMU_MEM_ALLOCATE, nicCmdEventSetCommon}, + {BF_PFMU_MEM_RELEASE, nicCmdEventSetCommon}, + {BF_PFMU_TAG_READ, nicCmdEventPfmuTagRead}, + {BF_PFMU_TAG_WRITE, nicCmdEventSetCommon}, + {BF_PROFILE_READ, nicCmdEventPfmuDataRead}, + {BF_PROFILE_WRITE, nicCmdEventSetCommon}, + {BF_PN_READ, nicCmdEventSetCommon}, + {BF_PN_WRITE, nicCmdEventSetCommon}, + {BF_PFMU_MEM_ALLOC_MAP_READ, nicCmdEventSetCommon}, +#if CFG_SUPPORT_TX_BF_FPGA + {BF_PFMU_SW_TAG_WRITE, nicCmdEventSetCommon} +#endif +}; + +uint32_t +wlanoidTxBfAction(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + union PARAM_CUSTOM_TXBF_ACTION_STRUCT *prTxBfActionInfo; + union CMD_TXBF_ACTION rCmdTxBfActionInfo; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + u_int8_t fgSetQuery, fgNeedResp; + uint32_t u4TxBfCmdId; + uint8_t ucIdx; + + DEBUGFUNC("wlanoidTxBfAction"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(union + PARAM_CUSTOM_TXBF_ACTION_STRUCT); + + if (u4SetBufferLen < sizeof(union + PARAM_CUSTOM_TXBF_ACTION_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prTxBfActionInfo = (union PARAM_CUSTOM_TXBF_ACTION_STRUCT *) + pvSetBuffer; + + memcpy(&rCmdTxBfActionInfo, prTxBfActionInfo, + sizeof(union CMD_TXBF_ACTION)); + + u4TxBfCmdId = + rCmdTxBfActionInfo.rProfileTagRead.ucTxBfCategory; + if (TXBF_CMD_NEED_TO_RESPONSE(u4TxBfCmdId) == + 0) { /* don't need response */ + fgSetQuery = TRUE; + fgNeedResp = FALSE; + } else { + fgSetQuery = FALSE; + fgNeedResp = TRUE; + } + + for (ucIdx = 0; ucIdx < ARRAY_SIZE(rTxBfCmdDoneHandler); + ucIdx++) { + if (u4TxBfCmdId == rTxBfCmdDoneHandler[ucIdx].u4TxBfCmdId) + break; + } + + if (ucIdx == ARRAY_SIZE(rTxBfCmdDoneHandler)) { + DBGLOG(RFTEST, ERROR, + "ucIdx [%d] overrun of rTxBfCmdDoneHandler\n", ucIdx); + return WLAN_STATUS_NOT_SUPPORTED; + } + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_BF_ACTION, + fgSetQuery, + fgNeedResp, + TRUE, + rTxBfCmdDoneHandler[ucIdx].pFunc, + nicOidCmdTimeoutCommon, + sizeof(union CMD_TXBF_ACTION), + (uint8_t *) &rCmdTxBfActionInfo, + pvSetBuffer, + u4SetBufferLen); + + return rWlanStatus; +} + +#if CFG_SUPPORT_MU_MIMO +uint32_t +wlanoidMuMimoAction(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT + *prMuMimoActionInfo; + union CMD_MUMIMO_ACTION rCmdMuMimoActionInfo; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + u_int8_t fgSetQuery, fgNeedResp; + uint32_t u4MuMimoCmdId; + void (*pFunc)(struct ADAPTER *, struct CMD_INFO *, + uint8_t *); + + DEBUGFUNC("wlanoidMuMimoAction"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prMuMimoActionInfo = (struct + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT *) pvSetBuffer; + + memcpy(&rCmdMuMimoActionInfo, prMuMimoActionInfo, + sizeof(union CMD_MUMIMO_ACTION)); + + u4MuMimoCmdId = rCmdMuMimoActionInfo.ucMuMimoCategory; + if (MU_CMD_NEED_TO_RESPONSE(u4MuMimoCmdId) == 0) { + fgSetQuery = TRUE; + fgNeedResp = FALSE; + } else { + fgSetQuery = FALSE; + fgNeedResp = TRUE; + } + + pFunc = nicCmdEventSetCommon; + if (u4MuMimoCmdId == MU_HQA_GET_QD) + pFunc = nicCmdEventGetQd; + else if (u4MuMimoCmdId == MU_HQA_GET_CALC_LQ) + pFunc = nicCmdEventGetCalcLq; + else if (u4MuMimoCmdId == MU_GET_CALC_INIT_MCS) + pFunc = nicCmdEventGetCalcInitMcs; + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_MU_CTRL, + fgSetQuery, + fgNeedResp, + TRUE, + pFunc, + nicOidCmdTimeoutCommon, + sizeof(union CMD_MUMIMO_ACTION), + (uint8_t *) &rCmdMuMimoActionInfo, + pvSetBuffer, + u4SetBufferLen); + + return rWlanStatus; +} +#endif /* CFG_SUPPORT_MU_MIMO */ +#endif /* CFG_SUPPORT_TX_BF */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Trigger FW Cal for Backup Cal Data to Host + * Side. + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetCalBackup(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct PARAM_CAL_BACKUP_STRUCT_V2 *prCalBackupDataV2Info; + + DBGLOG(RFTEST, INFO, "%s\n", __func__); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CAL_BACKUP_STRUCT_V2); + + if (u4SetBufferLen < sizeof(struct + PARAM_CAL_BACKUP_STRUCT_V2)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prCalBackupDataV2Info = (struct PARAM_CAL_BACKUP_STRUCT_V2 + *) pvSetBuffer; + + if (prCalBackupDataV2Info->ucReason == 1 + && prCalBackupDataV2Info->ucAction == 2) { + /* Trigger All Cal Function */ + return wlanoidSendCalBackupV2Cmd(prAdapter, pvSetBuffer, + u4SetBufferLen); + } else if (prCalBackupDataV2Info->ucReason == 4 + && prCalBackupDataV2Info->ucAction == 6) { + /* For Debug Use, Tell FW Print Cal Data (Rom or Ram) */ + return wlanoidSendCalBackupV2Cmd(prAdapter, pvSetBuffer, + u4SetBufferLen); + } else if (prCalBackupDataV2Info->ucReason == 3 + && prCalBackupDataV2Info->ucAction == 5) { + /* Send Cal Data to FW */ + if (prCalBackupDataV2Info->ucRomRam == 0) + prCalBackupDataV2Info->u4RemainLength = + g_rBackupCalDataAllV2.u4ValidRomCalDataLength; + else if (prCalBackupDataV2Info->ucRomRam == 1) + prCalBackupDataV2Info->u4RemainLength = + g_rBackupCalDataAllV2.u4ValidRamCalDataLength; + + return wlanoidSendCalBackupV2Cmd(prAdapter, pvSetBuffer, + u4SetBufferLen); + } + + return rWlanStatus; +} + +uint32_t wlanoidSendCalBackupV2Cmd(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen) { + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct PARAM_CAL_BACKUP_STRUCT_V2 *prCalBackupDataV2Info; + struct CMD_CAL_BACKUP_STRUCT_V2 *prCmdCalBackupDataV2; + uint8_t ucReason, ucAction, ucNeedResp, ucFragNum, ucRomRam; + uint32_t u4DumpMaxSize = PARAM_CAL_DATA_DUMP_MAX_SIZE; + uint32_t u4RemainLength, u4CurrAddr, u4CurrLen; + + DBGLOG(RFTEST, INFO, "%s\n", __func__); + + prCmdCalBackupDataV2 = (struct CMD_CAL_BACKUP_STRUCT_V2 *) + kalMemAlloc(sizeof(struct CMD_CAL_BACKUP_STRUCT_V2), + VIR_MEM_TYPE); + + prCalBackupDataV2Info = (struct PARAM_CAL_BACKUP_STRUCT_V2 *) + pvQueryBuffer; + + ucReason = prCalBackupDataV2Info->ucReason; + ucAction = prCalBackupDataV2Info->ucAction; + ucNeedResp = prCalBackupDataV2Info->ucNeedResp; + ucRomRam = prCalBackupDataV2Info->ucRomRam; + + if (ucAction == 2) { + /* Trigger All Cal Function */ + prCmdCalBackupDataV2->ucReason = ucReason; + prCmdCalBackupDataV2->ucAction = ucAction; + prCmdCalBackupDataV2->ucNeedResp = ucNeedResp; + prCmdCalBackupDataV2->ucFragNum = + prCalBackupDataV2Info->ucFragNum; + prCmdCalBackupDataV2->ucRomRam = ucRomRam; + prCmdCalBackupDataV2->u4ThermalValue = + prCalBackupDataV2Info->u4ThermalValue; + prCmdCalBackupDataV2->u4Address = + prCalBackupDataV2Info->u4Address; + prCmdCalBackupDataV2->u4Length = + prCalBackupDataV2Info->u4Length; + prCmdCalBackupDataV2->u4RemainLength = + prCalBackupDataV2Info->u4RemainLength; +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST_DBGLOG + DBGLOG(RFTEST, INFO, + "=========== Driver Send Query CMD#0 or CMD#1 (Info) ===========\n"); + DBGLOG(RFTEST, INFO, "Reason = %d\n", + prCmdCalBackupDataV2->ucReason); + DBGLOG(RFTEST, INFO, "Action = %d\n", + prCmdCalBackupDataV2->ucAction); + DBGLOG(RFTEST, INFO, "NeedResp = %d\n", + prCmdCalBackupDataV2->ucNeedResp); + DBGLOG(RFTEST, INFO, "FragNum = %d\n", + prCmdCalBackupDataV2->ucFragNum); + DBGLOG(RFTEST, INFO, "RomRam = %d\n", + prCmdCalBackupDataV2->ucRomRam); + DBGLOG(RFTEST, INFO, "ThermalValue = %d\n", + prCmdCalBackupDataV2->u4ThermalValue); + DBGLOG(RFTEST, INFO, "Address = 0x%08x\n", + prCmdCalBackupDataV2->u4Address); + DBGLOG(RFTEST, INFO, "Length = %d\n", + prCmdCalBackupDataV2->u4Length); + DBGLOG(RFTEST, INFO, "RemainLength = %d\n", + prCmdCalBackupDataV2->u4RemainLength); + DBGLOG(RFTEST, INFO, + "================================================================\n"); +#endif + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_CAL_BACKUP_IN_HOST_V2, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + NULL, + sizeof(struct CMD_CAL_BACKUP_STRUCT_V2), + (uint8_t *) prCmdCalBackupDataV2, + pvQueryBuffer, + u4QueryBufferLen); + + kalMemFree(prCmdCalBackupDataV2, VIR_MEM_TYPE, + sizeof(struct CMD_CAL_BACKUP_STRUCT_V2)); + } else if (ucAction == 0 || ucAction == 1 + || ucAction == 6) { + /* Query CMD#0 and CMD#1. */ + /* For Thermal Value and Total Cal Data Length. */ + prCmdCalBackupDataV2->ucReason = ucReason; + prCmdCalBackupDataV2->ucAction = ucAction; + prCmdCalBackupDataV2->ucNeedResp = ucNeedResp; + prCmdCalBackupDataV2->ucFragNum = + prCalBackupDataV2Info->ucFragNum; + prCmdCalBackupDataV2->ucRomRam = ucRomRam; + prCmdCalBackupDataV2->u4ThermalValue = + prCalBackupDataV2Info->u4ThermalValue; + prCmdCalBackupDataV2->u4Address = + prCalBackupDataV2Info->u4Address; + prCmdCalBackupDataV2->u4Length = + prCalBackupDataV2Info->u4Length; + prCmdCalBackupDataV2->u4RemainLength = + prCalBackupDataV2Info->u4RemainLength; +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST_DBGLOG + DBGLOG(RFTEST, INFO, + "=========== Driver Send Query CMD#0 or CMD#1 (Info) ===========\n"); + DBGLOG(RFTEST, INFO, "Reason = %d\n", + prCmdCalBackupDataV2->ucReason); + DBGLOG(RFTEST, INFO, "Action = %d\n", + prCmdCalBackupDataV2->ucAction); + DBGLOG(RFTEST, INFO, "NeedResp = %d\n", + prCmdCalBackupDataV2->ucNeedResp); + DBGLOG(RFTEST, INFO, "FragNum = %d\n", + prCmdCalBackupDataV2->ucFragNum); + DBGLOG(RFTEST, INFO, "RomRam = %d\n", + prCmdCalBackupDataV2->ucRomRam); + DBGLOG(RFTEST, INFO, "ThermalValue = %d\n", + prCmdCalBackupDataV2->u4ThermalValue); + DBGLOG(RFTEST, INFO, "Address = 0x%08x\n", + prCmdCalBackupDataV2->u4Address); + DBGLOG(RFTEST, INFO, "Length = %d\n", + prCmdCalBackupDataV2->u4Length); + DBGLOG(RFTEST, INFO, "RemainLength = %d\n", + prCmdCalBackupDataV2->u4RemainLength); + DBGLOG(RFTEST, INFO, + "================================================================\n"); +#endif + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_CAL_BACKUP_IN_HOST_V2, + FALSE, + TRUE, + FALSE, + nicCmdEventQueryCalBackupV2, + NULL, + sizeof(struct CMD_CAL_BACKUP_STRUCT_V2), + (uint8_t *) prCmdCalBackupDataV2, + pvQueryBuffer, + u4QueryBufferLen); + + kalMemFree(prCmdCalBackupDataV2, VIR_MEM_TYPE, + sizeof(struct CMD_CAL_BACKUP_STRUCT_V2)); + } else if (ucAction == 4) { + /* Query All Cal Data from FW (Rom or Ram). */ + u4RemainLength = prCalBackupDataV2Info->u4RemainLength; + u4CurrAddr = prCalBackupDataV2Info->u4Address + + prCalBackupDataV2Info->u4Length; + ucFragNum = prCalBackupDataV2Info->ucFragNum + 1; + + if (u4RemainLength > u4DumpMaxSize) { + u4CurrLen = u4DumpMaxSize; + u4RemainLength -= u4DumpMaxSize; + } else { + u4CurrLen = u4RemainLength; + u4RemainLength = 0; + } + + prCmdCalBackupDataV2->ucReason = ucReason; + prCmdCalBackupDataV2->ucAction = ucAction; + prCmdCalBackupDataV2->ucNeedResp = ucNeedResp; + prCmdCalBackupDataV2->ucFragNum = ucFragNum; + prCmdCalBackupDataV2->ucRomRam = ucRomRam; + prCmdCalBackupDataV2->u4ThermalValue = + prCalBackupDataV2Info->u4ThermalValue; + prCmdCalBackupDataV2->u4Address = u4CurrAddr; + prCmdCalBackupDataV2->u4Length = u4CurrLen; + prCmdCalBackupDataV2->u4RemainLength = u4RemainLength; +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST_DBGLOG + DBGLOG(RFTEST, INFO, + "========= Driver Send Query All Cal Data from FW (Info) =========\n"); + DBGLOG(RFTEST, INFO, "Reason = %d\n", + prCmdCalBackupDataV2->ucReason); + DBGLOG(RFTEST, INFO, "Action = %d\n", + prCmdCalBackupDataV2->ucAction); + DBGLOG(RFTEST, INFO, "NeedResp = %d\n", + prCmdCalBackupDataV2->ucNeedResp); + DBGLOG(RFTEST, INFO, "FragNum = %d\n", + prCmdCalBackupDataV2->ucFragNum); + DBGLOG(RFTEST, INFO, "RomRam = %d\n", + prCmdCalBackupDataV2->ucRomRam); + DBGLOG(RFTEST, INFO, "ThermalValue = %d\n", + prCmdCalBackupDataV2->u4ThermalValue); + DBGLOG(RFTEST, INFO, "Address = 0x%08x\n", + prCmdCalBackupDataV2->u4Address); + DBGLOG(RFTEST, INFO, "Length = %d\n", + prCmdCalBackupDataV2->u4Length); + DBGLOG(RFTEST, INFO, "RemainLength = %d\n", + prCmdCalBackupDataV2->u4RemainLength); + DBGLOG(RFTEST, INFO, + "=================================================================\n"); +#endif + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_CAL_BACKUP_IN_HOST_V2, + FALSE, + TRUE, + FALSE, + nicCmdEventQueryCalBackupV2, + NULL, + sizeof(struct CMD_CAL_BACKUP_STRUCT_V2), + (uint8_t *) prCmdCalBackupDataV2, + pvQueryBuffer, + u4QueryBufferLen); + + kalMemFree(prCmdCalBackupDataV2, VIR_MEM_TYPE, + sizeof(struct CMD_CAL_BACKUP_STRUCT_V2)); + } else if (ucAction == 5) { + /* Send All Cal Data to FW (Rom or Ram). */ + u4RemainLength = prCalBackupDataV2Info->u4RemainLength; + u4CurrAddr = prCalBackupDataV2Info->u4Address + + prCalBackupDataV2Info->u4Length; + ucFragNum = prCalBackupDataV2Info->ucFragNum + 1; + + if (u4RemainLength > u4DumpMaxSize) { + u4CurrLen = u4DumpMaxSize; + u4RemainLength -= u4DumpMaxSize; + } else { + u4CurrLen = u4RemainLength; + u4RemainLength = 0; + } + + prCmdCalBackupDataV2->ucReason = ucReason; + prCmdCalBackupDataV2->ucAction = ucAction; + prCmdCalBackupDataV2->ucNeedResp = ucNeedResp; + prCmdCalBackupDataV2->ucFragNum = ucFragNum; + prCmdCalBackupDataV2->ucRomRam = ucRomRam; + prCmdCalBackupDataV2->u4ThermalValue = + prCalBackupDataV2Info->u4ThermalValue; + prCmdCalBackupDataV2->u4Address = u4CurrAddr; + prCmdCalBackupDataV2->u4Length = u4CurrLen; + prCmdCalBackupDataV2->u4RemainLength = u4RemainLength; +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST_DBGLOG + DBGLOG(RFTEST, INFO, + "========= Driver Send All Cal Data to FW (Info) =========\n"); + DBGLOG(RFTEST, INFO, "Reason = %d\n", + prCmdCalBackupDataV2->ucReason); + DBGLOG(RFTEST, INFO, "Action = %d\n", + prCmdCalBackupDataV2->ucAction); + DBGLOG(RFTEST, INFO, "NeedResp = %d\n", + prCmdCalBackupDataV2->ucNeedResp); + DBGLOG(RFTEST, INFO, "FragNum = %d\n", + prCmdCalBackupDataV2->ucFragNum); + DBGLOG(RFTEST, INFO, "RomRam = %d\n", + prCmdCalBackupDataV2->ucRomRam); + DBGLOG(RFTEST, INFO, "ThermalValue = %d\n", + prCmdCalBackupDataV2->u4ThermalValue); + DBGLOG(RFTEST, INFO, "Address = 0x%08x\n", + prCmdCalBackupDataV2->u4Address); + DBGLOG(RFTEST, INFO, "Length = %d\n", + prCmdCalBackupDataV2->u4Length); + DBGLOG(RFTEST, INFO, "RemainLength = %d\n", + prCmdCalBackupDataV2->u4RemainLength); +#endif + /* Copy Cal Data From Driver to FW */ + if (prCmdCalBackupDataV2->ucRomRam == 0) + kalMemCopy( + (uint8_t *)(prCmdCalBackupDataV2->au4Buffer), + (uint8_t *)(g_rBackupCalDataAllV2.au4RomCalData) + + prCmdCalBackupDataV2->u4Address, + prCmdCalBackupDataV2->u4Length); + else if (prCmdCalBackupDataV2->ucRomRam == 1) + kalMemCopy( + (uint8_t *)(prCmdCalBackupDataV2->au4Buffer), + (uint8_t *)(g_rBackupCalDataAllV2.au4RamCalData) + + prCmdCalBackupDataV2->u4Address, + prCmdCalBackupDataV2->u4Length); +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST_DBGLOG + DBGLOG(RFTEST, INFO, + "Check some of elements (0x%08x), (0x%08x), (0x%08x), (0x%08x), (0x%08x)\n", + prCmdCalBackupDataV2->au4Buffer[0], + prCmdCalBackupDataV2->au4Buffer[1], + prCmdCalBackupDataV2->au4Buffer[2], + prCmdCalBackupDataV2->au4Buffer[3], + prCmdCalBackupDataV2->au4Buffer[4]); + DBGLOG(RFTEST, INFO, + "Check some of elements (0x%08x), (0x%08x), (0x%08x), (0x%08x), (0x%08x)\n", + prCmdCalBackupDataV2->au4Buffer[( + prCmdCalBackupDataV2->u4Length + / sizeof(uint32_t)) - 5], + prCmdCalBackupDataV2->au4Buffer[( + prCmdCalBackupDataV2->u4Length + / sizeof(uint32_t)) - 4], + prCmdCalBackupDataV2->au4Buffer[( + prCmdCalBackupDataV2->u4Length + / sizeof(uint32_t)) - 3], + prCmdCalBackupDataV2->au4Buffer[( + prCmdCalBackupDataV2->u4Length + / sizeof(uint32_t)) - 2], + prCmdCalBackupDataV2->au4Buffer[( + prCmdCalBackupDataV2->u4Length + / sizeof(uint32_t)) - 1]); + + DBGLOG(RFTEST, INFO, + "=================================================================\n"); +#endif + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_CAL_BACKUP_IN_HOST_V2, + FALSE, + TRUE, + FALSE, + nicCmdEventQueryCalBackupV2, + NULL, + sizeof(struct CMD_CAL_BACKUP_STRUCT_V2), + (uint8_t *) prCmdCalBackupDataV2, + pvQueryBuffer, + u4QueryBufferLen); + + kalMemFree(prCmdCalBackupDataV2, VIR_MEM_TYPE, + sizeof(struct CMD_CAL_BACKUP_STRUCT_V2)); + } + + return rWlanStatus; +} + +uint32_t +wlanoidQueryCalBackupV2(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct PARAM_CAL_BACKUP_STRUCT_V2 *prCalBackupDataV2Info; + + DBGLOG(RFTEST, INFO, "%s\n", __func__); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct CMD_CAL_BACKUP_STRUCT_V2); + + prCalBackupDataV2Info = (struct PARAM_CAL_BACKUP_STRUCT_V2 + *) pvQueryBuffer; + + if (prCalBackupDataV2Info->ucReason == 0 + && prCalBackupDataV2Info->ucAction == 0) { + /* Get Thermal Temp from FW */ + return wlanoidSendCalBackupV2Cmd(prAdapter, pvQueryBuffer, + u4QueryBufferLen); + } else if (prCalBackupDataV2Info->ucReason == 0 + && prCalBackupDataV2Info->ucAction == 1) { + /* Get Cal Data Size from FW */ + return wlanoidSendCalBackupV2Cmd(prAdapter, pvQueryBuffer, + u4QueryBufferLen); + } else if (prCalBackupDataV2Info->ucReason == 2 + && prCalBackupDataV2Info->ucAction == 4) { + /* Get Cal Data from FW */ + if (prCalBackupDataV2Info->ucRomRam == 0) + prCalBackupDataV2Info->u4RemainLength = + g_rBackupCalDataAllV2.u4ValidRomCalDataLength; + else if (prCalBackupDataV2Info->ucRomRam == 1) + prCalBackupDataV2Info->u4RemainLength = + g_rBackupCalDataAllV2.u4ValidRamCalDataLength; + + return wlanoidSendCalBackupV2Cmd(prAdapter, pvQueryBuffer, + u4QueryBufferLen); + } else { + return rWlanStatus; + } +} +#endif + + +#if CFG_SUPPORT_SMART_GEAR +uint32_t +wlandioSetSGStatus(IN struct ADAPTER *prAdapter, + IN uint8_t ucSGEnable, + IN uint8_t ucSGSpcCmd, + IN uint8_t ucNSS) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct CMD_SMART_GEAR_PARAM *prCmdSGStatus; + + prCmdSGStatus = (struct CMD_SMART_GEAR_PARAM *)cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(struct CMD_SMART_GEAR_PARAM)); + + if (!prCmdSGStatus) { + DBGLOG(SW4, ERROR, + "[SG]cnmMemAlloc for wlandioSetSGStatus failed!\n"); + return WLAN_STATUS_NOT_ACCEPTED; + } + + prCmdSGStatus->ucSGEnable = ucSGEnable; + prCmdSGStatus->ucSGSpcCmd = ucSGSpcCmd; + + prCmdSGStatus->ucSGCfg = 0xFF; + + if (ucSGSpcCmd == 0xFF) { + prCmdSGStatus->ucSGCfg = prAdapter->rWifiVar.ucSGCfg; + prCmdSGStatus->ucNSSCap = ucNSS; + prCmdSGStatus->ucSG24GFavorANT = + prAdapter->rWifiVar.ucSG24GFavorANT; + prCmdSGStatus->ucSG5GFavorANT = + prAdapter->rWifiVar.ucSG5GFavorANT; + } + + DBGLOG(SW4, INFO, + "[SG]Status[%d][%d][%d][%d][%d]\n", + prCmdSGStatus->ucSGEnable, prCmdSGStatus->ucSGSpcCmd, + prCmdSGStatus->ucNSSCap, prCmdSGStatus->ucSG24GFavorANT, + prCmdSGStatus->ucSG5GFavorANT); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SG_PARAM, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(*prCmdSGStatus), + (uint8_t *) prCmdSGStatus, NULL, 0); + + cnmMemFree(prAdapter, prCmdSGStatus); + return rWlanStatus; + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryMcrRead(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_CUSTOM_MCR_RW_STRUCT *prMcrRdInfo; + struct CMD_ACCESS_REG rCmdAccessReg; + struct mt66xx_chip_info *prChipInfo = NULL; + + DEBUGFUNC("wlanoidQueryMcrRead"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + prChipInfo = prAdapter->chip_info; + ASSERT(prChipInfo); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct + PARAM_CUSTOM_MCR_RW_STRUCT); + + if (u4QueryBufferLen < sizeof(struct + PARAM_CUSTOM_MCR_RW_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + prMcrRdInfo = (struct PARAM_CUSTOM_MCR_RW_STRUCT *) + pvQueryBuffer; + + /* 0x9000 - 0x9EFF reserved for FW */ +#if CFG_SUPPORT_SWCR + if ((prMcrRdInfo->u4McrOffset >> 16) == 0x9F00) { + swCrReadWriteCmd(prAdapter, SWCR_READ, + (uint16_t) (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(struct CMD_ACCESS_REG), + (uint8_t *) &rCmdAccessReg, + pvQueryBuffer, + u4QueryBufferLen); + } else { + if (prMcrRdInfo->u4McrOffset == 0 && + prChipInfo->asicGetChipID) { + prMcrRdInfo->u4McrData = + prChipInfo->asicGetChipID(prAdapter); + log_dbg(INIT, INFO, + "Get Chip ID [0x%08x] from FW\n", + prMcrRdInfo->u4McrData); + } else { + + HAL_MCR_RD(prAdapter, + /* address is in DWORD unit */ + (prMcrRdInfo->u4McrOffset & BITS(2, 31)), + &prMcrRdInfo->u4McrData); + + DBGLOG(INIT, TRACE, + "MCR Read: Offset = %#08x, Data = %#08x\n", + prMcrRdInfo->u4McrOffset, + prMcrRdInfo->u4McrData); + } + return WLAN_STATUS_SUCCESS; + } +} /* end of wlanoidQueryMcrRead() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to write MCR and enable specific function. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. + * \param[in] u4SetBufferLen The length of the set buffer. + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed + * due to invalid length of the set buffer, returns + * the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetMcrWrite(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_MCR_RW_STRUCT *prMcrWrInfo; + struct CMD_ACCESS_REG rCmdAccessReg; + +#if CFG_STRESS_TEST_SUPPORT + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prBssInfo = + aisGetAisBssInfo(prAdapter, AIS_DEFAULT_INDEX); + struct STA_RECORD *prStaRec = prBssInfo->prStaRecOfAP; + uint32_t u4McrOffset, u4McrData; +#endif + + DEBUGFUNC("wlanoidSetMcrWrite"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CUSTOM_MCR_RW_STRUCT); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_MCR_RW_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prMcrWrInfo = (struct PARAM_CUSTOM_MCR_RW_STRUCT *) + 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 ENUM_REGISTRY_FIXED_RATE) + (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 */ + } + } + + 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(struct CMD_ACCESS_REG), + (uint8_t *) &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(struct CMD_ACCESS_REG), + (uint8_t *) &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(struct CMD_ACCESS_REG), + (uint8_t *) &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(struct CMD_ACCESS_REG), + (uint8_t *) &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, + (uint16_t)(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) { + uint32_t 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, + (uint32_t) 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(struct CMD_ACCESS_REG), + (uint8_t *) &rCmdAccessReg, + pvSetBuffer, u4SetBufferLen); + } +#endif + +#if 1 + /* low power test special command */ + if (prMcrWrInfo->u4McrOffset == 0x11111110) { + uint32_t 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, + (uint32_t) 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(struct CMD_ACCESS_REG), + (uint8_t *) &rCmdAccessReg, + pvSetBuffer, u4SetBufferLen); + } +#endif + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN + if (prMcrWrInfo->u4McrOffset == 0x22220000) { + /* read test mode */ + kalSetSdioTestPattern(prAdapter->prGlueInfo, + TRUE, TRUE); + + return WLAN_STATUS_SUCCESS; + } + + if (prMcrWrInfo->u4McrOffset == 0x22220001) { + /* write test mode */ + kalSetSdioTestPattern(prAdapter->prGlueInfo, + TRUE, FALSE); + + return WLAN_STATUS_SUCCESS; + } + + if (prMcrWrInfo->u4McrOffset == 0x22220002) { + /* leave from test mode */ + kalSetSdioTestPattern(prAdapter->prGlueInfo, + FALSE, FALSE); + + return WLAN_STATUS_SUCCESS; + } +#endif + + /* fill command */ + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_ACCESS_REG), + (uint8_t *) &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 = %#08x, Data = %#08x\n", + prMcrWrInfo->u4McrOffset, + prMcrWrInfo->u4McrData); + + return WLAN_STATUS_SUCCESS; + } +} /* wlanoidSetMcrWrite */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to query driver 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryDrvMcrRead(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_CUSTOM_MCR_RW_STRUCT *prMcrRdInfo; + /* CMD_ACCESS_REG rCmdAccessReg; */ + + DEBUGFUNC("wlanoidQueryMcrRead"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct + PARAM_CUSTOM_MCR_RW_STRUCT); + + if (u4QueryBufferLen < sizeof(struct + PARAM_CUSTOM_MCR_RW_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + prMcrRdInfo = (struct PARAM_CUSTOM_MCR_RW_STRUCT *) + pvQueryBuffer; + + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + HAL_MCR_RD(prAdapter, (prMcrRdInfo->u4McrOffset & BITS(2, + 31)), &prMcrRdInfo->u4McrData); + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + + DBGLOG(INIT, TRACE, + "DRV MCR Read: Offset = %#08x, Data = %#08x\n", + prMcrRdInfo->u4McrOffset, prMcrRdInfo->u4McrData); + + return WLAN_STATUS_SUCCESS; + +} /* end of wlanoidQueryMcrRead() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to write MCR and enable specific function. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. + * \param[in] u4SetBufferLen The length of the set buffer. + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed + * due to invalid length of the set buffer, returns + * the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetDrvMcrWrite(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_MCR_RW_STRUCT *prMcrWrInfo; + /* CMD_ACCESS_REG rCmdAccessReg; */ + + DEBUGFUNC("wlanoidSetMcrWrite"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CUSTOM_MCR_RW_STRUCT); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_MCR_RW_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prMcrWrInfo = (struct PARAM_CUSTOM_MCR_RW_STRUCT *) + pvSetBuffer; + + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + HAL_MCR_WR(prAdapter, (prMcrWrInfo->u4McrOffset & BITS(2, + 31)), prMcrWrInfo->u4McrData); + + DBGLOG(INIT, TRACE, + "DRV MCR Write: Offset = %#08x, Data = %#08x\n", + prMcrWrInfo->u4McrOffset, prMcrWrInfo->u4McrData); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetMcrWrite */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to query SW CTRL + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[out] pvQueryBuf A pointer to the buffer that holds the result of + * the query. + * \param[in] u4QueryBufLen The length of the query buffer. + * \param[out] pu4QueryInfoLen If the call is successful, returns the number of + * bytes written into the query buffer. If the call + * failed due to invalid length of the query buffer, + * returns the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQuerySwCtrlRead(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_CUSTOM_SW_CTRL_STRUCT *prSwCtrlInfo; + uint32_t rWlanStatus; + uint16_t u2Id, u2SubId; + uint32_t u4Data; + + struct CMD_SW_DBG_CTRL rCmdSwCtrl; + + DEBUGFUNC("wlanoidQuerySwCtrlRead"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct + PARAM_CUSTOM_SW_CTRL_STRUCT); + + if (u4QueryBufferLen < sizeof(struct + PARAM_CUSTOM_SW_CTRL_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + prSwCtrlInfo = (struct PARAM_CUSTOM_SW_CTRL_STRUCT *) + pvQueryBuffer; + + u2Id = (uint16_t) (prSwCtrlInfo->u4Id >> 16); + u2SubId = (uint16_t) (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 */, + (uint16_t) u2SubId, &u4Data); + break; +#endif /* CFG_SUPPORT_SWCR */ + + case 0xFFFF: { + u4Data = 0x5AA56620; + } + break; + + case 0xBABA: + switch ((u2SubId >> 8) & BITS(0, 7)) { + case 0x00: + /* Dump Tx resource and queue status */ + qmDumpQueueStatus(prAdapter, NULL, 0); + cnmDumpMemoryStatus(prAdapter, NULL, 0); + break; + + case 0x01: + /* Dump StaRec info by index */ + cnmDumpStaRec(prAdapter, + (uint8_t) (u2SubId & BITS(0, 7))); + break; + + case 0x02: + /* Dump BSS info by index */ + bssDumpBssInfo(prAdapter, + (uint8_t) (u2SubId & BITS(0, 7))); + break; + + case 0x03: + /*Dump BSS statistics by index */ + wlanDumpBssStatistics(prAdapter, + (uint8_t) (u2SubId & BITS(0, 7))); + break; + + case 0x04: + halDumpHifStatus(prAdapter, NULL, 0); + break; + + default: + break; + } + + u4Data = 0xBABABABA; + 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(struct CMD_SW_DBG_CTRL), + (uint8_t *) &rCmdSwCtrl, + pvQueryBuffer, u4QueryBufferLen); + return rWlanStatus; + } + } /* 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetSwCtrlWrite(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_SW_CTRL_STRUCT *prSwCtrlInfo; + struct CMD_SW_DBG_CTRL rCmdSwCtrl; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + uint16_t u2Id, u2SubId; + uint32_t u4Data; + uint8_t ucOpRxNss, ucOpTxNss; + uint8_t ucChannelWidth; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + DEBUGFUNC("wlanoidSetSwCtrlWrite"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CUSTOM_SW_CTRL_STRUCT); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_SW_CTRL_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prSwCtrlInfo = (struct PARAM_CUSTOM_SW_CTRL_STRUCT *) + pvSetBuffer; + + u2Id = (uint16_t) (prSwCtrlInfo->u4Id >> 16); + u2SubId = (uint16_t) (prSwCtrlInfo->u4Id & BITS(0, 15)); + u4Data = prSwCtrlInfo->u4Data; + + switch (u2Id) { + + /* 0x9000 - 0x9EFF reserved for FW */ + /* 0xFFFE reserved for FW */ + +#if CFG_SUPPORT_SWCR + case 0x9F00: + swCrReadWriteCmd(prAdapter, SWCR_WRITE, (uint16_t) u2SubId, + &u4Data); + break; +#endif /* CFG_SUPPORT_SWCR */ + + case 0x2222: + ucOpRxNss = (uint8_t)(u4Data & BITS(0, 3)); + ucOpTxNss = (uint8_t)((u4Data & BITS(4, 7)) >> 4); + ucChannelWidth = (uint8_t)((u4Data & BITS(8, 11)) >> 8); + ucBssIndex = (uint8_t) u2SubId; + + if ((u2SubId & BITS(8, 15)) != 0) { /* Debug OP change + * parameters + */ + DBGLOG(RLM, INFO, + "[UT_OP] BSS[%d] IsBwChange[%d] BW[%d] IsRxNssChange[%d] RxNss[%d]", + ucBssIndex, + prAdapter->aprBssInfo[ucBssIndex]-> + fgIsOpChangeChannelWidth, + prAdapter->aprBssInfo[ucBssIndex]-> + ucOpChangeChannelWidth, + prAdapter->aprBssInfo[ucBssIndex]-> + fgIsOpChangeRxNss, + prAdapter->aprBssInfo[ucBssIndex]-> + ucOpChangeRxNss + ); + DBGLOG(RLM, INFO, + " IsTxNssChange[%d] TxNss[%d]\n", + prAdapter->aprBssInfo[ucBssIndex]-> + fgIsOpChangeTxNss, + prAdapter->aprBssInfo[ucBssIndex]-> + ucOpChangeTxNss + ); + + DBGLOG(RLM, INFO, + "[UT_OP] current OP mode: w[%d] s1[%d] s2[%d] sco[%d] RxNss[%d] TxNss[%d]\n", + prAdapter->aprBssInfo[ucBssIndex]-> + ucVhtChannelWidth, + prAdapter->aprBssInfo[ucBssIndex]-> + ucVhtChannelFrequencyS1, + prAdapter->aprBssInfo[ucBssIndex]-> + ucVhtChannelFrequencyS2, + prAdapter->aprBssInfo[ucBssIndex]-> + eBssSCO, + prAdapter->aprBssInfo[ucBssIndex]-> + ucOpRxNss, + prAdapter->aprBssInfo[ucBssIndex]-> + ucOpTxNss); + } else { + /* ucChannelWidth 0:20MHz, 1:40MHz, 2:80MHz, 3:160MHz + * 4:80+80MHz + */ + DBGLOG(RLM, INFO, + "[UT_OP] Change BSS[%d] OpMode to BW[%d] RxNss[%d] TxNss[%d]\n", + ucBssIndex, ucChannelWidth, + ucOpRxNss, ucOpTxNss); + rlmChangeOperationMode( + prAdapter, ucBssIndex, ucChannelWidth, + ucOpRxNss, ucOpTxNss, + #if CFG_SUPPORT_SMART_GEAR + 0x00, + #endif + rlmDummyChangeOpHandler); + } + break; + + case 0x1000: + if (u2SubId == 0x8000) { + /* CTIA power save mode setting (code: 0x10008000) */ + prAdapter->u4CtiaPowerMode = u4Data; + prAdapter->fgEnCtiaPowerMode = TRUE; + + /* */ + { + enum PARAM_POWER_MODE ePowerMode; + + if (prAdapter->u4CtiaPowerMode == 0) + /* force to keep in CAM mode */ + ePowerMode = Param_PowerModeCAM; + else if (prAdapter->u4CtiaPowerMode == 1) + ePowerMode = Param_PowerModeMAX_PSP; + else + ePowerMode = Param_PowerModeFast_PSP; + + rWlanStatus = nicConfigPowerSaveProfile( + prAdapter, + ucBssIndex, + ePowerMode, TRUE, PS_CALLER_SW_WRITE); + } + } + break; + case 0x1001: + if (u2SubId == 0x0) + prAdapter->fgEnOnlineScan = (u_int8_t) u4Data; + else if (u2SubId == 0x1) + prAdapter->fgDisBcnLostDetection = (u_int8_t) u4Data; + else if (u2SubId == 0x2) + prAdapter->rWifiVar.ucUapsd = (u_int8_t) u4Data; + else if (u2SubId == 0x3) { + prAdapter->u4UapsdAcBmp = u4Data & BITS(0, 15); + GET_BSS_INFO_BY_INDEX(prAdapter, + u4Data >> 16)->rPmProfSetupInfo.ucBmpDeliveryAC = + (uint8_t) prAdapter->u4UapsdAcBmp; + GET_BSS_INFO_BY_INDEX(prAdapter, + u4Data >> 16)->rPmProfSetupInfo.ucBmpTriggerAC = + (uint8_t) prAdapter->u4UapsdAcBmp; + } else if (u2SubId == 0x4) + prAdapter->fgDisStaAgingTimeoutDetection = + (u_int8_t) u4Data; + else if (u2SubId == 0x5) + prAdapter->rWifiVar.uc2G4BandwidthMode = + (uint8_t) u4Data; + else if (u2SubId == 0x0100) { + if (u4Data == 2) + prAdapter->rWifiVar.ucRxGf = FEATURE_DISABLED; + else + prAdapter->rWifiVar.ucRxGf = FEATURE_ENABLED; + } else if (u2SubId == 0x0101) + prAdapter->rWifiVar.ucRxShortGI = (uint8_t) u4Data; + else if (u2SubId == 0x0103) { /* AP Mode WMMPS */ + DBGLOG(OID, INFO, + "ApUapsd 0x10010103 cmd received: %d\n", + u4Data); + setApUapsdEnable(prAdapter, (u_int8_t) u4Data); + } else if (u2SubId == 0x0110) { + prAdapter->fgIsEnableLpdvt = (u_int8_t) u4Data; + prAdapter->fgEnOnlineScan = (u_int8_t) u4Data; + DBGLOG(INIT, INFO, "--- Enable LPDVT [%d] ---\n", + prAdapter->fgIsEnableLpdvt); + } + + break; + +#if CFG_SUPPORT_SWCR + case 0x1002: +#if CFG_RX_PKTS_DUMP + if (u2SubId == 0x0) { + if (u4Data) + u4Data = BIT(HIF_RX_PKT_TYPE_MANAGEMENT); + swCrFrameCheckEnable(prAdapter, u4Data); + } +#endif + if (u2SubId == 0x1) { + u_int8_t fgIsEnable; + uint8_t ucType; + uint32_t u4Timeout; + + fgIsEnable = (u_int8_t) (u4Data & 0xff); + ucType = 0; /* ((u4Data>>4) & 0xf); */ + u4Timeout = ((u4Data >> 8) & 0xff); + swCrDebugCheckEnable(prAdapter, fgIsEnable, ucType, + u4Timeout); + } + break; +#endif + case 0x1003: /* for debug switches */ + switch (u2SubId) { + case 1: + DBGLOG(OID, INFO, + "Enable VoE 5.7 Packet Jitter test\n"); + prAdapter->rDebugInfo.fgVoE5_7Test = !!u4Data; + break; + case 0x0002: + { + struct CMD_TX_AMPDU rTxAmpdu; + uint32_t rStatus; + + rTxAmpdu.fgEnable = !!u4Data; + + rStatus = wlanSendSetQueryCmd( + prAdapter, CMD_ID_TX_AMPDU, TRUE, FALSE, FALSE, + NULL, NULL, sizeof(struct CMD_TX_AMPDU), + (uint8_t *)&rTxAmpdu, NULL, 0); + DBGLOG(OID, INFO, "disable tx ampdu status %u\n", + rStatus); + break; + } + default: + break; + } + break; + +#if CFG_SUPPORT_802_11W + case 0x2000: + DBGLOG(RSN, INFO, "802.11w test 0x%x\n", u2SubId); + if (u2SubId == 0x0) + rsnStartSaQuery(prAdapter, ucBssIndex); + if (u2SubId == 0x1) + rsnStopSaQuery(prAdapter, ucBssIndex); + if (u2SubId == 0x2) + rsnSaQueryRequest(prAdapter, NULL); + if (u2SubId == 0x3) { + struct BSS_INFO *prBssInfo = + aisGetAisBssInfo(prAdapter, ucBssIndex); + + authSendDeauthFrame(prAdapter, prBssInfo, + 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: %u\n", u4Data); + + if ((enum ENUM_REGISTRY_FIXED_RATE) (u4Data) < + FIXED_RATE_NUM) + prAdapter->rWifiVar.eRateSetting = + (enum ENUM_REGISTRY_FIXED_RATE)(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, + ucBssIndex); +#else + aisBssBeaconTimeout(prAdapter); +#endif + + return WLAN_STATUS_SUCCESS; + + } else if (u2SubId == 0x1234) { + /* 1. Disable On-Lin Scan */ + /* 3. Disable FIFO FULL no ack */ + /* 4. Disable Roaming */ + /* Disalbe auto tx power */ + /* 2. Keep at CAM mode */ + /* 5. Disable Beacon Timeout Detection */ + rWlanStatus = nicEnterCtiaMode(prAdapter, TRUE, TRUE); + } else if (u2SubId == 0x1235) { + /* 1. Enaable On-Lin Scan */ + /* 3. Enable FIFO FULL no ack */ + /* 4. Enable Roaming */ + /* Enable auto tx power */ + /* 2. Keep at Fast PS */ + /* 5. Enable Beacon Timeout Detection */ + rWlanStatus = nicEnterCtiaMode(prAdapter, FALSE, TRUE); + } else if (u2SubId == 0x1260) { + /* Disable On-Line Scan */ + rWlanStatus = nicEnterCtiaModeOfScan(prAdapter, + TRUE, TRUE); + } else if (u2SubId == 0x1261) { + /* Enable On-Line Scan */ + rWlanStatus = nicEnterCtiaModeOfScan(prAdapter, + FALSE, TRUE); + } else if (u2SubId == 0x1262) { + /* Disable Roaming */ + rWlanStatus = nicEnterCtiaModeOfRoaming(prAdapter, + TRUE, TRUE); + } else if (u2SubId == 0x1263) { + /* Enable Roaming */ + rWlanStatus = nicEnterCtiaModeOfRoaming(prAdapter, + FALSE, TRUE); + } else if (u2SubId == 0x1264) { + /* Keep at CAM mode */ + rWlanStatus = nicEnterCtiaModeOfCAM(prAdapter, + TRUE, TRUE); + } else if (u2SubId == 0x1265) { + /* Keep at Fast PS */ + rWlanStatus = nicEnterCtiaModeOfCAM(prAdapter, + FALSE, TRUE); + } else if (u2SubId == 0x1266) { + /* Disable Beacon Timeout Detection */ + rWlanStatus = nicEnterCtiaModeOfBCNTimeout(prAdapter, + TRUE, TRUE); + } else if (u2SubId == 0x1267) { + /* Enable Beacon Timeout Detection */ + rWlanStatus = nicEnterCtiaModeOfBCNTimeout(prAdapter, + FALSE, TRUE); + } else if (u2SubId == 0x1268) { + /* Disalbe auto tx power */ + rWlanStatus = nicEnterCtiaModeOfAutoTxPower(prAdapter, + TRUE, TRUE); + } else if (u2SubId == 0x1269) { + /* Enable auto tx power */ + rWlanStatus = nicEnterCtiaModeOfAutoTxPower(prAdapter, + FALSE, TRUE); + } else if (u2SubId == 0x1270) { + /* Disalbe FIFO FULL no ack */ + rWlanStatus = nicEnterCtiaModeOfFIFOFullNoAck(prAdapter, + TRUE, TRUE); + } else if (u2SubId == 0x1271) { + /* Enable FIFO FULL no ack */ + rWlanStatus = nicEnterCtiaModeOfFIFOFullNoAck(prAdapter, + FALSE, TRUE); + } +#endif +#if CFG_MTK_STAGE_SCAN + else if (u2SubId == 0x1250) + prAdapter->aePreferBand[KAL_NETWORK_TYPE_AIS_INDEX] = + BAND_NULL; + else if (u2SubId == 0x1251) + prAdapter->aePreferBand[KAL_NETWORK_TYPE_AIS_INDEX] = + BAND_2G4; + else if (u2SubId == 0x1252) { + if (prAdapter->fgEnable5GBand) + prAdapter->aePreferBand + [KAL_NETWORK_TYPE_AIS_INDEX] = BAND_5G; + else + /* Skip this setting if 5G band is disabled */ + DBGLOG(SCN, INFO, + "Skip 5G stage scan request due to 5G is disabled\n"); + } +#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(struct CMD_SW_DBG_CTRL), + (uint8_t *) &rCmdSwCtrl, + pvSetBuffer, u4SetBufferLen); + } + } /* switch(u2Id) */ + + return rWlanStatus; +} /* wlanoidSetSwCtrlWrite */ + +uint32_t +wlanoidQueryChipConfig(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_CUSTOM_CHIP_CONFIG_STRUCT *prChipConfigInfo; + struct CMD_CHIP_CONFIG rCmdChipConfig; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQuerySwCtrlRead"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct + PARAM_CUSTOM_CHIP_CONFIG_STRUCT); + + if (u4QueryBufferLen < sizeof(struct + PARAM_CUSTOM_CHIP_CONFIG_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + prChipConfigInfo = (struct PARAM_CUSTOM_CHIP_CONFIG_STRUCT + *) pvQueryBuffer; + kalMemZero(&rCmdChipConfig, sizeof(rCmdChipConfig)); + + rCmdChipConfig.u2Id = prChipConfigInfo->u2Id; + rCmdChipConfig.ucType = prChipConfigInfo->ucType; + rCmdChipConfig.ucRespType = prChipConfigInfo->ucRespType; + rCmdChipConfig.u2MsgSize = prChipConfigInfo->u2MsgSize; + if (rCmdChipConfig.u2MsgSize > CHIP_CONFIG_RESP_SIZE) { + DBGLOG(REQ, INFO, + "Chip config Msg Size %u is not valid (query)\n", + rCmdChipConfig.u2MsgSize); + rCmdChipConfig.u2MsgSize = CHIP_CONFIG_RESP_SIZE; + } + kalMemCopy(rCmdChipConfig.aucCmd, prChipConfigInfo->aucCmd, + rCmdChipConfig.u2MsgSize); + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_CHIP_CONFIG, FALSE, TRUE, TRUE, + /*nicCmdEventQuerySwCtrlRead, */ + nicCmdEventQueryChipConfig, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_CHIP_CONFIG), + (uint8_t *) &rCmdChipConfig, + pvQueryBuffer, + u4QueryBufferLen); + + return rWlanStatus; + +} + +/* end of wlanoidQueryChipConfig() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set chip + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. + * \param[in] u4SetBufferLen The length of the set buffer. + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed + * due to invalid length of the set buffer, returns + * the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetChipConfig(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_CHIP_CONFIG_STRUCT *prChipConfigInfo; + struct CMD_CHIP_CONFIG rCmdChipConfig; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DATA_STRUCT_INSPECTING_ASSERT( + sizeof(prChipConfigInfo->aucCmd) == CHIP_CONFIG_RESP_SIZE); + DEBUGFUNC("wlanoidSetChipConfig"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct + PARAM_CUSTOM_CHIP_CONFIG_STRUCT); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_CHIP_CONFIG_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prChipConfigInfo = (struct PARAM_CUSTOM_CHIP_CONFIG_STRUCT + *) pvSetBuffer; + kalMemZero(&rCmdChipConfig, sizeof(rCmdChipConfig)); + + rCmdChipConfig.u2Id = prChipConfigInfo->u2Id; + rCmdChipConfig.ucType = prChipConfigInfo->ucType; + rCmdChipConfig.ucRespType = prChipConfigInfo->ucRespType; + rCmdChipConfig.u2MsgSize = prChipConfigInfo->u2MsgSize; + if (rCmdChipConfig.u2MsgSize > CHIP_CONFIG_RESP_SIZE) { + DBGLOG(REQ, INFO, + "Chip config Msg Size %u is not valid (set)\n", + rCmdChipConfig.u2MsgSize); + rCmdChipConfig.u2MsgSize = CHIP_CONFIG_RESP_SIZE; + } + kalMemCopy(rCmdChipConfig.aucCmd, prChipConfigInfo->aucCmd, + rCmdChipConfig.u2MsgSize); + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_CHIP_CONFIG, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_CHIP_CONFIG), + (uint8_t *) &rCmdChipConfig, + pvSetBuffer, u4SetBufferLen); + + return rWlanStatus; +} /* wlanoidSetChipConfig */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set cfg and callback + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetKeyCfg(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct PARAM_CUSTOM_KEY_CFG_STRUCT *prKeyCfgInfo; + + DEBUGFUNC("wlanoidSetKeyCfg"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CUSTOM_KEY_CFG_STRUCT); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_KEY_CFG_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + prKeyCfgInfo = (struct PARAM_CUSTOM_KEY_CFG_STRUCT *) + pvSetBuffer; + + if (kalMemCmp(prKeyCfgInfo->aucKey, "reload", 6) == 0) + wlanGetConfig(prAdapter); /* Reload config file */ + else + wlanCfgSet(prAdapter, prKeyCfgInfo->aucKey, + prKeyCfgInfo->aucValue, prKeyCfgInfo->u4Flag); + + wlanInitFeatureOption(prAdapter); + + DBGLOG(REQ, TRACE, + "StaVHT [%u], ApVHT [%u], GoVHT [%u], GcVHT [%u]\n", + prAdapter->rWifiVar.ucStaVht, + prAdapter->rWifiVar.ucApVht, + prAdapter->rWifiVar.ucP2pGoVht, + prAdapter->rWifiVar.ucP2pGcVht); + + DBGLOG(REQ, TRACE, "Nss [%u], Dbdc [%u]\n", + prAdapter->rWifiVar.ucNSS, + prAdapter->rWifiVar.eDbdcMode); + + DBGLOG(REQ, TRACE, + "TxLdpc [%u], RxLdpc [%u], StbcTx [%u], StbcRx [%u]\n", + prAdapter->rWifiVar.ucTxLdpc, + prAdapter->rWifiVar.ucRxLdpc, + prAdapter->rWifiVar.ucTxStbc, + prAdapter->rWifiVar.ucRxStbc); +#if CFG_SUPPORT_EASY_DEBUG + wlanFeatureToFw(prAdapter, prKeyCfgInfo->u4Flag); +#endif + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryEepromRead(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_CUSTOM_EEPROM_RW_STRUCT *prEepromRwInfo; + struct CMD_ACCESS_EEPROM rCmdAccessEeprom; + + DEBUGFUNC("wlanoidQueryEepromRead"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct + PARAM_CUSTOM_EEPROM_RW_STRUCT); + + if (u4QueryBufferLen < sizeof(struct + PARAM_CUSTOM_EEPROM_RW_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + prEepromRwInfo = (struct PARAM_CUSTOM_EEPROM_RW_STRUCT *) + pvQueryBuffer; + + kalMemZero(&rCmdAccessEeprom, + sizeof(struct CMD_ACCESS_EEPROM)); + rCmdAccessEeprom.u2Offset = prEepromRwInfo->info.rEeprom.ucEepromIndex; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_EEPROM, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryEepromRead, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_ACCESS_EEPROM), + (uint8_t *) &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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetEepromWrite(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_EEPROM_RW_STRUCT *prEepromRwInfo; + struct CMD_ACCESS_EEPROM rCmdAccessEeprom; + + DEBUGFUNC("wlanoidSetEepromWrite"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct + PARAM_CUSTOM_EEPROM_RW_STRUCT); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_EEPROM_RW_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prEepromRwInfo = (struct PARAM_CUSTOM_EEPROM_RW_STRUCT *) + pvSetBuffer; + + kalMemZero(&rCmdAccessEeprom, + sizeof(struct CMD_ACCESS_EEPROM)); + rCmdAccessEeprom.u2Offset = prEepromRwInfo->info.rEeprom.ucEepromIndex; + rCmdAccessEeprom.u2Data = prEepromRwInfo->info.rEeprom.u2EepromData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_EEPROM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_ACCESS_EEPROM), + (uint8_t *) &rCmdAccessEeprom, pvSetBuffer, + u4SetBufferLen); + +} /* wlanoidSetEepromWrite */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryOidInterfaceVersion(IN struct ADAPTER * + prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + DEBUGFUNC("wlanoidQueryOidInterfaceVersion"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *(uint32_t *) pvQueryBuffer = + prAdapter->chip_info->custom_oid_interface_version; + *pu4QueryInfoLen = sizeof(uint32_t); + + DBGLOG(REQ, WARN, "Custom OID interface version: %#08X\n", + *(uint32_t *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryMulticastList(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetMulticastList(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct CMD_MAC_MCAST_ADDR rCmdMacMcastAddr; + uint8_t ucBssIndex = 0; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* The data must be a multiple of the Ethernet address size. */ + if ((u4SetBufferLen % MAC_ADDR_LEN)) { + DBGLOG(REQ, WARN, "Invalid MC list length %u\n", + u4SetBufferLen); + + *pu4SetInfoLen = (((u4SetBufferLen + MAC_ADDR_LEN) - 1) / + MAC_ADDR_LEN) * MAC_ADDR_LEN; + + return WLAN_STATUS_INVALID_LENGTH; + } + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + + *pu4SetInfoLen = u4SetBufferLen; + + /* Verify if we can support so many multicast addresses. */ + if (u4SetBufferLen > MAX_NUM_GROUP_ADDR * MAC_ADDR_LEN) { + 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; + } + + kalMemZero(&rCmdMacMcastAddr, sizeof(rCmdMacMcastAddr)); + rCmdMacMcastAddr.u4NumOfGroupAddr = u4SetBufferLen / + MAC_ADDR_LEN; + rCmdMacMcastAddr.ucBssIndex = + ucBssIndex; + kalMemCopy(rCmdMacMcastAddr.arAddress, pvSetBuffer, + u4SetBufferLen); + DBGLOG(OID, INFO, + "MCAST white list: total=%d MAC0="MACSTR" MAC1="MACSTR + " MAC2="MACSTR" MAC3="MACSTR" MAC4="MACSTR"\n", + rCmdMacMcastAddr.u4NumOfGroupAddr, + MAC2STR(rCmdMacMcastAddr.arAddress[0]), + MAC2STR(rCmdMacMcastAddr.arAddress[1]), + MAC2STR(rCmdMacMcastAddr.arAddress[2]), + MAC2STR(rCmdMacMcastAddr.arAddress[3]), + MAC2STR(rCmdMacMcastAddr.arAddress[4])); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_MAC_MCAST_ADDR, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_MAC_MCAST_ADDR), + (uint8_t *) &rCmdMacMcastAddr, + pvSetBuffer, u4SetBufferLen); +} /* end of wlanoidSetMulticastList() */ + +uint32_t +wlanoidRssiMonitor(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_RSSI_MONITOR_T rRssi; + int8_t orig_max_rssi_value; + int8_t orig_min_rssi_value; + uint32_t rStatus1 = WLAN_STATUS_SUCCESS; + uint32_t rStatus2; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct PARAM_RSSI_MONITOR_T); + + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(OID, WARN, "Too short length %u\n", + u4QueryBufferLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + kalMemZero(&rRssi, sizeof(struct PARAM_RSSI_MONITOR_T)); + + orig_max_rssi_value = rRssi.max_rssi_value; + orig_min_rssi_value = rRssi.min_rssi_value; + + kalMemCopy(&rRssi, pvQueryBuffer, + sizeof(struct PARAM_RSSI_MONITOR_T)); + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo, + ucBssIndex) == + MEDIA_STATE_DISCONNECTED) { + DBGLOG(OID, TRACE, + "Set RSSI monitor when disconnected, enable=%d\n", + rRssi.enable); + if (rRssi.enable) + return WLAN_STATUS_ADAPTER_NOT_READY; + rStatus1 = WLAN_STATUS_ADAPTER_NOT_READY; + } + + if (!rRssi.enable) { + rRssi.max_rssi_value = 0; + rRssi.min_rssi_value = 0; + } + + DBGLOG(OID, TRACE, + "enable=%d, max_rssi_value=%d, min_rssi_value=%d, orig_max_rssi_value=%d, orig_min_rssi_value=%d\n", + rRssi.enable, rRssi.max_rssi_value, rRssi.min_rssi_value, + orig_max_rssi_value, orig_min_rssi_value); + + /* + * If status == WLAN_STATUS_ADAPTER_NOT_READY + * driver needs to info FW to stop mointor but set oid flag to false + * to prevent from multiple complete + */ + rStatus2 = wlanSendSetQueryCmd(prAdapter, + CMD_ID_RSSI_MONITOR, + TRUE, + FALSE, + (rStatus1 != WLAN_STATUS_ADAPTER_NOT_READY), + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct PARAM_RSSI_MONITOR_T), + (uint8_t *)&rRssi, NULL, 0); + + return (rStatus1 == WLAN_STATUS_ADAPTER_NOT_READY) ? + rStatus1 : rStatus2; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetCurrentPacketFilter(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t u4NewPacketFilter; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t rResult = WLAN_STATUS_FAILURE; + struct CMD_RX_PACKET_FILTER rSetRxPacketFilter; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(uint32_t)) { + *pu4SetInfoLen = sizeof(uint32_t); + return WLAN_STATUS_INVALID_LENGTH; + } + ASSERT(pvSetBuffer); + + /* Set the new packet filter. */ + u4NewPacketFilter = *(uint32_t *) pvSetBuffer; + + DBGLOG(REQ, TRACE, "New packet filter: %#08x\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; + DBGLOG(REQ, WARN, "some flags we don't support\n"); + 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 + + prAdapter->fgAllMulicastFilter = FALSE; + if (u4NewPacketFilter & PARAM_PACKET_FILTER_ALL_MULTICAST) + prAdapter->fgAllMulicastFilter = TRUE; + } while (FALSE); + + if (rStatus == WLAN_STATUS_SUCCESS) { + /* Store the packet filter */ + + prAdapter->u4OsPacketFilter &= PARAM_PACKET_FILTER_P2P_MASK; + prAdapter->u4OsPacketFilter |= u4NewPacketFilter; + + rSetRxPacketFilter.u4RxPacketFilter = + prAdapter->u4OsPacketFilter; + rResult = wlanoidSetPacketFilter(prAdapter, + &rSetRxPacketFilter, + TRUE, pvSetBuffer, + u4SetBufferLen); + DBGLOG(OID, TRACE, "[MC debug] u4OsPacketFilter=0x%x\n", + prAdapter->u4OsPacketFilter); + return rResult; + } else { + return rStatus; + } +} /* wlanoidSetCurrentPacketFilter */ + +uint32_t wlanoidSetPacketFilter(struct ADAPTER *prAdapter, + void *pvPacketFiltr, + u_int8_t fgIsOid, void *pvSetBuffer, + uint32_t u4SetBufferLen) { + struct CMD_RX_PACKET_FILTER *prSetRxPacketFilter = NULL; + + prSetRxPacketFilter = (struct CMD_RX_PACKET_FILTER *) + pvPacketFiltr; +#if CFG_SUPPORT_DROP_ALL_MC_PACKET + if (prAdapter->prGlueInfo->fgIsInSuspendMode) + prSetRxPacketFilter->u4RxPacketFilter &= + ~(PARAM_PACKET_FILTER_MULTICAST | + PARAM_PACKET_FILTER_ALL_MULTICAST); +#else + if (prAdapter->prGlueInfo->fgIsInSuspendMode) { + prSetRxPacketFilter->u4RxPacketFilter &= + ~(PARAM_PACKET_FILTER_ALL_MULTICAST); + prSetRxPacketFilter->u4RxPacketFilter |= + (PARAM_PACKET_FILTER_MULTICAST); + } +#endif + DBGLOG(OID, TRACE, + "[MC debug] u4PacketFilter=%x, IsSuspend=%d\n", + prSetRxPacketFilter->u4RxPacketFilter, + prAdapter->prGlueInfo->fgIsInSuspendMode); + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RX_FILTER, + TRUE, + FALSE, + fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_RX_PACKET_FILTER), + (uint8_t *)prSetRxPacketFilter, + pvSetBuffer, u4SetBufferLen); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryCurrentPacketFilter(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + DEBUGFUNC("wlanoidQueryCurrentPacketFilter"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(uint32_t); + + if (u4QueryBufferLen >= sizeof(uint32_t)) { + ASSERT(pvQueryBuffer); + *(uint32_t *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryAcpiDevicePowerState(IN struct ADAPTER * + prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { +#if DBG + enum PARAM_DEVICE_POWER_STATE *prPowerState; +#endif + + DEBUGFUNC("wlanoidQueryAcpiDevicePowerState"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(enum PARAM_DEVICE_POWER_STATE); + +#if DBG + prPowerState = (enum PARAM_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 + */ + *(enum PARAM_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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetAcpiDevicePowerState(IN struct ADAPTER * + prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + enum PARAM_DEVICE_POWER_STATE *prPowerState; + u_int8_t fgRetValue = TRUE; + + DEBUGFUNC("wlanoidSetAcpiDevicePowerState"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(enum PARAM_DEVICE_POWER_STATE); + + ASSERT(pvSetBuffer); + prPowerState = (enum PARAM_DEVICE_POWER_STATE *) + pvSetBuffer; + switch (*prPowerState) { + case ParamDeviceStateD0: + DBGLOG(REQ, INFO, "Set Power State: D0\n"); + kalDevSetPowerState(prAdapter->prGlueInfo, + (uint32_t) 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, + (uint32_t) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryFragThreshold(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetFragThreshold(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryRtsThreshold(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + DEBUGFUNC("wlanoidQueryRtsThreshold"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + DBGLOG(REQ, LOUD, "\n"); + + if (u4QueryBufferLen < sizeof(uint32_t)) { + *pu4QueryInfoLen = sizeof(uint32_t); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + *((uint32_t *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetRtsThreshold(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *prRtsThreshold; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(uint32_t); + if (u4SetBufferLen < sizeof(uint32_t)) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prRtsThreshold = (uint32_t *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetDisassociate(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct MSG_AIS_ABORT *prAisAbortMsg; + uint32_t u4DisconnectReason; + struct CONNECTION_SETTINGS *prConnSettings; + uint8_t ucBssIndex = 0; + struct AIS_FSM_INFO *prAisFsmInfo = NULL; + + DEBUGFUNC("wlanoidSetDisassociate"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + + *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; + } + + DBGLOG(REQ, LOUD, "ucBssIndex %d\n", ucBssIndex); + + prConnSettings = + aisGetConnSettings(prAdapter, ucBssIndex); + + /* Send AIS Abort Message */ + prAisAbortMsg = (struct MSG_AIS_ABORT *) cnmMemAlloc( + prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_AIS_ABORT)); + if (!prAisAbortMsg) { + DBGLOG(REQ, ERROR, "Fail in creating AisAbortMsg.\n"); + return WLAN_STATUS_FAILURE; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; + if (pvSetBuffer == NULL) + prAisAbortMsg->ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_LOCALLY; + else { + u4DisconnectReason = *((uint32_t *)pvSetBuffer); + prAisAbortMsg->ucReasonOfDisconnect = + u4DisconnectReason; + } + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + if (prAisFsmInfo->eCurrentState == AIS_STATE_SCAN || + prAisFsmInfo->eCurrentState == AIS_STATE_ONLINE_SCAN) + prAisFsmInfo->fgIsScanOidAborted = TRUE; + + prAisAbortMsg->fgDelayIndication = FALSE; + prAisAbortMsg->ucBssIndex = ucBssIndex; + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prAisAbortMsg, MSG_SEND_METHOD_BUF); + + /* indicate for disconnection */ + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo, + ucBssIndex) == + MEDIA_STATE_CONNECTED) + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY, NULL, + 0, ucBssIndex); +#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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQuery802dot11PowerSaveProfile(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + DEBUGFUNC("wlanoidQuery802dot11PowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen != 0) { + ASSERT(pvQueryBuffer); + + /* *(PPARAM_POWER_MODE) pvQueryBuffer = (PARAM_POWER_MODE) + * (prAdapter->rWlanInfo.ePowerSaveMode.ucPsProfile); + */ + *(enum PARAM_POWER_MODE *) pvQueryBuffer = + (enum PARAM_POWER_MODE) ( + prAdapter->rWlanInfo.arPowerSaveMode[ + ucBssIndex].ucPsProfile); + *pu4QueryInfoLen = sizeof(enum 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) + */ + *(enum PARAM_POWER_MODE *) pvQueryBuffer = + (enum 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSet802dot11PowerSaveProfile(IN struct ADAPTER * + prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t status; + struct PARAM_POWER_MODE_ *prPowerMode; + struct BSS_INFO *prBssInfo; + + const uint8_t *apucPsMode[Param_PowerModeMax] = { + (uint8_t *) "CAM", + (uint8_t *) "MAX PS", + (uint8_t *) "FAST PS" + }; + + DEBUGFUNC("wlanoidSet802dot11PowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_POWER_MODE_); + prPowerMode = (struct PARAM_POWER_MODE_ *) pvSetBuffer; + + if (u4SetBufferLen < sizeof(struct PARAM_POWER_MODE_)) { + DBGLOG(REQ, WARN, + "Set power mode error: Invalid length %u\n", + u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } else if (prPowerMode->ePowerMode >= Param_PowerModeMax) { + DBGLOG(REQ, WARN, + "Set power mode error: Invalid power mode(%u)\n", + prPowerMode->ePowerMode); + return WLAN_STATUS_INVALID_DATA; + } else if (prPowerMode->ucBssIdx >= + prAdapter->ucHwBssIdNum) { + DBGLOG(REQ, WARN, + "Set power mode error: Invalid BSS index(%u)\n", + prPowerMode->ucBssIdx); + return WLAN_STATUS_INVALID_DATA; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prPowerMode->ucBssIdx); + + if (prAdapter->fgEnCtiaPowerMode) { + if (prPowerMode->ePowerMode != Param_PowerModeCAM) { + /* User setting to PS mode (Param_PowerModeMAX_PSP or + * Param_PowerModeFast_PSP) + */ + + if (prAdapter->u4CtiaPowerMode == 0) + /* force to keep in CAM mode */ + prPowerMode->ePowerMode = Param_PowerModeCAM; + else if (prAdapter->u4CtiaPowerMode == 1) + prPowerMode->ePowerMode = + Param_PowerModeMAX_PSP; + else if (prAdapter->u4CtiaPowerMode == 2) + prPowerMode->ePowerMode = + Param_PowerModeFast_PSP; + } + } + + /* only CAM mode allowed when TP/Sigma on */ + if ((prAdapter->rWifiVar.ucTpTestMode == + ENUM_TP_TEST_MODE_THROUGHPUT) || + (prAdapter->rWifiVar.ucTpTestMode == + ENUM_TP_TEST_MODE_SIGMA_AC_N_PMF)) + prPowerMode->ePowerMode = Param_PowerModeCAM; + else if (prAdapter->rWifiVar.ePowerMode != + Param_PowerModeMax) + prPowerMode->ePowerMode = prAdapter->rWifiVar.ePowerMode; + + /* for WMM PS Sigma certification, keep WiFi in ps mode continuously */ + /* force PS == Param_PowerModeMAX_PSP */ + if ((prAdapter->rWifiVar.ucTpTestMode == + ENUM_TP_TEST_MODE_SIGMA_WMM_PS) && + (prPowerMode->ePowerMode >= Param_PowerModeMAX_PSP)) + prPowerMode->ePowerMode = Param_PowerModeMAX_PSP; + + status = nicConfigPowerSaveProfile(prAdapter, prPowerMode->ucBssIdx, + prPowerMode->ePowerMode, + TRUE, PS_CALLER_COMMON); + + if (prBssInfo->eNetworkType < 0 || + prBssInfo->eNetworkType >= NETWORK_TYPE_NUM) { + DBGLOG(INIT, WARN, + "Invalid eNetworkType: %d\n", + prBssInfo->eNetworkType); + } else if (prPowerMode->ePowerMode >= 0 && + prPowerMode->ePowerMode < Param_PowerModeMax) { + DBGLOG(INIT, TRACE, + "Set %s Network BSS(%u) PS mode to %s (%d)\n", + apucNetworkType[prBssInfo->eNetworkType], + prPowerMode->ucBssIdx, + apucPsMode[prPowerMode->ePowerMode], + prPowerMode->ePowerMode); + } else { + DBGLOG(INIT, TRACE, + "Invalid PS mode setting (%d) for %s Network BSS(%u)\n", + prPowerMode->ePowerMode, + apucNetworkType[prBssInfo->eNetworkType], + prPowerMode->ucBssIdx); + } + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryAdHocMode(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetAdHocMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryFrequency(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_INFO *prAisBssInfo; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + DEBUGFUNC("wlanoidQueryFrequency"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + prConnSettings = + aisGetConnSettings(prAdapter, ucBssIndex); + prAisBssInfo = + aisGetAisBssInfo(prAdapter, ucBssIndex); + + if (prConnSettings->eOPMode == + NET_TYPE_INFRA) { + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo, + ucBssIndex) == + MEDIA_STATE_CONNECTED) + *(uint32_t *) pvQueryBuffer = nicChannelNum2Freq( + prAisBssInfo->ucPrimaryChannel); + else + *(uint32_t *) pvQueryBuffer = 0; + } else + *(uint32_t *) pvQueryBuffer = nicChannelNum2Freq( + prConnSettings->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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetFrequency(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct CONNECTION_SETTINGS *prConnSettings; + uint32_t *pu4FreqInKHz; + uint8_t ucBssIndex = 0; + + DEBUGFUNC("wlanoidSetFrequency"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + + DBGLOG(REQ, LOUD, "ucBssIndex %d\n", ucBssIndex); + + prConnSettings = + aisGetConnSettings(prAdapter, ucBssIndex); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + pu4FreqInKHz = (uint32_t *) pvSetBuffer; + + prConnSettings->ucAdHocChannelNum = + (uint8_t) nicFreq2ChannelNum(*pu4FreqInKHz); + prConnSettings->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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetChannel(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryBeaconInterval(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct CONNECTION_SETTINGS *prConnSettings; + struct PARAM_BSSID_EX *prCurrBssid; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + DEBUGFUNC("wlanoidQueryBeaconInterval"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + prConnSettings = + aisGetConnSettings(prAdapter, ucBssIndex); + + prCurrBssid = aisGetCurrBssId(prAdapter, + ucBssIndex); + + *pu4QueryInfoLen = sizeof(uint32_t); + + if (u4QueryBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo, + ucBssIndex) == + MEDIA_STATE_CONNECTED) { + if (prConnSettings->eOPMode == NET_TYPE_INFRA) + *(uint32_t *) pvQueryBuffer = + prCurrBssid->rConfiguration + .u4BeaconPeriod; + else + *(uint32_t *) pvQueryBuffer = + (uint32_t)prAdapter->rWlanInfo.u2BeaconPeriod; + } else { + if (prConnSettings->eOPMode == + NET_TYPE_INFRA) + *(uint32_t *) pvQueryBuffer = 0; + else + *(uint32_t *) pvQueryBuffer = + (uint32_t)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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetBeaconInterval(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pu4BeaconInterval; + + DEBUGFUNC("wlanoidSetBeaconInterval"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(uint32_t); + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + pu4BeaconInterval = (uint32_t *) pvSetBuffer; + + if ((*pu4BeaconInterval < DOT11_BEACON_PERIOD_MIN) + || (*pu4BeaconInterval > DOT11_BEACON_PERIOD_MAX)) { + DBGLOG(REQ, TRACE, "Invalid Beacon Interval = %u\n", + *pu4BeaconInterval); + return WLAN_STATUS_INVALID_DATA; + } + + prAdapter->rWlanInfo.u2BeaconPeriod = (uint16_t) * + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryAtimWindow(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct CONNECTION_SETTINGS *prConnSettings; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + DEBUGFUNC("wlanoidQueryAtimWindow"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + prConnSettings = + aisGetConnSettings(prAdapter, ucBssIndex); + + *pu4QueryInfoLen = sizeof(uint32_t); + + if (u4QueryBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prConnSettings->eOPMode == NET_TYPE_INFRA) + *(uint32_t *) pvQueryBuffer = 0; + else + *(uint32_t *) pvQueryBuffer = (uint32_t) + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetAtimWindow(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pu4AtimWindow; + + DEBUGFUNC("wlanoidSetAtimWindow"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + pu4AtimWindow = (uint32_t *) pvSetBuffer; + + prAdapter->rWlanInfo.u2AtimWindow = (uint16_t) * + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetCurrentAddr(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetCSUMOffload(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t u4CSUMFlags; + struct CMD_BASIC_CONFIG rCmdBasicConfig; + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; + + DEBUGFUNC("wlanoidSetCSUMOffload"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + u4CSUMFlags = *(uint32_t *) pvSetBuffer; + + kalMemZero(&rCmdBasicConfig, + sizeof(struct CMD_BASIC_CONFIG)); + + 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; + rCmdBasicConfig.ucCtrlFlagAssertPath = + prWifiVar->ucCtrlFlagAssertPath; + rCmdBasicConfig.ucCtrlFlagDebugLevel = + prWifiVar->ucCtrlFlagDebugLevel; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_BASIC_CONFIG, + TRUE, + FALSE, + TRUE, + NULL, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_BASIC_CONFIG), + (uint8_t *) &rCmdBasicConfig, + pvSetBuffer, u4SetBufferLen); + + return WLAN_STATUS_SUCCESS; +} +#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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetNetworkAddress(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t i, u4IPv4AddrIdx; + struct CMD_SET_NETWORK_ADDRESS_LIST + *prCmdNetworkAddressList; + struct PARAM_NETWORK_ADDRESS_LIST *prNetworkAddressList = + (struct PARAM_NETWORK_ADDRESS_LIST *) pvSetBuffer; + struct PARAM_NETWORK_ADDRESS *prNetworkAddress; + uint32_t u4IPv4AddrCount, u4CmdSize; +#if CFG_ENABLE_GTK_FRAME_FILTER + uint32_t u4IpV4AddrListSize; + struct BSS_INFO *prBssInfo; +#endif + + DEBUGFUNC("wlanoidSetNetworkAddress"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 4; + + if (u4SetBufferLen < OFFSET_OF(struct + PARAM_NETWORK_ADDRESS_LIST, arAddress)) + return WLAN_STATUS_INVALID_DATA; + + *pu4SetInfoLen = 0; + u4IPv4AddrCount = 0; + + /* 4 <1.1> Get IPv4 address count */ + /* We only suppot IPv4 address setting */ + prNetworkAddress = prNetworkAddressList->arAddress; + for (i = 0; i < prNetworkAddressList->u4AddressCount; i++) { + if ((prNetworkAddress->u2AddressType == + PARAM_PROTOCOL_ID_TCP_IP) && + (prNetworkAddress->u2AddressLength == IPV4_ADDR_LEN)) { + u4IPv4AddrCount++; + } + + prNetworkAddress = (struct PARAM_NETWORK_ADDRESS *) + ((unsigned long) prNetworkAddress + + (unsigned long) (prNetworkAddress->u2AddressLength*2 + + OFFSET_OF(struct PARAM_NETWORK_ADDRESS, aucAddress))); + } + + /* 4 <2> Calculate command buffer size */ + /* construct payload of command packet */ + if (u4IPv4AddrCount == 0) + u4CmdSize = sizeof(struct CMD_SET_NETWORK_ADDRESS_LIST); + else + u4CmdSize = + OFFSET_OF(struct CMD_SET_NETWORK_ADDRESS_LIST, + arNetAddress) + + (sizeof(struct CMD_IPV4_NETWORK_ADDRESS) * + u4IPv4AddrCount); + + /* 4 <3> Allocate command buffer */ + prCmdNetworkAddressList = (struct CMD_SET_NETWORK_ADDRESS_LIST *) + kalMemAlloc(u4CmdSize, VIR_MEM_TYPE); + + if (prCmdNetworkAddressList == NULL) + return WLAN_STATUS_FAILURE; + + kalMemZero(prCmdNetworkAddressList, u4CmdSize); + prCmdNetworkAddressList->ucVersion = 1; +#if CFG_ENABLE_GTK_FRAME_FILTER + u4IpV4AddrListSize = + OFFSET_OF(struct IPV4_NETWORK_ADDRESS_LIST, arNetAddr) + + (u4IPv4AddrCount * + sizeof(struct CMD_IPV4_NETWORK_ADDRESS)); + prBssInfo = aisGetAisBssInfo(prAdapter, + prNetworkAddressList->ucBssIdx); + if (prBssInfo->prIpV4NetAddrList) + FREE_IPV4_NETWORK_ADDR_LIST(prBssInfo->prIpV4NetAddrList); + prBssInfo->prIpV4NetAddrList = + (struct IPV4_NETWORK_ADDRESS_LIST *) + kalMemAlloc(u4IpV4AddrListSize, + VIR_MEM_TYPE); + prBssInfo->prIpV4NetAddrList->ucAddrCount = + (uint8_t) u4IPv4AddrCount; +#endif + + /* 4 <4> Fill P_CMD_SET_NETWORK_ADDRESS_LIST */ + prCmdNetworkAddressList->ucBssIndex = + prNetworkAddressList->ucBssIdx; + + /* only to set IP address to FW once ARP filter is enabled */ + if (prAdapter->fgEnArpFilter) { + prCmdNetworkAddressList->ucAddressCount = + (uint8_t) u4IPv4AddrCount; + prNetworkAddress = prNetworkAddressList->arAddress; + + /* DBGLOG(INIT, INFO, ("%s: u4IPv4AddrCount (%lu)\n", + * __FUNCTION__, u4IPv4AddrCount)); + */ + + for (i = 0, u4IPv4AddrIdx = 0; + i < prNetworkAddressList->u4AddressCount; i++) { + if (prNetworkAddress->u2AddressType == + PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == + IPV4_ADDR_LEN) { + + kalMemCopy(prCmdNetworkAddressList-> + arNetAddress[u4IPv4AddrIdx].aucIpAddr, + prNetworkAddress->aucAddress, + sizeof(uint32_t)); + kalMemCopy(prCmdNetworkAddressList-> + arNetAddress[u4IPv4AddrIdx].aucIpMask, + prNetworkAddress-> + aucAddress+sizeof(uint32_t), + sizeof(uint32_t)); +#if CFG_ENABLE_GTK_FRAME_FILTER + kalMemCopy(prBssInfo->prIpV4NetAddrList-> + arNetAddr[u4IPv4AddrIdx].aucIpAddr, + prNetworkAddress->aucAddress, + sizeof(uint32_t)); +#endif + + DBGLOG(OID, INFO, + "%s:IPv4 Addr[%u]["IPV4STR"]Mask["IPV4STR"]\n", + __func__, + u4IPv4AddrIdx, + IPV4TOSTR(prNetworkAddress->aucAddress), + IPV4TOSTR(prNetworkAddress-> + aucAddress+sizeof(uint32_t))); + + u4IPv4AddrIdx++; + } + + prNetworkAddress = (struct PARAM_NETWORK_ADDRESS *) + ((unsigned long)prNetworkAddress + + (unsigned long)(prNetworkAddress-> + u2AddressLength*2 + + OFFSET_OF(struct PARAM_NETWORK_ADDRESS, + aucAddress))); + } + + } else { + prCmdNetworkAddressList->ucAddressCount = 0; + } + + DBGLOG(OID, INFO, + "%s: Set %u IPv4 address for BSS[%d] ver[%d]\n", __func__, + u4IPv4AddrCount, + prCmdNetworkAddressList->ucBssIndex, + prCmdNetworkAddressList->ucVersion); + + /* 4 <5> Send command */ + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_IP_ADDRESS, + TRUE, + FALSE, + TRUE, + nicCmdEventSetIpAddress, + nicOidCmdTimeoutCommon, + u4CmdSize, + (uint8_t *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidRftestSetTestMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t rStatus; + struct CMD_TEST_CTRL rCmdTestCtrl; + + DEBUGFUNC("wlanoidRftestSetTestMode"); + + ASSERT(prAdapter); + 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_CTRL, + TRUE, + FALSE, + TRUE, + nicCmdEventEnterRfTest, + nicOidCmdEnterRFTestTimeout, + sizeof(struct CMD_TEST_CTRL), + (uint8_t *) &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 RF test ICAP 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidRftestSetTestIcapMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t rStatus; + struct CMD_TEST_CTRL rCmdTestCtrl; + struct ICAP_INFO_T *prIcapInfo = NULL; + + DEBUGFUNC("wlanoidRftestSetTestIcapMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + prIcapInfo = &prAdapter->rIcapInfo; + ASSERT(prIcapInfo); + + *pu4SetInfoLen = 0; + + if (u4SetBufferLen == 0) { + if (prIcapInfo->eIcapState == ICAP_STATE_INIT) { + /* switch to RF Test mode */ + rCmdTestCtrl.ucAction = 0; /* Switch mode */ + rCmdTestCtrl.u.u4OpMode = 2; /* ICAP mode */ + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_TEST_CTRL, + TRUE, + FALSE, + TRUE, + nicCmdEventEnterRfTest, + nicOidCmdEnterRFTestTimeout, + sizeof(struct CMD_TEST_CTRL), + (uint8_t *) &rCmdTestCtrl, + pvSetBuffer, u4SetBufferLen); + } else { + /* already in ICAP mode .. */ + DBGLOG(RFTEST, WARN, + "Switch ICAP FAil in State(%d)\n", + prIcapInfo->eIcapState); + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidRftestSetAbortTestMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t rStatus; + struct CMD_TEST_CTRL rCmdTestCtrl; + + DEBUGFUNC("wlanoidRftestSetAbortTestMode"); + + ASSERT(prAdapter); + 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_CTRL, + TRUE, + FALSE, + TRUE, + nicCmdEventLeaveRfTest, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_TEST_CTRL), + (uint8_t *) &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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidRftestQueryAutoTest(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_MTK_WIFI_TEST_STRUCT *prRfATInfo; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidRftestQueryAutoTest"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(struct + PARAM_MTK_WIFI_TEST_STRUCT); + +#if 0 /* PeiHsuan Temp Remove this check for workaround Gen2/Gen3 EM Mode + * Modification + */ + if (u4QueryBufferLen != sizeof(struct PARAM_MTK_WIFI_TEST_STRUCT)) { + DBGLOG(REQ, ERROR, "Invalid data. QueryBufferLen: %ld.\n", + u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } +#endif + + prRfATInfo = (struct PARAM_MTK_WIFI_TEST_STRUCT *) + pvQueryBuffer; + + DBGLOG(RFTEST, INFO, + "Get AT_CMD BufferLen = %d, AT Index = %d, Data = %d\n", + u4QueryBufferLen, + prRfATInfo->u4FuncIndex, + prRfATInfo->u4FuncData); + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidRftestSetAutoTest(IN struct ADAPTER *prAdapter, + OUT void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_MTK_WIFI_TEST_STRUCT *prRfATInfo; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidRftestSetAutoTest"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_MTK_WIFI_TEST_STRUCT); + +#if 0 /* PeiHsuan Temp Remove this check for workaround Gen2/Gen3 EM Mode + * Modification + */ + if (u4SetBufferLen != sizeof(struct + PARAM_MTK_WIFI_TEST_STRUCT)) { + DBGLOG(REQ, ERROR, "Invalid data. SetBufferLen: %ld.\n", + u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } +#endif + + prRfATInfo = (struct PARAM_MTK_WIFI_TEST_STRUCT *) + pvSetBuffer; + + DBGLOG(RFTEST, INFO, + "Set AT_CMD BufferLen = %d, AT Index = %d, Data = %d\n", + u4SetBufferLen, + prRfATInfo->u4FuncIndex, + prRfATInfo->u4FuncData); + + rStatus = rftestSetATInfo(prAdapter, + prRfATInfo->u4FuncIndex, prRfATInfo->u4FuncData); + + return rStatus; +} + +/* RF test OID set handler */ +uint32_t rftestSetATInfo(IN struct ADAPTER *prAdapter, + uint32_t u4FuncIndex, uint32_t u4FuncData) { + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + struct CMD_TEST_CTRL *pCmdTestCtrl; + struct mt66xx_chip_info *prChipInfo; + uint16_t cmd_size; + + ASSERT(prAdapter); + + prChipInfo = prAdapter->chip_info; + prGlueInfo = prAdapter->prGlueInfo; + cmd_size = prChipInfo->u2CmdTxHdrSize + sizeof(struct CMD_TEST_CTRL); + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, cmd_size); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = cmd_size; + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_TEST_CTRL; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->u4SetInfoLen = sizeof(struct CMD_TEST_CTRL); + prCmdInfo->pvInformationBuffer = NULL; + prCmdInfo->u4InformationBufferLength = 0; + + /* Setup WIFI_CMD_T (payload = CMD_TEST_CTRL_T) */ + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + prCmdInfo->ucCID, + CMD_PACKET_TYPE_ID, + &prCmdInfo->ucCmdSeqNum, + prCmdInfo->fgSetQuery, + &pCmdTestCtrl, FALSE, 0, S2D_INDEX_CMD_H2N); + pCmdTestCtrl->ucAction = 1; /* Set ATInfo */ + pCmdTestCtrl->u.rRfATInfo.u4FuncIndex = u4FuncIndex; + pCmdTestCtrl->u.rRfATInfo.u4FuncData = u4FuncData; + + if ((u4FuncIndex == RF_AT_FUNCID_COMMAND) + && (u4FuncData == RF_AT_COMMAND_ICAP)) + prAdapter->rIcapInfo.eIcapState = ICAP_STATE_START; + + /* ICAP dump name Reset */ + if ((u4FuncIndex == RF_AT_FUNCID_COMMAND) + && (u4FuncData == RF_AT_COMMAND_RESET_DUMP_NAME)) + prAdapter->rIcapInfo.u2DumpIndex = 0; + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, + (struct QUE_ENTRY *) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prAdapter->prGlueInfo); + + return WLAN_STATUS_PENDING; +} + +uint32_t wlanoidExtRfTestICapStart(IN struct ADAPTER *prAdapter, + OUT void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct CMD_TEST_CTRL_EXT_T rCmdTestCtrl; + struct RBIST_CAP_START_T *prCmdICapInfo; + struct PARAM_MTK_WIFI_TEST_STRUCT_EXT_T *prRfATInfo; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidExtRfTestICapStart"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct + PARAM_MTK_WIFI_TEST_STRUCT_EXT_T); + + prRfATInfo = (struct PARAM_MTK_WIFI_TEST_STRUCT_EXT_T *) + pvSetBuffer; + + DBGLOG(RFTEST, INFO, + "Set AT_CMD BufferLen = %d, AT Index = %d\n", + u4SetBufferLen, + prRfATInfo->u4FuncIndex); + + rCmdTestCtrl.ucAction = ACTION_IN_RFTEST; + rCmdTestCtrl.u.rRfATInfo.u4FuncIndex = + SET_ICAP_CAPTURE_START; + + prCmdICapInfo = &(rCmdTestCtrl.u.rRfATInfo.Data.rICapInfo); + kalMemCopy(prCmdICapInfo, &(prRfATInfo->Data.rICapInfo), + sizeof(struct RBIST_CAP_START_T)); + + if (prCmdICapInfo->u4Trigger == TRUE) + prAdapter->rIcapInfo.eIcapState = ICAP_STATE_START; + else + /* ICAP STOP, reset state to INIT state*/ + prAdapter->rIcapInfo.eIcapState = ICAP_STATE_INIT; + + rStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_RF_TEST, + TRUE, /* Query Bit: True->write False->read */ + FALSE,/*fgNeedRsp*/ + TRUE, /*fgIsOid*/ + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_TEST_CTRL_EXT_T), + (uint8_t *)&rCmdTestCtrl, pvSetBuffer, + u4SetBufferLen); + return rStatus; +} + +uint32_t wlanoidExtRfTestICapStatus(IN struct ADAPTER *prAdapter, + OUT void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct CMD_TEST_CTRL_EXT_T rCmdTestCtrl; + struct RBIST_CAP_START_T *prCmdICapInfo; + struct PARAM_MTK_WIFI_TEST_STRUCT_EXT_T *prRfATInfo; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidExtRfTestICapStatus"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct + PARAM_MTK_WIFI_TEST_STRUCT_EXT_T); + + prRfATInfo = (struct PARAM_MTK_WIFI_TEST_STRUCT_EXT_T *) + pvSetBuffer; + + DBGLOG(RFTEST, INFO, + "Set AT_CMD BufferLen = %d, AT Index = %d\n", + u4SetBufferLen, + prRfATInfo->u4FuncIndex); + + rCmdTestCtrl.ucAction = ACTION_IN_RFTEST; + rCmdTestCtrl.u.rRfATInfo.u4FuncIndex = + GET_ICAP_CAPTURE_STATUS; + + + prAdapter->rIcapInfo.eIcapState = ICAP_STATE_QUERY_STATUS; + + + prCmdICapInfo = &(rCmdTestCtrl.u.rRfATInfo.Data.rICapInfo); + kalMemCopy(prCmdICapInfo, &(prRfATInfo->Data.rICapInfo), + sizeof(struct RBIST_CAP_START_T)); + + rStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_RF_TEST, + FALSE, /* Query Bit: True->write False->read */ + TRUE, + TRUE, + NULL, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_TEST_CTRL_EXT_T), + (uint8_t *)(&rCmdTestCtrl), pvSetBuffer, + u4SetBufferLen); + return rStatus; +} + +void wlanoidRfTestICapRawDataProc(IN struct ADAPTER * + prAdapter, uint32_t u4CapStartAddr, + uint32_t u4TotalBufferSize) { + struct CMD_TEST_CTRL_EXT_T rCmdTestCtrl; + struct PARAM_MTK_WIFI_TEST_STRUCT_EXT_T *prRfATInfo; + uint32_t u4SetBufferLen = 0; + void *pvSetBuffer = NULL; + int32_t rStatus; + + ASSERT(prAdapter); + + prRfATInfo = &(rCmdTestCtrl.u.rRfATInfo); + + rCmdTestCtrl.ucAction = ACTION_IN_RFTEST; + prRfATInfo->u4FuncIndex = GET_ICAP_RAW_DATA; + prRfATInfo->Data.rICapDump.u4Address = u4CapStartAddr; + prRfATInfo->Data.rICapDump.u4AddrOffset = 0x04; + prRfATInfo->Data.rICapDump.u4Bank = 1; + prRfATInfo->Data.rICapDump.u4BankSize = u4TotalBufferSize; + + rStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_RF_TEST, + FALSE, /* Query Bit: True->write False->read */ + TRUE, + FALSE, /*fgIsOid = FALSE, main thread trigger*/ + NULL, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_TEST_CTRL_EXT_T), + (uint8_t *)(&rCmdTestCtrl), + pvSetBuffer, u4SetBufferLen); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief wifi driver response IQ data for QA agent + * + * \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 + */ +/*----------------------------------------------------------------------------*/ + +uint32_t wlanoidRfTestICapGetIQData(IN struct ADAPTER *prAdapter, + OUT void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct _RBIST_IQ_DATA_T *prIQArray = NULL; + struct ICAP_INFO_T *prICapInfo = NULL; + struct RBIST_DUMP_IQ_T *prRbistDump = NULL; + int32_t i = 0; + uint32_t u4MaxIQDataCount = 0; + uint32_t u4DumpIndex = 0; + uint32_t u4Value, u4DataLen = 0; + uint32_t u4WFNum = 0, u4IQType = 0; + uint8_t *pData; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prICapInfo = &prAdapter->rIcapInfo; + prIQArray = prICapInfo->prIQArray; + prRbistDump = (struct RBIST_DUMP_IQ_T *)pvSetBuffer; + u4WFNum = prRbistDump->u4WfNum; + u4IQType = prRbistDump->u4IQType; + pData = prRbistDump->pucIcapData; + + u4DumpIndex = prICapInfo->au4ICapDumpIndex[u4WFNum][u4IQType]; + + prICapInfo->eIcapState = ICAP_STATE_QA_TOOL_CAPTURE; + + + + /* 1. Maximum 1KB = ICAP_EVENT_DATA_SAMPLE (256) slots */ + u4MaxIQDataCount = prICapInfo->u4IQArrayIndex - u4DumpIndex; + if (u4MaxIQDataCount > ICAP_EVENT_DATA_SAMPLE) + u4MaxIQDataCount = ICAP_EVENT_DATA_SAMPLE; + + /* 2. update IQ Sample Count*/ + prRbistDump->u4IcapCnt = u4MaxIQDataCount; + + /* 3. Copy to buffer */ + for (i = 0; i < u4MaxIQDataCount; i++) { + u4Value = prIQArray[u4DumpIndex++].u4IQArray[u4WFNum][u4IQType]; + kalMemCopy(pData + u4DataLen, (uint8_t *) &u4Value, + sizeof(u4Value)); + u4DataLen += sizeof(u4Value); + } + + /* 4. update response IQ data length */ + prRbistDump->u4IcapDataLen = u4DataLen; + + + prICapInfo->au4ICapDumpIndex[u4WFNum][u4IQType] = u4DumpIndex; + + DBGLOG(RFTEST, INFO, "CurrICapDumpIndex[WF%d][%c]=%d,IQCnt=%d,len=%d\n", + u4WFNum, + (u4IQType == CAP_I_TYPE) ? + 'I' : 'Q', + u4DumpIndex, + u4MaxIQDataCount, + u4DataLen); + + return rStatus; +} +uint32_t +rftestQueryATInfo(IN struct ADAPTER *prAdapter, + uint32_t u4FuncIndex, uint32_t u4FuncData, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen) { + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + struct CMD_TEST_CTRL *pCmdTestCtrl; + union EVENT_TEST_STATUS *prTestStatus; + struct mt66xx_chip_info *prChipInfo; + uint16_t cmd_size; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + prChipInfo = prAdapter->chip_info; + + if (u4FuncIndex == RF_AT_FUNCID_FW_INFO) { + /* driver implementation */ + prTestStatus = (union EVENT_TEST_STATUS *) pvQueryBuffer; + + prTestStatus->rATInfo.u4FuncData = + (prAdapter->chip_info->em_interface_version << 16) | + (prAdapter->rVerInfo.u2FwOwnVersion); + + DBGLOG(RFTEST, INFO, "RF_AT_FUNCID_FW_INFO=0x%x\n", + prTestStatus->rATInfo.u4FuncData); + + u4QueryBufferLen = sizeof(union EVENT_TEST_STATUS); + + return WLAN_STATUS_SUCCESS; + } else if (u4FuncIndex == RF_AT_FUNCID_DRV_INFO) { + /* driver implementation */ + prTestStatus = (union EVENT_TEST_STATUS *) pvQueryBuffer; + + prTestStatus->rATInfo.u4FuncData = CFG_DRV_OWN_VERSION; + u4QueryBufferLen = sizeof(union EVENT_TEST_STATUS); + + return WLAN_STATUS_SUCCESS; + } else if (u4FuncIndex == + RF_AT_FUNCID_QUERY_ICAP_DUMP_FILE) { + /* driver implementation */ + prTestStatus = (union EVENT_TEST_STATUS *) pvQueryBuffer; + + prTestStatus->rATInfo.u4FuncData = + prAdapter->rIcapInfo.u2DumpIndex; + u4QueryBufferLen = sizeof(union EVENT_TEST_STATUS); + + return WLAN_STATUS_SUCCESS; + } + + cmd_size = prChipInfo->u2CmdTxHdrSize + sizeof(struct CMD_TEST_CTRL); + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, cmd_size); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = cmd_size; + prCmdInfo->pfCmdDoneHandler = nicCmdEventQueryRfTestATInfo; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_TEST_CTRL; + prCmdInfo->fgSetQuery = FALSE; + prCmdInfo->fgNeedResp = TRUE; + prCmdInfo->u4SetInfoLen = sizeof(struct CMD_TEST_CTRL); + prCmdInfo->pvInformationBuffer = pvQueryBuffer; + prCmdInfo->u4InformationBufferLength = u4QueryBufferLen; + + /* Setup WIFI_CMD_T (payload = CMD_TEST_CTRL_T) */ + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + prCmdInfo->ucCID, + CMD_PACKET_TYPE_ID, + &prCmdInfo->ucCmdSeqNum, + prCmdInfo->fgSetQuery, + &pCmdTestCtrl, FALSE, 0, S2D_INDEX_CMD_H2N); + pCmdTestCtrl->ucAction = 2; /* Get ATInfo */ + pCmdTestCtrl->u.rRfATInfo.u4FuncIndex = u4FuncIndex; + pCmdTestCtrl->u.rRfATInfo.u4FuncData = u4FuncData; + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, + (struct QUE_ENTRY *) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prAdapter->prGlueInfo); + + return WLAN_STATUS_PENDING; + +} + +uint32_t rftestSetFrequency(IN struct ADAPTER *prAdapter, + IN uint32_t u4FreqInKHz, + IN uint32_t *pu4SetInfoLen) { + struct CMD_TEST_CTRL rCmdTestCtrl; + + ASSERT(prAdapter); + + rCmdTestCtrl.ucAction = 5; /* Set Channel Frequency */ + rCmdTestCtrl.u.u4ChannelFreq = u4FreqInKHz; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_TEST_CTRL, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_TEST_CTRL), + (uint8_t *) &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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanSendSetQueryCmd(IN struct ADAPTER *prAdapter, + uint8_t ucCID, + u_int8_t fgSetQuery, + u_int8_t fgNeedResp, + u_int8_t fgIsOid, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + uint32_t u4SetQueryInfoLen, + uint8_t *pucInfoBuffer, OUT void *pvSetQueryBuffer, + IN uint32_t u4SetQueryBufferLen) { + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + uint8_t *pucCmfBuf; + struct mt66xx_chip_info *prChipInfo; + uint16_t cmd_size; + + if (kalIsResetting()) { + DBGLOG(INIT, WARN, "Chip resetting, skip\n"); + return WLAN_STATUS_FAILURE; + } + + prGlueInfo = prAdapter->prGlueInfo; + prChipInfo = prAdapter->chip_info; + cmd_size = prChipInfo->u2CmdTxHdrSize + u4SetQueryInfoLen; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, cmd_size); + DEBUGFUNC("wlanSendSetQueryCmd"); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T FAILED ID[0x%x]\n", + ucCID); + return WLAN_STATUS_FAILURE; + } + + /* Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->u2InfoBufLen = cmd_size; + prCmdInfo->pfCmdDoneHandler = pfCmdDoneHandler; + prCmdInfo->pfCmdTimeoutHandler = pfCmdTimeoutHandler; + prCmdInfo->fgIsOid = fgIsOid; + prCmdInfo->ucCID = ucCID; + prCmdInfo->fgSetQuery = fgSetQuery; + prCmdInfo->fgNeedResp = fgNeedResp; + prCmdInfo->u4SetInfoLen = u4SetQueryInfoLen; + prCmdInfo->pvInformationBuffer = pvSetQueryBuffer; + prCmdInfo->u4InformationBufferLength = u4SetQueryBufferLen; + + /* Setup WIFI_CMD_T (no payload) */ + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + prCmdInfo->ucCID, + CMD_PACKET_TYPE_ID, + &prCmdInfo->ucCmdSeqNum, + prCmdInfo->fgSetQuery, + &pucCmfBuf, FALSE, 0, S2D_INDEX_CMD_H2N); + if (u4SetQueryInfoLen > 0 && pucInfoBuffer != NULL) + kalMemCopy(pucCmfBuf, pucInfoBuffer, + u4SetQueryInfoLen); + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, + (struct QUE_ENTRY *) 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 + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetWapiMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *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 (*(uint32_t *) 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->ucBssIndex = AIS_DEFAULT_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 = (struct WIFI_CMD *) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + cp = (uint8_t *) (prWifiCmd->aucBuffer); + + kalMemCopy(cp, (uint8_t *) pvSetBuffer, 4); + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, + (struct QUE_ENTRY *) 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 + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetWapiAssocInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct WAPI_INFO_ELEM *prWapiInfo; + struct CONNECTION_SETTINGS *prConnSettings; + uint8_t ucBssIndex = 0; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + DEBUGFUNC("wlanoidSetWapiAssocInfo"); + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + + DBGLOG(REQ, LOUD, "ucBssIndex %d\n", ucBssIndex); + + prConnSettings = + aisGetConnSettings(prAdapter, ucBssIndex); + + prConnSettings->fgWapiMode = FALSE; + + if (u4SetBufferLen < 20 /* From EID to Group cipher */) + return WLAN_STATUS_INVALID_LENGTH; + + if (!wextSrchDesiredWAPIIE((uint8_t *) pvSetBuffer, + u4SetBufferLen, (uint8_t **) &prWapiInfo)) + return WLAN_STATUS_INVALID_LENGTH; + + if (!prWapiInfo || prWapiInfo->ucLength < 18) + return WLAN_STATUS_INVALID_LENGTH; + + /* Skip Version check */ + + /*Cipher suite count check, only one of each for now*/ + if (prWapiInfo->u2AKMSuiteCount > 1 || + prWapiInfo->u2PairSuiteCount > 1) + return WLAN_STATUS_INVALID_LENGTH; + + DBGLOG(SEC, TRACE, + "WAPI: Assoc Info auth mgt suite [%d]: %02x-%02x-%02x-%02x\n", + prWapiInfo->u2AKMSuiteCount, + (uint8_t) (prWapiInfo->u4AKMSuite & 0x000000FF), + (uint8_t) ((prWapiInfo->u4AKMSuite >> 8) & 0x000000FF), + (uint8_t) ((prWapiInfo->u4AKMSuite >> 16) & 0x000000FF), + (uint8_t) ((prWapiInfo->u4AKMSuite >> 24) & 0x000000FF)); + + if (prWapiInfo->u4AKMSuite != WAPI_AKM_SUITE_802_1X + && prWapiInfo->u4AKMSuite != WAPI_AKM_SUITE_PSK) + return WLAN_STATUS_NOT_SUPPORTED; + + DBGLOG(SEC, TRACE, + "WAPI: Assoc Info pairwise cipher suite [%d]: %02x-%02x-%02x-%02x\n", + prWapiInfo->u2PairSuiteCount, + (uint8_t) (prWapiInfo->u4PairSuite & 0x000000FF), + (uint8_t) ((prWapiInfo->u4PairSuite >> 8) & 0x000000FF), + (uint8_t) ((prWapiInfo->u4PairSuite >> 16) & 0x000000FF), + (uint8_t) ((prWapiInfo->u4PairSuite >> 24) & 0x000000FF)); + + if (prWapiInfo->u4PairSuite != WAPI_CIPHER_SUITE_WPI) + return WLAN_STATUS_NOT_SUPPORTED; + + DBGLOG(SEC, TRACE, + "WAPI: Assoc Info group cipher suite : %02x-%02x-%02x-%02x\n", + (uint8_t) (prWapiInfo->u4GroupSuite & 0x000000FF), + (uint8_t) ((prWapiInfo->u4GroupSuite >> 8) & 0x000000FF), + (uint8_t) ((prWapiInfo->u4GroupSuite >> 16) & 0x000000FF), + (uint8_t) ((prWapiInfo->u4GroupSuite >> 24) & 0x000000FF)); + + if (prWapiInfo->u4GroupSuite != WAPI_CIPHER_SUITE_WPI) + return WLAN_STATUS_NOT_SUPPORTED; + + prConnSettings->u4WapiSelectedAKMSuite + = prWapiInfo->u4AKMSuite; + prConnSettings->u4WapiSelectedPairwiseCipher + = prWapiInfo->u4PairSuite; + prConnSettings->u4WapiSelectedGroupCipher + = prWapiInfo->u4GroupSuite; + + prConnSettings->fgWapiMode = TRUE; + + 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetWapiKey(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + struct PARAM_WPI_KEY *prNewKey; + struct CMD_802_11_KEY *prCmdKey; + uint8_t *pc; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + struct mt66xx_chip_info *prChipInfo; + uint16_t cmd_size; + uint8_t ucBssIndex = 0; + + DEBUGFUNC("wlanoidSetWapiKey"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + prChipInfo = prAdapter->chip_info; + + 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 = (struct PARAM_WPI_KEY *) pvSetBuffer; + + ucBssIndex = prNewKey->ucBssIdx; + DBGLOG(REQ, LOUD, "ucBssIndex %d\n", ucBssIndex); + + DBGLOG_MEM8(REQ, TRACE, (uint8_t *) pvSetBuffer, 560); + pc = (uint8_t *) pvSetBuffer; + + *pu4SetInfoLen = u4SetBufferLen; + + /* Todo:: WAPI AP mode !!!!! */ + prBssInfo = + aisGetAisBssInfo(prAdapter, ucBssIndex); + + prNewKey->ucKeyID = prNewKey->ucKeyID & BIT(0); + + /* 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, (uint8_t *) prNewKey->aucWPIEK, + (uint8_t) prNewKey->u4LenWPIEK); + prNewKey->u4LenWPICK = 16; + + DBGLOG(REQ, TRACE, "CK Key(%d):\r\n", + (uint8_t) prNewKey->u4LenWPICK); + DBGLOG_MEM8(REQ, TRACE, (uint8_t *) prNewKey->aucWPICK, + (uint8_t) 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, (uint8_t *) prNewKey->aucPN, 16); + + prGlueInfo = prAdapter->prGlueInfo; + + cmd_size = prChipInfo->u2CmdTxHdrSize + u4SetBufferLen; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, cmd_size); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* compose CMD_ID_ADD_REMOVE_KEY cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->u2InfoBufLen = cmd_size; + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_ADD_REMOVE_KEY; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->u4SetInfoLen = u4SetBufferLen; + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + + /* Setup WIFI_CMD_T */ + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + prCmdInfo->ucCID, + CMD_PACKET_TYPE_ID, + &prCmdInfo->ucCmdSeqNum, + prCmdInfo->fgSetQuery, &prCmdKey, FALSE, 0, S2D_INDEX_CMD_H2N); + + kalMemZero(prCmdKey, sizeof(struct CMD_802_11_KEY)); + + prCmdKey->ucAddRemove = 1; /* Add */ + + if (prNewKey->eKeyType == ENUM_WPI_PAIRWISE_KEY) { + prCmdKey->ucTxKey = 1; + prCmdKey->ucKeyType = 1; + } + kalMemCopy(prCmdKey->aucPeerAddr, + (uint8_t *) prNewKey->aucAddrIndex, MAC_ADDR_LEN); + if ((prCmdKey->aucPeerAddr[0] & prCmdKey->aucPeerAddr[1] & + prCmdKey->aucPeerAddr[2] & + prCmdKey->aucPeerAddr[3] & prCmdKey->aucPeerAddr[4] & + prCmdKey->aucPeerAddr[5]) == 0xFF) { + prStaRec = cnmGetStaRecByAddress(prAdapter, + prBssInfo->ucBssIndex, prBssInfo->aucBSSID); + ASSERT(prStaRec); /* AIS RSN Group key, addr is BC addr */ + kalMemCopy(prCmdKey->aucPeerAddr, prStaRec->aucMacAddr, + MAC_ADDR_LEN); + } else { + prStaRec = cnmGetStaRecByAddress(prAdapter, + prBssInfo->ucBssIndex, prCmdKey->aucPeerAddr); + } + + prCmdKey->ucBssIdx = + prBssInfo->ucBssIndex; /* AIS */ + + prCmdKey->ucKeyId = prNewKey->ucKeyID; + + prCmdKey->ucKeyLen = 32; + + prCmdKey->ucAlgorithmId = CIPHER_SUITE_WPI; + + kalMemCopy(prCmdKey->aucKeyMaterial, + (uint8_t *) prNewKey->aucWPIEK, 16); + + kalMemCopy(prCmdKey->aucKeyMaterial + 16, + (uint8_t *) prNewKey->aucWPICK, 16); + + kalMemCopy(prCmdKey->aucKeyRsc, (uint8_t *) prNewKey->aucPN, + 16); + + if (prCmdKey->ucTxKey) { + if (prStaRec) { + if (prCmdKey->ucKeyType) { /* AIS RSN STA */ + prCmdKey->ucWlanIndex = prStaRec->ucWlanIndex; + prStaRec->fgTransmitKeyExist = + TRUE; /* wait for CMD Done ? */ + } else { + ASSERT(FALSE); + } + } +#if 0 + if (fgAddTxBcKey || !prStaRec) { + + if ((prCmdKey->aucPeerAddr[0] + & prCmdKey->aucPeerAddr[1] + & prCmdKey->aucPeerAddr[2] + & prCmdKey->aucPeerAddr[3] + & prCmdKey->aucPeerAddr[4] + & prCmdKey->aucPeerAddr[5]) == 0xFF) { + prCmdKey->ucWlanIndex = + 255; /* AIS WEP Tx key */ + } else { /* Exist this case ? */ + ASSERT(FALSE); + /* prCmdKey->ucWlanIndex = */ + /* secPrivacySeekForBcEntry(prAdapter, */ + /* prBssInfo->ucBssIndex, */ + /* NETWORK_TYPE_AIS, */ + /* prCmdKey->aucPeerAddr, */ + /* prCmdKey->ucAlgorithmId, */ + /* prCmdKey->ucKeyId, */ + } + + prBssInfo->fgBcDefaultKeyExist = TRUE; + prBssInfo->ucBMCWlanIndex = + prCmdKey->ucWlanIndex; /* Saved for AIS WEP */ + prBssInfo->ucTxBcDefaultIdx = prCmdKey->ucKeyId; + } +#endif + } else { + /* Including IBSS RSN Rx BC key ? */ + if ((prCmdKey->aucPeerAddr[0] & prCmdKey->aucPeerAddr[1] & + prCmdKey->aucPeerAddr[2] & prCmdKey->aucPeerAddr[3] & + prCmdKey->aucPeerAddr[4] & prCmdKey->aucPeerAddr[5]) == + 0xFF) { + prCmdKey->ucWlanIndex = + WTBL_RESERVED_ENTRY; /* AIS WEP, should not have + * this case!! + */ + } else { + if (prStaRec) { /* AIS RSN Group key but addr is BSSID + */ + /* ASSERT(prStaRec->ucBMCWlanIndex < WTBL_SIZE) + */ + prCmdKey->ucWlanIndex = + secPrivacySeekForBcEntry(prAdapter, + prStaRec->ucBssIndex, + prStaRec->aucMacAddr, + prStaRec->ucIndex, + prCmdKey->ucAlgorithmId, + prCmdKey->ucKeyId); + prStaRec->ucWlanIndex = prCmdKey->ucWlanIndex; + } else { /* Exist this case ? */ + ASSERT(FALSE); + /* prCmdKey->ucWlanIndex = */ + /* secPrivacySeekForBcEntry(prAdapter, */ + /* prBssInfo->ucBssIndex, */ + /* NETWORK_TYPE_AIS, */ + /* prCmdKey->aucPeerAddr, */ + /* prCmdKey->ucAlgorithmId, */ + /* prCmdKey->ucKeyId, */ + } + } + } + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, + (struct QUE_ENTRY *) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; +} /* wlanoidSetAddKey */ +#endif + +#if CFG_ENABLE_WAKEUP_ON_LAN +uint32_t +wlanoidSetAddWakeupPattern(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_PM_PACKET_PATTERN *prPacketPattern; + + DEBUGFUNC("wlanoidSetAddWakeupPattern"); + DBGLOG(REQ, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_PM_PACKET_PATTERN); + + if (u4SetBufferLen < sizeof(struct PARAM_PM_PACKET_PATTERN)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prPacketPattern = (struct PARAM_PM_PACKET_PATTERN *) + pvSetBuffer; + + /* FIXME: Send the struct to firmware */ + + return WLAN_STATUS_FAILURE; +} + +uint32_t +wlanoidSetRemoveWakeupPattern(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_PM_PACKET_PATTERN *prPacketPattern; + + DEBUGFUNC("wlanoidSetAddWakeupPattern"); + DBGLOG(REQ, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_PM_PACKET_PATTERN); + + if (u4SetBufferLen < sizeof(struct PARAM_PM_PACKET_PATTERN)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prPacketPattern = (struct PARAM_PM_PACKET_PATTERN *) + pvSetBuffer; + + /* FIXME: Send the struct to firmware */ + + return WLAN_STATUS_FAILURE; +} + +uint32_t +wlanoidQueryEnableWakeup(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t *pu4WakeupEventEnable; + + DEBUGFUNC("wlanoidQueryEnableWakeup"); + DBGLOG(REQ, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(uint32_t); + + if (u4QueryBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + pu4WakeupEventEnable = (uint32_t *) pvQueryBuffer; + + *pu4WakeupEventEnable = prAdapter->u4WakeupEventEnable; + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidSetEnableWakeup(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pu4WakeupEventEnable; + + DEBUGFUNC("wlanoidSetEnableWakup"); + DBGLOG(REQ, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + pu4WakeupEventEnable = (uint32_t *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetWiFiWmmPsTest(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_WMM_PS_TEST_STRUCT *prWmmPsTestInfo; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct CMD_SET_WMM_PS_TEST_STRUCT rSetWmmPsTestParam; + uint16_t u2CmdBufLen; + struct PM_PROFILE_SETUP_INFO *prPmProfSetupInfo; + struct BSS_INFO *prBssInfo; + + DEBUGFUNC("wlanoidSetWiFiWmmPsTest"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct + PARAM_CUSTOM_WMM_PS_TEST_STRUCT); + + prWmmPsTestInfo = (struct PARAM_CUSTOM_WMM_PS_TEST_STRUCT *) + pvSetBuffer; + + rSetWmmPsTestParam.ucBssIndex = + prWmmPsTestInfo->ucBssIdx; + rSetWmmPsTestParam.bmfgApsdEnAc = + prWmmPsTestInfo->bmfgApsdEnAc; + rSetWmmPsTestParam.ucIsEnterPsAtOnce = + prWmmPsTestInfo->ucIsEnterPsAtOnce; + rSetWmmPsTestParam.ucIsDisableUcTrigger = + prWmmPsTestInfo->ucIsDisableUcTrigger; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + rSetWmmPsTestParam.ucBssIndex); + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + prPmProfSetupInfo->ucBmpDeliveryAC = + (rSetWmmPsTestParam.bmfgApsdEnAc >> 4) & BITS(0, 3); + prPmProfSetupInfo->ucBmpTriggerAC = + rSetWmmPsTestParam.bmfgApsdEnAc & BITS(0, 3); + + u2CmdBufLen = sizeof(struct CMD_SET_WMM_PS_TEST_STRUCT); + +#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, + nicCmdEventSetCommon,/* TODO? */ + nicCmdTimeoutCommon, u2CmdBufLen, + (uint8_t *) &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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetTxAmpdu(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct CMD_TX_AMPDU rTxAmpdu; + uint16_t u2CmdBufLen; + u_int8_t *pfgEnable; + + DEBUGFUNC("wlanoidSetTxAmpdu"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(u_int8_t); + + pfgEnable = (u_int8_t *) pvSetBuffer; + + rTxAmpdu.fgEnable = *pfgEnable; + + u2CmdBufLen = sizeof(struct CMD_TX_AMPDU); + + rStatus = wlanSendSetQueryCmd(prAdapter, CMD_ID_TX_AMPDU, + TRUE, FALSE, TRUE, NULL, NULL, + u2CmdBufLen, + (uint8_t *) &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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetAddbaReject(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct CMD_ADDBA_REJECT rAddbaReject; + uint16_t u2CmdBufLen; + u_int8_t *pfgEnable; + + DEBUGFUNC("wlanoidSetAddbaReject"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(u_int8_t); + + pfgEnable = (u_int8_t *) pvSetBuffer; + + rAddbaReject.fgEnable = *pfgEnable; + + u2CmdBufLen = sizeof(struct CMD_ADDBA_REJECT); + + rStatus = wlanSendSetQueryCmd(prAdapter, CMD_ID_ADDBA_REJECT, + TRUE, FALSE, TRUE, NULL, NULL, + u2CmdBufLen, + (uint8_t *) &rAddbaReject, NULL, 0); + + return rStatus; +} /* wlanoidSetAddbaReject */ + +#if CFG_SLT_SUPPORT + +uint32_t +wlanoidQuerySLTStatus(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct PARAM_MTK_SLT_TEST_STRUCT *prMtkSltInfo = + (struct PARAM_MTK_SLT_TEST_STRUCT *) NULL; + struct SLT_INFO *prSltInfo = (struct SLT_INFO *) NULL; + + DEBUGFUNC("wlanoidQuerySLTStatus"); + DBGLOG(REQ, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(struct PARAM_MTK_SLT_TEST_STRUCT); + + if (u4QueryBufferLen < sizeof(struct + PARAM_MTK_SLT_TEST_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvQueryBuffer); + + prMtkSltInfo = (struct PARAM_MTK_SLT_TEST_STRUCT *) + pvQueryBuffer; + + prSltInfo = &(prAdapter->rWifiVar.rSltInfo); + + switch (prMtkSltInfo->rSltFuncIdx) { + case ENUM_MTK_SLT_FUNC_LP_SET: { + struct PARAM_MTK_SLT_LP_TEST_STRUCT *prLpSetting = + (struct PARAM_MTK_SLT_LP_TEST_STRUCT *) NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof( + struct PARAM_MTK_SLT_LP_TEST_STRUCT)); + + prLpSetting = (struct PARAM_MTK_SLT_LP_TEST_STRUCT *) + &prMtkSltInfo->unFuncInfoContent; + + prLpSetting->u4BcnRcvNum = prSltInfo->u4BeaconReceiveCnt; + } + break; + default: + /* TBD... */ + break; + } + + return rWlanStatus; +} /* wlanoidQuerySLTStatus */ + +uint32_t +wlanoidUpdateSLTMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct PARAM_MTK_SLT_TEST_STRUCT *prMtkSltInfo = + (struct PARAM_MTK_SLT_TEST_STRUCT *) NULL; + struct SLT_INFO *prSltInfo = (struct SLT_INFO *) NULL; + struct BSS_DESC *prBssDesc = (struct BSS_DESC *) NULL; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + /* 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(struct PARAM_MTK_SLT_TEST_STRUCT); + + if (u4SetBufferLen < sizeof(struct + PARAM_MTK_SLT_TEST_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prMtkSltInfo = (struct PARAM_MTK_SLT_TEST_STRUCT *) + pvSetBuffer; + + prSltInfo = &(prAdapter->rWifiVar.rSltInfo); + prBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + + switch (prMtkSltInfo->rSltFuncIdx) { + case ENUM_MTK_SLT_FUNC_INITIAL: { /* Initialize */ + struct PARAM_MTK_SLT_INITIAL_STRUCT *prMtkSltInit = + (struct PARAM_MTK_SLT_INITIAL_STRUCT *) NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof( + struct PARAM_MTK_SLT_INITIAL_STRUCT)); + + prMtkSltInit = (struct PARAM_MTK_SLT_INITIAL_STRUCT *) + &prMtkSltInfo->unFuncInfoContent; + + if (prSltInfo->prPseudoStaRec != NULL) { + /* The driver has been initialized. */ + prSltInfo->prPseudoStaRec = NULL; + } + + prSltInfo->prPseudoBssDesc = scanSearchExistingBssDesc( + prAdapter, BSS_TYPE_IBSS, + prMtkSltInit->aucTargetMacAddr, + prMtkSltInit->aucTargetMacAddr); + + prSltInfo->u2SiteID = prMtkSltInit->u2SiteID; + + /* Bandwidth 2.4G: Channel 1~14 + * Bandwidth 5G: *36, 40, 44, 48, 52, 56, 60, 64, + * *100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, + * 149, 153, *157, 161, + * 184, 188, 192, 196, 200, 204, 208, 212, *216 + */ + prSltInfo->ucChannel2G4 = 1 + (prSltInfo->u2SiteID % 4) * 5; + + switch (prSltInfo->ucChannel2G4) { + case 1: + prSltInfo->ucChannel5G = 36; + break; + case 6: + prSltInfo->ucChannel5G = 52; + break; + case 11: + prSltInfo->ucChannel5G = 104; + break; + case 16: + prSltInfo->ucChannel2G4 = 14; + prSltInfo->ucChannel5G = 161; + break; + default: + ASSERT(FALSE); + } + + if (prSltInfo->prPseudoBssDesc == NULL) { + do { + prSltInfo->prPseudoBssDesc = + scanAllocateBssDesc(prAdapter); + + if (prSltInfo->prPseudoBssDesc == NULL) { + rWlanStatus = WLAN_STATUS_FAILURE; + break; + } + prBssDesc = prSltInfo->prPseudoBssDesc; + + } while (FALSE); + } else { + prBssDesc = prSltInfo->prPseudoBssDesc; + } + + if (prBssDesc) { + prBssDesc->eBSSType = BSS_TYPE_IBSS; + + COPY_MAC_ADDR(prBssDesc->aucSrcAddr, + prMtkSltInit->aucTargetMacAddr); + COPY_MAC_ADDR(prBssDesc->aucBSSID, + prBssInfo->aucOwnMacAddr); + + prBssDesc->u2BeaconInterval = 100; + prBssDesc->u2ATIMWindow = 0; + prBssDesc->ucDTIMPeriod = 1; + + prBssDesc->u2IELength = 0; + + prBssDesc->fgIsERPPresent = TRUE; + prBssDesc->fgIsHTPresent = TRUE; + + prBssDesc->u2OperationalRateSet = BIT(RATE_36M_INDEX); + prBssDesc->u2BSSBasicRateSet = BIT(RATE_36M_INDEX); + prBssDesc->fgIsUnknownBssBasicRate = FALSE; + + prBssDesc->fgIsLargerTSF = TRUE; + + prBssDesc->eBand = BAND_2G4; + + prBssDesc->ucChannelNum = prSltInfo->ucChannel2G4; + + prBssDesc->ucPhyTypeSet = PHY_TYPE_SET_802_11ABGN; + + GET_CURRENT_SYSTIME(&prBssDesc->rUpdateTime); + } + } + break; + case ENUM_MTK_SLT_FUNC_RATE_SET: /* Update RF Settings. */ + if (prSltInfo->prPseudoStaRec == NULL) { + rWlanStatus = WLAN_STATUS_FAILURE; + } else { + struct PARAM_MTK_SLT_TR_TEST_STRUCT *prTRSetting = + (struct PARAM_MTK_SLT_TR_TEST_STRUCT *) NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof( + struct PARAM_MTK_SLT_TR_TEST_STRUCT)); + + prStaRec = prSltInfo->prPseudoStaRec; + prTRSetting = (struct PARAM_MTK_SLT_TR_TEST_STRUCT *) + &prMtkSltInfo->unFuncInfoContent; + + if (prTRSetting->rNetworkType == + PARAM_NETWORK_TYPE_OFDM5) { + prBssInfo->eBand = BAND_5G; + prBssInfo->ucPrimaryChannel = + prSltInfo->ucChannel5G; + } + if (prTRSetting->rNetworkType == + PARAM_NETWORK_TYPE_OFDM24) { + prBssInfo->eBand = BAND_2G4; + prBssInfo->ucPrimaryChannel = + prSltInfo->ucChannel2G4; + } + + if ((prTRSetting->u4FixedRate & FIXED_BW_DL40) != 0) { + /* RF 40 */ + /* It would controls RFBW capability in WTBL. */ + prStaRec->u2HtCapInfo |= + HT_CAP_INFO_SUP_CHNL_WIDTH; + /* This controls RF BW, RF BW would be 40 + * only if + * 1. PHY_TYPE_BIT_HT is TRUE. + * 2. SCO is SCA/SCB. + */ + prStaRec->ucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + + /* U20/L20 Control. */ + switch (prTRSetting->u4FixedRate & 0xC000) { + case FIXED_EXT_CHNL_U20: + prBssInfo->eBssSCO = + CHNL_EXT_SCB; /* +2 */ + if (prTRSetting->rNetworkType == + PARAM_NETWORK_TYPE_OFDM5) { + prBssInfo->ucPrimaryChannel + += 2; + } else { + /* For channel 1, testing L20 at + * channel 8. AOSP + */ + SetTestChannel( + &prBssInfo->ucPrimaryChannel); + } + break; + case FIXED_EXT_CHNL_L20: + default: /* 40M */ + prBssInfo->eBssSCO = + CHNL_EXT_SCA; /* -2 */ + if (prTRSetting->rNetworkType == + PARAM_NETWORK_TYPE_OFDM5) { + prBssInfo->ucPrimaryChannel + -= 2; + } else { + /* For channel 11 / 14. testing + * U20 at channel 3. AOSP + */ + SetTestChannel( + &prBssInfo->ucPrimaryChannel); + } + 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_SW_INDEX); + break; + case RATE_OFDM_48M: + prStaRec->u2DesiredNonHTRateSet = + BIT(RATE_48M_SW_INDEX); + break; + case RATE_OFDM_36M: + prStaRec->u2DesiredNonHTRateSet = + BIT(RATE_36M_SW_INDEX); + break; + case RATE_OFDM_24M: + prStaRec->u2DesiredNonHTRateSet = + BIT(RATE_24M_SW_INDEX); + break; + case RATE_OFDM_6M: + prStaRec->u2DesiredNonHTRateSet = + BIT(RATE_6M_SW_INDEX); + break; + case RATE_CCK_11M_LONG: + prStaRec->u2DesiredNonHTRateSet = + BIT(RATE_11M_SW_INDEX); + break; + case RATE_CCK_1M_LONG: + prStaRec->u2DesiredNonHTRateSet = + BIT(RATE_1M_SW_INDEX); + break; + case RATE_GF_MCS_0: + prStaRec->u2DesiredNonHTRateSet = + BIT(RATE_HT_PHY_SW_INDEX); + prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + break; + case RATE_MM_MCS_7: + prStaRec->u2DesiredNonHTRateSet = + BIT(RATE_HT_PHY_SW_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_SW_INDEX); + prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + break; + default: + prStaRec->u2DesiredNonHTRateSet = + BIT(RATE_36M_SW_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. */ + struct PARAM_MTK_SLT_LP_TEST_STRUCT *prLpSetting = + (struct PARAM_MTK_SLT_LP_TEST_STRUCT *) NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof( + struct PARAM_MTK_SLT_LP_TEST_STRUCT)); + + prLpSetting = (struct PARAM_MTK_SLT_LP_TEST_STRUCT *) + &prMtkSltInfo->unFuncInfoContent; + + if (prSltInfo->prPseudoBssDesc == NULL) { + /* Please initial SLT Mode first. */ + break; + } + prBssDesc = prSltInfo->prPseudoBssDesc; + + switch (prLpSetting->rLpTestMode) { + case ENUM_MTK_LP_TEST_NORMAL: + /* In normal mode, we would use target MAC address to be + * the BSSID. + */ + COPY_MAC_ADDR(prBssDesc->aucBSSID, + prBssInfo->aucOwnMacAddr); + prSltInfo->fgIsDUT = FALSE; + break; + case ENUM_MTK_LP_TEST_GOLDEN_SAMPLE: + /* 1. Lower AIFS of BCN queue. + * 2. Fixed Random Number tobe 0. + */ + prSltInfo->fgIsDUT = FALSE; + /* In LP test mode, we would use MAC address of Golden + * Sample to be the BSSID. + */ + COPY_MAC_ADDR(prBssDesc->aucBSSID, + prBssInfo->aucOwnMacAddr); + break; + case ENUM_MTK_LP_TEST_DUT: + /* 1. Enter Sleep Mode. + * 2. Fix random number a large value & enlarge AIFN of + * BCN queue. + */ + COPY_MAC_ADDR(prBssDesc->aucBSSID, + prBssDesc->aucSrcAddr); + prSltInfo->u4BeaconReceiveCnt = 0; + prSltInfo->fgIsDUT = TRUE; + break; + } + + } + + break; + default: + break; + } + + return WLAN_STATUS_FAILURE; + + return rWlanStatus; +} /* wlanoidUpdateSLTMode */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to query NVRAM value. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[out] pvQueryBuf A pointer to the buffer that holds the result of + * the query. + * \param[in] u4QueryBufLen The length of the query buffer. + * \param[out] pu4QueryInfoLen If the call is successful, returns the number of + * bytes written into the query buffer. If the call + * failed due to invalid length of the query buffer, + * returns the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_FAILURE + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryNvramRead(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_CUSTOM_EEPROM_RW_STRUCT *rNvRwInfo; + uint16_t u2Data; + u_int8_t fgStatus; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4Ofs = 0; + + DEBUGFUNC("wlanoidQueryNvramRead"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct + PARAM_CUSTOM_EEPROM_RW_STRUCT); + + if (u4QueryBufferLen < sizeof(struct + PARAM_CUSTOM_EEPROM_RW_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + rNvRwInfo = (struct PARAM_CUSTOM_EEPROM_RW_STRUCT *) + pvQueryBuffer; + + if (rNvRwInfo->ucMethod == + PARAM_EEPROM_READ_METHOD_READ) { + u4Ofs = rNvRwInfo->info.rEeprom.ucEepromIndex << 1; + fgStatus = kalCfgDataRead16(prAdapter->prGlueInfo, + u4Ofs, /* change to byte offset */ + &u2Data); + if (fgStatus) { + rNvRwInfo->info.rEeprom.u2EepromData = u2Data; + DBGLOG(REQ, INFO, + "NVRAM Read: index=%#X, data=%#02X\r\n", + rNvRwInfo->info.rEeprom.ucEepromIndex, + u2Data); + } else { + DBGLOG(REQ, ERROR, "NVRAM Read Failed: index=%#x.\r\n", + rNvRwInfo->info.rEeprom.ucEepromIndex); + rStatus = WLAN_STATUS_FAILURE; + } + } else if (rNvRwInfo->ucMethod == + PARAM_EEPROM_READ_METHOD_GETSIZE) { + rNvRwInfo->info.rEeprom.u2EepromData = + MAX_CFG_FILE_WIFI_REC_SIZE; + DBGLOG(REQ, INFO, "EEPROM size =%d\r\n", + rNvRwInfo->info.rEeprom.u2EepromData); + } else if (rNvRwInfo->ucMethod == + PARAM_EEPROM_READ_NVRAM) { + u4Ofs = rNvRwInfo->info.rNvram.u2NvIndex; + fgStatus = kalCfgDataRead16(prAdapter->prGlueInfo, + u4Ofs, + &u2Data); + + if (fgStatus) { + rNvRwInfo->info.rNvram.u2NvData = u2Data & 0x00FF; + DBGLOG(REQ, INFO, + "index=%#X, data=%#02X\r\n", + rNvRwInfo->info.rNvram.u2NvIndex, + rNvRwInfo->info.rNvram.u2NvData); + } else { + DBGLOG(REQ, ERROR, "NVRAM Read Failed: index=%#x.\r\n", + rNvRwInfo->info.rNvram.u2NvIndex); + rStatus = WLAN_STATUS_FAILURE; + } + + } + + *pu4QueryInfoLen = sizeof(struct + PARAM_CUSTOM_EEPROM_RW_STRUCT); + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetNvramWrite(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_EEPROM_RW_STRUCT *rNvRwInfo; + u_int8_t fgStatus = FALSE; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidSetNvramWrite"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct + PARAM_CUSTOM_EEPROM_RW_STRUCT); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_EEPROM_RW_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + rNvRwInfo = (struct PARAM_CUSTOM_EEPROM_RW_STRUCT *) + pvSetBuffer; + + if (rNvRwInfo->ucMethod == PARAM_EEPROM_WRITE_NVRAM) + fgStatus = kalCfgDataWrite8(prAdapter->prGlueInfo, + rNvRwInfo->info.rNvram.u2NvIndex, + rNvRwInfo->info.rNvram.u2NvData & 0x00FF); + + DBGLOG(REQ, INFO, "status(%d),index=%#X, data=%#02X\n", + fgStatus, + rNvRwInfo->info.rNvram.u2NvIndex, + rNvRwInfo->info.rNvram.u2NvData); + + /*update nvram to firmware*/ + if (fgStatus == TRUE) + wlanLoadManufactureData(prAdapter, + kalGetConfiguration(prAdapter->prGlueInfo)); + else + fgStatus = kalCfgDataWrite16(prAdapter->prGlueInfo, + rNvRwInfo->info.rEeprom.ucEepromIndex << + 1, /* change to byte offset */ + rNvRwInfo->info.rEeprom.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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryCfgSrcType(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + ASSERT(prAdapter); + + *pu4QueryInfoLen = sizeof(enum ENUM_CFG_SRC_TYPE); + + if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) + *(enum ENUM_CFG_SRC_TYPE *) pvQueryBuffer = + CFG_SRC_TYPE_NVRAM; + else + *(enum ENUM_CFG_SRC_TYPE *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryEepromType(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + ASSERT(prAdapter); + + *pu4QueryInfoLen = sizeof(enum ENUM_EEPROM_TYPE *); + +#if CFG_SUPPORT_NIC_CAPABILITY + if (prAdapter->fgIsEepromUsed == TRUE) + *(enum ENUM_EEPROM_TYPE *) pvQueryBuffer = + EEPROM_TYPE_PRESENT; + else + *(enum ENUM_EEPROM_TYPE *) pvQueryBuffer = EEPROM_TYPE_NO; +#else + *(enum ENUM_EEPROM_TYPE *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetCountryCode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint8_t *pucCountry; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + + if (regd_is_single_sku_en()) { + rlmDomainOidSetCountry(prAdapter, pvSetBuffer, + u4SetBufferLen); + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_SUCCESS; + } + + ASSERT(u4SetBufferLen == 2); + + *pu4SetInfoLen = 2; + + pucCountry = pvSetBuffer; + + prAdapter->rWifiVar.u2CountryCode = + (((uint16_t) pucCountry[0]) << 8) | ((uint16_t) pucCountry[1]); + + /* Force to re-search country code in regulatory domains */ + prAdapter->prDomainInfo = NULL; + rlmDomainSendCmd(prAdapter); + + /* Update supported channel list in channel table based on current + * country domain + */ + wlanUpdateChannelTable(prAdapter->prGlueInfo); + +#if CFG_SUPPORT_SAP_DFS_CHANNEL + if (aisGetConnectedBssInfo(prAdapter)) { + struct BSS_INFO *prAisBssInfo = + aisGetConnectedBssInfo(prAdapter); + + if (prAisBssInfo == NULL) { + return WLAN_STATUS_FAILURE; + } + + /* restore DFS channels table */ + wlanUpdateDfsChannelTable(prAdapter->prGlueInfo, + -1, /* p2p role index */ + prAisBssInfo->ucPrimaryChannel, /* primary channel */ + 0, /* bandwidth */ + 0, /* sco */ + 0 /* center frequency */); + } +#endif + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidSetScanMacOui(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct PARAM_BSS_MAC_OUI *prParamMacOui; + struct BSS_INFO *prBssInfo; + + ASSERT(prAdapter); + ASSERT(prAdapter->prGlueInfo); + ASSERT(pvSetBuffer); + ASSERT(u4SetBufferLen == sizeof(struct PARAM_BSS_MAC_OUI)); + + prParamMacOui = (struct PARAM_BSS_MAC_OUI *)pvSetBuffer; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prParamMacOui->ucBssIndex); + if (!prBssInfo) { + log_dbg(REQ, ERROR, "Invalid bss info (ind=%u)\n", + prParamMacOui->ucBssIndex); + return WLAN_STATUS_FAILURE; + } + + kalMemCopy(prBssInfo->ucScanOui, prParamMacOui->ucMacOui, MAC_OUI_LEN); + prBssInfo->fgIsScanOuiSet = TRUE; + *pu4SetInfoLen = MAC_OUI_LEN; + + return WLAN_STATUS_SUCCESS; +} + +#if 0 +uint32_t +wlanoidSetNoaParam(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_NOA_PARAM_STRUCT *prNoaParam; + struct CMD_CUSTOM_NOA_PARAM_STRUCT rCmdNoaParam; + + DEBUGFUNC("wlanoidSetNoaParam"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct + PARAM_CUSTOM_NOA_PARAM_STRUCT); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_NOA_PARAM_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prNoaParam = (struct PARAM_CUSTOM_NOA_PARAM_STRUCT *) + pvSetBuffer; + + kalMemZero(&rCmdNoaParam, + sizeof(struct CMD_CUSTOM_NOA_PARAM_STRUCT)); + 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(struct CMD_CUSTOM_NOA_PARAM_STRUCT), + (uint8_t *) &rCmdNoaParam, pvSetBuffer, + u4SetBufferLen); +} + +uint32_t +wlanoidSetOppPsParam(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_OPPPS_PARAM_STRUCT *prOppPsParam; + struct CMD_CUSTOM_OPPPS_PARAM_STRUCT rCmdOppPsParam; + + DEBUGFUNC("wlanoidSetOppPsParam"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct + PARAM_CUSTOM_OPPPS_PARAM_STRUCT); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_OPPPS_PARAM_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prOppPsParam = (struct PARAM_CUSTOM_OPPPS_PARAM_STRUCT *) + pvSetBuffer; + + kalMemZero(&rCmdOppPsParam, + sizeof(struct CMD_CUSTOM_OPPPS_PARAM_STRUCT)); + rCmdOppPsParam.u4CTwindowMs = prOppPsParam->u4CTwindowMs; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_OPPPS_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_CUSTOM_OPPPS_PARAM_STRUCT), + (uint8_t *) &rCmdOppPsParam, pvSetBuffer, + u4SetBufferLen); +} + +uint32_t +wlanoidSetUApsdParam(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_UAPSD_PARAM_STRUCT *prUapsdParam; + struct CMD_CUSTOM_UAPSD_PARAM_STRUCT rCmdUapsdParam; + struct PM_PROFILE_SETUP_INFO *prPmProfSetupInfo; + struct BSS_INFO *prBssInfo; + + DEBUGFUNC("wlanoidSetUApsdParam"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct + PARAM_CUSTOM_UAPSD_PARAM_STRUCT); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_UAPSD_PARAM_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prBssInfo = & + (prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + + prUapsdParam = (struct PARAM_CUSTOM_UAPSD_PARAM_STRUCT *) + pvSetBuffer; + + kalMemZero(&rCmdUapsdParam, + sizeof(struct CMD_CUSTOM_OPPPS_PARAM_STRUCT)); + 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(struct CMD_CUSTOM_OPPPS_PARAM_STRUCT), + (uint8_t *)&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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetBT(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + + struct PTA_IPC *prPtaIpc; + + DEBUGFUNC("wlanoidSetBT.\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PTA_IPC); + if (u4SetBufferLen != sizeof(struct PTA_IPC)) { + /* 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 = (struct PTA_IPC *) pvSetBuffer; + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS && CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(INIT, INFO, + "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]); + + DBGLOG(INIT, INFO, + "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(struct PTA_IPC), + (uint8_t *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryBT(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + /* P_PARAM_PTA_IPC_T prPtaIpc; */ + /* UINT_32 u4QueryBuffLen; */ + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct PTA_IPC); + + /* Check for query buffer length */ + if (u4QueryBufferLen != sizeof(struct PTA_IPC)) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvQueryBuffer); + /* prPtaIpc = (P_PTA_IPC_T)pvQueryBuffer; */ + /* prPtaIpc->ucCmd = BT_CMD_PROFILE; */ + /* prPtaIpc->ucLen = sizeof(prPtaIpc->u); */ + /* nicPtaGetProfile(prAdapter, (PUINT_8)&prPtaIpc->u, &u4QueryBuffLen); + */ + + return WLAN_STATUS_SUCCESS; +} + +#if 0 +uint32_t +wlanoidQueryBtSingleAntenna(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + P_PTA_INFO_T prPtaInfo; + uint32_t *pu4SingleAntenna; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(uint32_t); + + /* Check for query buffer length */ + if (u4QueryBufferLen != sizeof(uint32_t)) { + DBGLOG(REQ, WARN, "Invalid length %lu\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvQueryBuffer); + + prPtaInfo = &prAdapter->rPtaInfo; + pu4SingleAntenna = (uint32_t *) pvQueryBuffer; + + if (prPtaInfo->fgSingleAntenna) { + /* DBGLOG(INIT, INFO, (KERN_WARNING DRV_NAME + * "Q Single Ant = 1\r\n")); + */ + *pu4SingleAntenna = 1; + } else { + /* DBGLOG(INIT, INFO, (KERN_WARNING DRV_NAME + * "Q Single Ant = 0\r\n")); + */ + *pu4SingleAntenna = 0; + } + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidSetBtSingleAntenna(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + + uint32_t *pu4SingleAntenna; + uint32_t u4SingleAntenna; + P_PTA_INFO_T prPtaInfo; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + prPtaInfo = &prAdapter->rPtaInfo; + + *pu4SetInfoLen = sizeof(uint32_t); + if (u4SetBufferLen != sizeof(uint32_t)) + 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 = (uint32_t *) pvSetBuffer; + u4SingleAntenna = *pu4SingleAntenna; + + if (u4SingleAntenna == 0) { + /* DBGLOG(INIT, INFO, (KERN_WARNING DRV_NAME + * "Set Single Ant = 0\r\n")); + */ + prPtaInfo->fgSingleAntenna = FALSE; + } else { + /* DBGLOG(INIT, INFO, (KERN_WARNING DRV_NAME + * "Set Single Ant = 1\r\n")); + */ + prPtaInfo->fgSingleAntenna = TRUE; + } + ptaFsmRunEventSetConfig(prAdapter, &prPtaInfo->rPtaParam); + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS +uint32_t +wlanoidQueryPta(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + P_PTA_INFO_T prPtaInfo; + uint32_t *pu4Pta; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(uint32_t); + + /* Check for query buffer length */ + if (u4QueryBufferLen != sizeof(uint32_t)) { + DBGLOG(REQ, WARN, "Invalid length %lu\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvQueryBuffer); + + prPtaInfo = &prAdapter->rPtaInfo; + pu4Pta = (uint32_t *) pvQueryBuffer; + + if (prPtaInfo->fgEnabled) { + /* DBGLOG(INIT, INFO, (KERN_WARNING DRV_NAME"PTA = 1\r\n")); */ + *pu4Pta = 1; + } else { + /* DBGLOG(INIT, INFO, (KERN_WARNING DRV_NAME"PTA = 0\r\n")); */ + *pu4Pta = 0; + } + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidSetPta(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pu4PtaCtrl; + uint32_t u4PtaCtrl; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(uint32_t); + if (u4SetBufferLen != sizeof(uint32_t)) + 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 = (uint32_t *) pvSetBuffer; + u4PtaCtrl = *pu4PtaCtrl; + + if (u4PtaCtrl == 0) { + /* DBGLOG(INIT, INFO, (KERN_WARNING DRV_NAME"Set Pta= 0\r\n")); + */ + nicPtaSetFunc(prAdapter, FALSE); + } else { + /* DBGLOG(INIT, INFO, (KERN_WARNING DRV_NAME"Set Pta= 1\r\n")); + */ + nicPtaSetFunc(prAdapter, TRUE); + } + + return WLAN_STATUS_SUCCESS; +} +#endif + +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set Tx power profile. + * + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. + * \param[in] u4SetBufferLen The length of the set buffer. + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed + * due to invalid length of the set buffer, returns + * the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetTxPower(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct SET_TXPWR_CTRL *pTxPwr = (struct SET_TXPWR_CTRL *) + pvSetBuffer; + struct SET_TXPWR_CTRL *prCmd; + uint32_t i; + uint32_t rStatus; + + DEBUGFUNC("wlanoidSetTxPower"); + DBGLOG(REQ, LOUD, "\r\n"); + + prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, + sizeof(struct SET_TXPWR_CTRL)); + + if (!prCmd) { + DBGLOG(REQ, ERROR, "prCmd not available\n"); + return WLAN_STATUS_FAILURE; + } + kalMemZero(prCmd, sizeof(struct SET_TXPWR_CTRL)); + prCmd->c2GLegacyStaPwrOffset = + pTxPwr->c2GLegacyStaPwrOffset; + prCmd->c2GHotspotPwrOffset = pTxPwr->c2GHotspotPwrOffset; + prCmd->c2GP2pPwrOffset = pTxPwr->c2GP2pPwrOffset; + prCmd->c2GBowPwrOffset = pTxPwr->c2GBowPwrOffset; + prCmd->c5GLegacyStaPwrOffset = + pTxPwr->c5GLegacyStaPwrOffset; + prCmd->c5GHotspotPwrOffset = pTxPwr->c5GHotspotPwrOffset; + prCmd->c5GP2pPwrOffset = pTxPwr->c5GP2pPwrOffset; + prCmd->c5GBowPwrOffset = pTxPwr->c5GBowPwrOffset; + prCmd->ucConcurrencePolicy = pTxPwr->ucConcurrencePolicy; + for (i = 0; i < 14; i++) + prCmd->acTxPwrLimit2G[i] = pTxPwr->acTxPwrLimit2G[i]; + + for (i = 0; i < 4; i++) + prCmd->acTxPwrLimit5G[i] = pTxPwr->acTxPwrLimit5G[i]; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + +#if 0 + DBGLOG(INIT, INFO, "c2GLegacyStaPwrOffset=%d\n", + pTxPwr->c2GLegacyStaPwrOffset); + DBGLOG(INIT, INFO, "c2GHotspotPwrOffset=%d\n", + pTxPwr->c2GHotspotPwrOffset); + DBGLOG(INIT, INFO, "c2GP2pPwrOffset=%d\n", + pTxPwr->c2GP2pPwrOffset); + DBGLOG(INIT, INFO, "c2GBowPwrOffset=%d\n", + pTxPwr->c2GBowPwrOffset); + DBGLOG(INIT, INFO, "c5GLegacyStaPwrOffset=%d\n", + pTxPwr->c5GLegacyStaPwrOffset); + DBGLOG(INIT, INFO, "c5GHotspotPwrOffset=%d\n", + pTxPwr->c5GHotspotPwrOffset); + DBGLOG(INIT, INFO, "c5GP2pPwrOffset=%d\n", + pTxPwr->c5GP2pPwrOffset); + DBGLOG(INIT, INFO, "c5GBowPwrOffset=%d\n", + pTxPwr->c5GBowPwrOffset); + DBGLOG(INIT, INFO, "ucConcurrencePolicy=%d\n", + pTxPwr->ucConcurrencePolicy); + + for (i = 0; i < 14; i++) + DBGLOG(INIT, INFO, "acTxPwrLimit2G[%d]=%d\n", i, + pTxPwr->acTxPwrLimit2G[i]); + + for (i = 0; i < 4; i++) + DBGLOG(INIT, INFO, "acTxPwrLimit5G[%d]=%d\n", i, + pTxPwr->acTxPwrLimit5G[i]); +#endif + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_TXPWR_CTRL, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + TRUE, /* fgIsOid */ + nicCmdEventSetCommon, nicOidCmdTimeoutCommon, + sizeof(struct SET_TXPWR_CTRL), /* u4SetQueryInfoLen */ + (uint8_t *) prCmd, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + /* ASSERT(rStatus == WLAN_STATUS_PENDING); */ + cnmMemFree(prAdapter, prCmd); + + return rStatus; + +} + +uint32_t wlanSendMemDumpCmd(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen) { + struct PARAM_CUSTOM_MEM_DUMP_STRUCT *prMemDumpInfo; + struct CMD_DUMP_MEM *prCmdDumpMem; + struct CMD_DUMP_MEM rCmdDumpMem; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4MemSize = PARAM_MEM_DUMP_MAX_SIZE; + + uint32_t u4RemainLeng = 0; + uint32_t u4CurAddr = 0; + uint8_t ucFragNum = 0; + + prCmdDumpMem = &rCmdDumpMem; + prMemDumpInfo = (struct PARAM_CUSTOM_MEM_DUMP_STRUCT *) + 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 { + uint32_t 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; +#if CFG_SUPPORT_QA_TOOL + prCmdDumpMem->u4IcapContent = prMemDumpInfo->u4IcapContent; +#endif /* CFG_SUPPORT_QA_TOOL */ + + DBGLOG(REQ, TRACE, "[%d] 0x%X, len %u, remain len %u\n", + ucFragNum, prCmdDumpMem->u4Address, + prCmdDumpMem->u4Length, prCmdDumpMem->u4RemainLength); + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_DUMP_MEM, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryMemDump, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_DUMP_MEM), + (uint8_t *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryMemDump(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_CUSTOM_MEM_DUMP_STRUCT *prMemDumpInfo; + + DEBUGFUNC("wlanoidQueryMemDump"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(uint32_t); + + prMemDumpInfo = (struct PARAM_CUSTOM_MEM_DUMP_STRUCT *) + pvQueryBuffer; + DBGLOG(REQ, TRACE, "Dump 0x%X, len %u\n", + prMemDumpInfo->u4Address, prMemDumpInfo->u4Length); + + prMemDumpInfo->u4RemainLength = prMemDumpInfo->u4Length; + prMemDumpInfo->u4Length = 0; + prMemDumpInfo->ucFragNum = 0; + + return wlanSendMemDumpCmd(prAdapter, pvQueryBuffer, + u4QueryBufferLen); + +} /* end of wlanoidQueryMcrRead() */ + +#if CFG_ENABLE_WIFI_DIRECT +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to set the p2p mode. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. + * \param[in] u4SetBufferLen The length of the set buffer. + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed + * due to invalid length of the set buffer, returns + * the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetP2pMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t status = WLAN_STATUS_SUCCESS; + struct PARAM_CUSTOM_P2P_SET_STRUCT *prSetP2P = + (struct PARAM_CUSTOM_P2P_SET_STRUCT *) NULL; + /* P_MSG_P2P_NETDEV_REGISTER_T prP2pNetdevRegMsg = + * P_MSG_P2P_NETDEV_REGISTER_T)NULL; + */ + DEBUGFUNC("wlanoidSetP2pMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CUSTOM_P2P_SET_STRUCT); + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_P2P_SET_STRUCT)) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prSetP2P = (struct PARAM_CUSTOM_P2P_SET_STRUCT *) + pvSetBuffer; + + DBGLOG(P2P, TRACE, "Set P2P enable[%d] mode[%d]\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 + * enable = 1, mode = 2 => init dual Soft AP network + * enable = 1, mode = 3 => init AP+P2P network + */ + + + DBGLOG(P2P, TRACE, "P2P Compile as (%d)p2p-like interface\n", + KAL_P2P_NUM); + + if (prSetP2P->u4Mode >= RUNNING_P2P_MODE_NUM) { + DBGLOG(P2P, ERROR, "P2P interface mode(%d) is wrong\n", + prSetP2P->u4Mode); + ASSERT(0); + } + + if (prSetP2P->u4Enable) { + p2pSetMode(prSetP2P->u4Mode); + + if (p2pLaunch(prAdapter->prGlueInfo)) { + /* ToDo:: ASSERT */ + ASSERT(prAdapter->fgIsP2PRegistered); + if (prAdapter->rWifiVar.ucApUapsd + && (prSetP2P->u4Mode != RUNNING_P2P_MODE)) { + DBGLOG(OID, INFO, + "wlanoidSetP2pMode Default enable ApUapsd\n"); + setApUapsdEnable(prAdapter, TRUE); + } + prAdapter->u4P2pMode = prSetP2P->u4Mode; + } else { + DBGLOG(P2P, ERROR, "P2P Launch Failed\n"); + status = WLAN_STATUS_FAILURE; + } + + } else { + if (prAdapter->fgIsP2PRegistered) + p2pRemove(prAdapter->prGlueInfo); + + } + +#if 0 + prP2pNetdevRegMsg = (struct MSG_P2P_NETDEV_REGISTER *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + (sizeof(struct MSG_P2P_NETDEV_REGISTER))); + + 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 = (uint8_t) prSetP2P->u4Mode; + + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prP2pNetdevRegMsg, MSG_SEND_METHOD_BUF); +#endif + + return status; + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set the GTK rekey data + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetGtkRekeyData(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + uint8_t *pucCmdBuf; + struct mt66xx_chip_info *prChipInfo; + uint16_t cmd_size; + + DBGLOG(REQ, INFO, "wlanoidSetGtkRekeyData\n"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + prChipInfo = prAdapter->chip_info; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(RSN, WARN, + "Fail in set rekey! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + *pu4SetInfoLen = u4SetBufferLen; + + prGlueInfo = prAdapter->prGlueInfo; + cmd_size = prChipInfo->u2CmdTxHdrSize + + sizeof(struct PARAM_GTK_REKEY_DATA); + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, cmd_size); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* compose PARAM_GTK_REKEY_DATA cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->u2InfoBufLen = cmd_size; + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_SET_GTK_REKEY_DATA; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->u4SetInfoLen = u4SetBufferLen; + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + + /* Setup WIFI_CMD_T */ + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + prCmdInfo->ucCID, + CMD_PACKET_TYPE_ID, + &prCmdInfo->ucCmdSeqNum, + prCmdInfo->fgSetQuery, + &pucCmdBuf, FALSE, 0, S2D_INDEX_CMD_H2N); + + kalMemCopy(pucCmdBuf, (uint8_t *) pvSetBuffer, + u4SetBufferLen); + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, + (struct QUE_ENTRY *) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; + +} /* wlanoidSetGtkRekeyData */ + +#if CFG_SUPPORT_SCHED_SCAN +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to request starting of schedule scan + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. + * \param[in] u4SetBufferLen The length of the set buffer. + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed + * due to invalid length of the set buffer, returns + * the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_ADAPTER_NOT_READY + * \retval WLAN_STATUS_INVALID_LENGTH + * \retval WLAN_STATUS_INVALID_DATA + * + * \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetStartSchedScan(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct PARAM_SCHED_SCAN_REQUEST *prSchedScanRequest = + (struct PARAM_SCHED_SCAN_REQUEST *) pvSetBuffer; + uint8_t ucBssIndex; + + if (pvSetBuffer == NULL) + return WLAN_STATUS_INVALID_DATA; + + ucBssIndex = prSchedScanRequest->ucBssIndex; + + DEBUGFUNC("wlanoidSetStartSchedScan()"); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, + "Fail in set scheduled scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pu4SetInfoLen); + *pu4SetInfoLen = 0; + + if (u4SetBufferLen != sizeof(struct + PARAM_SCHED_SCAN_REQUEST)) + return WLAN_STATUS_INVALID_LENGTH; + else if (kalGetMediaStateIndicated(prAdapter->prGlueInfo, + ucBssIndex) == + MEDIA_STATE_CONNECTED + && prAdapter->fgEnOnlineScan == FALSE) + return WLAN_STATUS_FAILURE; + + if (prAdapter->fgIsRadioOff) { + DBGLOG(REQ, WARN, + "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + goto success; + } + + if (!scnFsmSchedScanRequest(prAdapter, prSchedScanRequest)) { + DBGLOG(REQ, WARN, "scnFsmSchedScanRequest failure !!\n"); + return WLAN_STATUS_FAILURE; + } + +success: + prAdapter->prGlueInfo->prSchedScanRequest = prSchedScanRequest; + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to request termination of schedule scan + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. + * \param[in] u4SetBufferLen The length of the set buffer. + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed + * due to invalid length of the set buffer, returns + * the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_ADAPTER_NOT_READY + * \retval WLAN_STATUS_INVALID_LENGTH + * \retval WLAN_STATUS_INVALID_DATA + * + * \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetStopSchedScan(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t ret; + struct PARAM_SCHED_SCAN_REQUEST *prSchedScanRequest = + prAdapter->prGlueInfo->prSchedScanRequest; + + ASSERT(prAdapter); + + /* ask SCN module to stop scan request */ + if (scnFsmSchedScanStopRequest(prAdapter) == TRUE) { + kalMemFree(prSchedScanRequest->pucChannels, + VIR_MEM_TYPE, prSchedScanRequest->ucChnlNum); + kalMemFree(prSchedScanRequest->pucIE, + VIR_MEM_TYPE, + prGlueInfo->prSchedScanRequest->u4IELength); + kalMemFree(prSchedScanRequest, + VIR_MEM_TYPE, + sizeof(struct PARAM_SCHED_SCAN_REQUEST)); + prAdapter->prGlueInfo->prSchedScanRequest = NULL; + ret = WLAN_STATUS_SUCCESS; + } else { + DBGLOG(REQ, WARN, "scnFsmSchedScanStopRequest failed.\n"); + ret = WLAN_STATUS_RESOURCES; + } + return ret; +} +#endif /* CFG_SUPPORT_SCHED_SCAN */ + +#if CFG_M0VE_BA_TO_DRIVER +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to reset BA scoreboard. + * + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanoidResetBAScoreboard(IN struct ADAPTER * + prAdapter, IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen) { + uint32_t rStatus; + + DEBUGFUNC("wlanoidResetBAScoreboard"); + DBGLOG(REQ, WARN, "[Puff]wlanoidResetBAScoreboard\n"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_RESET_BA_SCOREBOARD, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + TRUE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + u4SetBufferLen, /* u4SetQueryInfoLen */ + (uint8_t *) pvSetBuffer, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + /* ASSERT(rStatus == WLAN_STATUS_PENDING); */ + + return rStatus; + +} + +#endif + +#if CFG_SUPPORT_BATCH_SCAN + +#define CMD_WLS_BATCHING "WLS_BATCHING" + +#define BATCHING_SET "SET" +#define BATCHING_GET "GET" +#define BATCHING_STOP "STOP" + +#define PARAM_SCANFREQ "SCANFREQ" +#define PARAM_MSCAN "MSCAN" +#define PARAM_BESTN "BESTN" +#define PARAM_CHANNEL "CHANNEL" +#define PARAM_RTT "RTT" + +uint32_t +batchSetCmd(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4WritenLen) { + struct CHANNEL_INFO *prRfChannelInfo; + struct CMD_BATCH_REQ rCmdBatchReq; + + uint32_t rStatus = WLAN_STATUS_SUCCESS; + int8_t *head, *p, *p2; + uint32_t tokens; + int32_t scanfreq, mscan, bestn, rtt; + char *pcTemp; + /* CHAR c_scanfreq[4], c_mscan[4], c_bestn[4], c_rtt[4], c_channel[100]; + */ + /* INT_32 ch_type; */ + uint32_t u4Value = 0; + int32_t i4Ret = 0; + + DBGLOG(SCN, TRACE, "[BATCH] command=%s, len=%u\n", + (char *)pvSetBuffer, u4SetBufferLen); + + if (!pu4WritenLen) + return -EINVAL; + *pu4WritenLen = 0; + + if (u4SetBufferLen < kalStrLen(CMD_WLS_BATCHING)) { + DBGLOG(SCN, TRACE, "[BATCH] invalid len %d\n", + u4SetBufferLen); + return -EINVAL; + } + + head = pvSetBuffer + kalStrLen(CMD_WLS_BATCHING) + 1; + kalMemSet(&rCmdBatchReq, 0, sizeof(struct CMD_BATCH_REQ)); + + if (!kalStrnCmp(head, BATCHING_SET, + kalStrLen(BATCHING_SET))) { + + DBGLOG(SCN, TRACE, "XXX Start Batch Scan XXX\n"); + + head += kalStrLen(BATCHING_SET) + 1; + + /* SCANFREQ, MSCAN, BESTN */ + tokens = sscanf(head, "SCANFREQ=%d MSCAN=%d BESTN=%d", + &scanfreq, &mscan, &bestn); + if (tokens != 3) { + DBGLOG(SCN, TRACE, + "[BATCH] Parse fail: tokens=%d, SCANFREQ=%d MSCAN=%d BESTN=%d\n", + tokens, scanfreq, mscan, bestn); + return -EINVAL; + } + /* RTT */ + p = kalStrStr(head, PARAM_RTT); + if (!p) { + DBGLOG(SCN, TRACE, "[BATCH] Parse RTT fail. head=%s\n", + head); + return -EINVAL; + } + tokens = sscanf(p, "RTT=%d", &rtt); + if (tokens != 1) { + DBGLOG(SCN, TRACE, + "[BATCH] Parse fail: tokens=%d, rtt=%d\n", + tokens, rtt); + return -EINVAL; + } + /* CHANNEL */ + p = kalStrStr(head, PARAM_CHANNEL); + if (!p) { + DBGLOG(SCN, TRACE, "[BATCH] Parse CHANNEL fail(1)\n"); + return -EINVAL; + } + head = p; + p = kalStrChr(head, '>'); + if (!p) { + DBGLOG(SCN, TRACE, "[BATCH] Parse CHANNEL fail(2)\n"); + return -EINVAL; + } + /* else { + * p = '.'; // remove '>' because sscanf can not parse <%s> + * } + */ + /* tokens = sscanf(head, "CHANNEL=<%s", c_channel); + * if (tokens != 1) { + * DBGLOG(SCN, TRACE, "[BATCH] Parse fail: tokens=%d, + * CHANNEL=<%s>\n", tokens, c_channel); + * return -EINVAL; + * } + */ + rCmdBatchReq.ucChannelType = SCAN_CHANNEL_SPECIFIED; + rCmdBatchReq.ucChannelListNum = 0; + prRfChannelInfo = &rCmdBatchReq.arChannelList[0]; + p = head + kalStrLen(PARAM_CHANNEL) + 2; /* c_channel; */ + pcTemp = (char *)p; + while ((p2 = kalStrSep(&pcTemp, ",")) != NULL) { + if (p2 == NULL || *p2 == 0) + break; + if (*p2 == '\0') + continue; + if (*p2 == 'A') { + rCmdBatchReq.ucChannelType = + rCmdBatchReq.ucChannelType == + SCAN_CHANNEL_2G4 ? + SCAN_CHANNEL_FULL : SCAN_CHANNEL_5G; + } else if (*p2 == 'B') { + rCmdBatchReq.ucChannelType = + rCmdBatchReq.ucChannelType == + SCAN_CHANNEL_5G ? + SCAN_CHANNEL_FULL : SCAN_CHANNEL_2G4; + } else { + + /* Translate Freq from MHz to channel number. */ + /* prRfChannelInfo->ucChannelNum = + * kalStrtol(p2, NULL, 0); + */ + i4Ret = kalkStrtou32(p2, 0, &u4Value); + if (i4Ret) + DBGLOG(SCN, TRACE, + "parse ucChannelNum error i4Ret=%d\n", + i4Ret); + prRfChannelInfo->ucChannelNum = + (uint8_t) u4Value; + DBGLOG(SCN, TRACE, + "Scanning Channel:%d, freq: %d\n", + prRfChannelInfo->ucChannelNum, + nicChannelNum2Freq( + prRfChannelInfo->ucChannelNum)); + prRfChannelInfo->ucBand = + prRfChannelInfo->ucChannelNum < 15 + ? BAND_2G4 : BAND_5G; + + rCmdBatchReq.ucChannelListNum++; + if (rCmdBatchReq.ucChannelListNum >= 32) + break; + prRfChannelInfo++; + } + } + + /* set channel for test */ +#if 0 + rCmdBatchReq.ucChannelType = + 4; /* SCAN_CHANNEL_SPECIFIED; */ + rCmdBatchReq.ucChannelListNum = 0; + prRfChannelInfo = &rCmdBatchReq.arChannelList[0]; + for (i = 1; i <= 14; i++) { + + /* filter out some */ + if (i == 1 || i == 5 || i == 11) + continue; + + /* Translate Freq from MHz to channel number. */ + prRfChannelInfo->ucChannelNum = i; + DBGLOG(SCN, TRACE, "Scanning Channel:%d, freq: %d\n", + prRfChannelInfo->ucChannelNum, + nicChannelNum2Freq( + prRfChannelInfo->ucChannelNum)); + prRfChannelInfo->ucBand = BAND_2G4; + + rCmdBatchReq.ucChannelListNum++; + prRfChannelInfo++; + } +#endif +#if 0 + rCmdBatchReq.ucChannelType = 0; /* SCAN_CHANNEL_FULL; */ +#endif + + rCmdBatchReq.u4Scanfreq = scanfreq; + rCmdBatchReq.ucMScan = mscan > CFG_BATCH_MAX_MSCAN ? + CFG_BATCH_MAX_MSCAN : mscan; + rCmdBatchReq.ucBestn = bestn; + rCmdBatchReq.ucRtt = rtt; + DBGLOG(SCN, TRACE, + "[BATCH] SCANFREQ=%d MSCAN=%d BESTN=%d RTT=%d\n", + rCmdBatchReq.u4Scanfreq, rCmdBatchReq.ucMScan, + rCmdBatchReq.ucBestn, rCmdBatchReq.ucRtt); + + if (rCmdBatchReq.ucChannelType != SCAN_CHANNEL_SPECIFIED) { + DBGLOG(SCN, TRACE, "[BATCH] CHANNELS = %s\n", + rCmdBatchReq.ucChannelType == SCAN_CHANNEL_FULL ? + "FULL" : rCmdBatchReq.ucChannelType == + SCAN_CHANNEL_2G4 ? "2.4G all" : "5G all"); + } else { + DBGLOG(SCN, TRACE, "[BATCH] CHANNEL list\n"); + prRfChannelInfo = &rCmdBatchReq.arChannelList[0]; + for (tokens = 0; tokens < rCmdBatchReq.ucChannelListNum; + tokens++) { + DBGLOG(SCN, TRACE, "[BATCH] %s, %d\n", + prRfChannelInfo->ucBand + == BAND_2G4 ? "2.4G" : "5G", + prRfChannelInfo->ucChannelNum); + prRfChannelInfo++; + } + } + + rCmdBatchReq.ucSeqNum = 1; + rCmdBatchReq.ucNetTypeIndex = KAL_NETWORK_TYPE_AIS_INDEX; + rCmdBatchReq.ucCmd = SCAN_BATCH_REQ_START; + + *pu4WritenLen = kalSnprintf(pvSetBuffer, 3, "%d", + rCmdBatchReq.ucMScan); + + } else if (!kalStrnCmp(head, BATCHING_STOP, + kalStrLen(BATCHING_STOP))) { + + DBGLOG(SCN, TRACE, "XXX Stop Batch Scan XXX\n"); + + rCmdBatchReq.ucSeqNum = 1; + rCmdBatchReq.ucNetTypeIndex = KAL_NETWORK_TYPE_AIS_INDEX; + rCmdBatchReq.ucCmd = SCAN_BATCH_REQ_STOP; + } else { + return -EINVAL; + } + + rStatus = wlanSendSetQueryCmd(prAdapter, CMD_ID_SET_BATCH_REQ, + TRUE, FALSE, TRUE, NULL, NULL, + sizeof(struct CMD_BATCH_REQ), + (uint8_t *) &rCmdBatchReq, NULL, 0); + + /* kalMemSet(pvSetBuffer, 0, u4SetBufferLen); */ + /* rStatus = kalSnprintf(pvSetBuffer, 2, "%s", "OK"); */ + + /* exit: */ + return rStatus; +} + +uint32_t +batchGetCmd(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct CMD_BATCH_REQ rCmdBatchReq; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct EVENT_BATCH_RESULT *prEventBatchResult; + /* UINT_32 i; */ + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + prEventBatchResult = (struct EVENT_BATCH_RESULT *) + pvQueryBuffer; + + DBGLOG(SCN, TRACE, "XXX Get Batch Scan Result (%d) XXX\n", + prEventBatchResult->ucScanCount); + + *pu4QueryInfoLen = sizeof(struct EVENT_BATCH_RESULT); + + rCmdBatchReq.ucSeqNum = 2; + rCmdBatchReq.ucCmd = SCAN_BATCH_REQ_RESULT; + rCmdBatchReq.ucMScan = + prEventBatchResult->ucScanCount; /* Get which round result */ + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_BATCH_REQ, + FALSE, + TRUE, + TRUE, + nicCmdEventBatchScanResult, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_BATCH_REQ), + (uint8_t *) &rCmdBatchReq, + (void *) pvQueryBuffer, + u4QueryBufferLen); + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] prAdapter Pointer to the Adapter structure + * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set + * \param[in] u4SetBufferLen The length of the set buffer + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed due to invalid length of + * the set buffer, returns the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. + * \retval WLAN_STATUS_INVALID_LENGTH + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetBatchScanReq(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + return batchSetCmd(prAdapter, pvSetBuffer, u4SetBufferLen, + pu4SetInfoLen); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[out] pvQueryBuffer A pointer to the buffer that holds the result of + * the query. + * \param[in] u4QueryBufferLen The length of the query buffer. + * \param[out] pu4QueryInfoLen If the call is successful, returns the number of + * bytes written into the query buffer. If the call + * failed due to invalid length of the query buffer, + * returns the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryBatchScanResult(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + return batchGetCmd(prAdapter, pvQueryBuffer, + u4QueryBufferLen, pu4QueryInfoLen); + +} /* end of wlanoidQueryBatchScanResult() */ + +#endif /* CFG_SUPPORT_BATCH_SCAN */ + +#if CFG_SUPPORT_PASSPOINT +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called by HS2.0 to set the assoc info, which is needed + * to add to Association request frame while join HS2.0 AP. + * + * \param[in] prAdapter Pointer to the Adapter structure + * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set + * \param[in] u4SetBufferLen The length of the set buffer + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed due to invalid length of + * the set buffer, returns the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. + * \retval WLAN_STATUS_INVALID_LENGTH + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetHS20Info(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct IE_HS20_INDICATION *prHS20IndicationIe; + struct HS20_INFO *prHS20Info; + uint8_t ucBssIndex = 0; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + DEBUGFUNC("wlanoidSetHS20AssocInfo"); + DBGLOG(OID, LOUD, "\r\n"); + + if (u4SetBufferLen == 0) + return WLAN_STATUS_INVALID_LENGTH; + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + + prHS20Info = aisGetHS20Info(prAdapter, ucBssIndex); + + *pu4SetInfoLen = u4SetBufferLen; + + prHS20IndicationIe = (struct IE_HS20_INDICATION *) + pvSetBuffer; + + prHS20Info->ucHotspotConfig = + prHS20IndicationIe->ucHotspotConfig; + prHS20Info->fgConnectHS20AP = TRUE; + + DBGLOG(SEC, TRACE, "HS20 IE sz %u\n", u4SetBufferLen); + + return WLAN_STATUS_SUCCESS; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set_bssid_pool + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] pvSetBuffer Pointer to the buffer that holds the data to be + * set. + * \param[in] u4SetBufferLen The length of the set buffer. + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed + * due to invalid length of the set buffer, returns + * the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + * \retval WLAN_STATUS_ADAPTER_NOT_READY + * \retval WLAN_STATUS_MULTICAST_FULL + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetHS20BssidPool(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + uint8_t ucBssIndex = 0; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (u4SetBufferLen < sizeof(struct + PARAM_HS20_SET_BSSID_POOL)) { + *pu4SetInfoLen = sizeof(struct PARAM_HS20_SET_BSSID_POOL); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + + DBGLOG(REQ, LOUD, "ucBssIndex %d\n", ucBssIndex); + + rWlanStatus = hs20SetBssidPool(prAdapter, pvSetBuffer, + ucBssIndex); + + return rWlanStatus; +} /* end of wlanoidSendHS20GASRequest() */ + +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_SNIFFER +uint32_t +wlanoidSetMonitor(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_MONITOR_SET_STRUCT *prMonitorSetInfo; + struct CMD_MONITOR_SET_INFO rCmdMonitorSetInfo; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidSetMonitor"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct + PARAM_CUSTOM_MONITOR_SET_STRUCT); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_MONITOR_SET_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prMonitorSetInfo = (struct PARAM_CUSTOM_MONITOR_SET_STRUCT + *) pvSetBuffer; + + rCmdMonitorSetInfo.ucEnable = prMonitorSetInfo->ucEnable; + rCmdMonitorSetInfo.ucBand = prMonitorSetInfo->ucBand; + rCmdMonitorSetInfo.ucPriChannel = + prMonitorSetInfo->ucPriChannel; + rCmdMonitorSetInfo.ucSco = prMonitorSetInfo->ucSco; + rCmdMonitorSetInfo.ucChannelWidth = + prMonitorSetInfo->ucChannelWidth; + rCmdMonitorSetInfo.ucChannelS1 = + prMonitorSetInfo->ucChannelS1; + rCmdMonitorSetInfo.ucChannelS2 = + prMonitorSetInfo->ucChannelS2; + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_MONITOR, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_MONITOR_SET_INFO), + (uint8_t *) &rCmdMonitorSetInfo, + pvSetBuffer, + u4SetBufferLen); + + return rWlanStatus; +} +#endif + +#if CFG_SUPPORT_MSP +uint32_t +wlanoidQueryWlanInfo(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + DEBUGFUNC("wlanoidQueryWlanInfo"); + + return wlanQueryWlanInfo(prAdapter, pvQueryBuffer, u4QueryBufferLen, + pu4QueryInfoLen, TRUE); +} + +uint32_t +wlanQueryWlanInfo(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen, + IN uint8_t fgIsOid) { + struct PARAM_HW_WLAN_INFO *prHwWlanInfo; + + DEBUGFUNC("wlanQueryWlanInfo"); + DBGLOG(REQ, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(struct PARAM_HW_WLAN_INFO); + + 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(uint32_t); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(struct PARAM_HW_WLAN_INFO)) { + DBGLOG(REQ, WARN, "Too short length %u\n", + u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prHwWlanInfo = (struct PARAM_HW_WLAN_INFO *)pvQueryBuffer; + DBGLOG(RSN, INFO, + "MT6632 : wlanoidQueryWlanInfo index = %d\n", + prHwWlanInfo->u4Index); + + /* *pu4QueryInfoLen = 8 + prRxStatistics->u4TotalNum; */ + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_WTBL_INFO, + FALSE, + TRUE, + fgIsOid, + nicCmdEventQueryWlanInfo, + nicOidCmdTimeoutCommon, + sizeof(struct PARAM_HW_WLAN_INFO), + (uint8_t *)prHwWlanInfo, + pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryWlanInfo */ + +uint32_t +wlanoidQueryMibInfo(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + DEBUGFUNC("wlanoidQueryMibInfo"); + + return wlanQueryMibInfo(prAdapter, pvQueryBuffer, u4QueryBufferLen, + pu4QueryInfoLen, TRUE); +} + +uint32_t +wlanQueryMibInfo(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen, + IN uint8_t fgIsOid) +{ + struct PARAM_HW_MIB_INFO *prHwMibInfo; + + DEBUGFUNC("wlanoidQueryMibInfo"); + DBGLOG(REQ, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(struct PARAM_HW_MIB_INFO); + + 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(uint32_t); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(struct + PARAM_HW_MIB_INFO)) { + DBGLOG(REQ, WARN, "Too short length %u\n", + u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prHwMibInfo = (struct PARAM_HW_MIB_INFO *)pvQueryBuffer; + DBGLOG(RSN, INFO, + "MT6632 : wlanoidQueryMibInfo index = %d\n", + prHwMibInfo->u4Index); + + /* *pu4QueryInfoLen = 8 + prRxStatistics->u4TotalNum; */ + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_MIB_INFO, + FALSE, + TRUE, + fgIsOid, + nicCmdEventQueryMibInfo, + nicOidCmdTimeoutCommon, + sizeof(struct PARAM_HW_MIB_INFO), + (uint8_t *)prHwMibInfo, + pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryMibInfo */ +#endif + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set FW log to Host. + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetFwLog2Host( + IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct CMD_FW_LOG_2_HOST_CTRL *prFwLog2HostCtrl; + + DEBUGFUNC("wlanoidSetFwLog2Host"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct CMD_FW_LOG_2_HOST_CTRL); + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, + "Fail in set FW log to Host! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4SetBufferLen < sizeof(struct + CMD_FW_LOG_2_HOST_CTRL)) { + DBGLOG(REQ, WARN, "Too short length %d\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prFwLog2HostCtrl = (struct CMD_FW_LOG_2_HOST_CTRL *) + pvSetBuffer; + + DBGLOG(REQ, INFO, "McuDest %d, LogType %d\n", + prFwLog2HostCtrl->ucMcuDest, + prFwLog2HostCtrl->ucFwLog2HostCtrl); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_FW_LOG_2_HOST, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_FW_LOG_2_HOST_CTRL), + (uint8_t *)prFwLog2HostCtrl, + pvSetBuffer, u4SetBufferLen); +} + +uint32_t +wlanoidNotifyFwSuspend( + IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct CMD_SUSPEND_MODE_SETTING *prSuspendCmd; + + if (!prAdapter || !pvSetBuffer) + return WLAN_STATUS_INVALID_DATA; + + prSuspendCmd = (struct CMD_SUSPEND_MODE_SETTING *) + pvSetBuffer; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_SUSPEND_MODE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_SUSPEND_MODE_SETTING), + (uint8_t *)prSuspendCmd, + NULL, + 0); +} + +uint32_t +wlanoidQueryCnm( + IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_GET_CNM_T *prCnmInfo = NULL; + + DEBUGFUNC("wlanoidQueryCnm"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (prAdapter->fgIsEnableLpdvt) + return WLAN_STATUS_NOT_SUPPORTED; + + *pu4QueryInfoLen = sizeof(struct PARAM_GET_CNM_T); + + if (u4QueryBufferLen < sizeof(struct PARAM_GET_CNM_T)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + prCnmInfo = (struct PARAM_GET_CNM_T *)pvQueryBuffer; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_CNM, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryCnmInfo, + nicOidCmdTimeoutCommon, + sizeof(struct PARAM_GET_CNM_T), + (uint8_t *)prCnmInfo, + pvQueryBuffer, u4QueryBufferLen); +} + +uint32_t +wlanoidPacketKeepAlive(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct PARAM_PACKET_KEEPALIVE_T *prPacket; + + DEBUGFUNC("wlanoidPacketKeepAlive"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(struct PARAM_PACKET_KEEPALIVE_T); + + /* Check for query buffer length */ + if (u4SetBufferLen < *pu4SetInfoLen) { + DBGLOG(OID, WARN, "Too short length %u\n", u4SetBufferLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + prPacket = (struct PARAM_PACKET_KEEPALIVE_T *) + kalMemAlloc(sizeof(struct PARAM_PACKET_KEEPALIVE_T), + VIR_MEM_TYPE); + if (!prPacket) { + DBGLOG(OID, ERROR, + "Can not alloc memory for struct PARAM_PACKET_KEEPALIVE_T\n"); + return -ENOMEM; + } + kalMemCopy(prPacket, pvSetBuffer, + sizeof(struct PARAM_PACKET_KEEPALIVE_T)); + + DBGLOG(OID, INFO, "enable=%d, index=%d\r\n", + prPacket->enable, prPacket->index); + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_WFC_KEEP_ALIVE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct PARAM_PACKET_KEEPALIVE_T), + (uint8_t *)prPacket, NULL, 0); + kalMemFree(prPacket, VIR_MEM_TYPE, + sizeof(struct PARAM_PACKET_KEEPALIVE_T)); + return rStatus; +} + +#if CFG_SUPPORT_DBDC +uint32_t +wlanoidSetDbdcEnable( + IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint8_t ucDBDCEnable; + + if (!prAdapter || !pvSetBuffer) + return WLAN_STATUS_INVALID_DATA; + + /* Be careful. + * We only use the test cmd "set_dbdc" to enable DBDC HW + * wo/ OP Mode Change. Besides, it may also confuse original + * DBDC FSM. + */ + kalMemCopy(&ucDBDCEnable, pvSetBuffer, 1); + cnmUpdateDbdcSetting(prAdapter, ucDBDCEnable); + + return WLAN_STATUS_SUCCESS; +} +#endif /*#if CFG_SUPPORT_DBDC*/ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set tx target power base. + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQuerySetTxTargetPower(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_SET_TX_TARGET_POWER + *prSetTxTargetPowerInfo; + struct CMD_SET_TX_TARGET_POWER rCmdSetTxTargetPower; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQuerySetTxTargetPower"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct + PARAM_CUSTOM_SET_TX_TARGET_POWER *); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_SET_TX_TARGET_POWER *)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prSetTxTargetPowerInfo = + (struct PARAM_CUSTOM_SET_TX_TARGET_POWER *) pvSetBuffer; + + kalMemSet(&rCmdSetTxTargetPower, 0, + sizeof(struct CMD_SET_TX_TARGET_POWER)); + + rCmdSetTxTargetPower.ucTxTargetPwr = + prSetTxTargetPowerInfo->ucTxTargetPwr; + + DBGLOG(INIT, INFO, + "MT6632 : wlanoidQuerySetTxTargetPower =%x dbm\n", + rCmdSetTxTargetPower.ucTxTargetPwr); + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_TX_PWR, + TRUE, /* fgSetQuery Bit: True->write False->read */ + FALSE, /* fgNeedResp */ + TRUE, /* fgIsOid*/ + nicCmdEventSetCommon, /* REF: wlanoidSetDbdcEnable */ + nicOidCmdTimeoutCommon, + sizeof(struct CMD_ACCESS_EFUSE), + (uint8_t *) (&rCmdSetTxTargetPower), pvSetBuffer, + u4SetBufferLen); + + return rWlanStatus; +} + +#if (CFG_SUPPORT_DFS_MASTER == 1) +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set rdd report. + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQuerySetRddReport(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_SET_RDD_REPORT *prSetRddReport; + struct CMD_RDD_ON_OFF_CTRL *prCmdRddOnOffCtrl; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQuerySetRddReport"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CUSTOM_SET_RDD_REPORT + *); + + ASSERT(pvSetBuffer); + + prSetRddReport = (struct PARAM_CUSTOM_SET_RDD_REPORT *) + pvSetBuffer; + + prCmdRddOnOffCtrl = (struct CMD_RDD_ON_OFF_CTRL *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(*prCmdRddOnOffCtrl)); + + ASSERT(prCmdRddOnOffCtrl); + if (prCmdRddOnOffCtrl == NULL) { + DBGLOG(INIT, ERROR, "prCmdRddOnOffCtrl is NULL"); + return WLAN_STATUS_FAILURE; + } + + prCmdRddOnOffCtrl->ucDfsCtrl = RDD_RADAR_EMULATE; + + prCmdRddOnOffCtrl->ucRddIdx = prSetRddReport->ucDbdcIdx; + + if (prCmdRddOnOffCtrl->ucRddIdx) + prCmdRddOnOffCtrl->ucRddRxSel = RDD_IN_SEL_1; + else + prCmdRddOnOffCtrl->ucRddRxSel = RDD_IN_SEL_0; + + DBGLOG(INIT, INFO, + "MT6632 : wlanoidQuerySetRddReport - DFS ctrl: %.d, RDD index: %d\n", + prCmdRddOnOffCtrl->ucDfsCtrl, prCmdRddOnOffCtrl->ucRddIdx); + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_RDD_ON_OFF_CTRL, + TRUE, /* fgSetQuery Bit: True->write False->read */ + FALSE, /* fgNeedResp */ + TRUE, /* fgIsOid*/ + nicCmdEventSetCommon, /* REF: wlanoidSetDbdcEnable */ + nicOidCmdTimeoutCommon, + sizeof(*prCmdRddOnOffCtrl), + (uint8_t *) (prCmdRddOnOffCtrl), pvSetBuffer, + u4SetBufferLen); + + cnmMemFree(prAdapter, prCmdRddOnOffCtrl); + + return rWlanStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set rdd report. + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQuerySetRadarDetectMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_SET_RADAR_DETECT_MODE + *prSetRadarDetectMode; + struct CMD_RDD_ON_OFF_CTRL *prCmdRddOnOffCtrl; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQuerySetRadarDetectMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = + sizeof(struct PARAM_CUSTOM_SET_RADAR_DETECT_MODE *); + + ASSERT(pvSetBuffer); + + prSetRadarDetectMode = + (struct PARAM_CUSTOM_SET_RADAR_DETECT_MODE *) pvSetBuffer; + + prCmdRddOnOffCtrl = (struct CMD_RDD_ON_OFF_CTRL *)cnmMemAlloc( + prAdapter, RAM_TYPE_MSG, + sizeof(*prCmdRddOnOffCtrl)); + + ASSERT(prCmdRddOnOffCtrl); + if (prCmdRddOnOffCtrl == NULL) { + DBGLOG(INIT, ERROR, "prCmdRddOnOffCtrl is NULL"); + return WLAN_STATUS_FAILURE; + } + + prCmdRddOnOffCtrl->ucDfsCtrl = RDD_DET_MODE; + + prCmdRddOnOffCtrl->ucSetVal = + prSetRadarDetectMode->ucRadarDetectMode; + + DBGLOG(INIT, INFO, + "MT6632 : wlanoidQuerySetRadarDetectMode - DFS ctrl: %.d, Radar Detect Mode: %d\n", + prCmdRddOnOffCtrl->ucDfsCtrl, prCmdRddOnOffCtrl->ucSetVal); + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_RDD_ON_OFF_CTRL, + TRUE, /* fgSetQuery Bit: True->write False->read */ + FALSE, /* fgNeedResp */ + TRUE, /* fgIsOid*/ + nicCmdEventSetCommon, /* REF: wlanoidSetDbdcEnable */ + nicOidCmdTimeoutCommon, + sizeof(*prCmdRddOnOffCtrl), + (uint8_t *) (prCmdRddOnOffCtrl), + pvSetBuffer, + u4SetBufferLen); + + cnmMemFree(prAdapter, prCmdRddOnOffCtrl); + + return rWlanStatus; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidLinkDown(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + DEBUGFUNC("wlanoidSetDisassociate"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 0; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, + "Fail in set link down! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + aisBssLinkDown(prAdapter, ucBssIndex); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetDisassociate */ + +#if CFG_SUPPORT_NCHO + +uint32_t +wlanoidSetNchoHeader(struct CMD_HEADER *prCmdHeader, + struct CMD_FORMAT_V1 *pr_cmd_v1, + char *pStr, uint32_t u4Len) { + prCmdHeader->cmdVersion = CMD_VER_1_EXT; + prCmdHeader->cmdType = CMD_TYPE_QUERY; + prCmdHeader->itemNum = 1; + prCmdHeader->cmdBufferLen = sizeof(struct CMD_FORMAT_V1); + kalMemSet(prCmdHeader->buffer, 0, MAX_CMD_BUFFER_LENGTH); + + if (!prCmdHeader || !pStr || u4Len == 0) + return WLAN_STATUS_FAILURE; + + pr_cmd_v1->itemStringLength = u4Len; + kalMemCopy(pr_cmd_v1->itemString, pStr, u4Len); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidSetNchoRoamTrigger(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + int32_t *pi4Param = NULL; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoRoamTrigger"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(int32_t); + + if (u4SetBufferLen < sizeof(int32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + if (prAdapter->rNchoInfo.fgNCHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + pi4Param = (int32_t *) pvSetBuffer; + if (*pi4Param < RCPI_LOW_BOUND + || *pi4Param > RCPI_HIGH_BOUND) { + DBGLOG(INIT, ERROR, "NCHO roam trigger invalid %d\n", + *pi4Param); + return WLAN_STATUS_INVALID_DATA; + } + + rStatus = wlanNchoSetFWRssiTrigger(prAdapter, *pi4Param); + if (rStatus == WLAN_STATUS_SUCCESS) { + prAdapter->rNchoInfo.i4RoamTrigger = *pi4Param; + DBGLOG(INIT, TRACE, "NCHO roam trigger is %d\n", + prAdapter->rNchoInfo.i4RoamTrigger); + } + + return rStatus; +} + +uint32_t +wlanoidQueryNchoRoamTrigger(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER cmdV1Header; + struct CMD_HEADER *prCmdV1Header = (struct CMD_HEADER *) + pvQueryBuffer; + struct CMD_FORMAT_V1 *prCmdV1 = NULL; + + DEBUGFUNC("wlanoidQueryNchoRoamTrigger"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct CMD_HEADER); + + if (u4QueryBufferLen < sizeof(struct CMD_HEADER)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgNCHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + prCmdV1 = (struct CMD_FORMAT_V1 *) prCmdV1Header->buffer; + rStatus = wlanoidSetNchoHeader(prCmdV1Header, + prCmdV1, + FW_CFG_KEY_NCHO_ROAM_RCPI, + kalStrLen(FW_CFG_KEY_NCHO_ROAM_RCPI)); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "NCHO no enough memory\n"); + return rStatus; + } + kalMemCopy(&cmdV1Header, prCmdV1Header, + sizeof(struct CMD_HEADER)); + rStatus = wlanSendSetQueryCmd( + prAdapter, + CMD_ID_GET_SET_CUSTOMER_CFG, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryCfgRead, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_HEADER), + (uint8_t *)&cmdV1Header, + pvQueryBuffer, + u4QueryBufferLen); + return rStatus; +} + +uint32_t +wlanoidSetNchoRoamDelta(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + int32_t *pi4Param = NULL; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoRoamDelta"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(int32_t); + + if (u4SetBufferLen < sizeof(int32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + if (prAdapter->rNchoInfo.fgNCHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + pi4Param = (int32_t *) pvSetBuffer; + if (*pi4Param > 100) { + DBGLOG(INIT, ERROR, "NCHO roam delta invalid %d\n", + *pi4Param); + return WLAN_STATUS_INVALID_DATA; + } + + prAdapter->rNchoInfo.i4RoamDelta = *pi4Param; + DBGLOG(INIT, TRACE, "NCHO roam delta is %d\n", *pi4Param); + rStatus = WLAN_STATUS_SUCCESS; + + return rStatus; +} + +uint32_t +wlanoidQueryNchoRoamDelta(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + int32_t *pParam = NULL; + + DEBUGFUNC("wlanoidQueryNchoRoamDelta"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(int32_t)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgNCHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + pParam = (int32_t *) pvQueryBuffer; + *pParam = prAdapter->rNchoInfo.i4RoamDelta; + DBGLOG(INIT, TRACE, "NCHO roam delta is %d\n", *pParam); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidSetNchoRoamScnPeriod(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pParam = NULL; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoRoamScnPeriod"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + if (prAdapter->rNchoInfo.fgNCHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + pParam = (uint32_t *) pvSetBuffer; + rStatus = wlanNchoSetFWScanPeriod(prAdapter, *pParam); + if (rStatus == WLAN_STATUS_SUCCESS) { + prAdapter->rNchoInfo.u4RoamScanPeriod = *pParam; + DBGLOG(INIT, TRACE, "NCHO roam scan period is %d\n", *pParam); + } + + return rStatus; +} + +uint32_t +wlanoidQueryNchoRoamScnPeriod(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER cmdV1Header; + struct CMD_HEADER *prCmdV1Header = (struct CMD_HEADER *)pvQueryBuffer; + struct CMD_FORMAT_V1 *prCmdV1 = NULL; + + DEBUGFUNC("wlanoidQueryNchoRoamScnPeriod"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgNCHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + prCmdV1 = (struct CMD_FORMAT_V1 *) prCmdV1Header->buffer; + rStatus = wlanoidSetNchoHeader(prCmdV1Header, + prCmdV1, + FW_CFG_KEY_NCHO_SCAN_PERIOD, + kalStrLen(FW_CFG_KEY_NCHO_SCAN_PERIOD)); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "NCHO no enough memory\n"); + return rStatus; + } + kalMemCopy(&cmdV1Header, prCmdV1Header, sizeof(struct CMD_HEADER)); + rStatus = wlanSendSetQueryCmd( + prAdapter, + CMD_ID_GET_SET_CUSTOMER_CFG, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryCfgRead, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_HEADER), + (uint8_t *)&cmdV1Header, + pvQueryBuffer, + u4QueryBufferLen); + return rStatus; +} + +uint32_t +wlanoidSetNchoRoamScnChnl(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct CFG_NCHO_SCAN_CHNL *prRoamScnChnl = NULL; + + DEBUGFUNC("wlanoidSetNchoRoamScnChnl"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(struct CFG_NCHO_SCAN_CHNL); + + if (u4SetBufferLen < sizeof(struct CFG_NCHO_SCAN_CHNL)) + return WLAN_STATUS_INVALID_LENGTH; + + if (prAdapter->rNchoInfo.fgNCHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + prRoamScnChnl = (struct CFG_NCHO_SCAN_CHNL *) pvSetBuffer; + + kalMemCopy(&prAdapter->rNchoInfo.rRoamScnChnl, + prRoamScnChnl, *pu4SetInfoLen); + DBGLOG(INIT, TRACE, + "NCHO set roam scan channel num is %d\n", + prRoamScnChnl->ucChannelListNum); + + prAdapter->rNchoInfo.u4RoamScanControl = 1; + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidAddNchoRoamScnChnl(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct CFG_NCHO_SCAN_CHNL *prRoamScnChnl = NULL; + + DEBUGFUNC("wlanoidSetNchoRoamScnChnl"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(struct CFG_NCHO_SCAN_CHNL); + + if (u4SetBufferLen < sizeof(struct CFG_NCHO_SCAN_CHNL)) + return WLAN_STATUS_INVALID_LENGTH; + + if (prAdapter->rNchoInfo.fgNCHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + prRoamScnChnl = (struct CFG_NCHO_SCAN_CHNL *) pvSetBuffer; + + kalMemCopy(&prAdapter->rNchoInfo.rAddRoamScnChnl, + prRoamScnChnl, *pu4SetInfoLen); + DBGLOG(INIT, TRACE, + "NCHO set roam scan channel num is %d\n", + prRoamScnChnl->ucChannelListNum); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidQueryNchoRoamScnChnl(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + struct CFG_NCHO_SCAN_CHNL *prRoamScnChnl = NULL; + struct CFG_NCHO_SCAN_CHNL *chnl; + + DEBUGFUNC("wlanoidQueryNchoRoamScnChnl"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(struct CFG_NCHO_SCAN_CHNL)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgNCHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + prRoamScnChnl = (struct CFG_NCHO_SCAN_CHNL *) pvQueryBuffer; + + if (prAdapter->rNchoInfo.u4RoamScanControl) + chnl = &prAdapter->rNchoInfo.rRoamScnChnl; + else + chnl = &prAdapter->rNchoInfo.rAddRoamScnChnl; + + kalMemCopy(prRoamScnChnl, chnl, u4QueryBufferLen); + DBGLOG(INIT, TRACE, "NCHO roam scan channel num is %d, ctrl %d\n", + prRoamScnChnl->ucChannelListNum, + prAdapter->rNchoInfo.u4RoamScanControl); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidSetNchoRoamScnCtrl(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pParam = NULL; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoRoamScnChnl"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (uint32_t *) pvSetBuffer; + if (*pParam != TRUE && *pParam != FALSE) { + DBGLOG(INIT, ERROR, "NCHO roam scan control invalid %d\n", + *pParam); + return WLAN_STATUS_INVALID_DATA; + } + + prAdapter->rNchoInfo.u4RoamScanControl = *pParam; + DBGLOG(INIT, TRACE, "NCHO roam scan control is %d\n", + *pParam); + rStatus = WLAN_STATUS_SUCCESS; + + return rStatus; +} + +uint32_t +wlanoidQueryNchoRoamScnCtrl(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t *pParam = NULL; + + DEBUGFUNC("wlanoidQueryNchoRoamScnCtrl"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgNCHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + pParam = (uint32_t *) pvQueryBuffer; + *pParam = prAdapter->rNchoInfo.u4RoamScanControl; + DBGLOG(INIT, TRACE, "NCHO roam scan control is %d\n", + *pParam); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidSetNchoScnChnlTime(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pParam = NULL; + char acCmd[NCHO_CMD_MAX_LENGTH] = {0}; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoScnChnlTime"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (uint32_t *) pvSetBuffer; + if (*pParam < 10 && *pParam > 1000) { + DBGLOG(INIT, ERROR, "NCHO scan channel time invalid %d\n", + *pParam); + return WLAN_STATUS_INVALID_DATA; + } + + kalSprintf(acCmd, "%s %d", FW_CFG_KEY_NCHO_SCN_CHANNEL_TIME, + *pParam); + rStatus = wlanFwCfgParse(prAdapter, acCmd); + if (rStatus == WLAN_STATUS_SUCCESS) { + prAdapter->rNchoInfo.u4ScanChannelTime = *pParam; + DBGLOG(INIT, TRACE, "NCHO scan channel time is %d\n", + *pParam); + } + + return rStatus; +} + +uint32_t +wlanoidQueryNchoScnChnlTime(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER cmdV1Header; + struct CMD_HEADER *prCmdV1Header = (struct CMD_HEADER *) + pvQueryBuffer; + struct CMD_FORMAT_V1 *prCmdV1 = NULL; + + DEBUGFUNC("wlanoidQueryNchoScnChnlTime"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct CMD_HEADER); + + if (u4QueryBufferLen < sizeof(struct CMD_HEADER)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgNCHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + prCmdV1 = (struct CMD_FORMAT_V1 *) prCmdV1Header->buffer; + rStatus = wlanoidSetNchoHeader(prCmdV1Header, prCmdV1, + FW_CFG_KEY_NCHO_SCN_CHANNEL_TIME, + kalStrLen(FW_CFG_KEY_NCHO_SCN_CHANNEL_TIME)); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "NCHO no enough memory\n"); + return rStatus; + } + kalMemCopy(&cmdV1Header, prCmdV1Header, + sizeof(struct CMD_HEADER)); + rStatus = wlanSendSetQueryCmd( + prAdapter, + CMD_ID_GET_SET_CUSTOMER_CFG, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryCfgRead, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_HEADER), + (uint8_t *)&cmdV1Header, + pvQueryBuffer, + u4QueryBufferLen); + return rStatus; +} + +uint32_t +wlanoidSetNchoScnHomeTime(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pParam = NULL; + char acCmd[NCHO_CMD_MAX_LENGTH] = {0}; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoScnHomeTime"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (uint32_t *) pvSetBuffer; + if (*pParam < 10 && *pParam > 1000) { + DBGLOG(INIT, ERROR, "NCHO scan home time invalid %d\n", + *pParam); + return WLAN_STATUS_INVALID_DATA; + } + + kalSprintf(acCmd, "%s %d", FW_CFG_KEY_NCHO_SCN_HOME_TIME, + *pParam); + DBGLOG(REQ, TRACE, "NCHO cmd is %s\n", acCmd); + rStatus = wlanFwCfgParse(prAdapter, acCmd); + if (rStatus == WLAN_STATUS_SUCCESS) { + prAdapter->rNchoInfo.u4ScanHomeTime = *pParam; + DBGLOG(INIT, TRACE, "NCHO scan home time is %d\n", *pParam); + } + + return rStatus; +} + +uint32_t +wlanoidQueryNchoScnHomeTime(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER cmdV1Header; + struct CMD_HEADER *prCmdV1Header = (struct CMD_HEADER *) + pvQueryBuffer; + struct CMD_FORMAT_V1 *prCmdV1 = NULL; + + DEBUGFUNC("wlanoidQueryNchoScnHomeTime"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct CMD_HEADER); + + if (u4QueryBufferLen < sizeof(struct CMD_HEADER)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgNCHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + prCmdV1 = (struct CMD_FORMAT_V1 *) prCmdV1Header->buffer; + rStatus = wlanoidSetNchoHeader(prCmdV1Header, prCmdV1, + FW_CFG_KEY_NCHO_SCN_HOME_TIME, + kalStrLen(FW_CFG_KEY_NCHO_SCN_HOME_TIME)); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "NCHO no enough memory\n"); + return rStatus; + } + kalMemCopy(&cmdV1Header, prCmdV1Header, + sizeof(struct CMD_HEADER)); + rStatus = wlanSendSetQueryCmd( + prAdapter, + CMD_ID_GET_SET_CUSTOMER_CFG, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryCfgRead, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_HEADER), + (uint8_t *)&cmdV1Header, + pvQueryBuffer, + u4QueryBufferLen); + return rStatus; +} + +uint32_t +wlanoidSetNchoScnHomeAwayTime(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pParam = NULL; + char acCmd[NCHO_CMD_MAX_LENGTH] = {0}; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoScnHomeAwayTime"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (uint32_t *) pvSetBuffer; + if (*pParam < 10 && *pParam > 1000) { + DBGLOG(INIT, ERROR, "NCHO scan home away time invalid %d\n", + *pParam); + return WLAN_STATUS_INVALID_DATA; + } + + + kalSprintf(acCmd, "%s %d", + FW_CFG_KEY_NCHO_SCN_HOME_AWAY_TIME, *pParam); + DBGLOG(REQ, TRACE, "NCHO cmd is %s\n", acCmd); + rStatus = wlanFwCfgParse(prAdapter, acCmd); + if (rStatus == WLAN_STATUS_SUCCESS) { + prAdapter->rNchoInfo.u4ScanHomeawayTime = *pParam; + DBGLOG(INIT, TRACE, "NCHO scan home away is %d\n", *pParam); + } + + return rStatus; +} + +uint32_t +wlanoidQueryNchoScnHomeAwayTime(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER cmdV1Header; + struct CMD_HEADER *prCmdV1Header = (struct CMD_HEADER *) + pvQueryBuffer; + struct CMD_FORMAT_V1 *prCmdV1 = NULL; + + DEBUGFUNC("wlanoidQueryNchoScnHomeTime"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct CMD_HEADER); + + if (u4QueryBufferLen < sizeof(struct CMD_HEADER)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgNCHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + prCmdV1 = (struct CMD_FORMAT_V1 *) prCmdV1Header->buffer; + rStatus = wlanoidSetNchoHeader(prCmdV1Header, prCmdV1, + FW_CFG_KEY_NCHO_SCN_HOME_AWAY_TIME, + kalStrLen(FW_CFG_KEY_NCHO_SCN_HOME_AWAY_TIME)); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "NCHO no enough memory\n"); + return rStatus; + } + kalMemCopy(&cmdV1Header, prCmdV1Header, + sizeof(struct CMD_HEADER)); + rStatus = wlanSendSetQueryCmd( + prAdapter, + CMD_ID_GET_SET_CUSTOMER_CFG, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryCfgRead, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_HEADER), + (uint8_t *)&cmdV1Header, + pvQueryBuffer, + u4QueryBufferLen); + return rStatus; +} + +uint32_t +wlanoidSetNchoScnNprobes(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pParam = NULL; + char acCmd[NCHO_CMD_MAX_LENGTH] = {0}; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoScnNprobes"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (uint32_t *) pvSetBuffer; + if (*pParam > 16) { + DBGLOG(INIT, ERROR, "NCHO scan Nprobes invalid %d\n", + *pParam); + return WLAN_STATUS_INVALID_DATA; + } + + + kalSprintf(acCmd, "%s %d", FW_CFG_KEY_NCHO_SCN_NPROBES, + *pParam); + rStatus = wlanFwCfgParse(prAdapter, acCmd); + if (rStatus == WLAN_STATUS_SUCCESS) { + prAdapter->rNchoInfo.u4ScanNProbes = *pParam; + DBGLOG(INIT, TRACE, "NCHO Nprobes is %d\n", *pParam); + } + return rStatus; +} + +uint32_t +wlanoidQueryNchoScnNprobes(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER cmdV1Header; + struct CMD_HEADER *prCmdV1Header = (struct CMD_HEADER *) + pvQueryBuffer; + struct CMD_FORMAT_V1 *prCmdV1 = NULL; + + DEBUGFUNC("wlanoidQueryNchoScnNprobes"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct CMD_HEADER); + + if (u4QueryBufferLen < sizeof(struct CMD_HEADER)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgNCHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + prCmdV1 = (struct CMD_FORMAT_V1 *) prCmdV1Header->buffer; + rStatus = wlanoidSetNchoHeader(prCmdV1Header, + prCmdV1, + FW_CFG_KEY_NCHO_SCN_NPROBES, + kalStrLen(FW_CFG_KEY_NCHO_SCN_NPROBES)); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "NCHO no enough memory\n"); + return rStatus; + } + kalMemCopy(&cmdV1Header, prCmdV1Header, + sizeof(struct CMD_HEADER)); + rStatus = wlanSendSetQueryCmd( + prAdapter, + CMD_ID_GET_SET_CUSTOMER_CFG, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryCfgRead, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_HEADER), + (uint8_t *)&cmdV1Header, + pvQueryBuffer, + u4QueryBufferLen); + return rStatus; +} + +uint32_t +wlanoidGetNchoReassocInfo(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct BSS_DESC *prBssDesc = NULL; + struct PARAM_CONNECT *prParamConn; + + DEBUGFUNC("wlanoidGetNchoReassocInfo"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + ASSERT(pvQueryBuffer); + + prParamConn = (struct PARAM_CONNECT *)pvQueryBuffer; + if (prAdapter->rNchoInfo.fgNCHOEnabled == TRUE) { + prBssDesc = scanSearchBssDescByBssid(prAdapter, + prParamConn->pucBssid); + if (prBssDesc != NULL) { + prParamConn->u4SsidLen = prBssDesc->ucSSIDLen; + COPY_SSID(prParamConn->pucSsid, + prParamConn->u4SsidLen, + prBssDesc->aucSSID, + prBssDesc->ucSSIDLen); + rStatus = WLAN_STATUS_SUCCESS; + } + } + return rStatus; +} + +uint32_t +wlanoidSendNchoActionFrameStart(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct NCHO_INFO *prNchoInfo = NULL; + struct NCHO_ACTION_FRAME_PARAMS *prParamActionFrame = NULL; + + DEBUGFUNC("wlanoidSendNchoActionFrameStart"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + + prNchoInfo = &prAdapter->rNchoInfo; + prParamActionFrame = (struct NCHO_ACTION_FRAME_PARAMS *)pvSetBuffer; + prNchoInfo->fgIsSendingAF = TRUE; + prNchoInfo->fgChGranted = FALSE; + COPY_MAC_ADDR(prNchoInfo->rParamActionFrame.aucBssid, + prParamActionFrame->aucBssid); + prNchoInfo->rParamActionFrame.i4channel = prParamActionFrame->i4channel; + prNchoInfo->rParamActionFrame.i4DwellTime = + prParamActionFrame->i4DwellTime; + prNchoInfo->rParamActionFrame.i4len = prParamActionFrame->i4len; + kalMemCopy(prNchoInfo->rParamActionFrame.aucData, + prParamActionFrame->aucData, + prParamActionFrame->i4len); + DBGLOG(INIT, TRACE, "NCHO send ncho action frame start\n"); + rStatus = WLAN_STATUS_SUCCESS; + + return rStatus; +} + +uint32_t +wlanoidSendNchoActionFrameEnd(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSendNchoActionFrameEnd"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + prAdapter->rNchoInfo.fgIsSendingAF = FALSE; + prAdapter->rNchoInfo.fgChGranted = TRUE; + DBGLOG(INIT, TRACE, "NCHO send action frame end\n"); + rStatus = WLAN_STATUS_SUCCESS; + + return rStatus; +} + +uint32_t +wlanoidSetNchoWesMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pParam = NULL; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoWesMode"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (uint32_t *) pvSetBuffer; + if (*pParam != TRUE && *pParam != FALSE) { + DBGLOG(INIT, ERROR, "NCHO wes mode invalid %d\n", *pParam); + return WLAN_STATUS_INVALID_DATA; + } + + + prAdapter->rNchoInfo.u4WesMode = *pParam; + DBGLOG(INIT, TRACE, "NCHO WES mode is %d\n", *pParam); + rStatus = WLAN_STATUS_SUCCESS; + + return rStatus; +} + +uint32_t +wlanoidQueryNchoWesMode(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t *pParam = NULL; + + DEBUGFUNC("wlanoidQueryNchoWesMode"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgNCHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + pParam = (uint32_t *) pvQueryBuffer; + *pParam = prAdapter->rNchoInfo.u4WesMode; + DBGLOG(INIT, TRACE, "NCHO Wes mode is %d\n", *pParam); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidSetNchoBand(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pParam = NULL; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoBand"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (uint32_t *) pvSetBuffer; + + switch (*pParam) { + case NCHO_BAND_AUTO: + prAdapter->aePreferBand[NETWORK_TYPE_AIS] = BAND_NULL; + prAdapter->rNchoInfo.eBand = NCHO_BAND_AUTO; + rStatus = WLAN_STATUS_SUCCESS; + break; + case NCHO_BAND_2G4: + prAdapter->aePreferBand[NETWORK_TYPE_AIS] = BAND_2G4; + prAdapter->rNchoInfo.eBand = NCHO_BAND_2G4; + rStatus = WLAN_STATUS_SUCCESS; + break; + case NCHO_BAND_5G: + prAdapter->aePreferBand[NETWORK_TYPE_AIS] = BAND_5G; + prAdapter->rNchoInfo.eBand = NCHO_BAND_5G; + rStatus = WLAN_STATUS_SUCCESS; + break; + default: + DBGLOG(INIT, ERROR, "NCHO wes mode invalid %d\n", *pParam); + rStatus = WLAN_STATUS_INVALID_DATA; + break; + } + + DBGLOG(INIT, INFO, "NCHO enabled:%d ,band:%d,status:%d\n" + , prAdapter->rNchoInfo.fgNCHOEnabled, *pParam, rStatus); + + + return rStatus; +} + +uint32_t +wlanoidQueryNchoBand(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t *pParam = NULL; + + DEBUGFUNC("wlanoidQueryNchoBand"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgNCHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + pParam = (uint32_t *) pvQueryBuffer; + *pParam = prAdapter->rNchoInfo.eBand; + DBGLOG(INIT, TRACE, "NCHO band is %d\n", *pParam); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidSetNchoDfsScnMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pParam = NULL; + char acCmd[NCHO_CMD_MAX_LENGTH] = {0}; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoDfsScnMode"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (uint32_t *) pvSetBuffer; + if (*pParam >= NCHO_DFS_SCN_NUM) { + DBGLOG(INIT, ERROR, "NCHO DFS scan mode invalid %d\n", + *pParam); + return WLAN_STATUS_INVALID_DATA; + } + + + kalSprintf(acCmd, "%s %d", FW_CFG_KEY_NCHO_SCAN_DFS_MODE, + *pParam); + rStatus = wlanFwCfgParse(prAdapter, acCmd); + if (rStatus == WLAN_STATUS_SUCCESS) { + prAdapter->rNchoInfo.eDFSScnMode = *pParam; + DBGLOG(INIT, TRACE, "NCHO DFS scan mode is %d\n", *pParam); + } + + return rStatus; +} + +uint32_t +wlanoidQueryNchoDfsScnMode(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER cmdV1Header; + struct CMD_HEADER *prCmdV1Header = (struct CMD_HEADER *) + pvQueryBuffer; + struct CMD_FORMAT_V1 *prCmdV1 = NULL; + + DEBUGFUNC("wlanoidQueryNchoDfsScnMode"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct CMD_HEADER); + + if (u4QueryBufferLen < sizeof(struct CMD_HEADER)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgNCHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + prCmdV1 = (struct CMD_FORMAT_V1 *) prCmdV1Header->buffer; + rStatus = wlanoidSetNchoHeader(prCmdV1Header, prCmdV1, + FW_CFG_KEY_NCHO_SCAN_DFS_MODE, + kalStrLen(FW_CFG_KEY_NCHO_SCAN_DFS_MODE)); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "NCHO no enough memory\n"); + return rStatus; + } + kalMemCopy(&cmdV1Header, prCmdV1Header, + sizeof(struct CMD_HEADER)); + rStatus = wlanSendSetQueryCmd( + prAdapter, + CMD_ID_GET_SET_CUSTOMER_CFG, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryCfgRead, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_HEADER), + (uint8_t *)&cmdV1Header, + pvQueryBuffer, + u4QueryBufferLen); + return rStatus; +} + +uint32_t +wlanoidSetNchoEnable(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pParam = NULL; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoEnable"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (uint32_t *) pvSetBuffer; + if (*pParam != 0 && *pParam != 1) { + DBGLOG(INIT, ERROR, "NCHO DFS scan mode invalid %d\n", + *pParam); + return WLAN_STATUS_INVALID_DATA; + } + + rStatus = wlanNchoSetFWEnable(prAdapter, *pParam); + if (rStatus == WLAN_STATUS_SUCCESS) { + wlanNchoInit(prAdapter, FALSE); + prAdapter->rNchoInfo.fgNCHOEnabled = *pParam; + DBGLOG(INIT, INFO, "NCHO enable is %d\n", *pParam); + } + + return rStatus; +} + +uint32_t +wlanoidQueryNchoEnable(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER cmdV1Header; + struct CMD_HEADER *prCmdV1Header = (struct CMD_HEADER *) + pvQueryBuffer; + struct CMD_FORMAT_V1 *prCmdV1 = NULL; + + DEBUGFUNC("wlanoidQueryNchoRoamTrigger"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct CMD_HEADER); + + if (u4QueryBufferLen < sizeof(struct CMD_HEADER)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + prCmdV1 = (struct CMD_FORMAT_V1 *) prCmdV1Header->buffer; + rStatus = wlanoidSetNchoHeader(prCmdV1Header, + prCmdV1, + FW_CFG_KEY_NCHO_ENABLE, + kalStrLen(FW_CFG_KEY_NCHO_ENABLE)); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "NCHO no enough memory\n"); + return rStatus; + } + kalMemCopy(&cmdV1Header, prCmdV1Header, + sizeof(struct CMD_HEADER)); + rStatus = wlanSendSetQueryCmd( + prAdapter, + CMD_ID_GET_SET_CUSTOMER_CFG, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryCfgRead, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_HEADER), + (uint8_t *)&cmdV1Header, + pvQueryBuffer, + u4QueryBufferLen); + return rStatus; +} +#endif /* CFG_SUPPORT_NCHO */ + +#if CFG_SUPPORT_EASY_DEBUG +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set fw cfg info + * + * \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_INVALID_DATA + * \retval WLAN_STATUS_SUCCESS + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanoidSetFwParam(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + ASSERT(prAdapter); + + if (!pvSetBuffer || !u4SetBufferLen) { + DBGLOG(OID, ERROR, "Buffer is NULL\n"); + return WLAN_STATUS_INVALID_DATA; + } + DBGLOG(OID, INFO, "Fw Params: %s\n", (uint8_t *)pvSetBuffer); + return wlanFwCfgParse(prAdapter, (uint8_t *)pvSetBuffer); +} +#endif /* CFG_SUPPORT_EASY_DEBUG */ + +uint32_t +wlanoidAddRoamScnChnl(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct CFG_SCAN_CHNL *prRoamScnChnl = NULL; + + *pu4SetInfoLen = sizeof(struct CFG_SCAN_CHNL); + + if (u4SetBufferLen < sizeof(struct CFG_SCAN_CHNL)) + return WLAN_STATUS_INVALID_LENGTH; + + prRoamScnChnl = (struct CFG_SCAN_CHNL *) pvSetBuffer; + + kalMemCopy(&prAdapter->rAddRoamScnChnl, prRoamScnChnl, *pu4SetInfoLen); + DBGLOG(INIT, TRACE, "set roam scan channel num is %d\n", + prRoamScnChnl->ucChannelListNum); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidAbortScan(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + + struct AIS_FSM_INFO *prAisFsmInfo = NULL; + uint8_t ucBssIndex = 0; + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + if (prAisFsmInfo->eCurrentState == AIS_STATE_SCAN || + prAisFsmInfo->eCurrentState == AIS_STATE_ONLINE_SCAN) { + DBGLOG(OID, INFO, "ucBssIndex = %d\n", ucBssIndex); + prAisFsmInfo->fgIsScanOidAborted = TRUE; + aisFsmStateAbort_SCAN(prAdapter, ucBssIndex); + } + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidDisableTdlsPs(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct CMD_TDLS_PS_T rTdlsPs; + + if (!prAdapter || !pvSetBuffer) + return WLAN_STATUS_INVALID_DATA; + + rTdlsPs.ucIsEnablePs = *(uint8_t *)pvSetBuffer - '0'; + DBGLOG(OID, INFO, "enable tdls ps %d\n", + rTdlsPs.ucIsEnablePs); + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_TDLS_PS, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(rTdlsPs), + (uint8_t *)&rTdlsPs, + NULL, + 0); +} + +uint32_t wlanoidSetSer(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t u4CmdId; + + /* check SER is supported or not */ + if (prAdapter->rWifiVar.fgEnableSer == FALSE) + return WLAN_STATUS_NOT_SUPPORTED; +#if defined(_HIF_USB) + if (prAdapter->chip_info->u4SerUsbMcuEventAddr == 0) + return WLAN_STATUS_NOT_SUPPORTED; + +#endif + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (u4SetBufferLen != sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + u4CmdId = *((uint32_t *)pvSetBuffer); + + DBGLOG(OID, INFO, "Set SER CMD[%d]\n", u4CmdId); + + switch (u4CmdId) { + case SER_USER_CMD_DISABLE: + wlanoidSerExtCmd(prAdapter, SER_ACTION_SET, + SER_SET_DISABLE, 0); + break; + + case SER_USER_CMD_ENABLE: + wlanoidSerExtCmd(prAdapter, SER_ACTION_SET, SER_SET_ENABLE, 0); + break; + + case SER_USER_CMD_ENABLE_MASK_TRACKING_ONLY: + wlanoidSerExtCmd(prAdapter, SER_ACTION_SET_ENABLE_MASK, + SER_ENABLE_TRACKING, 0); + break; + + case SER_USER_CMD_ENABLE_MASK_L1_RECOVER_ONLY: + wlanoidSerExtCmd(prAdapter, SER_ACTION_SET_ENABLE_MASK, + SER_ENABLE_TRACKING | SER_ENABLE_L1_RECOVER, + 0); + break; + + case SER_USER_CMD_ENABLE_MASK_L2_RECOVER_ONLY: + wlanoidSerExtCmd(prAdapter, SER_ACTION_SET_ENABLE_MASK, + SER_ENABLE_TRACKING | SER_ENABLE_L2_RECOVER, + 0); + break; + + case SER_USER_CMD_ENABLE_MASK_L3_RX_ABORT_ONLY: + wlanoidSerExtCmd(prAdapter, SER_ACTION_SET_ENABLE_MASK, + SER_ENABLE_TRACKING | SER_ENABLE_L3_RX_ABORT, + 0); + break; + + case SER_USER_CMD_ENABLE_MASK_L3_TX_ABORT_ONLY: + wlanoidSerExtCmd(prAdapter, SER_ACTION_SET_ENABLE_MASK, + SER_ENABLE_TRACKING | SER_ENABLE_L3_TX_ABORT, + 0); + break; + + case SER_USER_CMD_ENABLE_MASK_L3_TX_DISABLE_ONLY: + wlanoidSerExtCmd(prAdapter, SER_ACTION_SET_ENABLE_MASK, + SER_ENABLE_TRACKING | + SER_ENABLE_L3_TX_DISABLE, 0); + break; + + case SER_USER_CMD_ENABLE_MASK_L3_BFRECOVER_ONLY: + wlanoidSerExtCmd(prAdapter, SER_ACTION_SET_ENABLE_MASK, + SER_ENABLE_TRACKING | + SER_ENABLE_L3_BF_RECOVER, 0); + break; + + case SER_USER_CMD_ENABLE_MASK_RECOVER_ALL: + wlanoidSerExtCmd(prAdapter, SER_ACTION_SET_ENABLE_MASK, + (SER_ENABLE_TRACKING | + SER_ENABLE_L1_RECOVER | + SER_ENABLE_L2_RECOVER | + SER_ENABLE_L3_RX_ABORT | + SER_ENABLE_L3_TX_ABORT | + SER_ENABLE_L3_TX_DISABLE | + SER_ENABLE_L3_BF_RECOVER), 0); + break; + + case SER_USER_CMD_L0_RECOVER: + wlanoidSerExtCmd(prAdapter, SER_ACTION_RECOVER, + SER_SET_L0_RECOVER, 0); + break; + + case SER_USER_CMD_L1_RECOVER: + wlanoidSerExtCmd(prAdapter, SER_ACTION_RECOVER, + SER_SET_L1_RECOVER, 0); + break; + + case SER_USER_CMD_L2_BN0_RECOVER: + wlanoidSerExtCmd(prAdapter, SER_ACTION_RECOVER, + SER_SET_L2_RECOVER, ENUM_BAND_0); + break; + + case SER_USER_CMD_L2_BN1_RECOVER: + wlanoidSerExtCmd(prAdapter, SER_ACTION_RECOVER, + SER_SET_L2_RECOVER, ENUM_BAND_1); + break; + + case SER_USER_CMD_L3_RX0_ABORT: + wlanoidSerExtCmd(prAdapter, SER_ACTION_RECOVER, + SER_SET_L3_RX_ABORT, ENUM_BAND_0); + break; + + case SER_USER_CMD_L3_RX1_ABORT: + wlanoidSerExtCmd(prAdapter, SER_ACTION_RECOVER, + SER_SET_L3_RX_ABORT, ENUM_BAND_1); + break; + + case SER_USER_CMD_L3_TX0_ABORT: + wlanoidSerExtCmd(prAdapter, SER_ACTION_RECOVER, + SER_SET_L3_TX_ABORT, ENUM_BAND_0); + break; + + case SER_USER_CMD_L3_TX1_ABORT: + wlanoidSerExtCmd(prAdapter, SER_ACTION_RECOVER, + SER_SET_L3_TX_ABORT, ENUM_BAND_1); + break; + + case SER_USER_CMD_L3_TX0_DISABLE: + wlanoidSerExtCmd(prAdapter, SER_ACTION_RECOVER, + SER_SET_L3_TX_DISABLE, ENUM_BAND_0); + break; + + case SER_USER_CMD_L3_TX1_DISABLE: + wlanoidSerExtCmd(prAdapter, SER_ACTION_RECOVER, + SER_SET_L3_TX_DISABLE, ENUM_BAND_1); + break; + + case SER_USER_CMD_L3_BF_RECOVER: + wlanoidSerExtCmd(prAdapter, SER_ACTION_RECOVER, + SER_SET_L3_BF_RECOVER, 0); + break; + + default: + DBGLOG(OID, ERROR, "Error SER CMD\n"); + } + + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanoidSerExtCmd(IN struct ADAPTER *prAdapter, uint8_t ucAction, + uint8_t ucSerSet, uint8_t ucDbdcIdx) { + struct EXT_CMD_SER_T rCmdSer = {0}; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + rCmdSer.ucAction = ucAction; + rCmdSer.ucSerSet = ucSerSet; + rCmdSer.ucDbdcIdx = ucDbdcIdx; + + rStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_SER, + TRUE, + FALSE, + TRUE, + NULL, + nicOidCmdTimeoutCommon, + sizeof(struct EXT_CMD_SER_T), + (uint8_t *)&rCmdSer, NULL, 0); + return rStatus; +} + +#if (CFG_SUPPORT_TXPOWER_INFO == 1) +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set rdd report. + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryTxPowerInfo(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T *prTxPowerInfo = + NULL; + struct CMD_TX_POWER_SHOW_INFO_T rCmdTxPowerShowInfo; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + if (!prAdapter) + return WLAN_STATUS_FAILURE; + if (!pvQueryBuffer) + return WLAN_STATUS_FAILURE; + if (!pu4QueryInfoLen) + return WLAN_STATUS_FAILURE; + + if (u4QueryBufferLen < + sizeof(struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T)) { + *pu4QueryInfoLen = sizeof(struct + PARAM_TXPOWER_ALL_RATE_POWER_INFO_T); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + *pu4QueryInfoLen = sizeof(struct + PARAM_TXPOWER_ALL_RATE_POWER_INFO_T); + + prTxPowerInfo = (struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T + *) pvQueryBuffer; + + kalMemSet(&rCmdTxPowerShowInfo, 0, + sizeof(struct CMD_TX_POWER_SHOW_INFO_T)); + + rCmdTxPowerShowInfo.ucPowerCtrlFormatId = + TX_POWER_SHOW_INFO; + rCmdTxPowerShowInfo.ucTxPowerInfoCatg = + prTxPowerInfo->ucTxPowerCategory; + rCmdTxPowerShowInfo.ucBandIdx = prTxPowerInfo->ucBandIdx; + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_TX_POWER_FEATURE_CTRL, + FALSE, /* Query Bit: True->write False->read */ + TRUE, + TRUE, + nicCmdEventQueryTxPowerInfo, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_TX_POWER_SHOW_INFO_T), + (uint8_t *) (&rCmdTxPowerShowInfo), + pvQueryBuffer, + u4QueryBufferLen); + + return rWlanStatus; +} +#endif +uint32_t +wlanoidSetTxPowerByRateManual(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + + struct PARAM_TXPOWER_BY_RATE_SET_T *prPwrParam; + struct CMD_POWER_RATE_TXPOWER_CTRL_T rCmdPwrCtl; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + if (!prAdapter) + return WLAN_STATUS_FAILURE; + if (!pvSetBuffer) + return WLAN_STATUS_FAILURE; + + prPwrParam = (struct PARAM_TXPOWER_BY_RATE_SET_T + *) pvSetBuffer; + + kalMemSet(&rCmdPwrCtl, 0, + sizeof(struct CMD_POWER_RATE_TXPOWER_CTRL_T)); + + rCmdPwrCtl.u1PowerCtrlFormatId = TX_RATE_POWER_CTRL; + rCmdPwrCtl.u1PhyMode = prPwrParam->u1PhyMode; + rCmdPwrCtl.u1TxRate = prPwrParam->u1TxRate; + rCmdPwrCtl.u1BW = prPwrParam->u1BW; + rCmdPwrCtl.i1TxPower = prPwrParam->i1TxPower; + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_TX_POWER_FEATURE_CTRL, + TRUE, /* Query Bit: True->write False->read */ + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(rCmdPwrCtl), + (uint8_t *) (&rCmdPwrCtl), + NULL, + 0); + + return rWlanStatus; +} + +#if CFG_SUPPORT_MBO +uint32_t +wlanoidBssDisallowedList(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct WIFI_VAR *prWifiVar = NULL; + + + if (!prAdapter || !u4SetBufferLen || !pvSetBuffer || + u4SetBufferLen != sizeof(struct PARAM_BSS_DISALLOWED_LIST)) + return WLAN_STATUS_NOT_ACCEPTED; + + prWifiVar = &prAdapter->rWifiVar; + kalMemCopy(&prWifiVar->rBssDisallowedList, pvSetBuffer, u4SetBufferLen); + DBGLOG(OID, INFO, "Set disallowed list size: %d\n", + prWifiVar->rBssDisallowedList.u4NumBssDisallowed); + return WLAN_STATUS_SUCCESS; +} +#endif + +uint32_t +wlanoidSetDrvRoamingPolicy(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t u4RoamingPoily = 0; + struct ROAMING_INFO *prRoamingFsmInfo; + struct CONNECTION_SETTINGS *prConnSettings; + uint32_t u4CurConPolicy; + uint8_t ucBssIndex = 0; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + + u4RoamingPoily = *(uint32_t *)pvSetBuffer; + + prRoamingFsmInfo = + aisGetRoamingInfo(prAdapter, ucBssIndex); + + prConnSettings = (struct CONNECTION_SETTINGS *) + aisGetConnSettings(prAdapter, ucBssIndex); + u4CurConPolicy = prConnSettings->eConnectionPolicy; + + if (u4RoamingPoily == 1) { + if (((aisGetCurrState(prAdapter, ucBssIndex) == + AIS_STATE_NORMAL_TR) + || (aisGetCurrState(prAdapter, ucBssIndex) == + AIS_STATE_ONLINE_SCAN)) + && (prRoamingFsmInfo->eCurrentState == ROAMING_STATE_IDLE)) + prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_BEST_RSSI; + roamingFsmRunEventStart(prAdapter, ucBssIndex); + } else { + if (prRoamingFsmInfo->eCurrentState != ROAMING_STATE_IDLE) + roamingFsmRunEventAbort(prAdapter, ucBssIndex); + } + prRoamingFsmInfo->fgDrvRoamingAllow = (u_int8_t) + u4RoamingPoily; + + DBGLOG(REQ, INFO, + "wlanoidSetDrvRoamingPolicy, RoamingPoily= %d, conn policy= [%d] -> [%d]\n", + u4RoamingPoily, u4CurConPolicy, + prConnSettings->eConnectionPolicy); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanoidUpdateFtIes(struct ADAPTER *prAdapter, void *pvSetBuffer, + uint32_t u4SetBufferLen, uint32_t *pu4SetInfoLen) +{ + struct FT_IES *prFtIes = NULL; + uint32_t u4IeLen = 0; + uint8_t *pucIEStart = NULL; + struct cfg80211_update_ft_ies_params *ftie = NULL; + struct STA_RECORD *prStaRec = NULL; + struct MSG_SAA_FT_CONTINUE *prFtContinueMsg = NULL; + uint8_t ucBssIndex = 0; + + if (!pvSetBuffer || u4SetBufferLen == 0) { + DBGLOG(OID, ERROR, + "FT: pvSetBuffer is Null %d, Buffer Len %u\n", + !pvSetBuffer, u4SetBufferLen); + return WLAN_STATUS_INVALID_DATA; + } + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + + prStaRec = aisGetTargetStaRec(prAdapter, ucBssIndex); + ftie = (struct cfg80211_update_ft_ies_params *)pvSetBuffer; + prFtIes = aisGetFtIe(prAdapter, ucBssIndex); + if (ftie->ie_len == 0) { + DBGLOG(OID, WARN, "FT: FT Ies length is 0\n"); + return WLAN_STATUS_SUCCESS; + } + if (prFtIes->u4IeLength != ftie->ie_len) { + kalMemFree(prFtIes->pucIEBuf, VIR_MEM_TYPE, + prFtIes->u4IeLength); + prFtIes->pucIEBuf = kalMemAlloc(ftie->ie_len, VIR_MEM_TYPE); + prFtIes->u4IeLength = ftie->ie_len; + } + + if (!prFtIes->pucIEBuf) { + DBGLOG(OID, ERROR, + "FT: prFtIes->pucIEBuf memory allocation failed, ft ie_len=%u\n", + ftie->ie_len); + return WLAN_STATUS_FAILURE; + } + + pucIEStart = prFtIes->pucIEBuf; + u4IeLen = prFtIes->u4IeLength; + prFtIes->u2MDID = ftie->md; + prFtIes->prFTIE = NULL; + prFtIes->prMDIE = NULL; + prFtIes->prRsnIE = NULL; + prFtIes->prTIE = NULL; + if (u4IeLen) + kalMemCopy(pucIEStart, ftie->ie, u4IeLen); + while (u4IeLen >= 2) { + uint32_t u4InfoElemLen = IE_SIZE(pucIEStart); + + if (u4InfoElemLen > u4IeLen) + break; + switch (pucIEStart[0]) { + case ELEM_ID_MOBILITY_DOMAIN: + prFtIes->prMDIE = + (struct IE_MOBILITY_DOMAIN *)pucIEStart; + break; + case ELEM_ID_FAST_TRANSITION: + prFtIes->prFTIE = + (struct IE_FAST_TRANSITION *)pucIEStart; + break; + case ELEM_ID_RESOURCE_INFO_CONTAINER: + break; + case ELEM_ID_TIMEOUT_INTERVAL: + prFtIes->prTIE = + (struct IE_TIMEOUT_INTERVAL *)pucIEStart; + break; + case ELEM_ID_RSN: + prFtIes->prRsnIE = (struct RSN_INFO_ELEM *)pucIEStart; + break; + } + u4IeLen -= u4InfoElemLen; + pucIEStart += u4InfoElemLen; + } + DBGLOG(OID, INFO, + "FT: MdId %d IesLen %u, MDIE %d FTIE %d RSN %d TIE %d\n", + ftie->md, prFtIes->u4IeLength, !!prFtIes->prMDIE, + !!prFtIes->prFTIE, !!prFtIes->prRsnIE, !!prFtIes->prTIE); + /* check if SAA is waiting to send Reassoc req */ + if (!prStaRec || prStaRec->ucAuthTranNum != AUTH_TRANSACTION_SEQ_2 || + !prStaRec->fgIsReAssoc || prStaRec->ucStaState != STA_STATE_1) + return WLAN_STATUS_SUCCESS; + + prFtContinueMsg = (struct MSG_SAA_FT_CONTINUE *)cnmMemAlloc( + prAdapter, RAM_TYPE_MSG, sizeof(struct MSG_SAA_FT_CONTINUE)); + if (!prFtContinueMsg) { + DBGLOG(OID, WARN, "FT: failed to allocate Join Req Msg\n"); + return WLAN_STATUS_FAILURE; + } + prFtContinueMsg->rMsgHdr.eMsgId = MID_OID_SAA_FSM_CONTINUE; + prFtContinueMsg->prStaRec = prStaRec; + /* ToDo: for Resource Request Protocol, we need to check if RIC request + ** is included. + */ + if (prFtIes->prMDIE && (prFtIes->prMDIE->ucBitMap & BIT(1))) + prFtContinueMsg->fgFTRicRequest = TRUE; + else + prFtContinueMsg->fgFTRicRequest = FALSE; + DBGLOG(OID, INFO, "FT: continue to do auth/assoc, Ft Request %d\n", + prFtContinueMsg->fgFTRicRequest); + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *)prFtContinueMsg, + MSG_SEND_METHOD_BUF); + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanoidSendNeighborRequest(struct ADAPTER *prAdapter, + void *pvSetBuffer, uint32_t u4SetBufferLen, + uint32_t *pu4SetInfoLen) +{ + struct SUB_ELEMENT_LIST *prSSIDIE = NULL; + struct BSS_INFO *prAisBssInfo = NULL; + uint8_t ucSSIDIELen = 0; + uint8_t *pucSSID = (uint8_t *)pvSetBuffer; + uint8_t ucBssIndex = 0; + + if (!prAdapter) + return WLAN_STATUS_INVALID_DATA; + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + if (!prAisBssInfo) + return WLAN_STATUS_INVALID_DATA; + if (prAisBssInfo->eConnectionState != MEDIA_STATE_CONNECTED) { + DBGLOG(OID, ERROR, "didn't connected any Access Point\n"); + return WLAN_STATUS_FAILURE; + } + if (u4SetBufferLen == 0 || !pucSSID) { + rrmTxNeighborReportRequest(prAdapter, + prAisBssInfo->prStaRecOfAP, NULL); + return WLAN_STATUS_SUCCESS; + } + + ucSSIDIELen = (uint8_t)(u4SetBufferLen + sizeof(*prSSIDIE)); + prSSIDIE = kalMemAlloc(ucSSIDIELen, PHY_MEM_TYPE); + if (!prSSIDIE) { + DBGLOG(OID, ERROR, "No Memory\n"); + return WLAN_STATUS_FAILURE; + } + prSSIDIE->prNext = NULL; + prSSIDIE->rSubIE.ucSubID = ELEM_ID_SSID; + prSSIDIE->rSubIE.ucLength = (uint8_t)u4SetBufferLen; + kalMemCopy(&prSSIDIE->rSubIE.aucOptInfo[0], pucSSID, + (uint8_t)u4SetBufferLen); + DBGLOG(OID, INFO, "Send Neighbor Request, SSID=%s\n", HIDE(pucSSID)); + rrmTxNeighborReportRequest(prAdapter, prAisBssInfo->prStaRecOfAP, + prSSIDIE); + kalMemFree(prSSIDIE, PHY_MEM_TYPE, ucSSIDIELen); + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanoidSync11kCapabilities(struct ADAPTER *prAdapter, + void *pvSetBuffer, uint32_t u4SetBufferLen, + uint32_t *pu4SetInfoLen) +{ + struct CMD_SET_RRM_CAPABILITY rCmdRrmCapa; + + kalMemZero(&rCmdRrmCapa, sizeof(rCmdRrmCapa)); + rCmdRrmCapa.ucCmdVer = 0x1; + rCmdRrmCapa.ucRrmEnable = 1; + rrmFillRrmCapa(&rCmdRrmCapa.ucCapabilities[0]); + rCmdRrmCapa.ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RRM_CAPABILITY, + TRUE, + FALSE, + TRUE, + NULL, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_SET_RRM_CAPABILITY), + (uint8_t *)&rCmdRrmCapa, + pvSetBuffer, u4SetBufferLen); + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanoidSendBTMQuery(struct ADAPTER *prAdapter, void *pvSetBuffer, + uint32_t u4SetBufferLen, uint32_t *pu4SetInfoLen) +{ + struct STA_RECORD *prStaRec = NULL; + struct BSS_TRANSITION_MGT_PARAM_T *prBtmMgt = NULL; + struct BSS_INFO *prAisBssInfo; + uint8_t ucBssIndex = 0; + int32_t u4Ret = 0; + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + + if (!prAisBssInfo || + prAisBssInfo->eConnectionState != + MEDIA_STATE_CONNECTED) { + DBGLOG(OID, INFO, "Not connected yet\n"); + return WLAN_STATUS_FAILURE; + } + prStaRec = prAisBssInfo->prStaRecOfAP; + if (!prStaRec || !prStaRec->fgSupportBTM) { + DBGLOG(OID, INFO, + "Target BSS(%p) didn't support Bss Transition Management\n", + prStaRec); + return WLAN_STATUS_FAILURE; + } + prBtmMgt = aisGetBTMParam(prAdapter, ucBssIndex); + prBtmMgt->ucDialogToken = wnmGetBtmToken(); + if (pvSetBuffer) { + u4Ret = kalkStrtou8(pvSetBuffer, 0, &prBtmMgt->ucQueryReason); + if (u4Ret) + DBGLOG(OID, WARN, "parse reason u4Ret=%d\n", u4Ret); + } else { + prBtmMgt->ucQueryReason = BSS_TRANSITION_LOW_RSSI; + } + DBGLOG(OID, INFO, "Send BssTransitionManagementQuery, Reason %d\n", + prBtmMgt->ucQueryReason); + wnmSendBTMQueryFrame(prAdapter, prStaRec); + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanoidTspecOperation(struct ADAPTER *prAdapter, void *pvBuffer, + uint32_t u4BufferLen, uint32_t *pu4InfoLen) +{ + struct PARAM_QOS_TSPEC *prTspecParam = NULL; + struct MSG_TS_OPERATE *prMsgTsOperate = NULL; + uint8_t *pucCmd = (uint8_t *)pvBuffer; + uint8_t *pucSavedPtr = NULL; + uint8_t *pucItem = NULL; + uint32_t u4Ret = 1; + uint8_t ucApsdSetting = 2; /* 0: legacy; 1: u-apsd; 2: not set yet */ + uint8_t ucBssIndex = 0; + enum TSPEC_OP_CODE eTsOp; + struct BSS_INFO *prAisBssInfo; + +#if !CFG_SUPPORT_WMM_AC + DBGLOG(OID, INFO, "WMM AC is not supported\n"); + return WLAN_STATUS_FAILURE; +#endif + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + + if (kalStrniCmp(pucCmd, "dumpts", 6) == 0) { + *pu4InfoLen = kalSnprintf(pucCmd, u4BufferLen, "%s", + "\nAll Active Tspecs:\n"); + u4BufferLen -= *pu4InfoLen; + pucCmd += *pu4InfoLen; + *pu4InfoLen += + wmmDumpActiveTspecs(prAdapter, pucCmd, u4BufferLen, + ucBssIndex); + return WLAN_STATUS_SUCCESS; + } + + if (kalStrniCmp(pucCmd, "addts", 5) == 0) + eTsOp = TX_ADDTS_REQ; + else if (kalStrniCmp(pucCmd, "delts", 5) == 0) + eTsOp = TX_DELTS_REQ; + else { + DBGLOG(OID, INFO, "wrong operation %s\n", pucCmd); + return WLAN_STATUS_FAILURE; + } + /* addts token n,tid n,dir n,psb n,up n,fixed n,size n,maxsize + ** n,maxsrvint n, minsrvint n, + ** inact n, suspension n, srvstarttime n, minrate n,meanrate n,peakrate + ** n,burst n,delaybound n, + ** phyrate n,SBA n,mediumtime n + */ + prMsgTsOperate = (struct MSG_TS_OPERATE *)cnmMemAlloc( + prAdapter, RAM_TYPE_MSG, sizeof(struct MSG_TS_OPERATE)); + if (!prMsgTsOperate) + return WLAN_STATUS_FAILURE; + + kalMemZero(prMsgTsOperate, sizeof(struct MSG_TS_OPERATE)); + prMsgTsOperate->rMsgHdr.eMsgId = MID_OID_WMM_TSPEC_OPERATE; + prMsgTsOperate->eOpCode = eTsOp; + prTspecParam = &prMsgTsOperate->rTspecParam; + pucCmd += 6; + pucItem = (uint8_t *)kalStrtokR(pucCmd, ",", &pucSavedPtr); + while (pucItem) { + if (kalStrniCmp(pucItem, "token ", 6) == 0) + u4Ret = kalkStrtou8(pucItem + 6, 0, + &prTspecParam->ucDialogToken); + else if (kalStrniCmp(pucItem, "tid ", 4) == 0) { + u4Ret = kalkStrtou8(pucItem + 4, 0, + &prMsgTsOperate->ucTid); + prTspecParam->rTsInfo.ucTid = prMsgTsOperate->ucTid; + } else if (kalStrniCmp(pucItem, "dir ", 4) == 0) + u4Ret = kalkStrtou8(pucItem + 4, 0, + &prTspecParam->rTsInfo.ucDirection); + else if (kalStrniCmp(pucItem, "psb ", 4) == 0) + u4Ret = kalkStrtou8(pucItem+4, 0, &ucApsdSetting); + else if (kalStrniCmp(pucItem, "up ", 3) == 0) + u4Ret = kalkStrtou8(pucItem + 3, 0, + &prTspecParam->rTsInfo.ucuserPriority); + else if (kalStrniCmp(pucItem, "size ", 5) == 0) { + uint16_t u2Size = 0; + + u4Ret = kalkStrtou16(pucItem+5, 0, &u2Size); + prTspecParam->u2NominalMSDUSize |= u2Size; + } else if (kalStrniCmp(pucItem, "fixed ", 6) == 0) { + uint8_t ucFixed = 0; + + u4Ret = kalkStrtou8(pucItem+6, 0, &ucFixed); + if (ucFixed) + prTspecParam->u2NominalMSDUSize |= BIT(15); + } else if (kalStrniCmp(pucItem, "maxsize ", 8) == 0) + u4Ret = kalkStrtou16(pucItem + 8, 0, + &prTspecParam->u2MaxMSDUsize); + else if (kalStrniCmp(pucItem, "maxsrvint ", 10) == 0) + u4Ret = kalkStrtou32(pucItem + 10, 0, + &prTspecParam->u4MaxSvcIntv); + else if (kalStrniCmp(pucItem, "minsrvint ", 10) == 0) + u4Ret = kalkStrtou32(pucItem + 10, 0, + &prTspecParam->u4MinSvcIntv); + else if (kalStrniCmp(pucItem, "inact ", 6) == 0) + u4Ret = kalkStrtou32(pucItem + 6, 0, + &prTspecParam->u4InactIntv); + else if (kalStrniCmp(pucItem, "suspension ", 11) == 0) + u4Ret = kalkStrtou32(pucItem + 11, 0, + &prTspecParam->u4SpsIntv); + else if (kalStrniCmp(pucItem, "srvstarttime ", 13) == 0) + u4Ret = kalkStrtou32(pucItem + 13, 0, + &prTspecParam->u4SvcStartTime); + else if (kalStrniCmp(pucItem, "minrate ", 8) == 0) + u4Ret = kalkStrtou32(pucItem + 8, 0, + &prTspecParam->u4MinDataRate); + else if (kalStrniCmp(pucItem, "meanrate ", 9) == 0) + u4Ret = kalkStrtou32(pucItem + 9, 0, + &prTspecParam->u4MeanDataRate); + else if (kalStrniCmp(pucItem, "peakrate ", 9) == 0) + u4Ret = kalkStrtou32(pucItem + 9, 0, + &prTspecParam->u4PeakDataRate); + else if (kalStrniCmp(pucItem, "burst ", 6) == 0) + u4Ret = kalkStrtou32(pucItem + 6, 0, + &prTspecParam->u4MaxBurstSize); + else if (kalStrniCmp(pucItem, "delaybound ", 11) == 0) + u4Ret = kalkStrtou32(pucItem + 11, 0, + &prTspecParam->u4DelayBound); + else if (kalStrniCmp(pucItem, "phyrate ", 8) == 0) + u4Ret = kalkStrtou32(pucItem + 8, 0, + &prTspecParam->u4MinPHYRate); + else if (kalStrniCmp(pucItem, "sba ", 4) == 0) + u4Ret = wlanDecimalStr2Hexadecimals( + pucItem + 4, &prTspecParam->u2Sba); + else if (kalStrniCmp(pucItem, "mediumtime ", 11) == 0) + u4Ret = kalkStrtou16(pucItem + 11, 0, + &prTspecParam->u2MediumTime); + + if (u4Ret) { + DBGLOG(OID, ERROR, "Parse %s error\n", pucItem); + cnmMemFree(prAdapter, prMsgTsOperate); + return WLAN_STATUS_FAILURE; + } + pucItem = + (uint8_t *)kalStrtokR(NULL, ",", &pucSavedPtr); + } + /* if APSD is not set in addts request, use global wmmps settings */ + prAisBssInfo = + aisGetAisBssInfo(prAdapter, ucBssIndex); + if (!prAisBssInfo) + DBGLOG(OID, ERROR, "AisBssInfo is NULL!\n"); + else if (ucApsdSetting == 2) { + struct PM_PROFILE_SETUP_INFO *prPmProf = NULL; + enum ENUM_ACI eAc = + aucUp2ACIMap[prTspecParam->rTsInfo.ucuserPriority]; + + prPmProf = &prAisBssInfo->rPmProfSetupInfo; + switch (prTspecParam->rTsInfo.ucDirection) { + case UPLINK_TS: /* UpLink*/ + if (prPmProf->ucBmpTriggerAC & BIT(eAc)) + prTspecParam->rTsInfo.ucApsd = 1; + break; + case DOWNLINK_TS:/* DownLink */ + if (prPmProf->ucBmpDeliveryAC & BIT(eAc)) + prTspecParam->rTsInfo.ucApsd = 1; + break; + case BI_DIR_TS: /* Bi-directional */ + if ((prPmProf->ucBmpTriggerAC & BIT(eAc)) && + (prPmProf->ucBmpDeliveryAC & BIT(eAc))) + prTspecParam->rTsInfo.ucApsd = 1; + break; + } + } else + prTspecParam->rTsInfo.ucApsd = ucApsdSetting; + *(--pucCmd) = 0; + pucCmd -= 5; + DBGLOG(OID, INFO, + "%d: %s %d %d %d %d %d %d %d %u %u %u %u %u %u %u %u %u %u %u 0x%04x %d\n", + ucBssIndex, + pucCmd, prTspecParam->ucDialogToken, prTspecParam->rTsInfo.ucTid, + prTspecParam->rTsInfo.ucDirection, prTspecParam->rTsInfo.ucApsd, + prTspecParam->rTsInfo.ucuserPriority, + prTspecParam->u2NominalMSDUSize, prTspecParam->u2MaxMSDUsize, + prTspecParam->u4MaxSvcIntv, prTspecParam->u4MinSvcIntv, + prTspecParam->u4InactIntv, prTspecParam->u4SpsIntv, + prTspecParam->u4SvcStartTime, prTspecParam->u4MinDataRate, + prTspecParam->u4MeanDataRate, prTspecParam->u4PeakDataRate, + prTspecParam->u4MaxBurstSize, prTspecParam->u4DelayBound, + prTspecParam->u4MinPHYRate, prTspecParam->u2Sba, + prTspecParam->u2MediumTime); + prMsgTsOperate->ucBssIdx = ucBssIndex; + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *)prMsgTsOperate, + MSG_SEND_METHOD_BUF); + return WLAN_STATUS_SUCCESS; +} + +/* It's a Integretion Test function for RadioMeasurement. If you found errors +** during doing Radio Measurement, +** you can run this IT function with iwpriv wlan0 driver \"RM-IT +** xx,xx,xx, xx\" +** xx,xx,xx,xx is the RM request frame data +*/ +uint32_t wlanoidPktProcessIT(struct ADAPTER *prAdapter, void *pvBuffer, + uint32_t u4BufferLen, uint32_t *pu4InfoLen) +{ + struct SW_RFB rSwRfb; + static uint8_t aucPacket[200] = {0,}; + uint8_t *pucSavedPtr = (int8_t *)pvBuffer; + uint8_t *pucItem = NULL; + uint8_t j = 0; + int8_t i = 0; + uint8_t ucByte; + u_int8_t fgBTMReq = FALSE; + void (*process_func)(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); + uint8_t ucBssIndex = 0; + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + + if (!pvBuffer) { + DBGLOG(OID, ERROR, "pvBuffer is NULL\n"); + return WLAN_STATUS_FAILURE; + } + + if (!kalStrniCmp(pucSavedPtr, "RM-IT", 5)) { + process_func = rrmProcessRadioMeasurementRequest; + pucSavedPtr += 5; + } else if (!kalStrniCmp(pucSavedPtr, "BTM-IT", 6)) { + process_func = wnmRecvBTMRequest; + pucSavedPtr += 6; + fgBTMReq = TRUE; + } else if (!kalStrniCmp(pucSavedPtr, "BT-IT", 5)) { + DBGLOG(OID, INFO, "Simulate beacon timeout!!!\n"); + aisBssBeaconTimeout(prAdapter, ucBssIndex); + return WLAN_STATUS_SUCCESS; + } else { + pucSavedPtr[10] = 0; + DBGLOG(OID, ERROR, "IT type %s is not supported\n", + pucSavedPtr); + return WLAN_STATUS_NOT_SUPPORTED; + } + kalMemZero(aucPacket, sizeof(aucPacket)); + pucItem = kalStrtokR(pucSavedPtr, ",", &pucSavedPtr); + while (pucItem) { + ucByte = *pucItem; + i = 0; + while (ucByte) { + if (i > 1) { + DBGLOG(OID, ERROR, + "more than 2 char for one byte\n"); + return WLAN_STATUS_FAILURE; + } else if (i == 1) + aucPacket[j] <<= 4; + if (ucByte >= '0' && ucByte <= '9') + aucPacket[j] |= ucByte - '0'; + else if (ucByte >= 'a' && ucByte <= 'f') + aucPacket[j] |= ucByte - 'a' + 10; + else if (ucByte >= 'A' && ucByte <= 'F') + aucPacket[j] |= ucByte - 'A' + 10; + else { + DBGLOG(OID, ERROR, "not a hex char %c\n", + ucByte); + return WLAN_STATUS_FAILURE; + } + ucByte = *(++pucItem); + i++; + } + j++; + pucItem = kalStrtokR(NULL, ",", &pucSavedPtr); + } + DBGLOG(OID, INFO, "Dump IT packet, len %d\n", j); + dumpMemory8(aucPacket, j); + if (j < WLAN_MAC_MGMT_HEADER_LEN) { + DBGLOG(OID, ERROR, "packet length %d less than mac header 24\n", + j); + return WLAN_STATUS_FAILURE; + } + kalMemZero(&rSwRfb, sizeof(rSwRfb)); + rSwRfb.pvHeader = (void *)&aucPacket[0]; + rSwRfb.u2PacketLen = j; + rSwRfb.u2HeaderLen = WLAN_MAC_MGMT_HEADER_LEN; + rSwRfb.ucStaRecIdx = KAL_NETWORK_TYPE_AIS_INDEX; + if (fgBTMReq) { + struct HW_MAC_RX_DESC rRxStatus; + + rRxStatus.ucChanFreq = 6; + rSwRfb.ucChnlNum = HAL_RX_STATUS_GET_CHNL_NUM(&rRxStatus); + rSwRfb.prRxStatus = (void *)&rRxStatus; + rSwRfb.ucChanFreq = 6; + wnmWNMAction(prAdapter, &rSwRfb); + } else { + process_func(prAdapter, &rSwRfb); + } + + return WLAN_STATUS_SUCCESS; +} + +/* Firmware Integration Test functions +** This function receives commands that are input by a firmware IT test script +** By using IT test script, RD no need to run IT with a real Access Point +** For example: iwpriv wlan0 driver \"Fw-Event Roaming ....\" +*/ +uint32_t wlanoidFwEventIT(struct ADAPTER *prAdapter, void *pvBuffer, + uint32_t u4BufferLen, uint32_t *pu4InfoLen) +{ + uint8_t *pucCmd = (int8_t *)pvBuffer; + uint8_t ucBssIndex = 0; + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + + /* Firmware roaming Integration Test case */ + if (!kalStrniCmp(pucCmd, "Roaming", 7)) { + struct CMD_ROAMING_TRANSIT rTransit = {0}; + struct BSS_DESC *prBssDesc = + aisGetTargetBssDesc(prAdapter, ucBssIndex); + + if (prBssDesc) + rTransit.u2Data = prBssDesc->ucRCPI; + rTransit.u2Event = ROAMING_EVENT_DISCOVERY; + rTransit.eReason = ROAMING_REASON_POOR_RCPI; + rTransit.ucBssidx = ucBssIndex; + roamingFsmRunEventDiscovery(prAdapter, &rTransit); + } else { + DBGLOG(OID, ERROR, "Not supported Fw Event IT type %s\n", + pucCmd); + return WLAN_STATUS_FAILURE; + } + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanoidDumpUapsdSetting(struct ADAPTER *prAdapter, void *pvBuffer, + uint32_t u4BufferLen, uint32_t *pu4InfoLen) +{ + uint8_t *pucCmd = (uint8_t *)pvBuffer; + uint8_t ucFinalSetting = 0; + uint8_t ucStaticSetting = 0; + struct PM_PROFILE_SETUP_INFO *prPmProf = NULL; + struct BSS_INFO *prAisBssInfo; + uint8_t ucBssIndex = 0; + + if (!pvBuffer) { + DBGLOG(OID, ERROR, "pvBuffer is NULL\n"); + return WLAN_STATUS_FAILURE; + } + + ucBssIndex = GET_IOCTL_BSSIDX(prAdapter); + + prAisBssInfo = + aisGetAisBssInfo(prAdapter, ucBssIndex); + + if (!prAisBssInfo) + return WLAN_STATUS_FAILURE; + prPmProf = &prAisBssInfo->rPmProfSetupInfo; + ucStaticSetting = + (prPmProf->ucBmpDeliveryAC << 4) | prPmProf->ucBmpTriggerAC; + ucFinalSetting = wmmCalculateUapsdSetting(prAdapter, ucBssIndex); + *pu4InfoLen = kalSnprintf( + pucCmd, u4BufferLen, + "\nStatic Uapsd Setting:0x%02x\nFinal Uapsd Setting:0x%02x", + ucStaticSetting, ucFinalSetting); + return WLAN_STATUS_SUCCESS; +} + +#if CFG_SUPPORT_OSHARE +uint32_t +wlanoidSetOshareMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + if (!prAdapter || !pvSetBuffer) + return WLAN_STATUS_INVALID_DATA; + + DBGLOG(OID, TRACE, "wlanoidSetOshareMode\n"); + + return wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_OSHARE_MODE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + TRUE, /* fgIsOid */ + nicCmdEventSetCommon, /* pfCmdDoneHandler*/ + nicOidCmdTimeoutCommon, /* pfCmdTimeoutHandler */ + u4SetBufferLen, /* u4SetQueryInfoLen */ + (uint8_t *) pvSetBuffer,/* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0); /* u4SetQueryBufferLen */ +} +#endif + +uint32_t +wlanoidQueryWifiLogLevelSupport(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_WIFI_LOG_LEVEL_UI *pparam; + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + pparam = (struct PARAM_WIFI_LOG_LEVEL_UI *) pvQueryBuffer; + pparam->u4Enable = wlanDbgLevelUiSupport(prAdapter, + pparam->u4Version, pparam->u4Module); + + DBGLOG(OID, INFO, "version: %d, module: %d, enable: %d\n", + pparam->u4Version, + pparam->u4Module, + pparam->u4Enable); + + *pu4QueryInfoLen = sizeof(struct PARAM_WIFI_LOG_LEVEL_UI); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidQueryWifiLogLevel(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_WIFI_LOG_LEVEL *pparam; + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + pparam = (struct PARAM_WIFI_LOG_LEVEL *) pvQueryBuffer; + pparam->u4Level = wlanDbgGetLogLevelImpl(prAdapter, + pparam->u4Version, + pparam->u4Module); + + DBGLOG(OID, INFO, "version: %d, module: %d, level: %d\n", + pparam->u4Version, + pparam->u4Module, + pparam->u4Level); + + *pu4QueryInfoLen = sizeof(struct PARAM_WIFI_LOG_LEVEL_UI); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidSetWifiLogLevel(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_WIFI_LOG_LEVEL *pparam; + + ASSERT(prAdapter); + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + pparam = (struct PARAM_WIFI_LOG_LEVEL *) pvSetBuffer; + + DBGLOG(OID, INFO, "version: %d, module: %d, level: %d\n", + pparam->u4Version, + pparam->u4Module, + pparam->u4Level); + + wlanDbgSetLogLevelImpl(prAdapter, + pparam->u4Version, + pparam->u4Module, + pparam->u4Level); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanoidSetDrvSer(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + ASSERT(prAdapter); + + prAdapter->u4HifChkFlag |= HIF_DRV_SER; + kalSetHifDbgEvent(prAdapter->prGlueInfo); + + return 0; +} + +uint32_t wlanoidSetAmsduNum(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct mt66xx_chip_info *prChipInfo = NULL; + + ASSERT(prAdapter); + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prChipInfo = prAdapter->chip_info; + prChipInfo->ucMaxSwAmsduNum = (uint8_t)*((uint32_t *)pvSetBuffer); + DBGLOG(OID, INFO, "Set SW AMSDU Num: %d\n", + prChipInfo->ucMaxSwAmsduNum); + return 0; +} + +uint32_t wlanoidSetAmsduSize(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct mt66xx_chip_info *prChipInfo = NULL; + struct WIFI_VAR *prWifiVar = NULL; + + ASSERT(prAdapter); + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prChipInfo = prAdapter->chip_info; + prWifiVar = &prAdapter->rWifiVar; + prWifiVar->u4TxMaxAmsduInAmpduLen = *((uint32_t *)pvSetBuffer); + DBGLOG(OID, INFO, "Set SW AMSDU max Size: %d\n", + prWifiVar->u4TxMaxAmsduInAmpduLen); + return 0; +} + +uint32_t +wlanoidShowPdmaInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + prAdapter->u4HifDbgFlag |= DEG_HIF_PDMA; + kalSetHifDbgEvent(prAdapter->prGlueInfo); + + return 0; +} + +uint32_t +wlanoidShowPseInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + prAdapter->u4HifDbgFlag |= DEG_HIF_PSE; + kalSetHifDbgEvent(prAdapter->prGlueInfo); + + return 0; +} + +uint32_t +wlanoidShowPleInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + prAdapter->u4HifDbgFlag |= DEG_HIF_PLE; + kalSetHifDbgEvent(prAdapter->prGlueInfo); + + return 0; +} + +uint32_t +wlanoidShowCsrInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + prAdapter->u4HifDbgFlag |= DEG_HIF_HOST_CSR; + kalSetHifDbgEvent(prAdapter->prGlueInfo); + + return 0; +} + +uint32_t +wlanoidShowDmaschInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + prAdapter->u4HifDbgFlag |= DEG_HIF_DMASCH; + kalSetHifDbgEvent(prAdapter->prGlueInfo); + + return 0; +} + +#if CFG_SUPPORT_LOWLATENCY_MODE +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to enable/disable low latency mode from oid + * + * \param[in] prAdapter A pointer to the Adapter structure. + * \param[in] pvSetBuffer A pointer to the buffer that holds the + * OID-specific data to be set. + * \param[in] u4SetBufferLen The number of bytes the set buffer. + * \param[out] pu4SetInfoLen Points to the number of bytes it read or is + * needed + * \retval WLAN_STATUS_SUCCESS + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanoidSetLowLatencyMode( + IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t u4Events; + struct BSS_INFO *prAisBssInfo; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + DEBUGFUNC("wlanoidSetLowLatencyMode"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + if (u4SetBufferLen != sizeof(uint32_t)) { + *pu4SetInfoLen = sizeof(uint32_t); + return WLAN_STATUS_INVALID_LENGTH; + } + ASSERT(pu4SetInfoLen); + + prAisBssInfo = + aisGetAisBssInfo(prAdapter, ucBssIndex); + if (!prAisBssInfo) { + DBGLOG(OID, ERROR, "prAisBssInfo = NULL\n"); + *pu4SetInfoLen = 0; + return WLAN_STATUS_FAILURE; + } + + /* Initialize */ + kalMemCopy(&u4Events, pvSetBuffer, u4SetBufferLen); + + /* Set low latency mode */ + DBGLOG(OID, INFO, "DPP LowLatencySet(from oid set) event:0x%x\n", + u4Events); + wlanSetLowLatencyMode(prAdapter, u4Events); + + *pu4SetInfoLen = 0; /* We do not need to read */ + + return WLAN_STATUS_SUCCESS; +} + +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + +uint32_t wlanoidGetWifiType(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct PARAM_GET_WIFI_TYPE *prParamGetWifiType; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate; + struct BSS_INFO *prBssInfo = NULL; + uint8_t ucBssIdx; + uint8_t ucPhyType; + uint8_t ucMaxCopySize; + uint8_t *pNameBuf; + *pu4SetInfoLen = 0; + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, ERROR, + "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + prParamGetWifiType = (struct PARAM_GET_WIFI_TYPE *)pvSetBuffer; + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prParamGetWifiType->prNetDev); + ucBssIdx = prNetDevPrivate->ucBssIdx; + DBGLOG(OID, INFO, "bss index=%d\n", ucBssIdx); + kalMemZero(prParamGetWifiType->arWifiTypeName, + sizeof(prParamGetWifiType->arWifiTypeName)); + pNameBuf = &prParamGetWifiType->arWifiTypeName[0]; + ucMaxCopySize = sizeof(prParamGetWifiType->arWifiTypeName) - 1; + if (ucBssIdx > prAdapter->ucHwBssIdNum) { + DBGLOG(OID, ERROR, "invalid bss index: %u\n", ucBssIdx); + return WLAN_STATUS_INVALID_DATA; + } + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + if ((!prBssInfo) || (!IS_BSS_ACTIVE(prBssInfo))) { + DBGLOG(OID, ERROR, "invalid BssInfo: %p, %u\n", + prBssInfo, ucBssIdx); + return WLAN_STATUS_INVALID_DATA; + } + ucPhyType = prBssInfo->ucPhyTypeSet; + if (ucPhyType & PHY_TYPE_SET_802_11AC) + kalStrnCpy(pNameBuf, "11AC", ucMaxCopySize); + else if (ucPhyType & PHY_TYPE_SET_802_11N) + kalStrnCpy(pNameBuf, "11N", ucMaxCopySize); + else if (ucPhyType & PHY_TYPE_SET_802_11G) + kalStrnCpy(pNameBuf, "11G", ucMaxCopySize); + else if (ucPhyType & PHY_TYPE_SET_802_11A) + kalStrnCpy(pNameBuf, "11A", ucMaxCopySize); + else if (ucPhyType & PHY_TYPE_SET_802_11B) + kalStrnCpy(pNameBuf, "11B", ucMaxCopySize); + else + DBGLOG(OID, INFO, + "unknown wifi type, prBssInfo->ucPhyTypeSet: %u\n", + ucPhyType); + *pu4SetInfoLen = kalStrLen(pNameBuf); + DBGLOG(OID, INFO, "wifi type=[%s](%d), phyType=%u\n", + pNameBuf, *pu4SetInfoLen, ucPhyType); + return WLAN_STATUS_SUCCESS; +} + +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR +uint32_t wlanoidGetLinkQualityInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct PARAM_GET_LINK_QUALITY_INFO *prParam; + struct WIFI_LINK_QUALITY_INFO *prSrcLinkQualityInfo = NULL; + struct WIFI_LINK_QUALITY_INFO *prDstLinkQualityInfo = NULL; + + prParam = (struct PARAM_GET_LINK_QUALITY_INFO *)pvSetBuffer; + prSrcLinkQualityInfo = &(prAdapter->rLinkQualityInfo); + prDstLinkQualityInfo = prParam->prLinkQualityInfo; + kalMemCopy(prDstLinkQualityInfo, prSrcLinkQualityInfo, + sizeof(struct WIFI_LINK_QUALITY_INFO)); + + return WLAN_STATUS_SUCCESS; +} +#endif /* CFG_SUPPORT_LINK_QUALITY_MONITOR */ + +#if CFG_SUPPORT_ANT_SWAP +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to query antenna swap capablity + * + * \param[in] prAdapter A pointer to the Adapter structure. + * \param[in] pvSetBuffer A pointer to the buffer that holds the + * OID-specific data to be set. + * \param[in] u4SetBufferLen The number of bytes the set buffer. + * \param[out] pu4SetInfoLen Points to the number of bytes it read or is + * needed + * \retval WLAN_STATUS_SUCCESS + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanoidQueryAntennaSwap(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) + +{ + uint32_t *puSupportSwpAntenn = 0; + + if (!prAdapter) { + DBGLOG(REQ, ERROR, "prAdapter is NULL\n"); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + if (!pu4QueryInfoLen) { + DBGLOG(REQ, ERROR, "pu4QueryInfoLen is NULL\n"); + return WLAN_STATUS_INVALID_DATA; + } + + *pu4QueryInfoLen = sizeof(uint32_t); + + /* Check for query buffer length */ + if (u4QueryBufferLen != sizeof(uint32_t)) { + DBGLOG(REQ, WARN, "Invalid length %lu\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvQueryBuffer); + + puSupportSwpAntenn = (uint32_t *) pvQueryBuffer; + + *puSupportSwpAntenn = !!(prAdapter->fgIsSupportAntSwp); + DBGLOG(REQ, WARN, "*puSupportSwpAntenn : %lu\n", + *puSupportSwpAntenn); + return WLAN_STATUS_SUCCESS; +} +#endif /* CFG_SUPPORT_ANT_SWAP */ + +#if CFG_SUPPORT_DYNAMIC_PWR_LIMIT +/* dynamic tx power control oid function */ +uint32_t wlanoidTxPowerControl(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct PARAM_TX_PWR_CTRL_IOCTL *prPwrCtrlParam; + struct TX_PWR_CTRL_ELEMENT *oldElement; + u_int8_t fgApplied; + + if (!pvSetBuffer) + return WLAN_STATUS_INVALID_DATA; + + prPwrCtrlParam = (struct PARAM_TX_PWR_CTRL_IOCTL *)pvSetBuffer; + if ((prPwrCtrlParam == NULL) || (prPwrCtrlParam->name == NULL)) { + DBGLOG(OID, ERROR, "prPwrCtrlParam is NULL\n"); + return WLAN_STATUS_FAILURE; + } + + fgApplied = prPwrCtrlParam->fgApplied; + + oldElement = txPwrCtrlFindElement(prAdapter, + prPwrCtrlParam->name, 0, TRUE, + PWR_CTRL_TYPE_DYNAMIC_LIST); + if (oldElement != NULL) + oldElement->fgApplied = FALSE; + + if (fgApplied == TRUE) { + oldElement = txPwrCtrlFindElement(prAdapter, + prPwrCtrlParam->name, prPwrCtrlParam->index, + FALSE, PWR_CTRL_TYPE_DYNAMIC_LIST); + if (oldElement != NULL) { + if (prPwrCtrlParam->newSetting != NULL) { + struct TX_PWR_CTRL_ELEMENT *newElement; + + newElement = txPwrCtrlStringToStruct( + prPwrCtrlParam->newSetting, TRUE); + if (newElement == NULL) { + DBGLOG(OID, ERROR, + "parse new setting fail, <%s>\n", + prPwrCtrlParam->newSetting); + return WLAN_STATUS_FAILURE; + } + + kalMemCopy(newElement->name, oldElement->name, + MAX_TX_PWR_CTRL_ELEMENT_NAME_SIZE); + newElement->index = oldElement->index; + newElement->eCtrlType = oldElement->eCtrlType; + txPwrCtrlDeleteElement(prAdapter, + newElement->name, newElement->index, + PWR_CTRL_TYPE_DYNAMIC_LIST); + oldElement = newElement; + txPwrCtrlAddElement(prAdapter, oldElement); + } + oldElement->fgApplied = TRUE; + } + } + + if (oldElement != NULL) + rlmDomainSendPwrLimitCmd(prAdapter); + + return WLAN_STATUS_SUCCESS; +} +#endif + +uint32_t +wlanoidExternalAuthDone(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct STA_RECORD *prStaRec; + uint8_t ucBssIndex = 0; + struct PARAM_EXTERNAL_AUTH *params; + struct MSG_SAA_EXTERNAL_AUTH_DONE *prExternalAuthMsg = NULL; + + params = (struct PARAM_EXTERNAL_AUTH *) pvSetBuffer; + ucBssIndex = params->ucBssIdx; + if (!IS_BSS_INDEX_VALID(ucBssIndex)) { + DBGLOG(REQ, ERROR, + "SAE-confirm failed with invalid BssIdx in ndev\n"); + return WLAN_STATUS_INVALID_DATA; + } + + prExternalAuthMsg = (struct MSG_SAA_EXTERNAL_AUTH_DONE *)cnmMemAlloc( + prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_SAA_EXTERNAL_AUTH_DONE)); + if (!prExternalAuthMsg) { + DBGLOG(OID, WARN, + "SAE-confirm failed to allocate Msg\n"); + return WLAN_STATUS_RESOURCES; + } + + prStaRec = cnmGetStaRecByAddress(prAdapter, ucBssIndex, params->bssid); + if (!prStaRec) { + DBGLOG(REQ, WARN, "SAE-confirm failed with bssid:" MACSTR "\n", + MAC2STR(params->bssid)); + return WLAN_STATUS_INVALID_DATA; + } + + prExternalAuthMsg->rMsgHdr.eMsgId = MID_OID_SAA_FSM_EXTERNAL_AUTH; + prExternalAuthMsg->prStaRec = prStaRec; + prExternalAuthMsg->status = params->status; + + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *)prExternalAuthMsg, + MSG_SEND_METHOD_BUF); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidIndicateBssInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct GLUE_INFO *prGlueInfo; + struct BSS_DESC **pprBssDesc = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint8_t i = 0; + + DEBUGFUNC("wlanoidIndicateBssInfo"); + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + pprBssDesc = &prAdapter->rWifiVar.rScanInfo.rSchedScanParam. + aprPendingBssDescToInd[0]; + + for (; i < SCN_SSID_MATCH_MAX_NUM; i++) { + if (pprBssDesc[i] == NULL) + break; + if (pprBssDesc[i]->u2RawLength == 0) + continue; + kalIndicateBssInfo(prGlueInfo, + (uint8_t *) pprBssDesc[i]->aucRawBuf, + pprBssDesc[i]->u2RawLength, + pprBssDesc[i]->ucChannelNum, + RCPI_TO_dBm(pprBssDesc[i]->ucRCPI)); + } + DBGLOG(SCN, INFO, "pending %d sched scan results\n", i); + if (i > 0) + kalMemZero(&pprBssDesc[0], i * sizeof(struct BSS_DESC *)); + + return rStatus; +} /* wlanoidIndicateBssInfo */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/wlan_p2p.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/wlan_p2p.c new file mode 100644 index 0000000000000..29e5f4cc0b939 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/common/wlan_p2p.c @@ -0,0 +1,1739 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + + +/****************************************************************************** + * C O M P I L E 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 + */ +/*---------------------------------------------------------------------------*/ +uint32_t +wlanoidSendSetQueryP2PCmd(IN struct ADAPTER *prAdapter, + IN uint8_t ucCID, + IN uint8_t ucBssIdx, + IN u_int8_t fgSetQuery, + IN u_int8_t fgNeedResp, + IN u_int8_t fgIsOid, + IN PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + IN PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + IN uint32_t u4SetQueryInfoLen, + IN uint8_t *pucInfoBuffer, + OUT void *pvSetQueryBuffer, + IN uint32_t u4SetQueryBufferLen) +{ + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + uint8_t *pucCmdBuf; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + ASSERT(prGlueInfo); + prChipInfo = prAdapter->chip_info; + + DEBUGFUNC("wlanoidSendSetQueryP2PCmd"); + DBGLOG(REQ, TRACE, "Command ID = 0x%08X\n", ucCID); + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + (prChipInfo->u2CmdTxHdrSize + u4SetQueryInfoLen)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->u2InfoBufLen = + (uint16_t) (prChipInfo->u2CmdTxHdrSize + u4SetQueryInfoLen); + prCmdInfo->pfCmdDoneHandler = pfCmdDoneHandler; + prCmdInfo->pfCmdTimeoutHandler = pfCmdTimeoutHandler; + prCmdInfo->fgIsOid = fgIsOid; + prCmdInfo->ucCID = ucCID; + prCmdInfo->fgSetQuery = fgSetQuery; + prCmdInfo->fgNeedResp = fgNeedResp; + prCmdInfo->u4SetInfoLen = u4SetQueryInfoLen; + prCmdInfo->pvInformationBuffer = pvSetQueryBuffer; + prCmdInfo->u4InformationBufferLength = u4SetQueryBufferLen; + + /* Setup WIFI_CMD_T (no payload) */ + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + prCmdInfo->ucCID, + CMD_PACKET_TYPE_ID, + &prCmdInfo->ucCmdSeqNum, + prCmdInfo->fgSetQuery, &pucCmdBuf, FALSE, 0, S2D_INDEX_CMD_H2N); + + if (u4SetQueryInfoLen > 0 && pucInfoBuffer != NULL) + kalMemCopy(pucCmdBuf, + pucInfoBuffer, u4SetQueryInfoLen); + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (struct QUE_ENTRY *) 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 + */ +/*---------------------------------------------------------------------------*/ +#if 0 +uint32_t +wlanoidSetAddP2PKey(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct CMD_802_11_KEY rCmdKey; + struct PARAM_KEY *prNewKey; + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + + DEBUGFUNC("wlanoidSetAddP2PKey"); + DBGLOG(REQ, INFO, "\n"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prNewKey = (struct PARAM_KEY *) pvSetBuffer; + + /* Verify the key structure length. */ + if (prNewKey->u4Length > u4SetBufferLen) { + log_dbg(REQ, WARN, + "Invalid key structure length (%d) greater than total buffer length (%d)\n", + (uint8_t) prNewKey->u4Length, (uint8_t) 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(struct PARAM_KEY, aucKeyMaterial)) { + log_dbg(REQ, WARN, + "Invalid key material length (%d)\n", + (uint8_t) 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; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prNewKey->ucBssIdx); + ASSERT(prBssInfo); +#if 0 + if (prBssInfo->ucBMCWlanIndex >= WTBL_SIZE) { + prBssInfo->ucBMCWlanIndex = + secPrivacySeekForBcEntry(prAdapter, + prBssInfo->ucBssIndex, prBssInfo->aucBSSID, + 0xff, CIPHER_SUITE_NONE, 0xff); + } +#endif + /* fill CMD_802_11_KEY */ + kalMemZero(&rCmdKey, sizeof(struct 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 0 + /* group client */ + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { +#else + /* group client */ + if (kalP2PGetRole(prAdapter->prGlueInfo) == 1) { +#endif + + rCmdKey.ucIsAuthenticator = 0; + } else { /* group owner */ + rCmdKey.ucIsAuthenticator = 1; + /* Force to set GO/AP Tx */ + rCmdKey.ucTxKey = 1; + } + + COPY_MAC_ADDR(rCmdKey.aucPeerAddr, prNewKey->arBSSID); + rCmdKey.ucBssIdx = prNewKey->ucBssIdx; + 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 */ + else if (prNewKey->u4KeyLength == WEP_40_LEN) + rCmdKey.ucAlgorithmId = CIPHER_SUITE_WEP40; /* WEP 40 */ + else if (prNewKey->u4KeyLength == WEP_104_LEN) + rCmdKey.ucAlgorithmId = CIPHER_SUITE_WEP104; /* WEP 104 */ + else + ASSERT(FALSE); + rCmdKey.ucKeyId = (uint8_t) (prNewKey->u4KeyIndex & 0xff); + rCmdKey.ucKeyLen = (uint8_t) prNewKey->u4KeyLength; + kalMemCopy(rCmdKey.aucKeyMaterial, + (uint8_t *) prNewKey->aucKeyMaterial, rCmdKey.ucKeyLen); + + if ((rCmdKey.aucPeerAddr[0] & + rCmdKey.aucPeerAddr[1] & rCmdKey.aucPeerAddr[2] & + rCmdKey.aucPeerAddr[3] & rCmdKey.aucPeerAddr[4] & + rCmdKey.aucPeerAddr[5]) == 0xFF) { + kalMemCopy(rCmdKey.aucPeerAddr, + prBssInfo->aucBSSID, MAC_ADDR_LEN); + if (!rCmdKey.ucIsAuthenticator) { + prStaRec = cnmGetStaRecByAddress(prAdapter, + rCmdKey.ucBssIdx, rCmdKey.aucPeerAddr); + if (!prStaRec) + ASSERT(FALSE); + } + } else { + prStaRec = cnmGetStaRecByAddress(prAdapter, + rCmdKey.ucBssIdx, rCmdKey.aucPeerAddr); + } + + if (rCmdKey.ucTxKey) { + if (prStaRec) { + if (rCmdKey.ucKeyType) { /* RSN STA */ + ASSERT(prStaRec->ucWlanIndex < WTBL_SIZE); + rCmdKey.ucWlanIndex = prStaRec->ucWlanIndex; + /* wait for CMD Done ? */ + prStaRec->fgTransmitKeyExist = TRUE; + } else { + ASSERT(FALSE); + } + } else { + if (prBssInfo) { /* GO/AP Tx BC */ + ASSERT(prBssInfo->ucBMCWlanIndex < WTBL_SIZE); + rCmdKey.ucWlanIndex = prBssInfo->ucBMCWlanIndex; + prBssInfo->fgBcDefaultKeyExist = TRUE; + prBssInfo->ucTxDefaultKeyID = rCmdKey.ucKeyId; + } else { + /* GC WEP Tx key ? */ + rCmdKey.ucWlanIndex = 255; + ASSERT(FALSE); + } + } + } else { + if (((rCmdKey.aucPeerAddr[0] & rCmdKey.aucPeerAddr[1] & + rCmdKey.aucPeerAddr[2] & rCmdKey.aucPeerAddr[3] & + rCmdKey.aucPeerAddr[4] & + rCmdKey.aucPeerAddr[5]) == 0xFF) || + ((rCmdKey.aucPeerAddr[0] | rCmdKey.aucPeerAddr[1] | + rCmdKey.aucPeerAddr[2] | rCmdKey.aucPeerAddr[3] | + rCmdKey.aucPeerAddr[4] | rCmdKey.aucPeerAddr[5]) == 0x00)) { + rCmdKey.ucWlanIndex = 255; /* GC WEP ? */ + ASSERT(FALSE); + } else { + if (prStaRec) { /* GC Rx RSN Group key */ + rCmdKey.ucWlanIndex = + secPrivacySeekForBcEntry(prAdapter, + prStaRec->ucBssIndex, + prStaRec->aucMacAddr, + prStaRec->ucIndex, + rCmdKey.ucAlgorithmId, + rCmdKey.ucKeyId); + prStaRec->ucBMCWlanIndex = rCmdKey.ucWlanIndex; + ASSERT(prStaRec->ucBMCWlanIndex < WTBL_SIZE); + } else { /* Exist this case ? */ + ASSERT(FALSE); + } + } + } + + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_ADD_REMOVE_KEY, + prNewKey->ucBssIdx, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + NULL, + sizeof(struct CMD_802_11_KEY), + (uint8_t *)&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 + */ +/*---------------------------------------------------------------------------*/ +uint32_t +wlanoidSetRemoveP2PKey(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct CMD_802_11_KEY rCmdKey; + struct PARAM_REMOVE_KEY *prRemovedKey; + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + + DEBUGFUNC("wlanoidSetRemoveP2PKey"); + ASSERT(prAdapter); + + if (u4SetBufferLen < sizeof(struct PARAM_REMOVE_KEY)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + prRemovedKey = (struct PARAM_REMOVE_KEY *) 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; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prRemovedKey->ucBssIdx); + + kalMemZero((uint8_t *)&rCmdKey, sizeof(struct CMD_802_11_KEY)); + + rCmdKey.ucAddRemove = 0; /* remove */ + /* group client */ + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + rCmdKey.ucIsAuthenticator = 0; + } else { /* group owner */ + rCmdKey.ucIsAuthenticator = 1; + } + kalMemCopy(rCmdKey.aucPeerAddr, + (uint8_t *) prRemovedKey->arBSSID, MAC_ADDR_LEN); + rCmdKey.ucBssIdx = prRemovedKey->ucBssIdx; + rCmdKey.ucKeyId = (uint8_t) (prRemovedKey->u4KeyIndex & 0x000000ff); + + /* Clean up the Tx key flag */ + prStaRec = cnmGetStaRecByAddress(prAdapter, + prRemovedKey->ucBssIdx, prRemovedKey->arBSSID); + + /* mark for MR1 to avoid remove-key, + * but remove the wlan_tbl0 at the same time + */ + if (1 /*prRemovedKey->u4KeyIndex & IS_UNICAST_KEY */) { + if (prStaRec) { + rCmdKey.ucKeyType = 1; + rCmdKey.ucWlanIndex = prStaRec->ucWlanIndex; + prStaRec->fgTransmitKeyExist = FALSE; + } else if (rCmdKey.ucIsAuthenticator) + prBssInfo->fgBcDefaultKeyExist = FALSE; + } else { + if (rCmdKey.ucIsAuthenticator) + prBssInfo->fgBcDefaultKeyExist = FALSE; + } + + if (!prStaRec) { + if (prAdapter->rWifiVar.rConnSettings.eAuthMode < AUTH_MODE_WPA + && prAdapter->rWifiVar.rConnSettings.eEncStatus + != ENUM_ENCRYPTION_DISABLED) { + rCmdKey.ucWlanIndex = prBssInfo->ucBMCWlanIndex; + } else { + rCmdKey.ucWlanIndex = WTBL_RESERVED_ENTRY; + return WLAN_STATUS_SUCCESS; + } + } + + /* mark for MR1 to avoid remove-key, + * but remove the wlan_tbl0 at the same time + */ + /* secPrivacyFreeForEntry(prAdapter, rCmdKey.ucWlanIndex); */ + + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_ADD_REMOVE_KEY, + prRemovedKey->ucBssIdx, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + NULL, + sizeof(struct CMD_802_11_KEY), + (uint8_t *)&rCmdKey, + pvSetBuffer, + u4SetBufferLen); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetP2pNetworkAddress(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t i, j; + struct CMD_SET_NETWORK_ADDRESS_LIST *prCmdNWAddrList; + struct PARAM_NETWORK_ADDRESS_LIST *prNWAddrList = + (struct PARAM_NETWORK_ADDRESS_LIST *) pvSetBuffer; + struct PARAM_NETWORK_ADDRESS *prNWAddress; + struct PARAM_NETWORK_ADDRESS_IP *prNetAddrIp; + uint32_t u4IpAddressCount, u4CmdSize; + + DEBUGFUNC("wlanoidSetP2pNetworkAddress"); + DBGLOG(INIT, TRACE, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 4; + + if (u4SetBufferLen < sizeof(struct PARAM_NETWORK_ADDRESS_LIST)) + return WLAN_STATUS_INVALID_DATA; + + *pu4SetInfoLen = 0; + u4IpAddressCount = 0; + + prNWAddress = prNWAddrList->arAddress; + for (i = 0; i < prNWAddrList->u4AddressCount; i++) { + if (prNWAddress->u2AddressType + == PARAM_PROTOCOL_ID_TCP_IP && + prNWAddress->u2AddressLength + == sizeof(struct PARAM_NETWORK_ADDRESS_IP)) { + u4IpAddressCount++; + } + + prNWAddress = (struct PARAM_NETWORK_ADDRESS *) + ((unsigned long) prNWAddress + + (unsigned long) (prNWAddress->u2AddressLength + + OFFSET_OF(struct PARAM_NETWORK_ADDRESS, aucAddress))); + } + + /* construct payload of command packet */ + u4CmdSize = + OFFSET_OF(struct CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress) + + sizeof(struct CMD_IPV4_NETWORK_ADDRESS) * u4IpAddressCount; + + prCmdNWAddrList = (struct CMD_SET_NETWORK_ADDRESS_LIST *) + kalMemAlloc(u4CmdSize, VIR_MEM_TYPE); + + if (prCmdNWAddrList == NULL) + return WLAN_STATUS_FAILURE; + + /* fill P_CMD_SET_NETWORK_ADDRESS_LIST */ + prCmdNWAddrList->ucBssIndex = prNWAddrList->ucBssIdx; + prCmdNWAddrList->ucAddressCount = (uint8_t) u4IpAddressCount; + prNWAddress = prNWAddrList->arAddress; + for (i = 0, j = 0; i < prNWAddrList->u4AddressCount; i++) { + if (prNWAddress->u2AddressType + == PARAM_PROTOCOL_ID_TCP_IP && + prNWAddress->u2AddressLength + == sizeof(struct PARAM_NETWORK_ADDRESS_IP)) { + prNetAddrIp = (struct PARAM_NETWORK_ADDRESS_IP *) + prNWAddress->aucAddress; + + kalMemCopy( + prCmdNWAddrList->arNetAddress[j].aucIpAddr, + &(prNetAddrIp->in_addr), sizeof(uint32_t)); + + j++; + } + + prNWAddress = (struct PARAM_NETWORK_ADDRESS *) + ((unsigned long) prNWAddress + + (unsigned long) (prNWAddress->u2AddressLength + + OFFSET_OF(struct PARAM_NETWORK_ADDRESS, aucAddress))); + } + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_IP_ADDRESS, + TRUE, + FALSE, + TRUE, + nicCmdEventSetIpAddress, + nicOidCmdTimeoutCommon, + u4CmdSize, + (uint8_t *) prCmdNWAddrList, + pvSetBuffer, + u4SetBufferLen); + + kalMemFree(prCmdNWAddrList, 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryP2pPowerSaveProfile(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryP2pPowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen != 0) { + ASSERT(pvQueryBuffer); + /* TODO: FIXME */ + /* *(enum PARAM_POWER_MODE *) pvQueryBuffer = + * (enum PARAM_POWER_MODE) + *(prAdapter->rWlanInfo. + * arPowerSaveMode[prAdapter->ucP2PDevBssIdx].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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetP2pPowerSaveProfile(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t status; + enum PARAM_POWER_MODE ePowerMode; + + DEBUGFUNC("wlanoidSetP2pPowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(enum PARAM_POWER_MODE); + if (u4SetBufferLen < sizeof(enum PARAM_POWER_MODE)) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } else if (*(enum PARAM_POWER_MODE *) + pvSetBuffer >= Param_PowerModeMax) { + DBGLOG(REQ, WARN, "Invalid power mode %d\n", + *(enum PARAM_POWER_MODE *) pvSetBuffer); + return WLAN_STATUS_INVALID_DATA; + } + + ePowerMode = *(enum PARAM_POWER_MODE *) pvSetBuffer; + + if (prAdapter->fgEnCtiaPowerMode) { + if (ePowerMode == Param_PowerModeCAM) { + /*Todo:: Nothing */ + /*Todo:: Nothing */ + } else { + /* User setting to PS mode + *(Param_PowerModeMAX_PSP or Param_PowerModeFast_PSP) + */ + + if (prAdapter->u4CtiaPowerMode == 0) { + /* force to keep in CAM mode */ + ePowerMode = Param_PowerModeCAM; + } else if (prAdapter->u4CtiaPowerMode == 1) { + ePowerMode = Param_PowerModeMAX_PSP; + } else if (prAdapter->u4CtiaPowerMode == 2) { + ePowerMode = Param_PowerModeFast_PSP; + } + } + } + + /* TODO: FIXME */ + status = nicConfigPowerSaveProfile(prAdapter, prAdapter->ucP2PDevBssIdx, + ePowerMode, TRUE, PS_CALLER_P2P); + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetP2pSetNetworkAddress(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t i, j; + struct CMD_SET_NETWORK_ADDRESS_LIST *prCmdNWAddrList; + struct PARAM_NETWORK_ADDRESS_LIST *prNWAddrList = + (struct PARAM_NETWORK_ADDRESS_LIST *) pvSetBuffer; + struct PARAM_NETWORK_ADDRESS *prNWAddress; + struct PARAM_NETWORK_ADDRESS_IP *prNetAddrIp; + uint32_t u4IpAddressCount, u4CmdSize; + uint8_t *pucBuf = (uint8_t *) pvSetBuffer; + + DEBUGFUNC("wlanoidSetP2pSetNetworkAddress"); + DBGLOG(INIT, TRACE, "\n"); + DBGLOG(INIT, INFO, "wlanoidSetP2pSetNetworkAddress (%d)\n", + (int16_t) u4SetBufferLen); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 4; + + if (u4SetBufferLen < sizeof(struct PARAM_NETWORK_ADDRESS_LIST)) + return WLAN_STATUS_INVALID_DATA; + + *pu4SetInfoLen = 0; + u4IpAddressCount = 0; + + prNWAddress = prNWAddrList->arAddress; + for (i = 0; i < prNWAddrList->u4AddressCount; i++) { + if (prNWAddress->u2AddressType + == PARAM_PROTOCOL_ID_TCP_IP && + prNWAddress->u2AddressLength + == sizeof(struct PARAM_NETWORK_ADDRESS_IP)) { + u4IpAddressCount++; + } + + prNWAddress = (struct PARAM_NETWORK_ADDRESS *) + ((unsigned long) prNWAddress + + (unsigned long) (prNWAddress->u2AddressLength + + OFFSET_OF(struct PARAM_NETWORK_ADDRESS, aucAddress))); + } + + /* construct payload of command packet */ + u4CmdSize = + OFFSET_OF(struct CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress) + + sizeof(struct CMD_IPV4_NETWORK_ADDRESS) * u4IpAddressCount; + + if (u4IpAddressCount == 0) + u4CmdSize = sizeof(struct CMD_SET_NETWORK_ADDRESS_LIST); + + prCmdNWAddrList = (struct CMD_SET_NETWORK_ADDRESS_LIST *) + kalMemAlloc(u4CmdSize, VIR_MEM_TYPE); + + if (prCmdNWAddrList == NULL) + return WLAN_STATUS_FAILURE; + + /* fill P_CMD_SET_NETWORK_ADDRESS_LIST */ + prCmdNWAddrList->ucBssIndex = prNWAddrList->ucBssIdx; + + /* only to set IP address to FW once ARP filter is enabled */ + if (prAdapter->fgEnArpFilter) { + prCmdNWAddrList->ucAddressCount = + (uint8_t) u4IpAddressCount; + prNWAddress = prNWAddrList->arAddress; + + DBGLOG(INIT, INFO, "u4IpAddressCount (%u)\n", + (int32_t) u4IpAddressCount); + + for (i = 0, j = 0; i < prNWAddrList->u4AddressCount; i++) { + if (prNWAddress->u2AddressType + == PARAM_PROTOCOL_ID_TCP_IP && + prNWAddress->u2AddressLength + == sizeof(struct PARAM_NETWORK_ADDRESS_IP)) { + + prNetAddrIp = + (struct PARAM_NETWORK_ADDRESS_IP *) + prNWAddress->aucAddress; + + kalMemCopy( + prCmdNWAddrList->arNetAddress[j] + .aucIpAddr, + &(prNetAddrIp->in_addr), + sizeof(uint32_t)); + + j++; + + pucBuf = (uint8_t *) &prNetAddrIp->in_addr; + DBGLOG(INIT, INFO, + "prNetAddrIp->in_addr:%d:%d:%d:%d\n", + (uint8_t) pucBuf[0], + (uint8_t) pucBuf[1], + (uint8_t) pucBuf[2], + (uint8_t) pucBuf[3]); + } + + prNWAddress = (struct PARAM_NETWORK_ADDRESS *) + ((unsigned long) prNWAddress + + (unsigned long) (prNWAddress->u2AddressLength + + OFFSET_OF(struct PARAM_NETWORK_ADDRESS, + aucAddress))); + } + + } else { + prCmdNWAddrList->ucAddressCount = 0; + } + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_IP_ADDRESS, + TRUE, + FALSE, + TRUE, + nicCmdEventSetIpAddress, + nicOidCmdTimeoutCommon, + u4CmdSize, + (uint8_t *) prCmdNWAddrList, + pvSetBuffer, + u4SetBufferLen); + + kalMemFree(prCmdNWAddrList, 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetP2PMulticastList(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct CMD_MAC_MCAST_ADDR rCmdMacMcastAddr; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* The data must be a multiple of the Ethernet address size. */ + if ((u4SetBufferLen % MAC_ADDR_LEN)) { + DBGLOG(REQ, WARN, "Invalid MC list length %u\n", + u4SetBufferLen); + + *pu4SetInfoLen = + (((u4SetBufferLen + MAC_ADDR_LEN) - 1) + / MAC_ADDR_LEN) * MAC_ADDR_LEN; + + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = u4SetBufferLen; + + /* Verify if we can support so many multicast addresses. */ + if (u4SetBufferLen > MAX_NUM_GROUP_ADDR * MAC_ADDR_LEN) { + 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; + /* TODO: */ + rCmdMacMcastAddr.ucBssIndex = prAdapter->ucP2PDevBssIdx; + kalMemCopy(rCmdMacMcastAddr.arAddress, pvSetBuffer, u4SetBufferLen); + + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_MAC_MCAST_ADDR, + prAdapter->ucP2PDevBssIdx, + /* TODO: */ + /* This CMD response is no need + * to complete the OID. + * Or the event would unsync. + */ + TRUE, FALSE, FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_MAC_MCAST_ADDR), + (uint8_t *) &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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSendP2PSDRequest(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (u4SetBufferLen < sizeof(struct PARAM_P2P_SEND_SD_REQUEST)) { + *pu4SetInfoLen = sizeof(struct 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSendP2PSDResponse(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (u4SetBufferLen < sizeof(struct PARAM_P2P_SEND_SD_RESPONSE)) { + *pu4SetInfoLen = sizeof(struct 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidGetP2PSDRequest(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; +/* PUINT_8 pucChannelNum = NULL; */ +/* UINT_8 ucChannelNum = 0, ucSeqNum = 0; */ + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(struct PARAM_P2P_GET_SD_REQUEST)) { + *pu4QueryInfoLen = sizeof(struct PARAM_P2P_GET_SD_REQUEST); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + DBGLOG(P2P, TRACE, "Get Service Discovery Request\n"); + + *pu4QueryInfoLen = 0; + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidGetP2PSDResponse(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + /* UINT_8 ucSeqNum = 0, */ + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(struct PARAM_P2P_GET_SD_RESPONSE)) { + *pu4QueryInfoLen = sizeof(struct PARAM_P2P_GET_SD_RESPONSE); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + DBGLOG(P2P, TRACE, "Get Service Discovery Response\n"); + + *pu4QueryInfoLen = 0; + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetP2PTerminateSDPhase(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct PARAM_P2P_TERMINATE_SD_PHASE *prP2pTerminateSD = + (struct PARAM_P2P_TERMINATE_SD_PHASE *) NULL; + uint8_t aucNullAddr[] = NULL_MAC_ADDR; + + do { + if ((prAdapter == NULL) || (pu4SetInfoLen == NULL)) + break; + + if ((u4SetBufferLen) && (pvSetBuffer == NULL)) + break; + + if (u4SetBufferLen + < sizeof(struct PARAM_P2P_TERMINATE_SD_PHASE)) { + + *pu4SetInfoLen = + sizeof(struct PARAM_P2P_TERMINATE_SD_PHASE); + rWlanStatus = WLAN_STATUS_BUFFER_TOO_SHORT; + break; + } + + prP2pTerminateSD = + (struct 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetSecCheckRequest(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + +#if 0 /* Comment it because CMD_ID_SEC_CHECK is not defined */ + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SEC_CHECK, + prAdapter->ucP2PDevBssIdx, + FALSE, + TRUE, + TRUE, + NULL, + nicOidCmdTimeoutCommon, + u4SetBufferLen, + (uint8_t *) pvSetBuffer, + pvSetBuffer, + u4SetBufferLen); +#else + return WLAN_STATUS_NOT_SUPPORTED; +#endif +} /* end of wlanoidSetSecCheckRequest() */ + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidGetSecCheckResponse(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + /* P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T)NULL; */ + struct GLUE_INFO *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[0]->aucSecCheckRsp, + u4QueryBufferLen); +#endif + kalMemCopy((uint8_t *) + (pvQueryBuffer + + OFFSET_OF(struct iw_p2p_transport_struct, aucBuffer)), + prGlueInfo->prP2PInfo[0]->aucSecCheckRsp, + u4QueryBufferLen); + + return rWlanStatus; +} /* end of wlanoidGetSecCheckResponse() */ +#endif +#endif + +uint32_t +wlanoidSetNoaParam(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct PARAM_CUSTOM_NOA_PARAM_STRUCT *prNoaParam; + struct CMD_CUSTOM_NOA_PARAM_STRUCT rCmdNoaParam; + + DEBUGFUNC("wlanoidSetNoaParam"); + DBGLOG(INIT, TRACE, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CUSTOM_NOA_PARAM_STRUCT); + + if (u4SetBufferLen < sizeof(struct PARAM_CUSTOM_NOA_PARAM_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prNoaParam = (struct PARAM_CUSTOM_NOA_PARAM_STRUCT *) pvSetBuffer; + + kalMemZero(&rCmdNoaParam, sizeof(struct CMD_CUSTOM_NOA_PARAM_STRUCT)); + rCmdNoaParam.u4NoaDurationMs = prNoaParam->u4NoaDurationMs; + rCmdNoaParam.u4NoaIntervalMs = prNoaParam->u4NoaIntervalMs; + rCmdNoaParam.u4NoaCount = prNoaParam->u4NoaCount; + rCmdNoaParam.ucBssIdx = prNoaParam->ucBssIdx; + +#if 0 + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_NOA_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_CUSTOM_NOA_PARAM_STRUCT), + (uint8_t *) &rCmdNoaParam, + pvSetBuffer, + u4SetBufferLen); +#else + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_NOA_PARAM, + prNoaParam->ucBssIdx, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_CUSTOM_NOA_PARAM_STRUCT), + (uint8_t *) &rCmdNoaParam, + pvSetBuffer, + u4SetBufferLen); + +#endif + +} + +uint32_t +wlanoidSetOppPsParam(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct PARAM_CUSTOM_OPPPS_PARAM_STRUCT *prOppPsParam; + struct CMD_CUSTOM_OPPPS_PARAM_STRUCT rCmdOppPsParam; + + DEBUGFUNC("wlanoidSetOppPsParam"); + DBGLOG(INIT, TRACE, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CUSTOM_OPPPS_PARAM_STRUCT); + + if (u4SetBufferLen < sizeof(struct PARAM_CUSTOM_OPPPS_PARAM_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prOppPsParam = (struct PARAM_CUSTOM_OPPPS_PARAM_STRUCT *) pvSetBuffer; + + kalMemZero(&rCmdOppPsParam, + sizeof(struct CMD_CUSTOM_OPPPS_PARAM_STRUCT)); + rCmdOppPsParam.u4CTwindowMs = prOppPsParam->u4CTwindowMs; + rCmdOppPsParam.ucBssIdx = prOppPsParam->ucBssIdx; + +#if 0 + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_OPPPS_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_CUSTOM_OPPPS_PARAM_STRUCT), + (uint8_t *) &rCmdOppPsParam, + pvSetBuffer, + u4SetBufferLen); +#else + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_OPPPS_PARAM, + prOppPsParam->ucBssIdx, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_CUSTOM_OPPPS_PARAM_STRUCT), + (uint8_t *) &rCmdOppPsParam, + pvSetBuffer, + u4SetBufferLen); + +#endif + +} + +uint32_t +wlanoidSetUApsdParam(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct PARAM_CUSTOM_UAPSD_PARAM_STRUCT *prUapsdParam; + struct CMD_CUSTOM_UAPSD_PARAM_STRUCT rCmdUapsdParam; + struct PM_PROFILE_SETUP_INFO *prPmProfSetupInfo; + struct BSS_INFO *prBssInfo; + u_int8_t fgIsOid = TRUE; + + DEBUGFUNC("wlanoidSetUApsdParam"); + DBGLOG(INIT, TRACE, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CUSTOM_UAPSD_PARAM_STRUCT); + + if (u4SetBufferLen < sizeof(struct PARAM_CUSTOM_UAPSD_PARAM_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prUapsdParam = (struct PARAM_CUSTOM_UAPSD_PARAM_STRUCT *) pvSetBuffer; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prUapsdParam->ucBssIdx); + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + + kalMemZero(&rCmdUapsdParam, + sizeof(struct CMD_CUSTOM_UAPSD_PARAM_STRUCT)); + + rCmdUapsdParam.fgEnAPSD = 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 (prAdapter->prGlueInfo) + fgIsOid = (prAdapter->prGlueInfo->u4TxThreadPid + != KAL_GET_CURRENT_THREAD_ID()); + +#if 0 + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_UAPSD_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_CUSTOM_UAPSD_PARAM_STRUCT), + (uint8_t *) &rCmdUapsdParam, + pvSetBuffer, + u4SetBufferLen); +#else + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_UAPSD_PARAM, + prBssInfo->ucBssIndex, + TRUE, + FALSE, + fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_CUSTOM_UAPSD_PARAM_STRUCT), + (uint8_t *) &rCmdUapsdParam, + pvSetBuffer, + u4SetBufferLen); + +#endif +} + +uint32_t +wlanoidQueryP2pVersion(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + uint32_t 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(uint8_t)) { + *pu4QueryInfoLen = sizeof(uint8_t); + rResult = WLAN_STATUS_BUFFER_TOO_SHORT; + break; + } + + } while (FALSE); + + return rResult; +} /* wlanoidQueryP2pVersion */ + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to set the WPS mode. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. + * \param[in] u4SetBufferLen The length of the set buffer. + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed + * due to invalid length of the set buffer, returns + * the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetP2pWPSmode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t status; + uint32_t u4IsWPSmode = 0; + int i = 0; + + DEBUGFUNC("wlanoidSetP2pWPSmode"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (pvSetBuffer) + u4IsWPSmode = *(uint32_t *) pvSetBuffer; + else + u4IsWPSmode = 0; + + /* set all Role to the same value */ + for (i = 0; i < KAL_P2P_NUM; i++) + if (u4IsWPSmode) + prAdapter->rWifiVar.prP2PConnSettings[i]->fgIsWPSMode + = 1; + else + prAdapter->rWifiVar.prP2PConnSettings[i]->fgIsWPSMode + = 0; + + status = nicUpdateBss(prAdapter, prAdapter->ucP2PDevBssIdx); + + return status; +} /* end of wlanoidSetP2pWPSmode() */ + +#endif + +uint32_t +wlanoidSetP2pSupplicantVersion(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t rResult = WLAN_STATUS_FAILURE; + uint8_t 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(uint8_t); + + if (u4SetBufferLen < sizeof(uint8_t)) { + rResult = WLAN_STATUS_INVALID_LENGTH; + break; + } + + ucVersionNum = *((uint8_t *) pvSetBuffer); + + rResult = WLAN_STATUS_SUCCESS; + } while (FALSE); + + return rResult; +} /* wlanoidSetP2pSupplicantVersion */ + +#if CFG_SUPPORT_P2P_RSSI_QUERY +uint32_t +wlanoidQueryP2pRssi(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryP2pRssi"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (prAdapter->fgIsEnableLpdvt) + return WLAN_STATUS_NOT_SUPPORTED; + + *pu4QueryInfoLen = sizeof(int32_t); + + /* 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) { + + int32_t rRssi; + + /* ranged from (-128 ~ 30) in unit of dBm */ + rRssi = (int32_t) prAdapter->rP2pLinkQuality.cRssi; + + 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(int32_t)); + 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 + +uint32_t +wlanoidAbortP2pScan(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + + DBGLOG(P2P, INFO, "wlanoidAbortP2pScan\n"); + + ASSERT(prAdapter); + + p2pDevFsmRunEventScanAbort(prAdapter, NULL); + + return WLAN_STATUS_SUCCESS; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/dvt/dvt_common.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/dvt/dvt_common.c new file mode 100644 index 0000000000000..c1e73809f3a73 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/dvt/dvt_common.c @@ -0,0 +1,1196 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +/* + ** Id: include/dvt_common.c + */ + +/*! \file dvt_common.c + * \brief This file contains the declairations of sys dvt command + */ + +/******************************************************************************* + * C O M P I L E 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" + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +struct AUTOMATION_DVT automation_dvt; +struct TXS_FREE_LIST_POOL TxsFreeEntrylist; + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#if CFG_SUPPORT_WIFI_SYSDVT +/* +* This routine is used to init TXS pool for DVT +*/ +void TxsPoolInit(void) +{ + if (TxsFreeEntrylist.txs_list_cnt == 0) { + spin_lock_init(&TxsFreeEntrylist.Lock); + INIT_LIST_HEAD(&TxsFreeEntrylist.pool_head.List); + INIT_LIST_HEAD(&TxsFreeEntrylist.head.mList); + } + + TxsFreeEntrylist.txs_list_cnt++; +} + +/* +* This routine is used to uninit TXS pool for DVT +*/ +void TxsPoolUnInit(void) +{ + struct list_head *prCur, *prNext; + + TxsFreeEntrylist.txs_list_cnt--; + + if (TxsFreeEntrylist.txs_list_cnt == 0) { + struct TXS_LIST_POOL *pEntry = NULL; + + list_for_each_safe(prCur, prNext, + &TxsFreeEntrylist.pool_head.List) { + pEntry = + list_entry(prCur, struct TXS_LIST_POOL, List); + list_del_init(&pEntry->List); + list_del(prCur); + if (pEntry == NULL) + DBGLOG(REQ, LOUD, "pEntry null\n"); + kfree(pEntry); + } + } +} + +/* +* This routine is used to test TXS function. +* init TXS DVT structure and start to test +*/ +bool TxsInit(void) +{ + uint32_t i; + struct TXS_LIST *list = &automation_dvt.txs.txs_list; + + if (automation_dvt.txs.isinit) + return TRUE; + + automation_dvt.txs.isinit = FALSE; + automation_dvt.txs.total_req = 0; + automation_dvt.txs.total_rsp = 0; + automation_dvt.txs.stop_send_test = TRUE; + automation_dvt.txs.test_type = 0; + automation_dvt.txs.pid = 1; + + spin_lock_init(&list->lock); + + for (i = 0; i < PID_SIZE; i++) { + INIT_LIST_HEAD(&list->pHead[i].mList); + automation_dvt.txs.check_item[i].time_stamp = 0; + } + + list->Num = 0; + TxsPoolInit(); + + if (list_empty(&TxsFreeEntrylist.pool_head.List)) { + struct TXS_LIST_POOL *Pool = NULL; + struct TXS_LIST_POOL *pFreepool = NULL; + struct TXS_LIST_ENTRY *pEntry = NULL; + struct TXS_LIST_ENTRY *newEntry = NULL; + + Pool = kmalloc(sizeof(struct TXS_LIST_POOL), GFP_ATOMIC); + pFreepool = &TxsFreeEntrylist.pool_head; + list_add(&Pool->List, &pFreepool->List); + pEntry = &TxsFreeEntrylist.head; + + for (i = 0; i < TXS_LIST_ELEM_NUM; i++) { + newEntry = &Pool->Entry[i]; + list_add(&newEntry->mList, &pEntry->mList); + } + } + + list->pFreeEntrylist = &TxsFreeEntrylist; + automation_dvt.txs.isinit = TRUE; + return TRUE; +} + +/* +* This routine is used to test TXS function. +* destroy TXS DVT structure +*/ +bool TxsExit(void) +{ + uint32_t i = 0; + unsigned long IrqFlags = 0; + uint16_t wait_cnt = 0; + struct TXS_LIST *list = &automation_dvt.txs.txs_list; + + automation_dvt.txs.isinit = FALSE; + automation_dvt.txs.total_req = 0; + automation_dvt.txs.total_rsp = 0; + automation_dvt.txs.stop_send_test = TRUE; + automation_dvt.txs.test_type = 0; + automation_dvt.txs.pid = 1; + + while (automation_dvt.txs.txs_list.Num > 0) { + DBGLOG(REQ, LOUD, "wait entry to be deleted\n"); + kalMsleep(100);/* OS_WAIT(10); */ + wait_cnt++; + + if (wait_cnt > 100) + break; + } + + spin_lock_irqsave(&list->lock, IrqFlags); + + for (i = 0; i < PID_SIZE; i++) { + INIT_LIST_HEAD(&list->pHead[i].mList); + automation_dvt.txs.check_item[i].time_stamp = 0; + } + + spin_unlock_irqrestore(&list->lock, IrqFlags); + list->Num = 0; + TxsPoolUnInit(); + DBGLOG(REQ, LOUD, "TxsPoolUnInit done\n"); + + return TRUE; +} + +/* +* This routine is used to initial DVT of automation. +*/ +bool AutomationInit(struct ADAPTER *pAd, int32_t auto_type) +{ + bool ret; + + ret = TRUE; + if (!pAd) + return FALSE; + + DBGLOG(REQ, LOUD, "In AutomationInit\n"); + + if (pAd->auto_dvt == NULL) { + kalMemZero(&automation_dvt, sizeof(struct AUTOMATION_DVT)); + pAd->auto_dvt = &automation_dvt; + DBGLOG(REQ, LOUD, "AutomationInit\n"); + } + + switch (auto_type) { + case TXS: + ret = TxsInit(); + break; + case RXV: + break; +#if (CFG_SUPPORT_DMASHDL_SYSDVT) + case DMASHDL: + break; +#endif + case CSO: + break; + case SKIP_CH: + break; + } + + return ret; +} + +struct TXS_LIST_ENTRY *GetTxsEntryFromFreeList(void) +{ + struct TXS_LIST_ENTRY *pEntry = NULL; + struct TXS_LIST_ENTRY *pheadEntry = NULL; + struct TXS_FREE_LIST_POOL *pFreeEntrylist = NULL; + unsigned long IrqFlags = 0; + uint32_t i; + + pFreeEntrylist = + automation_dvt.txs.txs_list.pFreeEntrylist; + if (pFreeEntrylist == NULL) + return NULL; + + spin_lock_irqsave(&pFreeEntrylist->Lock, IrqFlags); + + if (list_empty(&pFreeEntrylist->head.mList)) { + struct TXS_LIST_POOL *Pool = NULL; + struct TXS_LIST_POOL *pFreepool = NULL; + + DBGLOG(REQ, LOUD, "allocated new pool\n"); + Pool = kmalloc(sizeof(struct TXS_LIST_POOL), GFP_ATOMIC); + pFreepool = &pFreeEntrylist->pool_head; + list_add(&Pool->List, &pFreepool->List); + pheadEntry = &pFreeEntrylist->head; + + for (i = 0; i < TXS_LIST_ELEM_NUM; i++) { + pEntry = &Pool->Entry[i]; + list_add(&pEntry->mList, &pheadEntry->mList); + } + pFreeEntrylist->entry_number += TXS_LIST_ELEM_NUM; + } + + pheadEntry = &pFreeEntrylist->head; + if (!list_empty(&pheadEntry->mList)) { + pEntry = list_entry(&pheadEntry->mList, + struct TXS_LIST_ENTRY, mList); + list_del(&pEntry->mList); + } + + if (pEntry != NULL) + pFreeEntrylist->entry_number -= 1; + + spin_unlock_irqrestore(&pFreeEntrylist->Lock, IrqFlags); + return pEntry; +} + +/* +* This routine is used to test TXS function. +* Send RTS +*/ +int SendRTS( + struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + struct MSDU_INFO *prMsduInfo; + struct _FRAME_RTS *prTxFrame; + struct BSS_INFO *prBssInfo; + uint16_t u2EstimatedFrameLen; + unsigned long duration = 0; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + ASSERT(prBssInfo); + + /* Calculate MSDU buffer length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + + sizeof(struct _FRAME_RTS); + + /* Alloc MSDU_INFO */ + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc(prAdapter, + u2EstimatedFrameLen); + + if (!prMsduInfo) { + DBGLOG(REQ, WARN, + "No MSDU_INFO_T for sending dvt RTS Frame.\n"); + return -1; + } + + kalMemZero(prMsduInfo->prPacket, u2EstimatedFrameLen); + + prTxFrame = prMsduInfo->prPacket; + + /* Fill frame ctrl */ + prTxFrame->u2FrameCtrl = MAC_FRAME_RTS; + duration = 192 + (uint16_t)((sizeof(struct _FRAME_RTS)<<4)/2); + if (((sizeof(struct _FRAME_RTS)) << 4)%2) + duration++; + prTxFrame->u2Duration = 16 + (uint16_t)duration; + COPY_MAC_ADDR(prTxFrame->aucDestAddr, prStaRec->aucMacAddr); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); + + /* Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prBssInfo->ucBssIndex, + prStaRec->ucIndex, + 16, sizeof(struct _FRAME_RTS), + pfTxDoneHandler, MSDU_RATE_MODE_AUTO); + + /* Enqueue the frame to send this control frame */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + DBGLOG(REQ, INFO, "RTS - Send RTS\n"); + return WLAN_STATUS_SUCCESS; +} + +/* +* This routine is used to test TXS function. +* Send BA packet +*/ +int SendBA( + struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + struct MSDU_INFO *prMsduInfo; + struct _FRAME_BA *prTxFrame; + struct BSS_INFO *prBssInfo; + uint16_t u2EstimatedFrameLen; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + ASSERT(prBssInfo); + + /* Calculate MSDU buffer length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + + sizeof(struct _FRAME_BA); + + /* Alloc MSDU_INFO */ + prMsduInfo = (struct MSDU_INFO *) + cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + + if (!prMsduInfo) { + DBGLOG(REQ, WARN, + "No MSDU_INFO_T for sending dvt RTS Frame.\n"); + return -1; + } + + kalMemZero(prMsduInfo->prPacket, u2EstimatedFrameLen); + + prTxFrame = prMsduInfo->prPacket; + + /* Fill frame ctrl */ + prTxFrame->u2FrameCtrl = MAC_FRAME_BLOCK_ACK; + + COPY_MAC_ADDR(prTxFrame->aucDestAddr, prStaRec->aucMacAddr); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); + + /* Compose the frame body's frame */ + prTxFrame->BarControl.ACKPolicy = 1; + prTxFrame->BarControl.Compressed = 1; + /* prTxFrame->StartingSeq.field.StartSeq = pBAEntry->LastIndSeq; */ + + /* Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prBssInfo->ucBssIndex, + prStaRec->ucIndex, + 16, sizeof(struct _FRAME_BA), + pfTxDoneHandler, MSDU_RATE_MODE_AUTO); + + /* Enqueue the frame to send this control frame */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + DBGLOG(REQ, INFO, "BA - Send BA\n"); + return WLAN_STATUS_SUCCESS; +} + +bool send_add_txs_queue(uint8_t pid, uint8_t wlan_idx) +{ + struct TXS_LIST *list = &automation_dvt.txs.txs_list; + uint32_t idx = 0; + unsigned long IrqFlags = 0; + struct TXS_LIST_ENTRY *pEntry; + struct TXS_LIST_ENTRY *pheadEntry; + + automation_dvt.txs.total_req++; + + if (!list || !automation_dvt.txs.isinit) { + DBGLOG(REQ, WARN, "txs_list doesnot init\n"); + return FALSE; + } + + spin_lock_irqsave(&list->lock, IrqFlags); + + pEntry = GetTxsEntryFromFreeList(); + + if (!pEntry) { + spin_unlock_irqrestore(&list->lock, IrqFlags); + DBGLOG(REQ, LOUD, "pEntry is null!!!\n"); + return FALSE; + } + + idx = automation_dvt.txs.pid % PID_SIZE; + pheadEntry = &list->pHead[idx]; + pEntry->wlan_idx = wlan_idx; + list_add(&pEntry->mList, &pheadEntry->mList); + list->Num++; + automation_dvt.txs.pid++; + + spin_unlock_irqrestore(&list->lock, IrqFlags); + + return TRUE; +} + +bool receive_del_txs_queue( + uint32_t sn, + uint8_t pid, + uint8_t wlan_idx, + uint32_t time_stamp) +{ + struct TXS_LIST *list = &automation_dvt.txs.txs_list; + unsigned long IrqFlags = 0; + unsigned long IrqFlags2 = 0; + struct TXS_FREE_LIST_POOL *pFreeEntrylist = NULL; + struct TXS_LIST_ENTRY *pheadEntry = NULL; + struct TXS_LIST_ENTRY *pEntry = NULL; + + automation_dvt.txs.total_rsp++; + + if (!list || !automation_dvt.txs.isinit) { + DBGLOG(REQ, LOUD, "txs_list doesnot init\n"); + return FALSE; + } + + pFreeEntrylist = list->pFreeEntrylist; + spin_lock_irqsave(&list->lock, IrqFlags); + + list_for_each_entry(pEntry, &list->pHead[pid].mList, mList) { + if (pEntry->wlan_idx == wlan_idx) { + if (automation_dvt.txs.check_item[pid].time_stamp + == time_stamp) + automation_dvt.txs.duplicate_txs = TRUE; + + automation_dvt.txs.check_item[pid].time_stamp = + time_stamp; + list_del_init(&pEntry->mList); + list->Num--; + spin_lock_irqsave(&pFreeEntrylist->Lock, IrqFlags2); + pheadEntry = &pFreeEntrylist->head; + list_add_tail(&pEntry->mList, &pheadEntry->mList); + pFreeEntrylist->entry_number += 1; + spin_unlock_irqrestore(&pFreeEntrylist->Lock, + IrqFlags2); + break; + } + } + spin_unlock_irqrestore(&list->lock, IrqFlags); + return pEntry; +} + +/* +* This routine is used to test TXS function. +* Send specific type of packet and check if TXS is back +*/ +int priv_driver_txs_test( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct STA_RECORD *prStaRec = NULL; + uint32_t u4WCID; + uint8_t ucStaIdx; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int32_t i4Recv = 0; + int32_t txs_test_type; + int32_t txs_test_format; + int8_t *this_char = NULL; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **)netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + this_char = kalStrStr(*apcArgv, "="); + if (!this_char) + return -1; + this_char++; + + DBGLOG(REQ, LOUD, "string = %s\n", this_char); + + i4Recv = sscanf(this_char, "%d-%d-%d", + &(txs_test_type), &(txs_test_format), &(u4WCID)); + + DBGLOG(REQ, LOUD, "txs_test_type=%d, txs_test_format=%d, u4WCID=%d\n", + txs_test_type, txs_test_format, u4WCID); + + if (!AutomationInit(prAdapter, TXS)) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "AutomationInit Fail!\n"); + return i4BytesWritten; + } + + automation_dvt.txs.duplicate_txs = FALSE; + + switch (txs_test_type) { + case TXS_INIT: + TxsExit(); + break; + + case TXS_COUNT_TEST: + automation_dvt.txs.stop_send_test = FALSE; + automation_dvt.txs.test_type = TXS_COUNT_TEST; + automation_dvt.txs.format = txs_test_format; + break; + + case TXS_BAR_TEST: + automation_dvt.txs.stop_send_test = FALSE; + automation_dvt.txs.test_type = TXS_BAR_TEST; + automation_dvt.txs.format = txs_test_format; + /* SendRefreshBAR(pAd, pEntry); */ + break; + + case TXS_DEAUTH_TEST: + automation_dvt.txs.stop_send_test = FALSE; + automation_dvt.txs.test_type = TXS_DEAUTH_TEST; + automation_dvt.txs.format = txs_test_format; + /* aisFsmSteps(prAdapter, AIS_STATE_DISCONNECTING); */ + authSendDeauthFrame(prAdapter, + prAdapter->prAisBssInfo, + prAdapter->prAisBssInfo->prStaRecOfAP, + (struct SW_RFB *) NULL, + REASON_CODE_DEAUTH_LEAVING_BSS, + aisDeauthXmitComplete); + break; + + case TXS_RTS_TEST: + automation_dvt.txs.stop_send_test = FALSE; + automation_dvt.txs.test_type = TXS_RTS_TEST; + automation_dvt.txs.format = txs_test_format; + if (wlanGetStaIdxByWlanIdx(prAdapter, u4WCID, &ucStaIdx) == + WLAN_STATUS_SUCCESS) { + prStaRec = &prAdapter->arStaRec[ucStaIdx]; + } else { + DBGLOG(REQ, LOUD, + "automation wlanGetStaIdxByWlanIdx failed\n"); + } + SendRTS(prAdapter, prStaRec, AutomationTxDone); + break; + + case TXS_BA_TEST: + automation_dvt.txs.stop_send_test = FALSE; + automation_dvt.txs.test_type = TXS_BA_TEST; + automation_dvt.txs.format = txs_test_format; + + if (wlanGetStaIdxByWlanIdx(prAdapter, u4WCID, &ucStaIdx) == + WLAN_STATUS_SUCCESS) { + prStaRec = &prAdapter->arStaRec[ucStaIdx]; + } else { + DBGLOG(REQ, LOUD, + "Automation wlanGetStaIdxByWlanIdx failed\n"); + } + + SendBA(prAdapter, prStaRec, AutomationTxDone); + break; + + case TXS_DUMP_DATA: + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "automation_dvt.txs.test_type=%u\n", + automation_dvt.txs.test_type); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "automation_dvt.txs.format=%u\n", + automation_dvt.txs.format); + break; + } + + return i4BytesWritten; +} + +/* +* This routine is used to test TXS function. +* Check TXS test result +*/ +int priv_driver_txs_test_result( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t txs_test_result = 0, wait_cnt = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int32_t i4Recv = 0; + int8_t *this_char = NULL; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + struct TXS_LIST *list = NULL; + + + list = &automation_dvt.txs.txs_list; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **)netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + this_char = kalStrStr(*apcArgv, "="); + if (!this_char) + return -1; + this_char++; + + DBGLOG(REQ, LOUD, "string = %s\n", this_char); + + i4Recv = kalkStrtos32(this_char, 0, &(txs_test_result)); + DBGLOG(REQ, LOUD, "txs_test_result = %d\n", txs_test_result); + + if (!AutomationInit(prAdapter, TXS)) { + DBGLOG(REQ, LOUD, "AutomationInit Fail!\n"); + return FALSE; + } + + automation_dvt.txs.stop_send_test = TRUE; + DBGLOG(REQ, LOUD, "wait entry to be deleted txs.total_req/rsp=%d %d\n", + automation_dvt.txs.total_req, automation_dvt.txs.total_rsp); + + if (txs_test_result == 1) { + while (automation_dvt.txs.total_req != + automation_dvt.txs.total_rsp) { + kalMsleep(100);/* OS_WAIT(10); */ + wait_cnt++; + if (wait_cnt > 100) + break; + } + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "txs.total_req %u\n", automation_dvt.txs.total_req); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "txs.total_rsp %u\n", automation_dvt.txs.total_rsp); + + if (automation_dvt.txs.total_req == automation_dvt.txs.total_rsp + && (automation_dvt.txs.total_req != 0)) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "TXS_COUNT_TEST------> PASS\n"); + } else { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "TXS_COUNT_TEST------> ERROR\n"); + } + } else if (txs_test_result == 2) { + while (list->Num > 0) { + DBGLOG(REQ, LOUD, "wait entry to be deleted\n"); + kalMsleep(100);/* OS_WAIT(10);*/ + wait_cnt++; + if (wait_cnt > 100) + break; + } + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "txs.total_req %u\n", automation_dvt.txs.total_req); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "txs.total_rsp %u\n", automation_dvt.txs.total_rsp); + + if (list->Num == 0) { + if ((automation_dvt.txs.duplicate_txs == FALSE) && + (automation_dvt.txs.total_req != 0)) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "Correct Frame Test------> PASS\n"); + } else { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "Correct Frame Test------> FAIL duplicate txs"); + } + } else { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "Correct Frame Test------> FAIL txs_q->Num = (%d)\n", + list->Num); + } + } + return i4BytesWritten; +} + +/* +* return 0 : No Need Test +* 1: Check Data frame +* 2: Check management and control frame +*/ +int is_frame_test(struct ADAPTER *pAd, uint8_t send_received) +{ + if (!pAd || (pAd->auto_dvt == NULL)) + return 0; + + if (send_received == 0 && automation_dvt.txs.stop_send_test == TRUE) + return 0; + + switch (automation_dvt.txs.test_type) { + case TXS_COUNT_TEST: + return 1; + case TXS_BAR_TEST: + case TXS_DEAUTH_TEST: + case TXS_RTS_TEST: + case TXS_BA_TEST: + return 2; + + default: + return 0; + } +} + +uint32_t AutomationTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + DBGLOG(REQ, LOUD, "AutomationTxDone!\n"); + if (rTxDoneStatus) + DBGLOG(REQ, LOUD, + "EVENT-TX DONE [status: %d][seq: %d]: Current Time = %d\n", + rTxDoneStatus, prMsduInfo->ucTxSeqNum, + kalGetTimeTick()); + return WLAN_STATUS_SUCCESS; +} + + +/* +* This routine is used to test RXV function. +* step1. AP fixed rate and ping to STA +* step2. STA iwpriv cmd with RXV_TEST=enable-TxMode-BW-MCS-SGI-STBC-LDPC +* step3. STA RXV_RESULT=1, check whether RX packets received from AP +* matched with specific rate +*/ +int priv_driver_rxv_test( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int32_t i4Recv = 0; + uint32_t u4Enable = 0; + int8_t *this_char = NULL; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + uint32_t u4Mode = 0, u4Bw = 0, u4Mcs = 0; + uint32_t u4SGI = 0, u4STBC = 0, u4LDPC = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **)netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + this_char = kalStrStr(*apcArgv, "="); + if (!this_char) + return -1; + this_char++; + + DBGLOG(REQ, LOUD, "string = %s\n", this_char); + + i4Recv = sscanf(this_char, "%d-%d-%d-%d-%d-%d-%d", &(u4Enable), + &(u4Mode), &(u4Bw), &(u4Mcs), + &(u4SGI), &(u4STBC), &(u4LDPC)); + DBGLOG(RX, LOUD, + "%s():Enable = %d, Mode = %d, BW = %d, MCS = %d\n" + "\t\t\t\tSGI = %d, STBC = %d, LDPC = %d\n", + __func__, u4Enable, u4Mode, u4Bw, u4Mcs, + u4SGI, u4STBC, u4LDPC); + + if (!AutomationInit(prAdapter, RXV)) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "AutomationInit Fail!\n"); + return i4BytesWritten; + } + + if (u4Mode == TX_RATE_MODE_OFDM) { + switch (u4Mcs) { + case 0: + u4Mcs = 11; + break; + case 1: + u4Mcs = 15; + break; + case 2: + u4Mcs = 10; + break; + case 3: + u4Mcs = 14; + break; + case 4: + u4Mcs = 9; + break; + case 5: + u4Mcs = 13; + break; + case 6: + u4Mcs = 8; + break; + case 7: + u4Mcs = 12; + break; + default: + DBGLOG(RX, ERROR, + "[%s]OFDM mode but wrong MCS!\n", __func__); + break; + } + } + + automation_dvt.rxv.rxv_test_result = TRUE; + automation_dvt.rxv.enable = u4Enable; + automation_dvt.rxv.rx_count = 0; + + /* expected packets */ + automation_dvt.rxv.rx_mode = u4Mode; + automation_dvt.rxv.rx_bw = u4Bw; + automation_dvt.rxv.rx_rate = u4Mcs; + automation_dvt.rxv.rx_sgi = u4SGI; + automation_dvt.rxv.rx_stbc = u4STBC; + automation_dvt.rxv.rx_ldpc = u4LDPC; + + return i4BytesWritten; +} + +/* +* This routine is used to judge result of RXV DVT. +*/ +int priv_driver_rxv_test_result( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **)netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "RXV Test------> rx_count(%d)\n", + automation_dvt.rxv.rx_count); + + if (automation_dvt.rxv.rxv_test_result == TRUE && + automation_dvt.rxv.rx_count != 0) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "RXV Test------> PASS\n"); + } else { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "RXV Test------> FAIL\n"); + } + + automation_dvt.rxv.enable = 0; + + return i4BytesWritten; +} + +#if (CFG_SUPPORT_CONNAC2X == 1) +/* +* This routine is used to test RXV function. +* It will check RXV of incoming packets if match pre-setting from iwpriv +* Note. This is FALCON RXV format +*/ +void connac2x_rxv_correct_test( + IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + uint32_t prxv1, crxv1; + uint32_t txmode, rate, frmode, sgi, nsts, ldpc, stbc; + + automation_dvt.rxv.rx_count++; + + /* P-RXV1 */ + prxv1 = ((struct HW_MAC_RX_STS_GROUP_3_V2 *) + prSwRfb->prRxStatusGroup3)->u4RxVector[0]; + rate = (prxv1 & CONNAC2X_RX_VT_RX_RATE_MASK) + >> CONNAC2X_RX_VT_RX_RATE_OFFSET; + nsts = (prxv1 & CONNAC2X_RX_VT_NSTS_MASK) + >> CONNAC2X_RX_VT_NSTS_OFFSET; + ldpc = prxv1 & CONNAC2X_RX_VT_LDPC; + /* C-RXV1 */ + crxv1 = prSwRfb->prRxStatusGroup5->u4RxVector[0]; + stbc = (crxv1 & CONNAC2X_RX_VT_STBC_MASK) + >> CONNAC2X_RX_VT_STBC_OFFSET; + txmode = (crxv1 & CONNAC2X_RX_VT_RX_MODE_MASK) + >> CONNAC2X_RX_VT_RX_MODE_OFFSET; + frmode = (crxv1 & CONNAC2X_RX_VT_FR_MODE_MASK) + >> CONNAC2X_RX_VT_FR_MODE_OFFSET; + sgi = (crxv1 & CONNAC2X_RX_VT_SHORT_GI_MASK) + >> CONNAC2X_RX_VT_SHORT_GI_OFFSET; + + if (txmode != automation_dvt.rxv.rx_mode) { + automation_dvt.rxv.rxv_test_result = FALSE; + DBGLOG(RX, ERROR, "[%s]Receive TxMode=%d, Check RxMode=%d\n", + __func__, txmode, automation_dvt.rxv.rx_mode); + } + if (rate != automation_dvt.rxv.rx_rate) { + automation_dvt.rxv.rxv_test_result = FALSE; + DBGLOG(RX, ERROR, "[%s]Receive TxRate=%d, Check RxRate=%d\n", + __func__, rate, automation_dvt.rxv.rx_rate); + } + if (frmode != automation_dvt.rxv.rx_bw) { + automation_dvt.rxv.rxv_test_result = FALSE; + DBGLOG(RX, ERROR, "[%s]Receive BW=%d, Check BW=%d\n", + __func__, frmode, automation_dvt.rxv.rx_bw); + } + if (sgi != automation_dvt.rxv.rx_sgi) { + automation_dvt.rxv.rxv_test_result = FALSE; + DBGLOG(RX, ERROR, "[%s]Receive Sgi=%d, Check Sgi=%d\n", + __func__, sgi, automation_dvt.rxv.rx_sgi); + } + if (stbc != automation_dvt.rxv.rx_stbc) { + automation_dvt.rxv.rxv_test_result = FALSE; + DBGLOG(RX, ERROR, "[%s]Receive Stbc=%d, Check Stbc=%d\n", + __func__, stbc, automation_dvt.rxv.rx_stbc); + } + if (ldpc != automation_dvt.rxv.rx_ldpc) { + automation_dvt.rxv.rxv_test_result = FALSE; + DBGLOG(RX, ERROR, "[%s]Receive Ldpc=%d, Check Ldpc=%d\n", + __func__, ldpc, automation_dvt.rxv.rx_ldpc); + } + + DBGLOG(RX, INFO, + "\n================ RXV Automation end ================\n"); +} +#endif + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +/* +* This routine is used to test CSO function. +* Set 0xffff at checksum filed when cso_ctrl is enabled(15 for all TX case) +* Checksum should be recalculated by HW CSO function. +* step1. iwpriv cmd with CSO_TEST=15 (set CRC of tx packet to 0xffff) +* step2. run TX traffic +* step3. Passed if throughput is normal +*/ +int priv_driver_cso_test( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int32_t i4Recv = 0; + uint8_t ucCsoCtrl = 0; + int8_t *this_char = NULL; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **)netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + this_char = kalStrStr(*apcArgv, "="); + if (!this_char) + return -1; + this_char++; + + DBGLOG(REQ, LOUD, "string = %s\n", this_char); + + i4Recv = kalkStrtou8(this_char, 0, &(ucCsoCtrl)); + DBGLOG(RX, LOUD, "cso_ctrl = %u\n", ucCsoCtrl); + + if (!AutomationInit(prAdapter, CSO)) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "AutomationInit Fail!\n"); + return i4BytesWritten; + } + + /* CSO_TEST=15 for all TX test case */ + /* CSO_TX_IPV4 = BIT(0), */ + /* CSO_TX_IPV6 = BIT(1), */ + /* CSO_TX_TCP = BIT(2), */ + /* CSO_TX_UDP = BIT(3), */ + automation_dvt.cso_ctrl = ucCsoCtrl; + + return i4BytesWritten; +} +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +/* +* This routine is used to test HW feature +* Set a value to allow how many packets be transmitting +*/ +int priv_driver_set_tx_test( + IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + uint32_t u4Ret, u4Parse; + struct ADAPTER *prAdapter = NULL; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **)netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc == 2) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + + prAdapter->u2TxTest = (uint16_t) u4Parse; + DBGLOG(REQ, LOUD, "prAdapter->u2TxTest = %d\n", + prAdapter->u2TxTest); + } else { + DBGLOG(REQ, ERROR, "iwpriv wlanXX driver TX_TEST xxxx\n"); + } + + prAdapter->u2TxTestCount = 0; + return i4BytesWritten; +} + +/* +* This routine is used to test HE Trigger Data +* Assign specific AC of Data to verify HW behavior when receive Trigger frame +*/ +int priv_driver_set_tx_test_ac( + IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + uint32_t u4Ret, u4Parse; + struct ADAPTER *prAdapter = NULL; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **)netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc == 2) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + + prAdapter->ucTxTestUP = (uint8_t) u4Parse; + DBGLOG(REQ, LOUD, "prAdapter->ucTxTestUP = %d\n", + prAdapter->ucTxTestUP); + } else { + DBGLOG(REQ, ERROR, "iwpriv wlanXX driver TX_TEST_AC xx\n"); + } + + return i4BytesWritten; +} + +/* +* This routine is used to skip legal channel sanity check. +* During FPGA stage, could get wrong frequency information +* from RXD. Ignore this error +*/ +int priv_driver_skip_legal_ch_check( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int32_t i4Recv = 0; + uint32_t u4Enable = 0; + int8_t *this_char = NULL; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **)netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + this_char = kalStrStr(*apcArgv, "="); + if (!this_char) + return -1; + this_char++; + + DBGLOG(REQ, LOUD, "string = %s\n", this_char); + + i4Recv = kalkStrtos32(this_char, 0, &(u4Enable)); + DBGLOG(RX, LOUD, "skip_legal_ch_enable = %d\n", u4Enable); + + if (!AutomationInit(prAdapter, SKIP_CH)) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "AutomationInit Fail!\n"); + return i4BytesWritten; + } + + automation_dvt.skip_legal_ch_enable = u4Enable; + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "skip_legal_ch_enable = %d\n", u4Enable); + return i4BytesWritten; +} + +#endif /* CFG_SUPPORT_WIFI_SYSDVT */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/dvt/dvt_dmashdl.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/dvt/dvt_dmashdl.c new file mode 100644 index 0000000000000..f04e83d7e6d71 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/dvt/dvt_dmashdl.c @@ -0,0 +1,1133 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + dvt_dmashdl.c + + Abstract: + For DMA sheduler DVT. + Please refer to DVT plan of DMA SCHEDULER for details + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Kai 2019/01/28 develop this for MT7915 USB(WA) +*/ +#include "precomp.h" + +#if (CFG_SUPPORT_DMASHDL_SYSDVT) +/* +* This routine is used to test return page rule +*/ +void dmashdl_dvt_item_6( + struct GLUE_INFO *prGlueInfo, + struct DMASHDL_DVT_CMD_T *tDvtCmd) +{ + uint32_t value; + struct ADAPTER *prAdapter = NULL; +#if (CFG_SUPPORT_CONNAC2X == 1) + struct mt66xx_chip_info *prChipInfo; +#endif + prAdapter = prGlueInfo->prAdapter; + + if (tDvtCmd->ucSubItemNo == DMASHDL_DVT_SUBITEM_1) { + if (!AutomationInit(prAdapter, DMASHDL)) + return; + + /* reset all setting and count */ + HIF_RESET_SW_LOGIC(prGlueInfo); + + /* mapping all queue to Group 0~4 */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR, + 0x44443210); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_ADDR, + 0x44444444); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_ADDR, + 0x44444444); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR, + 0x44444444); + + /* set quota, max quota 0x4, min quota 0x2*/ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_ADDR, + 0x00040002); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_ADDR, + 0x00040002); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_ADDR, + 0x00040002); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_ADDR, + 0x00040002); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_ADDR, + 0x00040002); + + /* enable refill */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR, + 0xffe00000); + + /* maximux page */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR, + 0x10); + + /* enable WA CPU mode */ + kalDevRegRead(prGlueInfo, + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR, + &value); + value = value | + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_WACPU_MODE_EN_MASK; + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR, + value); + +#if (CFG_SUPPORT_CONNAC2X == 1) + /* inform WACPU test item */ + prChipInfo = prAdapter->chip_info; + if (prChipInfo->is_support_wacpu) + CmdExtDmaShdlDvt2WA(prAdapter, + tDvtCmd->ucItemNo, + tDvtCmd->ucSubItemNo); +#endif /* CFG_SUPPORT_CONNAC2X */ + + /* Step 1. init RSV & SRC */ + HIF_ADD_RSV_CNT(prGlueInfo, 0, 0x2); + HIF_ADD_SRC_CNT(prGlueInfo, 0, 0x3); + HIF_ADD_SRC_CNT(prGlueInfo, 1, 0x4); + HIF_ADD_RSV_CNT(prGlueInfo, 2, 0x1); + HIF_ADD_SRC_CNT(prGlueInfo, 2, 0x2); + HIF_ADD_SRC_CNT(prGlueInfo, 3, 0x2); + HIF_ADD_SRC_CNT(prGlueInfo, 4, 0x2); + HIF_CPU_RTN_CNT(prGlueInfo, 4, 0x2); + + DMASHDL_DVT_SET_ITEM(prAdapter, DMASHDL_DVT_ITEM_6); + } else if (tDvtCmd->ucSubItemNo == DMASHDL_DVT_SUBITEM_2) { + /* step 2. return 3 free pages to Group 0 */ + HIF_SUB_SRC_CNT(prGlueInfo, 0, 0x3); + HIF_ADD_RSV_CNT(prGlueInfo, 0, 0x3); + } +} + +/* +* This routine is used to test FFA refill +*/ +void dmashdl_dvt_item_5( + struct GLUE_INFO *prGlueInfo, + struct DMASHDL_DVT_CMD_T *tDvtCmd) +{ + uint32_t value; + struct ADAPTER *prAdapter = NULL; +#if (CFG_SUPPORT_CONNAC2X == 1) + struct mt66xx_chip_info *prChipInfo; +#endif + prAdapter = prGlueInfo->prAdapter; + + if (!AutomationInit(prAdapter, DMASHDL)) + return; + + /* reset all setting and count */ + HIF_RESET_SW_LOGIC(prGlueInfo); + + /* mapping all queue to Group 0~4 */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR, + 0x44443210); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_ADDR, + 0x44444444); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_ADDR, + 0x44444444); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR, + 0x44444444); + + if (tDvtCmd->ucSubItemNo == DMASHDL_DVT_SUBITEM_2) { + /* set quota, min quota 0x5 for Group 0 & 1 */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_ADDR, + 0x0fff0005); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_ADDR, + 0x0fff0005); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_ADDR, + 0x0fff0001); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_ADDR, + 0x0fff0002); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_ADDR, + 0x0fff0001); + } else { + /* set quota, min quota 0x5 for Group1*/ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_ADDR, + 0x0fff0001); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_ADDR, + 0x0fff0005); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_ADDR, + 0x0fff0001); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_ADDR, + 0x0fff0001); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_ADDR, + 0x0fff0001); + } + + /* enable refill */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR, + 0xffe00000); + + /* maximux page */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR, + 0x10); + + /* enable WA CPU mode */ + kalDevRegRead(prGlueInfo, + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR, + &value); + value = value | + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_WACPU_MODE_EN_MASK; + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR, + value); + +#if (CFG_SUPPORT_CONNAC2X == 1) + /* inform WACPU test item */ + prChipInfo = prAdapter->chip_info; + if (prChipInfo->is_support_wacpu) + CmdExtDmaShdlDvt2WA(prAdapter, + tDvtCmd->ucItemNo, + tDvtCmd->ucSubItemNo); +#endif /* CFG_SUPPORT_CONNAC2X */ + + /* init quota */ + HIF_ADD_RSV_CNT(prGlueInfo, 0, 0x13); + + /* maximux page, start to move packet */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR, + 0x1); + + DMASHDL_DVT_RESET(prAdapter); + DMASHDL_DVT_SET_SUBITEM(prAdapter, tDvtCmd->ucSubItemNo); + DMASHDL_DVT_SET_ITEM(prAdapter, DMASHDL_DVT_ITEM_5); + + /* start to send ping packets to each group */ +} + +/* +* This routine is used to test slot priority +*/ +void dmashdl_dvt_item_4( + struct GLUE_INFO *prGlueInfo, + struct DMASHDL_DVT_CMD_T *tDvtCmd) +{ + uint32_t value; + struct ADAPTER *prAdapter = NULL; +#if (CFG_SUPPORT_CONNAC2X == 1) + struct mt66xx_chip_info *prChipInfo; +#endif + prAdapter = prGlueInfo->prAdapter; + + if (tDvtCmd->ucSubItemNo == DMASHDL_DVT_SUBITEM_1) { + if (!AutomationInit(prAdapter, DMASHDL)) + return; + + /* reset all setting and count */ + HIF_RESET_SW_LOGIC(prGlueInfo); + + /* mapping all queue to Group 0~4 */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR, + 0x44443210); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_ADDR, + 0x44444444); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_ADDR, + 0x44444444); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR, + 0x44444444); + + /* set quota, max quota 0x8, min quota 0x2*/ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_ADDR, + 0x0fff0001); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_ADDR, + 0x0fff0001); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_ADDR, + 0x0fff0001); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_ADDR, + 0x0fff0001); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_ADDR, + 0x0fff0001); + + /* enable refill */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR, + 0xffe00000); + + /* disable joint ASK RR */ + kalDevRegRead(prGlueInfo, + WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_ADDR, + &value); + value = (value & +~WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_GUP_ACT_MAP_MASK); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_ADDR, + value); + + /* disable SRC_CNT_PRI_EN & */ + /* pre-define each slot group strict order(enable as default) */ + kalDevRegRead(prGlueInfo, + WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR, + &value); + value = (value & +~WF_HIF_DMASHDL_TOP_PAGE_SETTING_SRC_CNT_PRI_EN_MASK) | +WF_HIF_DMASHDL_TOP_PAGE_SETTING_GROUP_SEQUENCE_ORDER_TYPE_MASK; + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR, + value); + + /* maximux page */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR, + 0x10); + + /* enable WA CPU mode */ + kalDevRegRead(prGlueInfo, + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR, + &value); + value = value | +WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_WACPU_MODE_EN_MASK; + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR, + value); + +#if (CFG_SUPPORT_CONNAC2X == 1) + /* inform WACPU test item */ + prChipInfo = prAdapter->chip_info; + if (prChipInfo->is_support_wacpu) + CmdExtDmaShdlDvt2WA(prAdapter, + tDvtCmd->ucItemNo, + tDvtCmd->ucSubItemNo); +#endif /* CFG_SUPPORT_CONNAC2X */ + + /* init quota */ + HIF_ADD_RSV_CNT(prGlueInfo, 0, 0x13); + + DMASHDL_DVT_RESET(prAdapter); + DMASHDL_DVT_SET_ITEM(prAdapter, DMASHDL_DVT_ITEM_4); + + /* start to send ping packets to each group */ + } else if (tDvtCmd->ucSubItemNo == DMASHDL_DVT_SUBITEM_2) { + /* maximux page, start to move packet */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR, + 0x1); + } +} + +/* +* This routine is used to test group priority +*/ +void dmashdl_dvt_item_3( + struct GLUE_INFO *prGlueInfo, + struct DMASHDL_DVT_CMD_T *tDvtCmd) +{ + uint32_t value; + struct ADAPTER *prAdapter = NULL; +#if (CFG_SUPPORT_CONNAC2X == 1) + struct mt66xx_chip_info *prChipInfo; +#endif + prAdapter = prGlueInfo->prAdapter; + + if (tDvtCmd->ucSubItemNo == DMASHDL_DVT_SUBITEM_1) { + if (!AutomationInit(prAdapter, DMASHDL)) + return; + + /* reset all setting and count */ + HIF_RESET_SW_LOGIC(prGlueInfo); + + /* mapping all queue to Group 0~4 */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR, + 0x44443210); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_ADDR, + 0x44444444); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_ADDR, + 0x44444444); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR, + 0x44444444); + + /* set quota, max quota 0x8, min quota 0x2*/ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_ADDR, + 0x0fff0001); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_ADDR, + 0x0fff0001); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_ADDR, + 0x0fff0001); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_ADDR, + 0x0fff0001); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_ADDR, + 0x0fff0001); + + /* enable refill */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR, + 0xffe00000); + + /* disable joint ASK RR */ + kalDevRegRead(prGlueInfo, + WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_ADDR, + &value); + value = value & +~WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_GUP_ACT_MAP_MASK; + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_ADDR, + value); + +/* disable SRC_CNT_PRI_EN & user program group sequence order type */ + kalDevRegRead(prGlueInfo, + WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR, + &value); + value = value & +~WF_HIF_DMASHDL_TOP_PAGE_SETTING_SRC_CNT_PRI_EN_MASK & +~WF_HIF_DMASHDL_TOP_PAGE_SETTING_GROUP_SEQUENCE_ORDER_TYPE_MASK; + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR, + value); + + /* group priority */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_ADDR, + 0x76540123); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_ADDR, + 0xfedcba98); + + /* maximux page */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR, + 0x10); + + /* enable WA CPU mode */ + kalDevRegRead(prGlueInfo, + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR, + &value); + value = value | + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_WACPU_MODE_EN_MASK; + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR, + value); + +#if (CFG_SUPPORT_CONNAC2X == 1) + /* inform WACPU test item */ + prChipInfo = prAdapter->chip_info; + if (prChipInfo->is_support_wacpu) + CmdExtDmaShdlDvt2WA(prAdapter, + tDvtCmd->ucItemNo, + tDvtCmd->ucSubItemNo); +#endif /* CFG_SUPPORT_CONNAC2X */ + + /* init quota */ + HIF_ADD_RSV_CNT(prGlueInfo, 0, 0x13); + + DMASHDL_DVT_RESET(prAdapter); + DMASHDL_DVT_SET_ITEM(prAdapter, DMASHDL_DVT_ITEM_3); + + /* start to send ping packets to each group */ + } else if (tDvtCmd->ucSubItemNo == DMASHDL_DVT_SUBITEM_2) { + /* maximux page, start to move packet */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR, + 0x1); + } +} + +/* +* This routine is used to run stress test +*/ +void dmashdl_dvt_item_2( + struct GLUE_INFO *prGlueInfo, + struct DMASHDL_DVT_CMD_T *tDvtCmd) +{ + uint32_t value; +#if (CFG_SUPPORT_CONNAC2X == 1) + struct mt66xx_chip_info *prChipInfo; +#endif + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + + if (!AutomationInit(prAdapter, DMASHDL)) + return; + + /* reset all setting and count */ + HIF_RESET_SW_LOGIC(prGlueInfo); + + /* mapping all queue to Group 0~4 */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR, + 0x21043210); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_ADDR, + 0x04321043); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_ADDR, + 0x32104321); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR, + 0x10432104); + + /* set quota, max quota 0x8, min quota 0x2*/ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_ADDR, + 0x00080002); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_ADDR, + 0x00080002); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_ADDR, + 0x00080002); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_ADDR, + 0x00080002); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_ADDR, + 0x00080002); + + /* enable refill */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR, + 0xffe00000); + + /* maximux page */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR, + 0x10); + + /* enable WA CPU mode */ + kalDevRegRead(prGlueInfo, + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR, + &value); + value = value | + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_WACPU_MODE_EN_MASK; + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR, + value); + +#if (CFG_SUPPORT_CONNAC2X == 1) + /* inform WACPU test item */ + prChipInfo = prAdapter->chip_info; + if (prChipInfo->is_support_wacpu) + CmdExtDmaShdlDvt2WA(prAdapter, + tDvtCmd->ucItemNo, + tDvtCmd->ucSubItemNo); +#endif /* CFG_SUPPORT_CONNAC2X */ + + /* init quota */ + HIF_ADD_RSV_CNT(prGlueInfo, 0, 0x13); + + /* maximux page, start to move packet */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR, + 0x1); + + DMASHDL_DVT_RESET(prAdapter); + DMASHDL_DVT_SET_ITEM(prAdapter, DMASHDL_DVT_ITEM_2); + + /* start to send ping packets to each group */ +} + +/* +* This routine is used to test flow_control for Group 0 ~ 4 +*/ +void dmashdl_dvt_item_1( + struct GLUE_INFO *prGlueInfo, + struct DMASHDL_DVT_CMD_T *tDvtCmd) +{ + uint32_t value; + struct ADAPTER *prAdapter = NULL; +#if (CFG_SUPPORT_CONNAC2X == 1) + struct mt66xx_chip_info *prChipInfo; +#endif + prAdapter = prGlueInfo->prAdapter; + + if (!AutomationInit(prAdapter, DMASHDL)) + return; + + /* reset all setting and count */ + HIF_RESET_SW_LOGIC(prGlueInfo); + + /* mapping all queue to Group 0~4 */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR, + 0x21043210); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_ADDR, + 0x04321043); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_ADDR, + 0x32104321); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR, + 0x10432104); + + /* set quota, max quota 0xfff, min quota 0x4*/ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_ADDR, + 0x0fff0004); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_ADDR, + 0x0fff0004); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_ADDR, + 0x0fff0004); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_ADDR, + 0x0fff0004); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_ADDR, + 0x0fff0004); + + /* disable refill */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR, + 0x0); + + /* maximux page */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR, + 0x10); + + /* enable WA CPU mode */ + kalDevRegRead(prGlueInfo, + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR, + &value); + value = value | + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_WACPU_MODE_EN_MASK; + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR, + value); + + /* tell WA CPU don't return pages */ +#if (CFG_SUPPORT_CONNAC2X == 1) + /* inform WACPU test item */ + prChipInfo = prAdapter->chip_info; + if (prChipInfo->is_support_wacpu) + CmdExtDmaShdlDvt2WA(prAdapter, + tDvtCmd->ucItemNo, + tDvtCmd->ucSubItemNo); +#endif /* CFG_SUPPORT_CONNAC2X */ + + /* init quota */ + HIF_ADD_RSV_CNT(prGlueInfo, 0, 0x4); + HIF_ADD_RSV_CNT(prGlueInfo, 1, 0x4); + HIF_ADD_RSV_CNT(prGlueInfo, 2, 0x4); + HIF_ADD_RSV_CNT(prGlueInfo, 3, 0x4); + HIF_ADD_RSV_CNT(prGlueInfo, 4, 0x4); + + /* maximux page, start to move packet */ + /* SubItem 1 set max page=1, SubItem 2 set max page=2 */ + if (tDvtCmd->ucSubItemNo == DMASHDL_DVT_SUBITEM_2) + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR, 0x2); + else + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR, 0x1); + + DMASHDL_DVT_RESET(prAdapter); + DMASHDL_DVT_SET_SUBITEM(prAdapter, tDvtCmd->ucSubItemNo); + DMASHDL_DVT_SET_ITEM(prAdapter, DMASHDL_DVT_ITEM_1); + /* start to send ping packets to each group */ + +} + +/* +* This routine is reset DMASHDL setting +*/ +void dmashdl_dvt_reset_default( + struct GLUE_INFO *prGlueInfo) +{ + uint32_t value; + + /* reset all setting and count */ + HIF_RESET_SW_LOGIC(prGlueInfo); + + /* mapping all queue to Group 0~4 */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR, + 0x44443210); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_ADDR, + 0x44444444); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_ADDR, + 0x44444444); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR, + 0x44444444); + + /* set quota, max quota 0xfff, min quota 0x1*/ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_ADDR, + 0x0fff0001); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_ADDR, + 0x0fff0001); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_ADDR, + 0x0fff0001); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_ADDR, + 0x0fff0001); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_ADDR, + 0x0fff0001); + + /* enable refill */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR, + 0xffe00000); + + /* group priority */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_ADDR, + 0x76540123); + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_ADDR, + 0xfedcba98); + + /* maximux page */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR, + 0x1); + + /* As default */ + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR, + 0x3f1000); + + /* enable WA CPU mode */ + kalDevRegRead(prGlueInfo, + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR, + &value); + value = value | + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_WACPU_MODE_EN_MASK; + kalDevRegWrite(prGlueInfo, + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR, + value); + + /* init quota */ + HIF_ADD_RSV_CNT(prGlueInfo, 0, 0x13); +} + +/* +* This routine is used to check result. +*/ +int dmashdl_dvt_check_pass( + struct GLUE_INFO *prGlueInfo) +{ + uint32_t addr, free, status[16]; + uint32_t rsvcnt, rsvcnt2, srccnt, freecnt, ffacnt; + uint8_t ucItemNo, ucSubItemNo; + uint8_t i = 0; + uint8_t result = 1; + struct ADAPTER *pAd = NULL; + + pAd = prGlueInfo->prAdapter; + + /* get DVT item */ + ucItemNo = DMASHDL_DVT_GET_ITEM(pAd); + ucSubItemNo = DMASHDL_DVT_GET_SUBITEM(pAd); + + /* get free page & FFA page */ + kalDevRegRead(prGlueInfo, WF_HIF_DMASHDL_TOP_STATUS_RD_ADDR, &free); + + /* fetch status of group0 ~ 15 to array */ + for (i = 0; i < ARRAY_SIZE(status); i++) { + addr = WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_ADDR + i*4; + kalDevRegRead(prGlueInfo, addr, &status[i]); + } + + /* check different CR for different DVT item */ + switch (ucItemNo) { + case DMASHDL_DVT_ITEM_1: + for (i = 0; i < 5; i++) { + rsvcnt = (status[i] & + WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_RSV_CNT_MASK) >> + WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_RSV_CNT_SHFT; + srccnt = (status[i] & + WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_SRC_CNT_MASK) >> + WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_SRC_CNT_SHFT; + + /* Item 1-1 */ + /* check Group0~5 RSV count == 0 && SRC count == 4 */ + if (ucSubItemNo == DMASHDL_DVT_SUBITEM_1) { + if (rsvcnt != 0 || srccnt != 4) { + result = 0; + break; + } + } else if (ucSubItemNo == DMASHDL_DVT_SUBITEM_2) { + /* Item 1-2 */ + /* check Group0~5 rsv_cnt == 1 && src_cnt == 3 */ + if (rsvcnt != 1 || srccnt != 3) { + result = 0; + break; + } + } + } + + break; + case DMASHDL_DVT_ITEM_2: + /* DVT Item 2 */ + /* check Group1(BE) RSV count == 2 & SRC count == 0 */ + /* check Free page == 0x13) & FFA == 0x9 */ + rsvcnt = (status[1] & + WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_RSV_CNT_MASK) >> + WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_RSV_CNT_SHFT; + srccnt = (status[1] & + WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_SRC_CNT_MASK) >> + WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_SRC_CNT_SHFT; + freecnt = (free & + WF_HIF_DMASHDL_TOP_STATUS_RD_FREE_PAGE_CNT_MASK) >> + WF_HIF_DMASHDL_TOP_STATUS_RD_FREE_PAGE_CNT_SHFT; + ffacnt = (free & + WF_HIF_DMASHDL_TOP_STATUS_RD_FFA_CNT_MASK) >> + WF_HIF_DMASHDL_TOP_STATUS_RD_FFA_CNT_SHFT; + if (rsvcnt != 2 || srccnt != 0 || + freecnt != 0x13 || ffacnt != 0x9) + result = 0; + + break; + case DMASHDL_DVT_ITEM_3: + DBGLOG(REQ, INFO, + "Check packet's queue id in sequence on WA\n"); + break; + case DMASHDL_DVT_ITEM_4: + DBGLOG(REQ, INFO, + "Check packet's queue id in sequence on WA\n"); + break; + case DMASHDL_DVT_ITEM_5: + /* Item 5-1 */ + /* check Group1 rsv_cnt == 5, src_cnt == 5 */ + if (ucSubItemNo == DMASHDL_DVT_SUBITEM_1) { + rsvcnt = (status[1] & + WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_RSV_CNT_MASK) >> + WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_RSV_CNT_SHFT; + srccnt = (status[1] & + WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_SRC_CNT_MASK) >> + WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_SRC_CNT_SHFT; + + if (rsvcnt != 5 || srccnt != 5) + result = 0; + } else if (ucSubItemNo == DMASHDL_DVT_SUBITEM_2) { + /* Item 5-2 */ + /* check Group0 rsv_cnt > Group1 rsv_cnt */ + rsvcnt = (status[0] & + WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_RSV_CNT_MASK) >> + WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_RSV_CNT_SHFT; + rsvcnt2 = (status[1] & + WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_RSV_CNT_MASK) >> + WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_RSV_CNT_SHFT; + + if (rsvcnt < rsvcnt2) { + /* failed when Group0's rescnt is less than Group1's */ + result = 0; + } + } + + break; + case DMASHDL_DVT_ITEM_6: + /* check Group0 ~ Group4 */ + /* group 0: rsv_cnt == 2, src_cnt == 0 */ + /* group 1: rsv_cnt == 0, src_cnt == 4 */ + /* group 2: rsv_cnt == 2, src_cnt == 2 */ + /* group 3: rsv_cnt == 2, src_cnt == 2 */ + /* group 4: rsv_cnt == 2, src_cnt == 0 */ + for (i = 0; i < 5; i++) { + rsvcnt = (status[i] & + WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_RSV_CNT_MASK) >> + WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_RSV_CNT_SHFT; + srccnt = (status[i] & + WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_SRC_CNT_MASK) >> + WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_SRC_CNT_SHFT; + + if (i == 0) { + if (rsvcnt != 2 || srccnt != 0) { + result = 0; + break; + } + } else if (i == 1) { + if (rsvcnt != 0 || srccnt != 4) { + result = 0; + break; + } + } else if (i == 2) { + if (rsvcnt != 2 || srccnt != 2) { + result = 0; + break; + } + } else if (i == 3) { + if (rsvcnt != 2 || srccnt != 2) { + result = 0; + break; + } + } else if (i == 4) { + if (rsvcnt != 2 || srccnt != 0) { + result = 0; + break; + } + } + } + + break; + default: + DBGLOG(REQ, INFO, "[DMASHDL] no support this test item\n"); + } + + return result; +} + +/* +* This routine is used to end of DMASHDL DVT and check result. +* iwpriv wlan0 driver "DMASHDL_DVT_ITEM 0" +* echo "DVT PASS" if result is passed +*/ +int dmashdl_dvt_result( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen, + struct DMASHDL_DVT_CMD_T *tDvtCmd) +{ + struct ADAPTER *prAdapter = NULL; +#if (CFG_SUPPORT_CONNAC2X == 1) + struct mt66xx_chip_info *prChipInfo; +#endif + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t idx = 0; + uint8_t dvt_item; + uint8_t *dvt_ping_nums; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **)netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + if (dmashdl_dvt_check_pass(prGlueInfo) == 1) + DBGLOG(REQ, INFO, "DVT PASS\n"); + priv_driver_show_dmashdl_allcr(prNetDev, pcCommand, i4TotalLen); + +#if (CFG_SUPPORT_CONNAC2X == 1) + prChipInfo = prAdapter->chip_info; + /* inform WACPU, this is DVT case */ + if (prChipInfo->is_support_wacpu) + CmdExtDmaShdlDvt2WA(prAdapter, + tDvtCmd->ucItemNo, + tDvtCmd->ucSubItemNo); +#endif /* CFG_SUPPORT_CONNAC2X */ + + if (prAdapter->auto_dvt) { + dvt_item = prAdapter->auto_dvt->dmashdl.dvt_item; + if (dvt_item == DMASHDL_DVT_ITEM_1 + || dvt_item == DMASHDL_DVT_ITEM_2 + || dvt_item == DMASHDL_DVT_ITEM_3 + || dvt_item == DMASHDL_DVT_ITEM_4) { + dvt_ping_nums = + &(prAdapter->auto_dvt->dmashdl.dvt_ping_nums[0]); + for (idx = 0; idx < 32; idx++) + DBGLOG(REQ, INFO, + "Ping nums %u\n", dvt_ping_nums[idx]); + } + } + /* Reset DMASHDL DVT structure after result got */ + DMASHDL_DVT_RESET(prAdapter); + /* Reset DMASHDL setting to default */ + dmashdl_dvt_reset_default(prGlueInfo); + + return i4BytesWritten; +} + +int8_t cmd_atoi(uint8_t ch) +{ + if (ch >= 'a' && ch <= 'f') + return ch - 87; + else if (ch >= 'A' && ch <= 'F') + return ch - 55; + else if (ch >= '0' && ch <= '9') + return ch - 48; + + return 0; +} + +/* +* This routine is used to run DMASHDL DVT items. +* iwpriv wlan0 driver "DMASHDL_DVT_ITEM item subitem" +* For example, run item 1-2: +* iwpriv wlan0 driver "DMASHDL_DVT_ITEM 1 2" +* ping 10.10.10.1 -c 25 (Do some test) +* iwpriv wlan0 driver "DMASHDL_DVT_ITEM 0" +* PS. Item 0 is stop DVT and then check result +*/ +int priv_driver_dmashdl_dvt_item( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen) +{ + struct ADAPTER *prAdapter = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + struct DMASHDL_DVT_CMD_T tDvtCmd; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **)netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, INFO, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + tDvtCmd.ucItemNo = cmd_atoi(apcArgv[1][0]); + tDvtCmd.ucArgNo = i4Argc - 2; + if (tDvtCmd.ucArgNo) + tDvtCmd.ucSubItemNo = cmd_atoi(apcArgv[2][0]); + else + tDvtCmd.ucSubItemNo = 0; + + DBGLOG(REQ, INFO, "[Item Num]=%u\n", tDvtCmd.ucItemNo); + + switch (tDvtCmd.ucItemNo) { + case DMASHDL_DVT_RESULT: + dmashdl_dvt_result(prNetDev, pcCommand, i4TotalLen, &tDvtCmd); + break; + case DMASHDL_DVT_ITEM_1: + dmashdl_dvt_item_1(prGlueInfo, &tDvtCmd); + break; + case DMASHDL_DVT_ITEM_2: + dmashdl_dvt_item_2(prGlueInfo, &tDvtCmd); + break; + case DMASHDL_DVT_ITEM_3: + dmashdl_dvt_item_3(prGlueInfo, &tDvtCmd); + break; + case DMASHDL_DVT_ITEM_4: + dmashdl_dvt_item_4(prGlueInfo, &tDvtCmd); + break; + case DMASHDL_DVT_ITEM_5: + dmashdl_dvt_item_5(prGlueInfo, &tDvtCmd); + break; + case DMASHDL_DVT_ITEM_6: + dmashdl_dvt_item_6(prGlueInfo, &tDvtCmd); + break; + default: + DBGLOG(REQ, INFO, "[DMASHDL] no support this test item\n"); + } + return i4BytesWritten; +} + +/* +* This routine is used to dump related CRs about DMASHDL. +* iwpriv wlan0 driver "DMASHDL_DUMP_MEM" +*/ +int priv_driver_show_dmashdl_allcr( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t addr, value; + int32_t i4BytesWritten = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **)netdev_priv(prNetDev)); + + for (addr = WF_HIF_DMASHDL_TOP_WACPU_REFILL_ADDR; + addr <= WF_HIF_DMASHDL_TOP_GROUP15_CONTROL_ADDR; + addr += 4) { + kalDevRegRead(prGlueInfo, addr, &value); + DBGLOG(REQ, INFO, + "[DMASHDL] Addr[0x%08X], value=0x%08X\n", addr, value); + } + + DBGLOG(REQ, INFO, "[DMASHDL] Queue Mapping\n"); + for (addr = WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR; + addr <= WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR; + addr += 4) { + kalDevRegRead(prGlueInfo, addr, &value); + DBGLOG(REQ, INFO, + "[DMASHDL] Addr[0x%08X], value=0x%08X\n", addr, value); + } + + kalDevRegRead(prGlueInfo, WF_HIF_DMASHDL_TOP_STATUS_RD_ADDR, &value); + DBGLOG(REQ, INFO, + "[DMASHDL] Status RD[0x%08X] value = 0x%08X\n", + WF_HIF_DMASHDL_TOP_STATUS_RD_ADDR, value); + DBGLOG(REQ, INFO, "[DMASHDL] Status RD GP\n"); + for (addr = WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_ADDR; + addr <= WF_HIF_DMASHDL_TOP_STATUS_RD_GP15_ADDR; + addr += 4) { + kalDevRegRead(prGlueInfo, addr, &value); + DBGLOG(REQ, INFO, + "[DMASHDL] Addr[0x%08X], value=0x%08X\n", addr, value); + } + DBGLOG(REQ, INFO, "[DMASHDL] Status RD GP PKT cnt\n"); + for (addr = WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_ADDR; + addr <= WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_ADDR; + addr += 4) { + kalDevRegRead(prGlueInfo, addr, &value); + DBGLOG(REQ, INFO, + "[DMASHDL] Addr[0x%08X], value=0x%08X\n", addr, value); + } + + return i4BytesWritten; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/cmd_buf.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/cmd_buf.c new file mode 100644 index 0000000000000..c10d05529274c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/cmd_buf.c @@ -0,0 +1,321 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + + +/******************************************************************************* + * C O M P I L E 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 + ******************************************************************************* + */ +u_int8_t fgCmdDumpIsDone = FALSE; +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is used to initial the MGMT memory pool for CMD Packet. + * + * @param prAdapter Pointer to the Adapter structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void cmdBufInitialize(IN struct ADAPTER *prAdapter) +{ + struct CMD_INFO *prCmdInfo; + uint32_t 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() */ + +#define CMD_DUMP_NUM_PER_LINE 5 +/*----------------------------------------------------------------------------*/ +/*! + * @brief dump CMD queue and print to trace, for debug use only + * @param[in] prQueue Pointer to the command Queue to be dumped + * @param[in] quename Name of the queue + */ +/*----------------------------------------------------------------------------*/ +void cmdBufDumpCmdQueue(struct QUE *prQueue, + int8_t *queName) +{ + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) + QUEUE_GET_HEAD(prQueue); + uint8_t i = 1, pos = 0; + char buf[500] = {0}; + + DBGLOG(NIC, INFO, "Dump CMD info for %s, Elem number:%u\n", + queName, prQueue->u4NumElem); + kalMemZero(buf, sizeof(buf)); + while (prCmdInfo) { + u_int8_t fgEndLine = i == prQueue->u4NumElem || + i % CMD_DUMP_NUM_PER_LINE == 0; + + pos += kalSnprintf(buf + pos, 30, + "CID:0x%02x,SEQ:%d,Type:%d%s", + prCmdInfo->ucCID, + prCmdInfo->ucCmdSeqNum, + prCmdInfo->eCmdType, + fgEndLine ? "\n" : "; "); + if (fgEndLine) { + DBGLOG(NIC, INFO, "%s", buf); + kalMemZero(buf, sizeof(buf)); + pos = 0; + } + prCmdInfo = (struct CMD_INFO *) QUEUE_GET_NEXT_ENTRY(( + struct QUE_ENTRY *) prCmdInfo); + i++; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +#if CFG_DBG_MGT_BUF +struct CMD_INFO *cmdBufAllocateCmdInfoX(IN struct ADAPTER + *prAdapter, IN uint32_t u4Length, + uint8_t *fileAndLine) +#else +struct CMD_INFO *cmdBufAllocateCmdInfo(IN struct ADAPTER + *prAdapter, IN uint32_t u4Length) +#endif +{ + struct CMD_INFO *prCmdInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("cmdBufAllocateCmdInfo"); + + ASSERT(prAdapter); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + QUEUE_REMOVE_HEAD(&prAdapter->rFreeCmdList, prCmdInfo, + struct CMD_INFO *); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + + if (prCmdInfo) { + kalMemZero(prCmdInfo, sizeof(struct CMD_INFO)); + /* Setup initial value in CMD_INFO_T */ + prCmdInfo->u2InfoBufLen = 0; + prCmdInfo->fgIsOid = FALSE; + + if (u4Length) { + /* Start address of allocated memory */ + u4Length = TFCB_FRAME_PAD_TO_DW(u4Length); + +#if CFG_DBG_MGT_BUF + prCmdInfo->pucInfoBuffer = cnmMemAllocX(prAdapter, + RAM_TYPE_BUF, u4Length, fileAndLine); +#else + prCmdInfo->pucInfoBuffer = cnmMemAlloc(prAdapter, + RAM_TYPE_BUF, u4Length); +#endif + + 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 { + kalMemZero(prCmdInfo->pucInfoBuffer, u4Length); + } + } else { + prCmdInfo->pucInfoBuffer = NULL; + } + fgCmdDumpIsDone = FALSE; + } else if (!fgCmdDumpIsDone) { + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct QUE *prCmdQue = &prGlueInfo->rCmdQueue; + struct QUE *prPendingCmdQue = &prAdapter->rPendingCmdQueue; + struct TX_TCQ_STATUS *prTc = &prAdapter->rTxCtrl.rTc; + + fgCmdDumpIsDone = TRUE; + cmdBufDumpCmdQueue(prCmdQue, "waiting Tx CMD queue"); + cmdBufDumpCmdQueue(prPendingCmdQue, + "waiting response CMD queue"); + DBGLOG(NIC, INFO, "Tc4 number:%d\n", + prTc->au4FreeBufferCount[TC4_INDEX]); + } + + if (prCmdInfo) { + DBGLOG(MEM, TRACE, + "CMD[0x%p] allocated! LEN[%04u], Rest[%u]\n", + prCmdInfo, u4Length, prAdapter->rFreeCmdList.u4NumElem); + + } else { + /* dump debug log */ + prAdapter->u4HifDbgFlag |= DEG_HIF_DEFAULT_DUMP; + kalSetHifDbgEvent(prAdapter->prGlueInfo); + + DBGLOG(MEM, ERROR, + "CMD allocation failed! LEN[%04u], Rest[%u]\n", + u4Length, prAdapter->rFreeCmdList.u4NumElem); + } + + 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 struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo) +{ + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("cmdBufFreeCmdInfo"); + + ASSERT(prAdapter); + + 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); + } + + if (prCmdInfo) + DBGLOG(MEM, LOUD, "CMD[0x%p] freed! Rest[%u]\n", prCmdInfo, + prAdapter->rFreeCmdList.u4NumElem); + + return; + +} /* end of cmdBufFreeCmdPacket() */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic.c new file mode 100644 index 0000000000000..fabf3ef358d56 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic.c @@ -0,0 +1,4867 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic.c#4 + */ + +/*! \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. + */ + + +/******************************************************************************* + * C O M P I L E 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 uint8_t 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 */ + PHY_TYPE_SET_802_11AC, + PHY_TYPE_SET_802_11ANAC, + PHY_TYPE_SET_802_11ABGNAC, +#if (CFG_SUPPORT_802_11AX == 1) + PHY_TYPE_SET_802_11ABGNACAX, +#endif +}; + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +static struct INT_EVENT_MAP 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 uint8_t ucIntEventMapSize = (sizeof( + arIntEventMapTable) / sizeof(struct INT_EVENT_MAP)); + +static IST_EVENT_FUNCTION apfnEventFuncTable[] = { + nicProcessAbnormalInterrupt, /*!< INT_EVENT_ABNORMAL */ + nicProcessSoftwareInterrupt, /*!< INT_EVENT_SW_INT */ + nicProcessTxInterrupt, /*!< INT_EVENT_TX */ + nicProcessRxInterrupt, /*!< INT_EVENT_RX */ +}; + +struct ECO_INFO g_eco_info = {0xFF}; +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +#if defined(_HIF_USB) +struct TIMER rSerSyncTimer = { + .rLinkEntry = {0} +}; +#endif + +/******************************************************************************* + * 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) \ +{ \ + pucMem = (uint8_t *)kalMemAlloc(u4Size, eMemType); \ + if (pucMem == (uint8_t *)NULL) { \ + DBGLOG(INIT, ERROR, \ + "Could not allocate %u bytes for %s.\n", \ + u4Size, (char *) pucComment); \ + break; \ + } \ + ASSERT(((unsigned long)pucMem % 4) == 0); \ + DBGLOG(INIT, TRACE, "Alloc %u bytes, addr = 0x%p for %s.\n", \ + u4Size, (void *) pucMem, (char *) 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicAllocateAdapterMemory(IN struct ADAPTER + *prAdapter) +{ + uint32_t status = WLAN_STATUS_RESOURCES; + struct RX_CTRL *prRxCtrl; + struct TX_CTRL *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 = (uint8_t *) NULL; + prRxCtrl->pucRxCached = (uint8_t *) NULL; + + /* 4 <1> Memory for Management Memory Pool and CMD_INFO_T */ + /* Allocate memory for the struct CMD_INFO + * and its MGMT memory pool. + */ + prAdapter->u4MgtBufCachedSize = MGT_BUFFER_SIZE; + + LOCAL_NIC_ALLOCATE_MEMORY(prAdapter->pucMgtBufCached, + prAdapter->u4MgtBufCachedSize, PHY_MEM_TYPE, + "COMMON MGMT MEMORY POOL"); + + /* 4 <2> Memory for RX Descriptor */ + /* Initialize the number of rx buffers + * we will have in our queue. + */ + /* We may setup ucRxPacketDescriptors by GLUE Layer, + * and using this variable directly. + */ + /* Allocate memory for the SW receive structures. */ + prRxCtrl->u4RxCachedSize = CFG_RX_MAX_PKT_NUM * ALIGN_4( + sizeof(struct SW_RFB)); + + LOCAL_NIC_ALLOCATE_MEMORY(prRxCtrl->pucRxCached, + prRxCtrl->u4RxCachedSize, + VIR_MEM_TYPE, "struct SW_RFB"); + + /* 4 <3> Memory for TX DEscriptor */ + prTxCtrl->u4TxCachedSize = CFG_TX_MAX_PKT_NUM * ALIGN_4( + sizeof(struct MSDU_INFO)); + + LOCAL_NIC_ALLOCATE_MEMORY(prTxCtrl->pucTxCached, + prTxCtrl->u4TxCachedSize, + VIR_MEM_TYPE, "struct MSDU_INFO"); + + /* 4 <4> Memory for Common Coalescing Buffer */ + + /* Get valid buffer size based on config & host capability */ + prAdapter->u4CoalescingBufCachedSize = + halGetValidCoalescingBufSize(prAdapter); + + /* Allocate memory for the common coalescing buffer. */ + prAdapter->pucCoalescingBufCached = kalAllocateIOBuffer( + prAdapter->u4CoalescingBufCachedSize); + + if (prAdapter->pucCoalescingBufCached == NULL) { + DBGLOG(INIT, ERROR, + "Could not allocate %u bytes for coalescing buffer.\n", + prAdapter->u4CoalescingBufCachedSize); + break; + } + + /* <5> Memory for HIF */ + if (halAllocateIOBuffer(prAdapter) != WLAN_STATUS_SUCCESS) + break; + +#if CFG_DBG_MGT_BUF + LINK_INITIALIZE(&prAdapter->rMemTrackLink); +#endif + 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 struct ADAPTER *prAdapter) +{ + struct TX_CTRL *prTxCtrl; + struct RX_CTRL *prRxCtrl; + uint32_t u4Idx; + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + + /* 4 <5> Memory for HIF */ + halReleaseIOBuffer(prAdapter); + + /* 4 <4> Memory for Common Coalescing Buffer */ + if (prAdapter->pucCoalescingBufCached) { + kalReleaseIOBuffer((void *) + prAdapter->pucCoalescingBufCached, + prAdapter->u4CoalescingBufCachedSize); + prAdapter->pucCoalescingBufCached = (uint8_t *) NULL; + } + + /* 4 <3> Memory for TX Descriptor */ + if (prTxCtrl->pucTxCached) { + kalMemFree((void *) prTxCtrl->pucTxCached, VIR_MEM_TYPE, + prTxCtrl->u4TxCachedSize); + prTxCtrl->pucTxCached = (uint8_t *) NULL; + } + /* 4 <2> Memory for RX Descriptor */ + if (prRxCtrl->pucRxCached) { + kalMemFree((void *) prRxCtrl->pucRxCached, VIR_MEM_TYPE, + prRxCtrl->u4RxCachedSize); + prRxCtrl->pucRxCached = (uint8_t *) NULL; + } + /* 4 <1> Memory for Management Memory Pool */ + if (prAdapter->pucMgtBufCached) { + kalMemFree((void *) prAdapter->pucMgtBufCached, + PHY_MEM_TYPE, prAdapter->u4MgtBufCachedSize); + prAdapter->pucMgtBufCached = (uint8_t *) NULL; + } + + /* Memory for TX Desc Template */ + for (u4Idx = 0; u4Idx < CFG_STA_REC_NUM; u4Idx++) + nicTxFreeDescTemplate(prAdapter, + &prAdapter->arStaRec[u4Idx]); + +#if CFG_DBG_MGT_BUF + do { + u_int8_t fgUnfreedMem = FALSE; + struct BUF_INFO *prBufInfo; + + /* Dynamic allocated memory from OS */ + if (prAdapter->u4MemFreeDynamicCount != + prAdapter->u4MemAllocDynamicCount) + fgUnfreedMem = TRUE; + + /* MSG buffer */ + prBufInfo = &prAdapter->rMsgBufInfo; + if (prBufInfo->u4AllocCount != (prBufInfo->u4FreeCount + + prBufInfo->u4AllocNullCount)) + fgUnfreedMem = TRUE; + + /* MGT buffer */ + prBufInfo = &prAdapter->rMgtBufInfo; + if (prBufInfo->u4AllocCount != (prBufInfo->u4FreeCount + + prBufInfo->u4AllocNullCount)) + fgUnfreedMem = TRUE; + + /* Check if all allocated memories are free */ + if (fgUnfreedMem) { + DBGLOG(MEM, ERROR, + "Unequal memory alloc/free count!\n"); + + qmDumpQueueStatus(prAdapter, NULL, 0); + cnmDumpMemoryStatus(prAdapter, NULL, 0); + } + + if (!wlanIsChipNoAck(prAdapter)) { + /* Skip this ASSERT if chip is no ACK */ + if (prAdapter->u4MemFreeDynamicCount != + prAdapter->u4MemAllocDynamicCount) { + struct MEM_TRACK *prMemTrack = NULL; + + DBGLOG(MEM, ERROR, "----- Memory Leak -----\n"); + LINK_FOR_EACH_ENTRY(prMemTrack, + &prAdapter->rMemTrackLink, + rLinkEntry, + struct MEM_TRACK) { + DBGLOG(MEM, ERROR, + "file:line %s, cmd id: %u, where: %u\n", + prMemTrack->pucFileAndLine, + prMemTrack->u2CmdIdAndWhere & + 0x00FF, + (prMemTrack->u2CmdIdAndWhere & + 0xFF00) >> 8); + } + } + ASSERT(prAdapter->u4MemFreeDynamicCount == + prAdapter->u4MemAllocDynamicCount); + } + } while (FALSE); +#endif + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief disable global interrupt + * + * @param prAdapter pointer to the Adapter handler + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicDisableInterrupt(IN struct ADAPTER *prAdapter) +{ + halDisableInterrupt(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief enable global interrupt + * + * @param prAdapter pointer to the Adapter handler + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicEnableInterrupt(IN struct ADAPTER *prAdapter) +{ + halEnableInterrupt(prAdapter); + +} /* end of nicEnableInterrupt() */ + +#if 0 /* CFG_SDIO_INTR_ENHANCE */ +/*----------------------------------------------------------------------------*/ +/*! + * @brief Read interrupt status from hardware + * + * @param prAdapter pointer to the Adapter handler + * @param the interrupts + * + * @return N/A + * + */ +/*----------------------------------------------------------------------------*/ +void nicSDIOReadIntStatus(IN struct ADAPTER *prAdapter, + OUT uint32_t *pu4IntStatus) +{ + struct ENHANCE_MODE_DATA_STRUCT *prSDIOCtrl; + + DEBUGFUNC("nicSDIOReadIntStatus"); + + ASSERT(prAdapter); + ASSERT(pu4IntStatus); + + prSDIOCtrl = prAdapter->prSDIOCtrl; + ASSERT(prSDIOCtrl); + + HAL_PORT_RD(prAdapter, + MCR_WHISR, + sizeof(struct ENHANCE_MODE_DATA_STRUCT), + (uint8_t *) prSDIOCtrl, + sizeof(struct ENHANCE_MODE_DATA_STRUCT)); + + 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->rTxInfo.au4WTSR[2] + | prSDIOCtrl->rTxInfo.au4WTSR[3] + | prSDIOCtrl->rTxInfo.au4WTSR[4] + | prSDIOCtrl->rTxInfo.au4WTSR[5] + | prSDIOCtrl->rTxInfo.au4WTSR[6] + | prSDIOCtrl->rTxInfo.au4WTSR[7])) { + prSDIOCtrl->u4WHISR |= WHISR_TX_DONE_INT; + } + + if ((prSDIOCtrl->u4WHISR & BIT(31)) == 0 && + HAL_GET_MAILBOX_READ_CLEAR(prAdapter) == TRUE && + (prSDIOCtrl->u4RcvMailbox0 != 0 + || prSDIOCtrl->u4RcvMailbox1 != 0)) { + prSDIOCtrl->u4WHISR |= BIT(31); + } + + *pu4IntStatus = prSDIOCtrl->u4WHISR; + +} /* end of nicSDIOReadIntStatus() */ +#endif + +#if 0 /*defined(_HIF_PCIE) */ +void nicPCIEReadIntStatus(IN struct ADAPTER *prAdapter, + OUT uint32_t *pu4IntStatus) +{ + uint32_t u4RegValue; + + *pu4IntStatus = 0; + + HAL_MCR_RD(prAdapter, WPDMA_INT_STA, &u4RegValue); + + if (HAL_IS_RX_DONE_INTR(u4RegValue)) + *pu4IntStatus |= WHISR_RX0_DONE_INT; + + if (HAL_IS_TX_DONE_INTR(u4RegValue)) + *pu4IntStatus |= WHISR_TX_DONE_INT; + + /* clear interrupt */ + HAL_MCR_WR(prAdapter, WPDMA_INT_STA, u4RegValue); + +} +#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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicProcessIST(IN struct ADAPTER *prAdapter) +{ + if (prAdapter == NULL) { + DBGLOG(REQ, ERROR, "prAdapter is NULL!!"); + return WLAN_STATUS_FAILURE; + } + return nicProcessISTWithSpecifiedCount(prAdapter, + prAdapter->rWifiVar.u4HifIstLoopCount); +} + +uint32_t nicProcessISTWithSpecifiedCount(IN struct ADAPTER *prAdapter, + IN uint32_t u4HifIstLoopCount) +{ + uint32_t u4Status = WLAN_STATUS_SUCCESS; + uint32_t u4IntStatus = 0; + uint32_t i; + + 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; + } + + for (i = 0; i < u4HifIstLoopCount; i++) { + + HAL_READ_INT_STATUS(prAdapter, &u4IntStatus); + /* DBGLOG(INIT, TRACE, "u4IntStatus: 0x%x\n", u4IntStatus); */ + + if (u4IntStatus == 0) { + if (i == 0) + u4Status = WLAN_STATUS_NOT_INDICATING; + break; + } + + nicProcessIST_impl(prAdapter, u4IntStatus); + } + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicProcessIST_impl(IN struct ADAPTER *prAdapter, + IN uint32_t u4IntStatus) +{ + uint32_t u4IntCount = 0; + struct INT_EVENT_MAP *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 (0) { + /* ignore */ + } else if (apfnEventFuncTable[prIntEventMap->u4Event] != + NULL) { + apfnEventFuncTable[ + prIntEventMap->u4Event] (prAdapter); + } else { + DBGLOG(INTR, WARN, + "Empty INTR handler! ISAR bit#: %u, event:%u, func: 0x%p\n", + prIntEventMap->u4Int, + prIntEventMap->u4Event, + apfnEventFuncTable[prIntEventMap->u4Event]); + + /* to trap any NULL interrupt handler */ + ASSERT(0); + } + 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t nicVerifyChipID(IN struct ADAPTER *prAdapter) +{ + return halVerifyChipID(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter) +{ + + ASSERT(prAdapter); + + /* 4 <0> Initial value */ +} + +void nicHifInit(IN struct ADAPTER *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) + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicInitializeAdapter(IN struct ADAPTER *prAdapter) +{ + uint32_t u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + + prAdapter->fgIsIntEnableWithLPOwnSet = FALSE; + prAdapter->fgIsReadRevID = FALSE; + + do { + if (!nicVerifyChipID(prAdapter)) { + u4Status = WLAN_STATUS_FAILURE; + break; + } + /* 4 <1> MCR init */ + nicMCRInit(prAdapter); + + HAL_HIF_INIT(prAdapter); + + /* 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 struct ADAPTER *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 struct ADAPTER + *prAdapter) +{ + if (halIsHifStateSuspend(prAdapter)) + DBGLOG(RX, WARN, "suspend Abnormal\n"); + + prAdapter->prGlueInfo->IsrAbnormalCnt++; + + halProcessAbnormalInterrupt(prAdapter); + glSetRstReason(RST_PROCESS_ABNORMAL_INT); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief . + * + * @param prAdapter Pointer to the Adapter structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicProcessFwOwnBackInterrupt(IN struct ADAPTER + *prAdapter) +{ + +} /* end of nicProcessFwOwnBackInterrupt() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief . + * + * @param prAdapter Pointer to the Adapter structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicProcessSoftwareInterrupt(IN struct ADAPTER + *prAdapter) +{ + prAdapter->prGlueInfo->IsrSoftWareCnt++; + if (halIsHifStateSuspend(prAdapter)) + DBGLOG(RX, WARN, "suspend SW INT\n"); + halProcessSoftwareInterrupt(prAdapter); +} /* end of nicProcessSoftwareInterrupt() */ + +void nicSetSwIntr(IN struct ADAPTER *prAdapter, + IN uint32_t u4SwIntrBitmap) +{ + /* NOTE: + * SW interrupt in HW bit 16 is mapping to SW bit 0 + * (shift 16bit in HW transparancy) + * SW interrupt valid from b0~b15 + */ + ASSERT((u4SwIntrBitmap & BITS(0, 15)) == 0); + /* DBGLOG(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 + */ +/*----------------------------------------------------------------------------*/ +struct CMD_INFO *nicGetPendingCmdInfo(IN struct ADAPTER + *prAdapter, IN uint8_t ucSeqNum) +{ + struct QUE *prCmdQue; + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue = &rTempCmdQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) NULL; + + KAL_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, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + + if (prCmdInfo->ucCmdSeqNum == ucSeqNum) + break; + + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + + prCmdInfo = NULL; + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + 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 + */ +/*----------------------------------------------------------------------------*/ +struct MSDU_INFO *nicGetPendingTxMsduInfo( + IN struct ADAPTER *prAdapter, IN uint8_t ucWlanIndex, + IN uint8_t ucPID) +{ + struct QUE *prTxingQue; + struct QUE rTempQue; + struct QUE *prTempQue = &rTempQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct MSDU_INFO *prMsduInfo = (struct MSDU_INFO *) NULL; + + KAL_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, + struct QUE_ENTRY *); + while (prQueueEntry) { + prMsduInfo = (struct MSDU_INFO *) prQueueEntry; + + if ((prMsduInfo->ucPID == ucPID) + && (prMsduInfo->ucWlanIndex == ucWlanIndex)) + break; + + QUEUE_INSERT_TAIL(prTxingQue, prQueueEntry); + + prMsduInfo = NULL; + + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, + struct QUE_ENTRY *); + } + QUEUE_CONCATENATE_QUEUES(prTxingQue, prTempQue); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + if (prMsduInfo) { + DBGLOG(TX, TRACE, + "Get Msdu WIDX:PID[%u:%u] SEQ[%u] from Pending Q\n", + prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, + prMsduInfo->ucTxSeqNum); + } else { + DBGLOG(TX, WARN, + "Cannot get Target Msdu WIDX:PID[%u:%u] from Pending Q\n", + ucWlanIndex, ucPID); + } + + return prMsduInfo; +} + +void nicFreePendingTxMsduInfo(IN struct ADAPTER *prAdapter, + IN uint8_t ucIndex, IN enum ENUM_REMOVE_BY_MSDU_TPYE ucFreeType) +{ + struct QUE *prTxingQue; + struct QUE rTempQue; + struct QUE *prTempQue = &rTempQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct MSDU_INFO *prMsduInfoListHead = (struct MSDU_INFO *) + NULL; + struct MSDU_INFO *prMsduInfoListTail = (struct MSDU_INFO *) + NULL; + struct MSDU_INFO *prMsduInfo = (struct MSDU_INFO *) NULL; + uint8_t ucRemoveByIndex = 255; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + if (ucFreeType >= ENUM_REMOVE_BY_MSDU_TPYE_NUM) { + DBGLOG(TX, WARN, "Wrong remove type: %d\n", ucFreeType); + return; + } + + DBGLOG(NIC, TRACE, "ucIndex: %d, ucFreeType: %d\n", + ucIndex, ucFreeType); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + prTxingQue = &(prAdapter->rTxCtrl.rTxMgmtTxingQueue); + QUEUE_MOVE_ALL(prTempQue, prTxingQue); + + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, + struct QUE_ENTRY *); + + while (prQueueEntry) { + prMsduInfo = (struct MSDU_INFO *) prQueueEntry; + + switch (ucFreeType) { + case MSDU_REMOVE_BY_WLAN_INDEX: + ucRemoveByIndex = prMsduInfo->ucWlanIndex; + break; + case MSDU_REMOVE_BY_BSS_INDEX: + ucRemoveByIndex = prMsduInfo->ucBssIndex; + break; + case MSDU_REMOVE_BY_ALL: + ucRemoveByIndex = 0xFF; + break; + default: + break; + } + + if (ucRemoveByIndex == ucIndex) { + DBGLOG(TX, TRACE, + "%s: Get Msdu WIDX:PID[%u:%u] SEQ[%u] from Pending Q\n", + __func__, prMsduInfo->ucWlanIndex, + prMsduInfo->ucPID, + prMsduInfo->ucTxSeqNum); + + 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, + struct QUE_ENTRY *); + } + QUEUE_CONCATENATE_QUEUES(prTxingQue, prTempQue); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + /* free */ + if (prMsduInfoListHead) { + nicTxFreeMsduInfoPacket(prAdapter, prMsduInfoListHead); + nicTxReturnMsduInfo(prAdapter, prMsduInfoListHead); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This procedure is used to retrieve a CMD sequence number atomically + * + * @param prAdapter Pointer of ADAPTER_T + * + * @retval - UINT_8 + */ +/*----------------------------------------------------------------------------*/ +uint8_t nicIncreaseCmdSeqNum(IN struct ADAPTER *prAdapter) +{ + uint8_t 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 + */ +/*----------------------------------------------------------------------------*/ +uint8_t nicIncreaseTxSeqNum(IN struct ADAPTER *prAdapter) +{ + uint8_t ucRetval; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_SEQ_NUM); + + ucRetval = prAdapter->ucTxSeqNum; + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +nicMediaStateChange(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct EVENT_CONNECTION_STATUS *prConnectionStatus) +{ + struct GLUE_INFO *prGlueInfo; + struct AIS_FSM_INFO *prAisFsmInfo; + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + + switch (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType) { + case NETWORK_TYPE_AIS: + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + if (prConnectionStatus->ucMediaStatus == + MEDIA_STATE_DISCONNECTED) { /* disconnected */ + if (kalGetMediaStateIndicated(prGlueInfo, + ucBssIndex) != + MEDIA_STATE_DISCONNECTED || + prAisFsmInfo->eCurrentState == AIS_STATE_JOIN) { + + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, NULL, + 0, ucBssIndex); + + prAdapter->rWlanInfo.u4SysTime = + kalGetTimeTick(); + } + + /* reset buffered link quality information */ + prAdapter->rLinkQuality.rLq[ucBssIndex]. + fgIsLinkQualityValid = FALSE; + prAdapter->rLinkQuality.rLq[ucBssIndex]. + fgIsLinkRateValid = FALSE; + } else if (prConnectionStatus->ucMediaStatus == + MEDIA_STATE_CONNECTED) { /* connected */ + struct PARAM_BSSID_EX *prCurrBssid = + aisGetCurrBssId(prAdapter, ucBssIndex); + + prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); + + /* fill information for association result */ + prCurrBssid->rSsid.u4SsidLen = + prConnectionStatus->ucSsidLen; + kalMemCopy( + prCurrBssid->rSsid.aucSsid, + prConnectionStatus->aucSsid, + prConnectionStatus->ucSsidLen); + kalMemCopy(prCurrBssid->arMacAddress, + prConnectionStatus->aucBssid, MAC_ADDR_LEN); + prCurrBssid->u4Privacy = + prConnectionStatus->ucEncryptStatus;/* @FIXME */ + prCurrBssid->rRssi = 0; /* @FIXME */ + prCurrBssid->eNetworkTypeInUse = + PARAM_NETWORK_TYPE_AUTOMODE;/* @FIXME */ + prCurrBssid-> + rConfiguration.u4BeaconPeriod + = prConnectionStatus->u2BeaconPeriod; + prCurrBssid-> + rConfiguration.u4ATIMWindow + = prConnectionStatus->u2ATIMWindow; + prCurrBssid-> + rConfiguration.u4DSConfig = + prConnectionStatus->u4FreqInKHz; + prAdapter->rWlanInfo.ucNetworkType[ucBssIndex] = + prConnectionStatus->ucNetworkType; + prCurrBssid->eOpMode + = (enum ENUM_PARAM_OP_MODE) + prConnectionStatus->ucInfraMode; + + /* always indicate to OS according to + * MSDN (re-association/roaming) + */ + if (kalGetMediaStateIndicated(prGlueInfo, + ucBssIndex) != + MEDIA_STATE_CONNECTED) { + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_CONNECT, NULL, + 0, ucBssIndex); + } else { + /* connected -> connected : roaming ? */ + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_ROAM_OUT_FIND_BEST, + NULL, + 0, ucBssIndex); + } + } + break; + +#if CFG_ENABLE_BT_OVER_WIFI + case NETWORK_TYPE_BOW: + break; +#endif + +#if CFG_ENABLE_WIFI_DIRECT + case NETWORK_TYPE_P2P: + break; +#endif + default: + ASSERT(0); + } + + return WLAN_STATUS_SUCCESS; +} /* nicMediaStateChange */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This utility function is used to generate a join failure event to OS + * + * @param + * + * @retval + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicMediaJoinFailure(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN uint32_t rStatus) +{ + struct GLUE_INFO *prGlueInfo; + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + + switch (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType) { + case NETWORK_TYPE_AIS: + kalIndicateStatusAndComplete(prGlueInfo, rStatus, NULL, 0, + ucBssIndex); + + break; + + case NETWORK_TYPE_BOW: + case NETWORK_TYPE_P2P: + default: + break; + } + + return WLAN_STATUS_SUCCESS; +} /* end of nicMediaJoinFailure() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicChannelNum2Freq(uint32_t u4ChannelNum) +{ + uint32_t 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 <= 181) + || (u4ChannelNum == 16)) + u4ChannelInMHz = 5000 + u4ChannelNum * 5; + else if (u4ChannelNum >= 182 && u4ChannelNum <= 196) + u4ChannelInMHz = 4000 + u4ChannelNum * 5; + else if (u4ChannelNum == 201) + u4ChannelInMHz = 2730; + else if (u4ChannelNum == 202) + u4ChannelInMHz = 2498; + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicFreq2ChannelNum(uint32_t 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 5310000: + return 62; + case 5320000: + return 64; + case 5500000: + return 100; + case 5510000: + return 102; + case 5520000: + return 104; + case 5530000: + return 106; + case 5540000: + return 108; + case 5550000: + return 110; + case 5560000: + return 112; + case 5570000: + return 114; + case 5580000: + return 116; + case 5590000: + return 118; + case 5600000: + return 120; + case 5610000: + return 122; + case 5620000: + return 124; + case 5630000: + return 126; + case 5640000: + return 128; + case 5660000: + return 132; + case 5670000: + return 134; + case 5680000: + return 136; + case 5690000: + return 138; + case 5700000: + return 140; + case 5710000: + return 142; + case 5720000: + return 144; + case 5745000: + return 149; + case 5755000: + return 151; + case 5765000: + return 153; + case 5775000: + return 155; + case 5785000: + return 157; + case 5795000: + return 159; + case 5805000: + return 161; + case 5825000: + return 165; + case 5845000: + return 169; + case 5865000: + return 173; + default: + DBGLOG(BSS, INFO, "Return Invalid Channelnum = 0.\n"); + return 0; + } +} + +uint8_t nicGetVhtS1(uint8_t ucPrimaryChannel, + uint8_t ucBandwidth) +{ + /* find S1 (central channel 42, 58, 106, 122, and 155) */ + + if ((ucBandwidth == VHT_OP_CHANNEL_WIDTH_80) + || (ucBandwidth == VHT_OP_CHANNEL_WIDTH_80P80)) { + + if (ucPrimaryChannel >= 36 && ucPrimaryChannel <= 48) + return 42; + else if (ucPrimaryChannel >= 52 && ucPrimaryChannel <= 64) + return 58; + else if (ucPrimaryChannel >= 100 && ucPrimaryChannel <= 112) + return 106; + else if (ucPrimaryChannel >= 116 && ucPrimaryChannel <= 128) + return 122; + else if (ucPrimaryChannel >= 132 && ucPrimaryChannel <= 144) + return 138; + else if (ucPrimaryChannel >= 149 && ucPrimaryChannel <= 161) + return 155; + + } else if (ucBandwidth == VHT_OP_CHANNEL_WIDTH_160) { + + if (ucPrimaryChannel >= 36 && ucPrimaryChannel <= 64) + return 50; + else if (ucPrimaryChannel >= 100 && ucPrimaryChannel <= 128) + return 114; + + } else { + + return 0; + } + + 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 - + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicActivateNetwork(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + struct CMD_BSS_ACTIVATE_CTRL rCmdActivateCtrl; + struct BSS_INFO *prBssInfo; + /* const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; */ + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + /* Enable tx hang detect */ + prAdapter->u4TxHangFlag |= BIT(ucBssIndex); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + prBssInfo->fg40mBwAllowed = FALSE; + prBssInfo->fgAssoc40mBwAllowed = FALSE; + + rCmdActivateCtrl.ucBssIndex = ucBssIndex; + rCmdActivateCtrl.ucActive = 1; + rCmdActivateCtrl.ucNetworkType = (uint8_t) + prBssInfo->eNetworkType; + rCmdActivateCtrl.ucOwnMacAddrIndex = + prBssInfo->ucOwnMacIndex; + COPY_MAC_ADDR(rCmdActivateCtrl.aucBssMacAddr, + prBssInfo->aucOwnMacAddr); + + prBssInfo->ucBMCWlanIndex = + secPrivacySeekForBcEntry(prAdapter, prBssInfo->ucBssIndex, + prBssInfo->aucOwnMacAddr, + STA_REC_INDEX_NOT_FOUND, + CIPHER_SUITE_NONE, 0xFF); + rCmdActivateCtrl.ucBMCWlanIndex = prBssInfo->ucBMCWlanIndex; + + kalMemZero(&rCmdActivateCtrl.ucReserved, + sizeof(rCmdActivateCtrl.ucReserved)); + +#if 1 /* DBG */ + DBGLOG_LIMITED(RSN, INFO, + "[BSS index]=%d OwnMac%d=" MACSTR " BSSID=" MACSTR + " BMCIndex = %d NetType=%d\n", + ucBssIndex, + prBssInfo->ucOwnMacIndex, + MAC2STR(prBssInfo->aucOwnMacAddr), + MAC2STR(prBssInfo->aucBSSID), + prBssInfo->ucBMCWlanIndex, prBssInfo->eNetworkType); +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_BSS_ACTIVATE_CTRL, + TRUE, + FALSE, + FALSE, + NULL, NULL, + sizeof(struct CMD_BSS_ACTIVATE_CTRL), + (uint8_t *)&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 - + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicDeactivateNetwork(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + uint32_t u4Status; + struct CMD_BSS_ACTIVATE_CTRL rCmdActivateCtrl; + struct BSS_INFO *prBssInfo; + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + /* Disable tx hang detect */ + prAdapter->u4TxHangFlag &= ~BIT(ucBssIndex); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + /* FW only supports BMCWlan index 0 ~ 31. + * it always checks BMCWlan index validity and triggers + * assertion if BMCWlan index is invalid. + */ + if (prBssInfo->ucBMCWlanIndex == WTBL_RESERVED_ENTRY) { + DBGLOG(RSN, WARN, + "Network may be deactivated already, ignore\n"); + return WLAN_STATUS_NOT_ACCEPTED; + } + + kalMemZero(&rCmdActivateCtrl, + sizeof(struct CMD_BSS_ACTIVATE_CTRL)); + + rCmdActivateCtrl.ucBssIndex = ucBssIndex; + rCmdActivateCtrl.ucActive = 0; + rCmdActivateCtrl.ucNetworkType = + (uint8_t)prBssInfo->eNetworkType; + rCmdActivateCtrl.ucOwnMacAddrIndex = + prBssInfo->ucOwnMacIndex; + rCmdActivateCtrl.ucBMCWlanIndex = + prBssInfo->ucBMCWlanIndex; + + DBGLOG_LIMITED(RSN, INFO, + "[BSS index]=%d OwnMac=" MACSTR " BSSID=" MACSTR + " BMCIndex = %d NetType=%d\n", + ucBssIndex, + MAC2STR(prBssInfo->aucOwnMacAddr), + MAC2STR(prBssInfo->aucBSSID), + prBssInfo->ucBMCWlanIndex, prBssInfo->eNetworkType); + + u4Status = wlanSendSetQueryCmd(prAdapter, + CMD_ID_BSS_ACTIVATE_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_BSS_ACTIVATE_CTRL), + (uint8_t *)&rCmdActivateCtrl, NULL, 0); + + secRemoveBssBcEntry(prAdapter, prBssInfo, FALSE); + + /* free all correlated station records */ + cnmStaFreeAllStaByNetwork(prAdapter, ucBssIndex, + STA_REC_EXCLUDE_NONE); + if (HAL_IS_TX_DIRECT(prAdapter)) + nicTxDirectClearBssAbsentQ(prAdapter, ucBssIndex); + else + qmFreeAllByBssIdx(prAdapter, ucBssIndex); + + nicFreePendingTxMsduInfo(prAdapter, ucBssIndex, + MSDU_REMOVE_BY_BSS_INDEX); + kalClearSecurityFramesByBssIdx(prAdapter->prGlueInfo, ucBssIndex); + + cnmFreeWmmIndex(prAdapter, prBssInfo); + 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 + * ucBssIndex Index of BSS-INFO + * + * @retval - + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicUpdateBss(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + uint32_t u4Status = WLAN_STATUS_NOT_ACCEPTED; + struct BSS_INFO *prBssInfo; + struct CMD_SET_BSS_INFO rCmdSetBssInfo; + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + + kalMemZero(&rCmdSetBssInfo, + sizeof(struct CMD_SET_BSS_INFO)); + + rCmdSetBssInfo.ucBssIndex = ucBssIndex; + rCmdSetBssInfo.ucConnectionState = (uint8_t) + prBssInfo->eConnectionState; + rCmdSetBssInfo.ucCurrentOPMode = (uint8_t) + prBssInfo->eCurrentOPMode; + rCmdSetBssInfo.ucSSIDLen = (uint8_t) prBssInfo->ucSSIDLen; + kalMemCopy(rCmdSetBssInfo.aucSSID, prBssInfo->aucSSID, + prBssInfo->ucSSIDLen); + COPY_MAC_ADDR(rCmdSetBssInfo.aucBSSID, prBssInfo->aucBSSID); + rCmdSetBssInfo.ucIsQBSS = (uint8_t) prBssInfo->fgIsQBSS; + rCmdSetBssInfo.ucNonHTBasicPhyType = + prBssInfo->ucNonHTBasicPhyType; + rCmdSetBssInfo.u2OperationalRateSet = + prBssInfo->u2OperationalRateSet; + rCmdSetBssInfo.u2BSSBasicRateSet = + prBssInfo->u2BSSBasicRateSet; + rCmdSetBssInfo.u2HwDefaultFixedRateCode = + prBssInfo->u2HwDefaultFixedRateCode; + rCmdSetBssInfo.ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + rCmdSetBssInfo.u4PrivateData = prBssInfo->u4PrivateData; +#if CFG_SUPPORT_DBDC + /* + *To do: In fact, this is not used anymore and could be removed now. + *But command structure change has driver and firmware dependency. + *So currently using ENUM_BAND_AUTO is a temporary solution. + */ + rCmdSetBssInfo.ucDBDCBand = ENUM_BAND_AUTO; +#endif + rCmdSetBssInfo.ucWmmSet = prBssInfo->ucWmmQueSet; + rCmdSetBssInfo.ucNss = prBssInfo->ucOpTxNss; /* Backward compatible */ + + if (prBssInfo->fgBcDefaultKeyExist) { + if (prBssInfo->wepkeyWlanIdx < + prAdapter->ucTxDefaultWlanIndex) + rCmdSetBssInfo.ucBMCWlanIndex = + prBssInfo->wepkeyWlanIdx; + else if (prBssInfo->ucBMCWlanIndexSUsed[ + prBssInfo->ucBcDefaultKeyIdx]) + rCmdSetBssInfo.ucBMCWlanIndex = + prBssInfo->ucBMCWlanIndexS[ + prBssInfo->ucBcDefaultKeyIdx]; + } else + rCmdSetBssInfo.ucBMCWlanIndex = prBssInfo->ucBMCWlanIndex; + + DBGLOG(RSN, TRACE, "Update BSS BMC WlanIdx %u\n", + rCmdSetBssInfo.ucBMCWlanIndex); + +#if CFG_ENABLE_WIFI_DIRECT + rCmdSetBssInfo.ucHiddenSsidMode = + prBssInfo->eHiddenSsidType; +#endif + rlmFillSyncCmdParam(&rCmdSetBssInfo.rBssRlmParam, + prBssInfo); + + rCmdSetBssInfo.ucWapiMode = (uint8_t) FALSE; + + if (IS_BSS_AIS(prBssInfo)) { + struct CONNECTION_SETTINGS *prConnSettings = + aisGetConnSettings(prAdapter, ucBssIndex); +#if CFG_SUPPORT_PASSPOINT + /* mapping OSEN to WPA2, + * due to firmware no need to know current is OSEN + */ + if (prConnSettings->eAuthMode == AUTH_MODE_WPA_OSEN) + rCmdSetBssInfo.ucAuthMode = AUTH_MODE_WPA2; + else +#endif + rCmdSetBssInfo.ucAuthMode = (uint8_t) prConnSettings->eAuthMode; + rCmdSetBssInfo.ucEncStatus = (uint8_t) + prConnSettings->eEncStatus; + rCmdSetBssInfo.ucWapiMode = (uint8_t) + prConnSettings->fgWapiMode; + } +#if CFG_ENABLE_BT_OVER_WIFI + else if (IS_BSS_BOW(prBssInfo)) { + rCmdSetBssInfo.ucAuthMode = (uint8_t) AUTH_MODE_WPA2_PSK; + rCmdSetBssInfo.ucEncStatus = (uint8_t) + ENUM_ENCRYPTION3_KEY_ABSENT; + } +#endif + else { +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { + if (kalP2PGetCcmpCipher(prAdapter->prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData)) { + rCmdSetBssInfo.ucAuthMode = + (uint8_t) AUTH_MODE_WPA2_PSK; + rCmdSetBssInfo.ucEncStatus = + (uint8_t) + ENUM_ENCRYPTION3_ENABLED; + } else if (kalP2PGetTkipCipher(prAdapter->prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData)) { + rCmdSetBssInfo.ucAuthMode = + (uint8_t) AUTH_MODE_WPA_PSK; + rCmdSetBssInfo.ucEncStatus = + (uint8_t) ENUM_ENCRYPTION2_ENABLED; + } else if (kalP2PGetWepCipher(prAdapter->prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData)) { + rCmdSetBssInfo.ucAuthMode = + (uint8_t) AUTH_MODE_OPEN; + rCmdSetBssInfo.ucEncStatus = + (uint8_t) ENUM_ENCRYPTION1_ENABLED; + } else { + rCmdSetBssInfo.ucAuthMode = + (uint8_t) AUTH_MODE_OPEN; + rCmdSetBssInfo.ucEncStatus = + (uint8_t) ENUM_ENCRYPTION_DISABLED; + } + /* Need the probe response to detect the PBC overlap */ + rCmdSetBssInfo.ucIsApMode = + p2pFuncIsAPMode( + prAdapter->rWifiVar.prP2PConnSettings[ + prBssInfo->u4PrivateData]); + + } +#else + rCmdSetBssInfo.ucAuthMode = (uint8_t) AUTH_MODE_WPA2_PSK; + rCmdSetBssInfo.ucEncStatus = (uint8_t) + ENUM_ENCRYPTION3_KEY_ABSENT; +#endif + } + rCmdSetBssInfo.ucDisconnectDetectThreshold = 0; + + if (IS_BSS_AIS(prBssInfo) && + (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) && + (prBssInfo->prStaRecOfAP != NULL)) { + struct BSS_DESC *prBssDesc; + struct AIS_FSM_INFO *prAisFsmInfo; + + rCmdSetBssInfo.ucStaRecIdxOfAP = + prBssInfo->prStaRecOfAP->ucIndex; + cnmAisInfraConnectNotify(prAdapter); + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prBssDesc = prAisFsmInfo->prTargetBssDesc; + if (prBssDesc != NULL) + rCmdSetBssInfo.ucIotApAct = prBssDesc->ucIotApAct; +#if CFG_SUPPORT_SMART_GEAR + DBGLOG(SW4, INFO, "[SG]cnmAisInfraConnectNotify,%d\n", + prBssInfo->eConnectionState); + if (prBssInfo->eConnectionState == MEDIA_STATE_CONNECTED) { + uint8_t ucSGEnable = TRUE, ucRetValNss = 0; + ucRetValNss = wlanGetSupportNss(prAdapter, ucBssIndex); + DBGLOG(SW4, INFO, "[SG]SG Get NSS,%d\n", ucRetValNss); + if (rCmdSetBssInfo.ucIotApAct == WLAN_IOT_AP_DIS_SG) { + DBGLOG(SW4, INFO, + "[SG]Hit SG blacklist, disable SG\n"); + ucSGEnable = FALSE; + } + /*Send Event to Enable/Disable SG*/ + wlandioSetSGStatus(prAdapter, + ucSGEnable, 0xFF, ucRetValNss); + } +#endif + } +#if CFG_ENABLE_WIFI_DIRECT + else if ((prAdapter->fgIsP2PRegistered) && + (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) && + (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) + && (prBssInfo->prStaRecOfAP != NULL)) { + rCmdSetBssInfo.ucStaRecIdxOfAP = + prBssInfo->prStaRecOfAP->ucIndex; + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI +/* disabled for BOW to finish ucBssIndex migration */ + else if (prBssInfo->eNetworkType == NETWORK_TYPE_BOW && + prBssInfo->eCurrentOPMode == OP_MODE_BOW + && prBssInfo->prStaRecOfAP != NULL) { + rCmdSetBssInfo.ucStaRecIdxOfAP = + prBssInfo->prStaRecOfAP->ucIndex; + } +#endif + else + rCmdSetBssInfo.ucStaRecIdxOfAP = STA_REC_INDEX_NOT_FOUND; + +#if (CFG_SUPPORT_802_11AX == 1) + if (fgEfuseCtrlAxOn == 1) { + memcpy(rCmdSetBssInfo.ucHeOpParams, prBssInfo->ucHeOpParams, + HE_OP_BYTE_NUM); + rCmdSetBssInfo.ucBssColorInfo = prBssInfo->ucBssColorInfo; + rCmdSetBssInfo.u2HeBasicMcsSet = + CPU_TO_LE16(prBssInfo->u2HeBasicMcsSet); + } +#endif + +#if (CFG_SUPPORT_802_11V_MBSSID == 1) + rCmdSetBssInfo.ucMaxBSSIDIndicator = prBssInfo->ucMaxBSSIDIndicator; + rCmdSetBssInfo.ucMBSSIDIndex = prBssInfo->ucMBSSIDIndex; +#endif + + DBGLOG(BSS, INFO, + "Update Bss[%u] ConnState[%u] OPmode[%u] BSSID[" MACSTR + "] AuthMode[%u] EncStatus[%u] IotAct[%u]\n", ucBssIndex, + prBssInfo->eConnectionState, + prBssInfo->eCurrentOPMode, MAC2STR(prBssInfo->aucBSSID), + rCmdSetBssInfo.ucAuthMode, + rCmdSetBssInfo.ucEncStatus, + rCmdSetBssInfo.ucIotApAct); + + u4Status = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_BSS_INFO, + TRUE, + FALSE, + FALSE, + NULL, NULL, + sizeof(struct CMD_SET_BSS_INFO), + (uint8_t *)&rCmdSetBssInfo, NULL, 0); + + /* if BSS-INFO is going to be disconnected state, + * free all correlated station records + */ + if (prBssInfo->eConnectionState == + MEDIA_STATE_DISCONNECTED) { + /* clear client list */ + bssInitializeClientList(prAdapter, prBssInfo); + +#if DBG + DBGLOG(BSS, TRACE, "nicUpdateBss for disconnect state\n"); +#endif + /* free all correlated station records */ + cnmStaFreeAllStaByNetwork(prAdapter, ucBssIndex, + STA_REC_EXCLUDE_NONE); + if (HAL_IS_TX_DIRECT(prAdapter)) + nicTxDirectClearBssAbsentQ(prAdapter, ucBssIndex); + else + qmFreeAllByBssIdx(prAdapter, ucBssIndex); + kalClearSecurityFramesByBssIdx(prAdapter->prGlueInfo, + ucBssIndex); +#if CFG_ENABLE_GTK_FRAME_FILTER + if (prBssInfo->prIpV4NetAddrList) + FREE_IPV4_NETWORK_ADDR_LIST( + prBssInfo->prIpV4NetAddrList); +#endif +#if CFG_SUPPORT_DBDC + cnmDbdcRuntimeCheckDecision(prAdapter, ucBssIndex); +#endif + } + + return u4Status; +} + +/* BSS-INFO Indication (PM) */ +/*----------------------------------------------------------------------------*/ +/*! + * @brief This utility function is used to indicate PM that + * a BSS has been created. (for AdHoc / P2P-GO) + * + * @param prAdapter Pointer of ADAPTER_T + * ucBssIndex Index of BSS-INFO + * + * @retval - + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicPmIndicateBssCreated(IN struct ADAPTER + *prAdapter, IN uint8_t ucBssIndex) +{ + struct BSS_INFO *prBssInfo; + struct CMD_INDICATE_PM_BSS_CREATED rCmdIndicatePmBssCreated; + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + rCmdIndicatePmBssCreated.ucBssIndex = ucBssIndex; + 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(struct CMD_INDICATE_PM_BSS_CREATED), + (uint8_t *)&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 - + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicPmIndicateBssConnected(IN struct ADAPTER + *prAdapter, IN uint8_t ucBssIndex) +{ + struct BSS_INFO *prBssInfo; + struct CMD_INDICATE_PM_BSS_CONNECTED + rCmdIndicatePmBssConnected; + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + rCmdIndicatePmBssConnected.ucBssIndex = ucBssIndex; + 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; + + /* rCmdIndicatePmBssConnected.ucBmpDeliveryAC, */ + /* rCmdIndicatePmBssConnected.ucBmpTriggerAC); */ + + if ((GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType == NETWORK_TYPE_AIS) +#if CFG_ENABLE_WIFI_DIRECT + || ((GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType == NETWORK_TYPE_P2P) + && (prAdapter->fgIsP2PRegistered)) +#endif + ) { + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE && + prBssInfo->prStaRecOfAP) { + uint8_t ucUapsd = wmmCalculateUapsdSetting(prAdapter, + ucBssIndex); + + /* should sync Tspec uapsd settings */ + rCmdIndicatePmBssConnected.ucBmpDeliveryAC = + (ucUapsd >> 4) & 0xf; + rCmdIndicatePmBssConnected.ucBmpTriggerAC = + ucUapsd & 0xf; + rCmdIndicatePmBssConnected.fgIsUapsdConnection = + (uint8_t) 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(struct CMD_INDICATE_PM_BSS_CONNECTED), + (uint8_t *)&rCmdIndicatePmBssConnected, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This utility function is used to indicate PM that + * a BSS has been disconnected + * + * @param prAdapter Pointer of ADAPTER_T + * ucBssIndex Index of BSS-INFO + * + * @retval - + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicPmIndicateBssAbort(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + struct CMD_INDICATE_PM_BSS_ABORT rCmdIndicatePmBssAbort; + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + rCmdIndicatePmBssAbort.ucBssIndex = ucBssIndex; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_INDICATE_PM_BSS_ABORT, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_INDICATE_PM_BSS_ABORT), + (uint8_t *)&rCmdIndicatePmBssAbort, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This utility function is used to set power save bit map + * + * + * @param prAdapter Pointer of ADAPTER_T + * ucBssIndex Index of BSS-INFO + * ucSet enter power save or not(1 PS, 0 not PS) + * ucCaller index of bit map for caller + * @retval - + */ +/*----------------------------------------------------------------------------*/ +void +nicPowerSaveInfoMap(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN enum PARAM_POWER_MODE ePowerMode, + IN enum POWER_SAVE_CALLER ucCaller) +{ + uint32_t u4Flag; + + /* max caller is 24 */ + if (ucCaller >= PS_CALLER_MAX_NUM) + ASSERT(0); + + u4Flag = prAdapter->rWlanInfo.u4PowerSaveFlag[ucBssIndex]; + + /* set send command flag */ + if (ePowerMode != Param_PowerModeCAM) { + if ((u4Flag & 0x00FFFFFF) == BIT(ucCaller)) + u4Flag |= PS_SYNC_WITH_FW; + u4Flag &= ~BIT(ucCaller); + } else { + if (u4Flag == 0) + u4Flag |= PS_SYNC_WITH_FW; + u4Flag |= BIT(ucCaller); + } + + DBGLOG(NIC, INFO, + "Flag=0x%04x, Caller=%d, PM=%d, PSFlag[%d]=0x%04x\n", + u4Flag, ucCaller, ePowerMode, ucBssIndex, + prAdapter->rWlanInfo.u4PowerSaveFlag[ucBssIndex]); + + prAdapter->rWlanInfo.u4PowerSaveFlag[ucBssIndex] = u4Flag; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This utility function is used to set power save profile + * + * + * @param prAdapter Pointer of ADAPTER_T + * ucBssIndex Index of BSS-INFO + * ucSet enter power save or not(1 PS, 0 not PS) + * fgEnCmdEvent Enable the functions when command done and timeout + * ucCaller index of bit map for caller + * + * @retval WLAN_STATUS_SUCCESS + * @retval WLAN_STATUS_PENDING + * @retval WLAN_STATUS_FAILURE + * @retval WLAN_STATUS_NOT_SUPPORTED + */ +/*----------------------------------------------------------------------------*/ +uint32_t +nicConfigPowerSaveProfile(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN enum PARAM_POWER_MODE ePwrMode, + IN u_int8_t fgEnCmdEvent, + IN enum POWER_SAVE_CALLER ucCaller) +{ + DEBUGFUNC("nicConfigPowerSaveProfile"); + DBGLOG(INIT, TRACE, + "ucBssIndex:%d, ePwrMode:%d, fgEnCmdEvent:%d\n", + ucBssIndex, ePwrMode, fgEnCmdEvent); + + ASSERT(prAdapter); + + if (ucBssIndex >= prAdapter->ucHwBssIdNum) { + ASSERT(0); + return WLAN_STATUS_NOT_SUPPORTED; + } + + nicPowerSaveInfoMap(prAdapter, ucBssIndex, ePwrMode, ucCaller); + + prAdapter->rWlanInfo.arPowerSaveMode[ucBssIndex].ucBssIndex + = ucBssIndex; + prAdapter->rWlanInfo.arPowerSaveMode[ucBssIndex].ucPsProfile + = (uint8_t) ePwrMode; + + if (PS_SYNC_WITH_FW + & prAdapter->rWlanInfo.u4PowerSaveFlag[ucBssIndex]) { + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + prAdapter->rWlanInfo.u4PowerSaveFlag[ucBssIndex] + &= ~PS_SYNC_WITH_FW; + + DBGLOG(NIC, TRACE, + "SYNC_WITH_FW u4PowerSaveFlag[%d]=0x%04x\n", + ucBssIndex, + prAdapter->rWlanInfo.u4PowerSaveFlag[ucBssIndex]); + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_POWER_SAVE_MODE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + fgEnCmdEvent, /* fgIsOid */ + + /* pfCmdDoneHandler */ + (fgEnCmdEvent ? nicCmdEventSetCommon : NULL), + + /* pfCmdTimeoutHandler */ + (fgEnCmdEvent ? nicOidCmdTimeoutCommon : NULL), + + /* u4SetQueryInfoLen */ + sizeof(struct CMD_PS_PROFILE), + + /* pucInfoBuffer */ + (uint8_t *) &(prAdapter->rWlanInfo + .arPowerSaveMode[ucBssIndex]), + + /* pvSetQueryBuffer */ + NULL, + + /* u4SetQueryBufferLen */ + 0 + ); + + if (fgEnCmdEvent) + return rWlanStatus; + } + return WLAN_STATUS_SUCCESS; +} /* end of nicConfigPowerSaveProfile */ + +uint32_t +nicConfigProcSetCamCfgWrite(IN struct ADAPTER *prAdapter, + IN u_int8_t enabled, IN uint8_t ucBssIndex) +{ + enum PARAM_POWER_MODE ePowerMode; + struct CMD_PS_PROFILE rPowerSaveMode; + + if ((!prAdapter)) + return WLAN_STATUS_FAILURE; + + if (ucBssIndex >= BSS_DEFAULT_NUM) + return WLAN_STATUS_FAILURE; + rPowerSaveMode.ucBssIndex = ucBssIndex; + + if (enabled) { + prAdapter->rWlanInfo.fgEnSpecPwrMgt = TRUE; + ePowerMode = Param_PowerModeCAM; + rPowerSaveMode.ucPsProfile = (uint8_t) ePowerMode; + DBGLOG(INIT, INFO, "Enable CAM BssIndex:%d, PowerMode:%d\n", + ucBssIndex, rPowerSaveMode.ucPsProfile); + } else { + prAdapter->rWlanInfo.fgEnSpecPwrMgt = FALSE; + rPowerSaveMode.ucPsProfile = + prAdapter->rWlanInfo.arPowerSaveMode[ucBssIndex]. + ucPsProfile; + DBGLOG(INIT, INFO, + "Disable CAM BssIndex:%d, PowerMode:%d\n", + ucBssIndex, rPowerSaveMode.ucPsProfile); + } + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_POWER_SAVE_MODE, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_PS_PROFILE), + (uint8_t *) &rPowerSaveMode, + NULL, 0); +} + +uint32_t nicEnterCtiaMode(IN struct ADAPTER *prAdapter, + u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent) +{ + struct CMD_SW_DBG_CTRL rCmdSwCtrl; + /* CMD_ACCESS_REG rCmdAccessReg; */ + uint32_t rWlanStatus; + uint8_t ucBssIdx; + + DEBUGFUNC("nicEnterCtiaMode"); + DBGLOG(INIT, TRACE, "nicEnterCtiaMode: %d\n", fgEnterCtia); + + ASSERT(prAdapter); + + rWlanStatus = WLAN_STATUS_SUCCESS; + + if (fgEnterCtia) { + /* 1. Disable On-Lin Scan */ + prAdapter->fgEnOnlineScan = FALSE; + + /* 2. Disable FIFO FULL no ack */ + /* 3. Disable Roaming */ + /* 4. Disalbe auto tx power */ + rCmdSwCtrl.u4Id = 0xa0100003; + rCmdSwCtrl.u4Data = 0x0; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, NULL, NULL, + sizeof(struct CMD_SW_DBG_CTRL), + (uint8_t *)&rCmdSwCtrl, NULL, 0); + + /* 2. Keep at CAM mode */ + for (ucBssIdx = 0; ucBssIdx < KAL_AIS_NUM; ucBssIdx++) { + enum PARAM_POWER_MODE ePowerMode; + + prAdapter->u4CtiaPowerMode = 0; + prAdapter->fgEnCtiaPowerMode = TRUE; + + ePowerMode = Param_PowerModeCAM; + rWlanStatus = nicConfigPowerSaveProfile(prAdapter, + ucBssIdx, + ePowerMode, fgEnCmdEvent, PS_CALLER_CTIA); + } + + /* 5. Disable Beacon Timeout Detection */ + prAdapter->fgDisBcnLostDetection = TRUE; + } else { + /* 1. Enaable On-Lin Scan */ + prAdapter->fgEnOnlineScan = TRUE; + + /* 2. Enable FIFO FULL no ack */ + /* 3. Enable Roaming */ + /* 4. Enable auto tx power */ + /* */ + + rCmdSwCtrl.u4Id = 0xa0100003; + rCmdSwCtrl.u4Data = 0x1; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, NULL, NULL, + sizeof(struct CMD_SW_DBG_CTRL), + (uint8_t *)&rCmdSwCtrl, NULL, 0); + + /* 2. Keep at Fast PS */ + for (ucBssIdx = 0; ucBssIdx < KAL_AIS_NUM; ucBssIdx++) { + enum PARAM_POWER_MODE ePowerMode; + + prAdapter->u4CtiaPowerMode = 2; + prAdapter->fgEnCtiaPowerMode = TRUE; + + ePowerMode = Param_PowerModeFast_PSP; + rWlanStatus = nicConfigPowerSaveProfile(prAdapter, + ucBssIdx, + ePowerMode, fgEnCmdEvent, PS_CALLER_CTIA); + } + + /* 5. Enable Beacon Timeout Detection */ + prAdapter->fgDisBcnLostDetection = FALSE; + + } + + return rWlanStatus; +} /* end of nicEnterCtiaMode() */ + +uint32_t nicEnterCtiaModeOfScan(IN struct ADAPTER + *prAdapter, u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent) +{ + uint32_t rWlanStatus; + + ASSERT(prAdapter); + DBGLOG(INIT, INFO, "nicEnterCtiaModeOfScan: %d\n", + fgEnterCtia); + + rWlanStatus = WLAN_STATUS_SUCCESS; + + if (fgEnterCtia) { + /* Disable On-Line Scan */ + prAdapter->fgEnOnlineScan = FALSE; + } else { + /* Enable On-Line Scan */ + prAdapter->fgEnOnlineScan = TRUE; + } + + return rWlanStatus; +} + +uint32_t nicEnterCtiaModeOfRoaming(IN struct ADAPTER + *prAdapter, u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent) +{ + struct CMD_SW_DBG_CTRL rCmdSwCtrl; + uint32_t rWlanStatus; + + ASSERT(prAdapter); + DBGLOG(INIT, INFO, "nicEnterCtiaModeOfRoaming: %d\n", + fgEnterCtia); + + rWlanStatus = WLAN_STATUS_SUCCESS; + + if (fgEnterCtia) { + /* Disable Roaming */ + rCmdSwCtrl.u4Id = 0x55660000; + rCmdSwCtrl.u4Data = 0x0; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, NULL, NULL, + sizeof(struct CMD_SW_DBG_CTRL), + (uint8_t *) &rCmdSwCtrl, NULL, 0); + } else { + /* Enable Roaming */ + rCmdSwCtrl.u4Id = 0x55660000; + rCmdSwCtrl.u4Data = 0x1; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, NULL, NULL, + sizeof(struct CMD_SW_DBG_CTRL), + (uint8_t *) &rCmdSwCtrl, NULL, 0); + } + + return rWlanStatus; +} + +uint32_t nicEnterCtiaModeOfCAM(IN struct ADAPTER *prAdapter, + u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent) +{ + uint32_t rWlanStatus; + uint8_t ucBssIdx; + + ASSERT(prAdapter); + DBGLOG(INIT, INFO, "nicEnterCtiaModeOfCAM: %d\n", + fgEnterCtia); + + rWlanStatus = WLAN_STATUS_SUCCESS; + + if (fgEnterCtia) { + /* Keep at CAM mode */ + for (ucBssIdx = 0; ucBssIdx < KAL_AIS_NUM; ucBssIdx++) { + enum PARAM_POWER_MODE ePowerMode; + + prAdapter->u4CtiaPowerMode = 0; + prAdapter->fgEnCtiaPowerMode = TRUE; + + ePowerMode = Param_PowerModeCAM; + rWlanStatus = nicConfigPowerSaveProfile(prAdapter, + ucBssIdx, + ePowerMode, fgEnCmdEvent, PS_CALLER_CTIA_CAM); + } + } else { + /* Keep at Fast PS */ + for (ucBssIdx = 0; ucBssIdx < KAL_AIS_NUM; ucBssIdx++) { + enum PARAM_POWER_MODE ePowerMode; + + prAdapter->u4CtiaPowerMode = 2; + prAdapter->fgEnCtiaPowerMode = TRUE; + + ePowerMode = Param_PowerModeFast_PSP; + rWlanStatus = nicConfigPowerSaveProfile(prAdapter, + ucBssIdx, + ePowerMode, fgEnCmdEvent, PS_CALLER_CTIA_CAM); + } + } + + return rWlanStatus; +} + +uint32_t nicEnterCtiaModeOfBCNTimeout(IN struct ADAPTER + *prAdapter, u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent) +{ + uint32_t rWlanStatus; + + ASSERT(prAdapter); + DBGLOG(INIT, INFO, "nicEnterCtiaModeOfBCNTimeout: %d\n", + fgEnterCtia); + + rWlanStatus = WLAN_STATUS_SUCCESS; + + if (fgEnterCtia) { + /* Disable Beacon Timeout Detection */ + prAdapter->fgDisBcnLostDetection = TRUE; + } else { + /* Enable Beacon Timeout Detection */ + prAdapter->fgDisBcnLostDetection = FALSE; + } + + return rWlanStatus; +} + +uint32_t nicEnterCtiaModeOfAutoTxPower(IN struct ADAPTER + *prAdapter, u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent) +{ + struct CMD_SW_DBG_CTRL rCmdSwCtrl; + uint32_t rWlanStatus; + + ASSERT(prAdapter); + DBGLOG(INIT, INFO, "nicEnterCtiaModeOfAutoTxPower: %d\n", + fgEnterCtia); + + rWlanStatus = WLAN_STATUS_SUCCESS; + + if (fgEnterCtia) { + /* Disalbe auto tx power */ + rCmdSwCtrl.u4Id = 0x55670003; + rCmdSwCtrl.u4Data = 0x0; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_SW_DBG_CTRL), + (uint8_t *) &rCmdSwCtrl, + NULL, 0); + } else { + /* Enable auto tx power */ + rCmdSwCtrl.u4Id = 0x55670003; + rCmdSwCtrl.u4Data = 0x1; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_SW_DBG_CTRL), + (uint8_t *) &rCmdSwCtrl, + NULL, 0); + } + + return rWlanStatus; +} + +uint32_t nicEnterCtiaModeOfFIFOFullNoAck(IN struct ADAPTER + *prAdapter, u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent) +{ + struct CMD_SW_DBG_CTRL rCmdSwCtrl; + uint32_t rWlanStatus; + + ASSERT(prAdapter); + DBGLOG(INIT, INFO, "nicEnterCtiaModeOfFIFOFullNoAck: %d\n", + fgEnterCtia); + + rWlanStatus = WLAN_STATUS_SUCCESS; + + if (fgEnterCtia) { + /* Disable FIFO FULL no ack */ + rCmdSwCtrl.u4Id = 0x55680000; + rCmdSwCtrl.u4Data = 0x0; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_SW_DBG_CTRL), + (uint8_t *) &rCmdSwCtrl, + NULL, 0); + } else { + /* Enable FIFO FULL no ack */ + rCmdSwCtrl.u4Id = 0x55680000; + rCmdSwCtrl.u4Data = 0x1; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_SW_DBG_CTRL), + (uint8_t *) &rCmdSwCtrl, + NULL, 0); + } + + return rWlanStatus; +} + +uint32_t nicEnterTPTestMode(IN struct ADAPTER *prAdapter, + IN uint8_t ucFuncMask) +{ + struct CMD_SW_DBG_CTRL rCmdSwCtrl; + uint32_t rWlanStatus; + uint8_t ucBssIdx; + struct BSS_INFO *prBssInfo; + + ASSERT(prAdapter); + + rWlanStatus = WLAN_STATUS_SUCCESS; + + if (ucFuncMask) { + /* 1. Disable On-Lin Scan */ + if (ucFuncMask & TEST_MODE_DISABLE_ONLINE_SCAN) + prAdapter->fgEnOnlineScan = FALSE; + + /* 2. Disable Roaming */ + if (ucFuncMask & TEST_MODE_DISABLE_ROAMING) { + rCmdSwCtrl.u4Id = 0xa0210000; + rCmdSwCtrl.u4Data = 0x0; + wlanSendSetQueryCmd(prAdapter, CMD_ID_SW_DBG_CTRL, TRUE, + FALSE, FALSE, + NULL, NULL, sizeof(struct CMD_SW_DBG_CTRL), + (uint8_t *)&rCmdSwCtrl, NULL, 0); + } + /* 3. Keep at CAM mode */ + if (ucFuncMask & TEST_MODE_FIXED_CAM_MODE) + for (ucBssIdx = 0; ucBssIdx < prAdapter->ucHwBssIdNum; + ucBssIdx++) { + prBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIdx); + if (prBssInfo->fgIsInUse + && (prBssInfo->eCurrentOPMode + == OP_MODE_INFRASTRUCTURE)) + nicConfigPowerSaveProfile(prAdapter, + ucBssIdx, Param_PowerModeCAM, + FALSE, PS_CALLER_TP); + } + + /* 4. Disable Beacon Timeout Detection */ + if (ucFuncMask & TEST_MODE_DISABLE_BCN_LOST_DET) + prAdapter->fgDisBcnLostDetection = TRUE; + } else { + /* 1. Enaable On-Lin Scan */ + prAdapter->fgEnOnlineScan = TRUE; + + /* 2. Enable Roaming */ + rCmdSwCtrl.u4Id = 0xa0210000; + rCmdSwCtrl.u4Data = 0x1; + wlanSendSetQueryCmd(prAdapter, CMD_ID_SW_DBG_CTRL, TRUE, + FALSE, FALSE, + NULL, NULL, sizeof(struct CMD_SW_DBG_CTRL), + (uint8_t *)&rCmdSwCtrl, NULL, 0); + + /* 3. Keep at Fast PS */ + for (ucBssIdx = 0; ucBssIdx < prAdapter->ucHwBssIdNum; + ucBssIdx++) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + if (prBssInfo->fgIsInUse + && (prBssInfo->eCurrentOPMode + == OP_MODE_INFRASTRUCTURE)) + nicConfigPowerSaveProfile(prAdapter, ucBssIdx, + Param_PowerModeFast_PSP, + FALSE, PS_CALLER_TP); + } + + /* 4. Enable Beacon Timeout Detection */ + prAdapter->fgDisBcnLostDetection = FALSE; + } + + return rWlanStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This utility function is used to indicate firmware domain + * for beacon generation parameters + * + * @param prAdapter Pointer of ADAPTER_T + * eIeUpdMethod, Update Method + * ucBssIndex Index of BSS-INFO + * 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +nicUpdateBeaconIETemplate(IN struct ADAPTER *prAdapter, + IN enum ENUM_IE_UPD_METHOD eIeUpdMethod, + IN uint8_t ucBssIndex, IN uint16_t u2Capability, + IN uint8_t *aucIe, IN uint16_t u2IELen) +{ + struct CMD_BEACON_TEMPLATE_UPDATE *prCmdBcnUpdate; + uint16_t u2CmdBufLen = 0, cmd_size; + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + struct mt66xx_chip_info *prChipInfo; + + DEBUGFUNC("wlanUpdateBeaconIETemplate"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + prChipInfo = prAdapter->chip_info; + + 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(struct CMD_BEACON_TEMPLATE_UPDATE, + aucIE) + u2IELen; + } else if (eIeUpdMethod == IE_UPD_METHOD_DELETE_ALL) { + u2CmdBufLen = OFFSET_OF(struct CMD_BEACON_TEMPLATE_UPDATE, + u2IELen); +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP + } else if (eIeUpdMethod == IE_UPD_METHOD_UPDATE_PROBE_RSP) { + u2CmdBufLen = OFFSET_OF(struct CMD_BEACON_TEMPLATE_UPDATE, + aucIE) + u2IELen; + DBGLOG(NIC, INFO, + "update for probe response offload to firmware\n"); +#endif + } else { + DBGLOG(INIT, ERROR, "Unknown IeUpdMethod.\n"); + return WLAN_STATUS_FAILURE; + } + + /* prepare command info */ + cmd_size = prChipInfo->u2CmdTxHdrSize + u2CmdBufLen; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, cmd_size); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->u2InfoBufLen = cmd_size; + 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->u4SetInfoLen = u2CmdBufLen; + prCmdInfo->pvInformationBuffer = NULL; + prCmdInfo->u4InformationBufferLength = 0; + + /* Setup WIFI_CMD_T (no payload) */ + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + prCmdInfo->ucCID, + CMD_PACKET_TYPE_ID, + &prCmdInfo->ucCmdSeqNum, + prCmdInfo->fgSetQuery, + &prCmdBcnUpdate, FALSE, 0, S2D_INDEX_CMD_H2N); + + /* fill beacon updating command */ + prCmdBcnUpdate->ucUpdateMethod = (uint8_t) eIeUpdMethod; + prCmdBcnUpdate->ucBssIndex = ucBssIndex; + prCmdBcnUpdate->u2Capability = u2Capability; + prCmdBcnUpdate->u2IELen = u2IELen; + if (u2IELen > 0) + kalMemCopy(prCmdBcnUpdate->aucIE, aucIe, u2IELen); + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, + (struct QUE_ENTRY *) 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 struct ADAPTER *prAdapter) +{ + ASSERT(prAdapter); + + if (prAdapter->rWifiVar.eDesiredPhyConfig >= PHY_CONFIG_NUM) { + ASSERT(0); + return; + } + + prAdapter->rWifiVar.ucAvailablePhyTypeSet = + aucPhyCfg2PhyTypeSet[ + prAdapter->rWifiVar.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 + prAdapter->rWifiVar.eNonHTBasicPhyType2G4 = + PHY_TYPE_HR_DSSS_INDEX; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This utility function is used to update WMM Parms + * + * @param prAdapter Pointer of ADAPTER_T + * ucBssIndex Index of BSS-INFO + * + * @retval - + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicQmUpdateWmmParms(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + struct BSS_INFO *prBssInfo; + struct CMD_UPDATE_WMM_PARMS rCmdUpdateWmmParms; + struct mt66xx_chip_info *prChipInfo; + uint32_t u4TxHifRes = 0, u4Idx = 0; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + DBGLOG(QM, TRACE, "Update WMM parameters for BSS[%u]\n", + ucBssIndex); + + DBGLOG(QM, TRACE, "sizeof(struct AC_QUE_PARMS): %zu\n", + sizeof(struct AC_QUE_PARMS)); + DBGLOG(QM, TRACE, "sizeof(CMD_UPDATE_WMM_PARMS): %zu\n", + sizeof(struct CMD_UPDATE_WMM_PARMS)); + DBGLOG(QM, TRACE, "u2CmdTxHdrSize: %u\n", + prChipInfo->u2CmdTxHdrSize); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + rCmdUpdateWmmParms.ucBssIndex = (uint8_t) ucBssIndex; + kalMemCopy(&rCmdUpdateWmmParms.arACQueParms[0], + &prBssInfo->arACQueParms[0], + (sizeof(struct AC_QUE_PARMS) * AC_NUM)); + + rCmdUpdateWmmParms.fgIsQBSS = prBssInfo->fgIsQBSS; + rCmdUpdateWmmParms.ucWmmSet = (uint8_t) + prBssInfo->ucWmmQueSet; + + /* If VI use worse parameter than BE, need to use round-robbin queue + * to enqueue data from HIF to HW. + * (Should revise if HIF can have separate queue for each AC) + */ + if (rCmdUpdateWmmParms.arACQueParms[AC1].u2Aifsn + < rCmdUpdateWmmParms.arACQueParms[AC2].u2Aifsn) { + + /* Use round-robbin queuing in HIF */ + prAdapter->rWifiVar.ucTxMsduQueue = 1; + + /* The ratio of each AC is 1:1:1:1 in this case */ + u4TxHifRes = 0x00111111; + } else { + /* Use default setting when wifi init */ + prAdapter->rWifiVar.ucTxMsduQueue = + prAdapter->rWifiVar.ucTxMsduQueueInit; + u4TxHifRes = prAdapter->rWifiVar.u4TxHifRes; + } + + DBGLOG_LIMITED(QM, INFO, "ucTxMsduQueue:[%u], u4TxHifRes[%d]", + prAdapter->rWifiVar.ucTxMsduQueue, u4TxHifRes); + + for (u4Idx = 0; u4Idx < TX_PORT_NUM && u4TxHifRes; u4Idx++) { + prAdapter->au4TxHifResCtl[u4Idx] = u4TxHifRes & BITS(0, 3); + u4TxHifRes = u4TxHifRes >> 4; + } + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_UPDATE_WMM_PARMS, + TRUE, + FALSE, + FALSE, + NULL, NULL, + sizeof(struct CMD_UPDATE_WMM_PARMS), + (uint8_t *)&rCmdUpdateWmmParms, NULL, 0); +} + +#if (CFG_SUPPORT_802_11AX == 1) +uint32_t nicQmUpdateMUEdcaParams(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + struct BSS_INFO *prBssInfo; + struct _CMD_MQM_UPDATE_MU_EDCA_PARMS_T rCmdUpdateMUEdcaParms; + + ASSERT(prAdapter); + + DBGLOG(QM, INFO, "Update MU EDCA parameters for BSS[%u]\n", ucBssIndex); + + DBGLOG(QM, EVENT, "sizeof(CMD_MU_EDCA_PARAMS_T): %d\n", + sizeof(struct _CMD_MU_EDCA_PARAMS_T)); + DBGLOG(QM, EVENT, "sizeof(CMD_MQM_UPDATE_MU_EDCA_PARMS_T): %d\n", + sizeof(struct _CMD_MQM_UPDATE_MU_EDCA_PARMS_T)); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + rCmdUpdateMUEdcaParms.ucBssIndex = (uint8_t) ucBssIndex; + + if (prAdapter->fgMuEdcaOverride) { + + enum ENUM_WMM_ACI eAci; + struct _CMD_MU_EDCA_PARAMS_T *prMUEdca; + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + + prMUEdca = + &(rCmdUpdateMUEdcaParms.arMUEdcaParams[eAci]); + + prMUEdca->ucECWmin = 15; + prMUEdca->ucECWmax = 15; + prMUEdca->ucAifsn = 0; + prMUEdca->ucIsACMSet = 0; + prMUEdca->ucMUEdcaTimer = 0xff; + } + } else { + kalMemCopy(&rCmdUpdateMUEdcaParms.arMUEdcaParams[0], + &prBssInfo->arMUEdcaParams[0], + (sizeof(struct _CMD_MU_EDCA_PARAMS_T) * AC_NUM)); + } + + rCmdUpdateMUEdcaParms.fgIsQBSS = prBssInfo->fgIsQBSS; + rCmdUpdateMUEdcaParms.ucWmmSet = (uint8_t) prBssInfo->ucWmmQueSet; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_MQM_UPDATE_MU_EDCA_PARMS, + TRUE, + FALSE, + FALSE, + NULL, NULL, + sizeof(struct _CMD_MQM_UPDATE_MU_EDCA_PARMS_T), + (uint8_t *)&rCmdUpdateMUEdcaParms, NULL, 0); +} + +uint32_t nicRlmUpdateSRParams(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + struct BSS_INFO *prBssInfo; + struct _CMD_RLM_UPDATE_SR_PARMS_T rCmdUpdateSRParms; + + ASSERT(prAdapter); + + DBGLOG(RLM, INFO, + "Update Spatial Reuse parameters for BSS[%u] size: %d\n", + ucBssIndex, + sizeof(struct _CMD_RLM_UPDATE_SR_PARMS_T)); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + rCmdUpdateSRParms.ucBssIndex = ucBssIndex; + rCmdUpdateSRParms.ucSRControl = prBssInfo->ucSRControl; + rCmdUpdateSRParms.ucNonSRGObssPdMaxOffset = + prBssInfo->ucNonSRGObssPdMaxOffset; + rCmdUpdateSRParms.ucSRGObssPdMinOffset = + prBssInfo->ucSRGObssPdMinOffset; + rCmdUpdateSRParms.ucSRGObssPdMaxOffset = + prBssInfo->ucSRGObssPdMaxOffset; + rCmdUpdateSRParms.u4SRGBSSColorBitmapLow = CPU_TO_LE32( + (uint32_t)(prBssInfo->u8SRGBSSColorBitmap & 0xFFFFFFFF)); + rCmdUpdateSRParms.u4SRGBSSColorBitmapHigh = CPU_TO_LE32( + (uint32_t)(prBssInfo->u8SRGBSSColorBitmap >> 32)); + rCmdUpdateSRParms.u4SRGPartialBSSIDBitmapLow = CPU_TO_LE32( + (uint32_t)(prBssInfo->u8SRGPartialBSSIDBitmap & 0xFFFFFFFF)); + rCmdUpdateSRParms.u4SRGPartialBSSIDBitmapHigh = CPU_TO_LE32( + (uint32_t)(prBssInfo->u8SRGPartialBSSIDBitmap >> 32)); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_RLM_UPDATE_SR_PARAMS, + TRUE, + FALSE, + FALSE, + NULL, NULL, + sizeof(struct _CMD_RLM_UPDATE_SR_PARMS_T), + (uint8_t *)&rCmdUpdateSRParms, NULL, 0); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicUpdateTxPower(IN struct ADAPTER *prAdapter, + IN struct CMD_TX_PWR *prTxPwrParam) +{ + DEBUGFUNC("nicUpdateTxPower"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_TX_PWR, + TRUE, + FALSE, FALSE, NULL, NULL, + sizeof(struct CMD_TX_PWR), + (uint8_t *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicSetAutoTxPower(IN struct ADAPTER *prAdapter, + IN struct CMD_AUTO_POWER_PARAM *prAutoPwrParam) +{ + DEBUGFUNC("nicSetAutoTxPower"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_AUTOPWR_CTRL, + TRUE, + FALSE, + FALSE, + NULL, NULL, + sizeof(struct CMD_AUTO_POWER_PARAM), + (uint8_t *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicSetAutoTxPowerControl(IN struct ADAPTER + *prAdapter, IN struct CMD_TX_PWR *prTxPwrParam) +{ + DEBUGFUNC("nicUpdateTxPower"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_TX_PWR, + TRUE, + FALSE, FALSE, NULL, NULL, + sizeof(struct CMD_TX_PWR), + (uint8_t *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicUpdate5GOffset(IN struct ADAPTER *prAdapter, + IN struct CMD_5G_PWR_OFFSET *pr5GPwrOffset) +{ +#if 0 /* It is not needed anymore */ + DEBUGFUNC("nicUpdate5GOffset"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_5G_PWR_OFFSET, + TRUE, + FALSE, + FALSE, NULL, NULL, + sizeof(struct CMD_5G_PWR_OFFSET), + (uint8_t *) pr5GPwrOffset, NULL, 0); +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicUpdateDPD(IN struct ADAPTER *prAdapter, + IN struct CMD_PWR_PARAM *prDpdCalResult) +{ + DEBUGFUNC("nicUpdateDPD"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_PWR_PARAM, + TRUE, + FALSE, + FALSE, NULL, NULL, + sizeof(struct CMD_PWR_PARAM), + (uint8_t *) 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 struct ADAPTER *prAdapter, + IN const u_int8_t bAtResetFlow) +{ + ASSERT(prAdapter); + + /* <1> Initialize MGMT Memory pool and STA_REC */ + if (!bAtResetFlow) { + cnmMemInit(prAdapter); + cnmStaRecInit(prAdapter); + } + + cmdBufInitialize(prAdapter); + + if (!bAtResetFlow) { + /* <2> Mailbox Initialization */ + mboxInitialize(prAdapter); + + /* <3> Timer Initialization */ + cnmTimerInitialize(prAdapter); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This utility function reset some specific system service, + * such as STA-REC + * + * @param prAdapter Pointer of ADAPTER_T + * + * @retval none + */ +/*----------------------------------------------------------------------------*/ +void nicResetSystemService(IN struct ADAPTER *prAdapter) +{ + ASSERT(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This utility function is used to update WMM Parms + * + * @param prAdapter Pointer of ADAPTER_T + * + * @retval none + */ +/*----------------------------------------------------------------------------*/ +void nicUninitSystemService(IN struct ADAPTER *prAdapter) +{ + ASSERT(prAdapter); + + /* Timer Destruction */ + cnmTimerDestroy(prAdapter); + + /* Mailbox Destruction */ + mboxDestroy(prAdapter); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This utility function is used to update WMM Parms + * + * @param prAdapter Pointer of ADAPTER_T + * + * @retval none + */ +/*----------------------------------------------------------------------------*/ +void nicInitMGMT(IN struct ADAPTER *prAdapter, + IN struct REG_INFO *prRegInfo) +{ + uint8_t i; + + ASSERT(prAdapter); + + /* CNM Module - initialization */ + cnmInit(prAdapter); + + wmmInit(prAdapter); + + /* RLM Module - initialization */ + rlmFsmEventInit(prAdapter); + + /* SCN Module - initialization */ + scnInit(prAdapter); + + for (i = 0; i < KAL_AIS_NUM; i++) { + /* AIS Module - intiailization */ + aisFsmInit(prAdapter, i); + aisInitializeConnectionSettings(prAdapter, + prRegInfo, + i); +#if CFG_SUPPORT_ROAMING + /* Roaming Module - intiailization */ + roamingFsmInit(prAdapter, i); +#endif /* CFG_SUPPORT_ROAMING */ + } + +#if CFG_SUPPORT_SWCR + swCrDebugInit(prAdapter); +#endif /* CFG_SUPPORT_SWCR */ + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This utility function is used to update WMM Parms + * + * @param prAdapter Pointer of ADAPTER_T + * + * @retval none + */ +/*----------------------------------------------------------------------------*/ +void nicUninitMGMT(IN struct ADAPTER *prAdapter) +{ + uint8_t i; + + ASSERT(prAdapter); + +#if CFG_SUPPORT_SWCR + swCrDebugUninit(prAdapter); +#endif /* CFG_SUPPORT_SWCR */ + + for (i = 0; i < KAL_AIS_NUM; i++) { +#if CFG_SUPPORT_ROAMING + /* Roaming Module - unintiailization */ + roamingFsmUninit(prAdapter, i); +#endif /* CFG_SUPPORT_ROAMING */ + + /* AIS Module - unintiailization */ + aisFsmUninit(prAdapter, i); + } + + /* SCN Module - unintiailization */ + scnUninit(prAdapter); + + wmmUnInit(prAdapter); + + /* RLM Module - uninitialization */ + rlmFsmEventUninit(prAdapter); + + /* CNM Module - uninitialization */ + cnmUninit(prAdapter); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 u2CapInfo Capability settings + * @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 struct ADAPTER *prAdapter, + IN uint8_t rMacAddr[PARAM_MAC_ADDR_LEN], + IN struct PARAM_SSID *prSsid, + IN uint16_t u2CapInfo, + IN int32_t rRssi, + IN enum ENUM_PARAM_NETWORK_TYPE eNetworkType, + IN struct PARAM_802_11_CONFIG *prConfiguration, + IN enum ENUM_PARAM_OP_MODE eOpMode, + IN uint8_t rSupportedRates[PARAM_MAX_LEN_RATES_EX], + IN uint16_t u2IELength, IN uint8_t *pucIEBuf) +{ + u_int8_t bReplace; + uint32_t i; + uint32_t u4IdxWeakest = 0; + int32_t rWeakestRssi; + uint32_t u4BufferSize; + /* Privicy setting 0: Open / 1: WEP/WPA/WPA2 enabled */ + uint32_t u4Privacy = u2CapInfo & CAP_INFO_PRIVACY ? 1 : 0; + + ASSERT(prAdapter); + + rWeakestRssi = (int32_t) INT_MAX; + u4BufferSize = ARRAY_SIZE( + prAdapter->rWlanInfo.aucScanIEBuf); + + bReplace = FALSE; + + /* decide to replace or add */ + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + uint8_t j; + u_int8_t bUnMatch = TRUE; + + for (j = 0; j < KAL_AIS_NUM; j++) { + struct PARAM_BSSID_EX *prCurrBssid; + + prCurrBssid = aisGetCurrBssId(prAdapter, + j); + if (EQUAL_MAC_ADDR + (prAdapter->rWlanInfo. + arScanResult[i].arMacAddress, + prCurrBssid->arMacAddress)) { + bUnMatch = FALSE; + break; + } + } + + /* find weakest entry && not connected one */ + if (bUnMatch + && 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(struct PARAM_BSSID_EX, aucIEs)); + + /* then fill buffer */ + prAdapter->rWlanInfo.arScanResult[i].u4Length = + OFFSET_OF(struct PARAM_BSSID_EX, 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(struct PARAM_802_11_CONFIG)); + prAdapter->rWlanInfo.arScanResult[i].eOpMode = eOpMode; + kalMemCopy(( + prAdapter->rWlanInfo. + arScanResult[i].rSupportedRates), + rSupportedRates, (sizeof(uint8_t) * + PARAM_MAX_LEN_RATES_EX)); + prAdapter->rWlanInfo.arScanResult[i].u4IELength = + (uint32_t) 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(struct PARAM_BSSID_EX, aucIEs)); + + /* then fill buffer */ + prAdapter->rWlanInfo.arScanResult[i].u4Length = + OFFSET_OF(struct PARAM_BSSID_EX, 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(struct PARAM_802_11_CONFIG)); + prAdapter->rWlanInfo.arScanResult[i].eOpMode = eOpMode; + kalMemCopy(( + prAdapter->rWlanInfo.arScanResult[i]. + rSupportedRates), + rSupportedRates, (sizeof(uint8_t) * + PARAM_MAX_LEN_RATES_EX)); + prAdapter->rWlanInfo.arScanResult[i].u4IELength = + (uint32_t) 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 != (int32_t) INT_MAX) { + /* replace weakest one */ + i = u4IdxWeakest; + + /* free IE buffer then zero */ + nicFreeScanResultIE(prAdapter, i); + kalMemZero(&(prAdapter->rWlanInfo.arScanResult[i]), + OFFSET_OF(struct PARAM_BSSID_EX, aucIEs)); + + /* then fill buffer */ + prAdapter->rWlanInfo.arScanResult[i].u4Length = + OFFSET_OF(struct PARAM_BSSID_EX, 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(struct PARAM_802_11_CONFIG)); + prAdapter->rWlanInfo.arScanResult[i].eOpMode = eOpMode; + kalMemCopy(( + prAdapter->rWlanInfo.arScanResult[i]. + rSupportedRates), + rSupportedRates, (sizeof(uint8_t) * + PARAM_MAX_LEN_RATES_EX)); + prAdapter->rWlanInfo.arScanResult[i].u4IELength = + (uint32_t) 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 struct ADAPTER *prAdapter, + IN uint32_t u4Idx) +{ + uint32_t i; + uint8_t *pucPivot, *pucMovePivot; + uint32_t 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 = (uint8_t *) ((unsigned long) ( + prAdapter->rWlanInfo.apucScanResultIEs[u4Idx]) + + u4FreeSize); + + u4ReserveSize = ((unsigned long) pucPivot) - + (unsigned long) (&(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] = + (uint8_t *) ((unsigned long) ( + prAdapter->rWlanInfo. + apucScanResultIEs[i]) + - u4FreeSize); + } + } + } + + /* 1.2 reset the freed one */ + prAdapter->rWlanInfo.arScanResult[u4Idx].u4IELength = 0; + prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; + + /* 2. reduce IE buffer usage */ + prAdapter->rWlanInfo.u4ScanIEBufferUsage -= u4FreeSize; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is to hack parameters for WLAN TABLE for + * fixed rate settings + * + * @param prAdapter Pointer to the Adapter structure. + * @param eRateSetting + * @param pu2DesiredNonHTRateSet, + * @param pu2BSSBasicRateSet, + * @param pucMcsSet + * @param pucSupMcs32 + * @param pu2HtCapInfo + * + * @return WLAN_STATUS_SUCCESS + */ +/*----------------------------------------------------------------------------*/ +uint32_t +nicUpdateRateParams(IN struct ADAPTER *prAdapter, + IN enum ENUM_REGISTRY_FIXED_RATE eRateSetting, + IN uint8_t *pucDesiredPhyTypeSet, + IN uint16_t *pu2DesiredNonHTRateSet, + IN uint16_t *pu2BSSBasicRateSet, + IN uint8_t *pucMcsSet, IN uint8_t *pucSupMcs32, + IN uint16_t *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 = BIT(HT_RATE_MCS0_INDEX - 1); + *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 = BIT(HT_RATE_MCS1_INDEX - 1); + *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 = BIT(HT_RATE_MCS2_INDEX - 1); + *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 = BIT(HT_RATE_MCS3_INDEX - 1); + *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 = BIT(HT_RATE_MCS4_INDEX - 1); + *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 = BIT(HT_RATE_MCS5_INDEX - 1); + *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 = BIT(HT_RATE_MCS6_INDEX - 1); + *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 = BIT(HT_RATE_MCS7_INDEX - 1); + *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 = BIT(HT_RATE_MCS0_INDEX - 1); + *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 = BIT(HT_RATE_MCS1_INDEX - 1); + *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 = BIT(HT_RATE_MCS2_INDEX - 1); + *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 = BIT(HT_RATE_MCS3_INDEX - 1); + *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 = BIT(HT_RATE_MCS4_INDEX - 1); + *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 = BIT(HT_RATE_MCS5_INDEX - 1); + *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 = BIT(HT_RATE_MCS6_INDEX - 1); + *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 = BIT(HT_RATE_MCS7_INDEX - 1); + *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 = BIT(HT_RATE_MCS0_INDEX - 1); + *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 = BIT(HT_RATE_MCS1_INDEX - 1); + *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 = BIT(HT_RATE_MCS2_INDEX - 1); + *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 = BIT(HT_RATE_MCS3_INDEX - 1); + *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 = BIT(HT_RATE_MCS4_INDEX - 1); + *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 = BIT(HT_RATE_MCS5_INDEX - 1); + *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 = BIT(HT_RATE_MCS6_INDEX - 1); + *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 = BIT(HT_RATE_MCS7_INDEX - 1); + *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 = 0; + *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 = BIT(HT_RATE_MCS0_INDEX - 1); + *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 = BIT(HT_RATE_MCS1_INDEX - 1); + *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 = BIT(HT_RATE_MCS2_INDEX - 1); + *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 = BIT(HT_RATE_MCS3_INDEX - 1); + *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 = BIT(HT_RATE_MCS4_INDEX - 1); + *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 = BIT(HT_RATE_MCS5_INDEX - 1); + *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 = BIT(HT_RATE_MCS6_INDEX - 1); + *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 = BIT(HT_RATE_MCS7_INDEX - 1); + *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 = 0; + *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 + */ +/*----------------------------------------------------------------------------*/ + +uint32_t nicWriteMcr(IN struct ADAPTER *prAdapter, + IN uint32_t u4Address, IN uint32_t u4Value) +{ + struct CMD_ACCESS_REG rCmdAccessReg; + + rCmdAccessReg.u4Address = u4Address; + rCmdAccessReg.u4Data = u4Value; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + TRUE, + FALSE, + FALSE, NULL, NULL, + sizeof(struct CMD_ACCESS_REG), + (uint8_t *) &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 + */ +/*----------------------------------------------------------------------------*/ + +uint32_t +nicRlmArUpdateParms(IN struct ADAPTER *prAdapter, + IN uint32_t u4ArSysParam0, + IN uint32_t u4ArSysParam1, IN uint32_t u4ArSysParam2, + IN uint32_t u4ArSysParam3) +{ + uint8_t ucArVer, ucAbwVer, ucAgiVer; + uint16_t u2HtClrMask; + uint16_t u2LegacyClrMask; + uint8_t ucArCheckWindow; + uint8_t ucArPerL; + uint8_t ucArPerH; + uint8_t ucArPerForceRateDownPer; + + ucArVer = (uint8_t) (u4ArSysParam0 & BITS(0, 3)); + ucAbwVer = (uint8_t) ((u4ArSysParam0 & BITS(4, 5)) >> 4); + ucAgiVer = (uint8_t) ((u4ArSysParam0 & BITS(6, 7)) >> 6); + u2HtClrMask = (uint16_t) ((u4ArSysParam0 & BITS(8, + 15)) >> 8); + u2LegacyClrMask = (uint16_t) ((u4ArSysParam0 & BITS(16, + 31)) >> 16); + +#if 0 + ucArCheckWindow = (uint8_t) (u4ArSysParam1 & BITS(0, 7)); + ucArPerH = (uint8_t) ((u4ArSysParam1 & BITS(16, 23)) >> 16); + ucArPerL = (uint8_t) ((u4ArSysParam1 & BITS(24, 31)) >> 24); +#endif + + ucArCheckWindow = (uint8_t) (u4ArSysParam1 & BITS(0, 7)); + ucArPerForceRateDownPer = (uint8_t) (((u4ArSysParam1 >> 8) & + BITS(0, 7))); + ucArPerH = (uint8_t) (((u4ArSysParam1 >> 16) & BITS(0, 7))); + ucArPerL = (uint8_t) (((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 function is called to update Link Quality information + * + * @param prAdapter Pointer of Adapter Data Structure + * ucBssIndex + * prEventLinkQuality + * cRssi + * cLinkQuality + * + * @return none + */ +/*----------------------------------------------------------------------------*/ +void nicUpdateLinkQuality(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct EVENT_LINK_QUALITY *prEventLinkQuality) +{ + int8_t cRssi; + uint16_t u2AdjustRssi = 10; + struct LINK_SPEED_EX_ *prLq; + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + ASSERT(prEventLinkQuality); + + prLq = &prAdapter->rLinkQuality.rLq[ucBssIndex]; + switch (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType) { + case NETWORK_TYPE_AIS: + if (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eConnectionState == + MEDIA_STATE_CONNECTED) { + /* check is to prevent RSSI to be updated by + * incorrect initial RSSI from hardware + */ + /* buffer statistics for further query */ + if (prLq->fgIsLinkQualityValid == FALSE || + (kalGetTimeTick() - prLq->rLinkQualityUpdateTime) > + CFG_LINK_QUALITY_VALID_PERIOD) { + /* ranged from (-128 ~ 30) in unit of dBm */ + cRssi = + prEventLinkQuality->rLq[ucBssIndex]. + cRssi; + cRssi = + (int8_t) (((int16_t) + (cRssi) * u2AdjustRssi) / 10); + DBGLOG(RLM, INFO, + "Rssi=%d, NewRssi=%d\n", + prEventLinkQuality->rLq[ucBssIndex]. + cRssi, + cRssi); + nicUpdateRSSI(prAdapter, ucBssIndex, cRssi, + prEventLinkQuality->rLq[ucBssIndex]. + cLinkQuality); + } + + if (prLq->fgIsLinkRateValid == FALSE || + (kalGetTimeTick() - prLq->rLinkRateUpdateTime) + > CFG_LINK_QUALITY_VALID_PERIOD) { + nicUpdateLinkSpeed(prAdapter, ucBssIndex, + prEventLinkQuality->rLq[ucBssIndex]. + u2LinkSpeed); + } + + } + break; + +#if 0 +/* #if CFG_ENABLE_WIFI_DIRECT && CFG_SUPPORT_P2P_RSSI_QUERY */ + case NETWORK_TYPE_P2P: + if (prAdapter->fgIsP2pLinkQualityValid == FALSE + || (kalGetTimeTick() - prAdapter->rP2pLinkQualityUpdateTime) + > CFG_LINK_QUALITY_VALID_PERIOD) { + struct EVENT_LINK_QUALITY_EX *prEventLQEx = + (struct EVENT_LINK_QUALITY_EX *) + prEventLinkQuality; + + nicUpdateRSSI(prAdapter, ucBssIndex, + prEventLQEx->cRssiP2P, + prEventLQEx->cLinkQualityP2P); + } + break; +#endif + default: + break; + + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to update RSSI and Link Quality information + * + * @param prAdapter Pointer of Adapter Data Structure + * ucBssIndex + * cRssi + * cLinkQuality + * + * @return none + */ +/*----------------------------------------------------------------------------*/ +void nicUpdateRSSI(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN int8_t cRssi, + IN int8_t cLinkQuality) +{ + ASSERT(prAdapter); + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + switch (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType) { + case NETWORK_TYPE_AIS: + if (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eConnectionState == + MEDIA_STATE_CONNECTED) { + prAdapter->rLinkQuality.rLq[ucBssIndex]. + fgIsLinkQualityValid = TRUE; + prAdapter->rLinkQuality.rLq[ucBssIndex]. + rLinkQualityUpdateTime = kalGetTimeTick(); + + prAdapter->rLinkQuality.rLq[ucBssIndex]. + cRssi = cRssi; + prAdapter->rLinkQuality.rLq[ucBssIndex]. + cLinkQuality = cLinkQuality; + /* indicate to glue layer */ + kalUpdateRSSI(prAdapter->prGlueInfo, + ucBssIndex, cRssi, cLinkQuality); + } + + break; +#if CFG_ENABLE_WIFI_DIRECT && CFG_SUPPORT_P2P_RSSI_QUERY + case NETWORK_TYPE_P2P: + prAdapter->fgIsP2pLinkQualityValid = TRUE; + prAdapter->rP2pLinkQualityUpdateTime = kalGetTimeTick(); + + prAdapter->rP2pLinkQuality.cRssi = cRssi; + prAdapter->rP2pLinkQuality.cLinkQuality = cLinkQuality; + + kalUpdateRSSI(prAdapter->prGlueInfo, + ucBssIndex, cRssi, cLinkQuality); + break; +#endif + default: + break; + + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to update Link Quality information + * + * @param prAdapter Pointer of Adapter Data Structure + * ucBssIndex + * prEventLinkQuality + * cRssi + * cLinkQuality + * + * @return none + */ +/*----------------------------------------------------------------------------*/ +void nicUpdateLinkSpeed(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN uint16_t u2LinkSpeed) +{ + ASSERT(prAdapter); + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + switch (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType) { + case NETWORK_TYPE_AIS: + if (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eConnectionState == + MEDIA_STATE_CONNECTED) { + /* buffer statistics for further query */ + prAdapter->rLinkQuality.rLq[ucBssIndex]. + fgIsLinkRateValid = TRUE; + prAdapter->rLinkQuality.rLq[ucBssIndex]. + rLinkRateUpdateTime = kalGetTimeTick(); + + prAdapter->rLinkQuality.rLq[ucBssIndex]. + u2LinkSpeed = u2LinkSpeed; + } + break; + + default: + break; + + } + +} + +#if CFG_SUPPORT_RDD_TEST_MODE +uint32_t nicUpdateRddTestMode(IN struct ADAPTER *prAdapter, + IN struct CMD_RDD_CH *prRddChParam) +{ + DEBUGFUNC("nicUpdateRddTestMode.\n"); + + ASSERT(prAdapter); + + /* aisFsmScanRequest(prAdapter, NULL); */ + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RDD_CH, + TRUE, + FALSE, FALSE, NULL, NULL, + sizeof(struct CMD_RDD_CH), + (uint8_t *) prRddChParam, NULL, 0); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to apply network address setting to + * both OS side and firmware domain + * + * @param prAdapter Pointer of Adapter Data Structure + * + * @return none + */ +/*----------------------------------------------------------------------------*/ + +uint32_t nicApplyNetworkAddress(IN struct ADAPTER + *prAdapter) +{ + uint32_t i; + + ASSERT(prAdapter); + + /* copy to adapter */ + COPY_MAC_ADDR(prAdapter->rMyMacAddr, + prAdapter->rWifiVar.aucMacAddress); + + /* 4 <3> Update new MAC address to all 3 networks */ + COPY_MAC_ADDR(prAdapter->rWifiVar.aucDeviceAddress, + prAdapter->rMyMacAddr); + prAdapter->rWifiVar.aucDeviceAddress[0] ^= + MAC_ADDR_LOCAL_ADMIN; + + for (i = 0; i < KAL_P2P_NUM; i++) { + COPY_MAC_ADDR(prAdapter->rWifiVar.aucInterfaceAddress[i], + prAdapter->rMyMacAddr); + prAdapter->rWifiVar.aucInterfaceAddress[i][0] |= 0x2; + prAdapter->rWifiVar.aucInterfaceAddress[i][0] ^= + i << MAC_ADDR_LOCAL_ADMIN; + } + +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + if (prAdapter->rWifiVar.arBssInfoPool[i].eNetworkType == + NETWORK_TYPE_P2P) { + COPY_MAC_ADDR( + prAdapter->rWifiVar.arBssInfoPool[i]. + aucOwnMacAddr, + prAdapter->rWifiVar.aucDeviceAddress); + } + } + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + if (prAdapter->rWifiVar.arBssInfoPool[i].eNetworkType == + NETWORK_TYPE_BOW) { + COPY_MAC_ADDR( + prAdapter->rWifiVar.arBssInfoPool[i]. + 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); + + if (KAL_AIS_NUM > 1) { + /* Generate from wlan0 MAC */ + COPY_MAC_ADDR(prAdapter->rWifiVar.aucMacAddress1, + prAdapter->rWifiVar.aucMacAddress); + /* Update wlan1 address */ + prAdapter->rWifiVar.aucMacAddress1[3] ^= BIT(1); + } + + return WLAN_STATUS_SUCCESS; +} + +#if 1 +uint8_t nicGetChipHwVer(void) +{ + return g_eco_info.ucHwVer; +} + +uint8_t nicGetChipSwVer(void) +{ + return g_eco_info.ucRomVer; +} + +uint8_t nicGetChipFactoryVer(void) +{ + return g_eco_info.ucFactoryVer; +} + +uint8_t nicSetChipHwVer(uint8_t value) +{ + g_eco_info.ucHwVer = value; + return 0; +} + +uint8_t nicSetChipSwVer(uint8_t value) +{ + g_eco_info.ucRomVer = value; + return 0; +} + +uint8_t nicSetChipFactoryVer(uint8_t value) +{ + g_eco_info.ucFactoryVer = value; + return 0; +} + +#else +uint8_t nicGetChipHwVer(void) +{ + return mtk_wcn_wmt_ic_info_get(WMTCHIN_HWVER) & BITS(0, 7); +} + +uint8_t nicGetChipSwVer(void) +{ + return mtk_wcn_wmt_ic_info_get(WMTCHIN_FWVER) & BITS(0, 7); +} + +uint8_t nicGetChipFactoryVer(void) +{ + return (mtk_wcn_wmt_ic_info_get(WMTCHIN_FWVER) & BITS(8, + 11)) >> 8; +} +#endif + +uint8_t nicGetChipEcoVer(IN struct ADAPTER *prAdapter) +{ + struct ECO_INFO *prEcoInfo; + uint8_t ucEcoVer; + uint8_t ucCurSwVer, ucCurHwVer, ucCurFactoryVer; + + ucCurSwVer = nicGetChipSwVer(); + ucCurHwVer = nicGetChipHwVer(); + ucCurFactoryVer = nicGetChipFactoryVer(); + + ucEcoVer = 0; + + while (TRUE) { + /* Get ECO info from table */ + prEcoInfo = (struct ECO_INFO *) & + (prAdapter->chip_info->eco_info[ucEcoVer]); + + if ((prEcoInfo->ucRomVer == 0) && + (prEcoInfo->ucHwVer == 0) && + (prEcoInfo->ucFactoryVer == 0)) { + + /* last ECO info */ + if (ucEcoVer > 0) + ucEcoVer--; + + /* End of table */ + break; + } + + if ((prEcoInfo->ucRomVer == ucCurSwVer) && + (prEcoInfo->ucHwVer == ucCurHwVer) && + (prEcoInfo->ucFactoryVer == ucCurFactoryVer)) { + break; + } + + ucEcoVer++; + } + +#if 0 + DBGLOG(INIT, INFO, + "Cannot get ECO version for SwVer[0x%02x]HwVer[0x%02x]FactoryVer[0x%1x],recognize as latest version[E%u]\n", + ucCurSwVer, ucCurHwVer, ucCurFactoryVer, + prAdapter->chip_info->eco_info[ucEcoVer].ucEcoVer); +#endif + return prAdapter->chip_info->eco_info[ucEcoVer].ucEcoVer; +} + +u_int8_t nicIsEcoVerEqualTo(IN struct ADAPTER *prAdapter, + uint8_t ucEcoVer) +{ + if (ucEcoVer == prAdapter->chip_info->eco_ver) + return TRUE; + else + return FALSE; +} + +u_int8_t nicIsEcoVerEqualOrLaterTo(IN struct ADAPTER + *prAdapter, uint8_t ucEcoVer) +{ + if (ucEcoVer <= prAdapter->chip_info->eco_ver) + return TRUE; + else + return FALSE; +} + +void nicSerStopTxRx(IN struct ADAPTER *prAdapter) +{ +#if defined(_HIF_USB) + unsigned long ulFlags; + + /*TODO: multiple spinlocks seems risky. + * http://www.linuxgrill.com/anonymous/fire/netfilter/ + * kernel-hacking-HOWTO-5.html + */ + /* 1. Make sure ucSerState is accessed sequentially. + * 2. Two scenario for race condition: + * - When hif_thread is doing usb_submit_urb, SER occurs. + * hif_thread acquires the lock first, + * so nicSerSyncTimerHandler must wait hif_thread + * until it completes current usb_submit_urb. + * Then, nicSerSyncTimerHandler acquires the lock, + * change ucSerState to prevent subsequent usb_submit_urb and + * cancel ALL TX BULK OUT URB. + * - When SER is triggered and executed, + * hif_thread is prepared to do usb_submit_urb. + * nicSerSyncTimerHandler acquires the lock first, + * which guarantees ucSerState is accessed sequentially. + * Then, hif_thread acquires the lock, knows that SER is ongoing, + * and bypass usb_submit_urb. + */ + spin_lock_irqsave(&prAdapter->prGlueInfo->rHifInfo.rStateLock, + ulFlags); +#endif + + DBGLOG(NIC, WARN, "SER: Stop HIF Tx/Rx!\n"); + + prAdapter->ucSerState = SER_STOP_HOST_TX_RX; + + /* Force own to FW as ACK and stop HIF */ + prAdapter->fgWiFiInSleepyState = TRUE; + +#if defined(_HIF_USB) + spin_unlock_irqrestore(&prAdapter->prGlueInfo->rHifInfo.rStateLock, + ulFlags); +#endif + +} + +void nicSerStopTx(IN struct ADAPTER *prAdapter) +{ + DBGLOG(NIC, WARN, "SER: Stop HIF Tx!\n"); + + prAdapter->ucSerState = SER_STOP_HOST_TX; +} + +void nicSerStartTxRx(IN struct ADAPTER *prAdapter) +{ + DBGLOG(NIC, WARN, "SER: Start HIF T/R!\n"); + + prAdapter->ucSerState = SER_IDLE_DONE; +} + +u_int8_t nicSerIsWaitingReset(IN struct ADAPTER *prAdapter) +{ + if (prAdapter->ucSerState == SER_STOP_HOST_TX_RX) + return TRUE; + else + return FALSE; +} + +u_int8_t nicSerIsTxStop(IN struct ADAPTER *prAdapter) +{ + switch (prAdapter->ucSerState) { + case SER_STOP_HOST_TX: + case SER_STOP_HOST_TX_RX: + case SER_REINIT_HIF: + return TRUE; + + case SER_IDLE_DONE: + default: + return FALSE; + } +} + +u_int8_t nicSerIsRxStop(IN struct ADAPTER *prAdapter) +{ + switch (prAdapter->ucSerState) { + case SER_STOP_HOST_TX_RX: + case SER_REINIT_HIF: + return TRUE; + + case SER_STOP_HOST_TX: + case SER_IDLE_DONE: + default: + return FALSE; + } +} + +void nicSerReInitBeaconFrame(IN struct ADAPTER *prAdapter) +{ + struct P2P_ROLE_FSM_INFO *prRoleP2pFsmInfo; + + prRoleP2pFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + 0); + if (prRoleP2pFsmInfo != NULL) { + bssUpdateBeaconContent(prAdapter, + prRoleP2pFsmInfo->ucBssIndex); + DBGLOG(NIC, INFO, "SER beacon frame is updated\n"); + } +} + +#if defined(_HIF_USB) +void nicSerTimerHandler(IN struct ADAPTER *prAdapter, + IN unsigned long plParamPtr) +{ + halSerSyncTimerHandler(prAdapter); + cnmTimerStartTimer(prAdapter, + &rSerSyncTimer, + WIFI_SER_SYNC_TIMER_TIMEOUT_IN_MS); +} +#endif + +void nicSerInit(IN struct ADAPTER *prAdapter) +{ +#if defined(_HIF_USB) + /* check SER is supported or not */ + if (prAdapter->rWifiVar.fgEnableSer == TRUE && + prAdapter->chip_info->u4SerUsbMcuEventAddr != 0) { + cnmTimerInitTimer(prAdapter, + &rSerSyncTimer, + (PFN_MGMT_TIMEOUT_FUNC) nicSerTimerHandler, + (unsigned long) NULL); + cnmTimerStartTimer(prAdapter, + &rSerSyncTimer, + WIFI_SER_SYNC_TIMER_TIMEOUT_IN_MS); + } +#endif + /* if ser is not enabled, disable this feature in FW */ + if (prAdapter->rWifiVar.fgEnableSer == FALSE +#if defined(_HIF_USB) + || prAdapter->chip_info->u4SerUsbMcuEventAddr == 0 +#endif + ) { + wlanoidSerExtCmd(prAdapter, SER_ACTION_SET, + SER_SET_DISABLE, 0); + } + +} + +void nicSerDeInit(IN struct ADAPTER *prAdapter) +{ +#if defined(_HIF_USB) + cnmTimerStopTimer(prAdapter, &rSerSyncTimer); +#endif +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_cmd_event.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_cmd_event.c new file mode 100644 index 0000000000000..c450d78fa917d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_cmd_event.c @@ -0,0 +1,5459 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/ + * MT6620_WIFI_DRIVER_V2_3/nic/nic_cmd_event.c#3 + */ + +/*! \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. + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" +#include "gl_ate_agent.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +const struct NIC_CAPABILITY_V2_REF_TABLE + gNicCapabilityV2InfoTable[] = { +#if defined(_HIF_SDIO) + {TAG_CAP_TX_RESOURCE, nicEventQueryTxResourceEntry}, +#endif + {TAG_CAP_TX_EFUSEADDRESS, nicCmdEventQueryNicEfuseAddr}, + {TAG_CAP_COEX_FEATURE, nicCmdEventQueryNicCoexFeature}, + {TAG_CAP_SINGLE_SKU, rlmDomainExtractSingleSkuInfoFromFirmware}, +#if CFG_TCP_IP_CHKSUM_OFFLOAD + {TAG_CAP_CSUM_OFFLOAD, nicCmdEventQueryNicCsumOffload}, +#endif + {TAG_CAP_HW_VERSION, nicCfgChipCapHwVersion}, + {TAG_CAP_SW_VERSION, nicCfgChipCapSwVersion}, + {TAG_CAP_MAC_ADDR, nicCfgChipCapMacAddr}, + {TAG_CAP_PHY_CAP, nicCfgChipCapPhyCap}, + {TAG_CAP_MAC_CAP, nicCfgChipCapMacCap}, + {TAG_CAP_FRAME_BUF_CAP, nicCfgChipCapFrameBufCap}, + {TAG_CAP_BEAMFORM_CAP, nicCfgChipCapBeamformCap}, + {TAG_CAP_LOCATION_CAP, nicCfgChipCapLocationCap}, + {TAG_CAP_MUMIMO_CAP, nicCfgChipCapMuMimoCap}, + {TAG_CAP_HW_ADIE_VERSION, nicCfgChipAdieHwVersion}, +#if CFG_SUPPORT_ANT_SWAP + {TAG_CAP_ANTSWP, nicCfgChipCapAntSwpCap}, +#endif +#if (CFG_SUPPORT_P2PGO_ACS == 1) + {TAG_CAP_P2P, nicCfgChipP2PCap}, +#endif + {TAG_CAP_HOST_STATUS_EMI_OFFSET, nicCmdEventHostStatusEmiOffset}, + +}; + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +struct MIB_INFO_STAT g_arMibInfo[ENUM_BAND_NUM]; +uint8_t fgEfuseCtrlAxOn = 1; /* run time control if support AX by efuse */ + + +/******************************************************************************* + * F U N C T I O N D A T A + ******************************************************************************* + */ +void nicCmdEventQueryMcrRead(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct PARAM_CUSTOM_MCR_RW_STRUCT *prMcrRdInfo; + struct GLUE_INFO *prGlueInfo; + struct CMD_ACCESS_REG *prCmdAccessReg; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prCmdAccessReg = (struct CMD_ACCESS_REG *) (pucEventBuf); + + u4QueryInfoLen = sizeof(struct PARAM_CUSTOM_MCR_RW_STRUCT); + + prMcrRdInfo = (struct PARAM_CUSTOM_MCR_RW_STRUCT *) + prCmdInfo->pvInformationBuffer; + prMcrRdInfo->u4McrOffset = prCmdAccessReg->u4Address; + prMcrRdInfo->u4McrData = prCmdAccessReg->u4Data; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + + return; + +} + +void nicCmdEventQueryCfgRead(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct CMD_HEADER *prInCfgHeader; + struct GLUE_INFO *prGlueInfo; + struct CMD_HEADER *prOutCfgHeader; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prInCfgHeader = (struct CMD_HEADER *) (pucEventBuf); + u4QueryInfoLen = sizeof(struct CMD_HEADER); + prOutCfgHeader = (struct CMD_HEADER *) + (prCmdInfo->pvInformationBuffer); + + kalMemCopy(prOutCfgHeader, prInCfgHeader, + sizeof(struct CMD_HEADER)); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +#if CFG_SUPPORT_QA_TOOL +void nicCmdEventQueryRxStatistics(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + struct PARAM_CUSTOM_ACCESS_RX_STAT *prRxStatistics; + struct EVENT_ACCESS_RX_STAT *prEventAccessRxStat; + uint32_t u4QueryInfoLen, i; + struct GLUE_INFO *prGlueInfo; + uint32_t *prElement; + uint32_t u4Temp; + /* P_CMD_ACCESS_RX_STAT prCmdRxStat, prRxStat; */ + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventAccessRxStat = (struct EVENT_ACCESS_RX_STAT *) ( + pucEventBuf); + + prRxStatistics = (struct PARAM_CUSTOM_ACCESS_RX_STAT *) + prCmdInfo->pvInformationBuffer; + prRxStatistics->u4SeqNum = prEventAccessRxStat->u4SeqNum; + prRxStatistics->u4TotalNum = + prEventAccessRxStat->u4TotalNum; + + u4QueryInfoLen = sizeof(struct CMD_ACCESS_RX_STAT); + + if (prRxStatistics->u4SeqNum == u4RxStatSeqNum) { + prElement = &g_HqaRxStat.MAC_FCS_Err; + for (i = 0; i < HQA_RX_STATISTIC_NUM; i++) { + u4Temp = ntohl( + prEventAccessRxStat->au4Buffer[i]); + kalMemCopy(prElement, &u4Temp, 4); + + if (i < (HQA_RX_STATISTIC_NUM - 1)) + prElement++; + } + + g_HqaRxStat.AllMacMdrdy0 = ntohl( + prEventAccessRxStat->au4Buffer[i]); + i++; + g_HqaRxStat.AllMacMdrdy1 = ntohl( + prEventAccessRxStat->au4Buffer[i]); + /* i++; */ + /* g_HqaRxStat.AllFCSErr0 = + * ntohl(prEventAccessRxStat->au4Buffer[i]); + */ + /* i++; */ + /* g_HqaRxStat.AllFCSErr1 = + * ntohl(prEventAccessRxStat->au4Buffer[i]); + */ + } + + DBGLOG(INIT, ERROR, + "MT6632 : RX Statistics Test SeqNum = %d, TotalNum = %d\n", + (unsigned int)prEventAccessRxStat->u4SeqNum, + (unsigned int)prEventAccessRxStat->u4TotalNum); + + DBGLOG(INIT, ERROR, + "MAC_FCS_ERR = %d, MAC_MDRDY = %d, MU_RX_CNT = %d, RX_FIFO_FULL = %d\n", + (unsigned int)prEventAccessRxStat->au4Buffer[0], + (unsigned int)prEventAccessRxStat->au4Buffer[1], + (unsigned int)prEventAccessRxStat->au4Buffer[65], + (unsigned int)prEventAccessRxStat->au4Buffer[22]); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} + +#if CFG_SUPPORT_TX_BF +void nicCmdEventPfmuDataRead(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct GLUE_INFO *prGlueInfo; + union PFMU_DATA *prEventPfmuDataRead = NULL; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventPfmuDataRead = (union PFMU_DATA *) (pucEventBuf); + + u4QueryInfoLen = sizeof(union PFMU_DATA); + + g_rPfmuData = *prEventPfmuDataRead; + } + + DBGLOG(INIT, INFO, "=========== Before ===========\n"); + if (prEventPfmuDataRead != NULL) { + DBGLOG(INIT, INFO, "u2Phi11 = 0x%x\n", + prEventPfmuDataRead->rField.u2Phi11); + DBGLOG(INIT, INFO, "ucPsi21 = 0x%x\n", + prEventPfmuDataRead->rField.ucPsi21); + DBGLOG(INIT, INFO, "u2Phi21 = 0x%x\n", + prEventPfmuDataRead->rField.u2Phi21); + DBGLOG(INIT, INFO, "ucPsi31 = 0x%x\n", + prEventPfmuDataRead->rField.ucPsi31); + DBGLOG(INIT, INFO, "u2Phi31 = 0x%x\n", + prEventPfmuDataRead->rField.u2Phi31); + DBGLOG(INIT, INFO, "ucPsi41 = 0x%x\n", + prEventPfmuDataRead->rField.ucPsi41); + DBGLOG(INIT, INFO, "u2Phi22 = 0x%x\n", + prEventPfmuDataRead->rField.u2Phi22); + DBGLOG(INIT, INFO, "ucPsi32 = 0x%x\n", + prEventPfmuDataRead->rField.ucPsi32); + DBGLOG(INIT, INFO, "u2Phi32 = 0x%x\n", + prEventPfmuDataRead->rField.u2Phi32); + DBGLOG(INIT, INFO, "ucPsi42 = 0x%x\n", + prEventPfmuDataRead->rField.ucPsi42); + DBGLOG(INIT, INFO, "u2Phi33 = 0x%x\n", + prEventPfmuDataRead->rField.u2Phi33); + DBGLOG(INIT, INFO, "ucPsi43 = 0x%x\n", + prEventPfmuDataRead->rField.ucPsi43); + DBGLOG(INIT, INFO, "u2dSNR00 = 0x%x\n", + prEventPfmuDataRead->rField.u2dSNR00); + DBGLOG(INIT, INFO, "u2dSNR01 = 0x%x\n", + prEventPfmuDataRead->rField.u2dSNR01); + DBGLOG(INIT, INFO, "u2dSNR02 = 0x%x\n", + prEventPfmuDataRead->rField.u2dSNR02); + DBGLOG(INIT, INFO, "u2dSNR03 = 0x%x\n", + prEventPfmuDataRead->rField.u2dSNR03); + } +} + +void nicCmdEventPfmuTagRead(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct GLUE_INFO *prGlueInfo; + struct EVENT_PFMU_TAG_READ *prEventPfmuTagRead = NULL; + struct PARAM_CUSTOM_PFMU_TAG_READ_STRUCT *prPfumTagRead = + NULL; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + if (!pucEventBuf) { + DBGLOG(INIT, ERROR, "pucEventBuf is NULL.\n"); + return; + } + if (!prCmdInfo->pvInformationBuffer) { + DBGLOG(INIT, ERROR, + "prCmdInfo->pvInformationBuffer is NULL.\n"); + return; + } + /* 4 <2> Update information of OID */ + if (!prCmdInfo->fgIsOid) { + DBGLOG(INIT, ERROR, "cmd %u seq #%u not oid!", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + return; + } + prGlueInfo = prAdapter->prGlueInfo; + prEventPfmuTagRead = (struct EVENT_PFMU_TAG_READ *) ( + pucEventBuf); + + prPfumTagRead = (struct PARAM_CUSTOM_PFMU_TAG_READ_STRUCT *) + prCmdInfo->pvInformationBuffer; + + kalMemCopy(prPfumTagRead, prEventPfmuTagRead, + sizeof(struct EVENT_PFMU_TAG_READ)); + + u4QueryInfoLen = sizeof(union CMD_TXBF_ACTION); + + g_rPfmuTag1 = prPfumTagRead->ru4TxBfPFMUTag1; + g_rPfmuTag2 = prPfumTagRead->ru4TxBfPFMUTag2; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + + DBGLOG(INIT, INFO, + "========================== (R)Tag1 info ==========================\n"); + + DBGLOG(INIT, INFO, + " Row data0 : %x, Row data1 : %x, Row data2 : %x, Row data3 : %x\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.au4RawData[0], + prEventPfmuTagRead->ru4TxBfPFMUTag1.au4RawData[1], + prEventPfmuTagRead->ru4TxBfPFMUTag1.au4RawData[2], + prEventPfmuTagRead->ru4TxBfPFMUTag1.au4RawData[3]); + DBGLOG(INIT, INFO, "ProfileID = %d Invalid status = %d\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucProfileID, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucInvalidProf); + DBGLOG(INIT, INFO, "0:iBF / 1:eBF = %d\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucTxBf); + DBGLOG(INIT, INFO, "0:SU / 1:MU = %d\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucSU_MU); + DBGLOG(INIT, INFO, "DBW(0/1/2/3 BW20/40/80/160NC) = %d\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucDBW); + DBGLOG(INIT, INFO, "RMSD = %d\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucRMSD); + DBGLOG(INIT, INFO, + "Nrow = %d, Ncol = %d, Ng = %d, LM = %d\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucNrow, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucNcol, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucNgroup, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucLM); + DBGLOG(INIT, INFO, + "Mem1(%d, %d), Mem2(%d, %d), Mem3(%d, %d), Mem4(%d, %d)\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr1ColIdx, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr1RowIdx, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr2ColIdx, + (prEventPfmuTagRead->ru4TxBfPFMUTag1. + rField.ucMemAddr2RowIdx | + (prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr2RowIdxMsb + << 5)), + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr3ColIdx, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr3RowIdx, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr4ColIdx, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr4RowIdx); + DBGLOG(INIT, INFO, + "SNR STS0=0x%x, SNR STS1=0x%x, SNR STS2=0x%x, SNR STS3=0x%x\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucSNR_STS0, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucSNR_STS1, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucSNR_STS2, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucSNR_STS3); + DBGLOG(INIT, INFO, + "===============================================================\n"); + + DBGLOG(INIT, INFO, + "========================== (R)Tag2 info ==========================\n"); + DBGLOG(INIT, INFO, + " Row data0 : %x, Row data1 : %x, Row data2 : %x\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.au4RawData[0], + prEventPfmuTagRead->ru4TxBfPFMUTag2.au4RawData[1], + prEventPfmuTagRead->ru4TxBfPFMUTag2.au4RawData[2]); + DBGLOG(INIT, INFO, "Smart Ant Cfg = %d\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.u2SmartAnt); + DBGLOG(INIT, INFO, "SE index = %d\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucSEIdx); + DBGLOG(INIT, INFO, "RMSD Threshold = %d\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucRMSDThd); + DBGLOG(INIT, INFO, + "MCS TH L1SS = %d, S1SS = %d, L2SS = %d, S2SS = %d\n" + "L3SS = %d, S3SS = %d\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucMCSThL1SS, + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucMCSThS1SS, + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucMCSThL2SS, + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucMCSThS2SS, + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucMCSThL3SS, + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucMCSThS3SS); + DBGLOG(INIT, INFO, "iBF lifetime limit(unit:4ms) = 0x%x\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.uciBfTimeOut); + DBGLOG(INIT, INFO, + "iBF desired DBW = %d\n 0/1/2/3 : BW20/40/80/160NC\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.uciBfDBW); + DBGLOG(INIT, INFO, + "iBF desired Ncol = %d\n 0/1/2 : Ncol = 1 ~ 3\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.uciBfNcol); + DBGLOG(INIT, INFO, + "iBF desired Nrow = %d\n 0/1/2/3 : Nrow = 1 ~ 4\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.uciBfNrow); + DBGLOG(INIT, INFO, + "===============================================================\n"); + +} + +#endif /* CFG_SUPPORT_TX_BF */ +#if CFG_SUPPORT_MU_MIMO +void nicCmdEventGetQd(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct GLUE_INFO *prGlueInfo; + struct EVENT_HQA_GET_QD *prEventHqaGetQd; + uint32_t i; + + struct PARAM_CUSTOM_GET_QD_STRUCT *prGetQd = NULL; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + if (!pucEventBuf) { + DBGLOG(INIT, ERROR, "pucEventBuf is NULL.\n"); + return; + } + if (!prCmdInfo->pvInformationBuffer) { + DBGLOG(INIT, ERROR, + "prCmdInfo->pvInformationBuffer is NULL.\n"); + return; + } + /* 4 <2> Update information of OID */ + if (!prCmdInfo->fgIsOid) { + DBGLOG(INIT, ERROR, "cmd %u seq #%u not oid!\n", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + return; + } + prGlueInfo = prAdapter->prGlueInfo; + prEventHqaGetQd = (struct EVENT_HQA_GET_QD *) (pucEventBuf); + + prGetQd = (struct PARAM_CUSTOM_GET_QD_STRUCT *) + prCmdInfo->pvInformationBuffer; + + kalMemCopy(prGetQd, prEventHqaGetQd, + sizeof(struct EVENT_HQA_GET_QD)); + + u4QueryInfoLen = sizeof(union CMD_MUMIMO_ACTION); + + /* g_rPfmuTag1 = prPfumTagRead->ru4TxBfPFMUTag1; */ + /* g_rPfmuTag2 = prPfumTagRead->ru4TxBfPFMUTag2; */ + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + + DBGLOG(INIT, INFO, " event id : %x\n", prGetQd->u4EventId); + for (i = 0; i < 14; i++) + DBGLOG(INIT, INFO, "au4RawData[%d]: %x\n", i, + prGetQd->au4RawData[i]); + +} + +void nicCmdEventGetCalcLq(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct GLUE_INFO *prGlueInfo; + struct EVENT_HQA_GET_MU_CALC_LQ *prEventHqaGetMuCalcLq; + uint32_t i, j; + + struct PARAM_CUSTOM_GET_MU_CALC_LQ_STRUCT *prGetMuCalcLq = + NULL; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + if (!pucEventBuf) { + DBGLOG(INIT, ERROR, "pucEventBuf is NULL.\n"); + return; + } + if (!prCmdInfo->pvInformationBuffer) { + DBGLOG(INIT, ERROR, + "prCmdInfo->pvInformationBuffer is NULL.\n"); + return; + } + /* 4 <2> Update information of OID */ + if (!prCmdInfo->fgIsOid) { + DBGLOG(INIT, ERROR, "cmd %u seq #%u not oid!\n", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + return; + } + prGlueInfo = prAdapter->prGlueInfo; + prEventHqaGetMuCalcLq = (struct EVENT_HQA_GET_MU_CALC_LQ *) + (pucEventBuf); + + prGetMuCalcLq = (struct PARAM_CUSTOM_GET_MU_CALC_LQ_STRUCT + *) prCmdInfo->pvInformationBuffer; + + kalMemCopy(prGetMuCalcLq, prEventHqaGetMuCalcLq, + sizeof(struct EVENT_HQA_GET_MU_CALC_LQ)); + + u4QueryInfoLen = sizeof(union CMD_MUMIMO_ACTION); + + /* g_rPfmuTag1 = prPfumTagRead->ru4TxBfPFMUTag1; */ + /* g_rPfmuTag2 = prPfumTagRead->ru4TxBfPFMUTag2; */ + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + + + DBGLOG(INIT, INFO, " event id : %x\n", + prGetMuCalcLq->u4EventId); + for (i = 0; i < NUM_OF_USER; i++) + for (j = 0; j < NUM_OF_MODUL; j++) + DBGLOG(INIT, INFO, " lq_report[%d][%d]: %x\n", i, j, + prGetMuCalcLq->rEntry.lq_report[i][j]); + +} + +void nicCmdEventGetCalcInitMcs(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct GLUE_INFO *prGlueInfo; + struct EVENT_SHOW_GROUP_TBL_ENTRY *prEventShowGroupTblEntry + = NULL; + + struct PARAM_CUSTOM_SHOW_GROUP_TBL_ENTRY_STRUCT + *prShowGroupTbl; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + if (!pucEventBuf) { + DBGLOG(INIT, ERROR, "pucEventBuf is NULL.\n"); + return; + } + if (!prCmdInfo->pvInformationBuffer) { + DBGLOG(INIT, ERROR, + "prCmdInfo->pvInformationBuffer is NULL.\n"); + return; + } + /* 4 <2> Update information of OID */ + if (!prCmdInfo->fgIsOid) { + DBGLOG(INIT, ERROR, "cmd %u seq #%u not oid!\n", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + return; + } + prGlueInfo = prAdapter->prGlueInfo; + prEventShowGroupTblEntry = (struct + EVENT_SHOW_GROUP_TBL_ENTRY *) (pucEventBuf); + + prShowGroupTbl = (struct + PARAM_CUSTOM_SHOW_GROUP_TBL_ENTRY_STRUCT *) + prCmdInfo->pvInformationBuffer; + + kalMemCopy(prShowGroupTbl, prEventShowGroupTblEntry, + sizeof(struct EVENT_SHOW_GROUP_TBL_ENTRY)); + + u4QueryInfoLen = sizeof(union CMD_MUMIMO_ACTION); + + /* g_rPfmuTag1 = prPfumTagRead->ru4TxBfPFMUTag1; */ + /* g_rPfmuTag2 = prPfumTagRead->ru4TxBfPFMUTag2; */ + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + + + DBGLOG(INIT, INFO, + "========================== (R)Group table info ==========================\n"); + DBGLOG(INIT, INFO, " event id : %x\n", + prEventShowGroupTblEntry->u4EventId); + DBGLOG(INIT, INFO, "index = %x numUser = %x\n", + prEventShowGroupTblEntry->index, + prEventShowGroupTblEntry->numUser); + DBGLOG(INIT, INFO, "BW = %x NS0/1/ = %x/%x\n", + prEventShowGroupTblEntry->BW, prEventShowGroupTblEntry->NS0, + prEventShowGroupTblEntry->NS1); + DBGLOG(INIT, INFO, "PFIDUser0/1 = %x/%x\n", + prEventShowGroupTblEntry->PFIDUser0, + prEventShowGroupTblEntry->PFIDUser1); + DBGLOG(INIT, INFO, + "fgIsShortGI = %x, fgIsUsed = %x, fgIsDisable = %x\n", + prEventShowGroupTblEntry->fgIsShortGI, + prEventShowGroupTblEntry->fgIsUsed, + prEventShowGroupTblEntry->fgIsDisable); + DBGLOG(INIT, INFO, "initMcsUser0/1 = %x/%x\n", + prEventShowGroupTblEntry->initMcsUser0, + prEventShowGroupTblEntry->initMcsUser1); + DBGLOG(INIT, INFO, "dMcsUser0: 0/1/ = %x/%x\n", + prEventShowGroupTblEntry->dMcsUser0, + prEventShowGroupTblEntry->dMcsUser1); + +} +#endif /* CFG_SUPPORT_MU_MIMO */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +void nicCmdEventQuerySwCtrlRead(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct PARAM_CUSTOM_SW_CTRL_STRUCT *prSwCtrlInfo; + struct GLUE_INFO *prGlueInfo; + struct CMD_SW_DBG_CTRL *prCmdSwCtrl; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prCmdSwCtrl = (struct CMD_SW_DBG_CTRL *) (pucEventBuf); + + u4QueryInfoLen = sizeof(struct PARAM_CUSTOM_SW_CTRL_STRUCT); + + prSwCtrlInfo = (struct PARAM_CUSTOM_SW_CTRL_STRUCT *) + prCmdInfo->pvInformationBuffer; + prSwCtrlInfo->u4Id = prCmdSwCtrl->u4Id; + prSwCtrlInfo->u4Data = prCmdSwCtrl->u4Data; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} + +void nicCmdEventQueryChipConfig(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct PARAM_CUSTOM_CHIP_CONFIG_STRUCT *prChipConfigInfo; + struct GLUE_INFO *prGlueInfo; + struct CMD_CHIP_CONFIG *prCmdChipConfig; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prCmdChipConfig = (struct CMD_CHIP_CONFIG *) (pucEventBuf); + + u4QueryInfoLen = sizeof(struct + PARAM_CUSTOM_CHIP_CONFIG_STRUCT); + + if (prCmdInfo->u4InformationBufferLength < sizeof( + struct PARAM_CUSTOM_CHIP_CONFIG_STRUCT)) { + DBGLOG(REQ, INFO, + "Chip config u4InformationBufferLength %u is not valid (event)\n", + prCmdInfo->u4InformationBufferLength); + } + prChipConfigInfo = (struct PARAM_CUSTOM_CHIP_CONFIG_STRUCT + *) prCmdInfo->pvInformationBuffer; + prChipConfigInfo->ucRespType = prCmdChipConfig->ucRespType; + prChipConfigInfo->u2MsgSize = prCmdChipConfig->u2MsgSize; + DBGLOG(REQ, INFO, "%s: RespTyep %u\n", __func__, + prChipConfigInfo->ucRespType); + DBGLOG(REQ, INFO, "%s: u2MsgSize %u\n", __func__, + prChipConfigInfo->u2MsgSize); + +#if 0 + if (prChipConfigInfo->u2MsgSize > CHIP_CONFIG_RESP_SIZE) { + DBGLOG(REQ, INFO, + "Chip config Msg Size %u is not valid (event)\n", + prChipConfigInfo->u2MsgSize); + prChipConfigInfo->u2MsgSize = CHIP_CONFIG_RESP_SIZE; + } +#endif + kalMemCopy(prChipConfigInfo->aucCmd, + prCmdChipConfig->aucCmd, prChipConfigInfo->u2MsgSize); + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} + +void nicCmdEventSetCommon(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, + prCmdInfo->u4InformationBufferLength, WLAN_STATUS_SUCCESS); + } + +} + +void nicCmdEventSetIpAddress(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + uint32_t u4Count; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + u4Count = (prCmdInfo->u4SetInfoLen - OFFSET_OF( + struct CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress)) + / sizeof(struct CMD_IPV4_NETWORK_ADDRESS); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + OFFSET_OF(struct PARAM_NETWORK_ADDRESS_LIST, + arAddress) + u4Count * + (OFFSET_OF(struct PARAM_NETWORK_ADDRESS, aucAddress) + + sizeof(struct PARAM_NETWORK_ADDRESS_IP)), + WLAN_STATUS_SUCCESS); + } + +} + +void nicCmdEventQueryRfTestATInfo(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + union EVENT_TEST_STATUS *prTestStatus, *prQueryBuffer; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prTestStatus = (union EVENT_TEST_STATUS *) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prQueryBuffer = (union EVENT_TEST_STATUS *) + prCmdInfo->pvInformationBuffer; + + /* Memory copy length is depended on upper-layer */ + kalMemCopy(prQueryBuffer, prTestStatus, + prCmdInfo->u4InformationBufferLength); + + u4QueryInfoLen = sizeof(union EVENT_TEST_STATUS); + + /* Update Query Information Length */ + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} + +void nicCmdEventQueryLinkQuality(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + struct EVENT_LINK_QUALITY *prLinkQuality; + struct PARAM_LINK_SPEED_EX *prLinkSpeed; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; + uint32_t i; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prLinkQuality = (struct EVENT_LINK_QUALITY *) pucEventBuf; + prLinkSpeed = (struct PARAM_LINK_SPEED_EX *) + prCmdInfo->pvInformationBuffer; + + for (i = 0; i < BSSID_NUM; i++) { + prLinkSpeed->rLq[i].u2LinkSpeed + = prLinkQuality->rLq[i].u2LinkSpeed * 5000; + + /* ranged from (-128 ~ 30) in unit of dBm */ + prLinkSpeed->rLq[i].cRssi + = prLinkQuality->rLq[i].cRssi; + + DBGLOG(REQ, TRACE, + "ucBssIdx = %d, rate = %u, signal = %d\n", + i, prLinkSpeed->rLq[i].u2LinkSpeed, + prLinkSpeed->rLq[i].cRssi); + } + u4QueryInfoLen = sizeof(struct PARAM_LINK_SPEED_EX); + + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + 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 struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct LINK_QUALITY *prLinkQuality; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; + uint32_t *pu4LinkSpeed; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prLinkQuality = (struct LINK_QUALITY *) pucEventBuf; + + prGlueInfo = prAdapter->prGlueInfo; + pu4LinkSpeed = (uint32_t *) (prCmdInfo->pvInformationBuffer); + *pu4LinkSpeed = prLinkQuality->u2LinkSpeed * 5000; + + u4QueryInfoLen = sizeof(uint32_t); + + if (prCmdInfo->fgIsOid) + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); +} + +void nicCmdEventQueryLinkSpeedEx(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct EVENT_LINK_QUALITY *prLinkQuality; + struct PARAM_LINK_SPEED_EX *pu4LinkSpeed; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; + uint32_t i; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prLinkQuality = (struct EVENT_LINK_QUALITY *) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + pu4LinkSpeed = (struct PARAM_LINK_SPEED_EX *) ( + prCmdInfo->pvInformationBuffer); + + for (i = 0; i < BSSID_NUM; i++) { + pu4LinkSpeed->rLq[i].u2LinkSpeed + = prLinkQuality->rLq[i].u2LinkSpeed * 5000; + + /* ranged from (-128 ~ 30) in unit of dBm */ + pu4LinkSpeed->rLq[i].cRssi + = prLinkQuality->rLq[i].cRssi; + + DBGLOG(NIC, TRACE, + "ucBssIdx = %d, rate = %u, signal = %d\n", + i, + pu4LinkSpeed->rLq[i].u2LinkSpeed, + pu4LinkSpeed->rLq[i].cRssi); + } + + u4QueryInfoLen = sizeof(struct PARAM_LINK_SPEED_EX); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +void nicCmdEventQueryStatistics(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + struct PARAM_802_11_STATISTICS_STRUCT *prStatistics; + struct EVENT_STATISTICS *prEventStatistics; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + struct WIFI_LINK_QUALITY_INFO *prLinkQualityInfo; + struct SCAN_INFO *prScanInfo; +#endif + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (struct EVENT_STATISTICS *) pucEventBuf; + + prGlueInfo = prAdapter->prGlueInfo; + + u4QueryInfoLen = sizeof(struct + PARAM_802_11_STATISTICS_STRUCT); + prStatistics = (struct PARAM_802_11_STATISTICS_STRUCT *) + prCmdInfo->pvInformationBuffer; + + 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; +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prStatistics->rMdrdyCnt = prEventStatistics->rMdrdyCnt; + prStatistics->rChnlIdleCnt = prEventStatistics->rChnlIdleCnt; + prStatistics->u4HwAwakeDuration = + prEventStatistics->u4HwMacAwakeDuration; + + prLinkQualityInfo = + &(prAdapter->rLinkQualityInfo); + + prLinkQualityInfo->u8TxRetryCount = + prStatistics->rRetryCount.QuadPart; + + prLinkQualityInfo->u8TxRtsFailCount = + prStatistics->rRTSFailureCount.QuadPart; + prLinkQualityInfo->u8TxAckFailCount = + prStatistics->rACKFailureCount.QuadPart; + prLinkQualityInfo->u8TxFailCount = + prLinkQualityInfo->u8TxRtsFailCount + + prLinkQualityInfo->u8TxAckFailCount; + prLinkQualityInfo->u8TxTotalCount = + prStatistics->rTransmittedFragmentCount.QuadPart; + + prLinkQualityInfo->u8RxTotalCount = + prStatistics->rReceivedFragmentCount.QuadPart; + /* FW report is diff, driver count total */ + prLinkQualityInfo->u8RxErrCount += + prStatistics->rFCSErrorCount.QuadPart; + prLinkQualityInfo->u8MdrdyCount = + prStatistics->rMdrdyCnt.QuadPart; + prLinkQualityInfo->u8IdleSlotCount = + prStatistics->rChnlIdleCnt.QuadPart; + prLinkQualityInfo->u4HwMacAwakeDuration = + prStatistics->u4HwAwakeDuration; + if (prScanInfo->eCurrentState == SCAN_STATE_SCANNING) + prLinkQualityInfo->u2FlagScanning = 1; + else + prLinkQualityInfo->u2FlagScanning = 0; + + wlanFinishCollectingLinkQuality(prGlueInfo); + + DBGLOG(SW4, TRACE, + "EVENT_STATISTICS: rTransmittedFragmentCount.QuadPart:%lld, rRetryCount.QuadPart:%lld, rRTSFailureCount.QuadPart:%lld, rACKFailureCount.QuadPart:%lld, rReceivedFragmentCount.QuadPart:%lld, rFCSErrorCount.QuadPart:%lld, rChnlIdleCnt.QuadPart:%lld\n", + prEventStatistics->rTransmittedFragmentCount.QuadPart, + prEventStatistics->rRetryCount.QuadPart, + prEventStatistics->rRTSFailureCount.QuadPart, + prEventStatistics->rACKFailureCount.QuadPart, + prEventStatistics->rReceivedFragmentCount.QuadPart, + prEventStatistics->rFCSErrorCount.QuadPart, + prEventStatistics->rChnlIdleCnt.QuadPart + ); +#endif + + if (prCmdInfo->fgIsOid) + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); +} + +void nicCmdEventQueryBugReport(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ +#define BUG_REPORT_VERSION 1 + + struct EVENT_BUG_REPORT *prStatistics; + struct EVENT_BUG_REPORT *prEventStatistics; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (struct EVENT_BUG_REPORT *) + pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + u4QueryInfoLen = sizeof(struct EVENT_BUG_REPORT); + if (prEventStatistics->u4BugReportVersion == + BUG_REPORT_VERSION) { + prStatistics = (struct EVENT_BUG_REPORT *) + prCmdInfo->pvInformationBuffer; + kalMemCopy(prStatistics, + prEventStatistics, u4QueryInfoLen); + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +void nicCmdEventEnterRfTest(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + uint32_t u4Idx = 0; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + /* [driver-land] */ + prAdapter->fgTestMode = TRUE; + + /* 0. always indicate disconnection */ + for (u4Idx = 0; u4Idx < KAL_AIS_NUM; u4Idx++) { + if (kalGetMediaStateIndicated( + prAdapter->prGlueInfo, + u4Idx) != + MEDIA_STATE_DISCONNECTED) + kalIndicateStatusAndComplete( + prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, + NULL, 0, u4Idx); + } + /* 1. Remove pending TX */ + nicTxRelease(prAdapter, TRUE); + + /* 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); + + /* Block til firmware completed entering into RF test mode */ + kalMsleep(500); + +#if defined(_HIF_SDIO) && 0 + /* 3. Disable Interrupt */ + HAL_INTR_DISABLE(prAdapter); + + /* 4. Block til firmware completed entering into RF test mode */ + kalMsleep(500); + while (1) { + uint32_t u4Value; + + 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 Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4SetInfoLen, + WLAN_STATUS_NOT_SUPPORTED); + + } + return; + } + kalMsleep(10); + } + + /* 5. Clear Interrupt Status */ + { + uint32_t u4WHISR = 0; + uint16_t au2TxCount[16]; + + HAL_READ_INTR_STATUS(prAdapter, 4, (uint8_t *)&u4WHISR); + if (HAL_IS_TX_DONE_INTR(u4WHISR)) + HAL_READ_TX_RELEASED_COUNT(prAdapter, au2TxCount); + } + /* 6. Reset TX Counter */ + nicTxResetResource(prAdapter); + + /* 7. Re-enable Interrupt */ + HAL_INTR_ENABLE(prAdapter); +#endif + + /* 8. completion indication */ + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, + WLAN_STATUS_SUCCESS); + } +#if CFG_SUPPORT_NVRAM + /* 9. load manufacture data */ + if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) + wlanLoadManufactureData(prAdapter, + kalGetConfiguration(prAdapter->prGlueInfo)); + else + DBGLOG(REQ, WARN, "%s: load manufacture data fail\n", + __func__); +#endif + +} + +void nicCmdEventLeaveRfTest(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + uint32_t u4Idx = 0; + + /* Block until firmware completed leaving from RF test mode */ + kalMsleep(500); + +#if defined(_HIF_SDIO) && 0 + uint32_t u4WHISR = 0; + uint16_t au2TxCount[16]; + uint32_t u4Value; + + /* 1. Disable Interrupt */ + HAL_INTR_DISABLE(prAdapter); + + /* 2. Block until 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 Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4SetInfoLen, + WLAN_STATUS_NOT_SUPPORTED); + + } + return; + } + kalMsleep(10); + } + /* 3. Clear Interrupt Status */ + HAL_READ_INTR_STATUS(prAdapter, 4, (uint8_t *)&u4WHISR); + if (HAL_IS_TX_DONE_INTR(u4WHISR)) + HAL_READ_TX_RELEASED_COUNT(prAdapter, au2TxCount); + /* 4. Reset TX Counter */ + nicTxResetResource(prAdapter); + + /* 5. Re-enable Interrupt */ + HAL_INTR_ENABLE(prAdapter); +#endif + + /* 6. set driver-land variable */ + prAdapter->fgTestMode = FALSE; + + /* 7. completion indication */ + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, + WLAN_STATUS_SUCCESS); + } + + /* 8. Indicate as disconnected */ + for (u4Idx = 0; u4Idx < KAL_AIS_NUM; u4Idx++) { + if (kalGetMediaStateIndicated( + prAdapter->prGlueInfo, + u4Idx) != + MEDIA_STATE_DISCONNECTED) { + + kalIndicateStatusAndComplete( + prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, + NULL, 0, u4Idx); + + prAdapter->rWlanInfo.u4SysTime = + kalGetTimeTick(); + } + } +#if CFG_SUPPORT_NVRAM + /* 9. load manufacture data */ + if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) + wlanLoadManufactureData(prAdapter, + kalGetConfiguration(prAdapter->prGlueInfo)); + else + DBGLOG(REQ, WARN, "%s: load manufacture data fail\n", + __func__); +#endif + + /* 10. Override network address */ + wlanUpdateNetworkAddress(prAdapter); + +} + +void nicCmdEventQueryMcastAddr(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct GLUE_INFO *prGlueInfo; + struct CMD_MAC_MCAST_ADDR *prEventMacMcastAddr; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventMacMcastAddr = (struct CMD_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 struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct PARAM_CUSTOM_EEPROM_RW_STRUCT *prEepromRdInfo; + struct GLUE_INFO *prGlueInfo; + struct CMD_ACCESS_EEPROM *prEventAccessEeprom; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventAccessEeprom = (struct CMD_ACCESS_EEPROM *) ( + pucEventBuf); + + u4QueryInfoLen = sizeof(struct + PARAM_CUSTOM_EEPROM_RW_STRUCT); + + prEepromRdInfo = (struct PARAM_CUSTOM_EEPROM_RW_STRUCT *) + prCmdInfo->pvInformationBuffer; + prEepromRdInfo->info.rEeprom.ucEepromIndex = (uint8_t) ( + prEventAccessEeprom->u2Offset); + prEepromRdInfo->info.rEeprom.u2EepromData = + prEventAccessEeprom->u2Data; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} + +void nicCmdEventSetMediaStreamMode(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + struct PARAM_MEDIA_STREAMING_INDICATION + rParamMediaStreamIndication; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, + WLAN_STATUS_SUCCESS); + } + + rParamMediaStreamIndication.rStatus.eStatusType = + ENUM_STATUS_TYPE_MEDIA_STREAM_MODE; + rParamMediaStreamIndication.eMediaStreamMode = + prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode == 0 ? + ENUM_MEDIA_STREAM_OFF : ENUM_MEDIA_STREAM_ON; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (void *)&rParamMediaStreamIndication, + sizeof(struct PARAM_MEDIA_STREAMING_INDICATION), + AIS_DEFAULT_INDEX); +} + +void nicCmdEventSetStopSchedScan(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + /* + * DBGLOG(SCN, INFO, "--->nicCmdEventSetStopSchedScan\n" )); + */ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + /* + * DBGLOG(SCN, INFO, "<--kalSchedScanStopped\n" ); + */ + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4InformationBufferLength, + WLAN_STATUS_SUCCESS); + } + + DBGLOG(SCN, INFO, + "nicCmdEventSetStopSchedScan OID done, release lock and send event to uplayer\n"); + /* Due to dead lock issue, need to release the IO + * control before calling kernel APIs + */ + kalSchedScanStopped(prAdapter->prGlueInfo, + !prCmdInfo->fgIsOid); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo) +{ + ASSERT(prAdapter); + + if (prCmdInfo->fgIsOid) + 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 struct ADAPTER *prAdapter, + IN struct CMD_INFO *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 struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo) +{ + ASSERT(prAdapter); + + /* 1. Remove pending TX frames */ + nicTxRelease(prAdapter, TRUE); + + /* 1.1 clear pending Security / Management Frames */ + kalClearSecurityFrames(prAdapter->prGlueInfo); + kalClearMgmtFrames(prAdapter->prGlueInfo); + + /* 1.2 clear pending TX packet queued in glue layer */ + kalFlushPendingTxPackets(prAdapter->prGlueInfo); + + /* 2. indicate for OID failure */ + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, + 0, WLAN_STATUS_FAILURE); +} + +#if CFG_SUPPORT_QA_TOOL +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called when received dump memory event packet. + * transfer the memory data to the IQ format data and write into file + * + * @param prIQAry Pointer to the array store I or Q data. + * prDataLen The return data length - bytes + * u4IQ 0: get I data + * 1 : get Q data + * + * @return -1: open file error + * + */ +/*----------------------------------------------------------------------------*/ +int32_t GetIQData(struct ADAPTER *prAdapter, + int32_t **prIQAry, uint32_t *prDataLen, uint32_t u4IQ, + uint32_t u4GetWf1) +{ + uint8_t aucPath[50]; /* the path for iq data dump out */ + uint8_t aucData[50]; /* iq data in string format */ + uint32_t i = 0, j = 0, count = 0; + int32_t ret = -1; + int32_t rv; + struct file *file = NULL; + + *prIQAry = prAdapter->rIcapInfo.au4IQData; + + /* sprintf(aucPath, "/pattern.txt"); // CSD's Pattern */ + kalSprintf(aucPath, "/tmp/dump_out_%05hu_WF%u.txt", + prAdapter->rIcapInfo.u2DumpIndex - 1, u4GetWf1); + if (kalCheckPath(aucPath) == -1) { + kalSnprintf(aucPath, sizeof(aucPath), + "/data/dump_out_%05hu_WF%u.txt", + prAdapter->rIcapInfo.u2DumpIndex - 1, u4GetWf1); + } + + DBGLOG(INIT, INFO, + "iCap Read Dump File dump_out_%05hu_WF%u.txt\n", + prAdapter->rIcapInfo.u2DumpIndex - 1, u4GetWf1); + + file = kalFileOpen(aucPath, O_RDONLY, 0); + + if ((file != NULL) && !IS_ERR(file)) { + /* read 1K data per time */ + for (i = 0; i < RTN_IQ_DATA_LEN / sizeof(uint32_t); + i++, prAdapter->rIcapInfo.au4Offset[u4GetWf1][u4IQ] += + IQ_FILE_LINE_OFFSET) { + if (kalFileRead(file, + prAdapter->rIcapInfo.au4Offset[u4GetWf1][u4IQ], + aucData, IQ_FILE_IQ_STR_LEN) == 0) + break; + + count = 0; + + for (j = 0; j < 8; j++) { + if (aucData[j] != ' ') + aucData[count++] = aucData[j]; + } + + aucData[count] = '\0'; + + /* transfer data format (string to int) */ + rv = kalStrtoint(aucData, 0, + &prAdapter->rIcapInfo.au4IQData[i]); + } + *prDataLen = i * sizeof(uint32_t); + kalFileClose(file); + ret = 0; + } + + DBGLOG(INIT, INFO, + "MT6632 : QA_AGENT GetIQData prDataLen = %d\n", *prDataLen); + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT GetIQData i = %d\n", + i); + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called when received dump memory event packet. + * transfer the memory data to the IQ format data and write into file + * + * @param prEventDumpMem Pointer to the event dump memory structure. + * + * @return 0: SUCCESS, -1: FAIL + * + */ +/*----------------------------------------------------------------------------*/ + +uint32_t nicTsfRawData2IqFmt(struct EVENT_DUMP_MEM + *prEventDumpMem, struct ICAP_INFO_T *prIcap) +{ + static uint8_t + aucPathWF0[40]; /* the path for iq data dump out */ + static uint8_t + aucPathWF1[40]; /* the path for iq data dump out */ + static uint8_t + aucPathRAWWF0[40]; /* the path for iq data dump out */ + static uint8_t + aucPathRAWWF1[40]; /* the path for iq data dump out */ + uint8_t *pucDataWF0 = NULL; /* the data write into file */ + uint8_t *pucDataWF1 = NULL; /* the data write into file */ + uint8_t *pucDataRAWWF0 = + NULL; /* the data write into file */ + uint8_t *pucDataRAWWF1 = + NULL; /* the data write into file */ + uint32_t u4SrcOffset; /* record the buffer offset */ + uint32_t u4FmtLen = 0; /* bus format length */ + uint32_t u4CpyLen = 0; + uint32_t u4RemainByte; + uint32_t u4DataWBufSize = 150; + uint32_t u4DataRAWWBufSize = 150; + uint32_t u4DataWLenF0 = 0; + uint32_t u4DataWLenF1 = 0; + uint32_t u4DataRAWWLenF0 = 0; + uint32_t u4DataRAWWLenF1 = 0; + + u_int8_t fgAppend; + int32_t u4Iqc160WF0Q0, u4Iqc160WF1I1; + + static uint8_t + ucDstOffset; /* for alignment. bcs we send 2KB data per packet,*/ + /*the data will not align in 12 bytes case. */ + static uint32_t u4CurTimeTick; + + static union ICAP_BUS_FMT icapBusData; + uint32_t *ptr; + + pucDataWF0 = kmalloc(u4DataWBufSize, GFP_KERNEL); + pucDataWF1 = kmalloc(u4DataWBufSize, GFP_KERNEL); + pucDataRAWWF0 = kmalloc(u4DataRAWWBufSize, GFP_KERNEL); + pucDataRAWWF1 = kmalloc(u4DataRAWWBufSize, GFP_KERNEL); + + + if ((!pucDataWF0) || (!pucDataWF1) || (!pucDataRAWWF0) + || (!pucDataRAWWF1)) { + DBGLOG(INIT, ERROR, "kmalloc failed.\n"); + kfree(pucDataWF0); + kfree(pucDataWF1); + kfree(pucDataRAWWF0); + kfree(pucDataRAWWF1); + ASSERT(-1); + return -1; + } + + fgAppend = TRUE; + if (prEventDumpMem->ucFragNum == 1) { + + u4CurTimeTick = kalGetTimeTick(); + /* Store memory dump into sdcard, + * path /sdcard/dump__ + * _.hex + */ +#if defined(LINUX) + + /* if blbist mkdir undre /data/blbist, + * the dump files wouls put on it + */ + kalScnprintf(aucPathWF0, sizeof(aucPathWF0), + "/tmp/dump_out_%05hu_WF0.txt", prIcap->u2DumpIndex); + kalScnprintf(aucPathWF1, sizeof(aucPathWF1), + "/tmp/dump_out_%05hu_WF1.txt", prIcap->u2DumpIndex); + if (kalCheckPath(aucPathWF0) == -1) { + kalMemSet(aucPathWF0, 0x00, sizeof(aucPathWF0)); + kalScnprintf(aucPathWF0, sizeof(aucPathWF0), + "/data/dump_out_%05hu_WF0.txt", + prIcap->u2DumpIndex); + } else + kalTrunkPath(aucPathWF0); + + if (kalCheckPath(aucPathWF1) == -1) { + kalMemSet(aucPathWF1, 0x00, sizeof(aucPathWF1)); + kalScnprintf(aucPathWF1, sizeof(aucPathWF1), + "/data/dump_out_%05hu_WF1.txt", + prIcap->u2DumpIndex); + } else + kalTrunkPath(aucPathWF1); + + kalScnprintf(aucPathRAWWF0, sizeof(aucPathRAWWF0), + "/dump_RAW_%hu_WF0.txt", prIcap->u2DumpIndex); + kalScnprintf(aucPathRAWWF1, sizeof(aucPathRAWWF1), + "/dump_RAW_%hu_WF1.txt", prIcap->u2DumpIndex); + if (kalCheckPath(aucPathRAWWF0) == -1) { + kalMemSet(aucPathRAWWF0, 0x00, sizeof(aucPathRAWWF0)); + kalScnprintf(aucPathRAWWF0, sizeof(aucPathRAWWF0), + "/data/dump_RAW_%05hu_WF0.txt", + prIcap->u2DumpIndex); + } else + kalTrunkPath(aucPathRAWWF0); + + if (kalCheckPath(aucPathRAWWF1) == -1) { + kalMemSet(aucPathRAWWF1, 0x00, sizeof(aucPathRAWWF1)); + kalScnprintf(aucPathRAWWF1, sizeof(aucPathRAWWF1), + "/data/dump_RAW_%05hu_WF1.txt", + prIcap->u2DumpIndex); + } else + kalTrunkPath(aucPathRAWWF1); + +#else + kal_sprintf_ddk(aucPathWF0, sizeof(aucPathWF0), + u4CurTimeTick, prEventDumpMem->u4Address, + prEventDumpMem->u4Length + + prEventDumpMem->u4RemainLength); + kal_sprintf_ddk(aucPathWF1, sizeof(aucPathWF1), + u4CurTimeTick, prEventDumpMem->u4Address, + prEventDumpMem->u4Length + + prEventDumpMem->u4RemainLength); +#endif + /* fgAppend = FALSE; */ + } + + ptr = (uint32_t *)(&prEventDumpMem->aucBuffer[0]); + + for (u4SrcOffset = 0, + u4RemainByte = prEventDumpMem->u4Length; u4RemainByte > 0; + ) { + u4FmtLen = + (prEventDumpMem->eIcapContent + == ICAP_CONTENT_SPECTRUM) ? + sizeof(struct SPECTRUM_BUS_FMT) : sizeof(union + ICAP_BUS_FMT); + /* 4 bytes : 12 bytes */ + u4CpyLen = (u4RemainByte - u4FmtLen >= 0) ? u4FmtLen : + u4RemainByte; + + if ((ucDstOffset + u4CpyLen) > sizeof(icapBusData)) { + DBGLOG(INIT, ERROR, + "ucDstOffset(%u) + u4CpyLen(%u) exceed bound of icapBusData\n", + ucDstOffset, u4CpyLen); + kfree(pucDataWF0); + kfree(pucDataWF1); + kfree(pucDataRAWWF0); + kfree(pucDataRAWWF1); + ASSERT(-1); + return -1; + } + memcpy((uint8_t *)&icapBusData + ucDstOffset, + &prEventDumpMem->aucBuffer[0] + u4SrcOffset, u4CpyLen); +#if 0 + if (prEventDumpMem->eIcapContent == ICAP_CONTENT_ADC) { + sprintf(aucDataWF0, "%8d,%8d\n", + icapBusData.rAdcBusData.u4Dcoc0I, + icapBusData.rAdcBusData.u4Dcoc0Q); + sprintf(aucDataWF1, "%8d,%8d\n", + icapBusData.rAdcBusData.u4Dcoc1I, + icapBusData.rAdcBusData.u4Dcoc1Q); + } +#endif + if (prEventDumpMem->eIcapContent == ICAP_CONTENT_FIIQ || + prEventDumpMem->eIcapContent == ICAP_CONTENT_FDIQ) { + u4DataWLenF0 = kalScnprintf(pucDataWF0, u4DataWBufSize, + "%8d,%8d\n", + icapBusData.rIqcBusData.u4Iqc0I, + icapBusData.rIqcBusData.u4Iqc0Q); + u4DataWLenF1 = kalScnprintf(pucDataWF1, u4DataWBufSize, + "%8d,%8d\n", + icapBusData.rIqcBusData.u4Iqc1I, + icapBusData.rIqcBusData.u4Iqc1Q); + } else if (prEventDumpMem->eIcapContent - 1000 == + ICAP_CONTENT_FIIQ + || prEventDumpMem->eIcapContent - 1000 == + ICAP_CONTENT_FDIQ) { + u4Iqc160WF0Q0 = + icapBusData.rIqc160BusData.u4Iqc0Q0P1 | + (icapBusData.rIqc160BusData.u4Iqc0Q0P2 << 8); + u4Iqc160WF1I1 = + icapBusData.rIqc160BusData.u4Iqc1I1P1 | + (icapBusData.rIqc160BusData.u4Iqc1I1P2 << 4); + + u4DataWLenF0 = kalScnprintf(pucDataWF0, u4DataWBufSize, + "%8d,%8d\n%8d,%8d\n", + icapBusData.rIqc160BusData.u4Iqc0I0, + u4Iqc160WF0Q0, + icapBusData.rIqc160BusData.u4Iqc0I1, + icapBusData.rIqc160BusData.u4Iqc0Q1); + + u4DataWLenF1 = kalScnprintf(pucDataWF1, u4DataWBufSize, + "%8d,%8d\n%8d,%8d\n", + icapBusData.rIqc160BusData.u4Iqc1I0, + icapBusData.rIqc160BusData.u4Iqc1Q0, + u4Iqc160WF1I1, + icapBusData.rIqc160BusData.u4Iqc1Q1); + + } else if (prEventDumpMem->eIcapContent == + ICAP_CONTENT_SPECTRUM) { + u4DataWLenF0 = kalScnprintf(pucDataWF0, u4DataWBufSize, + "%8d,%8d\n", + icapBusData.rSpectrumBusData.u4DcocI, + icapBusData.rSpectrumBusData.u4DcocQ); + } else if (prEventDumpMem->eIcapContent == + ICAP_CONTENT_ADC) { + u4DataWLenF0 = kalScnprintf(pucDataWF0, u4DataWBufSize, + "%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n", + icapBusData.rPackedAdcBusData.u4AdcI0T0, + icapBusData.rPackedAdcBusData.u4AdcQ0T0, + icapBusData.rPackedAdcBusData.u4AdcI0T1, + icapBusData.rPackedAdcBusData.u4AdcQ0T1, + icapBusData.rPackedAdcBusData.u4AdcI0T2, + icapBusData.rPackedAdcBusData.u4AdcQ0T2, + icapBusData.rPackedAdcBusData.u4AdcI0T3, + icapBusData.rPackedAdcBusData.u4AdcQ0T3, + icapBusData.rPackedAdcBusData.u4AdcI0T4, + icapBusData.rPackedAdcBusData.u4AdcQ0T4, + icapBusData.rPackedAdcBusData.u4AdcI0T5, + icapBusData.rPackedAdcBusData.u4AdcQ0T5); + + u4DataWLenF1 = kalScnprintf(pucDataWF1, u4DataWBufSize, + "%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n", + icapBusData.rPackedAdcBusData.u4AdcI1T0, + icapBusData.rPackedAdcBusData.u4AdcQ1T0, + icapBusData.rPackedAdcBusData.u4AdcI1T1, + icapBusData.rPackedAdcBusData.u4AdcQ1T1, + icapBusData.rPackedAdcBusData.u4AdcI1T2, + icapBusData.rPackedAdcBusData.u4AdcQ1T2, + icapBusData.rPackedAdcBusData.u4AdcI1T3, + icapBusData.rPackedAdcBusData.u4AdcQ1T3, + icapBusData.rPackedAdcBusData.u4AdcI1T4, + icapBusData.rPackedAdcBusData.u4AdcQ1T4, + icapBusData.rPackedAdcBusData.u4AdcI1T5, + icapBusData.rPackedAdcBusData.u4AdcQ1T5); + } else if (prEventDumpMem->eIcapContent - 2000 == + ICAP_CONTENT_ADC) { + u4DataWLenF0 = kalScnprintf(pucDataWF0, u4DataWBufSize, + "%8d,%8d\n%8d,%8d\n%8d,%8d\n", + icapBusData.rPackedAdcBusData.u4AdcI0T0, + icapBusData.rPackedAdcBusData.u4AdcQ0T0, + icapBusData.rPackedAdcBusData.u4AdcI0T1, + icapBusData.rPackedAdcBusData.u4AdcQ0T1, + icapBusData.rPackedAdcBusData.u4AdcI0T2, + icapBusData.rPackedAdcBusData.u4AdcQ0T2); + + u4DataWLenF1 = kalScnprintf(pucDataWF1, u4DataWBufSize, + "%8d,%8d\n%8d,%8d\n%8d,%8d\n", + icapBusData.rPackedAdcBusData.u4AdcI1T0, + icapBusData.rPackedAdcBusData.u4AdcQ1T0, + icapBusData.rPackedAdcBusData.u4AdcI1T1, + icapBusData.rPackedAdcBusData.u4AdcQ1T1, + icapBusData.rPackedAdcBusData.u4AdcI1T2, + icapBusData.rPackedAdcBusData.u4AdcQ1T2); + } else if (prEventDumpMem->eIcapContent == + ICAP_CONTENT_TOAE) { + /* actually, this is DCOC. we take TOAE as DCOC */ + u4DataWLenF0 = kalScnprintf(pucDataWF0, u4DataWBufSize, + "%8d,%8d\n", + icapBusData.rAdcBusData.u4Dcoc0I, + icapBusData.rAdcBusData.u4Dcoc0Q); + u4DataWLenF1 = kalScnprintf(pucDataWF1, u4DataWBufSize, + "%8d,%8d\n", + icapBusData.rAdcBusData.u4Dcoc1I, + icapBusData.rAdcBusData.u4Dcoc1Q); + } + if (u4CpyLen == + u4FmtLen) { /* the data format is complete */ + kalWriteToFile(aucPathWF0, fgAppend, pucDataWF0, + u4DataWLenF0); + kalWriteToFile(aucPathWF1, fgAppend, pucDataWF1, + u4DataWLenF1); + } + ptr = (uint32_t *)(&prEventDumpMem->aucBuffer[0] + + u4SrcOffset); + u4DataRAWWLenF0 = kalScnprintf(pucDataRAWWF0, u4DataWBufSize, + "%08x%08x%08x\n", + *(ptr + 2), *(ptr + 1), *ptr); + kalWriteToFile(aucPathRAWWF0, fgAppend, pucDataRAWWF0, + u4DataRAWWLenF0); + kalWriteToFile(aucPathRAWWF1, fgAppend, pucDataRAWWF1, + u4DataRAWWLenF1); + + u4RemainByte -= u4CpyLen; + u4SrcOffset += u4CpyLen; /* shift offset */ + /* only use ucDstOffset at first packet for align 2KB */ + ucDstOffset = 0; + } + /* if this is a last packet, we can't transfer the remain data. + * bcs we can't guarantee the data is complete align data format + */ + /* the data format is complete */ + if (u4CpyLen != u4FmtLen) { + /* not align 2KB, keep the data + * and next packet data will append it + */ + ucDstOffset = u4CpyLen; + } + + kfree(pucDataWF0); + kfree(pucDataWF1); + kfree(pucDataRAWWF0); + kfree(pucDataRAWWF1); + + if (u4RemainByte < 0) { + ASSERT(-1); + return -1; + } + + return 0; +} +#endif /* CFG_SUPPORT_QA_TOOL */ + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +void nicCmdEventQueryCalBackupV2(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + struct PARAM_CAL_BACKUP_STRUCT_V2 *prCalBackupDataV2Info; + struct CMD_CAL_BACKUP_STRUCT_V2 *prEventCalBackupDataV2; + uint32_t u4QueryInfoLen, u4QueryInfo, u4TempAddress; + struct GLUE_INFO *prGlueInfo; + + DBGLOG(RFTEST, INFO, "%s\n", __func__); + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + + prGlueInfo = prAdapter->prGlueInfo; + prEventCalBackupDataV2 = (struct CMD_CAL_BACKUP_STRUCT_V2 *) + (pucEventBuf); + + u4QueryInfoLen = sizeof(struct CMD_CAL_BACKUP_STRUCT_V2); + + prCalBackupDataV2Info = (struct PARAM_CAL_BACKUP_STRUCT_V2 + *) prCmdInfo->pvInformationBuffer; +#if 0 + DBGLOG(RFTEST, INFO, + "============ Receive a Cal Data EVENT (Info) ============\n"); + DBGLOG(RFTEST, INFO, "Reason = %d\n", + prEventCalBackupDataV2->ucReason); + DBGLOG(RFTEST, INFO, "Action = %d\n", + prEventCalBackupDataV2->ucAction); + DBGLOG(RFTEST, INFO, "NeedResp = %d\n", + prEventCalBackupDataV2->ucNeedResp); + DBGLOG(RFTEST, INFO, "FragNum = %d\n", + prEventCalBackupDataV2->ucFragNum); + DBGLOG(RFTEST, INFO, "RomRam = %d\n", + prEventCalBackupDataV2->ucRomRam); + DBGLOG(RFTEST, INFO, "ThermalValue = %d\n", + prEventCalBackupDataV2->u4ThermalValue); + DBGLOG(RFTEST, INFO, "Address = 0x%08x\n", + prEventCalBackupDataV2->u4Address); + DBGLOG(RFTEST, INFO, "Length = %d\n", + prEventCalBackupDataV2->u4Length); + DBGLOG(RFTEST, INFO, "RemainLength = %d\n", + prEventCalBackupDataV2->u4RemainLength); + DBGLOG(RFTEST, INFO, + "=========================================================\n"); +#endif + + if (prEventCalBackupDataV2->ucReason == 0 + && prEventCalBackupDataV2->ucAction == 0) { + DBGLOG(RFTEST, INFO, + "Received an EVENT for Query Thermal Temp.\n"); + prCalBackupDataV2Info->u4ThermalValue = + prEventCalBackupDataV2->u4ThermalValue; + g_rBackupCalDataAllV2.u4ThermalInfo = + prEventCalBackupDataV2->u4ThermalValue; + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } else if (prEventCalBackupDataV2->ucReason == 0 + && prEventCalBackupDataV2->ucAction == 1) { + DBGLOG(RFTEST, INFO, + "Received an EVENT for Query Total Cal Data Length.\n"); + prCalBackupDataV2Info->u4Length = + prEventCalBackupDataV2->u4Length; + + if (prEventCalBackupDataV2->ucRomRam == 0) + g_rBackupCalDataAllV2.u4ValidRomCalDataLength = + prEventCalBackupDataV2->u4Length; + else if (prEventCalBackupDataV2->ucRomRam == 1) + g_rBackupCalDataAllV2.u4ValidRamCalDataLength = + prEventCalBackupDataV2->u4Length; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } else if (prEventCalBackupDataV2->ucReason == 2 + && prEventCalBackupDataV2->ucAction == 4) { + DBGLOG(RFTEST, INFO, + "Received an EVENT for Query All Cal (%s) Data. FragNum = %d\n", + prCalBackupDataV2Info->ucRomRam == 0 ? "ROM" : "RAM", + prEventCalBackupDataV2->ucFragNum); + prCalBackupDataV2Info->u4Address = + prEventCalBackupDataV2->u4Address; + prCalBackupDataV2Info->u4Length = + prEventCalBackupDataV2->u4Length; + prCalBackupDataV2Info->u4RemainLength = + prEventCalBackupDataV2->u4RemainLength; + prCalBackupDataV2Info->ucFragNum = + prEventCalBackupDataV2->ucFragNum; + + /* Copy Cal Data From FW to Driver Array */ + if (prEventCalBackupDataV2->ucRomRam == 0) { + u4TempAddress = prEventCalBackupDataV2->u4Address; + kalMemCopy( + (uint8_t *)(g_rBackupCalDataAllV2.au4RomCalData) + + u4TempAddress, + (uint8_t *)(prEventCalBackupDataV2->au4Buffer), + prEventCalBackupDataV2->u4Length); + } else if (prEventCalBackupDataV2->ucRomRam == 1) { + u4TempAddress = prEventCalBackupDataV2->u4Address; + kalMemCopy( + (uint8_t *)(g_rBackupCalDataAllV2.au4RamCalData) + + u4TempAddress, + (uint8_t *)(prEventCalBackupDataV2->au4Buffer), + prEventCalBackupDataV2->u4Length); + } + + if (prEventCalBackupDataV2->u4Address == 0xFFFFFFFF) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Address Error!!!!!!!!!!!\n"); + } else if (prEventCalBackupDataV2->u4RemainLength == 0 + && prEventCalBackupDataV2->ucRomRam == 1) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Get Cal Data from FW (%s). Finish!!!!!!!!!!!\n", + prCalBackupDataV2Info->ucRomRam == 0 ? "ROM" : "RAM"); + } else if (prEventCalBackupDataV2->u4RemainLength == 0 + && prEventCalBackupDataV2->ucRomRam == 0) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Get Cal Data from FW (%s). Finish!!!!!!!!!!!\n", + prCalBackupDataV2Info->ucRomRam == 0 ? "ROM" : "RAM"); + prCalBackupDataV2Info->ucFragNum = 0; + prCalBackupDataV2Info->ucRomRam = 1; + prCalBackupDataV2Info->u4ThermalValue = 0; + prCalBackupDataV2Info->u4Address = 0; + prCalBackupDataV2Info->u4Length = 0; + prCalBackupDataV2Info->u4RemainLength = 0; + DBGLOG(RFTEST, INFO, + "RLM CMD : Get Cal Data from FW (%s). Start!!!!!!!!!!!!!!!!\n", + prCalBackupDataV2Info->ucRomRam == 0 ? "ROM" : "RAM"); + DBGLOG(RFTEST, INFO, "Thermal Temp = %d\n", + g_rBackupCalDataAllV2.u4ThermalInfo); + wlanoidQueryCalBackupV2(prAdapter, + prCalBackupDataV2Info, + sizeof(struct PARAM_CAL_BACKUP_STRUCT_V2), + &u4QueryInfo); + } else { + wlanoidSendCalBackupV2Cmd(prAdapter, + prCmdInfo->pvInformationBuffer, + prCmdInfo->u4InformationBufferLength); + } + } else if (prEventCalBackupDataV2->ucReason == 3 + && prEventCalBackupDataV2->ucAction == 5) { + DBGLOG(RFTEST, INFO, + "Received an EVENT for Send All Cal Data. FragNum = %d\n", + prEventCalBackupDataV2->ucFragNum); + prCalBackupDataV2Info->u4Address = + prEventCalBackupDataV2->u4Address; + prCalBackupDataV2Info->u4Length = + prEventCalBackupDataV2->u4Length; + prCalBackupDataV2Info->u4RemainLength = + prEventCalBackupDataV2->u4RemainLength; + prCalBackupDataV2Info->ucFragNum = + prEventCalBackupDataV2->ucFragNum; + + if (prEventCalBackupDataV2->u4RemainLength == 0 + || prEventCalBackupDataV2->u4Address == 0xFFFFFFFF) { + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } else { + wlanoidSendCalBackupV2Cmd(prAdapter, + prCmdInfo->pvInformationBuffer, + prCmdInfo->u4InformationBufferLength); + } + } else { + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to handle dump burst event + * + * @param prAdapter Pointer to the Adapter structure. + * @param prCmdInfo Pointer to the command information + * @param pucEventBuf Pointer to event buffer + * + * @return none + * + */ +/*----------------------------------------------------------------------------*/ +void nicEventQueryMemDump(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct EVENT_DUMP_MEM *prEventDumpMem; + static uint8_t aucPath[256]; + static uint8_t aucPath_done[300]; + static uint32_t u4CurTimeTick; + + ASSERT(prAdapter); + ASSERT(pucEventBuf); + + kalSprintf(aucPath, "/dump_%05hu.hex", + prAdapter->rIcapInfo.u2DumpIndex); + + prEventDumpMem = (struct EVENT_DUMP_MEM *) (pucEventBuf); + + if (kalCheckPath(aucPath) == -1) { + kalMemSet(aucPath, 0x00, 256); + kalSprintf(aucPath, "/data/dump_%05hu.hex", + prAdapter->rIcapInfo.u2DumpIndex); + } + + if (prEventDumpMem->ucFragNum == 1) { + /* Store memory dump into sdcard, + * path /sdcard/dump__ + * _.hex + */ + u4CurTimeTick = kalGetTimeTick(); +#if defined(LINUX) + + /* if blbist mkdir undre /data/blbist, + * the dump files wouls put on it + */ + kalSprintf(aucPath, "/dump_%05hu.hex", + prAdapter->rIcapInfo.u2DumpIndex); + if (kalCheckPath(aucPath) == -1) { + kalMemSet(aucPath, 0x00, 256); + kalSprintf(aucPath, "/data/dump_%05hu.hex", + prAdapter->rIcapInfo.u2DumpIndex); + } +#else + kal_sprintf_ddk(aucPath, sizeof(aucPath), + u4CurTimeTick, + prEventDumpMem->u4Address, + prEventDumpMem->u4Length + + prEventDumpMem->u4RemainLength); +#endif + 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 CFG_SUPPORT_QA_TOOL + nicTsfRawData2IqFmt(prEventDumpMem, &prAdapter->rIcapInfo); +#endif /* CFG_SUPPORT_QA_TOOL */ + DBGLOG(INIT, INFO, + "iCap : ==> (u4RemainLength = %x, u4Address=%x )\n", + prEventDumpMem->u4RemainLength, + prEventDumpMem->u4Address); + + if (prEventDumpMem->u4RemainLength == 0 + || prEventDumpMem->u4Address == 0xFFFFFFFF) { + + /* The request is finished or firmware response a error */ + /* Reply time tick to iwpriv */ + + prAdapter->rIcapInfo.eIcapState = ICAP_STATE_FW_DUMP_DONE; + + kalSprintf(aucPath_done, "/file_dump_done.txt"); + if (kalCheckPath(aucPath_done) == -1) { + kalMemSet(aucPath_done, 0x00, 256); + kalSprintf(aucPath_done, "/data/file_dump_done.txt"); + } + DBGLOG(INIT, INFO, ": ==> gen done_file\n"); + kalWriteToFile(aucPath_done, FALSE, aucPath_done, + sizeof(aucPath_done)); +#if CFG_SUPPORT_QA_TOOL + prAdapter->rIcapInfo.au4Offset[0][0] = 0; + prAdapter->rIcapInfo.au4Offset[0][1] = 9; + prAdapter->rIcapInfo.au4Offset[1][0] = 0; + prAdapter->rIcapInfo.au4Offset[1][1] = 9; +#endif /* CFG_SUPPORT_QA_TOOL */ + + prAdapter->rIcapInfo.u2DumpIndex++; + + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct GLUE_INFO *prGlueInfo; + struct EVENT_DUMP_MEM *prEventDumpMem; + static uint8_t aucPath[256]; + /* static UINT_8 aucPath_done[300]; */ + static uint32_t u4CurTimeTick; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (1) { + prGlueInfo = prAdapter->prGlueInfo; + prEventDumpMem = (struct EVENT_DUMP_MEM *) (pucEventBuf); + + u4QueryInfoLen = sizeof(struct PARAM_CUSTOM_MEM_DUMP_STRUCT + *); + + if (prEventDumpMem->ucFragNum == 1) { + /* Store memory dump into sdcard, + * path /sdcard/dump__ + * _.hex + */ + u4CurTimeTick = kalGetTimeTick(); +#if defined(LINUX) + + /* PeiHsuan add for avoiding out of memory 20160801 */ + if (prAdapter->rIcapInfo.u2DumpIndex >= 20) + prAdapter->rIcapInfo.u2DumpIndex = 0; + + /* if blbist mkdir undre /data/blbist, + * the dump files wouls put on it + */ + sprintf(aucPath, "/dump_%05hu.hex", + prAdapter->rIcapInfo.u2DumpIndex); + if (kalCheckPath(aucPath) == -1) { + kalMemSet(aucPath, 0x00, 256); + sprintf(aucPath, "/data/dump_%05hu.hex", + prAdapter->rIcapInfo.u2DumpIndex); + } else + kalTrunkPath(aucPath); + + DBGLOG(INIT, INFO, + "iCap Create New Dump File dump_%05hu.hex\n", + prAdapter->rIcapInfo.u2DumpIndex); +#else + kal_sprintf_ddk(aucPath, sizeof(aucPath), + u4CurTimeTick, + prEventDumpMem->u4Address, + prEventDumpMem->u4Length + + prEventDumpMem->u4RemainLength); + /* strcpy(aucPath, "dump.hex"); */ +#endif + 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 CFG_SUPPORT_QA_TOOL + nicTsfRawData2IqFmt(prEventDumpMem, &prAdapter->rIcapInfo); +#endif /* CFG_SUPPORT_QA_TOOL */ + if (prEventDumpMem->u4RemainLength == 0 + || prEventDumpMem->u4Address == 0xFFFFFFFF) { + /* The request is finished or firmware response + * a error + */ + /* Reply time tick to iwpriv */ + if (prCmdInfo->fgIsOid) { + + /* the oid would be complete only in oid-trigger + * mode, that is no need to if the event-trigger + */ + if (prAdapter->rIcapInfo.eIcapState + == ICAP_STATE_FW_DUMPING) { + *((uint32_t *) + prCmdInfo->pvInformationBuffer) + = u4CurTimeTick; + kalOidComplete(prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + } + } + + prAdapter->rIcapInfo.eIcapState + = ICAP_STATE_FW_DUMP_DONE; + +#if defined(LINUX) + + prAdapter->rIcapInfo.u2DumpIndex++; + +#else + kal_sprintf_done_ddk(aucPath_done, + sizeof(aucPath_done)); + kalWriteToFile(aucPath_done, FALSE, aucPath_done, + sizeof(aucPath_done)); +#endif + } else { +#if defined(LINUX) + +#else /* 2013/05/26 fw would try to send the buffer successfully */ + /* The memory dump request is not finished, + * Send next command + */ + wlanSendMemDumpCmd(prAdapter, + prCmdInfo->pvInformationBuffer, + prCmdInfo->u4InformationBufferLength); +#endif + } + } + + return; + +} + +#if CFG_SUPPORT_BATCH_SCAN +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called when event for SUPPORT_BATCH_SCAN + * + * @param prAdapter Pointer to the Adapter structure. + * @param prCmdInfo Pointer to the command information + * @param pucEventBuf Pointer to the event buffer + * + * @return none + * + */ +/*----------------------------------------------------------------------------*/ +void nicCmdEventBatchScanResult(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct EVENT_BATCH_RESULT *prEventBatchResult; + struct GLUE_INFO *prGlueInfo; + + DBGLOG(SCN, TRACE, "nicCmdEventBatchScanResult"); + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventBatchResult = (struct EVENT_BATCH_RESULT *) + pucEventBuf; + + u4QueryInfoLen = sizeof(struct EVENT_BATCH_RESULT); + kalMemCopy(prCmdInfo->pvInformationBuffer, + prEventBatchResult, sizeof(struct EVENT_BATCH_RESULT)); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} +#endif + +void nicEventHifCtrlv2(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ +#if defined(_HIF_USB) + struct EVENT_HIF_CTRL *prEventHifCtrl; + struct GL_HIF_INFO *prHifInfo; + + prEventHifCtrl = (struct EVENT_HIF_CTRL *) ( + prEvent->aucBuffer); + + if (prEventHifCtrl->ucHifSuspend) { + /* suspend event, change state to PRE_SUSPEND_DONE */ + if (prEventHifCtrl->ucHifTxTrafficStatus == + ENUM_HIF_TRAFFIC_IDLE && + prEventHifCtrl->ucHifRxTrafficStatus == + ENUM_HIF_TRAFFIC_IDLE) { /* success */ + halUSBPreSuspendDone(prAdapter, + NULL, prEvent->aucBuffer); + } else { + /* busy */ + /* invalid */ + halUSBPreSuspendTimeout(prAdapter, NULL); + } + } else { + /* if USB get resume event, change to LINK_UP */ + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + glUsbSetState(prHifInfo, USB_STATE_LINK_UP); + } +#endif +} + +void nicEventHifCtrl(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ +#if defined(_HIF_USB) + struct EVENT_HIF_CTRL *prEventHifCtrl; + struct BUS_INFO *prBusInfo; + + prBusInfo = prAdapter->chip_info->bus_info; + prEventHifCtrl = (struct EVENT_HIF_CTRL *) ( + prEvent->aucBuffer); + + DBGLOG(HAL, INFO, "%s: EVENT_ID_HIF_CTRL\n", __func__); + DBGLOG(HAL, INFO, "prEventHifCtrl->ucHifType = %hhu suspend %d\n", + prEventHifCtrl->ucHifType, prEventHifCtrl->ucHifSuspend); + DBGLOG(HAL, INFO, + "prEventHifCtrl->ucHifTxTrafficStatus, prEventHifCtrl->ucHifRxTrafficStatus = %hhu, %hhu\n", + prEventHifCtrl->ucHifTxTrafficStatus, + prEventHifCtrl->ucHifRxTrafficStatus); + + if (prBusInfo->u4SuspendVer == SUSPEND_V2) { + /* Suspend V2, control state of HIF here */ + nicEventHifCtrlv2(prAdapter, prEvent); + } else { + if (prEventHifCtrl->ucHifTxTrafficStatus == + ENUM_HIF_TRAFFIC_IDLE && + prEventHifCtrl->ucHifRxTrafficStatus == + ENUM_HIF_TRAFFIC_IDLE) { /* success */ + halUSBPreSuspendDone(prAdapter, + NULL, prEvent->aucBuffer); + } else { + /* busy */ + /* invalid */ + halUSBPreSuspendTimeout(prAdapter, NULL); + } + } +#endif +} + +#if CFG_SUPPORT_BUILD_DATE_CODE +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called when event for build date code information + * has been retrieved + * + * @param prAdapter Pointer to the Adapter structure. + * @param prCmdInfo Pointer to the command information + * @param pucEventBuf Pointer to the event buffer + * + * @return none + * + */ +/*----------------------------------------------------------------------------*/ +void nicCmdEventBuildDateCode(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct EVENT_BUILD_DATE_CODE *prEvent; + struct GLUE_INFO *prGlueInfo; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEvent = (struct EVENT_BUILD_DATE_CODE *) pucEventBuf; + + u4QueryInfoLen = sizeof(uint8_t) * 16; + kalMemCopy(prCmdInfo->pvInformationBuffer, + prEvent->aucDateCode, sizeof(uint8_t) * 16); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called when event for query STA link status + * has been retrieved + * + * @param prAdapter Pointer to the Adapter structure. + * @param prCmdInfo Pointer to the command information + * @param pucEventBuf Pointer to the event buffer + * + * @return none + * + */ +/*----------------------------------------------------------------------------*/ +void nicCmdEventQueryStaStatistics(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct EVENT_STA_STATISTICS *prEvent; + struct GLUE_INFO *prGlueInfo; + struct PARAM_GET_STA_STATISTICS *prStaStatistics; + enum ENUM_WMM_ACI eAci; + struct STA_RECORD *prStaRec; + uint8_t ucDbdcIdx, ucIdx; +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + struct WIFI_LINK_QUALITY_INFO *prLinkQualityInfo; +#endif + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + ASSERT(prCmdInfo->pvInformationBuffer); + + prGlueInfo = prAdapter->prGlueInfo; + prEvent = (struct EVENT_STA_STATISTICS *) pucEventBuf; + prStaStatistics = (struct PARAM_GET_STA_STATISTICS *) + prCmdInfo->pvInformationBuffer; + + u4QueryInfoLen = sizeof(struct PARAM_GET_STA_STATISTICS); + + /* Statistics from FW is valid */ + if (prEvent->u4Flags & BIT(0)) { + prStaStatistics->ucPer = prEvent->ucPer; + prStaStatistics->ucRcpi = prEvent->ucRcpi; + prStaStatistics->u4PhyMode = prEvent->u4PhyMode; + prStaStatistics->u2LinkSpeed = prEvent->u2LinkSpeed; + + prStaStatistics->u4TxFailCount = prEvent->u4TxFailCount; + prStaStatistics->u4TxLifeTimeoutCount = + prEvent->u4TxLifeTimeoutCount; + prStaStatistics->u4TransmitCount = + prEvent->u4TransmitCount; + prStaStatistics->u4TransmitFailCount = + prEvent->u4TransmitFailCount; + prStaStatistics->u4Rate1TxCnt = prEvent->u4Rate1TxCnt; + prStaStatistics->u4Rate1FailCnt = + prEvent->u4Rate1FailCnt; + + prStaStatistics->ucTemperature = prEvent->ucTemperature; + prStaStatistics->ucSkipAr = prEvent->ucSkipAr; + prStaStatistics->ucArTableIdx = prEvent->ucArTableIdx; + prStaStatistics->ucRateEntryIdx = + prEvent->ucRateEntryIdx; + prStaStatistics->ucRateEntryIdxPrev = + prEvent->ucRateEntryIdxPrev; + prStaStatistics->ucTxSgiDetectPassCnt = + prEvent->ucTxSgiDetectPassCnt; + prStaStatistics->ucAvePer = prEvent->ucAvePer; +#if (CFG_SUPPORT_RA_GEN == 0) + kalMemCopy(prStaStatistics->aucArRatePer, + prEvent->aucArRatePer, + sizeof(prEvent->aucArRatePer)); + kalMemCopy(prStaStatistics->aucRateEntryIndex, + prEvent->aucRateEntryIndex, + sizeof(prEvent->aucRateEntryIndex)); +#else + prStaStatistics->u4AggRangeCtrl_0 = + prEvent->u4AggRangeCtrl_0; + prStaStatistics->u4AggRangeCtrl_1 = + prEvent->u4AggRangeCtrl_1; + prStaStatistics->ucRangeType = prEvent->ucRangeType; +#if (CFG_SUPPORT_CONNAC2X == 1) + prStaStatistics->u4AggRangeCtrl_2 = + prEvent->u4AggRangeCtrl_2; + prStaStatistics->u4AggRangeCtrl_3 = + prEvent->u4AggRangeCtrl_3; +#endif + kalMemCopy(prStaStatistics->aucReserved5, + prEvent->aucReserved5, + sizeof(prEvent->aucReserved5)); +#endif + prStaStatistics->ucArStateCurr = prEvent->ucArStateCurr; + prStaStatistics->ucArStatePrev = prEvent->ucArStatePrev; + prStaStatistics->ucArActionType = + prEvent->ucArActionType; + prStaStatistics->ucHighestRateCnt = + prEvent->ucHighestRateCnt; + prStaStatistics->ucLowestRateCnt = + prEvent->ucLowestRateCnt; + prStaStatistics->u2TrainUp = prEvent->u2TrainUp; + prStaStatistics->u2TrainDown = prEvent->u2TrainDown; + kalMemCopy(&prStaStatistics->rTxVector, + &prEvent->rTxVector, + sizeof(prEvent->rTxVector)); + kalMemCopy(&prStaStatistics->rMibInfo, + &prEvent->rMibInfo, + sizeof(prEvent->rMibInfo)); + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; ucDbdcIdx++) { + g_arMibInfo[ucDbdcIdx].u4RxMpduCnt += + prStaStatistics->rMibInfo[ucDbdcIdx]. + u4RxMpduCnt; + g_arMibInfo[ucDbdcIdx].u4FcsError += + prStaStatistics->rMibInfo[ucDbdcIdx]. + u4FcsError; + g_arMibInfo[ucDbdcIdx].u4RxFifoFull += + prStaStatistics->rMibInfo[ucDbdcIdx]. + u4RxFifoFull; + g_arMibInfo[ucDbdcIdx].u4AmpduTxSfCnt += + prStaStatistics->rMibInfo[ucDbdcIdx]. + u4AmpduTxSfCnt; + g_arMibInfo[ucDbdcIdx].u4AmpduTxAckSfCnt += + prStaStatistics->rMibInfo[ucDbdcIdx]. + u4AmpduTxAckSfCnt; + + for (ucIdx = 0; ucIdx <= AGG_RANGE_SEL_NUM; ucIdx++) + g_arMibInfo[ucDbdcIdx].au2TxRangeAmpduCnt[ucIdx] + += prStaStatistics->rMibInfo[ucDbdcIdx]. + au2TxRangeAmpduCnt[ucIdx]; + } + + prStaStatistics->fgIsForceTxStream = + prEvent->fgIsForceTxStream; + prStaStatistics->fgIsForceSeOff = + prEvent->fgIsForceSeOff; +#if (CFG_SUPPORT_RA_GEN == 0) + kalMemCopy(prStaStatistics->aucReserved6, + prEvent->aucReserved6, + sizeof(prEvent->aucReserved6)); +#else + prStaStatistics->u2RaRunningCnt = + prEvent->u2RaRunningCnt; + prStaStatistics->ucRaStatus = prEvent->ucRaStatus; + prStaStatistics->ucFlag = prEvent->ucFlag; + kalMemCopy(&prStaStatistics->aucTxQuality, + &prEvent->aucTxQuality, + sizeof(prEvent->aucTxQuality)); + prStaStatistics->ucTxRateUpPenalty = + prEvent->ucTxRateUpPenalty; + prStaStatistics->ucLowTrafficMode = + prEvent->ucLowTrafficMode; + prStaStatistics->ucLowTrafficCount = + prEvent->ucLowTrafficCount; + prStaStatistics->ucLowTrafficDashBoard = + prEvent->ucLowTrafficDashBoard; + prStaStatistics->ucDynamicSGIState = + prEvent->ucDynamicSGIState; + prStaStatistics->ucDynamicSGIScore = + prEvent->ucDynamicSGIScore; + prStaStatistics->ucDynamicBWState = + prEvent->ucDynamicBWState; + prStaStatistics->ucDynamicGband256QAMState = + prEvent->ucDynamicGband256QAMState; + prStaStatistics->ucVhtNonSpRateState = + prEvent->ucVhtNonSpRateState; +#endif + prStaRec = cnmGetStaRecByIndex(prAdapter, + prEvent->ucStaRecIdx); + + if (prStaRec) { + /*link layer statistics */ + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; + eAci++) { + prStaStatistics->arLinkStatistics[eAci]. + u4TxFailMsdu = + prEvent->arLinkStatistics[eAci]. + u4TxFailMsdu; + prStaStatistics->arLinkStatistics[eAci]. + u4TxRetryMsdu = + prEvent->arLinkStatistics[eAci]. + u4TxRetryMsdu; + + /*for dump bss statistics */ + prStaRec->arLinkStatistics[eAci]. + u4TxFailMsdu = + prEvent->arLinkStatistics[eAci]. + u4TxFailMsdu; + prStaRec->arLinkStatistics[eAci]. + u4TxRetryMsdu = + prEvent->arLinkStatistics[eAci]. + u4TxRetryMsdu; + } + } + if (prEvent->u4TxCount) { + uint32_t u4TxDoneAirTimeMs = + USEC_TO_MSEC(prEvent->u4TxDoneAirTime * + 32); + + prStaStatistics->u4TxAverageAirTime = + (u4TxDoneAirTimeMs / + prEvent->u4TxCount); + } else { + prStaStatistics->u4TxAverageAirTime = 0; + } + +#if CFG_ENABLE_PER_STA_STATISTICS_LOG +#if CFG_SUPPORT_WFD + /* dump statistics for WFD */ + if (prAdapter->rWifiVar + .rWfdConfigureSettings.ucWfdEnable == 1) { + uint32_t u4LinkScore = 0; + uint32_t u4TotalError = + prStaStatistics->u4TxFailCount + + prStaStatistics->u4TxLifeTimeoutCount; + uint32_t u4TxExceedThresholdCount = + prStaStatistics->u4TxExceedThresholdCount; + uint32_t u4TxTotalCount = + prStaStatistics->u4TxTotalCount; + + /* Calcute Link Score + * u4LinkScore 10~100 , + * ExceedThreshold ratio 0~90 only + * u4LinkScore 0~9 + * Drop packet ratio 0~9 and + * all packets exceed threshold + */ + if (u4TxTotalCount) { + if (u4TxExceedThresholdCount <= u4TxTotalCount) + u4LinkScore = (90 - + ((u4TxExceedThresholdCount * 90) + / u4TxTotalCount)); + else + u4LinkScore = 0; + } else + u4LinkScore = 90; + + u4LinkScore += 10; + if (u4LinkScore == 10) { + if (u4TotalError <= u4TxTotalCount) + u4LinkScore = (10 - + ((u4TotalError * 10) / + u4TxTotalCount)); + else + u4LinkScore = 0; + } + + if (u4LinkScore > 100) + u4LinkScore = 100; + + prAdapter->rWifiVar.rWfdConfigureSettings.u4LinkScore + = u4LinkScore; + + log_dbg(P2P, INFO, + "[%u][%u] link_score=%u, rssi=%u, rate=%u, threshold_cnt=%u, fail_cnt=%u\n", + prEvent->ucNetworkTypeIndex, + prEvent->ucStaRecIdx, + u4LinkScore, + prStaStatistics->ucRcpi, + prStaStatistics->u2LinkSpeed, + prStaStatistics->u4TxExceedThresholdCount, + prStaStatistics->u4TxFailCount); + log_dbg(P2P, INFO, "timeout_cnt=%u, apt=%u, aat=%u, total_cnt=%u\n", + prStaStatistics->u4TxLifeTimeoutCount, + prStaStatistics->u4TxAverageProcessTime, + prStaStatistics->u4TxAverageAirTime, + prStaStatistics->u4TxTotalCount); + } +#endif +#endif +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + prLinkQualityInfo = &(prAdapter->rLinkQualityInfo); + prLinkQualityInfo->u4CurTxRate = prEvent->u2LinkSpeed * 5; +#endif + } + + if (prCmdInfo->fgIsOid) + kalOidComplete(prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called when event for query LTE safe channels + * has been retrieved + * + * @param prAdapter Pointer to the Adapter structure. + * @param prCmdInfo Pointer to the command information + * @param pucEventBuf Pointer to the event buffer + * + * @return none + */ +/*----------------------------------------------------------------------------*/ +void nicCmdEventQueryLteSafeChn(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + struct EVENT_LTE_SAFE_CHN *prEvent; + struct PARAM_GET_CHN_INFO *prLteSafeChnInfo; + uint8_t ucIdx = 0; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo; + + if ((prAdapter == NULL) || (prCmdInfo == NULL) || (pucEventBuf == NULL) + || (prCmdInfo->pvInformationBuffer == NULL)) { + ASSERT(FALSE); + return; + } + + prEvent = (struct EVENT_LTE_SAFE_CHN *) pucEventBuf; + + prLteSafeChnInfo = (struct PARAM_GET_CHN_INFO *) + prCmdInfo->pvInformationBuffer; + + if (prLteSafeChnInfo->ucRoleIndex >= BSS_P2P_NUM) { + ASSERT(FALSE); + kalMemFree(prLteSafeChnInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_GET_CHN_INFO)); + return; + } + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prLteSafeChnInfo->ucRoleIndex); + if (prP2pRoleFsmInfo == NULL) { + DBGLOG(P2P, ERROR, + "Corresponding P2P Role FSM empty: %d.\n", + prLteSafeChnInfo->ucRoleIndex); + kalMemFree(prLteSafeChnInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_GET_CHN_INFO)); + return; + } + + /* Statistics from FW is valid */ + if (prEvent->u4Flags & BIT(0)) { + struct LTE_SAFE_CHN_INFO *prLteSafeChnList; + + prLteSafeChnList = &prLteSafeChnInfo->rLteSafeChnList; + for (ucIdx = 0; ucIdx < + ENUM_SAFE_CH_MASK_MAX_NUM; + ucIdx++) { + prLteSafeChnList->au4SafeChannelBitmask[ucIdx] + = prEvent->rLteSafeChn. + au4SafeChannelBitmask[ucIdx]; + + DBGLOG(NIC, INFO, + "[ACS]LTE safe channels[%d]=0x%08x\n", + ucIdx, + prLteSafeChnList->au4SafeChannelBitmask[ucIdx]); + } + } else { + DBGLOG(NIC, ERROR, "FW's event is NOT valid.\n"); + } + p2pFunProcessAcsReport(prAdapter, + prLteSafeChnInfo->ucRoleIndex, + prLteSafeChnInfo, + &(prP2pRoleFsmInfo->rAcsReqInfo)); + kalMemFree(prLteSafeChnInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_GET_CHN_INFO)); +} + +void nicEventRddPulseDump(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + uint16_t u2Idx, u2PulseCnt; + struct EVENT_WIFI_RDD_TEST *prRddPulseEvent; + + ASSERT(prAdapter); + ASSERT(pucEventBuf); + + prRddPulseEvent = (struct EVENT_WIFI_RDD_TEST *) ( + pucEventBuf); + + u2PulseCnt = (prRddPulseEvent->u4FuncLength - + RDD_EVENT_HDR_SIZE) / RDD_ONEPLUSE_SIZE; + + DBGLOG(INIT, INFO, "[RDD]0x%08x %08d[RDD%d]\n", + prRddPulseEvent->u4Prefix + , prRddPulseEvent->u4Count, prRddPulseEvent->ucRddIdx); + + for (u2Idx = 0; u2Idx < u2PulseCnt; u2Idx++) { + DBGLOG(INIT, INFO, + "[RDD]0x%02x%02x%02x%02x %02x%02x%02x%02x[RDD%d]\n" + , prRddPulseEvent->aucBuffer[RDD_ONEPLUSE_SIZE * u2Idx + + RDD_PULSE_OFFSET3] + , prRddPulseEvent->aucBuffer[RDD_ONEPLUSE_SIZE * u2Idx + + RDD_PULSE_OFFSET2] + , prRddPulseEvent->aucBuffer[RDD_ONEPLUSE_SIZE * u2Idx + + RDD_PULSE_OFFSET1] + , prRddPulseEvent->aucBuffer[RDD_ONEPLUSE_SIZE * u2Idx + + RDD_PULSE_OFFSET0] + , prRddPulseEvent->aucBuffer[RDD_ONEPLUSE_SIZE * u2Idx + + RDD_PULSE_OFFSET7] + , prRddPulseEvent->aucBuffer[RDD_ONEPLUSE_SIZE * u2Idx + + RDD_PULSE_OFFSET6] + , prRddPulseEvent->aucBuffer[RDD_ONEPLUSE_SIZE * u2Idx + + RDD_PULSE_OFFSET5] + , prRddPulseEvent->aucBuffer[RDD_ONEPLUSE_SIZE * u2Idx + + RDD_PULSE_OFFSET4] + , prRddPulseEvent->ucRddIdx + ); + } + +} + +#if CFG_SUPPORT_MSP +void nicCmdEventQueryWlanInfo(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct PARAM_HW_WLAN_INFO *prWlanInfo; + struct EVENT_WLAN_INFO *prEventWlanInfo; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventWlanInfo = (struct EVENT_WLAN_INFO *) pucEventBuf; + + DBGLOG(RSN, INFO, "MT6632 : nicCmdEventQueryWlanInfo\n"); + + prGlueInfo = prAdapter->prGlueInfo; + + u4QueryInfoLen = sizeof(struct PARAM_HW_WLAN_INFO); + prWlanInfo = (struct PARAM_HW_WLAN_INFO *) + prCmdInfo->pvInformationBuffer; + + /* prWlanInfo->u4Length = sizeof(PARAM_HW_WLAN_INFO_T); */ + if (prEventWlanInfo && prWlanInfo) { + kalMemCopy(&prWlanInfo->rWtblTxConfig, + &prEventWlanInfo->rWtblTxConfig, + sizeof(struct PARAM_TX_CONFIG)); + kalMemCopy(&prWlanInfo->rWtblSecConfig, + &prEventWlanInfo->rWtblSecConfig, + sizeof(struct PARAM_SEC_CONFIG)); + kalMemCopy(&prWlanInfo->rWtblKeyConfig, + &prEventWlanInfo->rWtblKeyConfig, + sizeof(struct PARAM_KEY_CONFIG)); + kalMemCopy(&prWlanInfo->rWtblRateInfo, + &prEventWlanInfo->rWtblRateInfo, + sizeof(struct PARAM_PEER_RATE_INFO)); + kalMemCopy(&prWlanInfo->rWtblBaConfig, + &prEventWlanInfo->rWtblBaConfig, + sizeof(struct PARAM_PEER_BA_CONFIG)); + kalMemCopy(&prWlanInfo->rWtblPeerCap, + &prEventWlanInfo->rWtblPeerCap, + sizeof(struct PARAM_PEER_CAP)); + kalMemCopy(&prWlanInfo->rWtblRxCounter, + &prEventWlanInfo->rWtblRxCounter, + sizeof(struct PARAM_PEER_RX_COUNTER_ALL)); + kalMemCopy(&prWlanInfo->rWtblTxCounter, + &prEventWlanInfo->rWtblTxCounter, + sizeof(struct PARAM_PEER_TX_COUNTER_ALL)); + } + + if (prCmdInfo->fgIsOid) + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); +} + + +void nicCmdEventQueryMibInfo(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct PARAM_HW_MIB_INFO *prMibInfo; + struct EVENT_MIB_INFO *prEventMibInfo; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventMibInfo = (struct EVENT_MIB_INFO *) pucEventBuf; + + DBGLOG(RSN, INFO, "MT6632 : nicCmdEventQueryMibInfo\n"); + + prGlueInfo = prAdapter->prGlueInfo; + + u4QueryInfoLen = sizeof(struct PARAM_HW_MIB_INFO); + prMibInfo = (struct PARAM_HW_MIB_INFO *) + prCmdInfo->pvInformationBuffer; + if (prEventMibInfo && prMibInfo) { + kalMemCopy(&prMibInfo->rHwMibCnt, + &prEventMibInfo->rHwMibCnt, + sizeof(struct HW_MIB_COUNTER)); + kalMemCopy(&prMibInfo->rHwMib2Cnt, + &prEventMibInfo->rHwMib2Cnt, + sizeof(struct HW_MIB2_COUNTER)); + kalMemCopy(&prMibInfo->rHwTxAmpduMts, + &prEventMibInfo->rHwTxAmpduMts, + sizeof(struct HW_TX_AMPDU_METRICS)); + } + + if (prCmdInfo->fgIsOid) + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); +} +#endif + +uint32_t nicEventQueryTxResourceEntry(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct NIC_TX_RESOURCE *prTxResource; + uint32_t version = *((uint32_t *)pucEventBuf); + + + prAdapter->fgIsNicTxReousrceValid = TRUE; + + if (version & NIC_TX_RESOURCE_REPORT_VERSION_PREFIX) + return nicEventQueryTxResource(prAdapter, pucEventBuf); + + /* 6632, 7668 ways */ + prAdapter->nicTxReousrce.txResourceInit = NULL; + + prTxResource = (struct NIC_TX_RESOURCE *)pucEventBuf; + prAdapter->nicTxReousrce.u4CmdTotalResource = + prTxResource->u4CmdTotalResource; + prAdapter->nicTxReousrce.u4CmdResourceUnit = + prTxResource->u4CmdResourceUnit; + prAdapter->nicTxReousrce.u4DataTotalResource = + prTxResource->u4DataTotalResource; + prAdapter->nicTxReousrce.u4DataResourceUnit = + prTxResource->u4DataResourceUnit; + + DBGLOG(INIT, INFO, + "nicCmdEventQueryNicTxResource: u4CmdTotalResource = %x\n", + prAdapter->nicTxReousrce.u4CmdTotalResource); + DBGLOG(INIT, INFO, + "nicCmdEventQueryNicTxResource: u4CmdResourceUnit = %x\n", + prAdapter->nicTxReousrce.u4CmdResourceUnit); + DBGLOG(INIT, INFO, + "nicCmdEventQueryNicTxResource: u4DataTotalResource = %x\n", + prAdapter->nicTxReousrce.u4DataTotalResource); + DBGLOG(INIT, INFO, + "nicCmdEventQueryNicTxResource: u4DataResourceUnit = %x\n", + prAdapter->nicTxReousrce.u4DataResourceUnit); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t nicCmdEventQueryNicEfuseAddr(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct NIC_EFUSE_ADDRESS *prTxResource = + (struct NIC_EFUSE_ADDRESS *)pucEventBuf; + + prAdapter->u4EfuseStartAddress = + prTxResource->u4EfuseStartAddress; + prAdapter->u4EfuseEndAddress = + prTxResource->u4EfuseEndAddress; + + DBGLOG(INIT, INFO, + "nicCmdEventQueryNicEfuseAddr: u4EfuseStartAddress = %x\n", + prAdapter->u4EfuseStartAddress); + DBGLOG(INIT, INFO, + "nicCmdEventQueryNicEfuseAddr: u4EfuseEndAddress = %x\n", + prAdapter->u4EfuseEndAddress); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t nicCmdEventQueryNicCoexFeature(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct NIC_COEX_FEATURE *prCoexFeature = + (struct NIC_COEX_FEATURE *)pucEventBuf; + + prAdapter->u4FddMode = prCoexFeature->u4FddMode; + + DBGLOG(INIT, INFO, + "nicCmdEventQueryNicCoexFeature: u4FddMode = %x\n", + prAdapter->u4FddMode); + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +uint32_t nicCmdEventQueryNicCsumOffload(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct NIC_CSUM_OFFLOAD *prChecksumOffload = + (struct NIC_CSUM_OFFLOAD *)pucEventBuf; + + prAdapter->fgIsSupportCsumOffload = + prChecksumOffload->ucIsSupportCsumOffload; + + DBGLOG(INIT, INFO, + "nicCmdEventQueryNicCsumOffload: ucIsSupportCsumOffload = %x\n", + prAdapter->fgIsSupportCsumOffload); + + return WLAN_STATUS_SUCCESS; +} +#endif + +uint32_t nicCfgChipCapHwVersion(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct mt66xx_chip_info *prChipInfo = NULL; + struct CAP_HW_VERSION *prHwVer = + (struct CAP_HW_VERSION *)pucEventBuf; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + ASSERT(prChipInfo); + + prAdapter->rVerInfo.u2FwProductID = prHwVer->u2ProductID; + prChipInfo->u4ChipIpConfig = prHwVer->u4ConfigId; + prChipInfo->u4ChipIpVersion = prHwVer->u4TopIpID; + + return WLAN_STATUS_SUCCESS; +} + +uint32_t nicCfgChipAdieHwVersion(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct mt66xx_chip_info *prChipInfo = NULL; + struct CAP_HW_ADIE_VERSION *prAdieHwVer = + (struct CAP_HW_ADIE_VERSION *)pucEventBuf; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + ASSERT(prChipInfo); + + prChipInfo->u2ADieChipVersion = prAdieHwVer->u2ProductID; + DBGLOG(INIT, INFO, "A DieID = 0x%x\n", prAdieHwVer->u2ProductID); + return WLAN_STATUS_SUCCESS; +} + + +uint32_t nicCfgChipCapSwVersion(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct CAP_SW_VERSION *prSwVer = + (struct CAP_SW_VERSION *)pucEventBuf; + + prAdapter->rVerInfo.u2FwOwnVersion = prSwVer->u2FwVersion; + prAdapter->rVerInfo.ucFwBuildNumber = + prSwVer->u2FwBuildNumber; + kalMemCopy(prAdapter->rVerInfo.aucFwBranchInfo, + prSwVer->aucBranchInfo, 4); + kalMemCopy(prAdapter->rVerInfo.aucFwDateCode, + prSwVer->aucDateCode, 16); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t nicCfgChipCapMacAddr(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct CAP_MAC_ADDR *prMacAddr = (struct CAP_MAC_ADDR *)pucEventBuf; + uint8_t aucZeroMacAddr[] = NULL_MAC_ADDR; + + COPY_MAC_ADDR(prAdapter->rWifiVar.aucPermanentAddress, + prMacAddr->aucMacAddr); + COPY_MAC_ADDR(prAdapter->rWifiVar.aucMacAddress, + prMacAddr->aucMacAddr); + prAdapter->fgIsEmbbededMacAddrValid = (u_int8_t) ( + !IS_BMCAST_MAC_ADDR(prMacAddr->aucMacAddr) && + !EQUAL_MAC_ADDR(aucZeroMacAddr, prMacAddr->aucMacAddr)); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t nicCfgChipCapPhyCap(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct CAP_PHY_CAP *prPhyCap = (struct CAP_PHY_CAP *)pucEventBuf; + + prAdapter->rWifiVar.ucStaVht &= prPhyCap->ucVht; + wlanCfgSetUint32(prAdapter, "StaVHT", prAdapter->rWifiVar.ucStaVht); + if (prAdapter->rWifiVar.ucApVht != FEATURE_FORCE_ENABLED) { + prAdapter->rWifiVar.ucApVht &= prPhyCap->ucVht; + wlanCfgSetUint32(prAdapter, "ApVHT", + prAdapter->rWifiVar.ucApVht); + } + prAdapter->rWifiVar.ucP2pGoVht &= prPhyCap->ucVht; + wlanCfgSetUint32(prAdapter, "P2pGoVHT", prAdapter->rWifiVar.ucP2pGoVht); + prAdapter->rWifiVar.ucP2pGcVht &= prPhyCap->ucVht; + wlanCfgSetUint32(prAdapter, "P2pGcVHT", prAdapter->rWifiVar.ucP2pGcVht); + prAdapter->fgIsHw5GBandDisabled = !prPhyCap->uc5gBand; + prAdapter->rWifiVar.ucNSS = (prPhyCap->ucNss > + prAdapter->rWifiVar.ucNSS) ? + (prAdapter->rWifiVar.ucNSS):(prPhyCap->ucNss); + wlanCfgSetUint32(prAdapter, "Nss", prAdapter->rWifiVar.ucNSS); +#if CFG_SUPPORT_DBDC + if (!prPhyCap->ucDbdc) { + prAdapter->rWifiVar.eDbdcMode = ENUM_DBDC_MODE_DISABLED; + wlanCfgSetUint32(prAdapter, "DbdcMode", + prAdapter->rWifiVar.eDbdcMode); + } else if (prPhyCap->ucWifiPath + == (WLAN_FLAG_2G4_WF0 | WLAN_FLAG_5G_WF1)) { + prAdapter->rWifiVar.eDbdcMode = ENUM_DBDC_MODE_STATIC; + wlanCfgSetUint32(prAdapter, "DbdcMode", + prAdapter->rWifiVar.eDbdcMode); + } +#endif + prAdapter->rWifiVar.ucTxLdpc &= prPhyCap->ucTxLdpc; + wlanCfgSetUint32(prAdapter, "LdpcTx", prAdapter->rWifiVar.ucTxLdpc); + prAdapter->rWifiVar.ucRxLdpc &= prPhyCap->ucRxLdpc; + wlanCfgSetUint32(prAdapter, "LdpcRx", prAdapter->rWifiVar.ucRxLdpc); + prAdapter->rWifiVar.ucTxStbc &= prPhyCap->ucTxStbc; + wlanCfgSetUint32(prAdapter, "StbcTx", prAdapter->rWifiVar.ucTxStbc); + prAdapter->rWifiVar.ucRxStbc &= prPhyCap->ucRxStbc; + wlanCfgSetUint32(prAdapter, "StbcRx", prAdapter->rWifiVar.ucRxStbc); + + + if ((prPhyCap->ucWifiPath != 0xF) && (prPhyCap->ucWifiPath != 0x3)) { + /* May be legal settings in the future */ + DBGLOG(INIT, ERROR, "illegle ucWifiPath %x\n", + prPhyCap->ucWifiPath); + } else { /* 0xF = 2*2, 0x3 = 1*1 */ + DBGLOG(INIT, TRACE, "ucWifiPath %x\n", + prPhyCap->ucWifiPath); + } + /* Overwirte driver default setting here */ + prAdapter->rWifiFemCfg.u2WifiPath = prPhyCap->ucWifiPath; + + +#if (CFG_SUPPORT_802_11AX == 1) + prAdapter->rWifiVar.ucStaHe &= prPhyCap->ucHe; + wlanCfgSetUint32(prAdapter, "StaHE", prAdapter->rWifiVar.ucStaHe); + prAdapter->rWifiVar.ucApHe &= prPhyCap->ucHe; + wlanCfgSetUint32(prAdapter, "ApHE", prAdapter->rWifiVar.ucApHe); + prAdapter->rWifiVar.ucP2pGoHe &= prPhyCap->ucHe; + wlanCfgSetUint32(prAdapter, "P2pGoHE", prAdapter->rWifiVar.ucP2pGoHe); + prAdapter->rWifiVar.ucP2pGcHe &= prPhyCap->ucHe; + wlanCfgSetUint32(prAdapter, "P2pGcHE", prAdapter->rWifiVar.ucP2pGcHe); + if (prAdapter->rWifiVar.ucStaHe & BIT(0)) { /* (wifi.cfg & chip cap) */ + fgEfuseCtrlAxOn = 1; /* default is 0 */ + } +#endif + + DBGLOG(INIT, TRACE, + "Vht [%u] He[%u] 5gBand [%d], Nss [%d], Dbdc [%d]\n", + prPhyCap->ucVht, + prPhyCap->ucHe, + prPhyCap->uc5gBand, + prPhyCap->ucNss, + prPhyCap->ucDbdc); + + DBGLOG(INIT, TRACE, + "TxLdpc [%u], RxLdpc [%u], StbcTx [%u], StbcRx [%u], WifiPath [%x]\n", + prPhyCap->ucTxLdpc, + prPhyCap->ucRxLdpc, + prPhyCap->ucTxStbc, + prPhyCap->ucRxStbc, + prPhyCap->ucWifiPath); + + + return WLAN_STATUS_SUCCESS; +} + +#if (CFG_SUPPORT_P2PGO_ACS == 1) +uint32_t nicCfgChipP2PCap(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ +#if 0 + struct CAP_PHY_CAP *prPhyCap = + (struct CAP_PHY_CAP *)pucEventBuf; + prAdapter->rWifiVar.ucStaVht &= prPhyCap->ucVht; +#endif + wlanCfgSetUint32(prAdapter, "P2pGoACSEnable", + prAdapter->rWifiVar.ucP2pGoACS); + DBGLOG(INIT, INFO, "P2pGoACSEnable:ACS Enable[%d]\n", + prAdapter->rWifiVar.ucP2pGoACS); + return WLAN_STATUS_SUCCESS; + } +#endif + +uint32_t nicCmdEventHostStatusEmiOffset(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct NIC_HOST_STATUS_EMI_OFFSET *prOffset = + (struct NIC_HOST_STATUS_EMI_OFFSET *)pucEventBuf; + + prAdapter->u4HostStatusEmiOffset = prOffset->u4EmiOffset; + + DBGLOG(INIT, INFO, + "EMI offset= %x\n", + prAdapter->u4HostStatusEmiOffset); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t nicCfgChipCapMacCap(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct CAP_MAC_CAP *prMacCap = (struct CAP_MAC_CAP *)pucEventBuf; + + if (prMacCap->ucHwBssIdNum > 0 + && prMacCap->ucHwBssIdNum <= MAX_BSSID_NUM) { + prAdapter->ucHwBssIdNum = prMacCap->ucHwBssIdNum; + prAdapter->ucP2PDevBssIdx = prAdapter->ucHwBssIdNum; + prAdapter->aprBssInfo[prAdapter->ucP2PDevBssIdx] = + &prAdapter->rWifiVar.rP2pDevInfo; + } + + if (prMacCap->ucWtblEntryNum > 0 + && prMacCap->ucWtblEntryNum <= WTBL_SIZE) { + prAdapter->ucWtblEntryNum = prMacCap->ucWtblEntryNum; + prAdapter->ucTxDefaultWlanIndex = prAdapter->ucWtblEntryNum + - 1; + } + + prAdapter->ucWmmSetNum = prMacCap->ucWmmSet > 0 ? + prMacCap->ucWmmSet : 1; + DBGLOG(INIT, INFO, + "ucHwBssIdNum: %d, ucWtblEntryNum: %d, ucWmmSetNum: %d.\n", + prMacCap->ucHwBssIdNum, + prMacCap->ucWtblEntryNum, + prMacCap->ucWmmSet); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t nicCfgChipCapFrameBufCap(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + return WLAN_STATUS_SUCCESS; +} + +uint32_t nicCfgChipCapBeamformCap(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + return WLAN_STATUS_SUCCESS; +} + +uint32_t nicCfgChipCapLocationCap(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + return WLAN_STATUS_SUCCESS; +} + +uint32_t nicCfgChipCapMuMimoCap(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + return WLAN_STATUS_SUCCESS; +} + +#if CFG_SUPPORT_ANT_SWAP +uint32_t nicCfgChipCapAntSwpCap(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct CAP_ANTSWP *prAntSwpCap = (struct CAP_ANTSWP *)pucEventBuf; + + /* FW's value combines both platform and FW capablity */ + prAdapter->fgIsSupportAntSwp = prAntSwpCap->ucIsSupported; + DBGLOG(INIT, INFO, + "fgIsSupportAntSwp = %d\n", + prAdapter->fgIsSupportAntSwp); + + return WLAN_STATUS_SUCCESS; +} +#endif /* CFG_SUPPORT_ANT_SWAP */ + +struct nicTxRsrcEvtHdlr nicTxRsrcEvtHdlrTbl[] = { + {NIC_TX_RESOURCE_REPORT_VERSION_1, + nicEventQueryTxResource_v1, + nicTxResourceUpdate_v1}, +}; + +uint32_t nicEventQueryTxResource(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf) +{ + uint32_t i, i_max; + uint32_t version = *((uint32_t *)(pucEventBuf)); + + i_max = sizeof(nicTxRsrcEvtHdlrTbl) / sizeof( + struct nicTxRsrcEvtHdlr); + for (i = 0; i < i_max; i += 2) { + if (version == nicTxRsrcEvtHdlrTbl[i].u4Version) { + /* assign callback to do the resource init. */ + prAdapter->nicTxReousrce.txResourceInit = + nicTxRsrcEvtHdlrTbl[i].nicTxResourceInit; + + return nicTxRsrcEvtHdlrTbl[i].nicEventTxResource( + prAdapter, pucEventBuf); + } + } + + /* invalid version, cannot find the handler */ + DBGLOG(INIT, ERROR, + "nicEventQueryTxResource(): Invaalid version.\n"); + prAdapter->nicTxReousrce.txResourceInit = NULL; + + return WLAN_STATUS_NOT_SUPPORTED; +} + +uint32_t nicEventQueryTxResource_v1(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf) +{ + struct tx_resource_report_v1 *pV1 = + (struct tx_resource_report_v1 *)pucEventBuf; + uint16_t page_size; + + /* PSE */ + page_size = pV1->u4PlePsePageSize & 0xFFFF; + prAdapter->nicTxReousrce.u4CmdTotalResource = + pV1->u4HifCmdPsePageQuota; + prAdapter->nicTxReousrce.u4CmdResourceUnit = page_size; + prAdapter->nicTxReousrce.u4DataTotalResource = + pV1->u4HifDataPsePageQuota; + prAdapter->nicTxReousrce.u4DataResourceUnit = page_size; + + /* PLE */ + page_size = (pV1->u4PlePsePageSize >> 16) & 0xFFFF; + prAdapter->nicTxReousrce.u4CmdTotalResourcePle = + pV1->u4HifCmdPlePageQuota; + prAdapter->nicTxReousrce.u4CmdResourceUnitPle = page_size; + prAdapter->nicTxReousrce.u4DataTotalResourcePle = + pV1->u4HifDataPlePageQuota; + prAdapter->nicTxReousrce.u4DataResourceUnitPle = page_size; + + /* PpTxAddCnt */ + prAdapter->nicTxReousrce.ucPpTxAddCnt = pV1->ucPpTxAddCnt; + + /* enable PLE resource control flag */ + if (!prAdapter->nicTxReousrce.u4DataTotalResourcePle) + prAdapter->rTxCtrl.rTc.fgNeedPleCtrl = FALSE; + else + prAdapter->rTxCtrl.rTc.fgNeedPleCtrl = + NIC_TX_RESOURCE_CTRL_PLE; + return WLAN_STATUS_SUCCESS; +} + +void nicCmdEventQueryNicCapabilityV2(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct EVENT_NIC_CAPABILITY_V2 *prEventNicV2 = + (struct EVENT_NIC_CAPABILITY_V2 *)pucEventBuf; + struct NIC_CAPABILITY_V2_ELEMENT *prElement; + uint32_t tag_idx, table_idx, offset; + + offset = 0; + + /* process each element */ + for (tag_idx = 0; tag_idx < prEventNicV2->u2TotalElementNum; + tag_idx++) { + + prElement = (struct NIC_CAPABILITY_V2_ELEMENT *)( + prEventNicV2->aucBuffer + offset); + + for (table_idx = 0; + table_idx < (sizeof(gNicCapabilityV2InfoTable) / sizeof( + struct NIC_CAPABILITY_V2_REF_TABLE)); + table_idx++) { + + /* find the corresponding tag's handler */ + if (gNicCapabilityV2InfoTable[table_idx].tag_type == + prElement->tag_type) { + gNicCapabilityV2InfoTable[table_idx].hdlr( + prAdapter, prElement->aucbody); + break; + } + } + + /* move to the next tag */ + offset += prElement->body_len + (uint16_t) OFFSET_OF( + struct NIC_CAPABILITY_V2_ELEMENT, aucbody); + } + +} + +#if (CFG_SUPPORT_TXPOWER_INFO == 1) +void nicCmdEventQueryTxPowerInfo(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + struct EXT_EVENT_TXPOWER_ALL_RATE_POWER_INFO_T *prEvent = + NULL; + struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T *prTxPowerInfo = + NULL; + uint32_t u4QueryInfoLen = 0; + struct GLUE_INFO *prGlueInfo = NULL; + + if (!prAdapter) + return; + + prGlueInfo = prAdapter->prGlueInfo; + if (!prCmdInfo) + return; + if (!pucEventBuf) + return; + if (!(prCmdInfo->pvInformationBuffer)) + return; + + if (prCmdInfo->fgIsOid) { + prEvent = (struct EXT_EVENT_TXPOWER_ALL_RATE_POWER_INFO_T *) + pucEventBuf; + + if (prEvent->ucTxPowerCategory == + TXPOWER_EVENT_SHOW_ALL_RATE_TXPOWER_INFO) { + prEvent = + (struct + EXT_EVENT_TXPOWER_ALL_RATE_POWER_INFO_T *) + pucEventBuf; + prTxPowerInfo = + (struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T *) + prCmdInfo->pvInformationBuffer; + u4QueryInfoLen = + sizeof( + struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T); + + kalMemCopy(prTxPowerInfo, prEvent, + sizeof( + struct EXT_EVENT_TXPOWER_ALL_RATE_POWER_INFO_T)); + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} +#endif + +void nicEventLinkQuality(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct mt66xx_chip_info *prChipInfo = NULL; + struct CMD_INFO *prCmdInfo; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + +#if CFG_ENABLE_WIFI_DIRECT && CFG_SUPPORT_P2P_RSSI_QUERY + if (prEvent->u2PacketLen == prChipInfo->event_hdr_size + + sizeof(struct EVENT_LINK_QUALITY_EX)) { + struct EVENT_LINK_QUALITY_EX *prLqEx = + (struct EVENT_LINK_QUALITY_EX *) (prEvent->aucBuffer); + + if (prLqEx->ucIsLQ0Rdy) + nicUpdateLinkQuality(prAdapter, 0, + (struct LINK_QUALITY *) prLqEx); + if (prLqEx->ucIsLQ1Rdy) + nicUpdateLinkQuality(prAdapter, 1, + (struct 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, 0, + (struct LINK_QUALITY *) (prEvent->aucBuffer)); + } +#else + /*only support ais query */ + { + struct BSS_INFO *prBssInfo; + + for (ucBssIndex = 0; ucBssIndex < prAdapter->ucHwBssIdNum; + ucBssIndex++) { + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + if (IS_BSS_AIS(prBssInfo) && + prBssInfo->fgIsInUse) { + nicUpdateLinkQuality(prAdapter, ucBssIndex, + (struct 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 >= (int32_t) ( + prAdapter->rLinkQuality.rLq[ucBssIndex].cRssi)) { + + prAdapter->rWlanInfo.eRssiTriggerType = + ENUM_RSSI_TRIGGER_TRIGGERED; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (void *) &(prAdapter->rWlanInfo.rRssiTriggerValue), + sizeof(int32_t), + ucBssIndex); + } else if (prAdapter->rWlanInfo.eRssiTriggerType == + ENUM_RSSI_TRIGGER_LESS && + prAdapter->rWlanInfo.rRssiTriggerValue <= (int32_t) ( + prAdapter->rLinkQuality.rLq[ucBssIndex].cRssi)) { + + prAdapter->rWlanInfo.eRssiTriggerType = + ENUM_RSSI_TRIGGER_TRIGGERED; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (void *) &(prAdapter->rWlanInfo.rRssiTriggerValue), + sizeof(int32_t), + ucBssIndex); + } +#endif +} + +uint32_t nicExtTsfRawData2IqFmt( + struct EXT_EVENT_RBIST_DUMP_DATA_T *prEventDumpMem, + struct ICAP_INFO_T *prIcap) +{ + static uint8_t + aucPathWF0[40]; /* the path for iq data dump out */ + static uint8_t + aucPathWF1[40]; /* the path for iq data dump out */ + static uint8_t + aucPathRAWWF0[40]; /* the path for iq data dump out */ + static uint8_t + aucPathRAWWF1[40]; /* the path for iq data dump out */ + uint8_t *pucDataWF0 = NULL; /* the data write into file */ + uint8_t *pucDataWF1 = NULL; /* the data write into file */ + uint8_t *pucDataRAWWF0 = + NULL; /* the data write into file */ + uint8_t *pucDataRAWWF1 = + NULL; /* the data write into file */ + uint32_t u4SrcOffset; /* record the buffer offset */ + uint32_t u4FmtLen = 0; /* bus format length */ + uint32_t u4CpyLen = 0; + uint32_t u4RemainByte; + uint32_t u4DataWBufSize = 150; + uint32_t u4DataRAWWBufSize = 150; + uint32_t u4DataWLenF0 = 0; + uint32_t u4DataWLenF1 = 0; + uint32_t u4DataRAWWLenF0 = 0; + uint32_t u4DataRAWWLenF1 = 0; + u_int8_t fgAppend; + int32_t u4Iqc160WF0Q0, u4Iqc160WF1I1; + /* for alignment. bcs we send 2KB data per packet,*/ + static uint8_t ucDstOffset; + /* the data will not align in 12 bytes case. */ + static uint32_t u4CurTimeTick; + + static union ICAP_BUS_FMT icapBusData; + uint32_t *ptr; + + pucDataWF0 = kmalloc(u4DataWBufSize, GFP_KERNEL); + pucDataWF1 = kmalloc(u4DataWBufSize, GFP_KERNEL); + pucDataRAWWF0 = kmalloc(u4DataRAWWBufSize, GFP_KERNEL); + pucDataRAWWF1 = kmalloc(u4DataRAWWBufSize, GFP_KERNEL); + + + if ((!pucDataWF0) || (!pucDataWF1) || (!pucDataRAWWF0) + || (!pucDataRAWWF1)) { + DBGLOG(INIT, ERROR, "kmalloc failed.\n"); + kfree(pucDataWF0); + kfree(pucDataWF1); + kfree(pucDataRAWWF0); + kfree(pucDataRAWWF1); + ASSERT(-1); + return -1; + } + + fgAppend = TRUE; + if (prEventDumpMem->u4PktNum == 0) { + u4CurTimeTick = kalGetTimeTick(); + /* Store memory dump into sdcard, + * path /sdcard/dump__ + * _.hex + */ +#if defined(LINUX) + + /* if blbist mkdir undre /data/blbist, + * the dump files wouls put on it + */ + kalScnprintf(aucPathWF0, sizeof(aucPathWF0), + "/dump_out_%05hu_WF0.txt", prIcap->u2DumpIndex); + kalScnprintf(aucPathWF1, sizeof(aucPathWF1), + "/dump_out_%05hu_WF1.txt", prIcap->u2DumpIndex); + if (kalCheckPath(aucPathWF0) == -1) { + kalMemSet(aucPathWF0, 0x00, sizeof(aucPathWF0)); + kalScnprintf(aucPathWF0, sizeof(aucPathWF0), + "/data/dump_out_%05hu_WF0.txt", + prIcap->u2DumpIndex); + } else + kalTrunkPath(aucPathWF0); + + if (kalCheckPath(aucPathWF1) == -1) { + kalMemSet(aucPathWF1, 0x00, sizeof(aucPathWF1)); + kalScnprintf(aucPathWF1, sizeof(aucPathWF1), + "/data/dump_out_%05hu_WF1.txt", + prIcap->u2DumpIndex); + } else + kalTrunkPath(aucPathWF1); + + kalScnprintf(aucPathRAWWF0, sizeof(aucPathRAWWF0), + "/dump_RAW_%05hu_WF0.txt", prIcap->u2DumpIndex); + kalScnprintf(aucPathRAWWF1, sizeof(aucPathRAWWF1), + "/dump_RAW_%05hu_WF1.txt", prIcap->u2DumpIndex); + if (kalCheckPath(aucPathRAWWF0) == -1) { + kalMemSet(aucPathRAWWF0, 0x00, sizeof(aucPathRAWWF0)); + kalScnprintf(aucPathRAWWF0, sizeof(aucPathRAWWF0), + "/data/dump_RAW_%05hu_WF0.txt", + prIcap->u2DumpIndex); + } else + kalTrunkPath(aucPathRAWWF0); + + if (kalCheckPath(aucPathRAWWF1) == -1) { + kalMemSet(aucPathRAWWF1, 0x00, sizeof(aucPathRAWWF1)); + kalScnprintf(aucPathRAWWF1, sizeof(aucPathRAWWF1), + "/data/dump_RAW_%hu_WF1.txt", + prIcap->u2DumpIndex); + } else + kalTrunkPath(aucPathRAWWF1); + +#else + /* TODO: check Address */ + kal_sprintf_ddk(aucPathWF0, sizeof(aucPathWF0), + u4CurTimeTick, prEventDumpMem->u4Address, + prEventDumpMem->u4Length + + prEventDumpMem->u4RemainLength); + kal_sprintf_ddk(aucPathWF1, sizeof(aucPathWF1), + u4CurTimeTick, prEventDumpMem->u4Address, + prEventDumpMem->u4Length + + prEventDumpMem->u4RemainLength); +#endif + /* fgAppend = FALSE; */ + } + + ptr = (uint32_t *)(&prEventDumpMem->u4Data); + + for (u4SrcOffset = 0, + u4RemainByte = prEventDumpMem->u4DataLength; + u4RemainByte > 0;) { + u4FmtLen = (prIcap->u4CapNode == ICAP_CONTENT_SPECTRUM) ? + sizeof(struct SPECTRUM_BUS_FMT) : sizeof(union + ICAP_BUS_FMT); + /* 4 bytes : 12 bytes */ + u4CpyLen = (u4RemainByte - u4FmtLen >= 0) ? u4FmtLen : + u4RemainByte; + if ((ucDstOffset + u4CpyLen) > sizeof(icapBusData)) { + DBGLOG(INIT, ERROR, + "ucDstOffset(%u) + u4CpyLen(%u) exceed bound of icapBusData\n", + ucDstOffset, u4CpyLen); + kfree(pucDataWF0); + kfree(pucDataWF1); + kfree(pucDataRAWWF0); + kfree(pucDataRAWWF1); + ASSERT(-1); + return -1; + } + + memcpy((uint8_t *)&icapBusData + ucDstOffset, + &prEventDumpMem->u4Data + u4SrcOffset, u4CpyLen); + if (prIcap->u4CapNode == ICAP_CONTENT_FIIQ + || prIcap->u4CapNode == ICAP_CONTENT_FDIQ) { + u4DataWLenF0 = kalScnprintf(pucDataWF0, u4DataWBufSize, + "%8d,%8d\n", + icapBusData.rIqcBusData.u4Iqc0I, + icapBusData.rIqcBusData.u4Iqc0Q); + u4DataWLenF1 = kalScnprintf(pucDataWF1, u4DataWBufSize, + "%8d,%8d\n", + icapBusData.rIqcBusData.u4Iqc1I, + icapBusData.rIqcBusData.u4Iqc1Q); + } else if (prIcap->u4CapNode - 1000 == ICAP_CONTENT_FIIQ || + prIcap->u4CapNode - 1000 == ICAP_CONTENT_FDIQ) { + u4Iqc160WF0Q0 = icapBusData.rIqc160BusData.u4Iqc0Q0P1 | + (icapBusData.rIqc160BusData.u4Iqc0Q0P2 << 8); + u4Iqc160WF1I1 = icapBusData.rIqc160BusData.u4Iqc1I1P1 | + (icapBusData.rIqc160BusData.u4Iqc1I1P2 << 4); + + u4DataWLenF0 = kalScnprintf(pucDataWF0, u4DataWBufSize, + "%8d,%8d\n%8d,%8d\n", + icapBusData.rIqc160BusData.u4Iqc0I0, + u4Iqc160WF0Q0, + icapBusData.rIqc160BusData.u4Iqc0I1, + icapBusData.rIqc160BusData.u4Iqc0Q1); + + u4DataWLenF1 = kalScnprintf(pucDataWF1, u4DataWBufSize, + "%8d,%8d\n%8d,%8d\n", + icapBusData.rIqc160BusData.u4Iqc1I0, + icapBusData.rIqc160BusData.u4Iqc1Q0, + u4Iqc160WF1I1, + icapBusData.rIqc160BusData.u4Iqc1Q1); + + } else if (prIcap->u4CapNode == ICAP_CONTENT_SPECTRUM) { + u4DataWLenF0 = kalScnprintf(pucDataWF0, u4DataWBufSize, + "%8d,%8d\n", + icapBusData.rSpectrumBusData.u4DcocI, + icapBusData.rSpectrumBusData.u4DcocQ); + } else if (prIcap->u4CapNode == ICAP_CONTENT_ADC) { + u4DataWLenF0 = kalScnprintf(pucDataWF0, u4DataWBufSize, + "%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n", + icapBusData.rPackedAdcBusData.u4AdcI0T0, + icapBusData.rPackedAdcBusData.u4AdcQ0T0, + icapBusData.rPackedAdcBusData.u4AdcI0T1, + icapBusData.rPackedAdcBusData.u4AdcQ0T1, + icapBusData.rPackedAdcBusData.u4AdcI0T2, + icapBusData.rPackedAdcBusData.u4AdcQ0T2, + icapBusData.rPackedAdcBusData.u4AdcI0T3, + icapBusData.rPackedAdcBusData.u4AdcQ0T3, + icapBusData.rPackedAdcBusData.u4AdcI0T4, + icapBusData.rPackedAdcBusData.u4AdcQ0T4, + icapBusData.rPackedAdcBusData.u4AdcI0T5, + icapBusData.rPackedAdcBusData.u4AdcQ0T5); + + u4DataWLenF1 = kalScnprintf(pucDataWF1, u4DataWBufSize, + "%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n", + icapBusData.rPackedAdcBusData.u4AdcI1T0, + icapBusData.rPackedAdcBusData.u4AdcQ1T0, + icapBusData.rPackedAdcBusData.u4AdcI1T1, + icapBusData.rPackedAdcBusData.u4AdcQ1T1, + icapBusData.rPackedAdcBusData.u4AdcI1T2, + icapBusData.rPackedAdcBusData.u4AdcQ1T2, + icapBusData.rPackedAdcBusData.u4AdcI1T3, + icapBusData.rPackedAdcBusData.u4AdcQ1T3, + icapBusData.rPackedAdcBusData.u4AdcI1T4, + icapBusData.rPackedAdcBusData.u4AdcQ1T4, + icapBusData.rPackedAdcBusData.u4AdcI1T5, + icapBusData.rPackedAdcBusData.u4AdcQ1T5); + } else if (prIcap->u4CapNode - 2000 == ICAP_CONTENT_ADC) { + u4DataWLenF0 = kalScnprintf(pucDataWF0, u4DataWBufSize, + "%8d,%8d\n%8d,%8d\n%8d,%8d\n", + icapBusData.rPackedAdcBusData.u4AdcI0T0, + icapBusData.rPackedAdcBusData.u4AdcQ0T0, + icapBusData.rPackedAdcBusData.u4AdcI0T1, + icapBusData.rPackedAdcBusData.u4AdcQ0T1, + icapBusData.rPackedAdcBusData.u4AdcI0T2, + icapBusData.rPackedAdcBusData.u4AdcQ0T2); + + u4DataWLenF1 = kalScnprintf(pucDataWF1, u4DataWBufSize, + "%8d,%8d\n%8d,%8d\n%8d,%8d\n", + icapBusData.rPackedAdcBusData.u4AdcI1T0, + icapBusData.rPackedAdcBusData.u4AdcQ1T0, + icapBusData.rPackedAdcBusData.u4AdcI1T1, + icapBusData.rPackedAdcBusData.u4AdcQ1T1, + icapBusData.rPackedAdcBusData.u4AdcI1T2, + icapBusData.rPackedAdcBusData.u4AdcQ1T2); + } else if (prIcap->u4CapNode == ICAP_CONTENT_TOAE) { + /* actually, this is DCOC. we take TOAE as DCOC */ + u4DataWLenF0 = kalScnprintf(pucDataWF0, u4DataWBufSize, + "%8d,%8d\n", + icapBusData.rAdcBusData.u4Dcoc0I, + icapBusData.rAdcBusData.u4Dcoc0Q); + u4DataWLenF1 = kalScnprintf(pucDataWF1, u4DataWBufSize, + "%8d,%8d\n", + icapBusData.rAdcBusData.u4Dcoc1I, + icapBusData.rAdcBusData.u4Dcoc1Q); + } + if (u4CpyLen == + u4FmtLen) { /* the data format is complete */ + kalWriteToFile(aucPathWF0, fgAppend, pucDataWF0, + u4DataWLenF0); + kalWriteToFile(aucPathWF1, fgAppend, pucDataWF1, + u4DataWLenF1); + } + ptr = (uint32_t *)(&prEventDumpMem->u4Data + u4SrcOffset); + u4DataRAWWLenF0 = kalScnprintf(pucDataRAWWF0, u4DataWBufSize, + "%08x%08x%08x\n", + *(ptr + 2), *(ptr + 1), *ptr); + kalWriteToFile(aucPathRAWWF0, fgAppend, pucDataRAWWF0, + u4DataRAWWLenF0); + kalWriteToFile(aucPathRAWWF1, fgAppend, pucDataRAWWF1, + u4DataRAWWLenF1); + + u4RemainByte -= u4CpyLen; + u4SrcOffset += u4CpyLen; /* shift offset */ + /* only use ucDstOffset at first packet for align 2KB */ + ucDstOffset = 0; + } + /* if this is a last packet, we can't transfer the remain data. + * bcs we can't guarantee the data is complete align data format + */ + if (u4CpyLen != + u4FmtLen) { /* the data format is complete */ + /* not align 2KB, keep the data and next packet data + * will append it + */ + ucDstOffset = u4CpyLen; + } + + kfree(pucDataWF0); + kfree(pucDataWF1); + kfree(pucDataRAWWF0); + kfree(pucDataRAWWF1); + + if (u4RemainByte < 0) { + ASSERT(-1); + return -1; + } + + return 0; +} + +void nicExtEventReCalData(IN struct ADAPTER *prAdapter, IN uint8_t *pucEventBuf) +{ + struct EXT_EVENT_RECAL_DATA_T *prReCalData = NULL; + struct RECAL_INFO_T *prReCalInfo = NULL; + struct RECAL_DATA_T *prCalArray = NULL; + uint32_t u4Idx = 0; + + ASSERT(pucEventBuf); + ASSERT(prAdapter); + prReCalInfo = &prAdapter->rReCalInfo; + if (prReCalInfo->prCalArray == NULL) { + prCalArray = (struct RECAL_DATA_T *)kalMemAlloc( + 2048 * sizeof(struct RECAL_DATA_T), VIR_MEM_TYPE); + + if (prCalArray == NULL) { + DBGLOG(RFTEST, ERROR, + "Unable to alloc memory for recal data\n"); + return; + } + prReCalInfo->prCalArray = prCalArray; + } + + if (prReCalInfo->u4Count >= 2048) { + DBGLOG(RFTEST, ERROR, + "Too many Recal packet, maximum packets will be 2048, ignore\n"); + return; + } + + prCalArray = prReCalInfo->prCalArray; + DBGLOG(RFTEST, INFO, "prCalArray[%d] address [%p]\n", + prReCalInfo->u4Count, + &prCalArray[prReCalInfo->u4Count]); + + prReCalData = (struct EXT_EVENT_RECAL_DATA_T *)pucEventBuf; + switch (prReCalData->u4Type) { + case 0: { + unsigned long ulTmpData; + + prReCalData->u.ucData[9] = '\0'; + prReCalData->u.ucData[19] = '\0'; + u4Idx = prReCalInfo->u4Count; + + if (kalStrtoul(&prReCalData->u.ucData[1], 16, &ulTmpData)) + DBGLOG(RFTEST, ERROR, "convert fail: ucData[1]\n"); + else + prCalArray[u4Idx].u4CalId = (unsigned int)ulTmpData; + if (kalStrtoul(&prReCalData->u.ucData[11], 16, &ulTmpData)) + DBGLOG(RFTEST, ERROR, "convert fail: ucData[11]\n"); + else + prCalArray[u4Idx].u4CalAddr = (unsigned int)ulTmpData; + if (kalStrtoul(&prReCalData->u.ucData[20], 16, &ulTmpData)) + DBGLOG(RFTEST, ERROR, "convert fail: ucData[20] %s\n", + &prReCalData->u.ucData[20]); + else + prCalArray[u4Idx].u4CalValue = (unsigned int)ulTmpData; + + DBGLOG(RFTEST, TRACE, "[0x%08x][0x%08x][0x%08x]\n", + prCalArray[u4Idx].u4CalId, + prCalArray[u4Idx].u4CalAddr, + prCalArray[u4Idx].u4CalValue); + prReCalInfo->u4Count++; + break; + } + case 1: + /* Todo: for extension to handle int */ + /* data directly come from FW */ + break; + } +} + + +void nicExtEventICapIQData(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct EXT_EVENT_RBIST_DUMP_DATA_T *prICapEvent; + uint32_t Idxi = 0, Idxj = 0, Idxk = 0; + struct _RBIST_IQ_DATA_T *prIQArray = NULL; + struct ICAP_INFO_T *prIcapInfo = NULL; + + ASSERT(prAdapter); + ASSERT(pucEventBuf); + + prICapEvent = (struct EXT_EVENT_RBIST_DUMP_DATA_T *) + pucEventBuf; + prIcapInfo = &prAdapter->rIcapInfo; + prIQArray = prIcapInfo->prIQArray; + ASSERT(prIQArray); + + /* If we receive the packet which is delivered from + * last time data-capure, we need to drop it. + */ + DBGLOG(RFTEST, INFO, "prICapEvent->u4PktNum = %d\n", + prICapEvent->u4PktNum); + if (prICapEvent->u4PktNum > prIcapInfo->u4ICapEventCnt) { + if (prICapEvent->u4DataLength == 0) + prIcapInfo->eIcapState = ICAP_STATE_FW_DUMP_DONE; + + DBGLOG(RFTEST, ERROR, + "Packet out of order: Pkt num %d, EventCnt %d\n", + prICapEvent->u4PktNum, prIcapInfo->u4ICapEventCnt); + return; + } + + DBGLOG(RFTEST, INFO, + "u4SmplCnt = [%d], u4WFCnt = [%d], IQArrayIndex = [%d]\n", + prICapEvent->u4SmplCnt, + prICapEvent->u4WFCnt, + prIcapInfo->u4IQArrayIndex); + + if (prICapEvent->u4DataLength != 0 && + prICapEvent->u4SmplCnt * prICapEvent->u4WFCnt * + NUM_OF_CAP_TYPE > ICAP_EVENT_DATA_SAMPLE) { + /* Max count = Total ICAP_EVENT_DATA_SAMPLE count + * and cut into half (I/Q) + */ + prICapEvent->u4SmplCnt = ICAP_EVENT_DATA_SAMPLE / + NUM_OF_CAP_TYPE; + DBGLOG(RFTEST, WARN, + "u4SmplCnt is larger than buffer size\n"); + } + + if (prIcapInfo->u4IQArrayIndex + prICapEvent->u4SmplCnt >= + MAX_ICAP_IQ_DATA_CNT) { + DBGLOG(RFTEST, ERROR, + "Too many packets from FW, skip rest of them\n"); + return; + } + + for (Idxi = 0; Idxi < prICapEvent->u4SmplCnt; Idxi++) { + for (Idxj = 0; Idxj < prICapEvent->u4WFCnt; Idxj++) { + prIQArray[prIcapInfo->u4IQArrayIndex]. + u4IQArray[Idxj][CAP_I_TYPE] = + prICapEvent->u4Data[Idxk++]; + prIQArray[prIcapInfo->u4IQArrayIndex]. + u4IQArray[Idxj][CAP_Q_TYPE] = + prICapEvent->u4Data[Idxk++]; + } + prIcapInfo->u4IQArrayIndex++; + } + + /* Print ICap data to console for debugging purpose */ + for (Idxi = 0; Idxi < prICapEvent->u4SmplCnt; Idxi++) + if (prICapEvent->u4Data[Idxi] == 0) + DBGLOG(RFTEST, WARN, "Data[%d] : %x\n", Idxi, + prICapEvent->u4Data[Idxi]); + + + /* Update ICapEventCnt */ + if (prICapEvent->u4DataLength != 0) + prIcapInfo->u4ICapEventCnt++; + + /* Check whether is the last FW event or not */ + if ((prICapEvent->u4DataLength == 0) + && (prICapEvent->u4PktNum == prIcapInfo->u4ICapEventCnt)) { + /* Reset ICapEventCnt */ + prAdapter->rIcapInfo.eIcapState = ICAP_STATE_FW_DUMP_DONE; + prIcapInfo->u4ICapEventCnt = 0; + DBGLOG(INIT, INFO, ": ==> gen done_file\n"); + } else + prAdapter->rIcapInfo.eIcapState = ICAP_STATE_FW_DUMPING; + +} + +void nicExtEventQueryMemDump(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct EXT_EVENT_RBIST_DUMP_DATA_T *prEventDumpMem; + static uint8_t aucPath[256]; + static uint8_t aucPath_done[300]; + static uint32_t u4CurTimeTick; + + ASSERT(prAdapter); + ASSERT(pucEventBuf); + + kalSprintf(aucPath, "/dump_%05hu.hex", + prAdapter->rIcapInfo.u2DumpIndex); + + prEventDumpMem = (struct EXT_EVENT_RBIST_DUMP_DATA_T *) + pucEventBuf; + + if (kalCheckPath(aucPath) == -1) { + kalMemSet(aucPath, 0x00, 256); + kalSprintf(aucPath, "/data/dump_%05hu.hex", + prAdapter->rIcapInfo.u2DumpIndex); + } + + if (prEventDumpMem->u4PktNum == 0) { + /* Store memory dump into sdcard, + * path /sdcard/dump__ + * _.hex + */ + u4CurTimeTick = kalGetTimeTick(); +#if defined(LINUX) + + /* if blbist mkdir undre /data/blbist, + * the dump files wouls put on it + */ + kalSprintf(aucPath, "/dump_%05hu.hex", + prAdapter->rIcapInfo.u2DumpIndex); + if (kalCheckPath(aucPath) == -1) { + kalMemSet(aucPath, 0x00, 256); + kalSprintf(aucPath, "/data/dump_%05hu.hex", + prAdapter->rIcapInfo.u2DumpIndex); + } +#else + /* TODO: check Address */ + kal_sprintf_ddk(aucPath, sizeof(aucPath), + u4CurTimeTick, prEventDumpMem->u4Address, + prEventDumpMem->u4Length + + prEventDumpMem->u4RemainLength); +#endif + kalWriteToFile(aucPath, FALSE, + (uint8_t *)prEventDumpMem->u4Data, + prEventDumpMem->u4DataLength); + } else { + /* Append current memory dump to the hex file */ + kalWriteToFile(aucPath, TRUE, + (uint8_t *)prEventDumpMem->u4Data, + prEventDumpMem->u4DataLength); + } +#if CFG_SUPPORT_QA_TOOL + nicExtTsfRawData2IqFmt(prEventDumpMem, + &prAdapter->rIcapInfo); +#endif /* CFG_SUPPORT_QA_TOOL */ + + /* TODO: check Address */ + + if (prEventDumpMem->u4DataLength == 0) { + /* The request is finished or firmware response a error */ + /* Reply time tick to iwpriv */ + + prAdapter->rIcapInfo.eIcapState = ICAP_STATE_FW_DUMP_DONE; + + kalSprintf(aucPath_done, "/file_dump_done.txt"); + if (kalCheckPath(aucPath_done) == -1) { + kalMemSet(aucPath_done, 0x00, 256); + kalSprintf(aucPath_done, "/data/file_dump_done.txt"); + } + DBGLOG(INIT, INFO, ": ==> gen done_file\n"); + kalWriteToFile(aucPath_done, FALSE, aucPath_done, + sizeof(aucPath_done)); +#if CFG_SUPPORT_QA_TOOL + prAdapter->rIcapInfo.au4Offset[0][0] = 0; + prAdapter->rIcapInfo.au4Offset[0][1] = 9; + prAdapter->rIcapInfo.au4Offset[1][0] = 0; + prAdapter->rIcapInfo.au4Offset[1][1] = 9; +#endif /* CFG_SUPPORT_QA_TOOL */ + prAdapter->rIcapInfo.u2DumpIndex++; + + } +} + + +uint32_t nicRfTestEventHandler(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + uint32_t u4QueryInfoLen = 0; + struct EXT_EVENT_RF_TEST_RESULT_T *prResult; + struct EXT_EVENT_RBIST_CAP_STATUS_T *prCapStatus; + struct mt66xx_chip_info *prChipInfo = NULL; + struct ATE_OPS_T *prAteOps = NULL; + struct ICAP_INFO_T *prIcapInfo; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + ASSERT(prChipInfo); + prAteOps = prChipInfo->prAteOps; + ASSERT(prAteOps); + prIcapInfo = &prAdapter->rIcapInfo; + + prResult = (struct EXT_EVENT_RF_TEST_RESULT_T *) + prEvent->aucBuffer; + DBGLOG(RFTEST, INFO, "%s funcID = %d\n", + __func__, + prResult->u4FuncIndex); + switch (prResult->u4FuncIndex) { + case GET_ICAP_CAPTURE_STATUS: + u4QueryInfoLen = sizeof(struct + EXT_EVENT_RBIST_CAP_STATUS_T); + prCapStatus = (struct EXT_EVENT_RBIST_CAP_STATUS_T *) + prEvent->aucBuffer; + + DBGLOG(RFTEST, INFO, "%s iCapDone = %d , icap state=%d\n", + __func__, + prCapStatus->u4CapDone, + prAdapter->rIcapInfo.eIcapState); + if (prCapStatus->u4CapDone && + prIcapInfo->eIcapState != ICAP_STATE_FW_DUMP_DONE) { + wlanoidRfTestICapRawDataProc(prAdapter, + 0 /*prCapStatus->u4CapStartAddr*/, + 0 /*prCapStatus->u4TotalBufferSize*/); + prIcapInfo->eIcapState = ICAP_STATE_FW_DUMPING; + } + break; + + case GET_ICAP_RAW_DATA: + if (prAteOps->getRbistDataDumpEvent) { + prAteOps->getRbistDataDumpEvent(prAdapter, + prEvent->aucBuffer); + if (prIcapInfo->eIcapState != ICAP_STATE_FW_DUMP_DONE) + wlanoidRfTestICapRawDataProc(prAdapter, + 0 /*prCapStatus->u4CapStartAddr*/, + 0 /*prCapStatus->u4TotalBufferSize*/); + } + break; + + case RE_CALIBRATION: + nicExtEventReCalData(prAdapter, prEvent->aucBuffer); + break; + + default: + DBGLOG(RFTEST, WARN, "Unknown rf test event, ignore\n"); + break; + } + + return u4QueryInfoLen; +} + +void nicEventLayer0ExtMagic(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + uint32_t u4QueryInfoLen = 0; + struct CMD_INFO *prCmdInfo = NULL; + + log_dbg(NIC, TRACE, "prEvent->ucExtenEID = %x\n", prEvent->ucExtenEID); + + switch (prEvent->ucExtenEID) { + case EXT_EVENT_ID_CMD_RESULT: + u4QueryInfoLen = sizeof(struct + PARAM_CUSTOM_EFUSE_BUFFER_MODE); + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + break; + + case EXT_EVENT_ID_EFUSE_ACCESS: + { + struct EVENT_ACCESS_EFUSE *prEventEfuseAccess; + + u4QueryInfoLen = sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE); + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + prEventEfuseAccess = (struct EVENT_ACCESS_EFUSE *) ( + prEvent->aucBuffer); + + /* Efuse block size 16 */ + kalMemCopy(prAdapter->aucEepromVaule, + prEventEfuseAccess->aucData, 16); + break; + } + + case EXT_EVENT_ID_RF_TEST: + u4QueryInfoLen = nicRfTestEventHandler(prAdapter, prEvent); + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + break; + + case EXT_EVENT_ID_GET_TX_POWER: + { + struct EXT_EVENT_GET_TX_POWER *prEventGetTXPower; + + u4QueryInfoLen = sizeof(struct PARAM_CUSTOM_GET_TX_POWER); + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + prEventGetTXPower = (struct EXT_EVENT_GET_TX_POWER *) ( + prEvent->aucBuffer); + + prAdapter->u4GetTxPower = + prEventGetTXPower->ucTx0TargetPower; + break; + } + + case EXT_EVENT_ID_EFUSE_FREE_BLOCK: + { + struct EXT_EVENT_EFUSE_FREE_BLOCK *prEventGetFreeBlock; + + u4QueryInfoLen = sizeof(struct + PARAM_CUSTOM_EFUSE_FREE_BLOCK); + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + prEventGetFreeBlock = (struct EXT_EVENT_EFUSE_FREE_BLOCK *) + (prEvent->aucBuffer); + prAdapter->u4FreeBlockNum = + prEventGetFreeBlock->u2FreeBlockNum; + break; + } + + case EXT_EVENT_ID_BF_STATUS_READ: + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + if (prCmdInfo != NULL && prCmdInfo->pfCmdDoneHandler) { + struct EXT_EVENT_BF_STATUS_T *prExtBfStatus = + (struct EXT_EVENT_BF_STATUS_T *)prEvent->aucBuffer; + + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, + prExtBfStatus->aucBuf); + } + break; + + case EXT_EVENT_ID_MAX_AMSDU_LENGTH_UPDATE: + { + struct EXT_EVENT_MAX_AMSDU_LENGTH_UPDATE *prEventAmsdu; + struct STA_RECORD *prStaRec; + uint8_t ucStaRecIndex; + + prEventAmsdu = (struct EXT_EVENT_MAX_AMSDU_LENGTH_UPDATE *) + (prEvent->aucBuffer); + + ucStaRecIndex = secGetStaIdxByWlanIdx( + prAdapter, prEventAmsdu->ucWlanIdx); + if (ucStaRecIndex == STA_REC_INDEX_NOT_FOUND) + break; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIndex); + if (!prStaRec) + break; + + if (prStaRec->ucMaxMpduCount == 0 || + prStaRec->ucMaxMpduCount > prEventAmsdu->ucAmsduLen) + prStaRec->ucMaxMpduCount = prEventAmsdu->ucAmsduLen; + + DBGLOG(NIC, INFO, + "Amsdu update event ucWlanIdx[%u] ucLen[%u] ucMaxMpduCount[%u]\n", + prEventAmsdu->ucWlanIdx, prEventAmsdu->ucAmsduLen, + prStaRec->ucMaxMpduCount); + break; + } +#if CFG_SUPPORT_WIFI_SYSDVT + case EXT_EVENT_ID_SYSDVT_TEST: + { + u4QueryInfoLen = sizeof(struct SYSDVT_CTRL_EXT_T); + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + break; + } +#endif /* CFG_SUPPORT_WIFI_SYSDVT */ + default: + break; + } + + if (prCmdInfo != NULL) { + if ((prCmdInfo->fgIsOid) != 0) + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } +#if (CFG_SUPPORT_TXPOWER_INFO == 1) + else if ((prEvent->ucExtenEID) == + EXT_EVENT_ID_TX_POWER_FEATURE_CTRL) { + u4QueryInfoLen = sizeof(struct + PARAM_TXPOWER_ALL_RATE_POWER_INFO_T); + /* 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, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + } +#endif + else if ((prEvent->ucExtenEID) == EXT_EVENT_ID_MAC_INFO) { + u4QueryInfoLen = sizeof(struct EXT_EVENT_MAC_INFO_T); + prCmdInfo = + nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + if (prCmdInfo->pfCmdDoneHandler) { + prCmdInfo->pfCmdDoneHandler( + prAdapter, + prCmdInfo, + prEvent->aucBuffer + ); + } else if ((prCmdInfo->fgIsOid) != 0) + kalOidComplete( + prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + } else if (prEvent->ucExtenEID == EXT_EVENT_ID_DUMP_MEM) { + u4QueryInfoLen = sizeof(struct EXT_CMD_EVENT_DUMP_MEM_T); + prCmdInfo = nicGetPendingCmdInfo( + prAdapter, + prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + if (prCmdInfo->pfCmdDoneHandler) { + prCmdInfo->pfCmdDoneHandler( + prAdapter, + prCmdInfo, + prEvent->aucBuffer + ); + } else if ((prCmdInfo->fgIsOid) != 0) + kalOidComplete( + prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + } +} + +void nicEventMicErrorInfo(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + struct EVENT_MIC_ERR_INFO *prMicError; + /* P_PARAM_AUTH_EVENT_T prAuthEvent; */ + struct STA_RECORD *prStaRec; + struct PARAM_BSSID_EX *prCurrBssid = + aisGetCurrBssId(prAdapter, + ucBssIndex); + + DBGLOG(RSN, EVENT, "EVENT_ID_MIC_ERR_INFO\n"); + + prMicError = (struct EVENT_MIC_ERR_INFO *) ( + prEvent->aucBuffer); + prStaRec = cnmGetStaRecByAddress(prAdapter, + ucBssIndex, + prCurrBssid->arMacAddress); + ASSERT(prStaRec); + + if (prStaRec) + rsnTkipHandleMICFailure(prAdapter, prStaRec, + (u_int8_t) prMicError->u4Flags); + else + DBGLOG(RSN, INFO, "No STA rec!!\n"); +#if 0 + prAuthEvent = (struct PARAM_AUTH_EVENT *) + prAdapter->aucIndicationEventBuffer; + + /* Status type: Authentication Event */ + prAuthEvent->rStatus.eStatusType = + ENUM_STATUS_TYPE_AUTHENTICATION; + + /* Authentication request */ + prAuthEvent->arRequest[0].u4Length = sizeof( + struct PARAM_AUTH_REQUEST); + kalMemCopy((void *) prAuthEvent->arRequest[0].arBssid, + (void *) prAdapter->rWlanInfo.rCurrBssId.arMacAddress, + 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, + (void *) prAuthEvent, + sizeof(struct PARAM_STATUS_INDICATION) + sizeof( + struct PARAM_AUTH_REQUEST)); +#endif +} + +void nicEventScanDone(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + scnEventScanDone(prAdapter, + (struct EVENT_SCAN_DONE *) (prEvent->aucBuffer), TRUE); +} + +void nicEventSchedScanDone(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + DBGLOG(INIT, INFO, "EVENT_ID_SCHED_SCAN_DONE\n"); + scnEventSchedScanDone(prAdapter, + (struct EVENT_SCHED_SCAN_DONE *) (prEvent->aucBuffer)); +} + +void nicEventSleepyNotify(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ +#if !defined(_HIF_USB) + struct EVENT_SLEEPY_INFO *prEventSleepyNotify; + + prEventSleepyNotify = (struct EVENT_SLEEPY_INFO *) ( + prEvent->aucBuffer); + + prAdapter->fgWiFiInSleepyState = (u_int8_t) ( + prEventSleepyNotify->ucSleepyState); + +#if CFG_SUPPORT_MULTITHREAD + if (prEventSleepyNotify->ucSleepyState) + kalSetFwOwnEvent2Hif(prAdapter->prGlueInfo); +#endif +#endif +} + +void nicEventBtOverWifi(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ +#if CFG_ENABLE_BT_OVER_WIFI + uint8_t aucTmp[sizeof(struct BT_OVER_WIFI_EVENT) + sizeof( + struct BOW_LINK_DISCONNECTED)]; + struct EVENT_BT_OVER_WIFI *prEventBtOverWifi; + struct BT_OVER_WIFI_EVENT *prBowEvent; + struct BOW_LINK_CONNECTED *prBowLinkConnected; + struct BOW_LINK_DISCONNECTED *prBowLinkDisconnected; + + prEventBtOverWifi = (struct EVENT_BT_OVER_WIFI *) ( + prEvent->aucBuffer); + + /* construct event header */ + prBowEvent = (struct BT_OVER_WIFI_EVENT *) aucTmp; + + if (prEventBtOverWifi->ucLinkStatus == 0) { + /* Connection */ + prBowEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_CONNECTED; + prBowEvent->rHeader.ucSeqNumber = 0; + prBowEvent->rHeader.u2PayloadLength = sizeof( + struct BOW_LINK_CONNECTED); + + /* fill event body */ + prBowLinkConnected = (struct 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( + struct BOW_LINK_DISCONNECTED); + + /* fill event body */ + prBowLinkDisconnected = (struct BOW_LINK_DISCONNECTED *) ( + prBowEvent->aucPayload); + prBowLinkDisconnected->ucReason = 0; /* @FIXME */ + kalMemZero(prBowLinkDisconnected->aucPeerAddress, + MAC_ADDR_LEN); /* @FIXME */ + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prBowEvent); + } +#endif +} + +void nicEventStatistics(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct CMD_INFO *prCmdInfo; + + /* buffer statistics for further query */ + prAdapter->fgIsStatValid = TRUE; + prAdapter->rStatUpdateTime = kalGetTimeTick(); + kalMemCopy(&prAdapter->rStatStruct, prEvent->aucBuffer, + sizeof(struct 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); + } +} +void nicEventWlanInfo(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct CMD_INFO *prCmdInfo; + + /* buffer statistics for further query */ + prAdapter->fgIsStatValid = TRUE; + prAdapter->rStatUpdateTime = kalGetTimeTick(); + kalMemCopy(&prAdapter->rEventWlanInfo, prEvent->aucBuffer, + sizeof(struct EVENT_WLAN_INFO)); + + DBGLOG(RSN, INFO, "EVENT_ID_WTBL_INFO"); + /* 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); + } +} + +void nicEventMibInfo(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct CMD_INFO *prCmdInfo; + + + /* buffer statistics for further query */ + prAdapter->fgIsStatValid = TRUE; + prAdapter->rStatUpdateTime = kalGetTimeTick(); + + DBGLOG(RSN, INFO, "EVENT_ID_MIB_INFO"); + /* 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); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is to decide if the beacon time out is reasonable +* by the TRX and some known factors +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return true if the beacon timeout event is valid after policy checking +* false if the beacon timeout event needs to be ignored +*/ +/*----------------------------------------------------------------------------*/ +bool nicBeaconTimeoutFilterPolicy(IN struct ADAPTER *prAdapter, + uint8_t ucBcnTimeoutReason, uint8_t *ucDisconnectReason, + uint8_t ucBssIdx) +{ + struct RX_CTRL *prRxCtrl; + struct TX_CTRL *prTxCtrl; + OS_SYSTIME u4CurrentTime; + bool bValid = true; + uint32_t u4MonitorWindow; + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; +#if CFG_SUPPORT_WFD + struct WFD_CFG_SETTINGS *prWfdCfgSettings = + &prAdapter->rWifiVar.rWfdConfigureSettings; +#endif + + ASSERT(prAdapter); + u4MonitorWindow = CFG_BEACON_TIMEOUT_FILTER_DURATION_DEFAULT_VALUE; + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + GET_CURRENT_SYSTIME(&u4CurrentTime); + + DBGLOG(NIC, INFO, + "u4MonitorWindow: %d, u4CurrentTime: %d, u4LastRxTime: %d, u4LastTxTime: %d", + u4MonitorWindow, u4CurrentTime, + prRxCtrl->u4LastRxTime[ucBssIdx], + prTxCtrl->u4LastTxTime[ucBssIdx]); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + + if (IS_BSS_AIS(prBssInfo)) { + if (ucBcnTimeoutReason == BEACON_TIMEOUT_REASON_HIGH_PER) { + bValid = true; + } else if (!CHECK_FOR_TIMEOUT(u4CurrentTime, + prRxCtrl->u4LastRxTime[ucBssIdx], + SEC_TO_SYSTIME(MSEC_TO_SEC(u4MonitorWindow)))) { + /* Policy 1, if RX in the past duration (in ms) */ + if (scanBeaconTimeoutFilterPolicyForAis( + prAdapter, ucBssIdx)) { + DBGLOG(NIC, INFO, "Driver find better TX AP"); + *ucDisconnectReason = + DISCONNECT_REASON_CODE_RADIO_LOST_TX_ERR; + } else { + DBGLOG(NIC, INFO, "RX in the past duration"); + bValid = false; + } + } + } +#if CFG_ENABLE_WIFI_DIRECT + else if (IS_BSS_P2P(prBssInfo)) { + if (!CHECK_FOR_TIMEOUT(u4CurrentTime, + prRxCtrl->u4LastRxTime[ucBssIdx], + SEC_TO_SYSTIME(MSEC_TO_SEC(u4MonitorWindow)))) { + DBGLOG(NIC, INFO, + "Policy 1 hit, RX in the past duration"); + bValid = false; + } +#if CFG_SUPPORT_WFD + else if (prWfdCfgSettings->ucWfdEnable && + prWfdCfgSettings->u4LinkScore > 0) { + DBGLOG(NIC, INFO, + "Policy 2 hit, link score > 0 in WFD"); + bValid = false; + } +#endif /* CFG_SUPPORT_WFD */ + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + + DBGLOG(NIC, INFO, "valid beacon time out event?: %d", bValid); + + return bValid; +} + +void nicEventBeaconTimeout(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + DBGLOG(NIC, INFO, "EVENT_ID_BSS_BEACON_TIMEOUT\n"); + + if (prAdapter->fgDisBcnLostDetection == FALSE) { + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + struct EVENT_BSS_BEACON_TIMEOUT *prEventBssBeaconTimeout; + + prEventBssBeaconTimeout = (struct EVENT_BSS_BEACON_TIMEOUT + *) (prEvent->aucBuffer); + + if (prEventBssBeaconTimeout->ucBssIndex >= + prAdapter->ucHwBssIdNum) + return; + + DBGLOG(NIC, INFO, "Reason code: %d\n", + prEventBssBeaconTimeout->ucReasonCode); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prEventBssBeaconTimeout->ucBssIndex); + + if (IS_BSS_AIS(prBssInfo)) { + uint8_t ucDisconnectReason = + DISCONNECT_REASON_CODE_RADIO_LOST; + + if (nicBeaconTimeoutFilterPolicy(prAdapter, + prEventBssBeaconTimeout->ucReasonCode, + &ucDisconnectReason, + prBssInfo->ucBssIndex)) + aisBssBeaconTimeout_impl(prAdapter, + prEventBssBeaconTimeout->ucReasonCode, + ucDisconnectReason, + prBssInfo->ucBssIndex); + } +#if CFG_ENABLE_WIFI_DIRECT + else if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) { + uint8_t ucDisconnectReason = + DISCONNECT_REASON_CODE_RADIO_LOST; + + if (nicBeaconTimeoutFilterPolicy(prAdapter, + prEventBssBeaconTimeout->ucReasonCode, + &ucDisconnectReason, + prEventBssBeaconTimeout->ucBssIndex)) + p2pRoleFsmRunEventBeaconTimeout(prAdapter, + prBssInfo); + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (GET_BSS_INFO_BY_INDEX(prAdapter, + prEventBssBeaconTimeout->ucBssIndex)->eNetworkType == + NETWORK_TYPE_BOW) { + /* ToDo:: Nothing */ + } +#endif + else { + DBGLOG(RX, ERROR, + "EVENT_ID_BSS_BEACON_TIMEOUT: (ucBssIndex = %d)\n", + prEventBssBeaconTimeout->ucBssIndex); + } + } + +} + +void nicEventUpdateNoaParams(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { + struct EVENT_UPDATE_NOA_PARAMS *prEventUpdateNoaParam; + + prEventUpdateNoaParam = (struct EVENT_UPDATE_NOA_PARAMS *) ( + prEvent->aucBuffer); + + if (GET_BSS_INFO_BY_INDEX(prAdapter, + prEventUpdateNoaParam->ucBssIndex)->eNetworkType + == NETWORK_TYPE_P2P) { + + p2pProcessEvent_UpdateNOAParam(prAdapter, + prEventUpdateNoaParam->ucBssIndex, + prEventUpdateNoaParam); + } else { + ASSERT(0); + } + } +#else + ASSERT(0); +#endif +} + +void nicEventStaAgingTimeout(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + if (prAdapter->fgDisStaAgingTimeoutDetection == FALSE) { + struct EVENT_STA_AGING_TIMEOUT *prEventStaAgingTimeout; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + + prEventStaAgingTimeout = (struct EVENT_STA_AGING_TIMEOUT *) + (prEvent->aucBuffer); + prStaRec = cnmGetStaRecByIndex(prAdapter, + prEventStaAgingTimeout->ucStaRecIdx); + if (prStaRec == NULL) + return; + + DBGLOG(NIC, INFO, "EVENT_ID_STA_AGING_TIMEOUT: STA[%u] " + MACSTR "\n", + prEventStaAgingTimeout->ucStaRecIdx, + MAC2STR(prStaRec->aucMacAddr)); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + bssRemoveClient(prAdapter, prBssInfo, prStaRec); + + if (prAdapter->fgIsP2PRegistered) { + p2pFuncDisconnect(prAdapter, prBssInfo, prStaRec, FALSE, + REASON_CODE_DISASSOC_INACTIVITY); + } + + } + /* gDisStaAgingTimeoutDetection */ +} + +void nicEventApObssStatus(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) + rlmHandleObssStatusEventPkt(prAdapter, + (struct EVENT_AP_OBSS_STATUS *) prEvent->aucBuffer); +#endif +} + +void nicEventRoamingStatus(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ +#if CFG_SUPPORT_ROAMING + struct CMD_ROAMING_TRANSIT *prTransit; + + prTransit = (struct CMD_ROAMING_TRANSIT *) ( + prEvent->aucBuffer); + + /* Default path */ + if (!IS_BSS_INDEX_AIS(prAdapter, prTransit->ucBssidx)) { + DBGLOG(NIC, LOUD, + "Use default, invalid index = %d\n", + prTransit->ucBssidx); + prTransit->ucBssidx = AIS_DEFAULT_INDEX; + } + + roamingFsmProcessEvent(prAdapter, prTransit); +#endif /* CFG_SUPPORT_ROAMING */ +} + +void nicEventSendDeauth(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct SW_RFB rSwRfb; + + DBGLOG(NIC, INFO, "%s\n", __func__); +#if DBG + struct WLAN_MAC_HEADER *prWlanMacHeader; + + prWlanMacHeader = (struct WLAN_MAC_HEADER *)prEvent->aucBuffer; + DBGLOG(RX, TRACE, "nicRx: aucAddr1: " MACSTR "\n", + MAC2STR(prWlanMacHeader->aucAddr1)); + DBGLOG(RX, TRACE, "nicRx: aucAddr2: " MACSTR "\n", + MAC2STR(prWlanMacHeader->aucAddr2)); +#endif + + /* receive packets without StaRec */ + rSwRfb.pvHeader = (struct WLAN_MAC_HEADER *)prEvent->aucBuffer; + if (authSendDeauthFrame(prAdapter, NULL, NULL, &rSwRfb, + REASON_CODE_CLASS_3_ERR, + (PFN_TX_DONE_HANDLER) NULL) == WLAN_STATUS_SUCCESS) { + + DBGLOG(RX, ERROR, "Send Deauth Error\n"); + } +} + +void nicEventUpdateRddStatus(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ +#if CFG_SUPPORT_RDD_TEST_MODE + struct EVENT_RDD_STATUS *prEventRddStatus; + + prEventRddStatus = (struct EVENT_RDD_STATUS *) ( + prEvent->aucBuffer); + + prAdapter->ucRddStatus = prEventRddStatus->ucRddStatus; +#endif +} + +void nicEventUpdateBwcsStatus(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct PTA_IPC *prEventBwcsStatus; + + prEventBwcsStatus = (struct PTA_IPC *) (prEvent->aucBuffer); + +#if CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(RSN, EVENT, "BCM BWCS Event: %02x%02x%02x%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, + (void *) prEventBwcsStatus, sizeof(struct PTA_IPC), + AIS_DEFAULT_INDEX); +} + +void nicEventUpdateBcmDebug(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct PTA_IPC *prEventBwcsStatus; + + prEventBwcsStatus = (struct PTA_IPC *) (prEvent->aucBuffer); + +#if CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(RSN, EVENT, "BCM FW status: %02x%02x%02x%02x\n", + prEventBwcsStatus->u.aucBTPParams[0], + prEventBwcsStatus->u.aucBTPParams[1], + prEventBwcsStatus->u.aucBTPParams[2], + prEventBwcsStatus->u.aucBTPParams[3]); +#endif +} + +void nicEventAddPkeyDone(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct EVENT_ADD_KEY_DONE_INFO *prKeyDone; + struct STA_RECORD *prStaRec = NULL; + uint8_t ucKeyId; + + prKeyDone = (struct EVENT_ADD_KEY_DONE_INFO *) ( + prEvent->aucBuffer); + + DBGLOG(RSN, INFO, "EVENT_ID_ADD_PKEY_DONE BSSIDX=%d " MACSTR + "\n", + prKeyDone->ucBSSIndex, MAC2STR(prKeyDone->aucStaAddr)); + + prStaRec = cnmGetStaRecByAddress(prAdapter, + prKeyDone->ucBSSIndex, + prKeyDone->aucStaAddr); + + if (!prStaRec) { + ucKeyId = + aisGetAisSpecBssInfo(prAdapter, + prKeyDone->ucBSSIndex)->ucKeyAlgorithmId; + if ((ucKeyId == CIPHER_SUITE_WEP40) + || (ucKeyId == CIPHER_SUITE_WEP104)) { + DBGLOG(RX, INFO, "WEP, ucKeyAlgorithmId= %d\n", + ucKeyId); + prStaRec = cnmGetStaRecByAddress(prAdapter, + prKeyDone->ucBSSIndex, + prAdapter->rWifiVar.arBssInfoPool[ + prKeyDone->ucBSSIndex].aucBSSID); + if (!prStaRec) { + DBGLOG(RX, INFO, + "WEP, AddPKeyDone, ucBSSIndex %d, Addr " + MACSTR ", StaRec is NULL\n", + prKeyDone->ucBSSIndex, + MAC2STR(prAdapter->rWifiVar + .arBssInfoPool[prKeyDone-> + ucBSSIndex].aucBSSID)); + } + } else { + DBGLOG(RX, INFO, + "AddPKeyDone, ucBSSIndex %d, Addr " + MACSTR ", StaRec is NULL\n", + prKeyDone->ucBSSIndex, + MAC2STR(prKeyDone->aucStaAddr)); + } + } + if (prStaRec) { + DBGLOG(RSN, INFO, "STA " MACSTR " Add Key Done!!\n", + MAC2STR(prStaRec->aucMacAddr)); + prStaRec->fgIsTxKeyReady = TRUE; + qmUpdateStaRec(prAdapter, prStaRec); + } +} + +void nicEventIcapDone(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct EVENT_ICAP_STATUS *prEventIcapStatus; + struct PARAM_CUSTOM_MEM_DUMP_STRUCT rMemDumpInfo; + uint32_t u4QueryInfo; + + prEventIcapStatus = (struct EVENT_ICAP_STATUS *) ( + prEvent->aucBuffer); + + rMemDumpInfo.u4Address = prEventIcapStatus->u4StartAddress; + rMemDumpInfo.u4Length = prEventIcapStatus->u4IcapSieze; +#if CFG_SUPPORT_QA_TOOL + rMemDumpInfo.u4IcapContent = + prEventIcapStatus->u4IcapContent; +#endif + + wlanoidQueryMemDump(prAdapter, &rMemDumpInfo, + sizeof(rMemDumpInfo), &u4QueryInfo); +} + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +struct PARAM_CAL_BACKUP_STRUCT_V2 g_rCalBackupDataV2; + +void nicEventCalAllDone(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct CMD_CAL_BACKUP_STRUCT_V2 *prEventCalBackupDataV2; + uint32_t u4QueryInfo; + + DBGLOG(RFTEST, INFO, "%s\n", __func__); + + memset(&g_rCalBackupDataV2, 0, + sizeof(struct PARAM_CAL_BACKUP_STRUCT_V2)); + + prEventCalBackupDataV2 = (struct CMD_CAL_BACKUP_STRUCT_V2 *) + (prEvent->aucBuffer); + + if (prEventCalBackupDataV2->ucReason == 1 + && prEventCalBackupDataV2->ucAction == 2) { + DBGLOG(RFTEST, INFO, + "Received an EVENT for Trigger Do All Cal Function.\n"); + + g_rCalBackupDataV2.ucReason = 2; + g_rCalBackupDataV2.ucAction = 4; + g_rCalBackupDataV2.ucNeedResp = 1; + g_rCalBackupDataV2.ucFragNum = 0; + g_rCalBackupDataV2.ucRomRam = 0; + g_rCalBackupDataV2.u4ThermalValue = 0; + g_rCalBackupDataV2.u4Address = 0; + g_rCalBackupDataV2.u4Length = 0; + g_rCalBackupDataV2.u4RemainLength = 0; + + DBGLOG(RFTEST, INFO, + "RLM CMD : Get Cal Data from FW (%s). Start!!!!!!!!!!!!!!!!\n", + g_rCalBackupDataV2.ucRomRam == 0 ? "ROM" : "RAM"); + DBGLOG(RFTEST, INFO, "Thermal Temp = %d\n", + g_rBackupCalDataAllV2.u4ThermalInfo); + wlanoidQueryCalBackupV2(prAdapter, + &g_rCalBackupDataV2, + sizeof(struct PARAM_CAL_BACKUP_STRUCT_V2), + &u4QueryInfo); + } + +} +#endif + +void nicEventDebugMsg(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct EVENT_DEBUG_MSG *prEventDebugMsg; + uint8_t ucMsgType; + uint16_t u2MsgSize; + uint8_t *pucMsg; + + prEventDebugMsg = (struct EVENT_DEBUG_MSG *)( + prEvent->aucBuffer); + if (!prEventDebugMsg) { + DBGLOG(RSN, WARN, "prEventDebugMsg is NULL\n"); + return; + } + + ucMsgType = prEventDebugMsg->ucMsgType; + u2MsgSize = prEventDebugMsg->u2MsgSize; + pucMsg = prEventDebugMsg->aucMsg; + +#if CFG_SUPPORT_QA_TOOL + if (ucMsgType == DEBUG_MSG_TYPE_ASCII) { + if (kalStrnCmp("[RECAL DUMP START]", pucMsg, 18) == 0) { + prAdapter->rReCalInfo.fgDumped = TRUE; + return; + } else if (kalStrnCmp("[RECAL DUMP END]", pucMsg, 16) == 0) { + prAdapter->rReCalInfo.fgDumped = TRUE; + return; + } else if (prAdapter->rReCalInfo.fgDumped && + kalStrnCmp("[Recal]", pucMsg, 7) == 0) { + struct WIFI_EVENT *prTmpEvent; + struct EXT_EVENT_RECAL_DATA_T *prCalData; + uint32_t u4Size = sizeof(struct WIFI_EVENT) + + sizeof(struct EXT_EVENT_RECAL_DATA_T); + + prTmpEvent = (struct WIFI_EVENT *) + kalMemAlloc(u4Size, VIR_MEM_TYPE); + + if (prTmpEvent == NULL) { + DBGLOG(RFTEST, ERROR, + "Unable to alloc memory for prTmpEvent\n"); + return; + } + kalMemZero(prTmpEvent, u4Size); + + prCalData = (struct EXT_EVENT_RECAL_DATA_T *) + prTmpEvent->aucBuffer; + if (prCalData) { + prCalData->u4FuncIndex = RE_CALIBRATION; + prCalData->u4Type = 0; + /* format: [XXXXXXXX][YYYYYYYY]ZZZZZZZZ */ + kalMemCopy(prCalData->u.ucData, pucMsg + 7, 28); + nicRfTestEventHandler(prAdapter, prTmpEvent); + } + kalMemFree(prTmpEvent, VIR_MEM_TYPE, u4Size); + } + } +#endif + + wlanPrintFwLog(pucMsg, u2MsgSize, ucMsgType, NULL); +} + +void nicEventTdls(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + TdlsexEventHandle(prAdapter->prGlueInfo, + (uint8_t *)prEvent->aucBuffer, + (uint32_t)(prEvent->u2PacketLength - 8)); +} + +void nicEventRssiMonitor(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + int32_t rssi = 0; + struct GLUE_INFO *prGlueInfo; + struct wiphy *wiphy; + struct net_device *dev; + + prGlueInfo = prAdapter->prGlueInfo; + wiphy = priv_to_wiphy(prGlueInfo); + + kalMemCopy(&rssi, prEvent->aucBuffer, sizeof(int32_t)); + DBGLOG(RX, TRACE, "EVENT_ID_RSSI_MONITOR value=%d\n", rssi); +#if KERNEL_VERSION(3, 16, 0) <= LINUX_VERSION_CODE + dev = wlanGetNetDev(prAdapter->prGlueInfo, + AIS_DEFAULT_INDEX); + if (dev != NULL) { + mtk_cfg80211_vendor_event_rssi_beyond_range(wiphy, + dev->ieee80211_ptr, rssi); + } +#endif +} + +void nicEventDumpMem(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct CMD_INFO *prCmdInfo; + + DBGLOG(SW4, INFO, "%s: EVENT_ID_DUMP_MEM\n", __func__); + + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + DBGLOG(NIC, INFO, ": ==> 1\n"); + 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); + } else { + /* Burst mode */ + DBGLOG(NIC, INFO, ": ==> 2\n"); +#if 0 + nicEventQueryMemDump(prAdapter, prEvent->aucBuffer); +#endif + } +} + +void nicEventAssertDump(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct mt66xx_chip_info *prChipInfo = NULL; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + if (wlanIsChipRstRecEnabled(prAdapter)) + wlanChipRstPreAct(prAdapter); + + if (prEvent->ucS2DIndex == S2D_INDEX_EVENT_N2H) { + if (!prAdapter->fgN9AssertDumpOngoing) { + DBGLOG(NIC, ERROR, + "%s: EVENT_ID_ASSERT_DUMP\n", __func__); + DBGLOG(NIC, ERROR, + "\n[DUMP_N9]====N9 ASSERT_DUMPSTART====\n"); + prAdapter->fgKeepPrintCoreDump = TRUE; + if (kalOpenCorDumpFile(TRUE) != WLAN_STATUS_SUCCESS) + DBGLOG(NIC, ERROR, "kalOpenCorDumpFile fail\n"); + else + prAdapter->fgN9CorDumpFileOpend = TRUE; + + prAdapter->fgN9AssertDumpOngoing = TRUE; + wlanCorDumpTimerInit(prAdapter, TRUE); + } + if (prAdapter->fgN9AssertDumpOngoing) { + + if (prAdapter->fgKeepPrintCoreDump) + DBGLOG(NIC, ERROR, "[DUMP_N9]%s:\n", + prEvent->aucBuffer); + if (!kalStrnCmp(prEvent->aucBuffer, + ";more log added here", 5) + || !kalStrnCmp(prEvent->aucBuffer, + ";[core dump start]", 5)) + prAdapter->fgKeepPrintCoreDump = FALSE; + + if (prAdapter->fgN9CorDumpFileOpend) { + if (kalWriteCorDumpFile( + prEvent->aucBuffer, + prEvent->u2PacketLength - + prChipInfo->event_hdr_size, + TRUE) != WLAN_STATUS_SUCCESS) { + DBGLOG(NIC, INFO, + "kalWriteN9CorDumpFile fail\n"); + } + } + wlanCorDumpTimerReset(prAdapter, TRUE); + } + } else { + /* prEvent->ucS2DIndex == S2D_INDEX_EVENT_C2H */ + if (!prAdapter->fgCr4AssertDumpOngoing) { + DBGLOG(NIC, ERROR, + "%s: EVENT_ID_ASSERT_DUMP\n", __func__); + DBGLOG(NIC, ERROR, + "\n[DUMP_Cr4]====CR4 ASSERT_DUMPSTART====\n"); + prAdapter->fgKeepPrintCoreDump = TRUE; + if (kalOpenCorDumpFile(FALSE) != WLAN_STATUS_SUCCESS) + DBGLOG(NIC, ERROR, "kalOpenCorDumpFile fail\n"); + else + prAdapter->fgCr4CorDumpFileOpend = TRUE; + + prAdapter->fgCr4AssertDumpOngoing = TRUE; + wlanCorDumpTimerInit(prAdapter, FALSE); + } + if (prAdapter->fgCr4AssertDumpOngoing) { + if (prAdapter->fgKeepPrintCoreDump) + DBGLOG(NIC, ERROR, "[DUMP_CR4]%s:\n", + prEvent->aucBuffer); + if (!kalStrnCmp(prEvent->aucBuffer, + ";more log added here", 5)) + prAdapter->fgKeepPrintCoreDump = FALSE; + + if (prAdapter->fgCr4CorDumpFileOpend) { + if (kalWriteCorDumpFile( + prEvent->aucBuffer, + prEvent->u2PacketLength - + prChipInfo->event_hdr_size, + FALSE) != WLAN_STATUS_SUCCESS) { + DBGLOG(NIC, ERROR, + "kalWriteN9CorDumpFile fail\n"); + } + } + wlanCorDumpTimerReset(prAdapter, FALSE); + } + } +} + +void nicEventRddSendPulse(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + DBGLOG(RLM, INFO, "%s: EVENT_ID_RDD_SEND_PULSE\n", + __func__); + + nicEventRddPulseDump(prAdapter, prEvent->aucBuffer); +} + +void nicEventUpdateCoexPhyrate(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + uint8_t i; + struct EVENT_UPDATE_COEX_PHYRATE *prEventUpdateCoexPhyrate; + + ASSERT(prAdapter); + + DBGLOG(NIC, LOUD, "%s\n", __func__); + + prEventUpdateCoexPhyrate = (struct EVENT_UPDATE_COEX_PHYRATE + *)(prEvent->aucBuffer); + + for (i = 0; i < (prAdapter->ucHwBssIdNum + 1); i++) { + prAdapter->aprBssInfo[i]->u4CoexPhyRateLimit = + prEventUpdateCoexPhyrate->au4PhyRateLimit[i]; + DBGLOG_LIMITED(NIC, TRACE, "Coex:BSS[%d]R:%d\n", i, + prAdapter->aprBssInfo[i]->u4CoexPhyRateLimit); + } + + prAdapter->ucSmarGearSupportSisoOnly = + prEventUpdateCoexPhyrate->ucSupportSisoOnly; + prAdapter->ucSmartGearWfPathSupport = + prEventUpdateCoexPhyrate->ucWfPathSupport; + + DBGLOG_LIMITED(NIC, INFO, "Smart Gear SISO:%d, WF:%d\n", + prAdapter->ucSmarGearSupportSisoOnly, + prAdapter->ucSmartGearWfPathSupport); +} + +void nicCmdEventQueryCnmInfo(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct PARAM_GET_CNM_T *prCnmInfoQuery = NULL; + struct PARAM_GET_CNM_T *prCnmInfoEvent = NULL; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + if (prCmdInfo->fgIsOid) { + prCnmInfoQuery = (struct PARAM_GET_CNM_T *) + prCmdInfo->pvInformationBuffer; + prCnmInfoEvent = (struct PARAM_GET_CNM_T *)pucEventBuf; + kalMemCopy(prCnmInfoQuery, prCnmInfoEvent, + sizeof(struct PARAM_GET_CNM_T)); + + prGlueInfo = prAdapter->prGlueInfo; + u4QueryInfoLen = sizeof(struct PARAM_GET_CNM_T); + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +void nicEventCnmInfo(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct CMD_INFO *prCmdInfo; + + /* 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); + } +} + +#if CFG_SUPPORT_REPLAY_DETECTION +void nicCmdEventSetAddKey(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct WIFI_CMD *prWifiCmd = NULL; + struct CMD_802_11_KEY *prCmdKey = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct GL_DETECT_REPLAY_INFO *prDetRplyInfo = NULL; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4InformationBufferLength, + WLAN_STATUS_SUCCESS); + } + + prGlueInfo = prAdapter->prGlueInfo; + + if (pucEventBuf) { + prWifiCmd = (struct WIFI_CMD *) (pucEventBuf); + prCmdKey = (struct CMD_802_11_KEY *) (prWifiCmd->aucBuffer); + + if (!IS_BSS_INDEX_AIS(prAdapter, + prCmdKey->ucBssIdx)) + return; + + /* AIS only */ + if (!prCmdKey->ucKeyType && + prCmdKey->ucKeyId >= 0 && prCmdKey->ucKeyId < 4) { + /* Only save data broadcast key info. + * ucKeyType == 1 means unicast key + * ucKeyId == 4 or ucKeyId == 5 means it is a PMF key + */ + prDetRplyInfo = aisGetDetRplyInfo(prAdapter, + prCmdKey->ucBssIdx); + + prDetRplyInfo->ucCurKeyId = prCmdKey->ucKeyId; + prDetRplyInfo->ucKeyType = prCmdKey->ucKeyType; + prDetRplyInfo->arReplayPNInfo[ + prCmdKey->ucKeyId].fgRekey = TRUE; + prDetRplyInfo->arReplayPNInfo[ + prCmdKey->ucKeyId].fgFirstPkt = TRUE; + DBGLOG(NIC, TRACE, + "[%d] Keyid is %d, ucKeyType is %d\n", + prCmdKey->ucBssIdx, + prCmdKey->ucKeyId, prCmdKey->ucKeyType); + } + } +} +void nicOidCmdTimeoutSetAddKey(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo) +{ + ASSERT(prAdapter); + + DBGLOG(NIC, WARN, "Wlan setaddkey timeout.\n"); + if (prCmdInfo->fgIsOid) + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, + 0, WLAN_STATUS_FAILURE); +} +#endif + +#if CFG_SUPPORT_LOWLATENCY_MODE +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is in response of EVENT_ID_LOW_LATENCY_INFO form FW + * + * @param prAdapter Pointer to the Adapter structure. + * @param prEvent Pointer to the event structure. + * @retval none + */ +/*----------------------------------------------------------------------------*/ +void nicEventUpdateLowLatencyInfoStatus(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct EVENT_LOW_LATENCY_INFO *prEvtLowLatencyInfo; + struct rtc_time tm; + struct timeval tv = { 0 }; +#if CFG_SUPPORT_DATA_STALL + uint8_t event[12]; + uint32_t iEventTime; + int8_t i, ret = 0; +#endif + + ASSERT(prAdapter); + + prEvtLowLatencyInfo = + (struct EVENT_LOW_LATENCY_INFO *)(prEvent->aucBuffer); + + do_gettimeofday(&tv); + rtc_time_to_tm(tv.tv_sec, &tm); + + DBGLOG_LIMITED(NIC, INFO, + "Low Latency DPP Info: drv cert=[%d], evt cert=[%d], evt dup=[%d] drv det=[%d] %02d-%02d %02d:%02d:%02d.%06u\n", + prAdapter->fgTxDupCertificate, + prEvtLowLatencyInfo->fgTxDupCert, + prEvtLowLatencyInfo->fgTxDupEnable, + prAdapter->fgEnTxDupDetect, + tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, + tm.tm_min, tm.tm_sec, (unsigned int)tv.tv_usec); + + if (prAdapter->fgTxDupCertificate != prEvtLowLatencyInfo->fgTxDupCert) { + + prAdapter->fgTxDupCertificate = + prEvtLowLatencyInfo->fgTxDupCert; + +#if CFG_SUPPORT_DATA_STALL + ret = sprintf(event, "%03d%02d%06u", + EVENT_TX_DUP_CERT_CHANGE, + tm.tm_sec, + (unsigned int)tv.tv_usec); + if (ret < 0 || ret > sizeof(event)) { + DBGLOG_LIMITED(NIC, INFO, "sprintf failed:%d\n", ret); + return; + } + + iEventTime = 0; + for (i = 0 ; i < 8 ; i++) + iEventTime = iEventTime*10 + atoi(event[i]); + + KAL_REPORT_ERROR_EVENT(prAdapter, + iEventTime, + (uint16_t)sizeof(uint32_t), + 0, + TRUE); +#endif + } + +#if CFG_SUPPORT_DATA_STALL + if (prAdapter->fgTxDupCertificate) { + + /* Indicate detect result to driver if detect on */ + if (prAdapter->fgEnTxDupDetect) { + if (prEvtLowLatencyInfo->fgTxDupEnable) { + ret = sprintf(event, "%03d%02d%06u", + EVENT_TX_DUP_ON, + tm.tm_sec, + (unsigned int)tv.tv_usec); + } else { + ret = sprintf(event, "%03d%02d%06u", + EVENT_TX_DUP_OFF, + tm.tm_sec, + (unsigned int)tv.tv_usec); + } + if (ret < 0 || ret > sizeof(event)) { + DBGLOG_LIMITED(NIC, INFO, + "sprintf failed:%d\n", ret); + return; + } + + /* Convert 11 byte string like '10121316927' to + * 8 digits uint32 integer 10121316 + */ + iEventTime = 0; + for (i = 0 ; i < 8 ; i++) + iEventTime = iEventTime*10 + atoi(event[i]); + + KAL_REPORT_ERROR_EVENT(prAdapter, + iEventTime, + (uint16_t)sizeof(uint32_t), + 0, + TRUE); + } + } +#endif +} +#endif + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_ext_cmd_event.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_ext_cmd_event.c new file mode 100644 index 0000000000000..c83028bd56ba6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_ext_cmd_event.c @@ -0,0 +1,482 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/*! \file nic_ext_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. + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ +#if (CFG_SUPPORT_CONNAC2X == 1) + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" +#include "gl_ate_agent.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 + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D A T A + ******************************************************************************* + */ +static uint32_t +wlanSendSetQueryExtCmd2WA( + struct ADAPTER *prAdapter, + uint8_t ucCID, + uint8_t ucExtCID, + u_int8_t fgSetQuery, + u_int8_t fgNeedResp, + u_int8_t fgIsOid, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + uint32_t u4SetQueryInfoLen, + uint8_t *pucInfoBuffer, + void *pvSetQueryBuffer, + uint32_t u4SetQueryBufferLen) +{ + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + uint8_t *pucCmdBuf; + struct mt66xx_chip_info *prChipInfo; + + prGlueInfo = prAdapter->prGlueInfo; + prChipInfo = prAdapter->chip_info; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + (prChipInfo->u2CmdTxHdrSize + u4SetQueryInfoLen)); + + DEBUGFUNC("wlanSendSetQueryCmd"); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->u2InfoBufLen = + (uint16_t)(prChipInfo->u2CmdTxHdrSize + u4SetQueryInfoLen); + prCmdInfo->pfCmdDoneHandler = pfCmdDoneHandler; + prCmdInfo->pfCmdTimeoutHandler = pfCmdTimeoutHandler; + prCmdInfo->fgIsOid = fgIsOid; + prCmdInfo->ucCID = ucCID; + prCmdInfo->fgSetQuery = fgSetQuery; + prCmdInfo->fgNeedResp = fgNeedResp; + prCmdInfo->u4SetInfoLen = u4SetQueryInfoLen; + prCmdInfo->pvInformationBuffer = pvSetQueryBuffer; + prCmdInfo->u4InformationBufferLength = u4SetQueryBufferLen; + + /* Setup WIFI_CMD_T (no payload) */ + NIC_FILL_CMD_TX_HDR(prAdapter, + prCmdInfo->pucInfoBuffer, + prCmdInfo->u2InfoBufLen, + prCmdInfo->ucCID, + CMD_PACKET_TYPE_ID, + &prCmdInfo->ucCmdSeqNum, + prCmdInfo->fgSetQuery, + &pucCmdBuf, FALSE, ucExtCID, S2D_INDEX_CMD_H2C); + if (u4SetQueryInfoLen > 0 && pucInfoBuffer != NULL) + kalMemCopy(pucCmdBuf, pucInfoBuffer, u4SetQueryInfoLen); + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (struct QUE_ENTRY *) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + return WLAN_STATUS_PENDING; +} + +static uint32_t StaRecUpdateBasic( + struct ADAPTER *pAd, + uint8_t *pMsgBuf, + void *args) +{ + struct STA_RECORD *pStaRecCfg = (struct STA_RECORD *)args; + struct STAREC_COMMON_T StaRecCommon = {0}; + + /* Fill TLV format */ + StaRecCommon.u2Tag = STA_REC_BASIC; + StaRecCommon.u2Length = sizeof(struct STAREC_COMMON_T); + StaRecCommon.u4ConnectionType = CPU_TO_LE32(CONNECTION_INFRA_STA); + StaRecCommon.ucConnectionState = pStaRecCfg->ucStaState; + /* New info to indicate this is new way to update STAREC */ + StaRecCommon.u2ExtraInfo = STAREC_COMMON_EXTRAINFO_V2; + + if (pStaRecCfg->ucStaState == STA_STATE_1) + StaRecCommon.u2ExtraInfo |= STAREC_COMMON_EXTRAINFO_NEWSTAREC; + +#if 0 /* TODO: soft ap mode */ +#ifdef CONFIG_AP_SUPPORT + if (pEntry) { + StaRecCommon.ucIsQBSS = + CLIENT_STATUS_TEST_FLAG(pEntry, + fCLIENT_STATUS_WMM_CAPABLE) ? + TRUE : FALSE; + StaRecCommon.u2AID = cpu2le16(pEntry->Aid); + } + +#endif /* CONFIG_AP_SUPPORT */ +#endif + + StaRecCommon.ucIsQBSS = pStaRecCfg->fgIsQoS; + + StaRecCommon.u2AID = CPU_TO_LE16(pStaRecCfg->u2AssocId); + kalMemCopy(&StaRecCommon.aucPeerMacAddr[0], &pStaRecCfg->aucMacAddr[0], + MAC_ADDR_LEN); + + /* Append this feature */ +#if 0 /* TODO: big endian platform */ +#ifdef RT_BIG_ENDIAN + StaRecCommon.u2Tag = cpu2le16(StaRecCommon.u2Tag); + StaRecCommon.u2Length = cpu2le16(StaRecCommon.u2Length); + StaRecCommon.u2ExtraInfo = cpu2le16(StaRecCommon.u2ExtraInfo); +#endif +#endif + kalMemCopy(pMsgBuf, + (char *)&StaRecCommon, + sizeof(struct STAREC_COMMON_T)); + return 0; +} + +static uint32_t BssInfoUpdateBasic( + struct ADAPTER *pAd, + uint8_t *pMsgBuf, + uint8_t ucBssIdx) +{ + struct BSSINFO_BASIC_T rBssInfo = {0}; + struct BSS_INFO *prBssInfo; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecBssInfo = + aisGetAisSpecBssInfo(pAd, ucBssIdx); + + prBssInfo = pAd->aprBssInfo[ucBssIdx]; + /* Tag assignment */ + rBssInfo.u2Tag = BSS_INFO_BASIC; + rBssInfo.u2Length = sizeof(struct BSSINFO_BASIC_T); + /* content */ + kalMemCopy(rBssInfo.aucBSSID, prBssInfo->aucBSSID, MAC_ADDR_LEN); + rBssInfo.ucBcMcWlanidx = ucBssIdx; + rBssInfo.ucActive = TRUE; + rBssInfo.ucWmmIdx = prBssInfo->ucWmmQueSet; + rBssInfo.ucCipherSuit = + prAisSpecBssInfo->ucKeyAlgorithmId; + +/* WA didn't use */ +/* +* rBssInfo.u4NetworkType = NETWORK_TYPE_AIS; +* rBssInfo.u2BcnInterval = 100; +* rBssInfo.ucDtimPeriod = 1; +*/ + + /* Append this feature */ + kalMemCopy(pMsgBuf, + (char *)&rBssInfo, + sizeof(struct BSSINFO_BASIC_T)); + return 0; +} + +static uint32_t BssInfoUpdateConnectOwnDev( + struct ADAPTER *pAd, + uint8_t *pMsgBuf, + uint8_t ucBssIdx) +{ + struct BSSINFO_CONNECT_OWN_DEV_T rBssInfo = {0}; + struct BSS_INFO *prBssInfo; + + prBssInfo = pAd->aprBssInfo[ucBssIdx]; + /* Tag assignment */ + rBssInfo.u2Tag = BSS_INFO_OWN_MAC; + rBssInfo.u2Length = sizeof(struct BSSINFO_CONNECT_OWN_DEV_T); + /* content */ + rBssInfo.ucHwBSSIndex = ucBssIdx; + rBssInfo.ucOwnMacIdx = prBssInfo->ucOwnMacIndex; + rBssInfo.ucConnectionType = CPU_TO_LE32(CONNECTION_INFRA_STA); + + /* Append this feature */ + kalMemCopy(pMsgBuf, + (char *)&rBssInfo, + sizeof(struct BSSINFO_CONNECT_OWN_DEV_T)); + return 0; +} + +static uint32_t DevInfoUpdateBasic( + struct ADAPTER *pAd, + uint8_t *pMsgBuf, + uint8_t ucBssIdx) +{ + struct CMD_DEVINFO_ACTIVE_T rDevInfo = {0}; + struct BSS_INFO *prBssInfo; + + prBssInfo = pAd->aprBssInfo[ucBssIdx]; + + /* Tag assignment */ + rDevInfo.u2Tag = DEV_INFO_ACTIVE; + rDevInfo.u2Length = sizeof(struct CMD_DEVINFO_ACTIVE_T); + /* content */ + kalMemCopy(rDevInfo.aucOwnMacAddr, + prBssInfo->aucOwnMacAddr, MAC_ADDR_LEN); + rDevInfo.ucActive = TRUE; + rDevInfo.ucDbdcIdx = 0; + + /* Append this feature */ + kalMemCopy(pMsgBuf, + (char *)&rDevInfo, + sizeof(struct CMD_DEVINFO_ACTIVE_T)); + return 0; +} + +uint32_t CmdExtStaRecUpdate2WA( + struct ADAPTER *pAd, + struct STA_RECORD *pStaRecCfg) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + uint32_t size; + struct CMD_STAREC_UPDATE_T *prCmdContent; + + size = sizeof(struct CMD_STAREC_UPDATE_T); + size += sizeof(struct STAREC_COMMON_T); + + prCmdContent = cnmMemAlloc(pAd, RAM_TYPE_BUF, size); + if (!prCmdContent) { + log_dbg(MEM, WARN, + "%s: command allocation failed\n", + __func__); + + return WLAN_STATUS_RESOURCES; + } + + prCmdContent->ucBssIndex = pStaRecCfg->ucBssIndex; + prCmdContent->ucWlanIdx = pStaRecCfg->ucWlanIndex; + prCmdContent->ucMuarIdx = 0; + + StaRecUpdateBasic(pAd, + (uint8_t *)prCmdContent+sizeof(struct CMD_STAREC_UPDATE_T), + (void *)pStaRecCfg); + + rWlanStatus = wlanSendSetQueryExtCmd2WA(pAd, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_STAREC_UPDATE, + TRUE, + FALSE, + TRUE, + NULL, + nicOidCmdTimeoutCommon, + size, + (uint8_t *) (prCmdContent), + NULL, 0); + cnmMemFree(pAd, prCmdContent); + return rWlanStatus; +} + +#if (CFG_SUPPORT_DMASHDL_SYSDVT) +/* Inform DVT item to WA */ +uint32_t CmdExtDmaShdlDvt2WA( + struct ADAPTER *pAd, + uint8_t ucItemNo, + uint8_t ucSubItemNo) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + uint32_t size; + struct EXT_CMD_CR4_DMASHDL_DVT_T *prCmdContent; + + size = sizeof(struct EXT_CMD_CR4_DMASHDL_DVT_T); + + prCmdContent = cnmMemAlloc(pAd, RAM_TYPE_BUF, size); + if (!prCmdContent) { + log_dbg(MEM, WARN, + "%s: command allocation failed\n", + __func__); + + return WLAN_STATUS_RESOURCES; + } + + prCmdContent->ucItemNo = ucItemNo; + prCmdContent->ucSubItemNo = ucSubItemNo; + + rWlanStatus = wlanSendSetQueryExtCmd2WA(pAd, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_CR4_DMASHDL_DVT, + TRUE, + FALSE, + TRUE, + NULL, + nicOidCmdTimeoutCommon, + size, + (uint8_t *) (prCmdContent), + NULL, 0); + cnmMemFree(pAd, prCmdContent); + return rWlanStatus; +} +#endif /* CFG_SUPPORT_DMASHDL_SYSDVT */ + +uint32_t CmdExtBssInfoUpdate2WA( + struct ADAPTER *pAd, + uint8_t ucBssIndex) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + uint32_t size; + struct BSS_INFO *prBssInfo; + struct CMD_BSSINFO_UPDATE_T *prCmdContent; + + ASSERT(pAd); + ASSERT(ucBssIndex <= pAd->ucHwBssIdNum); + + prBssInfo = pAd->aprBssInfo[ucBssIndex]; + + size = sizeof(struct CMD_BSSINFO_UPDATE_T); + size += sizeof(struct BSSINFO_BASIC_T); + size += sizeof(struct BSSINFO_CONNECT_OWN_DEV_T); + + prCmdContent = cnmMemAlloc(pAd, RAM_TYPE_BUF, size); + if (!prCmdContent) { + log_dbg(MEM, WARN, + "%s: command allocation failed\n", + __func__); + return WLAN_STATUS_RESOURCES; + } + + prCmdContent->ucBssIndex = ucBssIndex; + prCmdContent->u2TotalElementNum = 1; + + BssInfoUpdateBasic(pAd, + (uint8_t *)prCmdContent+sizeof(struct CMD_BSSINFO_UPDATE_T), + ucBssIndex); + + BssInfoUpdateConnectOwnDev(pAd, + (uint8_t *)prCmdContent + + sizeof(struct CMD_BSSINFO_UPDATE_T) + + sizeof(struct BSSINFO_BASIC_T), + ucBssIndex); + + rWlanStatus = wlanSendSetQueryExtCmd2WA(pAd, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_BSSINFO_UPDATE, + TRUE, + FALSE, + TRUE, + NULL, + nicOidCmdTimeoutCommon, + size, + (uint8_t *) (prCmdContent), + NULL, 0); + cnmMemFree(pAd, prCmdContent); + return rWlanStatus; +} + +uint32_t CmdExtDevInfoUpdate2WA( + struct ADAPTER *pAd, + uint8_t ucBssIndex) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + uint32_t size; + struct CMD_DEVINFO_UPDATE_T *prCmdContent; + struct BSS_INFO *prBssInfo; + + prBssInfo = pAd->aprBssInfo[ucBssIndex]; + + ASSERT(pAd); + + size = sizeof(struct CMD_DEVINFO_UPDATE_T); + size += sizeof(struct CMD_DEVINFO_ACTIVE_T); + + prCmdContent = cnmMemAlloc(pAd, RAM_TYPE_BUF, size); + if (!prCmdContent) { + log_dbg(MEM, WARN, + "%s: command allocation failed\n", + __func__); + + return WLAN_STATUS_RESOURCES; + } + + prCmdContent->ucOwnMacIdx = prBssInfo->ucOwnMacIndex; + prCmdContent->u2TotalElementNum = 1; + + DevInfoUpdateBasic(pAd, + (uint8_t *)prCmdContent+sizeof(struct CMD_DEVINFO_UPDATE_T), + ucBssIndex); + + rWlanStatus = wlanSendSetQueryExtCmd2WA(pAd, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_DEVINFO_UPDATE, + TRUE, + FALSE, + TRUE, + NULL, + nicOidCmdTimeoutCommon, + size, + (uint8_t *) (prCmdContent), + NULL, 0); + cnmMemFree(pAd, prCmdContent); + return rWlanStatus; +} + +#endif /* CFG_SUPPORT_CONNAC2X == 1 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_pwr_mgt.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_pwr_mgt.c new file mode 100644 index 0000000000000..48da5e3f0f296 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_pwr_mgt.c @@ -0,0 +1,424 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + + +/******************************************************************************* + * C O M P I L E 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 + ******************************************************************************* + */ + +void nicpmWakeUpWiFi(IN struct ADAPTER *prAdapter) +{ + if (!nicVerifyChipID(prAdapter)) { + DBGLOG(INIT, ERROR, "Chip id verify error!\n"); + return; + } + HAL_WAKE_UP_WIFI(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to process the POWER ON procedure. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicpmSetFWOwn(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnableGlobalInt) +{ + halSetFWOwn(prAdapter, fgEnableGlobalInt); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to process the POWER OFF procedure. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +u_int8_t nicpmSetDriverOwn(IN struct ADAPTER *prAdapter) +{ + return halSetDriverOwn(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to set ACPI power mode to D0. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +u_int8_t nicpmSetAcpiPowerD0(IN struct ADAPTER *prAdapter) +{ + +#if 0 + uint32_t u4Status = WLAN_STATUS_SUCCESS; + uint32_t u4Value = 0, u4WHISR = 0; + uint16_t au2TxCount[16]; + uint32_t i; +#if CFG_ENABLE_FW_DOWNLOAD + uint32_t u4FwImgLength, u4FwLoadAddr, u4Cr4FwImgLength; + void *prFwMappingHandle; + void *pvFwImageMapFile = NULL; + void *pvCr4FwImageMapFile = NULL; +#if CFG_ENABLE_FW_DIVIDED_DOWNLOAD + struct FIRMWARE_DIVIDED_DOWNLOAD *prFwHead; + u_int8_t fgValidHead = TRUE; + +#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(MT6630) + /* 1. Request Ownership to enter F/W download state */ + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); +#if !CFG_ENABLE_FULL_PM + nicpmSetDriverOwn(prAdapter); +#endif + + /* 2. Initialize the Adapter */ + u4Status = nicInitializeAdapter(prAdapter); + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "nicInitializeAdapter failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } +#endif + +#if CFG_ENABLE_FW_DOWNLOAD + prFwMappingHandle = + kalFirmwareImageMapping(prAdapter->prGlueInfo, + &pvFwImageMapFile, &u4FwImgLength, + &pvCr4FwImageMapFile, &u4Cr4FwImgLength); + if (!prFwMappingHandle) { + DBGLOG(INIT, ERROR, + "Fail to load FW image from file!\n"); + pvFwImageMapFile = NULL; + } +#if defined(MT6630) + 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 = + (struct FIRMWARE_DIVIDED_DOWNLOAD *) + ((uint8_t *) + pvFwImageMapFile + u4FwImgLength - + (2 * sizeof(struct FWDL_SECTION_INFO))); +#if 0 + if (prFwHead->u4Signature == MTK_WIFI_SIGNATURE && + prFwHead->u4CRC == wlanCRC32( + (uint8_t *) pvFwImageMapFile + + u4CRCOffset, + u4FwImgLength - u4CRCOffset)) { + fgValidHead = TRUE; + } else { + fgValidHead = FALSE; + } +#endif + /* 3b. engage divided firmware downloading */ + if (fgValidHead == TRUE) { + wlanFwDvdDwnloadHandler(prAdapter, prFwHead, + pvFwImageMapFile, &u4Status); + } else +#endif + { + if (wlanImageSectionConfig(prAdapter, + u4FwLoadAddr, + u4FwImgLength, TRUE) + != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "Firmware download configuration failed!\n"); + + u4Status = WLAN_STATUS_FAILURE; + break; + } + wlanFwDwnloadHandler(prAdapter, u4FwImgLength, + pvFwImageMapFile, &u4Status); + } + /* escape to top */ + if (u4Status != WLAN_STATUS_SUCCESS) { + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, + prFwMappingHandle, pvFwImageMapFile, + pvCr4FwImageMapFile); + 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, + pvCr4FwImageMapFile); + u4Status = WLAN_STATUS_FAILURE; + break; + } +#endif + + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, + prFwMappingHandle, pvFwImageMapFile, + pvCr4FwImageMapFile); + } 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 +#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; + } + i++; + kalMsleep(10); + } + + if (u4Status == WLAN_STATUS_SUCCESS) { + /* 6.1 reset interrupt status */ + HAL_READ_INTR_STATUS(prAdapter, 4, (uint8_t *)&u4WHISR); + if (HAL_IS_TX_DONE_INTR(u4WHISR)) + HAL_READ_TX_RELEASED_COUNT(prAdapter, + au2TxCount); + + /* 6.2 reset TX Resource for normal operation */ + nicTxResetResource(prAdapter); + + /* 6.3 Enable interrupt */ + nicEnableInterrupt(prAdapter); + + /* 6.4 Update basic configuration */ + wlanUpdateBasicConfig(prAdapter); + + /* 6.5 Apply Network Address */ + nicApplyNetworkAddress(prAdapter); + + /* 6.6 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; +#else + return TRUE; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is used to set ACPI power mode to D3. + * + * @param prAdapter pointer to the Adapter handler + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +u_int8_t nicpmSetAcpiPowerD3(IN struct ADAPTER *prAdapter) +{ + /* UINT_32 i; */ + + ASSERT(prAdapter); + +#if 0 + /* 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, TRUE); + + /* 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; +#endif + return TRUE; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_rate.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_rate.c new file mode 100644 index 0000000000000..c64deedf2c0dd --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_rate.c @@ -0,0 +1,1181 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/*! \file "nic_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. + */ + + +/******************************************************************************* + * C O M P I L E 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 RA_FIXEDRATE_FIELD_CCK_MCS_S 0 +#define RA_FIXEDRATE_FIELD_CCK_MCS_E 1 +#define RA_FIXEDRATE_FIELD_S_PREAMBLE 2 +#define RA_FIXEDRATE_FIELD_MCS_S 0 +#define RA_FIXEDRATE_FIELD_MCS_E 5 + +#define RA_FIXEDRATE_V1_FIELD_MODE_S 6 +#define RA_FIXEDRATE_V1_FIELD_MODE_E 8 +#define RA_FIXEDRATE_V1_FIELD_VHTNSS_S 9 +#define RA_FIXEDRATE_V1_FIELD_VHTNSS_E 10 + +#define RA_FIXEDRATE_V2_FIELD_MODE_S 6 +#define RA_FIXEDRATE_V2_FIELD_MODE_E 10 +#define RA_FIXEDRATE_V2_FIELD_VHTNSS_S 12 +#define RA_FIXEDRATE_V2_FIELD_VHTNSS_E 14 + +#define RA_FIXEDRATE_FIELD_STBC 11 + +#define RA_FIXEDRATE_FIELD_HE_LTF_MASK BITS(15, 16) +#define RA_FIXEDRATE_FIELD_HE_LTF_OFFSET 15 +#define RA_FIXEDRATE_FIELD_HE_GI_MASK BITS(17, 18) +#define RA_FIXEDRATE_FIELD_HE_GI_OFFSET 17 +#define RA_FIXEDRATE_FIELD_HE_ER_DCM 19 +#define RA_FIXEDRATE_FIELD_HE_ER_106 20 + +#define RA_FIXEDRATE_FIELD_FORMAT_VER_MASK BITS(23, 24) +#define RA_FIXEDRATE_FIELD_FORMAT_VER_OFFSET 23 + +#define RA_FIXEDRATE_FIELD_BAND 25 +#define RA_FIXEDRATE_FIELD_BW_S 26 +#define RA_FIXEDRATE_FIELD_BW_E 27 +#define RA_FIXEDRATE_FIELD_SPEEN 28 +#define RA_FIXEDRATE_FIELD_LDPC 29 +#define RA_FIXEDRATE_FIELD_SGI 30 +#define RA_FIXEDRATE BIT(31) + + +const uint16_t au2RateCCKLong[CCK_RATE_NUM] = { + 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 */ +}; + +const uint16_t au2RateCCKShort[CCK_RATE_NUM] = { + 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 */ +}; + +const uint16_t au2RateOFDM[OFDM_RATE_NUM] = { + 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 */ +}; + +const uint16_t au2RateHTMixed[HT_RATE_NUM] = { + RATE_MM_MCS_32, /* RATE_MCS32_INDEX, */ + 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, */ +}; + +const uint16_t au2RateHTGreenField[HT_RATE_NUM] = { + RATE_GF_MCS_32, /* RATE_MCS32_INDEX, */ + 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, */ +}; + +const uint16_t au2RateVHT[VHT_RATE_NUM] = { + RATE_VHT_MCS_0, /* RATE_MCS0_INDEX, */ + RATE_VHT_MCS_1, /* RATE_MCS1_INDEX, */ + RATE_VHT_MCS_2, /* RATE_MCS2_INDEX, */ + RATE_VHT_MCS_3, /* RATE_MCS3_INDEX, */ + RATE_VHT_MCS_4, /* RATE_MCS4_INDEX, */ + RATE_VHT_MCS_5, /* RATE_MCS5_INDEX, */ + RATE_VHT_MCS_6, /* RATE_MCS6_INDEX, */ + RATE_VHT_MCS_7, /* RATE_MCS7_INDEX, */ + RATE_VHT_MCS_8, /* RATE_MCS8_INDEX, */ + RATE_VHT_MCS_9 /* RATE_MCS9_INDEX, */ +}; + +/* in unit of 100kb/s */ +const struct EMU_MAC_RATE_INFO arMcsRate2PhyRate[] = { + /* Phy Rate Code, + * BW20, BW20 SGI, BW40, BW40 SGI, BW80, BW80 SGI, BW160, BW160 SGI + */ + RATE_INFO(PHY_RATE_MCS0, 65, 72, 135, 150, 293, 325, 585, 650), + RATE_INFO(PHY_RATE_MCS1, 130, 144, 270, 300, 585, 650, 1170, 1300), + RATE_INFO(PHY_RATE_MCS2, 195, 217, 405, 450, 878, 975, 1755, 1950), + RATE_INFO(PHY_RATE_MCS3, 260, 289, 540, 600, 1170, 1300, 2340, 2600), + RATE_INFO(PHY_RATE_MCS4, 390, 433, 810, 900, 1755, 1950, 3510, 3900), + RATE_INFO(PHY_RATE_MCS5, 520, 578, 1080, 1200, 2340, 2600, 4680, 5200), + RATE_INFO(PHY_RATE_MCS6, 585, 650, 1215, 1350, 2633, 2925, 5265, 5850), + RATE_INFO(PHY_RATE_MCS7, 650, 722, 1350, 1500, 2925, 3250, 5850, 6500), + RATE_INFO(PHY_RATE_MCS8, 780, 867, 1620, 1800, 3510, 3900, 7020, 7800), + RATE_INFO(PHY_RATE_MCS9, 867, 963, 1800, 2000, 3900, 4333, 7800, 8667), + RATE_INFO(PHY_RATE_MCS32, 0, 0, 60, 67, 0, 0, 0, 0) +}; + +/* in uint of 500kb/s */ +const uint8_t aucHwRate2PhyRate[] = { + RATE_1M, /*1M long */ + RATE_2M, /*2M long */ + RATE_5_5M, /*5.5M long */ + RATE_11M, /*11M long */ + RATE_1M, /*1M short invalid */ + RATE_2M, /*2M short */ + RATE_5_5M, /*5.5M short */ + RATE_11M, /*11M short */ + RATE_48M, /*48M */ + RATE_24M, /*24M */ + RATE_12M, /*12M */ + RATE_6M, /*6M */ + RATE_54M, /*54M */ + RATE_36M, /*36M */ + RATE_18M, /*18M */ + RATE_9M /*9M */ +}; +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +char *HW_TX_MODE_STR[] = { + "CCK", "OFDM", "MM", "GF", "VHT", "PLR", + "N/A", "N/A", "HE_SU", "HE_ER", "HE_TRIG", "HE_MU"}; +char *HW_TX_RATE_CCK_STR[] = {"1M", "2M", "5.5M", "11M", "N/A"}; +char *HW_TX_RATE_OFDM_STR[] = {"6M", "9M", "12M", "18M", "24M", "36M", + "48M", "54M", "N/A"}; +char *HW_TX_RATE_BW[] = {"BW20", "BW40", "BW80", "BW160/BW8080", "N/A"}; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +#define TX_GET_GI(_gi, _mode) \ + ((_mode) >= TX_RATE_MODE_HE_SU ? (((_gi) & 0xf0) >> 4) : ((_gi) & 0xf)) + +/******************************************************************************* + * 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 + ******************************************************************************* + */ +uint32_t +nicGetPhyRateByMcsRate( + IN uint8_t ucIdx, + IN uint8_t ucBw, + IN uint8_t ucGI) +{ + return arMcsRate2PhyRate[ucIdx].u4PhyRate[ucBw][ucGI]; +} + +uint32_t +nicGetHwRateByPhyRate( + IN uint8_t ucIdx) +{ + return aucHwRate2PhyRate[ucIdx]; /* uint : 500 kbps */ +} + +uint32_t +nicSwIndex2RateIndex( + IN uint8_t ucRateSwIndex, + OUT uint8_t *pucRateIndex, + OUT uint8_t *pucPreambleOption +) +{ + ASSERT(pucRateIndex); + ASSERT(pucPreambleOption); + + if (ucRateSwIndex >= RATE_6M_SW_INDEX) { + *pucRateIndex = ucRateSwIndex - RATE_6M_SW_INDEX; + *pucPreambleOption = PREAMBLE_OFDM_MODE; + } else { + *pucRateIndex = ucRateSwIndex; + *pucPreambleOption = PREAMBLE_DEFAULT_LONG_NONE; + } + return WLAN_STATUS_SUCCESS; +} + +uint32_t nicRateIndex2RateCode(IN uint8_t ucPreambleOption, + IN uint8_t ucRateIndex, OUT uint16_t *pu2RateCode) +{ + switch (ucPreambleOption) { + case PREAMBLE_DEFAULT_LONG_NONE: + if (ucRateIndex >= CCK_RATE_NUM) + return WLAN_STATUS_INVALID_DATA; + *pu2RateCode = au2RateCCKLong[ucRateIndex]; + break; + + case PREAMBLE_OPTION_SHORT: + if (ucRateIndex >= CCK_RATE_NUM) + return WLAN_STATUS_INVALID_DATA; + *pu2RateCode = au2RateCCKShort[ucRateIndex]; + break; + + case PREAMBLE_OFDM_MODE: + if (ucRateIndex >= OFDM_RATE_NUM) + return WLAN_STATUS_INVALID_DATA; + *pu2RateCode = au2RateOFDM[ucRateIndex]; + break; + + case PREAMBLE_HT_MIXED_MODE: + if (ucRateIndex >= HT_RATE_NUM) + return WLAN_STATUS_INVALID_DATA; + *pu2RateCode = au2RateHTMixed[ucRateIndex]; + break; + + case PREAMBLE_HT_GREEN_FIELD: + if (ucRateIndex >= HT_RATE_NUM) + return WLAN_STATUS_INVALID_DATA; + *pu2RateCode = au2RateHTGreenField[ucRateIndex]; + break; + + case PREAMBLE_VHT_FIELD: + if (ucRateIndex >= VHT_RATE_NUM) + return WLAN_STATUS_INVALID_DATA; + *pu2RateCode = au2RateVHT[ucRateIndex]; + break; + + default: + return WLAN_STATUS_INVALID_DATA; + } + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +nicRateCode2PhyRate( + IN uint16_t u2RateCode, + IN uint8_t ucBandwidth, + IN uint8_t ucGI, + IN uint8_t ucRateNss) +{ + uint8_t ucPhyRate; + uint16_t u2TxMode; + uint32_t u4PhyRateBy1SS, u4PhyRateIn100Kbps = 0; + + ucPhyRate = RATE_CODE_GET_PHY_RATE(u2RateCode); + u2TxMode = u2RateCode & RATE_TX_MODE_MASK; + ucRateNss = ucRateNss + AR_SS_1; /* change to be base=1 */ + + if ((u2TxMode == TX_MODE_HT_GF) + || (u2TxMode == TX_MODE_HT_MM)) { + + if (ucPhyRate > PHY_RATE_MCS7) + u2RateCode = u2RateCode - HT_RATE_MCS7_INDEX; + else + ucRateNss = AR_SS_1; + + } else if ((u2TxMode == TX_MODE_OFDM) + || (u2TxMode == TX_MODE_CCK)) { + ucRateNss = AR_SS_1; + } + DBGLOG(NIC, LOUD, + "Coex:nicRateCode2PhyRate,RC:%x,B:%d,I:%d\n", + u2RateCode, ucBandwidth, ucGI); + + u4PhyRateBy1SS = nicRateCode2DataRate(u2RateCode, + ucBandwidth, ucGI); + u4PhyRateIn100Kbps = u4PhyRateBy1SS * ucRateNss; + + DBGLOG(NIC, LOUD, + "Coex:nicRateCode2PhyRate,1ss R:%d,PHY R:%d\n", + u4PhyRateBy1SS, u4PhyRateIn100Kbps); + + return u4PhyRateIn100Kbps; +} + +uint32_t +nicRateCode2DataRate( + IN uint16_t u2RateCode, + IN uint8_t ucBandwidth, + IN uint8_t ucGI) +{ + uint8_t ucPhyRate, ucIdx, ucBw = 0; + uint32_t u4PhyRateIn100Kbps = 0; + uint16_t u2TxMode; + + if ((ucBandwidth == FIX_BW_NO_FIXED) + || (ucBandwidth == FIX_BW_20)) + ucBw = MAC_BW_20; + else if (ucBandwidth == FIX_BW_40) + ucBw = MAC_BW_40; + else if (ucBandwidth == FIX_BW_80) + ucBw = MAC_BW_80; + else if (ucBandwidth == FIX_BW_160) + ucBw = MAC_BW_160; + + ucPhyRate = RATE_CODE_GET_PHY_RATE(u2RateCode); + u2TxMode = u2RateCode & RATE_TX_MODE_MASK; + /* Set MMSS parameter if HT/VHT rate */ + if ((u2TxMode == TX_MODE_HT_GF) || + (u2TxMode == TX_MODE_HT_MM) || + (u2TxMode == TX_MODE_VHT)) { + /* No SGI Greenfield for 1T */ + /* Refer to section 20.3.11.11.6 of IEEE802.11-2012 */ + if (u2TxMode == TX_MODE_HT_GF) + ucGI = MAC_GI_NORMAL; + + ucIdx = ucPhyRate; + + if (ucIdx == PHY_RATE_MCS32) + ucIdx = 10; + + u4PhyRateIn100Kbps = nicGetPhyRateByMcsRate(ucIdx, ucBw, + ucGI); + } else if ((u2TxMode == TX_MODE_OFDM) || + (u2TxMode == TX_MODE_CCK)) { + u4PhyRateIn100Kbps = (nicGetHwRateByPhyRate( + ucPhyRate & BITS(0, 3))) * 5; + } else { + ASSERT(FALSE); + } + return u4PhyRateIn100Kbps; +} + +u_int8_t +nicGetRateIndexFromRateSetWithLimit( + IN uint16_t u2RateSet, + IN uint32_t u4PhyRateLimit, + IN u_int8_t fgGetLowest, + OUT uint8_t *pucRateSwIndex) +{ + uint32_t i; + uint32_t u4CurPhyRate, u4TarPhyRate, u4HighestPhyRate, + u4LowestPhyRate; + uint8_t ucRateIndex, ucRatePreamble, ucTarRateSwIndex, + ucHighestPhyRateSwIdx, ucLowestPhyRateSwIdx; + uint16_t u2CurRateCode; + uint32_t u4Status; + + /* Set init value */ + if (fgGetLowest) { + u4TarPhyRate = 0xFFFFFFFF; + u4HighestPhyRate = 0; + ucHighestPhyRateSwIdx = RATE_NUM_SW; + } else { + u4TarPhyRate = 0; + u4LowestPhyRate = 0xFFFFFFFF; + ucLowestPhyRateSwIdx = RATE_NUM_SW; + } + + ucTarRateSwIndex = RATE_NUM_SW; + + /* Find SW rate index by limitation */ + for (i = RATE_1M_SW_INDEX; i <= RATE_54M_SW_INDEX; i++) { + if (u2RateSet & BIT(i)) { + + /* Convert SW rate index to phy rate in 100kbps */ + nicSwIndex2RateIndex(i, &ucRateIndex, &ucRatePreamble); + u4Status = nicRateIndex2RateCode(ucRatePreamble, + ucRateIndex, &u2CurRateCode); + + if (u4Status != WLAN_STATUS_SUCCESS) + continue; + + u4CurPhyRate = + nicRateCode2DataRate(u2CurRateCode, MAC_BW_20, + MAC_GI_NORMAL); + + /* Compare */ + if (fgGetLowest) { + if (u4HighestPhyRate < u4CurPhyRate) { + u4HighestPhyRate = u4CurPhyRate; + ucHighestPhyRateSwIdx = i; + } + if ((u4CurPhyRate >= u4PhyRateLimit) + && (u4CurPhyRate <= u4TarPhyRate)) { + u4TarPhyRate = u4CurPhyRate; + ucTarRateSwIndex = i; + } + } else { + if (u4LowestPhyRate > u4CurPhyRate) { + u4LowestPhyRate = u4CurPhyRate; + ucLowestPhyRateSwIdx = i; + } + if ((u4CurPhyRate <= u4PhyRateLimit) + && (u4CurPhyRate >= u4TarPhyRate)) { + u4TarPhyRate = u4CurPhyRate; + ucTarRateSwIndex = i; + } + } + } + } + + /* Return target SW rate index */ + if (ucTarRateSwIndex < RATE_NUM_SW) { + *pucRateSwIndex = ucTarRateSwIndex; + } else { + if (fgGetLowest) + *pucRateSwIndex = ucHighestPhyRateSwIdx; + else + *pucRateSwIndex = ucLowestPhyRateSwIdx; + } + return TRUE; +} + +char *nicHwRateOfdmStr( + uint16_t ofdm_idx) +{ + switch (ofdm_idx) { + case 11: /* 6M */ + return HW_TX_RATE_OFDM_STR[0]; + case 15: /* 9M */ + return HW_TX_RATE_OFDM_STR[1]; + case 10: /* 12M */ + return HW_TX_RATE_OFDM_STR[2]; + case 14: /* 18M */ + return HW_TX_RATE_OFDM_STR[3]; + case 9: /* 24M */ + return HW_TX_RATE_OFDM_STR[4]; + case 13: /* 36M */ + return HW_TX_RATE_OFDM_STR[5]; + case 8: /* 48M */ + return HW_TX_RATE_OFDM_STR[6]; + case 12: /* 54M */ + return HW_TX_RATE_OFDM_STR[7]; + default: + return HW_TX_RATE_OFDM_STR[8]; + } +} + +uint32_t nicSetFixedRateData( + struct FIXED_RATE_INFO *pFixedRate, + uint32_t *pu4Data) +{ + uint32_t u4Data = 0; + uint8_t u4Nsts = 1; + uint8_t u1FormatVer; + uint8_t u1TxModeMcsNumMax[ENUM_TX_MODE_NUM]; + + kalMemZero(u1TxModeMcsNumMax, ENUM_TX_MODE_NUM); + /* u1TxModeMcsNumMax[ENUM_TX_MODE_NUM] = {4, 8, 33, 33, 10}; */ + u1TxModeMcsNumMax[ENUM_TX_MODE_CCK] = 4; + u1TxModeMcsNumMax[ENUM_TX_MODE_OFDM] = 8; + u1TxModeMcsNumMax[ENUM_TX_MODE_MM] = 33; + u1TxModeMcsNumMax[ENUM_TX_MODE_GF] = 33; + u1TxModeMcsNumMax[ENUM_TX_MODE_VHT] = 10; + +#if (CFG_SUPPORT_802_11AX == 1) + if (fgEfuseCtrlAxOn == 1) { + /* u1TxModeMcsNumMax[ENUM_TX_MODE_NUM] */ + /* = {4, 8, 33, 33, 10, 2, 0, 0, 12, 12, 12, 12}; */ + u1TxModeMcsNumMax[ENUM_TX_MODE_PLR] = 2; + u1TxModeMcsNumMax[ENUM_TX_MODE_HE_SU] = 12; + u1TxModeMcsNumMax[ENUM_TX_MODE_HE_ER] = 12; + u1TxModeMcsNumMax[ENUM_TX_MODE_HE_TRIG] = 12; + u1TxModeMcsNumMax[ENUM_TX_MODE_HE_MU] = 12; + } +#endif + + u4Data |= RA_FIXEDRATE; + + u1FormatVer = (pFixedRate->u4Mode < TX_RATE_MODE_HE_SU) ? + RATE_VER_1 : RATE_VER_2; + + u4Data |= ((u1FormatVer << RA_FIXEDRATE_FIELD_FORMAT_VER_OFFSET) + & RA_FIXEDRATE_FIELD_FORMAT_VER_MASK); + + if (u1FormatVer == RATE_VER_1) { + if (pFixedRate->u4SGI) + u4Data |= BIT(RA_FIXEDRATE_FIELD_SGI); + } else { + if (pFixedRate->u4SGI < GI_HE_NUM) + u4Data |= ((pFixedRate->u4SGI << + RA_FIXEDRATE_FIELD_HE_GI_OFFSET) & + RA_FIXEDRATE_FIELD_HE_GI_MASK); + else + DBGLOG(INIT, ERROR, + "Wrong HE GI! SGI=0, MGI=1, LGI=2\n"); + } + + if (pFixedRate->u4LDPC) + u4Data |= BIT(RA_FIXEDRATE_FIELD_LDPC); + if (pFixedRate->u4SpeEn) + u4Data |= BIT(RA_FIXEDRATE_FIELD_SPEEN); + if (pFixedRate->u4STBC) + u4Data |= BIT(RA_FIXEDRATE_FIELD_STBC); + + if (pFixedRate->u4Bw <= MAC_BW_160) + u4Data |= ((pFixedRate->u4Bw << RA_FIXEDRATE_FIELD_BW_S) + & BITS(RA_FIXEDRATE_FIELD_BW_S, RA_FIXEDRATE_FIELD_BW_E)); + else { + DBGLOG(INIT, ERROR, + "Wrong BW! BW20=0, BW40=1, BW80=2,BW160=3\n"); + return WLAN_STATUS_INVALID_DATA; + } + + if (pFixedRate->u4Mode < ENUM_TX_MODE_NUM) { + if (u1FormatVer == RATE_VER_1) + u4Data |= + ((pFixedRate->u4Mode << RA_FIXEDRATE_V1_FIELD_MODE_S) + & BITS(RA_FIXEDRATE_V1_FIELD_MODE_S, + RA_FIXEDRATE_V1_FIELD_MODE_E)); + else + u4Data |= + ((pFixedRate->u4Mode << RA_FIXEDRATE_V2_FIELD_MODE_S) + & BITS(RA_FIXEDRATE_V2_FIELD_MODE_S, + RA_FIXEDRATE_V2_FIELD_MODE_E)); + + if (pFixedRate->u4Mcs < u1TxModeMcsNumMax[pFixedRate->u4Mode]) { + if (pFixedRate->u4Mode != TX_RATE_MODE_OFDM) + u4Data |= pFixedRate->u4Mcs; + } else { + DBGLOG(INIT, ERROR, "%s mode but wrong MCS(=%d)!\n", + HW_TX_MODE_STR[pFixedRate->u4Mode], + pFixedRate->u4Mcs); + return WLAN_STATUS_INVALID_DATA; + } + + switch (pFixedRate->u4Mode) { + case TX_RATE_MODE_CCK: + if (pFixedRate->u4Preamble) + if (pFixedRate->u4Mcs > 0) + u4Data |= + BIT(RA_FIXEDRATE_FIELD_S_PREAMBLE); + else { + DBGLOG(INIT, ERROR, "SP but MCS=0!\n"); + return WLAN_STATUS_INVALID_DATA; + } + else + u4Data &= ~BIT(RA_FIXEDRATE_FIELD_S_PREAMBLE); + break; + case TX_RATE_MODE_OFDM: + switch (pFixedRate->u4Mcs) { + case 0: + /* 6'b001011 */ + u4Data |= 11; + break; + case 1: + /* 6'b001111 */ + u4Data |= 15; + break; + case 2: + /* 6'b001010 */ + u4Data |= 10; + break; + case 3: + /* 6'b001110 */ + u4Data |= 14; + break; + case 4: + /* 6'b001001 */ + u4Data |= 9; + break; + case 5: + /* 6'b001101 */ + u4Data |= 13; + break; + case 6: + /* 6'b001000 */ + u4Data |= 8; + break; + case 7: + /* 6'b001100 */ + u4Data |= 12; + break; + default: + DBGLOG(INIT, ERROR, + "OFDM mode but wrong MCS!\n"); + return WLAN_STATUS_INVALID_DATA; + } + break; + case TX_RATE_MODE_HTMIX: + case TX_RATE_MODE_HTGF: + if (pFixedRate->u4Mcs != 32) { + u4Nsts += (pFixedRate->u4Mcs >> 3); + if (pFixedRate->u4STBC && (u4Nsts == 1)) + u4Nsts++; + } + break; + case TX_RATE_MODE_PLR: + break; + case TX_RATE_MODE_VHT: + case TX_RATE_MODE_HE_SU: + case TX_RATE_MODE_HE_ER: + case TX_RATE_MODE_HE_TRIG: + case TX_RATE_MODE_HE_MU: + if (pFixedRate->u4STBC && (pFixedRate->u4VhtNss == 1)) + u4Nsts++; + else + u4Nsts = pFixedRate->u4VhtNss; + break; + default: + break; + } + } else { + DBGLOG(INIT, ERROR, + "Wrong TxMode! CCK=0, OFDM=1, HT=2, GF=3, VHT=4"); + DBGLOG(INIT, ERROR, + "HE_SU=8, HE_ER_SU=9, HE_TRIG=10, HE_MU=11\n"); + return WLAN_STATUS_INVALID_DATA; + } + + if (u1FormatVer == RATE_VER_1) + u4Data |= (((u4Nsts - 1) << RA_FIXEDRATE_V1_FIELD_VHTNSS_S) + & BITS(RA_FIXEDRATE_V1_FIELD_VHTNSS_S, + RA_FIXEDRATE_V1_FIELD_VHTNSS_E)); + else { + u4Data |= (((u4Nsts - 1) << RA_FIXEDRATE_V2_FIELD_VHTNSS_S) + & BITS(RA_FIXEDRATE_V2_FIELD_VHTNSS_S, + RA_FIXEDRATE_V2_FIELD_VHTNSS_E)); + u4Data |= ((pFixedRate->u4HeLTF << + RA_FIXEDRATE_FIELD_HE_LTF_OFFSET) + & RA_FIXEDRATE_FIELD_HE_LTF_MASK); + + if (pFixedRate->u4Mode == TX_RATE_MODE_HE_ER) { + if (pFixedRate->u4HeErDCM) + u4Data |= RA_FIXEDRATE_FIELD_HE_ER_DCM; + if (pFixedRate->u4HeEr106t) + u4Data |= RA_FIXEDRATE_FIELD_HE_ER_106; + } + } + + *pu4Data = u4Data; + return WLAN_STATUS_SUCCESS; +} + +uint32_t nicRateHeLtfCheckGi( + struct FIXED_RATE_INFO *pFixedRate) +{ + uint32_t u4Mode, u4GI; + + u4Mode = pFixedRate->u4Mode; + u4GI = pFixedRate->u4SGI; + + if (u4Mode < TX_RATE_MODE_HE_SU) + return WLAN_STATUS_SUCCESS; + + switch (pFixedRate->u4HeLTF) { + case HE_LTF_1X: + if (u4GI == GI_HE_SGI) { + if ((u4Mode == TX_RATE_MODE_HE_SU) || + (u4Mode == TX_RATE_MODE_HE_ER)) + return WLAN_STATUS_SUCCESS; + } else if (u4GI == GI_HE_MGI) { + /* also need non-OFDMA */ + if (u4Mode == TX_RATE_MODE_HE_TRIG) + return WLAN_STATUS_SUCCESS; + } + break; + case HE_LTF_2X: + if (u4GI == GI_HE_SGI) { + if ((u4Mode == TX_RATE_MODE_HE_SU) || + (u4Mode == TX_RATE_MODE_HE_ER) || + (u4Mode == TX_RATE_MODE_HE_MU)) + return WLAN_STATUS_SUCCESS; + } else if (u4GI == GI_HE_MGI) { + if ((u4Mode >= TX_RATE_MODE_HE_SU) && + (u4Mode <= TX_RATE_MODE_HE_MU)) + return WLAN_STATUS_SUCCESS; + } + break; + case HE_LTF_4X: + if (u4GI == GI_HE_SGI) { + if ((u4Mode == TX_RATE_MODE_HE_SU) || + (u4Mode == TX_RATE_MODE_HE_ER) || + (u4Mode == TX_RATE_MODE_HE_MU)) + return WLAN_STATUS_SUCCESS; + } else if (u4GI == GI_HE_LGI) { + if ((u4Mode >= TX_RATE_MODE_HE_SU) && + (u4Mode <= TX_RATE_MODE_HE_MU)) + return WLAN_STATUS_SUCCESS; + } + break; + + default: + break; + } + + return WLAN_STATUS_FAILURE; +} + +uint8_t nicGetTxSgiInfo( + IN struct PARAM_PEER_CAP *prWtblPeerCap, + IN uint8_t u1TxMode) +{ + if (!prWtblPeerCap) + return FALSE; + + switch (prWtblPeerCap->ucFrequencyCapability) { + case BW_20: + return TX_GET_GI(prWtblPeerCap->fgG2, u1TxMode); + case BW_40: + return TX_GET_GI(prWtblPeerCap->fgG4, u1TxMode); + case BW_80: + return TX_GET_GI(prWtblPeerCap->fgG8, u1TxMode); + case BW_160: + return TX_GET_GI(prWtblPeerCap->fgG16, u1TxMode); + default: + return FALSE; + } +} + +uint8_t nicGetTxLdpcInfo( + IN struct PARAM_TX_CONFIG *prWtblTxConfig) +{ + if (!prWtblTxConfig) + return FALSE; + + if (prWtblTxConfig->fgIsHE) + return prWtblTxConfig->fgHeLDPC; + else if (prWtblTxConfig->fgIsVHT) + return prWtblTxConfig->fgVhtLDPC; + else + return prWtblTxConfig->fgLDPC; +} + +uint16_t nicGetStatIdxInfo(IN struct ADAPTER *prAdapter, + IN uint8_t ucWlanIdx) +{ + static uint8_t aucWlanIdxArray[CFG_STAT_DBG_PEER_NUM] = {0}; + static uint16_t u2ValidBitMask; /* support max 16 peers */ + uint8_t ucIdx, ucStaIdx, ucCnt = 0; + uint8_t ucWlanIdxExist; + + /* check every wlanIdx and unmask no longer used wlanIdx */ + for (ucIdx = 0; ucIdx < CFG_STAT_DBG_PEER_NUM; ucIdx++) { + if (u2ValidBitMask & BIT(ucIdx)) { + ucWlanIdxExist = aucWlanIdxArray[ucIdx]; + + if (wlanGetStaIdxByWlanIdx(prAdapter, ucWlanIdxExist, + &ucStaIdx) != WLAN_STATUS_SUCCESS) + u2ValidBitMask &= ~BIT(ucIdx); + } + } + + /* Search matched WlanIdx */ + for (ucIdx = 0; ucIdx < CFG_STAT_DBG_PEER_NUM; ucIdx++) { + if (u2ValidBitMask & BIT(ucIdx)) { + ucCnt++; + ucWlanIdxExist = aucWlanIdxArray[ucIdx]; + + if (ucWlanIdxExist == ucWlanIdx) { + DBGLOG(REQ, INFO, + "=== Matched, Mask=0x%x, ucIdx=%d ===\n", + u2ValidBitMask, ucIdx); + return ucIdx; + } + } + } + + /* No matched WlanIdx, add new one */ + if (ucCnt < CFG_STAT_DBG_PEER_NUM) { + for (ucIdx = 0; ucIdx < CFG_STAT_DBG_PEER_NUM; ucIdx++) { + if (~u2ValidBitMask & BIT(ucIdx)) { + u2ValidBitMask |= BIT(ucIdx); + aucWlanIdxArray[ucIdx] = ucWlanIdx; + DBGLOG(REQ, INFO, + "=== New Add, Mask=0x%x, ucIdx=%d ===\n", + u2ValidBitMask, ucIdx); + return ucIdx; + } + } + } + + return 0xFFFF; +} + +int32_t nicGetTxRateInfo(IN char *pcCommand, IN int i4TotalLen, + u_int8_t fgDumpAll, + struct PARAM_HW_WLAN_INFO *prHwWlanInfo, + struct PARAM_GET_STA_STATISTICS *prQueryStaStatistics) +{ + uint8_t i, txmode, rate, stbc, sgi; + uint8_t nsts; + int32_t i4BytesWritten = 0; + + for (i = 0; i < AUTO_RATE_NUM; i++) { + txmode = HW_TX_RATE_TO_MODE( + prHwWlanInfo->rWtblRateInfo.au2RateCode[i]); + if (txmode >= ENUM_TX_MODE_NUM) + txmode = ENUM_TX_MODE_NUM - 1; + rate = HW_TX_RATE_TO_MCS( + prHwWlanInfo->rWtblRateInfo.au2RateCode[i]); + nsts = HW_TX_RATE_TO_NSS( + prHwWlanInfo->rWtblRateInfo.au2RateCode[i]) + 1; + stbc = HW_TX_RATE_TO_STBC( + prHwWlanInfo->rWtblRateInfo.au2RateCode[i]); + sgi = nicGetTxSgiInfo(&prHwWlanInfo->rWtblPeerCap, txmode); + + if (fgDumpAll) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Rate index[%d] ", i); + + if (prHwWlanInfo->rWtblRateInfo.ucRateIdx == i) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "--> "); + } else { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", " "); + } + } + + if (!fgDumpAll) { + if (prHwWlanInfo->rWtblRateInfo.ucRateIdx != i) + continue; + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s", "Auto TX Rate", " = "); + } + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", HW_TX_RATE_CCK_STR[rate & 0x3]); + else if (txmode == TX_RATE_MODE_OFDM) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", nicHwRateOfdmStr(rate)); + else if ((txmode == TX_RATE_MODE_HTMIX) || + (txmode == TX_RATE_MODE_HTGF)) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "MCS%d, ", rate); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s%d_MCS%d, ", stbc ? "NSTS" : "NSS", + nsts, rate); + + if (prQueryStaStatistics->ucSkipAr) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability + < 4 ? HW_TX_RATE_BW[ + prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability] + : HW_TX_RATE_BW[4]); + } else { + if ((txmode == TX_RATE_MODE_CCK) || + (txmode == TX_RATE_MODE_OFDM)) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", HW_TX_RATE_BW[0]); + else + if (i > prHwWlanInfo->rWtblPeerCap + .ucChangeBWAfterRateN) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + prHwWlanInfo->rWtblPeerCap. + ucFrequencyCapability < 4 ? + (prHwWlanInfo->rWtblPeerCap. + ucFrequencyCapability > BW_20 ? + HW_TX_RATE_BW[prHwWlanInfo-> + rWtblPeerCap + .ucFrequencyCapability - 1] : + HW_TX_RATE_BW[prHwWlanInfo->rWtblPeerCap + .ucFrequencyCapability]) : + HW_TX_RATE_BW[4]); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", + prHwWlanInfo->rWtblPeerCap. + ucFrequencyCapability < 4 ? + HW_TX_RATE_BW[ + prHwWlanInfo->rWtblPeerCap + .ucFrequencyCapability] : + HW_TX_RATE_BW[4]); + } + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", rate < 4 ? "LP" : "SP"); + else if (txmode == TX_RATE_MODE_OFDM) + ; + else if ((txmode == TX_RATE_MODE_HTMIX) || + (txmode == TX_RATE_MODE_HTGF) || + (txmode == TX_RATE_MODE_VHT) || + (txmode == TX_RATE_MODE_PLR)) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", sgi == 0 ? "LGI" : "SGI"); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", sgi == 0 ? "SGI" : + (sgi == 1 ? "MGI" : "LGI")); + + if (prQueryStaStatistics->ucSkipAr) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s%s%s\n", + txmode <= ENUM_TX_MODE_NUM ? + HW_TX_MODE_STR[txmode] : "N/A", + stbc ? ", STBC, " : ", ", + nicGetTxLdpcInfo( + &prHwWlanInfo->rWtblTxConfig) == 0 ? + "BCC" : "LDPC"); + } else { +#if (CFG_SUPPORT_RA_GEN == 0) + if (prQueryStaStatistics->aucArRatePer[ + prQueryStaStatistics->aucRateEntryIndex[i]] == 0xFF) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s%s%s (--)\n", + txmode < ENUM_TX_MODE_NUM ? + HW_TX_MODE_STR[txmode] : "N/A", + stbc ? ", STBC, " : ", ", + ((nicGetTxLdpcInfo( + &prHwWlanInfo->rWtblTxConfig) == 0) + || (txmode == TX_RATE_MODE_CCK) + || (txmode == TX_RATE_MODE_OFDM)) ? + "BCC" : "LDPC"); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s%s%s (%d)\n", + txmode < ENUM_TX_MODE_NUM ? + HW_TX_MODE_STR[txmode] : "N/A", + stbc ? ", STBC, " : ", ", + ((nicGetTxLdpcInfo( + &prHwWlanInfo->rWtblTxConfig) == 0) + || (txmode == TX_RATE_MODE_CCK) + || (txmode == TX_RATE_MODE_OFDM)) + ? "BCC" : "LDPC", + prQueryStaStatistics->aucArRatePer[ + prQueryStaStatistics + ->aucRateEntryIndex[i]]); +#else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s%s%s\n", + txmode < ENUM_TX_MODE_NUM ? + HW_TX_MODE_STR[txmode] : "N/A", + stbc ? ", STBC, " : ", ", + ((nicGetTxLdpcInfo( + &prHwWlanInfo->rWtblTxConfig) == 0) || + (txmode == TX_RATE_MODE_CCK) || + (txmode == TX_RATE_MODE_OFDM)) ? + "BCC" : "LDPC"); +#endif + } + + if (!fgDumpAll) + break; + } + + return i4BytesWritten; +} + +int32_t nicGetRxRateInfo(struct ADAPTER *prAdapter, IN char *pcCommand, + IN int i4TotalLen, IN uint8_t ucWlanIdx) +{ + uint32_t txmode, rate, frmode, sgi, nsts, ldpc, stbc, groupid, mu; + int32_t i4BytesWritten = 0; + uint32_t u4RxVector0 = 0, u4RxVector1 = 0; + uint8_t ucStaIdx; + struct CHIP_DBG_OPS *prChipDbg; + + if (wlanGetStaIdxByWlanIdx(prAdapter, ucWlanIdx, &ucStaIdx) == + WLAN_STATUS_SUCCESS) { + u4RxVector0 = prAdapter->arStaRec[ucStaIdx].u4RxVector0; + u4RxVector1 = prAdapter->arStaRec[ucStaIdx].u4RxVector1; + DBGLOG(REQ, LOUD, "****** RX Vector0 = 0x%08x ******\n", + u4RxVector0); + DBGLOG(REQ, LOUD, "****** RX Vector1 = 0x%08x ******\n", + u4RxVector1); + } else { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s", "Last RX Rate", " = NOT SUPPORT"); + return i4BytesWritten; + } + + prChipDbg = prAdapter->chip_info->prDebugOps; + + if (prChipDbg && prChipDbg->show_rx_rate_info) { + i4BytesWritten = prChipDbg->show_rx_rate_info( + prAdapter, + pcCommand, + i4TotalLen, + ucStaIdx); + return i4BytesWritten; + } + + txmode = (u4RxVector0 & RX_VT_RX_MODE_MASK) >> RX_VT_RX_MODE_OFFSET; + rate = (u4RxVector0 & RX_VT_RX_RATE_MASK) >> RX_VT_RX_RATE_OFFSET; + frmode = (u4RxVector0 & RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET; + nsts = ((u4RxVector1 & RX_VT_NSTS_MASK) >> RX_VT_NSTS_OFFSET); + stbc = (u4RxVector0 & RX_VT_STBC_MASK) >> RX_VT_STBC_OFFSET; + sgi = u4RxVector0 & RX_VT_SHORT_GI; + ldpc = u4RxVector0 & RX_VT_LDPC; + groupid = (u4RxVector1 & RX_VT_GROUP_ID_MASK) >> RX_VT_GROUP_ID_OFFSET; + + if (groupid && groupid != 63) { + mu = 1; + } else { + mu = 0; + nsts += 1; + } + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%-20s%s", "Last RX Rate", " = "); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + rate < 4 ? HW_TX_RATE_CCK_STR[rate] : + HW_TX_RATE_CCK_STR[4]); + else if (txmode == TX_RATE_MODE_OFDM) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + nicHwRateOfdmStr(rate)); + else if ((txmode == TX_RATE_MODE_HTMIX) || + (txmode == TX_RATE_MODE_HTGF)) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "MCS%d, ", rate); + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "NSS%d_MCS%d, ", + nsts, rate); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + frmode < 4 ? HW_TX_RATE_BW[frmode] : HW_TX_RATE_BW[4]); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + rate < 4 ? "LP" : "SP"); + else if (txmode == TX_RATE_MODE_OFDM) + ; + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + sgi == 0 ? "LGI" : "SGI"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s", stbc == 0 ? "" : "STBC, "); + + if (mu) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, %s, %s (%d)\n", + (txmode < ENUM_TX_MODE_NUM ? + HW_TX_MODE_STR[txmode] : "N/A"), + ldpc == 0 ? "BCC" : "LDPC", "MU", groupid); + } else { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, %s\n", + (txmode < ENUM_TX_MODE_NUM ? + HW_TX_MODE_STR[txmode] : "N/A"), + ldpc == 0 ? "BCC" : "LDPC"); + } + + return i4BytesWritten; +} + + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_rx.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_rx.c new file mode 100644 index 0000000000000..6fa5dd9b03068 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_rx.c @@ -0,0 +1,4409 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_rx.c#5 + */ + +/*! \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. + */ + + +/******************************************************************************* + * C O M P I L E 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 "que_mgt.h" +#include "wnm.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 CFG_MGMT_FRAME_HANDLING +static PROCESS_RX_MGT_FUNCTION +apfnProcessRxMgtFrame[MAX_NUM_OF_FC_SUBTYPES] = { +#if CFG_SUPPORT_AAA + aaaFsmRunEventRxAssoc, /* subtype 0000: Association request */ +#else + NULL, /* subtype 0000: Association request */ +#endif /* CFG_SUPPORT_AAA */ + saaFsmRunEventRxAssoc, /* subtype 0001: Association response */ +#if CFG_SUPPORT_AAA + aaaFsmRunEventRxAssoc, /* subtype 0010: Reassociation request */ +#else + NULL, /* subtype 0010: Reassociation request */ +#endif /* CFG_SUPPORT_AAA */ + saaFsmRunEventRxAssoc, /* subtype 0011: Reassociation response */ +#if CFG_SUPPORT_ADHOC || CFG_ENABLE_WIFI_DIRECT + 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 + +static struct RX_EVENT_HANDLER arEventTable[] = { + {EVENT_ID_RX_ADDBA, qmHandleEventRxAddBa}, + {EVENT_ID_DBDC_SWITCH_DONE, cnmDbdcEventHwSwitchDone}, + {EVENT_ID_RX_DELBA, qmHandleEventRxDelBa}, + {EVENT_ID_LINK_QUALITY, nicEventLinkQuality}, + {EVENT_ID_LAYER_0_EXT_MAGIC_NUM, nicEventLayer0ExtMagic}, + {EVENT_ID_MIC_ERR_INFO, nicEventMicErrorInfo}, + {EVENT_ID_SCAN_DONE, nicEventScanDone}, + {EVENT_ID_SCHED_SCAN_DONE, nicEventSchedScanDone}, + {EVENT_ID_TX_DONE, nicTxProcessTxDoneEvent}, + {EVENT_ID_SLEEPY_INFO, nicEventSleepyNotify}, +#if CFG_ENABLE_BT_OVER_WIFI + {EVENT_ID_BT_OVER_WIFI, nicEventBtOverWifi}, +#endif + {EVENT_ID_STATISTICS, nicEventStatistics}, + {EVENT_ID_WTBL_INFO, nicEventWlanInfo}, + {EVENT_ID_MIB_INFO, nicEventMibInfo}, + {EVENT_ID_CH_PRIVILEGE, cnmChMngrHandleChEvent}, + {EVENT_ID_BSS_ABSENCE_PRESENCE, qmHandleEventBssAbsencePresence}, + {EVENT_ID_STA_CHANGE_PS_MODE, qmHandleEventStaChangePsMode}, + {EVENT_ID_STA_UPDATE_FREE_QUOTA, qmHandleEventStaUpdateFreeQuota}, + {EVENT_ID_BSS_BEACON_TIMEOUT, nicEventBeaconTimeout}, + {EVENT_ID_UPDATE_NOA_PARAMS, nicEventUpdateNoaParams}, + {EVENT_ID_STA_AGING_TIMEOUT, nicEventStaAgingTimeout}, + {EVENT_ID_AP_OBSS_STATUS, nicEventApObssStatus}, + {EVENT_ID_ROAMING_STATUS, nicEventRoamingStatus}, + {EVENT_ID_SEND_DEAUTH, nicEventSendDeauth}, + {EVENT_ID_UPDATE_RDD_STATUS, nicEventUpdateRddStatus}, + {EVENT_ID_UPDATE_BWCS_STATUS, nicEventUpdateBwcsStatus}, + {EVENT_ID_UPDATE_BCM_DEBUG, nicEventUpdateBcmDebug}, + {EVENT_ID_ADD_PKEY_DONE, nicEventAddPkeyDone}, + {EVENT_ID_ICAP_DONE, nicEventIcapDone}, + {EVENT_ID_DEBUG_MSG, nicEventDebugMsg}, + {EVENT_ID_TDLS, nicEventTdls}, +#if (CFG_SUPPORT_HE_ER == 1) + {EVENT_ID_BSS_ER_TX_MODE, bssProcessErTxModeEvent}, +#endif + {EVENT_ID_RSSI_MONITOR, nicEventRssiMonitor}, + {EVENT_ID_DUMP_MEM, nicEventDumpMem}, +#if CFG_ASSERT_DUMP + {EVENT_ID_ASSERT_DUMP, nicEventAssertDump}, +#endif +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST + {EVENT_ID_CAL_ALL_DONE, nicEventCalAllDone}, +#endif + {EVENT_ID_HIF_CTRL, nicEventHifCtrl}, + {EVENT_ID_RDD_SEND_PULSE, nicEventRddSendPulse}, +#if (CFG_SUPPORT_DFS_MASTER == 1) + {EVENT_ID_UPDATE_COEX_PHYRATE, nicEventUpdateCoexPhyrate}, + {EVENT_ID_RDD_REPORT, cnmRadarDetectEvent}, + {EVENT_ID_CSA_DONE, cnmCsaDoneEvent}, +#if CFG_SUPPORT_IDC_CH_SWITCH + {EVENT_ID_LTE_IDC_REPORT, cnmIdcDetectHandler}, +#endif +#else + {EVENT_ID_UPDATE_COEX_PHYRATE, nicEventUpdateCoexPhyrate}, +#endif + {EVENT_ID_TX_ADDBA, qmHandleEventTxAddBa}, + {EVENT_ID_GET_CNM, nicEventCnmInfo}, +#if CFG_SUPPORT_SMART_GEAR + {EVENT_ID_SG_STATUS, cnmEventSGStatus}, +#endif + {EVENT_ID_OPMODE_CHANGE, cnmOpmodeEventHandler}, +#if CFG_SUPPORT_LOWLATENCY_MODE + {EVENT_ID_LOW_LATENCY_INFO, nicEventUpdateLowLatencyInfoStatus}, +#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 struct ADAPTER *prAdapter) +{ + struct RX_CTRL *prRxCtrl; + uint8_t *pucMemHandle; + struct SW_RFB *prSwRfb = (struct SW_RFB *) NULL; + uint32_t i; + + DEBUGFUNC("nicRxInitialize"); + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + + /* 4 <0> Clear allocated memory. */ + kalMemZero((void *) 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 = (struct SW_RFB *) pucMemHandle; + + if (nicRxSetupRFB(prAdapter, prSwRfb)) { + DBGLOG(RX, ERROR, + "nicRxInitialize failed: Cannot allocate packet buffer for SwRfb!\n"); + return; + } + nicRxReturnRFB(prAdapter, prSwRfb); + + pucMemHandle += ALIGN_4(sizeof(struct SW_RFB)); + } + + if (prRxCtrl->rFreeSwRfbList.u4NumElem != + CFG_RX_MAX_PKT_NUM) + ASSERT_NOMEM(); + /* Check if the memory allocation consist with this + * initialization function + */ + ASSERT((uint32_t) (pucMemHandle - prRxCtrl->pucRxCached) == + prRxCtrl->u4RxCachedSize); + + /* 4 <2> Clear all RX counters */ + RX_RESET_ALL_CNTS(prRxCtrl); + + prRxCtrl->pucRxCoalescingBufPtr = + prAdapter->pucCoalescingBufCached; + +#if CFG_HIF_STATISTICS + prRxCtrl->u4TotalRxAccessNum = 0; + prRxCtrl->u4TotalRxPacketNum = 0; +#endif + +#if CFG_HIF_RX_STARVATION_WARNING + prRxCtrl->u4QueuedCnt = 0; + prRxCtrl->u4DequeuedCnt = 0; +#endif + +} /* end of nicRxInitialize() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Uninitialize the RFBs + * + * @param prAdapter Pointer to the Adapter structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicRxUninitialize(IN struct ADAPTER *prAdapter) +{ + struct RX_CTRL *prRxCtrl; + struct SW_RFB *prSwRfb = (struct SW_RFB *) 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, + struct SW_RFB *); + 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_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, + struct SW_RFB *); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + if (prSwRfb) { + if (prSwRfb->pvPacket) + kalPacketFree(prAdapter->prGlueInfo, + prSwRfb->pvPacket); + prSwRfb->pvPacket = NULL; + } else { + break; + } + } while (TRUE); + +} /* end of nicRxUninitialize() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Fill RFB + * + * @param prAdapter pointer to the Adapter handler + * @param prSWRfb specify the RFB to receive rx data + * + * @return (none) + * + */ +/*----------------------------------------------------------------------------*/ +void nicRxFillRFB(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb) +{ + struct RX_DESC_OPS_T *prRxDescOps = prAdapter->chip_info->prRxDescOps; + + if (prRxDescOps->nic_rxd_fill_rfb) + prRxDescOps->nic_rxd_fill_rfb(prAdapter, prSwRfb); + else + DBGLOG(RX, ERROR, + "%s:: no nic_rxd_fill_rfb??\n", + __func__); +} + +#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 struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb) +{ + struct RX_CSO_REPORT_T *rReport; + uint32_t u4TcpUdpIpCksStatus; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + u4TcpUdpIpCksStatus = prSwRfb->u4TcpUdpIpCksStatus; + rReport = (struct RX_CSO_REPORT_T *) &u4TcpUdpIpCksStatus; + DBGLOG_LIMITED(RX, LOUD, + "RX_IPV4_STATUS=%d, RX_TCP_STATUS=%d, RX_UDP_STATUS=%d\n", + rReport->u4IpV4CksStatus, rReport->u4TcpCksStatus, + rReport->u4UdpCksStatus); + DBGLOG_LIMITED(RX, LOUD, + "RX_IPV4_TYPE=%d, RX_IPV6_TYPE=%d, RX_TCP_TYPE=%d, RX_UDP_TYPE=%d\n", + rReport->u4IpV4CksType, rReport->u4IpV6CksType, + rReport->u4TcpCksType, rReport->u4UdpCksType); + + 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 rxDefragMPDU() is used to defragment the incoming packets. + * + * \param[in] prSWRfb The RFB which is being processed. + * \param[in] UINT_16 u2FrameCtrl + * + * \retval NOT NULL Receive the last fragment data + * \retval NULL Receive the fragment packet which is not the last + */ +/*----------------------------------------------------------------------------*/ +struct SW_RFB *nicRxDefragMPDU(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSWRfb, OUT struct QUE *prReturnedQue) +{ + + struct SW_RFB *prOutputSwRfb = (struct SW_RFB *) NULL; +#if 1 + struct RX_CTRL *prRxCtrl; + struct FRAG_INFO *prFragInfo; + uint32_t i = 0, j; + uint16_t u2SeqCtrl, u2FrameCtrl; + uint8_t ucFragNum; + u_int8_t fgFirst = FALSE; + u_int8_t fgLast = FALSE; + OS_SYSTIME rCurrentTime; + struct WLAN_MAC_HEADER *prWlanHeader = NULL; + void *prRxStatus = NULL; + struct HW_MAC_RX_STS_GROUP_4 *prRxStatusGroup4 = NULL; + + DEBUGFUNC("nicRx: rxmDefragMPDU\n"); + + ASSERT(prSWRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + + prRxStatus = prSWRfb->prRxStatus; + ASSERT(prRxStatus); + + if (prSWRfb->fgHdrTran == FALSE) { + prWlanHeader = (struct WLAN_MAC_HEADER *) prSWRfb->pvHeader; + u2FrameCtrl = prWlanHeader->u2FrameCtrl; + } else { + prRxStatusGroup4 = prSWRfb->prRxStatusGroup4; + prSWRfb->u2SequenceControl = HAL_RX_STATUS_GET_SEQFrag_NUM( + prRxStatusGroup4); + u2FrameCtrl = HAL_RX_STATUS_GET_FRAME_CTL_FIELD( + prRxStatusGroup4); + } + u2SeqCtrl = prSWRfb->u2SequenceControl; + ucFragNum = (uint8_t) (u2SeqCtrl & MASK_SC_FRAG_NUM); + prSWRfb->u2FrameCtrl = u2FrameCtrl; + + if (!(u2FrameCtrl & MASK_FC_MORE_FRAG)) { + /* The last fragment frame */ + if (ucFragNum) { + DBGLOG(RX, LOUD, + "FC %04x M %04x SQ %04x\n", u2FrameCtrl, + (uint16_t) (u2FrameCtrl & MASK_FC_MORE_FRAG), + u2SeqCtrl); + fgLast = TRUE; + } + /* Non-fragment frame */ + else + return prSWRfb; + } + /* The fragment frame except the last one */ + else { + if (ucFragNum == 0) { + DBGLOG(RX, LOUD, + "FC %04x M %04x SQ %04x\n", u2FrameCtrl, + (uint16_t) (u2FrameCtrl & MASK_FC_MORE_FRAG), + u2SeqCtrl); + fgFirst = TRUE; + } else { + DBGLOG(RX, LOUD, + "FC %04x M %04x SQ %04x\n", u2FrameCtrl, + (uint16_t) (u2FrameCtrl & MASK_FC_MORE_FRAG), + u2SeqCtrl); + } + } + + GET_CURRENT_SYSTIME(&rCurrentTime); + + for (j = 0; j < MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS; j++) { + prFragInfo = &prSWRfb->prStaRec->rFragInfo[j]; + if (prFragInfo->pr1stFrag) { + /* I. If the receive timer for the MSDU or MMPDU that + * is stored in the fragments queue exceeds + * dot11MaxReceiveLifetime, we discard the uncompleted + * fragments. + * II. If we didn't receive the last MPDU for a period, + * we use this function for remove frames. + */ + if (CHECK_FOR_EXPIRATION(rCurrentTime, + prFragInfo->rReceiveLifetimeLimit)) { + prFragInfo->pr1stFrag->eDst = + RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) + prFragInfo->pr1stFrag); + + prFragInfo->pr1stFrag = (struct SW_RFB *) NULL; + } + } + } + + for (i = 0; i < MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS; i++) { + + prFragInfo = &prSWRfb->prStaRec->rFragInfo[i]; + + if (fgFirst) { /* looking for timed-out frag buffer */ + + if (prFragInfo->pr1stFrag == (struct SW_RFB *) + NULL) /* find a free frag buffer */ + break; + } else { + /* looking for a buffer with desired next seqctrl */ + + if (prFragInfo->pr1stFrag == (struct SW_RFB *) NULL) + continue; + + if (RXM_IS_QOS_DATA_FRAME(u2FrameCtrl)) { + if (RXM_IS_QOS_DATA_FRAME( + prFragInfo->pr1stFrag->u2FrameCtrl)) { + if (u2SeqCtrl == + prFragInfo->u2NextFragSeqCtrl) + break; + } + } else { + if (!RXM_IS_QOS_DATA_FRAME( + prFragInfo->pr1stFrag->u2FrameCtrl)) { + if (u2SeqCtrl == + prFragInfo->u2NextFragSeqCtrl) + break; + } + } + } + } + + if (i >= MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS) { + + /* Can't find a proper struct FRAG_INFO. + * I. 1st Fragment MPDU, all of the FragInfo are exhausted + * II. 2nd ~ (n-1)th Fragment MPDU, can't find the right + * FragInfo for defragment. + * Because we won't process fragment frame outside this + * function, so we should free it right away. + */ + nicRxReturnRFB(prAdapter, prSWRfb); + + return (struct SW_RFB *) NULL; + } + + ASSERT(prFragInfo); + + /* retrieve Rx payload */ + prSWRfb->pucPayload = (uint8_t *) (( + (unsigned long) prSWRfb->pvHeader) + + prSWRfb->u2HeaderLen); + prSWRfb->u2PayloadLength = + (uint16_t) (prSWRfb->u2RxByteCount - (( + unsigned long) prSWRfb->pucPayload - + (unsigned long) prRxStatus)); + + if (fgFirst) { + DBGLOG(RX, LOUD, "rxDefragMPDU first\n"); + + SET_EXPIRATION_TIME(prFragInfo->rReceiveLifetimeLimit, + TU_TO_SYSTIME( + DOT11_RECEIVE_LIFETIME_TU_DEFAULT)); + + prFragInfo->pr1stFrag = prSWRfb; + + prFragInfo->pucNextFragStart = + (uint8_t *) prSWRfb->pucRecvBuff + + prSWRfb->u2RxByteCount; + + prFragInfo->u2NextFragSeqCtrl = u2SeqCtrl + 1; + DBGLOG(RX, LOUD, + "First: nextFragmentSeqCtrl = %04x, u2SeqCtrl = %04x\n", + prFragInfo->u2NextFragSeqCtrl, u2SeqCtrl); + + /* prSWRfb->fgFragmented = TRUE; */ + /* whsu: todo for checksum */ + } else { + prFragInfo->pr1stFrag->u2RxByteCount += + prSWRfb->u2PayloadLength; + + if (prFragInfo->pr1stFrag->u2RxByteCount > + CFG_RX_MAX_PKT_SIZE) { + + prFragInfo->pr1stFrag->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) + prFragInfo->pr1stFrag); + + prFragInfo->pr1stFrag = (struct SW_RFB *) NULL; + + nicRxReturnRFB(prAdapter, prSWRfb); + } else { + kalMemCopy(prFragInfo->pucNextFragStart, + prSWRfb->pucPayload, + prSWRfb->u2PayloadLength); + /* [6630] update rx byte count and packet length */ + prFragInfo->pr1stFrag->u2PacketLen += + prSWRfb->u2PayloadLength; + prFragInfo->pr1stFrag->u2PayloadLength += + prSWRfb->u2PayloadLength; + + if (fgLast) { /* The last one, free the buffer */ + DBGLOG(RX, LOUD, "Defrag: finished\n"); + + prOutputSwRfb = prFragInfo->pr1stFrag; + + prFragInfo->pr1stFrag = (struct SW_RFB *) NULL; + } else { + DBGLOG(RX, LOUD, "Defrag: mid fraged\n"); + + prFragInfo->pucNextFragStart += + prSWRfb->u2PayloadLength; + + prFragInfo->u2NextFragSeqCtrl++; + } + + nicRxReturnRFB(prAdapter, prSWRfb); + } + } + + /* DBGLOG_MEM8(RXM, INFO, */ + /* prFragInfo->pr1stFrag->pucPayload, */ + /* prFragInfo->pr1stFrag->u2PayloadLength); */ +#endif + return prOutputSwRfb; +} /* end of rxmDefragMPDU() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Do duplicate detection + * + * @param prSwRfb Pointer to the RX packet + * + * @return TRUE: a duplicate, FALSE: not a duplicate + */ +/*----------------------------------------------------------------------------*/ +u_int8_t nicRxIsDuplicateFrame(IN OUT struct SW_RFB + *prSwRfb) +{ + + /* Non-QoS Unicast Data or Unicast MMPDU: SC Cache #4; + * QoS Unicast Data: SC Cache #0~3; + * Broadcast/Multicast: RetryBit == 0 + */ + uint32_t u4SeqCtrlCacheIdx; + uint16_t u2SequenceControl, u2FrameCtrl; + u_int8_t fgIsDuplicate = FALSE, fgIsAmsduSubframe = FALSE; + struct WLAN_MAC_HEADER *prWlanHeader = NULL; + void *prRxStatus = NULL; + struct HW_MAC_RX_STS_GROUP_4 *prRxStatusGroup4 = NULL; + + DEBUGFUNC("nicRx: Enter rxmIsDuplicateFrame()\n"); + + ASSERT(prSwRfb); + + /* Situations in which the STC_REC is missing include: + * (1) Probe Request (2) (Re)Association Request + * (3) IBSS data frames (4) Probe Response + */ + if (!prSwRfb->prStaRec) + return FALSE; + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + fgIsAmsduSubframe = prSwRfb->ucPayloadFormat; + if (prSwRfb->fgHdrTran == FALSE) { + prWlanHeader = (struct WLAN_MAC_HEADER *) prSwRfb->pvHeader; + u2SequenceControl = prSwRfb->u2SequenceControl; + u2FrameCtrl = prWlanHeader->u2FrameCtrl; + } else { + prRxStatusGroup4 = prSwRfb->prRxStatusGroup4; + u2SequenceControl = HAL_RX_STATUS_GET_SEQFrag_NUM( + prRxStatusGroup4); + u2FrameCtrl = HAL_RX_STATUS_GET_FRAME_CTL_FIELD( + prRxStatusGroup4); + } + prSwRfb->u2SequenceControl = u2SequenceControl; + + /* Case 1: Unicast QoS data */ + if (RXM_IS_QOS_DATA_FRAME( + u2FrameCtrl)) { + /* WLAN header shall exist when doing duplicate detection */ + if (prSwRfb->ucTid < CFG_RX_MAX_BA_TID_NUM && + prSwRfb->prStaRec-> + aprRxReorderParamRefTbl[prSwRfb->ucTid]) { + + /* QoS data with an RX BA agreement + * Case 1: The packet is not an AMPDU subframe, + * so the RetryBit may be set to 1 (TBC). + * Case 2: The RX BA agreement was just established. + * Some enqueued packets may not be sent with + * aggregation. + */ + + DBGLOG(RX, LOUD, "RX: SC=0x%X (BA Entry present)\n", + u2SequenceControl); + + /* Update the SN cache in order to ensure the + * correctness of duplicate removal in case the + * BA agreement is deleted + */ + prSwRfb->prStaRec->au2CachedSeqCtrl[prSwRfb->ucTid] = + u2SequenceControl; + + /* debug */ +#if 0 + DBGLOG(RXM, LOUD, + "RXM: SC= 0x%X (Cache[%d] updated) with BA\n", + u2SequenceControl, prSwRfb->ucTID); + + if (g_prMqm->arRxBaTable[ + prSwRfb->prStaRec->aucRxBaTable[prSwRfb->ucTID]] + .ucStatus == BA_ENTRY_STATUS_DELETING) { + DBGLOG(RXM, LOUD, + "RXM: SC= 0x%X (Cache[%d] updated) with DELETING BA\n", + u2SequenceControl, prSwRfb->ucTID); + } +#endif + + /* HW scoreboard shall take care Case 1. + * Let the layer layer handle Case 2. + */ + return FALSE; /* Not a duplicate */ + } + + if (prSwRfb->prStaRec->ucDesiredPhyTypeSet & + (PHY_TYPE_BIT_HT | PHY_TYPE_BIT_VHT)) { + u4SeqCtrlCacheIdx = prSwRfb->ucTid; +#if (CFG_SUPPORT_802_11AX == 1) + } else if (prSwRfb->prStaRec->ucDesiredPhyTypeSet & + PHY_TYPE_BIT_HE) { + u4SeqCtrlCacheIdx = prSwRfb->ucTid; +#endif + } else { + if (prSwRfb->ucTid < 8) { /* UP = 0~7 */ + u4SeqCtrlCacheIdx = aucTid2ACI[prSwRfb->ucTid]; + } else { + DBGLOG(RX, WARN, + "RXM: (Warning) Unknown QoS Data with TID=%d\n", + prSwRfb->ucTid); + /* Ignore duplicate frame check */ + return FALSE; + } + } + } + /* Case 2: Unicast non-QoS data or MMPDUs */ + else + u4SeqCtrlCacheIdx = TID_NUM; + + /* If this is a retransmission */ + if (u2FrameCtrl & MASK_FC_RETRY) { + if (u2SequenceControl != + prSwRfb->prStaRec->au2CachedSeqCtrl[u4SeqCtrlCacheIdx]) { + prSwRfb->prStaRec->au2CachedSeqCtrl[u4SeqCtrlCacheIdx] = + u2SequenceControl; + if (fgIsAmsduSubframe == + RX_PAYLOAD_FORMAT_FIRST_SUB_AMSDU) + prSwRfb->prStaRec-> + afgIsIgnoreAmsduDuplicate[ + u4SeqCtrlCacheIdx] = TRUE; + DBGLOG(RX, LOUD, "RXM: SC= 0x%x (Cache[%u] updated)\n", + u2SequenceControl, u4SeqCtrlCacheIdx); + } else { + /* A duplicate. */ + if (prSwRfb->prStaRec-> + afgIsIgnoreAmsduDuplicate[u4SeqCtrlCacheIdx]) { + if (fgIsAmsduSubframe == + RX_PAYLOAD_FORMAT_LAST_SUB_AMSDU) + prSwRfb->prStaRec-> + afgIsIgnoreAmsduDuplicate[ + u4SeqCtrlCacheIdx] = FALSE; + } else { + fgIsDuplicate = TRUE; + DBGLOG(RX, LOUD, + "RXM: SC= 0x%x (Cache[%u] duplicate)\n", + u2SequenceControl, u4SeqCtrlCacheIdx); + } + } + } + + /* Not a retransmission */ + else { + + prSwRfb->prStaRec->au2CachedSeqCtrl[u4SeqCtrlCacheIdx] = + u2SequenceControl; + prSwRfb->prStaRec->afgIsIgnoreAmsduDuplicate[u4SeqCtrlCacheIdx] + = FALSE; + + DBGLOG(RX, LOUD, "RXM: SC= 0x%x (Cache[%u] updated)\n", + u2SequenceControl, u4SeqCtrlCacheIdx); + } + + return fgIsDuplicate; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfb) +{ + struct RX_CTRL *prRxCtrl; + struct TX_CTRL *prTxCtrl; + u_int8_t fgIsRetained = FALSE; + uint32_t u4CurrentRxBufferCount; + /* P_STA_RECORD_T prStaRec = (P_STA_RECORD_T)NULL; */ + + DEBUGFUNC("nicRxProcessPktWithoutReorder"); + /* DBGLOG(RX, TRACE, ("\n")); */ + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + u4CurrentRxBufferCount = prRxCtrl->rFreeSwRfbList.u4NumElem; + /* QM USED = $A, AVAILABLE COUNT = $B, INDICATED TO OS = $C + * TOTAL = $A + $B + $C + * + * Case #1 (Retain) + * ------------------------------------------------------- + * $A + $B < THRESHOLD := $A + $B + $C < THRESHOLD + $C + * := $TOTAL - THRESHOLD < $C + * => $C used too much, retain + * + * Case #2 (Non-Retain) + * ------------------------------------------------------- + * $A + $B > THRESHOLD := $A + $B + $C > THRESHOLD + $C + * := $TOTAL - THRESHOLD > $C + * => still available for $C to use + * + */ + +#if defined(LINUX) + fgIsRetained = FALSE; +#else + fgIsRetained = (((u4CurrentRxBufferCount + + qmGetRxReorderQueuedBufferCount(prAdapter) + + prTxCtrl->i4PendingFwdFrameCount) < + CFG_RX_RETAINED_PKT_THRESHOLD) ? TRUE : FALSE); +#endif + + /* DBGLOG(RX, INFO, ("fgIsRetained = %d\n", fgIsRetained)); */ +#if CFG_ENABLE_PER_STA_STATISTICS + if (prSwRfb->prStaRec + && (prAdapter->rWifiVar.rWfdConfigureSettings.ucWfdEnable > + 0)) + prSwRfb->prStaRec->u4TotalRxPktsNumber++; +#endif + if (kalProcessRxPacket(prAdapter->prGlueInfo, + prSwRfb->pvPacket, + prSwRfb->pvHeader, + (uint32_t) prSwRfb->u2PacketLen, fgIsRetained, + prSwRfb->aeCSUM) != WLAN_STATUS_SUCCESS) { + DBGLOG(RX, ERROR, + "kalProcessRxPacket return value != WLAN_STATUS_SUCCESS\n"); + + nicRxReturnRFB(prAdapter, prSwRfb); + return; + } + +#if CFG_SUPPORT_MULTITHREAD + if (HAL_IS_RX_DIRECT(prAdapter)) { + kalRxIndicateOnePkt(prAdapter->prGlueInfo, + (void *) GLUE_GET_PKT_DESCRIPTOR( + GLUE_GET_PKT_QUEUE_ENTRY(prSwRfb->pvPacket))); + RX_ADD_CNT(prRxCtrl, RX_DATA_INDICATION_COUNT, 1); + if (fgIsRetained) + RX_ADD_CNT(prRxCtrl, RX_DATA_RETAINED_COUNT, 1); + } else { + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); + QUEUE_INSERT_TAIL(&(prAdapter->rRxQueue), + (struct QUE_ENTRY *) GLUE_GET_PKT_QUEUE_ENTRY( + prSwRfb->pvPacket)); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); + + prRxCtrl->ucNumIndPacket++; + kalSetTxEvent2Rx(prAdapter->prGlueInfo); + } +#else + prRxCtrl->apvIndPacket[prRxCtrl->ucNumIndPacket] = + prSwRfb->pvPacket; + prRxCtrl->ucNumIndPacket++; +#endif + +#ifndef LINUX + if (fgIsRetained) { + prRxCtrl->apvRetainedPacket[prRxCtrl->ucNumRetainedPacket] = + prSwRfb->pvPacket; + prRxCtrl->ucNumRetainedPacket++; + } else +#endif + prSwRfb->pvPacket = NULL; + + + /* Return RFB */ + if (nicRxSetupRFB(prAdapter, prSwRfb)) { + DBGLOG(RX, WARN, + "Cannot allocate packet buffer for SwRfb!\n"); + if (!timerPendingTimer( + &prAdapter->rPacketDelaySetupTimer)) { + DBGLOG(RX, WARN, + "Start ReturnIndicatedRfb Timer (%u)\n", + RX_RETURN_INDICATED_RFB_TIMEOUT_SEC); + cnmTimerStartTimer(prAdapter, + &prAdapter->rPacketDelaySetupTimer, + SEC_TO_MSEC( + RX_RETURN_INDICATED_RFB_TIMEOUT_SEC)); + } + } + nicRxReturnRFB(prAdapter, prSwRfb); +} + +u_int8_t nicRxCheckForwardPktResource( + IN struct ADAPTER *prAdapter, uint32_t ucTid) +{ + struct TX_CTRL *prTxCtrl; + uint8_t i, uTxQidx; + + prTxCtrl = &prAdapter->rTxCtrl; + uTxQidx = aucACI2TxQIdx[aucTid2ACI[ucTid]]; + + /* If the resource used more than half, we could control WMM resource + * by limit every AC queue. + */ + for (i = uTxQidx+1; i < WMM_AC_INDEX_NUM; i++) { + if (GLUE_GET_REF_CNT(prTxCtrl + ->i4PendingFwdFrameWMMCount[uTxQidx]) >= + GLUE_GET_REF_CNT(prTxCtrl + ->i4PendingFwdFrameWMMCount[i]) && + GLUE_GET_REF_CNT(prTxCtrl + ->i4PendingFwdFrameWMMCount[i]) > 0 && + GLUE_GET_REF_CNT(prTxCtrl + ->i4PendingFwdFrameCount) > prAdapter + ->rQM.u4MaxForwardBufferCount) + return FALSE; + } + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct MSDU_INFO *prMsduInfo, *prRetMsduInfoList; + struct TX_CTRL *prTxCtrl; + struct RX_CTRL *prRxCtrl; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxProcessForwardPkt"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prTxCtrl = &prAdapter->rTxCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + + if (prSwRfb->ucTid >= TX_DESC_TID_NUM) { + DBGLOG_LIMITED(RX, WARN, + "Wrong forward packet: tid:%d\n", prSwRfb->ucTid); + prSwRfb->ucTid = 0; + } + + if (!nicRxCheckForwardPktResource(prAdapter, prSwRfb->ucTid)) { + nicRxReturnRFB(prAdapter, prSwRfb); + return; + } + + DBGLOG_LIMITED(RX, TRACE, "to forward packet: %d,%d,%d,%d,%d\n", + GLUE_GET_REF_CNT(prTxCtrl->i4PendingFwdFrameWMMCount[0]), + GLUE_GET_REF_CNT(prTxCtrl->i4PendingFwdFrameWMMCount[1]), + GLUE_GET_REF_CNT(prTxCtrl->i4PendingFwdFrameWMMCount[2]), + GLUE_GET_REF_CNT(prTxCtrl->i4PendingFwdFrameWMMCount[3]), + GLUE_GET_REF_CNT(prTxCtrl->i4PendingFwdFrameCount)); + + prMsduInfo = cnmPktAlloc(prAdapter, 0); + + if (prMsduInfo && + kalProcessRxPacket(prAdapter->prGlueInfo, + prSwRfb->pvPacket, + prSwRfb->pvHeader, + (uint32_t) prSwRfb->u2PacketLen, + prRxCtrl->rFreeSwRfbList.u4NumElem < + CFG_RX_RETAINED_PKT_THRESHOLD ? TRUE : FALSE, + prSwRfb->aeCSUM) == WLAN_STATUS_SUCCESS) { + + /* parsing forward frame */ + wlanProcessTxFrame(prAdapter, (void *) (prSwRfb->pvPacket)); + /* pack into MSDU_INFO_T */ + nicTxFillMsduInfo(prAdapter, prMsduInfo, + (void *) (prSwRfb->pvPacket)); + + prMsduInfo->eSrc = TX_PACKET_FORWARDING; + prMsduInfo->ucBssIndex = secGetBssIdxByWlanIdx(prAdapter, + prSwRfb->ucWlanIdx); + prMsduInfo->ucUserPriority = prSwRfb->ucTid; + + /* release RX buffer (to rIndicatedRfbList) */ + prSwRfb->pvPacket = NULL; + nicRxReturnRFB(prAdapter, prSwRfb); + + /* Handle if prMsduInfo out of bss index range*/ + if (prMsduInfo->ucBssIndex > MAX_BSSID_NUM) { + DBGLOG(QM, INFO, + "Invalid bssidx:%u\n", prMsduInfo->ucBssIndex); + if (prMsduInfo->pfTxDoneHandler != NULL) + prMsduInfo->pfTxDoneHandler(prAdapter, + prMsduInfo, + TX_RESULT_DROPPED_IN_DRIVER); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + return; + } + + /* increase forward frame counter */ + GLUE_INC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount); + + /* add resource control for WMM forward packet */ + GLUE_INC_REF_CNT(prTxCtrl + ->i4PendingFwdFrameWMMCount[ + aucACI2TxQIdx[aucTid2ACI[prSwRfb->ucTid]]]); + + /* 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 */ + DBGLOG(QM, INFO, "No Tx MSDU_INFO for forwarding frames\n"); + nicRxReturnRFB(prAdapter, prSwRfb); + if (prMsduInfo) + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfb) +{ + struct SW_RFB *prSwRfbDuplicated; + struct TX_CTRL *prTxCtrl; + struct RX_CTRL *prRxCtrl; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxProcessGOBroadcastPkt"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prTxCtrl = &prAdapter->rTxCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + + 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_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, + prSwRfbDuplicated, struct SW_RFB *); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + if (prSwRfbDuplicated) { + kalMemCopy(prSwRfbDuplicated->pucRecvBuff, + prSwRfb->pucRecvBuff, + ALIGN_4(prSwRfb->u2RxByteCount + + HIF_RX_HW_APPENDED_LEN)); + + prSwRfbDuplicated->ucPacketType = RX_PKT_TYPE_RX_DATA; + prSwRfbDuplicated->ucStaRecIdx = prSwRfb->ucStaRecIdx; + nicRxFillRFB(prAdapter, prSwRfbDuplicated); + GLUE_COPY_PRIV_DATA( + prSwRfbDuplicated->pvPacket, + prSwRfb->pvPacket); + + /* 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); + +} + +#if CFG_SUPPORT_SNIFFER +void nicRxFillRadiotapMCS(IN OUT struct MONITOR_RADIOTAP + *prMonitorRadiotap, + IN struct HW_MAC_RX_STS_GROUP_3 *prRxStatusGroup3) +{ + uint8_t ucFrMode; + uint8_t ucShortGI; + uint8_t ucRxMode; + uint8_t ucLDPC; + uint8_t ucSTBC; + uint8_t ucNess; + + ucFrMode = (((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET); + /* VHTA1 B0-B1 */ + ucShortGI = ((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_SHORT_GI) ? 1 : 0; /* HT_shortgi */ + ucRxMode = (((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_RX_MODE_MASK) >> RX_VT_RX_MODE_OFFSET); + ucLDPC = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_LDPC) ? + 1 : 0; /* HT_adcode */ + ucSTBC = (((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_STBC_MASK) >> RX_VT_STBC_OFFSET); /* HT_stbc */ + ucNess = (((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_NESS_MASK) >> RX_VT_NESS_OFFSET); /* HT_extltf */ + + prMonitorRadiotap->ucMcsKnown = + (BITS(0, 6) | (((ucNess & BIT(1)) >> 1) << 7)); + + prMonitorRadiotap->ucMcsFlags = ((ucFrMode) | + (ucShortGI << 2) | + ((ucRxMode & BIT(0)) << 3) | + (ucLDPC << 4) | (ucSTBC << 5) | + ((ucNess & BIT(0)) << 7)); + /* Bit[6:0] for 802.11n, mcs0 ~ mcs7 */ + prMonitorRadiotap->ucMcsMcs = (( + prRxStatusGroup3)->u4RxVector[0] & RX_VT_RX_RATE_MASK); +} + +void nicRxFillRadiotapVHT(IN OUT struct MONITOR_RADIOTAP + *prMonitorRadiotap, + IN struct HW_MAC_RX_STS_GROUP_3 *prRxStatusGroup3) +{ + uint8_t ucSTBC; + uint8_t ucTxopPsNotAllow; + uint8_t ucShortGI; + uint8_t ucNsym; + uint8_t ucLdpcExtraOfdmSym; + uint8_t ucBeamFormed; + uint8_t ucFrMode; + uint8_t ucNsts; + uint8_t ucMcs; + + prMonitorRadiotap->u2VhtKnown = RADIOTAP_VHT_ALL_KNOWN; + prMonitorRadiotap->u2VhtKnown &= + ~RADIOTAP_VHT_SHORT_GI_NSYM_KNOWN; + + ucSTBC = (((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_STBC_MASK) >> + RX_VT_STBC_OFFSET); /* BIT[7]: VHTA1 B3 */ + ucTxopPsNotAllow = ((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_TXOP_PS_NOT_ALLOWED) ? 1 : 0; /* VHTA1 B22 */ + /* + * ucNsym = ((prRxStatusGroup3)->u4RxVector[0] + * & RX_VT_SHORT_GI_NSYM) ? 1 : 0; //VHTA2 B1 + */ + ucNsym = 0; /* Invalid in MT6632*/ + ucShortGI = ((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_SHORT_GI) ? 1 : 0; /* VHTA2 B0 */ + ucLdpcExtraOfdmSym = ((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_LDPC_EXTRA_OFDM_SYM) ? 1 : 0; /* VHTA2 B3 */ + ucBeamFormed = ((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_BEAMFORMED) ? 1 : 0; /* VHTA2 B8 */ + prMonitorRadiotap->ucVhtFlags = ((ucSTBC) | + (ucTxopPsNotAllow << 1) | + (ucShortGI << 2) | (ucNsym << 3) + | (ucLdpcExtraOfdmSym << 4) + | (ucBeamFormed << 5)); + + ucFrMode = (((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET); + /* VHTA1 B0-B1 */ + switch (ucFrMode) { + case RX_VT_FR_MODE_20: + prMonitorRadiotap->ucVhtBandwidth = 0; + break; + case RX_VT_FR_MODE_40: + prMonitorRadiotap->ucVhtBandwidth = 1; + break; + case RX_VT_FR_MODE_80: + prMonitorRadiotap->ucVhtBandwidth = 4; + break; + case RX_VT_FR_MODE_160: + prMonitorRadiotap->ucVhtBandwidth = 11; + break; + default: + prMonitorRadiotap->ucVhtBandwidth = 0; + } + + /* Set to 0~7 for 1~8 space time streams */ + ucNsts = (((prRxStatusGroup3)->u4RxVector[1] & + RX_VT_NSTS_MASK) >> RX_VT_NSTS_OFFSET) + 1; + /* VHTA1 B10-B12 */ + + /* Bit[3:0] for 802.11ac, mcs0 ~ mcs9 */ + ucMcs = ((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_RX_RATE_AC_MASK); + + prMonitorRadiotap->aucVhtMcsNss[0] = ((ucMcs << 4) | + (ucNsts - ucSTBC)); /* STBC = Nsts - Nss */ + + /* + * prMonitorRadiotap->ucVhtCoding = + * (((prRxStatusGroup3)->u4RxVector[0] + * & RX_VT_CODING_MASK) >> RX_VT_CODING_OFFSET); + */ + prMonitorRadiotap->ucVhtCoding = 0; /* Invalid in MT6632*/ + + /* VHTA2 B2-B3 */ + + prMonitorRadiotap->ucVhtGroupId = + (((((prRxStatusGroup3)->u4RxVector[1] & + RX_VT_GROUPID_1_MASK) >> RX_VT_GROUPID_1_OFFSET) << 2) | + (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_GROUPID_0_MASK) + >> RX_VT_GROUPID_0_OFFSET)); + /* VHTA1 B4-B9 */ + /* VHTA1 B13-B21 */ + prMonitorRadiotap->u2VhtPartialAid = (((( + prRxStatusGroup3)->u4RxVector[2] + & RX_VT_AID_1_MASK) << 4) | + (((prRxStatusGroup3)->u4RxVector[1] + & RX_VT_AID_0_MASK) >> + RX_VT_AID_0_OFFSET)); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Process HIF monitor packet + * + * @param prAdapter pointer to the Adapter handler + * @param prSWRfb the RFB to receive rx data + * + * @return (none) + * + */ +/*----------------------------------------------------------------------------*/ +void nicRxProcessMonitorPacket(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb) +{ + struct sk_buff *prSkb = NULL; + struct RX_CTRL *prRxCtrl; + void *prRxStatus; + struct HW_MAC_RX_STS_GROUP_2 *prRxStatusGroup2; + struct HW_MAC_RX_STS_GROUP_3 *prRxStatusGroup3; + struct MONITOR_RADIOTAP rMonitorRadiotap; + struct RADIOTAP_FIELD_VENDOR_ rRadiotapFieldVendor; + uint8_t *prVendorNsOffset; + uint32_t u4VendorNsLen; + uint32_t u4RadiotapLen; + uint32_t u4ItPresent; + uint8_t aucMtkOui[] = VENDOR_OUI_MTK; + uint8_t ucRxRate; + uint8_t ucRxMode; + uint8_t ucChanNum = 0; + uint8_t ucMcs; + uint8_t ucFrMode; + uint8_t ucShortGI; + uint32_t u4PhyRate; + struct RX_DESC_OPS_T *prRxDescOps; + enum ENUM_BAND eBand = 0; + +#if CFG_SUPPORT_MULTITHREAD + KAL_SPIN_LOCK_DECLARATION(); +#endif + + DEBUGFUNC("nicRxProcessMonitorPacket"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + prRxDescOps = prAdapter->chip_info->prRxDescOps; + + prRxCtrl = &prAdapter->rRxCtrl; + + nicRxFillRFB(prAdapter, prSwRfb); + + /* can't parse radiotap info if no rx vector */ + if (((prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_2)) == 0) + || ((prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_3)) == 0)) { + nicRxReturnRFB(prAdapter, prSwRfb); + return; + } + + prRxStatus = prSwRfb->prRxStatus; + prRxStatusGroup2 = prSwRfb->prRxStatusGroup2; + prRxStatusGroup3 = prSwRfb->prRxStatusGroup3; + + /* Bit Number 30 Vendor Namespace */ + u4VendorNsLen = sizeof(struct RADIOTAP_FIELD_VENDOR_); + rRadiotapFieldVendor.aucOUI[0] = aucMtkOui[0]; + rRadiotapFieldVendor.aucOUI[1] = aucMtkOui[1]; + rRadiotapFieldVendor.aucOUI[2] = aucMtkOui[2]; + rRadiotapFieldVendor.ucSubNamespace = 0; + rRadiotapFieldVendor.u2DataLen = u4VendorNsLen - 6; + /* VHTA1 B0-B1 */ + rRadiotapFieldVendor.ucData = ((( + prRxStatusGroup3)->u4RxVector[0] + & RX_VT_FR_MODE_MASK) >> + RX_VT_FR_MODE_OFFSET); + + ucRxMode = (((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_RX_MODE_MASK) >> RX_VT_RX_MODE_OFFSET); + + if (ucRxMode == RX_VT_VHT_MODE) { + u4RadiotapLen = RADIOTAP_LEN_VHT; + u4ItPresent = RADIOTAP_FIELDS_VHT; + } else if ((ucRxMode == RX_VT_MIXED_MODE) + || (ucRxMode == RX_VT_GREEN_MODE)) { + u4RadiotapLen = RADIOTAP_LEN_HT; + u4ItPresent = RADIOTAP_FIELDS_HT; + } else { + u4RadiotapLen = RADIOTAP_LEN_LEGACY; + u4ItPresent = RADIOTAP_FIELDS_LEGACY; + } + + /* Radiotap Header & Bit Number 30 Vendor Namespace */ + prVendorNsOffset = (uint8_t *) &rMonitorRadiotap + + u4RadiotapLen; + u4RadiotapLen += u4VendorNsLen; + kalMemSet(&rMonitorRadiotap, 0, + sizeof(struct MONITOR_RADIOTAP)); + kalMemCopy(prVendorNsOffset, + (uint8_t *) &rRadiotapFieldVendor, u4VendorNsLen); + rMonitorRadiotap.u2ItLen = cpu_to_le16(u4RadiotapLen); + rMonitorRadiotap.u4ItPresent = u4ItPresent; + + /* Bit Number 0 TSFT */ + rMonitorRadiotap.u8MacTime = + (prRxStatusGroup2->u4Timestamp); + + /* Bit Number 1 FLAGS */ + if (prSwRfb->fgIsFrag) + rMonitorRadiotap.ucFlags |= BIT(3); + + if (prSwRfb->fgIsFCS) + rMonitorRadiotap.ucFlags |= BIT(6); + + /* Bit Number 2 RATE */ + if ((ucRxMode == RX_VT_LEGACY_CCK) + || (ucRxMode == RX_VT_LEGACY_OFDM)) { + /* Bit[2:0] for Legacy CCK, Bit[3:0] for Legacy OFDM */ + ucRxRate = ((prRxStatusGroup3)->u4RxVector[0] & BITS(0, 3)); + rMonitorRadiotap.ucRate = nicGetHwRateByPhyRate(ucRxRate); + } else { + ucMcs = ((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_RX_RATE_AC_MASK); + /* VHTA1 B0-B1 */ + ucFrMode = (((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET); + ucShortGI = ((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_SHORT_GI) ? 1 : 0; /* VHTA2 B0 */ + + /* ucRate(500kbs) = u4PhyRate(100kbps) / 5, max ucRate = 0xFF */ + u4PhyRate = nicGetPhyRateByMcsRate(ucMcs, ucFrMode, + ucShortGI); + if (u4PhyRate > 1275) + rMonitorRadiotap.ucRate = 0xFF; + else + rMonitorRadiotap.ucRate = u4PhyRate / 5; + } + + /* Bit Number 3 CHANNEL */ + if (ucRxMode == RX_VT_LEGACY_CCK) + rMonitorRadiotap.u2ChFlags |= BIT(5); + else /* OFDM */ + rMonitorRadiotap.u2ChFlags |= BIT(6); + + RX_STATUS_GET(prRxDescOps, ucChanNum, get_ch_num, prRxStatus); + RX_STATUS_GET(prRxDescOps, eBand, get_rf_band, prRxStatus); + if (eBand == BAND_2G4) { + rMonitorRadiotap.u2ChFlags |= BIT(7); + rMonitorRadiotap.u2ChFrequency = (ucChanNum * 5 + 2407); + } else { /* BAND_5G */ + rMonitorRadiotap.u2ChFlags |= BIT(8); + rMonitorRadiotap.u2ChFrequency = (ucChanNum * 5 + 5000); + } + + /* Bit Number 5 ANT SIGNAL */ + rMonitorRadiotap.ucAntennaSignal = + RCPI_TO_dBm(HAL_RX_STATUS_GET_RCPI0(prRxStatusGroup3)); + + /* Bit Number 6 ANT NOISE */ + rMonitorRadiotap.ucAntennaNoise = (((( + prRxStatusGroup3)->u4RxVector[5] + & RX_VT_NF0_MASK) >> 1) + + 128); + + /* Bit Number 11 ANT, Invalid for MT6632 and MT7615 */ + rMonitorRadiotap.ucAntenna = (( + prRxStatusGroup3)->u4RxVector[2] & RX_VT_SEL_ANT) ? 1 : 0; + + /* Bit Number 19 MCS */ + if ((u4ItPresent & RADIOTAP_FIELD_MCS)) + nicRxFillRadiotapMCS(&rMonitorRadiotap, prRxStatusGroup3); + + /* Bit Number 20 AMPDU */ + if (prSwRfb->fgIsAmpdu) { + if (prSwRfb->ucRxvSeqNo) + ++prRxCtrl->u4AmpduRefNum; + rMonitorRadiotap.u4AmpduRefNum = prRxCtrl->u4AmpduRefNum; + } + + /* Bit Number 21 VHT */ + if ((u4ItPresent & RADIOTAP_FIELD_VHT)) + nicRxFillRadiotapVHT(&rMonitorRadiotap, prRxStatusGroup3); + + prSwRfb->pvHeader -= u4RadiotapLen; + kalMemCopy(prSwRfb->pvHeader, &rMonitorRadiotap, + u4RadiotapLen); + + prSkb = (struct sk_buff *)(prSwRfb->pvPacket); + prSkb->data = (unsigned char *)(prSwRfb->pvHeader); + + skb_reset_tail_pointer(prSkb); + skb_trim(prSkb, 0); + skb_put(prSkb, (u4RadiotapLen + prSwRfb->u2PacketLen)); + +#if CFG_SUPPORT_MULTITHREAD + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); + QUEUE_INSERT_TAIL(&(prAdapter->rRxQueue), + (struct QUE_ENTRY *) GLUE_GET_PKT_QUEUE_ENTRY( + prSwRfb->pvPacket)); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); + + prRxCtrl->ucNumIndPacket++; + kalSetTxEvent2Rx(prAdapter->prGlueInfo); +#else + prRxCtrl->apvIndPacket[prRxCtrl->ucNumIndPacket] = + prSwRfb->pvPacket; + prRxCtrl->ucNumIndPacket++; +#endif + + prSwRfb->pvPacket = NULL; + /* Return RFB */ + if (nicRxSetupRFB(prAdapter, prSwRfb)) { + DBGLOG(RX, WARN, + "Cannot allocate packet buffer for SwRfb!\n"); + if (!timerPendingTimer( + &prAdapter->rPacketDelaySetupTimer)) { + DBGLOG(RX, WARN, + "Start ReturnIndicatedRfb Timer (%u)\n", + RX_RETURN_INDICATED_RFB_TIMEOUT_SEC); + cnmTimerStartTimer(prAdapter, + &prAdapter->rPacketDelaySetupTimer, + SEC_TO_MSEC( + RX_RETURN_INDICATED_RFB_TIMEOUT_SEC)); + } + } + nicRxReturnRFB(prAdapter, prSwRfb); +} +#else +/*----------------------------------------------------------------------------*/ +/*! + * @brief Process HIF monitor packet + * + * @param prAdapter pointer to the Adapter handler + * @param prSWRfb the RFB to receive rx data + * + * @return (none) + * + */ +/*----------------------------------------------------------------------------*/ +void nicRxProcessMonitorPacket(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb) +{ +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Process & Parsing RXV for traffic indicator + * + * @param prAdapter pointer to the Adapter handler + * @param prSWRfb the RFB to receive rx data + * + * @return (none) + * + */ +/*----------------------------------------------------------------------------*/ +#if CFG_SUPPORT_PERF_IND +void nicRxPerfIndProcessRXV(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint8_t ucBssIndex) +{ + struct mt66xx_chip_info *prChipInfo; + + prChipInfo = prAdapter->chip_info; + if (prChipInfo->asicRxPerfIndProcessRXV) + prChipInfo->asicRxPerfIndProcessRXV( + prAdapter, prSwRfb, ucBssIndex); + /* else { */ + /* print too much, remove for system perfomance */ + /* DBGLOG(RX, ERROR, "%s: no asicRxPerfIndProcessRXV ??\n", */ + /* __func__); */ + /* } */ +} +#endif + +static void nicRxSendDeauthPacket(IN struct ADAPTER *prAdapter, + IN uint16_t u2FrameCtrl, + IN uint8_t *pucSrcAddr, + IN uint8_t *pucDestAddr, + IN uint8_t *pucBssid) +{ + struct SW_RFB rSwRfb; + struct WLAN_MAC_HEADER rWlanHeader; + uint32_t u4Status; + + if (!prAdapter || !pucSrcAddr || !pucDestAddr || !pucBssid) + return; + + kalMemZero(&rSwRfb, sizeof(rSwRfb)); + kalMemZero(&rWlanHeader, sizeof(rWlanHeader)); + + rWlanHeader.u2FrameCtrl = u2FrameCtrl; + COPY_MAC_ADDR(rWlanHeader.aucAddr1, pucSrcAddr); + COPY_MAC_ADDR(rWlanHeader.aucAddr2, pucDestAddr); + COPY_MAC_ADDR(rWlanHeader.aucAddr3, pucBssid); + rSwRfb.pvHeader = &rWlanHeader; + + u4Status = authSendDeauthFrame(prAdapter, + NULL, + NULL, + &rSwRfb, + REASON_CODE_CLASS_3_ERR, + NULL); + if (u4Status != WLAN_STATUS_SUCCESS) + DBGLOG(NIC, WARN, "u4Status: %d\n", u4Status); +} + +static void nicRxProcessDropPacket(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct WLAN_MAC_HEADER *prWlanHeader = NULL; + uint8_t ucBssIndex = 0; + uint16_t u2FrameCtrl; + + if (!prAdapter || !prSwRfb) + return; + + prWlanHeader = (struct WLAN_MAC_HEADER *) prSwRfb->pvHeader; + + if (!prWlanHeader) + return; + + u2FrameCtrl = prWlanHeader->u2FrameCtrl; + DBGLOG(NIC, TRACE, + "TA: " MACSTR " RA: " MACSTR " bssid: " MACSTR " fc: 0x%x\n", + MAC2STR(prWlanHeader->aucAddr2), + MAC2STR(prWlanHeader->aucAddr1), + MAC2STR(prWlanHeader->aucAddr3), + u2FrameCtrl); + + if ((u2FrameCtrl & (MASK_FC_FROM_DS | MASK_FC_TO_DS)) == 0) + return; + + for (ucBssIndex = 0; ucBssIndex < prAdapter->ucHwBssIdNum; + ucBssIndex++) { + struct BSS_INFO *prBssInfo; + u_int8_t fgSendDeauth = FALSE; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + if (!prBssInfo) + continue; + if (IS_BSS_NOT_ALIVE(prAdapter, prBssInfo)) + continue; + switch (prBssInfo->eNetworkType) { + case NETWORK_TYPE_P2P: + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT && + EQUAL_MAC_ADDR(prWlanHeader->aucAddr3, + prBssInfo->aucOwnMacAddr)) + fgSendDeauth = TRUE; + break; + default: + break; + } + + if (fgSendDeauth) + nicRxSendDeauthPacket(prAdapter, + u2FrameCtrl, + prWlanHeader->aucAddr1, + prWlanHeader->aucAddr2, + prWlanHeader->aucAddr3); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb) +{ + struct RX_CTRL *prRxCtrl; + struct SW_RFB *prRetSwRfb, *prNextSwRfb; + struct HW_MAC_RX_DESC *prRxStatus; + + u_int8_t fgDrop; + uint8_t ucBssIndex = 0; + struct mt66xx_chip_info *prChipInfo; + struct STA_RECORD *prStaRec; + struct RX_DESC_OPS_T *prRxDescOps; + + DEBUGFUNC("nicRxProcessDataPacket"); + /* DBGLOG(INIT, TRACE, ("\n")); */ + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + nicRxFillRFB(prAdapter, prSwRfb); + + fgDrop = FALSE; + + prRxCtrl = &prAdapter->rRxCtrl; + prChipInfo = prAdapter->chip_info; + prRxDescOps = prChipInfo->prRxDescOps; + prRxStatus = prSwRfb->prRxStatus; + + /* Check AMPDU_nERR_Bitmap */ + prSwRfb->fgDataFrame = TRUE; + prSwRfb->fgFragFrame = FALSE; + prSwRfb->fgReorderBuffer = FALSE; + +#if CFG_WIFI_SW_CIPHER_MISMATCH + if (prSwRfb->prStaRec && + prSwRfb->prStaRec->fgTransmitKeyExist && + prSwRfb->prStaRec->ucStaState == STA_STATE_3 && + prSwRfb->fgIsBC == FALSE && + prSwRfb->fgIsMC == FALSE && + !prSwRfb->fgIsCipherMS) { + uint16_t u2FrameCtrl = 0; + + if (prSwRfb->fgHdrTran == FALSE) { + u2FrameCtrl = ((struct WLAN_MAC_HEADER *) + prSwRfb->pvHeader)->u2FrameCtrl; + prSwRfb->fgIsCipherMS = + !RXM_IS_PROTECTED_FRAME(u2FrameCtrl); + } else if (prSwRfb->prRxStatusGroup4) { + u2FrameCtrl = HAL_RX_STATUS_GET_FRAME_CTL_FIELD( + prSwRfb->prRxStatusGroup4); + prSwRfb->fgIsCipherMS = + !RXM_IS_PROTECTED_FRAME(u2FrameCtrl); + } + } +#endif + + if (prRxDescOps->nic_rxd_sanity_check) + fgDrop = prRxDescOps->nic_rxd_sanity_check( + prAdapter, prSwRfb); + else { + DBGLOG(RX, ERROR, + "%s:: no nic_rxd_sanity_check??\n", __func__); + fgDrop = TRUE; + } + + if (fgDrop && prRxStatus->ucWlanIdx >= WTBL_SIZE && + HAL_RX_STATUS_IS_LLC_MIS(prRxStatus)) + nicRxProcessDropPacket(prAdapter, prSwRfb); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD || CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 + if (prAdapter->fgIsSupportCsumOffload && fgDrop == FALSE) + nicRxFillChksumStatus(prAdapter, prSwRfb); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + /* if(secCheckClassError(prAdapter, prSwRfb, prStaRec) == TRUE && */ + if (prAdapter->fgTestMode == FALSE && fgDrop == FALSE) { +#if CFG_HIF_RX_STARVATION_WARNING + prRxCtrl->u4QueuedCnt++; +#endif + ucBssIndex = secGetBssIdxByWlanIdx(prAdapter, + prSwRfb->ucWlanIdx); + GLUE_SET_PKT_BSS_IDX(prSwRfb->pvPacket, ucBssIndex); + STATS_RX_PKT_INFO_DISPLAY(prSwRfb); + +#if ((CFG_SUPPORT_802_11AX == 1) && (CFG_SUPPORT_WIFI_SYSDVT == 1)) + if (fgEfuseCtrlAxOn == 1) { + if (prAdapter->fgEnShowHETrigger) { + uint16_t u2TxFrameCtrl; + + u2TxFrameCtrl = (*(uint8_t *) (prSwRfb->pvHeader) & + MASK_FRAME_TYPE); + if (RXM_IS_TRIGGER_FRAME(u2TxFrameCtrl)) { + DBGLOG(NIC, STATE, + "\n%s: HE Trigger --------------\n", + __func__); + dumpMemory8((uint8_t *)prSwRfb->prRxStatus, + prSwRfb->u2RxByteCount); + DBGLOG(NIC, STATE, + "%s: HE Trigger end --------------\n", + __func__); + nicRxReturnRFB(prAdapter, prSwRfb); + return; + } + } + } +#endif /* CFG_SUPPORT_802_11AX == 1 */ + + prRetSwRfb = qmHandleRxPackets(prAdapter, prSwRfb); + if (prRetSwRfb != NULL) { + do { +#if (CFG_SUPPORT_MSP == 1) + /* collect RXV information */ + if (prChipInfo->asicRxProcessRxvforMSP) + prChipInfo->asicRxProcessRxvforMSP( + prAdapter, prRetSwRfb); +#endif /* CFG_SUPPORT_MSP == 1 */ +#if CFG_SUPPORT_PERF_IND + nicRxPerfIndProcessRXV( + prAdapter, + prRetSwRfb, + ucBssIndex); +#endif + + /* save next first */ + prNextSwRfb = (struct SW_RFB *) + QUEUE_GET_NEXT_ENTRY( + (struct QUE_ENTRY *) + prRetSwRfb); + + switch (prRetSwRfb->eDst) { + case RX_PKT_DESTINATION_HOST: + prStaRec = cnmGetStaRecByIndex( + prAdapter, + prRetSwRfb->ucStaRecIdx); + if (prStaRec && + IS_STA_IN_AIS(prStaRec)) { +#if ARP_MONITER_ENABLE + qmHandleRxArpPackets(prAdapter, + prRetSwRfb); + qmHandleRxDhcpPackets(prAdapter, + prRetSwRfb); +#endif + } +#if CFG_SUPPORT_WIFI_SYSDVT +#if (CFG_SUPPORT_CONNAC2X == 1) + /* Not handle non-CONNAC2X case */ + if (RXV_AUTODVT_DNABLED(prAdapter) && + (prRetSwRfb->ucGroupVLD & + BIT(RX_GROUP_VLD_3)) && + (prRetSwRfb->ucGroupVLD & + BIT(RX_GROUP_VLD_5))) { + connac2x_rxv_correct_test( + prAdapter, prRetSwRfb); + } +#endif +#endif /* CFG_SUPPORT_WIFI_SYSDVT */ + if (prStaRec && + prStaRec->ucBssIndex < MAX_BSSID_NUM) { + GET_CURRENT_SYSTIME( + &prRxCtrl->u4LastRxTime + [prStaRec->ucBssIndex]); + } + 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); + } +} + +#if 1 +void nicRxProcessEventPacket(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb) +{ + struct mt66xx_chip_info *prChipInfo; + struct CMD_INFO *prCmdInfo; + struct WIFI_EVENT *prEvent; + uint32_t u4Idx, u4Size; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + prChipInfo = prAdapter->chip_info; + prEvent = (struct WIFI_EVENT *) + (prSwRfb->pucRecvBuff + prChipInfo->rxd_size); + if (prEvent->ucEID != EVENT_ID_DEBUG_MSG + && prEvent->ucEID != EVENT_ID_ASSERT_DUMP) { + DBGLOG(NIC, TRACE, + "RX EVENT: ID[0x%02X] SEQ[%u] LEN[%u]\n", + prEvent->ucEID, prEvent->ucSeqNum, + prEvent->u2PacketLength); + } +#if (CFG_SUPPORT_STATISTICS == 1) + wlanWakeLogEvent(prEvent->ucEID); +#endif + /* Event handler table */ + u4Size = sizeof(arEventTable) / sizeof(struct + RX_EVENT_HANDLER); + + for (u4Idx = 0; u4Idx < u4Size; u4Idx++) { + if (prEvent->ucEID == arEventTable[u4Idx].eEID) { + arEventTable[u4Idx].pfnHandler(prAdapter, prEvent); + + break; + } + } + + /* Event cannot be found in event handler table, use default action */ + if (u4Idx >= u4Size) { + 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); + } else { + DBGLOG_LIMITED(RX, INFO, + "UNHANDLED RX EVENT: ID[0x%02X] SEQ[%u] LEN[%u]\n", + prEvent->ucEID, prEvent->ucSeqNum, + prEvent->u2PacketLength); + } + } + + /* Reset Chip NoAck flag */ + if (prAdapter->fgIsChipNoAck) { + DBGLOG_LIMITED(RX, WARN, + "Got response from chip, clear NoAck flag!\n"); + WARN_ON(TRUE); + } + prAdapter->ucOidTimeoutCount = 0; + prAdapter->fgIsChipNoAck = FALSE; + + nicRxReturnRFB(prAdapter, prSwRfb); +} +#else +u_int8_t fgKeepPrintCoreDump = FALSE; +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb) +{ + struct CMD_INFO *prCmdInfo; + /* P_MSDU_INFO_T prMsduInfo; */ + struct WIFI_EVENT *prEvent; + struct GLUE_INFO *prGlueInfo; + u_int8_t fgIsNewVersion; + /*#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1)*/ + uint32_t u4QueryInfoLen; + /*#endif*/ + /*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ + struct EVENT_ACCESS_EFUSE *prEventEfuseAccess; + struct EXT_EVENT_EFUSE_FREE_BLOCK *prEventGetFreeBlock; + /*#endif*/ + DEBUGFUNC("nicRxProcessEventPacket"); + /* DBGLOG(INIT, TRACE, ("\n")); */ + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + nicRxFillRFB(prAdapter, prSwRfb); + if (prSwRfb->prRxStatusGroup3 == NULL) { + DBGLOG(RX, WARN, + "rxStatusGroup3 for MGMT frame is NULL, drop this packet, dump RXD and Packet\n"); + DBGLOG_MEM8(RX, WARN, (uint8_t *) prSwRfb->prRxStatus, + sizeof(*prSwRfb->prRxStatus)); + if (prSwRfb->pvHeader) + DBGLOG_MEM8(RX, WARN, (uint8_t *) prSwRfb->pvHeader, + prSwRfb->u2PacketLen > 32 ? + 32 : prSwRfb->u2PacketLen); + nicRxReturnRFB(prAdapter, prSwRfb); + RX_INC_CNT(&prAdapter->rRxCtrl, RX_DROP_TOTAL_COUNT); +#if 0 +#if CFG_CHIP_RESET_SUPPORT + glSetRstReason(RST_GROUP3_NULL); + glResetTrigger(prAdapter); +#endif +#endif + ) { + DBGLOG(INIT, INFO, + "RX EVENT: ID[0x%02X] SEQ[%u] LEN[%u]\n", + prEvent->ucEID, prEvent->ucSeqNum, + prEvent->u2PacketLength); + } + + /* Event Handling */ + switch (prEvent->ucEID) { +#if 0 /* It is removed now */ + case EVENT_ID_CMD_RESULT: + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + struct EVENT_CMD_RESULT *prCmdResult; + + prCmdResult = (struct EVENT_CMD_RESULT *) + ((uint8_t *) 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; +#endif + +#if 0 + case EVENT_ID_CONNECTION_STATUS: + /* OBSELETE */ + { + struct EVENT_CONNECTION_STATUS *prConnectionStatus; + + prConnectionStatus = + (struct EVENT_CONNECTION_STATUS *) + (prEvent->aucBuffer); + + DbgPrint("RX EVENT: EVENT_ID_CONNECTION_STATUS = %d\n", + prConnectionStatus->ucMediaStatus); + if (prConnectionStatus->ucMediaStatus == + MEDIA_STATE_DISCONNECTED) { + /* disconnected */ + if (kalGetMediaStateIndicated(prGlueInfo) != + MEDIA_STATE_DISCONNECTED) { + + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, + NULL, 0); + + prAdapter->rWlanInfo.u4SysTime = + kalGetTimeTick(); + } + } else if (prConnectionStatus->ucMediaStatus == + MEDIA_STATE_CONNECTED) { + /* connected */ + prAdapter->rWlanInfo.u4SysTime = + kalGetTimeTick(); + + /* fill information for association result */ + prAdapter->rWlanInfo.rCurrBssId.rSsid. + u4SsidLen = prConnectionStatus->ucSsidLen; + kalMemCopy( + prAdapter->rWlanInfo.rCurrBssId. + rSsid.aucSsid, + prConnectionStatus->aucSsid, + prConnectionStatus->ucSsidLen); + + kalMemCopy( + prAdapter->rWlanInfo.rCurrBssId. + arMacAddress, + prConnectionStatus->aucBssid, + MAC_ADDR_LEN); + /* @FIXME */ + prAdapter->rWlanInfo.rCurrBssId.u4Privacy = + prConnectionStatus->ucEncryptStatus; + /* @FIXME */ + prAdapter->rWlanInfo.rCurrBssId.rRssi = 0; + /* @FIXME */ + prAdapter->rWlanInfo.rCurrBssId. + eNetworkTypeInUse = PARAM_NETWORK_TYPE_AUTOMODE; + prAdapter->rWlanInfo.rCurrBssId.rConfiguration. + u4BeaconPeriod + = prConnectionStatus->u2BeaconPeriod; + prAdapter->rWlanInfo.rCurrBssId.rConfiguration. + u4ATIMWindow + = prConnectionStatus->u2ATIMWindow; + prAdapter->rWlanInfo.rCurrBssId.rConfiguration. + u4DSConfig + = prConnectionStatus->u4FreqInKHz; + prAdapter->rWlanInfo.ucNetworkType = + prConnectionStatus->ucNetworkType; + + switch (prConnectionStatus->ucInfraMode) { + case 0: + prAdapter->rWlanInfo.rCurrBssId.eOpMode + = NET_TYPE_IBSS; + break; + case 1: + prAdapter->rWlanInfo.rCurrBssId.eOpMode + = NET_TYPE_INFRA; + break; + case 2: + default: + prAdapter->rWlanInfo.rCurrBssId.eOpMode + = NET_TYPE_AUTO_SWITCH; + break; + } + /* always indicate to OS according to MSDN + * (re-association/roaming) + */ + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_CONNECT, NULL, 0); + } + } + break; + + case EVENT_ID_SCAN_RESULT: + /* OBSELETE */ + break; +#endif + + case EVENT_ID_RX_ADDBA: + /* The FW indicates that an RX BA agreement + * will be established + */ + qmHandleEventRxAddBa(prAdapter, prEvent); + break; + + case EVENT_ID_RX_DELBA: + /* The FW indicates that an RX BA agreement + * has been deleted + */ + qmHandleEventRxDelBa(prAdapter, prEvent); + break; + + case EVENT_ID_CHECK_REORDER_BUBBLE: + qmHandleEventCheckReorderBubble(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( + struct EVENT_LINK_QUALITY_EX)) { + struct EVENT_LINK_QUALITY_EX *prLqEx = + (struct EVENT_LINK_QUALITY_EX *) + (prEvent->aucBuffer); + + if (prLqEx->ucIsLQ0Rdy) + nicUpdateLinkQuality(prAdapter, 0, + (struct EVENT_LINK_QUALITY *) + prLqEx); + if (prLqEx->ucIsLQ1Rdy) + nicUpdateLinkQuality(prAdapter, 1, + (struct 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, 0, + (struct EVENT_LINK_QUALITY *) + (prEvent->aucBuffer)); + } +#else + /*only support ais query */ + { + uint8_t ucBssIndex; + struct BSS_INFO *prBssInfo; + + for (ucBssIndex = 0; + ucBssIndex < prAdapter->ucHwBssIdNum; + ucBssIndex++) { + prBssInfo = + prAdapter->aprBssInfo[ + ucBssIndex]; + + if ((prBssInfo->eNetworkType == + NETWORK_TYPE_AIS) + && (prBssInfo->fgIsInUse)) + break; + } + + /* No hit(bss1 for default ais network) */ + if (ucBssIndex >= prAdapter->ucHwBssIdNum) + ucBssIndex = 1; + + nicUpdateLinkQuality(prAdapter, ucBssIndex, + (struct 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 + >= (int32_t) ( + prAdapter->rLinkQuality.cRssi)) { + prAdapter->rWlanInfo.eRssiTriggerType = + ENUM_RSSI_TRIGGER_TRIGGERED; + + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (void *) + &(prAdapter->rWlanInfo. + rRssiTriggerValue), + sizeof(int32_t)); + } else if (prAdapter->rWlanInfo.eRssiTriggerType == + ENUM_RSSI_TRIGGER_LESS + && prAdapter->rWlanInfo.rRssiTriggerValue + <= (int32_t) ( + prAdapter->rLinkQuality.cRssi)) { + prAdapter->rWlanInfo.eRssiTriggerType = + ENUM_RSSI_TRIGGER_TRIGGERED; + + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (void *) + &(prAdapter->rWlanInfo. + rRssiTriggerValue), + sizeof(int32_t)); + } +#endif + + break; + + /*#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1)*/ + case EVENT_ID_LAYER_0_EXT_MAGIC_NUM: + if ((prEvent->ucExtenEID) == EXT_EVENT_ID_CMD_RESULT) { + + u4QueryInfoLen = + sizeof( + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE); + + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + if ((prCmdInfo->fgIsOid) != 0) { + kalOidComplete( + prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo( + prAdapter, prCmdInfo); + } + } + } + /*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ + + else if ((prEvent->ucExtenEID) == + EXT_EVENT_ID_CMD_EFUSE_ACCESS) { + u4QueryInfoLen = + sizeof( + struct PARAM_CUSTOM_ACCESS_EFUSE); + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + prEventEfuseAccess = + (struct EVENT_ACCESS_EFUSE *) + (prEvent->aucBuffer); + + /* Efuse block size 16 */ + kalMemCopy(prAdapter->aucEepromVaule, + prEventEfuseAccess->aucData, 16); + + if (prCmdInfo != NULL) { + if ((prCmdInfo->fgIsOid) != 0) { + kalOidComplete( + prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo( + prAdapter, prCmdInfo); + + } + } + } + + else if ((prEvent->ucExtenEID) == + EXT_EVENT_ID_EFUSE_FREE_BLOCK) { + u4QueryInfoLen = sizeof(struct + PARAM_CUSTOM_EFUSE_FREE_BLOCK); + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + prEventGetFreeBlock = + (struct EXT_EVENT_EFUSE_FREE_BLOCK *) + (prEvent->aucBuffer); + prAdapter->u4FreeBlockNum = + prEventGetFreeBlock->u2FreeBlockNum; + + if (prCmdInfo != NULL) { + if ((prCmdInfo->fgIsOid) != 0) { + kalOidComplete( + prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, + prCmdInfo); + } + } + } + /*#endif*/ + break; + /*#endif*/ + + case EVENT_ID_MIC_ERR_INFO: { + struct EVENT_MIC_ERR_INFO *prMicError; + /* P_PARAM_AUTH_EVENT_T prAuthEvent; */ + struct STA_RECORD *prStaRec; + + DBGLOG(RSN, EVENT, "EVENT_ID_MIC_ERR_INFO\n"); + + prMicError = (struct EVENT_MIC_ERR_INFO *) ( + prEvent->aucBuffer); + prStaRec = cnmGetStaRecByAddress(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, + prAdapter->rWlanInfo.rCurrBssId.arMacAddress); + ASSERT(prStaRec); + + if (prStaRec) + rsnTkipHandleMICFailure(prAdapter, prStaRec, + (u_int8_t) prMicError->u4Flags); + else + DBGLOG(RSN, INFO, "No STA rec!!\n"); +#if 0 + prAuthEvent = (struct PARAM_AUTH_EVENT *) + prAdapter->aucIndicationEventBuffer; + + /* Status type: Authentication Event */ + prAuthEvent->rStatus.eStatusType = + ENUM_STATUS_TYPE_AUTHENTICATION; + + /* Authentication request */ + prAuthEvent->arRequest[0].u4Length = sizeof( + struct PARAM_AUTH_REQUEST); + kalMemCopy((void *) prAuthEvent->arRequest[0].arBssid, + (void *) + prAdapter->rWlanInfo.rCurrBssId.arMacAddress, + 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, + (void *) prAuthEvent, + sizeof(struct PARAM_STATUS_INDICATION) + sizeof( + struct PARAM_AUTH_REQUEST)); +#endif + } + break; + +#if 0 /* Marked for MT6630 */ + case EVENT_ID_ASSOC_INFO: { + struct EVENT_ASSOC_INFO *prAssocInfo; + + prAssocInfo = (struct EVENT_ASSOC_INFO *) ( + prEvent->aucBuffer); + + kalHandleAssocInfo(prAdapter->prGlueInfo, prAssocInfo); + } + break; + + case EVENT_ID_802_11_PMKID: { + struct PARAM_AUTH_EVENT *prAuthEvent; + uint8_t *cp; + uint32_t u4LenOfUsedBuffer; + + prAuthEvent = (struct PARAM_AUTH_EVENT *) + prAdapter->aucIndicationEventBuffer; + + prAuthEvent->rStatus.eStatusType = + ENUM_STATUS_TYPE_CANDIDATE_LIST; + + u4LenOfUsedBuffer = + (uint32_t) (prEvent->u2PacketLength - 8); + + prAuthEvent->arRequest[0].u4Length = u4LenOfUsedBuffer; + + cp = (uint8_t *) &prAuthEvent->arRequest[0]; + + /* Status type: PMKID Candidatelist Event */ + kalMemCopy(cp, (struct EVENT_PMKID_CANDIDATE_LIST *) ( + prEvent->aucBuffer), + prEvent->u2PacketLength - 8); + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (void *) prAuthEvent, + sizeof(struct PARAM_STATUS_INDICATION) + + u4LenOfUsedBuffer); + } + break; +#endif + case EVENT_ID_SCAN_DONE: + fgIsNewVersion = TRUE; + scnEventScanDone(prAdapter, + (struct EVENT_SCAN_DONE *) (prEvent->aucBuffer), + fgIsNewVersion); + break; + + case EVENT_ID_NLO_DONE: + DBGLOG(INIT, INFO, "EVENT_ID_NLO_DONE\n"); + scnEventNloDone(prAdapter, + (struct EVENT_NLO_DONE *) (prEvent->aucBuffer)); +#if CFG_SUPPORT_PNO + prAdapter->prAisBssInfo->fgIsPNOEnable = FALSE; + if (prAdapter->prAisBssInfo->fgIsNetRequestInActive + && prAdapter->prAisBssInfo->fgIsPNOEnable) { + UNSET_NET_ACTIVE(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex); + DBGLOG(INIT, INFO, + "INACTIVE AIS from ACTIVEto disable PNO\n"); + /* sync with firmware */ + nicDeactivateNetwork(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex); + } +#endif + break; + + case EVENT_ID_TX_DONE: +#if 1 + nicTxProcessTxDoneEvent(prAdapter, prEvent); +#else + { + struct EVENT_TX_DONE *prTxDone; + + prTxDone = + (struct EVENT_TX_DONE *) + (prEvent->aucBuffer); + + DBGLOG(INIT, INFO, + "EVENT_ID_TX_DONE WIDX:PID[%u:%u] Status[%u] SN[%u]\n", + prTxDone->ucWlanIndex, + prTxDone->ucPacketSeq, + prTxDone->ucStatus, + prTxDone->u2SequenceNumber); + + /* call related TX Done Handler */ + prMsduInfo = nicGetPendingTxMsduInfo(prAdapter, + prTxDone->ucWlanIndex, + 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 ENUM_TX_RESULT_CODE) + (prTxDone->ucStatus)); + + if (prMsduInfo->eSrc == TX_PACKET_MGMT) + cnmMgtPktFree( + prAdapter, prMsduInfo); + else + nicTxReturnMsduInfo( + prAdapter, prMsduInfo); + } + } +#endif + break; + + case EVENT_ID_SLEEPY_INFO: +#if defined(_HIF_USB) +#else + { + struct EVENT_SLEEPY_INFO *prEventSleepyNotify; + + prEventSleepyNotify = (struct EVENT_SLEEPY_INFO *) ( + prEvent->aucBuffer); + + prAdapter->fgWiFiInSleepyState = (u_int8_t) ( + prEventSleepyNotify->ucSleepyState); + +#if CFG_SUPPORT_MULTITHREAD + if (prEventSleepyNotify->ucSleepyState) + kalSetFwOwnEvent2Hif(prGlueInfo); +#endif + } +#endif + break; + case EVENT_ID_BT_OVER_WIFI: +#if CFG_ENABLE_BT_OVER_WIFI + { + uint8_t aucTmp[sizeof(struct BT_OVER_WIFI_EVENT) + + sizeof(struct BOW_LINK_DISCONNECTED)]; + struct EVENT_BT_OVER_WIFI *prEventBtOverWifi; + struct BT_OVER_WIFI_EVENT *prBowEvent; + struct BOW_LINK_CONNECTED *prBowLinkConnected; + struct BOW_LINK_DISCONNECTED *prBowLinkDisconnected; + + prEventBtOverWifi = (struct EVENT_BT_OVER_WIFI *) ( + prEvent->aucBuffer); + + /* construct event header */ + prBowEvent = (struct BT_OVER_WIFI_EVENT *) aucTmp; + + if (prEventBtOverWifi->ucLinkStatus == 0) { + /* Connection */ + prBowEvent->rHeader.ucEventId = + BOW_EVENT_ID_LINK_CONNECTED; + prBowEvent->rHeader.ucSeqNumber = 0; + prBowEvent->rHeader.u2PayloadLength = sizeof( + struct BOW_LINK_CONNECTED); + + /* fill event body */ + prBowLinkConnected = + (struct 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( + struct BOW_LINK_DISCONNECTED); + + /* fill event body */ + prBowLinkDisconnected = + (struct BOW_LINK_DISCONNECTED *) + (prBowEvent->aucPayload); + /* @FIXME */ + prBowLinkDisconnected->ucReason = 0; + 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(struct 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; + +#if CFG_SUPPORT_MSP + case EVENT_ID_WTBL_INFO: + /* buffer statistics for further query */ + prAdapter->fgIsStatValid = TRUE; + prAdapter->rStatUpdateTime = kalGetTimeTick(); + kalMemCopy(&prAdapter->rEventWlanInfo, + prEvent->aucBuffer, + sizeof(struct EVENT_WLAN_INFO)); + + DBGLOG(RSN, INFO, "EVENT_ID_WTBL_INFO"); + /* 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_MIB_INFO: + /* buffer statistics for further query */ + prAdapter->fgIsStatValid = TRUE; + prAdapter->rStatUpdateTime = kalGetTimeTick(); + + DBGLOG(RSN, INFO, "EVENT_ID_MIB_INFO"); + /* command response handling */ + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + if (prCmdInfo->pfCmdDoneHandler) + prCmdInfo->pfCmdDoneHandler(prAdapter, + prCmdInfo, + prEvent->aucBuffer); + else if (prCmdInfo->fgIsOid) + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + 0, WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + + break; +#endif + 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) { + struct BSS_INFO *prBssInfo = + (struct BSS_INFO *) NULL; + struct EVENT_BSS_BEACON_TIMEOUT + *prEventBssBeaconTimeout; + + prEventBssBeaconTimeout = + (struct EVENT_BSS_BEACON_TIMEOUT *) + (prEvent->aucBuffer); + + if (prEventBssBeaconTimeout->ucBssIndex >= + prAdapter->ucHwBssIdNum) + break; + + DBGLOG(INIT, INFO, "Reason code: %d\n", + prEventBssBeaconTimeout->ucReasonCode); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prEventBssBeaconTimeout->ucBssIndex); + + if (prEventBssBeaconTimeout->ucBssIndex == + prAdapter->prAisBssInfo->ucBssIndex) + aisBssBeaconTimeout(prAdapter); +#if CFG_ENABLE_WIFI_DIRECT + else if (prBssInfo->eNetworkType == + NETWORK_TYPE_P2P) + p2pRoleFsmRunEventBeaconTimeout( + prAdapter, prBssInfo); +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (GET_BSS_INFO_BY_INDEX(prAdapter, + prEventBssBeaconTimeout->ucBssIndex)-> + eNetworkType == NETWORK_TYPE_BOW) { + /* ToDo:: Nothing */ + } +#endif + else { + DBGLOG(RX, ERROR, + "EVENT_ID_BSS_BEACON_TIMEOUT: (ucBssIndex = %d)\n", + prEventBssBeaconTimeout->ucBssIndex); + } + } + + break; + case EVENT_ID_UPDATE_NOA_PARAMS: +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { + struct EVENT_UPDATE_NOA_PARAMS + *prEventUpdateNoaParam; + + prEventUpdateNoaParam = + (struct EVENT_UPDATE_NOA_PARAMS *) + (prEvent->aucBuffer); + + if (GET_BSS_INFO_BY_INDEX(prAdapter, + prEventUpdateNoaParam-> + ucBssIndex)-> + eNetworkType == + NETWORK_TYPE_P2P) { + p2pProcessEvent_UpdateNOAParam( + prAdapter, + prEventUpdateNoaParam-> + ucBssIndex, + prEventUpdateNoaParam); + } else { + ASSERT(0); + } + } +#else + ASSERT(0); +#endif + break; + + case EVENT_ID_STA_AGING_TIMEOUT: +#if CFG_ENABLE_WIFI_DIRECT + { + if (prAdapter->fgDisStaAgingTimeoutDetection == FALSE) { + struct EVENT_STA_AGING_TIMEOUT + *prEventStaAgingTimeout; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo = + (struct BSS_INFO *) NULL; + + prEventStaAgingTimeout = + (struct EVENT_STA_AGING_TIMEOUT *) + (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 = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + bssRemoveClient(prAdapter, prBssInfo, prStaRec); + + /* Call False Auth */ + if (prAdapter->fgIsP2PRegistered) { + p2pFuncDisconnect(prAdapter, + prBssInfo, 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, + (struct EVENT_AP_OBSS_STATUS *) + prEvent->aucBuffer); +#endif + break; + + case EVENT_ID_ROAMING_STATUS: +#if CFG_SUPPORT_ROAMING + { + struct CMD_ROAMING_TRANSIT *prTransit; + + prTransit = (struct CMD_ROAMING_TRANSIT *) ( + prEvent->aucBuffer); + roamingFsmProcessEvent(prAdapter, prTransit); + } +#endif /* CFG_SUPPORT_ROAMING */ + break; + case EVENT_ID_SEND_DEAUTH: +#if DBG + { + struct WLAN_MAC_HEADER *prWlanMacHeader; + + prWlanMacHeader = (struct WLAN_MAC_HEADER *) + prEvent->aucBuffer; + 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 = (struct WLAN_MAC_HEADER *) + prEvent->aucBuffer; + if (authSendDeauthFrame(prAdapter, + NULL, + NULL, + prSwRfb, + REASON_CODE_CLASS_3_ERR, + (PFN_TX_DONE_HANDLER) NULL) == + WLAN_STATUS_SUCCESS) { + DBGLOG(RX, INFO, "Send Deauth Error\n"); + } + break; + +#if CFG_SUPPORT_RDD_TEST_MODE + case EVENT_ID_UPDATE_RDD_STATUS: { + struct EVENT_RDD_STATUS *prEventRddStatus; + + prEventRddStatus = (struct EVENT_RDD_STATUS *) ( + prEvent->aucBuffer); + + prAdapter->ucRddStatus = prEventRddStatus->ucRddStatus; + } + + break; +#endif + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS + case EVENT_ID_UPDATE_BWCS_STATUS: + { + struct PTA_IPC *prEventBwcsStatus; + + prEventBwcsStatus = + (struct PTA_IPC *) (prEvent->aucBuffer); + +#if CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(RSN, EVENT, "BCM BWCS Event: %02x%02x%02x%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, + (void *) prEventBwcsStatus, + sizeof(struct PTA_IPC)); + } + + break; + + case EVENT_ID_UPDATE_BCM_DEBUG: { + struct PTA_IPC *prEventBwcsStatus; + + prEventBwcsStatus = + (struct PTA_IPC *) (prEvent->aucBuffer); + +#if CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(RSN, EVENT, "BCM FW status: %02x%02x%02x%02x\n", + prEventBwcsStatus->u.aucBTPParams[0], + prEventBwcsStatus->u.aucBTPParams[1], + prEventBwcsStatus->u.aucBTPParams[2], + prEventBwcsStatus->u.aucBTPParams[3]); +#endif + } + + break; +#endif + case EVENT_ID_ADD_PKEY_DONE: { + struct EVENT_ADD_KEY_DONE_INFO *prAddKeyDone; + struct STA_RECORD *prStaRec; + + prAddKeyDone = (struct EVENT_ADD_KEY_DONE_INFO *) ( + prEvent->aucBuffer); + + DBGLOG(RSN, EVENT, + "EVENT_ID_ADD_PKEY_DONE BSSIDX=%d " MACSTR "\n", + prAddKeyDone->ucBSSIndex, + MAC2STR(prAddKeyDone->aucStaAddr)); + + prStaRec = cnmGetStaRecByAddress(prAdapter, + prAddKeyDone->ucBSSIndex, + prAddKeyDone->aucStaAddr); + + if (prStaRec) { + DBGLOG(RSN, EVENT, + "STA " MACSTR " Add Key Done!!\n", + MAC2STR(prStaRec->aucMacAddr)); + prStaRec->fgIsTxKeyReady = TRUE; + qmUpdateStaRec(prAdapter, prStaRec); + } + } + break; + case EVENT_ID_ICAP_DONE: { + struct EVENT_ICAP_STATUS *prEventIcapStatus; + struct PARAM_CUSTOM_MEM_DUMP_STRUCT rMemDumpInfo; + uint32_t u4QueryInfo; + + prEventIcapStatus = (struct EVENT_ICAP_STATUS *) ( + prEvent->aucBuffer); + + rMemDumpInfo.u4Address = + prEventIcapStatus->u4StartAddress; + rMemDumpInfo.u4Length = + prEventIcapStatus->u4IcapSieze; +#if CFG_SUPPORT_QA_TOOL + rMemDumpInfo.u4IcapContent = + prEventIcapStatus->u4IcapContent; +#endif + + wlanoidQueryMemDump(prAdapter, &rMemDumpInfo, + sizeof(rMemDumpInfo), &u4QueryInfo); + + } + + break; + case EVENT_ID_DEBUG_MSG: { + struct EVENT_DEBUG_MSG *prEventDebugMsg; + uint16_t u2DebugMsgId; + uint8_t ucMsgType; + uint8_t ucFlags; + uint32_t u4Value; + uint16_t u2MsgSize; + uint8_t *pucMsg; + + prEventDebugMsg = (struct EVENT_DEBUG_MSG *) ( + prEvent->aucBuffer); + + u2DebugMsgId = prEventDebugMsg->u2DebugMsgId; + ucMsgType = prEventDebugMsg->ucMsgType; + ucFlags = prEventDebugMsg->ucFlags; + u4Value = prEventDebugMsg->u4Value; + u2MsgSize = prEventDebugMsg->u2MsgSize; + pucMsg = prEventDebugMsg->aucMsg; + + DBGLOG(SW4, TRACE, + "DEBUG_MSG Id %u Type %u Fg 0x%x Val 0x%x Size %u\n", + u2DebugMsgId, ucMsgType, + ucFlags, u4Value, u2MsgSize); + + if (u2MsgSize <= DEBUG_MSG_SIZE_MAX) { + if (ucMsgType >= DEBUG_MSG_TYPE_END) + ucMsgType = DEBUG_MSG_TYPE_MEM32; + + if (ucMsgType == DEBUG_MSG_TYPE_ASCII) { + uint8_t *pucChr; + + pucMsg[u2MsgSize] = '\0'; + + /* skip newline */ + pucChr = kalStrChr(pucMsg, '\0'); + if (*(pucChr - 1) == '\n') + *(pucChr - 1) = '\0'; + + DBGLOG(SW4, INFO, "%s\n", pucMsg); + } else if (ucMsgType == DEBUG_MSG_TYPE_MEM8) { + DBGLOG(SW4, INFO, "Dump MEM8\n"); + DBGLOG_MEM8(SW4, INFO, + pucMsg, u2MsgSize); + } else { + DBGLOG(SW4, INFO, "Dump MEM32\n"); + DBGLOG_MEM32(SW4, INFO, pucMsg, + u2MsgSize); + } + } /* DEBUG_MSG_SIZE_MAX */ + else + DBGLOG(SW4, INFO, + "Debug msg size %u is too large.\n", + u2MsgSize); + } + break; + +#if CFG_SUPPORT_BATCH_SCAN + case EVENT_ID_BATCH_RESULT: + DBGLOG(SCN, TRACE, "Got EVENT_ID_BATCH_RESULT"); + + /* command response handling */ + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + if (prCmdInfo->pfCmdDoneHandler) + prCmdInfo->pfCmdDoneHandler(prAdapter, + prCmdInfo, + prEvent->aucBuffer); + else if (prCmdInfo->fgIsOid) + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + 0, WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + + break; +#endif /* CFG_SUPPORT_BATCH_SCAN */ + +#if CFG_SUPPORT_TDLS + case EVENT_ID_TDLS: + + TdlsexEventHandle(prAdapter->prGlueInfo, + (uint8_t *) prEvent->aucBuffer, + (uint32_t) (prEvent->u2PacketLength - 8)); + break; +#endif /* CFG_SUPPORT_TDLS */ + + case EVENT_ID_DUMP_MEM: + DBGLOG(INIT, INFO, "%s: EVENT_ID_DUMP_MEM\n", __func__); + + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + DBGLOG(INIT, INFO, ": ==> 1\n"); + 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); + } else { + /* Burst mode */ + DBGLOG(INIT, INFO, ": ==> 2\n"); + nicEventQueryMemDump(prAdapter, + prEvent->aucBuffer); + } + break; +#if CFG_ASSERT_DUMP + case EVENT_ID_ASSERT_DUMP: + + if (prEvent->ucS2DIndex == S2D_INDEX_EVENT_N2H) { + if (!prAdapter->fgN9AssertDumpOngoing) { + DBGLOG(INIT, INFO, + "%s: EVENT_ID_ASSERT_DUMP\n", + __func__); + DBGLOG(INIT, INFO, + "\n[DUMP_N9]====N9 ASSERT_DUMPSTART====\n"); + fgKeepPrintCoreDump = TRUE; + if (kalOpenCorDumpFile(TRUE) != + WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, + "kalOpenCorDumpFile fail\n"); + else + prAdapter->fgN9CorDumpFileOpend + = TRUE; + + prAdapter->fgN9AssertDumpOngoing = TRUE; + } else if (prAdapter->fgN9AssertDumpOngoing) { + + if (fgKeepPrintCoreDump) + DBGLOG(INIT, INFO, + "[DUMP_N9]%s:\n", + prEvent->aucBuffer); + if (!kalStrnCmp(prEvent->aucBuffer, + ";more log added here", + 5) || !kalStrnCmp( + prEvent->aucBuffer, + ";[core dump start]", + 5)) + fgKeepPrintCoreDump = FALSE; + + if (prAdapter->fgN9CorDumpFileOpend && + (kalWriteCorDumpFile( + prEvent->aucBuffer, + prEvent->u2PacketLength, + TRUE) != + WLAN_STATUS_SUCCESS)) { + DBGLOG(INIT, INFO, + "kalWriteN9CorDumpFile fail\n"); + } + wlanCorDumpTimerReset(prAdapter, TRUE); + } + } else { + /* prEvent->ucS2DIndex == S2D_INDEX_EVENT_C2H */ + if (!prAdapter->fgCr4AssertDumpOngoing) { + DBGLOG(INIT, INFO, + "%s: EVENT_ID_ASSERT_DUMP\n", + __func__); + DBGLOG(INIT, INFO, + "\n[DUMP_Cr4]====CR4 ASSERT_DUMPSTART====\n"); + fgKeepPrintCoreDump = TRUE; + if (kalOpenCorDumpFile(FALSE) != + WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, + "kalOpenCorDumpFile fail\n"); + else + prAdapter-> + fgCr4CorDumpFileOpend = TRUE; + + prAdapter->fgCr4AssertDumpOngoing = + TRUE; + } else if (prAdapter->fgCr4AssertDumpOngoing) { + if (fgKeepPrintCoreDump) + DBGLOG(INIT, INFO, + "[DUMP_CR4]%s:\n", + prEvent->aucBuffer); + if (!kalStrnCmp(prEvent->aucBuffer, + ";more log added here", + 5)) + fgKeepPrintCoreDump = FALSE; + + if (prAdapter->fgCr4CorDumpFileOpend && + (kalWriteCorDumpFile( + prEvent->aucBuffer, + prEvent->u2PacketLength, + FALSE) != + WLAN_STATUS_SUCCESS)) { + DBGLOG(INIT, INFO, + "kalWriteN9CorDumpFile fail\n"); + } + wlanCorDumpTimerReset(prAdapter, FALSE); + } + } + break; + +#endif + + case EVENT_ID_RDD_SEND_PULSE: + DBGLOG(INIT, INFO, "%s: EVENT_ID_RDD_SEND_PULSE\n", + __func__); + + nicEventRddPulseDump(prAdapter, prEvent->aucBuffer); + break; + + case EVENT_ID_ACCESS_RX_STAT: + case EVENT_ID_ACCESS_REG: + case EVENT_ID_NIC_CAPABILITY: + 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; + } + + /* Reset Chip NoAck flag */ + if (prGlueInfo->prAdapter->fgIsChipNoAck) { + DBGLOG(INIT, WARN, + "Got response from chip, clear NoAck flag!\n"); + WARN_ON(TRUE); + } + prGlueInfo->prAdapter->ucOidTimeoutCount = 0; + prGlueInfo->prAdapter->fgIsChipNoAck = FALSE; + + nicRxReturnRFB(prAdapter, prSwRfb); + } +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb) +{ + struct GLUE_INFO *prGlueInfo; + uint8_t ucSubtype; +#if CFG_SUPPORT_802_11W + /* BOOL fgMfgDrop = FALSE; */ +#endif +#if CFG_WIFI_SW_CIPHER_MISMATCH + struct WLAN_MAC_HEADER *prWlanHeader = NULL; +#endif + ASSERT(prAdapter); + ASSERT(prSwRfb); + + nicRxFillRFB(prAdapter, prSwRfb); + +#if CFG_WIFI_SW_CIPHER_MISMATCH + prWlanHeader = (struct WLAN_MAC_HEADER *) prSwRfb->pvHeader; +#endif + ucSubtype = (*(uint8_t *) (prSwRfb->pvHeader) & + MASK_FC_SUBTYPE) >> OFFSET_OF_FC_SUBTYPE; + +#if CFG_RX_PKTS_DUMP + { + struct WLAN_MAC_MGMT_HEADER *prWlanMgmtHeader; + uint16_t u2TxFrameCtrl; + + u2TxFrameCtrl = (*(uint8_t *) (prSwRfb->pvHeader) & + MASK_FRAME_TYPE); + +#if ((CFG_SUPPORT_802_11AX == 1) && (CFG_SUPPORT_WIFI_SYSDVT == 1)) + if (fgEfuseCtrlAxOn == 1) { + if (RXM_IS_TRIGGER_FRAME(u2TxFrameCtrl)) { + if (prAdapter->fgEnShowHETrigger) { + DBGLOG(NIC, STATE, + "HE Trigger --------------\n"); + dumpMemory8((uint8_t *)prSwRfb->prRxStatus, + prSwRfb->u2RxByteCount); + DBGLOG(NIC, STATE, + "HE Trigger end --------------\n"); + } + nicRxReturnRFB(prAdapter, prSwRfb); + return; + } + } +#endif /* CFG_SUPPORT_802_11AX == 1 */ + + if (prAdapter->rRxCtrl.u4RxPktsDumpTypeMask & BIT( + HIF_RX_PKT_TYPE_MANAGEMENT)) { + if (u2TxFrameCtrl == MAC_FRAME_BEACON + || u2TxFrameCtrl == MAC_FRAME_PROBE_RSP) { + + prWlanMgmtHeader = + (struct WLAN_MAC_MGMT_HEADER *) ( + prSwRfb->pvHeader); + + DBGLOG(SW4, INFO, + "QM RX MGT: net %u sta idx %u wlan idx %u ssn %u ptype %u subtype %u 11 %u\n", + prSwRfb->prStaRec->ucBssIndex, + prSwRfb->ucStaRecIdx, + prSwRfb->ucWlanIdx, + prWlanMgmtHeader->u2SeqCtrl, + /* The new SN of the frame */ + prSwRfb->ucPacketType, ucSubtype); + /* HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr))); */ + + DBGLOG_MEM8(SW4, TRACE, + (uint8_t *) prSwRfb->pvHeader, + prSwRfb->u2PacketLen); + } + } + } +#endif +#if CFG_SUPPORT_802_11W + if (prSwRfb->fgIcvErr) { + if (prSwRfb->ucSecMode == CIPHER_SUITE_BIP) + DBGLOG(RSN, INFO, "[MFP] RX with BIP ICV ERROR\n"); + else + DBGLOG(RSN, INFO, "[MFP] RX with ICV ERROR\n"); + + nicRxReturnRFB(prAdapter, prSwRfb); + RX_INC_CNT(&prAdapter->rRxCtrl, RX_DROP_TOTAL_COUNT); + return; + } +#endif + +#if CFG_WIFI_SW_CIPHER_MISMATCH + if ((rsnCheckBipKeyInstalled(prAdapter, prSwRfb->prStaRec)) + && (prSwRfb->prStaRec->ucStaState == STA_STATE_3) + && (!(prWlanHeader->u2FrameCtrl & MASK_FC_PROTECTED_FRAME)) + && (prSwRfb->fgIsBC == FALSE) + && (prSwRfb->fgIsMC == FALSE)) { + prSwRfb->fgIsCipherMS = TRUE; + } +#endif + + if (prAdapter->fgTestMode == FALSE) { +#if CFG_MGMT_FRAME_HANDLING + prGlueInfo = prAdapter->prGlueInfo; + if ((prGlueInfo == NULL) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(RX, WARN, + "Bypass this mgmt frame without wlanProbe done\n"); + } else 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); +} + +void nicRxProcessMsduReport(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb) +{ + halRxProcessMsduReport(prAdapter, prSwRfb); + + nicRxReturnRFB(prAdapter, prSwRfb); +} + +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG +static void nicRxCheckWakeupReason(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb) +{ + struct RX_DESC_OPS_T *prRxDescOps; + + prRxDescOps = prAdapter->chip_info->prRxDescOps; + if (prRxDescOps->nic_rxd_check_wakeup_reason) + prRxDescOps->nic_rxd_check_wakeup_reason(prAdapter, prSwRfb); + else + DBGLOG(RX, ERROR, + "%s:: no nic_rxd_check_wakeup_reason??\n", + __func__); +} +#endif /* CFG_SUPPORT_WAKEUP_REASON_DEBUG */ + +static void nicRxProcessPacketType( + struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb) +{ + struct RX_CTRL *prRxCtrl; + struct mt66xx_chip_info *prChipInfo; + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + + prRxCtrl = &prAdapter->rRxCtrl; + prChipInfo = prAdapter->chip_info; + switch (prSwRfb->ucPacketType) { + case RX_PKT_TYPE_RX_DATA: + if (HAL_IS_RX_DIRECT(prAdapter) + && HAL_MON_EN(prAdapter)) { + spin_lock_bh(&prGlueInfo->rSpinLock[ + SPIN_LOCK_RX_DIRECT]); + nicRxProcessMonitorPacket( + prAdapter, prSwRfb); + spin_unlock_bh(&prGlueInfo->rSpinLock[ + SPIN_LOCK_RX_DIRECT]); + break; + } else if (HAL_MON_EN(prAdapter)) { + nicRxProcessMonitorPacket( + prAdapter, prSwRfb); + break; + } + if (HAL_IS_RX_DIRECT(prAdapter)) { + spin_lock_bh(&prGlueInfo->rSpinLock[ + SPIN_LOCK_RX_DIRECT]); + nicRxProcessDataPacket( + prAdapter, + prSwRfb); + spin_unlock_bh(&prGlueInfo->rSpinLock[ + SPIN_LOCK_RX_DIRECT]); + } else { + nicRxProcessDataPacket( + prAdapter, + prSwRfb); + } + break; + + case RX_PKT_TYPE_SW_DEFINED: + /* HIF_RX_PKT_TYPE_EVENT */ + if ((NIC_RX_GET_U2_SW_PKT_TYPE( + prSwRfb->prRxStatus) & + prChipInfo->u2RxSwPktBitMap) == + prChipInfo->u2RxSwPktEvent) { + nicRxProcessEventPacket( + prAdapter, + prSwRfb); + } + /* case HIF_RX_PKT_TYPE_MANAGEMENT: */ + else if ((NIC_RX_GET_U2_SW_PKT_TYPE( + prSwRfb->prRxStatus) + & prChipInfo->u2RxSwPktBitMap) + == prChipInfo->u2RxSwPktFrame){ + /* OFLD pkts should go data flow + * 1: EAPOL + * 2: ARP / NS + * 3: TDLS + */ + RX_STATUS_GET( + prChipInfo->prRxDescOps, + prSwRfb->ucOFLD, + get_ofld, + prSwRfb->prRxStatus); + if (prSwRfb->ucOFLD) { + if (HAL_IS_RX_DIRECT(prAdapter)) { + spin_lock_bh(&prGlueInfo->rSpinLock[ + SPIN_LOCK_RX_DIRECT]); + if (HAL_MON_EN(prAdapter)) + nicRxProcessMonitorPacket( + prAdapter, prSwRfb); + else + nicRxProcessDataPacket( + prAdapter, prSwRfb); + spin_unlock_bh(&prGlueInfo->rSpinLock[ + SPIN_LOCK_RX_DIRECT]); + } else { + if (HAL_MON_EN(prAdapter)) + nicRxProcessMonitorPacket( + prAdapter, prSwRfb); + else + nicRxProcessDataPacket( + prAdapter, prSwRfb); + } + } + else + nicRxProcessMgmtPacket( + prAdapter, prSwRfb); + } else { + DBGLOG(RX, ERROR, + "u2PktTYpe(0x%04X) is OUT OF DEF.!!!\n", + NIC_RX_GET_U2_SW_PKT_TYPE( + prSwRfb->prRxStatus)); + DBGLOG_MEM8(RX, ERROR, + prSwRfb->pucRecvBuff, + prSwRfb->u2RxByteCount); + + /*ASSERT(0);*/ + nicRxReturnRFB(prAdapter, + prSwRfb); + RX_INC_CNT(prRxCtrl, + RX_TYPE_ERR_DROP_COUNT); + RX_INC_CNT(prRxCtrl, + RX_DROP_TOTAL_COUNT); + + } + break; + + case RX_PKT_TYPE_MSDU_REPORT: + nicRxProcessMsduReport(prAdapter, + prSwRfb); + break; + + /* case HIF_RX_PKT_TYPE_TX_LOOPBACK: */ + /* case HIF_RX_PKT_TYPE_MANAGEMENT: */ + case RX_PKT_TYPE_TX_STATUS: + case RX_PKT_TYPE_RX_VECTOR: + case RX_PKT_TYPE_TM_REPORT: + default: + nicRxReturnRFB(prAdapter, prSwRfb); + 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; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief nicProcessRFBs is used to process RFBs in the rReceivedRFBList queue. + * + * @param prAdapter Pointer to the Adapter structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicRxProcessRFBs(IN struct ADAPTER *prAdapter) +{ + struct RX_CTRL *prRxCtrl; + struct SW_RFB *prSwRfb = (struct SW_RFB *) NULL; + struct QUE rTempRfbList; + struct QUE *prTempRfbList = &rTempRfbList; + uint32_t u4RxLoopCount, u4Tick; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxProcessRFBs"); + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + prRxCtrl->ucNumIndPacket = 0; + prRxCtrl->ucNumRetainedPacket = 0; + u4RxLoopCount = prAdapter->rWifiVar.u4TxRxLoopCount; + u4Tick = kalGetTimeTick(); + + QUEUE_INITIALIZE(prTempRfbList); + + while (u4RxLoopCount--) { + while (QUEUE_IS_NOT_EMPTY(&prRxCtrl->rReceivedRfbList)) { + + /* check process RFB timeout */ + if ((kalGetTimeTick() - u4Tick) > RX_PROCESS_TIMEOUT) { + DBGLOG(RX, WARN, + "Process RFBs timeout, pending count: %u\n", + prRxCtrl->rReceivedRfbList.u4NumElem); + kalSetRxProcessEvent(prAdapter->prGlueInfo); + break; + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_MOVE_ALL(prTempRfbList, + &prRxCtrl->rReceivedRfbList); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + while (QUEUE_IS_NOT_EMPTY(prTempRfbList)) { + QUEUE_REMOVE_HEAD(prTempRfbList, + prSwRfb, struct SW_RFB *); + + if (!prSwRfb) + break; +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG + if (kalIsWakeupByWlan(prAdapter)) + nicRxCheckWakeupReason(prAdapter, + prSwRfb); +#endif + + /* Too many leading tabs - + * consider code refactoring + */ + nicRxProcessPacketType(prAdapter, prSwRfb); + } + + if (prRxCtrl->ucNumIndPacket > 0) { + RX_ADD_CNT(prRxCtrl, RX_DATA_INDICATION_COUNT, + prRxCtrl->ucNumIndPacket); + RX_ADD_CNT(prRxCtrl, RX_DATA_RETAINED_COUNT, + prRxCtrl->ucNumRetainedPacket); +#if !CFG_SUPPORT_MULTITHREAD +#if CFG_NATIVE_802_11 + kalRxIndicatePkts(prAdapter->prGlueInfo, + (uint32_t) prRxCtrl->ucNumIndPacket, + (uint32_t) + prRxCtrl->ucNumRetainedPacket); +#else + kalRxIndicatePkts(prAdapter->prGlueInfo, + prRxCtrl->apvIndPacket, + (uint32_t) prRxCtrl->ucNumIndPacket); +#endif +#endif + kalPerMonStart(prAdapter->prGlueInfo); + } + } + } +} /* end of nicRxProcessRFBs() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicRxSetupRFB(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + void *pvPacket; + uint8_t *pucRecvBuff; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + if (!prSwRfb->pvPacket) { + kalMemZero(prSwRfb, sizeof(struct SW_RFB)); + pvPacket = kalPacketAlloc(prAdapter->prGlueInfo, + CFG_RX_MAX_PKT_SIZE, &pucRecvBuff); + if (pvPacket == NULL) + return WLAN_STATUS_RESOURCES; + + prSwRfb->pvPacket = pvPacket; + prSwRfb->pucRecvBuff = (void *) pucRecvBuff; + } else { + kalMemZero(((uint8_t *) prSwRfb + OFFSET_OF(struct SW_RFB, + prRxStatus)), + (sizeof(struct SW_RFB) - OFFSET_OF(struct SW_RFB, + prRxStatus))); + } + + prSwRfb->prRxStatus = 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 struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct RX_CTRL *prRxCtrl; + struct QUE_ENTRY *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_FREE_QUE); + + if (prSwRfb->pvPacket) { + /* QUEUE_INSERT_TAIL */ + QUEUE_INSERT_TAIL(&prRxCtrl->rFreeSwRfbList, prQueEntry); + if (prAdapter->u4NoMoreRfb != 0) { + DBGLOG_LIMITED(RX, INFO, + "Free rfb and set IntEvent!!!!!\n"); + kalSetDrvIntEvent(prAdapter->prGlueInfo); + } + } else { + /* QUEUE_INSERT_TAIL */ + QUEUE_INSERT_TAIL(&prRxCtrl->rIndicatedRfbList, prQueEntry); + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + /* Trigger Rx if there are free SwRfb */ + if (halIsPendingRx(prAdapter) + && (prRxCtrl->rFreeSwRfbList.u4NumElem > 0)) + kalSetIntEvent(prAdapter->prGlueInfo); +} /* 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 struct ADAPTER *prAdapter) +{ + ASSERT(prAdapter); + prAdapter->prGlueInfo->IsrRxCnt++; + + if (halIsHifStateSuspend(prAdapter)) { + DBGLOG(RX, WARN, "suspend RX INT\n"); + } + + /* SER break point */ + if (nicSerIsRxStop(prAdapter)) { + /* Skip following Rx handling */ + return; + } + + halProcessRxInterrupt(prAdapter); + +#if CFG_SUPPORT_MULTITHREAD + kalSetRxProcessEvent(prAdapter->prGlueInfo); +#else + nicRxProcessRFBs(prAdapter); +#endif + + 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 struct ADAPTER * + prAdapter, IN const enum ENUM_CSUM_RESULT aeCSUM[]) { + struct RX_CTRL *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)) { + /* count success num */ + RX_INC_CNT(prRxCtrl, RX_CSUM_IP_SUCCESS_COUNT); + } else if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_FAILED) + || (aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_FAILED)) { + RX_INC_CNT(prRxCtrl, RX_CSUM_IP_FAILED_COUNT); + } else if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_NONE) + && (aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_NONE)) { + RX_INC_CNT(prRxCtrl, RX_CSUM_UNKNOWN_L3_PKT_COUNT); + } else { + ASSERT(0); + } + + if (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_SUCCESS) { + /* count success num */ + RX_INC_CNT(prRxCtrl, RX_CSUM_TCP_SUCCESS_COUNT); + } else if (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_FAILED) { + RX_INC_CNT(prRxCtrl, RX_CSUM_TCP_FAILED_COUNT); + } else if (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_SUCCESS) { + RX_INC_CNT(prRxCtrl, RX_CSUM_UDP_SUCCESS_COUNT); + } else if (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_FAILED) { + RX_INC_CNT(prRxCtrl, RX_CSUM_UDP_FAILED_COUNT); + } else if ((aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_NONE) + && (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_NONE)) { + RX_INC_CNT(prRxCtrl, RX_CSUM_UNKNOWN_L4_PKT_COUNT); + } else { + ASSERT(0); + } + +} /* end of nicRxUpdateCSUMStatistics() */ +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is used to query current status of RX Module. + * + * @param prAdapter Pointer to the Adapter structure. + * @param pucBuffer Pointer to the message buffer. + * @param pu4Count Pointer to the buffer of message length count. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicRxQueryStatus(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuffer, OUT uint32_t *pu4Count) +{ + struct RX_CTRL *prRxCtrl; + uint8_t *pucCurrBuf = pucBuffer; + uint32_t u4CurrCount; + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + ASSERT(pu4Count); + +#define SPRINTF_RX_QSTATUS(arg) \ + { \ + u4CurrCount = \ + kalScnprintf(pucCurrBuf, *pu4Count, PRINTF_ARG arg); \ + pucCurrBuf += (uint8_t)u4CurrCount; \ + *pu4Count -= u4CurrCount; \ + } + + + SPRINTF_RX_QSTATUS(("\n\nRX CTRL STATUS:")); + SPRINTF_RX_QSTATUS(("\n===============")); + SPRINTF_RX_QSTATUS(("\nFREE RFB w/i BUF LIST :%9u", + prRxCtrl->rFreeSwRfbList.u4NumElem)); + SPRINTF_RX_QSTATUS(("\nFREE RFB w/o BUF LIST :%9u", + prRxCtrl->rIndicatedRfbList.u4NumElem)); + SPRINTF_RX_QSTATUS(("\nRECEIVED RFB LIST :%9u", + prRxCtrl->rReceivedRfbList.u4NumElem)); + + SPRINTF_RX_QSTATUS(("\n\n")); + + /* *pu4Count = (UINT_32)((UINT_32)pucCurrBuf - (UINT_32)pucBuffer); */ + +} /* end of nicRxQueryStatus() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Clear RX related counters + * + * @param prAdapter Pointer of Adapter Data Structure + * + * @return - (none) + */ +/*----------------------------------------------------------------------------*/ +void nicRxClearStatistics(IN struct ADAPTER *prAdapter) +{ + struct RX_CTRL *prRxCtrl; + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + RX_RESET_ALL_CNTS(prRxCtrl); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is used to query current statistics of RX Module. + * + * @param prAdapter Pointer to the Adapter structure. + * @param pucBuffer Pointer to the message buffer. + * @param pu4Count Pointer to the buffer of message length count. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicRxQueryStatistics(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuffer, OUT uint32_t *pu4Count) +{ + struct RX_CTRL *prRxCtrl; + uint8_t *pucCurrBuf = pucBuffer; + uint32_t u4CurrCount; + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + ASSERT(pu4Count); + +#define SPRINTF_RX_COUNTER(eCounter) \ + { \ + u4CurrCount = kalScnprintf(pucCurrBuf, *pu4Count, \ + "%-30s : %u\n", #eCounter, \ + (uint32_t)prRxCtrl->au8Statistics[eCounter]); \ + pucCurrBuf += (uint8_t)u4CurrCount; \ + *pu4Count -= u4CurrCount; \ + } + + SPRINTF_RX_COUNTER(RX_MPDU_TOTAL_COUNT); + SPRINTF_RX_COUNTER(RX_SIZE_ERR_DROP_COUNT); + SPRINTF_RX_COUNTER(RX_DATA_INDICATION_COUNT); + SPRINTF_RX_COUNTER(RX_DATA_RETURNED_COUNT); + SPRINTF_RX_COUNTER(RX_DATA_RETAINED_COUNT); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD || CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 + SPRINTF_RX_COUNTER(RX_CSUM_TCP_FAILED_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_UDP_FAILED_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_IP_FAILED_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_TCP_SUCCESS_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_UDP_SUCCESS_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_IP_SUCCESS_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_UNKNOWN_L4_PKT_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_UNKNOWN_L3_PKT_COUNT); + SPRINTF_RX_COUNTER(RX_IP_V6_PKT_CCOUNT); +#endif + + /* *pu4Count = (UINT_32)(pucCurrBuf - pucBuffer); */ + + nicRxClearStatistics(prAdapter); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Read the Response data from data port + * + * @param prAdapter pointer to the Adapter handler + * @param pucRspBuffer pointer to the Response buffer + * + * @retval WLAN_STATUS_SUCCESS: Response packet has been read + * @retval WLAN_STATUS_FAILURE: Read Response packet timeout or error occurred + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t +nicRxWaitResponse(IN struct ADAPTER *prAdapter, + IN uint8_t ucPortIdx, OUT uint8_t *pucRspBuffer, + IN uint32_t u4MaxRespBufferLen, OUT uint32_t *pu4Length) { + struct mt66xx_chip_info *prChipInfo; + struct WIFI_EVENT *prEvent; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + u4Status = halRxWaitResponse(prAdapter, ucPortIdx, + pucRspBuffer, + u4MaxRespBufferLen, pu4Length); + if (u4Status == WLAN_STATUS_SUCCESS) { + DBGLOG(RX, TRACE, + "Dump Response buffer, length = %u\n", *pu4Length); + DBGLOG_MEM8(RX, TRACE, pucRspBuffer, *pu4Length); + + prEvent = (struct WIFI_EVENT *) + (pucRspBuffer + prChipInfo->rxd_size); + + DBGLOG(INIT, TRACE, + "RX EVENT: ID[0x%02X] SEQ[%u] LEN[%u]\n", + prEvent->ucEID, prEvent->ucSeqNum, + prEvent->u2PacketLength); + } else { + prAdapter->u4HifDbgFlag |= DEG_HIF_DEFAULT_DUMP; + halPrintHifDbgInfo(prAdapter); + DBGLOG(RX, ERROR, "halRxWaitResponse fail!status %X\n", + u4Status); + } + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Set filter to enable Promiscuous Mode + * + * @param prAdapter Pointer to the Adapter structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicRxEnablePromiscuousMode(IN struct ADAPTER * + prAdapter) { + ASSERT(prAdapter); + +} /* end of nicRxEnablePromiscuousMode() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Set filter to disable Promiscuous Mode + * + * @param prAdapter Pointer to the Adapter structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicRxDisablePromiscuousMode(IN struct ADAPTER * + prAdapter) { + ASSERT(prAdapter); + +} /* end of nicRxDisablePromiscuousMode() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief this function flushes all packets queued in reordering module + * + * @param prAdapter Pointer to the Adapter structure. + * + * @retval WLAN_STATUS_SUCCESS Flushed successfully + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicRxFlush(IN struct ADAPTER *prAdapter) +{ + struct SW_RFB *prSwRfb; + + ASSERT(prAdapter); + prSwRfb = qmFlushRxQueues(prAdapter); + if (prSwRfb != NULL) { + do { + struct SW_RFB *prNextSwRfb; + + /* save next first */ + prNextSwRfb = (struct SW_RFB *) QUEUE_GET_NEXT_ENTRY(( + struct QUE_ENTRY *) prSwRfb); + + /* free */ + nicRxReturnRFB(prAdapter, prSwRfb); + + prSwRfb = prNextSwRfb; + } while (prSwRfb); + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param + * + * @retval + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicRxProcessActionFrame(IN struct ADAPTER * + prAdapter, IN struct SW_RFB *prSwRfb) { + struct WLAN_ACTION_FRAME *prActFrame; + struct BSS_INFO *prBssInfo = NULL; +#if CFG_SUPPORT_802_11W + u_int8_t fgRobustAction = FALSE; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecBssInfo; +#endif + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + DBGLOG(RSN, TRACE, "[Rx] nicRxProcessActionFrame\n"); + + if (prSwRfb->u2PacketLen < sizeof(struct WLAN_ACTION_FRAME) + - 1) + return WLAN_STATUS_INVALID_PACKET; + prActFrame = (struct WLAN_ACTION_FRAME *) prSwRfb->pvHeader; + + DBGLOG(RSN, TRACE, "Action frame category=%d\n", + prActFrame->ucCategory); + +#if CFG_SUPPORT_802_11W + /* DBGLOG(RSN, TRACE, ("[Rx] fgRobustAction=%d\n", fgRobustAction)); */ + fgRobustAction = secIsRobustActionFrame(prAdapter, prSwRfb->pvHeader); + if (fgRobustAction && prSwRfb->prStaRec && + GET_BSS_INFO_BY_INDEX(prAdapter, + prSwRfb->prStaRec->ucBssIndex)->eNetworkType == + NETWORK_TYPE_AIS) { + prAisSpecBssInfo = + aisGetAisSpecBssInfo(prAdapter, + prSwRfb->prStaRec->ucBssIndex); + + DBGLOG(RSN, INFO, + "[Rx]RobustAction %x %x\n", + prSwRfb->ucWlanIdx, + prSwRfb->ucSecMode); + + if (prAisSpecBssInfo->fgMgmtProtection + && (!(prActFrame->u2FrameCtrl & MASK_FC_PROTECTED_FRAME) +#if CFG_WIFI_SW_CIPHER_MISMATCH + && (prSwRfb->fgIsCipherMS))) { +#else + && (prSwRfb->ucSecMode == CIPHER_SUITE_CCMP))) { +#endif + DBGLOG(RSN, INFO, + "[MFP] Not handle and drop un-protected robust action frame!!\n"); + return WLAN_STATUS_INVALID_PACKET; + } + } +#endif + + if (prSwRfb->prStaRec) + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prSwRfb->prStaRec->ucBssIndex); + + switch (prActFrame->ucCategory) { +#if CFG_M0VE_BA_TO_DRIVER + case CATEGORY_BLOCK_ACK_ACTION: + DBGLOG(RX, WARN, + "[Puff][%s] Rx CATEGORY_BLOCK_ACK_ACTION\n", __func__); + + if (prSwRfb->prStaRec) + mqmHandleBaActionFrame(prAdapter, prSwRfb); + + break; +#endif +#if DSCP_SUPPORT + case CATEGORY_QOS_ACTION: + DBGLOG(RX, INFO, "received dscp action frame: %d\n", + __LINE__); + handleQosMapConf(prAdapter, prSwRfb); + break; +#endif + case CATEGORY_PUBLIC_ACTION: + aisFuncValidateRxActionFrame(prAdapter, prSwRfb); +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { + rlmProcessPublicAction(prAdapter, prSwRfb); + if (prBssInfo) + p2pFuncValidateRxActionFrame(prAdapter, prSwRfb, + (prBssInfo->ucBssIndex == + prAdapter->ucP2PDevBssIdx), + (uint8_t) prBssInfo->u4PrivateData); + else + p2pFuncValidateRxActionFrame(prAdapter, + prSwRfb, TRUE, 0); + } +#endif + break; + + case CATEGORY_HT_ACTION: + rlmProcessHtAction(prAdapter, prSwRfb); + break; + case CATEGORY_VENDOR_SPECIFIC_ACTION: +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { + if (prBssInfo) + p2pFuncValidateRxActionFrame(prAdapter, prSwRfb, + (prBssInfo->ucBssIndex == + prAdapter->ucP2PDevBssIdx), + (uint8_t) prBssInfo->u4PrivateData); + else + p2pFuncValidateRxActionFrame(prAdapter, + prSwRfb, TRUE, 0); + } +#endif +#if CFG_SUPPORT_NCHO + if (prBssInfo && prBssInfo->eNetworkType == NETWORK_TYPE_AIS) { + if (prAdapter->rNchoInfo.fgNCHOEnabled == TRUE + && prAdapter->rNchoInfo.u4WesMode == TRUE) { + aisFuncValidateRxActionFrame(prAdapter, + prSwRfb); + DBGLOG(INIT, INFO, + "NCHO CATEGORY_VENDOR_SPECIFIC_ACTION\n"); + } + } +#endif + break; +#if CFG_SUPPORT_802_11W + case CATEGORY_SA_QUERY_ACTION: { + struct BSS_INFO *prBssInfo; + + if (prSwRfb->prStaRec) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prSwRfb->prStaRec->ucBssIndex); + ASSERT(prBssInfo); + if ((prBssInfo->eNetworkType == NETWORK_TYPE_AIS) && + aisGetAisSpecBssInfo(prAdapter, + prSwRfb->prStaRec->ucBssIndex)-> + fgMgmtProtection /* Use MFP */) { + /* MFP test plan 5.3.3.4 */ + rsnSaQueryAction(prAdapter, prSwRfb); + } else if ((prBssInfo->eNetworkType == + NETWORK_TYPE_P2P) && + (prBssInfo->eCurrentOPMode == + OP_MODE_ACCESS_POINT)) { + /* AP PMF */ + DBGLOG(RSN, INFO, + "[Rx] nicRx AP PMF SAQ action\n"); + if (rsnCheckBipKeyInstalled(prAdapter, + prSwRfb->prStaRec)) { + /* MFP test plan 4.3.3.4 */ + rsnApSaQueryAction(prAdapter, prSwRfb); + } + } + } + } + break; +#endif + case CATEGORY_WNM_ACTION: { + if (prSwRfb->prStaRec && + GET_BSS_INFO_BY_INDEX(prAdapter, + prSwRfb->prStaRec->ucBssIndex) + ->eNetworkType == NETWORK_TYPE_AIS) { + DBGLOG(RX, INFO, "WNM action frame: %d\n", __LINE__); + wnmWNMAction(prAdapter, prSwRfb); + } else + DBGLOG(RX, INFO, "WNM action frame: %d\n", __LINE__); + } + break; + +#if CFG_SUPPORT_DFS + case CATEGORY_SPEC_MGT: { + if (prAdapter->fgEnable5GBand) { + DBGLOG(RLM, INFO, + "[Channel Switch]nicRxProcessActionFrame\n"); + rlmProcessSpecMgtAction(prAdapter, prSwRfb); + } + } + break; +#endif + +#if CFG_SUPPORT_802_11AC + case CATEGORY_VHT_ACTION: + rlmProcessVhtAction(prAdapter, prSwRfb); + break; +#endif + +#if (CFG_SUPPORT_TWT == 1) + case CATEGORY_S1G_ACTION: + twtProcessS1GAction(prAdapter, prSwRfb); + break; +#endif + +#if CFG_SUPPORT_802_11K + case CATEGORY_RM_ACTION: + switch (prActFrame->ucAction) { + case RM_ACTION_RM_REQUEST: +#if CFG_SUPPORT_RM_BEACON_REPORT_BY_SUPPLICANT + /* handle RM beacon request by supplicant */ + if (prAdapter->prAisBssInfo && + prSwRfb->prStaRec + && prSwRfb->prStaRec->ucBssIndex == + prAdapter->prAisBssInfo->ucBssIndex) + aisFuncValidateRxActionFrame(prAdapter, + prSwRfb); +#else + rrmProcessRadioMeasurementRequest(prAdapter, prSwRfb); +#endif + break; + case RM_ACTION_REIGHBOR_RESPONSE: + rrmProcessNeighborReportResonse(prAdapter, prActFrame, + prSwRfb); + break; + } + break; +#endif + case CATEGORY_WME_MGT_NOTIFICATION: + wmmParseQosAction(prAdapter, prSwRfb); + break; + default: + break; + } /* end of switch case */ + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param + * + * @retval + */ +/*----------------------------------------------------------------------------*/ +uint8_t nicRxGetRcpiValueFromRxv( + IN struct ADAPTER *prAdapter, + IN uint8_t ucRcpiMode, + IN struct SW_RFB *prSwRfb) +{ + struct mt66xx_chip_info *prChipInfo; + + prChipInfo = prAdapter->chip_info; + if (prChipInfo->asicRxGetRcpiValueFromRxv) + return prChipInfo->asicRxGetRcpiValueFromRxv( + ucRcpiMode, prSwRfb); + else { + DBGLOG(RX, ERROR, "%s: no asicRxGetRcpiValueFromRxv ??\n", + __func__); + return 0; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param + * + * @retval + */ +/*----------------------------------------------------------------------------*/ +int32_t nicRxGetLastRxRssi(struct ADAPTER *prAdapter, IN char *pcCommand, + IN int i4TotalLen, IN uint8_t ucWlanIdx) +{ + int32_t i4RSSI0 = 0, i4RSSI1 = 0, i4RSSI2 = 0, i4RSSI3 = 0; + int32_t i4BytesWritten = 0; + uint32_t u4RxVector3 = 0; + uint8_t ucStaIdx; + struct CHIP_DBG_OPS *prChipDbg; + + if (wlanGetStaIdxByWlanIdx(prAdapter, ucWlanIdx, &ucStaIdx) == + WLAN_STATUS_SUCCESS) { + u4RxVector3 = prAdapter->arStaRec[ucStaIdx].u4RxVector3; + DBGLOG(REQ, LOUD, "****** RX Vector3 = 0x%08x ******\n", + u4RxVector3); + } else { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s", "Last RX RSSI", " = NOT SUPPORT"); + return i4BytesWritten; + } + + prChipDbg = prAdapter->chip_info->prDebugOps; + + if (prChipDbg && prChipDbg->show_rx_rssi_info) { + i4BytesWritten = prChipDbg->show_rx_rssi_info( + prAdapter, + pcCommand, + i4TotalLen, + ucStaIdx); + return i4BytesWritten; + } + + i4RSSI0 = RCPI_TO_dBm((u4RxVector3 & RX_VT_RCPI0_MASK) >> + RX_VT_RCPI0_OFFSET); + i4RSSI1 = RCPI_TO_dBm((u4RxVector3 & RX_VT_RCPI1_MASK) >> + RX_VT_RCPI1_OFFSET); + + if (prAdapter->rWifiVar.ucNSS > 2) { + i4RSSI2 = RCPI_TO_dBm((u4RxVector3 & RX_VT_RCPI2_MASK) >> + RX_VT_RCPI2_OFFSET); + i4RSSI3 = RCPI_TO_dBm((u4RxVector3 & RX_VT_RCPI3_MASK) >> + RX_VT_RCPI3_OFFSET); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%-20s%s%d %d %d %d\n", + "Last RX Data RSSI", " = ", + i4RSSI0, i4RSSI1, i4RSSI2, i4RSSI3); + } else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%-20s%s%d %d\n", + "Last RX Data RSSI", " = ", i4RSSI0, i4RSSI1); + + return i4BytesWritten; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_rxd_v1.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_rxd_v1.c new file mode 100644 index 0000000000000..b5e5024ad9984 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_rxd_v1.c @@ -0,0 +1,568 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_tx.c#2 + */ + +/*! \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. + */ + + +/******************************************************************************* + * C O M P I L E 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 + ******************************************************************************* + */ + +uint16_t nic_rxd_v1_get_rx_byte_count( + void *prRxStatus) +{ + return HAL_RX_STATUS_GET_RX_BYTE_CNT( + (struct HW_MAC_RX_DESC *)prRxStatus); +} + +uint8_t nic_rxd_v1_get_packet_type( + void *prRxStatus) +{ + return HAL_RX_STATUS_GET_PKT_TYPE( + (struct HW_MAC_RX_DESC *)prRxStatus); +} + +uint8_t nic_rxd_v1_get_wlan_idx( + void *prRxStatus) +{ + return HAL_RX_STATUS_GET_WLAN_IDX( + (struct HW_MAC_RX_DESC *)prRxStatus); +} + +uint8_t nic_rxd_v1_get_sec_mode( + void *prRxStatus) +{ + return HAL_RX_STATUS_GET_SEC_MODE( + (struct HW_MAC_RX_DESC *)prRxStatus); +} + +uint8_t nic_rxd_v1_get_sw_class_error_bit( + void *prRxStatus) +{ + struct HW_MAC_RX_DESC *prRxD; + + prRxD = (struct HW_MAC_RX_DESC *)prRxStatus; + + if ((prRxD->u2StatusFlag & RXS_DW2_RX_CLASSERR_BITMAP) + == RXS_DW2_RX_CLASSERR_VALUE) { + DBGLOG(RSN, ERROR, + "RX_CLASSERR: StatusFlag=0x%x\n", + prRxD->u2StatusFlag); + return TRUE; + } else + return FALSE; +} + +uint8_t nic_rxd_v1_get_ch_num( + void *prRxStatus) +{ + return HAL_RX_STATUS_GET_CHNL_NUM( + (struct HW_MAC_RX_DESC *)prRxStatus); +} + +uint8_t nic_rxd_v1_get_rf_band( + void *prRxStatus) +{ + return HAL_RX_STATUS_GET_RF_BAND( + (struct HW_MAC_RX_DESC *)prRxStatus); +} + +uint8_t nic_rxd_v1_get_tcl( + void *prRxStatus) +{ + return HAL_RX_STATUS_GET_TCL( + (struct HW_MAC_RX_DESC *)prRxStatus); +} + +uint8_t nic_rxd_v1_get_ofld( + void *prRxStatus) +{ + return HAL_RX_STATUS_GET_OFLD( + (struct HW_MAC_RX_DESC *)prRxStatus); +} +/*----------------------------------------------------------------------------*/ +/*! + * @brief Fill RFB + * + * @param prAdapter pointer to the Adapter handler + * @param prSWRfb specify the RFB to receive rx data + * + * @return (none) + * + */ +/*----------------------------------------------------------------------------*/ +void nic_rxd_v1_fill_rfb( + struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb) +{ + struct mt66xx_chip_info *prChipInfo; + struct HW_MAC_RX_DESC *prRxStatus; + + uint32_t u4PktLen = 0; + /* UINT_32 u4MacHeaderLen; */ + uint32_t u4HeaderOffset; + uint16_t u2RxStatusOffset; + + DEBUGFUNC("nicRxFillRFB"); + + prChipInfo = prAdapter->chip_info; + prRxStatus = prSwRfb->prRxStatus; + + u4PktLen = (uint32_t) HAL_RX_STATUS_GET_RX_BYTE_CNT( + prRxStatus); + u4HeaderOffset = (uint32_t) ( + HAL_RX_STATUS_GET_HEADER_OFFSET(prRxStatus)); + + u2RxStatusOffset = prChipInfo->rxd_size; + prSwRfb->ucGroupVLD = (uint8_t) HAL_RX_STATUS_GET_GROUP_VLD( + prRxStatus); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_4)) { + prSwRfb->prRxStatusGroup4 = (struct HW_MAC_RX_STS_GROUP_4 *) + ((uint8_t *) prRxStatus + u2RxStatusOffset); + u2RxStatusOffset += sizeof(struct HW_MAC_RX_STS_GROUP_4); + + } + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_1)) { + prSwRfb->prRxStatusGroup1 = (struct HW_MAC_RX_STS_GROUP_1 *) + ((uint8_t *) prRxStatus + u2RxStatusOffset); + u2RxStatusOffset += sizeof(struct HW_MAC_RX_STS_GROUP_1); + + } + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_2)) { + prSwRfb->prRxStatusGroup2 = (struct HW_MAC_RX_STS_GROUP_2 *) + ((uint8_t *) prRxStatus + u2RxStatusOffset); + u2RxStatusOffset += sizeof(struct HW_MAC_RX_STS_GROUP_2); + + } + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_3)) { + prSwRfb->prRxStatusGroup3 = (struct HW_MAC_RX_STS_GROUP_3 *) + ((uint8_t *) prRxStatus + u2RxStatusOffset); + u2RxStatusOffset += sizeof(struct HW_MAC_RX_STS_GROUP_3); + } + + prSwRfb->u2RxStatusOffst = u2RxStatusOffset; + prSwRfb->pvHeader = (uint8_t *) prRxStatus + + u2RxStatusOffset + u4HeaderOffset; + prSwRfb->u2RxByteCount = u4PktLen; + prSwRfb->u2PacketLen = (uint16_t) (u4PktLen - + (u2RxStatusOffset + u4HeaderOffset)); + prSwRfb->u2HeaderLen = (uint16_t) + HAL_RX_STATUS_GET_HEADER_LEN(prRxStatus); + prSwRfb->ucWlanIdx = (uint8_t) HAL_RX_STATUS_GET_WLAN_IDX( + prRxStatus); + prSwRfb->ucStaRecIdx = secGetStaIdxByWlanIdx(prAdapter, + (uint8_t) HAL_RX_STATUS_GET_WLAN_IDX(prRxStatus)); + prSwRfb->prStaRec = cnmGetStaRecByIndex(prAdapter, + prSwRfb->ucStaRecIdx); + prSwRfb->ucTid = (uint8_t) HAL_RX_STATUS_GET_TID( + prRxStatus); + prSwRfb->fgHdrTran = HAL_RX_STATUS_IS_HEADER_TRAN(prRxStatus); + prSwRfb->ucPayloadFormat = HAL_RX_STATUS_GET_PAYLOAD_FORMAT(prRxStatus); + prSwRfb->fgIcvErr = HAL_RX_STATUS_IS_ICV_ERROR(prRxStatus); + prSwRfb->ucSecMode = HAL_RX_STATUS_GET_SEC_MODE(prRxStatus); + prSwRfb->ucOFLD = HAL_RX_STATUS_GET_OFLD(prRxStatus); + prSwRfb->fgIsBC = HAL_RX_STATUS_IS_BC(prRxStatus); + prSwRfb->fgIsMC = HAL_RX_STATUS_IS_MC(prRxStatus); + prSwRfb->fgIsCipherMS = HAL_RX_STATUS_IS_CIPHER_MISMATCH(prRxStatus); + prSwRfb->fgIsCipherLenMS = HAL_RX_STATUS_IS_CLM_ERROR(prRxStatus); + prSwRfb->ucKeyID = HAL_RX_STATUS_GET_KEY_ID(prRxStatus); + prSwRfb->fgIsFrag = HAL_RX_STATUS_IS_FRAG(prRxStatus); + prSwRfb->fgIsFCS = HAL_RX_STATUS_IS_FCS_ERROR(prRxStatus); + prSwRfb->fgIsAmpdu = HAL_RX_STATUS_IS_AMPDU_FORMAT(prRxStatus); + prSwRfb->ucRxvSeqNo = HAL_RX_STATUS_GET_RXV_SEQ_NO(prRxStatus); + prSwRfb->ucChnlNum = HAL_RX_STATUS_GET_CHNL_NUM(prRxStatus); + +#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 = (uint8_t) ((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 +} + +u_int8_t nic_rxd_v1_sanity_check( + struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb) +{ + struct mt66xx_chip_info *prChipInfo; + struct HW_MAC_RX_DESC *prRxStatus; + u_int8_t fgDrop = FALSE; + + prChipInfo = prAdapter->chip_info; + prRxStatus = (struct HW_MAC_RX_DESC *)prSwRfb->prRxStatus; + /* BA session */ + if ((prRxStatus->u2StatusFlag & RXS_DW2_AMPDU_nERR_BITMAP) + == RXS_DW2_AMPDU_nERR_VALUE) + prSwRfb->fgReorderBuffer = TRUE; + /* non BA session */ + else if ((prRxStatus->u2StatusFlag & RXS_DW2_RX_nERR_BITMAP) + == RXS_DW2_RX_nERR_VALUE) { + if ((prRxStatus->u2StatusFlag & RXS_DW2_RX_nDATA_BITMAP) == + RXS_DW2_RX_nDATA_VALUE) + prSwRfb->fgDataFrame = FALSE; + + if ((prRxStatus->u2StatusFlag & RXS_DW2_RX_FRAG_BITMAP) == + RXS_DW2_RX_FRAG_VALUE) + prSwRfb->fgFragFrame = TRUE; + + } else { + fgDrop = TRUE; + if (!HAL_RX_STATUS_IS_ICV_ERROR(prRxStatus) + && HAL_RX_STATUS_IS_TKIP_MIC_ERROR(prRxStatus)) { + uint8_t ucBssIndex = + secGetBssIdxByWlanIdx(prAdapter, + HAL_RX_STATUS_GET_WLAN_IDX(prRxStatus)); + struct STA_RECORD *prStaRec = NULL; + struct PARAM_BSSID_EX *prCurrBssid = + aisGetCurrBssId(prAdapter, + ucBssIndex); + + if (prCurrBssid) + prStaRec = cnmGetStaRecByAddress(prAdapter, + ucBssIndex, + prCurrBssid->arMacAddress); + if (prStaRec) { + DBGLOG(RSN, EVENT, "MIC_ERR_PKT\n"); + rsnTkipHandleMICFailure(prAdapter, prStaRec, 0); + } + } +#if UNIFIED_MAC_RX_FORMAT + else if (HAL_RX_STATUS_IS_LLC_MIS(prRxStatus) + && !HAL_RX_STATUS_IS_ERROR(prRxStatus) + && !FEAT_SUP_LLC_VLAN_RX(prChipInfo)) { + uint16_t *pu2EtherType; + + nicRxFillRFB(prAdapter, prSwRfb); + + pu2EtherType = (uint16_t *) + ((uint8_t *)prSwRfb->pvHeader + + 2 * MAC_ADDR_LEN); + + /* If ethernet type is VLAN, do not drop it. + * Pass up to driver process + */ + if (prSwRfb->u2HeaderLen >= ETH_HLEN + && *pu2EtherType == NTOHS(ETH_P_VLAN)) + fgDrop = FALSE; + } +#else + else if (HAL_RX_STATUS_IS_LLC_MIS(prRxStatus)) { + DBGLOG(RSN, EVENT, ("LLC_MIS_ERR\n")); + fgDrop = TRUE; /* Drop after send de-auth */ + } +#endif + } + + /* Drop plain text during security connection */ + if (prSwRfb->fgIsCipherMS && prSwRfb->fgDataFrame == TRUE) { + uint16_t *pu2EtherType; + + pu2EtherType = (uint16_t *) + ((uint8_t *)prSwRfb->pvHeader + + 2 * MAC_ADDR_LEN); + if (prSwRfb->u2HeaderLen >= ETH_HLEN + && (*pu2EtherType == NTOHS(ETH_P_1X) +#if CFG_SUPPORT_WAPI + || (*pu2EtherType == NTOHS(ETH_WPI_1X)) +#endif + )) { + fgDrop = FALSE; + DBGLOG(RSN, INFO, + "Don't drop eapol or wpi packet\n"); + } else { + fgDrop = TRUE; + DBGLOG(RSN, INFO, + "Drop plain text during security connection\n"); + } + } + + return fgDrop; +} + +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG +void nic_rxd_v1_check_wakeup_reason( + struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb) +{ + struct mt66xx_chip_info *prChipInfo; + struct WIFI_EVENT *prEvent; + uint8_t *pvHeader = NULL; + struct HW_MAC_RX_DESC *prRxStatus; + uint16_t u2PktLen = 0; + uint32_t u4HeaderOffset; + + prChipInfo = prAdapter->chip_info; + + prRxStatus = (struct HW_MAC_RX_DESC *)prSwRfb->prRxStatus; + if (!prRxStatus) + return; + + prSwRfb->ucGroupVLD = (uint8_t) HAL_RX_STATUS_GET_GROUP_VLD(prRxStatus); + + switch (prSwRfb->ucPacketType) { + case RX_PKT_TYPE_RX_DATA: + { + uint16_t u2Temp = 0; + + u2PktLen = HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus); + u4HeaderOffset = (uint32_t) + (HAL_RX_STATUS_GET_HEADER_OFFSET(prRxStatus)); + u2Temp = prChipInfo->rxd_size; + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_4)) + u2Temp += sizeof(struct HW_MAC_RX_STS_GROUP_4); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_1)) + u2Temp += sizeof(struct HW_MAC_RX_STS_GROUP_1); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_2)) + u2Temp += sizeof(struct HW_MAC_RX_STS_GROUP_2); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_3)) + u2Temp += sizeof(struct HW_MAC_RX_STS_GROUP_3); + pvHeader = (uint8_t *)prRxStatus + u2Temp + u4HeaderOffset; + u2PktLen -= u2Temp + u4HeaderOffset; + if (!pvHeader) { + DBGLOG(RX, ERROR, + "data packet but pvHeader is NULL!\n"); + break; + } + if ((prRxStatus->u2StatusFlag & (RXS_DW2_RX_nERR_BITMAP | + RXS_DW2_RX_nDATA_BITMAP)) == RXS_DW2_RX_nDATA_VALUE) { + struct WLAN_MAC_HEADER *prWlanMacHeader = + (struct WLAN_MAC_HEADER *)pvHeader; + + if ((prWlanMacHeader->u2FrameCtrl & MASK_FRAME_TYPE) == + MAC_FRAME_BLOCK_ACK_REQ) { + DBGLOG(RX, INFO, + "BAR frame[SSN:%d,TID:%d] wakeup host\n" + , prSwRfb->u2SSN, prSwRfb->ucTid); + break; + } + } + u2Temp = (pvHeader[ETH_TYPE_LEN_OFFSET] << 8) | + (pvHeader[ETH_TYPE_LEN_OFFSET + 1]); + + switch (u2Temp) { + case ETH_P_IPV4: + u2Temp = *(uint16_t *) &pvHeader[ETH_HLEN + 4]; + DBGLOG(RX, INFO, + "IP Packet from:%d.%d.%d.%d,", + pvHeader[ETH_HLEN + 12], + pvHeader[ETH_HLEN + 13], + pvHeader[ETH_HLEN + 14], + pvHeader[ETH_HLEN + 15]); + DBGLOG(RX, INFO, + " IP ID 0x%04x wakeup host\n", + u2Temp); + break; + case ETH_P_ARP: + break; + case ETH_P_1X: + case ETH_P_PRE_1X: +#if CFG_SUPPORT_WAPI + case ETH_WPI_1X: +#endif + case ETH_P_AARP: + case ETH_P_IPV6: + case ETH_P_IPX: + case 0x8100: /* VLAN */ + case 0x890d: /* TDLS */ + DBGLOG(RX, INFO, + "Data Packet, EthType 0x%04x wakeup host\n", + u2Temp); + break; + default: + DBGLOG(RX, WARN, + "abnormal packet, EthType 0x%04x wakeup host\n", + u2Temp); + DBGLOG_MEM8(RX, INFO, + pvHeader, u2PktLen > 50 ? 50:u2PktLen); + break; + } + break; + } + case RX_PKT_TYPE_SW_DEFINED: + /* HIF_RX_PKT_TYPE_EVENT */ + if ((NIC_RX_GET_U2_SW_PKT_TYPE(prSwRfb->prRxStatus) & + RXM_RXD_PKT_TYPE_SW_BITMAP) == + RXM_RXD_PKT_TYPE_SW_EVENT) { + + prEvent = (struct WIFI_EVENT *) + (prSwRfb->pucRecvBuff + prChipInfo->rxd_size); + + DBGLOG(RX, INFO, "Event 0x%02x wakeup host\n", + prEvent->ucEID); + break; + + } + /* case HIF_RX_PKT_TYPE_MANAGEMENT: */ + else if ((NIC_RX_GET_U2_SW_PKT_TYPE(prSwRfb->prRxStatus) & + RXM_RXD_PKT_TYPE_SW_BITMAP) == + RXM_RXD_PKT_TYPE_SW_FRAME) { + uint8_t ucSubtype; + struct WLAN_MAC_MGMT_HEADER *prWlanMgmtHeader; + uint16_t u2Temp = prChipInfo->rxd_size; + + u4HeaderOffset = (uint32_t) + (HAL_RX_STATUS_GET_HEADER_OFFSET(prRxStatus)); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_4)) + u2Temp += sizeof(struct HW_MAC_RX_STS_GROUP_4); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_1)) + u2Temp += sizeof(struct HW_MAC_RX_STS_GROUP_1); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_2)) + u2Temp += sizeof(struct HW_MAC_RX_STS_GROUP_2); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_3)) + u2Temp += sizeof(struct HW_MAC_RX_STS_GROUP_3); + pvHeader = (uint8_t *) + prRxStatus + u2Temp + u4HeaderOffset; + if (!pvHeader) { + DBGLOG(RX, ERROR, + "Mgmt Frame but pvHeader is NULL!\n"); + break; + } + prWlanMgmtHeader = + (struct WLAN_MAC_MGMT_HEADER *)pvHeader; + ucSubtype = (prWlanMgmtHeader->u2FrameCtrl & + MASK_FC_SUBTYPE) >> OFFSET_OF_FC_SUBTYPE; + DBGLOG(RX, INFO, + "MGMT frame subtype: %d\n", + ucSubtype); + DBGLOG(RX, INFO, + " SeqCtrl %d wakeup host\n", + prWlanMgmtHeader->u2SeqCtrl); + } else { + DBGLOG(RX, ERROR, + "[%s]: u2PktTYpe(0x%04X) is OUT OF DEF.!!!\n", + __func__, prSwRfb->ucPacketType); + ASSERT(0); + } + break; + default: + DBGLOG(RX, WARN, "Unknown Packet %d wakeup host\n", + prSwRfb->ucPacketType); + break; + } +} +#endif /* CFG_SUPPORT_WAKEUP_REASON_DEBUG */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_rxd_v2.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_rxd_v2.c new file mode 100644 index 0000000000000..735ade64e9b3f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_rxd_v2.c @@ -0,0 +1,594 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_tx.c#2 + */ + +/*! \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. + */ + + +#if (CFG_SUPPORT_CONNAC2X == 1) +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#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 + ******************************************************************************* + */ + +uint16_t nic_rxd_v2_get_rx_byte_count( + void *prRxStatus) +{ + return HAL_MAC_CONNAC2X_RX_STATUS_GET_RX_BYTE_CNT( + (struct HW_MAC_CONNAC2X_RX_DESC *)prRxStatus); +} + +uint8_t nic_rxd_v2_get_packet_type( + void *prRxStatus) +{ + return HAL_MAC_CONNAC2X_RX_STATUS_GET_PKT_TYPE( + (struct HW_MAC_CONNAC2X_RX_DESC *)prRxStatus); +} + +uint8_t nic_rxd_v2_get_wlan_idx( + void *prRxStatus) +{ + return HAL_MAC_CONNAC2X_RX_STATUS_GET_WLAN_IDX( + (struct HW_MAC_CONNAC2X_RX_DESC *)prRxStatus); +} + +uint8_t nic_rxd_v2_get_sec_mode( + void *prRxStatus) +{ + return HAL_MAC_CONNAC2X_RX_STATUS_GET_SEC_MODE( + (struct HW_MAC_CONNAC2X_RX_DESC *)prRxStatus); +} + +uint8_t nic_rxd_v2_get_sw_class_error_bit( + void *prRxStatus) +{ + struct HW_MAC_CONNAC2X_RX_DESC *prRxD; + + prRxD = (struct HW_MAC_CONNAC2X_RX_DESC *)prRxStatus; + if (HAL_MAC_CONNAC2X_RX_STATUS_IS_SW_DEFINE_RX_CLASSERR(prRxD)) { + DBGLOG(RSN, ERROR, + "RX_CLASSERR: RXD.DW2=0x%x\n", + prRxD->u4DW2); + return TRUE; + } else + return FALSE; +} + +uint8_t nic_rxd_v2_get_ch_num( + void *prRxStatus) +{ + return HAL_MAC_CONNAC2X_RX_STATUS_GET_CHNL_NUM( + (struct HW_MAC_CONNAC2X_RX_DESC *)prRxStatus); +} + +uint8_t nic_rxd_v2_get_rf_band( + void *prRxStatus) +{ + return HAL_MAC_CONNAC2X_RX_STATUS_GET_RF_BAND( + (struct HW_MAC_CONNAC2X_RX_DESC *)prRxStatus); +} + +uint8_t nic_rxd_v2_get_tcl( + void *prRxStatus) +{ + return HAL_MAC_CONNAC2X_RX_STATUS_GET_TCL( + (struct HW_MAC_CONNAC2X_RX_DESC *)prRxStatus); +} + +uint8_t nic_rxd_v2_get_ofld( + void *prRxStatus) +{ + return HAL_MAC_CONNAC2X_RX_STATUS_GET_OFLD( + (struct HW_MAC_CONNAC2X_RX_DESC *)prRxStatus); +} +/*----------------------------------------------------------------------------*/ +/*! + * @brief Fill RFB + * + * @param prAdapter pointer to the Adapter handler + * @param prSWRfb specify the RFB to receive rx data + * + * @return (none) + * + */ +/*----------------------------------------------------------------------------*/ +void nic_rxd_v2_fill_rfb( + struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb) +{ + struct mt66xx_chip_info *prChipInfo; + struct HW_MAC_CONNAC2X_RX_DESC *prRxStatus; + + uint32_t u4PktLen = 0; + /* UINT_32 u4MacHeaderLen; */ + uint32_t u4HeaderOffset; + uint16_t u2RxStatusOffset; + + DEBUGFUNC("nicRxFillRFB"); + + prChipInfo = prAdapter->chip_info; + prRxStatus = prSwRfb->prRxStatus; + + u4PktLen = (uint32_t) HAL_MAC_CONNAC2X_RX_STATUS_GET_RX_BYTE_CNT( + prRxStatus); + u4HeaderOffset = (uint32_t) ( + HAL_MAC_CONNAC2X_RX_STATUS_GET_HEADER_OFFSET(prRxStatus)); + + u2RxStatusOffset = prChipInfo->rxd_size; + prSwRfb->ucGroupVLD = + (uint8_t) HAL_MAC_CONNAC2X_RX_STATUS_GET_GROUP_VLD(prRxStatus); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_4)) { + prSwRfb->prRxStatusGroup4 = (struct HW_MAC_RX_STS_GROUP_4 *) + ((uint8_t *) prRxStatus + u2RxStatusOffset); + u2RxStatusOffset += sizeof(struct HW_MAC_RX_STS_GROUP_4); + + } + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_1)) { + prSwRfb->prRxStatusGroup1 = (struct HW_MAC_RX_STS_GROUP_1 *) + ((uint8_t *) prRxStatus + u2RxStatusOffset); + u2RxStatusOffset += sizeof(struct HW_MAC_RX_STS_GROUP_1); + + } + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_2)) { + prSwRfb->prRxStatusGroup2 = (struct HW_MAC_RX_STS_GROUP_2 *) + ((uint8_t *) prRxStatus + u2RxStatusOffset); + u2RxStatusOffset += sizeof(struct HW_MAC_RX_STS_GROUP_2); + + } + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_3)) { + prSwRfb->prRxStatusGroup3 = (void *) + ((uint8_t *) prRxStatus + u2RxStatusOffset); + u2RxStatusOffset += sizeof(struct HW_MAC_RX_STS_GROUP_3_V2); + } + + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_5)) { + prSwRfb->prRxStatusGroup5 = (struct HW_MAC_RX_STS_GROUP_5 *) + ((uint8_t *) prRxStatus + u2RxStatusOffset); + u2RxStatusOffset += prChipInfo->group5_size; + } + + + prSwRfb->u2RxStatusOffst = u2RxStatusOffset; + prSwRfb->pvHeader = (uint8_t *) prRxStatus + + u2RxStatusOffset + u4HeaderOffset; + prSwRfb->u2RxByteCount = u4PktLen; + prSwRfb->u2PacketLen = (uint16_t) (u4PktLen - + (u2RxStatusOffset + u4HeaderOffset)); + prSwRfb->u2HeaderLen = (uint16_t) + HAL_MAC_CONNAC2X_RX_STATUS_GET_HEADER_LEN(prRxStatus); + prSwRfb->ucWlanIdx = + (uint8_t) HAL_MAC_CONNAC2X_RX_STATUS_GET_WLAN_IDX(prRxStatus); + prSwRfb->ucStaRecIdx = secGetStaIdxByWlanIdx(prAdapter, + (uint8_t) HAL_MAC_CONNAC2X_RX_STATUS_GET_WLAN_IDX(prRxStatus)); + prSwRfb->prStaRec = cnmGetStaRecByIndex(prAdapter, + prSwRfb->ucStaRecIdx); + prSwRfb->ucTid = + (uint8_t) HAL_MAC_CONNAC2X_RX_STATUS_GET_TID(prRxStatus); + prSwRfb->fgHdrTran = + HAL_MAC_CONNAC2X_RX_STATUS_IS_HEADER_TRAN(prRxStatus); + prSwRfb->ucPayloadFormat = + HAL_MAC_CONNAC2X_RX_STATUS_GET_PAYLOAD_FORMAT(prRxStatus); + prSwRfb->fgIcvErr = + HAL_MAC_CONNAC2X_RX_STATUS_IS_ICV_ERROR(prRxStatus); + prSwRfb->ucSecMode = + HAL_MAC_CONNAC2X_RX_STATUS_GET_SEC_MODE(prRxStatus); + prSwRfb->ucOFLD = HAL_MAC_CONNAC2X_RX_STATUS_GET_OFLD(prRxStatus); + prSwRfb->fgIsBC = HAL_MAC_CONNAC2X_RX_STATUS_IS_BC(prRxStatus); + prSwRfb->fgIsMC = HAL_MAC_CONNAC2X_RX_STATUS_IS_MC(prRxStatus); + prSwRfb->fgIsCipherMS = + HAL_MAC_CONNAC2X_RX_STATUS_IS_CIPHER_MISMATCH(prRxStatus); + prSwRfb->fgIsCipherLenMS = + HAL_MAC_CONNAC2X_RX_STATUS_IS_CLM_ERROR(prRxStatus); + prSwRfb->fgIsFrag = HAL_MAC_CONNAC2X_RX_STATUS_IS_FRAG(prRxStatus); + prSwRfb->fgIsFCS = HAL_MAC_CONNAC2X_RX_STATUS_IS_FCS_ERROR(prRxStatus); + prSwRfb->fgIsAmpdu = HAL_MAC_CONNAC2X_RX_STATUS_IS_NAMP(prRxStatus); + prSwRfb->ucRxvSeqNo = + HAL_MAC_CONNAC2X_RX_STATUS_GET_RXV_SEQ_NO(prRxStatus); + prSwRfb->ucChnlNum = + HAL_MAC_CONNAC2X_RX_STATUS_GET_CHNL_NUM(prRxStatus); +#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 = (uint8_t) ((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 +} + +u_int8_t nic_rxd_v2_sanity_check( + struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb) +{ + struct mt66xx_chip_info *prChipInfo; + struct HW_MAC_CONNAC2X_RX_DESC *prRxStatus; + u_int8_t fgDrop = FALSE; + + prChipInfo = prAdapter->chip_info; + prRxStatus = (struct HW_MAC_CONNAC2X_RX_DESC *)prSwRfb->prRxStatus; + + if (!HAL_MAC_CONNAC2X_RX_STATUS_IS_FCS_ERROR(prRxStatus)) { + if (!HAL_MAC_CONNAC2X_RX_STATUS_IS_NAMP(prRxStatus) + && !HAL_MAC_CONNAC2X_RX_STATUS_IS_DAF(prRxStatus)) + prSwRfb->fgReorderBuffer = TRUE; + else if (HAL_MAC_CONNAC2X_RX_STATUS_IS_NDATA(prRxStatus)) + prSwRfb->fgDataFrame = FALSE; + else if (HAL_MAC_CONNAC2X_RX_STATUS_IS_FRAG(prRxStatus)) + prSwRfb->fgFragFrame = TRUE; + } else { + uint8_t ucBssIndex = + secGetBssIdxByWlanIdx(prAdapter, + HAL_MAC_CONNAC2X_RX_STATUS_GET_WLAN_IDX(prRxStatus)); + + fgDrop = TRUE; + if (!HAL_MAC_CONNAC2X_RX_STATUS_IS_ICV_ERROR(prRxStatus) + && HAL_MAC_CONNAC2X_RX_STATUS_IS_TKIP_MIC_ERROR( + prRxStatus)) { + struct STA_RECORD *prStaRec = NULL; + struct PARAM_BSSID_EX *prCurrBssid = + aisGetCurrBssId(prAdapter, + ucBssIndex); + + if (prCurrBssid) + prStaRec = cnmGetStaRecByAddress(prAdapter, + ucBssIndex, + prCurrBssid->arMacAddress); + if (prStaRec) { + DBGLOG(RSN, EVENT, "MIC_ERR_PKT\n"); + rsnTkipHandleMICFailure(prAdapter, prStaRec, 0); + } + } else if (HAL_MAC_CONNAC2X_RX_STATUS_IS_LLC_MIS(prRxStatus) + && !HAL_MAC_CONNAC2X_RX_STATUS_IS_ERROR(prRxStatus) + && !FEAT_SUP_LLC_VLAN_RX(prChipInfo)) { + uint16_t *pu2EtherType; + + nicRxFillRFB(prAdapter, prSwRfb); + + pu2EtherType = (uint16_t *) + ((uint8_t *)prSwRfb->pvHeader + + 2 * MAC_ADDR_LEN); + + /* If ethernet type is VLAN, do not drop it. + * Pass up to driver process + */ + if (prSwRfb->u2HeaderLen >= ETH_HLEN + && *pu2EtherType == NTOHS(ETH_P_VLAN)) + fgDrop = FALSE; + } + } + + /* Drop plain text during security connection */ + if (prSwRfb->fgIsCipherMS && prSwRfb->fgDataFrame == TRUE) { + uint16_t *pu2EtherType; + + pu2EtherType = (uint16_t *) + ((uint8_t *)prSwRfb->pvHeader + + 2 * MAC_ADDR_LEN); + if (prSwRfb->u2HeaderLen >= ETH_HLEN + && (*pu2EtherType == NTOHS(ETH_P_1X) +#if CFG_SUPPORT_WAPI + || (*pu2EtherType == NTOHS(ETH_WPI_1X)) +#endif + )) { + fgDrop = FALSE; + DBGLOG(RSN, INFO, + "Don't drop eapol or wpi packet\n"); + } else { + fgDrop = TRUE; + DBGLOG(RSN, INFO, + "Drop plain text during security connection\n"); + } + } + + return fgDrop; +} + +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG +void nic_rxd_v2_check_wakeup_reason( + struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb) +{ + struct mt66xx_chip_info *prChipInfo; + struct WIFI_EVENT *prEvent; + uint8_t *pvHeader = NULL; + struct HW_MAC_CONNAC2X_RX_DESC *prRxStatus; + uint16_t u2PktLen = 0; + uint32_t u4HeaderOffset; + u_int8_t fgDrop = FALSE; + + prChipInfo = prAdapter->chip_info; + + prRxStatus = (struct HW_MAC_CONNAC2X_RX_DESC *) prSwRfb->prRxStatus; + if (!prRxStatus) + return; + + fgDrop = nic_rxd_v2_sanity_check(prAdapter, prSwRfb); + if (fgDrop) { + DBGLOG(RX, WARN, + "%s: sanity check failed. drop!\n", __func__); + return; + } + + prSwRfb->ucGroupVLD = + (uint8_t) HAL_MAC_CONNAC2X_RX_STATUS_GET_GROUP_VLD(prRxStatus); + + switch (prSwRfb->ucPacketType) { + case RX_PKT_TYPE_SW_DEFINED: + if (prSwRfb->ucOFLD) { + DBGLOG(RX, INFO, "Need to treat as data frame.\n"); + /* + * In order to jump to case RX_PKT_TYPE_RX_DATA, + * DO NOT ADD break here!!! + */ + } else { + /* HIF_RX_PKT_TYPE_EVENT */ + if ((NIC_RX_GET_U2_SW_PKT_TYPE(prSwRfb->prRxStatus) & + CONNAC2X_RX_STATUS_PKT_TYPE_SW_BITMAP) == + CONNAC2X_RX_STATUS_PKT_TYPE_SW_EVENT) { + prEvent = (struct WIFI_EVENT *) + (prSwRfb->pucRecvBuff + prChipInfo->rxd_size); + DBGLOG(RX, INFO, "Event 0x%02x wakeup host\n", + prEvent->ucEID); + break; + } else if ((NIC_RX_GET_U2_SW_PKT_TYPE(prSwRfb->prRxStatus) & + CONNAC2X_RX_STATUS_PKT_TYPE_SW_BITMAP) == + CONNAC2X_RX_STATUS_PKT_TYPE_SW_FRAME) { + /* case HIF_RX_PKT_TYPE_MANAGEMENT: */ + uint8_t ucSubtype; + struct WLAN_MAC_MGMT_HEADER *prWlanMgmtHeader; + uint16_t u2Temp = prChipInfo->rxd_size; + + u2PktLen = + HAL_MAC_CONNAC2X_RX_STATUS_GET_RX_BYTE_CNT( + prRxStatus); + + u4HeaderOffset = (uint32_t) + HAL_MAC_CONNAC2X_RX_STATUS_GET_HEADER_OFFSET( + prRxStatus); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_4)) + u2Temp += sizeof(struct HW_MAC_RX_STS_GROUP_4); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_1)) + u2Temp += sizeof(struct HW_MAC_RX_STS_GROUP_1); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_2)) + u2Temp += sizeof(struct HW_MAC_RX_STS_GROUP_2); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_3)) + u2Temp += + sizeof(struct HW_MAC_RX_STS_GROUP_3_V2); + pvHeader = (uint8_t *) + prRxStatus + u2Temp + u4HeaderOffset; + u2PktLen -= u2Temp + u4HeaderOffset; + if (!pvHeader) { + DBGLOG(RX, ERROR, + "Frame but pvHeader is NULL!\n"); + break; + } + prWlanMgmtHeader = + (struct WLAN_MAC_MGMT_HEADER *)pvHeader; + ucSubtype = (prWlanMgmtHeader->u2FrameCtrl & + MASK_FC_SUBTYPE) >> OFFSET_OF_FC_SUBTYPE; + DBGLOG(RX, INFO, + "frame subtype: %d", + ucSubtype); + DBGLOG(RX, INFO, + " SeqCtrl %d wakeup host\n", + prWlanMgmtHeader->u2SeqCtrl); + DBGLOG_MEM8(RX, INFO, + pvHeader, u2PktLen > 50 ? 50:u2PktLen); + } else { + DBGLOG(RX, ERROR, + "[%s]: u2PktTYpe(0x%04X) is OUT OF DEF.!!!\n", + __func__, + NIC_RX_GET_U2_SW_PKT_TYPE(prSwRfb->prRxStatus)); + ASSERT(0); + } + break; + } + case RX_PKT_TYPE_RX_DATA: + { + uint16_t u2Temp = 0; + + u2PktLen = + HAL_MAC_CONNAC2X_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus); + u4HeaderOffset = (uint32_t) + HAL_MAC_CONNAC2X_RX_STATUS_GET_HEADER_OFFSET( + prRxStatus); + u2Temp = prChipInfo->rxd_size; + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_4)) + u2Temp += sizeof(struct HW_MAC_RX_STS_GROUP_4); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_1)) + u2Temp += sizeof(struct HW_MAC_RX_STS_GROUP_1); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_2)) + u2Temp += sizeof(struct HW_MAC_RX_STS_GROUP_2); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_3)) + u2Temp += sizeof(struct HW_MAC_RX_STS_GROUP_3_V2); + pvHeader = (uint8_t *)prRxStatus + u2Temp + u4HeaderOffset; + u2PktLen -= u2Temp + u4HeaderOffset; + if (!pvHeader) { + DBGLOG(RX, ERROR, + "data packet but pvHeader is NULL!\n"); + break; + } + if (HAL_MAC_CONNAC2X_RX_STATUS_IS_NDATA(prRxStatus)) { + struct WLAN_MAC_HEADER *prWlanMacHeader = + (struct WLAN_MAC_HEADER *)pvHeader; + + if ((prWlanMacHeader->u2FrameCtrl & MASK_FRAME_TYPE) == + MAC_FRAME_BLOCK_ACK_REQ) { + DBGLOG(RX, INFO, + "BAR frame[SSN:%d,TID:%d] wakeup host\n" + , prSwRfb->u2SSN, prSwRfb->ucTid); + break; + } + } + u2Temp = (pvHeader[ETH_TYPE_LEN_OFFSET] << 8) | + (pvHeader[ETH_TYPE_LEN_OFFSET + 1]); + + switch (u2Temp) { + case ETH_P_IPV4: + u2Temp = *(uint16_t *) &pvHeader[ETH_HLEN + 4]; + DBGLOG(RX, INFO, + "IP Packet from:%d.%d.%d.%d,\n", + pvHeader[ETH_HLEN + 12], + pvHeader[ETH_HLEN + 13], + pvHeader[ETH_HLEN + 14], + pvHeader[ETH_HLEN + 15]); + DBGLOG(RX, INFO, + " IP ID 0x%04x wakeup host\n", + u2Temp); + break; + case ETH_P_ARP: + break; + case ETH_P_1X: + case ETH_P_PRE_1X: +#if CFG_SUPPORT_WAPI + case ETH_WPI_1X: +#endif + case ETH_P_AARP: + case ETH_P_IPV6: + case ETH_P_IPX: + case 0x8100: /* VLAN */ + case 0x890d: /* TDLS */ + DBGLOG(RX, INFO, + "Data Packet, EthType 0x%04x wakeup host\n", + u2Temp); + break; + default: + DBGLOG(RX, WARN, + "abnormal packet, EthType 0x%04x wakeup host\n", + u2Temp); + DBGLOG_MEM8(RX, INFO, + pvHeader, u2PktLen > 50 ? 50:u2PktLen); + break; + } + break; + } + + default: + DBGLOG(RX, WARN, "Unknown Packet %d wakeup host\n", + prSwRfb->ucPacketType); + break; + } +} +#endif /* CFG_SUPPORT_WAKEUP_REASON_DEBUG */ +#endif /* CFG_SUPPORT_CONNAC2X == 1 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_tx.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_tx.c new file mode 100644 index 0000000000000..8415a39cd90a4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_tx.c @@ -0,0 +1,5473 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_tx.c#2 + */ + +/*! \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. + */ + + +/******************************************************************************* + * C O M P I L E 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 "que_mgt.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 + ******************************************************************************* + */ + +PFN_TX_DATA_DONE_CB g_pfTxDataDoneCb = nicTxMsduDoneCb; + +static const struct TX_RESOURCE_CONTROL + arTcResourceControl[TC_NUM] = { + /* dest port index, dest queue index, HIF TX queue index */ + /* First HW queue */ + {PORT_INDEX_LMAC, MAC_TXQ_AC0_INDEX, HIF_TX_AC0_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC1_INDEX, HIF_TX_AC1_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC2_INDEX, HIF_TX_AC2_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC3_INDEX, HIF_TX_AC3_INDEX}, + {PORT_INDEX_MCU, MCU_Q1_INDEX, HIF_TX_CPU_INDEX}, + + /* Second HW queue */ +#if NIC_TX_ENABLE_SECOND_HW_QUEUE + {PORT_INDEX_LMAC, MAC_TXQ_AC10_INDEX, HIF_TX_AC10_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC11_INDEX, HIF_TX_AC11_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC12_INDEX, HIF_TX_AC12_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC13_INDEX, HIF_TX_AC13_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC11_INDEX, HIF_TX_AC11_INDEX}, +#endif +}; + +/* Traffic settings per TC */ +static const struct TX_TC_TRAFFIC_SETTING + arTcTrafficSettings[NET_TC_NUM] = { + /* Tx desc template format, Remaining Tx time, + * Retry count + */ + /* For Data frame with StaRec, + * set Long Format to enable the following settings + */ + { + NIC_TX_DESC_LONG_FORMAT_LENGTH, NIC_TX_AC_BE_REMAINING_TX_TIME, + NIC_TX_DATA_DEFAULT_RETRY_COUNT_LIMIT + }, + { + NIC_TX_DESC_LONG_FORMAT_LENGTH, NIC_TX_AC_BK_REMAINING_TX_TIME, + NIC_TX_DATA_DEFAULT_RETRY_COUNT_LIMIT + }, + { + NIC_TX_DESC_LONG_FORMAT_LENGTH, NIC_TX_AC_VI_REMAINING_TX_TIME, + NIC_TX_DATA_DEFAULT_RETRY_COUNT_LIMIT + }, + { + NIC_TX_DESC_LONG_FORMAT_LENGTH, NIC_TX_AC_VO_REMAINING_TX_TIME, + NIC_TX_DATA_DEFAULT_RETRY_COUNT_LIMIT + }, + + /* MGMT frame */ + { + NIC_TX_DESC_LONG_FORMAT_LENGTH, NIC_TX_MGMT_REMAINING_TX_TIME, + NIC_TX_MGMT_DEFAULT_RETRY_COUNT_LIMIT + }, + + /* non-StaRec frame (BMC, etc...) */ + { + NIC_TX_DESC_LONG_FORMAT_LENGTH, TX_DESC_TX_TIME_NO_LIMIT, + NIC_TX_DATA_DEFAULT_RETRY_COUNT_LIMIT + }, +}; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +static uint8_t *apucTxResultStr[TX_RESULT_NUM] = { + (uint8_t *) DISP_STRING("SUCCESS"), /* success */ + (uint8_t *) DISP_STRING("LIFE_TO"), /* life timeout */ + (uint8_t *) DISP_STRING("RTS_ER"), /* RTS error */ + (uint8_t *) DISP_STRING("MPDU_ER"), /* MPDU error */ + (uint8_t *) DISP_STRING("AGE_TO"), /* aging timeout */ + (uint8_t *) DISP_STRING("FLUSHED"), /* flushed */ + (uint8_t *) DISP_STRING("BIP_ER"), /* BIP error */ + (uint8_t *) DISP_STRING("UNSPEC_ER"), /* unspecified error */ + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) DISP_STRING("DP_IN_DRV"), /* drop in driver */ + (uint8_t *) DISP_STRING("DP_IN_FW"), /* drop in FW */ + (uint8_t *) DISP_STRING("QUE_CLR"), /* queue clearance */ + (uint8_t *) DISP_STRING("INACT_BSS") /* inactive BSS */ +}; + +static uint8_t *apucBandwidt[4] = { + (uint8_t *)"20", (uint8_t *)"40", + (uint8_t *)"80", (uint8_t *)"160/80+80" +}; + +/******************************************************************************* + * M A 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 struct ADAPTER *prAdapter) +{ + struct TX_CTRL *prTxCtrl; + uint8_t *pucMemHandle; + struct MSDU_INFO *prMsduInfo; + uint32_t i; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicTxInitialize"); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + /* 4 <1> Initialization of Traffic Class Queue Parameters */ + nicTxResetResource(prAdapter); + + prTxCtrl->pucTxCoalescingBufPtr = + prAdapter->pucCoalescingBufCached; + + prTxCtrl->u4WrIdx = 0; + + /* 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 = (struct MSDU_INFO *) pucMemHandle; + kalMemZero(prMsduInfo, sizeof(struct MSDU_INFO)); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TX_MSDU_INFO_LIST); + QUEUE_INSERT_TAIL(&prTxCtrl->rFreeMsduInfoList, + (struct QUE_ENTRY *) prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TX_MSDU_INFO_LIST); + + pucMemHandle += ALIGN_4(sizeof(struct MSDU_INFO)); + } + + ASSERT(prTxCtrl->rFreeMsduInfoList.u4NumElem == + CFG_TX_MAX_PKT_NUM); + /* Check if the memory allocation consist + * with this initialization function + */ + ASSERT((uint32_t) (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; + prTxCtrl->i4PendingFwdFrameWMMCount[WMM_AC_BE_INDEX] = 0; + prTxCtrl->i4PendingFwdFrameWMMCount[WMM_AC_BK_INDEX] = 0; + prTxCtrl->i4PendingFwdFrameWMMCount[WMM_AC_VI_INDEX] = 0; + prTxCtrl->i4PendingFwdFrameWMMCount[WMM_AC_VO_INDEX] = 0; + + /* Assign init value */ + /* Tx sequence number */ + prAdapter->ucTxSeqNum = 0; + /* PID pool */ + for (i = 0; i < WTBL_SIZE; i++) + prAdapter->aucPidPool[i] = NIC_TX_DESC_DRIVER_PID_MIN; + + /* enable/disable TX resource control */ + prTxCtrl->fgIsTxResourceCtrl = NIC_TX_RESOURCE_CTRL; + + prAdapter->cArpNoResponseIdx = -1; + + qmInit(prAdapter, halIsTxResourceControlEn(prAdapter)); + + TX_RESET_ALL_CNTS(prTxCtrl); + +} /* end of nicTxInitialize() */ + +u_int8_t nicTxSanityCheckResource(IN struct ADAPTER + *prAdapter) +{ + struct TX_CTRL *prTxCtrl; + uint8_t ucTC; + uint32_t ucTotalMaxResource = 0; + uint32_t ucTotalFreeResource = 0; + u_int8_t fgError = FALSE; + + if (prAdapter->rWifiVar.ucTxDbg & BIT(0)) { + prTxCtrl = &prAdapter->rTxCtrl; + + for (ucTC = TC0_INDEX; ucTC < TC_NUM; ucTC++) { + ucTotalMaxResource += + prTxCtrl->rTc.au4MaxNumOfPage[ucTC]; + ucTotalFreeResource += + prTxCtrl->rTc.au4FreePageCount[ucTC]; + + if (prTxCtrl->rTc.au4FreePageCount[ucTC] > + prTxCtrl->u4TotalPageNum) { + DBGLOG(TX, ERROR, + "%s:%u\n error\n", __func__, __LINE__); + fgError = TRUE; + } + + if (prTxCtrl->rTc.au4MaxNumOfPage[ucTC] > + prTxCtrl->u4TotalPageNum) { + DBGLOG(TX, ERROR, + "%s:%u\n error\n", __func__, __LINE__); + fgError = TRUE; + } + + if (prTxCtrl->rTc.au4FreePageCount[ucTC] > + prTxCtrl->rTc.au4MaxNumOfPage[ucTC]) { + DBGLOG(TX, ERROR, + "%s:%u\n error\n", __func__, __LINE__); + fgError = TRUE; + } + } + + if (ucTotalMaxResource != prTxCtrl->u4TotalPageNum) { + DBGLOG(TX, ERROR, + "%s:%u\n error\n", __func__, __LINE__); + fgError = TRUE; + } + + if (ucTotalMaxResource < ucTotalFreeResource) { + DBGLOG(TX, ERROR, + "%s:%u\n error\n", __func__, __LINE__); + fgError = TRUE; + } + + if (ucTotalFreeResource > prTxCtrl->u4TotalPageNum) { + DBGLOG(TX, ERROR, + "%s:%u\n error\n", __func__, __LINE__); + fgError = TRUE; + } + + if (fgError) { + DBGLOG(TX, ERROR, "Total resource[%u]\n", + prTxCtrl->u4TotalPageNum); + qmDumpQueueStatus(prAdapter, NULL, 0); + } + } + + return !fgError; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Condition check if the PLE resource control is needed or not + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] ucTC Specify the resource of TC + * + * \retval FALSE Resource control is not needed. + * \retval TRUE Resource is not needed. + */ +/*----------------------------------------------------------------------------*/ + +u_int8_t nicTxResourceIsPleCtrlNeeded(IN struct ADAPTER + *prAdapter, IN uint8_t ucTC) +{ + struct TX_CTRL *prTxCtrl; + struct TX_TCQ_STATUS *prTc; + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + prTc = &prTxCtrl->rTc; + + /* no PLE resource control */ + if (!prTc->fgNeedPleCtrl) + return FALSE; + + /* CMD doesn't have PLE */ + if (ucTC == 4) + return FALSE; + + /* rom stage inbabd command use TC0. need refine a good method */ + if ((ucTC == 0) && (prAdapter->fgIsFwDownloaded == FALSE)) + return FALSE; + + return TRUE; +} + + +uint32_t nicTxResourceGetPleFreeCount(IN struct ADAPTER + *prAdapter, IN uint8_t ucTC) +{ + struct TX_CTRL *prTxCtrl; + struct TX_TCQ_STATUS *prTc; + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + prTc = &prTxCtrl->rTc; + + if (!nicTxResourceIsPleCtrlNeeded(prAdapter, ucTC)) { + /* unlimited value*/ + return 0xFFFFFFFF; + } + + return prTc->au4FreePageCount_PLE[ucTC]; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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. + */ +/*----------------------------------------------------------------------------*/ + +uint32_t nicTxAcquireResourcePLE(IN struct ADAPTER + *prAdapter, IN uint8_t ucTC) +{ + struct TX_CTRL *prTxCtrl; + struct TX_TCQ_STATUS *prTc; + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + prTc = &prTxCtrl->rTc; + + if (ucTC >= TC_NUM) + return WLAN_STATUS_FAILURE; + + if (!nicTxResourceIsPleCtrlNeeded(prAdapter, ucTC)) + return WLAN_STATUS_SUCCESS; + + DBGLOG(INIT, INFO, + "Acquire PLE: TC%d AcquirePageCnt[%u] FreeBufferCnt[%u] FreePageCnt[%u]\n", + ucTC, NIX_TX_PLE_PAGE_CNT_PER_FRAME, + prTc->au4FreeBufferCount_PLE[ucTC], + prTc->au4FreePageCount_PLE[ucTC]); + + + /* PLE Acquire */ + if (prTc->au4FreePageCount_PLE[ucTC] >= + NIX_TX_PLE_PAGE_CNT_PER_FRAME) { + prTc->au4FreePageCount_PLE[ucTC] -= + NIX_TX_PLE_PAGE_CNT_PER_FRAME; + + return WLAN_STATUS_SUCCESS; + } + + DBGLOG(INIT, ERROR, + "Acquire PLE FAILURE. TC%d AcquirePageCnt[%u] FreeBufferCnt[%u] FreePageCnt[%u]\n", + ucTC, NIX_TX_PLE_PAGE_CNT_PER_FRAME, + prTc->au4FreeBufferCount_PLE[ucTC], + prTc->au4FreePageCount_PLE[ucTC]); + + + return WLAN_STATUS_RESOURCES; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t u4CurrTick; +uint32_t nicTxAcquireResource(IN struct ADAPTER *prAdapter, + IN uint8_t ucTC, IN uint32_t u4PageCount, + IN u_int8_t fgReqLock) +{ +#define TC4_NO_RESOURCE_DELAY_MS 5 /* exponential of 5s */ + + struct TX_CTRL *prTxCtrl; + struct TX_TCQ_STATUS *prTc; + uint32_t u4Status = WLAN_STATUS_RESOURCES; + uint32_t u4MaxPageCntPerFrame = + prAdapter->rTxCtrl.u4MaxPageCntPerFrame; + struct QUE_MGT *prQM; + + KAL_SPIN_LOCK_DECLARATION(); + + /* enable/disable TX resource control */ + if (!prAdapter->rTxCtrl.fgIsTxResourceCtrl || ucTC >= TC_NUM) + return WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + prTc = &prTxCtrl->rTc; + + if (fgReqLock) + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); +#if 1 + prQM = &prAdapter->rQM; + if (prTc->au4FreePageCount[ucTC] >= u4PageCount) { + + if (nicTxAcquireResourcePLE(prAdapter, + ucTC) != WLAN_STATUS_SUCCESS) { + if (fgReqLock) + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TX_RESOURCE); + + return WLAN_STATUS_RESOURCES; + } + + /* This update must be AFTER the PLE-resource-check */ + if (ucTC == TC4_INDEX) + u4CurrTick = 0; + prTc->au4FreePageCount[ucTC] -= u4PageCount; + prTc->au4FreeBufferCount[ucTC] = + (prTc->au4FreePageCount[ucTC] / u4MaxPageCntPerFrame); + prQM->au4QmTcUsedPageCounter[ucTC] += u4PageCount; + + DBGLOG(TX, TEMP, + "Acquire: TC%d AcquirePageCnt[%u] FreeBufferCnt[%u] FreePageCnt[%u]\n", + ucTC, u4PageCount, prTc->au4FreeBufferCount[ucTC], + prTc->au4FreePageCount[ucTC]); + + u4Status = WLAN_STATUS_SUCCESS; + } +#else + if (prTxCtrl->rTc.au4FreePageCount[ucTC] > 0) { + + prTxCtrl->rTc.au4FreePageCount[ucTC] -= 1; + + u4Status = WLAN_STATUS_SUCCESS; + } +#endif + if (fgReqLock) + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + if (ucTC == TC4_INDEX) { + if (u4CurrTick == 0) + u4CurrTick = kalGetTimeTick(); + if (CHECK_FOR_TIMEOUT(kalGetTimeTick(), u4CurrTick, + SEC_TO_SYSTIME(TC4_NO_RESOURCE_DELAY_MS))) { +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanDumpTcResAndTxedCmd(NULL, 0); +#endif + cmdBufDumpCmdQueue(&prAdapter->rPendingCmdQueue, + "waiting response CMD queue"); + } + } + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxPollingResource(IN struct ADAPTER *prAdapter, + IN uint8_t ucTC) +{ + struct TX_CTRL *prTxCtrl; + uint32_t u4Status = WLAN_STATUS_FAILURE; + int32_t i = NIC_TX_RESOURCE_POLLING_TIMEOUT; + /*UINT_32 au4WTSR[8];*/ + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + if (ucTC >= TC_NUM) + return WLAN_STATUS_FAILURE; + + if (prTxCtrl->rTc.au4FreeBufferCount[ucTC] > 0) + return WLAN_STATUS_SUCCESS; + + while (i-- > 0) { +#if 1 + u4Status = halTxPollingResource(prAdapter, ucTC); + if (u4Status == WLAN_STATUS_RESOURCES) + kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC); + else + break; +#else + HAL_READ_TX_RELEASED_COUNT(prAdapter, au4WTSR); + + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + break; + } else if (halTxReleaseResource(prAdapter, + (uint16_t *) au4WTSR)) { + if (prTxCtrl->rTc.au4FreeBufferCount[ucTC] > 0) { + u4Status = WLAN_STATUS_SUCCESS; + break; + } + kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC); + } else { + kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC); + } +#endif + } + +#if DBG + { + int32_t i4Times = NIC_TX_RESOURCE_POLLING_TIMEOUT - (i + 1); + + if (i4Times) { + DBGLOG(TX, TRACE, + "Polling MCR_WTSR delay %ld times, %ld 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. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +u_int8_t nicTxReleaseResource(IN struct ADAPTER *prAdapter, + IN uint8_t ucTc, IN uint32_t u4PageCount, + IN u_int8_t fgReqLock, IN u_int8_t fgPLE) +{ + struct TX_TCQ_STATUS *prTcqStatus; + u_int8_t bStatus = FALSE; + uint32_t u4MaxPageCntPerFrame = + prAdapter->rTxCtrl.u4MaxPageCntPerFrame; + struct QUE_MGT *prQM = NULL; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + /* enable/disable TX resource control */ + if (!prAdapter->rTxCtrl.fgIsTxResourceCtrl || ucTc >= TC_NUM) + return TRUE; + + /* No need to do PLE resource control */ + if (fgPLE && !nicTxResourceIsPleCtrlNeeded(prAdapter, ucTc)) + return TRUE; + + prTcqStatus = &prAdapter->rTxCtrl.rTc; + prQM = &prAdapter->rQM; + + /* Return free Tc page count */ + if (fgReqLock) + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + if (fgPLE) { + prTcqStatus->au4FreePageCount_PLE[ucTc] += u4PageCount; + prTcqStatus->au4FreeBufferCount_PLE[ucTc] = + (prTcqStatus->au4FreePageCount_PLE[ucTc] / + NIX_TX_PLE_PAGE_CNT_PER_FRAME); + } else { + prTcqStatus->au4FreePageCount[ucTc] += u4PageCount; + prTcqStatus->au4FreeBufferCount[ucTc] = + (prTcqStatus->au4FreePageCount[ucTc] / + u4MaxPageCntPerFrame); + } + prQM->au4QmTcResourceBackCounter[ucTc] += u4PageCount; + + if (fgReqLock) + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + +#if (CFG_SUPPORT_TRACE_TC4 == 1) + if (ucTc == TC4_INDEX) + wlanTraceReleaseTcRes(prAdapter, u4PageCount, + prTcqStatus->au4FreePageCount[ucTc]); +#endif + bStatus = TRUE; + + return bStatus; +} /* end of nicTxReleaseResource() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Driver maintain a variable that is synchronous with the usage of + * individual TC Buffer Count. This function will release TC Buffer + * count for resource allocated but un-Tx MSDU_INFO + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicTxReleaseMsduResource(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfoListHead) +{ + struct MSDU_INFO *prMsduInfo = prMsduInfoListHead, + *prNextMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + while (prMsduInfo) { + prNextMsduInfo = (struct MSDU_INFO *) QUEUE_GET_NEXT_ENTRY(( + struct QUE_ENTRY *) prMsduInfo); + + nicTxReleaseResource_PSE(prAdapter, prMsduInfo->ucTC, + nicTxGetPageCount( + prAdapter, prMsduInfo->u2FrameLength, + FALSE), FALSE); + + nicTxReleaseResource_PLE(prAdapter, prMsduInfo->ucTC, + NIX_TX_PLE_PAGE_CNT_PER_FRAME, FALSE); + + prMsduInfo = prNextMsduInfo; + }; + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Reset TC Buffer Count to initialized value + * + * \param[in] prAdapter Pointer to the Adapter structure. + * + * @return WLAN_STATUS_SUCCESS + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxResetResource(IN struct ADAPTER *prAdapter) +{ + struct TX_CTRL *prTxCtrl; + uint8_t ucIdx; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicTxResetResource"); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + /* Following two lines MUST be in order. */ + prTxCtrl->u4PageSize = halGetHifTxPageSize(prAdapter); + prTxCtrl->u4MaxPageCntPerFrame = nicTxGetMaxPageCntPerFrame( + prAdapter); + + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + /* Delta page count */ + kalMemZero(prTxCtrl->rTc.au4TxDonePageCount, + sizeof(prTxCtrl->rTc.au4TxDonePageCount)); + kalMemZero(prTxCtrl->rTc.au4PreUsedPageCount, + sizeof(prTxCtrl->rTc.au4PreUsedPageCount)); + + prTxCtrl->rTc.ucNextTcIdx = TC0_INDEX; + prTxCtrl->rTc.u4AvaliablePageCount = 0; + + DBGLOG(TX, TRACE, + "Default TCQ free resource [%u %u %u %u %u]\n", + prAdapter->rWifiVar.au4TcPageCount[TC0_INDEX], + prAdapter->rWifiVar.au4TcPageCount[TC1_INDEX], + prAdapter->rWifiVar.au4TcPageCount[TC2_INDEX], + prAdapter->rWifiVar.au4TcPageCount[TC3_INDEX], + prAdapter->rWifiVar.au4TcPageCount[TC4_INDEX]); + + /* Reset counter: PSE */ + prAdapter->rTxCtrl.u4TotalPageNum = 0; + prAdapter->rTxCtrl.u4TotalTxRsvPageNum = 0; + /* Reset counter: PLE */ + prAdapter->rTxCtrl.u4TotalPageNumPle = 0; + + /* Assign resource for each TC according to prAdapter->rWifiVar */ + for (ucIdx = TC0_INDEX; ucIdx < TC_NUM; ucIdx++) { + + /* + * PSE + */ + + /* Page Count */ + prTxCtrl->rTc.au4MaxNumOfPage[ucIdx] = + prAdapter->rWifiVar.au4TcPageCount[ucIdx]; + prTxCtrl->rTc.au4FreePageCount[ucIdx] = + prAdapter->rWifiVar.au4TcPageCount[ucIdx]; + + DBGLOG(TX, TRACE, "Set TC%u Default[%u] Max[%u] Free[%u]\n", + ucIdx, + prAdapter->rWifiVar.au4TcPageCount[ucIdx], + prTxCtrl->rTc.au4MaxNumOfPage[ucIdx], + prTxCtrl->rTc.au4FreePageCount[ucIdx]); + + /* Buffer count */ + prTxCtrl->rTc.au4MaxNumOfBuffer[ucIdx] = + (prTxCtrl->rTc.au4MaxNumOfPage[ucIdx] / + (prTxCtrl->u4MaxPageCntPerFrame)); + + prTxCtrl->rTc.au4FreeBufferCount[ucIdx] = + (prTxCtrl->rTc.au4FreePageCount[ucIdx] / + (prTxCtrl->u4MaxPageCntPerFrame)); + + + DBGLOG(TX, TRACE, + "Set TC%u Default[%u] Buffer Max[%u] Free[%u]\n", + ucIdx, + prAdapter->rWifiVar.au4TcPageCount[ucIdx], + prTxCtrl->rTc.au4MaxNumOfBuffer[ucIdx], + prTxCtrl->rTc.au4FreeBufferCount[ucIdx]); + + prAdapter->rTxCtrl.u4TotalPageNum += + prTxCtrl->rTc.au4MaxNumOfPage[ucIdx]; + + + /* + * PLE + */ + if (prAdapter->rTxCtrl.rTc.fgNeedPleCtrl) { + /* Page Count */ + prTxCtrl->rTc.au4MaxNumOfPage_PLE[ucIdx] = + prAdapter->rWifiVar.au4TcPageCountPle[ucIdx]; + prTxCtrl->rTc.au4FreePageCount_PLE[ucIdx] = + prAdapter->rWifiVar.au4TcPageCountPle[ucIdx]; + + DBGLOG(TX, TRACE, + "[PLE]Set TC%u Default[%u] Max[%u] Free[%u]\n", + ucIdx, + prAdapter->rWifiVar.au4TcPageCountPle[ucIdx], + prTxCtrl->rTc.au4MaxNumOfPage_PLE[ucIdx], + prTxCtrl->rTc.au4FreePageCount_PLE[ucIdx]); + + /* Buffer count */ + prTxCtrl->rTc.au4MaxNumOfBuffer_PLE[ucIdx] = + (prTxCtrl->rTc.au4MaxNumOfPage_PLE[ucIdx] / + NIX_TX_PLE_PAGE_CNT_PER_FRAME); + + prTxCtrl->rTc.au4FreeBufferCount_PLE[ucIdx] = + (prTxCtrl->rTc.au4FreePageCount_PLE[ucIdx] / + NIX_TX_PLE_PAGE_CNT_PER_FRAME); + + + DBGLOG(TX, TRACE, + "[PLE]Set TC%u Default[%u] Buffer Max[%u] Free[%u]\n", + ucIdx, + prAdapter->rWifiVar.au4TcPageCountPle[ucIdx], + prTxCtrl->rTc.au4MaxNumOfBuffer_PLE[ucIdx], + prTxCtrl->rTc.au4FreeBufferCount_PLE[ucIdx]); + + prAdapter->rTxCtrl.u4TotalPageNumPle += + prTxCtrl->rTc.au4MaxNumOfPage_PLE[ucIdx]; + } + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + if (!prAdapter->fgIsNicTxReousrceValid)/* use default value */ + prAdapter->nicTxReousrce.ucPpTxAddCnt = + NIC_TX_LEN_ADDING_LENGTH; + DBGLOG(TX, TRACE, + "Reset TCQ free resource to Page <>:Buf [%u:%u %u:%u %u:%u %u:%u %u:%u]\n", + prTxCtrl->rTc.au4FreePageCount[TC0_INDEX], + prTxCtrl->rTc.au4FreeBufferCount[TC0_INDEX], + prTxCtrl->rTc.au4FreePageCount[TC1_INDEX], + prTxCtrl->rTc.au4FreeBufferCount[TC1_INDEX], + prTxCtrl->rTc.au4FreePageCount[TC2_INDEX], + prTxCtrl->rTc.au4FreeBufferCount[TC2_INDEX], + prTxCtrl->rTc.au4FreePageCount[TC3_INDEX], + prTxCtrl->rTc.au4FreeBufferCount[TC3_INDEX], + prTxCtrl->rTc.au4FreePageCount[TC4_INDEX], + prTxCtrl->rTc.au4FreeBufferCount[TC4_INDEX]); + + if (prAdapter->rTxCtrl.rTc.fgNeedPleCtrl) + DBGLOG(TX, TRACE, + "Reset TCQ free resource to Page <>:Buf [%u:%u %u:%u %u:%u %u:%u %u:%u]\n", + prTxCtrl->rTc.au4FreePageCount_PLE[TC0_INDEX], + prTxCtrl->rTc.au4FreeBufferCount_PLE[TC0_INDEX], + prTxCtrl->rTc.au4FreePageCount_PLE[TC1_INDEX], + prTxCtrl->rTc.au4FreeBufferCount_PLE[TC1_INDEX], + prTxCtrl->rTc.au4FreePageCount_PLE[TC2_INDEX], + prTxCtrl->rTc.au4FreeBufferCount_PLE[TC2_INDEX], + prTxCtrl->rTc.au4FreePageCount_PLE[TC3_INDEX], + prTxCtrl->rTc.au4FreeBufferCount_PLE[TC3_INDEX], + prTxCtrl->rTc.au4FreePageCount_PLE[TC4_INDEX], + prTxCtrl->rTc.au4FreeBufferCount_PLE[TC4_INDEX]); + + + DBGLOG(TX, TRACE, + "Reset TCQ MAX resource to Page <>:Buf [%u:%u %u:%u %u:%u %u:%u %u:%u]\n", + prTxCtrl->rTc.au4MaxNumOfPage[TC0_INDEX], + prTxCtrl->rTc.au4MaxNumOfBuffer[TC0_INDEX], + prTxCtrl->rTc.au4MaxNumOfPage[TC1_INDEX], + prTxCtrl->rTc.au4MaxNumOfBuffer[TC1_INDEX], + prTxCtrl->rTc.au4MaxNumOfPage[TC2_INDEX], + prTxCtrl->rTc.au4MaxNumOfBuffer[TC2_INDEX], + prTxCtrl->rTc.au4MaxNumOfPage[TC3_INDEX], + prTxCtrl->rTc.au4MaxNumOfBuffer[TC3_INDEX], + prTxCtrl->rTc.au4MaxNumOfPage[TC4_INDEX], + prTxCtrl->rTc.au4MaxNumOfBuffer[TC4_INDEX]); + + if (prAdapter->rTxCtrl.rTc.fgNeedPleCtrl) + DBGLOG(TX, TRACE, + "Reset TCQ MAX resource to Page <>:Buf [%u:%u %u:%u %u:%u %u:%u %u:%u]\n", + prTxCtrl->rTc.au4MaxNumOfPage_PLE[TC0_INDEX], + prTxCtrl->rTc.au4MaxNumOfBuffer_PLE[TC0_INDEX], + prTxCtrl->rTc.au4MaxNumOfPage_PLE[TC1_INDEX], + prTxCtrl->rTc.au4MaxNumOfBuffer_PLE[TC1_INDEX], + prTxCtrl->rTc.au4MaxNumOfPage_PLE[TC2_INDEX], + prTxCtrl->rTc.au4MaxNumOfBuffer_PLE[TC2_INDEX], + prTxCtrl->rTc.au4MaxNumOfPage_PLE[TC3_INDEX], + prTxCtrl->rTc.au4MaxNumOfBuffer_PLE[TC3_INDEX], + prTxCtrl->rTc.au4MaxNumOfPage_PLE[TC4_INDEX], + prTxCtrl->rTc.au4MaxNumOfBuffer_PLE[TC4_INDEX]); + + return WLAN_STATUS_SUCCESS; +} + +#if QM_FAST_TC_RESOURCE_CTRL +uint32_t +nicTxGetAdjustableResourceCnt(IN struct ADAPTER *prAdapter) +{ + struct TX_CTRL *prTxCtrl; + uint8_t ucIdx; + uint32_t u4TotAdjCnt = 0; + uint32_t u4AdjCnt; + struct QUE_MGT *prQM = NULL; + + prQM = &prAdapter->rQM; + prTxCtrl = &prAdapter->rTxCtrl; + + for (ucIdx = TC0_INDEX; ucIdx < TC_NUM; ucIdx++) { + if (ucIdx == TC4_INDEX) + continue; + + if (prTxCtrl->rTc.au4FreeBufferCount[ucIdx] > + prQM->au4MinReservedTcResource[ucIdx]) + u4AdjCnt = prTxCtrl->rTc.au4FreeBufferCount[ucIdx] - + prQM->au4MinReservedTcResource[ucIdx]; + else + u4AdjCnt = 0; + + u4TotAdjCnt += u4AdjCnt; + } + + /* no PLE resource control */ + if (!prAdapter->rTxCtrl.rTc.fgNeedPleCtrl) + return u4TotAdjCnt; + + /* PLE part */ + for (ucIdx = TC0_INDEX; ucIdx < TC_NUM; ucIdx++) { + if (ucIdx == TC4_INDEX) + continue; + + if (prTxCtrl->rTc.au4FreeBufferCount_PLE[ucIdx] > + prQM->au4MinReservedTcResource[ucIdx]) + u4AdjCnt = prTxCtrl->rTc.au4FreeBufferCount_PLE[ucIdx] - + prQM->au4MinReservedTcResource[ucIdx]; + else + u4AdjCnt = 0; + + u4TotAdjCnt += u4AdjCnt; + } + + return u4TotAdjCnt; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +uint16_t nicTxGetResource(IN struct ADAPTER *prAdapter, + IN uint8_t ucTC) +{ + struct TX_CTRL *prTxCtrl; + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + ASSERT(prTxCtrl); + + if (ucTC >= TC_NUM) + return 0; + else + return prTxCtrl->rTc.au4FreePageCount[ucTC]; +} + +uint8_t nicTxGetFrameResourceType(IN uint8_t eFrameType, + IN struct MSDU_INFO *prMsduInfo) +{ + uint8_t ucTC; + + switch (eFrameType) { + case FRAME_TYPE_802_1X: + ucTC = TC4_INDEX; + break; + + case FRAME_TYPE_MMPDU: + if (prMsduInfo) + ucTC = prMsduInfo->ucTC; + else + ucTC = TC4_INDEX; + break; + + default: + DBGLOG(INIT, WARN, "Undefined Frame Type(%u)\n", + eFrameType); + ucTC = TC4_INDEX; + break; + } + + return ucTC; +} + +uint8_t nicTxGetCmdResourceType(IN struct CMD_INFO + *prCmdInfo) +{ + uint8_t ucTC; + + switch (prCmdInfo->eCmdType) { + case COMMAND_TYPE_NETWORK_IOCTL: + case COMMAND_TYPE_GENERAL_IOCTL: + ucTC = TC4_INDEX; + break; + + case COMMAND_TYPE_SECURITY_FRAME: + case COMMAND_TYPE_DATA_FRAME: + ucTC = nicTxGetFrameResourceType(FRAME_TYPE_802_1X, NULL); + break; + + case COMMAND_TYPE_MANAGEMENT_FRAME: + ucTC = nicTxGetFrameResourceType(FRAME_TYPE_MMPDU, + prCmdInfo->prMsduInfo); + break; + + default: + DBGLOG(INIT, WARN, "Undefined CMD Type(%u)\n", + prCmdInfo->eCmdType); + ucTC = TC4_INDEX; + break; + } + + return ucTC; +} + +uint8_t nicTxGetTxQByTc(IN struct ADAPTER *prAdapter, + IN uint8_t ucTc) +{ + return arTcResourceControl[ucTc].ucHifTxQIndex; +} + +uint8_t nicTxGetTxDestPortIdxByTc(IN uint8_t ucTc) +{ + return arTcResourceControl[ucTc].ucDestPortIndex; +} + +uint8_t nicTxGetTxDestQIdxByTc(IN uint8_t ucTc) +{ + return arTcResourceControl[ucTc].ucDestQueueIndex; +} + +uint32_t nicTxGetRemainingTxTimeByTc(IN uint8_t ucTc) +{ + return arTcTrafficSettings[ucTc].u4RemainingTxTime; +} + +uint8_t nicTxGetTxCountLimitByTc(IN uint8_t ucTc) +{ + return arTcTrafficSettings[ucTc].ucTxCountLimit; +} +/*----------------------------------------------------------------------------*/ +/*! + * @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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxMsduInfoList(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfoListHead) +{ + struct MSDU_INFO *prMsduInfo, *prNextMsduInfo; + struct QUE qDataPort0, qDataPort1; + struct QUE *prDataPort0, *prDataPort1; + uint32_t status; + + ASSERT(prAdapter); + ASSERT(prMsduInfoListHead); + + prMsduInfo = prMsduInfoListHead; + + prDataPort0 = &qDataPort0; + prDataPort1 = &qDataPort1; + + QUEUE_INITIALIZE(prDataPort0); + QUEUE_INITIALIZE(prDataPort1); + + /* Separate MSDU_INFO_T lists into 2 categories: for Port#0 & Port#1 */ + while (prMsduInfo) { + prNextMsduInfo = (struct MSDU_INFO *) QUEUE_GET_NEXT_ENTRY(( + struct QUE_ENTRY *) prMsduInfo); + + switch (prMsduInfo->ucTC) { + case TC0_INDEX: + case TC1_INDEX: + case TC2_INDEX: + case TC3_INDEX: + QUEUE_GET_NEXT_ENTRY((struct QUE_ENTRY *) prMsduInfo) = + NULL; + QUEUE_INSERT_TAIL(prDataPort0, + (struct QUE_ENTRY *) prMsduInfo); + status = nicTxAcquireResource( + prAdapter, prMsduInfo->ucTC, + nicTxGetPageCount( + prAdapter, prMsduInfo->u2FrameLength, + FALSE), TRUE); + ASSERT(status == WLAN_STATUS_SUCCESS); + + break; + + case TC4_INDEX: /* Management packets */ + QUEUE_GET_NEXT_ENTRY((struct QUE_ENTRY *) prMsduInfo) = + NULL; + QUEUE_INSERT_TAIL(prDataPort1, + (struct QUE_ENTRY *) prMsduInfo); + + status = nicTxAcquireResource( + prAdapter, prMsduInfo->ucTC, + nicTxGetPageCount(prAdapter, + prMsduInfo->u2FrameLength, + FALSE), TRUE); + ASSERT(status == WLAN_STATUS_SUCCESS); + + break; + + default: + ASSERT(0); + break; + } + + prMsduInfo = prNextMsduInfo; + } + + if (prDataPort0->u4NumElem > 0) + nicTxMsduQueue(prAdapter, 0, prDataPort0); + + if (prDataPort1->u4NumElem > 0) + nicTxMsduQueue(prAdapter, 1, prDataPort1); + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_SUPPORT_MULTITHREAD +/*----------------------------------------------------------------------------*/ +/*! + * @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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxMsduInfoListMthread(IN struct ADAPTER + *prAdapter, IN struct MSDU_INFO *prMsduInfoListHead) +{ +#if CFG_FIX_2_TX_PORT + struct MSDU_INFO *prMsduInfo, *prNextMsduInfo; + struct QUE qDataPort0, qDataPort1; + struct QUE *prDataPort0, *prDataPort1; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prMsduInfoListHead); + + prMsduInfo = prMsduInfoListHead; + + prDataPort0 = &qDataPort0; + prDataPort1 = &qDataPort1; + + QUEUE_INITIALIZE(prDataPort0); + QUEUE_INITIALIZE(prDataPort1); + + /* Separate MSDU_INFO_T lists into 2 categories: for Port#0 & Port#1 */ + while (prMsduInfo) { + prNextMsduInfo = (struct MSDU_INFO *) QUEUE_GET_NEXT_ENTRY(( + struct QUE_ENTRY *) prMsduInfo); + + switch (prMsduInfo->ucTC) { + case TC0_INDEX: + case TC1_INDEX: + case TC2_INDEX: + case TC3_INDEX: + QUEUE_GET_NEXT_ENTRY((struct QUE_ENTRY *) prMsduInfo) = + NULL; + QUEUE_INSERT_TAIL(prDataPort0, + (struct QUE_ENTRY *) prMsduInfo); + break; + + case TC4_INDEX: /* Management packets */ + QUEUE_GET_NEXT_ENTRY((struct QUE_ENTRY *) prMsduInfo) = + NULL; + QUEUE_INSERT_TAIL(prDataPort1, + (struct QUE_ENTRY *) prMsduInfo); + break; + + default: + ASSERT(0); + break; + } + + nicTxFillDataDesc(prAdapter, prMsduInfo); + + prMsduInfo = prNextMsduInfo; + } + + if (prDataPort0->u4NumElem > 0 + || prDataPort1->u4NumElem > 0) { + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + QUEUE_CONCATENATE_QUEUES((&(prAdapter->rTxP0Queue)), + (prDataPort0)); + QUEUE_CONCATENATE_QUEUES((&(prAdapter->rTxP1Queue)), + (prDataPort1)); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + + kalSetTxEvent2Hif(prAdapter->prGlueInfo); + } +#else + struct MSDU_INFO *prMsduInfo, *prNextMsduInfo; + struct QUE qDataPort[BSS_DEFAULT_NUM][TX_PORT_NUM]; + struct QUE *prDataPort[BSS_DEFAULT_NUM][TX_PORT_NUM]; + int32_t i, j; + u_int8_t fgSetTx2Hif = FALSE; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prMsduInfoListHead); + + prMsduInfo = prMsduInfoListHead; + + for (i = 0; i < BSS_DEFAULT_NUM; i++) { + for (j = 0; j < TX_PORT_NUM; j++) { + prDataPort[i][j] = &qDataPort[i][j]; + QUEUE_INITIALIZE(prDataPort[i][j]); + } + } + + /* Separate MSDU_INFO_T lists into 2 categories: for Port#0 & Port#1 */ + while (prMsduInfo) { + fgSetTx2Hif = TRUE; + prNextMsduInfo = (struct MSDU_INFO *) QUEUE_GET_NEXT_ENTRY(( + struct QUE_ENTRY *) prMsduInfo); + if (prMsduInfo->ucTC >= 0 && + prMsduInfo->ucTC < TC_NUM) { + QUEUE_GET_NEXT_ENTRY( + (struct QUE_ENTRY *) prMsduInfo) = + NULL; + QUEUE_INSERT_TAIL( + prDataPort[prMsduInfo->ucBssIndex][prMsduInfo->ucTC], + (struct QUE_ENTRY *) prMsduInfo); + } else + ASSERT(0); + + nicTxFillDataDesc(prAdapter, prMsduInfo); + GLUE_INC_REF_CNT(prAdapter->rHifStats.u4DataInCount); + + prMsduInfo = prNextMsduInfo; + } + + if (fgSetTx2Hif) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + for (i = 0; i < BSS_DEFAULT_NUM; i++) { + for (j = 0; j < TX_PORT_NUM; j++) { + QUEUE_CONCATENATE_QUEUES( + (&(prAdapter->rTxPQueue[i][j])), + (prDataPort[i][j])); + } + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + kalSetTxEvent2Hif(prAdapter->prGlueInfo); + } + +#endif + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief In this function, we'll write frame(PACKET_INFO_T) into HIF + * when apply multithread. + * + * @param prAdapter Pointer to the Adapter structure. + * + * @retval WLAN_STATUS_SUCCESS Bus access ok. + * @retval WLAN_STATUS_FAILURE Bus access fail. + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxMsduQueueMthread(IN struct ADAPTER *prAdapter) +{ +#if CFG_FIX_2_TX_PORT + struct QUE qDataPort0, qDataPort1; + struct QUE *prDataPort0, *prDataPort1; + uint32_t u4TxLoopCount; + + KAL_SPIN_LOCK_DECLARATION(); + + prDataPort0 = &qDataPort0; + prDataPort1 = &qDataPort1; + + QUEUE_INITIALIZE(prDataPort0); + QUEUE_INITIALIZE(prDataPort1); + + u4TxLoopCount = prAdapter->rWifiVar.u4HifTxloopCount; + + while (u4TxLoopCount--) { + while (QUEUE_IS_NOT_EMPTY(&(prAdapter->rTxP0Queue))) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + QUEUE_MOVE_ALL(prDataPort0, &(prAdapter->rTxP0Queue)); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + + nicTxMsduQueue(prAdapter, 0, prDataPort0); + + if (QUEUE_IS_NOT_EMPTY(prDataPort0)) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TX_PORT_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD( + &(prAdapter->rTxP0Queue), + prDataPort0); + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TX_PORT_QUE); + + break; + } + } + + while (QUEUE_IS_NOT_EMPTY(&(prAdapter->rTxP1Queue))) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + QUEUE_MOVE_ALL(prDataPort1, &(prAdapter->rTxP1Queue)); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + + nicTxMsduQueue(prAdapter, 1, prDataPort1); + + if (QUEUE_IS_NOT_EMPTY(prDataPort1)) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TX_PORT_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD( + &(prAdapter->rTxP1Queue), + prDataPort1); + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TX_PORT_QUE); + + break; + } + } + } +#else + + uint32_t u4TxLoopCount = prAdapter->rWifiVar.u4HifTxloopCount; + + if (halIsHifStateSuspend(prAdapter)) { + DBGLOG(TX, WARN, "Suspend TxMsduQueueMthread\n"); + return WLAN_STATUS_SUCCESS; + } + + while (u4TxLoopCount--) { + if (prAdapter->rWifiVar.ucTxMsduQueue == 1) + nicTxMsduQueueByRR(prAdapter); + else + nicTxMsduQueueByPrio(prAdapter); + } +#endif + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief In this function, we'll write MSDU into HIF by TC priority + * + * + * @param prAdapter Pointer to the Adapter structure. + * + */ +/*----------------------------------------------------------------------------*/ +void nicTxMsduQueueByPrio(struct ADAPTER *prAdapter) +{ + struct QUE qDataPort[BSS_DEFAULT_NUM][TX_PORT_NUM]; + struct QUE *prDataPort[BSS_DEFAULT_NUM][TX_PORT_NUM]; + int32_t i, j, k; + struct BSS_INFO *prBssInfo; +#if QM_FORWARDING_FAIRNESS + struct QUE_MGT *prQM = &prAdapter->rQM; +#endif + + KAL_SPIN_LOCK_DECLARATION(); + + for (i = 0; i < BSS_DEFAULT_NUM; i++) { + for (j = 0; j < TX_PORT_NUM; j++) { + prDataPort[i][j] = &qDataPort[i][j]; + QUEUE_INITIALIZE(prDataPort[i][j]); + } + } + + for (j = TX_PORT_NUM - 1; j >= 0; j--) { +#if QM_FORWARDING_FAIRNESS + i = prQM->u4HeadBssInfoIndex; +#else + i = 0; +#endif + for (k = 0; k < BSS_DEFAULT_NUM; k++) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, i); + while (!prBssInfo->fgIsNetAbsent && QUEUE_IS_NOT_EMPTY( + &(prAdapter->rTxPQueue[i][j]))) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TX_PORT_QUE); + QUEUE_MOVE_ALL(prDataPort[i][j], + &(prAdapter->rTxPQueue[i][j])); + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TX_PORT_QUE); + + TRACE(nicTxMsduQueue(prAdapter, + 0, prDataPort[i][j]), + "Move TxPQueue%d_%d %d", + i, j, prDataPort[i][j]->u4NumElem); + + if (QUEUE_IS_NOT_EMPTY(prDataPort[i][j])) { + KAL_ACQUIRE_SPIN_LOCK( + prAdapter, + SPIN_LOCK_TX_PORT_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD( + &(prAdapter->rTxPQueue[i][j]), + prDataPort[i][j]); + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TX_PORT_QUE); + break; + } + } + i++; + i %= BSS_DEFAULT_NUM; + } + } +#if QM_FORWARDING_FAIRNESS + prQM->u4HeadBssInfoIndex++; + prQM->u4HeadBssInfoIndex %= BSS_DEFAULT_NUM; +#endif +} + +#if CFG_SUPPORT_LOWLATENCY_MODE +/*----------------------------------------------------------------------------*/ +/*! + * @brief In this function, we'll pick high priority packet to data queue + * + * + * @param prAdapter Pointer to the Adapter structure. + * @param prDataPort Pointer to data queue + * + */ +/*----------------------------------------------------------------------------*/ +static void nicTxMsduPickHighPrioPkt(struct ADAPTER *prAdapter, + struct QUE *prDataPort0, + struct QUE *prDataPort1) +{ + struct QUE *prDataPort, *prTxQue; + struct MSDU_INFO *prMsduInfo; + struct sk_buff *prSkb; + int32_t i4TcIdx, i; + uint32_t u4QSize, u4Idx; + uint8_t ucPortIdx; + + for (i4TcIdx = TX_PORT_NUM - 1; i4TcIdx >= 0; i4TcIdx--) { + for (i = 0; i < BSS_DEFAULT_NUM; i++) { + prTxQue = &(prAdapter->rTxPQueue[i][i4TcIdx]); + u4QSize = prTxQue->u4NumElem; + for (u4Idx = 0; u4Idx < u4QSize; u4Idx++) { + QUEUE_REMOVE_HEAD(prTxQue, prMsduInfo, + struct MSDU_INFO *); + if (!prMsduInfo || !prMsduInfo->prPacket) { + QUEUE_INSERT_TAIL( + prTxQue, + (struct QUE_ENTRY *)prMsduInfo); + continue; + } + + ucPortIdx = halTxRingDataSelect( + prAdapter, prMsduInfo); + prDataPort = + (ucPortIdx == TX_RING_DATA1_IDX_1) ? + prDataPort1 : prDataPort0; + + prSkb = prMsduInfo->prPacket; + if (prSkb->mark == NIC_TX_SKB_PRIORITY_MARK1 || + (prSkb->mark & + BIT(NIC_TX_SKB_PRIORITY_MARK_BIT))) { + QUEUE_INSERT_TAIL( + prDataPort, + (struct QUE_ENTRY *)prMsduInfo); + } else { + QUEUE_INSERT_TAIL( + prTxQue, + (struct QUE_ENTRY *)prMsduInfo); + } + } + } + } +} +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief In this function, we'll write MSDU into HIF by Round-Robin + * + * + * @param prAdapter Pointer to the Adapter structure. + * + */ +/*----------------------------------------------------------------------------*/ +void nicTxMsduQueueByRR(struct ADAPTER *prAdapter) +{ + struct WIFI_VAR *prWifiVar; + struct QUE qDataPort0, qDataPort1, + arTempQue[BSS_DEFAULT_NUM][TX_PORT_NUM]; + struct QUE *prDataPort0, *prDataPort1, *prDataPort, *prTxQue; + struct MSDU_INFO *prMsduInfo; + uint32_t u4Idx, u4IsNotAllQueneEmpty, i, j; + uint8_t ucPortIdx; + uint32_t au4TxCnt[BSS_DEFAULT_NUM][TX_PORT_NUM], u4Offset = 0; + char aucLogBuf[512]; + struct BSS_INFO *prBssInfo; + struct QUE_MGT *prQM = &prAdapter->rQM; + + KAL_SPIN_LOCK_DECLARATION(); + + prWifiVar = &prAdapter->rWifiVar; + prDataPort0 = &qDataPort0; + prDataPort1 = &qDataPort1; + QUEUE_INITIALIZE(prDataPort0); + QUEUE_INITIALIZE(prDataPort1); + kalMemZero(aucLogBuf, 512); + + for (i = 0; i < BSS_DEFAULT_NUM; i++) { + for (u4Idx = 0; u4Idx < TX_PORT_NUM; u4Idx++) { + QUEUE_INITIALIZE(&arTempQue[i][u4Idx]); + au4TxCnt[i][u4Idx] = 0; + } + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + +#if CFG_SUPPORT_LOWLATENCY_MODE + /* Dequeue each TCQ to dataQ, high priority packet first */ + if (prWifiVar->ucLowLatencyPacketPriority & BIT(1)) + nicTxMsduPickHighPrioPkt(prAdapter, prDataPort0, prDataPort1); +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + + +#if QM_FORWARDING_FAIRNESS + i = prQM->u4HeadBssInfoIndex; +#else + i = 0; +#endif + for (j = 0; j < BSS_DEFAULT_NUM; j++) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, i); + /* Dequeue each TCQ to dataQ by round-robin */ + /* Check each TCQ is empty or not */ + u4IsNotAllQueneEmpty = BITS(0, TC_NUM - 1); + while (!prBssInfo->fgIsNetAbsent && u4IsNotAllQueneEmpty) { + u4Idx = prAdapter->u4TxHifResCtlIdx; + prTxQue = &(prAdapter->rTxPQueue[i][u4Idx]); + if (QUEUE_IS_NOT_EMPTY(prTxQue)) { + QUEUE_REMOVE_HEAD(prTxQue, prMsduInfo, + struct MSDU_INFO *); + if (prMsduInfo != NULL) { + ucPortIdx = halTxRingDataSelect( + prAdapter, prMsduInfo); + prDataPort = + (ucPortIdx == TX_RING_DATA1_IDX_1) ? + prDataPort1 : prDataPort0; + QUEUE_INSERT_TAIL(prDataPort, + (struct QUE_ENTRY *) prMsduInfo); + au4TxCnt[i][u4Idx]++; + } else { + /* unset empty queue */ + u4IsNotAllQueneEmpty &= ~BIT(u4Idx); + DBGLOG(NIC, WARN, "prMsduInfo NULL\n"); + } + } else { + /* unset empty queue */ + u4IsNotAllQueneEmpty &= ~BIT(u4Idx); + } + prAdapter->u4TxHifResCtlNum++; + if (prAdapter->u4TxHifResCtlNum >= + prAdapter->au4TxHifResCtl[u4Idx]) { + prAdapter->u4TxHifResCtlIdx++; + prAdapter->u4TxHifResCtlIdx %= TC_NUM; + prAdapter->u4TxHifResCtlNum = 0; + } + + } + i++; + i %= BSS_DEFAULT_NUM; + } +#if QM_FORWARDING_FAIRNESS + prQM->u4HeadBssInfoIndex++; + prQM->u4HeadBssInfoIndex %= BSS_DEFAULT_NUM; +#endif + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + + nicTxMsduQueue(prAdapter, 0, prDataPort0); + nicTxMsduQueue(prAdapter, 0, prDataPort1); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + /* Enque from dataQ to TCQ if TX don't finish */ + /* Need to reverse dataQ by TC first */ + while (QUEUE_IS_NOT_EMPTY(prDataPort0)) { + QUEUE_REMOVE_HEAD(prDataPort0, prMsduInfo, struct MSDU_INFO *); + QUEUE_INSERT_HEAD( + &arTempQue[prMsduInfo->ucBssIndex][prMsduInfo->ucTC], + (struct QUE_ENTRY *) prMsduInfo); + } + while (QUEUE_IS_NOT_EMPTY(prDataPort1)) { + QUEUE_REMOVE_HEAD(prDataPort1, prMsduInfo, struct MSDU_INFO *); + QUEUE_INSERT_HEAD( + &arTempQue[prMsduInfo->ucBssIndex][prMsduInfo->ucTC], + (struct QUE_ENTRY *) prMsduInfo); + } + + for (i = 0; i < BSS_DEFAULT_NUM; i++) { + for (u4Idx = 0; u4Idx < TX_PORT_NUM; u4Idx++) { + while (QUEUE_IS_NOT_EMPTY(&arTempQue[i][u4Idx])) { + QUEUE_REMOVE_HEAD(&arTempQue[i][u4Idx], + prMsduInfo, struct MSDU_INFO *); + QUEUE_INSERT_HEAD( + &prAdapter->rTxPQueue[i][u4Idx], + (struct QUE_ENTRY *) prMsduInfo); + } + } + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + + for (i = 0; i < BSS_DEFAULT_NUM; i++) { + for (u4Idx = 0; u4Idx < TX_PORT_NUM; u4Idx++) { + u4Offset += snprintf( + aucLogBuf + u4Offset, 512 - u4Offset, + "TC[%u]:%u ", u4Idx, au4TxCnt[i][u4Idx]); + } + } + DBGLOG_LIMITED(NIC, LOUD, "%s\n", aucLogBuf); +} + +uint32_t nicTxGetMsduPendingCnt(IN struct ADAPTER + *prAdapter) +{ +#if CFG_FIX_2_TX_PORT + return prAdapter->rTxP0Queue.u4NumElem + + prAdapter->rTxP1Queue.u4NumElem; +#else + int32_t i, j; + uint32_t retValue = 0; + + for (i = 0; i < BSS_DEFAULT_NUM; i++) + for (j = 0; j < TX_PORT_NUM; j++) + retValue += prAdapter->rTxPQueue[i][j].u4NumElem; + return retValue; +#endif +} + +#endif + +void nicTxComposeDescAppend(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + OUT uint8_t *prTxDescBuffer) +{ + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + + if (prChipInfo->prTxDescOps->fillNicAppend) + prChipInfo->prTxDescOps->fillNicAppend(prAdapter, + prMsduInfo, prTxDescBuffer); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief In this function, we'll compose the Tx descriptor of the MSDU. + * + * @param prAdapter Pointer to the Adapter structure. + * @param prMsduInfo Pointer to the Msdu info + * @param prTxDesc Pointer to the Tx descriptor buffer + * + * @retval VOID + */ +/*----------------------------------------------------------------------------*/ +void +nicTxComposeDesc( + IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN uint32_t u4TxDescLength, + IN u_int8_t fgIsTemplate, + OUT uint8_t *prTxDescBuffer) +{ + struct TX_DESC_OPS_T *prTxDescOps = prAdapter->chip_info->prTxDescOps; + + if (prTxDescOps->nic_txd_compose) + prTxDescOps->nic_txd_compose( + prAdapter, + prMsduInfo, + u4TxDescLength, + fgIsTemplate, + prTxDescBuffer); + else + DBGLOG(TX, ERROR, "%s:: no nic_txd_compose??\n", __func__); +} + +void +nicTxComposeSecurityFrameDesc( + IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, + OUT uint8_t *prTxDescBuffer, + OUT uint8_t *pucTxDescLength) +{ + struct TX_DESC_OPS_T *prTxDescOps = prAdapter->chip_info->prTxDescOps; + + if (prTxDescOps->nic_txd_compose_security_frame) + prTxDescOps->nic_txd_compose_security_frame( + prAdapter, + prCmdInfo, + prTxDescBuffer, + pucTxDescLength); + else + DBGLOG(TX, ERROR, "%s:: no nic_txd_compose_security_frame??\n", + __func__); +} + +void +nicTxForceAmsduForCert( + struct ADAPTER *prAdapter, + u_int8_t *prTxDescBuffer) +{ +#if (CFG_SUPPORT_802_11AX == 1) && (CFG_SUPPORT_CONNAC2X == 1) + struct HW_MAC_CONNAC2X_TX_DESC *prTxDesc = + (struct HW_MAC_CONNAC2X_TX_DESC *) prTxDescBuffer; + + if (fgEfuseCtrlAxOn == 1) { + if (prAdapter->rWifiVar.ucHeAmsduInAmpduTx && + prAdapter->rWifiVar.ucHeCertForceAmsdu) + HAL_MAC_CONNAC2X_TXD_SET_HW_AMSDU(prTxDesc); + } +#endif /* (CFG_SUPPORT_802_11AX == 1) && (CFG_SUPPORT_CONNAC2X == 1) */ +} + +u_int8_t nicTxIsTXDTemplateAllowed(IN struct ADAPTER + *prAdapter, IN struct MSDU_INFO *prMsduInfo, + IN struct STA_RECORD *prStaRec) +{ + if (prMsduInfo->fgIsTXDTemplateValid) { + if (prMsduInfo->fgIs802_1x) + return FALSE; + + if (prMsduInfo->ucRateMode != MSDU_RATE_MODE_AUTO) + return FALSE; + + if (!prStaRec) + return FALSE; + + if (prMsduInfo->ucControlFlag) + return FALSE; + + if (prMsduInfo->pfTxDoneHandler) + return FALSE; + + if (prAdapter->rWifiVar.ucDataTxRateMode) + return FALSE; + + return TRUE; + } + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief In this function, we'll compose the Tx descriptor of the MSDU. + * + * @param prAdapter Pointer to the Adapter structure. + * @param prMsduInfo Pointer to the Msdu info + * @param prTxDesc Pointer to the Tx descriptor buffer + * + * @retval VOID + */ +/*----------------------------------------------------------------------------*/ +void +nicTxFillDesc(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + OUT uint8_t *prTxDescBuffer, OUT uint32_t *pu4TxDescLength) +{ + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + void *prTxDesc = prTxDescBuffer; + void *prTxDescTemplate = NULL; + struct STA_RECORD *prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + uint32_t u4TxDescLength; +#if CFG_TCP_IP_CHKSUM_OFFLOAD + uint8_t ucChksumFlag = 0; +#endif + struct TX_DESC_OPS_T *prTxDescOps = prChipInfo->prTxDescOps; + + /* + * ------------------------------------------------------------------- + * Fill up common fileds + * ------------------------------------------------------------------- + */ + u4TxDescLength = NIC_TX_DESC_LONG_FORMAT_LENGTH; + + /* Get TXD from pre-allocated template */ + if (nicTxIsTXDTemplateAllowed(prAdapter, prMsduInfo, + prStaRec)) { + prTxDescTemplate = + prStaRec->aprTxDescTemplate[prMsduInfo->ucUserPriority]; + } + if (prTxDescTemplate) { + if (prMsduInfo->ucPacketType == TX_PACKET_TYPE_DATA) + kalMemCopy(prTxDesc, prTxDescTemplate, + u4TxDescLength + prChipInfo->txd_append_size); + else + kalMemCopy(prTxDesc, prTxDescTemplate, u4TxDescLength); + /* Overwrite fields for EOSP or More data */ + nicTxFillDescByPktOption(prAdapter, prMsduInfo, prTxDesc); + } else { /* Compose TXD by Msdu info */ + DBGLOG_LIMITED(NIC, TRACE, "Compose TXD by Msdu info\n"); +#if (UNIFIED_MAC_TX_FORMAT == 1) + if (prMsduInfo->eSrc == TX_PACKET_MGMT) + prMsduInfo->ucPacketFormat = TXD_PKT_FORMAT_COMMAND; + else + prMsduInfo->ucPacketFormat = prChipInfo->ucPacketFormat; +#endif /* UNIFIED_MAC_TX_FORMAT == 1 */ + nicTxComposeDesc(prAdapter, prMsduInfo, u4TxDescLength, + FALSE, prTxDescBuffer); + + /* Compose TxD append */ + if (prMsduInfo->ucPacketType == TX_PACKET_TYPE_DATA) + nicTxComposeDescAppend(prAdapter, prMsduInfo, + prTxDescBuffer + u4TxDescLength); + } + + nicTxForceAmsduForCert(prAdapter, (u_int8_t *)prTxDesc); + /* + * -------------------------------------------------------------------- + * Fill up remaining parts, per-packet variant fields + * -------------------------------------------------------------------- + */ + if (prTxDescOps->fillTxByteCount) + prTxDescOps->fillTxByteCount(prAdapter, + prMsduInfo, prTxDesc); + + /* Checksum offload */ +#if CFG_TCP_IP_CHKSUM_OFFLOAD + if (prAdapter->fgIsSupportCsumOffload + && prMsduInfo->eSrc == TX_PACKET_OS) { + if (prAdapter->u4CSUMFlags & + (CSUM_OFFLOAD_EN_TX_TCP | CSUM_OFFLOAD_EN_TX_UDP | + CSUM_OFFLOAD_EN_TX_IP)) { + ASSERT(prMsduInfo->prPacket); + kalQueryTxChksumOffloadParam(prMsduInfo->prPacket, + &ucChksumFlag); + if (prTxDescOps->nic_txd_chksum_op) + prTxDescOps->nic_txd_chksum_op( + prTxDesc, ucChksumFlag); + else + DBGLOG(TX, ERROR, + "%s:: no nic_txd_chksum_op??\n", + __func__); + } + } +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + /* Set EtherType & VLAN for non 802.11 frame */ + if (prTxDescOps->nic_txd_header_format_op) + prTxDescOps->nic_txd_header_format_op( + prTxDesc, prMsduInfo); + else + DBGLOG(TX, ERROR, + "%s:: no nic_txd_header_format_op??\n", + __func__); + + if (pu4TxDescLength) + *pu4TxDescLength = u4TxDescLength; +} + +void +nicTxFillDataDesc(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + uint8_t *pucOutputBuf; + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + + pucOutputBuf = skb_push((struct sk_buff *) + prMsduInfo->prPacket, + NIC_TX_DESC_AND_PADDING_LENGTH + + prChipInfo->txd_append_size); + + nicTxFillDesc(prAdapter, prMsduInfo, pucOutputBuf, NULL); + /* dump TXD to debug TX issue */ + if (prAdapter->rWifiVar.ucDataTxDone == 1) + halDumpTxdInfo(prAdapter, (uint32_t *)pucOutputBuf); +} + +void +nicTxCopyDesc(IN struct ADAPTER *prAdapter, + IN uint8_t *pucTarTxDesc, IN uint8_t *pucSrcTxDesc, + OUT uint8_t *pucTxDescLength) +{ + struct TX_DESC_OPS_T *prTxDescOps; + uint8_t ucTxDescLength; + + prTxDescOps = prAdapter->chip_info->prTxDescOps; + if (prTxDescOps->nic_txd_long_format_op(pucSrcTxDesc, FALSE)) + ucTxDescLength = NIC_TX_DESC_LONG_FORMAT_LENGTH; + else + ucTxDescLength = NIC_TX_DESC_SHORT_FORMAT_LENGTH; + + kalMemCopy(pucTarTxDesc, pucSrcTxDesc, ucTxDescLength); + + if (pucTxDescLength) + *pucTxDescLength = ucTxDescLength; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief In this function, we'll generate Tx descriptor template for each TID. + * + * @param prAdapter Pointer to the Adapter structure. + * @param prStaRec Pointer to the StaRec structure. + * + * @retval VOID + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxGenerateDescTemplate(IN struct ADAPTER + *prAdapter, IN struct STA_RECORD *prStaRec) +{ + uint8_t ucTid; + uint8_t ucTc; + uint32_t u4TxDescSize, u4TxDescAppendSize; + void *prTxDesc; + struct MSDU_INFO *prMsduInfo; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + + /* Free previous template, first */ + /* nicTxFreeDescTemplate(prAdapter, prStaRec); */ + for (ucTid = 0; ucTid < TX_DESC_TID_NUM; ucTid++) + prStaRec->aprTxDescTemplate[ucTid] = NULL; + + prMsduInfo = cnmPktAlloc(prAdapter, 0); + + if (!prMsduInfo) + return WLAN_STATUS_RESOURCES; + + prChipInfo = prAdapter->chip_info; + + /* Fill up MsduInfo template */ + prMsduInfo->eSrc = TX_PACKET_OS; + prMsduInfo->fgIs802_11 = FALSE; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_1x_NonProtected = FALSE; + prMsduInfo->fgIs802_3 = FALSE; + prMsduInfo->fgIsVlanExists = FALSE; + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->prPacket = NULL; + prMsduInfo->u2FrameLength = 0; + prMsduInfo->u4Option = 0; + prMsduInfo->u4FixedRateOption = 0; + prMsduInfo->ucRateMode = MSDU_RATE_MODE_AUTO; + prMsduInfo->ucBssIndex = prStaRec->ucBssIndex; + prMsduInfo->ucPacketType = TX_PACKET_TYPE_DATA; + prMsduInfo->ucPacketFormat = prChipInfo->ucPacketFormat; + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucPID = NIC_TX_DESC_PID_RESERVED; + + u4TxDescSize = NIC_TX_DESC_LONG_FORMAT_LENGTH; + u4TxDescAppendSize = prChipInfo->txd_append_size; + + DBGLOG(QM, INFO, + "Generate TXD template for STA[%u] QoS[%u]\n", + prStaRec->ucIndex, prStaRec->fgIsQoS); + + /* Generate new template */ + if (prStaRec->fgIsQoS) { + /* For QoS STA, generate 8 TXD template (TID0~TID7) */ + for (ucTid = 0; ucTid < TX_DESC_TID_NUM; ucTid++) { + + if (prAdapter->rWifiVar.ucTcRestrict < TC_NUM) + ucTc = prAdapter->rWifiVar.ucTcRestrict; + else + ucTc = + arNetwork2TcResource[ + prStaRec->ucBssIndex][ + aucTid2ACI[ucTid]]; + u4TxDescSize = arTcTrafficSettings[ucTc].u4TxDescLength; + + /* Include TxD append */ + prTxDesc = kalMemAlloc( + u4TxDescSize + u4TxDescAppendSize, + VIR_MEM_TYPE); + DBGLOG(QM, TRACE, "STA[%u] TID[%u] TxDTemp[0x%p]\n", + prStaRec->ucIndex, ucTid, prTxDesc); + if (!prTxDesc) { + rStatus = WLAN_STATUS_RESOURCES; + break; + } + + /* Update MsduInfo TID & TC */ + prMsduInfo->ucUserPriority = ucTid; + prMsduInfo->ucTC = ucTc; + + /* Compose Tx desc template */ + nicTxComposeDesc( + prAdapter, prMsduInfo, u4TxDescSize, TRUE, + (uint8_t *) prTxDesc); + + /* Fill TxD append */ + nicTxComposeDescAppend(prAdapter, prMsduInfo, + ((uint8_t *)prTxDesc + u4TxDescSize)); + + prStaRec->aprTxDescTemplate[ucTid] = prTxDesc; + } + } else { + /* For non-QoS STA, generate 1 TXD template (TID0) */ + do { + if (prAdapter->rWifiVar.ucTcRestrict < TC_NUM) + ucTc = prAdapter->rWifiVar.ucTcRestrict; + else + ucTc = arNetwork2TcResource[ + prStaRec->ucBssIndex][ + NET_TC_WMM_AC_BE_INDEX]; + + /* ucTxDescSize = + * arTcTrafficSettings[ucTc].ucTxDescLength; + */ + u4TxDescSize = NIC_TX_DESC_LONG_FORMAT_LENGTH; + + prTxDesc = kalMemAlloc( + u4TxDescSize + u4TxDescAppendSize, + VIR_MEM_TYPE); + if (!prTxDesc) { + rStatus = WLAN_STATUS_RESOURCES; + break; + } + /* Update MsduInfo TID & TC */ + prMsduInfo->ucUserPriority = 0; + prMsduInfo->ucTC = ucTc; + + /* Compose Tx desc template */ + nicTxComposeDesc( + prAdapter, prMsduInfo, u4TxDescSize, TRUE, + (uint8_t *) prTxDesc); + + /* Fill TxD append */ + nicTxComposeDescAppend(prAdapter, prMsduInfo, + ((uint8_t *)prTxDesc + u4TxDescSize)); + + for (ucTid = 0; ucTid < TX_DESC_TID_NUM; ucTid++) { + prStaRec->aprTxDescTemplate[ucTid] = prTxDesc; + DBGLOG(QM, TRACE, + "TXD template: TID[%u] Ptr[0x%p]\n", + ucTid, prTxDesc); + } + } while (FALSE); + } + + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief In this function, we'll free Tx descriptor template for each TID. + * + * @param prAdapter Pointer to the Adapter structure. + * @param prStaRec Pointer to the StaRec structure. + * + * @retval VOID + */ +/*----------------------------------------------------------------------------*/ +void nicTxFreeDescTemplate(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + struct TX_DESC_OPS_T *prTxDescOps; + uint8_t ucTid; + uint8_t ucTxDescSize; + void *prTxDesc; + + DBGLOG(QM, TRACE, "Free TXD template for STA[%u] QoS[%u]\n", + prStaRec->ucIndex, prStaRec->fgIsQoS); + + prTxDescOps = prAdapter->chip_info->prTxDescOps; + if (prStaRec->fgIsQoS) { + for (ucTid = 0; ucTid < TX_DESC_TID_NUM; ucTid++) { + prTxDesc = prStaRec->aprTxDescTemplate[ucTid]; + + if (prTxDesc) { + if (prTxDescOps->nic_txd_long_format_op( + prTxDesc, FALSE)) + ucTxDescSize = + NIC_TX_DESC_LONG_FORMAT_LENGTH; + else + ucTxDescSize = + NIC_TX_DESC_SHORT_FORMAT_LENGTH; + + kalMemFree(prTxDesc, VIR_MEM_TYPE, + ucTxDescSize); + + prTxDesc = + prStaRec->aprTxDescTemplate[ucTid] = + NULL; + } + } + } else { + prTxDesc = prStaRec->aprTxDescTemplate[0]; + if (prTxDesc) { + if (prTxDescOps->nic_txd_long_format_op( + prTxDesc, FALSE)) + ucTxDescSize = NIC_TX_DESC_LONG_FORMAT_LENGTH; + else + ucTxDescSize = NIC_TX_DESC_SHORT_FORMAT_LENGTH; + + kalMemFree(prTxDesc, VIR_MEM_TYPE, ucTxDescSize); + prTxDesc = NULL; + } + for (ucTid = 0; ucTid < TX_DESC_TID_NUM; ucTid++) + prStaRec->aprTxDescTemplate[ucTid] = NULL; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief In this function, we'll Update H/W AMSDU filed of TxD template. + * + * @param prAdapter Pointer to the Adapter structure. + * @param prStaRec Pointer to the StaRec structure. + * @param ucTid Select target Tid template + * @param ucSet Set or clear + * + * @retval VOID + */ +/*----------------------------------------------------------------------------*/ +void nicTxSetHwAmsduDescTemplate( + IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN uint8_t ucTid, + IN u_int8_t fgSet) +{ + struct TX_DESC_OPS_T *prTxDescOps = prAdapter->chip_info->prTxDescOps; + + if (prTxDescOps->nic_txd_set_hw_amsdu_template) + prTxDescOps->nic_txd_set_hw_amsdu_template( + prAdapter, + prStaRec, + ucTid, + fgSet); + else + DBGLOG(TX, ERROR, + "%s:: no nic_txd_set_hw_amsdu_template??\n", + __func__); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Write data to device done + * + * \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. + * \param[in] prQue msdu info que to be free + * + * \retval TRUE operation success + * \retval FALSE operation fail + */ +/*----------------------------------------------------------------------------*/ +void nicTxMsduDoneCb(IN struct GLUE_INFO *prGlueInfo, + IN struct QUE *prQue) +{ + struct MSDU_INFO *prMsduInfo, *prNextMsduInfo; + struct QUE rFreeQueue; + struct QUE *prFreeQueue; + /* P_NATIVE_PACKET prNativePacket;*/ + struct TX_CTRL *prTxCtrl; + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + prFreeQueue = &rFreeQueue; + QUEUE_INITIALIZE(prFreeQueue); + + if (prQue && prQue->u4NumElem > 0) { + prMsduInfo = (struct MSDU_INFO *) QUEUE_GET_HEAD(prQue); + + while (prMsduInfo) { + prNextMsduInfo = + (struct MSDU_INFO *) QUEUE_GET_NEXT_ENTRY( + &prMsduInfo->rQueEntry); + +#if 1 + nicTxFreePacket(prAdapter, prMsduInfo, FALSE); +#else + prNativePacket = prMsduInfo->prPacket; + + /* Free MSDU_INFO */ + if (prMsduInfo->eSrc == TX_PACKET_OS) { + wlanTxProfilingTagMsdu(prAdapter, prMsduInfo, + TX_PROF_TAG_DRV_DEQUE); + kalSendComplete( + prAdapter->prGlueInfo, prNativePacket, + WLAN_STATUS_SUCCESS); + prMsduInfo->prPacket = NULL; + } else if (prMsduInfo->eSrc == TX_PACKET_FORWARDING) { + GLUE_DEC_REF_CNT( + prTxCtrl->i4PendingFwdFrameCount); + } +#endif + + if (!prMsduInfo->pfTxDoneHandler) + QUEUE_INSERT_TAIL(prFreeQueue, + (struct QUE_ENTRY *) prMsduInfo); + + prMsduInfo = prNextMsduInfo; + } + + wlanTxProfilingTagMsdu(prAdapter, + (struct MSDU_INFO *) QUEUE_GET_HEAD(&rFreeQueue), + TX_PROF_TAG_DRV_FREE); + + nicTxReturnMsduInfo(prAdapter, + (struct MSDU_INFO *) + QUEUE_GET_HEAD(&rFreeQueue)); + } +} + +void nicHifTxMsduDoneCb(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct TX_CTRL *prTxCtrl; + + if (!prAdapter || !prMsduInfo) + return; + + prTxCtrl = &prAdapter->rTxCtrl; + + if (prMsduInfo->pfTxDoneHandler) { + KAL_SPIN_LOCK_DECLARATION(); + + /* Record native packet pointer for Tx done log */ + WLAN_GET_FIELD_32(&prMsduInfo->prPacket, + &prMsduInfo->u4TxDoneTag); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TXING_MGMT_LIST); + QUEUE_INSERT_TAIL(&(prTxCtrl->rTxMgmtTxingQueue), + (struct QUE_ENTRY *) prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TXING_MGMT_LIST); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxMsduQueue(IN struct ADAPTER *prAdapter, + uint8_t ucPortIdx, struct QUE *prQue) +{ + struct MSDU_INFO *prMsduInfo; + struct TX_CTRL *prTxCtrl; + + ASSERT(prAdapter); + ASSERT(prQue); + + prTxCtrl = &prAdapter->rTxCtrl; + +#if CFG_HIF_STATISTICS + prTxCtrl->u4TotalTxAccessNum++; + prTxCtrl->u4TotalTxPacketNum += prQue->u4NumElem; +#endif + + while (QUEUE_IS_NOT_EMPTY(prQue)) { + u_int8_t fgTxDoneHandler; + + QUEUE_REMOVE_HEAD(prQue, prMsduInfo, struct MSDU_INFO *); + + if (prMsduInfo == NULL) { + DBGLOG(TX, WARN, "prMsduInfo is NULL\n"); + break; + } + + if (!halTxIsDataBufEnough(prAdapter, prMsduInfo)) { + QUEUE_INSERT_HEAD(prQue, + (struct QUE_ENTRY *) prMsduInfo); + break; + } + + fgTxDoneHandler = prMsduInfo->pfTxDoneHandler ? + TRUE : FALSE; + +#if !CFG_SUPPORT_MULTITHREAD + nicTxFillDataDesc(prAdapter, prMsduInfo); +#endif + + if (prMsduInfo->eSrc == TX_PACKET_OS) { + wlanTxProfilingTagMsdu(prAdapter, prMsduInfo, + TX_PROF_TAG_DRV_TX_DONE); + wlanFillTimestamp(prAdapter, prMsduInfo->prPacket, + PHASE_HIF_TX); + } + + if (!fgTxDoneHandler) + wlanTxProfilingTagMsdu(prAdapter, prMsduInfo, + TX_PROF_TAG_DRV_TX_DONE); + +#if (CFG_SUPPORT_STATISTICS == 1) + StatsEnvTxTime2Hif(prAdapter, prMsduInfo); +#endif + HAL_WRITE_TX_DATA(prAdapter, prMsduInfo); + } + + HAL_KICK_TX_DATA(prAdapter); + + 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxCmd(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t ucTC) +{ + struct MSDU_INFO *prMsduInfo; + struct TX_CTRL *prTxCtrl; + struct sk_buff *skb; + struct TX_DESC_OPS_T *prTxDescOps; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + prTxDescOps = prAdapter->chip_info->prTxDescOps; + prTxCtrl = &prAdapter->rTxCtrl; +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanTraceTxCmd(prCmdInfo); +#endif + + if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME || + prCmdInfo->eCmdType == COMMAND_TYPE_DATA_FRAME) { + prMsduInfo = prCmdInfo->prMsduInfo; + + /* dump TXD to debug TX issue */ + if (prAdapter->rWifiVar.ucDataTxDone == 3) + halDumpTxdInfo(prAdapter, + (uint32_t *)prMsduInfo->aucTxDescBuffer); + + prCmdInfo->pucTxd = prMsduInfo->aucTxDescBuffer; + if (prTxDescOps->nic_txd_long_format_op( + prMsduInfo->aucTxDescBuffer, FALSE)) + prCmdInfo->u4TxdLen = NIC_TX_DESC_LONG_FORMAT_LENGTH; + else + prCmdInfo->u4TxdLen = NIC_TX_DESC_SHORT_FORMAT_LENGTH; + + skb = (struct sk_buff *)prMsduInfo->prPacket; + prCmdInfo->pucTxp = skb->data; + prCmdInfo->u4TxpLen = skb->len; + + HAL_WRITE_TX_CMD(prAdapter, prCmdInfo, ucTC); + + prMsduInfo->prPacket = NULL; + + DBGLOG_LIMITED(INIT, TRACE, + "TX Data Frame: BSS[%u] WIDX:PID[%u:%u] SEQ[%u] STA[%u] RSP[%u]\n", + prMsduInfo->ucBssIndex, prMsduInfo->ucWlanIndex, + prMsduInfo->ucPID, + prMsduInfo->ucTxSeqNum, prMsduInfo->ucStaRecIndex, + prMsduInfo->pfTxDoneHandler ? TRUE : FALSE); + + if (prMsduInfo->pfTxDoneHandler) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TXING_MGMT_LIST); + QUEUE_INSERT_TAIL(&(prTxCtrl->rTxMgmtTxingQueue), + (struct QUE_ENTRY *) prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TXING_MGMT_LIST); + } else { + /* Only return MSDU_INFO */ + /* NativePacket will be freed at + * SEC frame CMD callback + */ + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } + + } else if (prCmdInfo->eCmdType == + COMMAND_TYPE_MANAGEMENT_FRAME) { + prMsduInfo = prCmdInfo->prMsduInfo; + + ASSERT(prMsduInfo->fgIs802_11 == TRUE); + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + + /* dump TXD to debug TX issue */ + if (prAdapter->rWifiVar.ucDataTxDone == 3) + halDumpTxdInfo(prAdapter, + (uint32_t *)prMsduInfo->aucTxDescBuffer); + + prCmdInfo->pucTxd = prMsduInfo->aucTxDescBuffer; + if (prTxDescOps->nic_txd_long_format_op( + prMsduInfo->aucTxDescBuffer, FALSE)) + prCmdInfo->u4TxdLen = NIC_TX_DESC_LONG_FORMAT_LENGTH; + else + prCmdInfo->u4TxdLen = NIC_TX_DESC_SHORT_FORMAT_LENGTH; + + prCmdInfo->pucTxp = prMsduInfo->prPacket; + prCmdInfo->u4TxpLen = prMsduInfo->u2FrameLength; + + HAL_WRITE_TX_CMD(prAdapter, prCmdInfo, ucTC); + /* <4> Management Frame Post-Processing */ + GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum); + + DBGLOG(INIT, TRACE, + "TX MGMT Frame: BSS[%u] WIDX:PID[%u:%u] SEQ[%u] STA[%u] RSP[%u]\n", + prMsduInfo->ucBssIndex, prMsduInfo->ucWlanIndex, + prMsduInfo->ucPID, + prMsduInfo->ucTxSeqNum, prMsduInfo->ucStaRecIndex, + prMsduInfo->pfTxDoneHandler ? TRUE : FALSE); + + if (prMsduInfo->pfTxDoneHandler) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TXING_MGMT_LIST); + QUEUE_INSERT_TAIL(&(prTxCtrl->rTxMgmtTxingQueue), + (struct QUE_ENTRY *) prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TXING_MGMT_LIST); + } else { + cnmMgtPktFree(prAdapter, prMsduInfo); + } + + } else { + prCmdInfo->pucTxd = prCmdInfo->pucInfoBuffer; + prCmdInfo->u4TxdLen = prCmdInfo->u2InfoBufLen; + prCmdInfo->pucTxp = NULL; + prCmdInfo->u4TxpLen = 0; + + HAL_WRITE_TX_CMD(prAdapter, prCmdInfo, ucTC); + } + + 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 struct ADAPTER *prAdapter, + IN u_int8_t fgProcTxDoneHandler) +{ + struct TX_CTRL *prTxCtrl; + struct MSDU_INFO *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, + struct MSDU_INFO *); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + if (prMsduInfo) { + DBGLOG(TX, TRACE, + "%s: Get Msdu WIDX:PID[%u:%u] SEQ[%u] from Pending Q\n", + __func__, prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, + prMsduInfo->ucTxSeqNum); + + /* invoke done handler */ + if (prMsduInfo->pfTxDoneHandler && fgProcTxDoneHandler) + prMsduInfo->pfTxDoneHandler( + prAdapter, prMsduInfo, + TX_RESULT_DROPPED_IN_DRIVER); + + nicTxFreeMsduInfoPacket(prAdapter, prMsduInfo); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } else { + break; + } + } while (TRUE); + +} /* end of nicTxRelease() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Process the TX Done interrupt and pull in more pending frames in SW + * Queues for transmission. + * + * @param prAdapter Pointer to the Adapter structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicProcessTxInterrupt(IN struct ADAPTER *prAdapter) +{ + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; + + prAdapter->prGlueInfo->IsrTxCnt++; + halProcessTxInterrupt(prAdapter); + + if (halIsHifStateSuspend(prAdapter)) + DBGLOG(TX, WARN, "Suspend TX INT\n"); + + /* Indicate Service Thread */ + if (kalGetTxPendingCmdCount(prAdapter->prGlueInfo) > 0 + || wlanGetTxPendingFrameCount(prAdapter) > 0) + kalSetEvent(prAdapter->prGlueInfo); + + /* SER break point */ + if (nicSerIsTxStop(prAdapter)) { + /* Skip following Tx handling */ + return; + } + + /* TX Commands */ + if (kalGetTxPendingCmdCount(prAdapter->prGlueInfo)) + wlanTxCmdMthread(prAdapter); + + /* Process TX data packet to HIF */ + if (nicTxGetMsduPendingCnt(prAdapter) >= + prWifiVar->u4TxIntThCount) + nicTxMsduQueueMthread(prAdapter); +} /* end of nicProcessTxInterrupt() */ + +void nicTxFreePacket(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN u_int8_t fgDrop) +{ + void *prNativePacket; + struct TX_CTRL *prTxCtrl; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + + prNativePacket = prMsduInfo->prPacket; + + wlanTxProfilingTagMsdu(prAdapter, prMsduInfo, TX_PROF_TAG_DRV_FREE); + + if (fgDrop) + rStatus = WLAN_STATUS_FAILURE; + + if (prMsduInfo->eSrc == TX_PACKET_OS) { + if (prNativePacket) + kalSendComplete(prAdapter->prGlueInfo, prNativePacket, + rStatus); + if (fgDrop) + wlanUpdateTxStatistics(prAdapter, prMsduInfo, + TRUE); /*get per-AC Tx drop packets */ + } else if (prMsduInfo->eSrc == TX_PACKET_MGMT) { + if (prMsduInfo->pfTxDoneHandler) + prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, + TX_RESULT_DROPPED_IN_DRIVER); + if (prNativePacket) + cnmMemFree(prAdapter, prNativePacket); + } else if (prMsduInfo->eSrc == TX_PACKET_FORWARDING) { + GLUE_DEC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount); + GLUE_DEC_REF_CNT(prTxCtrl + ->i4PendingFwdFrameWMMCount[ + aucACI2TxQIdx[aucTid2ACI[prMsduInfo->ucUserPriority]]]); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfoListHead) +{ + void *prNativePacket; + struct MSDU_INFO *prMsduInfo = prMsduInfoListHead; + struct TX_CTRL *prTxCtrl; + + ASSERT(prAdapter); + ASSERT(prMsduInfoListHead); + + prTxCtrl = &prAdapter->rTxCtrl; + + while (prMsduInfo) { + prNativePacket = prMsduInfo->prPacket; + +#if 1 + nicTxFreePacket(prAdapter, prMsduInfo, TRUE); +#else + if (prMsduInfo->eSrc == TX_PACKET_OS) { + if (prNativePacket) + kalSendComplete( + prAdapter->prGlueInfo, prNativePacket, + WLAN_STATUS_FAILURE); + /*get per-AC Tx drop packets */ + wlanUpdateTxStatistics(prAdapter, prMsduInfo, TRUE); + } else if (prMsduInfo->eSrc == TX_PACKET_MGMT) { + if (prMsduInfo->pfTxDoneHandler) + prMsduInfo->pfTxDoneHandler( + prAdapter, prMsduInfo, + TX_RESULT_DROPPED_IN_DRIVER); + if (prNativePacket) + cnmMemFree(prAdapter, prNativePacket); + } else if (prMsduInfo->eSrc == TX_PACKET_FORWARDING) { + GLUE_DEC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount); + } +#endif + prMsduInfo = (struct MSDU_INFO *) QUEUE_GET_NEXT_ENTRY(( + struct QUE_ENTRY *) prMsduInfo); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief this function returns P_MSDU_INFO_T of MsduInfoList to + * TxCtrl->rfreeMsduInfoList + * + * @param prAdapter Pointer to the Adapter structure. + * @param prMsduInfoList a link list of P_MSDU_INFO_T + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicTxReturnMsduInfo(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfoListHead) +{ + struct TX_CTRL *prTxCtrl; + struct MSDU_INFO *prMsduInfo = prMsduInfoListHead, + *prNextMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + while (prMsduInfo) { + prNextMsduInfo = (struct MSDU_INFO *) QUEUE_GET_NEXT_ENTRY(( + struct QUE_ENTRY *) prMsduInfo); + + switch (prMsduInfo->eSrc) { + case TX_PACKET_FORWARDING: + wlanReturnPacket(prAdapter, prMsduInfo->prPacket); + break; + case TX_PACKET_OS: + case TX_PACKET_OS_OID: + case TX_PACKET_MGMT: + default: + break; + } + + /* Reset MSDU_INFO fields */ + kalMemZero(prMsduInfo, sizeof(struct MSDU_INFO)); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TX_MSDU_INFO_LIST); + QUEUE_INSERT_TAIL(&prTxCtrl->rFreeMsduInfoList, + (struct QUE_ENTRY *) prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TX_MSDU_INFO_LIST); + prMsduInfo = prNextMsduInfo; + }; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief this function fills packet information to P_MSDU_INFO_T + * + * @param prAdapter Pointer to the Adapter structure. + * @param prMsduInfo P_MSDU_INFO_T + * @param prPacket P_NATIVE_PACKET + * + * @retval TRUE Success to extract information + * @retval FALSE Fail to extract correct information + */ +/*----------------------------------------------------------------------------*/ +u_int8_t nicTxFillMsduInfo(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN void *prPacket) +{ + struct GLUE_INFO *prGlueInfo; + + ASSERT(prAdapter); + + kalMemZero(prMsduInfo, sizeof(struct MSDU_INFO)); + + prGlueInfo = prAdapter->prGlueInfo; + ASSERT(prGlueInfo); + + kalGetEthDestAddr(prAdapter->prGlueInfo, prPacket, + prMsduInfo->aucEthDestAddr); + + prMsduInfo->prPacket = prPacket; + prMsduInfo->ucBssIndex = GLUE_GET_PKT_BSS_IDX(prPacket); +#if CFG_SUPPORT_WIFI_SYSDVT + if (prAdapter->ucTxTestUP != TX_TEST_UP_UNDEF) + prMsduInfo->ucUserPriority = prAdapter->ucTxTestUP; + else +#endif /* CFG_SUPPORT_WIFI_SYSDVT */ + prMsduInfo->ucUserPriority = GLUE_GET_PKT_TID(prPacket); + prMsduInfo->ucMacHeaderLength = GLUE_GET_PKT_HEADER_LEN( + prPacket); + prMsduInfo->u2FrameLength = (uint16_t) + GLUE_GET_PKT_FRAME_LEN(prPacket); + prMsduInfo->u4PageCount = nicTxGetPageCount(prAdapter, + prMsduInfo->u2FrameLength, FALSE); + + if (GLUE_IS_PKT_FLAG_SET(prPacket)) { + prMsduInfo->fgIs802_1x = GLUE_TEST_PKT_FLAG(prPacket, + ENUM_PKT_1X) ? TRUE : FALSE; + prMsduInfo->fgIs802_1x_NonProtected = + GLUE_TEST_PKT_FLAG(prPacket, + ENUM_PKT_NON_PROTECTED_1X) ? TRUE : FALSE; + prMsduInfo->fgIs802_3 = GLUE_TEST_PKT_FLAG(prPacket, + ENUM_PKT_802_3) ? TRUE : FALSE; + prMsduInfo->fgIsVlanExists = GLUE_TEST_PKT_FLAG(prPacket, + ENUM_PKT_VLAN_EXIST) ? TRUE : FALSE; + + if (prMsduInfo->fgIs802_1x) + prMsduInfo->eEapolKeyType = secGetEapolKeyType((( + struct sk_buff *)prPacket)->data); + + if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_DHCP) + && prAdapter->rWifiVar.ucDhcpTxDone) + prMsduInfo->ucPktType = ENUM_PKT_DHCP; + else if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_ARP) + && prAdapter->rWifiVar.ucArpTxDone) + prMsduInfo->ucPktType = ENUM_PKT_ARP; + else if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_1X)) + prMsduInfo->ucPktType = ENUM_PKT_1X; + else if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_ICMP)) + prMsduInfo->ucPktType = ENUM_PKT_ICMP; + else if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_TDLS)) + prMsduInfo->ucPktType = ENUM_PKT_TDLS; + else if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_DNS)) + prMsduInfo->ucPktType = ENUM_PKT_DNS; + +#if (CFG_SUPPORT_DMASHDL_SYSDVT) + if (prMsduInfo->ucPktType != ENUM_PKT_ICMP) { + /* blocking non ICMP packets at DMASHDL DVT items */ + if (DMASHDL_DVT_ALLOW_PING_ONLY(prAdapter)) + return FALSE; + } +#endif + if (prMsduInfo->ucPktType != 0) { + prMsduInfo->pfTxDoneHandler = wlanPktTxDone; + prMsduInfo->ucTxSeqNum = GLUE_GET_PKT_SEQ_NO(prPacket); + } + +#if CFG_SUPPORT_WIFI_SYSDVT + if (prAdapter->ucTxTestUP != TX_TEST_UP_UNDEF) + ; + else +#endif /* CFG_SUPPORT_WIFI_SYSDVT */ + if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_DHCP) || + GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_ARP) || + GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_1X)) { + /* Set BSS/STA lowest basic rate */ + prMsduInfo->ucRateMode = MSDU_RATE_MODE_LOWEST_RATE; + } + } + + /* Add dummy Tx done */ + if ((prAdapter->rWifiVar.ucDataTxDone == 1) + && (prMsduInfo->pfTxDoneHandler == NULL)) + prMsduInfo->pfTxDoneHandler = nicTxDummyTxDone; + + prMsduInfo->pfHifTxMsduDoneCb = nicHifTxMsduDoneCb; + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxAdjustTcq(IN struct ADAPTER *prAdapter) +{ +#if CFG_SUPPORT_MULTITHREAD + struct TX_TCQ_ADJUST rTcqAdjust; + struct TX_CTRL *prTxCtrl; + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + qmAdjustTcQuotasMthread(prAdapter, &rTcqAdjust, + &prTxCtrl->rTc); + +#else + + uint32_t u4Num; + struct TX_TCQ_ADJUST rTcqAdjust; + struct TX_CTRL *prTxCtrl; + struct TX_TCQ_STATUS *prTcqStatus; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + prTcqStatus = &prAdapter->rTxCtrl.rTc; + ASSERT(prTxCtrl); + + if (qmAdjustTcQuotas(prAdapter, &rTcqAdjust, + &prTxCtrl->rTc)) { + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + for (u4Num = 0; u4Num < TC_NUM; u4Num++) { + /* Page count */ + prTxCtrl->rTc.au4FreePageCount[u4Num] += + (rTcqAdjust.ai4Variation[u4Num] * + NIC_TX_MAX_PAGE_PER_FRAME); + prTxCtrl->rTc.au4MaxNumOfPage[u4Num] += + (rTcqAdjust.ai4Variation[u4Num] * + NIC_TX_MAX_PAGE_PER_FRAME); + + /* Buffer count */ + prTxCtrl->rTc.au4FreeBufferCount[u4Num] += + rTcqAdjust.ai4Variation[u4Num]; + prTxCtrl->rTc.au4MaxNumOfBuffer[u4Num] += + rTcqAdjust.ai4Variation[u4Num]; + + ASSERT(prTxCtrl->rTc.au4FreeBufferCount[u4Num] >= 0); + ASSERT(prTxCtrl->rTc.au4MaxNumOfBuffer[u4Num] >= 0); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); +#if 0 + DBGLOG(TX, LOUD, + "TCQ Status Free Page:Buf[%03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u]\n", + prTcqStatus->au4FreePageCount[TC0_INDEX], + prTcqStatus->au4FreeBufferCount[TC0_INDEX], + prTcqStatus->au4FreePageCount[TC1_INDEX], + prTcqStatus->au4FreeBufferCount[TC1_INDEX], + prTcqStatus->au4FreePageCount[TC2_INDEX], + prTcqStatus->au4FreeBufferCount[TC2_INDEX], + prTcqStatus->au4FreePageCount[TC3_INDEX], + prTcqStatus->au4FreeBufferCount[TC3_INDEX], + prTcqStatus->au4FreePageCount[TC4_INDEX], + prTcqStatus->au4FreeBufferCount[TC4_INDEX], + prTcqStatus->au4FreePageCount[TC5_INDEX], + prTcqStatus->au4FreeBufferCount[TC5_INDEX]); +#endif + DBGLOG(TX, LOUD, + "TCQ Status Max Page:Buf[%03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u]\n", + prTcqStatus->au4MaxNumOfPage[TC0_INDEX], + prTcqStatus->au4MaxNumOfBuffer[TC0_INDEX], + prTcqStatus->au4MaxNumOfPage[TC1_INDEX], + prTcqStatus->au4MaxNumOfBuffer[TC1_INDEX], + prTcqStatus->au4MaxNumOfPage[TC2_INDEX], + prTcqStatus->au4MaxNumOfBuffer[TC2_INDEX], + prTcqStatus->au4MaxNumOfPage[TC3_INDEX], + prTcqStatus->au4MaxNumOfBuffer[TC3_INDEX], + prTcqStatus->au4MaxNumOfPage[TC4_INDEX], + prTcqStatus->au4MaxNumOfBuffer[TC4_INDEX]); + + } +#endif + 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 + */ +/*----------------------------------------------------------------------------*/ + +uint32_t nicTxFlush(IN struct ADAPTER *prAdapter) +{ + struct MSDU_INFO *prMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + if (HAL_IS_TX_DIRECT(prAdapter)) { + nicTxDirectClearAllStaPsQ(prAdapter); + } else { + /* ask Per STA/AC queue to be fllushed + * and return all queued packets + */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + prMsduInfo = qmFlushTxQueues(prAdapter); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + + if (prMsduInfo != NULL) { + nicTxFreeMsduInfoPacket(prAdapter, prMsduInfo); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } + } + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_ENABLE_FW_DOWNLOAD +/*----------------------------------------------------------------------------*/ +/*! + * \brief In this function, we'll write Command(CMD_INFO_T) into HIF. + * However this function is used for INIT_CMD. + * + * In order to avoid further maintenance issues, these 2 functions + * are separated + * + * @param prAdapter Pointer to the Adapter structure. + * @param prPacketInfo Pointer of CMD_INFO_T + * @param ucTC Specify the resource of TC + * + * @retval WLAN_STATUS_SUCCESS Bus access ok. + * @retval WLAN_STATUS_FAILURE Bus access fail. + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxInitCmd(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint16_t u2Port) +{ + uint16_t u2OverallBufferLength; + /* Pointer to Transmit Data Structure Frame */ + uint8_t *pucOutputBuf = (uint8_t *) NULL; + struct TX_CTRL *prTxCtrl; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prChipInfo = prAdapter->chip_info; + prTxCtrl = &prAdapter->rTxCtrl; + pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; + u2OverallBufferLength = TFCB_FRAME_PAD_TO_DW(( + prCmdInfo->u2InfoBufLen + prChipInfo->u2HifTxdSize) & + (uint16_t) + HIF_TX_HDR_TX_BYTE_COUNT_MASK); + + /* <0> Copy HIF TXD if need */ + HAL_WRITE_HIF_TXD(prChipInfo, pucOutputBuf, + prCmdInfo->u2InfoBufLen); + + /* <1> Copy CMD Header to command buffer + * (by using pucCoalescingBufCached) + */ + kalMemCopy((void *)&pucOutputBuf[prChipInfo->u2HifTxdSize], + (void *) prCmdInfo->pucInfoBuffer, prCmdInfo->u2InfoBufLen); + + ASSERT(u2OverallBufferLength <= + prAdapter->u4CoalescingBufCachedSize); + + GLUE_INC_REF_CNT(prAdapter->rHifStats.u4CmdInCount); + /* <2> Write frame to data port */ + HAL_WRITE_TX_PORT(prAdapter, u2Port/*NIC_TX_INIT_CMD_PORT*/, + (uint32_t) u2OverallBufferLength, + (uint8_t *) pucOutputBuf, + (uint32_t) 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxInitResetResource(IN struct ADAPTER + *prAdapter) +{ + struct TX_CTRL *prTxCtrl; + uint8_t ucIdx; + uint32_t u4MaxPageCntPerFrame = + prAdapter->rTxCtrl.u4MaxPageCntPerFrame; + + DEBUGFUNC("nicTxInitResetResource"); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + /* Delta page count */ + kalMemZero(prTxCtrl->rTc.au4TxDonePageCount, + sizeof(prTxCtrl->rTc.au4TxDonePageCount)); + kalMemZero(prTxCtrl->rTc.au4PreUsedPageCount, + sizeof(prTxCtrl->rTc.au4PreUsedPageCount)); + prTxCtrl->rTc.ucNextTcIdx = TC0_INDEX; + prTxCtrl->rTc.u4AvaliablePageCount = 0; + + /* Page count */ + prTxCtrl->rTc.au4MaxNumOfPage[TC0_INDEX] = + NIC_TX_INIT_PAGE_COUNT_TC0; + prTxCtrl->rTc.au4FreePageCount[TC0_INDEX] = + NIC_TX_INIT_PAGE_COUNT_TC0; + + prTxCtrl->rTc.au4MaxNumOfPage[TC1_INDEX] = + NIC_TX_INIT_PAGE_COUNT_TC1; + prTxCtrl->rTc.au4FreePageCount[TC1_INDEX] = + NIC_TX_INIT_PAGE_COUNT_TC1; + + prTxCtrl->rTc.au4MaxNumOfPage[TC2_INDEX] = + NIC_TX_INIT_PAGE_COUNT_TC2; + prTxCtrl->rTc.au4FreePageCount[TC2_INDEX] = + NIC_TX_INIT_PAGE_COUNT_TC2; + + prTxCtrl->rTc.au4MaxNumOfPage[TC3_INDEX] = + NIC_TX_INIT_PAGE_COUNT_TC3; + prTxCtrl->rTc.au4FreePageCount[TC3_INDEX] = + NIC_TX_INIT_PAGE_COUNT_TC3; + + prTxCtrl->rTc.au4MaxNumOfPage[TC4_INDEX] = + NIC_TX_INIT_PAGE_COUNT_TC4; + prTxCtrl->rTc.au4FreePageCount[TC4_INDEX] = + NIC_TX_INIT_PAGE_COUNT_TC4; + + /* Buffer count */ + for (ucIdx = TC0_INDEX; ucIdx < TC_NUM; ucIdx++) { + prTxCtrl->rTc.au4MaxNumOfBuffer[ucIdx] = + prTxCtrl->rTc.au4MaxNumOfPage[ucIdx] / + u4MaxPageCntPerFrame; + prTxCtrl->rTc.au4FreeBufferCount[ucIdx] = + prTxCtrl->rTc.au4FreePageCount[ucIdx] / + u4MaxPageCntPerFrame; + } + + return WLAN_STATUS_SUCCESS; + +} + +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Handle data packet that will send to firmware + * + * + * @param prAdapter Pointer to the Adapter structure. + * @param prMsduInfo Pointer of MSDU_INFO + * + * @retval TRUE Process success. + */ +/*----------------------------------------------------------------------------*/ +u_int8_t nicTxProcessCmdDataPacket(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ +#if (CFG_SUPPORT_CONNAC2X == 0) +#define _SET_PKT_FORMAT HAL_MAC_TX_DESC_SET_PKT_FORMAT +#define _SET_REMAINING_LIFE_TIME_IN_MS \ + HAL_MAC_TX_DESC_SET_REMAINING_LIFE_TIME_IN_MS +#define _SET_PID HAL_MAC_TX_DESC_SET_PID +#define _TX_DESC struct HW_MAC_TX_DESC* +#else +#define _SET_PKT_FORMAT HAL_MAC_CONNAC2X_TXD_SET_PKT_FORMAT +#define _SET_REMAINING_LIFE_TIME_IN_MS \ + HAL_MAC_CONNAC2X_TXD_SET_REMAINING_LIFE_TIME_IN_MS +#define _SET_PID HAL_MAC_CONNAC2X_TXD_SET_PID +#define _TX_DESC struct HW_MAC_CONNAC2X_TX_DESC* +#endif + struct BSS_INFO *prBssInfo; + _TX_DESC prTxDesc; + + /* Sanity check */ + if (!prMsduInfo->prPacket) { + DBGLOG_LIMITED(TX, WARN, "MSDU prPacket is null\n"); + return FALSE; + } + + if (!prMsduInfo->u2FrameLength) { + DBGLOG_LIMITED(TX, WARN, "MSDU u2FrameLength is 0\n"); + return FALSE; + } + + if (!prMsduInfo->ucMacHeaderLength) { + DBGLOG_LIMITED(TX, WARN, "MSDU ucMacHeaderLength is 0\n"); + return FALSE; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prMsduInfo->ucBssIndex); + /* Set StaRecIndex here*/ + qmDetermineStaRecIndex(prAdapter, prMsduInfo); + prMsduInfo->eSrc = TX_PACKET_OS; + + /* MMPDU: force stick to TC4 */ + prMsduInfo->ucTC = TC4_INDEX; + + /* No Tx descriptor template for MMPDU */ + prMsduInfo->fgIsTXDTemplateValid = FALSE; + + /* Set packet type to data to fill correct TxD */ + prMsduInfo->ucPacketType = TX_PACKET_TYPE_DATA; + +#if CFG_SUPPORT_MULTITHREAD + nicTxFillDesc(prAdapter, prMsduInfo, + prMsduInfo->aucTxDescBuffer, NULL); + /* DBGLOG_MEM32(HAL, ERROR, prMsduInfo->aucTxDescBuffer, 64); */ +#endif + + /* + * Adjust TxD for command data after fill description + */ + prTxDesc = (_TX_DESC) prMsduInfo->aucTxDescBuffer; + + /* (1) Force set packet format to command for command data*/ +#if (UNIFIED_MAC_TX_FORMAT == 1) + _SET_PKT_FORMAT(prTxDesc, TXD_PKT_FORMAT_COMMAND); +#endif + + /* (2) Set remaining TX time to no limit as cut-through data. + * Not use arTcTrafficSettings[TC4_INDEX].u4RemainingTxTime; + */ + if (!(prMsduInfo->u4Option & MSDU_OPT_MANUAL_LIFE_TIME)) + prMsduInfo->u4RemainingLifetime = TX_DESC_TX_TIME_NO_LIMIT; + + _SET_REMAINING_LIFE_TIME_IN_MS(prTxDesc, + prMsduInfo->u4RemainingLifetime); + + /* (3) If prMsduInfo->pfTxDoneHandler is not set (ie. PID is not set) + * Still set PID for command data packet for firmware usage. Driver + * does not handle EVENT_ID_TX_DONE in this case + */ + if (prMsduInfo->ucPID < NIC_TX_DESC_DRIVER_PID_MIN) { + prMsduInfo->ucPID = nicTxAssignPID(prAdapter, + prMsduInfo->ucWlanIndex); + + _SET_PID(prTxDesc, prMsduInfo->ucPID); + } + +#undef _SET_PKT_FORMAT +#undef _SET_REMAINING_LIFE_TIME_IN_MS +#undef _SET_PID +#undef _TX_DESC + + return TRUE; +} + +u_int8_t nicTxProcessMngPacket(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ +#if 0 + uint16_t u2RateCode; +#endif + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + + if (prMsduInfo->eSrc != TX_PACKET_MGMT) + return FALSE; + + /* Sanity check */ + if (!prMsduInfo->prPacket) + return FALSE; + + if (!prMsduInfo->u2FrameLength) + return FALSE; + + if (!prMsduInfo->ucMacHeaderLength) + return FALSE; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prMsduInfo->ucBssIndex); + prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + + /* MMPDU: force stick to TC4 */ + if (prMsduInfo->fgMgmtUseDataQ) + prMsduInfo->ucTC = TC0_INDEX; + else + prMsduInfo->ucTC = TC4_INDEX; + + /* No Tx descriptor template for MMPDU */ + prMsduInfo->fgIsTXDTemplateValid = FALSE; + + /* Fixed Rate */ + if (prMsduInfo->ucRateMode == MSDU_RATE_MODE_AUTO && + prMsduInfo->fgMgmtUseDataQ != TRUE) { +#if 0 + prMsduInfo->ucRateMode = MSDU_RATE_MODE_MANUAL_DESC; + + if (prStaRec) + u2RateCode = prStaRec->u2HwDefaultFixedRateCode; + else + u2RateCode = prBssInfo->u2HwDefaultFixedRateCode; + + nicTxSetPktFixedRateOption(prMsduInfo, u2RateCode, + FIX_BW_NO_FIXED, FALSE, FALSE); +#else + nicTxSetPktLowestFixedRate(prAdapter, prMsduInfo); +#endif + } +#if CFG_SUPPORT_MULTITHREAD + nicTxFillDesc(prAdapter, prMsduInfo, + prMsduInfo->aucTxDescBuffer, NULL); +#endif + + return TRUE; +} + +void nicTxProcessTxDoneEvent(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct EVENT_TX_DONE *prTxDone; + struct MSDU_INFO *prMsduInfo; + struct TX_CTRL *prTxCtrl = &prAdapter->rTxCtrl; + char *prBw = "INVALID"; + + prTxDone = (struct EVENT_TX_DONE *) (prEvent->aucBuffer); + + if (prTxDone->ucFlag & BIT(TXS_WITH_ADVANCED_INFO)) { + /* Tx Done with advanced info */ + if (prTxDone->ucStatus != 0) + DBGLOG_LIMITED(NIC, INFO, + "EVENT_ID_TX_DONE WIDX:PID[%u:%u] Status[%u:%s] SN[%u] TID[%u] CNT[%u] Flush[%u]\n", + prTxDone->ucWlanIndex, prTxDone->ucPacketSeq, + prTxDone->ucStatus, + apucTxResultStr[prTxDone->ucStatus], + prTxDone->u2SequenceNumber, prTxDone->ucTid, + prTxDone->ucTxCount, prTxDone->ucFlushReason); + else + DBGLOG(NIC, TRACE, + "EVENT_ID_TX_DONE WIDX:PID[%u:%u] Status[%u:%s] SN[%u] TID[%u] CNT[%u] Flush[%u]\n", + prTxDone->ucWlanIndex, prTxDone->ucPacketSeq, + prTxDone->ucStatus, + apucTxResultStr[prTxDone->ucStatus], + prTxDone->u2SequenceNumber, prTxDone->ucTid, + prTxDone->ucTxCount, prTxDone->ucFlushReason); + + if (prTxDone->ucFlag & BIT(TXS_IS_EXIST)) { + uint8_t ucNss, ucStbc; + int8_t icTxPwr; + uint32_t *pu4RawTxs = + (uint32_t *)&prTxDone->aucRawTxS[0]; + + ucNss = (prTxDone->u2TxRate & TX_DESC_NSTS_MASK) >> + TX_DESC_NSTS_OFFSET; + ucNss += 1; + ucStbc = (prTxDone->u2TxRate & TX_DESC_STBC) ? + TRUE : FALSE; + + if (ucStbc) + ucNss /= 2; + + if (prTxDone->ucBandwidth >= + sizeof(apucBandwidt) / sizeof(uint8_t *)) + DBGLOG(NIC, WARN, "Invalid bandwidth: %u", + prTxDone->ucBandwidth); + else + prBw = apucBandwidt[prTxDone->ucBandwidth]; + + if (prTxDone->ucStatus != 0) + DBGLOG_LIMITED(NIC, INFO, + "||RATE[0x%04x] BW[%s] NSS[%u] ArIdx[%u] RspRate[0x%02x]\n", + prTxDone->u2TxRate, + prBw, + ucNss, + prTxDone->ucRateTableIdx, + prTxDone->ucRspRate); + else + DBGLOG(NIC, TRACE, + "||RATE[0x%04x] BW[%s] NSS[%u] ArIdx[%u] RspRate[0x%02x]\n", + prTxDone->u2TxRate, + prBw, + ucNss, + prTxDone->ucRateTableIdx, + prTxDone->ucRspRate); + icTxPwr = (int8_t)prTxDone->ucTxPower; + if (icTxPwr & BIT(6)) + icTxPwr |= BIT(7); + + if (prTxDone->ucStatus != 0) + DBGLOG_LIMITED(NIC, INFO, + "||AMPDU[%u] PS[%u] IBF[%u] EBF[%u] TxPwr[%d%sdBm] TSF[%u] TxDelay[%uus]\n", + prTxDone->u4AppliedFlag & + BIT(TX_FRAME_IN_AMPDU_FORMAT) ? + TRUE : FALSE, + prTxDone->u4AppliedFlag & + BIT(TX_FRAME_PS_BIT) ? TRUE : FALSE, + prTxDone->u4AppliedFlag & + BIT(TX_FRAME_IMP_BF) ? TRUE : FALSE, + prTxDone->u4AppliedFlag & + BIT(TX_FRAME_EXP_BF) ? TRUE : FALSE, + icTxPwr / 2, icTxPwr & BIT(0) ? + ".5" : "", + prTxDone->u4Timestamp, + prTxDone->u4TxDelay); + else + DBGLOG_LIMITED(NIC, TRACE, + "||AMPDU[%u] PS[%u] IBF[%u] EBF[%u] TxPwr[%d%sdBm] TSF[%u] TxDelay[%uus]\n", + prTxDone->u4AppliedFlag & + BIT(TX_FRAME_IN_AMPDU_FORMAT) ? + TRUE : FALSE, + prTxDone->u4AppliedFlag & + BIT(TX_FRAME_PS_BIT) ? TRUE : FALSE, + prTxDone->u4AppliedFlag & + BIT(TX_FRAME_IMP_BF) ? TRUE : FALSE, + prTxDone->u4AppliedFlag & + BIT(TX_FRAME_EXP_BF) ? TRUE : FALSE, + icTxPwr / 2, icTxPwr & BIT(0) ? + ".5" : "", + prTxDone->u4Timestamp, + prTxDone->u4TxDelay); + if (prTxDone->ucStatus != 0) + DBGLOG_LIMITED(NIC, INFO, + "TxS[%08x %08x %08x %08x %08x %08x %08x]\n", + *pu4RawTxs, + *(pu4RawTxs + 1), *(pu4RawTxs + 2), + *(pu4RawTxs + 3), *(pu4RawTxs + 4), + *(pu4RawTxs + 5), *(pu4RawTxs + 6)); + else + DBGLOG_LIMITED(NIC, TRACE, + "TxS[%08x %08x %08x %08x %08x %08x %08x]\n", + *pu4RawTxs, + *(pu4RawTxs + 1), *(pu4RawTxs + 2), + *(pu4RawTxs + 3), *(pu4RawTxs + 4), + *(pu4RawTxs + 5), *(pu4RawTxs + 6)); + } + } else { + DBGLOG(NIC, TRACE, + "EVENT_ID_TX_DONE WIDX:PID[%u:%u] Status[%u:%s] SN[%u]\n", + prTxDone->ucWlanIndex, prTxDone->ucPacketSeq, + prTxDone->ucStatus, + apucTxResultStr[prTxDone->ucStatus], + prTxDone->u2SequenceNumber); + } + + /* call related TX Done Handler */ + prMsduInfo = nicGetPendingTxMsduInfo(prAdapter, + prTxDone->ucWlanIndex, + prTxDone->ucPacketSeq); + +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT + DBGLOG(NIC, 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 CFG_SUPPORT_WIFI_SYSDVT + if (is_frame_test(prAdapter, 1) != 0) { + prAdapter->auto_dvt->txs.received_pid = prTxDone->ucPacketSeq; + receive_del_txs_queue(prTxDone->u2SequenceNumber, + prTxDone->ucPacketSeq, prTxDone->ucWlanIndex, + prTxDone->u4Timestamp); + DBGLOG(REQ, LOUD, + "Done receive_del_txs_queue pid=%d timestamp=%d\n", + prTxDone->ucPacketSeq, prTxDone->u4Timestamp); + } +#endif + + if (prMsduInfo) { + prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, + (enum ENUM_TX_RESULT_CODE) (prTxDone->ucStatus)); + + if (prMsduInfo->eSrc == TX_PACKET_MGMT) + cnmMgtPktFree(prAdapter, prMsduInfo); +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + else if (prMsduInfo->prToken) + prMsduInfo->pfTxDoneHandler = NULL; +#endif + else { + nicTxFreePacket(prAdapter, prMsduInfo, FALSE); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } + + if (prTxDone->ucStatus == 0 && + prMsduInfo->ucBssIndex < MAX_BSSID_NUM) + GET_CURRENT_SYSTIME( + &prTxCtrl->u4LastTxTime + [prMsduInfo->ucBssIndex]); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxEnqueueMsdu(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct TX_CTRL *prTxCtrl; + struct MSDU_INFO *prNextMsduInfo, *prRetMsduInfo, + *prMsduInfoHead; + struct QUE qDataPort0, qDataPort1; + struct QUE *prDataPort0, *prDataPort1; + struct CMD_INFO *prCmdInfo; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + prDataPort0 = &qDataPort0; + prDataPort1 = &qDataPort1; + + QUEUE_INITIALIZE(prDataPort0); + QUEUE_INITIALIZE(prDataPort1); + + /* check how many management frame are being queued */ + while (prMsduInfo) { + prNextMsduInfo = (struct MSDU_INFO *) QUEUE_GET_NEXT_ENTRY(( + struct QUE_ENTRY *) prMsduInfo); + + QUEUE_GET_NEXT_ENTRY((struct QUE_ENTRY *) prMsduInfo) = + NULL; + + if (prMsduInfo->eSrc == TX_PACKET_MGMT) { + if (nicTxProcessMngPacket(prAdapter, prMsduInfo)) { + /* Valid MGMT */ + QUEUE_INSERT_TAIL(prDataPort1, + (struct QUE_ENTRY *) + prMsduInfo); + } else { + /* Invalid MGMT */ + DBGLOG(TX, WARN, + "Invalid MGMT[0x%p] BSS[%u] STA[%u],free it\n", + prMsduInfo, prMsduInfo->ucBssIndex, + prMsduInfo->ucStaRecIndex); + + cnmMgtPktFree(prAdapter, prMsduInfo); + } + } else { + QUEUE_INSERT_TAIL(prDataPort0, + (struct QUE_ENTRY *) prMsduInfo); + } + + prMsduInfo = prNextMsduInfo; + } + + if (prDataPort0->u4NumElem) { + /* send to QM */ + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + prRetMsduInfo = qmEnqueueTxPackets(prAdapter, + (struct MSDU_INFO *) QUEUE_GET_HEAD(prDataPort0)); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); +#if ARP_MONITER_ENABLE + if (prAdapter->cArpNoResponseIdx >= 0) { +#if CFG_SUPPORT_DATA_STALL + KAL_REPORT_ERROR_EVENT(prAdapter, + EVENT_ARP_NO_RESPONSE, + (uint16_t)sizeof(uint32_t), + prAdapter->cArpNoResponseIdx, + FALSE); +#endif /* CFG_SUPPORT_DATA_STALL */ + aisBssBeaconTimeout(prAdapter, + prAdapter->cArpNoResponseIdx); + prAdapter->cArpNoResponseIdx = -1; + } +#endif /* ARP_MONITER_ENABLE */ + /* post-process for dropped packets */ + if (prRetMsduInfo) { /* unable to enqueue */ + nicTxFreeMsduInfoPacket(prAdapter, prRetMsduInfo); + nicTxReturnMsduInfo(prAdapter, prRetMsduInfo); + } + } + + if (prDataPort1->u4NumElem) { + prMsduInfoHead = (struct MSDU_INFO *) QUEUE_GET_HEAD( + prDataPort1); + + if (nicTxGetFreeCmdCount(prAdapter) < + NIC_TX_CMD_INFO_RESERVED_COUNT) { + /* not enough descriptors for sending */ + u4Status = WLAN_STATUS_FAILURE; + + /* free all MSDUs */ + while (prMsduInfoHead) { + prNextMsduInfo = + (struct MSDU_INFO *) + 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 = + (struct MSDU_INFO *) + QUEUE_GET_NEXT_ENTRY( + &prMsduInfoHead->rQueEntry); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, + SPIN_LOCK_CMD_RESOURCE); + QUEUE_REMOVE_HEAD( + &prAdapter->rFreeCmdList, + prCmdInfo, + struct CMD_INFO *); + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_CMD_RESOURCE); + + if (prCmdInfo) { + GLUE_INC_REF_CNT( + prTxCtrl->i4TxMgmtPendingNum); + + kalMemZero(prCmdInfo, + sizeof(struct CMD_INFO)); + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + /* Tag MGMT enqueue time */ + GET_CURRENT_SYSTIME( + &prMsduInfoHead-> + rPktProfile.rEnqueueTimestamp); +#endif + prCmdInfo->eCmdType = + COMMAND_TYPE_MANAGEMENT_FRAME; + prCmdInfo->u2InfoBufLen = + prMsduInfoHead->u2FrameLength; + prCmdInfo->pucInfoBuffer = NULL; + prCmdInfo->prMsduInfo = prMsduInfoHead; + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->pfCmdTimeoutHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->ucCmdSeqNum = + prMsduInfoHead->ucTxSeqNum; + + DBGLOG(TX, TRACE, + "%s: EN-Q MSDU[0x%p] SEQ[%u] BSS[%u] STA[%u] to CMD Q\n", + __func__, prMsduInfoHead, + prMsduInfoHead->ucTxSeqNum, + prMsduInfoHead->ucBssIndex, + prMsduInfoHead->ucStaRecIndex); + + kalEnqueueCommand(prAdapter->prGlueInfo, + (struct QUE_ENTRY *) prCmdInfo); + } else { + /* Cmd free count is larger than + * expected, but allocation fail. + */ + u4Status = WLAN_STATUS_FAILURE; + + if (prMsduInfoHead->pfTxDoneHandler + != NULL) { + prMsduInfoHead->pfTxDoneHandler( + prAdapter, + prMsduInfoHead, + TX_RESULT_DROPPED_IN_DRIVER); + } + + 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 WLAN index + * + * @param prAdapter Pointer to the Adapter structure. + * + * @retval + */ +/*----------------------------------------------------------------------------*/ +uint8_t nicTxGetWlanIdx(struct ADAPTER *prAdapter, + uint8_t ucBssIdx, uint8_t ucStaRecIdx) +{ + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + uint8_t ucWlanIndex = prAdapter->ucTxDefaultWlanIndex; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIdx); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + + if (prStaRec) + ucWlanIndex = prStaRec->ucWlanIndex; + else if ((ucStaRecIdx == STA_REC_INDEX_BMCAST) + && prBssInfo->fgIsInUse) { + if (prBssInfo->fgBcDefaultKeyExist) { + if (prBssInfo->wepkeyUsed[prBssInfo->ucBcDefaultKeyIdx] + && prBssInfo->wepkeyWlanIdx + < prAdapter->ucTxDefaultWlanIndex) + ucWlanIndex = prBssInfo->wepkeyWlanIdx; + else if (prBssInfo->ucBMCWlanIndexSUsed[ + prBssInfo->ucBcDefaultKeyIdx]) + ucWlanIndex = + prBssInfo->ucBMCWlanIndexS[ + prBssInfo->ucBcDefaultKeyIdx]; + } else + ucWlanIndex = prBssInfo->ucBMCWlanIndex; + } + + if (ucWlanIndex >= WTBL_SIZE) { + DBGLOG(TX, WARN, + "Unexpected WIDX[%u] BSS[%u] STA[%u], set WIDX to default value[%u]\n", + ucWlanIndex, ucBssIdx, ucStaRecIdx, + prAdapter->ucTxDefaultWlanIndex); + + ucWlanIndex = prAdapter->ucTxDefaultWlanIndex; + } + + return ucWlanIndex; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * @param prAdapter Pointer to the Adapter structure. + * + * @retval + */ +/*----------------------------------------------------------------------------*/ +u_int8_t nicTxIsMgmtResourceEnough(IN struct ADAPTER + *prAdapter) +{ + if (nicTxGetFreeCmdCount(prAdapter) > + (CFG_TX_MAX_CMD_PKT_NUM / 2)) + return TRUE; + else + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief this function returns available count in command queue + * + * @param prAdapter Pointer to the Adapter structure. + * + * @retval + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxGetFreeCmdCount(IN struct ADAPTER *prAdapter) +{ + ASSERT(prAdapter); + + return prAdapter->rFreeCmdList.u4NumElem; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief this function returns page count of frame + * + * @param prAdapter Pointer to the Adapter structure. + * @param u4FrameLength frame length + * + * @retval page count of this frame + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxGetPageCount(IN struct ADAPTER *prAdapter, + IN uint32_t u4FrameLength, IN u_int8_t fgIncludeDesc) +{ + return halTxGetPageCount(prAdapter, u4FrameLength, + fgIncludeDesc); +} + +uint32_t nicTxGetCmdPageCount(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo) +{ + uint32_t u4PageCount; + + switch (prCmdInfo->eCmdType) { + case COMMAND_TYPE_NETWORK_IOCTL: + case COMMAND_TYPE_GENERAL_IOCTL: + u4PageCount = nicTxGetPageCount(prAdapter, + prCmdInfo->u2InfoBufLen, TRUE); + break; + + case COMMAND_TYPE_SECURITY_FRAME: + case COMMAND_TYPE_MANAGEMENT_FRAME: + case COMMAND_TYPE_DATA_FRAME: + /* No TxD append field for management packet */ + u4PageCount = nicTxGetPageCount(prAdapter, + prCmdInfo->u2InfoBufLen + + NIC_TX_DESC_LONG_FORMAT_LENGTH, + TRUE); + break; + + default: + DBGLOG(INIT, WARN, "Undefined CMD Type(%u)\n", + prCmdInfo->eCmdType); + u4PageCount = nicTxGetPageCount(prAdapter, + prCmdInfo->u2InfoBufLen, FALSE); + break; + } + + return u4PageCount; +} + +void nicTxSetMngPacket(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + uint8_t ucBssIndex, uint8_t ucStaRecIndex, + uint8_t ucMacHeaderLength, + uint16_t u2FrameLength, + PFN_TX_DONE_HANDLER pfTxDoneHandler, + uint8_t ucRateMode) +{ + static uint16_t u2SwSn; + ASSERT(prMsduInfo); + + prMsduInfo->ucBssIndex = ucBssIndex; + prMsduInfo->ucStaRecIndex = ucStaRecIndex; + prMsduInfo->ucMacHeaderLength = ucMacHeaderLength; + prMsduInfo->u2FrameLength = u2FrameLength; + prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; + prMsduInfo->ucRateMode = ucRateMode; + + /* Reset default value for MMPDU */ + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_1x_NonProtected = + TRUE; /*For data frame only, no sense for management frame*/ + prMsduInfo->u4FixedRateOption = 0; + prMsduInfo->cPowerOffset = 0; + prMsduInfo->u4Option = 0; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->ucPID = NIC_TX_DESC_PID_RESERVED; + prMsduInfo->ucPacketType = TX_PACKET_TYPE_MGMT; + prMsduInfo->ucUserPriority = 0; + prMsduInfo->eSrc = TX_PACKET_MGMT; + u2SwSn++; + if (u2SwSn > 4095) + u2SwSn = 0; + nicTxSetPktSequenceNumber(prMsduInfo, u2SwSn); +} + +void nicTxSetDataPacket(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + uint8_t ucBssIndex, uint8_t ucStaRecIndex, + uint8_t ucMacHeaderLength, + uint16_t u2FrameLength, PFN_TX_DONE_HANDLER pfTxDoneHandler, + uint8_t ucRateMode, enum ENUM_TX_PACKET_SRC eSrc, + uint8_t ucTID, + u_int8_t fgIs802_11Frame, u_int8_t fgIs1xFrame) +{ + ASSERT(prMsduInfo); + + prMsduInfo->ucBssIndex = ucBssIndex; + prMsduInfo->ucStaRecIndex = ucStaRecIndex; + prMsduInfo->ucMacHeaderLength = ucMacHeaderLength; + prMsduInfo->u2FrameLength = u2FrameLength; + prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; + prMsduInfo->ucRateMode = ucRateMode; + prMsduInfo->ucUserPriority = ucTID; + prMsduInfo->fgIs802_11 = fgIs802_11Frame; + prMsduInfo->eSrc = eSrc; + prMsduInfo->fgIs802_1x = fgIs1xFrame; + + /* Reset default value for data packet */ + prMsduInfo->u4FixedRateOption = 0; + prMsduInfo->cPowerOffset = 0; + prMsduInfo->u4Option = 0; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->ucPID = NIC_TX_DESC_PID_RESERVED; + prMsduInfo->ucPacketType = TX_PACKET_TYPE_DATA; +} + +void nicTxFillDescByPktOption( + struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + void *prTxDesc) +{ + struct TX_DESC_OPS_T *prTxDescOps = prAdapter->chip_info->prTxDescOps; + + if (prTxDescOps->nic_txd_fill_by_pkt_option) + prTxDescOps->nic_txd_fill_by_pkt_option( + prMsduInfo, + prTxDesc); + else + DBGLOG(TX, ERROR, "%s:: no nic_txd_fill_by_pkt_option??\n", + __func__); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Extra configuration for Tx packet + * + * @retval + */ +/*----------------------------------------------------------------------------*/ +void nicTxConfigPktOption(struct MSDU_INFO *prMsduInfo, + uint32_t u4OptionMask, u_int8_t fgSetOption) +{ + if (fgSetOption) + prMsduInfo->u4Option |= u4OptionMask; + else + prMsduInfo->u4Option &= ~u4OptionMask; +} + +void nicTxConfigPktControlFlag(struct MSDU_INFO *prMsduInfo, + uint8_t ucControlFlagMask, u_int8_t fgSetFlag) +{ + /* Set control flag */ + if (fgSetFlag) + prMsduInfo->ucControlFlag |= ucControlFlagMask; + else + prMsduInfo->ucControlFlag &= + ~ucControlFlagMask; /* Clear control flag */ +} + +void nicTxSetPktLifeTime(struct MSDU_INFO *prMsduInfo, + uint32_t u4TxLifeTimeInMs) +{ + prMsduInfo->u4RemainingLifetime = u4TxLifeTimeInMs; + prMsduInfo->u4Option |= MSDU_OPT_MANUAL_LIFE_TIME; +} + +void nicTxSetPktRetryLimit(struct MSDU_INFO *prMsduInfo, + uint8_t ucRetryLimit) +{ + prMsduInfo->ucRetryLimit = ucRetryLimit; + prMsduInfo->u4Option |= MSDU_OPT_MANUAL_RETRY_LIMIT; +} + +void nicTxSetPktPowerOffset(struct MSDU_INFO *prMsduInfo, + int8_t cPowerOffset) +{ + prMsduInfo->cPowerOffset = cPowerOffset; + prMsduInfo->u4Option |= MSDU_OPT_MANUAL_POWER_OFFSET; +} + +void nicTxSetPktSequenceNumber(struct MSDU_INFO *prMsduInfo, + uint16_t u2SN) +{ + prMsduInfo->u2SwSN = u2SN; + prMsduInfo->u4Option |= MSDU_OPT_MANUAL_SN; +} + +void nicTxSetPktMacTxQue(struct MSDU_INFO *prMsduInfo, + uint8_t ucMacTxQue) +{ + uint8_t ucTcIdx; + + for (ucTcIdx = TC0_INDEX; ucTcIdx < TC_NUM; ucTcIdx++) { + if (arTcResourceControl[ucTcIdx].ucDestQueueIndex == + ucMacTxQue) + break; + } + + if (ucTcIdx < TC_NUM) { + prMsduInfo->ucTC = ucTcIdx; + prMsduInfo->u4Option |= MSDU_OPT_MANUAL_TX_QUE; + } +} + +void nicTxSetPktFixedRateOptionFull( + struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + uint16_t u2RateCode, + uint8_t ucBandwidth, + u_int8_t fgShortGI, + u_int8_t fgLDPC, + u_int8_t fgDynamicBwRts, + u_int8_t fgBeamforming, + uint8_t ucAntennaIndex) +{ + struct TX_DESC_OPS_T *prTxDescOps = prAdapter->chip_info->prTxDescOps; + + if (prTxDescOps->nic_txd_set_pkt_fixed_rate_option_full) + prTxDescOps->nic_txd_set_pkt_fixed_rate_option_full( + prMsduInfo, + u2RateCode, + ucBandwidth, + fgShortGI, + fgLDPC, + fgDynamicBwRts, + fgBeamforming, + ucAntennaIndex); + else + DBGLOG(TX, ERROR, + "%s:: no nic_txd_set_pkt_fixed_rate_option_full??\n", + __func__); +} + +void nicTxSetPktFixedRateOption( + struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + uint16_t u2RateCode, + uint8_t ucBandwidth, + u_int8_t fgShortGI, + u_int8_t fgDynamicBwRts) +{ + struct TX_DESC_OPS_T *prTxDescOps = prAdapter->chip_info->prTxDescOps; + + if (prTxDescOps->nic_txd_set_pkt_fixed_rate_option) + prTxDescOps->nic_txd_set_pkt_fixed_rate_option( + prMsduInfo, + u2RateCode, + ucBandwidth, + fgShortGI, + fgDynamicBwRts); + else + DBGLOG(TX, ERROR, + "%s:: no nicTxSetPktFixedRateOption??\n", + __func__); +} + +void nicTxSetPktLowestFixedRate(IN struct ADAPTER + *prAdapter, IN struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo = GET_BSS_INFO_BY_INDEX( + prAdapter, prMsduInfo->ucBssIndex); + struct STA_RECORD *prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + uint8_t ucRateSwIndex, ucRateIndex, ucRatePreamble; + uint16_t u2RateCode, u2RateCodeLimit, u2OperationalRateSet; + uint32_t u4CurrentPhyRate, u4Status; + + /* Not to use TxD template for fixed rate */ + prMsduInfo->fgIsTXDTemplateValid = FALSE; + + /* Fixed Rate */ + prMsduInfo->ucRateMode = MSDU_RATE_MODE_MANUAL_DESC; + + if (prStaRec) { + u2RateCode = prStaRec->u2HwDefaultFixedRateCode; + u2OperationalRateSet = prStaRec->u2OperationalRateSet; + } else { + u2RateCode = prBssInfo->u2HwDefaultFixedRateCode; + u2OperationalRateSet = prBssInfo->u2OperationalRateSet; + } + + /* CoexPhyRateLimit is 0 means phy rate is unlimited */ + if (prBssInfo->u4CoexPhyRateLimit != 0) { + + u4CurrentPhyRate = nicRateCode2PhyRate(u2RateCode, + FIX_BW_NO_FIXED, MAC_GI_NORMAL, AR_SS_NULL); + + if (prBssInfo->u4CoexPhyRateLimit > u4CurrentPhyRate) { + nicGetRateIndexFromRateSetWithLimit( + u2OperationalRateSet, + prBssInfo->u4CoexPhyRateLimit, + TRUE, &ucRateSwIndex); + + /* Convert SW rate index to rate code */ + nicSwIndex2RateIndex(ucRateSwIndex, &ucRateIndex, + &ucRatePreamble); + u4Status = nicRateIndex2RateCode(ucRatePreamble, + ucRateIndex, &u2RateCodeLimit); + if (u4Status == WLAN_STATUS_SUCCESS) { + /* Replace by limitation rate */ + u2RateCode = u2RateCodeLimit; + DBGLOG(NIC, INFO, + "Coex RatePreamble=%d, R_SW_IDX:%d, R_CODE:0x%x\n", + ucRatePreamble, ucRateIndex, u2RateCode); + } + } + } + nicTxSetPktFixedRateOption(prAdapter, prMsduInfo, u2RateCode, + FIX_BW_NO_FIXED, FALSE, FALSE); +} + +void nicTxSetPktMoreData(struct MSDU_INFO + *prCurrentMsduInfo, u_int8_t fgSetMoreDataBit) +{ + struct WLAN_MAC_HEADER *prWlanMacHeader = NULL; + + if (prCurrentMsduInfo->fgIs802_11) { + prWlanMacHeader = + (struct WLAN_MAC_HEADER *) (((uint8_t *) ( + prCurrentMsduInfo->prPacket)) + MAC_TX_RESERVED_FIELD); + } + + if (fgSetMoreDataBit) { + if (!prCurrentMsduInfo->fgIs802_11) + prCurrentMsduInfo->u4Option |= MSDU_OPT_MORE_DATA; + else + prWlanMacHeader->u2FrameCtrl |= MASK_FC_MORE_DATA; + } else { + if (!prCurrentMsduInfo->fgIs802_11) + prCurrentMsduInfo->u4Option &= ~MSDU_OPT_MORE_DATA; + else + prWlanMacHeader->u2FrameCtrl &= ~MASK_FC_MORE_DATA; + } +} + +uint8_t nicTxAssignPID(IN struct ADAPTER *prAdapter, + IN uint8_t ucWlanIndex) +{ + uint8_t ucRetval; + uint8_t *pucPidPool; + + ASSERT(prAdapter); + + pucPidPool = &prAdapter->aucPidPool[ucWlanIndex]; + + ucRetval = *pucPidPool; + + /* Driver side Tx Sequence number: 1~127 */ + (*pucPidPool)++; + + if (*pucPidPool > NIC_TX_DESC_DRIVER_PID_MAX) + *pucPidPool = NIC_TX_DESC_DRIVER_PID_MIN; + + return ucRetval; +} + +void nicTxSetPktEOSP(struct MSDU_INFO *prCurrentMsduInfo, + u_int8_t fgSetEOSPBit) +{ + struct WLAN_MAC_HEADER_QOS *prWlanMacHeader = NULL; + u_int8_t fgWriteToDesc = TRUE; + + if (prCurrentMsduInfo->fgIs802_11) { + prWlanMacHeader = + (struct WLAN_MAC_HEADER_QOS *) (((uint8_t *) ( + prCurrentMsduInfo->prPacket)) + MAC_TX_RESERVED_FIELD); + fgWriteToDesc = FALSE; + } + + if (fgSetEOSPBit) { + if (fgWriteToDesc) + prCurrentMsduInfo->u4Option |= MSDU_OPT_EOSP; + else + prWlanMacHeader->u2QosCtrl |= MASK_QC_EOSP; + } else { + if (fgWriteToDesc) + prCurrentMsduInfo->u4Option &= ~MSDU_OPT_EOSP; + else + prWlanMacHeader->u2QosCtrl &= ~MASK_QC_EOSP; + } +} + +uint32_t +nicTxDummyTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + struct PERF_MONITOR *prPerMonitor = &prAdapter->rPerMonitor; + + if (rTxDoneStatus == 0) { + prPerMonitor->ulTotalTxSuccessCount++; + } else { + DBGLOG(TX, INFO, + "Msdu WIDX:PID[%u:%u] SEQ[%u] Tx Status[%u]\n", + prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, + prMsduInfo->ucTxSeqNum, rTxDoneStatus); + prPerMonitor->ulTotalTxFailCount++; + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Update BSS Tx Params + * + * @param prStaRec The peer + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicTxUpdateBssDefaultRate(struct BSS_INFO *prBssInfo) +{ + uint8_t ucLowestBasicRateIndex; + + prBssInfo->u2HwDefaultFixedRateCode = RATE_OFDM_6M; + + /* 4 <1> Find Lowest Basic Rate Index for default TX Rate of MMPDU */ + if (rateGetLowestRateIndexFromRateSet( + prBssInfo->u2BSSBasicRateSet, &ucLowestBasicRateIndex)) { + nicRateIndex2RateCode(PREAMBLE_DEFAULT_LONG_NONE, + ucLowestBasicRateIndex, + &prBssInfo->u2HwDefaultFixedRateCode); + } else { + switch (prBssInfo->ucNonHTBasicPhyType) { + case PHY_TYPE_ERP_INDEX: + case PHY_TYPE_OFDM_INDEX: + prBssInfo->u2HwDefaultFixedRateCode = RATE_OFDM_6M; + break; + + default: + prBssInfo->u2HwDefaultFixedRateCode = RATE_CCK_1M_LONG; + break; + } + } + +#if (CFG_SUPPORT_HE_ER == 1) + if (prBssInfo->ucErMode == RA_DCM) { + prBssInfo->u2HwDefaultFixedRateCode = RATE_HE_ER_DCM_MCS_0; + DBGLOG_LIMITED(TX, WARN, + "nicTxUpdateBssDefaultRate:HE_ER DCM\n"); + } else if (prBssInfo->ucErMode == RA_ER_106) { + prBssInfo->u2HwDefaultFixedRateCode = RATE_HE_ER_TONE_106_MCS_0; + DBGLOG_LIMITED(TX, WARN, + "nicTxUpdateBssDefaultRate:HE_ER 106 tone\n"); + } else { + DBGLOG_LIMITED(TX, WARN, + "nicTxUpdateBssDefaultRate:HE_ER Disable\n"); + } +#endif + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Update StaRec Tx parameters + * + * @param prStaRec The peer + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicTxUpdateStaRecDefaultRate(struct ADAPTER *prAdapter, struct STA_RECORD + *prStaRec) +{ + uint8_t ucLowestBasicRateIndex; + + prStaRec->u2HwDefaultFixedRateCode = RATE_OFDM_6M; + + /* 4 <1> Find Lowest Basic Rate Index for default TX Rate of MMPDU */ + if (rateGetLowestRateIndexFromRateSet( + prStaRec->u2BSSBasicRateSet, &ucLowestBasicRateIndex)) { + nicRateIndex2RateCode(PREAMBLE_DEFAULT_LONG_NONE, + ucLowestBasicRateIndex, + &prStaRec->u2HwDefaultFixedRateCode); + } else { + if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11B) + prStaRec->u2HwDefaultFixedRateCode = RATE_CCK_1M_LONG; + else if (prStaRec->ucDesiredPhyTypeSet & + PHY_TYPE_SET_802_11G) + prStaRec->u2HwDefaultFixedRateCode = RATE_OFDM_6M; + else if (prStaRec->ucDesiredPhyTypeSet & + PHY_TYPE_SET_802_11A) + prStaRec->u2HwDefaultFixedRateCode = RATE_OFDM_6M; + else if (prStaRec->ucDesiredPhyTypeSet & + PHY_TYPE_SET_802_11N) + prStaRec->u2HwDefaultFixedRateCode = RATE_MM_MCS_0; + } + +#if (CFG_SUPPORT_HE_ER == 1) + { + struct BSS_INFO *prBssInfo; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + if (prBssInfo->ucErMode == RA_DCM) { + prBssInfo->u2HwDefaultFixedRateCode = + RATE_HE_ER_DCM_MCS_0; + DBGLOG_LIMITED(TX, WARN, + "nicTxUpdateStaRecDefaultRate:HE_ER DCM\n"); + } else if (prBssInfo->ucErMode == RA_ER_106) { + prBssInfo->u2HwDefaultFixedRateCode = + RATE_HE_ER_TONE_106_MCS_0; + DBGLOG_LIMITED(TX, WARN, + "nicTxUpdateStaRecDefaultRate:HE_ER 106 tone\n"); + } else { + DBGLOG_LIMITED(TX, WARN, + "nicTxUpdateStaRecDefaultRate:HE_ER Disable\n"); + } + } +#endif + +} + +void nicTxCancelSendingCmd(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo) +{ + halTxCancelSendingCmd(prAdapter, prCmdInfo); +} + +uint32_t nicTxGetMaxPageCntPerFrame(IN struct ADAPTER + *prAdapter) +{ + uint32_t page_size = halGetHifTxPageSize(prAdapter); + + /* + * want to replace + * #define NIC_TX_MAX_PAGE_PER_FRAME \ + * ((NIC_TX_DESC_AND_PADDING_LENGTH + + * NIC_TX_DESC_HEADER_PADDING_LENGTH + \ + * NIC_TX_MAX_SIZE_PER_FRAME + NIC_TX_PAGE_SIZE - 1) + * / NIC_TX_PAGE_SIZE) + */ + + return ((NIC_TX_DESC_AND_PADDING_LENGTH + + NIC_TX_DESC_HEADER_PADDING_LENGTH + + NIC_TX_MAX_SIZE_PER_FRAME + page_size - 1) / page_size); +} + +/* TX Direct functions : BEGIN */ + +/*----------------------------------------------------------------------------*/ +/* + * \brief This function is to start rTxDirectHifTimer to try to + * send out packets in + * rStaPsQueue[], rBssAbsentQueue[], rTxDirectHifQueue[]. + * + * \param[in] prAdapter Pointer of Adapter + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +void nicTxDirectStartCheckQTimer(IN struct ADAPTER + *prAdapter) +{ + mod_timer(&prAdapter->rTxDirectHifTimer, jiffies + 1); +} + +void nicTxDirectClearSkbQ(IN struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct sk_buff *prSkb; + + while (TRUE) { + spin_lock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + prSkb = skb_dequeue(&prAdapter->rTxDirectSkbQueue); + spin_unlock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + if (prSkb == NULL) + break; + + kalSendComplete(prGlueInfo, prSkb, + WLAN_STATUS_NOT_ACCEPTED); + } +} + +void nicTxDirectClearHifQ(IN struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + uint8_t ucHifTc = 0; + struct QUE rNeedToFreeQue; + struct QUE *prNeedToFreeQue = &rNeedToFreeQue; + + QUEUE_INITIALIZE(prNeedToFreeQue); + + for (ucHifTc = 0; ucHifTc < TX_PORT_NUM; ucHifTc++) { + spin_lock_bh( + &prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + if (QUEUE_IS_NOT_EMPTY( + &prAdapter->rTxDirectHifQueue[ucHifTc])) { + QUEUE_MOVE_ALL(prNeedToFreeQue, + &prAdapter->rTxDirectHifQueue[ucHifTc]); + spin_unlock_bh( + &prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + + wlanProcessQueuedMsduInfo(prAdapter, + (struct MSDU_INFO *) + QUEUE_GET_HEAD(prNeedToFreeQue)); + } else { + spin_unlock_bh( + &prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + } + } +} + +void nicTxDirectClearStaPsQ(IN struct ADAPTER *prAdapter, + uint8_t ucStaRecIndex) +{ + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct QUE rNeedToFreeQue; + struct QUE *prNeedToFreeQue = &rNeedToFreeQue; + + QUEUE_INITIALIZE(prNeedToFreeQue); + spin_lock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + if (QUEUE_IS_NOT_EMPTY( + &prAdapter->rStaPsQueue[ucStaRecIndex])) { + QUEUE_MOVE_ALL(prNeedToFreeQue, + &prAdapter->rStaPsQueue[ucStaRecIndex]); + spin_unlock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + + wlanProcessQueuedMsduInfo(prAdapter, + (struct MSDU_INFO *) QUEUE_GET_HEAD(prNeedToFreeQue)); + } else { + spin_unlock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + } +} + +void nicTxDirectClearBssAbsentQ(IN struct ADAPTER + *prAdapter, uint8_t ucBssIndex) +{ + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct QUE rNeedToFreeQue; + struct QUE *prNeedToFreeQue = &rNeedToFreeQue; + + QUEUE_INITIALIZE(prNeedToFreeQue); + spin_lock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + if (QUEUE_IS_NOT_EMPTY( + &prAdapter->rBssAbsentQueue[ucBssIndex])) { + QUEUE_MOVE_ALL(prNeedToFreeQue, + &prAdapter->rBssAbsentQueue[ucBssIndex]); + spin_unlock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + + wlanProcessQueuedMsduInfo(prAdapter, + (struct MSDU_INFO *) QUEUE_GET_HEAD(prNeedToFreeQue)); + } else { + spin_unlock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + } +} + +void nicTxDirectClearAllStaPsQ(IN struct ADAPTER *prAdapter) +{ + uint8_t ucStaRecIndex; + uint32_t u4StaPsBitmap; + + u4StaPsBitmap = prAdapter->u4StaPsBitmap; + + if (!u4StaPsBitmap) + return; + + for (ucStaRecIndex = 0; ucStaRecIndex < CFG_STA_REC_NUM; + ++ucStaRecIndex) { + if (QUEUE_IS_NOT_EMPTY( + &prAdapter->rStaPsQueue[ucStaRecIndex])) { + nicTxDirectClearStaPsQ(prAdapter, + ucStaRecIndex); + u4StaPsBitmap &= ~BIT(ucStaRecIndex); + } + if (u4StaPsBitmap == 0) + break; + } +} + +/*----------------------------------------------------------------------------*/ +/* + * \brief This function is to check the StaRec is in Ps or not, + * and store MsduInfo(s) or sent MsduInfo(s) to the next + * stage respectively. + * + * \param[in] prAdapter Pointer of Adapter + * \param[in] ucStaRecIndex Indictate which StaRec to be checked + * \param[in] prQue Pointer of MsduInfo queue which to be processed + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +static void nicTxDirectCheckStaPsQ(IN struct ADAPTER + *prAdapter, uint8_t ucStaRecIndex, struct QUE *prQue) +{ + struct STA_RECORD *prStaRec; /* The current focused STA */ + struct MSDU_INFO *prMsduInfo; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + u_int8_t fgReturnStaPsQ = FALSE; + + if (ucStaRecIndex >= CFG_STA_REC_NUM) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIndex); + + QUEUE_CONCATENATE_QUEUES( + &prAdapter->rStaPsQueue[ucStaRecIndex], prQue); + QUEUE_REMOVE_HEAD(&prAdapter->rStaPsQueue[ucStaRecIndex], + prQueueEntry, struct QUE_ENTRY *); + prMsduInfo = (struct MSDU_INFO *) prQueueEntry; + + if (prMsduInfo == NULL) { + DBGLOG(TX, INFO, "prMsduInfo empty\n"); + return; + } + + if (prStaRec == NULL) { + DBGLOG(TX, INFO, "prStaRec empty\n"); + return; + } + + if (prStaRec->fgIsInPS) { + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + DBGLOG(TX, INFO, "fgIsInPS!\n"); + while (1) { + if (prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported && + (prStaRec->ucBmpTriggerAC + & BIT(prMsduInfo->ucTC))) { + if (prStaRec->ucFreeQuotaForDelivery > 0) { + prStaRec->ucFreeQuotaForDelivery--; + QUEUE_INSERT_TAIL( + prQue, + (struct QUE_ENTRY *) + prMsduInfo); + } else { + fgReturnStaPsQ = TRUE; + break; + } + } else { + if (prStaRec->ucFreeQuotaForNonDelivery > 0) { + prStaRec->ucFreeQuotaForNonDelivery--; + QUEUE_INSERT_TAIL( + prQue, + (struct QUE_ENTRY *) + prMsduInfo); + } else { + fgReturnStaPsQ = TRUE; + break; + } + } + if (QUEUE_IS_NOT_EMPTY( + &prAdapter->rStaPsQueue[ucStaRecIndex])) { + QUEUE_REMOVE_HEAD( + &prAdapter->rStaPsQueue[ucStaRecIndex], + prQueueEntry, struct QUE_ENTRY *); + prMsduInfo = (struct MSDU_INFO *) prQueueEntry; + if (prMsduInfo == NULL) { + DBGLOG(TX, INFO, "prMsduInfo null\n"); + break; + } + } else { + break; + } + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + if (fgReturnStaPsQ) { + QUEUE_INSERT_HEAD( + &prAdapter->rStaPsQueue[ucStaRecIndex], + (struct QUE_ENTRY *) prMsduInfo); + prAdapter->u4StaPsBitmap |= BIT(ucStaRecIndex); + return; + } + } else { + QUEUE_INSERT_TAIL(prQue, (struct QUE_ENTRY *) prMsduInfo); + if (QUEUE_IS_NOT_EMPTY( + &prAdapter->rStaPsQueue[ucStaRecIndex])) + QUEUE_CONCATENATE_QUEUES(prQue, + &prAdapter->rStaPsQueue[ucStaRecIndex]); + } + prAdapter->u4StaPsBitmap &= ~BIT(ucStaRecIndex); +} + +/*----------------------------------------------------------------------------*/ +/* + * \brief This function is to check the Bss is net absent or not, + * and store MsduInfo(s) or sent MsduInfo(s) to the next + * stage respectively. + * + * \param[in] prAdapter Pointer of Adapter + * \param[in] ucBssIndex Indictate which Bss to be checked + * \param[in] prQue Pointer of MsduInfo queue which to be processed + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +static void nicTxDirectCheckBssAbsentQ(IN struct ADAPTER + *prAdapter, uint8_t ucBssIndex, struct QUE *prQue) +{ + struct BSS_INFO *prBssInfo; + struct MSDU_INFO *prMsduInfo; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + u_int8_t fgReturnBssAbsentQ = FALSE; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + QUEUE_CONCATENATE_QUEUES( + &prAdapter->rBssAbsentQueue[ucBssIndex], prQue); + QUEUE_REMOVE_HEAD(&prAdapter->rBssAbsentQueue[ucBssIndex], + prQueueEntry, struct QUE_ENTRY *); + prMsduInfo = (struct MSDU_INFO *) prQueueEntry; + + if (prMsduInfo == NULL) { + DBGLOG(TX, INFO, "prMsduInfo empty\n"); + return; + } + + if (prBssInfo->fgIsNetAbsent) { + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + DBGLOG(TX, INFO, "fgIsNetAbsent!\n"); + while (1) { + if (prBssInfo->ucBssFreeQuota > 0) { + prBssInfo->ucBssFreeQuota--; + QUEUE_INSERT_TAIL( + prQue, (struct QUE_ENTRY *) prMsduInfo); + DBGLOG(TX, INFO, + "fgIsNetAbsent Quota Availalbe\n"); + } else { + fgReturnBssAbsentQ = TRUE; + DBGLOG(TX, INFO, "fgIsNetAbsent NoQuota\n"); + break; + } + if (QUEUE_IS_NOT_EMPTY( + &prAdapter->rBssAbsentQueue[ucBssIndex])) { + QUEUE_REMOVE_HEAD( + &prAdapter->rBssAbsentQueue[ucBssIndex], + prQueueEntry, struct QUE_ENTRY *); + prMsduInfo = (struct MSDU_INFO *) prQueueEntry; + } else { + break; + } + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + if (fgReturnBssAbsentQ) { + QUEUE_INSERT_HEAD( + &prAdapter->rBssAbsentQueue[ucBssIndex], + (struct QUE_ENTRY *) prMsduInfo); + prAdapter->u4BssAbsentBitmap |= BIT(ucBssIndex); + return; + } + } else { + if (prAdapter->u4BssAbsentBitmap) + DBGLOG(TX, INFO, "fgIsNetAbsent END!\n"); + QUEUE_INSERT_TAIL(prQue, (struct QUE_ENTRY *) prMsduInfo); + if (QUEUE_IS_NOT_EMPTY( + &prAdapter->rBssAbsentQueue[ucBssIndex])) + QUEUE_CONCATENATE_QUEUES(prQue, + &prAdapter->rBssAbsentQueue[ucBssIndex]); + } + prAdapter->u4BssAbsentBitmap &= ~BIT(ucBssIndex); +} + +/*----------------------------------------------------------------------------*/ +/* + * \brief Get Tc for hif port mapping. + * + * \param[in] prMsduInfo Pointer of the MsduInfo + * + * \retval Tc which maps to hif port. + */ +/*----------------------------------------------------------------------------*/ +static uint8_t nicTxDirectGetHifTc(struct MSDU_INFO + *prMsduInfo) +{ + uint8_t ucHifTc = 0; + + if (prMsduInfo->ucTC >= 0 && prMsduInfo->ucTC < TC_NUM) + ucHifTc = prMsduInfo->ucTC; + else + ASSERT(0); + + return ucHifTc; +} + +/*----------------------------------------------------------------------------*/ +/* + * \brief This function is called by nicTxDirectStartXmit() + * and nicTxDirectTimerCheckHifQ(). + * It is the main function to send skb out on HIF bus. + * + * \param[in] prSkb Pointer of the sk_buff to be sent + * \param[in] prMsduInfo Pointer of the MsduInfo + * \param[in] prAdapter Pointer of Adapter + * \param[in] ucCheckTc Indictate which Tc HifQ to be checked + * \param[in] ucStaRecIndex Indictate which StaPsQ to be checked + * \param[in] ucBssIndex Indictate which BssAbsentQ to be checked + * + * \retval WLAN_STATUS + */ +/*----------------------------------------------------------------------------*/ +static uint32_t nicTxDirectStartXmitMain(struct sk_buff + *prSkb, struct MSDU_INFO *prMsduInfo, + struct ADAPTER *prAdapter, + uint8_t ucCheckTc, uint8_t ucStaRecIndex, + uint8_t ucBssIndex) +{ + struct STA_RECORD *prStaRec; /* The current focused STA */ + struct BSS_INFO *prBssInfo; + uint8_t ucTC = 0, ucHifTc = 0; + struct QUE *prTxQue; + u_int8_t fgDropPacket = FALSE; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct QUE rProcessingQue; + struct QUE *prProcessingQue = &rProcessingQue; + uint8_t ucActivedTspec = 0; + + + QUEUE_INITIALIZE(prProcessingQue); + + ucActivedTspec = + wmmHasActiveTspec(aisGetWMMInfo(prAdapter, ucBssIndex)); + + if (prSkb) { + nicTxFillMsduInfo(prAdapter, prMsduInfo, prSkb); + + /* Tx profiling */ + wlanTxProfilingTagMsdu(prAdapter, prMsduInfo, + TX_PROF_TAG_DRV_ENQUE); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prMsduInfo->ucBssIndex); + + if (!prBssInfo) { + /* No BSS_INFO */ + fgDropPacket = TRUE; + } else if (IS_BSS_ACTIVE(prBssInfo)) { + /* BSS active */ + fgDropPacket = FALSE; + } else { + /* BSS inactive */ + fgDropPacket = TRUE; + } + + if (fgDropPacket) { + DBGLOG(QM, TRACE, + "Drop the Packet for inactive Bss %u\n", + prMsduInfo->ucBssIndex); + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_31); + TX_INC_CNT(&prAdapter->rTxCtrl, TX_INACTIVE_BSS_DROP); + + wlanProcessQueuedMsduInfo(prAdapter, prMsduInfo); + return WLAN_STATUS_FAILURE; + } + + qmDetermineStaRecIndex(prAdapter, prMsduInfo); + + wlanUpdateTxStatistics(prAdapter, prMsduInfo, + FALSE); /*get per-AC Tx packets */ + + switch (prMsduInfo->ucStaRecIndex) { + case STA_REC_INDEX_BMCAST: + ucTC = + arNetwork2TcResource[ + prMsduInfo->ucBssIndex][ + NET_TC_BMC_INDEX]; + + /* Always set BMC packet retry limit to unlimited */ + if (!(prMsduInfo->u4Option + & MSDU_OPT_MANUAL_RETRY_LIMIT)) + nicTxSetPktRetryLimit(prMsduInfo, + TX_DESC_TX_COUNT_NO_LIMIT); + + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_23); + break; + case STA_REC_INDEX_NOT_FOUND: + /* Drop packet if no STA_REC is found */ + DBGLOG(QM, TRACE, "Drop the Packet for no STA_REC\n"); + + TX_INC_CNT(&prAdapter->rTxCtrl, TX_INACTIVE_STA_DROP); + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_24); + wlanProcessQueuedMsduInfo(prAdapter, prMsduInfo); + return WLAN_STATUS_FAILURE; + default: + prTxQue = qmDetermineStaTxQueue(prAdapter, prMsduInfo, + ucActivedTspec, &ucTC); + break; /*default */ + } /* switch (prMsduInfo->ucStaRecIndex) */ + + prMsduInfo->ucTC = ucTC; + prMsduInfo->ucWmmQueSet = + prBssInfo->ucWmmQueSet; /* to record WMM Set */ + + /* Check the Tx descriptor template is valid */ + qmSetTxPacketDescTemplate(prAdapter, prMsduInfo); + + /* Set Tx rate */ + switch (prAdapter->rWifiVar.ucDataTxRateMode) { + case DATA_RATE_MODE_BSS_LOWEST: + nicTxSetPktLowestFixedRate(prAdapter, prMsduInfo); + break; + + case DATA_RATE_MODE_MANUAL: + prMsduInfo->u4FixedRateOption = + prAdapter->rWifiVar.u4DataTxRateCode; + + prMsduInfo->ucRateMode = MSDU_RATE_MODE_MANUAL_DESC; + break; + + case DATA_RATE_MODE_AUTO: + default: + if (prMsduInfo->ucRateMode + == MSDU_RATE_MODE_LOWEST_RATE) + nicTxSetPktLowestFixedRate( + prAdapter, prMsduInfo); + break; + } + + nicTxFillDataDesc(prAdapter, prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + + QUEUE_INSERT_TAIL(prProcessingQue, + (struct QUE_ENTRY *) prMsduInfo); + + /* Power-save STA handling */ + nicTxDirectCheckStaPsQ(prAdapter, prMsduInfo->ucStaRecIndex, + prProcessingQue); + + /* Absent BSS handling */ + nicTxDirectCheckBssAbsentQ(prAdapter, + prMsduInfo->ucBssIndex, prProcessingQue); + + if (QUEUE_IS_EMPTY(prProcessingQue)) + return WLAN_STATUS_SUCCESS; + + if (prProcessingQue->u4NumElem != 1) { + while (1) { + QUEUE_REMOVE_HEAD(prProcessingQue, prQueueEntry, + struct QUE_ENTRY *); + if (prQueueEntry == NULL) + break; + prMsduInfo = (struct MSDU_INFO *) prQueueEntry; + ucHifTc = nicTxDirectGetHifTc(prMsduInfo); + QUEUE_INSERT_TAIL( + &prAdapter->rTxDirectHifQueue[ucHifTc], + (struct QUE_ENTRY *) prMsduInfo); + } + nicTxDirectStartCheckQTimer(prAdapter); + return WLAN_STATUS_SUCCESS; + } + + QUEUE_REMOVE_HEAD(prProcessingQue, prQueueEntry, + struct QUE_ENTRY *); + prMsduInfo = (struct MSDU_INFO *) prQueueEntry; + ucHifTc = nicTxDirectGetHifTc(prMsduInfo); + + if (QUEUE_IS_NOT_EMPTY( + &prAdapter->rTxDirectHifQueue[ucHifTc])) { + QUEUE_INSERT_TAIL( + &prAdapter->rTxDirectHifQueue[ucHifTc], + (struct QUE_ENTRY *) prMsduInfo); + QUEUE_REMOVE_HEAD( + &prAdapter->rTxDirectHifQueue[ucHifTc], + prQueueEntry, struct QUE_ENTRY *); + prMsduInfo = (struct MSDU_INFO *) prQueueEntry; + } + } else { + if (ucStaRecIndex != 0xff || ucBssIndex != 0xff) { + /* Power-save STA handling */ + if (ucStaRecIndex != 0xff) + nicTxDirectCheckStaPsQ(prAdapter, ucStaRecIndex, + prProcessingQue); + + /* Absent BSS handling */ + if (ucBssIndex != 0xff) + nicTxDirectCheckBssAbsentQ( + prAdapter, ucBssIndex, + prProcessingQue); + + if (QUEUE_IS_EMPTY(prProcessingQue)) + return WLAN_STATUS_SUCCESS; + + if (prProcessingQue->u4NumElem != 1) { + while (1) { + QUEUE_REMOVE_HEAD( + prProcessingQue, prQueueEntry, + struct QUE_ENTRY *); + if (prQueueEntry == NULL) + break; + prMsduInfo = + (struct MSDU_INFO *) + prQueueEntry; + ucHifTc = + nicTxDirectGetHifTc(prMsduInfo); + QUEUE_INSERT_TAIL( + &prAdapter-> + rTxDirectHifQueue[ucHifTc], + (struct QUE_ENTRY *) + prMsduInfo); + } + nicTxDirectStartCheckQTimer(prAdapter); + return WLAN_STATUS_SUCCESS; + } + + QUEUE_REMOVE_HEAD(prProcessingQue, prQueueEntry, + struct QUE_ENTRY *); + prMsduInfo = (struct MSDU_INFO *) prQueueEntry; + ucHifTc = nicTxDirectGetHifTc(prMsduInfo); + } else { + if (ucCheckTc != 0xff) + ucHifTc = ucCheckTc; + + if (QUEUE_IS_EMPTY( + &prAdapter->rTxDirectHifQueue[ucHifTc])) { + DBGLOG(TX, INFO, + "ERROR: no rTxDirectHifQueue (%u)\n", + ucHifTc); + return WLAN_STATUS_FAILURE; + } + QUEUE_REMOVE_HEAD( + &prAdapter->rTxDirectHifQueue[ucHifTc], + prQueueEntry, struct QUE_ENTRY *); + prMsduInfo = (struct MSDU_INFO *) prQueueEntry; + } + } + + while (1) { + if (!halTxIsDataBufEnough(prAdapter, prMsduInfo)) { + QUEUE_INSERT_HEAD( + &prAdapter->rTxDirectHifQueue[ucHifTc], + (struct QUE_ENTRY *) prMsduInfo); + mod_timer(&prAdapter->rTxDirectHifTimer, + jiffies + TX_DIRECT_CHECK_INTERVAL); + + return WLAN_STATUS_SUCCESS; + } + + if (prMsduInfo->pfTxDoneHandler) { + KAL_SPIN_LOCK_DECLARATION(); + + /* Record native packet pointer for Tx done log */ + WLAN_GET_FIELD_32(&prMsduInfo->prPacket, + &prMsduInfo->u4TxDoneTag); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TXING_MGMT_LIST); + QUEUE_INSERT_TAIL( + &(prAdapter->rTxCtrl.rTxMgmtTxingQueue), + (struct QUE_ENTRY *) prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TXING_MGMT_LIST); + } + HAL_WRITE_TX_DATA(prAdapter, prMsduInfo); + + if (QUEUE_IS_NOT_EMPTY( + &prAdapter->rTxDirectHifQueue[ucHifTc])) { + QUEUE_REMOVE_HEAD( + &prAdapter->rTxDirectHifQueue[ucHifTc], + prQueueEntry, struct QUE_ENTRY *); + prMsduInfo = (struct MSDU_INFO *) prQueueEntry; + if (prMsduInfo == NULL) { + DBGLOG(TX, WARN, + "prMsduInfo is NULL\n"); + break; + } + } else { + break; + } + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/* + * \brief This function is the timeout function of timer rTxDirectSkbTimer. + * The purpose is to check if rTxDirectSkbQueue has any skb to be sent. + * + * \param[in] data Pointer of GlueInfo + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE +void nicTxDirectTimerCheckSkbQ(struct timer_list *timer) +#else +void nicTxDirectTimerCheckSkbQ(unsigned long data) +#endif + +{ +#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE + struct ADAPTER *prAdapter = + from_timer(prAdapter, timer, rTxDirectSkbTimer); + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; +#else + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)data; + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; +#endif + if (skb_queue_len(&prAdapter->rTxDirectSkbQueue)) + nicTxDirectStartXmit(NULL, prGlueInfo); + else + DBGLOG(TX, INFO, "fgHasNoMsdu FALSE\n"); +} + +/*----------------------------------------------------------------------------*/ +/* + * \brief This function is the timeout function of timer rTxDirectHifTimer. + * The purpose is to check if rStaPsQueue, rBssAbsentQueue, + * and rTxDirectHifQueue has any MsduInfo to be sent. + * + * \param[in] data Pointer of GlueInfo + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE +void nicTxDirectTimerCheckHifQ(struct timer_list *timer) +#else +void nicTxDirectTimerCheckHifQ(unsigned long data) +#endif +{ +#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE + struct ADAPTER *prAdapter = + from_timer(prAdapter, timer, rTxDirectHifTimer); + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; +#else + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)data; + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; +#endif + uint8_t ucHifTc = 0; + uint32_t u4StaPsBitmap, u4BssAbsentBitmap; + uint8_t ucStaRecIndex, ucBssIndex; + + spin_lock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + + u4StaPsBitmap = prAdapter->u4StaPsBitmap; + u4BssAbsentBitmap = prAdapter->u4BssAbsentBitmap; + + if (u4StaPsBitmap) + for (ucStaRecIndex = 0; ucStaRecIndex < CFG_STA_REC_NUM; + ++ucStaRecIndex) { + if (QUEUE_IS_NOT_EMPTY( + &prAdapter->rStaPsQueue[ucStaRecIndex])) { + nicTxDirectStartXmitMain(NULL, NULL, prAdapter, + 0xff, ucStaRecIndex, 0xff); + u4StaPsBitmap &= ~BIT(ucStaRecIndex); + DBGLOG(TX, INFO, + "ucStaRecIndex: %u\n", ucStaRecIndex); + } + if (u4StaPsBitmap == 0) + break; + } + + if (u4BssAbsentBitmap) + for (ucBssIndex = 0; ucBssIndex < MAX_BSSID_NUM + 1; + ++ucBssIndex) { + if (QUEUE_IS_NOT_EMPTY( + &prAdapter->rBssAbsentQueue[ucBssIndex])) { + nicTxDirectStartXmitMain(NULL, NULL, prAdapter, + 0xff, 0xff, ucBssIndex); + u4BssAbsentBitmap &= ~BIT(ucBssIndex); + DBGLOG(TX, INFO, + "ucBssIndex: %u\n", ucBssIndex); + } + if (u4BssAbsentBitmap == 0) + break; + } + + + for (ucHifTc = 0; ucHifTc < TX_PORT_NUM; ucHifTc++) + if (QUEUE_IS_NOT_EMPTY( + &prAdapter->rTxDirectHifQueue[ucHifTc])) + nicTxDirectStartXmitMain(NULL, NULL, prAdapter, ucHifTc, + 0xff, 0xff); + + spin_unlock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); +} + +/*----------------------------------------------------------------------------*/ +/* + * \brief This function is have to called by kalHardStartXmit(). + * The purpose is to let as many as possible TX processing in softirq + * instead of in kernel thread to reduce TX CPU usage. + * NOTE: Currently only USB interface can use this function. + * + * \param[in] prSkb Pointer of the sk_buff to be sent + * \param[in] prGlueInfo Pointer of prGlueInfo + * + * \retval WLAN_STATUS + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxDirectStartXmit(struct sk_buff *prSkb, + struct GLUE_INFO *prGlueInfo) +{ + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + struct MSDU_INFO *prMsduInfo; + uint32_t ret = WLAN_STATUS_SUCCESS; + + spin_lock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + + if (prSkb) { + prMsduInfo = cnmPktAlloc(prAdapter, 0); + + if (prMsduInfo == NULL) { + DBGLOG(TX, INFO, "cnmPktAlloc NULL\n"); + skb_queue_tail(&prAdapter->rTxDirectSkbQueue, prSkb); + + ret = WLAN_STATUS_SUCCESS; + goto end; + } + if (skb_queue_len(&prAdapter->rTxDirectSkbQueue)) { + skb_queue_tail(&prAdapter->rTxDirectSkbQueue, prSkb); + prSkb = skb_dequeue(&prAdapter->rTxDirectSkbQueue); + } + } else { + prMsduInfo = cnmPktAlloc(prAdapter, 0); + if (prMsduInfo != NULL) { + prSkb = skb_dequeue(&prAdapter->rTxDirectSkbQueue); + if (prSkb == NULL) { + DBGLOG(TX, INFO, + "ERROR: no rTxDirectSkbQueue\n"); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + ret = WLAN_STATUS_FAILURE; + goto end; + } + } else { + ret = WLAN_STATUS_FAILURE; + goto end; + } + } + + while (1) { + nicTxDirectStartXmitMain(prSkb, prMsduInfo, prAdapter, 0xff, + 0xff, 0xff); + prSkb = skb_dequeue(&prAdapter->rTxDirectSkbQueue); + if (prSkb != NULL) { + prMsduInfo = cnmPktAlloc(prAdapter, 0); + if (prMsduInfo == NULL) { + skb_queue_head(&prAdapter->rTxDirectSkbQueue, + prSkb); + break; + } + } else { + break; + } + } + +end: + if (skb_queue_len(&prAdapter->rTxDirectSkbQueue)) + mod_timer(&prAdapter->rTxDirectSkbTimer, + jiffies + TX_DIRECT_CHECK_INTERVAL); + spin_unlock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + return ret; +} +/* TX Direct functions : END */ + + +/*----------------------------------------------------------------------------*/ +/* + * \brief Assign Tc resource to prWifiVar according to firmware's report + * + * \param[in] prSkb Pointer of the sk_buff to be sent + * \param[in] prGlueInfo Pointer of prGlueInfo + * + */ +/*----------------------------------------------------------------------------*/ + +void nicTxResourceUpdate_v1(IN struct ADAPTER *prAdapter) +{ + uint8_t string[128], idx, i, tc_num, ret = 0; + uint32_t u4share, u4remains; + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; + uint32_t *pau4TcPageCount; +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + struct QUE_MGT *prQM = &prAdapter->rQM; +#endif + + + /* + * Use the settings in config file first, + * else, use the settings reported from firmware. + */ + + + /* + * 1. assign PSE/PLE free page count for each TC + */ + + tc_num = (TC_NUM - 1); /* except TC4_INDEX */ + for (i = 0; i < 2; i++) { + if (i == 0) { + /* PSE CMD*/ + prWifiVar->au4TcPageCount[TC4_INDEX] = + prAdapter->nicTxReousrce.u4CmdTotalResource; + + /* calculate PSE free page count for each TC, + * except TC_4 + */ + u4share = prAdapter->nicTxReousrce.u4DataTotalResource / + tc_num; + u4remains = prAdapter->nicTxReousrce. + u4DataTotalResource % tc_num; + pau4TcPageCount = prWifiVar->au4TcPageCount; + } else { + /* PLE CMD*/ + prWifiVar->au4TcPageCountPle[TC4_INDEX] = + prAdapter->nicTxReousrce.u4CmdTotalResourcePle; + + /* calculate PLE free page count for each TC, + * except TC_4 + */ + u4share = prAdapter->nicTxReousrce. + u4DataTotalResourcePle / tc_num; + u4remains = prAdapter->nicTxReousrce. + u4DataTotalResourcePle % tc_num; + pau4TcPageCount = prWifiVar->au4TcPageCountPle; + } + + /* assign free page count for each TC, except TC_4 */ + for (idx = TC0_INDEX; idx < TC_NUM; idx++) { + if (idx != TC4_INDEX) + pau4TcPageCount[idx] = u4share; + } + /* if there is remaings, give them to TC_3, which is VO */ + pau4TcPageCount[TC3_INDEX] += u4remains; + } + + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + /* + * 2. assign guaranteed page count for each TC + */ + + /* 2 1. update guaranteed page count in QM */ + for (idx = 0; idx < TC_NUM; idx++) + prQM->au4GuaranteedTcResource[idx] = + prWifiVar->au4TcPageCount[idx]; +#endif + + + +#if CFG_SUPPORT_CFG_FILE + /* + * 3. Use the settings in config file first, + * else, use the settings reported from firmware. + */ + + /* 3 1. update for free page count */ + for (idx = 0; idx < TC_NUM; idx++) { + + /* construct prefix: Tc0Page, Tc1Page... */ + memset(string, 0, sizeof(string) / sizeof(uint8_t)); + ret = snprintf(string, sizeof(string) / sizeof(uint8_t), + "Tc%xPage", idx); + if (ret > (sizeof(string) / sizeof(uint8_t))) { + DBGLOG(NIC, INFO, + "sprintf failed of page count:%d\n", ret); + } else { + /* update the final value */ + prWifiVar->au4TcPageCount[idx] = + (uint32_t) wlanCfgGetUint32(prAdapter, + string, prWifiVar->au4TcPageCount[idx]); + } + } + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + /* 3 2. update for guaranteed page count */ + for (idx = 0; idx < TC_NUM; idx++) { + + /* construct prefix: Tc0Grt, Tc1Grt... */ + memset(string, 0, sizeof(string) / sizeof(uint8_t)); + ret = snprintf(string, sizeof(string) / sizeof(uint8_t), + "Tc%xGrt", idx); + if (ret > (sizeof(string) / sizeof(uint8_t))) { + DBGLOG(NIC, INFO, + "sprintf failed of guaranteed page count:%d\n", ret); + } else { + /* update the final value */ + prQM->au4GuaranteedTcResource[idx] = + (uint32_t) wlanCfgGetUint32(prAdapter, + string, prQM->au4GuaranteedTcResource[idx]); + } + } +#endif /* end of #if QM_ADAPTIVE_TC_RESOURCE_CTRL */ +#endif /* end of #if CFG_SUPPORT_CFG_FILE */ + + + + + /* + * 4. Peak throughput settings. + * Give most of the resource to TC1_INDEX. + * Reference to arNetwork2TcResource[], AC_BE uses TC1_INDEX. + */ + if (prAdapter->rWifiVar.ucTpTestMode == + ENUM_TP_TEST_MODE_THROUGHPUT) { + uint32_t u4psePageCnt, u4plePageCnt, u4pseRemain, + u4pleRemain; +#define DEFAULT_PACKET_NUM 5 + + + /* pse */ + u4pseRemain = prAdapter->nicTxReousrce.u4DataTotalResource; + u4psePageCnt = DEFAULT_PACKET_NUM * + nicTxGetMaxPageCntPerFrame(prAdapter); + + /* ple */ + u4pleRemain = + prAdapter->nicTxReousrce.u4DataTotalResourcePle; + u4plePageCnt = DEFAULT_PACKET_NUM * + NIX_TX_PLE_PAGE_CNT_PER_FRAME; + + /* equally giving to each TC */ + for (idx = 0; idx < TC_NUM; idx++) { + if (idx == TC4_INDEX) + continue; + + /* pse */ + prWifiVar->au4TcPageCount[idx] = u4psePageCnt; + u4pseRemain -= u4psePageCnt; + + /* ple */ + prWifiVar->au4TcPageCountPle[idx] = u4plePageCnt; + u4pleRemain -= u4plePageCnt; + } + + /* remaings are to TC1_INDEX */ + prWifiVar->au4TcPageCount[TC1_INDEX] += u4pseRemain; + prWifiVar->au4TcPageCountPle[TC1_INDEX] += u4pleRemain; + } +} + +void nicTxChangeDataPortByAc( + struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t ucAci, + u_int8_t fgToMcu) +{ + struct TX_DESC_OPS_T *prTxDescOps = prAdapter->chip_info->prTxDescOps; + + if (prTxDescOps->nic_txd_change_data_port_by_ac) + prTxDescOps->nic_txd_change_data_port_by_ac( + prStaRec, + ucAci, + fgToMcu); +} + +/* if some msdus are waiting tx done status, but now roaming done, then need to +** change wlan index of these msdus to match tx done status event +** In multi-thread solution, we also need to check if pending tx packets in +** hif_thread tx queue. +*/ +void nicTxHandleRoamingDone(struct ADAPTER *prAdapter, + struct STA_RECORD *prOldStaRec, + struct STA_RECORD *prNewStaRec) +{ + struct MSDU_INFO *prMsduInfo = NULL; + uint8_t ucOldWlanIndex = prOldStaRec->ucWlanIndex; + uint8_t ucNewWlanIndex = prNewStaRec->ucWlanIndex; + uint8_t ucIndex = 0, i; + + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + prMsduInfo = (struct MSDU_INFO *)QUEUE_GET_HEAD( + &prAdapter->rTxCtrl.rTxMgmtTxingQueue); + while (prMsduInfo) { + if (prMsduInfo->ucWlanIndex == ucOldWlanIndex) + prMsduInfo->ucWlanIndex = ucNewWlanIndex; + prMsduInfo = (struct MSDU_INFO *)QUEUE_GET_NEXT_ENTRY( + &prMsduInfo->rQueEntry); + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + +/* I think any time we disconnect with previous AP, rTxP0Queue and rTxP1Queue +** should be empty. +** because we have stopped dequeue when initial to connect the new roaming AP. +** It is enough time for hif_thread to send out these packets. But anyway, let's +** prepare code for that case to avoid scheduler corner case. +*/ +#if CFG_SUPPORT_MULTITHREAD + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); +#if CFG_FIX_2_TX_PORT + prMsduInfo = (struct MSDU_INFO *)QUEUE_GET_HEAD(&prAdapter->rTxP0Queue); + while (prMsduInfo) { + if (prMsduInfo->ucWlanIndex == ucOldWlanIndex) + prMsduInfo->ucWlanIndex = ucNewWlanIndex; + prMsduInfo = (struct MSDU_INFO *)QUEUE_GET_NEXT_ENTRY( + &prMsduInfo->rQueEntry); + } + prMsduInfo = (struct MSDU_INFO *)QUEUE_GET_HEAD(&prAdapter->rTxP1Queue); + while (prMsduInfo) { + if (prMsduInfo->ucWlanIndex == ucOldWlanIndex) + prMsduInfo->ucWlanIndex = ucNewWlanIndex; + prMsduInfo = (struct MSDU_INFO *)QUEUE_GET_NEXT_ENTRY( + &prMsduInfo->rQueEntry); + } +#else + for (i = 0; i < BSS_DEFAULT_NUM; i++) { + for (ucIndex = 0; ucIndex < TX_PORT_NUM; ucIndex++) { + prMsduInfo = (struct MSDU_INFO *)QUEUE_GET_HEAD( + &prAdapter->rTxPQueue[i][ucIndex]); + while (prMsduInfo) { + if (prMsduInfo->ucWlanIndex == ucOldWlanIndex) + prMsduInfo->ucWlanIndex = + ucNewWlanIndex; + prMsduInfo = + (struct MSDU_INFO *) QUEUE_GET_NEXT_ENTRY( + &prMsduInfo->rQueEntry); + } + } + } +#endif + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); +#endif +} + +int32_t nicTxGetVectorInfo(IN char *pcCommand, IN int i4TotalLen, + IN struct TX_VECTOR_BBP_LATCH *prTxV) +{ + uint8_t rate, txmode, frmode, sgi, ldpc, nsts, stbc, txpwr; + int32_t i4BytesWritten = 0; + + rate = TX_VECTOR_GET_TX_RATE(prTxV); + txmode = TX_VECTOR_GET_TX_MODE(prTxV); + frmode = TX_VECTOR_GET_TX_FRMODE(prTxV); + nsts = TX_VECTOR_GET_TX_NSTS(prTxV) + 1; + sgi = TX_VECTOR_GET_TX_SGI(prTxV); + ldpc = TX_VECTOR_GET_TX_LDPC(prTxV); + stbc = TX_VECTOR_GET_TX_STBC(prTxV); + txpwr = TX_VECTOR_GET_TX_PWR(prTxV); + + if (prTxV->u4TxV[0] == 0xFFFFFFFF) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Last TX Rate", " = ", "N/A"); + } else { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s", "Last TX Rate", " = "); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", rate < 4 ? HW_TX_RATE_CCK_STR[rate] : + HW_TX_RATE_CCK_STR[4]); + else if (txmode == TX_RATE_MODE_OFDM) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", nicHwRateOfdmStr(rate)); + else if ((txmode == TX_RATE_MODE_HTMIX) || + (txmode == TX_RATE_MODE_HTGF)) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "MCS%d, ", rate); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s%d_MCS%d, ", stbc ? "NSTS" : "NSS", + nsts, rate); + + if (txmode == TX_RATE_MODE_HE_ER) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + frmode > 0 ? "106-RU" : "242-RU"); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + frmode < 4 ? HW_TX_RATE_BW[frmode] : + HW_TX_RATE_BW[4]); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", rate < 4 ? "LP" : "SP"); + else if (txmode == TX_RATE_MODE_OFDM) + ; + else if ((txmode == TX_RATE_MODE_HTMIX) || + (txmode == TX_RATE_MODE_HTGF) || + (txmode == TX_RATE_MODE_VHT) || + (txmode == TX_RATE_MODE_PLR)) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", sgi == 0 ? "LGI" : "SGI"); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", sgi == 0 ? "LGI" : + (sgi == 1 ? "SGI" : "MGI")); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s%s%s\n", + txmode < 5 ? HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5], + stbc ? ", STBC, " : ", ", ldpc == 0 ? "BCC" : "LDPC"); + } + + return i4BytesWritten; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_txd_v1.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_txd_v1.c new file mode 100644 index 0000000000000..dcd14df4ba2fc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_txd_v1.c @@ -0,0 +1,765 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_tx.c#2 + */ + +/*! \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. + */ + + +/******************************************************************************* + * C O M P I L E 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 + ******************************************************************************* + */ +uint8_t nic_txd_v1_long_format_op( + void *prTxDesc, + uint8_t fgSet) +{ + if (fgSet) + HAL_MAC_TX_DESC_SET_LONG_FORMAT( + (struct HW_MAC_TX_DESC *)prTxDesc); + return HAL_MAC_TX_DESC_IS_LONG_FORMAT( + (struct HW_MAC_TX_DESC *)prTxDesc); +} + +uint8_t nic_txd_v1_tid_op( + void *prTxDesc, + uint8_t ucTid, + uint8_t fgSet) +{ + if (fgSet) + HAL_MAC_TX_DESC_SET_TID( + (struct HW_MAC_TX_DESC *)prTxDesc, ucTid); + return HAL_MAC_TX_DESC_GET_TID( + (struct HW_MAC_TX_DESC *)prTxDesc); +} + +uint8_t nic_txd_v1_queue_idx_op( + void *prTxDesc, + uint8_t ucQueIdx, + uint8_t fgSet) +{ + if (fgSet) + HAL_MAC_TX_DESC_SET_QUEUE_INDEX( + (struct HW_MAC_TX_DESC *)prTxDesc, ucQueIdx); + return HAL_MAC_TX_DESC_GET_QUEUE_INDEX( + (struct HW_MAC_TX_DESC *)prTxDesc); +} + +#if (CFG_TCP_IP_CHKSUM_OFFLOAD == 1) +void nic_txd_v1_chksum_op( + void *prTxDesc, + uint8_t ucChksumFlag) +{ + if ((ucChksumFlag & TX_CS_IP_GEN)) + HAL_MAC_TX_DESC_SET_IP_CHKSUM( + (struct HW_MAC_TX_DESC *)prTxDesc); + if ((ucChksumFlag & TX_CS_TCP_UDP_GEN)) + HAL_MAC_TX_DESC_SET_TCP_UDP_CHKSUM( + (struct HW_MAC_TX_DESC *)prTxDesc); +} +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD == 1 */ + +void nic_txd_v1_header_format_op( + void *prTxDesc, + struct MSDU_INFO *prMsduInfo) +{ + if (!prMsduInfo->fgIs802_11) { + if (prMsduInfo->fgIs802_3) + HAL_MAC_TX_DESC_UNSET_ETHERNET_II( + (struct HW_MAC_TX_DESC *)prTxDesc); + if (prMsduInfo->fgIsVlanExists) + HAL_MAC_TX_DESC_SET_VLAN( + (struct HW_MAC_TX_DESC *)prTxDesc); + } +} + +void nic_txd_v1_fill_by_pkt_option( + struct MSDU_INFO *prMsduInfo, + void *prTxD) +{ + struct HW_MAC_TX_DESC *prTxDesc = (struct HW_MAC_TX_DESC *)prTxD; + uint32_t u4PktOption = prMsduInfo->u4Option; + u_int8_t fgIsLongFormat; + u_int8_t fgProtected = FALSE; + + /* Skip this function if no options is set */ + if (!u4PktOption) + return; + + fgIsLongFormat = HAL_MAC_TX_DESC_IS_LONG_FORMAT(prTxDesc); + + /* Fields in DW0 and DW1 (Short Format) */ + if (u4PktOption & MSDU_OPT_NO_ACK) + HAL_MAC_TX_DESC_SET_NO_ACK(prTxDesc); + + if (u4PktOption & MSDU_OPT_PROTECTED_FRAME) { + /* DBGLOG(RSN, INFO, "MSDU_OPT_PROTECTED_FRAME\n"); */ + HAL_MAC_TX_DESC_SET_PROTECTION(prTxDesc); + fgProtected = TRUE; + } + + switch (HAL_MAC_TX_DESC_GET_HEADER_FORMAT(prTxDesc)) { + case HEADER_FORMAT_802_11_ENHANCE_MODE: + if (u4PktOption & MSDU_OPT_EOSP) + HAL_MAC_TX_DESC_SET_EOSP(prTxDesc); + + if (u4PktOption & MSDU_OPT_AMSDU) + HAL_MAC_TX_DESC_SET_AMSDU(prTxDesc); + break; + + case HEADER_FORMAT_NON_802_11: + if (u4PktOption & MSDU_OPT_EOSP) + HAL_MAC_TX_DESC_SET_EOSP(prTxDesc); + + if (u4PktOption & MSDU_OPT_MORE_DATA) + HAL_MAC_TX_DESC_SET_MORE_DATA(prTxDesc); + + if (u4PktOption & MSDU_OPT_REMOVE_VLAN) + HAL_MAC_TX_DESC_SET_REMOVE_VLAN(prTxDesc); + break; + + case HEADER_FORMAT_802_11_NORMAL_MODE: + if (fgProtected && prMsduInfo->prPacket) { + struct WLAN_MAC_HEADER *prWlanHeader = + (struct WLAN_MAC_HEADER *) ((unsigned long) ( + prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prWlanHeader->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + } + break; + + default: + break; + } + + if (!fgIsLongFormat) + return; + + /* Fields in DW2~6 (Long Format) */ + if (u4PktOption & MSDU_OPT_NO_AGGREGATE) + HAL_MAC_TX_DESC_SET_BA_DISABLE(prTxDesc); + + if (u4PktOption & MSDU_OPT_TIMING_MEASURE) + HAL_MAC_TX_DESC_SET_TIMING_MEASUREMENT(prTxDesc); + + if (u4PktOption & MSDU_OPT_NDP) + HAL_MAC_TX_DESC_SET_NDP(prTxDesc); + + if (u4PktOption & MSDU_OPT_NDPA) + HAL_MAC_TX_DESC_SET_NDPA(prTxDesc); + + if (u4PktOption & MSDU_OPT_SOUNDING) + HAL_MAC_TX_DESC_SET_SOUNDING_FRAME(prTxDesc); + + if (u4PktOption & MSDU_OPT_FORCE_RTS) + HAL_MAC_TX_DESC_SET_FORCE_RTS_CTS(prTxDesc); + + if (u4PktOption & MSDU_OPT_BIP) + HAL_MAC_TX_DESC_SET_BIP(prTxDesc); + + /* SW field */ + if (u4PktOption & MSDU_OPT_SW_DURATION) + HAL_MAC_TX_DESC_SET_DURATION_CONTROL_BY_SW(prTxDesc); + + if (u4PktOption & MSDU_OPT_SW_PS_BIT) + HAL_MAC_TX_DESC_SET_SW_PM_CONTROL(prTxDesc); + + if (u4PktOption & MSDU_OPT_SW_HTC) + HAL_MAC_TX_DESC_SET_HTC_EXIST(prTxDesc); +#if 0 + if (u4PktOption & MSDU_OPT_SW_BAR_SN) + HAL_MAC_TX_DESC_SET_SW_BAR_SSN(prTxDesc); +#endif + if (u4PktOption & MSDU_OPT_MANUAL_SN) { + HAL_MAC_TX_DESC_SET_TXD_SN_VALID(prTxDesc); + HAL_MAC_TX_DESC_SET_SEQUENCE_NUMBER(prTxDesc, + prMsduInfo->u2SwSN); + } + +} + +void nic_txd_v1_fill_by_pkt_ctrl( + struct MSDU_INFO *prMsduInfo, + void *prTxD) +{ + struct HW_MAC_TX_DESC *prTxDesc = (struct HW_MAC_TX_DESC *)prTxD; + uint8_t ucPktControl = prMsduInfo->ucControlFlag; + uint8_t ucSwReserved; + + /* Skip this function if no options is set */ + if (!ucPktControl) + return; + + if (HAL_MAC_TX_DESC_IS_LONG_FORMAT(prTxDesc)) { + ucSwReserved = HAL_MAC_TX_DESC_GET_SW_RESERVED(prTxDesc); + + if (ucPktControl & MSDU_CONTROL_FLAG_FORCE_TX) + ucSwReserved |= MSDU_CONTROL_FLAG_FORCE_TX; + + HAL_MAC_TX_DESC_SET_SW_RESERVED(prTxDesc, ucSwReserved); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief In this function, we'll compose the Tx descriptor of the MSDU. + * + * @param prAdapter Pointer to the Adapter structure. + * @param prMsduInfo Pointer to the Msdu info + * @param prTxDesc Pointer to the Tx descriptor buffer + * + * @retval VOID + */ +/*----------------------------------------------------------------------------*/ +void nic_txd_v1_compose( + struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + uint32_t u4TxDescLength, + u_int8_t fgIsTemplate, + uint8_t *prTxDescBuffer) +{ + struct HW_MAC_TX_DESC *prTxDesc; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + uint8_t ucEtherTypeOffsetInWord; + uint32_t u4TxDescAndPaddingLength; + uint8_t ucTarPort, ucTarQueue; +#if ((CFG_SISO_SW_DEVELOP == 1) || (CFG_SUPPORT_SPE_IDX_CONTROL == 1)) + enum ENUM_WF_PATH_FAVOR_T eWfPathFavor; +#endif + prTxDesc = (struct HW_MAC_TX_DESC *) prTxDescBuffer; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prMsduInfo->ucBssIndex); + prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + + u4TxDescAndPaddingLength = u4TxDescLength + + NIC_TX_DESC_PADDING_LENGTH; + + kalMemZero(prTxDesc, u4TxDescAndPaddingLength); + + /* Move to nicTxFillDesc */ + /* Tx byte count */ + /* HAL_MAC_TX_DESC_SET_TX_BYTE_COUNT(prTxDesc, + * ucTxDescAndPaddingLength + prMsduInfo->u2FrameLength); + */ + + /* Ether-type offset */ + if (prMsduInfo->fgIs802_11) { + ucEtherTypeOffsetInWord = + (NIC_TX_PSE_HEADER_LENGTH + + prMsduInfo->ucMacHeaderLength + + prMsduInfo->ucLlcLength) >> 1; + } else { + ucEtherTypeOffsetInWord = ((ETHER_HEADER_LEN - + ETHER_TYPE_LEN) + NIC_TX_PSE_HEADER_LENGTH) >> 1; + } + HAL_MAC_TX_DESC_SET_ETHER_TYPE_OFFSET(prTxDesc, + ucEtherTypeOffsetInWord); + + /* Port index / queue index */ + ucTarPort = nicTxGetTxDestPortIdxByTc(prMsduInfo->ucTC); + HAL_MAC_TX_DESC_SET_PORT_INDEX(prTxDesc, ucTarPort); + + ucTarQueue = nicTxGetTxDestQIdxByTc(prMsduInfo->ucTC); + if (ucTarPort == PORT_INDEX_LMAC) + ucTarQueue += (prBssInfo->ucWmmQueSet * WMM_AC_INDEX_NUM); + + HAL_MAC_TX_DESC_SET_QUEUE_INDEX(prTxDesc, ucTarQueue); + + /* BMC packet */ + if (prMsduInfo->ucStaRecIndex == STA_REC_INDEX_BMCAST) { + HAL_MAC_TX_DESC_SET_BMC(prTxDesc); + + /* Must set No ACK to mask retry bit in FC */ + HAL_MAC_TX_DESC_SET_NO_ACK(prTxDesc); + } + /* WLAN index */ + prMsduInfo->ucWlanIndex = nicTxGetWlanIdx(prAdapter, + prMsduInfo->ucBssIndex, prMsduInfo->ucStaRecIndex); + +#if 0 /* DBG */ + DBGLOG(RSN, INFO, + "Tx WlanIndex = %d eAuthMode = %d\n", + prMsduInfo->ucWlanIndex, + prAdapter->rWifiVar.rConnSettings.eAuthMode); +#endif + HAL_MAC_TX_DESC_SET_WLAN_INDEX(prTxDesc, + prMsduInfo->ucWlanIndex); + + /* Header format */ + if (prMsduInfo->fgIs802_11) { + HAL_MAC_TX_DESC_SET_HEADER_FORMAT(prTxDesc, + HEADER_FORMAT_802_11_NORMAL_MODE); + HAL_MAC_TX_DESC_SET_802_11_HEADER_LENGTH(prTxDesc, + (prMsduInfo->ucMacHeaderLength >> 1)); + } else { + HAL_MAC_TX_DESC_SET_HEADER_FORMAT(prTxDesc, + HEADER_FORMAT_NON_802_11); + HAL_MAC_TX_DESC_SET_ETHERNET_II(prTxDesc); + } + + /* Header Padding */ + HAL_MAC_TX_DESC_SET_HEADER_PADDING(prTxDesc, + NIC_TX_DESC_HEADER_PADDING_LENGTH); + + /* TID */ + HAL_MAC_TX_DESC_SET_TID(prTxDesc, + prMsduInfo->ucUserPriority); + + /* Protection */ + if (secIsProtectedFrame(prAdapter, prMsduInfo, prStaRec)) { + /* Update Packet option, + * PF bit will be set in nicTxFillDescByPktOption() + */ + if ((prStaRec && prStaRec->fgTransmitKeyExist) + || fgIsTemplate) { + nicTxConfigPktOption( + prMsduInfo, MSDU_OPT_PROTECTED_FRAME, + TRUE); + + if (prMsduInfo->fgIs802_1x && + prMsduInfo->fgIs802_1x_NonProtected) { + nicTxConfigPktOption( + prMsduInfo, MSDU_OPT_PROTECTED_FRAME, + FALSE); + DBGLOG(RSN, LOUD, + "Pairwise EAPoL not protect!\n"); + } + } else if (prMsduInfo->ucStaRecIndex == + STA_REC_INDEX_BMCAST) {/* BMC packet */ + nicTxConfigPktOption(prMsduInfo, + MSDU_OPT_PROTECTED_FRAME, + TRUE); + DBGLOG(RSN, LOUD, "Protect BMC frame!\n"); + } + } +#if (UNIFIED_MAC_TX_FORMAT == 1) + /* Packet Format */ + HAL_MAC_TX_DESC_SET_PKT_FORMAT(prTxDesc, + prMsduInfo->ucPacketFormat); +#endif + + /* Own MAC */ + HAL_MAC_TX_DESC_SET_OWN_MAC_INDEX(prTxDesc, + prBssInfo->ucOwnMacIndex); + + if (u4TxDescLength == NIC_TX_DESC_SHORT_FORMAT_LENGTH) { + HAL_MAC_TX_DESC_SET_SHORT_FORMAT(prTxDesc); + + /* Update Packet option */ + nic_txd_v1_fill_by_pkt_option(prMsduInfo, prTxDesc); + + /* Short format, Skip DW 2~6 */ + return; + } + HAL_MAC_TX_DESC_SET_LONG_FORMAT(prTxDesc); + + /* Update Packet option */ + nic_txd_v1_fill_by_pkt_option(prMsduInfo, prTxDesc); + + nic_txd_v1_fill_by_pkt_ctrl(prMsduInfo, prTxDesc); + + /* Type */ + if (prMsduInfo->fgIs802_11) { + struct WLAN_MAC_HEADER *prWlanHeader = + (struct WLAN_MAC_HEADER *) ((unsigned long) ( + prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + HAL_MAC_TX_DESC_SET_TYPE(prTxDesc, + (prWlanHeader->u2FrameCtrl & MASK_FC_TYPE) >> 2); + HAL_MAC_TX_DESC_SET_SUB_TYPE(prTxDesc, + (prWlanHeader->u2FrameCtrl & MASK_FC_SUBTYPE) >> + OFFSET_OF_FC_SUBTYPE); + } + /* PID */ + if (prMsduInfo->pfTxDoneHandler) { + prMsduInfo->ucPID = nicTxAssignPID(prAdapter, + prMsduInfo->ucWlanIndex); + HAL_MAC_TX_DESC_SET_PID(prTxDesc, prMsduInfo->ucPID); + HAL_MAC_TX_DESC_SET_TXS_TO_MCU(prTxDesc); + } else if (prAdapter->rWifiVar.ucDataTxDone == 2) { + /* Log mode: only TxS to FW, no event to driver */ + HAL_MAC_TX_DESC_SET_PID(prTxDesc, NIC_TX_DESC_PID_RESERVED); + HAL_MAC_TX_DESC_SET_TXS_TO_MCU(prTxDesc); + } + + /* Remaining TX time */ + if (!(prMsduInfo->u4Option & MSDU_OPT_MANUAL_LIFE_TIME)) + prMsduInfo->u4RemainingLifetime = + nicTxGetRemainingTxTimeByTc(prMsduInfo->ucTC); + HAL_MAC_TX_DESC_SET_REMAINING_LIFE_TIME_IN_MS(prTxDesc, + prMsduInfo->u4RemainingLifetime); + + /* Tx count limit */ + if (!(prMsduInfo->u4Option & MSDU_OPT_MANUAL_RETRY_LIMIT)) { + /* Note: BMC packet retry limit is set to unlimited */ + prMsduInfo->ucRetryLimit = + nicTxGetTxCountLimitByTc(prMsduInfo->ucTC); + } + HAL_MAC_TX_DESC_SET_REMAINING_TX_COUNT(prTxDesc, + prMsduInfo->ucRetryLimit); + + /* Power Offset */ + HAL_MAC_TX_DESC_SET_POWER_OFFSET(prTxDesc, + prMsduInfo->cPowerOffset); + + /* Fix rate */ + switch (prMsduInfo->ucRateMode) { + case MSDU_RATE_MODE_MANUAL_DESC: + HAL_MAC_TX_DESC_SET_DW(prTxDesc, 6, 1, + &prMsduInfo->u4FixedRateOption); +#if ((CFG_SISO_SW_DEVELOP == 1) || (CFG_SUPPORT_SPE_IDX_CONTROL == 1)) + /* Update spatial extension index setting */ + eWfPathFavor = wlanGetAntPathType(prAdapter, ENUM_WF_NON_FAVOR); + HAL_MAC_TX_DESC_SET_SPE_IDX(prTxDesc, + wlanGetSpeIdx(prAdapter, prBssInfo->ucBssIndex, + eWfPathFavor)); +#endif + /* Set SPE_IDX_SEL to: + * 0: reference SPE_IDX configuration in TXD + * 1: reference SPE_IDX configuration in WTBL + */ + HAL_MAC_TX_DESC_SET_SPE_IDX_SEL(prTxDesc, 0); + HAL_MAC_TX_DESC_SET_FIXED_RATE_MODE_TO_DESC(prTxDesc); + HAL_MAC_TX_DESC_SET_FIXED_RATE_ENABLE(prTxDesc); + break; + + case MSDU_RATE_MODE_MANUAL_CR: + HAL_MAC_TX_DESC_SET_FIXED_RATE_MODE_TO_CR(prTxDesc); + HAL_MAC_TX_DESC_SET_FIXED_RATE_ENABLE(prTxDesc); + break; + + case MSDU_RATE_MODE_AUTO: + default: + break; + } + +} + + +void nic_txd_v1_compose_security_frame( + struct ADAPTER *prAdapter, + struct CMD_INFO *prCmdInfo, + uint8_t *prTxDescBuffer, + uint8_t *pucTxDescLength) +{ + struct HW_MAC_TX_DESC *prTxDesc = (struct HW_MAC_TX_DESC *) + prTxDescBuffer; + uint8_t ucTxDescAndPaddingLength = + NIC_TX_DESC_LONG_FORMAT_LENGTH + NIC_TX_DESC_PADDING_LENGTH; + + struct BSS_INFO *prBssInfo; + uint8_t ucTid = 0; + uint8_t ucTempTC = TC4_INDEX; + void *prNativePacket; + uint8_t ucEtherTypeOffsetInWord; + struct MSDU_INFO *prMsduInfo; + + prMsduInfo = prCmdInfo->prMsduInfo; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prMsduInfo->ucBssIndex); + prNativePacket = prMsduInfo->prPacket; + + ASSERT(prNativePacket); + + kalMemZero(prTxDesc, ucTxDescAndPaddingLength); + + /* WLAN index */ + prMsduInfo->ucWlanIndex = nicTxGetWlanIdx(prAdapter, + prMsduInfo->ucBssIndex, prMsduInfo->ucStaRecIndex); + + /* UC to a connected peer */ + HAL_MAC_TX_DESC_SET_WLAN_INDEX(prTxDesc, + prMsduInfo->ucWlanIndex); + /* Redirect Security frame to TID0 */ + /* ucTempTC = arNetwork2TcResource[prStaRec->ucBssIndex] + * [aucTid2ACI[ucTid]]; + */ + + /* Tx byte count */ + HAL_MAC_TX_DESC_SET_TX_BYTE_COUNT(prTxDesc, + ucTxDescAndPaddingLength + prCmdInfo->u2InfoBufLen); + + /* Ether-type offset */ + ucEtherTypeOffsetInWord = ((ETHER_HEADER_LEN - + ETHER_TYPE_LEN) + NIC_TX_PSE_HEADER_LENGTH) >> 1; + HAL_MAC_TX_DESC_SET_ETHER_TYPE_OFFSET(prTxDesc, + ucEtherTypeOffsetInWord); + + /* Port index / queue index */ + HAL_MAC_TX_DESC_SET_PORT_INDEX(prTxDesc, + nicTxGetTxDestPortIdxByTc(ucTempTC)); + HAL_MAC_TX_DESC_SET_QUEUE_INDEX(prTxDesc, + nicTxGetTxDestQIdxByTc(ucTempTC)); + + /* Header format */ + HAL_MAC_TX_DESC_SET_HEADER_FORMAT(prTxDesc, + HEADER_FORMAT_NON_802_11); + + /* Long Format */ + HAL_MAC_TX_DESC_SET_LONG_FORMAT(prTxDesc); + + /* Update Packet option */ + nicTxFillDescByPktOption(prAdapter, prMsduInfo, prTxDesc); + + if (!GLUE_TEST_PKT_FLAG(prNativePacket, ENUM_PKT_802_3)) { + /* Set EthernetII */ + HAL_MAC_TX_DESC_SET_ETHERNET_II(prTxDesc); + } + /* Header Padding */ + HAL_MAC_TX_DESC_SET_HEADER_PADDING(prTxDesc, + NIC_TX_DESC_HEADER_PADDING_LENGTH); + + /* TID */ + HAL_MAC_TX_DESC_SET_TID(prTxDesc, ucTid); + + /* Remaining TX time */ + HAL_MAC_TX_DESC_SET_REMAINING_LIFE_TIME_IN_MS(prTxDesc, + nicTxGetRemainingTxTimeByTc(ucTempTC)); + + /* Tx count limit */ + HAL_MAC_TX_DESC_SET_REMAINING_TX_COUNT(prTxDesc, + nicTxGetTxCountLimitByTc(ucTempTC)); + + /* Set lowest BSS basic rate */ + HAL_MAC_TX_DESC_SET_FR_RATE(prTxDesc, + prBssInfo->u2HwDefaultFixedRateCode); + HAL_MAC_TX_DESC_SET_FIXED_RATE_MODE_TO_DESC(prTxDesc); + HAL_MAC_TX_DESC_SET_FIXED_RATE_ENABLE(prTxDesc); + + /* Packet Format */ + HAL_MAC_TX_DESC_SET_PKT_FORMAT(prTxDesc, + TXD_PKT_FORMAT_COMMAND); + + /* Own MAC */ + HAL_MAC_TX_DESC_SET_OWN_MAC_INDEX(prTxDesc, + prBssInfo->ucOwnMacIndex); + + /* PID */ + if (prMsduInfo->pfTxDoneHandler) { + prMsduInfo->ucPID = nicTxAssignPID(prAdapter, + prMsduInfo->ucWlanIndex); + HAL_MAC_TX_DESC_SET_PID(prTxDesc, prMsduInfo->ucPID); + HAL_MAC_TX_DESC_SET_TXS_TO_MCU(prTxDesc); + } + + if (pucTxDescLength) + *pucTxDescLength = ucTxDescAndPaddingLength; +} + +void nic_txd_v1_set_pkt_fixed_rate_option_full( + struct MSDU_INFO *prMsduInfo, + uint16_t u2RateCode, + uint8_t ucBandwidth, + u_int8_t fgShortGI, + u_int8_t fgLDPC, + u_int8_t fgDynamicBwRts, + u_int8_t fgBeamforming, + uint8_t ucAntennaIndex) +{ + struct HW_MAC_TX_DESC rTxDesc; + struct HW_MAC_TX_DESC *prTxDesc = &rTxDesc; + + kalMemZero(prTxDesc, NIC_TX_DESC_LONG_FORMAT_LENGTH); + + /* Follow the format of Tx descriptor DW 6 */ + HAL_MAC_TX_DESC_SET_FR_RATE(prTxDesc, u2RateCode); + + if (ucBandwidth) + HAL_MAC_TX_DESC_SET_FR_BW(prTxDesc, ucBandwidth); + + if (fgBeamforming) + HAL_MAC_TX_DESC_SET_FR_BF(prTxDesc); + + if (fgShortGI) + HAL_MAC_TX_DESC_SET_FR_SHORT_GI(prTxDesc); + + if (fgLDPC) + HAL_MAC_TX_DESC_SET_FR_LDPC(prTxDesc); + + if (fgDynamicBwRts) + HAL_MAC_TX_DESC_SET_FR_DYNAMIC_BW_RTS(prTxDesc); + + HAL_MAC_TX_DESC_SET_FR_ANTENNA_ID(prTxDesc, ucAntennaIndex); + + /* Write back to RateOption of MSDU_INFO */ + HAL_MAC_TX_DESC_GET_DW(prTxDesc, 6, 1, + &prMsduInfo->u4FixedRateOption); + + prMsduInfo->ucRateMode = MSDU_RATE_MODE_MANUAL_DESC; + +} + +void nic_txd_v1_set_pkt_fixed_rate_option( + struct MSDU_INFO *prMsduInfo, + uint16_t u2RateCode, + uint8_t ucBandwidth, + u_int8_t fgShortGI, + u_int8_t fgDynamicBwRts) +{ + struct HW_MAC_TX_DESC rTxDesc; + struct HW_MAC_TX_DESC *prTxDesc = &rTxDesc; + + kalMemZero(prTxDesc, NIC_TX_DESC_LONG_FORMAT_LENGTH); + + /* Follow the format of Tx descriptor DW 6 */ + HAL_MAC_TX_DESC_SET_FR_RATE(prTxDesc, u2RateCode); + + if (ucBandwidth) + HAL_MAC_TX_DESC_SET_FR_BW(prTxDesc, ucBandwidth); + + if (fgShortGI) + HAL_MAC_TX_DESC_SET_FR_SHORT_GI(prTxDesc); + + if (fgDynamicBwRts) + HAL_MAC_TX_DESC_SET_FR_DYNAMIC_BW_RTS(prTxDesc); + + /* Write back to RateOption of MSDU_INFO */ + HAL_MAC_TX_DESC_GET_DW(prTxDesc, 6, 1, + &prMsduInfo->u4FixedRateOption); + + prMsduInfo->ucRateMode = MSDU_RATE_MODE_MANUAL_DESC; + +} + +void nic_txd_v1_set_hw_amsdu_template( + struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t ucTid, + u_int8_t fgSet) +{ + struct HW_MAC_TX_DESC *prTxDesc; + + DBGLOG(QM, INFO, + "Update HW Amsdu field of TXD template for STA[%u] Tid[%u]\n", + prStaRec->ucIndex, ucTid); + + if (prStaRec->aprTxDescTemplate[ucTid]) { + prTxDesc = (struct HW_MAC_TX_DESC *) + prStaRec->aprTxDescTemplate[ucTid]; + if (fgSet) + HAL_MAC_TX_DESC_SET_HW_AMSDU(prTxDesc); + else + HAL_MAC_TX_DESC_UNSET_HW_AMSDU(prTxDesc); + } +} + +void nic_txd_v1_change_data_port_by_ac( + struct STA_RECORD *prStaRec, + uint8_t ucAci, + u_int8_t fgToMcu) +{ + uint8_t ucTid; + void **pprTxDTemplate = NULL; + + if (!prStaRec) + return; + DBGLOG(TX, INFO, "Data Packets in Aci %d will route to %s\n", ucAci, + fgToMcu ? "MCU" : "LMAC"); + pprTxDTemplate = &prStaRec->aprTxDescTemplate[0]; + for (ucTid = 0; ucTid < TX_DESC_TID_NUM; ucTid++) { + if (aucTid2ACI[ucTid] != ucAci) + continue; + HAL_MAC_TX_DESC_SET_PORT_INDEX( + (struct HW_MAC_TX_DESC *)pprTxDTemplate[ucTid], + fgToMcu ? PORT_INDEX_MCU:PORT_INDEX_LMAC); + } +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_txd_v2.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_txd_v2.c new file mode 100644 index 0000000000000..58e81c60ce5a7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_txd_v2.c @@ -0,0 +1,818 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_tx.c#2 + */ + +/*! \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. + */ + + +#if (CFG_SUPPORT_CONNAC2X == 1) +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#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 + ******************************************************************************* + */ + +uint8_t nic_txd_v2_long_format_op( + void *prTxDesc, + uint8_t fgSet) +{ + if (fgSet) + HAL_MAC_CONNAC2X_TXD_SET_LONG_FORMAT( + (struct HW_MAC_CONNAC2X_TX_DESC *)prTxDesc); + return HAL_MAC_CONNAC2X_TXD_IS_LONG_FORMAT( + (struct HW_MAC_CONNAC2X_TX_DESC *)prTxDesc); +} + +uint8_t nic_txd_v2_tid_op( + void *prTxDesc, + uint8_t ucTid, + uint8_t fgSet) +{ + if (fgSet) + HAL_MAC_CONNAC2X_TXD_SET_TID( + (struct HW_MAC_CONNAC2X_TX_DESC *)prTxDesc, ucTid); + return HAL_MAC_CONNAC2X_TXD_GET_TID( + (struct HW_MAC_CONNAC2X_TX_DESC *)prTxDesc); +} + +uint8_t nic_txd_v2_queue_idx_op( + void *prTxDesc, + uint8_t ucQueIdx, + uint8_t fgSet) +{ + if (fgSet) + HAL_MAC_CONNAC2X_TXD_SET_QUEUE_INDEX( + (struct HW_MAC_CONNAC2X_TX_DESC *)prTxDesc, ucQueIdx); + return HAL_MAC_CONNAC2X_TXD_GET_QUEUE_INDEX( + (struct HW_MAC_CONNAC2X_TX_DESC *)prTxDesc); +} + +#if (CFG_TCP_IP_CHKSUM_OFFLOAD == 1) +void nic_txd_v2_chksum_op( + void *prTxDesc, + uint8_t ucChksumFlag) +{ + if ((ucChksumFlag & TX_CS_IP_GEN)) + HAL_MAC_CONNAC2X_TXD_SET_IP_CHKSUM( + (struct HW_MAC_CONNAC2X_TX_DESC *)prTxDesc); + if ((ucChksumFlag & TX_CS_TCP_UDP_GEN)) + HAL_MAC_CONNAC2X_TXD_SET_TCP_UDP_CHKSUM( + (struct HW_MAC_CONNAC2X_TX_DESC *)prTxDesc); +} +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD == 1 */ + +void nic_txd_v2_header_format_op( + void *prTxDesc, + struct MSDU_INFO *prMsduInfo) +{ + if (!prMsduInfo->fgIs802_11) { + if (prMsduInfo->fgIs802_3) + HAL_MAC_CONNAC2X_TXD_UNSET_ETHERNET_II( + (struct HW_MAC_CONNAC2X_TX_DESC *)prTxDesc); + if (prMsduInfo->fgIsVlanExists) + HAL_MAC_CONNAC2X_TXD_SET_VLAN( + (struct HW_MAC_CONNAC2X_TX_DESC *)prTxDesc); + } +} + +void nic_txd_v2_fill_by_pkt_option( + struct MSDU_INFO *prMsduInfo, + void *prTxD) +{ + struct HW_MAC_CONNAC2X_TX_DESC *prTxDesc = + (struct HW_MAC_CONNAC2X_TX_DESC *)prTxD; + uint32_t u4PktOption = prMsduInfo->u4Option; + u_int8_t fgIsLongFormat; + u_int8_t fgProtected = FALSE; + + /* Skip this function if no options is set */ + if (!u4PktOption) + return; + + fgIsLongFormat = HAL_MAC_CONNAC2X_TXD_IS_LONG_FORMAT(prTxDesc); + + /* Fields in DW0 and DW1 (Short Format) */ + if (u4PktOption & MSDU_OPT_NO_ACK) + HAL_MAC_CONNAC2X_TXD_SET_NO_ACK(prTxDesc); + + if (u4PktOption & MSDU_OPT_PROTECTED_FRAME) { + /* DBGLOG(RSN, INFO, "MSDU_OPT_PROTECTED_FRAME\n"); */ + HAL_MAC_CONNAC2X_TXD_SET_PROTECTION(prTxDesc); + fgProtected = TRUE; + } + + switch (HAL_MAC_CONNAC2X_TXD_GET_HEADER_FORMAT(prTxDesc)) { + case HEADER_FORMAT_802_11_ENHANCE_MODE: + if (u4PktOption & MSDU_OPT_EOSP) + HAL_MAC_CONNAC2X_TXD_SET_EOSP(prTxDesc); + + if (u4PktOption & MSDU_OPT_AMSDU) + HAL_MAC_CONNAC2X_TXD_SET_AMSDU(prTxDesc); + break; + + case HEADER_FORMAT_NON_802_11: + if (u4PktOption & MSDU_OPT_EOSP) + HAL_MAC_CONNAC2X_TXD_SET_EOSP(prTxDesc); + + if (u4PktOption & MSDU_OPT_MORE_DATA) + HAL_MAC_CONNAC2X_TXD_SET_MORE_DATA(prTxDesc); + + if (u4PktOption & MSDU_OPT_REMOVE_VLAN) + HAL_MAC_CONNAC2X_TXD_SET_REMOVE_VLAN(prTxDesc); + break; + + case HEADER_FORMAT_802_11_NORMAL_MODE: + if (fgProtected && prMsduInfo->prPacket) { + struct WLAN_MAC_HEADER *prWlanHeader = + (struct WLAN_MAC_HEADER *) + ((unsigned long) (prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + + prWlanHeader->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + } + break; + + default: + break; + } + + if (!fgIsLongFormat) + return; + + /* Fields in DW2~6 (Long Format) */ + if (u4PktOption & MSDU_OPT_NO_AGGREGATE) + HAL_MAC_CONNAC2X_TXD_SET_BA_DISABLE(prTxDesc); + + if (u4PktOption & MSDU_OPT_TIMING_MEASURE) + HAL_MAC_CONNAC2X_TXD_SET_TIMING_MEASUREMENT(prTxDesc); + + if (u4PktOption & MSDU_OPT_NDP) + HAL_MAC_CONNAC2X_TXD_SET_NDP(prTxDesc); + + if (u4PktOption & MSDU_OPT_NDPA) + HAL_MAC_CONNAC2X_TXD_SET_NDPA(prTxDesc); + + if (u4PktOption & MSDU_OPT_SOUNDING) + HAL_MAC_CONNAC2X_TXD_SET_SOUNDING_FRAME(prTxDesc); + + if (u4PktOption & MSDU_OPT_FORCE_RTS) + HAL_MAC_CONNAC2X_TXD_SET_FORCE_RTS_CTS(prTxDesc); + + if (u4PktOption & MSDU_OPT_BIP) + HAL_MAC_CONNAC2X_TXD_SET_BIP(prTxDesc); + + /* SW field */ + if (u4PktOption & MSDU_OPT_SW_DURATION) + HAL_MAC_CONNAC2X_TXD_SET_DURATION_CONTROL_BY_SW(prTxDesc); + + if (u4PktOption & MSDU_OPT_SW_PS_BIT) + HAL_MAC_CONNAC2X_TXD_SET_SW_PM_CONTROL(prTxDesc); + + if (u4PktOption & MSDU_OPT_SW_HTC) + HAL_MAC_CONNAC2X_TXD_SET_HTC_EXIST(prTxDesc); +#if 0 + if (u4PktOption & MSDU_OPT_SW_BAR_SN) + HAL_MAC_TX_DESC_SET_SW_BAR_SSN(prTxDesc); +#endif + if (u4PktOption & MSDU_OPT_MANUAL_SN) { + HAL_MAC_CONNAC2X_TXD_SET_TXD_SN_VALID(prTxDesc); + HAL_MAC_CONNAC2X_TXD_SET_SEQUENCE_NUMBER + (prTxDesc, prMsduInfo->u2SwSN); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief In this function, we'll compose the Tx descriptor of the MSDU. +* +* @param prAdapter Pointer to the Adapter structure. +* @param prMsduInfo Pointer to the Msdu info +* @param prTxDesc Pointer to the Tx descriptor buffer +* +* @retval VOID +*/ +/*----------------------------------------------------------------------------*/ +void nic_txd_v2_compose( + struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + u_int32_t u4TxDescLength, + u_int8_t fgIsTemplate, + u_int8_t *prTxDescBuffer) +{ + struct HW_MAC_CONNAC2X_TX_DESC *prTxDesc; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + u_int8_t ucEtherTypeOffsetInWord; + u_int32_t u4TxDescAndPaddingLength; + u_int8_t ucTarQueue, ucTarPort; +#if ((CFG_SISO_SW_DEVELOP == 1) || (CFG_SUPPORT_SPE_IDX_CONTROL == 1)) + enum ENUM_WF_PATH_FAVOR_T eWfPathFavor; +#endif + + prTxDesc = (struct HW_MAC_CONNAC2X_TX_DESC *) prTxDescBuffer; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + u4TxDescAndPaddingLength = u4TxDescLength + NIC_TX_DESC_PADDING_LENGTH; + + kalMemZero(prTxDesc, u4TxDescAndPaddingLength); + + /* Ether-type offset */ + if (prMsduInfo->fgIs802_11) { + ucEtherTypeOffsetInWord = + (prAdapter->chip_info->pse_header_length + + prMsduInfo->ucMacHeaderLength + + prMsduInfo->ucLlcLength) >> 1; + } else { + ucEtherTypeOffsetInWord = + ((ETHER_HEADER_LEN - ETHER_TYPE_LEN) + + prAdapter->chip_info->pse_header_length) >> 1; + } + HAL_MAC_CONNAC2X_TXD_SET_ETHER_TYPE_OFFSET( + prTxDesc, + ucEtherTypeOffsetInWord); + + ucTarPort = nicTxGetTxDestPortIdxByTc(prMsduInfo->ucTC); + if (ucTarPort == PORT_INDEX_MCU && + prMsduInfo->ucControlFlag & MSDU_CONTROL_FLAG_FORCE_TX) { + /* To MCU packet with always tx flag */ + ucTarQueue = MAC_TXQ_ALTX_0_INDEX; + } else { + ucTarQueue = nicTxGetTxDestQIdxByTc(prMsduInfo->ucTC); + ucTarQueue += (prBssInfo->ucWmmQueSet * WMM_AC_INDEX_NUM); + } + +#if (CFG_SUPPORT_DMASHDL_SYSDVT) + if (prMsduInfo->ucPktType == ENUM_PKT_ICMP) { + /* send packets to specific mapping queue for DMASHDL DVT */ + if (DMASHDL_DVT_QUEUE_MAPPING_TYPE1(prAdapter)) { + ucTarQueue = DMASHDL_DVT_GET_MAPPING_QID(prAdapter); + prMsduInfo->ucTarQueue = ucTarQueue; + DMASHDL_DVT_SET_MAPPING_QID(prAdapter, + (ucTarQueue + 1) % MAC_TXQ_AC33_INDEX); + } else if (DMASHDL_DVT_QUEUE_MAPPING_TYPE2(prAdapter)) { + ucTarQueue = DMASHDL_DVT_GET_MAPPING_QID(prAdapter); + prMsduInfo->ucTarQueue = ucTarQueue; + DMASHDL_DVT_SET_MAPPING_QID(prAdapter, + (ucTarQueue + 1) % MAC_TXQ_AC2_INDEX); + } + } +#endif + + HAL_MAC_CONNAC2X_TXD_SET_QUEUE_INDEX(prTxDesc, ucTarQueue); + + /* BMC packet */ + if (prMsduInfo->ucStaRecIndex == STA_REC_INDEX_BMCAST) { + HAL_MAC_CONNAC2X_TXD_SET_BMC(prTxDesc); + + /* Must set No ACK to mask retry bit in FC */ + HAL_MAC_CONNAC2X_TXD_SET_NO_ACK(prTxDesc); + } + /* WLAN index */ + prMsduInfo->ucWlanIndex = nicTxGetWlanIdx(prAdapter, + prMsduInfo->ucBssIndex, prMsduInfo->ucStaRecIndex); + +#if 0 /* DBG */ + DBGLOG(RSN, INFO, + "Tx WlanIndex = %d eAuthMode = %d\n", prMsduInfo->ucWlanIndex, + prAdapter->rWifiVar.rConnSettings.eAuthMode); +#endif + HAL_MAC_CONNAC2X_TXD_SET_WLAN_INDEX( + prTxDesc, prMsduInfo->ucWlanIndex); + + /* Header format */ + if (prMsduInfo->fgIs802_11) { + HAL_MAC_CONNAC2X_TXD_SET_HEADER_FORMAT( + prTxDesc, HEADER_FORMAT_802_11_NORMAL_MODE); + HAL_MAC_CONNAC2X_TXD_SET_802_11_HEADER_LENGTH( + prTxDesc, (prMsduInfo->ucMacHeaderLength >> 1)); + } else { + HAL_MAC_CONNAC2X_TXD_SET_HEADER_FORMAT( + prTxDesc, HEADER_FORMAT_NON_802_11); + HAL_MAC_CONNAC2X_TXD_SET_ETHERNET_II(prTxDesc); + } + + /* Header Padding */ + HAL_MAC_CONNAC2X_TXD_SET_HEADER_PADDING( + prTxDesc, NIC_TX_DESC_HEADER_PADDING_LENGTH); + + /* TID */ + HAL_MAC_CONNAC2X_TXD_SET_TID(prTxDesc, prMsduInfo->ucUserPriority); + + /* Protection */ + if (secIsProtectedFrame(prAdapter, prMsduInfo, prStaRec)) { + /* Update Packet option, */ + /* PF bit will be set in nicTxFillDescByPktOption() */ + if ((prStaRec + && prStaRec->fgTransmitKeyExist) || fgIsTemplate) { + DBGLOG_LIMITED(RSN, TRACE, + "Set MSDU_OPT_PROTECTED_FRAME\n"); + nicTxConfigPktOption( + prMsduInfo, MSDU_OPT_PROTECTED_FRAME, TRUE); + + if (prMsduInfo->fgIs802_1x && + prMsduInfo->fgIs802_1x_NonProtected) { + nicTxConfigPktOption( + prMsduInfo, + MSDU_OPT_PROTECTED_FRAME, FALSE); + DBGLOG(RSN, LOUD, + "Pairwise EAPoL not protect!\n"); + } + } else if (prMsduInfo->ucStaRecIndex + == STA_REC_INDEX_BMCAST) {/* BMC packet */ + nicTxConfigPktOption( + prMsduInfo, MSDU_OPT_PROTECTED_FRAME, TRUE); + DBGLOG(RSN, LOUD, "Protect BMC frame!\n"); + } + } +#if (UNIFIED_MAC_TX_FORMAT == 1) + /* Packet Format */ + HAL_MAC_CONNAC2X_TXD_SET_PKT_FORMAT( + prTxDesc, prMsduInfo->ucPacketFormat); +#endif + + /* Own MAC */ + HAL_MAC_CONNAC2X_TXD_SET_OWN_MAC_INDEX( + prTxDesc, prBssInfo->ucOwnMacIndex); + + if (u4TxDescLength == NIC_TX_DESC_SHORT_FORMAT_LENGTH) { + HAL_MAC_CONNAC2X_TXD_SET_SHORT_FORMAT(prTxDesc); + + /* Update Packet option */ + nic_txd_v2_fill_by_pkt_option(prMsduInfo, prTxDesc); + + /* Short format, Skip DW 2~6 */ + return; + } + HAL_MAC_CONNAC2X_TXD_SET_LONG_FORMAT(prTxDesc); + + /* Update Packet option */ + nic_txd_v2_fill_by_pkt_option(prMsduInfo, prTxDesc); + + /* Type */ + if (prMsduInfo->fgIs802_11) { + struct WLAN_MAC_HEADER *prWlanHeader = + (struct WLAN_MAC_HEADER *) + ((unsigned long) + (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + HAL_MAC_CONNAC2X_TXD_SET_TYPE( + prTxDesc, + (prWlanHeader->u2FrameCtrl & MASK_FC_TYPE) >> 2); + HAL_MAC_CONNAC2X_TXD_SET_SUB_TYPE( + prTxDesc, + (prWlanHeader->u2FrameCtrl & MASK_FC_SUBTYPE) + >> OFFSET_OF_FC_SUBTYPE); + + HAL_MAC_CONNAC2X_TXD7_SET_TYPE( + prTxDesc, + (prWlanHeader->u2FrameCtrl & MASK_FC_TYPE) >> 2); + HAL_MAC_CONNAC2X_TXD7_SET_SUB_TYPE( + prTxDesc, + (prWlanHeader->u2FrameCtrl & MASK_FC_SUBTYPE) + >> OFFSET_OF_FC_SUBTYPE); + } + /* PID */ + if (prMsduInfo->pfTxDoneHandler) { + prMsduInfo->ucPID = nicTxAssignPID( + prAdapter, prMsduInfo->ucWlanIndex); + HAL_MAC_CONNAC2X_TXD_SET_PID(prTxDesc, prMsduInfo->ucPID); + HAL_MAC_CONNAC2X_TXD_SET_TXS_TO_MCU(prTxDesc); + } else if (prAdapter->rWifiVar.ucDataTxDone == 2) { + /* Log mode: only TxS to FW, no event to driver */ + HAL_MAC_CONNAC2X_TXD_SET_PID( + prTxDesc, NIC_TX_DESC_PID_RESERVED); + HAL_MAC_CONNAC2X_TXD_SET_TXS_TO_MCU(prTxDesc); + } + +#if CFG_SUPPORT_WIFI_SYSDVT + if (prMsduInfo->pfTxDoneHandler) { + DBGLOG(REQ, LOUD, "PacketType=%d\n", + prMsduInfo->ucPacketType); + if (is_frame_test(prAdapter, 0) == 1 && + prMsduInfo->ucPacketType == 0) { /* Data */ + prMsduInfo->ucPID = prAdapter->auto_dvt->txs.pid; + HAL_MAC_CONNAC2X_TXD_SET_PID(prTxDesc, + prAdapter->auto_dvt->txs.pid); + HAL_MAC_CONNAC2X_TXD_SET_TXS_FORMAT(prTxDesc, + prAdapter->auto_dvt->txs.format); + send_add_txs_queue(prAdapter->auto_dvt->txs.pid, + prMsduInfo->ucWlanIndex); + DBGLOG(REQ, LOUD, + "Send_add_txs_queue pid=%d auto_txs_format=%d\n", + prMsduInfo->ucPID, + prAdapter->auto_dvt->txs.format); + } else if (is_frame_test(prAdapter, 0) == 2 && + prMsduInfo->ucPacketType == 1) { /* Mgmt */ + struct WLAN_MAC_HEADER *prWlanHeader = + (struct WLAN_MAC_HEADER *) + ((unsigned long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + + if (((prWlanHeader->u2FrameCtrl & + MASK_FC_TYPE) >> 2) == 0 && + ((prWlanHeader->u2FrameCtrl & MASK_FC_SUBTYPE) + >> OFFSET_OF_FC_SUBTYPE) == 8) + ;/* FC_TYPE_MGMT=0, SUBTYPE_BEACON=8 */ + else if (((prWlanHeader->u2FrameCtrl & + MASK_FC_TYPE) >> 2) == 0) { + prMsduInfo->ucPID = + prAdapter->auto_dvt->txs.pid; + HAL_MAC_CONNAC2X_TXD_SET_PID(prTxDesc, + prAdapter->auto_dvt->txs.pid); + HAL_MAC_CONNAC2X_TXD_SET_TXS_FORMAT(prTxDesc, + prAdapter->auto_dvt->txs.format); + send_add_txs_queue(prAdapter->auto_dvt->txs.pid, + prMsduInfo->ucWlanIndex); + DBGLOG(REQ, LOUD, + "Send_add_txs_queue pid=%d auto_txs_format=%d\n", + prMsduInfo->ucPID, + prAdapter->auto_dvt->txs.format); + } else { + prMsduInfo->ucPID = + prAdapter->auto_dvt->txs.pid; + HAL_MAC_CONNAC2X_TXD_SET_PID(prTxDesc, + prAdapter->auto_dvt->txs.pid); + HAL_MAC_CONNAC2X_TXD_SET_TXS_FORMAT(prTxDesc, + prAdapter->auto_dvt->txs.format); + HAL_MAC_CONNAC2X_TXD_SET_NO_ACK(prTxDesc); + send_add_txs_queue( + prAdapter->auto_dvt->txs.pid, + prMsduInfo->ucWlanIndex); + DBGLOG(REQ, LOUD, + "Send_add_txs_queue pid=%d auto_txs_format=%d\n", + prMsduInfo->ucPID, + prAdapter->auto_dvt->txs.format); + } + } + } +#endif /* AUTOMATION */ + + /* Remaining TX time */ + if (!(prMsduInfo->u4Option & MSDU_OPT_MANUAL_LIFE_TIME)) + prMsduInfo->u4RemainingLifetime = + nicTxGetRemainingTxTimeByTc(prMsduInfo->ucTC); + HAL_MAC_CONNAC2X_TXD_SET_REMAINING_LIFE_TIME_IN_MS( + prTxDesc, prMsduInfo->u4RemainingLifetime); + + /* Tx count limit */ + if (!(prMsduInfo->u4Option & MSDU_OPT_MANUAL_RETRY_LIMIT)) { + /* Note: BMC packet retry limit is set to unlimited */ + prMsduInfo->ucRetryLimit = + nicTxGetTxCountLimitByTc(prMsduInfo->ucTC); + } + HAL_MAC_CONNAC2X_TXD_SET_REMAINING_TX_COUNT( + prTxDesc, prMsduInfo->ucRetryLimit); + + /* Power Offset */ + HAL_MAC_CONNAC2X_TXD_SET_POWER_OFFSET( + prTxDesc, prMsduInfo->cPowerOffset); + + /* Fix rate */ + switch (prMsduInfo->ucRateMode) { + case MSDU_RATE_MODE_MANUAL_DESC: + HAL_MAC_TX_DESC_SET_DW( + prTxDesc, 6, 1, &prMsduInfo->u4FixedRateOption); +#if (CFG_SISO_SW_DEVELOP == 1 || CFG_SUPPORT_SPE_IDX_CONTROL == 1) + /* Update spatial extension index setting */ + eWfPathFavor = wlanGetAntPathType(prAdapter, ENUM_WF_NON_FAVOR); + HAL_MAC_CONNAC2X_TXD_SET_SPE_IDX( + prTxDesc, + wlanGetSpeIdx(prAdapter, prBssInfo->ucBssIndex, + eWfPathFavor)); +#endif + HAL_MAC_CONNAC2X_TXD_SET_SPE_IDX_SEL(prTxDesc, + ENUM_SPE_SEL_BY_TXD); + HAL_MAC_CONNAC2X_TXD_SET_FIXED_RATE_MODE_TO_DESC(prTxDesc); + HAL_MAC_CONNAC2X_TXD_SET_FIXED_RATE_ENABLE(prTxDesc); + +#if (CFG_SUPPORT_HE_ER == 1) + if (prBssInfo->ucErMode == RA_DCM || + prBssInfo->ucErMode == RA_ER_106) { + /* 2 HE LTF */ + HAL_MAC_CONNAC2X_TXD_SET_HE_LTF(prTxDesc, 1); + /* 1.6us GI */ + HAL_MAC_CONNAC2X_TXD_SET_GI_TYPE(prTxDesc, 1); + /* DBGLOG(TX, WARN, "nic_txd:LTF:2(%x,GI:1.6(%x", */ + /* HAL_MAC_CONNAC2X_TXD_GET_HE_LTF(prTxDesc), */ + /* HAL_MAC_CONNAC2X_TXD_GET_GI_TYPE(prTxDesc)); */ + } +#endif + break; + + case MSDU_RATE_MODE_MANUAL_CR: + HAL_MAC_CONNAC2X_TXD_SET_FIXED_RATE_MODE_TO_CR(prTxDesc); + HAL_MAC_CONNAC2X_TXD_SET_FIXED_RATE_ENABLE(prTxDesc); + break; + + case MSDU_RATE_MODE_AUTO: + default: + break; + } +} + +void nic_txd_v2_compose_security_frame( + struct ADAPTER *prAdapter, + struct CMD_INFO *prCmdInfo, + uint8_t *prTxDescBuffer, + uint8_t *pucTxDescLength) +{ + struct HW_MAC_CONNAC2X_TX_DESC *prTxDesc + = (struct HW_MAC_CONNAC2X_TX_DESC *) prTxDescBuffer; + uint8_t ucTxDescAndPaddingLength + = NIC_TX_DESC_LONG_FORMAT_LENGTH + NIC_TX_DESC_PADDING_LENGTH; + struct BSS_INFO *prBssInfo; + uint8_t ucTid = 0; + uint8_t ucTempTC = TC4_INDEX; + void *prNativePacket; + uint8_t ucEtherTypeOffsetInWord; + struct MSDU_INFO *prMsduInfo; + + prMsduInfo = prCmdInfo->prMsduInfo; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + prNativePacket = prMsduInfo->prPacket; + + ASSERT(prNativePacket); + + kalMemZero(prTxDesc, ucTxDescAndPaddingLength); + + /* WLAN index */ + prMsduInfo->ucWlanIndex = + nicTxGetWlanIdx(prAdapter, + prMsduInfo->ucBssIndex, prMsduInfo->ucStaRecIndex); + + /* UC to a connected peer */ + HAL_MAC_CONNAC2X_TXD_SET_WLAN_INDEX(prTxDesc, + prMsduInfo->ucWlanIndex); + + /* Tx byte count */ + HAL_MAC_CONNAC2X_TXD_SET_TX_BYTE_COUNT(prTxDesc, + ucTxDescAndPaddingLength + prCmdInfo->u2InfoBufLen); + + /* Ether-type offset */ + ucEtherTypeOffsetInWord = + ((ETHER_HEADER_LEN - ETHER_TYPE_LEN) + + prAdapter->chip_info->pse_header_length) + >> 1; + + HAL_MAC_CONNAC2X_TXD_SET_ETHER_TYPE_OFFSET(prTxDesc, + ucEtherTypeOffsetInWord); + + /* queue index */ + HAL_MAC_CONNAC2X_TXD_SET_QUEUE_INDEX(prTxDesc, + nicTxGetTxDestQIdxByTc(ucTempTC)); + + /* Header format */ + HAL_MAC_CONNAC2X_TXD_SET_HEADER_FORMAT(prTxDesc, + HEADER_FORMAT_NON_802_11); + + /* Long Format */ + HAL_MAC_CONNAC2X_TXD_SET_LONG_FORMAT(prTxDesc); + + /* Update Packet option */ + nic_txd_v2_fill_by_pkt_option(prMsduInfo, prTxDesc); + + if (!GLUE_TEST_PKT_FLAG(prNativePacket, ENUM_PKT_802_3)) { + /* Set EthernetII */ + HAL_MAC_CONNAC2X_TXD_SET_ETHERNET_II(prTxDesc); + } + /* Header Padding */ + HAL_MAC_CONNAC2X_TXD_SET_HEADER_PADDING(prTxDesc, + NIC_TX_DESC_HEADER_PADDING_LENGTH); + + /* TID */ + HAL_MAC_CONNAC2X_TXD_SET_TID(prTxDesc, ucTid); + + /* Remaining TX time */ + HAL_MAC_CONNAC2X_TXD_SET_REMAINING_LIFE_TIME_IN_MS(prTxDesc, + nicTxGetRemainingTxTimeByTc(ucTempTC)); + + /* Tx count limit */ + HAL_MAC_CONNAC2X_TXD_SET_REMAINING_TX_COUNT(prTxDesc, + nicTxGetTxCountLimitByTc(ucTempTC)); + + /* Set lowest BSS basic rate */ + HAL_MAC_CONNAC2X_TXD_SET_FR_RATE(prTxDesc, + prBssInfo->u2HwDefaultFixedRateCode); +#if 0 /* FALCON_TODO */ + HAL_MAC_FALCON_TX_DESC_SET_FIXED_RATE_MODE_TO_DESC(prTxDesc); +#endif + HAL_MAC_CONNAC2X_TXD_SET_FIXED_RATE_ENABLE(prTxDesc); + + /* Packet Format */ + HAL_MAC_CONNAC2X_TXD_SET_PKT_FORMAT(prTxDesc, TXD_PKT_FORMAT_COMMAND); + + /* Own MAC */ + HAL_MAC_CONNAC2X_TXD_SET_OWN_MAC_INDEX(prTxDesc, + prBssInfo->ucOwnMacIndex); + + /* PID */ + if (prMsduInfo->pfTxDoneHandler) { + prMsduInfo->ucPID = + nicTxAssignPID(prAdapter, prMsduInfo->ucWlanIndex); + HAL_MAC_CONNAC2X_TXD_SET_PID(prTxDesc, prMsduInfo->ucPID); + HAL_MAC_CONNAC2X_TXD_SET_TXS_TO_MCU(prTxDesc); + } + + if (pucTxDescLength) + *pucTxDescLength = ucTxDescAndPaddingLength; +} + +void nic_txd_v2_set_pkt_fixed_rate_option_full(struct MSDU_INFO + *prMsduInfo, + uint16_t u2RateCode, + uint8_t ucBandwidth, + u_int8_t fgShortGI, + u_int8_t fgLDPC, + u_int8_t fgDynamicBwRts, u_int8_t fgBeamforming, + uint8_t ucAntennaIndex) +{ + struct HW_MAC_CONNAC2X_TX_DESC rTxDesc; + struct HW_MAC_CONNAC2X_TX_DESC *prTxDesc = &rTxDesc; + + kalMemZero(prTxDesc, NIC_TX_DESC_LONG_FORMAT_LENGTH); + + /* Follow the format of Tx descriptor DW 6 */ + HAL_MAC_CONNAC2X_TXD_SET_FR_RATE(prTxDesc, u2RateCode); + + if (ucBandwidth) + HAL_MAC_CONNAC2X_TXD_SET_FR_BW(prTxDesc, ucBandwidth); +#if 0 + if (fgBeamforming) + HAL_MAC_CONNAC2X_TXD_SET_FR_BF(prTxDesc); +#else + DBGLOG(TX, ERROR, "%s:: Need BF owner to check this setting!\n", + __func__); +#endif + if (fgShortGI) + HAL_MAC_CONNAC2X_TXD_SET_GI_TYPE(prTxDesc, SHORT_GI); + + if (fgLDPC) + HAL_MAC_CONNAC2X_TXD_SET_LDPC(prTxDesc); + + if (fgDynamicBwRts) + HAL_MAC_CONNAC2X_TXD_SET_FR_DYNAMIC_BW_RTS(prTxDesc); + + HAL_MAC_CONNAC2X_TXD_SET_FR_ANTENNA_ID(prTxDesc, ucAntennaIndex); + + /* Write back to RateOption of MSDU_INFO */ + HAL_MAC_TX_DESC_GET_DW(prTxDesc, 6, 1, + &prMsduInfo->u4FixedRateOption); + + prMsduInfo->ucRateMode = MSDU_RATE_MODE_MANUAL_DESC; + +} + +void nic_txd_v2_set_pkt_fixed_rate_option( + struct MSDU_INFO *prMsduInfo, + uint16_t u2RateCode, + uint8_t ucBandwidth, + u_int8_t fgShortGI, + u_int8_t fgDynamicBwRts) +{ + struct HW_MAC_CONNAC2X_TX_DESC rTxDesc; + struct HW_MAC_CONNAC2X_TX_DESC *prTxDesc = &rTxDesc; + + kalMemZero(prTxDesc, NIC_TX_DESC_LONG_FORMAT_LENGTH); + + /* Follow the format of Tx descriptor DW 6 */ + HAL_MAC_CONNAC2X_TXD_SET_FR_RATE(prTxDesc, u2RateCode); + + if (ucBandwidth) + HAL_MAC_CONNAC2X_TXD_SET_FR_BW(prTxDesc, ucBandwidth); + + if (fgShortGI) + HAL_MAC_CONNAC2X_TXD_SET_GI_TYPE(prTxDesc, SHORT_GI); + + if (fgDynamicBwRts) + HAL_MAC_CONNAC2X_TXD_SET_FR_DYNAMIC_BW_RTS(prTxDesc); + + /* Write back to RateOption of MSDU_INFO */ + HAL_MAC_TX_DESC_GET_DW(prTxDesc, 6, 1, + &prMsduInfo->u4FixedRateOption); + + prMsduInfo->ucRateMode = MSDU_RATE_MODE_MANUAL_DESC; + +} + +void nic_txd_v2_set_hw_amsdu_template( + struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + u_int8_t ucTid, + IN u_int8_t fgSet) +{ + struct HW_MAC_CONNAC2X_TX_DESC *prTxDesc; + + DBGLOG(QM, INFO, + "Update HW Amsdu field of TXD template for STA[%u] Tid[%u]\n", + prStaRec->ucIndex, ucTid); + + if (prStaRec->aprTxDescTemplate[ucTid]) { + prTxDesc = + (struct HW_MAC_CONNAC2X_TX_DESC *) + prStaRec->aprTxDescTemplate[ucTid]; + if (fgSet) + HAL_MAC_CONNAC2X_TXD_SET_HW_AMSDU(prTxDesc); + else + HAL_MAC_CONNAC2X_TXD_UNSET_HW_AMSDU(prTxDesc); + } +} +#endif /* CFG_SUPPORT_CONNAC2X == 1 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_umac.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_umac.c new file mode 100644 index 0000000000000..85fc186ccb4c6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/nic_umac.c @@ -0,0 +1,458 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_umac.c#5 + */ + +/*! \file nic_umac.c + * \brief Functions that used for debug UMAC + * + * This file includes the functions used do umac debug + * + */ + +/******************************************************************************* + * C O M P I L E 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 "que_mgt.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + + + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +struct UMAC_PG_INFO_AND_RESERVE_CNT_CR_OFFSET_MAP { + uint8_t ucGroupID; + uint32_t u4PgReservePageCntRegOffset; + uint32_t u4PgInfoRegOffset; +}; + +struct UMAC_PG_MAX_MIN_QUOTA_SET { + uint8_t ucPageGroupID; + uint16_t u2MaxPageQuota; + uint16_t u2MinPageQuota; +}; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +const struct UMAC_PG_INFO_AND_RESERVE_CNT_CR_OFFSET_MAP + g_arPlePgInfoAndReserveCrOffsetMap[] = { + { + UMAC_PG_HIF0_GROUP_0, + UMAC_PG_HIF0_GROUP(UMAC_PLE_CFG_POOL_INDEX), + UMAC_HIF0_PG_INFO(UMAC_PLE_CFG_POOL_INDEX) + }, + { + UMAC_PG_HIF0_GROUP_0, + UMAC_PG_HIF0_GROUP(UMAC_PLE_CFG_POOL_INDEX), + UMAC_HIF0_PG_INFO(UMAC_PLE_CFG_POOL_INDEX) + }, + { + UMAC_PG_CPU_GROUP_2, + UMAC_PG_CPU_GROUP(UMAC_PLE_CFG_POOL_INDEX), + UMAC_CPU_PG_INFO(UMAC_PLE_CFG_POOL_INDEX) + }, +}; + +const struct UMAC_PG_INFO_AND_RESERVE_CNT_CR_OFFSET_MAP + g_arPsePgInfoAndReserveCrOffsetMap[] = { + { + UMAC_PG_HIF0_GROUP_0, + UMAC_PG_HIF0_GROUP(UMAC_PSE_CFG_POOL_INDEX), + UMAC_HIF0_PG_INFO(UMAC_PSE_CFG_POOL_INDEX) + }, + { + UMAC_PG_HIF1_GROUP_1, + UMAC_PG_HIF1_GROUP(UMAC_PSE_CFG_POOL_INDEX), + UMAC_HIF1_PG_INFO(UMAC_PSE_CFG_POOL_INDEX) + }, + { + UMAC_PG_CPU_GROUP_2, + UMAC_PG_CPU_GROUP(UMAC_PSE_CFG_POOL_INDEX), + UMAC_CPU_PG_INFO(UMAC_PSE_CFG_POOL_INDEX) + }, + { + UMAC_PG_LMAC0_GROUP_3, + UMAC_PG_LMAC0_GROUP(UMAC_PSE_CFG_POOL_INDEX), + UMAC_LMAC0_PG_INFO(UMAC_PSE_CFG_POOL_INDEX) + }, + { + UMAC_PG_LMAC1_GROUP_4, + UMAC_PG_LMAC1_GROUP(UMAC_PSE_CFG_POOL_INDEX), + UMAC_LMAC1_PG_INFO(UMAC_PSE_CFG_POOL_INDEX) + }, + { + UMAC_PG_LMAC2_GROUP_5, + UMAC_PG_LMAC2_GROUP(UMAC_PSE_CFG_POOL_INDEX), + UMAC_LMAC2_PG_INFO(UMAC_PSE_CFG_POOL_INDEX) + }, + { + UMAC_PG_PLE_GROUP_6, + UMAC_PG_PLE_GROUP(UMAC_PSE_CFG_POOL_INDEX), + UMAC_PLE_PG_INFO(UMAC_PSE_CFG_POOL_INDEX) + }, +}; + +/******************************************************************************* + * M A 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 halUmacWrapSourcePortSanityCheck: + * + * @param IN BOOLEAN fgPsePleFlag, + * IN UINT_8 ucPageGroupID + * @return TRUE/FALSE + */ +/*----------------------------------------------------------------------------*/ + +OUT u_int8_t halUmacWrapSourcePortSanityCheck( + IN u_int8_t fgPsePleFlag, IN uint8_t ucPageGroupID) +{ + + if (fgPsePleFlag == UMAC_PSE_CFG_POOL_INDEX) { + if (ucPageGroupID > UMAC_PG_PLE_GROUP_6) + return FALSE; + } else if (fgPsePleFlag == UMAC_PLE_CFG_POOL_INDEX) { + if ((ucPageGroupID != UMAC_PG_HIF0_GROUP_0) + && (ucPageGroupID != UMAC_PG_CPU_GROUP_2)) + return FALSE; + } else + return FALSE; + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief halUmacWrapRsvPgCnt: + * + * @param IN P_ADAPTER_T prAdapter + * IN BOOLEAN fgPsePleFlag, + * IN UINT_8 ucPageGroupID + * @return UINT_16 + */ +/*----------------------------------------------------------------------------*/ + +OUT uint16_t halUmacWrapRsvPgCnt(IN struct ADAPTER + *prAdapter, IN u_int8_t fgPsePleFlag, + IN uint8_t ucPageGroupID) +{ + uint32_t u4RegAddr = 0; + uint32_t u4Value = 0; + + if (halUmacWrapSourcePortSanityCheck(fgPsePleFlag, + ucPageGroupID) == FALSE) + return UMAC_FID_FAULT; + + if (fgPsePleFlag == UMAC_PSE_CFG_POOL_INDEX) + u4RegAddr = + g_arPsePgInfoAndReserveCrOffsetMap[ucPageGroupID]. + u4PgInfoRegOffset; + else if (fgPsePleFlag == UMAC_PLE_CFG_POOL_INDEX) + u4RegAddr = + g_arPlePgInfoAndReserveCrOffsetMap[ucPageGroupID]. + u4PgInfoRegOffset; + + HAL_MCR_RD(prAdapter, u4RegAddr, &u4Value); + + return (uint16_t) (u4Value & BITS(0, 11)); +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief halUmacWrapSrcPgCnt: + * + * @param IN P_ADAPTER_T prAdapter + * IN BOOLEAN fgPsePleFlag, + * IN UINT_8 ucPageGroupID + * @return UINT_16 + */ +/*----------------------------------------------------------------------------*/ + +OUT uint16_t halUmacWrapSrcPgCnt(IN struct ADAPTER + *prAdapter, IN u_int8_t fgPsePleFlag, + IN uint8_t ucPageGroupID) +{ + uint32_t u4RegAddr = 0; + uint32_t u4Value = 0; + + if (halUmacWrapSourcePortSanityCheck(fgPsePleFlag, + ucPageGroupID) == FALSE) + return UMAC_FID_FAULT; + + if (fgPsePleFlag == UMAC_PSE_CFG_POOL_INDEX) + u4RegAddr = + g_arPsePgInfoAndReserveCrOffsetMap[ucPageGroupID]. + u4PgInfoRegOffset; + else if (fgPsePleFlag == UMAC_PLE_CFG_POOL_INDEX) + u4RegAddr = + g_arPlePgInfoAndReserveCrOffsetMap[ucPageGroupID]. + u4PgInfoRegOffset; + + HAL_MCR_RD(prAdapter, u4RegAddr, &u4Value); + + return (uint16_t) ((u4Value & BITS(16, 27)) >> 16); +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief halUmacPbufCtrlTotalPageNum: + * + * @param IN P_ADAPTER_T prAdapter + * IN BOOLEAN fgPsePleFlag, + * @return UINT_16 + */ +/*----------------------------------------------------------------------------*/ + +OUT uint16_t halUmacPbufCtrlTotalPageNum(IN struct ADAPTER + *prAdapter, IN uint16_t fgPsePleFlag) +{ + uint32_t u4Value = 0; + + HAL_MCR_RD(prAdapter, UMAC_PBUF_CTRL(fgPsePleFlag), + &u4Value); + + return (uint16_t) (u4Value & + UMAC_PBUF_CTRL_TOTAL_PAGE_NUM_MASK); +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief halUmacWrapFrePageCnt: + * + * @param IN P_ADAPTER_T prAdapter + * IN BOOLEAN fgPsePleFlag, + * @return UINT_16 + */ +/*----------------------------------------------------------------------------*/ + +OUT uint16_t halUmacWrapFrePageCnt(IN struct ADAPTER + *prAdapter, IN u_int8_t fgPsePleFlag) +{ + uint32_t u4Value = 0; + + HAL_MCR_RD(prAdapter, UMAC_FREEPG_CNT(fgPsePleFlag), + &u4Value); + return (u4Value & UMAC_FREEPG_CNT_FREEPAGE_CNT_MASK) >> + UMAC_FREEPG_CNT_FREEPAGE_CNT_OFFSET; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief halUmacWrapFfaCnt: + * + * @param IN P_ADAPTER_T prAdapter + * IN BOOLEAN fgPsePleFlag, + * @return UINT_16 + */ +/*----------------------------------------------------------------------------*/ + +OUT uint16_t halUmacWrapFfaCnt(IN struct ADAPTER *prAdapter, + IN u_int8_t fgPsePleFlag) +{ + uint32_t u4Value = 0; + + HAL_MCR_RD(prAdapter, UMAC_FREEPG_CNT(fgPsePleFlag), + &u4Value); + return (u4Value & UMAC_FREEPG_CNT_FFA_CNT_MASK) >> + UMAC_FREEPG_CNT_FFA_CNT_OFFSET; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief halUmacInfoGetMiscStatus: + * + * @param IN P_ADAPTER_T prAdapter + * IN P_UMAC_STAT2_GET_T pUmacStat2Get, + * @return UINT_16 + */ +/*----------------------------------------------------------------------------*/ + + +OUT u_int8_t halUmacInfoGetMiscStatus(IN struct ADAPTER + *prAdapter, IN struct UMAC_STAT2_GET *pUmacStat2Get) +{ + pUmacStat2Get->u2PleRevPgHif0Group0 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PLE_CFG_POOL_INDEX, + UMAC_PG_HIF0_GROUP_0); + + pUmacStat2Get->u2PleRevPgCpuGroup2 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PLE_CFG_POOL_INDEX, + UMAC_PG_CPU_GROUP_2); + + pUmacStat2Get->u2PseRevPgHif0Group0 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_HIF0_GROUP_0); + + pUmacStat2Get->u2PseRevPgHif1Group1 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_HIF1_GROUP_1); + + pUmacStat2Get->u2PseRevPgCpuGroup2 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_CPU_GROUP_2); + + pUmacStat2Get->u2PseRevPgLmac0Group3 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_LMAC0_GROUP_3); + + pUmacStat2Get->u2PseRevPgLmac1Group4 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_LMAC1_GROUP_4); + + pUmacStat2Get->u2PseRevPgLmac2Group5 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_LMAC2_GROUP_5); + + pUmacStat2Get->u2PseRevPgPleGroup6 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_PLE_GROUP_6); + + pUmacStat2Get->u2PleSrvPgHif0Group0 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PLE_CFG_POOL_INDEX, + UMAC_PG_HIF0_GROUP_0); + + pUmacStat2Get->u2PleSrvPgCpuGroup2 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PLE_CFG_POOL_INDEX, + UMAC_PG_CPU_GROUP_2); + + pUmacStat2Get->u2PseSrvPgHif0Group0 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_HIF0_GROUP_0); + + pUmacStat2Get->u2PseSrvPgHif1Group1 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_HIF1_GROUP_1); + + pUmacStat2Get->u2PseSrvPgCpuGroup2 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_CPU_GROUP_2); + + pUmacStat2Get->u2PseSrvPgLmac0Group3 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_LMAC0_GROUP_3); + + pUmacStat2Get->u2PseSrvPgLmac1Group4 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_LMAC1_GROUP_4); + + pUmacStat2Get->u2PseSrvPgLmac2Group5 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_LMAC2_GROUP_5); + + pUmacStat2Get->u2PseSrvPgPleGroup6 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_PLE_GROUP_6); + + + pUmacStat2Get->u2PleTotalPageNum = + halUmacPbufCtrlTotalPageNum(prAdapter, + UMAC_PLE_CFG_POOL_INDEX); + + pUmacStat2Get->u2PseTotalPageNum = + halUmacPbufCtrlTotalPageNum(prAdapter, + UMAC_PSE_CFG_POOL_INDEX); + + pUmacStat2Get->u2PleFreePageNum = halUmacWrapFrePageCnt( + prAdapter, UMAC_PLE_CFG_POOL_INDEX); + + pUmacStat2Get->u2PseFreePageNum = halUmacWrapFrePageCnt( + prAdapter, UMAC_PSE_CFG_POOL_INDEX); + + pUmacStat2Get->u2PleFfaNum = halUmacWrapFfaCnt(prAdapter, + UMAC_PLE_CFG_POOL_INDEX); + + pUmacStat2Get->u2PseFfaNum = halUmacWrapFfaCnt(prAdapter, + UMAC_PSE_CFG_POOL_INDEX); + + return TRUE; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/p2p_nic.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/p2p_nic.c new file mode 100644 index 0000000000000..b0379c4598974 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/p2p_nic.c @@ -0,0 +1,283 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 struct ADAPTER *prAdapter, + IN struct EVENT_P2P_DEV_DISCOVER_RESULT *prP2pResult, + IN uint8_t *pucRxIEBuf, + IN uint16_t u2RxIELength) +{ + struct P2P_INFO *prP2pInfo = (struct P2P_INFO *) NULL; + struct EVENT_P2P_DEV_DISCOVER_RESULT *prTargetResult = + (struct EVENT_P2P_DEV_DISCOVER_RESULT *) NULL; + uint32_t u4Idx = 0; + u_int8_t bUpdate = FALSE; + + uint8_t *pucIeBuf = (uint8_t *) NULL; + uint16_t u2IELength = 0; + uint8_t 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(struct EVENT_P2P_DEV_DISCOVER_RESULT)); + + /* then buffer */ + kalMemCopy(prTargetResult, + (void *) prP2pResult, + sizeof(struct EVENT_P2P_DEV_DISCOVER_RESULT)); + + /* 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 (((unsigned long) prP2pInfo->pucCurrIePtr + + (unsigned long) u2RxIELength) > + (unsigned long)& + prP2pInfo->aucCommIePool + [CFG_MAX_COMMON_IE_BUF_LEN]) { + + /* Common Buffer is no enough. */ + u2RxIELength = + (uint16_t) ((unsigned long) + &prP2pInfo->aucCommIePool + [CFG_MAX_COMMON_IE_BUF_LEN] - + (unsigned long) + prP2pInfo->pucCurrIePtr); + } + + /* Step to next buffer address. */ + prP2pInfo->pucCurrIePtr = + (uint8_t *) ((unsigned long) + prP2pInfo->pucCurrIePtr + + (unsigned long) u2RxIELength); + } + + /* Restore buffer pointer. */ + prTargetResult->pucIeBuf = pucIeBuf; + + if (pucRxIEBuf) { + /* If new received IE is available. + * Replace the old one & update new IE length. + */ + kalMemCopy(pucIeBuf, pucRxIEBuf, u2RxIELength); + prTargetResult->u2IELength = u2RxIELength; + } else { + /* There is no new IE information, + * keep the old one. + */ + prTargetResult->u2IELength = u2IELength; + } + } + } + + if (!bUpdate) { + /* We would flush the whole scan result + * after each scan request is issued. + * If P2P device is too many, it may over the scan list. + */ + if ((u4Idx < CFG_MAX_NUM_BSS_LIST) + && (UNEQUAL_MAC_ADDR(zeroMac, + prP2pResult->aucDeviceAddr))) { + + prTargetResult = &prP2pInfo->arP2pDiscoverResult[u4Idx]; + + /* zero */ + kalMemZero(prTargetResult, + sizeof(struct EVENT_P2P_DEV_DISCOVER_RESULT)); + + /* then buffer */ + kalMemCopy(prTargetResult, + (void *) prP2pResult, + sizeof(struct EVENT_P2P_DEV_DISCOVER_RESULT)); + + /* printk("DVC FND %d " MACSTR", " MACSTR "\n", + * prP2pInfo->u4DeviceNum, + * MAC2STR(prP2pResult->aucDeviceAddr), + * MAC2STR(prTargetResult->aucDeviceAddr)); + */ + + if (u2RxIELength) { + prTargetResult->pucIeBuf = + prP2pInfo->pucCurrIePtr; + + if (((unsigned long) prP2pInfo->pucCurrIePtr + + (unsigned long) u2RxIELength) > + (unsigned long) + &prP2pInfo->aucCommIePool + [CFG_MAX_COMMON_IE_BUF_LEN]) { + + /* Common Buffer is no enough. */ + u2IELength = + (uint16_t) ((unsigned long) + &prP2pInfo->aucCommIePool + [CFG_MAX_COMMON_IE_BUF_LEN] - + (unsigned long) + prP2pInfo->pucCurrIePtr); + } else { + u2IELength = u2RxIELength; + } + + prP2pInfo->pucCurrIePtr = + (uint8_t *) ((unsigned long) + prP2pInfo->pucCurrIePtr + + (unsigned long) u2IELength); + + kalMemCopy((void *) prTargetResult->pucIeBuf, + (void *) pucRxIEBuf, + (uint32_t) u2IELength); + + prTargetResult->u2IELength = u2IELength; + } else { + prTargetResult->pucIeBuf = NULL; + prTargetResult->u2IELength = 0; + } + + prP2pInfo->u4DeviceNum++; + + } else { + /* TODO: Fixme to replace an old one. (?) */ + ASSERT(FALSE); + } + } +} /* nicRxAddP2pDevice */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/que_mgt.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/que_mgt.c new file mode 100644 index 0000000000000..74b8d19e0f62f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/nic/que_mgt.c @@ -0,0 +1,8363 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \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. + */ + + +/******************************************************************************* + * C O M P I L E 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 "queue.h" +#if CFG_MTK_MCIF_WIFI_SUPPORT +#include "mddp.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 + ******************************************************************************* + */ +OS_SYSTIME g_arMissTimeout[CFG_STA_REC_NUM][CFG_RX_MAX_BA_TID_NUM]; + +const uint8_t aucTid2ACI[TX_DESC_TID_NUM] = { + WMM_AC_BE_INDEX, /* TID0 */ + WMM_AC_BK_INDEX, /* TID1 */ + WMM_AC_BK_INDEX, /* TID2 */ + WMM_AC_BE_INDEX, /* TID3 */ + WMM_AC_VI_INDEX, /* TID4 */ + WMM_AC_VI_INDEX, /* TID5 */ + WMM_AC_VO_INDEX, /* TID6 */ + WMM_AC_VO_INDEX /* TID7 */ +}; + +const uint8_t aucACI2TxQIdx[WMM_AC_INDEX_NUM] = { + TX_QUEUE_INDEX_AC1, /* WMM_AC_BE_INDEX */ + TX_QUEUE_INDEX_AC0, /* WMM_AC_BK_INDEX */ + TX_QUEUE_INDEX_AC2, /* WMM_AC_VI_INDEX */ + TX_QUEUE_INDEX_AC3 /* WMM_AC_VO_INDEX */ +}; + +const uint8_t *apucACI2Str[WMM_AC_INDEX_NUM] = { + "BE", "BK", "VI", "VO" +}; + +const uint8_t arNetwork2TcResource[MAX_BSSID_NUM + 1][NET_TC_NUM] = { + /* HW Queue Set 1 */ + /* AC_BE, AC_BK, AC_VI, AC_VO, MGMT, BMC */ + /* AIS */ + {TC1_INDEX, TC0_INDEX, TC2_INDEX, TC3_INDEX, TC4_INDEX, BMC_TC_INDEX}, + /* P2P/BoW */ + {TC1_INDEX, TC0_INDEX, TC2_INDEX, TC3_INDEX, TC4_INDEX, BMC_TC_INDEX}, + /* P2P/BoW */ + {TC1_INDEX, TC0_INDEX, TC2_INDEX, TC3_INDEX, TC4_INDEX, BMC_TC_INDEX}, + /* P2P/BoW */ + {TC1_INDEX, TC0_INDEX, TC2_INDEX, TC3_INDEX, TC4_INDEX, BMC_TC_INDEX}, + /* P2P_DEV */ + {TC1_INDEX, TC0_INDEX, TC2_INDEX, TC3_INDEX, TC4_INDEX, BMC_TC_INDEX}, +}; + +const uint8_t aucWmmAC2TcResourceSet1[WMM_AC_INDEX_NUM] = { + TC1_INDEX, + TC0_INDEX, + TC2_INDEX, + TC3_INDEX +}; + +#if NIC_TX_ENABLE_SECOND_HW_QUEUE +const uint8_t aucWmmAC2TcResourceSet2[WMM_AC_INDEX_NUM] = { + TC7_INDEX, + TC6_INDEX, + TC8_INDEX, + TC9_INDEX +}; +#endif +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +#if ARP_MONITER_ENABLE +static uint16_t arpMoniter; +static uint8_t apIp[4]; +static uint8_t gatewayIp[4]; +static uint32_t last_rx_packets, latest_rx_packets; +#endif +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR +#define LINK_QUALITY_COUNT_DUP(prAdapter, prSwRfb) \ +do { \ + struct BSS_INFO *prBssInfo = NULL; \ + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, \ + AIS_DEFAULT_INDEX); \ + if (prBssInfo && prBssInfo->prStaRecOfAP) \ + if (prBssInfo->prStaRecOfAP->ucWlanIndex == \ + prSwRfb->ucWlanIdx) \ + prAdapter->rLinkQualityInfo.u4RxDupCount++; \ +} while (0) +#else +#define LINK_QUALITY_COUNT_DUP +#endif /* CFG_SUPPORT_LINK_QUALITY_MONITOR */ + +#if CFG_RX_REORDERING_ENABLED +#define qmHandleRxPackets_AOSP_1 \ +do { \ + /* ToDo[6630]: duplicate removal */ \ + if (!fgIsBMC && nicRxIsDuplicateFrame(prCurrSwRfb) == TRUE) { \ + DBGLOG(QM, TRACE, "Duplicated packet is detected\n"); \ + RX_INC_CNT(&prAdapter->rRxCtrl, RX_DUPICATE_DROP_COUNT); \ + LINK_QUALITY_COUNT_DUP(prAdapter, prCurrSwRfb); \ + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; \ + } \ + /* ToDo[6630]: defragmentation */ \ + if (prCurrSwRfb->fgFragFrame) { \ + prCurrSwRfb = nicRxDefragMPDU(prAdapter, \ + prCurrSwRfb, prReturnedQue); \ + if (prCurrSwRfb) { \ + prRxStatus = prCurrSwRfb->prRxStatus; \ + DBGLOG(QM, TRACE, \ + "defragmentation RxStatus=%p\n", prRxStatus); \ + } \ + } \ + if (prCurrSwRfb) { \ + fgMicErr = FALSE; \ + if (prCurrSwRfb->ucSecMode == \ + CIPHER_SUITE_TKIP_WO_MIC) { \ + if (prCurrSwRfb->prStaRec) { \ + uint8_t ucBssIndex; \ + struct BSS_INFO *prBssInfo = NULL; \ + uint8_t *pucMicKey = NULL; \ + ucBssIndex = \ + prCurrSwRfb->prStaRec->ucBssIndex; \ + ASSERT(ucBssIndex < prAdapter->ucHwBssIdNum); \ + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, \ + ucBssIndex); \ + ASSERT(prBssInfo); \ + if (prBssInfo->eCurrentOPMode == \ + OP_MODE_INFRASTRUCTURE) \ + pucMicKey = \ + &(aisGetAisSpecBssInfo(prAdapter, \ + ucBssIndex)->aucRxMicKey[0]); \ + else { \ + ASSERT(FALSE); \ + } \ + /* SW TKIP MIC verify */ \ + if (pucMicKey == NULL) { \ + DBGLOG(RX, ERROR, \ + "No TKIP Mic Key\n"); \ + fgMicErr = TRUE; \ + } \ + else if (tkipMicDecapsulateInRxHdrTransMode( \ + prCurrSwRfb, pucMicKey) == FALSE) { \ + fgMicErr = TRUE; \ + } \ + } \ + if (fgMicErr) { \ + /* bypass tkip frag */ \ + if (!prCurrSwRfb->fgFragFrame) { \ + log_dbg(RX, ERROR, \ + "Mark NULL for TKIP Mic Error\n"); \ + RX_INC_CNT(&prAdapter->rRxCtrl, \ + RX_MIC_ERROR_DROP_COUNT); \ + prCurrSwRfb->eDst = \ + RX_PKT_DESTINATION_NULL; \ + } \ + } \ + } \ + QUEUE_INSERT_TAIL(prReturnedQue, \ + (struct QUE_ENTRY *)prCurrSwRfb); \ + } \ +} while (0) +#endif + +#define RX_DIRECT_REORDER_LOCK(pad, dbg) \ +do { \ + struct GLUE_INFO *_glue = pad->prGlueInfo; \ + if (!HAL_IS_RX_DIRECT(pad) || !_glue) \ + break; \ + if (dbg) \ + DBGLOG(QM, EVENT, "RX_DIRECT_REORDER_LOCK %d\n", __LINE__); \ + spin_lock_bh(&_glue->rSpinLock[SPIN_LOCK_RX_DIRECT_REORDER]);\ +} while (0) + +#define RX_DIRECT_REORDER_UNLOCK(pad, dbg) \ +do { \ + struct GLUE_INFO *_glue = pad->prGlueInfo; \ + if (!HAL_IS_RX_DIRECT(pad) || !_glue) \ + break; \ + if (dbg) \ + DBGLOG(QM, EVENT, "RX_DIRECT_REORDER_UNLOCK %u\n", __LINE__); \ + spin_unlock_bh(&_glue->rSpinLock[SPIN_LOCK_RX_DIRECT_REORDER]); \ +} while (0) + +/******************************************************************************* + * 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 Queue Management for TX + * + * \param[in] (none) + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void qmInit(IN struct ADAPTER *prAdapter, + IN u_int8_t isTxResrouceControlEn) +{ + uint32_t u4Idx; +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + uint32_t u4TotalMinReservedTcResource = 0; + uint32_t u4TotalTcResource = 0; + uint32_t u4TotalGurantedTcResource = 0; +#endif + + struct QUE_MGT *prQM = &prAdapter->rQM; + + /* DbgPrint("QM: Enter qmInit()\n"); */ + + /* 4 <2> Initialize other TX queues (queues not in STA_RECs) */ + for (u4Idx = 0; u4Idx < NUM_OF_PER_TYPE_TX_QUEUES; u4Idx++) + QUEUE_INITIALIZE(&(prQM->arTxQueue[u4Idx])); + + /* 4 <3> Initialize the RX BA table and RX queues */ + /* Initialize the RX Reordering Parameters and Queues */ + for (u4Idx = 0; u4Idx < CFG_NUM_OF_RX_BA_AGREEMENTS; u4Idx++) { + prQM->arRxBaTable[u4Idx].fgIsValid = FALSE; + QUEUE_INITIALIZE(&(prQM->arRxBaTable[u4Idx].rReOrderQue)); + prQM->arRxBaTable[u4Idx].u2WinStart = 0xFFFF; + prQM->arRxBaTable[u4Idx].u2WinEnd = 0xFFFF; + + prQM->arRxBaTable[u4Idx].fgIsWaitingForPktWithSsn = FALSE; + prQM->arRxBaTable[u4Idx].fgHasBubble = FALSE; +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + prQM->arRxBaTable[u4Idx].u8LastAmsduSubIdx = + RX_PAYLOAD_FORMAT_MSDU; + prQM->arRxBaTable[u4Idx].fgAmsduNeedLastFrame = FALSE; + prQM->arRxBaTable[u4Idx].fgIsAmsduDuplicated = FALSE; +#endif + cnmTimerInitTimer(prAdapter, + &(prQM->arRxBaTable[u4Idx].rReorderBubbleTimer), + (PFN_MGMT_TIMEOUT_FUNC) qmHandleReorderBubbleTimeout, + (unsigned long) (&prQM->arRxBaTable[u4Idx])); + + } + prQM->ucRxBaCount = 0; + + kalMemSet(&g_arMissTimeout, 0, sizeof(g_arMissTimeout)); + + prQM->fgIsTxResrouceControlEn = isTxResrouceControlEn; + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + /* 4 <4> Initialize TC resource control variables */ + for (u4Idx = 0; u4Idx < TC_NUM; u4Idx++) + prQM->au4AverageQueLen[u4Idx] = 0; + + ASSERT(prQM->u4TimeToAdjustTcResource + && prQM->u4TimeToUpdateQueLen); + + for (u4Idx = 0; u4Idx < TC_NUM; u4Idx++) { + prQM->au4CurrentTcResource[u4Idx] = + prAdapter->rTxCtrl.rTc.au4MaxNumOfBuffer[u4Idx]; + + if (u4Idx != TC4_INDEX) { + u4TotalTcResource += prQM->au4CurrentTcResource[u4Idx]; + u4TotalGurantedTcResource += + prQM->au4GuaranteedTcResource[u4Idx]; + u4TotalMinReservedTcResource += + prQM->au4MinReservedTcResource[u4Idx]; + } + } + + /* Sanity Check */ + if (u4TotalMinReservedTcResource > u4TotalTcResource) + kalMemZero(prQM->au4MinReservedTcResource, + sizeof(prQM->au4MinReservedTcResource)); + + if (u4TotalGurantedTcResource > u4TotalTcResource) + kalMemZero(prQM->au4GuaranteedTcResource, + sizeof(prQM->au4GuaranteedTcResource)); + + u4TotalGurantedTcResource = 0; + + /* Initialize Residual TC resource */ + for (u4Idx = 0; u4Idx < TC_NUM; u4Idx++) { + if (prQM->au4GuaranteedTcResource[u4Idx] < + prQM->au4MinReservedTcResource[u4Idx]) + prQM->au4GuaranteedTcResource[u4Idx] = + prQM->au4MinReservedTcResource[u4Idx]; + + if (u4Idx != TC4_INDEX) + u4TotalGurantedTcResource += + prQM->au4GuaranteedTcResource[u4Idx]; + } + + prQM->u4ResidualTcResource = u4TotalTcResource - + u4TotalGurantedTcResource; + + prQM->fgTcResourcePostAnnealing = FALSE; + prQM->fgForceReassign = FALSE; +#if QM_FAST_TC_RESOURCE_CTRL + prQM->fgTcResourceFastReaction = FALSE; +#endif +#endif + +#if QM_TEST_MODE + prQM->u4PktCount = 0; + +#if QM_TEST_FAIR_FORWARDING + + prQM->u4CurrentStaRecIndexToEnqueue = 0; + { + uint8_t aucMacAddr[MAC_ADDR_LEN]; + struct STA_RECORD *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->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + COPY_MAC_ADDR((prStaRec)->aucMacAddr, aucMacAddr); + + } + +#endif + +#endif + +#if QM_FORWARDING_FAIRNESS + for (u4Idx = 0; u4Idx < NUM_OF_PER_STA_TX_QUEUES; u4Idx++) { + prQM->au4ResourceUsedCount[u4Idx] = 0; + prQM->au4HeadStaRecIndex[u4Idx] = 0; + } + + prQM->u4HeadBssInfoIndex = 0; + prQM->u4GlobalResourceUsedCount = 0; +#endif + + prQM->u4TxAllowedStaCount = 0; + + prQM->rLastTxPktDumpTime = (OS_SYSTIME) kalGetTimeTick(); + +} + +#if QM_TEST_MODE +void qmTestCases(IN struct ADAPTER *prAdapter) +{ + struct QUE_MGT *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, &prAdapter->arStaRec[0]); + } else { + + uint8_t 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 Update a STA_REC + * + * \param[in] prAdapter Pointer to the Adapter instance + * \param[in] prStaRec The pointer of the STA_REC + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void qmUpdateStaRec(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + struct BSS_INFO *prBssInfo; + u_int8_t fgIsTxAllowed = FALSE; + + if (!prStaRec) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + ASSERT(prBssInfo); + + /* 4 <1> Ensure STA is valid */ + if (prStaRec->fgIsValid) { + /* 4 <2.1> STA/BSS is protected */ + if (secIsProtectedBss(prAdapter, prBssInfo)) { + if (prStaRec->fgIsTxKeyReady || + secIsWepBss(prAdapter, prBssInfo)) + fgIsTxAllowed = TRUE; + else + fgIsTxAllowed = FALSE; + } + /* 4 <2.2> OPEN security */ + else + fgIsTxAllowed = TRUE; + } + /* 4 Update StaRec */ + qmSetStaRecTxAllowed(prAdapter, prStaRec, fgIsTxAllowed); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Activate a STA_REC + * + * \param[in] prAdapter Pointer to the Adapter instance + * \param[in] prStaRec The pointer of the STA_REC + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void qmActivateStaRec(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + /* 4 <1> Deactivate first */ + if (!prStaRec) + return; + + if (prStaRec->fgIsValid) { /* The STA_REC has been activated */ + DBGLOG(QM, WARN, + "QM: (WARNING) Activating a STA_REC which has been activated\n"); + DBGLOG(QM, WARN, + "QM: (WARNING) Deactivating a STA_REC before re-activating\n"); + /* To flush TX/RX queues and del RX BA agreements */ + qmDeactivateStaRec(prAdapter, prStaRec); + } + /* 4 <2> Activate the STA_REC */ + /* Reset buffer count */ + prStaRec->ucFreeQuota = 0; + prStaRec->ucFreeQuotaForDelivery = 0; + prStaRec->ucFreeQuotaForNonDelivery = 0; + + /* Init the STA_REC */ + prStaRec->fgIsValid = TRUE; + prStaRec->fgIsInPS = FALSE; + + /* Default setting of TX/RX AMPDU */ + prStaRec->fgTxAmpduEn = IS_FEATURE_ENABLED( + prAdapter->rWifiVar.ucAmpduTx); + prStaRec->fgRxAmpduEn = IS_FEATURE_ENABLED( + prAdapter->rWifiVar.ucAmpduRx); + + nicTxGenerateDescTemplate(prAdapter, prStaRec); + + qmUpdateStaRec(prAdapter, prStaRec); + + /* 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 + +#if CFG_MTK_MCIF_WIFI_SUPPORT + mddpNotifyDrvTxd(prAdapter, prStaRec, TRUE); +#endif + + DBGLOG(QM, INFO, "QM: +STA[%d]\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 struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + uint32_t i; + + if (!prStaRec) + return; + /* 4 <1> Flush TX queues */ + if (HAL_IS_TX_DIRECT(prAdapter)) { + nicTxDirectClearStaPsQ(prAdapter, prStaRec->ucIndex); + } else { + struct MSDU_INFO *prFlushedTxPacketList = NULL; + + prFlushedTxPacketList = qmFlushStaTxQueues(prAdapter, + prStaRec->ucIndex); + + 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, prStaRec->ucIndex, (uint8_t) i, + FALSE); + } + + /* 4 <3> Deactivate the STA_REC */ + prStaRec->fgIsValid = FALSE; + prStaRec->fgIsInPS = FALSE; + prStaRec->fgIsTxKeyReady = FALSE; + + /* Reset buffer count */ + prStaRec->ucFreeQuota = 0; + prStaRec->ucFreeQuotaForDelivery = 0; + prStaRec->ucFreeQuotaForNonDelivery = 0; + + nicTxFreeDescTemplate(prAdapter, prStaRec); + + qmUpdateStaRec(prAdapter, prStaRec); + +#if CFG_MTK_MCIF_WIFI_SUPPORT + mddpNotifyDrvTxd(prAdapter, prStaRec, FALSE); +#endif + + DBGLOG(QM, INFO, "QM: -STA[%u]\n", prStaRec->ucIndex); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Deactivate a STA_REC + * + * \param[in] prAdapter Pointer to the Adapter instance + * \param[in] ucBssIndex The index of the BSS + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void qmFreeAllByBssIdx(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIndex) +{ + + struct QUE_MGT *prQM; + struct QUE *prQue; + struct QUE rNeedToFreeQue; + struct QUE rTempQue; + struct QUE *prNeedToFreeQue; + struct QUE *prTempQue; + struct MSDU_INFO *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, + struct MSDU_INFO *); + while (prMsduInfo) { + + if (prMsduInfo->ucBssIndex == ucBssIndex) { + /* QUEUE_INSERT_TAIL */ + QUEUE_INSERT_TAIL(prNeedToFreeQue, + (struct QUE_ENTRY *) prMsduInfo); + } else { + /* QUEUE_INSERT_TAIL */ + QUEUE_INSERT_TAIL(prQue, + (struct QUE_ENTRY *) prMsduInfo); + } + + QUEUE_REMOVE_HEAD(prTempQue, prMsduInfo, + struct MSDU_INFO *); + } + if (QUEUE_IS_NOT_EMPTY(prNeedToFreeQue)) + wlanProcessQueuedMsduInfo(prAdapter, + (struct MSDU_INFO *) + QUEUE_GET_HEAD(prNeedToFreeQue)); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Flush all TX queues + * + * \param[in] (none) + * + * \return The flushed packets (in a list of MSDU_INFOs) + */ +/*----------------------------------------------------------------------------*/ +struct MSDU_INFO *qmFlushTxQueues(IN struct ADAPTER *prAdapter) +{ + uint8_t ucStaArrayIdx; + uint8_t ucQueArrayIdx; + + struct QUE_MGT *prQM = &prAdapter->rQM; + + struct QUE rTempQue; + struct QUE *prTempQue = &rTempQue; + struct QUE *prQue; + + DBGLOG(QM, TRACE, "QM: Enter qmFlushTxQueues()\n"); + + QUEUE_INITIALIZE(prTempQue); + + /* Concatenate all MSDU_INFOs in per-STA queues */ + for (ucStaArrayIdx = 0; ucStaArrayIdx < CFG_STA_REC_NUM; + ucStaArrayIdx++) { + for (ucQueArrayIdx = 0; + ucQueArrayIdx < NUM_OF_PER_STA_TX_QUEUES; + ucQueArrayIdx++) { + prQue = &(prAdapter->arStaRec[ucStaArrayIdx]. + arPendingTxQueue[ucQueArrayIdx]); + QUEUE_CONCATENATE_QUEUES(prTempQue, prQue); + prQue = &(prAdapter->arStaRec[ucStaArrayIdx]. + arTxQueue[ucQueArrayIdx]); + QUEUE_CONCATENATE_QUEUES(prTempQue, prQue); + } + } + + /* Flush per-Type queues */ + for (ucQueArrayIdx = 0; + ucQueArrayIdx < NUM_OF_PER_TYPE_TX_QUEUES; + ucQueArrayIdx++) { + prQue = &(prQM->arTxQueue[ucQueArrayIdx]); + QUEUE_CONCATENATE_QUEUES(prTempQue, prQue); + } + + return (struct MSDU_INFO *)QUEUE_GET_HEAD(prTempQue); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Flush TX packets for a particular STA + * + * \param[in] u4StaRecIdx STA_REC index + * + * \return The flushed packets (in a list of MSDU_INFOs) + */ +/*----------------------------------------------------------------------------*/ +struct MSDU_INFO *qmFlushStaTxQueues(IN struct ADAPTER *prAdapter, + IN uint32_t u4StaRecIdx) +{ + uint8_t ucQueArrayIdx; + struct STA_RECORD *prStaRec; + struct QUE *prQue; + struct QUE rTempQue; + struct QUE *prTempQue = &rTempQue; + + DBGLOG(QM, TRACE, "QM: Enter qmFlushStaTxQueues(%u)\n", u4StaRecIdx); + + ASSERT(u4StaRecIdx < CFG_STA_REC_NUM); + + prStaRec = &prAdapter->arStaRec[u4StaRecIdx]; + ASSERT(prStaRec); + + QUEUE_INITIALIZE(prTempQue); + + /* Concatenate all MSDU_INFOs in TX queues of this STA_REC */ + for (ucQueArrayIdx = 0; + ucQueArrayIdx < NUM_OF_PER_STA_TX_QUEUES; ucQueArrayIdx++) { + prQue = &(prStaRec->arPendingTxQueue[ucQueArrayIdx]); + QUEUE_CONCATENATE_QUEUES(prTempQue, prQue); + prQue = &(prStaRec->arTxQueue[ucQueArrayIdx]); + QUEUE_CONCATENATE_QUEUES(prTempQue, prQue); + } + + return (struct MSDU_INFO *)QUEUE_GET_HEAD(prTempQue); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Flush RX packets + * + * \param[in] (none) + * + * \return The flushed packets (in a list of SW_RFBs) + */ +/*----------------------------------------------------------------------------*/ +struct SW_RFB *qmFlushRxQueues(IN struct ADAPTER *prAdapter) +{ + uint32_t i; + struct SW_RFB *prSwRfbListHead; + struct SW_RFB *prSwRfbListTail; + struct QUE_MGT *prQM = &prAdapter->rQM; + + prSwRfbListHead = prSwRfbListTail = NULL; + + DBGLOG(QM, TRACE, "QM: Enter qmFlushRxQueues()\n"); + + RX_DIRECT_REORDER_LOCK(prAdapter, 0); + 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 = (struct SW_RFB *) + QUEUE_GET_HEAD( + &(prQM->arRxBaTable[i]. + rReOrderQue)); + prSwRfbListTail = (struct SW_RFB *) + 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 = (struct SW_RFB *) + QUEUE_GET_TAIL( + &(prQM->arRxBaTable[i]. + rReOrderQue)); + } + + QUEUE_INITIALIZE(&(prQM->arRxBaTable[i].rReOrderQue)); + if (QM_RX_GET_NEXT_SW_RFB(prSwRfbListTail)) { + DBGLOG(QM, ERROR, + "QM: non-null tail->next at arRxBaTable[%u]\n", + i); + } + } else { + continue; + } + } + RX_DIRECT_REORDER_UNLOCK(prAdapter, 0); + + 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) + */ +/*----------------------------------------------------------------------------*/ +struct SW_RFB *qmFlushStaRxQueue(IN struct ADAPTER *prAdapter, + IN uint32_t u4StaRecIdx, IN uint32_t u4Tid) +{ + /* UINT_32 i; */ + struct SW_RFB *prSwRfbListHead; + struct SW_RFB *prSwRfbListTail; + struct RX_BA_ENTRY *prReorderQueParm; + struct STA_RECORD *prStaRec; + + DBGLOG(QM, TRACE, "QM: Enter qmFlushStaRxQueues(%u)\n", u4StaRecIdx); + + prSwRfbListHead = prSwRfbListTail = NULL; + + prStaRec = &prAdapter->arStaRec[u4StaRecIdx]; + ASSERT(prStaRec); + + /* No matter whether this is an activated STA_REC, do flush */ +#if 0 + if (!prStaRec->fgIsValid) + return NULL; +#endif + + /* Obtain the RX BA Entry pointer */ + prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[u4Tid]); + + /* Note: For each queued packet, + * prCurrSwRfb->eDst equals RX_PKT_DESTINATION_HOST + */ + if (prReorderQueParm) { + RX_DIRECT_REORDER_LOCK(prAdapter, 0); + if (QUEUE_IS_NOT_EMPTY(&(prReorderQueParm->rReOrderQue))) { + + prSwRfbListHead = (struct SW_RFB *) + QUEUE_GET_HEAD( + &(prReorderQueParm->rReOrderQue)); + prSwRfbListTail = (struct SW_RFB *) + QUEUE_GET_TAIL( + &(prReorderQueParm->rReOrderQue)); + + QUEUE_INITIALIZE(&(prReorderQueParm->rReOrderQue)); + } + RX_DIRECT_REORDER_UNLOCK(prAdapter, 0); + } + + if (prSwRfbListTail) { + if (QM_RX_GET_NEXT_SW_RFB(prSwRfbListTail)) { + DBGLOG(QM, ERROR, + "QM: non-empty tail->next at STA %u TID %u\n", + u4StaRecIdx, u4Tid); + } + + /* Terminate the MSDU_INFO list with a NULL pointer */ + QM_TX_SET_NEXT_SW_RFB(prSwRfbListTail, NULL); + } + return prSwRfbListHead; +} + +struct QUE *qmDetermineStaTxQueue(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN uint8_t ucActiveTs, OUT uint8_t *pucTC) +{ + struct QUE *prTxQue = NULL; + struct STA_RECORD *prStaRec; + enum ENUM_WMM_ACI eAci = WMM_AC_BE_INDEX; + u_int8_t fgCheckACMAgain; + uint8_t ucTC, ucQueIdx = WMM_AC_BE_INDEX; + struct BSS_INFO *prBssInfo; + /* BEtoBK, na, VItoBE, VOtoVI */ + uint8_t aucNextUP[WMM_AC_INDEX_NUM] = {1, 1, 0, 4}; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prMsduInfo->ucBssIndex); + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, + prMsduInfo->ucStaRecIndex); + if (prStaRec == NULL) + return prTxQue; + + if (!prStaRec) { + DBGLOG(QM, ERROR, "prStaRec is null.\n"); + return NULL; + } + if (prMsduInfo->ucUserPriority < 8) { + QM_DBG_CNT_INC(&prAdapter->rQM, + prMsduInfo->ucUserPriority + 15); + } + + eAci = WMM_AC_BE_INDEX; + do { + fgCheckACMAgain = FALSE; + if (prStaRec->fgIsQoS) { + if (prMsduInfo->ucUserPriority < TX_DESC_TID_NUM) { + eAci = aucTid2ACI[prMsduInfo->ucUserPriority]; + ucQueIdx = aucACI2TxQIdx[eAci]; + ucTC = + arNetwork2TcResource[ + prMsduInfo->ucBssIndex][eAci]; + } else { + ucQueIdx = TX_QUEUE_INDEX_AC1; + ucTC = TC1_INDEX; + eAci = WMM_AC_BE_INDEX; + DBGLOG(QM, WARN, + "Packet TID is not in [0~7]\n"); + ASSERT(0); + } + if ((prBssInfo->arACQueParms[eAci].ucIsACMSet) && + !(ucActiveTs & BIT(eAci)) && + (eAci != WMM_AC_BK_INDEX)) { + DBGLOG(WMM, TRACE, + "ucUserPriority: %d, aucNextUP[eAci]: %d", + prMsduInfo->ucUserPriority, + aucNextUP[eAci]); + prMsduInfo->ucUserPriority = aucNextUP[eAci]; + fgCheckACMAgain = TRUE; + } + } else { + ucQueIdx = TX_QUEUE_INDEX_NON_QOS; + ucTC = arNetwork2TcResource[prMsduInfo->ucBssIndex][ + NET_TC_WMM_AC_BE_INDEX]; + } + + if (prAdapter->rWifiVar.ucTcRestrict < TC_NUM) { + ucTC = prAdapter->rWifiVar.ucTcRestrict; + ucQueIdx = ucTC; + } + + } while (fgCheckACMAgain); + + if (ucQueIdx >= NUM_OF_PER_STA_TX_QUEUES) { + DBGLOG(QM, ERROR, + "ucQueIdx = %u, needs 0~3 to avoid out-of-bounds.\n", + ucQueIdx); + return NULL; + } + if (prStaRec->fgIsTxAllowed) { + /* non protected BSS or protected BSS with key set */ + prTxQue = prStaRec->aprTargetQueue[ucQueIdx]; + } else if (secIsProtectedBss(prAdapter, prBssInfo) && + prMsduInfo->fgIs802_1x && + prMsduInfo->fgIs802_1x_NonProtected) { + /* protected BSS without key set */ + /* Tx pairwise EAPOL 1x packet (non-protected frame) */ + prTxQue = &prStaRec->arTxQueue[ucQueIdx]; + } else { + /* protected BSS without key set */ + /* Enqueue protected frame into pending queue */ + prTxQue = prStaRec->aprTargetQueue[ucQueIdx]; + } + + *pucTC = ucTC; + /* + * Record how many packages enqueue this STA + * to TX during statistic intervals + */ + prStaRec->u4EnqueueCounter++; + + return prTxQue; +} + +void qmSetTxPacketDescTemplate(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct STA_RECORD *prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX( + prAdapter, prMsduInfo->ucStaRecIndex); + + /* Check the Tx descriptor template is valid */ + if (prStaRec && + prStaRec->aprTxDescTemplate[prMsduInfo->ucUserPriority]) { + prMsduInfo->fgIsTXDTemplateValid = TRUE; + } else { + if (prStaRec) { + DBGLOG(QM, TRACE, + "Cannot get TXD template for STA[%u] QoS[%u] MSDU UP[%u]\n", + prStaRec->ucIndex, prStaRec->fgIsQoS, + prMsduInfo->ucUserPriority); + } + prMsduInfo->fgIsTXDTemplateValid = FALSE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief : To StaRec, function to stop TX + * + * \param[in] : + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void qmSetStaRecTxAllowed(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, IN u_int8_t fgIsTxAllowed) +{ + uint8_t ucIdx; + struct QUE *prSrcQ, *prDstQ; + + DBGLOG(QM, INFO, "Set Sta[%u] TxAllowed from [%u] to [%u] %s TxQ\n", + prStaRec->ucIndex, + prStaRec->fgIsTxAllowed, + fgIsTxAllowed, + fgIsTxAllowed ? "normal" : "pending"); + + /* Update Tx queue when allowed state change*/ + if (prStaRec->fgIsTxAllowed != fgIsTxAllowed) { + for (ucIdx = 0; ucIdx < NUM_OF_PER_STA_TX_QUEUES; ucIdx++) { + if (fgIsTxAllowed) { + prSrcQ = &prStaRec->arPendingTxQueue[ucIdx]; + prDstQ = &prStaRec->arTxQueue[ucIdx]; + } else { + prSrcQ = &prStaRec->arTxQueue[ucIdx]; + prDstQ = &prStaRec->arPendingTxQueue[ucIdx]; + } + + QUEUE_CONCATENATE_QUEUES_HEAD(prDstQ, prSrcQ); + prStaRec->aprTargetQueue[ucIdx] = prDstQ; + } + + if (fgIsTxAllowed) + prAdapter->rQM.u4TxAllowedStaCount++; + else + prAdapter->rQM.u4TxAllowedStaCount--; + } + prStaRec->fgIsTxAllowed = fgIsTxAllowed; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Enqueue TX packets + * + * \param[in] prMsduInfoListHead Pointer to the list of TX packets + * + * \return The freed packets, which are not enqueued + */ +/*----------------------------------------------------------------------------*/ +struct MSDU_INFO *qmEnqueueTxPackets(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfoListHead) +{ + struct MSDU_INFO *prMsduInfoReleaseList; + struct MSDU_INFO *prCurrentMsduInfo; + struct MSDU_INFO *prNextMsduInfo; + + struct QUE *prTxQue; + struct QUE rNotEnqueuedQue; + struct STA_RECORD *prStaRec; + uint8_t ucTC; + struct TX_CTRL *prTxCtrl = &prAdapter->rTxCtrl; + struct QUE_MGT *prQM = &prAdapter->rQM; + struct BSS_INFO *prBssInfo; + u_int8_t fgDropPacket; + uint8_t ucActivedTspec = 0; + + DBGLOG(QM, LOUD, "Enter qmEnqueueTxPackets\n"); + + ASSERT(prMsduInfoListHead); + + prMsduInfoReleaseList = NULL; + prCurrentMsduInfo = NULL; + QUEUE_INITIALIZE(&rNotEnqueuedQue); + prNextMsduInfo = prMsduInfoListHead; + + do { + prCurrentMsduInfo = prNextMsduInfo; + prNextMsduInfo = QM_TX_GET_NEXT_MSDU_INFO( + prCurrentMsduInfo); + ucTC = TC1_INDEX; + + /* 4 <0> Sanity check of BSS_INFO */ + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prCurrentMsduInfo->ucBssIndex); + + if (!prBssInfo) { + /* No BSS_INFO */ + fgDropPacket = TRUE; + } else if (IS_BSS_ACTIVE(prBssInfo)) { + /* BSS active */ + fgDropPacket = FALSE; + } else { + /* BSS inactive */ + fgDropPacket = TRUE; + } + + if (!fgDropPacket) { + /* 4 <1> Lookup the STA_REC index */ + /* The ucStaRecIndex will be set in this function */ + qmDetermineStaRecIndex(prAdapter, prCurrentMsduInfo); + + /*get per-AC Tx packets */ + wlanUpdateTxStatistics(prAdapter, prCurrentMsduInfo, + FALSE); + + DBGLOG(QM, LOUD, "Enqueue MSDU by StaRec[%u]!\n", + prCurrentMsduInfo->ucStaRecIndex); + + switch (prCurrentMsduInfo->ucStaRecIndex) { + case STA_REC_INDEX_BMCAST: + prTxQue = + &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST]; + ucTC = + arNetwork2TcResource[prCurrentMsduInfo-> + ucBssIndex][NET_TC_BMC_INDEX]; + + /* Always set BMC packet retry limit + * to unlimited + */ + if (!(prCurrentMsduInfo->u4Option & + MSDU_OPT_MANUAL_RETRY_LIMIT)) + nicTxSetPktRetryLimit(prCurrentMsduInfo, + TX_DESC_TX_COUNT_NO_LIMIT); + + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_23); + break; + + case STA_REC_INDEX_NOT_FOUND: + /* Drop packet if no STA_REC is found */ + DBGLOG(QM, TRACE, + "Drop the Packet for no STA_REC\n"); + + prTxQue = &rNotEnqueuedQue; + + TX_INC_CNT(&prAdapter->rTxCtrl, + TX_INACTIVE_STA_DROP); + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_24); + break; + + default: + ucActivedTspec = wmmHasActiveTspec( + aisGetWMMInfo(prAdapter, + prCurrentMsduInfo->ucBssIndex)); + + prTxQue = qmDetermineStaTxQueue( + prAdapter, prCurrentMsduInfo, + ucActivedTspec, &ucTC); + if (!prTxQue) { + DBGLOG(QM, INFO, + "Drop the Packet for TxQue is NULL\n"); + prTxQue = &rNotEnqueuedQue; + TX_INC_CNT(&prAdapter->rTxCtrl, + TX_INACTIVE_STA_DROP); + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_24); + } +#if ARP_MONITER_ENABLE + prStaRec = + QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, + prCurrentMsduInfo-> + ucStaRecIndex); + if (prStaRec && IS_STA_IN_AIS(prStaRec) && + prCurrentMsduInfo->eSrc == TX_PACKET_OS) + qmDetectArpNoResponse(prAdapter, + prCurrentMsduInfo); +#endif + break; /*default */ + } /* switch (prCurrentMsduInfo->ucStaRecIndex) */ + + if (prCurrentMsduInfo->eSrc == TX_PACKET_FORWARDING) { + DBGLOG(QM, TRACE, + "Forward Pkt to STA[%u] BSS[%u]\n", + prCurrentMsduInfo->ucStaRecIndex, + prCurrentMsduInfo->ucBssIndex); + + if (prTxQue->u4NumElem >= + prQM->u4MaxForwardBufferCount) { + DBGLOG(QM, INFO, + "Drop the Packet for full Tx queue (forwarding) Bss %u\n", + prCurrentMsduInfo->ucBssIndex); + prTxQue = &rNotEnqueuedQue; + TX_INC_CNT(&prAdapter->rTxCtrl, + TX_FORWARD_OVERFLOW_DROP); + } + } + + } else { + DBGLOG(QM, TRACE, + "Drop the Packet for inactive Bss %u\n", + prCurrentMsduInfo->ucBssIndex); + 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 */ + /* Note that the BSS Index and STA_REC index are determined in + * qmDetermineStaRecIndex(prCurrentMsduInfo). + */ + prCurrentMsduInfo->ucTC = ucTC; + + /* Check the Tx descriptor template is valid */ + qmSetTxPacketDescTemplate(prAdapter, prCurrentMsduInfo); + + /* Set Tx rate */ + switch (prAdapter->rWifiVar.ucDataTxRateMode) { + case DATA_RATE_MODE_BSS_LOWEST: + nicTxSetPktLowestFixedRate(prAdapter, + prCurrentMsduInfo); + break; + + case DATA_RATE_MODE_MANUAL: + prCurrentMsduInfo->u4FixedRateOption = + prAdapter->rWifiVar.u4DataTxRateCode; + + prCurrentMsduInfo->ucRateMode = + MSDU_RATE_MODE_MANUAL_DESC; + break; + + case DATA_RATE_MODE_AUTO: + default: + if (prCurrentMsduInfo->ucRateMode == + MSDU_RATE_MODE_LOWEST_RATE) + nicTxSetPktLowestFixedRate(prAdapter, + prCurrentMsduInfo); + break; + } + + /* 4 <4> Enqueue the packet */ + QUEUE_INSERT_TAIL(prTxQue, + (struct QUE_ENTRY *) prCurrentMsduInfo); + wlanFillTimestamp(prAdapter, prCurrentMsduInfo->prPacket, + PHASE_ENQ_QM); + /* + * Record how many packages enqueue + * to TX during statistic intervals + */ + if (prTxQue != &rNotEnqueuedQue) { + prQM->u4EnqueueCounter++; + /* how many page count this frame wanted */ + prQM->au4QmTcWantedPageCounter[ucTC] += + prCurrentMsduInfo->u4PageCount; + } +#if QM_TC_RESOURCE_EMPTY_COUNTER + if (prCurrentMsduInfo->u4PageCount > + prTxCtrl->rTc.au4FreePageCount[ucTC]) + prQM->au4QmTcResourceEmptyCounter[ + prCurrentMsduInfo->ucBssIndex][ucTC]++; +#endif + +#if QM_FAST_TC_RESOURCE_CTRL && QM_ADAPTIVE_TC_RESOURCE_CTRL + if (prTxQue != &rNotEnqueuedQue) { + /* Check and trigger fast TC resource + * adjustment for queued packets + */ + qmCheckForFastTcResourceCtrl(prAdapter, ucTC); + } +#endif + +#if QM_TEST_MODE + if (++prQM->u4PktCount == QM_TEST_TRIGGER_TX_COUNT) { + prQM->u4PktCount = 0; + qmTestCases(prAdapter); + } +#endif + } while (prNextMsduInfo); + + if (QUEUE_IS_NOT_EMPTY(&rNotEnqueuedQue)) { + QM_TX_SET_NEXT_MSDU_INFO((struct MSDU_INFO *) + QUEUE_GET_TAIL(&rNotEnqueuedQue), NULL); + prMsduInfoReleaseList = (struct MSDU_INFO *) QUEUE_GET_HEAD( + &rNotEnqueuedQue); + } +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + /* 4 Update TC resource control related variables */ + /* Keep track of the queue length */ + qmDoAdaptiveTcResourceCtrl(prAdapter); +#endif + + return prMsduInfoReleaseList; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Determine the STA_REC index for a packet + * + * \param[in] prMsduInfo Pointer to the packet + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void qmDetermineStaRecIndex(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + uint32_t i; + + struct STA_RECORD *prTempStaRec; + struct BSS_INFO *prBssInfo; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + prTempStaRec = NULL; + + ASSERT(prMsduInfo); + + DBGLOG(QM, LOUD, + "Msdu BSS Idx[%u] OpMode[%u] StaRecOfApExist[%u]\n", + prMsduInfo->ucBssIndex, prBssInfo->eCurrentOPMode, + prBssInfo->prStaRecOfAP ? TRUE : FALSE); + + switch (prBssInfo->eCurrentOPMode) { + case OP_MODE_IBSS: + case OP_MODE_ACCESS_POINT: + /* 4 <1> DA = BMCAST */ + if (IS_BMCAST_MAC_ADDR(prMsduInfo->aucEthDestAddr)) { + prMsduInfo->ucStaRecIndex = STA_REC_INDEX_BMCAST; + DBGLOG(QM, LOUD, "TX with DA = BMCAST\n"); + return; + } + break; + + /* Infra Client/GC */ + case OP_MODE_INFRASTRUCTURE: + case OP_MODE_BOW: + if (prBssInfo->prStaRecOfAP) { +#if CFG_SUPPORT_TDLS + + prTempStaRec = + cnmGetTdlsPeerByAddress(prAdapter, + prBssInfo->ucBssIndex, + prMsduInfo->aucEthDestAddr); + if (IS_DLS_STA(prTempStaRec) + && prTempStaRec->ucStaState == STA_STATE_3) { + if (g_arTdlsLink[prTempStaRec->ucTdlsIndex]) { + prMsduInfo->ucStaRecIndex = + prTempStaRec->ucIndex; + return; + } + } +#endif + /* 4 <2> Check if an AP STA is present */ + prTempStaRec = prBssInfo->prStaRecOfAP; + + DBGLOG(QM, LOUD, + "StaOfAp Idx[%u] WIDX[%u] Valid[%u] TxAllowed[%u] InUse[%u] Type[%u]\n", + prTempStaRec->ucIndex, + prTempStaRec->ucWlanIndex, + prTempStaRec->fgIsValid, + prTempStaRec->fgIsTxAllowed, + prTempStaRec->fgIsInUse, + prTempStaRec->eStaType); + + if (prTempStaRec->fgIsInUse) { + prMsduInfo->ucStaRecIndex = + prTempStaRec->ucIndex; + DBGLOG(QM, LOUD, "TX with AP_STA[%u]\n", + prTempStaRec->ucIndex); + return; + } + } + break; + + case OP_MODE_P2P_DEVICE: + break; + + default: + break; + } + + /* 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_STA_REC_NUM; i++) { + prTempStaRec = &(prAdapter->arStaRec[i]); + if (prTempStaRec->fgIsInUse) { + if (EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, + prMsduInfo->aucEthDestAddr)) { + prMsduInfo->ucStaRecIndex = + prTempStaRec->ucIndex; + DBGLOG(QM, LOUD, "TX with STA[%u]\n", + 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 = + (uint8_t) prQM->u4CurrentStaRecIndexToEnqueue; +#endif +} + +struct STA_RECORD *qmDetermineStaToBeDequeued( + IN struct ADAPTER *prAdapter, + IN uint32_t u4StartStaRecIndex) +{ + + return NULL; +} + +struct QUE *qmDequeueStaTxPackets(IN struct ADAPTER *prAdapter) +{ + + return NULL; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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) + */ +/*----------------------------------------------------------------------------*/ +uint32_t +qmDequeueTxPacketsFromPerStaQueues(IN struct ADAPTER *prAdapter, + OUT struct QUE *prQue, IN uint8_t ucTC, + IN uint32_t u4CurrentQuota, + IN uint32_t *prPleCurrentQuota, + IN uint32_t u4TotalQuota) +{ + uint32_t ucLoop; /* Loop for */ + + uint32_t u4CurStaIndex = 0; + uint32_t u4CurStaUsedResource = 0; + + /* The current focused STA */ + struct STA_RECORD *prStaRec; + /* The Bss for current focused STA */ + struct BSS_INFO *prBssInfo; + /* The current TX queue to dequeue */ + struct QUE *prCurrQueue; + /* The dequeued packet */ + struct MSDU_INFO *prDequeuedPkt; + + /* To remember the total forwarded packets for a STA */ + uint32_t u4CurStaForwardFrameCount; + /* The maximum number of packets a STA can forward */ + uint32_t u4MaxForwardFrameCountLimit; + uint32_t u4AvaliableResource; /* The TX resource amount */ + uint32_t u4MaxResourceLimit; + + u_int8_t fgEndThisRound; + struct QUE_MGT *prQM = &prAdapter->rQM; + + uint8_t *pucPsStaFreeQuota; +#if CFG_SUPPORT_SOFT_ACM + uint8_t ucAc; + u_int8_t fgAcmFlowCtrl = FALSE; + static const uint8_t aucTc2Ac[] = {ACI_BK, ACI_BE, ACI_VI, ACI_VO}; +#endif + + /* Sanity Check */ + if (!u4CurrentQuota) { + DBGLOG(TX, LOUD, + "(Fairness) Skip TC = %u u4CurrentQuota = %u\n", ucTC, + u4CurrentQuota); + prQM->au4DequeueNoTcResourceCounter[ucTC]++; + return u4CurrentQuota; + } + /* Check PLE resource */ + if (!(*prPleCurrentQuota)) + return u4CurrentQuota; + /* 4 <1> Assign init value */ + u4AvaliableResource = u4CurrentQuota; + u4MaxResourceLimit = u4TotalQuota; + +#if QM_FORWARDING_FAIRNESS + u4CurStaIndex = prQM->au4HeadStaRecIndex[ucTC]; + u4CurStaUsedResource = prQM->au4ResourceUsedCount[ucTC]; +#endif + + fgEndThisRound = FALSE; + ucLoop = 0; + u4CurStaForwardFrameCount = 0; + + DBGLOG(QM, TEMP, + "(Fairness) TC[%u] Init Head STA[%u] Resource[%u]\n", + ucTC, u4CurStaIndex, u4AvaliableResource); + + /* 4 <2> Traverse STA array from Head STA */ + /* From STA[x] to STA[x+1] to STA[x+2] to ... to STA[x] */ + while (ucLoop < CFG_STA_REC_NUM) { + prStaRec = &prAdapter->arStaRec[u4CurStaIndex]; + prCurrQueue = &prStaRec->arTxQueue[ucTC]; + + /* 4 <2.1> Find a Tx allowed STA */ + /* Only Data frame will be queued in */ + /* if (prStaRec->fgIsTxAllowed) { */ + if (QUEUE_IS_NOT_EMPTY(prCurrQueue)) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + /* prCurrQueue = &prStaRec->aprTxQueue[ucTC]; */ + prDequeuedPkt = NULL; + pucPsStaFreeQuota = NULL; + /* Set default forward count limit to unlimited */ + u4MaxForwardFrameCountLimit = + QM_STA_FORWARD_COUNT_UNLIMITED; + + /* 4 <2.2> Update forward frame/page count + * limit for this STA + */ + /* AP mode: STA in PS buffer handling */ + if (prStaRec->fgIsInPS) { + if (prStaRec->fgIsQoS && + prStaRec->fgIsUapsdSupported && + (prStaRec->ucBmpTriggerAC & + BIT(ucTC))) { + u4MaxForwardFrameCountLimit = + prStaRec-> + ucFreeQuotaForDelivery; + pucPsStaFreeQuota = + &prStaRec-> + ucFreeQuotaForDelivery; + } else { + u4MaxForwardFrameCountLimit = + prStaRec-> + ucFreeQuotaForNonDelivery; + pucPsStaFreeQuota = + &prStaRec-> + ucFreeQuotaForNonDelivery; + } + } + + /* fgIsInPS */ + /* Absent BSS handling */ + if (prBssInfo->fgIsNetAbsent) { + if (u4MaxForwardFrameCountLimit > + prBssInfo->ucBssFreeQuota) + u4MaxForwardFrameCountLimit = + prBssInfo->ucBssFreeQuota; + } +#if CFG_SUPPORT_DBDC + if (prAdapter->rWifiVar.fgDbDcModeEn) + u4MaxResourceLimit = + gmGetDequeueQuota(prAdapter, + prStaRec, prBssInfo, + u4TotalQuota); +#endif +#if CFG_SUPPORT_SOFT_ACM + if (ucTC <= TC3_INDEX && + prStaRec->afgAcmRequired[aucTc2Ac[ucTC]]) { + ucAc = aucTc2Ac[ucTC]; + DBGLOG(QM, TRACE, "AC %d Pending Pkts %u\n", + ucAc, prCurrQueue->u4NumElem); + /* Quick check remain medium time and pending + ** packets + */ + if (QUEUE_IS_EMPTY(prCurrQueue) || + !wmmAcmCanDequeue(prAdapter, ucAc, 0, + prBssInfo->ucBssIndex)) + goto skip_dequeue; + fgAcmFlowCtrl = TRUE; + } else + fgAcmFlowCtrl = FALSE; +#endif + /* 4 <2.3> Dequeue packet */ + /* Three cases to break: (1) No resource + * (2) No packets (3) Fairness + */ + while (!QUEUE_IS_EMPTY(prCurrQueue)) { + prDequeuedPkt = (struct MSDU_INFO *) + QUEUE_GET_HEAD(prCurrQueue); + + if ((u4CurStaForwardFrameCount >= + u4MaxForwardFrameCountLimit) || + (u4CurStaUsedResource >= + u4MaxResourceLimit)) { + /* Exceeds Limit */ + prQM-> + au4DequeueNoTcResourceCounter[ucTC]++; + break; + } else if (prDequeuedPkt->u4PageCount > + u4AvaliableResource) { + /* Available Resource is not enough */ + prQM-> + au4DequeueNoTcResourceCounter[ucTC]++; + if (!(prAdapter->rWifiVar. + ucAlwaysResetUsedRes & BIT(0))) + fgEndThisRound = TRUE; + break; + } else if ((*prPleCurrentQuota) < + NIX_TX_PLE_PAGE_CNT_PER_FRAME) { + if (!(prAdapter->rWifiVar. + ucAlwaysResetUsedRes & BIT(0))) + fgEndThisRound = TRUE; + break; + } else if (!prStaRec->fgIsValid) { + /* In roaming, if the sta_rec doesn't + * active by event 0x0C, it can't + * dequeue data. + */ + DBGLOG_LIMITED(QM, WARN, + "sta_rec is not valid\n"); + break; + } +#if CFG_SUPPORT_SOFT_ACM + if (fgAcmFlowCtrl) { + uint32_t u4PktTxTime = 0; + + u4PktTxTime = wmmCalculatePktUsedTime( + prBssInfo, prStaRec, + prDequeuedPkt->u2FrameLength - + ETH_HLEN); + if (!wmmAcmCanDequeue(prAdapter, ucAc, + u4PktTxTime, + prBssInfo->ucBssIndex)) + break; + } +#endif + /* Available to be Tx */ + + QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, + struct MSDU_INFO *); + + if (!QUEUE_IS_EMPTY(prCurrQueue)) { + /* XXX: check all queues for STA */ + prDequeuedPkt->ucPsForwardingType = + PS_FORWARDING_MORE_DATA_ENABLED; + } + /* to record WMM Set */ + prDequeuedPkt->ucWmmQueSet = + prBssInfo->ucWmmQueSet; + QUEUE_INSERT_TAIL(prQue, + (struct QUE_ENTRY *) + prDequeuedPkt); + prStaRec->u4DeqeueuCounter++; + prQM->u4DequeueCounter++; + + u4AvaliableResource -= + prDequeuedPkt->u4PageCount; + u4CurStaUsedResource += + prDequeuedPkt->u4PageCount; + u4CurStaForwardFrameCount++; + (*prPleCurrentQuota) -= + NIX_TX_PLE_PAGE_CNT_PER_FRAME; + } +#if CFG_SUPPORT_SOFT_ACM +skip_dequeue: +#endif + /* AP mode: Update STA in PS Free quota */ + if (prStaRec->fgIsInPS && pucPsStaFreeQuota) { + if ((*pucPsStaFreeQuota) >= + u4CurStaForwardFrameCount) + (*pucPsStaFreeQuota) -= + u4CurStaForwardFrameCount; + else + (*pucPsStaFreeQuota) = 0; + } + + if (prBssInfo->fgIsNetAbsent) { + if (prBssInfo->ucBssFreeQuota >= + u4CurStaForwardFrameCount) + prBssInfo->ucBssFreeQuota -= + u4CurStaForwardFrameCount; + else + prBssInfo->ucBssFreeQuota = 0; + } + } + + if (fgEndThisRound) { + /* End this round */ + break; + } + + /* Prepare for next STA */ + ucLoop++; + u4CurStaIndex++; + u4CurStaIndex %= CFG_STA_REC_NUM; + u4CurStaUsedResource = 0; + u4CurStaForwardFrameCount = 0; + } + + /* 4 <3> Store Head Sta information to QM */ + /* No need to count used resource if thers is only one STA */ + if ((prQM->u4TxAllowedStaCount == 1) || + (prAdapter->rWifiVar.ucAlwaysResetUsedRes & BIT(1))) + u4CurStaUsedResource = 0; + +#if QM_FORWARDING_FAIRNESS + prQM->au4HeadStaRecIndex[ucTC] = u4CurStaIndex; + prQM->au4ResourceUsedCount[ucTC] = u4CurStaUsedResource; +#endif + + DBGLOG(QM, TEMP, + "(Fairness) TC[%u] Scheduled Head STA[%u] Left Resource[%u]\n", + ucTC, u4CurStaIndex, u4AvaliableResource); + + return u4AvaliableResource; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 BMC_TC_INDEX) + * \param[in] ucMaxNum The maximum amount of available resource + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void +qmDequeueTxPacketsFromPerTypeQueues(IN struct ADAPTER *prAdapter, + OUT struct QUE *prQue, IN uint8_t ucTC, + IN uint32_t u4CurrentQuota, + IN uint32_t *prPleCurrentQuota, + IN uint32_t u4TotalQuota) +{ + uint32_t u4AvaliableResource, u4LeftResource; + uint32_t u4MaxResourceLimit; + uint32_t u4TotalUsedResource = 0; + struct QUE_MGT *prQM; + PFN_DEQUEUE_FUNCTION pfnDeQFunc[2]; + u_int8_t fgChangeDeQFunc = TRUE; + u_int8_t fgGlobalQueFirst = TRUE; + + DBGLOG(QM, TEMP, "Enter %s (TC = %d, quota = %u)\n", + __func__, ucTC, u4CurrentQuota); + + /* Broadcast/Multicast data packets */ + if (u4CurrentQuota == 0) + return; + /* Check PLE resource */ + if (!(*prPleCurrentQuota)) + return; + + prQM = &prAdapter->rQM; + + u4AvaliableResource = u4CurrentQuota; + u4MaxResourceLimit = u4TotalQuota; +#if QM_FORWARDING_FAIRNESS + u4TotalUsedResource = prQM->u4GlobalResourceUsedCount; + fgGlobalQueFirst = prQM->fgGlobalQFirst; +#endif + + /* Dequeue function selection */ + if (fgGlobalQueFirst) { + pfnDeQFunc[0] = qmDequeueTxPacketsFromGlobalQueue; + pfnDeQFunc[1] = qmDequeueTxPacketsFromPerStaQueues; + } else { + pfnDeQFunc[0] = qmDequeueTxPacketsFromPerStaQueues; + pfnDeQFunc[1] = qmDequeueTxPacketsFromGlobalQueue; + } + + /* 1st dequeue function */ + u4LeftResource = pfnDeQFunc[0](prAdapter, prQue, ucTC, + u4AvaliableResource, + prPleCurrentQuota, + (u4MaxResourceLimit - u4TotalUsedResource)); + + /* dequeue function comsumes no resource, change */ + if ((u4LeftResource >= u4AvaliableResource) && + (u4AvaliableResource >= + prAdapter->rTxCtrl.u4MaxPageCntPerFrame)) { + fgChangeDeQFunc = TRUE; + } else { + u4TotalUsedResource += + (u4AvaliableResource - u4LeftResource); + /* Used resource exceeds limit, change */ + if (u4TotalUsedResource >= u4MaxResourceLimit) + fgChangeDeQFunc = TRUE; + } + + if (fgChangeDeQFunc) { + fgGlobalQueFirst = !fgGlobalQueFirst; + u4TotalUsedResource = 0; + } + + /* 2nd dequeue function */ + u4LeftResource = pfnDeQFunc[1](prAdapter, prQue, ucTC, + u4LeftResource, prPleCurrentQuota, u4MaxResourceLimit); + +#if QM_FORWARDING_FAIRNESS + prQM->fgGlobalQFirst = fgGlobalQueFirst; + prQM->u4GlobalResourceUsedCount = u4TotalUsedResource; +#endif + +} /* qmDequeueTxPacketsFromPerTypeQueues */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Dequeue TX packets from a QM global Queue for a particular TC + * + * \param[out] prQue The queue to put the dequeued packets + * \param[in] ucTC The TC index(Shall always be BMC_TC_INDEX) + * \param[in] ucMaxNum The maximum amount of available resource + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +uint32_t +qmDequeueTxPacketsFromGlobalQueue(IN struct ADAPTER *prAdapter, + OUT struct QUE *prQue, + IN uint8_t ucTC, IN uint32_t u4CurrentQuota, + IN uint32_t *prPleCurrentQuota, + IN uint32_t u4TotalQuota) +{ + struct BSS_INFO *prBssInfo; + struct QUE *prCurrQueue; + uint32_t u4AvaliableResource; + struct MSDU_INFO *prDequeuedPkt; + struct MSDU_INFO *prBurstEndPkt; + struct QUE rMergeQue; + struct QUE *prMergeQue; + struct QUE_MGT *prQM; + + DBGLOG(QM, TEMP, "Enter %s (TC = %d, quota = %u)\n", + __func__, ucTC, u4CurrentQuota); + + /* Broadcast/Multicast data packets */ + if (u4CurrentQuota == 0) + return u4CurrentQuota; + /* Check PLE resource */ + if (!(*prPleCurrentQuota)) + return u4CurrentQuota; + + prQM = &prAdapter->rQM; + + /* 4 <1> Determine the queue */ + prCurrQueue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST]; + u4AvaliableResource = u4CurrentQuota; + prDequeuedPkt = NULL; + prBurstEndPkt = NULL; + + QUEUE_INITIALIZE(&rMergeQue); + prMergeQue = &rMergeQue; + + /* 4 <2> Dequeue packets */ + while (!QUEUE_IS_EMPTY(prCurrQueue)) { + prDequeuedPkt = (struct MSDU_INFO *) QUEUE_GET_HEAD( + prCurrQueue); + if (prDequeuedPkt->u4PageCount > u4AvaliableResource) + break; + if ((*prPleCurrentQuota) < NIX_TX_PLE_PAGE_CNT_PER_FRAME) + break; + + QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, + struct MSDU_INFO *); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prDequeuedPkt->ucBssIndex); + + if (IS_BSS_ACTIVE(prBssInfo)) { + if (!prBssInfo->fgIsNetAbsent) { + /* to record WMM Set */ + prDequeuedPkt->ucWmmQueSet = + prBssInfo->ucWmmQueSet; + QUEUE_INSERT_TAIL(prQue, + (struct QUE_ENTRY *) + prDequeuedPkt); + prBurstEndPkt = prDequeuedPkt; + prQM->u4DequeueCounter++; + u4AvaliableResource -= + prDequeuedPkt->u4PageCount; + (*prPleCurrentQuota) -= + NIX_TX_PLE_PAGE_CNT_PER_FRAME; + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_26); + } else { + QUEUE_INSERT_TAIL(prMergeQue, + (struct QUE_ENTRY *) + 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((struct MSDU_INFO *) + QUEUE_GET_TAIL(prCurrQueue), NULL); + } + + return u4AvaliableResource; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +struct MSDU_INFO *qmDequeueTxPackets(IN struct ADAPTER *prAdapter, + IN struct TX_TCQ_STATUS *prTcqStatus) +{ + int32_t i; + struct MSDU_INFO *prReturnedPacketListHead; + struct QUE rReturnedQue; + uint32_t u4MaxQuotaLimit; + uint32_t u4AvailableResourcePLE; + + DBGLOG(QM, TEMP, "Enter qmDequeueTxPackets\n"); + + QUEUE_INITIALIZE(&rReturnedQue); + + prReturnedPacketListHead = NULL; + + /* TC0 to TC3: AC0~AC3 (commands packets are not handled by QM) */ + for (i = TC3_INDEX; i >= TC0_INDEX; i--) { + DBGLOG(QM, TEMP, "Dequeue packets from Per-STA queue[%u]\n", i); + + /* If only one STA is Tx allowed, + * no need to restrict Max quota + */ + if (prAdapter->rWifiVar.u4MaxTxDeQLimit) + u4MaxQuotaLimit = prAdapter->rWifiVar.u4MaxTxDeQLimit; + else if (prAdapter->rQM.u4TxAllowedStaCount == 1) + u4MaxQuotaLimit = QM_STA_FORWARD_COUNT_UNLIMITED; + else + u4MaxQuotaLimit = + (uint32_t) prTcqStatus->au4MaxNumOfPage[i]; + + u4AvailableResourcePLE = nicTxResourceGetPleFreeCount( + prAdapter, i); + + if (i == BMC_TC_INDEX) + qmDequeueTxPacketsFromPerTypeQueues(prAdapter, + &rReturnedQue, (uint8_t)i, + prTcqStatus->au4FreePageCount[i], + &u4AvailableResourcePLE, + u4MaxQuotaLimit); + else + qmDequeueTxPacketsFromPerStaQueues(prAdapter, + &rReturnedQue, + (uint8_t)i, + prTcqStatus->au4FreePageCount[i], + &u4AvailableResourcePLE, + u4MaxQuotaLimit); + + /* The aggregate number of dequeued packets */ + DBGLOG(QM, TEMP, "DQA)[%u](%u)\n", i, + rReturnedQue.u4NumElem); + } + + if (QUEUE_IS_NOT_EMPTY(&rReturnedQue)) { + prReturnedPacketListHead = (struct MSDU_INFO *) + QUEUE_GET_HEAD(&rReturnedQue); + QM_TX_SET_NEXT_MSDU_INFO((struct MSDU_INFO *) + QUEUE_GET_TAIL(&rReturnedQue), NULL); + } + + return prReturnedPacketListHead; +} + +#if CFG_SUPPORT_MULTITHREAD +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +struct MSDU_INFO *qmDequeueTxPacketsMthread( + IN struct ADAPTER *prAdapter, + IN struct TX_TCQ_STATUS *prTcqStatus) +{ + + /* INT_32 i; */ + struct MSDU_INFO *prReturnedPacketListHead; + /* QUE_T rReturnedQue; */ + /* UINT_32 u4MaxQuotaLimit; */ + struct MSDU_INFO *prMsduInfo, *prNextMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + if (prAdapter->rQM.fgForceReassign) + qmDoAdaptiveTcResourceCtrl(prAdapter); +#endif + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + prReturnedPacketListHead = qmDequeueTxPackets(prAdapter, + prTcqStatus); + + /* require the resource first to prevent from unsync */ + prMsduInfo = prReturnedPacketListHead; + while (prMsduInfo) { + prNextMsduInfo = (struct MSDU_INFO *) QUEUE_GET_NEXT_ENTRY(( + struct QUE_ENTRY *) prMsduInfo); + nicTxAcquireResource(prAdapter, prMsduInfo->ucTC, + nicTxGetPageCount(prAdapter, prMsduInfo->u2FrameLength, + FALSE), FALSE); + prMsduInfo = prNextMsduInfo; + } + + if (prReturnedPacketListHead) + wlanTxProfilingTagMsdu(prAdapter, prReturnedPacketListHead, + TX_PROF_TAG_DRV_DEQUE); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + 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) + */ +/*----------------------------------------------------------------------------*/ +u_int8_t +qmAdjustTcQuotasMthread(IN struct ADAPTER *prAdapter, + OUT struct TX_TCQ_ADJUST *prTcqAdjust, + IN struct TX_TCQ_STATUS *prTcqStatus) +{ +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + uint32_t i; + struct QUE_MGT *prQM = &prAdapter->rQM; + + KAL_SPIN_LOCK_DECLARATION(); + + /* Must initialize */ + for (i = 0; i < QM_ACTIVE_TC_NUM; i++) + prTcqAdjust->ai4Variation[i] = 0; + + /* 4 <1> If TC resource is not just adjusted, exit directly */ + if (!prQM->fgTcResourcePostAnnealing) + return FALSE; + + /* 4 <2> Adjust TcqStatus according to + * the updated prQM->au4CurrentTcResource + */ + else { + int32_t i4TotalExtraQuota = 0; + int32_t ai4ExtraQuota[QM_ACTIVE_TC_NUM]; + u_int8_t fgResourceRedistributed = TRUE; + + /* Must initialize */ + for (i = 0; i < TC_NUM; i++) + prTcqAdjust->ai4Variation[i] = 0; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + /* Obtain the free-to-distribute resource */ + for (i = 0; i < QM_ACTIVE_TC_NUM; i++) { + ai4ExtraQuota[i] = + (int32_t) prTcqStatus->au4MaxNumOfBuffer[i] - + (int32_t) prQM->au4CurrentTcResource[i]; + + if (ai4ExtraQuota[i] > 0) { + /* The resource shall be reallocated + * to other TCs + */ + if (ai4ExtraQuota[i] > + prTcqStatus->au4FreeBufferCount[ + i]) { + ai4ExtraQuota[i] = + prTcqStatus-> + au4FreeBufferCount[i]; + fgResourceRedistributed = FALSE; + } + + i4TotalExtraQuota += ai4ExtraQuota[i]; + prTcqAdjust->ai4Variation[i] = + (-ai4ExtraQuota[i]); + } + } + + /* Distribute quotas to TCs which need extra resource + * according to prQM->au4CurrentTcResource + */ + for (i = 0; i < QM_ACTIVE_TC_NUM; i++) { + if (ai4ExtraQuota[i] < 0) { + if ((-ai4ExtraQuota[i]) > i4TotalExtraQuota) { + ai4ExtraQuota[i] = (-i4TotalExtraQuota); + fgResourceRedistributed = FALSE; + } + + i4TotalExtraQuota += ai4ExtraQuota[i]; + prTcqAdjust->ai4Variation[i] = + (-ai4ExtraQuota[i]); + } + } + + /* In case some TC is waiting for TX Done, + * continue to adjust TC quotas upon TX Done + */ + prQM->fgTcResourcePostAnnealing = (!fgResourceRedistributed); + + for (i = 0; i < TC_NUM; i++) { + prTcqStatus->au4FreePageCount[i] += + (prTcqAdjust->ai4Variation[i] * + prAdapter->rTxCtrl.u4MaxPageCntPerFrame); + prTcqStatus->au4MaxNumOfPage[i] += + (prTcqAdjust->ai4Variation[i] * + prAdapter->rTxCtrl.u4MaxPageCntPerFrame); + + prTcqStatus->au4FreeBufferCount[i] += + prTcqAdjust->ai4Variation[i]; + prTcqStatus->au4MaxNumOfBuffer[i] += + prTcqAdjust->ai4Variation[i]; + } + + + /* PLE */ + qmAdjustTcQuotaPle(prAdapter, prTcqAdjust, prTcqStatus); + + +#if QM_FAST_TC_RESOURCE_CTRL + prQM->fgTcResourceFastReaction = FALSE; +#endif + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + } + + return TRUE; +#else + return FALSE; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Adjust the TC PLE 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 qmAdjustTcQuotaPle(IN struct ADAPTER *prAdapter, + OUT struct TX_TCQ_ADJUST *prTcqAdjust, + IN struct TX_TCQ_STATUS *prTcqStatus) +{ + uint8_t i; + int32_t i4pages; + struct TX_CTRL *prTxCtrl; + struct TX_TCQ_STATUS *prTc; + int32_t i4TotalExtraQuota = 0; + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + prTc = &prTxCtrl->rTc; + + /* no PLE resource control */ + if (!prTc->fgNeedPleCtrl) + return; + + /* collect free PLE resource */ + for (i = TC0_INDEX; i < TC_NUM; i++) { + + if (!nicTxResourceIsPleCtrlNeeded(prAdapter, i)) + continue; + + /* adjust ple resource */ + i4pages = prTcqAdjust->ai4Variation[i] * + NIX_TX_PLE_PAGE_CNT_PER_FRAME; + + if (i4pages < 0) { + /* donate resource to other TC */ + if (prTcqStatus->au4FreePageCount_PLE[i] < (-i4pages)) { + /* not enough to give */ + i4pages = + -(prTcqStatus->au4FreePageCount_PLE[i]); + } + i4TotalExtraQuota += -i4pages; + + prTcqStatus->au4FreePageCount_PLE[i] += i4pages; + prTcqStatus->au4MaxNumOfPage_PLE[i] += i4pages; + + prTcqStatus->au4FreeBufferCount_PLE[i] += + (i4pages / NIX_TX_PLE_PAGE_CNT_PER_FRAME); + prTcqStatus->au4MaxNumOfBuffer_PLE[i] += + (i4pages / NIX_TX_PLE_PAGE_CNT_PER_FRAME); + } + } + + /* distribute PLE resource */ + for (i = TC0_INDEX; i < TC_NUM; i++) { + if (!nicTxResourceIsPleCtrlNeeded(prAdapter, i)) + continue; + + /* adjust ple resource */ + i4pages = prTcqAdjust->ai4Variation[i] * + NIX_TX_PLE_PAGE_CNT_PER_FRAME; + + if (i4pages > 0) { + if (i4TotalExtraQuota >= i4pages) { + i4TotalExtraQuota -= i4pages; + } else { + i4pages = i4TotalExtraQuota; + i4TotalExtraQuota = 0; + } + prTcqStatus->au4FreePageCount_PLE[i] += i4pages; + prTcqStatus->au4MaxNumOfPage_PLE[i] += i4pages; + + prTcqStatus->au4FreeBufferCount_PLE[i] = + (prTcqStatus->au4FreePageCount_PLE[i] / + NIX_TX_PLE_PAGE_CNT_PER_FRAME); + prTcqStatus->au4MaxNumOfBuffer_PLE[i] = + (prTcqStatus->au4MaxNumOfBuffer_PLE[i] / + NIX_TX_PLE_PAGE_CNT_PER_FRAME); + } + } + + /* distribute remaining PLE resource */ + while (i4TotalExtraQuota != 0) { + DBGLOG(QM, INFO, + "distribute remaining PLE resource[%u]\n", + i4TotalExtraQuota); + for (i = TC0_INDEX; i < TC_NUM; i++) { + if (!nicTxResourceIsPleCtrlNeeded(prAdapter, i)) + continue; + + if (i4TotalExtraQuota >= + NIX_TX_PLE_PAGE_CNT_PER_FRAME) { + prTcqStatus->au4FreePageCount_PLE[i] += + NIX_TX_PLE_PAGE_CNT_PER_FRAME; + prTcqStatus->au4MaxNumOfPage_PLE[i] += + NIX_TX_PLE_PAGE_CNT_PER_FRAME; + + prTcqStatus->au4FreeBufferCount_PLE[i] += 1; + prTcqStatus->au4MaxNumOfBuffer_PLE[i] += 1; + + i4TotalExtraQuota -= + NIX_TX_PLE_PAGE_CNT_PER_FRAME; + } else { + /* remaining PLE pages are + * not enough for a package + */ + prTcqStatus->au4FreePageCount_PLE[i] += + i4TotalExtraQuota; + prTcqStatus->au4MaxNumOfPage_PLE[i] += + i4TotalExtraQuota; + + prTcqStatus->au4FreeBufferCount_PLE[i] = + (prTcqStatus->au4FreePageCount_PLE[i] / + NIX_TX_PLE_PAGE_CNT_PER_FRAME); + prTcqStatus->au4MaxNumOfBuffer_PLE[i] = + (prTcqStatus->au4MaxNumOfPage_PLE[i] / + NIX_TX_PLE_PAGE_CNT_PER_FRAME); + + i4TotalExtraQuota = 0; + } + } + } + +} + +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \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) + */ +/*----------------------------------------------------------------------------*/ +u_int8_t qmAdjustTcQuotas(IN struct ADAPTER *prAdapter, + OUT struct TX_TCQ_ADJUST *prTcqAdjust, + IN struct TX_TCQ_STATUS *prTcqStatus) +{ +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + uint32_t i; + struct QUE_MGT *prQM = &prAdapter->rQM; + + /* Must initialize */ + for (i = 0; i < QM_ACTIVE_TC_NUM; i++) + prTcqAdjust->ai4Variation[i] = 0; + + /* 4 <1> If TC resource is not just adjusted, exit directly */ + if (!prQM->fgTcResourcePostAnnealing) + return FALSE; + /* 4 <2> Adjust TcqStatus according to + * the updated prQM->au4CurrentTcResource + */ + else { + int32_t i4TotalExtraQuota = 0; + int32_t ai4ExtraQuota[QM_ACTIVE_TC_NUM]; + u_int8_t fgResourceRedistributed = TRUE; + + /* Obtain the free-to-distribute resource */ + for (i = 0; i < QM_ACTIVE_TC_NUM; i++) { + ai4ExtraQuota[i] = + (int32_t) prTcqStatus->au4MaxNumOfBuffer[i] - + (int32_t) prQM->au4CurrentTcResource[i]; + + if (ai4ExtraQuota[i] > 0) { + /* The resource shall be + * reallocated to other TCs + */ + if (ai4ExtraQuota[i] > + prTcqStatus->au4FreeBufferCount[i]) { + ai4ExtraQuota[i] = + prTcqStatus-> + au4FreeBufferCount[i]; + fgResourceRedistributed = FALSE; + } + + i4TotalExtraQuota += ai4ExtraQuota[i]; + prTcqAdjust->ai4Variation[i] = + (-ai4ExtraQuota[i]); + } + } + + /* Distribute quotas to TCs which need extra resource + * according to prQM->au4CurrentTcResource + */ + for (i = 0; i < QM_ACTIVE_TC_NUM; i++) { + if (ai4ExtraQuota[i] < 0) { + if ((-ai4ExtraQuota[i]) > i4TotalExtraQuota) { + ai4ExtraQuota[i] = (-i4TotalExtraQuota); + fgResourceRedistributed = FALSE; + } + + i4TotalExtraQuota += ai4ExtraQuota[i]; + prTcqAdjust->ai4Variation[i] = + (-ai4ExtraQuota[i]); + } + } + + /* In case some TC is waiting for TX Done, + * continue to adjust TC quotas upon TX Done + */ + prQM->fgTcResourcePostAnnealing = (!fgResourceRedistributed); + +#if QM_FAST_TC_RESOURCE_CTRL + prQM->fgTcResourceFastReaction = FALSE; +#endif + +#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->au4FreeBufferCount[0], + prTcqStatus->au4FreeBufferCount[1], + prTcqStatus->au4FreeBufferCount[2], + prTcqStatus->au4FreeBufferCount[3], + prTcqStatus->au4FreeBufferCount[4], + prTcqStatus->au4FreeBufferCount[5]); +#endif + } + + return TRUE; +#else + return FALSE; +#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 struct ADAPTER *prAdapter) +{ + int32_t u4CurrQueLen, u4Tc, u4StaRecIdx; + struct STA_RECORD *prStaRec; + struct QUE_MGT *prQM = &prAdapter->rQM; + struct BSS_INFO *prBssInfo; + + /* 4 <1> Update the queue lengths for TC0 to TC3 (skip TC4) and TC5 */ + for (u4Tc = 0; u4Tc < QM_ACTIVE_TC_NUM; u4Tc++) { + u4CurrQueLen = 0; + + /* Calculate per-STA queue length */ + if (u4Tc < NUM_OF_PER_STA_TX_QUEUES) { + for (u4StaRecIdx = 0; u4StaRecIdx < CFG_STA_REC_NUM; + u4StaRecIdx++) { + prStaRec = cnmGetStaRecByIndex(prAdapter, + u4StaRecIdx); + if (prStaRec) { + prBssInfo = GET_BSS_INFO_BY_INDEX( + prAdapter, + prStaRec->ucBssIndex); + + /* If the STA is activated, + * get the queue length + */ + if ((prStaRec->fgIsValid) && + (!prBssInfo->fgIsNetAbsent)) + u4CurrQueLen += + (prStaRec-> + arTxQueue[u4Tc]. + u4NumElem); + } + } + } + + if (u4Tc == BMC_TC_INDEX) { + /* Update the queue length for (BMCAST) */ + u4CurrQueLen += prQM->arTxQueue[ + TX_QUEUE_INDEX_BMCAST].u4NumElem; + } + + if (prQM->au4AverageQueLen[u4Tc] == 0) { + prQM->au4AverageQueLen[u4Tc] = (u4CurrQueLen << + prQM->u4QueLenMovingAverage); + } else { + prQM->au4AverageQueLen[u4Tc] -= + (prQM->au4AverageQueLen[u4Tc] >> + prQM->u4QueLenMovingAverage); + prQM->au4AverageQueLen[u4Tc] += (u4CurrQueLen); + } + } +#if 0 + /* Update the queue length for TC5 (BMCAST) */ + u4CurrQueLen = + prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST].u4NumElem; + + if (prQM->au4AverageQueLen[TC5_INDEX] == 0) { + prQM->au4AverageQueLen[TC5_INDEX] = (u4CurrQueLen << + QM_QUE_LEN_MOVING_AVE_FACTOR); + } else { + prQM->au4AverageQueLen[TC5_INDEX] -= + (prQM->au4AverageQueLen[TC5_INDEX] >> + QM_QUE_LEN_MOVING_AVE_FACTOR); + prQM->au4AverageQueLen[TC5_INDEX] += (u4CurrQueLen); + } +#endif +} + +void qmAllocateResidualTcResource(IN struct ADAPTER *prAdapter, + IN int32_t *ai4TcResDemand, + IN uint32_t *pu4ResidualResource, + IN uint32_t *pu4ShareCount) +{ + struct QUE_MGT *prQM = &prAdapter->rQM; + uint32_t u4Share = 0; + uint32_t u4TcIdx; + uint8_t ucIdx; + uint32_t au4AdjTc[] = { TC3_INDEX, TC2_INDEX, TC1_INDEX, TC0_INDEX }; + uint32_t u4AdjTcSize = (sizeof(au4AdjTc) / sizeof(uint32_t)); + uint32_t u4ResidualResource = *pu4ResidualResource; + uint32_t u4ShareCount = *pu4ShareCount; + + /* If there is no resource left, exit directly */ + if (u4ResidualResource == 0) + return; + + /* This shall not happen */ + if (u4ShareCount == 0) { + prQM->au4CurrentTcResource[TC1_INDEX] += u4ResidualResource; + DBGLOG(QM, ERROR, "QM: (Error) u4ShareCount = 0\n"); + return; + } + + /* Share the residual resource evenly */ + u4Share = (u4ResidualResource / u4ShareCount); + if (u4Share) { + for (u4TcIdx = 0; u4TcIdx < QM_ACTIVE_TC_NUM; u4TcIdx++) { + /* Skip TC4 (not adjustable) */ + if (u4TcIdx == TC4_INDEX) + continue; + + if (ai4TcResDemand[u4TcIdx] > 0) { + if (ai4TcResDemand[u4TcIdx] > u4Share) { + prQM->au4CurrentTcResource[u4TcIdx] += + u4Share; + u4ResidualResource -= u4Share; + ai4TcResDemand[u4TcIdx] -= u4Share; + } else { + prQM->au4CurrentTcResource[u4TcIdx] += + ai4TcResDemand[u4TcIdx]; + u4ResidualResource -= + ai4TcResDemand[u4TcIdx]; + ai4TcResDemand[u4TcIdx] = 0; + } + } + } + } + + /* By priority, allocate the left resource + * that is not divisible by u4Share + */ + ucIdx = 0; + while (u4ResidualResource) { + u4TcIdx = au4AdjTc[ucIdx]; + + if (ai4TcResDemand[u4TcIdx]) { + prQM->au4CurrentTcResource[u4TcIdx]++; + u4ResidualResource--; + ai4TcResDemand[u4TcIdx]--; + + if (ai4TcResDemand[u4TcIdx] == 0) + u4ShareCount--; + } + + if (u4ShareCount <= 0) + break; + + ucIdx++; + ucIdx %= u4AdjTcSize; + } + + /* Allocate the left resource */ + prQM->au4CurrentTcResource[TC3_INDEX] += u4ResidualResource; + + *pu4ResidualResource = u4ResidualResource; + *pu4ShareCount = u4ShareCount; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Assign TX resource for each TC according to TX queue length and + * current assignment + * + * \param (none) + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void qmReassignTcResource(IN struct ADAPTER *prAdapter) +{ + int32_t i4TotalResourceDemand = 0; + uint32_t u4ResidualResource = 0; + uint32_t u4TcIdx; + int32_t ai4TcResDemand[QM_ACTIVE_TC_NUM]; + uint32_t u4ShareCount = 0; + uint32_t u4Share = 0; + struct QUE_MGT *prQM = &prAdapter->rQM; + uint32_t u4ActiveTcCount = 0; + uint32_t u4LastActiveTcIdx = TC3_INDEX; + + /* 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 (u4TcIdx = 0; u4TcIdx < QM_ACTIVE_TC_NUM; u4TcIdx++) { + /* Skip TC4, which is not adjustable */ + if (u4TcIdx == TC4_INDEX) + continue; + + /* Define: extra_demand = que_length + + * min_reserved_quota - current_quota + */ + ai4TcResDemand[u4TcIdx] = ((int32_t)(QM_GET_TX_QUEUE_LEN( + prAdapter, u4TcIdx) + + prQM->au4MinReservedTcResource[u4TcIdx]) - + (int32_t)prQM->au4CurrentTcResource[u4TcIdx]); + + /* If there are queued packets, allocate extra resource + * for the TC (for TCP consideration) + */ + if (QM_GET_TX_QUEUE_LEN(prAdapter, u4TcIdx)) { + ai4TcResDemand[u4TcIdx] += + prQM->u4ExtraReservedTcResource; + u4ActiveTcCount++; + } + + i4TotalResourceDemand += ai4TcResDemand[u4TcIdx]; + } + + /* 4 <2> Case 1: Demand <= Total Resource */ + if (i4TotalResourceDemand <= 0) { + + /* 4 <2.1> Calculate the residual resource evenly */ + /* excluding TC4 */ + if (u4ActiveTcCount == 0) + u4ShareCount = (QM_ACTIVE_TC_NUM - 1); + else + u4ShareCount = u4ActiveTcCount; + + u4ResidualResource = (uint32_t) (-i4TotalResourceDemand); + u4Share = (u4ResidualResource / u4ShareCount); + + /* 4 <2.2> Satisfy every TC and share + * the residual resource evenly + */ + for (u4TcIdx = 0; u4TcIdx < QM_ACTIVE_TC_NUM; u4TcIdx++) { + /* Skip TC4 (not adjustable) */ + if (u4TcIdx == TC4_INDEX) + continue; + + prQM->au4CurrentTcResource[u4TcIdx] += + ai4TcResDemand[u4TcIdx]; + + /* Every TC is fully satisfied */ + ai4TcResDemand[u4TcIdx] = 0; + + /* The left resource will be allocated */ + if (QM_GET_TX_QUEUE_LEN(prAdapter, u4TcIdx) || + (u4ActiveTcCount == 0)) { + prQM->au4CurrentTcResource[u4TcIdx] += u4Share; + u4ResidualResource -= u4Share; + u4LastActiveTcIdx = u4TcIdx; + } + } + + /* 4 <2.3> Allocate the left resource to last active TC */ + prQM->au4CurrentTcResource[u4LastActiveTcIdx] += + (u4ResidualResource); + + } + /* 4 <3> Case 2: Demand > Total Resource --> Guarantee + * a minimum amount of resource for each TC + */ + else { + u4ShareCount = 0; + u4ResidualResource = prQM->u4ResidualTcResource; + + /* 4 <3.1> Allocated resouce amount = minimum + * of (guaranteed, total demand) + */ + for (u4TcIdx = 0; u4TcIdx < QM_ACTIVE_TC_NUM; u4TcIdx++) { + /* Skip TC4 (not adjustable) */ + if (u4TcIdx == TC4_INDEX) + continue; + + /* The demand can be fulfilled with + * the guaranteed resource amount + */ + if ((prQM->au4CurrentTcResource[u4TcIdx] + + ai4TcResDemand[u4TcIdx]) <= + prQM->au4GuaranteedTcResource[u4TcIdx]) { + + prQM->au4CurrentTcResource[u4TcIdx] += + ai4TcResDemand[u4TcIdx]; + u4ResidualResource += + (prQM->au4GuaranteedTcResource[u4TcIdx] + - prQM->au4CurrentTcResource[u4TcIdx]); + ai4TcResDemand[u4TcIdx] = 0; + } + + /* The demand can not be fulfilled with + * the guaranteed resource amount + */ + else { + ai4TcResDemand[u4TcIdx] -= + (prQM->au4GuaranteedTcResource[u4TcIdx] + - prQM->au4CurrentTcResource[u4TcIdx]); + + prQM->au4CurrentTcResource[u4TcIdx] = + prQM->au4GuaranteedTcResource[u4TcIdx]; + u4ShareCount++; + } + } + + /* 4 <3.2> Allocate the residual resource */ + qmAllocateResidualTcResource(prAdapter, ai4TcResDemand, + &u4ResidualResource, &u4ShareCount); + } + + prQM->fgTcResourcePostAnnealing = TRUE; + +#if QM_PRINT_TC_RESOURCE_CTRL + /* Debug print */ + DBGLOG(QM, INFO, + "QM: TC Rsc adjust to [%03u:%03u:%03u:%03u:%03u:%03u]\n", + prQM->au4CurrentTcResource[0], + prQM->au4CurrentTcResource[1], + prQM->au4CurrentTcResource[2], + prQM->au4CurrentTcResource[3], + prQM->au4CurrentTcResource[4], + prQM->au4CurrentTcResource[5]); +#endif + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Adjust TX resource for each TC according to TX queue length and + * current assignment + * + * \param (none) + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void qmDoAdaptiveTcResourceCtrl(IN struct ADAPTER *prAdapter) +{ + struct QUE_MGT *prQM = &prAdapter->rQM; + + if (prQM->fgForceReassign) { + prQM->u4TimeToUpdateQueLen = 1; + prQM->u4TimeToAdjustTcResource = 1; + prQM->fgTcResourceFastReaction = TRUE; + + prQM->fgForceReassign = FALSE; + } + + /* 4 <0> Check to update queue length or not */ + if (--prQM->u4TimeToUpdateQueLen) + return; + /* 4 <1> Update TC queue length */ + prQM->u4TimeToUpdateQueLen = QM_INIT_TIME_TO_UPDATE_QUE_LEN; + qmUpdateAverageTxQueLen(prAdapter); + + /* 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); +#if QM_FAST_TC_RESOURCE_CTRL + if (prQM->fgTcResourceFastReaction) { + prQM->fgTcResourceFastReaction = FALSE; + nicTxAdjustTcq(prAdapter); + } +#endif + } + } + + /* Debug */ +#if QM_PRINT_TC_RESOURCE_CTRL + do { + uint32_t u4Tc; + + for (u4Tc = 0; u4Tc < QM_ACTIVE_TC_NUM; u4Tc++) { + if (QM_GET_TX_QUEUE_LEN(prAdapter, u4Tc) >= 100) { + log_dbg(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; + } + } + } while (FALSE); +#endif + +} + +#if QM_FAST_TC_RESOURCE_CTRL +void qmCheckForFastTcResourceCtrl(IN struct ADAPTER *prAdapter, + IN uint8_t ucTc) +{ + struct QUE_MGT *prQM = &prAdapter->rQM; + u_int8_t fgTrigger = FALSE; + + if (!prAdapter->rTxCtrl.rTc.au4FreeBufferCount[ucTc] + || ((prAdapter->rTxCtrl.rTc.fgNeedPleCtrl) && + (!prAdapter->rTxCtrl.rTc.au4FreeBufferCount_PLE[ucTc]))) { + if (!prQM->au4CurrentTcResource[ucTc] || + nicTxGetAdjustableResourceCnt(prAdapter)) + fgTrigger = TRUE; + } + + /* Trigger TC resource adjustment + * if there is a requirement coming for a empty TC + */ + if (fgTrigger) { + prQM->fgForceReassign = TRUE; + + DBGLOG(QM, LOUD, + "Trigger TC Resource adjustment for TC[%u]\n", ucTc); + } +} +#endif + +#endif + +uint32_t gmGetDequeueQuota( + IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct BSS_INFO *prBssInfo, + IN uint32_t u4TotalQuota +) +{ + uint32_t u4Weight = 100; + uint32_t u4Quota; + + struct QUE_MGT *prQM = &prAdapter->rQM; + + /* Only apply to SDIO, PCIE/AXI use HW DMA */ + if ((prAdapter->rWifiVar.uDeQuePercentEnable == FALSE) || + (prQM->fgIsTxResrouceControlEn == FALSE)) + return u4TotalQuota; + + if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_VHT) { + if (prBssInfo->ucVhtChannelWidth > + VHT_OP_CHANNEL_WIDTH_20_40) { + /* BW80 NSS1 rate: MCS9 433 Mbps */ + u4Weight = prAdapter->rWifiVar.u4DeQuePercentVHT80Nss1; + } else if (prBssInfo->eBssSCO != CHNL_EXT_SCN) { + /* BW40 NSS1 Max rate: 200 Mbps */ + u4Weight = prAdapter->rWifiVar.u4DeQuePercentVHT40Nss1; + } else { + /* BW20 NSS1 Max rate: 72.2Mbps (MCS8 86.7Mbps) */ + u4Weight = prAdapter->rWifiVar.u4DeQuePercentVHT20Nss1; + } + } else if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_HT) { + if (prBssInfo->ucHtOpInfo1 & HT_OP_INFO1_STA_CHNL_WIDTH) { + /* BW40 NSS1 Max rate: 150 Mbps (MCS9 200Mbps)*/ + u4Weight = prAdapter->rWifiVar.u4DeQuePercentHT40Nss1; + } else { + /* BW20 NSS1 Max rate: 72.2Mbps (MCS8 86.7Mbps)*/ + u4Weight = prAdapter->rWifiVar.u4DeQuePercentHT20Nss1; + } + } +#if (CFG_SUPPORT_802_11AX == 1) + else if (fgEfuseCtrlAxOn == 1) { + if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_HE) + ;/* TBD */ + } +#endif + + u4Quota = u4TotalQuota * u4Weight / 100; + + if (u4Quota > u4TotalQuota || u4Quota <= 0) + return u4TotalQuota; + + return u4Quota; +} + +/*----------------------------------------------------------------------------*/ +/* RX-Related Queue Management */ +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +/*! + * \brief Init Queue Management for RX + * + * \param[in] (none) + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void qmInitRxQueues(IN struct ADAPTER *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 + */ +/*----------------------------------------------------------------------------*/ +struct SW_RFB *qmHandleRxPackets(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfbListHead) +{ + +#if CFG_RX_REORDERING_ENABLED + struct SW_RFB *prCurrSwRfb; + struct SW_RFB *prNextSwRfb; + void *prRxStatus; + struct QUE rReturnedQue; + struct QUE *prReturnedQue; + uint8_t *pucEthDestAddr; + u_int8_t fgIsBMC, fgIsHTran; + u_int8_t fgMicErr; +#if CFG_SUPPORT_REPLAY_DETECTION + u_int8_t ucBssIndexRly = 0; + struct BSS_INFO *prBssInfoRly = NULL; +#endif + + DEBUGFUNC("qmHandleRxPackets"); + + ASSERT(prSwRfbListHead); + + prReturnedQue = &rReturnedQue; + + QUEUE_INITIALIZE(prReturnedQue); + prNextSwRfb = prSwRfbListHead; + + do { + prCurrSwRfb = prNextSwRfb; + prNextSwRfb = QM_RX_GET_NEXT_SW_RFB(prCurrSwRfb); + + prRxStatus = prCurrSwRfb->prRxStatus; + if (prCurrSwRfb->u2RxByteCount > CFG_RX_MAX_PKT_SIZE) { + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) prCurrSwRfb); + DBGLOG(QM, ERROR, + "Drop packet when packet length is larger than CFG_RX_MAX_PKT_SIZE. Packet length=%d\n", + prCurrSwRfb->u2RxByteCount); + continue; + } + /* 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)) { + log_dbg(SW4, INFO, + "QM RX DATA: net _u sta idx %u wlan idx %u", + prCurrSwRfb->ucStaRecIdx, + prCurrSwRfb->ucWlanIdx); + log_dbg(SW4, INFO, + " ssn _u tid %u ptype %u 11 %u\n", + prCurrSwRfb->ucTid, + prCurrSwRfb->ucPacketType, + prCurrSwRfb->fgReorderBuffer); + + DBGLOG_MEM8(SW4, TRACE, + (uint8_t *) prCurrSwRfb->pvHeader, + prCurrSwRfb->u2PacketLen); + } +#endif + + fgIsBMC = (prCurrSwRfb->fgIsBC | prCurrSwRfb->fgIsMC); + fgIsHTran = FALSE; + if (prCurrSwRfb->fgHdrTran) { + /* (!HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)){ */ + + uint8_t ucBssIndex; + struct BSS_INFO *prBssInfo; + uint8_t aucTaAddr[MAC_ADDR_LEN]; + + fgIsHTran = TRUE; + pucEthDestAddr = prCurrSwRfb->pvHeader; + if (prCurrSwRfb->prRxStatusGroup4 == NULL) { + DBGLOG(QM, ERROR, + "H/W did Header Trans but prRxStatusGroup4 is NULL !!!\n"); + DBGLOG_MEM8(QM, ERROR, prCurrSwRfb->pucRecvBuff, + prCurrSwRfb->u2RxByteCount); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) + prCurrSwRfb); + DBGLOG(RX, WARN, + "rxStatusGroup4 for data packet is NULL, drop this packet, and dump RXD and Packet\n"); + DBGLOG_MEM8(RX, WARN, (uint8_t *) prRxStatus, + sizeof(*prRxStatus)); + if (prCurrSwRfb->pvHeader) + DBGLOG_MEM8(RX, WARN, + prCurrSwRfb->pvHeader, + prCurrSwRfb->u2PacketLen > + 32 ? 32 : + prCurrSwRfb->u2PacketLen); +#if 0 + glSetRstReason(RST_GROUP4_NULL); + GL_RESET_TRIGGER(prAdapter, + RST_FLAG_DO_CORE_DUMP); +#endif + continue; + } + + if (prCurrSwRfb->prStaRec == NULL) { + /* Workaround WTBL Issue */ + HAL_RX_STATUS_GET_TA( + prCurrSwRfb->prRxStatusGroup4, + aucTaAddr); + prCurrSwRfb->ucStaRecIdx = + secLookupStaRecIndexFromTA( + prAdapter, aucTaAddr); + if (prCurrSwRfb->ucStaRecIdx < + CFG_STA_REC_NUM) { + prCurrSwRfb->prStaRec = + cnmGetStaRecByIndex(prAdapter, + prCurrSwRfb-> + ucStaRecIdx); +#define __STR_FMT__ \ + "Re-search the staRec = %d, mac = " MACSTR ", byteCnt= %d\n" + log_dbg(QM, TRACE, + __STR_FMT__, + prCurrSwRfb->ucStaRecIdx, + MAC2STR(aucTaAddr), + prCurrSwRfb->u2RxByteCount); +#undef __STR_FMT__ + } + + if (prCurrSwRfb->prStaRec == NULL) { + DBGLOG(QM, TRACE, + "Mark NULL the Packet for no STA_REC, wlanIdx=%d\n", + prCurrSwRfb->ucWlanIdx); + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_NO_STA_DROP_COUNT); + prCurrSwRfb->eDst = + RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) + prCurrSwRfb); + continue; + } + + prCurrSwRfb->ucWlanIdx = + prCurrSwRfb->prStaRec->ucWlanIndex; + GLUE_SET_PKT_BSS_IDX(prCurrSwRfb->pvPacket, + secGetBssIdxByWlanIdx(prAdapter, + prCurrSwRfb->ucWlanIdx)); + } + + ucBssIndex = prCurrSwRfb->prStaRec->ucBssIndex; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex); + + if (!IS_BSS_ACTIVE(prBssInfo)) { + log_dbg(QM, TRACE, "Mark NULL the Packet for inactive Bss %u\n", + ucBssIndex); + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_INACTIVE_BSS_DROP_COUNT); + prCurrSwRfb->eDst = + RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) + prCurrSwRfb); + continue; + } + + if (prBssInfo->eCurrentOPMode == + OP_MODE_ACCESS_POINT) { + if (IS_BMCAST_MAC_ADDR( + pucEthDestAddr)) { + prCurrSwRfb->eDst = + RX_PKT_DESTINATION_HOST_WITH_FORWARD; + } else if ( + secLookupStaRecIndexFromTA( + prAdapter, + pucEthDestAddr) + != + STA_REC_INDEX_NOT_FOUND) { + + prCurrSwRfb->eDst = + RX_PKT_DESTINATION_FORWARD; + } + } +#if CFG_SUPPORT_PASSPOINT + else if (hs20IsFrameFilterEnabled(prAdapter, + prBssInfo) && + hs20IsUnsecuredFrame(prAdapter, + prBssInfo, + prCurrSwRfb)) { + DBGLOG(QM, WARN, + "Mark NULL the Packet for Dropped Packet %u\n", + ucBssIndex); + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_HS20_DROP_COUNT); + prCurrSwRfb->eDst = + RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) + prCurrSwRfb); + continue; + } +#endif /* CFG_SUPPORT_PASSPOINT */ + } else { + uint16_t u2FrameCtrl = 0; + struct WLAN_MAC_HEADER *prWlanHeader = NULL; + struct BSS_INFO *prAisBssInfo = NULL; + + prAisBssInfo = aisGetAisBssInfo(prAdapter, + secGetBssIdxByWlanIdx( + prAdapter, + prCurrSwRfb->ucWlanIdx)); + prWlanHeader = (struct WLAN_MAC_HEADER *) + prCurrSwRfb->pvHeader; + u2FrameCtrl = prWlanHeader->u2FrameCtrl; + prCurrSwRfb->u2SequenceControl = + prWlanHeader->u2SeqCtrl; + if (prCurrSwRfb->prStaRec == NULL && + RXM_IS_DATA_FRAME(u2FrameCtrl) && + (prAisBssInfo) && + (prAisBssInfo->eConnectionState == + MEDIA_STATE_CONNECTED)) { + /* rx header translation */ + log_dbg(QM, WARN, "RXD Trans: FrameCtrl=0x%02x GVLD=0x%x, StaRecIdx=%d, WlanIdx=%d PktLen=%d\n", + u2FrameCtrl, prCurrSwRfb->ucGroupVLD, + prCurrSwRfb->ucStaRecIdx, + prCurrSwRfb->ucWlanIdx, + prCurrSwRfb->u2PacketLen); + DBGLOG_MEM8(QM, LOUD, + (uint8_t *) + prCurrSwRfb->pvHeader, + (prCurrSwRfb-> + u2PacketLen > 32) ? 32 : + prCurrSwRfb-> + u2PacketLen); + if (prAisBssInfo + && prAisBssInfo->prStaRecOfAP) + if (EQUAL_MAC_ADDR( + prWlanHeader-> + aucAddr1, + prAisBssInfo-> + aucOwnMacAddr) + && EQUAL_MAC_ADDR( + prWlanHeader-> + aucAddr2, + prAisBssInfo-> + aucBSSID)) { + uint16_t u2MACLen = 0; + /* QoS data, VHT */ + if (RXM_IS_QOS_DATA_FRAME( + u2FrameCtrl)) + u2MACLen = sizeof( + struct WLAN_MAC_HEADER_QOS); + else + u2MACLen = sizeof( + struct + WLAN_MAC_HEADER); + u2MACLen += + ETH_LLC_LEN + + ETH_SNAP_OUI_LEN; + u2MACLen -= + ETHER_TYPE_LEN_OFFSET; + prCurrSwRfb->pvHeader += + u2MACLen; + kalMemCopy( + prCurrSwRfb->pvHeader, + prWlanHeader->aucAddr1, + MAC_ADDR_LEN); + kalMemCopy( + prCurrSwRfb->pvHeader + + MAC_ADDR_LEN, + prWlanHeader->aucAddr2, + MAC_ADDR_LEN); + prCurrSwRfb->u2PacketLen -= + u2MACLen; + + /* record StaRec related info */ + prCurrSwRfb->prStaRec = + prAisBssInfo-> + prStaRecOfAP; + prCurrSwRfb->ucStaRecIdx = + prCurrSwRfb->prStaRec-> + ucIndex; + prCurrSwRfb->ucWlanIdx = + prCurrSwRfb->prStaRec-> + ucWlanIndex; + GLUE_SET_PKT_BSS_IDX( + prCurrSwRfb->pvPacket, + secGetBssIdxByWlanIdx( + prAdapter, + prCurrSwRfb-> + ucWlanIdx)); + DBGLOG_MEM8(QM, WARN, + (uint8_t *) + prCurrSwRfb->pvHeader, + (prCurrSwRfb-> + u2PacketLen > 64) ? 64 : + prCurrSwRfb-> + u2PacketLen); + } + } + } + +#if CFG_SUPPORT_WAPI + if (prCurrSwRfb->u2PacketLen > ETHER_HEADER_LEN) { + uint8_t *pc = (uint8_t *) prCurrSwRfb->pvHeader; + uint16_t u2Etype = 0; + + u2Etype = (pc[ETHER_TYPE_LEN_OFFSET] << 8) | + (pc[ETHER_TYPE_LEN_OFFSET + 1]); + /* for wapi integrity test. WPI_1x packet should be + * always in non-encrypted mode. if we received any + * WPI(0x88b4) packet that is encrypted, drop here. + */ + if (u2Etype == ETH_WPI_1X && + prCurrSwRfb->ucSecMode != 0 && + prCurrSwRfb->fgIsCipherMS == 0) { + DBGLOG(QM, INFO, + "drop wpi packet with sec mode\n"); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) prCurrSwRfb); + continue; + } + } +#endif + + + /* Todo:: Move the data class error check here */ + +#if CFG_SUPPORT_REPLAY_DETECTION + if (prCurrSwRfb->prStaRec) { + ucBssIndexRly = prCurrSwRfb->prStaRec->ucBssIndex; + prBssInfoRly = GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndexRly); + if (prBssInfoRly && !IS_BSS_ACTIVE(prBssInfoRly)) { + DBGLOG(QM, INFO, + "Mark NULL the Packet for inactive Bss %u\n", + ucBssIndexRly); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) prCurrSwRfb); + continue; + } + } + if (fgIsBMC && prBssInfoRly && IS_BSS_AIS(prBssInfoRly) && + qmHandleRxReplay(prAdapter, prCurrSwRfb)) { + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) prCurrSwRfb); + continue; + } +#endif + + if (prCurrSwRfb->fgReorderBuffer && !fgIsBMC && fgIsHTran) { + /* 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. + */ + if (prCurrSwRfb->ucTid >= CFG_RX_MAX_BA_TID_NUM) { + log_dbg(QM, ERROR, + "TID from RXD = %d, out of range !!!\n", + prCurrSwRfb->ucTid); + DBGLOG_MEM8(QM, ERROR, + prCurrSwRfb->pucRecvBuff, + prCurrSwRfb->u2RxByteCount); + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) prCurrSwRfb); + } else + qmProcessPktWithReordering(prAdapter, + prCurrSwRfb, prReturnedQue); + + } else if (prCurrSwRfb->fgDataFrame) { + /* Check Class Error */ + if (prCurrSwRfb->prStaRec && + (secCheckClassError(prAdapter, prCurrSwRfb, + prCurrSwRfb->prStaRec) == TRUE)) { + struct RX_BA_ENTRY *prReorderQueParm = NULL; + + if ((prCurrSwRfb->ucTid < CFG_RX_MAX_BA_TID_NUM) + && !fgIsBMC && fgIsHTran && + (HAL_RX_STATUS_GET_FRAME_CTL_FIELD( + prCurrSwRfb->prRxStatusGroup4) & + MASK_FRAME_TYPE) != MAC_FRAME_DATA) { + prReorderQueParm = + ((prCurrSwRfb->prStaRec-> + aprRxReorderParamRefTbl)[ + prCurrSwRfb->ucTid]); + } + + if (prReorderQueParm && + prReorderQueParm->fgIsValid) { + /* Only QoS Data frame with BA aggrement + * shall enter reordering buffer + */ + qmProcessPktWithReordering(prAdapter, + prCurrSwRfb, + prReturnedQue); + } else + qmHandleRxPackets_AOSP_1; + } else { + DBGLOG(QM, TRACE, + "Mark NULL the Packet for class error\n"); + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_CLASS_ERR_DROP_COUNT); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) prCurrSwRfb); + } + } else { + struct WLAN_MAC_HEADER *prWlanMacHeader; + + ASSERT(prCurrSwRfb->pvHeader); + + prWlanMacHeader = (struct WLAN_MAC_HEADER *) + prCurrSwRfb->pvHeader; + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + + switch (prWlanMacHeader->u2FrameCtrl & + MASK_FRAME_TYPE) { + /* BAR frame */ + case MAC_FRAME_BLOCK_ACK_REQ: + qmProcessBarFrame(prAdapter, + prCurrSwRfb, prReturnedQue); + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_BAR_DROP_COUNT); + break; + default: + DBGLOG(QM, TRACE, + "Mark NULL the Packet for non-interesting type\n"); + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_NO_INTEREST_DROP_COUNT); + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) prCurrSwRfb); + break; + } + } + + } while (prNextSwRfb); + + /* The returned list of SW_RFBs must end with a NULL pointer */ + if (QUEUE_IS_NOT_EMPTY(prReturnedQue)) + QM_TX_SET_NEXT_MSDU_INFO((struct SW_RFB *) QUEUE_GET_TAIL( + prReturnedQue), NULL); + + return (struct SW_RFB *) QUEUE_GET_HEAD(prReturnedQue); + +#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 struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + OUT struct QUE *prReturnedQue) +{ + + struct STA_RECORD *prStaRec; + struct RX_BA_ENTRY *prReorderQueParm; + +#if CFG_SUPPORT_RX_AMSDU + uint8_t u8AmsduSubframeIdx; + uint32_t u4SeqNo; +#endif + DEBUGFUNC("qmProcessPktWithReordering"); + + ASSERT(prSwRfb); + ASSERT(prReturnedQue); + + /* We should have STA_REC here */ + prStaRec = prSwRfb->prStaRec; + ASSERT(prStaRec); + ASSERT(prSwRfb->ucTid < CFG_RX_MAX_BA_TID_NUM); + + if (prSwRfb->ucTid >= CFG_RX_MAX_BA_TID_NUM) { + DBGLOG(QM, WARN, "TID from RXD = %d, out of range!!\n", + prSwRfb->ucTid); + DBGLOG_MEM8(QM, ERROR, prSwRfb->pucRecvBuff, + prSwRfb->u2RxByteCount); + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) prSwRfb); + return; + } + + /* Check whether the BA agreement exists */ + prReorderQueParm = (( + prStaRec->aprRxReorderParamRefTbl)[prSwRfb->ucTid]); + if (!prReorderQueParm || !(prReorderQueParm->fgIsValid)) { + DBGLOG(QM, TRACE, + "Reordering but no BA agreement for STA[%d] TID[%d]\n", + prStaRec->ucIndex, prSwRfb->ucTid); + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) prSwRfb); + return; + } + + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_DATA_REORDER_TOTAL_COUNT); + + prSwRfb->u2SSN = HAL_RX_STATUS_GET_SEQFrag_NUM( + prSwRfb->prRxStatusGroup4) >> RX_STATUS_SEQ_NUM_OFFSET; + +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + /* QUEUE_INITIALIZE(&prSwRfb->rAmsduQue); */ + + u8AmsduSubframeIdx = prSwRfb->ucPayloadFormat; + + /* prMpduSwRfb = prReorderQueParm->prMpduSwRfb; */ + u4SeqNo = (uint32_t)prSwRfb->u2SSN; + DBGLOG(RX, LOUD, "qmProcessPktWithReordering: SEQ:%d\n", u4SeqNo); + + switch (u8AmsduSubframeIdx) { + case RX_PAYLOAD_FORMAT_FIRST_SUB_AMSDU: + if (prReorderQueParm->fgAmsduNeedLastFrame) { + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_DATA_AMSDU_MISS_COUNT); + prReorderQueParm->fgAmsduNeedLastFrame = FALSE; + } + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_DATA_MSDU_IN_AMSDU_COUNT); + RX_INC_CNT(&prAdapter->rRxCtrl, RX_DATA_AMSDU_COUNT); + break; + + case RX_PAYLOAD_FORMAT_MIDDLE_SUB_AMSDU: + prReorderQueParm->fgAmsduNeedLastFrame = TRUE; + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_DATA_MSDU_IN_AMSDU_COUNT); + if (prReorderQueParm->u4SeqNo != u4SeqNo) { + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_DATA_AMSDU_MISS_COUNT); + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_DATA_AMSDU_COUNT); + } + break; + case RX_PAYLOAD_FORMAT_LAST_SUB_AMSDU: + prReorderQueParm->fgAmsduNeedLastFrame = FALSE; + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_DATA_MSDU_IN_AMSDU_COUNT); + if (prReorderQueParm->u4SeqNo != u4SeqNo) { + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_DATA_AMSDU_MISS_COUNT); + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_DATA_AMSDU_COUNT); + } + break; + + case RX_PAYLOAD_FORMAT_MSDU: + if (prReorderQueParm->fgAmsduNeedLastFrame) { + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_DATA_AMSDU_MISS_COUNT); + prReorderQueParm->fgAmsduNeedLastFrame = FALSE; + } + break; + default: + break; + } + + prReorderQueParm->u4SeqNo = u4SeqNo; +#endif + + RX_DIRECT_REORDER_LOCK(prAdapter, 0); + /* Insert reorder packet */ + qmInsertReorderPkt(prAdapter, prSwRfb, prReorderQueParm, + prReturnedQue); + RX_DIRECT_REORDER_UNLOCK(prAdapter, 0); +} + +void qmProcessBarFrame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, OUT struct QUE *prReturnedQue) +{ + + struct STA_RECORD *prStaRec; + struct RX_BA_ENTRY *prReorderQueParm; + struct CTRL_BAR_FRAME *prBarCtrlFrame; + + uint32_t u4SSN; + uint32_t u4WinStart; + uint32_t u4WinEnd; + + ASSERT(prSwRfb); + ASSERT(prReturnedQue); + ASSERT(prSwRfb->pvHeader); + + prBarCtrlFrame = (struct CTRL_BAR_FRAME *) prSwRfb->pvHeader; + + prSwRfb->ucTid = + (*((uint16_t *) ((uint8_t *) prBarCtrlFrame + + CTRL_BAR_BAR_CONTROL_OFFSET))) >> + BAR_CONTROL_TID_INFO_OFFSET; + prSwRfb->u2SSN = + (*((uint16_t *) ((uint8_t *) prBarCtrlFrame + + CTRL_BAR_BAR_INFORMATION_OFFSET))) >> + OFFSET_BAR_SSC_SN; + + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (struct QUE_ENTRY *) prSwRfb); + + /* Incorrect STA_REC index */ + prSwRfb->ucStaRecIdx = secLookupStaRecIndexFromTA(prAdapter, + prBarCtrlFrame->aucSrcAddr); + if (prSwRfb->ucStaRecIdx >= CFG_STA_REC_NUM) { + 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 */ + prSwRfb->prStaRec = cnmGetStaRecByIndex(prAdapter, + prSwRfb->ucStaRecIdx); + prStaRec = prSwRfb->prStaRec; + if (prStaRec == NULL) { + /* ASSERT(prStaRec); */ + return; + } +#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; + } + + RX_DIRECT_REORDER_LOCK(prAdapter, 0); + + u4SSN = (uint32_t) (prSwRfb->u2SSN); + u4WinStart = (uint32_t) (prReorderQueParm->u2WinStart); + u4WinEnd = (uint32_t) (prReorderQueParm->u2WinEnd); + + if (qmCompareSnIsLessThan(u4WinStart, u4SSN)) { + prReorderQueParm->u2WinStart = (uint16_t) u4SSN; + prReorderQueParm->u2WinEnd = + ((prReorderQueParm->u2WinStart) + + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT; +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + prReorderQueParm->u8LastAmsduSubIdx = RX_PAYLOAD_FORMAT_MSDU; +#endif + DBGLOG(QM, TRACE, + "QM:(BAR)[%d](%u){%hu,%hu}\n", + prSwRfb->ucTid, u4SSN, + prReorderQueParm->u2WinStart, + prReorderQueParm->u2WinEnd); + qmPopOutDueToFallAhead(prAdapter, prReorderQueParm, + prReturnedQue); + } else { + DBGLOG(QM, TRACE, "QM:(BAR)(%d)(%u){%u,%u}\n", + prSwRfb->ucTid, u4SSN, u4WinStart, u4WinEnd); + } + RX_DIRECT_REORDER_UNLOCK(prAdapter, 0); +} + +void qmInsertReorderPkt(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN struct RX_BA_ENTRY *prReorderQueParm, + OUT struct QUE *prReturnedQue) +{ + uint32_t u4SeqNo; + uint32_t u4WinStart; + uint32_t u4WinEnd; + + /* Start to reorder packets */ + u4SeqNo = (uint32_t) (prSwRfb->u2SSN); + u4WinStart = (uint32_t) (prReorderQueParm->u2WinStart); + u4WinEnd = (uint32_t) (prReorderQueParm->u2WinEnd); + + /* Debug */ + DBGLOG_LIMITED(QM, LOUD, "QM:(R)[%u](%u){%u,%u}\n", prSwRfb->ucTid, + u4SeqNo, u4WinStart, u4WinEnd); + + if (prReorderQueParm->fgNoDrop) { + if (!qmCompareSnIsLessThan(u4SeqNo, + prReorderQueParm->u2WinStart)) { + /* Fall behind SSN pkts started to Fall within + * StartWin + */ + prReorderQueParm->u4SNOverlapCount++; + if (prReorderQueParm->u4SNOverlapCount > 10) { + /* Set threshold as 10 to make sure + * the SSN is really falling within StartWin + */ + prReorderQueParm->u4SNOverlapCount = 0; + prReorderQueParm->fgNoDrop = FALSE; + DBGLOG(QM, INFO, "NO drop = FALSE, [%d][%d]\n", + u4SeqNo, prReorderQueParm->u2WinStart); + } + } + } + /* 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(prAdapter, prSwRfb, + prReorderQueParm, prReturnedQue); + +#if QM_RX_WIN_SSN_AUTO_ADVANCING + if (prReorderQueParm->fgIsWaitingForPktWithSsn) { + /* Let the first received packet + * pass the reorder check + */ + DBGLOG(QM, LOUD, "QM:(A)[%d](%u){%u,%u}\n", + prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); + + prReorderQueParm->u2WinStart = (uint16_t) u4SeqNo; + prReorderQueParm->u2WinEnd = + ((prReorderQueParm->u2WinStart) + + (prReorderQueParm->u2WinSize) - 1) % + MAX_SEQ_NO_COUNT; + prReorderQueParm->fgIsWaitingForPktWithSsn = FALSE; +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + prReorderQueParm->u8LastAmsduSubIdx = + RX_PAYLOAD_FORMAT_MSDU; +#endif + } +#endif + + qmPopOutDueToFallWithin(prAdapter, 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)))) { + + uint16_t u2Delta, u2BeforeWinEnd; + uint32_t u4BeforeCount, u4MissingCount; + +#if QM_RX_WIN_SSN_AUTO_ADVANCING + if (prReorderQueParm->fgIsWaitingForPktWithSsn) + prReorderQueParm->fgIsWaitingForPktWithSsn = FALSE; +#endif + + qmInsertFallAheadReorderPkt(prAdapter, prSwRfb, + prReorderQueParm, prReturnedQue); + + u2BeforeWinEnd = prReorderQueParm->u2WinEnd; + + /* Advance the window after inserting a new tail */ + prReorderQueParm->u2WinEnd = (uint16_t) u4SeqNo; + prReorderQueParm->u2WinStart = + (((prReorderQueParm->u2WinEnd) + MAX_SEQ_NO_COUNT - + prReorderQueParm->u2WinSize + 1) % + MAX_SEQ_NO_COUNT); +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + prReorderQueParm->u8LastAmsduSubIdx = + RX_PAYLOAD_FORMAT_MSDU; +#endif + u4BeforeCount = prReorderQueParm->rReOrderQue.u4NumElem; + qmPopOutDueToFallAhead(prAdapter, prReorderQueParm, + prReturnedQue); + + if (prReorderQueParm->u2WinEnd >= u2BeforeWinEnd) + u2Delta = prReorderQueParm->u2WinEnd - u2BeforeWinEnd; + else + u2Delta = MAX_SEQ_NO_COUNT - (u2BeforeWinEnd - + prReorderQueParm->u2WinEnd); + + u4MissingCount = u2Delta - (u4BeforeCount - + prReorderQueParm->rReOrderQue.u4NumElem); + + RX_ADD_CNT(&prAdapter->rRxCtrl, RX_DATA_REORDER_MISS_COUNT, + u4MissingCount); + /* If the SSN jump over 1024, + * we consider it as an abnormal jump and + * temporally reserve the fall behind packets until + * the pkt SSN is really falling within StartWin + */ + if (u2Delta > QUARTER_SEQ_NO_COUNT) { + prReorderQueParm->fgNoDrop = TRUE; + prReorderQueParm->u4SNOverlapCount = 0; + DBGLOG_LIMITED(QM, INFO, + "QM: SSN jump over 1024:[%d]\n", u2Delta); + } + DBGLOG_LIMITED(QM, TRACE, "QM: Miss Count:[%d]\n", + RX_GET_CNT(&prAdapter->rRxCtrl, + RX_DATA_REORDER_MISS_COUNT)); + } + /* Case 3: Fall behind */ + else { +#if CFG_SUPPORT_LOWLATENCY_MODE || CFG_SUPPORT_OSHARE + if (qmIsNoDropPacket(prAdapter, prSwRfb) || + prReorderQueParm->fgNoDrop) { + DBGLOG(QM, LOUD, "QM: No drop packet:[%d](%d){%d,%d}\n", + prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); + + qmPopOutReorderPkt(prAdapter, prSwRfb, + prReturnedQue, RX_DATA_REORDER_BEHIND_COUNT); + return; + } +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + +#if QM_RX_WIN_SSN_AUTO_ADVANCING && QM_RX_INIT_FALL_BEHIND_PASS + if (prReorderQueParm->fgIsWaitingForPktWithSsn) { + DBGLOG(QM, LOUD, "QM:(P)[%u](%u){%u,%u}\n", + prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); + qmPopOutReorderPkt(prAdapter, prSwRfb, prReturnedQue, + RX_DATA_REORDER_BEHIND_COUNT); + return; + } +#endif + + /* An erroneous packet */ + DBGLOG(QM, LOUD, "QM:(D)[%u](%u){%u,%u}\n", prSwRfb->ucTid, + u4SeqNo, u4WinStart, u4WinEnd); + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + qmPopOutReorderPkt(prAdapter, prSwRfb, prReturnedQue, + RX_DATA_REORDER_BEHIND_COUNT); + return; + } +} + +void qmInsertFallWithinReorderPkt(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN struct RX_BA_ENTRY *prReorderQueParm, + OUT struct QUE *prReturnedQue) +{ + struct SW_RFB *prExaminedQueuedSwRfb; + struct QUE *prReorderQue; + uint8_t u8AmsduSubframeIdx; /* RX reorder for one MSDU in AMSDU issue */ + + ASSERT(prSwRfb); + ASSERT(prReorderQueParm); + ASSERT(prReturnedQue); + + prReorderQue = &(prReorderQueParm->rReOrderQue); + prExaminedQueuedSwRfb = (struct SW_RFB *) QUEUE_GET_HEAD( + prReorderQue); + + u8AmsduSubframeIdx = prSwRfb->ucPayloadFormat; + + /* There are no packets queued in the Reorder Queue */ + if (prExaminedQueuedSwRfb == NULL) { + ((struct QUE_ENTRY *) prSwRfb)->prPrev = NULL; + ((struct QUE_ENTRY *) prSwRfb)->prNext = NULL; + prReorderQue->prHead = (struct QUE_ENTRY *) prSwRfb; + prReorderQue->prTail = (struct QUE_ENTRY *) prSwRfb; + prReorderQue->u4NumElem++; + } + + /* Determine the insert position */ + else { + do { + /* Case 1: Terminate. A duplicate packet */ + if ((prExaminedQueuedSwRfb->u2SSN) == + (prSwRfb->u2SSN)) { +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + /* if middle or last and first is not + * duplicated, not a duplicat packet + */ + if (!prReorderQueParm->fgIsAmsduDuplicated && + (u8AmsduSubframeIdx == + RX_PAYLOAD_FORMAT_MIDDLE_SUB_AMSDU || + u8AmsduSubframeIdx == + RX_PAYLOAD_FORMAT_LAST_SUB_AMSDU)) { + + prExaminedQueuedSwRfb = + (struct SW_RFB *)(( + (struct QUE_ENTRY *) + prExaminedQueuedSwRfb)->prNext); + while (prExaminedQueuedSwRfb && + ((prExaminedQueuedSwRfb-> + u2SSN) == (prSwRfb->u2SSN))) + prExaminedQueuedSwRfb = + (struct SW_RFB *)(( + (struct QUE_ENTRY *) + prExaminedQueuedSwRfb)-> + prNext); + + break; + } + /* if first is duplicated, + * drop subsequent middle and last frames + */ + if (u8AmsduSubframeIdx == + RX_PAYLOAD_FORMAT_FIRST_SUB_AMSDU) + prReorderQueParm->fgIsAmsduDuplicated = + TRUE; +#endif + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + qmPopOutReorderPkt(prAdapter, + prSwRfb, prReturnedQue, + RX_DUPICATE_DROP_COUNT); + LINK_QUALITY_COUNT_DUP(prAdapter, 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 = + (struct SW_RFB *) (((struct QUE_ENTRY *) + prExaminedQueuedSwRfb)->prNext); + } while (prExaminedQueuedSwRfb); +#if CFG_SUPPORT_RX_AMSDU + prReorderQueParm->fgIsAmsduDuplicated = FALSE; +#endif + /* Update the Reorder Queue Parameters according to + * the found insert position + */ + if (prExaminedQueuedSwRfb == NULL) { + /* The received packet shall be placed at the tail */ + ((struct QUE_ENTRY *) prSwRfb)->prPrev = + prReorderQue->prTail; + ((struct QUE_ENTRY *) prSwRfb)->prNext = NULL; + (prReorderQue->prTail)->prNext = + (struct QUE_ENTRY *) (prSwRfb); + prReorderQue->prTail = (struct QUE_ENTRY *) (prSwRfb); + } else { + ((struct QUE_ENTRY *) prSwRfb)->prPrev = + ((struct QUE_ENTRY *) + prExaminedQueuedSwRfb)->prPrev; + ((struct QUE_ENTRY *) prSwRfb)->prNext = + (struct QUE_ENTRY *) prExaminedQueuedSwRfb; + if (((struct QUE_ENTRY *) prExaminedQueuedSwRfb) == + (prReorderQue->prHead)) { + /* The received packet will become the head */ + prReorderQue->prHead = + (struct QUE_ENTRY *) prSwRfb; + } else { + (((struct QUE_ENTRY *) + prExaminedQueuedSwRfb)->prPrev)->prNext = + (struct QUE_ENTRY *) prSwRfb; + } + ((struct QUE_ENTRY *) prExaminedQueuedSwRfb)->prPrev = + (struct QUE_ENTRY *) prSwRfb; + } + + prReorderQue->u4NumElem++; + } + +} + +void qmInsertFallAheadReorderPkt(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN struct RX_BA_ENTRY *prReorderQueParm, + OUT struct QUE *prReturnedQue) +{ + struct QUE *prReorderQue; + + ASSERT(prSwRfb); + ASSERT(prReorderQueParm); + ASSERT(prReturnedQue); +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + prReorderQueParm->fgIsAmsduDuplicated = FALSE; +#endif + prReorderQue = &(prReorderQueParm->rReOrderQue); + /* There are no packets queued in the Reorder Queue */ + if (QUEUE_IS_EMPTY(prReorderQue)) { + ((struct QUE_ENTRY *) prSwRfb)->prPrev = NULL; + ((struct QUE_ENTRY *) prSwRfb)->prNext = NULL; + prReorderQue->prHead = (struct QUE_ENTRY *) prSwRfb; + } else { + ((struct QUE_ENTRY *) prSwRfb)->prPrev = + prReorderQue->prTail; + ((struct QUE_ENTRY *) prSwRfb)->prNext = NULL; + (prReorderQue->prTail)->prNext = (struct QUE_ENTRY *) ( + prSwRfb); + } + prReorderQue->prTail = (struct QUE_ENTRY *) prSwRfb; + prReorderQue->u4NumElem++; +} + +void qmPopOutReorderPkt(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, OUT struct QUE *prReturnedQue, + IN enum ENUM_RX_STATISTIC_COUNTER eRxCounter) +{ + uint32_t u4PktCnt = 0; + /* RX reorder for one MSDU in AMSDU issue */ +#if 0 + struct SW_RFB *prAmsduSwRfb; +#endif + + u4PktCnt++; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *)prSwRfb); + +#if 0 + u4PktCnt += prSwRfb->rAmsduQue.u4NumElem; + QUEUE_REMOVE_HEAD(&prSwRfb->rAmsduQue, prAmsduSwRfb, + struct SW_RFB *); + while (prAmsduSwRfb) { + /* Update MSDU destination of AMSDU */ + prAmsduSwRfb->eDst = prSwRfb->eDst; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *)prAmsduSwRfb); + QUEUE_REMOVE_HEAD(&prSwRfb->rAmsduQue, prAmsduSwRfb, + struct SW_RFB *); + } +#endif + + RX_ADD_CNT(&prAdapter->rRxCtrl, eRxCounter, u4PktCnt); +} + +void qmPopOutDueToFallWithin(IN struct ADAPTER *prAdapter, + IN struct RX_BA_ENTRY *prReorderQueParm, + OUT struct QUE *prReturnedQue) +{ + struct SW_RFB *prReorderedSwRfb; + struct QUE *prReorderQue; + u_int8_t fgDequeuHead, fgMissing; + OS_SYSTIME rCurrentTime, *prMissTimeout; + /* RX reorder for one MSDU in AMSDU issue */ + uint8_t fgIsAmsduSubframe; + + 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 = (struct SW_RFB *) QUEUE_GET_HEAD( + prReorderQue); + fgDequeuHead = FALSE; + + /* RX reorder for one MSDU in AMSDU issue */ + fgIsAmsduSubframe = prReorderedSwRfb->ucPayloadFormat; +#if CFG_SUPPORT_RX_AMSDU + /* If SN + 1 come and last frame is first or middle, + * update winstart + */ + if ((qmCompareSnIsLessThan((prReorderQueParm->u2WinStart), + (prReorderedSwRfb->u2SSN))) + && (prReorderQueParm->u4SeqNo != + prReorderQueParm->u2WinStart)) { + if (prReorderQueParm->u8LastAmsduSubIdx == + RX_PAYLOAD_FORMAT_FIRST_SUB_AMSDU + || prReorderQueParm->u8LastAmsduSubIdx == + RX_PAYLOAD_FORMAT_MIDDLE_SUB_AMSDU) { + + prReorderQueParm->u2WinStart = + (((prReorderQueParm->u2WinStart) + 1) % + MAX_SEQ_NO_COUNT); + prReorderQueParm->u8LastAmsduSubIdx = + RX_PAYLOAD_FORMAT_MSDU; + } + } +#endif + /* SN == WinStart, so the head packet + * shall be indicated (advance the window) + */ + if ((prReorderedSwRfb->u2SSN) == + (prReorderQueParm->u2WinStart)) { + + fgDequeuHead = TRUE; + /* RX reorder for one MSDU in AMSDU issue */ + /* if last frame, winstart++. + * Otherwise, keep winstart + */ + if (fgIsAmsduSubframe == + RX_PAYLOAD_FORMAT_LAST_SUB_AMSDU + || fgIsAmsduSubframe == RX_PAYLOAD_FORMAT_MSDU) + prReorderQueParm->u2WinStart = + (((prReorderedSwRfb->u2SSN) + 1) % + MAX_SEQ_NO_COUNT); +#if CFG_SUPPORT_RX_AMSDU + prReorderQueParm->u8LastAmsduSubIdx = fgIsAmsduSubframe; +#endif + } + /* SN > WinStart, break to update WinEnd */ + else { + /* Start bubble timer */ + if (!prReorderQueParm->fgHasBubble) { + cnmTimerStartTimer(prAdapter, + &(prReorderQueParm->rReorderBubbleTimer), + prAdapter->u4QmRxBaMissTimeout); + prReorderQueParm->fgHasBubble = TRUE; + prReorderQueParm->u2FirstBubbleSn = + prReorderQueParm->u2WinStart; + + DBGLOG(QM, TRACE, + "QM:(Bub Timer) STA[%u] TID[%u] BubSN[%u] Win{%d, %d}\n", + prReorderQueParm->ucStaRecIdx, + prReorderedSwRfb->ucTid, + prReorderQueParm->u2FirstBubbleSn, + prReorderQueParm->u2WinStart, + prReorderQueParm->u2WinEnd); + } + + if (fgMissing && + CHECK_FOR_TIMEOUT(rCurrentTime, *prMissTimeout, + MSEC_TO_SYSTIME( + prAdapter->u4QmRxBaMissTimeout + ))) { + + 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); +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + prReorderQueParm->u8LastAmsduSubIdx = + RX_PAYLOAD_FORMAT_MSDU; +#endif + fgMissing = FALSE; + } else + break; + } + + /* Dequeue the head packet */ + if (fgDequeuHead) { + if (((struct QUE_ENTRY *) prReorderedSwRfb)->prNext == + NULL) { + prReorderQue->prHead = NULL; + prReorderQue->prTail = NULL; + } else { + prReorderQue->prHead = + ((struct QUE_ENTRY *) + prReorderedSwRfb)->prNext; + (((struct QUE_ENTRY *) + prReorderedSwRfb)->prNext)->prPrev = + NULL; + } + prReorderQue->u4NumElem--; + DBGLOG(QM, LOUD, "QM: [%d] %d (%d)\n", + prReorderQueParm->ucTid, + prReorderedSwRfb->u2PacketLen, + prReorderedSwRfb->u2SSN); + qmPopOutReorderPkt(prAdapter, prReorderedSwRfb, + prReturnedQue, RX_DATA_REORDER_WITHIN_COUNT); + } + } + + 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 struct ADAPTER *prAdapter, + IN struct RX_BA_ENTRY *prReorderQueParm, + OUT struct QUE *prReturnedQue) +{ + struct SW_RFB *prReorderedSwRfb; + struct QUE *prReorderQue; + u_int8_t fgDequeuHead; + uint8_t fgIsAmsduSubframe;/* RX reorder for one MSDU in AMSDU issue */ + + 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 = + (struct SW_RFB *) QUEUE_GET_HEAD(prReorderQue); + fgDequeuHead = FALSE; + + /* RX reorder for one MSDU in AMSDU issue */ + fgIsAmsduSubframe = prReorderedSwRfb->ucPayloadFormat; +#if CFG_SUPPORT_RX_AMSDU + /* If SN + 1 come and last frame is first or middle, + * update winstart + */ + if ((qmCompareSnIsLessThan((prReorderQueParm->u2WinStart), + (prReorderedSwRfb->u2SSN))) + && (prReorderQueParm->u4SeqNo != + prReorderQueParm->u2WinStart)) { + if (prReorderQueParm->u8LastAmsduSubIdx == + RX_PAYLOAD_FORMAT_FIRST_SUB_AMSDU + || prReorderQueParm->u8LastAmsduSubIdx == + RX_PAYLOAD_FORMAT_MIDDLE_SUB_AMSDU) { + + prReorderQueParm->u2WinStart = + (((prReorderQueParm->u2WinStart) + 1) % + MAX_SEQ_NO_COUNT); + prReorderQueParm->u8LastAmsduSubIdx = + RX_PAYLOAD_FORMAT_MSDU; + } + } +#endif + /* SN == WinStart, so the head packet shall be + * indicated (advance the window) + */ + if ((prReorderedSwRfb->u2SSN) == + (prReorderQueParm->u2WinStart)) { + + fgDequeuHead = TRUE; + /* RX reorder for one MSDU in AMSDU issue */ + /* if last frame, winstart++. + * Otherwise, keep winstart + */ + if (fgIsAmsduSubframe == + RX_PAYLOAD_FORMAT_LAST_SUB_AMSDU || + fgIsAmsduSubframe == RX_PAYLOAD_FORMAT_MSDU) + prReorderQueParm->u2WinStart = + (((prReorderedSwRfb->u2SSN) + 1) % + MAX_SEQ_NO_COUNT); +#if CFG_SUPPORT_RX_AMSDU + prReorderQueParm->u8LastAmsduSubIdx = fgIsAmsduSubframe; +#endif + } + + /* SN < WinStart, so the head packet shall be + * indicated (do not advance the window) + */ + else if (qmCompareSnIsLessThan((uint32_t)( + prReorderedSwRfb->u2SSN), + (uint32_t)(prReorderQueParm->u2WinStart))) + fgDequeuHead = TRUE; + + /* SN > WinStart, break to update WinEnd */ + else { + /* Start bubble timer */ + if (!prReorderQueParm->fgHasBubble) { + cnmTimerStartTimer(prAdapter, + &(prReorderQueParm-> + rReorderBubbleTimer), + prAdapter->u4QmRxBaMissTimeout); + prReorderQueParm->fgHasBubble = TRUE; + prReorderQueParm->u2FirstBubbleSn = + prReorderQueParm->u2WinStart; + + DBGLOG(QM, TRACE, + "QM:(Bub Timer) STA[%u] TID[%u] BubSN[%u] Win{%d, %d}\n", + prReorderQueParm->ucStaRecIdx, + prReorderedSwRfb->ucTid, + prReorderQueParm->u2FirstBubbleSn, + prReorderQueParm->u2WinStart, + prReorderQueParm->u2WinEnd); + } + break; + } + + /* Dequeue the head packet */ + if (fgDequeuHead) { + if (((struct QUE_ENTRY *) prReorderedSwRfb)->prNext == + NULL) { + prReorderQue->prHead = NULL; + prReorderQue->prTail = NULL; + } else { + prReorderQue->prHead = ((struct QUE_ENTRY *) + prReorderedSwRfb)->prNext; + (((struct QUE_ENTRY *) prReorderedSwRfb)-> + prNext)->prPrev = NULL; + } + prReorderQue->u4NumElem--; + DBGLOG_LIMITED(QM, TRACE, "QM: [%u] %u (%u)\n", + prReorderQueParm->ucTid, + prReorderedSwRfb->u2PacketLen, + prReorderedSwRfb->u2SSN); + + qmPopOutReorderPkt(prAdapter, prReorderedSwRfb, + prReturnedQue, RX_DATA_REORDER_AHEAD_COUNT); + } + } + + /* After WinStart has been determined, update the WinEnd */ + prReorderQueParm->u2WinEnd = + (((prReorderQueParm->u2WinStart) + + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT); + +} + +void qmHandleReorderBubbleTimeout(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr) +{ + struct RX_BA_ENTRY *prReorderQueParm = + (struct RX_BA_ENTRY *) ulParamPtr; + + ASSERT(prAdapter); + + if (!prReorderQueParm->fgIsValid) { + DBGLOG(QM, TRACE, + "QM:(Bub Check Cancel) STA[%u] TID[%u], No Rx BA entry\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + return; + } + + if (!prReorderQueParm->fgHasBubble) { + DBGLOG(QM, TRACE, + "QM:(Bub Check Cancel) STA[%u] TID[%u], Bubble has been filled\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + return; + } + + DBGLOG(QM, TRACE, + "QM:(Bub Timeout) STA[%u] TID[%u] BubSN[%u]\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid, + prReorderQueParm->u2FirstBubbleSn); + + qmHandleEventCheckReorderBubble(prAdapter, prReorderQueParm); +} + +void qmHandleEventCheckReorderBubble(IN struct ADAPTER *prAdapter, + struct RX_BA_ENTRY *prReorderQueParm) +{ + struct QUE *prReorderQue; + struct QUE rReturnedQue; + struct QUE *prReturnedQue = &rReturnedQue; + struct SW_RFB *prReorderedSwRfb, *prSwRfb; + OS_SYSTIME *prMissTimeout; + + QUEUE_INITIALIZE(prReturnedQue); + + /* Sanity Check */ + if (!prReorderQueParm) { + DBGLOG(QM, TRACE, "QM:(Bub Check Cancel) No Rx BA entry\n"); + return; + } + + if (!prReorderQueParm->fgIsValid) { + DBGLOG(QM, TRACE, + "QM:(Bub Check Cancel) STA[%u] TID[%u], No Rx BA entry\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + return; + } + + if (!prReorderQueParm->fgHasBubble) { + DBGLOG(QM, TRACE, + "QM:(Bub Check Cancel) STA[%u] TID[%u], Bubble has been filled\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + return; + } + + prReorderQue = &(prReorderQueParm->rReOrderQue); + + RX_DIRECT_REORDER_LOCK(prAdapter, 0); + + if (QUEUE_IS_EMPTY(prReorderQue)) { + prReorderQueParm->fgHasBubble = FALSE; + + DBGLOG(QM, TRACE, + "QM:(Bub Check Cancel) STA[%u] TID[%u], Bubble has been filled\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + + RX_DIRECT_REORDER_UNLOCK(prAdapter, 0); + return; + } + + DBGLOG(QM, TRACE, + "QM:(Bub Check Event Got) STA[%u] TID[%u]\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + + /* Expected bubble timeout => pop out packets before win_end */ + if (prReorderQueParm->u2FirstBubbleSn == + prReorderQueParm->u2WinStart) { + + prReorderedSwRfb = (struct SW_RFB *) QUEUE_GET_TAIL( + prReorderQue); + + prReorderQueParm->u2WinStart = prReorderedSwRfb->u2SSN + 1; + if (prReorderQueParm->u2WinStart >= MAX_SEQ_NO_COUNT) + prReorderQueParm->u2WinStart %= MAX_SEQ_NO_COUNT; + prReorderQueParm->u2WinEnd = + ((prReorderQueParm->u2WinStart) + + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT; +#if CFG_SUPPORT_RX_AMSDU + prReorderQueParm->u8LastAmsduSubIdx = + RX_PAYLOAD_FORMAT_MSDU; +#endif + qmPopOutDueToFallAhead(prAdapter, prReorderQueParm, + prReturnedQue); + + DBGLOG(QM, TRACE, + "QM:(Bub Flush) STA[%u] TID[%u] BubSN[%u] Win{%u, %u}\n", + prReorderQueParm->ucStaRecIdx, + prReorderQueParm->ucTid, + prReorderQueParm->u2FirstBubbleSn, + prReorderQueParm->u2WinStart, + prReorderQueParm->u2WinEnd); + + prReorderQueParm->fgHasBubble = FALSE; + RX_DIRECT_REORDER_UNLOCK(prAdapter, 0); + + /* process prReturnedQue after unlock prReturnedQue */ + if (QUEUE_IS_NOT_EMPTY(prReturnedQue)) { + QM_TX_SET_NEXT_MSDU_INFO( + (struct SW_RFB *) QUEUE_GET_TAIL( + prReturnedQue), NULL); + + prSwRfb = (struct SW_RFB *) + QUEUE_GET_HEAD(prReturnedQue); + while (prSwRfb) { + DBGLOG(QM, TRACE, + "QM:(Bub Flush) STA[%u] TID[%u] Pop Out SN[%u]\n", + prReorderQueParm->ucStaRecIdx, + prReorderQueParm->ucTid, + prSwRfb->u2SSN); + + prSwRfb = (struct SW_RFB *) + QUEUE_GET_NEXT_ENTRY( + (struct QUE_ENTRY *) prSwRfb); + } + + wlanProcessQueuedSwRfb(prAdapter, + (struct SW_RFB *) + QUEUE_GET_HEAD(prReturnedQue)); + } else { + DBGLOG(QM, TRACE, + "QM:(Bub Flush) STA[%u] TID[%u] Pop Out 0 packet\n", + prReorderQueParm->ucStaRecIdx, + prReorderQueParm->ucTid); + } + } + /* First bubble has been filled but others exist */ + else { + prReorderQueParm->u2FirstBubbleSn = + prReorderQueParm->u2WinStart; + + DBGLOG(QM, TRACE, + "QM:(Bub Timer) STA[%u] TID[%u] BubSN[%u] Win{%u, %u}\n", + prReorderQueParm->ucStaRecIdx, + prReorderQueParm->ucTid, + prReorderQueParm->u2FirstBubbleSn, + prReorderQueParm->u2WinStart, + prReorderQueParm->u2WinEnd); + RX_DIRECT_REORDER_UNLOCK(prAdapter, 0); + + cnmTimerStartTimer(prAdapter, + &(prReorderQueParm->rReorderBubbleTimer), + prAdapter->u4QmRxBaMissTimeout); + } + + prMissTimeout = &g_arMissTimeout[ + prReorderQueParm->ucStaRecIdx][prReorderQueParm->ucTid]; + if (QUEUE_IS_EMPTY(prReorderQue)) { + DBGLOG(QM, TRACE, + "QM:(Bub Check) Reset prMissTimeout to zero\n"); + *prMissTimeout = 0; + } else { + DBGLOG(QM, TRACE, + "QM:(Bub Check) Reset prMissTimeout to current time\n"); + GET_CURRENT_SYSTIME(prMissTimeout); + } +} + +u_int8_t qmCompareSnIsLessThan(IN uint32_t u4SnLess, IN uint32_t u4SnGreater) +{ + /* 0 <---> SnLess <--(gap>2048)--> SnGreater : SnLess > SnGreater */ + if ((u4SnLess + HALF_SEQ_NO_COUNT) <= u4SnGreater) + 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 struct MAILBOX_MSG prMailboxRxMsg) +{ + /* DbgPrint("QM: Enter qmHandleMailboxRxMessage()\n"); */ + /* TODO */ +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Handle ADD TX BA Event from the FW + * + * \param[in] prAdapter Adapter pointer + * \param[in] prEvent The event packet from the FW + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void qmHandleEventTxAddBa(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct mt66xx_chip_info *prChipInfo; + struct EVENT_TX_ADDBA *prEventTxAddBa; + struct STA_RECORD *prStaRec; + uint8_t ucStaRecIdx; + uint8_t ucTid; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + DBGLOG(QM, INFO, "QM:Event +TxBa\n"); + + if (!prChipInfo->is_support_hw_amsdu && + prChipInfo->ucMaxSwAmsduNum <= 1) { + DBGLOG(QM, INFO, "QM:Event +TxBa but chip is not support\n"); + return; + } + + prEventTxAddBa = (struct EVENT_TX_ADDBA *) (prEvent->aucBuffer); + ucStaRecIdx = prEventTxAddBa->ucStaRecIdx; + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, ucStaRecIdx); + if (!prStaRec) { + /* Invalid STA_REC index, discard the event packet */ + /* ASSERT(0); */ + DBGLOG(QM, INFO, + "QM: (Warning) TX ADDBA Event for a NULL STA_REC\n"); + return; + } + + for (ucTid = 0; ucTid < TX_DESC_TID_NUM; ucTid++) { + uint8_t ucStaEn = prStaRec->ucAmsduEnBitmap & BIT(ucTid); + uint8_t ucEvtEn = prEventTxAddBa->ucAmsduEnBitmap & BIT(ucTid); + + if (prChipInfo->is_support_hw_amsdu && ucStaEn != ucEvtEn) + nicTxSetHwAmsduDescTemplate(prAdapter, prStaRec, ucTid, + ucEvtEn >> ucTid); + } + + prStaRec->ucAmsduEnBitmap = prEventTxAddBa->ucAmsduEnBitmap; + prStaRec->ucMaxMpduCount = prEventTxAddBa->ucMaxMpduCount; + prStaRec->u4MaxMpduLen = prEventTxAddBa->u4MaxMpduLen; + prStaRec->u4MinMpduLen = prEventTxAddBa->u4MinMpduLen; + + DBGLOG(QM, INFO, + "QM:Event +TxBa bitmap[0x%x] count[%u] MaxLen[%u] MinLen[%u]\n", + prStaRec->ucAmsduEnBitmap, prStaRec->ucMaxMpduCount, + prStaRec->u4MaxMpduLen, prStaRec->u4MinMpduLen); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct EVENT_RX_ADDBA *prEventRxAddBa; + struct STA_RECORD *prStaRec; + uint32_t u4Tid; + uint32_t u4WinSize; + + DBGLOG(QM, INFO, "QM:Event +RxBa\n"); + + prEventRxAddBa = (struct EVENT_RX_ADDBA *) ( + prEvent->aucBuffer); + 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, + (uint8_t) u4Tid, + (prEventRxAddBa->u2BAStartSeqCtrl >> + OFFSET_BAR_SSC_SN), + (uint16_t) u4WinSize)) { + + /* FW shall ensure the availabiilty of + * the free-to-use BA entry + */ + DBGLOG(QM, ERROR, "QM: (Error) qmAddRxBaEntry() failure\n"); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct EVENT_RX_DELBA *prEventRxDelBa; + struct STA_RECORD *prStaRec; + + /* DbgPrint("QM:Event -RxBa\n"); */ + + prEventRxDelBa = (struct EVENT_RX_DELBA *) ( + prEvent->aucBuffer); + 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); + +} + +struct RX_BA_ENTRY *qmLookupRxBaEntry(IN struct ADAPTER *prAdapter, + uint8_t ucStaRecIdx, uint8_t ucTid) +{ + int i; + struct QUE_MGT *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; +} + +u_int8_t qmAddRxBaEntry(IN struct ADAPTER *prAdapter, + IN uint8_t ucStaRecIdx, IN uint8_t ucTid, + IN uint16_t u2WinStart, IN uint16_t u2WinSize) +{ + int i; + struct RX_BA_ENTRY *prRxBaEntry = NULL; + struct STA_RECORD *prStaRec; + struct QUE_MGT *prQM = &prAdapter->rQM; + + ASSERT(ucStaRecIdx < CFG_STA_REC_NUM); + + if (ucStaRecIdx >= CFG_STA_REC_NUM || ucTid >= CFG_RX_MAX_BA_TID_NUM) { + /* Invalid STA_REC index, discard the event packet */ + DBGLOG(QM, WARN, + "QM: (WARNING) RX ADDBA Event for a invalid ucStaRecIdx = %d, ucTID=%d\n", + ucStaRecIdx, ucTid); + return FALSE; + } + + prStaRec = &prAdapter->arStaRec[ucStaRecIdx]; + ASSERT(prStaRec); + + /* 4 <1> Delete before adding */ + /* Remove the BA entry for the same (STA, TID) tuple if it exists */ + /* prQM->ucRxBaCount-- */ + if (qmLookupRxBaEntry(prAdapter, ucStaRecIdx, ucTid)) + qmDelRxBaEntry(prAdapter, ucStaRecIdx, ucTid, TRUE); + /* 4 <2> Add a new BA entry */ + /* No available entry to store the BA agreement info. Retrun FALSE. */ + if (prQM->ucRxBaCount >= CFG_NUM_OF_RX_BA_AGREEMENTS) { + DBGLOG(QM, ERROR, + "QM: **failure** (limited resource, ucRxBaCount=%d)\n", + prQM->ucRxBaCount); + return FALSE; + } + /* Find the free-to-use BA entry */ + for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) { + if (!prQM->arRxBaTable[i].fgIsValid) { + prRxBaEntry = &(prQM->arRxBaTable[i]); + prQM->ucRxBaCount++; + DBGLOG(QM, LOUD, + "QM: ucRxBaCount=%d\n", prQM->ucRxBaCount); + break; + } + } + + /* If a free-to-use entry is found, + * configure it and associate it with the STA_REC + */ + u2WinSize += CFG_RX_BA_INC_SIZE; + if (prRxBaEntry) { + prRxBaEntry->ucStaRecIdx = ucStaRecIdx; + prRxBaEntry->ucTid = ucTid; + prRxBaEntry->u2WinStart = u2WinStart; + prRxBaEntry->u2WinSize = u2WinSize; + prRxBaEntry->u2WinEnd = ((u2WinStart + u2WinSize - 1) % + MAX_SEQ_NO_COUNT); +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + prRxBaEntry->u8LastAmsduSubIdx = RX_PAYLOAD_FORMAT_MSDU; + prRxBaEntry->fgAmsduNeedLastFrame = FALSE; + prRxBaEntry->fgIsAmsduDuplicated = FALSE; +#endif + prRxBaEntry->fgIsValid = TRUE; + prRxBaEntry->fgIsWaitingForPktWithSsn = TRUE; + prRxBaEntry->fgHasBubble = FALSE; + + g_arMissTimeout[ucStaRecIdx][ucTid] = 0; + + DBGLOG(QM, INFO, + "QM: +RxBA(STA=%u TID=%u WinStart=%u WinEnd=%u WinSize=%u)\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 struct ADAPTER *prAdapter, + IN uint8_t ucStaRecIdx, IN uint8_t ucTid, + IN u_int8_t fgFlushToHost) +{ + struct RX_BA_ENTRY *prRxBaEntry; + struct STA_RECORD *prStaRec; + struct SW_RFB *prFlushedPacketList = NULL; + struct QUE_MGT *prQM = &prAdapter->rQM; + + ASSERT(ucStaRecIdx < CFG_STA_REC_NUM); + + 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 { + + struct SW_RFB *prSwRfb; + struct SW_RFB *prNextSwRfb; + + prSwRfb = prFlushedPacketList; + + do { + prNextSwRfb = (struct SW_RFB *) + QUEUE_GET_NEXT_ENTRY( + (struct QUE_ENTRY *) prSwRfb); + nicRxReturnRFB(prAdapter, prSwRfb); + prSwRfb = prNextSwRfb; + } while (prSwRfb); + + } + + } + + if (prRxBaEntry->fgHasBubble) { + DBGLOG(QM, TRACE, + "QM:(Bub Check Cancel) STA[%u] TID[%u], DELBA\n", + prRxBaEntry->ucStaRecIdx, prRxBaEntry->ucTid); + + cnmTimerStopTimer(prAdapter, + &prRxBaEntry->rReorderBubbleTimer); + prRxBaEntry->fgHasBubble = FALSE; + } +#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 + { + struct RX_CTRL *prRxCtrl; + + prRxCtrl = &prAdapter->rRxCtrl; + DBGLOG(QM, TRACE, + "QM: (RX DEBUG) Enqueued: %d / Dequeued: %d\n", + prRxCtrl->u4QueuedCnt, prRxCtrl->u4DequeuedCnt); + } +#endif +} + +u_int8_t qmIsIndependentPkt(IN struct SW_RFB *prSwRfb) +{ + struct sk_buff *skb = NULL; + + if (prSwRfb->u2PacketLen <= ETHER_HEADER_LEN) + return FALSE; + + skb = (struct sk_buff *)(prSwRfb->pvPacket); + if (!skb) + return FALSE; + + if (GLUE_GET_INDEPENDENT_PKT(skb)) + return TRUE; + + return FALSE; +} + +void mqmParseAssocReqWmmIe(IN struct ADAPTER *prAdapter, + IN uint8_t *pucIE, IN struct STA_RECORD *prStaRec) +{ + struct IE_WMM_INFO *prIeWmmInfo; + uint8_t ucQosInfo; + uint8_t ucQosInfoAC; + uint8_t ucBmpAC; + uint8_t aucWfaOui[] = VENDOR_OUI_WFA; + + if ((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) + && (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) { + + switch (WMM_IE_OUI_SUBTYPE(pucIE)) { + case VENDOR_OUI_SUBTYPE_WMM_INFO: + if (IE_LEN(pucIE) != 7) + break; /* WMM Info IE with a wrong length */ + + prStaRec->fgIsQoS = TRUE; + prStaRec->fgIsWmmSupported = TRUE; + + prIeWmmInfo = (struct IE_WMM_INFO *) pucIE; + ucQosInfo = prIeWmmInfo->ucQosInfo; + ucQosInfoAC = ucQosInfo & BITS(0, 3); + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucUapsd)) + prStaRec->fgIsUapsdSupported = + (ucQosInfoAC) ? TRUE : FALSE; + else + prStaRec->fgIsUapsdSupported = FALSE; + + 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; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, IN uint8_t *pucIE, + IN uint16_t u2IELength) +{ + struct STA_RECORD *prStaRec; + uint16_t u2Offset; + uint8_t *pucIEStart; + uint32_t u4Flags; + + 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 (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS)) + return; + + /* Determine whether QoS is enabled with the association */ + else { + prStaRec->u4Flags = 0; + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_VENDOR: + mqmParseAssocReqWmmIe(prAdapter, + pucIE, prStaRec); + +#if CFG_SUPPORT_MTK_SYNERGY + if (rlmParseCheckMTKOuiIE(prAdapter, + pucIE, &u4Flags)) + prStaRec->u4Flags = u4Flags; +#endif + + break; + + case ELEM_ID_HT_CAP: + /* Some client won't put the WMM IE + * if client is 802.11n + */ + if (IE_LEN(pucIE) == + (sizeof(struct IE_HT_CAP) - 2)) + prStaRec->fgIsQoS = TRUE; + break; + default: + break; + } + } + + DBGLOG(QM, TRACE, + "MQM: Assoc_Req Parsing (QoS Enabled=%d)\n", + prStaRec->fgIsQoS); + + } +} + +void mqmParseAssocRspWmmIe(IN uint8_t *pucIE, + IN struct STA_RECORD *prStaRec) +{ + uint8_t aucWfaOui[] = VENDOR_OUI_WFA; + + if ((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) + && (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) { + struct IE_WMM_PARAM *prWmmParam = (struct IE_WMM_PARAM *) pucIE; + enum ENUM_ACI eAci; + + 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; + prStaRec->fgIsUapsdSupported = + !!(prWmmParam->ucQosInfo & WMM_QOS_INFO_UAPSD); + for (eAci = ACI_BE; eAci < ACI_NUM; eAci++) + prStaRec->afgAcmRequired[eAci] = !!( + prWmmParam->arAcParam[eAci].ucAciAifsn & + WMM_ACIAIFSN_ACM); + DBGLOG(WMM, INFO, + "WMM: " MACSTR "ACM BK=%d BE=%d VI=%d VO=%d\n", + MAC2STR(prStaRec->aucMacAddr), + prStaRec->afgAcmRequired[ACI_BK], + prStaRec->afgAcmRequired[ACI_BE], + prStaRec->afgAcmRequired[ACI_VI], + prStaRec->afgAcmRequired[ACI_VO]); + 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; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, IN uint8_t *pucIE, + IN uint16_t u2IELength) +{ + struct STA_RECORD *prStaRec; + uint16_t u2Offset; + uint8_t *pucIEStart; + uint32_t u4Flags; + + 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.ucQoS); + + /* If the device does not support QoS + * or if WMM is not supported by the peer, exit. + */ + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS)) + return; + + /* Determine whether QoS is enabled with the association */ + else { + prStaRec->u4Flags = 0; + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_VENDOR: + /* Process WMM related IE */ + mqmParseAssocRspWmmIe(pucIE, prStaRec); + +#if CFG_SUPPORT_MTK_SYNERGY + if (rlmParseCheckMTKOuiIE(prAdapter, + pucIE, &u4Flags)) + prStaRec->u4Flags = u4Flags; +#endif + + break; + + case ELEM_ID_HT_CAP: + /* Some AP won't put the WMM IE + * if client is 802.11n + */ + if (IE_LEN(pucIE) == + (sizeof(struct IE_HT_CAP) - 2)) + prStaRec->fgIsQoS = TRUE; + break; +#if DSCP_SUPPORT + case ELEM_ID_QOS_MAP_SET: + DBGLOG(QM, WARN, + "QM: received assoc resp qosmapset ie\n"); + qosParseQosMapSet(prAdapter, prStaRec, pucIE); + break; +#endif + default: + break; + } + } + /* Parse AC parameters and write to HW CRs */ + if ((prStaRec->fgIsQoS) + && (prStaRec->eStaType == STA_TYPE_LEGACY_AP)) { + mqmParseEdcaParameters(prAdapter, prSwRfb, pucIEStart, + u2IELength, TRUE); +#if (CFG_SUPPORT_802_11AX == 1) + if (fgEfuseCtrlAxOn == 1) { + mqmParseMUEdcaParams(prAdapter, prSwRfb, + pucIEStart, u2IELength, TRUE); + } +#endif + +#if ARP_MONITER_ENABLE + qmResetArpDetect(); +#endif + } + DBGLOG(QM, TRACE, + "MQM: Assoc_Rsp Parsing (QoS Enabled=%d)\n", + prStaRec->fgIsQoS); + if (prStaRec->fgIsWmmSupported) + nicQmUpdateWmmParms(prAdapter, prStaRec->ucBssIndex); +#if (CFG_SUPPORT_802_11AX == 1) + if (fgEfuseCtrlAxOn == 1) { + if (prStaRec->fgIsMuEdcaSupported || + prAdapter->fgMuEdcaOverride) { + nicQmUpdateMUEdcaParams(prAdapter, + prStaRec->ucBssIndex); + } + } +#endif + + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void mqmProcessBcn(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, IN uint8_t *pucIE, + IN uint16_t u2IELength) +{ + struct BSS_INFO *prBssInfo; + u_int8_t fgNewParameter; +#if (CFG_SUPPORT_802_11AX == 1) + u_int8_t fgNewMUEdca = FALSE; +#endif + uint8_t i; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + ASSERT(pucIE); + + DBGLOG(QM, TRACE, "Enter %s\n", __func__); + + fgNewParameter = FALSE; + + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, i); + + if (IS_BSS_ACTIVE(prBssInfo)) { + if (prBssInfo->eCurrentOPMode == + OP_MODE_INFRASTRUCTURE && + prBssInfo->eConnectionState == + MEDIA_STATE_CONNECTED) { + /* P2P client or AIS infra STA */ + if (EQUAL_MAC_ADDR(prBssInfo->aucBSSID, + ((struct WLAN_MAC_MGMT_HEADER *) + (prSwRfb->pvHeader))->aucBSSID)) { + + fgNewParameter = + mqmParseEdcaParameters( + prAdapter, + prSwRfb, pucIE, + u2IELength, FALSE); +#if (CFG_SUPPORT_802_11AX == 1) + if (fgEfuseCtrlAxOn == 1) { + fgNewMUEdca = mqmParseMUEdcaParams( + prAdapter, prSwRfb, pucIE, + u2IELength, FALSE); + } +#endif + } + } + + /* Appy new parameters if necessary */ + if (fgNewParameter) { + nicQmUpdateWmmParms(prAdapter, + prBssInfo->ucBssIndex); + fgNewParameter = FALSE; + } +#if (CFG_SUPPORT_802_11AX == 1) + if (fgEfuseCtrlAxOn == 1) { + if (fgNewMUEdca) { + nicQmUpdateMUEdcaParams(prAdapter, + prBssInfo->ucBssIndex); + fgNewMUEdca = FALSE; + } + } +#endif + } + } /* end of IS_BSS_ACTIVE() */ +} + + +u_int8_t mqmUpdateEdcaParameters(IN struct BSS_INFO *prBssInfo, + IN uint8_t *pucIE, IN u_int8_t fgForceOverride) +{ + struct AC_QUE_PARMS *prAcQueParams; + struct IE_WMM_PARAM *prIeWmmParam; + enum ENUM_WMM_ACI eAci; + u_int8_t fgNewParameter = FALSE; + + do { + if (IE_LEN(pucIE) != 24) + break; /* WMM Param IE with a wrong length */ + + prIeWmmParam = (struct IE_WMM_PARAM *) pucIE; + + /* Check the Parameter Set Count to determine + * whether EDCA parameters have been changed + */ + if (!fgForceOverride) { + if (mqmCompareEdcaParameters(prIeWmmParam, prBssInfo)) { + fgNewParameter = FALSE; + break; + } + } + + fgNewParameter = TRUE; + /* Update Parameter Set Count */ + prBssInfo->ucWmmParamSetCount = (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); + log_dbg(QM, INFO, "BSS[%u]: eAci[%d] ACM[%d] Aifsn[%d] CWmin/max[%d/%d] TxopLimit[%d] NewParameter[%d]\n", + prBssInfo->ucBssIndex, eAci, + prAcQueParams->ucIsACMSet, + prAcQueParams->u2Aifsn, prAcQueParams->u2CWmin, + prAcQueParams->u2CWmax, + prAcQueParams->u2TxopLimit, fgNewParameter); + } + } while (FALSE); + + return fgNewParameter; +} + +#if (CFG_SUPPORT_802_11AX == 1) +uint8_t mqmCompareMUEdcaParameters( + struct _IE_MU_EDCA_PARAM_T *prIeMUEdcaParam, + struct BSS_INFO *prBssInfo) +{ + struct _CMD_MU_EDCA_PARAMS_T *prBSSMUEdca; + struct _MU_AC_PARAM_RECORD_T *prMUAcParamInIE; + enum ENUM_WMM_ACI eAci; + + /* Check Set Count */ + if (prBssInfo->ucMUEdcaUpdateCnt != + (prIeMUEdcaParam->ucMUQosInfo & WMM_QOS_INFO_PARAM_SET_CNT)) + return FALSE; + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prBSSMUEdca = &prBssInfo->arMUEdcaParams[eAci]; + prMUAcParamInIE = &prIeMUEdcaParam->arMUAcParam[eAci]; + + /* ACM */ + if (prBSSMUEdca->ucIsACMSet != ((prMUAcParamInIE->ucAciAifsn & + WMM_ACIAIFSN_ACM) ? TRUE : FALSE)) + return FALSE; + + /* AIFSN */ + if (prBSSMUEdca->ucAifsn != (prMUAcParamInIE->ucAciAifsn & + WMM_ACIAIFSN_AIFSN)) + return FALSE; + + /* CW Max */ + if (prBSSMUEdca->ucECWmax != + ((prMUAcParamInIE->ucEcw & WMM_ECW_WMAX_MASK) + >> WMM_ECW_WMAX_OFFSET)) + return FALSE; + + /* CW Min */ + if (prBSSMUEdca->ucECWmin != + (prMUAcParamInIE->ucEcw & WMM_ECW_WMIN_MASK)) + return FALSE; + + /* MU EDCA timer */ + if (prBSSMUEdca->ucMUEdcaTimer != + prMUAcParamInIE->ucMUEdcaTimer) + return FALSE; + } + + return TRUE; +} + +uint8_t mqmUpdateMUEdcaParams(struct BSS_INFO *prBssInfo, + uint8_t *pucIE, uint8_t fgForceOverride) +{ + struct _CMD_MU_EDCA_PARAMS_T *prBSSMUEdca; + struct _IE_MU_EDCA_PARAM_T *prIeMUEdcaParam; + struct _MU_AC_PARAM_RECORD_T *prMUAcParamInIE; + enum ENUM_WMM_ACI eAci; + uint8_t fgNewParameter = FALSE; + + do { + if (IE_LEN(pucIE) != 14) + break; /* MU EDCA Param IE with a wrong length */ + + prIeMUEdcaParam = (struct _IE_MU_EDCA_PARAM_T *) pucIE; + + /* + * Check the Parameter Set Count to determine whether + * MU EDCA parameters have been changed + */ + if (!fgForceOverride) { + if (mqmCompareMUEdcaParameters(prIeMUEdcaParam, + prBssInfo)) { + fgNewParameter = FALSE; + break; + } + } + + fgNewParameter = TRUE; + /* Update Parameter Set Count */ + prBssInfo->ucMUEdcaUpdateCnt = (prIeMUEdcaParam->ucMUQosInfo & + WMM_QOS_INFO_PARAM_SET_CNT); + /* Update MU EDCA parameters to BSS structure */ + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prMUAcParamInIE = &(prIeMUEdcaParam->arMUAcParam[eAci]); + prBSSMUEdca = &prBssInfo->arMUEdcaParams[eAci]; + + prBSSMUEdca->ucECWmin = prMUAcParamInIE->ucEcw & + WMM_ECW_WMIN_MASK; + prBSSMUEdca->ucECWmax = (prMUAcParamInIE->ucEcw & + WMM_ECW_WMAX_MASK) + >> WMM_ECW_WMAX_OFFSET; + prBSSMUEdca->ucAifsn = (prMUAcParamInIE->ucAciAifsn & + WMM_ACIAIFSN_AIFSN); + prBSSMUEdca->ucIsACMSet = (prMUAcParamInIE->ucAciAifsn & + WMM_ACIAIFSN_ACM) ? TRUE : FALSE; + prBSSMUEdca->ucMUEdcaTimer = + prMUAcParamInIE->ucMUEdcaTimer; + + DBGLOG(QM, INFO, + "BSS[%u]: eAci[%d] ACM[%d] Aifsn[%d],", + prBssInfo->ucBssIndex, eAci, + prBSSMUEdca->ucIsACMSet, prBSSMUEdca->ucAifsn); + DBGLOG(QM, INFO, + "ECWmin/max[%d/%d] NewParameter[%d]\n", + prBSSMUEdca->ucECWmin, prBSSMUEdca->ucECWmax, + fgNewParameter); + + } + } while (FALSE); + + return fgNewParameter; +} + +uint8_t +mqmParseMUEdcaParams( + struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb, + uint8_t *pucIE, + uint16_t u2IELength, + uint8_t fgForceOverride) +{ + struct STA_RECORD *prStaRec; + uint16_t u2Offset; + struct BSS_INFO *prBssInfo; + uint8_t fgNewParameter = FALSE; + + DEBUGFUNC("mqmParseMUEdcaParams"); + + if (!prSwRfb) + return FALSE; + + if (!pucIE) + return FALSE; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (prStaRec == NULL) + return FALSE; + + DBGLOG(QM, TRACE, "QM: (fgIsQoS=%d)\n", prStaRec->fgIsQoS); + + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS) || + (!prStaRec->fgIsQoS)) + return FALSE; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + /* Goal: Obtain the MU EDCA parameters */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_RESERVED: + if (IE_ID_EXT(pucIE) == ELEM_EXT_ID_MU_EDCA_PARAM) { + prStaRec->fgIsMuEdcaSupported = TRUE; + fgNewParameter = mqmUpdateMUEdcaParams( + prBssInfo, pucIE, fgForceOverride); + } + break; + default: + break; + } + } + + return fgNewParameter; +} +#endif + + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t +mqmParseEdcaParameters(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, IN uint8_t *pucIE, + IN uint16_t u2IELength, IN u_int8_t fgForceOverride) +{ + struct STA_RECORD *prStaRec; + uint16_t u2Offset; + uint8_t aucWfaOui[] = VENDOR_OUI_WFA; + struct BSS_INFO *prBssInfo; + u_int8_t fgNewParameter = FALSE; + + DEBUGFUNC("mqmParseEdcaParameters"); + + if (!prSwRfb) + return FALSE; + + if (!pucIE) + return FALSE; + + prStaRec = cnmGetStaRecByIndex(prAdapter, + prSwRfb->ucStaRecIdx); + /* ASSERT(prStaRec); */ + + if (prStaRec == NULL) + return FALSE; + + DBGLOG(QM, TRACE, "QM: (fgIsWmmSupported=%d, fgIsQoS=%d)\n", + prStaRec->fgIsWmmSupported, prStaRec->fgIsQoS); + + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS) + || (!prStaRec->fgIsWmmSupported) + || (!prStaRec->fgIsQoS)) + return FALSE; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + /* Goal: Obtain the EDCA parameters */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_WMM: + if (!((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) && + (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3)))) + break; + + switch (WMM_IE_OUI_SUBTYPE(pucIE)) { + case VENDOR_OUI_SUBTYPE_WMM_PARAM: + fgNewParameter = + mqmUpdateEdcaParameters(prBssInfo, + pucIE, fgForceOverride); + break; + + default: + /* Other WMM QoS IEs. Ignore */ + break; + } + + /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS, ... + * (not cared) + */ + break; + default: + break; + } + } + + return fgNewParameter; +} + +u_int8_t mqmCompareEdcaParameters(IN struct IE_WMM_PARAM *prIeWmmParam, + IN struct BSS_INFO *prBssInfo) +{ + struct AC_QUE_PARMS *prAcQueParams; + struct WMM_AC_PARAM *prWmmAcParams; + enum ENUM_WMM_ACI eAci; + + /* return FALSE; */ + + /* Check Set Count */ + if (prBssInfo->ucWmmParamSetCount != + (prIeWmmParam->ucQosInfo & WMM_QOS_INFO_PARAM_SET_CNT)) + return FALSE; + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prAcQueParams = &prBssInfo->arACQueParms[eAci]; + prWmmAcParams = &prIeWmmParam->arAcParam[eAci]; + + /* ACM */ + if (prAcQueParams->ucIsACMSet != ((prWmmAcParams->ucAciAifsn & + WMM_ACIAIFSN_ACM) ? TRUE : FALSE)) + return FALSE; + + /* AIFSN */ + if (prAcQueParams->u2Aifsn != (prWmmAcParams->ucAciAifsn & + WMM_ACIAIFSN_AIFSN)) + return FALSE; + + /* CW Max */ + if (prAcQueParams->u2CWmax != + (BIT((prWmmAcParams->ucEcw & WMM_ECW_WMAX_MASK) >> + WMM_ECW_WMAX_OFFSET) - 1)) + return FALSE; + + /* CW Min */ + if (prAcQueParams->u2CWmin != (BIT(prWmmAcParams->ucEcw & + WMM_ECW_WMIN_MASK) - 1)) + return FALSE; + + if (prAcQueParams->u2TxopLimit != + prWmmAcParams->u2TxopLimit) + return FALSE; + } + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct IE_WMM_PARAM *prIeWmmParam, + IN uint32_t u4AcOffset, + OUT struct AC_QUE_PARMS *prAcQueParams) +{ + struct WMM_AC_PARAM *prAcParam = + &prIeWmmParam->arAcParam[u4AcOffset]; + + prAcQueParams->ucIsACMSet = (prAcParam->ucAciAifsn & + WMM_ACIAIFSN_ACM) ? TRUE : FALSE; + + prAcQueParams->u2Aifsn = (prAcParam->ucAciAifsn & + WMM_ACIAIFSN_AIFSN); + + prAcQueParams->u2CWmax = BIT((prAcParam->ucEcw & + WMM_ECW_WMAX_MASK) >> WMM_ECW_WMAX_OFFSET) - 1; + + prAcQueParams->u2CWmin = BIT(prAcParam->ucEcw & + WMM_ECW_WMIN_MASK) - 1; + + WLAN_GET_FIELD_16(&prAcParam->u2TxopLimit, + &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 struct ADAPTER *prAdapter, + IN struct BSS_DESC *prScanResult, + OUT struct STA_RECORD *prStaRec) +{ + uint8_t *pucIE; + uint16_t u2IELength; + uint16_t u2Offset; + uint8_t aucWfaOui[] = VENDOR_OUI_WFA; + u_int8_t fgIsHtVht; + + DEBUGFUNC("mqmProcessScanResult"); + + ASSERT(prScanResult); + ASSERT(prStaRec); + + /* Reset the flag before parsing */ + prStaRec->fgIsWmmSupported = FALSE; + prStaRec->fgIsUapsdSupported = FALSE; + prStaRec->fgIsQoS = FALSE; +#if (CFG_SUPPORT_802_11AX == 1) + prStaRec->fgIsMuEdcaSupported = FALSE; +#endif + + fgIsHtVht = FALSE; + + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS)) + return; + + u2IELength = prScanResult->u2IELength; + pucIE = prScanResult->aucIEBuf; + + /* <1> Determine whether the peer supports WMM/QoS and UAPSDU */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + + case ELEM_ID_EXTENDED_CAP: +#if CFG_SUPPORT_TDLS + TdlsBssExtCapParse(prStaRec, pucIE); +#endif /* CFG_SUPPORT_TDLS */ +#if CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT + prStaRec->fgSupportBTM = + !!((*(uint32_t *)(pucIE + 2)) & + BIT(ELEM_EXT_CAP_BSS_TRANSITION_BIT)); +#endif + break; + + case ELEM_ID_WMM: + if ((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) && + (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) { + struct IE_WMM_PARAM *prWmmParam = + (struct IE_WMM_PARAM *)pucIE; + enum ENUM_ACI eAci; + + switch (WMM_IE_OUI_SUBTYPE(pucIE)) { + case VENDOR_OUI_SUBTYPE_WMM_PARAM: + /* WMM Param IE with a wrong length */ + if (IE_LEN(pucIE) != 24) + break; + prStaRec->fgIsWmmSupported = TRUE; + prStaRec->fgIsUapsdSupported = + !!(prWmmParam->ucQosInfo & + WMM_QOS_INFO_UAPSD); + for (eAci = ACI_BE; eAci < ACI_NUM; + eAci++) + prStaRec->afgAcmRequired + [eAci] = !!( + prWmmParam + ->arAcParam + [eAci] + .ucAciAifsn & + WMM_ACIAIFSN_ACM); + DBGLOG(WMM, INFO, + "WMM: " MACSTR + "ACM BK=%d BE=%d VI=%d VO=%d\n", + MAC2STR(prStaRec->aucMacAddr), + prStaRec->afgAcmRequired[ACI_BK], + prStaRec->afgAcmRequired[ACI_BE], + prStaRec->afgAcmRequired[ACI_VI], + prStaRec->afgAcmRequired + [ACI_VO]); + break; + + case VENDOR_OUI_SUBTYPE_WMM_INFO: + /* WMM Info IE with a wrong length */ + if (IE_LEN(pucIE) != 7) + break; + prStaRec->fgIsWmmSupported = TRUE; + prStaRec->fgIsUapsdSupported = + (((( + (struct IE_WMM_INFO *) + pucIE)->ucQosInfo) + & WMM_QOS_INFO_UAPSD) + ? TRUE : FALSE); + break; + + default: + /* A WMM QoS IE that doesn't matter. + * Ignore it. + */ + break; + } + } + break; + + default: + /* A WMM IE that doesn't matter. Ignore it. */ + break; + } + } + + /* <1> Determine QoS */ + if (prStaRec->ucDesiredPhyTypeSet & (PHY_TYPE_SET_802_11N | + PHY_TYPE_SET_802_11AC)) + fgIsHtVht = TRUE; + + if (fgIsHtVht || prStaRec->fgIsWmmSupported) + prStaRec->fgIsQoS = TRUE; + +#if (CFG_SUPPORT_802_11AX == 1) + if (fgEfuseCtrlAxOn == 1) { + if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11AX) + prStaRec->fgIsQoS = TRUE; + } +#endif + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Generate the WMM Info IE by Param + * + * \param[in] prAdapter Adapter pointer + * @param prMsduInfo The TX MMPDU + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +uint32_t +mqmFillWmmInfoIE(uint8_t *pucOutBuf, + u_int8_t fgSupportUAPSD, uint8_t ucBmpDeliveryAC, + uint8_t ucBmpTriggerAC, uint8_t ucUapsdSp) +{ + struct IE_WMM_INFO *prIeWmmInfo; + uint32_t ucUapsd[] = { + WMM_QOS_INFO_BE_UAPSD, + WMM_QOS_INFO_BK_UAPSD, + WMM_QOS_INFO_VI_UAPSD, + WMM_QOS_INFO_VO_UAPSD + }; + uint8_t aucWfaOui[] = VENDOR_OUI_WFA; + + ASSERT(pucOutBuf); + + prIeWmmInfo = (struct IE_WMM_INFO *) pucOutBuf; + + prIeWmmInfo->ucId = ELEM_ID_WMM; + prIeWmmInfo->ucLength = ELEM_MAX_LEN_WMM_INFO; + + /* WMM-2.2.1 WMM Information Element Field Values */ + prIeWmmInfo->aucOui[0] = aucWfaOui[0]; + prIeWmmInfo->aucOui[1] = aucWfaOui[1]; + prIeWmmInfo->aucOui[2] = aucWfaOui[2]; + prIeWmmInfo->ucOuiType = VENDOR_OUI_TYPE_WMM; + prIeWmmInfo->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_INFO; + + prIeWmmInfo->ucVersion = VERSION_WMM; + prIeWmmInfo->ucQosInfo = 0; + + /* UAPSD initial queue configurations (delivery and trigger enabled) */ + if (fgSupportUAPSD) { + uint8_t ucQosInfo = 0; + uint8_t i; + + /* Static U-APSD setting */ + for (i = ACI_BE; i <= ACI_VO; i++) { + if (ucBmpDeliveryAC & ucBmpTriggerAC & BIT(i)) + ucQosInfo |= (uint8_t) ucUapsd[i]; + } + + if (ucBmpDeliveryAC & ucBmpTriggerAC) { + switch (ucUapsdSp) { + case WMM_MAX_SP_LENGTH_ALL: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_ALL; + break; + + case WMM_MAX_SP_LENGTH_2: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_2; + break; + + case WMM_MAX_SP_LENGTH_4: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_4; + break; + + case WMM_MAX_SP_LENGTH_6: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_6; + break; + + default: + DBGLOG(QM, 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. + */ + return IE_SIZE(prIeWmmInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Generate the WMM Info IE + * + * \param[in] prAdapter Adapter pointer + * @param prMsduInfo The TX MMPDU + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +uint32_t +mqmGenerateWmmInfoIEByStaRec(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, struct STA_RECORD *prStaRec, + uint8_t *pucOutBuf) +{ + struct PM_PROFILE_SETUP_INFO *prPmProfSetupInfo; + u_int8_t fgSupportUapsd; + + ASSERT(pucOutBuf); + + /* In case QoS is not turned off, exit directly */ + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS)) + return 0; + + if (prStaRec == NULL) + return 0; + + if (!prStaRec->fgIsQoS) + return 0; + + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + + fgSupportUapsd = (IS_FEATURE_ENABLED( + prAdapter->rWifiVar.ucUapsd) && + prStaRec->fgIsUapsdSupported); + + return mqmFillWmmInfoIE(pucOutBuf, + fgSupportUapsd, + prPmProfSetupInfo->ucBmpDeliveryAC, + prPmProfSetupInfo->ucBmpTriggerAC, + prPmProfSetupInfo->ucUapsdSp); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Generate the WMM Info IE + * + * \param[in] prAdapter Adapter pointer + * @param prMsduInfo The TX MMPDU + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void mqmGenerateWmmInfoIE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint32_t u4Length; + + DEBUGFUNC("mqmGenerateWmmInfoIE"); + + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + if (prStaRec == NULL) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + u4Length = mqmGenerateWmmInfoIEByStaRec(prAdapter, + prBssInfo, prStaRec, + ((uint8_t *) prMsduInfo->prPacket + + prMsduInfo->u2FrameLength)); + + prMsduInfo->u2FrameLength += u4Length; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Generate the WMM Param IE + * + * \param[in] prAdapter Adapter pointer + * @param prMsduInfo The TX MMPDU + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void mqmGenerateWmmParamIE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct IE_WMM_PARAM *prIeWmmParam; + + uint8_t aucWfaOui[] = VENDOR_OUI_WFA; + + uint8_t aucACI[] = { + WMM_ACI_AC_BE, + WMM_ACI_AC_BK, + WMM_ACI_AC_VI, + WMM_ACI_AC_VO + }; + + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + enum ENUM_WMM_ACI eAci; + struct WMM_AC_PARAM *prAcParam; + + DEBUGFUNC("mqmGenerateWmmParamIE"); + DBGLOG(QM, LOUD, "\n"); + + ASSERT(prMsduInfo); + + /* In case QoS is not turned off, exit directly */ + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS)) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + + if (prStaRec) { + if (!prStaRec->fgIsQoS) + return; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prMsduInfo->ucBssIndex); + + if (!prBssInfo->fgIsQBSS) + return; + + prIeWmmParam = (struct IE_WMM_PARAM *) + ((uint8_t *) 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 initial queue configurations (delivery and trigger enabled) */ + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucUapsd)) + prIeWmmParam->ucQosInfo |= WMM_QOS_INFO_UAPSD; + + /* EDCA parameter */ + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prAcParam = &prIeWmmParam->arAcParam[eAci]; + + /* ACI */ + prAcParam->ucAciAifsn = aucACI[eAci]; + /* ACM */ + if (prBssInfo->arACQueParmsForBcast[eAci].ucIsACMSet) + prAcParam->ucAciAifsn |= WMM_ACIAIFSN_ACM; + /* AIFSN */ + prAcParam->ucAciAifsn |= + (prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn & + WMM_ACIAIFSN_AIFSN); + + /* ECW Min */ + prAcParam->ucEcw = (prBssInfo->aucCWminLog2ForBcast[eAci] & + WMM_ECW_WMIN_MASK); + /* ECW Max */ + prAcParam->ucEcw |= + ((prBssInfo->aucCWmaxLog2ForBcast[eAci] << + WMM_ECW_WMAX_OFFSET) & WMM_ECW_WMAX_MASK); + + /* Txop limit */ + WLAN_SET_FIELD_16(&prAcParam->u2TxopLimit, + prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit); + + } + + /* Increment the total IE length + * for the Element ID and Length fields. + */ + prMsduInfo->u2FrameLength += IE_SIZE(prIeWmmParam); + +} + +#if CFG_SUPPORT_TDLS +/*----------------------------------------------------------------------------*/ +/*! + * @brief Generate the WMM Param IE + * + * \param[in] prAdapter Adapter pointer + * @param prMsduInfo The TX MMPDU + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +uint32_t mqmGenerateWmmParamIEByParam(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, uint8_t *pOutBuf) +{ + struct IE_WMM_PARAM *prIeWmmParam; + + uint8_t aucWfaOui[] = VENDOR_OUI_WFA; + + uint8_t aucACI[] = { + WMM_ACI_AC_BE, + WMM_ACI_AC_BK, + WMM_ACI_AC_VI, + WMM_ACI_AC_VO + }; + + struct AC_QUE_PARMS *prACQueParms; + /* BE, BK, VO, VI */ + uint8_t auCWminLog2ForBcast[WMM_AC_INDEX_NUM] = {4, 4, 3, 2}; + uint8_t auCWmaxLog2ForBcast[WMM_AC_INDEX_NUM] = {10, 10, 4, 3}; + uint8_t auAifsForBcast[WMM_AC_INDEX_NUM] = {3, 7, 2, 2}; + /* If the AP is OFDM */ + uint8_t auTxopForBcast[WMM_AC_INDEX_NUM] = {0, 0, 94, 47}; + + enum ENUM_WMM_ACI eAci; + struct WMM_AC_PARAM *prAcParam; + + DEBUGFUNC("mqmGenerateWmmParamIE"); + DBGLOG(QM, LOUD, "\n"); + + ASSERT(pOutBuf); + + /* In case QoS is not turned off, exit directly */ + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS)) + return WLAN_STATUS_SUCCESS; + + if (!prBssInfo->fgIsQBSS) + return WLAN_STATUS_SUCCESS; + + if (IS_FEATURE_ENABLED( + prAdapter->rWifiVar.fgTdlsBufferSTASleep)) { + prACQueParms = prBssInfo->arACQueParmsForBcast; + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prACQueParms[eAci].ucIsACMSet = 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]; + + /* used to send WMM IE */ + prBssInfo->aucCWminLog2ForBcast[eAci] = + auCWminLog2ForBcast[eAci]; + prBssInfo->aucCWmaxLog2ForBcast[eAci] = + auCWmaxLog2ForBcast[eAci]; + } + } + + prIeWmmParam = (struct IE_WMM_PARAM *) pOutBuf; + + prIeWmmParam->ucId = ELEM_ID_WMM; + prIeWmmParam->ucLength = ELEM_MAX_LEN_WMM_PARAM; + + /* WMM-2.2.1 WMM Information Element Field Values */ + prIeWmmParam->aucOui[0] = aucWfaOui[0]; + prIeWmmParam->aucOui[1] = aucWfaOui[1]; + prIeWmmParam->aucOui[2] = aucWfaOui[2]; + prIeWmmParam->ucOuiType = VENDOR_OUI_TYPE_WMM; + prIeWmmParam->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_PARAM; + + prIeWmmParam->ucVersion = VERSION_WMM; + /* STAUT Buffer STA, also sleeps (optional) + * The STAUT sends a TDLS Setup/Response/Confirm Frame, + * with all four AC flags set to 1 in QoS Info Field + * to STA 2, via the AP, + */ + if (IS_FEATURE_ENABLED( + prAdapter->rWifiVar.fgTdlsBufferSTASleep)) + prIeWmmParam->ucQosInfo = (0x0F & + WMM_QOS_INFO_PARAM_SET_CNT); + else + prIeWmmParam->ucQosInfo = (prBssInfo->ucWmmParamSetCount & + WMM_QOS_INFO_PARAM_SET_CNT); + + /* UAPSD initial queue configurations (delivery and trigger enabled) */ + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucUapsd)) + prIeWmmParam->ucQosInfo |= WMM_QOS_INFO_UAPSD; + + /* EDCA parameter */ + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prAcParam = &prIeWmmParam->arAcParam[eAci]; + /* ACI */ + prAcParam->ucAciAifsn = aucACI[eAci]; + /* ACM */ + if (prBssInfo->arACQueParmsForBcast[eAci].ucIsACMSet) + prAcParam->ucAciAifsn |= WMM_ACIAIFSN_ACM; + /* AIFSN */ + prAcParam->ucAciAifsn |= + (prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn & + WMM_ACIAIFSN_AIFSN); + + /* ECW Min */ + prAcParam->ucEcw = (prBssInfo->aucCWminLog2ForBcast[eAci] & + WMM_ECW_WMIN_MASK); + /* ECW Max */ + prAcParam->ucEcw |= + ((prBssInfo->aucCWmaxLog2ForBcast[eAci] << + WMM_ECW_WMAX_OFFSET) & WMM_ECW_WMAX_MASK); + + /* Txop limit */ + WLAN_SET_FIELD_16(&prAcParam->u2TxopLimit, + prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit); + + } + + /* Increment the total IE length + * for the Element ID and Length fields. + */ + return IE_SIZE(prIeWmmParam); + +} + +#endif + +u_int8_t isProbeResponse(IN struct MSDU_INFO *prMgmtTxMsdu) +{ + struct WLAN_MAC_HEADER *prWlanHdr = + (struct WLAN_MAC_HEADER *) NULL; + + prWlanHdr = + (struct WLAN_MAC_HEADER *) ((unsigned long) + prMgmtTxMsdu->prPacket + MAC_TX_RESERVED_FIELD); + + return (prWlanHdr->u2FrameCtrl & MASK_FRAME_TYPE) == + MAC_FRAME_PROBE_RSP ? TRUE : FALSE; +} + + +enum ENUM_FRAME_ACTION qmGetFrameAction(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN uint8_t ucStaRecIdx, IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_FRAME_TYPE_IN_CMD_Q eFrameType, + IN uint16_t u2FrameLength) +{ + enum ENUM_FRAME_ACTION eFrameAction = FRAME_ACTION_TX_PKT; + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint8_t ucTC = nicTxGetFrameResourceType(eFrameType, prMsduInfo); + uint16_t u2FreeResource = nicTxGetResource(prAdapter, ucTC); + uint8_t ucReqResource; + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; + + DEBUGFUNC("qmGetFrameAction"); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, ucStaRecIdx); + + do { + /* 4 <1> Tx, if FORCE_TX is set */ + if (prMsduInfo) { + if (prMsduInfo->ucControlFlag & + MSDU_CONTROL_FLAG_FORCE_TX) { + eFrameAction = FRAME_ACTION_TX_PKT; + break; + } + } + /* 4 <2> Drop, if BSS is inactive */ + if (!IS_BSS_ACTIVE(prBssInfo)) { + DBGLOG(QM, TRACE, + "Drop packets (BSS[%u] is INACTIVE)\n", + prBssInfo->ucBssIndex); + eFrameAction = FRAME_ACTION_DROP_PKT; + break; + } + + /* 4 <3> Queue, if BSS is absent, drop probe response */ + if (prBssInfo->fgIsNetAbsent) { + if (prMsduInfo && isProbeResponse(prMsduInfo)) { + DBGLOG(TX, TRACE, + "Drop probe response (BSS[%u] Absent)\n", + prBssInfo->ucBssIndex); + + eFrameAction = FRAME_ACTION_DROP_PKT; + } else { + DBGLOG(TX, TRACE, + "Queue packets (BSS[%u] Absent)\n", + prBssInfo->ucBssIndex); + eFrameAction = FRAME_ACTION_QUEUE_PKT; + } + break; + } + + /* 4 <4> Check based on StaRec */ + if (prStaRec) { + /* 4 <4.1> Drop, if StaRec is not in use */ + if (!prStaRec->fgIsInUse) { + DBGLOG(QM, TRACE, + "Drop packets (Sta[%u] not in USE)\n", + prStaRec->ucIndex); + eFrameAction = FRAME_ACTION_DROP_PKT; + break; + } + /* 4 <4.2> Sta in PS */ + if (prStaRec->fgIsInPS) { + ucReqResource = nicTxGetPageCount(prAdapter, + u2FrameLength, FALSE) + + prWifiVar->ucCmdRsvResource + + QM_MGMT_QUEUED_THRESHOLD; + + /* 4 <4.2.1> Tx, if resource is enough */ + if (u2FreeResource > ucReqResource) { + eFrameAction = FRAME_ACTION_TX_PKT; + break; + } + /* 4 <4.2.2> Queue, if resource is not enough */ + else { + DBGLOG(QM, INFO, + "Queue packets (Sta[%u] in PS)\n", + prStaRec->ucIndex); + eFrameAction = FRAME_ACTION_QUEUE_PKT; + break; + } + } + } + + } while (FALSE); + + /* <5> Resource CHECK! */ + /* <5.1> Reserve resource for CMD & 1X */ + if (eFrameType == FRAME_TYPE_MMPDU) { + ucReqResource = nicTxGetPageCount(prAdapter, u2FrameLength, + FALSE) + prWifiVar->ucCmdRsvResource; + + if (u2FreeResource < ucReqResource) { + eFrameAction = FRAME_ACTION_QUEUE_PKT; + DBGLOG(QM, INFO, + "Queue MGMT (MSDU[0x%p] Req/Rsv/Free[%u/%u/%u])\n", + prMsduInfo, + nicTxGetPageCount(prAdapter, + u2FrameLength, FALSE), + prWifiVar->ucCmdRsvResource, u2FreeResource); + } + + /* <6> Timeout check! */ +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + if ((eFrameAction == FRAME_ACTION_QUEUE_PKT) && prMsduInfo) { + OS_SYSTIME rCurrentTime, rEnqTime; + + GET_CURRENT_SYSTIME(&rCurrentTime); + rEnqTime = prMsduInfo->rPktProfile.rEnqueueTimestamp; + + if (CHECK_FOR_TIMEOUT(rCurrentTime, rEnqTime, + MSEC_TO_SYSTIME( + prWifiVar->u4MgmtQueueDelayTimeout))) { + eFrameAction = FRAME_ACTION_DROP_PKT; + log_dbg(QM, INFO, "Drop MGMT (MSDU[0x%p] timeout[%ums])\n", + prMsduInfo, + prWifiVar->u4MgmtQueueDelayTimeout); + } + } +#endif + } + + return eFrameAction; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct EVENT_BSS_ABSENCE_PRESENCE *prEventBssStatus; + struct BSS_INFO *prBssInfo; + u_int8_t fgIsNetAbsentOld; + struct GLUE_INFO *glue = prAdapter->prGlueInfo; + struct GL_HIF_INFO *hif = &glue->rHifInfo; + char *pos = NULL, *end = NULL; + char buf[512]; + int i; + + prEventBssStatus = (struct EVENT_BSS_ABSENCE_PRESENCE *) ( + prEvent->aucBuffer); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prEventBssStatus->ucBssIndex); + fgIsNetAbsentOld = prBssInfo->fgIsNetAbsent; + prBssInfo->fgIsNetAbsent = prEventBssStatus->ucIsAbsent; + prBssInfo->ucBssFreeQuota = prEventBssStatus->ucBssFreeQuota; + + memset(buf, 0, sizeof(buf)); + pos = buf; + end = pos + sizeof(buf); + for (i = 0; i < NUM_OF_TX_RING; ++i) { + pos += kalSnprintf(pos, end - pos, "[%u]", + hif->TxRing[i].u4UsedCnt); + } + + DBGLOG(QM, INFO, "NAF:B=%d,A=%d,F=%d used=%d %s\n", + prEventBssStatus->ucBssIndex, prBssInfo->fgIsNetAbsent, + prBssInfo->ucBssFreeQuota, hif->rTokenInfo.u4UsedCnt, buf); + + if (!prBssInfo->fgIsNetAbsent) { + /* ToDo:: QM_DBG_CNT_INC */ + QM_DBG_CNT_INC(&(prAdapter->rQM), QM_DBG_CNT_27); + } else { + /* ToDo:: QM_DBG_CNT_INC */ + QM_DBG_CNT_INC(&(prAdapter->rQM), QM_DBG_CNT_28); + } + /* From Absent to Present */ + if ((fgIsNetAbsentOld) && (!prBssInfo->fgIsNetAbsent)) { + if (HAL_IS_TX_DIRECT(prAdapter)) + nicTxDirectStartCheckQTimer(prAdapter); + else { +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + prAdapter->rQM.fgForceReassign = TRUE; +#endif + kalSetEvent(prAdapter->prGlueInfo); + kalSetTxEvent2Hif(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 struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct EVENT_STA_CHANGE_PS_MODE *prEventStaChangePsMode; + struct STA_RECORD *prStaRec; + u_int8_t fgIsInPSOld; + + /* DbgPrint("QM:Event -RxBa\n"); */ + + prEventStaChangePsMode = (struct EVENT_STA_CHANGE_PS_MODE *) + (prEvent->aucBuffer); + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, + prEventStaChangePsMode->ucStaRecIdx); + /* ASSERT(prStaRec); */ + + if (prStaRec) { + + fgIsInPSOld = prStaRec->fgIsInPS; + prStaRec->fgIsInPS = prEventStaChangePsMode->ucIsInPs; + + qmUpdateFreeQuota(prAdapter, + prStaRec, + prEventStaChangePsMode->ucUpdateMode, + prEventStaChangePsMode->ucFreeQuota); + + DBGLOG(QM, INFO, "PS=%d,%d\n", + prEventStaChangePsMode->ucStaRecIdx, + prStaRec->fgIsInPS); + + /* From PS to Awake */ + if ((fgIsInPSOld) && (!prStaRec->fgIsInPS)) { + if (HAL_IS_TX_DIRECT(prAdapter)) + nicTxDirectStartCheckQTimer(prAdapter); + else { +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + prAdapter->rQM.fgForceReassign = TRUE; +#endif + 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 struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct EVENT_STA_UPDATE_FREE_QUOTA + *prEventStaUpdateFreeQuota; + struct STA_RECORD *prStaRec; + + prEventStaUpdateFreeQuota = (struct + EVENT_STA_UPDATE_FREE_QUOTA *) (prEvent->aucBuffer); + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, + prEventStaUpdateFreeQuota->ucStaRecIdx); + /* 2013/08/30 + * Station Record possible been freed. + */ + /* ASSERT(prStaRec); */ + + if (prStaRec) { + if (prStaRec->fgIsInPS) { + qmUpdateFreeQuota(prAdapter, + prStaRec, + prEventStaUpdateFreeQuota->ucUpdateMode, + prEventStaUpdateFreeQuota->ucFreeQuota); + + if (HAL_IS_TX_DIRECT(prAdapter)) + nicTxDirectStartCheckQTimer(prAdapter); + else + kalSetEvent(prAdapter->prGlueInfo); + } + 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 struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, IN uint8_t ucUpdateMode, + IN uint8_t ucFreeQuota) +{ + + uint8_t ucFreeQuotaForNonDelivery; + uint8_t 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t qmGetRxReorderQueuedBufferCount(IN struct ADAPTER *prAdapter) +{ + uint32_t i, u4Total; + struct QUE_MGT *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; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Dump current queue status + * + * \param[in] (none) + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +uint32_t qmDumpQueueStatus(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, IN uint32_t u4Max) +{ + struct TX_CTRL *prTxCtrl; + struct QUE_MGT *prQM; + struct GLUE_INFO *prGlueInfo; + uint32_t i, u4TotalBufferCount, u4TotalPageCount; + uint32_t u4CurBufferCount, u4CurPageCount; + uint32_t u4Len = 0; + + DEBUGFUNC(("%s", __func__)); + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + prQM = &prAdapter->rQM; + prGlueInfo = prAdapter->prGlueInfo; + u4TotalBufferCount = 0; + u4TotalPageCount = 0; + u4CurBufferCount = 0; + u4CurPageCount = 0; + + LOGBUF(pucBuf, u4Max, u4Len, "\n"); + LOGBUF(pucBuf, u4Max, u4Len, + "------------\n"); + + for (i = TC0_INDEX; i < TC_NUM; i++) { + LOGBUF(pucBuf, u4Max, u4Len, + "TC%u ResCount: Max[%02u/%03u] Free[%02u/%03u] PreUsed[%03u]\n", + i, prTxCtrl->rTc.au4MaxNumOfBuffer[i], + prTxCtrl->rTc.au4MaxNumOfPage[i], + prTxCtrl->rTc.au4FreeBufferCount[i], + prTxCtrl->rTc.au4FreePageCount[i], + prTxCtrl->rTc.au4PreUsedPageCount[i]); + + u4TotalBufferCount += prTxCtrl->rTc.au4MaxNumOfBuffer[i]; + u4TotalPageCount += prTxCtrl->rTc.au4MaxNumOfPage[i]; + u4CurBufferCount += prTxCtrl->rTc.au4FreeBufferCount[i]; + u4CurPageCount += prTxCtrl->rTc.au4FreePageCount[i]; + } + + LOGBUF(pucBuf, u4Max, u4Len, + "ToT ResCount: Max[%02u/%03u] Free[%02u/%03u]\n", + u4TotalBufferCount, u4TotalPageCount, u4CurBufferCount, + u4CurPageCount); + + u4TotalBufferCount = 0; + u4TotalPageCount = 0; + u4CurBufferCount = 0; + u4CurPageCount = 0; + LOGBUF(pucBuf, u4Max, u4Len, + "------------\n"); + + for (i = TC0_INDEX; i < TC_NUM; i++) { + LOGBUF(pucBuf, u4Max, u4Len, + "TC%u ResCount: Max[%02u/%03u] Free[%02u/%03u] PreUsed[%03u]\n", + i, prTxCtrl->rTc.au4MaxNumOfBuffer_PLE[i], + prTxCtrl->rTc.au4MaxNumOfPage_PLE[i], + prTxCtrl->rTc.au4FreeBufferCount_PLE[i], + prTxCtrl->rTc.au4FreePageCount_PLE[i], + prTxCtrl->rTc.au4PreUsedPageCount[i]); + + u4TotalBufferCount += prTxCtrl->rTc.au4MaxNumOfBuffer_PLE[i]; + u4TotalPageCount += prTxCtrl->rTc.au4MaxNumOfPage_PLE[i]; + u4CurBufferCount += prTxCtrl->rTc.au4FreeBufferCount_PLE[i]; + u4CurPageCount += prTxCtrl->rTc.au4FreePageCount_PLE[i]; + } + + LOGBUF(pucBuf, u4Max, u4Len, + "ToT ResCount: Max[%02u/%03u] Free[%02u/%03u]\n", + u4TotalBufferCount, u4TotalPageCount, u4CurBufferCount, + u4CurPageCount); + + LOGBUF(pucBuf, u4Max, u4Len, + "---------------------------------\n"); + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + for (i = TC0_INDEX; i < TC_NUM; i++) { + LOGBUF(pucBuf, u4Max, u4Len, + "TC%u AvgQLen[%04u] minRsv[%02u] CurTcRes[%02u] GrtdTcRes[%02u]\n", + i, QM_GET_TX_QUEUE_LEN(prAdapter, i), + prQM->au4MinReservedTcResource[i], + prQM->au4CurrentTcResource[i], + prQM->au4GuaranteedTcResource[i]); + } + + LOGBUF(pucBuf, u4Max, u4Len, + "Resource Residual[%u] ExtraRsv[%u]\n", + prQM->u4ResidualTcResource, + prQM->u4ExtraReservedTcResource); + LOGBUF(pucBuf, u4Max, u4Len, + "QueLenMovingAvg[%u] Time2AdjResource[%u] Time2UpdateQLen[%u]\n", + prQM->u4QueLenMovingAverage, prQM->u4TimeToAdjustTcResource, + prQM->u4TimeToUpdateQueLen); +#endif + + DBGLOG(SW4, INFO, "---------------------------------\n"); + +#if QM_FORWARDING_FAIRNESS + for (i = 0; i < NUM_OF_PER_STA_TX_QUEUES; i++) { + LOGBUF(pucBuf, u4Max, u4Len, + "TC%u HeadSta[%u] ResourceUsedCount[%u]\n", + i, prQM->au4HeadStaRecIndex[i], + prQM->au4ResourceUsedCount[i]); + } +#endif + + LOGBUF(pucBuf, u4Max, u4Len, + "BMC or unknown TxQueue Len[%u]\n", + prQM->arTxQueue[0].u4NumElem); + LOGBUF(pucBuf, u4Max, u4Len, + "Pending QLen Normal[%u] Sec[%u] Cmd[%u]\n", + GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum), + GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum), + GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingCmdNum)); + +#if defined(LINUX) + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + LOGBUF(pucBuf, u4Max, u4Len, + "Pending BSS[%u] QLen[%u:%u:%u:%u]\n", i, + prGlueInfo->ai4TxPendingFrameNumPerQueue[i][0], + prGlueInfo->ai4TxPendingFrameNumPerQueue[i][1], + prGlueInfo->ai4TxPendingFrameNumPerQueue[i][2], + prGlueInfo->ai4TxPendingFrameNumPerQueue[i][3]); + } +#endif + LOGBUF(pucBuf, u4Max, u4Len, "Pending FWD CNT[%d]\n", + prTxCtrl->i4PendingFwdFrameCount); + LOGBUF(pucBuf, u4Max, u4Len, "Pending MGMT CNT[%d]\n", + prTxCtrl->i4TxMgmtPendingNum); + + LOGBUF(pucBuf, u4Max, u4Len, + "---------------------------------\n"); + + LOGBUF(pucBuf, u4Max, u4Len, "Total RFB[%u]\n", + CFG_RX_MAX_PKT_NUM); + LOGBUF(pucBuf, u4Max, u4Len, "rFreeSwRfbList[%u]\n", + prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem); + LOGBUF(pucBuf, u4Max, u4Len, "rReceivedRfbList[%u]\n", + prAdapter->rRxCtrl.rReceivedRfbList.u4NumElem); + LOGBUF(pucBuf, u4Max, u4Len, "rIndicatedRfbList[%u]\n", + prAdapter->rRxCtrl.rIndicatedRfbList.u4NumElem); + LOGBUF(pucBuf, u4Max, u4Len, "ucNumIndPacket[%u]\n", + prAdapter->rRxCtrl.ucNumIndPacket); + LOGBUF(pucBuf, u4Max, u4Len, "ucNumRetainedPacket[%u]\n", + prAdapter->rRxCtrl.ucNumRetainedPacket); + + LOGBUF(pucBuf, u4Max, u4Len, + "---------------------------------\n"); + LOGBUF(pucBuf, u4Max, u4Len, + "CMD: Free[%u/%u] PQ[%u] CQ[%u] TCQ[%u] TCDQ[%u]\n", + prAdapter->rFreeCmdList.u4NumElem, + CFG_TX_MAX_CMD_PKT_NUM, + prAdapter->rPendingCmdQueue.u4NumElem, + prGlueInfo->rCmdQueue.u4NumElem, + prAdapter->rTxCmdQueue.u4NumElem, + prAdapter->rTxCmdDoneQueue.u4NumElem); + LOGBUF(pucBuf, u4Max, u4Len, + "MSDU: Free[%u/%u] Pending[%u] Done[%u]\n", + prAdapter->rTxCtrl.rFreeMsduInfoList.u4NumElem, + CFG_TX_MAX_PKT_NUM, + prAdapter->rTxCtrl.rTxMgmtTxingQueue.u4NumElem, + prAdapter->rTxDataDoneQueue.u4NumElem); + + LOGBUF(pucBuf, u4Max, u4Len, + "---------------------------------\n"); + if (prGlueInfo->rCmdQueue.u4NumElem > 0) + cmdBufDumpCmdQueue(&prGlueInfo->rCmdQueue, + "waiting Tx CMD queue"); + + return u4Len; +} + +#if CFG_M0VE_BA_TO_DRIVER +/*----------------------------------------------------------------------------*/ +/*! + * @brief Send DELBA Action frame + * + * @param fgIsInitiator DELBA_ROLE_INITIATOR or DELBA_ROLE_RECIPIENT + * @param prStaRec Pointer to the STA_REC of the receiving peer + * @param u4Tid TID of the BA entry + * @param u4ReasonCode The reason code carried in the Action frame + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void +mqmSendDelBaFrame(IN struct ADAPTER *prAdapter, + IN u_int8_t fgIsInitiator, IN struct STA_RECORD *prStaRec, + IN uint32_t u4Tid, IN uint32_t u4ReasonCode) +{ + + struct MSDU_INFO *prTxMsduInfo; + struct ACTION_DELBA_FRAME *prDelBaFrame; + struct BSS_INFO *prBssInfo; + + DBGLOG(QM, WARN, "[Puff]: Enter mqmSendDelBaFrame()\n"); + + ASSERT(prStaRec); + + /* 3 <1> Block the message in case of invalid STA */ + if (!prStaRec->fgIsInUse) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) sta_rec is not inuse\n", + __func__); + return; + } + /* Check HT-capabale STA */ + if (!(prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_HT)) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) sta is NOT HT-capable(0x%08X)\n", + __func__, + prStaRec->ucDesiredPhyTypeSet); + return; + } + /* 4 <2> Construct the DELBA frame */ + prTxMsduInfo = (struct MSDU_INFO *) cnmMgtPktAlloc( + prAdapter, ACTION_DELBA_FRAME_LEN); + + if (!prTxMsduInfo) { + log_dbg(QM, WARN, "[Puff][%s]: (Warning) DELBA for TID=%ld was not sent (MSDU_INFO alloc failure)\n", + __func__, u4Tid); + return; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + /* Fill the Action frame */ + prDelBaFrame = (struct ACTION_DELBA_FRAME *) + ((uint32_t) (prTxMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + prDelBaFrame->u2FrameCtrl = MAC_FRAME_ACTION; +#if CFG_SUPPORT_802_11W + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) DELBA is 80211w enabled\n", + __func__); + prDelBaFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + } +#endif + + prDelBaFrame->u2DurationID = 0; + prDelBaFrame->ucCategory = CATEGORY_BLOCK_ACK_ACTION; + prDelBaFrame->ucAction = ACTION_DELBA; + + prDelBaFrame->u2DelBaParameterSet = 0; + prDelBaFrame->u2DelBaParameterSet |= ((fgIsInitiator ? + ACTION_DELBA_INITIATOR_MASK : 0)); + prDelBaFrame->u2DelBaParameterSet |= ((u4Tid << + ACTION_DELBA_TID_OFFSET) & ACTION_DELBA_TID_MASK); + prDelBaFrame->u2ReasonCode = u4ReasonCode; + + COPY_MAC_ADDR(prDelBaFrame->aucDestAddr, + prStaRec->aucMacAddr); + COPY_MAC_ADDR(prDelBaFrame->aucSrcAddr, + prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prDelBaFrame->aucBSSID, prBssInfo->aucBSSID); + + /* 4 <3> Configure the MSDU_INFO and forward it to TXM */ + TX_SET_MMPDU(prAdapter, + prTxMsduInfo, + prStaRec->ucBssIndex, + (prStaRec != NULL) ? (prStaRec->ucIndex) : + (STA_REC_INDEX_NOT_FOUND), + WLAN_MAC_HEADER_LEN, ACTION_DELBA_FRAME_LEN, NULL, + MSDU_RATE_MODE_AUTO); + + /* TID and fgIsInitiator are needed + * when processing TX Done of the DELBA frame + */ + prTxMsduInfo->ucTID = (uint8_t) u4Tid; + prTxMsduInfo->ucControlFlag = (fgIsInitiator ? 1 : 0); + + nicTxEnqueueMsdu(prAdapter, prTxMsduInfo); + + DBGLOG(QM, WARN, + "[Puff][%s]: Send DELBA for TID=%ld Initiator=%d\n", + __func__, u4Tid, fgIsInitiator); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Callback function for the TX Done event for an ADDBA_RSP + * + * @param prMsduInfo The TX packet + * @param rWlanStatus WLAN_STATUS_SUCCESS if TX is successful + * + * @return WLAN_STATUS_BUFFER_RETAINED is returned if the buffer shall not be + * freed by TXM + */ +/*----------------------------------------------------------------------------*/ +uint32_t +mqmCallbackAddBaRspSent(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + struct RX_BA_ENTRY *prRxBaEntry; + struct STA_RECORD *prStaRec; + struct QUE_MGT *prQM; + + uint32_t u4Tid = 0; + + /* ASSERT(prMsduInfo); */ + prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + prQM = &prAdapter->rQM; + + DBGLOG(QM, WARN, + "[Puff]: Enter mqmCallbackAddBaRspSent()\n"); + + /* 4 <0> Check STA_REC status */ + /* Check STA_REC is inuse */ + if (!prStaRec->fgIsInUse) { + DBGLOG(QM, WARN, "[Puff][%s]: (Warning) sta_rec is not inuse\n", + __func__); + return WLAN_STATUS_SUCCESS; + } + /* Check HT-capabale STA */ + if (!(prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_HT)) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) sta is NOT HT-capable(0x%08X)\n", + __func__, + prStaRec->ucDesiredPhyTypeSet); + /* To free the received ADDBA_REQ directly */ + return WLAN_STATUS_SUCCESS; + } + /* 4 <1> Find the corresponding BA entry */ + /* TID is stored in MSDU_INFO when composing the ADDBA_RSP frame */ + u4Tid = prMsduInfo->ucTID; + prRxBaEntry = &prQM->arRxBaTable[u4Tid]; + + /* Note: Due to some reason, for example, receiving a DELBA, + * the BA entry may not be in state NEGO + */ + /* 4 <2> INVALID state */ + if (!prRxBaEntry) { + log_dbg(QM, WARN, "[Puff][%s]: (RX_BA) ADDBA_RSP ---> peer (STA=%d TID=%d)(TX successful)(invalid BA)\n", + __func__, prStaRec->ucIndex, u4Tid); + } + /* 4 <3> NEGO, ACTIVE, or DELETING state */ + else { + switch (rTxDoneStatus) { + /* 4 TX Success */ + case TX_RESULT_SUCCESS: + + DBGLOG(QM, WARN, + "[Puff][%s]: (RX_BA) ADDBA_RSP ---> peer (STA=%d TID=%d)(TX successful)\n", + __func__, prStaRec->ucIndex, u4Tid); + + /* 4 NEGO or ACTIVE state */ + if (prRxBaEntry->ucStatus != BA_ENTRY_STATUS_DELETING) + mqmRxModifyBaEntryStatus(prAdapter, prRxBaEntry, + BA_ENTRY_STATUS_ACTIVE); + break; + + /* 4 TX Failure */ + default: + + log_dbg(QM, WARN, "[Puff][%s]: (RX_BA) ADDBA_RSP ---> peer (STA=%d TID=%ld Entry_Status=%d)(TX failed)\n", + __func__, prStaRec->ucIndex, + u4Tid, prRxBaEntry->ucStatus); + + /* 4 NEGO or ACTIVE state */ + /* Notify the host to delete the agreement */ + if (prRxBaEntry->ucStatus != BA_ENTRY_STATUS_DELETING) { + mqmRxModifyBaEntryStatus(prAdapter, prRxBaEntry, + BA_ENTRY_STATUS_DELETING); + + /* Send DELBA to the peer to ensure + * the BA state is synchronized + */ + mqmSendDelBaFrame(prAdapter, + DELBA_ROLE_RECIPIENT, + prStaRec, u4Tid, + STATUS_CODE_UNSPECIFIED_FAILURE); + } + break; + } + + } + + return WLAN_STATUS_SUCCESS; /* TXM shall release the packet */ + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Check if there is any idle RX BA + * + * @param u4Param (not used) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void mqmTimeoutCheckIdleRxBa(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr) +{ + int8_t i; + struct RX_BA_ENTRY *prRxBa; + uint32_t u4IdleCountThreshold = 0; + struct STA_RECORD *prStaRec; + struct QUE_MGT *prQM; + + DBGLOG(QM, WARN, + "[Puff]: Enter mqmTimeoutIdleRxBaDetection()\n"); + + prQM = &prAdapter->rQM; + + /* 4 <1> Restart the timer */ + cnmTimerStopTimer(prAdapter, + &prAdapter->rMqmIdleRxBaDetectionTimer); + cnmTimerStartTimer(prAdapter, + &prAdapter->rMqmIdleRxBaDetectionTimer, + MQM_IDLE_RX_BA_CHECK_INTERVAL); + + /* 4 <2> Increment the idle count for each idle BA */ + for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) { + + prRxBa = &prQM->arRxBaTable[i]; + + if (prRxBa->ucStatus == BA_ENTRY_STATUS_ACTIVE) { + + prStaRec = cnmGetStaRecByIndex(prAdapter, + prRxBa->ucStaRecIdx); + + if (!prStaRec->fgIsInUse) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) sta_rec is not inuse\n", + __func__); + ASSERT(0); + } + /* Check HT-capabale STA */ + if (!(prStaRec->ucDesiredPhyTypeSet & + PHY_TYPE_BIT_HT)) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) sta is NOT HT-capable(0x%08X)\n", + __func__, + prStaRec->ucDesiredPhyTypeSet); + ASSERT(0); + } + /* 4 <2.1> Idle detected, increment idle count + * and see if a DELBA should be sent + */ + if (prRxBa->u2SnapShotSN == + prStaRec->au2CachedSeqCtrl[prRxBa->ucTid]) { + + prRxBa->ucIdleCount++; + + ASSERT(prRxBa->ucTid < 8); + switch (aucTid2ACI[prRxBa->ucTid]) { + case 0: /* BK */ + u4IdleCountThreshold = + MQM_DEL_IDLE_RXBA_THRESHOLD_BK; + break; + case 1: /* BE */ + u4IdleCountThreshold = + MQM_DEL_IDLE_RXBA_THRESHOLD_BE; + break; + case 2: /* VI */ + u4IdleCountThreshold = + MQM_DEL_IDLE_RXBA_THRESHOLD_VI; + break; + case 3: /* VO */ + u4IdleCountThreshold = + MQM_DEL_IDLE_RXBA_THRESHOLD_VO; + break; + } + + if (prRxBa->ucIdleCount >= + u4IdleCountThreshold) { + mqmRxModifyBaEntryStatus(prAdapter, + prRxBa, + BA_ENTRY_STATUS_INVALID); + mqmSendDelBaFrame(prAdapter, + DELBA_ROLE_RECIPIENT, prStaRec, + (uint32_t) prRxBa->ucTid, + REASON_CODE_PEER_TIME_OUT); + qmDelRxBaEntry(prAdapter, + prStaRec->ucIndex, + prRxBa->ucTid, TRUE); + } + } + /* 4 <2.2> Activity detected */ + else { + prRxBa->u2SnapShotSN = + prStaRec->au2CachedSeqCtrl[ + prRxBa->ucTid]; + prRxBa->ucIdleCount = 0; + continue; /* check the next BA entry */ + } + } + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Do RX BA entry state transition + * + * @param prRxBaEntry The BA entry pointer + * @param eStatus The state to transition to + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void +mqmRxModifyBaEntryStatus(IN struct ADAPTER *prAdapter, + IN struct RX_BA_ENTRY *prRxBaEntry, + IN enum ENUM_BA_ENTRY_STATUS eStatus) +{ + struct STA_RECORD *prStaRec; + struct QUE_MGT *prQM; + + u_int8_t fgResetScoreBoard = FALSE; + + ASSERT(prRxBaEntry); + + prStaRec = cnmGetStaRecByIndex(prAdapter, + prRxBaEntry->ucStaRecIdx); + ASSERT(prStaRec); + prQM = &prAdapter->rQM; + + if (prRxBaEntry->ucStatus == (uint8_t) eStatus) { + DBGLOG(QM, WARN, "[Puff][%s]: eStatus are identical...\n", + __func__, prRxBaEntry->ucStatus); + return; + } + /* 4 <1> State transition from state X */ + switch (prRxBaEntry->ucStatus) { + + /* 4 <1.1> From (X = INVALID) to (ACTIVE or NEGO or DELETING) */ + case BA_ENTRY_STATUS_INVALID: + + /* Associate the BA entry with the STA_REC + * when leaving INVALID state + */ + kalMemCopy(&prQM->arRxBaTable[prRxBaEntry->ucTid], + prRxBaEntry, sizeof(struct RX_BA_ENTRY)); + + /* Increment the RX BA counter */ + prQM->ucRxBaCount++; + ASSERT(prQM->ucRxBaCount <= CFG_NUM_OF_RX_BA_AGREEMENTS); + + /* Since AMPDU may be received during INVALID state */ + fgResetScoreBoard = TRUE; + + /* Reset Idle Count since this BA entry is being activated now. + * Note: If there is no ACTIVE entry, + * the idle detection timer will not be started. + */ + prRxBaEntry->ucIdleCount = 0; + break; + + /* 4 <1.2> Other cases */ + default: + break; + } + + /* 4 <2> State trasition to state Y */ + switch (eStatus) { + + /* 4 <2.1> From (NEGO, ACTIVE, DELETING) to (Y=INVALID) */ + case BA_ENTRY_STATUS_INVALID: + + /* Disassociate the BA entry with the STA_REC */ + kalMemZero(&prQM->arRxBaTable[prRxBaEntry->ucTid], + sizeof(struct RX_BA_ENTRY)); + + /* Decrement the RX BA counter */ + prQM->ucRxBaCount--; + ASSERT(prQM->ucRxBaCount < CFG_NUM_OF_RX_BA_AGREEMENTS); + + /* (TBC) */ + fgResetScoreBoard = TRUE; + + /* If there is not any BA agreement, + * stop doing idle detection + */ + if (prQM->ucRxBaCount == 0) { + if (MQM_CHECK_FLAG(prAdapter->u4FlagBitmap, + MQM_FLAG_IDLE_RX_BA_TIMER_STARTED)) { + cnmTimerStopTimer(prAdapter, + &prAdapter->rMqmIdleRxBaDetectionTimer); + MQM_CLEAR_FLAG(prAdapter->u4FlagBitmap, + MQM_FLAG_IDLE_RX_BA_TIMER_STARTED); + } + } + + break; + + /* 4 <2.2> From (any) to (Y=ACTIVE) */ + case BA_ENTRY_STATUS_ACTIVE: + + /* If there is at least one BA going into ACTIVE, + * start idle detection + */ + if (!MQM_CHECK_FLAG(prAdapter->u4FlagBitmap, + MQM_FLAG_IDLE_RX_BA_TIMER_STARTED)) { + cnmTimerInitTimer(prAdapter, + &prAdapter->rMqmIdleRxBaDetectionTimer, + (PFN_MGMT_TIMEOUT_FUNC) mqmTimeoutCheckIdleRxBa, + (unsigned long) NULL); + /* No parameter */ + + cnmTimerStopTimer(prAdapter, + &prAdapter->rMqmIdleRxBaDetectionTimer); + +#if MQM_IDLE_RX_BA_DETECTION + cnmTimerStartTimer(prAdapter, + &prAdapter->rMqmIdleRxBaDetectionTimer, + MQM_IDLE_RX_BA_CHECK_INTERVAL); + MQM_SET_FLAG(prAdapter->u4FlagBitmap, + MQM_FLAG_IDLE_RX_BA_TIMER_STARTED); +#endif + } + + break; + + case BA_ENTRY_STATUS_NEGO: + default: + break; + } + + if (fgResetScoreBoard) { + struct CMD_RESET_BA_SCOREBOARD *prCmdBody; + + prCmdBody = (struct CMD_RESET_BA_SCOREBOARD *) + cnmMemAlloc(prAdapter, RAM_TYPE_BUF, + sizeof(struct CMD_RESET_BA_SCOREBOARD)); + ASSERT(prCmdBody); + + prCmdBody->ucflag = MAC_ADDR_TID_MATCH; + prCmdBody->ucTID = prRxBaEntry->ucTid; + kalMemCopy(prCmdBody->aucMacAddr, prStaRec->aucMacAddr, + PARAM_MAC_ADDR_LEN); + + wlanoidResetBAScoreboard(prAdapter, prCmdBody, + sizeof(struct CMD_RESET_BA_SCOREBOARD)); + + cnmMemFree(prAdapter, prCmdBody); + } + + DBGLOG(QM, WARN, + "[Puff]QM: (RX_BA) [STA=%d TID=%d] status from %d to %d\n", + prRxBaEntry->ucStaRecIdx, prRxBaEntry->ucTid, + prRxBaEntry->ucStatus, eStatus); + + prRxBaEntry->ucStatus = (uint8_t) eStatus; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void mqmHandleAddBaReq(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + struct ACTION_ADDBA_REQ_FRAME *prAddBaReq; + struct ACTION_ADDBA_REQ_BODY rAddBaReqBody; + struct ACTION_ADDBA_RSP_FRAME *prAddBaRsp; + struct ACTION_ADDBA_RSP_BODY rAddBaRspBody; + struct RX_BA_ENTRY *prRxBaEntry; + struct MSDU_INFO *prTxMsduInfo; + struct QUE_MGT *prQM; + + /* Reject or accept the ADDBA_REQ */ + u_int8_t fgIsReqAccepted = TRUE; + /* Indicator: Whether a new RX BA entry will be added */ + u_int8_t fgIsNewEntryAdded = FALSE; + + uint32_t u4Tid; + uint32_t u4StaRecIdx; + uint16_t u2WinStart; + uint16_t u2WinSize; + uint32_t u4BuffSize; + +#if CFG_SUPPORT_BCM + uint32_t u4BuffSizeBT; +#endif + + ASSERT(prSwRfb); + + prStaRec = prSwRfb->prStaRec; + prQM = &prAdapter->rQM; + + do { + + /* 4 <0> Check if this is an active HT-capable STA */ + /* Check STA_REC is inuse */ + if (!prStaRec->fgIsInUse) { + log_dbg(QM, WARN, "[Puff][%s]: (Warning) sta_rec is not inuse\n", + __func__); + break; + } + /* Check HT-capabale STA */ + if (!(prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_HT)) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) sta is NOT HT-capable(0x%08X)\n", + __func__, + prStaRec->ucDesiredPhyTypeSet); + break; /* To free the received ADDBA_REQ directly */ + } + /* 4 <1> Check user configurations and HW capabilities */ + /* Check configurations (QoS support, AMPDU RX support) */ + if ((!prAdapter->rWifiVar.fgSupportQoS) || + (!prAdapter->rWifiVar.fgSupportAmpduRx) || + (!prStaRec->fgRxAmpduEn)) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) BA ACK Policy not supported fgSupportQoS(%d)", + __func__, prAdapter->rWifiVar.fgSupportQoS); + DBGLOG(QM, WARN, + "fgSupportAmpduRx(%d), fgRxAmpduEn(%d)\n", + prAdapter->rWifiVar.fgSupportAmpduRx, + prStaRec->fgRxAmpduEn); + /* Will send an ADDBA_RSP with DECLINED */ + fgIsReqAccepted = FALSE; + } + /* Check capability */ + prAddBaReq = ((struct ACTION_ADDBA_REQ_FRAME *) ( + prSwRfb->pvHeader)); + kalMemCopy((uint8_t *) (&rAddBaReqBody), + (uint8_t *) (&(prAddBaReq->aucBAParameterSet[0])), + 6); + if ((((rAddBaReqBody.u2BAParameterSet) & + BA_PARAM_SET_ACK_POLICY_MASK) >> + BA_PARAM_SET_ACK_POLICY_MASK_OFFSET) + != BA_PARAM_SET_ACK_POLICY_IMMEDIATE_BA) { + /* Only Immediate_BA is supported */ + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) BA ACK Policy not supported (0x%08X)\n", + __func__, rAddBaReqBody.u2BAParameterSet); + /* Will send an ADDBA_RSP with DECLINED */ + fgIsReqAccepted = FALSE; + } + + /* 4 <2> Determine the RX BA entry (existing or to be added) */ + /* Note: BA entry index = (TID, STA_REC index) */ + u4Tid = (((rAddBaReqBody.u2BAParameterSet) & + BA_PARAM_SET_TID_MASK) >> + BA_PARAM_SET_TID_MASK_OFFSET); + u4StaRecIdx = prStaRec->ucIndex; + DBGLOG(QM, WARN, + "[Puff][%s]: BA entry index = [TID(%d), STA_REC index(%d)]\n", + __func__, u4Tid, u4StaRecIdx); + + u2WinStart = ((rAddBaReqBody.u2BAStartSeqCtrl) >> + OFFSET_BAR_SSC_SN); + u2WinSize = (((rAddBaReqBody.u2BAParameterSet) & + BA_PARAM_SET_BUFFER_SIZE_MASK) >> + BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET); + DBGLOG(QM, WARN, + "[Puff][%s]: BA entry info = [WinStart(%d), WinSize(%d)]\n", + __func__, u2WinStart, u2WinSize); + + if (fgIsReqAccepted) { + + prRxBaEntry = &prQM->arRxBaTable[u4Tid]; + + if (!prRxBaEntry) { + + /* 4 INVALID state && BA entry + * available --> Add a new entry and accept + */ + if (prQM->ucRxBaCount < + CFG_NUM_OF_RX_BA_AGREEMENTS) { + + fgIsNewEntryAdded = + qmAddRxBaEntry(prAdapter, + (uint8_t) u4StaRecIdx, + (uint8_t) u4Tid, u2WinStart, + u2WinSize); + + if (!fgIsNewEntryAdded) { + DBGLOG(QM, ERROR, + "[Puff][%s]: (Error) Free RX BA entry alloc failure\n"); + fgIsReqAccepted = FALSE; + } else { + log_dbg(QM, WARN, "[Puff][%s]: Create a new BA Entry\n"); + } + } + /* 4 INVALID state && BA entry + * unavailable --> Reject the ADDBA_REQ + */ + else { + log_dbg(QM, WARN, "[Puff][%s]: (Warning) Free RX BA entry unavailable(req: %d)\n", + __func__, prQM->ucRxBaCount); + /* Will send ADDBA_RSP with DECLINED */ + fgIsReqAccepted = FALSE; + } + } else { + + /* 4 NEGO or DELETING state --> + * Ignore the ADDBA_REQ + * For NEGO: do nothing. Wait for TX Done of + * ADDBA_RSP + * For DELETING: do nothing. Wait for TX Done + * of DELBA + */ + if (prRxBaEntry->ucStatus != + BA_ENTRY_STATUS_ACTIVE) { + /* Ignore the ADDBA_REQ since + * the current state is NEGO + */ + log_dbg(QM, WARN, "[Puff][%s]:(Warning)ADDBA_REQ for TID=%ld is received, status:%d)\n", + __func__, u4Tid, + prRxBaEntry->ucStatus); + break; + } + } + } + /* 4 <3> Construct the ADDBA_RSP frame */ + prTxMsduInfo = (struct MSDU_INFO *) cnmMgtPktAlloc( + prAdapter, ACTION_ADDBA_RSP_FRAME_LEN); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + if (!prTxMsduInfo) { + + /* The peer may send an ADDBA_REQ message later. + * Do nothing to the BA entry. No DELBA will be + * sent (because cnmMgtPktAlloc() may fail again). + * No BA deletion event will be sent to the host + * (because cnmMgtPktAlloc() may fail again). + */ + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) ADDBA_RSP alloc failure\n", + __func__); + + if (fgIsNewEntryAdded) { + /* If a new entry has been created due + * to this ADDBA_REQ, delete it + */ + ASSERT(prRxBaEntry); + mqmRxModifyBaEntryStatus(prAdapter, + prRxBaEntry, BA_ENTRY_STATUS_INVALID); + } + + break; /* Exit directly to free the ADDBA_REQ */ + } + + /* Fill the ADDBA_RSP message */ + prAddBaRsp = (struct ACTION_ADDBA_RSP_FRAME *) + ((uint32_t) (prTxMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + prAddBaRsp->u2FrameCtrl = MAC_FRAME_ACTION; + +#if CFG_SUPPORT_802_11W + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) ADDBA_RSP is 80211w enabled\n", + __func__); + prAddBaReq->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + } +#endif + prAddBaRsp->u2DurationID = 0; + prAddBaRsp->ucCategory = CATEGORY_BLOCK_ACK_ACTION; + prAddBaRsp->ucAction = ACTION_ADDBA_RSP; + prAddBaRsp->ucDialogToken = prAddBaReq->ucDialogToken; + + log_dbg(QM, WARN, "[Puff][%s]: (Warning) ADDBA_RSP DurationID(%d) Category(%d) Action(%d) DialogToken(%d)\n", + __func__, prAddBaRsp->u2DurationID, + prAddBaRsp->ucCategory, prAddBaRsp->ucAction, + prAddBaRsp->ucDialogToken); + + if (fgIsReqAccepted) + rAddBaRspBody.u2StatusCode = STATUS_CODE_SUCCESSFUL; + else + rAddBaRspBody.u2StatusCode = STATUS_CODE_REQ_DECLINED; + + /* WinSize = min(WinSize in ADDBA_REQ, CFG_RX_BA_MAX_WINSIZE) */ + u4BuffSize = (((rAddBaReqBody.u2BAParameterSet) & + BA_PARAM_SET_BUFFER_SIZE_MASK) >> + BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET); + + /*If ADDBA req WinSize<=0 => use default WinSize(16) */ + if ((u4BuffSize > CFG_RX_BA_MAX_WINSIZE) + || (u4BuffSize <= 0)) + u4BuffSize = CFG_RX_BA_MAX_WINSIZE; +#if CFG_SUPPORT_BCM + /* TODO: Call BT coexistence function to limit the winsize */ + u4BuffSizeBT = bcmRequestBaWinSize(); + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) bcmRequestBaWinSize(%d)\n", + __func__, u4BuffSizeBT); + + if (u4BuffSize > u4BuffSizeBT) + u4BuffSize = u4BuffSizeBT; +#endif /* CFG_SUPPORT_BCM */ + + rAddBaRspBody.u2BAParameterSet = (BA_POLICY_IMMEDIATE | + (u4Tid << BA_PARAM_SET_TID_MASK_OFFSET) | + (u4BuffSize << BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET)); + + /* TODO: Determine the BA timeout value + * according to the default preference + */ + rAddBaRspBody.u2BATimeoutValue = + rAddBaReqBody.u2BATimeoutValue; + + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) ADDBA_RSP u4BuffSize(%d) StatusCode(%d)", + __func__, u4BuffSize, rAddBaRspBody.u2StatusCode); + DBGLOG(QM, WARN, + "BAParameterSet(0x%08X) BATimeoutValue(%d)\n", + rAddBaRspBody.u2BAParameterSet, + rAddBaRspBody.u2BATimeoutValue); + kalMemCopy((uint8_t *) (&(prAddBaRsp->aucStatusCode[0])), + (uint8_t *) (&rAddBaRspBody), 6); + + COPY_MAC_ADDR(prAddBaRsp->aucDestAddr, + prStaRec->aucMacAddr); + COPY_MAC_ADDR(prAddBaRsp->aucSrcAddr, + prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prAddBaRsp->aucBSSID, prAddBaReq->aucBSSID); + + /* 4 <4> Forward the ADDBA_RSP to TXM */ + TX_SET_MMPDU(prAdapter, + prTxMsduInfo, + prStaRec->ucBssIndex, + (prStaRec != NULL) ? (prStaRec->ucIndex) : + (STA_REC_INDEX_NOT_FOUND), + WLAN_MAC_HEADER_LEN, + ACTION_ADDBA_RSP_FRAME_LEN, + mqmCallbackAddBaRspSent, + MSDU_RATE_MODE_AUTO); + + /* Note: prTxMsduInfo->ucTID is not used for transmitting the + * ADDBA_RSP. However, when processing TX Done of this + * ADDBA_RSP, the TID value is needed, so store the TID value + * in advance to prevent parsing the ADDBA_RSP frame + */ + prTxMsduInfo->ucTID = (uint8_t) u4Tid; + + nicTxEnqueueMsdu(prAdapter, prTxMsduInfo); + + DBGLOG(QM, WARN, + "[Puff][%s]: (RX_BA) ADDBA_RSP ---> peer (STA=%d TID=%ld)\n", + __func__, + prStaRec->ucIndex, u4Tid); + +#if 0 + /* 4 <5> Notify the host to start buffer reordering */ + /* Only when a new BA entry is indeed + * added will the host be notified + */ + if (fgIsNewEntryAdded) { + ASSERT(fgIsReqAccepted); + + prSwRfbEventToHost = (struct SW_RFB *) cnmMgtPktAlloc( + EVENT_RX_ADDBA_PACKET_LEN); + + if (!prSwRfbEventToHost) { + + /* Note: DELBA will not be sent since + * cnmMgtPktAlloc() may fail again. However, + * it does not matter because upon receipt of + * AMPDUs without a RX BA agreement, + * MQM will send DELBA frames + */ + + DBGLOG(MQM, WARN, + "MQM: (Warning) EVENT packet alloc failed\n"); + + /* Ensure that host and FW are synchronized */ + mqmRxModifyBaEntryStatus(prRxBaEntry, + BA_ENTRY_STATUS_INVALID); + + break; /* Free the received ADDBA_REQ */ + } + prEventRxAddBa = (struct EVENT_RX_ADDBA *) + prSwRfbEventToHost->pucBuffer; + prEventRxAddBa->ucStaRecIdx = (uint8_t) u4StaRecIdx; + prEventRxAddBa->u2Length = EVENT_RX_ADDBA_PACKET_LEN; + prEventRxAddBa->ucEID = EVENT_ID_RX_ADDBA; + /* Unsolicited event packet */ + prEventRxAddBa->ucSeqNum = 0; + prEventRxAddBa->u2BAParameterSet = + rAddBaRspBody.u2BAParameterSet; + prEventRxAddBa->u2BAStartSeqCtrl = + rAddBaReqBody.u2BAStartSeqCtrl; + prEventRxAddBa->u2BATimeoutValue = + rAddBaReqBody.u2BATimeoutValue; + prEventRxAddBa->ucDialogToken = + prAddBaReq->ucDialogToken; + + log_dbg(MQM, INFO, "MQM: (RX_BA) Event ADDBA ---> driver (STA=%ld TID=%ld WinStart=%d)\n", + u4StaRecIdx, u4Tid, + (prEventRxAddBa->u2BAStartSeqCtrl >> 4)); + + /* Configure the SW_RFB for the Event packet */ + RXM_SET_EVENT_PACKET( + /* struct SW_RFB **/ (struct SW_RFB *) + prSwRfbEventToHost, + /* HIF RX Packet pointer */ + (uint8_t *) prEventRxAddBa, + /* HIF RX port number */ HIF_RX0_INDEX + ); + + rxmSendEventToHost(prSwRfbEventToHost); + + + } +#endif + + } while (FALSE); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void mqmHandleAddBaRsp(IN struct SW_RFB *prSwRfb) +{ + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void mqmHandleDelBa(IN struct SW_RFB *prSwRfb) +{ + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void mqmHandleBaActionFrame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct WLAN_ACTION_FRAME *prRxFrame; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxFrame = (struct WLAN_ACTION_FRAME *) prSwRfb->pvHeader; + DBGLOG(RLM, WARN, "[Puff][%s] Action(%d)\n", __func__, + prRxFrame->ucAction); + + switch (prRxFrame->ucAction) { + + case ACTION_ADDBA_REQ: + DBGLOG(RLM, WARN, + "[Puff][%s] (RX_BA) ADDBA_REQ <--- peer\n", __func__); + mqmHandleAddBaReq(prAdapter, prSwRfb); + break; + + case ACTION_ADDBA_RSP: + DBGLOG(RLM, WARN, + "[Puff][%s] (RX_BA) ADDBA_RSP <--- peer\n", __func__); + mqmHandleAddBaRsp(prSwRfb); + break; + + case ACTION_DELBA: + DBGLOG(RLM, WARN, "[Puff][%s] (RX_BA) DELBA <--- peer\n", + __func__); + mqmHandleDelBa(prSwRfb); + break; + + default: + DBGLOG(RLM, WARN, "[Puff][%s] Unknown BA Action Frame\n", + __func__); + break; + } + +} + +#endif + +#if ARP_MONITER_ENABLE +void qmDetectArpNoResponse(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct STA_RECORD *prStaRec; + struct sk_buff *prSkb = NULL; + uint8_t *pucData = NULL; + uint16_t u2EtherType = 0; + int arpOpCode = 0; + struct BSS_INFO *prAisBssInfo = NULL; + struct WIFI_VAR *prWifiVar = NULL; + uint32_t uArpMonitorNumber; + uint32_t uArpMonitorRxPktNum; + struct net_device *prNetDev = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + + if (!prAdapter || + !prAdapter->prGlueInfo || + !prAdapter->prGlueInfo->prDevHandler) { + DBGLOG(QM, WARN, "Param is invalid\n"); + return; + } + prGlueInfo = prAdapter->prGlueInfo; + prNetDev = prGlueInfo->prDevHandler; + prWifiVar = &prAdapter->rWifiVar; + uArpMonitorNumber = prWifiVar->uArpMonitorNumber; + uArpMonitorRxPktNum = prWifiVar->uArpMonitorRxPktNum; + + if (uArpMonitorNumber == 0) + return; + + /* We need to disable arp monitor in CTIA mode */ + if (prAdapter->fgDisBcnLostDetection == TRUE) + return; + + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX( + prAdapter, prMsduInfo->ucStaRecIndex); + if (!prStaRec || !IS_STA_IN_AIS(prStaRec)) + return; + + prAisBssInfo = aisGetAisBssInfo(prAdapter, + prStaRec->ucBssIndex); + + if (prMsduInfo->eSrc != TX_PACKET_OS) + return; + + prSkb = (struct sk_buff *)prMsduInfo->prPacket; + + if (!prSkb || (prSkb->len <= ETHER_HEADER_LEN)) + return; + + pucData = prSkb->data; + if (!pucData) + return; + u2EtherType = (pucData[ETH_TYPE_LEN_OFFSET] << 8) | + (pucData[ETH_TYPE_LEN_OFFSET + 1]); + + if (u2EtherType != ETH_P_ARP) + return; + + /* If ARP req is neither to apIp nor to gatewayIp, ignore detection */ + if (kalMemCmp(apIp, &pucData[ETH_TYPE_LEN_OFFSET + 26], + sizeof(apIp)) && + kalMemCmp(gatewayIp, &pucData[ETH_TYPE_LEN_OFFSET + 26], + sizeof(gatewayIp))) + return; + + arpOpCode = (pucData[ETH_TYPE_LEN_OFFSET + 8] << 8) | + (pucData[ETH_TYPE_LEN_OFFSET + 8 + 1]); + + if (arpOpCode == ARP_PRO_REQ) { + arpMoniter++; + /* Record counts of RX Packets when Tx 1st ARP Req */ + if (!last_rx_packets) { + last_rx_packets = prNetDev->stats.rx_packets; + latest_rx_packets = 0; + } + /* Record counts of RX Packets when TX ARP Req recently */ + latest_rx_packets = prNetDev->stats.rx_packets; + if (arpMoniter > uArpMonitorNumber) { + if ((latest_rx_packets - last_rx_packets) <= + uArpMonitorRxPktNum) { + DBGLOG(INIT, WARN, "IOT issue, arp no resp!\n"); + if (prAisBssInfo) + prAisBssInfo->u2DeauthReason = + BEACON_TIMEOUT_DUE_2_APR_NO_RESPONSE; + prAdapter->cArpNoResponseIdx = + prStaRec->ucBssIndex; + } else + DBGLOG(INIT, WARN, "ARP, still have %d pkts\n", + latest_rx_packets - last_rx_packets); + arpMoniter = 0; + last_rx_packets = 0; + latest_rx_packets = 0; + kalMemZero(apIp, sizeof(apIp)); + } + } +} + +void qmHandleRxArpPackets(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb) +{ + uint8_t *pucData = NULL; + uint16_t u2EtherType = 0; + int arpOpCode = 0; + struct BSS_INFO *prAisBssInfo = NULL; + + prAisBssInfo = aisGetAisBssInfo(prAdapter, + secGetBssIdxByRfb(prAdapter, prSwRfb)); + + if (prSwRfb->u2PacketLen <= ETHER_HEADER_LEN) + return; + + pucData = (uint8_t *)prSwRfb->pvHeader; + if (!pucData) + return; + u2EtherType = (pucData[ETH_TYPE_LEN_OFFSET] << 8) | + (pucData[ETH_TYPE_LEN_OFFSET + 1]); + + if (u2EtherType != ETH_P_ARP) + return; + + arpOpCode = (pucData[ETH_TYPE_LEN_OFFSET + 8] << 8) | + (pucData[ETH_TYPE_LEN_OFFSET + 8 + 1]); + if (arpOpCode == ARP_PRO_RSP) { + arpMoniter = 0; + if (prAisBssInfo && + prAisBssInfo->prStaRecOfAP) { + if (EQUAL_MAC_ADDR( + &(pucData[ETH_TYPE_LEN_OFFSET + 10]), + /* source hardware address */ + prAisBssInfo-> + prStaRecOfAP->aucMacAddr)) { + kalMemCopy(apIp, + &(pucData[ETH_TYPE_LEN_OFFSET + 16]), + sizeof(apIp)); + DBGLOG(INIT, TRACE, + "get arp response from AP %d.%d.%d.%d\n", + apIp[0], apIp[1], apIp[2], apIp[3]); + #if ARP_BRUST_OPTIMIZE + kalMemCopy((uint8_t *)&(prAdapter->arp_b_stat.apIp), apIp, sizeof(apIp)); + #endif + } + } + } +} + +void qmHandleRxDhcpPackets(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb) +{ + uint8_t *pucData = NULL; + uint8_t *pucEthBody = NULL; + uint8_t *pucUdpBody = NULL; + uint32_t udpLength = 0; + uint32_t i = 0; + struct BOOTP_PROTOCOL *prBootp = NULL; + uint32_t u4DhcpMagicCode = 0; + uint8_t dhcpTypeGot = 0; + uint8_t dhcpGatewayGot = 0; + + if (prSwRfb->u2PacketLen <= ETHER_HEADER_LEN) + return; + + pucData = (uint8_t *)prSwRfb->pvHeader; + if (!pucData) + return; + if (((pucData[ETH_TYPE_LEN_OFFSET] << 8) | + pucData[ETH_TYPE_LEN_OFFSET + 1]) != ETH_P_IPV4) + return; + + pucEthBody = &pucData[ETH_HLEN]; + if (((pucEthBody[0] & IPVH_VERSION_MASK) >> + IPVH_VERSION_OFFSET) != IPVERSION) + return; + if (pucEthBody[9] != IP_PRO_UDP) + return; + + pucUdpBody = &pucEthBody[(pucEthBody[0] & 0x0F) * 4]; + if ((pucUdpBody[0] << 8 | pucUdpBody[1]) != UDP_PORT_DHCPS || + (pucUdpBody[2] << 8 | pucUdpBody[3]) != UDP_PORT_DHCPC) + return; + + udpLength = pucUdpBody[4] << 8 | pucUdpBody[5]; + + prBootp = (struct BOOTP_PROTOCOL *) &pucUdpBody[8]; + + WLAN_GET_FIELD_BE32(&prBootp->aucOptions[0], + &u4DhcpMagicCode); + if (u4DhcpMagicCode != DHCP_MAGIC_NUMBER) { + DBGLOG(INIT, WARN, + "dhcp wrong magic number, magic code: %d\n", + u4DhcpMagicCode); + return; + } + + /* 1. 248 is from udp header to the beginning of dhcp option + * 2. not sure the dhcp option always usd 255 as a end mark? + * if so, while condition should be removed? + */ + while (i < udpLength - 248) { + /* bcz of the strange struct BOOTP_PROTOCOL *, + * the dhcp magic code was count in dhcp options + * so need to [i + 4] to skip it + */ + switch (prBootp->aucOptions[i + 4]) { + case 3: + /* both dhcp ack and offer will update it */ + if (prBootp->aucOptions[i + 6] || + prBootp->aucOptions[i + 7] || + prBootp->aucOptions[i + 8] || + prBootp->aucOptions[i + 9]) { + gatewayIp[0] = prBootp->aucOptions[i + 6]; + gatewayIp[1] = prBootp->aucOptions[i + 7]; + gatewayIp[2] = prBootp->aucOptions[i + 8]; + gatewayIp[3] = prBootp->aucOptions[i + 9]; + + DBGLOG(INIT, TRACE, "Gateway ip: %d.%d.%d.%d\n", + gatewayIp[0], + gatewayIp[1], + gatewayIp[2], + gatewayIp[3]); + #if ARP_BRUST_OPTIMIZE + kalMemCopy((uint8_t *) &(prAdapter->arp_b_stat.gatewayIp), gatewayIp, sizeof(gatewayIp)); + #endif + }; + dhcpGatewayGot = 1; + break; + case 53: + if (prBootp->aucOptions[i + 6] != 0x02 + && prBootp->aucOptions[i + 6] != 0x05) { + DBGLOG(INIT, WARN, + "wrong dhcp message type, type: %d\n", + prBootp->aucOptions[i + 6]); + if (dhcpGatewayGot) + kalMemZero(gatewayIp, + sizeof(gatewayIp)); + return; + } else if (prBootp->aucOptions[i + 6] == 0x05) { + struct AIS_FSM_INFO *prAisFsmInfo = NULL; + uint8_t ucBssIndex = + secGetBssIdxByRfb( + prAdapter, prSwRfb); + prAisFsmInfo = + aisGetAisFsmInfo(prAdapter, + ucBssIndex); + /* Check if join timer is ticking, then release + * channel privilege and stop join timer. + */ + qmReleaseCHAtFinishedDhcp(prAdapter, + &prAisFsmInfo->rJoinTimeoutTimer, + ucBssIndex); + } + dhcpTypeGot = 1; + break; + case 255: + return; + + default: + break; + } + if (dhcpGatewayGot && dhcpTypeGot) + return; + + i += prBootp->aucOptions[i + 5] + 2; + } + DBGLOG(INIT, WARN, + "can't find the dhcp option 255?, need to check the net log\n"); +} + +void qmResetArpDetect(void) +{ + arpMoniter = 0; + last_rx_packets = 0; + latest_rx_packets = 0; + kalMemZero(apIp, sizeof(apIp)); + kalMemZero(gatewayIp, sizeof(gatewayIp)); +} +#endif + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL +void qmResetTcControlResource(IN struct ADAPTER *prAdapter) +{ + uint32_t u4Idx; + uint32_t u4TotalMinReservedTcResource = 0; + uint32_t u4TotalTcResource = 0; + uint32_t u4TotalGurantedTcResource = 0; + struct QUE_MGT *prQM = &prAdapter->rQM; + + /* Initialize TC resource control variables */ + for (u4Idx = 0; u4Idx < TC_NUM; u4Idx++) + prQM->au4AverageQueLen[u4Idx] = 0; + + ASSERT(prQM->u4TimeToAdjustTcResource + && prQM->u4TimeToUpdateQueLen); + + for (u4Idx = 0; u4Idx < TC_NUM; u4Idx++) { + prQM->au4CurrentTcResource[u4Idx] = + prAdapter->rTxCtrl.rTc.au4MaxNumOfBuffer[u4Idx]; + + if (u4Idx != TC4_INDEX) { + u4TotalTcResource += prQM->au4CurrentTcResource[u4Idx]; + u4TotalGurantedTcResource += + prQM->au4GuaranteedTcResource[u4Idx]; + u4TotalMinReservedTcResource += + prQM->au4MinReservedTcResource[u4Idx]; + } + } + + /* Sanity Check */ + if (u4TotalMinReservedTcResource > u4TotalTcResource) + kalMemZero(prQM->au4MinReservedTcResource, + sizeof(prQM->au4MinReservedTcResource)); + + if (u4TotalGurantedTcResource > u4TotalTcResource) + kalMemZero(prQM->au4GuaranteedTcResource, + sizeof(prQM->au4GuaranteedTcResource)); + + u4TotalGurantedTcResource = 0; + + /* Initialize Residual TC resource */ + for (u4Idx = 0; u4Idx < TC_NUM; u4Idx++) { + if (prQM->au4GuaranteedTcResource[u4Idx] < + prQM->au4MinReservedTcResource[u4Idx]) + prQM->au4GuaranteedTcResource[u4Idx] = + prQM->au4MinReservedTcResource[u4Idx]; + + if (u4Idx != TC4_INDEX) + u4TotalGurantedTcResource += + prQM->au4GuaranteedTcResource[u4Idx]; + } + + prQM->u4ResidualTcResource = u4TotalTcResource - + u4TotalGurantedTcResource; + +} +#endif + +#ifdef CFG_SUPPORT_REPLAY_DETECTION +/* To change PN number to UINT64 */ +#define CCMPTSCPNNUM 6 +u_int8_t qmRxPNtoU64(uint8_t *pucPN, uint8_t uPNNum, + uint64_t *pu64Rets) +{ + uint8_t ucCount = 0; + uint64_t u64Data = 0; + + if (!pu64Rets) { + DBGLOG(QM, ERROR, "Please input valid pu8Rets\n"); + return FALSE; + } + + if (uPNNum > CCMPTSCPNNUM) { + DBGLOG(QM, ERROR, "Please input valid uPNNum:%d\n", uPNNum); + return FALSE; + } + + *pu64Rets = 0; + for (; ucCount < uPNNum; ucCount++) { + u64Data = ((uint64_t) pucPN[ucCount]) << (8 * ucCount); + *pu64Rets += u64Data; + } + return TRUE; +} + +/* To check PN/TSC between RxStatus and local record. + * return TRUE if PNS is not bigger than PNT + */ +u_int8_t qmRxDetectReplay(uint8_t *pucPNS, uint8_t *pucPNT) +{ + uint64_t u8RxNum = 0; + uint64_t u8LocalRec = 0; + + if (!pucPNS || !pucPNT) { + DBGLOG(QM, ERROR, "Please input valid PNS:%p and PNT:%p\n", + pucPNS, pucPNT); + return TRUE; + } + + if (!qmRxPNtoU64(pucPNS, CCMPTSCPNNUM, &u8RxNum) + || !qmRxPNtoU64(pucPNT, CCMPTSCPNNUM, &u8LocalRec)) { + DBGLOG(QM, ERROR, "PN2U64 failed\n"); + return TRUE; + } + /* PN overflow ? */ + return !(u8RxNum > u8LocalRec); +} + +/* TO filter broadcast and multicast data packet replay issue. */ +u_int8_t qmHandleRxReplay(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb) +{ + uint8_t *pucPN = NULL; + uint8_t ucKeyID = 0; /* 0~4 */ + /* CIPHER_SUITE_NONE~CIPHER_SUITE_GCMP */ + uint8_t ucSecMode = CIPHER_SUITE_NONE; + struct GLUE_INFO *prGlueInfo = NULL; + struct GL_WPA_INFO *prWpaInfo = NULL; + struct GL_DETECT_REPLAY_INFO *prDetRplyInfo = NULL; + + if (!prAdapter) + return TRUE; + if (prSwRfb->u2PacketLen <= ETHER_HEADER_LEN) + return TRUE; + + if (!(prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_1))) { + DBGLOG_LIMITED(QM, TRACE, "Group 1 invalid\n"); + return FALSE; + } + + /* BMC only need check CCMP and TKIP Cipher suite */ + ucSecMode = prSwRfb->ucSecMode; + + prGlueInfo = prAdapter->prGlueInfo; + + prWpaInfo = aisGetWpaInfo(prAdapter, + secGetBssIdxByRfb(prAdapter, prSwRfb)); + + DBGLOG_LIMITED(QM, TRACE, "ucSecMode = [%u], ChiperGroup = [%u]\n", + ucSecMode, prWpaInfo->u4CipherGroup); + + if (ucSecMode != CIPHER_SUITE_CCMP + && ucSecMode != CIPHER_SUITE_TKIP) { + DBGLOG_LIMITED(QM, TRACE, + "SecMode: %d and CipherGroup: %d, no need check replay\n", + ucSecMode, prWpaInfo->u4CipherGroup); + return FALSE; + } + + if (prWpaInfo->u4CipherGroup != IW_AUTH_CIPHER_TKIP && + prWpaInfo->u4CipherGroup != IW_AUTH_CIPHER_CCMP) { + DBGLOG(QM, ERROR, + "RX status Chipher mode doens't match AP's setting\n"); + return FALSE; + } + + ucKeyID = prSwRfb->ucKeyID; + if (ucKeyID >= MAX_KEY_NUM) { + DBGLOG(QM, ERROR, "KeyID: %d error\n", ucKeyID); + return TRUE; + } + + prDetRplyInfo = aisGetDetRplyInfo(prAdapter, + secGetBssIdxByRfb(prAdapter, prSwRfb)); + /* TODO : Need check fw rekey while fw rekey event. */ + if (ucKeyID != prDetRplyInfo->ucCurKeyId) { + DBGLOG(QM, TRACE, + "use last keyID while detect replay information.(0x%x->0x%x)\n", + prDetRplyInfo->ucCurKeyId, ucKeyID); + ucKeyID = prDetRplyInfo->ucCurKeyId; + } + + if (prDetRplyInfo->arReplayPNInfo[ucKeyID].fgFirstPkt) { + prDetRplyInfo->arReplayPNInfo[ucKeyID].fgFirstPkt = FALSE; + HAL_RX_STATUS_GET_PN(prSwRfb->prRxStatusGroup1, + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN); + DBGLOG(QM, INFO, + "First check packet. Key ID:0x%x\n", ucKeyID); + return FALSE; + } + + pucPN = prSwRfb->prRxStatusGroup1->aucPN; + DBGLOG_LIMITED(QM, TRACE, + "BC packet 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x--0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n", + pucPN[0], pucPN[1], pucPN[2], pucPN[3], pucPN[4], pucPN[5], + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN[0], + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN[1], + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN[2], + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN[3], + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN[4], + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN[5]); + if (qmRxDetectReplay(pucPN, + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN)) { + DBGLOG_LIMITED(QM, WARN, "Drop BC replay packet!\n"); + return TRUE; + } + + HAL_RX_STATUS_GET_PN(prSwRfb->prRxStatusGroup1, + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN); + return FALSE; +} +#endif + +u_int8_t +qmIsIPLayerPacket(uint8_t *pucPkt) +{ + uint16_t u2EtherType = + (pucPkt[ETH_TYPE_LEN_OFFSET] << 8) + | (pucPkt[ETH_TYPE_LEN_OFFSET + 1]); + + if (u2EtherType == ETH_P_IPV4 || u2EtherType == ETH_P_IPV6) { + uint8_t *pucEthBody = &pucPkt[ETH_HLEN]; + uint8_t ucIpProto = + (u2EtherType == ETH_P_IPV4 ? + pucEthBody[IP_PROTO_HLEN] : + pucEthBody[IPV6_HDR_PROTOCOL_OFFSET]); + + if (ucIpProto == IP_PRO_UDP || ucIpProto == IP_PRO_TCP) + return TRUE; + } + + return FALSE; +} + +u_int8_t +qmIsNoDropPacket(IN struct ADAPTER *prAdapter, IN struct SW_RFB *prSwRfb) +{ + uint8_t *pucData = (uint8_t *) prSwRfb->pvHeader; + uint8_t ucBssIndex + = secGetBssIdxByWlanIdx(prAdapter, prSwRfb->ucWlanIdx); + u_int8_t fgCheckDrop = FALSE; + struct BSS_INFO *prBssInfo = NULL; + + if (ucBssIndex <= MAX_BSSID_NUM) + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + +#if CFG_SUPPORT_LOWLATENCY_MODE + if (prAdapter->fgEnLowLatencyMode) + fgCheckDrop = TRUE; +#endif + +#if CFG_SUPPORT_OSHARE + if (!fgCheckDrop && + (prAdapter->fgEnOshareMode) && + prBssInfo && + prBssInfo->eNetworkType == NETWORK_TYPE_P2P) + fgCheckDrop = TRUE; +#endif + +#if CFG_MTK_MDDP_WH_SUPPORT + if (!fgCheckDrop && prAdapter->fgMddpActivated && + prBssInfo && + prBssInfo->eNetworkType == NETWORK_TYPE_P2P) { + struct WIFI_VAR *prWifiVar = NULL; + struct P2P_CONNECTION_SETTINGS *prP2PConnSettings = NULL; + + prWifiVar = &prAdapter->rWifiVar; + if (prWifiVar && prBssInfo->u4PrivateData < BSS_P2P_NUM) { + prP2PConnSettings = prWifiVar->prP2PConnSettings[ + prBssInfo->u4PrivateData]; + fgCheckDrop = prP2PConnSettings && + p2pFuncIsAPMode(prP2PConnSettings); + } + } +#endif + + if (fgCheckDrop && qmIsIPLayerPacket(pucData)) + return TRUE; + + /* For some special packet, like DNS, DHCP, + * do not drop evan fall behind. + */ + if (qmIsIndependentPkt(prSwRfb)) + return TRUE; + + return FALSE; +} + +void qmMoveStaTxQueue(struct STA_RECORD *prSrcStaRec, + struct STA_RECORD *prDstStaRec) +{ + uint8_t ucQueArrayIdx; + struct QUE *prSrcQue = NULL; + struct QUE *prDstQue = NULL; + struct MSDU_INFO *prMsduInfo = NULL; + uint8_t ucDstStaIndex = 0; + + ASSERT(prSrcStaRec); + ASSERT(prDstStaRec); + + prSrcQue = &prSrcStaRec->arTxQueue[0]; + prDstQue = &prDstStaRec->arTxQueue[0]; + ucDstStaIndex = prDstStaRec->ucIndex; + + DBGLOG(QM, INFO, "Pending MSDUs for TC 0~3, %u %u %u %u\n", + prSrcQue[TC0_INDEX].u4NumElem, prSrcQue[TC1_INDEX].u4NumElem, + prSrcQue[TC2_INDEX].u4NumElem, prSrcQue[TC3_INDEX].u4NumElem); + /* Concatenate all MSDU_INFOs in TX queues of this STA_REC */ + for (ucQueArrayIdx = 0; ucQueArrayIdx < TC4_INDEX; ucQueArrayIdx++) { + prMsduInfo = (struct MSDU_INFO *)QUEUE_GET_HEAD( + &prSrcQue[ucQueArrayIdx]); + while (prMsduInfo) { + prMsduInfo->ucStaRecIndex = ucDstStaIndex; + prMsduInfo = (struct MSDU_INFO *)QUEUE_GET_NEXT_ENTRY( + &prMsduInfo->rQueEntry); + } + QUEUE_CONCATENATE_QUEUES((&prDstQue[ucQueArrayIdx]), + (&prSrcQue[ucQueArrayIdx])); + } +} + +void qmHandleDelTspec(struct ADAPTER *prAdapter, struct STA_RECORD *prStaRec, + enum ENUM_ACI eAci) +{ + uint8_t aucNextUP[ACI_NUM] = {1 /* BEtoBK */, 1 /*na */, 0 /*VItoBE */, + 4 /*VOtoVI */}; + enum ENUM_ACI aeNextAci[ACI_NUM] = {ACI_BK, ACI_BK, ACI_BE, ACI_VI}; + uint8_t ucActivedTspec = 0; + uint8_t ucNewUp = 0; + struct QUE *prSrcQue = NULL; + struct QUE *prDstQue = NULL; + struct MSDU_INFO *prMsduInfo = NULL; + struct AC_QUE_PARMS *prAcQueParam = NULL; + uint8_t ucTc = 0; + struct BSS_INFO *prAisBssInfo = NULL; + + if (!prStaRec || eAci == ACI_NUM || eAci == ACI_BK || !prAdapter) { + DBGLOG(QM, ERROR, "prSta NULL %d, eAci %d, prAdapter NULL %d\n", + !prStaRec, eAci, !prAdapter); + return; + } + prAisBssInfo = aisGetAisBssInfo(prAdapter, + prStaRec->ucBssIndex); + if (!prAisBssInfo) { + DBGLOG(QM, ERROR, "prAisBssInfo NULL\n"); + return; + } + + prSrcQue = &prStaRec->arTxQueue[aucWmmAC2TcResourceSet1[eAci]]; + prAcQueParam = &(prAisBssInfo->arACQueParms[0]); + ucActivedTspec = wmmHasActiveTspec( + aisGetWMMInfo(prAdapter, prAisBssInfo->ucBssIndex)); + + while (prAcQueParam[eAci].ucIsACMSet && + !(ucActivedTspec & BIT(eAci)) && eAci != ACI_BK) { + eAci = aeNextAci[eAci]; + ucNewUp = aucNextUP[eAci]; + } + DBGLOG(QM, INFO, "new ACI %d, ACM %d, HasTs %d\n", eAci, + prAcQueParam[eAci].ucIsACMSet, !!(ucActivedTspec & BIT(eAci))); + ucTc = aucWmmAC2TcResourceSet1[eAci]; + prDstQue = &prStaRec->arTxQueue[ucTc]; + prMsduInfo = (struct MSDU_INFO *)QUEUE_GET_HEAD(prSrcQue); + while (prMsduInfo) { + prMsduInfo->ucUserPriority = ucNewUp; + prMsduInfo->ucTC = ucTc; + prMsduInfo = (struct MSDU_INFO *)QUEUE_GET_NEXT_ENTRY( + &prMsduInfo->rQueEntry); + } + QUEUE_CONCATENATE_QUEUES(prDstQue, prSrcQue); +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + qmUpdateAverageTxQueLen(prAdapter); + qmReassignTcResource(prAdapter); +#endif + nicTxAdjustTcq(prAdapter); + kalSetEvent(prAdapter->prGlueInfo); +} + +void qmReleaseCHAtFinishedDhcp(struct ADAPTER *prAdapter, + struct TIMER *prTimer, uint8_t ucBssIndex) +{ + if (!timerPendingTimer(prTimer)) { + DBGLOG(QM, ERROR, "No channel occupation\n"); + } else { + DBGLOG(QM, INFO, "Dhcp done, stop join timer.\n"); + cnmTimerStopTimer(prAdapter, prTimer); + aisFsmRunEventJoinTimeout(prAdapter, ucBssIndex); + } +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/agent/agent.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/agent/agent.c new file mode 100644 index 0000000000000..599c2b030e4cc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/agent/agent.c @@ -0,0 +1,5272 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#include "agent.h" + +u_char *agnt_rstrtok; +u_char *agent_trtok(u_char *s, const u_char *ct) +{ + u_char *sbegin, *send; + + sbegin = s ? s : agnt_rstrtok; + + if (!sbegin) + return NULL; + + sbegin += strspn(sbegin, ct); + + if (*sbegin == '\0') { + agnt_rstrtok = NULL; + return NULL; + } + + send = strpbrk(sbegin, ct); + + if (send && *send != '\0') + *send++ = '\0'; + + agnt_rstrtok = send; + return sbegin; +} + + +/***************************************************************************** + * HQA DLL handler + *****************************************************************************/ +static s_int32 agent_cfg_find_next_token(struct agent_cfg_parse_state_s + *state) +{ + s_int8 *x = state->ptr; + s_int8 *s; + + if (state->nexttoken) { + s_int32 t = state->nexttoken; + + state->nexttoken = 0; + return t; + } + + for (;;) { + switch (*x) { + case 0: + state->ptr = x; + return AGENT_STATE_EOF; + case '\n': + x++; + state->ptr = x; + return AGENT_STATE_NEWLINE; + case ' ': + case ',': + /*case ':': should not including : , mac addr would be fail*/ + case '\t': + case '\r': + x++; + continue; + case '#': + while (*x && (*x != '\n')) + x++; + if (*x == '\n') { + state->ptr = x + 1; + return AGENT_STATE_NEWLINE; + } + state->ptr = x; + return AGENT_STATE_EOF; + + default: + goto text; + } + } + +textdone: + state->ptr = x; + *s = 0; + return AGENT_STATE_TEXT; +text: + state->text = s = x; +textresume: + for (;;) { + switch (*x) { + case 0: + goto textdone; + case ' ': + case ',': + /* case ':': */ + case '\t': + case '\r': + x++; + goto textdone; + case '\n': + state->nexttoken = AGENT_STATE_NEWLINE; + x++; + goto textdone; + case '"': + x++; + for (;;) { + switch (*x) { + case 0: + /* unterminated quoted thing */ + state->ptr = x; + return AGENT_STATE_EOF; + case '"': + x++; + goto textresume; + default: + *s++ = *x++; + } + } + break; + case '\\': + x++; + switch (*x) { + case 0: + goto textdone; + case 'n': + *s++ = '\n'; + break; + case 'r': + *s++ = '\r'; + break; + case 't': + *s++ = '\t'; + break; + case '\\': + *s++ = '\\'; + break; + case '\r': + /* \ -> line continuation */ + if (x[1] != '\n') { + x++; + continue; + } + case '\n': + /* \ -> line continuation */ + x++; + /* eat any extra whitespace */ + while ((*x == ' ') || (*x == '\t')) + x++; + continue; + default: + /* unknown escape -- just copy */ + *s++ = *x++; + } + continue; + default: + *s++ = *x++; + state->textsize++; + + } + } + return AGENT_STATE_EOF; +} + +static u_int32 agent_cfg_parse_argument(s_int8 *cmd_line, + s_int32 *argc, s_int8 *argv[]) +{ + struct agent_cfg_parse_state_s state; + s_int8 **args; + s_int32 nargs; + + if (cmd_line == NULL || argc == NULL || argv == NULL) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("parameter is NULL: %p, %p, %p\n", + cmd_line, argc, argv)); + + return SERV_STATUS_AGENT_INVALID_NULL_POINTER; + } + args = argv; + nargs = 0; + state.ptr = cmd_line; + state.nexttoken = 0; + state.maxsize = 0; + state.textsize = 0; + state.text = 0; + + if (strnlen(cmd_line, 512) >= 512) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("cmd_line >= 512\n")); + return SERV_STATUS_AGENT_INVALID_LEN; + } + + for (;;) { + switch (agent_cfg_find_next_token(&state)) { + case AGENT_STATE_EOF: + goto exit; + case AGENT_STATE_NEWLINE: + goto exit; + case AGENT_STATE_TEXT: + if (nargs < AGENT_CFG_ARGV_MAX) + args[nargs++] = state.text; + break; + } + } + +exit: + *argc = nargs; + return SERV_STATUS_SUCCESS; +} + + +static s_int32 set_param_and_shift_buf( + boolean convert, u_int32 size, u_char *in, u_char **out) +{ + if (!(*out)) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("*buf NULL pointer with size=%u\n", size)); + return SERV_STATUS_AGENT_INVALID_NULL_POINTER; + } + + if (!in) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("out NULL pointer with size=%u\n", size)); + return SERV_STATUS_AGENT_INVALID_NULL_POINTER; + } + + if (convert) { + if (size == sizeof(u_int32)) { + u_int32 *tmp = (u_int32 *) in; + + *tmp = SERV_OS_HTONL(*tmp); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: size=%u, val=%u\n", __func__, size, *tmp)); + } else if (size == sizeof(u_int16)) { + u_int16 *tmp = (u_int16 *) in; + + *tmp = SERV_OS_HTONS(*tmp); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: size=%u, val=%u\n", __func__, size, *tmp)); + } else { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_WARN, + ("%s: size %u not supported\n", __func__, size)); + return SERV_STATUS_AGENT_NOT_SUPPORTED; + } + } + + sys_ad_move_mem(*out, in, size); + *out = *out + size; + + return SERV_STATUS_SUCCESS; +} + +static s_int32 get_param_and_shift_buf( + boolean convert, u_int32 size, u_char **buf, u_char *out) +{ + if (!(*buf)) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("*buf NULL pointer with size=%u\n", size)); + return SERV_STATUS_AGENT_INVALID_NULL_POINTER; + } + + if (!out) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("out NULL pointer with size=%u\n", size)); + return SERV_STATUS_AGENT_INVALID_NULL_POINTER; + } + + sys_ad_move_mem(out, *buf, size); + *buf = *buf + size; + + if (!convert) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: size=%u", __func__, size)); + return SERV_STATUS_SUCCESS; + } + + if (size == sizeof(u_int32)) { + u_int32 *tmp = (u_int32 *) out; + + *tmp = SERV_OS_NTOHL(*tmp); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: size=%u, val=%u\n", __func__, size, *tmp)); + } else if (size == sizeof(u_int16)) { + u_int16 *tmp = (u_int16 *) out; + + *tmp = SERV_OS_NTOHS(*tmp); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: size=%u, val=%u\n", __func__, size, *tmp)); + } else { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_WARN, + ("%s: size %u not supported\n", __func__, size)); + return SERV_STATUS_AGENT_NOT_SUPPORTED; + } + + return SERV_STATUS_SUCCESS; +} + +static s_int32 update_hqa_frame( + struct hqa_frame *hqa_frame, s_int32 length, s_int32 status) +{ + hqa_frame->length = SERV_OS_HTONS((length)); + status = SERV_OS_HTONS((status)); + sys_ad_move_mem(hqa_frame->data, &status, 2); + return SERV_STATUS_SUCCESS; +} + +static s_int32 legacy_function( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + /* + * Legacy function means older chips use only, + * but not support in following CONNAC2 projects. + */ + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + update_hqa_frame(hqa_frame, 2, SERV_STATUS_SUCCESS); + return SERV_STATUS_SUCCESS; +} + +static s_int32 todo_function( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + update_hqa_frame(hqa_frame, 2, SERV_STATUS_SUCCESS); + return SERV_STATUS_SUCCESS; +} + +static s_int32 hqa_open_adapter( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + ret = mt_serv_start(serv_test); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_close_adapter( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + ret = mt_serv_stop(serv_test); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_set_tx_path( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS, value = 0; + u_char *data = hqa_frame->data; + u_char band_idx = SERV_GET_PARAM(serv_test, ctrl_band_idx); + u_int16 tx_ant = 0; + + if (hqa_frame->length > 2) { + /* new format with band index, + * and data length extedned to 8 bytes + */ + /* tx path in bitwise */ + get_param_and_shift_buf(TRUE, sizeof(value), + &data, (u_char *)&value); + tx_ant = value; + /* band index */ + get_param_and_shift_buf(TRUE, sizeof(value), + &data, (u_char *)&value); + band_idx = value; + + /* Set Band idx */ + SERV_SET_PARAM(serv_test, ctrl_band_idx, (u_char)band_idx); + + if (band_idx && tx_ant > 0x3) + tx_ant >>= 2; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: tx_path:%d, band:%d\n", __func__, + tx_ant, band_idx)); + } else { + /* legacy command format, + * data length is 2 bytes without band index + */ + get_param_and_shift_buf(TRUE, sizeof(tx_ant), + &data, (u_char *)&tx_ant); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: tx_path:%d\n", __func__, tx_ant)); + } + + /* Set parameters */ + CONFIG_SET_PARAM(serv_test, tx_ant, tx_ant, band_idx); + + ret = mt_serv_set_tx_path(serv_test); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_set_rx_path( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS, value = 0; + u_char *data = hqa_frame->data; + u_char band_idx = SERV_GET_PARAM(serv_test, ctrl_band_idx); + u_int16 rx_ant = 0; + + if (hqa_frame->length > 2) { + /* new format with band index, + * and data length extedned to 8 bytes + */ + /* rx path in bitwise */ + get_param_and_shift_buf(TRUE, sizeof(value), + &data, (u_char *)&value); + rx_ant = value; + /* band index */ + get_param_and_shift_buf(TRUE, sizeof(value), + &data, (u_char *)&value); + band_idx = value; + + /* Set Band idx */ + SERV_SET_PARAM(serv_test, ctrl_band_idx, (u_char)band_idx); + + if (band_idx && rx_ant > 0x3) + rx_ant >>= 2; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: rx_path:%d, band:%d\n", __func__, + rx_ant, band_idx)); + } else { + /* legacy command format, + * data length is 2 bytes without band index + */ + get_param_and_shift_buf(TRUE, sizeof(rx_ant), + &data, (u_char *)&rx_ant); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: rx_path:%d\n", __func__, rx_ant)); + } + + /* Set parameters */ + CONFIG_SET_PARAM(serv_test, rx_ant, rx_ant, band_idx); + + ret = mt_serv_set_rx_path(serv_test); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_set_tx_power_ext( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_int32 power = 0, band_idx = 0, channel = 0; + u_int32 ch_band = 0, ant_idx = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + /* Request format type */ + get_param_and_shift_buf(TRUE, sizeof(power), + &data, (u_char *)&power); + get_param_and_shift_buf(TRUE, sizeof(band_idx), + &data, (u_char *)&band_idx); + get_param_and_shift_buf(TRUE, sizeof(channel), + &data, (u_char *)&channel); + get_param_and_shift_buf(TRUE, sizeof(ch_band), + &data, (u_char *)&ch_band); + get_param_and_shift_buf(TRUE, sizeof(ant_idx), + &data, (u_char *)&ant_idx); + + /* Set parameters */ + SERV_SET_PARAM(serv_test, ctrl_band_idx, (u_char)band_idx); + CONFIG_SET_PARAM(serv_test, pwr_param.ant_idx, + (u_int32)ant_idx, band_idx); + CONFIG_SET_PARAM(serv_test, pwr_param.power, + (u_int32)power, band_idx); + CONFIG_SET_PARAM(serv_test, pwr_param.channel, + (u_int32)channel, band_idx); + CONFIG_SET_PARAM(serv_test, pwr_param.band_idx, + (u_int32)band_idx, band_idx); + CONFIG_SET_PARAM(serv_test, pwr_param.ch_band, + (u_int32)ch_band, band_idx); + + ret = mt_serv_tx_power_operation(serv_test, SERV_TEST_TXPWR_SET_PWR); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: power=%u, band_idx=%u, channel=%u\n", + __func__, power, band_idx, channel)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: ch_band=%u, ant_idx=%u\n", + __func__, ch_band, ant_idx)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static struct hqa_cmd_entry CMD_SET0[] = { + /* cmd id start from 0x1000 */ + {0x0, hqa_open_adapter}, + {0x1, hqa_close_adapter}, + {0x2, legacy_function}, + {0x3, legacy_function}, + {0x4, legacy_function}, + {0x6, legacy_function}, + {0x7, legacy_function}, + {0x8, legacy_function}, + {0xa, legacy_function}, + {0xb, hqa_set_tx_path}, + {0xc, hqa_set_rx_path}, + {0xd, legacy_function}, + {0xe, legacy_function}, + {0xf, legacy_function}, + {0x10, legacy_function}, + {0x11, hqa_set_tx_power_ext}, + {0x14, legacy_function}, + {0x15, todo_function}, + {0x18, legacy_function} +}; + +static s_int32 hqa_set_preamble( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_char band_idx = SERV_GET_PARAM(serv_test, ctrl_band_idx); + u_int32 tx_mode = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + /* Request format type: Mode (4 bytes) */ + get_param_and_shift_buf(TRUE, sizeof(tx_mode), + &data, (u_char *)&tx_mode); + + /* Set parameters */ + /* + * 000: Legacy CCK + * 001: Legacy OFDM + * 010: HT Mixed mode + * 011: HT Green field mode + * 100: VHT mode + */ + CONFIG_SET_PARAM(serv_test, tx_mode, (u_char)tx_mode, band_idx); + + ret = mt_serv_set_preamble(serv_test); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: phy_mode=%u\n", __func__, tx_mode)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_set_rate( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_char band_idx = SERV_GET_PARAM(serv_test, ctrl_band_idx); + u_int32 mcs = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + /* Request format type: MCS (4 bytes) */ + get_param_and_shift_buf(TRUE, sizeof(mcs), + &data, (u_char *)&mcs); + + /* Set parameters */ + CONFIG_SET_PARAM(serv_test, mcs, (u_char)mcs, band_idx); + + ret = mt_serv_set_rate(serv_test); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: mcs=%u\n", __func__, mcs)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_set_nss( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_char band_idx = SERV_GET_PARAM(serv_test, ctrl_band_idx); + u_int32 nss = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + /* Request format type: NSS (4 bytes) */ + get_param_and_shift_buf(TRUE, sizeof(nss), + &data, (u_char *)&nss); + + /* Set parameters */ + CONFIG_SET_PARAM(serv_test, nss, (u_char)nss, band_idx); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: nss=%u\n", __func__, nss)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_set_system_bw( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_char band_idx = SERV_GET_PARAM(serv_test, ctrl_band_idx); + u_int32 bw = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + /* Request format type: BW (4 bytes) */ + get_param_and_shift_buf(TRUE, sizeof(bw), + &data, (u_char *)&bw); + + /* Set parameters */ + CONFIG_SET_PARAM(serv_test, bw, (u_char)bw, band_idx); + + ret = mt_serv_set_system_bw(serv_test); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: bw=%u\n", __func__, bw)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_set_per_pkt_bw( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_char band_idx = SERV_GET_PARAM(serv_test, ctrl_band_idx); + u_int32 per_pkt_bw = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + /* Request format type: Per-Pkt BW (4 bytes) */ + get_param_and_shift_buf(TRUE, sizeof(per_pkt_bw), + &data, (u_char *)&per_pkt_bw); + + /* Set parameters */ + CONFIG_SET_PARAM(serv_test, per_pkt_bw, (u_char)per_pkt_bw, band_idx); + + ret = mt_serv_set_per_pkt_bw(serv_test); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: per_pkt_bw=%u\n", __func__, per_pkt_bw)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_set_freq_offset( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_char band_idx = SERV_GET_PARAM(serv_test, ctrl_band_idx); + u_int32 freq_offset = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + /* Request format type: freq offset (4 bytes) */ + get_param_and_shift_buf(TRUE, sizeof(freq_offset), + &data, (u_char *)&freq_offset); + + /* Set parameters */ + CONFIG_SET_PARAM(serv_test, rf_freq_offset, + (u_int32)freq_offset, band_idx); + + ret = mt_serv_set_freq_offset(serv_test); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: freq offset=%u\n", __func__, freq_offset)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_low_power( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_int32 control = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(control), + &data, (u_char *)&control); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: control=%u\n", __func__, control)); + + /* + * 0: enter low power mode + * 1: leave low power mode + */ + ret = mt_serv_set_low_power(serv_test, control); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_get_antswap_capability( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_int32 antswap_support = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, ("%s\n", __func__)); + + ret = mt_serv_get_antswap_capability(serv_test, &antswap_support); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("antswap_support = %x\n", antswap_support)); + + antswap_support = SERV_OS_HTONL(antswap_support); + sys_ad_move_mem(hqa_frame->data + 2, &antswap_support, + sizeof(antswap_support)); + update_hqa_frame(hqa_frame, 2 + sizeof(antswap_support), ret); + + return ret; +} + +static s_int32 hqa_set_antswap( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_int32 band, ant = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(u_int32), + &data, (u_char *)&band); + get_param_and_shift_buf(TRUE, sizeof(u_int32), + &data, (u_char *)&ant); + + ret = mt_serv_set_antswap(serv_test, ant); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static struct hqa_cmd_entry CMD_SET1[] = { + /* cmd id start from 0x1100 */ + {0x0, legacy_function}, + {0x1, hqa_set_preamble}, + {0x2, hqa_set_rate}, + {0x3, hqa_set_nss}, + {0x4, hqa_set_system_bw}, + {0x5, hqa_set_per_pkt_bw}, + {0x6, legacy_function}, + {0x7, hqa_set_freq_offset}, + {0x9, legacy_function}, + {0xb, hqa_low_power}, + {0xd, hqa_get_antswap_capability}, + {0xe, hqa_set_antswap} +}; + +static s_int32 hqa_reset_txrx_counter( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + ret = mt_serv_reset_txrx_counter(serv_test); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_cal_bypass( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_int32 item = 0, band_idx = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + /* Request format type */ + get_param_and_shift_buf(TRUE, sizeof(item), + &data, (u_char *)&item); + get_param_and_shift_buf(TRUE, sizeof(band_idx), + &data, (u_char *)&band_idx); + + /* Set parameters */ + SERV_SET_PARAM(serv_test, ctrl_band_idx, (u_char)band_idx); + + ret = mt_serv_set_cal_bypass(serv_test, item); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: item=%u, band_idx=%u\n", + __func__, item, band_idx)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_set_rx_vector_idx( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_int32 band_idx = 0, group1 = 0, group2 = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(band_idx), + &data, (u_char *)&band_idx); + get_param_and_shift_buf(TRUE, sizeof(group1), + &data, (u_char *)&group1); + get_param_and_shift_buf(TRUE, sizeof(group2), + &data, (u_char *)&group2); + + /* Set parameters */ + SERV_SET_PARAM(serv_test, ctrl_band_idx, (u_char)band_idx); + + ret = mt_serv_set_rx_vector_idx(serv_test, group1, group2); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_set_fagc_rssi_path( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_int32 band_idx = 0, fagc_path = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(band_idx), + &data, (u_char *)&band_idx); + get_param_and_shift_buf(TRUE, sizeof(fagc_path), + &data, (u_char *)&fagc_path); + + /* Set parameters */ + SERV_SET_PARAM(serv_test, ctrl_band_idx, (u_char)band_idx); + CONFIG_SET_PARAM(serv_test, fagc_path, (u_char)fagc_path, band_idx); + + ret = mt_serv_set_fagc_rssi_path(serv_test); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static struct hqa_cmd_entry CMD_SET2[] = { + /* cmd id start from 0x1200 */ + {0x0, hqa_reset_txrx_counter}, + {0x5, legacy_function}, + {0x8, hqa_cal_bypass}, + {0x9, hqa_set_rx_vector_idx}, + {0xa, hqa_set_fagc_rssi_path} +}; + +static s_int32 hqa_mac_bbp_reg_read( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_register *test_regs = &serv_test->test_reg; + u_char *data = hqa_frame->data; + u_int32 cr_val; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(u_int32), + &data, (u_char *)&test_regs->cr_addr); + + test_regs->cr_num = 1; + + /* Allocate cr_val memory */ + ret = sys_ad_alloc_mem((u_char **)&test_regs->cr_val, sizeof(u_int32)); + if (ret) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: allocate register memory fail\n", __func__)); + ret = SERV_STATUS_AGENT_INVALID_NULL_POINTER; + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; + } + + ret = mt_serv_reg_eprm_operation(serv_test, SERV_TEST_REG_MAC_READ); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: cr_addr=0x%08x, cr_val=0x%08x\n", + __func__, test_regs->cr_addr, *test_regs->cr_val)); + + cr_val = SERV_OS_HTONL(*test_regs->cr_val); + + /* Update hqa_frame with response: status (2 bytes) */ + sys_ad_move_mem(hqa_frame->data + 2, &cr_val, sizeof(cr_val)); + update_hqa_frame(hqa_frame, 2 + sizeof(cr_val), ret); + + /* Free cr_val memory */ + sys_ad_free_mem(test_regs->cr_val); + + return ret; +} + +static s_int32 hqa_mac_bbp_reg_write( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_register *test_regs = &serv_test->test_reg; + u_char *data = hqa_frame->data; + u_int32 cr_val; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(u_int32), + &data, (u_char *)&test_regs->cr_addr); + get_param_and_shift_buf(TRUE, sizeof(u_int32), + &data, (u_char *)&cr_val); + + /* Allocate cr_val memory */ + ret = sys_ad_alloc_mem((u_char **)&test_regs->cr_val, sizeof(u_int32)); + if (ret) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: allocate register memory fail\n", __func__)); + ret = SERV_STATUS_AGENT_INVALID_NULL_POINTER; + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; + } + sys_ad_move_mem(test_regs->cr_val, &cr_val, sizeof(cr_val)); + + ret = mt_serv_reg_eprm_operation(serv_test, SERV_TEST_REG_MAC_WRITE); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: cr_addr=0x%08x, cr_val=0x%08x\n", + __func__, test_regs->cr_addr, *test_regs->cr_val)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + /* Free cr_val memory */ + sys_ad_free_mem(test_regs->cr_val); + + return ret; +} + +static s_int32 hqa_mac_bbp_reg_bulk_read( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_int16 cr_seq = 0; + struct test_register *test_regs = &serv_test->test_reg; + u_char *data = hqa_frame->data; + u_int32 cr_total_len, cr_value = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(test_regs->cr_addr), + &data, (u_char *)&test_regs->cr_addr); + get_param_and_shift_buf(TRUE, sizeof(test_regs->cr_num), + &data, (u_char *)&test_regs->cr_num); + + /* Allocate cr_val memory */ + cr_total_len = test_regs->cr_num << 2; + ret = sys_ad_alloc_mem((u_char **)&test_regs->cr_val, cr_total_len); + if (ret) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: allocate register memory fail\n", __func__)); + ret = SERV_STATUS_AGENT_INVALID_NULL_POINTER; + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; + } + + if (test_regs->cr_num > 371) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: requested len is longer, make it smaller\n", + __func__)); + ret = SERV_STATUS_AGENT_INVALID_LEN; + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; + } + + ret = mt_serv_reg_eprm_operation(serv_test, + SERV_TEST_REG_MAC_READ_BULK); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: cr_addr=0x%08x, cr_num(unit: 4bytes)=%d\n", + __func__, test_regs->cr_addr, test_regs->cr_num)); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: cr_val = 0x%08x\n", __func__, *test_regs->cr_val)); + + for (cr_seq = 0; cr_seq < test_regs->cr_num; cr_seq++) { + cr_value = test_regs->cr_val[cr_seq]; + test_regs->cr_val[cr_seq] = SERV_OS_HTONL(cr_value); + } + + /* Update hqa_frame with response: status (2 bytes) */ + sys_ad_move_mem(hqa_frame->data + 2, test_regs->cr_val, cr_total_len); + update_hqa_frame(hqa_frame, 2 + cr_total_len, ret); + + /* Free cr_val memory */ + sys_ad_free_mem(test_regs->cr_val); + + return ret; +} + +static s_int32 hqa_rf_reg_bulk_read( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_int16 cr_seq = 0; + struct test_register *test_regs = &serv_test->test_reg; + u_char *data = hqa_frame->data; + u_int32 cr_total_len, cr_value = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(u_int32), + &data, (u_char *)&test_regs->wf_sel); + get_param_and_shift_buf(TRUE, sizeof(u_int32), + &data, (u_char *)&test_regs->cr_addr); + get_param_and_shift_buf(TRUE, sizeof(u_int32), + &data, (u_char *)&test_regs->cr_num); + + /* Allocate cr_val memory */ + cr_total_len = test_regs->cr_num << 2; + ret = sys_ad_alloc_mem((u_char **)&test_regs->cr_val, cr_total_len); + if (ret) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: allocate register memory fail\n", __func__)); + ret = SERV_STATUS_AGENT_INVALID_NULL_POINTER; + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; + } + + ret = mt_serv_reg_eprm_operation(serv_test, + SERV_TEST_REG_RF_READ_BULK); + + for (cr_seq = 0; cr_seq < test_regs->cr_num; cr_seq++) { + cr_value = test_regs->cr_val[cr_seq]; + test_regs->cr_val[cr_seq] = SERV_OS_HTONL(cr_value); + } + /* Update hqa_frame with response: status (2 bytes) */ + sys_ad_move_mem(hqa_frame->data + 2, test_regs->cr_val, cr_total_len); + update_hqa_frame(hqa_frame, 2 + cr_total_len, ret); + + /* Free cr_val memory */ + sys_ad_free_mem(test_regs->cr_val); + + return ret; +} + +static s_int32 hqa_rf_reg_bulk_write( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_register *test_regs = &serv_test->test_reg; + u_char *data = hqa_frame->data; + u_int32 idx, cr_total_len; + u_int32 *dst; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(u_int32), + &data, (u_char *)&test_regs->wf_sel); + get_param_and_shift_buf(TRUE, sizeof(u_int32), + &data, (u_char *)&test_regs->cr_addr); + get_param_and_shift_buf(TRUE, sizeof(u_int32), + &data, (u_char *)&test_regs->cr_num); + + /* Allocate cr_val memory */ + cr_total_len = test_regs->cr_num << 2; + ret = sys_ad_alloc_mem((u_char **)&test_regs->cr_val, cr_total_len); + if (ret) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: allocate register memory fail\n", __func__)); + ret = SERV_STATUS_AGENT_INVALID_NULL_POINTER; + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; + } + + for (idx = 0; idx < test_regs->cr_num; idx++) { + dst = test_regs->cr_val + idx; + get_param_and_shift_buf(TRUE, sizeof(u_int32), + &data, (u_char *) dst); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: cr_addr=0x%08x, cr_val=0x%08x\n", + __func__, test_regs->cr_addr, *dst)); + } + + ret = mt_serv_reg_eprm_operation(serv_test, + SERV_TEST_REG_RF_WRITE_BULK); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + /* Free cr_val memory */ + sys_ad_free_mem(test_regs->cr_val); + + return ret; +} + +static s_int32 hqa_read_eeprom( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_eeprom *test_eprms = &serv_test->test_eprm; + u_char *data = hqa_frame->data; + u_int16 value; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(u_int16), + &data, (u_char *)&test_eprms->offset); + + /* Allocate value memory */ + ret = sys_ad_alloc_mem((u_char **)&test_eprms->value, sizeof(u_int16)); + if (ret) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: allocate eeprom memory fail\n", __func__)); + ret = SERV_STATUS_AGENT_INVALID_NULL_POINTER; + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; + } + + ret = mt_serv_reg_eprm_operation(serv_test, SERV_TEST_EEPROM_READ); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: offset=0x%04x, value=0x%04x\n", + __func__, test_eprms->offset, *test_eprms->value)); + + value = SERV_OS_HTONS(*test_eprms->value); + + /* Update hqa_frame with response: status (2 bytes) */ + sys_ad_move_mem(hqa_frame->data + 2, &value, sizeof(value)); + update_hqa_frame(hqa_frame, 2 + sizeof(value), ret); + + /* Free value memory */ + sys_ad_free_mem(test_eprms->value); + + return ret; +} + +static s_int32 hqa_write_eeprom( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_eeprom *test_eprms = &serv_test->test_eprm; + u_char *data = hqa_frame->data; + u_int16 value; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(u_int16), + &data, (u_char *)&test_eprms->offset); + get_param_and_shift_buf(TRUE, sizeof(u_int16), + &data, (u_char *)&value); + + /* Allocate value memory */ + ret = sys_ad_alloc_mem((u_char **)&test_eprms->value, sizeof(u_int16)); + if (ret) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: allocate eeprom memory fail\n", __func__)); + ret = SERV_STATUS_AGENT_INVALID_NULL_POINTER; + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; + } + sys_ad_move_mem(test_eprms->value, &value, sizeof(value)); + + ret = mt_serv_reg_eprm_operation(serv_test, SERV_TEST_EEPROM_WRITE); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: offset=0x%04x, value=0x%04x\n", + __func__, test_eprms->offset, *test_eprms->value)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + /* Free value memory */ + sys_ad_free_mem(test_eprms->value); + + return ret; +} + +static void memcpy_eeprom(u_char *dst, u_char *src, u_long len) +{ + u_long i; + u_short *p_dst, *p_src; + + p_dst = (u_short *) dst; + p_src = (u_short *) src; + + for (i = 0; i < (len >> 1); i++) { + *p_dst = SERV_OS_NTOHS(*p_src); + p_dst++; + p_src++; + } + + if ((len % 2) != 0) { + sys_ad_move_mem(p_dst, p_src, (len % 2)); + *p_dst = SERV_OS_NTOHS(*p_dst); + } +} + +static s_int32 hqa_read_bulk_eeprom( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_eeprom *test_eprms = &serv_test->test_eprm; + u_char *data = hqa_frame->data; + u_int32 eeprom_size; + u_int16 offset, length; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(test_eprms->offset), + &data, (u_char *)&test_eprms->offset); + get_param_and_shift_buf(TRUE, sizeof(test_eprms->length), + &data, (u_char *)&test_eprms->length); + + /* Allocate value memory */ + eeprom_size = serv_test->test_winfo->chip_cap.efuse_size; + offset = test_eprms->offset; + length = test_eprms->length; + ret = sys_ad_alloc_mem((u_char **)&test_eprms->value, eeprom_size); + if (ret) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: allocate eeprom memory fail\n", __func__)); + ret = SERV_STATUS_AGENT_INVALID_NULL_POINTER; + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; + } + + ret = mt_serv_reg_eprm_operation(serv_test, + SERV_TEST_EEPROM_READ_BULK); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: offset=0x%04x, length=%d\n", __func__, offset, length)); + + /* Update hqa_frame with response: status (2 bytes) */ + if (offset + length <= eeprom_size) + memcpy_eeprom(hqa_frame->data + 2, + (u_char *)test_eprms->value + offset, length); + else { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: exceed eeprom size (offset=0x%04x, size=%d)\n", + __func__, offset+length, eeprom_size)); + length = 0; + ret = SERV_STATUS_AGENT_INVALID_LEN; + } + update_hqa_frame(hqa_frame, 2 + length, ret); + + /* Free value memory */ + sys_ad_free_mem(test_eprms->value); + + return ret; +} + +static s_int32 hqa_write_bulk_eeprom( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_eeprom *test_eprms = &serv_test->test_eprm; + u_char *data = hqa_frame->data; + u_int32 eeprom_size; + u_int16 offset = 0, length = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(test_eprms->offset), + &data, (u_char *)&test_eprms->offset); + get_param_and_shift_buf(TRUE, sizeof(test_eprms->length), + &data, (u_char *)&test_eprms->length); + + /* Allocate value memory */ + eeprom_size = serv_test->test_winfo->chip_cap.efuse_size; + ret = sys_ad_alloc_mem((u_char **)&test_eprms->value, eeprom_size); + if (ret) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: allocate eeprom memory fail\n", __func__)); + ret = SERV_STATUS_AGENT_INVALID_NULL_POINTER; + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; + } + memcpy_eeprom((u_char *)test_eprms->value + (test_eprms->offset & ~0x1), + data, test_eprms->length); + + ret = mt_serv_reg_eprm_operation(serv_test, + SERV_TEST_EEPROM_WRITE_BULK); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: offset=0x%04x, length=%d\n", __func__, offset, length)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + /* Free value memory */ + sys_ad_free_mem(test_eprms->value); + + return ret; +} + +static s_int32 hqa_check_efuse_mode( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_int32 efuse_mode; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + if (WINFO_GET_PARAM(serv_test, use_efuse)) + efuse_mode = 1; + else + efuse_mode = 0; + + efuse_mode = SERV_OS_HTONL(efuse_mode); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: efuse_mode=%u\n", __func__, efuse_mode)); + + /* Update hqa_frame with response: status (2 bytes) */ + sys_ad_move_mem(hqa_frame->data + 2, &efuse_mode, sizeof(efuse_mode)); + update_hqa_frame(hqa_frame, 6, ret); + + return ret; +} + +static s_int32 hqa_get_free_efuse_block( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_int32 free_block; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + ret = mt_serv_reg_eprm_operation(serv_test, + SERV_TEST_EEPROM_GET_FREE_EFUSE_BLOCK); + + free_block = EEPROM_GET_PARAM(serv_test, efuse_free_block); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: efuse_free_block=%u\n", __func__, free_block)); + + free_block = SERV_OS_HTONL(free_block); + + /* Update hqa_frame with response: status (2 bytes) */ + sys_ad_move_mem(hqa_frame->data + 2, &free_block, sizeof(free_block)); + update_hqa_frame(hqa_frame, 2 + sizeof(free_block), ret); + + return ret; +} + +static s_int32 hqa_get_tx_power( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_int32 power = 0, band_idx = 0, channel = 0; + u_int32 ch_band = 0, ant_idx = 0, efuse_offset = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + /* Request format type */ + get_param_and_shift_buf(TRUE, sizeof(channel), + &data, (u_char *)&channel); + get_param_and_shift_buf(TRUE, sizeof(band_idx), + &data, (u_char *)&band_idx); + get_param_and_shift_buf(TRUE, sizeof(ch_band), + &data, (u_char *)&ch_band); + get_param_and_shift_buf(TRUE, sizeof(ant_idx), + &data, (u_char *)&ant_idx); + + /* set parameters */ + SERV_SET_PARAM(serv_test, ctrl_band_idx, (u_char)band_idx); + CONFIG_SET_PARAM(serv_test, pwr_param.ant_idx, + (u_int32)ant_idx, band_idx); + CONFIG_SET_PARAM(serv_test, pwr_param.channel, + (u_int32)channel, band_idx); + CONFIG_SET_PARAM(serv_test, pwr_param.band_idx, + (u_int32)band_idx, band_idx); + CONFIG_SET_PARAM(serv_test, pwr_param.ch_band, + (u_int32)ch_band, band_idx); + + ret = mt_serv_tx_power_operation(serv_test, SERV_TEST_TXPWR_GET_PWR); + + power = CONFIG_GET_PARAM(serv_test, pwr_param.power, band_idx); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: power=%u, band_idx=%u, channel=%u\n", + __func__, power, band_idx, channel)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: ch_band=%u, ant_idx=%u\n", + __func__, ch_band, ant_idx)); + + /* update hqa_frame with response: status (2 bytes) */ + efuse_offset = SERV_OS_HTONL(efuse_offset); + sys_ad_move_mem(hqa_frame->data + 2, &efuse_offset, + sizeof(efuse_offset)); + power = SERV_OS_HTONL(power); + sys_ad_move_mem(hqa_frame->data + 2 + 4, &power, sizeof(power)); + update_hqa_frame(hqa_frame, + 2 + sizeof(power) + sizeof(efuse_offset), ret); + + return ret; +} + +static s_int32 hqa_set_cfg_on_off( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_int32 type, enable = 0, band_idx = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + /* Request format type */ + get_param_and_shift_buf(TRUE, sizeof(type), + &data, (u_char *)&type); + get_param_and_shift_buf(TRUE, sizeof(enable), + &data, (u_char *)&enable); + get_param_and_shift_buf(TRUE, sizeof(band_idx), + &data, (u_char *)&band_idx); + + /* Set parameters */ + SERV_SET_PARAM(serv_test, ctrl_band_idx, (u_char)band_idx); + CONFIG_SET_PARAM(serv_test, log_type, (u_char)type, band_idx); + CONFIG_SET_PARAM(serv_test, log_enable, (u_char)enable, band_idx); + + ret = mt_serv_set_cfg_on_off(serv_test); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: type=%u, enable=%u, band_idx=%u\n", + __func__, type, enable, band_idx)); + + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_get_freq_offset( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_int32 freq_offset = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + ret = mt_serv_get_freq_offset(serv_test, &freq_offset); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: freq offset: %d\n", __func__, freq_offset)); + + /* update hqa_frame with response: status (2 bytes) */ + freq_offset = SERV_OS_HTONL(freq_offset); + sys_ad_move_mem(hqa_frame->data + 2, &freq_offset, sizeof(freq_offset)); + update_hqa_frame(hqa_frame, 2 + sizeof(freq_offset), ret); + + return ret; +} + +static s_int32 hqa_dbdc_tx_tone( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct hqa_tx_tone param; + u_char *data = hqa_frame->data; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + sys_ad_zero_mem(¶m, sizeof(param)); + + /* Request format type */ + get_param_and_shift_buf(TRUE, sizeof(param.band_idx), + &data, (u_char *)¶m.band_idx); + get_param_and_shift_buf(TRUE, sizeof(param.tx_tone_en), + &data, (u_char *)¶m.tx_tone_en); + get_param_and_shift_buf(TRUE, sizeof(param.ant_idx), + &data, (u_char *)¶m.ant_idx); + get_param_and_shift_buf(TRUE, sizeof(param.tone_type), + &data, (u_char *)¶m.tone_type); + get_param_and_shift_buf(TRUE, sizeof(param.tone_freq), + &data, (u_char *)¶m.tone_freq); + get_param_and_shift_buf(TRUE, sizeof(param.dc_offset_I), + &data, (u_char *)¶m.dc_offset_I); + get_param_and_shift_buf(TRUE, sizeof(param.dc_offset_Q), + &data, (u_char *)¶m.dc_offset_Q); + get_param_and_shift_buf(TRUE, sizeof(param.band), + &data, (u_char *)¶m.band); + get_param_and_shift_buf(TRUE, sizeof(param.rf_pwr), + &data, (u_char *)¶m.rf_pwr); + get_param_and_shift_buf(TRUE, sizeof(param.digi_pwr), + &data, (u_char *)¶m.digi_pwr); + + /* Set parameters */ + SERV_SET_PARAM(serv_test, ctrl_band_idx, (u_char)param.band_idx); + CONFIG_SET_PARAM(serv_test, tx_tone_en, + (u_int32)param.tx_tone_en, param.band_idx); + CONFIG_SET_PARAM(serv_test, ant_idx, + (u_int32)param.ant_idx, param.band_idx); + CONFIG_SET_PARAM(serv_test, tone_type, + (u_int32)param.tone_type, param.band_idx); + CONFIG_SET_PARAM(serv_test, tone_freq, + (u_int32)param.tone_freq, param.band_idx); + CONFIG_SET_PARAM(serv_test, dc_offset_I, + (u_int32)param.dc_offset_I, param.band_idx); + CONFIG_SET_PARAM(serv_test, dc_offset_Q, + (u_int32)param.dc_offset_Q, param.band_idx); + CONFIG_SET_PARAM(serv_test, ch_band, + (u_char)param.band, param.band_idx); + CONFIG_SET_PARAM(serv_test, rf_pwr, + (u_int32)param.rf_pwr, param.band_idx); + CONFIG_SET_PARAM(serv_test, digi_pwr, + (u_int32)param.digi_pwr, param.band_idx); + + ret = mt_serv_dbdc_tx_tone(serv_test); + ret = mt_serv_dbdc_tx_tone_pwr(serv_test); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: band_idx=%u, tx_tone_en=%u, ant_idx=0x%x\n", + __func__, param.band_idx, param.tx_tone_en, param.ant_idx)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: tone_type=%u, tone_freq=%u, dc_offset_I=0x%x\n", + __func__, param.tone_type, param.tone_freq, + param.dc_offset_I)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: dc_offset_Q=%u, band=%u, rf_pwr=0x%x, digi_pwr=0x%x\n", + __func__, param.dc_offset_Q, param.band, param.rf_pwr, + param.digi_pwr)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_dbdc_continuous_tx( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct hqa_continuous_tx param; + u_char *data = hqa_frame->data; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + sys_ad_zero_mem(¶m, sizeof(param)); + + get_param_and_shift_buf(TRUE, sizeof(param.band_idx), + &data, (u_char *) ¶m.band_idx); + get_param_and_shift_buf(TRUE, sizeof(param.tx_tone_en), + &data, (u_char *) ¶m.tx_tone_en); + get_param_and_shift_buf(TRUE, sizeof(param.ant_mask), + &data, (u_char *) ¶m.ant_mask); + get_param_and_shift_buf(TRUE, sizeof(param.tx_mode), + &data, (u_char *) ¶m.tx_mode); + get_param_and_shift_buf(TRUE, sizeof(param.bw), + &data, (u_char *) ¶m.bw); + get_param_and_shift_buf(TRUE, sizeof(param.pri_ch), + &data, (u_char *) ¶m.pri_ch); + get_param_and_shift_buf(TRUE, sizeof(param.rate), + &data, (u_char *) ¶m.rate); + get_param_and_shift_buf(TRUE, sizeof(param.central_ch), + &data, (u_char *) ¶m.central_ch); + get_param_and_shift_buf(TRUE, sizeof(param.tx_fd_mode), + &data, (u_char *) ¶m.tx_fd_mode); + + /* Set parameters */ + SERV_SET_PARAM(serv_test, ctrl_band_idx, (u_char)param.band_idx); + CONFIG_SET_PARAM(serv_test, tx_tone_en, + (u_int32)param.tx_tone_en, param.band_idx); + CONFIG_SET_PARAM(serv_test, ant_mask, + (u_int32)param.ant_mask, param.band_idx); + CONFIG_SET_PARAM(serv_test, tx_mode, + (u_char)param.tx_mode, param.band_idx); + CONFIG_SET_PARAM(serv_test, bw, + (u_char)param.bw, param.band_idx); + CONFIG_SET_PARAM(serv_test, ctrl_ch, + (u_char)param.pri_ch, param.band_idx); + CONFIG_SET_PARAM(serv_test, rate, + (u_int32)param.rate, param.band_idx); + CONFIG_SET_PARAM(serv_test, channel, + (u_char)param.central_ch, param.band_idx); + CONFIG_SET_PARAM(serv_test, tx_fd_mode, + (u_int32)param.tx_fd_mode, param.band_idx); + + ret = mt_serv_dbdc_continuous_tx(serv_test); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: param band_idx=%u, tx_tone_en=%u, ant_mask=0x%x\n", + __func__, param.band_idx, param.tx_tone_en, param.ant_mask)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: param phy_mode=%u, bw=%u, pri_ch=%u\n", + __func__, param.tx_mode, param.bw, param.pri_ch)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: param rate=%u, central_ch=%u, tx_fd_mode=%u\n", + __func__, param.rate, param.central_ch, param.tx_fd_mode)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_set_rx_filter_pkt_len( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_int32 band_idx = 0, enable = 0, rx_pkt_len = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(band_idx), + &data, (u_char *)&band_idx); + get_param_and_shift_buf(TRUE, sizeof(enable), + &data, (u_char *)&enable); + get_param_and_shift_buf(TRUE, sizeof(rx_pkt_len), + &data, (u_char *)&rx_pkt_len); + + /* Set parameters */ + SERV_SET_PARAM(serv_test, ctrl_band_idx, (u_char)band_idx); + CONFIG_SET_PARAM(serv_test, rx_filter_en, + (u_int8)enable, band_idx); + CONFIG_SET_PARAM(serv_test, rx_filter_pkt_len, + (u_int32)rx_pkt_len, band_idx); + + ret = mt_serv_set_rx_filter_pkt_len(serv_test); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_get_tx_info( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_int32 tx_cnt0 = 0, tx_cnt1 = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + ret = mt_serv_get_tx_info(serv_test); + + /* Get parameters */ + tx_cnt0 = CONFIG_GET_PARAM(serv_test, tx_stat.tx_done_cnt, + TEST_DBDC_BAND0); + tx_cnt0 = SERV_OS_HTONL(tx_cnt0); +/* #ifdef DBDC_MODE */ +#if 1 + if (IS_TEST_DBDC(serv_test->test_winfo)) { + tx_cnt1 = CONFIG_GET_PARAM(serv_test, tx_stat.tx_done_cnt, + TEST_DBDC_BAND1); + tx_cnt1 = SERV_OS_HTONL(tx_cnt1); + } +#endif + /* Update hqa_frame with response: status (2 bytes) */ + sys_ad_move_mem((hqa_frame->data + 2), + &tx_cnt0, sizeof(tx_cnt0)); + sys_ad_move_mem((hqa_frame->data + 2 + sizeof(tx_cnt0)), + &tx_cnt1, sizeof(tx_cnt1)); + update_hqa_frame(hqa_frame, + 2 + sizeof(tx_cnt0) + sizeof(tx_cnt1), ret); + + return ret; +} + +static s_int32 hqa_get_cfg_on_off( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + s_int32 type = 0, band_idx = 0; + u_int32 result = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + /* Request format type */ + get_param_and_shift_buf(TRUE, sizeof(type), + &data, (u_char *)&type); + get_param_and_shift_buf(TRUE, sizeof(band_idx), + &data, (u_char *)&band_idx); + + ret = mt_serv_get_cfg_on_off(serv_test, type, &result); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: type=%u, result=%u\n", __func__, type, result)); + + /* Update hqa_frame with response: status (2 bytes) */ + result = SERV_OS_HTONL(result); + sys_ad_move_mem(hqa_frame->data + 2, &result, sizeof(result)); + update_hqa_frame(hqa_frame, 2 + sizeof(result), ret); + + return ret; +} + +static s_int32 hqa_ca53_reg_read( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_register *test_regs = &serv_test->test_reg; + u_char *data = hqa_frame->data; + u_long cr_val; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + /* Use u_long here to get 4bytes firmly */ + get_param_and_shift_buf(TRUE, sizeof(u_long), + &data, (u_char *)&test_regs->cr_addr); + + /* Allocate cr_val memory */ + ret = sys_ad_alloc_mem((u_char **)&test_regs->cr_val, sizeof(u_long)); + if (ret) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: allocate register memory fail\n", __func__)); + ret = SERV_STATUS_AGENT_INVALID_NULL_POINTER; + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; + } + + ret = mt_serv_reg_eprm_operation(serv_test, SERV_TEST_REG_CA53_READ); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: cr_addr=0x%08x, cr_val=0x%08x\n", + __func__, test_regs->cr_addr, *test_regs->cr_val)); + + cr_val = SERV_OS_HTONL(*test_regs->cr_val); + + /* Update hqa_frame with response: status (2 bytes) */ + sys_ad_move_mem(hqa_frame->data + 2, &cr_val, sizeof(cr_val)); + update_hqa_frame(hqa_frame, 2 + sizeof(cr_val), ret); + + /* Free cr_val memory */ + sys_ad_free_mem(test_regs->cr_val); + + return ret; +} + +static s_int32 hqa_ca53_reg_write( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_register *test_regs = &serv_test->test_reg; + u_char *data = hqa_frame->data; + u_int32 cr_val; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + /* Use u_long here to get 4bytes firmly */ + get_param_and_shift_buf(TRUE, sizeof(u_long), + &data, (u_char *)&test_regs->cr_addr); + get_param_and_shift_buf(TRUE, sizeof(u_int32), + &data, (u_char *)&cr_val); + + /* Allocate cr_val memory */ + ret = sys_ad_alloc_mem((u_char **)&test_regs->cr_val, sizeof(u_int32)); + if (ret) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: allocate register memory fail\n", __func__)); + ret = SERV_STATUS_AGENT_INVALID_NULL_POINTER; + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; + } + sys_ad_move_mem(test_regs->cr_val, &cr_val, sizeof(cr_val)); + + ret = mt_serv_reg_eprm_operation(serv_test, SERV_TEST_REG_CA53_WRITE); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: cr_addr=0x%08x, cr_val=0x%08x\n", + __func__, test_regs->cr_addr, *test_regs->cr_val)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + /* Free cr_val memory */ + sys_ad_free_mem(test_regs->cr_val); + + return ret; +} + +static s_int32 hqa_get_tx_tone_pwr( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_int32 power = 0, ant_idx = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + /* request format type */ + get_param_and_shift_buf(TRUE, sizeof(ant_idx), + &data, (u_char *)&ant_idx); + + ret = mt_serv_get_tx_tone_pwr(serv_test, ant_idx, &power); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: ant_idx: %d, power: %d\n", + __func__, ant_idx, power)); + + /* update hqa_frame with response: status (2 bytes) */ + power = SERV_OS_HTONL(power); + sys_ad_move_mem(hqa_frame->data + 2, &power, sizeof(power)); + update_hqa_frame(hqa_frame, 2 + sizeof(power), ret); + + return ret; +} + +static struct hqa_cmd_entry CMD_SET3[] = { + /* cmd id start from 0x1300 */ + {0x0, hqa_mac_bbp_reg_read}, + {0x1, hqa_mac_bbp_reg_write}, + {0x2, hqa_mac_bbp_reg_bulk_read}, + {0x3, hqa_rf_reg_bulk_read}, + {0x4, hqa_rf_reg_bulk_write}, + {0x5, hqa_read_eeprom}, + {0x6, hqa_write_eeprom}, + {0x7, hqa_read_bulk_eeprom}, + {0x8, hqa_write_bulk_eeprom}, + {0x9, hqa_check_efuse_mode}, + {0xa, hqa_get_free_efuse_block}, + {0xd, hqa_get_tx_power}, + {0xe, hqa_set_cfg_on_off}, + {0xf, hqa_get_freq_offset}, + {0x10, hqa_dbdc_tx_tone}, + {0x11, hqa_dbdc_continuous_tx}, + {0x12, hqa_set_rx_filter_pkt_len}, + {0x13, hqa_get_tx_info}, + {0x14, hqa_get_cfg_on_off}, + {0x15, legacy_function}, + {0x17, legacy_function}, + {0x18, hqa_ca53_reg_read}, + {0x19, hqa_ca53_reg_write}, + {0x1a, hqa_get_tx_tone_pwr} +}; + +static s_int32 hqa_get_thermal_val( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_int32 value = 0; + u_char band_idx; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + /* request format type */ + band_idx = serv_test->ctrl_band_idx; + + ret = mt_serv_get_thermal_val(serv_test, band_idx, &value); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: value: %d\n", __func__, value)); + + /* update hqa_frame with response: status (2 bytes) */ + value = SERV_OS_HTONL(value); + sys_ad_move_mem(hqa_frame->data + 2, &value, sizeof(value)); + update_hqa_frame(hqa_frame, 2 + sizeof(value), ret); + + return ret; +} + +static struct hqa_cmd_entry CMD_SET4[] = { + /* cmd id start from 0x1400 */ + {0x1, hqa_get_thermal_val} +}; + +static s_int32 hqa_get_fw_info( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct serv_fw_info *fw_info = NULL; + u_char op_mode; + u_int8 loop, month = 0; + u_char date[8], time[6]; + u_char *kernel_info = NULL; + u_char *month_array[12] = { + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec", + }; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + fw_info = WINFO_GET_PADDR(serv_test, wm_fw_info); + sys_ad_zero_mem(&date[0], sizeof(date)); + sys_ad_zero_mem(&time[0], sizeof(time)); + + /* Get information from kernel */ + for (loop = 0; loop < 12; loop++) { + kernel_info = strstr(utsname()->version, month_array[loop]); + + if (kernel_info) + break; + } + + /* SW package build time */ + sys_ad_move_mem(&time[0], kernel_info + 7, 2); + sys_ad_move_mem(&time[2], kernel_info + 10, 2); + sys_ad_move_mem(&time[4], kernel_info + 13, 2); + + /* SW package build date */ + sys_ad_move_mem(&date[0], kernel_info + 20, 4); + sys_ad_move_mem(&date[6], kernel_info + 4, 2); + + for (loop = 0; loop < 12; loop++) { + if (sys_ad_cmp_mem(month_array[loop], kernel_info, 3) == 0) { + month = loop + 1; + break; + } + } + + date[4] = month / 10 % 10 + '0'; + date[5] = month % 10 + '0'; + + /* Update hqa_frame with response: status (2 bytes) */ + /* The 1 byte for op_mode doesn't use anymore but still keep it */ + sys_ad_move_mem((hqa_frame->data + 2), &op_mode, sizeof(op_mode)); + sys_ad_move_mem((hqa_frame->data + 2 + sizeof(op_mode)), + &date, sizeof(date)); + sys_ad_move_mem((hqa_frame->data + 2 + sizeof(op_mode) + sizeof(date)), + &time, sizeof(time)); + sys_ad_move_mem((hqa_frame->data + 2 + sizeof(op_mode) + + sizeof(date) + sizeof(time)), + &fw_info->ram_built_date[0], + sizeof(fw_info->ram_built_date)); + update_hqa_frame(hqa_frame, (2+1+8+6+15), ret); + + return ret; +} + +static s_int32 hqa_set_stbc( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_char band_idx = SERV_GET_PARAM(serv_test, ctrl_band_idx); + u_int32 stbc = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + /* Request format type: Enable (4 bytes) */ + get_param_and_shift_buf(TRUE, sizeof(stbc), + &data, (u_char *)&stbc); + + /* Set parameters */ + CONFIG_SET_PARAM(serv_test, stbc, (u_char)stbc, band_idx); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: stbc enable=%u\n", __func__, stbc)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_set_short_gi( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_char band_idx = SERV_GET_PARAM(serv_test, ctrl_band_idx); + u_int32 sgi = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + /* Request format type: Enable (4 bytes) */ + get_param_and_shift_buf(TRUE, sizeof(sgi), + &data, (u_char *)&sgi); + + /* Set parameters */ + CONFIG_SET_PARAM(serv_test, sgi, (u_char)sgi, band_idx); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: sgi enable=%u\n", __func__, sgi)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_set_dpd( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_int32 on_off = 0, wf_sel = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + /* Request format type */ + get_param_and_shift_buf(TRUE, sizeof(on_off), + &data, (u_char *)&on_off); + get_param_and_shift_buf(TRUE, sizeof(wf_sel), + &data, (u_char *)&wf_sel); + + ret = mt_serv_set_dpd(serv_test, on_off, wf_sel); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: on_off: %d, wf_sel: %d\n", __func__, on_off, wf_sel)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_set_tssi_onoff( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_int32 on_off = 0, wf_sel = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + /* Request format type */ + get_param_and_shift_buf(TRUE, sizeof(on_off), + &data, (u_char *)&on_off); + get_param_and_shift_buf(TRUE, sizeof(wf_sel), + &data, (u_char *)&wf_sel); + + ret = mt_serv_set_tssi(serv_test, on_off, wf_sel); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: on_off: %d\n", __func__, on_off)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_get_rx_statistics_leg( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct hqa_rx_stat_leg rx_stat; + struct test_rx_stat_leg test_rx_stat; + u_char dw_cnt = 0, dw_idx = 0; + u_char *ptr2 = NULL; + u_int32 *ptr = NULL; + u_int32 buf; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + ret = mt_serv_get_rx_stat_leg(serv_test, &test_rx_stat); + sys_ad_move_mem(&rx_stat, &test_rx_stat, + sizeof(struct hqa_rx_stat_leg)); + dw_cnt = sizeof(struct hqa_rx_stat_leg) >> 2; + + for (dw_idx = 0, ptr = (u_int32 *)&rx_stat, ptr2 = hqa_frame->data + 2; + dw_idx < dw_cnt; dw_idx++, ptr++, ptr2 += 4) { + buf = SERV_OS_HTONL(*ptr); + sys_ad_move_mem(ptr2, &buf, sizeof(u_int32)); + } + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2 + sizeof(struct hqa_rx_stat_leg), ret); + + return ret; +} + +static s_int32 hqa_get_rx_statistics_all( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + u_int32 buf_size = 0; + s_int32 ret = SERV_STATUS_SUCCESS; + u_int32 type_mask = 0, band_idx = 0, type_num = 0, length; + u_int32 blk_idx = 0, type_idx = 0, buf = 0; + u_int32 dw_idx = 0, dw_cnt = 0; + u_int32 *ptr2 = NULL; + struct test_rx_stat_u *rx_stat = NULL; + boolean dbdc_mode = FALSE; + u_int8 path[TEST_ANT_NUM] = {0}; + u_int8 path_len = 0; + u_int8 *ptr = NULL; + u_char *data = hqa_frame->data; + struct hqa_rx_stat_resp_format st_form[SERV_RX_STAT_TYPE_NUM] = { + {SERV_RX_STAT_TYPE_BAND, 0, 0, 0, + sizeof(struct hqa_rx_stat_band_info)}, + {SERV_RX_STAT_TYPE_PATH, 0, 0, 0, + sizeof(struct hqa_rx_stat_path_info)}, + {SERV_RX_STAT_TYPE_USER, 0, 0, 0, + sizeof(struct hqa_rx_stat_user_info)}, + {SERV_RX_STAT_TYPE_COMM, 0, 0, 0, + sizeof(struct hqa_rx_stat_comm_info)} + }; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + /* Request format type */ + get_param_and_shift_buf(TRUE, sizeof(type_mask), + &data, (u_char *)&type_mask); + get_param_and_shift_buf(TRUE, sizeof(band_idx), + &data, (u_char *)&band_idx); + + /* check dbdc mode condition */ + dbdc_mode = IS_TEST_DBDC(serv_test->test_winfo); + + /* sanity check for band index param */ + if ((!dbdc_mode) && (band_idx != TEST_DBDC_BAND0)) + goto error2; + + /* check wifi path combination for specific band */ + ret = mt_serv_get_wf_path_comb(serv_test, + band_idx, + dbdc_mode, + path, + &path_len); + + /* TODO: check user combination for specific band */ + /* host driver not support related utility */ + /* if need this function, need host driver support */ + + /* update item mask for each type */ + st_form[SERV_RX_STAT_TYPE_BAND].item_mask = BIT(band_idx); + for (blk_idx = 0; blk_idx < path_len; blk_idx++) + st_form[SERV_RX_STAT_TYPE_PATH].item_mask |= BIT(path[blk_idx]); + for (blk_idx = 0; blk_idx < TEST_USER_NUM; blk_idx++) + st_form[SERV_RX_STAT_TYPE_USER].item_mask |= BIT(blk_idx); + st_form[SERV_RX_STAT_TYPE_COMM].item_mask = BIT(0); + + /* update block count for each type */ + for (type_idx = SERV_RX_STAT_TYPE_BAND; + type_idx < SERV_RX_STAT_TYPE_NUM; type_idx++) { + for (blk_idx = 0; blk_idx < 32; blk_idx++) { + if (st_form[type_idx].item_mask & BIT(blk_idx)) + st_form[type_idx].blk_cnt++; + } + } + + ptr = hqa_frame->data + 2 + sizeof(type_num); + + /* allocate dynamic memory for rx stat info */ + ret = sys_ad_alloc_mem((u_char **)&rx_stat, + sizeof(struct test_rx_stat_u)); + if (ret != SERV_STATUS_SUCCESS) + goto error1; + + for (type_idx = SERV_RX_STAT_TYPE_BAND; + type_idx < SERV_RX_STAT_TYPE_NUM; type_idx++) { + if (type_mask & BIT(type_idx)) { + type_num++; + length = st_form[type_idx].blk_cnt * + st_form[type_idx].blk_size; + + /* fill in type */ + buf = SERV_OS_HTONL(st_form[type_idx].type); + sys_ad_move_mem(ptr, &buf, sizeof(buf)); + ptr += sizeof(st_form[type_idx].type); + buf_size += sizeof(st_form[type_idx].type); + + /* fill in version */ + buf = SERV_OS_HTONL(st_form[type_idx].version); + sys_ad_move_mem(ptr, &buf, sizeof(buf)); + ptr += sizeof(st_form[type_idx].version); + buf_size += sizeof(st_form[type_idx].version); + + /* fill in item mask */ + buf = SERV_OS_HTONL(st_form[type_idx].item_mask); + sys_ad_move_mem(ptr, &buf, sizeof(buf)); + ptr += sizeof(st_form[type_idx].item_mask); + buf_size += sizeof(st_form[type_idx].item_mask); + + /* fill in length */ + buf = SERV_OS_HTONL(length); + sys_ad_move_mem(ptr, &buf, sizeof(buf)); + ptr += sizeof(length); + buf_size += sizeof(length); + + for (blk_idx = 0; blk_idx < 32; blk_idx++) { + if (st_form[type_idx].item_mask + & BIT(blk_idx)) { + /* service handle for rx stat info */ + mt_serv_get_rx_stat(serv_test, + band_idx, + blk_idx, + type_idx, + rx_stat); + + ptr2 = (u_int32 *) rx_stat; + dw_cnt = st_form[type_idx].blk_size + >> 2; + for (dw_idx = 0; dw_idx < dw_cnt; + dw_idx++, ptr2++, + ptr += 4) { + /* endian transform */ + buf = SERV_OS_HTONL(*ptr2); + /* fill in block content */ + sys_ad_move_mem(ptr, &buf, + sizeof(buf)); + } + + buf_size += st_form[type_idx].blk_size; + } + } + } + } + + /* free allocated memory */ + sys_ad_free_mem(rx_stat); + + /* fill in type num */ + ptr = hqa_frame->data + 2; + buf = SERV_OS_HTONL(type_num); + sys_ad_move_mem(ptr, &buf, sizeof(buf)); + buf_size += sizeof(type_num); + update_hqa_frame(hqa_frame, (2 + buf_size), ret); + + return ret; + +error1: + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: memory allocation fail for rx stat.\n", + __func__)); + update_hqa_frame(hqa_frame, 2, ret); + return ret; + +error2: + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: invalid band index for non-dbdc mode.\n", + __func__)); + update_hqa_frame(hqa_frame, 2, ret); + return ret; +} + +static s_int32 hqa_get_capability( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_int8 *ptr = hqa_frame->data + 2; + struct test_capability capability; + u_int32 convert, i, *cast = NULL; + u_int32 item_num = sizeof(struct test_capability) / 4; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + /* get content */ + ret = mt_serv_get_capability(serv_test, &capability); + + /* fill header */ + capability.version = GET_CAPABILITY_VER; + capability.tag_num = GET_CAPABILITY_TAG_NUM; + capability.ph_cap.tag = GET_CAPABILITY_TAG_PHY; + capability.ph_cap.tag_len = GET_CAPABILITY_TAG_PHY_LEN; + capability.ext_cap.tag = GET_CAPABILITY_TAG_PHY_EXT; + capability.ext_cap.tag_len = GET_CAPABILITY_TAG_PHY_EXT_LEN; + + cast = (u_int32 *)&capability; + + /* convert and put data */ + for (i = 0; i < item_num; i++) { + convert = SERV_OS_HTONL(cast[i]); + sys_ad_move_mem(ptr, &convert, sizeof(convert)); + ptr += sizeof(convert); + } + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, (item_num*4) + 2, ret); + return ret; +} + +static s_int32 hqa_calibration_test_mode( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_configuration *test_config; + u_char *data = hqa_frame->data; + u_int32 mode, icap_len, resp_len = 2; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(mode), + &data, (u_char *)&mode); + get_param_and_shift_buf(TRUE, sizeof(icap_len), + &data, (u_char *)&icap_len); + + /* Set parameters */ + test_config = &serv_test->test_config[serv_test->ctrl_band_idx]; + + if (test_config) { + if (mode == fTEST_OPER_NORMAL_MODE) { + test_config->op_mode &= + ~(fTEST_FFT_ENABLE | fTEST_IN_RFTEST); + } else if (mode == fTEST_OPER_RFTEST_MODE) { + test_config->op_mode |= fTEST_IN_RFTEST; + } else if (mode == fTEST_OPER_ICAP_MODE) { + test_config->op_mode |= fTEST_IN_RFTEST; + } else { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: Mode = %d error!!!\n", __func__, mode)); + } + } else + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: Mode = test_config is null!!!\n", __func__)); + + ret = mt_serv_calibration_test_mode(serv_test, mode); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, resp_len, ret); + + return ret; +} + +static s_int32 hqa_do_cal_item( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_int32 item = 0, band_idx = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(item), + &data, (u_char *)&item); + get_param_and_shift_buf(TRUE, sizeof(band_idx), + &data, (u_char *)&band_idx); + + serv_test->ctrl_band_idx = (u_char)band_idx; + + ret = mt_serv_do_cal_item(serv_test, item); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: item: %d, band_idx: %d\n", __func__, item, band_idx)); + + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_tmr_setting( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_tmr_info *tmr_info = &serv_test->test_tmr; + u_char *data = hqa_frame->data; + + get_param_and_shift_buf(TRUE, sizeof(tmr_info->setting), + &data, (u_char *)&tmr_info->setting); + get_param_and_shift_buf(TRUE, sizeof(tmr_info->version), + &data, (u_char *)&tmr_info->version); + get_param_and_shift_buf(TRUE, sizeof(tmr_info->through_hold), + &data, (u_char *)&tmr_info->through_hold); + get_param_and_shift_buf(TRUE, sizeof(tmr_info->iter), + &data, (u_char *)&tmr_info->iter); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: setting=%d, version=%d, through_hold=%d, iter=%d\n", + __func__, tmr_info->setting, tmr_info->version, + tmr_info->through_hold, tmr_info->iter)); + + ret = mt_serv_set_tmr(serv_test); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_get_chipid( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_int32 chip_id; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + ret = mt_serv_get_chipid(serv_test); + + chip_id = WINFO_GET_PARAM(serv_test, chip_id); + chip_id = SERV_OS_HTONL(chip_id); + + /* Update hqa_frame with response: status (2 bytes) */ + sys_ad_move_mem(hqa_frame->data + 2, &chip_id, sizeof(chip_id)); + update_hqa_frame(hqa_frame, 2 + sizeof(chip_id), ret); + + return ret; +} + +static s_int32 hqa_mps_set_seq_data( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_configuration *test_config = NULL; + struct test_mps_cb *mps_cb = NULL; + struct test_mps_setting *mps_setting = NULL; + u_char *data = hqa_frame->data; + u_int32 *param = NULL; + u_int32 band_idx, idx, value = 0; + u_int16 len; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(band_idx), + &data, (u_char *)&band_idx); + + len = hqa_frame->length / sizeof(u_int32) - 1; + if ((len > TEST_MPS_ITEM_LEN) || (len == 0)) { + ret = SERV_STATUS_AGENT_INVALID_LEN; + goto err; + } + + ret = sys_ad_alloc_mem((u_char **)¶m, sizeof(u_int32) * len); + if (ret) { + ret = SERV_STATUS_AGENT_INVALID_NULL_POINTER; + goto err; + } + + for (idx = 0; idx < len; idx++) { + get_param_and_shift_buf(TRUE, sizeof(u_int32), + &data, (u_char *)&value); + param[idx] = value; + } + + /* Set parameters */ + serv_test->ctrl_band_idx = (u_char)band_idx; + test_config = &serv_test->test_config[band_idx]; + mps_cb = &test_config->mps_cb; + + if (mps_cb->mps_setting == NULL) { + ret = sys_ad_alloc_mem((u_char **)&mps_cb->mps_setting, + sizeof(struct test_mps_setting) * (len+1)); + if (ret) { + sys_ad_free_mem(param); + ret = SERV_STATUS_AGENT_INVALID_NULL_POINTER; + goto err; + } + sys_ad_zero_mem(mps_cb->mps_setting, + sizeof(struct test_mps_setting) * (len+1)); + } + + mps_cb->mps_cnt = len; + mps_setting = mps_cb->mps_setting; + + for (idx = 0; idx < len; idx++) { + mps_setting[idx+1].tx_mode = (param[idx] & 0x0F000000) >> 24; + mps_setting[idx+1].tx_ant = (param[idx] & 0x00FFFF00) >> 8; + mps_setting[idx+1].mcs = (param[idx] & 0x000000FF); + } + sys_ad_free_mem(param); + + ret = mt_serv_mps_set_seq_data(serv_test); + +err: + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: band_idx=%d, len=%d, op_mode=0x%x, mps_cnt=%d\n", + __func__, band_idx, len, + test_config->op_mode, mps_cb->mps_cnt)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_mps_set_payload_length( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_configuration *test_config = NULL; + struct test_mps_cb *mps_cb = NULL; + struct test_mps_setting *mps_setting = NULL; + u_char *data = hqa_frame->data; + u_int32 *param = NULL; + u_int32 band_idx, idx, value = 0; + u_int16 len; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(band_idx), + &data, (u_char *)&band_idx); + + len = hqa_frame->length / sizeof(u_int32) - 1; + if ((len > TEST_MPS_ITEM_LEN) || (len == 0)) { + ret = SERV_STATUS_AGENT_INVALID_LEN; + goto err; + } + + ret = sys_ad_alloc_mem((u_char **)¶m, sizeof(u_int32) * len); + if (ret) { + ret = SERV_STATUS_AGENT_INVALID_NULL_POINTER; + goto err; + } + + for (idx = 0; idx < len; idx++) { + get_param_and_shift_buf(TRUE, sizeof(u_int32), + &data, (u_char *)&value); + param[idx] = value; + } + + /* Set parameters */ + serv_test->ctrl_band_idx = (u_char)band_idx; + test_config = &serv_test->test_config[band_idx]; + mps_cb = &test_config->mps_cb; + + if (mps_cb->mps_setting == NULL) { + ret = sys_ad_alloc_mem((u_char **)&mps_cb->mps_setting, + sizeof(struct test_mps_setting) * (len+1)); + if (ret) { + sys_ad_free_mem(param); + ret = SERV_STATUS_AGENT_INVALID_NULL_POINTER; + goto err; + } + sys_ad_zero_mem(mps_cb->mps_setting, + sizeof(struct test_mps_setting) * (len+1)); + } + + mps_cb->mps_cnt = len; + mps_setting = mps_cb->mps_setting; + + for (idx = 0; idx < len; idx++) { + if (param[idx] > TEST_MAX_PKT_LEN) + param[idx] = TEST_MAX_PKT_LEN; + else if (param[idx] < TEST_MIN_PKT_LEN) + param[idx] = TEST_MIN_PKT_LEN; + + mps_setting[idx+1].pkt_len = param[idx]; + } + sys_ad_free_mem(param); + + ret = mt_serv_mps_set_payload_length(serv_test); + +err: + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: band_idx=%d, len=%d, op_mode=0x%x, mps_cnt=%d\n", + __func__, band_idx, len, + test_config->op_mode, mps_cb->mps_cnt)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_mps_set_packet_count( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_configuration *test_config = NULL; + struct test_mps_cb *mps_cb = NULL; + struct test_mps_setting *mps_setting = NULL; + u_char *data = hqa_frame->data; + u_int32 *param = NULL; + u_int32 band_idx, idx, value = 0; + u_int16 len; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(band_idx), + &data, (u_char *)&band_idx); + + len = hqa_frame->length / sizeof(u_int32) - 1; + if ((len > TEST_MPS_ITEM_LEN) || (len == 0)) { + ret = SERV_STATUS_AGENT_INVALID_LEN; + goto err; + } + + ret = sys_ad_alloc_mem((u_char **)¶m, sizeof(u_int32) * len); + if (ret) { + ret = SERV_STATUS_AGENT_INVALID_NULL_POINTER; + goto err; + } + + for (idx = 0; idx < len; idx++) { + get_param_and_shift_buf(TRUE, sizeof(u_int32), + &data, (u_char *)&value); + param[idx] = value; + } + + /* Set parameters */ + serv_test->ctrl_band_idx = (u_char)band_idx; + test_config = &serv_test->test_config[band_idx]; + mps_cb = &test_config->mps_cb; + + if (mps_cb->mps_setting == NULL) { + ret = sys_ad_alloc_mem((u_char **)&mps_cb->mps_setting, + sizeof(struct test_mps_setting) * (len+1)); + if (ret) { + sys_ad_free_mem(param); + ret = SERV_STATUS_AGENT_INVALID_NULL_POINTER; + goto err; + } + sys_ad_zero_mem(mps_cb->mps_setting, + sizeof(struct test_mps_setting) * (len+1)); + } + + mps_cb->mps_cnt = len; + mps_setting = mps_cb->mps_setting; + + for (idx = 0; idx < len; idx++) + mps_setting[idx+1].pkt_cnt = param[idx]; + + sys_ad_free_mem(param); + + ret = mt_serv_mps_set_packet_count(serv_test); + +err: + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: band_idx=%d, len=%d, op_mode=0x%x, mps_cnt=%d\n", + __func__, band_idx, len, + test_config->op_mode, mps_cb->mps_cnt)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_mps_set_power_gain( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_configuration *test_config = NULL; + struct test_mps_cb *mps_cb = NULL; + struct test_mps_setting *mps_setting = NULL; + u_char *data = hqa_frame->data; + u_int32 *param = NULL; + u_int32 band_idx, idx, value = 0; + u_int16 len; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(band_idx), + &data, (u_char *)&band_idx); + + len = hqa_frame->length / sizeof(u_int32) - 1; + if ((len > TEST_MPS_ITEM_LEN) || (len == 0)) { + ret = SERV_STATUS_AGENT_INVALID_LEN; + goto err; + } + + ret = sys_ad_alloc_mem((u_char **)¶m, sizeof(u_int32) * len); + if (ret) { + ret = SERV_STATUS_AGENT_INVALID_NULL_POINTER; + goto err; + } + + for (idx = 0; idx < len; idx++) { + get_param_and_shift_buf(TRUE, sizeof(u_int32), + &data, (u_char *)&value); + param[idx] = value; + } + + /* Set parameters */ + serv_test->ctrl_band_idx = (u_char)band_idx; + test_config = &serv_test->test_config[band_idx]; + mps_cb = &test_config->mps_cb; + + if (mps_cb->mps_setting == NULL) { + ret = sys_ad_alloc_mem((u_char **)&mps_cb->mps_setting, + sizeof(struct test_mps_setting) * (len+1)); + if (ret) { + sys_ad_free_mem(param); + ret = SERV_STATUS_AGENT_INVALID_NULL_POINTER; + goto err; + } + sys_ad_zero_mem(mps_cb->mps_setting, + sizeof(struct test_mps_setting) * (len+1)); + } + + mps_cb->mps_cnt = len; + mps_setting = mps_cb->mps_setting; + + for (idx = 0; idx < len; idx++) + mps_setting[idx+1].pwr = param[idx]; + + sys_ad_free_mem(param); + + ret = mt_serv_mps_set_power_gain(serv_test); + +err: + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: band_idx=%d, len=%d, op_mode=0x%x, mps_cnt=%d\n", + __func__, band_idx, len, + test_config->op_mode, mps_cb->mps_cnt)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_mps_start( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_int32 band_idx; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(band_idx), + &data, (u_char *)&band_idx); + + /* Set parameters */ + SERV_SET_PARAM(serv_test, ctrl_band_idx, (u_char)band_idx); + + ret = mt_serv_mps_operation(serv_test, SERV_TEST_MPS_START_TX); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_mps_stop( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_int32 band_idx; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(band_idx), + &data, (u_char *)&band_idx); + + /* Set parameters */ + SERV_SET_PARAM(serv_test, ctrl_band_idx, (u_char)band_idx); + + ret = mt_serv_mps_operation(serv_test, SERV_TEST_MPS_STOP_TX); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_check_efuse_mode_type( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_int32 e2p_cur_mode = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + e2p_cur_mode = (u_int32)WINFO_GET_PARAM(serv_test, e2p_cur_mode); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: e2p_cur_mode=0x%x\n", __func__, e2p_cur_mode)); + + e2p_cur_mode = SERV_OS_HTONL(e2p_cur_mode); + + /* Update hqa_frame with response: status (2 bytes) */ + sys_ad_move_mem(hqa_frame->data + 2, &e2p_cur_mode, + sizeof(e2p_cur_mode)); + update_hqa_frame(hqa_frame, 2 + sizeof(e2p_cur_mode), ret); + + return ret; +} + +static s_int32 hqa_check_efuse_nativemode_type( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_int32 e2p_access_mode = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + e2p_access_mode = (u_int32)WINFO_GET_PARAM(serv_test, e2p_access_mode); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: e2p_access_mode=0x%x\n", __func__, e2p_access_mode)); + + e2p_access_mode = SERV_OS_HTONL(e2p_access_mode); + + /* Update hqa_frame with response: status (2 bytes) */ + sys_ad_move_mem(hqa_frame->data + 2, &e2p_access_mode, + sizeof(e2p_access_mode)); + update_hqa_frame(hqa_frame, 2 + sizeof(e2p_access_mode), ret); + + return ret; +} + +static s_int32 hqa_set_band_mode( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_band_state *band_state; + u_char *data = hqa_frame->data; + u_int32 band_mode = 0, band_type = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(band_mode), + &data, (u_char *)&band_mode); + get_param_and_shift_buf(TRUE, sizeof(band_type), + &data, (u_char *)&band_type); + + /* Set parameters */ + band_state = SERV_GET_PADDR(serv_test, test_bstat); + BSTATE_SET_PARAM(serv_test, band_mode, band_mode); + BSTATE_SET_PARAM(serv_test, band_type, band_type); + + ret = mt_serv_set_band_mode(serv_test); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: band_mode=%u, band_type=%u\n", + __func__, band_mode, band_type)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_get_band_mode( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_band_state *band_state; + u_char *data = hqa_frame->data; + u_int32 band_type = 0, band_idx = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(band_idx), + &data, (u_char *)&band_idx); + + /* Set parameters */ + band_state = SERV_GET_PADDR(serv_test, test_bstat); + serv_test->ctrl_band_idx = (u_char)band_idx; + ret = mt_serv_get_band_mode(serv_test); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: band_type=%u\n", + __func__, band_type)); + + band_type = SERV_OS_HTONL(band_state->band_type); + + /* Update hqa_frame with response: status (2 bytes) */ + sys_ad_move_mem(hqa_frame->data + 2, &band_type, sizeof(band_type)); + update_hqa_frame(hqa_frame, 2 + sizeof(band_type), ret); + + return ret; +} + +static s_int32 hqa_rdd_start( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_int32 rdd_num = 0; + u_int32 rdd_sel = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(rdd_num), + &data, (u_char *)&rdd_num); + get_param_and_shift_buf(TRUE, sizeof(rdd_sel), + &data, (u_char *)&rdd_sel); + + ret = mt_serv_set_rdd_on_off(serv_test, rdd_num, rdd_sel, TRUE); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: rdd_num: %d, rdd_sel: %d\n", + __func__, rdd_num, rdd_sel)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_rdd_stop( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_int32 rdd_num = 0; + u_int32 rdd_sel = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(rdd_num), + &data, (u_char *)&rdd_num); + get_param_and_shift_buf(TRUE, sizeof(rdd_sel), + &data, (u_char *)&rdd_sel); + + ret = mt_serv_set_rdd_on_off(serv_test, rdd_num, rdd_sel, FALSE); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: rdd_num: %d, rdd_sel: %d\n", + __func__, rdd_num, rdd_sel)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_log_on_off( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_int32 band_idx = 0, log_type = 0, log_ctrl = 0, log_size = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(band_idx), + &data, (u_char *)&band_idx); + get_param_and_shift_buf(TRUE, sizeof(log_type), + &data, (u_char *)&log_type); + get_param_and_shift_buf(TRUE, sizeof(log_ctrl), + &data, (u_char *)&log_ctrl); + get_param_and_shift_buf(TRUE, sizeof(log_size), + &data, (u_char *)&log_size); + + /* Set parameters */ + SERV_SET_PARAM(serv_test, ctrl_band_idx, (u_char)band_idx); + + ret = mt_serv_log_on_off(serv_test, log_type, log_ctrl, log_size); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_mps_set_nss( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_configuration *test_config = NULL; + struct test_mps_cb *mps_cb = NULL; + struct test_mps_setting *mps_setting = NULL; + u_char *data = hqa_frame->data; + u_int32 *param = NULL; + u_int32 band_idx, idx, value = 0; + u_int16 len; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(band_idx), + &data, (u_char *) &band_idx); + + len = hqa_frame->length / sizeof(u_int32) - 1; + if ((len > TEST_MPS_ITEM_LEN) || (len == 0)) { + ret = SERV_STATUS_AGENT_INVALID_LEN; + goto err; + } + + ret = sys_ad_alloc_mem((u_char **)¶m, sizeof(u_int32) * len); + if (ret) { + ret = SERV_STATUS_AGENT_INVALID_NULL_POINTER; + goto err; + } + + for (idx = 0; idx < len; idx++) { + get_param_and_shift_buf(TRUE, sizeof(u_int32), + &data, (u_char *) &value); + param[idx] = value; + } + + /* Set parameters */ + serv_test->ctrl_band_idx = (u_char)band_idx; + test_config = &serv_test->test_config[band_idx]; + mps_cb = &test_config->mps_cb; + + if (mps_cb->mps_setting == NULL) { + ret = sys_ad_alloc_mem((u_char **)&mps_cb->mps_setting, + sizeof(struct test_mps_setting) * (len+1)); + if (ret) { + sys_ad_free_mem(param); + ret = SERV_STATUS_AGENT_INVALID_NULL_POINTER; + goto err; + } + sys_ad_zero_mem(mps_cb->mps_setting, + sizeof(struct test_mps_setting) * (len+1)); + } + + mps_cb->mps_cnt = len; + mps_setting = mps_cb->mps_setting; + + for (idx = 0; idx < len; idx++) + mps_setting[idx+1].nss = param[idx]; + + sys_ad_free_mem(param); + + ret = mt_serv_mps_set_nss(serv_test); + +err: + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: band_idx=%d, len=%d, op_mode=0x%x, mps_cnt=%d\n", + __func__, band_idx, len, + test_config->op_mode, mps_cb->mps_cnt)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_mps_set_per_packet_bw( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_configuration *test_config = NULL; + struct test_mps_cb *mps_cb = NULL; + struct test_mps_setting *mps_setting = NULL; + u_char *data = hqa_frame->data; + u_int32 *param = NULL; + u_int32 band_idx, idx, value = 0; + u_int16 len; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(band_idx), + &data, (u_char *)&band_idx); + + len = hqa_frame->length / sizeof(u_int32) - 1; + if ((len > TEST_MPS_ITEM_LEN) || (len == 0)) { + ret = SERV_STATUS_AGENT_INVALID_LEN; + goto err; + } + + ret = sys_ad_alloc_mem((u_char **)¶m, sizeof(u_int32) * len); + if (ret) { + ret = SERV_STATUS_AGENT_INVALID_NULL_POINTER; + goto err; + } + + for (idx = 0; idx < len; idx++) { + get_param_and_shift_buf(TRUE, sizeof(u_int32), + &data, (u_char *) &value); + + switch (value) { + case 0: + value = TEST_BW_20; + break; + + case 1: + value = TEST_BW_40; + break; + + case 2: + value = TEST_BW_80; + break; + + case 3: + value = TEST_BW_10; + break; + + case 4: + value = TEST_BW_5; + break; + + case 5: + value = TEST_BW_160C; + break; + + case 6: + value = TEST_BW_160NC; + break; + + default: + value = TEST_BW_20; + break; + } + + param[idx] = value; + } + + /* Set parameters */ + serv_test->ctrl_band_idx = (u_char)band_idx; + test_config = &serv_test->test_config[band_idx]; + mps_cb = &test_config->mps_cb; + + if (mps_cb->mps_setting == NULL) { + ret = sys_ad_alloc_mem((u_char **)&mps_cb->mps_setting, + sizeof(struct test_mps_setting) * (len+1)); + if (ret) { + sys_ad_free_mem(param); + ret = SERV_STATUS_AGENT_INVALID_NULL_POINTER; + goto err; + } + sys_ad_zero_mem(mps_cb->mps_setting, + sizeof(struct test_mps_setting) * (len+1)); + } + + mps_cb->mps_cnt = len; + mps_setting = mps_cb->mps_setting; + + for (idx = 0; idx < len; idx++) + mps_setting[idx+1].pkt_bw = param[idx]; + + sys_ad_free_mem(param); + + ret = mt_serv_mps_set_per_packet_bw(serv_test); + +err: + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: band_idx=%d, len=%d, op_mode=0x%x, mps_cnt=%d\n", + __func__, band_idx, len, + test_config->op_mode, mps_cb->mps_cnt)); + + /* Update hqa_frame with response: status (2 bytes) */ + update_hqa_frame(hqa_frame, 2, ret); + + return ret; +} + +static s_int32 hqa_icap_ctrl( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + s_int32 icap_stat = 0; + u_char *data = hqa_frame->data; + u_int32 wf_num = 0, iq_type = 0; + u_int32 control = 0, resp_len = 2; + u_int32 value = 0, i = 0; + u_long max_data_len = 0; + u_char src_addr[SERV_MAC_ADDR_LEN]; + s_int32 *icap_data = NULL; + s_int32 *icap_data_cnt = NULL; + struct hqa_rbist_cap_start icap_info; + + get_param_and_shift_buf(TRUE, sizeof(control), + &data, (u_char *)&control); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: control: %d\n", __func__, control)); + + switch (control) { + case 1: + /* clear memory */ + sys_ad_zero_mem(&icap_info, sizeof(icap_info)); + + get_param_and_shift_buf(TRUE, sizeof(icap_info.trig), + &data, (u_char *)&(icap_info.trig)); + + get_param_and_shift_buf(TRUE, sizeof(icap_info.ring_cap_en), + &data, (u_char *)&(icap_info.ring_cap_en)); + + get_param_and_shift_buf(TRUE, sizeof(icap_info.trig_event), + &data, (u_char *)&(icap_info.trig_event)); + + get_param_and_shift_buf(TRUE, sizeof(icap_info.cap_node), + &data, (u_char *)&(icap_info.cap_node)); + + get_param_and_shift_buf(TRUE, sizeof(icap_info.cap_len), + &data, (u_char *)&(icap_info.cap_len)); + + get_param_and_shift_buf(TRUE, sizeof(icap_info.cap_stop_cycle), + &data, (u_char *)&(icap_info.cap_stop_cycle)); + + get_param_and_shift_buf(TRUE, sizeof(icap_info.bw), + &data, (u_char *)&(icap_info.bw)); + + get_param_and_shift_buf(TRUE, sizeof(icap_info.mac_trig_event), + &data, (u_char *)&(icap_info.mac_trig_event)); + + get_param_and_shift_buf(FALSE, SERV_MAC_ADDR_LEN, + &data, (u_char *)src_addr); + + get_param_and_shift_buf(TRUE, sizeof(icap_info.band_idx), + &data, (u_char *)&(icap_info.band_idx)); + + get_param_and_shift_buf(TRUE, sizeof(icap_info.phy_idx), + &data, (u_char *)&(icap_info.phy_idx)); + + get_param_and_shift_buf(TRUE, sizeof(icap_info.cap_src), + &data, (u_char *)&(icap_info.cap_src)); + + /* source address lsb */ + for (i = 0; i < 4; i++) + icap_info.src_addr_lsb |= ((src_addr[i]) << (i << 3)); + + /* source address msb */ + for (i = 0; i < 2; i++) + icap_info.src_addr_msb |= ((src_addr[i+4]) << (i << 3)); + icap_info.src_addr_msb |= ((0x1) << 16); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: trig = 0x%08x, ring_cap_en = 0x%08x\n" + , __func__, icap_info.trig, icap_info.ring_cap_en)); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: trig_event = 0x%08x, cap_node = 0x%08x\n" + , __func__, icap_info.trig_event, icap_info.cap_node)); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: cap_len = 0x%08x, cap_stop_cycle = 0x%08x\n" + , __func__, icap_info.cap_len, icap_info.cap_stop_cycle)); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: bw = 0x%08x, mac_trig_event = 0x%08x\n" + , __func__, icap_info.bw, icap_info.mac_trig_event)); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: src_addr_msb = 0x%08x, src_addr_lsb = 0x%08x\n" + , __func__, icap_info.src_addr_msb, icap_info.src_addr_lsb)); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: band_idx = 0x%08x, phy_idx = 0x%08x\n" + , __func__, icap_info.band_idx, icap_info.phy_idx)); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: cap_src = 0x%08x\n", __func__, icap_info.cap_src)); + + ret = mt_serv_set_icap_start(serv_test, &icap_info); + if (ret) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s : mt_serv_set_icap_start is failed!!\n" + , __func__)); + goto error1; + } + break; + + case 2: + ret = mt_serv_get_icap_status(serv_test, &icap_stat); + if (ret) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s : mt_serv_get_icap_status is failed!!\n" + , __func__)); + goto error1; + } else { + ret = icap_stat; + update_hqa_frame(hqa_frame, resp_len, ret); + return SERV_STATUS_SUCCESS; + } + break; + + case 3: + get_param_and_shift_buf(TRUE, sizeof(wf_num), + &data, (u_char *)&(wf_num)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: wf_num: %d\n", __func__, wf_num)); + + get_param_and_shift_buf(TRUE, sizeof(iq_type), + &data, (u_char *)&(iq_type)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: iq_type: %d\n", __func__, iq_type)); + + ret = sys_ad_alloc_mem((u_char **)&icap_data_cnt + , sizeof(s_int32)); + if (ret) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s : Not enough memory for dynamic allocating!!\n" + , __func__)); + goto error1; + } + sys_ad_zero_mem(icap_data_cnt, sizeof(s_int32)); + + ret = mt_serv_get_icap_max_data_len(serv_test, &max_data_len); + if (ret || (max_data_len == 0)) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s : mt_serv_get_icap_max_data_len is failed!!\n" + , __func__)); + goto error1; + } + + ret = sys_ad_alloc_mem((u_char **)&icap_data, max_data_len); + if (ret) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s : Not enough memory for dynamic allocating!!\n" + , __func__)); + goto error1; + } + sys_ad_zero_mem(icap_data, max_data_len); + + ret = mt_serv_get_icap_data(serv_test, + icap_data_cnt, icap_data, wf_num, iq_type); + if (ret) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s : mt_serv_get_icap_data is not supported!!\n" + , __func__)); + goto error1; + } + + value = SERV_OS_HTONL(control); + sys_ad_move_mem(hqa_frame->data + resp_len, + &value, sizeof(value)); + resp_len += sizeof(value); + value = SERV_OS_HTONL(wf_num); + sys_ad_move_mem(hqa_frame->data + resp_len, + &value, sizeof(value)); + resp_len += sizeof(value); + value = SERV_OS_HTONL(iq_type); + sys_ad_move_mem(hqa_frame->data + resp_len, + &value, sizeof(value)); + resp_len += sizeof(value); + value = SERV_OS_HTONL(*icap_data_cnt); + sys_ad_move_mem(hqa_frame->data + resp_len, + &value, sizeof(value)); + resp_len += sizeof(value); + + for (i = 0; i < *icap_data_cnt; i++) { + value = SERV_OS_HTONL(icap_data[i]); + sys_ad_move_mem(hqa_frame->data + resp_len, + &value, sizeof(value)); + resp_len += sizeof(value); + } + break; + + default: + break; + } + +error1: + if (ret) + ret = SERV_STATUS_AGENT_NOT_SUPPORTED; + + update_hqa_frame(hqa_frame, resp_len, ret); + + if (icap_data_cnt) + sys_ad_free_mem(icap_data_cnt); + + if (icap_data) + sys_ad_free_mem(icap_data); + + return ret; +} + +static s_int32 hqa_get_dump_recal( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_int32 resp_len = 6; + u_char *data = hqa_frame->data; + u_int32 band_idx = 0; + u_int32 recal_cnt = 0, recal_dw_num = 0; + u_int32 *content = NULL, *OriAddr = NULL; + u_int32 value = 0, dw_cnt = 0, i = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(band_idx), + &data, (u_char *)&band_idx); + + serv_test->ctrl_band_idx = (u_char)band_idx; + + ret = mt_serv_get_recal_cnt(serv_test, + &recal_cnt, &recal_dw_num); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: band_idx: %d, rxv_cnt: %d, rxv_dw_num: %d\n", + __func__, band_idx, recal_cnt, recal_dw_num)); + + dw_cnt = recal_cnt * recal_dw_num; + + ret = sys_ad_alloc_mem((u_char **)&content, + sizeof(*content) * dw_cnt); + if (ret != SERV_STATUS_SUCCESS) + goto error1; + + OriAddr = content; + + ret = mt_serv_get_recal_content(serv_test, content); + + /* Update hqa_frame with response: status (2 bytes) */ + value = SERV_OS_HTONL(recal_cnt); + sys_ad_move_mem(hqa_frame->data + 2, + &value, sizeof(value)); + + for (i = 0; i < dw_cnt; i++, content++) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: content[%d]: 0x%x\n", __func__, i, *content)); + + value = SERV_OS_HTONL(*content); + sys_ad_move_mem(hqa_frame->data + resp_len, + &value, sizeof(value)); + + resp_len += sizeof(value); + } + + /* Free memory */ + sys_ad_free_mem(OriAddr); + + update_hqa_frame(hqa_frame, resp_len, ret); + + return ret; + +error1: + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: dynamic memory allocate fail!!\n", __func__)); + if (content) + sys_ad_free_mem(content); + /* TODO: respond to application for error handle */ + update_hqa_frame(hqa_frame, resp_len, ret); + + return ret; +} + +static s_int32 hqa_get_dump_rxv( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_int32 resp_len = 2; + u_char *data = hqa_frame->data; + u_int32 band_idx = 0; + u_int32 rxv_cnt = 0, rxv_dw_num = 0; + u_int32 *content = NULL, *OriAddr = NULL; + u_int32 value = 0, dw_cnt = 0, i = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(band_idx), + &data, (u_char *)&band_idx); + + serv_test->ctrl_band_idx = (u_char)band_idx; + + ret = mt_serv_get_rxv_cnt(serv_test, &rxv_cnt, &rxv_dw_num); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: band_idx: %d, rxv_cnt: %d, rxv_dw_num: %d\n", + __func__, band_idx, rxv_cnt, rxv_dw_num)); + + dw_cnt = rxv_cnt * rxv_dw_num; + ret = sys_ad_alloc_mem((u_char **)&content, + sizeof(*content) * dw_cnt); + if (ret != SERV_STATUS_SUCCESS) + goto error1; + + OriAddr = content; + + ret = mt_serv_get_rxv_content(serv_test, dw_cnt, content); + + /* Update hqa_frame with response: Count (2 bytes) */ + value = SERV_OS_HTONL(rxv_cnt); + sys_ad_move_mem(hqa_frame->data + resp_len, + &value, sizeof(value)); + + resp_len += sizeof(value); + + for (i = 0; i < dw_cnt; i += 4, content++) { + value = SERV_OS_HTONL(*content); + sys_ad_move_mem(hqa_frame->data + resp_len, + &value, sizeof(value)); + resp_len += sizeof(value); + } + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: resp_len = %d\n", __func__, resp_len)); + + /* Free memory */ + sys_ad_free_mem(OriAddr); + + update_hqa_frame(hqa_frame, resp_len, ret); + + return ret; + +error1: + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: dynamic memory allocate fail!!\n", __func__)); + if (content) + sys_ad_free_mem(content); + /* TODO: respond to application for error handle */ + update_hqa_frame(hqa_frame, resp_len, ret); + + return ret; +} + +static s_int32 hqa_get_dump_rdd( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_int32 resp_len = 2; + u_char *data = hqa_frame->data; + u_int32 band_idx = 0; + u_int32 rdd_cnt = 0, rdd_dw_num = 0; + u_int32 *content = NULL, *OriAddr = NULL; + u_int32 value = 0, i = 0, total_cnt = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(band_idx), + &data, (u_char *)&band_idx); + + serv_test->ctrl_band_idx = (u_char)band_idx; + + ret = mt_serv_get_rdd_cnt(serv_test, &rdd_cnt, &rdd_dw_num); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: band_idx: %d, pulse number: %d, rdd buffer size: %d\n", + __func__, band_idx, rdd_cnt, rdd_dw_num)); + + ret = sys_ad_alloc_mem((u_char **)&content, + sizeof(*content) * rdd_dw_num); + if (ret != SERV_STATUS_SUCCESS) + goto error1; + + OriAddr = content; + + ret = mt_serv_get_rdd_content(serv_test, content, &total_cnt); + + if (total_cnt > 0) { + /* Update hqa_frame with response: status (2 bytes) */ + /* Response format: + * cmd type + cmd ID + length + Sequence + + * data: + * status (2 bytes) + + * [count (4 bytes)] + value1 (4 bytes) + value2 (4 bytes) + */ + /* Count = Total number of 4 bytes RDD values divided by 2 */ + value = SERV_OS_HTONL(total_cnt/2); + sys_ad_move_mem(hqa_frame->data + resp_len, + &value, sizeof(value)); + resp_len += sizeof(value); + + for (i = 0; i < total_cnt; i++, content++) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: content[%d]: 0x%08x\n", + __func__, i, *content)); + + value = SERV_OS_HTONL(*content); + sys_ad_move_mem(hqa_frame->data + resp_len, + &value, sizeof(value)); + resp_len += sizeof(value); + } + + } else { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: total_cnt %d\n", __func__, total_cnt)); + sys_ad_move_mem(hqa_frame->data + resp_len, + &total_cnt, sizeof(total_cnt)); + resp_len += sizeof(total_cnt); + } + + /* Free memory */ + sys_ad_free_mem(OriAddr); + + update_hqa_frame(hqa_frame, resp_len, ret); + + return ret; + +error1: + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: dynamic memory allocate fail!!\n", __func__)); + if (content) + sys_ad_free_mem(content); + /* TODO: respond to application for error handle */ + update_hqa_frame(hqa_frame, resp_len, ret); + + return ret; +} + +static s_int32 hqa_get_hetb_info( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_int32 resp_len = 2; + u_char band_idx = serv_test->ctrl_band_idx; + u_int32 afactor = 0, ldpc_str_sym = 0, pe_disamb = 0; + u_int32 tx_pe = 0, l_sig_len = 0, value = 0; + u_int8 dmnt_ru_idx = 0; + struct test_ru_info *ru_info = NULL; + + dmnt_ru_idx = CONFIG_GET_PARAM(serv_test, dmnt_ru_idx, band_idx); + ru_info = CONFIG_GET_PADDR(serv_test, + ru_info_list[dmnt_ru_idx], + band_idx); + afactor = ru_info->afactor_init; + ldpc_str_sym = ru_info->ldpc_extr_sym; + pe_disamb = ru_info->pe_disamb; + tx_pe = ru_info->t_pe; + l_sig_len = ru_info->l_len; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: band_idx:0x%x, dmnt_ru_idx:0x%x afactor:0x%x\n", + __func__, band_idx, dmnt_ru_idx, afactor)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("ldpc_str_sym:0x%x, pe_disamb:0x%x\n", + ldpc_str_sym, pe_disamb)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("tx_pe:0x%x,l_sig_len:0x%x\n", + tx_pe, l_sig_len)); + + /* The response array should be a-factor, + * ldpc extra symbol, + * PE disambiguilty, + * TX PE, + * L-SIG length + */ + value = SERV_OS_HTONL(afactor); + sys_ad_move_mem(hqa_frame->data + 2, &value, sizeof(value)); + value = SERV_OS_HTONL(ldpc_str_sym); + sys_ad_move_mem(hqa_frame->data + 2 + sizeof(value), &value, + sizeof(value)); + value = SERV_OS_HTONL(pe_disamb); + sys_ad_move_mem(hqa_frame->data + 2 + sizeof(value)*2, + &value, sizeof(value)); + value = SERV_OS_HTONL(tx_pe); + sys_ad_move_mem(hqa_frame->data + 2 + sizeof(value)*3, &value, + sizeof(value)); + value = SERV_OS_HTONL(l_sig_len); + sys_ad_move_mem(hqa_frame->data + 2 + sizeof(value)*4, &value, + sizeof(value)); + resp_len += 5*sizeof(u_int32); + + update_hqa_frame(hqa_frame, resp_len, ret); + + return ret; +} + +static s_int32 hqa_translate_ru_allocation( + u_int32 user_ru_allocation, + u_int32 *allocation) +{ + u_int8 i = 0; + + *allocation = 0; + for (i = 0 ; i < sizeof(u_int32)*2 ; i++) { + *allocation |= ((user_ru_allocation & 0x1) << i); + user_ru_allocation >>= 4; + } + + return SERV_STATUS_SUCCESS; +} + +static s_int32 hqa_set_ru_info( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_int32 resp_len = 2; + u_int32 band_idx = 0; + u_int32 len = 0, seg_sta_cnt[2] = {0}, sta_seq = 0, value = 0; + u_char param_cnt = 0, segment_idx = 0, param_loop = 0; + u_char *data = hqa_frame->data; + u_int32 mpdu_length = 0; + struct test_ru_allocatoin *ru_allocation = NULL; + struct test_ru_info *ru_info = NULL; + + len = hqa_frame->length; + + get_param_and_shift_buf(TRUE, + sizeof(u_int32), + &data, + (u_char *)&band_idx); + get_param_and_shift_buf(TRUE, + sizeof(u_int32), + &data, + (u_char *)&seg_sta_cnt[0]); + get_param_and_shift_buf(TRUE, + sizeof(u_int32), + &data, + (u_char *)&seg_sta_cnt[1]); + len -= sizeof(u_int32)*3; /* array length */ + + if (seg_sta_cnt[0]+seg_sta_cnt[1] == 0) + return SERV_STATUS_AGENT_INVALID_LEN; + + len /= (seg_sta_cnt[0]+seg_sta_cnt[1]); /* per ru length */ + param_cnt = len/sizeof(u_int32); /* param count */ + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: Band:%d [ru_segment 0]:%d, [ru_segment 1]:%d\n", + __func__, band_idx, seg_sta_cnt[0], seg_sta_cnt[1])); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("\t\tparameters count:%d\n", param_cnt)); + + mpdu_length = CONFIG_GET_PARAM(serv_test, tx_len, band_idx); + ru_allocation = CONFIG_GET_PADDR(serv_test, ru_alloc, band_idx); + ru_info = CONFIG_GET_PADDR(serv_test, ru_info_list[0], band_idx); + sys_ad_zero_mem(ru_info, sizeof(struct test_ru_info)*MAX_MULTI_TX_STA); + sys_ad_set_mem(ru_allocation, sizeof(*ru_allocation), 0xff); + + /* for maximum bw 80+80/160, 2 segments only */ + for (sta_seq = 0; + sta_seq < seg_sta_cnt[0]+seg_sta_cnt[1]; + sta_seq++) { + param_loop = param_cnt; + + if (sta_seq < seg_sta_cnt[0]) + segment_idx = 0; + else + segment_idx = 1; + + ru_info[sta_seq].valid = TRUE; + /* ru caterogy */ + get_param_and_shift_buf(TRUE, + sizeof(u_int32), + &data, + (u_char *)&value); + param_loop--; + /* ru allocation */ + get_param_and_shift_buf(TRUE, + sizeof(u_int32), + &data, + (u_char *)&value); + param_loop--; + hqa_translate_ru_allocation(value, + &ru_info[sta_seq].allocation); + /* aid */ + get_param_and_shift_buf(TRUE, + sizeof(u_int32), + &data, + (u_char *)&value); + param_loop--; + ru_info[sta_seq].aid = value; + get_param_and_shift_buf(TRUE, + sizeof(u_int32), + &data, + (u_char *)&value); + param_loop--; + ru_info[sta_seq].ru_index = (value << 1) | segment_idx; + get_param_and_shift_buf(TRUE, + sizeof(u_int32), + &data, + (u_char *)&value); + param_loop--; + ru_info[sta_seq].rate = value; + get_param_and_shift_buf(TRUE, + sizeof(u_int32), + &data, + (u_char *)&value); + param_loop--; + ru_info[sta_seq].ldpc = value; + get_param_and_shift_buf(TRUE, + sizeof(u_int32), + &data, + (u_char *)&value); + param_loop--; + ru_info[sta_seq].nss = value; + if (ru_info[sta_seq].nss == 0) + ru_info[sta_seq].nss = 1; + + get_param_and_shift_buf(TRUE, + sizeof(u_int32), + &data, + (u_char *)&value); + param_loop--; + ru_info[sta_seq].start_sp_st = value-1; + get_param_and_shift_buf(TRUE, + sizeof(u_int32), + &data, + (u_char *)&value); + param_loop--; + if (value > 24) + ru_info[sta_seq].mpdu_length = value; + else + ru_info[sta_seq].mpdu_length = mpdu_length; + + if (param_loop) { + get_param_and_shift_buf(TRUE, + sizeof(u_int32), + &data, + (u_char *)&value); + param_loop--; + ru_info[sta_seq].alpha = value; + } else + ru_info[sta_seq].alpha = 1; /* default value */ + + if (param_loop) { + get_param_and_shift_buf(TRUE, + sizeof(u_int32), + &data, + (u_char *)&value); + param_loop--; + ru_info[sta_seq].ru_mu_nss = value; + } else + ru_info[sta_seq].ru_mu_nss = 1; /* default value */ + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: ru_segment[%d][0x%x]: ru_idx:%d\n", + __func__, segment_idx, + ru_info[sta_seq].allocation, + ru_info[sta_seq].ru_index >> 1)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("\t\t\t\trate:%x, ldpc:%d\n", + ru_info[sta_seq].rate, + ru_info[sta_seq].ldpc)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("\t\t\t\tnss:%d, mimo nss:%d\n", + ru_info[sta_seq].nss, + ru_info[sta_seq].ru_mu_nss)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("\t\t\t\t start spatial stream:%d,\n", + ru_info[sta_seq].start_sp_st)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("\t\t\t\tmpdu length=%d, alpha:%d\n", + ru_info[sta_seq].mpdu_length, + ru_info[sta_seq].alpha)); + } + + update_hqa_frame(hqa_frame, resp_len, ret); + + return ret; +} + +static struct hqa_cmd_entry CMD_SET5[] = { + /* cmd id start from 0x1500 */ + {0x0, hqa_get_fw_info}, + {0x1, legacy_function}, + {0x2, hqa_set_stbc}, + {0x3, hqa_set_short_gi}, + {0x4, hqa_set_dpd}, + {0x5, hqa_set_tssi_onoff}, + {0x6, hqa_get_rx_statistics_leg}, + {0x7, legacy_function}, + {0x8, legacy_function}, + {0x9, hqa_calibration_test_mode}, + {0xa, hqa_do_cal_item}, + {0xf, hqa_tmr_setting}, + {0x10, legacy_function}, + {0x11, todo_function}, + {0x12, legacy_function}, + {0x13, legacy_function}, + {0x14, hqa_get_chipid}, + {0x15, hqa_mps_set_seq_data}, + {0x16, hqa_mps_set_payload_length}, + {0x17, hqa_mps_set_packet_count}, + {0x18, hqa_mps_set_power_gain}, + {0x19, hqa_mps_start}, + {0x1a, hqa_mps_stop}, + {0x1c, hqa_get_rx_statistics_all}, + {0x1d, hqa_get_capability}, + {0x21, legacy_function}, + {0x22, hqa_check_efuse_mode_type}, + {0x23, hqa_check_efuse_nativemode_type}, + {0x24, legacy_function}, + {0x25, legacy_function}, + {0x26, legacy_function}, + {0x27, legacy_function}, + {0x28, legacy_function}, + {0x29, legacy_function}, + {0x2c, hqa_set_band_mode}, + {0x2d, hqa_get_band_mode}, + {0x2e, hqa_rdd_start}, + {0x2f, hqa_rdd_stop}, + {0x31, legacy_function}, + {0x32, legacy_function}, + {0x33, hqa_log_on_off}, + {0x34, legacy_function}, + {0x35, legacy_function}, + {0x36, hqa_mps_set_nss}, + {0x37, hqa_mps_set_per_packet_bw}, + {0x80, hqa_icap_ctrl}, + {0x81, hqa_get_dump_recal}, + {0x82, hqa_get_dump_rxv}, + {0x83, hqa_get_dump_rdd}, + {0x91, hqa_get_hetb_info}, + {0x94, hqa_set_ru_info} +}; + +static s_int32 hqa_set_channel_ext( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct hqa_set_ch param; + u_char *data = hqa_frame->data; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + sys_ad_zero_mem(¶m, sizeof(param)); + + get_param_and_shift_buf(TRUE, sizeof(param.ext_id), + &data, (u_char *)¶m.ext_id); + get_param_and_shift_buf(TRUE, sizeof(param.num_param), + &data, (u_char *)¶m.num_param); + get_param_and_shift_buf(TRUE, sizeof(param.band_idx), + &data, (u_char *)¶m.band_idx); + get_param_and_shift_buf(TRUE, sizeof(param.central_ch0), + &data, (u_char *)¶m.central_ch0); + get_param_and_shift_buf(TRUE, sizeof(param.central_ch1), + &data, (u_char *)¶m.central_ch1); + get_param_and_shift_buf(TRUE, sizeof(param.sys_bw), + &data, (u_char *)¶m.sys_bw); + get_param_and_shift_buf(TRUE, sizeof(param.perpkt_bw), + &data, (u_char *)¶m.perpkt_bw); + get_param_and_shift_buf(TRUE, sizeof(param.pri_sel), + &data, (u_char *)¶m.pri_sel); + get_param_and_shift_buf(TRUE, sizeof(param.reason), + &data, (u_char *)¶m.reason); + get_param_and_shift_buf(TRUE, sizeof(param.ch_band), + &data, (u_char *)¶m.ch_band); + get_param_and_shift_buf(TRUE, sizeof(param.out_band_freq), + &data, (u_char *)¶m.out_band_freq); + + if (param.band_idx < TEST_DBDC_BAND_NUM) { + /* Set parameters */ + SERV_SET_PARAM(serv_test, ctrl_band_idx, + (u_char)param.band_idx); + CONFIG_SET_PARAM(serv_test, channel, + (u_char)param.central_ch0, param.band_idx); + CONFIG_SET_PARAM(serv_test, channel_2nd, + (u_char)param.central_ch1, param.band_idx); + CONFIG_SET_PARAM(serv_test, per_pkt_bw, + (u_char)param.perpkt_bw, param.band_idx); + CONFIG_SET_PARAM(serv_test, bw, + (u_char)param.sys_bw, param.band_idx); + CONFIG_SET_PARAM(serv_test, pri_sel, + (u_char)param.pri_sel, param.band_idx); + CONFIG_SET_PARAM(serv_test, ch_band, + (u_char)param.ch_band, param.band_idx); + CONFIG_SET_PARAM(serv_test, out_band_freq, + (u_int32)param.out_band_freq, param.band_idx); + + ret = mt_serv_set_channel(serv_test); + } else + ret = SERV_STATUS_AGENT_INVALID_BANDIDX; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: band_idx: %d, ch0: %d, ch1: %d, sys_bw: %d, ", + __func__, param.band_idx, param.central_ch0, + param.central_ch1, param.sys_bw)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("perpkt_bw: %d, pri_sel: %d, ch_band: %d\n", + param.perpkt_bw, param.pri_sel, param.ch_band)); + + /* Update hqa_frame with response: status (2 bytes) */ + sys_ad_move_mem(hqa_frame->data + 2, (u_char *) ¶m.ext_id, 4); + update_hqa_frame(hqa_frame, 6, ret); + + return ret; +} + +static s_int32 hqa_set_txcontent_ext( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct hqa_tx_content param; + struct serv_hdr_802_11 *phdr = NULL; + u_char *data = hqa_frame->data; + u_char *payload, sta_seq = 0; + boolean enable = FALSE; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + sys_ad_zero_mem(¶m, sizeof(param)); + + get_param_and_shift_buf(TRUE, sizeof(param.ext_id), + &data, (u_char *)¶m.ext_id); + get_param_and_shift_buf(TRUE, sizeof(param.num_param), + &data, (u_char *)¶m.num_param); + get_param_and_shift_buf(TRUE, sizeof(param.band_idx), + &data, (u_char *)¶m.band_idx); + get_param_and_shift_buf(TRUE, sizeof(param.fc), + &data, (u_char *)¶m.fc); + get_param_and_shift_buf(TRUE, sizeof(param.dur), + &data, (u_char *)¶m.dur); + get_param_and_shift_buf(TRUE, sizeof(param.seq), + &data, (u_char *)¶m.seq); + get_param_and_shift_buf(TRUE, sizeof(param.fixed_payload), + &data, (u_char *)¶m.fixed_payload); + get_param_and_shift_buf(TRUE, sizeof(param.txlen), + &data, (u_char *)¶m.txlen); + get_param_and_shift_buf(TRUE, sizeof(param.payload_len), + &data, (u_char *)¶m.payload_len); + get_param_and_shift_buf(FALSE, SERV_MAC_ADDR_LEN, + &data, param.addr1); + get_param_and_shift_buf(FALSE, SERV_MAC_ADDR_LEN, + &data, param.addr2); + get_param_and_shift_buf(FALSE, SERV_MAC_ADDR_LEN, + &data, param.addr3); + + /* 52 for the size before payload */ + if (param.payload_len > TEST_MAX_PATTERN_SIZE) + param.payload_len = TEST_MAX_PATTERN_SIZE; + + /* Set parameters */ + SERV_SET_PARAM(serv_test, ctrl_band_idx, (u_char)param.band_idx); + for (sta_seq = 0; sta_seq < MAX_MULTI_TX_STA ; sta_seq++) { + CONFIG_SET_PADDR(serv_test, addr1[sta_seq], param.addr1, + SERV_MAC_ADDR_LEN, param.band_idx); + CONFIG_SET_PADDR(serv_test, addr2[sta_seq], param.addr2, + SERV_MAC_ADDR_LEN, param.band_idx); + CONFIG_SET_PADDR(serv_test, addr3[sta_seq], param.addr3, + SERV_MAC_ADDR_LEN, param.band_idx); + } + CONFIG_SET_PARAM(serv_test, dur, + (u_short)param.dur, param.band_idx); + CONFIG_SET_PARAM(serv_test, seq, + (u_short)param.seq, param.band_idx); + CONFIG_SET_PARAM(serv_test, pl_len, + (u_int32)param.payload_len, param.band_idx); + CONFIG_SET_PARAM(serv_test, tx_len, + (u_int32)param.txlen, param.band_idx); + CONFIG_SET_PARAM(serv_test, fixed_payload, + (u_int32)param.fixed_payload, param.band_idx); + + payload = CONFIG_GET_PADDR(serv_test, payload[0], param.band_idx); + phdr = (struct serv_hdr_802_11 *)CONFIG_GET_PADDR(serv_test, + template_frame, + param.band_idx); + sys_ad_move_mem(&phdr->fc, ¶m.fc, sizeof(phdr->fc)); + phdr->duration = (u_int16)param.dur; + phdr->sequence = (u_int16)param.seq; + + /* Error check for txlen and payload_len */ + /* the fixed_payload means Normal : 0, repeat:1 , random:2*/ + /* random:2 dont follow this rule*/ + if ((param.txlen == 0) || + ((param.payload_len == 0) && (param.fixed_payload != 2))) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: txlen/payload_len=%u/%u can't be 0!!\n", + __func__, param.txlen, param.payload_len)); + return SERV_STATUS_AGENT_INVALID_LEN; + } + + /* Packet tx time feature implementation */ + enable = CONFIG_GET_PARAM(serv_test, tx_time_param.pkt_tx_time_en, + param.band_idx); + if (enable == TRUE) { + CONFIG_SET_PARAM(serv_test, tx_time_param.pkt_tx_time, + (u_int32)param.txlen, param.band_idx); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: fc=0x%04x, dur=%u, seq=%u, plen=%u\n", + __func__, param.fc, param.dur, param.seq, + param.payload_len)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: pkt_tx_time=%u, genpkt=%u\n", + __func__, param.txlen, + param.fixed_payload)); + } else { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: fc=0x%04x, dur=%u, seq=%u, plen=%u\n", + __func__, param.fc, param.dur, param.seq, + param.payload_len)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: txlen=%u, genpkt=%u\n", + __func__, param.txlen, param.fixed_payload)); + } + + get_param_and_shift_buf(FALSE, param.payload_len, &data, payload); + + ret = mt_serv_set_tx_content(serv_test); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: addr1=%02x:%02x:%02x:%02x:%02x:%02x\n", + __func__, param.addr1[0], param.addr1[1], param.addr1[2], + param.addr1[3], param.addr1[4], param.addr1[5])); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: addr2=%02x:%02x:%02x:%02x:%02x:%02x\n", + __func__, param.addr2[0], param.addr2[1], param.addr2[2], + param.addr2[3], param.addr2[4], param.addr2[5])); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: addr3=%02x:%02x:%02x:%02x:%02x:%02x\n", + __func__, param.addr3[0], param.addr3[1], param.addr3[2], + param.addr3[3], param.addr3[4], param.addr3[5])); + + /* Update hqa_frame with response: status (2 bytes) */ + sys_ad_move_mem(hqa_frame->data + 2, (u_char *) ¶m.ext_id, + sizeof(param.ext_id)); + update_hqa_frame(hqa_frame, 2 + sizeof(param.ext_id), ret); + + return ret; +} + +static s_int32 hqa_start_tx_ext( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct hqa_tx param; + u_char *data = hqa_frame->data; + u_char ant_idx = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + sys_ad_zero_mem(¶m, sizeof(param)); + + get_param_and_shift_buf(TRUE, sizeof(param.ext_id), + &data, (u_char *)¶m.ext_id); + get_param_and_shift_buf(TRUE, sizeof(param.num_param), + &data, (u_char *)¶m.num_param); + get_param_and_shift_buf(TRUE, sizeof(param.band_idx), + &data, (u_char *)¶m.band_idx); + get_param_and_shift_buf(TRUE, sizeof(param.pkt_cnt), + &data, (u_char *)¶m.pkt_cnt); + get_param_and_shift_buf(TRUE, sizeof(param.tx_mode), + &data, (u_char *)¶m.tx_mode); + get_param_and_shift_buf(TRUE, sizeof(param.rate), + &data, (u_char *)¶m.rate); + get_param_and_shift_buf(TRUE, sizeof(param.pwr), + &data, (u_char *)¶m.pwr); + get_param_and_shift_buf(TRUE, sizeof(param.stbc), + &data, (u_char *)¶m.stbc); + get_param_and_shift_buf(TRUE, sizeof(param.ldpc), + &data, (u_char *)¶m.ldpc); + get_param_and_shift_buf(TRUE, sizeof(param.ibf), + &data, (u_char *)¶m.ibf); + get_param_and_shift_buf(TRUE, sizeof(param.ebf), + &data, (u_char *)¶m.ebf); + get_param_and_shift_buf(TRUE, sizeof(param.wlan_id), + &data, (u_char *)¶m.wlan_id); + get_param_and_shift_buf(TRUE, sizeof(param.aifs), + &data, (u_char *)¶m.aifs); + get_param_and_shift_buf(TRUE, sizeof(param.gi), + &data, (u_char *)¶m.gi); + get_param_and_shift_buf(TRUE, sizeof(param.tx_path), + &data, (u_char *)¶m.tx_path); + get_param_and_shift_buf(TRUE, sizeof(param.nss), + &data, (u_char *)¶m.nss); + get_param_and_shift_buf(TRUE, sizeof(param.hw_tx_enable), + &data, (u_char *)¶m.hw_tx_enable); + + if (!param.pkt_cnt) + param.pkt_cnt = 0x8fffffff; + + /* Set parameters */ + SERV_SET_PARAM(serv_test, ctrl_band_idx, (u_char)param.band_idx); + CONFIG_SET_PARAM(serv_test, tx_stat.tx_cnt, + (u_int32)param.pkt_cnt, param.band_idx); + CONFIG_SET_PARAM(serv_test, tx_mode, + (u_char)param.tx_mode, param.band_idx); + CONFIG_SET_PARAM(serv_test, mcs, + (u_char)param.rate, param.band_idx); + CONFIG_SET_PARAM(serv_test, stbc, + (u_char)param.stbc, param.band_idx); + CONFIG_SET_PARAM(serv_test, ldpc, + (u_char)param.ldpc, param.band_idx); +#if 0 /* remove tx_path setting while start Tx, + * it should be done prior to switch channel + */ + CONFIG_SET_PARAM(serv_test, tx_ant, + (u_char)param.tx_path, param.band_idx); +#endif + CONFIG_SET_PARAM(serv_test, nss, + (u_char)param.nss, param.band_idx); + CONFIG_SET_PARAM(serv_test, sgi, + (u_char)param.gi, param.band_idx); + CONFIG_SET_PARAM(serv_test, wcid_ref, + (u_int8)param.wlan_id, param.band_idx); + CONFIG_SET_PARAM(serv_test, ipg_param.ipg, + (u_int32)param.aifs, param.band_idx); + for (ant_idx = 0; ant_idx < TEST_ANT_NUM; ant_idx++) + CONFIG_SET_PARAM(serv_test, tx_pwr[ant_idx], + (u_int32)param.pwr, param.band_idx); + WINFO_SET_PARAM(serv_test, hw_tx_enable, param.hw_tx_enable); + if (mt_serv_submit_tx(serv_test) != SERV_STATUS_SUCCESS) + goto err_out; + + ret = mt_serv_start_tx(serv_test); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: band_idx=%u, pkt_cnt=0x%4x, phy=%u\n", + __func__, param.band_idx, param.pkt_cnt, param.tx_mode)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: pwr=%u, mcs=%u, stbc=%u, ldpc=%u\n", + __func__, param.pwr, param.rate, param.stbc, param.ldpc)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: ibf=%u, ebf=%u, wlan_id=%u, aifs=%u\n", + __func__, param.ibf, param.ebf, param.wlan_id, param.aifs)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: gi=%u, nss=%u hwtx=%u\n", + __func__, param.gi, param.nss, param.hw_tx_enable)); + + /* Update hqa_frame with response: status (2 bytes) */ + sys_ad_move_mem(hqa_frame->data + 2, ¶m.ext_id, + sizeof(param.ext_id)); + update_hqa_frame(hqa_frame, 2 + sizeof(param.ext_id), ret); + +err_out: + return ret; +} + +static s_int32 hqa_start_rx_ext( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_char own_mac[SERV_MAC_ADDR_LEN]; + u_int32 ext_id = 0, param_num = 0, band_idx = 0, rx_path = 0; + u_int32 user_idx = 0, tx_mode = 0, ltf_gi = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + sys_ad_zero_mem(own_mac, SERV_MAC_ADDR_LEN); + get_param_and_shift_buf(TRUE, sizeof(u_int32), + &data, (u_char *)&ext_id); + get_param_and_shift_buf(TRUE, sizeof(u_int32), + &data, (u_char *)¶m_num); + get_param_and_shift_buf(TRUE, sizeof(u_int32), + &data, (u_char *)&band_idx); + get_param_and_shift_buf(FALSE, SERV_MAC_ADDR_LEN, + &data, (u_char *)&own_mac); + get_param_and_shift_buf(TRUE, sizeof(u_int32), + &data, (u_char *)&rx_path); + get_param_and_shift_buf(TRUE, sizeof(u_int32), &data, + (u_char *)CONFIG_GET_PADDR(serv_test, + mu_rx_aid, + band_idx)); + if (param_num > 3) { + get_param_and_shift_buf(TRUE, sizeof(u_int32), + &data, (u_char *)&tx_mode); + get_param_and_shift_buf(TRUE, sizeof(u_int32), + &data, (u_char *)<f_gi); + get_param_and_shift_buf(TRUE, sizeof(u_int32), + &data, (u_char *)&user_idx); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: param num:%d\n", __func__, param_num)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: \ttx_mode:%d, ltf_gi:%d, user_idx:%d\n", + __func__, tx_mode, ltf_gi, user_idx)); + } + + /* Set parameters */ + SERV_SET_PARAM(serv_test, ctrl_band_idx, (u_char)band_idx); + CONFIG_SET_PADDR(serv_test, own_mac, own_mac, + SERV_MAC_ADDR_LEN, band_idx); +#if 0 /* remove rx_path setting while start Rx, + * it should be done prior to switch channel + */ + CONFIG_SET_PARAM(serv_test, rx_ant, (u_int16)rx_path, band_idx); +#endif + CONFIG_SET_PARAM(serv_test, tx_mode, tx_mode, band_idx); + CONFIG_SET_PARAM(serv_test, sgi, ltf_gi, band_idx); + CONFIG_SET_PARAM(serv_test, user_idx, (u_int8)user_idx, band_idx); + + ret = mt_serv_start_rx(serv_test); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: param num=%u, band_idx=%u\n", + __func__, param_num, band_idx)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: mac=%02x:%02x:%02x:%02x:%02x:%02x\n", + __func__, own_mac[0], own_mac[1], own_mac[2], + own_mac[3], own_mac[4], own_mac[5])); + + /* Update hqa_frame with response: status (2 bytes) */ + sys_ad_move_mem(hqa_frame->data + 2, (u_char *) &ext_id, + sizeof(ext_id)); + update_hqa_frame(hqa_frame, 2 + sizeof(ext_id), ret); + + return ret; +} + +static s_int32 hqa_stop_tx_ext( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_int32 ext_id = 0, param_num = 0, band_idx = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(ext_id), + &data, (u_char *)&ext_id); + get_param_and_shift_buf(TRUE, sizeof(param_num), + &data, (u_char *)¶m_num); + get_param_and_shift_buf(TRUE, sizeof(band_idx), + &data, (u_char *)&band_idx); + + /* Set parameters */ + SERV_SET_PARAM(serv_test, ctrl_band_idx, (u_char)band_idx); + + ret = mt_serv_stop_tx(serv_test); + if (ret != SERV_STATUS_SUCCESS) + goto err_out; + + ret = mt_serv_revert_tx(serv_test); + if (ret != SERV_STATUS_SUCCESS) + goto err_out; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: band_idx=%u\n", __func__, band_idx)); + + /* Update hqa_frame with response: status (2 bytes) */ + sys_ad_move_mem(hqa_frame->data + 2, (u_char *) &ext_id, + sizeof(ext_id)); + update_hqa_frame(hqa_frame, 2 + sizeof(ext_id), ret); + +err_out: + return ret; +} + +static s_int32 hqa_stop_rx_ext( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_int32 ext_id = 0, param_num = 0, band_idx = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(ext_id), + &data, (u_char *)&ext_id); + get_param_and_shift_buf(TRUE, sizeof(param_num), + &data, (u_char *)¶m_num); + get_param_and_shift_buf(TRUE, sizeof(band_idx), + &data, (u_char *)&band_idx); + + /* Set parameters */ + SERV_SET_PARAM(serv_test, ctrl_band_idx, (u_char)band_idx); + + ret = mt_serv_stop_rx(serv_test); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: band_idx=%u\n", __func__, band_idx)); + + /* Update hqa_frame with response: status (2 bytes) */ + sys_ad_move_mem(hqa_frame->data + 2, (u_char *) &ext_id, + sizeof(ext_id)); + update_hqa_frame(hqa_frame, 2 + sizeof(ext_id), ret); + + return ret; +} + +static s_int32 hqa_set_tx_time( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_int32 ext_id = 0, is_tx_time = 0, band_idx = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + get_param_and_shift_buf(TRUE, sizeof(ext_id), + &data, (u_char *)&ext_id); + get_param_and_shift_buf(TRUE, sizeof(band_idx), + &data, (u_char *)&band_idx); + get_param_and_shift_buf(TRUE, sizeof(is_tx_time), + &data, (u_char *)&is_tx_time); + + /* Set parameters */ + SERV_SET_PARAM(serv_test, ctrl_band_idx, (u_char)band_idx); + + /* 0: use tx length, 1: use tx time */ + if (is_tx_time == 1) + CONFIG_SET_PARAM(serv_test, tx_time_param.pkt_tx_time_en, + TRUE, band_idx); + else { + CONFIG_SET_PARAM(serv_test, tx_time_param.pkt_tx_time_en, + FALSE, band_idx); + /* Reset to 0 when start tx everytime */ + CONFIG_SET_PARAM(serv_test, tx_time_param.pkt_tx_time, + 0, band_idx); + } + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: band_idx=%u, is_tx_time=%u\n", + __func__, band_idx, is_tx_time)); + + /* Update hqa_frame with response: status (2 bytes) */ + sys_ad_move_mem(hqa_frame->data + 2, (u_char *) &ext_id, + sizeof(ext_id)); + update_hqa_frame(hqa_frame, 2 + sizeof(ext_id), ret); + + return ret; +} + +static s_int32 hqa_off_ch_scan( + struct service_test *serv_test, struct hqa_frame *hqa_frame) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char *data = hqa_frame->data; + u_int32 ext_id = 0, dbdc_idx = 0, mntr_ch = 0; + u_int32 is_aband = 0, mntr_bw = 0, mntr_tx_rx_pth = 0; + u_int32 scan_mode = 0; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, ("%s\n", __func__)); + + /* Get parameters from command frame */ + /* Data sequences of command frame: + * ext_id (4 bytes) + dbdc_idx (4 bytes) + mntr_ch (4 bytes) + + * is_aband (4 bytes) + mntr_bw (4 bytes) + + * mntr_tx_rx_pth (4 bytes) + scan_mode (4 bytes) + */ + get_param_and_shift_buf(TRUE, sizeof(ext_id), + &data, (u_char *)&ext_id); + get_param_and_shift_buf(TRUE, sizeof(dbdc_idx), + &data, (u_char *)&dbdc_idx); + get_param_and_shift_buf(TRUE, sizeof(mntr_ch), + &data, (u_char *)&mntr_ch); + get_param_and_shift_buf(TRUE, sizeof(is_aband), + &data, (u_char *)&is_aband); + get_param_and_shift_buf(TRUE, sizeof(mntr_bw), + &data, (u_char *)&mntr_bw); + get_param_and_shift_buf(TRUE, sizeof(mntr_tx_rx_pth), + &data, (u_char *)&mntr_tx_rx_pth); + get_param_and_shift_buf(TRUE, sizeof(scan_mode), + &data, (u_char *)&scan_mode); + + switch (mntr_bw) { + case HQA_BAND_WIDTH_20: + mntr_bw = TEST_BW_20; + break; + + case HQA_BAND_WIDTH_40: + mntr_bw = TEST_BW_40; + break; + + case HQA_BAND_WIDTH_80: + mntr_bw = TEST_BW_80; + break; + + case HQA_BAND_WIDTH_10: + mntr_bw = TEST_BW_10; + break; + + case HQA_BAND_WIDTH_5: + mntr_bw = TEST_BW_5; + break; + + case HQA_BAND_WIDTH_160: + mntr_bw = TEST_BW_160C; + break; + + case HQA_BAND_WIDTH_8080: + mntr_bw = TEST_BW_160NC; + break; + + default: + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: bw 0x%x is out of range\n", __func__, mntr_bw)); + mntr_bw = TEST_BW_20; + break; + } + + /* Set parameters */ + SERV_SET_PARAM(serv_test, ctrl_band_idx, (u_char)dbdc_idx); + CONFIG_SET_PARAM(serv_test, off_ch_param.ext_id, + (u_int32)ext_id, dbdc_idx); + CONFIG_SET_PARAM(serv_test, off_ch_param.dbdc_idx, + (u_int32)dbdc_idx, dbdc_idx); + CONFIG_SET_PARAM(serv_test, off_ch_param.mntr_ch, + (u_int32)mntr_ch, dbdc_idx); + CONFIG_SET_PARAM(serv_test, off_ch_param.is_aband, + (u_int32)is_aband, dbdc_idx); + CONFIG_SET_PARAM(serv_test, off_ch_param.mntr_bw, + (u_int32)mntr_bw, dbdc_idx); + CONFIG_SET_PARAM(serv_test, off_ch_param.mntr_tx_rx_pth, + (u_int32)mntr_tx_rx_pth, dbdc_idx); + CONFIG_SET_PARAM(serv_test, off_ch_param.scan_mode, + (u_int32)scan_mode, dbdc_idx); + + ret = mt_serv_set_off_ch_scan(serv_test); + + /* Update hqa_frame with response: status (2 bytes) */ + sys_ad_move_mem(hqa_frame->data + 2, (u_char *) &ext_id, + sizeof(ext_id)); + update_hqa_frame(hqa_frame, 2 + sizeof(ext_id), ret); + + return ret; +} + +static struct hqa_cmd_entry CMD_SET6[] = { + /* cmd id start from 0x1600 */ + {0x1, hqa_set_channel_ext}, + {0x2, hqa_set_txcontent_ext}, + {0x3, hqa_start_tx_ext}, + {0x4, hqa_start_rx_ext}, + {0x5, hqa_stop_tx_ext}, + {0x6, hqa_stop_rx_ext}, + {0x7, legacy_function}, + {0x8, legacy_function}, + {0x9, legacy_function}, + {0xa, legacy_function}, + {0xb, legacy_function}, + {0xc, legacy_function}, + {0x26, hqa_set_tx_time}, + {0x27, hqa_off_ch_scan} +}; + +static struct hqa_cmd_table CMD_TABLES[] = { + { + CMD_SET0, + SERV_ARRAY_SIZE(CMD_SET0), + 0x1000, + } + , + { + CMD_SET1, + SERV_ARRAY_SIZE(CMD_SET1), + 0x1100, + } + , + { + CMD_SET2, + SERV_ARRAY_SIZE(CMD_SET2), + 0x1200, + } + , + { + CMD_SET3, + SERV_ARRAY_SIZE(CMD_SET3), + 0x1300, + } + , + { + CMD_SET4, + SERV_ARRAY_SIZE(CMD_SET4), + 0x1400, + } + , + { + CMD_SET5, + SERV_ARRAY_SIZE(CMD_SET5), + 0x1500, + } + , + { + CMD_SET6, + SERV_ARRAY_SIZE(CMD_SET6), + 0x1600, + } + , +}; + +static struct priv_hqa_cmd_id_mapping priv_hqa_cmd_mapping[] = { + {"OpenAdapter", 0x1000, + {0} }, + {"CloseAdapter", 0x1001, + {0} }, + {"SetBandMode", 0x152c, + {4, 4} }, + {"SetTxPath", 0x100b, + {4, 4} }, + {"SetRxPath", 0x100c, + {4, 4} }, + {"GetTxInfo", 0x1313, + {0} }, + {"DBDCStartTX", 0x1600, + {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4} }, + {"DBDCStartRX", 0x1600, + {4, 4, 4, 6, 4, 4, 4, 4, 4} }, + {"DBDCStopTX", 0x1600, + {4, 4, 4} }, + {"DBDCStopRX", 0x1600, + {4, 4, 4} }, + {"DBDCSetChannel", 0x1600, + {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4} }, + {"DBDCSetTXContent", 0x1600, + {4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6} }, + {"GetRXStatisticsAllNew", 0x151c, + {4, 4} }, + {"GetChipCapability", 0x151d, + {0} }, + {"ResetTxRxCounter", 0x1200, + {0} }, + {"CalibrationTestMode", 0x1509, + {4, 4} }, + {"CapWiFiSpectrum", 0x1580, + {4, 4, 4, 4, 4, 4, 4, 4, 4, 6} }, +}; + +s_int32 mt_agent_hqa_cmd_string_parser( + s_int8 *hqa_frame_string, struct hqa_frame *hqa_frame) +{ + s_int8 i = 0, j = 0, pattern_found = 0; + s_int8 *this_para = NULL; + s_int32 i4argc = 0; + s_int8 *apc_argv[AGENT_CFG_ARGV_MAX] = { 0 }; + u_char tmpdata[100] = { 0 }; + s_int8 tmp_mac[SERV_MAC_ADDR_LEN] = { 0 }; + u_int16 tmp_length = 0; + u_int32 tmp_value = 0; + u_int16 tmp_value2 = 0; + u_char *data = NULL; + u_int16 ret = 0; + u_int8 parasize = 0; + + for (i = 0; i < sizeof(priv_hqa_cmd_mapping) / sizeof(struct + priv_hqa_cmd_id_mapping); i++) { + if (strncasecmp(hqa_frame_string, + priv_hqa_cmd_mapping[i].cmd_str, + strlen(priv_hqa_cmd_mapping[i].cmd_str)) == 0) { + + /*Command Found in table*/ + pattern_found = 1; + + /*Parsing the parameters if it has*/ + this_para = strstr(hqa_frame_string, "="); + if (this_para) { + /*Roll over "=", get Parameters y,y,y,y...*/ + this_para++; + agent_cfg_parse_argument(this_para, + &i4argc, apc_argv); + /*debug use*/ + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("argc is %i\n", i4argc)); + for (j = 0 ; j < i4argc; j++) { + SERV_LOG(SERV_DBG_CAT_TEST, + SERV_DBG_LVL_TRACE, + ("argv is %s\n", apc_argv[j++])); + } + } + + break; + } + } + + /*pack the hqa command*/ + if (pattern_found) { + if (i4argc) { + data = tmpdata; + for (j = 0; j < i4argc; j++) { + parasize = priv_hqa_cmd_mapping[i].para_size[j]; + tmp_length += parasize; + + if (parasize == SERV_MAC_ADDR_LEN) { + ret = sscanf(apc_argv[j], + "%x:%x:%x:%x:%x:%x", + (unsigned int *)&tmp_mac[0], + (unsigned int *)&tmp_mac[1], + (unsigned int *)&tmp_mac[2], + (unsigned int *)&tmp_mac[3], + (unsigned int *)&tmp_mac[4], + (unsigned int *)&tmp_mac[5]); + + if (ret) + set_param_and_shift_buf(FALSE, parasize, + (u_char *)&tmp_mac, &data); + } else if (parasize == 4) { + ret = kstrtou32(apc_argv[j], 0, + &tmp_value); + set_param_and_shift_buf(TRUE, parasize, + (u_char *)&tmp_value, &data); + } else if (parasize == 2) { + ret = kstrtou16(apc_argv[j], 0, + &tmp_value2); + set_param_and_shift_buf(TRUE, parasize, + (u_char *)&tmp_value2, &data); + } else { + ret = kstrtou8(apc_argv[j], 0, + (u_int8 *)&tmp_value); + set_param_and_shift_buf(TRUE, parasize, + (u_char *)&tmp_value, &data); + } + } + } + + hqa_frame->magic_no = SERV_OS_HTONL(TEST_CMD_MAGIC_NO); + hqa_frame->type = 0; + hqa_frame->id = SERV_OS_HTONS(priv_hqa_cmd_mapping[i].cmd_id); + hqa_frame->length = tmp_length; + hqa_frame->sequence = 0; + memcpy(hqa_frame->data, tmpdata, tmp_length); + + /*debug use*/ + data = (u_char *)hqa_frame; + for (j = 0; j < sizeof(struct hqa_frame)/sizeof(u_char); j++) { + if (!(j % 16)) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("\n")); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + (" 0x%02x ", *data++)); + } + + return SERV_STATUS_SUCCESS; + } else + return SERV_STATUS_AGENT_NOT_SUPPORTED; +} + +s_int32 mt_agent_hqa_cmd_handler( + struct service *serv, struct hqa_frame_ctrl *hqa_frame_ctrl) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct service_test *serv_test; + u_int16 cmd_id; + u_int32 table_idx = 0, ext_cmd_id = 0; + u_int32 magic_no = 0; + struct hqa_frame *hqa_frame = NULL; + + if (hqa_frame_ctrl->type == 1) { + ret = mt_agent_hqa_cmd_string_parser( + hqa_frame_ctrl->hqa_frame_comm.hqa_frame_string, + hqa_frame_ctrl->hqa_frame_comm.hqa_frame_eth); + /*can return for debug*/ + /*return ret;*/ + if (ret != SERV_STATUS_SUCCESS) + return ret; + } + + hqa_frame = hqa_frame_ctrl->hqa_frame_comm.hqa_frame_eth; + + magic_no = SERV_OS_NTOHL(hqa_frame->magic_no); + serv_test = (struct service_test *)serv->serv_handle; + + if (magic_no != TEST_CMD_MAGIC_NO) + return SERV_STATUS_AGENT_INVALID_PARAM; + + hqa_frame->length = SERV_OS_NTOHS(hqa_frame->length); + + cmd_id = SERV_OS_NTOHS(hqa_frame->id); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: command id=0x%02x\n", __func__, cmd_id)); + + while (table_idx < + (sizeof(CMD_TABLES) / sizeof(struct hqa_cmd_table))) { + if ((cmd_id & 0xff00) == CMD_TABLES[table_idx].cmd_offset) { + u_int32 cmd_loop = 0; + struct hqa_cmd_entry *cmd_set = NULL; + + cmd_set = CMD_TABLES[table_idx].cmd_set; + /* Fix me, should align with other command set */ + if (CMD_TABLES[table_idx].cmd_offset == 0x1600) { + sys_ad_move_mem(&ext_cmd_id, + hqa_frame->data, + sizeof(ext_cmd_id)); + cmd_id = SERV_OS_NTOHL(ext_cmd_id); + } + + cmd_id &= 0xff; + ret = SERV_STATUS_AGENT_NOT_SUPPORTED; + while (cmd_loop < CMD_TABLES[table_idx].cmd_set_size) { + if (cmd_id == cmd_set[cmd_loop].index) { + ret = cmd_set[cmd_loop].handler( + serv_test, hqa_frame); + + goto done; + } else + cmd_loop++; + } + } else + table_idx++; + } + +done: + if (cmd_id == TEST_CMD_REQ) { + hqa_frame->type = TEST_CMD_RSP; + /* hqa_frame->type = 0x8005; */ + } else + hqa_frame->type = TEST_CMDRSP; + + return ret; +} + +/***************************************************************************** + * iwpriv command handler + *****************************************************************************/ + +static struct hqa_frame hqa_cmd_frame; + +static struct agent_cli_act_handler cli_act_cmds[] = { + {"ATESTART", mt_serv_start}, + {"APSTOP", mt_serv_start}, + {"ATESTOP", mt_serv_stop}, + {"APSTART", mt_serv_stop}, + {"TXCOMMIT", mt_serv_submit_tx}, + {"TXREVERT", mt_serv_revert_tx}, + {"TXFRAME", mt_serv_start_tx}, + {"TXSTOP", mt_serv_stop_tx}, + {"RXFRAME", mt_serv_start_rx}, + {"RXSTOP", mt_serv_stop_rx}, + {"", NULL} /* the last entry */ +}; + +s_int32 mt_agent_cli_act(u_char *name, struct service *serv) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct service_test *serv_test = NULL; + struct agent_cli_act_handler *entry = cli_act_cmds; + + serv_test = (struct service_test *)serv->serv_handle; + + while (strlen(entry->name)) { + if (strcmp(name, entry->name) == 0) + ret = entry->handler(serv_test); + + entry++; + } + + return ret; +} + +static struct agent_cli_set_w_handler cli_set_w_cmds[] = { + {"", NULL} /* the last entry */ +}; + +s_int32 mt_agent_cli_set_w(u_char *name, struct service *serv, u_char *param) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_long str2value = 0; + struct agent_cli_set_w_handler *entry = cli_set_w_cmds; + struct hqa_frame *hqa_cmd = &hqa_cmd_frame; + u_int16 value = 0; + + sys_ad_zero_mem(hqa_cmd, sizeof(*hqa_cmd)); + + if (kstrtol(param, 10, &str2value) == 0) { + value = str2value; + value = SERV_OS_HTONS(value); + sys_ad_move_mem(hqa_cmd->data, &value, sizeof(u_int16)); + while (strlen(entry->name)) { + if (strcmp(name, entry->name) == 0) + ret = entry->handler( + (struct service_test *)serv->serv_handle, + hqa_cmd); + entry++; + } + } else + ret = SERV_STATUS_AGENT_INVALID_PARAM; + + return ret; +} + +static struct agent_cli_set_dw_handler cli_set_dw_cmds[] = { + {"ATETXMCS", hqa_set_rate}, + {"ATETXNSS", hqa_set_nss}, + {"ATENSS", hqa_set_nss}, + {"ATETXSTBC", hqa_set_stbc}, + {"ATETXMODE", hqa_set_preamble}, + {"ATETXGI", hqa_set_short_gi}, + {"", NULL} /* the last entry */ +}; + +s_int32 mt_agent_cli_set_dw(u_char *name, struct service *serv, u_char *param) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_long str2value = 0; + struct agent_cli_set_dw_handler *entry = cli_set_dw_cmds; + struct hqa_frame *hqa_cmd = &hqa_cmd_frame; + u_int32 value = 0; + + sys_ad_zero_mem(hqa_cmd, sizeof(*hqa_cmd)); + if (kstrtol(param, 10, &str2value) == 0) { + value = str2value; + value = SERV_OS_HTONL(value); + sys_ad_move_mem(hqa_cmd->data, &value, sizeof(u_int32)); + while (strlen(entry->name)) { + if (strcmp(name, entry->name) == 0) + ret = entry->handler( + (struct service_test *)serv->serv_handle, + hqa_cmd); + entry++; + } + } else + ret = SERV_STATUS_AGENT_INVALID_PARAM; + + return ret; +} + +s_int32 mt_agent_set_bw(struct service_test *serv_test, u_char *arg) +{ + u_int32 ret = 0; + u_int32 param[2] = {0}; + u_int8 i = 0; + u_char *value; + struct hqa_frame *hqa_cmd = &hqa_cmd_frame; + u_char *data = hqa_cmd->data; + + sys_ad_zero_mem(hqa_cmd, sizeof(*hqa_cmd)); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: Bw = %s\n", __func__, arg)); + + for (i = 0, value = agent_trtok(arg, ":"); + value; value = agent_trtok(NULL, ":")) { + if (i == 2) + break; + kstrtol(value, 10, (long *)¶m[i++]); + } + + set_param_and_shift_buf(TRUE, sizeof(u_int32), + (u_char *)¶m[0], &data); + hqa_set_system_bw(serv_test, hqa_cmd); + + data = hqa_cmd->data; + set_param_and_shift_buf(TRUE, sizeof(u_int32), + (u_char *)¶m[1], &data); + hqa_set_per_pkt_bw(serv_test, hqa_cmd); + + return ret; +} + +s_int32 mt_agent_set_ctrl_band( + struct service_test *serv_test, u_char *arg) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_long str2value = 0; + u_int32 value = 0; + + if (kstrtol(arg, 10, &str2value) == 0) { + value = str2value; + SERV_SET_PARAM(serv_test, ctrl_band_idx, value); + } else + ret = SERV_STATUS_AGENT_INVALID_PARAM; + + return ret; +} + +s_int32 mt_agent_set_pwr( + struct service_test *serv_test, u_char *arg) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_int32 value = 0; + u_long input = 0; + struct hqa_frame *hqa_cmd = &hqa_cmd_frame; + u_char *data = hqa_cmd->data; + + if (kstrtol(arg, 10, (long *)&input) == 0) { + /* power */ + value = input; + set_param_and_shift_buf(TRUE, sizeof(u_int32), + (u_char *)&value, &data); + /* band index */ + value = serv_test->ctrl_band_idx; + set_param_and_shift_buf(TRUE, sizeof(u_int32), + (u_char *)&value, &data); + /* channel */ + value = CONFIG_GET_PARAM(serv_test, channel, + SERV_GET_PARAM(serv_test, + ctrl_band_idx)); + set_param_and_shift_buf(TRUE, sizeof(u_int32), + (u_char *)&value, &data); + /* channel band */ + value = CONFIG_GET_PARAM(serv_test, ch_band, + SERV_GET_PARAM(serv_test, + ctrl_band_idx)); + set_param_and_shift_buf(TRUE, sizeof(u_int32), + (u_char *)&value, &data); + /* ant index */ + value = 0; + set_param_and_shift_buf(TRUE, sizeof(u_int32), + (u_char *)&value, &data); + hqa_set_tx_power_ext(serv_test, hqa_cmd); + } else + ret = SERV_STATUS_AGENT_INVALID_PARAM; + + return ret; +} + +s_int32 mt_agent_set_channel( + struct service_test *serv_test, u_char *arg) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_int32 value = 0; + u_int32 input[4] = {0}; + u_int8 i = 0; + struct hqa_frame *hqa_cmd = &hqa_cmd_frame; + u_char *data = hqa_cmd->data, *tok = NULL; + + sys_ad_zero_mem(hqa_cmd, sizeof(*hqa_cmd)); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: control_band_idx:%x, Channel = %s\n", + __func__, serv_test->ctrl_band_idx, arg)); + + for (i = 0, tok = agent_trtok(arg, ":"); + tok; + tok = agent_trtok(NULL, ":")) { + if (i == 4) + break; + + kstrtol(tok, 10, (long *)&input[i++]); + } + + /* For backward compatibility */ + if (input[0] >= 36 && input[0] <= 181) { + if (input[1] == 0) { + input[1] = 1; /* channel_band 5G as 1*/ + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("\x1b[41m%s(): 5G Channel:%d, then force Channel_Band:%d !!\x1b[m\n", + __func__, input[0], input[1])); + } + } + + /* ext id */ + set_param_and_shift_buf(TRUE, sizeof(u_int32), + (u_char *)&value, &data); + /* parameters count */ + value = 8; + set_param_and_shift_buf(TRUE, sizeof(u_int32), + (u_char *)&value, &data); + /* band index */ + value = serv_test->ctrl_band_idx; + set_param_and_shift_buf(TRUE, sizeof(u_int32), + (u_char *)&value, &data); + /* central channel index */ + value = input[0]; + set_param_and_shift_buf(TRUE, sizeof(u_int32), + (u_char *)&value, &data); + /* 2nd central channel index */ + value = input[3]; + set_param_and_shift_buf(TRUE, sizeof(u_int32), + (u_char *)&value, &data); + /* system bandwidth */ + value = CONFIG_GET_PARAM(serv_test, bw, + serv_test->ctrl_band_idx); + set_param_and_shift_buf(TRUE, sizeof(u_int32), + (u_char *)&value, &data); + /* data band width */ + value = CONFIG_GET_PARAM(serv_test, per_pkt_bw, + serv_test->ctrl_band_idx); + set_param_and_shift_buf(TRUE, sizeof(u_int32), + (u_char *)&value, &data); + /* primary offset */ + value = input[2]; + set_param_and_shift_buf(TRUE, sizeof(u_int32), + (u_char *)&value, &data); + /* reason */ + value = 0; + set_param_and_shift_buf(TRUE, sizeof(u_int32), + (u_char *)&value, &data); + /* channel band */ + value = input[1]; + set_param_and_shift_buf(TRUE, sizeof(u_int32), + (u_char *)&value, &data); + value = 0; + /* out band frequency */ + set_param_and_shift_buf(TRUE, sizeof(u_int32), + (u_char *)&value, &data); + + hqa_set_channel_ext(serv_test, hqa_cmd); + + return ret; +} + +s_int32 mt_agent_set_ru_cli(struct service_test *serv_test, u_char *arg) +{ + s_int32 ret = SERV_STATUS_AGENT_INVALID_PARAM; + s_int32 input_cnt = 0; + u_char *value = NULL, i = 0, band_idx; + struct test_ru_info *ru_info = NULL; + + band_idx = SERV_GET_PARAM(serv_test, ctrl_band_idx); + + ru_info = (struct test_ru_info *)CONFIG_GET_PADDR(serv_test, + ru_info_list[0], + band_idx); + + if (strlen(arg) > 0) { + sys_ad_zero_mem(ru_info, + sizeof(struct test_ru_info)*MAX_MULTI_TX_STA); + + for (i = 0, value = agent_trtok(arg, ":"); + value; + value = agent_trtok((char *)NULL, ":"), i++) { + input_cnt = sscanf(value, + "%4x-%d-%d-%d-%d-%d-%d-%d-%d", + &ru_info[i].allocation, + &ru_info[i].aid, + &ru_info[i].ru_index, + &ru_info[i].rate, + &ru_info[i].ldpc, + &ru_info[i].nss, + &ru_info[i].start_sp_st, + &ru_info[i].mpdu_length, + &ru_info[i].alpha); + + if (input_cnt < 0) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("Invalid format, %s ignored!\n", arg)); + goto err_out; + } else if (strlen(value) > 0 && input_cnt == 9) { + ru_info[i].valid = TRUE; + + if (ru_info[i].mpdu_length == 0) + ru_info[i].mpdu_length = + CONFIG_GET_PARAM(serv_test, + tx_len, + band_idx); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: segment[%d]: alloc:%04x\n", + __func__, (ru_info[i].ru_index & 0x1), + ru_info[i].allocation)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s:\t\t\tru_idx:%d, length:%d,\n", + __func__, (ru_info[i].ru_index >> 1), + ru_info[i].mpdu_length)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s:\t\t\talpha:%d, rate:0x%x,\n", + __func__, ru_info[i].alpha, + ru_info[i].rate)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: \t\t\tldpc:%d, nss:%d\n", + __func__, ru_info[i].ldpc, + ru_info[i].nss)); + } else { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("Invalid format, %s ignored!\n", arg)); + goto err_out; + } + } + + ret = SERV_STATUS_SUCCESS; + } + +err_out: + return ret; +} + +s_int32 mt_agent_set_txant(struct service_test *serv_test, u_char *arg) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_int32 value = 0; + struct hqa_frame *hqa_cmd = &hqa_cmd_frame; + u_char *data = hqa_cmd->data; + u_long str2value = 0; + + sys_ad_zero_mem(hqa_cmd, sizeof(*hqa_cmd)); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: TX PATH = %s\n", __func__, arg)); + + hqa_cmd->length = 2*sizeof(u_int32); + + if (kstrtol(arg, 10, &str2value) == 0) { + value = str2value; + set_param_and_shift_buf(TRUE, sizeof(u_int32), + (u_char *)&value, &data); + value = SERV_GET_PARAM(serv_test, ctrl_band_idx); + set_param_and_shift_buf(TRUE, sizeof(u_int32), + (u_char *)&value, &data); + hqa_set_tx_path(serv_test, hqa_cmd); + } else + ret = SERV_STATUS_AGENT_INVALID_PARAM; + + return ret; +} + +s_int32 mt_agent_set_rxant(struct service_test *serv_test, u_char *arg) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_int32 value = 0; + u_long str2value = 0; + struct hqa_frame *hqa_cmd = &hqa_cmd_frame; + u_char *data = hqa_cmd->data; + + sys_ad_zero_mem(hqa_cmd, sizeof(*hqa_cmd)); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: RX PATH = %s\n", __func__, arg)); + + hqa_cmd->length = 2*sizeof(u_int32); + + if (kstrtol(arg, 10, (long *)&str2value) == 0) { + value = str2value; + set_param_and_shift_buf(TRUE, sizeof(u_int32), + (u_char *)&value, &data); + value = SERV_GET_PARAM(serv_test, ctrl_band_idx); + set_param_and_shift_buf(TRUE, sizeof(u_int32), + (u_char *)&value, &data); + hqa_set_rx_path(serv_test, hqa_cmd); + } else + ret = SERV_STATUS_AGENT_INVALID_PARAM; + + return ret; +} + +static struct agent_cli_set_ext_handler cli_set_ext_cmds[] = { + {"ATECTRLBANDIDX", mt_agent_set_ctrl_band}, + {"ATETXPOW0", mt_agent_set_pwr}, + {"ATECHANNEL", mt_agent_set_channel}, + {"ATETXBW", mt_agent_set_bw}, + {"ATERUINFO", mt_agent_set_ru_cli}, + {"ATETXANT", mt_agent_set_txant}, + {"ATERXANT", mt_agent_set_rxant}, + {"", NULL} /* the last entry */ +}; + +s_int32 mt_agent_cli_set_ext(u_char *name, struct service *serv, u_char *arg) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct agent_cli_set_ext_handler *entry = cli_set_ext_cmds; + + while (strlen(entry->name)) { + if (strcmp(name, entry->name) == 0) + ret = entry->handler( + (struct service_test *)serv->serv_handle, + arg); + + entry++; + } + + return ret; +} + +/***************************************************************************** + * Service init/exit handler + *****************************************************************************/ +s_int32 mt_agent_init_service(struct service *serv) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + switch (serv->serv_id) { + case SERV_HANDLE_TEST: + ret = mt_serv_init_test( + (struct service_test *)serv->serv_handle); + break; + + default: + return SERV_STATUS_AGENT_FAIL; + } + + return ret; +} + +s_int32 mt_agent_exit_service(struct service *serv) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + switch (serv->serv_id) { + case SERV_HANDLE_TEST: + ret = mt_serv_exit_test( + (struct service_test *)serv->serv_handle); + break; + + default: + return SERV_STATUS_AGENT_FAIL; + } + + return ret; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/hal/gen4m/operation_gen4m.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/hal/gen4m/operation_gen4m.c new file mode 100644 index 0000000000000..b48cdf342b94f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/hal/gen4m/operation_gen4m.c @@ -0,0 +1,2931 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#include "operation.h" + +#define CFG_WAIT_TSSI_READY 0 +extern s_int32 mt_engine_calc_phy( + struct test_ru_info *ru_info, + u_int32 apep_length, + u_int8 stbc, + u_int8 ltf_gi, + u_int8 max_tpe); + +union hetb_rx_cmm { + struct { + unsigned long long tigger_type:4; + unsigned long long ul_length:12; + unsigned long long cascade_ind:1; + unsigned long long cs_required:1; + unsigned long long ul_bw:2; + unsigned long long gi_ltf:2; + unsigned long long mimo_ltf:1; + unsigned long long ltf_sym_midiam:3; + unsigned long long stbc:1; + unsigned long long ldpc_extra_sym:1; + unsigned long long ap_tx_pwr:6; + unsigned long long t_pe:3; + unsigned long long spt_reuse:16; + unsigned long long doppler:1; + unsigned long long sig_a_reserved:9; + unsigned long long reserved:1; + } field; + unsigned long long cmm_info; +}; + +union hetb_tx_usr { + struct { + u_int32 aid:12; + u_int32 allocation:8; + u_int32 coding:1; + u_int32 mcs:4; + u_int32 dcm:1; + u_int32 ss_allocation:6; + } field; + u_int32 usr_info; +}; + +struct icap_dump_iq { + u_int32 wf_num; + u_int32 iq_type; + u_int32 icap_cnt; /*IQ Data Simple Count*/ + u_int32 icap_data_len; + u_int8 *picap_data; +}; + +/***************************************************************************** + * Enum value definition + *****************************************************************************/ +/* gen4m Function ID List */ +enum ENUM_RF_AT_FUNCID { + 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, + RF_AT_FUNCID_PWR_DETECTOR, + RF_AT_FUNCID_WBRSSI_IBSSI, + + /* 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, + RF_AT_FUNCID_SET_TA, + RF_AT_FUNCID_SET_RX_MATCH_RULE, + + /* 80211AC & Jmode */ + RF_AT_FUNCID_SET_CBW = 71, + RF_AT_FUNCID_SET_DBW, + RF_AT_FUNCID_SET_PRIMARY_CH, + RF_AT_FUNCID_SET_ENCODE_MODE, + RF_AT_FUNCID_SET_J_MODE, + + /* ICAP command */ + RF_AT_FUNCID_SET_ICAP_CONTENT = 80, + RF_AT_FUNCID_SET_ICAP_MODE, + RF_AT_FUNCID_SET_ICAP_STARTCAP, + RF_AT_FUNCID_SET_ICAP_SIZE = 83, + RF_AT_FUNCID_SET_ICAP_TRIGGER_OFFSET, + RF_AT_FUNCID_QUERY_ICAP_DUMP_FILE = 85, + + /* 2G 5G Band */ + RF_AT_FUNCID_SET_BAND = 90, + + /* Reset Counter */ + RF_AT_FUNCID_RESETTXRXCOUNTER = 91, + + /* FAGC RSSI Path */ + RF_AT_FUNCID_FAGC_RSSI_PATH = 92, + + /* Set RX Filter Packet Length */ + RF_AT_FUNCID_RX_FILTER_PKT_LEN = 93, + + /* Tone */ + RF_AT_FUNCID_SET_TONE_RF_GAIN = 96, + RF_AT_FUNCID_SET_TONE_DIGITAL_GAIN = 97, + RF_AT_FUNCID_SET_TONE_TYPE = 98, + RF_AT_FUNCID_SET_TONE_DC_OFFSET = 99, + RF_AT_FUNCID_SET_TONE_BW = 100, + + /* MT6632 Add */ + RF_AT_FUNCID_SET_MAC_HEADER = 101, + RF_AT_FUNCID_SET_SEQ_CTRL = 102, + RF_AT_FUNCID_SET_PAYLOAD = 103, + RF_AT_FUNCID_SET_DBDC_BAND_IDX = 104, + RF_AT_FUNCID_SET_BYPASS_CAL_STEP = 105, + + /* Set RX Path */ + RF_AT_FUNCID_SET_RX_PATH = 106, + + /* Set Frequency Offset */ + RF_AT_FUNCID_SET_FRWQ_OFFSET = 107, + + /* Get Frequency Offset */ + RF_AT_FUNCID_GET_FREQ_OFFSET = 108, + + /* Set RXV Debug Index */ + RF_AT_FUNCID_SET_RXV_INDEX = 109, + + /* Set Test Mode DBDC Enable */ + RF_AT_FUNCID_SET_DBDC_ENABLE = 110, + + /* Get Test Mode DBDC Enable */ + RF_AT_FUNCID_GET_DBDC_ENABLE = 111, + + /* Set ICAP Ring Capture */ + RF_AT_FUNCID_SET_ICAP_RING = 112, + + /* Set TX Path */ + RF_AT_FUNCID_SET_TX_PATH = 113, + + /* Set Nss */ + RF_AT_FUNCID_SET_NSS = 114, + + /* Set TX Antenna Mask */ + RF_AT_FUNCID_SET_ANTMASK = 115, + + /* TMR set command */ + RF_AT_FUNCID_SET_TMR_ROLE = 116, + RF_AT_FUNCID_SET_TMR_MODULE = 117, + RF_AT_FUNCID_SET_TMR_DBM = 118, + RF_AT_FUNCID_SET_TMR_ITER = 119, + + /* Set ADC For IRR Feature */ + RF_AT_FUNCID_SET_ADC = 120, + + /* Set RX Gain For IRR Feature */ + RF_AT_FUNCID_SET_RX_GAIN = 121, + + /* Set TTG For IRR Feature */ + RF_AT_FUNCID_SET_TTG = 122, + + /* Set TTG ON/OFF For IRR Feature */ + RF_AT_FUNCID_TTG_ON_OFF = 123, + + /* Set TSSI for QA Tool Setting */ + RF_AT_FUNCID_SET_TSSI = 124, + + /* Set Recal Cal Step */ + RF_AT_FUNCID_SET_RECAL_CAL_STEP = 125, + + /* Set iBF/eBF enable */ + RF_AT_FUNCID_SET_IBF_ENABLE = 126, + RF_AT_FUNCID_SET_EBF_ENABLE = 127, + + /* Set MPS Setting */ + RF_AT_FUNCID_SET_MPS_SIZE = 128, + RF_AT_FUNCID_SET_MPS_SEQ_DATA = 129, + RF_AT_FUNCID_SET_MPS_PAYLOAD_LEN = 130, + RF_AT_FUNCID_SET_MPS_PKT_CNT = 131, + RF_AT_FUNCID_SET_MPS_PWR_GAIN = 132, + RF_AT_FUNCID_SET_MPS_NSS = 133, + RF_AT_FUNCID_SET_MPS_PACKAGE_BW = 134, + + RF_AT_FUNCID_GET_CH_TX_PWR_OFFSET = 136, + /* Antenna swap feature*/ + RF_AT_FUNCID_SET_ANT_SWP = 153, + RF_AT_FUNCID_SET_RX_MU_AID = 157, + RF_AT_FUNCID_SET_TX_HE_TB_TTRCR0 = 158, + RF_AT_FUNCID_SET_TX_HE_TB_TTRCR1 = 159, + RF_AT_FUNCID_SET_TX_HE_TB_TTRCR2 = 160, + RF_AT_FUNCID_SET_TX_HE_TB_TTRCR3 = 161, + RF_AT_FUNCID_SET_TX_HE_TB_TTRCR4 = 162, + RF_AT_FUNCID_SET_TX_HE_TB_TTRCR5 = 163, + RF_AT_FUNCID_SET_TX_HE_TB_TTRCR6 = 164, + RF_AT_FUNCID_SET_SECURITY_MODE = 165, + RF_AT_FUNCID_SET_LP_MODE = 166, + + /* Set HW TX enable */ + RF_AT_FUNCID_SET_HWTX_MODE = 167 +}; + +/* Command */ +enum ENUM_RF_AT_COMMAND { + RF_AT_COMMAND_STOPTEST = 0, + RF_AT_COMMAND_STARTTX, + RF_AT_COMMAND_STARTRX, + RF_AT_COMMAND_RESET, + RF_AT_COMMAND_OUTPUT_POWER, /* Payload */ + /* Local freq is renamed to Local leakage */ + RF_AT_COMMAND_LO_LEAKAGE, + /* OFDM (LTF/STF), CCK (PI,PI/2) */ + RF_AT_COMMAND_CARRIER_SUPPR, + RF_AT_COMMAND_TRX_IQ_CAL, + RF_AT_COMMAND_TSSI_CAL, + RF_AT_COMMAND_DPD_CAL, + RF_AT_COMMAND_CW, + RF_AT_COMMAND_ICAP, + RF_AT_COMMAND_RDD, + RF_AT_COMMAND_CH_SWITCH_FOR_ICAP, + RF_AT_COMMAND_RESET_DUMP_NAME, + RF_AT_COMMAND_SINGLE_TONE, + RF_AT_COMMAND_RDD_OFF, + RF_AT_COMMAND_NUM +}; + +/* Preamble */ +enum ENUM_RF_AT_PREAMBLE { + RF_AT_PREAMBLE_NORMAL = 0, + RF_AT_PREAMBLE_CCK_SHORT, + RF_AT_PREAMBLE_11N_MM, + RF_AT_PREAMBLE_11N_GF, + RF_AT_PREAMBLE_11AC, + RF_AT_PREAMBLE_NUM +}; + +/* Ack Policy */ +enum ENUM_RF_AT_ACK_POLICY { + 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 ENUM_RF_AUTOTEST_STATE { + 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 { + ATE_LOG_RXV = 1, + ATE_LOG_RDD, + ATE_LOG_RE_CAL, + ATE_LOG_TYPE_NUM, + ATE_LOG_RXINFO, + ATE_LOG_TXDUMP, + ATE_LOG_TEST +}; + +enum { + ATE_LOG_OFF, + ATE_LOG_ON, + ATE_LOG_DUMP, + ATE_LOG_CTRL_NUM, +}; + +enum ENUM_ATE_CAP_TYPE { + /* I/Q Type */ + ATE_CAP_I_TYPE = 0, + ATE_CAP_Q_TYPE = 1, + ATE_NUM_OF_CAP_TYPE +}; +/***************************************************************************** + * Global Variable + *****************************************************************************/ +static struct hqa_m_rx_stat test_hqa_rx_stat; +static struct test_rx_stat_band_info backup_band0_info; +static struct test_rx_stat_band_info backup_band1_info; +static u_char g_tx_mode; + + + +static u_int32 tm_ch_num_to_freq(u_int32 ch_num) +{ + u_int32 ch_in_mhz; + + if (ch_num >= 1 && ch_num <= 13) + ch_in_mhz = 2412 + (ch_num - 1) * 5; + else if (ch_num == 14) + ch_in_mhz = 2484; + else if (ch_num == 133) + ch_in_mhz = 3665; /* 802.11y */ + else if (ch_num == 137) + ch_in_mhz = 3685; /* 802.11y */ + else if ((ch_num >= 34 && ch_num <= 181) + || (ch_num == 16)) + ch_in_mhz = 5000 + ch_num * 5; + else if (ch_num >= 182 && ch_num <= 196) + ch_in_mhz = 4000 + ch_num * 5; + else if (ch_num == 201) + ch_in_mhz = 2730; + else if (ch_num == 202) + ch_in_mhz = 2498; + else + ch_in_mhz = 0; + + return 1000 * ch_in_mhz; +} + +static u_int32 tm_bw_hqa_mapping_at(u_int32 bw) +{ + u_int32 bw_mapping = 0; + + /* BW Mapping in QA Tool + * 0: BW20 + * 1: BW40 + * 2: BW80 + * 3: BW10 + * 4: BW5 + * 5: BW160C + * 6: BW160NC + */ + /* BW Mapping in FW + * 0: BW20 + * 1: BW40 + * 2: BW80 + * 3: BW160C + * 4: BW160NC + * 5: BW5 + * 6: BW10 + */ + if (bw == 0) + bw_mapping = 0; + else if (bw == 1) + bw_mapping = 1; + else if (bw == 2) + bw_mapping = 2; + else if (bw == 3) + bw_mapping = 6; + else if (bw == 4) + bw_mapping = 5; + else if (bw == 5) + bw_mapping = 3; + else if (bw == 6) + bw_mapping = 4; + + return bw_mapping; +} + +static s_int32 tm_rftest_set_auto_test( + struct test_wlan_info *winfos, + u_int32 func_idx, + u_int32 func_data) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct param_mtk_wifi_test_struct rf_at_info; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + rf_at_info.func_idx = func_idx; + rf_at_info.func_data = func_data; + + ret = pr_oid_funcptr(winfos, /*call back to ServiceWlanOid*/ + OP_WLAN_OID_RFTEST_SET_AUTO_TEST, + &rf_at_info, + sizeof(rf_at_info), + NULL, + NULL); + + return ret; + +} + +static s_int32 tm_rftest_query_auto_test( + struct test_wlan_info *winfos, + struct param_mtk_wifi_test_struct *prf_at_info, + u_int32 *buf_len) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + ret = pr_oid_funcptr(winfos, /*call back to ServiceWlanOid*/ + OP_WLAN_OID_RFTEST_QUERY_AUTO_TEST, + prf_at_info, + sizeof(*prf_at_info), + NULL, + NULL); + + return ret; + +} + +static s_int32 tm_icap_mode( + struct test_wlan_info *winfos) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + ret = pr_oid_funcptr(winfos, /*call back to ServiceWlanOid*/ + OP_WLAN_OID_SET_TEST_ICAP_MODE, + NULL, + 0, + NULL, + NULL); + + SERV_LOG(SERV_DBG_CAT_MISC, SERV_DBG_LVL_WARN, + ("Switch ICAP Mode,ret=0x%08x\n", ret)); + + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_set_tr_mac( + struct test_wlan_info *winfos, + s_int32 op_type, boolean enable, u_char band_idx) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_set_tx_stream( + struct test_wlan_info *winfos, + u_int32 stream_nums, u_char band_idx) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_set_tx_path( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + ret = tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_DBDC_BAND_IDX, band_idx); + + ret = tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_TX_PATH, + (u_int32)configs->tx_ant); + + return ret; +} + +s_int32 mt_op_set_rx_path( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + u_int32 rx_ant = (u_int32)configs->rx_ant; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + ret = tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_DBDC_BAND_IDX, band_idx); + + rx_ant = ((rx_ant << 16) | (0 & BITS(0, 15))); + ret = tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_RX_PATH, + rx_ant); + + return ret; +} + +s_int32 mt_op_set_rx_filter( + struct test_wlan_info *winfos, struct rx_filter_ctrl rx_filter) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_set_clean_persta_txq( + struct test_wlan_info *winfos, + boolean sta_pause_enable, u_char omac_idx, u_char band_idx) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_set_cfg_on_off( + struct test_wlan_info *winfos, + u_int8 type, u_int8 enable, u_char band_idx) +{ + u_int32 func_index, func_data; + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + switch (type) { + case 0: /* TSSI */ + func_index = RF_AT_FUNCID_SET_TSSI; + break; + case 1: /* DPD */ + func_index = RF_AT_FUNCID_DPD_MODE; + break; + default: + ret = SERV_STATUS_HAL_OP_FAIL; + return ret; + } + + func_data = 0; + + if (enable == 0) + func_data &= ~BIT(0); + else + func_data |= BIT(0); + + if (band_idx == 0) + func_data &= ~BIT(1); + else + func_data |= BIT(1); + + ret = tm_rftest_set_auto_test( + winfos, func_index, func_data); + + return ret; +} + +s_int32 mt_op_log_on_off( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 log_type, + u_int32 log_ctrl, + u_int32 log_size) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct param_mtk_wifi_test_struct rf_at_info; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + u_int32 buf_len = 0; + u_int32 rxv; + s_int32 i, target_len = 0, max_dump_rxv_cnt = 500; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + if ((log_ctrl == ATE_LOG_DUMP) && (log_type == ATE_LOG_RXV)) { + rf_at_info.func_idx = RF_AT_FUNCID_RESULT_INFO; + rf_at_info.func_data = RF_AT_FUNCID_RXV_DUMP; + ret = tm_rftest_query_auto_test(winfos, + &rf_at_info, &buf_len); + if (ret == SERV_STATUS_SUCCESS) { + target_len = rf_at_info.func_data * 36; + if (target_len >= (max_dump_rxv_cnt * 36)) + target_len = (max_dump_rxv_cnt * 36); + } + + for (i = 0; i < target_len; i += 4) { + rf_at_info.func_idx = RF_AT_FUNCID_RXV_DUMP; + rf_at_info.func_data = i; + ret = tm_rftest_query_auto_test(winfos, + &rf_at_info, &buf_len); + + if (ret == SERV_STATUS_SUCCESS) { + rxv = rf_at_info.func_data; + if (i % 36 == 0) { + /* Todo */ + /* TOOL_PRINTLOG... */ + } + + if (((i % 36) / 4) + 1 == 9) { + /* Todo */ + /* TOOL_PRINTLOG... */ + } + } + + } + + /* TOOL_PRINTLOG(RFTEST, ERROR, "[LOG DUMP END]\n"); */ + } + + return ret; +} + +s_int32 mt_op_set_antenna_port( + struct test_wlan_info *winfos, + u_int8 rf_mode_mask, u_int8 rf_port_mask, u_int8 ant_port_mask) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_set_slot_time( + struct test_wlan_info *winfos, + u_int8 slot_time, u_int8 sifs_time, + u_int8 rifs_time, u_int16 eifs_time, u_char band_idx) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_set_power_drop_level( + struct test_wlan_info *winfos, + u_int8 pwr_drop_level, u_char band_idx) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_set_rx_filter_pkt_len( + struct test_wlan_info *winfos, + u_int8 enable, u_char band_idx, u_int32 rx_pkt_len) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + u_int32 func_data; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + func_data = rx_pkt_len & BITS(0, 23); + func_data |= (u_int32)(band_idx << 24); + + if (enable == 1) + func_data |= BIT(30); + else + func_data &= ~BIT(30); + + ret = tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_RX_FILTER_PKT_LEN, func_data); + + return ret; +} + +s_int32 mt_op_get_antswap_capability( + struct test_wlan_info *winfos, + u_int32 *antswap_support) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + ret = pr_oid_funcptr(winfos, /*call back to ServiceWlanOid*/ + OP_WLAN_OID_GET_ANTSWAP_CAPBILITY, + NULL, + 0, + antswap_support, + NULL); + + return ret; +} + +s_int32 mt_op_set_antswap( + struct test_wlan_info *winfos, + u_int32 ant) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + ret = tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_ANT_SWP, ant); + + return ret; +} + +s_int32 mt_op_set_freq_offset( + struct test_wlan_info *winfos, + u_int32 freq_offset, u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + ret = tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_FRWQ_OFFSET, freq_offset); + + return ret; +} + +s_int32 mt_op_set_phy_counter( + struct test_wlan_info *winfos, + s_int32 control, u_char band_idx) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_set_rxv_index( + struct test_wlan_info *winfos, + u_int8 group_1, u_int8 group_2, u_char band_idx) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_set_fagc_path( + struct test_wlan_info *winfos, + u_int8 path, u_char band_idx) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_set_fw_mode( + struct test_wlan_info *winfos, u_char fw_mode) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_set_rf_test_mode( + struct test_wlan_info *winfos, + u_int32 op_mode, u_int8 icap_len, u_int16 rsp_len) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_set_test_mode_start( + struct test_wlan_info *winfos) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + ret = pr_oid_funcptr(winfos, /*call back to ServiceWlanOid*/ + OP_WLAN_OID_SET_TEST_MODE_START, + NULL, + 0, + NULL, + NULL); + + return ret; +} + +s_int32 mt_op_set_test_mode_abort( + struct test_wlan_info *winfos) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + ret = pr_oid_funcptr(winfos, /*call back to ServiceWlanOid*/ + OP_WLAN_OID_SET_TEST_MODE_ABORT, + NULL, + 0, + NULL, + NULL); + + return ret; +} + +s_int32 mt_op_backup_and_set_cr( + struct test_wlan_info *winfos, + struct test_bk_cr *bks, + u_char band_idx) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_restore_cr( + struct test_wlan_info *winfos, + struct test_bk_cr *bks, + u_char band_idx) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_set_ampdu_ba_limit( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_int8 agg_limit) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_set_sta_pause_cr( + struct test_wlan_info *winfos) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_set_ifs_cr( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_write_mac_bbp_reg( + struct test_wlan_info *winfos, + struct test_register *regs) +{ + struct param_custom_mcr_rw_struct mcr_info; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + s_int32 ret = SERV_STATUS_SUCCESS; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + mcr_info.mcr_offset = regs->cr_addr; + mcr_info.mcr_data = *regs->cr_val; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: cr_val=0x%08x\n", + __func__, *regs->cr_val)); + + ret = pr_oid_funcptr(winfos, /*call back to ServiceWlanOid*/ + OP_WLAN_OID_SET_MCR_WRITE, + &mcr_info, + sizeof(mcr_info), + NULL, + NULL); + + return ret; +} + +s_int32 mt_op_read_bulk_mac_bbp_reg( + struct test_wlan_info *winfos, + struct test_register *regs) +{ + struct param_custom_mcr_rw_struct mcr_info; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + u_int32 idx; + s_int32 ret = SERV_STATUS_SUCCESS; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + for (idx = 0; idx < regs->cr_num ; idx++) { + mcr_info.mcr_offset = regs->cr_addr + idx * 4; + mcr_info.mcr_data = 0; + + ret = pr_oid_funcptr(winfos, /*call back to ServiceWlanOid*/ + OP_WLAN_OID_QUERY_MCR_READ, + &mcr_info, + sizeof(mcr_info), + NULL, + NULL); + + if (ret == SERV_STATUS_SUCCESS) { + *regs->cr_val = mcr_info.mcr_data; + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: cr_val=0x%08x\n", + __func__, *regs->cr_val)); + } else { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: read fail ret = %d\n", + __func__, ret)); + } + } + + return ret; +} + +s_int32 mt_op_read_bulk_rf_reg( + struct test_wlan_info *winfos, + struct test_register *regs) +{ + struct param_custom_mcr_rw_struct mcr_info; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + u_int32 idx; + s_int32 ret = SERV_STATUS_SUCCESS; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + if (regs->wf_sel == 0) + regs->cr_addr = regs->cr_addr | 0x99900000; + else if (regs->wf_sel == 1) + regs->cr_addr = regs->cr_addr | 0x99910000; + + for (idx = 0; idx < regs->cr_num; idx++) { + mcr_info.mcr_offset = regs->cr_addr + idx * 4; + mcr_info.mcr_data = 0; + + ret = pr_oid_funcptr(winfos, /*call back to ServiceWlanOid*/ + OP_WLAN_OID_QUERY_MCR_READ, + &mcr_info, + sizeof(mcr_info), + NULL, + NULL); + + if (ret == SERV_STATUS_SUCCESS) { + *regs->cr_val = mcr_info.mcr_data; + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: cr_val=0x%08x\n", + __func__, *regs->cr_val)); + } else { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: read fail ret = %d\n", + __func__, ret)); + } + } + + return ret; +} + +s_int32 mt_op_write_bulk_rf_reg( + struct test_wlan_info *winfos, + struct test_register *regs) +{ + struct param_custom_mcr_rw_struct mcr_info; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + s_int32 ret = SERV_STATUS_SUCCESS; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + if (regs->wf_sel == 0) + regs->cr_addr = regs->cr_addr | 0x99900000; + else if (regs->wf_sel == 1) + regs->cr_addr = regs->cr_addr | 0x99910000; + + mcr_info.mcr_offset = regs->cr_addr; + mcr_info.mcr_data = *regs->cr_val; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: cr_val=0x%08x\n", + __func__, *regs->cr_val)); + + ret = pr_oid_funcptr(winfos, /*call back to ServiceWlanOid*/ + OP_WLAN_OID_SET_MCR_WRITE, + &mcr_info, + sizeof(mcr_info), + NULL, + NULL); + + return ret; +} + +s_int32 mt_op_read_bulk_eeprom( + struct test_wlan_info *winfos, + struct test_eeprom *eprms) +{ +#if 0 + struct param_custom_mcr_rw_struct mcr_info; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + u_int32 idx; + s_int32 ret = SERV_STATUS_SUCCESS; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + for (idx = 0; idx < eprms->length; idx++) { + mcr_info.mcr_offset = eprms->offset + idx * 4; + mcr_info.mcr_data = 0; + + ret = pr_oid_funcptr(winfos, /*call back to ServiceWlanOid*/ + OP_WLAN_OID_QUERY_MCR_READ, + &mcr_info, + sizeof(mcr_info), + NULL, + NULL); + } +#endif + return SERV_STATUS_SUCCESS; +} + +static void mt_op_set_manual_he_tb_value( + struct test_wlan_info *winfos, + struct test_ru_info *ru_sta, + struct test_configuration *configs) +{ + union hetb_rx_cmm cmm; + union hetb_tx_usr usr; + u_int8 ltf_sym_code[] = { + 0, 0, 1, 2, 2, 3, 3, 4, 4 /* SS 1~8 */ + }; + + /* setup MAC start */ + /* step 1, common info of TF */ + sys_ad_zero_mem(&cmm, sizeof(cmm)); + cmm.field.sig_a_reserved = 0x1ff; + cmm.field.ul_length = ru_sta->l_len; + cmm.field.t_pe = + (ru_sta->afactor_init & 0x3) | ((ru_sta->pe_disamb & 0x1) << 2); + cmm.field.ldpc_extra_sym = ru_sta->ldpc_extr_sym; + if (configs->stbc && ru_sta->nss == 1) + cmm.field.ltf_sym_midiam = ltf_sym_code[ru_sta->nss+1]; + else + cmm.field.ltf_sym_midiam = ltf_sym_code[ru_sta->nss]; + cmm.field.gi_ltf = configs->sgi; + cmm.field.ul_bw = configs->bw; + cmm.field.stbc = configs->stbc; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: [TF TTRCR0 ] tigger_type:0x%x,\n", + __func__, cmm.field.tigger_type)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("ul_length:0x%x cascade_ind:0x%x,\n", + cmm.field.ul_length, cmm.field.cascade_ind)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("cs_required:0x%x, ul_bw:0x%x,\n", + cmm.field.cs_required, cmm.field.ul_bw)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("gi_ltf:0x%x, mimo_ltf:0x%x,\n", + cmm.field.gi_ltf, cmm.field.mimo_ltf)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("ltf_sym_midiam:0x%x, stbc:0x%x,\n", + cmm.field.ltf_sym_midiam, cmm.field.stbc)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("ldpc_extra_sym :0x%x, ap_tx_pwr: 0x%x\n", + cmm.field.ldpc_extra_sym, cmm.field.ap_tx_pwr)); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: [TF TTRCR0 ] cr_value:0x%08x\n", + __func__, (u_int32)(cmm.cmm_info & 0xffffffff))); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: [TF TTRCR1 ] cr_value:0x%08x\n", + __func__, (u_int32)((cmm.cmm_info & 0xffffffff00000000) >> 32))); + + /* step 1, users info */ + sys_ad_zero_mem(&usr, sizeof(usr)); + usr.field.aid = 0x1; + usr.field.allocation = ru_sta->ru_index; + usr.field.coding = ru_sta->ldpc; + usr.field.mcs = ru_sta->rate & ~BIT(5); + usr.field.dcm = (ru_sta->rate & BIT(5)) >> 4; + usr.field.ss_allocation = + ((ru_sta->nss-1) << 3) | (ru_sta->start_sp_st & 0x7); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: [TF TTRCR2 ] aid:%d\n", + __func__, usr.field.aid)); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("allocation:%d, coding:%d,\n", + usr.field.allocation, usr.field.coding)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("mcs:0x%x, dcm:%d,\n", + usr.field.mcs, usr.field.dcm)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("ss_allocation:%d\n", + usr.field.ss_allocation)); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: [TF TTRCR2 ] cr_value:0x%08x\n", + __func__, usr.usr_info)); + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_TX_HE_TB_TTRCR0, + (cmm.cmm_info & 0xffffffff)); + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_TX_HE_TB_TTRCR1, + ((cmm.cmm_info & 0xffffffff00000000) >> 32)); + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_TX_HE_TB_TTRCR2, usr.usr_info); + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_TX_HE_TB_TTRCR3, 0x7f); + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_TX_HE_TB_TTRCR4, 0xffffffff); + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_TX_HE_TB_TTRCR5, 0xffffffff); + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_TX_HE_TB_TTRCR6, 0xffffffff); + +} + +s_int32 mt_op_start_tx( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs) +{ + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + u_char tx_pwr = configs->tx_pwr[configs->nss]; + u_int32 aifs = configs->ipg_param.ipg; + u_int32 pkt_cnt = configs->tx_stat.tx_cnt; + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_ru_info *ru_sta = &configs->ru_info_list[0]; + struct param_mtk_wifi_test_struct rf_at_info; + u_int32 tx_cnt = 0, buf_len = 0; +#if (CFG_WAIT_TSSI_READY == 1) + u_char i; +#endif + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_DBDC_BAND_IDX, band_idx); + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_PKTCNT, pkt_cnt); + + if (configs->tx_mode == TEST_MODE_OFDM) { + configs->tx_mode = TEST_MODE_CCK; + configs->mcs += 4; + } else if ((configs->tx_mode == TEST_MODE_CCK) + && ((configs->mcs == 9) + || (configs->mcs == 10) || (configs->mcs == 11))) + configs->tx_mode = TEST_MODE_OFDM; + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_PREAMBLE, configs->tx_mode); + + if (configs->tx_mode == TEST_MODE_CCK) { + configs->mcs |= 0x00000000; + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_RATE, configs->mcs); + } else if (configs->tx_mode == TEST_MODE_OFDM) { + if (configs->mcs == 9) + configs->mcs = 1; + else if (configs->mcs == 10) + configs->mcs = 2; + else if (configs->mcs == 11) + configs->mcs = 3; + configs->mcs |= 0x00000000; + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_RATE, configs->mcs); + } else if (configs->tx_mode >= TEST_MODE_HTMIX && + configs->tx_mode <= TEST_MODE_HE_TB) { + + if (configs->tx_mode == TEST_MODE_HE_TB) { + /*do ru operation*/ + if (ru_sta->valid) { + /*Calculate HE TB PHY Info*/ + mt_engine_calc_phy(ru_sta, + ru_sta->mpdu_length+13, + configs->stbc, + configs->sgi, + configs->max_pkt_ext); + + configs->dmnt_ru_idx = 0; + + /*Replace the mcs/nss/ldpc/mpdu_len setting*/ + configs->mcs = ru_sta->rate; + configs->nss = ru_sta->nss; + configs->ldpc = ru_sta->ldpc; + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_PKTLEN, ru_sta->mpdu_length); + + /*Do Calc Manual HE TB TX*/ + mt_op_set_manual_he_tb_value(winfos, + ru_sta, configs); + } + } + configs->mcs |= 0x80000000; + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_RATE, configs->mcs); + } + + if (tx_pwr > 0x3F) + tx_pwr += 128; + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_POWER, tx_pwr); + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_STBC, (u_int32)configs->stbc); + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_ENCODE_MODE, (u_int32)configs->ldpc); + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_IBF_ENABLE, (u_int32)configs->ibf); + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_EBF_ENABLE, (u_int32)configs->ebf); + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_PKTINTERVAL, aifs); + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_GI, configs->sgi); + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_NSS, configs->nss); + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_HWTX_MODE, winfos->hw_tx_enable); + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_COMMAND, RF_AT_COMMAND_STARTTX); + + /* For production line test, get tx count for wait calibration ready */ +#if (CFG_WAIT_TSSI_READY == 1) + for (i = 0; i < 100; i++) { +#endif + if (band_idx == TEST_DBDC_BAND0) + rf_at_info.func_idx = RF_AT_FUNCID_TXED_COUNT; + else + rf_at_info.func_idx = RF_AT_FUNCID_TXED_COUNT | BIT(8); + + rf_at_info.func_data = 0; + ret = tm_rftest_query_auto_test(winfos, + &rf_at_info, &buf_len); + if (ret == SERV_STATUS_SUCCESS) + tx_cnt = rf_at_info.func_data; + +#if (CFG_WAIT_TSSI_READY == 1) + /* For production line test, + * get tx count 16 for wait tssi ready + */ + if (tx_cnt >= 16) + break; + + msleep(20); + } +#endif + + + return ret; +} + +s_int32 mt_op_stop_tx( + struct test_wlan_info *winfos, + u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_DBDC_BAND_IDX, band_idx); + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_COMMAND, RF_AT_COMMAND_STOPTEST); + + return ret; +} + +s_int32 mt_op_start_rx( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + u_int32 func_data; + struct param_mtk_wifi_test_struct rf_at_info; + u_int32 buf_len = 0; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + /* Clear rx statistics backup buffer */ + if (band_idx == 0) { + sys_ad_zero_mem(&backup_band0_info, + sizeof(struct test_rx_stat_band_info)); + } else { + sys_ad_zero_mem(&backup_band1_info, + sizeof(struct test_rx_stat_band_info)); + } + + if (configs->tx_mode == TEST_MODE_HE_MU) { + if (configs->mu_rx_aid) + ret = tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_RX_MU_AID, + configs->mu_rx_aid); + else + ret = tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_RX_MU_AID, + 0xf800);/* 0xf800 to disable */ + } + + sys_ad_move_mem(&func_data, configs->own_mac, 4); + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_TA, func_data); + + func_data = 0; + sys_ad_move_mem(&func_data, configs->own_mac + 4, 2); + tm_rftest_set_auto_test(winfos, + (RF_AT_FUNCID_SET_TA | BIT(18)), func_data); + + ret = tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_DBDC_BAND_IDX, band_idx); + ret = tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_COMMAND, RF_AT_COMMAND_STARTRX); + + /* For production line test, get tx count for wait calibration ready */ + rf_at_info.func_idx = RF_AT_FUNCID_TXED_COUNT; + rf_at_info.func_data = 0; + ret = tm_rftest_query_auto_test(winfos, + &rf_at_info, &buf_len); + + return ret; +} + +s_int32 mt_op_stop_rx( + struct test_wlan_info *winfos, + u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_DBDC_BAND_IDX, band_idx); + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_COMMAND, RF_AT_COMMAND_STOPTEST); + + return ret; +} + +s_int32 mt_op_set_channel( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs) +{ + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + u_char central_ch0 = configs->channel; + u_char central_ch1 = configs->channel_2nd; + u_char sys_bw = configs->bw; + u_char per_pkt_bw = configs->per_pkt_bw; + u_char ch_band = configs->ch_band; + u_char pri_sel = configs->pri_sel; + s_int32 SetFreq = 0; + s_int32 ret = SERV_STATUS_SUCCESS; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + /* For POR Cal Setting - 20160601 */ + if ((central_ch0 == central_ch1) && + (sys_bw == 6) && (per_pkt_bw == 6)) { + return ret; + } + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_DBDC_BAND_IDX, band_idx); + + if ((central_ch0 >= 7 && central_ch0 <= 16) && ch_band == 1) { + /*Ch7 - Ch12, 5G (5035-5060) ch_band: 0:2.4G 1:5G */ + SetFreq = 1000 * (5000 + central_ch0 * 5); + } else if (central_ch0 == 6 && ch_band == 1) { + SetFreq = 1000 * 5032; + } else { + SetFreq = tm_ch_num_to_freq((u_int32)central_ch0); + } + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_CHNL_FREQ, SetFreq); + + if (sys_bw == 6) { + SetFreq = tm_ch_num_to_freq((u_int32)central_ch1); + tm_rftest_set_auto_test(winfos, + (RF_AT_FUNCID_CHNL_FREQ | BIT(16)), SetFreq); + } + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_CBW, + tm_bw_hqa_mapping_at((u_int32)sys_bw)); + + /* For POR Cal Setting - 20160601 */ + if ((sys_bw == 6) && (per_pkt_bw == 6)) + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_DBW, tm_bw_hqa_mapping_at(5)); + else { + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_DBW, + tm_bw_hqa_mapping_at((u_int32)per_pkt_bw)); + } + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_PRIMARY_CH, pri_sel); + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_BAND, ch_band); + + return ret; +} + +s_int32 mt_op_set_tx_content( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs) +{ + struct serv_hdr_802_11 *phdr = NULL; + u_int32 func_data; + u_int16 fc_16; + u_int32 fc, dur, seq; + u_int32 gen_payload_rule = configs->fixed_payload; + u_int32 pay_load = configs->payload[0]; + u_int32 tx_len = configs->tx_len; + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + phdr = (struct serv_hdr_802_11 *)&configs->template_frame[0]; + sys_ad_move_mem(&fc_16, &phdr->fc, sizeof(fc_16)); + fc = (u_int32)fc_16; + dur = (u_int32)phdr->duration; + seq = (u_int32)phdr->sequence; + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_DBDC_BAND_IDX, band_idx); + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_MAC_HEADER, + (fc | (dur << 16))); + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_SEQ_CTRL, seq); + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_PAYLOAD, + ((gen_payload_rule << 16) | pay_load)); + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_PKTLEN, tx_len); + + + sys_ad_move_mem(&func_data, configs->addr1[0], 4); + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_MAC_ADDRESS, func_data); + + func_data = 0; + sys_ad_move_mem(&func_data, configs->addr1[0] + 4, 2); + tm_rftest_set_auto_test(winfos, + (RF_AT_FUNCID_SET_MAC_ADDRESS | BIT(18)), + func_data); + + sys_ad_move_mem(&func_data, configs->addr2[0], 4); + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_TA, func_data); + + func_data = 0; + sys_ad_move_mem(&func_data, configs->addr2[0] + 4, 2); + tm_rftest_set_auto_test(winfos, + (RF_AT_FUNCID_SET_TA | BIT(18)), func_data); + + return ret; +} + +s_int32 mt_op_set_preamble( + struct test_wlan_info *winfos, + u_char mode) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + g_tx_mode = mode; + + if (mode == TEST_MODE_OFDM) + mode = TEST_MODE_CCK; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: tx mode = %d\n", + __func__, mode)); + + ret = tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_PREAMBLE, mode); + + return ret; +} + +s_int32 mt_op_set_rate( + struct test_wlan_info *winfos, + u_char mcs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + if (g_tx_mode == TEST_MODE_OFDM) { + g_tx_mode = TEST_MODE_CCK; + mcs += 4; + } + + if (g_tx_mode == TEST_MODE_CCK) + mcs |= 0x00000000; + else if (g_tx_mode == TEST_MODE_OFDM) { + if (mcs == 9) + mcs = 1; + else if (mcs == 10) + mcs = 2; + else if (mcs == 11) + mcs = 3; + mcs |= 0x00000000; + } else if (g_tx_mode >= TEST_MODE_HTMIX && + g_tx_mode <= TEST_MODE_HE_TB) + mcs |= 0x80000000; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: mcs = %d\n", + __func__, mcs)); + + ret = tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_RATE, mcs); + + return ret; +} + +s_int32 mt_op_set_system_bw( + struct test_wlan_info *winfos, + u_char sys_bw) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + ret = tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_CBW, + tm_bw_hqa_mapping_at((u_int32)sys_bw)); + + return ret; +} + +s_int32 mt_op_set_per_pkt_bw( + struct test_wlan_info *winfos, + u_char per_pkt_bw) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + ret = tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_DBW, + tm_bw_hqa_mapping_at((u_int32)per_pkt_bw)); + + return ret; +} + +s_int32 mt_op_reset_txrx_counter( + struct test_wlan_info *winfos) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + ret = tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_RESETTXRXCOUNTER, 0); + + return ret; +} + +s_int32 mt_op_set_rx_vector_idx( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 group1, + u_int32 group2) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + u_int32 func_data; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + func_data = group1; + func_data |= (group2 << 8); + func_data |= (u_int32)(band_idx << 16); + + ret = tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_RXV_INDEX, func_data); + + return ret; +} + +s_int32 mt_op_get_rx_stat_leg( + struct test_wlan_info *winfos, + struct test_rx_stat_leg *rx_stat) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_set_fagc_rssi_path( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 fagc_path) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + u_int32 func_data; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + func_data = (u_int32)(band_idx << 16) | (fagc_path & BITS(0, 15)); + + ret = tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_FAGC_RSSI_PATH, func_data); + + return ret; +} + +s_int32 mt_op_dbdc_tx_tone( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + u_int32 func_data; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + /* + * Select TX Antenna + * RF_Power: (1db) 0~15 + * Digi_Power: (0.25db) -32~31 + */ + func_data = (u_int32)configs->ant_idx << 16 | configs->rf_pwr; + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_TONE_RF_GAIN, func_data); + func_data = (u_int32)configs->ant_idx << 16 | configs->digi_pwr; + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_TONE_DIGITAL_GAIN, func_data); + + /* DBDC Band Index : Band0, Band1 */ + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_DBDC_BAND_IDX, band_idx); + + if (configs->tx_tone_en) { + /* Band : 2.4G/5G */ + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_BAND, + (u_int32)configs->ch_band); + + /* ToneType : Single or Two */ + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_TONE_TYPE, + (u_int32)configs->tone_type); + + /* ToneFreq: DC/5M/10M/20M/40M */ + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_TONE_BW, + configs->tone_freq); + + /* DC Offset I, DC Offset Q */ + func_data = (configs->dc_offset_Q << 16) | + configs->dc_offset_I; + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_TONE_DC_OFFSET, + func_data); + + /* Control TX Tone Start and Stop */ + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_COMMAND, + RF_AT_COMMAND_SINGLE_TONE); + } else { + /* Control TX Tone Start and Stop */ + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_COMMAND, RF_AT_COMMAND_STOPTEST); + } + + return ret; +} + +s_int32 mt_op_dbdc_tx_tone_pwr( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_dbdc_continuous_tx( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs) +{ + s_int32 SetFreq = 0; + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + u_int32 tx_mode = configs->tx_mode; + u_int32 rate = configs->rate; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + if (configs->tx_tone_en) { + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_DBDC_BAND_IDX, + (u_int32)band_idx); + + SetFreq = tm_ch_num_to_freq(configs->channel); + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_CHNL_FREQ, SetFreq); + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_PRIMARY_CH, + configs->pri_sel); + + if (tx_mode == 1) { + tx_mode = 0; + rate += 4; + } else if ((tx_mode == 0) && + ((rate == 9) || (rate == 10) || (rate == 11))) + tx_mode = 1; + + ret = tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_PREAMBLE, tx_mode); + + if (tx_mode == 0) { + rate |= 0x00000000; + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_RATE, rate); + } else if (tx_mode == 1) { + if (rate == 9) + rate = 1; + else if (rate == 10) + rate = 2; + else if (rate == 11) + rate = 3; + rate |= 0x00000000; + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_RATE, rate); + } else if (tx_mode >= 2 && tx_mode <= 4) { + rate |= 0x80000000; + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_RATE, rate); + } + + ret = tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_CBW, + tm_bw_hqa_mapping_at((u_int32)configs->bw)); + + ret = tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_CW_MODE, + configs->tx_fd_mode); + + if (ret != SERV_STATUS_SUCCESS) + return SERV_STATUS_HAL_OP_FAIL; + + ret = tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_ANTMASK, + (u_int32)configs->ant_mask); + + if (ret != SERV_STATUS_SUCCESS) + return SERV_STATUS_HAL_OP_FAIL; + + ret = tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_COMMAND, RF_AT_COMMAND_CW); + if (ret != SERV_STATUS_SUCCESS) + return SERV_STATUS_HAL_OP_FAIL; + + } else { + ret = tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_COMMAND, + RF_AT_COMMAND_STOPTEST); + + if (ret != SERV_STATUS_SUCCESS) + return SERV_STATUS_HAL_OP_FAIL; + } + return ret; +} + +s_int32 mt_op_get_tx_info( + struct test_wlan_info *winfos, + struct test_configuration *test_configs_band0, + struct test_configuration *test_configs_band1) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct param_mtk_wifi_test_struct rf_at_info; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + u_int32 buf_len = 0; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + rf_at_info.func_idx = RF_AT_FUNCID_TXED_COUNT; + rf_at_info.func_data = 0; + ret = tm_rftest_query_auto_test(winfos, + &rf_at_info, &buf_len); + if (ret == SERV_STATUS_SUCCESS) + test_configs_band0->tx_stat.tx_done_cnt = rf_at_info.func_data; + + rf_at_info.func_idx = RF_AT_FUNCID_TXED_COUNT | BIT(8); + rf_at_info.func_data = 0; + ret = tm_rftest_query_auto_test(winfos, + &rf_at_info, &buf_len); + if (ret == SERV_STATUS_SUCCESS) + test_configs_band1->tx_stat.tx_done_cnt = rf_at_info.func_data; + + return ret; +} + +s_int32 mt_op_get_rx_statistics_all( + struct test_wlan_info *winfos, + struct hqa_comm_rx_stat *hqa_rx_stat) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct param_custom_access_rx_stat rx_stat_test; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + rx_stat_test.seq_num = 0; + rx_stat_test.total_num = 72; + + ret = pr_oid_funcptr(winfos, /*call back to ServiceWlanOid*/ + OP_WLAN_OID_QUERY_RX_STATISTICS, + &rx_stat_test, + sizeof(rx_stat_test), + NULL, + hqa_rx_stat); + + return ret; +} + +s_int32 mt_op_get_capability( + struct test_wlan_info *winfos, + struct test_capability *capability) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + ret = pr_oid_funcptr(winfos, /*call back to ServiceWlanOid*/ + OP_WLAN_OID_GET_CAPABILITY, + NULL, + 0, + NULL, + capability); + + return ret; +} + +s_int32 mt_op_calibration_test_mode( + struct test_wlan_info *winfos, + u_char mode) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + if (mode == 2) + ret = tm_icap_mode(winfos); + + return ret; +} + +s_int32 mt_op_set_icap_start( + struct test_wlan_info *winfos, + u_int8 *data) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + struct test_struct_ext r_test_info; + struct hqa_rbist_cap_start *pr_rbist_info; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + pr_rbist_info = &(r_test_info.data.icap_info); + + /*copy icap start parameters*/ + sys_ad_move_mem(pr_rbist_info, + data, + sizeof(struct hqa_rbist_cap_start)); + + /*over write parameters for mobile setting*/ + pr_rbist_info->en_bit_width = 0; /* 0:32bit, 1:96bit, 2:128bit */ + pr_rbist_info->arch = 1; /*0:Support on-chip, 1:Support on-the fly*/ + pr_rbist_info->phy_idx = 0; + + SERV_LOG(SERV_DBG_CAT_MISC, SERV_DBG_LVL_WARN, + ("%s: en_bit_width = 0x%08x, arch = 0x%08x, phy_idx = 0x%08x\n", + __func__, + pr_rbist_info->en_bit_width, + pr_rbist_info->arch, + pr_rbist_info->phy_idx)); + + pr_rbist_info->emi_start_addr = + (u_int32) (winfos->emi_phy_base & 0xFFFFFFFF); + pr_rbist_info->emi_end_addr = + (u_int32) ((winfos->emi_phy_base + + winfos->emi_phy_size) & 0xFFFFFFFF); + pr_rbist_info->emi_msb_addr = 0; /*CONNAC 1.x useless*/ + + SERV_LOG(SERV_DBG_CAT_MISC, SERV_DBG_LVL_WARN, + ("%s: StartAddr=0x%08x,EndAddr=0x%08x,MsbAddr=0x%08x\n", + __func__, + pr_rbist_info->emi_start_addr, + pr_rbist_info->emi_end_addr, + pr_rbist_info->emi_msb_addr)); + + if (pr_rbist_info->trig == 1) { /*Start Capture data*/ + ret = pr_oid_funcptr(winfos, /*call back to ServiceWlanOid*/ + OP_WLAN_OID_SET_TEST_ICAP_START, + &r_test_info, + sizeof(r_test_info), + NULL, + NULL); + } else if (pr_rbist_info->trig == 0) { /*don't Capture data*/ + ret = pr_oid_funcptr(winfos, /*call back to ServiceWlanOid*/ + OP_WLAN_OID_SET_TEST_ICAP_ABORT, + &r_test_info, + sizeof(r_test_info), + NULL, + NULL); + } + + SERV_LOG(SERV_DBG_CAT_MISC, SERV_DBG_LVL_WARN, + ("Start ICAP trig:%d,node=0x%08x,ret=0x%08x\n", + pr_rbist_info->trig, + pr_rbist_info->cap_node, + ret)); + + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_get_icap_status( + struct test_wlan_info *winfos, + s_int32 *icap_stat) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + struct test_struct_ext r_test_info; + + ret = pr_oid_funcptr(winfos, /*call back to ServiceWlanOid*/ + OP_WLAN_OID_SET_TEST_ICAP_STATUS, + &r_test_info, + sizeof(r_test_info), + NULL, + icap_stat); + + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + SERV_LOG(SERV_DBG_CAT_MISC, SERV_DBG_LVL_WARN, + ("Query Status ICAP %d, ret=0x%X\n", + *icap_stat, /*0:OK,1:WAITING,2:FAIL*/ + ret)); + + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_get_icap_max_data_len( + struct test_wlan_info *winfos, + u_long *max_data_len) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + ret = pr_oid_funcptr(winfos, /*call back to ServiceWlanOid*/ + OP_WLAN_OID_GET_TEST_ICAP_MAX_DATA_LEN, + NULL, + 0, + NULL, + max_data_len); + + SERV_LOG(SERV_DBG_CAT_MISC, SERV_DBG_LVL_WARN, + ("ICAP max data len %lu", *max_data_len)); + + + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_get_icap_data( + struct test_wlan_info *winfos, + s_int32 *icap_cnt, + s_int32 *icap_data, + u_int32 wf_num, + u_int32 iq_type) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct icap_dump_iq r_dump_iq; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + r_dump_iq.wf_num = wf_num; + r_dump_iq.iq_type = iq_type; + r_dump_iq.icap_cnt = 0; + r_dump_iq.icap_data_len = 0; + r_dump_iq.picap_data = (s_int8 *)icap_data; + + ret = pr_oid_funcptr(winfos, /*call back to ServiceWlanOid*/ + OP_WLAN_OID_GET_TEST_ICAP_DATA, + &r_dump_iq, + sizeof(r_dump_iq), + NULL, + NULL); + + if (ret == SERV_STATUS_SUCCESS) { + *icap_cnt = r_dump_iq.icap_cnt; + /*debug*/ + /*sys_ad_mem_dump32(icap_data, r_dump_iq.icap_data_len);*/ + } + + SERV_LOG(SERV_DBG_CAT_MISC, SERV_DBG_LVL_WARN, + ("ICAP:wf[%d][%c],cnt:%d,len:%d,data:0x%p,ret:0x%X\n", + r_dump_iq.wf_num, + (r_dump_iq.iq_type == ATE_CAP_I_TYPE)?'I':'Q', + *icap_cnt, + r_dump_iq.icap_data_len, + icap_data, + ret)); + + + return ret; +} + +s_int32 mt_op_do_cal_item( + struct test_wlan_info *winfos, + u_int32 item, + u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + ret = pr_oid_funcptr(winfos, /*call back to ServiceWlanOid*/ + OP_WLAN_OID_RESET_RECAL_COUNT, + NULL, + 0, + NULL, + NULL); + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_DBDC_BAND_IDX, band_idx); + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_RECAL_CAL_STEP, item); + + return ret; +} + +s_int32 mt_op_set_band_mode( + struct test_wlan_info *winfos, + struct test_band_state *band_state) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + u_int32 dbdc_enb; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + if (band_state->band_mode == TEST_BAND_MODE_DUAL) + dbdc_enb = TEST_DBDC_ENABLE; + else + dbdc_enb = TEST_DBDC_DISABLE; + + SET_TEST_DBDC(winfos, dbdc_enb); + + ret = tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_DBDC_ENABLE, dbdc_enb); + + return ret; +} + +s_int32 mt_op_get_chipid( + struct test_wlan_info *winfos) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_mps_start( + struct test_wlan_info *winfos, + u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_DBDC_BAND_IDX, band_idx); + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_COMMAND, RF_AT_COMMAND_STARTTX); + + return ret; +} + +s_int32 mt_op_mps_set_nss( + struct test_wlan_info *winfos, + u_int32 len, + struct test_mps_setting *mps_setting) +{ + u_int32 i; + s_int32 ret = SERV_STATUS_SUCCESS; + + for (i = 0; i < len; i++) { + tm_rftest_set_auto_test(winfos, + (RF_AT_FUNCID_SET_MPS_NSS | (i << 16)), + mps_setting[i+1].nss); + } + + return ret; +} + +s_int32 mt_op_mps_set_per_packet_bw( + struct test_wlan_info *winfos, + u_int32 len, + struct test_mps_setting *mps_setting) +{ + u_int32 i; + s_int32 ret = SERV_STATUS_SUCCESS; + + for (i = 0; i < len; i++) { + tm_rftest_set_auto_test(winfos, + (RF_AT_FUNCID_SET_MPS_PACKAGE_BW | (i << 16)), + mps_setting[i+1].pkt_bw); + } + + return ret; +} + +s_int32 mt_op_mps_set_packet_count( + struct test_wlan_info *winfos, + u_int32 len, + struct test_mps_setting *mps_setting) +{ + u_int32 i; + s_int32 ret = SERV_STATUS_SUCCESS; + + for (i = 0; i < len; i++) { + tm_rftest_set_auto_test(winfos, + (RF_AT_FUNCID_SET_MPS_PKT_CNT | (i << 16)), + mps_setting[i+1].pkt_cnt); + } + + return ret; +} + +s_int32 mt_op_mps_set_payload_length( + struct test_wlan_info *winfos, + u_int32 len, + struct test_mps_setting *mps_setting) +{ + u_int32 i; + s_int32 ret = SERV_STATUS_SUCCESS; + + for (i = 0; i < len; i++) { + tm_rftest_set_auto_test(winfos, + (RF_AT_FUNCID_SET_MPS_PAYLOAD_LEN | (i << 16)), + mps_setting[i+1].pkt_len); + } + + return ret; +} + +s_int32 mt_op_mps_set_power_gain( + struct test_wlan_info *winfos, + u_int32 len, + struct test_mps_setting *mps_setting) +{ + u_int32 i; + s_int32 ret = SERV_STATUS_SUCCESS; + + for (i = 0; i < len; i++) { + tm_rftest_set_auto_test(winfos, + (RF_AT_FUNCID_SET_MPS_PWR_GAIN | (i << 16)), + mps_setting[i+1].pwr); + } + + return ret; +} + +s_int32 mt_op_mps_set_seq_data( + struct test_wlan_info *winfos, + u_int32 len, + struct test_mps_setting *mps_setting) +{ + u_int32 i; + u_int32 *mps_set = NULL; + u_int32 mode, mcs, tx_path; + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + ret = sys_ad_alloc_mem((u_char **)&mps_set, sizeof(u_int32) * len); + + if (pr_oid_funcptr == NULL) { + sys_ad_free_mem(mps_set); + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + } + + for (i = 0; i < len; i++) { + mode = mps_setting[i+1].tx_mode; + mcs = mps_setting[i+1].mcs; + tx_path = mps_setting[i+1].tx_ant; + + if (mode == 1) { + mode = 0; + mcs += 4; + } else if ((mode == 0) && ((mcs == 9) || (mcs == 10) || + (mcs == 11))) { + mode = 1; + } + + if (mode == 0) { + mcs |= 0x00000000; + } else if (mode == 1) { + if (mcs == 9) + mcs = 1; + else if (mcs == 10) + mcs = 2; + else if (mcs == 11) + mcs = 3; + mcs |= 0x00000000; + } else if (mode >= 2 && mode <= 4) { + mcs |= 0x80000000; + } + + mps_set[i] = (mcs) | (tx_path << 8) | (mode << 24); + + } + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_MPS_SIZE, len); + + for (i = 0; i < len; i++) { + tm_rftest_set_auto_test(winfos, + (RF_AT_FUNCID_SET_MPS_SEQ_DATA | (i << 16)), + mps_set[i]); + } + + sys_ad_free_mem(mps_set); + + return ret; +} + +s_int32 mt_op_get_tx_pwr( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx, + u_char channel, + u_char ant_idx, + u_int32 *power) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + struct param_mtk_wifi_test_struct rf_at_info; + u_int32 buf_len = 0; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_DBDC_BAND_IDX, band_idx); + + rf_at_info.func_idx = RF_AT_FUNCID_GET_CH_TX_PWR_OFFSET; + rf_at_info.func_data = 0; + + ret = tm_rftest_query_auto_test(winfos, + &rf_at_info, &buf_len); + + if (ret == SERV_STATUS_SUCCESS) { + *power = rf_at_info.func_data; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: pwr:%u!\n", + __func__, *power)); + } else { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: fail!\n", + __func__)); + } + + return ret; +} + +s_int32 mt_op_set_tx_pwr( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx, + struct test_txpwr_param *pwr_param) +{ + u_int32 Pwr = pwr_param->power; + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_DBDC_BAND_IDX, band_idx); + + if (Pwr > 0x3F) + Pwr += 128; + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_POWER, Pwr); + + return ret; +} + +s_int32 mt_op_get_freq_offset( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 *freq_offset) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_get_cfg_on_off( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 type, + u_int32 *result) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_get_tx_tone_pwr( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 ant_idx, + u_int32 *power) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_reset_recal_cnt( + struct test_wlan_info *winfos +) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + ret = pr_oid_funcptr(winfos, /*call back to ServiceWlanOid*/ + OP_WLAN_OID_RESET_RECAL_COUNT, + NULL, + 0, + 0, + NULL); + + return ret; +} + +s_int32 mt_op_get_recal_cnt( + struct test_wlan_info *winfos, + u_int32 *recal_cnt, + u_int32 *recal_dw_num) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + + ret = pr_oid_funcptr(winfos, /*call back to ServiceWlanOid*/ + OP_WLAN_OID_GET_RECAL_COUNT, + NULL, + 0, + recal_cnt, + NULL); + + *recal_dw_num = 3; /* ncal_id, cal_addr, cal_value */ + + return ret; +} + +s_int32 mt_op_get_recal_content( + struct test_wlan_info *winfos, + u_int32 *content) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + ret = pr_oid_funcptr(winfos, /*call back to ServiceWlanOid*/ + OP_WLAN_OID_GET_RECAL_CONTENT, + NULL, + 0, + NULL, + content); + + return ret; +} + +s_int32 mt_op_get_rxv_cnt( + struct test_wlan_info *winfos, + u_int32 *rxv_cnt, + u_int32 *rxv_dw_num) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct param_mtk_wifi_test_struct rf_at_info; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + u_int32 buf_len = 0; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + rf_at_info.func_idx = RF_AT_FUNCID_RESULT_INFO; + rf_at_info.func_data = RF_AT_FUNCID_RXV_DUMP; + ret = tm_rftest_query_auto_test(winfos, + &rf_at_info, &buf_len); + + if (ret == SERV_STATUS_SUCCESS) { + if (rf_at_info.func_data > 56) + rf_at_info.func_data = 56; + + *rxv_cnt = rf_at_info.func_data; + *rxv_dw_num = 36; /* 9 cycle * 4 bytes = 36, 9 cycles */ + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: rxv_cnt = %d, rxv_dw_num = %d\n", + __func__, *rxv_cnt, *rxv_dw_num)); + } else { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: get rxv count fail ret = %d\n", + __func__, ret)); + + return ret; + } + + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_get_rxv_content( + struct test_wlan_info *winfos, + u_int32 dw_cnt, + u_int32 *content) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct param_mtk_wifi_test_struct rf_at_info; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + u_int32 i, buf_len = 0; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + for (i = 0; i < dw_cnt; i += 4) { + rf_at_info.func_idx = RF_AT_FUNCID_RXV_DUMP; + rf_at_info.func_data = i; + ret = tm_rftest_query_auto_test(winfos, + &rf_at_info, &buf_len); + + if (ret == SERV_STATUS_SUCCESS) { + *content = rf_at_info.func_data; + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: content[%d] = %x\n", + __func__, i, *content)); + } else { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: get rxv data fail ret = %d\n", + __func__, ret)); + + return ret; + } + } + + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_set_cal_bypass( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 cal_item) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_set_dpd( + struct test_wlan_info *winfos, + u_int32 on_off, + u_int32 wf_sel) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_set_tssi( + struct test_wlan_info *winfos, + u_int32 on_off, + u_int32 wf_sel) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_get_thermal_val( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx, + u_int32 *value) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct param_mtk_wifi_test_struct rf_at_info; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + u_int32 buf_len = 0; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + rf_at_info.func_idx = RF_AT_FUNCID_TEMP_SENSOR; + rf_at_info.func_data = 0; + + ret = tm_rftest_query_auto_test(winfos, + &rf_at_info, &buf_len); + + if (ret == SERV_STATUS_SUCCESS) { + *value = rf_at_info.func_data; + *value = *value >> 16; + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: value = %x\n", + __func__, *value)); + } else { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: get thermal fail ret = %d\n", + __func__, ret)); + + return ret; + } + + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_set_rdd_test( + struct test_wlan_info *winfos, + u_int32 rdd_idx, + u_int32 rdd_sel, + u_int32 enable) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_set_off_ch_scan( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx, + struct test_off_ch_param *param) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_get_rdd_cnt( + struct test_wlan_info *winfos, + u_int32 *rdd_cnt, + u_int32 *rdd_dw_num) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_get_rdd_content( + struct test_wlan_info *winfos, + u_int32 *content, + u_int32 *total_cnt) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_set_tam_arb( + struct test_wlan_info *winfos, + u_int8 arb_op_mode) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_set_muru_manual( + void *virtual_device, + struct test_wlan_info *winfos, + struct test_configuration *configs) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_hetb_ctrl( + struct test_wlan_info *winfos, + u_char band_idx, + u_char ctrl_type, + u_char enable, + u_int8 bw, + u_int8 ltf_gi, + u_int8 stbc, + u_int8 pri_ru_idx, + struct test_ru_info *ru_info) +{ + return SERV_STATUS_SUCCESS; +} + + +s_int32 mt_op_get_rx_stat_band( + struct test_wlan_info *winfos, + u_int8 band_idx, + u_int8 blk_idx, + struct test_rx_stat_band_info *rx_st_band) +{ + + s_int32 ret = SERV_STATUS_SUCCESS; + struct param_custom_access_rx_stat rx_stat_test; + wlan_oid_handler_t pr_oid_funcptr = winfos->oid_funcptr; + + if (pr_oid_funcptr == NULL) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + tm_rftest_set_auto_test(winfos, + RF_AT_FUNCID_SET_DBDC_BAND_IDX, band_idx); + + rx_stat_test.seq_num = 0; + rx_stat_test.total_num = 72; + + ret = pr_oid_funcptr(winfos, /*call back to ServiceWlanOid*/ + OP_WLAN_OID_QUERY_RX_STATISTICS, + &rx_stat_test, + sizeof(rx_stat_test), + NULL, + &test_hqa_rx_stat); + + if (band_idx == M_BAND_0) { + rx_st_band->mac_rx_fcs_err_cnt = + SERV_OS_NTOHL(test_hqa_rx_stat.mac_rx_fcs_err_cnt) + + SERV_OS_NTOHL(backup_band0_info.mac_rx_fcs_err_cnt); + rx_st_band->mac_rx_mdrdy_cnt = + SERV_OS_NTOHL(test_hqa_rx_stat.mac_rx_mdrdy_cnt) + + SERV_OS_NTOHL(backup_band0_info.mac_rx_mdrdy_cnt); + rx_st_band->mac_rx_len_mismatch = + SERV_OS_NTOHL(test_hqa_rx_stat.mac_rx_len_mismatch) + + SERV_OS_NTOHL(backup_band0_info.mac_rx_len_mismatch); + rx_st_band->mac_rx_fcs_ok_cnt = rx_st_band->mac_rx_mdrdy_cnt - + rx_st_band->mac_rx_fcs_err_cnt; + rx_st_band->phy_rx_fcs_err_cnt_cck = + SERV_OS_NTOHL(test_hqa_rx_stat.phy_rx_fcs_err_cnt_cck); + rx_st_band->phy_rx_fcs_err_cnt_ofdm = + SERV_OS_NTOHL(test_hqa_rx_stat.phy_rx_fcs_err_cnt_ofdm); + rx_st_band->phy_rx_pd_cck = + SERV_OS_NTOHL(test_hqa_rx_stat.phy_rx_pd_cck); + rx_st_band->phy_rx_pd_ofdm = + SERV_OS_NTOHL(test_hqa_rx_stat.phy_rx_pd_ofdm); + rx_st_band->phy_rx_sig_err_cck = + SERV_OS_NTOHL(test_hqa_rx_stat.phy_rx_sig_err_cck); + rx_st_band->phy_rx_sfd_err_cck = + SERV_OS_NTOHL(test_hqa_rx_stat.phy_rx_sfd_err_cck); + rx_st_band->phy_rx_sig_err_ofdm = + SERV_OS_NTOHL(test_hqa_rx_stat.phy_rx_sig_err_ofdm); + rx_st_band->phy_rx_tag_err_ofdm = + SERV_OS_NTOHL(test_hqa_rx_stat.phy_rx_tag_err_ofdm); + rx_st_band->phy_rx_mdrdy_cnt_cck = + SERV_OS_NTOHL(test_hqa_rx_stat.phy_rx_mdrdy_cnt_cck); + rx_st_band->phy_rx_mdrdy_cnt_ofdm = + SERV_OS_NTOHL(test_hqa_rx_stat.phy_rx_mdrdy_cnt_ofdm); + + /* Backup Band1 info */ + backup_band1_info.mac_rx_fcs_err_cnt += + test_hqa_rx_stat.mac_rx_fcs_err_cnt_band1; + + backup_band1_info.mac_rx_mdrdy_cnt += + test_hqa_rx_stat.mac_rx_mdrdy_cnt_band1; + + backup_band1_info.mac_rx_len_mismatch += + test_hqa_rx_stat.mac_rx_len_mismatch_band1; + + /* Reset Band0 backup info */ + sys_ad_zero_mem(&backup_band0_info, + sizeof(struct test_rx_stat_band_info)); + } else { + rx_st_band->mac_rx_fcs_err_cnt = + SERV_OS_NTOHL( + test_hqa_rx_stat.mac_rx_fcs_err_cnt_band1) + + SERV_OS_NTOHL( + backup_band1_info.mac_rx_fcs_err_cnt); + rx_st_band->mac_rx_mdrdy_cnt = + SERV_OS_NTOHL( + test_hqa_rx_stat.mac_rx_mdrdy_cnt_band1) + + SERV_OS_NTOHL( + backup_band1_info.mac_rx_mdrdy_cnt); + rx_st_band->mac_rx_len_mismatch = + SERV_OS_NTOHL( + test_hqa_rx_stat.mac_rx_len_mismatch_band1) + + SERV_OS_NTOHL( + backup_band1_info.mac_rx_len_mismatch); + rx_st_band->mac_rx_fcs_ok_cnt = rx_st_band->mac_rx_mdrdy_cnt - + rx_st_band->mac_rx_fcs_err_cnt; + rx_st_band->phy_rx_fcs_err_cnt_cck = + SERV_OS_NTOHL( + test_hqa_rx_stat.phy_rx_fcs_err_cnt_cck_band1); + rx_st_band->phy_rx_fcs_err_cnt_ofdm = + SERV_OS_NTOHL( + test_hqa_rx_stat.phy_rx_fcs_err_cnt_ofdm_band1); + rx_st_band->phy_rx_pd_cck = + SERV_OS_NTOHL( + test_hqa_rx_stat.phy_rx_pd_cck_band1); + rx_st_band->phy_rx_pd_ofdm = + SERV_OS_NTOHL( + test_hqa_rx_stat.phy_rx_pd_ofdm_band1); + rx_st_band->phy_rx_sig_err_cck = + SERV_OS_NTOHL( + test_hqa_rx_stat.phy_rx_sig_err_cck_band1); + rx_st_band->phy_rx_sfd_err_cck = + SERV_OS_NTOHL( + test_hqa_rx_stat.phy_rx_sfd_err_cck_band1); + rx_st_band->phy_rx_sig_err_ofdm = + SERV_OS_NTOHL( + test_hqa_rx_stat.phy_rx_sig_err_ofdm_band1); + rx_st_band->phy_rx_tag_err_ofdm = + SERV_OS_NTOHL( + test_hqa_rx_stat.phy_rx_tag_err_ofdm_band1); + rx_st_band->phy_rx_mdrdy_cnt_cck = + SERV_OS_NTOHL( + test_hqa_rx_stat.phy_rx_mdrdy_cnt_cck_band1); + rx_st_band->phy_rx_mdrdy_cnt_ofdm = + SERV_OS_NTOHL( + test_hqa_rx_stat.phy_rx_mdrdy_cnt_ofdm_band1); + + + /* Backup Band0 info */ + backup_band0_info.mac_rx_fcs_err_cnt += + test_hqa_rx_stat.mac_rx_fcs_err_cnt; + + backup_band0_info.mac_rx_mdrdy_cnt += + test_hqa_rx_stat.mac_rx_mdrdy_cnt; + + backup_band0_info.mac_rx_len_mismatch += + test_hqa_rx_stat.mac_rx_len_mismatch; + + /* Reset Band1 backup info */ + sys_ad_zero_mem(&backup_band1_info, + sizeof(struct test_rx_stat_band_info)); + } + + return ret; +} + +s_int32 mt_op_set_mutb_spe( + struct test_wlan_info *winfos, + u_char band_idx, + u_char tx_mode, + u_int8 spe_idx) +{ + return SERV_STATUS_SUCCESS; +} + + +s_int32 mt_op_get_rx_stat_path( + struct test_wlan_info *winfos, + u_int8 band_idx, + u_int8 blk_idx, + struct test_rx_stat_path_info *rx_st_path) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + switch (blk_idx) { + case ANT_WF0: + rx_st_path->rcpi = + SERV_OS_NTOHL(test_hqa_rx_stat.rcpi0); + rx_st_path->rssi = + SERV_OS_NTOHL(test_hqa_rx_stat.rssi0); + rx_st_path->fagc_ib_rssi = + SERV_OS_NTOHL(test_hqa_rx_stat.fagc_ib_RSSSI0); + rx_st_path->fagc_wb_rssi = + SERV_OS_NTOHL(test_hqa_rx_stat.fagc_wb_RSSSI0); + rx_st_path->inst_ib_rssi = + SERV_OS_NTOHL(test_hqa_rx_stat.inst_ib_RSSSI0); + rx_st_path->inst_wb_rssi = + SERV_OS_NTOHL(test_hqa_rx_stat.inst_wb_RSSSI0); + break; + case ANT_WF1: + rx_st_path->rcpi = + SERV_OS_NTOHL(test_hqa_rx_stat.rcpi1); + rx_st_path->rssi = + SERV_OS_NTOHL(test_hqa_rx_stat.rssi1); + rx_st_path->fagc_ib_rssi = + SERV_OS_NTOHL(test_hqa_rx_stat.fagc_ib_RSSSI1); + rx_st_path->fagc_wb_rssi = + SERV_OS_NTOHL(test_hqa_rx_stat.fagc_wb_RSSSI1); + rx_st_path->inst_ib_rssi = + SERV_OS_NTOHL(test_hqa_rx_stat.inst_ib_RSSSI1); + rx_st_path->inst_wb_rssi = + SERV_OS_NTOHL(test_hqa_rx_stat.inst_wb_RSSSI1); + break; + + default: + ret = SERV_STATUS_HAL_OP_FAIL; + break; + } + + return ret; +} + +s_int32 mt_op_set_ru_aid( + struct test_wlan_info *winfos, + u_char band_idx, + u_int16 mu_rx_aid) + +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_get_rx_stat_user( + struct test_wlan_info *winfos, + u_int8 band_idx, + u_int8 blk_idx, + struct test_rx_stat_user_info *rx_st_user) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + rx_st_user->freq_offset_from_rx = + SERV_OS_NTOHL(test_hqa_rx_stat.freq_offset_from_rx); + if (band_idx == M_BAND_0) + rx_st_user->snr = SERV_OS_NTOHL(test_hqa_rx_stat.snr0); + else + rx_st_user->snr = SERV_OS_NTOHL(test_hqa_rx_stat.snr1); + + rx_st_user->fcs_error_cnt = + SERV_OS_NTOHL(test_hqa_rx_stat.mac_rx_fcs_err_cnt); + + return ret; +} + +s_int32 mt_op_get_rx_stat_comm( + struct test_wlan_info *winfos, + u_int8 band_idx, + u_int8 blk_idx, + struct test_rx_stat_comm_info *rx_st_comm) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + rx_st_comm->rx_fifo_full = + SERV_OS_NTOHL(test_hqa_rx_stat.rx_fifo_full); + rx_st_comm->aci_hit_low = + SERV_OS_NTOHL(test_hqa_rx_stat.aci_hit_low); + rx_st_comm->aci_hit_high = + SERV_OS_NTOHL(test_hqa_rx_stat.aci_hit_high); + rx_st_comm->mu_pkt_count = + SERV_OS_NTOHL(test_hqa_rx_stat.mu_pkt_count); + rx_st_comm->sig_mcs = + SERV_OS_NTOHL(test_hqa_rx_stat.sig_mcs); + rx_st_comm->sinr = + SERV_OS_NTOHL(test_hqa_rx_stat.sinr); + if (band_idx == M_BAND_0) { + rx_st_comm->driver_rx_count = + SERV_OS_NTOHL(test_hqa_rx_stat.driver_rx_count); + } else { + rx_st_comm->driver_rx_count = + SERV_OS_NTOHL(test_hqa_rx_stat.driver_rx_count1); + } + return ret; +} + +s_int32 mt_op_get_wf_path_comb( + struct test_wlan_info *winfos, + u_int8 band_idx, + boolean dbdc_mode_en, + u_int8 *path, + u_int8 *path_len) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_int8 i = 0; + + /* sanity check for null pointer */ + if (!path) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + /* sanity check for null pointer */ + if (!path_len) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + if (dbdc_mode_en) { + *path_len = 1; + if (band_idx == M_BAND_0) + *path = 0; + else + *path = 1; + } else { + *path_len = 2; + for (i = 0; i < *path_len; i++) + *(path + i) = i; + } + + if (*path_len > MAX_ANT_NUM) + ret = FALSE; + + return ret; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/hal/include/operation.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/hal/include/operation.h new file mode 100644 index 0000000000000..88865799bcf7e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/hal/include/operation.h @@ -0,0 +1,486 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#ifndef __OPERATION_H__ +#define __OPERATION_H__ + +#include "test_mac.h" +#include "net_adaption.h" + +/***************************************************************************** + * Enum value definition + *****************************************************************************/ +/* gen4m object id list */ +enum op_wlan_oid { + OP_WLAN_OID_SET_TEST_MODE_START = 0, + OP_WLAN_OID_SET_TEST_MODE_ABORT = 1, + OP_WLAN_OID_RFTEST_SET_AUTO_TEST = 2, + OP_WLAN_OID_QUERY_RX_STATISTICS = 3, + OP_WLAN_OID_SET_TEST_ICAP_MODE = 4, + OP_WLAN_OID_RFTEST_QUERY_AUTO_TEST = 5, + OP_WLAN_OID_SET_MCR_WRITE = 6, + OP_WLAN_OID_QUERY_MCR_READ = 7, + OP_WLAN_OID_GET_RECAL_COUNT = 8, + OP_WLAN_OID_GET_RECAL_CONTENT = 9, + OP_WLAN_OID_GET_ANTSWAP_CAPBILITY = 10, + OP_WLAN_OID_SET_TEST_ICAP_START = 11, + OP_WLAN_OID_SET_TEST_ICAP_ABORT = 12, + OP_WLAN_OID_SET_TEST_ICAP_STATUS = 13, + OP_WLAN_OID_GET_TEST_ICAP_MAX_DATA_LEN = 14, + OP_WLAN_OID_GET_TEST_ICAP_DATA = 15, + OP_WLAN_OID_RESET_RECAL_COUNT = 16, + OP_WLAN_OID_GET_CAPABILITY = 17, + OP_WLAN_OID_NUM +}; + +enum ENUM_ANT_NUM { + ANT_WF0 = 0, + ANT_WF1 = 1, + MAX_ANT_NUM +}; + +enum ENUM_M_BAND_NUM { + M_BAND_0 = 0, + M_BAND_1 = 1, + M_BAND_NUM +}; + +/***************************************************************************** + * Structure definition + *****************************************************************************/ +struct param_mtk_wifi_test_struct { + u_int32 func_idx; + u_int32 func_data; +}; + +struct param_custom_access_rx_stat { + u_int32 seq_num; + u_int32 total_num; +}; + +struct param_custom_mcr_rw_struct { + u_int32 mcr_offset; + u_int32 mcr_data; +}; + +struct test_txpwr_cfg { + u_int32 ant_idx; + u_int32 txpwr; + u_int32 channel; + u_int32 band_idx; + u_int32 ch_band; +}; + +struct test_ch_cfg { + u_int8 ctrl_ch; + u_int8 ctrl_ch2; + u_int8 central_ch; + u_int8 bw; + u_int8 tx_strm; + u_int8 rx_path; + boolean scan; + boolean dfs_check; + u_int8 band_idx; + u_int8 ch_band; + u_int32 out_band_freq; +}; + +/* Test rbist status for hqa command usage*/ +struct GNU_PACKED hqa_rbist_cap_start { + u_int32 trig; + u_int32 ring_cap_en; + u_int32 trig_event; + u_int32 cap_node; + u_int32 cap_len; + u_int32 cap_stop_cycle; + u_int32 mac_trig_event; + u_int32 src_addr_lsb; + u_int32 src_addr_msb; + u_int32 band_idx; + u_int32 bw; + u_int32 en_bit_width; /* 0:32bit, 1:96bit, 2:128bit */ + u_int32 arch; /* 0:on-chip, 1:on-the-fly */ + u_int32 phy_idx; + u_int32 emi_start_addr; + u_int32 emi_end_addr; + u_int32 emi_msb_addr; + u_int32 cap_src; + u_int32 resv[2]; +}; + +struct test_struct_ext { + u_int32 func_idx; + union { + u_int32 func_data; + u_int32 cal_dump; + struct hqa_rbist_cap_start icap_info; + } data; +}; + +/***************************************************************************** + * Function declaration + *****************************************************************************/ +s_int32 mt_op_set_tr_mac( + struct test_wlan_info *winfos, + s_int32 op_type, boolean enable, u_char band_idx); +s_int32 mt_op_set_tx_stream( + struct test_wlan_info *winfos, + u_int32 stream_nums, u_char band_idx); +s_int32 mt_op_set_tx_path( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs); +s_int32 mt_op_set_rx_path( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs); +s_int32 mt_op_set_rx_filter( + struct test_wlan_info *winfos, + struct rx_filter_ctrl rx_filter); +s_int32 mt_op_set_clean_persta_txq( + struct test_wlan_info *winfos, + boolean sta_pause_enable, u_char omac_idx, u_char band_idx); +s_int32 mt_op_set_cfg_on_off( + struct test_wlan_info *winfos, + u_int8 type, u_int8 enable, u_char band_idx); +s_int32 mt_op_log_on_off( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 log_type, + u_int32 log_ctrl, + u_int32 log_size); +s_int32 mt_op_set_antenna_port( + struct test_wlan_info *winfos, + u_int8 rf_mode_mask, u_int8 rf_port_mask, u_int8 ant_port_mask); +s_int32 mt_op_set_slot_time( + struct test_wlan_info *winfos, + u_int8 slot_time, u_int8 sifs_time, u_int8 rifs_time, + u_int16 eifs_time, u_char band_idx); +s_int32 mt_op_set_power_drop_level( + struct test_wlan_info *winfos, + u_int8 pwr_drop_level, u_char band_idx); +s_int32 mt_op_set_rx_filter_pkt_len( + struct test_wlan_info *winfos, + u_int8 enable, u_char band_idx, u_int32 rx_pkt_len); +s_int32 mt_op_get_antswap_capability( + struct test_wlan_info *winfos, + u_int32 *antswap_support); +s_int32 mt_op_set_antswap( + struct test_wlan_info *winfos, + u_int32 ant); +s_int32 mt_op_set_freq_offset( + struct test_wlan_info *winfos, + u_int32 freq_offset, u_char band_idx); +s_int32 mt_op_set_phy_counter( + struct test_wlan_info *winfos, + s_int32 control, u_char band_idx); +s_int32 mt_op_set_rxv_index( + struct test_wlan_info *winfos, + u_int8 group_1, u_int8 group_2, u_char band_idx); +s_int32 mt_op_set_fagc_path( + struct test_wlan_info *winfos, + u_int8 path, u_char band_idx); +s_int32 mt_op_set_fw_mode( + struct test_wlan_info *winfos, u_char fw_mode); +s_int32 mt_op_set_rf_test_mode( + struct test_wlan_info *winfos, + u_int32 op_mode, u_int8 icap_len, u_int16 rsp_len); +s_int32 mt_op_start_tx( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs); +s_int32 mt_op_stop_tx( + struct test_wlan_info *winfos, + u_char band_idx); +s_int32 mt_op_start_rx( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs); +s_int32 mt_op_stop_rx( + struct test_wlan_info *winfos, + u_char band_idx); +s_int32 mt_op_set_channel( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs); +s_int32 mt_op_set_tx_content( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs); +s_int32 mt_op_set_preamble( + struct test_wlan_info *winfos, + u_char mode); +s_int32 mt_op_set_rate( + struct test_wlan_info *winfos, + u_char mcs); +s_int32 mt_op_set_system_bw( + struct test_wlan_info *winfos, + u_char sys_bw); +s_int32 mt_op_set_per_pkt_bw( + struct test_wlan_info *winfos, + u_char per_pkt_bw); +s_int32 mt_op_reset_txrx_counter( + struct test_wlan_info *winfos); +s_int32 mt_op_set_rx_vector_idx( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 group1, + u_int32 group2); +s_int32 mt_op_set_fagc_rssi_path( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 fagc_path); +s_int32 mt_op_get_rx_stat_leg( + struct test_wlan_info *winfos, + struct test_rx_stat_leg *rx_stat); +s_int32 mt_op_dbdc_tx_tone( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs); +s_int32 mt_op_dbdc_tx_tone_pwr( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs); +s_int32 mt_op_dbdc_continuous_tx( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs); +s_int32 mt_op_get_tx_info( + struct test_wlan_info *winfos, + struct test_configuration *test_configs_band0, + struct test_configuration *test_configs_band1); +s_int32 mt_op_get_rx_statistics_all( + struct test_wlan_info *winfos, + struct hqa_comm_rx_stat *hqa_rx_stat); +s_int32 mt_op_get_capability( + struct test_wlan_info *winfos, + struct test_capability *capability); +s_int32 mt_op_calibration_test_mode( + struct test_wlan_info *winfos, + u_char mode); +s_int32 mt_op_set_icap_start( + struct test_wlan_info *winfos, + u_int8 *data); +s_int32 mt_op_get_icap_status( + struct test_wlan_info *winfos, + s_int32 *icap_stat); +s_int32 mt_op_get_icap_max_data_len( + struct test_wlan_info *winfos, + u_long *max_data_len); +s_int32 mt_op_get_icap_data( + struct test_wlan_info *winfos, + s_int32 *icap_cnt, + s_int32 *icap_data, + u_int32 wf_num, + u_int32 iq_type); +s_int32 mt_op_do_cal_item( + struct test_wlan_info *winfos, + u_int32 item, + u_char band_idx); +s_int32 mt_op_set_band_mode( + struct test_wlan_info *winfos, + struct test_band_state *band_state); +s_int32 mt_op_get_chipid( + struct test_wlan_info *winfos); +s_int32 mt_op_mps_start( + struct test_wlan_info *winfos, + u_char band_idx); +s_int32 mt_op_mps_set_nss( + struct test_wlan_info *winfos, + u_int32 len, + struct test_mps_setting *mps_setting); +s_int32 mt_op_mps_set_per_packet_bw( + struct test_wlan_info *winfos, + u_int32 len, + struct test_mps_setting *mps_setting); +s_int32 mt_op_mps_set_packet_count( + struct test_wlan_info *winfos, + u_int32 len, + struct test_mps_setting *mps_setting); + +s_int32 mt_op_mps_set_payload_length( + struct test_wlan_info *winfos, + u_int32 len, + struct test_mps_setting *mps_setting); +s_int32 mt_op_mps_set_power_gain( + struct test_wlan_info *winfos, + u_int32 len, + struct test_mps_setting *mps_setting); +s_int32 mt_op_mps_set_seq_data( + struct test_wlan_info *winfos, + u_int32 len, + struct test_mps_setting *mps_setting); +s_int32 mt_op_set_muru_manual( + void *virtual_device, + struct test_wlan_info *winfos, + struct test_configuration *configs); +s_int32 mt_op_set_tam_arb( + struct test_wlan_info *winfos, + u_int8 arb_op_mode); + +/* gen4m operation define */ +s_int32 mt_op_set_test_mode_start(struct test_wlan_info *winfos); +s_int32 mt_op_set_test_mode_abort(struct test_wlan_info *winfos); + +/* For test mac usage */ +s_int32 mt_op_backup_and_set_cr( + struct test_wlan_info *winfos, + struct test_bk_cr *bks, + u_char band_idx); +s_int32 mt_op_restore_cr( + struct test_wlan_info *winfos, + struct test_bk_cr *bks, + u_char band_idx); +s_int32 mt_op_set_ampdu_ba_limit( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_int8 agg_limit); +s_int32 mt_op_set_sta_pause_cr( + struct test_wlan_info *winfos); +s_int32 mt_op_set_ifs_cr( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx); +s_int32 mt_op_write_mac_bbp_reg( + struct test_wlan_info *winfos, + struct test_register *regs); +s_int32 mt_op_read_bulk_mac_bbp_reg( + struct test_wlan_info *winfos, + struct test_register *regs); +s_int32 mt_op_read_bulk_rf_reg( + struct test_wlan_info *winfos, + struct test_register *regs); +s_int32 mt_op_write_bulk_rf_reg( + struct test_wlan_info *winfos, + struct test_register *regs); +s_int32 mt_op_read_bulk_eeprom( + struct test_wlan_info *winfos, + struct test_eeprom *eprms); + +/* For test phy usage */ +s_int32 mt_op_get_tx_pwr( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx, + u_char channel, + u_char ant_idx, + u_int32 *power); +s_int32 mt_op_set_tx_pwr( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx, + struct test_txpwr_param *pwr_param); +s_int32 mt_op_set_freq_offset( + struct test_wlan_info *winfos, + u_int32 freq_offset, u_char band_idx); +s_int32 mt_op_get_freq_offset( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 *freq_offset); +s_int32 mt_op_get_cfg_on_off( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 type, + u_int32 *result); +s_int32 mt_op_get_tx_tone_pwr( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 ant_idx, + u_int32 *power); +s_int32 mt_op_get_recal_cnt( + struct test_wlan_info *winfos, + u_int32 *recal_cnt, + u_int32 *recal_dw_num); +s_int32 mt_op_get_recal_content( + struct test_wlan_info *winfos, + u_int32 *content); +s_int32 mt_op_get_rxv_cnt( + struct test_wlan_info *winfos, + u_int32 *rxv_cnt, + u_int32 *rxv_dw_num); +s_int32 mt_op_get_rxv_content( + struct test_wlan_info *winfos, + u_int32 dw_cnt, + u_int32 *content); +s_int32 mt_op_set_cal_bypass( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 cal_item); +s_int32 mt_op_set_dpd( + struct test_wlan_info *winfos, + u_int32 on_off, + u_int32 wf_sel); +s_int32 mt_op_set_tssi( + struct test_wlan_info *winfos, + u_int32 on_off, + u_int32 wf_sel); +s_int32 mt_op_get_thermal_val( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx, + u_int32 *value); +s_int32 mt_op_set_rdd_test( + struct test_wlan_info *winfos, + u_int32 rdd_idx, + u_int32 rdd_sel, + u_int32 enable); +s_int32 mt_op_set_off_ch_scan( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx, + struct test_off_ch_param *off_ch_param); +s_int32 mt_op_get_rdd_cnt( + struct test_wlan_info *winfos, + u_int32 *rdd_cnt, + u_int32 *rdd_dw_num); +s_int32 mt_op_get_rdd_content( + struct test_wlan_info *winfos, + u_int32 *content, + u_int32 *total_cnt); +s_int32 mt_op_hetb_ctrl( + struct test_wlan_info *winfos, + u_char band_idx, + u_char ctrl_type, + u_char enable, + u_int8 bw, + u_int8 ltf_gi, + u_int8 stbc, + u_int8 pri_ru_idx, + struct test_ru_info *ru_info); +s_int32 mt_op_set_ru_aid( + struct test_wlan_info *winfos, + u_char band_idx, + u_int16 mu_rx_aid); +s_int32 mt_op_set_mutb_spe( + struct test_wlan_info *winfos, + u_char band_idx, + u_char tx_mode, + u_int8 spe_idx); +s_int32 mt_op_get_rx_stat_band( + struct test_wlan_info *winfos, + u_int8 band_idx, + u_int8 blk_idx, + struct test_rx_stat_band_info *rx_st_band); +s_int32 mt_op_get_rx_stat_path( + struct test_wlan_info *winfos, + u_int8 band_idx, + u_int8 blk_idx, + struct test_rx_stat_path_info *rx_st_path); +s_int32 mt_op_get_rx_stat_user( + struct test_wlan_info *winfos, + u_int8 band_idx, + u_int8 blk_idx, + struct test_rx_stat_user_info *rx_st_user); +s_int32 mt_op_get_rx_stat_comm( + struct test_wlan_info *winfos, + u_int8 band_idx, + u_int8 blk_idx, + struct test_rx_stat_comm_info *rx_st_comm); +s_int32 mt_op_get_wf_path_comb( + struct test_wlan_info *winfos, + u_int8 band_idx, + boolean dbdc_mode_en, + u_int8 *path, + u_int8 *path_len); +#endif /* __OPERATION_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/hal/include/test_mac.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/hal/include/test_mac.h new file mode 100644 index 0000000000000..b300b8c9e5adc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/hal/include/test_mac.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#ifndef __TEST_MAC_H__ +#define __TEST_MAC_H__ + +#include "net_adaption.h" + +/***************************************************************************** + * Function declaration + *****************************************************************************/ +s_int32 mt_test_mac_backup_and_set_cr( + struct test_wlan_info *winfos, + struct test_bk_cr *bks, + u_char band_idx); +s_int32 mt_test_mac_restore_cr( + struct test_wlan_info *winfos, + struct test_bk_cr *bks, + u_char band_idx); +s_int32 mt_test_mac_set_ampdu_ba_limit( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_int8 agg_limit); +s_int32 mt_test_mac_set_sta_pause_cr( + struct test_wlan_info *winfos); +s_int32 mt_test_mac_set_ifs_cr( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx); + +#endif /* __TEST_MAC_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/hal/jedi/operation_jedi.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/hal/jedi/operation_jedi.c new file mode 100644 index 0000000000000..745a9f6014897 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/hal/jedi/operation_jedi.c @@ -0,0 +1,2185 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#include "rt_config.h" +#include "operation.h" + +s_int32 mt_op_set_tr_mac( + struct test_wlan_info *winfos, + s_int32 op_type, boolean enable, u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; +#ifdef CONFIG_HW_HAL_OFFLOAD + struct _EXT_CMD_ATE_TEST_MODE_T param; +#endif + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + +#ifdef CONFIG_HW_HAL_OFFLOAD + sys_ad_zero_mem(¶m, sizeof(param)); + param.ucAteTestModeEn = 1; + param.ucAteIdx = EXT_ATE_SET_TRX; + param.Data.rAteSetTrx.ucType = op_type; + param.Data.rAteSetTrx.ucEnable = enable; + param.Data.rAteSetTrx.ucBand = band_idx; + /* + * Make sure FW command configuration completed + * for store tx packet in PLE first + * Use aucReserved[1] for ucATEIdx extension feasibility + */ + param.aucReserved[1] = INIT_CMD_SET_AND_WAIT_RETRY_RSP; + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: op_type=%d, enable=%u, band_idx=%u\n", + __func__, op_type, enable, band_idx)); + + ret = MtCmdATETest(ad, ¶m); +#else + ret = MtAsicSetMacTxRx(ad, op_type, enable, band_idx); +#endif + + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_set_tx_stream( + struct test_wlan_info *winfos, + u_int32 stream_nums, u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; +#ifdef CONFIG_HW_HAL_OFFLOAD + struct _EXT_CMD_ATE_TEST_MODE_T param; +#endif + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + +#ifdef CONFIG_HW_HAL_OFFLOAD + sys_ad_zero_mem(¶m, sizeof(param)); + param.ucAteTestModeEn = 1; + param.ucAteIdx = EXT_ATE_SET_TX_STREAM; + param.Data.rAteSetTxStream.ucStreamNum = stream_nums; + param.Data.rAteSetTxStream.ucBand = band_idx; + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: stream_nums=%u, band_idx=%u\n", + __func__, stream_nums, band_idx)); + + ret = MtCmdATETest(ad, ¶m); +#else + ret = MtAsicSetTxStream(ad, stream_nums, band_idx); +#endif + + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_set_tx_path( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + return ret; +} + +s_int32 mt_op_set_rx_path( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + return ret; +} + + +s_int32 mt_op_set_rx_filter( + struct test_wlan_info *winfos, + struct rx_filter_ctrl rx_filter) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; +#ifdef CONFIG_HW_HAL_OFFLOAD + MT_RX_FILTER_CTRL_T filter; + struct _EXT_CMD_ATE_TEST_MODE_T param; +#endif + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + +#ifdef CONFIG_HW_HAL_OFFLOAD + sys_ad_zero_mem(&filter, sizeof(MT_RX_FILTER_CTRL_T)); + sys_ad_move_mem(&filter, &rx_filter, sizeof(MT_RX_FILTER_CTRL_T)); + sys_ad_zero_mem(¶m, sizeof(param)); + param.ucAteTestModeEn = 1; + param.ucAteIdx = EXT_ATE_SET_RX_FILTER; + param.Data.rAteSetRxFilter.ucBand = filter.u1BandIdx; + + if (filter.bPromiscuous) + param.Data.rAteSetRxFilter.ucPromiscuousMode = 1; + else { + param.Data.rAteSetRxFilter.ucReportEn = + (u_char)filter.bFrameReport; + param.Data.rAteSetRxFilter.u4FilterMask = + cpu2le32(filter.filterMask); + } + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: band_idx=%u\n", __func__, filter.u1BandIdx)); + + ret = MtCmdATETest(ad, ¶m); +#else + ret = MtAsicSetRxFilter(ad, filter); +#endif + + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_set_clean_persta_txq( + struct test_wlan_info *winfos, + boolean sta_pause_enable, u_char omac_idx, u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; +#ifdef CONFIG_HW_HAL_OFFLOAD + RTMP_ADAPTER *ad = NULL; + struct _EXT_CMD_ATE_TEST_MODE_T param; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + sys_ad_zero_mem(¶m, sizeof(param)); + param.ucAteTestModeEn = 1; + param.ucAteIdx = EXT_ATE_SET_CLEAN_PERSTA_TXQUEUE; + param.Data.rAteSetCleanPerStaTxQueue.fgStaPauseEnable = + sta_pause_enable; + /* Give a same STA ID */ + param.Data.rAteSetCleanPerStaTxQueue.ucStaID = 0; + param.Data.rAteSetCleanPerStaTxQueue.ucBand = band_idx; + /* use omac index*/ + param.Data.rAteSetCleanPerStaTxQueue.aucReserved[0] = omac_idx; + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: sta_pause_enable=%u, band_idx=%u, reserved[0]=%u\n", + __func__, sta_pause_enable, band_idx, + param.Data.rAteSetCleanPerStaTxQueue.aucReserved[0])); + + ret = MtCmdATETest(ad, ¶m); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; +#else + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: function does't support yet.\n", __func__)); +#endif + + return ret; +} + +s_int32 mt_op_set_cfg_on_off( + struct test_wlan_info *winfos, + u_int8 type, u_int8 enable, u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; +#ifdef CONFIG_HW_HAL_OFFLOAD + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: type=%u, enable=%u, band_idx=%u\n", + __func__, type, enable, band_idx)); + + ret = MtCmdCfgOnOff(ad, type, enable, (u_int8)band_idx); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; +#endif + + return ret; +} + +s_int32 mt_op_log_on_off( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 log_type, + u_int32 log_ctrl, + u_int32 log_size) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + return ret; +} + + +s_int32 mt_op_set_antenna_port( + struct test_wlan_info *winfos, + u_int8 rf_mode_mask, u_int8 rf_port_mask, u_int8 ant_port_mask) +{ + s_int32 ret = SERV_STATUS_SUCCESS; +#ifdef CONFIG_HW_HAL_OFFLOAD + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: rf_mode_mask=%u, rf_port_mask=%u, ant_port_mask=%u\n", + __func__, rf_mode_mask, rf_port_mask, ant_port_mask)); + + ret = MtCmdSetAntennaPort( + ad, rf_mode_mask, rf_port_mask, ant_port_mask); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; +#endif + + return ret; +} + +s_int32 mt_op_set_slot_time( + struct test_wlan_info *winfos, + u_int8 slot_time, u_int8 sifs_time, u_int8 rifs_time, + u_int16 eifs_time, u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ret = MtCmdATESetSlotTime(ad, slot_time, sifs_time, + rifs_time, eifs_time, band_idx); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_set_power_drop_level( + struct test_wlan_info *winfos, + u_int8 pwr_drop_level, u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; +#ifdef CONFIG_HW_HAL_OFFLOAD + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: pwr_drop_level=%u, band_idx=%u\n", + __func__, pwr_drop_level, band_idx)); + + ret = MtCmdATESetPowerDropLevel(ad, pwr_drop_level, band_idx); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; +#endif /* CONFIG_HW_HAL_OFFLOAD */ + + return ret; +} + +s_int32 mt_op_set_rx_filter_pkt_len( + struct test_wlan_info *winfos, + u_int8 enable, u_char band_idx, u_int32 rx_pkt_len) +{ + s_int32 ret = SERV_STATUS_SUCCESS; +#ifdef CONFIG_HW_HAL_OFFLOAD + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: enable=%u, band_idx=%u, rx_pkt_len=%u\n", + __func__, enable, band_idx, rx_pkt_len)); + + ret = MtCmdRxFilterPktLen(ad, enable, band_idx, rx_pkt_len); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; +#endif + + return ret; +} + +s_int32 mt_op_get_antswap_capability( + struct test_wlan_info *winfos, + u_int32 *antswap_support) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + return ret; +} + +s_int32 mt_op_set_antswap( + struct test_wlan_info *winfos, + u_int32 ant) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + return ret; +} + +s_int32 mt_op_set_freq_offset( + struct test_wlan_info *winfos, + u_int32 freq_offset, u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + +#ifdef CONFIG_HW_HAL_OFFLOAD + ret = MtCmdSetFreqOffset(ad, freq_offset, band_idx); +#else + ret = MtAsicSetRfFreqOffset(ad, freq_offset); +#endif + + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_set_phy_counter( + struct test_wlan_info *winfos, + s_int32 control, u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ret = MtCmdSetPhyCounter(ad, control, (u_int8) band_idx); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_set_rxv_index( + struct test_wlan_info *winfos, + u_int8 group_1, u_int8 group_2, u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ret = MtCmdSetRxvIndex(ad, group_1, group_2, (u_int8) band_idx); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_set_fagc_path( + struct test_wlan_info *winfos, + u_int8 path, u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ret = MtCmdSetFAGCPath(ad, path, (u_int8) band_idx); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_set_fw_mode( + struct test_wlan_info *winfos, u_char fw_mode) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ret = MtCmdATEModeCtrl(ad, fw_mode); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_set_rf_test_mode( + struct test_wlan_info *winfos, + u_int32 op_mode, u_int8 icap_len, u_int16 rsp_len) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ret = MtCmdRfTestSwitchMode(ad, op_mode, icap_len, rsp_len); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_set_test_mode_start( + struct test_wlan_info *winfos) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + return ret; +} + +s_int32 mt_op_set_test_mode_abort( + struct test_wlan_info *winfos) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + return ret; +} + +s_int32 mt_op_backup_and_set_cr( + struct test_wlan_info *winfos, + struct test_bk_cr *bks, + u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + ret = mt_test_mac_backup_and_set_cr(winfos, bks, band_idx); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SET_MAC; + + return ret; +} + +s_int32 mt_op_restore_cr( + struct test_wlan_info *winfos, + struct test_bk_cr *bks, + u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + ret = mt_test_mac_restore_cr(winfos, bks, band_idx); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SET_MAC; + + return ret; +} + +s_int32 mt_op_set_ampdu_ba_limit( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_int8 agg_limit) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + ret = mt_test_mac_set_ampdu_ba_limit(winfos, configs, agg_limit); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SET_MAC; + + return ret; +} + +s_int32 mt_op_set_sta_pause_cr( + struct test_wlan_info *winfos) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + ret = mt_test_mac_set_sta_pause_cr(winfos); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SET_MAC; + + return ret; +} + +s_int32 mt_op_set_ifs_cr( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + ret = mt_test_mac_set_ifs_cr(winfos, configs, band_idx); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SET_MAC; + + return ret; +} + +s_int32 mt_op_write_mac_bbp_reg( + struct test_wlan_info *winfos, + struct test_register *regs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + return ret; +} + +s_int32 mt_op_read_bulk_mac_bbp_reg( + struct test_wlan_info *winfos, + struct test_register *regs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + return ret; +} + +s_int32 mt_op_read_bulk_rf_reg( + struct test_wlan_info *winfos, + struct test_register *regs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + return ret; +} + +s_int32 mt_op_write_bulk_rf_reg( + struct test_wlan_info *winfos, + struct test_register *regs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + return ret; +} + +s_int32 mt_op_read_bulk_eeprom( + struct test_wlan_info *winfos, + struct test_eeprom *eprms) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + return ret; +} + +s_int32 mt_op_start_tx( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + return ret; +} + +s_int32 mt_op_stop_tx( + struct test_wlan_info *winfos, + u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + return ret; +} + +s_int32 mt_op_start_rx( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + return ret; +} + +s_int32 mt_op_stop_rx( + struct test_wlan_info *winfos, + u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + return ret; +} + +s_int32 mt_op_set_channel( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + ret = net_ad_update_wdev(band_idx, winfos, configs); + if (ret) + goto error; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: band_idx: %d, bw: %d, ch:%d", + __func__, band_idx, configs->bw, configs->channel)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("ctrl_ch: %d, cntl_ch2: %d, pri_sel: %d\n", + configs->ctrl_ch, configs->channel_2nd, configs->pri_sel)); + + return ret; + +error: + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: set channel fail, ", __func__)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("control channel: %d|%d\n", configs->ctrl_ch, + configs->channel)); + return SERV_STATUS_OSAL_NET_FAIL_SET_CHANNEL; +} + +s_int32 mt_op_set_tx_content( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + return ret; +} + +s_int32 mt_op_set_preamble( + struct test_wlan_info *winfos, + u_char mode) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + return ret; +} + +s_int32 mt_op_set_rate( + struct test_wlan_info *winfos, + u_char mcs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + return ret; +} + +s_int32 mt_op_set_system_bw( + struct test_wlan_info *winfos, + u_char sys_bw) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + return ret; +} + +s_int32 mt_op_set_per_pkt_bw( + struct test_wlan_info *winfos, + u_char per_pkt_bw) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + return ret; +} + +s_int32 mt_op_reset_txrx_counter( + struct test_wlan_info *winfos) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + RX_STATISTIC_RXV *rx_stat; + u_int32 control = 0, user_idx = 0, band_idx = 0; + struct _RTMP_CHIP_DBG *chip_dbg = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: reset txrx counter\n", __func__)); + + chip_dbg = hc_get_chip_dbg(ad->hdev_ctrl); + + for (band_idx = TEST_DBDC_BAND0; + band_idx < TEST_DBDC_BAND_NUM; band_idx++) { + control = 0; + ret = MtCmdSetPhyCounter(ad, control, band_idx); + if (ret) + goto error; + + control = 1; + ret = MtCmdSetPhyCounter(ad, control, band_idx); + if (ret) + goto error; + + /* reset rx stat fcs error count */ + rx_stat = ad->rx_stat_rxv + band_idx; + for (user_idx = 0; user_idx < TEST_USER_NUM; user_idx++) { + rx_stat->fcs_error_cnt[user_idx] = 0; + rx_stat->FreqOffsetFromRx[user_idx] = 0; + rx_stat->SNR[user_idx] = 0; + } + + if (chip_dbg) { + chip_dbg->get_tx_mibinfo(ad, band_idx, + MODE_CCK, + BW_20); + chip_dbg->get_tx_mibinfo(ad, band_idx, + MODE_CCK, + BW_40); + chip_dbg->get_tx_mibinfo(ad, band_idx, + MODE_CCK, + BW_80); + chip_dbg->get_tx_mibinfo(ad, band_idx, + MODE_CCK, + BW_160); + chip_dbg->get_tx_mibinfo(ad, band_idx, + MODE_HE_MU, + BW_20); + } + } + + return ret; + +error: + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: reset tx rx phy counter fail(0x%08x).\n", __func__, ret)); + return ret; +} + +s_int32 mt_op_set_rx_vector_idx( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 group1, + u_int32 group2) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + return ret; +} + +s_int32 mt_op_set_fagc_rssi_path( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 fagc_path) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + return ret; +} + +s_int32 mt_op_get_rx_stat_leg( + struct test_wlan_info *winfos, + struct test_rx_stat_leg *rx_stat) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + TESTMODE_STATISTIC_INFO st; + RX_STATISTIC_RXV *rx_stat_rxv; + u_char band_idx, band_num, user_idx; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + if (IS_TEST_DBDC(winfos)) { + band_num = 2; + rx_stat_rxv = ad->rx_stat_rxv + 0; + rx_stat->fagc_ib_rssi[0] = rx_stat_rxv->FAGC_RSSI_IB[0]; + rx_stat->fagc_ib_rssi[1] = rx_stat_rxv->FAGC_RSSI_IB[1]; + rx_stat->fagc_wb_rssi[0] = rx_stat_rxv->FAGC_RSSI_WB[0]; + rx_stat->fagc_wb_rssi[1] = rx_stat_rxv->FAGC_RSSI_WB[1]; + rx_stat->rcpi0 = rx_stat_rxv->RCPI[0]; + rx_stat->rcpi1 = rx_stat_rxv->RCPI[1]; + rx_stat->rssi0 = rx_stat_rxv->RSSI[0]; + rx_stat->rssi1 = rx_stat_rxv->RSSI[1]; + + rx_stat_rxv = &ad->rx_stat_rxv + 1; + rx_stat->fagc_ib_rssi[2] = rx_stat_rxv->FAGC_RSSI_IB[0]; + rx_stat->fagc_ib_rssi[3] = rx_stat_rxv->FAGC_RSSI_IB[1]; + rx_stat->fagc_wb_rssi[2] = rx_stat_rxv->FAGC_RSSI_WB[0]; + rx_stat->fagc_wb_rssi[3] = rx_stat_rxv->FAGC_RSSI_WB[1]; + rx_stat->rcpi2 = rx_stat_rxv->RCPI[0]; + rx_stat->rcpi3 = rx_stat_rxv->RCPI[1]; + rx_stat->rssi2 = rx_stat_rxv->RSSI[0]; + rx_stat->rssi3 = rx_stat_rxv->RSSI[1]; + } else { + band_num = 1; + rx_stat_rxv = ad->rx_stat_rxv + 0; + rx_stat->fagc_ib_rssi[0] = rx_stat_rxv->FAGC_RSSI_IB[0]; + rx_stat->fagc_ib_rssi[1] = rx_stat_rxv->FAGC_RSSI_IB[1]; + rx_stat->fagc_ib_rssi[2] = rx_stat_rxv->FAGC_RSSI_IB[2]; + rx_stat->fagc_ib_rssi[3] = rx_stat_rxv->FAGC_RSSI_IB[3]; + rx_stat->fagc_wb_rssi[0] = rx_stat_rxv->FAGC_RSSI_WB[0]; + rx_stat->fagc_wb_rssi[1] = rx_stat_rxv->FAGC_RSSI_WB[1]; + rx_stat->fagc_wb_rssi[2] = rx_stat_rxv->FAGC_RSSI_WB[2]; + rx_stat->fagc_wb_rssi[3] = rx_stat_rxv->FAGC_RSSI_WB[3]; + rx_stat->rcpi0 = rx_stat_rxv->RCPI[0]; + rx_stat->rcpi1 = rx_stat_rxv->RCPI[1]; + rx_stat->rcpi2 = rx_stat_rxv->RCPI[2]; + rx_stat->rcpi3 = rx_stat_rxv->RCPI[3]; + rx_stat->rssi0 = rx_stat_rxv->RSSI[0]; + rx_stat->rssi1 = rx_stat_rxv->RSSI[1]; + rx_stat->rssi2 = rx_stat_rxv->RSSI[2]; + rx_stat->rssi3 = rx_stat_rxv->RSSI[3]; + } + + for (band_idx = 0; band_idx < band_num; band_idx++) { + /* read statistic from firmware */ + chip_get_rx_stat(ad, band_idx, &st); + + /* Copy statistic info */ + switch (band_idx) { + case 0: + /* MAC COUNT */ + rx_stat->mac_rx_fcs_ok_cnt = + st.mac_rx_fcs_ok_cnt; + rx_stat->mac_rx_fcs_err_cnt = + st.mac_rx_fcs_err_cnt; + rx_stat->mac_rx_len_mismatch = + st.mac_rx_len_mismatch; + rx_stat->rx_fifo_full = + st.mac_rx_fifo_full; + rx_stat->mac_rx_mdrdy_cnt = + st.mac_rx_mdrdy_cnt; + + /* PHY COUNT */ + rx_stat->phy_rx_pd_cck = + st.phy_rx_pd_cck; + rx_stat->phy_rx_pd_ofdm = + st.phy_rx_pd_ofdm; + rx_stat->phy_rx_sig_err_cck = + st.phy_rx_sig_err_cck; + rx_stat->phy_rx_sfd_err_cck = + st.phy_rx_sfd_err_cck; + rx_stat->phy_rx_sig_err_ofdm = + st.phy_rx_sig_err_ofdm; + rx_stat->phy_rx_tag_err_ofdm = + st.phy_rx_tag_err_ofdm; + rx_stat->phy_rx_mdrdy_cnt_cck = + st.phy_rx_mdrdy_cnt_cck; + rx_stat->phy_rx_mdrdy_cnt_ofdm = + st.phy_rx_mdrdy_cnt_ofdm; + rx_stat->phy_rx_fcs_err_cnt_cck = + st.phy_rx_fcs_err_cnt_cck; + rx_stat->phy_rx_fcs_err_cnt_ofdm = + st.phy_rx_fcs_err_cnt_ofdm; + break; + + case 1: + /* MAC COUNT */ + rx_stat->mac_rx_fcs_err_cnt_band1 = + st.mac_rx_fcs_err_cnt; + rx_stat->mac_rx_len_mismatch_band1 = + st.mac_rx_len_mismatch; + rx_stat->rx_fifo_full_band1 = + st.mac_rx_fifo_full; + rx_stat->mac_rx_mdrdy_cnt_band1 = + st.mac_rx_mdrdy_cnt; + + /* PHY COUNT */ + rx_stat->phy_rx_pd_cck_band1 = + st.phy_rx_pd_cck; + rx_stat->phy_rx_pd_ofdm_band1 = + st.phy_rx_pd_ofdm; + rx_stat->phy_rx_sig_err_cck_band1 = + st.phy_rx_sig_err_cck; + rx_stat->phy_rx_sfd_err_cck_band1 = + st.phy_rx_sfd_err_cck; + rx_stat->phy_rx_sig_err_ofdm_band1 = + st.phy_rx_sig_err_ofdm; + rx_stat->phy_rx_tag_err_ofdm_band1 = + st.phy_rx_tag_err_ofdm; + rx_stat->phy_rx_mdrdy_cnt_cck_band1 = + st.phy_rx_mdrdy_cnt_cck; + rx_stat->phy_rx_mdrdy_cnt_ofdm_band1 = + st.phy_rx_mdrdy_cnt_ofdm; + break; + + default: + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + } + } + + rx_stat->freq_offset_rx = + rx_stat_rxv->FreqOffsetFromRx[0]; + + for (user_idx = 0; user_idx < TEST_USER_NUM; user_idx++) { + rx_stat->user_rx_freq_offset[user_idx] = + rx_stat_rxv->FreqOffsetFromRx[user_idx]; + rx_stat->user_snr[user_idx] = + (u_int32)rx_stat_rxv->SNR[user_idx]; + rx_stat->fcs_error_cnt[user_idx] = + rx_stat_rxv->fcs_error_cnt[user_idx]; + } + + return ret; +} + +s_int32 mt_op_dbdc_tx_tone( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + u_int8 tx_tone_en = 0, ant_idx = 0, tone_type = 0; + u_int8 tone_freq = 0; + s_int32 dc_offset_I = 0, dc_offset_Q = 0, ch_band = 0; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + tx_tone_en = (u_int8) configs->tx_tone_en; + ant_idx = (u_int8) configs->ant_idx; + tone_type = (u_int8) configs->tone_type; + tone_freq = (u_int8) configs->tone_freq; + dc_offset_I = (s_int32) configs->dc_offset_I; + dc_offset_Q = (s_int32) configs->dc_offset_Q; + ch_band = (s_int32) configs->ch_band; + + ret = MtCmdTxTone(ad, band_idx, tx_tone_en, + ant_idx, tone_type, tone_freq, + dc_offset_I, dc_offset_Q, ch_band); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_dbdc_tx_tone_pwr( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + u_int8 ant_idx = 0; + u_int32 digi_pwr = 0; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ant_idx = (u_int8) configs->ant_idx; + digi_pwr = configs->digi_pwr; + + ret = MtCmdTxTonePower(ad, 0x12, digi_pwr, ant_idx, band_idx); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_dbdc_continuous_tx( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + u_int8 tx_tone_en = 0; + u_int32 ant_mask = 0, tx_mode = 0, bw = 0; + u_int32 pri_sel = 0, rate = 0, channel = 0; + u_int32 tx_fd_mode = 0; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + tx_tone_en = configs->tx_tone_en; + ant_mask = configs->ant_mask; + tx_mode = configs->tx_mode; + bw = configs->bw; + pri_sel = configs->pri_sel; + rate = configs->rate; + channel = configs->channel; + tx_fd_mode = configs->tx_fd_mode; + + ret = MtCmdTxContinous(ad, tx_mode, bw, + pri_sel, channel, rate, ant_mask, + tx_fd_mode, band_idx, tx_tone_en); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_get_tx_info( + struct test_wlan_info *winfos, + struct test_configuration *test_configs_band0, + struct test_configuration *test_configs_band1) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_int32 mib_counter = 0; + RTMP_ADAPTER *ad = NULL; + struct _RTMP_CHIP_DBG *chip_dbg = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + chip_dbg = hc_get_chip_dbg(ad->hdev_ctrl); + + if (chip_dbg) { + mib_counter = chip_dbg->get_tx_mibinfo(ad, BAND0, + test_configs_band0->tx_mode, + test_configs_band0->per_pkt_bw); + + test_configs_band0->tx_stat.tx_done_cnt += mib_counter; + + mib_counter = chip_dbg->get_tx_mibinfo(ad, BAND1, + test_configs_band1->tx_mode, + test_configs_band1->per_pkt_bw); + + test_configs_band1->tx_stat.tx_done_cnt += mib_counter; + } else + ret = SERV_STATUS_HAL_OP_FAIL; + + return ret; +} + +s_int32 mt_op_get_rx_statistics_all( + struct test_wlan_info *winfos, + struct hqa_comm_rx_stat *hqa_rx_stat) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + return ret; +} + +s_int32 mt_op_get_capability( + struct test_wlan_info *winfos, + struct test_capability *capability) +{ + s_int32 ret = SERV_STATUS_SERV_TEST_NOT_SUPPORTED; + + return ret; +} + +s_int32 mt_op_calibration_test_mode( + struct test_wlan_info *winfos, + u_char mode) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + u_int8 icap_len = 0; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ret = MtCmdRfTestSwitchMode(ad, mode, + icap_len, RF_TEST_DEFAULT_RESP_LEN); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_set_icap_start( + struct test_wlan_info *winfos, + u_int8 *data) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + RTMP_CHIP_OP *ops = NULL; +#ifdef INTERNAL_CAPTURE_SUPPORT + RBIST_CAP_START_T *prICapInfo = (RBIST_CAP_START_T *)data; +#endif/* INTERNAL_CAPTURE_SUPPORT */ + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ops = hc_get_chip_ops(ad->hdev_ctrl); + +#ifdef INTERNAL_CAPTURE_SUPPORT + if (ops->ICapStart != NULL) + ret = ops->ICapStart(ad, (u_int8 *)prICapInfo); + else { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s : The function is not hooked !!\n", __func__)); + } +#endif/* INTERNAL_CAPTURE_SUPPORT */ + + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_get_icap_status( + struct test_wlan_info *winfos, + s_int32 *icap_stat) +{ + RTMP_ADAPTER *ad = NULL; + RTMP_CHIP_OP *ops = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ops = hc_get_chip_ops(ad->hdev_ctrl); + +#ifdef INTERNAL_CAPTURE_SUPPORT + if (ops->ICapStatus != NULL) + *icap_stat = ops->ICapStatus(ad); + else { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s : The function is not hooked !!\n", __func__)); + return SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + } +#endif/* INTERNAL_CAPTURE_SUPPORT */ + + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_get_icap_max_data_len( + struct test_wlan_info *winfos, + u_long *max_data_len) +{ + *max_data_len = (ICAP_EVENT_DATA_SAMPLE * sizeof(INT32)); + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_get_icap_data( + struct test_wlan_info *winfos, + s_int32 *icap_cnt, + s_int32 *icap_data, + u_int32 wf_num, + u_int32 iq_type) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + RTMP_CHIP_OP *ops = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ops = hc_get_chip_ops(ad->hdev_ctrl); + +#ifdef INTERNAL_CAPTURE_SUPPORT + if (ops->ICapGetIQData != NULL) + ret = ops->ICapGetIQData(ad + , icap_data, icap_cnt, iq_type, wf_num); + else if (ops->ICapCmdSolicitRawDataProc != NULL) + ret = ops->ICapCmdSolicitRawDataProc(ad + , icap_data, icap_cnt, iq_type, wf_num); + else { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s : The function is not hooked !!\n", __func__)); + } +#endif/* INTERNAL_CAPTURE_SUPPORT */ + + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_do_cal_item( + struct test_wlan_info *winfos, + u_int32 item, + u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ret = MtCmdDoCalibration(ad, 0x1, item, band_idx); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_set_band_mode( + struct test_wlan_info *winfos, + struct test_band_state *band_state) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + return ret; +} + +s_int32 mt_op_get_chipid( + struct test_wlan_info *winfos) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + return ret; +} + +s_int32 mt_op_mps_start( + struct test_wlan_info *winfos, + u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + return ret; +} + +s_int32 mt_op_mps_set_nss( + struct test_wlan_info *winfos, + u_int32 len, + struct test_mps_setting *mps_setting) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + return ret; +} + +s_int32 mt_op_mps_set_per_packet_bw( + struct test_wlan_info *winfos, + u_int32 len, + struct test_mps_setting *mps_setting) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + return ret; +} + +s_int32 mt_op_mps_set_packet_count( + struct test_wlan_info *winfos, + u_int32 len, + struct test_mps_setting *mps_setting) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + return ret; +} + +s_int32 mt_op_mps_set_payload_length( + struct test_wlan_info *winfos, + u_int32 len, + struct test_mps_setting *mps_setting) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + return ret; +} + +s_int32 mt_op_mps_set_power_gain( + struct test_wlan_info *winfos, + u_int32 len, + struct test_mps_setting *mps_setting) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + return ret; +} + +s_int32 mt_op_mps_set_seq_data( + struct test_wlan_info *winfos, + u_int32 len, + struct test_mps_setting *mps_setting) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + return ret; +} + +s_int32 mt_op_get_tx_pwr( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx, + u_char channel, + u_char ant_idx, + u_int32 *power) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + EXT_EVENT_ID_GET_TX_POWER_T txpwr_result; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ret = MtCmdGetTxPower(ad, band_idx, channel, ant_idx, &txpwr_result); + *power = (u_int32)txpwr_result.i1TargetPower; + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_set_tx_pwr( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx, + struct test_txpwr_param *pwr_param) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + struct test_txpwr_cfg txpwr_cfg; + ATE_TXPOWER txpwr; + + /* sanity check for null pointer */ + if (!pwr_param) + return SERV_STATUS_HAL_OP_INVALID_NULL_POINTER; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + txpwr_cfg.ant_idx = pwr_param->ant_idx; + txpwr_cfg.txpwr = configs->tx_pwr[pwr_param->ant_idx]; + txpwr_cfg.channel = configs->channel; + txpwr_cfg.band_idx = band_idx; + txpwr_cfg.ch_band = configs->ch_band; + + sys_ad_zero_mem(&txpwr, sizeof(ATE_TXPOWER)); + sys_ad_move_mem(&txpwr, &txpwr_cfg, sizeof(ATE_TXPOWER)); + ret = MtCmdSetTxPowerCtrl(ad, txpwr); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_get_freq_offset( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 *freq_offset) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ret = MtCmdGetFreqOffset(ad, band_idx, freq_offset); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_get_cfg_on_off( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 type, + u_int32 *result) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ret = MtCmdGetCfgOnOff(ad, type, band_idx, result); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_get_tx_tone_pwr( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 ant_idx, + u_int32 *power) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ret = MtCmdRfTestGetTxTonePower(ad, power, ant_idx, band_idx); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_get_recal_cnt( + struct test_wlan_info *winfos, + u_int32 *recal_cnt, + u_int32 *recal_dw_num) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_get_recal_content( + struct test_wlan_info *winfos, + u_int32 *content) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_get_rxv_cnt( + struct test_wlan_info *winfos, + u_int32 *rxv_cnt, + u_int32 *rxv_dw_num) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_get_rxv_content( + struct test_wlan_info *winfos, + u_int32 dw_cnt, + u_int32 *content) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_set_cal_bypass( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 cal_item) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ret = MtCmdDoCalibration(ad, CALIBRATION_BYPASS, cal_item, band_idx); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_set_dpd( + struct test_wlan_info *winfos, + u_int32 on_off, + u_int32 wf_sel) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ret = MtAsicSetDPD(ad, on_off, wf_sel); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_set_tssi( + struct test_wlan_info *winfos, + u_int32 on_off, + u_int32 wf_sel) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ret = MtAsicSetTSSI(ad, on_off, wf_sel); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_get_thermal_val( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx, + u_int32 *value) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + /* 0: get temperature; 1: get adc */ + ret = MtCmdGetThermalSensorResult(ad, 0, + band_idx, value); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_set_rdd_test( + struct test_wlan_info *winfos, + u_int32 rdd_idx, + u_int32 rdd_sel, + u_int32 enable) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: rdd_idx: %d, rdd_sel: %d, enable:%d\n", + __func__, rdd_idx, rdd_sel, enable)); + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ret = MtCmdSetRDDTestExt(ad, rdd_idx, rdd_sel, enable); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_set_off_ch_scan( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx, + struct test_off_ch_param *param) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + EXT_CMD_OFF_CH_SCAN_CTRL_T ext_cmd_param; + u_char ch = 0; + u_char work_tx_strm_pth = 0, work_rx_strm_pth = 0, off_ch_idx = 0; + u_char ch_ext_index = 0; + u_char ch_ext_above[] = { + 36, 44, 52, 60, + 100, 108, 116, 124, + 132, 140, 149, 157, 0 + }; + u_char ch_ext_below[] = { + 40, 48, 56, 64, + 104, 112, 120, 128, + 136, 144, 153, 161, 0 + }; + u_char prim_ch[off_ch_ch_idx_num] = {0, 0}; + u_char bw[off_ch_ch_idx_num] = {0, 0}; + u_char cen_ch[off_ch_ch_idx_num] = {0, 0}; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s ", __func__)); + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + work_tx_strm_pth = configs->tx_ant; + work_rx_strm_pth = configs->rx_strm_pth; + prim_ch[off_ch_wrk_ch_idx] = configs->channel; + bw[off_ch_wrk_ch_idx] = configs->bw; + prim_ch[off_ch_mntr_ch_idx] = param->mntr_ch; + bw[off_ch_mntr_ch_idx] = param->mntr_bw; + + for (off_ch_idx = 0; off_ch_idx < off_ch_ch_idx_num; off_ch_idx++) { + ch = prim_ch[off_ch_idx]; + + /* Initialize index */ + ch_ext_index = 0; + + switch (bw[off_ch_idx]) { + case TEST_BW_20: + break; + + case TEST_BW_40: + while (ch_ext_above[ch_ext_index] != 0) { + if (ch == ch_ext_above[ch_ext_index]) + ch = ch + 2; + else if (ch == ch_ext_below[ch_ext_index]) + ch = ch - 2; + + ch_ext_index++; + } + break; + + case TEST_BW_80: + case TEST_BW_160NC: + ch = vht_cent_ch_freq(ch, VHT_BW_80); + break; + + case TEST_BW_160C: + ch = vht_cent_ch_freq(ch, VHT_BW_160); + break; + + default: + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: off_ch_idx %d, BW is invalid %d\n", + __func__, off_ch_idx, bw[off_ch_idx])); + ret = NDIS_STATUS_FAILURE; + goto err0; + } + + cen_ch[off_ch_idx] = ch; + } + + /* Initialize */ + sys_ad_zero_mem(&ext_cmd_param, sizeof(ext_cmd_param)); + + /* Fill in ext_cmd_param */ + ext_cmd_param.mntr_prim_ch = param->mntr_ch; + ext_cmd_param.mntr_cntrl_ch = cen_ch[off_ch_mntr_ch_idx]; + ext_cmd_param.mntr_bw = bw[off_ch_mntr_ch_idx]; + ext_cmd_param.mntr_tx_strm_pth = param->mntr_tx_rx_pth; + ext_cmd_param.mntr_rx_strm_pth = param->mntr_tx_rx_pth; + + ext_cmd_param.work_prim_ch = prim_ch[off_ch_wrk_ch_idx]; + ext_cmd_param.work_cntrl_ch = cen_ch[off_ch_wrk_ch_idx]; + ext_cmd_param.work_bw = bw[off_ch_wrk_ch_idx]; + ext_cmd_param.work_tx_strm_pth = work_tx_strm_pth; + ext_cmd_param.work_rx_strm_pth = work_rx_strm_pth; + + ext_cmd_param.dbdc_idx = param->dbdc_idx; + ext_cmd_param.scan_mode = param->scan_mode; + ext_cmd_param.is_aband = param->is_aband; + ext_cmd_param.off_ch_scn_type = off_ch_scan_simple_rx; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: mntr_ch:%d mntr_bw:%d mntr_central_ch:%d\n", + __func__, ext_cmd_param.mntr_prim_ch, + ext_cmd_param.mntr_bw, ext_cmd_param.mntr_cntrl_ch)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: work_prim_ch:%d work_bw:%d work_central_ch:%d\n", + __func__, ext_cmd_param.work_prim_ch, + ext_cmd_param.work_bw, ext_cmd_param.work_cntrl_ch)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: scan_mode:%d dbdc_idx:%d is_aband:%d\n", + __func__, ext_cmd_param.scan_mode, + ext_cmd_param.dbdc_idx, ext_cmd_param.is_aband)); + + ret = mt_cmd_off_ch_scan(ad, &ext_cmd_param); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; + +err0: + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: invalid parameters\n", __func__)); + return ret; +} + +s_int32 mt_op_get_rdd_cnt( + struct test_wlan_info *winfos, + u_int32 *rdd_cnt, + u_int32 *rdd_dw_num) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + /* refactor after log onoff feature ready */ + struct _ATE_CTRL *ATECtrl = NULL; + struct _ATE_LOG_DUMP_CB *log_cb = NULL; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s:\n", __func__)); + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ATECtrl = &(ad->ATECtrl); + log_cb = &(ATECtrl->log_dump[ATE_LOG_RDD-1]); + + /* radar pulse number */ + *rdd_cnt = log_cb->idx; + /* RDD buffer size */ + *rdd_dw_num = log_cb->len; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: radar pulse number is %d, RDD buffer size is %d\n", + __func__, log_cb->idx, log_cb->len)); + + return ret; +} + + +s_int32 mt_op_get_rdd_content( + struct test_wlan_info *winfos, + u_int32 *content, + u_int32 *total_cnt) +{ + static u_int32 idx; + s_int32 ret = SERV_STATUS_SUCCESS; + u_int32 end = 0, remindIdx = 0; + RTMP_ADAPTER *ad = NULL; + struct _ATE_CTRL *ATECtrl = NULL; + struct _ATE_LOG_DUMP_CB *log_cb = NULL; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s:\n", __func__)); + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ATECtrl = &(ad->ATECtrl); + log_cb = &(ATECtrl->log_dump[ATE_LOG_RDD-1]); + + if (log_cb == NULL) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: log_cb == NULL\n", __func__)); + return SERV_STATUS_HAL_OP_INVALID_PAD; + } + + /* Prepare for RDD dump */ + /* refactor after log onoff feature ready */ + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("[RDD DUMP START][HQA_GetDumpRDD]\n")); + ad->fgDumpStart = 1; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: radar pulse number is %d, RDD buffer size is %d\n", + __func__, log_cb->idx, log_cb->len)); + + if ((ATECtrl->firstRDD == TRUE) || (ATECtrl->firstQATool == TRUE)) { + /* + * Reset idx - 1. HQA RDD dump (re-)enable + * Reset idx - 2. HQA Tool (re-)open + */ + idx = 0; + } + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, ("idx: %d\n", idx)); + /* If log_cb->idx greater than log_cb->len(RDDBufferSize), + * it will re-count from 0 + */ + remindIdx = (idx > log_cb->idx) ? + ((log_cb->idx + log_cb->len) - idx) : + (log_cb->idx - idx); + + end = (remindIdx > MAX_RDD_DUMP_SIZE) ? + ((idx + MAX_RDD_DUMP_SIZE) % (log_cb->len)) : + ((idx + remindIdx) % (log_cb->len)); + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("remindIdx: %d, end: %d\n", remindIdx, end)); + + /* log on/off is not ready */ + + return ret; +} + + +s_int32 mt_op_set_muru_manual( + void *virtual_device, + struct test_wlan_info *winfos, + struct test_configuration *configs) +{ +#if defined(CFG_SUPPORT_FALCON_MURU) + RTMP_ADAPTER *ad = NULL; + u_int8 ru_seq = 0, wmm_idx = 0; + CMD_MURU_MANCFG_INTERFACER MuruManCfg; + struct _MAC_TABLE_ENTRY *mac_tbl_entry = NULL; + struct test_tx_stack *stack = &configs->stack; + struct test_ru_info *ru_info = &configs->ru_info_list[0]; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + mac_tbl_entry = (struct _MAC_TABLE_ENTRY *)stack->virtual_wtbl[0]; + + sys_ad_zero_mem(&MuruManCfg, sizeof(MuruManCfg)); + + MuruManCfg.rCfgCmm.u1PpduFmt = MURU_PPDU_HE_MU; + MuruManCfg.u4ManCfgBmpCmm = MURU_FIXED_CMM_PPDU_FMT; + net_ad_get_band_idx(virtual_device, &MuruManCfg.rCfgCmm.u1Band); + MuruManCfg.u4ManCfgBmpCmm |= MURU_FIXED_CMM_BAND; + net_ad_get_wmm_idx(virtual_device, &wmm_idx); + MuruManCfg.rCfgCmm.u1WmmSet = wmm_idx; + MuruManCfg.u4ManCfgBmpCmm |= MURU_FIXED_CMM_WMM_SET; + if (configs->per_pkt_bw > TEST_BW_80) + MuruManCfg.rCfgDl.u1Bw = 0x3; /* 0x3 imply 80+80/160 */ + else + MuruManCfg.rCfgDl.u1Bw = configs->per_pkt_bw; + MuruManCfg.u4ManCfgBmpDl |= MURU_FIXED_BW; + MuruManCfg.rCfgDl.u1SigBMcs = (configs->mcs & 0xf); + MuruManCfg.u4ManCfgBmpDl |= MURU_FIXED_SIGB_MCS; + MuruManCfg.rCfgDl.u1SigBDcm = ((configs->mcs & BIT5) ? 0x1 : 0); + MuruManCfg.u4ManCfgBmpDl |= MURU_FIXED_SIGB_DCM; + MuruManCfg.rCfgDl.u1TxMode = configs->tx_mode; + MuruManCfg.u4ManCfgBmpDl |= MURU_FIXED_TX_MODE; + MuruManCfg.rCfgDl.u1UserCnt = stack->index; + MuruManCfg.u4ManCfgBmpDl |= MURU_FIXED_TOTAL_USER_CNT; + sys_ad_move_mem(&MuruManCfg.rCfgDl.au1RU, + &configs->ru_alloc, + sizeof(configs->ru_alloc)); + MuruManCfg.u4ManCfgBmpDl |= MURU_FIXED_TONE_PLAN; + MuruManCfg.rCfgDl.u1GI = configs->stack.tx_info[0].gi; + MuruManCfg.rCfgDl.u1Ltf = configs->stack.tx_info[0].ltf; + MuruManCfg.u4ManCfgBmpDl |= (MURU_FIXED_GI | MURU_FIXED_LTF); + for (ru_seq = 0 ; ru_seq < MAX_MULTI_TX_STA ; ru_seq++) { + u_int8 seg = 0, alloc = 0; + MURU_DL_USER_INFO *user_info = NULL; + struct phy_params *phy_param = NULL; + + if (ru_info[ru_seq].valid) { + user_info = &MuruManCfg.rCfgDl.arUserInfoDl[ru_seq]; + seg = (ru_info[ru_seq].ru_index & 0x1); + alloc = (ru_info[ru_seq].ru_index >> 1); + phy_param = &mac_tbl_entry[ru_seq].phy_param; + + user_info->u2WlanIdx = mac_tbl_entry[ru_seq].wcid; + user_info->u1RuAllocBn = seg; + user_info->u1RuAllocIdx = alloc; + user_info->u1Mcs = (phy_param->rate & 0xf); + + if (phy_param->rate & BIT5) /* DCM required */ + user_info->u1Mcs |= BIT4; + + user_info->u1Nss = phy_param->vht_nss-1; + user_info->u1Ldpc = phy_param->ldpc; + + if ((ru_info[ru_seq].ru_index >> 1) == 18) { + u_int8 *au1C26 = NULL; + + au1C26 = MuruManCfg.rCfgDl.au1C26; + au1C26[(ru_info[ru_seq].ru_index & 1)] = 1; + } + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: Add user[%d] wcid:%d, ru index:%d,\n", + __func__, ru_seq, user_info->u2WlanIdx, + user_info->u1RuAllocIdx)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("\t\tsegment:%d, mcs:%d\n", + user_info->u1RuAllocBn, + user_info->u1Mcs)); + } + } + MuruManCfg.u4ManCfgBmpDl |= MURU_FIXED_USER_WLAN_ID; + MuruManCfg.u4ManCfgBmpDl |= MURU_FIXED_USER_COD; + MuruManCfg.u4ManCfgBmpDl |= MURU_FIXED_USER_MCS; + MuruManCfg.u4ManCfgBmpDl |= MURU_FIXED_USER_NSS; + MuruManCfg.u4ManCfgBmpDl |= MURU_FIXED_USER_RU_ALLOC; + + wifi_test_muru_set_manual_config(ad, &MuruManCfg); +#endif /* CFG_SUPPORT_FALCON_MURU */ + + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_set_tam_arb( + struct test_wlan_info *winfos, + u_int8 arb_op_mode) +{ +#if defined(CFG_SUPPORT_FALCON_MURU) + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + wifi_test_muru_set_arb_op_mode(ad, arb_op_mode); +#endif /* CFG_SUPPORT_FALCON_MURU */ + + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_op_get_rx_stat_band( + struct test_wlan_info *winfos, + u_int8 band_idx, + u_int8 blk_idx, + struct test_rx_stat_band_info *rx_st_band) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + TEST_RX_STAT_BAND_INFO st; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ret = chip_get_rx_stat_band(ad, band_idx, blk_idx, &st); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + rx_st_band->mac_rx_fcs_err_cnt = st.mac_rx_fcs_err_cnt; + rx_st_band->mac_rx_mdrdy_cnt = st.mac_rx_mdrdy_cnt; + rx_st_band->mac_rx_len_mismatch = st.mac_rx_len_mismatch; + rx_st_band->mac_rx_fcs_ok_cnt = st.mac_rx_fcs_ok_cnt; + rx_st_band->phy_rx_fcs_err_cnt_cck = st.phy_rx_fcs_err_cnt_cck; + rx_st_band->phy_rx_fcs_err_cnt_ofdm = st.phy_rx_fcs_err_cnt_ofdm; + rx_st_band->phy_rx_pd_cck = st.phy_rx_pd_cck; + rx_st_band->phy_rx_pd_ofdm = st.phy_rx_pd_ofdm; + rx_st_band->phy_rx_sig_err_cck = st.phy_rx_sig_err_cck; + rx_st_band->phy_rx_sfd_err_cck = st.phy_rx_sfd_err_cck; + rx_st_band->phy_rx_sig_err_ofdm = st.phy_rx_sig_err_ofdm; + rx_st_band->phy_rx_tag_err_ofdm = st.phy_rx_tag_err_ofdm; + rx_st_band->phy_rx_mdrdy_cnt_cck = st.phy_rx_mdrdy_cnt_cck; + rx_st_band->phy_rx_mdrdy_cnt_ofdm = st.phy_rx_mdrdy_cnt_ofdm; + + return ret; +} + +s_int32 mt_op_get_rx_stat_path( + struct test_wlan_info *winfos, + u_int8 band_idx, + u_int8 blk_idx, + struct test_rx_stat_path_info *rx_st_path) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + TEST_RX_STAT_PATH_INFO st; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ret = chip_get_rx_stat_path(ad, band_idx, blk_idx, &st); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + rx_st_path->rcpi = st.rcpi; + rx_st_path->rssi = st.rssi; + rx_st_path->fagc_ib_rssi = st.fagc_ib_rssi; + rx_st_path->fagc_wb_rssi = st.fagc_wb_rssi; + rx_st_path->inst_ib_rssi = st.inst_ib_rssi; + rx_st_path->inst_wb_rssi = st.inst_wb_rssi; + + return ret; +} + +s_int32 mt_op_get_rx_stat_user( + struct test_wlan_info *winfos, + u_int8 band_idx, + u_int8 blk_idx, + struct test_rx_stat_user_info *rx_st_user) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + TEST_RX_STAT_USER_INFO st; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ret = chip_get_rx_stat_user(ad, band_idx, blk_idx, &st); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + rx_st_user->freq_offset_from_rx = st.freq_offset_from_rx; + rx_st_user->snr = st.snr; + rx_st_user->fcs_error_cnt = st.fcs_error_cnt; + + return ret; +} + +s_int32 mt_op_get_rx_stat_comm( + struct test_wlan_info *winfos, + u_int8 band_idx, + u_int8 blk_idx, + struct test_rx_stat_comm_info *rx_st_comm) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + TEST_RX_STAT_COMM_INFO st; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ret = chip_get_rx_stat_comm(ad, band_idx, blk_idx, &st); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + rx_st_comm->rx_fifo_full = st.rx_fifo_full; + rx_st_comm->aci_hit_low = st.aci_hit_low; + rx_st_comm->aci_hit_high = st.aci_hit_high; + rx_st_comm->mu_pkt_count = st.mu_pkt_count; + rx_st_comm->sig_mcs = st.sig_mcs; + rx_st_comm->sinr = st.sinr; + rx_st_comm->driver_rx_count = st.driver_rx_count; + + return ret; +} + +s_int32 mt_op_get_wf_path_comb( + struct test_wlan_info *winfos, + u_int8 band_idx, + boolean dbdc_mode_en, + u_int8 *path, + u_int8 *path_len) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + ret = chip_get_wf_path_comb(ad, band_idx, dbdc_mode_en, path, path_len); + if (ret) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 mt_op_hetb_ctrl( + struct test_wlan_info *winfos, + u_char band_idx, + u_char ctrl_type, + boolean enable, + u_int8 bw, + u_int8 ltf_gi, + u_int8 stbc, + u_int8 pri_ru_idx, + struct test_ru_info *ru_info) +{ + s_int32 ret = SERV_STATUS_SUCCESS; +#if defined(DOT11_HE_AX) + RTMP_ADAPTER *ad = NULL; + struct _RTMP_CHIP_DBG *chip_dbg = NULL; + struct _ATE_RU_STA *ru = (struct _ATE_RU_STA *)ru_info; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + chip_dbg = hc_get_chip_dbg(ad->hdev_ctrl); + + if (ctrl_type == OP_HETB_RX_CFG) { + u_int64 hetb_rx_csd = 0x240004000060FF; + + if (chip_dbg->ctrl_manual_hetb_rx) + chip_dbg->ctrl_manual_hetb_rx(ad, + band_idx, + enable, + bw, + ltf_gi, + stbc, + hetb_rx_csd, + &ru[pri_ru_idx], + ru); + else + ret = SERV_STATUS_HAL_OP_FAIL; + } else { + if (chip_dbg->ctrl_manual_hetb_tx) + chip_dbg->ctrl_manual_hetb_tx(ad, + band_idx, + ctrl_type, + bw, + ltf_gi, + stbc, + ru); + else + ret = SERV_STATUS_HAL_OP_FAIL; + } +#endif /* DOT11_HE_AX */ + return ret; +} + +s_int32 mt_op_set_ru_aid( + struct test_wlan_info *winfos, + u_char band_idx, + u_int16 mu_rx_aid) +{ + s_int32 ret = SERV_STATUS_SUCCESS; +#ifdef CONFIG_HW_HAL_OFFLOAD + RTMP_ADAPTER *ad = NULL; + struct _EXT_CMD_ATE_TEST_MODE_T param; + u_int8 testmode_en = 1; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + sys_ad_zero_mem(¶m, sizeof(param)); + param.ucAteTestModeEn = testmode_en; + param.ucAteIdx = ENUM_ATE_SET_MU_RX_AID; + param.Data.set_mu_rx_aid.band_idx = band_idx; + param.Data.set_mu_rx_aid.aid = cpu2le16(mu_rx_aid); + + param.aucReserved[1] = INIT_CMD_SET_AND_WAIT_RETRY_RSP; + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s: Set to decode MU accodring to AID:%d\n", + __func__, param.Data.set_mu_rx_aid.aid)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("\t\t(%d means disable)\n", 0xf800)); + ret = MtCmdATETest(ad, ¶m); + + if (ret != 0) + ret = SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD; +#endif + + return ret; +} + +s_int32 mt_op_set_mutb_spe( + struct test_wlan_info *winfos, + u_char band_idx, + u_char tx_mode, + u_int8 spe_idx) +{ + RTMP_ADAPTER *ad = NULL; + struct _RTMP_CHIP_DBG *chip_dbg = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_OP_INVALID_PAD; + + chip_dbg = hc_get_chip_dbg(ad->hdev_ctrl); + if (chip_dbg->chip_ctrl_spe) + chip_dbg->chip_ctrl_spe(ad, band_idx, tx_mode, spe_idx); + + return SERV_STATUS_SUCCESS; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/hal/jedi/test_dmac.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/hal/jedi/test_dmac.c new file mode 100644 index 0000000000000..c735e1266983e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/hal/jedi/test_dmac.c @@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#include "rt_config.h" +#include "test_mac.h" + +s_int32 mt_test_mac_backup_and_set_cr( + struct test_wlan_info *winfos, + struct test_bk_cr *bks, + u_char band_idx) +{ + struct _RTMP_CHIP_OP *ops = hc_get_chip_ops(winfos->hdev_ctrl); + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_MAC_INVALID_PAD; + + if (ops->backup_reg_before_ate) + ops->backup_reg_before_ate(ad); + else + return SERV_STATUS_HAL_MAC_INVALID_CHIPOPS; + +#if 0 +#ifndef MT7615 + if (!IS_MT7615(pAd)) { + /* VHT20 MCS9 Support on LDPC Mode */ + net_ad_backup_cr(winfos, bks, + WF_WTBLOFF_TOP_LUECR_ADDR, SERV_TEST_MAC_BKCR); + MAC_IO_READ32(ad->hdev_ctrl, WF_WTBLOFF_TOP_LUECR_ADDR, &val); + val = 0xFFFFFFFF; + MAC_IO_WRITE32(ad->hdev_ctrl, WF_WTBLOFF_TOP_LUECR_ADDR, val); + } +#endif /* !defined(MT7615) */ +#endif + + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_test_mac_restore_cr( + struct test_wlan_info *winfos, + struct test_bk_cr *bks, + u_char band_idx) +{ + struct _RTMP_CHIP_OP *ops = hc_get_chip_ops(winfos->hdev_ctrl); + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_MAC_INVALID_PAD; + + if (ops->restore_reg_after_ate) + ops->restore_reg_after_ate(ad); + else + return SERV_STATUS_HAL_MAC_INVALID_CHIPOPS; + +#if 0 +#ifndef MT7615 + if (!IS_MT7615(pAd)) { + /* VHT20 MCS9 Support on LDPC Mode backup */ + net_ad_restore_cr(winfos, WF_WTBLOFF_TOP_LUECR_ADDR); + } +#endif /* defined(MT7663) */ +#endif + + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_test_mac_set_ampdu_ba_limit( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_int8 agg_limit) +{ + struct _RTMP_CHIP_OP *ops = hc_get_chip_ops(winfos->hdev_ctrl); + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_MAC_INVALID_PAD; + + if (ops->set_ba_limit) + ops->set_ba_limit(ad, configs->wmm_idx, agg_limit); + else + return SERV_STATUS_HAL_MAC_INVALID_CHIPOPS; + + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_test_mac_set_sta_pause_cr( + struct test_wlan_info *winfos) +{ + RTMP_ADAPTER *ad = NULL; + struct _RTMP_CHIP_OP *ops = hc_get_chip_ops(winfos->hdev_ctrl); + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_MAC_INVALID_PAD; + + if (ops->pause_ac_queue) + ops->pause_ac_queue(ad, 0xf); + else + return SERV_STATUS_HAL_MAC_INVALID_CHIPOPS; + + return SERV_STATUS_SUCCESS; +} + +s_int32 mt_test_mac_set_ifs_cr( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx) +{ + RTMP_ADAPTER *ad = NULL; + struct _RTMP_CHIP_OP *ops = hc_get_chip_ops(winfos->hdev_ctrl); + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_HAL_MAC_INVALID_PAD; + + if (ops->set_ifs) + ops->set_ifs(ad, band_idx); + else + return SERV_STATUS_HAL_MAC_INVALID_CHIPOPS; + + return SERV_STATUS_SUCCESS; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/hal/jedi/test_fmac.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/hal/jedi/test_fmac.c new file mode 100644 index 0000000000000..8d80d8cb6827a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/hal/jedi/test_fmac.c @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#include "rt_config.h" +#include "test_mac.h" diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/osal/gen4m/net_adaption_gen4m.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/osal/gen4m/net_adaption_gen4m.c new file mode 100644 index 0000000000000..3092df940d5be --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/osal/gen4m/net_adaption_gen4m.c @@ -0,0 +1,414 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#include "net_adaption.h" +#define GEM4M_NET_ADAPTION_SUPPORT 0 +#if GEM4M_NET_ADAPTION_SUPPORT +static struct test_thread_cb g_test_thread[SERV_THREAD_NUM]; +#endif + +struct service_test *net_ad_wrap_service(void *adapter) +{ + return (struct service_test *)adapter; +} + +void net_ad_thread_proceed_tx( + struct test_wlan_info *winfos, u_char band_idx) +{ +} + +void net_ad_thread_stop_tx( + struct test_wlan_info *winfos) +{ +} + +s_int32 net_ad_init_thread( + struct test_wlan_info *winfos, + struct test_configuration *configs, + enum service_thread_list thread_idx) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_release_thread(u_char thread_idx) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_backup_cr( + struct test_wlan_info *winfos, struct test_bk_cr *test_bkcr, + u_long offset, enum test_bk_cr_type type) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_restore_cr( + struct test_wlan_info *winfos, struct test_bk_cr *test_bkcr, + u_long offset) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_cfg_queue( + struct test_wlan_info *winfos, boolean enable) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_enter_normal( + struct test_wlan_info *winfos, + struct test_backup_params *bak) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_exit_normal( + struct test_wlan_info *winfos, + struct test_backup_params *bak) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_update_wdev( + u_int8 band_idx, + struct test_wlan_info *winfos, + struct test_configuration *configs) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_init_wdev( + struct test_wlan_info *winfos, + struct test_configuration *configs, u_char band_idx) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_release_wdev( + struct test_wlan_info *winfos, + struct test_configuration *configs) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_alloc_wtbl( + struct test_wlan_info *winfos, + u_char *da, + void *virtual_dev, + void **virtual_wtbl) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_free_wtbl( + struct test_wlan_info *winfos, + u_char *da, + void *virtual_wtbl) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_apply_wtbl( + struct test_wlan_info *winfos, + void *virtual_dev, + void *virtual_wtbl) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_match_wtbl( + void *virtual_wtbl, + u_int16 wcid) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_set_aid( + void *virtual_wtbl, + u_int16 aid) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_get_wmm_idx( + void *virtual_device, + u_int8 *wmm_idx) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_get_band_idx( + void *virtual_device, + u_char *band_idx) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_get_omac_idx( + struct test_wlan_info *winfos, + void *virtual_device, + u_char *omac_idx) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_fill_phy_info( + void *virtual_wtbl, + struct test_tx_info *tx_info) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_get_speidx( + struct test_wlan_info *winfos, + u_int16 ant_sel, + u_int8 *spe_idx) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_fill_spe_antid( + struct test_wlan_info *winfos, + void *virtual_wtbl, + u_int8 spe_idx, + u_int8 ant_pri) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_fill_pkt( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char *buf, u_int32 txlen, u_int32 hlen) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_alloc_pkt( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_int32 mpdu_length, + void **pkt_skb) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_enq_pkt( + struct test_wlan_info *winfos, + u_short q_idx, + void *virtual_wtbl, + void *virtual_device, + void *pkt) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_free_pkt( + struct test_wlan_info *winfos, + void *pkt_skb) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_trigger_tx( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_int8 band_idx, + void *pkt) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_rx_done_handle( + struct test_wlan_info *winfos, + void *rx_blk) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_set_band_mode( + struct test_wlan_info *winfos, + struct test_band_state *band_state) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_set_txpwr_power_drop( + struct test_wlan_info *winfos, + u_char power_drop, u_char band_idx) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_set_txpwr_percentage( + struct test_wlan_info *winfos, + u_char percentage_ctrl, u_char band_idx) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_set_txpwr_backoff( + struct test_wlan_info *winfos, + u_char backoff_ctrl, u_char band_idx) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_init_txpwr( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_handle_mcs32( + struct test_wlan_info *winfos, + void *virtual_wtbl, u_int8 bw) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_cfg_wtbl( + struct test_wlan_info *winfos, + struct test_configuration *configs) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_set_wmm_param_by_qid( + u_int8 wmm_idx, + u_int8 q_idx, + struct test_wlan_info *winfos, + struct test_configuration *configs) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_clean_sta_q( + struct test_wlan_info *winfos, u_char wcid) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_set_auto_resp( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx, u_char mode) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_set_low_power( + struct test_wlan_info *winfos, u_int32 control) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_read_mac_bbp_reg( + struct test_wlan_info *winfos, + struct test_register *regs) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_write_mac_bbp_reg( + struct test_wlan_info *winfos, + struct test_register *regs) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_read_bulk_mac_bbp_reg( + struct test_wlan_info *winfos, + struct test_configuration *configs, + struct test_register *regs) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_read_bulk_rf_reg( + struct test_wlan_info *winfos, + struct test_register *regs) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_write_bulk_rf_reg( + struct test_wlan_info *winfos, + struct test_register *regs) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +void net_ad_read_ca53_reg(struct test_register *regs) +{ +} + +void net_ad_write_ca53_reg(struct test_register *regs) +{ +} + +s_int32 net_ad_read_write_eeprom( + struct test_wlan_info *winfos, + struct test_eeprom *eprms, + boolean is_read) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_read_write_bulk_eeprom( + struct test_wlan_info *winfos, + struct test_eeprom *eprms, + boolean is_read) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_get_free_efuse_block( + struct test_wlan_info *winfos, + struct test_eeprom *eprms) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_mps_tx_operation( + struct test_wlan_info *winfos, + struct test_configuration *configs, + boolean is_start_tx) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_set_tmr( + struct test_wlan_info *winfos, + struct test_tmr_info *tmr_info) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_get_rxv_stat( + struct test_wlan_info *winfos, + u_char ctrl_band_idx, + struct test_rx_stat *rx_stat) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_get_rxv_cnt( + struct test_wlan_info *winfos, + u_char ctrl_band_idx, + u_int32 *byte_cnt) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + +s_int32 net_ad_get_rxv_content( + struct test_wlan_info *winfos, + u_char ctrl_band_idx, + void *content) +{ + return SERV_STATUS_OSAL_NET_FAIL; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/osal/gen4m/sys_adaption_gen4m.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/osal/gen4m/sys_adaption_gen4m.c new file mode 100644 index 0000000000000..019782e6a4a5c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/osal/gen4m/sys_adaption_gen4m.c @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#include "sys_adaption.h" +#include "gl_os.h" +#include "gl_kal.h" +#include "gl_wext.h" +#include "precomp.h" +#include "debug.h" + +#define UNUSED(x) ((void)(x)) +/***************************************************************************** + * Packet free related functions + *****************************************************************************/ +void sys_ad_free_pkt(void *packet) +{ + +} + +/***************************************************************************** + * OS memory allocate/manage/free related functions + *****************************************************************************/ +s_int32 sys_ad_alloc_mem(u_char **mem, u_long size) +{ + *mem = (u_char *)kalMemAlloc(size, PHY_MEM_TYPE); + + if (*mem) + return SERV_STATUS_SUCCESS; + else + return SERV_STATUS_OSAL_SYS_FAIL; +} + +void sys_ad_free_mem(void *mem) +{ + ASSERT(mem); + kfree(mem); +} + +void sys_ad_zero_mem(void *ptr, u_long length) +{ + kalMemZero(ptr, length); +} + +void sys_ad_set_mem(void *ptr, u_long length, u_char value) +{ + kalMemSet(ptr, value, length); +} + + +void sys_ad_move_mem(void *dest, void *src, u_long length) +{ + kalMemMove(dest, src, length); +} + +s_int32 sys_ad_cmp_mem(void *dest, void *src, u_long length) +{ + return kalMemCmp(dest, src, length); +} + +/***************************************************************************** + * OS task create/manage/kill related functions + *****************************************************************************/ +s_int32 sys_ad_kill_os_task(struct serv_os_task *task) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 sys_ad_attach_os_task( + struct serv_os_task *task, SERV_OS_TASK_CALLBACK fn, u_long arg) +{ + return SERV_STATUS_SUCCESS; +} + +s_int32 sys_ad_init_os_task( + struct serv_os_task *task, char *task_name, + void *priv_winfos, void *priv_configs) +{ + return SERV_STATUS_SUCCESS; +} + +boolean sys_ad_wait_os_task( + void *reserved, struct serv_os_task *task, s_int32 *status) +{ + return SERV_STATUS_SUCCESS; +} + +void sys_ad_wakeup_os_task(struct serv_os_task *task) +{ + UNUSED(task); +} +/***************************************************************************** + * OS debug functions + *****************************************************************************/ +void sys_ad_mem_dump32(void *ptr, u_long length) +{ + dumpMemory32((s_int32 *)ptr, length); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/osal/include/net_adaption.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/osal/include/net_adaption.h new file mode 100644 index 0000000000000..b873f14e102be --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/osal/include/net_adaption.h @@ -0,0 +1,1733 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#ifndef __NET_ADAPTION_H__ +#define __NET_ADAPTION_H__ + +#include "sys_adaption.h" + +/***************************************************************************** + * Type definition + *****************************************************************************/ + + +/***************************************************************************** + * Macro + *****************************************************************************/ +/* Service DBDC configuration */ +#define TEST_DBDC_BAND0 0 +#define TEST_DBDC_BAND1 1 + +/* #ifdef DBDC_MODE */ +#if 1 +#define SET_TEST_DBDC(_test_winfo, _boolean) \ + (_test_winfo->dbdc_mode = _boolean) +#define IS_TEST_DBDC(_test_winfo) _test_winfo->dbdc_mode +#define TEST_DBDC_BAND_NUM 2 +#else +#define IS_TEST_DBDC(_test_winfo) FALSE +#define TEST_DBDC_BAND_NUM 1 +#endif + +/* Packet */ +#define SERV_LENGTH_802_11 24 + +/* For rx stat type */ +#define SERV_TEST_RX_STAT_MACFCSERRCNT 0x1 +#define SERV_TEST_RX_STAT_MAC_MDRDYCNT 0x2 +#define SERV_TEST_RX_STAT_PHY_MDRDYCNT 0x3 +#define SERV_TEST_RX_STAT_PHY_FCSERRCNT 0x4 +#define SERV_TEST_RX_STAT_PD 0x5 +#define SERV_TEST_RX_STAT_CCK_SIG_SFD 0x6 +#define SERV_TEST_RX_STAT_OFDM_SIG_TAG 0x7 +#define SERV_TEST_RX_STAT_RSSI 0x8 +#define SERV_TEST_RX_RESET_PHY_COUNT 0x9 +#define SERV_TEST_RX_RESET_MAC_COUNT 0xa +#define SERV_TEST_RX_STAT_RSSI_RX23 0xB +#define SERV_TEST_RX_STAT_ACI_HITL 0xC +#define SERV_TEST_RX_STAT_ACI_HITH 0xD +#define SERV_TEST_RX_STAT_MACFCSERRCNT_BAND1 0xE +#define SERV_TEST_RX_STAT_MAC_MDRDYCNT_BAND1 0xF +#define SERV_TEST_RX_STAT_MAC_RXLENMISMATCH 0x10 +#define SERV_TEST_RX_STAT_MAC_RXLENMISMATCH_BAND1 0x11 +#define SERV_TEST_RX_FIFO_FULL_COUNT 0x12 +#define SERV_TEST_RX_FIFO_FULL_COUNT_BAND1 0x13 +#define SERV_TEST_RX_STAT_PHY_MDRDYCNT_BAND1 0x14 +#define SERV_TEST_RX_STAT_PHY_FCSERRCNT_BAND1 0x15 +#define SERV_TEST_RX_STAT_PD_BAND1 0x16 +#define SERV_TEST_RX_STAT_CCK_SIG_SFD_BAND1 0x17 +#define SERV_TEST_RX_STAT_OFDM_SIG_TAG_BAND1 0x18 +#define SERV_TEST_RX_ACI_HIT 0x19 +#define SERV_TEST_RX_STAT_MAC_FCS_OK_COUNT 0x1A + +/* MAC behavior control */ +#define SERV_TEST_MAC_TX 1 +#define SERV_TEST_MAC_RX 2 +#define SERV_TEST_MAC_TXRX 3 +#define SERV_TEST_MAC_TXRX_RXV 4 +#define SERV_TEST_MAC_RXV 5 +#define SERV_TEST_MAC_RX_RXV 6 + +/* Setting max packet length to 13311 after MT7615 */ +#define TEST_PKT_LEN 13311 + +#define TEST_MAX_PATTERN_SIZE 128 + +#define TEST_MAX_PKT_LEN 1496 +#define TEST_MIN_PKT_LEN 25 +#define TEST_MAX_BKCR_NUM 30 + +/* For packet tx time, in unit of byte */ +#define TEST_MAX_HT_AMPDU_LEN 65000 +#define TEST_MAX_VHT_MPDU_LEN 6700 /* 11454 */ +#define TEST_DEFAULT_MPDU_LEN 4096 +#define TEST_MAX_MSDU_LEN 2304 +#define TEST_MIN_MSDU_LEN 22 +#define TEST_DEFAULT_MAC_HDR_LEN 24 +#define TEST_QOS_MAC_HDR_LEN 26 + +/* For ipg and duty cycle, in unit of us */ +#define TEST_SIG_EXTENSION 6 +#define TEST_DEFAULT_SLOT_TIME 9 +#define TEST_DEFAULT_SIFS_TIME 10 +/* ICR: 7-bit, ATCR/TRCR limitation: 8-bit/9-bit */ +#define TEST_MAX_SIFS_TIME 127 +#define TEST_MAX_AIFSN 0xF +#define TEST_MIN_AIFSN 0x1 +#define TEST_MAX_CW 0x10 +#define TEST_MIN_CW 0x0 +#define TEST_NORMAL_CLOCK_TIME 50 /* in uint of ns */ +#define TEST_BBP_PROCESSING_TIME 1500 /* in uint of ns */ + +/* Spec related definition */ +#define TEST_RIFS_TIME 2 /* 802.11n */ +/* Refine to 60 from 360 us, 2018.05.09 */ +#define TEST_EIFS_TIME 60 + +/* The expected enqueue packet number when rx event trigger */ +#define TEST_ENQ_PKT_NUM 100 + +#define TEST_RXV_SIZE 9 +#define TEST_ANT_NUM 4 +#define TEST_USER_NUM 16 + +/* MAC address length */ +#define SERV_MAC_ADDR_LEN 6 + +/* Wcid related */ +#define SERV_WCID_ALL 0xFF + +#ifndef IFNAMELEN +#define IFNAMELEN 16 +#endif + +#define SERV_IOCTLBUFF 2048 + +/* Test log dump type */ +#define fTEST_LOG_RXV (1 << TEST_LOG_RXV) +#define fTEST_LOG_RDD (1 << TEST_LOG_RDD) +#define fTEST_LOG_RE_CAL (1 << TEST_LOG_RE_CAL) +#define fTEST_LOG_RXINFO (1 << TEST_LOG_RXINFO) +#define fTEST_LOG_TXDUMP (1 << TEST_LOG_TXDUMP) +#define fTEST_LOG_TEST (1 << TEST_LOG_TEST) +#define fTEST_LOG_TXSSHOW (1 << TEST_LOG_TXSSHOW) + +/* Test ant user select */ +#define TEST_ANT_USER_SEL 0x80000000 + +/* Test mps item length/stat */ +#define TEST_MPS_ITEM_LEN 1024 +#define TEST_MPS_ITEM_RUNNING (1<<0) +#define BITS(m, n) (~(BIT(m)-1) & ((BIT(n) - 1) | BIT(n))) + +#if defined(DOT11_HE_AX) +#define MAX_MULTI_TX_STA 16 +#else +#define MAX_MULTI_TX_STA 2 +#endif + +/***************************************************************************** + * Enum value definition + *****************************************************************************/ +/* Service queue id */ +enum { + SERV_QID_AC_BK, + SERV_QID_AC_BE, + SERV_QID_AC_VI, + SERV_QID_AC_VO, + SERV_QID_HCCA, + SERV_QID_BMC = 8, + SERV_QID_MGMT = 13, + SERV_QID_RX = 14, + SERV_QID_CTRL = 16, + SERV_QID_BCN = 17, +}; + +/* Service rx filter packet type */ +enum { + SERV_RX_FILTER_STBC_BCN_BC_MC = 1 << 0, + SERV_RX_FILTER_FCS_ERROR = 1 << 1, + /* drop 802.11 protocol version not is 0 */ + SERV_RX_FILTER_PROTOCOL_VERSION = 1 << 2, + SERV_RX_FILTER_PROB_REQ = 1 << 3, + /* drop all mcast frame */ + SERV_RX_FILTER_MC_ALL = 1 << 4, + SERV_RX_FILTER_BC_ALL = 1 << 5, + /* drop mcast frame that is not in the mcast table */ + SERV_RX_FILTER_MC_TABLE = 1 << 6, + /* drop bc/mc packet matches the following condition: */ + /* ToDS=0,FromDS=1,A3=OwnMAC0 or OwnMAC1 */ + SERV_RX_FILTER_BC_MC_OWN_MAC_A3 = 1 << 7, + /* drop bc/mc packet matches the following condition: */ + /* ToDS=0,FromDS=0,A3!=BSSID0 or BSSID1 */ + SERV_RX_FILTER_BC_MC_DIFF_BSSID_A3 = 1 << 8, + /* drop bc/mc packet matches the following condition: */ + /* ToDS=0,FromDS=1,A2!=BSSID0 or BSSID1 */ + SERV_RX_FILTER_BC_MC_DIFF_BSSID_A2 = 1 << 9, + /* drop bcn packet and A3!=BSSID0 or BSSID1 */ + SERV_RX_FILTER_BCN_DIFF_BSSID = 1 << 10, + /* drop control packets with reserve type */ + SERV_RX_FILTER_CTRL_RSV = 1 << 11, + SERV_RX_FILTER_CTS = 1 << 12, + SERV_RX_FILTER_RTS = 1 << 13, + /* drop duplicate frame, BA session not includign in this filter */ + SERV_RX_FILTER_DUPLICATE = 1 << 14, + /* drop not my BSSID0/1/2/3 if enabled */ + SERV_RX_FILTER_NOT_OWN_BSSID = 1 << 15, + /* drop uncast packet not to OWN MAC 0/1/2/3/4 */ + SERV_RX_FILTER_NOT_OWN_UCAST = 1 << 16, + /* drop diff bassid TIM broadcast */ + SERV_RX_FILTER_NOT_OWN_BTIM = 1 << 17, + /*drop NDPA control frame */ + SERV_RX_FILTER_NDPA = 1 << 18, +}; + +/* Test DBDC band mode for QA */ +enum test_band_mode { + TEST_BAND_MODE_UNUSE = 0, + TEST_BAND_MODE_SINGLE, + TEST_BAND_MODE_DUAL +}; + +/* Test DBDC band type for QA */ +enum test_band_type { + TEST_BAND_TYPE_UNUSE = 0, + TEST_BAND_TYPE_G, + TEST_BAND_TYPE_A, + TEST_BAND_TYPE_ALL +}; + +/* Test DBDC enable for QA */ +enum test_dbdc_enable { + TEST_DBDC_DISABLE = 0, + TEST_DBDC_ENABLE +}; + +/* HWTX enable for QA */ +enum test_hwtx_enable { + TEST_HWTX_DISABLE = 0, + TEST_HWTX_ENABLE +}; + + +/* Test backup CR type */ +enum test_bk_cr_type { + SERV_TEST_EMPTY_BKCR = 0, + SERV_TEST_MAC_BKCR, + SERV_TEST_HIF_BKCR, + SERV_TEST_PHY_BKCR, + SERV_TEST_HW_BKCR, + SERV_TEST_MCU_BKCR, + SERV_TEST_BKCR_TYPE_NUM +}; + +/* Test tx strategy */ +enum test_tx_strategy { + TEST_TX_STRA_TASKLET = 0, + TEST_TX_STRA_THREAD +}; + +/* Test tx type */ +enum test_tx_type { + TEST_TX_TYPE_TXD = 0, + TEST_TX_TYPE_WTBL +}; + +/* Test rx statistic type */ +enum test_rx_stat_type { + TEST_RX_STAT_RXV, + TEST_RX_STAT_PER_PKT, + TEST_RX_STAT_RESET_CNT, + TEST_RX_STAT_COUNTER_802_11, + TEST_RX_STAT_STAT_TYPE_NUM +}; + +/* Test bw definition */ +enum test_bw_type { + TEST_BW_20 = 0, + TEST_BW_40, + TEST_BW_80, + TEST_BW_10, + TEST_BW_5, + TEST_BW_160C, + TEST_BW_160NC, + TEST_BW_NUM +}; + +/* Test HE LTF definition */ +enum test_he_ltf_type { + TEST_HE_LTF_X1, + TEST_HE_LTF_X2, + TEST_HE_LTF_X4, +}; + +/* Test HE GI definition */ +enum test_he_gi_type { + TEST_GI_8, + TEST_GI_16, + TEST_GI_32, +}; + +/* Test phy mode definition */ +enum test_phy_mode_type { + TEST_MODE_CCK = 0, + TEST_MODE_OFDM, + TEST_MODE_HTMIX, + TEST_MODE_HTGREENFIELD, + TEST_MODE_VHT, + TEST_MODE_HE_24G, + TEST_MODE_HE_5G, + TEST_MODE_HE_SU = 8, + TEST_MODE_HE_ER, + TEST_MODE_HE_TB, + TEST_MODE_HE_MU, + TEST_MODE_VHT_MIMO, + TEST_MODE_NUM +}; + +/* Test payload policy */ +enum { + TEST_USER_PAYLOAD = 0, + TEST_FIXED_PAYLOAD, + TEST_RANDOM_PAYLOAD +}; + +/* Test log dump type */ +enum { + TEST_LOG_RXV = 1, + TEST_LOG_RDD, + TEST_LOG_RE_CAL, + TEST_LOG_TYPE_NUM, + TEST_LOG_RXINFO, + TEST_LOG_TXDUMP, + TEST_LOG_TEST, + TEST_LOG_TXSSHOW, +}; + +enum { + TEST_LOG_OFF, + TEST_LOG_ON, + TEST_LOG_DUMP, + TEST_LOG_CTRL_NUM, +}; + +enum { + TEST_RX_STAT_BAND = 0, + TEST_RX_STAT_PATH, + TEST_RX_STAT_USER, + TEST_RX_STAT_COMM, + TEST_RX_STAT_NUM +}; + +/***************************************************************************** + * Data struct definition + *****************************************************************************/ +/* Service IOCTL related definitions */ +struct serv_ioctl_input { + union { + s_char ifrn_name[IFNAMELEN]; /* if name, e.g. "eth0" */ + } ifr_ifrn; + union { + s_char *name; + struct { + s_char *pointer; + u_int16 length; + u_int16 flags; + } data; + } u; +}; + +/* Servoce spec related data struct */ +struct GNU_PACKED serv_frame_control { +#ifdef RT_BIG_ENDIAN + u_int16 order:1; /* Strict order expected */ + u_int16 wep:1; /* Wep data */ + u_int16 more_data:1; /* More data bit */ + u_int16 pwr_mgmt:1; /* Power management bit */ + u_int16 retry:1; /* Retry status bit */ + u_int16 more_frag:1; /* More fragment bit */ + u_int16 fr_ds:1; /* From DS indication */ + u_int16 to_ds:1; /* To DS indication */ + u_int16 sub_type:4; /* MSDU subtype */ + u_int16 type:2; /* MSDU type */ + u_int16 ver:2; /* Protocol version */ +#else + u_int16 ver:2; /* Protocol version */ + u_int16 type:2; /* MSDU type, refer to FC_TYPE_XX */ + u_int16 sub_type:4; /* MSDU subtype, refer to SUBTYPE_XXX */ + u_int16 to_ds:1; /* To DS indication */ + u_int16 fr_ds:1; /* From DS indication */ + u_int16 more_frag:1; /* More fragment bit */ + u_int16 retry:1; /* Retry status bit */ + u_int16 pwr_mgmt:1; /* Power management bit */ + u_int16 more_data:1; /* More data bit */ + u_int16 wep:1; /* Wep data */ + u_int16 order:1; /* Strict order expected */ +#endif /* !RT_BIG_ENDIAN */ +}; + +struct GNU_PACKED serv_hdr_802_11 { + struct serv_frame_control fc; + u_int16 duration; + u_char addr1[6]; + u_char addr2[6]; + u_char addr3[6]; +#ifdef RT_BIG_ENDIAN + u_int16 sequence:12; + u_int16 frag:4; +#else + u_int16 frag:4; + u_int16 sequence:12; +#endif /* !RT_BIG_ENDIAN */ + u_char octet[0]; +}; + +/* Service fw related information */ +struct serv_fw_info { + boolean ra_offload; + u_int8 chip_id; /* different with top cr*/ + u_int8 eco_ver; + u_int8 num_of_region; + u_int8 format_ver; + u_int8 format_flag; + u_int8 ram_ver[10]; + u_int8 ram_built_date[15]; + u_int32 crc; +}; + +/* Service chip capability related definition */ +struct serv_mcs_nss_caps { + boolean g_band_256_qam; + u_int8 max_nss; + u_int8 max_vht_mcs; + u_int8 bw160_max_nss; +}; + +struct serv_qos_caps { + u_char wmm_hw_num; + u_char wmm_detect_method; + u_int32 txop_scenario; + u_int32 current_txop; + u_int32 default_txop; +}; + +struct serv_spe_map { + u_int8 ant_sel; + u_int8 spe_idx; +}; + +struct serv_spe_map_list { + struct serv_spe_map *spe_map; + u_int8 size; +}; + +struct serv_chip_cap { + /* ------------------------ packet --------------------- */ + /* TxWI or LMAC TxD max size */ + u_int8 tx_wi_size; + /* RxWI or LMAC RxD max size */ + u_int8 rx_wi_size; + /* Tx Hw meta info size which including all hw info fields */ + u_int8 tx_hw_hdr_len; + /* Rx Hw meta info size */ + u_int8 rx_hw_hdr_len; + u_int8 num_of_tx_ring; + u_int8 num_of_rx_ring; + u_int16 tx_ring_size; + u_int8 ht_ampdu_exp; + u_int16 non_he_tx_ba_wsize; + u_int8 max_mpdu_len; + u_int8 vht_ampdu_exp; + u_int16 he_tx_ba_wsize; + u_int8 he_ampdu_exp; + u_int16 efuse_size; + struct serv_mcs_nss_caps mcs_nss; + struct serv_qos_caps qos; + struct serv_spe_map_list spe_map_list; + boolean swq_per_band; +}; + +/* Service channel configuration */ +struct serv_channel_cfg { + u_char ctrl_channel; + /*Only used for 80+80 case */ + u_char ctrl_channel2; + u_char central_channel; + u_char bw; + u_char tx_stream; + u_char rx_stream; + boolean scan; + boolean dfs_check; + u_char band_idx; + u_char ch_band; + u_int32 out_band_freq; +}; + +/* Test data rate map */ +struct test_data_rate_map { + u_char mcs; /* MCS index */ + u_int32 tx_data_rate; /* Data rate in K bit */ +}; + +/* Test data aggregation threshold */ +struct test_datalen_limit_map { + u_char phy_mode; /* MCS index */ + u_int32 amsdu_limit; /* Data rate in K bit */ +}; + +/* Test ant to spe_idx map */ +struct test_ant_map { + u_int32 ant_sel; + u_int32 spe_idx; +}; + +/* Test rx filter */ +/* TODO: factor out here for naming */ +struct rx_filter_ctrl { + u_int32 filterMask; + boolean bPromiscuous; + boolean bFrameReport; + u_char u1BandIdx; +}; + +/* Test backup CR */ +struct test_bk_cr { + u_long offset; + u_int32 val; + enum test_bk_cr_type type; +}; + +/* Test backup params from normal */ +struct test_backup_params { + bool en_tx_burst; + bool en_bss_coex; + u_int16 bcn_prd; +}; + +/* Test tx counters */ +struct test_tx_statistic { + u_int32 tx_cnt; + u_int32 tx_done_cnt; /* Tx DMA Done */ + u_int32 txed_cnt; +}; + +/* Test rx stat band info */ +struct test_rx_stat_band_info { + u_int32 mac_rx_fcs_err_cnt; + u_int32 mac_rx_mdrdy_cnt; + u_int32 mac_rx_len_mismatch; + u_int32 mac_rx_fcs_ok_cnt; + u_int32 phy_rx_fcs_err_cnt_cck; + u_int32 phy_rx_fcs_err_cnt_ofdm; + u_int32 phy_rx_pd_cck; + u_int32 phy_rx_pd_ofdm; + u_int32 phy_rx_sig_err_cck; + u_int32 phy_rx_sfd_err_cck; + u_int32 phy_rx_sig_err_ofdm; + u_int32 phy_rx_tag_err_ofdm; + u_int32 phy_rx_mdrdy_cnt_cck; + u_int32 phy_rx_mdrdy_cnt_ofdm; +}; + +/* Test rx stat path info */ +struct test_rx_stat_path_info { + u_int32 rcpi; + u_int32 rssi; + u_int32 fagc_ib_rssi; + u_int32 fagc_wb_rssi; + u_int32 inst_ib_rssi; + u_int32 inst_wb_rssi; +}; + +/* Test rx stat user info */ +struct test_rx_stat_user_info { + s_int32 freq_offset_from_rx; + u_int32 snr; + u_int32 fcs_error_cnt; +}; + +/* Test rx stat comm info */ +struct test_rx_stat_comm_info { + u_int32 rx_fifo_full; + u_int32 aci_hit_low; + u_int32 aci_hit_high; + u_int32 mu_pkt_count; + u_int32 sig_mcs; + u_int32 sinr; + u_int32 driver_rx_count; +}; + +/* Test rx stat */ +struct test_rx_stat { + struct test_rx_stat_band_info rx_st_band[TEST_DBDC_BAND_NUM]; + struct test_rx_stat_path_info rx_st_path[TEST_ANT_NUM]; + struct test_rx_stat_user_info rx_st_user[TEST_USER_NUM]; + struct test_rx_stat_comm_info rx_st_comm; +}; + +/* Test rx stat union */ +struct test_rx_stat_u { + union { + struct test_rx_stat_band_info rx_st_band; + struct test_rx_stat_path_info rx_st_path; + struct test_rx_stat_user_info rx_st_user; + struct test_rx_stat_comm_info rx_st_comm; + } u; +}; + +struct GNU_PACKED test_rx_stat_leg { + u_int32 mac_rx_fcs_err_cnt; + u_int32 mac_rx_mdrdy_cnt; + u_int32 phy_rx_fcs_err_cnt_cck; + u_int32 phy_rx_fcs_err_cnt_ofdm; + u_int32 phy_rx_pd_cck; + u_int32 phy_rx_pd_ofdm; + u_int32 phy_rx_sig_err_cck; + u_int32 phy_rx_sfd_err_cck; + u_int32 phy_rx_sig_err_ofdm; + u_int32 phy_rx_tag_err_ofdm; + u_int32 wb_rssi0; + u_int32 ib_rssi0; + u_int32 wb_rssi1; + u_int32 ib_rssi1; + u_int32 phy_rx_mdrdy_cnt_cck; + u_int32 phy_rx_mdrdy_cnt_ofdm; + u_int32 driver_rx_cnt; + u_int32 rcpi0; + u_int32 rcpi1; + s_int32 freq_offset_rx; + u_int32 rssi0; + u_int32 rssi1; + u_int32 rx_fifo_full; + u_int32 mac_rx_len_mismatch; + u_int32 mac_rx_fcs_err_cnt_band1; + u_int32 mac_rx_mdrdy_cnt_band1; + u_int32 fagc_ib_rssi[TEST_ANT_NUM]; + u_int32 fagc_wb_rssi[TEST_ANT_NUM]; + u_int32 inst_ib_rssi[TEST_ANT_NUM]; + u_int32 inst_wb_rssi[TEST_ANT_NUM]; + u_int32 aci_hit_low; + u_int32 aci_git_high; + u_int32 driver_rx_cnt1; + u_int32 rcpi2; + u_int32 rcpi3; + u_int32 rssi2; + u_int32 rssi3; + u_int32 snr0; + u_int32 snr1; + u_int32 snr2; + u_int32 snr3; + u_int32 rx_fifo_full_band1; + u_int32 mac_rx_len_mismatch_band1; + u_int32 phy_rx_pd_cck_band1; + u_int32 phy_rx_pd_ofdm_band1; + u_int32 phy_rx_sig_err_cck_band1; + u_int32 phy_rx_sfd_err_cck_band1; + u_int32 phy_rx_sig_err_ofdm_band1; + u_int32 phy_rx_tag_err_ofdm_band1; + u_int32 phy_rx_mdrdy_cnt_cck_band1; + u_int32 phy_rx_mdrdy_cnt_ofdm_band1; + u_int32 phy_rx_fcs_err_cnt_cck_band1; + u_int32 phy_rx_fcs_err_cnt_ofdm_band1; + u_int32 mu_pkt_cnt; + u_int32 sig_mcs; + u_int32 sinr; + u_int32 rxv_rssi; + u_int32 mac_rx_fcs_ok_cnt; + u_int32 leg_rssi_sub[8]; + s_int32 user_rx_freq_offset[TEST_USER_NUM]; + u_int32 user_snr[TEST_USER_NUM]; + u_int32 fcs_error_cnt[TEST_USER_NUM]; +}; + +/* For mobile temp use */ +struct GNU_PACKED hqa_m_rx_stat { + u_int32 mac_rx_fcs_err_cnt; + u_int32 mac_rx_mdrdy_cnt; + u_int32 phy_rx_fcs_err_cnt_cck; + u_int32 phy_rx_fcs_err_cnt_ofdm; + u_int32 phy_rx_pd_cck; + u_int32 phy_rx_pd_ofdm; + u_int32 phy_rx_sig_err_cck; + u_int32 phy_rx_sfd_err_cck; + u_int32 phy_rx_sig_err_ofdm; + u_int32 phy_rx_tag_err_ofdm; + u_int32 wb_rssi0; + u_int32 ib_rssi0; + u_int32 wb_rssi1; + u_int32 ib_rssi1; + u_int32 phy_rx_mdrdy_cnt_cck; + u_int32 phy_rx_mdrdy_cnt_ofdm; + u_int32 driver_rx_count; + u_int32 rcpi0; + u_int32 rcpi1; + s_int32 freq_offset_from_rx; + u_int32 rssi0; + u_int32 rssi1; + u_int32 rx_fifo_full; /* out_of_resource */ + u_int32 mac_rx_len_mismatch; + u_int32 mac_rx_fcs_err_cnt_band1; + u_int32 mac_rx_mdrdy_cnt_band1; + u_int32 fagc_ib_RSSSI0; + u_int32 fagc_ib_RSSSI1; + u_int32 fagc_ib_RSSSI2; + u_int32 fagc_ib_RSSSI3; + u_int32 fagc_wb_RSSSI0; + u_int32 fagc_wb_RSSSI1; + u_int32 fagc_wb_RSSSI2; + u_int32 fagc_wb_RSSSI3; + u_int32 inst_ib_RSSSI0; + u_int32 inst_ib_RSSSI1; + u_int32 inst_ib_RSSSI2; + u_int32 inst_ib_RSSSI3; + u_int32 inst_wb_RSSSI0; + u_int32 inst_wb_RSSSI1; + u_int32 inst_wb_RSSSI2; + u_int32 inst_wb_RSSSI3; + u_int32 aci_hit_low; + u_int32 aci_hit_high; + u_int32 driver_rx_count1; + u_int32 rcpi2; + u_int32 rcpi3; + u_int32 rssi2; + u_int32 rssi3; + u_int32 snr0; + u_int32 snr1; + u_int32 snr2; + u_int32 snr3; + u_int32 rx_fifo_full_band1; + u_int32 mac_rx_len_mismatch_band1; + u_int32 phy_rx_pd_cck_band1; + u_int32 phy_rx_pd_ofdm_band1; + u_int32 phy_rx_sig_err_cck_band1; + u_int32 phy_rx_sfd_err_cck_band1; + u_int32 phy_rx_sig_err_ofdm_band1; + u_int32 phy_rx_tag_err_ofdm_band1; + u_int32 phy_rx_mdrdy_cnt_cck_band1; + u_int32 phy_rx_mdrdy_cnt_ofdm_band1; + u_int32 phy_rx_fcs_err_cnt_cck_band1; + u_int32 phy_rx_fcs_err_cnt_ofdm_band1; + u_int32 mu_pkt_count; + u_int32 sig_mcs; + u_int32 sinr; + u_int32 rxv_rssi; + /* u_int32 reserved[184]; */ + u_int32 phy_mdrdy; + u_int32 noise_floor; + u_int32 all_len_mismatch_ch_cnt_band0; + u_int32 all_len_mismatch_ch_cnt_band1; + u_int32 all_mac_mdrdy0; + u_int32 all_mac_mdrdy1; + u_int32 all_fcs_err0; + u_int32 all_fcs_err1; + u_int32 rx_ok0; + u_int32 rx_ok1; + u_int32 per0; + u_int32 per1; +}; + +struct GNU_PACKED hqa_comm_rx_stat { + union { + struct hqa_m_rx_stat r_test_m_hqa_rx_stat; + } u; +}; + +/* Test capability */ +/* VER 0x0001: Init version */ +/* VER 0x0002: Add hw_tx support, channel_band_dbdc */ + +#define GET_CAPABILITY_VER 0x0002 +#define GET_CAPABILITY_TAG_NUM 2 + +/* phy capability */ +#define GET_CAPABILITY_TAG_PHY 1 +#define GET_CAPABILITY_TAG_PHY_LEN 16 + +/* phy capability ext */ +#define GET_CAPABILITY_TAG_PHY_EXT 2 +#define GET_CAPABILITY_TAG_PHY_EXT_LEN 16 + +struct test_capability_ph_cap { + /* header */ + u_int32 tag; /* GET_CAPABILITY_TAG_PHY */ + u_int32 tag_len; /* GET_CAPABILITY_TAG_PHY_LEN */ + + /* content: GET_CAPABILITY_TAG_PHY_LEN */ + + /* BIT0 : 11 a/b/g BIT1: 11n , BIT2: 11ac , BIT3: 11ax */ + u_int32 protocol; + + /* 1:1x1, 2:2x2, ... */ + u_int32 ant_num; + + /* BIT0: DBDC support */ + u_int32 dbdc; + + /* BIT0: TxLDPC , BTI1 : RxLDPC , BIT2: TxSTBC , BIT3: RxSTBC */ + u_int32 coding; + + /* BIT0 : 2.4G BIT1: 5G , BIT2: 6G */ + u_int32 channel_band; + + /* BIT0: BW20, BIT1:BW40, BIT2:BW80, BIT3:BW160, BIT4:BW80+80 */ + u_int32 bandwidth; + + /* BIT0 : Band0 2.4G BIT1: Band1 5G , BIT2: Band0 6G */ + /* BIT16 : Band1 2.4G BIT17: Band1 5G , BIT18: Band1 6G */ + u_int32 channel_band_dbdc; + + u_int32 reserved[9]; +}; + +struct test_capability_ext_cap { + /* header */ + u_int32 tag; /* GET_CAPABILITY_TAG_PHY_EXT */ + u_int32 tag_len; /* GET_CAPABILITY_TAG_PHY_EXT_LEN */ + + /* content: GET_CAPABILITY_TAG_PHY_EXT_LEN */ + + /* BIT0: AntSwap */ + /* BIT1: HW TX support */ + u_int32 feature1; + u_int32 reserved[15]; +}; + +struct test_capability { + u_int32 version; + u_int32 tag_num; + struct test_capability_ph_cap ph_cap; + struct test_capability_ext_cap ext_cap; +}; + +/* Test mps for service */ +struct test_mps_setting { + u_int32 tx_mode; + u_int16 tx_ant; + u_int32 mcs; + u_int32 pkt_len; + u_int32 pkt_cnt; + u_int32 pwr; + u_int32 nss; + u_int32 pkt_bw; +}; + +struct test_mps_cb { + SERV_OS_SPIN_LOCK lock; + u_int32 mps_cnt; + u_int32 stat; + boolean setting_inuse; + u_int32 ref_idx; + struct test_mps_setting *mps_setting; +}; + +/* Test tx time feature parameters */ +struct tx_time_param { + /* The packet transmission time feature enable or disable */ + boolean pkt_tx_time_en; + /* The target packet transmission time */ + u_int32 pkt_tx_time; + /* MPDU length in byte */ + u_int32 pkt_tx_len; + /* MSDU length in bye */ + u_int32 pkt_msdu_len; + u_int32 pkt_hdr_len; + /* count for aggregated MPDU */ + u_int32 pkt_ampdu_cnt; + /* mark as QOS data required */ + u_int8 pkt_need_qos; + /* mark as A-MSDU required */ + u_int8 pkt_need_amsdu; + /* mark as AMPDU equired */ + u_int8 pkt_need_ampdu; +}; + +/* Test ipg feature parameters */ +struct ipg_param { + /* The target idle time */ + u_int32 ipg; + /* Only OFDM/HT/VHT need to consider sig_ext */ + u_int8 sig_ext; + u_int16 slot_time; + u_int16 sifs_time; + /* 0: AC_BK, 1: AC_BE, 2: AC_VI, 3: AC_VO */ + u_int8 ac_num; + u_int8 aifsn; + u_int16 cw; + u_int16 txop; +}; + +/* Test tx power feature parameters */ +struct test_txpwr_param { + u_int32 ant_idx; + u_int32 power; + u_int32 channel; + u_int32 band_idx; + u_int32 ch_band; +}; + +/* Test off channel scan parameters */ +struct test_off_ch_param { + u_int32 ext_id; /* ExtendId of command */ + u_int32 dbdc_idx; /* DBDC index */ + u_int32 mntr_ch; /* Monitoring channel */ + u_int32 is_aband; /* 0: 2.4G channel, 1: 5G channel */ + u_int32 mntr_bw; /* Bandwidth of monitoring channel */ + u_int32 mntr_tx_rx_pth; /* Monitoring TX/RX stream path */ + u_int32 scan_mode; /* ScanStart/ScanRunning/ScanStop */ +}; + +/* Test band state for UI/driver communication */ +struct test_band_state { + /* The single/dual band which UI wants to show */ + u_int32 band_mode; + /* The a/g band type which driver shall configure */ + u_int32 band_type; +}; + +struct test_ru_info { + boolean valid; + u_int32 aid; + u_int32 allocation; + u_int32 ru_index; + u_int32 rate; + u_int32 ldpc; + u_int32 nss; + u_int32 start_sp_st; + u_int32 mpdu_length; + s_int32 alpha; + u_int32 ru_mu_nss; + /* end of user input*/ + u_int32 t_pe; + u_int32 afactor_init; + u_int32 symbol_init; + u_int32 excess; + u_int32 dbps; + u_int32 cbps; + u_int32 dbps_s; + u_int32 cbps_s; + u_int32 pld; + u_int32 avbits; + u_int32 dbps_last; + u_int32 cbps_last; + u_int8 ldpc_extr_sym; + u_int32 tx_time_x5; + u_int8 pe_disamb; + s_int16 punc; + u_int32 l_len; +}; + +struct test_tx_info { + u_int8 tx_mode; + u_int8 bw; + u_int8 stbc; + u_int8 ldpc; + u_int8 ltf; + u_int8 gi; + u_int8 mcs; + u_int8 nss; + u_int8 ibf; + u_int8 ebf; + u_int32 mpdu_length; +}; + +/* Tx stack entry for service */ +struct test_tx_stack { + u_int8 entry_limit; + u_int8 index; + u_int8 q_idx; + u_int16 quota; + u_int8 da[MAX_MULTI_TX_STA][SERV_MAC_ADDR_LEN]; + void *virtual_wtbl[MAX_MULTI_TX_STA]; + void *virtual_device[MAX_MULTI_TX_STA]; + void *pkt_skb[MAX_MULTI_TX_STA]; + struct test_tx_info tx_info[MAX_MULTI_TX_STA]; +}; + +struct test_ru_allocatoin { + /* maximum 8 sub-20MHz for 160/80+80 MHz bandwidth */ + u_int8 sub20[8]; +}; + +/* Test configuration for service */ +struct test_configuration { + /* Test operated mode */ + u_int32 op_mode; + + /* Test packet */ + u_char *test_pkt; /* Buffer for test packet */ + void *pkt_skb; + u_int32 is_alloc_skb; + + /* OS related */ + SERV_OS_COMPLETION tx_wait; + u_char tx_status; /* 0: task idle, 1: task is running */ + + /* Hardware resource */ + void *wdev[2]; + u_char wdev_idx; + u_char wmm_idx; + u_short ac_idx; + + /* Wifi related */ + u_int8 wcid_ref; + + /* Tx frame */ + u_char template_frame[32]; + u_char addr1[MAX_MULTI_TX_STA][SERV_MAC_ADDR_LEN]; + u_char addr2[MAX_MULTI_TX_STA][SERV_MAC_ADDR_LEN]; + u_char addr3[MAX_MULTI_TX_STA][SERV_MAC_ADDR_LEN]; + u_char payload[TEST_MAX_PATTERN_SIZE]; + u_short dur; + u_short seq; + u_short hdr_len; /* Header Length */ + u_int32 pl_len; + u_int32 tx_len; + u_int32 fixed_payload; /* Normal:0,Repeat:1,Random:2 */ + + /* Tx */ + u_int8 tx_strategy; + u_int8 tx_method[TEST_MODE_NUM]; + struct test_tx_stack stack; + struct test_ru_info ru_info_list[MAX_MULTI_TX_STA]; + u_int8 dmnt_ru_idx; + struct test_ru_allocatoin ru_alloc; + u_int8 rate_ctrl_type; + u_int32 duty_cycle; + struct tx_time_param tx_time_param; + struct ipg_param ipg_param; + u_int8 retry; + + /* Rx */ + u_char own_mac[SERV_MAC_ADDR_LEN]; + u_int8 rx_filter_en; + u_int32 rx_filter_pkt_len; + u_int32 mu_rx_aid; + + /* Test Tx statistic */ + boolean txs_enable; + struct test_tx_statistic tx_stat; + + /* Phy */ + u_int8 backup_tx_ant; + u_int16 tx_ant; + u_int8 backup_rx_ant; + u_int16 rx_ant; + u_char channel; + u_char ch_band; + u_char ctrl_ch; + u_int8 pri_sel; + s_int8 ch_offset; + u_char tx_mode; + u_char bw; + u_char per_pkt_bw; + u_char mcs; + u_char nss; + u_char stbc; + u_char ldpc; /* 0:BCC 1:LDPC */ + u_char sgi; + u_char preamble; + u_char fagc_path; + u_char tx_strm_num; /* TX stream number for channel */ + u_char rx_strm_pth; /* RX antenna path for channel */ + u_char backup_channel; + u_char backup_phymode; + u_char channel_2nd; + u_int32 out_band_freq; + u_int32 rf_freq_offset; + u_int32 thermal_val; + u_int8 max_pkt_ext; + u_int64 hetb_rx_csd; + u_int8 user_idx; + + /* Tx power */ + struct test_txpwr_param pwr_param; + s_int8 tx_pwr[TEST_ANT_NUM]; + boolean tx_pwr_sku_en; /* sku on/off status */ + boolean tx_pwr_percentage_en; /* power percentage on/off status */ + boolean tx_pwr_backoff_en; /* backoff on/off status */ + u_int32 tx_pwr_percentage_level; /* tx power percentage level */ + + /* Tx Tone */ + u_int32 tx_tone_en; + u_int32 ant_idx; + u_int32 tone_type; + u_int32 tone_freq; + u_int32 dc_offset_I; + u_int32 dc_offset_Q; + u_int32 rf_pwr; + u_int32 digi_pwr; + + /* Continuous Tx */ + u_int32 ant_mask; + u_int32 rate; + u_int32 tx_fd_mode; + + /* Set Cfg on off */ + u_char log_type; + u_char log_enable; + + /* MPS related */ + struct test_mps_cb mps_cb; + + /*iBF, eBF*/ + u_char ibf; + u_char ebf; + + /* off ch scan */ + struct test_off_ch_param off_ch_param; +}; + +/* Test wlan information for service */ +struct test_wlan_info { + void *os_cookie; /* save specific structure relative to OS */ + struct net_device *net_dev; + u_int32 chip_id; + + /* fw info */ + struct serv_fw_info wm_fw_info; + + /* hdev */ + void *hdev_ctrl; + + /* DBDC */ + boolean dbdc_mode; + + /* Token HW resource */ + u_int32 pkt_tx_tkid_max; + + /* Chip cap */ + struct serv_chip_cap chip_cap; + + /* EEPROM related information */ + boolean use_efuse; + u_char e2p_cur_mode; + u_char e2p_access_mode; + + /*========== gen4m only ==========*/ + /* wlan oid handler */ + wlan_oid_handler_t oid_funcptr; + + /*connsys emi phy memory start addr*/ + phys_addr_t emi_phy_base; + + /*connsys emi total phy memory size*/ + unsigned long long emi_phy_size; + + /* HW Tx on off */ + u_int32 hw_tx_enable; + +}; + +/* Test control register read/write for service */ +struct test_register { + u_int32 cr_addr; + /* For read/write bulk cr usage */ + u_int16 cr_num; + /* Determine size by cr_num */ + u_int32 *cr_val; + /* For rf reg read/write only */ + u_int32 wf_sel; +}; + +/* Test eeprom read/write for service */ +struct test_eeprom { + u_int16 offset; + /* For read/write bulk cr usage */ + u_int16 length; + /* Determine size by length */ + u_int16 *value; + /* For get efuse block count only */ + u_int32 efuse_free_block; +}; + +/* Test operation hook handlers for service */ +struct test_operation { + s_int32 (*op_set_tr_mac)( + struct test_wlan_info *winfos, + s_int32 op_type, boolean enable, u_char band_idx); + s_int32 (*op_set_tx_stream)( + struct test_wlan_info *winfos, + u_int32 stream_nums, u_char band_idx); + s_int32 (*op_set_tx_path)( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs); + s_int32 (*op_set_rx_path)( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs); + s_int32 (*op_set_rx_filter)( + struct test_wlan_info *winfos, + struct rx_filter_ctrl rx_filter); + s_int32 (*op_set_clean_persta_txq)( + struct test_wlan_info *winfos, + boolean sta_pause_enable, u_char wdev_idx, u_char band_idx); + s_int32 (*op_log_on_off)( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 log_type, + u_int32 log_ctrl, + u_int32 log_size); + s_int32 (*op_dbdc_tx_tone)( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs); + s_int32 (*op_dbdc_tx_tone_pwr)( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs); + s_int32 (*op_dbdc_continuous_tx)( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs); + s_int32 (*op_get_tx_info)( + struct test_wlan_info *winfos, + struct test_configuration *test_configs_band0, + struct test_configuration *test_configs_band1); + s_int32 (*op_set_antenna_port)( + struct test_wlan_info *winfos, + u_int8 rf_mode_mask, u_int8 rf_port_mask, + u_int8 ant_port_mask); + s_int32 (*op_set_slot_time)( + struct test_wlan_info *winfos, + u_int8 slot_time, u_int8 sifs_time, + u_int8 rifs_time, u_int16 eifs_time, + u_char band_idx); + s_int32 (*op_set_power_drop_level)( + struct test_wlan_info *winfos, + u_int8 pwr_drop_level, u_char band_idx); + s_int32 (*op_set_rx_filter_pkt_len)( + struct test_wlan_info *winfos, + u_int8 enable, u_char band_idx, u_int32 rx_pkt_len); + s_int32 (*op_get_antswap_capability)( + struct test_wlan_info *winfos, + u_int32 *antswap_support); + s_int32 (*op_set_antswap)( + struct test_wlan_info *winfos, + u_int32 ant); + s_int32 (*op_set_freq_offset)( + struct test_wlan_info *winfos, + u_int32 freq_offset, u_char band_idx); + s_int32 (*op_set_phy_counter)( + struct test_wlan_info *winfos, + s_int32 control, u_char band_idx); + s_int32 (*op_set_rxv_index)( + struct test_wlan_info *winfos, + u_int8 group_1, u_int8 group_2, u_char band_idx); + s_int32 (*op_set_fagc_path)( + struct test_wlan_info *winfos, + u_int8 path, u_char band_idx); + s_int32 (*op_set_fw_mode)( + struct test_wlan_info *winfos, + u_char fw_mode); + s_int32 (*op_set_rf_test_mode)( + struct test_wlan_info *winfos, + u_int32 op_mode, u_int8 icap_len, u_int16 rsp_len); + s_int32 (*op_set_test_mode_start)( + struct test_wlan_info *winfos); + s_int32 (*op_set_test_mode_abort)( + struct test_wlan_info *winfos); + s_int32 (*op_start_tx)( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs); + s_int32 (*op_stop_tx)( + struct test_wlan_info *winfos, + u_char band_idx); + s_int32 (*op_start_rx)( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs); + s_int32 (*op_stop_rx)( + struct test_wlan_info *winfos, + u_char band_idx); + s_int32 (*op_set_channel)( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs); + s_int32 (*op_set_tx_content)( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_configuration *configs); + s_int32 (*op_set_preamble)( + struct test_wlan_info *winfos, + u_char mode); + s_int32 (*op_set_rate)( + struct test_wlan_info *winfos, + u_char mcs); + s_int32 (*op_set_system_bw)( + struct test_wlan_info *winfos, + u_char sys_bw); + s_int32 (*op_set_per_pkt_bw)( + struct test_wlan_info *winfos, + u_char per_pkt_bw); + s_int32 (*op_reset_txrx_counter)( + struct test_wlan_info *winfos); + s_int32 (*op_set_rx_vector_idx)( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 group1, + u_int32 group2); + s_int32 (*op_get_rx_stat_leg)( + struct test_wlan_info *winfos, + struct test_rx_stat_leg *rx_stat); + s_int32 (*op_set_fagc_rssi_path)( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 fagc_path); + s_int32 (*op_get_rx_statistics_all)( + struct test_wlan_info *winfos, + struct hqa_comm_rx_stat *hqa_rx_stat); + s_int32 (*op_get_capability)( + struct test_wlan_info *winfos, + struct test_capability *capability); + s_int32 (*op_calibration_test_mode)( + struct test_wlan_info *winfos, + u_char mode); + s_int32 (*op_set_icap_start)( + struct test_wlan_info *winfos, + u_int8 *data); + s_int32 (*op_get_icap_status)( + struct test_wlan_info *winfos, + s_int32 *icap_stat); + s_int32 (*op_get_icap_max_data_len)( + struct test_wlan_info *winfos, + u_long *max_data_len); + s_int32 (*op_get_icap_data)( + struct test_wlan_info *winfos, + s_int32 *icap_cnt, + s_int32 *icap_data, + u_int32 wf_num, + u_int32 iq_type); + s_int32 (*op_do_cal_item)( + struct test_wlan_info *winfos, + u_int32 item, u_char band_idx); + s_int32 (*op_set_band_mode)( + struct test_wlan_info *winfos, + struct test_band_state *band_state); + s_int32 (*op_get_chipid)( + struct test_wlan_info *winfos); + s_int32 (*op_mps_start)( + struct test_wlan_info *winfos, + u_char band_idx); + s_int32 (*op_mps_set_nss)( + struct test_wlan_info *winfos, + u_int32 len, + struct test_mps_setting *mps_setting); + s_int32 (*op_mps_set_per_packet_bw)( + struct test_wlan_info *winfos, + u_int32 len, + struct test_mps_setting *mps_setting); + s_int32 (*op_mps_set_packet_count)( + struct test_wlan_info *winfos, + u_int32 len, + struct test_mps_setting *mps_setting); + s_int32 (*op_mps_set_payload_length)( + struct test_wlan_info *winfos, + u_int32 len, + struct test_mps_setting *mps_setting); + s_int32 (*op_mps_set_power_gain)( + struct test_wlan_info *winfos, + u_int32 len, + struct test_mps_setting *mps_setting); + s_int32 (*op_mps_set_seq_data)( + struct test_wlan_info *winfos, + u_int32 len, + struct test_mps_setting *mps_setting); + s_int32 (*op_set_tam_arb)( + struct test_wlan_info *winfos, + u_int8 arb_op_mode); + s_int32 (*op_set_muru_manual)( + void *virtual_device, + struct test_wlan_info *winfos, + struct test_configuration *configs); + /* For test phy usage */ + s_int32 (*op_get_tx_pwr)( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx, + u_char channel, + u_char ant_idx, + u_int32 *power); + s_int32 (*op_set_tx_pwr)( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx, + struct test_txpwr_param *pwr_param); + s_int32 (*op_write_mac_bbp_reg)( + struct test_wlan_info *winfos, + struct test_register *regs); + s_int32 (*op_read_bulk_mac_bbp_reg)( + struct test_wlan_info *winfos, + struct test_register *regs); + s_int32 (*op_read_bulk_rf_reg)( + struct test_wlan_info *winfos, + struct test_register *regs); + s_int32 (*op_write_bulk_rf_reg)( + struct test_wlan_info *winfos, + struct test_register *regs); + s_int32 (*op_read_bulk_eeprom)( + struct test_wlan_info *winfos, + struct test_eeprom *eprms); + s_int32 (*op_get_freq_offset)( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 *freq_offset); + s_int32 (*op_get_cfg_on_off)( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 type, + u_int32 *result); + s_int32 (*op_get_tx_tone_pwr)( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 ant_idx, + u_int32 *power); + s_int32 (*op_get_recal_cnt)( + struct test_wlan_info *winfos, + u_int32 *recal_cnt, + u_int32 *recal_dw_num); + s_int32 (*op_get_recal_content)( + struct test_wlan_info *winfos, + u_int32 *content); + s_int32 (*op_get_rdd_content)( + struct test_wlan_info *winfos, + u_int32 *content, + u_int32 *total_cnt); + s_int32 (*op_get_rdd_cnt)( + struct test_wlan_info *winfos, + u_int32 *rdd_cnt, + u_int32 *rdd_dw_num); + s_int32 (*op_get_rxv_cnt)( + struct test_wlan_info *winfos, + u_int32 *rxv_cnt, + u_int32 *rxv_dw_num); + s_int32 (*op_get_rxv_content)( + struct test_wlan_info *winfos, + u_int32 dw_cnt, + u_int32 *content); + s_int32 (*op_get_thermal_val)( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx, + u_int32 *value); + s_int32 (*op_set_cal_bypass)( + struct test_wlan_info *winfos, + u_char band_idx, + u_int32 cal_item); + s_int32 (*op_set_cfg_on_off)( + struct test_wlan_info *winfos, + u_int8 type, u_int8 enable, u_char band_idx); + s_int32 (*op_set_dpd)( + struct test_wlan_info *winfos, + u_int32 on_off, + u_int32 wf_sel); + s_int32 (*op_set_tssi)( + struct test_wlan_info *winfos, + u_int32 on_off, + u_int32 wf_sel); + s_int32 (*op_set_rdd_test)( + struct test_wlan_info *winfos, + u_int32 rdd_idx, + u_int32 rdd_sel, + u_int32 enable); + s_int32 (*op_set_off_ch_scan)( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx, + struct test_off_ch_param *off_ch_param); + s_int32 (*op_get_rx_stat)( + struct test_wlan_info *winfos, + u_char band_idx, + struct test_rx_stat *rx_stat); + s_int32 (*op_hetb_ctrl)( + struct test_wlan_info *winfos, + u_char band_idx, + u_char ctrl_type, + boolean enable, + u_int8 bw, + u_int8 ltf_gi, + u_int8 stbc, + u_int8 pri_ru_idx, + struct test_ru_info *ru_info); + s_int32 (*op_set_ru_aid)( + struct test_wlan_info *winfos, + u_char band_idx, + u_int16 mu_rx_aid); + s_int32 (*op_set_mutb_spe)( + struct test_wlan_info *winfos, + u_char band_idx, + u_char phy_mode, + u_int8 spe_idx); + s_int32 (*op_get_wf_path_comb)( + struct test_wlan_info *winfos, + u_int8 band_idx, + boolean dbdc_mode_en, + u_int8 *path, + u_int8 *path_len); + s_int32 (*op_get_rx_stat_band)( + struct test_wlan_info *winfos, + u_int8 band_idx, + u_int8 blk_idx, + struct test_rx_stat_band_info *rx_st_band); + s_int32 (*op_get_rx_stat_path)( + struct test_wlan_info *winfos, + u_int8 band_idx, + u_int8 blk_idx, + struct test_rx_stat_path_info *rx_st_path); + s_int32 (*op_get_rx_stat_user)( + struct test_wlan_info *winfos, + u_int8 band_idx, + u_int8 blk_idx, + struct test_rx_stat_user_info *rx_st_user); + s_int32 (*op_get_rx_stat_comm)( + struct test_wlan_info *winfos, + u_int8 band_idx, + u_int8 blk_idx, + struct test_rx_stat_comm_info *rx_st_comm); + /* For test mac usage */ + s_int32 (*op_backup_and_set_cr)( + struct test_wlan_info *winfos, + struct test_bk_cr *bks, + u_char band_idx); + s_int32 (*op_restore_cr)( + struct test_wlan_info *winfos, + struct test_bk_cr *bks, + u_char band_idx); + s_int32 (*op_set_ampdu_ba_limit)( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_int8 agg_limit); + s_int32 (*op_set_sta_pause_cr)( + struct test_wlan_info *winfos); + s_int32 (*op_set_ifs_cr)( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx); +}; + + +/* Test tmr for service */ +struct test_tmr_info { + u_int32 setting; + u_int32 version; + u_int32 through_hold; + u_int32 iter; +}; + +/***************************************************************************** + * Function declaration + *****************************************************************************/ +s_int32 net_ad_init_thread( + struct test_wlan_info *winfos, + struct test_configuration *configs, + enum service_thread_list thread_idx); +s_int32 net_ad_release_thread( + u_char thread_idx); +s_int32 net_ad_backup_cr( + struct test_wlan_info *winfos, + struct test_bk_cr *test_bkcr, + u_long offset, enum test_bk_cr_type type); +s_int32 net_ad_restore_cr( + struct test_wlan_info *winfos, + struct test_bk_cr *test_bkcr, + u_long offset); +s_int32 net_ad_cfg_queue( + struct test_wlan_info *winfos, boolean enable); +s_int32 net_ad_enter_normal( + struct test_wlan_info *winfos, + struct test_backup_params *configs); +s_int32 net_ad_exit_normal( + struct test_wlan_info *winfos, + struct test_backup_params *configs); +s_int32 net_ad_update_wdev( + u_int8 band_idx, + struct test_wlan_info *winfos, + struct test_configuration *configs); +s_int32 net_ad_init_wdev( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx); +s_int32 net_ad_release_wdev( + struct test_wlan_info *winfos, + struct test_configuration *configs); +s_int32 net_ad_fill_pkt( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char *buf, u_int32 txlen, u_int32 hlen); +s_int32 net_ad_alloc_pkt( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_int32 mpdu_length, + void **pkt_skb); +s_int32 net_ad_free_pkt( + struct test_wlan_info *winfos, + void *pkt_skb); +s_int32 net_ad_enq_pkt( + struct test_wlan_info *winfos, + u_short q_idx, + void *virtual_wtbl, + void *virtual_device, + void *pkt); +s_int32 net_ad_trigger_tx( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_int8 band_idx, + void *pkt); +s_int32 net_ad_rx_done_handle( + struct test_wlan_info *winfos, + void *rx_blk); +s_int32 net_ad_set_band_mode( + struct test_wlan_info *winfos, + struct test_band_state *band_state); +s_int32 net_ad_set_txpwr_sku( + struct test_wlan_info *winfos, + u_char sku_ctrl, u_char band_idx); +s_int32 net_ad_set_txpwr_power_drop( + struct test_wlan_info *winfos, + u_char power_drop, + u_char band_idx); +s_int32 net_ad_set_txpwr_percentage( + struct test_wlan_info *winfos, + u_char percentage_ctrl, + u_char band_idx); +s_int32 net_ad_set_txpwr_backoff( + struct test_wlan_info *winfos, + u_char backoff_ctrl, u_char band_idx); +s_int32 net_ad_init_txpwr( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx); +s_int32 net_ad_handle_mcs32( + struct test_wlan_info *winfos, + void *virtual_device, u_int8 bw); +s_int32 net_ad_cfg_wtbl( + struct test_wlan_info *winfos, + struct test_configuration *configs); +s_int32 net_ad_set_wmm_param_by_qid( + u_int8 wmm_idx, + u_int8 q_idx, + struct test_wlan_info *winfos, + struct test_configuration *configs); +s_int32 net_ad_clean_sta_q( + struct test_wlan_info *winfos, + u_char wcid); +s_int32 net_ad_set_auto_resp( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx, u_char mode); +s_int32 net_ad_set_low_power( + struct test_wlan_info *winfos, u_int32 control); +s_int32 net_ad_read_mac_bbp_reg( + struct test_wlan_info *winfos, + struct test_register *regs); +s_int32 net_ad_write_mac_bbp_reg( + struct test_wlan_info *winfos, + struct test_register *regs); +s_int32 net_ad_read_bulk_mac_bbp_reg( + struct test_wlan_info *winfos, + struct test_configuration *configs, + struct test_register *regs); +s_int32 net_ad_read_bulk_rf_reg( + struct test_wlan_info *winfos, + struct test_register *regs); +s_int32 net_ad_write_bulk_rf_reg( + struct test_wlan_info *winfos, + struct test_register *regs); +void net_ad_read_ca53_reg(struct test_register *regs); +void net_ad_write_ca53_reg(struct test_register *regs); +s_int32 net_ad_read_write_eeprom( + struct test_wlan_info *winfos, + struct test_eeprom *eprms, + boolean is_read); +s_int32 net_ad_read_write_bulk_eeprom( + struct test_wlan_info *winfos, + struct test_eeprom *eprms, + boolean is_read); +s_int32 net_ad_get_free_efuse_block( + struct test_wlan_info *winfos, + struct test_eeprom *eprms); +s_int32 net_ad_mps_tx_operation( + struct test_wlan_info *winfos, + struct test_configuration *configs, + boolean is_start_tx); +s_int32 net_ad_set_tmr( + struct test_wlan_info *winfos, + struct test_tmr_info *tmr_info); +s_int32 net_ad_get_rxv_stat( + struct test_wlan_info *winfos, + u_char ctrl_band_idx, + struct test_rx_stat *rx_stat + ); +s_int32 net_ad_get_rxv_cnt( + struct test_wlan_info *winfos, + u_char ctrl_band_idx, + u_int32 *byte_cnt); +s_int32 net_ad_get_rxv_content( + struct test_wlan_info *winfos, + u_char ctrl_band_idx, + void *content); + +s_int32 net_ad_alloc_wtbl( + struct test_wlan_info *winfos, + u_char *da, + void *virtual_dev, + void **virtual_wtbl); +s_int32 net_ad_free_wtbl( + struct test_wlan_info *winfos, + u_char *da, + void *virtual_wtbl); +s_int32 net_ad_apply_wtbl( + struct test_wlan_info *winfos, + void *virtual_dev, + void *virtual_wtbl); +s_int32 net_ad_match_wtbl( + void *virtual_wtbl, + u_int16 wcid); +s_int32 net_ad_get_band_idx( + void *virtual_device, + u_char *band_idx); +s_int32 net_ad_get_wmm_idx( + void *virtual_device, + u_int8 *wmm_idx); +s_int32 net_ad_get_omac_idx( + struct test_wlan_info *winfos, + void *virtual_device, + u_char *omac_idx); +s_int32 net_ad_set_aid( + void *virtual_wtbl, + u_int16 aid); +s_int32 net_ad_fill_phy_info( + void *virtual_wtbl, + struct test_tx_info *tx_info); +s_int32 net_ad_fill_spe_antid( + struct test_wlan_info *winfos, + void *virtual_wtbl, + u_int8 spe_idx, + u_int8 ant_pri); +s_int32 net_ad_get_speidx( + struct test_wlan_info *winfos, + u_int16 ant_sel, + u_int8 *spe_idx); +#endif /* __NET_ADAPTION_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/osal/include/sys_adaption.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/osal/include/sys_adaption.h new file mode 100644 index 0000000000000..9382bc8c372f3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/osal/include/sys_adaption.h @@ -0,0 +1,342 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#ifndef __SYS_ADAPTION_H__ +#define __SYS_ADAPTION_H__ + +#include +#include +#include +#include +#include + +/***************************************************************************** + * Type definition + *****************************************************************************/ +#define s_int8 signed char +#define s_int16 signed short +#define s_int32 signed int +#define s_int64 signed long long +#define u_int8 unsigned char +#define u_int16 unsigned short +#define u_int32 unsigned int +#define u_int64 unsigned long long +#define s_char signed char +#define boolean unsigned char + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef GNU_PACKED +#define GNU_PACKED __packed +#endif /* GNU_PACKED */ + +/* Spin lock */ +#define SERV_OS_SPIN_LOCK spinlock_t + +/* Completion */ +#define SERV_OS_COMPLETION struct completion + +/* Service task */ +#define SERV_OS_TASK_NAME_LEN 16 +struct serv_os_task { + char task_name[SERV_OS_TASK_NAME_LEN]; + void *priv_winfos; + void *priv_configs; + unsigned char task_killed; + struct task_struct *kthread_task; + wait_queue_head_t kthread_q; + boolean kthread_running; +}; +typedef s_int32(*SERV_OS_TASK_CALLBACK) (u_long); + +/*gen4m wlan oid call back function*/ +typedef uint32_t (*wlan_oid_handler_t) (void *winfos, + uint32_t oid_type, + void *param, + uint32_t param_len, + uint32_t *rsp_len, + void *rsp_data); + +/***************************************************************************** + * Macro + *****************************************************************************/ +/* Service IP return status */ +/* The first byte means module and the second byte means error status */ +/* Success */ +#define SERV_STATUS_SUCCESS 0x0000 + +/* Agent module: failure */ +#define SERV_STATUS_AGENT_FAIL 0x0100 +/* Agent module: invalid null pointer */ +#define SERV_STATUS_AGENT_INVALID_NULL_POINTER 0x0101 +/* Agent module: invalid band idx */ +#define SERV_STATUS_AGENT_INVALID_BANDIDX 0x0102 +/* Agent module: invalid length */ +#define SERV_STATUS_AGENT_INVALID_LEN 0x0103 +/* Agent module: invalid parameter */ +#define SERV_STATUS_AGENT_INVALID_PARAM 0x0104 +/* Agent module: not supported */ +#define SERV_STATUS_AGENT_NOT_SUPPORTED 0x0105 + +/* Service test module: failure */ +#define SERV_STATUS_SERV_TEST_FAIL 0x0200 +/* Service test module: invalid null pointer */ +#define SERV_STATUS_SERV_TEST_INVALID_NULL_POINTER 0x0201 +/* Service test module: invalid band idx */ +#define SERV_STATUS_SERV_TEST_INVALID_BANDIDX 0x0202 +/* Service test module: invalid length */ +#define SERV_STATUS_SERV_TEST_INVALID_LEN 0x0203 +/* Service test module: invalid parameter */ +#define SERV_STATUS_SERV_TEST_INVALID_PARAM 0x0204 +/* Service test module: not supported */ +#define SERV_STATUS_SERV_TEST_NOT_SUPPORTED 0x0205 + +/* Test engine module: failure */ +#define SERV_STATUS_ENGINE_FAIL 0x0300 +/* Test engine module: invalid null pointer */ +#define SERV_STATUS_ENGINE_INVALID_NULL_POINTER 0x0301 +/* Test engine module: invalid band idx */ +#define SERV_STATUS_ENGINE_INVALID_BANDIDX 0x0302 +/* Test engine module: invalid length */ +#define SERV_STATUS_ENGINE_INVALID_LEN 0x0303 +/* Test engine module: invalid parameter */ +#define SERV_STATUS_ENGINE_INVALID_PARAM 0x0304 +/* Test engine module: not supported */ +#define SERV_STATUS_ENGINE_NOT_SUPPORTED 0x0305 + +/* Hal test mac module: failure */ +#define SERV_STATUS_HAL_MAC_FAIL 0x0400 +/* Hal test mac module: invalid padapter */ +#define SERV_STATUS_HAL_MAC_INVALID_PAD 0x0401 +/* Hal test mac module: invalid null pointer */ +#define SERV_STATUS_HAL_MAC_INVALID_NULL_POINTER 0x0402 +/* Hal test mac module: invalid band idx */ +#define SERV_STATUS_HAL_MAC_INVALID_BANDIDX 0x0403 +/* Hal test mac module: un-registered chip ops */ +#define SERV_STATUS_HAL_MAC_INVALID_CHIPOPS 0x0404 + +/* Hal operation module: failure */ +#define SERV_STATUS_HAL_OP_FAIL 0x0500 +/* Hal operation module: failure to send fw command */ +#define SERV_STATUS_HAL_OP_FAIL_SEND_FWCMD 0x0501 +/* Hal operation module: failure to set mac behavior */ +#define SERV_STATUS_HAL_OP_FAIL_SET_MAC 0x0502 +/* Hal operation module: invalid padapter */ +#define SERV_STATUS_HAL_OP_INVALID_PAD 0x0503 +/* Hal operation module: invalid null pointer */ +#define SERV_STATUS_HAL_OP_INVALID_NULL_POINTER 0x0504 +/* Hal operation module: invalid band idx */ +#define SERV_STATUS_HAL_OP_INVALID_BANDIDX 0x0505 + +/* Osal net adaption module: failure */ +#define SERV_STATUS_OSAL_NET_FAIL 0x0600 +/* Osal net adaption module: failure to send fw command */ +#define SERV_STATUS_OSAL_NET_FAIL_SEND_FWCMD 0x0601 +/* Osal net adaption module: failure to init wdev */ +#define SERV_STATUS_OSAL_NET_FAIL_INIT_WDEV 0x0602 +/* Osal net adaption module: failure to release wdev */ +#define SERV_STATUS_OSAL_NET_FAIL_RELEASE_WDEV 0x0603 +/* Osal net adaption module: failure to update wdev */ +#define SERV_STATUS_OSAL_NET_FAIL_UPDATE_WDEV 0x0604 +/* Osal net adaption module: failure to set channel */ +#define SERV_STATUS_OSAL_NET_FAIL_SET_CHANNEL 0x0605 +/* Osal net adaption module: invalid padapter */ +#define SERV_STATUS_OSAL_NET_INVALID_PAD 0x0606 +/* Osal net adaption module: invalid null pointer */ +#define SERV_STATUS_OSAL_NET_INVALID_NULL_POINTER 0x0607 +/* Osal net adaption module: invalid band idx */ +#define SERV_STATUS_OSAL_NET_INVALID_BANDIDX 0x0608 +/* Osal net adaption module: invalid length */ +#define SERV_STATUS_OSAL_NET_INVALID_LEN 0x0609 +/* Osal net adaption module: invalid parameter */ +#define SERV_STATUS_OSAL_NET_INVALID_PARAM 0x060A + +/* Osal sys adaption module: failure */ +#define SERV_STATUS_OSAL_SYS_FAIL 0x0700 +/* Osal sys adaption module: invalid padapter */ +#define SERV_STATUS_OSAL_SYS_INVALID_PAD 0x0701 +/* Osal sys adaption module: invalid null pointer */ +#define SERV_STATUS_OSAL_SYS_INVALID_NULL_POINTER 0x0702 +/* Osal sys adaption module: invalid band idx */ +#define SERV_STATUS_OSAL_SYS_INVALID_BANDIDX 0x0703 + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +/* Use bitmap to allow coexist of OP_MODE_TXFRAME and OP_MODE_RXFRAME */ +#define fTEST_IDLE (1 << 0) +#define fTEST_TX_ENABLE (1 << 1) +#define fTEST_RX_ENABLE (1 << 2) +#define fTEST_TXCONT_ENABLE (1 << 3) +#define fTEST_TXCARR_ENABLE (1 << 4) +#define fTEST_TXCARRSUPP_ENABLE (1 << 5) +#define fTEST_MPS (1 << 6) +#define fTEST_FFT_ENABLE (1 << 7) +#define fTEST_EXIT (1 << 8) +#define fTEST_IN_RFTEST (1 << 9) +#define fTEST_IN_BF (1 << 10) +#define fTEST_IN_ICAPOVERLAP (1 << 11) + +/* OPMODE */ +#define fTEST_OPER_NORMAL_MODE 0 +#define fTEST_OPER_RFTEST_MODE 1 +#define fTEST_OPER_ICAP_MODE 2 +#define fTEST_OPER_ICAP_OVERLAP 3 +#define fTEST_OPER_WIFI_SPECTRUM 4 + +/* Stop Transmission */ +#define OP_MODE_TXSTOP ((~(fTEST_TX_ENABLE)) \ + &(~(fTEST_TXCONT_ENABLE)) \ + &(~(fTEST_TXCARR_ENABLE)) \ + &(~(fTEST_TXCARRSUPP_ENABLE)) \ + &(~(fTEST_MPS))) +/* Stop Receiving Frames */ +#define OP_MODE_RXSTOP (~(fTEST_RX_ENABLE)) +/* Enter/Reset ATE */ +#define OP_MODE_START (fTEST_IDLE) +/* Stop/Exit ATE */ +#define OP_MODE_STOP (fTEST_EXIT) +/* Continuous Transmit Frames (without time gap) */ +#define OP_MODE_TXCONT ((fTEST_TX_ENABLE) \ + |(fTEST_TXCONT_ENABLE)) +/* Transmit Carrier */ +#define OP_MODE_TXCARR ((fTEST_TX_ENABLE) \ + |(fTEST_TXCARR_ENABLE)) +/* Transmit Carrier Suppression (information without carrier) */ +#define OP_MODE_TXCARRSUPP ((fTEST_TX_ENABLE) \ + |(fTEST_TXCARRSUPP_ENABLE)) +/* Transmit Frames */ +#define OP_MODE_TXFRAME (fTEST_TX_ENABLE) +/* Receive Frames */ +#define OP_MODE_RXFRAME (fTEST_RX_ENABLE) +/* MPS */ +#define OP_MODE_MPS ((fTEST_TX_ENABLE)|(fTEST_MPS)) +/* FFT */ +#define OP_MODE_FFT ((fTEST_FFT_ENABLE)|(fTEST_IN_RFTEST)) + +/* Service debug level */ +#define SERV_DBG_LVL_OFF 0 +#define SERV_DBG_LVL_ERROR 1 +#define SERV_DBG_LVL_WARN 2 +#define SERV_DBG_LVL_TRACE 3 +#define SERV_DBG_LVL_MAX SERV_DBG_LVL_TRACE + +/* Debug category */ +#define SERV_DBG_CAT_MISC 0 /* misc */ +#define SERV_DBG_CAT_TEST 1 /* service test */ +#define SERV_DBG_CAT_ENGN 2 /* service engine */ +#define SERV_DBG_CAT_ADAPT 3 /* service adaption */ +#define SERV_DBG_CAT_ALL SERV_DBG_CAT_MISC +#define SERV_DBG_CAT_EN_ALL_MASK 0xFFFFFFFFu + +/* Debugging and printing related definitions and prototypes */ +#define SERV_PRINT printk +#define SERV_PRINT_MAC(addr) \ + (addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]) + +#define SERV_LOG(category, level, fmt) \ + do { \ + if ((0x1 << category) & (SERV_DBG_CAT_EN_ALL_MASK)) \ + if (level <= SERV_DBG_LVL_WARN) \ + SERV_PRINT fmt; \ + } while (0) + +/* OS task related data structure and definition */ +#define SERV_OS_TASK_GET(__pTask) \ + (__pTask) +#define SERV_OS_TASK_GET_WINFOS(__pTask) \ + ((__pTask)->priv_winfos) +#define SERV_OS_TASK_GET_CONFIGS(__pTask) \ + ((__pTask)->priv_configs) +#define SERV_OS_TASK_IS_KILLED(__pTask) \ + ((__pTask)->task_killed) + +#define SERV_OS_INIT_COMPLETION(__pCompletion) \ + init_completion(__pCompletion) +#define SERV_OS_EXIT_COMPLETION(__pCompletion) \ + complete(__pCompletion) +#define SERV_OS_COMPLETE(__pCompletion) \ + complete(__pCompletion) +#define SERV_OS_WAIT_FOR_COMPLETION_TIMEOUT(__pCompletion, __Timeout) \ + wait_for_completion_timeout(__pCompletion, __Timeout) + +/* Spin_lock enhanced for service spin lock */ +#define SERV_OS_ALLOCATE_SPIN_LOCK(__lock) \ + spin_lock_init((spinlock_t *)(__lock)) +#define SERV_OS_FREE_SPIN_LOCK(lock) \ + do {} while (0) +#define SERV_OS_SEM_LOCK(__lock) \ + spin_lock_bh((spinlock_t *)(__lock)) + +#define SERV_OS_SEM_UNLOCK(__lock) \ + spin_unlock_bh((spinlock_t *)(__lock)) + +/* NTOHS/NTONS/NTOHL/NTONS */ +#define SERV_OS_NTOHS(_val) (ntohs((_val))) +#define SERV_OS_HTONS(_val) (htons((_val))) +#define SERV_OS_NTOHL(_val) (ntohl((_val))) +#define SERV_OS_HTONL(_val) (htonl((_val))) + +/* Service skb packet clone */ +#define SERV_PKT_TO_OSPKT(_p) ((struct sk_buff *)(_p)) +#define SERV_OS_PKT_CLONE(_pkt, _src, _flag) \ + { \ + _src = skb_clone(SERV_PKT_TO_OSPKT(_pkt), _flag); \ + } + +/* Array size */ +#define SERV_ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +/***************************************************************************** + * Enum value definition + *****************************************************************************/ +/* Service thread usage list */ +enum service_thread_list { + SERV_THREAD_TEST = 0, + SERV_THREAD_NUM +}; + +/***************************************************************************** + * Data struct definition + *****************************************************************************/ +/* Service thread cb for test */ +struct test_thread_cb { + boolean is_init; + struct serv_os_task task; + SERV_OS_SPIN_LOCK lock; + u_char service_stat; + s_int32 deq_cnt; + SERV_OS_COMPLETION cmd_done; + u_long cmd_expire; +}; + +/***************************************************************************** + * Function declaration + *****************************************************************************/ +void sys_ad_free_pkt(void *packet); +s_int32 sys_ad_alloc_mem(u_char **mem, u_long size); +void sys_ad_free_mem(void *mem); +void sys_ad_zero_mem(void *ptr, u_long length); +void sys_ad_set_mem(void *ptr, u_long length, u_char value); +void sys_ad_move_mem(void *dest, void *src, u_long length); +s_int32 sys_ad_cmp_mem(void *dest, void *src, u_long length); +s_int32 sys_ad_kill_os_task(struct serv_os_task *task); +s_int32 sys_ad_attach_os_task( + struct serv_os_task *task, SERV_OS_TASK_CALLBACK fn, u_long arg); +s_int32 sys_ad_init_os_task( + struct serv_os_task *task, char *task_name, + void *priv_winfos, void *priv_configs); +boolean sys_ad_wait_os_task( + void *reserved, struct serv_os_task *task, s_int32 *status); +void sys_ad_wakeup_os_task(struct serv_os_task *task); + +void sys_ad_mem_dump32(void *ptr, u_long length); + +#endif /* __SYS_ADAPTION_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/osal/jedi/net_adaption_jedi.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/osal/jedi/net_adaption_jedi.c new file mode 100644 index 0000000000000..5b89f93e1fa9b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/osal/jedi/net_adaption_jedi.c @@ -0,0 +1,3696 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#include "rt_config.h" +#include "net_adaption.h" + +static s_int32 net_ad_open_inf(struct wifi_dev *wdev); +static s_int32 net_ad_close_inf(struct wifi_dev *wdev); +static s_int32 net_ad_enqueue_mlme_pkt( + RTMP_ADAPTER *ad, + void *pkt, + struct wifi_dev *wdev, + u_char q_idx, + boolean is_data_queue); +static s_int32 net_ad_tx_pkt_handle( + RTMP_ADAPTER *ad, + struct wifi_dev *wdev, + struct _TX_BLK *tx_blk); +static s_int32 net_ad_tx( + RTMP_ADAPTER *ad, + struct wifi_dev *wdev, + struct _TX_BLK *tx_blk); + +static struct test_thread_cb g_test_thread[SERV_THREAD_NUM]; +struct test_ant_map test_ant_to_spe_idx_map[] = { + /* All */ + {0x0, 0}, + {0xF, 0}, + /* 1 Ant */ + {0x1, 0}, /* Tx0 */ + {0x2, 1}, /* Tx1 */ + {0x4, 3}, /* Tx2 */ + {0x8, 9}, /* Tx3 */ + /* 2 Ant */ + {0x3, 0}, + {0x5, 2}, + {0x9, 8}, + {0x6, 4}, + {0xA, 6}, + {0xC, 16}, + /* 3 Ant */ + {0x7, 0}, /* 0_1_2 */ + {0xB, 10}, /* 0_1_3 */ + {0xD, 12}, /* 0_2_3 */ + {0xE, 18}, /* 1_2_3 */ +}; + +/***************************************************************************** + * Internal functions + *****************************************************************************/ +static s_int32 net_ad_mps_check_stat( + struct test_wlan_info *winfos, + struct test_configuration *configs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_mps_cb *mps_cb; + struct test_mps_setting *mps_setting; + u_int32 tx_cnt, txed_cnt; + + mps_cb = &configs->mps_cb; + mps_setting = mps_cb->mps_setting; + if (!mps_setting || !mps_cb->mps_cnt) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: mps_cb/mps_setting NULL %p/%p\n", + __func__, mps_cb, mps_setting)); + + ret = SERV_STATUS_OSAL_NET_INVALID_NULL_POINTER; + return ret; + } + + tx_cnt = configs->tx_stat.tx_cnt; + txed_cnt = configs->tx_stat.txed_cnt; + + if ((mps_cb->stat & TEST_MPS_ITEM_RUNNING) + && (txed_cnt >= tx_cnt)) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: mps_idx finished idx=%d, mps_cnt=%d\n", + __func__, mps_cb->ref_idx, mps_cb->mps_cnt)); + SERV_OS_SEM_LOCK(&mps_cb->lock); + mps_cb->stat = 0; + SERV_OS_SEM_UNLOCK(&mps_cb->lock); + + if (mps_cb->ref_idx > mps_cb->mps_cnt) { + configs->op_mode &= ~fTEST_MPS; + mps_cb->setting_inuse = FALSE; + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: mps all finished idx=%d, mps_cnt=%d\n", + __func__, mps_cb->ref_idx, mps_cb->mps_cnt)); + + ret = net_ad_mps_tx_operation(winfos, configs, FALSE); + } + } + + return ret; +} + +static s_int32 net_ad_mps_dump_setting( + struct test_configuration *configs, + u_int16 idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_mps_cb *mps_cb; + struct test_mps_setting *mps_setting; + + mps_cb = &configs->mps_cb; + mps_setting = mps_cb->mps_setting; + if (!mps_setting || !mps_cb->mps_cnt) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: mps_cb/mps_setting NULL %p/%p\n", + __func__, mps_cb, mps_setting)); + + ret = SERV_STATUS_OSAL_NET_INVALID_NULL_POINTER; + return ret; + } + + if (idx == 0xFFFF) { + for (idx = 1; idx <= mps_cb->mps_cnt; idx++) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_OFF, + ("item_idx=%d, phy_mode=%d, ", + idx, mps_setting[idx].tx_mode)); + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_OFF, + ("tx_ant=0x%x, mcs=%d, ", + mps_setting[idx].tx_ant, + mps_setting[idx].mcs)); + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_OFF, + ("pkt_len=%d, pkt_cnt=%d, ", + mps_setting[idx].pkt_len, + mps_setting[idx].pkt_cnt)); + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_OFF, + ("pwr=%d, nss=%d, pkt_bw=%d\n", + mps_setting[idx].pwr, + mps_setting[idx].nss, + mps_setting[idx].pkt_bw)); + + } + } else { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_OFF, + ("item_idx=%d, phy_mode=%d, ", + idx, mps_setting[idx].tx_mode)); + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_OFF, + ("tx_ant=0x%x, mcs=%d, ", + mps_setting[idx].tx_ant, + mps_setting[idx].mcs)); + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_OFF, + ("pkt_len=%d, pkt_cnt=%d, ", + mps_setting[idx].pkt_len, + mps_setting[idx].pkt_cnt)); + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_OFF, + ("pwr=%d, nss=%d, pkt_bw=%d\n", + mps_setting[idx].pwr, + mps_setting[idx].nss, + mps_setting[idx].pkt_bw)); + } + + return ret; +} + +static s_int32 net_ad_mps_load_setting( + struct test_wlan_info *winfos, + struct test_configuration *configs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_mps_cb *mps_cb; + struct test_mps_setting *mps_setting; + u_char *test_pkt; + u_int32 idx, tx_mode, tx_ant, mcs, pwr; + u_int32 pkt_len, pkt_cnt, nss, pkt_bw; + + /* TODO: factor out here for tx power */ +#if 0 + ATE_TXPOWER TxPower; + + os_zero_mem(&TxPower, sizeof(TxPower)); +#endif + + test_pkt = configs->test_pkt; + mps_cb = &configs->mps_cb; + mps_setting = mps_cb->mps_setting; + if (!mps_cb || !mps_setting) + goto err0; + + SERV_OS_SEM_LOCK(&mps_cb->lock); + + if (mps_cb->stat & TEST_MPS_ITEM_RUNNING) + goto err1; + + mps_cb->stat |= TEST_MPS_ITEM_RUNNING; + idx = mps_cb->ref_idx; + + if (idx > mps_cb->mps_cnt) + goto err2; + + tx_mode = mps_setting[idx].tx_mode; + tx_ant = mps_setting[idx].tx_ant; + mcs = mps_setting[idx].mcs; + pwr = mps_setting[idx].pwr; + pkt_len = mps_setting[idx].pkt_len; + pkt_cnt = mps_setting[idx].pkt_cnt; + nss = mps_setting[idx].nss; + pkt_bw = mps_setting[idx].pkt_bw; + configs->tx_mode = tx_mode; + configs->tx_ant = tx_ant; + configs->mcs = mcs; + configs->nss = nss; + configs->per_pkt_bw = pkt_bw; + configs->tx_len = pkt_len; + configs->tx_stat.tx_cnt = pkt_cnt; + configs->tx_stat.tx_done_cnt = 0; + configs->tx_stat.txed_cnt = 0; + + /* TODO: factor out here for tx power */ +#if 0 + ATECtrl->TxPower0 = pwr; + TxPower.Power = pwr; + TxPower.Channel = Channel; + TxPower.Dbdc_idx = band_idx; + TxPower.Band_idx = Ch_Band; + ATECtrl->need_set_pwr = TRUE; +#endif + + SERV_OS_SEM_UNLOCK(&mps_cb->lock); + + /* TODO: factor out here for tx power */ +#if 0 + ret = ate_op->SetTxPower0(pAd, TxPower); +#endif + + /* Here means no need to fill packet first time */ + if (mps_cb->ref_idx != 1) { + ret = net_ad_fill_pkt(winfos, configs, test_pkt, + configs->tx_len, configs->hdr_len); + if (ret) + goto err2; + } + + ret = net_ad_mps_dump_setting(configs, mps_cb->ref_idx); + mps_cb->ref_idx++; + + return ret; + +err2: + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: mps_cb->ref_idx=%d, mps_cnt=%d\n", + __func__, mps_cb->ref_idx, mps_cb->mps_cnt)); +err1: + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: item=%d is running\n", + __func__, mps_cb->ref_idx - 1)); + SERV_OS_SEM_UNLOCK(&mps_cb->lock); + return ret; +err0: + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: mps_cb/mps_setting NULL %p/%p\n", + __func__, mps_cb, mps_setting)); + return ret; +} + +static VOID net_ad_thread_set_service( + struct test_wlan_info *winfos, + u_char band_idx, u_int8 *stat) +{ + u_int8 mask = 0; + + if (IS_TEST_DBDC(winfos) && (band_idx == TEST_DBDC_BAND1)) + mask = 1 << TEST_DBDC_BAND1; + else + mask = 1 << TEST_DBDC_BAND0; + + *stat |= mask; +} + +VOID net_ad_thread_proceed_tx( + struct test_wlan_info *winfos, u_char band_idx) +{ + u_char thread_idx = SERV_THREAD_TEST; + + RTMP_SEM_LOCK(&g_test_thread[thread_idx].lock); + net_ad_thread_set_service(winfos, + band_idx, + &g_test_thread[thread_idx].service_stat); + RTMP_SEM_UNLOCK(&g_test_thread[thread_idx].lock); + sys_ad_wakeup_os_task(&g_test_thread[thread_idx].task); +} + +VOID net_ad_thread_stop_tx(struct test_wlan_info *winfos) +{ +} + +static s_int32 net_ad_thread_handler( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + PQUEUE_HEADER mgmt_swq = NULL; + struct test_configuration *test_config; + struct test_tx_stack *stack = NULL; + struct ipg_param *ipg_param; + struct tx_time_param *tx_time_param; + struct wifi_dev *wdev; + u_int32 op_mode, txed_cnt = 0, tx_cnt = 0, pkt_tx_time, ipg; + s_int32 dequeue_size, multi_users = 0; + u_short q_idx; + u_int8 need_ampdu; + u_char hwq_idx; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + if (winfos->chip_cap.swq_per_band) + mgmt_swq = &ad->mgmt_que[band_idx]; + else + mgmt_swq = &ad->mgmt_que[0]; + test_config = &configs[band_idx]; + stack = &test_config->stack; + op_mode = test_config->op_mode; + q_idx = test_config->ac_idx; + txed_cnt = test_config->tx_stat.txed_cnt; + tx_cnt = test_config->tx_stat.tx_cnt; + ipg_param = &test_config->ipg_param; + tx_time_param = &test_config->tx_time_param; + pkt_tx_time = tx_time_param->pkt_tx_time; + need_ampdu = tx_time_param->pkt_need_ampdu; + ipg = ipg_param->ipg; + wdev = (struct wifi_dev *)configs->stack.virtual_wtbl[0]; + hwq_idx = hif_get_resource_idx(ad->hdev_ctrl, wdev, TX_MGMT, q_idx); + dequeue_size = g_test_thread[SERV_THREAD_TEST].deq_cnt; + + do { + u_long free_num; + +test_thread_dequeue: + free_num = hif_get_tx_resource_free_num(ad->hdev_ctrl, hwq_idx); + +#if 0 + if (multi_users > 0) { + UCHAR *pate_pkt + = TESTMODE_GET_PARAM(pAd, band_idx, test_pkt); + + ate_ctrl->wcid_ref = multi_users; + ret = MT_ATEGenPkt(pAd, pate_pkt, band_idx); + } +#endif + + if (op_mode & OP_MODE_STOP) + break; + + if (!(op_mode & OP_MODE_TXFRAME)) + break; + + if (!free_num) + break; + +round_tx: + if (((pkt_tx_time > 0) || (ipg > 0)) && + (mgmt_swq->Number >= MGMT_QUE_MAX_NUMS)) + break; + + /* For service thread tx packet counter control */ + if (tx_cnt <= txed_cnt) + break; + + if ((pkt_tx_time > 0) && need_ampdu) + q_idx = WMM_AC_BE; + else + q_idx = WMM_AC_BK; + + ret = net_ad_enq_pkt(winfos, + q_idx, + stack->virtual_wtbl[stack->q_idx], + stack->virtual_device[stack->q_idx], + stack->pkt_skb[stack->q_idx]); + if (ret) + break; + + txed_cnt++; + stack->q_idx++; + + if (stack->q_idx == stack->index) + stack->q_idx = 0; + + if (((pkt_tx_time > 0) && need_ampdu) || (ipg > 0)) { + PKT_TOKEN_CB *cb = NULL; + PKT_TOKEN_QUEUE *que = NULL; + u_int32 free_token_cnt, pkt_tx_token_id_max; + + cb = hc_get_ct_cb(winfos->hdev_ctrl); + que = cut_through_get_token_queue_by_band(cb, 0); + free_token_cnt = + cut_through_get_free_token_cnt(que); + pkt_tx_token_id_max = que->pkt_tkid_max; + free_num = hif_get_tx_resource_free_num(ad->hdev_ctrl, + hwq_idx); + + if ((free_token_cnt + > (pkt_tx_token_id_max - TEST_ENQ_PKT_NUM)) + && (free_num > 0) + && (mgmt_swq->Number < MGMT_QUE_MAX_NUMS)) + goto round_tx; + } + + dequeue_size--; + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: band_idx=%u, tx_cnt=%u, txed_cnt=%u, ", + __func__, band_idx, tx_cnt, txed_cnt)); + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("dequeue=%d, multi_user=%d, free=%lu\n", + dequeue_size, multi_users, free_num)); + + if (!dequeue_size) { + multi_users--; + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: dequeue %d finish, multi_user=%d\n", + __func__, dequeue_size, multi_users)); + } else + goto test_thread_dequeue; + } while (multi_users > 0); + + test_config->tx_stat.txed_cnt = txed_cnt; + test_config->tx_stat.tx_cnt = tx_cnt; + + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: band_idx=%d, tx_cnt=%u, txed_cnt=%u, dequeue=%d\n", + __func__, band_idx, tx_cnt, txed_cnt, dequeue_size)); + + return ret; +} + +static s_int32 net_ad_thread_get_band_idx( + struct test_wlan_info *winfos, + u_int8 *stat) +{ + u_int8 mask = 0; + + mask = 1 << TEST_DBDC_BAND0; + + if (*stat & mask) { + *stat &= ~mask; + return TEST_DBDC_BAND0; + } + + mask = 1 << TEST_DBDC_BAND1; + + if (IS_TEST_DBDC(winfos) && (*stat & mask)) { + *stat &= ~mask; + return TEST_DBDC_BAND1; + } + + return -1; +} + +static s_int32 net_ad_thread(u_long context) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct serv_os_task *task = (SERV_OS_TASK *) context; + struct test_wlan_info *winfos = NULL; + struct test_configuration *configs = NULL; + RTMP_ADAPTER *ad = NULL; + u_char thread_idx = SERV_THREAD_TEST; + s_int32 status; + s_int32 band_idx = 0; + u_char service_stat = 0; + + if (!task) + goto err; + + winfos = (struct test_wlan_info *)SERV_OS_TASK_GET_WINFOS(task); + configs = (struct test_configuration *)SERV_OS_TASK_GET_CONFIGS(task); + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + goto err; + + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: init thread_idx %u for band %d\n", + __func__, thread_idx, band_idx)); + SERV_OS_COMPLETE(&g_test_thread[thread_idx].cmd_done); + + while (!SERV_OS_TASK_IS_KILLED(task)) { + if (sys_ad_wait_os_task(NULL, task, &status) == FALSE) { + RTMP_SET_FLAG(ad, fRTMP_ADAPTER_HALT_IN_PROGRESS); + break; + } + + SERV_OS_SEM_LOCK(&g_test_thread[thread_idx].lock); + service_stat = g_test_thread[thread_idx].service_stat; + + do { + if (!service_stat) + break; + + band_idx = net_ad_thread_get_band_idx(winfos, + &service_stat); + + if (band_idx == -1) + break; + + ret = net_ad_thread_handler( + winfos, configs, (u_char)band_idx); + } while (1); + + g_test_thread[thread_idx].service_stat = service_stat; + SERV_OS_SEM_UNLOCK(&g_test_thread[thread_idx].lock); + + if (band_idx == -1) + goto err; + + if (configs->op_mode & fTEST_MPS) { + ret = net_ad_mps_check_stat(winfos, configs); + if (ret) + break; + + ret = net_ad_mps_load_setting(winfos, configs); + if (ret) + break; + } + + schedule(); + + if (ret) + break; + } + +err: + if (ad) + RTMP_CLEAR_FLAG(ad, fRTMP_ADAPTER_HALT_IN_PROGRESS); + + g_test_thread[thread_idx].is_init = FALSE; + + if (ret) + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: abnormal leave err=0x%08x\n", __func__, ret)); + + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: leave\n", __func__)); + + return ret; +} + +static s_int32 net_ad_init_payload( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char *packet, u_int32 len) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + u_int32 policy, pl_len, pos; + u_char *payload; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + policy = configs->fixed_payload; + payload = configs->payload; + pl_len = configs->pl_len; + + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_OFF, + ("%s: len=%d, pl_len=%u, policy=%x\n", + __func__, len, pl_len, policy)); + + if (policy == TEST_RANDOM_PAYLOAD) { + for (pos = 0; pos < len; pos++) + packet[pos] = RandomByte(ad); + + return ret; + } + + if (!payload) + return SERV_STATUS_OSAL_NET_INVALID_NULL_POINTER; + + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_OFF, + ("%s: payload=%x\n", __func__, payload[0])); + + if (pl_len == 0) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: payload length can't be 0!!\n", __func__)); + + return SERV_STATUS_OSAL_NET_INVALID_LEN; + } + + if (policy == TEST_USER_PAYLOAD) { + sys_ad_zero_mem(packet, len); + sys_ad_move_mem(packet, payload, pl_len); + } else if (policy == TEST_FIXED_PAYLOAD) { + for (pos = 0; pos < len; pos += pl_len) + sys_ad_move_mem(&packet[pos], payload, pl_len); + } + + return ret; +} + +static s_int32 net_ad_fill_tmac_info( + RTMP_ADAPTER *ad, + TMAC_INFO *tmac_info, + u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct service_test *serv_test; + struct test_configuration *configs; + struct tx_time_param *tx_time_param; + struct wifi_dev *wdev = NULL; + u_char *addr1 = NULL; + u_char tx_mode, mcs, vht_nss, wmm_idx; + u_int32 ant_sel, pkt_tx_time; + u_int8 need_qos, need_amsdu, need_ampdu; + boolean fgspe; + + /* Note: shall not use ad here */ + serv_test = (struct service_test *)ad->serv.serv_handle; + configs = &serv_test->test_config[band_idx]; + wdev = configs->wdev[0]; + tx_time_param = &configs->tx_time_param; + pkt_tx_time = tx_time_param->pkt_tx_time; + need_qos = tx_time_param->pkt_need_qos; + need_amsdu = tx_time_param->pkt_need_amsdu; + need_ampdu = tx_time_param->pkt_need_ampdu; + + if (!wdev) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: cannot get wdev\n", __func__)); + + return SERV_STATUS_OSAL_NET_INVALID_PARAM; + } + + configs->hdr_len = LENGTH_802_11; + addr1 = configs->addr1[0]; + ant_sel = configs->tx_ant; + tx_mode = configs->tx_mode; + mcs = configs->mcs; + vht_nss = configs->nss; + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: addr1=%02x:%02x:%02x:%02x:%02x:%02x\n", + __func__, SERV_PRINT_MAC(addr1))); + + /* Fill TMAC_INFO */ + sys_ad_zero_mem(tmac_info, sizeof(*tmac_info)); + tmac_info->LongFmt = TRUE; + + if (pkt_tx_time > 0) { + tmac_info->WifiHdrLen = (u_int8)tx_time_param->pkt_hdr_len; + tmac_info->PktLen = (u_int16)tx_time_param->pkt_msdu_len; + tmac_info->NeedTrans = FALSE; + + if (need_qos | need_amsdu | need_ampdu) { + tmac_info->HdrPad = 2; + tmac_info->BmcPkt = FALSE; + tmac_info->UserPriority = 0; + } else { + tmac_info->HdrPad = 0; + tmac_info->BmcPkt = IS_BM_MAC_ADDR(addr1); + tmac_info->UserPriority = 0; + } + } else { + tmac_info->WifiHdrLen = (u_int8)configs->hdr_len; + tmac_info->HdrPad = 0; + tmac_info->PktLen = (u_int16)configs->tx_len; + tmac_info->BmcPkt = IS_BM_MAC_ADDR(addr1); + } + + /* no ack */ + if ((pkt_tx_time > 0) && (need_ampdu)) + tmac_info->bAckRequired = 1; + else + tmac_info->bAckRequired = 0; + + tmac_info->FrmType = FC_TYPE_DATA; + tmac_info->SubType = SUBTYPE_QDATA; + tmac_info->OwnMacIdx = wdev->OmacIdx; + + /* no frag */ + tmac_info->FragIdx = 0; + + /* no protection */ + tmac_info->CipherAlg = 0; + + /* tx path setting */ + tmac_info->VhtNss = vht_nss ? vht_nss : 1; + tmac_info->AntPri = 0; + tmac_info->SpeEn = 0; + + /* timing measure setting */ + if ((ad->pTmrCtrlStruct != NULL) + && (ad->pTmrCtrlStruct->TmrEnable == TMR_INITIATOR)) + tmac_info->TimingMeasure = 1; + + /* band_idx for tx ring choose */ + tmac_info->band_idx = band_idx; + + switch (ant_sel) { + case 0: /* both */ + tmac_info->AntPri = 0; + tmac_info->SpeEn = 1; + break; + + case 1: /* tx0 */ + tmac_info->AntPri = 0; + tmac_info->SpeEn = 0; + break; + + case 2: /* tx1 */ + tmac_info->AntPri = 2; /* b'010 */ + tmac_info->SpeEn = 0; + break; + } + + + /* Need to modify the way of getting wmm_idx */ + wmm_idx = configs->wmm_idx; + tmac_info->WmmSet = wmm_idx; + + if (ant_sel & TEST_ANT_USER_SEL) { + ant_sel &= ~TEST_ANT_USER_SEL; + tmac_info->AntPri = ant_sel; + } else { + s_int32 map_idx; + + for (map_idx = 0; + map_idx < SERV_ARRAY_SIZE(test_ant_to_spe_idx_map); + map_idx++) { + if (ant_sel == + test_ant_to_spe_idx_map[map_idx].ant_sel) + break; + } + + if (map_idx == SERV_ARRAY_SIZE(test_ant_to_spe_idx_map)) + tmac_info->AntPri = 0; + else + tmac_info->AntPri + = test_ant_to_spe_idx_map[map_idx].spe_idx; + } + + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: ant_sel=%x, ant_pri=%x, vht_nss=%x, TxD.VhtNss=%x\n", + __func__, ant_sel, tmac_info->AntPri, + vht_nss, tmac_info->VhtNss)); + + /* Fill transmit setting */ + tmac_info->TxRadioSet.RateCode = mcs; + tmac_info->TxRadioSet.PhyMode = tx_mode; + tmac_info->TxRadioSet.CurrentPerPktBW = configs->per_pkt_bw; + tmac_info->TxRadioSet.ShortGI = configs->sgi; + tmac_info->TxRadioSet.Stbc = configs->stbc; + tmac_info->TxRadioSet.Ldpc = configs->ldpc; + + tmac_info->QueIdx = + asic_get_hwq_from_ac(ad, tmac_info->WmmSet, configs->ac_idx); + + if ((pkt_tx_time > 0) && (need_ampdu)) { + tmac_info->Wcid = configs->wcid_ref; + tmac_info->FixRate = 0; + tmac_info->BaDisable = FALSE; + tmac_info->RemainTxCnt = 1; + } else { + tmac_info->Wcid = 0; + tmac_info->FixRate = 1; + tmac_info->BaDisable = TRUE; + tmac_info->RemainTxCnt = 15; + } + + if (configs->txs_enable) { + tmac_info->TxS2Host = TRUE; + tmac_info->TxS2Mcu = FALSE; + tmac_info->TxSFmt = 1; + } + + if (tx_mode == TEST_MODE_CCK) { + tmac_info->TxRadioSet.Premable = LONG_PREAMBLE; + + if (mcs == MCS_9) { + tmac_info->TxRadioSet.RateCode = 0; + tmac_info->TxRadioSet.Premable = SHORT_PREAMBLE; + } else if (mcs == MCS_10) { + tmac_info->TxRadioSet.RateCode = 1; + tmac_info->TxRadioSet.Premable = SHORT_PREAMBLE; + } else if (mcs == MCS_11) { + tmac_info->TxRadioSet.RateCode = 2; + tmac_info->TxRadioSet.Premable = SHORT_PREAMBLE; + } + } + + tmac_info->Wcid = configs->wcid_ref; + if (tmac_info->AntPri >= 24) + fgspe = TRUE; + else + fgspe = FALSE; + + if ((pkt_tx_time > 0) && (need_ampdu)) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: tmac_info->Wcid/Wmmset/QueIdx=%d/%d/%d\n", + __func__, tmac_info->Wcid, + tmac_info->WmmSet, tmac_info->QueIdx)); + } + + return ret; +} + +static s_int32 net_ad_fill_non_offload_tx_blk( + RTMP_ADAPTER *ad, + struct wifi_dev *wdev, + void *tx_blk) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + PACKET_INFO pkt_info; + void *packet; + TX_BLK *txblk = (TX_BLK *)tx_blk; + + packet = txblk->pPacket; + txblk->Wcid = RTMP_GET_PACKET_WCID(packet); + RTMP_QueryPacketInfo( + packet, &pkt_info, &txblk->pSrcBufHeader, &txblk->SrcBufLen); + + TX_BLK_SET_FLAG(txblk, fTX_CT_WithTxD); + + if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(packet)) + TX_BLK_SET_FLAG(txblk, fTX_bClearEAPFrame); + + if (IS_ASIC_CAP(ad, fASIC_CAP_TX_HDR_TRANS)) { + if ((txblk->TxFrameType == TX_LEGACY_FRAME) + || (txblk->TxFrameType == TX_AMSDU_FRAME) + || (txblk->TxFrameType == TX_MCAST_FRAME)) + TX_BLK_SET_FLAG(txblk, fTX_HDR_TRANS); + } + + txblk->pSrcBufData = txblk->pSrcBufHeader; + + return ret; +} + +static boolean net_ad_fill_offload_tx_blk( + RTMP_ADAPTER *ad, + struct wifi_dev *wdev, + void *tx_blk, + boolean retry) +{ + struct _RTMP_CHIP_CAP *cap = hc_get_chip_cap(ad->hdev_ctrl); + PACKET_INFO pkt_info; + PNDIS_PACKET pPacket; + TX_BLK *txblk = (TX_BLK *)tx_blk; + + pPacket = txblk->pPacket; + txblk->Wcid = RTMP_GET_PACKET_WCID(pPacket); + RTMP_QueryPacketInfo(pPacket, + &pkt_info, + &txblk->pSrcBufHeader, + &txblk->SrcBufLen); + txblk->pSrcBufHeader += cap->TXWISize; + /* Due to testmode allocate size include TXWISize */ + txblk->SrcBufLen -= cap->TXWISize; + + TX_BLK_SET_FLAG(txblk, fTX_CT_WithTxD); + + if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pPacket)) + TX_BLK_SET_FLAG(txblk, fTX_bClearEAPFrame); + + /* testmode data does not support fTX_HDR_TRANS yet + if (IS_ASIC_CAP(pAd, fASIC_CAP_TX_HDR_TRANS)) { + if ((txblk->TxFrameType == TX_LEGACY_FRAME) + || (txblk->TxFrameType == TX_AMSDU_FRAME) + || (txblk->TxFrameType == TX_MCAST_FRAME)) + TX_BLK_SET_FLAG(tx_blk, fTX_HDR_TRANS); + } + */ + + txblk->pSrcBufData = txblk->pSrcBufHeader; + txblk->wmm_set = HcGetWmmIdx(ad, wdev); + + if (retry) + TX_BLK_SET_FLAG(txblk, fTX_bRetryUnlimit); + else + TX_BLK_SET_FLAG(txblk, fTX_bNoRetry); + + txblk->UserPriority = 0; + + /* no frag */ + txblk->FragIdx = 0; + /* no protection */ + SET_CIPHER_NONE(txblk->CipherAlg); + return TRUE; +} + +/***************************************************************************** + * Extern functions + *****************************************************************************/ +struct service_test *net_ad_wrap_service(void *adapter) +{ + struct _RTMP_ADAPTER *ad = (struct _RTMP_ADAPTER *)adapter; + struct service *serv = &ad->serv; + + return (struct service_test *)serv->serv_handle; +} + +struct wifi_dev_ops serv_wdev_ops = { + .open = net_ad_open_inf, + .close = net_ad_close_inf, + .send_mlme_pkt = net_ad_enqueue_mlme_pkt, + .tx_pkt_handle = net_ad_tx_pkt_handle, + .ate_tx = net_ad_tx, + .disconn_act = wifi_sys_disconn_act +}; + +s_int32 net_ad_open_inf(struct wifi_dev *wdev) +{ + struct _RTMP_ADAPTER *ad = (struct _RTMP_ADAPTER *)wdev->sys_handle; + +#ifdef RELEASE_EXCLUDE + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_OFF, + ("%s --->\n", __func__)); +#endif /* RELEASE_EXCLUDE */ + + if (wifi_sys_open(wdev) != TRUE) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_OFF, + ("%s: open fail!!!\n", __func__)); + return FALSE; + } + + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_OFF, + ("%s: inf up for ra_%x(func_idx) OmacIdx=%d\n", + __func__, wdev->func_idx, wdev->OmacIdx)); + + MlmeRadioOn(ad, wdev); + + wdev->bAllowBeaconing = FALSE; + +#ifdef RELEASE_EXCLUDE + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_OFF, + ("%s <---\n", __func__)); +#endif /* RELEASE_EXCLUDE */ + + return TRUE; +} + +s_int32 net_ad_close_inf(struct wifi_dev *wdev) +{ + struct _RTMP_ADAPTER *ad = (struct _RTMP_ADAPTER *)wdev->sys_handle; + +#ifdef RELEASE_EXCLUDE + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_OFF, + ("%s --->\n", __func__)); +#endif /* RELEASE_EXCLUDE */ + + if (ad == NULL) + return FALSE; + + if (wifi_sys_close(wdev) != TRUE) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: close fail!!!\n", __func__)); + return FALSE; + } + +#ifdef RELEASE_EXCLUDE + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_OFF, + ("%s <---\n", __func__)); +#endif /* RELEASE_EXCLUDE */ + + return TRUE; +} + +s_int32 net_ad_enqueue_mlme_pkt( + RTMP_ADAPTER *ad, + void *pkt, + struct wifi_dev *wdev, + u_char q_idx, + boolean is_data_queue) +{ + s_int32 ret; + struct qm_ops *ops = ad->qm_ops; + + RTMP_SET_PACKET_MGMT_PKT(pkt, 1); + + ret = ops->enq_mgmtq_pkt(ad, wdev, pkt); + + return ret; +} + +s_int32 net_ad_tx_pkt_handle( + RTMP_ADAPTER *ad, + struct wifi_dev *wdev, + struct _TX_BLK *tx_blk) +{ + struct wifi_dev_ops *ops = NULL; + s_int32 ret = NDIS_STATUS_SUCCESS; + + if (!wdev) { + RELEASE_NDIS_PACKET(ad, tx_blk->pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } + + ops = wdev->wdev_ops; + ret = ops->ate_tx(ad, wdev, tx_blk); + + return ret; +} + +s_int32 net_ad_tx( + RTMP_ADAPTER *ad, + struct wifi_dev *wdev, + struct _TX_BLK *tx_blk) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + TMAC_INFO tmac_info; + PQUEUE_ENTRY q_entry; + RTMP_ARCH_OP *arch_ops = hc_get_arch_ops(ad->hdev_ctrl); + u_int32 band_idx = HcGetBandByWdev(wdev); + + q_entry = RemoveHeadQueue(&tx_blk->TxPacketList); + tx_blk->pPacket = QUEUE_ENTRY_TO_PACKET(q_entry); + RTMP_SET_PACKET_WCID(tx_blk->pPacket, 0); + + /* Fill tx blk for test mode */ + ret = net_ad_fill_non_offload_tx_blk(ad, wdev, tx_blk); + + /* TMAC_INFO setup for test mode */ + ret = net_ad_fill_tmac_info(ad, &tmac_info, band_idx); + if (ret) + return ret; + + return arch_ops->ate_hw_tx(ad, &tmac_info, tx_blk); +} + +s_int32 net_ad_tx_v2( + struct _RTMP_ADAPTER *ad, + struct wifi_dev *wdev, + struct _TX_BLK *tx_blk) +{ + u_int8 band_idx = 0, need_ampdu = 0, need_amsdu = 0; + s_int32 ret = 0; + PQUEUE_ENTRY q_entry; + RTMP_ARCH_OP *arch_ops = hc_get_arch_ops(ad->hdev_ctrl); + struct service_test *serv_test = NULL; + struct test_configuration *configs = NULL; + struct tx_time_param *tx_time_settings = NULL; + + serv_test = (struct service_test *)ad->serv.serv_handle; + q_entry = RemoveHeadQueue(&tx_blk->TxPacketList); + tx_blk->pPacket = QUEUE_ENTRY_TO_PACKET(q_entry); + + band_idx = HcGetBandByWdev(wdev); + configs = &serv_test->test_config[band_idx]; + tx_time_settings = &configs->tx_time_param; + need_ampdu = tx_time_settings->pkt_need_ampdu; + need_amsdu = tx_time_settings->pkt_need_amsdu; + + if (tx_time_settings->pkt_need_qos) { + tx_blk->wifi_hdr_len = (UINT8) tx_time_settings->pkt_hdr_len; + tx_blk->MpduHeaderLen = (UINT8) tx_time_settings->pkt_hdr_len; + } else { + tx_blk->wifi_hdr_len = (UINT8) LENGTH_802_11; + tx_blk->MpduHeaderLen = (UINT8) LENGTH_802_11; + } + + if (need_ampdu) { + TX_BLK_CLEAR_FLAG(tx_blk, fTX_ForceRate); + TX_BLK_SET_FLAG(tx_blk, fTX_bAckRequired); + TX_BLK_SET_FLAG(tx_blk, fTX_bAteAgg); + tx_blk->HdrPadLen = 2; + } else { + TX_BLK_SET_FLAG(tx_blk, fTX_ForceRate); + TX_BLK_CLEAR_FLAG(tx_blk, fTX_bAckRequired); + tx_blk->HdrPadLen = 0; + } + + /* Fill TX blk for ATE mode */ + if (configs->tx_mode == TEST_MODE_HE_MU && configs->retry) + ret = net_ad_fill_offload_tx_blk(ad, wdev, tx_blk, TRUE); + else + ret = net_ad_fill_offload_tx_blk(ad, wdev, tx_blk, FALSE); + + tx_blk->QueIdx = configs->ac_idx; + if (mt_engine_search_stack(configs, + RTMP_GET_PACKET_WCID(tx_blk->pPacket), + (void **)&tx_blk->pMacEntry) != SERV_STATUS_SUCCESS) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: wcid:%d is in-valid in stack!\n", __func__, + RTMP_GET_PACKET_WCID(tx_blk->pPacket))); + + return NDIS_STATUS_FAILURE; + } +#if defined(CONFIG_AP_SUPPORT) + if (tx_blk->pMacEntry) + tx_blk->pMbss = tx_blk->pMacEntry->pMbss; +#endif + if (configs->txs_enable) + TX_BLK_SET_FLAG(tx_blk, fTX_bAteTxsRequired); + + return arch_ops->hw_tx(ad, tx_blk); +} + +s_int32 net_ad_init_thread( + struct test_wlan_info *winfos, + struct test_configuration *configs, + enum service_thread_list thread_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + /* Init test_thread_cb */ + if (thread_idx == SERV_THREAD_TEST) { + g_test_thread[thread_idx].deq_cnt = 1; + g_test_thread[thread_idx].cmd_expire = RTMPMsecsToJiffies(3000); + SERV_OS_INIT_COMPLETION(&g_test_thread[thread_idx].cmd_done); + + if (!g_test_thread[thread_idx].is_init) { + ret = sys_ad_init_os_task( + &g_test_thread[thread_idx].task, + "serv_thread_tx", + (VOID *)winfos, + (VOID *)configs); + if (ret) + goto err; + + NdisAllocateSpinLock( + ad, &g_test_thread[thread_idx].lock); + + ret = sys_ad_attach_os_task( + &g_test_thread[thread_idx].task, + net_ad_thread, + (ULONG)&g_test_thread[thread_idx].task); + + if (!RTMP_OS_WAIT_FOR_COMPLETION_TIMEOUT + (&g_test_thread[thread_idx].cmd_done, + g_test_thread[thread_idx].cmd_expire)) + goto err; + + if (ret) + goto err; + + g_test_thread[thread_idx].is_init = TRUE; + } + + g_test_thread[thread_idx].service_stat = 0; + } + + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_OFF, + ("%s: initialize thread_idx=%d\n", __func__, thread_idx)); + + return ret; + +err: + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: tx thread init fail err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 net_ad_release_thread( + u_char thread_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + if (&g_test_thread[thread_idx].task) + ret = sys_ad_kill_os_task(&g_test_thread[thread_idx].task); + + if (ret != SERV_STATUS_SUCCESS) + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("kill test mode tx task failed!\n")); + else + g_test_thread[thread_idx].is_init = FALSE; + + NdisFreeSpinLock(&g_test_thread[thread_idx].lock); + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_OFF, + ("%s: release thread_idx=%d\n", __func__, thread_idx)); + + return ret; +} + +s_int32 net_ad_backup_cr( + struct test_wlan_info *winfos, + struct test_bk_cr *test_bkcr, + u_long offset, enum test_bk_cr_type type) +{ + struct test_bk_cr *entry = NULL; + RTMP_ADAPTER *ad = NULL; + u_int32 entry_idx; + + if ((type >= SERV_TEST_BKCR_TYPE_NUM) + || (type == SERV_TEST_EMPTY_BKCR)) + return SERV_STATUS_OSAL_NET_FAIL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + for (entry_idx = 0; entry_idx < TEST_MAX_BKCR_NUM; entry_idx++) { + struct test_bk_cr *tmp = &test_bkcr[entry_idx]; + + if ((tmp->type == SERV_TEST_EMPTY_BKCR) && (entry == NULL)) { + entry = tmp; + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: find empty bk entry %d\n", + __func__, entry_idx)); + } else if ((tmp->type == type) && (tmp->offset == offset)) { + entry = tmp; + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: update bk entry %d\n", + __func__, entry_idx)); + break; + } + } + + if (!entry) + return SERV_STATUS_OSAL_NET_FAIL; + + entry->type = type; + entry->offset = offset; + + switch (type) { + case SERV_TEST_MAC_BKCR: + MAC_IO_READ32(ad->hdev_ctrl, offset, &entry->val); + break; + + case SERV_TEST_HIF_BKCR: + HIF_IO_READ32(ad->hdev_ctrl, offset, &entry->val); + break; + + case SERV_TEST_PHY_BKCR: + PHY_IO_READ32(ad->hdev_ctrl, offset, &entry->val); + break; + + case SERV_TEST_HW_BKCR: + HW_IO_READ32(ad->hdev_ctrl, offset, &entry->val); + break; + + case SERV_TEST_MCU_BKCR: + MCU_IO_READ32(ad->hdev_ctrl, offset, &entry->val); + break; + + default: + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_WARN, + ("%s: bk-type not supported\n", __func__)); + entry->type = SERV_TEST_EMPTY_BKCR; + entry->offset = 0; + break; + } + + return SERV_STATUS_SUCCESS; +} + +s_int32 net_ad_restore_cr( + struct test_wlan_info *winfos, + struct test_bk_cr *test_bkcr, + u_long offset) +{ + struct test_bk_cr *entry = NULL; + RTMP_ADAPTER *ad = NULL; + u_int32 entry_idx; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + for (entry_idx = 0; entry_idx < TEST_MAX_BKCR_NUM; entry_idx++) { + struct test_bk_cr *tmp = &test_bkcr[entry_idx]; + + if (tmp->offset == offset) { + entry = tmp; + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: find entry %d\n", __func__, entry_idx)); + break; + } + } + + if (!entry) + return SERV_STATUS_OSAL_NET_FAIL; + + switch (entry->type) { + case SERV_TEST_MAC_BKCR: + MAC_IO_WRITE32(ad->hdev_ctrl, offset, entry->val); + break; + + case SERV_TEST_HIF_BKCR: + HIF_IO_WRITE32(ad->hdev_ctrl, offset, entry->val); + break; + + case SERV_TEST_PHY_BKCR: + PHY_IO_WRITE32(ad->hdev_ctrl, offset, entry->val); + break; + + case SERV_TEST_HW_BKCR: + HW_IO_WRITE32(ad->hdev_ctrl, offset, entry->val); + break; + + case SERV_TEST_MCU_BKCR: + MCU_IO_WRITE32(ad->hdev_ctrl, offset, entry->val); + break; + + default: + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_WARN, + ("%s: bk-type not supported\n", __func__)); + entry->type = SERV_TEST_EMPTY_BKCR; + entry->offset = 0; + break; + } + + entry->type = SERV_TEST_EMPTY_BKCR; + entry->offset = 0; + entry->val = 0; + + return SERV_STATUS_SUCCESS; +} + +s_int32 net_ad_cfg_queue( + struct test_wlan_info *winfos, boolean enable) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; +#ifdef CONFIG_AP_SUPPORT + s_int32 bss_id, max_num_bss; +#endif /* CONFIG_AP_SUPPROT */ + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + +#ifdef CONFIG_AP_SUPPORT + max_num_bss = ad->ApCfg.BssidNum; +#endif + + if (enable) { + /* Start DMA */ + chip_set_hif_dma(ad, DMA_TX_RX, TRUE); + + /* Start to deq sw queue */ + RTMP_CLEAR_FLAG(ad, fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET); + + /* Start tcp/ip layer queue */ + RTMP_OS_NETDEV_START_QUEUE(ad->net_dev); +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(ad) { + if (max_num_bss > MAX_MBSSID_NUM(ad)) + max_num_bss = MAX_MBSSID_NUM(ad); + + for (bss_id = FIRST_MBSSID; + bss_id < MAX_MBSSID_NUM(ad); bss_id++) { + if (ad->ApCfg.MBSSID[bss_id].wdev.if_dev) + RTMP_OS_NETDEV_START_QUEUE( + ad->ApCfg.MBSSID[bss_id].wdev.if_dev); + } + } +#endif /* CONFIG_AP_SUPPROT */ + } else { + /* Stop tcp/ip layer queue */ + RTMP_OS_NETDEV_STOP_QUEUE(ad->net_dev); +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(ad) { + if (max_num_bss > MAX_MBSSID_NUM(ad)) + max_num_bss = MAX_MBSSID_NUM(ad); + + for (bss_id = FIRST_MBSSID; + bss_id < MAX_MBSSID_NUM(ad); bss_id++) { + if (ad->ApCfg.MBSSID[bss_id].wdev.if_dev) + RTMP_OS_NETDEV_STOP_QUEUE( + ad->ApCfg.MBSSID[bss_id].wdev.if_dev); + } + } +#endif /* CONFIG_AP_SUPPROT */ + /* Stop to deq sw queue */ + RTMP_SET_FLAG(ad, fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET); + + /* Stop DMA */ + chip_set_hif_dma(ad, DMA_TX_RX, FALSE); + } + + return ret; +} + +s_int32 net_ad_startup_ap( + struct test_wlan_info *winfos) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; +#ifdef CONFIG_AP_SUPPORT + BSS_STRUCT *mbss = NULL; +#endif /* CONFIG_AP_SUPPROT */ + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + +#ifdef CONFIG_AP_SUPPORT + mbss = &ad->ApCfg.MBSSID[MAIN_MBSSID]; +#endif /* CONFIG_AP_SUPPROT */ + + ret = NICInitializeAdapter(ad); + if (ret != NDIS_STATUS_SUCCESS) + return SERV_STATUS_OSAL_NET_FAIL; + + RTMPSetTimer(&ad->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV); + +#ifdef CONFIG_AP_SUPPORT + APStartUp(ad, mbss, AP_BSS_OPER_ALL); +#endif /* CONFIG_AP_SUPPROT */ + + /* Start tx path queues */ + ret = net_ad_cfg_queue(winfos, TRUE); + + return ret; +} + +s_int32 net_ad_stop_ap( + struct test_wlan_info *winfos) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + boolean cancelled; +#ifdef CONFIG_AP_SUPPORT + s_int32 bss_id, max_num_bss; + BSS_STRUCT *mbss = NULL; +#endif + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + +#ifdef CONFIG_AP_SUPPORT + max_num_bss = ad->ApCfg.BssidNum; + mbss = &ad->ApCfg.MBSSID[MAIN_MBSSID]; +#endif + + /* Stop tx path queues */ + ret = net_ad_cfg_queue(winfos, FALSE); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(ad) { + if (max_num_bss > MAX_MBSSID_NUM(ad)) + max_num_bss = MAX_MBSSID_NUM(ad); + + /* First IdBss must not be 0 (BSS0), must be 1 (BSS1) */ + for (bss_id = FIRST_MBSSID; + bss_id < MAX_MBSSID_NUM(ad); bss_id++) { + if (ad->ApCfg.MBSSID[bss_id].wdev.if_dev) + ad->ApCfg.MBSSID[bss_id].wdev.protection = 0; + } + } +#endif + chip_set_hif_dma(ad, DMA_TX_RX, TRUE); +#ifdef CONFIG_AP_SUPPORT + APStop(ad, mbss, AP_BSS_OPER_ALL); +#endif /* CONFIG_AP_SUPPORT */ + RTMP_CLEAR_FLAG(ad, fRTMP_ADAPTER_HALT_IN_PROGRESS); + + RTMPCancelTimer(&ad->Mlme.PeriodicTimer, &cancelled); + RTMP_SET_FLAG(ad, fRTMP_ADAPTER_SYSEM_READY); + + return ret; +} + +s_int32 net_ad_enter_normal( + struct test_wlan_info *winfos, + struct test_backup_params *bak) +{ + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + ad->CommonCfg.bEnableTxBurst = bak->en_tx_burst; + ad->CommonCfg.BeaconPeriod = bak->bcn_prd; + net_ad_startup_ap(winfos); + ad->CommonCfg.bBssCoexEnable = bak->en_bss_coex; + + return SERV_STATUS_SUCCESS; +} + +s_int32 net_ad_exit_normal( + struct test_wlan_info *winfos, + struct test_backup_params *bak) +{ + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + net_ad_stop_ap(winfos); + + bak->en_tx_burst = ad->CommonCfg.bEnableTxBurst; + ad->CommonCfg.bEnableTxBurst = FALSE; + bak->en_bss_coex = ad->CommonCfg.bBssCoexEnable; + /* To prevent BSS scan occupy execution time */ + ad->CommonCfg.bBssCoexEnable = FALSE; + bak->bcn_prd = ad->CommonCfg.BeaconPeriod; + /* To disable TBTT interrupt */ + ad->CommonCfg.BeaconPeriod = 0; + + return SERV_STATUS_SUCCESS; +} + +s_int32 net_ad_update_wdev( + u_int8 band_idx, + struct test_wlan_info *winfos, + struct test_configuration *configs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct wifi_dev *wdev = NULL; +#if defined(DOT11_HE_AX) + struct wifi_dev *wdev_txd = NULL; +#endif + RTMP_ADAPTER *ad = NULL; + u_char ch_band; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + /* To update wdev setting according to ch_band */ +#if defined(DOT11_HE_AX) + wdev_txd = (struct wifi_dev *)configs->wdev[1]; + + if (!wdev_txd) + goto err; + + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_OFF, + ("%s: wdev_idx(txd)=%d, ch=%d\n", + __func__, wdev_txd->wdev_idx, wdev_txd->channel)); + + HcReleaseRadioForWdev(ad, wdev_txd); +#endif /* DOT11_HE_AX */ + wdev = (struct wifi_dev *)configs->wdev[0]; + + if (!wdev) + goto err; + + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_OFF, + ("%s: wdev_idx=%d, ch=%d\n", + __func__, wdev->wdev_idx, wdev->channel)); + + HcReleaseRadioForWdev(ad, wdev); + +/* #ifdef DBDC_MODE */ +#if 1 + if (IS_MT7915(ad) && IS_TEST_DBDC(winfos)) { + u_int8 rx_sel = (configs->rx_ant & 0x3); + + if (band_idx == DBDC_BAND0) + ad->dbdc_band0_rx_path = rx_sel; + else + ad->dbdc_band1_rx_path = rx_sel; + } else +#endif /* DBDC_MODE */ + { + ad->Antenna.field.TxPath = configs->tx_ant; + ad->Antenna.field.RxPath = configs->rx_ant; + } + + ch_band = configs->ch_band; + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_OFF, + ("%s: ch_band=%d\n", __func__, ch_band)); + + if (ch_band == 0) + wdev->PhyMode = PHYMODE_CAP_24G; + else + wdev->PhyMode = PHYMODE_CAP_5G; +#if defined(DOT11_HE_AX) + if (ch_band == 0) + wdev_txd->PhyMode = PHYMODE_CAP_24G; + else + wdev_txd->PhyMode = PHYMODE_CAP_5G; +#endif + /* + * QA mode used central ch, + * thus wdev ch set as qa mode's control ch of relating bw setting + */ + wdev->channel = configs->ctrl_ch; + wlan_config_set_ch_band(wdev, ch_band); + wlan_config_set_tx_stream(wdev, configs->tx_ant); + wlan_config_set_rx_stream(wdev, configs->rx_ant); + wlan_config_set_ht_bw(wdev, + ((configs->bw > TEST_BW_20) ? HT_BW_40 : HT_BW_20)); + wlan_config_set_ext_cha(wdev, configs->ch_offset); + wlan_config_set_cen_ch_2(wdev, configs->channel_2nd); + if (configs->bw > TEST_BW_5) + wlan_config_set_vht_bw(wdev, + (VHT_BW_80+(configs->bw-TEST_BW_5))); + else + wlan_config_set_vht_bw(wdev, + ((configs->bw > TEST_BW_40) ? + (VHT_BW_80+(configs->bw-BW_80)) : VHT_BW_2040)); +#if defined(DOT11_HE_AX) + if (configs->per_pkt_bw > TEST_BW_80) + wlan_config_set_ap_bw(wdev, VHT_BW_160); + else + wlan_config_set_ap_bw(wdev, configs->per_pkt_bw); + wlan_config_set_ap_cen(wdev, configs->channel-configs->ch_offset); +#endif /* DOT11_HE_AX */ + + if (wdev_attr_update(ad, wdev) != TRUE) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: error to update wdev\n", __func__)); + goto err; + } + + if (wdev_edca_acquire(ad, wdev) != TRUE) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: error to acquire edca\n", __func__)); + goto err; + } + +#if defined(DOT11_HE_AX) + wdev_txd->channel = configs->ctrl_ch; + + wlan_config_set_ch_band(wdev_txd, ch_band); + wlan_config_set_tx_stream(wdev_txd, configs->tx_ant); + wlan_config_set_rx_stream(wdev_txd, configs->rx_ant); + wlan_config_set_ht_bw(wdev_txd, + ((configs->bw > TEST_BW_20) ? HT_BW_40 : HT_BW_20)); + wlan_config_set_ext_cha(wdev_txd, configs->ch_offset); + wlan_config_set_cen_ch_2(wdev_txd, configs->channel_2nd); + if (configs->bw > TEST_BW_5) + wlan_config_set_vht_bw(wdev_txd, + (VHT_BW_80+(configs->bw-TEST_BW_5))); + else + wlan_config_set_vht_bw(wdev_txd, + ((configs->bw > TEST_BW_40) ? + (VHT_BW_80+(configs->bw-BW_80)) : VHT_BW_2040)); + if (configs->per_pkt_bw > TEST_BW_80) + wlan_config_set_ap_bw(wdev, VHT_BW_160); + else + wlan_config_set_ap_bw(wdev_txd, configs->per_pkt_bw); + wlan_config_set_ap_cen(wdev_txd, configs->channel-configs->ch_offset); + + if (wdev_attr_update(ad, wdev_txd) != TRUE) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: error to update wdev\n", __func__)); + goto err; + } + + if (wdev_edca_acquire(ad, wdev_txd) != TRUE) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: error to acquire edca\n", __func__)); + goto err; + } +#endif + + return ret; + +err: + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: updats wdev failed!\n", __func__)); + + return SERV_STATUS_OSAL_NET_FAIL_UPDATE_WDEV; +} + +s_int32 net_ad_init_wdev( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct wifi_dev *wdev = NULL; + RTMP_ADAPTER *ad = NULL; + u_char *own_mac_addr = NULL, *bssid = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + /* To init wdev */ + wdev = (struct wifi_dev *)configs->wdev[0]; + + if (wdev_init(ad, wdev, WDEV_TYPE_SERVICE_TXD, + ad->wdev_list[band_idx]->if_dev, + band_idx, NULL, (void *)ad) != TRUE) + goto err; + + if (!wdev) + return SERV_STATUS_OSAL_NET_INVALID_PARAM; + + if (IS_AXE(ad) || IS_MT7915(ad)) + serv_wdev_ops.ate_tx = net_ad_tx_v2; + + if (wdev_ops_register(wdev, WDEV_TYPE_SERVICE_TXD, &serv_wdev_ops, 0) + != TRUE) + goto err; + + configs->wdev_idx = wdev->wdev_idx; + wdev->channel = configs->channel; + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_OFF, + ("%s: wdev_idx=%d, channel=%d\n", + __func__, wdev->wdev_idx, wdev->channel)); + + if (wdev->channel > 14) + wdev->PhyMode = PHYMODE_CAP_5G; + else + wdev->PhyMode = PHYMODE_CAP_24G; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(ad) + own_mac_addr = (u_char *)&configs->addr3[0]; + +#endif +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(ad) + own_mac_addr = (u_char *)&configs->addr2[0]; +#endif + sys_ad_move_mem(wdev->if_addr, own_mac_addr, SERV_MAC_ADDR_LEN); + + if (wdev_do_open(wdev) != TRUE) + goto err; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(ad) + bssid = (u_char *)&configs->addr2[0]; + +#endif +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(ad) + bssid = (u_char *)&configs->addr1[0]; +#endif + sys_ad_move_mem(wdev->bssid, bssid, SERV_MAC_ADDR_LEN); + + if (wifi_sys_linkup(wdev, NULL) != TRUE) + goto err; + +#if defined(DOT11_HE_AX) + wdev = (struct wifi_dev *)configs->wdev[1]; + + if (wdev_init(ad, wdev, WDEV_TYPE_SERVICE_TXC, + ad->wdev_list[band_idx]->if_dev, + band_idx, NULL, (void *)ad) != TRUE) + goto err; + + if (!wdev) + return SERV_STATUS_OSAL_NET_INVALID_PARAM; + + if (IS_AXE(ad) || IS_MT7915(ad)) + serv_wdev_ops.ate_tx = net_ad_tx_v2; + + if (wdev_ops_register(wdev, WDEV_TYPE_SERVICE_TXC, &serv_wdev_ops, 0) + != TRUE) + goto err; + + wdev->channel = configs->channel; + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_OFF, + ("%s: wdev_idx=%d, channel=%d\n", + __func__, wdev->wdev_idx, wdev->channel)); + + if (wdev->channel > 14) + wdev->PhyMode = PHYMODE_CAP_5G; + else + wdev->PhyMode = PHYMODE_CAP_24G; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(ad) + own_mac_addr = (u_char *)&configs->addr3[0]; + +#endif +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(ad) + own_mac_addr = (u_char *)&configs->addr2[0]; +#endif + own_mac_addr[0] |= 0x2; + sys_ad_move_mem(wdev->if_addr, own_mac_addr, SERV_MAC_ADDR_LEN); + + if (wdev_do_open(wdev) != TRUE) + goto err; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(ad) + bssid = (u_char *)&configs->addr2[0]; + +#endif +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(ad) + bssid = (u_char *)&configs->addr1[0]; +#endif + bssid[0] |= 0x2; + sys_ad_move_mem(wdev->bssid, bssid, SERV_MAC_ADDR_LEN); + + if (wifi_sys_linkup(wdev, NULL) != TRUE) + goto err; +#endif /* DOT11_HE_AX */ + + return ret; + +err: + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: inits wdev failed!\n", __func__)); + + return SERV_STATUS_OSAL_NET_FAIL_INIT_WDEV; +} + +s_int32 net_ad_release_wdev( + struct test_wlan_info *winfos, + struct test_configuration *configs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct wifi_dev *wdev; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s\n", __func__)); + + /* To release wdev */ + wdev = configs->wdev[0]; + + if (!wdev) + goto err; + + if (wifi_sys_linkdown(wdev) != TRUE) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: linkdown failed!\n", __func__)); + goto err; + } + + if (wdev_do_close(wdev) != TRUE) + goto err; + + if (wdev_deinit(ad, wdev) != TRUE) + goto err; + +#if defined(DOT11_HE_AX) + wdev = configs->wdev[1]; + + if (!wdev) + goto err; + + if (wifi_sys_linkdown(wdev) != TRUE) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: linkdown failed!\n", __func__)); + goto err; + } + + if (wdev_do_close(wdev) != TRUE) + goto err; + + if (wdev_deinit(ad, wdev) != TRUE) + goto err; +#endif /* DOT11_HE_AX */ + + return ret; + +err: + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: releases wdev failed!\n", __func__)); + + return SERV_STATUS_OSAL_NET_FAIL_RELEASE_WDEV; +} + +s_int32 net_ad_alloc_wtbl( + struct test_wlan_info *winfos, + u_char *da, + void *virtual_device, + void **virtual_wtbl) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: invalid adapter!\n", __func__)); + ret = SERV_STATUS_OSAL_NET_INVALID_PAD; + goto err_out; + } + + if (virtual_device == NULL) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: invalid wdev!\n", __func__)); + ret = SERV_STATUS_OSAL_NET_INVALID_NULL_POINTER; + goto err_out; + } + + *virtual_wtbl = (void *)MacTableInsertEntry(ad, + da, + virtual_device, + ENTRY_ATE, + OPMODE_ATE, + TRUE); + + if (*virtual_wtbl == NULL) + ret = SERV_STATUS_OSAL_NET_FAIL; + +err_out: + return ret; +} + +s_int32 net_ad_free_wtbl( + struct test_wlan_info *winfos, + u_char *da, + void *virtual_wtbl) +{ + RTMP_ADAPTER *ad = NULL; + struct _MAC_TABLE_ENTRY *mac_tbl_entry = NULL; + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + if (virtual_wtbl) { + mac_tbl_entry = (struct _MAC_TABLE_ENTRY *)virtual_wtbl; + MacTableDeleteEntry(ad, mac_tbl_entry->wcid, da); + } else + return SERV_STATUS_OSAL_NET_INVALID_NULL_POINTER; + + return SERV_STATUS_SUCCESS; +} + +s_int32 net_ad_apply_wtbl( + struct test_wlan_info *winfos, + void *virtual_dev, + void *virtual_wtbl) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + struct serv_chip_cap *chip_cap = NULL; + struct caps_info *cap = NULL; + struct ampdu_caps *ampdu = NULL; + u_short bw_winsiz = 0, tid_idx = 0; + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + chip_cap = &winfos->chip_cap; + + if (virtual_wtbl) { + struct _MAC_TABLE_ENTRY *entry = NULL; + struct phy_params *phy_info = NULL; + + entry = (struct _MAC_TABLE_ENTRY *)virtual_wtbl; + phy_info = &entry->phy_param; + cap = &entry->cap; + ampdu = &entry->cap.ampdu; + + if (phy_info->phy_mode > MODE_VHT) + entry->MaxHTPhyMode.field.MODE = MODE_VHT; + else + entry->MaxHTPhyMode.field.MODE = phy_info->phy_mode; + + if (phy_info->phy_mode > MODE_OFDM) { + entry->MaxRAmpduFactor = chip_cap->ht_ampdu_exp; + ampdu->max_ht_ampdu_len_exp = chip_cap->ht_ampdu_exp; + } + if (phy_info->phy_mode > MODE_HTGREENFIELD) { + entry->MaxRAmpduFactor = chip_cap->vht_ampdu_exp; + ampdu->max_mpdu_len = chip_cap->max_mpdu_len; + ampdu->max_vht_ampdu_len_exp = chip_cap->vht_ampdu_exp; + } +#if defined(DOT11_HE_AX) + if (phy_info->phy_mode > MODE_VHT) { + cap->modes |= (HE_24G_SUPPORT | HE_5G_SUPPORT); + cap->he_mac_cap |= HE_AMSDU_IN_ACK_EN_AMPDU; + ampdu->max_he_ampdu_len_exp = chip_cap->he_ampdu_exp; + } +#endif + CLIENT_STATUS_SET_FLAG(entry, fCLIENT_STATUS_WMM_CAPABLE); + cap->ch_bw.he_ch_width = BW_80; + + if (wifi_sys_conn_act(virtual_dev, virtual_wtbl) != TRUE) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s(): connect action fail!\n", __func__)); + } + +#if defined(DOT11_VHT_AC) + if (IS_HIF_TYPE(ad, HIF_MT)) + RAInit(ad, entry); +#endif + + if (phy_info->phy_mode <= MODE_VHT) + bw_winsiz = chip_cap->non_he_tx_ba_wsize; +#if defined(DOT11_HE_AX) + else + bw_winsiz = chip_cap->he_tx_ba_wsize; +#endif /* DIT11_HE_AX */ + + for (tid_idx = 0; tid_idx < 8 ; tid_idx++) + AsicUpdateBASession(ad, + entry->wcid, + tid_idx, + 0, + bw_winsiz, + TRUE, + BA_SESSION_ORI, + 0); + +#ifdef RACTRL_FW_OFFLOAD_SUPPORT + if (winfos->wm_fw_info.ra_offload == TRUE) { + CMD_STAREC_AUTO_RATE_UPDATE_T rRaParam; + RA_PHY_CFG_T *rate_cfg = NULL; + u_int8 gi_type = phy_info->gi_type; + u_int8 ltf_type = phy_info->ltf_type; + + entry->bAutoTxRateSwitch = FALSE; + sys_ad_zero_mem(&rRaParam, + sizeof(CMD_STAREC_AUTO_RATE_UPDATE_T)); + rate_cfg = &rRaParam.FixedRateCfg; + rate_cfg->MODE = phy_info->phy_mode; + if (phy_info->phy_mode == TEST_MODE_HE_MU || + phy_info->phy_mode == TEST_MODE_VHT_MIMO) { + /* work-around to prevent TX CCK + * while 5GHz band + */ + rate_cfg->MODE = TEST_MODE_OFDM; + phy_info->rate = 7; + } + rate_cfg->STBC = phy_info->stbc; + if (phy_info->phy_mode < MODE_HE_SU) { + if (phy_info->gi_type) + rate_cfg->ShortGI = BIT(phy_info->bw); + else + rate_cfg->ShortGI = 0; + } +#if defined(DOT11_HE_AX) + else { + switch (phy_info->bw) { + case BW_40: + rate_cfg->ShortGI = (gi_type << 2); + rate_cfg->he_ltf = (ltf_type << 2); + break; + case BW_80: + rate_cfg->ShortGI = (gi_type << 4); + rate_cfg->he_ltf = (ltf_type << 4); + break; + case BW_160: + rate_cfg->ShortGI = (gi_type << 6); + rate_cfg->he_ltf = (ltf_type << 6); + break; + default: + rate_cfg->ShortGI = gi_type; + rate_cfg->he_ltf = ltf_type; + } + } +#endif /* DOT11_HE_AX */ + rate_cfg->BW = phy_info->bw; + if (phy_info->ldpc) { + switch (phy_info->phy_mode) { + case MODE_HTMIX: + case MODE_HTGREENFIELD: + rate_cfg->ldpc = 1; + break; + case MODE_VHT: + rate_cfg->ldpc = 2; + break; +#if defined(DOT11_HE_AX) + case MODE_HE_SU: + case MODE_HE_EXT_SU: + case MODE_HE_TRIG: + case MODE_HE_MU: + rate_cfg->ldpc = 4; + break; +#endif /* DOT11_HE_AX */ + default:/* should not happen */ + rate_cfg->ldpc = 0; + } + } + rate_cfg->MCS = phy_info->rate; + if (phy_info->dcm) + rate_cfg->MCS |= BIT(4); + if (phy_info->su_ext_tone) + rate_cfg->MCS |= BIT(5); + rate_cfg->VhtNss = phy_info->vht_nss; + #if 0 /* ToDO */ + rRaParam.ucShortPreamble = + TESTMODE_GET_PARAM(pAd, + HcGetBandByWdev(virtual_dev), + preamble); + #endif + rRaParam.u4Field = RA_PARAM_FIXED_RATE; + RAParamUpdate(ad, entry, &rRaParam); + } +#endif + } else + ret = SERV_STATUS_OSAL_NET_INVALID_NULL_POINTER; + + return ret; +} + +s_int32 net_ad_match_wtbl( + void *virtual_wtbl, + u_int16 wcid) +{ + struct _MAC_TABLE_ENTRY *mac_tbl_entry = NULL; + /* Get adapter from jedi driver first */ + + mac_tbl_entry = (struct _MAC_TABLE_ENTRY *)virtual_wtbl; + + if (mac_tbl_entry->wcid == wcid) + return TRUE; + + return FALSE; +} + +s_int32 net_ad_set_aid( + void *virtual_wtbl, + u_int16 aid) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct _MAC_TABLE_ENTRY *entry = NULL; + + entry = (struct _MAC_TABLE_ENTRY *)virtual_wtbl; + + if (entry) + entry->Aid = aid; + else + ret = SERV_STATUS_OSAL_NET_INVALID_NULL_POINTER; + + return ret; +} + +s_int32 net_ad_get_wmm_idx( + void *virtual_device, + u_int8 *wmm_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct wifi_dev *wdev = (struct wifi_dev *)virtual_device; + + if (wdev == NULL) { + ret = SERV_STATUS_OSAL_NET_INVALID_NULL_POINTER; + goto err_out; + } + + *wmm_idx = HcGetWmmIdx(NULL, (struct wifi_dev *)virtual_device); + +err_out: + return ret; +} + +s_int32 net_ad_get_band_idx( + void *virtual_device, + u_char *band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + if (virtual_device == NULL) + ret = SERV_STATUS_OSAL_NET_INVALID_NULL_POINTER; + else { + struct wifi_dev *wdev = (struct wifi_dev *)virtual_device; + + *band_idx = HcGetBandByWdev(wdev); + } + + return ret; +} + +s_int32 net_ad_get_omac_idx( + struct test_wlan_info *winfos, + void *virtual_device, + u_char *omac_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) { + ret = SERV_STATUS_OSAL_NET_INVALID_PAD; + goto err_out; + } + + if (virtual_device == NULL) + ret = SERV_STATUS_OSAL_NET_INVALID_NULL_POINTER; + else { + struct wifi_dev *wdev = (struct wifi_dev *)virtual_device; + + *omac_idx = HcGetOmacIdx(ad, wdev); + } + +err_out: + return ret; +} + +s_int32 net_ad_fill_phy_info( + void *virtual_wtbl, + struct test_tx_info *tx_info) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct _MAC_TABLE_ENTRY *entry = NULL; + struct phy_params *phy_info = NULL; + + entry = (struct _MAC_TABLE_ENTRY *)virtual_wtbl; + phy_info = &entry->phy_param; + + sys_ad_zero_mem(phy_info, sizeof(*phy_info)); + + phy_info->phy_mode = tx_info->tx_mode; +#ifdef TXBF_SUPPORT + phy_info->tx_ibf = tx_info->ibf; + phy_info->tx_ebf = tx_info->ebf; +#endif + phy_info->stbc = tx_info->stbc; + phy_info->ldpc = tx_info->ldpc; + phy_info->bw = tx_info->bw; + phy_info->vht_nss = tx_info->nss; + phy_info->gi_type = tx_info->gi; + phy_info->ltf_type = tx_info->ltf; + +#if defined(DOT11_HE_AX) + if (phy_info->phy_mode > TEST_MODE_VHT) { + phy_info->rate = (tx_info->mcs & 0xf); + /* b'5 for DCM */ + phy_info->dcm = (tx_info->mcs & BIT(5)) ? TRUE : FALSE; + + if (phy_info->phy_mode == TEST_MODE_HE_ER) { + /* b'4 for tone*/ + if (tx_info->mcs & BIT(4)) + phy_info->su_ext_tone = TRUE; + else + phy_info->su_ext_tone = FALSE; + } + } else +#endif /* DOT11_HE_AX */ + { + phy_info->rate = (tx_info->mcs & 0x1f); + } + + return ret; +} + +s_int32 net_ad_get_speidx( + struct test_wlan_info *winfos, + u_int16 ant_sel, + u_int8 *spe_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + u_int8 map_idx = 0; + struct serv_spe_map *spe_map = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) { + ret = SERV_STATUS_OSAL_NET_INVALID_PAD; + goto err_out; + } + + *spe_idx = 0; + spe_map = winfos->chip_cap.spe_map_list.spe_map; + for (map_idx = 0; + map_idx < winfos->chip_cap.spe_map_list.size; + map_idx++) { + if (ant_sel == spe_map[map_idx].ant_sel) { + *spe_idx = spe_map[map_idx].spe_idx; + break; + } + } + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s spe idx=%d(map_idx:%d/%d)\n", + __func__, *spe_idx, map_idx, + winfos->chip_cap.spe_map_list.size)); + +err_out: + return ret; +} + + +s_int32 net_ad_fill_spe_antid( + struct test_wlan_info *winfos, + void *virtual_wtbl, + u_int8 spe_idx, + u_int8 ant_pri) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + struct _MAC_TABLE_ENTRY *entry = NULL; + struct phy_params *phy_info = NULL; +#ifdef RACTRL_FW_OFFLOAD_SUPPORT + CMD_STAREC_AUTO_RATE_UPDATE_T rRaParam; +#endif /* RACTRL_FW_OFFLOAD_SUPPORT */ + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) { + ret = SERV_STATUS_OSAL_NET_INVALID_PAD; + goto err_out; + } + + if (virtual_wtbl == NULL) { + ret = SERV_STATUS_OSAL_NET_INVALID_NULL_POINTER; + goto err_out; + } + + entry = (struct _MAC_TABLE_ENTRY *)virtual_wtbl; + phy_info = &entry->phy_param; + + phy_info->spe_idx = spe_idx; + phy_info->ant_pri = ant_pri; + +#ifdef RACTRL_FW_OFFLOAD_SUPPORT + sys_ad_zero_mem(&rRaParam, sizeof(CMD_STAREC_AUTO_RATE_UPDATE_T)); + + rRaParam.ucSpeEn = spe_idx; + rRaParam.u4Field = RA_PARAM_SPE_UPDATE; + RAParamUpdate(ad, entry, &rRaParam); +#endif /* RACTRL_FW_OFFLOAD_SUPPORT */ + +err_out: + return ret; +} + + +s_int32 net_ad_fill_pkt( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char *buf, u_int32 txlen, u_int32 hlen) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + u_char *tmac_info, *pheader, *payload; + u_char *addr1, *addr2, *addr3, *template; + u_int8 tx_hw_hdr_len; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + tx_hw_hdr_len = winfos->chip_cap.tx_wi_size; + addr1 = configs->addr1[0]; + addr2 = configs->addr2[0]; + addr3 = configs->addr3[0]; + template = configs->template_frame; + + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s(wcid:%d):: DA: %02x:%02x:%02x:%02x:%02x:%02x\n\t", + __func__, configs->wcid_ref, SERV_PRINT_MAC(addr1))); + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("SA: %02x:%02x:%02x:%02x:%02x:%02x\n\t", + SERV_PRINT_MAC(addr2))); + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("BSSID: %02x:%02x:%02x:%02x:%02x:%02x\n", + SERV_PRINT_MAC(addr3))); + + /* Error check for txlen */ + if (txlen == 0) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: tx length can't be 0!!\n", __func__)); + + return SERV_STATUS_OSAL_NET_INVALID_LEN; + } + + tmac_info = buf; + pheader = (buf + tx_hw_hdr_len); + payload = (pheader + hlen); + sys_ad_zero_mem(buf, TEST_PKT_LEN); + + /* TODO: factor out here for BF */ +#if 0 +#ifdef TXBF_SUPPORT + { + UCHAR iTxBf = TESTMODE_GET_PARAM(pAd, band_idx, ibf); + UCHAR eTxBf = TESTMODE_GET_PARAM(pAd, band_idx, ebf); + + /* Use wcid 1~4 */ + if (iTxBf || eTxBf) { + if ((ATECtrl->wcid_ref > ATE_BFMU_NUM) + || (ATECtrl->wcid_ref < 1)) + ATECtrl->wcid_ref = ATE_BF_WCID; + + addr1 = ATECtrl->pfmu_info[ATECtrl->wcid_ref - 1].addr; + } + + SERV_LOG(DBG_CAT_TEST, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%s:: DA: %02x:%02x:%02x:%02x:%02x:%02x, wcid=%u\n", + __func__, PRINT_MAC(addr1), ATECtrl->wcid_ref)); + } +#endif +#endif + + sys_ad_move_mem(pheader, template, hlen); + sys_ad_move_mem(pheader + 4, addr1, SERV_MAC_ADDR_LEN); + sys_ad_move_mem(pheader + 10, addr2, SERV_MAC_ADDR_LEN); + sys_ad_move_mem(pheader + 16, addr3, SERV_MAC_ADDR_LEN); + + ret = net_ad_init_payload(winfos, configs, payload, txlen - hlen); + if (ret) + return ret; + + /* TODO: factor out here for log dump */ +#if 0 +#if !defined(COMPOS_TESTMODE_WIN) + + if (ATECtrl->en_log & fATE_LOG_TXDUMP) { + INT i = 0; + PHEADER_802_11 hdr = (HEADER_802_11 *) pheader; + + SERV_LOG(DBG_CAT_TEST, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("[TXCONTENT DUMP START]\n")); + asic_dump_tmac_info(pAd, tmac_info); + SERV_LOG(DBG_CAT_TEST, DBG_SUBCAT_ALL, + DBG_LVL_OFF, ("[TXD RAW]: ")); + + for (i = 0; i < tx_hw_hdr_len; i++) + MTWF_LOG(DBG_CAT_TEST, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%04x", tmac_info[i])); + + SERV_LOG(DBG_CAT_TEST, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("\nADDR1: %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(hdr->Addr1))); + SERV_LOG(DBG_CAT_TEST, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("ADDR2: %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(hdr->Addr2))); + SERV_LOG(DBG_CAT_TEST, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("ADDR3: %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(hdr->Addr3))); + SERV_LOG(DBG_CAT_TEST, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("FC: %04x\n", *(UINT16 *) (&hdr->FC))); + SERV_LOG(DBG_CAT_TEST, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("\tFrom DS: %x\n", hdr->FC.FrDs)); + SERV_LOG(DBG_CAT_TEST, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("\tTo DS: %x\n", hdr->FC.ToDs)); + SERV_LOG(DBG_CAT_TEST, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("[CONTENT RAW]: ")); + + for (i = 0; i < (txlen - hlen); i++) + SERV_LOG(DBG_CAT_TEST, DBG_SUBCAT_ALL, DBG_LVL_INFO, + ("%02x", payload[i])); + + SERV_LOG(DBG_CAT_TEST, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("\n[TXCONTENT DUMP END]\n")); + } +#endif /* !defined(COMPOS_TESTMODE_WIN) */ +#endif + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(ad, (u_char *) pheader, DIR_WRITE, FALSE); +#ifdef MT_MAC + if (IS_HIF_TYPE(ad, HIF_MT)) + MTMacInfoEndianChange(ad, tmac_info, TYPE_TMACINFO, + sizeof(TMAC_TXD_L)); +#endif +#endif + + return ret; +} + +s_int32 net_ad_alloc_pkt( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_int32 mpdu_length, + void **pkt_skb) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + u_char *src_buff; + u_short qid; + u_int8 tx_hw_hdr_len; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + src_buff = configs->test_pkt; + qid = configs->ac_idx; + tx_hw_hdr_len = winfos->chip_cap.tx_hw_hdr_len; + + if (!src_buff) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: invalid test_pkt\n", __func__)); + goto err_out; + } + + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: test_pkt=%p, ring idx=%u\n", __func__, src_buff, qid)); + + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: txlen=%d, tx_hw_hdr_len=%d, total=%d\n", + __func__, mpdu_length, tx_hw_hdr_len, + mpdu_length + tx_hw_hdr_len)); + + ret = RTMPAllocateNdisPacket(ad, + pkt_skb, + NULL, + 0, + src_buff, + mpdu_length + tx_hw_hdr_len); + + if (ret != NDIS_STATUS_SUCCESS) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: AllocateNdisPacket fail\n", __func__)); + goto err_out; + } + +err_out: + return ret; +} + +s_int32 net_ad_free_pkt( + struct test_wlan_info *winfos, + void *pkt_skb) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + RTMPFreeNdisPacket(ad, pkt_skb); + + return ret; +} + +s_int32 net_ad_enq_pkt( + struct test_wlan_info *winfos, + u_short q_idx, + void *virtual_wtbl, + void *virtual_device, + void *pkt_skb) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + PNDIS_PACKET pkt = NULL; + struct sk_buff *skb = NULL, *skb2 = NULL; + struct wifi_dev *wdev = (struct wifi_dev *)virtual_device; + struct _MAC_TABLE_ENTRY *entry = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) { + ret = SERV_STATUS_OSAL_NET_INVALID_PAD; + goto err_out; + } + + if (virtual_device) + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: wdev_idx=%d, q_idx=%d, pkt_va=%p\n", + __func__, wdev->wdev_idx, q_idx, pkt_skb)); + else { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: invalid wdev(%p)!\n", __func__, wdev)); + ret = SERV_STATUS_OSAL_NET_INVALID_NULL_POINTER; + goto err_out; + } + + if (virtual_wtbl) + entry = (struct _MAC_TABLE_ENTRY *)virtual_wtbl; + else { + ret = SERV_STATUS_OSAL_NET_INVALID_NULL_POINTER; + goto err_out; + } + + if (pkt_skb) { + skb = (struct sk_buff *)pkt_skb; + SERV_OS_PKT_CLONE(skb, skb2, GFP_ATOMIC); + + if (skb2 == NULL) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: clone packet fail\n", __func__)); + ret = SERV_STATUS_OSAL_NET_FAIL; + goto err_out; + } else { + pkt = (PNDIS_PACKET)skb2; + RTMP_SET_PACKET_WCID(pkt, entry->wcid); + RTMP_SET_PACKET_WDEV(pkt, wdev->wdev_idx); + + RTMP_SET_PACKET_TXTYPE(pkt, TX_ATE_FRAME); + + if (q_idx > 0) { + RTMP_SET_PACKET_QUEIDX(pkt, QID_AC_BE); + RTMP_SET_PACKET_TYPE(pkt, TX_DATA); + } else { + RTMP_SET_PACKET_QUEIDX(pkt, 0); + RTMP_SET_PACKET_TYPE(pkt, TX_MGMT); + } + } + + ret = send_mlme_pkt(ad, pkt, wdev, q_idx, FALSE); + } + + if (ret) + ret = SERV_STATUS_OSAL_NET_FAIL; + +err_out: + return ret; +} + +s_int32 net_ad_trigger_tx( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_int8 band_idx, + void *pkt) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + u_int32 txdone_cnt = 0, tx_cnt = 0, op_mode = 0; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + if (band_idx >= TEST_DBDC_BAND_NUM) { + ret = SERV_STATUS_OSAL_NET_INVALID_BANDIDX; + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: wrong band_idx %u, ret=0x%08x\n", + __func__, band_idx, ret)); + goto done; + } + + tx_cnt = configs->tx_stat.tx_cnt; + op_mode = configs->op_mode; + + /* Do not count in packet number when tx is not in start stage */ + if (!(op_mode & OP_MODE_TXFRAME)) + goto done; + + /* Triggered when RX tasklet free token */ + if (pkt) { + ad->RalinkCounters.KickTxCount++; + txdone_cnt++; + } + + if (configs->tx_strategy == TEST_TX_STRA_THREAD) + net_ad_thread_proceed_tx(winfos, band_idx); + else if (configs->tx_strategy == TEST_TX_STRA_TASKLET) { + if ((op_mode & OP_MODE_TXFRAME) && (txdone_cnt < tx_cnt)) + ret = net_ad_enq_pkt(winfos, + configs->ac_idx, + configs->stack.virtual_wtbl[0], + configs->stack.virtual_device[0], + configs->stack.pkt_skb[0]); + else if ((op_mode & OP_MODE_TXFRAME) + && (txdone_cnt == tx_cnt)) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: all tx is done\n", __func__)); + + if (op_mode & fTEST_MPS) { + SERV_OS_COMPLETION *tx_wait; + + tx_wait = &configs->tx_wait; + SERV_OS_COMPLETE(tx_wait); + SERV_LOG(SERV_DBG_CAT_ADAPT, + SERV_DBG_LVL_TRACE, + ("%s: finish one MPS item\n", + __func__)); + } + + /* Tx status enters idle mode */ + configs->tx_status = 0; + } else if (!(op_mode & OP_MODE_TXFRAME)) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: stop tx bottom is pressed\n", + __func__)); + + if (op_mode & fTEST_MPS) { + SERV_OS_COMPLETION *tx_wait; + + tx_wait = &configs->tx_wait; + op_mode &= ~fTEST_MPS; + configs->op_mode = op_mode; + SERV_OS_COMPLETE(tx_wait); + SERV_LOG(SERV_DBG_CAT_ADAPT, + SERV_DBG_LVL_TRACE, + ("%s: MPS stop\n", __func__)); + } + } else { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_WARN, + ("%s: do not match any condition, ", + __func__)); + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_WARN, + ("op_mode:0x%x, tx_cnt:%u, txdone_cnt:%u\n", + op_mode, tx_cnt, txdone_cnt)); + } + } else { + ret = SERV_STATUS_OSAL_NET_INVALID_PARAM; + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: wrong tx strategy=%d, ret=0x%08x\n", + __func__, configs->tx_strategy, ret)); + goto done; + } + +done: + return ret; +} + +s_int32 net_ad_rx_done_handle( + struct test_wlan_info *winfos, + void *rx_blk) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + struct service_test *serv_test; + RX_BLK *rxblk = (RX_BLK *)rx_blk; + u_char band_idx; + u_int32 chfreq0 = 0, chfreq1 = 0; + u_int32 bn0_cr_addr = RMAC_CHFREQ0; +/* #ifdef DBDC_MODE */ +#if 1 + u_int32 bn1_cr_addr = RMAC_CHFREQ1; +#endif /* DBDC_MODE */ + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + if (IS_MT7915(ad)) + band_idx = rxblk->band; + else { + MAC_IO_READ32(ad->hdev_ctrl, bn0_cr_addr, &chfreq0); +/* #ifdef DBDC_MODE */ +#if 1 + MAC_IO_READ32(ad->hdev_ctrl, bn1_cr_addr, &chfreq1); +#endif /* DBDC_MODE */ + + /* Note: shall not use ad here */ + serv_test = (struct service_test *)ad->serv.serv_handle; + + /* RX packet counter calculate by chfreq of RXD */ + if (rxblk->channel_freq == chfreq0) + band_idx = TEST_DBDC_BAND0; +/* #ifdef DBDC_MODE */ +#if 1 + else if (rxblk->channel_freq == chfreq1) + band_idx = TEST_DBDC_BAND1; +#endif /* DBDC_MODE */ + else { + SERV_LOG(SERV_DBG_CAT_ALL, SERV_DBG_LVL_ERROR, + ("%s: wrong chfreq!!\n" + "\tRXD.ch_freq=%u, chfreq0=%u, chfreq1=%u\n", + __func__, rxblk->channel_freq, + chfreq0, chfreq1)); + return SERV_STATUS_OSAL_NET_INVALID_PARAM; + } + } + + return ret; +} + +s_int32 net_ad_set_band_mode( + struct test_wlan_info *winfos, + struct test_band_state *band_state) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + if (band_state->band_mode == TEST_BAND_MODE_SINGLE) { + if (band_state->band_type == TEST_BAND_TYPE_A) + Set_WirelessMode_Proc(ad, "14"); + else if (band_state->band_type == TEST_BAND_TYPE_G) + Set_WirelessMode_Proc(ad, "9"); + else + ret = SERV_STATUS_OSAL_NET_INVALID_PARAM; + } + + return ret; +} + +s_int32 net_ad_set_txpwr_sku( + struct test_wlan_info *winfos, + u_char sku_ctrl, u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + ret = MtCmdTxPowerSKUCtrl(ad, sku_ctrl, band_idx); + if (ret) + ret = SERV_STATUS_OSAL_NET_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 net_ad_set_txpwr_power_drop( + struct test_wlan_info *winfos, + u_char power_drop, u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + ret = MtCmdTxPowerDropCtrl(ad, power_drop, band_idx); + if (ret) + ret = SERV_STATUS_OSAL_NET_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 net_ad_set_txpwr_percentage( + struct test_wlan_info *winfos, + u_char percentage_ctrl, u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + ret = MtCmdTxPowerPercentCtrl(ad, percentage_ctrl, band_idx); + if (ret) + ret = SERV_STATUS_OSAL_NET_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 net_ad_set_txpwr_backoff( + struct test_wlan_info *winfos, + u_char backoff_ctrl, u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + ret = MtCmdTxBfBackoffCtrl(ad, backoff_ctrl, band_idx); + if (ret) + ret = SERV_STATUS_OSAL_NET_FAIL_SEND_FWCMD; + + return ret; +} + +s_int32 net_ad_init_txpwr( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + if (band_idx >= TEST_DBDC_BAND_NUM) + return SERV_STATUS_OSAL_NET_INVALID_BANDIDX; + + /* Disable tx power related function for test mode */ + ret = net_ad_set_txpwr_sku(winfos, configs->tx_pwr_sku_en, band_idx); + if (ret) + goto error; + + ret = net_ad_set_txpwr_power_drop( + winfos, configs->tx_pwr_percentage_level, band_idx); + if (ret) + goto error; + + ret = net_ad_set_txpwr_percentage( + winfos, configs->tx_pwr_percentage_en, band_idx); + if (ret) + goto error; + + ret = net_ad_set_txpwr_backoff( + winfos, configs->tx_pwr_backoff_en, band_idx); + if (ret) + goto error; + + return ret; + +error: + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: engine init tx power fail, err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 net_ad_handle_mcs32( + struct test_wlan_info *winfos, + void *virtual_wtbl, u_int8 bw) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + union WTBL_DW5 wtbl_txcap; + u_int32 dw_mask = 0; + struct _MAC_TABLE_ENTRY *entry = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + if (entry == NULL) { + ret = SERV_STATUS_OSAL_NET_INVALID_NULL_POINTER; + goto err_out; + } else + entry = (struct _MAC_TABLE_ENTRY *)virtual_wtbl; + + dw_mask = ~(3 << 12); /* only update fcap bit[13:12] */ + wtbl_txcap.field.fcap = bw; + + /* WTBLDW5 */ + ret = WtblDwSet(ad, entry->wcid, 1, 5, dw_mask, wtbl_txcap.word); + if (ret) + ret = SERV_STATUS_OSAL_NET_FAIL_SEND_FWCMD; + +err_out: + return ret; +} + +s_int32 net_ad_cfg_wtbl( + struct test_wlan_info *winfos, + struct test_configuration *configs +) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + struct _RTMP_CHIP_CAP *cap = NULL; + struct _EXT_CMD_ATE_TEST_MODE_T param; + struct tx_time_param *tx_time_param; + P_HT_CAP_T wtbl_ht_cap; + P_VHT_CAP_T wtbl_vht_cap; + P_ANT_CAP_T wtbl_ant_cap; + P_BA_CAP_T wtbl_ba_cap; + P_RATE_CAP_T wtbl_rate_cap; + u_int8 need_qos, need_amsdu, need_ampdu; + u_char tx_mode, mcs, nss, bw, sgi, stbc, ldpc, preamble, u4Stbc; + u_int32 ant_sel = 0; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + cap = hc_get_chip_cap(ad->hdev_ctrl); + tx_time_param = &configs->tx_time_param; + wtbl_ht_cap = ¶m.Data.rAteSetAmpduWtbl.rWtblHt; + wtbl_vht_cap = ¶m.Data.rAteSetAmpduWtbl.rWtblVht; + wtbl_ant_cap = ¶m.Data.rAteSetAmpduWtbl.rWtblAnt; + wtbl_ba_cap = ¶m.Data.rAteSetAmpduWtbl.rWtblBa; + wtbl_rate_cap = ¶m.Data.rAteSetAmpduWtbl.rWtblRate; + + need_qos = tx_time_param->pkt_need_qos; + need_amsdu = tx_time_param->pkt_need_amsdu; + need_ampdu = tx_time_param->pkt_need_ampdu; + tx_mode = configs->tx_mode; + mcs = configs->mcs; + nss = configs->nss; + bw = configs->bw; + sgi = configs->sgi; + stbc = configs->stbc; + ldpc = configs->ldpc; + ant_sel = configs->tx_ant; + preamble = configs->preamble; + + sys_ad_zero_mem(¶m, sizeof(param)); + param.ucAteTestModeEn = TRUE; + param.ucAteIdx = ENUM_ATE_SET_AMPDU_WTBL; + + switch (tx_mode) { + case TEST_MODE_HTMIX: + case TEST_MODE_HTGREENFIELD: + wtbl_ht_cap->fgIsHT = TRUE; + wtbl_ht_cap->fgLDPC = ldpc; + + if (cap) + wtbl_ht_cap->ucAmpduFactor + = winfos->chip_cap.ht_ampdu_exp; + else + wtbl_ht_cap->ucAmpduFactor = 3; + + break; + + case TEST_MODE_VHT: + wtbl_ht_cap->fgIsHT = 1; + wtbl_vht_cap->fgIsVHT = 1; + wtbl_vht_cap->fgVhtLDPC = ldpc; + + if (cap) + wtbl_ht_cap->ucAmpduFactor + = winfos->chip_cap.vht_ampdu_exp; + else + wtbl_ht_cap->ucAmpduFactor = 7; + + break; + + default: + wtbl_ht_cap->fgIsHT = 0; + wtbl_vht_cap->fgIsVHT = 0; + break; + } + + if (need_ampdu) { + if (ant_sel & TEST_ANT_USER_SEL) { + ant_sel &= ~TEST_ANT_USER_SEL; + } else { + s_int32 map_idx = 0; + s_int32 map_idx_len = sizeof(test_ant_to_spe_idx_map) + / sizeof(test_ant_to_spe_idx_map[0]); + + for (map_idx = 0; map_idx < map_idx_len; map_idx++) { + if (ant_sel == + test_ant_to_spe_idx_map[map_idx].ant_sel) + break; + } + if (map_idx == map_idx_len) + ant_sel = 0; + else + ant_sel + = test_ant_to_spe_idx_map[map_idx].spe_idx; + } + + wtbl_ant_cap->ucSpe = (ant_sel & 0x1F); + wtbl_ant_cap->AntIDConfig.ucANTIDSts0 = ant_sel; + wtbl_ant_cap->AntIDConfig.ucANTIDSts1 = ant_sel; + wtbl_ant_cap->AntIDConfig.ucANTIDSts2 = ant_sel; + wtbl_ant_cap->AntIDConfig.ucANTIDSts3 = ant_sel; + + wtbl_ba_cap->ucBaEn = 1; + wtbl_ba_cap->ucBaSize = 7; + param.Data.rAteSetAmpduWtbl.ucIPsm = 1; + } + + wtbl_rate_cap->ucFcap = bw; + + if (sgi) { + switch (bw) { + case TEST_BW_20: + wtbl_rate_cap->fgG2 = TRUE; + break; + + case TEST_BW_40: + wtbl_rate_cap->fgG4 = TRUE; + break; + + case TEST_BW_80: + wtbl_rate_cap->fgG8 = TRUE; + break; + + case TEST_BW_160C: + wtbl_rate_cap->fgG16 = TRUE; + break; + + default: + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_OFF, + ("%s: can't find such bw, use default\n", + __func__)); + break; + } + } + + u4Stbc = raStbcSettingCheck(stbc, tx_mode, mcs, nss, 0, 0); + + wtbl_rate_cap->ucStbc = u4Stbc; + wtbl_rate_cap->ucMode = tx_mode; + wtbl_rate_cap->ucSgi = sgi; + wtbl_rate_cap->ucBw = bw; + wtbl_rate_cap->ucNss = nss; + wtbl_rate_cap->ucPreamble = preamble; + wtbl_rate_cap->ucLdpc = ldpc; + wtbl_rate_cap->au2RateCode = mcs; + + if (need_qos) + param.Data.rAteSetAmpduWtbl.ucQos = 1; + +#ifdef CONFIG_HW_HAL_OFFLOAD + ret = MtCmdATETest(ad, ¶m); +#endif + + return ret; +} + +s_int32 net_ad_set_wmm_param_by_qid( + u_char wmm_idx, + u_int8 q_idx, + struct test_wlan_info *winfos, + struct test_configuration *configs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + struct ipg_param *ipg_param; + u_int16 slot_time, sifs_time, cw; + u_int8 ac_num, aifsn; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + ipg_param = &configs->ipg_param; + + if (wmm_idx > 3) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: invalid wmm_idx=%d, ", + __func__, wmm_idx)); + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("reset to 0xff!\n")); + wmm_idx = 0xFF; + } + + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: wmm_idx=%d\n", __func__, wmm_idx)); + + if ((q_idx != QID_AC_BE) + && (q_idx != TxQ_IDX_ALTX0) + && (q_idx != TxQ_IDX_ALTX1)) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: impossible!\n", __func__)); + return SERV_STATUS_OSAL_NET_INVALID_PARAM; + } + + slot_time = ipg_param->slot_time; + sifs_time = ipg_param->sifs_time; + ac_num = q_idx; + aifsn = ipg_param->aifsn; + cw = ipg_param->cw; + ret = AsicSetWmmParam(ad, wmm_idx, + (u_int32) ac_num, WMM_PARAM_AIFSN, + (u_int32) aifsn); + if (ret) + return ret; + + ret = AsicSetWmmParam(ad, wmm_idx, + (u_int32) ac_num, WMM_PARAM_CWMIN, + (u_int32) cw); + if (ret) + return ret; + + ret = AsicSetWmmParam(ad, wmm_idx, + (u_int32) ac_num, WMM_PARAM_CWMAX, + (u_int32) cw); + + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: qid=%d, slot_time=%d, sifs_time=%d, ", + __func__, q_idx, slot_time, sifs_time)); + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("ac_num=%d, aifsn=%d, cw=%d\n", ac_num, aifsn, cw)); + + return ret; +} + +s_int32 net_ad_clean_sta_q( + struct test_wlan_info *winfos, u_char wcid) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + struct qm_ops *ops = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + ops = ad->qm_ops; + + if (ops->sta_clean_queue) { + ret = ops->sta_clean_queue(ad, wcid); + if (ret) + ret = SERV_STATUS_OSAL_NET_FAIL_SEND_FWCMD; + } + + return ret; +} + +s_int32 net_ad_set_auto_resp( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx, u_char mode) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + u_char *sa = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + +#ifdef CONFIG_AP_SUPPORT + sa = configs->addr3[0]; +#endif +#ifdef CONFIG_STA_SUPPORT + sa = configs->addr2[0]; +#endif + + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s\n", __func__)); + + if (mode) { + if (sa) + sys_ad_move_mem(sa, &configs->own_mac, + SERV_MAC_ADDR_LEN); + + AsicDevInfoUpdate(ad, 0x0, (u_int8 *)&configs->own_mac, + band_idx, TRUE, DEVINFO_ACTIVE_FEATURE); + } else { + AsicDevInfoUpdate(ad, 0x0, (u_int8 *)ad->CurrentAddress, + band_idx, TRUE, DEVINFO_ACTIVE_FEATURE); + } + + return ret; +} + +s_int32 net_ad_set_low_power( + struct test_wlan_info *winfos, u_int32 control) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + if (control) + MlmeLpEnter(ad); + else + MlmeLpExit(ad); + + return ret; +} + +s_int32 net_ad_read_mac_bbp_reg( + struct test_wlan_info *winfos, + struct test_register *regs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + RTMP_IO_READ32(ad->hdev_ctrl, regs->cr_addr, regs->cr_val); + + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: cr_addr=0x%08x, cr_val=0x%08x\n", + __func__, regs->cr_addr, *regs->cr_val)); + + return ret; +} + +s_int32 net_ad_write_mac_bbp_reg( + struct test_wlan_info *winfos, + struct test_register *regs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + RTMP_IO_WRITE32(ad->hdev_ctrl, regs->cr_addr, *regs->cr_val); + + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: cr_addr=0x%08x, cr_val=0x%08x\n", + __func__, regs->cr_addr, *regs->cr_val)); + + return ret; +} + +s_int32 net_ad_read_bulk_mac_bbp_reg( + struct test_wlan_info *winfos, + struct test_configuration *configs, + struct test_register *regs) +{ +#define REG_BLOCK_SIZE 128 + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + u_int32 reg_seq, addr, reg_total, value; + u_char offset_byte = 0x4; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + addr = regs->cr_addr; + reg_total = regs->cr_num; + + for (reg_seq = 0; reg_seq < reg_total; reg_seq++) { + RTMP_IO_READ32(ad->hdev_ctrl, + addr, + &value); + + sys_ad_move_mem(regs->cr_val+reg_seq, + &value, sizeof(value)); + addr += offset_byte; + } + + return ret; +} + +s_int32 net_ad_read_bulk_rf_reg( + struct test_wlan_info *winfos, + struct test_register *regs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + u_int32 idx, addr, value; + u_int32 *dst; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + for (idx = 0; idx < regs->cr_num; idx++) { + addr = regs->cr_addr + (idx << 2); + dst = regs->cr_val + idx; + ret = MtCmdRFRegAccessRead(ad, regs->wf_sel, addr, &value); + if (ret) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("wf_sel=%d, cr_addr=0x%08x, ", + regs->wf_sel, addr)); + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("cr_val=0x%08x fail\n", value)); + break; + } + + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: wf_sel=%d, cr_addr=0x%08x, cr_val=0x%08x\n", + __func__, regs->wf_sel, addr, value)); + + sys_ad_move_mem(dst, &value, sizeof(value)); + } + + return ret; +} + +s_int32 net_ad_write_bulk_rf_reg( + struct test_wlan_info *winfos, + struct test_register *regs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + u_int32 idx, addr, value; + u_int32 *src; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + for (idx = 0; idx < regs->cr_num; idx++) { + addr = regs->cr_addr + (idx << 2); + src = regs->cr_val + idx; + sys_ad_move_mem(&value, src, sizeof(value)); + + ret = MtCmdRFRegAccessWrite(ad, regs->wf_sel, addr, value); + if (ret) { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("wf_sel=%d, cr_addr=0x%08x, ", + regs->wf_sel, addr)); + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("cr_val=0x%08x fail\n", value)); + break; + } + + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: wf_sel=%d, cr_addr=0x%08x, cr_val=0x%08x\n", + __func__, regs->wf_sel, addr, value)); + } + + return ret; +} + +void net_ad_read_ca53_reg(struct test_register *regs) +{ + u_long offset; + + regs->cr_addr = (u_long)ioremap(regs->cr_addr, CA53_GPIO_REMAP_SIZE); + sys_ad_move_mem((u_char *)&offset, (u_char *)®s->cr_addr, + sizeof(u_long)); + RTMP_SYS_IO_READ32(offset, regs->cr_val); + iounmap((void *)offset); +} + +void net_ad_write_ca53_reg(struct test_register *regs) +{ + u_long offset; + + regs->cr_addr = (u_long)ioremap(regs->cr_addr, CA53_GPIO_REMAP_SIZE); + sys_ad_move_mem((u_char *)&offset, (u_char *)®s->cr_addr, + sizeof(u_long)); + RTMP_SYS_IO_WRITE32(offset, *regs->cr_val); + iounmap((void *)offset); +} + +s_int32 net_ad_read_write_eeprom( + struct test_wlan_info *winfos, + struct test_eeprom *eprms, + boolean is_read) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + u_int16 value; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + if (is_read) { + RT28xx_EEPROM_READ16(ad, eprms->offset, value); + sys_ad_move_mem(eprms->value, &value, sizeof(value)); + } else + RT28xx_EEPROM_WRITE16(ad, eprms->offset, *eprms->value); + + return ret; +} + +s_int32 net_ad_read_write_bulk_eeprom( + struct test_wlan_info *winfos, + struct test_eeprom *eprms, + boolean is_read) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + u_int16 offset, length, value, eeprom_size = 0; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + eeprom_size = winfos->chip_cap.efuse_size; + if (is_read) { + RTMP_OS_NETDEV_STOP_QUEUE(ad->net_dev); + for (offset = 0 ; offset < (eeprom_size >> 1) ; offset++) { + RT28xx_EEPROM_READ16(ad, (offset << 1), value); + eprms->value[offset] = value; + } + + RTMP_OS_NETDEV_START_QUEUE(ad->net_dev); + } else { + offset = eprms->offset; + length = eprms->length; + +#if defined(RTMP_FLASH_SUPPORT) + + if (length == 16) + sys_ad_move_mem(ad->EEPROMImage + offset, + eprms->value + offset, length); + + else if (length == eeprom_size) + rtmp_ee_flash_write_all(ad); + + if (length != 16) +#endif /* RTMP_FLASH_SUPPORT */ + { + if ((offset + length) <= eeprom_size) { + u_int16 val_seq = 0; + + for (val_seq = 0; + val_seq < (length >> 1); + val_seq++) { + value = eprms->value[offset >> 1]; + RT28xx_EEPROM_WRITE16(ad, + offset, + value); + } + } else { + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: exceed eeprom size(%d), ", + __func__, EEPROM_SIZE)); + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("offset=0x%08x, length=%d, ", + offset, length)); + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("offset+length=0x%08x\n", + offset+length)); + } + } + } + + return ret; +} + +s_int32 net_ad_get_free_efuse_block( + struct test_wlan_info *winfos, + struct test_eeprom *eprms) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + eFuseGetFreeBlockCount(ad, &eprms->efuse_free_block); + + return ret; +} + +s_int32 net_ad_mps_tx_operation( + struct test_wlan_info *winfos, + struct test_configuration *configs, + boolean is_start_tx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_mps_cb *mps_cb; + struct test_mps_setting *mps_setting; + + mps_cb = &configs->mps_cb; + mps_setting = mps_cb->mps_setting; + if (!mps_setting || !mps_cb->mps_cnt) { + ret = SERV_STATUS_OSAL_NET_INVALID_NULL_POINTER; + goto err; + } + + if (is_start_tx) { + if (configs->op_mode & OP_MODE_MPS) { + ret = SERV_STATUS_OSAL_NET_FAIL; + goto err; + } + + if (mps_cb->setting_inuse) { + ret = SERV_STATUS_OSAL_NET_FAIL; + goto err; + } + + configs->op_mode |= fTEST_MPS; + mps_cb->ref_idx = 1; + mps_cb->setting_inuse = TRUE; + ret = net_ad_mps_load_setting(winfos, configs); + if (ret) + goto err; + + ret = net_ad_mps_dump_setting(configs, 0xFFFF); + } else { + configs->op_mode &= ~OP_MODE_TXFRAME; + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: op_mode=0x%x, inuse=0x%x, setting_addr=%p\n", + __func__, configs->op_mode, mps_cb->setting_inuse, + mps_setting)); + + if (!(configs->op_mode & OP_MODE_MPS) + && !mps_cb->setting_inuse) { + struct test_mps_setting **setting_addr = + &(mps_cb->mps_setting); + mps_cb->mps_cnt = 0; + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: before free mem=%p\n", + __func__, mps_setting)); + sys_ad_free_mem(*setting_addr); + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_TRACE, + ("%s: after free mem=%p\n", + __func__, mps_setting)); + *setting_addr = NULL; + } + } + + return ret; +err: + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: error, mps_cnt=%d, mps_setting=%p\n", + __func__, mps_cb->mps_cnt, mps_setting)); + SERV_LOG(SERV_DBG_CAT_ADAPT, SERV_DBG_LVL_ERROR, + ("%s: error, op_mode=0x%x, setting_inuse=0x%x\n", + __func__, configs->op_mode, mps_cb->setting_inuse)); + + return ret; +} + +s_int32 net_ad_set_tmr( + struct test_wlan_info *winfos, + struct test_tmr_info *tmr_info) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + s_char tmr_setting[8], tmr_hw_version[8]; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + if (tmr_info->version == TMR_HW_VER_100) + tmr_info->version = TMR_VER_1_0; + else if (tmr_info->version == TMR_HW_VER_150) + tmr_info->version = TMR_VER_1_5; + else if (tmr_info->version == TMR_HW_VER_200) + tmr_info->version = TMR_VER_2_0; + else { + SERV_LOG(SERV_DBG_CAT_ALL, SERV_DBG_LVL_ERROR, + ("%s: wrong version %d!!\n", + __func__, tmr_info->version)); + return SERV_STATUS_OSAL_NET_INVALID_PARAM; + } + + sprintf(tmr_setting, "%d", tmr_info->setting); + sprintf(tmr_hw_version, "%d", tmr_info->version); + + ret = TmrUpdateParameter(ad, tmr_info->through_hold, tmr_info->iter); + if (ret) + return SERV_STATUS_OSAL_NET_FAIL; + ret = setTmrVerProc(ad, tmr_hw_version); + if (ret) + return SERV_STATUS_OSAL_NET_FAIL; + ret = setTmrEnableProc(ad, tmr_setting); + + return ret; +} + +s_int32 net_ad_get_rxv_stat( + struct test_wlan_info *winfos, + u_char ctrl_band_idx, + struct test_rx_stat *rx_stat) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + RX_STATISTIC_RXV *rxv_stat; + u_char ant_idx = 0, user_idx = 0; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + rxv_stat = ad->rx_stat_rxv + ctrl_band_idx; + + /* update rx stat info (per antenna path) */ + for (ant_idx = 0; ant_idx < TEST_ANT_NUM; ant_idx++) { + rx_stat->rx_st_path[ant_idx].fagc_ib_rssi = + rxv_stat->FAGC_RSSI_IB[ant_idx]; + rx_stat->rx_st_path[ant_idx].fagc_wb_rssi = + rxv_stat->FAGC_RSSI_WB[ant_idx]; + rx_stat->rx_st_path[ant_idx].rcpi = + rxv_stat->RCPI[ant_idx]; + rx_stat->rx_st_path[ant_idx].rssi = + rxv_stat->RSSI[ant_idx]; + } + + /* update rx stat info (per user) */ + for (user_idx = 0; user_idx < TEST_USER_NUM; user_idx++) { + rx_stat->rx_st_user[user_idx].freq_offset_from_rx = + rxv_stat->FreqOffsetFromRx[user_idx]; + rx_stat->rx_st_user[user_idx].snr = + (u_int32)rxv_stat->SNR[user_idx]; + rx_stat->rx_st_user[user_idx].fcs_error_cnt = + rxv_stat->fcs_error_cnt[user_idx]; + } + + return ret; +} + +s_int32 net_ad_get_rxv_cnt( + struct test_wlan_info *winfos, + u_char ctrl_band_idx, + u_int32 *byte_cnt) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + chip_get_rxv_cnt(ad, ctrl_band_idx, byte_cnt); + + return ret; +} + +s_int32 net_ad_get_rxv_content( + struct test_wlan_info *winfos, + u_char ctrl_band_idx, + void *content) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + RTMP_ADAPTER *ad = NULL; + + /* Get adapter from jedi driver first */ + GET_PAD_FROM_NET_DEV(ad, winfos->net_dev); + if (ad == NULL) + return SERV_STATUS_OSAL_NET_INVALID_PAD; + + chip_get_rxv_content(ad, ctrl_band_idx, content); + + return ret; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/osal/jedi/sys_adaption_jedi.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/osal/jedi/sys_adaption_jedi.c new file mode 100644 index 0000000000000..b834d6db9c9fb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/glue/osal/jedi/sys_adaption_jedi.c @@ -0,0 +1,179 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#include "rt_config.h" +#include "sys_adaption.h" + +/***************************************************************************** + * Packet free related functions + *****************************************************************************/ +void sys_ad_free_pkt(void *packet) +{ + if (packet) { + dev_kfree_skb_any(SERV_PKT_TO_OSPKT(packet)); + packet = NULL; + } +} + +/***************************************************************************** + * OS memory allocate/manage/free related functions + *****************************************************************************/ +s_int32 sys_ad_alloc_mem(u_char **mem, u_long size) +{ + *mem = kmalloc(size, GFP_ATOMIC); + + if (*mem) + return SERV_STATUS_SUCCESS; + else + return SERV_STATUS_OSAL_SYS_FAIL; +} + +void sys_ad_free_mem(void *mem) +{ + ASSERT(mem); + kfree(mem); +} + +void sys_ad_zero_mem(void *ptr, u_long length) +{ + memset(ptr, 0, length); +} + +void sys_ad_set_mem(void *ptr, u_long length, u_char value) +{ + memset(ptr, value, length); +} + +void sys_ad_move_mem(void *dest, void *src, u_long length) +{ + memmove(dest, src, length); +} + +s_int32 sys_ad_cmp_mem(void *dest, void *src, u_long length) +{ + return memcmp(dest, src, length); +} + +/***************************************************************************** + * OS task create/manage/kill related functions + *****************************************************************************/ +static inline s_int32 _sys_ad_kill_os_task(struct serv_os_task *task) +{ + s_int32 ret = SERV_STATUS_OSAL_SYS_FAIL; + + if (task->kthread_task) { + if (kthread_stop(task->kthread_task) == 0) { + task->kthread_task = NULL; + ret = SERV_STATUS_SUCCESS; + } else { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_WARN, + ("%s kthread_task %s stop failed\n", __func__, + task->task_name)); + } + } else + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_WARN, + ("%s null kthread_task %s\n", __func__, + task->task_name)); + + return ret; +} + +static inline s_int32 _sys_ad_attach_os_task( + IN struct serv_os_task *task, IN SERV_OS_TASK_CALLBACK fn, + IN u_long arg) +{ + s_int32 status = SERV_STATUS_SUCCESS; + + task->task_killed = 0; + + if (task->kthread_task) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s non-null kthread_task %s\n", __func__, + task->task_name)); + status = SERV_STATUS_OSAL_SYS_FAIL; + goto done; + } + + task->kthread_task = kthread_run((cast_fn) fn, (void *)arg, + task->task_name); + + if (IS_ERR(task->kthread_task)) { + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s kthread_run %s err %ld\n", __func__, + task->task_name, PTR_ERR(task->kthread_task))); + task->kthread_task = NULL; + status = SERV_STATUS_OSAL_SYS_FAIL; + goto done; + } + +done: + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s %s end %d\n", __func__, task->task_name, status)); + + return status; +} + +static inline s_int32 _sys_ad_init_os_task( + IN struct serv_os_task *task, IN char *task_name, + IN void *priv_winfos, IN void *priv_configs) +{ + s_int32 len; + + ASSERT(task); + len = strlen(task_name); + len = len > (SERV_OS_TASK_NAME_LEN - 1) + ? (SERV_OS_TASK_NAME_LEN - 1) : len; + os_move_mem(&task->task_name[0], task_name, len); + + if (priv_winfos) + task->priv_winfos = priv_winfos; + + if (priv_configs) + task->priv_configs = priv_configs; + + init_waitqueue_head(&(task->kthread_q)); + + return SERV_STATUS_SUCCESS; +} + +boolean _sys_ad_wait_os_task( + IN void *reserved, IN struct serv_os_task *task, IN s_int32 *status) +{ + RTMP_WAIT_EVENT_INTERRUPTIBLE((*status), task); + + if ((task->task_killed == 1) || ((*status) != 0)) + return FALSE; + + return TRUE; +} + +s_int32 sys_ad_kill_os_task(struct serv_os_task *task) +{ + return _sys_ad_kill_os_task(task); +} + +s_int32 sys_ad_attach_os_task( + struct serv_os_task *task, SERV_OS_TASK_CALLBACK fn, u_long arg) +{ + return _sys_ad_attach_os_task(task, fn, arg); +} + +s_int32 sys_ad_init_os_task( + struct serv_os_task *task, char *task_name, + void *priv_winfos, void *priv_configs) +{ + return _sys_ad_init_os_task(task, task_name, + priv_winfos, priv_configs); +} + +boolean sys_ad_wait_os_task( + void *reserved, struct serv_os_task *task, s_int32 *status) +{ + return _sys_ad_wait_os_task(reserved, task, status); +} + +VOID sys_ad_wakeup_os_task(struct serv_os_task *task) +{ + WAKE_UP(task); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/include/agent.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/include/agent.h new file mode 100644 index 0000000000000..c170bbcdadc0f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/include/agent.h @@ -0,0 +1,344 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc + */ +#ifndef __AGENT_H__ +#define __AGENT_H__ + +#include "service_test.h" + +/***************************************************************************** + * Type definition + *****************************************************************************/ + +/***************************************************************************** + * Macro + *****************************************************************************/ +#define AGENT_CFG_ARGV_MAX 20 +#define SERV_TEST_ON(_config) ((((_config)->op_mode) & \ + OP_MODE_START) == OP_MODE_START) + +#define TEST_CMDREQ 0x0008 +#define TEST_CMDRSP 0x8008 +#define TEST_CMD_MAGIC_NO 0x18142880 + +#define TEST_CMD_REQ 0x0005 +#define TEST_CMD_RSP 0x8005 + +/***************************************************************************** + * Enum value definition + *****************************************************************************/ +/* String Parser State */ +enum { + AGENT_STATE_EOF = 0, + AGENT_STATE_TEXT = 1, + AGENT_STATE_NEWLINE = 2 +}; + +/* Service handle id */ +enum { + SERV_HANDLE_RESV = 0, + SERV_HANDLE_TEST = 1 +}; + +enum { + SERV_RX_STAT_TYPE_BAND = 0, + SERV_RX_STAT_TYPE_PATH, + SERV_RX_STAT_TYPE_USER, + SERV_RX_STAT_TYPE_COMM, + SERV_RX_STAT_TYPE_NUM +}; + +enum { + HQA_BAND_WIDTH_20 = 0, + HQA_BAND_WIDTH_40, + HQA_BAND_WIDTH_80, + HQA_BAND_WIDTH_10, + HQA_BAND_WIDTH_5, + HQA_BAND_WIDTH_160, + HQA_BAND_WIDTH_8080, + HQA_BAND_WIDTH_NUM +}; + +/***************************************************************************** + * Data struct definition + *****************************************************************************/ +/* Main service data struct */ +struct service { + u_int32 serv_id; + void *serv_handle; +}; + +#pragma pack(1) +struct GNU_PACKED hqa_set_ch { + u_int32 ext_id; + u_int32 num_param; + u_int32 band_idx; + u_int32 central_ch0; + u_int32 central_ch1; + u_int32 sys_bw; + u_int32 perpkt_bw; + u_int32 pri_sel; + u_int32 reason; + u_int32 ch_band; + u_int32 out_band_freq; +}; + +struct GNU_PACKED hqa_tx_content { + u_int32 ext_id; + u_int32 num_param; + u_int32 band_idx; + u_int32 fc; + u_int32 dur; + u_int32 seq; + u_int32 fixed_payload; /* Normal:0,Repeat:1,Random:2 */ + u_int32 txlen; + u_int32 payload_len; + u_char addr1[SERV_MAC_ADDR_LEN]; + u_char addr2[SERV_MAC_ADDR_LEN]; + u_char addr3[SERV_MAC_ADDR_LEN]; + u_char payload[0]; +}; + +struct GNU_PACKED hqa_tx { + u_int32 ext_id; + u_int32 num_param; + u_int32 band_idx; + u_int32 pkt_cnt; + u_int32 tx_mode; + u_int32 rate; + u_int32 pwr; + u_int32 stbc; + u_int32 ldpc; + u_int32 ibf; + u_int32 ebf; + u_int32 wlan_id; + u_int32 aifs; + u_int32 gi; + u_int32 tx_path; + u_int32 nss; + u_int32 hw_tx_enable; +}; + +struct GNU_PACKED hqa_frame { + u_int32 magic_no; + u_int16 type; + u_int16 id; + u_int16 length; + u_int16 sequence; + u_int8 data[SERV_IOCTLBUFF]; +}; + +struct GNU_PACKED hqa_frame_ctrl { + int8_t type; + union { + struct hqa_frame *hqa_frame_eth; + int8_t *hqa_frame_string; + } hqa_frame_comm; +}; + +struct GNU_PACKED hqa_tx_tone { + u_int32 band_idx; + u_int32 tx_tone_en; + u_int32 ant_idx; + u_int32 tone_type; + u_int32 tone_freq; + u_int32 dc_offset_I; + u_int32 dc_offset_Q; + u_int32 band; + u_int32 rf_pwr; + u_int32 digi_pwr; +}; + +struct GNU_PACKED hqa_continuous_tx { + u_int32 band_idx; + u_int32 tx_tone_en; + u_int32 ant_mask; + u_int32 tx_mode; + u_int32 bw; + u_int32 pri_ch; + u_int32 rate; + u_int32 central_ch; + u_int32 tx_fd_mode; +}; + +struct GNU_PACKED hqa_rx_stat_resp_format { + u_int32 type; + u_int32 version; + u_int32 item_mask; + u_int32 blk_cnt; + u_int32 blk_size; +}; + +struct GNU_PACKED hqa_rx_stat_band_info { + u_int32 mac_rx_fcs_err_cnt; + u_int32 mac_rx_mdrdy_cnt; + u_int32 mac_rx_len_mismatch; + u_int32 mac_rx_fcs_ok_cnt; + u_int32 phy_rx_fcs_err_cnt_cck; + u_int32 phy_rx_fcs_err_cnt_ofdm; + u_int32 phy_rx_pd_cck; + u_int32 phy_rx_pd_ofdm; + u_int32 phy_rx_sig_err_cck; + u_int32 phy_rx_sfd_err_cck; + u_int32 phy_rx_sig_err_ofdm; + u_int32 phy_rx_tag_err_ofdm; + u_int32 phy_rx_mdrdy_cnt_cck; + u_int32 phy_rx_mdrdy_cnt_ofdm; +}; + +struct GNU_PACKED hqa_rx_stat_path_info { + u_int32 rcpi; + u_int32 rssi; + u_int32 fagc_ib_rssi; + u_int32 fagc_wb_rssi; + u_int32 inst_ib_rssi; + u_int32 inst_wb_rssi; +}; + +struct GNU_PACKED hqa_rx_stat_user_info { + s_int32 freq_offset_from_rx; + u_int32 snr; + u_int32 fcs_error_cnt; +}; + +struct GNU_PACKED hqa_rx_stat_comm_info { + u_int32 rx_fifo_full; + u_int32 aci_hit_low; + u_int32 aci_hit_high; + u_int32 mu_pkt_count; + u_int32 sig_mcs; + u_int32 sinr; + u_int32 driver_rx_count; +}; + +struct GNU_PACKED hqa_rx_stat_leg { + u_int32 mac_rx_fcs_err_cnt; + u_int32 mac_rx_mdrdy_cnt; + u_int32 phy_rx_fcs_err_cnt_cck; + u_int32 phy_rx_fcs_err_cnt_ofdm; + u_int32 phy_rx_pd_cck; + u_int32 phy_rx_pd_ofdm; + u_int32 phy_rx_sig_err_cck; + u_int32 phy_rx_sfd_err_cck; + u_int32 phy_rx_sig_err_ofdm; + u_int32 phy_rx_tag_err_ofdm; + u_int32 wb_rssi0; + u_int32 ib_rssi0; + u_int32 wb_rssi1; + u_int32 ib_rssi1; + u_int32 phy_rx_mdrdy_cnt_cck; + u_int32 phy_rx_mdrdy_cnt_ofdm; + u_int32 driver_rx_cnt; + u_int32 rcpi0; + u_int32 rcpi1; + s_int32 freq_offset_rx; + u_int32 rssi0; + u_int32 rssi1; + u_int32 rx_fifo_full; + u_int32 mac_rx_len_mismatch; + u_int32 mac_rx_fcs_err_cnt_band1; + u_int32 mac_rx_mdrdy_cnt_band1; + u_int32 fagc_ib_rssi[TEST_ANT_NUM]; + u_int32 fagc_wb_rssi[TEST_ANT_NUM]; + u_int32 inst_ib_rssi[TEST_ANT_NUM]; + u_int32 inst_wb_rssi[TEST_ANT_NUM]; + u_int32 aci_hit_low; + u_int32 aci_git_high; + u_int32 driver_rx_cnt1; + u_int32 rcpi2; + u_int32 rcpi3; + u_int32 rssi2; + u_int32 rssi3; + u_int32 snr0; + u_int32 snr1; + u_int32 snr2; + u_int32 snr3; + u_int32 rx_fifo_full_band1; + u_int32 mac_rx_len_mismatch_band1; + u_int32 phy_rx_pd_cck_band1; + u_int32 phy_rx_pd_ofdm_band1; + u_int32 phy_rx_sig_err_cck_band1; + u_int32 phy_rx_sfd_err_cck_band1; + u_int32 phy_rx_sig_err_ofdm_band1; + u_int32 phy_rx_tag_err_ofdm_band1; + u_int32 phy_rx_mdrdy_cnt_cck_band1; + u_int32 phy_rx_mdrdy_cnt_ofdm_band1; + u_int32 phy_rx_fcs_err_cnt_cck_band1; + u_int32 phy_rx_fcs_err_cnt_ofdm_band1; + u_int32 mu_pkt_cnt; + u_int32 sig_mcs; + u_int32 sinr; + u_int32 rxv_rssi; + u_int32 mac_rx_fcs_ok_cnt; + u_int32 leg_rssi_sub[8]; + s_int32 user_rx_freq_offset[TEST_USER_NUM]; + u_int32 user_snr[TEST_USER_NUM]; + u_int32 fcs_error_cnt[TEST_USER_NUM]; +}; + +#pragma pack() + +struct hqa_cmd_entry { + u_int8 index; + s_int32 (*handler)(struct service_test *serv_test, + struct hqa_frame *hqa_frame); +}; + +struct hqa_cmd_table { + struct hqa_cmd_entry *cmd_set; + u_int32 cmd_set_size; + u_int32 cmd_offset; +}; + +struct agent_cfg_parse_state_s { + s_int8 *ptr; + s_int8 *text; + u_int32 textsize; + s_int32 nexttoken; + u_int32 maxsize; +}; + +struct priv_hqa_cmd_id_mapping { + u_int8 *cmd_str; + u_int16 cmd_id; + u_int8 para_size[AGENT_CFG_ARGV_MAX]; +}; + +struct agent_cli_act_handler { + u_char name[100]; + s_int32 (*handler)(struct service_test *serv_test); +}; + +struct agent_cli_set_w_handler { + u_char name[100]; + s_int32 (*handler)(struct service_test *serv_test, + struct hqa_frame *hqa_cmd); +}; + +struct agent_cli_set_dw_handler { + u_char name[100]; + s_int32 (*handler)(struct service_test *serv_test, + struct hqa_frame *hqa_cmd); +}; + +struct agent_cli_set_ext_handler { + u_char name[100]; + s_int32 (*handler)(struct service_test *serv_test, + u_char *arg); +}; + +/***************************************************************************** + * Function declaration + *****************************************************************************/ +s_int32 mt_agent_hqa_cmd_handler( + struct service *serv, struct hqa_frame_ctrl *hqa_frame_ctrl); +s_int32 mt_agent_init_service(struct service *serv); +s_int32 mt_agent_exit_service(struct service *serv); +s_int32 mt_agent_cli_act(u_char *name, struct service *serv); +s_int32 mt_agent_cli_set_w(u_char *name, struct service *serv, u_char *param); +s_int32 mt_agent_cli_set_dw(u_char *name, struct service *serv, u_char *param); +s_int32 mt_agent_cli_set_ext(u_char *name, + struct service *serv, u_char *arg); + +#endif /* __AGENT_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/service/include/service_test.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/service/include/service_test.h new file mode 100644 index 0000000000000..d38f118257702 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/service/include/service_test.h @@ -0,0 +1,282 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#ifndef __SERVICE_TEST_H__ +#define __SERVICE_TEST_H__ + +#include "test_engine.h" +#include "operation.h" + +/***************************************************************************** + * Macro + *****************************************************************************/ +#define SERV_GET_PARAM(_struct, _member) \ + (_struct->_member) +#define SERV_GET_PADDR(_struct, _member) \ + (&_struct->_member) +#define SERV_SET_PARAM(_struct, _member, _val) \ + (_struct->_member = _val) +#define WINFO_GET_PARAM(_struct, _member) \ + (_struct->test_winfo->_member) +#define WINFO_GET_PADDR(_struct, _member) \ + (&_struct->test_winfo->_member) +#define WINFO_SET_PARAM(_struct, _member, _val) \ + (_struct->test_winfo->_member = _val) +#define BSTATE_GET_PARAM(_struct, _member) \ + (_struct->test_bstat._member) +#define BSTATE_SET_PARAM(_struct, _member, _val) \ + (_struct->test_bstat._member = _val) +#define CONFIG_GET_PARAM(_struct, _member, _bandidx) \ + (_struct->test_config[_bandidx]._member) +#define CONFIG_GET_PADDR(_struct, _member, _bandidx) \ + (&_struct->test_config[_bandidx]._member) +#define CONFIG_SET_PARAM(_struct, _member, _val, _bandidx) \ + (_struct->test_config[_bandidx]._member = _val) +#define CONFIG_SET_PADDR(_struct, _member, _val, _size, _bandidx) ({ \ + struct test_configuration *configs; \ + configs = &_struct->test_config[_bandidx]; \ + (sys_ad_move_mem(configs->_member, _val, _size)); \ + }) +#define EEPROM_GET_PARAM(_struct, _member) \ + (_struct->test_eprm._member) +#define EEPROM_SET_PARAM(_struct, _member, _val) \ + (_struct->test_eprm._member = _val) + + +/***************************************************************************** + * Enum value definition + *****************************************************************************/ +/* Service test item id */ +enum { + SERV_TEST_ITEM_INIT = 0, + SERV_TEST_ITEM_EXIT, + SERV_TEST_ITEM_START, + SERV_TEST_ITEM_STOP, + SERV_TEST_ITEM_START_TX, + SERV_TEST_ITEM_STOP_TX, + SERV_TEST_ITEM_START_RX, + SERV_TEST_ITEM_STOP_RX +}; + +/* Service test register/eeprom related operation */ +enum { + SERV_TEST_REG_MAC_READ = 0, + SERV_TEST_REG_MAC_WRITE, + SERV_TEST_REG_MAC_READ_BULK, + SERV_TEST_REG_RF_READ_BULK, + SERV_TEST_REG_RF_WRITE_BULK, + SERV_TEST_REG_CA53_READ, + SERV_TEST_REG_CA53_WRITE, + + SERV_TEST_EEPROM_READ = 10, + SERV_TEST_EEPROM_WRITE, + SERV_TEST_EEPROM_READ_BULK, + SERV_TEST_EEPROM_WRITE_BULK, + SERV_TEST_EEPROM_GET_FREE_EFUSE_BLOCK +}; + +/* Service test mps related operation */ +enum { + SERV_TEST_MPS_START_TX = 0, + SERV_TEST_MPS_STOP_TX +}; + +/* Service test tx power related operation */ +enum { + SERV_TEST_TXPWR_SET_PWR = 0, + SERV_TEST_TXPWR_GET_PWR, + SERV_TEST_TXPWR_SET_PWR_INIT, + SERV_TEST_TXPWR_SET_PWR_MAN, +}; + +/***************************************************************************** + * Data struct definition + *****************************************************************************/ +/* Service data struct for test mode usage */ +struct service_test { + /*========== Jedi only ==========*/ + /* Wlan related information which test needs */ + struct test_wlan_info *test_winfo; + + /* Test backup CR */ + struct test_bk_cr test_bkcr[TEST_MAX_BKCR_NUM]; + + /* Test Rx statistic */ + struct test_rx_stat test_rx_statistic[TEST_DBDC_BAND_NUM]; + + /* The band related state which communicate between UI/driver */ + struct test_band_state test_bstat; + + /* The band_idx which user wants to control currently */ + u_char ctrl_band_idx; + + struct test_backup_params test_backup; + + /*========== Common part ==========*/ + /* Test configuration */ + struct test_configuration test_config[TEST_DBDC_BAND_NUM]; + + /* Test operation */ + struct test_operation *test_op; + + /* Test control register read/write */ + struct test_register test_reg; + + /* Test eeprom read/write */ + struct test_eeprom test_eprm; + + /* Test tmr related configuration */ + struct test_tmr_info test_tmr; + + /* Jedi: false, Gen4m: true */ + boolean engine_offload; + + /* TODO: factor out here for log dump */ + u_int32 en_log; + /* struct _ATE_LOG_DUMP_CB log_dump[ATE_LOG_TYPE_NUM]; */ +}; + +/***************************************************************************** + * Function declaration + *****************************************************************************/ +s_int32 mt_serv_init_test(struct service_test *serv_test); +s_int32 mt_serv_exit_test(struct service_test *serv_test); +s_int32 mt_serv_start(struct service_test *serv_test); +s_int32 mt_serv_stop(struct service_test *serv_test); +s_int32 mt_serv_set_channel(struct service_test *serv_test); +s_int32 mt_serv_set_tx_content(struct service_test *serv_test); +s_int32 mt_serv_set_tx_path(struct service_test *serv_test); +s_int32 mt_serv_set_rx_path(struct service_test *serv_test); +s_int32 mt_serv_submit_tx(struct service_test *serv_test); +s_int32 mt_serv_revert_tx(struct service_test *serv_test); +s_int32 mt_serv_start_tx(struct service_test *serv_test); +s_int32 mt_serv_stop_tx(struct service_test *serv_test); +s_int32 mt_serv_start_rx(struct service_test *serv_test); +s_int32 mt_serv_stop_rx(struct service_test *serv_test); +s_int32 mt_serv_set_freq_offset(struct service_test *serv_test); +s_int32 mt_serv_tx_power_operation( + struct service_test *serv_test, u_int32 item); +s_int32 mt_serv_get_freq_offset( + struct service_test *serv_test, u_int32 *freq_offset); +s_int32 mt_serv_get_cfg_on_off( + struct service_test *serv_test, + u_int32 type, u_int32 *result); +s_int32 mt_serv_get_tx_tone_pwr( + struct service_test *serv_test, + u_int32 ant_idx, u_int32 *power); +s_int32 mt_serv_get_thermal_val( + struct service_test *serv_test, + u_char band_idx, + u_int32 *value); +s_int32 mt_serv_set_cal_bypass( + struct service_test *serv_test, + u_int32 cal_item); +s_int32 mt_serv_set_dpd( + struct service_test *serv_test, + u_int32 on_off, + u_int32 wf_sel); +s_int32 mt_serv_set_tssi( + struct service_test *serv_test, + u_int32 on_off, + u_int32 wf_sel); +s_int32 mt_serv_set_rdd_on_off( + struct service_test *serv_test, + u_int32 rdd_num, + u_int32 rdd_sel, + u_int32 enable); +s_int32 mt_serv_set_off_ch_scan( + struct service_test *serv_test); +s_int32 mt_serv_set_icap_start( + struct service_test *serv_test, + struct hqa_rbist_cap_start *icap_info); +s_int32 mt_serv_get_icap_status( + struct service_test *serv_test, + s_int32 *icap_stat); +s_int32 mt_serv_get_icap_max_data_len( + struct service_test *serv_test, + u_long *max_data_len); +s_int32 mt_serv_get_icap_data( + struct service_test *serv_test, + s_int32 *icap_cnt, + s_int32 *icap_data, + u_int32 wf_num, + u_int32 iq_type); +s_int32 mt_serv_get_recal_cnt( + struct service_test *serv_test, + u_int32 *recal_cnt, + u_int32 *recal_dw_num); +s_int32 mt_serv_get_recal_content( + struct service_test *serv_test, + u_int32 *content); +s_int32 mt_serv_get_rxv_cnt( + struct service_test *serv_test, + u_int32 *rxv_cnt, + u_int32 *rxv_dw_num); +s_int32 mt_serv_get_rxv_content( + struct service_test *serv_test, + u_int32 dw_cnt, + u_int32 *content); +s_int32 mt_serv_get_rdd_cnt( + struct service_test *serv_test, + u_int32 *rdd_cnt, + u_int32 *rdd_dw_num); +s_int32 mt_serv_get_rdd_content( + struct service_test *serv_test, + u_int32 *content, + u_int32 *total_cnt); +s_int32 mt_serv_reset_txrx_counter(struct service_test *serv_test); +s_int32 mt_serv_set_rx_vector_idx( + struct service_test *serv_test, u_int32 group1, u_int32 group2); +s_int32 mt_serv_set_fagc_rssi_path( + struct service_test *serv_test); +s_int32 mt_serv_get_rx_stat_leg( + struct service_test *serv_test, + struct test_rx_stat_leg *rx_stat); +s_int32 mt_serv_get_capability( + struct service_test *serv_test, + struct test_capability *capability); +s_int32 mt_serv_calibration_test_mode( + struct service_test *serv_test, u_char mode); +s_int32 mt_serv_do_cal_item( + struct service_test *serv_test, u_int32 item); +s_int32 mt_serv_set_band_mode(struct service_test *serv_test); +s_int32 mt_serv_get_band_mode(struct service_test *serv_test); +s_int32 mt_serv_log_on_off( + struct service_test *serv_test, u_int32 log_type, + u_int32 log_ctrl, u_int32 log_size); +s_int32 mt_serv_set_cfg_on_off(struct service_test *serv_test); +s_int32 mt_serv_set_rx_filter_pkt_len(struct service_test *serv_test); +s_int32 mt_serv_get_wf_path_comb(struct service_test *serv_test, + u_int8 band_idx, boolean dbdc_mode_en, u_int8 *path, u_int8 *path_len); +s_int32 mt_serv_set_low_power( + struct service_test *serv_test, u_int32 control); +s_int32 mt_serv_get_antswap_capability( + struct service_test *serv_test, u_int32 *antswap_support); +s_int32 mt_serv_set_antswap( + struct service_test *serv_test, u_int32 ant); +s_int32 mt_serv_reg_eprm_operation( + struct service_test *serv_test, u_int32 item); +s_int32 mt_serv_mps_operation( + struct service_test *serv_test, u_int32 item); +s_int32 mt_serv_get_chipid(struct service_test *serv_test); +s_int32 mt_serv_mps_set_nss(struct service_test *serv_test); +s_int32 mt_serv_mps_set_per_packet_bw(struct service_test *serv_test); +s_int32 mt_serv_mps_set_packet_count(struct service_test *serv_test); +s_int32 mt_serv_mps_set_payload_length(struct service_test *serv_test); +s_int32 mt_serv_mps_set_power_gain(struct service_test *serv_test); +s_int32 mt_serv_mps_set_seq_data(struct service_test *serv_test); +s_int32 mt_serv_set_tmr(struct service_test *serv_test); +s_int32 mt_serv_set_preamble(struct service_test *serv_test); +s_int32 mt_serv_set_rate(struct service_test *serv_test); +s_int32 mt_serv_set_system_bw(struct service_test *serv_test); +s_int32 mt_serv_set_per_pkt_bw(struct service_test *serv_test); +s_int32 mt_serv_dbdc_tx_tone(struct service_test *serv_test); +s_int32 mt_serv_dbdc_tx_tone_pwr(struct service_test *serv_test); +s_int32 mt_serv_dbdc_continuous_tx(struct service_test *serv_test); +s_int32 mt_serv_get_tx_info(struct service_test *serv_test); +s_int32 mt_serv_main(struct service_test *serv_test, u_int32 test_item); +s_int32 mt_serv_get_rx_stat(struct service_test *serv_test, u_int8 band_idx, + u_int8 blk_idx, u_int8 test_rx_stat_cat, struct test_rx_stat_u *st); + +#endif /* __SERVICE_TEST_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/service/include/test_engine.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/service/include/test_engine.h new file mode 100644 index 0000000000000..d08b0adf3e288 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/service/include/test_engine.h @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#ifndef __TEST_ENGINE_H__ +#define __TEST_ENGINE_H__ + +#include "operation.h" + +/***************************************************************************** + * Macrolog_dump + *****************************************************************************/ +#define engine_min(_a, _b) ((_a > _b) ? _b : _a) + +#define engine_max(_a, _b) ((_a > _b) ? _a : _b) + +#define engine_ceil(_a, _b) (((_a%_b) > 0) ? ((_a/_b)+1) : (_a/_b)) + +#define TEST_ANT_USER_DEF 0x80000000 + +/***************************************************************************** + * Enum value definition + *****************************************************************************/ +enum TEST_HETB_CTRL { + OP_HETB_TX_CFG = 0, + OP_HETB_TX_START = 1, + OP_HETB_TX_STOP = 2, + OP_HETB_RX_CFG = 3, +}; + +/***************************************************************************** + * Data struct definition + *****************************************************************************/ +struct test_he_ru_const { + u_int8 max_index; + u_int16 sd; /* data subcarriers */ + u_int16 sd_d; /* data subcarriers for DCM */ + u_int16 sd_s; /* data subcarriers short */ + u_int16 sd_s_d; /* data subcarriers short for DCM*/ +}; + +/***************************************************************************** + * Function declaration + *****************************************************************************/ +s_int32 mt_engine_search_stack( + struct test_configuration *configs, + u_int8 wcid, + void **virtual_wtbl); +s_int32 mt_engine_subscribe_tx( + struct test_operation *ops, + struct test_wlan_info *winfos, + struct test_configuration *configs); +s_int32 mt_engine_unsubscribe_tx( + struct test_operation *ops, + struct test_wlan_info *winfos, + struct test_configuration *configs); +s_int32 mt_engine_start( + struct test_wlan_info *winfos, + struct test_backup_params *bak, + struct test_configuration *configs, + struct test_operation *ops, + struct test_bk_cr *bks, + struct test_rx_stat *rx_stat, + u_int32 en_log); +s_int32 mt_engine_stop( + struct test_wlan_info *winfos, + struct test_backup_params *bak, + struct test_configuration *configs, + struct test_operation *ops, + struct test_bk_cr *bks); +s_int32 mt_engine_calc_ipg_param_by_ipg( + struct test_configuration *configs); +s_int32 mt_engine_set_auto_resp( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx, u_char mode); +s_int32 mt_engine_start_tx( + struct test_wlan_info *winfos, + struct test_configuration *configs, + struct test_operation *ops, + u_char band_idx); +s_int32 mt_engine_stop_tx( + struct test_wlan_info *winfos, + struct test_configuration *configs, + struct test_operation *ops, + u_char band_idx); +s_int32 mt_engine_start_rx( + struct test_wlan_info *winfos, + struct test_configuration *configs, + struct test_operation *ops, + u_char band_idx); +s_int32 mt_engine_stop_rx( + struct test_wlan_info *winfos, + struct test_configuration *configs, + struct test_operation *ops, + u_char band_idx); + +#endif /* __TEST_ENGINE_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/service/service_test.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/service/service_test.c new file mode 100644 index 0000000000000..ba6985f64ca06 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/service/service_test.c @@ -0,0 +1,2479 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#include "service_test.h" + +u_char template_frame[32] = { 0x88, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0xAA, 0xBB, 0x12, 0x34, 0x56, + 0x00, 0x11, 0x22, 0xAA, 0xBB, 0xCC, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/***************************************************************************** + * Internal functions + *****************************************************************************/ +static s_int32 mt_serv_init_op(struct test_operation *ops) +{ + ops->op_set_tr_mac = mt_op_set_tr_mac; + ops->op_set_tx_stream = mt_op_set_tx_stream; + ops->op_set_tx_path = mt_op_set_tx_path; + ops->op_set_rx_path = mt_op_set_rx_path; + ops->op_set_rx_filter = mt_op_set_rx_filter; + ops->op_set_clean_persta_txq = mt_op_set_clean_persta_txq; + ops->op_set_cfg_on_off = mt_op_set_cfg_on_off; + ops->op_log_on_off = mt_op_log_on_off; + ops->op_dbdc_tx_tone = mt_op_dbdc_tx_tone; + ops->op_dbdc_tx_tone_pwr = mt_op_dbdc_tx_tone_pwr; + ops->op_dbdc_continuous_tx = mt_op_dbdc_continuous_tx; + ops->op_get_tx_info = mt_op_get_tx_info; + ops->op_set_antenna_port = mt_op_set_antenna_port; + ops->op_set_slot_time = mt_op_set_slot_time; + ops->op_set_power_drop_level = mt_op_set_power_drop_level; + ops->op_get_antswap_capability = mt_op_get_antswap_capability; + ops->op_set_antswap = mt_op_set_antswap; + ops->op_set_rx_filter_pkt_len = mt_op_set_rx_filter_pkt_len; + ops->op_set_freq_offset = mt_op_set_freq_offset; + ops->op_set_phy_counter = mt_op_set_phy_counter; + ops->op_set_rxv_index = mt_op_set_rxv_index; + ops->op_set_fagc_path = mt_op_set_fagc_path; + ops->op_set_fw_mode = mt_op_set_fw_mode; + ops->op_set_rf_test_mode = mt_op_set_rf_test_mode; + ops->op_set_test_mode_start = mt_op_set_test_mode_start; + ops->op_set_test_mode_abort = mt_op_set_test_mode_abort; + ops->op_start_tx = mt_op_start_tx; + ops->op_stop_tx = mt_op_stop_tx; + ops->op_start_rx = mt_op_start_rx; + ops->op_stop_rx = mt_op_stop_rx; + ops->op_set_channel = mt_op_set_channel; + ops->op_set_tx_content = mt_op_set_tx_content; + ops->op_set_preamble = mt_op_set_preamble; + ops->op_set_rate = mt_op_set_rate; + ops->op_set_system_bw = mt_op_set_system_bw; + ops->op_set_per_pkt_bw = mt_op_set_per_pkt_bw; + ops->op_reset_txrx_counter = mt_op_reset_txrx_counter; + ops->op_set_rx_vector_idx = mt_op_set_rx_vector_idx; + ops->op_set_fagc_rssi_path = mt_op_set_fagc_rssi_path; + ops->op_get_rx_stat_leg = mt_op_get_rx_stat_leg; + ops->op_get_rx_statistics_all = mt_op_get_rx_statistics_all; + ops->op_get_capability = mt_op_get_capability; + ops->op_calibration_test_mode = mt_op_calibration_test_mode; + ops->op_set_icap_start = mt_op_set_icap_start; + ops->op_get_icap_status = mt_op_get_icap_status; + ops->op_get_icap_max_data_len = mt_op_get_icap_max_data_len; + ops->op_get_icap_data = mt_op_get_icap_data; + ops->op_do_cal_item = mt_op_do_cal_item; + ops->op_set_band_mode = mt_op_set_band_mode; + ops->op_get_chipid = mt_op_get_chipid; + ops->op_mps_start = mt_op_mps_start; + ops->op_mps_set_nss = mt_op_mps_set_nss; + ops->op_mps_set_per_packet_bw = mt_op_mps_set_per_packet_bw; + ops->op_mps_set_packet_count = mt_op_mps_set_packet_count; + ops->op_mps_set_payload_length = mt_op_mps_set_payload_length; + ops->op_mps_set_power_gain = mt_op_mps_set_power_gain; + ops->op_mps_set_seq_data = mt_op_mps_set_seq_data; + ops->op_get_tx_pwr = mt_op_get_tx_pwr; + ops->op_set_tx_pwr = mt_op_set_tx_pwr; + ops->op_get_freq_offset = mt_op_get_freq_offset; + ops->op_get_cfg_on_off = mt_op_get_cfg_on_off; + ops->op_get_tx_tone_pwr = mt_op_get_tx_tone_pwr; + ops->op_get_recal_cnt = mt_op_get_recal_cnt; + ops->op_get_recal_content = mt_op_get_recal_content; + ops->op_get_rxv_cnt = mt_op_get_rxv_cnt; + ops->op_get_rxv_content = mt_op_get_rxv_content; + ops->op_get_thermal_val = mt_op_get_thermal_val; + ops->op_set_cal_bypass = mt_op_set_cal_bypass; + ops->op_set_dpd = mt_op_set_dpd; + ops->op_set_tssi = mt_op_set_tssi; + ops->op_set_rdd_test = mt_op_set_rdd_test; + ops->op_get_wf_path_comb = mt_op_get_wf_path_comb; + ops->op_set_off_ch_scan = mt_op_set_off_ch_scan; + ops->op_get_rdd_cnt = mt_op_get_rdd_cnt; + ops->op_get_rdd_content = mt_op_get_rdd_content; + ops->op_set_muru_manual = mt_op_set_muru_manual; + ops->op_set_tam_arb = mt_op_set_tam_arb; + ops->op_hetb_ctrl = mt_op_hetb_ctrl; + ops->op_set_ru_aid = mt_op_set_ru_aid; + ops->op_set_mutb_spe = mt_op_set_mutb_spe; + ops->op_get_rx_stat_band = mt_op_get_rx_stat_band; + ops->op_get_rx_stat_path = mt_op_get_rx_stat_path; + ops->op_get_rx_stat_user = mt_op_get_rx_stat_user; + ops->op_get_rx_stat_comm = mt_op_get_rx_stat_comm; + /* For test mac usage */ + ops->op_backup_and_set_cr = mt_op_backup_and_set_cr; + ops->op_restore_cr = mt_op_restore_cr; + ops->op_set_ampdu_ba_limit = mt_op_set_ampdu_ba_limit; + ops->op_set_sta_pause_cr = mt_op_set_sta_pause_cr; + ops->op_set_ifs_cr = mt_op_set_ifs_cr; + ops->op_write_mac_bbp_reg = mt_op_write_mac_bbp_reg; + ops->op_read_bulk_mac_bbp_reg = mt_op_read_bulk_mac_bbp_reg; + ops->op_read_bulk_rf_reg = mt_op_read_bulk_rf_reg; + ops->op_write_bulk_rf_reg = mt_op_write_bulk_rf_reg; + ops->op_read_bulk_eeprom = mt_op_read_bulk_eeprom; + + return SERV_STATUS_SUCCESS; +} + +static s_int32 mt_serv_init_config( + struct test_configuration *configs, u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + if (band_idx == TEST_DBDC_BAND0) { + /* Operated mode init */ + configs->op_mode = OP_MODE_STOP; + + /* Test packet init */ + ret = sys_ad_alloc_mem((u_char **) &configs->test_pkt, + TEST_PKT_LEN); + configs->pkt_skb = NULL; + + /* OS related init */ + SERV_OS_INIT_COMPLETION(&configs->tx_wait); + configs->tx_status = 0; + + /* Hardware resource init */ + configs->wdev_idx = 0; + configs->wmm_idx = 0; + configs->ac_idx = SERV_QID_AC_BE; + + /* Tx frame init */ + sys_ad_move_mem(&configs->template_frame, &template_frame, 32); + configs->addr1[0][0] = 0x00; + configs->addr1[0][1] = 0x11; + configs->addr1[0][2] = 0x22; + configs->addr1[0][3] = 0xAA; + configs->addr1[0][4] = 0xBB; + configs->addr1[0][5] = 0xCC; + sys_ad_move_mem(configs->addr2[0], configs->addr1[0], + SERV_MAC_ADDR_LEN); + sys_ad_move_mem(configs->addr3[0], &configs->addr1[0], + SERV_MAC_ADDR_LEN); + configs->payload[0] = 0xAA; + configs->seq = 0; + configs->hdr_len = SERV_LENGTH_802_11; + configs->pl_len = 1; + configs->tx_len = 1058; + configs->fixed_payload = 1; + configs->max_pkt_ext = 2; + configs->retry = 1; + + /* Tx strategy/type init */ + configs->txs_enable = FALSE; + configs->tx_strategy = TEST_TX_STRA_THREAD; + configs->rate_ctrl_type = TEST_TX_TYPE_TXD; + + /* Tx timing init */ + configs->duty_cycle = 0; + configs->tx_time_param.pkt_tx_time_en = FALSE; + configs->tx_time_param.pkt_tx_time = 0; + configs->ipg_param.ipg = 0; + configs->ipg_param.sig_ext = TEST_SIG_EXTENSION; + configs->ipg_param.slot_time = TEST_DEFAULT_SLOT_TIME; + configs->ipg_param.sifs_time = TEST_DEFAULT_SIFS_TIME; + configs->ipg_param.ac_num = SERV_QID_AC_BE; + configs->ipg_param.aifsn = TEST_MIN_AIFSN; + configs->ipg_param.cw = TEST_MIN_CW; + configs->ipg_param.txop = 0; + + /* Rx init */ + sys_ad_zero_mem(&configs->own_mac, SERV_MAC_ADDR_LEN); + + /* Test tx statistic and txs init */ + configs->txs_enable = FALSE; + sys_ad_zero_mem(&configs->tx_stat, + sizeof(struct test_tx_statistic)); + + /* Phy */ + configs->tx_ant = 1; + configs->rx_ant = 1; + + /* TODO: factor out here for phy */ + configs->channel = 1; + configs->ch_band = 0; + configs->ctrl_ch = 1; +#if 0 + if (BOARD_IS_5G_ONLY(pAd)) + configs->channel = 36; + else + configs->channel = 1; +#endif + configs->tx_mode = TEST_MODE_OFDM; + configs->bw = TEST_BW_20; + configs->mcs = 7; + configs->sgi = 0; + + /* tx power */ + configs->tx_pwr_sku_en = FALSE; + configs->tx_pwr_percentage_en = FALSE; + configs->tx_pwr_backoff_en = FALSE; + configs->tx_pwr_percentage_level = 100; + } +/* #ifdef DBDC_MODE */ +#if 0 + else if (band_idx == TEST_DBDC_BAND1) { + /* Operated mode init */ + configs->op_mode = OP_MODE_STOP; + + /* Test packet init */ + ret = sys_ad_alloc_mem((u_char **) &configs->test_pkt, + TEST_PKT_LEN); + configs->pkt_skb = NULL; + + /* OS related init */ + SERV_OS_INIT_COMPLETION(&configs->tx_wait); + configs->tx_status = 0; + + /* Hardware resource init */ + configs->wdev_idx = 1; + configs->wmm_idx = 1; + configs->ac_idx = SERV_QID_AC_BE; + + /* Tx frame init */ + sys_ad_move_mem(&configs->template_frame, &template_frame, 32); + configs->addr1[0][0] = 0x00; + configs->addr1[1][0] = 0x11; + configs->addr1[2][0] = 0x22; + configs->addr1[3][0] = 0xAA; + configs->addr1[4][0] = 0xBB; + configs->addr1[5][0] = 0xCC; + sys_ad_move_mem(&configs->addr2, &configs->addr1, + SERV_MAC_ADDR_LEN); + sys_ad_move_mem(&configs->addr3, &configs->addr1, + SERV_MAC_ADDR_LEN); + configs->payload[0] = 0xAA; + configs->seq = 0; + configs->hdr_len = SERV_LENGTH_802_11; + configs->pl_len = 1; + configs->tx_len = 1024; + configs->fixed_payload = 1; + configs->max_pkt_ext = 2; + configs->retry = 1; + + /* Tx strategy/type init */ + configs->tx_strategy = TEST_TX_STRA_THREAD; + configs->rate_ctrl_type = TEST_TX_TYPE_TXD; + + /* Tx timing init */ + configs->duty_cycle = 0; + configs->tx_time_param.pkt_tx_time_en = FALSE; + configs->tx_time_param.pkt_tx_time = 0; + configs->ipg_param.ipg = 0; + configs->ipg_param.sig_ext = TEST_SIG_EXTENSION; + configs->ipg_param.slot_time = TEST_DEFAULT_SLOT_TIME; + configs->ipg_param.sifs_time = TEST_DEFAULT_SIFS_TIME; + configs->ipg_param.ac_num = SERV_QID_AC_BE; + configs->ipg_param.aifsn = TEST_MIN_AIFSN; + configs->ipg_param.cw = TEST_MIN_CW; + configs->ipg_param.txop = 0; + + /* Rx init */ + sys_ad_zero_mem(&configs->own_mac, SERV_MAC_ADDR_LEN); + + /* Test tx statistic and txs init */ + configs->txs_enable = FALSE; + sys_ad_zero_mem(&configs->tx_stat, + sizeof(struct test_tx_statistic)); + + /* Phy */ + configs->tx_ant = 1; + configs->rx_ant = 1; + + /* TODO: factor out here for phy */ + configs->channel = 36; + configs->ch_band = 1; + configs->ctrl_ch = 36; +#if 0 + if (pAd->CommonCfg.eDBDC_mode == ENUM_DBDC_5G5G) { + configs->channel = 100; + configs->ctrl_ch = 100; + } else { + configs->channel = 36; + configs->ctrl_ch = 36; + } +#endif + configs->tx_mode = TEST_MODE_OFDM; + configs->bw = TEST_BW_20; + configs->mcs = 7; + configs->sgi = 0; + + /* TODO: factor out here for Tx power */ + } +#endif /* DBDC_MODE */ + else + return SERV_STATUS_SERV_TEST_INVALID_BANDIDX; + + return ret; +} + +static s_int32 mt_serv_release_config( + struct test_configuration *configs, u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + if (band_idx == TEST_DBDC_BAND0) { + if (configs->test_pkt) { + sys_ad_free_mem(configs->test_pkt); + configs->test_pkt = NULL; + } + } +/* #ifdef DBDC_MODE */ +#if 1 + else if (band_idx == TEST_DBDC_BAND1) { + if (configs->test_pkt) { + sys_ad_free_mem(configs->test_pkt); + configs->test_pkt = NULL; + } + } +#endif /* DBDC_MODE */ + else + return SERV_STATUS_SERV_TEST_INVALID_BANDIDX; + + return ret; +} + +/***************************************************************************** + * Extern functions + *****************************************************************************/ +/* For test mode init of service.git */ +s_int32 mt_serv_init_test(struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char band_idx; + + if (!serv_test->engine_offload) { + for (band_idx = TEST_DBDC_BAND0; + band_idx < TEST_DBDC_BAND_NUM; band_idx++) { + ret = mt_serv_init_config( + &serv_test->test_config[band_idx], band_idx); + if (ret != SERV_STATUS_SUCCESS) + return SERV_STATUS_SERV_TEST_FAIL; + } + + /* Control band0 as default setting */ + serv_test->ctrl_band_idx = TEST_DBDC_BAND0; + + /* Init test mode backup CR data struct */ + sys_ad_zero_mem(serv_test->test_bkcr, + sizeof(struct test_bk_cr) * TEST_MAX_BKCR_NUM); + + /* Init test mode rx statistic data struct */ + sys_ad_zero_mem(serv_test->test_rx_statistic, + sizeof(struct test_rx_stat) * TEST_DBDC_BAND_NUM); + + /* Init test mode rx statistic data struct */ + sys_ad_zero_mem(&serv_test->test_bstat, + sizeof(struct test_band_state)); + } else { + serv_test->test_winfo->dbdc_mode = TEST_DBDC_DISABLE; + serv_test->test_winfo->hw_tx_enable = TEST_HWTX_DISABLE; + } + ret = mt_serv_init_op(serv_test->test_op); + + /* Init test mode control register data struct */ + sys_ad_zero_mem(&serv_test->test_reg, + sizeof(struct test_register)); + + /* Init test mode eeprom data struct */ + sys_ad_zero_mem(&serv_test->test_eprm, + sizeof(struct test_eeprom)); + + /* Init test mode eeprom data struct */ + serv_test->ctrl_band_idx = 0; + + /* TODO: factor out here */ + /* Common Part */ + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +/* For test mode exit of service.git */ +s_int32 mt_serv_exit_test(struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char band_idx; + + if (!serv_test->engine_offload) { + for (band_idx = TEST_DBDC_BAND0; + band_idx < TEST_DBDC_BAND_NUM; band_idx++) { + ret = mt_serv_release_config( + &serv_test->test_config[band_idx], band_idx); + if (ret != SERV_STATUS_SUCCESS) + return SERV_STATUS_SERV_TEST_FAIL; + } + } + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_start(struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + if (!serv_test->engine_offload) { + ret = mt_engine_start(serv_test->test_winfo, + &serv_test->test_backup, + serv_test->test_config, + serv_test->test_op, + serv_test->test_bkcr, + &serv_test->test_rx_statistic[0], + serv_test->en_log); + } else { + ret = serv_test->test_op->op_set_test_mode_start( + serv_test->test_winfo); + } + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_stop(struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + if (!serv_test->engine_offload) { + ret = mt_engine_stop(serv_test->test_winfo, + &serv_test->test_backup, + serv_test->test_config, + serv_test->test_op, + serv_test->test_bkcr); + } else { + ret = serv_test->test_op->op_set_test_mode_abort( + serv_test->test_winfo); + } + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_set_channel(struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_configuration *configs; + struct test_wlan_info *winfos = serv_test->test_winfo; + struct test_operation *ops = serv_test->test_op; + struct serv_chip_cap *cap = &winfos->chip_cap; + s_int32 ant_loop; + u_char ant_mask = 0; + u_int32 tx_stream_num = 0, max_stream_num = 0; + s_int8 ch_offset = 0; +#if 0 + u_char tmp = 0; +#endif + u_char pri_sel = 0, channel = 0, channel_2nd = 0; + const s_int8 bw40_sel[] = { -2, 2}; + const s_int8 bw80_sel[] = { -6, -2, 2, 6}; + const s_int8 bw160_sel[] = { -14, -10, -6, -2, 2, 6, 10, 14}; + + configs = &serv_test->test_config[ctrl_band_idx]; + + /* update max stream num cap */ + max_stream_num = cap->mcs_nss.max_nss; + if (IS_TEST_DBDC(winfos)) + max_stream_num /= 2; + + for (ant_loop = 0; ant_loop < max_stream_num; ant_loop++) { + if (configs->tx_ant & (0x1 << ant_loop)) + ant_mask |= (0x1 << ant_loop); + } + + /* update tx anteena config */ + configs->tx_ant = ant_mask; + + /* + * To get TX max stream number from TX antenna bit mask + * tx_sel=2 -> tx_stream_num=2 + * tx_sel=4 -> tx_stream_num=3 + * tx_sel=8 -> tx_stream_num=4 + */ + + /* + * tx stream for arbitrary tx ant bitmap + * (ex: tx_sel=5 -> tx_stream_num=3, not 2) + */ + for (ant_loop = max_stream_num; ant_loop > 0; ant_loop--) { + if (ant_mask & BIT(ant_loop - 1)) { + tx_stream_num = ant_loop; + break; + } + } + + /* tx stream parameter sanity protection */ + tx_stream_num = tx_stream_num ? tx_stream_num : 1; + tx_stream_num = (tx_stream_num <= max_stream_num) + ? tx_stream_num : max_stream_num; + + /* update tx stream num config */ + configs->tx_strm_num = tx_stream_num; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: tx_ant:0x%x, tx stream:%u\n", + __func__, configs->tx_ant, configs->tx_strm_num)); + + for (ant_loop = 0; ant_loop < max_stream_num; ant_loop++) { + if (configs->rx_ant & (0x1 << ant_loop)) + ant_mask |= (0x1 << ant_loop); + } + + /* fw need parameter rx stream path */ + configs->rx_ant = ant_mask; + configs->rx_strm_pth = ant_mask; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: rx_ant:0x%x, rx path:0x%x\n", __func__, + configs->rx_ant, configs->rx_strm_pth)); + + /* read test config info */ + pri_sel = configs->pri_sel; + channel = configs->channel; + channel_2nd = configs->channel_2nd; + + switch (configs->bw) { + case TEST_BW_20: + configs->ctrl_ch = channel; + if (configs->per_pkt_bw > configs->bw) { + switch (configs->per_pkt_bw) { + case TEST_BW_80: + if (pri_sel >= 4) + goto error; + + ch_offset = bw80_sel[pri_sel]; + break; + case TEST_BW_160C: + case TEST_BW_160NC: + if (pri_sel >= 8) + goto error; + + ch_offset = bw160_sel[pri_sel]; + break; + default: /* BW_40 */ + if (pri_sel > 1) + goto error; + + ch_offset = bw40_sel[pri_sel]; + } + } + + break; + case TEST_BW_40: + if (pri_sel >= 2) + goto error; + + configs->ctrl_ch = channel + bw40_sel[pri_sel]; + ch_offset = bw40_sel[pri_sel]; + + break; + + case TEST_BW_160NC: + if (pri_sel >= 8) + goto error; + + if (!channel_2nd) + goto error2; + +#if 0 + /* swap control channel to be in order */ + if (channel_2nd < channel) { + tmp = channel; + channel = channel_2nd; + channel_2nd = tmp; + } +#endif + /* TODO: bw80+80 primary select definition */ + if (pri_sel < 4) { + configs->ctrl_ch = channel + bw80_sel[pri_sel]; + ch_offset = bw80_sel[pri_sel]; + } else { + configs->ctrl_ch = channel + bw80_sel[pri_sel - 4]; + ch_offset = bw80_sel[pri_sel - 4]; + } + + break; + + case TEST_BW_80: + if (pri_sel >= 4) + goto error; + + configs->ctrl_ch = channel + bw80_sel[pri_sel]; + ch_offset = bw80_sel[pri_sel]; + + break; + + case TEST_BW_160C: + if (pri_sel >= 8) + goto error; + + configs->ctrl_ch = channel + bw160_sel[pri_sel]; + ch_offset = bw160_sel[pri_sel]; + + break; + + default: + goto error3; + } + + /* sanity check for channel parameter */ + if (((channel + ch_offset) <= 0) || + ((channel - ch_offset) <= 0)) + goto error; + + /* update test config info */ + configs->pri_sel = pri_sel; + configs->ch_offset = ch_offset; + configs->channel = channel; + configs->channel_2nd = channel_2nd; + + /* set channel */ + ret = ops->op_set_channel(winfos, ctrl_band_idx, configs); + if (ret) + goto error; + + return ret; + +error: + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: set channel fail, ", __func__)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("control channel: %d|%d\n", configs->ctrl_ch, + channel - ch_offset)); + return SERV_STATUS_OSAL_NET_FAIL_SET_CHANNEL; + +error2: + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: set channel fail, ", __func__)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("second control channel is 0 for bw 80+80\n")); + return SERV_STATUS_OSAL_NET_FAIL_SET_CHANNEL; + +error3: + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: set channel fail, ", __func__)); + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("bw=%d is invalid\n", configs->bw)); + return SERV_STATUS_OSAL_NET_FAIL_SET_CHANNEL; +} + +s_int32 mt_serv_set_tx_content(struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_configuration *configs; + + configs = &serv_test->test_config[ctrl_band_idx]; + + ret = serv_test->test_op->op_set_tx_content( + serv_test->test_winfo, + ctrl_band_idx, + configs); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_set_tx_path(struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_configuration *configs; + + configs = &serv_test->test_config[ctrl_band_idx]; + + ret = serv_test->test_op->op_set_tx_path( + serv_test->test_winfo, + ctrl_band_idx, + configs); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_set_rx_path(struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_configuration *configs; + + configs = &serv_test->test_config[ctrl_band_idx]; + + ret = serv_test->test_op->op_set_rx_path( + serv_test->test_winfo, + ctrl_band_idx, + configs); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_submit_tx(struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_configuration *configs; + struct test_operation *ops = serv_test->test_op; + struct test_wlan_info *winfos = serv_test->test_winfo; + + configs = &serv_test->test_config[ctrl_band_idx]; + + if (!serv_test->engine_offload) { + ret = mt_engine_subscribe_tx(ops, winfos, configs); + if (ret) + goto err_out; + } else { + /* TBD */ + } + +err_out: + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%04x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_revert_tx(struct service_test *serv_test) +{ + u_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_configuration *configs; + struct test_operation *ops = serv_test->test_op; + struct test_wlan_info *winfos = serv_test->test_winfo; + + configs = &serv_test->test_config[ctrl_band_idx]; + + if (!serv_test->engine_offload) { + ret = mt_engine_unsubscribe_tx(ops, winfos, configs); + if (ret) + goto err_out; + } else { + /* TBD */ + } + +err_out: + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_start_tx(struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_configuration *configs; + struct test_operation *ops = serv_test->test_op; + struct test_wlan_info *winfos = serv_test->test_winfo; + struct test_txpwr_param *pwr_param = NULL; + + configs = &serv_test->test_config[ctrl_band_idx]; + pwr_param = &configs->pwr_param; + + if (!pwr_param) { + ret = SERV_STATUS_SERV_TEST_INVALID_NULL_POINTER; + goto err_out; + } + + if (configs->tx_mode < TEST_MODE_HE_SU) { + if (configs->mcs == 32 + && configs->per_pkt_bw != TEST_BW_40 + && configs->bw != TEST_BW_40) { + ret = SERV_STATUS_SERV_TEST_INVALID_PARAM; + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: bandwidth must to be 40 at MCS 32\n", __func__)); + goto err_out; + } + } + + if (!serv_test->engine_offload) { + ret = ops->op_set_tx_pwr( + winfos, configs, ctrl_band_idx, pwr_param); + if (ret) + return ret; + + ret = mt_engine_calc_ipg_param_by_ipg( + &serv_test->test_config[ctrl_band_idx]); + if (ret) + goto err_out; + + ret = mt_engine_start_tx(serv_test->test_winfo, + &serv_test->test_config[ctrl_band_idx], + serv_test->test_op, ctrl_band_idx); + } else { + ret = serv_test->test_op->op_start_tx( + serv_test->test_winfo, + ctrl_band_idx, + &serv_test->test_config[ctrl_band_idx]); + } + +err_out: + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_stop_tx(struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + + if (!serv_test->engine_offload) { + ret = mt_engine_stop_tx(serv_test->test_winfo, + &serv_test->test_config[ctrl_band_idx], + serv_test->test_op, ctrl_band_idx); + } else { + ret = serv_test->test_op->op_stop_tx( + serv_test->test_winfo, + ctrl_band_idx); + } + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_start_rx(struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_wlan_info *winfos = serv_test->test_winfo; + struct serv_chip_cap *cap = &winfos->chip_cap; + struct test_configuration *configs; + s_int32 ant_loop; + u_char ant_mask = 0; + u_int32 max_stream_num = 0; + + configs = &serv_test->test_config[ctrl_band_idx]; + + if (!serv_test->engine_offload) { + ret = mt_engine_set_auto_resp(serv_test->test_winfo, + &serv_test->test_config[ctrl_band_idx], + ctrl_band_idx, 1); + if (ret) + return ret; + + /* update max stream num cap */ + max_stream_num = cap->mcs_nss.max_nss; + + for (ant_loop = 0; ant_loop < max_stream_num; ant_loop++) { + if (configs->rx_ant & (0x1 << ant_loop)) + ant_mask |= (0x1 << ant_loop); + } + + /* fw need parameter rx stream path */ + configs->rx_ant = ant_mask; + configs->rx_strm_pth = ant_mask; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: rx_ant:0x%x, rx path:0x%x\n", __func__, + configs->rx_ant, configs->rx_strm_pth)); + + ret = mt_engine_start_rx(serv_test->test_winfo, + &serv_test->test_config[ctrl_band_idx], + serv_test->test_op, ctrl_band_idx); + } else { + ret = serv_test->test_op->op_start_rx( + serv_test->test_winfo, + ctrl_band_idx, + configs); + } + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_stop_rx(struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + + if (!serv_test->engine_offload) { + ret = mt_engine_stop_rx(serv_test->test_winfo, + &serv_test->test_config[ctrl_band_idx], + serv_test->test_op, ctrl_band_idx); + } else { + ret = serv_test->test_op->op_stop_rx( + serv_test->test_winfo, + ctrl_band_idx); + } + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_set_freq_offset(struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_configuration *configs; + struct test_operation *ops = serv_test->test_op; + u_int32 rf_freq_offset; + + configs = &serv_test->test_config[ctrl_band_idx]; + + rf_freq_offset = configs->rf_freq_offset; + + ret = ops->op_set_freq_offset( + serv_test->test_winfo, + rf_freq_offset, + ctrl_band_idx); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_tx_power_operation( + struct service_test *serv_test, u_int32 item) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_configuration *configs; + struct test_wlan_info *winfos = serv_test->test_winfo; + struct test_operation *ops = serv_test->test_op; + struct test_txpwr_param *pwr_param = NULL; + + configs = &serv_test->test_config[ctrl_band_idx]; + if (!configs) + return SERV_STATUS_SERV_TEST_INVALID_NULL_POINTER; + + pwr_param = &configs->pwr_param; + if (!pwr_param) + return SERV_STATUS_SERV_TEST_INVALID_NULL_POINTER; + + if (pwr_param->ant_idx >= TEST_ANT_NUM) + goto error; + + switch (item) { + case SERV_TEST_TXPWR_SET_PWR: + configs->tx_pwr[pwr_param->ant_idx] = pwr_param->power; + ret = ops->op_set_tx_pwr( + winfos, configs, ctrl_band_idx, pwr_param); + break; + + case SERV_TEST_TXPWR_GET_PWR: + ret = ops->op_get_tx_pwr( + winfos, configs, ctrl_band_idx, + configs->channel, (u_char)pwr_param->ant_idx, + &(pwr_param->power)); + break; + + case SERV_TEST_TXPWR_SET_PWR_INIT: + /* TODO: */ + break; + + case SERV_TEST_TXPWR_SET_PWR_MAN: + /* TODO: */ + break; + + default: + return SERV_STATUS_SERV_TEST_INVALID_PARAM; + } + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; + +error: + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_TRACE, + ("%s: invalid parameter for ant_idx(0x%x).\n", + __func__, pwr_param->ant_idx)); + return SERV_STATUS_SERV_TEST_INVALID_PARAM; +} + +s_int32 mt_serv_get_freq_offset( + struct service_test *serv_test, u_int32 *freq_offset) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_operation *ops; + + ops = serv_test->test_op; + ret = ops->op_get_freq_offset( + serv_test->test_winfo, + ctrl_band_idx, + freq_offset); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_get_cfg_on_off( + struct service_test *serv_test, + u_int32 type, + u_int32 *result) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_operation *ops; + + ops = serv_test->test_op; + ret = ops->op_get_cfg_on_off( + serv_test->test_winfo, + ctrl_band_idx, + type, + result); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_get_tx_tone_pwr( + struct service_test *serv_test, + u_int32 ant_idx, + u_int32 *power) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_operation *ops; + + ops = serv_test->test_op; + ret = ops->op_get_tx_tone_pwr( + serv_test->test_winfo, + ctrl_band_idx, + ant_idx, + power); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_get_thermal_val( + struct service_test *serv_test, + u_char band_idx, + u_int32 *value) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_configuration *configs; + struct test_operation *ops; + + configs = &serv_test->test_config[ctrl_band_idx]; + + ops = serv_test->test_op; + ret = ops->op_get_thermal_val( + serv_test->test_winfo, + configs, + ctrl_band_idx, + value); + + /* update config */ + configs->thermal_val = *value; + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_set_cal_bypass( + struct service_test *serv_test, + u_int32 cal_item) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_operation *ops; + + ops = serv_test->test_op; + ret = ops->op_set_cal_bypass( + serv_test->test_winfo, + ctrl_band_idx, + cal_item); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_set_dpd( + struct service_test *serv_test, + u_int32 on_off, + u_int32 wf_sel) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_operation *ops; + + ops = serv_test->test_op; + ret = ops->op_set_dpd( + serv_test->test_winfo, + on_off, + wf_sel); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_set_tssi( + struct service_test *serv_test, + u_int32 on_off, + u_int32 wf_sel) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_operation *ops; + + ops = serv_test->test_op; + ret = ops->op_set_tssi( + serv_test->test_winfo, + on_off, + wf_sel); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_set_rdd_on_off( + struct service_test *serv_test, + u_int32 rdd_num, + u_int32 rdd_sel, + u_int32 enable) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_operation *ops; + struct test_wlan_info *winfos; + + ops = serv_test->test_op; + winfos = serv_test->test_winfo; + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_OFF, + ("%s(): ctrl_band_idx %d, enable %d\n", + __func__, ctrl_band_idx, enable)); + + if (ops->op_set_tr_mac) + ret = ops->op_set_tr_mac(winfos, SERV_TEST_MAC_RX, + enable, ctrl_band_idx); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: op_set_tr_mac, err=0x%08x\n", __func__, ret)); + + if (ops->op_set_rdd_test) + ops->op_set_rdd_test(winfos, rdd_num, rdd_sel, enable); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: op_set_rdd_test, err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_set_off_ch_scan( + struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_configuration *configs; + struct test_wlan_info *winfos = serv_test->test_winfo; + struct test_operation *ops = serv_test->test_op; + struct test_off_ch_param *param = NULL; + + configs = &serv_test->test_config[ctrl_band_idx]; + if (!configs) + return SERV_STATUS_SERV_TEST_INVALID_NULL_POINTER; + + param = &configs->off_ch_param; + if (!param) + return SERV_STATUS_SERV_TEST_INVALID_NULL_POINTER; + + ret = ops->op_set_off_ch_scan( + winfos, configs, ctrl_band_idx, param); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + + +s_int32 mt_serv_set_icap_start( + struct service_test *serv_test, + struct hqa_rbist_cap_start *icap_info) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_operation *op = serv_test->test_op; + struct test_wlan_info *winfos = serv_test->test_winfo; + + if (op->op_set_icap_start) + ret = op->op_set_icap_start(winfos, (u_int8 *)icap_info); + else + ret = SERV_STATUS_SERV_TEST_NOT_SUPPORTED; + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err = 0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_get_icap_status( + struct service_test *serv_test, + s_int32 *icap_stat) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_operation *op = serv_test->test_op; + struct test_wlan_info *winfos = serv_test->test_winfo; + + if (op->op_get_icap_status) + ret = op->op_get_icap_status(winfos, icap_stat); + else + ret = SERV_STATUS_SERV_TEST_NOT_SUPPORTED; + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err = 0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_get_icap_max_data_len( + struct service_test *serv_test, + u_long *max_data_len) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_operation *op = serv_test->test_op; + struct test_wlan_info *winfos = serv_test->test_winfo; + + if (op->op_get_icap_max_data_len) + ret = op->op_get_icap_max_data_len(winfos, max_data_len); + else + ret = SERV_STATUS_SERV_TEST_NOT_SUPPORTED; + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err = 0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_get_icap_data( + struct service_test *serv_test, + s_int32 *icap_cnt, + s_int32 *icap_data, + u_int32 wf_num, + u_int32 iq_type) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_operation *op = serv_test->test_op; + struct test_wlan_info *winfos = serv_test->test_winfo; + + if (op->op_get_icap_data) + ret = op->op_get_icap_data(winfos, icap_cnt + , icap_data, wf_num, iq_type); + else + ret = SERV_STATUS_SERV_TEST_NOT_SUPPORTED; + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err = 0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_get_recal_cnt( + struct service_test *serv_test, + u_int32 *recal_cnt, + u_int32 *recal_dw_num) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_operation *ops; + + ops = serv_test->test_op; + + ret = ops->op_get_recal_cnt( + serv_test->test_winfo, + recal_cnt, + recal_dw_num); + + return ret; +} + +s_int32 mt_serv_get_recal_content( + struct service_test *serv_test, + u_int32 *content) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_operation *ops; + + ops = serv_test->test_op; + + ret = ops->op_get_recal_content( + serv_test->test_winfo, + content); + + return ret; +} + +s_int32 mt_serv_get_rxv_cnt( + struct service_test *serv_test, + u_int32 *rxv_cnt, + u_int32 *rxv_dw_num) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_wlan_info *winfos; + struct test_operation *ops; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + + u_int32 byte_cnt = 0; + + if (!serv_test->engine_offload) { + winfos = serv_test->test_winfo; + + /* Note: only support single rxv count report */ + *rxv_cnt = 1; + + /* query rxv byte count */ + ret = net_ad_get_rxv_cnt(winfos, ctrl_band_idx, &byte_cnt); + } else { + ops = serv_test->test_op; + ret = ops->op_get_rxv_cnt( + serv_test->test_winfo, + rxv_cnt, + rxv_dw_num); + } + + return ret; +} + +s_int32 mt_serv_get_rxv_content( + struct service_test *serv_test, + u_int32 dw_cnt, + u_int32 *content) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_wlan_info *winfos; + struct test_operation *ops; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + + if (!serv_test->engine_offload) { + /* query rxv content */ + winfos = serv_test->test_winfo; + ret = net_ad_get_rxv_content(winfos, ctrl_band_idx, content); + } else { + ops = serv_test->test_op; + ret = ops->op_get_rxv_content( + serv_test->test_winfo, + dw_cnt, + content); + } + + return ret; +} + +s_int32 mt_serv_get_rdd_cnt( + struct service_test *serv_test, + u_int32 *rdd_cnt, + u_int32 *rdd_dw_num) +{ + struct test_operation *ops; + s_int32 ret = SERV_STATUS_SUCCESS; + + ops = serv_test->test_op; + ret = ops->op_get_rdd_cnt( + serv_test->test_winfo, + rdd_cnt, + rdd_dw_num); + + return ret; +} + +s_int32 mt_serv_get_rdd_content( + struct service_test *serv_test, + u_int32 *content, + u_int32 *total_cnt) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_operation *ops; + + ops = serv_test->test_op; + ret = ops->op_get_rdd_content( + serv_test->test_winfo, + content, total_cnt); + + return ret; +} + +s_int32 mt_serv_reset_txrx_counter( + struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_wlan_info *winfos; + struct test_configuration *config_band0; + struct test_configuration *config_band1; + struct test_rx_stat *test_rx_st; + u_int8 ant_idx = 0, band_idx = 0; + + winfos = serv_test->test_winfo; + config_band0 = &serv_test->test_config[TEST_DBDC_BAND0]; + config_band1 = &serv_test->test_config[TEST_DBDC_BAND1]; + + for (band_idx = TEST_DBDC_BAND0; + band_idx < TEST_DBDC_BAND_NUM; band_idx++) { + test_rx_st = serv_test->test_rx_statistic + band_idx; + sys_ad_zero_mem(test_rx_st, + sizeof(struct test_rx_stat)); + + for (ant_idx = 0; ant_idx < TEST_ANT_NUM; ant_idx++) { + test_rx_st->rx_st_path[ant_idx].rssi = 0xFF; + test_rx_st->rx_st_path[ant_idx].rcpi = 0xFF; + test_rx_st->rx_st_path[ant_idx].fagc_ib_rssi = 0xFF; + test_rx_st->rx_st_path[ant_idx].fagc_wb_rssi = 0xFF; + } + } + + config_band0->tx_stat.tx_done_cnt = 0; + if (IS_TEST_DBDC(winfos)) + config_band1->tx_stat.tx_done_cnt = 0; + + ret = serv_test->test_op->op_reset_txrx_counter( + serv_test->test_winfo); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_set_rx_vector_idx( + struct service_test *serv_test, u_int32 group1, u_int32 group2) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_operation *ops; + + ops = serv_test->test_op; + ret = ops->op_set_rx_vector_idx( + serv_test->test_winfo, + serv_test->ctrl_band_idx, + group1, + group2); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_set_fagc_rssi_path( + struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_operation *ops; + + ops = serv_test->test_op; + ret = ops->op_set_fagc_rssi_path( + serv_test->test_winfo, + serv_test->ctrl_band_idx, + serv_test->test_config[TEST_DBDC_BAND0].fagc_path); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_get_rx_stat_leg( + struct service_test *serv_test, + struct test_rx_stat_leg *rx_stat) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_operation *ops; + + ops = serv_test->test_op; + ret = ops->op_get_rx_stat_leg( + serv_test->test_winfo, rx_stat); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_get_rx_stat( + struct service_test *serv_test, + u_int8 band_idx, + u_int8 blk_idx, + u_int8 test_rx_stat_cat, + struct test_rx_stat_u *st) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_operation *ops; + struct test_wlan_info *winfos; + struct test_rx_stat *stat; + boolean dbdc_mode = FALSE; + + ops = serv_test->test_op; + winfos = serv_test->test_winfo; + stat = &serv_test->test_rx_statistic[band_idx]; + + /* check dbdc mode condition */ + dbdc_mode = IS_TEST_DBDC(serv_test->test_winfo); + + /* sanity check for band index param */ + if ((!dbdc_mode) && (band_idx != TEST_DBDC_BAND0)) + goto error1; + + switch (test_rx_stat_cat) { + case TEST_RX_STAT_BAND: + ret = ops->op_get_rx_stat_band( + serv_test->test_winfo, + band_idx, + blk_idx, + stat->rx_st_band + blk_idx); + + sys_ad_move_mem(st, stat->rx_st_band + blk_idx, + sizeof(struct test_rx_stat_band_info)); + break; + case TEST_RX_STAT_PATH: + ret = ops->op_get_rx_stat_path( + serv_test->test_winfo, + band_idx, + blk_idx, + stat->rx_st_path + blk_idx); + + sys_ad_move_mem(st, stat->rx_st_path + blk_idx, + sizeof(struct test_rx_stat_path_info)); + break; + case TEST_RX_STAT_USER: + ret = ops->op_get_rx_stat_user( + serv_test->test_winfo, + band_idx, + blk_idx, + stat->rx_st_user + blk_idx); + + sys_ad_move_mem(st, stat->rx_st_user + blk_idx, + sizeof(struct test_rx_stat_user_info)); + break; + case TEST_RX_STAT_COMM: + ret = ops->op_get_rx_stat_comm( + serv_test->test_winfo, + band_idx, + blk_idx, + &stat->rx_st_comm); + + sys_ad_move_mem(st, &stat->rx_st_comm, + sizeof(struct test_rx_stat_comm_info)); + break; + default: + break; + } + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; + +error1: + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: invalid band index for non-dbdc mode.\n", + __func__)); + return ret; +} + +s_int32 mt_serv_get_capability( + struct service_test *serv_test, + struct test_capability *capability) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_operation *op = serv_test->test_op; + struct test_wlan_info *winfo = serv_test->test_winfo; + + ret = op->op_get_capability(winfo, capability); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_calibration_test_mode( + struct service_test *serv_test, u_char mode) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_operation *op = serv_test->test_op; + struct test_wlan_info *winfo = serv_test->test_winfo; + + ret = op->op_calibration_test_mode(winfo, mode); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_do_cal_item( + struct service_test *serv_test, u_int32 item) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + + ret = serv_test->test_op->op_do_cal_item( + serv_test->test_winfo, + item, ctrl_band_idx); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_set_band_mode( + struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_operation *ops; + + ops = serv_test->test_op; + + if (!serv_test->engine_offload) { + ret = net_ad_set_band_mode( + serv_test->test_winfo, + &serv_test->test_bstat); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + } else { + ret = ops->op_set_band_mode( + serv_test->test_winfo, + &serv_test->test_bstat); + } + + return ret; +} + +s_int32 mt_serv_get_band_mode( + struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + u_int32 band_type; + struct test_operation *ops; + + ops = serv_test->test_op; + + if (!serv_test->engine_offload) { + /* + * DLL will query two times per band0/band1 if DBDC chip set. + * 0: no this band + * 1: 2.4G + * 2: 5G + * 3. 2.4G+5G + */ + if (IS_TEST_DBDC(serv_test->test_winfo)) + band_type = (ctrl_band_idx == TEST_DBDC_BAND0) + ? TEST_BAND_TYPE_G : TEST_BAND_TYPE_A; + else { + /* Always report 2.4+5G*/ + band_type = TEST_BAND_TYPE_ALL; + + /* + * If IS_TEST_DBDC=0, + * band_idx should not be 1 so return band_mode=0 + */ + if (ctrl_band_idx == TEST_DBDC_BAND1) + band_type = TEST_BAND_TYPE_UNUSE; + } + + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: band_type=%u\n", __func__, band_type)); + } else { + ret = ops->op_set_band_mode( + serv_test->test_winfo, + &serv_test->test_bstat); + + if (ctrl_band_idx == TEST_DBDC_BAND0) + band_type = TEST_BAND_TYPE_ALL; + else { + if (serv_test->test_bstat.band_mode == + TEST_BAND_MODE_DUAL) + band_type = TEST_BAND_TYPE_ALL; + else + band_type = TEST_BAND_TYPE_UNUSE; + } + } + + BSTATE_SET_PARAM(serv_test, band_type, band_type); + + return ret; +} + +s_int32 mt_serv_log_on_off( + struct service_test *serv_test, u_int32 log_type, + u_int32 log_ctrl, u_int32 log_size) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_operation *ops; + + ops = serv_test->test_op; + ret = ops->op_log_on_off( + serv_test->test_winfo, + serv_test->ctrl_band_idx, + log_type, + log_ctrl, + log_size); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + + +s_int32 mt_serv_set_cfg_on_off( + struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_configuration *configs; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_operation *ops; + + configs = &serv_test->test_config[ctrl_band_idx]; + + ops = serv_test->test_op; + ret = ops->op_set_cfg_on_off( + serv_test->test_winfo, + (u_int8)configs->log_type, + (u_int8)configs->log_enable, + ctrl_band_idx); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_set_rx_filter_pkt_len(struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_configuration *configs; + struct test_operation *ops; + + configs = &serv_test->test_config[serv_test->ctrl_band_idx]; + ops = serv_test->test_op; + ret = ops->op_set_rx_filter_pkt_len( + serv_test->test_winfo, + configs->rx_filter_en, + serv_test->ctrl_band_idx, + configs->rx_filter_pkt_len); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_set_low_power( + struct service_test *serv_test, u_int32 control) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + ret = net_ad_set_low_power(serv_test->test_winfo, control); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_get_antswap_capability( + struct service_test *serv_test, u_int32 *antswap_support) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + struct test_operation *ops; + + ops = serv_test->test_op; + + ret = ops->op_get_antswap_capability( + serv_test->test_winfo, + antswap_support); + + return ret; +} + +s_int32 mt_serv_set_antswap( + struct service_test *serv_test, u_int32 ant) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + struct test_operation *ops; + + ops = serv_test->test_op; + + ret = ops->op_set_antswap( + serv_test->test_winfo, + ant); + + return ret; +} + +s_int32 mt_serv_reg_eprm_operation( + struct service_test *serv_test, u_int32 item) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_operation *ops; + + ops = serv_test->test_op; + + switch (item) { + case SERV_TEST_REG_MAC_READ: + if (!serv_test->engine_offload) { + ret = net_ad_read_mac_bbp_reg(serv_test->test_winfo, + &serv_test->test_reg); + } else { + ops = serv_test->test_op; + ret = ops->op_read_bulk_mac_bbp_reg( + serv_test->test_winfo, + &serv_test->test_reg); + } + break; + + case SERV_TEST_REG_MAC_WRITE: + if (!serv_test->engine_offload) { + + ret = net_ad_write_mac_bbp_reg(serv_test->test_winfo, + &serv_test->test_reg); + } else { + ops = serv_test->test_op; + ret = ops->op_write_mac_bbp_reg(serv_test->test_winfo, + &serv_test->test_reg); + } + break; + + case SERV_TEST_REG_MAC_READ_BULK: + if (!serv_test->engine_offload) { + ret = net_ad_read_bulk_mac_bbp_reg( + serv_test->test_winfo, + &serv_test->test_config[TEST_DBDC_BAND0], + &serv_test->test_reg); + } else { + ops = serv_test->test_op; + ret = ops->op_read_bulk_mac_bbp_reg( + serv_test->test_winfo, + &serv_test->test_reg); + } + break; + + case SERV_TEST_REG_RF_READ_BULK: + if (!serv_test->engine_offload) { + ret = net_ad_read_bulk_rf_reg(serv_test->test_winfo, + &serv_test->test_reg); + } else { + ops = serv_test->test_op; + ret = ops->op_read_bulk_rf_reg(serv_test->test_winfo, + &serv_test->test_reg); + } + break; + + case SERV_TEST_REG_RF_WRITE_BULK: + if (!serv_test->engine_offload) { + ret = net_ad_write_bulk_rf_reg(serv_test->test_winfo, + &serv_test->test_reg); + } else { + ops = serv_test->test_op; + ret = ops->op_write_bulk_rf_reg(serv_test->test_winfo, + &serv_test->test_reg); + } + break; + + case SERV_TEST_REG_CA53_READ: + net_ad_read_ca53_reg(&serv_test->test_reg); + break; + + case SERV_TEST_REG_CA53_WRITE: + net_ad_write_ca53_reg(&serv_test->test_reg); + break; + + case SERV_TEST_EEPROM_READ: + ret = net_ad_read_write_eeprom(serv_test->test_winfo, + &serv_test->test_eprm, + TRUE); + break; + + case SERV_TEST_EEPROM_WRITE: + ret = net_ad_read_write_eeprom(serv_test->test_winfo, + &serv_test->test_eprm, + FALSE); + break; + + case SERV_TEST_EEPROM_READ_BULK: + if (!serv_test->engine_offload) { + ret = net_ad_read_write_bulk_eeprom(serv_test->test_winfo, + &serv_test->test_eprm, + TRUE); + } else { + ops = serv_test->test_op; + ret = ops->op_read_bulk_eeprom(serv_test->test_winfo, + &serv_test->test_eprm); + } + break; + + case SERV_TEST_EEPROM_WRITE_BULK: + ret = net_ad_read_write_bulk_eeprom(serv_test->test_winfo, + &serv_test->test_eprm, + FALSE); + break; + + case SERV_TEST_EEPROM_GET_FREE_EFUSE_BLOCK: + ret = net_ad_get_free_efuse_block(serv_test->test_winfo, + &serv_test->test_eprm); + break; + + default: + return SERV_STATUS_SERV_TEST_INVALID_PARAM; + } + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_mps_operation( + struct service_test *serv_test, u_int32 item) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + + if (!serv_test->engine_offload) { + switch (item) { + case SERV_TEST_MPS_START_TX: + ret = net_ad_mps_tx_operation(serv_test->test_winfo, + &serv_test->test_config[ctrl_band_idx], + TRUE); + + if (ret) + return ret; + + ret = mt_engine_start_tx(serv_test->test_winfo, + &serv_test->test_config[ctrl_band_idx], + serv_test->test_op, ctrl_band_idx); + break; + + case SERV_TEST_MPS_STOP_TX: + ret = net_ad_mps_tx_operation(serv_test->test_winfo, + &serv_test->test_config[ctrl_band_idx], + FALSE); + break; + + default: + return SERV_STATUS_SERV_TEST_INVALID_PARAM; + } + } else { + switch (item) { + case SERV_TEST_MPS_START_TX: + ret = serv_test->test_op->op_mps_start( + serv_test->test_winfo, + ctrl_band_idx); + break; + + case SERV_TEST_MPS_STOP_TX: + ret = serv_test->test_op->op_stop_tx( + serv_test->test_winfo, + ctrl_band_idx); + break; + + default: + return SERV_STATUS_SERV_TEST_INVALID_PARAM; + } + + } + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_get_chipid( + struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + ret = serv_test->test_op->op_get_chipid( + serv_test->test_winfo); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_mps_set_nss( + struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_configuration *test_config; + struct test_mps_cb *mps_cb; + u_int32 len; + + test_config = &serv_test->test_config[ctrl_band_idx]; + mps_cb = &test_config->mps_cb; + len = mps_cb->mps_cnt; + + ret = serv_test->test_op->op_mps_set_nss( + serv_test->test_winfo, + mps_cb->mps_cnt, + mps_cb->mps_setting); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_mps_set_per_packet_bw( + struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_configuration *test_config; + struct test_mps_cb *mps_cb; + u_int32 len; + + test_config = &serv_test->test_config[ctrl_band_idx]; + mps_cb = &test_config->mps_cb; + len = mps_cb->mps_cnt; + + ret = serv_test->test_op->op_mps_set_per_packet_bw( + serv_test->test_winfo, + mps_cb->mps_cnt, + mps_cb->mps_setting); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_mps_set_packet_count( + struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_configuration *test_config; + struct test_mps_cb *mps_cb; + u_int32 len; + + test_config = &serv_test->test_config[ctrl_band_idx]; + mps_cb = &test_config->mps_cb; + len = mps_cb->mps_cnt; + + ret = serv_test->test_op->op_mps_set_packet_count( + serv_test->test_winfo, + mps_cb->mps_cnt, + mps_cb->mps_setting); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + + +s_int32 mt_serv_mps_set_payload_length( + struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_configuration *test_config; + struct test_mps_cb *mps_cb; + u_int32 len; + + test_config = &serv_test->test_config[ctrl_band_idx]; + mps_cb = &test_config->mps_cb; + len = mps_cb->mps_cnt; + + ret = serv_test->test_op->op_mps_set_payload_length( + serv_test->test_winfo, + mps_cb->mps_cnt, + mps_cb->mps_setting); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + + +s_int32 mt_serv_mps_set_power_gain( + struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_configuration *test_config; + struct test_mps_cb *mps_cb; + u_int32 len; + + test_config = &serv_test->test_config[ctrl_band_idx]; + mps_cb = &test_config->mps_cb; + len = mps_cb->mps_cnt; + + ret = serv_test->test_op->op_mps_set_power_gain( + serv_test->test_winfo, + mps_cb->mps_cnt, + mps_cb->mps_setting); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_mps_set_seq_data( + struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_configuration *test_config; + struct test_mps_cb *mps_cb; + u_int32 len; + + test_config = &serv_test->test_config[ctrl_band_idx]; + mps_cb = &test_config->mps_cb; + len = mps_cb->mps_cnt; + + if (!serv_test->engine_offload) { + + } else { + ret = serv_test->test_op->op_mps_set_seq_data( + serv_test->test_winfo, + mps_cb->mps_cnt, + mps_cb->mps_setting); + } + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_set_tmr(struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + ret = net_ad_set_tmr(serv_test->test_winfo, &serv_test->test_tmr); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_set_preamble(struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + u_char tx_mode = serv_test->test_config[ctrl_band_idx].tx_mode; + + if (!serv_test->engine_offload) { + + } else { + ret = serv_test->test_op->op_set_preamble( + serv_test->test_winfo, + tx_mode); + } + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_set_rate(struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + u_char mcs = serv_test->test_config[ctrl_band_idx].mcs; + + if (!serv_test->engine_offload) { + + } else { + ret = serv_test->test_op->op_set_rate( + serv_test->test_winfo, + mcs); + } + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_set_system_bw(struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + u_char sys_bw = serv_test->test_config[ctrl_band_idx].bw; + + if (!serv_test->engine_offload) { + + } else { + ret = serv_test->test_op->op_set_system_bw( + serv_test->test_winfo, + sys_bw); + } + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_set_per_pkt_bw(struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + u_char per_pkt_bw = serv_test->test_config[ctrl_band_idx].per_pkt_bw; + + if (!serv_test->engine_offload) { + + } else { + ret = serv_test->test_op->op_set_per_pkt_bw( + serv_test->test_winfo, + per_pkt_bw); + } + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_dbdc_tx_tone(struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_configuration *configs; + + configs = &serv_test->test_config[ctrl_band_idx]; + + ret = serv_test->test_op->op_dbdc_tx_tone( + serv_test->test_winfo, + ctrl_band_idx, + configs); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_dbdc_tx_tone_pwr(struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_configuration *configs; + + configs = &serv_test->test_config[ctrl_band_idx]; + + ret = serv_test->test_op->op_dbdc_tx_tone_pwr( + serv_test->test_winfo, + ctrl_band_idx, + configs); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_dbdc_continuous_tx(struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_char ctrl_band_idx = serv_test->ctrl_band_idx; + struct test_configuration *configs; + + configs = &serv_test->test_config[ctrl_band_idx]; + + ret = serv_test->test_op->op_dbdc_continuous_tx( + serv_test->test_winfo, + ctrl_band_idx, + configs); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_get_tx_info(struct service_test *serv_test) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_configuration *test_configs_band0; + struct test_configuration *test_configs_band1; + + test_configs_band0 = &serv_test->test_config[TEST_DBDC_BAND0]; + test_configs_band1 = &serv_test->test_config[TEST_DBDC_BAND1]; + + ret = serv_test->test_op->op_get_tx_info( + serv_test->test_winfo, + test_configs_band0, + test_configs_band1); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_get_wf_path_comb( + struct service_test *serv_test, + u_int8 band_idx, + boolean dbdc_mode_en, + u_int8 *path, + u_int8 *path_len +) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_configuration *test_configs; + + test_configs = &serv_test->test_config[TEST_DBDC_BAND0]; + + ret = serv_test->test_op->op_get_wf_path_comb( + serv_test->test_winfo, + band_idx, + dbdc_mode_en, + path, + path_len); + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_serv_main(struct service_test *serv_test, u_int32 test_item) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + + switch (test_item) { + case SERV_TEST_ITEM_INIT: + ret = mt_serv_init_test(serv_test); + break; + + case SERV_TEST_ITEM_EXIT: + ret = mt_serv_exit_test(serv_test); + break; + + case SERV_TEST_ITEM_START: + ret = mt_serv_start(serv_test); + break; + + case SERV_TEST_ITEM_STOP: + ret = mt_serv_stop(serv_test); + break; + + case SERV_TEST_ITEM_START_TX: + ret = mt_serv_start_tx(serv_test); + break; + + case SERV_TEST_ITEM_STOP_TX: + ret = mt_serv_stop_tx(serv_test); + break; + + case SERV_TEST_ITEM_START_RX: + ret = mt_serv_start_rx(serv_test); + break; + + case SERV_TEST_ITEM_STOP_RX: + ret = mt_serv_stop_rx(serv_test); + break; + + default: + return SERV_STATUS_SERV_TEST_NOT_SUPPORTED; + } + + if (ret) + SERV_LOG(SERV_DBG_CAT_TEST, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/service/test_engine.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/service/test_engine.c new file mode 100644 index 0000000000000..a661acf228f73 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/wlan_service/service/test_engine.c @@ -0,0 +1,2902 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +#include "test_engine.h" + +static u_int8 sigext_time_list[] = { + 0, /* CCK */ + 6, /* OFDM */ + 6, /* HTMIX */ + 6, /* HTGREENFIELD */ + 6, /* VHT */ +}; + +static u_int16 slot_time_list[] = { + 9, /* CCK */ + 9, /* OFDM */ + 9, /* HTMIX */ + 9, /* HTGREENFIELD */ + 9, /* VHT */ +}; + +struct test_data_rate_map cck_mode_map[] = { + {0, 1000}, + {1, 2000}, + {2, 5500}, + {3, 11000}, + {9, 2000}, + {10, 5500}, + {11, 11000}, +}; + +struct test_data_rate_map ofdm_mode_map[] = { + {0, 6000}, + {1, 9000}, + {2, 12000}, + {3, 18000}, + {4, 24000}, + {5, 36000}, + {6, 48500}, + {7, 54000}, +}; + +struct test_data_rate_map n_mode_map[] = { + {0, 6500}, + {1, 13000}, + {2, 19500}, + {3, 26000}, + {4, 39000}, + {5, 52000}, + {6, 58500}, + {7, 65000}, + {32, 6000}, /* MCS32 */ +}; + +struct test_data_rate_map ac_mode_map_bw20[] = { + {0, 65}, /* in unit of 100k */ + {1, 130}, + {2, 195}, + {3, 260}, + {4, 390}, + {5, 520}, + {6, 585}, + {7, 650}, + {8, 780}, +}; + +struct test_data_rate_map ac_mode_map_bw40[] = { + {0, 135}, /* in unit of 100k */ + {1, 270}, + {2, 405}, + {3, 540}, + {4, 810}, + {5, 1080}, + {6, 1215}, + {7, 1350}, + {8, 1620}, + {9, 1800}, +}; + +struct test_data_rate_map ac_mode_map_bw80[] = { + {0, 293}, /* in unit of 100k */ + {1, 585}, + {2, 878}, + {3, 1170}, + {4, 1755}, + {5, 2340}, + {6, 2633}, + {7, 2925}, + {8, 3510}, + {9, 3900}, +}; + +struct test_data_rate_map ac_mode_map_bw160[] = { + {0, 585}, /* in unit of 100k */ + {1, 1170}, + {2, 1755}, + {3, 2340}, + {4, 3510}, + {5, 4680}, + {6, 5265}, + {7, 5850}, + {8, 7020}, + {9, 7800}, +}; + +/* phy rates comes from NSS = 1, Long GI */ +static struct test_data_rate_map he_su_mode_map_bw20[] = { + /*index, nss1, nss2, nss3, nss4*/ + {0, 73}, /* in unit of 100k */ + {1, 146}, + {2, 219}, + {3, 293}, + {4, 439}, + {5, 585}, + {6, 658}, + {7, 731}, + {8, 878}, + {9, 975}, + {10, 1097}, + {11, 1219}, + {33, 36}, /* MCS0 DCM */ + {34, 73}, /* MCS1 DCM */ +}; + +static struct test_data_rate_map he_su_mode_map_bw40[] = { + /*index, nss1{0.8gi, 1.6gi, 3.2gi}, nss2{0.8gi, 1.6gi, 3.2gi}, + *nss3{0.8gi, 1.6gi, 3.2gi}, nss4{0.8gi, 1.6gi, 3.2gi} + */ + {0, 146}, /* in unit of 100k */ + {1, 293}, + {2, 439}, + {3, 585}, + {4, 878}, + {5, 1170}, + {6, 1316}, + {7, 1463}, + {8, 1755}, + {9, 1950}, + {10, 2194}, + {11, 2438}, + {33, 73}, /* MCS0 DCM */ + {34, 146}, /* MCS1 DCM */ +}; + + +static struct test_data_rate_map he_su_mode_map_bw80[] = { + /*index, nss1{0.8gi, 1.6gi, 3.2gi}, nss2{0.8gi, 1.6gi, 3.2gi}, + * nss3{0.8gi, 1.6gi, 3.2gi}, nss4{0.8gi, 1.6gi, 3.2gi} + */ + {0, 306}, /* in unit of 100k */ + {1, 613}, + {2, 919}, + {3, 1225}, + {4, 1838}, + {5, 2450}, + {6, 2756}, + {7, 3063}, + {8, 3675}, + {9, 4083}, + {10, 4594}, + {11, 5104}, + {33, 153}, /* MCS0 DCM */ + {34, 306}, /* MCS1 DCM */ +}; + +static struct test_data_rate_map he_su_mode_map_bw160[] = { + /*index, nss1{0.8gi, 1.6gi, 3.2gi}, nss2{0.8gi, 1.6gi, 3.2gi}, + *nss3{0.8gi, 1.6gi, 3.2gi}, nss4{0.8gi, 1.6gi, 3.2gi} + */ + {0, 613}, /* in unit of 100k */ + {1, 1225}, + {2, 1838}, + {3, 2450}, + {4, 3675}, + {5, 4900}, + {6, 5513}, + {7, 6125}, + {8, 7350}, + {9, 8166}, + {10, 9188}, + {11, 10208}, + {33, 306}, /* MCS0 DCM */ + {34, 613}, /* MCS1 DCM */ +}; + +static struct test_datalen_limit_map datalen_limit[] = { + {TEST_MODE_CCK, 2304}, + {TEST_MODE_OFDM, 2304}, + {TEST_MODE_HTMIX, 7935}, + {TEST_MODE_HTGREENFIELD, 7935}, + {TEST_MODE_VHT, 11454}, + {0}, /* reserved */ + {0}, /* reserved */ + {0}, /* reserved */ + {TEST_MODE_HE_SU, 11454}, + {TEST_MODE_HE_ER, 11454}, + {TEST_MODE_HE_MU, 11454}, + {TEST_MODE_HE_TB, 11454}, + {TEST_MODE_VHT_MIMO, 11454}, +}; + +static u_int8 test_he_bpscs[] = { + 1, 2, 2, 4, 4, 6, 6, 6, 8, 8, 10, 10 /* MCS0~11 */ +}; + +static u_int8 test_he_rate_density[] = { + 2, 2, 4, 2, 4, 3, 4, 6, 4, 6, 4, 6 /* MCS0~11 */ +}; + +static u_int8 test_ltf_sym[] = { + 0, 1, 2, 4, 4, 6, 6, 8, 8 /* SS 1~8 */ +}; + +static u_int8 test_he_t_ltf_sym_x5[] = { + 24, 40, 80 /* 3.2+1.6 us, 6.4+1.6, 12.8+3.2 */ +}; + +static u_int8 test_he_t_sym_x5[] = { + 68, 72, 80 /* base GI, double GI, quadruple GI */ +}; + +static u_int8 test_he_t_pe_x5[] = { + 0, 20, 40, 60, 80 /* 0us, 4us, 8us, 12us, 16us */ +}; + +static struct test_he_ru_const test_ru_const[] = { + {37, 24, 12, 6, 2}, + {53, 48, 24, 12, 6}, + {61, 102, 51, 24, 12}, + {65, 234, 117, 60, 30}, + {67, 468, 234, 120, 60}, + {68, 980, 490, 240, 120}, + {69, 1960, 980, 492, 246} +}; + +/***************************************************************************** + * Internal functions + *****************************************************************************/ +static s_int32 mt_engine_init_mps( + struct test_configuration *configs) +{ + struct test_mps_cb *mps_cb = NULL; + + mps_cb = &configs->mps_cb; + + if (mps_cb->mps_setting) + sys_ad_free_mem(mps_cb->mps_setting); + + sys_ad_zero_mem(mps_cb, sizeof(*mps_cb)); + mps_cb->setting_inuse = FALSE; + mps_cb->mps_cnt = 0; + mps_cb->stat = 0; + mps_cb->ref_idx = 1; + mps_cb->mps_setting = NULL; + SERV_OS_ALLOCATE_SPIN_LOCK(&mps_cb->lock); + + return SERV_STATUS_SUCCESS; +} + +static s_int32 mt_engine_release_mps( + struct test_configuration *configs) +{ + struct test_mps_cb *mps_cb = NULL; + + mps_cb = &configs->mps_cb; + + if (mps_cb->mps_setting) + sys_ad_free_mem(mps_cb->mps_setting); + + mps_cb->mps_setting = NULL; + mps_cb->setting_inuse = FALSE; + mps_cb->mps_cnt = 0; + mps_cb->stat = 0; + mps_cb->ref_idx = 1; + SERV_OS_FREE_SPIN_LOCK(&mps_cb->lock); + + return SERV_STATUS_SUCCESS; +} + +static u_int8 mt_engine_get_sigext_time_by_phymode(u_char tx_mode) +{ + u_int8 sigext_time = 0; + + switch (tx_mode) { + case TEST_MODE_CCK: + sigext_time = sigext_time_list[TEST_MODE_CCK]; + break; + + case TEST_MODE_OFDM: + sigext_time = sigext_time_list[TEST_MODE_OFDM]; + break; + + case TEST_MODE_HTMIX: + sigext_time = sigext_time_list[TEST_MODE_HTMIX]; + break; + + case TEST_MODE_HTGREENFIELD: + sigext_time = sigext_time_list[TEST_MODE_HTGREENFIELD]; + break; + + case TEST_MODE_VHT: + sigext_time = sigext_time_list[TEST_MODE_VHT]; + break; + + default: + sigext_time = sigext_time_list[TEST_MODE_OFDM]; + break; + } + + return sigext_time; +} + +static u_int16 mt_engine_get_slot_time_by_phymode(u_char tx_mode) +{ + u_int16 slot_time = 0; + + switch (tx_mode) { + case TEST_MODE_CCK: + slot_time = slot_time_list[TEST_MODE_CCK]; + break; + + case TEST_MODE_OFDM: + slot_time = slot_time_list[TEST_MODE_OFDM]; + break; + + case TEST_MODE_HTMIX: + slot_time = slot_time_list[TEST_MODE_HTMIX]; + break; + + case TEST_MODE_HTGREENFIELD: + slot_time = slot_time_list[TEST_MODE_HTGREENFIELD]; + break; + + case TEST_MODE_VHT: + slot_time = slot_time_list[TEST_MODE_VHT]; + break; + + default: + slot_time = slot_time_list[TEST_MODE_OFDM]; + break; + } + + return slot_time; +} + +static u_int8 mt_engine_trans_gi(u_int8 tx_mode, u_int32 ltf_gi) +{ + u_int8 gi_type = 0; + + if (tx_mode == TEST_MODE_HE_SU || + tx_mode == TEST_MODE_HE_ER || + tx_mode == TEST_MODE_HE_MU) { + switch (ltf_gi) { + case 1: + case 2: + gi_type = TEST_GI_8+(ltf_gi-1); + break; + case 3: + case 4: + gi_type = TEST_GI_8+((ltf_gi-3) ? 0:2); + break; + default: + gi_type = TEST_GI_8; + break; + } + } else if (tx_mode == TEST_MODE_HE_TB) { + switch (ltf_gi) { + case 2: + gi_type = TEST_GI_32; + break; + default: + gi_type = TEST_GI_16; + break; + } + } else /* for non-HE PPDU types, gi equavalent to Sgi. */ + gi_type = ltf_gi; + + return gi_type; +} + +static u_int8 mt_engine_trans_ltf(u_int8 tx_mode, u_int32 ltf_gi) +{ + u_int8 ltf_type = 0; + + if (tx_mode == TEST_MODE_HE_SU || tx_mode == TEST_MODE_HE_ER) { + switch (ltf_gi) { + case 1: + case 2: + ltf_type = TEST_HE_LTF_X2; + break; + case 3: + case 4: + ltf_type = TEST_HE_LTF_X4; + break; + default: + ltf_type = TEST_HE_LTF_X1; + break; + } + } else if (tx_mode == TEST_MODE_HE_MU) { + switch (ltf_gi) { + case 0: + case 3: + ltf_type = TEST_HE_LTF_X4; + break; + default: + ltf_type = TEST_HE_LTF_X2; + break; + } + } else if (tx_mode == TEST_MODE_HE_TB) { + ltf_type = ltf_gi; + } else /* for non-HE PPDU types, ltf is not required. */ + ltf_type = 0; + + return ltf_type; +} + + +static u_int16 mt_engine_get_cw(u_int32 ipg, u_int16 slot_time) +{ + u_int32 cnt = 0, val; + + val = (ipg + slot_time) / slot_time; + + while (val >>= 1) + cnt++; + + if (cnt >= TEST_MAX_CW) + cnt = TEST_MAX_CW; + + return cnt; +} + +static s_int32 mt_engine_calc_duty_cycle(struct test_configuration *configs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct ipg_param *ipg_param; + struct tx_time_param *tx_time_param; + u_int32 ipg, pkt_tx_time, duty_cycle; + + ipg_param = &configs->ipg_param; + tx_time_param = &configs->tx_time_param; + + ipg = ipg_param->ipg; + pkt_tx_time = tx_time_param->pkt_tx_time; + duty_cycle = configs->duty_cycle; + + /* Calculate needed ipg/pkt_tx_time and duty_cycle */ + if ((duty_cycle > 0) && (pkt_tx_time == 0) && (ipg == 0)) { + /* TODO: need to consider this case in the future */ + duty_cycle = 0; + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("%s: there are no pkt_tx_time/ipg!! ", + __func__)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("use default setting and set duty_cycle=%d\n", + duty_cycle)); + } else if ((duty_cycle > 0) && (pkt_tx_time > 0) && (ipg == 0)) { + ipg = ((pkt_tx_time * 100) / duty_cycle) - pkt_tx_time; + ipg_param->ipg = ipg; + /* + * If ipg value does't make sense, + * there's error handle when get ipg parameter + */ + ret = mt_engine_calc_ipg_param_by_ipg(configs); + if (ret) { + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("%s: calculate ipg_param fail!!\n", + __func__)); + } + } else if ((duty_cycle > 0) && (pkt_tx_time == 0) && (ipg > 0)) { + /* + * If pkt_tx_time does't make sense, + * there's error handle when start tx + */ + pkt_tx_time = (duty_cycle * ipg) / (100 - duty_cycle); + } else { + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("%s: already existed pkt_tx_time/ipg, ", + __func__)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("can't set duty_cycle!! ")); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("expected duty_cycle=%d%%\n", duty_cycle)); + + duty_cycle = (pkt_tx_time * 100) / (pkt_tx_time + ipg); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("%s: real duty_cycle=%d%%\n", __func__, duty_cycle)); + } + + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("%s: duty_cycle=%d%%, ipg=%dus, pkt_tx_time=%dus\n", + __func__, duty_cycle, ipg, pkt_tx_time)); + + tx_time_param->pkt_tx_time = pkt_tx_time; + configs->duty_cycle = duty_cycle; + + return ret; +} + +static s_int32 mt_engine_map_subcarriers( + u_int8 ru_index, u_int8 dcm) +{ + s_int32 subcarriers = 0, idx = 0; + + for (idx = 0 ; idx < SERV_ARRAY_SIZE(test_ru_const) ; idx++) { + if (ru_index < test_ru_const[idx].max_index) { + if (dcm) + subcarriers = test_ru_const[idx].sd_d; + else + subcarriers = test_ru_const[idx].sd; + + break; + } + } + + return subcarriers; +} + +static s_int32 mt_engine_map_subcarriers_short( + u_int8 ru_index, u_int8 dcm) +{ + s_int32 subcarriers_short = 0, idx = 0; + + for (idx = 0 ; idx < SERV_ARRAY_SIZE(test_ru_const) ; idx++) { + if (ru_index < test_ru_const[idx].max_index) { + if (dcm) + subcarriers_short = test_ru_const[idx].sd_s_d; + else + subcarriers_short = test_ru_const[idx].sd_s; + + break; + } + } + + return subcarriers_short; +} + +static s_int32 mt_engine_calc_bytes_by_time( + u_char tx_mode, u_char nss, u_char t_pe, u_char ltf, + u_char gi, s_int32 dbps, s_int32 tx_time) +{ + u_int8 m_stbc = 1, tail = 6; + u_int32 data_time = 0; + u_int32 symbol_cnt = 0, psdu_length = 0; + u_int32 ltf_time = test_ltf_sym[nss]*test_he_t_ltf_sym_x5[ltf]; + + data_time = tx_time*5; + data_time -= (5 * 20 + (20+40+40+ltf_time) + test_he_t_pe_x5[t_pe]); + symbol_cnt = engine_ceil(data_time, test_he_t_sym_x5[gi]); + + if (symbol_cnt > 0x3fff) /* H/W limitation */ + symbol_cnt = 0x3fff; + + psdu_length = ((symbol_cnt / m_stbc) * dbps - 16 - tail) / 8; + + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("\t%s: \tsymbol=%d, PSDU length:%d\n", + __func__, symbol_cnt, psdu_length)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("\t\t: \t(0x3fff is H/W limiation)\n")); + + return psdu_length; +} + +static u_int32 mt_engine_calc_txlen( + struct test_configuration *configs) +{ + struct tx_time_param *tx_time_param; + u_int32 txlen = 0, hlen = 0, tx_data_rate = 0, pkt_tx_time = 0; + u_char tx_mode, mcs, mcs_1ss, nss = 1; + u_char bw = 0, bw_fact = 1, sgi = 0; + + /* + * 1. Get the tx data rate + * 2. Get the packet tx time + * 3. Calculate the packet length by tx_data_rate and packet_tx_time + * 4. Return txlen + */ + tx_time_param = &configs->tx_time_param; + pkt_tx_time = tx_time_param->pkt_tx_time; + hlen = configs->hdr_len; + tx_mode = configs->tx_mode; + mcs = configs->mcs; + bw = configs->bw; + sgi = configs->sgi; + mcs_1ss = mcs; + + if (tx_mode == TEST_MODE_CCK) { + /* Legacy CCK mode */ + u_int8 cck_map_idx; + + for (cck_map_idx = 0; + cck_map_idx < SERV_ARRAY_SIZE(cck_mode_map); + cck_map_idx++) { + if (mcs_1ss == cck_mode_map[cck_map_idx].mcs) + break; + } + + if (cck_map_idx == SERV_ARRAY_SIZE(cck_mode_map)) { + tx_data_rate = cck_mode_map[0].tx_data_rate; + mcs = mcs_1ss = cck_mode_map[0].mcs; + configs->mcs = mcs; + } else + tx_data_rate = cck_mode_map[cck_map_idx].tx_data_rate; + + /* Transfer from bit to byte with expected tx time */ + txlen = pkt_tx_time * tx_data_rate / 1000 / 8; + } else if (tx_mode == TEST_MODE_OFDM) { + /* Legacy OFDM mode */ + u_int8 ofdm_map_idx; + + for (ofdm_map_idx = 0; + ofdm_map_idx < SERV_ARRAY_SIZE(ofdm_mode_map); + ofdm_map_idx++) { + if (mcs_1ss == ofdm_mode_map[ofdm_map_idx].mcs) + break; + } + + if (ofdm_map_idx == SERV_ARRAY_SIZE(ofdm_mode_map)) { + tx_data_rate = ofdm_mode_map[0].tx_data_rate; + mcs = mcs_1ss = ofdm_mode_map[0].mcs; + configs->mcs = mcs; + } else + tx_data_rate = ofdm_mode_map[ofdm_map_idx].tx_data_rate; + + /* Transfer from bit to byte with expected tx time */ + txlen = pkt_tx_time * tx_data_rate / 1000 / 8; + } else if (tx_mode == TEST_MODE_HTMIX + || tx_mode == TEST_MODE_HTGREENFIELD) { + /* HT mode */ + u_int8 n_map_idx; + + if (mcs != 32) { + mcs_1ss = mcs % 8; + nss = (mcs / 8) + 1; + bw_fact = (bw == TEST_BW_40) ? 2 : 1; + } else { + bw_fact = 1; + nss = 1; + } + + for (n_map_idx = 0; + n_map_idx < SERV_ARRAY_SIZE(n_mode_map); n_map_idx++) { + if (mcs_1ss == n_mode_map[n_map_idx].mcs) + break; + } + + if (n_map_idx == SERV_ARRAY_SIZE(n_mode_map)) { + tx_data_rate = n_mode_map[0].tx_data_rate; + mcs = mcs_1ss = n_mode_map[0].mcs; + configs->mcs = mcs; + } else + tx_data_rate = n_mode_map[n_map_idx].tx_data_rate; + + tx_data_rate = tx_data_rate * nss * bw_fact; + + if (sgi == 1) + tx_data_rate = (tx_data_rate / 9) * 10; + + /* Transfer from bit to byte with expected tx time */ + txlen = pkt_tx_time * tx_data_rate / 1000 / 8; + } else if (tx_mode == TEST_MODE_VHT) { + /* VHT mode */ + u_int8 ac_map_idx; + struct test_data_rate_map *vht_mode_map; + u_int32 array_cnt = 0; + + if (bw == TEST_BW_20) { + vht_mode_map = ac_mode_map_bw20; + array_cnt = SERV_ARRAY_SIZE(ac_mode_map_bw20); + } else if (bw == TEST_BW_40) { + vht_mode_map = ac_mode_map_bw40; + array_cnt = SERV_ARRAY_SIZE(ac_mode_map_bw40); + } else if (bw == TEST_BW_80) { + vht_mode_map = ac_mode_map_bw80; + array_cnt = SERV_ARRAY_SIZE(ac_mode_map_bw80); + } else if (bw == TEST_BW_160C) { + vht_mode_map = ac_mode_map_bw160; + array_cnt = SERV_ARRAY_SIZE(ac_mode_map_bw160); + } else { + vht_mode_map = ac_mode_map_bw20; + array_cnt = SERV_ARRAY_SIZE(ac_mode_map_bw20); + } + + for (ac_map_idx = 0; ac_map_idx < array_cnt; ac_map_idx++) { + if (mcs == vht_mode_map[ac_map_idx].mcs) + break; + } + + if (ac_map_idx == array_cnt) { + tx_data_rate = vht_mode_map[0].tx_data_rate; + mcs = mcs_1ss = vht_mode_map[0].mcs; + configs->mcs = mcs; + } else + tx_data_rate = vht_mode_map[ac_map_idx].tx_data_rate; + + /* TODO: need to check for sgi equation */ + if (sgi == 1) + tx_data_rate = (tx_data_rate / 9) * 10; + + /* Transfer from bit to byte with expected tx time */ + txlen = pkt_tx_time * tx_data_rate / 10 / 8; + } else if (tx_mode == TEST_MODE_HE_SU) { + u_int8 map_idx = 0; + struct test_data_rate_map *rate_map = NULL; + u_int32 array_cnt = 0; + + switch (sgi) { + case 0: + case 1: + case 4: + sgi = 0; + break; + case 2: + sgi = 1; + break; + case 3: + sgi = 2; + break; + } + + nss = configs->nss; + + if (bw == TEST_BW_20) { + rate_map = he_su_mode_map_bw20; + array_cnt = SERV_ARRAY_SIZE(he_su_mode_map_bw20); + } else if (bw == TEST_BW_40) { + rate_map = he_su_mode_map_bw40; + array_cnt = SERV_ARRAY_SIZE(he_su_mode_map_bw40); + } else if (bw == TEST_BW_80) { + rate_map = he_su_mode_map_bw80; + array_cnt = SERV_ARRAY_SIZE(he_su_mode_map_bw80); + } else if (bw == TEST_BW_160NC || bw == TEST_BW_160C) { + rate_map = he_su_mode_map_bw160; + array_cnt = SERV_ARRAY_SIZE(he_su_mode_map_bw160); + } else { + rate_map = he_su_mode_map_bw20; + array_cnt = SERV_ARRAY_SIZE(he_su_mode_map_bw20); + } + + for (map_idx = 0; + map_idx < array_cnt; + map_idx++) { + if (mcs == rate_map[map_idx].mcs) + break; + } + + if (map_idx == array_cnt) { + tx_data_rate = rate_map[0].tx_data_rate; + mcs = mcs_1ss = rate_map[0].mcs; + configs->mcs = mcs; + } else + tx_data_rate = rate_map[map_idx].tx_data_rate; + + tx_data_rate *= nss; + + switch (sgi) { + case 1: + tx_data_rate = (tx_data_rate * 100) / 90; + break; + + case 2: + tx_data_rate = (tx_data_rate * 100) / 85; + break; + + default: + if (sgi > 0) + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("%s: invalid gi=%d, ignored as 0.\n", + __func__, sgi)); + break; + } + /* Transfer from bit to byte with expected tx time */ + txlen = pkt_tx_time * tx_data_rate / 10 / 8; + } else if (tx_mode == TEST_MODE_HE_TB) { + struct test_ru_info *ru_info = NULL; + u_int32 ds = 0, dss = 0; + + ru_info = &configs->ru_info_list[0]; + mcs = (ru_info->rate & 0xf); + ds = mt_engine_map_subcarriers(ru_info->ru_index >> 1, + (ru_info->rate & BIT(5))); + + if (ds) { + dss = mt_engine_map_subcarriers_short( + ru_info->ru_index >> 1, + (ru_info->rate & BIT(5))); + + nss = ru_info->nss; + ru_info->cbps = ds * nss * test_he_bpscs[mcs]; + + ru_info->dbps = test_he_rate_density[mcs]-1; + ru_info->dbps *= ru_info->cbps; + ru_info->dbps /= test_he_rate_density[mcs]; + + txlen = mt_engine_calc_bytes_by_time(tx_mode, + nss, + 0, + mt_engine_trans_ltf(tx_mode, sgi), + mt_engine_trans_gi(tx_mode, sgi), + ru_info->dbps, + pkt_tx_time); + /* reserve FCS(4)+Delimiter(4)+ + * A-Control(4)+H/W revered(1) + */ + txlen -= 13; + ru_info->mpdu_length = txlen; + } else { + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("%s: unknown RU Index:[%d],\n", __func__, + (ru_info->ru_index >> 1))); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("\t\tforced transmit l024 bytes MPDU!\n")); + + /* reserve FCS(4)+Delimiter(4)+ + * A-Control(4)+H/W revered(1) + */ + txlen = 1024 - 13; + } + } + + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("%s: phy_mode=%d, mcs/mcs_1ss=%d/%d, nss=%d, ", + __func__, tx_mode, mcs, mcs_1ss, nss)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("bw/bw_fact=%d/%d, sgi=%d, ", bw, bw_fact, sgi)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("txlen=%d, pkt_tx_time=%d, tx_data_rate=%d\n", + txlen, pkt_tx_time, tx_data_rate)); + + if (tx_mode > TEST_MODE_VHT) { + if (txlen >= (TEST_MAX_VHT_MPDU_LEN * 256)) { + txlen = (TEST_MAX_VHT_MPDU_LEN * 256); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("%s: expected txlen > HE PPDU max len, ", + __func__)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("reduce the txlen=%d\n", txlen)); + } + } else if (tx_mode == TEST_MODE_VHT) { + if (txlen >= (TEST_MAX_VHT_MPDU_LEN * 64)) { + txlen = (TEST_MAX_VHT_MPDU_LEN * 64); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("%s: expected txlen > VHT PPDU max len, ", + __func__)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("reduce the txlen=%d\n", txlen)); + } + } else if (tx_mode == TEST_MODE_HTMIX + || tx_mode == TEST_MODE_HTGREENFIELD) { + if (txlen >= TEST_MAX_HT_AMPDU_LEN) { + txlen = TEST_MAX_HT_AMPDU_LEN; + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("%s: expected txlen > HT PPDU max len, ", + __func__)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("reduce the txlen=%d\n", txlen)); + } + } else if (tx_mode == TEST_MODE_OFDM) { + if (txlen >= TEST_MAX_MSDU_LEN) { + txlen = TEST_MAX_MSDU_LEN; + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("%s: expected txlen > OFDM PPDU max len, ", + __func__)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("reduce the txlen=%d\n", txlen)); + } + } else if (tx_mode == TEST_MODE_CCK) { + if (txlen >= TEST_MAX_MSDU_LEN) { + txlen = TEST_MAX_MSDU_LEN; + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("%s: expected txlen > CCK PPDU max len, ", + __func__)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("reduce the txlen=%d\n", txlen)); + } + } + + return txlen; +} + +static u_int32 mt_engine_calc_hlen( + struct test_configuration *configs, + boolean *need_qos, boolean *need_amsdu, boolean *need_ampdu) +{ + u_int32 txlen = 0, hlen = TEST_DEFAULT_MAC_HDR_LEN; + u_char tx_mode, use_data_frame = 1; + + /* + * 1. Get the tx data rate + * 2. Check if need to send packet with AMPDU format + * 3. Check if need to send packet with AMSDU-in-AMPDU format + * 4. Return the expected packet header length by tx packet type + * if need to has QoS field and HTC field. + */ + txlen = configs->tx_len; + tx_mode = configs->tx_mode; + + if (txlen <= TEST_MIN_MSDU_LEN) { + use_data_frame = 0; + /* Here we need to go mgmt/ctrl frame mode */ + } else if (txlen > TEST_MAX_MSDU_LEN) { + if (tx_mode > TEST_MODE_OFDM) { + *need_qos = TRUE; + /* mark need_amsdu to notify A-MSDU like packet */ + *need_amsdu = TRUE; + } + + if (txlen > datalen_limit[tx_mode].amsdu_limit) + *need_ampdu = TRUE; + } + + /* Force aggregation due to TXCMD required */ + if (tx_mode == TEST_MODE_VHT_MIMO || tx_mode == TEST_MODE_HE_MU) { + *need_qos = TRUE; + *need_ampdu = TRUE; + } + + if (use_data_frame && *need_qos) + hlen = TEST_QOS_MAC_HDR_LEN; + + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("%s: header len=%d -> %d\n", __func__, + configs->hdr_len, hlen)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("%s: txlen=%d, ", __func__, txlen)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("need_qos/amsdu/ampdu/dataframe=%d/%d/%d/%d/%d\n", + *need_qos, *need_amsdu, *need_ampdu, use_data_frame, hlen)); + + return hlen; +} + +static s_int32 mt_engine_handle_ampdu( + struct test_wlan_info *winfos, + struct test_configuration *configs, + struct test_operation *ops, + u_char *buf) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct tx_time_param *tx_time_param = NULL; + u_int32 txlen, per_mpdu_len; + u_int8 tx_hw_hdr_len; + u_int8 ampdu_agg_cnt = 0; + + /* Update WTBL first */ + ret = net_ad_cfg_wtbl(winfos, configs); + if (ret) + return ret; + + tx_time_param = &configs->tx_time_param; + tx_hw_hdr_len = winfos->chip_cap.tx_wi_size; + txlen = tx_time_param->pkt_tx_len; + + per_mpdu_len = TEST_MAX_MSDU_LEN; + ampdu_agg_cnt = txlen / per_mpdu_len; + + if (txlen % per_mpdu_len) + ampdu_agg_cnt++; + + tx_time_param->pkt_msdu_len = txlen/ampdu_agg_cnt; + tx_time_param->pkt_ampdu_cnt = ampdu_agg_cnt; + + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("txlen/msdu len/agg cnt=%d/%d/%d\n", + txlen, tx_time_param->pkt_msdu_len, + tx_time_param->pkt_ampdu_cnt)); + + ret = net_ad_fill_pkt(winfos, configs, buf, + tx_time_param->pkt_msdu_len, + tx_time_param->pkt_hdr_len); + + return ret; +} + +static s_int32 mt_engine_handle_non_ampdu( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char *buf) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct tx_time_param *tx_time_param; + + tx_time_param = &configs->tx_time_param; + + ret = net_ad_fill_pkt(winfos, configs, buf, + tx_time_param->pkt_msdu_len, + tx_time_param->pkt_hdr_len); + + return ret; +} + +static s_int32 mt_engine_gen_burst_pkt( + struct test_wlan_info *winfos, + struct test_configuration *configs, + struct test_operation *ops, + u_char *buf) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct tx_time_param *tx_time_param; + u_int32 txlen, hlen; + u_int8 need_qos, need_amsdu, need_ampdu; + + tx_time_param = &configs->tx_time_param; + + txlen = tx_time_param->pkt_tx_len; + hlen = tx_time_param->pkt_hdr_len; + need_qos = tx_time_param->pkt_need_qos; + need_amsdu = tx_time_param->pkt_need_amsdu; + need_ampdu = tx_time_param->pkt_need_ampdu; + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_TRACE, + ("%s: txlen/hlen=%d/%d, ", + __func__, txlen, hlen)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_TRACE, + ("qos/amsdu/ampdu=%d/%d/%d\n", + need_qos, need_amsdu, need_ampdu)); + + /* Update WTBL if necessary */ + /* Generate tx packet */ + /* + * Note: the difference between handle_ampdu/handle_non_ampdu + * is txlen and hlen, maybe reduce API here and call fill_pkt directly + */ + if (need_ampdu) { + ret = mt_engine_handle_ampdu(winfos, configs, ops, buf); + } else { + /* + * No aggregation, directly go with specific length + * and through ALTX queue + */ + tx_time_param->pkt_msdu_len = txlen; + ret = mt_engine_handle_non_ampdu(winfos, configs, buf); + } + + return ret; +} + +static s_int32 mt_engine_gen_pkt( + struct test_wlan_info *winfos, + struct test_configuration *configs, + struct test_operation *ops, + u_char *buf) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct tx_time_param *tx_time_param; + u_int32 pkt_tx_time; + + tx_time_param = &configs->tx_time_param; + + if (!buf) { + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("%s: null buf\n", __func__)); + + return SERV_STATUS_ENGINE_INVALID_NULL_POINTER; + } + + /* For long packet implementation */ + tx_time_param->pkt_tx_len = configs->tx_len; + tx_time_param->pkt_hdr_len = configs->hdr_len; + tx_time_param->pkt_need_qos = 0; + tx_time_param->pkt_need_amsdu = 0; + tx_time_param->pkt_need_ampdu = 0; + tx_time_param->pkt_ampdu_cnt = 1; + pkt_tx_time = tx_time_param->pkt_tx_time; + + if (pkt_tx_time > 0) { + u_int32 new_txlen; + + new_txlen = mt_engine_calc_txlen(configs); + + if (new_txlen > 0) + configs->tx_len = new_txlen; + else { + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("%s: can't get txlen by pkt tx time\n", + __func__)); + } + + tx_time_param->pkt_tx_len = new_txlen; + } + + tx_time_param->pkt_hdr_len = mt_engine_calc_hlen( + configs, &tx_time_param->pkt_need_qos, + &tx_time_param->pkt_need_amsdu, + &tx_time_param->pkt_need_ampdu); + + ret = mt_engine_gen_burst_pkt(winfos, configs, ops, buf); + + return ret; +} + +static s_int32 mt_engine_apply_ipg_param( + struct test_wlan_info *winfos, + struct test_configuration *configs, + struct test_operation *ops, + u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct ipg_param *ipg_param; + u_int32 ipg; + u_int16 slot_time, sifs_time, cw; + u_int8 aifsn, wmm_idx = 0; + + ipg_param = &configs->ipg_param; + ipg = ipg_param->ipg; + + if (ipg > 0) { + /* Get packet q_idx and decide which CR need to be changed */ + slot_time = ipg_param->slot_time; + sifs_time = ipg_param->sifs_time; + aifsn = ipg_param->aifsn; + cw = ipg_param->cw; + } else { + /* Write default value back to HW */ + slot_time = TEST_DEFAULT_SLOT_TIME; + sifs_time = TEST_DEFAULT_SIFS_TIME; + aifsn = TEST_MIN_AIFSN; + cw = 0; + } + + ipg_param->slot_time = slot_time; + ipg_param->sifs_time = sifs_time; + ipg_param->aifsn = aifsn; + ipg_param->cw = cw; + + ret = ops->op_set_ifs_cr(winfos, configs, band_idx); + if (ret) + goto err_out; + + ret = ops->op_set_slot_time(winfos, + (u_int8) slot_time, + (u_int8) sifs_time, + TEST_RIFS_TIME, + TEST_EIFS_TIME, + (u_int8) band_idx); + if (ret) + goto err_out; + + ret = net_ad_get_wmm_idx(configs->stack.virtual_device[0], &wmm_idx); + if (ret) + goto err_out; + + ret = net_ad_set_wmm_param_by_qid(wmm_idx, configs->ac_idx, + winfos, configs); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("%s: ipg=%d, slot_time=%d, sifs_time=%d, aifsn=%d, cw=%d\n", + __func__, ipg, slot_time, sifs_time, aifsn, cw)); + +err_out: + return ret; +} + +static boolean is_mt_engine_stack_full(struct test_configuration *configs) +{ + boolean ret = FALSE; + struct test_tx_stack *stack = &configs->stack; + + if (stack->index == stack->entry_limit) + ret = TRUE; + + return ret; +} + +static boolean is_mt_engine_stack_empty(struct test_configuration *configs) +{ + boolean ret = FALSE; + struct test_tx_stack *stack = &configs->stack; + + if (stack->index == 0) + ret = TRUE; + + return ret; +} + + +static s_int32 mt_engine_stack_push( + struct test_configuration *configs, + void *virtual_device, + u_int8 *da, + void *virtual_wtbl, + struct test_tx_info *tx_info) +{ + u_int32 ret = -1; + struct test_tx_stack *stack = &configs->stack; + + if (stack->index < stack->entry_limit) { + sys_ad_move_mem(stack->da[stack->index], da, SERV_MAC_ADDR_LEN); + stack->virtual_device[stack->index] = virtual_device; + stack->virtual_wtbl[stack->index] = virtual_wtbl; + sys_ad_move_mem(&stack->tx_info[stack->index], + tx_info, sizeof(*tx_info)); + ret = stack->index; + + stack->index++; + } else { + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("(%s)Stack for TX is full!\n", __func__)); + } + + return ret; +} + +static u_int32 mt_engine_stack_pop( + struct test_configuration *configs, + u_char **da, + void **virtual_wtbl) +{ + u_int32 ret = SERV_STATUS_SUCCESS; + struct test_tx_stack *stack = &configs->stack; + + if (stack->index > 0) { + *virtual_wtbl = stack->virtual_wtbl[stack->index-1]; + stack->virtual_wtbl[stack->index-1] = NULL; + stack->virtual_device[stack->index-1] = NULL; + *da = stack->da[stack->index-1]; + sys_ad_zero_mem(&stack->tx_info[stack->index-1], + sizeof(stack->tx_info[stack->index-1])); + + stack->index--; + } else { + ret = SERV_STATUS_ENGINE_FAIL; + *virtual_wtbl = NULL; + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("(%s)Stack for Tx is empty, dismissed\n", __func__)); + } + + return ret; +} + +static s_int32 mt_engine_store_tx_info( + struct test_operation *ops, + struct test_wlan_info *winfos, + struct test_configuration *configs, + void *virtual_device, + u_char *da, + void *virtual_wtbl, + struct test_tx_info *tx_info) +{ + s_int32 ret = SERV_STATUS_SUCCESS, sta_idx = -1; + u_char *pate_pkt = (u_char *)configs->test_pkt; + struct test_tx_stack *stack = &configs->stack; + + if (pate_pkt == NULL) { + ret = -1; + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("%s: Invalid pre-allocated buffer for MPDU\n", + __func__)); + + goto err_out; + } + + if (is_mt_engine_stack_full(configs) == FALSE) { + if (tx_info) { + net_ad_fill_phy_info(virtual_wtbl, tx_info); + + if ((configs->tx_mode < TEST_MODE_HE_SU) && + (tx_info->mcs & 0x7f) == 32) + net_ad_handle_mcs32(winfos, + virtual_wtbl, + tx_info->bw); + } else { + ret = SERV_STATUS_ENGINE_INVALID_NULL_POINTER; + goto err_out; + } + + net_ad_apply_wtbl(winfos, virtual_device, virtual_wtbl); + + sta_idx = mt_engine_stack_push(configs, + virtual_device, + da, + virtual_wtbl, + tx_info); + + if (sta_idx > -1 && sta_idx < MAX_MULTI_TX_STA) { + u_int8 *pate_pkt = configs->test_pkt; + struct tx_time_param *tx_time_param = NULL; + u_int32 pkt_tx_time = 0; + u_int32 tx_len = 0; + + tx_time_param = &configs->tx_time_param; + pkt_tx_time = tx_time_param->pkt_tx_time; + + tx_len = tx_info->mpdu_length; + configs->tx_len = tx_info->mpdu_length; + + /* Prepare tx packet */ + ret = mt_engine_gen_pkt(winfos, + configs, + ops, + pate_pkt); + + if (ret != SERV_STATUS_SUCCESS) { + SERV_LOG(SERV_DBG_CAT_ENGN, + SERV_DBG_LVL_ERROR, + ("%s: Generate packets failed(0x%04x)\n", + __func__, ret)); + goto err_out; + } + + if (stack->pkt_skb[sta_idx]) + ret = net_ad_free_pkt(winfos, + stack->pkt_skb[sta_idx]); + + if (ret != SERV_STATUS_SUCCESS) { + SERV_LOG(SERV_DBG_CAT_ENGN, + SERV_DBG_LVL_ERROR, + ("%s: Free Packet fail(0x%04x)\n", + __func__, ret)); + goto err_out; + } else + stack->pkt_skb[sta_idx] = NULL; + + ret = net_ad_alloc_pkt(winfos, + configs, + tx_time_param->pkt_msdu_len, + &stack->pkt_skb[sta_idx]); + + if (ret != SERV_STATUS_SUCCESS) { + SERV_LOG(SERV_DBG_CAT_ENGN, + SERV_DBG_LVL_ERROR, + ("%s: Allocate Packet fail(0x%04x)\n", + __func__, ret)); + goto err_out; + } else { + configs->is_alloc_skb |= BIT(sta_idx); + } + } else { + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("%s: TX stack entry stored failed\n", + __func__)); + } + } else { + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("%s: Tx stack is full!\n", __func__)); + } + +err_out: + return ret; +} + +static u_int8 mt_engine_decode_gi( + u_int8 tx_mode, + u_int32 ltf_gi) +{ + u_int8 gi_type = 0; + + if (tx_mode == TEST_MODE_HE_SU || + tx_mode == TEST_MODE_HE_ER || + tx_mode == TEST_MODE_HE_MU) { + switch (ltf_gi) { + case 1: + case 2: + gi_type = TEST_GI_8+(ltf_gi-1); + break; + case 3: + case 4: + gi_type = TEST_GI_8+((ltf_gi-3) ? 0:2); + break; + default: + gi_type = TEST_GI_8; + break; + } + } else if (tx_mode == TEST_MODE_HE_TB) { + switch (ltf_gi) { + case 2: + gi_type = TEST_GI_32; + break; + default: + gi_type = TEST_GI_16; + break; + } + } else /* for non-HE PPDU types, gi equavalent to Sgi. */ + gi_type = ltf_gi; + + return gi_type; +} + +static u_int8 mt_engine_decode_ltf( + u_int8 tx_mode, + u_int32 ltf_gi) +{ + u_int8 ltf_type = 0; + + if (tx_mode == TEST_MODE_HE_SU || tx_mode == TEST_MODE_HE_ER) { + switch (ltf_gi) { + case 1: + case 2: + ltf_type = TEST_HE_LTF_X2; + break; + case 3: + case 4: + ltf_type = TEST_HE_LTF_X4; + break; + default: + ltf_type = TEST_HE_LTF_X1; + break; + } + } else if (tx_mode == TEST_MODE_HE_MU) { + switch (ltf_gi) { + case 0: + case 3: + ltf_type = TEST_HE_LTF_X4; + break; + default: + ltf_type = TEST_HE_LTF_X2; + break; + } + } else if (tx_mode == TEST_MODE_HE_TB) { + ltf_type = ltf_gi; + } else /* for non-HE PPDU types, ltf is not required. */ + ltf_type = TEST_HE_LTF_X1; + + return ltf_type; +} + +static u_int8 mt_engine_get_sub_band(u_int32 ru_index) +{ + u_int8 sub_band_idx = 0; + + if (ru_index == 68 || ru_index == 67) + sub_band_idx = 0; + else if (ru_index > 64) + sub_band_idx = ((ru_index % 65) * 2); + else if (ru_index > 60) + sub_band_idx = (ru_index % 61); + else if (ru_index > 52) + sub_band_idx = ((ru_index % 53) >> 1); + else if (ru_index > 36) + sub_band_idx = ((ru_index % 37) >> 2); + else + sub_band_idx = (ru_index / 9); + + return sub_band_idx; +} + +static u_int32 mt_engine_add_allocation( + struct test_ru_allocatoin *alloc_info, + u_int8 allocation, + u_int8 seg, + u_int32 ru_index) +{ + u_int8 sub_band_idx = 0; + + sub_band_idx = mt_engine_get_sub_band(ru_index) + seg*4; + + if ((sub_band_idx > 4) || (sub_band_idx < 0)) { + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_TRACE, + ("%s: idx is invaild:%d\n ", + __func__, sub_band_idx)); + + sys_ad_set_mem(&alloc_info->sub20[0], 8, 0x72); + return SERV_STATUS_ENGINE_INVALID_PARAM; + } + + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_TRACE, + ("%s: ru index:%d (%d), ", + __func__, ru_index, sub_band_idx)); + /* 0x7f is center-26 tone, should be ignored */ + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_TRACE, + ("%2x -> %2x\n", + alloc_info->sub20[sub_band_idx], allocation)); + if ((alloc_info->sub20[sub_band_idx] != allocation) + && (allocation != 0x7f)) { + if (alloc_info->sub20[sub_band_idx] == 0xff) { + alloc_info->sub20[sub_band_idx] = allocation; + + if (allocation == 0xc8) { + /* D3.1, Table 28-24, 0xc8 is 484-tone + * D3.1, Table 28-24, 0x72 is 484-empty-tone + */ + if (((sub_band_idx+1) >= 0) + && ((sub_band_idx+1) < 8)) + alloc_info-> + sub20[sub_band_idx+1] = 0x72; + else + return SERV_STATUS_ENGINE_INVALID_PARAM; + + } else if (allocation == 0xd0) { + /* D3.1, Table 28-24, 0xd0 is 996-tone + * D3.1, Table 28-24, 0x73 is 484-empty-tone + */ + if (((sub_band_idx+1) >= 0) + && ((sub_band_idx+3) < 8)) { + alloc_info-> + sub20[sub_band_idx+1] = 0x73; + alloc_info-> + sub20[sub_band_idx+2] = 0x73; + alloc_info-> + sub20[sub_band_idx+3] = 0x73; + } else + return SERV_STATUS_ENGINE_INVALID_PARAM; + + } + } + } + + return SERV_STATUS_SUCCESS; +} + +static s_int32 mt_engine_fill_empty_allocation( + struct test_ru_allocatoin *alloc_info) +{ + u_int8 alloc_idx = 0; + + for (alloc_idx = 0 ; alloc_idx < sizeof(*alloc_info) ; alloc_idx++) { + /* D3.1, Table 28-24, 0x71 is 242-empty */ + if (alloc_info->sub20[alloc_idx] == 0xff) + alloc_info->sub20[alloc_idx] = 0x71; + } + + return SERV_STATUS_SUCCESS; +} + +static s_int32 mt_engine_calc_symbol_by_bytes( + struct test_ru_info *ru_info, boolean stbc, + u_char rate_den, u_int32 apep_length) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + s_int32 m_stbc = 1, tail = 6; + u_int32 rate = 0; + s_int32 ds = 0, dss = 0; + + ds = mt_engine_map_subcarriers(ru_info->ru_index >> 1, + (ru_info->rate & BIT(5))); + + if (ds) + dss = mt_engine_map_subcarriers_short(ru_info->ru_index >> 1, + (ru_info->rate & BIT(5))); + else { + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("%s: unknown RU Index:[%d]!\n", + __func__, (ru_info->ru_index >> 1))); + + ret = SERV_STATUS_ENGINE_INVALID_PARAM; + goto err_out; + } + + rate = ru_info->rate & (~BIT(5)); + + if (stbc) + m_stbc++; + + if (ru_info->ldpc) + tail = 0; + + ru_info->cbps = ds * ru_info->nss * test_he_bpscs[rate]; + ru_info->dbps = ru_info->cbps * (rate_den-1) / rate_den; + ru_info->cbps_s = dss * ru_info->nss * test_he_bpscs[rate]; + ru_info->dbps_s = ru_info->cbps_s * (rate_den-1) / rate_den; + + apep_length *= 8; + apep_length += (16 + tail); + ru_info->symbol_init = engine_ceil(apep_length, + (m_stbc * ru_info->dbps)); + ru_info->symbol_init *= m_stbc; + ru_info->excess = (apep_length % (m_stbc * ru_info->dbps)); + + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("%s: RU index[%d], apep length:%d symbol_init:%d,\n", + __func__, ru_info->ru_index >> 1, + apep_length, ru_info->symbol_init)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("\t%s: R[%d/%d], cbps:%d, dbps:%d,\n", + __func__, rate_den-1, rate_den, ru_info->cbps, ru_info->dbps)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("\t%s: cbps_s:%d, dbps_s:%d excess:%d\n", + __func__, ru_info->cbps_s, + ru_info->dbps_s, ru_info->excess)); + +err_out: + return ret; +} + +static s_int32 mt_engine_calc_afactor(struct test_ru_info *ru_info) +{ + s_int32 ret = 0, m_stbc = 1; + + if (ru_info->excess == 0) { + ru_info->excess = m_stbc * ru_info->dbps; + ru_info->afactor_init = 4; + } else { + u_int32 sym_short = (m_stbc * ru_info->dbps_s); + u_int32 symbol = engine_ceil(ru_info->excess, sym_short); + + ru_info->afactor_init = engine_min(4, symbol); + } + + /* prepare for caculate ldpc extra symbol */ + if (ru_info->afactor_init == 4) { + ru_info->dbps_last = ru_info->dbps; + ru_info->cbps_last = ru_info->cbps; + } else { + ru_info->dbps_last = ru_info->afactor_init * ru_info->dbps_s; + ru_info->cbps_last = ru_info->afactor_init * ru_info->cbps_s; + } + + ru_info->pld = (ru_info->symbol_init - m_stbc) * ru_info->dbps; + ru_info->pld += m_stbc * ru_info->dbps_last; + ru_info->avbits = (ru_info->symbol_init - m_stbc) * ru_info->cbps; + ru_info->avbits += m_stbc * ru_info->cbps_last; + + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("\t%s: \tafactor=%d, symbol cnt=%d\n", + __func__, ru_info->afactor_init, ru_info->symbol_init)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("\t%s: cbps_l:%d, dbps_l:%d, pld:%d, avbits:%d\n", + __func__, ru_info->cbps_last, ru_info->dbps_last, + ru_info->pld, ru_info->avbits)); + + return ret; +} + +static s_int32 mt_engine_calc_l_ldpc( + s_int32 avbits, s_int32 pld, u_char rate_den, + s_int32 *cw, s_int32 *l_ldpc) +{ + if (avbits <= 648) { + *cw = 1; + *l_ldpc = ((avbits >= (pld + 912/rate_den)) ? 2 : 1) * 648; + } else if (avbits <= (648 * 2)) { + *cw = 1; + *l_ldpc = ((avbits >= (pld + 1464/rate_den)) ? 3 : 2) * 648; + } else if (avbits <= (648 * 3)) { + *cw = 1; + *l_ldpc = (648 * 3); + } else if (avbits <= (648 * 4)) { + *cw = 2; + *l_ldpc = ((avbits >= (pld + 2916/rate_den)) ? 3 : 2) * 648; + } else { + *cw = engine_ceil((pld * rate_den), ((648 * 3) * (rate_den-1))); + *l_ldpc = (648 * 3); + } + + return 0; +} + +static boolean mt_engine_calc_extr_sym( + struct test_ru_info *ru_info, boolean stbc, u_char rd) +{ + boolean ret = FALSE; + s_int32 cw = 0, l_ldpc = 0, shrt = 0; + + mt_engine_calc_l_ldpc(ru_info->avbits, ru_info->pld, rd, &cw, &l_ldpc); + + shrt = (s_int32)((cw * l_ldpc * (rd-1) / rd) - ru_info->pld); + if (shrt < 0) + shrt = 0; + ru_info->punc = (s_int16)(cw * l_ldpc - ru_info->avbits - shrt); + if (ru_info->punc < 0) + ru_info->punc = 0; + + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_TRACE, + ("\t%s: cw:%d, avbits:%d, punc:%d, l_ldpc:%d, shrt:%d\n", + __func__, cw, ru_info->avbits, ru_info->punc, l_ldpc, shrt)); + + if (((10 * ru_info->punc > cw * l_ldpc / rd) && + (5 * shrt < 6 * ru_info->punc * (rd-1))) || + (10 * ru_info->punc > 3 * cw * l_ldpc / rd)) + ret = TRUE; + + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("\t%s: LDPC extra symbol:%d\n", __func__, ret)); + + return ret; +} + +static s_int32 mt_engine_calc_pe_disamb( + struct test_ru_info *ru_info, u_char ltf_gi, u_char max_pe) +{ + u_int8 pe_symbol_x5 = 0; + s_int32 ret = 0, gi = 0; + u_int32 t_pe = ru_info->afactor_init; + s_int32 ltf_time = 0; + u_int32 nss = engine_max(ru_info->ru_mu_nss, ru_info->nss); + + ltf_time = test_ltf_sym[nss]; + ltf_time *= test_he_t_ltf_sym_x5[ltf_gi]; + + if (ltf_gi == 2) + gi = TEST_GI_32; + else + gi = TEST_GI_16; + + /* txtime = 20 + T_HE-PREAMBLE + N_SYM*T_SYM + + * N_MA*N_HE-LTF*T_HE-LTF-SYM + T_PE + + * SignalExtension (28-135) + * T_HE-PREAMBLE = T_RL-SIG + T_HE-SIG-A + + * T_HE-STF-T + N_HE-LTF*T_HE-LTF-SYM, + * for an HE TB PPDU + * According to Table 28-12 of 802.11ax D3.0, T_RL-SIG = 4, + * T_HE-SIG-A = 8, T_HE-STF-T = 8, + * N_HE-LTF*T_HE-LTF-SYM (N_HE-LTF = {1,2,4,6})) + * N_MA = 0 due to doppler is not support, and SignalExtension = 0 + * due to not supported + */ + ru_info->tx_time_x5 = 5 * 20 + (20+40+40+ltf_time) + + ru_info->symbol_init * test_he_t_sym_x5[gi] + 0 + + test_he_t_pe_x5[t_pe] + 0; + ru_info->l_len = engine_ceil((ru_info->tx_time_x5-20*5), (4*5))*3-3-2; + + pe_symbol_x5 = test_he_t_pe_x5[t_pe]; + pe_symbol_x5 += (4 * (((ru_info->tx_time_x5 - 20 * 5)%20) ? 1 : 0)); + if (pe_symbol_x5 >= test_he_t_sym_x5[gi]) + ru_info->pe_disamb = 1; + else + ru_info->pe_disamb = 0; + + ru_info->t_pe = t_pe; + + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("\t%s: L-Len=%d, PE Disambiguilty=%d\n", + __func__, ru_info->l_len, ru_info->pe_disamb)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("\t\t%s: tx_time(x5)=%d, tx_ltf_sym(x5):%d,\n", + __func__, ru_info->tx_time_x5, ltf_time)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("\t\t%s: tx_sym(x5):%d, tx_pe(x5):%d\n", + __func__, test_he_t_sym_x5[gi], test_he_t_pe_x5[t_pe])); + + return ret; +} + +static s_int32 mt_engine_recalc_phy_info( + struct test_ru_info *ru_info, u_int8 stbc, u_int8 ltf_gi, u_int8 max_pe) +{ + u_char rd = 0; + u_char m_stbc = (stbc) ? 2 : 1; + s_int32 shrt = 0; + u_int32 cw = 0, l_ldpc = 0; + + rd = test_he_rate_density[ru_info->rate & ~BIT(5)]; + + if (ru_info->afactor_init == 3) { + u_int32 short_sym = ru_info->afactor_init * ru_info->cbps_s; + + ru_info->avbits += m_stbc * (ru_info->cbps - short_sym); + } else + ru_info->avbits += m_stbc * ru_info->cbps_s; + + mt_engine_calc_l_ldpc(ru_info->avbits, ru_info->pld, + rd, &cw, &l_ldpc); + + shrt = (s_int32)(cw * l_ldpc * (rd-1) / rd - ru_info->pld); + if (shrt < 0) + shrt = 0; + ru_info->punc = (s_int32)(cw * l_ldpc - ru_info->avbits - shrt); + if (ru_info->punc < 0) + ru_info->punc = 0; + + if (ru_info->afactor_init == 4) { + ru_info->symbol_init += m_stbc; + ru_info->afactor_init = 1; + } else + ru_info->afactor_init++; + + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("\t\t%s: (re)afactor:%d\n", + __func__, ru_info->afactor_init)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_TRACE, + ("\t\t%s: (re)cw:%d, (re)avbits:%d,\n", + __func__, cw, ru_info->avbits)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_TRACE, + ("\t\t%s: (re)punc:%d, (re)l_ldpc:%d, (re)shrt:%d\n", + __func__, ru_info->punc, l_ldpc, shrt)); + + mt_engine_calc_pe_disamb(ru_info, ltf_gi, max_pe); + + return SERV_STATUS_SUCCESS; +} + + +s_int32 mt_engine_calc_phy( + struct test_ru_info *ru_info, + u_int32 apep_length, + u_int8 stbc, + u_int8 ltf_gi, + u_int8 max_tpe) +{ + u_char rate_den = 0; + + rate_den = test_he_rate_density[ru_info->rate & ~BIT(5)]; + mt_engine_calc_symbol_by_bytes(ru_info, stbc, rate_den, apep_length); + mt_engine_calc_afactor(ru_info); + mt_engine_calc_pe_disamb(ru_info, ltf_gi, max_tpe); + + if (ru_info->ldpc && + mt_engine_calc_extr_sym(ru_info, stbc, rate_den)) { + ru_info->ldpc_extr_sym = 1; + + mt_engine_recalc_phy_info(ru_info, stbc, ltf_gi, max_tpe); + } + + return SERV_STATUS_SUCCESS; +} + +static struct test_ru_info *mt_engine_search_dom_ru( + struct test_configuration *configs) +{ + u_int8 sta_idx = 0; + u_int8 dominate_user_idx = 0; + u_int32 max_tx_time = 0; + struct test_ru_info *ru_info = &configs->ru_info_list[0]; + + for (sta_idx = 0 ; sta_idx < MAX_MULTI_TX_STA ; sta_idx++) { + if (ru_info[sta_idx].valid) { + if (ru_info[sta_idx].tx_time_x5 > max_tx_time) { + max_tx_time = ru_info[sta_idx].tx_time_x5; + dominate_user_idx = sta_idx; + } + } + } + + configs->dmnt_ru_idx = dominate_user_idx; + ru_info = &configs->ru_info_list[dominate_user_idx]; + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("%s: dominated by user[%d], RU index:%d\n", + __func__, dominate_user_idx, ru_info->ru_index >> 1)); + + return ru_info; +} + +static s_int32 mt_engine_apply_spe_antid( + struct test_operation *ops, + struct test_wlan_info *winfos, + struct test_configuration *configs) +{ + u_int8 band_idx = 0; + u_int8 ant_pri = 0, spe_idx = 0, stack_idx = 0; + s_int32 ret = SERV_STATUS_SUCCESS; + u_int32 ant_sel = configs->tx_ant; + struct test_tx_stack *stack = &configs->stack; + + net_ad_get_band_idx(stack->virtual_device[0], &band_idx); + + if (ant_sel & TEST_ANT_USER_DEF) { + ant_sel &= ~TEST_ANT_USER_DEF; + spe_idx = ant_sel; + } else { + /* fix me, ant_sel should not depend on band index */ + ant_sel >>= 2*band_idx; + + net_ad_get_speidx(winfos, ant_sel, &spe_idx); + } + + + /* store SPE index to TXD and WTBL */ + while (stack->virtual_wtbl[stack_idx] && (stack_idx < (stack->index))) { + net_ad_fill_spe_antid(winfos, stack->virtual_wtbl[stack_idx], + spe_idx, ant_pri); + stack_idx++; + } + ops->op_set_mutb_spe(winfos, band_idx, configs->tx_mode, spe_idx); + + return ret; +} + +/***************************************************************************** + * Extern functions + *****************************************************************************/ +s_int32 mt_engine_search_stack( + struct test_configuration *configs, + u_int8 wcid, + void **virtual_wtbl) +{ + s_int32 ret = SERV_STATUS_ENGINE_FAIL, idx = 0; + struct test_tx_stack *stack = &configs->stack; + + if (stack->index == 0) { + SERV_LOG(SERV_DBG_CAT_ENGN, + SERV_DBG_LVL_ERROR, + ("(%s)Stack for Tx is empty, dismissed!\n", __func__)); + + goto end; + } else { + for (idx = 0 ; idx < stack->index ; idx++) { + if (stack->virtual_wtbl[idx] && + net_ad_match_wtbl(stack->virtual_wtbl[idx], + wcid)) { + *virtual_wtbl = stack->virtual_wtbl[idx]; + ret = SERV_STATUS_SUCCESS; + break; + } + } + } + +end: + return ret; +} + +s_int32 mt_engine_unsubscribe_tx( + struct test_operation *ops, + struct test_wlan_info *winfos, + struct test_configuration *configs) +{ + u_char *da = NULL; + u_int32 ret = SERV_STATUS_SUCCESS; + void *virtual_wtbl = NULL; + + while (is_mt_engine_stack_empty(configs) == FALSE) { + mt_engine_stack_pop(configs, &da, &virtual_wtbl); + + net_ad_free_wtbl(winfos, da, virtual_wtbl); + } + +#if defined(CONFIG_AP_SUPPORT) && defined(CFG_SUPPORT_FALCON_MURU) + if (ops->op_set_tam_arb) + ops->op_set_tam_arb(winfos, 0x1); +#endif + + return ret; +} + +s_int32 mt_engine_subscribe_tx( + struct test_operation *ops, + struct test_wlan_info *winfos, + struct test_configuration *configs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_tx_info tx_info; + u_int8 tx_mthd = 0, tone_idx = 0; + void *virtual_device = NULL, *virtual_wtbl = NULL; + + if (!is_mt_engine_stack_empty(configs)) { + mt_engine_unsubscribe_tx(ops, winfos, configs); + + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("%s: Preiously stored TX information will be flushed!\n", + __func__)); + } + + sys_ad_zero_mem(&tx_info, sizeof(tx_info)); + + /* Calculate duty_cycle related parameter first */ + if (configs->duty_cycle > 0) + ret = mt_engine_calc_duty_cycle(configs); + + tx_info.tx_mode = configs->tx_mode; + if (configs->per_pkt_bw >= TEST_BW_160C) + tx_info.bw = 0x3; + else + tx_info.bw = configs->per_pkt_bw; + tx_info.stbc = configs->stbc; + tx_info.ldpc = configs->ldpc; + tx_info.mpdu_length = configs->tx_len; + tx_info.gi = mt_engine_decode_gi(configs->tx_mode, configs->sgi); + tx_info.ltf = mt_engine_decode_ltf(configs->tx_mode, configs->sgi); + tx_info.ibf = configs->ibf; + tx_info.ebf = configs->ebf; + + tx_mthd = configs->tx_method[configs->tx_mode]; + virtual_device = (struct wifi_dev *)configs->wdev[tx_mthd]; + + if (tx_info.tx_mode < TEST_MODE_HE_TB) { + if (ops->op_set_tam_arb) + ops->op_set_tam_arb(winfos, 0x5); + + tx_info.mcs = configs->mcs; + tx_info.nss = configs->nss; + + if (net_ad_alloc_wtbl(winfos, + configs->addr1[0], + virtual_device, + &virtual_wtbl) == SERV_STATUS_SUCCESS) + mt_engine_store_tx_info(ops, + winfos, + configs, + virtual_device, + configs->addr1[0], + virtual_wtbl, + &tx_info); + else { + ret = SERV_STATUS_OSAL_NET_INVALID_NULL_POINTER; + goto err_out; + } + } else { + u_int8 idx = 0, *da = NULL; + struct test_ru_info *ru_info = &configs->ru_info_list[0]; + + if (tx_info.tx_mode == TEST_MODE_VHT_MIMO) + tx_info.tx_mode = TEST_MODE_VHT; + + for (idx = 0 ; idx < MAX_MULTI_TX_STA ; idx++) { + da = configs->addr1[idx]; + if (ru_info[idx].valid) { + tx_info.mcs = ru_info[idx].rate; + tx_info.nss = ru_info[idx].nss; + tx_info.ldpc = ru_info[idx].ldpc; + if (ru_info[idx].mpdu_length > + TEST_QOS_MAC_HDR_LEN) + tx_info.mpdu_length = + ru_info[idx].mpdu_length; + + ret = net_ad_alloc_wtbl(winfos, + configs->addr1[idx], + virtual_device, + &virtual_wtbl); + + if (ret == SERV_STATUS_SUCCESS) { + if (ru_info[idx].aid) + net_ad_set_aid(virtual_wtbl, + ru_info[idx].aid); + mt_engine_store_tx_info(ops, + winfos, + configs, + virtual_device, + configs->addr1[idx], + virtual_wtbl, + &tx_info); + } else + goto err_out; + + + if (tx_info.tx_mode == TEST_MODE_HE_MU) { + mt_engine_add_allocation( + &configs->ru_alloc, + ru_info[idx].allocation, + (ru_info[idx].ru_index & 0x1), + (ru_info[idx].ru_index >> 1)); + } else { + /* TEST_MODE_HE_TB */ + mt_engine_calc_phy(&ru_info[idx], + tx_info.mpdu_length+13, + tx_info.stbc, + configs->sgi, + configs->max_pkt_ext); + } + } + } + if (tx_info.tx_mode == TEST_MODE_HE_MU) { + mt_engine_fill_empty_allocation(&configs->ru_alloc); + + for (tone_idx = 0; + tone_idx < sizeof(configs->ru_alloc); + tone_idx++) { + SERV_LOG(SERV_DBG_CAT_ENGN, + SERV_DBG_LVL_ERROR, + ("%s: allocation[%d] = 0x%x\n", + __func__, + tone_idx, + configs->ru_alloc.sub20[tone_idx])); + } + + if (ops->op_set_tam_arb) { + ret = ops->op_set_tam_arb(winfos, 0x2); + if (ret != SERV_STATUS_SUCCESS) + goto err_out; + } + + if (ops->op_set_muru_manual) { + ret = ops->op_set_muru_manual(virtual_device, + winfos, + configs); + if (ret != SERV_STATUS_SUCCESS) + goto err_out; + } + } + } + + if (ops->op_set_ampdu_ba_limit) { + ret = ops->op_set_ampdu_ba_limit(winfos, + configs, + configs->tx_time_param.pkt_ampdu_cnt); + if (ret) + return ret; + } + + if (ops->op_set_sta_pause_cr) { + ret = ops->op_set_sta_pause_cr(winfos); + if (ret) + return ret; + } + + ret = mt_engine_apply_spe_antid(ops, winfos, configs); + if (ret != SERV_STATUS_SUCCESS) + goto err_out; + +#if 0 +#ifdef SINGLE_SKU_V2 + Ret = mt_engine_apply_pwr_offset(ad, ctrl_band_idx); +#endif +#endif +err_out: + if (ret) + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("%s: err=0x%04x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_engine_start( + struct test_wlan_info *winfos, + struct test_backup_params *bak, + struct test_configuration *configs, + struct test_operation *ops, + struct test_bk_cr *bks, + struct test_rx_stat *rx_stat, + u_int32 en_log) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_configuration *test_config; + /* TODO: factor out here for rx_filter data struct */ + struct rx_filter_ctrl rx_filter; + u_char band_idx; + + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + for (band_idx = TEST_DBDC_BAND0; + band_idx < TEST_DBDC_BAND_NUM; band_idx++) { + test_config = &configs[band_idx]; + + /*** Step1: Sanity check ***/ + /* Make sure mt_engine_init_band_info successfully + when interface up + */ + if (test_config->op_mode & OP_MODE_START) { + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_WARN, + ("%s: test mode has already started, ", + __func__)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_WARN, + ("wdev_idx:%u, band_idx:%u\n", + test_config->wdev_idx, band_idx)); + + goto done; + } + + /* Allocate tx packet buffer */ + if (!test_config->test_pkt) { + ret = sys_ad_alloc_mem( + (u_char **)&test_config->test_pkt, + TEST_PKT_LEN); + if (ret) + goto err; + } + + /*** Step2: Remind firmware that enable test mode ***/ + ret = ops->op_set_fw_mode(winfos, 1); + if (ret) + goto err; + + /* TODO: factor out here for BF related init */ +#if 0 +#if (defined(MT_MAC)) +#ifdef TXBF_SUPPORT + /* Before going into ATE mode, stop sounding first */ + mt_Trigger_Sounding_Packet(pAd, FALSE, 0, 0, 0, NULL); +#endif /* TXBF_SUPPORT */ +#endif /* MT_MAC */ +#endif + /* TODO: factor out here for PCIE related init */ +#if 0 +#ifdef PCIE_ASPM_DYM_CTRL_SUPPORT + mt_asic_pcie_aspm_dym_ctrl(pAd, band_idx, FALSE, FALSE); + set_pcie_aspm_dym_ctrl_cap(pAd, FALSE); +#endif /* PCIE_ASPM_DYM_CTRL_SUPPORT */ +#endif + + /*** Step3: Backup and set CRs for test mode ***/ + /* + * Backup original CRs and change to + * test mode specific CR settings. + * Restore it back when go back to normal mode. + */ + ret = ops->op_backup_and_set_cr(winfos, bks, band_idx); + if (ret) + goto err; + + /*** Step4: Init mps/rx stat ***/ + ret = mt_engine_init_mps(test_config); + if (ret) + goto err; + + /*** Step5: Disable rmac and configure rx filter ***/ + ret = ops->op_set_tr_mac( + winfos, SERV_TEST_MAC_RX, FALSE, band_idx); + if (ret) + goto err; + + /* Rx filter */ + sys_ad_zero_mem(&rx_filter, sizeof(rx_filter)); + rx_filter.bPromiscuous = FALSE; + rx_filter.bFrameReport = TRUE; + rx_filter.filterMask = SERV_RX_FILTER_NDPA + | SERV_RX_FILTER_NOT_OWN_BTIM + | SERV_RX_FILTER_NOT_OWN_UCAST + | SERV_RX_FILTER_RTS + | SERV_RX_FILTER_CTS + | SERV_RX_FILTER_CTRL_RSV + | SERV_RX_FILTER_BC_MC_DIFF_BSSID_A2 + | SERV_RX_FILTER_BC_MC_DIFF_BSSID_A3 + | SERV_RX_FILTER_BC_MC_OWN_MAC_A3 + | SERV_RX_FILTER_PROTOCOL_VERSION + | SERV_RX_FILTER_FCS_ERROR; + rx_filter.u1BandIdx = band_idx; + ret = ops->op_set_rx_filter(winfos, rx_filter); + if (ret) + goto err; + } + + /*** Step6: Init tx thread ***/ + ret = net_ad_init_thread(winfos, configs, SERV_THREAD_TEST); + if (ret) + goto err; + + /*** Step7: Stop normal function ***/ + ret = net_ad_exit_normal(winfos, bak); + if (ret) + goto err; + + for (band_idx = TEST_DBDC_BAND0; + band_idx < TEST_DBDC_BAND_NUM; band_idx++) { + test_config = &configs[band_idx]; + sys_ad_zero_mem(&test_config->stack, + sizeof(test_config->stack)); + + /*** Step8: Set op mode and init wdev/txpwr ***/ + /* call wdev_do_open must be behind ATE status set */ + /* call wdev_do_open must be after mt_adaption_stop_ap */ + test_config->op_mode = OP_MODE_START; + ret = net_ad_init_wdev(winfos, test_config, band_idx); + if (ret) + goto err; + + /* Init tx power feature */ + ret = net_ad_init_txpwr(winfos, test_config, band_idx); + if (ret) + goto err; + + if (winfos->dbdc_mode) + test_config->stack.entry_limit = MAX_MULTI_TX_STA/2; + else + test_config->stack.entry_limit = MAX_MULTI_TX_STA; + + test_config->is_alloc_skb = 0; + + sys_ad_zero_mem(test_config->tx_method, + sizeof(u_int8)*TEST_MODE_NUM); + test_config->tx_method[TEST_MODE_HE_MU] = 1; + test_config->tx_method[TEST_MODE_VHT_MIMO] = 1; + test_config->max_pkt_ext = 2; + test_config->hetb_rx_csd = 0x240004000060FF; + } + + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("%s: enter test mode, wdev_idx=%u\n", + __func__, test_config->wdev_idx)); + +done: + return ret; + +err: + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("%s: enter test mode fail, err=0x%8x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_engine_stop( + struct test_wlan_info *winfos, + struct test_backup_params *bak, + struct test_configuration *configs, + struct test_operation *ops, + struct test_bk_cr *bks) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct test_configuration *test_config; + void **pkt_skb = NULL; + /* TODO: factor out here for rx_filter data struct */ + struct rx_filter_ctrl rx_filter; + u_char band_idx; + u_int16 rsp_len = 8; + u_int8 icap_len = 0; + + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_TRACE, ("%s\n", __func__)); + + for (band_idx = TEST_DBDC_BAND0; + band_idx < TEST_DBDC_BAND_NUM; band_idx++) { + test_config = &configs[band_idx]; + + /*** Step1: Sanity check ***/ + if ((test_config->op_mode & OP_MODE_STOP) + || !(test_config->op_mode & OP_MODE_START)) { + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_WARN, + ("%s: test mode has already stopped, ", + __func__)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_WARN, + ("wdev_idx=%u, band_idx=%u\n", + test_config->wdev_idx, band_idx)); + + test_config->op_mode = OP_MODE_STOP; + + goto done; + } + + /*** Step2: Restore CRs for normal mode ***/ + ret = ops->op_restore_cr(winfos, bks, band_idx); + if (ret) + goto err; + + /*** Step3: Remind FW that switch mode ***/ + /* + * TODO: factor out here for rf test mode + * duplicated behavior reviewing + */ + if (test_config->op_mode & OP_MODE_FFT) { + + ret = ops->op_set_rf_test_mode(winfos, + fTEST_OPER_NORMAL_MODE, + icap_len, + rsp_len); + + /* For FW to switch back to normal mode stable time */ + /* mdelay(2000); */ + if (ret) + goto err; + + test_config->op_mode &= ~OP_MODE_FFT; + } + + if (test_config->op_mode & fTEST_IN_RFTEST) { + + ret = ops->op_set_rf_test_mode(winfos, + fTEST_OPER_NORMAL_MODE, + icap_len, + rsp_len); + + /* For FW to switch back to normal mode stable time */ + /* mdelay(2000); */ + if (ret) + goto err; + + test_config->op_mode &= ~fTEST_IN_RFTEST; + } + + /*** Step4: Configure rx filter ***/ + sys_ad_zero_mem(&rx_filter, sizeof(rx_filter)); + rx_filter.bPromiscuous = FALSE; + rx_filter.bFrameReport = FALSE; + rx_filter.filterMask = SERV_RX_FILTER_NDPA + | SERV_RX_FILTER_NOT_OWN_BTIM + | SERV_RX_FILTER_NOT_OWN_UCAST + | SERV_RX_FILTER_RTS + | SERV_RX_FILTER_CTS + | SERV_RX_FILTER_CTRL_RSV + | SERV_RX_FILTER_BC_MC_DIFF_BSSID_A2 + | SERV_RX_FILTER_BC_MC_DIFF_BSSID_A3 + | SERV_RX_FILTER_BC_MC_OWN_MAC_A3 + | SERV_RX_FILTER_PROTOCOL_VERSION + | SERV_RX_FILTER_FCS_ERROR; + rx_filter.u1BandIdx = band_idx; + ret = ops->op_set_rx_filter(winfos, rx_filter); + if (ret) + goto err; + + /*** Step5: Release mps/skb ***/ + ret = mt_engine_release_mps(test_config); + if (ret) + goto err; + + /* Release skb */ + pkt_skb = &test_config->pkt_skb; + + if (*pkt_skb) { + sys_ad_free_pkt(*pkt_skb); + *pkt_skb = NULL; + } + + /*** Step6: Release wdev and set op mode ***/ + /* call wdev_do_close must be before mt_adaption_startup_ap */ + ret = net_ad_release_wdev(winfos, test_config); + if (ret) + goto err; + + test_config->op_mode = OP_MODE_STOP; + + /*** Step7: Remind FW that disable test mode ***/ + ret = ops->op_set_fw_mode(winfos, 0); + if (ret) + goto err; + + /*** Step8: Enable tmac/rmac/rxv ***/ + ret = ops->op_set_tr_mac( + winfos, SERV_TEST_MAC_TXRX, TRUE, band_idx); + if (ret) + goto err; + } + + /*** Step9: resume normal function ***/ + ret = net_ad_enter_normal(winfos, bak); + if (ret) + goto err; + + /*** Step10: Release tx thread ***/ + ret = net_ad_release_thread(0); + /* msleep(2); */ + if (ret) + goto err; + + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("%s: leave test mode, wdev_idx=%u\n", + __func__, test_config->wdev_idx)); + +done: + return ret; + +err: + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("%s: leave test mode fail, err=0x%8x\n", __func__, ret)); + + test_config->op_mode = OP_MODE_STOP; + + return ret; +} + +s_int32 mt_engine_calc_ipg_param_by_ipg( + struct test_configuration *configs) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct ipg_param *ipg_param; + u_char tx_mode; + u_int32 ipg, real_ipg; + u_int8 sig_ext, aifsn; + u_int16 slot_time, sifs_time, cw; + + ipg_param = &configs->ipg_param; + tx_mode = configs->tx_mode; + ipg = ipg_param->ipg; + sig_ext = mt_engine_get_sigext_time_by_phymode(tx_mode); + slot_time = mt_engine_get_slot_time_by_phymode(tx_mode); + sifs_time = TEST_DEFAULT_SIFS_TIME; + + /* + * 1. ipg = sig_ext + sifs_time + slot_time + * 2. ipg = sig_ext + sifs_time + aifsn * slot_time + * + ((1 << cw) - 1) * slot_time + * If it's CCK mode, there's no need to consider sig_ext + * And it's no need to count in backoff time in older design + * Configure SIFS/SLOT only + * Consider which ac queue will be used each case + */ + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("%s: expected ipg=%d\n", __func__, ipg)); + + if (ipg < (sig_ext + sifs_time + slot_time)) { + ipg_param->ipg = 0; + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("%s: invalid ipg!! ", __func__)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("sig_ext/slot_time/sifs_time=%d/%d/%d, ", + sig_ext, slot_time, sifs_time)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("set ipg=%d\n", ipg)); + + if (configs->duty_cycle > 0) { + configs->duty_cycle = 0; + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("%s: invalid ipg!! ", __func__)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("set duty_cycle=%d\n", configs->duty_cycle)); + } + + return ret; + } + + ipg -= sig_ext; + + if (ipg <= (TEST_MAX_SIFS_TIME + slot_time)) { + sifs_time = ipg - slot_time; + aifsn = TEST_MIN_AIFSN; + cw = 0; + } else { + cw = mt_engine_get_cw(ipg, slot_time); + ipg -= ((1 << cw) - 1) * slot_time; + aifsn = ipg / slot_time; + + if (aifsn >= TEST_MAX_AIFSN) + aifsn = TEST_MAX_AIFSN; + + ipg -= aifsn * slot_time; + + if (ipg <= TEST_DEFAULT_SIFS_TIME) + sifs_time = TEST_DEFAULT_SIFS_TIME; + else if ((ipg > TEST_DEFAULT_SIFS_TIME) && + (ipg <= TEST_MAX_SIFS_TIME)) + sifs_time = ipg; + else + sifs_time = TEST_MAX_SIFS_TIME; + } + + real_ipg = sig_ext + sifs_time + aifsn * slot_time + + ((1 << cw) - 1) * slot_time; + + ipg_param->sig_ext = sig_ext; + ipg_param->slot_time = slot_time; + ipg_param->sifs_time = sifs_time; + ipg_param->aifsn = aifsn; + ipg_param->cw = cw; + ipg_param->txop = 0; + + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("%s: sig_ext=%d, slot_time=%d, sifs_time=%d, ", + __func__, sig_ext, slot_time, sifs_time)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("aifsn=%d, cw=%d, ", aifsn, cw)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("real ipg=%d\n", real_ipg)); + + return ret; +} + +s_int32 mt_engine_set_auto_resp( + struct test_wlan_info *winfos, + struct test_configuration *configs, + u_char band_idx, u_char mode) +{ + return net_ad_set_auto_resp(winfos, configs, band_idx, mode); +} + +s_int32 mt_engine_start_tx( + struct test_wlan_info *winfos, + struct test_configuration *configs, + struct test_operation *ops, + u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + struct ipg_param *ipg_param; + struct tx_time_param *tx_time_param; + struct test_tx_stack *stack = NULL; + u_int32 op_mode, tx_cnt, mcs, duty_cycle, ipg, pkt_tx_time; + u_char *test_pkt, stack_idx = 0; + u_char ctrl_ch, ch, bw; + + ipg_param = &configs->ipg_param; + tx_time_param = &configs->tx_time_param; + op_mode = configs->op_mode; + tx_cnt = configs->tx_stat.tx_cnt; + mcs = configs->mcs; + duty_cycle = configs->duty_cycle; + test_pkt = configs->test_pkt; + ctrl_ch = configs->ctrl_ch; + stack = &configs->stack; + ch = configs->channel; + bw = configs->bw; + + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("%s: band_idx=%u, ch=%u, ctrl_ch=%u, wdev_idx=%u\n", + __func__, band_idx, ch, ctrl_ch, configs->wdev_idx)); + + if (!test_pkt) { + ret = SERV_STATUS_ENGINE_INVALID_NULL_POINTER; + goto err; + } + + if (op_mode & OP_MODE_TXFRAME) { + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_WARN, + ("%s: already in TXFRAME mode now, tx is ongoing!\n", + __func__)); + goto done; + } + + /* Turn on tx again if set before */ + if (op_mode & OP_MODE_TXFRAME) { + ret = ops->op_set_tr_mac( + winfos, SERV_TEST_MAC_TX, FALSE, band_idx); + if (ret) + goto err; + } + + ret = ops->op_set_tr_mac( + winfos, SERV_TEST_MAC_RX_RXV, FALSE, band_idx); + if (ret) + goto err; + + if (configs->tx_mode == TEST_MODE_HE_TB) + ops->op_hetb_ctrl(winfos, band_idx, OP_HETB_TX_CFG, + TRUE, configs->per_pkt_bw, configs->sgi, + configs->stbc, configs->dmnt_ru_idx, + &configs->ru_info_list[0]); + + /* Stop tx/rx path queues */ + ret = net_ad_cfg_queue(winfos, FALSE); + + /* NOTE: here needs to polling tx/rx path until packets empty */ + + /* Start tx/rx path queues */ + ret = net_ad_cfg_queue(winfos, TRUE); + + /* Apply ipg setting to HW */ + ret = mt_engine_apply_ipg_param(winfos, configs, ops, band_idx); + if (ret) + goto err; + + if (tx_cnt != 0xFFFFFFFF) { + if (configs->tx_strategy != TEST_TX_STRA_THREAD) + tx_cnt += configs->tx_stat.tx_done_cnt; + + /* work aound to prevent refill flow interrupted */ + if (configs->tx_mode == TEST_MODE_HE_MU && configs->retry) + tx_cnt = 1; + + configs->tx_stat.tx_cnt = tx_cnt; + } + + /* Tx frame */ + op_mode |= OP_MODE_TXFRAME; + configs->op_mode = op_mode; + ipg = ipg_param->ipg; + pkt_tx_time = tx_time_param->pkt_tx_time; + + if ((pkt_tx_time > 0) || (ipg > 0)) { + u_int32 pkt_cnt, input_cnt; + u_int32 round = configs->tx_stat.tx_cnt; + u_int32 rounded = configs->tx_stat.txed_cnt; + u_int32 ampdu_cnt = tx_time_param->pkt_ampdu_cnt; + u_int32 token_limit = winfos->pkt_tx_tkid_max / 2; + + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("%s: repeat=0x%x, pkt_ampdu_cnt=%d, ", + __func__, round, ampdu_cnt)); + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_OFF, + ("token_limit=%d, pkt_tx_time=%d, ipg=%d\n", + token_limit, pkt_tx_time, ipg)); + + input_cnt = round*ampdu_cnt*stack->index; + input_cnt = input_cnt > token_limit ? token_limit : input_cnt; + + /* Enqueue packet in HW queue in advance */ + for (pkt_cnt = 0; + pkt_cnt < input_cnt; + pkt_cnt += configs->stack.index) { + for (stack_idx = 0; + stack_idx < configs->stack.index; + stack_idx++) + net_ad_enq_pkt(winfos, + configs->ac_idx, + stack->virtual_wtbl[stack_idx], + stack->virtual_device[stack_idx], + stack->pkt_skb[stack_idx]); + + rounded++; + } + + configs->stack.q_idx = 0; + configs->tx_stat.txed_cnt = rounded; + } + + /* workaround to prevent: + * 1.packet of primary RU dropped then queue length mismatched + * 2.packets stay at PLE after TxStop + */ + if (configs->tx_mode == TEST_MODE_HE_MU || + configs->tx_mode == TEST_MODE_VHT_MIMO) + net_ad_enq_pkt(winfos, + configs->ac_idx, + stack->virtual_wtbl[0], + stack->virtual_device[0], + stack->pkt_skb[0]); + + if (configs->tx_mode == TEST_MODE_HE_TB) + ops->op_hetb_ctrl(winfos, band_idx, OP_HETB_TX_START, + TRUE, 0, 0, 0, 0, NULL); + + ret = net_ad_trigger_tx(winfos, + configs, + band_idx, + NULL); + if (ret) + goto err; + + ret = ops->op_set_tr_mac(winfos, SERV_TEST_MAC_TX, TRUE, band_idx); + if (ret) + goto err; + + if (op_mode & OP_MODE_RXFRAME) { + ret = ops->op_set_tr_mac( + winfos, SERV_TEST_MAC_RX_RXV, TRUE, band_idx); + if (ret) + goto err; + } + +done: + return ret; +err: + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x, wdev_idx=%x\n", + __func__, ret, configs->wdev_idx)); + + return ret; +} + +s_int32 mt_engine_stop_tx( + struct test_wlan_info *winfos, + struct test_configuration *configs, + struct test_operation *ops, + u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_int32 op_mode, ipg, pkt_tx_time; + struct ipg_param *ipg_param; + struct tx_time_param *tx_time_param; + + ipg_param = &configs->ipg_param; + tx_time_param = &configs->tx_time_param; + op_mode = configs->op_mode; + ipg = ipg_param->ipg; + pkt_tx_time = tx_time_param->pkt_tx_time; + + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_TRACE, + ("%s: band_idx=%u\n", __func__, band_idx)); + + configs->tx_stat.txed_cnt = 0; + +#ifdef ATE_TXTHREAD + net_ad_thread_stop_tx(winfos); +#endif + + if ((op_mode & OP_MODE_TXFRAME) || (op_mode == OP_MODE_STOP)) { + op_mode &= ~OP_MODE_TXFRAME; + configs->op_mode = op_mode; + + ret = ops->op_set_tr_mac( + winfos, SERV_TEST_MAC_TX, FALSE, band_idx); + if (ret) + goto err; + + if ((pkt_tx_time > 0) || (ipg > 0)) { + u_char omac_idx = 0; + /* Flush SW queue */ + ret = net_ad_clean_sta_q(winfos, SERV_WCID_ALL); + if (ret) + return ret; + + ret = net_ad_get_omac_idx( + winfos, + configs->stack.virtual_device[0], + &omac_idx); + if (ret != SERV_STATUS_SUCCESS) + goto err; + + /* + * Clean per sta tx queue and disable STA pause CRs + * for transmitting packet + */ + ret = ops->op_set_clean_persta_txq( + winfos, FALSE, omac_idx, band_idx); + if (ret != SERV_STATUS_SUCCESS) + goto err; + } + } + + if (configs->tx_mode == TEST_MODE_HE_TB) + ops->op_hetb_ctrl(winfos, band_idx, OP_HETB_TX_STOP, + TRUE, 0, 0, 0, 0, NULL); + +err: + return ret; +} + +s_int32 mt_engine_start_rx( + struct test_wlan_info *winfos, + struct test_configuration *configs, + struct test_operation *ops, + u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_int32 op_mode; + + op_mode = configs->op_mode; + if (op_mode & OP_MODE_RXFRAME) { + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_WARN, + ("%s: already in RXFRAME mode now, rx is ongoing!\n", + __func__)); + goto done; + } + + /* Turn off tx if set before */ + if (op_mode & OP_MODE_TXFRAME) { + ret = ops->op_set_tr_mac( + winfos, SERV_TEST_MAC_TX, FALSE, band_idx); + if (ret) + goto err; + } + + ret = ops->op_set_tr_mac( + winfos, SERV_TEST_MAC_RX_RXV, FALSE, band_idx); + if (ret) + goto err; + + /* Stop tx/rx path queues */ + ret = net_ad_cfg_queue(winfos, FALSE); + + /* NOTE: here needs to polling tx/rx path until packets empty */ + + /* Start tx/rx path queues */ + ret = net_ad_cfg_queue(winfos, TRUE); + + /* Turn on tx again if set before */ + if (op_mode & OP_MODE_TXFRAME) { + ret = ops->op_set_tr_mac( + winfos, SERV_TEST_MAC_TX, TRUE, band_idx); + if (ret) + goto err; + } + + ret = ops->op_set_tr_mac( + winfos, SERV_TEST_MAC_RX_RXV, TRUE, band_idx); + if (ret) + goto err; + + ret = ops->op_set_phy_counter(winfos, 0, TEST_DBDC_BAND0); + if (ret) + goto err; + + ret = ops->op_set_phy_counter(winfos, 1, TEST_DBDC_BAND0); + if (ret) + goto err; + + if (IS_TEST_DBDC(winfos)) { + ret = ops->op_set_phy_counter(winfos, 0, TEST_DBDC_BAND1); + if (ret) + goto err; + + ret = ops->op_set_phy_counter(winfos, 1, TEST_DBDC_BAND1); + if (ret) + goto err; + } + + op_mode |= OP_MODE_RXFRAME; + configs->op_mode = op_mode; + + if (configs->tx_mode == TEST_MODE_HE_TB) { + u_int8 sta_idx = 0; + struct test_ru_info *ru_info = &configs->ru_info_list[0]; + + for (sta_idx = 0 ; sta_idx < MAX_MULTI_TX_STA ; sta_idx++) { + if (ru_info[sta_idx].valid) { + /* 13 bytes for Delimiter+FCS+A_control+HW reserved */ + mt_engine_calc_phy(&ru_info[sta_idx], + ru_info[sta_idx].mpdu_length+13, + configs->stbc, + configs->sgi, + configs->max_pkt_ext*2); + } + } + if (mt_engine_search_dom_ru(configs) == NULL) { + ret = SERV_STATUS_ENGINE_FAIL; + goto err; + } + + ops->op_hetb_ctrl(winfos, band_idx, OP_HETB_RX_CFG, + TRUE, configs->per_pkt_bw, configs->sgi, + configs->stbc, configs->dmnt_ru_idx, + &configs->ru_info_list[0]); + } else if (configs->tx_mode == TEST_MODE_HE_MU) { + if (configs->mu_rx_aid) + ops->op_set_ru_aid(winfos, band_idx, + configs->mu_rx_aid); + else { + /* 0xf800 to disable */ + ops->op_set_ru_aid(winfos, band_idx, 0xf800); + } + } + +done: + return ret; + +err: + SERV_LOG(SERV_DBG_CAT_ENGN, SERV_DBG_LVL_ERROR, + ("%s: err=0x%08x\n", __func__, ret)); + + return ret; +} + +s_int32 mt_engine_stop_rx( + struct test_wlan_info *winfos, + struct test_configuration *configs, + struct test_operation *ops, + u_char band_idx) +{ + s_int32 ret = SERV_STATUS_SUCCESS; + u_int32 op_mode; + + op_mode = configs->op_mode; + + ret = ops->op_set_tr_mac( + winfos, SERV_TEST_MAC_RX_RXV, FALSE, band_idx); + + op_mode &= ~OP_MODE_RXFRAME; + configs->op_mode = op_mode; + + if (configs->tx_mode == TEST_MODE_HE_TB) { + ops->op_hetb_ctrl(winfos, band_idx, OP_HETB_RX_CFG, + FALSE, configs->per_pkt_bw, configs->sgi, + configs->stbc, configs->dmnt_ru_idx, + &configs->ru_info_list[0]); + } else if (configs->tx_mode == TEST_MODE_HE_MU) { + /* 0xf800 to disable */ + ops->op_set_ru_aid(winfos, band_idx, 0xf800); + } + + return ret; +} From 717013ce910f536035505cf97e267bb2e04243dd Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 22:08:39 +0800 Subject: [PATCH 19/32] Add files via upload --- .../wlan/core/gen4m/mgmt/aaa_fsm.c | 1716 ++++ .../wlan/core/gen4m/mgmt/ais_fsm.c | 7068 ++++++++++++++++ .../wlan/core/gen4m/mgmt/ap_selection.c | 1368 ++++ .../connectivity/wlan/core/gen4m/mgmt/assoc.c | 2127 +++++ .../connectivity/wlan/core/gen4m/mgmt/auth.c | 1383 ++++ .../connectivity/wlan/core/gen4m/mgmt/bss.c | 2588 ++++++ .../connectivity/wlan/core/gen4m/mgmt/cnm.c | 4359 ++++++++++ .../wlan/core/gen4m/mgmt/cnm_mem.c | 1864 +++++ .../wlan/core/gen4m/mgmt/cnm_timer.c | 712 ++ .../connectivity/wlan/core/gen4m/mgmt/he_ie.c | 104 + .../wlan/core/gen4m/mgmt/he_rlm.c | 1213 +++ .../wlan/core/gen4m/mgmt/hem_mbox.c | 643 ++ .../connectivity/wlan/core/gen4m/mgmt/hs20.c | 601 ++ .../connectivity/wlan/core/gen4m/mgmt/mddp.c | 832 ++ .../connectivity/wlan/core/gen4m/mgmt/mib.c | 138 + .../wlan/core/gen4m/mgmt/p2p_assoc.c | 143 + .../wlan/core/gen4m/mgmt/p2p_bss.c | 109 + .../wlan/core/gen4m/mgmt/p2p_dev_fsm.c | 1446 ++++ .../wlan/core/gen4m/mgmt/p2p_dev_state.c | 424 + .../wlan/core/gen4m/mgmt/p2p_fsm.c | 472 ++ .../wlan/core/gen4m/mgmt/p2p_func.c | 7190 +++++++++++++++++ .../wlan/core/gen4m/mgmt/p2p_ie.c | 238 + .../wlan/core/gen4m/mgmt/p2p_rlm.c | 1399 ++++ .../wlan/core/gen4m/mgmt/p2p_rlm_obss.c | 396 + .../wlan/core/gen4m/mgmt/p2p_role_fsm.c | 4123 ++++++++++ .../wlan/core/gen4m/mgmt/p2p_role_state.c | 744 ++ .../wlan/core/gen4m/mgmt/p2p_scan.c | 348 + .../wlan/core/gen4m/mgmt/privacy.c | 1445 ++++ .../wlan/core/gen4m/mgmt/qosmap.c | 281 + .../connectivity/wlan/core/gen4m/mgmt/rate.c | 364 + .../wlan/core/gen4m/mgmt/reg_rule.c | 336 + .../connectivity/wlan/core/gen4m/mgmt/rlm.c | 6588 +++++++++++++++ .../wlan/core/gen4m/mgmt/rlm_domain.c | 5555 +++++++++++++ .../wlan/core/gen4m/mgmt/rlm_obss.c | 402 + .../wlan/core/gen4m/mgmt/rlm_protection.c | 105 + .../wlan/core/gen4m/mgmt/roaming_fsm.c | 816 ++ .../connectivity/wlan/core/gen4m/mgmt/rrm.c | 1667 ++++ .../connectivity/wlan/core/gen4m/mgmt/rsn.c | 3709 +++++++++ .../wlan/core/gen4m/mgmt/saa_fsm.c | 2182 +++++ .../connectivity/wlan/core/gen4m/mgmt/scan.c | 4296 ++++++++++ .../wlan/core/gen4m/mgmt/scan_cache.c | 289 + .../wlan/core/gen4m/mgmt/scan_fsm.c | 1350 ++++ .../connectivity/wlan/core/gen4m/mgmt/stats.c | 809 ++ .../connectivity/wlan/core/gen4m/mgmt/swcr.c | 1470 ++++ .../connectivity/wlan/core/gen4m/mgmt/tdls.c | 1636 ++++ .../wlan/core/gen4m/mgmt/tkip_mic.c | 571 ++ .../connectivity/wlan/core/gen4m/mgmt/twt.c | 597 ++ .../wlan/core/gen4m/mgmt/twt_planner.c | 1382 ++++ .../wlan/core/gen4m/mgmt/twt_req_fsm.c | 669 ++ .../connectivity/wlan/core/gen4m/mgmt/wapi.c | 484 ++ .../connectivity/wlan/core/gen4m/mgmt/wmm.c | 1880 +++++ .../connectivity/wlan/core/gen4m/mgmt/wnm.c | 651 ++ 52 files changed, 83282 insertions(+) create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/aaa_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/ais_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/ap_selection.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/assoc.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/auth.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/bss.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/cnm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/cnm_mem.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/cnm_timer.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/he_ie.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/he_rlm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/hem_mbox.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/hs20.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/mddp.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/mib.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_assoc.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_bss.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_dev_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_dev_state.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_func.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_ie.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_rlm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_rlm_obss.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_role_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_role_state.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_scan.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/privacy.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/qosmap.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rate.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/reg_rule.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rlm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rlm_domain.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rlm_obss.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rlm_protection.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/roaming_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rrm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rsn.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/saa_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/scan.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/scan_cache.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/scan_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/stats.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/swcr.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/tdls.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/tkip_mic.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/twt.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/twt_planner.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/twt_req_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/wapi.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/wmm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/wnm.c diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/aaa_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/aaa_fsm.c new file mode 100644 index 0000000000000..aece2256619b4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/aaa_fsm.c @@ -0,0 +1,1716 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/aaa_fsm.c#3 $ + */ + +/*! \file "aaa_fsm.c" + * \brief This file defines the FSM for AAA MODULE. + * + * This file defines the FSM for AAA MODULE. + */ + +/****************************************************************************** + * C O M P I L E 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t aaaFsmSendEventJoinComplete(uint32_t rJoinStatus, + struct STA_RECORD *prStaRec, struct SW_RFB *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, + (struct MSG_HDR *) 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 struct MSG_HDR *prMsgHdr) +{ + P_MSG_SAA_JOIN_REQ_T prJoinReqMsg; + struct STA_RECORD *prStaRec; + struct BSS_INFO *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 = (struct IE_CHALLENGE_TEXT *) NULL; + } + + cnmTimerStopTimer(&prStaRec->rTxReqDoneOrRxRespTimer); + + prStaRec->ucStaState = STA_STATE_1; + + /* Trigger SAA MODULE */ + saaFsmSteps(prStaRec, SAA_STATE_SEND_AUTH1, (struct SW_RFB *) NULL); +} /* end of saaFsmRunEventStart() */ +#endif + +#if CFG_SUPPORT_AAA + +void aaaFsmRunEventTxReqTimeOut(IN struct ADAPTER *prAdapter, + IN unsigned long plParamPtr) +{ + struct STA_RECORD *prStaRec = (struct STA_RECORD *) plParamPtr; + struct BSS_INFO *prBssInfo; + + if (!prStaRec) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + DBGLOG(AAA, LOUD, + "EVENT-TIMER: TX REQ TIMEOUT, Current Time = %d\n", + kalGetTimeTick()); + + /* Trigger statistics log if Auth/Assoc Tx timeout */ + wlanTriggerStatsLog(prAdapter, prAdapter->rWifiVar.u4StatsLogDuration); + + switch (prStaRec->eAuthAssocState) { + case AAA_STATE_SEND_AUTH2: + DBGLOG(AAA, ERROR, + "LOST EVENT ,Auth Tx done disappear for (%d)Ms\n", + TU_TO_MSEC(TX_AUTHENTICATION_RESPONSE_TIMEOUT_TU)); + + prStaRec->eAuthAssocState = AA_STATE_IDLE; + + /* NOTE(Kevin): Change to STATE_1 */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + +#if CFG_ENABLE_WIFI_DIRECT + if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) + p2pRoleFsmRunEventAAATxFail(prAdapter, + prStaRec, prBssInfo); +#endif /* CFG_ENABLE_WIFI_DIRECT */ + break; +#if 0 + /*state 2 to state 3 only check Assoc_req valid, no need for time out + *the fail case already handle at aaaFsmRunEventRxAssoc + */ + case AAA_STATE_SEND_ASSOC2: + DBGLOG(AAA, ERROR, + "LOST EVENT ,Assoc Tx done disappear for (%d)Ms\n", + TU_TO_MSEC(TX_AUTHENTICATION_RESPONSE_TIMEOUT_TU)); + + + prStaRec->eAuthAssocState = AAA_STATE_SEND_AUTH2; + + /* NOTE(Kevin): Change to STATE_2 */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + +#if CFG_ENABLE_WIFI_DIRECT + if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) + p2pRoleFsmRunEventAAATxFail(prAdapter, + prStaRec, prBssInfo); +#endif /* CFG_ENABLE_WIFI_DIRECT */ + break; +#endif + + default: + return; + } + + +} /* end of saaFsmRunEventTxReqTimeOut() */ + + + + + +/*---------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + uint16_t u2StatusCode; + u_int8_t fgReplyAuth = FALSE; + struct WLAN_AUTH_FRAME *prAuthFrame = (struct WLAN_AUTH_FRAME *) NULL; + + ASSERT(prAdapter); + + do { + prAuthFrame = (struct WLAN_AUTH_FRAME *) prSwRfb->pvHeader; + + DBGLOG(AAA, INFO, + "SA: " MACSTR ", bssid: " MACSTR ", %d %d sta: %d\n", + MAC2STR(prAuthFrame->aucSrcAddr), + MAC2STR(prAuthFrame->aucBSSID), + prAuthFrame->u2AuthTransSeqNo, + prAuthFrame->u2AuthAlgNum, + prSwRfb->ucStaRecIdx); + +#if CFG_ENABLE_WIFI_DIRECT + prBssInfo = p2pFuncBSSIDFindBssInfo(prAdapter, + prAuthFrame->aucBSSID); + + /* 4 <1> Check P2P network conditions */ + + /* if (prBssInfo && prAdapter->fgIsP2PRegistered) */ + /* modify coding sytle to reduce indent */ + + if (!prAdapter->fgIsP2PRegistered) + goto bow_proc; + + if (prBssInfo && prBssInfo->fgIsNetActive) { + + /* 4 <1.1> Validate Auth Frame + * by Auth Algorithm/Transation Seq + */ + if (WLAN_STATUS_SUCCESS == + authProcessRxAuthFrame(prAdapter, + prSwRfb, + prBssInfo, + &u2StatusCode)) { + + if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + DBGLOG(AAA, TRACE, + "process RxAuth status success\n"); + /* 4 <1.2> Validate Auth Frame + * for Network Specific Conditions + */ + fgReplyAuth = p2pFuncValidateAuth( + prAdapter, + prBssInfo, + prSwRfb, + &prStaRec, + &u2StatusCode); + +#if CFG_SUPPORT_802_11W + if (prBssInfo->u4RsnSelectedAKMSuite == + RSN_AKM_SUITE_SAE) + break; + + /* AP PMF, if PMF connection, + * ignore Rx auth + */ + /* Certification 4.3.3.4 */ + if (rsnCheckBipKeyInstalled(prAdapter, + prStaRec)) { + DBGLOG(AAA, INFO, + "Drop RxAuth\n"); + return; + } +#endif + } else { + fgReplyAuth = TRUE; + } + break; + } + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +bow_proc: + + /* 4 <2> Check BOW network conditions */ +#if CFG_ENABLE_BT_OVER_WIFI + { + struct BOW_FSM_INFO *prBowFsmInfo = + (struct BOW_FSM_INFO *) NULL; + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prBowFsmInfo->ucBssIndex); + + if ((prBssInfo->fgIsNetActive) + && (prBssInfo->eCurrentOPMode == OP_MODE_BOW)) { + + /* 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 (u2StatusCode + == STATUS_CODE_SUCCESSFUL) { + + /* 4 <2.2> Validate Auth Frame + * for Network Specific + * Conditions + */ + fgReplyAuth = + bowValidateAuth(prAdapter, + prSwRfb, + &prStaRec, + &u2StatusCode); + + } else { + + fgReplyAuth = TRUE; + } + /* TODO(Kevin): Allocate a STA_RECORD_T + * for new client + */ + break; + } + } + } +#endif /* CFG_ENABLE_BT_OVER_WIFI */ + + return; + } while (FALSE); + + if (prStaRec) { + /* update RCPI */ + ASSERT(prSwRfb->prRxStatusGroup3); + prStaRec->ucRCPI = nicRxGetRcpiValueFromRxv( + prAdapter, + RCPI_MODE_MAX, + prSwRfb); + } + /* 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 = prAuthFrame->u2AuthAlgNum; + } else { + /* NOTE(Kevin): We should have STA_RECORD_T + * if the status code was successful + */ + ASSERT(!(u2StatusCode == STATUS_CODE_SUCCESSFUL)); + } + + if (prBssInfo->u4RsnSelectedAKMSuite == + RSN_AKM_SUITE_SAE) { + kalP2PIndicateRxMgmtFrame( + prAdapter->prGlueInfo, + prSwRfb, + FALSE, + (uint8_t)prBssInfo->u4PrivateData); + DBGLOG(AAA, INFO, "Forward RxAuth\n"); + return; + } + + /* NOTE: Ignore the return status for AAA */ + /* 4 <4> Reply Auth */ + authSendAuthFrame(prAdapter, + prStaRec, + prBssInfo->ucBssIndex, + prSwRfb, + AUTH_TRANSACTION_SEQ_2, + u2StatusCode); + + + /*sta_rec might be removed + * when client list full, skip timer setting + */ + /* + * check if prStaRec valid as authSendAuthFrame may free + * StaRec when TX resource is not enough + */ + if (prStaRec && prStaRec->fgIsInUse) { + cnmTimerStopTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer); + /*ToDo:Init Timer to check get + * Auth Txdone avoid sta_rec not clear + */ + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC) + aaaFsmRunEventTxReqTimeOut, + (unsigned long) prStaRec); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC( + TX_AUTHENTICATION_RESPONSE_TIMEOUT_TU)); + } + + + + } else if (prStaRec) + cnmStaRecFree(prAdapter, prStaRec); +} /* 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 + */ +/*---------------------------------------------------------------------------*/ +uint32_t aaaFsmRunEventRxAssoc(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + uint16_t u2StatusCode = STATUS_CODE_RESERVED; + u_int8_t fgReplyAssocResp = FALSE; + u_int8_t fgSendSAQ = FALSE; + struct WLAN_ASSOC_REQ_FRAME *prAssocReqFrame = + (struct WLAN_ASSOC_REQ_FRAME *) NULL; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + do { + prAssocReqFrame = + (struct WLAN_ASSOC_REQ_FRAME *) prSwRfb->pvHeader; + + /* 4 <1> Check if we have the STA_RECORD_T + * for incoming Assoc Req + */ + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + /* No Wtbl handling */ + if (!prStaRec) { + secHandleNoWtbl(prAdapter, prSwRfb); + prStaRec = prSwRfb->prStaRec; + } + + /* We should have the corresponding Sta Record. */ + if ((!prStaRec) || (!prStaRec->fgIsInUse)) { + /* Not to reply association response + * with failure code due to lack of STA_REC + */ + DBGLOG(AAA, TRACE, + "get sta fail, wlan idx: %d, sta index: %d\n", + prSwRfb->ucWlanIdx, + prSwRfb->ucStaRecIdx); + break; + } + + DBGLOG(AAA, INFO, + "SA: " MACSTR ", bssid: " MACSTR ", sta idx: %d\n", + MAC2STR(prAssocReqFrame->aucSrcAddr), + MAC2STR(prAssocReqFrame->aucBSSID), + prSwRfb->ucStaRecIdx); + + if (!IS_CLIENT_STA(prStaRec)) { + DBGLOG(AAA, ERROR, + "error sta type, skip process rx assoc\n"); + cnmDumpStaRec(prAdapter, prSwRfb->ucStaRecIdx); + break; + } + + DBGLOG(AAA, TRACE, + "RxAssoc enter ucStaState:%d, eAuthassocState:%d\n", + prStaRec->ucStaState, prStaRec->eAuthAssocState); + + 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); + + /* Maybe Auth Response TX fail, + * but actually it success. + */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + } + + /* update RCPI */ + ASSERT(prSwRfb->prRxStatusGroup3); + prStaRec->ucRCPI = + nicRxGetRcpiValueFromRxv( + prAdapter, RCPI_MODE_MAX, prSwRfb); + + /* 4 <2> Check P2P network conditions */ +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) + && (IS_STA_IN_P2P(prStaRec))) { + + prBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + 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 (u2StatusCode + == STATUS_CODE_SUCCESSFUL) { + /* 4 <2.2> + * Validate Assoc Req Frame + * for Network Specific + * Conditions + */ + fgReplyAssocResp = + p2pFuncValidateAssocReq( + prAdapter, + prSwRfb, + (uint16_t *) + &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_BOW_TYPE(prStaRec)) { + + prBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + if ((prBssInfo->fgIsNetActive) + && (prBssInfo->eCurrentOPMode == OP_MODE_BOW)) { + + /* 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 (u2StatusCode + == STATUS_CODE_SUCCESSFUL) { + + /* 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) { + uint16_t u2IELength; + uint8_t *pucIE; + + cnmTimerStopTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer); + + if ((((struct WLAN_ASSOC_REQ_FRAME *) + (prSwRfb->pvHeader))->u2FrameCtrl & MASK_FRAME_TYPE) == + MAC_FRAME_REASSOC_REQ) { + + u2IELength = prSwRfb->u2PacketLen - + (uint16_t) + OFFSET_OF(struct WLAN_REASSOC_REQ_FRAME, + aucInfoElem[0]); + + pucIE = ((struct WLAN_REASSOC_REQ_FRAME *) + (prSwRfb->pvHeader))->aucInfoElem; + } else { + u2IELength = prSwRfb->u2PacketLen - + (uint16_t) + OFFSET_OF(struct WLAN_ASSOC_REQ_FRAME, + aucInfoElem[0]); + + pucIE = ((struct WLAN_ASSOC_REQ_FRAME *) + (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))) { + prBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + if (p2pRoleFsmRunEventAAAComplete(prAdapter, + prStaRec, prBssInfo) + == WLAN_STATUS_SUCCESS) { + prStaRec->u2AssocId = + bssAssignAssocID(prStaRec); + /* prStaRec->eAuthAssocState + * = AA_STATE_IDLE; + */ + /* NOTE(Kevin): for TX done */ + prStaRec->eAuthAssocState = + AAA_STATE_SEND_ASSOC2; + /* 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; + + /* Invalid Association ID */ + prStaRec->u2AssocId = 0; + + /* If(Re)association fail, + * remove sta record and + * use class error to handle sta + */ + prStaRec->eAuthAssocState = + AA_STATE_IDLE; + + /* 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_BOW_TYPE(prStaRec))) { + /* if (bowRunEventAAAComplete(prAdapter, + * prStaRec) == WLAN_STATUS_SUCCESS) { + */ + prStaRec->u2AssocId = + bssAssignAssocID(prStaRec); + + /* NOTE(Kevin): for TX done */ + prStaRec->eAuthAssocState = + AAA_STATE_SEND_ASSOC2; + + /* NOTE(Kevin): + * Method A: Change to STATE_3 + * before handle TX Done + */ + /* cnmStaRecChangeState(prAdapter, + * prStaRec, STA_STATE_3); + */ + } +#endif + } else { + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + /* don't change state, + * just send assoc resp + * (NO need TX done, TIE + code30) + * and then SAQ + */ + if (u2StatusCode + == STATUS_CODE_ASSOC_REJECTED_TEMPORARILY) { + DBGLOG(AAA, INFO, "AP send SAQ\n"); + fgSendSAQ = TRUE; + } else +#endif + { + /* Invalid Association ID */ + prStaRec->u2AssocId = 0; + + /* If (Re)association fail, remove sta record + * and use class error to handle sta + */ + prStaRec->eAuthAssocState = AA_STATE_IDLE; + /* Remove from client list if it was previously + * associated + */ + if ((prStaRec->ucStaState > STA_STATE_1) && + prAdapter->fgIsP2PRegistered && + (IS_STA_IN_P2P(prStaRec))) { + struct BSS_INFO *prBssInfo = NULL; + + prBssInfo = GET_BSS_INFO_BY_INDEX( + prAdapter, + prStaRec->ucBssIndex); + if (prBssInfo) { + DBGLOG(AAA, INFO, + "Remove client\n"); + bssRemoveClient( + prAdapter, + prBssInfo, + prStaRec); + } + } + + /* 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); + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if (fgSendSAQ) { + /* if PMF connection, and return code 30, send SAQ */ + rsnApStartSaQuery(prAdapter, prStaRec); + } +#endif + + } + + 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 + */ +/*---------------------------------------------------------------------------*/ +uint32_t +aaaFsmRunEventTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + + DBGLOG(AAA, INFO, + "EVENT-TX DONE [status: %d][seq: %d]: Current Time = %d\n", + rTxDoneStatus, + prMsduInfo->ucTxSeqNum, + kalGetTimeTick()); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + /* For the case of replying ERROR STATUS CODE */ + if ((!prStaRec) || (!prStaRec->fgIsInUse)) + return WLAN_STATUS_SUCCESS; + + ASSERT(prStaRec->ucBssIndex <= prAdapter->ucHwBssIdNum); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + DBGLOG(AAA, TRACE, "TxDone ucStaState:%d, eAuthAssocState:%d\n", + prStaRec->ucStaState, prStaRec->eAuthAssocState); + + /* Trigger statistics log if Auth/Assoc Tx failed */ + if (rTxDoneStatus != TX_RESULT_SUCCESS) + wlanTriggerStatsLog(prAdapter, + prAdapter->rWifiVar.u4StatsLogDuration); + + 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; + + cnmTimerStopTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer); + + if (prStaRec->u2StatusCode == STATUS_CODE_SUCCESSFUL) { + if (rTxDoneStatus == TX_RESULT_SUCCESS) { + + /* NOTE(Kevin): + * Change to STATE_2 at TX Done + */ + cnmStaRecChangeState(prAdapter, + prStaRec, STA_STATE_2); + /* Error handle if can not + * complete the ASSOC flow + */ + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC(TX_ASSOCIATE_TIMEOUT_TU)); + } else { + + prStaRec->eAuthAssocState = + AA_STATE_IDLE; + + /* NOTE(Kevin): Change to STATE_1 */ + cnmStaRecChangeState(prAdapter, + prStaRec, STA_STATE_1); + +#if CFG_ENABLE_WIFI_DIRECT + if (prBssInfo->eNetworkType + == NETWORK_TYPE_P2P) + p2pRoleFsmRunEventAAATxFail( + prAdapter, + prStaRec, prBssInfo); +#endif /* CFG_ENABLE_WIFI_DIRECT */ +#if CFG_ENABLE_BT_OVER_WIFI + if (IS_STA_BOW_TYPE(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 (prStaRec->u2StatusCode == STATUS_CODE_SUCCESSFUL) { + if (rTxDoneStatus == TX_RESULT_SUCCESS) { + + prStaRec->eAuthAssocState = + AA_STATE_IDLE; + + /* NOTE(Kevin): + * Change to STATE_3 at TX Done + */ +#if CFG_ENABLE_WIFI_DIRECT + if (prBssInfo->eNetworkType + == NETWORK_TYPE_P2P) + p2pRoleFsmRunEventAAASuccess( + prAdapter, + prStaRec, + prBssInfo); +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +#if CFG_ENABLE_BT_OVER_WIFI + + if (IS_STA_BOW_TYPE(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 (prBssInfo->eNetworkType + == NETWORK_TYPE_P2P) + p2pRoleFsmRunEventAAATxFail( + prAdapter, + prStaRec, + prBssInfo); +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +#if CFG_ENABLE_BT_OVER_WIFI + if (IS_STA_BOW_TYPE(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 AA_STATE_IDLE: + /* 2013-08-27 frog: Do nothing. + * Somtimes we may send Assoc Resp twice. + * (Rx Assoc Req before the first Assoc TX Done) + * The AssocState is changed to IDLE after first TX done. + * Free station record when IDLE is seriously wrong. + */ + /* 2017-01-12 Do nothing only when STA is in state 3 */ + /* Free the StaRec if found any unexpected status */ + if (prStaRec->ucStaState != STA_STATE_3) + cnmStaRecFree(prAdapter, prStaRec); + break; + + default: + break; /* Ignore other cases */ + } + + DBGLOG(AAA, TRACE, "TxDone end ucStaState:%d, eAuthAssocState:%d\n", + prStaRec->ucStaState, prStaRec->eAuthAssocState); + + 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 struct MSG_HDR *prMsgHdr) +{ + P_JOIN_INFO_T prJoinInfo; + struct STA_RECORD *prStaRec; + + DEBUGFUNC("joinFsmRunEventAbort"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + + DBGLOG(JOIN, EVENT, "JOIN EVENT: ABORT\n"); + + /* NOTE(Kevin): when reach here, + * the ARB_STATE should be in ARB_STATE_JOIN. + */ + ASSERT(prJoinInfo->prBssDesc); + + /* 4 <1> Update Flags and Elements of JOIN Module. */ + /* Reset Send Auth/(Re)Assoc Frame Count */ + prJoinInfo->ucTxAuthAssocRetryCount = 0; + + /* Cancel all JOIN relative Timer */ + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rTxRequestTimer); + + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rRxResponseTimer); + + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rJoinTimer); + + /* 4 <2> Update the associated + * STA_RECORD_T during JOIN. + */ + /* Get a Station Record if possible, TA == BSSID for AP */ + prStaRec = staRecGetStaRecordByAddr(prAdapter, + prJoinInfo->prBssDesc->aucBSSID); + if (prStaRec) + prStaRec->ucStaState = STA_STATE_1; + /* Update Station Record - Class 1 Flag */ +#if DBG + else + ASSERT(0); + /* Shouldn't happened, because we already + * add this STA_RECORD_T at JOIN_STATE_INIT + */ + +#endif /* DBG */ + + /* 4 <3> Pull back to IDLE. */ + joinFsmSteps(prAdapter, JOIN_STATE_IDLE); + + /* 4 <4> If we are in Roaming, recover the settings of previous BSS. */ + /* NOTE: JOIN FAIL - + * Restore original setting from current struct BSS_INFO. + */ + if (prAdapter->eConnectionState == MEDIA_STATE_CONNECTED) + joinAdoptParametersFromCurrentBss(prAdapter); +} /* end of joinFsmRunEventAbort() */ +#endif + +/* TODO(Kevin): following code will be modified and move to AIS FSM */ +#if 0 +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will send Join Timeout Event to JOIN FSM. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * + * \retval WLAN_STATUS_FAILURE Fail because of Join Timeout + */ +/*----------------------------------------------------------------------------*/ +uint32_t joinFsmRunEventJoinTimeOut(IN struct ADAPTER *prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + struct STA_RECORD *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 struct ADAPTER *prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + struct BSS_DESC *prBssDesc; + + DEBUGFUNC("joinAdoptParametersFromPeerBss"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + prBssDesc = prJoinInfo->prBssDesc; + + /* 4 <1> Adopt Peer BSS' PHY TYPE */ + prAdapter->eCurrentPhyType = prBssDesc->ePhyType; + + DBGLOG(JOIN, INFO, "Target BSS[%s]'s PhyType = %s\n", + prBssDesc->aucSSID, + (prBssDesc->ePhyType == PHY_TYPE_ERP_INDEX) ? "ERP" : "HR_DSSS"); + + /* 4 <2> Adopt Peer BSS' Frequency(Band/Channel) */ + DBGLOG(JOIN, INFO, + "Target BSS's Channel = %d, Band = %d\n", + prBssDesc->ucChannelNum, prBssDesc->eBand); + + nicSwitchChannel(prAdapter, + prBssDesc->eBand, prBssDesc->ucChannelNum, 10); + + prJoinInfo->fgIsParameterAdopted = TRUE; +} /* end of joinAdoptParametersFromPeerBss() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will adopt the parameters from current associated BSS. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void joinAdoptParametersFromCurrentBss(IN struct ADAPTER *prAdapter) +{ + /* P_JOIN_INFO_T prJoinInfo = &prAdapter->rJoinInfo; */ + struct BSS_INFO *prBssInfo; + + ASSERT(prAdapter); + prBssInfo = &prAdapter->rBssInfo; + + /* 4 <1> Adopt current BSS' PHY TYPE */ + prAdapter->eCurrentPhyType = prBssInfo->ePhyType; + + /* 4 <2> Adopt current BSS' Frequency(Band/Channel) */ + DBGLOG(JOIN, INFO, + "Current BSS's Channel = %d, Band = %d\n", + prBssInfo->ucChnl, prBssInfo->eBand); + + nicSwitchChannel(prAdapter, prBssInfo->eBand, prBssInfo->ucChnl, 10); +} /* end of joinAdoptParametersFromCurrentBss() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will update all the SW variables and + * HW MCR registers after + * the association with target BSS. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void joinComplete(IN struct ADAPTER *prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + struct BSS_DESC *prBssDesc; + P_PEER_BSS_INFO_T prPeerBssInfo; + struct BSS_INFO *prBssInfo; + struct CONNECTION_SETTINGS *prConnSettings; + struct STA_RECORD *prStaRec; + struct TX_CTRL *prTxCtrl; +#if CFG_SUPPORT_802_11D + struct IE_COUNTRY *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 */ + /* Our BSS's PHY_TYPE is ERP now. */ + if ((prBssInfo->ePhyType == PHY_TYPE_ERP_INDEX) && + (prBssDesc->fgIsERPPresent)) { + + prBssInfo->fgIsERPPresent = TRUE; + /* Save the ERP for later check */ + prBssInfo->ucERP = prBssDesc->ucERP; + } 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) { + struct DOMAIN_INFO_ENTRY rDomainInfo; + + if (domainGetDomainInfoByScanResult(prAdapter, &rDomainInfo)) { + if (prBssDesc->prIECountry) { + prIECountry = prBssDesc->prIECountry; + + domainParseCountryInfoElem(prIECountry, + &prBssInfo->rDomainInfo); + + /* use the domain get from the BSS info */ + prBssInfo->fgIsCountryInfoPresent = TRUE; + nicSetupOpChnlList(prAdapter, + prBssInfo->rDomainInfo.u2CountryCode, + FALSE); + } else { + /* use the domain get from the scan result */ + prBssInfo->fgIsCountryInfoPresent = TRUE; + nicSetupOpChnlList(prAdapter, + rDomainInfo.u2CountryCode, FALSE); + } + } + } +#endif + + /* 4 <2.K> Signal Power of the associated AP */ + prBssInfo->rRcpi = prBssDesc->rRcpi; + prBssInfo->rRssi = RCPI_TO_dBm(prBssInfo->rRcpi); + GET_CURRENT_SYSTIME(&prBssInfo->rRssiLastUpdateTime); + + /* 4 <2.L> Capability Field of the associated AP */ + prBssInfo->u2CapInfo = prBssDesc->u2CapInfo; + + DBGLOG(JOIN, INFO, + "prBssInfo-> fgIsERPPresent = %d, ucERP = %02x, rRcpi = %d, rRssi = %ld\n", + prBssInfo->fgIsERPPresent, + prBssInfo->ucERP, + prBssInfo->rRcpi, + prBssInfo->rRssi); + +/* 4 <3> Update BSS_INFO_T from PEER_BSS_INFO_T & NIC RATE FUNC */ + /* 4 <3.A> Association ID */ + prBssInfo->u2AssocId = prPeerBssInfo->u2AssocId; + + /* 4 <3.B> WMM Information */ + if (prAdapter->fgIsEnableWMM + && (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_SUPPORT_WMM)) { + + prBssInfo->fgIsWmmAssoc = TRUE; + prTxCtrl->rTxQForVoipAccess = TXQ_AC3; + + qosWmmInfoInit(&prBssInfo->rWmmInfo, + (prBssInfo->ePhyType == PHY_TYPE_HR_DSSS_INDEX) + ? TRUE : FALSE); + + if (prPeerBssInfo->rWmmInfo.ucWmmFlag + & WMM_FLAG_AC_PARAM_PRESENT) { + kalMemCopy(&prBssInfo->rWmmInfo, + &prPeerBssInfo->rWmmInfo, sizeof(WMM_INFO_T)); + } else { + kalMemCopy(&prBssInfo->rWmmInfo, + &prPeerBssInfo->rWmmInfo, + sizeof(WMM_INFO_T) - + sizeof(prPeerBssInfo->rWmmInfo.arWmmAcParams)); + } + } else { + prBssInfo->fgIsWmmAssoc = FALSE; + prTxCtrl->rTxQForVoipAccess = TXQ_AC1; + + kalMemZero(&prBssInfo->rWmmInfo, sizeof(WMM_INFO_T)); + } + + /* 4 <3.C> Operational Rate Set & BSS Basic Rate Set */ + prBssInfo->u2OperationalRateSet = prPeerBssInfo->u2OperationalRateSet; + prBssInfo->u2BSSBasicRateSet = prPeerBssInfo->u2BSSBasicRateSet; + + /* 4 <3.D> Short Preamble */ + if (prBssInfo->fgIsERPPresent) { + +/* NOTE(Kevin 2007/12/24): Truth Table. + *Short Preamble Bit in + * Final Driver Setting(Short) + *TRUE FALSE FALSE FALSE(shouldn't have such case, + * use the AssocResp) + *TRUE FALSE TRUE FALSE + *FALSE FALSE FALSE FALSE(shouldn't have such case, + * use the AssocResp) + *FALSE FALSE TRUE FALSE + *TRUE TRUE FALSE TRUE(follow ERP) + *TRUE TRUE TRUE FALSE(follow ERP) + *FALSE TRUE FALSE FALSE(shouldn't have such case, + * and we should set to FALSE) + *FALSE TRUE TRUE FALSE(we should set to FALSE) + */ + if ((prPeerBssInfo->fgIsShortPreambleAllowed) && + ((prConnSettings->ePreambleType == PREAMBLE_TYPE_SHORT) || + /* Short Preamble Option Enable is TRUE */ + ((prConnSettings->ePreambleType == PREAMBLE_TYPE_AUTO) + && (prBssDesc->u2CapInfo & CAP_INFO_SHORT_PREAMBLE)))) { + + prBssInfo->fgIsShortPreambleAllowed = TRUE; + + if (prBssInfo->ucERP & ERP_INFO_BARKER_PREAMBLE_MODE) + prBssInfo->fgUseShortPreamble = FALSE; + else + prBssInfo->fgUseShortPreamble = TRUE; + + } else { + prBssInfo->fgIsShortPreambleAllowed = FALSE; + prBssInfo->fgUseShortPreamble = FALSE; + } + } else { + /* NOTE(Kevin 2007/12/24): Truth Table. + * Short Preamble Bit in + * Final Driver Setting(Short) + * TRUE FALSE FALSE + * FALSE FALSE FALSE + * TRUE TRUE TRUE + * FALSE TRUE(status success) TRUE + * --> Honor the result of prPeerBssInfo. + */ + + prBssInfo->fgIsShortPreambleAllowed = + prBssInfo->fgUseShortPreamble = + prPeerBssInfo->fgIsShortPreambleAllowed; + } + + DBGLOG(JOIN, INFO, + "prBssInfo->fgIsShortPreambleAllowed = %d, prBssInfo->fgUseShortPreamble = %d\n", + prBssInfo->fgIsShortPreambleAllowed, + prBssInfo->fgUseShortPreamble); + + /* 4 <3.E> Short Slot Time */ + /* AP support Short Slot Time */ + prBssInfo->fgUseShortSlotTime = + prPeerBssInfo->fgUseShortSlotTime; + + 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) { + uint16_t 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, + (uint8_t) TXQ_DATA_MASK, (uint8_t) 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, (void *) NULL, 0); +} /* end of joinComplete() */ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/ais_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/ais_fsm.c new file mode 100644 index 0000000000000..54e18d5a30a16 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/ais_fsm.c @@ -0,0 +1,7068 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/ais_fsm.c#4 + */ + +/*! \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. + */ + +/******************************************************************************* + * C O M P I L E 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_MTK_MCIF_WIFI_SUPPORT +#include "mddp.h" +#endif +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define AIS_ROAMING_CONNECTION_TRIAL_LIMIT 2 +#define AIS_JOIN_TIMEOUT 7 + +#if (CFG_SUPPORT_HE_ER == 1) +#define AP_TX_POWER 20 +#endif + +/******************************************************************************* + * 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 uint8_t *apucDebugAisState[AIS_STATE_NUM] = { + (uint8_t *) DISP_STRING("IDLE"), + (uint8_t *) DISP_STRING("SEARCH"), + (uint8_t *) DISP_STRING("SCAN"), + (uint8_t *) DISP_STRING("ONLINE_SCAN"), + (uint8_t *) DISP_STRING("LOOKING_FOR"), + (uint8_t *) DISP_STRING("WAIT_FOR_NEXT_SCAN"), + (uint8_t *) DISP_STRING("REQ_CHANNEL_JOIN"), + (uint8_t *) DISP_STRING("JOIN"), + (uint8_t *) DISP_STRING("JOIN_FAILURE"), + (uint8_t *) DISP_STRING("IBSS_ALONE"), + (uint8_t *) DISP_STRING("IBSS_MERGE"), + (uint8_t *) DISP_STRING("NORMAL_TR"), + (uint8_t *) DISP_STRING("DISCONNECTING"), + (uint8_t *) DISP_STRING("REQ_REMAIN_ON_CHANNEL"), + (uint8_t *) DISP_STRING("REMAIN_ON_CHANNEL"), + (uint8_t *) DISP_STRING("OFF_CHNL_TX") +}; + +/******************************************************************************* + * M A 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 aisFsmRunEventScanDoneTimeOut(IN struct ADAPTER *prAdapter, + unsigned long ulParam); +static void aisRemoveDeauthBlacklist(struct ADAPTER *prAdapter); + +static void aisFunClearAllTxReq(IN struct ADAPTER *prAdapter, + IN struct AIS_MGMT_TX_REQ_INFO *prAisMgmtTxInfo); +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +static void aisResetBssTranstionMgtParam(struct AIS_SPECIFIC_BSS_INFO + *prSpecificBssInfo) +{ +#if CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT + struct BSS_TRANSITION_MGT_PARAM_T *prBtmParam = + &prSpecificBssInfo->rBTMParam; + + if (prBtmParam->u2OurNeighborBssLen > 0) { + kalMemFree(prBtmParam->pucOurNeighborBss, VIR_MEM_TYPE, + prBtmParam->u2OurNeighborBssLen); + prBtmParam->u2OurNeighborBssLen = 0; + } + kalMemZero(prBtmParam, sizeof(*prBtmParam)); +#endif +} + +#if (CFG_SUPPORT_HE_ER == 1) +uint8_t aisCheckPowerMatchERCondition(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc) +{ + int8_t txpwr = 0; + int8_t icBeaconRSSI; + + icBeaconRSSI = RCPI_TO_dBm(prBssDesc->ucRCPI); + wlanGetMiniTxPower(prAdapter, prBssDesc->eBand, PHY_MODE_OFDM, &txpwr); + + DBGLOG(AIS, INFO, "ER: STA Tx power:%x, AP Tx power:%x, Bcon RSSI:%x\n", + txpwr, AP_TX_POWER, icBeaconRSSI); + + return ((txpwr - (AP_TX_POWER - icBeaconRSSI)) < -95); +} + +bool aisCheckUsingERRate(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc) +{ + bool fgIsStaUseERRate = false; + + if ((prBssDesc->fgIsERSUDisable == 0) && + (prBssDesc->ucDCMMaxConRx > 0) && + (prBssDesc->eBand == BAND_5G) && + (aisCheckPowerMatchERCondition(prAdapter, prBssDesc))) { + fgIsStaUseERRate = TRUE; + } + + DBGLOG(AIS, INFO, "ER: ER disable:%x, max rx:%x, band:%x, use ER:%x\n", + prBssDesc->fgIsERSUDisable, prBssDesc->ucDCMMaxConRx, + prBssDesc->eBand, fgIsStaUseERRate); + + return fgIsStaUseERRate; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * @brief the function is used to initialize the value of the connection + * settings for AIS network + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisInitializeConnectionSettings(IN struct ADAPTER *prAdapter, + IN struct REG_INFO *prRegInfo, IN uint8_t ucBssIndex) +{ + struct CONNECTION_SETTINGS *prConnSettings; + uint8_t aucAnyBSSID[] = BC_BSSID; + uint8_t aucZeroMacAddr[] = NULL_MAC_ADDR; + int i = 0; + + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + + /* 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->ucSSIDLen = 0; + + prConnSettings->eOPMode = NET_TYPE_INFRA; + + prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_BEST_RSSI; + + if (prRegInfo) { + prConnSettings->ucAdHocChannelNum = 0; + prConnSettings->eAdHocBand = + prRegInfo->u4StartFreq < 5000000 ? BAND_2G4 : BAND_5G; + prConnSettings->eAdHocMode = + (enum ENUM_PARAM_AD_HOC_MODE)(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, ucBssIndex); + + /* Features */ + prConnSettings->fgIsEnableRoaming = FALSE; + +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE + prConnSettings->fgSecModeChangeStartTimer = FALSE; +#endif + +#if CFG_SUPPORT_ROAMING +#if 0 + if (prRegInfo) + prConnSettings->fgIsEnableRoaming = + ((prRegInfo->fgDisRoaming > 0) ? (FALSE) : (TRUE)); +#else + if (prAdapter->rWifiVar.fgDisRoaming) + prConnSettings->fgIsEnableRoaming = FALSE; + else + prConnSettings->fgIsEnableRoaming = TRUE; +#endif +#endif /* CFG_SUPPORT_ROAMING */ + + prConnSettings->fgIsAdHocQoSEnable = FALSE; + +#if CFG_SUPPORT_802_11AC + prAdapter->rWifiVar.eDesiredPhyConfig + = PHY_CONFIG_802_11ABGNAC; +#else + prAdapter->rWifiVar.eDesiredPhyConfig + = PHY_CONFIG_802_11ABGN; +#endif + +#if (CFG_SUPPORT_802_11AX == 1) + if (fgEfuseCtrlAxOn == 1) { + prAdapter->rWifiVar.eDesiredPhyConfig + = PHY_CONFIG_802_11ABGNACAX; + } +#endif + + /* Set default bandwidth modes */ + prAdapter->rWifiVar.uc2G4BandwidthMode = + (prAdapter->rWifiVar.ucSta2gBandwidth == MAX_BW_40MHZ) + ? CONFIG_BW_20_40M + : CONFIG_BW_20M; + prAdapter->rWifiVar.uc5GBandwidthMode = CONFIG_BW_20_40M; + + prConnSettings->rRsnInfo.ucElemId = 0x30; + prConnSettings->rRsnInfo.u2Version = 0x0001; + prConnSettings->rRsnInfo.u4GroupKeyCipherSuite = 0; + prConnSettings->rRsnInfo.u4PairwiseKeyCipherSuiteCount = 0; + for (i = 0; i < MAX_NUM_SUPPORTED_CIPHER_SUITES; i++) + prConnSettings->rRsnInfo.au4PairwiseKeyCipherSuite[i] = 0; + prConnSettings->rRsnInfo.u4AuthKeyMgtSuiteCount = 0; + for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) + prConnSettings->rRsnInfo.au4AuthKeyMgtSuite[i] = 0; + prConnSettings->rRsnInfo.u2RsnCap = 0; + prConnSettings->rRsnInfo.fgRsnCapPresent = FALSE; +} /* end of aisFsmInitializeConnectionSettings() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief the function is used to initialize the value in AIS_FSM_INFO_T for + * AIS FSM operation + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisFsmInit(IN struct ADAPTER *prAdapter, uint8_t ucBssIndex) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prAisBssInfo; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecificBssInfo; + struct CONNECTION_SETTINGS *prConnSettings; + struct AIS_MGMT_TX_REQ_INFO *prMgmtTxReqInfo = + (struct AIS_MGMT_TX_REQ_INFO *) NULL; + uint8_t i; + + DEBUGFUNC("aisFsmInit()"); + DBGLOG(SW1, INFO, "->aisFsmInit(%d)\n", ucBssIndex); + + /* avoid that the prAisBssInfo is realloc */ + if (prAdapter->prAisBssInfo[ucBssIndex] != NULL) { + DBGLOG(SW1, INFO, "-> realloc(%d)\n", ucBssIndex); + return; + } + + prAdapter->prAisBssInfo[ucBssIndex] = prAisBssInfo = + cnmGetBssInfoAndInit(prAdapter, NETWORK_TYPE_AIS, FALSE); + if (!prAisBssInfo) { + DBGLOG(AIS, ERROR, + "aisFsmInit failed because prAisBssInfo is NULL, return.\n"); + return; + } + + /* update MAC address */ + COPY_MAC_ADDR(prAisBssInfo->aucOwnMacAddr, + prAdapter->rMyMacAddr); + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prAisSpecificBssInfo = + aisGetAisSpecBssInfo(prAdapter, ucBssIndex); + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + + /* 4 <1> Initiate FSM */ + prAisFsmInfo->ePreviousState = AIS_STATE_IDLE; + prAisFsmInfo->eCurrentState = AIS_STATE_IDLE; + + prAisFsmInfo->ucAvailableAuthTypes = 0; + + prAisFsmInfo->prTargetBssDesc = (struct BSS_DESC *)NULL; + + prAisFsmInfo->ucSeqNumOfReqMsg = 0; + prAisFsmInfo->ucSeqNumOfChReq = 0; + prAisFsmInfo->ucSeqNumOfScanReq = 0; + prAisFsmInfo->u2SeqNumOfScanReport = AIS_SCN_REPORT_SEQ_NOT_SET; + prAisFsmInfo->fgIsChannelRequested = FALSE; + prAisFsmInfo->fgIsChannelGranted = FALSE; + prAisFsmInfo->u4PostponeIndStartTime = 0; + /* Support AP Selection */ + prAisFsmInfo->ucJoinFailCntAfterScan = 0; + + prAisFsmInfo->fgIsScanOidAborted = FALSE; + + prAisFsmInfo->fgIsScanning = FALSE; + + /* 4 <1.1> Initiate FSM - Timer INIT */ + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rBGScanTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventBGSleepTimeOut, + (unsigned long)ucBssIndex); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rIbssAloneTimer, + (PFN_MGMT_TIMEOUT_FUNC) + aisFsmRunEventIbssAloneTimeOut, + (unsigned long)ucBssIndex); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rScanDoneTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventScanDoneTimeOut, + (unsigned long)ucBssIndex); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rJoinTimeoutTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventJoinTimeout, + (unsigned long)ucBssIndex); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rChannelTimeoutTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventChannelTimeout, + (unsigned long)ucBssIndex); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rDeauthDoneTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventDeauthTimeout, + (unsigned long)ucBssIndex); + +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rSecModeChangeTimer, + (PFN_MGMT_TIMEOUT_FUNC) + aisFsmRunEventSecModeChangeTimeout, + (unsigned long)ucBssIndex); +#endif + + prMgmtTxReqInfo = &prAisFsmInfo->rMgmtTxInfo; + LINK_INITIALIZE(&prMgmtTxReqInfo->rTxReqLink); + + /* 4 <1.2> Initiate PWR STATE */ + SET_NET_PWR_STATE_IDLE(prAdapter, prAisBssInfo->ucBssIndex); + + /* 4 <2> Initiate BSS_INFO_T - common part */ + BSS_INFO_INIT(prAdapter, prAisBssInfo); + if (ucBssIndex == AIS_DEFAULT_INDEX) + COPY_MAC_ADDR(prAisBssInfo->aucOwnMacAddr, + prAdapter->rWifiVar.aucMacAddress); + else + COPY_MAC_ADDR(prAisBssInfo->aucOwnMacAddr, + prAdapter->rWifiVar.aucMacAddress1); + + /* 4 <3> Initiate BSS_INFO_T - private part */ + /* TODO */ + prAisBssInfo->eBand = BAND_2G4; + prAisBssInfo->ucPrimaryChannel = 1; + prAisBssInfo->prStaRecOfAP = (struct STA_RECORD *) NULL; + prAisBssInfo->ucOpRxNss = prAisBssInfo->ucOpTxNss = + wlanGetSupportNss(prAdapter, prAisBssInfo->ucBssIndex); +#if (CFG_HW_WMM_BY_BSS == 0) + prAisBssInfo->ucWmmQueSet = + (prAdapter->rWifiVar.eDbdcMode == ENUM_DBDC_MODE_DISABLED) ? + DBDC_5G_WMM_INDEX : DBDC_2G_WMM_INDEX; +#endif + /* 4 <4> Allocate MSDU_INFO_T for Beacon */ + prAisBssInfo->prBeacon = cnmMgtPktAlloc(prAdapter, + OFFSET_OF(struct WLAN_BEACON_FRAME, + aucInfoElem[0]) + MAX_IE_LENGTH); + + if (prAisBssInfo->prBeacon) { + prAisBssInfo->prBeacon->eSrc = TX_PACKET_MGMT; + /* NULL STA_REC */ + prAisBssInfo->prBeacon->ucStaRecIndex = 0xFF; + } + + prAisBssInfo->ucBMCWlanIndex = WTBL_RESERVED_ENTRY; + + for (i = 0; i < MAX_KEY_NUM; i++) { + prAisBssInfo->ucBMCWlanIndexS[i] = WTBL_RESERVED_ENTRY; + prAisBssInfo->ucBMCWlanIndexSUsed[i] = FALSE; + prAisBssInfo->wepkeyUsed[i] = FALSE; + } +#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; + } + prAisBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC = + (uint8_t) prAdapter->u4UapsdAcBmp; + prAisBssInfo->rPmProfSetupInfo.ucBmpTriggerAC = + (uint8_t) prAdapter->u4UapsdAcBmp; + prAisBssInfo->rPmProfSetupInfo.ucUapsdSp = + (uint8_t) prAdapter->u4MaxSpLen; +#endif + + /* request list initialization */ + LINK_INITIALIZE(&prAisFsmInfo->rPendingReqList); + + /* Support AP Selection */ + LINK_MGMT_INIT(&prAdapter->rWifiVar.rBlackList); + kalMemZero(&prAisSpecificBssInfo->arCurEssChnlInfo[0], + sizeof(prAisSpecificBssInfo->arCurEssChnlInfo)); + LINK_INITIALIZE(&prAisSpecificBssInfo->rCurEssLink); + /* end Support AP Selection */ + LINK_INITIALIZE(&prAisBssInfo->rPmkidCache); + /* 11K, 11V */ + LINK_MGMT_INIT(&prAisSpecificBssInfo->rNeighborApList); + kalMemZero(&prAisSpecificBssInfo->rBTMParam, + sizeof(prAisSpecificBssInfo->rBTMParam)); + + rrmParamInit(prAdapter, ucBssIndex); +#if CFG_SUPPORT_802_11W + init_completion(&prAisBssInfo->rDeauthComp); + prAisBssInfo->encryptedDeauthIsInProcess = FALSE; +#endif + /* DBGPRINTF("[2] ucBmpDeliveryAC:0x%x, + * ucBmpTriggerAC:0x%x, ucUapsdSp:0x%x", + */ + /* prAisBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC, */ + /* prAisBssInfo->rPmProfSetupInfo.ucBmpTriggerAC, */ + /* prAisBssInfo->rPmProfSetupInfo.ucUapsdSp); */ + + /* Bind NetDev & BssInfo */ + /* wlanBindBssIdxToNetInterface(prAdapter->prGlueInfo, + * NET_DEV_WLAN_IDX, prAisBssInfo->ucBssIndex); + */ +} /* 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 struct ADAPTER *prAdapter, uint8_t ucBssIndex) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prAisBssInfo; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecificBssInfo; + struct CONNECTION_SETTINGS *prConnSettings; + u_int8_t fgHalted = kalIsHalted(); + GLUE_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("aisFsmUninit()"); + DBGLOG(SW1, INFO, "->aisFsmUninit(%d)\n", ucBssIndex); + + /* avoid that the prAisBssInfo is double freed */ + if (aisGetAisBssInfo(prAdapter, ucBssIndex) == NULL) + return; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + prAisSpecificBssInfo = + aisGetAisSpecBssInfo(prAdapter, ucBssIndex); + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + + /* 4 <1> Stop all timers */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rBGScanTimer); + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rIbssAloneTimer); + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rJoinTimeoutTimer); + if (timerPendingTimer(&(prAisFsmInfo->rScanDoneTimer))) { + /* call aisFsmRunEventScanDoneTimeOut() + * to reset scan fsm + */ + if (!fgHalted) { + aisFsmRunEventScanDoneTimeOut(prAdapter, + (unsigned long)ucBssIndex); + if (prAdapter->prGlueInfo->prScanRequest != NULL) { + GLUE_ACQUIRE_SPIN_LOCK(prAdapter->prGlueInfo, + SPIN_LOCK_NET_DEV); + kalCfg80211ScanDone(prAdapter->prGlueInfo + ->prScanRequest, TRUE); + prAdapter->prGlueInfo->prScanRequest = NULL; + prAisFsmInfo->u2SeqNumOfScanReport = + AIS_SCN_REPORT_SEQ_NOT_SET; + GLUE_RELEASE_SPIN_LOCK(prAdapter->prGlueInfo, + SPIN_LOCK_NET_DEV); + } + } + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); + } + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer); +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rSecModeChangeTimer); +#endif + /* 4 <2> flush pending request */ + aisFsmFlushRequest(prAdapter, ucBssIndex); + aisResetBssTranstionMgtParam(prAisSpecificBssInfo); + + aisFunClearAllTxReq(prAdapter, &(prAisFsmInfo->rMgmtTxInfo)); + + /* 4 <3> Reset driver-domain BSS-INFO */ + if (prAisBssInfo) { + /* Deactivate BSS. */ + UNSET_NET_ACTIVE(prAdapter, + prAisBssInfo->ucBssIndex); + if (!fgHalted) + nicDeactivateNetwork(prAdapter, + prAisBssInfo->ucBssIndex); + + if (prAisBssInfo->prBeacon) { + cnmMgtPktFree(prAdapter, prAisBssInfo->prBeacon); + prAisBssInfo->prBeacon = NULL; + } + + cnmFreeBssInfo(prAdapter, prAisBssInfo); + prAdapter->prAisBssInfo[ucBssIndex] = NULL; + } +#if CFG_SUPPORT_802_11W + rsnStopSaQuery(prAdapter, ucBssIndex); +#endif + /* Support AP Selection */ + LINK_MGMT_UNINIT(&prAdapter->rWifiVar.rBlackList, + struct AIS_BLACKLIST_ITEM, VIR_MEM_TYPE); + /* end Support AP Selection */ + LINK_MGMT_UNINIT(&prAisSpecificBssInfo->rNeighborApList, + struct NEIGHBOR_AP_T, VIR_MEM_TYPE); + + /* make sure pmkid cached is empty after uninit*/ + rsnFlushPmkid(prAdapter, ucBssIndex); + + rrmParamInit(prAdapter, ucBssIndex); +} /* end of aisFsmUninit() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Check if ais is processing beacon timeout + * + * @return true if processing + */ +/*----------------------------------------------------------------------------*/ +bool aisFsmIsInProcessPostpone(IN struct ADAPTER *prAdapter, + uint8_t ucBssIndex) +{ + struct AIS_FSM_INFO *fsm = aisGetAisFsmInfo(prAdapter, ucBssIndex); + struct BSS_INFO *bss = aisGetAisBssInfo(prAdapter, ucBssIndex); + struct CONNECTION_SETTINGS *set = + aisGetConnSettings(prAdapter, ucBssIndex); + + return bss->eConnectionState == MEDIA_STATE_DISCONNECTED && + fsm->u4PostponeIndStartTime > 0 && + !CHECK_FOR_TIMEOUT(kalGetTimeTick(), fsm->u4PostponeIndStartTime, + SEC_TO_MSEC(set->ucDelayTimeOfDisconnectEvent)); +} + +bool aisFsmIsBeaconTimeout(IN struct ADAPTER *prAdapter, + uint8_t ucBssIndex) +{ + struct BSS_INFO *prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + + return aisFsmIsInProcessPostpone(prAdapter, ucBssIndex) && + (prAisBssInfo->ucReasonOfDisconnect == + DISCONNECT_REASON_CODE_RADIO_LOST || + prAisBssInfo->ucReasonOfDisconnect == + DISCONNECT_REASON_CODE_RADIO_LOST_TX_ERR); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc, uint8_t ucBssIndex) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prAisBssInfo; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecificBssInfo; + struct CONNECTION_SETTINGS *prConnSettings; + struct STA_RECORD *prStaRec; + struct MSG_SAA_FSM_START *prJoinReqMsg; + struct GL_WPA_INFO *prWpaInfo; +#if (CFG_SUPPORT_HE_ER == 1) + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; +#endif + struct AIS_BLACKLIST_ITEM *prBlackList; + + DEBUGFUNC("aisFsmStateInit_JOIN()"); + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + prAisSpecificBssInfo = + aisGetAisSpecBssInfo(prAdapter, ucBssIndex); + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + prWpaInfo = aisGetWpaInfo(prAdapter, + ucBssIndex); + + /* 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, + prAisBssInfo->ucBssIndex, + prBssDesc); + + if (!prStaRec) { + DBGLOG(AIS, ERROR, + "aisFsmStateInit_JOIN failed because prStaRec is NULL, return.\n"); + return; + } + + prAisFsmInfo->prTargetStaRec = prStaRec; + + /* 4 <2.1> sync. to firmware domain */ + if (prStaRec->ucStaState == STA_STATE_1) + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + /* 4 <3> Update ucAvailableAuthTypes which we can choice during SAA */ + if (prAisBssInfo->eConnectionState == MEDIA_STATE_DISCONNECTED + /* Not in case of beacon timeout*/ + && !aisFsmIsBeaconTimeout(prAdapter, ucBssIndex)) { + + prStaRec->fgIsReAssoc = FALSE; + + switch (prConnSettings->eAuthMode) { + case AUTH_MODE_OPEN: + if (prConnSettings->rRsnInfo.au4AuthKeyMgtSuite[0] + == WLAN_AKM_SUITE_SAE) { + prAisFsmInfo->ucAvailableAuthTypes = + (uint8_t) (AUTH_TYPE_OPEN_SYSTEM | + AUTH_TYPE_SAE); + DBGLOG(AIS, INFO, + "JOIN INIT: eAuthMode == OPEN | SAE\n"); + } else { + prAisFsmInfo->ucAvailableAuthTypes = + (uint8_t) AUTH_TYPE_OPEN_SYSTEM; + DBGLOG(AIS, INFO, + "JOIN INIT: eAuthMode == OPEN\n"); + } + break; + case AUTH_MODE_WPA2_FT: + case AUTH_MODE_WPA2_FT_PSK: + case AUTH_MODE_WPA: + case AUTH_MODE_WPA_PSK: + case AUTH_MODE_WPA2: + case AUTH_MODE_WPA2_PSK: + case AUTH_MODE_WPA_OSEN: + case AUTH_MODE_WPA3_OWE: + prAisFsmInfo->ucAvailableAuthTypes = + (uint8_t) AUTH_TYPE_OPEN_SYSTEM; + break; + + case AUTH_MODE_SHARED: + prAisFsmInfo->ucAvailableAuthTypes = + (uint8_t) AUTH_TYPE_SHARED_KEY; + break; + + case AUTH_MODE_AUTO_SWITCH: + DBGLOG(AIS, LOUD, + "JOIN INIT: eAuthMode == AUTH_MODE_AUTO_SWITCH\n"); + prAisFsmInfo->ucAvailableAuthTypes = + (uint8_t) (AUTH_TYPE_OPEN_SYSTEM | + AUTH_TYPE_SHARED_KEY); + break; + + case AUTH_MODE_WPA3_SAE: + DBGLOG(AIS, LOUD, + "JOIN INIT: eAuthMode == AUTH_MODE_SAE\n"); + prAisFsmInfo->ucAvailableAuthTypes = + (uint8_t) AUTH_TYPE_SAE; + break; + + default: + 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; + /* reset BTM Params when do first connection */ + aisResetBssTranstionMgtParam(prAisSpecificBssInfo); + + /* Update Bss info before join */ + prAisBssInfo->eBand = prBssDesc->eBand; + prAisBssInfo->ucPrimaryChannel = prBssDesc->ucChannelNum; + +#if (CFG_SUPPORT_HE_ER == 1) + prStaRec->fgIsExtendedRange = FALSE; + + if (IS_FEATURE_ENABLED(prWifiVar->u4ExtendedRange)) { + /* check using the ER rate or not */ + prStaRec->fgIsExtendedRange = + aisCheckUsingERRate(prAdapter, prBssDesc); + } +#endif + } else { + DBGLOG(AIS, LOUD, "JOIN INIT: AUTH TYPE = %d for Roaming\n", + prAisSpecificBssInfo->ucRoamingAuthTypes); + + /* We do roaming while the medium is connected */ + prStaRec->fgIsReAssoc = TRUE; + + /* TODO(Kevin): We may call a sub function to + * acquire the Roaming Auth Type + */ + switch (prConnSettings->eAuthMode) { + case AUTH_MODE_OPEN: + if (prWpaInfo->u4WpaVersion == + IW_AUTH_WPA_VERSION_DISABLED + && prWpaInfo->u4AuthAlg == + IW_AUTH_ALG_FT) { + prAisFsmInfo->ucAvailableAuthTypes = + (uint8_t) AUTH_TYPE_FAST_BSS_TRANSITION; + DBGLOG(AIS, INFO, "FT: Non-RSN FT roaming\n"); + } else { + prAisFsmInfo->ucAvailableAuthTypes = + prAisSpecificBssInfo-> + ucRoamingAuthTypes; + } + break; + case AUTH_MODE_WPA2_FT: + case AUTH_MODE_WPA2_FT_PSK: + prAisFsmInfo->ucAvailableAuthTypes = + (uint8_t) AUTH_TYPE_FAST_BSS_TRANSITION; + DBGLOG(AIS, TRACE, "FT: RSN FT roaming\n"); + break; + case AUTH_MODE_WPA3_SAE: + prBlackList = + aisQueryBlackList(prAdapter, prBssDesc); + if (rsnSearchPmkidEntry(prAdapter, prBssDesc->aucBSSID, + ucBssIndex) + && + (!prBlackList || prBlackList->u2AuthStatus + != STATUS_INVALID_PMKID)) { + prAisFsmInfo->ucAvailableAuthTypes = + (uint8_t) AUTH_TYPE_OPEN_SYSTEM; + DBGLOG(AIS, INFO, + "SAE: change AUTH to OPEN when roaming with PMK\n"); + } else { + prAisFsmInfo->ucAvailableAuthTypes = + (uint8_t) AUTH_TYPE_SAE; + } + break; + default: + prAisFsmInfo->ucAvailableAuthTypes = + prAisSpecificBssInfo->ucRoamingAuthTypes; + break; + } + + prStaRec->ucTxAuthAssocRetryLimit = + TX_AUTH_ASSOCI_RETRY_LIMIT_FOR_ROAMING; + } + + /* 4 <4> Use an appropriate Authentication Algorithm + * Number among the ucAvailableAuthTypes + */ + if (prAisFsmInfo->ucAvailableAuthTypes & + (uint8_t) AUTH_TYPE_SHARED_KEY) { + + DBGLOG(AIS, LOUD, + "JOIN INIT: Try to do Authentication with AuthType == SHARED_KEY.\n"); + + prAisFsmInfo->ucAvailableAuthTypes &= + ~(uint8_t) AUTH_TYPE_SHARED_KEY; + + prStaRec->ucAuthAlgNum = + (uint8_t) AUTH_ALGORITHM_NUM_SHARED_KEY; + } else if (prAisFsmInfo->ucAvailableAuthTypes & (uint8_t) + AUTH_TYPE_OPEN_SYSTEM) { + + DBGLOG(AIS, LOUD, + "JOIN INIT: Try to do Authentication with AuthType == OPEN_SYSTEM.\n"); + prAisFsmInfo->ucAvailableAuthTypes &= + ~(uint8_t) AUTH_TYPE_OPEN_SYSTEM; + + prStaRec->ucAuthAlgNum = + (uint8_t) AUTH_ALGORITHM_NUM_OPEN_SYSTEM; + } else if (prAisFsmInfo->ucAvailableAuthTypes & (uint8_t) + AUTH_TYPE_FAST_BSS_TRANSITION) { + + DBGLOG(AIS, LOUD, + "JOIN INIT: Try to do Authentication with AuthType == FAST_BSS_TRANSITION.\n"); + + prAisFsmInfo->ucAvailableAuthTypes &= + ~(uint8_t) AUTH_TYPE_FAST_BSS_TRANSITION; + + prStaRec->ucAuthAlgNum = + (uint8_t) AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION; + } else if (prAisFsmInfo->ucAvailableAuthTypes & (uint8_t) + AUTH_TYPE_SAE) { + DBGLOG(AIS, LOUD, + "JOIN INIT: Try to do Authentication with AuthType == SAE.\n"); + + prStaRec->ucAuthAlgNum = + (uint8_t) AUTH_ALGORITHM_NUM_SAE; + } else { + DBGLOG(AIS, ERROR, + "JOIN INIT: Unsupported auth type %d\n", + prAisFsmInfo->ucAvailableAuthTypes); + return; + } + + /* 4 <5> Overwrite Connection Setting for eConnectionPolicy + * == ANY (Used by Assoc Req) + */ + if (prBssDesc->ucSSIDLen) + COPY_SSID(prConnSettings->aucSSID, prConnSettings->ucSSIDLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + /* 4 <6> Send a Msg to trigger SAA to start JOIN process. */ + prJoinReqMsg = + (struct MSG_SAA_FSM_START *)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct + MSG_SAA_FSM_START)); + if (!prJoinReqMsg) { + DBGLOG(AIS, ERROR, "Can't trigger SAA FSM\n"); + return; + } + + prJoinReqMsg->rMsgHdr.eMsgId = MID_AIS_SAA_FSM_START; + prJoinReqMsg->ucSeqNum = ++prAisFsmInfo->ucSeqNumOfReqMsg; + prJoinReqMsg->prStaRec = prStaRec; + + if (1) { + int j; + struct FRAG_INFO *prFragInfo; + + for (j = 0; j < MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS; j++) { + prFragInfo = &prStaRec->rFragInfo[j]; + + if (prFragInfo->pr1stFrag) { + /* nicRxReturnRFB(prAdapter, + * prFragInfo->pr1stFrag); + */ + prFragInfo->pr1stFrag = (struct SW_RFB *)NULL; + } + } + } +#if CFG_SUPPORT_802_11K + rlmSetMaxTxPwrLimit(prAdapter, + (prBssDesc->cPowerLimit != RLM_INVALID_POWER_LIMIT) + ? prBssDesc->cPowerLimit : RLM_MAX_TX_PWR, 1); +#endif + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *)prJoinReqMsg, + MSG_SEND_METHOD_BUF); +} /* end of aisFsmInit_JOIN() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Retry JOIN for AUTH_MODE_AUTO_SWITCH + * + * @param[in] prStaRec Pointer to the STA_RECORD_T + * + * @retval TRUE We will retry JOIN + * @retval FALSE We will not retry JOIN + */ +/*----------------------------------------------------------------------------*/ +u_int8_t aisFsmStateInit_RetryJOIN(IN struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, uint8_t ucBssIndex) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct MSG_SAA_FSM_START *prJoinReqMsg; + struct CONNECTION_SETTINGS *prConnSettings; + + DEBUGFUNC("aisFsmStateInit_RetryJOIN()"); + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + + /* Retry other AuthType if possible */ + if (!prAisFsmInfo->ucAvailableAuthTypes) + return FALSE; + + if ((prStaRec->u2StatusCode != + STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED) && + (prStaRec->u2StatusCode != + STATUS_CODE_AUTH_TIMEOUT) && + (prStaRec->u2StatusCode != + STATUS_CODE_INVALID_INFO_ELEMENT) && + (prStaRec->u2StatusCode != + STATUS_INVALID_PMKID)) { + prAisFsmInfo->ucAvailableAuthTypes = 0; + return FALSE; + } + + if (prConnSettings->rRsnInfo.au4AuthKeyMgtSuite[0] + == WLAN_AKM_SUITE_SAE && + prAisFsmInfo->ucAvailableAuthTypes & (uint8_t) + AUTH_TYPE_SAE) { + DBGLOG(AIS, INFO, + "RETRY JOIN INIT: Retry Authentication with AuthType == SAE.\n"); + + prAisFsmInfo->ucAvailableAuthTypes &= + ~(uint8_t) AUTH_TYPE_SAE; + + prStaRec->ucAuthAlgNum = + (uint8_t) AUTH_ALGORITHM_NUM_SAE; + } else if (prAisFsmInfo->ucAvailableAuthTypes & (uint8_t) + AUTH_TYPE_OPEN_SYSTEM) { + + DBGLOG(AIS, INFO, + "RETRY JOIN INIT: Retry Authentication with AuthType == OPEN_SYSTEM.\n"); + + prAisFsmInfo->ucAvailableAuthTypes &= + ~(uint8_t) AUTH_TYPE_OPEN_SYSTEM; + + prStaRec->ucAuthAlgNum = + (uint8_t) AUTH_ALGORITHM_NUM_OPEN_SYSTEM; + } else { + DBGLOG(AIS, ERROR, + "RETRY JOIN INIT: Retry Authentication with Unexpected AuthType: %d.\n", + prAisFsmInfo->ucAvailableAuthTypes); + return FALSE; + } + + /* No more available Auth Types */ + prAisFsmInfo->ucAvailableAuthTypes = 0; + + /* Trigger SAA to start JOIN process. */ + prJoinReqMsg = + (struct MSG_SAA_FSM_START *)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct + MSG_SAA_FSM_START)); + if (!prJoinReqMsg) { + DBGLOG(AIS, ERROR, "Can't trigger SAA FSM\n"); + return FALSE; + } + + prJoinReqMsg->rMsgHdr.eMsgId = MID_AIS_SAA_FSM_START; + prJoinReqMsg->ucSeqNum = ++prAisFsmInfo->ucSeqNumOfReqMsg; + prJoinReqMsg->prStaRec = prStaRec; + + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *)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 struct ADAPTER *prAdapter, + uint8_t ucBssIndex) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_INFO *prAisBssInfo; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + + /* 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, ucBssIndex); +} /* 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 struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc, uint8_t ucBssIndex) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_INFO *prAisBssInfo; + struct STA_RECORD *prStaRec = (struct STA_RECORD *)NULL; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + + /* 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, + prAisBssInfo->ucBssIndex, + prBssDesc); + + if (!prStaRec) { + DBGLOG(AIS, ERROR, + "aisFsmStateInit_IBSS_MERGE failed because prStaRec is NULL, return.\n"); + return; + } + + prStaRec->fgIsMerging = TRUE; + + prAisFsmInfo->prTargetStaRec = prStaRec; + + /* 4 <2.1> sync. to firmware domain */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + /* 4 <3> IBSS-Merge */ + aisFsmMergeIBSS(prAdapter, prStaRec); +} /* end of aisFsmStateInit_IBSS_MERGE() */ + +#endif /* CFG_SUPPORT_ADHOC */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Process of JOIN Abort + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisFsmStateAbort_JOIN(IN struct ADAPTER *prAdapter, + uint8_t ucBssIndex) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct MSG_SAA_FSM_ABORT *prJoinAbortMsg; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + + /* 1. Abort JOIN process */ + prJoinAbortMsg = + (struct MSG_SAA_FSM_ABORT *)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct + MSG_SAA_FSM_ABORT)); + if (!prJoinAbortMsg) { + DBGLOG(AIS, ERROR, "Can't abort SAA FSM\n"); + return; + } + + prJoinAbortMsg->rMsgHdr.eMsgId = MID_AIS_SAA_FSM_ABORT; + prJoinAbortMsg->ucSeqNum = prAisFsmInfo->ucSeqNumOfReqMsg; + prJoinAbortMsg->prStaRec = prAisFsmInfo->prTargetStaRec; + + prAisFsmInfo->prTargetBssDesc->fgIsConnected = FALSE; + prAisFsmInfo->prTargetBssDesc->fgIsConnecting = FALSE; + + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *)prJoinAbortMsg, + MSG_SEND_METHOD_BUF); + + /* 2. Return channel privilege */ + aisFsmReleaseCh(prAdapter, ucBssIndex); + + /* 3.1 stop join timeout timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rJoinTimeoutTimer); +} /* end of aisFsmAbortJOIN() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Process of SCAN Abort + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisFsmStateAbort_SCAN(IN struct ADAPTER *prAdapter, + uint8_t ucBssIndex) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct MSG_SCN_SCAN_CANCEL *prScanCancelMsg; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + + DBGLOG(AIS, STATE, "[%d] aisFsmStateAbort_SCAN\n", + ucBssIndex); + + /* Abort JOIN process. */ + prScanCancelMsg = + (struct MSG_SCN_SCAN_CANCEL *)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_SCN_SCAN_CANCEL)); + if (!prScanCancelMsg) { + DBGLOG(AIS, ERROR, "Can't abort SCN FSM\n"); + return; + } + kalMemZero(prScanCancelMsg, sizeof(struct MSG_SCN_SCAN_CANCEL)); + prScanCancelMsg->rMsgHdr.eMsgId = MID_AIS_SCN_SCAN_CANCEL; + prScanCancelMsg->ucSeqNum = prAisFsmInfo->ucSeqNumOfScanReq; + prScanCancelMsg->ucBssIndex = ucBssIndex; + prScanCancelMsg->fgIsChannelExt = FALSE; + if (prAisFsmInfo->fgIsScanOidAborted) { + prScanCancelMsg->fgIsOidRequest = TRUE; + prAisFsmInfo->fgIsScanOidAborted = FALSE; + } + + /* unbuffered message to guarantee scan is cancelled in sequence */ + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *)prScanCancelMsg, + MSG_SEND_METHOD_UNBUF); +} /* end of aisFsmAbortSCAN() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Process of NORMAL_TR Abort + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisFsmStateAbort_NORMAL_TR(IN struct ADAPTER *prAdapter, + uint8_t ucBssIndex) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + + /* TODO(Kevin): Do abort other MGMT func */ + + /* 1. Release channel to CNM */ + aisFsmReleaseCh(prAdapter, ucBssIndex); + + /* 2.1 stop join timeout timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rJoinTimeoutTimer); +} /* end of aisFsmAbortNORMAL_TR() */ + +#if CFG_SUPPORT_ADHOC +/*----------------------------------------------------------------------------*/ +/*! + * @brief Process of NORMAL_TR Abort + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisFsmStateAbort_IBSS(IN struct ADAPTER *prAdapter, + uint8_t ucBssIndex) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_DESC *prBssDesc; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + + /* 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, ucBssIndex); +} +#endif /* CFG_SUPPORT_ADHOC */ + +static u_int8_t +aisState_OFF_CHNL_TX(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + struct AIS_MGMT_TX_REQ_INFO *prMgmtTxInfo = + (struct AIS_MGMT_TX_REQ_INFO *) NULL; + struct AIS_OFF_CHNL_TX_REQ_INFO *prOffChnlTxPkt = + (struct AIS_OFF_CHNL_TX_REQ_INFO *) NULL; + struct AIS_FSM_INFO *prAisFsmInfo = + aisGetAisFsmInfo(prAdapter, ucBssIndex); + + prMgmtTxInfo = &prAisFsmInfo->rMgmtTxInfo; + + if (LINK_IS_EMPTY(&(prMgmtTxInfo->rTxReqLink))) { + cnmTimerStopTimer(prAdapter, + &prAisFsmInfo->rChannelTimeoutTimer); + aisFsmReleaseCh(prAdapter, ucBssIndex); + /* Link is empty, return back to IDLE. */ + return FALSE; + } + + prOffChnlTxPkt = + LINK_PEEK_HEAD(&(prMgmtTxInfo->rTxReqLink), + struct AIS_OFF_CHNL_TX_REQ_INFO, + rLinkEntry); + + if (prOffChnlTxPkt == NULL) { + DBGLOG(AIS, ERROR, + "Fatal Error, Link not empty but get NULL pointer.\n"); + aisFsmReleaseCh(prAdapter, ucBssIndex); + return FALSE; + } + + if (timerPendingTimer(&prAisFsmInfo->rChannelTimeoutTimer)) { + cnmTimerStopTimer(prAdapter, + &prAisFsmInfo->rChannelTimeoutTimer); + } + + cnmTimerStartTimer(prAdapter, + &prAisFsmInfo->rChannelTimeoutTimer, + prOffChnlTxPkt->u4Duration); + aisFuncTxMgmtFrame(prAdapter, + prMgmtTxInfo, + prOffChnlTxPkt->prMgmtTxMsdu, + prOffChnlTxPkt->u8Cookie, + ucBssIndex); + LINK_REMOVE_HEAD(&(prAisFsmInfo->rMgmtTxInfo.rTxReqLink), + prOffChnlTxPkt, + struct AIS_OFF_CHNL_TX_REQ_INFO *); + cnmMemFree(prAdapter, prOffChnlTxPkt); + + return TRUE; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Remove roaming requests including search and connect + * + * @param[in] + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisFsmRemoveRoamingRequest( + IN struct ADAPTER *prAdapter, IN uint8_t ucBssIndex) +{ + /* clear pending roaming connection request */ + aisFsmClearRequest(prAdapter, AIS_REQUEST_ROAMING_SEARCH, ucBssIndex); + aisFsmClearRequest(prAdapter, AIS_REQUEST_ROAMING_CONNECT, ucBssIndex); +} + +struct BSS_DESC *aisSearchBssDescByScore( + IN struct ADAPTER *prAdapter, IN uint8_t ucBssIndex) +{ + struct ROAMING_INFO *roam = aisGetRoamingInfo(prAdapter, ucBssIndex); + + return scanSearchBssDescByScoreForAis(prAdapter, + roam->eReason, ucBssIndex); +} + +uint8_t aisNeedTargetScan(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIndex) +{ + struct AIS_FSM_INFO *ais = NULL; + struct BSS_INFO *bss = NULL; + struct ROAMING_INFO *roam = NULL; + uint8_t discovering = FALSE; + uint8_t postponing = FALSE; + uint8_t issued = FALSE; + uint8_t trial = 0; + + ais = aisGetAisFsmInfo(prAdapter, ucBssIndex); + bss = aisGetAisBssInfo(prAdapter, ucBssIndex); + roam = aisGetRoamingInfo(prAdapter, ucBssIndex); + discovering = bss->eConnectionState == MEDIA_STATE_CONNECTED && + (roam->eCurrentState == ROAMING_STATE_DISCOVERY || + roam->eCurrentState == ROAMING_STATE_ROAM); + postponing = aisFsmIsInProcessPostpone(prAdapter, ucBssIndex); + trial = ais->ucConnTrialCount; + +#if CFG_SUPPORT_NCHO + issued = ais->fgTargetChnlScanIssued || + prAdapter->rNchoInfo.u4RoamScanControl; +#else + issued = ais->fgTargetChnlScanIssued; +#endif + + return (discovering && issued) || + (postponing && trial < AIS_ROAMING_CONNECTION_TRIAL_LIMIT); +} + +enum ENUM_AIS_STATE aisSearchHandleBssDesc(IN struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc, IN uint8_t ucBssIndex) +{ + + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prAisBssInfo; + struct CONNECTION_SETTINGS *prConnSettings; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + + /* 4 <2> We are not under Roaming Condition. */ + if (prAisBssInfo->eConnectionState == MEDIA_STATE_DISCONNECTED) { + /* 4 <2.a> If we have the matched one */ + if (prBssDesc) { + /* 4 Stored the Selected BSS security cipher. or + * later asoc req compose IE + */ + prAisBssInfo->u4RsnSelectedGroupCipher = + prBssDesc->u4RsnSelectedGroupCipher; + prAisBssInfo->u4RsnSelectedPairwiseCipher = + prBssDesc->u4RsnSelectedPairwiseCipher; + prAisBssInfo->u4RsnSelectedAKMSuite = + prBssDesc->u4RsnSelectedAKMSuite; + prAisBssInfo->eBand = prBssDesc->eBand; + if (prAisBssInfo->fgIsWmmInited == FALSE) + prAisBssInfo->ucWmmQueSet = + cnmWmmIndexDecision(prAdapter, prAisBssInfo); +#if CFG_SUPPORT_DBDC + /* DBDC decsion.may change OpNss */ + cnmDbdcPreConnectionEnableDecision( + prAdapter, + prAisBssInfo->ucBssIndex, + prBssDesc->eBand, + prBssDesc->ucChannelNum, + prAisBssInfo->ucWmmQueSet); +#endif /*CFG_SUPPORT_DBDC*/ + + /* 4 Do STATE transition and update current + * Operation Mode. + */ + if (prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) { + prAisBssInfo->eCurrentOPMode = + OP_MODE_INFRASTRUCTURE; + prAisFsmInfo->prTargetBssDesc = prBssDesc; + prAisFsmInfo->ucConnTrialCount++; + return AIS_STATE_REQ_CHANNEL_JOIN; +#if CFG_SUPPORT_ADHOC + } else if (prBssDesc->eBSSType == BSS_TYPE_IBSS) { + prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; + prAisFsmInfo->prTargetBssDesc = prBssDesc; + return AIS_STATE_IBSS_MERGE; +#endif /* CFG_SUPPORT_ADHOC */ + } else { + return AIS_STATE_WAIT_FOR_NEXT_SCAN; + } + } else { + /* 4 <2.b> If we don't have the matched one */ + if (prAisFsmInfo->rJoinReqTime != 0 && + CHECK_FOR_TIMEOUT(kalGetTimeTick(), + prAisFsmInfo->rJoinReqTime, + SEC_TO_SYSTIME(AIS_JOIN_TIMEOUT))) { + return AIS_STATE_JOIN_FAILURE; + } + + return aisFsmStateSearchAction(prAdapter, ucBssIndex); + } + } else { + /* 4 <3> We are under Roaming Condition. */ + if (prAisFsmInfo->ucConnTrialCount > + AIS_ROAMING_CONNECTION_TRIAL_LIMIT) { +#if CFG_SUPPORT_ROAMING + DBGLOG(AIS, STATE, "Roaming retry :%d fail!\n", + prAisFsmInfo->ucConnTrialCount); + roamingFsmRunEventFail(prAdapter, + ROAMING_FAIL_REASON_CONNLIMIT, ucBssIndex); +#endif /* CFG_SUPPORT_ROAMING */ + + /* reset retry count */ + prAisFsmInfo->ucConnTrialCount = 0; + + return AIS_STATE_NORMAL_TR; + } + +#define BSS_DESC_BAD_CASE \ + (!prBssDesc || (prBssDesc->fgIsConnected && \ + EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID) && \ + prConnSettings->eConnectionPolicy != CONNECT_BY_BSSID) || \ + prBssDesc->eBSSType != BSS_TYPE_INFRASTRUCTURE) + /* 4 <3.a> Following cases will go back to NORMAL_TR. + * Precondition: not user space triggered roaming + * + * 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. + * 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. + * however, if the connection policy is BSSID, means upper layer + * order driver connect to specific AP, we need still do connect + */ + if (prAisBssInfo->ucReasonOfDisconnect != + DISCONNECT_REASON_CODE_REASSOCIATION && + prAisBssInfo->ucReasonOfDisconnect != + DISCONNECT_REASON_CODE_ROAMING && BSS_DESC_BAD_CASE) { + if (prBssDesc) { + DBGLOG(ROAMING, INFO, + "fgIsConnected=%d, prBssDesc " MACSTR + ", prAisBssInfo " MACSTR "\n", + prBssDesc->fgIsConnected, + MAC2STR(prBssDesc->aucBSSID), + MAC2STR(prAisBssInfo->aucBSSID)); + } + if (prAisFsmInfo->fgTargetChnlScanIssued) { + /* if target channel scan has issued, and no + * roaming target is found, need to do full scan + */ + DBGLOG(AIS, INFO, + "[Roaming] No target found, try to full scan again\n"); + + prAisFsmInfo->fgTargetChnlScanIssued = FALSE; + return AIS_STATE_LOOKING_FOR; + } + +#if CFG_SUPPORT_ROAMING + roamingFsmRunEventFail(prAdapter, + ROAMING_FAIL_REASON_NOCANDIDATE, ucBssIndex); +#endif /* CFG_SUPPORT_ROAMING */ + + /* We already associated with it go back to NORMAL_TR */ + return AIS_STATE_NORMAL_TR; + } + + /* 4 <3.b> Try to roam out for JOIN this BSS_DESC_T. */ + if (BSS_DESC_BAD_CASE) + return aisFsmStateSearchAction(prAdapter, ucBssIndex); + + prAisFsmInfo->prTargetBssDesc = prBssDesc; + prAisFsmInfo->ucConnTrialCount++; + prAisFsmInfo->fgTargetChnlScanIssued = FALSE; + + return AIS_STATE_REQ_CHANNEL_JOIN; + } +} + +u_int8_t aisScanChannelFixed(struct ADAPTER *prAdapter, enum ENUM_BAND *prBand, + uint8_t *pucPrimaryChannel, IN uint8_t ucBssIndex) +{ + struct CONNECTION_SETTINGS *setting; + struct AIS_FSM_INFO *ais; + + ais = aisGetAisFsmInfo(prAdapter, ucBssIndex); + setting = aisGetConnSettings(prAdapter, ucBssIndex); + if (ais->eCurrentState == AIS_STATE_LOOKING_FOR && + setting->eConnectionPolicy == CONNECT_BY_BSSID && + setting->u4FreqInKHz != 0) { + *pucPrimaryChannel = + nicFreq2ChannelNum(setting->u4FreqInKHz * 1000); + if (*pucPrimaryChannel > 0) { + if (*pucPrimaryChannel <= 14) + *prBand = BAND_2G4; + else + *prBand = BAND_5G; + DBGLOG(AIS, INFO, "fixed channel %d, band %d\n", + *pucPrimaryChannel, *prBand); + return TRUE; + } + } else { + return cnmAisInfraChannelFixed(prAdapter, + prBand, pucPrimaryChannel); + } + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + enum ENUM_AIS_STATE eNextState, uint8_t ucBssIndex) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prAisBssInfo; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecificBssInfo; + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_DESC *prBssDesc; + struct MSG_CH_REQ *prMsgChReq; + struct MSG_SCN_SCAN_REQ_V2 *prScanReqMsg; + struct PARAM_SCAN_REQUEST_ADV *prScanRequest; + struct AIS_REQ_HDR *prAisReq; + struct ROAMING_INFO *prRoamingFsmInfo = NULL; + enum ENUM_BAND eBand = BAND_2G4; + uint8_t ucChannel = 1; + uint16_t u2ScanIELen; + u_int8_t fgIsTransition = (u_int8_t) FALSE; + uint8_t ucRfBw; + enum ENUM_AIS_STATE eNewState; + + DEBUGFUNC("aisFsmSteps()"); + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + prAisSpecificBssInfo = + aisGetAisSpecBssInfo(prAdapter, ucBssIndex); + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + prRoamingFsmInfo = + aisGetRoamingInfo(prAdapter, ucBssIndex); + + do { + + /* Do entering Next State */ + prAisFsmInfo->ePreviousState = prAisFsmInfo->eCurrentState; + + DBGLOG(AIS, STATE, "[AIS%d] TRANSITION: [%s] -> [%s]\n", + ucBssIndex, + aisGetFsmState(prAisFsmInfo->eCurrentState), + aisGetFsmState(eNextState)); + + /* NOTE(Kevin): This is the only place to change the + * eCurrentState(except initial) + */ + prAisFsmInfo->eCurrentState = eNextState; + + fgIsTransition = (u_int8_t) FALSE; + + aisPostponedEventOfDisconnTimeout(prAdapter, ucBssIndex); + + /* 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, ucBssIndex); + if (prAisFsmInfo->ePreviousState == + AIS_STATE_OFF_CHNL_TX) + aisFunClearAllTxReq(prAdapter, + &(prAisFsmInfo->rMgmtTxInfo)); + + if (prAisReq) + DBGLOG(AIS, INFO, + "eReqType=%d", prAisReq->eReqType); + else + DBGLOG(AIS, INFO, "No req anymore"); + + if (prAisReq == NULL || + prAisReq->eReqType == AIS_REQUEST_RECONNECT) { + if (IS_NET_ACTIVE(prAdapter, + prAisBssInfo->ucBssIndex)) { + UNSET_NET_ACTIVE(prAdapter, + prAisBssInfo->ucBssIndex); + nicDeactivateNetwork(prAdapter, + prAisBssInfo->ucBssIndex); + } + if (prAisReq != NULL) { + SET_NET_ACTIVE(prAdapter, + prAisBssInfo-> + ucBssIndex); + /* sync with firmware */ + nicActivateNetwork(prAdapter, + prAisBssInfo->ucBssIndex); + + SET_NET_PWR_STATE_ACTIVE(prAdapter, + prAisBssInfo->ucBssIndex); + + eNextState = AIS_STATE_SEARCH; + fgIsTransition = TRUE; + } else { + SET_NET_PWR_STATE_IDLE(prAdapter, + prAisBssInfo->ucBssIndex); + + if (prAdapter->rWifiVar. + rScanInfo.fgSchedScanning) { + SET_NET_ACTIVE(prAdapter, + prAisBssInfo->ucBssIndex); + nicActivateNetwork(prAdapter, + prAisBssInfo->ucBssIndex); + } + } + + if (prAisReq) { + /* free the message */ + cnmMemFree(prAdapter, prAisReq); + } + } else if (prAisReq->eReqType == AIS_REQUEST_SCAN) { + wlanClearScanningResult(prAdapter, ucBssIndex); + + eNextState = AIS_STATE_SCAN; + fgIsTransition = TRUE; + + /* free the message */ + cnmMemFree(prAdapter, prAisReq); + } else if (prAisReq->eReqType == + AIS_REQUEST_ROAMING_CONNECT + || prAisReq->eReqType == + AIS_REQUEST_ROAMING_SEARCH) { + /* ignore */ + /* free the message */ + cnmMemFree(prAdapter, prAisReq); + } else if (prAisReq->eReqType == + AIS_REQUEST_REMAIN_ON_CHANNEL) { + eNextState = AIS_STATE_REQ_REMAIN_ON_CHANNEL; + fgIsTransition = TRUE; + + /* free the message */ + cnmMemFree(prAdapter, prAisReq); + } + + prAisFsmInfo->u4SleepInterval = + AIS_BG_SCAN_INTERVAL_MIN_SEC; + + break; + + case AIS_STATE_SEARCH: + /* 4 <1> Search for a matched candidate and save + * it to prTargetBssDesc. + * changing the state, + * ATTENTION: anyone can't leave this case without + * except BTM, otherwise, may cause BtmResponseTimer's + * handler run worngly + */ +#if CFG_SLT_SUPPORT + prBssDesc = + prAdapter->rWifiVar.rSltInfo.prPseudoBssDesc; +#else + /* Support AP Selection */ + if (prAisFsmInfo->ucJoinFailCntAfterScan >= + SCN_BSS_JOIN_FAIL_THRESOLD) { + prBssDesc = NULL; + DBGLOG(AIS, STATE, + "Failed to connect %s more than 4 times after last scan, scan again\n", + prConnSettings->aucSSID); + } else { +#if CFG_SELECT_BSS_BASE_ON_MULTI_PARAM + prBssDesc = aisSearchBssDescByScore( + prAdapter, ucBssIndex); +#else + prBssDesc = scanSearchBssDescByPolicy + (prAdapter, prAisBssInfo->ucBssIndex); +#endif + } +#endif + + eNewState = aisSearchHandleBssDesc( + prAdapter, prBssDesc, ucBssIndex); + + if (eNewState != eNextState) { + eNextState = eNewState; + fgIsTransition = TRUE; + } + + break; + + case AIS_STATE_WAIT_FOR_NEXT_SCAN: + + DBGLOG(AIS, LOUD, + "SCAN: Idle Begin - Current Time = %u\n", + kalGetTimeTick()); + + cnmTimerStartTimer(prAdapter, + &prAisFsmInfo->rBGScanTimer, + SEC_TO_MSEC + (prAisFsmInfo->u4SleepInterval)); + + SET_NET_PWR_STATE_IDLE(prAdapter, + prAisBssInfo->ucBssIndex); + + 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, prAisBssInfo->ucBssIndex)) { + SET_NET_ACTIVE(prAdapter, + prAisBssInfo->ucBssIndex); + + /* sync with firmware */ + nicActivateNetwork(prAdapter, + prAisBssInfo->ucBssIndex); + } + prScanRequest = &(prAisFsmInfo->rScanRequest); + + /* IE length decision */ + if (prScanRequest->u4IELength > 0) { + u2ScanIELen = + (uint16_t) prScanRequest->u4IELength; + } else { +#if CFG_SUPPORT_WPS2 + u2ScanIELen = prConnSettings->u2WSCIELen; +#else + u2ScanIELen = 0; +#endif + } + + prScanReqMsg = + (struct MSG_SCN_SCAN_REQ_V2 *)cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + OFFSET_OF + (struct + MSG_SCN_SCAN_REQ_V2, + aucIE) + + u2ScanIELen); + if (!prScanReqMsg) { + DBGLOG(AIS, ERROR, "Can't trigger SCAN FSM\n"); + return; + } + kalMemZero(prScanReqMsg, OFFSET_OF + (struct MSG_SCN_SCAN_REQ_V2, + aucIE)+u2ScanIELen); + prScanReqMsg->rMsgHdr.eMsgId = MID_AIS_SCN_SCAN_REQ_V2; + prScanReqMsg->ucSeqNum = + ++prAisFsmInfo->ucSeqNumOfScanReq; + if (prAisFsmInfo->u2SeqNumOfScanReport == + AIS_SCN_REPORT_SEQ_NOT_SET) { + prAisFsmInfo->u2SeqNumOfScanReport = + (uint16_t) prScanReqMsg->ucSeqNum; + } + prScanReqMsg->ucBssIndex = + prAisBssInfo->ucBssIndex; +#if CFG_SUPPORT_802_11K + if (rrmFillScanMsg(prAdapter, prScanReqMsg)) { + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *)prScanReqMsg, + MSG_SEND_METHOD_BUF); + break; + } + COPY_MAC_ADDR(prScanReqMsg->aucBSSID, + "\xff\xff\xff\xff\xff\xff"); +#endif + +#if CFG_SUPPORT_RDD_TEST_MODE + prScanReqMsg->eScanType = SCAN_TYPE_PASSIVE_SCAN; +#else + if (prAisFsmInfo->eCurrentState == AIS_STATE_SCAN + || prAisFsmInfo->eCurrentState == + AIS_STATE_ONLINE_SCAN) { + uint8_t ucScanSSIDNum; + enum ENUM_SCAN_TYPE eScanType; + + ucScanSSIDNum = prScanRequest->u4SsidNum; + eScanType = prScanRequest->ucScanType; + + if (eScanType == SCAN_TYPE_ACTIVE_SCAN + && ucScanSSIDNum == 0) { + prScanReqMsg->eScanType = eScanType; + + prScanReqMsg->ucSSIDType + = SCAN_REQ_SSID_WILDCARD; + prScanReqMsg->ucSSIDNum = 0; + } else if (eScanType == SCAN_TYPE_PASSIVE_SCAN + && ucScanSSIDNum == 0) { + prScanReqMsg->eScanType = eScanType; + + prScanReqMsg->ucSSIDType = 0; + prScanReqMsg->ucSSIDNum = 0; + } else { + prScanReqMsg->eScanType = + SCAN_TYPE_ACTIVE_SCAN; + + prScanReqMsg->ucSSIDType = + SCAN_REQ_SSID_SPECIFIED; + prScanReqMsg->ucSSIDNum = ucScanSSIDNum; + prScanReqMsg->prSsid = + prScanRequest->rSsid; + } + kalMemCopy(prScanReqMsg->aucRandomMac, + prScanRequest->aucRandomMac, + MAC_ADDR_LEN); + prScanReqMsg->ucScnFuncMask |= + prScanRequest->ucScnFuncMask; + + } else { + prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; + + COPY_SSID(prAisFsmInfo->rRoamingSSID.aucSsid, + prAisFsmInfo->rRoamingSSID.u4SsidLen, + prConnSettings->aucSSID, + prConnSettings->ucSSIDLen); + + /* Scan for determined SSID */ + prScanReqMsg->ucSSIDType = + SCAN_REQ_SSID_SPECIFIED_ONLY; + prScanReqMsg->ucSSIDNum = 1; + prScanReqMsg->prSsid = + &(prAisFsmInfo->rRoamingSSID); +#if CFG_SUPPORT_SCAN_RANDOM_MAC + prScanReqMsg->ucScnFuncMask |= + ENUM_SCN_RANDOM_MAC_EN; +#endif + } +#endif + + /* using default channel dwell time/timeout value */ + prScanReqMsg->u2ProbeDelay = 0; + prScanReqMsg->u2ChannelDwellTime = 0; + prScanReqMsg->u2ChannelMinDwellTime = 0; + prScanReqMsg->u2TimeoutValue = 0; + /* Reduce APP scan's dwell time, prevent it affecting + * TX/RX performance + */ + if (prScanRequest->u4Flags & + NL80211_SCAN_FLAG_LOW_SPAN) { + prScanReqMsg->u2ChannelDwellTime = + SCAN_CHANNEL_DWELL_TIME_MSEC_APP; + prScanReqMsg->u2ChannelMinDwellTime = + SCAN_CHANNEL_MIN_DWELL_TIME_MSEC_APP; + } + /* check if tethering is running and need to fix on + * specific channel + */ + if (aisScanChannelFixed(prAdapter, &eBand, + &ucChannel, ucBssIndex)) { + prScanReqMsg->eScanChannel = + SCAN_CHANNEL_SPECIFIED; + prScanReqMsg->ucChannelListNum = 1; + prScanReqMsg->arChnlInfoList[0].eBand = eBand; + prScanReqMsg->arChnlInfoList[0].ucChannelNum = + ucChannel; + } else if (aisNeedTargetScan(prAdapter, + prAisBssInfo->ucBssIndex)) { + struct RF_CHANNEL_INFO *prChnlInfo = + &prScanReqMsg->arChnlInfoList[0]; + uint8_t ucChannelNum = 0; + uint8_t i = 0; + uint8_t essChnlNum = + prAisSpecificBssInfo->ucCurEssChnlInfoNum; + + for (i = 0; i < essChnlNum; i++) { + ucChannelNum = + prAisSpecificBssInfo-> + arCurEssChnlInfo[i].ucChannel; + if ((ucChannelNum >= 1) + && (ucChannelNum <= 14)) + prChnlInfo[i].eBand = BAND_2G4; + else + prChnlInfo[i].eBand = BAND_5G; + prChnlInfo[i].ucChannelNum + = ucChannelNum; + } + prScanReqMsg->ucChannelListNum = essChnlNum; + prScanReqMsg->eScanChannel = + SCAN_CHANNEL_SPECIFIED; + DBGLOG(AIS, INFO, + "[Roaming] Target Scan: Total number of scan channel(s)=%d\n", + prScanReqMsg->ucChannelListNum); + } else + if (prAdapter->aePreferBand + [KAL_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 + [KAL_NETWORK_TYPE_AIS_INDEX] == + BAND_2G4) { + prScanReqMsg->eScanChannel = SCAN_CHANNEL_2G4; + } else + if (prAdapter->aePreferBand + [KAL_NETWORK_TYPE_AIS_INDEX] == + BAND_5G) { + prScanReqMsg->eScanChannel = SCAN_CHANNEL_5G; + } else { + prScanReqMsg->eScanChannel = SCAN_CHANNEL_FULL; + } + + switch (prScanReqMsg->eScanChannel) { + case SCAN_CHANNEL_FULL: + case SCAN_CHANNEL_2G4: + case SCAN_CHANNEL_5G: + scanSetRequestChannel(prAdapter, + prScanRequest->u4ChannelNum, + prScanRequest->arChannel, + prScanRequest->u4Flags, + prAisFsmInfo->eCurrentState == + AIS_STATE_ONLINE_SCAN || + wlanWfdEnabled(prAdapter), + prScanReqMsg); + break; + default: + break; + } + + + if (u2ScanIELen > 0) { + kalMemCopy(prScanReqMsg->aucIE, + prScanRequest->pucIE, u2ScanIELen); + } else { +#if CFG_SUPPORT_WPS2 + if (prConnSettings->u2WSCIELen > 0) { + kalMemCopy(prScanReqMsg->aucIE, + &prConnSettings->aucWSCIE, + prConnSettings->u2WSCIELen); + } + } +#endif + prScanReqMsg->u2IELen = u2ScanIELen; + + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *)prScanReqMsg, + MSG_SEND_METHOD_BUF); + + /* reset prAisFsmInfo->rScanRequest */ + kalMemZero(prAisFsmInfo->aucScanIEBuf, + sizeof(prAisFsmInfo->aucScanIEBuf)); + prScanRequest->u4SsidNum = 0; + prScanRequest->ucScanType = SCAN_TYPE_ACTIVE_SCAN; + prScanRequest->u4IELength = 0; + prScanRequest->u4ChannelNum = 0; + prScanRequest->ucScnFuncMask = 0; + kalMemZero(prScanRequest->aucRandomMac, MAC_ADDR_LEN); + prAisFsmInfo->fgIsScanning = TRUE; + + /* Support AP Selection */ + prAisFsmInfo->ucJoinFailCntAfterScan = 0; + /* Scan flags will be set in next scan triggered by + * upper layer, reset to 0 to avoid next scan + * is triggered by Driver + */ + prScanRequest->u4Flags = 0; + break; + + case AIS_STATE_REQ_CHANNEL_JOIN: + /* stop Tx due to we need to connect a new AP. even the + ** new AP is operating on the same channel with current + ** , we still need to stop Tx, because firmware should + ** ensure all mgmt and dhcp packets are Tx in time, + ** and may cause normal data packets was queued and + ** eventually flushed in firmware + */ + if (prAisBssInfo->prStaRecOfAP && + prAisBssInfo->ucReasonOfDisconnect != + DISCONNECT_REASON_CODE_REASSOCIATION) + prAisBssInfo-> + prStaRecOfAP->fgIsTxAllowed = FALSE; + + /* send message to CNM for acquiring channel */ + prMsgChReq = + (struct MSG_CH_REQ *)cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_CH_REQ)); + if (!prMsgChReq) { + DBGLOG(AIS, ERROR, "Can't indicate CNM\n"); + return; + } + + prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; + prMsgChReq->ucBssIndex = + prAisBssInfo->ucBssIndex; + 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; +#if CFG_SUPPORT_DBDC + prMsgChReq->eDBDCBand = ENUM_BAND_AUTO; +#endif /*CFG_SUPPORT_DBDC */ + /* To do: check if 80/160MHz bandwidth is needed here */ + /* Decide RF BW by own OP and Peer OP BW */ + ucRfBw = + cnmGetDbdcBwCapability(prAdapter, + prAisBssInfo->ucBssIndex); + /* Revise to VHT OP BW */ + ucRfBw = rlmGetVhtOpBwByBssOpBw(ucRfBw); + if (ucRfBw > + prAisFsmInfo->prTargetBssDesc->eChannelWidth) + ucRfBw = + prAisFsmInfo-> + prTargetBssDesc->eChannelWidth; + + prMsgChReq->eRfChannelWidth = ucRfBw; + /* TODO: BW80+80 support */ + prMsgChReq->ucRfCenterFreqSeg1 = + nicGetVhtS1(prMsgChReq->ucPrimaryChannel, + prMsgChReq->eRfChannelWidth); + DBGLOG(RLM, INFO, + "AIS req CH for CH:%d, Bw:%d, s1=%d\n", + prAisBssInfo->ucPrimaryChannel, + prMsgChReq->eRfChannelWidth, + prMsgChReq->ucRfCenterFreqSeg1); + prMsgChReq->ucRfCenterFreqSeg2 = 0; + + rlmReviseMaxBw(prAdapter, prAisBssInfo->ucBssIndex, + &prMsgChReq->eRfSco, + (enum ENUM_CHANNEL_WIDTH *) + &prMsgChReq->eRfChannelWidth, + &prMsgChReq->ucRfCenterFreqSeg1, + &prMsgChReq->ucPrimaryChannel); + + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *)prMsgChReq, + MSG_SEND_METHOD_BUF); + + prAisFsmInfo->fgIsChannelRequested = TRUE; + break; + + case AIS_STATE_JOIN: + aisFsmStateInit_JOIN(prAdapter, + prAisFsmInfo->prTargetBssDesc, + ucBssIndex); + break; + + case AIS_STATE_JOIN_FAILURE: + nicMediaJoinFailure(prAdapter, + prAisBssInfo->ucBssIndex, + WLAN_STATUS_JOIN_FAILURE); + + prAisFsmInfo->prTargetBssDesc = NULL; + prAisFsmInfo->ucConnTrialCountLimit = 0; + eNextState = AIS_STATE_IDLE; + fgIsTransition = TRUE; + + break; + +#if CFG_SUPPORT_ADHOC + case AIS_STATE_IBSS_ALONE: + aisFsmStateInit_IBSS_ALONE(prAdapter, + ucBssIndex); + break; + + case AIS_STATE_IBSS_MERGE: + aisFsmStateInit_IBSS_MERGE(prAdapter, + prAisFsmInfo->prTargetBssDesc, + ucBssIndex); + break; +#endif /* CFG_SUPPORT_ADHOC */ + + case AIS_STATE_NORMAL_TR: + /* Renew op trx nss */ + cnmOpModeGetTRxNss(prAdapter, + prAisBssInfo->ucBssIndex, + &prAisBssInfo->ucOpRxNss, + &prAisBssInfo->ucOpTxNss); + + /* Don't do anything when rJoinTimeoutTimer + * is still ticking + */ + if (timerPendingTimer(&prAisFsmInfo->rJoinTimeoutTimer)) + break; + + if (prAisFsmInfo->ePreviousState == + AIS_STATE_OFF_CHNL_TX) + aisFunClearAllTxReq(prAdapter, + &(prAisFsmInfo->rMgmtTxInfo)); + + /* 1. Process for pending roaming scan */ + if (aisFsmIsRequestPending(prAdapter, + AIS_REQUEST_ROAMING_SEARCH, TRUE, + ucBssIndex) == TRUE) { + eNextState = AIS_STATE_LOOKING_FOR; + fgIsTransition = TRUE; + } + /* 2. Process for pending roaming connect */ + else if (aisFsmIsRequestPending(prAdapter, + AIS_REQUEST_ROAMING_CONNECT, TRUE, + ucBssIndex) + == TRUE) { + eNextState = AIS_STATE_SEARCH; + fgIsTransition = TRUE; + } + /* 3. Process for pending scan */ + else if (aisFsmIsRequestPending(prAdapter, + AIS_REQUEST_SCAN, TRUE, + ucBssIndex) == TRUE) { + wlanClearScanningResult(prAdapter, ucBssIndex); + eNextState = AIS_STATE_ONLINE_SCAN; + fgIsTransition = TRUE; + } else if (aisFsmIsRequestPending(prAdapter, + AIS_REQUEST_REMAIN_ON_CHANNEL, TRUE, + ucBssIndex) + == TRUE) { + eNextState = AIS_STATE_REQ_REMAIN_ON_CHANNEL; + fgIsTransition = TRUE; + } + + break; + + case AIS_STATE_DISCONNECTING: + /* send for deauth frame for disconnection */ + authSendDeauthFrame(prAdapter, + prAisBssInfo, + prAisBssInfo->prStaRecOfAP, + (struct SW_RFB *)NULL, + REASON_CODE_DEAUTH_LEAVING_BSS, + aisDeauthXmitComplete); + /* If it is scanning or BSS absent, HW may go away from + * serving channel, which may cause driver be not able + * to TX mgmt frame. So we need to start a longer timer + * to wait HW return to serving channel. + * We set the time out value to 1 second because + * it is long enough to return to serving channel + * in most cases, and disconnection delay is seamless + * to end-user even time out. + */ + cnmTimerStartTimer(prAdapter, + &prAisFsmInfo->rDeauthDoneTimer, + (prAisFsmInfo->fgIsScanning + || prAisBssInfo->fgIsNetAbsent) ? + 1000 : 100); + break; + + case AIS_STATE_REQ_REMAIN_ON_CHANNEL: + /* send message to CNM for acquiring channel */ + prMsgChReq = + (struct MSG_CH_REQ *)cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_CH_REQ)); + if (!prMsgChReq) { + DBGLOG(AIS, ERROR, "Can't indicate CNM\n"); + return; + } + + /* release channel */ + aisFsmReleaseCh(prAdapter, ucBssIndex); + + /* zero-ize */ + kalMemZero(prMsgChReq, sizeof(struct MSG_CH_REQ)); + + /* filling */ + prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; + prMsgChReq->ucBssIndex = + prAisBssInfo->ucBssIndex; + prMsgChReq->ucTokenID = ++prAisFsmInfo->ucSeqNumOfChReq; + prMsgChReq->eReqType = + prAisFsmInfo->rChReqInfo.eReqType; + prMsgChReq->u4MaxInterval = + prAisFsmInfo->rChReqInfo.u4DurationMs; + prMsgChReq->ucPrimaryChannel = + prAisFsmInfo->rChReqInfo.ucChannelNum; + prMsgChReq->eRfSco = prAisFsmInfo->rChReqInfo.eSco; + prMsgChReq->eRfBand = prAisFsmInfo->rChReqInfo.eBand; +#if CFG_SUPPORT_DBDC + prMsgChReq->eDBDCBand = ENUM_BAND_AUTO; +#endif + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *)prMsgChReq, + MSG_SEND_METHOD_BUF); + + prAisFsmInfo->fgIsChannelRequested = TRUE; + + break; + + case AIS_STATE_REMAIN_ON_CHANNEL: + if (!IS_NET_ACTIVE(prAdapter, + prAisBssInfo->ucBssIndex)) { + SET_NET_ACTIVE(prAdapter, + prAisBssInfo->ucBssIndex); + + /* sync with firmware */ + nicActivateNetwork(prAdapter, + prAisBssInfo->ucBssIndex); + } + + break; + + case AIS_STATE_OFF_CHNL_TX: + if (!IS_NET_ACTIVE(prAdapter, + prAisBssInfo->ucBssIndex)) { + SET_NET_ACTIVE(prAdapter, + prAisBssInfo->ucBssIndex); + + /* sync with firmware */ + nicActivateNetwork(prAdapter, + prAisBssInfo->ucBssIndex); + } + if (!aisState_OFF_CHNL_TX(prAdapter, ucBssIndex)) { + if (prAisBssInfo->eConnectionState == + MEDIA_STATE_CONNECTED) + eNextState = AIS_STATE_NORMAL_TR; + else + eNextState = AIS_STATE_IDLE; + fgIsTransition = TRUE; + } + break; + + default: + /* Make sure we have handle all STATEs */ + ASSERT(0); + break; + + } + } while (fgIsTransition); + + return; + +} /* end of aisFsmSteps() */ + +enum ENUM_AIS_STATE aisFsmStateSearchAction( + IN struct ADAPTER *prAdapter, uint8_t ucBssIndex) +{ + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_INFO *prAisBssInfo; + struct AIS_FSM_INFO *prAisFsmInfo; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + + if (prConnSettings->eOPMode == NET_TYPE_INFRA) + prAisFsmInfo->ucConnTrialCount++; + +#if CFG_SUPPORT_ADHOC + 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; + return AIS_STATE_IBSS_ALONE; + } +#endif /* CFG_SUPPORT_ADHOC */ + + return AIS_STATE_LOOKING_FOR; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void aisFsmRunEventScanDone(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_SCN_SCAN_DONE *prScanDoneMsg; + struct AIS_FSM_INFO *prAisFsmInfo; + enum ENUM_AIS_STATE eNextState; + uint8_t ucSeqNumOfCompMsg; + struct CONNECTION_SETTINGS *prConnSettings; + enum ENUM_SCAN_STATUS eStatus = SCAN_STATUS_DONE; + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq; + struct BCN_RM_PARAMS *prBcnRmParam; + struct ROAMING_INFO *prRoamingFsmInfo = NULL; + uint8_t ucBssIndex = 0; + + DEBUGFUNC("aisFsmRunEventScanDone()"); + + prScanDoneMsg = (struct MSG_SCN_SCAN_DONE *)prMsgHdr; + ucBssIndex = prScanDoneMsg->ucBssIndex; + + DBGLOG(AIS, LOUD, "[%d] EVENT-SCAN DONE: Current Time = %u\n", + ucBssIndex, + kalGetTimeTick()); + + if (aisGetAisBssInfo(prAdapter, ucBssIndex) == NULL) { + /* This case occurs when the AIS isn't done, but the wlan0 */ + /* has changed to AP mode. And the prAisBssInfo is freed. */ + DBGLOG(AIS, WARN, "prAisBssInfo is NULL, and then return\n"); + return; + } + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + prRoamingFsmInfo = + aisGetRoamingInfo(prAdapter, ucBssIndex); + prRmReq = aisGetRmReqParam(prAdapter, ucBssIndex); + prBcnRmParam = &prRmReq->rBcnRmParam; + + ucSeqNumOfCompMsg = prScanDoneMsg->ucSeqNum; + eStatus = prScanDoneMsg->eScanStatus; + cnmMemFree(prAdapter, prMsgHdr); + + DBGLOG(AIS, INFO, "ScanDone %u, status(%d) native req(%u)\n", + ucSeqNumOfCompMsg, eStatus, prAisFsmInfo->u2SeqNumOfScanReport); + + eNextState = prAisFsmInfo->eCurrentState; + + if ((uint16_t) ucSeqNumOfCompMsg == + prAisFsmInfo->u2SeqNumOfScanReport) { + prAisFsmInfo->u2SeqNumOfScanReport = AIS_SCN_REPORT_SEQ_NOT_SET; + prConnSettings->fgIsScanReqIssued = FALSE; + kalScanDone(prAdapter->prGlueInfo, ucBssIndex, + (eStatus == SCAN_STATUS_DONE) ? + WLAN_STATUS_SUCCESS : WLAN_STATUS_FAILURE); + } + if (ucSeqNumOfCompMsg != prAisFsmInfo->ucSeqNumOfScanReq) { + DBGLOG(AIS, WARN, + "SEQ NO of AIS SCN DONE MSG is not matched %u %u\n", + ucSeqNumOfCompMsg, prAisFsmInfo->ucSeqNumOfScanReq); + } else { + prAisFsmInfo->fgIsScanning = FALSE; + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_SCAN: + eNextState = AIS_STATE_IDLE; +#if CFG_SUPPORT_AGPS_ASSIST + scanReportScanResultToAgps(prAdapter); +#endif + break; + + case AIS_STATE_ONLINE_SCAN: + scanGetCurrentEssChnlList(prAdapter, ucBssIndex); + +#if CFG_SUPPORT_ROAMING + eNextState = aisFsmRoamingScanResultsUpdate(prAdapter, + ucBssIndex); +#else + eNextState = AIS_STATE_NORMAL_TR; +#endif /* CFG_SUPPORT_ROAMING */ +#if CFG_SUPPORT_AGPS_ASSIST + scanReportScanResultToAgps(prAdapter); +#endif +/* Support AP Selection */ + +/* end Support AP Selection */ + break; + + case AIS_STATE_LOOKING_FOR: + scanGetCurrentEssChnlList(prAdapter, ucBssIndex); + +#if CFG_SUPPORT_ROAMING + eNextState = aisFsmRoamingScanResultsUpdate(prAdapter, + ucBssIndex); +#else + eNextState = AIS_STATE_SEARCH; +#endif /* CFG_SUPPORT_ROAMING */ + break; + + default: + break; + + } + } + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState, ucBssIndex); + if (prBcnRmParam->eState == RM_NO_REQUEST) + return; + /* normal mode scan done, and beacon measurement is pending, + ** schedule to do measurement + */ + if (prBcnRmParam->eState == RM_WAITING) { + rrmDoBeaconMeasurement(prAdapter, ucBssIndex); + /* pending normal scan here, should schedule it on time */ + } else if (prBcnRmParam->rNormalScan.fgExist) { + struct NORMAL_SCAN_PARAMS *prParam = &prBcnRmParam->rNormalScan; + + DBGLOG(AIS, INFO, + "BCN REQ: Schedule normal scan after a beacon measurement done\n"); + prBcnRmParam->eState = RM_WAITING; + prBcnRmParam->rNormalScan.fgExist = FALSE; + cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer, + SEC_TO_MSEC(AIS_SCN_DONE_TIMEOUT_SEC)); + + aisFsmScanRequestAdv(prAdapter, &prParam->rScanRequest); + /* Radio Measurement is on-going, schedule to next Measurement + ** Element + */ + } else { +#if CFG_SUPPORT_802_11K + struct LINK *prBSSDescList = + &prAdapter->rWifiVar.rScanInfo.rBSSDescList; + struct BSS_DESC *prBssDesc = NULL; + uint32_t count = 0; + + /* collect updated bss for beacon request measurement */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, + struct BSS_DESC) + { + if (TIME_BEFORE(prRmReq->rScanStartTime, + prBssDesc->rUpdateTime)) { + rrmCollectBeaconReport( + prAdapter, prBssDesc, ucBssIndex); + count++; + } + } + DBGLOG(RRM, INFO, "BCN report Active Mode, total: %d\n", count); +#endif + rrmStartNextMeasurement(prAdapter, FALSE, ucBssIndex); + } +} /* end of aisFsmRunEventScanDone() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void aisFsmRunEventAbort(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_AIS_ABORT *prAisAbortMsg; + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prAisBssInfo; + uint8_t ucReasonOfDisconnect; + u_int8_t fgDelayIndication; + struct CONNECTION_SETTINGS *prConnSettings; + uint8_t ucBssIndex = 0; + + DEBUGFUNC("aisFsmRunEventAbort()"); + + /* 4 <1> Extract information of Abort Message and then free memory. */ + prAisAbortMsg = (struct MSG_AIS_ABORT *)prMsgHdr; + ucReasonOfDisconnect = prAisAbortMsg->ucReasonOfDisconnect; + fgDelayIndication = prAisAbortMsg->fgDelayIndication; + ucBssIndex = prAisAbortMsg->ucBssIndex; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + + cnmMemFree(prAdapter, prMsgHdr); + + DBGLOG(AIS, STATE, + "[%d] EVENT-ABORT: Current State %s, ucReasonOfDisconnect:%d\n", + ucBssIndex, + aisGetFsmState(prAisFsmInfo->eCurrentState), + ucReasonOfDisconnect); + + /* record join request time */ + GET_CURRENT_SYSTIME(&(prAisFsmInfo->rJoinReqTime)); + + /* 4 <2> clear previous pending connection request and insert new one */ + if (ucReasonOfDisconnect == DISCONNECT_REASON_CODE_DEAUTHENTICATED || + ucReasonOfDisconnect == DISCONNECT_REASON_CODE_DISASSOCIATED) { + struct STA_RECORD *prSta = prAisFsmInfo->prTargetStaRec; + struct BSS_DESC *prBss = prAisFsmInfo->prTargetBssDesc; + + if (prSta && prBss) { + struct AIS_BLACKLIST_ITEM *blk = + aisAddBlacklist(prAdapter, prBss); + + if (blk) { + blk->u2DeauthReason = prSta->u2ReasonCode; + blk->fgDeauthLastTime = TRUE; + } + } + } + + /* to support user space triggered roaming */ + if (ucReasonOfDisconnect == DISCONNECT_REASON_CODE_ROAMING && + prAisFsmInfo->eCurrentState != AIS_STATE_DISCONNECTING) { +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE + cnmTimerStopTimer(prAdapter, + &prAisFsmInfo->rSecModeChangeTimer); +#endif + prAisBssInfo->ucReasonOfDisconnect = ucReasonOfDisconnect; + if (prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR) { + /* 1. release channel */ + aisFsmReleaseCh(prAdapter, ucBssIndex); + /* 2.1 stop join timeout timer */ + cnmTimerStopTimer(prAdapter, + &prAisFsmInfo->rJoinTimeoutTimer); + aisFsmSteps(prAdapter, AIS_STATE_SEARCH, ucBssIndex); + } else { + aisFsmRemoveRoamingRequest(prAdapter, ucBssIndex); + aisFsmInsertRequest(prAdapter, + AIS_REQUEST_ROAMING_CONNECT, + ucBssIndex); + } + return; + } + /* Support AP Selection */ +#if CFG_SELECT_BSS_BASE_ON_MULTI_PARAM + scanGetCurrentEssChnlList(prAdapter, ucBssIndex); +#endif + /* end Support AP Selection */ + + aisFsmClearRequest(prAdapter, AIS_REQUEST_RECONNECT, ucBssIndex); + if (ucReasonOfDisconnect == DISCONNECT_REASON_CODE_NEW_CONNECTION || + ucReasonOfDisconnect == DISCONNECT_REASON_CODE_REASSOCIATION || + ucReasonOfDisconnect == DISCONNECT_REASON_CODE_ROAMING) + aisFsmInsertRequestToHead(prAdapter, + AIS_REQUEST_RECONNECT, ucBssIndex); + + if (prAisFsmInfo->eCurrentState != AIS_STATE_DISCONNECTING) { + if (ucReasonOfDisconnect != + DISCONNECT_REASON_CODE_REASSOCIATION) { + /* 4 <3> invoke abort handler */ + aisFsmStateAbort(prAdapter, ucReasonOfDisconnect, + fgDelayIndication, ucBssIndex); + } else { + /* 1. release channel */ + aisFsmReleaseCh(prAdapter, ucBssIndex); + /* 2.1 stop join timeout timer */ + cnmTimerStopTimer(prAdapter, + &prAisFsmInfo->rJoinTimeoutTimer); + + prAisBssInfo->ucReasonOfDisconnect = + ucReasonOfDisconnect; + aisFsmSteps(prAdapter, AIS_STATE_IDLE, ucBssIndex); + } + } +} /* 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 struct ADAPTER *prAdapter, + uint8_t ucReasonOfDisconnect, u_int8_t fgDelayIndication, + uint8_t ucBssIndex) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prAisBssInfo; + struct CONNECTION_SETTINGS *prConnSettings; + u_int8_t fgIsCheckConnected; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + + /* XXX: The wlan0 may has been changed to AP mode. */ + if (prAisBssInfo == NULL) + return; + + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + fgIsCheckConnected = FALSE; + + DBGLOG(AIS, STATE, + "[%d] aisFsmStateAbort DiscReason[%d], CurState[%d], delayIndi[%d]\n", + ucBssIndex, ucReasonOfDisconnect, + prAisFsmInfo->eCurrentState, fgDelayIndication); + + /* 4 <1> Save information of Abort Message and then free memory. */ + prAisBssInfo->ucReasonOfDisconnect = ucReasonOfDisconnect; + if (prAisBssInfo->eConnectionState == MEDIA_STATE_CONNECTED && + prAisFsmInfo->eCurrentState != AIS_STATE_DISCONNECTING && + ucReasonOfDisconnect != DISCONNECT_REASON_CODE_REASSOCIATION && + ucReasonOfDisconnect != DISCONNECT_REASON_CODE_ROAMING) + wmmNotifyDisconnected(prAdapter, ucBssIndex); + + + if (fgDelayIndication) { + uint8_t p2p = cnmP2pIsActive(prAdapter); + uint8_t join = timerPendingTimer( + &prAisFsmInfo->rJoinTimeoutTimer); + + if (p2p || join) { + fgDelayIndication = FALSE; + DBGLOG(AIS, INFO, + "delay indication not allowed due to p2p=%d, join=%d", + p2p, join); + } + } + + /* 4 <2> Abort current job. */ + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_IDLE: + case AIS_STATE_SEARCH: + case AIS_STATE_JOIN_FAILURE: + 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_ONLINE_SCAN: + fgIsCheckConnected = TRUE; + case AIS_STATE_SCAN: + /* Do abort SCAN */ + aisFsmStateAbort_SCAN(prAdapter, ucBssIndex); + break; + case AIS_STATE_LOOKING_FOR: + /* Do abort SCAN */ + aisFsmStateAbort_SCAN(prAdapter, ucBssIndex); + + /* in case roaming is triggered */ + fgIsCheckConnected = TRUE; + break; + + case AIS_STATE_REQ_CHANNEL_JOIN: + /* Release channel to CNM */ + aisFsmReleaseCh(prAdapter, ucBssIndex); + + /* in case roaming is triggered */ + fgIsCheckConnected = TRUE; + break; + + case AIS_STATE_JOIN: + /* Do abort JOIN */ + aisFsmStateAbort_JOIN(prAdapter, ucBssIndex); + + /* 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, ucBssIndex); + break; +#endif /* CFG_SUPPORT_ADHOC */ + case AIS_STATE_NORMAL_TR: + fgIsCheckConnected = TRUE; + break; + + case AIS_STATE_DISCONNECTING: + /* Do abort NORMAL_TR */ + aisFsmStateAbort_NORMAL_TR(prAdapter, ucBssIndex); + + break; + + case AIS_STATE_REQ_REMAIN_ON_CHANNEL: + /* release channel */ + aisFsmReleaseCh(prAdapter, ucBssIndex); + break; + + case AIS_STATE_REMAIN_ON_CHANNEL: + case AIS_STATE_OFF_CHNL_TX: + fgIsCheckConnected = TRUE; + /* 1. release channel */ + aisFsmReleaseCh(prAdapter, ucBssIndex); + + /* 2. stop channel timeout timer */ + cnmTimerStopTimer(prAdapter, + &prAisFsmInfo->rChannelTimeoutTimer); + + break; + + default: + break; + } + + if (fgIsCheckConnected + && (prAisBssInfo->eConnectionState == + MEDIA_STATE_CONNECTED)) { + + /* switch into DISCONNECTING state for sending DEAUTH + * if necessary + */ + if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE && + (prAisBssInfo->ucReasonOfDisconnect == + DISCONNECT_REASON_CODE_NEW_CONNECTION || + prAisBssInfo->ucReasonOfDisconnect == + DISCONNECT_REASON_CODE_LOCALLY) + && prAisBssInfo->prStaRecOfAP + && prAisBssInfo->prStaRecOfAP->fgIsInUse) { + aisFsmSteps(prAdapter, AIS_STATE_DISCONNECTING, + ucBssIndex); + + return; + } + /* Do abort NORMAL_TR */ + aisFsmStateAbort_NORMAL_TR(prAdapter, ucBssIndex); + } + rrmFreeMeasurementResources(prAdapter, ucBssIndex); + aisFsmDisconnect(prAdapter, fgDelayIndication, ucBssIndex); + + 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 struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_SAA_FSM_COMP *prJoinCompMsg; + struct AIS_FSM_INFO *prAisFsmInfo; + enum ENUM_AIS_STATE eNextState; + struct SW_RFB *prAssocRspSwRfb; + struct STA_RECORD *prStaRec; + uint8_t ucBssIndex = 0; + + DEBUGFUNC("aisFsmRunEventJoinComplete()"); + + prJoinCompMsg = (struct MSG_SAA_FSM_COMP *)prMsgHdr; + prAssocRspSwRfb = prJoinCompMsg->prSwRfb; + prStaRec = prJoinCompMsg->prStaRec; + if (prStaRec) + ucBssIndex = prStaRec->ucBssIndex; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + + eNextState = prAisFsmInfo->eCurrentState; + + /* Check State and SEQ NUM */ + if (prAisFsmInfo->eCurrentState == AIS_STATE_JOIN) { + /* Check SEQ NUM */ + if (prJoinCompMsg->ucSeqNum == prAisFsmInfo->ucSeqNumOfReqMsg) + eNextState = + aisFsmJoinCompleteAction(prAdapter, prMsgHdr); + else { + eNextState = AIS_STATE_JOIN_FAILURE; + DBGLOG(AIS, WARN, + "SEQ NO of AIS JOIN COMP MSG is not matched.\n"); + } + } + + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState, ucBssIndex); + + if (prAssocRspSwRfb) + nicRxReturnRFB(prAdapter, prAssocRspSwRfb); + + cnmMemFree(prAdapter, prMsgHdr); +} /* end of aisFsmRunEventJoinComplete() */ + +enum ENUM_AIS_STATE aisFsmJoinCompleteAction(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_SAA_FSM_COMP *prJoinCompMsg; + struct AIS_FSM_INFO *prAisFsmInfo; + struct ROAMING_INFO *roam; + enum ENUM_AIS_STATE eNextState; + struct STA_RECORD *prStaRec; + struct SW_RFB *prAssocRspSwRfb; + struct BSS_INFO *prAisBssInfo; + OS_SYSTIME rCurrentTime; + struct CONNECTION_SETTINGS *prConnSettings; + uint8_t ucBssIndex = 0; + + DEBUGFUNC("aisFsmJoinCompleteAction()"); + + GET_CURRENT_SYSTIME(&rCurrentTime); + + prJoinCompMsg = (struct MSG_SAA_FSM_COMP *)prMsgHdr; + prStaRec = prJoinCompMsg->prStaRec; + prAssocRspSwRfb = prJoinCompMsg->prSwRfb; + + ucBssIndex = prStaRec->ucBssIndex; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + eNextState = prAisFsmInfo->eCurrentState; + roam = aisGetRoamingInfo(prAdapter, ucBssIndex); + + do { + /* 4 <1> JOIN was successful */ + if (prJoinCompMsg->rJoinStatus == WLAN_STATUS_SUCCESS) { +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE + prConnSettings->fgSecModeChangeStartTimer = FALSE; +#endif + + /* 1. Reset retry count */ + prAisFsmInfo->ucConnTrialCount = 0; + + /* Completion of roaming */ + if (prAisBssInfo->eConnectionState == + 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 { + kalResetStats( + wlanGetNetDev( + prAdapter->prGlueInfo, + ucBssIndex)); + + /* 4 <1.1> Change FW's Media State + * immediately. + */ + aisChangeMediaState(prAisBssInfo, + 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) && + (prAisBssInfo->prStaRecOfAP->ucBssIndex == + prAisBssInfo->ucBssIndex)) { + + cnmStaRecChangeState(prAdapter, + prAisBssInfo->prStaRecOfAP, + STA_STATE_1); + cnmStaRecFree(prAdapter, + prAisBssInfo->prStaRecOfAP); + } + + /* For temp solution, need to refine */ + /* 4 <1.4> Update BSS_INFO_T */ + aisUpdateBssInfoForJOIN(prAdapter, prStaRec, + prAssocRspSwRfb); + + /* 4 <1.3> Activate current AP's STA_RECORD_T + * in Driver. + */ + cnmStaRecChangeState(prAdapter, prStaRec, + STA_STATE_3); + + /* 4 <1.5> Update RSSI if necessary */ + nicUpdateRSSI(prAdapter, + prAisBssInfo->ucBssIndex, + (int8_t) (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, + MEDIA_STATE_CONNECTED, + FALSE, + ucBssIndex); + + if (prAdapter->rWifiVar.ucTpTestMode == + ENUM_TP_TEST_MODE_THROUGHPUT) + nicEnterTPTestMode(prAdapter, + TEST_MODE_THROUGHPUT); + else if (prAdapter->rWifiVar.ucTpTestMode == + ENUM_TP_TEST_MODE_SIGMA_AC_N_PMF) + nicEnterTPTestMode(prAdapter, + TEST_MODE_SIGMA_AC_N_PMF); + else if (prAdapter->rWifiVar.ucTpTestMode == + ENUM_TP_TEST_MODE_SIGMA_WMM_PS) + nicEnterTPTestMode(prAdapter, + TEST_MODE_SIGMA_WMM_PS); + } + +#if CFG_SUPPORT_ROAMING + /* if roaming fsm is monitoring old AP, abort it*/ + if (roam->eCurrentState >= ROAMING_STATE_DECISION) + roamingFsmRunEventAbort(prAdapter, ucBssIndex); + + /* if user space roaming is enabled, we should + * disable driver/fw roaming + */ + if (prConnSettings->eConnectionPolicy != + CONNECT_BY_BSSID && roam->fgDrvRoamingAllow) { + prConnSettings->eConnectionPolicy = + CONNECT_BY_SSID_BEST_RSSI; + roamingFsmRunEventStart(prAdapter, ucBssIndex); + } +#endif /* CFG_SUPPORT_ROAMING */ + if (aisFsmIsRequestPending + (prAdapter, AIS_REQUEST_ROAMING_CONNECT, + FALSE, ucBssIndex) == FALSE) + prAisFsmInfo->rJoinReqTime = 0; + + /* remove all deauthing AP from blacklist */ + aisRemoveDeauthBlacklist(prAdapter); + prAisFsmInfo->ucJoinFailCntAfterScan = 0; + +#if CFG_SUPPORT_802_11K + aisResetNeighborApList(prAdapter, ucBssIndex); + if (prAisFsmInfo->prTargetBssDesc->aucRrmCap[0] & + BIT(RRM_CAP_INFO_NEIGHBOR_REPORT_BIT)) + aisSendNeighborRequest(prAdapter, + ucBssIndex); +#endif + + /* 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, + ucBssIndex) == FALSE) { + struct BSS_DESC *prBssDesc; + struct PARAM_SSID rSsid; + struct CONNECTION_SETTINGS *prConnSettings; + + prConnSettings = + aisGetConnSettings(prAdapter, + ucBssIndex); + prBssDesc = prAisFsmInfo->prTargetBssDesc; + + /* 1. Increase Failure Count */ + prStaRec->ucJoinFailureCount++; + + /* 2. release channel */ + aisFsmReleaseCh(prAdapter, ucBssIndex); + + /* 3.1 stop join timeout timer */ + cnmTimerStopTimer(prAdapter, + &prAisFsmInfo->rJoinTimeoutTimer); + + /* Support AP Selection */ + prAisFsmInfo->ucJoinFailCntAfterScan++; + + kalMemZero(&rSsid, sizeof(struct PARAM_SSID)); + if (prBssDesc) + COPY_SSID(rSsid.aucSsid, + rSsid.u4SsidLen, + prBssDesc->aucSSID, + prBssDesc->ucSSIDLen); + else + COPY_SSID(rSsid.aucSsid, + rSsid.u4SsidLen, + prConnSettings->aucSSID, + prConnSettings->ucSSIDLen); + + prBssDesc = + scanSearchBssDescByBssidAndSsid(prAdapter, + prStaRec->aucMacAddr, + TRUE, + &rSsid); + + if (prBssDesc == NULL) { + eNextState = AIS_STATE_JOIN_FAILURE; + DBGLOG(AIS, ERROR, + "Can't get bss descriptor\n"); + break; + } + + DBGLOG(AIS, INFO, + "ucJoinFailureCount=%d %d, Status=%d Reason=%d, eConnectionState=%d", + prStaRec->ucJoinFailureCount, + prBssDesc->ucJoinFailureCount, + prStaRec->u2StatusCode, + prStaRec->u2ReasonCode, + prAisBssInfo->eConnectionState); + + prBssDesc->u2JoinStatus = + prStaRec->u2StatusCode; + prBssDesc->ucJoinFailureCount++; + if (prBssDesc->ucJoinFailureCount >= + SCN_BSS_JOIN_FAIL_THRESOLD || + scanApOverload(prStaRec->u2StatusCode, + prStaRec->u2ReasonCode)) { + /* Support AP Selection */ + aisAddBlacklist(prAdapter, prBssDesc); + + GET_CURRENT_SYSTIME + (&prBssDesc->rJoinFailTime); + DBGLOG(AIS, INFO, + "Bss " MACSTR + " join fail %d times, temp disable it at time: %u\n", + MAC2STR(prBssDesc->aucBSSID), + prBssDesc->ucJoinFailureCount, + prBssDesc->rJoinFailTime); + } + + if (prStaRec->u2StatusCode + == STATUS_INVALID_PMKID) { + struct AIS_BLACKLIST_ITEM *prBlackList = + aisAddBlacklist(prAdapter, + prBssDesc); + if (prBlackList) { + prBlackList->u2AuthStatus = + prStaRec->u2StatusCode; + DBGLOG(AIS, INFO, + "Add blacklist due to STATUS_INVALID_PMKID\n"); + } + } + + /* Support AP Selection */ + if (prBssDesc->prBlack) + prBssDesc->prBlack->u2AuthStatus = + prStaRec->u2StatusCode; + + if (prBssDesc) + prBssDesc->fgIsConnecting = FALSE; + + /* 3.3 Free STA-REC */ + if (prStaRec != prAisBssInfo->prStaRecOfAP) + cnmStaRecFree(prAdapter, prStaRec); + + if (prAisBssInfo->eConnectionState == + MEDIA_STATE_CONNECTED || + prStaRec->u2StatusCode == + STATUS_CODE_ASSOC_REJECTED_TEMPORARILY) { + struct PARAM_SSID rSsid; + + /* roaming fail count and time */ + prAdapter->prGlueInfo->u4RoamFailCnt++; + prAdapter->prGlueInfo->u8RoamFailTime = + sched_clock(); +#if CFG_SUPPORT_ROAMING + eNextState = + AIS_STATE_WAIT_FOR_NEXT_SCAN; +#endif /* CFG_SUPPORT_ROAMING */ + + if (prAisBssInfo->prStaRecOfAP) + prAisBssInfo-> + prStaRecOfAP->fgIsTxAllowed + = TRUE; + + COPY_SSID(rSsid.aucSsid, + rSsid.u4SsidLen, + prAisBssInfo->aucSSID, + prAisBssInfo->ucSSIDLen); + prAisFsmInfo->prTargetBssDesc = + scanSearchBssDescByBssidAndSsid + (prAdapter, prAisBssInfo->aucBSSID, + TRUE, &rSsid); + prAisFsmInfo->prTargetStaRec = + prAisBssInfo->prStaRecOfAP; + if (!prAisFsmInfo->prTargetBssDesc) + DBGLOG(AIS, ERROR, + "Can't retrieve target bss descriptor\n"); + } else if (prAisFsmInfo->rJoinReqTime != 0 + && CHECK_FOR_TIMEOUT(rCurrentTime, + prAisFsmInfo->rJoinReqTime, + SEC_TO_SYSTIME + (AIS_JOIN_TIMEOUT))) { + /* 4.a temrminate join operation */ + eNextState = AIS_STATE_JOIN_FAILURE; + } else if (prAisFsmInfo->rJoinReqTime != 0 + && prBssDesc->ucJoinFailureCount >= + SCN_BSS_JOIN_FAIL_THRESOLD + && prBssDesc->u2JoinStatus) { + /* AP reject STA for + * STATUS_CODE_ASSOC_DENIED_AP_OVERLOAD + * , or AP block STA + */ + eNextState = AIS_STATE_JOIN_FAILURE; + } else { + /* 4.b send reconnect request */ + aisFsmInsertRequest(prAdapter, + AIS_REQUEST_RECONNECT, + ucBssIndex); + + eNextState = AIS_STATE_IDLE; + } + } + } + } while (0); + return eNextState; +} + +#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 struct ADAPTER *prAdapter, uint8_t ucBssIndex) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + + do { + /* Check State */ + if (prAisFsmInfo->eCurrentState == AIS_STATE_IBSS_ALONE) + aisUpdateBssInfoForCreateIBSS(prAdapter, ucBssIndex); + + } while (FALSE); +} /* end of aisFsmCreateIBSS() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will handle the Grant Msg of IBSS Merge which was + * sent by CNM to indicate that channel was changed for merging IBSS. + * + * @param[in] prAdapter Pointer of ADAPTER_T + * @param[in] prStaRec Pointer of STA_RECORD_T for merge + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisFsmMergeIBSS(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + enum ENUM_AIS_STATE eNextState; + struct BSS_INFO *prAisBssInfo; + uint8_t ucBssIndex = 0; + + ucBssIndex = prStaRec->ucBssIndex; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + + do { + + eNextState = prAisFsmInfo->eCurrentState; + + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_IBSS_MERGE: + { + struct BSS_DESC *prBssDesc; + + /* 4 <1.1> Change FW's Media State + * immediately. + */ + aisChangeMediaState(prAisBssInfo, + MEDIA_STATE_CONNECTED); + + /* 4 <1.2> Deactivate previous Peers' + * STA_RECORD_T in Driver if have. + */ + bssInitializeClientList(prAdapter, + prAisBssInfo); + + /* 4 <1.3> Unmark connection flag of previous + * BSS_DESC_T. + */ + prBssDesc = + scanSearchBssDescByBssid(prAdapter, + prAisBssInfo->aucBSSID); + if (prBssDesc != NULL) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = FALSE; + } + /* 4 <1.4> Add Peers' STA_RECORD_T to + * Client List + */ + bssAddClient(prAdapter, prAisBssInfo, prStaRec); + + /* 4 <1.5> Activate current Peer's STA_RECORD_T + * in Driver. + */ + cnmStaRecChangeState(prAdapter, prStaRec, + STA_STATE_3); + prStaRec->fgIsMerging = FALSE; + + /* 4 <1.6> Update BSS_INFO_T */ + aisUpdateBssInfoForMergeIBSS(prAdapter, + prStaRec); + + /* 4 <1.7> Enable other features */ + + /* 4 <1.8> Indicate Connected Event to Host + * immediately. + */ + aisIndicationOfMediaStateToHost(prAdapter, + MEDIA_STATE_CONNECTED, + FALSE, + ucBssIndex); + + /* 4 <1.9> Set the Next State of AIS FSM */ + eNextState = AIS_STATE_NORMAL_TR; + + /* 4 <1.10> Release channel privilege */ + aisFsmReleaseCh(prAdapter, ucBssIndex); + +#if CFG_SLT_SUPPORT + prAdapter->rWifiVar.rSltInfo.prPseudoStaRec = + prStaRec; +#endif + } + break; + + default: + break; + } + + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState, ucBssIndex); + + } while (FALSE); +} /* end of aisFsmMergeIBSS() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will handle the Notification of existing IBSS was found + * from SCN. + * + * @param[in] prMsgHdr Message of Notification of an IBSS was present. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisFsmRunEventFoundIBSSPeer(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_AIS_IBSS_PEER_FOUND *prAisIbssPeerFoundMsg; + struct AIS_FSM_INFO *prAisFsmInfo; + enum ENUM_AIS_STATE eNextState; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prAisBssInfo; + struct BSS_DESC *prBssDesc; + u_int8_t fgIsMergeIn; + uint8_t ucBssIndex = 0; + + prAisIbssPeerFoundMsg = (struct MSG_AIS_IBSS_PEER_FOUND *)prMsgHdr; + ucBssIndex = prAisIbssPeerFoundMsg->ucBssIndex; + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + + prStaRec = prAisIbssPeerFoundMsg->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(prAisBssInfo, + MEDIA_STATE_CONNECTED); + + /* 4 <1.2> Add Peers' STA_RECORD_T to + * Client List + */ + bssAddClient(prAdapter, prAisBssInfo, prStaRec); + +#if CFG_SLT_SUPPORT + /* 4 <1.3> Mark connection flag of + * BSS_DESC_T. + */ + prBssDesc = + scanSearchBssDescByTA(prAdapter, + prStaRec->aucMacAddr); + + if (prBssDesc != NULL) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + } + + /* 4 <1.4> Activate current Peer's + * STA_RECORD_T in Driver. + */ + /* TODO(Kevin): TBD */ + prStaRec->fgIsQoS = TRUE; +#else + /* 4 <1.3> Mark connection flag + * of BSS_DESC_T. + */ + prBssDesc = + scanSearchBssDescByBssid(prAdapter, + prAisBssInfo->aucBSSID); + + if (prBssDesc != NULL) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + } + + /* 4 <1.4> Activate current Peer's STA_RECORD_T + * in Driver. + */ + /* TODO(Kevin): TBD */ + prStaRec->fgIsQoS = FALSE; + +#endif + + cnmStaRecChangeState(prAdapter, prStaRec, + STA_STATE_3); + prStaRec->fgIsMerging = FALSE; + + /* 4 <1.6> sync. to firmware */ + nicUpdateBss(prAdapter, + prAisBssInfo->ucBssIndex); + + /* 4 <1.7> Indicate Connected Event to Host + * immediately. + */ + aisIndicationOfMediaStateToHost(prAdapter, + MEDIA_STATE_CONNECTED, + FALSE, + ucBssIndex); + + /* 4 <1.8> indicate PM for connected */ + nicPmIndicateBssConnected(prAdapter, + prAisBssInfo->ucBssIndex); + + /* 4 <1.9> Set the Next State of AIS FSM */ + eNextState = AIS_STATE_NORMAL_TR; + + /* 4 <1.10> Release channel privilege */ + aisFsmReleaseCh(prAdapter, ucBssIndex); + } + /* 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 + */ + bssAddClient(prAdapter, prAisBssInfo, prStaRec); + +#if CFG_SLT_SUPPORT + /* 4 <3.2> Activate current Peer's STA_RECORD_T + * in Driver. + */ + /* TODO(Kevin): TBD */ + prStaRec->fgIsQoS = TRUE; +#else + /* 4 <3.2> Activate current Peer's STA_RECORD_T + * in Driver. + */ + /* TODO(Kevin): TBD */ + prStaRec->fgIsQoS = FALSE; +#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, ucBssIndex); +} /* 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 struct ADAPTER *prAdapter, + enum ENUM_PARAM_MEDIA_STATE eConnectionState, + u_int8_t fgDelayIndication, + uint8_t ucBssIndex) +{ + struct EVENT_CONNECTION_STATUS rEventConnStatus; + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_INFO *prAisBssInfo; + struct AIS_FSM_INFO *prAisFsmInfo; + struct ROAMING_INFO *prRoamingFsmInfo; + + DEBUGFUNC("aisIndicationOfMediaStateToHost()"); + + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prRoamingFsmInfo = aisGetRoamingInfo(prAdapter, ucBssIndex); + + DBGLOG(AIS, LOUD, + "AIS%d indicate Media State to Host Current State [%d]\n", + ucBssIndex, + prAisBssInfo->eConnectionState); + + /* 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. + */ + DBGLOG(AIS, INFO, + "[%d] Current state: %d, connection state indicated: %d\n", + ucBssIndex, + prAisFsmInfo->eCurrentState, + prAisBssInfo->eConnectionStateIndicated); + + if (prAisBssInfo->eConnectionState == MEDIA_STATE_DISCONNECTED && + /* if receive DEAUTH in JOIN state, report disconnect*/ + !(prAisBssInfo->ucReasonOfDisconnect == + DISCONNECT_REASON_CODE_DEAUTHENTICATED && + prAisFsmInfo->eCurrentState == AIS_STATE_JOIN)) { + if (prAisBssInfo->eConnectionStateIndicated == eConnectionState) + return; + } + + if (!fgDelayIndication) { + /* 4 <0> Cancel Delay Timer */ + prAisFsmInfo->u4PostponeIndStartTime = 0; + + /* 4 <1> Fill EVENT_CONNECTION_STATUS */ + rEventConnStatus.ucMediaStatus = (uint8_t) eConnectionState; + + if (eConnectionState == MEDIA_STATE_CONNECTED) { + rEventConnStatus.ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_RESERVED; + + if (prAisBssInfo->eCurrentOPMode == + OP_MODE_INFRASTRUCTURE) { + rEventConnStatus.ucInfraMode = + (uint8_t) NET_TYPE_INFRA; + rEventConnStatus.u2AID = + prAisBssInfo->u2AssocId; + rEventConnStatus.u2ATIMWindow = 0; + } else if (prAisBssInfo->eCurrentOPMode == + OP_MODE_IBSS) { + rEventConnStatus.ucInfraMode = + (uint8_t) NET_TYPE_IBSS; + rEventConnStatus.u2AID = 0; + rEventConnStatus.u2ATIMWindow = + prAisBssInfo->u2ATIMWindow; + } + + 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 = + (uint8_t) PARAM_NETWORK_TYPE_DS; + break; + + case PHY_TYPE_ERP_INDEX: + rEventConnStatus.ucNetworkType = + (uint8_t) PARAM_NETWORK_TYPE_OFDM24; + break; + + case PHY_TYPE_OFDM_INDEX: + rEventConnStatus.ucNetworkType = + (uint8_t) PARAM_NETWORK_TYPE_OFDM5; + break; + + default: + rEventConnStatus.ucNetworkType = + (uint8_t) PARAM_NETWORK_TYPE_DS; + break; + } + } else { + rEventConnStatus.ucReasonOfDisconnect = + prAisBssInfo->ucReasonOfDisconnect; + } + + /* 4 <2> Indication */ + nicMediaStateChange(prAdapter, + prAisBssInfo->ucBssIndex, + &rEventConnStatus); + prAisBssInfo->eConnectionStateIndicated = eConnectionState; + if (eConnectionState == MEDIA_STATE_DISCONNECTED) { + aisRemoveDeauthBlacklist(prAdapter); + prAisFsmInfo->prTargetBssDesc = NULL; + prAisFsmInfo->prTargetStaRec = NULL; + prAisFsmInfo->ucConnTrialCount = 0; + prAdapter->rAddRoamScnChnl.ucChannelListNum = 0; + prRoamingFsmInfo->eReason = ROAMING_REASON_POOR_RCPI; +#if CFG_SUPPORT_NCHO + wlanNchoInit(prAdapter, TRUE); +#endif + } + } else { + DBGLOG(AIS, INFO, + "Postpone the indication of Disconnect for %d seconds\n", + prConnSettings->ucDelayTimeOfDisconnectEvent); + + prAisFsmInfo->u4PostponeIndStartTime = kalGetTimeTick(); + } +} /* 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 struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + struct BSS_INFO *prAisBssInfo; + struct CONNECTION_SETTINGS *prConnSettings; + struct AIS_FSM_INFO *prAisFsmInfo; + bool fgFound = TRUE; + bool fgIsPostponeTimeout; + enum ENUM_PARAM_CONNECTION_POLICY policy; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + /* firstly, check if we have started postpone indication. + ** otherwise, give a chance to do join before indicate to host + **/ + if (prAisFsmInfo->u4PostponeIndStartTime == 0) + return; + + /* if we're in req channel/join/search state, + * don't report disconnect. + */ + if (prAisFsmInfo->eCurrentState == AIS_STATE_JOIN || + prAisFsmInfo->eCurrentState == AIS_STATE_SEARCH || + prAisFsmInfo->eCurrentState == AIS_STATE_REQ_CHANNEL_JOIN) + return; + + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + fgIsPostponeTimeout = !aisFsmIsInProcessPostpone(prAdapter, ucBssIndex); + policy = prConnSettings->eConnectionPolicy; + + DBGLOG(AIS, EVENT, "policy %d, timeout %d, trial %d, limit %d\n", + policy, fgIsPostponeTimeout, prAisFsmInfo->ucConnTrialCount, + prAisFsmInfo->ucConnTrialCountLimit); + + /* only retry connect once when beacon timeout */ + if (policy != CONNECT_BY_BSSID && !fgIsPostponeTimeout && + !(prAisFsmInfo->ucConnTrialCount > + prAisFsmInfo->ucConnTrialCountLimit)) { + DBGLOG(AIS, INFO, + "DelayTimeOfDisconnect, don't report disconnect\n"); + return; + } + + /* 4 <2> Remove all connection request */ + while (fgFound) + fgFound = aisFsmClearRequest(prAdapter, + AIS_REQUEST_RECONNECT, ucBssIndex); + if (prAisFsmInfo->eCurrentState == AIS_STATE_LOOKING_FOR) + prAisFsmInfo->eCurrentState = AIS_STATE_IDLE; + + /* 4 <3> Indicate Disconnected Event to Host immediately. */ + aisIndicationOfMediaStateToHost(prAdapter, + MEDIA_STATE_DISCONNECTED, FALSE, + ucBssIndex); +} /* 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 struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + struct SW_RFB *prAssocRspSwRfb) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prAisBssInfo; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecBssInfo; + struct CONNECTION_SETTINGS *prConnSettings; + struct WLAN_ASSOC_RSP_FRAME *prAssocRspFrame; + struct BSS_DESC *prBssDesc; + uint16_t u2IELength; + uint8_t *pucIE; + struct PARAM_SSID rSsid; + uint8_t ucBssIndex = 0; + + DEBUGFUNC("aisUpdateBssInfoForJOIN()"); + + ucBssIndex = prStaRec->ucBssIndex; + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + prAisSpecBssInfo = aisGetAisSpecBssInfo(prAdapter, ucBssIndex); + prAssocRspFrame = + (struct WLAN_ASSOC_RSP_FRAME *)prAssocRspSwRfb->pvHeader; + + DBGLOG(AIS, INFO, + "[%d] Update AIS_BSS_INFO_T and apply settings to MAC\n", + ucBssIndex); + + /* 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 */ + /* Use AP's Cap Info as BSS Cap Info */ + prAisBssInfo->u2CapInfo = prStaRec->u2CapInfo; + + if (prAisBssInfo->u2CapInfo & CAP_INFO_SHORT_PREAMBLE) + prAisBssInfo->fgIsShortPreambleAllowed = TRUE; + else + prAisBssInfo->fgIsShortPreambleAllowed = FALSE; + +#if CFG_SUPPORT_TDLS + prAisBssInfo->fgTdlsIsProhibited = prStaRec->fgTdlsIsProhibited; + prAisBssInfo->fgTdlsIsChSwProhibited = prStaRec->fgTdlsIsChSwProhibited; +#endif /* CFG_SUPPORT_TDLS */ + + /* 4 <2.3> Setup PHY Attributes and Basic Rate Set/Operational + * Rate Set + */ + prAisBssInfo->ucPhyTypeSet = prStaRec->ucDesiredPhyTypeSet; + + prAisBssInfo->ucNonHTBasicPhyType = prStaRec->ucNonHTBasicPhyType; + + prAisBssInfo->u2OperationalRateSet = prStaRec->u2OperationalRateSet; + prAisBssInfo->u2BSSBasicRateSet = prStaRec->u2BSSBasicRateSet; + + nicTxUpdateBssDefaultRate(prAisBssInfo); + + /* 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 = + (uint16_t) ((prAssocRspSwRfb->u2PacketLen - + prAssocRspSwRfb->u2HeaderLen) - + (OFFSET_OF(struct WLAN_ASSOC_RSP_FRAME, 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 = prAisFsmInfo->prTargetBssDesc; + if (prBssDesc) + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + else + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, + prConnSettings->aucSSID, prConnSettings->ucSSIDLen); + + prBssDesc = + scanSearchBssDescByBssidAndSsid(prAdapter, + prAssocRspFrame->aucBSSID, TRUE, + &rSsid); + if (prBssDesc) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + prBssDesc->ucJoinFailureCount = 0; + + aisRemoveBlackList(prAdapter, prBssDesc); + /* 4 <4.1> Setup MIB for current BSS */ + prAisBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval; +#if (CFG_SUPPORT_802_11V_MBSSID == 1) + prAisBssInfo->ucMaxBSSIDIndicator = + prBssDesc->ucMaxBSSIDIndicator; + prAisBssInfo->ucMBSSIDIndex = prBssDesc->ucMBSSIDIndex; +#endif + } + + /* NOTE: Defer ucDTIMPeriod updating to when beacon is received + * after connection + */ + prAisBssInfo->ucDTIMPeriod = 0; + prAisBssInfo->fgTIMPresent = TRUE; + prAisBssInfo->u2ATIMWindow = 0; + + prAisBssInfo->ucBeaconTimeoutCount = AIS_BEACON_TIMEOUT_COUNT_INFRA; + +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + prAisSpecBssInfo->ucRoamSkipTimes = ROAMING_ONE_AP_SKIP_TIMES; + prAisSpecBssInfo->fgGoodRcpiArea = FALSE; + prAisSpecBssInfo->fgPoorRcpiArea = FALSE; +#endif + + /* 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); + + secPostUpdateAddr(prAdapter, + aisGetAisBssInfo(prAdapter, ucBssIndex)); + + /* 4 <4.3> Sync with firmware for BSS-INFO */ + nicUpdateBss(prAdapter, ucBssIndex); + + /* 4 <4.4> *DEFER OPERATION* nicPmIndicateBssConnected() + * will be invoked + */ + /* inside scanProcessBeaconAndProbeResp() after 1st beacon + * is received + */ +} /* end of aisUpdateBssInfoForJOIN() */ + +#if CFG_SUPPORT_ADHOC +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will create an Ad-Hoc network and start sending + * Beacon Frames. + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisUpdateBssInfoForCreateIBSS(IN struct ADAPTER *prAdapter, + uint8_t ucBssIndex) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prAisBssInfo; + struct CONNECTION_SETTINGS *prConnSettings; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + + 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 = (struct STA_RECORD *)NULL; + prAisBssInfo->u2AssocId = 0; + + /* 4 <1.4> Setup Channel, Band and Phy Attributes */ + prAisBssInfo->ucPrimaryChannel = prConnSettings->ucAdHocChannelNum; + prAisBssInfo->eBand = prConnSettings->eAdHocBand; + + if (prAisBssInfo->eBand == BAND_2G4) { + /* Depend on eBand */ + prAisBssInfo->ucPhyTypeSet = + prAdapter-> + rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11BGN; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prAisBssInfo->ucConfigAdHocAPMode = AD_HOC_MODE_MIXED_11BG; + } else { + /* Depend on eBand */ + prAisBssInfo->ucPhyTypeSet = + prAdapter-> + rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11ANAC; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prAisBssInfo->ucConfigAdHocAPMode = AD_HOC_MODE_11A; + } + + /* 4 <1.5> Setup MIB for current BSS */ + prAisBssInfo->u2BeaconInterval = prConnSettings->u2BeaconPeriod; + prAisBssInfo->ucDTIMPeriod = 0; + prAisBssInfo->u2ATIMWindow = prConnSettings->u2AtimWindow; + + prAisBssInfo->ucBeaconTimeoutCount = AIS_BEACON_TIMEOUT_COUNT_ADHOC; + + if (prConnSettings->eEncStatus == ENUM_ENCRYPTION1_ENABLED || + prConnSettings->eEncStatus == ENUM_ENCRYPTION2_ENABLED || + prConnSettings->eEncStatus == ENUM_ENCRYPTION3_ENABLED) { + prAisBssInfo->fgIsProtection = TRUE; + } else { + prAisBssInfo->fgIsProtection = FALSE; + } + + /* 3 <2> Update BSS_INFO_T common part */ + ibssInitForAdHoc(prAdapter, prAisBssInfo); + /* 4 <2.1> Initialize client list */ + bssInitializeClientList(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, prAisBssInfo->ucBssIndex); + + /* 4 <3.3> enable beaconing */ + bssUpdateBeaconContent(prAdapter, prAisBssInfo->ucBssIndex); + + /* 4 <3.4> Update AdHoc PM parameter */ + nicPmIndicateBssCreated(prAdapter, prAisBssInfo->ucBssIndex); + + /* 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)); +} /* 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 struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prAisBssInfo; + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_DESC *prBssDesc; + uint8_t ucBssIndex = 0; + + ucBssIndex = prStaRec->ucBssIndex; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + + 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 = (struct STA_RECORD *)NULL; + prAisBssInfo->u2AssocId = 0; + } + /* 3 <2> Update BSS_INFO_T from STA_RECORD_T */ + /* 4 <2.1> Setup Capability */ + /* Use Peer's Cap Info as IBSS Cap Info */ + prAisBssInfo->u2CapInfo = prStaRec->u2CapInfo; + + 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. */ + /* Set to FALSE for AdHoc */ + prAisBssInfo->fgUseShortSlotTime = FALSE; + 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; + /* Support AP Selection */ + aisRemoveBlackList(prAdapter, prBssDesc); + + /* 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; + } + + /* 3 <5> Set MAC HW */ + /* 4 <5.1> Find Lowest Basic Rate Index for default TX Rate of MMPDU */ + nicTxUpdateBssDefaultRate(prAisBssInfo); + + /* 4 <5.2> Setup channel and bandwidth */ + rlmBssInitForAPandIbss(prAdapter, prAisBssInfo); + + /* 4 <5.3> use command packets to inform firmware */ + nicUpdateBss(prAdapter, prAisBssInfo->ucBssIndex); + + /* 4 <5.4> enable beaconing */ + bssUpdateBeaconContent(prAdapter, prAisBssInfo->ucBssIndex); + + /* 4 <5.5> Update AdHoc PM parameter */ + nicPmIndicateBssConnected(prAdapter, + prAisBssInfo->ucBssIndex); + + /* 3 <6> Set ACTIVE flag. */ + prAisBssInfo->fgIsBeaconActivated = TRUE; + prAisBssInfo->fgHoldSameBssidForIBSS = TRUE; +} /* end of aisUpdateBssInfoForMergeIBSS() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will validate the Rx Probe Request Frame and then return + * result to BSS to indicate if need to send the corresponding + * Probe Response Frame if the specified conditions were matched. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] prSwRfb Pointer to SW RFB data structure. + * @param[out] pu4ControlFlags Control flags for replying the Probe Response + * + * @retval TRUE Reply the Probe Response + * @retval FALSE Don't reply the Probe Response + */ +/*----------------------------------------------------------------------------*/ +u_int8_t aisValidateProbeReq(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint8_t ucBssIndex, + OUT uint32_t *pu4ControlFlags) +{ + struct WLAN_MAC_MGMT_HEADER *prMgtHdr; + struct BSS_INFO *prBssInfo; + struct IE_SSID *prIeSsid = (struct IE_SSID *)NULL; + uint8_t *pucIE; + uint16_t u2IELength; + uint16_t u2Offset = 0; + u_int8_t fgReplyProbeResp = FALSE; + + prBssInfo = aisGetAisBssInfo(prAdapter, + ucBssIndex); + + /* 4 <1> Parse Probe Req IE and Get IE ptr + * (SSID, Supported Rate IE, ...) + */ + prMgtHdr = (struct WLAN_MAC_MGMT_HEADER *)prSwRfb->pvHeader; + + u2IELength = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen; + pucIE = + (uint8_t *) ((unsigned long)prSwRfb->pvHeader + + prSwRfb->u2HeaderLen); + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (IE_ID(pucIE) == ELEM_ID_SSID) { + if ((!prIeSsid) && (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) + prIeSsid = (struct IE_SSID *)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 struct ADAPTER *prAdapter, + IN u_int8_t fgDelayIndication, IN uint8_t ucBssIndex) +{ + struct BSS_INFO *prAisBssInfo; + uint16_t u2ReasonCode = REASON_CODE_UNSPECIFIED; + struct BSS_DESC *prBssDesc = NULL; + struct AIS_FSM_INFO *prAisFsmInfo = NULL; + + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + +#if (CFG_SUPPORT_TWT == 1) + twtPlannerReset(prAdapter, prAisBssInfo); +#endif + +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE + cnmTimerStopTimer(prAdapter, + aisGetSecModeChangeTimer(prAdapter, ucBssIndex)); +#endif + nicPmIndicateBssAbort(prAdapter, prAisBssInfo->ucBssIndex); + +#if CFG_SUPPORT_ADHOC + if (prAisBssInfo->fgIsBeaconActivated) { + nicUpdateBeaconIETemplate(prAdapter, + IE_UPD_METHOD_DELETE_ALL, + prAisBssInfo->ucBssIndex, + 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 (prAisBssInfo->eConnectionState == MEDIA_STATE_CONNECTED) { + + { + if (prAdapter->rWifiVar.ucTpTestMode != + ENUM_TP_TEST_MODE_NORMAL) + nicEnterTPTestMode(prAdapter, TEST_MODE_NONE); + +#if 0 + if (prAdapter->rWifiVar.ucSigmaTestMode) + nicEnterTPTestMode(prAdapter, TEST_MODE_NONE); +#endif + } + /* for NO TIM IE case */ + if (!prAisBssInfo->fgTIMPresent) { + nicConfigPowerSaveProfile(prAdapter, + prAisBssInfo->ucBssIndex, + Param_PowerModeFast_PSP, + FALSE, PS_CALLER_NO_TIM); + } + + if (prAisBssInfo->prStaRecOfAP) { + u2ReasonCode = + prAisBssInfo->prStaRecOfAP->u2ReasonCode; + } + if (prAisBssInfo->ucReasonOfDisconnect == + DISCONNECT_REASON_CODE_RADIO_LOST || + prAisBssInfo->ucReasonOfDisconnect == + DISCONNECT_REASON_CODE_RADIO_LOST_TX_ERR) { + scanRemoveBssDescByBssid(prAdapter, + prAisBssInfo->aucBSSID); + + /* remove from scanning results as well */ + wlanClearBssInScanningResult(prAdapter, + prAisBssInfo->aucBSSID); + } else { + scanRemoveConnFlagOfBssDescByBssid(prAdapter, + prAisBssInfo->aucBSSID); + prBssDesc = aisGetTargetBssDesc(prAdapter, ucBssIndex); + if (prBssDesc) { + prBssDesc->fgIsConnected = FALSE; + prBssDesc->fgIsConnecting = FALSE; + } + } + + if (fgDelayIndication) { + struct ROAMING_INFO *roam = + aisGetRoamingInfo(prAdapter, ucBssIndex); + + /* + * There is a chance that roaming failed before + * beacon timeout, so reset trial count here to + * ensure the new reconnection runs correctly. + */ + prAisFsmInfo->ucConnTrialCount = 0; + + switch (prAisBssInfo->ucReasonOfDisconnect) { + case DISCONNECT_REASON_CODE_RADIO_LOST: + roam->eReason = ROAMING_REASON_BEACON_TIMEOUT; + prAisFsmInfo->ucConnTrialCountLimit = 2; + break; + case DISCONNECT_REASON_CODE_RADIO_LOST_TX_ERR: + roam->eReason = ROAMING_REASON_TX_ERR; + prAisFsmInfo->ucConnTrialCountLimit = 2; + break; + case DISCONNECT_REASON_CODE_DEAUTHENTICATED: + case DISCONNECT_REASON_CODE_DISASSOCIATED: + roam->eReason = ROAMING_REASON_SAA_FAIL; + prAisFsmInfo->ucConnTrialCountLimit = 1; + break; + default: + DBGLOG(AIS, ERROR, "wrong reason %d", + prAisBssInfo->ucReasonOfDisconnect); + } + aisFsmClearRequest(prAdapter, + AIS_REQUEST_RECONNECT, ucBssIndex); + aisFsmInsertRequest(prAdapter, + AIS_REQUEST_RECONNECT, ucBssIndex); + + if (prAisBssInfo->eCurrentOPMode != OP_MODE_IBSS) + prAisBssInfo->fgHoldSameBssidForIBSS = FALSE; + } else { + prAisBssInfo->fgHoldSameBssidForIBSS = FALSE; + } + } else { + prAisBssInfo->fgHoldSameBssidForIBSS = FALSE; + } + + /* 4 <4> Change Media State immediately. */ + if (prAisBssInfo->ucReasonOfDisconnect != + DISCONNECT_REASON_CODE_REASSOCIATION) { + aisChangeMediaState(prAisBssInfo, + MEDIA_STATE_DISCONNECTED); + + /* 4 <4.1> sync. with firmware */ + nicUpdateBss(prAdapter, prAisBssInfo->ucBssIndex); + prAisBssInfo->prStaRecOfAP = (struct STA_RECORD *)NULL; + } + +#if CFG_SUPPORT_ROAMING + roamingFsmRunEventAbort(prAdapter, ucBssIndex); + aisFsmRemoveRoamingRequest(prAdapter, ucBssIndex); +#endif /* CFG_SUPPORT_ROAMING */ + + /* 4 <6> Indicate Disconnected Event to Host */ + aisIndicationOfMediaStateToHost(prAdapter, + MEDIA_STATE_DISCONNECTED, + fgDelayIndication, + ucBssIndex); + + /* 4 <7> Trigger AIS FSM */ + aisFsmSteps(prAdapter, AIS_STATE_IDLE, ucBssIndex); +} /* end of aisFsmDisconnect() */ + +static void aisFsmRunEventScanDoneTimeOut(IN struct ADAPTER *prAdapter, + unsigned long ulParam) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct CONNECTION_SETTINGS *prConnSettings; + uint8_t ucBssIndex = (uint8_t) ulParam; + + DEBUGFUNC("aisFsmRunEventScanDoneTimeOut()"); + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + + DBGLOG(AIS, STATE, + "[%d] aisFsmRunEventScanDoneTimeOut Current[%d] Seq=%u\n", + ucBssIndex, + prAisFsmInfo->eCurrentState, prAisFsmInfo->ucSeqNumOfScanReq); + + prAdapter->u4HifDbgFlag |= DEG_HIF_DEFAULT_DUMP; + kalSetHifDbgEvent(prAdapter->prGlueInfo); + + /* try to stop scan in CONNSYS */ + aisFsmStateAbort_SCAN(prAdapter, ucBssIndex); +} /* end of aisFsmBGSleepTimeout() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will indicate an Event of "Background Scan Time-Out" + * to AIS FSM. + * @param[in] u4Param Unused timer parameter + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisFsmRunEventBGSleepTimeOut(IN struct ADAPTER *prAdapter, + unsigned long ulParamPtr) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + enum ENUM_AIS_STATE eNextState; + uint8_t ucBssIndex = (uint8_t) ulParamPtr; + + DEBUGFUNC("aisFsmRunEventBGSleepTimeOut()"); + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + + eNextState = prAisFsmInfo->eCurrentState; + + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_WAIT_FOR_NEXT_SCAN: + DBGLOG(AIS, LOUD, + "[%d] EVENT - SCAN TIMER: Idle End - Current Time = %u\n", + ucBssIndex, + kalGetTimeTick()); + + eNextState = AIS_STATE_LOOKING_FOR; + + SET_NET_PWR_STATE_ACTIVE(prAdapter, + ucBssIndex); + + break; + + default: + break; + } + + /* Call aisFsmSteps() when we are going to change AIS STATE */ + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState, ucBssIndex); +} /* 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 struct ADAPTER *prAdapter, + unsigned long ulParamPtr) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + enum ENUM_AIS_STATE eNextState; + uint8_t ucBssIndex = (uint8_t) ulParamPtr; + + DEBUGFUNC("aisFsmRunEventIbssAloneTimeOut()"); + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + 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, + "[%d] EVENT-IBSS ALONE TIMER: Start pairing\n", + ucBssIndex); + + /* abort timer */ + aisFsmReleaseCh(prAdapter, ucBssIndex); + + /* 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, ucBssIndex); +} /* 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 struct ADAPTER *prAdapter, + unsigned long ulParamPtr) +{ + struct BSS_INFO *prAisBssInfo; + struct AIS_FSM_INFO *prAisFsmInfo; + enum ENUM_AIS_STATE eNextState; + OS_SYSTIME rCurrentTime; + uint8_t ucBssIndex = (uint8_t) ulParamPtr; + + DEBUGFUNC("aisFsmRunEventJoinTimeout()"); + + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + + eNextState = prAisFsmInfo->eCurrentState; + + GET_CURRENT_SYSTIME(&rCurrentTime); + + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_JOIN: + DBGLOG(AIS, WARN, "EVENT- JOIN TIMEOUT\n"); + + /* 1. Do abort JOIN */ + aisFsmStateAbort_JOIN(prAdapter, ucBssIndex); + + /* 2. Increase Join Failure Count */ + /* Support AP Selection */ + aisAddBlacklist(prAdapter, prAisFsmInfo->prTargetBssDesc); + prAisFsmInfo->prTargetBssDesc->ucJoinFailureCount++; + + if (prAisFsmInfo->prTargetBssDesc->ucJoinFailureCount < + JOIN_MAX_RETRY_FAILURE_COUNT) { + /* 3.1 Retreat to AIS_STATE_SEARCH state for next try */ + eNextState = AIS_STATE_SEARCH; + } else if (prAisBssInfo->eConnectionState == + MEDIA_STATE_CONNECTED) { + /* roaming cases */ + /* 3.2 Retreat to AIS_STATE_WAIT_FOR_NEXT_SCAN state for + * next try + */ + eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; + } else + if (prAisFsmInfo->rJoinReqTime != 0 && !CHECK_FOR_TIMEOUT + (rCurrentTime, prAisFsmInfo->rJoinReqTime, + SEC_TO_SYSTIME(AIS_JOIN_TIMEOUT))) { + /* 3.3 Retreat to AIS_STATE_WAIT_FOR_NEXT_SCAN state + * for next try + */ + eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; + } else { + /* 3.4 Retreat to AIS_STATE_JOIN_FAILURE to + * terminate join operation + */ + eNextState = AIS_STATE_JOIN_FAILURE; + } + + break; + + case AIS_STATE_NORMAL_TR: + /* 1. release channel */ + aisFsmReleaseCh(prAdapter, ucBssIndex); + + /* 2. process if there is pending scan */ + if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, + TRUE, ucBssIndex) == TRUE) { + wlanClearScanningResult(prAdapter, ucBssIndex); + eNextState = AIS_STATE_ONLINE_SCAN; + } + /* 3. Process for pending roaming scan */ + else if (aisFsmIsRequestPending + (prAdapter, AIS_REQUEST_ROAMING_SEARCH, + TRUE, ucBssIndex) == TRUE) + eNextState = AIS_STATE_LOOKING_FOR; + /* 4. Process for pending roaming scan */ + else if (aisFsmIsRequestPending + (prAdapter, AIS_REQUEST_ROAMING_CONNECT, + TRUE, ucBssIndex) == TRUE) + eNextState = AIS_STATE_SEARCH; + else if (aisFsmIsRequestPending + (prAdapter, AIS_REQUEST_REMAIN_ON_CHANNEL, + TRUE, ucBssIndex) == TRUE) + eNextState = AIS_STATE_REQ_REMAIN_ON_CHANNEL; + +#if CFG_SUPPORT_LOWLATENCY_MODE + /* 5. Check if need to set low latency after connected. */ + wlanConnectedForLowLatency(prAdapter); +#endif + + break; + + default: + /* release channel */ + aisFsmReleaseCh(prAdapter, ucBssIndex); + break; + + } + + /* Call aisFsmSteps() when we are going to change AIS STATE */ + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState, ucBssIndex); +} /* end of aisFsmRunEventJoinTimeout() */ + +void aisFsmRunEventDeauthTimeout(IN struct ADAPTER *prAdapter, + unsigned long ulParamPtr) +{ + uint8_t ucBssIndex = (uint8_t) ulParamPtr; + + aisDeauthXmitCompleteBss(prAdapter, ucBssIndex, TX_RESULT_LIFE_TIMEOUT); +} + +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE +void aisFsmRunEventSecModeChangeTimeout(IN struct ADAPTER *prAdapter, + unsigned long ulParamPtr) +{ + uint8_t ucBssIndex = (uint8_t) ulParamPtr; + + DBGLOG(AIS, INFO, + "[%d] Beacon security mode change timeout, trigger disconnect!\n", + ucBssIndex); + + aisBssSecurityChanged(prAdapter, ucBssIndex); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct ADAPTER *prAdapter, + IN struct PARAM_SSID *prSsid, IN uint8_t *pucIe, + IN uint32_t u4IeLength, + IN uint8_t ucBssIndex) +{ + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_INFO *prAisBssInfo; + struct AIS_FSM_INFO *prAisFsmInfo; + struct PARAM_SCAN_REQUEST_ADV *prScanRequest; + + DEBUGFUNC("aisFsmScanRequest()"); + + ASSERT(u4IeLength <= MAX_IE_LENGTH); + + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + prScanRequest = &(prAisFsmInfo->rScanRequest); + + DBGLOG(SCN, TRACE, + "[AIS%d] eCurrentState=%d, fgIsScanReqIssued=%d\n", + ucBssIndex, + prAisFsmInfo->eCurrentState, prConnSettings->fgIsScanReqIssued); + if (!prConnSettings->fgIsScanReqIssued) { + prConnSettings->fgIsScanReqIssued = TRUE; + kalMemZero(prScanRequest, + sizeof(struct PARAM_SCAN_REQUEST_ADV)); + prScanRequest->pucIE = prAisFsmInfo->aucScanIEBuf; + + if (prSsid == NULL) { + prScanRequest->u4SsidNum = 0; + } else { + prScanRequest->u4SsidNum = 1; + + COPY_SSID(prScanRequest->rSsid[0].aucSsid, + prScanRequest->rSsid[0].u4SsidLen, + prSsid->aucSsid, prSsid->u4SsidLen); + } + + if (u4IeLength > 0 && u4IeLength <= MAX_IE_LENGTH) { + prScanRequest->u4IELength = u4IeLength; + kalMemCopy(prScanRequest->pucIE, pucIe, u4IeLength); + } else { + prScanRequest->u4IELength = 0; + } + prScanRequest->ucScanType = SCAN_TYPE_ACTIVE_SCAN; + if (prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR) { + if (prAisBssInfo->eCurrentOPMode == + OP_MODE_INFRASTRUCTURE && + timerPendingTimer(&prAisFsmInfo-> + rJoinTimeoutTimer)) { + /* 802.1x might not finished yet, pend it for + * later handling .. + */ + aisFsmInsertRequest(prAdapter, + AIS_REQUEST_SCAN, + ucBssIndex); + } else { + if (prAisFsmInfo->fgIsChannelGranted == TRUE) { + DBGLOG(SCN, WARN, + "Scan Request with channel granted for join operation: %d, %d", + prAisFsmInfo->fgIsChannelGranted, + prAisFsmInfo->fgIsChannelRequested); + } + + /* start online scan */ + wlanClearScanningResult(prAdapter, ucBssIndex); + aisFsmSteps(prAdapter, AIS_STATE_ONLINE_SCAN, + ucBssIndex); + } + } else if (prAisFsmInfo->eCurrentState == AIS_STATE_IDLE) { + wlanClearScanningResult(prAdapter, ucBssIndex); + aisFsmSteps(prAdapter, AIS_STATE_SCAN, + ucBssIndex); + } else { + aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN, + ucBssIndex); + } + } else { + DBGLOG(SCN, WARN, "Scan Request dropped. (state: %d)\n", + prAisFsmInfo->eCurrentState); + } + +} /* end of aisFsmScanRequest() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is used to handle OID_802_11_BSSID_LIST_SCAN + * + * \param[in] prAdapter Pointer of ADAPTER_T + * \param[in] prRequestIn scan request + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void +aisFsmScanRequestAdv(IN struct ADAPTER *prAdapter, + IN struct PARAM_SCAN_REQUEST_ADV *prRequestIn) +{ + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_INFO *prAisBssInfo; + struct AIS_FSM_INFO *prAisFsmInfo; + struct PARAM_SCAN_REQUEST_ADV *prScanRequest; + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq; + uint8_t ucBssIndex = 0; + + DEBUGFUNC("aisFsmScanRequestAdv()"); + + if (!prRequestIn) { + log_dbg(SCN, WARN, "Scan request is NULL\n"); + return; + } + ucBssIndex = prRequestIn->ucBssIndex; + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prRmReq = aisGetRmReqParam(prAdapter, ucBssIndex); + prScanRequest = &(prAisFsmInfo->rScanRequest); + + DBGLOG(SCN, TRACE, "[AIS%d] eCurrentState=%d, fgIsScanReqIssued=%d\n", + ucBssIndex, + prAisFsmInfo->eCurrentState, prConnSettings->fgIsScanReqIssued); + + if (!prConnSettings->fgIsScanReqIssued) { + prConnSettings->fgIsScanReqIssued = TRUE; + + kalMemCopy(prScanRequest, prRequestIn, + sizeof(struct PARAM_SCAN_REQUEST_ADV)); + prScanRequest->pucIE = prAisFsmInfo->aucScanIEBuf; + + if (prRequestIn->u4IELength > 0 && + prRequestIn->u4IELength <= MAX_IE_LENGTH) { + prScanRequest->u4IELength = prRequestIn->u4IELength; + kalMemCopy(prScanRequest->pucIE, prRequestIn->pucIE, + prScanRequest->u4IELength); + } else { + prScanRequest->u4IELength = 0; + } + + if (prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR) { + if (prAisBssInfo->eCurrentOPMode == + OP_MODE_INFRASTRUCTURE && + timerPendingTimer(&prAisFsmInfo-> + rJoinTimeoutTimer)) { + /* 802.1x might not finished yet, pend it for + * later handling .. + */ + aisFsmInsertRequest(prAdapter, + AIS_REQUEST_SCAN, + ucBssIndex); + } else { + if (prAisFsmInfo->fgIsChannelGranted == TRUE) { + DBGLOG(SCN, WARN, + "Scan Request with channel granted for join operation: %d, %d", + prAisFsmInfo->fgIsChannelGranted, + prAisFsmInfo->fgIsChannelRequested); + } + + /* start online scan */ + wlanClearScanningResult(prAdapter, ucBssIndex); + aisFsmSteps(prAdapter, AIS_STATE_ONLINE_SCAN, + ucBssIndex); + } + } else if (prAisFsmInfo->eCurrentState == AIS_STATE_IDLE) { + wlanClearScanningResult(prAdapter, ucBssIndex); + aisFsmSteps(prAdapter, AIS_STATE_SCAN, + ucBssIndex); + } else { + aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN, + ucBssIndex); + } + } else if (prRmReq->rBcnRmParam.eState == + RM_ON_GOING) { + struct NORMAL_SCAN_PARAMS *prNormalScan = + &prRmReq->rBcnRmParam.rNormalScan; + + prNormalScan->fgExist = TRUE; + kalMemCopy(&(prNormalScan->rScanRequest), prRequestIn, + sizeof(struct PARAM_SCAN_REQUEST_ADV)); + prNormalScan->rScanRequest.pucIE = prNormalScan->aucScanIEBuf; + if (prRequestIn->u4IELength > 0 && + prRequestIn->u4IELength <= MAX_IE_LENGTH) { + prNormalScan->rScanRequest.u4IELength = + prRequestIn->u4IELength; + kalMemCopy(prNormalScan->rScanRequest.pucIE, + prRequestIn->pucIE, prRequestIn->u4IELength); + } else { + prNormalScan->rScanRequest.u4IELength = 0; + } + + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); + DBGLOG(AIS, INFO, + "BCN REQ: Buffer normal scan while Beacon request is scanning\n"); + } else { + DBGLOG(SCN, WARN, "Scan Request dropped. (state: %d)\n", + prAisFsmInfo->eCurrentState); + } + +} /* end of aisFsmScanRequestAdv() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is invoked when CNM granted channel privilege + * + * \param[in] prAdapter Pointer of ADAPTER_T + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void aisFsmRunEventChGrant(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct BSS_INFO *prAisBssInfo; + struct AIS_FSM_INFO *prAisFsmInfo; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecificBssInfo; + struct CONNECTION_SETTINGS *prConnSettings; + struct MSG_CH_GRANT *prMsgChGrant; + uint8_t ucTokenID; + uint32_t u4GrantInterval; + uint8_t ucBssIndex = 0; + + prMsgChGrant = (struct MSG_CH_GRANT *)prMsgHdr; + + ucTokenID = prMsgChGrant->ucTokenID; + u4GrantInterval = prMsgChGrant->u4GrantInterval; + ucBssIndex = prMsgChGrant->ucBssIndex; + + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prAisSpecificBssInfo = + aisGetAisSpecBssInfo(prAdapter, ucBssIndex); + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + +#if CFG_SISO_SW_DEVELOP + /* Driver record granted CH in BSS info */ + prAisBssInfo->fgIsGranted = TRUE; + prAisBssInfo->eBandGranted = prMsgChGrant->eRfBand; + prAisBssInfo->ucPrimaryChannelGranted = prMsgChGrant->ucPrimaryChannel; +#endif + + /* 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); + DBGLOG(AIS, INFO, "Start JOIN Timer!"); + aisFsmSteps(prAdapter, AIS_STATE_JOIN, ucBssIndex); + + prAisFsmInfo->fgIsChannelGranted = TRUE; + } else if (prAisFsmInfo->eCurrentState == + AIS_STATE_REQ_REMAIN_ON_CHANNEL + && prAisFsmInfo->ucSeqNumOfChReq == ucTokenID) { + /* 2. channel privilege has been approved */ + prAisFsmInfo->u4ChGrantedInterval = u4GrantInterval; + +#if CFG_SUPPORT_NCHO + if (prAdapter->rNchoInfo.fgNCHOEnabled == TRUE && + prAdapter->rNchoInfo.fgIsSendingAF == TRUE && + prAdapter->rNchoInfo.fgChGranted == FALSE) { + DBGLOG(INIT, TRACE, + "NCHO complete rAisChGrntComp trace time is %u\n", + kalGetTimeTick()); + prAdapter->rNchoInfo.fgChGranted = TRUE; + complete(&prAdapter->prGlueInfo->rAisChGrntComp); + } +#endif + if (prAisFsmInfo->rChReqInfo.eReqType == + CH_REQ_TYPE_OFFCHNL_TX) { + aisFsmSteps(prAdapter, AIS_STATE_OFF_CHNL_TX, + ucBssIndex); + } else { + /* + * 3.1 set timeout timer in cases upper layer + * cancel_remain_on_channel never comes + */ + cnmTimerStartTimer(prAdapter, + &prAisFsmInfo->rChannelTimeoutTimer, + prAisFsmInfo->u4ChGrantedInterval); + + /* 3.2 switch to remain_on_channel state */ + aisFsmSteps(prAdapter, AIS_STATE_REMAIN_ON_CHANNEL, + ucBssIndex); + + /* 3.3. indicate upper layer for channel ready */ + kalReadyOnChannel(prAdapter->prGlueInfo, + prAisFsmInfo->rChReqInfo.u8Cookie, + prAisFsmInfo->rChReqInfo.eBand, + prAisFsmInfo->rChReqInfo.eSco, + prAisFsmInfo->rChReqInfo.ucChannelNum, + prAisFsmInfo->rChReqInfo.u4DurationMs, + ucBssIndex); + } + + prAisFsmInfo->fgIsChannelGranted = TRUE; + } else { /* mismatched grant */ + /* 2. return channel privilege to CNM immediately */ + /* aisFsmReleaseCh(prAdapter, ucBssIndex); */ + DBGLOG(AIS, WARN, "channel grant token mismatch\n"); + } +} /* 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 struct ADAPTER *prAdapter, IN uint8_t ucBssIndex) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct MSG_CH_ABORT *prMsgChAbort; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + + if (prAisFsmInfo->fgIsChannelGranted == TRUE + || prAisFsmInfo->fgIsChannelRequested == TRUE) { + + prAisFsmInfo->fgIsChannelRequested = FALSE; + prAisFsmInfo->fgIsChannelGranted = FALSE; + + /* 1. return channel privilege to CNM immediately */ + prMsgChAbort = + (struct MSG_CH_ABORT *)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct + MSG_CH_ABORT)); + if (!prMsgChAbort) { + DBGLOG(AIS, ERROR, "Can't release Channel to CNM\n"); + return; + } + + prMsgChAbort->rMsgHdr.eMsgId = MID_MNY_CNM_CH_ABORT; + prMsgChAbort->ucBssIndex = ucBssIndex; + prMsgChAbort->ucTokenID = prAisFsmInfo->ucSeqNumOfChReq; +#if CFG_SUPPORT_DBDC + prMsgChAbort->eDBDCBand = ENUM_BAND_AUTO; +#endif /*CFG_SUPPORT_DBDC */ + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *)prMsgChAbort, + MSG_SEND_METHOD_BUF); + } +} /* end of aisFsmReleaseCh() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is to inform AIS that corresponding beacon has not + * been received for a while and probing is not successful + * + * \param[in] prAdapter Pointer of ADAPTER_T + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void aisBssBeaconTimeout(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) + +{ + /* trigger by driver, use dummy reason code */ + aisBssBeaconTimeout_impl(prAdapter, BEACON_TIMEOUT_REASON_NUM, + DISCONNECT_REASON_CODE_RADIO_LOST, ucBssIndex); +} + +void aisBssBeaconTimeout_impl(IN struct ADAPTER *prAdapter, + IN uint8_t ucBcnTimeoutReason, IN uint8_t ucDisconnectReason, + IN uint8_t ucBssIndex) +{ + struct BSS_INFO *prAisBssInfo; + u_int8_t fgDoAbortIndication = FALSE; + u_int8_t fgIsReasonPER = + (ucBcnTimeoutReason == BEACON_TIMEOUT_REASON_HIGH_PER); + struct CONNECTION_SETTINGS *prConnSettings; + + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + + /* 4 <1> Diagnose Connection for Beacon Timeout Event */ + if (prAisBssInfo->eConnectionState == MEDIA_STATE_CONNECTED) { + if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + struct STA_RECORD *prStaRec = + prAisBssInfo->prStaRecOfAP; + + if (prStaRec) + fgDoAbortIndication = TRUE; + + } else if (prAisBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + fgDoAbortIndication = TRUE; + } + } + /* 4 <2> invoke abort handler */ + if (fgDoAbortIndication) { + prAisBssInfo->u2DeauthReason = + REASON_CODE_BEACON_TIMEOUT*100 + + ucBcnTimeoutReason; + + DBGLOG(AIS, EVENT, "aisBssBeaconTimeout\n"); + aisFsmStateAbort(prAdapter, + ucDisconnectReason, + !fgIsReasonPER, + ucBssIndex); + } +} /* end of aisBssBeaconTimeout() */ + +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE +void aisBssSecurityChanged(struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + + aisFsmStateAbort(prAdapter, DISCONNECT_REASON_CODE_DEAUTHENTICATED, + FALSE, ucBssIndex); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \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 aisBssLinkDown(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + struct BSS_INFO *prAisBssInfo; + u_int8_t fgDoAbortIndication = FALSE; + struct CONNECTION_SETTINGS *prConnSettings; + + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + + /* 4 <1> Diagnose Connection for Beacon Timeout Event */ + if (prAisBssInfo->eConnectionState == MEDIA_STATE_CONNECTED) { + if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + struct STA_RECORD *prStaRec = + prAisBssInfo->prStaRecOfAP; + + if (prStaRec) + fgDoAbortIndication = TRUE; + + } else if (prAisBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + fgDoAbortIndication = TRUE; + } + } + /* 4 <2> invoke abort handler */ + if (fgDoAbortIndication) { + DBGLOG(AIS, EVENT, "aisBssLinkDown\n"); + aisFsmStateAbort(prAdapter, + DISCONNECT_REASON_CODE_DISASSOCIATED, FALSE, + ucBssIndex); + } + + /* kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + * WLAN_STATUS_SCAN_COMPLETE, NULL, 0); + */ +} /* end of aisBssLinkDown() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +aisDeauthXmitCompleteBss(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prAisBssInfo; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); +#if CFG_SUPPORT_802_11W + /* Notify completion after encrypted deauth frame tx done */ + if (prAisBssInfo->encryptedDeauthIsInProcess == TRUE) { + if (!completion_done(&prAisBssInfo->rDeauthComp)) { + DBGLOG(AIS, EVENT, "Complete rDeauthComp\n"); + complete(&prAisBssInfo->rDeauthComp); + } + } + prAisBssInfo->encryptedDeauthIsInProcess = FALSE; +#endif + if (rTxDoneStatus == TX_RESULT_SUCCESS) + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rDeauthDoneTimer); + + if (prAisFsmInfo->eCurrentState == AIS_STATE_DISCONNECTING) { + DBGLOG(AIS, EVENT, "aisDeauthXmitComplete\n"); + if (rTxDoneStatus != TX_RESULT_DROPPED_IN_DRIVER + && rTxDoneStatus != TX_RESULT_QUEUE_CLEARANCE) + aisFsmStateAbort(prAdapter, + prAisBssInfo->ucReasonOfDisconnect, + FALSE, ucBssIndex); + } else { + DBGLOG(AIS, WARN, + "DEAUTH frame transmitted without further handling"); + } + + return WLAN_STATUS_SUCCESS; + +} /* end of aisDeauthXmitComplete() */ + +uint32_t +aisDeauthXmitComplete(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + return aisDeauthXmitCompleteBss(prAdapter, + prMsduInfo->ucBssIndex, rTxDoneStatus); +} + +#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 struct ADAPTER *prAdapter, + uint32_t u4ReqScan, uint8_t ucBssIndex) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct CONNECTION_SETTINGS *prConnSettings; + enum ENUM_AIS_REQUEST_TYPE eAisRequest = AIS_REQUEST_NUM; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + + /* search candidates by best rssi */ + prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_BEST_RSSI; + + /* TODO: Stop roaming event in FW */ +#if CFG_SUPPORT_WFD +#if CFG_ENABLE_WIFI_DIRECT + { + /* Check WFD is running */ + struct WFD_CFG_SETTINGS *prWfdCfgSettings = + (struct WFD_CFG_SETTINGS *)NULL; + + prWfdCfgSettings = &(prAdapter->rWifiVar.rWfdConfigureSettings); + if ((prWfdCfgSettings->ucWfdEnable != 0)) { + DBGLOG(ROAMING, INFO, + "WFD is running. Stop roaming.\n"); + roamingFsmRunEventRoam(prAdapter, ucBssIndex); + roamingFsmRunEventFail(prAdapter, + ROAMING_FAIL_REASON_NOCANDIDATE, + ucBssIndex); + return; + } + } +#endif +#endif + + /* results are still new */ + if (!u4ReqScan) { + roamingFsmRunEventRoam(prAdapter, ucBssIndex); + 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 + && !timerPendingTimer(&prAisFsmInfo->rJoinTimeoutTimer)) { + if (eAisRequest == AIS_REQUEST_ROAMING_SEARCH) { + prAisFsmInfo->fgTargetChnlScanIssued = TRUE; + aisFsmSteps(prAdapter, AIS_STATE_LOOKING_FOR, + ucBssIndex); + } else + aisFsmSteps(prAdapter, AIS_STATE_SEARCH, + ucBssIndex); + } else { + aisFsmRemoveRoamingRequest(prAdapter, ucBssIndex); + aisFsmInsertRequest(prAdapter, eAisRequest, ucBssIndex); + } +} /* end of aisFsmRunEventRoamingDiscovery() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Update the time of ScanDone for roaming and transit to Roam state. + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +enum ENUM_AIS_STATE aisFsmRoamingScanResultsUpdate(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct ROAMING_INFO *prRoamingFsmInfo; + enum ENUM_AIS_STATE eNextState; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prRoamingFsmInfo = + aisGetRoamingInfo(prAdapter, ucBssIndex); + + roamingFsmScanResultsUpdate(prAdapter, ucBssIndex); + + eNextState = prAisFsmInfo->eCurrentState; + if (prRoamingFsmInfo->eCurrentState == ROAMING_STATE_DISCOVERY) { + aisFsmRemoveRoamingRequest(prAdapter, ucBssIndex); + roamingFsmRunEventRoam(prAdapter, ucBssIndex); + 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 struct ADAPTER *prAdapter, + IN struct STA_RECORD *prTargetStaRec) +{ + struct BSS_INFO *prAisBssInfo; + uint8_t ucBssIndex = prTargetStaRec->ucBssIndex; + + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + if (prAisBssInfo->prStaRecOfAP != prTargetStaRec) + wmmNotifyDisconnected(prAdapter, ucBssIndex); + + nicPmIndicateBssAbort(prAdapter, prAisBssInfo->ucBssIndex); + + /* 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 (prAisBssInfo->eConnectionState == MEDIA_STATE_CONNECTED) { + struct PARAM_SSID rSsid; + struct BSS_DESC *prBssDesc = NULL; + + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, prAisBssInfo->aucSSID, + prAisBssInfo->ucSSIDLen); + prBssDesc = + scanSearchBssDescByBssidAndSsid(prAdapter, + prAisBssInfo->aucBSSID, + TRUE, &rSsid); + if (prBssDesc) { + prBssDesc->fgIsConnected = FALSE; + prBssDesc->fgIsConnecting = FALSE; + } + } + + /* 4 <4> Change Media State immediately. */ + aisChangeMediaState(prAisBssInfo, MEDIA_STATE_ROAMING_DISC_PREV); + + /* 4 <4.1> sync. with firmware */ + /* Virtial BSSID */ + prTargetStaRec->ucBssIndex = (prAdapter->ucHwBssIdNum + 1); + nicUpdateBss(prAdapter, prAisBssInfo->ucBssIndex); + + secRemoveBssBcEntry(prAdapter, prAisBssInfo, TRUE); + prTargetStaRec->ucBssIndex = prAisBssInfo->ucBssIndex; + /* before deactivate previous AP, should move its pending MSDUs + ** to the new AP + */ + if (prAisBssInfo->prStaRecOfAP) + if (prAisBssInfo->prStaRecOfAP != prTargetStaRec && + prAisBssInfo->prStaRecOfAP->fgIsInUse) { + qmMoveStaTxQueue(prAisBssInfo->prStaRecOfAP, + prTargetStaRec); + /* Currently, firmware just drop all previous AP's + ** data packets, need to handle waiting tx done + ** status packets so driver no + */ +#if 0 + nicTxHandleRoamingDone(prAdapter, + prAisBssInfo->prStaRecOfAP, + prTargetStaRec); +#endif + cnmStaRecFree(prAdapter, prAisBssInfo->prStaRecOfAP); + } else + DBGLOG(AIS, WARN, "prStaRecOfAP is in use %d\n", + prAisBssInfo->prStaRecOfAP->fgIsInUse); + else + DBGLOG(AIS, WARN, + "NULL pointer of prAisBssInfo->prStaRecOfAP\n"); +} /* 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 struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct SW_RFB *prAssocRspSwRfb) +{ + struct BSS_INFO *prAisBssInfo; + uint8_t ucBssIndex = prStaRec->ucBssIndex; + + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + + /* 4 <1.1> Change FW's Media State immediately. */ + aisChangeMediaState(prAisBssInfo, 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)) { + /* before deactivate previous AP, should move its pending MSDUs + ** to the new AP + */ + qmMoveStaTxQueue(prAisBssInfo->prStaRecOfAP, prStaRec); + /* cnmStaRecChangeState(prAdapter, prAisBssInfo->prStaRecOfAP, + ** STA_STATE_1); + */ + cnmStaRecFree(prAdapter, prAisBssInfo->prStaRecOfAP); + } + + /* 4 <1.4> Update BSS_INFO_T */ + aisUpdateBssInfoForJOIN(prAdapter, prStaRec, prAssocRspSwRfb); + + /* 4 <1.3> 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, MEDIA_STATE_CONNECTED, + FALSE, ucBssIndex); +} /* 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t aisFsmIsRequestPending(IN struct ADAPTER *prAdapter, + IN enum ENUM_AIS_REQUEST_TYPE eReqType, + IN u_int8_t bRemove, + IN uint8_t ucBssIndex) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct AIS_REQ_HDR *prPendingReqHdr, *prPendingReqHdrNext; + u_int8_t found = FALSE; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + + /* traverse through pending request list */ + LINK_FOR_EACH_ENTRY_SAFE(prPendingReqHdr, + prPendingReqHdrNext, + &(prAisFsmInfo->rPendingReqList), rLinkEntry, + struct AIS_REQ_HDR) { + /* check for specified type */ + if (prPendingReqHdr->eReqType == eReqType) { + found = TRUE; + + /* check if need to remove */ + if (bRemove == TRUE) { + LINK_REMOVE_KNOWN_ENTRY(&(prAisFsmInfo-> + rPendingReqList), + &(prPendingReqHdr->rLinkEntry)); + + cnmMemFree(prAdapter, prPendingReqHdr); + DBGLOG(AIS, INFO, "Remove req=%d\n", eReqType); + } else + break; + } + } + + return found; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Clear any pending request + * + * @param prAdapter + * eReqType + * + * @return TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +u_int8_t aisFsmClearRequest(IN struct ADAPTER *prAdapter, + IN enum ENUM_AIS_REQUEST_TYPE eReqType, + IN uint8_t ucBssIndex) +{ + return aisFsmIsRequestPending(prAdapter, eReqType, TRUE, ucBssIndex); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Get next pending request + * + * @param prAdapter + * + * @return P_AIS_REQ_HDR_T + */ +/*----------------------------------------------------------------------------*/ +struct AIS_REQ_HDR *aisFsmGetNextRequest(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct AIS_REQ_HDR *prPendingReqHdr; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + + LINK_REMOVE_HEAD(&(prAisFsmInfo->rPendingReqList), prPendingReqHdr, + struct AIS_REQ_HDR *); + + return prPendingReqHdr; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Insert a new request + * + * @param prAdapter + * eReqType + * + * @return TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +u_int8_t aisFsmInsertRequest(IN struct ADAPTER *prAdapter, + IN enum ENUM_AIS_REQUEST_TYPE eReqType, + IN uint8_t ucBssIndex) +{ + struct AIS_REQ_HDR *prAisReq; + struct AIS_FSM_INFO *prAisFsmInfo; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + + prAisReq = + (struct AIS_REQ_HDR *)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct AIS_REQ_HDR)); + + if (!prAisReq) { + DBGLOG(AIS, ERROR, "Can't generate new message\n"); + return FALSE; + } + + prAisReq->eReqType = eReqType; + + /* attach request into pending request list */ + LINK_INSERT_TAIL(&prAisFsmInfo->rPendingReqList, &prAisReq->rLinkEntry); + + DBGLOG(AIS, INFO, "eCurrentState=%d, eReqType=%d, u4NumElem=%d\n", + prAisFsmInfo->eCurrentState, eReqType, + prAisFsmInfo->rPendingReqList.u4NumElem); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Insert a new request to head + * + * @param prAdapter + * eReqType + * + * @return TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +u_int8_t aisFsmInsertRequestToHead(IN struct ADAPTER *prAdapter, + IN enum ENUM_AIS_REQUEST_TYPE eReqType, + IN uint8_t ucBssIndex) +{ + struct AIS_REQ_HDR *prAisReq; + struct AIS_FSM_INFO *prAisFsmInfo; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + + prAisReq = + (struct AIS_REQ_HDR *)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct AIS_REQ_HDR)); + + if (!prAisReq) { + DBGLOG(AIS, ERROR, "Can't generate new message\n"); + return FALSE; + } + + prAisReq->eReqType = eReqType; + + /* attach request into pending request list */ + LINK_INSERT_HEAD(&prAisFsmInfo->rPendingReqList, &prAisReq->rLinkEntry); + + DBGLOG(AIS, INFO, "eCurrentState=%d, eReqType=%d, u4NumElem=%d\n", + prAisFsmInfo->eCurrentState, eReqType, + prAisFsmInfo->rPendingReqList.u4NumElem); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Flush all pending requests + * + * @param prAdapter + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisFsmFlushRequest(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIndex) +{ + struct AIS_REQ_HDR *prAisReq; + struct AIS_FSM_INFO *prAisFsmInfo; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + + DBGLOG(AIS, INFO, "aisFsmFlushRequest %d\n", + prAisFsmInfo->rPendingReqList.u4NumElem); + + while ((prAisReq = aisFsmGetNextRequest(prAdapter, ucBssIndex)) != NULL) + cnmMemFree(prAdapter, prAisReq); +} + +void aisFsmRunEventRemainOnChannel(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_REMAIN_ON_CHANNEL *prRemainOnChannel; + struct AIS_FSM_INFO *prAisFsmInfo; + struct CONNECTION_SETTINGS *prConnSettings; + uint8_t ucBssIndex = 0; + + DEBUGFUNC("aisFsmRunEventRemainOnChannel()"); + + prRemainOnChannel = (struct MSG_REMAIN_ON_CHANNEL *)prMsgHdr; + + ucBssIndex = prRemainOnChannel->ucBssIdx; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + + /* record parameters */ + prAisFsmInfo->rChReqInfo.eBand = prRemainOnChannel->eBand; + prAisFsmInfo->rChReqInfo.eSco = prRemainOnChannel->eSco; + prAisFsmInfo->rChReqInfo.ucChannelNum = prRemainOnChannel->ucChannelNum; + prAisFsmInfo->rChReqInfo.u4DurationMs = prRemainOnChannel->u4DurationMs; + prAisFsmInfo->rChReqInfo.u8Cookie = prRemainOnChannel->u8Cookie; + prAisFsmInfo->rChReqInfo.eReqType = prRemainOnChannel->eReqType; + + if ((prAisFsmInfo->eCurrentState == AIS_STATE_IDLE) || + (prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR + && !timerPendingTimer(&prAisFsmInfo->rJoinTimeoutTimer))) { + /* transit to next state */ + aisFsmSteps(prAdapter, AIS_STATE_REQ_REMAIN_ON_CHANNEL, + ucBssIndex); + } else { + aisFsmInsertRequest(prAdapter, AIS_REQUEST_REMAIN_ON_CHANNEL, + ucBssIndex); + } + + /* free messages */ + cnmMemFree(prAdapter, prMsgHdr); +} + +void aisFsmRunEventCancelRemainOnChannel(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prAisBssInfo; + struct MSG_CANCEL_REMAIN_ON_CHANNEL *prCancelRemainOnChannel; + u_int8_t rReturn = TRUE; + uint8_t ucBssIndex = 0; + + prCancelRemainOnChannel = + (struct MSG_CANCEL_REMAIN_ON_CHANNEL *)prMsgHdr; + + ucBssIndex = prCancelRemainOnChannel->ucBssIdx; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + + /* 1. Check the cookie first */ + if (prCancelRemainOnChannel->u8Cookie == + prAisFsmInfo->rChReqInfo.u8Cookie) { + + /* 2. release channel privilege/request */ + if (prAisFsmInfo->eCurrentState == + AIS_STATE_REQ_REMAIN_ON_CHANNEL) { + /* 2.1 elease channel */ + aisFsmReleaseCh(prAdapter, ucBssIndex); + } else if (prAisFsmInfo->eCurrentState == + AIS_STATE_REMAIN_ON_CHANNEL) { + /* 2.1 release channel */ + aisFsmReleaseCh(prAdapter, ucBssIndex); + + /* 2.2 stop channel timeout timer */ + cnmTimerStopTimer(prAdapter, + &prAisFsmInfo->rChannelTimeoutTimer); + } + + /* 3. clear pending request of remain_on_channel */ + rReturn = aisFsmClearRequest(prAdapter, + AIS_REQUEST_REMAIN_ON_CHANNEL, ucBssIndex); + + DBGLOG(AIS, TRACE, + "rReturn of aisFsmIsRequestPending is %d", rReturn); + + /* 4. decide which state to retreat */ + if (prAisFsmInfo->eCurrentState == + AIS_STATE_REQ_REMAIN_ON_CHANNEL + || prAisFsmInfo->eCurrentState == + AIS_STATE_REMAIN_ON_CHANNEL) { + if (prAisBssInfo->eConnectionState == + MEDIA_STATE_CONNECTED) + aisFsmSteps(prAdapter, AIS_STATE_NORMAL_TR, + ucBssIndex); + else + aisFsmSteps(prAdapter, AIS_STATE_IDLE, + ucBssIndex); + } + } + + /* 5. free message */ + cnmMemFree(prAdapter, prMsgHdr); +} + +static u_int8_t +aisFunChnlReqByOffChnl(IN struct ADAPTER *prAdapter, + IN struct AIS_OFF_CHNL_TX_REQ_INFO *prOffChnlTxReq, + IN uint8_t ucBssIndex) +{ + struct MSG_REMAIN_ON_CHANNEL *prMsgChnlReq = + (struct MSG_REMAIN_ON_CHANNEL *) NULL; + + prMsgChnlReq = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_REMAIN_ON_CHANNEL)); + if (prMsgChnlReq == NULL) { + DBGLOG(AIS, ERROR, "channel request buffer allocate fails.\n"); + return FALSE; + } + + prMsgChnlReq->u8Cookie = prOffChnlTxReq->u8Cookie; + prMsgChnlReq->u4DurationMs = prOffChnlTxReq->u4Duration; + prMsgChnlReq->ucChannelNum = prOffChnlTxReq->rChannelInfo.ucChannelNum; + prMsgChnlReq->eBand = prOffChnlTxReq->rChannelInfo.eBand; + prMsgChnlReq->eSco = prOffChnlTxReq->eChnlExt; + prMsgChnlReq->eReqType = CH_REQ_TYPE_OFFCHNL_TX; + + prMsgChnlReq->ucBssIdx = ucBssIndex; + + aisFsmRunEventRemainOnChannel(prAdapter, + (struct MSG_HDR *) prMsgChnlReq); + return TRUE; +} + +static u_int8_t +aisFunAddTxReq2Queue(IN struct ADAPTER *prAdapter, + IN struct AIS_MGMT_TX_REQ_INFO *prMgmtTxReqInfo, + IN struct MSG_MGMT_TX_REQUEST *prMgmtTxMsg, + OUT struct AIS_OFF_CHNL_TX_REQ_INFO **pprOffChnlTxReq) +{ + struct AIS_OFF_CHNL_TX_REQ_INFO *prTmpOffChnlTxReq = + (struct AIS_OFF_CHNL_TX_REQ_INFO *) NULL; + + prTmpOffChnlTxReq = cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(struct AIS_OFF_CHNL_TX_REQ_INFO)); + + if (prTmpOffChnlTxReq == NULL) { + DBGLOG(AIS, ERROR, "Allocate TX request buffer fails.\n"); + return FALSE; + } + + prTmpOffChnlTxReq->u8Cookie = prMgmtTxMsg->u8Cookie; + prTmpOffChnlTxReq->prMgmtTxMsdu = prMgmtTxMsg->prMgmtMsduInfo; + prTmpOffChnlTxReq->fgNoneCckRate = prMgmtTxMsg->fgNoneCckRate; + kalMemCopy(&prTmpOffChnlTxReq->rChannelInfo, + &prMgmtTxMsg->rChannelInfo, + sizeof(struct RF_CHANNEL_INFO)); + prTmpOffChnlTxReq->eChnlExt = prMgmtTxMsg->eChnlExt; + prTmpOffChnlTxReq->fgIsWaitRsp = prMgmtTxMsg->fgIsWaitRsp; + prTmpOffChnlTxReq->u4Duration = prMgmtTxMsg->u4Duration; + + LINK_INSERT_TAIL(&prMgmtTxReqInfo->rTxReqLink, + &prTmpOffChnlTxReq->rLinkEntry); + + *pprOffChnlTxReq = prTmpOffChnlTxReq; + + return TRUE; +} + +static void +aisFunHandleOffchnlTxReq(IN struct ADAPTER *prAdapter, + IN struct AIS_FSM_INFO *prAisFsmInfo, + IN struct MSG_MGMT_TX_REQUEST *prMgmtTxMsg, + IN uint8_t ucBssIndex) +{ + struct AIS_OFF_CHNL_TX_REQ_INFO *prOffChnlTxReq = + (struct AIS_OFF_CHNL_TX_REQ_INFO *) NULL; + struct AIS_MGMT_TX_REQ_INFO *prMgmtTxReqInfo = + (struct AIS_MGMT_TX_REQ_INFO *) NULL; + + prMgmtTxReqInfo = &(prAisFsmInfo->rMgmtTxInfo); + + if (prMgmtTxMsg->u4Duration < MIN_TX_DURATION_TIME_MS) + prMgmtTxMsg->u4Duration = MIN_TX_DURATION_TIME_MS; + + if (aisFunAddTxReq2Queue(prAdapter, prMgmtTxReqInfo, + prMgmtTxMsg, &prOffChnlTxReq) == FALSE) + goto error; + + if (prOffChnlTxReq == NULL) + return; + + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_OFF_CHNL_TX: + if (prAisFsmInfo->fgIsChannelGranted && + prAisFsmInfo->rChReqInfo.ucChannelNum == + prMgmtTxMsg->rChannelInfo.ucChannelNum && + prMgmtTxReqInfo->rTxReqLink.u4NumElem == 1) { + aisFsmSteps(prAdapter, AIS_STATE_OFF_CHNL_TX, + ucBssIndex); + } else { + log_dbg(P2P, INFO, "tx ch: %d, current ch: %d, granted: %d, tx link num: %d", + prMgmtTxMsg->rChannelInfo.ucChannelNum, + prAisFsmInfo->rChReqInfo.ucChannelNum, + prAisFsmInfo->fgIsChannelGranted, + prMgmtTxReqInfo->rTxReqLink.u4NumElem); + } + break; + default: + if (!aisFunChnlReqByOffChnl(prAdapter, prOffChnlTxReq, + ucBssIndex)) + goto error; + break; + } + + return; + +error: + LINK_REMOVE_KNOWN_ENTRY( + &(prMgmtTxReqInfo->rTxReqLink), + &prOffChnlTxReq->rLinkEntry); + cnmPktFree(prAdapter, prOffChnlTxReq->prMgmtTxMsdu); + cnmMemFree(prAdapter, prOffChnlTxReq); +} + +static u_int8_t +aisFunNeedOffchnlTx(IN struct ADAPTER *prAdapter, + IN struct MSG_MGMT_TX_REQUEST *prMgmtTxMsg) +{ + struct BSS_INFO *prAisBssInfo = (struct BSS_INFO *) NULL; + struct AIS_FSM_INFO *prAisFsmInfo; + uint8_t ucBssIndex = 0; + + ucBssIndex = prMgmtTxMsg->ucBssIdx; + + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + + if (!prMgmtTxMsg->fgIsOffChannel) + return FALSE; + + /* tx channel == op channel */ + if (prAisBssInfo->eConnectionState == MEDIA_STATE_CONNECTED && + prAisBssInfo->ucPrimaryChannel == + prMgmtTxMsg->rChannelInfo.ucChannelNum) + return FALSE; + + /* tx channel == roc channel */ + if (prAisFsmInfo->fgIsChannelGranted && + prAisFsmInfo->rChReqInfo.ucChannelNum == + prMgmtTxMsg->rChannelInfo.ucChannelNum) + return FALSE; + + DBGLOG(REQ, INFO, "Use offchannel to TX.\n"); + + return TRUE; +} + +void aisFsmRunEventMgmtFrameTx(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct MSG_MGMT_TX_REQUEST *prMgmtTxMsg = + (struct MSG_MGMT_TX_REQUEST *) NULL; + uint8_t ucBssIndex = 0; + + if (!prAdapter || !prMsgHdr) + return; + + prMgmtTxMsg = (struct MSG_MGMT_TX_REQUEST *) prMsgHdr; + ucBssIndex = prMgmtTxMsg->ucBssIdx; + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + + if (prAisFsmInfo == NULL) + goto exit; + + if (!aisFunNeedOffchnlTx(prAdapter, prMgmtTxMsg)) + aisFuncTxMgmtFrame(prAdapter, + &prAisFsmInfo->rMgmtTxInfo, + prMgmtTxMsg->prMgmtMsduInfo, + prMgmtTxMsg->u8Cookie, + ucBssIndex); + else + aisFunHandleOffchnlTxReq(prAdapter, + prAisFsmInfo, + prMgmtTxMsg, + ucBssIndex); + +exit: + cnmMemFree(prAdapter, prMsgHdr); +} /* aisFsmRunEventMgmtFrameTx */ + +#if CFG_SUPPORT_NCHO +void aisFsmRunEventNchoActionFrameTx(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prAisBssInfo = (struct BSS_INFO *)NULL; + struct MSG_MGMT_TX_REQUEST *prMgmtTxMsg = + (struct MSG_MGMT_TX_REQUEST *)NULL; + struct MSDU_INFO *prMgmtFrame = (struct MSDU_INFO *)NULL; + struct _ACTION_VENDOR_SPEC_FRAME_T *prVendorSpec = NULL; + uint8_t *pucFrameBuf = (uint8_t *) NULL; + struct NCHO_INFO *prNchoInfo = NULL; + uint16_t u2PktLen = 0; + uint8_t ucBssIndex = 0; + + do { + prMgmtTxMsg = (struct MSG_MGMT_TX_REQUEST *)prMsgHdr; + + ucBssIndex = prMgmtTxMsg->ucBssIdx; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prNchoInfo = &(prAdapter->rNchoInfo); + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + + if (prAisFsmInfo == NULL) + break; + + u2PktLen = + (uint16_t) OFFSET_OF(struct _ACTION_VENDOR_SPEC_FRAME_T, + aucElemInfo[0]) + + prNchoInfo->rParamActionFrame.i4len + MAC_TX_RESERVED_FIELD; + prMgmtFrame = cnmMgtPktAlloc(prAdapter, u2PktLen); + if (prMgmtFrame == NULL) { + DBGLOG(REQ, ERROR, + "NCHO there is no memory for prMgmtFrame\n"); + break; + } + prMgmtTxMsg->prMgmtMsduInfo = prMgmtFrame; + + pucFrameBuf = + (uint8_t *) ((unsigned long)prMgmtFrame->prPacket + + MAC_TX_RESERVED_FIELD); + prVendorSpec = + (struct _ACTION_VENDOR_SPEC_FRAME_T *)pucFrameBuf; + prVendorSpec->u2FrameCtrl = MAC_FRAME_ACTION; + prVendorSpec->u2Duration = 0; + prVendorSpec->u2SeqCtrl = 0; + COPY_MAC_ADDR(prVendorSpec->aucDestAddr, + prNchoInfo->rParamActionFrame.aucBssid); + COPY_MAC_ADDR(prVendorSpec->aucSrcAddr, + prAisBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prVendorSpec->aucBSSID, prAisBssInfo->aucBSSID); + + kalMemCopy(prVendorSpec->aucElemInfo, + prNchoInfo->rParamActionFrame.aucData, + prNchoInfo->rParamActionFrame.i4len); + + prMgmtFrame->u2FrameLength = u2PktLen; + + aisFuncTxMgmtFrame(prAdapter, + &prAisFsmInfo->rMgmtTxInfo, + prMgmtTxMsg->prMgmtMsduInfo, + prMgmtTxMsg->u8Cookie, + ucBssIndex); + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* aisFsmRunEventNchoActionFrameTx */ +#endif + +void aisFsmRunEventChannelTimeout(IN struct ADAPTER *prAdapter, + unsigned long ulParamPtr) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prAisBssInfo; + uint8_t ucBssIndex = (uint8_t) ulParamPtr; + + DEBUGFUNC("aisFsmRunEventRemainOnChannel()"); + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + + if (prAisFsmInfo->eCurrentState == AIS_STATE_REMAIN_ON_CHANNEL) { + /* 1. release channel */ + aisFsmReleaseCh(prAdapter, ucBssIndex); + + /* 2. stop channel timeout timer */ + cnmTimerStopTimer(prAdapter, + &prAisFsmInfo->rChannelTimeoutTimer); + + /* 3. expiration indication to upper layer */ + kalRemainOnChannelExpired(prAdapter->prGlueInfo, + prAisFsmInfo->rChReqInfo.u8Cookie, + prAisFsmInfo->rChReqInfo.eBand, + prAisFsmInfo->rChReqInfo.eSco, + prAisFsmInfo->rChReqInfo.ucChannelNum, + ucBssIndex); + + /* 4. decide which state to retreat */ + if (prAisBssInfo->eConnectionState == + MEDIA_STATE_CONNECTED) + aisFsmSteps(prAdapter, AIS_STATE_NORMAL_TR, + ucBssIndex); + else + aisFsmSteps(prAdapter, AIS_STATE_IDLE, + ucBssIndex); + + } else if (prAisFsmInfo->eCurrentState == AIS_STATE_OFF_CHNL_TX) { + aisFsmSteps(prAdapter, AIS_STATE_OFF_CHNL_TX, + ucBssIndex); + } else { + DBGLOG(AIS, WARN, + "Unexpected remain_on_channel timeout event\n"); + DBGLOG(AIS, STATE, "CURRENT State: [%s]\n", + aisGetFsmState(prAisFsmInfo->eCurrentState)); + } +} + +uint32_t +aisFsmRunEventMgmtFrameTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct AIS_MGMT_TX_REQ_INFO *prMgmtTxReqInfo = + (struct AIS_MGMT_TX_REQ_INFO *)NULL; + u_int8_t fgIsSuccess = FALSE; + uint64_t *pu8GlCookie = (uint64_t *) NULL; + uint8_t ucBssIndex = 0; + + do { + ucBssIndex = prMsduInfo->ucBssIndex; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prMgmtTxReqInfo = &(prAisFsmInfo->rMgmtTxInfo); + pu8GlCookie = + (uint64_t *) ((unsigned long) prMsduInfo->prPacket + + (unsigned long) prMsduInfo->u2FrameLength + + MAC_TX_RESERVED_FIELD); + + if (rTxDoneStatus != TX_RESULT_SUCCESS) { + DBGLOG(AIS, ERROR, "Mgmt Frame TX Fail, Status:%d.\n", + rTxDoneStatus); + } else { + fgIsSuccess = TRUE; + DBGLOG(AIS, INFO, + "Mgmt Frame TX Success, cookie: 0x%llx.\n", + *pu8GlCookie); +#if CFG_SUPPORT_NCHO + if (prAdapter->rNchoInfo.fgNCHOEnabled == TRUE && + prAdapter->rNchoInfo.fgIsSendingAF == TRUE && + prAdapter->rNchoInfo.fgChGranted == TRUE) { + prAdapter->rNchoInfo.fgIsSendingAF = FALSE; + DBGLOG(AIS, TRACE, "NCHO action frame tx done"); + } +#endif + } + + if (prMgmtTxReqInfo->prMgmtTxMsdu == prMsduInfo) { + kalIndicateMgmtTxStatus(prAdapter->prGlueInfo, + prMgmtTxReqInfo->u8Cookie, + fgIsSuccess, + prMsduInfo->prPacket, + (uint32_t) + prMsduInfo->u2FrameLength, + ucBssIndex); + + prMgmtTxReqInfo->prMgmtTxMsdu = NULL; + } + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; + +} /* aisFsmRunEventMgmtFrameTxDone */ + +uint32_t +aisFuncTxMgmtFrame(IN struct ADAPTER *prAdapter, + IN struct AIS_MGMT_TX_REQ_INFO *prMgmtTxReqInfo, + IN struct MSDU_INFO *prMgmtTxMsdu, IN uint64_t u8Cookie, + IN uint8_t ucBssIndex) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct MSDU_INFO *prTxMsduInfo = (struct MSDU_INFO *)NULL; + struct WLAN_MAC_HEADER *prWlanHdr = (struct WLAN_MAC_HEADER *)NULL; + struct STA_RECORD *prStaRec = (struct STA_RECORD *)NULL; + uint32_t ucStaRecIdx = STA_REC_INDEX_NOT_FOUND; + + do { + if (prMgmtTxReqInfo->fgIsMgmtTxRequested) { + + /* 1. prMgmtTxReqInfo->prMgmtTxMsdu != NULL */ + /* Packet on driver, not done yet, drop it. */ + prTxMsduInfo = prMgmtTxReqInfo->prMgmtTxMsdu; + if (prTxMsduInfo != NULL) { + + kalIndicateMgmtTxStatus(prAdapter->prGlueInfo, + prMgmtTxReqInfo->u8Cookie, + FALSE, + prTxMsduInfo->prPacket, + (uint32_t) + prTxMsduInfo->u2FrameLength, + ucBssIndex); + + /* Leave it to TX Done handler. */ + /* cnmMgtPktFree(prAdapter, prTxMsduInfo); */ + prMgmtTxReqInfo->prMgmtTxMsdu = NULL; + } + /* 2. prMgmtTxReqInfo->prMgmtTxMsdu == NULL */ + /* Packet transmitted, wait tx done. (cookie issue) */ + } + + prWlanHdr = + (struct WLAN_MAC_HEADER *)((unsigned long) + prMgmtTxMsdu->prPacket + + MAC_TX_RESERVED_FIELD); + prStaRec = + cnmGetStaRecByAddress(prAdapter, + ucBssIndex, + prWlanHdr->aucAddr1); + + if (IS_BMCAST_MAC_ADDR(prWlanHdr->aucAddr1)) + ucStaRecIdx = STA_REC_INDEX_BMCAST; + + if (prStaRec) + ucStaRecIdx = prStaRec->ucIndex; + + TX_SET_MMPDU(prAdapter, + prMgmtTxMsdu, + (prStaRec != + NULL) ? (prStaRec-> + ucBssIndex) + : (ucBssIndex), + ucStaRecIdx, + WLAN_MAC_MGMT_HEADER_LEN, + prMgmtTxMsdu->u2FrameLength, + aisFsmRunEventMgmtFrameTxDone, + MSDU_RATE_MODE_AUTO); + prMgmtTxReqInfo->u8Cookie = u8Cookie; + prMgmtTxReqInfo->prMgmtTxMsdu = prMgmtTxMsdu; + prMgmtTxReqInfo->fgIsMgmtTxRequested = TRUE; + + + nicTxConfigPktControlFlag(prMgmtTxMsdu, + MSDU_CONTROL_FLAG_FORCE_TX, TRUE); + + /* send to TX queue */ + nicTxEnqueueMsdu(prAdapter, prMgmtTxMsdu); + + } while (FALSE); + + return rWlanStatus; +} /* aisFuncTxMgmtFrame */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will validate the Rx Action Frame and indicate to uppoer + * layer if the specified conditions were matched. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] prSwRfb Pointer to SW RFB data structure. + * @param[out] pu4ControlFlags Control flags for replying the Probe Response + * + * @retval none + */ +/*----------------------------------------------------------------------------*/ +void aisFuncValidateRxActionFrame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct AIS_FSM_INFO *prAisFsmInfo = (struct AIS_FSM_INFO *)NULL; + uint8_t ucBssIndex = 0; + + DEBUGFUNC("aisFuncValidateRxActionFrame"); + + do { + if (prSwRfb->prStaRec) + ucBssIndex = prSwRfb->prStaRec->ucBssIndex; + + prAisFsmInfo + = aisGetAisFsmInfo(prAdapter, ucBssIndex); + + if (1 + /* prAisFsmInfo->u4AisPacketFilter & + * PARAM_PACKET_FILTER_ACTION_FRAME + */ + ) { + /* Leave the action frame to wpa_supplicant. */ + kalIndicateRxMgmtFrame(prAdapter->prGlueInfo, prSwRfb, + ucBssIndex); + } + + } while (FALSE); + + return; + +} /* aisFuncValidateRxActionFrame */ + +/* Support AP Selection */ +void aisRefreshFWKBlacklist(struct ADAPTER *prAdapter) +{ + struct AIS_BLACKLIST_ITEM *prEntry = NULL; + struct LINK *prBlackList = &prAdapter->rWifiVar.rBlackList.rUsingLink; + + DBGLOG(AIS, INFO, + "Refresh all the BSSes' fgIsInFWKBlacklist to FALSE\n"); + + LINK_FOR_EACH_ENTRY(prEntry, prBlackList, rLinkEntry, + struct AIS_BLACKLIST_ITEM) { + prEntry->fgIsInFWKBlacklist = FALSE; + } +} + +struct AIS_BLACKLIST_ITEM *aisAddBlacklist(struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc) +{ + struct AIS_BLACKLIST_ITEM *prEntry = NULL; + struct LINK_MGMT *prBlackList = &prAdapter->rWifiVar.rBlackList; + + if (!prBssDesc) { + DBGLOG(AIS, ERROR, "bss descriptor is NULL\n"); + return NULL; + } + if (prBssDesc->prBlack) { + GET_CURRENT_SYSTIME(&prBssDesc->prBlack->rAddTime); + prBssDesc->prBlack->ucCount++; + if (prBssDesc->prBlack->ucCount > 10) + prBssDesc->prBlack->ucCount = 10; + DBGLOG(AIS, INFO, "update blacklist for " MACSTR + ", count %d\n", + MAC2STR(prBssDesc->aucBSSID), + prBssDesc->prBlack->ucCount); + return prBssDesc->prBlack; + } + + prEntry = aisQueryBlackList(prAdapter, prBssDesc); + + if (prEntry) { + GET_CURRENT_SYSTIME(&prEntry->rAddTime); + prBssDesc->prBlack = prEntry; + prEntry->ucCount++; + if (prEntry->ucCount > 10) + prEntry->ucCount = 10; + DBGLOG(AIS, INFO, "update blacklist for " MACSTR + ", count %d\n", + MAC2STR(prBssDesc->aucBSSID), prEntry->ucCount); + return prEntry; + } + LINK_MGMT_GET_ENTRY(prBlackList, prEntry, struct AIS_BLACKLIST_ITEM, + VIR_MEM_TYPE); + if (!prEntry) { + DBGLOG(AIS, WARN, "No memory to allocate\n"); + return NULL; + } + prEntry->ucCount = 1; + /* Support AP Selection */ + prEntry->fgIsInFWKBlacklist = FALSE; + COPY_MAC_ADDR(prEntry->aucBSSID, prBssDesc->aucBSSID); + COPY_SSID(prEntry->aucSSID, prEntry->ucSSIDLen, prBssDesc->aucSSID, + prBssDesc->ucSSIDLen); + GET_CURRENT_SYSTIME(&prEntry->rAddTime); + prBssDesc->prBlack = prEntry; + + DBGLOG(AIS, INFO, "Add " MACSTR " to black List\n", + MAC2STR(prBssDesc->aucBSSID)); + return prEntry; +} + +void aisRemoveBlackList(struct ADAPTER *prAdapter, struct BSS_DESC *prBssDesc) +{ + struct AIS_BLACKLIST_ITEM *prEntry = NULL; + + prEntry = aisQueryBlackList(prAdapter, prBssDesc); + if (!prEntry) + return; + LINK_MGMT_RETURN_ENTRY(&prAdapter->rWifiVar.rBlackList, prEntry); + prBssDesc->prBlack = NULL; + DBGLOG(AIS, INFO, "Remove " MACSTR " from blacklist\n", + MAC2STR(prBssDesc->aucBSSID)); +} + +struct AIS_BLACKLIST_ITEM *aisQueryBlackList(struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc) +{ + struct AIS_BLACKLIST_ITEM *prEntry = NULL; + struct LINK *prBlackList = &prAdapter->rWifiVar.rBlackList.rUsingLink; + + if (!prBssDesc) + return NULL; + else if (prBssDesc->prBlack) + return prBssDesc->prBlack; + + LINK_FOR_EACH_ENTRY(prEntry, prBlackList, rLinkEntry, + struct AIS_BLACKLIST_ITEM) { + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prEntry) && + EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, + prEntry->aucSSID, prEntry->ucSSIDLen)) { + prBssDesc->prBlack = prEntry; + return prEntry; + } + } + DBGLOG(AIS, TRACE, MACSTR " is not in blacklist\n", + MAC2STR(prBssDesc->aucBSSID)); + return NULL; +} + +void aisRemoveTimeoutBlacklist(struct ADAPTER *prAdapter) +{ + struct AIS_BLACKLIST_ITEM *prEntry = NULL; + struct AIS_BLACKLIST_ITEM *prNextEntry = NULL; + struct LINK *prBlackList = &prAdapter->rWifiVar.rBlackList.rUsingLink; + OS_SYSTIME rCurrent; + struct BSS_DESC *prBssDesc = NULL; + + GET_CURRENT_SYSTIME(&rCurrent); + + LINK_FOR_EACH_ENTRY_SAFE(prEntry, prNextEntry, prBlackList, rLinkEntry, + struct AIS_BLACKLIST_ITEM) { + if (prEntry->fgIsInFWKBlacklist || + !CHECK_FOR_TIMEOUT(rCurrent, prEntry->rAddTime, + SEC_TO_MSEC(AIS_BLACKLIST_TIMEOUT))) + continue; + prBssDesc = scanSearchBssDescByBssid(prAdapter, + prEntry->aucBSSID); + if (prBssDesc) { + prBssDesc->prBlack = NULL; + prBssDesc->ucJoinFailureCount = 0; + DBGLOG(AIS, INFO, + "Remove Timeout "MACSTR" from blacklist\n", + MAC2STR(prBssDesc->aucBSSID)); + } + LINK_MGMT_RETURN_ENTRY(&prAdapter->rWifiVar.rBlackList, + prEntry); + } +} + +static void aisRemoveDeauthBlacklist(struct ADAPTER *prAdapter) +{ + struct AIS_BLACKLIST_ITEM *prEntry = NULL; + struct AIS_BLACKLIST_ITEM *prNextEntry = NULL; + struct LINK *prBlackList = &prAdapter->rWifiVar.rBlackList.rUsingLink; + struct BSS_DESC *prBssDesc = NULL; + + LINK_FOR_EACH_ENTRY_SAFE(prEntry, prNextEntry, prBlackList, rLinkEntry, + struct AIS_BLACKLIST_ITEM) { + if (prEntry->fgIsInFWKBlacklist || + !prEntry->fgDeauthLastTime) + continue; + + prBssDesc = scanSearchBssDescByBssid(prAdapter, + prEntry->aucBSSID); + if (prBssDesc) { + prBssDesc->prBlack = NULL; + prBssDesc->ucJoinFailureCount = 0; + DBGLOG(AIS, INFO, + "Remove deauth "MACSTR" from blacklist\n", + MAC2STR(prBssDesc->aucBSSID)); + } + LINK_MGMT_RETURN_ENTRY(&prAdapter->rWifiVar.rBlackList, + prEntry); + } +} + +void aisFsmRunEventBssTransition(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_AIS_BSS_TRANSITION_T *prMsg = + (struct MSG_AIS_BSS_TRANSITION_T *)prMsgHdr; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecificBssInfo; + struct BSS_TRANSITION_MGT_PARAM_T *prBtmParam; + enum WNM_AIS_BSS_TRANSITION eTransType = BSS_TRANSITION_MAX_NUM; + struct BSS_DESC *prBssDesc; + struct ROAMING_INFO *prRoamingFsmInfo = NULL; + u_int8_t fgNeedBtmResponse = FALSE; + uint8_t ucStatus = BSS_TRANSITION_MGT_STATUS_UNSPECIFIED; + uint8_t ucRcvToken = 0; + static uint8_t aucChnlList[MAXIMUM_OPERATION_CHANNEL_LIST]; + uint8_t ucBssIndex = 0; + + if (!prMsg) { + DBGLOG(AIS, WARN, "Msg Header is NULL\n"); + return; + } + + ucBssIndex = prMsg->ucBssIndex; + + prAisSpecificBssInfo = + aisGetAisSpecBssInfo(prAdapter, ucBssIndex); + prBtmParam = + &prAisSpecificBssInfo->rBTMParam; + prBssDesc = + aisGetTargetBssDesc(prAdapter, ucBssIndex); + prRoamingFsmInfo = + aisGetRoamingInfo(prAdapter, ucBssIndex); + eTransType = prMsg->eTransitionType; + fgNeedBtmResponse = prMsg->fgNeedResponse; + ucRcvToken = prMsg->ucToken; + + DBGLOG(AIS, INFO, "Transition Type: %d\n", eTransType); +#if CFG_SUPPORT_802_11K + aisCollectNeighborAP(prAdapter, prMsg->pucCandList, + prMsg->u2CandListLen, prMsg->ucValidityInterval, + ucBssIndex); +#endif + cnmMemFree(prAdapter, prMsgHdr); + /* Solicited BTM request: the case we're waiting btm request + ** after send btm query before roaming scan + */ + if (prBtmParam->ucDialogToken == ucRcvToken) { + prBtmParam->fgPendingResponse = fgNeedBtmResponse; + prBtmParam->fgUnsolicitedReq = FALSE; + + switch (prRoamingFsmInfo->eCurrentState) { + case ROAMING_STATE_REQ_CAND_LIST: + roamingFsmSteps(prAdapter, ROAMING_STATE_DISCOVERY, + ucBssIndex); + return; + case ROAMING_STATE_DISCOVERY: + /* this case need to fall through */ + case ROAMING_STATE_ROAM: + ucStatus = BSS_TRANSITION_MGT_STATUS_UNSPECIFIED; + goto send_response; + default: + /* not solicited btm request, but dialog token matches + ** occasionally. + */ + break; + } + } + prBtmParam->fgUnsolicitedReq = TRUE; + /* Unsolicited BTM request */ + switch (eTransType) { + case BSS_TRANSITION_DISASSOC: + ucStatus = BSS_TRANSITION_MGT_STATUS_ACCEPT; + break; + case BSS_TRANSITION_REQ_ROAMING: + { + struct NEIGHBOR_AP_T *prNeiAP = NULL; + struct LINK *prUsingLink = + &prAisSpecificBssInfo->rNeighborApList.rUsingLink; + uint8_t i = 0; + uint8_t ucChannel = 0; + uint8_t ucChnlCnt = 0; + uint16_t u2LeftTime = 0; + + if (!prBssDesc) { + DBGLOG(AIS, ERROR, "Target Bss Desc is NULL\n"); + break; + } + prBtmParam->fgPendingResponse = fgNeedBtmResponse; + kalMemZero(aucChnlList, sizeof(aucChnlList)); + LINK_FOR_EACH_ENTRY(prNeiAP, prUsingLink, rLinkEntry, + struct NEIGHBOR_AP_T) + { + ucChannel = prNeiAP->ucChannel; + for (i = 0; + i < ucChnlCnt && ucChannel != aucChnlList[i]; i++) + ; + if (i == ucChnlCnt) + ucChnlCnt++; + } + /* reserve 1 second for association */ + u2LeftTime = prBtmParam->u2DisassocTimer * + prBssDesc->u2BeaconInterval - + 1000; + /* check if left time is enough to do partial scan, if not + ** enought, reject directly + */ + if (u2LeftTime < ucChnlCnt * prBssDesc->u2BeaconInterval) { + ucStatus = BSS_TRANSITION_MGT_STATUS_UNSPECIFIED; + goto send_response; + } + roamingFsmSteps(prAdapter, ROAMING_STATE_DISCOVERY, + ucBssIndex); + return; + } + default: + ucStatus = BSS_TRANSITION_MGT_STATUS_ACCEPT; + break; + } +send_response: + if (fgNeedBtmResponse && + aisGetAisBssInfo(prAdapter, ucBssIndex) && + aisGetStaRecOfAP(prAdapter, ucBssIndex)) { + prBtmParam->ucStatusCode = ucStatus; + prBtmParam->ucTermDelay = 0; + kalMemZero(prBtmParam->aucTargetBssid, MAC_ADDR_LEN); + prBtmParam->u2OurNeighborBssLen = 0; + prBtmParam->fgPendingResponse = FALSE; + wnmSendBTMResponseFrame(prAdapter, + aisGetStaRecOfAP(prAdapter, ucBssIndex)); + } +} + +#if CFG_SUPPORT_802_11K +void aisSendNeighborRequest(struct ADAPTER *prAdapter, + uint8_t ucBssIndex) +{ + struct SUB_ELEMENT_LIST *prSSIDIE; + uint8_t aucBuffer[sizeof(*prSSIDIE) + 31]; + struct BSS_INFO *prBssInfo + = aisGetAisBssInfo(prAdapter, ucBssIndex); + + kalMemZero(aucBuffer, sizeof(aucBuffer)); + prSSIDIE = (struct SUB_ELEMENT_LIST *)&aucBuffer[0]; + prSSIDIE->rSubIE.ucSubID = ELEM_ID_SSID; + COPY_SSID(&prSSIDIE->rSubIE.aucOptInfo[0], prSSIDIE->rSubIE.ucLength, + prBssInfo->aucSSID, prBssInfo->ucSSIDLen); + rrmTxNeighborReportRequest(prAdapter, prBssInfo->prStaRecOfAP, + prSSIDIE); +} + +static u_int8_t aisCandPrefIEIsExist(uint8_t *pucSubIe, uint8_t ucLength) +{ + uint16_t u2Offset = 0; + + IE_FOR_EACH(pucSubIe, ucLength, u2Offset) { + if (IE_ID(pucSubIe) == ELEM_ID_NR_BSS_TRANSITION_CAND_PREF) + return TRUE; + } + return FALSE; +} + +static uint8_t aisGetNeighborApPreference(uint8_t *pucSubIe, uint8_t ucLength) +{ + uint16_t u2Offset = 0; + + IE_FOR_EACH(pucSubIe, ucLength, u2Offset) { + if (IE_ID(pucSubIe) == ELEM_ID_NR_BSS_TRANSITION_CAND_PREF) + return pucSubIe[2]; + } + /* If no preference element is presence, give default value(lowest) 0, + */ + /* but it will not be used as a reference. */ + return 0; +} + +static uint64_t aisGetBssTermTsf(uint8_t *pucSubIe, uint8_t ucLength) +{ + uint16_t u2Offset = 0; + + IE_FOR_EACH(pucSubIe, ucLength, u2Offset) { + if (IE_ID(pucSubIe) == ELEM_ID_NR_BSS_TERMINATION_DURATION) + return *(uint64_t *) &pucSubIe[2]; + } + /* If no preference element is presence, give default value(lowest) 0 */ + return 0; +} + +void aisCollectNeighborAP(struct ADAPTER *prAdapter, uint8_t *pucApBuf, + uint16_t u2ApBufLen, uint8_t ucValidInterval, + uint8_t ucBssIndex) +{ + struct NEIGHBOR_AP_T *prNeighborAP = NULL; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecBssInfo = + aisGetAisSpecBssInfo(prAdapter, ucBssIndex); + struct LINK_MGMT *prAPlist = &prAisSpecBssInfo->rNeighborApList; + struct IE_NEIGHBOR_REPORT *prIe = (struct IE_NEIGHBOR_REPORT *)pucApBuf; + int16_t c2BufLen; + uint16_t u2PrefIsZeroCount = 0; + + if (!prIe || !u2ApBufLen || u2ApBufLen < prIe->ucLength) + return; + LINK_MERGE_TO_TAIL(&prAPlist->rFreeLink, &prAPlist->rUsingLink); + for (c2BufLen = u2ApBufLen; c2BufLen > 0; c2BufLen -= IE_SIZE(prIe), + prIe = (struct IE_NEIGHBOR_REPORT *)((uint8_t *) prIe + + IE_SIZE(prIe))) { + /* BIT0-1: AP reachable, BIT2: same security with current + ** setting, + ** BIT3: same authenticator with current AP + */ + if (prIe->ucId != ELEM_ID_NEIGHBOR_REPORT || + (prIe->u4BSSIDInfo & 0x7) != 0x7) + continue; + LINK_MGMT_GET_ENTRY(prAPlist, prNeighborAP, + struct NEIGHBOR_AP_T, VIR_MEM_TYPE); + if (!prNeighborAP) + break; + prNeighborAP->fgHT = !!(prIe->u4BSSIDInfo & BIT(11)); + prNeighborAP->fgFromBtm = !!ucValidInterval; + prNeighborAP->fgRmEnabled = !!(prIe->u4BSSIDInfo & BIT(7)); + prNeighborAP->fgQoS = !!(prIe->u4BSSIDInfo & BIT(5)); + prNeighborAP->fgSameMD = !!(prIe->u4BSSIDInfo & BIT(10)); + prNeighborAP->ucChannel = prIe->ucChnlNumber; + prNeighborAP->fgPrefPresence = aisCandPrefIEIsExist( + prIe->aucSubElem, + IE_SIZE(prIe) - OFFSET_OF(struct IE_NEIGHBOR_REPORT, + aucSubElem)); + prNeighborAP->ucPreference = aisGetNeighborApPreference( + prIe->aucSubElem, + IE_SIZE(prIe) - OFFSET_OF(struct IE_NEIGHBOR_REPORT, + aucSubElem)); + prNeighborAP->u8TermTsf = aisGetBssTermTsf( + prIe->aucSubElem, + IE_SIZE(prIe) - OFFSET_OF(struct IE_NEIGHBOR_REPORT, + aucSubElem)); + COPY_MAC_ADDR(prNeighborAP->aucBssid, prIe->aucBSSID); + DBGLOG(AIS, INFO, + "Bssid" MACSTR + ", PrefPresence %d, Pref %d, Chnl %d, BssidInfo 0x%08x\n", + MAC2STR(prNeighborAP->aucBssid), + prNeighborAP->fgPrefPresence, + prNeighborAP->ucPreference, prIe->ucChnlNumber, + prIe->u4BSSIDInfo); + /* No need to save neighbor ap list with decendant preference + ** for (prTemp = LINK_ENTRY(prAPlist->rUsingLink.prNext, struct + ** NEIGHBOR_AP_T, rLinkEntry); + ** prTemp != prNeighborAP; + ** prTemp = LINK_ENTRY(prTemp->rLinkEntry.prNext, struct + ** NEIGHBOR_AP_T, rLinkEntry)) { + ** if (prTemp->ucPreference < prNeighborAP->ucPreference) { + ** __linkDel(prNeighborAP->rLinkEntry.prPrev, + ** prNeighborAP->rLinkEntry.prNext); + ** __linkAdd(&prNeighborAP->rLinkEntry, + ** prTemp->rLinkEntry.prPrev, &prTemp->rLinkEntry); + ** break; + ** } + ** } + */ + if (prNeighborAP->fgPrefPresence && + prNeighborAP->ucPreference == 0) + u2PrefIsZeroCount++; + + if (c2BufLen < IE_SIZE(prIe)) { + DBGLOG(AIS, WARN, "Truncated neighbor report\n"); + break; + } + } + prAisSpecBssInfo->rNeiApRcvTime = kalGetTimeTick(); + prAisSpecBssInfo->u4NeiApValidInterval = + !ucValidInterval + ? 0xffffffff + : TU_TO_MSEC(ucValidInterval * + aisGetAisBssInfo(prAdapter, ucBssIndex) + ->u2BeaconInterval); + + if (prAPlist->rUsingLink.u4NumElem > 0 && + prAPlist->rUsingLink.u4NumElem == u2PrefIsZeroCount) + DBGLOG(AIS, INFO, + "The number of valid neighbors is equal to the number of perf value is 0.\n"); +} + +void aisResetNeighborApList(IN struct ADAPTER *prAdapter, + uint8_t ucBssIndex) +{ + struct AIS_SPECIFIC_BSS_INFO *prAisSpecBssInfo = + aisGetAisSpecBssInfo(prAdapter, ucBssIndex); + struct LINK_MGMT *prAPlist = &prAisSpecBssInfo->rNeighborApList; + + LINK_MERGE_TO_TAIL(&prAPlist->rFreeLink, &prAPlist->rUsingLink); +} +#endif + +void aisFsmRunEventCancelTxWait(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct AIS_FSM_INFO *prAisFsmInfo = + (struct AIS_FSM_INFO *) NULL; + struct MSG_CANCEL_TX_WAIT_REQUEST *prCancelTxWaitMsg = + (struct MSG_CANCEL_TX_WAIT_REQUEST *) NULL; + struct BSS_INFO *prAisBssInfo = (struct BSS_INFO *) NULL; + struct AIS_MGMT_TX_REQ_INFO *prMgmtTxInfo = + (struct AIS_MGMT_TX_REQ_INFO *) NULL; + struct AIS_OFF_CHNL_TX_REQ_INFO *prOffChnlTxPkt = + (struct AIS_OFF_CHNL_TX_REQ_INFO *) NULL; + u_int8_t fgIsCookieFound = FALSE; + uint8_t ucBssIndex = 0; + + if (prAdapter == NULL || prMsgHdr == NULL) + goto exit; + + prCancelTxWaitMsg = (struct MSG_CANCEL_TX_WAIT_REQUEST *) prMsgHdr; + + ucBssIndex = prCancelTxWaitMsg->ucBssIdx; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + prMgmtTxInfo = &prAisFsmInfo->rMgmtTxInfo; + + if (prAisFsmInfo == NULL || + prAisBssInfo == NULL || prMgmtTxInfo == NULL) + goto exit; + + LINK_FOR_EACH_ENTRY(prOffChnlTxPkt, + &(prMgmtTxInfo->rTxReqLink), + rLinkEntry, + struct AIS_OFF_CHNL_TX_REQ_INFO) { + if (!prOffChnlTxPkt) + break; + if (prOffChnlTxPkt->u8Cookie == prCancelTxWaitMsg->u8Cookie) { + fgIsCookieFound = TRUE; + break; + } + } + + if (fgIsCookieFound == FALSE && prAisFsmInfo->eCurrentState != + AIS_STATE_OFF_CHNL_TX) + goto exit; + + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer); + aisFunClearAllTxReq(prAdapter, &(prAisFsmInfo->rMgmtTxInfo)); + aisFsmReleaseCh(prAdapter, ucBssIndex); + + if (prAisBssInfo->eConnectionState == + MEDIA_STATE_CONNECTED) + aisFsmSteps(prAdapter, AIS_STATE_NORMAL_TR, ucBssIndex); + else + aisFsmSteps(prAdapter, AIS_STATE_IDLE, ucBssIndex); + +exit: + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} + +static void +aisFunClearAllTxReq(IN struct ADAPTER *prAdapter, + IN struct AIS_MGMT_TX_REQ_INFO *prAisMgmtTxInfo) +{ + struct AIS_OFF_CHNL_TX_REQ_INFO *prOffChnlTxPkt = + (struct AIS_OFF_CHNL_TX_REQ_INFO *) NULL; + + while (!LINK_IS_EMPTY(&(prAisMgmtTxInfo->rTxReqLink))) { + LINK_REMOVE_HEAD(&(prAisMgmtTxInfo->rTxReqLink), + prOffChnlTxPkt, + struct AIS_OFF_CHNL_TX_REQ_INFO *); + if (!prOffChnlTxPkt) + continue; + kalIndicateMgmtTxStatus(prAdapter->prGlueInfo, + prOffChnlTxPkt->u8Cookie, + FALSE, + prOffChnlTxPkt->prMgmtTxMsdu->prPacket, + (uint32_t) prOffChnlTxPkt->prMgmtTxMsdu->u2FrameLength, + prOffChnlTxPkt->prMgmtTxMsdu->ucBssIndex); + cnmPktFree(prAdapter, prOffChnlTxPkt->prMgmtTxMsdu); + cnmMemFree(prAdapter, prOffChnlTxPkt); + } +} + +struct AIS_FSM_INFO *aisGetAisFsmInfo( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + return &(prAdapter->rWifiVar.rAisFsmInfo[ucBssIndex]); +} + +struct AIS_SPECIFIC_BSS_INFO *aisGetAisSpecBssInfo( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + return &(prAdapter->rWifiVar.rAisSpecificBssInfo[ucBssIndex]); +} + +struct BSS_TRANSITION_MGT_PARAM_T * + aisGetBTMParam( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + return &prAdapter->rWifiVar. + rAisSpecificBssInfo[ucBssIndex].rBTMParam; +} + +struct BSS_INFO *aisGetConnectedBssInfo( + IN struct ADAPTER *prAdapter) { + + struct BSS_INFO *prBssInfo; + uint8_t i; + + if (!prAdapter) + return NULL; + + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + + if (prBssInfo && + IS_BSS_AIS(prBssInfo) && + kalGetMediaStateIndicated( + prAdapter->prGlueInfo, + prBssInfo->ucBssIndex) == + MEDIA_STATE_CONNECTED) { + return prBssInfo; + } + } + + return NULL; +} + +struct BSS_INFO *aisGetAisBssInfo( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + return prAdapter->aprBssInfo[ucBssIndex]; +} + +struct STA_RECORD *aisGetStaRecOfAP( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + if (prAdapter->aprBssInfo[ucBssIndex]) + return prAdapter->aprBssInfo[ucBssIndex]->prStaRecOfAP; + + DBGLOG(AIS, WARN, "prStaRecOfAP is Null\n"); + return NULL; +} + +struct BSS_DESC *aisGetTargetBssDesc( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + return prAdapter->rWifiVar + .rAisFsmInfo[ucBssIndex].prTargetBssDesc; +} + +struct STA_RECORD *aisGetTargetStaRec( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + return prAdapter->rWifiVar.rAisFsmInfo[ucBssIndex].prTargetStaRec; +} + +uint8_t aisGetTargetBssDescChannel( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + return prAdapter->rWifiVar + .rAisFsmInfo[ucBssIndex].prTargetBssDesc->ucChannelNum; +} + +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE +struct TIMER *aisGetSecModeChangeTimer( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + return + &prAdapter->rWifiVar + .rAisFsmInfo[ucBssIndex].rSecModeChangeTimer; +} +#endif + +struct TIMER *aisGetScanDoneTimer( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + return + &prAdapter->rWifiVar + .rAisFsmInfo[ucBssIndex].rScanDoneTimer; +} + +enum ENUM_AIS_STATE aisGetCurrState( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + return + prAdapter->rWifiVar + .rAisFsmInfo[ucBssIndex].eCurrentState; +} + +struct CONNECTION_SETTINGS * + aisGetConnSettings( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + return &(prAdapter->rWifiVar.rConnSettings[ucBssIndex]); +} + +struct GL_WPA_INFO *aisGetWpaInfo( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + return &prAdapter->prGlueInfo->rWpaInfo[ucBssIndex]; +} + +u_int8_t aisGetWapiMode( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + return prAdapter->rWifiVar.rConnSettings[ucBssIndex].fgWapiMode; +} + +enum ENUM_PARAM_AUTH_MODE aisGetAuthMode( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + return prAdapter->rWifiVar.rConnSettings[ucBssIndex].eAuthMode; +} + +enum ENUM_PARAM_OP_MODE aisGetOPMode( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + return prAdapter->rWifiVar.rConnSettings[ucBssIndex].eOPMode; +} + +enum ENUM_WEP_STATUS aisGetEncStatus( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + return prAdapter->rWifiVar.rConnSettings[ucBssIndex].eEncStatus; +} + +struct IEEE_802_11_MIB *aisGetMib( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + return &prAdapter->rMib[ucBssIndex]; +} + +struct ROAMING_INFO *aisGetRoamingInfo( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + return &(prAdapter->rWifiVar.rRoamingInfo[ucBssIndex]); +} + +struct PARAM_BSSID_EX *aisGetCurrBssId( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + return &(prAdapter->rWlanInfo.rCurrBssId[ucBssIndex]); +} + +#if CFG_SUPPORT_PASSPOINT +struct HS20_INFO *aisGetHS20Info( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + return &(prAdapter->rWifiVar.rHS20Info[ucBssIndex]); +} +#endif + +struct RADIO_MEASUREMENT_REQ_PARAMS *aisGetRmReqParam( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + return &(prAdapter->rWifiVar.rRmReqParams[ucBssIndex]); +} + +struct RADIO_MEASUREMENT_REPORT_PARAMS * + aisGetRmReportParam( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + return &(prAdapter->rWifiVar.rRmRepParams[ucBssIndex]); +} + +struct WMM_INFO * + aisGetWMMInfo( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + return &(prAdapter->rWifiVar.rWmmInfo[ucBssIndex]); +} + +#ifdef CFG_SUPPORT_REPLAY_DETECTION +struct GL_DETECT_REPLAY_INFO * + aisGetDetRplyInfo( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + return &(prAdapter->prGlueInfo->prDetRplyInfo[ucBssIndex]); +} +#endif + +struct FT_IES * + aisGetFtIe( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + return &(prAdapter->rWifiVar.rConnSettings[ucBssIndex].rFtIeForTx); +} + +struct cfg80211_ft_event_params * + aisGetFtEventParam( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) { + + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) { + DBGLOG(AIS, LOUD, + "Use default, invalid index = %d\n", ucBssIndex); + ucBssIndex = AIS_DEFAULT_INDEX; + } + + return &(prAdapter->rWifiVar.rConnSettings[ucBssIndex].rFtEventParam); +} + +uint8_t * + aisGetFsmState( + IN enum ENUM_AIS_STATE eCurrentState) { + if (eCurrentState >= 0 && eCurrentState < AIS_STATE_NUM) + return apucDebugAisState[eCurrentState]; + + ASSERT(0); + return (uint8_t *) NULL; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/ap_selection.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/ap_selection.c new file mode 100644 index 0000000000000..4ba25bac2b904 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/ap_selection.c @@ -0,0 +1,1368 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +#include "precomp.h" + +/* + * definition for AP selection algrithm + */ +#define BSS_FULL_SCORE (100) +#define CHNL_BSS_NUM_THRESOLD 100 +#define BSS_STA_CNT_THRESOLD 30 +#define SCORE_PER_AP 1 +#define ROAMING_NO_SWING_SCORE_STEP 100 +/* MCS9 at BW 160 requires rssi at least -48dbm */ +#define BEST_RSSI -48 +/* MCS7 at 20BW, MCS5 at 40BW, MCS4 at 80BW, MCS3 at 160BW */ +#define GOOD_RSSI_FOR_HT_VHT -64 +/* Link speed 1Mbps need at least rssi -94dbm for 2.4G */ +#define MINIMUM_RSSI_2G4 -94 +/* Link speed 6Mbps need at least rssi -86dbm for 5G */ +#define MINIMUM_RSSI_5G -86 + +/* level of rssi range on StatusBar */ +#define RSSI_MAX_LEVEL -55 +#define RSSI_SECOND_LEVEL -66 + +#if CFG_TC10_FEATURE +#define RCPI_FOR_DONT_ROAM 80 /*-70dbm*/ +#else +#define RCPI_FOR_DONT_ROAM 60 /*-80dbm*/ +#endif + +/* Real Rssi of a Bss may range in current_rssi - 5 dbm + *to current_rssi + 5 dbm + */ +#define RSSI_DIFF_BETWEEN_BSS 10 /* dbm */ +#define LOW_RSSI_FOR_5G_BAND -70 /* dbm */ +#define HIGH_RSSI_FOR_5G_BAND -60 /* dbm */ + +/* Support driver triggers roaming */ +#define RCPI_DIFF_DRIVER_ROAM 20 /* 10 dbm */ + +/* In case 2.4G->5G, the trigger rssi is RSSI_BAD_NEED_ROAM_24G_TO_5G + * In other case(2.4G->2.4G/5G->2.4G/5G->5G), the trigger + * rssi is RSSI_BAD_NEED_ROAM + * + * The reason of using two rssi threshold is that we only + * want to benifit 2.4G->5G case, and keep original logic in + * other cases. + */ +#define RSSI_BAD_NEED_ROAM_24G_TO_5G -40 /* dbm */ +#define RSSI_BAD_NEED_ROAM -80 /* dbm */ + +#define CHNL_DWELL_TIME_DEFAULT 100 +#define CHNL_DWELL_TIME_ONLINE 50 + +/* When roam to 5G AP, the AP's rcpi should great than + * RCPI_THRESHOLD_ROAM_2_5G dbm + */ +#define RCPI_THRESHOLD_ROAM_TO_5G 90 /* rssi -65 */ + +#define WEIGHT_IDX_CHNL_UTIL 0 +#define WEIGHT_IDX_RSSI 2 +#define WEIGHT_IDX_SCN_MISS_CNT 2 +#define WEIGHT_IDX_PROBE_RSP 1 +#define WEIGHT_IDX_CLIENT_CNT 0 +#define WEIGHT_IDX_AP_NUM 0 +#define WEIGHT_IDX_5G_BAND 2 +#define WEIGHT_IDX_BAND_WIDTH 1 +#define WEIGHT_IDX_STBC 1 +#define WEIGHT_IDX_DEAUTH_LAST 1 +#define WEIGHT_IDX_BLACK_LIST 2 +#define WEIGHT_IDX_SAA 0 +#define WEIGHT_IDX_CHNL_IDLE 0 +#define WEIGHT_IDX_OPCHNL 0 + +#define WEIGHT_IDX_CHNL_UTIL_PER 0 +#define WEIGHT_IDX_RSSI_PER 4 +#define WEIGHT_IDX_SCN_MISS_CNT_PER 4 +#define WEIGHT_IDX_PROBE_RSP_PER 1 +#define WEIGHT_IDX_CLIENT_CNT_PER 1 +#define WEIGHT_IDX_AP_NUM_PER 6 +#define WEIGHT_IDX_5G_BAND_PER 4 +#define WEIGHT_IDX_BAND_WIDTH_PER 1 +#define WEIGHT_IDX_STBC_PER 1 +#define WEIGHT_IDX_DEAUTH_LAST_PER 1 +#define WEIGHT_IDX_BLACK_LIST_PER 4 +#define WEIGHT_IDX_SAA_PER 1 +#define WEIGHT_IDX_CHNL_IDLE_PER 6 +#define WEIGHT_IDX_OPCHNL_PER 6 + +struct WEIGHT_CONFIG { + uint8_t ucChnlUtilWeight; + uint8_t ucSnrWeight; + uint8_t ucRssiWeight; + uint8_t ucScanMissCntWeight; + uint8_t ucProbeRespWeight; + uint8_t ucClientCntWeight; + uint8_t ucApNumWeight; + uint8_t ucBandWeight; + uint8_t ucBandWidthWeight; + uint8_t ucStbcWeight; + uint8_t ucLastDeauthWeight; + uint8_t ucBlackListWeight; + uint8_t ucSaaWeight; + uint8_t ucChnlIdleWeight; + uint8_t ucOpchnlWeight; +}; + +struct WEIGHT_CONFIG gasMtkWeightConfig[ROAM_TYPE_NUM] = { + [ROAM_TYPE_RCPI] = { + .ucChnlUtilWeight = WEIGHT_IDX_CHNL_UTIL, + .ucRssiWeight = WEIGHT_IDX_RSSI, + .ucScanMissCntWeight = WEIGHT_IDX_SCN_MISS_CNT, + .ucProbeRespWeight = WEIGHT_IDX_PROBE_RSP, + .ucClientCntWeight = WEIGHT_IDX_CLIENT_CNT, + .ucApNumWeight = WEIGHT_IDX_AP_NUM, + .ucBandWeight = WEIGHT_IDX_5G_BAND, + .ucBandWidthWeight = WEIGHT_IDX_BAND_WIDTH, + .ucStbcWeight = WEIGHT_IDX_STBC, + .ucLastDeauthWeight = WEIGHT_IDX_DEAUTH_LAST, + .ucBlackListWeight = WEIGHT_IDX_BLACK_LIST, + .ucSaaWeight = WEIGHT_IDX_SAA, + .ucChnlIdleWeight = WEIGHT_IDX_CHNL_IDLE, + .ucOpchnlWeight = WEIGHT_IDX_OPCHNL + }, + [ROAM_TYPE_PER] = { + .ucChnlUtilWeight = WEIGHT_IDX_CHNL_UTIL_PER, + .ucRssiWeight = WEIGHT_IDX_RSSI_PER, + .ucScanMissCntWeight = WEIGHT_IDX_SCN_MISS_CNT_PER, + .ucProbeRespWeight = WEIGHT_IDX_PROBE_RSP_PER, + .ucClientCntWeight = WEIGHT_IDX_CLIENT_CNT_PER, + .ucApNumWeight = WEIGHT_IDX_AP_NUM_PER, + .ucBandWeight = WEIGHT_IDX_5G_BAND_PER, + .ucBandWidthWeight = WEIGHT_IDX_BAND_WIDTH_PER, + .ucStbcWeight = WEIGHT_IDX_STBC_PER, + .ucLastDeauthWeight = WEIGHT_IDX_DEAUTH_LAST_PER, + .ucBlackListWeight = WEIGHT_IDX_BLACK_LIST_PER, + .ucSaaWeight = WEIGHT_IDX_SAA_PER, + .ucChnlIdleWeight = WEIGHT_IDX_CHNL_IDLE_PER, + .ucOpchnlWeight = WEIGHT_IDX_OPCHNL_PER + } +}; + +uint8_t mtk_reason_to_type[ROAMING_REASON_NUM] = { + [0 ... ROAMING_REASON_NUM - 1] = ROAM_TYPE_RCPI, + [ROAMING_REASON_TX_ERR] = ROAM_TYPE_PER, +}; + +#if (CFG_SUPPORT_802_11AX == 1) +#define CALCULATE_SCORE_BY_AX_AP(prAdapter, prBssDesc, eRoamType) \ + ((eRoamType == ROAM_TYPE_PER) ? \ + ((prAdapter->rWifiVar).ucApSelAxWeight * \ + (prBssDesc->fgIsHEPresent ? \ + (BSS_FULL_SCORE/(prAdapter->rWifiVar).ucApSelAxScoreDiv) : 0)):0) +#endif + +#define CALCULATE_SCORE_BY_PROBE_RSP(prBssDesc, eRoamType) \ + (gasMtkWeightConfig[eRoamType].ucProbeRespWeight * \ + (prBssDesc->fgSeenProbeResp ? BSS_FULL_SCORE : 0)) + +#define CALCULATE_SCORE_BY_MISS_CNT(prAdapter, prBssDesc, eRoamType) \ + (gasMtkWeightConfig[eRoamType].ucScanMissCntWeight * \ + (prAdapter->rWifiVar.rScanInfo.u4ScanUpdateIdx - \ + prBssDesc->u4UpdateIdx > 3 ? 0 : \ + (BSS_FULL_SCORE - (prAdapter->rWifiVar.rScanInfo.u4ScanUpdateIdx - \ + prBssDesc->u4UpdateIdx) * 25))) + +#define CALCULATE_SCORE_BY_BAND(prAdapter, prBssDesc, cRssi, eRoamType) \ + (gasMtkWeightConfig[eRoamType].ucBandWeight * \ + ((prBssDesc->eBand == BAND_5G && prAdapter->fgEnable5GBand && \ + cRssi > -70) ? BSS_FULL_SCORE : 0)) + +#define CALCULATE_SCORE_BY_STBC(prAdapter, prBssDesc, eRoamType) \ + (gasMtkWeightConfig[eRoamType].ucStbcWeight * \ + (prBssDesc->fgMultiAnttenaAndSTBC ? BSS_FULL_SCORE:0)) + +#define CALCULATE_SCORE_BY_DEAUTH(prBssDesc, eRoamType) \ + (gasMtkWeightConfig[eRoamType].ucLastDeauthWeight * \ + (prBssDesc->prBlack && prBssDesc->prBlack->fgDeauthLastTime ? 0 : \ + BSS_FULL_SCORE)) + +#if CFG_SUPPORT_RSN_SCORE +#define CALCULATE_SCORE_BY_RSN(prBssDesc) \ + (WEIGHT_IDX_RSN * (prBssDesc->fgIsRSNSuitableBss ? BSS_FULL_SCORE:0)) +#endif + +#if 0 +static uint16_t scanCaculateScoreBySTBC(struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc, enum ROAM_TYPE eRoamType) +{ + uint16_t u2Score = 0; + uint8_t ucSpatial = 0; + + ucSpatial = prBssDesc->ucSpatial; + + if (prBssDesc->fgMultiAnttenaAndSTBC) { + ucSpatial = (ucSpatial >= 4)?4:ucSpatial; + u2Score = (BSS_FULL_SCORE-50)*ucSpatial; + } else { + u2Score = 0; + } + return u2Score*mtk_weight_config[eRoamType].ucStbcWeight; +} +#endif + +/* Channel Utilization: weight index will be */ +static uint16_t scanCalculateScoreByChnlInfo( + struct AIS_SPECIFIC_BSS_INFO *prAisSpecificBssInfo, uint8_t ucChannel, + enum ROAM_TYPE eRoamType) +{ + struct ESS_CHNL_INFO *prEssChnlInfo = &prAisSpecificBssInfo-> + arCurEssChnlInfo[0]; + uint8_t i = 0; + uint16_t u2Score = 0; + uint8_t weight = gasMtkWeightConfig[eRoamType].ucApNumWeight; + + for (; i < prAisSpecificBssInfo->ucCurEssChnlInfoNum; i++) { + if (ucChannel == prEssChnlInfo[i].ucChannel) { +#if 0 /* currently, we don't take channel utilization into account */ + /* the channel utilization max value is 255. + *great utilization means little weight value. + * the step of weight value is 2.6 + */ + u2Score = mtk_weight_config[eRoamType]. + ucChnlUtilWeight * (BSS_FULL_SCORE - + (prEssChnlInfo[i].ucUtilization * 10 / 26)); +#endif + /* if AP num on this channel is greater than 100, + * the weight will be 0. + * otherwise, the weight value decrease 1 + * if AP number increase 1 + */ + if (prEssChnlInfo[i].ucApNum <= CHNL_BSS_NUM_THRESOLD) + u2Score += weight * + (BSS_FULL_SCORE - prEssChnlInfo[i].ucApNum * + SCORE_PER_AP); + log_dbg(SCN, TRACE, "channel %d, AP num %d\n", + ucChannel, prEssChnlInfo[i].ucApNum); + break; + } + } + return u2Score; +} + +static uint16_t scanCalculateScoreByBandwidth(struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc, enum ROAM_TYPE eRoamType) +{ + uint16_t u2Score = 0; + enum ENUM_CHANNEL_WIDTH eChannelWidth = prBssDesc->eChannelWidth; + uint8_t ucSta5GBW = prAdapter->rWifiVar.ucSta5gBandwidth; + uint8_t ucSta2GBW = prAdapter->rWifiVar.ucSta2gBandwidth; + uint8_t ucStaBW = prAdapter->rWifiVar.ucStaBandwidth; + + if (prBssDesc->fgIsVHTPresent && prAdapter->fgEnable5GBand) { + if (ucSta5GBW > ucStaBW) + ucSta5GBW = ucStaBW; + switch (ucSta5GBW) { + case MAX_BW_20MHZ: + case MAX_BW_40MHZ: + eChannelWidth = CW_20_40MHZ; + break; + case MAX_BW_80MHZ: + eChannelWidth = CW_80MHZ; + break; + } + switch (eChannelWidth) { + case CW_20_40MHZ: + u2Score = 60; + break; + case CW_80MHZ: + u2Score = 80; + break; + case CW_160MHZ: + case CW_80P80MHZ: + u2Score = BSS_FULL_SCORE; + break; + } + } else if (prBssDesc->fgIsHTPresent) { + if (prBssDesc->eBand == BAND_2G4) { + if (ucSta2GBW > ucStaBW) + ucSta2GBW = ucStaBW; + u2Score = (prBssDesc->eSco == 0 || + ucSta2GBW == MAX_BW_20MHZ) ? 40:60; + } else if (prBssDesc->eBand == BAND_5G) { + if (ucSta5GBW > ucStaBW) + ucSta5GBW = ucStaBW; + u2Score = (prBssDesc->eSco == 0 || + ucSta5GBW == MAX_BW_20MHZ) ? 40:60; + } + } else if (prBssDesc->u2BSSBasicRateSet & RATE_SET_OFDM) + u2Score = 20; + else + u2Score = 10; + + return u2Score * gasMtkWeightConfig[eRoamType].ucBandWidthWeight; +} + +static uint16_t scanCalculateScoreByClientCnt(struct BSS_DESC *prBssDesc, + enum ROAM_TYPE eRoamType) +{ + uint16_t u2Score = 0; + uint16_t u2StaCnt = 0; +#define BSS_STA_CNT_NORMAL_SCORE 50 +#define BSS_STA_CNT_GOOD_THRESOLD 10 + + log_dbg(SCN, TRACE, "Exist bss load %d, sta cnt %d\n", + prBssDesc->fgExsitBssLoadIE, prBssDesc->u2StaCnt); + + if (!prBssDesc->fgExsitBssLoadIE) { + u2Score = BSS_STA_CNT_NORMAL_SCORE; + return u2Score * + gasMtkWeightConfig[eRoamType].ucClientCntWeight; + } + + u2StaCnt = prBssDesc->u2StaCnt; + if (u2StaCnt > BSS_STA_CNT_THRESOLD) + u2Score = 0; + else if (u2StaCnt < BSS_STA_CNT_GOOD_THRESOLD) + u2Score = BSS_FULL_SCORE - u2StaCnt; + else + u2Score = BSS_STA_CNT_NORMAL_SCORE; + + return u2Score * gasMtkWeightConfig[eRoamType].ucClientCntWeight; +} + +#if CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT +struct NEIGHBOR_AP_T *scanGetNeighborAPEntry(struct LINK *prNeighborApLink, + uint8_t *pucBssid) +{ + struct NEIGHBOR_AP_T *prNeighborAP = NULL; + + LINK_FOR_EACH_ENTRY(prNeighborAP, prNeighborApLink, rLinkEntry, + struct NEIGHBOR_AP_T) + { + if (EQUAL_MAC_ADDR(prNeighborAP->aucBssid, pucBssid)) + return prNeighborAP; + } + return NULL; +} + +u_int8_t scanPreferenceIsZero(struct ADAPTER *prAdapter, uint8_t *pucBssid, + uint8_t ucBssIndex) +{ + struct LINK *prNeighborAPLink = + &aisGetAisSpecBssInfo(prAdapter, ucBssIndex) + ->rNeighborApList.rUsingLink; + struct NEIGHBOR_AP_T *prNeighborAP = NULL; + + if (prNeighborAPLink->u4NumElem == 0) + return FALSE; + + prNeighborAP = scanGetNeighborAPEntry(prNeighborAPLink, pucBssid); + + if (prNeighborAP == NULL) + return FALSE; + if (!prNeighborAP->fgPrefPresence) + return FALSE; + if (prNeighborAP->ucPreference > 0) + return FALSE; + + return TRUE; +} +#endif + +static u_int8_t scanNeedReplaceCandidate(struct ADAPTER *prAdapter, + struct BSS_DESC *prCandBss, struct BSS_DESC *prCurrBss, + uint16_t u2CandScore, uint16_t u2CurrScore, + enum ROAM_TYPE eRoamType, uint8_t ucBssIndex) +{ + int8_t cCandRssi = RCPI_TO_dBm(prCandBss->ucRCPI); + int8_t cCurrRssi = RCPI_TO_dBm(prCurrBss->ucRCPI); + uint32_t u4UpdateIdx = prAdapter->rWifiVar.rScanInfo.u4ScanUpdateIdx; + uint16_t u2CandMiss = u4UpdateIdx - prCandBss->u4UpdateIdx; + uint16_t u2CurrMiss = u4UpdateIdx - prCurrBss->u4UpdateIdx; + struct BSS_DESC *prBssDesc = NULL; + int8_t ucOpChannelNum = 0; + + prBssDesc = aisGetTargetBssDesc(prAdapter, ucBssIndex); + if (prBssDesc) + ucOpChannelNum = prBssDesc->ucChannelNum; + +#if CFG_SUPPORT_NCHO + if (prAdapter->rNchoInfo.fgNCHOEnabled) + return cCurrRssi >= cCandRssi ? TRUE : FALSE; +#endif + + /* 1. No need check score case + * 1.1 Scan missing count of CurrBss is too more, + * but Candidate is suitable, don't replace + */ + if (u2CurrMiss > 2 && u2CurrMiss > u2CandMiss) { + log_dbg(SCN, INFO, "Scan Miss count of CurrBss > 2, and Candidate <= 2\n"); + return FALSE; + } + /* 1.2 Scan missing count of Candidate is too more, + * but CurrBss is suitable, replace + */ + if (u2CandMiss > 2 && u2CandMiss > u2CurrMiss) { + log_dbg(SCN, INFO, "Scan Miss count of Candidate > 2, and CurrBss <= 2\n"); + return TRUE; + } + /* 1.3 Hard connecting RSSI check */ + if ((prCurrBss->eBand == BAND_5G && cCurrRssi < MINIMUM_RSSI_5G) || + (prCurrBss->eBand == BAND_2G4 && cCurrRssi < MINIMUM_RSSI_2G4)) + return FALSE; + else if ((prCandBss->eBand == BAND_5G && cCandRssi < MINIMUM_RSSI_5G) || + (prCandBss->eBand == BAND_2G4 && cCandRssi < MINIMUM_RSSI_2G4)) + return TRUE; + + /* 1.4 prefer to select 5G Bss if Rssi of a 5G band BSS is good */ + if (eRoamType != ROAM_TYPE_PER) { + if (prCandBss->eBand != prCurrBss->eBand) { + if (prCandBss->eBand == BAND_5G) { + /* Candidate AP is 5G, don't replace it + * if it's good enough. + */ + if (cCandRssi >= GOOD_RSSI_FOR_HT_VHT) + return FALSE; + if (cCandRssi < LOW_RSSI_FOR_5G_BAND && + (cCurrRssi > cCandRssi + 5)) + return TRUE; + } else { + /* Current AP is 5G, replace candidate + * AP if current AP is good. + */ + if (cCurrRssi >= GOOD_RSSI_FOR_HT_VHT) + return TRUE; + if (cCurrRssi < LOW_RSSI_FOR_5G_BAND && + (cCandRssi > cCurrRssi + 5)) + return FALSE; + } + } + } + + /* 1.5 RSSI of Current Bss is lower than Candidate, don't replace + * If the lower Rssi is greater than -59dbm, + * then no need check the difference + * Otherwise, if difference is greater than 10dbm, select the good RSSI + */ + do { + if ((eRoamType == ROAM_TYPE_PER) && + cCandRssi >= RSSI_SECOND_LEVEL && + cCurrRssi >= RSSI_SECOND_LEVEL) + break; + if (cCandRssi - cCurrRssi >= RSSI_DIFF_BETWEEN_BSS) + return FALSE; + if (cCurrRssi - cCandRssi >= RSSI_DIFF_BETWEEN_BSS) + return TRUE; + } while (FALSE); + +#if CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT + if (scanPreferenceIsZero(prAdapter, prCurrBss->aucBSSID, + ucBssIndex)) { + log_dbg(SCN, INFO, + "BTM: %s[" MACSTR "] preference value is 0, skip it\n", + prCurrBss->aucSSID, MAC2STR(prCurrBss->aucBSSID)); + return FALSE; + } +#endif + if (eRoamType == ROAM_TYPE_PER) { + if (prCandBss->ucChannelNum == ucOpChannelNum) { + log_dbg(SCN, INFO, "CandBss in opchnl,add CurBss Score\n"); + u2CurrScore += BSS_FULL_SCORE * + gasMtkWeightConfig[eRoamType].ucOpchnlWeight; + } + if (prCurrBss->ucChannelNum == ucOpChannelNum) { + log_dbg(SCN, INFO, "CurrBss in opchnl,add CandBss Score\n"); + u2CandScore += BSS_FULL_SCORE * + gasMtkWeightConfig[eRoamType].ucOpchnlWeight; + } + } + + /* 2. Check Score */ + /* 2.1 Cases that no need to replace candidate */ + if (prCandBss->fgIsConnected) { + if ((u2CandScore + ROAMING_NO_SWING_SCORE_STEP) >= u2CurrScore) + return FALSE; + } else if (prCurrBss->fgIsConnected) { + if (u2CandScore >= (u2CurrScore + ROAMING_NO_SWING_SCORE_STEP)) + return FALSE; + } else if (u2CandScore >= u2CurrScore) + return FALSE; + /* 2.2 other cases, replace candidate */ + return TRUE; +} + +static u_int8_t scanSanityCheckBssDesc(struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc, enum ENUM_BAND eBand, uint8_t ucChannel, + u_int8_t fgIsFixedChannel, enum ENUM_ROAMING_REASON eRoamReason, + uint8_t ucBssIndex) +{ + struct BSS_INFO *prAisBssInfo; + struct BSS_DESC *target; + +#if CFG_SUPPORT_MBO + struct PARAM_BSS_DISALLOWED_LIST *disallow; + uint32_t i = 0; + + disallow = &prAdapter->rWifiVar.rBssDisallowedList; + for (i = 0; i < disallow->u4NumBssDisallowed; ++i) { + uint32_t index = i * MAC_ADDR_LEN; + + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, + &disallow->aucList[index])) { + log_dbg(SCN, WARN, MACSTR" disallowed list\n", + MAC2STR(prBssDesc->aucBSSID)); + return FALSE; + } + } + + if (prBssDesc->fgIsDisallowed) { + log_dbg(SCN, WARN, MACSTR" disallowed\n", + MAC2STR(prBssDesc->aucBSSID)); + return FALSE; + } +#endif + + + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + target = aisGetTargetBssDesc(prAdapter, ucBssIndex); + if (prBssDesc->prBlack) { + if (prBssDesc->prBlack->fgIsInFWKBlacklist) { + log_dbg(SCN, WARN, MACSTR" in FWK blacklist\n", + MAC2STR(prBssDesc->aucBSSID)); + return FALSE; + } + + if (prBssDesc->prBlack->fgDeauthLastTime) { + log_dbg(SCN, WARN, MACSTR " is sending deauth.\n", + MAC2STR(prBssDesc->aucBSSID)); + return FALSE; + } + } + + /* roaming case */ + if (target && + (prAisBssInfo->eConnectionState == MEDIA_STATE_CONNECTED || + aisFsmIsInProcessPostpone(prAdapter, ucBssIndex))) { + int32_t r1, r2; + + r1 = RCPI_TO_dBm(target->ucRCPI); + r2 = RCPI_TO_dBm(prBssDesc->ucRCPI); + if (prBssDesc->ucRCPI < RCPI_FOR_DONT_ROAM +#if CFG_SUPPORT_NCHO + || (prAdapter->rNchoInfo.fgNCHOEnabled && + (eRoamReason == ROAMING_REASON_POOR_RCPI || + eRoamReason == ROAMING_REASON_RETRY) && + r1 - r2 <= prAdapter->rNchoInfo.i4RoamDelta) +#endif + ) { + log_dbg(SCN, INFO, MACSTR " low rssi %d (cur=%d)\n", + MAC2STR(prBssDesc->aucBSSID), r2, r1); + return FALSE; + } + } + + if (ucBssIndex != AIS_DEFAULT_INDEX) { + struct BSS_DESC *target = + aisGetTargetBssDesc(prAdapter, AIS_DEFAULT_INDEX); + + if (target && prBssDesc->eBand == target->eBand) { + log_dbg(SCN, WARN, MACSTR" band %d used by main\n", + MAC2STR(prBssDesc->aucBSSID)); + return FALSE; + } + } + + if (!(prBssDesc->ucPhyTypeSet & + (prAdapter->rWifiVar.ucAvailablePhyTypeSet))) { + log_dbg(SCN, WARN, + MACSTR" ignore unsupported ucPhyTypeSet = %x\n", + MAC2STR(prBssDesc->aucBSSID), + prBssDesc->ucPhyTypeSet); + return FALSE; + } + if (prBssDesc->fgIsUnknownBssBasicRate) { + log_dbg(SCN, WARN, MACSTR" unknown bss basic rate\n", + MAC2STR(prBssDesc->aucBSSID)); + return FALSE; + } + if (fgIsFixedChannel && (eBand != prBssDesc->eBand || ucChannel != + prBssDesc->ucChannelNum)) { + log_dbg(SCN, WARN, + MACSTR" fix channel required band %d, channel %d\n", + MAC2STR(prBssDesc->aucBSSID), eBand, ucChannel); + return FALSE; + } + +#if CFG_SUPPORT_WIFI_SYSDVT + if (!IS_SKIP_CH_CHECK(prAdapter)) +#endif + if (!rlmDomainIsLegalChannel(prAdapter, prBssDesc->eBand, + prBssDesc->ucChannelNum)) { + log_dbg(SCN, WARN, MACSTR" band %d channel %d is not legal\n", + MAC2STR(prBssDesc->aucBSSID), prBssDesc->eBand, + prBssDesc->ucChannelNum); + return FALSE; + } + + if (CHECK_FOR_TIMEOUT(kalGetTimeTick(), prBssDesc->rUpdateTime, + SEC_TO_SYSTIME(wlanWfdEnabled(prAdapter) ? + SCN_BSS_DESC_STALE_SEC_WFD : SCN_BSS_DESC_STALE_SEC))) { + log_dbg(SCN, WARN, MACSTR " description is too old.\n", + MAC2STR(prBssDesc->aucBSSID)); + return FALSE; + } + +#if CFG_SUPPORT_WAPI + if (aisGetWapiMode(prAdapter, ucBssIndex)) { + if (!wapiPerformPolicySelection(prAdapter, prBssDesc, + ucBssIndex)) { + log_dbg(SCN, WARN, MACSTR " wapi policy select fail.\n", + MAC2STR(prBssDesc->aucBSSID)); + return FALSE; + } + } else +#endif + if (!rsnPerformPolicySelection(prAdapter, prBssDesc, + ucBssIndex)) { + log_dbg(SCN, WARN, MACSTR " rsn policy select fail.\n", + MAC2STR(prBssDesc->aucBSSID)); + return FALSE; + } + if (aisGetAisSpecBssInfo(prAdapter, + ucBssIndex)->fgCounterMeasure) { + log_dbg(SCN, WARN, MACSTR " Skip in counter measure period.\n", + MAC2STR(prBssDesc->aucBSSID)); + return FALSE; + } + + return TRUE; +} + +static uint16_t scanCalculateScoreByRssi(struct BSS_DESC *prBssDesc, + enum ROAM_TYPE eRoamType) +{ + uint16_t u2Score = 0; + int8_t cRssi = RCPI_TO_dBm(prBssDesc->ucRCPI); + + if (cRssi >= BEST_RSSI) + u2Score = 100; + else if (cRssi <= -98) + u2Score = 0; + else + u2Score = (cRssi + 98) * 2; + u2Score *= gasMtkWeightConfig[eRoamType].ucRssiWeight; + + return u2Score; +} + +static uint16_t scanCalculateScoreBySaa(struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc, enum ROAM_TYPE eRoamType) +{ + uint16_t u2Score = 0; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + + prStaRec = cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_AIS, + prBssDesc->aucSrcAddr); + if (prStaRec) + u2Score = gasMtkWeightConfig[eRoamType].ucSaaWeight * + (prStaRec->ucTxAuthAssocRetryCount ? 0 : BSS_FULL_SCORE); + else + u2Score = gasMtkWeightConfig[eRoamType].ucSaaWeight * + BSS_FULL_SCORE; + + return u2Score; +} + +static uint16_t scanCalculateScoreByIdleTime(struct ADAPTER *prAdapter, + uint8_t ucChannel, enum ROAM_TYPE eRoamType, uint8_t ucBssIndex) +{ + uint8_t u4ChCnt = 0; + uint16_t u2Score = 0; + uint16_t u2ChIdleSlot; + uint16_t u2ChIdleTime; + uint16_t u2ChIdleUtil; + uint16_t u2ChDwellTime; + struct SCAN_INFO *prScanInfo; + struct SCAN_PARAM *prScanParam; + struct BSS_INFO *prAisBssInfo; + + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &(prScanInfo->rScanParam); + + if (prScanParam->u2ChannelDwellTime > 0) + u2ChDwellTime = prScanParam->u2ChannelDwellTime; + else if (prAisBssInfo->eConnectionState == MEDIA_STATE_CONNECTED) + u2ChDwellTime = CHNL_DWELL_TIME_ONLINE; + else + u2ChDwellTime = CHNL_DWELL_TIME_DEFAULT; + + for (u4ChCnt = 0; u4ChCnt < prScanInfo + ->ucSparseChannelArrayValidNum; u4ChCnt++) { + if (ucChannel == prScanInfo->aucChannelNum[u4ChCnt]) { + u2ChIdleSlot = + prScanInfo->au2ChannelIdleTime[u4ChCnt]; + u2ChIdleTime = u2ChIdleSlot * 9; + u2ChIdleUtil = + (u2ChIdleTime * 100) / (u2ChDwellTime * 1000); + if (u2ChIdleUtil > BSS_FULL_SCORE) + u2ChIdleUtil = BSS_FULL_SCORE; + u2Score = u2ChIdleUtil * + gasMtkWeightConfig[eRoamType].ucChnlIdleWeight; + break; + } + } + + return u2Score; +} + +u_int8_t scanApOverload(uint16_t status, uint16_t reason) +{ + switch (status) { + case STATUS_CODE_ASSOC_DENIED_AP_OVERLOAD: + case STATUS_CODE_ASSOC_DENIED_BANDWIDTH: + case STATUS_CODE_ASSOC_DENIED_OUTSIDE_STANDARD: + case STATUS_CODE_AUTH_TIMEOUT: + case STATUS_CODE_ASSOC_TIMEOUT: + return TRUE; + } + switch (reason) { + case REASON_CODE_DISASSOC_LACK_OF_BANDWIDTH: + case REASON_CODE_DISASSOC_AP_OVERLOAD: + return TRUE; + } + return FALSE; +} + +uint16_t scanCalculateScoreByBlackList(struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc, enum ROAM_TYPE eRoamType) +{ + uint16_t u2Score = 0; + + if (!prBssDesc->prBlack) + u2Score = 100; + else if (scanApOverload(prBssDesc->prBlack->u2AuthStatus, + prBssDesc->prBlack->u2DeauthReason) || + prBssDesc->prBlack->ucCount >= 10) + u2Score = 0; + else + u2Score = 100 - prBssDesc->prBlack->ucCount * 10; + + return u2Score * gasMtkWeightConfig[eRoamType].ucBlackListWeight; +} + +uint16_t scanCalculateTotalScore(struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc, enum ROAM_TYPE eRoamType, + uint8_t ucBssIndex) +{ + struct AIS_SPECIFIC_BSS_INFO *prAisSpecificBssInfo = NULL; + uint16_t u2ScoreStaCnt = 0; + uint16_t u2ScoreBandwidth = 0; + uint16_t u2ScoreSTBC = 0; + uint16_t u2ScoreChnlInfo = 0; + uint16_t u2ScoreSnrRssi = 0; + uint16_t u2ScoreDeauth = 0; + uint16_t u2ScoreProbeRsp = 0; + uint16_t u2ScoreScanMiss = 0; + uint16_t u2ScoreBand = 0; + uint16_t u2ScoreSaa = 0; + uint16_t u2ScoreIdleTime = 0; + uint16_t u2ScoreTotal = 0; + uint16_t u2BlackListScore = 0; +#if (CFG_SUPPORT_802_11AX == 1) + uint16_t u2AxApScore = 0; +#endif + int8_t cRssi = -128; + + prAisSpecificBssInfo = + aisGetAisSpecBssInfo(prAdapter, ucBssIndex); + cRssi = RCPI_TO_dBm(prBssDesc->ucRCPI); + + u2ScoreBandwidth = + scanCalculateScoreByBandwidth(prAdapter, prBssDesc, eRoamType); + u2ScoreStaCnt = scanCalculateScoreByClientCnt(prBssDesc, eRoamType); + u2ScoreSTBC = CALCULATE_SCORE_BY_STBC(prAdapter, prBssDesc, eRoamType); + u2ScoreChnlInfo = + scanCalculateScoreByChnlInfo(prAisSpecificBssInfo, + prBssDesc->ucChannelNum, eRoamType); + u2ScoreSnrRssi = scanCalculateScoreByRssi(prBssDesc, eRoamType); + u2ScoreDeauth = CALCULATE_SCORE_BY_DEAUTH(prBssDesc, eRoamType); + u2ScoreProbeRsp = CALCULATE_SCORE_BY_PROBE_RSP(prBssDesc, eRoamType); + u2ScoreScanMiss = CALCULATE_SCORE_BY_MISS_CNT(prAdapter, + prBssDesc, eRoamType); + u2ScoreBand = CALCULATE_SCORE_BY_BAND(prAdapter, prBssDesc, + cRssi, eRoamType); + u2ScoreSaa = scanCalculateScoreBySaa(prAdapter, prBssDesc, eRoamType); + u2ScoreIdleTime = scanCalculateScoreByIdleTime(prAdapter, + prBssDesc->ucChannelNum, eRoamType, ucBssIndex); + u2BlackListScore = + scanCalculateScoreByBlackList(prAdapter, prBssDesc, eRoamType); + +#if (CFG_SUPPORT_802_11AX == 1) + u2AxApScore = CALCULATE_SCORE_BY_AX_AP(prAdapter, prBssDesc, eRoamType); +#endif + u2ScoreTotal = u2ScoreBandwidth + u2ScoreChnlInfo + + u2ScoreDeauth + u2ScoreProbeRsp + u2ScoreScanMiss + + u2ScoreSnrRssi + u2ScoreStaCnt + u2ScoreSTBC + + u2ScoreBand + u2BlackListScore + u2ScoreSaa + + u2ScoreIdleTime; +#if (CFG_SUPPORT_802_11AX == 1) + u2ScoreTotal += u2AxApScore; +#endif + +#if (CFG_SUPPORT_802_11AX == 1) +#define TEMP_LOG_TEMPLATE\ + MACSTR" cRSSI[%d] 5G[%d] Score,Total %d,DE[%d]"\ + ", PR[%d], SM[%d], RSSI[%d],BD[%d],BL[%d],SAA[%d]"\ + ", BW[%d], SC[%d],ST[%d],CI[%d],IT[%d],CU[%d,%d]"\ + ", HE[%d], AxWeight[%d], AxScoreDiv[%d], AxScore[%d]\n" +#else +#define TEMP_LOG_TEMPLATE\ + MACSTR" cRSSI[%d] 5G[%d] Score,Total %d,DE[%d]"\ + ", PR[%d], SM[%d], RSSI[%d],BD[%d],BL[%d],SAA[%d]"\ + ", BW[%d], SC[%d],ST[%d],CI[%d],IT[%d],CU[%d,%d]\n" +#endif + + log_dbg(SCN, INFO, + TEMP_LOG_TEMPLATE, + MAC2STR(prBssDesc->aucBSSID), cRssi, + (prBssDesc->eBand == BAND_5G ? 1 : 0), u2ScoreTotal, + u2ScoreDeauth, u2ScoreProbeRsp, u2ScoreScanMiss, + u2ScoreSnrRssi, u2ScoreBand, u2BlackListScore, + u2ScoreSaa, u2ScoreBandwidth, u2ScoreStaCnt, + u2ScoreSTBC, u2ScoreChnlInfo, u2ScoreIdleTime, + prBssDesc->fgExsitBssLoadIE, + prBssDesc->ucChnlUtilization +#if (CFG_SUPPORT_802_11AX == 1) + , prBssDesc->fgIsHEPresent + , (prAdapter->rWifiVar).ucApSelAxWeight + , (prAdapter->rWifiVar).ucApSelAxScoreDiv + , u2AxApScore +#endif + ); +#undef TEMP_LOG_TEMPLATE + + return u2ScoreTotal; +} +/* + * Bss Characteristics to be taken into account when calculate Score: + * Channel Loading Group: + * 1. Client Count (in BSS Load IE). + * 2. AP number on the Channel. + * + * RF Group: + * 1. Channel utilization. + * 2. SNR. + * 3. RSSI. + * + * Misc Group: + * 1. Deauth Last time. + * 2. Scan Missing Count. + * 3. Has probe response in scan result. + * + * Capability Group: + * 1. Prefer 5G band. + * 2. Bandwidth. + * 3. STBC and Multi Anttena. + */ +struct BSS_DESC *scanSearchBssDescByScoreForAis(struct ADAPTER *prAdapter, + enum ENUM_ROAMING_REASON eRoamReason, uint8_t ucBssIndex) +{ + struct AIS_SPECIFIC_BSS_INFO *prAisSpecificBssInfo = NULL; + struct ROAMING_INFO *prRoamingFsmInfo = NULL; + struct BSS_INFO *prAisBssInfo = NULL; + struct LINK *prEssLink = NULL; + struct CONNECTION_SETTINGS *prConnSettings = NULL; + struct BSS_DESC *prBssDesc = NULL; + struct BSS_DESC *prCandBssDesc = NULL; + struct BSS_DESC *prCandBssDescForLowRssi = NULL; + uint16_t u2ScoreTotal = 0; + uint16_t u2CandBssScore = 0; + uint16_t u2CandBssScoreForLowRssi = 0; + u_int8_t fgSearchBlackList = FALSE; + u_int8_t fgIsFixedChnl = FALSE; + enum ENUM_BAND eBand = BAND_2G4; + uint8_t ucChannel = 0; + enum ENUM_PARAM_CONNECTION_POLICY policy; + struct ROAMING_INFO *roam; + enum ROAM_TYPE eRoamType; + + if (!prAdapter || + eRoamReason >= ROAMING_REASON_NUM || eRoamReason < 0) { + log_dbg(SCN, ERROR, + "prAdapter %p, reason %d!\n", prAdapter, eRoamReason); + return NULL; + } + prAisSpecificBssInfo = aisGetAisSpecBssInfo(prAdapter, ucBssIndex); + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + prEssLink = &prAisSpecificBssInfo->rCurEssLink; + prRoamingFsmInfo = aisGetRoamingInfo(prAdapter, ucBssIndex); + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + roam = aisGetRoamingInfo(prAdapter, ucBssIndex); + eRoamType = mtk_reason_to_type[eRoamReason]; +#if CFG_SUPPORT_CHNL_CONFLICT_REVISE + fgIsFixedChnl = cnmAisDetectP2PChannel(prAdapter, &eBand, &ucChannel); +#else + fgIsFixedChnl = cnmAisInfraChannelFixed(prAdapter, &eBand, &ucChannel); +#endif + aisRemoveTimeoutBlacklist(prAdapter); + log_dbg(SCN, INFO, "ConnectionPolicy = %d, reason = %d\n", + prConnSettings->eConnectionPolicy, eRoamReason); + policy = prConnSettings->eConnectionPolicy; +try_again: + LINK_FOR_EACH_ENTRY(prBssDesc, prEssLink, rLinkEntryEss[ucBssIndex], + struct BSS_DESC) { + /* update blacklist info */ + if (!fgSearchBlackList) + prBssDesc->prBlack = + aisQueryBlackList(prAdapter, prBssDesc); + /* + * Skip if + * 1. sanity check fail or + * 2. bssid is in driver's blacklist in the first round + */ + if (!scanSanityCheckBssDesc(prAdapter, prBssDesc, eBand, + ucChannel, fgIsFixedChnl, eRoamReason, ucBssIndex) || + (!fgSearchBlackList && prBssDesc->prBlack)) + continue; + + /* pick by bssid first */ + if (policy == CONNECT_BY_BSSID) { + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, + prConnSettings->aucBSSID)) { + log_dbg(SCN, INFO, MACSTR" match bssid\n", + MAC2STR(prBssDesc->aucBSSID)); + prCandBssDesc = prBssDesc; + break; + } + /* skip when bssid unmatched if conn by bssid */ + log_dbg(SCN, INFO, MACSTR" unmatch bssid\n", + MAC2STR(prBssDesc->aucBSSID)); + continue; + } else if (policy == CONNECT_BY_BSSID_HINT) { + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, + prConnSettings->aucBSSIDHint)) { + log_dbg(SCN, INFO, MACSTR" match bssid_hint\n", + MAC2STR(prBssDesc->aucBSSID)); + prCandBssDesc = prBssDesc; + break; + } + } + + u2ScoreTotal = scanCalculateTotalScore(prAdapter, prBssDesc, + eRoamType, ucBssIndex); + if (!prCandBssDesc || + scanNeedReplaceCandidate(prAdapter, prCandBssDesc, + prBssDesc, u2CandBssScore, u2ScoreTotal, eRoamType, + ucBssIndex)) { + prCandBssDesc = prBssDesc; + u2CandBssScore = u2ScoreTotal; + } + } + + if (prCandBssDesc) { + if (prCandBssDesc->fgIsConnected && !fgSearchBlackList && + prEssLink->u4NumElem > 0) { + fgSearchBlackList = TRUE; + log_dbg(SCN, INFO, "Can't roam out, try blacklist\n"); + goto try_again; + } + + if (prConnSettings->eConnectionPolicy == CONNECT_BY_BSSID) + log_dbg(SCN, INFO, "Selected " + MACSTR + " %d base on ssid,when find %s, " + MACSTR + " in %d bssid,fix channel %d.\n", + MAC2STR(prCandBssDesc->aucBSSID), + RCPI_TO_dBm(prCandBssDesc->ucRCPI), + HIDE(prConnSettings->aucSSID), + MAC2STR(prConnSettings->aucBSSID), + prEssLink->u4NumElem, ucChannel); + else + log_dbg(SCN, INFO, + "Selected " + MACSTR + ", cRSSI[%d] 5G[%d] Score %d when find %s, " + MACSTR + " in %d BSSes, fix channel %d.\n", + MAC2STR(prCandBssDesc->aucBSSID), + RCPI_TO_dBm(prCandBssDesc->ucRCPI), + (prCandBssDesc->eBand == BAND_5G ? 1 : 0), + u2CandBssScore, prConnSettings->aucSSID, + MAC2STR(prConnSettings->aucBSSID), + prEssLink->u4NumElem, ucChannel); + + return prCandBssDesc; + } else if (prCandBssDescForLowRssi) { + log_dbg(SCN, INFO, "Selected " MACSTR + ", Score %d when find %s, " MACSTR + " in %d BSSes, fix channel %d.\n", + MAC2STR(prCandBssDescForLowRssi->aucBSSID), + u2CandBssScoreForLowRssi, prConnSettings->aucSSID, + MAC2STR(prConnSettings->aucBSSID), prEssLink->u4NumElem, + ucChannel); + return prCandBssDescForLowRssi; + } + + /* if No Candidate BSS is found, try BSSes which are in blacklist */ + if (!fgSearchBlackList && prEssLink->u4NumElem > 0) { + fgSearchBlackList = TRUE; + log_dbg(SCN, INFO, "No Bss is found, Try blacklist\n"); + goto try_again; + } + log_dbg(SCN, INFO, "Selected None when find %s, " MACSTR + " in %d BSSes, fix channel %d.\n", + prConnSettings->aucSSID, MAC2STR(prConnSettings->aucBSSID), + prEssLink->u4NumElem, ucChannel); + return NULL; +} + +uint8_t scanUpdateChannelList(uint8_t channel, + uint8_t *bitmap, uint8_t *count, struct ESS_CHNL_INFO *info) +{ + uint8_t byteNum = 0; + uint8_t bitNum = 0; + + byteNum = channel / 8; + bitNum = channel % 8; + if (bitmap[byteNum] & BIT(bitNum)) + return 1; + bitmap[byteNum] |= BIT(bitNum); + info[*count].ucChannel = channel; + *count += 1; + if (*count >= CFG_MAX_NUM_OF_CHNL_INFO) + return 0; + + return 1; +} + +void scanGetCurrentEssChnlList(struct ADAPTER *prAdapter, + uint8_t ucBssIndex) +{ + struct BSS_DESC *prBssDesc = NULL; + struct LINK *prBSSDescList = + &prAdapter->rWifiVar.rScanInfo.rBSSDescList; + struct CONNECTION_SETTINGS *prConnSettings = + aisGetConnSettings(prAdapter, ucBssIndex); + struct ESS_CHNL_INFO *prEssChnlInfo; + struct LINK *prCurEssLink; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecBssInfo; + uint8_t aucChnlBitMap[30] = {0,}; + uint8_t aucChnlApNum[215] = {0,}; + uint8_t aucChnlUtil[215] = {0,}; + uint8_t ucChnlCount = 0; + uint32_t i; + uint8_t j = 0; +#if CFG_SUPPORT_802_11K + struct LINK *prNeighborAPLink; +#endif + struct CFG_SCAN_CHNL *prRoamScnChnl = &prAdapter->rAddRoamScnChnl; + + if (!prConnSettings) { + log_dbg(SCN, INFO, "No prConnSettings\n"); + return; + } + + if (prConnSettings->ucSSIDLen == 0) { + log_dbg(SCN, INFO, "No Ess are expected to connect\n"); + return; + } + + prAisSpecBssInfo = + aisGetAisSpecBssInfo(prAdapter, ucBssIndex); + if (!prAisSpecBssInfo) { + log_dbg(SCN, INFO, "No prAisSpecBssInfo\n"); + return; + } + prEssChnlInfo = + &prAisSpecBssInfo->arCurEssChnlInfo[0]; + if (!prEssChnlInfo) { + log_dbg(SCN, INFO, "No prEssChnlInfo\n"); + return; + } + prCurEssLink = + &prAisSpecBssInfo->rCurEssLink; + if (!prCurEssLink) { + log_dbg(SCN, INFO, "No prCurEssLink\n"); + return; + } + + kalMemZero(prEssChnlInfo, CFG_MAX_NUM_OF_CHNL_INFO * + sizeof(struct ESS_CHNL_INFO)); + + while (!LINK_IS_EMPTY(prCurEssLink)) { + prBssDesc = LINK_PEEK_HEAD(prCurEssLink, + struct BSS_DESC, rLinkEntryEss[ucBssIndex]); + LINK_REMOVE_KNOWN_ENTRY(prCurEssLink, + &prBssDesc->rLinkEntryEss[ucBssIndex]); + } + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, + struct BSS_DESC) { + if (prBssDesc->ucChannelNum > 214) + continue; + /* Statistic AP num for each channel */ + if (aucChnlApNum[prBssDesc->ucChannelNum] < 255) + aucChnlApNum[prBssDesc->ucChannelNum]++; + if (aucChnlUtil[prBssDesc->ucChannelNum] < + prBssDesc->ucChnlUtilization) + aucChnlUtil[prBssDesc->ucChannelNum] = + prBssDesc->ucChnlUtilization; + if (!EQUAL_SSID(prConnSettings->aucSSID, + prConnSettings->ucSSIDLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen)) + continue; + /* Record same BSS list */ + LINK_INSERT_HEAD(prCurEssLink, + &prBssDesc->rLinkEntryEss[ucBssIndex]); + +#if CFG_SUPPORT_NCHO + /* scan control is 1: use NCHO channel list only */ + if (prAdapter->rNchoInfo.u4RoamScanControl) + continue; +#endif + if (!scanUpdateChannelList(prBssDesc->ucChannelNum, + aucChnlBitMap, &ucChnlCount, prEssChnlInfo)) + goto updated; + } + +#if CFG_SUPPORT_NCHO + if (prAdapter->rNchoInfo.fgNCHOEnabled) { + struct CFG_NCHO_SCAN_CHNL *ncho; + + if (prAdapter->rNchoInfo.u4RoamScanControl) + ncho = &prAdapter->rNchoInfo.rRoamScnChnl; + else + ncho = &prAdapter->rNchoInfo.rAddRoamScnChnl; + + /* handle user-specefied scan channel info */ + for (i = 0; ucChnlCount < CFG_MAX_NUM_OF_CHNL_INFO && + i < ncho->ucChannelListNum; i++) { + uint8_t chnl; + + chnl = ncho->arChnlInfoList[i].ucChannelNum; + if (!scanUpdateChannelList(chnl, + aucChnlBitMap, &ucChnlCount, prEssChnlInfo)) + goto updated; + } + + if (prAdapter->rNchoInfo.u4RoamScanControl) + goto updated; + } +#endif + +#if CFG_SUPPORT_802_11K + prNeighborAPLink = &prAisSpecBssInfo->rNeighborApList.rUsingLink; + if (!LINK_IS_EMPTY(prNeighborAPLink)) { + /* Add channels provided by Neighbor Report to + ** channel list for roaming scanning. + */ + struct NEIGHBOR_AP_T *prNeiAP = NULL; + enum ENUM_BAND eBand; + uint8_t ucChannel; + + LINK_FOR_EACH_ENTRY(prNeiAP, prNeighborAPLink, + rLinkEntry, struct NEIGHBOR_AP_T) { + ucChannel = prNeiAP->ucChannel; + eBand = ucChannel <= 14 ? BAND_2G4 : BAND_5G; + if (!rlmDomainIsLegalChannel( + prAdapter, eBand, ucChannel)) + continue; + if (!scanUpdateChannelList(ucChannel, + aucChnlBitMap, &ucChnlCount, prEssChnlInfo)) + goto updated; + } + } +#endif + + /* handle user-specefied scan channel info */ + for (i = 0; ucChnlCount < CFG_MAX_NUM_OF_CHNL_INFO && + i < prRoamScnChnl->ucChannelListNum; i++) { + uint8_t chnl; + + chnl = prRoamScnChnl->arChnlInfoList[i].ucChannelNum; + if (!scanUpdateChannelList(chnl, + aucChnlBitMap, &ucChnlCount, prEssChnlInfo)) + goto updated; + } + +updated: + + prAisSpecBssInfo->ucCurEssChnlInfoNum = ucChnlCount; + for (j = 0; j < ucChnlCount; j++) { + uint8_t ucChnl = prEssChnlInfo[j].ucChannel; + + prEssChnlInfo[j].ucApNum = aucChnlApNum[ucChnl]; + prEssChnlInfo[j].ucUtilization = aucChnlUtil[ucChnl]; + } +#if 0 + /* Sort according to AP number */ + for (j = 0; j < ucChnlCount; j++) { + for (i = j + 1; i < ucChnlCount; i++) + if (prEssChnlInfo[j].ucApNum > + prEssChnlInfo[i].ucApNum) { + struct ESS_CHNL_INFO rTemp = prEssChnlInfo[j]; + + prEssChnlInfo[j] = prEssChnlInfo[i]; + prEssChnlInfo[i] = rTemp; + } + } +#endif + log_dbg(SCN, INFO, "Find %s in %d BSSes, result %d\n", + prConnSettings->aucSSID, prBSSDescList->u4NumElem, + prCurEssLink->u4NumElem); +} + +uint8_t scanInDecidingRoaming(struct ADAPTER *prAdapter, uint8_t ucBssIndex) +{ + struct ROAMING_INFO *roam; + enum ENUM_PARAM_CONNECTION_POLICY policy; + struct CONNECTION_SETTINGS *setting; + + roam = aisGetRoamingInfo(prAdapter, ucBssIndex); + setting = aisGetConnSettings(prAdapter, ucBssIndex); + policy = setting->eConnectionPolicy; + + return IS_BSS_INDEX_AIS(prAdapter, ucBssIndex) && + roam->fgIsEnableRoaming && + roam->eCurrentState == ROAMING_STATE_DECISION && + policy != CONNECT_BY_BSSID ? TRUE : FALSE; + +} + +uint8_t scanCheckNeedDriverRoaming( + struct ADAPTER *prAdapter, uint8_t ucBssIndex) +{ + struct ROAMING_INFO *roam; + struct AIS_FSM_INFO *ais; + struct CONNECTION_SETTINGS *setting; + int8_t rssi; + + roam = aisGetRoamingInfo(prAdapter, ucBssIndex); + ais = aisGetAisFsmInfo(prAdapter, ucBssIndex); + setting = aisGetConnSettings(prAdapter, ucBssIndex); + rssi = prAdapter->rLinkQuality.rLq[ucBssIndex].cRssi; + + GET_CURRENT_SYSTIME(&roam->rRoamingDiscoveryUpdateTime); + +#if CFG_SUPPORT_DRIVER_ROAMING + /* + * try to select AP only when roaming is enabled and rssi is bad + */ + if (scanInDecidingRoaming(prAdapter, ucBssIndex) && + ais->eCurrentState == AIS_STATE_ONLINE_SCAN && + CHECK_FOR_TIMEOUT(roam->rRoamingDiscoveryUpdateTime, + roam->rRoamingLastDecisionTime, + SEC_TO_SYSTIME(prAdapter->rWifiVar.u4InactiveTimeout))) { + struct BSS_DESC *target; + struct BSS_DESC *bss; + + target = aisGetTargetBssDesc(prAdapter, ucBssIndex); + + bss = scanSearchBssDescByScoreForAis(prAdapter, + ROAMING_REASON_INACTIVE, ucBssIndex); + + if (bss == NULL) + return FALSE; + /* 2.4 -> 5 */ + if (bss->eBand == BAND_5G && target->eBand == BAND_2G4) { + if (rssi > RSSI_BAD_NEED_ROAM_24G_TO_5G) + return FALSE; + if (bss->ucRCPI >= RCPI_THRESHOLD_ROAM_TO_5G || + bss->ucRCPI - target->ucRCPI > RCPI_DIFF_DRIVER_ROAM) { + log_dbg(SCN, INFO, + "Driver trigger roaming to 5G band.\n"); + return TRUE; + } + } else { + if (rssi > RSSI_BAD_NEED_ROAM) + return FALSE; + if (bss->ucRCPI - target->ucRCPI > + RCPI_DIFF_DRIVER_ROAM) { + log_dbg(SCN, INFO, + "Driver trigger roaming for other cases.\n"); + return TRUE; + } + } + } +#endif + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is to decide if we can roam out by this beacon time +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return true if we can roam out +* false others +*/ +/*----------------------------------------------------------------------------*/ +uint8_t scanBeaconTimeoutFilterPolicyForAis(struct ADAPTER *prAdapter, + uint8_t ucBssIndex) +{ + int8_t rssi; + + rssi = prAdapter->rLinkQuality.rLq[ucBssIndex].cRssi; + if (scanInDecidingRoaming(prAdapter, ucBssIndex) && + rssi > GOOD_RSSI_FOR_HT_VHT - 5) { + struct BSS_DESC *target; + struct BSS_DESC *bss; + + /* Good rssi but beacon timeout happened => PER */ + target = aisGetTargetBssDesc(prAdapter, ucBssIndex); + bss = scanSearchBssDescByScoreForAis(prAdapter, + ROAMING_REASON_TX_ERR, ucBssIndex); + if (bss && UNEQUAL_MAC_ADDR(bss->aucBSSID, target->aucBSSID)) { + log_dbg(SCN, INFO, "Better AP for beacon timeout"); + return TRUE; + } + } + + return FALSE; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/assoc.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/assoc.c new file mode 100644 index 0000000000000..4ca0641c187f3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/assoc.c @@ -0,0 +1,2127 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/assoc.c#5 + */ + +/*! \file "assoc.c" + * \brief This file includes the 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 + ******************************************************************************* + */ +struct APPEND_VAR_IE_ENTRY txAssocReqIETable[] = { + {0, assocCalculateConnIELen, assocGenerateConnIE} + , /* supplicant connect IE including rsn */ +#if CFG_SUPPORT_SPEC_MGMT || CFG_SUPPORT_802_11K + {(ELEM_HDR_LEN + ELEM_MAX_LEN_POWER_CAP), + NULL, rlmReqGeneratePowerCapIE} + , /* 33 */ +#endif +#if CFG_SUPPORT_SPEC_MGMT + {(ELEM_HDR_LEN + ELEM_MAX_LEN_SUPPORTED_CHANNELS), + NULL, rlmReqGenerateSupportedChIE} + , /* 36 */ +#endif + {(ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP), NULL, rlmReqGenerateHtCapIE} + , /* 45 */ +#if CFG_SUPPORT_802_11R + {(ELEM_HDR_LEN + 1), NULL, assocGenerateMDIE}, /* Element ID: 54 */ + {0, rsnCalculateFTIELen, rsnGenerateFTIE}, /* Element ID: 55 */ +#endif +#if CFG_SUPPORT_802_11K + {(ELEM_HDR_LEN + 5), NULL, + rrmGenerateRRMEnabledCapIE}, /* Element ID: 70 */ +#endif + {(ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP), NULL, rlmReqGenerateExtCapIE} + , /* 127 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_INFO), NULL, mqmGenerateWmmInfoIE} + , /* 221 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_RSN + 4), NULL, rsnGenerateRSNIE} + , /* 48 */ +#if CFG_SUPPORT_802_11AC + {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP), NULL, rlmReqGenerateVhtCapIE} + , /*191 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP_MODE_NOTIFICATION), NULL, + rlmReqGenerateVhtOpNotificationIE} + , /*199 */ +#endif +#if (CFG_SUPPORT_802_11AX == 1) + {(0), heRlmCalculateHeCapIELen, heRlmReqGenerateHeCapIE} + , /* 255, EXT 35 */ +#endif +#if CFG_SUPPORT_MTK_SYNERGY + {(ELEM_HDR_LEN + ELEM_MIN_LEN_MTK_OUI), NULL, rlmGenerateMTKOuiIE} + , /* 221 */ +#endif + {(ELEM_HDR_LEN + ELEM_MAX_LEN_WPA), NULL, rsnGenerateWPAIE} + /* 221 */ +}; + +#if CFG_SUPPORT_AAA +struct VERIFY_IE_ENTRY rxAssocReqIETable[] = { + {ELEM_ID_RESERVED, NULL} /* 255 */ +}; + +struct APPEND_VAR_IE_ENTRY 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 */ +#if CFG_SUPPORT_802_11AC + {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP), NULL, rlmRspGenerateVhtCapIE} + , /*191 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP), NULL, rlmRspGenerateVhtOpIE} + , /*192 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP_MODE_NOTIFICATION), NULL, + rlmRspGenerateVhtOpNotificationIE} + , /*199 */ +#endif +#if CFG_SUPPORT_802_11AX + {0, heRlmCalculateHeCapIELen, heRlmRspGenerateHeCapIE} + , /* 255, EXT 35 */ + {0, heRlmCalculateHeOpIELen, heRlmRspGenerateHeOpIE} + , /* 255, EXT 36 */ +#endif + {(ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_PARAM), NULL, mqmGenerateWmmParamIE} + , /* 221 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_ASSOC_RSP_WSC_IE), NULL, + rsnGenerateWSCIEForAssocRsp} + , /* 221 */ +#if CFG_SUPPORT_MTK_SYNERGY + {(ELEM_HDR_LEN + ELEM_MIN_LEN_MTK_OUI), NULL, rlmGenerateMTKOuiIE} + /* 221 */ +#endif + , +#if CFG_SUPPORT_802_11W + {(ELEM_HDR_LEN + ELEM_MAX_LEN_TIMEOUT_IE), NULL, + rsnPmfGenerateTimeoutIE} + /* 56 */ +#endif + +}; +#endif /* 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 + ******************************************************************************* + */ +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is used to compose the Capability Info Field. + * + * @param[in] prStaRec Pointer to the STA_RECORD_T + * + * @retval Capability Info Field + */ +/*----------------------------------------------------------------------------*/ + +uint16_t assocBuildCapabilityInfo(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + uint32_t u4NonHTPhyType; + uint16_t u2CapInfo; + struct BSS_INFO *prBssInfo; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + /* Set up our requested capabilities. */ + u2CapInfo = CAP_INFO_ESS; + u2CapInfo |= CAP_CF_STA_NOT_POLLABLE; +#if CFG_SUPPORT_802_11K + u2CapInfo |= CAP_INFO_RADIO_MEASUREMENT; +#endif + + if (prStaRec->u2CapInfo & CAP_INFO_PRIVACY) + u2CapInfo |= CAP_INFO_PRIVACY; + + /* 7.3.1.4 */ + if (prStaRec->fgHasBasicPhyType) { + u4NonHTPhyType = prStaRec->ucNonHTBasicPhyType; + + if ((rNonHTPhyAttributes + [u4NonHTPhyType].fgIsShortPreambleOptionImplemented) && + /* Short Preamble Option Enable is TRUE */ + ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_SHORT) + || + ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_AUTO) + && (prStaRec->u2CapInfo & CAP_INFO_SHORT_PREAMBLE)))) { + + /* Case I: Implemented == TRUE + * and Short Preamble Option Enable == TRUE. + * Case II: Implemented == TRUE + * and Short Preamble == AUTO (depends on + * struct BSS_DESC's capability) + */ + u2CapInfo |= CAP_INFO_SHORT_PREAMBLE; + } +#if CFG_SUPPORT_SPEC_MGMT + /* 802.11h spectrum management is for 5G band, so + * now we only enable spectrum management bit for 5G case. + * In TGn 5.2.22, spectrum management bit should set to 1 + * to pass the UCC's check. + */ + if (prBssInfo && prBssInfo->eBand == BAND_5G) + u2CapInfo |= CAP_INFO_SPEC_MGT; +#endif + + 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) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void assocBuildReAssocReqFrameCommonIEs( + IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct CONNECTION_SETTINGS *prConnSettings; + struct STA_RECORD *prStaRec; + uint8_t *pucBuffer; + uint16_t u2SupportedRateSet; + uint8_t aucAllSupportedRates[RATE_NUM_SW] = { 0 }; + uint8_t ucAllSupportedRatesLen; + uint8_t ucSupRatesLen; + uint8_t ucExtSupRatesLen; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (!prStaRec) + return; + + pucBuffer = + (uint8_t *) ((unsigned long)prMsduInfo->prPacket + + (unsigned long)prMsduInfo->u2FrameLength); + + prConnSettings = + aisGetConnSettings(prAdapter, prStaRec->ucBssIndex); + + 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_BOW_TYPE(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 + + /* 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->ucDesiredPhyTypeSet) { + uint32_t u4NonHTPhyType; + + u4NonHTPhyType = prStaRec->ucNonHTBasicPhyType; + + u2SupportedRateSet = (prStaRec->u2OperationalRateSet & + rNonHTPhyAttributes + [u4NonHTPhyType].u2SupportedRateSet); + + if (!u2SupportedRateSet) { + DBGLOG(SAA, INFO, + "RateSet NonHTPhyType=%d OperationalRateSet=%d\n", + u4NonHTPhyType, prStaRec->u2OperationalRateSet); + 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); + } + } +} /* 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) + */ +/*----------------------------------------------------------------------------*/ +void +assocComposeReAssocReqFrameHeaderAndFF(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN uint8_t *pucBuffer, + IN uint8_t aucMACAddress[], + IN OUT uint16_t *pu2PayloadLen) +{ + struct WLAN_ASSOC_REQ_FRAME *prAssocFrame; + u_int8_t fgIsReAssoc; + + uint16_t u2FrameCtrl; + uint16_t u2CapInfo; + uint16_t u2ListenInterval; + + prAssocFrame = (struct WLAN_ASSOC_REQ_FRAME *)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)) { + + struct BSS_INFO *prAisBssInfo = + aisGetAisBssInfo(prAdapter, + prStaRec->ucBssIndex); + struct WLAN_REASSOC_REQ_FRAME *prReAssocFrame = + (struct WLAN_REASSOC_REQ_FRAME *)prAssocFrame; + + COPY_MAC_ADDR(prReAssocFrame->aucCurrentAPAddr, + prAisBssInfo->aucBSSID); + } else { + ASSERT(0); + /* We don't support ReAssociation for other network */ + } + + *pu2PayloadLen = + (CAP_INFO_FIELD_LEN + LISTEN_INTERVAL_FIELD_LEN + + CURR_AP_ADDR_FIELD_LEN); + } else { + *pu2PayloadLen = + (CAP_INFO_FIELD_LEN + LISTEN_INTERVAL_FIELD_LEN); + } +} /* end of assocComposeReAssocReqFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will send the (Re)Association Request frame + * + * @param[in] prStaRec Pointer to the STA_RECORD_T + * + * @retval WLAN_STATUS_RESOURCES No available resource for frame composing. + * @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module + */ +/*----------------------------------------------------------------------------*/ +uint32_t assocSendReAssocReqFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + struct MSDU_INFO *prMsduInfo; + struct BSS_INFO *prBssInfo; + + uint16_t u2PayloadLen; + uint16_t u2EstimatedFrameLen; + uint16_t u2EstimatedExtraIELen; + u_int8_t fgIsReAssoc; + uint32_t i; + uint16_t txAssocReqIENums; + + /* 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_SW - 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_SW - ELEM_MAX_LEN_SUP_RATES)); + } + + /* + Extra IE Length */ + u2EstimatedExtraIELen = 0; + txAssocReqIENums = sizeof(txAssocReqIETable) / + sizeof(struct APPEND_VAR_IE_ENTRY); + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 && CFG_ENABLE_WIFI_DIRECT + if (IS_STA_IN_P2P(prStaRec)) { + if ((prAdapter->fgIsP2PRegistered)) { + u2EstimatedExtraIELen = + p2pCalculate_IEForAssocReq(prAdapter, + prStaRec->ucBssIndex, + prStaRec); + } else { + DBGLOG(P2P, TRACE, "Function Linker Lost.\n"); + ASSERT(FALSE); + } + } else { + for (i = 0; i < txAssocReqIENums; i++) { + if (txAssocReqIETable[i].u2EstimatedFixedIELen != 0) { + u2EstimatedExtraIELen += + txAssocReqIETable[i].u2EstimatedFixedIELen; + } else { + u2EstimatedExtraIELen += (uint16_t) + txAssocReqIETable + [i].pfnCalculateVariableIELen(prAdapter, + prStaRec->ucBssIndex, prStaRec); + } + } + /* Calculate non-wfa vendor specific ie len */ + u2EstimatedExtraIELen += + assoc_get_nonwfa_vend_ie_len(prAdapter, + prStaRec->ucBssIndex); + } +#else + for (i = 0; i < txAssocReqIENums; i++) { + if (txAssocReqIETable[i].u2EstimatedFixedIELen != 0) { + u2EstimatedExtraIELen += + txAssocReqIETable[i].u2EstimatedFixedIELen; + } else { + u2EstimatedExtraIELen += (uint16_t) + txAssocReqIETable[i].pfnCalculateVariableIELen + (prAdapter, prStaRec->ucBssIndex, prStaRec); + } + } + /* Calculate non-wfa vendor specific ie len */ + u2EstimatedExtraIELen += assoc_get_nonwfa_vend_ie_len(prAdapter, + prStaRec->ucBssIndex); +#endif + u2EstimatedFrameLen += u2EstimatedExtraIELen; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SAA, WARN, + "No PKT_INFO_T for sending (Re)Assoc Request.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose (Re)Association Request frame header and fixed fields + * in MSDU_INfO_T. + */ + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + /* Compose Header and Fixed Field */ + assocComposeReAssocReqFrameHeaderAndFF(prAdapter, + prStaRec, + (uint8_t + *) ((unsigned + long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD), + prBssInfo->aucOwnMacAddr, + &u2PayloadLen); + + /* 4 <3> Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, + saaFsmRunEventTxDone, MSDU_RATE_MODE_AUTO); + + /* 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 (IS_STA_IN_P2P(prStaRec)) { + if ((prAdapter->fgIsP2PRegistered)) { + p2pGenerate_IEForAssocReq(prAdapter, prMsduInfo); + } else { + DBGLOG(P2P, TRACE, "Function Linker Lost.\n"); + ASSERT(FALSE); + } + } else { + /* Append IE */ + for (i = 0; i < txAssocReqIENums; i++) { + if (txAssocReqIETable[i].pfnAppendIE) + txAssocReqIETable[i].pfnAppendIE(prAdapter, + prMsduInfo); + } + /* Append non-wfa vendor specific ies for AIS mode */ + assoc_build_nonwfa_vend_ie(prAdapter, prMsduInfo); + } +#else + /* Append IE */ + for (i = 0; i < txAssocReqIENums; i++) { + if (txAssocReqIETable[i].pfnAppendIE) + txAssocReqIETable[i].pfnAppendIE(prAdapter, prMsduInfo); + } + /* Append non-wfa vendor specific ies for AIS mode */ + assoc_build_nonwfa_vend_ie(prAdapter, prMsduInfo); +#endif + + /* 4 <6> Update the (Re)association request information */ + if (IS_STA_IN_AIS(prStaRec)) { + struct WLAN_ASSOC_REQ_FRAME *prAssocFrame; + + prAssocFrame = + (struct WLAN_ASSOC_REQ_FRAME + *)((unsigned long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + + kalUpdateReAssocReqInfo(prAdapter->prGlueInfo, + (uint8_t *) &prAssocFrame->u2CapInfo, + prMsduInfo->u2FrameLength - + offsetof(struct WLAN_ASSOC_REQ_FRAME, + u2CapInfo), fgIsReAssoc, + prStaRec->ucBssIndex); + } +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) { + struct WLAN_ASSOC_REQ_FRAME *prAssocFrame; + + prAssocFrame = + (struct WLAN_ASSOC_REQ_FRAME + *)((unsigned long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + + kalP2PUpdateAssocInfo(prAdapter->prGlueInfo, + (uint8_t *) &prAssocFrame->u2CapInfo, + prMsduInfo->u2FrameLength - + offsetof(struct WLAN_ASSOC_REQ_FRAME, + u2CapInfo), fgIsReAssoc, + prStaRec->ucBssIndex); + } +#endif + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU + */ + + nicTxConfigPktControlFlag(prMsduInfo, MSDU_CONTROL_FLAG_FORCE_TX, TRUE); + + /* 4 <6> Enqueue the frame to send this (Re)Association request frame. + */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; +} /* end of assocSendReAssocReqFrame() */ + + +uint32_t assocCalculateConnIELen(struct ADAPTER *prAdapter, uint8_t ucBssIdx, + struct STA_RECORD *prStaRec) +{ + struct CONNECTION_SETTINGS *prConnSettings; + uint8_t ucBssIndex; + const uint8_t *rsnConn; + + ucBssIndex = prStaRec->ucBssIndex; + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + + if (IS_STA_IN_AIS(prStaRec) && prConnSettings->assocIeLen > 0) { + prConnSettings = aisGetConnSettings(prAdapter, ucBssIdx); + rsnConn = kalFindIeMatchMask(ELEM_ID_RSN, + prConnSettings->pucAssocIEs, + prConnSettings->assocIeLen, + NULL, 0, 0, NULL); + /* cut out RSN IE */ + if (rsnConn) + return prConnSettings->assocIeLen - + ELEM_HDR_LEN - RSN_IE(rsnConn)->ucLength; + else + return prConnSettings->assocIeLen; + } + + return 0; +} + +void assocGenerateConnIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct CONNECTION_SETTINGS *prConnSettings; + struct STA_RECORD *prStaRec; + uint8_t *pucBuffer, *cp; + const uint8_t *rsnConn; + const uint8_t *extCapConn; + uint8_t ucBssIndex; + uint32_t len, rsnIeLen; + uint32_t extCapIeLen; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + if (!prStaRec) + return; + + pucBuffer = (uint8_t *) ((unsigned long) + prMsduInfo->prPacket + (unsigned long) + prMsduInfo->u2FrameLength); + cp = pucBuffer; + ucBssIndex = prStaRec->ucBssIndex; + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + + if (IS_STA_IN_AIS(prStaRec) && prConnSettings->assocIeLen > 0) { + kalMemCopy(cp, prConnSettings->pucAssocIEs, + prConnSettings->assocIeLen); + cp += prConnSettings->assocIeLen; + + rsnConn = kalFindIeMatchMask(ELEM_ID_RSN, + pucBuffer, + cp - pucBuffer, + NULL, 0, 0, NULL); + + if (rsnConn) { + rsnIeLen = IE_SIZE(rsnConn); + + len = cp - rsnConn - rsnIeLen; + /* copy to the start of RSN IE*/ + cp = (char *) rsnConn; + /* jump to the end of RSN IE to copy Remaing IEs*/ + kalMemCopy(cp, rsnConn + rsnIeLen, len); + cp += len; + } + + extCapConn = kalFindIeMatchMask(ELEM_ID_EXTENDED_CAP, + pucBuffer, + cp - pucBuffer, + NULL, 0, 0, NULL); + + if (extCapConn) { + extCapIeLen = IE_SIZE(extCapConn); + + len = cp - extCapConn - extCapIeLen; + /* copy to the start of EXT CAP IE*/ + cp = (char *) extCapConn; + /* jump to the end of EXT CAP IE to copy remaing IEs */ + kalMemCopy(cp, extCapConn + extCapIeLen, len); + cp += len; + } + + } + prMsduInfo->u2FrameLength += cp - pucBuffer; + DBGLOG_MEM8(SAA, INFO, pucBuffer, cp - pucBuffer); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t assocCheckTxReAssocReqFrame(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct WLAN_ASSOC_REQ_FRAME *prAssocReqFrame; + struct STA_RECORD *prStaRec; + uint16_t u2TxFrameCtrl; + + prAssocReqFrame = (struct WLAN_ASSOC_REQ_FRAME *)(prMsduInfo->prPacket); + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t assocCheckTxReAssocRespFrame(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct WLAN_ASSOC_RSP_FRAME *prAssocRspFrame; + struct STA_RECORD *prStaRec; + uint16_t u2TxFrameCtrl; + + prAssocRspFrame = (struct WLAN_ASSOC_RSP_FRAME *)(prMsduInfo->prPacket); + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t +assocCheckRxReAssocRspFrameStatus(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + OUT uint16_t *pu2StatusCode) +{ + struct STA_RECORD *prStaRec; + struct WLAN_ASSOC_RSP_FRAME *prAssocRspFrame; + uint16_t u2RxFrameCtrl; + uint16_t u2RxCapInfo; + uint16_t u2RxStatusCode; + uint16_t u2RxAssocId; + + if (!prSwRfb || !pu2StatusCode) { + DBGLOG(SAA, ERROR, "Invalid parameter, ignore!\n"); + return WLAN_STATUS_FAILURE; + } + + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < + (CAP_INFO_FIELD_LEN + + STATUS_CODE_FIELD_LEN + + AID_FIELD_LEN)) { + DBGLOG(SAA, WARN, "Invalid AssocRsp length!"); + return WLAN_STATUS_FAILURE; + } + + DBGLOG(SAA, LOUD, "prSwRfb->u2PayloadLength = %d\n", + prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (!prStaRec) { + DBGLOG(SAA, ERROR, "Invalid prStaRec, ignore!\n"); + return WLAN_STATUS_INVALID_PACKET; + } + + /* 4 <1> locate the (Re)Association Resp Frame. */ + prAssocRspFrame = (struct WLAN_ASSOC_RSP_FRAME *)prSwRfb->pvHeader; + + /* If Association Response's BSSID doesn't match + * our target, ignore. + */ + if (!EQUAL_MAC_ADDR(prAssocRspFrame->aucBSSID, + prStaRec->aucMacAddr)) { + DBGLOG(SAA, INFO, "Unknown BSSID\n"); + return WLAN_STATUS_FAILURE; + } + + /* 4 <2> Parse the Header of (Re)Association Resp Frame. */ + /* WLAN_GET_FIELD_16(&prAssocRspFrame->u2FrameCtrl, &u2RxFrameCtrl); */ + u2RxFrameCtrl = prAssocRspFrame->u2FrameCtrl; + /* NOTE(Kevin): Optimized for ARM */ + u2RxFrameCtrl &= MASK_FRAME_TYPE; + if (prStaRec->fgIsReAssoc) { + if (u2RxFrameCtrl != MAC_FRAME_REASSOC_RSP) + return WLAN_STATUS_FAILURE; + + } else { + if (u2RxFrameCtrl != MAC_FRAME_ASSOC_RSP) + return WLAN_STATUS_FAILURE; + + } + + /* 4 <3> Parse the Fixed Fields of (Re)Association Resp Frame Body. */ + /* WLAN_GET_FIELD_16(&prAssocRspFrame->u2CapInfo, &u2RxCapInfo); */ + u2RxCapInfo = prAssocRspFrame->u2CapInfo; + /* NOTE(Kevin): Optimized for ARM */ + + /* WLAN_GET_FIELD_16(&prAssocRspFrame->u2StatusCode, &u2RxStatusCode); + */ + u2RxStatusCode = prAssocRspFrame->u2StatusCode; + /* NOTE(Kevin): Optimized for ARM */ + + /* 4 <4> Check CAP_INFO */ + /* NOTE(Kevin): CM suggest to add MGMT workaround for those APs + * didn't check the CAP Privacy Bit to overcome a corner case + * that the Privacy Bit of our SCAN result didn't consist with + * AP's Association Resp. + */ + if (u2RxStatusCode == STATUS_CODE_SUCCESSFUL) { +#if CFG_SUPPORT_WAPI + if (aisGetWapiMode(prAdapter, prStaRec->ucBssIndex)) { + /* 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) { + /* Update the information in the structure used to query and set + * OID_802_11_ASSOCIATION_INFORMATION. + */ + + kalUpdateReAssocRspInfo(prAdapter->prGlueInfo, + (uint8_t *) & + prAssocRspFrame->u2CapInfo, + prSwRfb->u2PacketLen - + prSwRfb->u2HeaderLen, + prStaRec->ucBssIndex); + } + /* 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->eStaType == STA_TYPE_LEGACY_AP) { + struct AIS_SPECIFIC_BSS_INFO *prBssSpecInfo; + + prBssSpecInfo = + aisGetAisSpecBssInfo(prAdapter, + prStaRec->ucBssIndex); + 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) { + uint8_t *pucIE, *pucTime; + uint16_t u2IELength; + uint16_t u2Offset = 0; + + u2IELength = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen; + pucIE = + (uint8_t *) ((unsigned long)prSwRfb->pvHeader + + prSwRfb->u2HeaderLen); + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (IE_ID(pucIE) == ELEM_ID_TIMEOUT_INTERVAL + && IE_LEN(pucIE) == 5) { + pucTime = ((struct IE_HDR *)pucIE)->aucInfo; + if (pucTime[0] == + ACTION_SA_TIMEOUT_ASSOC_COMEBACK) { + uint32_t tu; + + WLAN_GET_FIELD_32(pucTime + 1, &tu); + DBGLOG(SAA, INFO, + "AP rejected association temporarily;comeback duration %u TU (%u ms)\n", + tu, TU_TO_MSEC(tu)); + if (tu > + TX_ASSOCIATION_RETRY_TIMEOUT_TU) { + DBGLOG(SAA, INFO, + "Update timer based on comeback duration\n"); + /* ieee80211_reschedule_timer( + * wpa_s, ms); + */ + } + } + break; + } + } /* end of IE_FOR_EACH */ + } +#endif + *pu2StatusCode = u2RxStatusCode; + + return WLAN_STATUS_SUCCESS; + +} /* end of assocCheckRxReAssocRspFrameStatus() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will compose the Disassociation frame + * + * @param[in] prStaRec Pointer to the STA_RECORD_T + * @param[in] pucBuffer Pointer to the frame buffer. + * @param[in] aucMACAddress Given Our MAC Address. + * @param[in] u2ReasonCode The reason code of disassociation + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void +assocComposeDisassocFrame(IN struct STA_RECORD *prStaRec, + IN uint8_t *pucBuffer, IN uint8_t aucMACAddress[], + IN uint16_t u2ReasonCode) +{ + struct WLAN_DISASSOC_FRAME *prDisAssocFrame; + uint16_t u2FrameCtrl; + + prDisAssocFrame = (struct WLAN_DISASSOC_FRAME *)pucBuffer; + + /* 4 <1> Compose the frame header of the DisAssociation frame. */ + /* Fill the Frame Control field. */ + u2FrameCtrl = MAC_FRAME_DISASSOC; + + WLAN_SET_FIELD_16(&prDisAssocFrame->u2FrameCtrl, u2FrameCtrl); + + /* Fill the DA field with Target BSSID. */ + COPY_MAC_ADDR(prDisAssocFrame->aucDestAddr, prStaRec->aucMacAddr); + + /* Fill the SA field with our MAC Address. */ + COPY_MAC_ADDR(prDisAssocFrame->aucSrcAddr, aucMACAddress); + + /* Fill the BSSID field with Target BSSID. */ + COPY_MAC_ADDR(prDisAssocFrame->aucBSSID, prStaRec->aucMacAddr); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, + * so we need to clear it). + */ + prDisAssocFrame->u2SeqCtrl = 0; + + /* 4 <2> Compose the frame body's fixed field part of + * the Disassociation frame. + */ + /* Fill the Reason Code field. */ + WLAN_SET_FIELD_16(&prDisAssocFrame->u2ReasonCode, u2ReasonCode); +} /* end of assocComposeDisassocFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will send the Disassociation frame + * + * @param[in] prStaRec Pointer to the STA_RECORD_T + * @param[in] u2ReasonCode The reason code of disassociation + * + * @retval WLAN_STATUS_RESOURCES No available resource for frame composing. + * @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module + */ +/*----------------------------------------------------------------------------*/ +uint32_t assocSendDisAssocFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN uint16_t u2ReasonCode) +{ + uint8_t *pucMacAddress; + struct MSDU_INFO *prMsduInfo; + uint16_t u2PayloadLen; + uint16_t u2EstimatedFrameLen; + /* UINT_32 u4Status = WLAN_STATUS_SUCCESS; */ + + DBGLOG(RSN, INFO, "assocSendDisAssocFrame\n"); + + /* 4 <1> Allocate a PKT_INFO_T for Disassociation Frame */ + /* Init with MGMT Header Length + Length of Fixed Fields + IE Length */ + u2EstimatedFrameLen = + MAC_TX_RESERVED_FIELD + WLAN_MAC_MGMT_HEADER_LEN + + REASON_CODE_FIELD_LEN; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SAA, WARN, "No PKT_INFO_T for sending DisAssoc.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Disassociation frame header and fixed fields + * in MSDU_INfO_T. + */ + pucMacAddress = + GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex)->aucOwnMacAddr; + + /* Compose Header and Fixed Field */ + assocComposeDisassocFrame(prStaRec, + (uint8_t + *) ((unsigned long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD), pucMacAddress, + u2ReasonCode); + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + /* PMF certification 4.3.3.1, 4.3.3.2 send unprotected + * deauth reason 6/7 + */ + if (prStaRec->rPmfCfg.fgRxDeauthResp != TRUE) { + + struct WLAN_DISASSOC_FRAME *prDisassocFrame; + + prDisassocFrame = + (struct WLAN_DISASSOC_FRAME + *)((unsigned long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + + prDisassocFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + } + } +#endif + + u2PayloadLen = REASON_CODE_FIELD_LEN; + + /* 4 <3> Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, NULL, + MSDU_RATE_MODE_AUTO); + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + /* caution: access prStaRec only if true */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + /* 4.3.3.1 send unprotected deauth reason 6/7 */ + if (prStaRec->rPmfCfg.fgRxDeauthResp != TRUE) { + DBGLOG(RSN, INFO, + "Disassoc Set MSDU_OPT_PROTECTED_FRAME\n"); + nicTxConfigPktOption(prMsduInfo, + MSDU_OPT_PROTECTED_FRAME, TRUE); + } + + prStaRec->rPmfCfg.fgRxDeauthResp = FALSE; + } +#endif + DBGLOG(SAA, INFO, "ucTxSeqNum=%d ucStaRecIndex=%d u2ReasonCode=%d\n", + prMsduInfo->ucTxSeqNum, prMsduInfo->ucStaRecIndex, u2ReasonCode); + + /* 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t +assocProcessRxDisassocFrame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, IN uint8_t aucBSSID[], + OUT uint16_t *pu2ReasonCode) +{ + struct WLAN_DISASSOC_FRAME *prDisassocFrame; + uint16_t u2RxReasonCode; + + if (!prSwRfb || !aucBSSID || !pu2ReasonCode) { + DBGLOG(SAA, WARN, "Invalid parameters, ignore pkt!\n"); + return WLAN_STATUS_FAILURE; + } + + /* 4 <1> locate the Disassociation Frame. */ + prDisassocFrame = (struct WLAN_DISASSOC_FRAME *)prSwRfb->pvHeader; + + /* 4 <2> Parse the Header of Disassociation Frame. */ + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < + REASON_CODE_FIELD_LEN) { + DBGLOG(SAA, LOUD, "Invalid DisAssoc packet length!"); + 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t assocProcessRxAssocReqFrame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + OUT uint16_t *pu2StatusCode) +{ + struct WLAN_ASSOC_REQ_FRAME *prAssocReqFrame; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + struct IE_SSID *prIeSsid = (struct IE_SSID *)NULL; + struct RSN_INFO_ELEM *prIeRsn = (struct RSN_INFO_ELEM *)NULL; + struct IE_SUPPORTED_RATE_IOT *prIeSupportedRate = + (struct IE_SUPPORTED_RATE_IOT *)NULL; + struct IE_EXT_SUPPORTED_RATE *prIeExtSupportedRate = + (struct IE_EXT_SUPPORTED_RATE *)NULL; + struct WIFI_VAR *prWifiVar = NULL; + uint8_t *pucIE, *pucIEStart; + uint16_t u2IELength; + uint16_t u2Offset = 0; + uint16_t u2StatusCode = STATUS_CODE_SUCCESSFUL; + uint16_t u2RxFrameCtrl; + uint16_t u2BSSBasicRateSet; + uint8_t ucFixedFieldLength; + u_int8_t fgIsUnknownBssBasicRate; + uint32_t i; + u_int8_t fgIsTKIP = FALSE; + enum ENUM_BAND eBand = 0; + struct RX_DESC_OPS_T *prRxDescOps; + + if (!prAdapter || !prSwRfb || !pu2StatusCode) { + DBGLOG(SAA, WARN, "Invalid parameters, ignore pkt!\n"); + return WLAN_STATUS_FAILURE; + } + + prWifiVar = &(prAdapter->rWifiVar); + prRxDescOps = prAdapter->chip_info->prRxDescOps; + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prStaRec == NULL) + return WLAN_STATUS_FAILURE; + + /* 4 <1> locate the Association Req Frame. */ + prAssocReqFrame = (struct WLAN_ASSOC_REQ_FRAME *)prSwRfb->pvHeader; + + /* WLAN_GET_FIELD_16(&prAssocReqFrame->u2FrameCtrl, + * &u2RxFrameCtrl); + */ + u2RxFrameCtrl = prAssocReqFrame->u2FrameCtrl; + /* NOTE(Kevin): Optimized for ARM */ + u2RxFrameCtrl &= MASK_FRAME_TYPE; + + /* 4 <2> Parse the Header of Association Req Frame. */ + if (u2RxFrameCtrl == MAC_FRAME_REASSOC_REQ) + ucFixedFieldLength = + CAP_INFO_FIELD_LEN + LISTEN_INTERVAL_FIELD_LEN + + CURR_AP_ADDR_FIELD_LEN; + else + ucFixedFieldLength = + CAP_INFO_FIELD_LEN + LISTEN_INTERVAL_FIELD_LEN; + + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) + <= ucFixedFieldLength) { + /* Length of this (re)association req is invalid, ignore it */ + return WLAN_STATUS_FAILURE; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + /* 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 */ + + if (u2RxFrameCtrl == MAC_FRAME_REASSOC_REQ) { + prStaRec->fgIsReAssoc = TRUE; + + u2IELength = prSwRfb->u2PacketLen - + (uint16_t) OFFSET_OF(struct WLAN_REASSOC_REQ_FRAME, + aucInfoElem[0]); + + pucIEStart = pucIE = + ((struct WLAN_REASSOC_REQ_FRAME *)(prSwRfb-> + pvHeader))->aucInfoElem; + } else { + prStaRec->fgIsReAssoc = FALSE; + + u2IELength = prSwRfb->u2PacketLen - + (uint16_t) OFFSET_OF(struct WLAN_ASSOC_REQ_FRAME, + aucInfoElem[0]); + + pucIEStart = pucIE = prAssocReqFrame->aucInfoElem; + } + + /* 4 <3> Parse the Fixed Fields of Assoc Req Frame Body. */ + prStaRec->u2CapInfo = prAssocReqFrame->u2CapInfo; + +#if 0 +/* CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_HOTSPOT_PRIVACY_CHECK */ + if (prAdapter->fgIsP2PRegistered && IS_STA_P2P_TYPE(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 = (struct IE_SSID *)pucIE; + } + break; + + case ELEM_ID_SUP_RATES: + if ((!prIeSupportedRate) + && (IE_LEN(pucIE) <= RATE_NUM_SW)) + prIeSupportedRate = SUP_RATES_IOT_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_VHT_CAP: + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_VHT; + 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, + prStaRec, + &u2StatusCode); + if (u2StatusCode != STATUS_CODE_SUCCESSFUL) { + *pu2StatusCode = u2StatusCode; + return WLAN_STATUS_SUCCESS; + } + } +#endif + break; + case ELEM_ID_VENDOR: + if (p2pFuncParseCheckForTKIPInfoElem(pucIE)) + fgIsTKIP = TRUE; + +#if CFG_ENABLE_WIFI_DIRECT + { + if ((prAdapter->fgIsP2PRegistered)) { + uint8_t 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; + case ELEM_ID_IBSS_PARAM_SET: + /* Check IBSS parameter set length to avoid + * abnormal content + */ + if (IE_LEN(pucIE) != ELEM_MAX_LEN_IBSS_PARAMETER_SET) { + *pu2StatusCode = + STATUS_CODE_UNSPECIFIED_FAILURE; + DBGLOG(SAA, WARN, + "Invalid IBSS Parameter IE length!\n"); + return WLAN_STATUS_FAILURE; + } + break; +#if (CFG_SUPPORT_802_11AX == 1) + case ELEM_ID_RESERVED: + if (IE_ID_EXT(pucIE) == ELEM_EXT_ID_HE_CAP) + prStaRec->ucPhyTypeSet |= PHY_TYPE_SET_802_11AX; + break; +#endif + default: + for (i = 0; + i < + (sizeof(rxAssocReqIETable) / + sizeof(struct VERIFY_IE_ENTRY)); i++) { + + if (((IE_ID(pucIE)) == + rxAssocReqIETable[i].ucElemID) + && (rxAssocReqIETable[i].pfnVarifyIE != + NULL)) { + rxAssocReqIETable[i].pfnVarifyIE + (prAdapter, prSwRfb, + (struct IE_HDR *)pucIE, + &u2StatusCode); + + if (u2StatusCode != + STATUS_CODE_SUCCESSFUL) { + *pu2StatusCode = u2StatusCode; + return WLAN_STATUS_SUCCESS; + } + } + } + + break; + } + } /* end of IE_FOR_EACH */ + + /* + * According to TGn & TGac 4.2.44, AP should not bring HT/VHT Cap IE in + * the IE of Assoc resp, if the STA request to use TKIP cipher + */ + if (fgIsTKIP && !prWifiVar->ucApAllowHtVhtTkip) + prStaRec->ucPhyTypeSet &= ~(PHY_TYPE_BIT_VHT | PHY_TYPE_BIT_HT); + + /* 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) { + DBGLOG(SAA, WARN, "Supported Rate not present!\n"); + u2StatusCode = + STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED; + break; + } + /* Ignore any Basic Bit */ + rateGetRateSetFromIEs(prIeSupportedRate, + prIeExtSupportedRate, + &prStaRec->u2OperationalRateSet, + &u2BSSBasicRateSet, + &fgIsUnknownBssBasicRate); + + if ((prBssInfo-> + u2BSSBasicRateSet & prStaRec->u2OperationalRateSet) + != prBssInfo->u2BSSBasicRateSet) { + u2StatusCode = + STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED; + DBGLOG(SAA, WARN, "Basic rate not supported!\n"); + break; + } + + /* Accpet the Sta, update BSSBasicRateSet from Bss */ + prStaRec->u2BSSBasicRateSet = + prBssInfo->u2BSSBasicRateSet; + + prStaRec->u2DesiredNonHTRateSet = + (prStaRec->u2OperationalRateSet & RATE_SET_ALL_ABG); + + RX_STATUS_GET( + prRxDescOps, + eBand, + get_rf_band, + prSwRfb->prRxStatus); + if (eBand == BAND_2G4) { + 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; + } else { /* (BAND_5G == prBssDesc->eBande) */ + if (prStaRec->u2OperationalRateSet & + RATE_SET_OFDM) + prStaRec->ucPhyTypeSet |= + PHY_TYPE_BIT_OFDM; + } + + /* Update default Tx rate */ + nicTxUpdateStaRecDefaultRate(prAdapter, prStaRec); + +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_HOTSPOT_PRIVACY_CHECK + if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { + if (prIeRsn) { + if (!kalP2PGetCipher + (prAdapter->prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData)) { + 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 */ + { + uint8_t *cp = (uint8_t *) &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); + + if (prStaRec->pucAssocReqIe) { + kalMemCopy(prStaRec->pucAssocReqIe, + cp, u2IELength); + } else { + DBGLOG(SAA, LOUD, + "allocate memory for prStaRec->pucAssocReqIe failed!\n"); + return WLAN_STATUS_RESOURCES; + } + } + } +#endif + kalP2PUpdateAssocInfo(prAdapter->prGlueInfo, + (uint8_t *) &prAssocReqFrame->u2CapInfo, + u2IELength + + (prStaRec->fgIsReAssoc ? 10 : 4), + prStaRec->fgIsReAssoc, + prStaRec->ucBssIndex); + } +#endif + + *pu2StatusCode = u2StatusCode; + + return WLAN_STATUS_SUCCESS; + +} /* end of assocProcessRxAssocReqFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is used to compose Common Information Elements for + * Association Response Frame. + * + * @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. + * @param[in] prBssInfo Pointer to the BSS_INFO_T. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void +assocBuildReAssocRespFrameCommonIEs(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN struct BSS_INFO *prBssInfo) +{ + uint8_t *pucBuffer; + struct STA_RECORD *prStaRec; + uint8_t ucSupRatesLen; + uint8_t ucExtSupRatesLen; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + pucBuffer = + (uint8_t *) ((unsigned long)prMsduInfo->prPacket + + (unsigned long)prMsduInfo->u2FrameLength); + + if (prBssInfo->ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) { + ucSupRatesLen = ELEM_MAX_LEN_SUP_RATES; + ucExtSupRatesLen = + prBssInfo->ucAllSupportedRatesLen - ELEM_MAX_LEN_SUP_RATES; + } else { + ucSupRatesLen = prBssInfo->ucAllSupportedRatesLen; + ucExtSupRatesLen = 0; + } + + /* Fill the Supported Rates element. */ + if (ucSupRatesLen) { + SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_SUP_RATES; + SUP_RATES_IE(pucBuffer)->ucLength = ucSupRatesLen; + kalMemCopy(SUP_RATES_IE(pucBuffer)->aucSupportedRates, + prBssInfo->aucAllSupportedRates, ucSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } + + /* Fill the Extended Supported Rates element. */ + if (ucExtSupRatesLen) { + + EXT_SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_EXTENDED_SUP_RATES; + EXT_SUP_RATES_IE(pucBuffer)->ucLength = ucExtSupRatesLen; + + kalMemCopy(EXT_SUP_RATES_IE(pucBuffer)->aucExtSupportedRates, + &prBssInfo->aucAllSupportedRates[ucSupRatesLen], + ucExtSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + } +} /* end of assocBuildReAssocRespFrameCommonIEs() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will compose the (Re)Association Response frame + * + * @param[in] prStaRec Pointer to the STA_RECORD_T + * @param[in] pucBuffer Pointer to the frame buffer. + * @param[in] aucBssid Given BSSID. + * @param[in] u2CapInfo Capability Field of current BSS. + * @param[in out] pu2PayloadLen Return the length of the composed + * fixed fields + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void +assocComposeReAssocRespFrameHeaderAndFF(IN struct STA_RECORD *prStaRec, + IN uint8_t *pucBuffer, + IN uint8_t aucBSSID[], + IN uint16_t u2CapInfo, + IN OUT uint16_t *pu2PayloadLen) +{ + struct WLAN_ASSOC_RSP_FRAME *prAssocRspFrame; + u_int8_t fgIsReAssoc; + + uint16_t u2FrameCtrl; + + prAssocRspFrame = (struct WLAN_ASSOC_RSP_FRAME *)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)); + */ + /* NOTE(Kevin): Optimized for ARM */ + prAssocRspFrame->u2AssocId = + ((prStaRec->u2AssocId & AID_MASK) | AID_MSB); + + *pu2PayloadLen = + (CAP_INFO_FIELD_LEN + STATUS_CODE_FIELD_LEN + AID_FIELD_LEN); +} /* end of assocComposeReAssocRespFrameHeaderAndFF() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will send the (Re)Association Resp frame + * + * @param[in] prStaRec Pointer to the STA_RECORD_T + * + * @retval WLAN_STATUS_RESOURCES No available resource for frame composing. + * @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module + */ +/*----------------------------------------------------------------------------*/ +uint32_t assocSendReAssocRespFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + struct BSS_INFO *prBssInfo; + struct MSDU_INFO *prMsduInfo; + + uint16_t u2PayloadLen; + uint16_t u2EstimatedFrameLen; + uint16_t u2EstimatedExtraIELen; + u_int8_t fgIsReAssoc; + uint32_t i; + + /* 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_SW - ELEM_MAX_LEN_SUP_RATES)); + + /* + Extra IE Length */ + u2EstimatedExtraIELen = 0; + + for (i = 0; + i < + sizeof(txAssocRespIETable) / sizeof(struct APPEND_VAR_IE_ENTRY); + i++) { + if (txAssocRespIETable[i].u2EstimatedFixedIELen != 0) { + u2EstimatedExtraIELen += + txAssocRespIETable[i].u2EstimatedFixedIELen; + } else if (txAssocRespIETable[i].pfnCalculateVariableIELen != + NULL) { + u2EstimatedExtraIELen += (uint16_t) + txAssocRespIETable[i].pfnCalculateVariableIELen + (prAdapter, prStaRec->ucBssIndex, prStaRec); + } + + } + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(AAA, WARN, + "No PKT_INFO_T for sending (Re)Assoc Response.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose (Re)Association Request frame header and fixed fields + * in MSDU_INfO_T. + */ + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + /* Compose Header and Fixed Field */ + assocComposeReAssocRespFrameHeaderAndFF(prStaRec, + (uint8_t *) ((unsigned long) + (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + prBssInfo->aucBSSID, prBssInfo->u2CapInfo, + &u2PayloadLen); + + /* 4 <3> Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, + aaaFsmRunEventTxDone, MSDU_RATE_MODE_AUTO); + + /* 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(struct APPEND_VAR_IE_ENTRY); + i++) { + if (txAssocRespIETable[i].pfnAppendIE) + txAssocRespIETable[i].pfnAppendIE(prAdapter, + prMsduInfo); + + } + +#if CFG_SUPPORT_WFD + /* TODO put WFD IE in assoc resp if driver will send assoc resp */ + +#endif + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU + */ + + nicTxConfigPktControlFlag(prMsduInfo, MSDU_CONTROL_FLAG_FORCE_TX, TRUE); + + /* 4 <6> Enqueue the frame to send this (Re)Association request frame. + */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + DBGLOG(SAA, INFO, + "Send Assoc Resp to " MACSTR ", Seq: %d, status: %d\n", + MAC2STR(prStaRec->aucMacAddr), + prMsduInfo->ucTxSeqNum, + prStaRec->u2StatusCode); + + return WLAN_STATUS_SUCCESS; + +} /* end of assocSendReAssocRespFrame() */ + +/*-----------------------------------------------------------------------*/ +/*! + * @brief Get the non-wfa vendor ie length that was previously set + * by wpa_supplicant for association request frame. + * + * @param prAdapter pointer to driver adapter + * + * @retval length of the non-wfa vendor ie + */ +/*-----------------------------------------------------------------------*/ +uint16_t assoc_get_nonwfa_vend_ie_len(struct ADAPTER *prAdapter, + uint8_t ucBssIndex) +{ + struct CONNECTION_SETTINGS *prConnSettings; + + if (!prAdapter || !prAdapter->prGlueInfo) + return 0; + + prConnSettings = + aisGetConnSettings(prAdapter, ucBssIndex); + if (!prConnSettings) + return 0; + + return prConnSettings->non_wfa_vendor_ie_len; +} + +/*-----------------------------------------------------------------------*/ +/*! + * @brief Builds the non-wfa vendor specific ies into association + * request frame. + * + * @param prAdapter pointer to driver adapter + * prMsduInfo pointer to the msdu frame body + * + * @retval void + */ +/*-----------------------------------------------------------------------*/ +void assoc_build_nonwfa_vend_ie(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct CONNECTION_SETTINGS *prConnSettings; + uint8_t ucBssIndex = 0; + uint8_t *ptr = NULL; + uint16_t len = 0; + + if (!prAdapter || !prMsduInfo) + return; + + ucBssIndex = prMsduInfo->ucBssIndex; + prConnSettings = + aisGetConnSettings(prAdapter, ucBssIndex); + if (!prConnSettings) + return; + + len = prConnSettings->non_wfa_vendor_ie_len; + if (!len) + return; + + ptr = (uint8_t *)prMsduInfo->prPacket + + (uint16_t)prMsduInfo->u2FrameLength; + kalMemCopy(ptr, prConnSettings->non_wfa_vendor_ie_buf, + len); + prMsduInfo->u2FrameLength += len; +} + +void assocGenerateMDIE(IN struct ADAPTER *prAdapter, + IN OUT struct MSDU_INFO *prMsduInfo) +{ + uint8_t *pucBuffer = + (uint8_t *)prMsduInfo->prPacket + prMsduInfo->u2FrameLength; + uint8_t ucBssIndex = prMsduInfo->ucBssIndex; + enum ENUM_PARAM_AUTH_MODE eAuthMode = + aisGetAuthMode(prAdapter, ucBssIndex); + struct FT_IES *prFtIEs = aisGetFtIe(prAdapter, ucBssIndex); + struct GL_WPA_INFO *prWpaInfo = aisGetWpaInfo(prAdapter, + ucBssIndex); + + /* don't include MDIE in assoc request frame if auth mode is not FT + * related + */ + if (eAuthMode != AUTH_MODE_WPA2_FT && + eAuthMode != AUTH_MODE_WPA2_FT_PSK && + !(eAuthMode == AUTH_MODE_OPEN && + prWpaInfo->u4WpaVersion == + IW_AUTH_WPA_VERSION_DISABLED && + prWpaInfo->u4AuthAlg == + IW_AUTH_ALG_FT)) /* Non-RSN FT */ + return; + + if (!prFtIEs->prMDIE) { + struct BSS_DESC *prBssDesc = + aisGetTargetBssDesc(prAdapter, ucBssIndex); + uint8_t *pucIE = &prBssDesc->aucIEBuf[0]; + uint16_t u2IeLen = prBssDesc->u2IELength; + uint16_t u2IeOffSet = 0; + + IE_FOR_EACH(pucIE, u2IeLen, u2IeOffSet) + { + if (IE_ID(pucIE) == ELEM_ID_MOBILITY_DOMAIN) { + /* IE size for MD IE is fixed, it is 5 */ + prMsduInfo->u2FrameLength += 5; + kalMemCopy(pucBuffer, pucIE, 5); + break; + } + } + return; + } + prMsduInfo->u2FrameLength += + 5; /* IE size for MD IE is fixed, it is 5 */ + kalMemCopy(pucBuffer, prFtIEs->prMDIE, 5); + DBGLOG(SAA, TRACE, "FT: Generate MD IE\n"); +} + +#endif /* CFG_SUPPORT_AAA */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/auth.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/auth.c new file mode 100644 index 0000000000000..517039b80076c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/auth.c @@ -0,0 +1,1383 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + +/******************************************************************************* + * C O M P I L E 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 + ******************************************************************************* + */ +struct APPEND_VAR_IE_ENTRY txAuthIETable[] = { + {(ELEM_HDR_LEN + ELEM_MAX_LEN_CHALLENGE_TEXT), NULL, + authAddIEChallengeText}, + {0, authCalculateRSNIELen, authAddRSNIE}, /* Element ID: 48 */ + {(ELEM_HDR_LEN + 1), NULL, authAddMDIE}, /* Element ID: 54 */ + {0, rsnCalculateFTIELen, rsnGenerateFTIE}, /* Element ID: 55 */ +}; + +struct HANDLE_IE_ENTRY rxAuthIETable[] = { + {ELEM_ID_CHALLENGE_TEXT, authHandleIEChallengeText} +}; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will compose the Authentication frame header and + * fixed fields. + * + * @param[in] pucBuffer Pointer to the frame buffer. + * @param[in] aucPeerMACAddress Given Peer MAC Address. + * @param[in] aucMACAddress Given Our MAC Address. + * @param[in] u2AuthAlgNum Authentication Algorithm Number + * @param[in] u2TransactionSeqNum Transaction Sequence Number + * @param[in] u2StatusCode Status Code + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void +authComposeAuthFrameHeaderAndFF(IN uint8_t *pucBuffer, + IN uint8_t aucPeerMACAddress[], + IN uint8_t aucMACAddress[], + IN uint16_t u2AuthAlgNum, + IN uint16_t u2TransactionSeqNum, + IN uint16_t u2StatusCode) +{ + struct WLAN_AUTH_FRAME *prAuthFrame; + uint16_t u2FrameCtrl; + + prAuthFrame = (struct WLAN_AUTH_FRAME *)pucBuffer; + + /* 4 <1> Compose the frame header of the Authentication frame. */ + /* Fill the Frame Control field. */ + u2FrameCtrl = MAC_FRAME_AUTH; + + /* If this frame is the third frame in the shared key authentication + * sequence, it shall be encrypted. + */ + if ((u2AuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY) + && (u2TransactionSeqNum == AUTH_TRANSACTION_SEQ_3)) + u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + /* HW will also detect this bit for applying encryption */ + /* WLAN_SET_FIELD_16(&prAuthFrame->u2FrameCtrl, u2FrameCtrl); */ + prAuthFrame->u2FrameCtrl = u2FrameCtrl; + /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the DA field with Target BSSID. */ + COPY_MAC_ADDR(prAuthFrame->aucDestAddr, aucPeerMACAddress); + + /* Fill the SA field with our MAC Address. */ + COPY_MAC_ADDR(prAuthFrame->aucSrcAddr, aucMACAddress); + + switch (u2TransactionSeqNum) { + case AUTH_TRANSACTION_SEQ_1: + case AUTH_TRANSACTION_SEQ_3: + + /* Fill the BSSID field with Target BSSID. */ + COPY_MAC_ADDR(prAuthFrame->aucBSSID, aucPeerMACAddress); + break; + + case AUTH_TRANSACTION_SEQ_2: + case AUTH_TRANSACTION_SEQ_4: + + /* Fill the BSSID field with Current BSSID. */ + COPY_MAC_ADDR(prAuthFrame->aucBSSID, aucMACAddress); + break; + + default: + ASSERT(0); + } + + /* Clear the SEQ/FRAG_NO field. */ + prAuthFrame->u2SeqCtrl = 0; + + /* 4 <2> Compose the frame body's fixed field part of + * the Authentication frame. + */ + /* Fill the Authentication Algorithm Number field. */ + /* WLAN_SET_FIELD_16(&prAuthFrame->u2AuthAlgNum, u2AuthAlgNum); */ + prAuthFrame->u2AuthAlgNum = u2AuthAlgNum; + /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the Authentication Transaction Sequence Number field. */ + /* WLAN_SET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, + * u2TransactionSeqNum); + */ + prAuthFrame->u2AuthTransSeqNo = u2TransactionSeqNum; + /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the Status Code field. */ + /* WLAN_SET_FIELD_16(&prAuthFrame->u2StatusCode, u2StatusCode); */ + prAuthFrame->u2StatusCode = u2StatusCode; + /* NOTE(Kevin): Optimized for ARM */ +} /* end of authComposeAuthFrameHeaderAndFF() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will append Challenge Text IE to the Authentication + * frame + * + * @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void authAddIEChallengeText(IN struct ADAPTER *prAdapter, + IN OUT struct MSDU_INFO *prMsduInfo) +{ + struct WLAN_AUTH_FRAME *prAuthFrame; + struct STA_RECORD *prStaRec; + uint16_t u2TransactionSeqNum; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (!prStaRec) + return; + + /* For Management, frame header and payload are in a continuous + * buffer + */ + prAuthFrame = (struct WLAN_AUTH_FRAME *)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(((unsigned long)(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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t authSendAuthFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN uint16_t u2TransactionSeqNum) +{ + struct MSDU_INFO *prMsduInfo; + struct BSS_INFO *prBssInfo; + uint16_t u2EstimatedFrameLen; + uint16_t u2EstimatedExtraIELen; + uint16_t u2PayloadLen; + uint32_t i; + + DBGLOG(SAA, LOUD, "Send Auth Frame\n"); + + /* 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(struct APPEND_VAR_IE_ENTRY); + i++) { + if (txAssocRespIETable[i].u2EstimatedFixedIELen != 0) + u2EstimatedExtraIELen += + txAssocRespIETable[i].u2EstimatedFixedIELen; + else if (txAssocRespIETable[i].pfnCalculateVariableIELen != + NULL) + u2EstimatedExtraIELen += + (uint16_t)txAssocRespIETable[i] + .pfnCalculateVariableIELen( + prAdapter, prStaRec->ucBssIndex, + prStaRec); + } + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SAA, WARN, "No PKT_INFO_T for sending Auth Frame.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Authentication Request frame header and fixed fields + * in MSDU_INfO_T. + */ + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex) + + /* Compose Header and some Fixed Fields */ + authComposeAuthFrameHeaderAndFF((uint8_t *) + ((uint32_t) (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 */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, + saaFsmRunEventTxDone, MSDU_RATE_MODE_AUTO); + + /* 4 <4> Compose IEs in MSDU_INFO_T */ + for (i = 0; i < sizeof(txAuthIETable) / sizeof(struct APPEND_IE_ENTRY); + i++) { + if (txAuthIETable[i].pfnAppendIE) + txAuthIETable[i].pfnAppendIE(prAdapter, prMsduInfo); + + } + + /* TODO(Kevin): + * Also release the unused tail room of the composed MMPDU + */ + + nicTxConfigPktControlFlag(prMsduInfo, MSDU_CONTROL_FLAG_FORCE_TX, TRUE); + + /* 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +authSendAuthFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN uint8_t ucBssIndex, + IN struct SW_RFB *prFalseAuthSwRfb, + IN uint16_t u2TransactionSeqNum, IN uint16_t u2StatusCode) +{ + uint8_t *pucReceiveAddr; + uint8_t *pucTransmitAddr; + struct MSDU_INFO *prMsduInfo; + struct BSS_INFO *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; + uint16_t u2EstimatedFrameLen; + uint16_t u2EstimatedExtraIELen; + uint16_t u2PayloadLen; + uint16_t ucAuthAlgNum; + uint32_t i; + + /* 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(struct APPEND_VAR_IE_ENTRY); + i++) { + if (txAuthIETable[i].u2EstimatedFixedIELen != 0) + u2EstimatedExtraIELen += + txAuthIETable[i].u2EstimatedFixedIELen; + else + u2EstimatedExtraIELen += + txAuthIETable[i].pfnCalculateVariableIELen( + prAdapter, ucBssIndex, prStaRec); + } + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SAA, WARN, "No PKT_INFO_T for sending Auth Frame.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Authentication Request frame header and + * fixed fields in MSDU_INfO_T. + */ + if (prStaRec) { + prBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + 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 */ + struct WLAN_AUTH_FRAME *prFalseAuthFrame; + + prFalseAuthFrame = + (struct WLAN_AUTH_FRAME *)prFalseAuthSwRfb->pvHeader; + + pucTransmitAddr = prFalseAuthFrame->aucDestAddr; + + pucReceiveAddr = prFalseAuthFrame->aucSrcAddr; + + ucAuthAlgNum = prFalseAuthFrame->u2AuthAlgNum; + + u2TransactionSeqNum = (prFalseAuthFrame->u2AuthTransSeqNo + 1); + } + + /* Compose Header and some Fixed Fields */ + authComposeAuthFrameHeaderAndFF((uint8_t *) + ((unsigned long)(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 */ + + TX_SET_MMPDU(prAdapter, + prMsduInfo, + ucBssIndex, + (prStaRec != + NULL) ? (prStaRec->ucIndex) : (STA_REC_INDEX_NOT_FOUND), + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, pfTxDoneHandler, + MSDU_RATE_MODE_AUTO); + + if ((ucAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY) + && (u2TransactionSeqNum == AUTH_TRANSACTION_SEQ_3)) + nicTxConfigPktOption(prMsduInfo, MSDU_OPT_PROTECTED_FRAME, + TRUE); + /* 4 <4> Compose IEs in MSDU_INFO_T */ + for (i = 0; + i < sizeof(txAuthIETable) / sizeof(struct APPEND_VAR_IE_ENTRY); + i++) { + if (txAuthIETable[i].pfnAppendIE) + txAuthIETable[i].pfnAppendIE(prAdapter, prMsduInfo); + } + + /* TODO(Kevin): + * Also release the unused tail room of the composed MMPDU + */ + + nicTxConfigPktControlFlag(prMsduInfo, MSDU_CONTROL_FLAG_FORCE_TX, TRUE); + + /* 4 <6> Inform TXM to send this Authentication frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + DBGLOG(SAA, INFO, + "Send Auth Frame, TranSeq: %d, Status: %d, Seq: %d\n", + u2TransactionSeqNum, u2StatusCode, prMsduInfo->ucTxSeqNum); + + 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t authCheckTxAuthFrame(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN uint16_t u2TransactionSeqNum) +{ + struct WLAN_AUTH_FRAME *prAuthFrame; + struct STA_RECORD *prStaRec; + uint16_t u2TxFrameCtrl; + uint16_t u2TxAuthAlgNum; + uint16_t u2TxTransactionSeqNum; + + prAuthFrame = (struct WLAN_AUTH_FRAME *)(prMsduInfo->prPacket); + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + 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 != (uint16_t) (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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t authCheckRxAuthFrameTransSeq(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct WLAN_AUTH_FRAME *prAuthFrame; + uint16_t u2RxTransactionSeqNum; + uint16_t u2MinPayloadLen; + struct STA_RECORD *prStaRec; + + /* 4 <1> locate the Authentication Frame. */ + prAuthFrame = (struct WLAN_AUTH_FRAME *)prSwRfb->pvHeader; + + /* 4 <2> Parse the Header of Authentication Frame. */ + u2MinPayloadLen = (AUTH_ALGORITHM_NUM_FIELD_LEN + + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + + STATUS_CODE_FIELD_LEN); + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < u2MinPayloadLen) { + DBGLOG(SAA, WARN, + "Rx Auth payload: len[%u] < min expected len[%u]\n", + (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen), + u2MinPayloadLen); + DBGLOG(SAA, WARN, "=== Dump Rx Auth ===\n"); + DBGLOG_MEM8(SAA, WARN, prAuthFrame, prSwRfb->u2PacketLen); + return WLAN_STATUS_SUCCESS; + } + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (prStaRec && IS_STA_IN_AIS(prStaRec)) { + if (prStaRec->eAuthAssocState == SAA_STATE_EXTERNAL_AUTH) { + saaFsmRunEventRxAuth(prAdapter, prSwRfb); + 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 */ + + DBGLOG(SAA, LOUD, + "Authentication Packet: Auth Trans Seq No = %d\n", + u2RxTransactionSeqNum); + + switch (u2RxTransactionSeqNum) { + case AUTH_TRANSACTION_SEQ_2: + case AUTH_TRANSACTION_SEQ_4: + if (prStaRec && IS_STA_IN_P2P(prStaRec) && + !IS_AP_STA(prStaRec)) + aaaFsmRunEventRxAuth(prAdapter, prSwRfb); + else + 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); +#if CFG_IGNORE_INVALID_AUTH_TSN + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (!prStaRec) + return WLAN_STATUS_SUCCESS; + switch (prStaRec->eAuthAssocState) { + case SAA_STATE_SEND_AUTH1: + case SAA_STATE_WAIT_AUTH2: + case SAA_STATE_SEND_AUTH3: + case SAA_STATE_WAIT_AUTH4: + saaFsmRunEventRxAuth(prAdapter, prSwRfb); + break; + default: + break; + } +#endif + + 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t +authCheckRxAuthFrameStatus(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint16_t u2TransactionSeqNum, + OUT uint16_t *pu2StatusCode) +{ + struct STA_RECORD *prStaRec; + struct WLAN_AUTH_FRAME *prAuthFrame; + uint16_t u2RxAuthAlgNum; + uint16_t u2RxTransactionSeqNum; + /* UINT_16 u2RxStatusCode; // NOTE(Kevin): Optimized for ARM */ + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (!prStaRec) + return WLAN_STATUS_INVALID_PACKET; + + /* 4 <1> locate the Authentication Frame. */ + prAuthFrame = (struct WLAN_AUTH_FRAME *)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 != (uint16_t) prStaRec->ucAuthAlgNum) { + DBGLOG(SAA, WARN, + "Discard Auth frame with auth type = %d, current = %d\n", + u2RxAuthAlgNum, prStaRec->ucAuthAlgNum); + *pu2StatusCode = STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED; + return WLAN_STATUS_SUCCESS; + } + /* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, + * &u2RxTransactionSeqNum); + */ + u2RxTransactionSeqNum = prAuthFrame->u2AuthTransSeqNo; + /* NOTE(Kevin): Optimized for ARM */ + if (u2RxTransactionSeqNum != u2TransactionSeqNum) { + DBGLOG(SAA, WARN, + "Discard Auth frame with Transaction Seq No = %d\n", + u2RxTransactionSeqNum); + *pu2StatusCode = STATUS_CODE_AUTH_OUT_OF_SEQ; + return WLAN_STATUS_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(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb, struct IE_HDR *prIEHdr) +{ + struct WLAN_AUTH_FRAME *prAuthFrame; + struct STA_RECORD *prStaRec; + uint16_t u2TransactionSeqNum; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (!prStaRec) + return; + + /* For Management, frame header and payload are in + * a continuous buffer + */ + prAuthFrame = (struct WLAN_AUTH_FRAME *)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) { + cnmMemFree(prAdapter, prStaRec->prChallengeText); + prStaRec->prChallengeText = + (struct IE_CHALLENGE_TEXT *)NULL; + } + prStaRec->prChallengeText = + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, IE_SIZE(prIEHdr)); + if (prStaRec->prChallengeText == NULL) + return; + + /* Save the Challenge Text from Auth Seq 2 Frame, + * before sending Auth Seq 3 Frame + */ + COPY_IE(prStaRec->prChallengeText, prIEHdr); + } + + return; + +} /* end of authAddIEChallengeText() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will parse and process the incoming Authentication + * frame. + * + * @param[in] prSwRfb Pointer to SW RFB data structure. + * + * @retval WLAN_STATUS_SUCCESS This is the frame we should handle. + */ +/*----------------------------------------------------------------------------*/ +uint32_t authProcessRxAuth2_Auth4Frame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct WLAN_AUTH_FRAME *prAuthFrame; + uint8_t *pucIEsBuffer; + uint16_t u2IEsLen; + uint16_t u2Offset; + uint8_t ucIEID; + uint32_t i; + + prAuthFrame = (struct WLAN_AUTH_FRAME *)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(struct HANDLE_IE_ENTRY)); + i++) { + if ((ucIEID == rxAuthIETable[i].ucElemID) + && (rxAuthIETable[i].pfnHandleIE != NULL)) + rxAuthIETable[i].pfnHandleIE(prAdapter, + prSwRfb, + (struct IE_HDR *)pucIEsBuffer); + } + } + if (prAuthFrame->u2AuthAlgNum == + AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION) { + if (prAuthFrame->u2AuthTransSeqNo == AUTH_TRANSACTION_SEQ_4) { + /* todo: check MIC, if mic error, return + * WLAN_STATUS_FAILURE + */ + } else if (prAuthFrame->u2AuthTransSeqNo == + AUTH_TRANSACTION_SEQ_2) { + struct cfg80211_ft_event_params *prFtEvent = + aisGetFtEventParam(prAdapter, + secGetBssIdxByRfb(prAdapter, + prSwRfb)); + + prFtEvent->ies = + &prAuthFrame->aucInfoElem[0]; + prFtEvent->ies_len = u2IEsLen; + } + } + + return WLAN_STATUS_SUCCESS; + +} /* end of authProcessRxAuth2_Auth4Frame() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will compose the Deauthentication frame + * + * @param[in] pucBuffer Pointer to the frame buffer. + * @param[in] aucPeerMACAddress Given Peer MAC Address. + * @param[in] aucMACAddress Given Our MAC Address. + * @param[in] u2StatusCode Status Code + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void +authComposeDeauthFrameHeaderAndFF(IN uint8_t *pucBuffer, + IN uint8_t aucPeerMACAddress[], + IN uint8_t aucMACAddress[], + IN uint8_t aucBssid[], + IN uint16_t u2ReasonCode) +{ + struct WLAN_DEAUTH_FRAME *prDeauthFrame; + uint16_t u2FrameCtrl; + + prDeauthFrame = (struct WLAN_DEAUTH_FRAME *)pucBuffer; + + /* 4 <1> Compose the frame header of the Deauthentication frame. */ + /* Fill the Frame Control field. */ + u2FrameCtrl = MAC_FRAME_DEAUTH; + + /* WLAN_SET_FIELD_16(&prDeauthFrame->u2FrameCtrl, u2FrameCtrl); */ + prDeauthFrame->u2FrameCtrl = u2FrameCtrl; + /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the DA field with Target BSSID. */ + COPY_MAC_ADDR(prDeauthFrame->aucDestAddr, aucPeerMACAddress); + + /* Fill the SA field with our MAC Address. */ + COPY_MAC_ADDR(prDeauthFrame->aucSrcAddr, aucMACAddress); + + /* Fill the BSSID field with Target BSSID. */ + COPY_MAC_ADDR(prDeauthFrame->aucBSSID, aucBssid); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, + * so we need to clear it). + */ + prDeauthFrame->u2SeqCtrl = 0; + + /* 4 <2> Compose the frame body's fixed field part of + * the Authentication frame. + */ + /* Fill the Status Code field. */ + /* WLAN_SET_FIELD_16(&prDeauthFrame->u2ReasonCode, u2ReasonCode); */ + prDeauthFrame->u2ReasonCode = u2ReasonCode; + /* NOTE(Kevin): Optimized for ARM */ +} /* end of authComposeDeauthFrameHeaderAndFF() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will send the Deauthenticiation frame + * + * @param[in] prStaRec Pointer to the STA_RECORD_T + * @param[in] prClassErrSwRfb Pointer to the SW_RFB_T which is Class Error. + * @param[in] u2ReasonCode A reason code to indicate why to leave BSS. + * @param[in] pfTxDoneHandler TX Done call back function + * + * @retval WLAN_STATUS_RESOURCES No available resource for frame composing. + * @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module + * @retval WLAN_STATUS_FAILURE Didn't send Deauth frame for various reasons. + */ +/*----------------------------------------------------------------------------*/ +uint32_t +authSendDeauthFrame(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct STA_RECORD *prStaRec, + IN struct SW_RFB *prClassErrSwRfb, IN uint16_t u2ReasonCode, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + uint8_t *pucReceiveAddr; + uint8_t *pucTransmitAddr; + uint8_t *pucBssid = NULL; + struct MSDU_INFO *prMsduInfo; + uint16_t u2EstimatedFrameLen; + + struct DEAUTH_INFO *prDeauthInfo; + OS_SYSTIME rCurrentTime; + int32_t i4NewEntryIndex, i; + uint8_t ucStaRecIdx = STA_REC_INDEX_NOT_FOUND; + uint8_t ucBssIndex = prAdapter->ucHwBssIdNum; + uint8_t aucBMC[] = BC_MAC_ADDR; + + /* NOTE(Kevin): The best way to reply the Deauth is according to + * the incoming data frame + */ + /* 4 <1.1> Find the Receiver Address */ + if (prClassErrSwRfb) { + u_int8_t fgIsAbleToSendDeauth = FALSE; + uint16_t u2RxFrameCtrl; + struct WLAN_MAC_HEADER_A4 *prWlanMacHeader = NULL; + + prWlanMacHeader = + (struct WLAN_MAC_HEADER_A4 *)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; + + DBGLOG(SAA, INFO, + "u2FrameCtrl=0x%x, DestAddr=" MACSTR + " srcAddr=" MACSTR " BSSID=" MACSTR + ", u2SeqCtrl=0x%x\n", + prWlanMacHeader->u2FrameCtrl, + MAC2STR(prWlanMacHeader->aucAddr1), + MAC2STR(prWlanMacHeader->aucAddr2), + MAC2STR(prWlanMacHeader->aucAddr3), + prWlanMacHeader->u2SeqCtrl); + /* Check if corresponding BSS is able to send Deauth */ + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, i); + + if (IS_NET_ACTIVE(prAdapter, i) && + (EQUAL_MAC_ADDR + (prWlanMacHeader->aucAddr1, + prBssInfo->aucOwnMacAddr))) { + + fgIsAbleToSendDeauth = TRUE; + ucBssIndex = (uint8_t) i; + break; + } + } + + if (!fgIsAbleToSendDeauth) + return WLAN_STATUS_FAILURE; + + pucReceiveAddr = prWlanMacHeader->aucAddr2; + } else if (prStaRec) { + prBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + ucStaRecIdx = prStaRec->ucIndex; + ucBssIndex = prBssInfo->ucBssIndex; + + pucReceiveAddr = prStaRec->aucMacAddr; + } else if (prBssInfo) { + ucBssIndex = prBssInfo->ucBssIndex; + ucStaRecIdx = STA_REC_INDEX_BMCAST; + + pucReceiveAddr = aucBMC; + } else { + DBGLOG(SAA, WARN, "Not to send Deauth, invalid data!\n"); + return WLAN_STATUS_INVALID_DATA; + } + + /* 4 <1.2> Find Transmitter Address and BSSID. */ + pucTransmitAddr = prBssInfo->aucOwnMacAddr; + pucBssid = prBssInfo->aucBSSID; + + if (ucStaRecIdx != STA_REC_INDEX_BMCAST) { + /* 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 <5> Allocate a PKT_INFO_T for Deauthentication Frame */ + /* Init with MGMT Header Length + Length of Fixed Fields + IE Length */ + u2EstimatedFrameLen = + (MAC_TX_RESERVED_FIELD + WLAN_MAC_MGMT_HEADER_LEN + + REASON_CODE_FIELD_LEN); + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SAA, WARN, + "No PKT_INFO_T for sending Deauth Request.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <6> compose Deauthentication frame header and some fixed fields */ + authComposeDeauthFrameHeaderAndFF((uint8_t *) + ((unsigned long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD), + pucReceiveAddr, pucTransmitAddr, + pucBssid, u2ReasonCode); + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + /* PMF certification 4.3.3.1, 4.3.3.2 send unprotected + * deauth reason 6/7 + * if (AP mode & not for PMF reply case) OR (STA PMF) + */ + if (((GET_BSS_INFO_BY_INDEX + (prAdapter, + prStaRec->ucBssIndex)->eCurrentOPMode == + OP_MODE_ACCESS_POINT) + && (prStaRec->rPmfCfg.fgRxDeauthResp != TRUE)) + || + (GET_BSS_INFO_BY_INDEX + (prAdapter, + prStaRec->ucBssIndex)->eNetworkType == + (uint8_t) NETWORK_TYPE_AIS)) { + + struct WLAN_DEAUTH_FRAME *prDeauthFrame; + + prDeauthFrame = (struct WLAN_DEAUTH_FRAME *)(uint8_t *) + ((unsigned long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + + prDeauthFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + if (GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex)->eNetworkType == + (uint8_t) NETWORK_TYPE_AIS) { + GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex) + ->encryptedDeauthIsInProcess + = TRUE; + } + DBGLOG(SAA, INFO, + "Reason=%d, DestAddr=" MACSTR + " srcAddr=" MACSTR " BSSID=" MACSTR "\n", + prDeauthFrame->u2ReasonCode, + MAC2STR(prDeauthFrame->aucDestAddr), + MAC2STR(prDeauthFrame->aucSrcAddr), + MAC2STR(prDeauthFrame->aucBSSID)); + } + } +#endif + nicTxSetPktLifeTime(prMsduInfo, 100); + + nicTxSetPktRetryLimit(prMsduInfo, TX_DESC_TX_COUNT_NO_LIMIT); + + /* 4 <7> Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + ucBssIndex, + ucStaRecIdx, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + REASON_CODE_FIELD_LEN, + pfTxDoneHandler, MSDU_RATE_MODE_AUTO); + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + /* caution: access prStaRec only if true */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + /* 4.3.3.1 send unprotected deauth reason 6/7 */ + if (prStaRec->rPmfCfg.fgRxDeauthResp != TRUE) { + DBGLOG(RSN, INFO, + "Deauth Set MSDU_OPT_PROTECTED_FRAME\n"); + nicTxConfigPktOption(prMsduInfo, + MSDU_OPT_PROTECTED_FRAME, TRUE); + } + + prStaRec->rPmfCfg.fgRxDeauthResp = FALSE; + } +#endif + DBGLOG(SAA, INFO, "ucTxSeqNum=%d ucStaRecIndex=%d u2ReasonCode=%d\n", + prMsduInfo->ucTxSeqNum, prMsduInfo->ucStaRecIndex, u2ReasonCode); + + /* 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t authProcessRxDeauthFrame(IN struct SW_RFB *prSwRfb, + IN uint8_t aucBSSID[], + OUT uint16_t *pu2ReasonCode) +{ + struct WLAN_DEAUTH_FRAME *prDeauthFrame; + uint16_t u2RxReasonCode; + + if (!prSwRfb || !aucBSSID || !pu2ReasonCode) { + DBGLOG(SAA, WARN, "Invalid parameters, ignore pkt!\n"); + return WLAN_STATUS_FAILURE; + } + + /* 4 <1> locate the Deauthentication Frame. */ + prDeauthFrame = (struct WLAN_DEAUTH_FRAME *)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) { + DBGLOG(SAA, WARN, "Invalid Deauth packet length"); + 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t +authProcessRxAuth1Frame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint8_t aucExpectedBSSID[], + IN uint16_t u2ExpectedAuthAlgNum, + IN uint16_t u2ExpectedTransSeqNum, + OUT uint16_t *pu2ReturnStatusCode) +{ + struct WLAN_AUTH_FRAME *prAuthFrame; + uint16_t u2ReturnStatusCode = STATUS_CODE_SUCCESSFUL; + + /* 4 <1> locate the Authentication Frame. */ + prAuthFrame = (struct WLAN_AUTH_FRAME *)prSwRfb->pvHeader; + + /* 4 <2> Check the BSSID */ + if (UNEQUAL_MAC_ADDR(prAuthFrame->aucBSSID, aucExpectedBSSID)) + return WLAN_STATUS_FAILURE; /* Just Ignore this MMPDU */ + + /* 4 <3> Check the SA, which should not be MC/BC */ + if (prAuthFrame->aucSrcAddr[0] & BIT(0)) { + DBGLOG(P2P, WARN, + "Invalid STA MAC with MC/BC bit set: " MACSTR "\n", + MAC2STR(prAuthFrame->aucSrcAddr)); + return WLAN_STATUS_FAILURE; + } + + /* 4 <4> Parse the Fixed Fields of Authentication Frame Body. */ + if (prAuthFrame->u2AuthAlgNum != u2ExpectedAuthAlgNum) + u2ReturnStatusCode = STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED; + + if (prAuthFrame->u2AuthTransSeqNo != u2ExpectedTransSeqNum) + u2ReturnStatusCode = STATUS_CODE_AUTH_OUT_OF_SEQ; + + *pu2ReturnStatusCode = u2ReturnStatusCode; + + return WLAN_STATUS_SUCCESS; + +} /* end of authProcessRxAuth1Frame() */ + +uint32_t +authProcessRxAuthFrame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN struct BSS_INFO *prBssInfo, + OUT uint16_t *pu2ReturnStatusCode) +{ + struct WLAN_AUTH_FRAME *prAuthFrame; + uint16_t u2ReturnStatusCode = STATUS_CODE_SUCCESSFUL; + + if (!prBssInfo) + return WLAN_STATUS_FAILURE; + + /* 4 <1> locate the Authentication Frame. */ + prAuthFrame = (struct WLAN_AUTH_FRAME *)prSwRfb->pvHeader; + + /* 4 <2> Check the BSSID */ + if (UNEQUAL_MAC_ADDR(prAuthFrame->aucBSSID, + prBssInfo->aucBSSID)) + return WLAN_STATUS_FAILURE; /* Just Ignore this MMPDU */ + + /* 4 <3> Check the SA, which should not be MC/BC */ + if (prAuthFrame->aucSrcAddr[0] & BIT(0)) { + DBGLOG(P2P, WARN, + "Invalid STA MAC with MC/BC bit set: " MACSTR "\n", + MAC2STR(prAuthFrame->aucSrcAddr)); + return WLAN_STATUS_FAILURE; + } + + /* 4 <4> Parse the Fixed Fields of Authentication Frame Body. */ + if (prAuthFrame->u2AuthAlgNum != AUTH_ALGORITHM_NUM_OPEN_SYSTEM && + prAuthFrame->u2AuthAlgNum != AUTH_ALGORITHM_NUM_SAE) + u2ReturnStatusCode = STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED; + else if (prAuthFrame->u2AuthAlgNum == AUTH_ALGORITHM_NUM_OPEN_SYSTEM && + prAuthFrame->u2AuthTransSeqNo != AUTH_TRANSACTION_SEQ_1) + u2ReturnStatusCode = STATUS_CODE_AUTH_OUT_OF_SEQ; + else if (prAuthFrame->u2AuthAlgNum == AUTH_ALGORITHM_NUM_SAE && + prAuthFrame->u2AuthTransSeqNo != AUTH_TRANSACTION_SEQ_1 && + prAuthFrame->u2AuthTransSeqNo != AUTH_TRANSACTION_SEQ_2) + u2ReturnStatusCode = STATUS_CODE_AUTH_OUT_OF_SEQ; + + DBGLOG(AAA, LOUD, "u2ReturnStatusCode = %d\n", u2ReturnStatusCode); + + *pu2ReturnStatusCode = u2ReturnStatusCode; + + return WLAN_STATUS_SUCCESS; + +} + +/* ToDo: authAddRicIE, authHandleFtIEs, authAddTimeoutIE */ + +void authAddMDIE(IN struct ADAPTER *prAdapter, + IN OUT struct MSDU_INFO *prMsduInfo) +{ + uint8_t *pucBuffer = + (uint8_t *)prMsduInfo->prPacket + prMsduInfo->u2FrameLength; + uint8_t ucBssIdx = prMsduInfo->ucBssIndex; + struct FT_IES *prFtIEs = aisGetFtIe(prAdapter, ucBssIdx); + + if (!prFtIEs->prMDIE || + !rsnIsFtOverTheAir(prAdapter, ucBssIdx, prMsduInfo->ucStaRecIndex)) + return; + prMsduInfo->u2FrameLength += + 5; /* IE size for MD IE is fixed, it is 5 */ + kalMemCopy(pucBuffer, prFtIEs->prMDIE, 5); +} + +uint32_t authCalculateRSNIELen(struct ADAPTER *prAdapter, uint8_t ucBssIdx, + struct STA_RECORD *prStaRec) +{ + struct FT_IES *prFtIEs = aisGetFtIe(prAdapter, ucBssIdx); + + if (!prFtIEs->prRsnIE || + !rsnIsFtOverTheAir(prAdapter, ucBssIdx, prStaRec->ucIndex)) + return 0; + return IE_SIZE(prFtIEs->prRsnIE); +} + +void authAddRSNIE(IN struct ADAPTER *prAdapter, + IN OUT struct MSDU_INFO *prMsduInfo) +{ + authAddRSNIE_impl(prAdapter, prMsduInfo); +} + +uint32_t authAddRSNIE_impl(IN struct ADAPTER *prAdapter, + IN OUT struct MSDU_INFO *prMsduInfo) +{ + uint8_t *pucBuffer = + (uint8_t *)prMsduInfo->prPacket + prMsduInfo->u2FrameLength; + uint32_t ucRSNIeSize = 0; + uint8_t ucBssIdx = prMsduInfo->ucBssIndex; + struct FT_IES *prFtIEs = aisGetFtIe(prAdapter, ucBssIdx); + + if (!prFtIEs->prRsnIE || + !rsnIsFtOverTheAir(prAdapter, ucBssIdx, prMsduInfo->ucStaRecIndex)) + return FALSE; + + ucRSNIeSize = IE_SIZE(prFtIEs->prRsnIE); + prMsduInfo->u2FrameLength += ucRSNIeSize; + kalMemCopy(pucBuffer, prFtIEs->prRsnIE, ucRSNIeSize); + return TRUE; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/bss.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/bss.c new file mode 100644 index 0000000000000..4fc4fbd76327d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/bss.c @@ -0,0 +1,2588 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/bss.c#7 + */ + +/*! \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. + */ + +/****************************************************************************** + * C O M P I L E 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 + ****************************************************************************** + */ + +const uint8_t *apucNetworkType[NETWORK_TYPE_NUM] = { + (uint8_t *) "AIS", + (uint8_t *) "P2P", + (uint8_t *) "BOW", + (uint8_t *) "MBSS" +}; + +const uint8_t *apucNetworkOpMode[] = { + (uint8_t *) "INFRASTRUCTURE", + (uint8_t *) "IBSS", + (uint8_t *) "ACCESS_POINT", + (uint8_t *) "P2P_DEVICE", + (uint8_t *) "BOW" +}; + +#if (CFG_SUPPORT_ADHOC) || (CFG_SUPPORT_AAA) +struct APPEND_VAR_IE_ENTRY txBcnIETable[] = { + {(ELEM_HDR_LEN + (RATE_NUM_SW - 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 */ + , {0, p2pFuncCalculateP2p_IELenForBeacon, + p2pFuncGenerateP2p_IEForBeacon} /* 221 */ + , {0, p2pFuncCalculateWSC_IELenForBeacon, + p2pFuncGenerateWSC_IEForBeacon} /* 221 */ + , {0, p2pFuncCalculateP2P_IE_NoA, + p2pFuncGenerateP2P_IE_NoA} /* 221 */ +#endif /* CFG_ENABLE_WIFI_DIRECT */ +#if CFG_SUPPORT_802_11AC + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP), NULL, + rlmRspGenerateVhtCapIE} /*191 */ + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP), NULL, + rlmRspGenerateVhtOpIE} /*192 */ + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP_MODE_NOTIFICATION), NULL, + rlmRspGenerateVhtOpNotificationIE} /*199 */ +#endif +#if CFG_SUPPORT_802_11AX + , {0, heRlmCalculateHeCapIELen, + heRlmRspGenerateHeCapIE} /* 255, EXT 35 */ + , {0, heRlmCalculateHeOpIELen, + heRlmRspGenerateHeOpIE} /* 255, EXT 36 */ +#endif +#if CFG_SUPPORT_MTK_SYNERGY + , {(ELEM_HDR_LEN + ELEM_MIN_LEN_MTK_OUI), NULL, + rlmGenerateMTKOuiIE} /* 221 */ +#endif +#if (CFG_SUPPORT_DFS_MASTER == 1) + , {(ELEM_HDR_LEN + ELEM_MIN_LEN_CSA), NULL, + rlmGenerateCsaIE} /* 37 */ +#endif + +}; + +struct APPEND_VAR_IE_ENTRY txProbRspIETable[] = { + {(ELEM_HDR_LEN + (RATE_NUM_SW - 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_WPA), NULL, + rsnGenerateWPAIE} /* 221 */ + , {(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 */ +#if CFG_SUPPORT_802_11AC + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP), NULL, + rlmRspGenerateVhtCapIE} /*191 */ + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP), NULL, + rlmRspGenerateVhtOpIE} /*192 */ + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP_MODE_NOTIFICATION), NULL, + rlmRspGenerateVhtOpNotificationIE} /*199 */ +#endif +#if CFG_SUPPORT_802_11AX + , {0, heRlmCalculateHeCapIELen, + heRlmRspGenerateHeCapIE} /* 255, EXT 35 */ + , {0, heRlmCalculateHeOpIELen, + heRlmRspGenerateHeOpIE} /* 255, EXT 36 */ +#endif +#if CFG_SUPPORT_MTK_SYNERGY + , {(ELEM_HDR_LEN + ELEM_MIN_LEN_MTK_OUI), NULL, + rlmGenerateMTKOuiIE} /* 221 */ +#endif + +}; + +#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 decide PHY type set of STA_RECORD_T by given + * BSS_DESC_T for Infrastructure or AdHoc Mode. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] prBssDesc Received Beacon/ProbeResp from this STA + * @param[out] prStaRec StaRec to be decided PHY type set + * + * @retval VOID + */ +/*---------------------------------------------------------------------------*/ +void bssDetermineStaRecPhyTypeSet(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc, + OUT struct STA_RECORD *prStaRec) +{ + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; + uint8_t ucHtOption = FEATURE_ENABLED; + uint8_t ucVhtOption = FEATURE_ENABLED; + struct BSS_INFO *prBssInfo; +#if (CFG_SUPPORT_802_11AX == 1) + uint8_t ucHeOption = FEATURE_ENABLED; +#endif + + prStaRec->ucPhyTypeSet = prBssDesc->ucPhyTypeSet; +#if CFG_SUPPORT_BFEE + prStaRec->ucVhtCapNumSoundingDimensions = + prBssDesc->ucVhtCapNumSoundingDimensions; +#endif + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + /* Decide AIS PHY type set */ + if (prStaRec->eStaType == STA_TYPE_LEGACY_AP) { + struct CONNECTION_SETTINGS *prConnSettings; + enum ENUM_WEP_STATUS eEncStatus; + + prConnSettings = + aisGetConnSettings(prAdapter, prStaRec->ucBssIndex); + + eEncStatus = prConnSettings->eEncStatus; + + if (!(eEncStatus == ENUM_ENCRYPTION3_ENABLED || + eEncStatus == ENUM_ENCRYPTION3_KEY_ABSENT || + eEncStatus == ENUM_ENCRYPTION_DISABLED || + eEncStatus == ENUM_ENCRYPTION4_ENABLED || + eEncStatus == ENUM_ENCRYPTION4_KEY_ABSENT + )) { + DBGLOG(BSS, INFO, + "Ignore the HT/VHT Bit for TKIP as pairwise cipher configed!\n"); + prStaRec->ucPhyTypeSet &= + ~(PHY_TYPE_BIT_HT | PHY_TYPE_BIT_VHT); +#if (CFG_SUPPORT_802_11AX == 1) + prStaRec->ucPhyTypeSet &= ~(PHY_TYPE_BIT_HE); +#endif + } + + ucHtOption = prWifiVar->ucStaHt; + ucVhtOption = prWifiVar->ucStaVht; +#if (CFG_SUPPORT_802_11AX == 1) + if (fgEfuseCtrlAxOn == 1) + ucHeOption = prWifiVar->ucStaHe; +#endif + + } + /* Decide P2P GC PHY type set */ + else if (prStaRec->eStaType == STA_TYPE_P2P_GO) { + ucHtOption = prWifiVar->ucP2pGcHt; + ucVhtOption = prWifiVar->ucP2pGcVht; +#if (CFG_SUPPORT_802_11AX == 1) + ucHeOption = prWifiVar->ucP2pGcHe; +#endif + + } + + /* Set HT/VHT capability from Feature Option */ + if (IS_FEATURE_DISABLED(ucHtOption)) + prStaRec->ucPhyTypeSet &= ~PHY_TYPE_BIT_HT; + else if (IS_FEATURE_FORCE_ENABLED(ucHtOption)) + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HT; + + if (IS_FEATURE_DISABLED(ucVhtOption)) + prStaRec->ucPhyTypeSet &= ~PHY_TYPE_BIT_VHT; + else if (IS_FEATURE_FORCE_ENABLED(ucVhtOption)) + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_VHT; + else if (prBssInfo->eBand == BAND_2G4 && + IS_FEATURE_DISABLED(prWifiVar->ucVhtIeIn2g)) { + prStaRec->ucPhyTypeSet &= ~PHY_TYPE_BIT_VHT; + } + +#if (CFG_SUPPORT_802_11AX == 1) + if (fgEfuseCtrlAxOn == 1) { + if (IS_FEATURE_DISABLED(ucHeOption)) + prStaRec->ucPhyTypeSet &= ~PHY_TYPE_BIT_HE; + else if (IS_FEATURE_FORCE_ENABLED(ucHeOption)) + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HE; + } +#endif + + prStaRec->ucDesiredPhyTypeSet = + prStaRec->ucPhyTypeSet & prAdapter->rWifiVar.ucAvailablePhyTypeSet; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will decide PHY type set of BSS_INFO for + * AP Mode. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] fgIsApMode Legacy AP mode or P2P GO + * @param[out] prBssInfo BssInfo to be decided PHY type set + * + * @retval VOID + */ +/*----------------------------------------------------------------------------*/ +void bssDetermineApBssInfoPhyTypeSet(IN struct ADAPTER *prAdapter, + IN u_int8_t fgIsPureAp, + OUT struct BSS_INFO *prBssInfo) +{ + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; + uint8_t ucHtOption = FEATURE_ENABLED; + uint8_t ucVhtOption = FEATURE_ENABLED; +#if (CFG_SUPPORT_802_11AX == 1) + uint8_t ucHeOption = FEATURE_ENABLED; +#endif + + /* Decide AP mode PHY type set */ + if (fgIsPureAp) { + ucHtOption = prWifiVar->ucApHt; + ucVhtOption = prWifiVar->ucApVht; +#if (CFG_SUPPORT_802_11AX == 1) + ucHeOption = prWifiVar->ucApHe; +#endif + } + /* Decide P2P GO PHY type set */ + else { + ucHtOption = prWifiVar->ucP2pGoHt; + ucVhtOption = prWifiVar->ucP2pGoVht; +#if (CFG_SUPPORT_802_11AX == 1) + ucHeOption = prWifiVar->ucP2pGoHe; +#endif + } + + /* Set HT/VHT capability from Feature Option */ + if (IS_FEATURE_DISABLED(ucHtOption)) + prBssInfo->ucPhyTypeSet &= ~PHY_TYPE_BIT_HT; + else if (IS_FEATURE_FORCE_ENABLED(ucHtOption)) + prBssInfo->ucPhyTypeSet |= PHY_TYPE_BIT_HT; + else if (!fgIsPureAp && IS_FEATURE_ENABLED(ucHtOption)) + prBssInfo->ucPhyTypeSet |= PHY_TYPE_BIT_HT; + + if (IS_FEATURE_DISABLED(ucVhtOption)) { + prBssInfo->ucPhyTypeSet &= ~PHY_TYPE_BIT_VHT; + } else if (IS_FEATURE_FORCE_ENABLED(ucVhtOption)) { + prBssInfo->ucPhyTypeSet |= PHY_TYPE_BIT_VHT; + } else if (IS_FEATURE_ENABLED(ucVhtOption) && + prBssInfo->eBand == BAND_2G4 && + prWifiVar->ucVhtIeIn2g && + (prBssInfo->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) { + prBssInfo->ucPhyTypeSet |= PHY_TYPE_BIT_VHT; + } else if (!fgIsPureAp && + IS_FEATURE_ENABLED(ucVhtOption) && + (prBssInfo->eBand == BAND_5G)) { + prBssInfo->ucPhyTypeSet |= PHY_TYPE_BIT_VHT; + } + +#if (CFG_SUPPORT_802_11AX == 1) + if (IS_FEATURE_DISABLED(ucHeOption)) + prBssInfo->ucPhyTypeSet &= ~PHY_TYPE_BIT_HE; + else if (IS_FEATURE_FORCE_ENABLED(ucHeOption)) + prBssInfo->ucPhyTypeSet |= PHY_TYPE_BIT_HE; + else if (!fgIsPureAp && IS_FEATURE_ENABLED(ucHeOption)) + prBssInfo->ucPhyTypeSet |= PHY_TYPE_BIT_HE; +#endif + + prBssInfo->ucPhyTypeSet &= prAdapter->rWifiVar.ucAvailablePhyTypeSet; + +} + +/*---------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*---------------------------------------------------------------------------*/ +struct STA_RECORD *bssCreateStaRecFromBssDesc(IN struct ADAPTER *prAdapter, + IN enum ENUM_STA_TYPE eStaType, + IN uint8_t ucBssIndex, + IN struct BSS_DESC *prBssDesc) +{ + struct STA_RECORD *prStaRec; + uint8_t ucNonHTPhyTypeSet; + struct CONNECTION_SETTINGS *prConnSettings; + + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + + /* 4 <1> Get a valid STA_RECORD_T */ + prStaRec = + cnmGetStaRecByAddress(prAdapter, ucBssIndex, prBssDesc->aucSrcAddr); + if (!prStaRec) { + prStaRec = + cnmStaRecAlloc(prAdapter, eStaType, ucBssIndex, + prBssDesc->aucSrcAddr); + + if (!prStaRec) { + DBGLOG(BSS, WARN, + "STA_REC entry is full, cannot acquire new entry for [" + MACSTR "]!!\n", MAC2STR(prBssDesc->aucSrcAddr)); + return NULL; + } + + prStaRec->ucStaState = STA_STATE_1; + prStaRec->ucJoinFailureCount = 0; + /* TODO(Kevin): If this is an old entry, + * we may also reset the ucJoinFailureCount to 0. + */ + } + /* 4 <2> Update information from BSS_DESC_T to current P_STA_RECORD_T */ + prStaRec->u2CapInfo = prBssDesc->u2CapInfo; + + prStaRec->u2OperationalRateSet = prBssDesc->u2OperationalRateSet; + prStaRec->u2BSSBasicRateSet = prBssDesc->u2BSSBasicRateSet; + +#if 1 + bssDetermineStaRecPhyTypeSet(prAdapter, prBssDesc, prStaRec); +#else + prStaRec->ucPhyTypeSet = prBssDesc->ucPhyTypeSet; + + if (IS_STA_IN_AIS(prStaRec)) { + if (! + ((prConnSettings->eEncStatus == + ENUM_ENCRYPTION3_ENABLED) + || (prConnSettings->eEncStatus == + ENUM_ENCRYPTION3_KEY_ABSENT) + || (prConnSettings->eEncStatus == + ENUM_ENCRYPTION_DISABLED) + || (prAdapter->prGlueInfo->u2WSCAssocInfoIELen) +#if CFG_SUPPORT_WAPI + || (prAdapter->prGlueInfo->u2WapiAssocInfoIESz) +#endif +)) { + 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; +#endif + + 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 */ + { + /* 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 */ + prStaRec->u2DesiredNonHTRateSet = + (prStaRec-> + u2OperationalRateSet & prConnSettings->u2DesiredNonHTRateSet); + + /* 4 <3> 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 struct BSS_DESC + */ + if (prBssDesc->ucDTIMPeriod) + prStaRec->ucDTIMPeriod = prBssDesc->ucDTIMPeriod; + else + prStaRec->ucDTIMPeriod = 0; + /* Means that TIM was not parsed. */ + + } + /* 4 <4> Update default value */ + prStaRec->fgDiagnoseConnection = FALSE; + + /* 4 <5> Update default value for other Modules */ + /* Determine WMM related parameters for STA_REC */ + mqmProcessScanResult(prAdapter, prBssDesc, prStaRec); + + /* 4 <6> Update Tx Rate */ + /* Update default Tx rate */ + nicTxUpdateStaRecDefaultRate(prAdapter, 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 struct ADAPTER *prAdapter, IN uint8_t *pucBuffer, + IN struct STA_RECORD *prStaRec) +{ + struct WLAN_MAC_HEADER *prNullFrame; + struct BSS_INFO *prBssInfo; + uint16_t u2FrameCtrl; + uint8_t ucBssIndex; + + ucBssIndex = prStaRec->ucBssIndex; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + prNullFrame = (struct WLAN_MAC_HEADER *)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 struct ADAPTER *prAdapter, + IN uint8_t *pucBuffer, IN struct STA_RECORD *prStaRec, + IN uint8_t ucUP, IN u_int8_t fgSetEOSP) +{ + struct WLAN_MAC_HEADER_QOS *prQoSNullFrame; + struct BSS_INFO *prBssInfo; + uint16_t u2FrameCtrl; + uint16_t u2QosControl; + uint8_t ucBssIndex; + + ucBssIndex = prStaRec->ucBssIndex; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + prQoSNullFrame = (struct WLAN_MAC_HEADER_QOS *)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 = (uint16_t) (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. + */ +/*---------------------------------------------------------------------------*/ +uint32_t +bssSendNullFrame(IN struct ADAPTER *prAdapter, IN struct STA_RECORD *prStaRec, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + struct MSDU_INFO *prMsduInfo; + uint16_t u2EstimatedFrameLen; + + /* 4 <1> Allocate a PKT_INFO_T for Null Frame */ + /* Init with MGMT Header Length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + WLAN_MAC_HEADER_LEN; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(BSS, WARN, "No PKT_INFO_T for sending Null Frame.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Null frame in MSDU_INfO_T. */ + bssComposeNullFrame(prAdapter, + (uint8_t *) ((unsigned long)prMsduInfo->prPacket + + MAC_TX_RESERVED_FIELD), prStaRec); + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_HEADER_LEN, + WLAN_MAC_HEADER_LEN, pfTxDoneHandler, MSDU_RATE_MODE_AUTO); + + /* 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. + */ +/*---------------------------------------------------------------------------*/ +uint32_t +bssSendQoSNullFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, IN uint8_t ucUP, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + struct MSDU_INFO *prMsduInfo; + uint16_t u2EstimatedFrameLen; + + /* 4 <1> Allocate a PKT_INFO_T for Null Frame */ + /* Init with MGMT Header Length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + WLAN_MAC_HEADER_QOS_LEN; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(BSS, WARN, "No PKT_INFO_T for sending Null Frame.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Null frame in MSDU_INfO_T. */ + bssComposeQoSNullFrame(prAdapter, + (uint8_t + *) ((unsigned long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD), prStaRec, ucUP, + FALSE); + + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_HEADER_QOS_LEN, WLAN_MAC_HEADER_QOS_LEN, + pfTxDoneHandler, MSDU_RATE_MODE_AUTO); + + /* 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 struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + uint8_t *pucBuffer; + uint8_t ucExtSupRatesLen; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + pucBuffer = + (uint8_t *) ((unsigned long)prMsduInfo->prPacket + + (unsigned long)prMsduInfo->u2FrameLength); + + if (prBssInfo->ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) + + ucExtSupRatesLen = + prBssInfo->ucAllSupportedRatesLen - ELEM_MAX_LEN_SUP_RATES; + else + ucExtSupRatesLen = 0; + + /* Fill the Extended Supported Rates element. */ + if (ucExtSupRatesLen) { + + EXT_SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_EXTENDED_SUP_RATES; + EXT_SUP_RATES_IE(pucBuffer)->ucLength = ucExtSupRatesLen; + + kalMemCopy(EXT_SUP_RATES_IE(pucBuffer)->aucExtSupportedRates, + &prBssInfo->aucAllSupportedRates + [ELEM_MAX_LEN_SUP_RATES], ucExtSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + } +} /* end of bssGenerateExtSuppRate_IE() */ + +/*---------------------------------------------------------------------------*/ +/*! + * @brief This function is used to compose Common Information Elements for + * Beacon or Probe Response Frame. + * + * @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. + * @param[in] prBssInfo Pointer to the BSS_INFO_T. + * @param[in] pucDestAddr Pointer to the Destination Address, + * if NULL, means Beacon. + * + * @return (none) + */ +/*---------------------------------------------------------------------------*/ +void +bssBuildBeaconProbeRespFrameCommonIEs(IN struct MSDU_INFO *prMsduInfo, + IN struct BSS_INFO *prBssInfo, + IN uint8_t *pucDestAddr) +{ + uint8_t *pucBuffer; + uint8_t ucSupRatesLen; + + pucBuffer = + (uint8_t *) ((unsigned long)prMsduInfo->prPacket + + (unsigned long)prMsduInfo->u2FrameLength); + /* 4 <1> Fill the SSID element. */ + SSID_IE(pucBuffer)->ucId = ELEM_ID_SSID; + + if ((!pucDestAddr) + && (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { + /* For Beacon */ + if (prBssInfo->eHiddenSsidType == + ENUM_HIDDEN_SSID_ZERO_CONTENT) { + /* clear the data, but keep the correct + * length of the SSID + */ + SSID_IE(pucBuffer)->ucLength = prBssInfo->ucSSIDLen; + kalMemZero(SSID_IE(pucBuffer)->aucSSID, + prBssInfo->ucSSIDLen); + } else if (prBssInfo->eHiddenSsidType == + ENUM_HIDDEN_SSID_ZERO_LEN) { + /* empty SSID */ + SSID_IE(pucBuffer)->ucLength = 0; + } else { + SSID_IE(pucBuffer)->ucLength = prBssInfo->ucSSIDLen; + if (prBssInfo->ucSSIDLen) + kalMemCopy(SSID_IE(pucBuffer)->aucSSID, + prBssInfo->aucSSID, + prBssInfo->ucSSIDLen); + } + } else { /* Probe response */ + 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->eNetworkType == NETWORK_TYPE_P2P) { + /* IEEE 802.11 2007 - 7.3.2.6 */ + TIM_IE(pucBuffer)->ucId = ELEM_ID_TIM; + /* NOTE: fixed PVB length + * (AID is allocated from 8 ~ 15 only) + */ + TIM_IE(pucBuffer)->ucLength = + (3 + + MAX_LEN_TIM_PARTIAL_BMP) /*((u4N2 - u4N1) + 4) */; + TIM_IE(pucBuffer)->ucDTIMCount = + 0 /*prBssInfo->ucDTIMCount */; + /* will be overwritten by FW */ + TIM_IE(pucBuffer)->ucDTIMPeriod = + prBssInfo->ucDTIMPeriod; + /* will be overwritten by FW */ + TIM_IE(pucBuffer)->ucBitmapControl = + 0 /*ucBitmapControl | (uint8_t)u4N1 */; + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } else +#endif /* CFG_ENABLE_WIFI_DIRECT */ + { + /* NOTE(Kevin): 1. AIS - Didn't Support AP Mode. + * 2. BOW - Didn't Support BCAST and PS. + */ + } + } + + /* 4 <6> Fill the DS Parameter Set element. */ + if (prBssInfo->ucCountryIELen != 0) { + COUNTRY_IE(pucBuffer)->ucId = ELEM_ID_COUNTRY_INFO; + COUNTRY_IE(pucBuffer)->ucLength = prBssInfo->ucCountryIELen; + COUNTRY_IE(pucBuffer)->aucCountryStr[0] = + prBssInfo->aucCountryStr[0]; + COUNTRY_IE(pucBuffer)->aucCountryStr[1] = + prBssInfo->aucCountryStr[1]; + COUNTRY_IE(pucBuffer)->aucCountryStr[2] = + prBssInfo->aucCountryStr[2]; + kalMemCopy(COUNTRY_IE(pucBuffer)->arCountryStr, + prBssInfo->aucSubbandTriplet, + prBssInfo->ucCountryIELen - 3); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + } +} /* 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 uint8_t *pucBuffer, + IN uint8_t *pucDestAddr, + IN uint8_t *pucOwnMACAddress, + IN uint8_t *pucBSSID, + IN uint16_t u2BeaconInterval, + IN uint16_t u2CapInfo) +{ + struct WLAN_BEACON_FRAME *prBcnProbRspFrame; + uint8_t aucBCAddr[] = BC_MAC_ADDR; + uint16_t u2FrameCtrl; + + DEBUGFUNC("bssComposeBeaconProbeRespFrameHeaderAndFF"); + /* DBGLOG(INIT, LOUD, ("\n")); */ + + prBcnProbRspFrame = (struct WLAN_BEACON_FRAME *)pucBuffer; + + /* 4 <1> Compose the frame header of the Beacon /ProbeResp frame. */ + /* Fill the Frame Control field. */ + if (pucDestAddr) { + u2FrameCtrl = MAC_FRAME_PROBE_RSP; + } else { + u2FrameCtrl = MAC_FRAME_BEACON; + pucDestAddr = aucBCAddr; + } + /* WLAN_SET_FIELD_16(&prBcnProbRspFrame->u2FrameCtrl, u2FrameCtrl); */ + prBcnProbRspFrame->u2FrameCtrl = u2FrameCtrl; + /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the DA field with BCAST MAC ADDR or TA of ProbeReq. */ + COPY_MAC_ADDR(prBcnProbRspFrame->aucDestAddr, pucDestAddr); + + /* Fill the SA field with our MAC Address. */ + COPY_MAC_ADDR(prBcnProbRspFrame->aucSrcAddr, pucOwnMACAddress); + + /* Fill the BSSID field with current BSSID. */ + COPY_MAC_ADDR(prBcnProbRspFrame->aucBSSID, pucBSSID); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, + * so we need to clear it). + */ + prBcnProbRspFrame->u2SeqCtrl = 0; + + /* 4 <2> Compose the frame body's common fixed field part of the Beacon + * / ProbeResp frame. + */ + /* MAC will update TimeStamp field */ + + /* Fill the Beacon Interval field. */ + /* WLAN_SET_FIELD_16(&prBcnProbRspFrame->u2BeaconInterval, + * u2BeaconInterval); + */ + prBcnProbRspFrame->u2BeaconInterval = u2BeaconInterval; + /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the Capability Information field. */ + /* WLAN_SET_FIELD_16(&prBcnProbRspFrame->u2CapInfo, u2CapInfo); */ + prBcnProbRspFrame->u2CapInfo = u2CapInfo; + /* NOTE(Kevin): Optimized for ARM */ +} /* end of bssComposeBeaconProbeRespFrameHeaderAndFF() */ + +/*---------------------------------------------------------------------------*/ +/*! + * @brief Update the Beacon Frame Template to FW for AIS AdHoc and P2P GO. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] ucBssIndex Specify which network reply the Probe Response. + * + * @retval WLAN_STATUS_SUCCESS Success. + */ +/*---------------------------------------------------------------------------*/ +uint32_t bssUpdateBeaconContent(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + struct BSS_INFO *prBssInfo; + struct MSDU_INFO *prMsduInfo; + struct WLAN_BEACON_FRAME *prBcnFrame; + uint32_t i; + + DEBUGFUNC("bssUpdateBeaconContent"); + DBGLOG(INIT, LOUD, "\n"); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + /* 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((uint8_t *) + ((unsigned + long)(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->ucBssIndex = ucBssIndex; + + /* 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(struct APPEND_VAR_IE_ENTRY); + i++) { + if (txBcnIETable[i].pfnAppendIE) + txBcnIETable[i].pfnAppendIE(prAdapter, prMsduInfo); + + } + + prBcnFrame = (struct WLAN_BEACON_FRAME *)prMsduInfo->prPacket; + + DBGLOG(P2P, TRACE, "Dump beacon content to FW.\n"); + if (aucDebugModule[DBG_P2P_IDX] & DBG_CLASS_TRACE) { + dumpMemory8((uint8_t *) prMsduInfo->prPacket, + (uint32_t) prMsduInfo->u2FrameLength); + } + + return nicUpdateBeaconIETemplate(prAdapter, + IE_UPD_METHOD_UPDATE_ALL, + ucBssIndex, + prBssInfo->u2CapInfo, + (uint8_t *) prBcnFrame->aucInfoElem, + prMsduInfo->u2FrameLength - + OFFSET_OF(struct WLAN_BEACON_FRAME, + 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] ucBssIndex 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t +bssSendBeaconProbeResponse(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN uint8_t *pucDestAddr, + IN uint32_t u4ControlFlags) +{ + struct BSS_INFO *prBssInfo; + struct MSDU_INFO *prMsduInfo; + uint16_t u2EstimatedFrameLen; + uint16_t u2EstimatedFixedIELen; + uint16_t u2EstimatedExtraIELen; + struct APPEND_VAR_IE_ENTRY *prIeArray = NULL; + uint32_t u4IeArraySize = 0; + uint32_t i; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (!pucDestAddr) { /* For Beacon */ + prIeArray = &txBcnIETable[0]; + u4IeArraySize = + sizeof(txBcnIETable) / sizeof(struct APPEND_VAR_IE_ENTRY); + } else { + prIeArray = &txProbRspIETable[0]; + u4IeArraySize = + sizeof(txProbRspIETable) / + sizeof(struct APPEND_VAR_IE_ENTRY); + } + + /* 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 += (uint16_t) + prIeArray[i].pfnCalculateVariableIELen(prAdapter, + ucBssIndex, + NULL); + } + } + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(BSS, WARN, "No PKT_INFO_T for sending %s.\n", + ((!pucDestAddr) ? "Beacon" : "Probe Response")); + return WLAN_STATUS_RESOURCES; + } + + /* 4 <2> Compose Beacon/Probe Response frame header + * and fixed fields in MSDU_INfO_T. + */ + /* Compose Header and Fixed Field */ +#if CFG_ENABLE_WIFI_DIRECT + if (u4ControlFlags & BSS_PROBE_RESP_USE_P2P_DEV_ADDR) { + if (prAdapter->fgIsP2PRegistered) { + bssComposeBeaconProbeRespFrameHeaderAndFF((uint8_t *) + ((unsigned long) + (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((uint8_t *) + ((unsigned long) + (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + pucDestAddr, prBssInfo->aucOwnMacAddr, + prBssInfo->aucBSSID, + prBssInfo->u2BeaconInterval, prBssInfo->u2CapInfo); + } + + /* 4 <3> Update information of MSDU_INFO_T */ + + TX_SET_MMPDU(prAdapter, + prMsduInfo, + ucBssIndex, + STA_REC_INDEX_NOT_FOUND, + WLAN_MAC_MGMT_HEADER_LEN, + (WLAN_MAC_MGMT_HEADER_LEN + TIMESTAMP_FIELD_LEN + + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN), NULL, + MSDU_RATE_MODE_AUTO); + + /* 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); + + } + + /* Set limited retry count and lifetime for Probe Resp is reasonable */ + nicTxSetPktLifeTime(prMsduInfo, 100); + nicTxSetPktRetryLimit(prMsduInfo, 2); + + /* 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t bssProcessProbeRequest(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct WLAN_MAC_MGMT_HEADER *prMgtHdr; + struct BSS_INFO *prBssInfo; + uint8_t ucBssIndex; + uint8_t aucBCBSSID[] = BC_BSSID; + u_int8_t fgIsBcBssid; + u_int8_t fgReplyProbeResp; + uint32_t u4CtrlFlagsForProbeResp = 0; + enum ENUM_BAND eBand = 0; + uint8_t ucHwChannelNum = 0; + struct RX_DESC_OPS_T *prRxDescOps; + + prRxDescOps = prAdapter->chip_info->prRxDescOps; + /* 4 <1> Parse Probe Req and Get BSSID */ + prMgtHdr = (struct WLAN_MAC_MGMT_HEADER *)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 (ucBssIndex = 0; ucBssIndex <= prAdapter->ucP2PDevBssIdx; + ucBssIndex++) { + + if (!IS_NET_ACTIVE(prAdapter, ucBssIndex)) + continue; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if ((!fgIsBcBssid) + && UNEQUAL_MAC_ADDR(prBssInfo->aucBSSID, + prMgtHdr->aucBSSID)) + continue; + + RX_STATUS_GET( + prRxDescOps, + eBand, + get_rf_band, + prSwRfb->prRxStatus); + + RX_STATUS_GET( + prRxDescOps, + ucHwChannelNum, + get_ch_num, + prSwRfb->prRxStatus); + + if (prBssInfo->eBand != eBand) + continue; + + if (prBssInfo->ucPrimaryChannel != ucHwChannelNum) + continue; + + fgReplyProbeResp = FALSE; + + if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) { + +#if CFG_SUPPORT_ADHOC + fgReplyProbeResp = + aisValidateProbeReq(prAdapter, prSwRfb, + ucBssIndex, + &u4CtrlFlagsForProbeResp); +#endif + } +#if CFG_ENABLE_WIFI_DIRECT + else if ((prAdapter->fgIsP2PRegistered) + && (prBssInfo->eNetworkType == NETWORK_TYPE_P2P)) { + + fgReplyProbeResp = + p2pFuncValidateProbeReq(prAdapter, prSwRfb, + &u4CtrlFlagsForProbeResp, + (prBssInfo->ucBssIndex == + prAdapter->ucP2PDevBssIdx), + (uint8_t) + prBssInfo->u4PrivateData); + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (prBssInfo->eNetworkType == NETWORK_TYPE_BOW) + fgReplyProbeResp = + bowValidateProbeReq(prAdapter, prSwRfb, + &u4CtrlFlagsForProbeResp); +#endif + + if (fgReplyProbeResp) { + if (nicTxGetFreeCmdCount(prAdapter) > + (CFG_TX_MAX_CMD_PKT_NUM / 2)) { + /* Resource margin is enough */ + bssSendBeaconProbeResponse(prAdapter, + ucBssIndex, + prMgtHdr->aucSrcAddr, + u4CtrlFlagsForProbeResp); + } + } + } + + return WLAN_STATUS_SUCCESS; + +} /* end of bssProcessProbeRequest() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is used to initialize 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 bssInitializeClientList(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo) +{ + struct LINK *prStaRecOfClientList; + + prStaRecOfClientList = &prBssInfo->rStaRecOfClientList; + + if (!LINK_IS_EMPTY(prStaRecOfClientList)) + LINK_INITIALIZE(prStaRecOfClientList); + + DBGLOG(BSS, INFO, "Init BSS[%u] Client List\n", prBssInfo->ucBssIndex); + + bssCheckClientList(prAdapter, prBssInfo); +} /* 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 bssAddClient(IN struct ADAPTER *prAdapter, IN struct BSS_INFO *prBssInfo, + IN struct STA_RECORD *prStaRec) +{ + struct LINK *prClientList; + struct STA_RECORD *prCurrStaRec; + + prClientList = &prBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH_ENTRY(prCurrStaRec, prClientList, rLinkEntry, + struct STA_RECORD) { + + if (!prCurrStaRec) + break; + + if (prCurrStaRec == prStaRec) { + DBGLOG(BSS, WARN, + "Current Client List already contains that struct STA_RECORD[" + MACSTR "]\n", MAC2STR(prStaRec->aucMacAddr)); + return; + } + } + + LINK_INSERT_TAIL(prClientList, &prStaRec->rLinkEntry); + + bssCheckClientList(prAdapter, prBssInfo); +} /* 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) + */ +/*----------------------------------------------------------------------------*/ +u_int8_t bssRemoveClient(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct STA_RECORD *prStaRec) +{ + struct LINK *prClientList; + struct STA_RECORD *prCurrStaRec; + + prClientList = &prBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH_ENTRY(prCurrStaRec, prClientList, rLinkEntry, + struct STA_RECORD) { + + /* Break to check client list */ + if (!prCurrStaRec) + break; + + if (prCurrStaRec == prStaRec) { + + LINK_REMOVE_KNOWN_ENTRY(prClientList, + &prStaRec->rLinkEntry); + + return TRUE; + } + } + + DBGLOG(BSS, INFO, + "Current Client List didn't contain that struct STA_RECORD[" + MACSTR "] before removing.\n", MAC2STR(prStaRec->aucMacAddr)); + + bssCheckClientList(prAdapter, prBssInfo); + + return FALSE; +} /* end of bssRemoveStaRecFromClientList() */ + +struct STA_RECORD *bssRemoveClientByMac(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN uint8_t *pucMac) +{ + struct LINK *prClientList; + struct STA_RECORD *prCurrStaRec; + + prClientList = &prBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH_ENTRY(prCurrStaRec, prClientList, rLinkEntry, + struct STA_RECORD) { + + if (!prCurrStaRec) + break; + + if (EQUAL_MAC_ADDR(prCurrStaRec->aucMacAddr, pucMac)) { + + LINK_REMOVE_KNOWN_ENTRY(prClientList, + &prCurrStaRec->rLinkEntry); + + return prCurrStaRec; + } + } + + DBGLOG(BSS, INFO, + "Current Client List didn't contain that struct STA_RECORD[" + MACSTR "] before removing.\n", MAC2STR(pucMac)); + + bssCheckClientList(prAdapter, prBssInfo); + + return NULL; +} + +struct STA_RECORD *bssGetClientByMac(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN uint8_t *pucMac) +{ + struct LINK *prClientList; + struct STA_RECORD *prCurrStaRec; + + prClientList = &prBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH_ENTRY(prCurrStaRec, prClientList, rLinkEntry, + struct STA_RECORD) { + + if (!prCurrStaRec) + break; + + if (EQUAL_MAC_ADDR(prCurrStaRec->aucMacAddr, pucMac)) + return prCurrStaRec; + } + + DBGLOG(BSS, INFO, + "Current Client List didn't contain that struct STA_RECORD[" + MACSTR "] before removing.\n", MAC2STR(pucMac)); + + bssCheckClientList(prAdapter, prBssInfo); + + return NULL; +} + +struct STA_RECORD *bssRemoveHeadClient(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo) +{ + struct LINK *prStaRecOfClientList; + struct STA_RECORD *prStaRec = NULL; + + prStaRecOfClientList = &prBssInfo->rStaRecOfClientList; + + if (!LINK_IS_EMPTY(prStaRecOfClientList)) + LINK_REMOVE_HEAD(prStaRecOfClientList, prStaRec, + struct STA_RECORD *); + + bssCheckClientList(prAdapter, prBssInfo); + + return prStaRec; +} + +uint32_t bssGetClientCount(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo) +{ + return prBssInfo->rStaRecOfClientList.u4NumElem; +} + +void bssDumpClientList(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo) +{ + struct LINK *prClientList; + struct STA_RECORD *prCurrStaRec; + uint8_t ucCount = 0; + + prClientList = &prBssInfo->rStaRecOfClientList; + + DBGLOG(SW4, INFO, "Dump BSS[%u] Client List NUM[%u]\n", + prBssInfo->ucBssIndex, prClientList->u4NumElem); + + LINK_FOR_EACH_ENTRY(prCurrStaRec, prClientList, rLinkEntry, + struct STA_RECORD) { + + if (!prCurrStaRec) { + DBGLOG(SW4, INFO, "[%2u] is NULL STA_REC\n", ucCount); + break; + } + DBGLOG(SW4, INFO, "[%2u] STA[%u] [" MACSTR "]\n", ucCount, + prCurrStaRec->ucIndex, + MAC2STR(prCurrStaRec->aucMacAddr)); + + ucCount++; + } +} + +void bssCheckClientList(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo) +{ + struct LINK *prClientList; + struct STA_RECORD *prCurrStaRec; + uint8_t ucCount = 0; + u_int8_t fgError = FALSE; + + prClientList = &prBssInfo->rStaRecOfClientList; + + /* Check MAX number */ + if (prClientList->u4NumElem > P2P_MAXIMUM_CLIENT_COUNT) { + DBGLOG(SW4, INFO, "BSS[%u] Client List NUM[%u] ERR\n", + prBssInfo->ucBssIndex, prClientList->u4NumElem); + + fgError = TRUE; + } + + /* Check default list status */ + if (prClientList->u4NumElem == 0) { + if ((void *)prClientList->prNext != (void *)prClientList) + fgError = TRUE; + if ((void *)prClientList->prPrev != (void *)prClientList) + fgError = TRUE; + + if (fgError) { + DBGLOG(SW4, INFO, + "BSS[%u] Client List PTR next/prev[%p/%p] ERR\n", + prBssInfo->ucBssIndex, prClientList->prNext, + prClientList->prPrev); + } + } + + /* Traverse list */ + LINK_FOR_EACH_ENTRY(prCurrStaRec, prClientList, rLinkEntry, + struct STA_RECORD) { + if (!prCurrStaRec) { + fgError = TRUE; + DBGLOG(SW4, INFO, "BSS[%u] Client List NULL PTR ERR\n", + prBssInfo->ucBssIndex); + + break; + } + + ucCount++; + } + + /* Check real count and list number */ + if (ucCount != prClientList->u4NumElem) { + DBGLOG(SW4, INFO, + "BSS[%u] Client List NUM[%u] REAL CNT[%u] ERR\n", + prBssInfo->ucBssIndex, prClientList->u4NumElem, ucCount); + + fgError = TRUE; + } + + if (fgError) + bssDumpClientList(prAdapter, prBssInfo); + +} + +#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 struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct BSS_DESC *prBssDesc, IN uint8_t ucRCPI) +{ + struct STA_RECORD *prStaRec = NULL; + + u_int8_t fgIsCheckCapability = FALSE; + u_int8_t fgIsCheckTSF = FALSE; + u_int8_t fgIsGoingMerging = FALSE; + u_int8_t fgIsSameBSSID; + + /* 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, + prBssInfo->ucBssIndex, + 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 { + 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) { + u_int8_t 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, + prBssInfo->ucBssIndex) + == 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) { + /* 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) { + struct MSG_AIS_IBSS_PEER_FOUND *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, + prBssInfo->ucBssIndex, + 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 = (struct MSG_AIS_IBSS_PEER_FOUND *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_AIS_IBSS_PEER_FOUND)); + + if (!prAisIbssPeerFoundMsg) { + DBGLOG(AIS, ERROR, "Can't send Merge Msg\n"); + return; + } + + prAisIbssPeerFoundMsg->rMsgHdr.eMsgId = MID_SCN_AIS_FOUND_IBSS; + prAisIbssPeerFoundMsg->ucBssIndex = + prBssInfo->ucBssIndex; + 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, + (struct MSG_HDR *)prAisIbssPeerFoundMsg, + MSG_SEND_METHOD_BUF); + + } +} /* end of ibssProcessMatchedBeacon() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will check the Capability for Ad-Hoc to decide + * if we are able to merge with(same capability). + * + * @param[in] prBSSDesc Pointer to the BSS Descriptor. + * + * @retval WLAN_STATUS_FAILURE Can't pass the check of Capability. + * @retval WLAN_STATUS_SUCCESS Pass the check of Capability. + */ +/*----------------------------------------------------------------------------*/ +uint32_t ibssCheckCapabilityForAdHocMode(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc, + IN uint8_t ucBssIndex) +{ + struct CONNECTION_SETTINGS *prConnSettings; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + + 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; + } + /* 4 <4> Check the Security setting. */ + if (!rsnPerformPolicySelection(prAdapter, prBssDesc, + ucBssIndex)) + break; + + 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 struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo) +{ + uint8_t aucBSSID[MAC_ADDR_LEN]; + uint16_t *pu2BSSID = (uint16_t *) &aucBSSID[0]; + uint32_t i; + + /* 4 <1> Setup PHY Attributes and Basic Rate Set/Operational Rate Set */ + prBssInfo->ucNonHTBasicPhyType = (uint8_t) + 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(uint16_t); i++) + pu2BSSID[i] = (uint16_t) (kalRandomNumber() & 0xFFFF); + + /* 7.1.3.3.3 - + * The individual/group bit of the address is set to 0. + */ + aucBSSID[0] &= ~0x01; + /* 7.1.3.3.3 - + * The universal/local bit of the address is set to 1. + */ + aucBSSID[0] |= 0x02; + + COPY_MAC_ADDR(prBssInfo->aucBSSID, aucBSSID); + } + + /* 4 <3> Setup Capability - Short Preamble */ + if (rNonHTPhyAttributes + [prBssInfo->ucNonHTBasicPhyType].fgIsShortPreambleOptionImplemented + && + /* Short Preamble Option Enable is TRUE */ + ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_SHORT) || + (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 */ + nicTxUpdateBssDefaultRate(prBssInfo); +} /* 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 struct ADAPTER *prAdapter, IN struct BSS_INFO *prBssInfo, + IN u_int8_t fgIsRateUpdate) +{ + struct AC_QUE_PARMS *prACQueParms; + + enum ENUM_WMM_ACI eAci; + + uint8_t auCWminLog2ForBcast[WMM_AC_INDEX_NUM] = { 4, 4, 3, 2 }; + uint8_t auCWmaxLog2ForBcast[WMM_AC_INDEX_NUM] = { 10, 10, 4, 3 }; + uint8_t auAifsForBcast[WMM_AC_INDEX_NUM] = { 3, 7, 2, 2 }; + /* If the AP is OFDM */ + uint8_t auTxopForBcast[WMM_AC_INDEX_NUM] = { 0, 0, 94, 47 }; + + uint8_t auCWminLog2[WMM_AC_INDEX_NUM] = { 4, 4, 3, 2 }; + uint8_t auCWmaxLog2[WMM_AC_INDEX_NUM] = { 6, 10, 4, 3 }; + uint8_t auAifs[WMM_AC_INDEX_NUM] = { 3, 7, 1, 1 }; + /* If the AP is OFDM */ + uint8_t auTxop[WMM_AC_INDEX_NUM] = { 0, 0, 94, 47 }; + + DEBUGFUNC("bssInitForAP"); + +#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 = (uint8_t) + 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 + && + /* Short Preamble Option Enable is TRUE */ + ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_SHORT) || + (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; +#ifdef CFG_SET_BCN_CAPINFO_BY_DRIVER + /* 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; +#endif + /* 4 <6> Find Lowest Basic Rate Index for default TX Rate of MMPDU */ + nicTxUpdateBssDefaultRate(prBssInfo); + + /* 4 <7> Fill the EDCA */ + + prACQueParms = prBssInfo->arACQueParmsForBcast; + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + + prACQueParms[eAci].ucIsACMSet = 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]; + + /* used to send WMM IE */ + prBssInfo->aucCWminLog2ForBcast[eAci] = + auCWminLog2ForBcast[eAci]; + prBssInfo->aucCWmaxLog2ForBcast[eAci] = + auCWmaxLog2ForBcast[eAci]; + } + + DBGLOG(BSS, INFO, + "Bcast: ACM[%d,%d,%d,%d] Aifsn[%d,%d,%d,%d] CWmin/max[%d/%d,%d/%d,%d/%d,%d/%d] TxopLimit[%d,%d,%d,%d]\n", + prACQueParms[0].ucIsACMSet, prACQueParms[1].ucIsACMSet, + prACQueParms[2].ucIsACMSet, prACQueParms[3].ucIsACMSet, + prACQueParms[0].u2Aifsn, prACQueParms[1].u2Aifsn, + prACQueParms[2].u2Aifsn, prACQueParms[3].u2Aifsn, + prACQueParms[0].u2CWmin, prACQueParms[0].u2CWmax, + prACQueParms[1].u2CWmin, prACQueParms[1].u2CWmax, + prACQueParms[2].u2CWmin, prACQueParms[2].u2CWmax, + prACQueParms[3].u2CWmin, prACQueParms[3].u2CWmax, + prACQueParms[0].u2TxopLimit, prACQueParms[1].u2TxopLimit, + prACQueParms[2].u2TxopLimit, prACQueParms[3].u2TxopLimit); + + prACQueParms = prBssInfo->arACQueParms; + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + + prACQueParms[eAci].ucIsACMSet = 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, + "ACM[%d,%d,%d,%d] Aifsn[%d,%d,%d,%d] CWmin/max[%d/%d,%d/%d,%d/%d,%d/%d] TxopLimit[%d,%d,%d,%d]\n", + prACQueParms[0].ucIsACMSet, prACQueParms[1].ucIsACMSet, + prACQueParms[2].ucIsACMSet, prACQueParms[3].ucIsACMSet, + prACQueParms[0].u2Aifsn, prACQueParms[1].u2Aifsn, + prACQueParms[2].u2Aifsn, prACQueParms[3].u2Aifsn, + prACQueParms[0].u2CWmin, prACQueParms[0].u2CWmax, + prACQueParms[1].u2CWmin, prACQueParms[1].u2CWmax, + prACQueParms[2].u2CWmin, prACQueParms[2].u2CWmax, + prACQueParms[3].u2CWmin, prACQueParms[3].u2CWmax, + prACQueParms[0].u2TxopLimit, prACQueParms[1].u2TxopLimit, + prACQueParms[2].u2TxopLimit, prACQueParms[3].u2TxopLimit); + + /* Note: Caller should update the EDCA setting to HW by + * nicQmUpdateWmmParms() it there is no AIS network + * Note: In E2, only 4 HW queues. + * The the Edca parameters should be folow by AIS network + * Note: In E3, 8 HW queues. + * the Wmm parameters should be updated to right queues + * according to BSS + */ +} /* end of bssInitForAP() */ + +#endif /* CFG_SUPPORT_AAA */ + +void bssCreateStaRecFromAuth(IN struct ADAPTER *prAdapter) +{ + +} + +void bssUpdateStaRecFromAssocReq(IN struct ADAPTER *prAdapter) +{ + +} + +void bssDumpBssInfo(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIndex) +{ + struct BSS_INFO *prBssInfo; + /* P_LINK_T prStaRecOfClientList = (P_LINK_T) NULL; */ + /* P_STA_RECORD_T prCurrStaRec = (P_STA_RECORD_T) NULL; */ + + if (ucBssIndex > prAdapter->ucHwBssIdNum) { + DBGLOG(SW4, INFO, "Invalid BssInfo index[%u], skip dump!\n", + ucBssIndex); + return; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (!prBssInfo) { + DBGLOG(SW4, INFO, "Invalid BssInfo index[%u], skip dump!\n", + ucBssIndex); + return; + } + + DBGLOG(SW4, INFO, "OWNMAC[" MACSTR "] BSSID[" MACSTR "] SSID[%s]\n", + MAC2STR(prBssInfo->aucOwnMacAddr), MAC2STR(prBssInfo->aucBSSID), + HIDE(prBssInfo->aucSSID)); + + if (prBssInfo->eNetworkType >= 0 + && prBssInfo->eNetworkType < NETWORK_TYPE_NUM + && prBssInfo->eCurrentOPMode >= 0 + && prBssInfo->eCurrentOPMode < OP_MODE_NUM) { + DBGLOG(SW4, INFO, + "BSS IDX[%u] Type[%s] OPMode[%s] ConnState[%u] Absent[%u]\n", + prBssInfo->ucBssIndex, + apucNetworkType[prBssInfo->eNetworkType], + apucNetworkOpMode[prBssInfo->eCurrentOPMode], + prBssInfo->eConnectionState, prBssInfo->fgIsNetAbsent); + } + + DBGLOG(SW4, INFO, + "Channel[%u] Band[%u] SCO[%u] Assoc40mBwAllowed[%u] 40mBwAllowed[%u]\n", + prBssInfo->ucPrimaryChannel, prBssInfo->eBand, + prBssInfo->eBssSCO, prBssInfo->fgAssoc40mBwAllowed, + prBssInfo->fg40mBwAllowed); + + DBGLOG(SW4, INFO, "MaxBw[%u] OpRxNss[%u] OpTxNss[%u]\n", + cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex), + prBssInfo->ucOpRxNss, prBssInfo->ucOpTxNss); + + DBGLOG(SW4, INFO, "QBSS[%u] CapInfo[0x%04x] AID[%u]\n", + prBssInfo->fgIsQBSS, prBssInfo->u2CapInfo, prBssInfo->u2AssocId); + + DBGLOG(SW4, INFO, + "ShortPreamble Allowed[%u] EN[%u], ShortSlotTime[%u]\n", + prBssInfo->fgIsShortPreambleAllowed, + prBssInfo->fgUseShortPreamble, prBssInfo->fgUseShortSlotTime); + + DBGLOG(SW4, INFO, "PhyTypeSet: Basic[0x%02x] NonHtBasic[0x%02x]\n", + prBssInfo->ucPhyTypeSet, prBssInfo->ucNonHTBasicPhyType); + + DBGLOG(SW4, INFO, "RateSet: BssBasic[0x%04x] Operational[0x%04x]\n", + prBssInfo->u2BSSBasicRateSet, prBssInfo->u2OperationalRateSet); + + DBGLOG(SW4, INFO, "ATIMWindow[%u] DTIM Period[%u] Count[%u]\n", + prBssInfo->u2ATIMWindow, prBssInfo->ucDTIMPeriod, + prBssInfo->ucDTIMCount); + + DBGLOG(SW4, INFO, + "HT Operation Info1[0x%02x] Info2[0x%04x] Info3[0x%04x]\n", + prBssInfo->ucHtOpInfo1, prBssInfo->u2HtOpInfo2, + prBssInfo->u2HtOpInfo3); + + DBGLOG(SW4, INFO, + "ProtectMode HT[%u] ERP[%u], OperationMode GF[%u] RIFS[%u]\n", + prBssInfo->eHtProtectMode, prBssInfo->fgErpProtectMode, + prBssInfo->eGfOperationMode, prBssInfo->eRifsOperationMode); + + DBGLOG(SW4, INFO, + "(OBSS) ProtectMode HT[%u] ERP[%u], OperationMode GF[%u] RIFS[%u]\n", + prBssInfo->eObssHtProtectMode, prBssInfo->fgObssErpProtectMode, + prBssInfo->eObssGfOperationMode, + prBssInfo->fgObssRifsOperationMode); + + DBGLOG(SW4, INFO, + "VhtChannelWidth[%u] OpChangeChannelWidth[%u], IsOpChangeChannelWidth[%u]\n", + prBssInfo->ucVhtChannelWidth, prBssInfo->ucOpChangeChannelWidth, + prBssInfo->fgIsOpChangeChannelWidth); + + DBGLOG(SW4, INFO, "======== Dump Connected Client ========\n"); + +#if 0 + DBGLOG(SW4, INFO, "NumOfClient[%u]\n", + bssGetClientCount(prAdapter, prBssInfo)); + + prStaRecOfClientList = &prBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH_ENTRY(prCurrStaRec, prStaRecOfClientList, rLinkEntry, + struct STA_RECORD) { + DBGLOG(SW4, INFO, "STA[%u] [" MACSTR "]\n", + prCurrStaRec->ucIndex, + MAC2STR(prCurrStaRec->aucMacAddr)); + } +#else + bssDumpClientList(prAdapter, prBssInfo); +#endif + + DBGLOG(SW4, INFO, "============== Dump Done ==============\n"); +} + +int8_t bssGetRxNss(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc) +{ + uint8_t ucIeByte = 0; + int8_t ucBssNss = 0; + uint8_t *pucRxMcsBitMaskIe; + const uint8_t *pucIe; + + if (!prAdapter || !prBssDesc) { + DBGLOG(BSS, INFO, "GetRxNss Param Error!\n"); + return -EINVAL; + } + + pucIe = kalFindIeMatchMask( + ELEM_ID_HT_CAP, + &prBssDesc->aucIEBuf[0], + prBssDesc->u2IELength, + NULL, 0, 0, NULL); + + if (!pucIe) + return 1; + + pucRxMcsBitMaskIe = + &((struct IE_HT_CAP *)pucIe)-> + rSupMcsSet.aucRxMcsBitmask[0]; + do { + ucIeByte = pucRxMcsBitMaskIe[ucBssNss]; + if (ucIeByte) + ucBssNss++; + if (ucBssNss == 8) + return ucBssNss; + } while (ucIeByte != 0); + + return ucBssNss; +} + + +#if (CFG_SUPPORT_HE_ER == 1) +void bssProcessErTxModeEvent(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct BSS_INFO *prBssInfo; + struct EVENT_ER_TX_MODE *prErTxMode; + + prErTxMode = (struct EVENT_ER_TX_MODE *) (prEvent->aucBuffer); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prErTxMode->ucBssInfoIdx); + + prBssInfo->ucErMode = prErTxMode->ucErMode; + + DBGLOG_LIMITED(BSS, WARN, + "Receive ER Tx mode event,BSS[%d],Mode[0x%x]\n", + prErTxMode->ucBssInfoIdx, prErTxMode->ucErMode); +} +#endif + +#if CFG_SUPPORT_IOT_AP_BLACKLIST +/*----------------------------------------------------------------------------*/ +/*! + * @brief get IOT AP handle action. + * + * @param[in] prBssDesc + * + * @return ENUM_WLAN_IOT_AP_HANDLE_ACTION + */ +/*----------------------------------------------------------------------------*/ +uint32_t bssGetIotApAction(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc) +{ + uint8_t ucCnt = 0; + int8_t ucBssNss; + uint8_t *pucMask; + uint16_t u2MatchFlag; + const uint8_t *pucIes; + const uint8_t *pucIe; + struct WLAN_IOT_AP_RULE_T *prIotApRule; + + if (!prAdapter || !prBssDesc) { + DBGLOG(BSS, INFO, "GetIotApAction Param Error!\n"); + return -EINVAL; + } + /*To make sure one Bss only parse once*/ + if (prBssDesc->fgIotApActionValid) + return prBssDesc->ucIotApAct; + + + prBssDesc->fgIotApActionValid = TRUE; + prBssDesc->ucIotApAct = WLAN_IOT_AP_VOID; + + pucIes = &prBssDesc->aucIEBuf[0]; + for (ucCnt = 0; ucCnt < CFG_IOT_AP_RULE_MAX_CNT; ucCnt++) { + prIotApRule = &prAdapter->rIotApRule[ucCnt]; + u2MatchFlag = prIotApRule->u2MatchFlag; + + /*No need to match empty rule*/ + if (prIotApRule->u2MatchFlag == 0) + continue; + + /*Check if default rule is allowed*/ + if (!prAdapter->rWifiVar.fgEnDefaultIotApRule && + (prIotApRule->ucVersion & BIT(7))) + continue; + + /*Match Vendor OUI*/ + if (u2MatchFlag & BIT(WLAN_IOT_AP_FG_OUI)) { + pucIe = kalFindIeMatchMask( + WLAN_EID_VENDOR_SPECIFIC, + pucIes, prBssDesc->u2IELength, + prIotApRule->aVendorOui, + MAC_OUI_LEN, 2, NULL); + if (!pucIe) + continue; + /*Match!, Fall through*/ + } + + /*Match Vendor Data rule*/ + if (u2MatchFlag & BIT(WLAN_IOT_AP_FG_DATA)) { + pucMask = + u2MatchFlag & BIT(WLAN_IOT_AP_FG_DATA_MASK) ? + &prIotApRule->aVendorDataMask[0] : NULL; + pucIe = kalFindIeMatchMask( + WLAN_EID_VENDOR_SPECIFIC, + pucIes, prBssDesc->u2IELength, + prIotApRule->aVendorData, + prIotApRule->ucDataLen, 5, pucMask); + if (!pucIe) + continue; + /*Match!, Fall through*/ + } + + /*Match BSSID rule*/ + if (u2MatchFlag & BIT(WLAN_IOT_AP_FG_BSSID)) { + pucMask = + u2MatchFlag & BIT(WLAN_IOT_AP_FG_BSSID_MASK) ? + &prIotApRule->aBssidMask[0] : NULL; + if (kalMaskMemCmp(&prBssDesc->aucBSSID, + &prIotApRule->aBssid, + pucMask, + MAC_ADDR_LEN)) + continue; + /*Match!, Fall through*/ + } + + /*Match Rx NSS rule*/ + if (u2MatchFlag & BIT(WLAN_IOT_AP_FG_NSS)) { + ucBssNss = bssGetRxNss(prAdapter, prBssDesc); + if (ucBssNss < 0) + DBGLOG(BSS, TRACE, + "IOTAP Nss=%d invalid", ucBssNss); + if (ucBssNss != prIotApRule->ucNss) + continue; + /*Match!, Fall through*/ + } + + /*Match HT type rule*/ + if (u2MatchFlag & BIT(WLAN_IOT_AP_FG_HT)) { + if (prBssDesc->fgIsVHTPresent) { + if (prIotApRule->ucHtType != 2) + continue; + } else if (prBssDesc->fgIsHTPresent) { + if (prIotApRule->ucHtType != 1) + continue; + } else { + if (prIotApRule->ucHtType != 0) + continue; + } + /*Matched, Fall through*/ + } + + /*Match Band Rule*/ + if (u2MatchFlag & BIT(WLAN_IOT_AP_FG_BAND)) { + if (prBssDesc->eBand != prIotApRule->ucBand) + continue; + /*Matched, Fall through*/ + } + /*All match, set the actions*/ + prBssDesc->ucIotApAct = prIotApRule->ucAction; + } + return prBssDesc->ucIotApAct; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/cnm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/cnm.c new file mode 100644 index 0000000000000..5890770a5fb27 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/cnm.c @@ -0,0 +1,4359 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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 + */ + + +/******************************************************************************* + * C O M P I L E 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 "wsys_cmd_handler_fw.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#if CFG_SUPPORT_DBDC +#define DBDC_ENABLE_GUARD_TIME (4*1000) /* ms */ +#define DBDC_DISABLE_GUARD_TIME (1*1000) /* ms */ +#define DBDC_DISABLE_COUNTDOWN_TIME (2*1000) /* ms */ +#define DBDC_WMM_TX_QUOTA (0x90) +#endif /* CFG_SUPPORT_DBDC */ + +#if CFG_SUPPORT_IDC_CH_SWITCH +#define IDC_CSA_GUARD_TIME (60) /* 60 Sec */ +#endif + +#define CNM_WMM_QUOTA_RETRIGGER_TIME_MS (200) /* ms */ +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +#if CFG_SUPPORT_DBDC +enum ENUM_DBDC_GUARD_TIMER_T { + ENUM_DBDC_GUARD_TIMER_NONE, + + /* Prevent switch too quick */ + ENUM_DBDC_GUARD_TIMER_SWITCH_GUARD_TIME, + + /* Prevent continuously trigger by reconnection */ + ENUM_DBDC_GUARD_TIMER_DISABLE_COUNT_DOWN, + + ENUM_DBDC_GUARD_TIMER_NUM +}; + +enum ENUM_DBDC_FSM_STATE_T { + ENUM_DBDC_FSM_STATE_DISABLE_IDLE, + ENUM_DBDC_FSM_STATE_WAIT_PROTOCOL_ENABLE, + ENUM_DBDC_FSM_STATE_WAIT_HW_ENABLE, + ENUM_DBDC_FSM_STATE_ENABLE_GUARD, + ENUM_DBDC_FSM_STATE_ENABLE_IDLE, + ENUM_DBDC_FSM_STATE_WAIT_HW_DISABLE, + ENUM_DBDC_FSM_STATE_DISABLE_GUARD, + ENUM_DBDC_FSM_STATE_WAIT_PROTOCOL_DISABLE, + ENUM_DBDC_FSM_STATE_NUM +}; + +enum ENUM_OPMODE_STATE_T { + ENUM_OPMODE_STATE_DONE, + ENUM_OPMODE_STATE_FAIL, + ENUM_OPMODE_STATE_WAIT, + ENUM_OPMODE_STATE_NUM +}; + +struct DBDC_INFO_T { + enum ENUM_DBDC_FSM_STATE_T eDbdcFsmCurrState; + enum ENUM_DBDC_FSM_STATE_T eDbdcFsmPrevState; + enum ENUM_DBDC_FSM_STATE_T eDbdcFsmNextState; + + struct TIMER rDbdcGuardTimer; + enum ENUM_DBDC_GUARD_TIMER_T eDdbcGuardTimerType; + + uint8_t fgReqPrivelegeLock; + struct LINK rPendingMsgList; + + bool fgDbdcDisableOpmodeChangeDone; + enum ENUM_OPMODE_STATE_T eBssOpModeState[BSSID_NUM]; + + /* Set DBDC setting for incoming network */ + uint8_t ucPrimaryChannel; + uint8_t ucWmmQueIdx; + + /* Used for iwpriv to force enable DBDC*/ + bool fgHasSentCmd; + bool fgCmdEn; + + /* Used to queue enter/leave A+G event */ + bool fgPostpondEnterAG; + bool fgPostpondLeaveAG; + + /* For debug */ + OS_SYSTIME rPeivilegeLockTime; +}; + +enum ENUM_DBDC_FSM_EVENT_T { + DBDC_FSM_EVENT_BSS_DISCONNECT_LEAVE_AG, + DBDC_FSM_EVENT_BSS_CONNECTING_ENTER_AG, + DBDC_FSM_EVENT_SWITCH_GUARD_TIME_TO, + DBDC_FSM_EVENT_DISABLE_COUNT_DOWN_TO, + DBDC_FSM_EVENT_ACTION_FRAME_ALL_SUCCESS, + DBDC_FSM_EVENT_ACTION_FRAME_SOME_FAIL, + DBDC_FSM_EVENT_DBDC_HW_SWITCH_DONE, + DBDC_FSM_EVENT_ERR, + DBDC_FSM_EVENT_NUM +}; + +enum ENUM_DBDC_PROTOCOL_STATUS_T { + ENUM_DBDC_PROTOCOL_STATUS_DONE_SUCCESS = 0, + ENUM_DBDC_PROTOCOL_STATUS_DONE_FAIL, + ENUM_DBDC_PROTOCOL_STATUS_WAIT, + ENUM_DBDC_PROTOCOL_STATUS_NUM +}; + +typedef void (*DBDC_ENTRY_FUNC)(struct ADAPTER *); +typedef void (*DBDC_EVENT_HNDL_FUNC)(struct ADAPTER *, + enum ENUM_DBDC_FSM_EVENT_T); +typedef void (*DBDC_EXIT_FUNC)(struct ADAPTER *); + +struct DBDC_FSM_T { + DBDC_ENTRY_FUNC pfEntryFunc; + DBDC_EVENT_HNDL_FUNC pfEventHandlerFunc; + DBDC_EXIT_FUNC pfExitFunc; +}; +#endif /*CFG_SUPPORT_DBDC*/ + +/* Priority Order !!!! */ +enum ENUM_CNM_OPMODE_REQ_T { + CNM_OPMODE_REQ_DBDC = 0, + CNM_OPMODE_REQ_DBDC_SCAN = 1, + CNM_OPMODE_REQ_COEX = 2, + CNM_OPMODE_REQ_SMARTGEAR = 3, + CNM_OPMODE_REQ_SMARTGEAR_1T2R = 4, + CNM_OPMODE_REQ_COANT = 5, + CNM_OPMODE_REQ_NUM = 6, + CNM_OPMODE_REQ_MAX_CAP = 7 /* just for coding */ +}; + +enum ENUM_CNM_OPMODE_REQ_STATUS { + CNM_OPMODE_REQ_STATUS_SUCCESS, + CNM_OPMODE_REQ_STATUS_INVALID_PARAM, + CNM_OPMODE_REQ_STATUS_RUNNING, + CNM_OPMODE_REQ_STATUS_DEFER, + CNM_OPMODE_REQ_STATUS_NUM +}; + +struct CNM_OPMODE_BSS_REQ { + bool fgEnable; + bool fgNewRequest; + uint8_t ucOpRxNss; + uint8_t ucOpTxNss; +}; + +struct CNM_OPMODE_BSS_RUNNING_REQ { + /* Initiator */ + enum ENUM_CNM_OPMODE_REQ_T eReqIdx; + /* Highest prioirty req */ + enum ENUM_CNM_OPMODE_REQ_T eRunReq; + bool fgIsRunning; + uint8_t ucOpRxNss; + uint8_t ucOpTxNss; +}; + +struct CNM_OPMODE_BSS_CONTROL_T { + struct CNM_OPMODE_BSS_RUNNING_REQ + rRunning; + struct CNM_OPMODE_BSS_REQ + arReqPool[CNM_OPMODE_REQ_NUM]; +}; + +enum ENUM_CNM_WMM_QUOTA_REQ_T { + CNM_WMM_REQ_DBDC = 0, + CNM_WMM_REQ_NUM = 1, + CNM_WMM_REQ_DEFAULT = 2 /* just for coding */ +}; + +struct CNM_WMM_QUOTA_REQ { + bool fgEnable; + uint32_t u4ReqQuota; +}; + +struct CNM_WMM_QUOTA_RUNNING_REQ { + /* Initiator */ + enum ENUM_CNM_WMM_QUOTA_REQ_T eReqIdx; + /* Highest prioirty req */ + enum ENUM_CNM_WMM_QUOTA_REQ_T eRunReq; + bool fgIsRunning; + uint32_t u4ReqQuota; +}; + +struct CNM_WMM_QUOTA_CONTROL_T { + struct CNM_WMM_QUOTA_RUNNING_REQ + rRunning; + struct CNM_WMM_QUOTA_REQ + arReqPool[CNM_WMM_REQ_NUM]; + struct TIMER rTimer; +}; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +#if CFG_SUPPORT_IDC_CH_SWITCH +struct EVENT_LTE_SAFE_CHN g_rLteSafeChInfo; +#endif + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +#if CFG_SUPPORT_DBDC +#define DBDC_SET_GUARD_TIME(_prAdapter, _u4TimeoutMs) { \ + cnmTimerStartTimer(_prAdapter, \ + &g_rDbdcInfo.rDbdcGuardTimer, \ + _u4TimeoutMs); \ + g_rDbdcInfo.eDdbcGuardTimerType = \ + ENUM_DBDC_GUARD_TIMER_SWITCH_GUARD_TIME; \ +} + +#define DBDC_SET_DISABLE_COUNTDOWN(_prAdapter) { \ + cnmTimerStartTimer(_prAdapter, \ + &g_rDbdcInfo.rDbdcGuardTimer, \ + DBDC_DISABLE_COUNTDOWN_TIME); \ + g_rDbdcInfo.eDdbcGuardTimerType = \ + ENUM_DBDC_GUARD_TIMER_DISABLE_COUNT_DOWN; \ + } + +#define DBDC_FSM_MSG_WRONG_EVT(_eEvent) \ + log_dbg(CNM, WARN, \ + "[DBDC] Should not reveice evt %u during state %u\n", \ + _eEvent, \ + g_rDbdcInfo.eDbdcFsmCurrState) + +#define DBDC_FSM_MSG_ERROR_EVT(_eEvent) \ + log_dbg(CNM, ERROR, "[DBDC] Reveice evt %u during state %u\n", \ + _eEvent, \ + g_rDbdcInfo.eDbdcFsmCurrState) + +#define USE_DBDC_CAPABILITY() \ + ((g_rDbdcInfo.eDbdcFsmCurrState \ + == ENUM_DBDC_FSM_STATE_WAIT_PROTOCOL_ENABLE || \ + g_rDbdcInfo.eDbdcFsmCurrState \ + == ENUM_DBDC_FSM_STATE_WAIT_HW_ENABLE || \ + g_rDbdcInfo.eDbdcFsmCurrState \ + == ENUM_DBDC_FSM_STATE_ENABLE_GUARD || \ + g_rDbdcInfo.eDbdcFsmCurrState \ + == ENUM_DBDC_FSM_STATE_ENABLE_IDLE)?TRUE:FALSE) + +#define DBDC_SET_WMMBAND_FW_AUTO_BY_CHNL(_ucPrimaryChannel, _ucWmmQueIdx) \ + { \ + g_rDbdcInfo.ucPrimaryChannel = (_ucPrimaryChannel);\ + g_rDbdcInfo.ucWmmQueIdx = (_ucWmmQueIdx);\ + } + +#define DBDC_SET_WMMBAND_FW_AUTO_DEFAULT() \ + { \ + g_rDbdcInfo.ucPrimaryChannel = 0; \ + g_rDbdcInfo.ucWmmQueIdx = 0;\ + } + +#define DBDC_UPDATE_CMD_WMMBAND_FW_AUTO(_prCmdBody) \ + { \ + (_prCmdBody)->ucPrimaryChannel = g_rDbdcInfo.ucPrimaryChannel; \ + (_prCmdBody)->ucWmmQueIdx = g_rDbdcInfo.ucWmmQueIdx; \ + DBDC_SET_WMMBAND_FW_AUTO_DEFAULT(); \ + } + +#endif + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +static void +cnmDbdcFsmEntryFunc_DISABLE_IDLE( + IN struct ADAPTER *prAdapter +); + +static void +cnmDbdcFsmEntryFunc_WAIT_PROTOCOL_ENABLE( + IN struct ADAPTER *prAdapter +); + +static void +cnmDbdcFsmEntryFunc_WAIT_HW_ENABLE( + IN struct ADAPTER *prAdapter +); + +static void +cnmDbdcFsmEntryFunc_ENABLE_GUARD( + IN struct ADAPTER *prAdapter +); + +static void +cnmDbdcFsmEntryFunc_WAIT_HW_DISABLE( + IN struct ADAPTER *prAdapter +); + +static void +cnmDbdcFsmEntryFunc_ENABLE_IDLE( + IN struct ADAPTER *prAdapter +); + +static void +cnmDbdcFsmEntryFunc_DISABLE_GUARD( + IN struct ADAPTER *prAdapter +); + +static void +cnmDbdcFsmEventHandler_DISABLE_IDLE( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent +); + +static void +cnmDbdcFsmEventHandler_WAIT_PROTOCOL_ENABLE( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent +); + +static void +cnmDbdcFsmEventHandler_WAIT_HW_ENABLE( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent +); + +static void +cnmDbdcFsmEventHandler_ENABLE_GUARD( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent +); + +static void +cnmDbdcFsmEventHandler_ENABLE_IDLE( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent +); + +static void +cnmDbdcFsmEventHandler_WAIT_HW_DISABLE( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent +); + +static void +cnmDbdcFsmEventHandler_DISABLE_GUARD( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent +); + +static void +cnmDbdcFsmEventHandler_WAIT_PROTOCOL_DISABLE( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent +); + +static void +cnmDbdcFsmExitFunc_WAIT_HW_ENABLE( + IN struct ADAPTER *prAdapter +); + +static void +cnmDbdcFsmExitFunc_WAIT_HW_DISABLE( + IN struct ADAPTER *prAdapter +); + +static void +cnmDbdcOpModeChangeDoneCallback( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN bool fgSuccess +); + +static enum ENUM_CNM_OPMODE_REQ_STATUS +cnmOpModeSetTRxNss( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN enum ENUM_CNM_OPMODE_REQ_T eNewReq, + IN bool fgEnable, + IN uint8_t ucOpRxNss, + IN uint8_t ucOpTxNss +); + +static void +cnmWmmQuotaCallback( + IN struct ADAPTER *prAdapter, + IN unsigned long plParamPtr +); + +static void +cnmWmmQuotaSetMaxQuota( + IN struct ADAPTER *prAdapter, + IN uint8_t ucWmmIndex, + IN enum ENUM_CNM_WMM_QUOTA_REQ_T eNewReq, + IN bool fgEnable, + IN uint32_t u4ReqQuota +); + +/******************************************************************************* + * P R I V A T E D A T A 2 + ******************************************************************************* + */ +static struct DBDC_FSM_T arDdbcFsmActionTable[] = { + /* ENUM_DBDC_FSM_STATE_DISABLE_IDLE */ + { + cnmDbdcFsmEntryFunc_DISABLE_IDLE, + cnmDbdcFsmEventHandler_DISABLE_IDLE, + NULL + }, + + /* ENUM_DBDC_FSM_STATE_WAIT_PROTOCOL_ENABLE */ + { + cnmDbdcFsmEntryFunc_WAIT_PROTOCOL_ENABLE, + cnmDbdcFsmEventHandler_WAIT_PROTOCOL_ENABLE, + NULL + }, + + /* ENUM_DBDC_FSM_STATE_WAIT_HW_ENABLE */ + { + cnmDbdcFsmEntryFunc_WAIT_HW_ENABLE, + cnmDbdcFsmEventHandler_WAIT_HW_ENABLE, + cnmDbdcFsmExitFunc_WAIT_HW_ENABLE + }, + + /* ENUM_DBDC_FSM_STATE_ENABLE_GUARD */ + { + cnmDbdcFsmEntryFunc_ENABLE_GUARD, + cnmDbdcFsmEventHandler_ENABLE_GUARD, + NULL + }, + + /* ENUM_DBDC_FSM_STATE_ENABLE_IDLE */ + { + cnmDbdcFsmEntryFunc_ENABLE_IDLE, + cnmDbdcFsmEventHandler_ENABLE_IDLE, + NULL + }, + + /* ENUM_DBDC_FSM_STATE_WAIT_HW_DISABLE */ + { + cnmDbdcFsmEntryFunc_WAIT_HW_DISABLE, + cnmDbdcFsmEventHandler_WAIT_HW_DISABLE, + cnmDbdcFsmExitFunc_WAIT_HW_DISABLE + }, + + /* ENUM_DBDC_FSM_STATE_DISABLE_GUARD */ + { + cnmDbdcFsmEntryFunc_DISABLE_GUARD, + cnmDbdcFsmEventHandler_DISABLE_GUARD, + NULL + }, + + /* ENUM_DBDC_FSM_STATE_WAIT_PROTOCOL_DISABLE */ + { + NULL, + cnmDbdcFsmEventHandler_WAIT_PROTOCOL_DISABLE, + NULL + }, +}; + +#if CFG_SUPPORT_DBDC +static struct DBDC_INFO_T g_rDbdcInfo; +#endif + +#if CFG_SUPPORT_IDC_CH_SWITCH +OS_SYSTIME g_rLastCsaSysTime; +#endif + +static struct CNM_OPMODE_BSS_CONTROL_T g_arBssOpControl[BSS_DEFAULT_NUM]; +static uint8_t *apucCnmOpModeReq[CNM_OPMODE_REQ_MAX_CAP+1] = { + (uint8_t *) DISP_STRING("DBDC"), + (uint8_t *) DISP_STRING("DBDC Scan"), + (uint8_t *) DISP_STRING("COEX"), + (uint8_t *) DISP_STRING("SmartGear"), + (uint8_t *) DISP_STRING("SmartGear_1T2R"), + (uint8_t *) DISP_STRING("CoAnt"), + (uint8_t *) DISP_STRING("N/A"), + (uint8_t *) DISP_STRING("MAX_CAP") +}; + +static uint8_t *apucCnmOpModeReqStatus[CNM_OPMODE_REQ_STATUS_NUM+1] = { + (uint8_t *) DISP_STRING("Success"), + (uint8_t *) DISP_STRING("Invalid"), + (uint8_t *) DISP_STRING("Running"), + (uint8_t *) DISP_STRING("Defer"), + (uint8_t *) DISP_STRING("N/A") +}; + +static struct CNM_WMM_QUOTA_CONTROL_T g_arWmmQuotaControl[BSS_DEFAULT_NUM]; +static uint8_t *apucCnmWmmQuotaReq[CNM_WMM_REQ_DEFAULT+1] = { + (uint8_t *) DISP_STRING("DBDC"), + (uint8_t *) DISP_STRING("N/A"), + (uint8_t *) DISP_STRING("Default") +}; + +/******************************************************************************* + * M A C R O S 2 + ******************************************************************************* + */ +#define DBDC_FSM_EVENT_HANDLER(_prAdapter, _event) { \ + arDdbcFsmActionTable[g_rDbdcInfo.eDbdcFsmCurrState] \ + .pfEventHandlerFunc(_prAdapter, _event); \ + } + +/******************************************************************************* + * 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(struct ADAPTER *prAdapter) +{ + struct CNM_INFO *prCnmInfo; + struct CNM_OPMODE_BSS_CONTROL_T *prBssOpCtrl; + struct CNM_WMM_QUOTA_CONTROL_T *prWmmQuotaCtrl; + enum ENUM_CNM_OPMODE_REQ_T eReqIdx; + enum ENUM_CNM_WMM_QUOTA_REQ_T eReqIdxWmm; + uint8_t ucBssIndex, ucWmmIndex; + + ASSERT(prAdapter); + + prCnmInfo = &prAdapter->rCnmInfo; + prCnmInfo->fgChGranted = FALSE; + + if (prAdapter->ucHwBssIdNum > BSS_DEFAULT_NUM) { + /* Unexpected! out of bounds access may happen... */ + DBGLOG(CNM, WARN, + "HwBssNum(%d) > BSS_DEFAULT_NUM !!!\n", + prAdapter->ucHwBssIdNum); + } + + for (ucBssIndex = 0; ucBssIndex < prAdapter->ucHwBssIdNum; + ucBssIndex++) { + prBssOpCtrl = &(g_arBssOpControl[ucBssIndex]); + prBssOpCtrl->rRunning.fgIsRunning = false; + for (eReqIdx = CNM_OPMODE_REQ_DBDC; + eReqIdx < CNM_OPMODE_REQ_NUM; eReqIdx++) + prBssOpCtrl->arReqPool[eReqIdx].fgEnable = false; + } + + if (prAdapter->ucHwBssIdNum > MAX_BSSID_NUM || + prAdapter->ucWmmSetNum > MAX_BSSID_NUM) { + /* Unexpected! out of bounds access may happen... */ + DBGLOG(CNM, WARN, + "HwBssNum(%d)WmmNum(%d) > BSS_DEFAULT_NUM !!!\n", + prAdapter->ucHwBssIdNum, + prAdapter->ucWmmSetNum); + ASSERT(0); + } + + for (ucWmmIndex = 0; ucWmmIndex < prAdapter->ucWmmSetNum; + ucWmmIndex++) { + prWmmQuotaCtrl = &(g_arWmmQuotaControl[ucWmmIndex]); + prWmmQuotaCtrl->rRunning.fgIsRunning = false; + cnmTimerInitTimer(prAdapter, + &(prWmmQuotaCtrl->rTimer), + (PFN_MGMT_TIMEOUT_FUNC) + cnmWmmQuotaCallback, + (unsigned long) + ucWmmIndex); + for (eReqIdxWmm = CNM_WMM_REQ_DBDC; + eReqIdxWmm < CNM_WMM_REQ_NUM; eReqIdxWmm++) + prWmmQuotaCtrl->arReqPool[eReqIdxWmm].fgEnable = false; + } + +#if CFG_SUPPORT_IDC_CH_SWITCH + g_rLastCsaSysTime = 0; +#endif +} /* end of cnmInit()*/ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is used to initialize variables in CNM_INFO_T. + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void cnmUninit(struct ADAPTER *prAdapter) +{ + struct CNM_WMM_QUOTA_CONTROL_T *prWmmQuotaCtrl; + uint8_t ucWmmIndex; + + cnmTimerStopTimer(prAdapter, + &g_rDbdcInfo.rDbdcGuardTimer); + + for (ucWmmIndex = 0; ucWmmIndex < prAdapter->ucWmmSetNum; + ucWmmIndex++) { + prWmmQuotaCtrl = &(g_arWmmQuotaControl[ucWmmIndex]); + cnmTimerStopTimer(prAdapter, &(prWmmQuotaCtrl->rTimer)); + } +} /* 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(struct ADAPTER + *prAdapter, + struct MSG_HDR *prMsgHdr) +{ + struct MSG_CH_REQ *prMsgChReq; + struct CMD_CH_PRIVILEGE *prCmdBody; + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + uint32_t rStatus; +#if CFG_SUPPORT_DBDC + OS_SYSTIME rChReqQueueTime; +#endif + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prMsgChReq = (struct MSG_CH_REQ *)prMsgHdr; + +#if CFG_SUPPORT_DBDC + if (cnmDBDCIsReqPeivilegeLock()) { + LINK_INSERT_TAIL(&g_rDbdcInfo.rPendingMsgList, + &prMsgHdr->rLinkEntry); + log_dbg(CNM, INFO, + "[DBDC] ChReq: queued BSS %u Token %u REQ\n", + prMsgChReq->ucBssIndex, prMsgChReq->ucTokenID); + + /* Trigger EE dump if PeivilegeLock was held for more than 5s */ + rChReqQueueTime = kalGetTimeTick(); + if ((g_rDbdcInfo.rPeivilegeLockTime != 0) && + (rChReqQueueTime > g_rDbdcInfo.rPeivilegeLockTime) && + ((rChReqQueueTime - + g_rDbdcInfo.rPeivilegeLockTime) > 5000)) { + log_dbg(CNM, WARN, + "[DBDC] ChReq: long peivilege lock at %d, %d\n", + g_rDbdcInfo.rPeivilegeLockTime, + rChReqQueueTime); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_CHIP_RESET); + } + return; + } +#endif + + prCmdBody = (struct CMD_CH_PRIVILEGE *) + cnmMemAlloc(prAdapter, RAM_TYPE_BUF, + sizeof(struct CMD_CH_PRIVILEGE)); + ASSERT(prCmdBody); + + /* To do: exception handle */ + if (!prCmdBody) { + log_dbg(CNM, ERROR, + "ChReq: fail to get buf (net=%d, token=%d)\n", + prMsgChReq->ucBssIndex, prMsgChReq->ucTokenID); + + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + /* Activate network if it's not activated yet */ + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsgChReq->ucBssIndex); + + if (!IS_BSS_ACTIVE(prBssInfo)) { + SET_NET_ACTIVE(prAdapter, prBssInfo->ucBssIndex); + nicActivateNetwork(prAdapter, prBssInfo->ucBssIndex); + } + + log_dbg(CNM, INFO, + "ChReq net=%d token=%d b=%d c=%d s=%d w=%d s1=%d s2=%d d=%d t=%d\n", + prMsgChReq->ucBssIndex, prMsgChReq->ucTokenID, + prMsgChReq->eRfBand, prMsgChReq->ucPrimaryChannel, + prMsgChReq->eRfSco, prMsgChReq->eRfChannelWidth, + prMsgChReq->ucRfCenterFreqSeg1, + prMsgChReq->ucRfCenterFreqSeg2, + prMsgChReq->u4MaxInterval, + prMsgChReq->eReqType); + + prCmdBody->ucBssIndex = prMsgChReq->ucBssIndex; + prCmdBody->ucTokenID = prMsgChReq->ucTokenID; + prCmdBody->ucAction = CMD_CH_ACTION_REQ; /* Request */ + prCmdBody->ucPrimaryChannel = + prMsgChReq->ucPrimaryChannel; + prCmdBody->ucRfSco = (uint8_t)prMsgChReq->eRfSco; + prCmdBody->ucRfBand = (uint8_t)prMsgChReq->eRfBand; + prCmdBody->ucRfChannelWidth = (uint8_t) + prMsgChReq->eRfChannelWidth; + prCmdBody->ucRfCenterFreqSeg1 = (uint8_t) + prMsgChReq->ucRfCenterFreqSeg1; + prCmdBody->ucRfCenterFreqSeg2 = (uint8_t) + prMsgChReq->ucRfCenterFreqSeg2; + prCmdBody->ucReqType = (uint8_t)prMsgChReq->eReqType; + prCmdBody->ucDBDCBand = (uint8_t)prMsgChReq->eDBDCBand; + prCmdBody->aucReserved = 0; + prCmdBody->u4MaxInterval = prMsgChReq->u4MaxInterval; + prCmdBody->aucReserved2[0] = 0; + prCmdBody->aucReserved2[1] = 0; + prCmdBody->aucReserved2[2] = 0; + prCmdBody->aucReserved2[3] = 0; + prCmdBody->aucReserved2[4] = 0; + prCmdBody->aucReserved2[5] = 0; + prCmdBody->aucReserved2[6] = 0; + prCmdBody->aucReserved2[7] = 0; + + ASSERT(prCmdBody->ucBssIndex <= + prAdapter->ucHwBssIdNum); + + /* For monkey testing 20110901 */ + if (prCmdBody->ucBssIndex > prAdapter->ucHwBssIdNum) + log_dbg(CNM, ERROR, + "CNM: ChReq with wrong netIdx=%d\n\n", + prCmdBody->ucBssIndex); + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_CH_PRIVILEGE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + + /* u4SetQueryInfoLen */ + sizeof(struct CMD_CH_PRIVILEGE), + + /* pucInfoBuffer */ + (uint8_t *)prCmdBody, + + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + /* ASSERT(rStatus == WLAN_STATUS_PENDING); */ + + cnmMemFree(prAdapter, prCmdBody); + cnmMemFree(prAdapter, prMsgHdr); +} /* end of cnmChMngrRequestPrivilege()*/ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Before deliver the message to other module, it need to release + * the Channel privilege to Channel Manager. + * + * @param[in] prMsgHdr The message need to be delivered + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void cnmChMngrAbortPrivilege(struct ADAPTER *prAdapter, + struct MSG_HDR *prMsgHdr) +{ + struct MSG_CH_ABORT *prMsgChAbort; + struct CMD_CH_PRIVILEGE *prCmdBody; + struct CNM_INFO *prCnmInfo; + uint32_t rStatus; +#if CFG_SISO_SW_DEVELOP + struct BSS_INFO *prBssInfo; +#endif +#if CFG_SUPPORT_DBDC + struct LINK_ENTRY *prLinkEntry_pendingMsg; + struct MSG_CH_REQ *prPendingMsg; +#endif + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prMsgChAbort = (struct MSG_CH_ABORT *)prMsgHdr; + +#if CFG_SUPPORT_DBDC + if (cnmDBDCIsReqPeivilegeLock()) { + LINK_FOR_EACH(prLinkEntry_pendingMsg, + &g_rDbdcInfo.rPendingMsgList) { + prPendingMsg = (struct MSG_CH_REQ *) + LINK_ENTRY(prLinkEntry_pendingMsg, + struct MSG_HDR, rLinkEntry); + + /* Find matched request and check + * if it is being served. + */ + if (prPendingMsg->ucBssIndex == prMsgChAbort->ucBssIndex + && prPendingMsg->ucTokenID + == prMsgChAbort->ucTokenID) { + + LINK_REMOVE_KNOWN_ENTRY( + &g_rDbdcInfo.rPendingMsgList, + &prPendingMsg->rMsgHdr.rLinkEntry); + + log_dbg(CNM, INFO, "[DBDC] ChAbort: remove BSS %u Token %u REQ)\n", + prPendingMsg->ucBssIndex, + prPendingMsg->ucTokenID); + + cnmMemFree(prAdapter, prPendingMsg); + cnmMemFree(prAdapter, prMsgHdr); + + return; + } + } + } +#endif + + /* Check if being granted channel privilege is aborted */ + prCnmInfo = &prAdapter->rCnmInfo; + if (prCnmInfo->fgChGranted && + prCnmInfo->ucBssIndex == prMsgChAbort->ucBssIndex + && prCnmInfo->ucTokenID == prMsgChAbort->ucTokenID) { + + prCnmInfo->fgChGranted = FALSE; + } + + prCmdBody = (struct CMD_CH_PRIVILEGE *) + cnmMemAlloc(prAdapter, RAM_TYPE_BUF, + sizeof(struct CMD_CH_PRIVILEGE)); + if (!prCmdBody) { + log_dbg(CNM, ERROR, + "ChAbort: fail to get buf (net=%d, token=%d)\n", + prMsgChAbort->ucBssIndex, prMsgChAbort->ucTokenID); + + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + prCmdBody->ucBssIndex = prMsgChAbort->ucBssIndex; + prCmdBody->ucTokenID = prMsgChAbort->ucTokenID; + prCmdBody->ucAction = CMD_CH_ACTION_ABORT; /* Abort */ + prCmdBody->ucDBDCBand = (uint8_t) + prMsgChAbort->eDBDCBand; + + log_dbg(CNM, INFO, "ChAbort net=%d token=%d dbdc=%u\n", + prCmdBody->ucBssIndex, prCmdBody->ucTokenID, + prCmdBody->ucDBDCBand); + + ASSERT(prCmdBody->ucBssIndex <= + prAdapter->ucHwBssIdNum); + + /* For monkey testing 20110901 */ + if (prCmdBody->ucBssIndex > prAdapter->ucHwBssIdNum) + log_dbg(CNM, ERROR, + "CNM: ChAbort with wrong netIdx=%d\n\n", + prCmdBody->ucBssIndex); + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_CH_PRIVILEGE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + + /* u4SetQueryInfoLen */ + sizeof(struct CMD_CH_PRIVILEGE), + + /* pucInfoBuffer */ + (uint8_t *)prCmdBody, + + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + /* ASSERT(rStatus == WLAN_STATUS_PENDING); */ + +#if CFG_SISO_SW_DEVELOP + prBssInfo = + prAdapter->aprBssInfo[prMsgChAbort->ucBssIndex]; + /* Driver clear granted CH in BSS info */ + prBssInfo->fgIsGranted = FALSE; + prBssInfo->eBandGranted = BAND_NULL; + prBssInfo->ucPrimaryChannelGranted = 0; +#endif + + cnmMemFree(prAdapter, prCmdBody); + cnmMemFree(prAdapter, prMsgHdr); +} /* end of cnmChMngrAbortPrivilege()*/ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void cnmChMngrHandleChEvent(struct ADAPTER *prAdapter, + struct WIFI_EVENT *prEvent) +{ + struct EVENT_CH_PRIVILEGE *prEventBody; + struct MSG_CH_GRANT *prChResp; + struct BSS_INFO *prBssInfo; + struct CNM_INFO *prCnmInfo; + + ASSERT(prAdapter); + ASSERT(prEvent); + + prEventBody = (struct EVENT_CH_PRIVILEGE *)( + prEvent->aucBuffer); + prChResp = (struct MSG_CH_GRANT *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_CH_GRANT)); + if (!prChResp) { + log_dbg(CNM, ERROR, + "ChGrant: fail to get buf (net=%d, token=%d)\n", + prEventBody->ucBssIndex, prEventBody->ucTokenID); + + return; + } + + log_dbg(CNM, INFO, + "ChGrant net=%d token=%d ch=%d sco=%d u4GrantInterval=%d\n", + prEventBody->ucBssIndex, prEventBody->ucTokenID, + prEventBody->ucPrimaryChannel, + prEventBody->ucRfSco, prEventBody->u4GrantInterval); + + ASSERT(prEventBody->ucBssIndex <= + prAdapter->ucHwBssIdNum); + ASSERT(prEventBody->ucStatus == EVENT_CH_STATUS_GRANT); + + prBssInfo = + prAdapter->aprBssInfo[prEventBody->ucBssIndex]; + + /* Decide message ID based on network and response status */ + if (IS_BSS_AIS(prBssInfo)) + prChResp->rMsgHdr.eMsgId = MID_CNM_AIS_CH_GRANT; +#if CFG_ENABLE_WIFI_DIRECT + else if (prAdapter->fgIsP2PRegistered + && IS_BSS_P2P(prBssInfo)) + prChResp->rMsgHdr.eMsgId = MID_CNM_P2P_CH_GRANT; +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (IS_BSS_BOW(prBssInfo)) + prChResp->rMsgHdr.eMsgId = MID_CNM_BOW_CH_GRANT; +#endif + else { + cnmMemFree(prAdapter, prChResp); + return; + } + + prChResp->ucBssIndex = prEventBody->ucBssIndex; + prChResp->ucTokenID = prEventBody->ucTokenID; + prChResp->ucPrimaryChannel = + prEventBody->ucPrimaryChannel; + prChResp->eRfSco = (enum ENUM_CHNL_EXT) + prEventBody->ucRfSco; + prChResp->eRfBand = (enum ENUM_BAND) + prEventBody->ucRfBand; + prChResp->eRfChannelWidth = (enum ENUM_CHANNEL_WIDTH) + prEventBody->ucRfChannelWidth; + prChResp->ucRfCenterFreqSeg1 = + prEventBody->ucRfCenterFreqSeg1; + prChResp->ucRfCenterFreqSeg2 = + prEventBody->ucRfCenterFreqSeg2; + prChResp->eReqType = (enum ENUM_CH_REQ_TYPE) + prEventBody->ucReqType; + prChResp->eDBDCBand = (enum ENUM_DBDC_BN) + prEventBody->ucDBDCBand; + prChResp->u4GrantInterval = + prEventBody->u4GrantInterval; + + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *)prChResp, MSG_SEND_METHOD_BUF); + + /* Record current granted BSS for TXM's reference */ + prCnmInfo = &prAdapter->rCnmInfo; + prCnmInfo->ucBssIndex = prEventBody->ucBssIndex; + prCnmInfo->ucTokenID = prEventBody->ucTokenID; + prCnmInfo->fgChGranted = TRUE; +} + +#if (CFG_SUPPORT_DFS_MASTER == 1) +void cnmRadarDetectEvent(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct EVENT_RDD_REPORT *prEventBody; + struct BSS_INFO *prBssInfo; + struct MSG_P2P_RADAR_DETECT *prP2pRddDetMsg; + uint8_t ucBssIndex; + + log_dbg(CNM, INFO, "cnmRadarDetectEvent.\n"); + + prEventBody = (struct EVENT_RDD_REPORT *)( + prEvent->aucBuffer); + + prP2pRddDetMsg = (struct MSG_P2P_RADAR_DETECT *) + cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(*prP2pRddDetMsg)); + + if (!prP2pRddDetMsg) { + log_dbg(CNM, ERROR, + "cnmMemAlloc for prP2pRddDetMsg failed!\n"); + return; + } + + prP2pRddDetMsg->rMsgHdr.eMsgId = + MID_CNM_P2P_RADAR_DETECT; + + for (ucBssIndex = 0; ucBssIndex < BSS_DEFAULT_NUM; + ucBssIndex++) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex); + + if (prBssInfo && prBssInfo->fgIsDfsActive) { + prP2pRddDetMsg->ucBssIndex = ucBssIndex; + break; + } + } + + p2pFuncSetDfsState(DFS_STATE_DETECTED); + + p2pFuncRadarInfoInit(); + + g_rP2pRadarInfo.ucRadarReportMode = + prEventBody->ucRadarReportMode; + g_rP2pRadarInfo.ucRddIdx = prEventBody->ucRddIdx; + g_rP2pRadarInfo.ucLongDetected = + prEventBody->ucLongDetected; + g_rP2pRadarInfo.ucPeriodicDetected = + prEventBody->ucPeriodicDetected; + g_rP2pRadarInfo.ucLPBNum = prEventBody->ucLPBNum; + g_rP2pRadarInfo.ucPPBNum = prEventBody->ucPPBNum; + g_rP2pRadarInfo.ucLPBPeriodValid = + prEventBody->ucLPBPeriodValid; + g_rP2pRadarInfo.ucLPBWidthValid = + prEventBody->ucLPBWidthValid; + g_rP2pRadarInfo.ucPRICountM1 = + prEventBody->ucPRICountM1; + g_rP2pRadarInfo.ucPRICountM1TH = + prEventBody->ucPRICountM1TH; + g_rP2pRadarInfo.ucPRICountM2 = + prEventBody->ucPRICountM2; + g_rP2pRadarInfo.ucPRICountM2TH = + prEventBody->ucPRICountM2TH; + g_rP2pRadarInfo.u4PRI1stUs = prEventBody->u4PRI1stUs; + kalMemCopy(&g_rP2pRadarInfo.arLpbContent[0], + &prEventBody->arLpbContent[0], + prEventBody->ucLPBNum * sizeof(struct + LONG_PULSE_BUFFER)); + kalMemCopy(&g_rP2pRadarInfo.arPpbContent[0], + &prEventBody->arPpbContent[0], + prEventBody->ucPPBNum * sizeof(struct + PERIODIC_PULSE_BUFFER)); + + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *)prP2pRddDetMsg, MSG_SEND_METHOD_BUF); +} + +void cnmCsaDoneEvent(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + DBGLOG(CNM, INFO, "cnmCsaDoneEvent.\n"); + + if (prAdapter->rWifiVar.fgCsaInProgress == FALSE) { + DBGLOG(CNM, WARN, "Receive duplicate cnmCsaDoneEvent.\n"); + return; + } + + prAdapter->rWifiVar.fgCsaInProgress = FALSE; + + p2pFunChnlSwitchNotifyDone(prAdapter); +} +#endif + +#define CFG_SUPPORT_IDC_CROSS_BAND_SWITCH 1 + +#if CFG_SUPPORT_IDC_CH_SWITCH +uint8_t cnmDecideSapNewChannel( + IN struct GLUE_INFO *prGlueInfo, + IN struct BSS_INFO *prBssInfo) +{ + uint8_t ucSwitchMode; + uint32_t u4LteSafeChnBitMask_2G = 0, u4LteSafeChnBitMask_5G_1 = 0, + u4LteSafeChnBitMask_5G_2 = 0; + uint8_t ucCurrentChannel = 0; + + if (!prGlueInfo || !prBssInfo) { + DBGLOG(P2P, ERROR, "prGlueInfo or prBssInfo is NULL\n"); + return -EFAULT; + } + + ucCurrentChannel = prBssInfo->ucPrimaryChannel; + + ASSERT(ucCurrentChannel); + + if (ucCurrentChannel <= 14) + ucSwitchMode = CH_SWITCH_2G; + else { + ucSwitchMode = CH_SWITCH_5G; + DBGLOG(P2P, WARN, + "Switch to 5G channel instead\n"); + } + /* + * Get LTE safe channels + */ + if (g_rLteSafeChInfo.u4Flags & BIT(0)) { + u4LteSafeChnBitMask_2G = g_rLteSafeChInfo + .rLteSafeChn.au4SafeChannelBitmask[0]; + u4LteSafeChnBitMask_5G_1 = g_rLteSafeChInfo + .rLteSafeChn.au4SafeChannelBitmask[1]; + u4LteSafeChnBitMask_5G_2 = g_rLteSafeChInfo + .rLteSafeChn.au4SafeChannelBitmask[2]; + } + + if (ucSwitchMode == CH_SWITCH_2G) { + if (!(u4LteSafeChnBitMask_2G & BITS(1, 14))) { + DBGLOG(P2P, WARN, + "FW report 2.4G all channels unsafe!?\n"); +#if CFG_SUPPORT_IDC_CROSS_BAND_SWITCH + /* Choose 5G non-RDD Channel */ + if ((u4LteSafeChnBitMask_5G_1 || u4LteSafeChnBitMask_5G_2) + && prGlueInfo->prAdapter->rWifiVar + .fgCrossBandSwitchEn) { + ucSwitchMode = CH_SWITCH_5G; + DBGLOG(P2P, WARN, + "Switch to 5G channel instead\n"); + } else { + /* not to switch channel*/ + return 0; + } +#endif + } + } else { /*ucSwitchMode == CH_SWITCH_5G*/ + if ((!(u4LteSafeChnBitMask_5G_1 & BITS(0, 27))) && + (!(u4LteSafeChnBitMask_5G_2 & BITS(0, 8)))) { + DBGLOG(P2P, WARN, + "FW report 5G all channels unsafe!?\n"); +#if CFG_SUPPORT_IDC_CROSS_BAND_SWITCH + /* Choose 2.4G non-RDD Channel */ + if (u4LteSafeChnBitMask_2G + && prGlueInfo->prAdapter->rWifiVar + .fgCrossBandSwitchEn) { + ucSwitchMode = CH_SWITCH_2G; + DBGLOG(P2P, WARN, + "Switch to 2.4G channel instead\n"); + } else { + /* not to switch channel*/ + return 0; + } +#endif + } + } + + return p2pFunGetAcsBestCh(prGlueInfo->prAdapter, + ucSwitchMode == CH_SWITCH_2G ? BAND_2G4 : BAND_5G, + rlmGetBssOpBwByVhtAndHtOpInfo(prBssInfo), + u4LteSafeChnBitMask_2G, + u4LteSafeChnBitMask_5G_1, + u4LteSafeChnBitMask_5G_2); +} + +uint8_t cnmIdcCsaReq(IN struct ADAPTER *prAdapter, + IN uint8_t ch_num, IN uint8_t ucRoleIdx) +{ + struct BSS_INFO *prBssInfo = NULL; + uint8_t ucBssIdx = 0; + struct RF_CHANNEL_INFO rRfChnlInfo; + + ASSERT(ch_num); + + if (p2pFuncRoleToBssIdx( + prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) + return -1; + + DBGLOG(REQ, INFO, + "[CSA]RoleIdx = %d ,CH = %d BssIdx = %d\n", + ucRoleIdx, ch_num, ucBssIdx); + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + + if (prBssInfo->ucPrimaryChannel != ch_num) { + rRfChnlInfo.ucChannelNum = ch_num; + rRfChnlInfo.eBand = + (rRfChnlInfo.ucChannelNum <= 14) + ? BAND_2G4 : BAND_5G; + rRfChnlInfo.ucChnlBw = + rlmGetBssOpBwByVhtAndHtOpInfo(prBssInfo); + rRfChnlInfo.u2PriChnlFreq = + nicChannelNum2Freq(ch_num) / 1000; + rRfChnlInfo.u4CenterFreq1 = + rRfChnlInfo.u2PriChnlFreq; + rRfChnlInfo.u4CenterFreq2 = 0; + + DBGLOG(REQ, INFO, + "[CSA]CH=%d,Band=%d,BW=%d,PriFreq=%d,S1=%d\n", + rRfChnlInfo.ucChannelNum, + rRfChnlInfo.eBand, + rRfChnlInfo.ucChnlBw, + rRfChnlInfo.u2PriChnlFreq, + rRfChnlInfo.u4CenterFreq1); + + cnmSapChannelSwitchReq(prAdapter, &rRfChnlInfo, ucRoleIdx); + + /* Record Last Channel Switch Time */ + GET_CURRENT_SYSTIME(&g_rLastCsaSysTime); + + return 0; /* Return Success */ + + } else { + DBGLOG(CNM, INFO, + "[CSA]Req CH = cur CH:%d, Stop Req\n", + prBssInfo->ucPrimaryChannel); + return -1; + } +} + +void cnmIdcDetectHandler(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + + struct EVENT_LTE_SAFE_CHN *prEventBody; + uint8_t ucIdx; + struct BSS_INFO *prBssInfo; + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + uint8_t ucNewChannel = 0; + uint32_t u4Ret = 0; + OS_SYSTIME rCurrentTime = 0; + bool fgCsaCoolDown = FALSE; + uint8_t ucColdDownTime = 0; + struct WIFI_VAR *prWifiVar = + (struct WIFI_VAR *)NULL; + + prEventBody = (struct EVENT_LTE_SAFE_CHN *)( + prEvent->aucBuffer); + + g_rLteSafeChInfo.ucVersion = prEventBody->ucVersion; + g_rLteSafeChInfo.u4Flags = prEventBody->u4Flags; + + /* Statistics from FW is valid */ + if (prEventBody->u4Flags & BIT(0)) { + for (ucIdx = 0; + ucIdx < ENUM_SAFE_CH_MASK_MAX_NUM; + ucIdx++) { + g_rLteSafeChInfo.rLteSafeChn. + au4SafeChannelBitmask[ucIdx] + = prEventBody->rLteSafeChn. + au4SafeChannelBitmask[ucIdx]; + + DBGLOG(P2P, INFO, + "[CSA]LTE safe channels[%d]=0x%08x\n", + ucIdx, + prEventBody->rLteSafeChn. + au4SafeChannelBitmask[ucIdx]); + } + } + prWifiVar = &prAdapter->rWifiVar; + if (prWifiVar->ucChannelSwtichColdownTime) + ucColdDownTime = prWifiVar->ucChannelSwtichColdownTime; + else + ucColdDownTime = IDC_CSA_GUARD_TIME; + + + /* Only allow to switch channel once each minute*/ + GET_CURRENT_SYSTIME(&rCurrentTime); + if ((CHECK_FOR_TIMEOUT(rCurrentTime, + g_rLastCsaSysTime, + SEC_TO_SYSTIME(ucColdDownTime))) + || (g_rLastCsaSysTime == 0)) { + fgCsaCoolDown = TRUE; + } + + if (!fgCsaCoolDown) { + DBGLOG(CNM, INFO, + "[CSA]CsaCoolDown not Finish yet,rCurrentTime=%d,g_rLastCsaSysTime=%d,IDC_CSA_GUARD_TIME=%d\n", + rCurrentTime, + g_rLastCsaSysTime, + SEC_TO_SYSTIME(ucColdDownTime)); + return; + } + + /* Choose New Ch & Start CH Swtich*/ + prBssInfo = cnmGetSapBssInfo(prAdapter); + if (prBssInfo) { + DBGLOG(CNM, INFO, "[CSA]BssIdx=%d,CurCH=%d\n", + prBssInfo->ucBssIndex, + prBssInfo->ucPrimaryChannel); + ucNewChannel = cnmDecideSapNewChannel(prGlueInfo, + prBssInfo); + if (ucNewChannel) { + u4Ret = cnmIdcCsaReq(prAdapter, ucNewChannel, + prBssInfo->u4PrivateData); + DBGLOG(CNM, INFO, "[CSA]BssIdx=%d,NewCH=%d\n", + prBssInfo->ucBssIndex, ucNewChannel); + } else { + DBGLOG(CNM, INFO, + "[CSA]No Safe channel,not switch CH\n"); + } + } else { + DBGLOG(CNM, WARN, + "[CSA]SoftAp Not Exist\n"); + } + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t +cnmPreferredChannel(struct ADAPTER *prAdapter, + enum ENUM_BAND *prBand, uint8_t *pucPrimaryChannel, + enum ENUM_CHNL_EXT *prBssSCO) +{ + struct BSS_INFO *prBssInfo; + uint8_t i; + + ASSERT(prAdapter); + ASSERT(prBand); + ASSERT(pucPrimaryChannel); + ASSERT(prBssSCO); + + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, i); + + if (prBssInfo) { + if (IS_BSS_AIS(prBssInfo) + && 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t cnmAisInfraChannelFixed(struct ADAPTER + *prAdapter, + enum ENUM_BAND *prBand, + uint8_t *pucPrimaryChannel) +{ + struct BSS_INFO *prBssInfo; + uint8_t i; + struct WIFI_VAR *prWifiVar; + + ASSERT(prAdapter); + + prWifiVar = &prAdapter->rWifiVar; + + if (prWifiVar->u4ScanCtrl & + SCN_CTRL_DEFAULT_SCAN_CTRL) { + /* log_dbg(CNM, INFO, "ByPass AIS channel Fix check\n");*/ + return FALSE; + } + + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + +#if 0 + log_dbg(INIT, INFO, + "%s BSS[%u] active[%u] netType[%u]\n", + __func__, i, prBssInfo->fgIsNetActive, + prBssInfo->eNetworkType); +#endif + + if (!IS_NET_ACTIVE(prAdapter, i)) + continue; + +#if CFG_ENABLE_WIFI_DIRECT + if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P + && !cnmSapIsConcurrent(prAdapter)) { + u_int8_t fgFixedChannel = + p2pFuncIsAPMode( + prAdapter->rWifiVar.prP2PConnSettings[ + prBssInfo->u4PrivateData]); + + if (fgFixedChannel) { + + *prBand = prBssInfo->eBand; + *pucPrimaryChannel + = prBssInfo->ucPrimaryChannel; + + return TRUE; + + } + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI && CFG_BOW_LIMIT_AIS_CHNL + if (prBssInfo->eNetworkType == NETWORK_TYPE_BOW) { + *prBand = prBssInfo->eBand; + *pucPrimaryChannel = prBssInfo->ucPrimaryChannel; + + return TRUE; + } +#endif + + } + + return FALSE; +} + +#if CFG_SUPPORT_CHNL_CONFLICT_REVISE +u_int8_t cnmAisDetectP2PChannel(struct ADAPTER + *prAdapter, + enum ENUM_BAND *prBand, + uint8_t *pucPrimaryChannel) +{ + uint8_t i = 0; + struct BSS_INFO *prBssInfo; + + ASSERT(prAdapter); + +#if CFG_ENABLE_WIFI_DIRECT + for (; i < prAdapter->ucHwBssIdNum; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + if (prBssInfo->eNetworkType != NETWORK_TYPE_P2P) + continue; + if (prBssInfo->eConnectionState == + MEDIA_STATE_CONNECTED || + (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT + && prBssInfo->eIntendOPMode == OP_MODE_NUM)) { + *prBand = prBssInfo->eBand; + *pucPrimaryChannel = prBssInfo->ucPrimaryChannel; + return TRUE; + } + } +#endif + return FALSE; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void cnmAisInfraConnectNotify(struct ADAPTER *prAdapter) +{ +#if CFG_ENABLE_BT_OVER_WIFI + struct BSS_INFO *prBssInfo, *prAisBssInfo, *prBowBssInfo; + uint8_t i; + + ASSERT(prAdapter); + + prAisBssInfo = NULL; + prBowBssInfo = NULL; + + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + + if (prBssInfo && IS_BSS_ACTIVE(prBssInfo)) { + if (IS_BSS_AIS(prBssInfo)) + prAisBssInfo = prBssInfo; + else if (IS_BSS_BOW(prBssInfo)) + prBowBssInfo = prBssInfo; + } + } + + if (prAisBssInfo && prBowBssInfo + && 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t cnmAisIbssIsPermitted(struct ADAPTER + *prAdapter) +{ + struct BSS_INFO *prBssInfo; + uint8_t i; + + ASSERT(prAdapter); + + /* P2P device network shall be included */ + for (i = 0; i <= prAdapter->ucHwBssIdNum; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + + if (prBssInfo && IS_BSS_ACTIVE(prBssInfo) + && !IS_BSS_AIS(prBssInfo)) + return FALSE; + } + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param (none) + * + * @return TRUE: permitted + * FALSE: Not permitted + */ +/*----------------------------------------------------------------------------*/ +u_int8_t cnmP2PIsPermitted(struct ADAPTER *prAdapter) +{ + struct BSS_INFO *prBssInfo; + uint8_t i; + u_int8_t fgBowIsActive; + + ASSERT(prAdapter); + + fgBowIsActive = FALSE; + + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + + if (prBssInfo && IS_BSS_ACTIVE(prBssInfo)) { + if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) + return FALSE; + else if (IS_BSS_BOW(prBssInfo)) + fgBowIsActive = TRUE; + } + } + +#if CFG_ENABLE_BT_OVER_WIFI + if (fgBowIsActive) { + /* Notify BOW to do deactivation */ + bowNotifyAllLinkDisconnected(prAdapter); + } +#endif + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param (none) + * + * @return TRUE: permitted + * FALSE: Not permitted + */ +/*----------------------------------------------------------------------------*/ +u_int8_t cnmBowIsPermitted(struct ADAPTER *prAdapter) +{ + struct BSS_INFO *prBssInfo; + uint8_t i; + + ASSERT(prAdapter); + + /* P2P device network shall be included */ + for (i = 0; i <= prAdapter->ucHwBssIdNum; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + + if (prBssInfo && IS_BSS_ACTIVE(prBssInfo) && + (IS_BSS_P2P(prBssInfo) + || prBssInfo->eCurrentOPMode == OP_MODE_IBSS)) { + return FALSE; + } + } + + return TRUE; +} + + + +static uint8_t cnmGetAPBwPermitted(struct ADAPTER + *prAdapter, uint8_t ucBssIndex) +{ + struct BSS_INFO *prBssInfo; + uint8_t ucAPBandwidth = MAX_BW_160MHZ; + struct BSS_DESC *prBssDesc = NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *)NULL; + uint8_t i = 0; + uint8_t ucOffset = (MAX_BW_80MHZ - CW_80MHZ); + + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex); + + + if (IS_BSS_AIS(prBssInfo)) { + /*AIS station mode*/ + prBssDesc + = aisGetTargetBssDesc(prAdapter, ucBssIndex); + } else if (IS_BSS_P2P(prBssInfo)) { + /* P2P mode */ + + for (i = 0 ; i < BSS_P2P_NUM; i++) { + + if (!prAdapter->rWifiVar.aprP2pRoleFsmInfo[i]) + continue; + + if (prAdapter->rWifiVar.aprP2pRoleFsmInfo[i]->ucBssIndex + == + ucBssIndex) + break; + + } + + if (i >= BSS_P2P_NUM) { + prP2pRoleFsmInfo = NULL; + } else { + prP2pRoleFsmInfo = + prAdapter->rWifiVar.aprP2pRoleFsmInfo[i]; + + /*only GC need to consider GO's BW*/ + if (!p2pFuncIsAPMode( + prAdapter->rWifiVar.prP2PConnSettings[ + prBssInfo->u4PrivateData])) { + prBssDesc = prP2pRoleFsmInfo->rJoinInfo + .prTargetBssDesc; + } + + } + + + } + + if (prBssDesc) { + if (prBssDesc->eChannelWidth == CW_20_40MHZ) { + if ((prBssDesc->eSco == CHNL_EXT_SCA) + || (prBssDesc->eSco == CHNL_EXT_SCB)) + ucAPBandwidth = MAX_BW_40MHZ; + else + ucAPBandwidth = MAX_BW_20MHZ; + } else { + ucAPBandwidth = prBssDesc->eChannelWidth + ucOffset; + } + + } + + return ucAPBandwidth; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param (none) + * + * @return TRUE: permitted + * FALSE: Not permitted + */ +/*----------------------------------------------------------------------------*/ +u_int8_t cnmBss40mBwPermitted(struct ADAPTER *prAdapter, + uint8_t ucBssIndex) +{ + ASSERT(prAdapter); + + /* 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 + */ + + /* Decide max bandwidth by feature option */ + if (cnmGetBssMaxBw(prAdapter, + ucBssIndex) < MAX_BW_40MHZ) + return FALSE; + + /*check AP or GO capbility for Station or GC */ + if (cnmGetAPBwPermitted(prAdapter, + ucBssIndex) < MAX_BW_40MHZ) + return FALSE; +#if 0 + /* Decide max by other BSS */ + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + if (i != ucBssIndex) { + prBssInfo = prAdapter->aprBssInfo[i]; + + if (prBssInfo && IS_BSS_ACTIVE(prBssInfo) && + (prBssInfo->fg40mBwAllowed + || prBssInfo->fgAssoc40mBwAllowed)) + return FALSE; + } + } +#endif + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param (none) + * + * @return TRUE: permitted + * FALSE: Not permitted + */ +/*----------------------------------------------------------------------------*/ +u_int8_t cnmBss80mBwPermitted(struct ADAPTER *prAdapter, + uint8_t ucBssIndex) +{ + ASSERT(prAdapter); + + /* 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 + */ + + /* Check 40Mhz first */ + if (!cnmBss40mBwPermitted(prAdapter, ucBssIndex)) + return FALSE; + + /* Decide max bandwidth by feature option */ + if (cnmGetBssMaxBw(prAdapter, + ucBssIndex) < MAX_BW_80MHZ) + return FALSE; + + /*check AP or GO capbility for Station or GC */ + if (cnmGetAPBwPermitted(prAdapter, + ucBssIndex) < MAX_BW_80MHZ) + return FALSE; + + return TRUE; +} + +uint8_t cnmGetBssMaxBw(struct ADAPTER *prAdapter, + uint8_t ucBssIndex) +{ + struct BSS_INFO *prBssInfo; + uint8_t ucMaxBandwidth = + MAX_BW_80_80_MHZ; /*chip capability*/ + struct BSS_DESC *prBssDesc = NULL; + enum ENUM_BAND eBand = BAND_NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct P2P_CONNECTION_REQ_INFO *prP2pConnReqInfo = + (struct P2P_CONNECTION_REQ_INFO *) NULL; +#if (CFG_SUPPORT_SINGLE_SKU == 1) + uint8_t ucChannelBw = MAX_BW_80_80_MHZ; +#endif + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex); + + if (IS_BSS_AIS(prBssInfo)) { + /* STA mode */ + + + /* should check Bss_info could be used or not + *the info might not be trustable before state3 + */ + + prBssDesc = + aisGetTargetBssDesc(prAdapter, ucBssIndex); + if (prBssDesc) + eBand = prBssDesc->eBand; + else + eBand = prBssInfo->eBand; + + + ASSERT(eBand != BAND_NULL); + + if (eBand == BAND_2G4) + ucMaxBandwidth = prAdapter->rWifiVar.ucSta2gBandwidth; + else + ucMaxBandwidth = prAdapter->rWifiVar.ucSta5gBandwidth; + + if (ucMaxBandwidth > prAdapter->rWifiVar.ucStaBandwidth) + ucMaxBandwidth = prAdapter->rWifiVar.ucStaBandwidth; + } else if (IS_BSS_P2P(prBssInfo)) { + prP2pRoleFsmInfo = p2pFuncGetRoleByBssIdx(prAdapter, + ucBssIndex); + if (!prAdapter->rWifiVar.ucApChnlDefFromCfg + && prP2pRoleFsmInfo + && prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + prP2pConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + ucMaxBandwidth = prP2pConnReqInfo->eChnlBw; + } else { + /* AP mode */ + if (p2pFuncIsAPMode( + prAdapter->rWifiVar.prP2PConnSettings[ + prBssInfo->u4PrivateData])) { + if (prBssInfo->eBand == BAND_2G4) + ucMaxBandwidth = prAdapter->rWifiVar + .ucAp2gBandwidth; + else + ucMaxBandwidth = prAdapter->rWifiVar + .ucAp5gBandwidth; + + if (ucMaxBandwidth + > prAdapter->rWifiVar.ucApBandwidth) + ucMaxBandwidth = prAdapter->rWifiVar + .ucApBandwidth; + } + /* P2P mode */ + else { + if (prBssInfo->eBand == BAND_2G4) + ucMaxBandwidth = prAdapter->rWifiVar + .ucP2p2gBandwidth; + else + ucMaxBandwidth = prAdapter->rWifiVar + .ucP2p5gBandwidth; + } + + } + + } + +#if (CFG_SUPPORT_SINGLE_SKU == 1) + if (IS_BSS_AIS(prBssInfo) && prBssDesc) + ucChannelBw = rlmDomainGetChannelBw(prBssDesc->ucChannelNum); + else + ucChannelBw = + rlmDomainGetChannelBw(prBssInfo->ucPrimaryChannel); + if (ucMaxBandwidth > ucChannelBw) + ucMaxBandwidth = ucChannelBw; +#endif + DBGLOG_LIMITED(CNM, TRACE, "pCH=%d, BW=%d\n", + prBssInfo->ucPrimaryChannel, ucMaxBandwidth); + + return ucMaxBandwidth; +} + + +uint8_t cnmGetBssMaxBwToChnlBW(struct ADAPTER + *prAdapter, + uint8_t ucBssIndex) +{ + uint8_t ucMaxBandwidth = cnmGetBssMaxBw(prAdapter, + ucBssIndex); + return ucMaxBandwidth == MAX_BW_20MHZ ? ucMaxBandwidth : + (ucMaxBandwidth - 1); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Search available HW ID and BSS_INFO structure and initialize + * these parameters, i.e., fgIsNetActive, ucBssIndex, eNetworkType + * and ucOwnMacIndex + * + * @param (none) + * + * @return + */ +/*----------------------------------------------------------------------------*/ +struct BSS_INFO *cnmGetBssInfoAndInit(struct ADAPTER *prAdapter, + enum ENUM_NETWORK_TYPE eNetworkType, + u_int8_t fgIsP2pDevice) +{ + struct BSS_INFO *prBssInfo; + uint8_t i, ucBssIndex, ucOwnMacIdx; + + ASSERT(prAdapter); + + /*specific case for p2p device scan*/ + if (eNetworkType == NETWORK_TYPE_P2P && fgIsP2pDevice) { + prBssInfo = + prAdapter->aprBssInfo[prAdapter->ucP2PDevBssIdx]; + + prBssInfo->fgIsInUse = TRUE; + prBssInfo->ucBssIndex = prAdapter->ucP2PDevBssIdx; + prBssInfo->eNetworkType = eNetworkType; + prBssInfo->ucOwnMacIndex = prAdapter->ucHwBssIdNum; + + /* initialize wlan id and status for keys */ + prBssInfo->ucBMCWlanIndex = WTBL_RESERVED_ENTRY; + prBssInfo->wepkeyWlanIdx = WTBL_RESERVED_ENTRY; + for (i = 0; i < MAX_KEY_NUM; i++) { + prBssInfo->ucBMCWlanIndexSUsed[i] = FALSE; + prBssInfo->ucBMCWlanIndexS[i] = WTBL_RESERVED_ENTRY; + prBssInfo->wepkeyUsed[i] = FALSE; + } + + return prBssInfo; + } + + /*reserve ownMAC0 for MBSS*/ + ucOwnMacIdx = (eNetworkType == NETWORK_TYPE_MBSS) ? 0 : + 1; + + /* Find available HW set with the order 1,2,..*/ + do { + for (ucBssIndex = 0; + ucBssIndex < prAdapter->ucHwBssIdNum; + ucBssIndex++) { + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + + if (prBssInfo && prBssInfo->fgIsInUse + && ucOwnMacIdx == prBssInfo->ucOwnMacIndex) + break; + } + + if (ucBssIndex >= prAdapter->ucHwBssIdNum) { + /* No hit the ucOwnMacIndex could be + * assigned to this new bss + */ + break; + } + } while (++ucOwnMacIdx < prAdapter->ucHwBssIdNum); + + + /* should not dispatch P2P_DEV_BSS_INDEX (prAdapter->ucHwBssIdNum) + * to general bss. It means total BSS_INFO_NUM BSS are created, + * no more reseve for MBSS + */ + if (ucOwnMacIdx == prAdapter->ucHwBssIdNum) { + + for (ucBssIndex = 0; + ucBssIndex < prAdapter->ucHwBssIdNum; + ucBssIndex++) { + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + + /*If the Bss was alredy assigned, and in use*/ + if (prBssInfo && prBssInfo->fgIsInUse + && prBssInfo->ucOwnMacIndex == 0) + break; + } + + if (ucBssIndex >= prAdapter->ucHwBssIdNum) { + /* there is no NETWORK_TYPE_MBSS used before */ + + log_dbg(INIT, WARN, "[Warning] too much Bss in use, take reserve OwnMac(%d)for usage!\n", + ucOwnMacIdx); + ucOwnMacIdx = 0; + } + + } + + /* Find available BSS_INFO */ + for (ucBssIndex = 0; + ucBssIndex < prAdapter->ucHwBssIdNum; + ucBssIndex++) { + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + + if (prBssInfo && !prBssInfo->fgIsInUse) { + prBssInfo->fgIsInUse = TRUE; + prBssInfo->ucBssIndex = ucBssIndex; + prBssInfo->eNetworkType = eNetworkType; + prBssInfo->ucOwnMacIndex = ucOwnMacIdx; +#if (CFG_HW_WMM_BY_BSS == 1) + prBssInfo->ucWmmQueSet = DEFAULT_HW_WMM_INDEX; + prBssInfo->fgIsWmmInited = FALSE; +#endif + break; + } + } + + if (ucOwnMacIdx >= prAdapter->ucHwBssIdNum + || ucBssIndex >= prAdapter->ucHwBssIdNum) + prBssInfo = NULL; + if (prBssInfo) { + /* initialize wlan id and status for keys */ + prBssInfo->ucBMCWlanIndex = WTBL_RESERVED_ENTRY; + prBssInfo->wepkeyWlanIdx = WTBL_RESERVED_ENTRY; + for (i = 0; i < MAX_KEY_NUM; i++) { + prBssInfo->ucBMCWlanIndexSUsed[i] = FALSE; + prBssInfo->ucBMCWlanIndexS[i] = WTBL_RESERVED_ENTRY; + prBssInfo->wepkeyUsed[i] = FALSE; + } + } + return prBssInfo; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Search available HW ID and BSS_INFO structure and initialize + * these parameters, i.e., ucBssIndex, eNetworkType and ucOwnMacIndex + * + * @param (none) + * + * @return + */ +/*----------------------------------------------------------------------------*/ +void cnmFreeBssInfo(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo) +{ + ASSERT(prAdapter); + ASSERT(prBssInfo); + + prBssInfo->fgIsInUse = FALSE; +} + +#if CFG_SUPPORT_DBDC +/*----------------------------------------------------------------------------*/ +/*! + * @brief Init DBDC + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void cnmInitDbdcSetting(IN struct ADAPTER *prAdapter) +{ + struct CNM_OPMODE_BSS_REQ *prOpModeReq; + uint8_t ucBssLoopIndex; + + DBDC_SET_WMMBAND_FW_AUTO_DEFAULT(); + g_rDbdcInfo.fgHasSentCmd = FALSE; + g_rDbdcInfo.fgPostpondEnterAG = FALSE; + g_rDbdcInfo.fgPostpondLeaveAG = FALSE; + g_rDbdcInfo.rPeivilegeLockTime = 0; + + /* Parameter decision */ + switch (prAdapter->rWifiVar.eDbdcMode) { + case ENUM_DBDC_MODE_DISABLED: + cnmUpdateDbdcSetting(prAdapter, FALSE); + break; + + case ENUM_DBDC_MODE_DYNAMIC: + g_rDbdcInfo.eDbdcFsmCurrState = + ENUM_DBDC_FSM_STATE_DISABLE_IDLE; + g_rDbdcInfo.eDbdcFsmPrevState = + ENUM_DBDC_FSM_STATE_DISABLE_IDLE; + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_DISABLE_IDLE; + + cnmTimerInitTimer(prAdapter, + &g_rDbdcInfo.rDbdcGuardTimer, + (PFN_MGMT_TIMEOUT_FUNC)cnmDbdcGuardTimerCallback, + (unsigned long) NULL); + + g_rDbdcInfo.eDdbcGuardTimerType = + ENUM_DBDC_GUARD_TIMER_NONE; + g_rDbdcInfo.fgReqPrivelegeLock = FALSE; + LINK_INITIALIZE(&g_rDbdcInfo.rPendingMsgList); + g_rDbdcInfo.fgDbdcDisableOpmodeChangeDone = TRUE; + + for (ucBssLoopIndex = 0; + ucBssLoopIndex < prAdapter->ucHwBssIdNum; + ucBssLoopIndex++) + g_rDbdcInfo.eBssOpModeState[ucBssLoopIndex] = + ENUM_OPMODE_STATE_DONE; + + cnmUpdateDbdcSetting(prAdapter, FALSE); + break; + + case ENUM_DBDC_MODE_STATIC: + for (ucBssLoopIndex = 0; + ucBssLoopIndex < prAdapter->ucHwBssIdNum; + ucBssLoopIndex++) { + prOpModeReq = + &(g_arBssOpControl[ucBssLoopIndex]. + arReqPool[CNM_OPMODE_REQ_DBDC]); + prOpModeReq->fgEnable = TRUE; + prOpModeReq->ucOpRxNss = 1; + prOpModeReq->ucOpTxNss = 1; + } + cnmUpdateDbdcSetting(prAdapter, TRUE); + + /* Just resue dynamic DBDC FSM handler. */ + cnmDbdcFsmEntryFunc_ENABLE_IDLE(prAdapter); + break; + + default: + log_dbg(CNM, ERROR, "[DBDC]Incorrect DBDC mode %u\n", + prAdapter->rWifiVar.eDbdcMode); + break; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Check A+G Condition + * + * @param (none) + * + * @return TRUE: A+G, FALSE: NOT A+G + */ +/*----------------------------------------------------------------------------*/ +static u_int8_t cnmDbdcIsAGConcurrent( + IN struct ADAPTER *prAdapter, + IN enum ENUM_BAND eRfBand_Connecting) +{ + struct BSS_INFO *prBssInfo; + uint8_t ucBssIndex; + enum ENUM_BAND eBandCompare = eRfBand_Connecting; + u_int8_t fgAGConcurrent = FALSE; + enum ENUM_BAND eBssBand[BSSID_NUM] = {BAND_NULL}; + + for (ucBssIndex = 0; + ucBssIndex < prAdapter->ucHwBssIdNum; ucBssIndex++) { + + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + + if (IS_BSS_NOT_ALIVE(prAdapter, prBssInfo)) + continue; + + if (prBssInfo->eBand != BAND_2G4 + && prBssInfo->eBand != BAND_5G) + continue; + + eBssBand[ucBssIndex] = prBssInfo->eBand; + + if (eBandCompare != BAND_2G4 && eBandCompare != BAND_5G) + eBandCompare = prBssInfo->eBand; + + if (eBandCompare != prBssInfo->eBand) + fgAGConcurrent = TRUE; /*A+G*/ + } + + log_dbg(CNM, INFO, "[DBDC] BSS AG[%u.%u.%u.%u][%u]\n", + eBssBand[BSSID_0], + eBssBand[BSSID_1], + eBssBand[BSSID_2], + eBssBand[BSSID_3], + eRfBand_Connecting); + + return fgAGConcurrent; /*NOT A+G*/ +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief MT6632 HW capability will change between BW160+NSS2 and BW80+NSS1 + * + * @param (none) + * + * @return TRUE: WAIT/WAIT FAIL/Done Success/Done Fail + */ +/*----------------------------------------------------------------------------*/ +static enum ENUM_DBDC_PROTOCOL_STATUS_T cnmDbdcOpmodeChangeAndWait( + IN struct ADAPTER *prAdapter, + IN u_int8_t fgDbdcEn) +{ + uint8_t ucBssIndex; + uint8_t ucTRxNss; + struct BSS_INFO *prBssInfo; + enum ENUM_CNM_OPMODE_REQ_STATUS eStatus; + enum ENUM_DBDC_PROTOCOL_STATUS_T eRetVar = + ENUM_DBDC_PROTOCOL_STATUS_DONE_SUCCESS; + +#define IS_BSS_CLIENT(_prBssInfo) \ +(_prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) + + /* Always there are only up to 4 (BSSID_NUM) connected BSS. */ + for (ucBssIndex = 0; + ucBssIndex < prAdapter->ucHwBssIdNum && ucBssIndex < BSSID_NUM; + ucBssIndex++) { + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + ucTRxNss = fgDbdcEn ? + 1 : wlanGetSupportNss(prAdapter, ucBssIndex); + + if (IS_BSS_ALIVE(prAdapter, prBssInfo)) { + eStatus = cnmOpModeSetTRxNss(prAdapter, + ucBssIndex, + CNM_OPMODE_REQ_DBDC, + fgDbdcEn, + ucTRxNss, /* [DBDC] RxNss = TxNss */ + ucTRxNss); + + log_dbg(CNM, INFO, "[DBDC] BSS index[%u] to TRxNSS %u Mode:%s, status %u\n", + ucBssIndex, + ucTRxNss, + IS_BSS_CLIENT(prBssInfo) ? "Client" : "Master", + eStatus); + + switch (eStatus) { + case CNM_OPMODE_REQ_STATUS_RUNNING: + case CNM_OPMODE_REQ_STATUS_DEFER: + g_rDbdcInfo.fgDbdcDisableOpmodeChangeDone + = FALSE; + g_rDbdcInfo.eBssOpModeState[ucBssIndex] + = ENUM_OPMODE_STATE_WAIT; + eRetVar = ENUM_DBDC_PROTOCOL_STATUS_WAIT; + + break; + + case CNM_OPMODE_REQ_STATUS_SUCCESS: + g_rDbdcInfo.eBssOpModeState[ucBssIndex] + = ENUM_OPMODE_STATE_DONE; + break; + + case CNM_OPMODE_REQ_STATUS_INVALID_PARAM: + g_rDbdcInfo.eBssOpModeState[ucBssIndex] + = ENUM_OPMODE_STATE_FAIL; + +#define __SUCCESS__ ENUM_DBDC_PROTOCOL_STATUS_DONE_SUCCESS +#define __FAIL__ ENUM_DBDC_PROTOCOL_STATUS_DONE_FAIL + if (eRetVar == __SUCCESS__) + eRetVar = __FAIL__; +#undef __SUCCESS__ +#undef __FAIL__ + + break; + + default: + ASSERT(0); + break; + } + } else { + /* When DBDC is enabled, we limit all BSSes' OpTRxNss. + * Use the same API to update control table for + * inactive BSS. + */ + cnmOpModeSetTRxNss(prAdapter, + ucBssIndex, + CNM_OPMODE_REQ_DBDC, + fgDbdcEn, + ucTRxNss, /* [DBDC] RxNss = TxNss */ + ucTRxNss); + g_rDbdcInfo.eBssOpModeState[ucBssIndex] + = ENUM_OPMODE_STATE_DONE; + } + } + + return eRetVar; +} + + +void cnmDbdcOpModeChangeDoneCallback( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN bool fgSuccess) +{ + uint8_t ucBssLoopIndex; + bool fgIsAllActionFrameSuccess = true; + + if (fgSuccess) + g_rDbdcInfo.eBssOpModeState[ucBssIndex] = + ENUM_OPMODE_STATE_DONE; + else + g_rDbdcInfo.eBssOpModeState[ucBssIndex] = + ENUM_OPMODE_STATE_FAIL; + + log_dbg(CNM, INFO, "[DBDC] OPMODE STATE [%u/%u/%u/%u]\n", + g_rDbdcInfo.eBssOpModeState[BSSID_0], + g_rDbdcInfo.eBssOpModeState[BSSID_1], + g_rDbdcInfo.eBssOpModeState[BSSID_2], + g_rDbdcInfo.eBssOpModeState[BSSID_3]); + + for (ucBssLoopIndex = 0; + ucBssLoopIndex < prAdapter->ucHwBssIdNum; + ucBssLoopIndex++) { + + if (g_rDbdcInfo.eBssOpModeState[ucBssLoopIndex] == + ENUM_OPMODE_STATE_WAIT) + return; + + if (g_rDbdcInfo.eBssOpModeState[ucBssLoopIndex] == + ENUM_OPMODE_STATE_FAIL && + fgIsAllActionFrameSuccess == true) { + /* Some OP mode change FAIL */ + fgIsAllActionFrameSuccess = false; + } + } + + if (!g_rDbdcInfo.fgDbdcDisableOpmodeChangeDone) { + if (fgIsAllActionFrameSuccess) { + DBDC_FSM_EVENT_HANDLER(prAdapter, + DBDC_FSM_EVENT_ACTION_FRAME_ALL_SUCCESS); + } else { + DBDC_FSM_EVENT_HANDLER(prAdapter, + DBDC_FSM_EVENT_ACTION_FRAME_SOME_FAIL); + } + + g_rDbdcInfo.fgDbdcDisableOpmodeChangeDone = true; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Send DBDC Enable/Disable command to FW + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +uint32_t cnmUpdateDbdcSetting(IN struct ADAPTER *prAdapter, + IN u_int8_t fgDbdcEn) +{ + struct CMD_DBDC_SETTING rDbdcSetting; + struct CMD_DBDC_SETTING *prCmdBody; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + log_dbg(CNM, INFO, "[DBDC] %s\n", + fgDbdcEn ? "Enable" : "Disable"); + + /* Send event to FW */ + prCmdBody = (struct CMD_DBDC_SETTING *)&rDbdcSetting; + + kalMemZero(prCmdBody, sizeof(struct CMD_DBDC_SETTING)); + + prCmdBody->ucDbdcEn = fgDbdcEn; + + /* Parameter decision */ +#if (CFG_HW_WMM_BY_BSS == 1) + if (fgDbdcEn) { + u_int8_t ucWmmSetBitmapPerBSS; + struct BSS_INFO *prBssInfo; + u_int8_t ucBssIndex; + /* + * As DBDC enabled, for BSS use 2.4g Band, assign related + * WmmGroupSet bitmask to 1. + * This is used to indicate the WmmGroupSet is associated + * to Band#1 (otherwise, use for band#0) + */ + for (ucBssIndex = 0; ucBssIndex < prAdapter->ucHwBssIdNum; + ucBssIndex++) { + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + + if (!prBssInfo || prBssInfo->fgIsInUse == FALSE) + continue; + + if (prBssInfo->eBand == BAND_2G4) { + ucWmmSetBitmapPerBSS = prBssInfo->ucWmmQueSet; + prCmdBody->ucWmmBandBitmap |= + BIT(ucWmmSetBitmapPerBSS); + } + } + /* For P2P Device, we force it to use WMM3 */ + prBssInfo = prAdapter->aprBssInfo[P2P_DEV_BSS_INDEX]; + if (prBssInfo->eBand == BAND_2G4) + prCmdBody->ucWmmBandBitmap |= BIT(MAX_HW_WMM_INDEX); + } +#else + if (fgDbdcEn) + prCmdBody->ucWmmBandBitmap |= BIT(DBDC_2G_WMM_INDEX); +#endif + + /* FW uses ucWmmBandBitmap from driver if it does not support ver 1*/ + prCmdBody->ucCmdVer = 0x1; + prCmdBody->u2CmdLen = sizeof(struct CMD_DBDC_SETTING); + DBDC_UPDATE_CMD_WMMBAND_FW_AUTO(prCmdBody); + + if (g_rDbdcInfo.fgHasSentCmd == TRUE) + log_dbg(CNM, WARN, "Not event came back for DBDC\n"); + + g_rDbdcInfo.fgHasSentCmd = TRUE; + g_rDbdcInfo.fgCmdEn = fgDbdcEn; + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_DBDC_PARMS, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + + /* u4SetQueryInfoLen */ + sizeof(struct CMD_DBDC_SETTING), + + /* pucInfoBuffer */ + (uint8_t *)prCmdBody, + + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */); + + if (rStatus != WLAN_STATUS_PENDING) + DBGLOG(CNM, WARN, + "cnmUpdateDbdcSetting set cmd fail %d\n", rStatus); + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief DBDC FSM Entry + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static void +cnmDbdcFsmSteps( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_STATE_T eNextState, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent) +{ + /* Do entering Next State and do its initial function. */ + g_rDbdcInfo.eDbdcFsmPrevState = g_rDbdcInfo.eDbdcFsmCurrState; + g_rDbdcInfo.eDbdcFsmCurrState = eNextState; + g_rDbdcInfo.eDbdcFsmNextState = eNextState; + + log_dbg(CNM, INFO, "[DBDC] event %d state %d->%d\n", + eEvent, + g_rDbdcInfo.eDbdcFsmPrevState, + g_rDbdcInfo.eDbdcFsmCurrState); + + if (g_rDbdcInfo.eDbdcFsmPrevState != g_rDbdcInfo.eDbdcFsmCurrState) { + /* state change, call exit function of previous state */ + if (arDdbcFsmActionTable[g_rDbdcInfo.eDbdcFsmPrevState] + .pfExitFunc) { + arDdbcFsmActionTable[g_rDbdcInfo.eDbdcFsmPrevState] + .pfExitFunc(prAdapter); + } + + /* state change, call entry function of current state */ + if (arDdbcFsmActionTable[g_rDbdcInfo.eDbdcFsmCurrState] + .pfEntryFunc) { + arDdbcFsmActionTable[g_rDbdcInfo.eDbdcFsmCurrState] + .pfEntryFunc(prAdapter); + } + } +} + +u_int8_t +cnmDBDCIsReqPeivilegeLock(void) +{ + return g_rDbdcInfo.fgReqPrivelegeLock; +} + +static void +cnmDBDCFsmActionReqPeivilegeLock(void) +{ + g_rDbdcInfo.fgReqPrivelegeLock = TRUE; + g_rDbdcInfo.rPeivilegeLockTime = kalGetTimeTick(); + log_dbg(CNM, INFO, "[DBDC] ReqPrivelege Lock!!\n"); +} + +static void +cnmDBDCFsmActionReqPeivilegeUnLock(IN struct ADAPTER *prAdapter) +{ + struct MSG_CH_REQ *prPendingMsg; + struct MSG_HDR *prMsgHdr; + + g_rDbdcInfo.fgReqPrivelegeLock = FALSE; + g_rDbdcInfo.rPeivilegeLockTime = 0; + log_dbg(CNM, INFO, "[DBDC] ReqPrivelege Unlock!!\n"); + + while (!LINK_IS_EMPTY(&g_rDbdcInfo.rPendingMsgList)) { + + LINK_REMOVE_HEAD(&g_rDbdcInfo.rPendingMsgList, prMsgHdr, + struct MSG_HDR *); + + if (prMsgHdr) { + prPendingMsg = (struct MSG_CH_REQ *)prMsgHdr; + + log_dbg(CNM, INFO, "[DBDC] ChReq: send queued REQ of BSS %u Token %u\n", + prPendingMsg->ucBssIndex, + prPendingMsg->ucTokenID); + + cnmChMngrRequestPrivilege(prAdapter, + &prPendingMsg->rMsgHdr); + } else { + ASSERT(0); + } + } +} + +static void +cnmDbdcFsmEntryFunc_DISABLE_IDLE(IN struct ADAPTER *prAdapter) +{ + uint8_t ucWmmIndex; + uint8_t ucBssIndex; + struct CNM_OPMODE_BSS_CONTROL_T *prBssOpCtrl; + + if (cnmDBDCIsReqPeivilegeLock()) + cnmDBDCFsmActionReqPeivilegeUnLock(prAdapter); + + for (ucBssIndex = 0; ucBssIndex < prAdapter->ucHwBssIdNum; + ucBssIndex++) { + prBssOpCtrl = &(g_arBssOpControl[ucBssIndex]); + prBssOpCtrl->rRunning.fgIsRunning = false; + prBssOpCtrl->arReqPool[CNM_OPMODE_REQ_DBDC].fgEnable = false; + } + + for (ucWmmIndex = 0; ucWmmIndex < prAdapter->ucWmmSetNum; + ucWmmIndex++) { + cnmWmmQuotaSetMaxQuota( + prAdapter, + ucWmmIndex, + CNM_WMM_REQ_DBDC, + false, + 0 /* don't care */); + } +} + +static void +cnmDbdcFsmEntryFunc_WAIT_PROTOCOL_ENABLE(IN struct ADAPTER *prAdapter) +{ + if (!cnmDBDCIsReqPeivilegeLock()) + cnmDBDCFsmActionReqPeivilegeLock(); +} + +static void +cnmDbdcFsmEntryFunc_WAIT_HW_ENABLE(IN struct ADAPTER *prAdapter) +{ + uint32_t rStatus; + + if (!cnmDBDCIsReqPeivilegeLock()) + cnmDBDCFsmActionReqPeivilegeLock(); + + rStatus = cnmUpdateDbdcSetting(prAdapter, TRUE); + + if (rStatus != WLAN_STATUS_PENDING) { + cnmDBDCFsmActionReqPeivilegeUnLock(prAdapter); + DBDC_FSM_EVENT_HANDLER(prAdapter, + DBDC_FSM_EVENT_ERR); + } +} + +static void +cnmDbdcFsmEntryFunc_ENABLE_GUARD(IN struct ADAPTER *prAdapter) +{ + if (timerPendingTimer(&g_rDbdcInfo.rDbdcGuardTimer)) { + log_dbg(CNM, WARN, + "[DBDC] Guard Timer type %u should not exist, stop it\n", + g_rDbdcInfo.eDdbcGuardTimerType); + cnmTimerStopTimer(prAdapter, + &g_rDbdcInfo.rDbdcGuardTimer); + g_rDbdcInfo.eDdbcGuardTimerType = + ENUM_DBDC_GUARD_TIMER_NONE; + } + DBDC_SET_GUARD_TIME(prAdapter, DBDC_ENABLE_GUARD_TIME); +} + +static void +cnmDbdcFsmEntryFunc_ENABLE_IDLE( + IN struct ADAPTER *prAdapter +) +{ + uint8_t ucWmmIndex; + + for (ucWmmIndex = 0; ucWmmIndex < prAdapter->ucWmmSetNum; + ucWmmIndex++) { + cnmWmmQuotaSetMaxQuota( + prAdapter, + ucWmmIndex, + CNM_WMM_REQ_DBDC, + true, + DBDC_WMM_TX_QUOTA); + } +} + + +static void +cnmDbdcFsmEntryFunc_WAIT_HW_DISABLE(IN struct ADAPTER *prAdapter) +{ + uint32_t rStatus; + +#if (CFG_SUPPORT_DBDC_NO_BLOCKING_OPMODE) + if (!cnmDBDCIsReqPeivilegeLock()) + cnmDBDCFsmActionReqPeivilegeLock(); +#endif + + rStatus = cnmUpdateDbdcSetting(prAdapter, FALSE); + + if (rStatus != WLAN_STATUS_PENDING) { + cnmDBDCFsmActionReqPeivilegeUnLock(prAdapter); + DBDC_FSM_EVENT_HANDLER(prAdapter, + DBDC_FSM_EVENT_ERR); + } +} + +static void +cnmDbdcFsmEntryFunc_DISABLE_GUARD(IN struct ADAPTER *prAdapter) +{ + /* Do nothing if we will enter A+G immediately */ + if (g_rDbdcInfo.fgPostpondEnterAG) + return; + + if (timerPendingTimer(&g_rDbdcInfo.rDbdcGuardTimer)) { + log_dbg(CNM, WARN, + "[DBDC] Guard Timer type %u should not exist, stop it\n", + g_rDbdcInfo.eDdbcGuardTimerType); + cnmTimerStopTimer(prAdapter, + &g_rDbdcInfo.rDbdcGuardTimer); + g_rDbdcInfo.eDdbcGuardTimerType = + ENUM_DBDC_GUARD_TIMER_NONE; + } + DBDC_SET_GUARD_TIME(prAdapter, DBDC_DISABLE_GUARD_TIME); + + cnmDbdcOpmodeChangeAndWait(prAdapter, FALSE); +} + +static void +cnmDbdcFsmEventHandler_DISABLE_IDLE( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent) +{ + switch (eEvent) { + case DBDC_FSM_EVENT_BSS_DISCONNECT_LEAVE_AG: + /* Do Nothing */ + break; + + case DBDC_FSM_EVENT_BSS_CONNECTING_ENTER_AG: + /* Enable DBDC */ + switch (cnmDbdcOpmodeChangeAndWait(prAdapter, TRUE)) { + case ENUM_DBDC_PROTOCOL_STATUS_WAIT: + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_WAIT_PROTOCOL_ENABLE; + break; + + case ENUM_DBDC_PROTOCOL_STATUS_DONE_SUCCESS: + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_WAIT_HW_ENABLE; + break; + + case ENUM_DBDC_PROTOCOL_STATUS_DONE_FAIL: +#if (CFG_SUPPORT_DBDC_NO_BLOCKING_OPMODE) + log_dbg(CNM, WARN, + "[DBDC] OPMode Fail, ForceEn at state %d\n", + g_rDbdcInfo.eDbdcFsmCurrState); + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_WAIT_HW_ENABLE; + break; +#endif + + default: + break; + } + break; + + case DBDC_FSM_EVENT_SWITCH_GUARD_TIME_TO: + case DBDC_FSM_EVENT_DISABLE_COUNT_DOWN_TO: + case DBDC_FSM_EVENT_ACTION_FRAME_ALL_SUCCESS: + case DBDC_FSM_EVENT_ACTION_FRAME_SOME_FAIL: + case DBDC_FSM_EVENT_DBDC_HW_SWITCH_DONE: + /* ABNORMAL CASE*/ + DBDC_FSM_MSG_WRONG_EVT(eEvent); + break; + default: + /* WRONG EVENT */ + DBDC_FSM_MSG_ERROR_EVT(eEvent); + break; + } + + cnmDbdcFsmSteps(prAdapter, g_rDbdcInfo.eDbdcFsmNextState, eEvent); +} + +static void +cnmDbdcFsmEventHandler_WAIT_PROTOCOL_ENABLE( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent) +{ + switch (eEvent) { + case DBDC_FSM_EVENT_BSS_DISCONNECT_LEAVE_AG: + /* Stop Enabling DBDC */ + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_DISABLE_IDLE; + break; + + case DBDC_FSM_EVENT_BSS_CONNECTING_ENTER_AG: + /* IGNORE */ + break; + + case DBDC_FSM_EVENT_SWITCH_GUARD_TIME_TO: + case DBDC_FSM_EVENT_DISABLE_COUNT_DOWN_TO: + /* ABNORMAL CASE*/ + DBDC_FSM_MSG_WRONG_EVT(eEvent); + break; + + case DBDC_FSM_EVENT_ACTION_FRAME_ALL_SUCCESS: + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_WAIT_HW_ENABLE; + break; + + case DBDC_FSM_EVENT_ACTION_FRAME_SOME_FAIL: +#if (CFG_SUPPORT_DBDC_NO_BLOCKING_OPMODE) + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_WAIT_HW_ENABLE; + log_dbg(CNM, WARN, + "[DBDC] OPMode Fail, ForceEn at state %d\n", + g_rDbdcInfo.eDbdcFsmCurrState); +#else + /* Not recover anything. Stop Enable DBDC */ + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_DISABLE_IDLE; +#endif + + break; + + case DBDC_FSM_EVENT_DBDC_HW_SWITCH_DONE: + /* ABNORMAL CASE*/ + DBDC_FSM_MSG_WRONG_EVT(eEvent); + break; + + default: + /* WRONG EVENT */ + DBDC_FSM_MSG_ERROR_EVT(eEvent); + break; + } + + cnmDbdcFsmSteps(prAdapter, g_rDbdcInfo.eDbdcFsmNextState, eEvent); +} + +static void +cnmDbdcFsmEventHandler_WAIT_HW_ENABLE( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent) +{ + /* Prepare to Enable DBDC */ + + switch (eEvent) { + case DBDC_FSM_EVENT_BSS_DISCONNECT_LEAVE_AG: + g_rDbdcInfo.fgPostpondLeaveAG = TRUE; + break; + + case DBDC_FSM_EVENT_BSS_CONNECTING_ENTER_AG: + g_rDbdcInfo.fgPostpondLeaveAG = FALSE; + break; + + case DBDC_FSM_EVENT_SWITCH_GUARD_TIME_TO: + case DBDC_FSM_EVENT_DISABLE_COUNT_DOWN_TO: + case DBDC_FSM_EVENT_ACTION_FRAME_ALL_SUCCESS: + case DBDC_FSM_EVENT_ACTION_FRAME_SOME_FAIL: + /* ABNORMAL CASE*/ + DBDC_FSM_MSG_WRONG_EVT(eEvent); + break; + + case DBDC_FSM_EVENT_DBDC_HW_SWITCH_DONE: + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_ENABLE_GUARD; + break; + + case DBDC_FSM_EVENT_ERR: + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_DISABLE_IDLE; + g_rDbdcInfo.fgPostpondLeaveAG = FALSE; + break; + + default: + /* WRONG EVENT */ + DBDC_FSM_MSG_ERROR_EVT(eEvent); + break; + } + + cnmDbdcFsmSteps(prAdapter, g_rDbdcInfo.eDbdcFsmNextState, eEvent); + + /* Leave A+G immediately */ + if (eEvent == DBDC_FSM_EVENT_DBDC_HW_SWITCH_DONE && + g_rDbdcInfo.fgPostpondLeaveAG) { + DBDC_FSM_EVENT_HANDLER(prAdapter, + DBDC_FSM_EVENT_BSS_DISCONNECT_LEAVE_AG); + + g_rDbdcInfo.fgPostpondLeaveAG = FALSE; + } +} + + +static void +cnmDbdcFsmEventHandler_ENABLE_GUARD( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent) +{ + switch (eEvent) { + case DBDC_FSM_EVENT_BSS_DISCONNECT_LEAVE_AG: + /* stop guard timer */ + if (timerPendingTimer(&g_rDbdcInfo.rDbdcGuardTimer)) { + log_dbg(CNM, WARN, "[DBDC] Stop Guard Timer type %u\n", + g_rDbdcInfo.eDdbcGuardTimerType); + cnmTimerStopTimer(prAdapter, + &g_rDbdcInfo.rDbdcGuardTimer); + g_rDbdcInfo.eDdbcGuardTimerType = + ENUM_DBDC_GUARD_TIMER_NONE; + } + /* directly enter HW disable state */ + if (!cnmDbdcIsAGConcurrent(prAdapter, BAND_NULL)) + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_WAIT_HW_DISABLE; + break; + + case DBDC_FSM_EVENT_BSS_CONNECTING_ENTER_AG: + /* IGNORE */ + break; + + case DBDC_FSM_EVENT_SWITCH_GUARD_TIME_TO: + /* Exit DBDC if non A+G */ + if (!cnmDbdcIsAGConcurrent(prAdapter, BAND_NULL)) { + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_WAIT_HW_DISABLE; + } else { + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_ENABLE_IDLE; + } + break; + + case DBDC_FSM_EVENT_DISABLE_COUNT_DOWN_TO: + case DBDC_FSM_EVENT_ACTION_FRAME_ALL_SUCCESS: + case DBDC_FSM_EVENT_ACTION_FRAME_SOME_FAIL: + case DBDC_FSM_EVENT_DBDC_HW_SWITCH_DONE: + /* ABNORMAL CASE*/ + DBDC_FSM_MSG_WRONG_EVT(eEvent); + break; + + default: + /* WRONG EVENT */ + DBDC_FSM_MSG_ERROR_EVT(eEvent); + break; + } + + cnmDbdcFsmSteps(prAdapter, g_rDbdcInfo.eDbdcFsmNextState, eEvent); +} + +static void +cnmDbdcFsmEventHandler_ENABLE_IDLE( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent) +{ + switch (eEvent) { + case DBDC_FSM_EVENT_BSS_DISCONNECT_LEAVE_AG: + /* stop guard timer */ + if (timerPendingTimer(&g_rDbdcInfo.rDbdcGuardTimer)) { + log_dbg(CNM, WARN, "[DBDC] Guard Timer type %u should not exist, stop it\n", + g_rDbdcInfo.eDdbcGuardTimerType); + cnmTimerStopTimer(prAdapter, + &g_rDbdcInfo.rDbdcGuardTimer); + g_rDbdcInfo.eDdbcGuardTimerType = + ENUM_DBDC_GUARD_TIMER_NONE; + } + /* directly enter HW disable state */ + if (!cnmDbdcIsAGConcurrent(prAdapter, BAND_NULL)) + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_WAIT_HW_DISABLE; + break; + + case DBDC_FSM_EVENT_BSS_CONNECTING_ENTER_AG: + /* cancel DBDC disable countdown if exist */ + if (timerPendingTimer(&g_rDbdcInfo.rDbdcGuardTimer) && + g_rDbdcInfo.eDdbcGuardTimerType == + ENUM_DBDC_GUARD_TIMER_DISABLE_COUNT_DOWN) { + cnmTimerStopTimer(prAdapter, + &g_rDbdcInfo.rDbdcGuardTimer); + } + break; + + case DBDC_FSM_EVENT_SWITCH_GUARD_TIME_TO: + /* ABNORMAL CASE*/ + DBDC_FSM_MSG_WRONG_EVT(eEvent); + break; + + case DBDC_FSM_EVENT_DISABLE_COUNT_DOWN_TO: + if (!cnmDbdcIsAGConcurrent(prAdapter, BAND_NULL)) + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_WAIT_HW_DISABLE; + break; + + case DBDC_FSM_EVENT_ACTION_FRAME_ALL_SUCCESS: + case DBDC_FSM_EVENT_ACTION_FRAME_SOME_FAIL: + case DBDC_FSM_EVENT_DBDC_HW_SWITCH_DONE: + /* ABNORMAL CASE*/ + DBDC_FSM_MSG_WRONG_EVT(eEvent); + break; + + default: + /* WRONG EVENT */ + DBDC_FSM_MSG_ERROR_EVT(eEvent); + break; + } + + cnmDbdcFsmSteps(prAdapter, g_rDbdcInfo.eDbdcFsmNextState, eEvent); +} + +static void +cnmDbdcFsmEventHandler_WAIT_HW_DISABLE( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent) +{ + switch (eEvent) { + case DBDC_FSM_EVENT_BSS_DISCONNECT_LEAVE_AG: + g_rDbdcInfo.fgPostpondEnterAG = FALSE; + break; + + case DBDC_FSM_EVENT_BSS_CONNECTING_ENTER_AG: + g_rDbdcInfo.fgPostpondEnterAG = TRUE; + break; + + case DBDC_FSM_EVENT_SWITCH_GUARD_TIME_TO: + case DBDC_FSM_EVENT_DISABLE_COUNT_DOWN_TO: + case DBDC_FSM_EVENT_ACTION_FRAME_ALL_SUCCESS: + case DBDC_FSM_EVENT_ACTION_FRAME_SOME_FAIL: + /* ABNORMAL CASE*/ + DBDC_FSM_MSG_WRONG_EVT(eEvent); + break; + + case DBDC_FSM_EVENT_DBDC_HW_SWITCH_DONE: + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_DISABLE_GUARD; + break; + + case DBDC_FSM_EVENT_ERR: + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_ENABLE_IDLE; + g_rDbdcInfo.fgPostpondEnterAG = FALSE; + break; + + default: + /* WRONG EVENT */ + DBDC_FSM_MSG_ERROR_EVT(eEvent); + break; + } + + cnmDbdcFsmSteps(prAdapter, g_rDbdcInfo.eDbdcFsmNextState, eEvent); + + /* Enter A+G immediately */ + if (eEvent == DBDC_FSM_EVENT_DBDC_HW_SWITCH_DONE && + g_rDbdcInfo.fgPostpondEnterAG) { + DBDC_FSM_EVENT_HANDLER(prAdapter, + DBDC_FSM_EVENT_BSS_CONNECTING_ENTER_AG); + + g_rDbdcInfo.fgPostpondEnterAG = FALSE; + } +} + +static void +cnmDbdcFsmEventHandler_DISABLE_GUARD( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent) +{ + switch (eEvent) { + case DBDC_FSM_EVENT_BSS_DISCONNECT_LEAVE_AG: + /* IGNORE */ + break; + + case DBDC_FSM_EVENT_BSS_CONNECTING_ENTER_AG: + /* Enable DBDC */ + switch (cnmDbdcOpmodeChangeAndWait(prAdapter, TRUE)) { + case ENUM_DBDC_PROTOCOL_STATUS_WAIT: + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_WAIT_PROTOCOL_ENABLE; + break; + + case ENUM_DBDC_PROTOCOL_STATUS_DONE_SUCCESS: + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_WAIT_HW_ENABLE; + break; + + case ENUM_DBDC_PROTOCOL_STATUS_DONE_FAIL: +#if (CFG_SUPPORT_DBDC_NO_BLOCKING_OPMODE) + log_dbg(CNM, WARN, + "[DBDC] OPMode Fail, ForceEn at state %d\n", + g_rDbdcInfo.eDbdcFsmCurrState); + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_WAIT_HW_ENABLE; + break; +#endif + + default: + break; + } + break; + + case DBDC_FSM_EVENT_SWITCH_GUARD_TIME_TO: + +#define __PRO_ENABLE__ ENUM_DBDC_FSM_STATE_WAIT_PROTOCOL_ENABLE +#define __PRO_DISABLE__ ENUM_DBDC_FSM_STATE_WAIT_PROTOCOL_DISABLE +#define __HW_ENABLE__ ENUM_DBDC_FSM_STATE_WAIT_HW_ENABLE +#define __DISABLE__ ENUM_DBDC_FSM_STATE_DISABLE_IDLE +#define __STAT_WAIT__ ENUM_DBDC_PROTOCOL_STATUS_WAIT + + if (g_rDbdcInfo.fgDbdcDisableOpmodeChangeDone) { + if (cnmDbdcIsAGConcurrent(prAdapter, BAND_NULL)) { + switch (cnmDbdcOpmodeChangeAndWait( + prAdapter, TRUE)) { + case ENUM_DBDC_PROTOCOL_STATUS_WAIT: + g_rDbdcInfo.eDbdcFsmNextState = + __PRO_ENABLE__; + break; + case ENUM_DBDC_PROTOCOL_STATUS_DONE_SUCCESS: + g_rDbdcInfo.eDbdcFsmNextState = + __HW_ENABLE__; + break; + case ENUM_DBDC_PROTOCOL_STATUS_DONE_FAIL: +#if (CFG_SUPPORT_DBDC_NO_BLOCKING_OPMODE) + g_rDbdcInfo.eDbdcFsmNextState = + __HW_ENABLE__; + log_dbg(CNM, WARN, + "[DBDC] OPMode Fail, ForceEn at state %d\n", + g_rDbdcInfo.eDbdcFsmCurrState); +#else + if (cnmDbdcOpmodeChangeAndWait( + prAdapter, FALSE) + == __STAT_WAIT__) + g_rDbdcInfo.eDbdcFsmNextState = + __PRO_DISABLE__; + else + g_rDbdcInfo.eDbdcFsmNextState = + __DISABLE__; +#endif + break; + default: + break; + } + } else { + g_rDbdcInfo.eDbdcFsmNextState = + __DISABLE__; + } + } else { + g_rDbdcInfo.eDbdcFsmNextState = + __PRO_DISABLE__; + } + +#undef __PRO_ENABLE__ +#undef __PRO_DISABLE__ +#undef __HW_ENABLE__ +#undef __DISABLE__ +#undef __STAT_WAIT__ + + break; + + case DBDC_FSM_EVENT_DISABLE_COUNT_DOWN_TO: + /* ABNORMAL CASE */ + DBDC_FSM_MSG_WRONG_EVT(eEvent); + break; + + case DBDC_FSM_EVENT_ACTION_FRAME_ALL_SUCCESS: + case DBDC_FSM_EVENT_ACTION_FRAME_SOME_FAIL: + /* Do nothing */ + break; + + case DBDC_FSM_EVENT_DBDC_HW_SWITCH_DONE: + /* ABNORMAL CASE */ + DBDC_FSM_MSG_WRONG_EVT(eEvent); + break; + + default: + /* WRONG EVENT */ + DBDC_FSM_MSG_ERROR_EVT(eEvent); + break; + } + + cnmDbdcFsmSteps(prAdapter, g_rDbdcInfo.eDbdcFsmNextState, eEvent); +} + +static void +cnmDbdcFsmEventHandler_WAIT_PROTOCOL_DISABLE( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent) +{ + /* Prepare to Enable DBDC */ + + switch (eEvent) { + case DBDC_FSM_EVENT_BSS_DISCONNECT_LEAVE_AG: + /* Return to idle state to prevent getting stuck */ + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_DISABLE_IDLE; + break; + case DBDC_FSM_EVENT_BSS_CONNECTING_ENTER_AG: + /* IGNORE */ + break; + + case DBDC_FSM_EVENT_SWITCH_GUARD_TIME_TO: + case DBDC_FSM_EVENT_DISABLE_COUNT_DOWN_TO: + /* ABNORMAL CASE*/ + DBDC_FSM_MSG_WRONG_EVT(eEvent); + break; + +#define __PRO_ENABLE__ ENUM_DBDC_FSM_STATE_WAIT_PROTOCOL_ENABLE + + case DBDC_FSM_EVENT_ACTION_FRAME_ALL_SUCCESS: + case DBDC_FSM_EVENT_ACTION_FRAME_SOME_FAIL: + if (cnmDbdcIsAGConcurrent(prAdapter, BAND_NULL)) { + switch (cnmDbdcOpmodeChangeAndWait(prAdapter, TRUE)) { + case ENUM_DBDC_PROTOCOL_STATUS_WAIT: + g_rDbdcInfo.eDbdcFsmNextState = + __PRO_ENABLE__; + break; + case ENUM_DBDC_PROTOCOL_STATUS_DONE_SUCCESS: + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_WAIT_HW_ENABLE; + break; + case ENUM_DBDC_PROTOCOL_STATUS_DONE_FAIL: +#if (CFG_SUPPORT_DBDC_NO_BLOCKING_OPMODE) + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_WAIT_HW_ENABLE; + log_dbg(CNM, WARN, + "[DBDC] OPMode Fail, ForceEn at state %d\n", + g_rDbdcInfo.eDbdcFsmCurrState); +#else + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_DISABLE_IDLE; +#endif + break; + default: + break; + } + } else + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_DISABLE_IDLE; + break; + +#undef __PRO_ENABLE__ + + case DBDC_FSM_EVENT_DBDC_HW_SWITCH_DONE: + /* ABNORMAL CASE*/ + DBDC_FSM_MSG_WRONG_EVT(eEvent); + break; + + default: + /* WRONG EVENT */ + DBDC_FSM_MSG_ERROR_EVT(eEvent); + break; + } + + cnmDbdcFsmSteps(prAdapter, g_rDbdcInfo.eDbdcFsmNextState, eEvent); +} + +static void +cnmDbdcFsmExitFunc_WAIT_HW_ENABLE( + IN struct ADAPTER *prAdapter) +{ + cnmDBDCFsmActionReqPeivilegeUnLock(prAdapter); +} + +static void +cnmDbdcFsmExitFunc_WAIT_HW_DISABLE( + IN struct ADAPTER *prAdapter) +{ + /* Do not release privilege lock if we will enter A+G immediately */ + if (!g_rDbdcInfo.fgPostpondEnterAG) + cnmDBDCFsmActionReqPeivilegeUnLock(prAdapter); +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Get maximum bandwidth capability with considering DBDC mode + * + * @param (none) + * + * @return + */ +/*----------------------------------------------------------------------------*/ +uint8_t cnmGetDbdcBwCapability(IN struct ADAPTER + *prAdapter, + IN uint8_t ucBssIndex) +{ + uint8_t ucMaxBw = MAX_BW_20MHZ; + + ucMaxBw = cnmGetBssMaxBw(prAdapter, ucBssIndex); + + /* Can't use BW160 when DBDC enabled */ + if (USE_DBDC_CAPABILITY() && (ucMaxBw >= MAX_BW_160MHZ)) + ucMaxBw = MAX_BW_80MHZ; + + /* TODO: BW80+80 support */ + if (ucMaxBw == MAX_BW_80_80_MHZ) + ucMaxBw = MAX_BW_80MHZ; /* VHT should default support BW80 */ + + return ucMaxBw; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Run-time check if DBDC Need enable or update guard time. + * The WmmQ is set to the correct DBDC band before connetcting. + * It could make sure the TxPath is correct after connected. + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void cnmDbdcPreConnectionEnableDecision( + IN struct ADAPTER *prAdapter, + IN uint8_t ucChangedBssIndex, + IN enum ENUM_BAND eRfBand, + IN uint8_t ucPrimaryChannel, + IN uint8_t ucWmmQueIdx) +{ + log_dbg(CNM, INFO, "[DBDC] BSS %u Rf %u", ucChangedBssIndex, eRfBand); + + if (prAdapter->rWifiVar.eDbdcMode != ENUM_DBDC_MODE_DYNAMIC && + (prAdapter->rWifiVar.eDbdcMode != ENUM_DBDC_MODE_STATIC)) { + log_dbg(CNM, INFO, "[DBDC Debug] DBDC Mode %u Return", + prAdapter->rWifiVar.eDbdcMode); + return; + } + + if (prAdapter->rWifiVar.eDbdcMode == ENUM_DBDC_MODE_STATIC && + prAdapter->rWifiVar.fgDbDcModeEn) { + if (timerPendingTimer(&g_rDbdcInfo.rDbdcGuardTimer) && + g_rDbdcInfo.eDdbcGuardTimerType == + ENUM_DBDC_GUARD_TIMER_SWITCH_GUARD_TIME) { + /* update timer for connection retry */ + log_dbg(CNM, INFO, "[DBDC] DBDC guard time extend\n"); + cnmTimerStopTimer(prAdapter, + &g_rDbdcInfo.rDbdcGuardTimer); + cnmTimerStartTimer(prAdapter, + &g_rDbdcInfo.rDbdcGuardTimer, + DBDC_ENABLE_GUARD_TIME); + } + /* The DBDC is already ON, so renew WMM band information only */ + DBDC_SET_WMMBAND_FW_AUTO_BY_CHNL(ucPrimaryChannel, ucWmmQueIdx); + cnmUpdateDbdcSetting(prAdapter, TRUE); + return; + } + + if (timerPendingTimer(&g_rDbdcInfo.rDbdcGuardTimer) && + g_rDbdcInfo.eDdbcGuardTimerType + == ENUM_DBDC_GUARD_TIMER_SWITCH_GUARD_TIME) { + log_dbg(CNM, INFO, "[DBDC Debug] Guard Time Check"); + + if ((cnmDbdcIsAGConcurrent(prAdapter, eRfBand) && + !prAdapter->rWifiVar.fgDbDcModeEn) || + (!cnmDbdcIsAGConcurrent(prAdapter, eRfBand) && + prAdapter->rWifiVar.fgDbDcModeEn)) { + /* cancel Guard Time and change DBDC mode */ + cnmTimerStopTimer(prAdapter, + &g_rDbdcInfo.rDbdcGuardTimer); + g_rDbdcInfo.eDdbcGuardTimerType = + ENUM_DBDC_GUARD_TIMER_NONE; + } else { + log_dbg(CNM, INFO, "[DBDC Debug] Guard Time extend Return"); + cnmTimerStopTimer(prAdapter, + &g_rDbdcInfo.rDbdcGuardTimer); + cnmTimerStartTimer(prAdapter, + &g_rDbdcInfo.rDbdcGuardTimer, + DBDC_ENABLE_GUARD_TIME); + return; + } + } + + if (eRfBand != BAND_2G4 && eRfBand != BAND_5G) { + log_dbg(CNM, INFO, "[DBDC Debug] Wrong RF band Return"); + return; + } + + if (cnmDbdcIsAGConcurrent(prAdapter, eRfBand)) { + DBDC_SET_WMMBAND_FW_AUTO_BY_CHNL(ucPrimaryChannel, ucWmmQueIdx); + DBDC_FSM_EVENT_HANDLER(prAdapter, + DBDC_FSM_EVENT_BSS_CONNECTING_ENTER_AG); + } else { + DBDC_FSM_EVENT_HANDLER(prAdapter, + DBDC_FSM_EVENT_BSS_DISCONNECT_LEAVE_AG); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Run-time check if we need enable/disable DBDC or update guard time. + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void cnmDbdcRuntimeCheckDecision(IN struct ADAPTER + *prAdapter, + IN uint8_t ucChangedBssIndex) +{ + bool fgIsAgConcurrent; + + log_dbg(CNM, INFO, "[DBDC Debug] BSS %u", + ucChangedBssIndex); + + /* Only allow runtime switch for dynamic DBDC */ + if (prAdapter->rWifiVar.eDbdcMode != + ENUM_DBDC_MODE_DYNAMIC) { + log_dbg(CNM, INFO, "[DBDC Debug] DBDC Mode %u Return", + prAdapter->rWifiVar.eDbdcMode); + return; + } + + /* AGConcurrent status sync with DBDC satus. Do nothing. */ + fgIsAgConcurrent = cnmDbdcIsAGConcurrent(prAdapter, BAND_NULL); + if (fgIsAgConcurrent == prAdapter->rWifiVar.fgDbDcModeEn) + return; + + /* Only need to extend in DISABLE_GUARD for connection retry. + * If AGConcurrent status changes in ENABLE_GUARD, the FSM + * will go through DISABLE_GUARD state. It could make sure + * the interval of successive OPChange is larger than 4 sec + * (DBDC_ENABLE_GUARD_TIME). + */ + if (timerPendingTimer(&g_rDbdcInfo.rDbdcGuardTimer) && + g_rDbdcInfo.eDdbcGuardTimerType == + ENUM_DBDC_GUARD_TIMER_SWITCH_GUARD_TIME) { + + if (g_rDbdcInfo.eDbdcFsmCurrState == + ENUM_DBDC_FSM_STATE_DISABLE_GUARD) { + log_dbg(CNM, INFO, + "[DBDC] DBDC guard time extend, state %d\n", + g_rDbdcInfo.eDbdcFsmCurrState); + cnmTimerStopTimer(prAdapter, + &g_rDbdcInfo.rDbdcGuardTimer); + cnmTimerStartTimer(prAdapter, + &g_rDbdcInfo.rDbdcGuardTimer, + DBDC_ENABLE_GUARD_TIME); + } else + log_dbg(CNM, INFO, + "[DBDC] DBDC guard time, state %d\n", + g_rDbdcInfo.eDbdcFsmCurrState); + return; + } + + /* After COUNT_DOWN timeout in ENABLE_IDLE state, FSM will check + * AGConcurrent status agin. + */ + if (timerPendingTimer(&g_rDbdcInfo.rDbdcGuardTimer) && + g_rDbdcInfo.eDdbcGuardTimerType == + ENUM_DBDC_GUARD_TIMER_DISABLE_COUNT_DOWN) { + log_dbg(CNM, INFO, + "[DBDC Debug] Disable Countdown Return, state %d\n", + g_rDbdcInfo.eDbdcFsmCurrState); + return; + } + + if (cnmDbdcIsAGConcurrent(prAdapter, BAND_NULL)) { + DBDC_FSM_EVENT_HANDLER(prAdapter, + DBDC_FSM_EVENT_BSS_CONNECTING_ENTER_AG); + } else + DBDC_FSM_EVENT_HANDLER(prAdapter, + DBDC_FSM_EVENT_BSS_DISCONNECT_LEAVE_AG); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief DBDC Guard Time/Countdown Callback + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void cnmDbdcGuardTimerCallback(IN struct ADAPTER + *prAdapter, + IN unsigned long plParamPtr) +{ + log_dbg(CNM, INFO, "[DBDC Debug] Timer %u", + g_rDbdcInfo.eDdbcGuardTimerType); + + if (prAdapter->rWifiVar.eDbdcMode != + ENUM_DBDC_MODE_DYNAMIC) { + log_dbg(CNM, INFO, "[DBDC Debug] DBDC Mode %u Return", + prAdapter->rWifiVar.eDbdcMode); + return; + } + + if (g_rDbdcInfo.eDdbcGuardTimerType == + ENUM_DBDC_GUARD_TIMER_SWITCH_GUARD_TIME) { + + g_rDbdcInfo.eDdbcGuardTimerType = + ENUM_DBDC_GUARD_TIMER_NONE; + DBDC_FSM_EVENT_HANDLER(prAdapter, + DBDC_FSM_EVENT_SWITCH_GUARD_TIME_TO); + + } else if (g_rDbdcInfo.eDdbcGuardTimerType == + ENUM_DBDC_GUARD_TIMER_DISABLE_COUNT_DOWN) { + + g_rDbdcInfo.eDdbcGuardTimerType = + ENUM_DBDC_GUARD_TIMER_NONE; + DBDC_FSM_EVENT_HANDLER(prAdapter, + DBDC_FSM_EVENT_DISABLE_COUNT_DOWN_TO); + + } else + log_dbg(CNM, ERROR, "[DBDC] WRONG DBDC TO TYPE %u\n", + g_rDbdcInfo.eDdbcGuardTimerType); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief DBDC HW Switch done event + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void cnmDbdcEventHwSwitchDone(IN struct ADAPTER + *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct CMD_INFO *prCmdInfo; + u_int8_t fgDbdcEn; + + /* 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); + } + + /* Check DBDC state by FSM */ + if (g_rDbdcInfo.eDbdcFsmCurrState == + ENUM_DBDC_FSM_STATE_WAIT_HW_ENABLE) { + fgDbdcEn = true; + g_rDbdcInfo.fgHasSentCmd = false; + } else if (g_rDbdcInfo.eDbdcFsmCurrState == + ENUM_DBDC_FSM_STATE_WAIT_HW_DISABLE) { + fgDbdcEn = false; + g_rDbdcInfo.fgHasSentCmd = false; + } else if (g_rDbdcInfo.fgHasSentCmd == true) { + /* The "set_dbdc" test cmd may confuse original FSM. + * Besides, we do not config TxQuota for the testing cmd. + */ + log_dbg(CNM, INFO, + "[DBDC] switch event from cmd happen in state %u\n", + g_rDbdcInfo.eDbdcFsmCurrState); + g_rDbdcInfo.fgHasSentCmd = FALSE; + prAdapter->rWifiVar.fgDbDcModeEn = g_rDbdcInfo.fgCmdEn; + return; + } else { + log_dbg(CNM, ERROR, + "[DBDC] switch event happen in state %u\n", + g_rDbdcInfo.eDbdcFsmCurrState); + return; + } + + /* Change DBDC state */ + prAdapter->rWifiVar.fgDbDcModeEn = fgDbdcEn; + DBDC_FSM_EVENT_HANDLER(prAdapter, + DBDC_FSM_EVENT_DBDC_HW_SWITCH_DONE); +} + +#endif /*CFG_SUPPORT_DBDC*/ + + +enum ENUM_CNM_NETWORK_TYPE_T cnmGetBssNetworkType( + struct BSS_INFO *prBssInfo) +{ + if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) + return ENUM_CNM_NETWORK_TYPE_AIS; + else if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) { + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) + return ENUM_CNM_NETWORK_TYPE_P2P_GC; + else if (prBssInfo->eCurrentOPMode == + OP_MODE_ACCESS_POINT) + return ENUM_CNM_NETWORK_TYPE_P2P_GO; + } + return ENUM_CNM_NETWORK_TYPE_OTHER; +} + +u_int8_t cnmSapIsConcurrent(IN struct ADAPTER *prAdapter) +{ + if (prAdapter) + return (prAdapter->u4P2pMode == RUNNING_P2P_AP_MODE); + else + return FALSE; +} + +u_int8_t cnmSapIsActive(IN struct ADAPTER *prAdapter) +{ + return (cnmGetSapBssInfo(prAdapter) != NULL); +} + +struct BSS_INFO *cnmGetSapBssInfo(IN struct ADAPTER *prAdapter) +{ + struct BSS_INFO *prBssInfo; + uint8_t i; + + if (!prAdapter) + return NULL; + + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + + if (prBssInfo && + IS_BSS_P2P(prBssInfo) && + p2pFuncIsAPMode( + prAdapter->rWifiVar.prP2PConnSettings + [prBssInfo->u4PrivateData]) && + IS_NET_PWR_STATE_ACTIVE( + prAdapter, + prBssInfo->ucBssIndex)) + return prBssInfo; + } + + return NULL; +} + +uint8_t cnmSapChannelSwitchReq(IN struct ADAPTER *prAdapter, + IN struct RF_CHANNEL_INFO *prRfChannelInfo, + IN uint8_t ucRoleIdx) +{ + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct GL_P2P_INFO *prGlueP2pInfo = NULL; + struct MSG_P2P_SET_NEW_CHANNEL *prP2pSetNewChannelMsg = + (struct MSG_P2P_SET_NEW_CHANNEL *) NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct P2P_CONNECTION_REQ_INFO *prP2pConnReqInfo = + (struct P2P_CONNECTION_REQ_INFO *) NULL; + uint8_t ucBssIdx = 0; + + DBGLOG(P2P, INFO, + "role(%d) c=%d b=%d opw=%d\n", + ucRoleIdx, + prRfChannelInfo->ucChannelNum, + prRfChannelInfo->eBand, + prRfChannelInfo->ucChnlBw); + + /* Free chandef buffer */ + if (!prGlueInfo) { + DBGLOG(P2P, WARN, "glue info is not active\n"); + goto error; + } + prGlueP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + if (!prGlueP2pInfo) { + DBGLOG(P2P, WARN, "p2p glue info is not active\n"); + goto error; + } + if (prGlueP2pInfo->chandef != NULL) { + if (prGlueP2pInfo->chandef->chan) { + cnmMemFree(prGlueInfo->prAdapter, + prGlueP2pInfo->chandef->chan); + prGlueP2pInfo->chandef->chan = NULL; + } + cnmMemFree(prGlueInfo->prAdapter, + prGlueP2pInfo->chandef); + prGlueP2pInfo->chandef = NULL; + } + + /* Fill conn info */ + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, ucRoleIdx); + if (!prP2pRoleFsmInfo) + goto error; + prP2pConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + if (!prP2pConnReqInfo) + goto error; + + prP2pConnReqInfo->rChannelInfo.ucChannelNum = + prRfChannelInfo->ucChannelNum; + prP2pConnReqInfo->rChannelInfo.eBand = + prRfChannelInfo->eBand; + prP2pConnReqInfo->eChnlBw = + prRfChannelInfo->ucChnlBw; + + p2pFuncSetDfsState(DFS_STATE_INACTIVE); + + if (p2pFuncRoleToBssIdx( + prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) { + DBGLOG(P2P, WARN, "Incorrect role index"); + goto error; + } + + /* Set new channel */ + prP2pSetNewChannelMsg = (struct MSG_P2P_SET_NEW_CHANNEL *) + cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(*prP2pSetNewChannelMsg)); + if (prP2pSetNewChannelMsg == NULL) { + DBGLOG(P2P, WARN, + "prP2pSetNewChannelMsg alloc fail\n"); + goto error; + } + + prP2pSetNewChannelMsg->rMsgHdr.eMsgId = + MID_MNY_P2P_SET_NEW_CHANNEL; + prP2pSetNewChannelMsg->eChannelWidth = + (enum ENUM_CHANNEL_WIDTH) + rlmGetVhtOpBwByBssOpBw(prRfChannelInfo->ucChnlBw); + prP2pSetNewChannelMsg->ucRoleIdx = ucRoleIdx; + prP2pSetNewChannelMsg->ucBssIndex = ucBssIdx; + mboxSendMsg(prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prP2pSetNewChannelMsg, + MSG_SEND_METHOD_BUF); + + kalP2PSetRole(prGlueInfo, 2, ucRoleIdx); + + prGlueInfo->prP2PInfo[ucRoleIdx]->eChnlSwitchPolicy = + p2pFunDetermineChnlSwitchPolicy(prAdapter, ucBssIdx, + prRfChannelInfo); + + p2pFunNotifyChnlSwitch(prAdapter, ucBssIdx, + prGlueInfo->prP2PInfo[ucRoleIdx]->eChnlSwitchPolicy, + prRfChannelInfo); + + return 0; + +error: + + return -1; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Search available HW WMM index. +* +* @param (none) +* +* @return +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t cnmWmmIndexDecision( + IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo) +{ +#if (CFG_HW_WMM_BY_BSS == 1) + u_int8_t ucWmmIndex; + + for (ucWmmIndex = 0; ucWmmIndex < HW_WMM_NUM; ucWmmIndex++) { + if (prBssInfo && prBssInfo->fgIsInUse && + prBssInfo->fgIsWmmInited == FALSE) { + if (!(prAdapter->ucHwWmmEnBit & BIT(ucWmmIndex))) { + prAdapter->ucHwWmmEnBit |= BIT(ucWmmIndex); + prBssInfo->fgIsWmmInited = TRUE; + break; + } + } + } + return (ucWmmIndex < HW_WMM_NUM) ? ucWmmIndex : MAX_HW_WMM_INDEX; + +#else + /* Follow the same rule with cnmUpdateDbdcSetting */ + if (prBssInfo->eBand == BAND_5G) + return DBDC_5G_WMM_INDEX; + else + return (prAdapter->rWifiVar.eDbdcMode == + ENUM_DBDC_MODE_DISABLED) ? + DBDC_5G_WMM_INDEX : DBDC_2G_WMM_INDEX; +#endif +} +/*----------------------------------------------------------------------------*/ +/*! +* @brief Free BSS HW WMM index. +* +* @param (none) +* +* @return None +*/ +/*----------------------------------------------------------------------------*/ +void cnmFreeWmmIndex( + IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo) +{ +#if (CFG_HW_WMM_BY_BSS == 1) + prAdapter->ucHwWmmEnBit &= (~BIT(prBssInfo->ucWmmQueSet)); +#endif + prBssInfo->ucWmmQueSet = DEFAULT_HW_WMM_INDEX; + prBssInfo->fgIsWmmInited = FALSE; +} + +enum ENUM_CNM_OPMODE_REQ_T +cnmOpModeMapEvtReason( + enum ENUM_EVENT_OPMODE_CHANGE_REASON eEvt +) +{ + enum ENUM_CNM_OPMODE_REQ_T eReqIdx; + + switch (eEvt) { + case EVENT_OPMODE_CHANGE_REASON_DBDC: + eReqIdx = CNM_OPMODE_REQ_DBDC; + break; + case EVENT_OPMODE_CHANGE_REASON_COANT: + eReqIdx = CNM_OPMODE_REQ_COANT; + break; + case EVENT_OPMODE_CHANGE_REASON_DBDC_SCAN: + eReqIdx = CNM_OPMODE_REQ_DBDC_SCAN; + break; + case EVENT_OPMODE_CHANGE_REASON_SMARTGEAR: + eReqIdx = CNM_OPMODE_REQ_SMARTGEAR; + break; + case EVENT_OPMODE_CHANGE_REASON_SMARTGEAR_1T2R: + eReqIdx = CNM_OPMODE_REQ_SMARTGEAR_1T2R; + break; + case EVENT_OPMODE_CHANGE_REASON_COEX: + eReqIdx = CNM_OPMODE_REQ_COEX; + break; + default: + eReqIdx = CNM_OPMODE_REQ_NUM; + break; + } + return eReqIdx; +} + +void cnmOpModeDump( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex +) +{ + struct BSS_INFO *prBssInfo; + + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + DBGLOG(CNM, INFO, + "BSS[%d] DumpOpMode Tx(Cur:%x,Run:%x), Rx(Cur:%x,Run:%x)\n", + ucBssIndex, + prBssInfo->ucOpTxNss, + prBssInfo->fgIsOpChangeTxNss ? + prBssInfo->ucOpChangeTxNss : 0xFF, + prBssInfo->ucOpRxNss, + prBssInfo->fgIsOpChangeRxNss ? + prBssInfo->ucOpChangeRxNss : 0xFF); +} + +void cnmOpModeCallbackDispatcher( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN bool fgSuccess) +{ + struct CNM_OPMODE_BSS_CONTROL_T *prBssOpCtrl; + struct CNM_OPMODE_BSS_REQ *prReq; + enum ENUM_CNM_OPMODE_REQ_T eReqIdx; + + ASSERT(prAdapter); + if (ucBssIndex >= BSS_DEFAULT_NUM) { + DBGLOG(CNM, WARN, + "CbOpMode, invalid,B[%d]\n", + ucBssIndex); + return; + } + + /* Step 1. Run callback function */ + prBssOpCtrl = &g_arBssOpControl[ucBssIndex]; + if (!prBssOpCtrl->rRunning.fgIsRunning) { + /* GO/AP run cb immediately. */ + DBGLOG(CNM, INFO, + "CbOpMode, BSS[%d] none running, OpModeState[%d]\n", + ucBssIndex, + g_rDbdcInfo.eBssOpModeState[ucBssIndex]); + /* We have to callback op mode change done. + * Otherwise, DBDC state machine won't continue. + */ + if (g_rDbdcInfo.eBssOpModeState[ucBssIndex] == + ENUM_OPMODE_STATE_WAIT) { + cnmDbdcOpModeChangeDoneCallback( + prAdapter, ucBssIndex, fgSuccess); + } + } else { + switch (prBssOpCtrl->rRunning.eReqIdx) { + case CNM_OPMODE_REQ_DBDC: + cnmDbdcOpModeChangeDoneCallback( + prAdapter, ucBssIndex, fgSuccess); + break; + default: + break; + } + DBGLOG(CNM, INFO, + "CbOpMode,%s,Run,%s,T:%u,R:%u,%s\n", + apucCnmOpModeReq[prBssOpCtrl->rRunning.eReqIdx], + apucCnmOpModeReq[prBssOpCtrl->rRunning.eRunReq], + prBssOpCtrl->rRunning.ucOpTxNss, + prBssOpCtrl->rRunning.ucOpRxNss, + fgSuccess ? "OK" : "FAIL"); + } + prBssOpCtrl->rRunning.fgIsRunning = false; + + /* Step 2. Check pending request */ + for (eReqIdx = CNM_OPMODE_REQ_DBDC; + eReqIdx < CNM_OPMODE_REQ_NUM; + eReqIdx++) { + prReq = &(prBssOpCtrl->arReqPool[eReqIdx]); + if (prReq->fgNewRequest) + break; + } + + if (eReqIdx != CNM_OPMODE_REQ_NUM) { + DBGLOG(CNM, INFO, + "CbOpMode,ReTrigger:%s,En,%u,Tx:%u,Rx:%u\n", + apucCnmOpModeReq[eReqIdx], + prReq->fgEnable, + prReq->ucOpTxNss, + prReq->ucOpRxNss); + cnmOpModeSetTRxNss( + prAdapter, + ucBssIndex, + eReqIdx, + prReq->fgEnable, + prReq->ucOpRxNss, + prReq->ucOpTxNss); + } +} + +static enum ENUM_CNM_OPMODE_REQ_T +cnmOpModeReqDispatcher( + struct CNM_OPMODE_BSS_CONTROL_T *prBssOpCtrl +) +{ + struct CNM_OPMODE_BSS_REQ *prReq; + enum ENUM_CNM_OPMODE_REQ_T eReqIdx; + enum ENUM_CNM_OPMODE_REQ_T eReqFinal = CNM_OPMODE_REQ_MAX_CAP; + + if (prBssOpCtrl->rRunning.fgIsRunning) { + DBGLOG(CNM, INFO, + "OpMode %s (Tx:%d,Rx:%d) is running %s, defer new request\n", + apucCnmOpModeReq[prBssOpCtrl->rRunning.eReqIdx], + prBssOpCtrl->rRunning.ucOpTxNss, + prBssOpCtrl->rRunning.ucOpRxNss, + apucCnmOpModeReq[prBssOpCtrl->rRunning.eRunReq] + ); + return CNM_OPMODE_REQ_NUM; + } + + for (eReqIdx = CNM_OPMODE_REQ_DBDC; + eReqIdx < CNM_OPMODE_REQ_NUM; eReqIdx++) { + prReq = &(prBssOpCtrl->arReqPool[eReqIdx]); + prReq->fgNewRequest = false; + if (prReq->fgEnable && eReqIdx < eReqFinal) + eReqFinal = eReqIdx; + } + + return eReqFinal; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Set the operating TRx Nss. + * If failed to change OpRxNss, the OpTxNss will not change. + * If the BSS is not alive, just update to control table. + * + * @param prAdapter + * @param ucBssIndex + * @param eNewReq + * @param fgEnable + * @param ucOpRxNss + * @param ucOpTxNss + * + * @return ENUM_CNM_OPMODE_REQ_STATUS + */ +/*----------------------------------------------------------------------------*/ +enum ENUM_CNM_OPMODE_REQ_STATUS +cnmOpModeSetTRxNss( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN enum ENUM_CNM_OPMODE_REQ_T eNewReq, + IN bool fgEnable, + IN uint8_t ucOpRxNss, + IN uint8_t ucOpTxNss +) +{ + struct BSS_INFO *prBssInfo; + struct CNM_OPMODE_BSS_CONTROL_T *prBssOpCtrl; + struct CNM_OPMODE_BSS_REQ *prReq; + enum ENUM_OP_CHANGE_STATUS_T eRlmStatus; + enum ENUM_CNM_OPMODE_REQ_STATUS eStatus + = CNM_OPMODE_REQ_STATUS_SUCCESS; + uint8_t ucOpRxNssFinal, ucOpTxNssFinal, ucOpBwFinal; + enum ENUM_CNM_OPMODE_REQ_T eRunReq; + + ASSERT(prAdapter); + if (ucBssIndex > prAdapter->ucHwBssIdNum || + ucBssIndex >= BSS_DEFAULT_NUM) { + DBGLOG(CNM, WARN, "SetOpMode invalid BSS[%d]\n", ucBssIndex); + return CNM_OPMODE_REQ_STATUS_INVALID_PARAM; + } + + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + prBssOpCtrl = &g_arBssOpControl[ucBssIndex]; + prReq = &(prBssOpCtrl->arReqPool[eNewReq]); + + /* Step 1 Update req pool */ + prReq->fgEnable = fgEnable; + prReq->fgNewRequest = true; + prReq->ucOpRxNss = ucOpRxNss; + prReq->ucOpTxNss = ucOpTxNss; + + /* Step 2 Select the highest priority req */ + eRunReq = cnmOpModeReqDispatcher(prBssOpCtrl); + if (eRunReq == CNM_OPMODE_REQ_NUM) { + return CNM_OPMODE_REQ_STATUS_DEFER; + } else if (eRunReq == CNM_OPMODE_REQ_MAX_CAP) { + ucOpRxNssFinal = ucOpTxNssFinal = + wlanGetSupportNss(prAdapter, ucBssIndex); + } else { + prReq = &prBssOpCtrl->arReqPool[eRunReq]; + ucOpRxNssFinal = prReq->ucOpRxNss; + ucOpTxNssFinal = prReq->ucOpTxNss; + } + + if (IS_BSS_ALIVE(prAdapter, prBssInfo)) { + /* Step 3. Special rule for BW change (DBDC) + * We only bound OpBw @ BW80 for DBDC. + * This function colud not restore to current peer's + * OpBw. It's fine because below reasons(2018/08): + * 1) No DBDC project supports BW160 or NW80+80. + * 2) No feature wants to change OpBw. + * + * If you want to change OpBw in the future, please + * make sure you can restore to current peer's OpBw. + */ + ucOpBwFinal = rlmGetBssOpBwByVhtAndHtOpInfo(prBssInfo); + if ((eRunReq == CNM_OPMODE_REQ_DBDC || + eRunReq == CNM_OPMODE_REQ_DBDC_SCAN) && + ucOpBwFinal > MAX_BW_80MHZ) { + DBGLOG(CNM, INFO, + "SetOpMode Bss[%d] %s override BW %d to MAX_BW_80MHZ\n", + ucBssIndex, + apucCnmOpModeReq[eRunReq], + ucOpBwFinal); + ucOpBwFinal = MAX_BW_80MHZ; + } + + /* Step 4. Execute OpMode change function for alive BSS */ + eRlmStatus = rlmChangeOperationMode(prAdapter, + ucBssIndex, + ucOpBwFinal, + ucOpRxNssFinal, + ucOpTxNssFinal, + #if CFG_SUPPORT_SMART_GEAR + eNewReq, + #endif + cnmOpModeCallbackDispatcher + ); + + switch (eRlmStatus) { + case OP_CHANGE_STATUS_VALID_NO_CHANGE: + case OP_CHANGE_STATUS_VALID_CHANGE_CALLBACK_DONE: + eStatus = CNM_OPMODE_REQ_STATUS_SUCCESS; + break; + case OP_CHANGE_STATUS_VALID_CHANGE_CALLBACK_WAIT: + eStatus = CNM_OPMODE_REQ_STATUS_RUNNING; + prBssOpCtrl->rRunning.fgIsRunning = true; + prBssOpCtrl->rRunning.eReqIdx = eNewReq; + prBssOpCtrl->rRunning.eRunReq = eRunReq; + prBssOpCtrl->rRunning.ucOpTxNss = ucOpTxNssFinal; + prBssOpCtrl->rRunning.ucOpRxNss = ucOpRxNssFinal; + break; + case OP_CHANGE_STATUS_INVALID: + default: + eStatus = CNM_OPMODE_REQ_STATUS_INVALID_PARAM; + break; + } + } + + /* Step 5. Dump result */ + DBGLOG(CNM, INFO, + "SetOpMode Bss[%d] alive[%d] NewReq:%s %s RunReq:%s,%s\n", + ucBssIndex, IS_BSS_ALIVE(prAdapter, prBssInfo), + apucCnmOpModeReq[eNewReq], + fgEnable ? "En" : "Dis", + apucCnmOpModeReq[eRunReq], + apucCnmOpModeReqStatus[eStatus]); + cnmOpModeDump(prAdapter, ucBssIndex); + + return eStatus; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Get the operation TRx Nss. + * If DBDC is goning to enable or already enabled, return 1. + * Else return MaxCapability. + * + * @param prAdapter + * @param ucBssIndex + * @param pucOpRxNss + * @param pucOpTxNss + * + * @return ucOpTRxNss + */ +/*----------------------------------------------------------------------------*/ +void cnmOpModeGetTRxNss( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + OUT uint8_t *pucOpRxNss, + OUT uint8_t *pucOpTxNss) +{ + struct CNM_OPMODE_BSS_CONTROL_T *prBssOpCtrl; + struct CNM_OPMODE_BSS_REQ *prReq; + enum ENUM_CNM_OPMODE_REQ_T eReqIdx; + enum ENUM_CNM_OPMODE_REQ_T eCurrMaxIdx = CNM_OPMODE_REQ_MAX_CAP; + uint8_t ucOpRxNss, ucOpTxNss; + + if (pucOpRxNss == NULL || pucOpTxNss == NULL || + ucBssIndex >= BSS_DEFAULT_NUM) { + DBGLOG(CNM, WARN, + "GetOpMode invalid param B[%d]\n", + ucBssIndex); + return; + } + + ucOpRxNss = ucOpTxNss = wlanGetSupportNss(prAdapter, ucBssIndex); + prBssOpCtrl = &g_arBssOpControl[ucBssIndex]; + + *pucOpTxNss = ucOpTxNss; + *pucOpRxNss = ucOpRxNss; + + if (prBssOpCtrl->rRunning.fgIsRunning) { + eCurrMaxIdx = prBssOpCtrl->rRunning.eRunReq; + *pucOpTxNss = prBssOpCtrl->rRunning.ucOpTxNss; + *pucOpRxNss = prBssOpCtrl->rRunning.ucOpRxNss; + DBGLOG(CNM, INFO, + "GetOpMode,use running %s from %s\n", + apucCnmOpModeReq[eCurrMaxIdx], + apucCnmOpModeReq[prBssOpCtrl->rRunning.eReqIdx]); + } else { + for (eReqIdx = CNM_OPMODE_REQ_DBDC; + eReqIdx < CNM_OPMODE_REQ_NUM; + eReqIdx++) { + prReq = &(prBssOpCtrl->arReqPool[eReqIdx]); + if (prReq->fgEnable && !prReq->fgNewRequest) { + eCurrMaxIdx = eReqIdx; + *pucOpTxNss = (ucOpTxNss > prReq->ucOpTxNss) ? + prReq->ucOpTxNss : ucOpTxNss; + *pucOpRxNss = (ucOpRxNss > prReq->ucOpRxNss) ? + prReq->ucOpRxNss : ucOpRxNss; + break; + } + } + } + + DBGLOG(CNM, INFO, + "GetOpMode BSS[%u](%s) T:%d R:%u\n", + ucBssIndex, apucCnmOpModeReq[eCurrMaxIdx], + *pucOpTxNss, *pucOpRxNss); +} + +#if CFG_SUPPORT_SMART_GEAR +/*----------------------------------------------------------------------------*/ +/*! + * @brief Handle Smart Gear Status Change event from FW. + * + * @param prAdapter + * @param prEvent + * + * @return + */ +/*----------------------------------------------------------------------------*/ +void cnmEventSGStatus( + IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ +#if CFG_SUPPORT_DATA_STALL + struct EVENT_SMART_GEAT_STATE *prSGState; + enum ENUM_VENDOR_DRIVER_EVENT eEvent; + + ASSERT(prAdapter); + prSGState = (struct EVENT_SMART_GEAT_STATE *) (prEvent->aucBuffer); + + if (prSGState->fgIsEnable == 0x01) { + if (prSGState->u4StateIdx == 0x00) + eEvent = EVENT_SG_1T1R; + else + eEvent = EVENT_SG_2T2R; + } else if (prSGState->fgIsEnable == 0x00) { + eEvent = EVENT_SG_DISABLE; + } else { + ;/* Not correction value, juste reture;*/ + return; + } + + DBGLOG(CNM, INFO, + "[SG]cnmEventSGStatus,%u,%u,%u\n", + prSGState->fgIsEnable, prSGState->u4StateIdx, eEvent); + KAL_REPORT_ERROR_EVENT(prAdapter, + eEvent, (uint16_t)sizeof(u_int8_t), + 0, + TRUE); +#endif /* CFG_SUPPORT_DATA_STALL */ +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Event handler for EVENT_ID_OPMODE_CHANGE + * + * @param prAdapter + * @param prEvent + * + * @return + */ +/*----------------------------------------------------------------------------*/ +void cnmOpmodeEventHandler( + IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct EVENT_OPMODE_CHANGE *prEvtOpMode; + enum ENUM_CNM_OPMODE_REQ_T eReqIdx; + uint8_t ucBssIndex; + + ASSERT(prAdapter); + prEvtOpMode = (struct EVENT_OPMODE_CHANGE *) + (prEvent->aucBuffer); + + eReqIdx = cnmOpModeMapEvtReason( + (enum ENUM_EVENT_OPMODE_CHANGE_REASON) + prEvtOpMode->ucReason); + + if (eReqIdx >= CNM_OPMODE_REQ_NUM) { + DBGLOG(CNM, WARN, + "EvtOpMode,WrongReaosn,%u,Evt,%u,igonre\n", + eReqIdx, prEvtOpMode->ucReason); + return; + } + + DBGLOG(CNM, INFO, + "EvtOpMode, Req:%s BssBitmap:0x%x, En:%u T:%u R:%u\n", + apucCnmOpModeReq[eReqIdx], + prEvtOpMode->ucBssBitmap, + prEvtOpMode->ucEnable, + prEvtOpMode->ucOpTxNss, + prEvtOpMode->ucOpRxNss); + + for (ucBssIndex = 0; + ucBssIndex < prAdapter->ucHwBssIdNum; + ucBssIndex++) { + if (prEvtOpMode->ucBssBitmap & BIT(ucBssIndex)) { + cnmOpModeSetTRxNss( + prAdapter, + ucBssIndex, + eReqIdx, + prEvtOpMode->ucEnable, + prEvtOpMode->ucOpRxNss, + prEvtOpMode->ucOpTxNss + ); + } + } +} + +enum ENUM_CNM_WMM_QUOTA_REQ_T +cnmWmmQuotaReqDispatcher( + struct CNM_WMM_QUOTA_CONTROL_T *prWmmQuotaCtrl +) +{ + struct CNM_WMM_QUOTA_REQ *prReq; + enum ENUM_CNM_WMM_QUOTA_REQ_T eReqIdx; + enum ENUM_CNM_WMM_QUOTA_REQ_T eReqFinal = CNM_WMM_REQ_DEFAULT; + + if (prWmmQuotaCtrl->rRunning.fgIsRunning) { + DBGLOG(CNM, WARN, + "WmmQuota,PreReq,%s,RunningReq,%s\n", + apucCnmWmmQuotaReq[prWmmQuotaCtrl->rRunning.eReqIdx], + apucCnmWmmQuotaReq[prWmmQuotaCtrl->rRunning.eRunReq]); + } + + for (eReqIdx = CNM_WMM_REQ_DBDC; + eReqIdx < CNM_WMM_REQ_NUM; eReqIdx++) { + prReq = &(prWmmQuotaCtrl->arReqPool[eReqIdx]); + if (prReq->fgEnable && eReqIdx < eReqFinal) + eReqFinal = eReqIdx; + } + return eReqFinal; +} + +void +cnmWmmQuotaCallback( + IN struct ADAPTER *prAdapter, + IN unsigned long plParamPtr +) +{ + struct CNM_WMM_QUOTA_CONTROL_T *prWmmQuotaCtrl; + bool fgRun; + uint8_t ucWmmIndex; + + KAL_SPIN_LOCK_DECLARATION(); + + ucWmmIndex = (uint8_t)plParamPtr; + prWmmQuotaCtrl = &(g_arWmmQuotaControl[ucWmmIndex]); + + if (!prWmmQuotaCtrl->rRunning.fgIsRunning) { + DBGLOG(CNM, WARN, + "WmmQuotaCb,%d,None runnig\n", + ucWmmIndex); + return; + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_UPDATE_WMM_QUOTA); + fgRun = prAdapter->rWmmQuotaReqCS[ucWmmIndex].fgRun; + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_UPDATE_WMM_QUOTA); + + if (fgRun) { + DBGLOG(CNM, INFO, + "WmmQuotaCb,%d,Req,%s,Run,%s,Quota,%u,WakeUpHIF\n", + ucWmmIndex, + apucCnmWmmQuotaReq[prWmmQuotaCtrl->rRunning.eReqIdx], + apucCnmWmmQuotaReq[prWmmQuotaCtrl->rRunning.eRunReq], + prWmmQuotaCtrl->rRunning.u4ReqQuota + ); + kalSetWmmUpdateEvent(prAdapter->prGlueInfo); + if (!timerPendingTimer(&(prWmmQuotaCtrl->rTimer))) { + cnmTimerStartTimer( + prAdapter, &(prWmmQuotaCtrl->rTimer), + CNM_WMM_QUOTA_RETRIGGER_TIME_MS); + } + } else { + prWmmQuotaCtrl->rRunning.fgIsRunning = false; + DBGLOG(CNM, INFO, + "WmmQuotaCb,%u,%s,Run,%s,Quota,%u,Finish\n", + ucWmmIndex, + apucCnmWmmQuotaReq[prWmmQuotaCtrl->rRunning.eReqIdx], + apucCnmWmmQuotaReq[prWmmQuotaCtrl->rRunning.eRunReq], + prWmmQuotaCtrl->rRunning.u4ReqQuota); + } +} + +void cnmWmmQuotaSetMaxQuota( + IN struct ADAPTER *prAdapter, + IN uint8_t ucWmmIndex, + IN enum ENUM_CNM_WMM_QUOTA_REQ_T eNewReq, + IN bool fgEnable, + IN uint32_t u4ReqQuota +) +{ + struct CNM_WMM_QUOTA_CONTROL_T *prWmmQuotaCtrl; + enum ENUM_CNM_WMM_QUOTA_REQ_T eRunReq; + uint32_t u4QuotaFinal; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prWmmQuotaCtrl = &(g_arWmmQuotaControl[ucWmmIndex]); + prWmmQuotaCtrl->arReqPool[eNewReq].fgEnable = fgEnable; + prWmmQuotaCtrl->arReqPool[eNewReq].u4ReqQuota = u4ReqQuota; + + eRunReq = cnmWmmQuotaReqDispatcher(prWmmQuotaCtrl); + if (eRunReq == CNM_WMM_REQ_DEFAULT) { + /* unlimit */ + u4QuotaFinal = -1; + } else { + u4QuotaFinal = prWmmQuotaCtrl->arReqPool[eRunReq].u4ReqQuota; + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_UPDATE_WMM_QUOTA); + prAdapter->rWmmQuotaReqCS[ucWmmIndex].u4Quota = u4QuotaFinal; + prAdapter->rWmmQuotaReqCS[ucWmmIndex].fgRun = true; + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_UPDATE_WMM_QUOTA); + + prWmmQuotaCtrl->rRunning.fgIsRunning = true; + prWmmQuotaCtrl->rRunning.eReqIdx = eNewReq; + prWmmQuotaCtrl->rRunning.eRunReq = eRunReq; + prWmmQuotaCtrl->rRunning.u4ReqQuota = u4QuotaFinal; + DBGLOG(CNM, INFO, + "SetWmmQuota,%u,%s %s,Run,%s,Quota,0x%x\n", + ucWmmIndex, + apucCnmWmmQuotaReq[prWmmQuotaCtrl->rRunning.eReqIdx], + fgEnable ? "En" : "Dis", + apucCnmWmmQuotaReq[prWmmQuotaCtrl->rRunning.eRunReq], + prWmmQuotaCtrl->rRunning.u4ReqQuota); + + cnmWmmQuotaCallback(prAdapter, ucWmmIndex); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief check if p2p is active + * + * @param prAdapter + * + * @return + */ +/*----------------------------------------------------------------------------*/ +u_int8_t cnmP2pIsActive(IN struct ADAPTER *prAdapter) +{ + uint8_t ret; + + ret = (cnmGetP2pBssInfo(prAdapter) != NULL); + DBGLOG(CNM, TRACE, "P2p is %s\n", ret ? "ACTIVE" : "INACTIVE"); + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief get p2p bss info + * + * @param prAdapter + * + * @return + */ +/*----------------------------------------------------------------------------*/ +struct BSS_INFO *cnmGetP2pBssInfo(IN struct ADAPTER *prAdapter) +{ + struct BSS_INFO *prBssInfo; + uint8_t i; + + if (!prAdapter) + return NULL; + + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + + if (prBssInfo && + IS_BSS_P2P(prBssInfo) && + !p2pFuncIsAPMode( + prAdapter->rWifiVar.prP2PConnSettings + [prBssInfo->u4PrivateData]) && + IS_BSS_ALIVE(prAdapter, prBssInfo)) + return prBssInfo; + } + + return NULL; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/cnm_mem.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/cnm_mem.c new file mode 100644 index 0000000000000..6a9f602c0539b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/cnm_mem.c @@ -0,0 +1,1864 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +static uint8_t *apucStaRecType[STA_TYPE_INDEX_NUM] = { + (uint8_t *) "LEGACY", + (uint8_t *) "P2P", + (uint8_t *) "BOW" +}; + +static uint8_t *apucStaRecRole[STA_ROLE_INDEX_NUM] = { + (uint8_t *) "ADHOC", + (uint8_t *) "CLIENT", + (uint8_t *) "AP", + (uint8_t *) "DLS" +}; + +#if CFG_SUPPORT_TDLS +/* The list of valid data rates. */ +const uint8_t aucValidDataRate[] = { + 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_VHT_PHY, /* RATE_VHT_PHY_INDEX */ + RATE_HT_PHY /* RATE_HT_PHY_INDEX */ +}; +#endif + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +static void cnmStaRoutinesForAbort(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec); + +static void cnmStaRecHandleEventPkt(struct ADAPTER *prAdapter, + struct CMD_INFO *prCmdInfo, uint8_t *pucEventBuf); + +static void +cnmStaSendRemoveCmd(struct ADAPTER *prAdapter, + enum ENUM_STA_REC_CMD_ACTION eActionType, uint8_t ucStaRecIndex, + uint8_t ucBssIndex); + +#if (CFG_SUPPORT_802_11AX == 1) +static void cnmStaRecCmdHeContentFill( + struct STA_RECORD *prStaRec, + struct CMD_UPDATE_STA_RECORD *prCmdContent); +#endif + + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +struct MSDU_INFO *cnmPktAllocWrapper(struct ADAPTER *prAdapter, + uint32_t u4Length, uint8_t *pucStr) +{ + struct MSDU_INFO *prMsduInfo; + + prMsduInfo = cnmPktAlloc(prAdapter, u4Length); + log_dbg(MEM, LOUD, "Alloc MSDU_INFO[0x%p] by [%s]\n", + prMsduInfo, pucStr); + + return prMsduInfo; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void cnmPktFreeWrapper(struct ADAPTER *prAdapter, struct MSDU_INFO *prMsduInfo, + uint8_t *pucStr) +{ + log_dbg(MEM, LOUD, "Free MSDU_INFO[0x%p] by [%s]\n", + prMsduInfo, pucStr); + + cnmPktFree(prAdapter, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +struct MSDU_INFO *cnmPktAlloc(struct ADAPTER *prAdapter, uint32_t u4Length) +{ + struct MSDU_INFO *prMsduInfo; + struct QUE *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, struct MSDU_INFO *); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + + if (prMsduInfo) { + if (u4Length) { + 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; + } + } else { + prMsduInfo->prPacket = NULL; + } + } +#if DBG + if (prMsduInfo == NULL) { + log_dbg(MEM, WARN, "\n"); + log_dbg(MEM, WARN, "MgtDesc#=%ld\n", prQueList->u4NumElem); + +#if CFG_DBG_MGT_BUF + log_dbg(MEM, WARN, "rMgtBufInfo: alloc#=%ld, free#=%ld, null#=%ld\n", + prAdapter->rMgtBufInfo.u4AllocCount, + prAdapter->rMgtBufInfo.u4FreeCount, + prAdapter->rMgtBufInfo.u4AllocNullCount); +#endif + + log_dbg(MEM, WARN, "\n"); + } +#endif + + return prMsduInfo; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void cnmPktFree(struct ADAPTER *prAdapter, struct MSDU_INFO *prMsduInfo) +{ + struct QUE *prQueList; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + if (!prMsduInfo) + return; + + 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(struct ADAPTER *prAdapter) +{ + struct BUF_INFO *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 = (uint32_t) 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 = (uint32_t) 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 + */ +/*----------------------------------------------------------------------------*/ +#if CFG_DBG_MGT_BUF +void *cnmMemAllocX(IN struct ADAPTER *prAdapter, IN enum ENUM_RAM_TYPE eRamType, + IN uint32_t u4Length, uint8_t *fileAndLine) +#else +void *cnmMemAlloc(IN struct ADAPTER *prAdapter, IN enum ENUM_RAM_TYPE eRamType, + IN uint32_t u4Length) +#endif +{ + struct BUF_INFO *prBufInfo; + uint32_t rRequiredBitmap; + uint32_t u4BlockNum; + uint32_t i, u4BlkSzInPower; + void *pvMemory; + enum ENUM_SPIN_LOCK_CATEGORY_E eLockBufCat; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + if (u4Length == 0) { + log_dbg(MEM, WARN, + "%s: Length to be allocated is ZERO, skip!\n", + __func__); + return NULL; + } + + if (eRamType == RAM_TYPE_MSG && u4Length <= 256) { + prBufInfo = &prAdapter->rMsgBufInfo; + u4BlkSzInPower = MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2; + + u4BlockNum = (u4Length + MSG_BUF_BLOCK_SIZE - 1) + >> 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; + + u4BlockNum = (u4Length + MGT_BUF_BLOCK_SIZE - 1) + >> MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2; + + ASSERT(u4BlockNum <= MAX_NUM_OF_BUF_BLOCKS); + } + + if (eRamType == RAM_TYPE_MSG) + eLockBufCat = SPIN_LOCK_MSG_BUF; + else + eLockBufCat = SPIN_LOCK_MGT_BUF; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, eLockBufCat); + +#if CFG_DBG_MGT_BUF + prBufInfo->u4AllocCount++; +#endif + + 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] + = (uint8_t) u4BlockNum; + + KAL_RELEASE_SPIN_LOCK(prAdapter, eLockBufCat); + + /* Return the start address of + * allocated memory + */ + return (void *) (prBufInfo->pucBuf + + (i << u4BlkSzInPower)); + } + + rRequiredBitmap <<= 1; + } + } + +#if CFG_DBG_MGT_BUF + prBufInfo->u4AllocNullCount++; +#endif + + /* kalMemAlloc() shall not included in spin_lock */ + KAL_RELEASE_SPIN_LOCK(prAdapter, eLockBufCat); + +#ifdef LINUX +#if CFG_DBG_MGT_BUF + pvMemory = (void *) kalMemAlloc(u4Length + sizeof(struct MEM_TRACK), + PHY_MEM_TYPE); + if (pvMemory) { + struct MEM_TRACK *prMemTrack = (struct MEM_TRACK *)pvMemory; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_MGT_BUF); + LINK_INSERT_TAIL( + &prAdapter->rMemTrackLink, &prMemTrack->rLinkEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_MGT_BUF); + prMemTrack->pucFileAndLine = fileAndLine; + prMemTrack->u2CmdIdAndWhere = 0x0000; + pvMemory = (void *)(prMemTrack + 1); + kalMemZero(pvMemory, u4Length); + } +#else + pvMemory = (void *) kalMemAlloc(u4Length, PHY_MEM_TYPE); + if (!pvMemory) + DBGLOG(MEM, WARN, "kmalloc fail: %u\n", u4Length); +#endif +#else + pvMemory = (void *) NULL; +#endif + +#if CFG_DBG_MGT_BUF + if (pvMemory) + GLUE_INC_REF_CNT(prAdapter->u4MemAllocDynamicCount); +#endif + + 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 struct ADAPTER *prAdapter, IN void *pvMemory) +{ + struct BUF_INFO *prBufInfo; + uint32_t u4BlockIndex; + uint32_t rAllocatedBlocksBitmap; + enum ENUM_RAM_TYPE eRamType; + enum ENUM_SPIN_LOCK_CATEGORY_E eLockBufCat; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + if (!pvMemory) + return; + + /* Judge it belongs to which RAM type */ + if (((unsigned long) pvMemory + >= (unsigned long)&prAdapter->aucMsgBuf[0]) + && ((unsigned long) pvMemory + <= (unsigned long)&prAdapter->aucMsgBuf[MSG_BUFFER_SIZE - 1])) { + + prBufInfo = &prAdapter->rMsgBufInfo; + u4BlockIndex = ((unsigned long) pvMemory + - (unsigned long) prBufInfo->pucBuf) + >> MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2; + ASSERT(u4BlockIndex < MAX_NUM_OF_BUF_BLOCKS); + eRamType = RAM_TYPE_MSG; + } else if (((unsigned long) pvMemory + >= (unsigned long) prAdapter->pucMgtBufCached) + && ((unsigned long) pvMemory + <= ((unsigned long) prAdapter->pucMgtBufCached + + MGT_BUFFER_SIZE - 1))) { + prBufInfo = &prAdapter->rMgtBufInfo; + u4BlockIndex = ((unsigned long) pvMemory + - (unsigned long) prBufInfo->pucBuf) + >> MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2; + ASSERT(u4BlockIndex < MAX_NUM_OF_BUF_BLOCKS); + eRamType = RAM_TYPE_BUF; + } else { +#ifdef LINUX +#if CFG_DBG_MGT_BUF + struct MEM_TRACK *prTrack = (struct MEM_TRACK *) + ((uint8_t *)pvMemory - sizeof(struct MEM_TRACK)); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_MGT_BUF); + LINK_REMOVE_KNOWN_ENTRY( + &prAdapter->rMemTrackLink, &prTrack->rLinkEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_MGT_BUF); + kalMemFree(prTrack, PHY_MEM_TYPE, 0); +#else + /* For Linux, it is supported because size is not needed */ + kalMemFree(pvMemory, PHY_MEM_TYPE, 0); +#endif +#else + /* For Windows, it is not supported because of + * no size argument + */ + ASSERT(0); +#endif + +#if CFG_DBG_MGT_BUF + GLUE_INC_REF_CNT(prAdapter->u4MemFreeDynamicCount); +#endif + return; + } + + if (eRamType == RAM_TYPE_MSG) + eLockBufCat = SPIN_LOCK_MSG_BUF; + else + eLockBufCat = SPIN_LOCK_MGT_BUF; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, eLockBufCat); + +#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, eLockBufCat); + + return; + +} /* end of cnmMemFree() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void cnmStaRecInit(struct ADAPTER *prAdapter) +{ + struct STA_RECORD *prStaRec; + uint16_t i; + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + + prStaRec->ucIndex = (uint8_t) i; + prStaRec->fgIsInUse = FALSE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +struct STA_RECORD *cnmStaRecAlloc(struct ADAPTER *prAdapter, + enum ENUM_STA_TYPE eStaType, uint8_t ucBssIndex, uint8_t *pucMacAddr) +{ + struct STA_RECORD *prStaRec; + uint16_t i, k; + + ASSERT(prAdapter); + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + + if (!prStaRec->fgIsInUse) { + kalMemZero(prStaRec, sizeof(struct STA_RECORD)); + prStaRec->ucIndex = (uint8_t) i; + prStaRec->ucBssIndex = ucBssIndex; + prStaRec->fgIsInUse = TRUE; + + prStaRec->eStaType = eStaType; + prStaRec->ucBssIndex = ucBssIndex; + + /* Initialize the SN caches for duplicate detection */ + for (k = 0; k < TID_NUM + 1; k++) { + prStaRec->au2CachedSeqCtrl[k] = 0xFFFF; + prStaRec->afgIsIgnoreAmsduDuplicate[k] = FALSE; + } + + /* Initialize SW TX queues in STA_REC */ + for (k = 0; k < STA_WAIT_QUEUE_NUM; k++) + LINK_INITIALIZE(&prStaRec->arStaWaitQueue[k]); + +#if CFG_ENABLE_PER_STA_STATISTICS && CFG_ENABLE_PKT_LIFETIME_PROFILE + prStaRec->u4TotalTxPktsNumber = 0; + prStaRec->u4TotalTxPktsTime = 0; + prStaRec->u4TotalRxPktsNumber = 0; + prStaRec->u4MaxTxPktsTime = 0; +#endif + + for (k = 0; k < NUM_OF_PER_STA_TX_QUEUES; k++) { + QUEUE_INITIALIZE( + &prStaRec->arTxQueue[k]); + QUEUE_INITIALIZE( + &prStaRec->arPendingTxQueue[k]); + prStaRec->aprTargetQueue[k] + = &prStaRec->arPendingTxQueue[k]; + } + + prStaRec->ucAmsduEnBitmap = 0; + prStaRec->ucMaxMpduCount = 0; + prStaRec->u4MaxMpduLen = 0; + prStaRec->u4MinMpduLen = 0; + +#if DSCP_SUPPORT + qosMapSetInit(prStaRec); +#endif + break; + } + } + + /* Sync to chip to allocate WTBL resource */ + if (i < CFG_STA_REC_NUM) { + COPY_MAC_ADDR(prStaRec->aucMacAddr, pucMacAddr); + if (secPrivacySeekForEntry(prAdapter, prStaRec)) + cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); +#if DBG + else { + prStaRec->fgIsInUse = FALSE; + prStaRec = NULL; + ASSERT(FALSE); + } +#endif + } else { + prStaRec = NULL; + } + + return prStaRec; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void cnmStaRecFree(struct ADAPTER *prAdapter, struct STA_RECORD *prStaRec) +{ + uint8_t ucStaRecIndex, ucBssIndex; + + ASSERT(prAdapter); + + if (!prStaRec) + return; + + log_dbg(RSN, INFO, "cnmStaRecFree %d\n", prStaRec->ucIndex); + + ucStaRecIndex = prStaRec->ucIndex; + ucBssIndex = prStaRec->ucBssIndex; + + nicFreePendingTxMsduInfo(prAdapter, prStaRec->ucWlanIndex, + MSDU_REMOVE_BY_WLAN_INDEX); + + cnmStaRoutinesForAbort(prAdapter, prStaRec); + + cnmStaSendRemoveCmd(prAdapter, STA_REC_CMD_ACTION_STA, + ucStaRecIndex, ucBssIndex); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static void cnmStaRoutinesForAbort(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec) +{ + ASSERT(prAdapter); + + if (!prStaRec) + return; + + /* To do: free related resources, e.g. timers, buffers, etc */ + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + cnmTimerStopTimer(prAdapter, &prStaRec->rDeauthTxDoneTimer); + 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); + + /* Update the driver part table setting */ + secPrivacyFreeSta(prAdapter, prStaRec); + + prStaRec->fgIsInUse = FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void cnmStaFreeAllStaByNetwork(struct ADAPTER *prAdapter, uint8_t ucBssIndex, + uint8_t ucStaRecIndexExcluded) +{ +#if CFG_ENABLE_WIFI_DIRECT + struct BSS_INFO *prBssInfo; +#endif + struct STA_RECORD *prStaRec; + uint16_t i; + enum ENUM_STA_REC_CMD_ACTION eAction; + + if (ucBssIndex > prAdapter->ucHwBssIdNum) + return; + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = (struct STA_RECORD *) &prAdapter->arStaRec[i]; + + if (prStaRec->fgIsInUse && prStaRec->ucBssIndex == ucBssIndex + && i != ucStaRecIndexExcluded) + cnmStaRoutinesForAbort(prAdapter, prStaRec); + } /* end of for loop */ + + if (ucStaRecIndexExcluded < CFG_STA_REC_NUM) + eAction = STA_REC_CMD_ACTION_BSS_EXCLUDE_STA; + else + eAction = STA_REC_CMD_ACTION_BSS; + + cnmStaSendRemoveCmd(prAdapter, + eAction, + ucStaRecIndexExcluded, ucBssIndex); + +#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 + */ + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + if (prAdapter->fgIsP2PRegistered + && prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + rlmUpdateParamsForAP(prAdapter, prBssInfo, FALSE); + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +struct STA_RECORD *cnmGetStaRecByIndex(struct ADAPTER *prAdapter, + uint8_t ucIndex) +{ + struct STA_RECORD *prStaRec; + + ASSERT(prAdapter); + + if (ucIndex < CFG_STA_REC_NUM) + prStaRec = &prAdapter->arStaRec[ucIndex]; + else + prStaRec = 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 + */ +/*----------------------------------------------------------------------------*/ +struct STA_RECORD *cnmGetStaRecByAddress(struct ADAPTER *prAdapter, + uint8_t ucBssIndex, uint8_t *pucPeerMacAddr) +{ + struct STA_RECORD *prStaRec; + uint16_t i; + + ASSERT(prAdapter); + + if (!pucPeerMacAddr) + return NULL; + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + + if (prStaRec->fgIsInUse + && prStaRec->ucBssIndex == ucBssIndex + && EQUAL_MAC_ADDR( + prStaRec->aucMacAddr, pucPeerMacAddr)) { + break; + } + } + + return (i < CFG_STA_REC_NUM) ? prStaRec : NULL; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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(struct ADAPTER *prAdapter, struct STA_RECORD *prStaRec + , uint8_t ucNewState) +{ + u_int8_t fgNeedResp; + + if (!prAdapter) + return; + + if (!prStaRec) { + log_dbg(MEM, WARN, "%s: StaRec is NULL, skip!\n", __func__); + return; + } + + if (!prStaRec->fgIsInUse) { + log_dbg(MEM, WARN, "%s: StaRec[%u] is not in use, skip!\n", + __func__, prStaRec->ucIndex); + return; + } + + /* 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; + cnmDumpStaRec(prAdapter, prStaRec->ucIndex); + } + } else { + if (ucNewState != prStaRec->ucStaState + && prStaRec->ucStaState == STA_STATE_3) + qmDeactivateStaRec(prAdapter, prStaRec); + fgNeedResp = FALSE; + } + prStaRec->ucStaState = ucNewState; + + cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, fgNeedResp); + +#if 1 /* Marked for MT6630 */ +#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))) { + struct BSS_INFO *prBssInfo; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) + rlmUpdateParamsForAP(prAdapter, prBssInfo, FALSE); + } +#endif +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param[in] + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +static void cnmStaRecHandleEventPkt(struct ADAPTER *prAdapter, + struct CMD_INFO *prCmdInfo, uint8_t *pucEventBuf) +{ + struct EVENT_ACTIVATE_STA_REC *prEventContent; + struct STA_RECORD *prStaRec; + + prEventContent = (struct EVENT_ACTIVATE_STA_REC *) 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) + */ +/*----------------------------------------------------------------------------*/ +void cnmStaSendUpdateCmd(struct ADAPTER *prAdapter, struct STA_RECORD *prStaRec, + struct TXBF_PFMU_STA_INFO *prTxBfPfmuStaInfo, u_int8_t fgNeedResp) +{ + struct CMD_UPDATE_STA_RECORD *prCmdContent; + uint32_t rStatus; + + if (!prAdapter) + return; + + if (!prStaRec) { + log_dbg(MEM, WARN, "%s: StaRec is NULL, skip!\n", __func__); + return; + } + + if (!prStaRec->fgIsInUse) { + log_dbg(MEM, WARN, "%s: StaRec[%u] is not in use, skip!\n", + __func__, prStaRec->ucIndex); + return; + } + + /* 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(struct CMD_UPDATE_STA_RECORD)); + + /* To do: exception handle */ + if (!prCmdContent) { + log_dbg(MEM, WARN, "%s: CMD_ID_UPDATE_STA_RECORD command allocation failed\n", + __func__); + + return; + } + + /* Reset command buffer */ + kalMemZero(prCmdContent, sizeof(struct CMD_UPDATE_STA_RECORD)); + + if (prTxBfPfmuStaInfo) { + memcpy(&prCmdContent->u2PfmuId, prTxBfPfmuStaInfo, + sizeof(struct TXBF_PFMU_STA_INFO)); + } + + prCmdContent->ucStaIndex = prStaRec->ucIndex; + prCmdContent->ucStaType = (uint8_t) prStaRec->eStaType; + kalMemCopy(&prCmdContent->aucMacAddr[0], &prStaRec->aucMacAddr[0], + MAC_ADDR_LEN); + prCmdContent->u2AssocId = prStaRec->u2AssocId; + prCmdContent->u2ListenInterval = prStaRec->u2ListenInterval; + prCmdContent->ucBssIndex = prStaRec->ucBssIndex; + + prCmdContent->ucDesiredPhyTypeSet = prStaRec->ucDesiredPhyTypeSet; + prCmdContent->u2DesiredNonHTRateSet = prStaRec->u2DesiredNonHTRateSet; + prCmdContent->u2BSSBasicRateSet = prStaRec->u2BSSBasicRateSet; + prCmdContent->ucMcsSet = prStaRec->ucMcsSet; + prCmdContent->ucSupMcs32 = (uint8_t) prStaRec->fgSupMcs32; + prCmdContent->u2HwDefaultFixedRateCode + = prStaRec->u2HwDefaultFixedRateCode; + + /* Size is SUP_MCS_RX_BITMASK_OCTET_NUM */ + kalMemCopy(prCmdContent->aucRxMcsBitmask, prStaRec->aucRxMcsBitmask, + sizeof(prCmdContent->aucRxMcsBitmask)); + prCmdContent->u2RxHighestSupportedRate + = prStaRec->u2RxHighestSupportedRate; + prCmdContent->u4TxRateInfo = prStaRec->u4TxRateInfo; + + prCmdContent->u2HtCapInfo = prStaRec->u2HtCapInfo; + prCmdContent->ucNeedResp = (uint8_t) 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->u4VhtCapInfo = prStaRec->u4VhtCapInfo; + prCmdContent->u2VhtRxMcsMap = prStaRec->u2VhtRxMcsMap; + prCmdContent->u2VhtRxHighestSupportedDataRate + = prStaRec->u2VhtRxHighestSupportedDataRate; + prCmdContent->u2VhtTxMcsMap = prStaRec->u2VhtTxMcsMap; + prCmdContent->u2VhtTxHighestSupportedDataRate + = prStaRec->u2VhtTxHighestSupportedDataRate; + prCmdContent->ucVhtOpMode = prStaRec->ucVhtOpMode; + + prCmdContent->ucUapsdAc + = prStaRec->ucBmpTriggerAC | (prStaRec->ucBmpDeliveryAC << 4); + prCmdContent->ucUapsdSp = prStaRec->ucUapsdSp; + + prCmdContent->ucWlanIndex = prStaRec->ucWlanIndex; + prCmdContent->ucBMCWlanIndex = WTBL_RESERVED_ENTRY; + + prCmdContent->ucTrafficDataType = prStaRec->ucTrafficDataType; + prCmdContent->ucTxGfMode = prStaRec->ucTxGfMode; + prCmdContent->ucTxSgiMode = prStaRec->ucTxSgiMode; + prCmdContent->ucTxStbcMode = prStaRec->ucTxStbcMode; + prCmdContent->u4FixedPhyRate = prStaRec->u4FixedPhyRate; + prCmdContent->u2MaxLinkSpeed = prStaRec->u2MaxLinkSpeed; + prCmdContent->u2MinLinkSpeed = prStaRec->u2MinLinkSpeed; + prCmdContent->u4Flags = prStaRec->u4Flags; +#if CFG_SUPPORT_MTK_SYNERGY + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucMtkOui)) { + if (IS_FEATURE_ENABLED( + prAdapter->rWifiVar.ucGbandProbe256QAM)) { + prCmdContent->u4Flags + |= MTK_SYNERGY_CAP_SUPPORT_24G_MCS89_PROBING; + } + } +#endif + prCmdContent->ucTxAmpdu = prAdapter->rWifiVar.ucAmpduTx; + prCmdContent->ucRxAmpdu = prAdapter->rWifiVar.ucAmpduRx; + + /* AMSDU in AMPDU global configuration */ + prCmdContent->ucTxAmsduInAmpdu = prAdapter->rWifiVar.ucAmsduInAmpduTx; + prCmdContent->ucRxAmsduInAmpdu = prAdapter->rWifiVar.ucAmsduInAmpduRx; +#if (CFG_SUPPORT_802_11AX == 1) + /* prStaRec->ucDesiredPhyTypeSet firm in */ + /* bssDetermineStaRecPhyTypeSet() in advance */ + if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11AX) { + /* HE peer AMSDU in AMPDU configuration */ + prCmdContent->ucTxAmsduInAmpdu &= + prAdapter->rWifiVar.ucHeAmsduInAmpduTx; + prCmdContent->ucRxAmsduInAmpdu &= + prAdapter->rWifiVar.ucHeAmsduInAmpduRx; + } else +#endif + if ((prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11AC) || + (prStaRec->u4Flags & MTK_SYNERGY_CAP_SUPPORT_24G_MCS89)) { + /* VHT pear AMSDU in AMPDU configuration */ + prCmdContent->ucTxAmsduInAmpdu + &= prAdapter->rWifiVar.ucVhtAmsduInAmpduTx; + prCmdContent->ucRxAmsduInAmpdu + &= prAdapter->rWifiVar.ucVhtAmsduInAmpduRx; + } else if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11N) { + /* HT peer AMSDU in AMPDU configuration */ + prCmdContent->ucTxAmsduInAmpdu + &= prAdapter->rWifiVar.ucHtAmsduInAmpduTx; + prCmdContent->ucRxAmsduInAmpdu + &= prAdapter->rWifiVar.ucHtAmsduInAmpduRx; + } + + prCmdContent->u4TxMaxAmsduInAmpduLen + = prAdapter->rWifiVar.u4TxMaxAmsduInAmpduLen; +#if (CFG_SUPPORT_802_11AX == 1) + if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11AX) { + prCmdContent->rBaSize.rHeBaSize.u2RxBaSize = + prAdapter->rWifiVar.u2RxHeBaSize; + prCmdContent->rBaSize.rHeBaSize.u2TxBaSize = + prAdapter->rWifiVar.u2TxHeBaSize; + } else +#endif + { + prCmdContent->rBaSize.rHtVhtBaSize.ucTxBaSize + = prAdapter->rWifiVar.ucTxBaSize; + + if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11AC) + prCmdContent->rBaSize.rHtVhtBaSize.ucTxBaSize + = prAdapter->rWifiVar.ucRxVhtBaSize; + else + prCmdContent->rBaSize.rHeBaSize.u2TxBaSize + = prAdapter->rWifiVar.ucRxHtBaSize; + } + + /* RTS Policy */ + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucSigTaRts)) { + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucDynBwRts)) + prCmdContent->ucRtsPolicy = RTS_POLICY_DYNAMIC_BW; + else + prCmdContent->ucRtsPolicy = RTS_POLICY_STATIC_BW; + } else + prCmdContent->ucRtsPolicy = RTS_POLICY_LEGACY; + +#if (CFG_SUPPORT_802_11AX == 1) + if (fgEfuseCtrlAxOn == 1) { + cnmStaRecCmdHeContentFill(prStaRec, prCmdContent); + } +#endif + + log_dbg(REQ, TRACE, "Update StaRec[%u] WIDX[%u] State[%u] Type[%u] BssIdx[%u] AID[%u]\n", + prCmdContent->ucStaIndex, + prCmdContent->ucWlanIndex, + prCmdContent->ucStaState, + prCmdContent->ucStaType, + prCmdContent->ucBssIndex, + prCmdContent->u2AssocId); + + log_dbg(REQ, TRACE, "Update StaRec[%u] QoS[%u] UAPSD[%u]\n", + prCmdContent->ucStaIndex, + prCmdContent->ucIsQoS, + prCmdContent->ucIsUapsdSupported); + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_UPDATE_STA_RECORD, /* ucCID */ + TRUE, /* fgSetQuery */ + fgNeedResp, /* fgNeedResp */ + FALSE, /* fgIsOid */ + fgNeedResp ? cnmStaRecHandleEventPkt : NULL, NULL, + /* pfCmdTimeoutHandler */ + sizeof(struct CMD_UPDATE_STA_RECORD), /* u4SetQueryInfoLen */ + (uint8_t *) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + cnmMemFree(prAdapter, prCmdContent); + + if (rStatus != WLAN_STATUS_PENDING) { + log_dbg(MEM, WARN, + "%s: CMD_ID_UPDATE_STA_RECORD result 0x%08x\n", + __func__, rStatus); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param[in] + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +static void +cnmStaSendRemoveCmd(struct ADAPTER *prAdapter, + enum ENUM_STA_REC_CMD_ACTION eActionType, + uint8_t ucStaRecIndex, uint8_t ucBssIndex) +{ + struct CMD_REMOVE_STA_RECORD rCmdContent; + uint32_t rStatus; + + ASSERT(prAdapter); + + rCmdContent.ucActionType = (uint8_t) eActionType; + rCmdContent.ucStaIndex = ucStaRecIndex; + rCmdContent.ucBssIndex = ucBssIndex; + rCmdContent.ucReserved = 0; + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_REMOVE_STA_RECORD, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct CMD_REMOVE_STA_RECORD), /* u4SetQueryInfoLen */ + (uint8_t *) &rCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + log_dbg(MEM, WARN, + "%s: CMD_ID_REMOVE_STA_RECORD result 0x%08x\n", + __func__, rStatus); + } +} + +uint8_t *cnmStaRecGetTypeString(enum ENUM_STA_TYPE eStaType) +{ + uint8_t *pucTypeString = NULL; + + if (eStaType & STA_TYPE_LEGACY_MASK) + pucTypeString = apucStaRecType[STA_TYPE_LEGACY_INDEX]; + if (eStaType & STA_TYPE_P2P_MASK) + pucTypeString = apucStaRecType[STA_TYPE_P2P_INDEX]; + if (eStaType & STA_TYPE_BOW_MASK) + pucTypeString = apucStaRecType[STA_TYPE_BOW_INDEX]; + + return pucTypeString; +} + +uint8_t *cnmStaRecGetRoleString(enum ENUM_STA_TYPE eStaType) +{ + uint8_t *pucRoleString = NULL; + + if (eStaType & STA_TYPE_ADHOC_MASK) { + pucRoleString = apucStaRecRole[ + STA_ROLE_ADHOC_INDEX - STA_ROLE_BASE_INDEX]; + } + if (eStaType & STA_TYPE_CLIENT_MASK) { + pucRoleString = apucStaRecRole[ + STA_ROLE_CLIENT_INDEX - STA_ROLE_BASE_INDEX]; + } + if (eStaType & STA_TYPE_AP_MASK) { + pucRoleString = apucStaRecRole[ + STA_ROLE_AP_INDEX - STA_ROLE_BASE_INDEX]; + } + if (eStaType & STA_TYPE_DLS_MASK) { + pucRoleString = apucStaRecRole[ + STA_ROLE_DLS_INDEX - STA_ROLE_BASE_INDEX]; + } + + return pucRoleString; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param[in] + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void cnmDumpStaRec(IN struct ADAPTER *prAdapter, IN uint8_t ucStaRecIdx) +{ + uint8_t ucWTEntry; + uint32_t i; + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + + DEBUGFUNC("cnmDumpStaRec"); + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIdx); + + if (!prStaRec) { + log_dbg(SW4, INFO, "Invalid StaRec index[%u], skip dump!\n", + ucStaRecIdx); + return; + } + + ucWTEntry = prStaRec->ucWlanIndex; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + ASSERT(prBssInfo); + + log_dbg(SW4, INFO, "============= DUMP STA[%u] ===========\n", + ucStaRecIdx); + /* [1]STA_IDX [2]BSS_IDX + * [3]MAC [4]TYPE + * [5]WTBL [6]USED + * [7]State [8]QoS + * [9]HT/VHT [10]AID + * [11]WMM [12]UAPSD + * [13]SEC [14]PhyTypeSet + * [15]Desired [16]NonHtBasic + * [17]BssBasic [18]Operational + * [19]DesiredNonHT [20]Df FixedRate + * [21]HT Cap [22]ExtCap + * [23]BeemCap [24]MCS + * [25]MCS32 [26]VHT Cap + * [27]TxMCS [28]RxMCS + * [29]VhtOpMode [30]RCPI + * [31]InPS [32]TxAllowed + * [33]KeyRdy [34]AMPDU + * [35]TxQLEN TC [36]BMP AC Delivery/Trigger + * [37]FreeQuota:Total [38]Delivery/NonDelivery + * [39]aucRxMcsBitmask + */ + + log_dbg(SW4, INFO, "[1][%u],[2][%u],[3][" MACSTR + "],[4][%s %s],[5][%u],[6][%u],[7][%u],[8][%u],[9][%u/%u],[10][%u]\n", + prStaRec->ucIndex, + prStaRec->ucBssIndex, + MAC2STR(prStaRec->aucMacAddr), + cnmStaRecGetTypeString(prStaRec->eStaType), + cnmStaRecGetRoleString(prStaRec->eStaType), + ucWTEntry, prStaRec->fgIsInUse, + prStaRec->ucStaState, prStaRec->fgIsQoS, + (prStaRec->ucDesiredPhyTypeSet + & PHY_TYPE_SET_802_11N) ? TRUE : FALSE, + (prStaRec->ucDesiredPhyTypeSet + & PHY_TYPE_SET_802_11AC) ? TRUE : FALSE, + prStaRec->u2AssocId); + + log_dbg(SW4, INFO, "[11][%u],[12][%u],[13][%u],[14][0x%x],[15][0x%x],[16][0x%x],[17][0x%x],[18][0x%x],[19][0x%x],[20][0x%x]\n", + prStaRec->fgIsWmmSupported, + prStaRec->fgIsUapsdSupported, + secIsProtectedBss(prAdapter, prBssInfo), + prBssInfo->ucPhyTypeSet, + prStaRec->ucDesiredPhyTypeSet, + prStaRec->ucNonHTBasicPhyType, + prBssInfo->u2BSSBasicRateSet, + prStaRec->u2OperationalRateSet, + prStaRec->u2DesiredNonHTRateSet, + prStaRec->u2HwDefaultFixedRateCode); + + log_dbg(SW4, INFO, "[21][0x%x],[22][0x%x],[23][0x%x],[24][0x%x],[25][%u],[26][0x%x],[27][0x%x],[28][0x%x],[29][0x%x],[30][%u]\n", + prStaRec->u2HtCapInfo, + prStaRec->u2HtExtendedCap, + prStaRec->u4TxBeamformingCap, + prStaRec->ucMcsSet, + prStaRec->fgSupMcs32, + prStaRec->u4VhtCapInfo, + prStaRec->u2VhtTxMcsMap, + prStaRec->u2VhtRxMcsMap, + prStaRec->ucVhtOpMode, + prStaRec->ucRCPI); + + log_dbg(SW4, INFO, "[31][%u],[32][%u],[33][%u],[34][%u/%u],[35][%u:%u:%u:%u],[36][%x/%x],[37][%u],[38][%u/%u],[39][0x%x][0x%x]\n", + prStaRec->fgIsInPS, + prStaRec->fgIsTxAllowed, + prStaRec->fgIsTxKeyReady, + prStaRec->fgTxAmpduEn, + prStaRec->fgRxAmpduEn, + prStaRec->aprTargetQueue[0]->u4NumElem, + prStaRec->aprTargetQueue[1]->u4NumElem, + prStaRec->aprTargetQueue[2]->u4NumElem, + prStaRec->aprTargetQueue[3]->u4NumElem, + prStaRec->ucBmpDeliveryAC, + prStaRec->ucBmpTriggerAC, + prStaRec->ucFreeQuota, + prStaRec->ucFreeQuotaForDelivery, + prStaRec->ucFreeQuotaForNonDelivery, + prStaRec->aucRxMcsBitmask[0], + prStaRec->aucRxMcsBitmask[1]); + + for (i = 0; i < CFG_RX_MAX_BA_TID_NUM; i++) { + if (prStaRec->aprRxReorderParamRefTbl[i]) { + log_dbg(SW4, INFO, "TID[%u],Valid[%u],WinStart/End[%u/%u],WinSize[%u],ReOrderQueLen[%u],Bubble Exist[%u],SN[%u]\n", + prStaRec->aprRxReorderParamRefTbl[i] + ->ucTid, + prStaRec->aprRxReorderParamRefTbl[i] + ->fgIsValid, + prStaRec->aprRxReorderParamRefTbl[i] + ->u2WinStart, + prStaRec->aprRxReorderParamRefTbl[i] + ->u2WinEnd, + prStaRec->aprRxReorderParamRefTbl[i] + ->u2WinSize, + prStaRec->aprRxReorderParamRefTbl[i] + ->rReOrderQue.u4NumElem, + prStaRec->aprRxReorderParamRefTbl[i] + ->fgHasBubble, + prStaRec->aprRxReorderParamRefTbl[i] + ->u2FirstBubbleSn); + } + } + log_dbg(SW4, INFO, "============= DUMP END ===========\n"); +} + +uint32_t cnmDumpMemoryStatus(IN struct ADAPTER *prAdapter, IN uint8_t *pucBuf, + IN uint32_t u4Max) +{ + uint32_t u4Len = 0; +#if CFG_DBG_MGT_BUF + struct BUF_INFO *prBufInfo; + + LOGBUF(pucBuf, u4Max, u4Len, "\n"); + LOGBUF(pucBuf, u4Max, u4Len, + "============= DUMP Memory Status =============\n"); + + LOGBUF(pucBuf, u4Max, u4Len, + "Dynamic alloc OS memory count: alloc[%u] free[%u]\n", + prAdapter->u4MemAllocDynamicCount, + prAdapter->u4MemFreeDynamicCount); + + prBufInfo = &prAdapter->rMsgBufInfo; + + LOGBUF(pucBuf, u4Max, u4Len, + "MSG memory count: alloc[%u] free[%u] null[%u] bitmap[0x%08x]\n" + , + prBufInfo->u4AllocCount, + prBufInfo->u4FreeCount, + prBufInfo->u4AllocNullCount, + (uint32_t) prBufInfo->rFreeBlocksBitmap); + + prBufInfo = &prAdapter->rMgtBufInfo; + + LOGBUF(pucBuf, u4Max, u4Len, + "MGT memory count: alloc[%u] free[%u] null[%u] bitmap[0x%08x]\n" + , + prBufInfo->u4AllocCount, + prBufInfo->u4FreeCount, + prBufInfo->u4AllocNullCount, + (uint32_t) prBufInfo->rFreeBlocksBitmap); + + LOGBUF(pucBuf, u4Max, u4Len, "============= DUMP END =============\n"); + +#endif + + return u4Len; +} + +#if CFG_SUPPORT_TDLS +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to add a peer record. + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t /* TDLS_STATUS, prStaRec->ucNetTypeIndex */ +cnmPeerAdd(struct ADAPTER *prAdapter, void *pvSetBuffer, + uint32_t u4SetBufferLen, uint32_t *pu4SetInfoLen) +{ + struct CMD_PEER_ADD *prCmd; + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec, *prStaRecOfAp; + + /* sanity check */ + + if ((prAdapter == NULL) || (pvSetBuffer == NULL) + || (pu4SetInfoLen == NULL)) + return TDLS_STATUS_FAIL; + + /* init */ + *pu4SetInfoLen = sizeof(struct CMD_PEER_ADD); + prCmd = (struct CMD_PEER_ADD *) pvSetBuffer; + + prBssInfo + = GET_BSS_INFO_BY_INDEX(prAdapter, prCmd->ucBssIdx); + if (prBssInfo == NULL) { + log_dbg(MEM, ERROR, "prBssInfo %d is NULL!\n" + , prCmd->ucBssIdx); + return TDLS_STATUS_FAIL; + } + + prStaRec = cnmGetStaRecByAddress(prAdapter, + (uint8_t) prBssInfo->ucBssIndex, + prCmd->aucPeerMac); + + if (prStaRec == NULL) { + prStaRec = + cnmStaRecAlloc(prAdapter, STA_TYPE_DLS_PEER, + (uint8_t) prBssInfo->ucBssIndex, + prCmd->aucPeerMac); + + if (prStaRec == NULL) + return TDLS_STATUS_RESOURCES; + + if (prBssInfo->ucBssIndex) + prStaRec->ucBssIndex = prBssInfo->ucBssIndex; + + /* init the prStaRec */ + /* prStaRec will be zero first in cnmStaRecAlloc() */ + COPY_MAC_ADDR(prStaRec->aucMacAddr, prCmd->aucPeerMac); + + prStaRec->u2BSSBasicRateSet = prBssInfo->u2BSSBasicRateSet; + prStaRec->ucDesiredPhyTypeSet + = prAdapter->rWifiVar.ucAvailablePhyTypeSet; + prStaRec->u2DesiredNonHTRateSet + = prAdapter->rWifiVar.ucAvailablePhyTypeSet; + + prStaRec->u2OperationalRateSet + = prBssInfo->u2OperationalRateSet; + prStaRec->ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + prStaRec->eStaType = prCmd->eStaType; + + /* align setting with AP */ + prStaRecOfAp = prBssInfo->prStaRecOfAP; + if (prStaRecOfAp) { + prStaRec->u2DesiredNonHTRateSet + = prStaRecOfAp->u2DesiredNonHTRateSet; + } + + /* Init lowest rate to prevent CCK in 5G band */ + nicTxUpdateStaRecDefaultRate(prAdapter, prStaRec); + + /* Better to change state here, not at TX Done */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + } else { + if ((prStaRec->ucStaState > STA_STATE_1) + && (IS_DLS_STA(prStaRec))) { + /* TODO: Teardown the peer */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + } + } + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to update a peer record. + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t /* TDLS_STATUS */ +cnmPeerUpdate(struct ADAPTER *prAdapter, void *pvSetBuffer, + uint32_t u4SetBufferLen, uint32_t *pu4SetInfoLen) +{ + + struct CMD_PEER_UPDATE *prCmd; + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint8_t ucNonHTPhyTypeSet; + + uint16_t u2OperationalRateSet = 0; + + uint8_t ucRate; + uint16_t i, j; + + /* sanity check */ + if ((!prAdapter) || (!pvSetBuffer) || (!pu4SetInfoLen)) + return TDLS_STATUS_FAIL; + + /* init */ + *pu4SetInfoLen = sizeof(struct CMD_PEER_ADD); + prCmd = (struct CMD_PEER_UPDATE *) pvSetBuffer; + + prBssInfo + = GET_BSS_INFO_BY_INDEX(prAdapter, prCmd->ucBssIdx); + + if (prBssInfo == NULL) { + log_dbg(MEM, ERROR, "prBssInfo %d is NULL!\n" + , prCmd->ucBssIdx); + return TDLS_STATUS_FAIL; + } + prStaRec = cnmGetStaRecByAddress(prAdapter, + (uint8_t) prBssInfo->ucBssIndex, + prCmd->aucPeerMac); + + if ((!prStaRec) || !(prStaRec->fgIsInUse)) + return TDLS_STATUS_FAIL; + + if (!IS_DLS_STA(prStaRec)) + return TDLS_STATUS_FAIL; + + if (prBssInfo) { + if (prBssInfo->ucBssIndex) + prStaRec->ucBssIndex = prBssInfo->ucBssIndex; + } + + /* update the record join time. */ + GET_CURRENT_SYSTIME(&prStaRec->rUpdateTime); + + /* update Station Record - Status/Reason Code */ + prStaRec->u2StatusCode = prCmd->u2StatusCode; + prStaRec->u2AssocId = 0; /* no use */ + prStaRec->u2ListenInterval = 0; /* unknown */ + prStaRec->fgIsQoS = TRUE; + prStaRec->fgIsUapsdSupported + = ((1 << 4) & prCmd->aucExtCap[3]) ? TRUE : FALSE; + prStaRec->u4TxBeamformingCap = 0; /* no use */ + prStaRec->ucAselCap = 0; /* no use */ + prStaRec->ucRCPI = 120; + prStaRec->ucBmpTriggerAC = prCmd->UapsdBitmap; + prStaRec->ucBmpDeliveryAC = prCmd->UapsdBitmap; + prStaRec->ucUapsdSp = prCmd->UapsdMaxSp; + prStaRec->eStaType = prCmd->eStaType; + + /* ++ support rate */ + if (prCmd->u2SupRateLen) { + for (i = 0; i < prCmd->u2SupRateLen; i++) { + if (prCmd->aucSupRate[i]) { + ucRate = prCmd->aucSupRate[i] & RATE_MASK; + /* Search all valid data rates */ + for (j = 0; j < sizeof(aucValidDataRate) + / sizeof(uint8_t); j++) { + if (ucRate == aucValidDataRate[j]) { + u2OperationalRateSet |= BIT(j); + break; + } + } + } + + } + + prStaRec->u2OperationalRateSet = u2OperationalRateSet; + prStaRec->u2BSSBasicRateSet = prBssInfo->u2BSSBasicRateSet; + + /* 4 <5> PHY type setting */ + + prStaRec->ucPhyTypeSet = 0; + + if (prBssInfo->eBand == BAND_2G4) { + if (prCmd->fgIsSupHt) + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HT; + + /* if not 11n only */ + if (!(prStaRec->u2BSSBasicRateSet + & RATE_SET_BIT_HT_PHY)) { + /* check if support 11g */ + if ((prStaRec->u2OperationalRateSet + & RATE_SET_OFDM)) { + prStaRec->ucPhyTypeSet + |= PHY_TYPE_BIT_ERP; + } + + /* if not 11g only */ + if (!(prStaRec->u2BSSBasicRateSet + & RATE_SET_OFDM)) { + /* check if support 11b */ + if ((prStaRec->u2OperationalRateSet + & RATE_SET_HR_DSSS)) { + prStaRec->ucPhyTypeSet + |= PHY_TYPE_BIT_HR_DSSS; + } + } + } + } else { + if (prCmd->rVHtCap.u2CapInfo) + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_VHT; + + if (prCmd->fgIsSupHt) + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HT; + + /* if not 11n only */ + if (!(prStaRec->u2BSSBasicRateSet + & RATE_SET_BIT_HT_PHY)) { + /* Support 11a definitely */ + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_OFDM; + } + } + + if (IS_STA_IN_AIS(prStaRec)) { + struct CONNECTION_SETTINGS *prConnSettings; + enum ENUM_WEP_STATUS eEncStatus; + + prConnSettings = + aisGetConnSettings(prAdapter, + prStaRec->ucBssIndex); + + eEncStatus = prConnSettings->eEncStatus; + + if (!((eEncStatus == ENUM_ENCRYPTION3_ENABLED) + || (eEncStatus == ENUM_ENCRYPTION3_KEY_ABSENT) + || (eEncStatus == ENUM_ENCRYPTION_DISABLED) + )) { + + 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 + 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; + } + + } + + /* ++HT capability */ + + if (prCmd->fgIsSupHt) { + prAdapter->rWifiVar.eRateSetting = FIXED_RATE_NONE; + prStaRec->ucDesiredPhyTypeSet |= PHY_TYPE_BIT_HT; + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HT; + prStaRec->u2HtCapInfo = prCmd->rHtCap.u2CapInfo; + if (!IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxLdpc)) + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_LDPC_CAP; + prStaRec->ucAmpduParam = prCmd->rHtCap.ucAmpduParamsInfo; + prStaRec->u2HtExtendedCap = prCmd->rHtCap.u2ExtHtCapInfo; + prStaRec->u4TxBeamformingCap = prCmd->rHtCap.u4TxBfCapInfo; + prStaRec->ucAselCap = prCmd->rHtCap.ucAntennaSelInfo; + prStaRec->ucMcsSet = prCmd->rHtCap.rMCS.arRxMask[0]; + if (prCmd->rHtCap.rMCS.arRxMask[32 / 8] & BIT(0)) + prStaRec->fgSupMcs32 = TRUE; + else + prStaRec->fgSupMcs32 = FALSE; + kalMemCopy(prStaRec->aucRxMcsBitmask, + prCmd->rHtCap.rMCS.arRxMask, + sizeof(prStaRec->aucRxMcsBitmask)); + } + /* TODO ++VHT */ + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Get TDLS peer 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 + */ +/*----------------------------------------------------------------------------*/ +struct STA_RECORD *cnmGetTdlsPeerByAddress(struct ADAPTER *prAdapter, + uint8_t ucBssIndex, uint8_t aucPeerMACAddress[]) +{ + struct STA_RECORD *prStaRec; + uint16_t i; + + ASSERT(prAdapter); + ASSERT(aucPeerMACAddress); + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + if (prStaRec) { + if (prStaRec->fgIsInUse + && prStaRec->eStaType == STA_TYPE_DLS_PEER + && EQUAL_MAC_ADDR(prStaRec->aucMacAddr, + aucPeerMACAddress)) { + break; + } + } + } + + return prStaRec; +} + +#endif + +#if (CFG_SUPPORT_802_11AX == 1) +static void cnmStaRecCmdHeContentFill( + struct STA_RECORD *prStaRec, + struct CMD_UPDATE_STA_RECORD *prCmdContent) +{ + prCmdContent->ucVersion = CMD_UPDATE_STAREC_VER1; + memcpy(prCmdContent->ucHeMacCapInfo, prStaRec->ucHeMacCapInfo, + HE_MAC_CAP_BYTE_NUM); + memcpy(prCmdContent->ucHePhyCapInfo, prStaRec->ucHePhyCapInfo, + HE_PHY_CAP_BYTE_NUM); + + prCmdContent->u2HeRxMcsMapBW80 = + CPU_TO_LE16(prStaRec->u2HeRxMcsMapBW80); + prCmdContent->u2HeTxMcsMapBW80 = + CPU_TO_LE16(prStaRec->u2HeTxMcsMapBW80); + prCmdContent->u2HeRxMcsMapBW160 = + CPU_TO_LE16(prStaRec->u2HeRxMcsMapBW160); + prCmdContent->u2HeTxMcsMapBW160 = + CPU_TO_LE16(prStaRec->u2HeTxMcsMapBW160); + prCmdContent->u2HeRxMcsMapBW80P80 = + CPU_TO_LE16(prStaRec->u2HeRxMcsMapBW80P80); + prCmdContent->u2HeTxMcsMapBW80P80 = + CPU_TO_LE16(prStaRec->u2HeTxMcsMapBW80P80); +} +#endif + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/cnm_timer.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/cnm_timer.c new file mode 100644 index 0000000000000..b1403bbba2dc3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/cnm_timer.c @@ -0,0 +1,712 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/cnm_timer.c#1 + */ + +/*! \file "cnm_timer.c" + * \brief + * + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +static void cnmTimerStopTimer_impl(IN struct ADAPTER *prAdapter, + IN struct TIMER *prTimer, IN u_int8_t fgAcquireSpinlock); +static u_int8_t cnmTimerIsTimerValid(IN struct ADAPTER *prAdapter, + IN struct TIMER *prTimer); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine dump timer list for debug purpose + * + * \param[in] + * + * \retval + * + */ +/*----------------------------------------------------------------------------*/ +static void cnmTimerDumpTimer(IN struct ADAPTER *prAdapter) +{ + struct ROOT_TIMER *prRootTimer; + struct LINK_ENTRY *prLinkEntry; + struct TIMER *prTimerEntry; + struct LINK *prTimerList; + + prRootTimer = &prAdapter->rRootTimer; + prTimerList = &prRootTimer->rLinkHead; + + log_dbg(CNM, INFO, "Current time:%u\n", kalGetTimeTick()); + + LINK_FOR_EACH(prLinkEntry, prTimerList) { + if (prLinkEntry == NULL) + break; + + prTimerEntry = LINK_ENTRY(prLinkEntry, + struct TIMER, rLinkEntry); + + log_dbg(CNM, INFO, "timer:%p, func:%pf, ExpiredSysTime:%u\n", + prTimerEntry, + prTimerEntry->pfMgmtTimeOutFunc, + prTimerEntry->rExpiredSysTime); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to check if a timer exists in timer list. + * + * \param[in] prTimer The timer to check + * + * \retval TRUE Valid timer + * FALSE Invalid timer + * + */ +/*----------------------------------------------------------------------------*/ +static u_int8_t cnmTimerIsTimerValid(IN struct ADAPTER *prAdapter, + IN struct TIMER *prTimer) +{ + struct ROOT_TIMER *prRootTimer; + struct LINK *prTimerList; + struct LINK_ENTRY *prLinkEntry; + struct TIMER *prPendingTimer; + + ASSERT(prAdapter); + + prRootTimer = &prAdapter->rRootTimer; + + /* Check if the timer is in timer list */ + prTimerList = &(prAdapter->rRootTimer.rLinkHead); + + LINK_FOR_EACH(prLinkEntry, prTimerList) { + if (prLinkEntry == NULL) + break; + + prPendingTimer = LINK_ENTRY(prLinkEntry, + struct TIMER, rLinkEntry); + + if (prPendingTimer == prTimer) + return TRUE; + } + + log_dbg(CNM, WARN, "invalid pending timer %p func %pf\n", + prTimer, prTimer->pfMgmtTimeOutFunc); + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 u_int8_t cnmTimerSetTimer(IN struct ADAPTER *prAdapter, + IN OS_SYSTIME rTimeout, + IN enum ENUM_TIMER_WAKELOCK_TYPE_T eType) +{ + struct ROOT_TIMER *prRootTimer; + u_int8_t fgNeedWakeLock; + + ASSERT(prAdapter); + + prRootTimer = &prAdapter->rRootTimer; + + kalSetTimer(prAdapter->prGlueInfo, rTimeout); + + if ((eType == TIMER_WAKELOCK_REQUEST) + || (rTimeout <= SEC_TO_SYSTIME(WAKE_LOCK_MAX_TIME) + && (eType == TIMER_WAKELOCK_AUTO))) { + 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 struct ADAPTER *prAdapter) +{ + struct ROOT_TIMER *prRootTimer; + struct LINK *prTimerList; + struct LINK_ENTRY *prLinkEntry; + struct TIMER *prPendingTimer; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prRootTimer = &prAdapter->rRootTimer; + + /* Note: glue layer have configured timer */ + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + + log_dbg(CNM, WARN, "reset timer list\n"); + + /* Remove all pending timers */ + prTimerList = &(prAdapter->rRootTimer.rLinkHead); + + LINK_FOR_EACH(prLinkEntry, prTimerList) { + if (prLinkEntry == NULL) + break; + + prPendingTimer = LINK_ENTRY(prLinkEntry, + struct TIMER, rLinkEntry); + + /* Remove timer to prevent collapsing timer structure */ + cnmTimerStopTimer_impl(prAdapter, prPendingTimer, FALSE); + } + + LINK_INITIALIZE(&prRootTimer->rLinkHead); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + + KAL_WAKE_LOCK_INIT(prAdapter, prRootTimer->rWakeLock, "WLAN Timer"); + prRootTimer->fgWakeLocked = FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routines is called to destroy a root timer. + * When WIFI is off, the token shall be returned back to system. + * + * \param[in] + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void cnmTimerDestroy(IN struct ADAPTER *prAdapter) +{ + struct ROOT_TIMER *prRootTimer; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prRootTimer = &prAdapter->rRootTimer; + + if (prRootTimer->fgWakeLocked) { + KAL_WAKE_UNLOCK(prAdapter, prRootTimer->rWakeLock); + prRootTimer->fgWakeLocked = FALSE; + } + KAL_WAKE_LOCK_DESTROY(prAdapter, prRootTimer->rWakeLock); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + LINK_INITIALIZE(&prRootTimer->rLinkHead); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + + /* Note: glue layer will be responsible for timer destruction */ +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routines is called to initialize a timer. + * + * \param[in] prTimer Pointer to a timer structure. + * \param[in] pfnFunc Pointer to the call back function. + * \param[in] u4Data Parameter for call back function. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void +cnmTimerInitTimerOption(IN struct ADAPTER *prAdapter, + IN struct TIMER *prTimer, + IN PFN_MGMT_TIMEOUT_FUNC pfFunc, + IN unsigned long ulDataPtr, + IN enum ENUM_TIMER_WAKELOCK_TYPE_T eType) +{ + struct LINK *prTimerList; + struct LINK_ENTRY *prLinkEntry; + struct LINK_ENTRY *prTempLinkEntry; + /* Previous valid timer before the dangling timer */ + struct LINK_ENTRY *prPrevLinkEntry = NULL; + /* Next valid timer after the dangling timer */ + struct LINK_ENTRY *prNextLinkEntry = NULL; + struct TIMER *prPendingTimer; + + KAL_SPIN_LOCK_DECLARATION(); + ASSERT(prAdapter); + + ASSERT(prTimer); + + ASSERT((eType >= TIMER_WAKELOCK_AUTO) && (eType < TIMER_WAKELOCK_NUM)); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + + /* Remove pending timer */ + prTimerList = &(prAdapter->rRootTimer.rLinkHead); + + LINK_FOR_EACH(prLinkEntry, prTimerList) { + if (prLinkEntry == NULL) + break; + + prPendingTimer = LINK_ENTRY(prLinkEntry, + struct TIMER, rLinkEntry); + + if (prPendingTimer == prTimer) { + log_dbg(CNM, WARN, "re-init timer, timer %p func %pf\n", + prTimer, pfFunc); + + if (timerPendingTimer(prTimer)) { + /* Remove pending timer to prevent + * collapsing timer list. + */ + cnmTimerStopTimer_impl(prAdapter, + prTimer, FALSE); + continue; + } + + /* Timer structure was collapsed. Try to fix it. */ + log_dbg(CNM, WARN, "timer was collapsed. fix it!\n"); + LINK_FOR_EACH_PREV(prTempLinkEntry, prTimerList) { + if (prTempLinkEntry == NULL) + break; + + prPendingTimer = LINK_ENTRY( + prTempLinkEntry, + struct TIMER, rLinkEntry); + + if (prPendingTimer == prTimer) { + if (prNextLinkEntry == NULL) { + /* Link to head */ + prNextLinkEntry = + (struct LINK_ENTRY *) + prTimerList; + } + + /* Link to head */ + if (prPrevLinkEntry == NULL) { + prTimerList->prNext = + prNextLinkEntry; + prNextLinkEntry->prPrev = + (struct LINK_ENTRY *) + prTimerList; + prTimerList->u4NumElem--; + } else { /* Link to previous entry */ + prPrevLinkEntry->prNext = + prNextLinkEntry; + prNextLinkEntry->prPrev = + prPrevLinkEntry; + prTimerList->u4NumElem--; + } + + /* Dump timer */ + cnmTimerDumpTimer(prAdapter); + break; + } + /* Record next pending timer entry */ + prNextLinkEntry = prTempLinkEntry; + } + } + /* Record previous pending timer entry */ + prPrevLinkEntry = prLinkEntry; + } + + LINK_ENTRY_INITIALIZE(&prTimer->rLinkEntry); + + prTimer->pfMgmtTimeOutFunc = pfFunc; + prTimer->ulDataPtr = ulDataPtr; + prTimer->eType = eType; + + 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) + */ +/*----------------------------------------------------------------------------*/ +static void cnmTimerStopTimer_impl(IN struct ADAPTER *prAdapter, + IN struct TIMER *prTimer, IN u_int8_t fgAcquireSpinlock) +{ + struct 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 struct ADAPTER *prAdapter, IN struct TIMER *prTimer) +{ + ASSERT(prAdapter); + ASSERT(prTimer); + + log_dbg(CNM, TRACE, "stop timer, timer %p func %pf\n", + prTimer, prTimer->pfMgmtTimeOutFunc); + + 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 struct ADAPTER *prAdapter, IN struct TIMER *prTimer, + IN uint32_t u4TimeoutMs) +{ + struct ROOT_TIMER *prRootTimer; + struct LINK *prTimerList; + OS_SYSTIME rExpiredSysTime, rTimeoutSystime; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prTimer); + + log_dbg(CNM, TRACE, "start timer, timer %p func %pf %d ms\n", + prTimer, prTimer->pfMgmtTimeOutFunc, u4TimeoutMs); + +#if (CFG_SUPPORT_STATISTICS == 1) + /* Do not print oid timer to avoid log too much. + * We can deduce existence of OID timer from cmd and event. + */ + if ((prTimer != NULL) && (&(prAdapter->rOidTimeoutTimer) != prTimer) + && (wlan_fb_power_down == TRUE)) { + DBGLOG_LIMITED(CNM, INFO, + "[WLAN-LP] Start timer %p %u ms -handler(%pf)\n", + prTimer, + u4TimeoutMs, + prTimer->pfMgmtTimeOutFunc); + } +#endif + + 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 <= ((uint32_t) 0xFFFF * MSEC_PER_MIN)); + + prTimer->u2Minutes = (uint16_t) (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 < (((uint32_t) 0x80000000 - MSEC_PER_SEC) / KAL_HZ)); + rTimeoutSystime = MSEC_TO_SYSTIME(u4TimeoutMs); + if (rTimeoutSystime == 0) + rTimeoutSystime = 1; + 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, prTimer->eType); + } + + /* Add this timer to checking list */ + prTimer->rExpiredSysTime = rExpiredSysTime; + + if (!timerPendingTimer(prTimer)) { + LINK_INSERT_TAIL(prTimerList, &prTimer->rLinkEntry); + } else { + /* If the pending timer is not in timer list, we will have + * to add the timer to timer list anyway. Otherwise, the timer + * will never timeout. + */ + if (!cnmTimerIsTimerValid(prAdapter, prTimer)) + LINK_INSERT_TAIL(prTimerList, &prTimer->rLinkEntry); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routines is called to check the timer list. + * + * \param[in] + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void cnmTimerDoTimeOutCheck(IN struct ADAPTER *prAdapter) +{ + struct ROOT_TIMER *prRootTimer; + struct LINK *prTimerList; + struct LINK_ENTRY *prLinkEntry; + struct TIMER *prTimer; + OS_SYSTIME rCurSysTime; + PFN_MGMT_TIMEOUT_FUNC pfMgmtTimeOutFunc; + unsigned long ulTimeoutDataPtr; + u_int8_t fgNeedWakeLock; + enum ENUM_TIMER_WAKELOCK_TYPE_T eType = TIMER_WAKELOCK_NONE; + + 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) { + if (prLinkEntry == NULL) + break; + + prTimer = LINK_ENTRY(prLinkEntry, struct TIMER, rLinkEntry); + ASSERT(prTimer); + + /* Check if this entry is timeout. */ + if (!TIME_BEFORE(rCurSysTime, prTimer->rExpiredSysTime)) { + if (timerPendingTimer(prTimer)) { + cnmTimerStopTimer_impl(prAdapter, + prTimer, FALSE); + + pfMgmtTimeOutFunc = prTimer->pfMgmtTimeOutFunc; + ulTimeoutDataPtr = prTimer->ulDataPtr; + + 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); + #ifdef UT_TEST_MODE + if (testTimerTimeout(prAdapter, + pfMgmtTimeOutFunc, + ulTimeoutDataPtr)) + #endif + log_dbg(CNM, TRACE, "timer timeout, timer %p func %pf\n", + prTimer, prTimer->pfMgmtTimeOutFunc); + + (pfMgmtTimeOutFunc) (prAdapter, + ulTimeoutDataPtr); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TIMER); + } + } else { + log_dbg(CNM, WARN, "timer was re-inited, timer %p func %pf\n", + prTimer, prTimer->pfMgmtTimeOutFunc); + break; + } + + /* Search entire list again because of nest del and add + * timers and current MGMT_TIMER could be volatile after + * stopped + */ + prLinkEntry = (struct LINK_ENTRY *) prTimerList; + if (prLinkEntry == NULL) + break; + + prRootTimer->rNextExpiredSysTime + = rCurSysTime + MGMT_MAX_TIMEOUT_INTERVAL; + } else if (TIME_BEFORE(prTimer->rExpiredSysTime, + prRootTimer->rNextExpiredSysTime)) { + prRootTimer->rNextExpiredSysTime + = prTimer->rExpiredSysTime; + + if (prTimer->eType == TIMER_WAKELOCK_REQUEST) + eType = TIMER_WAKELOCK_REQUEST; + else if ((eType != TIMER_WAKELOCK_REQUEST) + && (prTimer->eType == TIMER_WAKELOCK_AUTO)) + eType = TIMER_WAKELOCK_AUTO; + } + } /* 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)((int32_t) prRootTimer->rNextExpiredSysTime + - (int32_t) rCurSysTime), + eType); + } + + if (prRootTimer->fgWakeLocked && !fgNeedWakeLock) { + KAL_WAKE_UNLOCK(prAdapter, prRootTimer->rWakeLock); + prRootTimer->fgWakeLocked = FALSE; + } + + /* release spin lock */ + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/he_ie.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/he_ie.c new file mode 100644 index 0000000000000..9a7cc8dd7386f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/he_ie.c @@ -0,0 +1,104 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: @(#) he_rlm.c@@ +*/ + +/*! \file "he_ie.c" +* \brief This file contains HE IE processing routines. +* +*/ + +#include "precomp.h" + +#if (CFG_SUPPORT_802_11AX == 1) +#include "he_ie.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 /* CFG_SUPPORT_802_11AX == 1 */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/he_rlm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/he_rlm.c new file mode 100644 index 0000000000000..e62918647387a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/he_rlm.c @@ -0,0 +1,1213 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: @(#) he_rlm.c@@ +*/ + +/*! \file "he_rlm.c" +* \brief This file contains HE Phy processing routines. +* +*/ + +/******************************************************************************* +* C O M P I L E 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_11AX == 1) +#include "he_rlm.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/* + * Ignore PPE Threshold (Optional) currently + * PPE threshold should be filled based on HW RX capability + */ +#define CFG_RX_PPE_THRESHOLD 1 + +/* + * NSS: 3 bits + * RU Index Bitmask: 4 bits + * PPET8 & PPET16 info for 2NSS and 4 RU index size: 6 * 2 * 4 = 48 bits + * PPE pad: 1 bit + * Total = 56 bits = 7 bytes + */ +#define MAX_PPE_THRESHOLD_LEN_2NSS 7 +#define MAX_PPE_THRESHOLD_LEN_1NSS 4 + +#if (CFG_SUPPORT_HE_ER == 1) +#define MAX_SUPPORT_CONSTELLATION_DCM_QPSK 2 +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +/* TBD: where/what is the proper place/way to store this config */ +uint8_t g_au8RlmHeCfgContellIdx[4][4][2] = { + /* NSS1 */ + {{CONSTELL_IDX_BPSK, CONSTELL_IDX_NONE}, /* RU idx 0 */ + {CONSTELL_IDX_BPSK, CONSTELL_IDX_NONE}, /* RU idx 1 */ + {CONSTELL_IDX_BPSK, CONSTELL_IDX_NONE}, /* RU idx 2 */ + {CONSTELL_IDX_BPSK, CONSTELL_IDX_NONE} }, /* RU idx 3 */ + /* NSS2 */ + {{CONSTELL_IDX_BPSK, CONSTELL_IDX_NONE}, /* RU idx 0 */ + {CONSTELL_IDX_BPSK, CONSTELL_IDX_NONE}, /* RU idx 1 */ + {CONSTELL_IDX_BPSK, CONSTELL_IDX_NONE}, /* RU idx 2 */ + {CONSTELL_IDX_BPSK, CONSTELL_IDX_NONE} }, /* RU idx 3 */ + /* NSS3 */ + {{CONSTELL_IDX_BPSK, CONSTELL_IDX_NONE}, /* RU idx 0 */ + {CONSTELL_IDX_BPSK, CONSTELL_IDX_NONE}, /* RU idx 1 */ + {CONSTELL_IDX_BPSK, CONSTELL_IDX_NONE}, /* RU idx 2 */ + {CONSTELL_IDX_BPSK, CONSTELL_IDX_NONE} }, /* RU idx 3 */ + /* NSS4 */ + {{CONSTELL_IDX_BPSK, CONSTELL_IDX_NONE}, /* RU idx 0 */ + {CONSTELL_IDX_BPSK, CONSTELL_IDX_NONE}, /* RU idx 1 */ + {CONSTELL_IDX_BPSK, CONSTELL_IDX_NONE}, /* RU idx 2 */ + {CONSTELL_IDX_BPSK, CONSTELL_IDX_NONE} } /* RU idx 3 */ +}; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define PPET_SUBFIELD_MASK 0x7 +#define BIT64(n) ((u_int64_t) 1UL << (n)) +#define BITS64(m, n) (~(BIT64(m)-1) & ((BIT64(n) - 1) | BIT64(n))) + +/******************************************************************************* +* 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 +******************************************************************************** +*/ +uint8_t _heGetBssBandBw(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + enum ENUM_BAND eBand) +{ + uint8_t ucMaxBandwidth = MAX_BW_20MHZ; + + if (IS_BSS_AIS(prBssInfo)) { + if (eBand == BAND_2G4) + ucMaxBandwidth = prAdapter->rWifiVar.ucSta2gBandwidth; + else + ucMaxBandwidth = prAdapter->rWifiVar.ucSta5gBandwidth; + + if (ucMaxBandwidth > prAdapter->rWifiVar.ucStaBandwidth) + ucMaxBandwidth = prAdapter->rWifiVar.ucStaBandwidth; + } else if (IS_BSS_P2P(prBssInfo)) { + /* AP mode */ + if (p2pFuncIsAPMode( + prAdapter->rWifiVar.prP2PConnSettings[ + prBssInfo->u4PrivateData])) { + if (prBssInfo->eBand == BAND_2G4) + ucMaxBandwidth = prAdapter->rWifiVar + .ucAp2gBandwidth; + else + ucMaxBandwidth = prAdapter->rWifiVar + .ucAp5gBandwidth; + + if (ucMaxBandwidth + > prAdapter->rWifiVar.ucApBandwidth) + ucMaxBandwidth = prAdapter->rWifiVar + .ucApBandwidth; + } + /* P2P mode */ + else { + if (prBssInfo->eBand == BAND_2G4) + ucMaxBandwidth = prAdapter->rWifiVar + .ucP2p2gBandwidth; + else + ucMaxBandwidth = prAdapter->rWifiVar + .ucP2p5gBandwidth; + } + } + + return ucMaxBandwidth; +} + +uint32_t heRlmCalculateHeCapIELen( + struct ADAPTER *prAdapter, + uint8_t ucBssIndex, + struct STA_RECORD *prStaRec) +{ + uint8_t ucMaxBw; + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + uint32_t u4OverallLen = OFFSET_OF(struct _IE_HE_CAP_T, aucVarInfo[0]); + + if (fgEfuseCtrlAxOn == 1) { + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + ucMaxBw = cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex); + + u4OverallLen += 4; + + if (ucMaxBw >= MAX_BW_160MHZ) + u4OverallLen += 4; + + if (ucMaxBw >= MAX_BW_80_80_MHZ) + u4OverallLen += 4; + +#if (CFG_RX_PPE_THRESHOLD == 1) + u4OverallLen += sizeof(struct _PPE_THRESHOLD_FIELD); +#endif + } else { + u4OverallLen = 0; + } + + return u4OverallLen; +} + +uint32_t heRlmCalculateHeOpIELen( + struct ADAPTER *prAdapter, + uint8_t ucBssIndex, + struct STA_RECORD *prStaRec) +{ + uint32_t u4OverallLen = OFFSET_OF(struct _IE_HE_OP_T, aucVarInfo[0]); + + return u4OverallLen; +} + +static void heRlmFillMCSMap( + struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct _HE_SUPPORTED_MCS_FIELD *prHeSupportedMcsSet) +{ + uint8_t i, ucSupportedNss; + + kalMemZero((void *) prHeSupportedMcsSet, + sizeof(struct _HE_SUPPORTED_MCS_FIELD)); + ucSupportedNss = wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex); + + for (i = 0; i < 8; i++) { + uint8_t ucOffset = i * 2; + uint8_t ucMcsMap; + + if (i < ucSupportedNss) { + if (prAdapter->fgMcsMapBeenSet) + ucMcsMap = prAdapter->ucMcsMapSetFromSigma; + else + ucMcsMap = HE_CAP_INFO_MCS_MAP_MCS11; + } else { + ucMcsMap = HE_CAP_INFO_MCS_NOT_SUPPORTED; + } + + prHeSupportedMcsSet->u2RxMcsMap |= (ucMcsMap << ucOffset); + prHeSupportedMcsSet->u2TxMcsMap |= (ucMcsMap << ucOffset); + } + + prHeSupportedMcsSet->u2RxMcsMap = + CPU_TO_LE32(prHeSupportedMcsSet->u2RxMcsMap); + prHeSupportedMcsSet->u2TxMcsMap = + CPU_TO_LE32(prHeSupportedMcsSet->u2TxMcsMap); +} + +/* + * ucBitPos: bit position (starting from 0) for setting 3-bit PPE value + * ucVal has to be 3-bit value (i.e. no greater than 7) + */ +static void heRlmSet3BitPPE(uint8_t *pMem, uint8_t ucBitPos, uint8_t ucVal) +{ + uint8_t ucValidBits, ucPosInCurByte; + uint8_t *pucCurByte = pMem + (ucBitPos >> 3); + + ucPosInCurByte = (ucBitPos & 0x7); + ucValidBits = 8 - ucPosInCurByte; + if (ucValidBits >= 3) { + (*pucCurByte) |= (ucVal << ucPosInCurByte); + } else { + (*pucCurByte) |= (((uint8_t)(ucVal << ucPosInCurByte)) & + BITS(ucPosInCurByte, 7)); + (*(pucCurByte + 1)) |= (ucVal >> ucValidBits); + } +} + +/* ucBitPos: bit position (starting from 0) for getting 3-bit PPE value */ +static uint8_t heRlmGet3BitPPE(uint8_t *pMem, uint8_t ucBitPos) +{ + /* ucValidBits: valid bit counts in current byte */ + uint8_t ucValidBits, ucPosInCurByte, ucPPE; + uint8_t *pucCurByte; + + /* Get the pointer of the byte that contains the ucBitPos */ + pucCurByte = pMem + (ucBitPos >> 3); /* divided by 8 */ + ucPosInCurByte = (ucBitPos & 0x7); + /* get the remaining bits in this byte */ + ucValidBits = 8 - ucPosInCurByte; + if (ucValidBits >= 3) { /* enough bits for getting 3-bit PPE */ + ucPPE = ((*pucCurByte) & + BITS(ucPosInCurByte, ucPosInCurByte + 2)) >> + ucPosInCurByte; + } else { + uint8_t ucLSb, ucMSb; + + ucLSb = ((*pucCurByte) & BITS(ucPosInCurByte, 7)) >> + ucPosInCurByte; + ucMSb = (*(pucCurByte + 1)) & BITS(0, 2 - ucValidBits); + ucPPE = ucLSb | (ucMSb << ucValidBits); + } + + return ucPPE; +} + +/* Note: ucSupportedNss is (actual NSS - 1) */ +static uint8_t heRlmFillPPEThresholdInfo( + uint8_t ucSupportedNss, + uint8_t ucRUIdxSize, + uint8_t *pMem +) +{ + uint8_t ucNssIdx, ucRUIdx; + uint8_t ucT16Pos = HE_CAP_PPE_PPET16_NSS1_RU0_SHFT; + uint8_t ucT8Pos = HE_CAP_PPE_PPET8_NSS1_RU0_SHFT; + uint8_t ucMaxSupportNss = (sizeof(g_au8RlmHeCfgContellIdx) / + sizeof(g_au8RlmHeCfgContellIdx[0])); + + /* Coverity: + * due to ucSupportedNss is Supported Nss - 1 + * if it > first dimention of g_au8RlmHeCfgContellIdx - 1 + * assign it to first dimention of g_au8RlmHeCfgContellIdx - 1 + */ + ucSupportedNss = (ucSupportedNss > (ucMaxSupportNss - 1)) ? + (ucMaxSupportNss - 1) : ucSupportedNss; + + for (ucNssIdx = 0; ucNssIdx <= ucSupportedNss; ucNssIdx++) { + for (ucRUIdx = 0; ucRUIdx < ucRUIdxSize; ucRUIdx++) { + heRlmSet3BitPPE(pMem, ucT16Pos, + g_au8RlmHeCfgContellIdx[ucNssIdx][ucRUIdx][0]); + heRlmSet3BitPPE(pMem, ucT8Pos, + g_au8RlmHeCfgContellIdx[ucNssIdx][ucRUIdx][1]); + ucT16Pos += PPE_SUBFIELD_BITS_NUM; + ucT8Pos += PPE_SUBFIELD_BITS_NUM; + } + } + + return ucT16Pos; +} + +static uint8_t heRlmFillPPEThreshold( + struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + uint8_t *pPPEThreshold) +{ + uint8_t ucRUIdxSize = 0, ucLen; + uint8_t ucSupportedNss = + wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex) - 1; + uint8_t ucMaxBw = + cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex); + + kalMemZero((void *) pPPEThreshold, sizeof(struct _PPE_THRESHOLD_FIELD)); + + /* Note: this field in spec is (actual NSS - 1) */ + (*pPPEThreshold) = ucSupportedNss; + + switch (ucMaxBw) { + case MAX_BW_20MHZ: + (*pPPEThreshold) |= HE_CAP_PPE_242_RU_IDX; + ucRUIdxSize = 1; + break; + case MAX_BW_40MHZ: + (*pPPEThreshold) |= HE_CAP_PPE_484_RU_IDX; + ucRUIdxSize = 2; + break; + case MAX_BW_80MHZ: + (*pPPEThreshold) |= HE_CAP_PPE_996_RU_IDX; + ucRUIdxSize = 3; + break; + case MAX_BW_160MHZ: + case MAX_BW_80_80_MHZ: + (*pPPEThreshold) |= HE_CAP_PPE_996X2_RU_IDX; + ucRUIdxSize = 4; + break; + default: + /* should never come here */ + ASSERT(0); + } + + ucLen = heRlmFillPPEThresholdInfo(ucSupportedNss, + ucRUIdxSize, pPPEThreshold); + + ucLen = (ucLen % 8) ? (ucLen / 8 + 1) : (ucLen / 8); + + return ucLen; +} + +static void heRlmFillHeCapIE( + struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct MSDU_INFO *prMsduInfo) +{ + struct _IE_HE_CAP_T *prHeCap; + struct _HE_SUPPORTED_MCS_FIELD *prHeSupportedMcsSet; + uint32_t u4OverallLen = OFFSET_OF(struct _IE_HE_CAP_T, aucVarInfo[0]); + uint16_t ucMaxBw; + u_int8_t fgBfEn = TRUE; + + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; +#if (CFG_RX_PPE_THRESHOLD == 1) + uint8_t *pPPEThreshold; +#endif + uint8_t ucSupportedNss = + wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex) - 1; + struct AIS_FSM_INFO *prAisFsmInfo = + aisGetAisFsmInfo(prAdapter, prBssInfo->ucBssIndex); + struct BSS_DESC *prBssDesc; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(prMsduInfo); + + prHeCap = (struct _IE_HE_CAP_T *) + (((uint8_t *)prMsduInfo->prPacket)+prMsduInfo->u2FrameLength); + + prHeCap->ucId = ELEM_ID_RESERVED; + prHeCap->ucExtId = ELEM_EXT_ID_HE_CAP; + + ucMaxBw = cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex); + + /* MAC capabilities */ + HE_RESET_MAC_CAP(prHeCap->ucHeMacCap); + + HE_SET_MAC_CAP_TRIGGER_PAD_DURATION(prHeCap->ucHeMacCap, + prWifiVar->ucTrigMacPadDur); + + HE_SET_MAC_CAP_HTC_HE(prHeCap->ucHeMacCap); + HE_SET_MAC_CAP_OM_CTRL(prHeCap->ucHeMacCap); + +#if (CFG_SUPPORT_TWT == 1) + if (IS_BSS_AIS(prBssInfo) && + IS_FEATURE_ENABLED(prWifiVar->ucTWTRequester)) + HE_SET_MAC_CAP_TWT_REQ(prHeCap->ucHeMacCap); +#endif + + /* PHY capabilities */ + HE_RESET_PHY_CAP(prHeCap->ucHePhyCap); + + if (_heGetBssBandBw(prAdapter, prBssInfo, BAND_2G4) + >= MAX_BW_40MHZ) + HE_SET_PHY_CAP_CHAN_WIDTH_SET_BW40_2G(prHeCap->ucHePhyCap); + + if (_heGetBssBandBw(prAdapter, prBssInfo, BAND_5G) + >= MAX_BW_40MHZ) + HE_SET_PHY_CAP_CHAN_WIDTH_SET_BW40_BW80_5G( + prHeCap->ucHePhyCap); + + if (_heGetBssBandBw(prAdapter, prBssInfo, BAND_5G) + >= MAX_BW_160MHZ) + HE_SET_PHY_CAP_CHAN_WIDTH_SET_BW160_5G(prHeCap->ucHePhyCap); + + if (_heGetBssBandBw(prAdapter, prBssInfo, BAND_5G) + >= MAX_BW_80_80_MHZ) + HE_SET_PHY_CAP_CHAN_WIDTH_SET_BW80P80_5G(prHeCap->ucHePhyCap); + + if (IS_FEATURE_ENABLED(prWifiVar->ucRxLdpc) && + IS_FEATURE_ENABLED(prWifiVar->ucTxLdpc)) + HE_SET_PHY_CAP_LDPC_CODING_IN_PAYLOAD(prHeCap->ucHePhyCap); + + if (IS_FEATURE_ENABLED(prWifiVar->ucTxStbc)) { + HE_SET_PHY_CAP_STBC_TX_LT_OR_EQ_80M(prHeCap->ucHePhyCap); + if (IS_BSS_AIS(prBssInfo)) + HE_SET_PHY_CAP_STBC_TX_GT_80M(prHeCap->ucHePhyCap); + } + + if (IS_FEATURE_ENABLED(prWifiVar->ucRxStbc)) { + HE_SET_PHY_CAP_STBC_RX_LT_OR_EQ_80M(prHeCap->ucHePhyCap); + if (IS_BSS_AIS(prBssInfo)) + HE_SET_PHY_CAP_STBC_RX_GT_80M(prHeCap->ucHePhyCap); + } + +#if CFG_SUPPORT_BFEE +#if CFG_SUPPORT_CONDITIONAL_BFEE + if ((prAdapter->rWifiVar.u4SwTestMode != ENUM_SW_TEST_MODE_SIGMA_AX) && + (IS_BSS_AIS(prBssInfo) && prAisFsmInfo != NULL)) { + prBssDesc = prAisFsmInfo->prTargetBssDesc; + if (prBssDesc != NULL && (bssGetRxNss(prAdapter, prBssDesc) == + wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex))) { + fgBfEn = FALSE; + DBGLOG(SW4, ERROR, + "Disable Bfee due to same Nss between STA and AP\n"); + } else { + fgBfEn = TRUE; + } + } +#endif + if ((fgBfEn == TRUE) && (IS_FEATURE_ENABLED(prWifiVar->ucStaHeBfee))) { + HE_SET_PHY_CAP_SU_BFMEE(prHeCap->ucHePhyCap); + HE_SET_PHY_CAP_BFMEE_STS_LT_OR_EQ_80M(prHeCap->ucHePhyCap, 3); + HE_SET_PHY_CAP_CODE_BOOK_4_2_SU_FB(prHeCap->ucHePhyCap); + HE_SET_PHY_CAP_CODE_BOOK_7_5_MU_FB(prHeCap->ucHePhyCap); + HE_SET_PHY_CAP_TRIG_SU_BF_FB(prHeCap->ucHePhyCap); + HE_SET_PHY_CAP_TRIG_MU_BF_PARTIAL_BW_FB(prHeCap->ucHePhyCap); + HE_SET_PHY_CAP_MAX_NC(prHeCap->ucHePhyCap, ucSupportedNss); + } +#endif + +#if (CFG_SUPPORT_HE_ER == 1) + if (IS_FEATURE_ENABLED(prWifiVar->u4ExtendedRange)) { + HE_SET_PHY_CAP_DCM_MAX_CONSTELLATION_TX(prHeCap->ucHePhyCap, + MAX_SUPPORT_CONSTELLATION_DCM_QPSK); + HE_SET_PHY_CAP_DCM_MAX_CONSTELLATION_RX(prHeCap->ucHePhyCap, + MAX_SUPPORT_CONSTELLATION_DCM_QPSK); + HE_SET_PHY_CAP_PARTIAL_BW_EXTENDED_RANGE(prHeCap->ucHePhyCap); + HE_SET_PHY_CAP_ER_SU_4X_HE_LTF(prHeCap->ucHePhyCap); + HE_SET_PHY_CAP_ER_SU_PPDU_1X_HE_LTF(prHeCap->ucHePhyCap); + + DBGLOG(RLM, INFO, "ER: Set ER Phy capabilities\n"); + } +#endif + + /* Set MCS map */ + prHeSupportedMcsSet = (struct _HE_SUPPORTED_MCS_FIELD *) + (((uint8_t *) prHeCap) + u4OverallLen); + heRlmFillMCSMap(prAdapter, prBssInfo, prHeSupportedMcsSet); + u4OverallLen += sizeof(struct _HE_SUPPORTED_MCS_FIELD); + + if (ucMaxBw >= MAX_BW_160MHZ) { + prHeSupportedMcsSet = (struct _HE_SUPPORTED_MCS_FIELD *) + (((uint8_t *) prHeCap) + u4OverallLen); + heRlmFillMCSMap(prAdapter, prBssInfo, prHeSupportedMcsSet); + u4OverallLen += sizeof(struct _HE_SUPPORTED_MCS_FIELD); + } + + if (ucMaxBw >= MAX_BW_80_80_MHZ) { + prHeSupportedMcsSet = (struct _HE_SUPPORTED_MCS_FIELD *) + (((uint8_t *) prHeCap) + u4OverallLen); + heRlmFillMCSMap(prAdapter, prBssInfo, prHeSupportedMcsSet); + u4OverallLen += sizeof(struct _HE_SUPPORTED_MCS_FIELD); + } + +#if (CFG_RX_PPE_THRESHOLD == 1) + pPPEThreshold = ((uint8_t *) prHeCap) + u4OverallLen; + u4OverallLen += + heRlmFillPPEThreshold(prAdapter, prBssInfo, pPPEThreshold); +#endif + /* The Element ID Extension byte is included in length calculation */ + prHeCap->ucLength = u4OverallLen - ELEM_HDR_LEN; + + prMsduInfo->u2FrameLength += IE_SIZE(prHeCap); +} + +void heRlmReqGenerateHeCapIE( + struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + + if (fgEfuseCtrlAxOn == 1) { + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AX) + && (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11AX))) + heRlmFillHeCapIE(prAdapter, prBssInfo, prMsduInfo); + } +} + +void heRlmRspGenerateHeCapIE( + struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint8_t ucPhyTypeSet; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + if (!IS_BSS_ACTIVE(prBssInfo)) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + /* Decide PHY type set source */ + if (prStaRec) { + /* Get PHY type set from target STA */ + ucPhyTypeSet = prStaRec->ucPhyTypeSet; + } else { + /* Get PHY type set from current BSS */ + ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + } + + if (RLM_NET_IS_11AX(prBssInfo) && + (ucPhyTypeSet & PHY_TYPE_SET_802_11AX)) + heRlmFillHeCapIE(prAdapter, prBssInfo, prMsduInfo); +} + +static void heRlmFillHeOpIE( + struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct MSDU_INFO *prMsduInfo) +{ + struct _IE_HE_OP_T *prHeOp; + uint32_t u4OverallLen = OFFSET_OF(struct _IE_HE_OP_T, aucVarInfo[0]); + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(prMsduInfo); + + prHeOp = (struct _IE_HE_OP_T *) + (((uint8_t *)prMsduInfo->prPacket)+prMsduInfo->u2FrameLength); + + prHeOp->ucId = ELEM_ID_RESERVED; + prHeOp->ucExtId = ELEM_EXT_ID_HE_OP; + + memcpy(prHeOp->ucHeOpParams, prBssInfo->ucHeOpParams, HE_OP_BYTE_NUM); + prHeOp->ucBssColorInfo = prBssInfo->ucBssColorInfo; + prHeOp->u2HeBasicMcsSet = CPU_TO_LE16(prBssInfo->u2HeBasicMcsSet); + + prHeOp->ucLength = u4OverallLen - ELEM_HDR_LEN; + prMsduInfo->u2FrameLength += IE_SIZE(prHeOp); +} + +void heRlmRspGenerateHeOpIE( + struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint8_t ucPhyTypeSet; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + if (!IS_BSS_ACTIVE(prBssInfo)) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + /* Decide PHY type set source */ + if (prStaRec) { + /* Get PHY type set from target STA */ + ucPhyTypeSet = prStaRec->ucPhyTypeSet; + } else { + /* Get PHY type set from current BSS */ + ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + } + + if (RLM_NET_IS_11AX(prBssInfo) && + (ucPhyTypeSet & PHY_TYPE_SET_802_11AX)) + heRlmFillHeOpIE(prAdapter, prBssInfo, prMsduInfo); +} + +static uint16_t heRlmGetHeMcsMap(uint8_t *pSrc) +{ + uint16_t u2McsMap; + + kalMemCopy(&u2McsMap, pSrc, sizeof(u2McsMap)); + u2McsMap = LE16_TO_CPU(u2McsMap); + + return u2McsMap; +} + +static uint32_t heRlmRecHeMcsMap( + struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + struct _IE_HE_CAP_T *prHeCap) +{ + uint32_t u4McsMapOffset; + uint16_t u2McsMap; + struct BSS_INFO *prBssInfo; + uint8_t ucHeCapMcsOwnNotSupportOffset = 0, ucMaxBw; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + ucMaxBw = cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex); + + /* BW 80Mhz */ + u4McsMapOffset = OFFSET_OF(struct _IE_HE_CAP_T, aucVarInfo[0]); + + u2McsMap = heRlmGetHeMcsMap(((uint8_t *)prHeCap) + u4McsMapOffset); + prStaRec->u2HeRxMcsMapBW80 = u2McsMap; + + if (wlanGetSupportNss(prAdapter, prStaRec->ucBssIndex) < 8) { + ucHeCapMcsOwnNotSupportOffset = + wlanGetSupportNss(prAdapter, prStaRec->ucBssIndex) * 2; + /* Mark Rx Mcs Map which we don't support */ + prStaRec->u2HeRxMcsMapBW80 |= + BITS(ucHeCapMcsOwnNotSupportOffset, 15); + } + if (prStaRec->u2HeRxMcsMapBW80 != u2McsMap) + DBGLOG(RLM, TRACE, "Change HeRxMcsMapBW80 from 0x%x to 0x%x\n", + u2McsMap, prStaRec->u2HeRxMcsMapBW80); + + u4McsMapOffset += sizeof(uint16_t); + + u2McsMap = heRlmGetHeMcsMap(((uint8_t *)prHeCap) + u4McsMapOffset); + prStaRec->u2HeTxMcsMapBW80 = u2McsMap; + + u4McsMapOffset += sizeof(uint16_t); + + /* BW 160Mhz */ + if (HE_IS_PHY_CAP_CHAN_WIDTH_SET_BW160_5G(prStaRec->ucHePhyCapInfo)) { + u2McsMap = heRlmGetHeMcsMap(((uint8_t *)prHeCap) + + u4McsMapOffset); + prStaRec->u2HeRxMcsMapBW160 = u2McsMap; + + if (ucMaxBw >= MAX_BW_160MHZ) { + /* Mark Rx Mcs Map which we don't support */ + prStaRec->u2HeRxMcsMapBW160 |= + BITS(ucHeCapMcsOwnNotSupportOffset, 15); + + if (prStaRec->u2HeRxMcsMapBW160 != u2McsMap) + DBGLOG(RLM, TRACE, + "Change McsMapBW160 from 0x%x to 0x%x\n", + u2McsMap, prStaRec->u2HeRxMcsMapBW160); + } else { + /* BW160 is not supported locally */ + prStaRec->u2HeRxMcsMapBW160 = BITS(0, 15); + } + + u4McsMapOffset += sizeof(uint16_t); + u2McsMap = heRlmGetHeMcsMap(((uint8_t *)prHeCap) + + u4McsMapOffset); + prStaRec->u2HeTxMcsMapBW160 = u2McsMap; + u4McsMapOffset += sizeof(uint16_t); + } else { + prStaRec->u2HeRxMcsMapBW160 = BITS(0, 15); + prStaRec->u2HeTxMcsMapBW160 = BITS(0, 15); + } + + /* BW 80+80 */ + if (HE_IS_PHY_CAP_CHAN_WIDTH_SET_BW80P80_5G(prStaRec->ucHePhyCapInfo)) { + u2McsMap = heRlmGetHeMcsMap(((uint8_t *)prHeCap) + + u4McsMapOffset); + prStaRec->u2HeRxMcsMapBW80P80 = u2McsMap; + + if (ucMaxBw >= MAX_BW_80_80_MHZ) { + /* Mark Rx Mcs Map which we don't support */ + prStaRec->u2HeRxMcsMapBW80P80 |= + BITS(ucHeCapMcsOwnNotSupportOffset, 15); + + if (prStaRec->u2HeRxMcsMapBW80P80 != u2McsMap) + DBGLOG(RLM, TRACE, + "Change McsMapBW80P80 from 0x%x to 0x%x\n", + u2McsMap, prStaRec->u2HeRxMcsMapBW80P80); + } else { + /* BW 80+80 is not supported locally */ + prStaRec->u2HeRxMcsMapBW80P80 = BITS(0, 15); + } + + u4McsMapOffset += sizeof(uint16_t); + u2McsMap = heRlmGetHeMcsMap(((uint8_t *)prHeCap) + + u4McsMapOffset); + prStaRec->u2HeTxMcsMapBW80P80 = u2McsMap; + u4McsMapOffset += sizeof(uint16_t); + } else { + prStaRec->u2HeRxMcsMapBW80P80 = BITS(0, 15); + prStaRec->u2HeTxMcsMapBW80P80 = BITS(0, 15); + } + + return u4McsMapOffset; +} + +static void heRlmRecHePPEThresholds(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + struct _IE_HE_CAP_T *prHeCap, + uint32_t u4Offset) +{ + /* To store subfiled values in peer's PPE threshold */ + uint8_t i, j, k, ucNSS, ucRUIdxBMP, ucRUIdxBMPTmp, ucPPEInfo[32], ucPos; + uint8_t *pucMem = ((uint8_t *)prHeCap) + u4Offset; + + ucNSS = (*pucMem) & HE_CAP_PPE_NSS; + ucRUIdxBMP = ((*pucMem) & HE_CAP_PPE_RU_IDX_BMP) >> + HE_CAP_PPE_RU_IDX_BMP_SHFT; + + k = 0; + ucPos = HE_CAP_PPE_PPET16_NSS1_RU0_SHFT; + for (i = 0; i <= ucNSS; i++) { + ucRUIdxBMPTmp = ucRUIdxBMP; + for (j = 0; j < PPE_RU_IDX_SIZE * 2; j++) { + if (ucRUIdxBMPTmp & 0x1) { + ucPPEInfo[k] = heRlmGet3BitPPE(pucMem, ucPos); + ucPos += 3; + } else { + ucPPEInfo[k] = 0; + } + k++; + ucRUIdxBMPTmp = (ucRUIdxBMPTmp >> 1); + } + } +} + +void heRlmRecHeCapInfo( + struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t *pucIE) +{ + uint32_t u4Offset; + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; + struct _IE_HE_CAP_T *prHeCap = (struct _IE_HE_CAP_T *) pucIE; + + /* if payload not contain any aucVarInfo, + * IE size = sizeof(struct _IE_HE_CAP_T) + */ + if (IE_SIZE(prHeCap) < (sizeof(struct _IE_HE_CAP_T))) { + DBGLOG(SCN, WARN, "HE_CAP IE_LEN err(%d)!\n", IE_LEN(prHeCap)); + return; + } + + memcpy(prStaRec->ucHeMacCapInfo, prHeCap->ucHeMacCap, + HE_MAC_CAP_BYTE_NUM); + memcpy(prStaRec->ucHePhyCapInfo, prHeCap->ucHePhyCap, + HE_PHY_CAP_BYTE_NUM); + +#if (CFG_SUPPORT_HE_ER == 1) + DBGLOG(RLM, INFO, "ER: TX:%d, RX:%d, bw:%d, 4x LTF:%d, 1X LTF:%d\n", + HE_GET_PHY_CAP_DCM_MAX_CONSTELLATION_TX( + prStaRec->ucHePhyCapInfo), + HE_GET_PHY_CAP_DCM_MAX_CONSTELLATION_RX( + prStaRec->ucHePhyCapInfo), + HE_GET_PHY_CAP_PARTIAL_BW_EXTENDED_RANGE( + prStaRec->ucHePhyCapInfo), + HE_GET_PHY_CAP_ER_SU_4X_HE_LTF( + prStaRec->ucHePhyCapInfo), + HE_GET_PHY_CAP_ER_SU_PPDU_1X_HE_LTF( + prStaRec->ucHePhyCapInfo)); +#endif + + /* Disable peer bfer cap indication to FW + * if our bfee feature is not on + */ + if (IS_FEATURE_DISABLED(prWifiVar->ucStaHeBfee)) { + HE_UNSET_PHY_CAP_SU_BFMER(prStaRec->ucHePhyCapInfo); + HE_UNSET_PHY_CAP_MU_BFMER(prStaRec->ucHePhyCapInfo); + } + + /* Set HE Rx Mcs Map upon peer's capability and our capability */ + u4Offset = heRlmRecHeMcsMap(prAdapter, prStaRec, prHeCap); + + /* Set HE PPE Thresholds if it exists */ + if (HE_IS_PHY_CAP_PPE_THRESHOLD(prStaRec->ucHePhyCapInfo)) + heRlmRecHePPEThresholds(prAdapter, prStaRec, prHeCap, u4Offset); +} + +void heRlmRecHeOperation( + struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + uint8_t *pucIE) +{ + struct _IE_HE_OP_T *prHeOp = (struct _IE_HE_OP_T *) pucIE; +#if (CFG_SUPPORT_HE_ER == 1) + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; + /* if payload not contain any aucVarInfo, + * IE size = sizeof(struct _IE_HE_OP_T) + */ + if (IE_SIZE(prHeOp) < (sizeof(struct _IE_HE_OP_T))) { + DBGLOG(SCN, WARN, "HE_OP IE_LEN err(%d)!\n", IE_LEN(prHeOp)); + return; + } + + if (IS_FEATURE_DISABLED(prWifiVar->u4ExtendedRange)) { + HE_SET_OP_PARAM_ER_SU_DISABLE(prHeOp->ucHeOpParams); + + DBGLOG(RLM, INFO, "ER: is ER SU: %d\n", + HE_IS_ER_SU_DISABLE(prHeOp->ucHeOpParams)); + } +#endif + + memcpy(prBssInfo->ucHeOpParams, prHeOp->ucHeOpParams, HE_OP_BYTE_NUM); + prBssInfo->ucBssColorInfo = prHeOp->ucBssColorInfo; + prBssInfo->u2HeBasicMcsSet = LE16_TO_CPU(prHeOp->u2HeBasicMcsSet); +} + +uint8_t heRlmUpdateSRParams( + struct BSS_INFO *prBssInfo, + uint8_t *pucIE) +{ + struct _IE_SR_PARAM_T *prSRParam = (struct _IE_SR_PARAM_T *) pucIE; + uint32_t u4IEOffset; + uint8_t fgIsNew = FALSE; + + if (prBssInfo->ucSRControl != prSRParam->ucSRControl) { + fgIsNew = TRUE; + prBssInfo->ucSRControl = prSRParam->ucSRControl; + } + + u4IEOffset = OFFSET_OF(struct _IE_SR_PARAM_T, aucVarInfo[0]); + + if (prBssInfo->ucSRControl & SR_PARAM_NON_SRG_OFFSET_PRESENT) { + struct _NON_SRG_SR_INFO_T *prNonSRGInfo = + (struct _NON_SRG_SR_INFO_T *) + (((uint8_t *) pucIE) + u4IEOffset); + + if (prBssInfo->ucNonSRGObssPdMaxOffset != + prNonSRGInfo->ucObssPdMaxOffset) { + + fgIsNew = TRUE; + prBssInfo->ucNonSRGObssPdMaxOffset = + prNonSRGInfo->ucObssPdMaxOffset; + } + + u4IEOffset += sizeof(struct _NON_SRG_SR_INFO_T); + } else + prBssInfo->ucNonSRGObssPdMaxOffset = 0; + + if (prBssInfo->ucSRControl & SR_PARAM_SRG_INFO_PRESENT) { + struct _SRG_SR_INFO_T *prSRGInfo = (struct _SRG_SR_INFO_T *) + (((uint8_t *) pucIE) + u4IEOffset); + + if (prBssInfo->ucSRGObssPdMinOffset != + prSRGInfo->ucObssPdMinOffset) { + fgIsNew = TRUE; + prBssInfo->ucSRGObssPdMinOffset = + prSRGInfo->ucObssPdMinOffset; + } + if (prBssInfo->ucSRGObssPdMaxOffset != + prSRGInfo->ucObssPdMaxOffset) { + fgIsNew = TRUE; + prBssInfo->ucSRGObssPdMaxOffset = + prSRGInfo->ucObssPdMaxOffset; + } + if (prBssInfo->u8SRGBSSColorBitmap != + LE64_TO_CPU(prSRGInfo->u8BSSColorBitmap)) { + fgIsNew = TRUE; + prBssInfo->u8SRGBSSColorBitmap = + LE64_TO_CPU(prSRGInfo->u8BSSColorBitmap); + } + if (prBssInfo->u8SRGPartialBSSIDBitmap != + LE64_TO_CPU(prSRGInfo->u8PartialBSSIDBitmap)) { + fgIsNew = TRUE; + prBssInfo->u8SRGPartialBSSIDBitmap = + LE64_TO_CPU(prSRGInfo->u8PartialBSSIDBitmap); + } + } else { + prBssInfo->ucSRGObssPdMinOffset = 0; + prBssInfo->ucSRGObssPdMaxOffset = 0; + prBssInfo->u8SRGBSSColorBitmap = 0; + prBssInfo->u8SRGPartialBSSIDBitmap = 0; + } + + return fgIsNew; +} + +uint8_t +heRlmRecHeSRParams( + struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct SW_RFB *prSwRfb, + uint8_t *pucIE, + uint16_t u2IELength) +{ + uint16_t u2Offset; + uint8_t fgNewParameter = FALSE; + + DEBUGFUNC("rlmParseHeSRParams"); + + if (!pucIE) + return FALSE; + + /* Obtain the SR parameters */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_RESERVED: + if (IE_ID_EXT(pucIE) == ELEM_EXT_ID_SR_PARAM) { + fgNewParameter = + heRlmUpdateSRParams(prBssInfo, pucIE); + } + break; + default: + break; + } + } + + return fgNewParameter; +} + +void heRlmInitHeHtcACtrlOMAndUPH( + struct ADAPTER *prAdapter) +{ + HE_SET_HTC_HE_VARIANT(prAdapter->u4HeHtcOM); + HE_SET_HTC_1ST_A_CTRL_ID(prAdapter->u4HeHtcOM, HTC_HE_A_CTRL_OM); + HE_SET_HTC_HE_OM_RX_NSS(prAdapter->u4HeHtcOM, 1); + HE_SET_HTC_HE_OM_TX_NSTS(prAdapter->u4HeHtcOM, 1); + HE_SET_HTC_HE_OM_CH_WIDTH(prAdapter->u4HeHtcOM, CH_BW_80); + HE_SET_HTC_HE_OM_UL_MU_DISABLE(prAdapter->u4HeHtcOM, 0); + HE_SET_HTC_HE_OM_UL_MU_DATA_DISABLE(prAdapter->u4HeHtcOM, 0); + HE_SET_HTC_2ND_A_CTRL_ID(prAdapter->u4HeHtcOM, HTC_HE_A_CTRL_UPH); + HE_SET_HTC_HE_UPH(prAdapter->u4HeHtcOM, 10); + HE_SET_HTC_HE_UPH_MIN_TX_PWR_FLAG(prAdapter->u4HeHtcOM, 0); +} + +void heRlmReqGenerateHeHtcACtrlOM( + IN struct HE_A_CTRL_OM_T *prHeActrlOM, + OUT uint32_t *pHtc) +{ + uint32_t u4HTC = 0; + + if (!pHtc || !prHeActrlOM) { + DBGLOG(RLM, WARN, + "heRlmReqGenerateHeHtcACtrlOM:: Please check function parameters.\n"); + return; + } + + HE_SET_HTC_1ST_A_CTRL_ID(u4HTC, HTC_HE_A_CTRL_OM); + HE_SET_HTC_HE_OM_RX_NSS(u4HTC, prHeActrlOM->ucRxNss); + HE_SET_HTC_HE_OM_TX_NSTS(u4HTC, prHeActrlOM->ucTxNsts); + HE_SET_HTC_HE_OM_CH_WIDTH(u4HTC, prHeActrlOM->ucBW); + HE_SET_HTC_HE_OM_UL_MU_DISABLE(u4HTC, prHeActrlOM->fgDisMuUL); + HE_SET_HTC_HE_OM_UL_MU_DATA_DISABLE(u4HTC, prHeActrlOM->fgDisMuULData); + *pHtc = u4HTC; + DBGLOG(RLM, STATE, "heRlmReqGenerateHeHtcACtrlOM:: u4HTC = 0x%08x\n"); +} + +void heRlmParseHeHtcACtrlOM( + uint32_t u4Htc, + struct HE_A_CTRL_OM_T *prHeActrlOM) +{ + DBGLOG(RLM, STATE, + "heRlmParseHeHtcACtrlOM:: HTC Control Field = 0x%08x\n", + u4Htc); + if (HE_GET_HTC_1ST_A_CTRL_ID(u4Htc) == HTC_HE_A_CTRL_OM) { + prHeActrlOM->ucRxNss = HE_GET_HTC_HE_OM_RX_NSS(u4Htc); + prHeActrlOM->ucTxNsts = HE_GET_HTC_HE_OM_TX_NSTS(u4Htc); + prHeActrlOM->ucBW = HE_GET_HTC_HE_OM_CH_WIDTH(u4Htc); + prHeActrlOM->fgDisMuUL = HE_GET_HTC_HE_OM_UL_MU_DISABLE(u4Htc); + prHeActrlOM->fgDisMuULData = + HE_GET_HTC_HE_OM_UL_MU_DATA_DISABLE(u4Htc); + } else + DBGLOG(RLM, WARN, "This is not Operating mode (OM).\n"); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the QoS Null + HTC 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 +heRlmComposeHtcNullFrame( + IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuffer, + IN struct STA_RECORD *prStaRec, + IN uint8_t ucUP, + IN u_int8_t fgSetEOSP) +{ + struct WLAN_MAC_HEADER_HT *prQoSNullFrame; + struct BSS_INFO *prBssInfo; + uint16_t u2FrameCtrl; + uint16_t u2QosControl; + uint8_t ucBssIndex; + + ASSERT(prStaRec); + ucBssIndex = prStaRec->ucBssIndex; + + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + ASSERT(pucBuffer); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + ASSERT(prBssInfo); + + prQoSNullFrame = (struct WLAN_MAC_HEADER_HT *) pucBuffer; + + /* 4 <1> Decide the Frame Control Field */ +#if 0 + u2FrameCtrl = MAC_FRAME_QOS_DATA | MASK_FC_ORDER; +#else + u2FrameCtrl = MAC_FRAME_QOS_NULL | MASK_FC_ORDER; +#endif + + if (IS_AP_STA(prStaRec)) { + u2FrameCtrl |= MASK_FC_TO_DS; + } 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; + + /* 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 = (uint16_t) (ucUP & WMM_QC_UP_MASK); + + if (fgSetEOSP) + u2QosControl |= WMM_QC_EOSP; + + prQoSNullFrame->u2QosCtrl = u2QosControl; + +#ifdef CFG_AX_CERT_WKR + HE_SET_HTC_2ND_A_CTRL_ID(prAdapter->u4HeHtcOM, HTC_HE_A_CTRL_UPH); + HE_SET_HTC_HE_UPH(prAdapter->u4HeHtcOM, 10); + HE_SET_HTC_HE_UPH_MIN_TX_PWR_FLAG(prAdapter->u4HeHtcOM, 0); +#endif + + prQoSNullFrame->u4HtCtrl = prAdapter->u4HeHtcOM; + + return; + +} /* end of bssComposeQoSNullFrameHeader() */ + +uint32_t heRlmSendHtcNullFrame( + IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN uint8_t ucUP, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + struct MSDU_INFO *prMsduInfo; + uint16_t 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_HTC_LEN; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(RLM, WARN, "No PKT_INFO_T for sending Null Frame.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Null frame in MSDU_INfO_T. */ + heRlmComposeHtcNullFrame(prAdapter, + (uint8_t *)((unsigned long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD), + prStaRec, ucUP, FALSE); + + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_HEADER_QOS_HTC_LEN, + WLAN_MAC_HEADER_QOS_HTC_LEN, + pfTxDoneHandler, + MSDU_RATE_MODE_AUTO); + + prMsduInfo->fgMgmtUseDataQ = TRUE; + /* prMsduInfo->ucUserPriority = 0;*/ + prMsduInfo->u4Option |= MSDU_OPT_NO_AGGREGATE; + prMsduInfo->u4Option |= MSDU_OPT_SW_HTC; + /* 4 <4> Inform TXM to send this Null frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; + +} /* end of bssSendQoSNullFrame() */ + +void heRlmInit( + struct ADAPTER *prAdapter) +{ + struct __HE_CFG_INFO_T *prHeCfg; + + prHeCfg = &prAdapter->rHeCfg; + prHeCfg->fgHeSupport = TRUE; + /* It can be disabled by wifi.cfg or iwpriv command */ + prHeCfg->fgHeEnable = TRUE; + /* It can be disabled by wifi.cfg or iwpriv command */ + prHeCfg->fgTwtRequesterEnable = TRUE; +} +#endif /* CFG_SUPPORT_802_11AX == 1 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/hem_mbox.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/hem_mbox.c new file mode 100644 index 0000000000000..ae0ec4574c6e9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/hem_mbox.c @@ -0,0 +1,643 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: mgmt/hem_mbox.c + */ + +/*! \file "hem_mbox.c" + * \brief + * + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +#if DBG +/*lint -save -e64 Type mismatch */ +static uint8_t *apucDebugMsg[] = { + (uint8_t *) DISP_STRING("MID_MNY_CNM_CH_REQ"), + (uint8_t *) DISP_STRING("MID_MNY_CNM_CH_ABORT"), + (uint8_t *) DISP_STRING("MID_CNM_AIS_CH_GRANT"), + (uint8_t *) DISP_STRING("MID_CNM_P2P_CH_GRANT"), + (uint8_t *) DISP_STRING("MID_CNM_BOW_CH_GRANT"), + +#if (CFG_SUPPORT_DFS_MASTER == 1) + (uint8_t *) DISP_STRING("MID_CNM_P2P_RADAR_DETECT"), + (uint8_t *) DISP_STRING("MID_CNM_P2P_CSA_DONE"), +#endif + (uint8_t *) DISP_STRING("MID_AIS_SCN_SCAN_REQ"), + (uint8_t *) DISP_STRING("MID_AIS_SCN_SCAN_REQ_V2"), + (uint8_t *) DISP_STRING("MID_AIS_SCN_SCAN_CANCEL"), + (uint8_t *) DISP_STRING("MID_P2P_SCN_SCAN_REQ"), + (uint8_t *) DISP_STRING("MID_P2P_SCN_SCAN_REQ_V2"), + (uint8_t *) DISP_STRING("MID_P2P_SCN_SCAN_CANCEL"), + (uint8_t *) DISP_STRING("MID_BOW_SCN_SCAN_REQ"), + (uint8_t *) DISP_STRING("MID_BOW_SCN_SCAN_REQ_V2"), + (uint8_t *) DISP_STRING("MID_BOW_SCN_SCAN_CANCEL"), + (uint8_t *) DISP_STRING("MID_RLM_SCN_SCAN_REQ"), + (uint8_t *) DISP_STRING("MID_RLM_SCN_SCAN_REQ_V2"), + (uint8_t *) DISP_STRING("MID_RLM_SCN_SCAN_CANCEL"), + (uint8_t *) DISP_STRING("MID_SCN_AIS_SCAN_DONE"), + (uint8_t *) DISP_STRING("MID_SCN_P2P_SCAN_DONE"), + (uint8_t *) DISP_STRING("MID_SCN_BOW_SCAN_DONE"), + (uint8_t *) DISP_STRING("MID_SCN_RLM_SCAN_DONE"), + + (uint8_t *) DISP_STRING("MID_OID_AIS_FSM_JOIN_REQ"), + (uint8_t *) DISP_STRING("MID_OID_AIS_FSM_ABORT"), + (uint8_t *) DISP_STRING("MID_AIS_SAA_FSM_START"), + (uint8_t *) DISP_STRING("MID_OID_SAA_FSM_CONTINUE"), + (uint8_t *) DISP_STRING("MID_OID_SAA_FSM_EXTERNAL_AUTH"), + (uint8_t *) DISP_STRING("MID_AIS_SAA_FSM_ABORT"), + (uint8_t *) DISP_STRING("MID_SAA_AIS_JOIN_COMPLETE"), + +#if CFG_ENABLE_BT_OVER_WIFI + (uint8_t *) DISP_STRING("MID_BOW_SAA_FSM_START"), + (uint8_t *) DISP_STRING("MID_BOW_SAA_FSM_ABORT"), + (uint8_t *) DISP_STRING("MID_SAA_BOW_JOIN_COMPLETE"), +#endif + +#if CFG_ENABLE_WIFI_DIRECT + (uint8_t *) DISP_STRING("MID_P2P_SAA_FSM_START"), + (uint8_t *) DISP_STRING("MID_P2P_SAA_FSM_ABORT"), + (uint8_t *) DISP_STRING("MID_SAA_P2P_JOIN_COMPLETE"), + + (uint8_t *) DISP_STRING("MID_MNY_P2P_FUN_SWITCH"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_DEVICE_DISCOVERY"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_CONNECTION_REQ"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_CONNECTION_ABORT"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_BEACON_UPDATE"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_STOP_AP"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_CHNL_REQ"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_CHNL_ABORT"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_MGMT_TX"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_MGMT_TX_CANCEL_WAIT"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_GROUP_DISSOLVE"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_MGMT_FRAME_REGISTER"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_NET_DEV_REGISTER"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_START_AP"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_DEL_IFACE"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_MGMT_FRAME_UPDATE"), +#if (CFG_SUPPORT_DFS_MASTER == 1) + (uint8_t *) DISP_STRING("MID_MNY_P2P_DFS_CAC"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_SET_NEW_CHANNEL"), +#endif +#if CFG_SUPPORT_WFD + (uint8_t *) DISP_STRING("MID_MNY_P2P_WFD_CFG_UPDATE"), +#endif + (uint8_t *) DISP_STRING("MID_MNY_P2P_ACTIVE_BSS"), +#endif + +#if CFG_SUPPORT_ADHOC + (uint8_t *) DISP_STRING("MID_SCN_AIS_FOUND_IBSS"), +#endif /* CFG_SUPPORT_ADHOC */ + + (uint8_t *) DISP_STRING("MID_SAA_AIS_FSM_ABORT"), + (uint8_t *) DISP_STRING("MID_MNY_AIS_REMAIN_ON_CHANNEL"), + (uint8_t *) DISP_STRING("MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL"), + (uint8_t *) DISP_STRING("MID_MNY_AIS_MGMT_TX"), + (uint8_t *) DISP_STRING("MID_MNY_AIS_MGMT_TX_CANCEL_WAIT"), + (uint8_t *) DISP_STRING("MID_WNM_AIS_BSS_TRANSITION"), +#if CFG_SUPPORT_NCHO + (uint8_t *) DISP_STRING("MID_MNY_AIS_NCHO_ACTION_FRAME") +#endif + (uint8_t *) DISP_STRING("MID_MNY_P2P_ACS"), + +#if (CFG_SUPPORT_TWT == 1) + (uint8_t *) DISP_STRING("MID_TWT_REQ_FSM_START"), + (uint8_t *) DISP_STRING("MID_TWT_REQ_FSM_TEARDOWN"), + (uint8_t *) DISP_STRING("MID_TWT_REQ_FSM_SUSPEND"), + (uint8_t *) DISP_STRING("MID_TWT_REQ_FSM_RESUME"), + (uint8_t *) DISP_STRING("MID_TWT_REQ_IND_RESULT"), + (uint8_t *) DISP_STRING("MID_TWT_REQ_IND_SUSPEND_DONE"), + (uint8_t *) DISP_STRING("MID_TWT_REQ_IND_RESUME_DONE"), + (uint8_t *) DISP_STRING("MID_TWT_REQ_IND_TEARDOWN_DONE"), + (uint8_t *) DISP_STRING("MID_TWT_REQ_IND_INFOFRM"), + (uint8_t *) DISP_STRING("MID_TWT_PARAMS_SET"), +#endif + +}; + +/*lint -restore */ +#endif /* DBG */ + +/* This message entry will be re-ordered based on the message ID order + * by invoking mboxInitMsgMap() + */ +static struct MSG_HNDL_ENTRY arMsgMapTable[] = { + {MID_MNY_CNM_CH_REQ, cnmChMngrRequestPrivilege}, + {MID_MNY_CNM_CH_ABORT, cnmChMngrAbortPrivilege}, + {MID_CNM_AIS_CH_GRANT, aisFsmRunEventChGrant}, +#if CFG_ENABLE_WIFI_DIRECT + /*set in gl_p2p_init.c */ + {MID_CNM_P2P_CH_GRANT, p2pFsmRunEventChGrant}, +#else + {MID_CNM_P2P_CH_GRANT, mboxDummy}, +#endif + +#if (CFG_SUPPORT_DFS_MASTER == 1) + {MID_CNM_P2P_RADAR_DETECT, p2pRoleFsmRunEventRadarDet}, + {MID_CNM_P2P_CSA_DONE, p2pRoleFsmRunEventCsaDone}, +#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 + /*set in gl_p2p_init.c */ + {MID_SCN_P2P_SCAN_DONE, p2pFsmRunEventScanDone}, +#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_OID_SAA_FSM_CONTINUE, saaFsmRunEventFTContinue}, + {MID_OID_SAA_FSM_EXTERNAL_AUTH, saaFsmRunEventExternalAuthDone}, + {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, p2pRoleFsmRunEventJoinComplete}, /* V */ + + {MID_MNY_P2P_FUN_SWITCH, p2pRoleFsmRunEventSwitchOPMode}, + {MID_MNY_P2P_DEVICE_DISCOVERY, p2pFsmRunEventScanRequest}, /* V */ + {MID_MNY_P2P_CONNECTION_REQ, p2pRoleFsmRunEventConnectionRequest}, + {MID_MNY_P2P_CONNECTION_ABORT, p2pRoleFsmRunEventConnectionAbort}, + {MID_MNY_P2P_BEACON_UPDATE, p2pRoleFsmRunEventBeaconUpdate}, + {MID_MNY_P2P_STOP_AP, p2pRoleFsmRunEventStopAP}, + {MID_MNY_P2P_CHNL_REQ, p2pDevFsmRunEventChannelRequest}, /* V */ + {MID_MNY_P2P_CHNL_ABORT, p2pDevFsmRunEventChannelAbort}, /* V */ + {MID_MNY_P2P_MGMT_TX, p2pFsmRunEventMgmtFrameTx}, /* V */ + {MID_MNY_P2P_MGMT_TX_CANCEL_WAIT, p2pFsmRunEventTxCancelWait}, + {MID_MNY_P2P_GROUP_DISSOLVE, p2pRoleFsmRunEventDissolve}, + {MID_MNY_P2P_MGMT_FRAME_REGISTER, + p2pDevFsmRunEventMgmtFrameRegister}, + {MID_MNY_P2P_NET_DEV_REGISTER, p2pFsmRunEventNetDeviceRegister}, + {MID_MNY_P2P_START_AP, p2pRoleFsmRunEventStartAP}, + {MID_MNY_P2P_DEL_IFACE, p2pRoleFsmRunEventDelIface}, + {MID_MNY_P2P_MGMT_FRAME_UPDATE, p2pFsmRunEventUpdateMgmtFrame}, +#if (CFG_SUPPORT_DFS_MASTER == 1) + {MID_MNY_P2P_DFS_CAC, p2pRoleFsmRunEventDfsCac}, + {MID_MNY_P2P_SET_NEW_CHANNEL, p2pRoleFsmRunEventSetNewChannel}, +#endif +#if CFG_SUPPORT_WFD + {MID_MNY_P2P_WFD_CFG_UPDATE, p2pFsmRunEventWfdSettingUpdate}, +#endif + {MID_MNY_P2P_ACTIVE_BSS, p2pDevFsmRunEventActiveDevBss}, +#endif + +#if CFG_SUPPORT_ADHOC + {MID_SCN_AIS_FOUND_IBSS, aisFsmRunEventFoundIBSSPeer}, +#endif /* CFG_SUPPORT_ADHOC */ + + {MID_SAA_AIS_FSM_ABORT, aisFsmRunEventAbort}, + {MID_MNY_AIS_REMAIN_ON_CHANNEL, + aisFsmRunEventRemainOnChannel}, + {MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL, + aisFsmRunEventCancelRemainOnChannel}, + {MID_MNY_AIS_MGMT_TX, aisFsmRunEventMgmtFrameTx}, + {MID_MNY_AIS_MGMT_TX_CANCEL_WAIT, aisFsmRunEventCancelTxWait}, + {MID_WNM_AIS_BSS_TRANSITION, aisFsmRunEventBssTransition}, + {MID_OID_WMM_TSPEC_OPERATE, wmmRunEventTSOperate}, + {MID_RRM_REQ_SCHEDULE, rrmRunEventProcessNextRm}, +#if CFG_SUPPORT_NCHO + {MID_MNY_AIS_NCHO_ACTION_FRAME, + aisFsmRunEventNchoActionFrameTx}, +#endif + {MID_MNY_P2P_ACS, p2pRoleFsmRunEventAcs}, + +#if (CFG_SUPPORT_TWT == 1) + {MID_TWT_REQ_FSM_START, twtReqFsmRunEventStart}, + {MID_TWT_REQ_FSM_TEARDOWN, twtReqFsmRunEventTeardown}, + {MID_TWT_REQ_FSM_SUSPEND, twtReqFsmRunEventSuspend}, + {MID_TWT_REQ_FSM_RESUME, twtReqFsmRunEventResume}, + {MID_TWT_REQ_IND_RESULT, twtPlannerRxNegoResult}, + {MID_TWT_REQ_IND_SUSPEND_DONE, twtPlannerSuspendDone}, + {MID_TWT_REQ_IND_RESUME_DONE, twtPlannerResumeDone}, + {MID_TWT_REQ_IND_TEARDOWN_DONE, twtPlannerTeardownDone}, + {MID_TWT_REQ_IND_INFOFRM, twtPlannerRxInfoFrm}, + {MID_TWT_PARAMS_SET, twtPlannerSetParams}, +#endif + +}; + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +#if DBG +#define MBOX_HNDL_MSG(prAdapter, prMsg) do { \ + if (prMsg->eMsgId >= 0 && prMsg->eMsgId < MID_TOTAL_NUM) { \ + 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); \ + } \ + } \ + else { \ + DBGLOG(CNM, ERROR, "Invalid MSG ID [%d]\n", prMsg->eMsgId); \ + cnmMemFree(prAdapter, prMsg); \ + } \ +} while (0) +#else +#define MBOX_HNDL_MSG(prAdapter, prMsg) do { \ + if (prMsg->eMsgId >= 0 && prMsg->eMsgId < MID_TOTAL_NUM) { \ + 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); \ + } \ + } \ + else { \ + DBGLOG(CNM, ERROR, "Invalid MSG ID [%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) +{ + uint32_t i, idx; + struct MSG_HNDL_ENTRY rTempEntry; + + ASSERT((sizeof(arMsgMapTable) / sizeof(struct + MSG_HNDL_ENTRY)) == MID_TOTAL_NUM); + + for (i = 0; i < MID_TOTAL_NUM; i++) { + if (arMsgMapTable[i].eMsgId == (enum ENUM_MSG_ID) i) + continue; + for (idx = i + 1; idx < MID_TOTAL_NUM; idx++) { + if (arMsgMapTable[idx].eMsgId == (enum ENUM_MSG_ID) 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 ENUM_MSG_ID) i); + while (arMsgMapTable[i].eMsgId != (enum ENUM_MSG_ID) i) + ; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void mboxSetup(IN struct ADAPTER *prAdapter, + IN enum ENUM_MBOX_ID eMboxId) +{ + struct MBOX *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 struct ADAPTER *prAdapter, + IN enum ENUM_MBOX_ID eMboxId, IN struct MSG_HDR *prMsg, + IN enum EUNM_MSG_SEND_METHOD eMethod) +{ + struct MBOX *prMbox; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(eMboxId < MBOX_ID_TOTAL_NUM); + ASSERT(prMsg); + if (!prMsg) { + DBGLOG(CNM, ERROR, "prMsg is NULL\n"); + return; + } + + ASSERT(prAdapter); + if (!prAdapter) { + DBGLOG(CNM, ERROR, "prAdapter is NULL\n"); + return; + } + + 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 struct ADAPTER *prAdapter, + enum ENUM_MBOX_ID eMboxId) +{ + struct MBOX *prMbox; + struct MSG_HDR *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, + struct MSG_HDR *); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); + + ASSERT(prMsg); + if (!prMsg) { + DBGLOG(CNM, ERROR, "prMsg is NULL\n"); + continue; + } +#ifdef UT_TEST_MODE + if (testMBoxRcv(prAdapter, prMsg)) +#endif + MBOX_HNDL_MSG(prAdapter, prMsg); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void mboxInitialize(IN struct ADAPTER *prAdapter) +{ + uint32_t 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 struct ADAPTER *prAdapter) +{ + struct MBOX *prMbox; + struct MSG_HDR *prMsg; + uint8_t 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, + struct MSG_HDR *); + 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 struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + ASSERT(prAdapter); + + cnmMemFree(prAdapter, prMsgHdr); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/hs20.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/hs20.c new file mode 100644 index 0000000000000..71deac15d69da --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/hs20.c @@ -0,0 +1,601 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/HS2_DEV_SW/ + * MT6620_WIFI_DRIVER_V2_1_HS_2_0/mgmt/hs20.c#2 + */ + +/*! \file "hs20.c" + * \brief This file including the hotspot 2.0 related function. + * + * This file provided the macros and functions library support for the + * protocol layer hotspot 2.0 related function. + * + */ + + +/****************************************************************************** + * C O M P I L E 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_PASSPOINT + +/****************************************************************************** + * 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 + ****************************************************************************** + */ + +void hs20FillExtCapIE(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, struct MSDU_INFO *prMsduInfo) +{ + struct IE_EXT_CAP *prExtCap; + struct HS20_INFO *prHS20Info; + uint8_t ucBssIndex = 0; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + ucBssIndex = prMsduInfo->ucBssIndex; + prHS20Info = aisGetHS20Info(prAdapter, ucBssIndex); + if (!prHS20Info) + return; + + /* Add Extended Capabilities IE */ + prExtCap = (struct IE_EXT_CAP *) + (((uint8_t *) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + + prExtCap->ucId = ELEM_ID_EXTENDED_CAP; + if (prHS20Info->fgConnectHS20AP == TRUE) + prExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + else + prExtCap->ucLength = 3 - ELEM_HDR_LEN; + + kalMemZero(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP); + + prExtCap->aucCapabilities[0] = ELEM_EXT_CAP_DEFAULT_VAL; + + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + prExtCap->aucCapabilities[0] &= ~ELEM_EXT_CAP_PSMP_CAP; + + if (prHS20Info->fgConnectHS20AP == TRUE) { + SET_EXT_CAP(prExtCap->aucCapabilities, + ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_BSS_TRANSITION_BIT); + SET_EXT_CAP(prExtCap->aucCapabilities, + ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_UTC_TSF_OFFSET_BIT); + SET_EXT_CAP(prExtCap->aucCapabilities, + ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_INTERWORKING_BIT); + SET_EXT_CAP(prExtCap->aucCapabilities, + ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_QOSMAPSET_BIT); + + /* For R2 WNM-Notification */ + SET_EXT_CAP(prExtCap->aucCapabilities, + ELEM_MAX_LEN_EXT_CAP, + ELEM_EXT_CAP_WNM_NOTIFICATION_BIT); + } + + pr_info("IE_SIZE(prExtCap) = %d, %d %d\n", + IE_SIZE(prExtCap), ELEM_HDR_LEN, ELEM_MAX_LEN_EXT_CAP); + + ASSERT(IE_SIZE(prExtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP)); + + prMsduInfo->u2FrameLength += IE_SIZE(prExtCap); +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief This function is called to fill up + * the content of Ext Cap IE bit 31. + * + * \param[in] prAdapter Pointer of ADAPTER_T + * \param[out] pucIE Pointer of the IE buffer + * + * \return VOID + */ +/*---------------------------------------------------------------------------*/ +void hs20FillProreqExtCapIE(IN struct ADAPTER *prAdapter, OUT uint8_t *pucIE) +{ + struct IE_EXT_CAP *prExtCap; + struct HS20_INFO *prHS20Info; + + ASSERT(prAdapter); + + prHS20Info = aisGetHS20Info(prAdapter, + AIS_DEFAULT_INDEX); + if (!prHS20Info) + return; + + /* Add Extended Capabilities IE */ + prExtCap = (struct IE_EXT_CAP *) pucIE; + + prExtCap->ucId = ELEM_ID_EXTENDED_CAP; + if (prHS20Info->fgConnectHS20AP == TRUE) + prExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + else + prExtCap->ucLength = 3 - ELEM_HDR_LEN; + + kalMemZero(prExtCap->aucCapabilities, prExtCap->ucLength); + + prExtCap->aucCapabilities[0] = ELEM_EXT_CAP_DEFAULT_VAL; + + if (prHS20Info->fgConnectHS20AP == TRUE) { + SET_EXT_CAP(prExtCap->aucCapabilities, + ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_BSS_TRANSITION_BIT); + SET_EXT_CAP(prExtCap->aucCapabilities, + ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_UTC_TSF_OFFSET_BIT); + SET_EXT_CAP(prExtCap->aucCapabilities, + ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_INTERWORKING_BIT); + SET_EXT_CAP(prExtCap->aucCapabilities, + ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_QOSMAPSET_BIT); + + /* For R2 WNM-Notification */ + SET_EXT_CAP(prExtCap->aucCapabilities, + ELEM_MAX_LEN_EXT_CAP, + ELEM_EXT_CAP_WNM_NOTIFICATION_BIT); + } +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief This function is called to fill up the content of HS2.0 IE. + * + * \param[in] prAdapter Pointer of ADAPTER_T + * \param[out] pucIE Pointer of the IE buffer + * + * \return VOID + */ +/*---------------------------------------------------------------------------*/ +void hs20FillHS20IE(IN struct ADAPTER *prAdapter, OUT uint8_t *pucIE) +{ + struct IE_HS20_INDICATION *prHS20IndicationIe; + /* P_HS20_INFO_T prHS20Info; */ + uint8_t aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + + /* prHS20Info = &(prAdapter->rWifiVar.rHS20Info); */ + + prHS20IndicationIe = (struct IE_HS20_INDICATION *) pucIE; + + prHS20IndicationIe->ucId = ELEM_ID_VENDOR; + prHS20IndicationIe->ucLength = + sizeof(struct IE_HS20_INDICATION) - ELEM_HDR_LEN; + prHS20IndicationIe->aucOui[0] = aucWfaOui[0]; + prHS20IndicationIe->aucOui[1] = aucWfaOui[1]; + prHS20IndicationIe->aucOui[2] = aucWfaOui[2]; + prHS20IndicationIe->ucType = VENDOR_OUI_TYPE_HS20; + + /* For PASSPOINT_R1 */ + /* prHS20IndicationIe->ucHotspotConfig = 0x00; */ + + /* For PASSPOINT_R2 */ + prHS20IndicationIe->ucHotspotConfig = 0x10; + +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief This function is called while calculating length of + * hotspot 2.0 indication IE for Probe Request. + * + * \param[in] prAdapter Pointer of ADAPTER_T + * \param[in] pucTargetBSSID Pointer of target HESSID + * + * \return the length of composed HS20 IE + */ +/*---------------------------------------------------------------------------*/ +uint32_t hs20CalculateHS20RelatedIEForProbeReq(IN struct ADAPTER *prAdapter, + IN uint8_t *pucTargetBSSID) +{ + uint32_t u4IeLength; + + if (0) /* Todo:: Not HS20 STA */ + return 0; + + u4IeLength = sizeof(struct IE_HS20_INDICATION) + + /* sizeof(IE_INTERWORKING_T) */ + + (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP); + + if (!pucTargetBSSID) { + /* Todo:: Nothing */ + /* u4IeLength -= MAC_ADDR_LEN; */ + } + + return u4IeLength; +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief This function is called while composing + * hotspot 2.0 indication IE for Probe Request. + * + * \param[in] prAdapter Pointer of ADAPTER_T + * \param[in] pucTargetBSSID Pointer of target HESSID + * \param[out] prIE Pointer of the IE buffer + * + * \return the wlan status + */ +/*---------------------------------------------------------------------------*/ +uint32_t hs20GenerateHS20RelatedIEForProbeReq(IN struct ADAPTER *prAdapter, + IN uint8_t *pucTargetBSSID, OUT uint8_t *prIE) +{ + if (0) /* Todo:: Not HS20 STA */ + return 0; +#if 0 + struct HS20_INFO *prHS20Info; + + prHS20Info = &(prAdapter->rWifiVar.rHS20Info); + + /* + * Generate 802.11u Interworking IE (107) + */ + hs20FillInterworkingIE(prAdapter, + prHS20Info->ucAccessNetworkOptions, + prHS20Info->ucVenueGroup, + prHS20Info->ucVenueType, + pucTargetBSSID, prIE); + prIE += IE_SIZE(prIE); +#endif + /* + * Generate Ext Cap IE (127) + */ + hs20FillProreqExtCapIE(prAdapter, prIE); + prIE += IE_SIZE(prIE); + + /* + * Generate HS2.0 Indication IE (221) + */ + hs20FillHS20IE(prAdapter, prIE); + prIE += IE_SIZE(prIE); + + return WLAN_STATUS_SUCCESS; +} + +u_int8_t hs20IsGratuitousArp(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prCurrSwRfb) +{ + uint8_t *pucSenderIP = + prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + ARP_SENDER_IP_OFFSET; + uint8_t *pucTargetIP = + prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + ARP_TARGET_IP_OFFSET; + uint8_t *pucSenderMac = ((uint8_t *) + prCurrSwRfb->pvHeader + + ETHER_HEADER_LEN + ARP_SENDER_MAC_OFFSET); + +#if CFG_HS20_DEBUG && 0 +/* UINT_8 aucIpAllZero[4] = {0,0,0,0}; */ +/* UINT_8 aucMACAllZero[MAC_ADDR_LEN] = {0,0,0,0,0,0}; */ + uint8_t *pucTargetMac = ((uint8_t *) + prCurrSwRfb->pvHeader + + ETHER_HEADER_LEN + ARP_TARGET_MAC_OFFSET); +#endif + +#if CFG_HS20_DEBUG && 0 + uint16_t *pu2ArpOper = (uint16_t *) ((uint8_t *) + prCurrSwRfb->pvHeader + + ETHER_HEADER_LEN + ARP_OPERATION_OFFSET); + + kalPrint("Recv ARP 0x%04X\n", htons(*pu2ArpOper)); + kalPrint("SENDER[" MACSTR "] [%d:%d:%d:%d]\n", + MAC2STR(pucSenderMac), *pucSenderIP, + *(pucSenderIP + 1), *(pucSenderIP + 2), *(pucSenderIP + 3)); + kalPrint("TARGET[" MACSTR "] [%d:%d:%d:%d]\n", + MAC2STR(pucTargetMac), *pucTargetIP, + *(pucTargetIP + 1), *(pucTargetIP + 2), *(pucTargetIP + 3)); +#endif + + /* IsGratuitousArp */ + if (!kalMemCmp(pucSenderIP, pucTargetIP, 4)) { + kalPrint( + "Drop Gratuitous ARP from [" MACSTR "] [%d:%d:%d:%d]\n", + MAC2STR(pucSenderMac), *pucTargetIP, *(pucTargetIP + 1), + *(pucTargetIP + 2), *(pucTargetIP + 3)); + return TRUE; + } + return FALSE; +} + +u_int8_t hs20IsUnsolicitedNeighborAdv(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prCurrSwRfb) +{ + uint8_t *pucIpv6Protocol = ((uint8_t *) + prCurrSwRfb->pvHeader + + ETHER_HEADER_LEN + IPV6_HDR_IP_PROTOCOL_OFFSET); + + /* kalPrint("pucIpv6Protocol [%02X:%02X]\n", + * *pucIpv6Protocol, IPV6_PROTOCOL_ICMPV6); + */ + if (*pucIpv6Protocol == IPV6_PROTOCOL_ICMPV6) { + uint8_t *pucICMPv6Type = + ((uint8_t *) prCurrSwRfb->pvHeader + + ETHER_HEADER_LEN + IPV6_HDR_LEN + ICMPV6_TYPE_OFFSET); + /* kalPrint("pucICMPv6Type [%02X:%02X]\n", + * *pucICMPv6Type, ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT); + */ + if (*pucICMPv6Type == ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT) { + uint8_t *pucICMPv6Flag = + ((uint8_t *) prCurrSwRfb->pvHeader + + ETHER_HEADER_LEN + + IPV6_HDR_LEN + ICMPV6_FLAG_OFFSET); + uint8_t *pucSrcMAC = ((uint8_t *) + prCurrSwRfb->pvHeader + MAC_ADDR_LEN); + +#if CFG_HS20_DEBUG + kalPrint("NAdv Flag [%02X] [R(%d)\\S(%d)\\O(%d)]\n", + *pucICMPv6Flag, + (uint8_t) (*pucICMPv6Flag + & ICMPV6_FLAG_ROUTER_BIT) >> 7, + (uint8_t) (*pucICMPv6Flag + & ICMPV6_FLAG_SOLICITED_BIT) >> 6, + (uint8_t) (*pucICMPv6Flag + & ICMPV6_FLAG_OVERWRITE_BIT) >> 5); +#endif + if (!(*pucICMPv6Flag & ICMPV6_FLAG_SOLICITED_BIT)) { + kalPrint( + "Drop Unsolicited Neighbor Advertisement from [" + MACSTR "]\n", MAC2STR(pucSrcMAC)); + return TRUE; + } + } + } + + return FALSE; +} + +#if CFG_ENABLE_GTK_FRAME_FILTER +u_int8_t hs20IsForgedGTKFrame(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, IN struct SW_RFB *prCurrSwRfb) +{ + struct CONNECTION_SETTINGS *prConnSettings = + aisGetConnSettings(prAdapter, prBssInfo->ucBssIndex); + uint8_t *pucEthDestAddr = prCurrSwRfb->pvHeader; + + /* 3 TODO: Need to verify this function before enable it */ + return FALSE; + + if ((prConnSettings->eEncStatus != ENUM_ENCRYPTION_DISABLED) + && IS_BMCAST_MAC_ADDR(pucEthDestAddr)) { + uint8_t ucIdx = 0; + uint32_t *prIpAddr, *prPacketDA; + uint16_t *pu2PktIpVer = + (uint16_t *) ((uint8_t *) + prCurrSwRfb->pvHeader + + (ETHER_HEADER_LEN - ETHER_TYPE_LEN)); + + if (*pu2PktIpVer == htons(ETH_P_IPV4)) { + if (!prBssInfo->prIpV4NetAddrList) + return FALSE; + for (ucIdx = 0; + ucIdx < prBssInfo + ->prIpV4NetAddrList->ucAddrCount; + ucIdx++) { + prIpAddr = (uint32_t *) + &prBssInfo->prIpV4NetAddrList + ->arNetAddr[ucIdx].aucIpAddr[0]; + prPacketDA = + (uint32_t *) ((uint8_t *) + prCurrSwRfb->pvHeader + + ETHER_HEADER_LEN + + IPV4_HDR_IP_DST_ADDR_OFFSET); + + if (kalMemCmp(prIpAddr, prPacketDA, 4) == 0) { + kalPrint("Drop FORGED IPv4 packet\n"); + return TRUE; + } + } + } +#ifdef CONFIG_IPV6 + else if (*pu2PktIpVer == htons(ETH_P_IPV6)) { + uint8_t aucIPv6Mac[MAC_ADDR_LEN]; + uint8_t *pucIdx = + prCurrSwRfb->pvHeader + + ETHER_HEADER_LEN + + IPV6_HDR_IP_DST_ADDR_MAC_HIGH_OFFSET; + + kalMemCopy(&aucIPv6Mac[0], pucIdx, 3); + pucIdx += 5; + kalMemCopy(&aucIPv6Mac[3], pucIdx, 3); + kalPrint( + "Get IPv6 frame Dst IP MAC part " MACSTR "\n", + MAC2STR(aucIPv6Mac)); + + if (EQUAL_MAC_ADDR(aucIPv6Mac, + prBssInfo->aucOwnMacAddr)) { + kalPrint("Drop FORGED IPv6 packet\n"); + return TRUE; + } + } +#endif + } + + return FALSE; +} +#endif + +u_int8_t hs20IsUnsecuredFrame(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, IN struct SW_RFB *prCurrSwRfb) +{ + uint16_t *pu2PktIpVer = (uint16_t *) ((uint8_t *) + prCurrSwRfb->pvHeader + (ETHER_HEADER_LEN - ETHER_TYPE_LEN)); + + /* kalPrint("IPVER 0x%4X\n", htons(*pu2PktIpVer)); */ +#if CFG_HS20_DEBUG & 0 + uint8_t i = 0; + + kalPrint("==============================================="); + for (i = 0; i < 96; i++) { + if (!(i % 16)) + kalPrint("\n"); + kalPrint("%02X ", *((uint8_t *) prCurrSwRfb->pvHeader + i)); + } + kalPrint("\n"); +#endif + +#if CFG_ENABLE_GTK_FRAME_FILTER + if (hs20IsForgedGTKFrame(prAdapter, prBssInfo, prCurrSwRfb)) + return TRUE; +#endif + if (*pu2PktIpVer == htons(ETH_P_ARP)) + return hs20IsGratuitousArp(prAdapter, prCurrSwRfb); + else if (*pu2PktIpVer == htons(ETH_P_IPV6)) + return hs20IsUnsolicitedNeighborAdv(prAdapter, prCurrSwRfb); + + return FALSE; +} + +u_int8_t hs20IsFrameFilterEnabled(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo) +{ +#if 1 + struct HS20_INFO *prHS20Info; + + prHS20Info = aisGetHS20Info(prAdapter, + prBssInfo->ucBssIndex); + + if (prHS20Info && prHS20Info->fgConnectHS20AP) + return TRUE; +#else + struct PARAM_SSID rParamSsid; + struct BSS_DESC *prBssDesc; + + rParamSsid.u4SsidLen = prBssInfo->ucSSIDLen; + COPY_SSID(rParamSsid.aucSsid, + rParamSsid.u4SsidLen, prBssInfo->aucSSID, prBssInfo->ucSSIDLen); + + prBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, + prBssInfo->aucBSSID, TRUE, &rParamSsid); + + if (!prBssDesc) + return FALSE; + + if (prBssDesc->fgIsSupportHS20) { + if (!(prBssDesc->ucHotspotConfig + & ELEM_HS_CONFIG_DGAF_DISABLED_MASK)) + return TRUE; + /* Disable frame filter only if DGAF == 1 */ + return FALSE; + } +#endif + + /* For Now, always return true to run hs20 check even for legacy AP */ + return TRUE; +} + +uint32_t hs20SetBssidPool(IN struct ADAPTER *prAdapter, + IN void *pvBuffer, + IN uint8_t ucBssIndex) +{ + struct PARAM_HS20_SET_BSSID_POOL *prParamBssidPool = + (struct PARAM_HS20_SET_BSSID_POOL *) pvBuffer; + struct HS20_INFO *prHS20Info; + uint8_t ucIdx; + + prHS20Info = aisGetHS20Info(prAdapter, ucBssIndex); + + pr_info("[%s]Set Bssid Pool! enable[%d] num[%d]\n", + __func__, prParamBssidPool->fgIsEnable, + prParamBssidPool->ucNumBssidPool); + + for (ucIdx = 0; ucIdx < prParamBssidPool->ucNumBssidPool; ucIdx++) { + COPY_MAC_ADDR( + prHS20Info->arBssidPool[ucIdx].aucBSSID, + &prParamBssidPool->arBSSID[ucIdx]); + + pr_info("[%s][%d][" MACSTR "]\n", + __func__, ucIdx, + MAC2STR(prHS20Info->arBssidPool[ucIdx].aucBSSID)); + } + prHS20Info->fgIsHS2SigmaMode = prParamBssidPool->fgIsEnable; + prHS20Info->ucNumBssidPoolEntry = prParamBssidPool->ucNumBssidPool; + +#if 0 + wlanClearScanningResult(prAdapter); +#endif + + return WLAN_STATUS_SUCCESS; +} + +#endif /* CFG_SUPPORT_PASSPOINT */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/mddp.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/mddp.c new file mode 100644 index 0000000000000..d8fdc0e992e40 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/mddp.c @@ -0,0 +1,832 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +/* +** Id: @(#) mddp.c@@ +*/ + +/*! \file mddp.c +* \brief Main routines for modem direct path handling +* +* This file contains the support routines of modem direct path operation. +*/ + + +/******************************************************************************* +* C O M P I L E 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_MTK_MCIF_WIFI_SUPPORT + +#include "gl_os.h" +#include "mddp_export.h" +#include "mddp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +struct mddpw_drv_handle_t gMddpWFunc = { + mddpMdNotifyInfo, + NULL, + NULL, + NULL, + NULL, +}; + +struct mddp_drv_conf_t gMddpDrvConf = { + .app_type = MDDP_APP_TYPE_WH, +}; + +struct mddp_drv_handle_t gMddpFunc = { +#if CFG_MTK_MDDP_WH_SUPPORT + .change_state = mddpChangeState, +#endif +}; + +#define MD_ON_OFF_TIMEOUT 1000 +#ifdef SOC3_0 +#define MD_STATUS_SYNC_CR 0x180600F4 +#else +#define MD_STATUS_SYNC_CR 0x1800701C +#endif +#define MD_SUPPORT_MDDP_STATUS_SYNC_CR_BIT BIT(0) +#define MD_STATUS_OFF_SYNC_BIT BIT(1) +#define MD_STATUS_ON_SYNC_BIT BIT(2) + +#if (CFG_SUPPORT_CONNAC2X == 0) +/* Use SER dummy register for mddp support flag */ +#define MDDP_SUPPORT_CR 0x820600d0 +#define MDDP_SUPPORT_CR_BIT BIT(23) +#endif + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#define MAC_ADDR_LEN 6 + +struct mddp_txd_t { +uint8_t version; +uint8_t wlan_idx; +uint8_t sta_idx; +uint8_t nw_if_name[8]; +uint8_t sta_mode; +uint8_t bss_id; +uint8_t wmmset; +uint8_t aucMacAddr[MAC_ADDR_LEN]; +uint8_t txd_length; +uint8_t txd[0]; +} __packed; + +struct tag_bootmode { + u32 size; + u32 tag; + u32 bootmode; + u32 boottype; +}; + +enum BOOTMODE { + NORMAL_BOOT = 0, + META_BOOT = 1, + RECOVERY_BOOT = 2, + SW_REBOOT = 3, + FACTORY_BOOT = 4, + ADVMETA_BOOT = 5, + ATE_FACTORY_BOOT = 6, + ALARM_BOOT = 7, + KERNEL_POWER_OFF_CHARGING_BOOT = 8, + LOW_POWER_OFF_CHARGING_BOOT = 9, + FASTBOOT = 99, + DOWNLOAD_BOOT = 100, + UNKNOWN_BOOT +}; + +enum BOOTMODE g_boot_mode = NORMAL_BOOT; +u_int8_t g_fgMddpEnabled = TRUE; + +struct mddpw_net_stat_ext_t stats; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +static void clear_md_wifi_off_bit(void); +static void clear_md_wifi_on_bit(void); +static bool wait_for_md_on_complete(void); +static void save_mddp_stats(void); + +static int32_t mddpRegisterCb(void) +{ + int32_t ret = 0; + + switch (g_boot_mode) { + case RECOVERY_BOOT: + g_fgMddpEnabled = FALSE; + break; + default: + g_fgMddpEnabled = TRUE; + break; + } + gMddpFunc.wifi_handle = &gMddpWFunc; + + ret = mddp_drv_attach(&gMddpDrvConf, &gMddpFunc); + DBGLOG(INIT, INFO, "mddp_drv_attach ret: %d, g_fgMddpEnabled: %d\n", + ret, g_fgMddpEnabled); + + kalMemZero(&stats, sizeof(struct mddpw_net_stat_ext_t)); + + return ret; +} + +static void mddpUnregisterCb(void) +{ + DBGLOG(INIT, INFO, "mddp_drv_detach\n"); + mddp_drv_detach(&gMddpDrvConf, &gMddpFunc); + gMddpFunc.wifi_handle = NULL; +} + +int32_t mddpGetMdStats(IN struct net_device *prDev) +{ + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate; + struct net_device_stats *prStats; + struct GLUE_INFO *prGlueInfo; + struct mddpw_net_stat_ext_t mddpNetStats; + int32_t ret; + uint8_t i = 0; + + if (!gMddpWFunc.get_net_stat_ext) + return 0; + + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prDev); + prStats = &prNetDevPrivate->stats; + prGlueInfo = prNetDevPrivate->prGlueInfo; + + if (!prGlueInfo || (prGlueInfo->u4ReadyFlag == 0) || + !prGlueInfo->prAdapter) + return 0; + + if (!prNetDevPrivate->ucMddpSupport) + return 0; + + ret = gMddpWFunc.get_net_stat_ext(&mddpNetStats); + if (ret != 0) { + DBGLOG(INIT, ERROR, "get_net_stat fail, ret: %d.\n", ret); + return 0; + } + for (i = 0; i < NW_IF_NUM_MAX; i++) { + struct mddpw_net_stat_elem_ext_t *element, *prev; + + element = &mddpNetStats.ifs[0][i]; + prev = &stats.ifs[0][i]; + if (kalStrnCmp(element->nw_if_name, prDev->name, + IFNAMSIZ) != 0) + continue; + + prStats->rx_packets += + element->rx_packets + prev->rx_packets; + prStats->tx_packets += + element->tx_packets + prev->tx_packets; + prStats->rx_bytes += + element->rx_bytes + prev->rx_bytes; + prStats->tx_bytes += + element->tx_bytes + prev->tx_bytes; + prStats->rx_errors += + element->rx_errors + prev->rx_errors; + prStats->tx_errors += + element->tx_errors + prev->tx_errors; + prStats->rx_dropped += + element->rx_dropped + prev->rx_dropped; + prStats->tx_dropped += + element->tx_dropped + prev->tx_dropped; + } + + return 0; +} + +int32_t mddpSetTxDescTemplate(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN uint8_t fgActivate) +{ + struct mddpw_txd_t *prMddpTxd; + uint32_t u32BufSize = 0; + uint8_t *buff = NULL; + + if (gMddpWFunc.add_txd) { + int32_t ret; + + u32BufSize = (sizeof(struct mddpw_txd_t) + + NIC_TX_DESC_LONG_FORMAT_LENGTH); + buff = kalMemAlloc(u32BufSize, VIR_MEM_TYPE); + + if (buff == NULL) { + DBGLOG(NIC, ERROR, "Can't allocate TXD buffer.\n"); + return -1; + } + prMddpTxd = (struct mddpw_txd_t *) buff; + prMddpTxd->version = 0; + prMddpTxd->sta_idx = prStaRec->ucIndex; + prMddpTxd->wlan_idx = prStaRec->ucWlanIndex; + memcpy(prMddpTxd->aucMacAddr, + prStaRec->aucMacAddr, MAC_ADDR_LEN); + if (fgActivate) + prMddpTxd->txd_length = NIC_TX_DESC_LONG_FORMAT_LENGTH; + else + prMddpTxd->txd_length = 0; + memcpy(prMddpTxd->txd, + prStaRec->aprTxDescTemplate[0], prMddpTxd->txd_length); + ret = gMddpWFunc.add_txd(prMddpTxd); + DBGLOG(NIC, INFO, "ret: %d\n", ret); + kalMemFree(buff, VIR_MEM_TYPE, u32BufSize); + } else { + DBGLOG(INIT, ERROR, "add_txd is NULL.\n"); + } + + return 0; +} + +static bool mddpIsSsnSent(struct ADAPTER *prAdapter, + uint8_t *prReorderBuf, uint16_t u2SSN) +{ + uint8_t ucSent = 0; + uint16_t u2Idx = u2SSN / 8; + uint8_t ucBit = u2SSN % 8; + + ucSent = (prReorderBuf[u2Idx] & BIT(ucBit)) != 0; + prReorderBuf[u2Idx] &= ~(BIT(ucBit)); + + return ucSent; +} + +static void mddpGetRxReorderBuffer(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb, + struct mddpw_md_virtual_buf_t **prMdBuf, + struct mddpw_ap_virtual_buf_t **prApBuf) +{ + struct mddpw_md_reorder_sync_table_t *prMdTable = NULL; + struct mddpw_ap_reorder_sync_table_t *prApTable = NULL; + uint8_t ucStaRecIdx = prSwRfb->ucStaRecIdx; + uint8_t ucTid = prSwRfb->ucTid; + int32_t u4Idx = 0; + + if (gMddpWFunc.get_md_rx_reorder_buf && + gMddpWFunc.get_ap_rx_reorder_buf) { + if (!gMddpWFunc.get_md_rx_reorder_buf(&prMdTable) && + !gMddpWFunc.get_ap_rx_reorder_buf(&prApTable)) { + u4Idx = prMdTable->reorder_info[ucStaRecIdx].buf_idx; + *prMdBuf = &prMdTable->virtual_buf[u4Idx][ucTid]; + *prApBuf = &prApTable->virtual_buf[u4Idx][ucTid]; + } + } +} + +void mddpUpdateReorderQueParm(struct ADAPTER *prAdapter, + struct RX_BA_ENTRY *prReorderQueParm, + struct SW_RFB *prSwRfb) +{ + struct mddpw_md_virtual_buf_t *prMdBuf = NULL; + struct mddpw_ap_virtual_buf_t *prApBuf = NULL; + uint16_t u2SSN = prReorderQueParm->u2WinStart, u2Idx; + + mddpGetRxReorderBuffer(prAdapter, prSwRfb, &prMdBuf, &prApBuf); + if (!prMdBuf || !prApBuf) { + DBGLOG(QM, ERROR, "Can't get reorder buffer.\n"); + return; + } + + for (u2Idx = 0; u2Idx < prReorderQueParm->u2WinSize; u2Idx++) { + if (prReorderQueParm->u2WinStart == prSwRfb->u2SSN || + !mddpIsSsnSent(prAdapter, prMdBuf->virtual_buf, u2SSN)) + break; + + prReorderQueParm->u2WinStart = + (u2SSN % MAX_SEQ_NO_COUNT); + prReorderQueParm->u2WinEnd = + (((prReorderQueParm->u2WinStart) + + (prReorderQueParm->u2WinSize) - 1) % + MAX_SEQ_NO_COUNT); + u2SSN = (u2SSN + 1) % MAX_SEQ_NO_COUNT; + DBGLOG(QM, TRACE, + "Update reorder window: SSN: %d, start: %d, end: %d.\n", + u2SSN, + prReorderQueParm->u2WinStart, + prReorderQueParm->u2WinEnd); + } + + prApBuf->start_idx = prReorderQueParm->u2WinStart; + prApBuf->end_idx = prReorderQueParm->u2WinEnd; +} + +int32_t mddpNotifyDrvTxd(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN uint8_t fgActivate) +{ + struct mddpw_drv_notify_info_t *prNotifyInfo; + struct mddpw_drv_info_t *prDrvInfo; + struct mddp_txd_t *prMddpTxd; + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + struct net_device *prNetdev; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate; + uint32_t u32BufSize = 0; + uint8_t *buff = NULL; + int32_t ret = 0; + + if (!gMddpWFunc.notify_drv_info) { + DBGLOG(NIC, ERROR, "notify_drv_info callback NOT exist.\n"); + ret = -1; + goto exit; + } + if (!prStaRec) { + DBGLOG(NIC, ERROR, "sta NOT valid\n"); + ret = -1; + goto exit; + } + if (prStaRec->ucBssIndex >= MAX_BSSID_NUM) { + DBGLOG(NIC, ERROR, "sta bssid NOT valid: %d.\n", + prStaRec->ucBssIndex); + ret = -1; + goto exit; + } + if (fgActivate && !prStaRec->aprTxDescTemplate[0]) { + DBGLOG(NIC, INFO, + "sta[%d]'s TXD NOT generated done, maybe wait.\n", + prStaRec->ucBssIndex); + ret = -1; + goto exit; + } + + prBssInfo = prAdapter->aprBssInfo[prStaRec->ucBssIndex]; + prNetdev = (struct net_device *) wlanGetNetInterfaceByBssIdx( + prAdapter->prGlueInfo, prStaRec->ucBssIndex); + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prNetdev); + + if (!prNetDevPrivate->ucMddpSupport) { + goto exit; + } + + u32BufSize = (sizeof(struct mddpw_drv_notify_info_t) + + sizeof(struct mddpw_drv_info_t) + + sizeof(struct mddp_txd_t) + + NIC_TX_DESC_LONG_FORMAT_LENGTH); + buff = kalMemAlloc(u32BufSize, VIR_MEM_TYPE); + + if (buff == NULL) { + DBGLOG(NIC, ERROR, "buffer allocation failed.\n"); + ret = -1; + goto exit; + } + prNotifyInfo = (struct mddpw_drv_notify_info_t *) buff; + prNotifyInfo->version = 0; + prNotifyInfo->buf_len = sizeof(struct mddpw_drv_info_t) + + sizeof(struct mddp_txd_t) + + NIC_TX_DESC_LONG_FORMAT_LENGTH; + prNotifyInfo->info_num = 1; + prDrvInfo = (struct mddpw_drv_info_t *) &(prNotifyInfo->buf[0]); + prDrvInfo->info_id = 3; /* MDDPW_DRV_INFO_TXD; */ + prDrvInfo->info_len = (sizeof(struct mddpw_txd_t) + + NIC_TX_DESC_LONG_FORMAT_LENGTH); + prMddpTxd = (struct mddp_txd_t *) &(prDrvInfo->info[0]); + prMddpTxd->version = 0; + prMddpTxd->sta_idx = prStaRec->ucIndex; + prMddpTxd->wlan_idx = prStaRec->ucWlanIndex; + prMddpTxd->sta_mode = prStaRec->eStaType; + prMddpTxd->bss_id = prStaRec->ucBssIndex; + prMddpTxd->wmmset = prBssInfo->ucWmmQueSet; + kalMemCopy(prMddpTxd->nw_if_name, prNetdev->name, + sizeof(prMddpTxd->nw_if_name)); + kalMemCopy(prMddpTxd->aucMacAddr, prStaRec->aucMacAddr, MAC_ADDR_LEN); + if (fgActivate) { + prMddpTxd->txd_length = NIC_TX_DESC_LONG_FORMAT_LENGTH; + kalMemCopy(prMddpTxd->txd, prStaRec->aprTxDescTemplate[0], + prMddpTxd->txd_length); + } else { + prMddpTxd->txd_length = 0; + } + + ret = gMddpWFunc.notify_drv_info(prNotifyInfo); + +#define TEMP_LOG_TEMPLATE "ver:%d,idx:%d,w_idx:%d,mod:%d,bss:%d,wmm:%d," \ + "name:%s,act:%d,ret:%d" + DBGLOG(NIC, INFO, TEMP_LOG_TEMPLATE, + prMddpTxd->version, + prMddpTxd->sta_idx, + prMddpTxd->wlan_idx, + prMddpTxd->sta_mode, + prMddpTxd->bss_id, + prMddpTxd->wmmset, + prMddpTxd->nw_if_name, + fgActivate, + ret); +#undef TEMP_LOG_TEMPLATE + +exit: + if (buff) + kalMemFree(buff, VIR_MEM_TYPE, u32BufSize); + return ret; +} + +int32_t mddpNotifyDrvMac(IN struct ADAPTER *prAdapter) +{ + struct mddpw_drv_notify_info_t *prNotifyInfo; + struct mddpw_drv_info_t *prDrvInfo; + uint32_t u32BufSize = 0; + uint8_t *buff = NULL; + struct BSS_INFO *prAisBssInfo = (struct BSS_INFO *) NULL; + + if (gMddpWFunc.notify_drv_info) { + int32_t ret; + + u32BufSize = (sizeof(struct mddpw_drv_notify_info_t) + + sizeof(struct mddpw_drv_info_t) + MAC_ADDR_LEN); + buff = kalMemAlloc(u32BufSize, VIR_MEM_TYPE); + + if (buff == NULL) { + DBGLOG(NIC, ERROR, "Can't allocate TXD buffer.\n"); + return -1; + } + prNotifyInfo = (struct mddpw_drv_notify_info_t *) buff; + prNotifyInfo->version = 0; + prNotifyInfo->buf_len = sizeof(struct mddpw_drv_info_t) + + MAC_ADDR_LEN; + prNotifyInfo->info_num = 1; + prDrvInfo = (struct mddpw_drv_info_t *) &(prNotifyInfo->buf[0]); + prDrvInfo->info_id = MDDPW_DRV_INFO_DEVICE_MAC; + prDrvInfo->info_len = MAC_ADDR_LEN; + /*SY MCIF TBC 0916*/ + prAisBssInfo = prAdapter->prAisBssInfo[0]; + COPY_MAC_ADDR(prDrvInfo->info, prAisBssInfo->aucOwnMacAddr); + + ret = gMddpWFunc.notify_drv_info(prNotifyInfo); + DBGLOG(INIT, INFO, "ret: %d.\n", ret); + kalMemFree(buff, VIR_MEM_TYPE, u32BufSize); + } else { + DBGLOG(INIT, ERROR, "notify_drv_info is NULL.\n"); + } + + return 0; +} + +int32_t mddpNotifyWifiStatus(IN enum mddp_drv_onoff_status wifiOnOffStatus) +{ + struct mddpw_drv_notify_info_t *prNotifyInfo; + struct mddpw_drv_info_t *prDrvInfo; + uint32_t u32BufSize = 0; + uint8_t *buff = NULL; + int32_t ret = 0; + + if (gMddpWFunc.notify_drv_info) { + int32_t ret; + + u32BufSize = (sizeof(struct mddpw_drv_notify_info_t) + + sizeof(struct mddpw_drv_info_t) + sizeof(bool)); + buff = kalMemAlloc(u32BufSize, VIR_MEM_TYPE); + + if (buff == NULL) { + DBGLOG(NIC, ERROR, "Can't allocate buffer.\n"); + return -1; + } + prNotifyInfo = (struct mddpw_drv_notify_info_t *) buff; + prNotifyInfo->version = 0; + prNotifyInfo->buf_len = sizeof(struct mddpw_drv_info_t) + + sizeof(bool); + prNotifyInfo->info_num = 1; + prDrvInfo = (struct mddpw_drv_info_t *) &(prNotifyInfo->buf[0]); + prDrvInfo->info_id = MDDPW_DRV_INFO_NOTIFY_WIFI_ONOFF; + prDrvInfo->info_len = WIFI_ONOFF_NOTIFICATION_LEN; + prDrvInfo->info[0] = wifiOnOffStatus; + + ret = gMddpWFunc.notify_drv_info(prNotifyInfo); + DBGLOG(INIT, INFO, "power: %d, ret: %d.\n", + wifiOnOffStatus, ret); + kalMemFree(buff, VIR_MEM_TYPE, u32BufSize); + } else { + DBGLOG(INIT, ERROR, "notify_drv_info is NULL.\n"); + ret = -1; + } + + return ret; +} + +void mddpNotifyWifiOnStart(void) +{ + mddpRegisterCb(); + mddpNotifyWifiStatus(MDDPW_DRV_INFO_WLAN_ON_START); +} + +int32_t mddpNotifyWifiOnEnd(void) +{ + int32_t ret; + + clear_md_wifi_on_bit(); + ret = mddpNotifyWifiStatus(MDDPW_DRV_INFO_WLAN_ON_END); + if (ret == 0) + ret = wait_for_md_on_complete() ? + WLAN_STATUS_SUCCESS : + WLAN_STATUS_FAILURE; + return ret; +} + +void mddpNotifyWifiOffStart(void) +{ + int32_t ret; + + clear_md_wifi_off_bit(); + ret = mddpNotifyWifiStatus(MDDPW_DRV_INFO_WLAN_OFF_START); +} + +void mddpNotifyWifiOffEnd(void) +{ + mddpNotifyWifiStatus(MDDPW_DRV_INFO_WLAN_OFF_END); + mddpUnregisterCb(); +} + +int32_t mddpMdNotifyInfo(struct mddpw_md_notify_info_t *prMdInfo) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + u_int8_t fgHalted = kalIsHalted(); + + DBGLOG(INIT, INFO, "MD notify mddpMdNotifyInfo.\n"); + + if (gPrDev == NULL) { + DBGLOG(INIT, ERROR, "gPrDev is NULL.\n"); + return 0; + } + + prGlueInfo = *((struct GLUE_INFO **)netdev_priv(gPrDev)); + if (prGlueInfo == NULL) { + DBGLOG(INIT, ERROR, "prGlueInfo is NULL.\n"); + return 0; + } + prAdapter = prGlueInfo->prAdapter; + if (prAdapter == NULL) { + DBGLOG(INIT, ERROR, "prAdapter is NULL.\n"); + return 0; + } + + if (fgHalted || !prGlueInfo->u4ReadyFlag) { + DBGLOG(INIT, INFO, + "Skip update info. to MD, fgHalted: %d, u4ReadyFlag: %d\n", + fgHalted, prGlueInfo->u4ReadyFlag); + return 0; + } + + if (prMdInfo->info_type == 1) { + uint32_t i; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + int32_t ret; + + save_mddp_stats(); + mddpNotifyWifiOnStart(); + ret = mddpNotifyWifiOnEnd(); + if (ret != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "mddpNotifyWifiOnEnd failed.\n"); + return 0; + } + mddpNotifyDrvMac(prAdapter); + + /* Notify STA's TXD to MD */ + for (i = 0; i < KAL_AIS_NUM; i++) { + struct BSS_INFO *prAisBssInfo = aisGetAisBssInfo( + prAdapter, + i); + + if (prAisBssInfo && prAisBssInfo->eConnectionState == + MEDIA_STATE_CONNECTED) + mddpNotifyDrvTxd(prAdapter, + prAisBssInfo->prStaRecOfAP, + TRUE); + } + /* Notify SAP clients' TXD to MD */ + prP2pBssInfo = cnmGetSapBssInfo(prAdapter); + if (prP2pBssInfo) { + struct LINK *prClientList; + struct STA_RECORD *prCurrStaRec; + + prClientList = &prP2pBssInfo->rStaRecOfClientList; + LINK_FOR_EACH_ENTRY(prCurrStaRec, prClientList, + rLinkEntry, struct STA_RECORD) { + if (!prCurrStaRec) + break; + mddpNotifyDrvTxd(prAdapter, + prCurrStaRec, + TRUE); + } + } + } + return 0; +} + +#if CFG_MTK_MDDP_WH_SUPPORT +int32_t mddpChangeState(enum mddp_state_e event, void *buf, uint32_t *buf_len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + u_int8_t fgHalted = kalIsHalted(); + + if (gPrDev == NULL) { + DBGLOG(INIT, ERROR, "gPrDev is NULL.\n"); + return 0; + } + + prGlueInfo = *((struct GLUE_INFO **)netdev_priv(gPrDev)); + if (prGlueInfo == NULL) { + DBGLOG(INIT, ERROR, "prGlueInfo is NULL.\n"); + return 0; + } + + if (fgHalted || !prGlueInfo->u4ReadyFlag) { + DBGLOG(INIT, ERROR, "fgHalted: %d, u4ReadyFlag: %d\n", + fgHalted, prGlueInfo->u4ReadyFlag); + return 0; + } + + prAdapter = prGlueInfo->prAdapter; + if (prAdapter == NULL) { + DBGLOG(INIT, ERROR, "prAdapter is NULL.\n"); + return 0; + } + + switch (event) { + case MDDP_STATE_ENABLING: + break; + + case MDDP_STATE_ACTIVATING: + break; + + case MDDP_STATE_ACTIVATED: + DBGLOG(INIT, INFO, "Mddp activated.\n"); + prAdapter->fgMddpActivated = true; + break; + + case MDDP_STATE_DEACTIVATING: + break; + + case MDDP_STATE_DEACTIVATED: + DBGLOG(INIT, INFO, "Mddp deactivated.\n"); + prAdapter->fgMddpActivated = false; + break; + + case MDDP_STATE_DISABLING: + case MDDP_STATE_UNINIT: + case MDDP_STATE_CNT: + case MDDP_STATE_DUMMY: + default: + break; + } + + return 0; + +} +#endif + +static void clear_md_wifi_off_bit(void) +{ + uint32_t u4Value = 0; + + DBGLOG(INIT, INFO, "md off start.\n"); + wf_ioremap_read(MD_STATUS_SYNC_CR, &u4Value); + u4Value |= MD_STATUS_OFF_SYNC_BIT; + wf_ioremap_write(MD_STATUS_SYNC_CR, u4Value); +} + +static void clear_md_wifi_on_bit(void) +{ + uint32_t u4Value = 0; + + wf_ioremap_read(MD_STATUS_SYNC_CR, &u4Value); + u4Value &= ~MD_STATUS_ON_SYNC_BIT; + wf_ioremap_write(MD_STATUS_SYNC_CR, u4Value); +} + +static bool wait_for_md_on_complete(void) +{ + uint32_t u4Value = 0; + uint32_t u4StartTime, u4CurTime; + bool fgCompletion = false; + struct GLUE_INFO *prGlueInfo = NULL; + + u4StartTime = kalGetTimeTick(); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(gPrDev)); + if (!prGlueInfo) { + DBGLOG(INIT, ERROR, "prGlueInfo is NULL.\n"); + return false; + } + + do { + wf_ioremap_read(MD_STATUS_SYNC_CR, &u4Value); + + if ((u4Value & MD_STATUS_ON_SYNC_BIT) > 0) { + DBGLOG(INIT, INFO, "md on end.\n"); + fgCompletion = true; + break; + } else if (!prGlueInfo->u4ReadyFlag) { + DBGLOG(INIT, WARN, "Skip waiting due to ready flag.\n"); + fgCompletion = false; + break; + } + + u4CurTime = kalGetTimeTick(); + if (CHECK_FOR_TIMEOUT(u4CurTime, u4StartTime, + MD_ON_OFF_TIMEOUT)) { + DBGLOG(INIT, ERROR, "wait for md on timeout\n"); + fgCompletion = false; + break; + } + + kalMsleep(CFG_RESPONSE_POLLING_DELAY); + } while (TRUE); + + return fgCompletion; +} + +void setMddpSupportRegister(IN struct ADAPTER *prAdapter) +{ +#if (CFG_SUPPORT_CONNAC2X == 0) + uint32_t u4Val = 0; + + HAL_MCR_RD(prAdapter, MDDP_SUPPORT_CR, &u4Val); + if (g_fgMddpEnabled) + u4Val |= MDDP_SUPPORT_CR_BIT; + else + u4Val &= ~MDDP_SUPPORT_CR_BIT; + HAL_MCR_WR(prAdapter, MDDP_SUPPORT_CR, u4Val); +#endif +} + +void mddpInit(void) +{ + struct device_node *np_chosen; + struct tag_bootmode *tag = NULL; + + np_chosen = of_find_node_by_path("/chosen"); + if (!np_chosen) + np_chosen = of_find_node_by_path("/chosen@0"); + + if (!np_chosen) + return; + + tag = (struct tag_bootmode *) of_get_property(np_chosen, "atag,boot", + NULL); + + if (!tag) + return; + + DBGLOG(INIT, INFO, "bootmode: 0x%x\n", tag->bootmode); + g_boot_mode = tag->bootmode; +} + +static void save_mddp_stats(void) +{ + struct mddpw_net_stat_ext_t temp; + uint8_t i = 0; + int32_t ret; + + if (!gMddpWFunc.get_net_stat_ext) + return; + + ret = gMddpWFunc.get_net_stat_ext(&temp); + if (ret != 0) { + DBGLOG(INIT, ERROR, "get_net_stat fail, ret: %d.\n", ret); + return; + } + + for (i = 0; i < NW_IF_NUM_MAX; i++) { + struct mddpw_net_stat_elem_ext_t *element, *curr; + + element = &temp.ifs[0][i]; + curr = &stats.ifs[0][i]; + + curr->rx_packets += element->rx_packets; + curr->tx_packets += element->tx_packets; + curr->rx_bytes += element->rx_bytes; + curr->tx_bytes += element->tx_bytes; + curr->rx_errors += element->rx_errors; + curr->tx_errors += element->tx_errors; + curr->rx_dropped += element->rx_dropped; + curr->tx_dropped += element->tx_dropped; + } +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/mib.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/mib.c new file mode 100644 index 0000000000000..33e39063f03ca --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/mib.c @@ -0,0 +1,138 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + +/******************************************************************************* + * C O M P I L E 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 + ******************************************************************************* + */ +const struct NON_HT_PHY_ATTRIBUTE 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) */ +}; + +const struct NON_HT_ATTRIBUTE 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) */ +}; + +const struct NON_HT_ATTRIBUTE rNonHTApModeAttributes[AP_MODE_NUM] = { + {PHY_TYPE_HR_DSSS_INDEX, BASIC_RATE_SET_HR_DSSS} + , /* For AP_MODE_11B(0) */ + {PHY_TYPE_ERP_INDEX, BASIC_RATE_SET_HR_DSSS_ERP} + , /* For AP_MODE_MIXED_11BG(1) */ + {PHY_TYPE_ERP_INDEX, BASIC_RATE_SET_ERP} + , /* For AP_MODE_11G(2) */ + {PHY_TYPE_ERP_P2P_INDEX, BASIC_RATE_SET_ERP_P2P} + , /* For AP_MODE_11G_P2P(3) */ + {PHY_TYPE_OFDM_INDEX, BASIC_RATE_SET_OFDM} + , /* For AP_MODE_11A(4) */ +}; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_assoc.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_assoc.c new file mode 100644 index 0000000000000..861f971ae9eb7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_assoc.c @@ -0,0 +1,143 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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) + */ +/*----------------------------------------------------------------------------*/ +uint8_t *p2pBuildReAssocReqFrameCommonIEs(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN uint8_t *pucBuffer) +{ + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + + /* 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, + prP2pBssInfo->aucSSID, + prP2pBssInfo->ucSSIDLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + return pucBuffer; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_bss.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_bss.c new file mode 100644 index 0000000000000..e6a53df326de8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_bss.c @@ -0,0 +1,109 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: @(#) p2p_bss.c@@ + */ + +/*! \file "p2p_bss.c" + * \brief This file contains the functions for creating p2p BSS(AP). + * + * This file contains the functions for BSS(AP). We may create a BSS + * network, or merge with exist IBSS network and sending Beacon Frame or reply + * the Probe Response Frame for received Probe Request Frame. + */ + +/****************************************************************************** + * C O M P I L E R F L A G S + ****************************************************************************** + */ + +/****************************************************************************** + * E X T E R N A L R E F E R E N C E S + ****************************************************************************** + */ + +#include "precomp.h" + +/****************************************************************************** + * C O N S T A N T S + ****************************************************************************** + */ + +/****************************************************************************** + * D A T A T Y P E S + ****************************************************************************** + */ + +/****************************************************************************** + * P U B L I C D A T A + ****************************************************************************** + */ + +/****************************************************************************** + * P R I V A T E D A T A + ****************************************************************************** + */ + +/****************************************************************************** + * M A C R O S + ****************************************************************************** + */ + +/****************************************************************************** + * F U N C T I O N D E C L A R A T I O N S + ****************************************************************************** + */ + +/****************************************************************************** + * F U N C T I O N S + ****************************************************************************** + */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_dev_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_dev_fsm.c new file mode 100644 index 0000000000000..4debbb715dbce --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_dev_fsm.c @@ -0,0 +1,1446 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#include "precomp.h" +#include "p2p_dev_state.h" +#if CFG_ENABLE_WIFI_DIRECT + +#if 1 +/*lint -save -e64 Type mismatch */ +static uint8_t *apucDebugP2pDevState[P2P_DEV_STATE_NUM] = { + (uint8_t *) DISP_STRING("P2P_DEV_STATE_IDLE"), + (uint8_t *) DISP_STRING("P2P_DEV_STATE_SCAN"), + (uint8_t *) DISP_STRING("P2P_DEV_STATE_REQING_CHANNEL"), + (uint8_t *) DISP_STRING("P2P_DEV_STATE_CHNL_ON_HAND"), + (uint8_t *) DISP_STRING("P2P_DEV_STATE_OFF_CHNL_TX") +}; + +/*lint -restore */ +#endif /* DBG */ + +uint8_t p2pDevFsmInit(IN struct ADAPTER *prAdapter) +{ + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) NULL; + struct P2P_CHNL_REQ_INFO *prP2pChnlReqInfo = + (struct P2P_CHNL_REQ_INFO *) NULL; + struct P2P_MGMT_TX_REQ_INFO *prP2pMgmtTxReqInfo = + (struct P2P_MGMT_TX_REQ_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + ASSERT_BREAK(prP2pDevFsmInfo != NULL); + + kalMemZero(prP2pDevFsmInfo, sizeof(struct P2P_DEV_FSM_INFO)); + + prP2pDevFsmInfo->eCurrentState = P2P_DEV_STATE_IDLE; + + cnmTimerInitTimer(prAdapter, + &(prP2pDevFsmInfo->rP2pFsmTimeoutTimer), + (PFN_MGMT_TIMEOUT_FUNC) p2pDevFsmRunEventTimeout, + (unsigned long) prP2pDevFsmInfo); + + prP2pBssInfo = + cnmGetBssInfoAndInit(prAdapter, NETWORK_TYPE_P2P, TRUE); + + if (prP2pBssInfo != NULL) { + COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, + prAdapter->rWifiVar.aucDeviceAddress); + DBGLOG(INIT, INFO, "Set p2p dev mac to " MACSTR "\n", + MAC2STR(prP2pBssInfo->aucOwnMacAddr)); + + prP2pDevFsmInfo->ucBssIndex = prP2pBssInfo->ucBssIndex; + + prP2pBssInfo->eCurrentOPMode = OP_MODE_P2P_DEVICE; + prP2pBssInfo->ucConfigAdHocAPMode = AP_MODE_11G_P2P; + prP2pBssInfo->u2HwDefaultFixedRateCode = RATE_OFDM_6M; + + prP2pBssInfo->eBand = BAND_2G4; +#if (CFG_HW_WMM_BY_BSS == 1) + prP2pBssInfo->ucWmmQueSet = MAX_HW_WMM_INDEX; +#else + if (prAdapter->rWifiVar.eDbdcMode + == ENUM_DBDC_MODE_DISABLED) + prP2pBssInfo->ucWmmQueSet = DBDC_5G_WMM_INDEX; + else + prP2pBssInfo->ucWmmQueSet = DBDC_2G_WMM_INDEX; +#endif + +#if CFG_SUPPORT_VHT_IE_IN_2G + if (prAdapter->rWifiVar.ucVhtIeIn2g) + prP2pBssInfo->ucPhyTypeSet = + prAdapter->rWifiVar. + ucAvailablePhyTypeSet + & (PHY_TYPE_SET_802_11GN | + PHY_TYPE_SET_802_11AC); + else +#endif + prP2pBssInfo->ucPhyTypeSet = + prAdapter->rWifiVar. + ucAvailablePhyTypeSet + & PHY_TYPE_SET_802_11GN; + + prP2pBssInfo->ucNonHTBasicPhyType = (uint8_t) + rNonHTApModeAttributes + [prP2pBssInfo->ucConfigAdHocAPMode] + .ePhyTypeIndex; + + prP2pBssInfo->u2BSSBasicRateSet = + rNonHTApModeAttributes + [prP2pBssInfo->ucConfigAdHocAPMode] + .u2BSSBasicRateSet; + + prP2pBssInfo->u2OperationalRateSet = + rNonHTPhyAttributes + [prP2pBssInfo->ucNonHTBasicPhyType] + .u2SupportedRateSet; + + prP2pBssInfo->u4PrivateData = 0;/* TH3 Huang */ + + rateGetDataRatesFromRateSet( + prP2pBssInfo->u2OperationalRateSet, + prP2pBssInfo->u2BSSBasicRateSet, + prP2pBssInfo->aucAllSupportedRates, + &prP2pBssInfo->ucAllSupportedRatesLen); + } + prP2pChnlReqInfo = &prP2pDevFsmInfo->rChnlReqInfo; + LINK_INITIALIZE(&prP2pChnlReqInfo->rP2pChnlReqLink); + + prP2pMgmtTxReqInfo = &prP2pDevFsmInfo->rMgmtTxInfo; + LINK_INITIALIZE(&prP2pMgmtTxReqInfo->rTxReqLink); + + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, + P2P_DEV_STATE_IDLE); + } while (FALSE); + + if (prP2pBssInfo) + return prP2pBssInfo->ucBssIndex; + else + return prAdapter->ucP2PDevBssIdx + 1; + +#if 0 + 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)); + + prP2pFsmInfo->eCurrentState = + prP2pFsmInfo->ePreviousState = P2P_STATE_IDLE; + + prP2pFsmInfo->prTargetBss = NULL; + + cnmTimerInitTimer(prAdapter, + &(prP2pFsmInfo->rP2pFsmTimeoutTimer), + (PFN_MGMT_TIMEOUT_FUNC) p2pFsmRunEventFsmTimeout, + (unsigned long) 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 = (uint8_t) + 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(struct WLAN_BEACON_FRAME, aucInfoElem[0]) + + MAX_IE_LENGTH); + + if (prP2pBssInfo->prBeacon) { + prP2pBssInfo->prBeacon->eSrc = TX_PACKET_MGMT; + /* NULL STA_REC */ + prP2pBssInfo->prBeacon->ucStaRecIndex = 0xFF; + 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 (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) + 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; +#endif +} /* p2pDevFsmInit */ + +void p2pDevFsmUninit(IN struct ADAPTER *prAdapter) +{ + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + ASSERT_BREAK(prP2pDevFsmInfo != NULL); + + prP2pBssInfo = + prAdapter->aprBssInfo[prP2pDevFsmInfo->ucBssIndex]; + + cnmTimerStopTimer(prAdapter, + &(prP2pDevFsmInfo->rP2pFsmTimeoutTimer)); + + p2pFunCleanQueuedMgmtFrame(prAdapter, + &prP2pDevFsmInfo->rQueuedActionFrame); + + p2pFunClearAllTxReq(prAdapter, &(prP2pDevFsmInfo->rMgmtTxInfo)); + + /* Abort device FSM */ + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, + P2P_DEV_STATE_IDLE); + p2pDevFsmRunEventAbort(prAdapter, prP2pDevFsmInfo); + + SET_NET_PWR_STATE_IDLE(prAdapter, prP2pBssInfo->ucBssIndex); + + /* Clear CmdQue */ + kalClearMgmtFramesByBssIdx(prAdapter->prGlueInfo, + prP2pBssInfo->ucBssIndex); + kalClearSecurityFramesByBssIdx(prAdapter->prGlueInfo, + prP2pBssInfo->ucBssIndex); + /* Clear PendingCmdQue */ + wlanReleasePendingCMDbyBssIdx(prAdapter, + prP2pBssInfo->ucBssIndex); + /* Clear PendingTxMsdu */ + nicFreePendingTxMsduInfo(prAdapter, + prP2pBssInfo->ucBssIndex, MSDU_REMOVE_BY_BSS_INDEX); + + /* Deactivate BSS. */ + UNSET_NET_ACTIVE(prAdapter, prP2pBssInfo->ucBssIndex); + + nicDeactivateNetwork(prAdapter, prP2pBssInfo->ucBssIndex); + + cnmFreeBssInfo(prAdapter, prP2pBssInfo); + } while (FALSE); + +#if 0 + struct P2P_FSM_INFO *prP2pFsmInfo = (struct P2P_FSM_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) 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. + */ + kalClearMgmtFramesByBssIdx(prAdapter->prGlueInfo, + NETWORK_TYPE_P2P_INDEX); + + /* Clear PendingCmdQue */ + wlanReleasePendingCMDbyBssIdx(prAdapter, + NETWORK_TYPE_P2P_INDEX); + + if (prP2pBssInfo->prBeacon) { + cnmMgtPktFree(prAdapter, prP2pBssInfo->prBeacon); + prP2pBssInfo->prBeacon = NULL; + } + } while (FALSE); + + return; +#endif +} /* p2pDevFsmUninit */ + +void +p2pDevFsmStateTransition(IN struct ADAPTER *prAdapter, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo, + IN enum ENUM_P2P_DEV_STATE eNextState) +{ + u_int8_t fgIsLeaveState = (u_int8_t) FALSE; + + ASSERT(prP2pDevFsmInfo); + if (!prP2pDevFsmInfo) { + DBGLOG(P2P, ERROR, "prP2pDevFsmInfo is NULL!\n"); + return; + } + + ASSERT(prP2pDevFsmInfo->ucBssIndex == prAdapter->ucP2PDevBssIdx); + if (prP2pDevFsmInfo->ucBssIndex != prAdapter->ucP2PDevBssIdx) { + log_dbg(P2P, ERROR, + "prP2pDevFsmInfo->ucBssIndex %d should be prAdapter->ucP2PDevBssIdx(%d)!\n", + prP2pDevFsmInfo->ucBssIndex, prAdapter->ucP2PDevBssIdx); + return; + } + + do { + if (!IS_BSS_ACTIVE( + prAdapter->aprBssInfo[prP2pDevFsmInfo->ucBssIndex])) { + if (!cnmP2PIsPermitted(prAdapter)) + return; + + SET_NET_ACTIVE(prAdapter, prP2pDevFsmInfo->ucBssIndex); + nicActivateNetwork(prAdapter, + prP2pDevFsmInfo->ucBssIndex); + } + + fgIsLeaveState = fgIsLeaveState ? FALSE : TRUE; + + if (!fgIsLeaveState) { + /* Print log with state changed */ + if (prP2pDevFsmInfo->eCurrentState != eNextState) + DBGLOG(P2P, STATE, + "[P2P_DEV]TRANSITION: [%s] -> [%s]\n", + apucDebugP2pDevState + [prP2pDevFsmInfo->eCurrentState], + apucDebugP2pDevState[eNextState]); + + /* Transition into current state. */ + prP2pDevFsmInfo->eCurrentState = eNextState; + } + + switch (prP2pDevFsmInfo->eCurrentState) { + case P2P_DEV_STATE_IDLE: + if (!fgIsLeaveState) { + fgIsLeaveState = p2pDevStateInit_IDLE(prAdapter, + &prP2pDevFsmInfo->rChnlReqInfo, + &eNextState); + } else { + p2pDevStateAbort_IDLE(prAdapter); + } + break; + case P2P_DEV_STATE_SCAN: + if (!fgIsLeaveState) { + p2pDevStateInit_SCAN(prAdapter, + prP2pDevFsmInfo->ucBssIndex, + &prP2pDevFsmInfo->rScanReqInfo); + } else { + p2pDevStateAbort_SCAN(prAdapter, + prP2pDevFsmInfo); + } + break; + case P2P_DEV_STATE_REQING_CHANNEL: + if (!fgIsLeaveState) { + fgIsLeaveState = p2pDevStateInit_REQING_CHANNEL( + prAdapter, + prP2pDevFsmInfo->ucBssIndex, + &(prP2pDevFsmInfo->rChnlReqInfo), + &eNextState); + } else { + p2pDevStateAbort_REQING_CHANNEL(prAdapter, + &(prP2pDevFsmInfo->rChnlReqInfo), + eNextState); + } + break; + case P2P_DEV_STATE_CHNL_ON_HAND: + if (!fgIsLeaveState) { + p2pDevStateInit_CHNL_ON_HAND(prAdapter, + prAdapter->aprBssInfo + [prP2pDevFsmInfo->ucBssIndex], + prP2pDevFsmInfo, + &(prP2pDevFsmInfo->rChnlReqInfo)); + } else { + p2pDevStateAbort_CHNL_ON_HAND(prAdapter, + prAdapter->aprBssInfo + [prP2pDevFsmInfo->ucBssIndex], + prP2pDevFsmInfo, + &(prP2pDevFsmInfo->rChnlReqInfo), + eNextState); + } + break; + case P2P_DEV_STATE_OFF_CHNL_TX: + if (!fgIsLeaveState) { + fgIsLeaveState = p2pDevStateInit_OFF_CHNL_TX( + prAdapter, + prP2pDevFsmInfo, + &(prP2pDevFsmInfo->rChnlReqInfo), + &(prP2pDevFsmInfo->rMgmtTxInfo), + &eNextState); + } else { + p2pDevStateAbort_OFF_CHNL_TX( + prAdapter, + prP2pDevFsmInfo, + &(prP2pDevFsmInfo->rMgmtTxInfo), + &(prP2pDevFsmInfo->rChnlReqInfo), + eNextState); + } + break; + default: + /* Unexpected state. */ + ASSERT(FALSE); + break; + } + } while (fgIsLeaveState); +} /* p2pDevFsmStateTransition */ + +void p2pDevFsmRunEventAbort(IN struct ADAPTER *prAdapter, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo) +{ + do { + ASSERT_BREAK((prAdapter != NULL) + && (prP2pDevFsmInfo != NULL)); + + if (prP2pDevFsmInfo->eCurrentState != P2P_DEV_STATE_IDLE) { + /* Get into IDLE state. */ + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, + P2P_DEV_STATE_IDLE); + } + + /* Abort IDLE. */ + p2pDevStateAbort_IDLE(prAdapter); + } while (FALSE); +} /* p2pDevFsmRunEventAbort */ + +void p2pDevFsmRunEventTimeout(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr) +{ + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) ulParamPtr; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pDevFsmInfo != NULL)); + + switch (prP2pDevFsmInfo->eCurrentState) { + case P2P_DEV_STATE_IDLE: + /* TODO: IDLE timeout for low power mode. */ + break; + case P2P_DEV_STATE_CHNL_ON_HAND: + if (prAdapter->prP2pInfo->ucExtendChanFlag) { + prAdapter->prP2pInfo->ucExtendChanFlag = 0; + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, P2P_DEV_STATE_IDLE); + break; + } + if (p2pFuncNeedWaitRsp(prAdapter, + prAdapter->prP2pInfo->eConnState)) { + DBGLOG(P2P, INFO, + "P2P: re-enter CHNL_ON_HAND with state: %d\n", + prAdapter->prP2pInfo->eConnState); + prAdapter->prP2pInfo->ucExtendChanFlag = 1; + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, + P2P_DEV_STATE_CHNL_ON_HAND); + } else { + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, + P2P_DEV_STATE_IDLE); + } + break; + case P2P_DEV_STATE_OFF_CHNL_TX: + p2pDevFsmStateTransition(prAdapter, prP2pDevFsmInfo, + P2P_DEV_STATE_OFF_CHNL_TX); + break; + default: + ASSERT(FALSE); + log_dbg(P2P, ERROR, + "Current P2P Dev State %d is unexpected for FSM timeout event.\n", + prP2pDevFsmInfo->eCurrentState); + break; + } + } while (FALSE); +} /* p2pDevFsmRunEventTimeout */ + +/*================ Message Event =================*/ +void p2pDevFsmRunEventScanRequest(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_P2P_SCAN_REQUEST *prP2pScanReqMsg = + (struct MSG_P2P_SCAN_REQUEST *) NULL; + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) NULL; + struct P2P_SCAN_REQ_INFO *prScanReqInfo = + (struct P2P_SCAN_REQ_INFO *) NULL; + uint32_t u4ChnlListSize = 0; + struct P2P_SSID_STRUCT *prP2pSsidStruct = + (struct P2P_SSID_STRUCT *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + if (prP2pDevFsmInfo == NULL) + break; + + if (prP2pDevFsmInfo->eCurrentState != P2P_DEV_STATE_IDLE) + p2pDevFsmRunEventAbort(prAdapter, prP2pDevFsmInfo); + + prP2pScanReqMsg = (struct MSG_P2P_SCAN_REQUEST *) prMsgHdr; + prScanReqInfo = &(prP2pDevFsmInfo->rScanReqInfo); + + DBGLOG(P2P, TRACE, "p2pDevFsmRunEventScanRequest\n"); + + /* Do we need to be in IDLE state? */ + /* p2pDevFsmRunEventAbort(prAdapter, prP2pDevFsmInfo); */ + + ASSERT(prScanReqInfo->fgIsScanRequest == FALSE); + + prScanReqInfo->fgIsAbort = TRUE; + prScanReqInfo->eScanType = prP2pScanReqMsg->eScanType; + prScanReqInfo->u2PassiveDewellTime = 0; + + if (prP2pScanReqMsg->u4NumChannel) { + 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(struct RF_CHANNEL_INFO) + * prScanReqInfo->ucNumChannelList; + kalMemCopy(prScanReqInfo->arScanChannelList, + prP2pScanReqMsg->arChannelListInfo, + u4ChnlListSize); + } else { + /* If channel number is ZERO. + * It means do a FULL channel scan. + */ + prScanReqInfo->eChannelSet = SCAN_CHANNEL_FULL; + } + + /* SSID */ + prP2pSsidStruct = prP2pScanReqMsg->prSSID; + for (prScanReqInfo->ucSsidNum = 0; + prScanReqInfo->ucSsidNum + < prP2pScanReqMsg->i4SsidNum; + prScanReqInfo->ucSsidNum++) { + kalMemCopy( + prScanReqInfo->arSsidStruct + [prScanReqInfo->ucSsidNum].aucSsid, + prP2pSsidStruct->aucSsid, + prP2pSsidStruct->ucSsidLen); + + prScanReqInfo->arSsidStruct + [prScanReqInfo->ucSsidNum].ucSsidLen = + prP2pSsidStruct->ucSsidLen; + + prP2pSsidStruct++; + } + + /* IE Buffer */ + kalMemCopy(prScanReqInfo->aucIEBuf, + prP2pScanReqMsg->pucIEBuf, + prP2pScanReqMsg->u4IELen); + + prScanReqInfo->u4BufLength = prP2pScanReqMsg->u4IELen; + + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, + P2P_DEV_STATE_SCAN); + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventScanRequest */ + +void p2pDevFsmRunEventScanAbort(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) NULL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + DBGLOG(P2P, TRACE, "p2pDevFsmRunEventScanAbort\n"); + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + if (prP2pDevFsmInfo->eCurrentState == P2P_DEV_STATE_SCAN) { + struct P2P_SCAN_REQ_INFO *prScanReqInfo = + &(prP2pDevFsmInfo->rScanReqInfo); + + prScanReqInfo->fgIsAbort = TRUE; + + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, + P2P_DEV_STATE_IDLE); + } + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pDevFsmRunEventScanAbort */ + +void +p2pDevFsmRunEventScanDone(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo) +{ + struct MSG_SCN_SCAN_DONE *prScanDoneMsg = + (struct MSG_SCN_SCAN_DONE *) prMsgHdr; + struct P2P_SCAN_REQ_INFO *prP2pScanReqInfo = + (struct P2P_SCAN_REQ_INFO *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prMsgHdr != NULL) + && (prP2pDevFsmInfo != NULL)); + + if (!prP2pDevFsmInfo) { + DBGLOG(P2P, ERROR, + "prP2pDevFsmInfo is null, maybe remove p2p already\n"); + break; + } + + prP2pScanReqInfo = &(prP2pDevFsmInfo->rScanReqInfo); + + if (prScanDoneMsg->ucSeqNum + != prP2pScanReqInfo->ucSeqNumOfScnMsg) { + DBGLOG(P2P, TRACE, + "P2P Scan Done SeqNum:%d <-> P2P Dev FSM Scan SeqNum:%d", + prScanDoneMsg->ucSeqNum, + prP2pScanReqInfo->ucSeqNumOfScnMsg); + break; + } + + ASSERT_BREAK(prScanDoneMsg->ucBssIndex + == prP2pDevFsmInfo->ucBssIndex); + + prP2pScanReqInfo->fgIsAbort = FALSE; + prP2pScanReqInfo->fgIsScanRequest = FALSE; + + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, + P2P_DEV_STATE_IDLE); + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventScanDone */ + +void p2pDevFsmRunEventChannelRequest(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) NULL; + struct P2P_CHNL_REQ_INFO *prChnlReqInfo = + (struct P2P_CHNL_REQ_INFO *) NULL; + u_int8_t fgIsChnlFound = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + if (prP2pDevFsmInfo == NULL) { + DBGLOG(P2P, WARN, "uninitialized p2p Dev fsm\n"); + break; + } + + prChnlReqInfo = &(prP2pDevFsmInfo->rChnlReqInfo); + + DBGLOG(P2P, TRACE, "p2pDevFsmRunEventChannelRequest\n"); + + /* printk( + * "p2pDevFsmRunEventChannelRequest check cookie =%lld\n", + * prChnlReqInfo->u8Cookie); + */ + + if (!LINK_IS_EMPTY(&prChnlReqInfo->rP2pChnlReqLink)) { + struct LINK_ENTRY *prLinkEntry = + (struct LINK_ENTRY *) NULL; + struct MSG_P2P_CHNL_REQUEST *prP2pMsgChnlReq = + (struct MSG_P2P_CHNL_REQUEST *) NULL; + + LINK_FOR_EACH(prLinkEntry, + &prChnlReqInfo->rP2pChnlReqLink) { + + prP2pMsgChnlReq = + (struct MSG_P2P_CHNL_REQUEST *) + LINK_ENTRY(prLinkEntry, + struct MSG_HDR, rLinkEntry); + + if (prP2pMsgChnlReq->eChnlReqType + == CH_REQ_TYPE_ROC) { + LINK_REMOVE_KNOWN_ENTRY( + &prChnlReqInfo->rP2pChnlReqLink, + prLinkEntry); + cnmMemFree(prAdapter, prP2pMsgChnlReq); + /* DBGLOG(P2P, TRACE, */ + /* ("p2pDevFsmRunEventChannelAbort: + * Channel Abort, cookie found:%d\n", + */ + /* prChnlAbortMsg->u8Cookie)); */ + fgIsChnlFound = TRUE; + break; + } + } + } + + /* Queue the channel request. */ + LINK_INSERT_TAIL(&(prChnlReqInfo->rP2pChnlReqLink), + &(prMsgHdr->rLinkEntry)); + prMsgHdr = NULL; + + /* If channel is not requested, + * it may due to channel is released. + */ + if ((!fgIsChnlFound) + && (prChnlReqInfo->eChnlReqType + == CH_REQ_TYPE_ROC) + && (prChnlReqInfo->fgIsChannelRequested)) { + + ASSERT( + (prP2pDevFsmInfo->eCurrentState + == P2P_DEV_STATE_REQING_CHANNEL) || + (prP2pDevFsmInfo->eCurrentState + == P2P_DEV_STATE_CHNL_ON_HAND)); + + p2pDevFsmRunEventAbort(prAdapter, prP2pDevFsmInfo); + + break; + } + + if (prP2pDevFsmInfo->eCurrentState == P2P_DEV_STATE_IDLE) { + /* Re-enter IDLE state would trigger channel request. */ + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, P2P_DEV_STATE_IDLE); + } + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventChannelRequest */ + +void p2pDevFsmRunEventChannelAbort(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) NULL; + struct MSG_P2P_CHNL_ABORT *prChnlAbortMsg = + (struct MSG_P2P_CHNL_ABORT *) NULL; + struct P2P_CHNL_REQ_INFO *prChnlReqInfo = + (struct P2P_CHNL_REQ_INFO *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prChnlAbortMsg = (struct MSG_P2P_CHNL_ABORT *) prMsgHdr; + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + if (prP2pDevFsmInfo == NULL) + break; + + prChnlReqInfo = &(prP2pDevFsmInfo->rChnlReqInfo); + + DBGLOG(P2P, TRACE, "p2pDevFsmRunEventChannelAbort\n"); + + p2pFunCleanQueuedMgmtFrame(prAdapter, + &prP2pDevFsmInfo->rQueuedActionFrame); + + /* If channel is not requested, + * it may due to channel is released. + */ + if ((prChnlAbortMsg->u8Cookie == prChnlReqInfo->u8Cookie) + && (prChnlReqInfo->fgIsChannelRequested) && + prChnlReqInfo->eChnlReqType == CH_REQ_TYPE_ROC) { + ASSERT( + (prP2pDevFsmInfo->eCurrentState + == P2P_DEV_STATE_REQING_CHANNEL) || + (prP2pDevFsmInfo->eCurrentState + == P2P_DEV_STATE_CHNL_ON_HAND)); + + /* + * If cancel-roc cmd is called from Supplicant + * while driver is waiting for FW's channel grant event, + * roc event must be returned to Supplicant + * first to reset Supplicant's variables + * and then transition to idle state. + */ + if (prP2pDevFsmInfo->eCurrentState + == P2P_DEV_STATE_REQING_CHANNEL) { + kalP2PIndicateChannelReady( + prAdapter->prGlueInfo, + prChnlReqInfo->u8Cookie, + prChnlReqInfo->ucReqChnlNum, + prChnlReqInfo->eBand, + prChnlReqInfo->eChnlSco, + prChnlReqInfo->u4MaxInterval); + kalP2PIndicateChannelExpired( + prAdapter->prGlueInfo, + prChnlReqInfo->u8Cookie, + prChnlReqInfo->ucReqChnlNum, + prChnlReqInfo->eBand, + prChnlReqInfo->eChnlSco); + } + p2pDevFsmRunEventAbort(prAdapter, prP2pDevFsmInfo); + + break; + } else if (!LINK_IS_EMPTY(&prChnlReqInfo->rP2pChnlReqLink)) { + struct LINK_ENTRY *prLinkEntry = + (struct LINK_ENTRY *) NULL; + struct MSG_P2P_CHNL_REQUEST *prP2pMsgChnlReq = + (struct MSG_P2P_CHNL_REQUEST *) NULL; + + LINK_FOR_EACH(prLinkEntry, + &prChnlReqInfo->rP2pChnlReqLink) { + prP2pMsgChnlReq = + (struct MSG_P2P_CHNL_REQUEST *) + LINK_ENTRY(prLinkEntry, + struct MSG_HDR, rLinkEntry); + + if (prP2pMsgChnlReq->u8Cookie + == prChnlAbortMsg->u8Cookie) { + LINK_REMOVE_KNOWN_ENTRY( + &prChnlReqInfo->rP2pChnlReqLink, + prLinkEntry); + log_dbg(P2P, TRACE, + "p2pDevFsmRunEventChannelAbort: Channel Abort, cookie found:0x%llx\n", + prChnlAbortMsg->u8Cookie); + kalP2PIndicateChannelReady( + prAdapter->prGlueInfo, + prP2pMsgChnlReq->u8Cookie, + prP2pMsgChnlReq->rChannelInfo + .ucChannelNum, + prP2pMsgChnlReq->rChannelInfo + .eBand, + prP2pMsgChnlReq->eChnlSco, + prP2pMsgChnlReq->u4Duration); + kalP2PIndicateChannelExpired( + prAdapter->prGlueInfo, + prP2pMsgChnlReq->u8Cookie, + prP2pMsgChnlReq->rChannelInfo + .ucChannelNum, + prP2pMsgChnlReq->rChannelInfo + .eBand, + prP2pMsgChnlReq->eChnlSco); + cnmMemFree(prAdapter, prP2pMsgChnlReq); + break; + } + } + } else { + log_dbg(P2P, WARN, + "p2pDevFsmRunEventChannelAbort: Channel Abort Fail, cookie not found:0x%llx\n", + prChnlAbortMsg->u8Cookie); + } + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventChannelAbort */ + +void +p2pDevFsmRunEventChnlGrant(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo) +{ + struct MSG_CH_GRANT *prMsgChGrant = (struct MSG_CH_GRANT *) NULL; + struct P2P_CHNL_REQ_INFO *prChnlReqInfo = + (struct P2P_CHNL_REQ_INFO *) NULL; + + do { + ASSERT((prAdapter != NULL) + && (prMsgHdr != NULL) + && (prP2pDevFsmInfo != NULL)); + + if ((prAdapter == NULL) + || (prMsgHdr == NULL) + || (prP2pDevFsmInfo == NULL)) + break; + + prMsgChGrant = (struct MSG_CH_GRANT *) prMsgHdr; + prChnlReqInfo = &(prP2pDevFsmInfo->rChnlReqInfo); + + if ((prMsgChGrant->ucTokenID + != prChnlReqInfo->ucSeqNumOfChReq) + || (!prChnlReqInfo->fgIsChannelRequested)) { + break; + } + + ASSERT(prMsgChGrant->ucPrimaryChannel + == prChnlReqInfo->ucReqChnlNum); + ASSERT(prMsgChGrant->eReqType + == prChnlReqInfo->eChnlReqType); + ASSERT(prMsgChGrant->u4GrantInterval + == prChnlReqInfo->u4MaxInterval); + + prChnlReqInfo->u4MaxInterval = prMsgChGrant->u4GrantInterval; + + if (prMsgChGrant->eReqType == CH_REQ_TYPE_ROC) { + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, + P2P_DEV_STATE_CHNL_ON_HAND); + } else { + ASSERT(prMsgChGrant->eReqType + == CH_REQ_TYPE_OFFCHNL_TX); + + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, + P2P_DEV_STATE_OFF_CHNL_TX); + } + } while (FALSE); + + if (prAdapter && prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventChnlGrant */ + +static u_int8_t +p2pDevChnlReqByOffChnl(IN struct ADAPTER *prAdapter, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo, + IN struct P2P_OFF_CHNL_TX_REQ_INFO *prOffChnlTxReq) +{ + struct MSG_P2P_CHNL_REQUEST *prMsgChnlReq = + (struct MSG_P2P_CHNL_REQUEST *) NULL; + + if (prAdapter == NULL || prP2pDevFsmInfo == NULL || + prOffChnlTxReq == NULL) + return FALSE; + + prMsgChnlReq = cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_P2P_CHNL_REQUEST)); + + if (prMsgChnlReq == NULL) { + DBGLOG(P2P, ERROR, + "Not enough MSG buffer for chnl request.\n"); + return FALSE; + } + + prMsgChnlReq->eChnlReqType = CH_REQ_TYPE_OFFCHNL_TX; + prMsgChnlReq->rMsgHdr.eMsgId = MID_MNY_P2P_CHNL_REQ; + prMsgChnlReq->u8Cookie = prOffChnlTxReq->u8Cookie; + prMsgChnlReq->u4Duration = prOffChnlTxReq->u4Duration; + kalMemCopy(&prMsgChnlReq->rChannelInfo, + &prOffChnlTxReq->rChannelInfo, + sizeof(struct RF_CHANNEL_INFO)); + prMsgChnlReq->eChnlSco = prOffChnlTxReq->eChnlExt; + p2pDevFsmRunEventChannelRequest(prAdapter, + (struct MSG_HDR *) prMsgChnlReq); + + return TRUE; +} /* p2pDevChnlReqByOffChnl */ + +static void +p2pDevAbortChlReqIfNeed(IN struct ADAPTER *prAdapter, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo) +{ + struct MSG_P2P_CHNL_ABORT *prMsgChnlAbort = + (struct MSG_P2P_CHNL_ABORT *) NULL; + + if (prAdapter == NULL || prChnlReqInfo == NULL || + prP2pDevFsmInfo == NULL) + return; + + /* Cancel ongoing channel request whose type is not offchannel-tx*/ + if (prP2pDevFsmInfo->eCurrentState != P2P_DEV_STATE_REQING_CHANNEL || + prChnlReqInfo->eChnlReqType == CH_REQ_TYPE_OFFCHNL_TX) + return; + + prMsgChnlAbort = cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(struct MSG_P2P_CHNL_ABORT)); + + if (prMsgChnlAbort == NULL) { + DBGLOG(P2P, ERROR, "Memory allocate failed.\n"); + return; + } + + prMsgChnlAbort->u8Cookie = prChnlReqInfo->u8Cookie; + p2pDevFsmRunEventChannelAbort(prAdapter, + (struct MSG_HDR *) prMsgChnlAbort); +} + +static void +p2pDevAdjustChnlTime(IN struct MSG_MGMT_TX_REQUEST *prMgmtTxMsg, + IN struct P2P_OFF_CHNL_TX_REQ_INFO *prOffChnlTxReq) +{ + enum ENUM_P2P_CONNECT_STATE eP2pActionFrameType = P2P_CNN_NORMAL; + uint32_t u4ExtendedTime = 0; + + if (prMgmtTxMsg == NULL || prOffChnlTxReq == NULL) + return; + + if (!prMgmtTxMsg->fgIsOffChannel) + return; + + if (prMgmtTxMsg->u4Duration < MIN_TX_DURATION_TIME_MS) { + /* + * The wait time requested from Supplicant may be too short + * to TX a frame, eg. nego.conf.. Overwrite the wait time + * as driver's min TX time. + */ + DBGLOG(P2P, INFO, "Overwrite channel duration from %d to %d\n", + prMgmtTxMsg->u4Duration, + MIN_TX_DURATION_TIME_MS); + prOffChnlTxReq->u4Duration = MIN_TX_DURATION_TIME_MS; + } else { + prOffChnlTxReq->u4Duration = prMgmtTxMsg->u4Duration; + } + + eP2pActionFrameType = p2pFuncGetP2pActionFrameType( + prMgmtTxMsg->prMgmtMsduInfo); + switch (eP2pActionFrameType) { + case P2P_CNN_GO_NEG_RESP: + u4ExtendedTime = P2P_DEV_EXTEND_CHAN_TIME; + break; + default: + break; + } + + if (u4ExtendedTime) { + DBGLOG(P2P, INFO, "Extended channel duration from %d to %d\n", + prOffChnlTxReq->u4Duration, + prOffChnlTxReq->u4Duration + u4ExtendedTime); + prOffChnlTxReq->u4Duration += u4ExtendedTime; + } +} /* p2pDevAdjustChnlTime */ + +static u_int8_t +p2pDevAddTxReq2Queue(IN struct ADAPTER *prAdapter, + IN struct P2P_MGMT_TX_REQ_INFO *prP2pMgmtTxReqInfo, + IN struct MSG_MGMT_TX_REQUEST *prMgmtTxMsg, + OUT struct P2P_OFF_CHNL_TX_REQ_INFO **pprOffChnlTxReq) +{ + struct P2P_OFF_CHNL_TX_REQ_INFO *prTmpOffChnlTxReq = + (struct P2P_OFF_CHNL_TX_REQ_INFO *) NULL; + + prTmpOffChnlTxReq = cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(struct P2P_OFF_CHNL_TX_REQ_INFO)); + + if (prTmpOffChnlTxReq == NULL) { + DBGLOG(P2P, ERROR, + "Allocate TX request buffer fails.\n"); + return FALSE; + } + + prTmpOffChnlTxReq->ucBssIndex = prMgmtTxMsg->ucBssIdx; + prTmpOffChnlTxReq->u8Cookie = prMgmtTxMsg->u8Cookie; + prTmpOffChnlTxReq->prMgmtTxMsdu = prMgmtTxMsg->prMgmtMsduInfo; + prTmpOffChnlTxReq->fgNoneCckRate = prMgmtTxMsg->fgNoneCckRate; + kalMemCopy(&prTmpOffChnlTxReq->rChannelInfo, + &prMgmtTxMsg->rChannelInfo, + sizeof(struct RF_CHANNEL_INFO)); + prTmpOffChnlTxReq->eChnlExt = prMgmtTxMsg->eChnlExt; + prTmpOffChnlTxReq->fgIsWaitRsp = prMgmtTxMsg->fgIsWaitRsp; + + p2pDevAdjustChnlTime(prMgmtTxMsg, prTmpOffChnlTxReq); + + LINK_INSERT_TAIL(&prP2pMgmtTxReqInfo->rTxReqLink, + &prTmpOffChnlTxReq->rLinkEntry); + + *pprOffChnlTxReq = prTmpOffChnlTxReq; + + return TRUE; +} + +static void +p2pDevHandleOffchnlTxReq(IN struct ADAPTER *prAdapter, + IN struct MSG_MGMT_TX_REQUEST *prMgmtTxMsg) +{ + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) NULL; + struct P2P_MGMT_TX_REQ_INFO *prP2pMgmtTxReqInfo = + (struct P2P_MGMT_TX_REQ_INFO *) NULL; + struct P2P_OFF_CHNL_TX_REQ_INFO *prOffChnlTxReq = + (struct P2P_OFF_CHNL_TX_REQ_INFO *) NULL; + struct P2P_CHNL_REQ_INFO *prChnlReqInfo = + (struct P2P_CHNL_REQ_INFO *) NULL; + + if (prAdapter == NULL || prMgmtTxMsg == NULL) + return; + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + if (prP2pDevFsmInfo == NULL) + return; + + prP2pMgmtTxReqInfo = &(prP2pDevFsmInfo->rMgmtTxInfo); + prChnlReqInfo = &(prP2pDevFsmInfo->rChnlReqInfo); + + if (prP2pMgmtTxReqInfo == NULL || prChnlReqInfo == NULL) + return; + + p2pDevAbortChlReqIfNeed(prAdapter, prP2pDevFsmInfo, prChnlReqInfo); + + if (p2pDevAddTxReq2Queue(prAdapter, prP2pMgmtTxReqInfo, + prMgmtTxMsg, &prOffChnlTxReq) == FALSE) + goto error; + + if (prOffChnlTxReq == NULL) + return; + + switch (prP2pDevFsmInfo->eCurrentState) { + case P2P_DEV_STATE_IDLE: + if (!p2pDevChnlReqByOffChnl(prAdapter, prP2pDevFsmInfo, + prOffChnlTxReq)) + goto error; + break; + case P2P_DEV_STATE_REQING_CHANNEL: + if (prChnlReqInfo->eChnlReqType != CH_REQ_TYPE_OFFCHNL_TX) { + DBGLOG(P2P, WARN, + "channel already requested by others\n"); + goto error; + } + break; + case P2P_DEV_STATE_OFF_CHNL_TX: + if (p2pFuncCheckOnRocChnl(&(prMgmtTxMsg->rChannelInfo), + prChnlReqInfo) && + prP2pMgmtTxReqInfo->rTxReqLink.u4NumElem <= 1) { + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, + P2P_DEV_STATE_OFF_CHNL_TX); + } else { + log_dbg(P2P, INFO, "tx ch: %d, current ch: %d, isRequested: %d, tx link num: %d", + prMgmtTxMsg->rChannelInfo.ucChannelNum, + prChnlReqInfo->ucReqChnlNum, + prChnlReqInfo->fgIsChannelRequested, + prP2pMgmtTxReqInfo->rTxReqLink.u4NumElem); + } + break; + default: + /* do nothing & wait for IDLE state to handle TX request */ + break; + } + + return; + +error: + LINK_REMOVE_KNOWN_ENTRY( + &(prP2pMgmtTxReqInfo->rTxReqLink), + &prOffChnlTxReq->rLinkEntry); + cnmMgtPktFree(prAdapter, prOffChnlTxReq->prMgmtTxMsdu); + cnmMemFree(prAdapter, prOffChnlTxReq); +} /* p2pDevHandleOffchnlTxReq */ + +static u_int8_t +p2pDevNeedOffchnlTx(IN struct ADAPTER *prAdapter, + IN struct MSG_MGMT_TX_REQUEST *prMgmtTxMsg) +{ + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) NULL; + struct P2P_CHNL_REQ_INFO *prChnlReqInfo = + (struct P2P_CHNL_REQ_INFO *) NULL; + struct WLAN_MAC_HEADER *prWlanHdr = (struct WLAN_MAC_HEADER *) NULL; + + if (prAdapter == NULL || prMgmtTxMsg == NULL) + return FALSE; + + if (!prMgmtTxMsg->fgIsOffChannel) + return FALSE; + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + prChnlReqInfo = prP2pDevFsmInfo != NULL ? + &(prP2pDevFsmInfo->rChnlReqInfo) : NULL; + + if (prChnlReqInfo == NULL) + return FALSE; + + prWlanHdr = (struct WLAN_MAC_HEADER *) + ((unsigned long) prMgmtTxMsg->prMgmtMsduInfo->prPacket + + MAC_TX_RESERVED_FIELD); + /* Probe response can only be sent during roc channel or op channel */ + if ((prWlanHdr->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_PROBE_RSP) + return FALSE; + + if (prP2pDevFsmInfo->eCurrentState == P2P_DEV_STATE_CHNL_ON_HAND && + p2pFuncCheckOnRocChnl(&(prMgmtTxMsg->rChannelInfo), + prChnlReqInfo)) + return FALSE; + + return TRUE; +} /* p2pDevNeedOffchnlTx */ + +void p2pDevFsmRunEventMgmtTx(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_MGMT_TX_REQUEST *prMgmtTxMsg = + (struct MSG_MGMT_TX_REQUEST *) NULL; + u_int8_t fgNeedOffchnlTx; + + prMgmtTxMsg = (struct MSG_MGMT_TX_REQUEST *) prMsgHdr; + + fgNeedOffchnlTx = p2pDevNeedOffchnlTx(prAdapter, prMgmtTxMsg); + DBGLOG(P2P, INFO, "fgNeedOffchnlTx: %d\n", fgNeedOffchnlTx); + + if (!fgNeedOffchnlTx) + p2pFuncTxMgmtFrame(prAdapter, + prAdapter->ucP2PDevBssIdx, + prMgmtTxMsg->prMgmtMsduInfo, + prMgmtTxMsg->fgNoneCckRate); + else + p2pDevHandleOffchnlTxReq(prAdapter, prMgmtTxMsg); + + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventMgmtTx */ + +uint32_t +p2pDevFsmRunEventMgmtFrameTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + u_int8_t fgIsSuccess = FALSE; + uint64_t *pu8GlCookie = (uint64_t *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + if (!prMsduInfo->prPacket) { + DBGLOG(P2P, WARN, + "Freed Msdu, do not indicate to host\n"); + break; + } + + pu8GlCookie = + (uint64_t *) ((unsigned long) prMsduInfo->prPacket + + (unsigned long) prMsduInfo->u2FrameLength + + MAC_TX_RESERVED_FIELD); + + if (rTxDoneStatus != TX_RESULT_SUCCESS) { + DBGLOG(P2P, INFO, + "Mgmt Frame TX Fail, Status: %d. cookie: 0x%llx\n", + rTxDoneStatus, *pu8GlCookie); + } else { + fgIsSuccess = TRUE; + DBGLOG(P2P, INFO, + "Mgmt Frame TX Done. cookie: 0x%llx\n", + *pu8GlCookie); + } + + kalP2PIndicateMgmtTxStatus(prAdapter->prGlueInfo, + prMsduInfo, + fgIsSuccess); + } while (FALSE); + + return WLAN_STATUS_SUCCESS; +} /* p2pDevFsmRunEventMgmtFrameTxDone */ + +void p2pDevFsmRunEventMgmtFrameRegister(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + /* TODO: RX Filter Management. */ + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventMgmtFrameRegister */ + +void p2pDevFsmRunEventActiveDevBss(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + if (prP2pDevFsmInfo->eCurrentState + == P2P_DEV_STATE_IDLE) { + /* Get into IDLE state to let BSS be active + * and do not Deactive. + */ + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, + P2P_DEV_STATE_IDLE); + } + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventActiveDevBss */ + +void +p2pDevFsmNotifyP2pRx(IN struct ADAPTER *prAdapter, uint8_t p2pFrameType, + u_int8_t *prFgBufferFrame) +{ + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) NULL; + u_int8_t fgNeedWaitRspFrame = FALSE; + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + fgNeedWaitRspFrame = p2pFuncNeedWaitRsp(prAdapter, p2pFrameType + 1); + + if (prP2pDevFsmInfo->eCurrentState == P2P_DEV_STATE_SCAN) { + if (fgNeedWaitRspFrame) + *prFgBufferFrame = TRUE; + return; + } + + if (prAdapter->prP2pInfo->eConnState != P2P_CNN_NORMAL) + return; + + if (fgNeedWaitRspFrame) { + DBGLOG(P2P, INFO, + "Extend channel duration, p2pFrameType: %d.\n", + p2pFrameType); + prAdapter->prP2pInfo->eConnState = p2pFrameType + 1; + } +} + +void p2pDevFsmRunEventTxCancelWait(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) NULL; + struct MSG_CANCEL_TX_WAIT_REQUEST *prCancelTxWaitMsg = + (struct MSG_CANCEL_TX_WAIT_REQUEST *) NULL; + struct P2P_MGMT_TX_REQ_INFO *prP2pMgmtTxInfo = + (struct P2P_MGMT_TX_REQ_INFO *) NULL; + struct P2P_OFF_CHNL_TX_REQ_INFO *prOffChnlTxPkt = + (struct P2P_OFF_CHNL_TX_REQ_INFO *) NULL; + u_int8_t fgIsCookieFound = FALSE; + + if (prAdapter == NULL || prMsgHdr == NULL) + goto exit; + + prCancelTxWaitMsg = (struct MSG_CANCEL_TX_WAIT_REQUEST *) prMsgHdr; + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + prP2pMgmtTxInfo = prP2pDevFsmInfo != NULL ? + &(prP2pDevFsmInfo->rMgmtTxInfo) : NULL; + + if (prCancelTxWaitMsg == NULL || prP2pDevFsmInfo == NULL || + prP2pMgmtTxInfo == NULL) + goto exit; + + LINK_FOR_EACH_ENTRY(prOffChnlTxPkt, + &(prP2pMgmtTxInfo->rTxReqLink), + rLinkEntry, + struct P2P_OFF_CHNL_TX_REQ_INFO) { + if (!prOffChnlTxPkt) + break; + if (prOffChnlTxPkt->u8Cookie == prCancelTxWaitMsg->u8Cookie) { + fgIsCookieFound = TRUE; + break; + } + } + + if (fgIsCookieFound == TRUE || prP2pDevFsmInfo->eCurrentState == + P2P_DEV_STATE_OFF_CHNL_TX) { + p2pFunClearAllTxReq(prAdapter, + &(prP2pDevFsmInfo->rMgmtTxInfo)); + p2pDevFsmRunEventAbort(prAdapter, prP2pDevFsmInfo); + } + +exit: + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventTxCancelWait */ + +#endif /* CFG_ENABLE_WIFI_DIRECT */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_dev_state.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_dev_state.c new file mode 100644 index 0000000000000..34e78cc6a8cac --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_dev_state.c @@ -0,0 +1,424 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#include "precomp.h" + +u_int8_t +p2pDevStateInit_IDLE(IN struct ADAPTER *prAdapter, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + OUT enum ENUM_P2P_DEV_STATE *peNextState) +{ + u_int8_t fgIsTransition = FALSE, fgIsShareInterface = TRUE; + uint32_t u4Idx = 0; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo; + struct P2P_MGMT_TX_REQ_INFO *prP2pMgmtTxInfo; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prChnlReqInfo) && (peNextState != NULL)); + + if (!LINK_IS_EMPTY(&(prChnlReqInfo->rP2pChnlReqLink))) { + fgIsTransition = TRUE; + *peNextState = P2P_DEV_STATE_REQING_CHANNEL; + break; + } + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + prP2pMgmtTxInfo = prP2pDevFsmInfo != NULL ? + &(prP2pDevFsmInfo->rMgmtTxInfo) : NULL; + if (prP2pDevFsmInfo && prP2pMgmtTxInfo && !LINK_IS_EMPTY( + &(prP2pMgmtTxInfo->rTxReqLink))) { + fgIsTransition = TRUE; + *peNextState = P2P_DEV_STATE_OFF_CHNL_TX; + break; + } + + /* Check the interface shared by P2P_DEV and P2P_ROLE or not? */ + /* If not shared, we shall let BSSID4 alive + * to receive PROVISION REQUEST from GC + */ + prGlueInfo = prAdapter->prGlueInfo; + if (prGlueInfo) { + for (u4Idx = 0; u4Idx < KAL_P2P_NUM; u4Idx++) { + if ((prGlueInfo->prP2PInfo[u4Idx] != NULL) && + (prGlueInfo->prP2PInfo[u4Idx]->aprRoleHandler + != NULL) && + (prGlueInfo->prP2PInfo[u4Idx]->aprRoleHandler + != + prGlueInfo->prP2PInfo[u4Idx]->prDevHandler)) { + fgIsShareInterface = FALSE; + break; + } + } + } + /************************* End *************************/ + + if (fgIsShareInterface) { + /* Stay in IDLE state. */ + UNSET_NET_ACTIVE(prAdapter, prAdapter->ucP2PDevBssIdx); + nicDeactivateNetwork(prAdapter, + prAdapter->ucP2PDevBssIdx); + } + } while (FALSE); + + return fgIsTransition; +} /* p2pDevStateInit_IDLE */ + +void p2pDevStateAbort_IDLE(IN struct ADAPTER *prAdapter) +{ + /* Currently Aobrt IDLE do nothing. */ +} /* p2pDevStateAbort_IDLE */ + +u_int8_t +p2pDevStateInit_REQING_CHANNEL(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + OUT enum ENUM_P2P_DEV_STATE *peNextState) +{ + u_int8_t fgIsTransition = FALSE; + struct MSG_P2P_CHNL_REQUEST *prP2pMsgChnlReq = + (struct MSG_P2P_CHNL_REQUEST *) NULL; + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prChnlReqInfo != NULL) && (peNextState != NULL)); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + + if (LINK_IS_EMPTY(&(prChnlReqInfo->rP2pChnlReqLink))) { + /* NO Channel Request Pending. */ + DBGLOG(P2P, ERROR, + "NO Pending Channel Request, but enter Req Channel State\n"); + fgIsTransition = TRUE; + *peNextState = P2P_DEV_STATE_IDLE; + break; + } + + LINK_REMOVE_HEAD(&(prChnlReqInfo->rP2pChnlReqLink), + prP2pMsgChnlReq, struct MSG_P2P_CHNL_REQUEST *); + + if (prP2pMsgChnlReq == NULL) { + ASSERT(FALSE); + break; + } + + if (prBssInfo->fgIsWmmInited == FALSE) + prBssInfo->ucWmmQueSet = MAX_HW_WMM_INDEX; + prBssInfo->eBand = prP2pMsgChnlReq->rChannelInfo.eBand; + cnmOpModeGetTRxNss( + prAdapter, prBssInfo->ucBssIndex, + &prBssInfo->ucOpRxNss, &prBssInfo->ucOpTxNss); + prChnlReqInfo->u4MaxInterval = prP2pMsgChnlReq->u4Duration; + prChnlReqInfo->ucReqChnlNum = + prP2pMsgChnlReq->rChannelInfo.ucChannelNum; + prChnlReqInfo->eChnlSco = prP2pMsgChnlReq->eChnlSco; + prChnlReqInfo->eBand = prP2pMsgChnlReq->rChannelInfo.eBand; + prChnlReqInfo->u8Cookie = prP2pMsgChnlReq->u8Cookie; + prChnlReqInfo->eChnlReqType = prP2pMsgChnlReq->eChnlReqType; + prChnlReqInfo->eChannelWidth = prBssInfo->ucVhtChannelWidth; + prChnlReqInfo->ucCenterFreqS1 = + prBssInfo->ucVhtChannelFrequencyS1; + prChnlReqInfo->ucCenterFreqS2 = + prBssInfo->ucVhtChannelFrequencyS2; + + p2pFuncAcquireCh(prAdapter, ucBssIdx, prChnlReqInfo); + } while (FALSE); + + if (prP2pMsgChnlReq) + cnmMemFree(prAdapter, prP2pMsgChnlReq); + + return fgIsTransition; +} /* p2pDevStateInit_REQING_CHANNEL */ + +void +p2pDevStateAbort_REQING_CHANNEL(IN struct ADAPTER *prAdapter, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN enum ENUM_P2P_DEV_STATE eNextState) +{ + do { + ASSERT_BREAK((prAdapter != NULL) + && (prChnlReqInfo != NULL) + && (eNextState < P2P_DEV_STATE_NUM)); + + switch (eNextState) { + case P2P_DEV_STATE_IDLE: + /* Channel abort case. */ + p2pFuncReleaseCh(prAdapter, + prAdapter->ucP2PDevBssIdx, prChnlReqInfo); + break; + case P2P_DEV_STATE_CHNL_ON_HAND: + /* Channel on hand case. */ + break; + case P2P_DEV_STATE_OFF_CHNL_TX: + /* OffChannel TX case. */ + break; + default: + /* Un-expected state transition. */ + DBGLOG(P2P, ERROR, + "Unexpected State Transition(eNextState=%d)\n", + eNextState); + ASSERT(FALSE); + break; + } + } while (FALSE); +} /* p2pDevStateAbort_REQING_CHANNEL */ + +void +p2pDevStateInit_CHNL_ON_HAND(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo) +{ + do { + uint32_t u4TimeoutMs = 0; + + ASSERT_BREAK((prAdapter != NULL) + && (prP2pDevFsmInfo != NULL) + && (prChnlReqInfo != NULL)); + + ASSERT(prChnlReqInfo->eChnlReqType == CH_REQ_TYPE_ROC); + + prChnlReqInfo->ucOriChnlNum = prP2pBssInfo->ucPrimaryChannel; + prChnlReqInfo->eOriBand = prP2pBssInfo->eBand; + prChnlReqInfo->eOriChnlSco = prP2pBssInfo->eBssSCO; + + prP2pBssInfo->ucPrimaryChannel = prChnlReqInfo->ucReqChnlNum; + prP2pBssInfo->eBand = prChnlReqInfo->eBand; + prP2pBssInfo->eBssSCO = prChnlReqInfo->eChnlSco; + + if (prAdapter->prP2pInfo->ucExtendChanFlag) + u4TimeoutMs = P2P_DEV_EXTEND_CHAN_TIME; + else + u4TimeoutMs = prChnlReqInfo->u4MaxInterval; + + log_dbg(P2P, INFO, + "Start channel on hand timer, Cookie: 0x%llx, Interval: %d\n", + prChnlReqInfo->u8Cookie, u4TimeoutMs); + + cnmTimerStartTimer(prAdapter, + &(prP2pDevFsmInfo->rP2pFsmTimeoutTimer), + u4TimeoutMs); + + /* Do NOT report channel ready event again for extension case */ + if (!prAdapter->prP2pInfo->ucExtendChanFlag) { + kalP2PIndicateChannelReady(prAdapter->prGlueInfo, + prChnlReqInfo->u8Cookie, + prChnlReqInfo->ucReqChnlNum, + prChnlReqInfo->eBand, + prChnlReqInfo->eChnlSco, + prChnlReqInfo->u4MaxInterval); + if (prP2pDevFsmInfo->rQueuedActionFrame.u2Length > 0) { + kalP2pIndicateQueuedMgmtFrame( + prAdapter->prGlueInfo, + &prP2pDevFsmInfo->rQueuedActionFrame); + p2pFunCleanQueuedMgmtFrame(prAdapter, + &prP2pDevFsmInfo->rQueuedActionFrame); + } + } + } while (FALSE); +} /* p2pDevStateInit_CHNL_ON_HAND */ + +void +p2pDevStateAbort_CHNL_ON_HAND(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN enum ENUM_P2P_DEV_STATE eNextState) +{ + do { + ASSERT_BREAK((prAdapter != NULL) || (prChnlReqInfo != NULL)); + + cnmTimerStopTimer(prAdapter, + &(prP2pDevFsmInfo->rP2pFsmTimeoutTimer)); + + prP2pBssInfo->ucPrimaryChannel = prChnlReqInfo->ucOriChnlNum; + prP2pBssInfo->eBand = prChnlReqInfo->eOriBand; + prP2pBssInfo->eBssSCO = prChnlReqInfo->eOriChnlSco; + + if (eNextState != P2P_DEV_STATE_CHNL_ON_HAND) { + kalP2PIndicateChannelExpired(prAdapter->prGlueInfo, + prChnlReqInfo->u8Cookie, + prChnlReqInfo->ucReqChnlNum, + prChnlReqInfo->eBand, + prChnlReqInfo->eChnlSco); + + p2pFuncReleaseCh(prAdapter, + prP2pDevFsmInfo->ucBssIndex, prChnlReqInfo); + p2pFunCleanQueuedMgmtFrame(prAdapter, + &prP2pDevFsmInfo->rQueuedActionFrame); + } + } while (FALSE); +} /* p2pDevStateAbort_CHNL_ON_HAND */ + +void p2pDevStateInit_SCAN(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct P2P_SCAN_REQ_INFO *prScanReqInfo) +{ + do { + ASSERT_BREAK((prAdapter != NULL) && (prScanReqInfo != NULL)); + + prScanReqInfo->fgIsScanRequest = TRUE; + + p2pFuncRequestScan(prAdapter, ucBssIndex, prScanReqInfo); + } while (FALSE); +} /* p2pDevStateInit_CHNL_ON_HAND */ + +void p2pDevStateAbort_SCAN(IN struct ADAPTER *prAdapter, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo) +{ + struct P2P_SCAN_REQ_INFO *prScanInfo = + (struct P2P_SCAN_REQ_INFO *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prP2pDevFsmInfo != NULL)); + + prScanInfo = &(prP2pDevFsmInfo->rScanReqInfo); + + p2pFuncCancelScan(prAdapter, + prP2pDevFsmInfo->ucBssIndex, + prScanInfo); + + kalP2PIndicateScanDone(prAdapter->prGlueInfo, + 0xFF, + prScanInfo->fgIsAbort); + } while (FALSE); +} /* p2pDevStateAbort_CHNL_ON_HAND */ + +u_int8_t +p2pDevStateInit_OFF_CHNL_TX(IN struct ADAPTER *prAdapter, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN struct P2P_MGMT_TX_REQ_INFO *prP2pMgmtTxInfo, + OUT enum ENUM_P2P_DEV_STATE *peNextState) +{ + struct P2P_OFF_CHNL_TX_REQ_INFO *prOffChnlTxPkt = + (struct P2P_OFF_CHNL_TX_REQ_INFO *) NULL; + + if (prAdapter == NULL || prP2pMgmtTxInfo == NULL || peNextState == NULL) + return FALSE; + + if (LINK_IS_EMPTY(&(prP2pMgmtTxInfo->rTxReqLink))) { + p2pFuncReleaseCh(prAdapter, + prAdapter->ucP2PDevBssIdx, + prChnlReqInfo); + /* Link is empty, return back to IDLE. */ + *peNextState = P2P_DEV_STATE_IDLE; + return TRUE; + } + + prOffChnlTxPkt = + LINK_PEEK_HEAD(&(prP2pMgmtTxInfo->rTxReqLink), + struct P2P_OFF_CHNL_TX_REQ_INFO, + rLinkEntry); + + if (prOffChnlTxPkt == NULL) { + DBGLOG(P2P, ERROR, + "Fatal Error, Link not empty but get NULL pointer.\n"); + ASSERT(FALSE); + return FALSE; + } + + if (!p2pFuncCheckOnRocChnl(&(prOffChnlTxPkt->rChannelInfo), + prChnlReqInfo)) { + DBGLOG(P2P, WARN, + "req channel(%d) != TX channel(%d), request chnl again", + prChnlReqInfo->ucReqChnlNum, + prOffChnlTxPkt->rChannelInfo.ucChannelNum); + + prChnlReqInfo->u8Cookie = prOffChnlTxPkt->u8Cookie; + prChnlReqInfo->eChnlReqType = CH_REQ_TYPE_OFFCHNL_TX; + prChnlReqInfo->eBand = prOffChnlTxPkt->rChannelInfo.eBand; + prChnlReqInfo->ucReqChnlNum = + prOffChnlTxPkt->rChannelInfo.ucChannelNum; + prChnlReqInfo->eChnlSco = prOffChnlTxPkt->eChnlExt; + prChnlReqInfo->u4MaxInterval = prOffChnlTxPkt->u4Duration; + + p2pFuncAcquireCh(prAdapter, + prP2pDevFsmInfo->ucBssIndex, + prChnlReqInfo); + } else { + cnmTimerStartTimer(prAdapter, + &(prP2pDevFsmInfo->rP2pFsmTimeoutTimer), + prOffChnlTxPkt->u4Duration); + p2pFuncTxMgmtFrame(prAdapter, + prP2pDevFsmInfo->ucBssIndex, + prOffChnlTxPkt->prMgmtTxMsdu, + prOffChnlTxPkt->fgNoneCckRate); + + LINK_REMOVE_HEAD(&(prP2pMgmtTxInfo->rTxReqLink), + prOffChnlTxPkt, + struct P2P_OFF_CHNL_TX_REQ_INFO *); + cnmMemFree(prAdapter, prOffChnlTxPkt); + } + + return FALSE; +} /* p2pDevSateInit_OFF_CHNL_TX */ + +void +p2pDevStateAbort_OFF_CHNL_TX(IN struct ADAPTER *prAdapter, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo, + IN struct P2P_MGMT_TX_REQ_INFO *prP2pMgmtTxInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN enum ENUM_P2P_DEV_STATE eNextState) +{ + cnmTimerStopTimer(prAdapter, &(prP2pDevFsmInfo->rP2pFsmTimeoutTimer)); + + if (eNextState == P2P_DEV_STATE_OFF_CHNL_TX) + return; + + p2pFunClearAllTxReq(prAdapter, prP2pMgmtTxInfo); + p2pFuncReleaseCh(prAdapter, + prAdapter->ucP2PDevBssIdx, + prChnlReqInfo); +} /* p2pDevSateAbort_OFF_CHNL_TX */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_fsm.c new file mode 100644 index 0000000000000..a2164bdfec278 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_fsm.c @@ -0,0 +1,472 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + + +/****************************************************************************** + * C O M P I L E 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 + ****************************************************************************** + */ + +/****************************************************************************** + * M A 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 u_int8_t p2pFsmUseRoleIf(IN struct ADAPTER *prAdapter, + uint8_t ucBssIdx) +{ + u_int8_t fgUseRoleInterface = FALSE; + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + + if (prBssInfo == NULL) { + DBGLOG(P2P, ERROR, "can not get bss info by bssIdx: %d", + ucBssIdx); + return FALSE; + } + + if (ucBssIdx != prAdapter->ucP2PDevBssIdx) { + if (IS_NET_ACTIVE(prAdapter, ucBssIdx)) { + fgUseRoleInterface = TRUE; + if (prBssInfo->eIftype != IFTYPE_P2P_CLIENT && + prBssInfo->eIftype != IFTYPE_P2P_GO && + !p2pFuncIsAPMode( + prAdapter->rWifiVar + .prP2PConnSettings + [prBssInfo->u4PrivateData])) { + DBGLOG(P2P, TRACE, + "force use dev interface.\n"); + fgUseRoleInterface = FALSE; + } + } else { + fgUseRoleInterface = FALSE; + } + } else { + fgUseRoleInterface = FALSE; + } + + DBGLOG(P2P, TRACE, "bss[%d %d], role: %d, use_role_if: %d\n", + ucBssIdx, + IS_NET_ACTIVE(prAdapter, ucBssIdx), + prBssInfo->eIftype, + fgUseRoleInterface); + + return fgUseRoleInterface; +} + +void p2pFsmRunEventScanRequest(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_P2P_SCAN_REQUEST *prP2pScanReqMsg = + (struct MSG_P2P_SCAN_REQUEST *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + if ((prAdapter == NULL) || (prMsgHdr == NULL)) + break; + + prP2pScanReqMsg = (struct MSG_P2P_SCAN_REQUEST *) prMsgHdr; + + prAdapter->prP2pInfo->eConnState = P2P_CNN_NORMAL; + + if (prP2pScanReqMsg->ucBssIdx == prAdapter->ucP2PDevBssIdx) + p2pDevFsmRunEventScanRequest(prAdapter, prMsgHdr); + else + p2pRoleFsmRunEventScanRequest(prAdapter, prMsgHdr); + + prMsgHdr = NULL; + /* Both p2pDevFsmRunEventScanRequest and + * p2pRoleFsmRunEventScanRequest + * free prMsgHdr before return, + * so prMsgHdr is needed to be NULL. + */ + } while (FALSE); + + /* + * if (prAdapter && prMsgHdr) + * cnmMemFree(prAdapter, prMsgHdr); + */ +} /* p2pDevFsmRunEventScanRequest */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_CH_GRANT *prMsgChGrant = (struct MSG_CH_GRANT *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prMsgChGrant = (struct MSG_CH_GRANT *) prMsgHdr; + + prP2pBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, + prMsgChGrant->ucBssIndex); + + prAdapter->prP2pInfo->eConnState = P2P_CNN_NORMAL; + prAdapter->prP2pInfo->ucExtendChanFlag = 0; + + DBGLOG(P2P, TRACE, "P2P Run Event Channel Grant\n"); + +#if CFG_SISO_SW_DEVELOP + /* Driver record granted CH in BSS info */ + prP2pBssInfo->fgIsGranted = TRUE; + prP2pBssInfo->eBandGranted = prMsgChGrant->eRfBand; + prP2pBssInfo->ucPrimaryChannelGranted = + prMsgChGrant->ucPrimaryChannel; +#endif + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_P2P_DEVICE: + ASSERT(prP2pBssInfo->ucBssIndex + == prAdapter->ucP2PDevBssIdx); + + p2pDevFsmRunEventChnlGrant(prAdapter, + prMsgHdr, + prAdapter->rWifiVar.prP2pDevFsmInfo); + break; + case OP_MODE_INFRASTRUCTURE: + case OP_MODE_ACCESS_POINT: + ASSERT(prP2pBssInfo->ucBssIndex + < prAdapter->ucP2PDevBssIdx); + + p2pRoleFsmRunEventChnlGrant(prAdapter, prMsgHdr, + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData)); + break; + default: + ASSERT(FALSE); + break; + } + } while (FALSE); +} /* p2pFsmRunEventChGrant */ + +void p2pFsmRunEventNetDeviceRegister(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_P2P_NETDEV_REGISTER *prNetDevRegisterMsg = + (struct MSG_P2P_NETDEV_REGISTER *) NULL; + + DBGLOG(P2P, TRACE, "p2pFsmRunEventNetDeviceRegister\n"); + + prNetDevRegisterMsg = (struct MSG_P2P_NETDEV_REGISTER *) prMsgHdr; + + if (prNetDevRegisterMsg->fgIsEnable) { + p2pSetMode((prNetDevRegisterMsg->ucMode == 1) ? TRUE : FALSE); + if (p2pLaunch(prAdapter->prGlueInfo)) + ASSERT(prAdapter->fgIsP2PRegistered); + } else { + if (prAdapter->fgIsP2PRegistered) + p2pRemove(prAdapter->prGlueInfo); + } + + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pFsmRunEventNetDeviceRegister */ + +void p2pFsmRunEventUpdateMgmtFrame(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_P2P_MGMT_FRAME_UPDATE *prP2pMgmtFrameUpdateMsg = + (struct MSG_P2P_MGMT_FRAME_UPDATE *) NULL; + + DBGLOG(P2P, TRACE, "p2pFsmRunEventUpdateMgmtFrame\n"); + + prP2pMgmtFrameUpdateMsg = (struct MSG_P2P_MGMT_FRAME_UPDATE *) 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; + } + + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pFsmRunEventUpdateMgmtFrame */ + +#if CFG_SUPPORT_WFD +void p2pFsmRunEventWfdSettingUpdate(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct WFD_CFG_SETTINGS *prWfdCfgSettings = + (struct WFD_CFG_SETTINGS *) NULL; + struct MSG_WFD_CONFIG_SETTINGS_CHANGED *prMsgWfdCfgSettings = + (struct MSG_WFD_CONFIG_SETTINGS_CHANGED *) NULL; + uint32_t i; + + /* WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; */ + + DBGLOG(P2P, INFO, "p2pFsmRunEventWfdSettingUpdate\n"); + + do { + ASSERT_BREAK((prAdapter != NULL)); + + if (prMsgHdr != NULL) { + prMsgWfdCfgSettings = + (struct MSG_WFD_CONFIG_SETTINGS_CHANGED *) + prMsgHdr; + prWfdCfgSettings = + prMsgWfdCfgSettings->prWfdCfgSettings; + } else { + prWfdCfgSettings = + &prAdapter->rWifiVar.rWfdConfigureSettings; + } + + DBGLOG(P2P, INFO, + "WFD Enalbe %x info %x state %x flag %x adv %x\n", + prWfdCfgSettings->ucWfdEnable, + prWfdCfgSettings->u2WfdDevInfo, + (uint32_t) prWfdCfgSettings->u4WfdState, + (uint32_t) prWfdCfgSettings->u4WfdFlag, + (uint32_t) prWfdCfgSettings->u4WfdAdvancedFlag); + + if (prWfdCfgSettings->ucWfdEnable == 0) + for (i = 0; i < KAL_P2P_NUM; i++) { + if (prAdapter->prGlueInfo->prP2PInfo[i]) + prAdapter->prGlueInfo->prP2PInfo[i] + ->u2WFDIELen = 0; + } + +#if CFG_ENABLE_PER_STA_STATISTICS_LOG + if (prAdapter->rWifiVar.aprP2pRoleFsmInfo[0]) { + /* Assume role 0 */ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) + prAdapter->rWifiVar.aprP2pRoleFsmInfo[0]; + + if (prWfdCfgSettings->ucWfdEnable == 1) + cnmTimerStartTimer(prAdapter, + &(prP2pRoleFsmInfo + ->rP2pRoleFsmGetStatisticsTimer), + (3 * P2P_ROLE_GET_STATISTICS_TIME)); + else { + cnmTimerStopTimer(prAdapter, + &prP2pRoleFsmInfo + ->rP2pRoleFsmGetStatisticsTimer); + /* Reset linkscore */ + prWfdCfgSettings->u4LinkScore = 0; + } + } +#endif + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} + +/* p2pFsmRunEventWfdSettingUpdate */ + +#endif /* CFG_SUPPORT_WFD */ + + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_SCN_SCAN_DONE *prScanDoneMsg = + (struct MSG_SCN_SCAN_DONE *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + + prScanDoneMsg = (struct MSG_SCN_SCAN_DONE *) prMsgHdr; + + prP2pBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, prScanDoneMsg->ucBssIndex); + + if (prAdapter->fgIsP2PRegistered == FALSE) { + DBGLOG(P2P, TRACE, + "P2P BSS Info is removed, break p2pFsmRunEventScanDone\n"); + + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + DBGLOG(P2P, TRACE, "P2P Scan Done Event\n"); + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_P2P_DEVICE: + ASSERT(prP2pBssInfo->ucBssIndex == prAdapter->ucP2PDevBssIdx); + p2pDevFsmRunEventScanDone(prAdapter, + prMsgHdr, + prAdapter->rWifiVar.prP2pDevFsmInfo); + break; + case OP_MODE_INFRASTRUCTURE: + case OP_MODE_ACCESS_POINT: + ASSERT(prP2pBssInfo->ucBssIndex < prAdapter->ucP2PDevBssIdx); + p2pRoleFsmRunEventScanDone(prAdapter, prMsgHdr, + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData)); + break; + default: + ASSERT(FALSE); + break; + } +} /* p2pFsmRunEventScanDone */ + +void p2pFsmRunEventMgmtFrameTx(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_MGMT_TX_REQUEST *prMgmtTxMsg = + (struct MSG_MGMT_TX_REQUEST *) NULL; + + do { + if ((prAdapter == NULL) || (prMsgHdr == NULL)) + break; + + prMgmtTxMsg = (struct MSG_MGMT_TX_REQUEST *) prMsgHdr; + + if (p2pFsmUseRoleIf(prAdapter, prMgmtTxMsg->ucBssIdx)) { + p2pRoleFsmRunEventMgmtTx(prAdapter, prMsgHdr); + } else { + prMgmtTxMsg->ucBssIdx = prAdapter->ucP2PDevBssIdx; + p2pDevFsmRunEventMgmtTx(prAdapter, prMsgHdr); + } + } while (FALSE); +} /* p2pFsmRunEventMgmtFrameTx */ + +void p2pFsmRunEventTxCancelWait(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_CANCEL_TX_WAIT_REQUEST *prCancelTxWaitMsg = + (struct MSG_CANCEL_TX_WAIT_REQUEST *) NULL; + + do { + if ((prAdapter == NULL) || (prMsgHdr == NULL)) + break; + + prCancelTxWaitMsg = + (struct MSG_CANCEL_TX_WAIT_REQUEST *) prMsgHdr; + + if (p2pFsmUseRoleIf(prAdapter, prCancelTxWaitMsg->ucBssIdx)) { + p2pRoleFsmRunEventTxCancelWait(prAdapter, prMsgHdr); + } else { + prCancelTxWaitMsg->ucBssIdx = prAdapter->ucP2PDevBssIdx; + p2pDevFsmRunEventTxCancelWait(prAdapter, prMsgHdr); + } + } while (FALSE); + +} /* p2pFsmRunEventTxCancelWait */ + +#endif /* CFG_ENABLE_WIFI_DIRECT */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_func.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_func.c new file mode 100644 index 0000000000000..d711a3fba1554 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_func.c @@ -0,0 +1,7190 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +#include "precomp.h" + +struct APPEND_VAR_ATTRI_ENTRY 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 */ +}; + +struct APPEND_VAR_IE_ENTRY txProbeRspIETable[] = { + {(ELEM_HDR_LEN + (RATE_NUM_SW - 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 */ +#if CFG_SUPPORT_802_11AC + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP), NULL, + rlmRspGenerateVhtCapIE} /*191 */ + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP), NULL, + rlmRspGenerateVhtOpIE} /*192 */ + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP_MODE_NOTIFICATION), NULL, + rlmRspGenerateVhtOpNotificationIE} /*199 */ +#endif +#if CFG_SUPPORT_802_11AX + , {0, heRlmCalculateHeCapIELen, + heRlmRspGenerateHeCapIE} /* 255, EXT 35 */ + , {0, heRlmCalculateHeOpIELen, + heRlmRspGenerateHeOpIE} /* 255, EXT 36 */ +#endif +#if CFG_SUPPORT_MTK_SYNERGY + , {(ELEM_HDR_LEN + ELEM_MIN_LEN_MTK_OUI), NULL, + rlmGenerateMTKOuiIE} /* 221 */ +#endif + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_WPA), NULL, + rsnGenerateWPAIE} /* 221 */ +}; + +#if (CFG_SUPPORT_DFS_MASTER == 1) +u_int8_t g_fgManualCac = FALSE; +uint32_t g_u4DriverCacTime; +uint32_t g_u4CacStartBootTime; +uint8_t g_ucRadarDetectMode = FALSE; +struct P2P_RADAR_INFO g_rP2pRadarInfo; +uint8_t g_ucDfsState = DFS_STATE_INACTIVE; +static uint8_t *apucDfsState[DFS_STATE_NUM] = { + (uint8_t *) DISP_STRING("DFS_STATE_INACTIVE"), + (uint8_t *) DISP_STRING("DFS_STATE_CHECKING"), + (uint8_t *) DISP_STRING("DFS_STATE_ACTIVE"), + (uint8_t *) DISP_STRING("DFS_STATE_DETECTED") +}; + +uint8_t *apucW53RadarType[3] = { + (uint8_t *) DISP_STRING("Unknown Type"), + (uint8_t *) DISP_STRING("Type 1 (short pulse)"), + (uint8_t *) DISP_STRING("Type 2 (short pulse)") +}; +uint8_t *apucW56RadarType[12] = { + (uint8_t *) DISP_STRING("Unknown Type"), + (uint8_t *) DISP_STRING("Type 1 (short pulse)"), + (uint8_t *) DISP_STRING("Type 2 (short pulse)"), + (uint8_t *) DISP_STRING("Type 3 (short pulse)"), + (uint8_t *) DISP_STRING("Type 4 (short pulse)"), + (uint8_t *) DISP_STRING("Type 5 (short pulse)"), + (uint8_t *) DISP_STRING("Type 6 (short pulse)"), + (uint8_t *) DISP_STRING("Type 7 (long pulse)"), + (uint8_t *) DISP_STRING("Type 8 (short pulse)"), + (uint8_t *) DISP_STRING("Type 4 or Type 5 or Type 6 (short pulse)"), + (uint8_t *) DISP_STRING("Type 5 or Type 6 or Type 8 (short pulse)"), + (uint8_t *) DISP_STRING("Type 5 or Type 6 (short pulse)") +}; +#endif + +static void +p2pFuncParseBeaconVenderId(IN struct ADAPTER *prAdapter, IN uint8_t *pucIE, + IN struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo, + IN uint8_t ucRoleIndex); +#if 0 +static void +p2pFuncGetAttriListAction(IN struct ADAPTER *prAdapter, + IN struct IE_P2P *prIe, + IN uint8_t ucOuiType, + OUT uint8_t **pucAttriListStart, + OUT uint16_t *u2AttriListLen, + OUT u_int8_t *fgIsAllocMem, + OUT u_int8_t *fgBackupAttributes, + OUT uint16_t *u2BufferSize); +#endif + +static void +p2pFuncProcessP2pProbeRspAction(IN struct ADAPTER *prAdapter, + IN uint8_t *pucIEBuf, IN uint8_t ucElemIdType, + OUT uint8_t *ucBssIdx, OUT struct BSS_INFO **prP2pBssInfo, + OUT u_int8_t *fgIsWSCIE, + OUT u_int8_t *fgIsP2PIE, + OUT u_int8_t *fgIsWFDIE, + OUT u_int8_t *fgIsVenderIE); + +static void +p2pFuncGetSpecAttriAction(IN struct IE_P2P *prP2pIE, + IN uint8_t ucOuiType, + IN uint8_t ucAttriID, + OUT struct P2P_ATTRIBUTE **prTargetAttri); + +/*---------------------------------------------------------------------------*/ +/*! + * @brief Function for requesting scan. + * There is an option to do ACTIVE or PASSIVE scan. + * + * @param eScanType - Specify the scan type of the scan request. + * It can be an ACTIVE/PASSIVE + * Scan. + * eChannelSet - Specify the preferred channel set. + * A FULL scan would request a legacy + * full channel normal scan.(usually ACTIVE). + * A P2P_SOCIAL scan would scan + * 1+6+11 channels.(usually ACTIVE) + * A SPECIFIC scan would + * only 1/6/11 channels scan. + * (Passive Listen/Specific Search) + * ucChannelNum - A specific channel number. + * (Only when channel is specified) + * eBand - A specific band. (Only when channel is specified) + * + * + * @return (none) + */ +/*---------------------------------------------------------------------------*/ +void p2pFuncRequestScan(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct P2P_SCAN_REQ_INFO *prScanReqInfo) +{ + struct MSG_SCN_SCAN_REQ_V2 *prScanReqV2 = + (struct MSG_SCN_SCAN_REQ_V2 *) NULL; + +#ifdef CFG_SUPPORT_BEAM_PLUS + /*NFC Beam + Indication */ + struct P2P_FSM_INFO *prP2pFsmInfo = (struct P2P_FSM_INFO *) NULL; +#endif + + 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); + } + + prScanReqV2 = (struct MSG_SCN_SCAN_REQ_V2 *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + (sizeof(struct MSG_SCN_SCAN_REQ_V2) + + (sizeof(struct PARAM_SSID) * + prScanReqInfo->ucSsidNum))); + if (!prScanReqV2) { + DBGLOG(P2P, ERROR, + "p2pFuncRequestScan: Memory allocation fail, can not send SCAN MSG to scan module\n"); + break; + } + + prScanReqV2->rMsgHdr.eMsgId = MID_P2P_SCN_SCAN_REQ_V2; + prScanReqV2->ucSeqNum = ++prScanReqInfo->ucSeqNumOfScnMsg; + prScanReqV2->ucBssIndex = ucBssIndex; + prScanReqV2->eScanType = prScanReqInfo->eScanType; + prScanReqV2->eScanChannel = prScanReqInfo->eChannelSet; + prScanReqV2->u2IELen = 0; + prScanReqV2->prSsid = (struct PARAM_SSID *) + ((unsigned long) prScanReqV2 + + sizeof(struct MSG_SCN_SCAN_REQ_V2)); + + /* Copy IE for Probe Request. */ + kalMemCopy(prScanReqV2->aucIE, + prScanReqInfo->aucIEBuf, prScanReqInfo->u4BufLength); + prScanReqV2->u2IELen = (uint16_t) prScanReqInfo->u4BufLength; + + prScanReqV2->u2ChannelDwellTime = + prScanReqInfo->u2PassiveDewellTime; + prScanReqV2->u2ChannelMinDwellTime = + SCAN_CHANNEL_DWELL_TIME_MIN_MSEC; + COPY_MAC_ADDR(prScanReqV2->aucBSSID, + "\xff\xff\xff\xff\xff\xff"); + + prScanReqV2->u2TimeoutValue = 0; + prScanReqV2->u2ProbeDelay = 0; + + switch (prScanReqInfo->eChannelSet) { + case SCAN_CHANNEL_SPECIFIED: + { + uint32_t u4Idx = 0; + struct RF_CHANNEL_INFO *prDomainInfo = + (struct RF_CHANNEL_INFO *) + prScanReqInfo->arScanChannelList; + + if (prScanReqInfo->ucNumChannelList + > MAXIMUM_OPERATION_CHANNEL_LIST) + prScanReqInfo->ucNumChannelList = + MAXIMUM_OPERATION_CHANNEL_LIST; + + for (u4Idx = 0; + u4Idx < prScanReqInfo->ucNumChannelList; + u4Idx++) { + prScanReqV2->arChnlInfoList + [u4Idx].ucChannelNum = + prDomainInfo->ucChannelNum; + prScanReqV2->arChnlInfoList + [u4Idx].eBand = + prDomainInfo->eBand; + prDomainInfo++; + } + + prScanReqV2->ucChannelListNum = + prScanReqInfo->ucNumChannelList; + } + /* fallthrough */ + case SCAN_CHANNEL_FULL: + /* fallthrough */ + case SCAN_CHANNEL_2G4: + /* fallthrough */ + case SCAN_CHANNEL_P2P_SOCIAL: + { + /* UINT_8 aucP2pSsid[] = P2P_WILDCARD_SSID; */ + struct PARAM_SSID *prParamSsid = + (struct PARAM_SSID *) NULL; + + prParamSsid = prScanReqV2->prSsid; + + for (prScanReqV2->ucSSIDNum = 0; + prScanReqV2->ucSSIDNum + < prScanReqInfo->ucSsidNum; + prScanReqV2->ucSSIDNum++) { + + COPY_SSID(prParamSsid->aucSsid, + prParamSsid->u4SsidLen, + prScanReqInfo->arSsidStruct + [prScanReqV2->ucSSIDNum] + .aucSsid, + prScanReqInfo->arSsidStruct + [prScanReqV2->ucSSIDNum] + .ucSsidLen); + + prParamSsid++; + } + + /* For compatible. (in FW?) need to check. */ + if (prScanReqV2->ucSSIDNum == 0) + prScanReqV2->ucSSIDType = + SCAN_REQ_SSID_P2P_WILDCARD; + else + prScanReqV2->ucSSIDType = + SCAN_REQ_SSID_SPECIFIED; + } + break; + default: + /* Currently there is no other scan channel set. */ + ASSERT(FALSE); + break; + } + + prScanReqInfo->fgIsScanRequest = TRUE; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prScanReqV2, + MSG_SEND_METHOD_BUF); + + } while (FALSE); +} /* p2pFuncRequestScan */ + +void p2pFuncCancelScan(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct P2P_SCAN_REQ_INFO *prScanInfo) +{ + struct MSG_SCN_SCAN_CANCEL *prScanCancelMsg = + (struct MSG_SCN_SCAN_CANCEL *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prScanInfo != NULL)); + + if (!prScanInfo->fgIsScanRequest) + break; + + DBGLOG(P2P, TRACE, "P2P Cancel Scan\n"); + + prScanCancelMsg = (struct MSG_SCN_SCAN_CANCEL *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct 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"); + break; + } + kalMemZero(prScanCancelMsg, + sizeof(struct MSG_SCN_SCAN_CANCEL)); + + prScanCancelMsg->rMsgHdr.eMsgId = + MID_P2P_SCN_SCAN_CANCEL; + prScanCancelMsg->ucBssIndex = ucBssIndex; + prScanCancelMsg->ucSeqNum = + prScanInfo->ucSeqNumOfScnMsg++; + prScanCancelMsg->fgIsChannelExt = FALSE; + prScanInfo->fgIsScanRequest = FALSE; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prScanCancelMsg, + MSG_SEND_METHOD_BUF); + } while (FALSE); +} /* p2pFuncCancelScan */ + +void p2pFuncGCJoin(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN struct P2P_JOIN_INFO *prP2pJoinInfo) +{ + struct MSG_SAA_FSM_START *prJoinReqMsg = + (struct MSG_SAA_FSM_START *) NULL; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + struct BSS_DESC *prBssDesc = (struct BSS_DESC *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prP2pBssInfo != NULL) + && (prP2pJoinInfo != NULL)); + + prBssDesc = prP2pJoinInfo->prTargetBssDesc; + if ((prBssDesc) == NULL) { + DBGLOG(P2P, ERROR, + "p2pFuncGCJoin: NO Target BSS Descriptor\n"); + ASSERT(FALSE); + break; + } + + if (prBssDesc->ucSSIDLen) { + COPY_SSID(prP2pBssInfo->aucSSID, + prP2pBssInfo->ucSSIDLen, + prBssDesc->aucSSID, + prBssDesc->ucSSIDLen); + } + + /* 2 <1> We are goin to connect to this BSS */ + prBssDesc->fgIsConnecting = TRUE; + + /* 2 <2> Setup corresponding STA_RECORD_T */ + prStaRec = bssCreateStaRecFromBssDesc(prAdapter, +#if CFG_P2P_CONNECT_ALL_BSS + (STA_TYPE_P2P_GO), +#else + (prBssDesc->fgIsP2PPresent + ? (STA_TYPE_P2P_GO) + : (STA_TYPE_LEGACY_AP)), +#endif + prP2pBssInfo->ucBssIndex, prBssDesc); + + if (prStaRec == NULL) { + DBGLOG(P2P, TRACE, "Create station record fail\n"); + ASSERT(FALSE); + break; + } + + prP2pJoinInfo->prTargetStaRec = prStaRec; + prP2pJoinInfo->fgIsJoinComplete = FALSE; + prP2pJoinInfo->u4BufLength = 0; + + /* 2 <2.1> Sync. to FW domain */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + if (prP2pBssInfo->eConnectionState + == MEDIA_STATE_DISCONNECTED) { + prStaRec->fgIsReAssoc = FALSE; + prP2pJoinInfo->ucAvailableAuthTypes = + (uint8_t) AUTH_TYPE_OPEN_SYSTEM; + prStaRec->ucTxAuthAssocRetryLimit = + TX_AUTH_ASSOCI_RETRY_LIMIT; + } else { + DBGLOG(P2P, ERROR, + "JOIN INIT: Join Request when connected.\n"); + break; + } + + /* 2 <4> Use an appropriate Authentication Algorithm Number + * among the ucAvailableAuthTypes. + */ + if (prP2pJoinInfo->ucAvailableAuthTypes + & (uint8_t) AUTH_TYPE_OPEN_SYSTEM) { + + DBGLOG(P2P, TRACE, + "JOIN INIT: Try to do Authentication with AuthType == OPEN_SYSTEM.\n"); + + prP2pJoinInfo->ucAvailableAuthTypes &= + ~(uint8_t) AUTH_TYPE_OPEN_SYSTEM; + + prStaRec->ucAuthAlgNum = + (uint8_t) AUTH_ALGORITHM_NUM_OPEN_SYSTEM; + } else { + DBGLOG(P2P, ERROR, + "JOIN INIT: ucAvailableAuthTypes Error.\n"); + ASSERT(FALSE); + break; + } + + /* 4 <5> Overwrite Connection Setting + * for eConnectionPolicy == ANY (Used by Assoc Req) + */ + + /* 2 <5> Backup desired channel. */ + + /* 2 <6> Send a Msg to trigger SAA to start JOIN process. */ + prJoinReqMsg = (struct MSG_SAA_FSM_START *) + cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(struct MSG_SAA_FSM_START)); + + if (!prJoinReqMsg) { + DBGLOG(P2P, TRACE, "Allocation Join Message Fail\n"); + return; + } + + prJoinReqMsg->rMsgHdr.eMsgId = MID_P2P_SAA_FSM_START; + prJoinReqMsg->ucSeqNum = ++prP2pJoinInfo->ucSeqNumOfReqMsg; + prJoinReqMsg->prStaRec = prStaRec; + + /* TODO: Consider fragmentation info in station record. */ + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prJoinReqMsg, + MSG_SEND_METHOD_BUF); + + } while (FALSE); + +} /* p2pFuncGCJoin */ + +/*---------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc, + IN struct STA_RECORD *prStaRec, + IN struct BSS_INFO *prP2pBssInfo, + IN struct SW_RFB *prAssocRspSwRfb) +{ + struct WLAN_ASSOC_RSP_FRAME *prAssocRspFrame = + (struct WLAN_ASSOC_RSP_FRAME *) NULL; + uint16_t u2IELength; + uint8_t *pucIE; + + DEBUGFUNC("p2pUpdateBssInfoForJOIN()"); + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prStaRec != NULL) + && (prP2pBssInfo != NULL) + && (prAssocRspSwRfb != NULL)); + + prAssocRspFrame = (struct WLAN_ASSOC_RSP_FRAME *) + prAssocRspSwRfb->pvHeader; + + if (prBssDesc == NULL) { + /* Target BSS NULL. */ + DBGLOG(P2P, TRACE, "Target BSS NULL\n"); + break; + } + + 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 */ + ASSERT_BREAK(prP2pBssInfo->eCurrentOPMode + == OP_MODE_INFRASTRUCTURE); + + /* 4 <1.2> Setup SSID */ + COPY_SSID(prP2pBssInfo->aucSSID, + prP2pBssInfo->ucSSIDLen, + prBssDesc->aucSSID, + prBssDesc->ucSSIDLen); + + /* 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 */ + /* Use AP's Cap Info as BSS Cap Info */ + prP2pBssInfo->u2CapInfo = prStaRec->u2CapInfo; + + 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; + + nicTxUpdateBssDefaultRate(prP2pBssInfo); + + /* 3 <3> Update BSS_INFO_T from SW_RFB_T + * (Association Resp Frame) + */ + /* 4 <3.1> Setup BSSID */ + if (UNEQUAL_MAC_ADDR(prBssDesc->aucBSSID, + prAssocRspFrame->aucBSSID)) { + DBGLOG(P2P, WARN, "Assoc BSSID " MACSTR "\n", + MAC2STR(prAssocRspFrame->aucBSSID)); + COPY_MAC_ADDR(prP2pBssInfo->aucBSSID, + prBssDesc->aucBSSID); + } else + COPY_MAC_ADDR(prP2pBssInfo->aucBSSID, + prAssocRspFrame->aucBSSID); + + u2IELength = + (uint16_t) ((prAssocRspSwRfb->u2PacketLen - + prAssocRspSwRfb->u2HeaderLen) - + (OFFSET_OF(struct WLAN_ASSOC_RSP_FRAME, + 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 */ + + 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, prP2pBssInfo->ucBssIndex); + + /* 4 <4.4> *DEFER OPERATION* + * nicPmIndicateBssConnected() will be invoked + * inside scanProcessBeaconAndProbeResp() + * after 1st beacon is received + */ + + } while (FALSE); +} /* end of p2pUpdateBssInfoForJOIN() */ + +uint32_t +p2pFunMgmtFrameTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + u_int8_t fgIsSuccess = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + 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"); + } + + kalP2PIndicateMgmtTxStatus(prAdapter->prGlueInfo, + prMsduInfo, fgIsSuccess); + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; + +} /* p2pFunMgmtFrameTxDone */ + +const char * +p2pActionFrameToString(enum ENUM_P2P_ACTION_FRAME_TYPE eP2pAction) +{ + switch (eP2pAction) { + case P2P_GO_NEG_REQ: + return "GO_NEG_REQ"; + case P2P_GO_NEG_RESP: + return "GO_NEG_RESP"; + case P2P_GO_NEG_CONF: + return "GO_NEG_CONF"; + case P2P_INVITATION_REQ: + return "INVITATION_REQ"; + case P2P_INVITATION_RESP: + return "INVITATION_RESP"; + case P2P_DEV_DISC_REQ: + return "DEV_DISC_REQ"; + case P2P_DEV_DISC_RESP: + return "DEV_DISC_RESP"; + case P2P_PROV_DISC_REQ: + return "PROV_DISC_REQ"; + case P2P_PROV_DISC_RESP: + return "PROV_DISC_RESP"; + } + + return "UNKNOWN P2P Public Action"; +} + +const char * +paToString(int32_t u4PaAction) +{ + switch (u4PaAction) { + case WLAN_PA_20_40_BSS_COEX: + return "PA_20_40_BSS_COEX"; + case WLAN_PA_VENDOR_SPECIFIC: + return "PA_VENDOR_SPECIFIC"; + case WLAN_PA_GAS_INITIAL_REQ: + return "PA_GAS_INITIAL_REQ"; + case WLAN_PA_GAS_INITIAL_RESP: + return "PA_GAS_INITIAL_RESP"; + case WLAN_PA_GAS_COMEBACK_REQ: + return "PA_GAS_COMEBACK_REQ"; + case WLAN_PA_GAS_COMEBACK_RESP: + return "PA_GAS_COMEBACK_RESP"; + case WLAN_TDLS_DISCOVERY_RESPONSE: + return "TDLS_DISCOVERY_RESPONSE"; + } + + return "UNKNOWN Public Action"; +} + + +const char * +actionToString(int32_t u4WlanAction) +{ + switch (u4WlanAction) { + case WLAN_ACTION_SPECTRUM_MGMT: + return "SPECTRUM_MGMT"; + case WLAN_ACTION_QOS: + return "QOS"; + case WLAN_ACTION_DLS: + return "DLS"; + case WLAN_ACTION_BLOCK_ACK: + return "BLOCK_ACK"; + case WLAN_ACTION_PUBLIC: + return "PUBLIC"; + case WLAN_ACTION_RADIO_MEASUREMENT: + return "RADIO_MEASUREMENT"; + case WLAN_ACTION_FT: + return "FT"; + case WLAN_ACTION_HT: + return "HT"; + case WLAN_ACTION_SA_QUERY: + return "SA_QUERY"; + case WLAN_ACTION_PROTECTED_DUAL: + return "PROTECTED_DUAL"; + case WLAN_ACTION_WNM: + return "WNM"; + case WLAN_ACTION_UNPROTECTED_WNM: + return "UNPROTECTED_WNM"; + case WLAN_ACTION_TDLS: + return "TDLS"; + case WLAN_ACTION_SELF_PROTECTED: + return "SELF_PROTECTED"; + case WLAN_ACTION_WMM: + return "WMM"; + case WLAN_ACTION_VENDOR_SPECIFIC: + return "VENDOR_SPECIFIC"; + } + + return "UNKNOWN Action Frame"; +} + + +enum ENUM_P2P_CONNECT_STATE +p2pFuncTagActionActionP2PFrame(IN struct MSDU_INFO *prMgmtTxMsdu, + IN struct WLAN_ACTION_FRAME *prActFrame, + IN uint8_t ucP2pAction, IN uint64_t u8Cookie) +{ + DBGLOG(P2P, INFO, + "Found P2P_%s, SA: " MACSTR + " - DA: " MACSTR ", cookie: 0x%llx, SeqNO: %d\n", + p2pActionFrameToString(ucP2pAction), + MAC2STR(prActFrame->aucSrcAddr), + MAC2STR(prActFrame->aucDestAddr), + u8Cookie, + prMgmtTxMsdu->ucTxSeqNum); + return ucP2pAction + 1; +} + +enum ENUM_P2P_CONNECT_STATE +p2pFuncTagActionActionFrame(IN struct MSDU_INFO *prMgmtTxMsdu, + IN struct WLAN_ACTION_FRAME *prActFrame, + IN uint8_t ucAction, IN uint64_t u8Cookie) +{ + uint8_t *pucVendor = NULL; + enum ENUM_P2P_CONNECT_STATE eCNNState = P2P_CNN_NORMAL; + + DBGLOG(P2P, INFO, + "Found WLAN_%s, SA: " MACSTR + " - DA: " MACSTR ", cookie: 0x%llx, SeqNo: %d\n", + paToString(ucAction), + MAC2STR(prActFrame->aucSrcAddr), + MAC2STR(prActFrame->aucDestAddr), + u8Cookie, + prMgmtTxMsdu->ucTxSeqNum); + + if (ucAction != WLAN_PA_VENDOR_SPECIFIC) + return P2P_CNN_NORMAL; + + pucVendor = (uint8_t *)prActFrame + 26; + if (*(pucVendor + 0) == 0x50 && + *(pucVendor + 1) == 0x6f && + *(pucVendor + 2) == 0x9a) { + if (*(pucVendor + 3) == 0x09) + /* found p2p IE */ + eCNNState = p2pFuncTagActionActionP2PFrame(prMgmtTxMsdu, + prActFrame, *(pucVendor + 4), u8Cookie); + else if (*(pucVendor + 3) == 0x0a) + /* found WFD IE */ + DBGLOG(P2P, INFO, "Found WFD IE, SA: " MACSTR + " - DA: " MACSTR "\n", + MAC2STR(prActFrame->aucSrcAddr), + MAC2STR(prActFrame->aucDestAddr)); + else + DBGLOG(P2P, INFO, + "Found Other vendor 0x%x, SA: " MACSTR + " - DA: " MACSTR "\n", + *(pucVendor + 3), + MAC2STR(prActFrame->aucSrcAddr), + MAC2STR(prActFrame->aucDestAddr)); + } + return eCNNState; +} + +enum ENUM_P2P_CONNECT_STATE +p2pFuncTagActionCategoryFrame(IN struct MSDU_INFO *prMgmtTxMsdu, + struct WLAN_ACTION_FRAME *prActFrame, + IN uint8_t ucCategory, + IN uint64_t u8Cookie) +{ + uint8_t ucAction = 0; + enum ENUM_P2P_CONNECT_STATE eCNNState = P2P_CNN_NORMAL; + + DBGLOG(P2P, TRACE, + "Found WLAN_ACTION_%s, SA: " MACSTR + " BSSID: " MACSTR + " DA: " MACSTR ", u8Cookie: 0x%llx, SeqNO: %d\n", + actionToString(ucCategory), + MAC2STR(prActFrame->aucSrcAddr), + MAC2STR(prActFrame->aucBSSID), + MAC2STR(prActFrame->aucDestAddr), + u8Cookie, + prMgmtTxMsdu->ucTxSeqNum); + + if (ucCategory == WLAN_ACTION_PUBLIC) { + ucAction = prActFrame->ucAction; + eCNNState = p2pFuncTagActionActionFrame(prMgmtTxMsdu, + prActFrame, ucAction, u8Cookie); + } + return eCNNState; +} + +void p2pProcessActionResponse(IN struct ADAPTER *prAdapter, + enum ENUM_P2P_ACTION_FRAME_TYPE eType) +{ + u_int8_t fgIdle = FALSE; + + if (!prAdapter || !prAdapter->prP2pInfo) + return; + + switch (prAdapter->prP2pInfo->eConnState) { + case P2P_CNN_GO_NEG_REQ: + if (eType == P2P_GO_NEG_RESP) + fgIdle = TRUE; + break; + case P2P_CNN_GO_NEG_RESP: + if (eType == P2P_GO_NEG_CONF || eType == P2P_GO_NEG_REQ) + fgIdle = TRUE; + break; + case P2P_CNN_INVITATION_REQ: + if (eType == P2P_INVITATION_RESP) + fgIdle = TRUE; + break; + case P2P_CNN_DEV_DISC_REQ: + if (eType == P2P_DEV_DISC_RESP) + fgIdle = TRUE; + break; + case P2P_CNN_PROV_DISC_REQ: + if (eType == P2P_PROV_DISC_RESP) + fgIdle = TRUE; + break; + default: + break; + } + + DBGLOG(P2P, INFO, "eConnState: %d, eType: %d\n", + prAdapter->prP2pInfo->eConnState, eType); + + if (fgIdle) + prAdapter->prP2pInfo->eConnState = P2P_CNN_NORMAL; +} + +/* + * used to debug p2p mgmt frame: + * GO Nego Req + * GO Nego Res + * GO Nego Confirm + * GO Invite Req + * GO Invite Res + * Device Discoverability Req + * Device Discoverability Res + * Provision Discovery Req + * Provision Discovery Res + */ +enum ENUM_P2P_CONNECT_STATE +p2pFuncTagMgmtFrame(IN struct MSDU_INFO *prMgmtTxMsdu, + IN uint64_t u8Cookie) +{ + /* P_MSDU_INFO_T prTxMsduInfo = (P_MSDU_INFO_T)NULL; */ + struct WLAN_MAC_HEADER *prWlanHdr = (struct WLAN_MAC_HEADER *) NULL; + struct WLAN_BEACON_FRAME *prProbRspHdr = + (struct WLAN_BEACON_FRAME *)NULL; + uint16_t u2TxFrameCtrl; + struct WLAN_ACTION_FRAME *prActFrame; + uint8_t ucCategory; + enum ENUM_P2P_CONNECT_STATE eCNNState = P2P_CNN_NORMAL; + + prWlanHdr = (struct WLAN_MAC_HEADER *) + ((unsigned long) prMgmtTxMsdu->prPacket + + MAC_TX_RESERVED_FIELD); + /* + * mgmt frame MASK_FC_TYPE = 0 + * use MASK_FRAME_TYPE is oK for frame type/subtype judge + */ + u2TxFrameCtrl = prWlanHdr->u2FrameCtrl & MASK_FRAME_TYPE; + + switch (u2TxFrameCtrl) { + case MAC_FRAME_PROBE_RSP: + prProbRspHdr = (struct WLAN_BEACON_FRAME *) prWlanHdr; + DBGLOG(P2P, INFO, + "TX Probe Response, SA: " MACSTR + " BSSID: " MACSTR + " DA: " MACSTR ", cookie: 0x%llx, seqNo: %d\n", + MAC2STR(prProbRspHdr->aucSrcAddr), + MAC2STR(prProbRspHdr->aucBSSID), + MAC2STR(prProbRspHdr->aucDestAddr), + u8Cookie, + prMgmtTxMsdu->ucTxSeqNum); + + break; + + case MAC_FRAME_ACTION: + prActFrame = (struct WLAN_ACTION_FRAME *)prWlanHdr; + ucCategory = prActFrame->ucCategory; + eCNNState = p2pFuncTagActionCategoryFrame(prMgmtTxMsdu, + prActFrame, ucCategory, u8Cookie); + + break; + default: + DBGLOG(P2P, INFO, + "Untagged frame type: 0x%x, A1: " MACSTR + ", A2: " MACSTR + ", A3: " MACSTR " seqNo: %d\n", + u2TxFrameCtrl, + MAC2STR(prWlanHdr->aucAddr1), + MAC2STR(prWlanHdr->aucAddr2), + MAC2STR(prWlanHdr->aucAddr3), + prMgmtTxMsdu->ucTxSeqNum); + break; + } + return eCNNState; +} + +uint32_t +p2pFuncTxMgmtFrame(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct MSDU_INFO *prMgmtTxMsdu, + IN u_int8_t fgNonCckRate) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + /* P_MSDU_INFO_T prTxMsduInfo = (P_MSDU_INFO_T)NULL; */ + struct WLAN_MAC_HEADER *prWlanHdr = (struct WLAN_MAC_HEADER *) NULL; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + uint8_t ucRetryLimit = 30; /* TX_DESC_TX_COUNT_NO_LIMIT; */ + u_int8_t fgDrop = FALSE; + struct BSS_INFO *prBssInfo; + uint64_t *pu8GlCookie = (uint64_t *) NULL; + uint64_t u8GlCookie; + enum ENUM_P2P_CONNECT_STATE eConnState = P2P_CNN_NORMAL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + /* Drop this frame if BSS inactive */ + if (!IS_NET_ACTIVE(prAdapter, ucBssIndex)) { + p2pDevFsmRunEventMgmtFrameTxDone(prAdapter, + prMgmtTxMsdu, TX_RESULT_INACTIVE_BSS); + cnmMgtPktFree(prAdapter, prMgmtTxMsdu); + fgDrop = TRUE; + break; + } + pu8GlCookie = + (uint64_t *) ((unsigned long) prMgmtTxMsdu->prPacket + + (unsigned long) prMgmtTxMsdu->u2FrameLength + + MAC_TX_RESERVED_FIELD); + + u8GlCookie = *pu8GlCookie; + + prWlanHdr = (struct WLAN_MAC_HEADER *) + ((unsigned long) prMgmtTxMsdu->prPacket + + MAC_TX_RESERVED_FIELD); + prStaRec = cnmGetStaRecByAddress(prAdapter, + ucBssIndex, prWlanHdr->aucAddr1); + /* prMgmtTxMsdu->ucBssIndex = ucBssIndex; */ + + switch (prWlanHdr->u2FrameCtrl & MASK_FRAME_TYPE) { + case MAC_FRAME_PROBE_RSP: + DBGLOG(P2P, TRACE, "TX Probe Resposne Frame\n"); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex); + if ((!nicTxIsMgmtResourceEnough(prAdapter)) + || (prBssInfo->fgIsNetAbsent)) { + DBGLOG(P2P, INFO, + "Drop Tx probe response due to resource issue\n"); + fgDrop = TRUE; + + break; + } + prMgmtTxMsdu->ucStaRecIndex = + (prStaRec != NULL) + ? (prStaRec->ucIndex) : (STA_REC_INDEX_NOT_FOUND); + DBGLOG(P2P, TRACE, + "Dump probe response content from supplicant.\n"); + if (aucDebugModule[DBG_P2P_IDX] & DBG_CLASS_TRACE) { + dumpMemory8((uint8_t *) prMgmtTxMsdu->prPacket, + (uint32_t) prMgmtTxMsdu->u2FrameLength); + } + + /* Modifiy Lie time to 100 mS due + * to the STA only wait 30-50mS + */ + /* and AP do not need send it after STA left */ + nicTxSetPktLifeTime(prMgmtTxMsdu, 100); + prMgmtTxMsdu = p2pFuncProcessP2pProbeRsp(prAdapter, + ucBssIndex, prMgmtTxMsdu); + + /* + * Not check prMsduInfo sanity + * as p2pFuncProcessP2pProbeRsp will always + * return a MsduInfo + */ + pu8GlCookie = + (uint64_t *) ((unsigned long) + prMgmtTxMsdu->prPacket + + (unsigned long) + prMgmtTxMsdu->u2FrameLength + + MAC_TX_RESERVED_FIELD); + /* Restore cookie as it will be corrupted + * in p2pFuncProcessP2pProbeRsp + */ + *pu8GlCookie = u8GlCookie; + ucRetryLimit = 6; + DBGLOG(P2P, TRACE, + "Dump probe response content to FW.\n"); + if (aucDebugModule[DBG_P2P_IDX] & DBG_CLASS_TRACE) { + dumpMemory8((uint8_t *) prMgmtTxMsdu->prPacket, + (uint32_t) prMgmtTxMsdu->u2FrameLength); + } + break; + default: + prMgmtTxMsdu->ucBssIndex = ucBssIndex; + break; + } + + if (fgDrop) { + /* Drop this frame */ + p2pDevFsmRunEventMgmtFrameTxDone(prAdapter, + prMgmtTxMsdu, TX_RESULT_DROPPED_IN_DRIVER); + cnmMgtPktFree(prAdapter, prMgmtTxMsdu); + + break; + } + + TX_SET_MMPDU(prAdapter, + prMgmtTxMsdu, + prMgmtTxMsdu->ucBssIndex, + (prStaRec != NULL) + ? (prStaRec->ucIndex) : (STA_REC_INDEX_NOT_FOUND), + WLAN_MAC_MGMT_HEADER_LEN, + prMgmtTxMsdu->u2FrameLength, + p2pDevFsmRunEventMgmtFrameTxDone, + MSDU_RATE_MODE_AUTO); + + nicTxSetPktRetryLimit(prMgmtTxMsdu, ucRetryLimit); + + eConnState = p2pFuncTagMgmtFrame(prMgmtTxMsdu, u8GlCookie); + + if (p2pFuncNeedWaitRsp(prAdapter, + prAdapter->prP2pInfo->eConnState)) + prAdapter->prP2pInfo->eConnState = eConnState; + + /* Bufferable MMPDUs are suggested to be queued */ + /* when GC is sleeping according to SPEC, */ + /* instead of being sent to ALTX Q. */ + + /* GO discoverability REQ needs to be sent to GC */ + /* when GC is awake due to P2P-6.1.10 cert fail */ + + if (!p2pFuncIsBufferableMMPDU(prAdapter, + eConnState, prMgmtTxMsdu)) + nicTxConfigPktControlFlag(prMgmtTxMsdu, + MSDU_CONTROL_FLAG_FORCE_TX, TRUE); + + nicTxEnqueueMsdu(prAdapter, prMgmtTxMsdu); + + + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncTxMgmtFrame */ + +void p2pFuncStopComplete(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo) +{ + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); + + DBGLOG(P2P, TRACE, "p2pFuncStopComplete\n"); + + /* GO: It would stop Beacon TX. + * GC: Stop all BSS related PS function. + */ + nicPmIndicateBssAbort(prAdapter, prP2pBssInfo->ucBssIndex); + /* Reset RLM related field of BSSINFO. */ + rlmBssAborted(prAdapter, prP2pBssInfo); + + UNSET_NET_ACTIVE(prAdapter, prP2pBssInfo->ucBssIndex); + nicDeactivateNetwork(prAdapter, prP2pBssInfo->ucBssIndex); + /* Release CNM channel */ + nicUpdateBss(prAdapter, prP2pBssInfo->ucBssIndex); + + /* Reset current OPMode */ + prP2pBssInfo->eCurrentOPMode = OP_MODE_INFRASTRUCTURE; + + /* Point StaRecOfAP to NULL when GC role stop Complete */ + prP2pBssInfo->prStaRecOfAP = NULL; + + kalP2pNotifyStopApComplete(prAdapter, + prP2pBssInfo->u4PrivateData); + } while (FALSE); + +} /* p2pFuncStopComplete */ + +/*---------------------------------------------------------------------------*/ +/*! + * @brief This function will start a P2P Group Owner and send Beacon Frames. + * + * @param (none) + * + * @return (none) + */ +/*---------------------------------------------------------------------------*/ +void +p2pFuncStartGO(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct P2P_CONNECTION_REQ_INFO *prP2pConnReqInfo, + IN struct P2P_CHNL_REQ_INFO *prP2pChnlReqInfo) +{ +#if (CFG_SUPPORT_DFS_MASTER == 1) + struct CMD_RDD_ON_OFF_CTRL *prCmdRddOnOffCtrl; +#endif + + do { + ASSERT_BREAK((prAdapter != NULL) && (prBssInfo != NULL)); + + if (prBssInfo->ucBssIndex >= prAdapter->ucHwBssIdNum) { + DBGLOG(P2P, ERROR, + "P2P BSS exceed the number of P2P interface number."); + ASSERT(FALSE); + break; + } + + DBGLOG(P2P, TRACE, "p2pFuncStartGO:\n"); + +#if (CFG_SUPPORT_DFS_MASTER == 1) + prCmdRddOnOffCtrl = (struct CMD_RDD_ON_OFF_CTRL *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(*prCmdRddOnOffCtrl)); + + if (!prCmdRddOnOffCtrl) { + break; + } + + prCmdRddOnOffCtrl->ucDfsCtrl = RDD_START_TXQ; + + /* + * FIX ME: Mobile driver can't get correct band. + * There is only 5G in DFS channel, + * which is on band_0. So it assigned to ENUM_BAND_0 + * as temp solution. + * Remember to fix it when driver could get + * the correct band from firmware. + */ + prCmdRddOnOffCtrl->ucRddIdx = ENUM_BAND_0; + + DBGLOG(P2P, INFO, + "p2pFuncStartGO: Start TXQ - DFS ctrl: %.d\n", + prCmdRddOnOffCtrl->ucDfsCtrl); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_RDD_ON_OFF_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(*prCmdRddOnOffCtrl), + (uint8_t *) prCmdRddOnOffCtrl, NULL, 0); + + cnmMemFree(prAdapter, prCmdRddOnOffCtrl); +#endif + + /* Re-start AP mode. */ + p2pFuncSwitchOPMode(prAdapter, + prBssInfo, prBssInfo->eIntendOPMode, FALSE); + + prBssInfo->eIntendOPMode = OP_MODE_NUM; + + /* 4 <1.1> Assign SSID */ + COPY_SSID(prBssInfo->aucSSID, + prBssInfo->ucSSIDLen, + prP2pConnReqInfo->rSsidStruct.aucSsid, + prP2pConnReqInfo->rSsidStruct.ucSsidLen); + + DBGLOG(P2P, TRACE, "GO SSID:%s\n", HIDE(prBssInfo->aucSSID)); + + /* 4 <1.2> Clear current AP's STA_RECORD_T and current AID */ + prBssInfo->prStaRecOfAP = (struct STA_RECORD *) NULL; + prBssInfo->u2AssocId = 0; + + /* 4 <1.3> Setup Channel, Band and Phy Attributes */ + prBssInfo->ucPrimaryChannel = prP2pChnlReqInfo->ucReqChnlNum; + prBssInfo->eBand = prP2pChnlReqInfo->eBand; + prBssInfo->eBssSCO = prP2pChnlReqInfo->eChnlSco; + + DBGLOG(P2P, TRACE, + "GO Channel:%d\n", + prBssInfo->ucPrimaryChannel); + + if (prBssInfo->eBand == BAND_5G) { + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet |= PHY_TYPE_SET_802_11A; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_11A; + } else if (prP2pConnReqInfo->eConnRequest + == P2P_CONNECTION_TYPE_PURE_AP) { + prBssInfo->ucPhyTypeSet |= PHY_TYPE_SET_802_11BG; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; + } else { + ASSERT(prP2pConnReqInfo->eConnRequest + == P2P_CONNECTION_TYPE_GO); + prBssInfo->ucPhyTypeSet |= PHY_TYPE_SET_802_11G; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_11G_P2P; + } + + /* Overwrite BSS PHY type set by Feature Options */ + bssDetermineApBssInfoPhyTypeSet(prAdapter, + (prP2pConnReqInfo->eConnRequest == + P2P_CONNECTION_TYPE_PURE_AP) ? TRUE : FALSE, prBssInfo); + + DBGLOG(P2P, TRACE, "Phy type: 0x%x\n", prBssInfo->ucPhyTypeSet); + + prBssInfo->ucNonHTBasicPhyType = (uint8_t) + 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 + prBssInfo->fgIsProtection = FALSE; + if (prP2pConnReqInfo->eConnRequest == P2P_CONNECTION_TYPE_GO) { + /* Always enable protection at P2P GO */ + prBssInfo->fgIsProtection = TRUE; + } else { + ASSERT(prP2pConnReqInfo->eConnRequest + == P2P_CONNECTION_TYPE_PURE_AP); + if (kalP2PGetCipher(prAdapter->prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData)) + prBssInfo->fgIsProtection = TRUE; + } + + bssInitForAP(prAdapter, prBssInfo, TRUE); + +#if 0 + if (prBssInfo->ucBMCWlanIndex >= WTBL_SIZE) { + prBssInfo->ucBMCWlanIndex = + secPrivacySeekForBcEntry(prAdapter, + prBssInfo->ucBssIndex, + prBssInfo->aucBSSID, 0xff, + CIPHER_SUITE_NONE, 0xff); + } +#endif + nicQmUpdateWmmParms(prAdapter, prBssInfo->ucBssIndex); +#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, prBssInfo->ucBssIndex); + + /* 4 <3.3> Update Beacon again + * for network phy type confirmed. + */ + bssUpdateBeaconContent(prAdapter, prBssInfo->ucBssIndex); + + /* 4 <3.4> Setup BSSID */ + nicPmIndicateBssCreated(prAdapter, prBssInfo->ucBssIndex); + + } while (FALSE); +} /* p2pFuncStartGO() */ + +void p2pFuncStopGO(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo) +{ + uint32_t u4ClientCount = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); + + DBGLOG(P2P, TRACE, "p2pFuncStopGO\n"); + + u4ClientCount = bssGetClientCount(prAdapter, prP2pBssInfo); + + if ((prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) + && (prP2pBssInfo->eIntendOPMode == OP_MODE_NUM)) { + /* AP is created, Beacon Updated. */ + p2pFuncDissolve(prAdapter, + prP2pBssInfo, TRUE, + REASON_CODE_DEAUTH_LEAVING_BSS); + prP2pBssInfo->eIntendOPMode = OP_MODE_P2P_DEVICE; + } + + /* Do not Deactivate Network if any Client existed, + * we'll deactive it after Deauth Tx done + */ + if (u4ClientCount == 0) { + DBGLOG(P2P, INFO, + "No client! Deactive GO immediately.\n"); + p2pChangeMediaState(prAdapter, + prP2pBssInfo, MEDIA_STATE_DISCONNECTED); + p2pFuncStopComplete(prAdapter, prP2pBssInfo); + } + + } while (FALSE); + +} /* p2pFuncStopGO */ + +uint32_t p2pFuncRoleToBssIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucRoleIdx, OUT uint8_t *pucBssIdx) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBssIdx != NULL)); + + if (ucRoleIdx >= BSS_P2P_NUM) { + rWlanStatus = WLAN_STATUS_FAILURE; + break; + } + if (!prAdapter->rWifiVar.aprP2pRoleFsmInfo[ucRoleIdx]) { + DBGLOG(P2P, WARN, + "%s, invalid aprP2pRoleFsmInfo, ignore\n", + __func__); + rWlanStatus = WLAN_STATUS_FAILURE; + } else + *pucBssIdx = prAdapter->rWifiVar + .aprP2pRoleFsmInfo[ucRoleIdx]->ucBssIndex; + + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncRoleToBssIdx */ + +struct P2P_ROLE_FSM_INFO *p2pFuncGetRoleByBssIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + int32_t i = 0; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL)); + + for (i = 0 ; i < BSS_P2P_NUM; i++) { + if (!prAdapter->rWifiVar.aprP2pRoleFsmInfo[i]) + continue; + + if (prAdapter->rWifiVar.aprP2pRoleFsmInfo[i]->ucBssIndex + == ucBssIndex) + break; + } + if (i < BSS_P2P_NUM) + prP2pRoleFsmInfo = + prAdapter->rWifiVar.aprP2pRoleFsmInfo[i]; + + } while (FALSE); + + return prP2pRoleFsmInfo; +} + + +void +p2pFuncSwitchOPMode(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN enum ENUM_OP_MODE eOpMode, + IN u_int8_t 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 will be done + * in p2pFuncStopGO(). + */ + /* p2pFuncDissolve(prAdapter, + * prP2pBssInfo, TRUE, + * REASON_CODE_DEAUTH_LEAVING_BSS); + */ + if (prP2pBssInfo->eIntendOPMode + != OP_MODE_P2P_DEVICE) { + p2pFuncStopGO(prAdapter, prP2pBssInfo); + + SET_NET_PWR_STATE_IDLE(prAdapter, + prP2pBssInfo->ucBssIndex); + } + break; + default: + break; + } + + prP2pBssInfo->eIntendOPMode = eOpMode; + + /* The state is in disconnecting and + * can not change any BSS status + */ + if (IS_NET_PWR_STATE_IDLE(prAdapter, + prP2pBssInfo->ucBssIndex) && + IS_NET_ACTIVE(prAdapter, + prP2pBssInfo->ucBssIndex)) { + DBGLOG(P2P, TRACE, + "under deauth procedure, Quit.\n"); + break; + } + + prP2pBssInfo->eCurrentOPMode = eOpMode; + switch (eOpMode) { + case OP_MODE_INFRASTRUCTURE: + DBGLOG(P2P, TRACE, + "p2pFuncSwitchOPMode: Switch to Client.\n"); + /* fall through */ + case OP_MODE_ACCESS_POINT: + /* Change interface address. */ + if (eOpMode == OP_MODE_ACCESS_POINT) { + DBGLOG(P2P, TRACE, + "p2pFuncSwitchOPMode: Switch to AP.\n"); + prP2pBssInfo->ucSSIDLen = 0; + } + +#if CFG_DUAL_P2PLIKE_INTERFACE + /*avoid ap1 Bss have diff A2 & A3, */ + /*ToDo : fix for P2P case*/ + +#else + COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, + prAdapter->rWifiVar + .aucInterfaceAddress[ + prP2pBssInfo->u4PrivateData]); + COPY_MAC_ADDR(prP2pBssInfo->aucBSSID, + prAdapter->rWifiVar + .aucInterfaceAddress[ + prP2pBssInfo->u4PrivateData]); +#endif + break; + case OP_MODE_P2P_DEVICE: + { + /* Change device address. */ + DBGLOG(P2P, TRACE, + "p2pFuncSwitchOPMode: Switch back to P2P Device.\n"); + + p2pChangeMediaState(prAdapter, + prP2pBssInfo, + MEDIA_STATE_DISCONNECTED); + + COPY_MAC_ADDR( + prP2pBssInfo->aucOwnMacAddr, + prAdapter->rWifiVar + .aucDeviceAddress); + COPY_MAC_ADDR( + prP2pBssInfo->aucBSSID, + prAdapter->rWifiVar + .aucDeviceAddress); + + } + break; + default: + ASSERT(FALSE); + break; + } + + if (1) { + struct P2P_DISCONNECT_INFO rP2PDisInfo; + + rP2PDisInfo.ucRole = 2; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_P2P_ABORT, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct P2P_DISCONNECT_INFO), + (uint8_t *) &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, + prP2pBssInfo->ucBssIndex); + } else if (prP2pBssInfo->eCurrentOPMode == eOpMode && + eOpMode == OP_MODE_INFRASTRUCTURE) { + /* + * Sometimes the interface is changed from P2P_CLIENT + * to STATION, but GC's connection flow is still in + * processing. We must force stop previous connection + * request to avoid unexpected behavior. + */ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct P2P_CONNECTION_REQ_INFO *prConnReqInfo = + (struct P2P_CONNECTION_REQ_INFO *) NULL; + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO( + prAdapter, prP2pBssInfo->u4PrivateData); + if (prP2pRoleFsmInfo == NULL) + break; + + prConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + if (prConnReqInfo == NULL) + break; + + if (prConnReqInfo->eConnRequest == + P2P_CONNECTION_TYPE_GC) { + log_dbg(P2P, INFO, "Force stop connection request since mode switch.\n"); + prConnReqInfo->eConnRequest = + P2P_CONNECTION_TYPE_IDLE; + p2pRoleFsmRunEventAbort(prAdapter, + prP2pRoleFsmInfo); + } + } + + } while (FALSE); +} /* p2pFuncSwitchOPMode */ + +/*---------------------------------------------------------------------------*/ +/*! + * \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 struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo) +{ + struct MSG_CH_ABORT *prMsgChRelease = (struct MSG_CH_ABORT *) NULL; + + DEBUGFUNC("p2pFuncReleaseCh()"); + + do { + ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL)); + + if (!prChnlReqInfo->fgIsChannelRequested) + break; + DBGLOG(P2P, TRACE, "P2P Release Channel\n"); + prChnlReqInfo->fgIsChannelRequested = FALSE; + + /* 1. return channel privilege to CNM immediately */ + prMsgChRelease = (struct MSG_CH_ABORT *) + cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(struct MSG_CH_ABORT)); + if (!prMsgChRelease) { + break; + } + + prMsgChRelease->rMsgHdr.eMsgId = MID_MNY_CNM_CH_ABORT; + prMsgChRelease->ucBssIndex = ucBssIdx; + prMsgChRelease->ucTokenID = prChnlReqInfo->ucSeqNumOfChReq++; +#if CFG_SUPPORT_DBDC + prMsgChRelease->eDBDCBand = ENUM_BAND_AUTO; + + DBGLOG(P2P, INFO, + "p2pFuncReleaseCh: P2P abort channel on band %u.\n", + prMsgChRelease->eDBDCBand); +#endif /*CFG_SUPPORT_DBDC*/ + mboxSendMsg(prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prMsgChRelease, + MSG_SEND_METHOD_BUF); + + } while (FALSE); +} /* p2pFuncReleaseCh */ + +/*---------------------------------------------------------------------------*/ +/*! + * @brief Process of CHANNEL_REQ_JOIN Initial. Enter CHANNEL_REQ_JOIN State. + * + * @param (none) + * + * @return (none) + */ +/*---------------------------------------------------------------------------*/ +void p2pFuncAcquireCh(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo) +{ + struct MSG_CH_REQ *prMsgChReq = (struct MSG_CH_REQ *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL)); + + p2pFuncReleaseCh(prAdapter, ucBssIdx, prChnlReqInfo); + + /* send message to CNM for acquiring channel */ + prMsgChReq = (struct MSG_CH_REQ *) + cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(struct MSG_CH_REQ)); + + if (!prMsgChReq) { + /* Can't indicate CNM for channel acquiring */ + break; + } + + prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; + prMsgChReq->ucBssIndex = ucBssIdx; + prMsgChReq->ucTokenID = ++prChnlReqInfo->ucSeqNumOfChReq; + prMsgChReq->eReqType = prChnlReqInfo->eChnlReqType; + prMsgChReq->u4MaxInterval = prChnlReqInfo->u4MaxInterval; + prMsgChReq->ucPrimaryChannel = prChnlReqInfo->ucReqChnlNum; + prMsgChReq->eRfSco = prChnlReqInfo->eChnlSco; + prMsgChReq->eRfBand = prChnlReqInfo->eBand; + prMsgChReq->eRfChannelWidth = prChnlReqInfo->eChannelWidth; + prMsgChReq->ucRfCenterFreqSeg1 = prChnlReqInfo->ucCenterFreqS1; + prMsgChReq->ucRfCenterFreqSeg2 = prChnlReqInfo->ucCenterFreqS2; +#if CFG_SUPPORT_DBDC + prMsgChReq->eDBDCBand = ENUM_BAND_AUTO; + + DBGLOG(P2P, INFO, + "p2pFuncAcquireCh: P2P Request channel on band %u, tokenID: %d, cookie: 0x%llx.\n", + prMsgChReq->eDBDCBand, + prMsgChReq->ucTokenID, + prChnlReqInfo->u8Cookie); + +#endif /*CFG_SUPPORT_DBDC*/ + /* Channel request join BSSID. */ + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prMsgChReq, + MSG_SEND_METHOD_BUF); + + prChnlReqInfo->fgIsChannelRequested = TRUE; + + } while (FALSE); +} /* p2pFuncAcquireCh */ + +#if (CFG_SUPPORT_DFS_MASTER == 1) +void p2pFuncStartRdd(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIdx) +{ + struct CMD_RDD_ON_OFF_CTRL *prCmdRddOnOffCtrl; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + uint8_t ucReqChnlNum; + + DEBUGFUNC("p2pFuncStartRdd()"); + + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prAdapter->aprBssInfo[ucBssIdx]->u4PrivateData); + + ucReqChnlNum = prP2pRoleFsmInfo->rChnlReqInfo.ucReqChnlNum; + + prCmdRddOnOffCtrl = (struct CMD_RDD_ON_OFF_CTRL *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(*prCmdRddOnOffCtrl)); + + if (!prCmdRddOnOffCtrl) { + DBGLOG(P2P, ERROR, + "cnmMemAlloc for prCmdRddOnOffCtrl failed!\n"); + return; + } + + prCmdRddOnOffCtrl->ucDfsCtrl = RDD_START; + + /* + * FIX ME: Mobile driver can't get correct band. + * There is only 5G in DFS channel, + * which is on band_0. So it assigned to ENUM_BAND_0 as temp solution. + * Remember to fix it when driver could get + * the correct band from firmware. + */ + prCmdRddOnOffCtrl->ucRddIdx = ENUM_BAND_0; + +#if (CFG_SUPPORT_SINGLE_SKU == 1) + if (rlmDomainGetDfsRegion() == NL80211_DFS_JP) { + if (ucReqChnlNum >= 52 && ucReqChnlNum <= 64) + prCmdRddOnOffCtrl->ucSetVal = REG_JP_53; + else if (ucReqChnlNum >= 100 && ucReqChnlNum <= 140) + prCmdRddOnOffCtrl->ucSetVal = REG_JP_56; + } else { + prCmdRddOnOffCtrl->ucSetVal = REG_DEFAULT; + } +#else + prCmdRddOnOffCtrl->ucSetVal = REG_DEFAULT; +#endif + + if (prCmdRddOnOffCtrl->ucRddIdx) + prCmdRddOnOffCtrl->ucRddRxSel = RDD_IN_SEL_1; + else + prCmdRddOnOffCtrl->ucRddRxSel = RDD_IN_SEL_0; + + DBGLOG(P2P, INFO, + "p2pFuncStartRdd: Start Radar detection - DFS ctrl: %d, RDD index: %d\n", + prCmdRddOnOffCtrl->ucDfsCtrl, prCmdRddOnOffCtrl->ucRddIdx); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_RDD_ON_OFF_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(*prCmdRddOnOffCtrl), + (uint8_t *) prCmdRddOnOffCtrl, NULL, 0); + + cnmMemFree(prAdapter, prCmdRddOnOffCtrl); +} /* p2pFuncStartRdd */ + +void p2pFuncStopRdd(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIdx) +{ + struct CMD_RDD_ON_OFF_CTRL *prCmdRddOnOffCtrl; + + DEBUGFUNC("p2pFuncStopRdd()"); + + prCmdRddOnOffCtrl = (struct CMD_RDD_ON_OFF_CTRL *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(*prCmdRddOnOffCtrl)); + + if (!prCmdRddOnOffCtrl) { + DBGLOG(P2P, ERROR, + "cnmMemAlloc for prCmdRddOnOffCtrl failed!\n"); + return; + } + + prCmdRddOnOffCtrl->ucDfsCtrl = RDD_STOP; + + /* + * FIX ME: Mobile driver can't get correct band. + * There is only 5G in DFS channel, + * which is on band_0. So it assigned to ENUM_BAND_0 as temp solution. + * Remember to fix it when driver could get + * the correct band from firmware. + */ + prCmdRddOnOffCtrl->ucRddIdx = ENUM_BAND_0; + + if (prCmdRddOnOffCtrl->ucRddIdx) + prCmdRddOnOffCtrl->ucRddRxSel = RDD_IN_SEL_1; + else + prCmdRddOnOffCtrl->ucRddRxSel = RDD_IN_SEL_0; + + DBGLOG(P2P, INFO, + "p2pFuncStopRdd: Stop Radar detection - DFS ctrl: %d, RDD index: %d\n", + prCmdRddOnOffCtrl->ucDfsCtrl, prCmdRddOnOffCtrl->ucRddIdx); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_RDD_ON_OFF_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(*prCmdRddOnOffCtrl), + (uint8_t *) prCmdRddOnOffCtrl, NULL, 0); + + cnmMemFree(prAdapter, prCmdRddOnOffCtrl); + +} /* p2pFuncStopRdd */ + + +void p2pFuncDfsSwitchCh(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct P2P_CHNL_REQ_INFO rP2pChnlReqInfo) +{ + + struct GLUE_INFO *prGlueInfo; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct CMD_RDD_ON_OFF_CTRL *prCmdRddOnOffCtrl; + uint8_t role_idx = 0; + u_int8_t fgIsCrossBand = FALSE; + + DEBUGFUNC("p2pFuncDfsSwitchCh()"); + + if (!prBssInfo) { + DBGLOG(P2P, ERROR, "prBssInfo shouldn't be NULL!\n"); + return; + } + + if (prBssInfo->eBand != rP2pChnlReqInfo.eBand) + fgIsCrossBand = TRUE; + + /* Setup Channel, Band */ + prBssInfo->ucPrimaryChannel = rP2pChnlReqInfo.ucReqChnlNum; + prBssInfo->eBand = rP2pChnlReqInfo.eBand; + prBssInfo->eBssSCO = rP2pChnlReqInfo.eChnlSco; + +/* To Support Cross Band Channel Swtich */ +#if CFG_SUPPORT_IDC_CH_SWITCH + if (prBssInfo->eBand == BAND_5G) { + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet |= PHY_TYPE_SET_802_11A; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_11A; + } else { /* Only SAP mode should enter this function */ + prBssInfo->ucPhyTypeSet |= PHY_TYPE_SET_802_11BG; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; + } + + /* Overwrite BSS PHY type set by Feature Options */ + bssDetermineApBssInfoPhyTypeSet(prAdapter, + TRUE, prBssInfo); + + prBssInfo->ucNonHTBasicPhyType = (uint8_t) + rNonHTApModeAttributes + [prBssInfo->ucConfigAdHocAPMode] + .ePhyTypeIndex; + prBssInfo->u2BSSBasicRateSet = + rNonHTApModeAttributes + [prBssInfo->ucConfigAdHocAPMode] + .u2BSSBasicRateSet; + prBssInfo->u2OperationalRateSet = + rNonHTPhyAttributes + [prBssInfo->ucNonHTBasicPhyType] + .u2SupportedRateSet; + kalMemZero(prBssInfo->aucAllSupportedRates, RATE_NUM_SW); + rateGetDataRatesFromRateSet( + prBssInfo->u2OperationalRateSet, + prBssInfo->u2BSSBasicRateSet, + prBssInfo->aucAllSupportedRates, + &prBssInfo->ucAllSupportedRatesLen); +#endif + + /* Setup channel and bandwidth */ + rlmBssInitForAPandIbss(prAdapter, prBssInfo); + + /* Update Beacon again for network phy type confirmed. */ + bssUpdateBeaconContent(prAdapter, prBssInfo->ucBssIndex); + + /* Reset HW TSF Update Mode and Beacon Mode */ + nicUpdateBss(prAdapter, prBssInfo->ucBssIndex); + + if (fgIsCrossBand) + nicPmIndicateBssCreated(prAdapter, + prBssInfo->ucBssIndex); + + prCmdRddOnOffCtrl = (struct CMD_RDD_ON_OFF_CTRL *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(*prCmdRddOnOffCtrl)); + + if (!prCmdRddOnOffCtrl) { + DBGLOG(P2P, ERROR, + "cnmMemAlloc for prCmdRddOnOffCtrl failed!\n"); + return; + } + + prCmdRddOnOffCtrl->ucDfsCtrl = RDD_START_TXQ; + + DBGLOG(P2P, TRACE, + "p2pFuncDfsSwitchCh: Start TXQ - DFS ctrl: %.d\n", + prCmdRddOnOffCtrl->ucDfsCtrl); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_RDD_ON_OFF_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(*prCmdRddOnOffCtrl), + (uint8_t *) prCmdRddOnOffCtrl, + NULL, 0); + + cnmMemFree(prAdapter, prCmdRddOnOffCtrl); + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prBssInfo->u4PrivateData); + + prGlueInfo = prAdapter->prGlueInfo; + role_idx = prP2pRoleFsmInfo->ucRoleIndex; + +#if CFG_SUPPORT_SAP_DFS_CHANNEL + wlanUpdateDfsChannelTable(prGlueInfo, + role_idx, + prBssInfo->ucPrimaryChannel, + prBssInfo->ucVhtChannelWidth, + prBssInfo->eBssSCO, + nicChannelNum2Freq(prBssInfo->ucVhtChannelFrequencyS1) / 1000); +#endif + + kalP2pIndicateChnlSwitch(prAdapter, prBssInfo); + + /* Down the flag */ + prAdapter->rWifiVar.ucChannelSwitchMode = 0; + + /* Check DBDC status */ + cnmDbdcRuntimeCheckDecision(prAdapter, prBssInfo->ucBssIndex); +} /* p2pFuncDfsSwitchCh */ + +u_int8_t p2pFuncCheckWeatherRadarBand( + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo) +{ + uint8_t ucReqChnlNum; + uint8_t ucCenterFreqS1; + enum ENUM_CHANNEL_WIDTH eChannelWidth; + enum ENUM_CHNL_EXT eChnlSco; + + + ucReqChnlNum = prChnlReqInfo->ucReqChnlNum; + ucCenterFreqS1 = prChnlReqInfo->ucCenterFreqS1; + eChannelWidth = prChnlReqInfo->eChannelWidth; + eChnlSco = prChnlReqInfo->eChnlSco; + +#if (CFG_SUPPORT_SINGLE_SKU == 1) + if (rlmDomainGetDfsRegion() == NL80211_DFS_ETSI) { + if (eChannelWidth == VHT_OP_CHANNEL_WIDTH_80) { + if (ucCenterFreqS1 >= 120 && ucCenterFreqS1 <= 128) + return TRUE; + } else { + if ((ucReqChnlNum >= 120 && ucReqChnlNum <= 128)) + return TRUE; + else if (ucReqChnlNum == 116 + && eChnlSco == CHNL_EXT_SCA) + return TRUE; /* ch116, 120 BW40 */ + } + } +#endif + + return FALSE; +} + +int32_t p2pFuncSetDriverCacTime(IN uint32_t u4CacTime) +{ + uint32_t i4Status = WLAN_STATUS_SUCCESS; + + g_u4DriverCacTime = u4CacTime; + + DBGLOG(P2P, INFO, + "p2pFuncSetDriverCacTime: g_u4ManualCacTime = %dsec\n", + g_u4DriverCacTime); + + return i4Status; +} + +void p2pFuncEnableManualCac(void) +{ + g_fgManualCac = TRUE; +} + +uint32_t p2pFuncGetDriverCacTime(void) +{ + return g_u4DriverCacTime; +} + +u_int8_t p2pFuncIsManualCac(void) +{ + return g_fgManualCac; +} + +void p2pFuncRadarInfoInit(void) +{ + kalMemZero(&g_rP2pRadarInfo, sizeof(g_rP2pRadarInfo)); +} + +void p2pFuncShowRadarInfo(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIdx) +{ + uint8_t ucCnt = 0; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + uint8_t ucReqChnlNum; + + if (g_rP2pRadarInfo.ucRadarReportMode == 1) { + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prAdapter->aprBssInfo[ucBssIdx]->u4PrivateData); + + ucReqChnlNum = prP2pRoleFsmInfo->rChnlReqInfo.ucReqChnlNum; + + DBGLOG(P2P, INFO, "-----Radar Detected Event-----\n"); + DBGLOG(P2P, INFO, + "Radar detected in DBDC band%d\n", + g_rP2pRadarInfo.ucRddIdx); + +#if (CFG_SUPPORT_SINGLE_SKU == 1) + switch (rlmDomainGetDfsRegion()) { + case NL80211_DFS_FCC: + DBGLOG(P2P, INFO, "Regulation domain: FCC\n"); + break; + case NL80211_DFS_ETSI: + DBGLOG(P2P, INFO, "Regulation domain: ETSI\n"); + break; + case NL80211_DFS_JP: + DBGLOG(P2P, INFO, "Regulation domain: JP\n"); + + if (ucReqChnlNum >= 52 && ucReqChnlNum <= 64) + DBGLOG(P2P, INFO, + "Radar type: W53 - %s\n", + p2pFuncJpW53RadarType()); + else if (ucReqChnlNum >= 100 && ucReqChnlNum <= 140) + DBGLOG(P2P, INFO, + "Radar type: W56 - %s\n", + p2pFuncJpW56RadarType()); + break; + default: + break; + } +#endif + + DBGLOG(P2P, INFO, "Radar Content:\n"); + + DBGLOG(P2P, INFO, "start time pulse width PRI\n"); + + if (g_rP2pRadarInfo.ucPeriodicDetected) { + DBGLOG(P2P, INFO, "%-10d %-11d -\n" + , g_rP2pRadarInfo.arPpbContent + [ucCnt].u4PeriodicStartTime + , g_rP2pRadarInfo.arPpbContent + [ucCnt].u2PeriodicPulseWidth); + + for (ucCnt = 1; + ucCnt < g_rP2pRadarInfo.ucPPBNum; ucCnt++) { + DBGLOG(P2P, INFO, "%-10d %-11d %d\n" + , g_rP2pRadarInfo.arPpbContent + [ucCnt].u4PeriodicStartTime + , g_rP2pRadarInfo.arPpbContent + [ucCnt].u2PeriodicPulseWidth + , (g_rP2pRadarInfo.arPpbContent + [ucCnt].u4PeriodicStartTime + - g_rP2pRadarInfo.arPpbContent + [ucCnt-1].u4PeriodicStartTime) + * 2 / 5); + } + } else if (g_rP2pRadarInfo.ucLongDetected) { + DBGLOG(P2P, INFO, "%-10d %-11d -\n" + , g_rP2pRadarInfo.arLpbContent + [ucCnt].u4LongStartTime + , g_rP2pRadarInfo.arLpbContent + [ucCnt].u2LongPulseWidth); + + for (ucCnt = 1; + ucCnt < g_rP2pRadarInfo.ucLPBNum; ucCnt++) { + DBGLOG(P2P, INFO, "%-10d %-11d %d\n" + , g_rP2pRadarInfo.arLpbContent + [ucCnt].u4LongStartTime + , g_rP2pRadarInfo.arLpbContent + [ucCnt].u2LongPulseWidth + , (g_rP2pRadarInfo.arLpbContent + [ucCnt].u4LongStartTime + - g_rP2pRadarInfo.arLpbContent + [ucCnt-1].u4LongStartTime) + * 2 / 5); + } + } + } +} + +void p2pFuncGetRadarInfo(IN struct P2P_RADAR_INFO *prP2pRadarInfo) +{ + kalMemCopy(prP2pRadarInfo, &g_rP2pRadarInfo, sizeof(*prP2pRadarInfo)); +} + +uint8_t *p2pFuncJpW53RadarType(void) +{ + uint32_t u4Type1Diff; + uint32_t u4Type2Diff; + + if (g_rP2pRadarInfo.u4PRI1stUs >= 1428) + u4Type1Diff = g_rP2pRadarInfo.u4PRI1stUs - 1428; + else + u4Type1Diff = 1428 - g_rP2pRadarInfo.u4PRI1stUs; + + if (g_rP2pRadarInfo.u4PRI1stUs >= 3846) + u4Type2Diff = g_rP2pRadarInfo.u4PRI1stUs - 3846; + else + u4Type2Diff = 3846 - g_rP2pRadarInfo.u4PRI1stUs; + + if (u4Type1Diff < u4Type2Diff) + return apucW53RadarType[1]; + else + return apucW53RadarType[2]; +} + +uint8_t *p2pFuncJpW56RadarType(void) +{ + uint32_t u4Type1Diff; + uint32_t u4Type2Diff; + + if (g_rP2pRadarInfo.ucLongDetected) + return apucW56RadarType[7]; + + if (g_rP2pRadarInfo.u4PRI1stUs >= 3980 + && g_rP2pRadarInfo.u4PRI1stUs <= 4020) + return apucW56RadarType[3]; + + if (g_rP2pRadarInfo.u4PRI1stUs >= 1368 + && g_rP2pRadarInfo.u4PRI1stUs <= 1448) { + + if (g_rP2pRadarInfo.u4PRI1stUs >= 1388) + u4Type1Diff = g_rP2pRadarInfo.u4PRI1stUs - 1388; + else + u4Type1Diff = 1388 - g_rP2pRadarInfo.u4PRI1stUs; + + if (g_rP2pRadarInfo.u4PRI1stUs >= 1428) + u4Type2Diff = g_rP2pRadarInfo.u4PRI1stUs - 1428; + else + u4Type2Diff = 1428 - g_rP2pRadarInfo.u4PRI1stUs; + + if (u4Type1Diff < u4Type2Diff) + return apucW56RadarType[1]; + else + return apucW56RadarType[2]; + + } + + if (g_rP2pRadarInfo.u4PRI1stUs >= 130 + && g_rP2pRadarInfo.u4PRI1stUs < 200) + return apucW56RadarType[4]; + + if (g_rP2pRadarInfo.u4PRI1stUs >= 200 + && g_rP2pRadarInfo.u4PRI1stUs <= 520) { + + if (g_rP2pRadarInfo.u4PRI1stUs <= 230) + return apucW56RadarType[9]; + + if (g_rP2pRadarInfo.u4PRI1stUs >= 323 + && g_rP2pRadarInfo.u4PRI1stUs <= 343) + return apucW56RadarType[10]; + + return apucW56RadarType[11]; + } + + return apucW56RadarType[0]; +} + +void p2pFuncSetRadarDetectMode(IN uint8_t ucRadarDetectMode) +{ + g_ucRadarDetectMode = ucRadarDetectMode; + + DBGLOG(P2P, INFO, + "p2pFuncSetRadarDetectMode: g_ucRadarDetectMode: %d\n", + g_ucRadarDetectMode); +} + +uint8_t p2pFuncGetRadarDetectMode(void) +{ + return g_ucRadarDetectMode; +} + +void p2pFuncSetDfsState(IN uint8_t ucDfsState) +{ + DBGLOG(P2P, INFO, + "[DFS_STATE] TRANSITION: [%s] -> [%s]\n", + apucDfsState[g_ucDfsState], apucDfsState[ucDfsState]); + + g_ucDfsState = ucDfsState; +} + +uint8_t p2pFuncGetDfsState(void) +{ + return g_ucDfsState; +} + +uint8_t *p2pFuncShowDfsState(void) +{ + return apucDfsState[g_ucDfsState]; +} + +void p2pFuncRecordCacStartBootTime(void) +{ + g_u4CacStartBootTime = kalGetBootTime(); +} + +uint32_t p2pFuncGetCacRemainingTime(void) +{ + uint32_t u4CurrentBootTime; + uint32_t u4CacRemainingTime; + + u4CurrentBootTime = kalGetBootTime(); + + u4CacRemainingTime = g_u4DriverCacTime - + (u4CurrentBootTime - g_u4CacStartBootTime)/1000000; + + return u4CacRemainingTime; +} +#endif + +#if 0 +uint32_t +p2pFuncBeaconUpdate(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBcnHdr, + IN uint32_t u4HdrLen, + IN uint8_t *pucBcnBody, + IN uint32_t u4BodyLen, + IN uint32_t u4DtimPeriod, + IN uint32_t u4BcnInterval) +{ + uint32_t rResultStatus = WLAN_STATUS_INVALID_DATA; + struct WLAN_BEACON_FRAME *prBcnFrame = + (struct WLAN_BEACON_FRAME *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct MSDU_INFO *prBcnMsduInfo = (struct MSDU_INFO *) NULL; + uint8_t *pucTIMBody = (uint8_t *) NULL; + uint16_t u2FrameLength = 0, uint16_t u2OldBodyLen = 0; + uint8_t 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. */ + uint16_t u2IELength = 0, u2Offset = 0; + uint8_t *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 = (uint16_t) ((uint32_t) pucTIMBody - + (uint32_t) prBcnFrame->aucInfoElem); + /* Move body. */ + kalMemCmp(aucIEBuf, pucTIMBody, u2OldBodyLen); + } while (FALSE); + if (pucBcnHdr) { + kalMemCopy(prBcnMsduInfo->prPacket, + pucBcnHdr, u4HdrLen); + pucTIMBody = (uint8_t *) + ((uint32_t) prBcnMsduInfo->prPacket + u4HdrLen); + prBcnMsduInfo->ucMacHeaderLength = + (WLAN_MAC_MGMT_HEADER_LEN + + (TIMESTAMP_FIELD_LEN + + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN)); + /* Header + Partial Body. */ + u2FrameLength = u4HdrLen; + } else { + /* Header not change. */ + u2FrameLength += prBcnMsduInfo->ucMacHeaderLength; + } + + if (pucBcnBody) { + kalMemCopy(pucTIMBody, pucBcnBody, u4BodyLen); + u2FrameLength += (uint16_t) 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 = (uint16_t) u4BcnInterval; + prP2pBssInfo->ucDTIMPeriod = (uint8_t) u4DtimPeriod; + prP2pBssInfo->u2CapInfo = prBcnFrame->u2CapInfo; + prBcnMsduInfo->ucPacketType = 3; + rResultStatus = nicUpdateBeaconIETemplate(prAdapter, + IE_UPD_METHOD_UPDATE_ALL, + NETWORK_TYPE_P2P_INDEX, + prP2pBssInfo->u2CapInfo, + (uint8_t *) prBcnFrame->aucInfoElem, + prBcnMsduInfo->u2FrameLength - + OFFSET_OF(struct WLAN_BEACON_FRAME, 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 +uint32_t +p2pFuncBeaconUpdate(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN struct P2P_BEACON_UPDATE_INFO *prBcnUpdateInfo, + IN uint8_t *pucNewBcnHdr, + IN uint32_t u4NewHdrLen, + IN uint8_t *pucNewBcnBody, + IN uint32_t u4NewBodyLen) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct WLAN_BEACON_FRAME *prBcnFrame = + (struct WLAN_BEACON_FRAME *) NULL; + struct MSDU_INFO *prBcnMsduInfo = (struct MSDU_INFO *) NULL; + uint8_t *pucIEBuf = (uint8_t *) NULL; + uint8_t aucIEBuf[MAX_IE_LENGTH]; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prP2pBssInfo != NULL) + && (prBcnUpdateInfo != NULL)); + + prBcnMsduInfo = prP2pBssInfo->prBeacon; + +#if DBG + if (prBcnUpdateInfo->pucBcnHdr != NULL) { + ASSERT((uint32_t) prBcnUpdateInfo->pucBcnHdr == + ((uint32_t) prBcnMsduInfo->prPacket + + MAC_TX_RESERVED_FIELD)); + } + + if (prBcnUpdateInfo->pucBcnBody != NULL) { + ASSERT((uint32_t) prBcnUpdateInfo->pucBcnBody == + ((uint32_t) prBcnUpdateInfo->pucBcnHdr + + (uint32_t) prBcnUpdateInfo->u4BcnHdrLen)); + } +#endif + prBcnFrame = (struct WLAN_BEACON_FRAME *) + ((unsigned long) 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 = (uint8_t *) prBcnFrame; + prBcnUpdateInfo->u4BcnHdrLen = u4NewHdrLen; + } + + pucIEBuf = (uint8_t *) + ((unsigned long) prBcnUpdateInfo->pucBcnHdr + + (unsigned long) prBcnUpdateInfo->u4BcnHdrLen); + kalMemCopy(pucIEBuf, aucIEBuf, u4NewBodyLen); + prBcnUpdateInfo->pucBcnBody = pucIEBuf; + + /* Frame Length */ + prBcnMsduInfo->u2FrameLength = (uint16_t) + (prBcnUpdateInfo->u4BcnHdrLen + + prBcnUpdateInfo->u4BcnBodyLen); + + prBcnMsduInfo->ucPacketType = TX_PACKET_TYPE_MGMT; + prBcnMsduInfo->fgIs802_11 = TRUE; + prBcnMsduInfo->ucBssIndex = prP2pBssInfo->ucBssIndex; + + /* 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, + (uint8_t *) prBcnFrame->aucInfoElem, + (prBcnMsduInfo->u2FrameLength - + OFFSET_OF(struct WLAN_BEACON_FRAME, aucInfoElem))); + +#if 1 + /* bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_P2P_INDEX); */ +#else + nicUpdateBeaconIETemplate(prAdapter, + IE_UPD_METHOD_UPDATE_ALL, + NETWORK_TYPE_P2P_INDEX, + prBcnFrame->u2CapInfo, + (uint8_t *) prBcnFrame->aucInfoElem, + (prBcnMsduInfo->u2FrameLength - + OFFSET_OF(struct WLAN_BEACON_FRAME, aucInfoElem))); +#endif + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncBeaconUpdate */ + +/*---------------------------------------------------------------------------*/ +/*! + * \brief This function is to update extra IEs (ex: WPS) for assoc resp. + * Caller should sanity check the params. + * + * \param[in] prAdapter Pointer of ADAPTER_T + * \param[in] prP2pBssInfo Pointer to BSS_INFO_T structure + * \param[in] AssocRespIE Pointer to extra IEs for assoc resp + * \param[in] u4AssocRespLen Length of extra IEs for assoc resp + * + * \return WLAN_STATUS + */ +/*---------------------------------------------------------------------------*/ + +uint32_t +p2pFuncAssocRespUpdate(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN uint8_t *AssocRespIE, IN uint32_t u4AssocRespLen) +{ + uint8_t ucOuiType = 0; + uint16_t u2SubTypeVersion = 0; + + if (!rsnParseCheckForWFAInfoElem(prAdapter, + AssocRespIE, &ucOuiType, &u2SubTypeVersion)) + return WLAN_STATUS_FAILURE; + + if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + kalP2PUpdateWSC_IE(prAdapter->prGlueInfo, 3, + (uint8_t *)AssocRespIE, IE_SIZE(AssocRespIE), + (uint8_t) (prP2pBssInfo->u4PrivateData)); + } + + return WLAN_STATUS_SUCCESS; +} + +#endif + +#if 0 +/* TODO: We do not apply IE in deauth frame set from upper layer now. */ +uint32_t +p2pFuncDeauth(IN struct ADAPTER *prAdapter, + IN uint8_t *pucPeerMacAddr, + IN uint16_t u2ReasonCode, + IN uint8_t *pucIEBuf, + IN uint16_t u2IELen, + IN u_int8_t fgSendDeauth) +{ + uint32_t rWlanStatus = WLAN_STATUS_FAILURE; + struct STA_RECORD *prCliStaRec = (struct STA_RECORD *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + u_int8_t 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: + { + struct LINK *prStaRecOfClientList = + (struct LINK *) NULL; + struct LINK_ENTRY *prLinkEntry = + (struct LINK_ENTRY *) NULL; + + prStaRecOfClientList = + &(prP2pBssInfo->rStaRecOfClientList); + + LINK_FOR_EACH(prLinkEntry, + prStaRecOfClientList) { + if ((uint32_t) prCliStaRec + == (uint32_t) 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. */ +uint32_t +p2pFuncDisassoc(IN struct ADAPTER *prAdapter, + IN uint8_t *pucPeerMacAddr, + IN uint16_t u2ReasonCode, + IN uint8_t *pucIEBuf, + IN uint16_t u2IELen, + IN u_int8_t fgSendDisassoc) +{ + uint32_t rWlanStatus = WLAN_STATUS_FAILURE; + struct STA_RECORD *prCliStaRec = (struct STA_RECORD *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + u_int8_t 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: + { + struct LINK *prStaRecOfClientList = + (struct LINK *) NULL; + struct LINK_ENTRY *prLinkEntry = + (struct LINK_ENTRY *) NULL; + + prStaRecOfClientList = + &(prP2pBssInfo->rStaRecOfClientList); + + LINK_FOR_EACH(prLinkEntry, + prStaRecOfClientList) { + if ((uint32_t) prCliStaRec + == (uint32_t) 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); */ + + } + + rWlanStatus = WLAN_STATUS_SUCCESS; + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncDisassoc */ + +#endif + +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP +uint32_t +p2pFuncProbeRespUpdate(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN uint8_t *ProbeRespIE, IN uint32_t u4ProbeRespLen) + +{ + struct MSDU_INFO *prMsduInfo = (struct MSDU_INFO *) NULL; + uint32_t u4IeArraySize = 0, u4Idx = 0; + uint8_t *pucP2pIe = (uint8_t *) NULL; + uint8_t *pucWpsIe = (uint8_t *) NULL; + uint8_t *pucWfdIe = (uint8_t *) NULL; + + if (prP2pBssInfo == NULL) + return WLAN_STATUS_FAILURE; + + /* reuse beacon MsduInfo */ + prMsduInfo = prP2pBssInfo->prBeacon; + + /* beacon prMsduInfo will be NULLify + * once BSS deactivated, so skip if it is + */ + if (!prMsduInfo) + return WLAN_STATUS_SUCCESS; + + if (!ProbeRespIE) { + DBGLOG(BSS, INFO, + "change beacon: has no extra probe response IEs\n"); + return WLAN_STATUS_SUCCESS; + } + if (p2pFuncIsAPMode( + prAdapter->rWifiVar + .prP2PConnSettings[prP2pBssInfo->u4PrivateData])) { + DBGLOG(BSS, INFO, + "change beacon: pure Ap mode do not add extra probe response IEs\n"); + return WLAN_STATUS_SUCCESS; + } + prMsduInfo->u2FrameLength = 0; + + bssBuildBeaconProbeRespFrameCommonIEs(prMsduInfo, + prP2pBssInfo, ProbeRespIE); + + u4IeArraySize = + sizeof(txProbeRspIETable) / sizeof(struct APPEND_VAR_IE_ENTRY); + + for (u4Idx = 0; u4Idx < u4IeArraySize; u4Idx++) { + if (txProbeRspIETable[u4Idx].pfnAppendIE) + txProbeRspIETable[u4Idx] + .pfnAppendIE(prAdapter, prMsduInfo); + } + + /* process probe response IE from supplicant */ + pucP2pIe = (uint8_t *) cfg80211_find_vendor_ie(WLAN_OUI_WFA, + WLAN_OUI_TYPE_WFA_P2P, + ProbeRespIE, + u4ProbeRespLen); + + pucWfdIe = (uint8_t *) cfg80211_find_vendor_ie(WLAN_OUI_WFA, + WLAN_OUI_TYPE_WFA_P2P + 1, + ProbeRespIE, + u4ProbeRespLen); + + pucWpsIe = (uint8_t *) cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, + WLAN_OUI_TYPE_MICROSOFT_WPS, + ProbeRespIE, + u4ProbeRespLen); + + if (pucP2pIe) { + kalMemCopy(prMsduInfo->prPacket + prMsduInfo->u2FrameLength, + pucP2pIe, IE_SIZE(pucP2pIe)); + prMsduInfo->u2FrameLength += IE_SIZE(pucP2pIe); + } + + if (pucWfdIe) { + kalMemCopy(prMsduInfo->prPacket + prMsduInfo->u2FrameLength, + pucWfdIe, IE_SIZE(pucWfdIe)); + prMsduInfo->u2FrameLength += IE_SIZE(pucWfdIe); + } + + if (pucWpsIe) { + kalMemCopy(prMsduInfo->prPacket + prMsduInfo->u2FrameLength, + pucWpsIe, IE_SIZE(pucWpsIe)); + prMsduInfo->u2FrameLength += IE_SIZE(pucWpsIe); + } + + DBGLOG(BSS, INFO, + "update probe response for bss index: %d, IE len: %d\n", + prP2pBssInfo->ucBssIndex, prMsduInfo->u2FrameLength); + /* dumpMemory8(prMsduInfo->prPacket, prMsduInfo->u2FrameLength); */ + + return nicUpdateBeaconIETemplate(prAdapter, + IE_UPD_METHOD_UPDATE_PROBE_RSP, + prP2pBssInfo->ucBssIndex, + prP2pBssInfo->u2CapInfo, + prMsduInfo->prPacket, + prMsduInfo->u2FrameLength); +} +#endif + +/*---------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN u_int8_t fgSendDeauth, + IN uint16_t u2ReasonCode) +{ + struct STA_RECORD *prCurrStaRec, *prStaRecNext; + struct LINK *prClientList; + + DEBUGFUNC("p2pFuncDissolve()"); + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_INFRASTRUCTURE: + /* Reset station record status. */ + if (prP2pBssInfo->prStaRecOfAP) { +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) + kalP2PGCIndicateConnectionStatus( + prAdapter->prGlueInfo, + (uint8_t) prP2pBssInfo->u4PrivateData, + NULL, NULL, 0, + REASON_CODE_DEAUTH_LEAVING_BSS, + WLAN_STATUS_MEDIA_DISCONNECT); +#else + kalP2PGCIndicateConnectionStatus( + prAdapter->prGlueInfo, + (uint8_t) prP2pBssInfo->u4PrivateData, + NULL, NULL, 0, + REASON_CODE_DEAUTH_LEAVING_BSS); +#endif + + /* 2012/02/14 frog: + * After formation before join group, + * prStaRecOfAP is NULL. + */ + p2pFuncDisconnect(prAdapter, + prP2pBssInfo, + prP2pBssInfo->prStaRecOfAP, + fgSendDeauth, + u2ReasonCode); + } + + /* Fix possible KE when RX Beacon & + * call nicPmIndicateBssConnected(). + * hit prStaRecOfAP == NULL. + */ + p2pChangeMediaState(prAdapter, + prP2pBssInfo, + 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. + */ + /* Send deauth. */ + authSendDeauthFrame(prAdapter, + prP2pBssInfo, + NULL, (struct SW_RFB *) NULL, + u2ReasonCode, (PFN_TX_DONE_HANDLER) NULL); + + prClientList = &prP2pBssInfo->rStaRecOfClientList; + + /* This case may let LINK_FOR_EACH_ENTRY_SAFE crash */ + if (prClientList == NULL) + break; + LINK_FOR_EACH_ENTRY_SAFE(prCurrStaRec, prStaRecNext, + prClientList, rLinkEntry, struct STA_RECORD) { + if (!prCurrStaRec) + break; + p2pFuncDisconnect(prAdapter, + prP2pBssInfo, prCurrStaRec, + TRUE, u2ReasonCode); + } + break; + default: + return; /* 20110420 -- alreay in Device Mode. */ + } + + /* Make the deauth frame send to FW ASAP. */ +#if !CFG_SUPPORT_MULTITHREAD + wlanAcquirePowerControl(prAdapter); +#endif + wlanProcessCommandQueue(prAdapter, + &prAdapter->prGlueInfo->rCmdQueue); +#if !CFG_SUPPORT_MULTITHREAD + wlanReleasePowerControl(prAdapter); +#endif + + /* Change Connection Status. */ + /* 20161025, can not set DISCONNECTED if clientcount > 0 */ + /*p2pChangeMediaState(prAdapter, + * prP2pBssInfo, MEDIA_STATE_DISCONNECTED); + */ + + } while (FALSE); +} /* p2pFuncDissolve */ + +/*---------------------------------------------------------------------------*/ +/*! + * @brief This function is called to dissolve from group or one group. + * (Would not change P2P FSM.) + * 1. GC: Disconnect from AP. (Send Deauth) + * 2. GO: Disconnect all STA + * + * @param[in] prAdapter Pointer to the adapter structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void +p2pFuncDisconnect(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN struct STA_RECORD *prStaRec, + IN u_int8_t fgSendDeauth, IN uint16_t u2ReasonCode) +{ + enum ENUM_PARAM_MEDIA_STATE eOriMediaStatus; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prStaRec != NULL) && (prP2pBssInfo != NULL)); + + ASSERT_BREAK(prP2pBssInfo->eNetworkType == NETWORK_TYPE_P2P); + + ASSERT_BREAK(prP2pBssInfo->ucBssIndex + < prAdapter->ucP2PDevBssIdx); + + eOriMediaStatus = prP2pBssInfo->eConnectionState; + + /* Indicate disconnect. */ + if (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData); + + kalP2PGOStationUpdate(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, prStaRec, FALSE); + } else { + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData); + + prP2pRoleFsmInfo->rJoinInfo.prTargetBssDesc = NULL; + + scanRemoveConnFlagOfBssDescByBssid(prAdapter, + prP2pBssInfo->aucBSSID); + } + + DBGLOG(P2P, INFO, + "p2pFuncDisconnect(): BssMode: %d, reason: %d, SendDeauth %s\n", + prP2pBssInfo->eCurrentOPMode, u2ReasonCode, + fgSendDeauth == TRUE ? "TRUE" : "FALSE"); + + if (fgSendDeauth) { + /* Send deauth. */ + authSendDeauthFrame(prAdapter, + prP2pBssInfo, + prStaRec, + (struct SW_RFB *) NULL, + u2ReasonCode, + (PFN_TX_DONE_HANDLER) + p2pRoleFsmRunEventDeauthTxDone); + + /* Make the deauth frame send to FW ASAP. */ +#if !CFG_SUPPORT_MULTITHREAD + wlanAcquirePowerControl(prAdapter); +#endif + wlanProcessCommandQueue(prAdapter, + &prAdapter->prGlueInfo->rCmdQueue); +#if !CFG_SUPPORT_MULTITHREAD + wlanReleasePowerControl(prAdapter); +#endif + } else { + /* Change station state. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + /* Reset Station Record Status. */ + p2pFuncResetStaRecStatus(prAdapter, prStaRec); + + cnmStaRecFree(prAdapter, prStaRec); + + if ((prP2pBssInfo->eCurrentOPMode + != OP_MODE_ACCESS_POINT) || + (bssGetClientCount(prAdapter, prP2pBssInfo) == 0)) { + DBGLOG(P2P, TRACE, + "No More Client, Media Status DISCONNECTED\n"); + p2pChangeMediaState(prAdapter, + prP2pBssInfo, + MEDIA_STATE_DISCONNECTED); + } + + if (eOriMediaStatus != prP2pBssInfo->eConnectionState) { + /* Update Disconnected state to FW. */ + nicUpdateBss(prAdapter, + prP2pBssInfo->ucBssIndex); + } + + } + } while (FALSE); + + return; + +} /* p2pFuncDisconnect */ + +void p2pFuncSetChannel(IN struct ADAPTER *prAdapter, + IN uint8_t ucRoleIdx, + IN struct RF_CHANNEL_INFO *prRfChannelInfo) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct P2P_CONNECTION_REQ_INFO *prP2pConnReqInfo = + (struct P2P_CONNECTION_REQ_INFO *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prRfChannelInfo != NULL)); + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, ucRoleIdx); + if (!prP2pRoleFsmInfo) + break; + prP2pConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + + prP2pConnReqInfo->rChannelInfo.ucChannelNum = + prRfChannelInfo->ucChannelNum; + prP2pConnReqInfo->rChannelInfo.eBand = prRfChannelInfo->eBand; + prP2pConnReqInfo->eChnlBw = prRfChannelInfo->ucChnlBw; + prP2pConnReqInfo->u2PriChnlFreq = + prRfChannelInfo->u2PriChnlFreq; + prP2pConnReqInfo->u4CenterFreq1 = + prRfChannelInfo->u4CenterFreq1; + prP2pConnReqInfo->u4CenterFreq2 = + prRfChannelInfo->u4CenterFreq2; + + } while (FALSE); +} /* p2pFuncSetChannel */ + +/*---------------------------------------------------------------------------*/ +/*! + * @brief Retry JOIN for AUTH_MODE_AUTO_SWITCH + * + * @param[in] prStaRec Pointer to the STA_RECORD_T + * + * @retval TRUE We will retry JOIN + * @retval FALSE We will not retry JOIN + */ +/*---------------------------------------------------------------------------*/ +u_int8_t p2pFuncRetryJOIN(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct P2P_JOIN_INFO *prJoinInfo) +{ + struct MSG_SAA_FSM_START *prJoinReqMsg = + (struct MSG_SAA_FSM_START *) NULL; + u_int8_t fgRetValue = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prStaRec != NULL) + && (prJoinInfo != NULL)); + + /* Retry other AuthType if possible */ + if (!prJoinInfo->ucAvailableAuthTypes) + break; + + if (prJoinInfo->ucAvailableAuthTypes + & (uint8_t) AUTH_TYPE_SHARED_KEY) { + + DBGLOG(P2P, INFO, + "RETRY JOIN INIT: Retry Authentication with AuthType == SHARED_KEY.\n"); + + prJoinInfo->ucAvailableAuthTypes &= + ~(uint8_t) AUTH_TYPE_SHARED_KEY; + + prStaRec->ucAuthAlgNum = + (uint8_t) AUTH_ALGORITHM_NUM_SHARED_KEY; + } else { + DBGLOG(P2P, ERROR, + "RETRY JOIN INIT: Retry Authentication with Unexpected AuthType.\n"); + ASSERT(0); + break; + } + + /* No more available Auth Types */ + prJoinInfo->ucAvailableAuthTypes = 0; + + /* Trigger SAA to start JOIN process. */ + prJoinReqMsg = (struct MSG_SAA_FSM_START *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_SAA_FSM_START)); + if (!prJoinReqMsg) { + break; + } + + prJoinReqMsg->rMsgHdr.eMsgId = MID_P2P_SAA_FSM_START; + prJoinReqMsg->ucSeqNum = ++prJoinInfo->ucSeqNumOfReqMsg; + prJoinReqMsg->prStaRec = prStaRec; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prJoinReqMsg, + MSG_SEND_METHOD_BUF); + + fgRetValue = TRUE; + } while (FALSE); + + return fgRetValue; + +} /* end of p2pFuncRetryJOIN() */ + +struct BSS_INFO *p2pFuncBSSIDFindBssInfo(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBSSID) +{ + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + uint8_t ucBssIdx = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBSSID != NULL)); + + for (ucBssIdx = 0; + ucBssIdx < prAdapter->ucHwBssIdNum; ucBssIdx++) { + if (!IS_NET_ACTIVE(prAdapter, ucBssIdx)) + continue; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + + if (EQUAL_MAC_ADDR(prBssInfo->aucBSSID, pucBSSID) + && IS_BSS_P2P(prBssInfo)) + break; + + prBssInfo = NULL; + } + + } while (FALSE); + + return prBssInfo; +} /* p2pFuncBSSIDFindBssInfo */ + +/*---------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*---------------------------------------------------------------------------*/ +u_int8_t +p2pFuncValidateAuth(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN struct SW_RFB *prSwRfb, + IN struct STA_RECORD **pprStaRec, + OUT uint16_t *pu2StatusCode) +{ + u_int8_t fgPmfConn = FALSE; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + struct WLAN_AUTH_FRAME *prAuthFrame = (struct WLAN_AUTH_FRAME *) NULL; + + DBGLOG(P2P, TRACE, "p2pValidate Authentication Frame\n"); + + + /* P2P 3.2.8 */ + *pu2StatusCode = STATUS_CODE_REQ_DECLINED; + prAuthFrame = (struct WLAN_AUTH_FRAME *) prSwRfb->pvHeader; + + if ((prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) || + (prP2pBssInfo->eIntendOPMode != OP_MODE_NUM)) { + /* We are not under AP Mode yet. */ + DBGLOG(P2P, WARN, + "Current OP mode is not under AP mode. (%d)\n", + prP2pBssInfo->eCurrentOPMode); + return FALSE; + } + + prStaRec = cnmGetStaRecByAddress(prAdapter, + prP2pBssInfo->ucBssIndex, prAuthFrame->aucSrcAddr); + + if (!prStaRec) { + prStaRec = cnmStaRecAlloc(prAdapter, STA_TYPE_P2P_GC, + prP2pBssInfo->ucBssIndex, + prAuthFrame->aucSrcAddr); + + /* TODO(Kevin): Error handling of allocation of + * struct STA_RECORD for + * exhausted case and do removal of unused struct STA_RECORD. + */ + /* Sent a message event to clean un-used STA_RECORD_T. */ + /* ASSERT(prStaRec); */ + if (!prStaRec) { + DBGLOG(P2P, WARN, + "StaRec Full. (%d)\n", CFG_STA_REC_NUM); + return TRUE; + } + + 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; + + /* Update default Tx rate */ + nicTxUpdateStaRecDefaultRate(prAdapter, prStaRec); + + /* NOTE(Kevin): Better to change state here, not at TX Done */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + } else { +#if CFG_SUPPORT_802_11W + /* AP PMF. if PMF connection, do not reset state & FSM */ + fgPmfConn = rsnCheckBipKeyInstalled(prAdapter, prStaRec); + if (fgPmfConn && + prP2pBssInfo->u4RsnSelectedAKMSuite != + RSN_AKM_SUITE_SAE) { + DBGLOG(P2P, WARN, "PMF Connction, return false\n"); + return FALSE; + } +#endif + + prSwRfb->ucStaRecIdx = prStaRec->ucIndex; + + if ((prStaRec->ucStaState > STA_STATE_1) + && (IS_STA_IN_P2P(prStaRec))) { + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + p2pFuncResetStaRecStatus(prAdapter, prStaRec); + + bssRemoveClient(prAdapter, prP2pBssInfo, prStaRec); + + p2pFuncDisconnect(prAdapter, + prP2pBssInfo, prStaRec, FALSE, + REASON_CODE_DISASSOC_INACTIVITY); + } + + } + + if (bssGetClientCount(prAdapter, prP2pBssInfo) + >= P2P_MAXIMUM_CLIENT_COUNT +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + || kalP2PMaxClients(prAdapter->prGlueInfo, + bssGetClientCount(prAdapter, prP2pBssInfo), + (uint8_t) prP2pBssInfo->u4PrivateData) +#endif + ) { + /* GROUP limit full. */ + /* P2P 3.2.8 */ + DBGLOG(P2P, WARN, + "Group Limit Full. (%d)\n", + bssGetClientCount(prAdapter, prP2pBssInfo)); + cnmStaRecFree(prAdapter, prStaRec); + *pu2StatusCode = STATUS_CODE_ASSOC_DENIED_AP_OVERLOAD; + return TRUE; + } +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + else { + /* Hotspot Blacklist */ + if (kalP2PCmpBlackList(prAdapter->prGlueInfo, + prAuthFrame->aucSrcAddr, + (uint8_t) prP2pBssInfo->u4PrivateData) + || !p2pRoleProcessACLInspection(prAdapter, + prStaRec->aucMacAddr, prP2pBssInfo->ucBssIndex)) { + DBGLOG(P2P, WARN, "in black list.\n"); + cnmStaRecFree(prAdapter, prStaRec); + *pu2StatusCode + = STATUS_CODE_ASSOC_DENIED_OUTSIDE_STANDARD; + return FALSE; + } + + } +#endif + /* prStaRec->eStaType = STA_TYPE_INFRA_CLIENT; */ + prStaRec->eStaType = STA_TYPE_P2P_GC; + + /* Update Station Record - Status/Reason Code */ + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + + prStaRec->ucJoinFailureCount = 0; + + *pprStaRec = prStaRec; + + *pu2StatusCode = STATUS_CODE_SUCCESSFUL; + + + return TRUE; + +} /* p2pFuncValidateAuth */ + +void p2pFuncResetStaRecStatus(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + do { + if ((prAdapter == NULL) || (prStaRec == NULL)) { + break; + } + + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + prStaRec->u2ReasonCode = REASON_CODE_RESERVED; + prStaRec->ucJoinFailureCount = 0; + prStaRec->fgTransmitKeyExist = FALSE; + + prStaRec->fgSetPwrMgtBit = FALSE; + + } while (FALSE); +} /* p2pFuncResetStaRecStatus */ + +/*---------------------------------------------------------------------------*/ +/*! + * @brief The function is used to initialize the value + * of the connection settings for P2P network + * + * @param (none) + * + * @return (none) + */ +/*---------------------------------------------------------------------------*/ +void +p2pFuncInitConnectionSettings(IN struct ADAPTER *prAdapter, + IN struct P2P_CONNECTION_SETTINGS *prP2PConnSettings, + IN u_int8_t fgIsApMode) +{ + struct WIFI_VAR *prWifiVar = NULL; + + ASSERT(prP2PConnSettings); + + prWifiVar = &(prAdapter->rWifiVar); + ASSERT(prWifiVar); + + prP2PConnSettings->fgIsApMode = fgIsApMode; + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + prP2PConnSettings->fgIsWPSMode = prWifiVar->ucApWpsMode; +#endif +} /* p2pFuncInitConnectionSettings */ + +/*---------------------------------------------------------------------------*/ +/*! + * @brief This function will validate the Rx Assoc Req Frame and then return + * the status code to AAA to indicate if need + * to perform following actions + * when the specified conditions were matched. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] prSwRfb Pointer to SW RFB data structure. + * @param[out] pu2StatusCode The Status Code of Validation Result + * + * @retval TRUE Reply the Assoc Resp + * @retval FALSE Don't reply the Assoc Resp + */ +/*---------------------------------------------------------------------------*/ +u_int8_t p2pFuncValidateAssocReq(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + OUT uint16_t *pu2StatusCode) +{ + u_int8_t fgReplyAssocResp = TRUE; + struct WLAN_ASSOC_REQ_FRAME *prAssocReqFrame = + (struct WLAN_ASSOC_REQ_FRAME *) NULL; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + + /* 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; + prAssocReqFrame = + (struct WLAN_ASSOC_REQ_FRAME *) prSwRfb->pvHeader; + + prP2pBssInfo = + p2pFuncBSSIDFindBssInfo(prAdapter, + prAssocReqFrame->aucBSSID); + + if (prP2pBssInfo == NULL) { + DBGLOG(P2P, ERROR, + "RX ASSOC frame without BSS active / BSSID match\n"); + break; + } + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prStaRec == NULL) { + /* Station record should be ready + * while RX AUTH frame. + */ + fgReplyAssocResp = FALSE; + break; + } + ASSERT(prSwRfb->prRxStatusGroup3); + prStaRec->ucRCPI = + nicRxGetRcpiValueFromRxv( + prAdapter, RCPI_MODE_MAX, prSwRfb); + + 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; + } + + *pu2StatusCode = STATUS_CODE_SUCCESSFUL; + + } while (FALSE); + + return fgReplyAssocResp; + +} /* p2pFuncValidateAssocReq */ + +/*---------------------------------------------------------------------------*/ +/*! +* @brief This function is used to check the TKIP IE +* +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t p2pFuncParseCheckForTKIPInfoElem(IN uint8_t *pucBuf) +{ + uint8_t aucWfaOui[] = VENDOR_OUI_WFA; + struct WPA_INFO_ELEM *prWpaIE = (struct WPA_INFO_ELEM *) NULL; + uint32_t u4GroupKeyCipher = 0; + + if (pucBuf == NULL) + return FALSE; + + prWpaIE = (struct WPA_INFO_ELEM *) pucBuf; + + if (prWpaIE->ucLength <= ELEM_MIN_LEN_WFA_OUI_TYPE_SUBTYPE) + return FALSE; + + if (kalMemCmp(prWpaIE->aucOui, aucWfaOui, sizeof(aucWfaOui))) + return FALSE; + + WLAN_GET_FIELD_32(&prWpaIE->u4GroupKeyCipherSuite, &u4GroupKeyCipher); + + if (prWpaIE->ucOuiType == VENDOR_OUI_TYPE_WPA && + u4GroupKeyCipher == WPA_CIPHER_SUITE_TKIP) + return TRUE; + else + return FALSE; +} /* p2pFuncParseCheckForP2PInfoElem */ + +/*---------------------------------------------------------------------------*/ +/*! + * @brief This function is used to check the P2P IE + * + * + * @return none + */ +/*---------------------------------------------------------------------------*/ +u_int8_t p2pFuncParseCheckForP2PInfoElem(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, OUT uint8_t *pucOuiType) +{ + uint8_t aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + struct IE_WFA *prWfaIE = (struct IE_WFA *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (pucBuf != NULL) && (pucOuiType != NULL)); + + prWfaIE = (struct IE_WFA *) 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 + */ +/*---------------------------------------------------------------------------*/ +u_int8_t +p2pFuncValidateProbeReq(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + OUT uint32_t *pu4ControlFlags, + IN u_int8_t fgIsDevInterface, + IN uint8_t ucRoleIdx) +{ + u_int8_t fgIsReplyProbeRsp = FALSE; + u_int8_t fgApplyp2PDevFilter = FALSE; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + + DEBUGFUNC("p2pFuncValidateProbeReq"); + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + + prP2pRoleFsmInfo = + prAdapter->rWifiVar.aprP2pRoleFsmInfo[ucRoleIdx]; + + /* Process both cases that with amd without add p2p interface */ + if (fgIsDevInterface) + fgApplyp2PDevFilter = TRUE; + else { + if (prAdapter->prGlueInfo->prP2PInfo[0]->prDevHandler == + prAdapter->prGlueInfo->prP2PInfo + [ucRoleIdx]->aprRoleHandler) + fgApplyp2PDevFilter = TRUE; + else + fgApplyp2PDevFilter = FALSE; + } + /* TODO: */ + if ((fgApplyp2PDevFilter && + (prAdapter->u4OsPacketFilter + & PARAM_PACKET_FILTER_PROBE_REQ)) + || (!fgApplyp2PDevFilter && + (prP2pRoleFsmInfo->u4P2pPacketFilter + & PARAM_PACKET_FILTER_PROBE_REQ))) { + /* Leave the probe response to p2p_supplicant. */ + kalP2PIndicateRxMgmtFrame(prAdapter->prGlueInfo, + prSwRfb, fgIsDevInterface, ucRoleIdx); + } + + } while (FALSE); + + return fgIsReplyProbeRsp; + +} /* end of p2pFuncValidateProbeReq() */ + +static void +p2pFunAbortOngoingScan(IN struct ADAPTER *prAdapter) +{ + struct SCAN_INFO *prScanInfo; + + if (!prAdapter) + return; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + if (!prScanInfo || (prScanInfo->eCurrentState != SCAN_STATE_SCANNING)) + return; + + if (IS_BSS_INDEX_AIS(prAdapter, + prScanInfo->rScanParam.ucBssIndex)) + aisFsmStateAbort_SCAN(prAdapter, + prScanInfo->rScanParam.ucBssIndex); +} + +static void p2pFunBufferP2pActionFrame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint8_t ucRoleIdx) +{ + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) NULL; + struct P2P_QUEUED_ACTION_FRAME *prFrame; + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + if (prP2pDevFsmInfo == NULL) + return; + + prFrame = &prP2pDevFsmInfo->rQueuedActionFrame; + + if (prFrame->u2Length > 0) { + DBGLOG(P2P, WARN, "p2p action frames are pending, drop it.\n"); + return; + } + + DBGLOG(P2P, INFO, "Buffer the p2p action frame.\n"); + prFrame->ucRoleIdx = ucRoleIdx; + prFrame->u4Freq = nicChannelNum2Freq(prSwRfb->ucChnlNum) / 1000; + prFrame->u2Length = prSwRfb->u2PacketLen; + prFrame->prHeader = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, + prSwRfb->u2PacketLen); + if (prFrame->prHeader == NULL) { + DBGLOG(P2P, WARN, "Allocate buffer fail.\n"); + p2pFunCleanQueuedMgmtFrame(prAdapter, prFrame); + return; + } + kalMemCopy(prFrame->prHeader, prSwRfb->pvHeader, prSwRfb->u2PacketLen); +} + +/*---------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, IN u_int8_t fgIsDevInterface, + IN uint8_t ucRoleIdx) +{ + struct WLAN_ACTION_FRAME *prActFrame; + struct WLAN_PUBLIC_VENDOR_ACTION_FRAME *prActPubVenFrame; + uint32_t u4OUI; + u_int8_t fgBufferFrame = FALSE; + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = NULL; + + DEBUGFUNC("p2pFuncValidateRxActionFrame"); + + if (prAdapter == NULL || prSwRfb == NULL) { + DBGLOG(P2P, ERROR, "Invalid parameter.\n"); + return; + } + prActFrame = (struct WLAN_ACTION_FRAME *) prSwRfb->pvHeader; + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + /* In case channel is not granted yet, we should ignore action + * frames which may come from unexpected channels. + */ + if (fgIsDevInterface && prP2pDevFsmInfo && + prP2pDevFsmInfo->eCurrentState == + P2P_DEV_STATE_REQING_CHANNEL) { + DBGLOG(P2P, INFO, + "ignore rx action frame %d on state:%d\n", + prActFrame->ucCategory, + prP2pDevFsmInfo->eCurrentState); + return; + } + + switch (prActFrame->ucCategory) { + case CATEGORY_PUBLIC_ACTION: + if (prActFrame->ucAction != 0x9) + break; + WLAN_GET_FIELD_BE32(prActFrame->ucActionDetails, &u4OUI); + DBGLOG(P2P, TRACE, "Action: oui: 0x%x\n", u4OUI); + if (u4OUI != P2P_IE_VENDOR_TYPE || + prSwRfb->u2PacketLen < + sizeof(struct WLAN_PUBLIC_VENDOR_ACTION_FRAME)) + break; + + prActPubVenFrame = + (struct WLAN_PUBLIC_VENDOR_ACTION_FRAME *) + prActFrame; + p2pProcessActionResponse(prAdapter, + prActPubVenFrame->ucPubSubType); + if (prActPubVenFrame->ucPubSubType == P2P_GO_NEG_REQ) + p2pFunAbortOngoingScan(prAdapter); + if (fgIsDevInterface) { + p2pDevFsmNotifyP2pRx(prAdapter, + prActPubVenFrame->ucPubSubType, + &fgBufferFrame); + } + /* Fall through */ + default: + break; + } + + if (fgBufferFrame) { + p2pFunBufferP2pActionFrame(prAdapter, + prSwRfb, + ucRoleIdx); + return; + } + + if (prAdapter->u4OsPacketFilter + & PARAM_PACKET_FILTER_ACTION_FRAME) { + /* Leave the Action frame to p2p_supplicant. */ + kalP2PIndicateRxMgmtFrame(prAdapter->prGlueInfo, + prSwRfb, fgIsDevInterface, ucRoleIdx); + } else { + DBGLOG(P2P, INFO, + "do not indicate action frame as filter closed\n"); + } + + return; + +} /* p2pFuncValidateRxMgmtFrame */ + +u_int8_t p2pFuncIsAPMode(IN struct P2P_CONNECTION_SETTINGS *prP2pConnSettings) +{ + if (prP2pConnSettings) { + if (prP2pConnSettings->fgIsWPSMode == 1) + return FALSE; + return prP2pConnSettings->fgIsApMode; + } else { + return FALSE; + } +} + +/* p2pFuncIsAPMode */ + +void +p2pFuncParseBeaconContent(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN uint8_t *pucIEInfo, IN uint32_t u4IELen) +{ + uint8_t *pucIE = (uint8_t *) NULL; + uint16_t u2Offset = 0; + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo = + (struct P2P_SPECIFIC_BSS_INFO *) NULL; + uint8_t i = 0; + struct RSN_INFO rRsnIe; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); + + if (u4IELen == 0) + break; + + prP2pSpecificBssInfo = + prAdapter->rWifiVar.prP2pSpecificBssInfo + [prP2pBssInfo->u4PrivateData]; + prP2pSpecificBssInfo->u2AttributeLen = 0; + prP2pSpecificBssInfo->u2WpaIeLen = 0; + prP2pSpecificBssInfo->u2RsnIeLen = 0; + + ASSERT_BREAK(pucIEInfo != NULL); + + pucIE = pucIEInfo; + + if (prP2pBssInfo->u2CapInfo & CAP_INFO_PRIVACY) + kalP2PSetCipher(prAdapter->prGlueInfo, + IW_AUTH_CIPHER_WEP40, + (uint8_t) prP2pBssInfo->u4PrivateData); + else + kalP2PSetCipher(prAdapter->prGlueInfo, + IW_AUTH_CIPHER_NONE, + (uint8_t) prP2pBssInfo->u4PrivateData); + + prP2pBssInfo->ucCountryIELen = 0; +#if (CFG_SUPPORT_802_11AX == 1) + prP2pBssInfo->ucPhyTypeSet &= ~PHY_TYPE_SET_802_11AX; +#endif + + IE_FOR_EACH(pucIE, u4IELen, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_SSID: /* 0 *//* V *//* Done */ + { + + /* DBGLOG(P2P, TRACE, ("SSID update\n")); */ + /* SSID is saved when start AP/GO */ + /* SSID IE set in beacon from supplicant + * will not always be + * the true since hidden SSID case + */ +#if 0 + 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); +#endif + + } + break; + case ELEM_ID_SUP_RATES: /* 1 *//* V *//* Done */ + { + DBGLOG(P2P, TRACE, "Support Rate IE\n"); + if ((SUP_RATES_IE(pucIE)->ucLength) + > ELEM_MAX_LEN_SUP_RATES) + SUP_RATES_IE(pucIE)->ucLength = + ELEM_MAX_LEN_SUP_RATES; + 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 */ + { + DBGLOG(P2P, TRACE, + "DS PARAM IE: %d.\n", + DS_PARAM_IE(pucIE)->ucCurrChnl); + + /* prP2pBssInfo->ucPrimaryChannel = + * DS_PARAM_IE(pucIE)->ucCurrChnl; + */ + + /* prP2pBssInfo->eBand = BAND_2G4; */ + } + break; + case ELEM_ID_TIM: /* 5 *//* V */ + TIM_IE(pucIE)->ucDTIMPeriod = + prP2pBssInfo->ucDTIMPeriod; + DBGLOG(P2P, TRACE, + "TIM IE, Len:%d, DTIM:%d\n", + IE_LEN(pucIE), + TIM_IE(pucIE)->ucDTIMPeriod); + break; + case ELEM_ID_COUNTRY_INFO: /* 7 */ + if (COUNTRY_IE(pucIE)->ucLength + >= ELEM_MIN_LEN_COUNTRY_INFO) { + prP2pBssInfo->ucCountryIELen = + COUNTRY_IE(pucIE)->ucLength; + kalMemCopy( + prP2pBssInfo->aucCountryStr, + COUNTRY_IE(pucIE)->aucCountryStr, 3); + kalMemCopy( + prP2pBssInfo->aucSubbandTriplet, + COUNTRY_IE(pucIE)->arCountryStr, + COUNTRY_IE(pucIE)->ucLength - 3); + } + 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); + + prP2pBssInfo->ucPhyTypeSet |= + PHY_TYPE_SET_802_11G; +#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:%x, TX Beamforming Cap:%x, Ant Selection Cap:%x\n", + HT_CAP_IE(pucIE) + ->u2HtExtendedCap, + HT_CAP_IE(pucIE) + ->u4TxBeamformingCap, + HT_CAP_IE(pucIE)->ucAselCap); + + prP2pBssInfo->ucPhyTypeSet |= + PHY_TYPE_SET_802_11N; +#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", + (uint8_t) + HT_CAP_IE(pucIE)->ucAmpduParam, + (uint8_t) + 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 */ + + DBGLOG(P2P, TRACE, "RSN IE\n"); + kalP2PSetCipher(prAdapter->prGlueInfo, + IW_AUTH_CIPHER_CCMP, + (uint8_t) prP2pBssInfo->u4PrivateData); + if (IE_LEN(pucIE) > ELEM_MAX_LEN_RSN) { + DBGLOG(P2P, ERROR, + "RSN IE length is unexpected !!\n"); + return; + } + kalMemCopy(prP2pSpecificBssInfo->aucRsnIeBuffer, + pucIE, IE_SIZE(pucIE)); + prP2pSpecificBssInfo->u2RsnIeLen + = IE_SIZE(pucIE); + if (rsnParseRsnIE(prAdapter, + RSN_IE(pucIE), &rRsnIe)) { + prP2pBssInfo->u4RsnSelectedGroupCipher = + RSN_CIPHER_SUITE_CCMP; + prP2pBssInfo + ->u4RsnSelectedPairwiseCipher = + RSN_CIPHER_SUITE_CCMP; + prP2pBssInfo->u4RsnSelectedAKMSuite = + RSN_AKM_SUITE_PSK; + prP2pBssInfo->u2RsnSelectedCapInfo = + rRsnIe.u2RsnCap; + DBGLOG(RSN, TRACE, + "RsnIe CAP:0x%x\n", + rRsnIe.u2RsnCap); + } + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + prP2pBssInfo->rApPmfCfg.fgMfpc = + (rRsnIe.u2RsnCap + & ELEM_WPA_CAP_MFPC) ? 1 : 0; + prP2pBssInfo->rApPmfCfg.fgMfpr = + (rRsnIe.u2RsnCap + & ELEM_WPA_CAP_MFPR) ? 1 : 0; + prP2pSpecificBssInfo->u4KeyMgtSuiteCount + = (rRsnIe.u4AuthKeyMgtSuiteCount + < P2P_MAX_AKM_SUITES) + ? rRsnIe.u4AuthKeyMgtSuiteCount + : P2P_MAX_AKM_SUITES; + for (i = 0; + i < rRsnIe.u4AuthKeyMgtSuiteCount; + i++) { + if ((rRsnIe.au4AuthKeyMgtSuite[i] + == RSN_AKM_SUITE_PSK_SHA256) || + (rRsnIe.au4AuthKeyMgtSuite[i] + == RSN_AKM_SUITE_802_1X_SHA256)) { + DBGLOG(RSN, INFO, + "SHA256 support\n"); + /* over-write + * u4RsnSelectedAKMSuite + * by SHA256 AKM + */ + prP2pBssInfo + ->u4RsnSelectedAKMSuite + = rRsnIe.au4AuthKeyMgtSuite[i]; + prP2pBssInfo + ->rApPmfCfg.fgSha256 + = TRUE; + break; + } else if (rRsnIe.au4AuthKeyMgtSuite[i] + == RSN_AKM_SUITE_SAE) + prP2pBssInfo + ->u4RsnSelectedAKMSuite + = rRsnIe.au4AuthKeyMgtSuite[i]; + + if (i < P2P_MAX_AKM_SUITES) { + prP2pSpecificBssInfo + ->au4KeyMgtSuite[i] + = rRsnIe.au4AuthKeyMgtSuite[i]; + } + } + DBGLOG(RSN, ERROR, + "bcn mfpc:%d, mfpr:%d, sha256:%d, 0x%04x\n", + prP2pBssInfo->rApPmfCfg.fgMfpc, + prP2pBssInfo->rApPmfCfg.fgMfpr, + prP2pBssInfo->rApPmfCfg.fgSha256, + prP2pBssInfo->u4RsnSelectedAKMSuite); +#endif + + break; + case ELEM_ID_EXTENDED_SUP_RATES: /* 50 *//* V */ + /* 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); + + prP2pBssInfo->ucPhyTypeSet |= + PHY_TYPE_SET_802_11N; +#else + uint16_t 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"); + { + p2pFuncParseBeaconVenderId(prAdapter, + pucIE, prP2pSpecificBssInfo, + (uint8_t) + prP2pBssInfo->u4PrivateData); + /* TODO: Store other Vender IE + * except for WMM Param. + */ + } + break; + case ELEM_ID_VHT_CAP: + prP2pBssInfo->ucPhyTypeSet |= + PHY_TYPE_SET_802_11AC; + break; + case ELEM_ID_VHT_OP: + prP2pBssInfo->ucPhyTypeSet |= + PHY_TYPE_SET_802_11AC; + break; +#if (CFG_SUPPORT_802_11AX == 1) + case ELEM_ID_RESERVED: + if (IE_ID_EXT(pucIE) == ELEM_EXT_ID_HE_CAP) + prP2pBssInfo->ucPhyTypeSet |= + PHY_TYPE_SET_802_11AX; + break; +#endif + default: + DBGLOG(P2P, TRACE, + "Unprocessed element ID:%d\n", + IE_ID(pucIE)); + break; + } + } + + } while (FALSE); +} /* p2pFuncParseBeaconContent */ + +/* Code refactoring for AOSP */ +static void +p2pFuncParseBeaconVenderId(IN struct ADAPTER *prAdapter, + IN uint8_t *pucIE, + IN struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo, + IN uint8_t ucRoleIndex) +{ + do { + uint8_t ucOuiType; + uint16_t u2SubTypeVersion; + + if (rsnParseCheckForWFAInfoElem( + prAdapter, pucIE, &ucOuiType, &u2SubTypeVersion)) { + if ((ucOuiType == VENDOR_OUI_TYPE_WPA) + && (u2SubTypeVersion == VERSION_WPA)) { + if (!kalP2PGetCcmpCipher(prAdapter->prGlueInfo, + ucRoleIndex)) + kalP2PSetCipher(prAdapter->prGlueInfo, + IW_AUTH_CIPHER_TKIP, + ucRoleIndex); + if (IE_LEN(pucIE) > ELEM_MAX_LEN_WPA) { + DBGLOG(P2P, ERROR, + "WPA IE length is unexpected !!\n"); + return; + } + kalMemCopy( + prP2pSpecificBssInfo + ->aucWpaIeBuffer, + pucIE, IE_SIZE(pucIE)); + prP2pSpecificBssInfo->u2WpaIeLen = + IE_SIZE(pucIE); + DBGLOG(P2P, TRACE, "WPA IE in supplicant\n"); + } else if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + kalP2PUpdateWSC_IE(prAdapter->prGlueInfo, + 0, pucIE, IE_SIZE(pucIE), ucRoleIndex); + DBGLOG(P2P, TRACE, "WPS IE in supplicant\n"); + } else if (ucOuiType == VENDOR_OUI_TYPE_WMM) { + DBGLOG(P2P, TRACE, "WMM IE in supplicant\n"); + } + /* 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); + DBGLOG(P2P, TRACE, "P2P IE in supplicant\n"); + } else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { + + kalMemCopy(&prP2pSpecificBssInfo + ->aucAttributesCache + [prP2pSpecificBssInfo->u2AttributeLen], + pucIE, IE_SIZE(pucIE)); + + prP2pSpecificBssInfo->u2AttributeLen += + IE_SIZE(pucIE); + } else { + DBGLOG(P2P, TRACE, + "Unknown 50-6F-9A-%d IE.\n", + ucOuiType); + } + } else { + kalMemCopy(&prP2pSpecificBssInfo->aucAttributesCache + [prP2pSpecificBssInfo->u2AttributeLen], + pucIE, IE_SIZE(pucIE)); + + prP2pSpecificBssInfo->u2AttributeLen += + IE_SIZE(pucIE); + DBGLOG(P2P, TRACE, + "Driver unprocessed Vender Specific IE\n"); + } + } while (0); +} + +struct BSS_DESC * +p2pFuncKeepOnConnection(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct P2P_CONNECTION_REQ_INFO *prConnReqInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN struct P2P_SCAN_REQ_INFO *prScanReqInfo) +{ + struct BSS_DESC *prTargetBss = (struct BSS_DESC *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prBssInfo != NULL) && + (prConnReqInfo != NULL) && (prChnlReqInfo != NULL) && + (prScanReqInfo != NULL)); + + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + break; + /* Update connection request information. */ + ASSERT(prConnReqInfo->eConnRequest == P2P_CONNECTION_TYPE_GC); + + /* Find BSS Descriptor first. */ + prTargetBss = scanP2pSearchDesc(prAdapter, prConnReqInfo); + + if (prTargetBss == NULL) { + /* Update scan parameter... to scan target device. */ + /* TODO: Need refine. */ + prScanReqInfo->ucNumChannelList = 1; + prScanReqInfo->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prScanReqInfo->eChannelSet = SCAN_CHANNEL_FULL; + /* Prevent other P2P ID in IE. */ + prScanReqInfo->u4BufLength = 0; + 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->eChnlReqType = CH_REQ_TYPE_JOIN; + + prChnlReqInfo->eChannelWidth = + prTargetBss->eChannelWidth; + prChnlReqInfo->ucCenterFreqS1 = + prTargetBss->ucCenterFreqS1; + prChnlReqInfo->ucCenterFreqS2 = + prTargetBss->ucCenterFreqS2; + } + + } while (FALSE); + + return prTargetBss; +} /* p2pFuncKeepOnConnection */ + +/* Currently Only for ASSOC Response Frame. */ +void p2pFuncStoreAssocRspIEBuffer(IN struct ADAPTER *prAdapter, + IN struct P2P_JOIN_INFO *prP2pJoinInfo, + IN struct SW_RFB *prSwRfb) +{ + struct WLAN_ASSOC_RSP_FRAME *prAssocRspFrame = + (struct WLAN_ASSOC_RSP_FRAME *) NULL; + int16_t i2IELen = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prP2pJoinInfo != NULL) && (prSwRfb != NULL)); + + prAssocRspFrame = + (struct WLAN_ASSOC_RSP_FRAME *) 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; + + prP2pJoinInfo->u4BufLength = (uint32_t) i2IELen; + + kalMemCopy(prP2pJoinInfo->aucIEBuf, + prAssocRspFrame->aucInfoElem, + prP2pJoinInfo->u4BufLength); + + } while (FALSE); +} /* p2pFuncStoreAssocRspIEBuffer */ + +/*---------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set Packet Filter. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] pvSetBuffer Pointer to the buffer + * that holds the data to be set. + * \param[in] u4SetBufferLen The length of the set buffer. + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed + * due to invalid length of the set buffer, returns + * the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + * \retval WLAN_STATUS_NOT_SUPPORTED + * \retval WLAN_STATUS_ADAPTER_NOT_READY + */ +/*---------------------------------------------------------------------------*/ +void +p2pFuncMgmtFrameRegister(IN struct ADAPTER *prAdapter, + IN uint16_t u2FrameType, + IN u_int8_t fgIsRegistered, + OUT uint32_t *pu4P2pPacketFilter) +{ + uint32_t u4NewPacketFilter = 0; + struct CMD_RX_PACKET_FILTER rSetRxPacketFilter; + + DEBUGFUNC("p2pFuncMgmtFrameRegister"); + + do { + ASSERT_BREAK(prAdapter != NULL); + + if (pu4P2pPacketFilter) + u4NewPacketFilter = *pu4P2pPacketFilter; + + switch (u2FrameType) { + case MAC_FRAME_PROBE_REQ: + if (fgIsRegistered) { + u4NewPacketFilter |= + PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(P2P, TRACE, + "Open packet filer probe request\n"); + } else { + u4NewPacketFilter &= + ~PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(P2P, TRACE, + "Close packet filer probe request\n"); + } + break; + case MAC_FRAME_ACTION: + if (fgIsRegistered) { + u4NewPacketFilter |= + PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(P2P, TRACE, + "Open packet filer action frame.\n"); + } else { + u4NewPacketFilter &= + ~PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(P2P, TRACE, + "Close packet filer action frame.\n"); + } + break; + default: + DBGLOG(P2P, TRACE, + "Ask frog to add code for mgmt:%x\n", + u2FrameType); + break; + } + + if (pu4P2pPacketFilter) + *pu4P2pPacketFilter = u4NewPacketFilter; + + /* u4NewPacketFilter |= prAdapter->u4OsPacketFilter; */ + + prAdapter->u4OsPacketFilter &= ~PARAM_PACKET_FILTER_P2P_MASK; + prAdapter->u4OsPacketFilter |= u4NewPacketFilter; + + DBGLOG(P2P, TRACE, + "P2P Set PACKET filter:0x%x\n", + prAdapter->u4OsPacketFilter); + + rSetRxPacketFilter.u4RxPacketFilter = + prAdapter->u4OsPacketFilter; + wlanoidSetPacketFilter(prAdapter, + &rSetRxPacketFilter, + FALSE, + &u4NewPacketFilter, + sizeof(u4NewPacketFilter)); + + } while (FALSE); +} /* p2pFuncMgmtFrameRegister */ + +void p2pFuncUpdateMgmtFrameRegister(IN struct ADAPTER *prAdapter, + IN uint32_t u4OsFilter) +{ + struct CMD_RX_PACKET_FILTER rSetRxPacketFilter; + + do { + + /* TODO: Filter need to be done. */ + /* 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); + + rSetRxPacketFilter.u4RxPacketFilter = + prAdapter->u4OsPacketFilter; + wlanoidSetPacketFilter(prAdapter, + &rSetRxPacketFilter, + FALSE, + &u4OsFilter, + sizeof(u4OsFilter)); + DBGLOG(P2P, TRACE, + "P2P Set PACKET filter:0x%x\n", + prAdapter->u4OsPacketFilter); + } + + } while (FALSE); +} /* p2pFuncUpdateMgmtFrameRegister */ + +void p2pFuncGetStationInfo(IN struct ADAPTER *prAdapter, + IN uint8_t *pucMacAddr, + OUT struct P2P_STATION_INFO *prStaInfo) +{ + + do { + ASSERT_BREAK((prAdapter != NULL) + && (pucMacAddr != NULL) && (prStaInfo != NULL)); + + prStaInfo->u4InactiveTime = 0; + prStaInfo->u4RxBytes = 0; + prStaInfo->u4TxBytes = 0; + prStaInfo->u4RxPackets = 0; + prStaInfo->u4TxPackets = 0; + /* TODO: */ + + } while (FALSE); +} /* p2pFuncGetStationInfo */ + +#if 0 +u_int8_t +p2pFuncGetAttriList(IN struct ADAPTER *prAdapter, + IN uint8_t ucOuiType, + IN uint8_t *pucIE, + IN uint16_t u2IELength, + OUT uint8_t **ppucAttriList, + OUT uint16_t *pu2AttriListLen) +{ + u_int8_t fgIsAllocMem = FALSE; + uint8_t aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + uint16_t u2Offset = 0; + struct IE_P2P *prIe = (struct IE_P2P *) NULL; + uint8_t *pucAttriListStart = (uint8_t *) NULL; + uint16_t u2AttriListLen = 0, u2BufferSize; + u_int8_t fgBackupAttributes = FALSE; + + u2BufferSize = 0; + + 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 (IE_ID(pucIE) == ELEM_ID_VENDOR) { + prIe = (struct IE_P2P *) 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)) { + p2pFuncGetAttriListAction(prAdapter, + prIe, ucOuiType, + &pucAttriListStart, + &u2AttriListLen, + &fgIsAllocMem, + &fgBackupAttributes, + &u2BufferSize); + } /* prIe->aucOui */ + } /* ELEM_ID_VENDOR */ + } /* IE_FOR_EACH */ + + } while (FALSE); + + if (pucAttriListStart) { + uint8_t *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) { + /* Todo:: Nothing */ + } else if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + /* Big Endian: WSC, WFD. */ + WSC_ATTRI_FOR_EACH(pucAttribute, + u2AttriListLen, u2Offset) { + DBGLOG(P2P, LOUD, + "Attribute ID:%d, Length:%d.\n", + WSC_ATTRI_ID(pucAttribute), + WSC_ATTRI_LEN(pucAttribute)); + } + } else { + } + + ASSERT(u2Offset == u2AttriListLen); + + *ppucAttriList = pucAttriListStart; + *pu2AttriListLen = u2AttriListLen; + + } else { + *ppucAttriList = (uint8_t *) NULL; + *pu2AttriListLen = 0; + } + + return fgIsAllocMem; +} /* p2pFuncGetAttriList */ + +/* Code refactoring for AOSP */ +static void +p2pFuncGetAttriListAction(IN struct ADAPTER *prAdapter, + IN struct IE_P2P *prIe, + IN uint8_t ucOuiType, + OUT uint8_t **pucAttriListStart, + OUT uint16_t *u2AttriListLen, + OUT u_int8_t *fgIsAllocMem, + OUT u_int8_t *fgBackupAttributes, + OUT uint16_t *u2BufferSize) +{ + do { + if (!(*pucAttriListStart)) { + *pucAttriListStart = &prIe->aucP2PAttributes[0]; + if (prIe->ucLength > P2P_OUI_TYPE_LEN) + *u2AttriListLen = + (uint16_t) + (prIe->ucLength - P2P_OUI_TYPE_LEN); + else + ASSERT(FALSE); + } else { + /* More than 2 attributes. */ + uint16_t u2CopyLen; + + if (*fgBackupAttributes == FALSE) { + struct P2P_SPECIFIC_BSS_INFO + *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) { + uint8_t *pucTmpBuf = (uint8_t *) NULL; + + pucTmpBuf = (uint8_t *) 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 = + (uint16_t) (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((uint8_t *) + ((unsigned long) (*pucAttriListStart) + + (unsigned long) (*u2AttriListLen)), + &prIe->aucP2PAttributes[0], u2CopyLen); + *u2AttriListLen += u2CopyLen; + } + + } + } while (0); +} +#endif + +struct MSDU_INFO *p2pFuncProcessP2pProbeRsp(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, IN struct MSDU_INFO *prMgmtTxMsdu) +{ + struct MSDU_INFO *prRetMsduInfo = prMgmtTxMsdu; + struct WLAN_BEACON_FRAME *prProbeRspFrame = + (struct WLAN_BEACON_FRAME *) NULL; + uint8_t *pucIEBuf = (uint8_t *) NULL; + uint16_t u2Offset = 0, u2IELength = 0, u2ProbeRspHdrLen = 0; + u_int8_t fgIsWSCIE = FALSE; + u_int8_t fgIsWFDIE = FALSE; + u_int8_t fgIsVenderIE = FALSE; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + uint16_t u2EstimateSize = 0, u2EstimatedExtraIELen = 0; + uint32_t u4IeArraySize = 0, u4Idx = 0; + u_int8_t u4P2PIEIdx = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMgmtTxMsdu != NULL)); + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + + /* 3 Make sure this is probe response frame. */ + prProbeRspFrame = (struct WLAN_BEACON_FRAME *) + ((unsigned long) 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 0 /*CFG_SUPPORT_WFD*/ + /* Reset in each time ?? */ + prAdapter->prGlueInfo + ->prP2PInfo[prP2pBssInfo->u4PrivateData] + ->u2WFDIELen = 0; +#endif +#if CFG_SUPPORT_CUSTOM_VENDOR_IE + prAdapter->prGlueInfo + ->prP2PInfo[prP2pBssInfo->u4PrivateData] + ->u2VenderIELen = 0; +#endif + + + IE_FOR_EACH(pucIEBuf, u2IELength, u2Offset) { + switch (IE_ID(pucIEBuf)) { + case ELEM_ID_SSID: + { + p2pFuncProcessP2pProbeRspAction( + prAdapter, + pucIEBuf, ELEM_ID_SSID, + &ucBssIdx, + &prP2pBssInfo, + &fgIsWSCIE, + &u4P2PIEIdx, + &fgIsWFDIE, + &fgIsVenderIE); + } + break; + case ELEM_ID_VENDOR: + { + p2pFuncProcessP2pProbeRspAction( + prAdapter, + pucIEBuf, ELEM_ID_VENDOR, + &ucBssIdx, + &prP2pBssInfo, + &fgIsWSCIE, + &u4P2PIEIdx, + &fgIsWFDIE, + &fgIsVenderIE); + } + 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(struct APPEND_VAR_IE_ENTRY); + for (u4Idx = 0; u4Idx < u4IeArraySize; u4Idx++) { + if (txProbeRspIETable[u4Idx].u2EstimatedFixedIELen) { + u2EstimatedExtraIELen += + txProbeRspIETable[u4Idx] + .u2EstimatedFixedIELen; + } + + else { + ASSERT(txProbeRspIETable[u4Idx] + .pfnCalculateVariableIELen); + + u2EstimatedExtraIELen += + (uint16_t) ( + txProbeRspIETable[u4Idx] + .pfnCalculateVariableIELen( + prAdapter, + ucBssIdx, NULL)); + } + + } + + if (fgIsWSCIE) + u2EstimatedExtraIELen += + kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 2, + (uint8_t) prP2pBssInfo->u4PrivateData); + + if (u4P2PIEIdx > 0) { + for (u4Idx = 0; u4Idx < u4P2PIEIdx; u4Idx++) + u2EstimatedExtraIELen += + kalP2PCalP2P_IELen( + prAdapter->prGlueInfo, + u4Idx, + (uint8_t) + prP2pBssInfo->u4PrivateData); + u2EstimatedExtraIELen += + p2pFuncCalculateP2P_IE_NoA(prAdapter, + ucBssIdx, NULL); + } +#if CFG_SUPPORT_WFD + ASSERT(sizeof(prAdapter->prGlueInfo + ->prP2PInfo[prP2pBssInfo->u4PrivateData]->aucWFDIE) + >= + prAdapter->prGlueInfo + ->prP2PInfo[prP2pBssInfo->u4PrivateData]->u2WFDIELen); + + if (fgIsWFDIE) + u2EstimatedExtraIELen += + prAdapter->prGlueInfo + ->prP2PInfo[prP2pBssInfo->u4PrivateData] + ->u2WFDIELen; +#endif +#if CFG_SUPPORT_CUSTOM_VENDOR_IE + if (fgIsVenderIE) + u2EstimatedExtraIELen += + prAdapter->prGlueInfo + ->prP2PInfo[prP2pBssInfo->u4PrivateData] + ->u2VenderIELen; +#endif + + u2EstimateSize += u2EstimatedExtraIELen; + if ((u2EstimateSize) > (prRetMsduInfo->u2FrameLength)) { + /* add sizeof(UINT_64) for Cookie */ + prRetMsduInfo = cnmMgtPktAlloc(prAdapter, + u2EstimateSize + sizeof(uint64_t)); + + if (prRetMsduInfo == NULL) { + DBGLOG(P2P, WARN, + "No packet for sending new probe response, use original one\n"); + prRetMsduInfo = prMgmtTxMsdu; + break; + } + + } + + prRetMsduInfo->ucBssIndex = ucBssIdx; + + /* 3 Compose / Re-compose probe response frame. */ + bssComposeBeaconProbeRespFrameHeaderAndFF((uint8_t *) + ((unsigned long) (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); + + prRetMsduInfo->ucStaRecIndex = prMgmtTxMsdu->ucStaRecIndex; + + for (u4Idx = 0; u4Idx < u4IeArraySize; u4Idx++) { + if (txProbeRspIETable[u4Idx].pfnAppendIE) + txProbeRspIETable[u4Idx] + .pfnAppendIE(prAdapter, prRetMsduInfo); + + } + + if (fgIsWSCIE) { + kalP2PGenWSC_IE(prAdapter->prGlueInfo, + 2, + (uint8_t *) + ((unsigned long) prRetMsduInfo->prPacket + + (unsigned long) prRetMsduInfo->u2FrameLength), + (uint8_t) prP2pBssInfo->u4PrivateData); + + prRetMsduInfo->u2FrameLength += (uint16_t) + kalP2PCalWSC_IELen(prAdapter->prGlueInfo, + 2, + (uint8_t) prP2pBssInfo->u4PrivateData); + } + + if (u4P2PIEIdx > 0) { + for (u4Idx = 0; u4Idx < u4P2PIEIdx; u4Idx++) { + kalP2PGenP2P_IE(prAdapter->prGlueInfo, + u4Idx, + (uint8_t *) + ((unsigned long) + prRetMsduInfo->prPacket + + (unsigned long) + prRetMsduInfo->u2FrameLength), + (uint8_t) prP2pBssInfo->u4PrivateData); + + prRetMsduInfo->u2FrameLength += + (uint16_t) + kalP2PCalP2P_IELen( + prAdapter->prGlueInfo, + u4Idx, + (uint8_t) prP2pBssInfo->u4PrivateData); + } + p2pFuncGenerateP2P_IE_NoA(prAdapter, prRetMsduInfo); + + } +#if CFG_SUPPORT_WFD + if (fgIsWFDIE > 0) { + ASSERT(prAdapter->prGlueInfo + ->prP2PInfo[prP2pBssInfo->u4PrivateData] + ->u2WFDIELen > 0); + kalMemCopy((uint8_t *) + ((unsigned long) prRetMsduInfo->prPacket + + (unsigned long) prRetMsduInfo->u2FrameLength), + prAdapter->prGlueInfo->prP2PInfo + [prP2pBssInfo->u4PrivateData]->aucWFDIE, + prAdapter->prGlueInfo->prP2PInfo + [prP2pBssInfo->u4PrivateData] + ->u2WFDIELen); + prRetMsduInfo->u2FrameLength += + (uint16_t) prAdapter->prGlueInfo + ->prP2PInfo[prP2pBssInfo->u4PrivateData] + ->u2WFDIELen; + + } +#endif /* CFG_SUPPORT_WFD */ +#if CFG_SUPPORT_CUSTOM_VENDOR_IE + if (fgIsVenderIE && + prAdapter->prGlueInfo + ->prP2PInfo[prP2pBssInfo->u4PrivateData] + ->u2VenderIELen > 0) { + kalMemCopy((uint8_t *) + ((unsigned long) prRetMsduInfo->prPacket + + (unsigned long) prRetMsduInfo->u2FrameLength), + prAdapter->prGlueInfo->prP2PInfo + [prP2pBssInfo->u4PrivateData] + ->aucVenderIE, + prAdapter->prGlueInfo->prP2PInfo + [prP2pBssInfo->u4PrivateData] + ->u2VenderIELen); + prRetMsduInfo->u2FrameLength += + (uint16_t) prAdapter->prGlueInfo + ->prP2PInfo[prP2pBssInfo->u4PrivateData] + ->u2VenderIELen; + } +#endif + + } while (FALSE); + + if (prRetMsduInfo != prMgmtTxMsdu) + cnmMgtPktFree(prAdapter, prMgmtTxMsdu); + + return prRetMsduInfo; +} /* p2pFuncProcessP2pProbeRsp */ + +/* Code refactoring for AOSP */ +static void +p2pFuncProcessP2pProbeRspAction(IN struct ADAPTER *prAdapter, + IN uint8_t *pucIEBuf, + IN uint8_t ucElemIdType, + OUT uint8_t *ucBssIdx, + OUT struct BSS_INFO **prP2pBssInfo, + OUT u_int8_t *fgIsWSCIE, + OUT u_int8_t *u4P2PIEIdx, + OUT u_int8_t *fgIsWFDIE, + OUT u_int8_t *fgIsVenderIE) +{ + uint8_t ucOuiType = 0; + uint16_t u2SubTypeVersion = 0; + + switch (ucElemIdType) { + case ELEM_ID_SSID: + { + if (SSID_IE(pucIEBuf)->ucLength > 7) { + for ((*ucBssIdx) = 0; + (*ucBssIdx) < prAdapter->ucHwBssIdNum; + (*ucBssIdx)++) { + *prP2pBssInfo = + GET_BSS_INFO_BY_INDEX( + prAdapter, *ucBssIdx); + if (!(*prP2pBssInfo)) + continue; + if (EQUAL_SSID( + (*prP2pBssInfo)->aucSSID, + (*prP2pBssInfo)->ucSSIDLen, + SSID_IE(pucIEBuf)->aucSSID, + SSID_IE(pucIEBuf)->ucLength)) { + break; + } + } + if ((*ucBssIdx) == prAdapter->ucP2PDevBssIdx) + *prP2pBssInfo = + GET_BSS_INFO_BY_INDEX( + prAdapter, *ucBssIdx); + } else { + *prP2pBssInfo = + GET_BSS_INFO_BY_INDEX( + prAdapter, + prAdapter->ucP2PDevBssIdx); + COPY_SSID( + (*prP2pBssInfo)->aucSSID, + (*prP2pBssInfo)->ucSSIDLen, + SSID_IE(pucIEBuf)->aucSSID, + SSID_IE(pucIEBuf)->ucLength); + + } + } + break; + case ELEM_ID_VENDOR: + if (rsnParseCheckForWFAInfoElem(prAdapter, + pucIEBuf, &ucOuiType, &u2SubTypeVersion)) { + if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + kalP2PUpdateWSC_IE(prAdapter->prGlueInfo, + 2, pucIEBuf, + IE_SIZE(pucIEBuf), + (uint8_t) + ((struct BSS_INFO *)*prP2pBssInfo) + ->u4PrivateData); + *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. + */ + if (*u4P2PIEIdx < MAX_P2P_IE_SIZE) { + kalP2PUpdateP2P_IE( + prAdapter->prGlueInfo, + *u4P2PIEIdx, + pucIEBuf, + IE_SIZE(pucIEBuf), + (uint8_t) + ((struct BSS_INFO *) + *prP2pBssInfo) + ->u4PrivateData); + *u4P2PIEIdx = *u4P2PIEIdx + 1; + } else + DBGLOG(P2P, WARN, + "Too much P2P IE for ProbeResp, skip update\n"); + } +#if CFG_SUPPORT_WFD + else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { + DBGLOG(P2P, INFO, + "WFD IE is found in probe resp (supp). Len %u\n", + IE_SIZE(pucIEBuf)); + if ((sizeof(prAdapter->prGlueInfo->prP2PInfo + [((struct BSS_INFO *)*prP2pBssInfo) + ->u4PrivateData]->aucWFDIE) + >= IE_SIZE(pucIEBuf))) { + *fgIsWFDIE = TRUE; + kalMemCopy(prAdapter->prGlueInfo + ->prP2PInfo + [((struct BSS_INFO *) + *prP2pBssInfo) + ->u4PrivateData]->aucWFDIE, + pucIEBuf, IE_SIZE(pucIEBuf)); + prAdapter->prGlueInfo + ->prP2PInfo + [((struct BSS_INFO *) + *prP2pBssInfo) + ->u4PrivateData]->u2WFDIELen = + IE_SIZE(pucIEBuf); + } + } /* VENDOR_OUI_TYPE_WFD */ +#endif + } else { + DBGLOG(P2P, INFO, + "Other vender IE is found in probe resp (supp). Len %u\n", + IE_SIZE(pucIEBuf)); +#if CFG_SUPPORT_CUSTOM_VENDOR_IE + if ((prAdapter->prGlueInfo->prP2PInfo + [((struct BSS_INFO *)*prP2pBssInfo) + ->u4PrivateData]->u2VenderIELen + + IE_SIZE(pucIEBuf)) < 1024) { + *fgIsVenderIE = TRUE; + kalMemCopy(prAdapter->prGlueInfo + ->prP2PInfo + [((struct BSS_INFO *) + *prP2pBssInfo) + ->u4PrivateData]->aucVenderIE + + prAdapter->prGlueInfo + ->prP2PInfo + [((struct BSS_INFO *) + *prP2pBssInfo) + ->u4PrivateData]->u2VenderIELen, + pucIEBuf, IE_SIZE(pucIEBuf)); + prAdapter->prGlueInfo + ->prP2PInfo + [((struct BSS_INFO *) + *prP2pBssInfo) + ->u4PrivateData]->u2VenderIELen += + IE_SIZE(pucIEBuf); + } +#endif + } + break; + default: + break; + } +} + +#if 0 /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */ +uint32_t +p2pFuncCalculateExtra_IELenForBeacon(IN struct ADAPTER *prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN struct STA_RECORD *prStaRec) +{ + + struct P2P_SPECIFIC_BSS_INFO *prP2pSpeBssInfo = + (struct P2P_SPECIFIC_BSS_INFO *) NULL; + uint32_t 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 struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct P2P_SPECIFIC_BSS_INFO *prP2pSpeBssInfo = + (struct P2P_SPECIFIC_BSS_INFO *) NULL; + uint8_t *pucIEBuf = (uint8_t *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + prP2pSpeBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) + break; + + pucIEBuf = (uint8_t *) ((uint32_t) prMsduInfo->prPacket + + (uint32_t) prMsduInfo->u2FrameLength); + + kalMemCopy(pucIEBuf, + prP2pSpeBssInfo->aucBeaconIECache, + prP2pSpeBssInfo->u2IELenForBCN); + + prMsduInfo->u2FrameLength += prP2pSpeBssInfo->u2IELenForBCN; + + } while (FALSE); +} /* p2pFuncGenerateExtra_IEForBeacon */ + +#else +uint32_t p2pFuncCalculateP2p_IELenForBeacon(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, IN struct STA_RECORD *prStaRec) +{ + struct P2P_SPECIFIC_BSS_INFO *prP2pSpeBssInfo = + (struct P2P_SPECIFIC_BSS_INFO *) NULL; + uint32_t u4IELen = 0; + struct BSS_INFO *prBssInfo; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (ucBssIdx < prAdapter->ucHwBssIdNum)); + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + if (!prAdapter->fgIsP2PRegistered) + break; + + if (p2pFuncIsAPMode( + prAdapter->rWifiVar.prP2PConnSettings + [prBssInfo->u4PrivateData])) + break; + + prP2pSpeBssInfo = + prAdapter->rWifiVar.prP2pSpecificBssInfo + [prBssInfo->u4PrivateData]; + + u4IELen = prP2pSpeBssInfo->u2AttributeLen; + + } while (FALSE); + + return u4IELen; +} /* p2pFuncCalculateP2p_IELenForBeacon */ + +void p2pFuncGenerateP2p_IEForBeacon(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct P2P_SPECIFIC_BSS_INFO *prP2pSpeBssInfo = + (struct P2P_SPECIFIC_BSS_INFO *) NULL; + uint8_t *pucIEBuf = (uint8_t *) NULL; + struct BSS_INFO *prBssInfo; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + if (!prAdapter->fgIsP2PRegistered) + break; + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + + prP2pSpeBssInfo = + prAdapter->rWifiVar.prP2pSpecificBssInfo + [prBssInfo->u4PrivateData]; + + if (p2pFuncIsAPMode( + prAdapter->rWifiVar.prP2PConnSettings + [prBssInfo->u4PrivateData])) + break; + + pucIEBuf = (uint8_t *) ((unsigned long) prMsduInfo->prPacket + + (unsigned long) prMsduInfo->u2FrameLength); + + kalMemCopy(pucIEBuf, + prP2pSpeBssInfo->aucAttributesCache, + prP2pSpeBssInfo->u2AttributeLen); + + prMsduInfo->u2FrameLength += prP2pSpeBssInfo->u2AttributeLen; + + } while (FALSE); +} /* p2pFuncGenerateP2p_IEForBeacon */ + +uint32_t p2pFuncCalculateWSC_IELenForBeacon(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, IN struct STA_RECORD *prStaRec) +{ + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + + if (prP2pBssInfo->eNetworkType != NETWORK_TYPE_P2P) + return 0; + + return kalP2PCalWSC_IELen(prAdapter->prGlueInfo, + 0, (uint8_t) prP2pBssInfo->u4PrivateData); +} /* p2pFuncCalculateP2p_IELenForBeacon */ + +void p2pFuncGenerateWSC_IEForBeacon(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + uint8_t *pucBuffer; + uint16_t u2IELen = 0; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + + if (prP2pBssInfo->eNetworkType != NETWORK_TYPE_P2P) + return; + + u2IELen = (uint16_t) kalP2PCalWSC_IELen(prAdapter->prGlueInfo, + 0, (uint8_t) prP2pBssInfo->u4PrivateData); + + pucBuffer = (uint8_t *) ((unsigned long) prMsduInfo->prPacket + + (unsigned long) prMsduInfo->u2FrameLength); + + ASSERT(pucBuffer); + + /* TODO: Check P2P FSM State. */ + kalP2PGenWSC_IE(prAdapter->prGlueInfo, + 0, pucBuffer, (uint8_t) prP2pBssInfo->u4PrivateData); + + prMsduInfo->u2FrameLength += u2IELen; +} /* p2pFuncGenerateP2p_IEForBeacon */ + +#endif +/*---------------------------------------------------------------------------*/ +/*! + * @brief This function is used to calculate P2P IE length for Beacon frame. + * + * @param[in] eNetTypeIndex Specify which network + * @param[in] prStaRec Pointer to the STA_RECORD_T + * + * @return The length of P2P IE added + */ +/*---------------------------------------------------------------------------*/ +uint32_t p2pFuncCalculateP2p_IELenForAssocRsp(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN struct STA_RECORD *prStaRec) +{ + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (prBssInfo->eNetworkType != NETWORK_TYPE_P2P) + return 0; + + return p2pFuncCalculateP2P_IELen(prAdapter, + ucBssIndex, + prStaRec, + txAssocRspAttributesTable, + sizeof(txAssocRspAttributesTable) / + sizeof(struct APPEND_VAR_ATTRI_ENTRY)); + +} /* 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 struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (!prStaRec) { + DBGLOG(P2P, ERROR, "prStaRec of ucStaRecIndex %d is NULL!\n", + prMsduInfo->ucStaRecIndex); + return; + } + + if (IS_STA_IN_P2P(prStaRec)) { + DBGLOG(P2P, TRACE, "Generate NULL P2P IE for Assoc Rsp.\n"); + + p2pFuncGenerateP2P_IE(prAdapter, + prMsduInfo->ucBssIndex, + TRUE, + &prMsduInfo->u2FrameLength, + prMsduInfo->prPacket, + 1500, + txAssocRspAttributesTable, + sizeof(txAssocRspAttributesTable) / + sizeof(struct APPEND_VAR_ATTRI_ENTRY)); + } else { + + DBGLOG(P2P, TRACE, "Legacy device, no P2P IE.\n"); + } +} /* p2pFuncGenerateP2p_IEForAssocRsp */ + +uint32_t +p2pFuncCalculateP2P_IELen(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct STA_RECORD *prStaRec, + IN struct APPEND_VAR_ATTRI_ENTRY arAppendAttriTable[], + IN uint32_t u4AttriTableSize) +{ + + uint32_t u4OverallAttriLen, u4Dummy; + uint16_t u2EstimatedFixedAttriLen; + uint32_t 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 struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN u_int8_t fgIsAssocFrame, + IN uint16_t *pu2Offset, + IN uint8_t *pucBuf, + IN uint16_t u2BufSize, + IN struct APPEND_VAR_ATTRI_ENTRY arAppendAttriTable[], + IN uint32_t u4AttriTableSize) +{ + uint8_t *pucBuffer = (uint8_t *) NULL; + struct IE_P2P *prIeP2P = (struct IE_P2P *) NULL; + uint32_t u4OverallAttriLen; + uint32_t u4AttriLen; + uint8_t aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + uint8_t aucTempBuffer[P2P_MAXIMUM_ATTRIBUTE_LEN]; + uint32_t i; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL)); + + pucBuffer = (uint8_t *) ((unsigned long) pucBuf + (*pu2Offset)); + + ASSERT_BREAK(pucBuffer != NULL); + + /* Check buffer length is still enough. */ + ASSERT_BREAK((u2BufSize - (*pu2Offset)) >= P2P_IE_OUI_HDR); + + prIeP2P = (struct IE_P2P *) 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, + ucBssIndex, 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 = (uint8_t *) + ((unsigned long) + prIeP2P + + (VENDOR_OUI_TYPE_LEN + + P2P_MAXIMUM_ATTRIBUTE_LEN)); + + prIeP2P = (struct IE_P2P *) + ((unsigned long) 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 = + (uint8_t) (VENDOR_OUI_TYPE_LEN + u4OverallAttriLen); + + } while (FALSE); +} /* p2pFuncGenerateP2P_IE */ + +uint32_t +p2pFuncAppendAttriStatusForAssocRsp(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN u_int8_t fgIsAssocFrame, + IN uint16_t *pu2Offset, + IN uint8_t *pucBuf, + IN uint16_t u2BufSize) +{ + uint8_t *pucBuffer; + struct P2P_ATTRI_STATUS *prAttriStatus; + uint32_t u4AttriLen = 0; + + ASSERT(prAdapter); + ASSERT(pucBuf); + + if (fgIsAssocFrame) + return u4AttriLen; + /* TODO: For assoc request P2P IE check in driver & + * return status in P2P IE. + */ + + pucBuffer = (uint8_t *) + ((unsigned long) pucBuf + + (unsigned long) (*pu2Offset)); + + ASSERT(pucBuffer); + prAttriStatus = (struct P2P_ATTRI_STATUS *) pucBuffer; + + ASSERT(u2BufSize >= ((*pu2Offset) + (uint16_t) u4AttriLen)); + + prAttriStatus->ucId = P2P_ATTRI_ID_STATUS; + WLAN_SET_FIELD_16(&prAttriStatus->u2Length, P2P_ATTRI_MAX_LEN_STATUS); + + prAttriStatus->ucStatusCode = P2P_STATUS_SUCCESS; + + u4AttriLen = (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_STATUS); + + (*pu2Offset) += (uint16_t) u4AttriLen; + + return u4AttriLen; +} /* p2pFuncAppendAttriStatusForAssocRsp */ + +uint32_t +p2pFuncAppendAttriExtListenTiming(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN u_int8_t fgIsAssocFrame, + IN uint16_t *pu2Offset, + IN uint8_t *pucBuf, + IN uint16_t u2BufSize) +{ + uint32_t u4AttriLen = 0; + struct P2P_ATTRI_EXT_LISTEN_TIMING *prP2pExtListenTiming = + (struct P2P_ATTRI_EXT_LISTEN_TIMING *) NULL; + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo = + (struct P2P_SPECIFIC_BSS_INFO *) NULL; + uint8_t *pucBuffer = NULL; + struct BSS_INFO *prBssInfo = NULL; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + ASSERT(prAdapter); + ASSERT(pucBuf); + ASSERT(prBssInfo); + + if (fgIsAssocFrame) + return u4AttriLen; + /* TODO: For extend listen timing. */ + + prP2pSpecificBssInfo = + prAdapter->rWifiVar.prP2pSpecificBssInfo + [prBssInfo->u4PrivateData]; + + u4AttriLen = (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_EXT_LISTEN_TIMING); + + ASSERT(u2BufSize >= ((*pu2Offset) + (uint16_t) u4AttriLen)); + + pucBuffer = (uint8_t *) + ((unsigned long) pucBuf + + (unsigned long) (*pu2Offset)); + + ASSERT(pucBuffer); + + prP2pExtListenTiming = (struct P2P_ATTRI_EXT_LISTEN_TIMING *) 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) += (uint16_t) u4AttriLen; + + return u4AttriLen; +} /* p2pFuncAppendAttriExtListenTiming */ + +struct IE_HDR * +p2pFuncGetSpecIE(IN struct ADAPTER *prAdapter, + IN uint8_t *pucIEBuf, + IN uint16_t u2BufferLen, + IN uint8_t ucElemID, + IN u_int8_t *pfgIsMore) +{ + struct IE_HDR *prTargetIE = (struct IE_HDR *) NULL; + uint8_t *pucIE = (uint8_t *) NULL; + uint16_t u2Offset = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (pucIEBuf != NULL)); + + pucIE = pucIEBuf; + + if (pfgIsMore) + *pfgIsMore = FALSE; + + IE_FOR_EACH(pucIE, u2BufferLen, u2Offset) { + if (IE_ID(pucIE) == ucElemID) { + if ((prTargetIE) && (pfgIsMore)) { + + *pfgIsMore = TRUE; + break; + } + prTargetIE = (struct IE_HDR *) pucIE; + + if (pfgIsMore == NULL) + break; + + } + } + + } while (FALSE); + + return prTargetIE; +} /* p2pFuncGetSpecIE */ + +struct P2P_ATTRIBUTE * +p2pFuncGetSpecAttri(IN struct ADAPTER *prAdapter, + IN uint8_t ucOuiType, + IN uint8_t *pucIEBuf, + IN uint16_t u2BufferLen, + IN uint8_t ucAttriID) +{ + struct IE_P2P *prP2pIE = (struct IE_P2P *) NULL; + struct P2P_ATTRIBUTE *prTargetAttri = (struct P2P_ATTRIBUTE *) NULL; + u_int8_t fgIsMore = FALSE; + uint8_t *pucIE = (uint8_t *) NULL; + uint16_t u2BufferLenLeft = 0; + + DBGLOG(P2P, INFO, + "Check AssocReq Oui type %u attri %u for len %u\n", + ucOuiType, ucAttriID, u2BufferLen); + + do { + ASSERT_BREAK((prAdapter != NULL) + && (pucIEBuf != NULL)); + + u2BufferLenLeft = u2BufferLen; + pucIE = pucIEBuf; + + do { + fgIsMore = FALSE; + prP2pIE = (struct IE_P2P *) p2pFuncGetSpecIE(prAdapter, + pucIE, u2BufferLenLeft, + ELEM_ID_VENDOR, &fgIsMore); + if (prP2pIE) { + ASSERT((unsigned long) prP2pIE + >= (unsigned long) pucIE); + u2BufferLenLeft = u2BufferLen - + (uint16_t) (((unsigned long) prP2pIE) - + ((unsigned long) 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) + p2pFuncGetSpecAttriAction(prP2pIE, + ucOuiType, ucAttriID, + &prTargetAttri); + /* P2P_OUI_TYPE_LEN */ + pucIE = (uint8_t *) + (((unsigned long) prP2pIE) + + IE_SIZE(prP2pIE)); + } + /* prP2pIE */ + } while (prP2pIE && fgIsMore && u2BufferLenLeft); + + } while (FALSE); + + return prTargetAttri; +} + +/* p2pFuncGetSpecAttri */ + +/* Code refactoring for AOSP */ +static void +p2pFuncGetSpecAttriAction(IN struct IE_P2P *prP2pIE, + IN uint8_t ucOuiType, + IN uint8_t ucAttriID, + OUT struct P2P_ATTRIBUTE **prTargetAttri) +{ + uint8_t *pucAttri = (uint8_t *) NULL; + uint16_t u2OffsetAttri = 0; + uint8_t aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + + 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_IE_OUI_HDR), + u2OffsetAttri) { + if (WSC_ATTRI_ID(pucAttri) + == ucAttriID) { + *prTargetAttri = + (struct P2P_ATTRIBUTE *) + pucAttri; + break; + } + + } + + } else if (ucOuiType == VENDOR_OUI_TYPE_P2P) { + P2P_ATTRI_FOR_EACH(pucAttri, + (IE_LEN(prP2pIE) - P2P_IE_OUI_HDR), + u2OffsetAttri) { + if (ATTRI_ID(pucAttri) + == ucAttriID) { + *prTargetAttri = + (struct P2P_ATTRIBUTE *) + pucAttri; + break; + } + } + + } +#if CFG_SUPPORT_WFD + else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { + WFD_ATTRI_FOR_EACH(pucAttri, + (IE_LEN(prP2pIE) - P2P_IE_OUI_HDR), + u2OffsetAttri) { + if (ATTRI_ID(pucAttri) + == (uint8_t) ucAttriID) { + *prTargetAttri = + (struct P2P_ATTRIBUTE *) + pucAttri; + break; + } + } + } +#endif + else { + /* Todo:: Nothing */ + /* Possible or else. */ + } + } + } /* ucOuiType */ +} + +uint32_t +p2pFuncGenerateBeaconProbeRsp(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct MSDU_INFO *prMsduInfo, + IN u_int8_t fgIsProbeRsp) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct WLAN_BEACON_FRAME *prBcnFrame = + (struct WLAN_BEACON_FRAME *) 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 = (struct WLAN_BEACON_FRAME *) prMsduInfo->prPacket; + + return nicUpdateBeaconIETemplate(prAdapter, + IE_UPD_METHOD_UPDATE_ALL, + prBssInfo->ucBssIndex, + prBssInfo->u2CapInfo, + (uint8_t *) prBcnFrame->aucInfoElem, + prMsduInfo->u2FrameLength - + OFFSET_OF(struct WLAN_BEACON_FRAME, aucInfoElem)); + + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncGenerateBeaconProbeRsp */ + +uint32_t +p2pFuncComposeBeaconProbeRspTemplate(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN uint8_t *pucBcnBuffer, + IN uint32_t u4BcnBufLen, + IN u_int8_t fgIsProbeRsp, + IN struct P2P_PROBE_RSP_UPDATE_INFO *prP2pProbeRspInfo, + IN u_int8_t fgSynToFW) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct MSDU_INFO *prMsduInfo = (struct MSDU_INFO *) NULL; + struct WLAN_MAC_HEADER *prWlanBcnFrame = + (struct WLAN_MAC_HEADER *) NULL; + + uint8_t *pucBuffer = (uint8_t *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (pucBcnBuffer != NULL) + && (prP2pBssInfo != NULL)); + + prWlanBcnFrame = (struct WLAN_MAC_HEADER *) 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; + + if (prMsduInfo == NULL) { + rWlanStatus = WLAN_STATUS_FAILURE; + break; + } + + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucStaRecIndex = 0xFF; + prMsduInfo->ucBssIndex = prP2pBssInfo->ucBssIndex; + + } else { + prMsduInfo = prP2pBssInfo->prBeacon; + + if (prMsduInfo == NULL) { + rWlanStatus = WLAN_STATUS_FAILURE; + break; + } + + if (u4BcnBufLen > + (OFFSET_OF(struct WLAN_BEACON_FRAME, + aucInfoElem[0]) + MAX_IE_LENGTH)) { + /* Unexpected error, buffer overflow. */ + ASSERT(FALSE); + break; + } + + } + + pucBuffer = (uint8_t *) + ((unsigned long) (prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + + kalMemCopy(pucBuffer, pucBcnBuffer, u4BcnBufLen); + + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = (uint16_t) u4BcnBufLen; + + if (fgSynToFW) + rWlanStatus = p2pFuncGenerateBeaconProbeRsp(prAdapter, + prP2pBssInfo, prMsduInfo, fgIsProbeRsp); + + } while (FALSE); + + return rWlanStatus; + +} /* p2pFuncComposeBeaconTemplate */ + +uint32_t wfdFuncCalculateWfdIELenForAssocRsp(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct STA_RECORD *prStaRec) +{ + +#if CFG_SUPPORT_WFD_COMPOSE_IE + uint16_t u2EstimatedExtraIELen = 0; + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + struct WFD_CFG_SETTINGS *prWfdCfgSettings = + (struct WFD_CFG_SETTINGS *) NULL; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + prWfdCfgSettings = &(prAdapter->rWifiVar.rWfdConfigureSettings); + + if (prBssInfo->eNetworkType != NETWORK_TYPE_P2P) + return 0; + + if (!IS_STA_P2P_TYPE(prStaRec) || !prWfdCfgSettings->ucWfdEnable) + return 0; + + u2EstimatedExtraIELen = prAdapter->prGlueInfo-> + prP2PInfo[prBssInfo->u4PrivateData]->u2WFDIELen; + + if (u2EstimatedExtraIELen < VENDOR_SPECIFIC_IE_LENGTH) + return u2EstimatedExtraIELen; + else + return 0; +#else + return 0; +#endif +} /* wfdFuncCalculateWfdIELenForAssocRsp */ + +void wfdFuncGenerateWfdIEForAssocRsp(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + +#if CFG_SUPPORT_WFD_COMPOSE_IE + struct STA_RECORD *prStaRec; + uint16_t u2EstimatedExtraIELen; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct GLUE_INFO *prGlueInfo; + struct GL_P2P_INFO *prP2PInfo; + struct WFD_CFG_SETTINGS *prWfdCfgSettings = + (struct WFD_CFG_SETTINGS *) NULL; + + if (!prAdapter || !prMsduInfo) + return; + + prGlueInfo = prAdapter->prGlueInfo; + if (!prGlueInfo) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + if (!prStaRec) + return; + + if (!IS_STA_P2P_TYPE(prStaRec)) + return; + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + if (!prP2pBssInfo) + return; + + prP2PInfo = prGlueInfo->prP2PInfo[prP2pBssInfo->u4PrivateData]; + if (!prP2PInfo) + return; + + prWfdCfgSettings = &(prAdapter->rWifiVar.rWfdConfigureSettings); + if (!prWfdCfgSettings->ucWfdEnable) + return; + + u2EstimatedExtraIELen = prP2PInfo->u2WFDIELen; + if (u2EstimatedExtraIELen > 0 && + u2EstimatedExtraIELen < VENDOR_SPECIFIC_IE_LENGTH) { + kalMemCopy(prMsduInfo->prPacket + prMsduInfo->u2FrameLength, + prP2PInfo->aucWFDIE, u2EstimatedExtraIELen); + prMsduInfo->u2FrameLength += u2EstimatedExtraIELen; + } + + return; +#else + + return; +#endif +} /* wfdFuncGenerateWfdIEForAssocRsp */ + +void +p2pFuncComposeNoaAttribute(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + OUT uint8_t *aucNoaAttrArray, + OUT uint32_t *pu4Len) +{ + struct BSS_INFO *prBssInfo = NULL; + struct P2P_ATTRI_NOA *prNoaAttr = NULL; + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo = NULL; + struct NOA_DESCRIPTOR *prNoaDesc = NULL; + uint32_t u4NumOfNoaDesc = 0; + uint32_t i = 0; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + prP2pSpecificBssInfo = + prAdapter->rWifiVar + .prP2pSpecificBssInfo[prBssInfo->u4PrivateData]; + + prNoaAttr = (struct P2P_ATTRI_NOA *) aucNoaAttrArray; + + prNoaAttr->ucId = P2P_ATTRI_ID_NOTICE_OF_ABSENCE; + prNoaAttr->ucIndex = prP2pSpecificBssInfo->ucNoAIndex; + + if (prP2pSpecificBssInfo->fgEnableOppPS) { + prNoaAttr->ucCTWOppPSParam = + P2P_CTW_OPPPS_PARAM_OPPPS_FIELD | + (prP2pSpecificBssInfo->u2CTWindow & + P2P_CTW_OPPPS_PARAM_CTWINDOW_MASK); + } else { + prNoaAttr->ucCTWOppPSParam = 0; + } + + for (i = 0; i < prP2pSpecificBssInfo->ucNoATimingCount; i++) { + if (prP2pSpecificBssInfo->arNoATiming[i].fgIsInUse) { + prNoaDesc = (struct NOA_DESCRIPTOR *) + &prNoaAttr->aucNoADesc + [i * sizeof(struct NOA_DESCRIPTOR)]; + + prNoaDesc->ucCountType = + prP2pSpecificBssInfo->arNoATiming[i].ucCount; + prNoaDesc->u4Duration = + prP2pSpecificBssInfo->arNoATiming[i].u4Duration; + prNoaDesc->u4Interval = + prP2pSpecificBssInfo->arNoATiming[i].u4Interval; + prNoaDesc->u4StartTime = + prP2pSpecificBssInfo->arNoATiming[i] + .u4StartTime; + + u4NumOfNoaDesc++; + } + } + + /* include "index" + "OppPs Params" + "NOA descriptors" */ + prNoaAttr->u2Length = 2 + + u4NumOfNoaDesc * sizeof(struct NOA_DESCRIPTOR); + + /* include "Attribute ID" + "Length" + "index" + + * "OppPs Params" + "NOA descriptors" + */ + *pu4Len = P2P_ATTRI_HDR_LEN + prNoaAttr->u2Length; +} + +uint32_t p2pFuncCalculateP2P_IE_NoA(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct STA_RECORD *prStaRec) +{ + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo = NULL; + uint8_t ucIdx; + uint32_t u4NumOfNoaDesc = 0; + struct BSS_INFO *prBssInfo; + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + if (p2pFuncIsAPMode( + prAdapter->rWifiVar.prP2PConnSettings + [prBssInfo->u4PrivateData])) + return 0; + + prP2pSpecificBssInfo = + prAdapter->rWifiVar.prP2pSpecificBssInfo + [prBssInfo->u4PrivateData]; + + for (ucIdx = 0; + ucIdx < prP2pSpecificBssInfo->ucNoATimingCount; ucIdx++) { + if (prP2pSpecificBssInfo->arNoATiming[ucIdx].fgIsInUse) + u4NumOfNoaDesc++; + } + + /* include "index" + "OppPs Params" + "NOA descriptors" */ + /* include "Attribute ID" + "Length" + "index" + + * "OppPs Params" + "NOA descriptors" + */ + return P2P_ATTRI_HDR_LEN + 2 + + (u4NumOfNoaDesc * sizeof(struct NOA_DESCRIPTOR)); +} + +void p2pFuncGenerateP2P_IE_NoA(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct IE_P2P *prIeP2P; + uint8_t aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + uint32_t u4AttributeLen; + struct BSS_INFO *prBssInfo; + + prBssInfo = + prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + + if (p2pFuncIsAPMode( + prAdapter->rWifiVar.prP2PConnSettings + [prBssInfo->u4PrivateData])) + return; + + prIeP2P = (struct IE_P2P *) + ((unsigned long) prMsduInfo->prPacket + + (uint32_t) prMsduInfo->u2FrameLength); + + prIeP2P->ucId = ELEM_ID_P2P; + prIeP2P->aucOui[0] = aucWfaOui[0]; + prIeP2P->aucOui[1] = aucWfaOui[1]; + prIeP2P->aucOui[2] = aucWfaOui[2]; + prIeP2P->ucOuiType = VENDOR_OUI_TYPE_P2P; + + /* Compose NoA attribute */ + p2pFuncComposeNoaAttribute(prAdapter, + prMsduInfo->ucBssIndex, + prIeP2P->aucP2PAttributes, + &u4AttributeLen); + + prIeP2P->ucLength = VENDOR_OUI_TYPE_LEN + u4AttributeLen; + + prMsduInfo->u2FrameLength += (ELEM_HDR_LEN + prIeP2P->ucLength); + +} + +void p2pFunCleanQueuedMgmtFrame(IN struct ADAPTER *prAdapter, + IN struct P2P_QUEUED_ACTION_FRAME *prFrame) +{ + if (prAdapter == NULL || prFrame == NULL || prFrame->u2Length == 0 || + prFrame->prHeader == NULL) + return; + + DBGLOG(P2P, INFO, "Clean queued p2p action frame.\n"); + + prFrame->ucRoleIdx = 0; + prFrame->u4Freq = 0; + prFrame->u2Length = 0; + cnmMemFree(prAdapter, prFrame->prHeader); + prFrame->prHeader = NULL; +} + +#if CFG_TC1_FEATURE +static u_int8_t p2pFuncSwitchSapChannelToDbdc( + struct ADAPTER *prAdapter, + struct BSS_INFO *prP2pBssInfo, + uint8_t ucStaChannelNum, + uint8_t ucSapChannelNum, + enum ENUM_BAND eStaBand, + enum ENUM_BAND eSapBand) +{ +#if CFG_SUPPORT_DBDC + if (prAdapter->rWifiVar.eDbdcMode == + ENUM_DBDC_MODE_DISABLED) + return FALSE; + + if (eStaBand == eSapBand && + eSapBand == BAND_5G && + ucStaChannelNum != 149) { + + struct RF_CHANNEL_INFO rRfChnlInfo; + + rRfChnlInfo.ucChannelNum = 6; + rRfChnlInfo.eBand = BAND_2G4; + rRfChnlInfo.ucChnlBw = + rlmGetBssOpBwByVhtAndHtOpInfo(prP2pBssInfo); + + DBGLOG(P2P, INFO, + "[DBDC] StaCH(%d), SapCH(%d)\n", + ucStaChannelNum, + ucSapChannelNum); + + cnmSapChannelSwitchReq(prAdapter, + &rRfChnlInfo, + prP2pBssInfo->u4PrivateData); + + return TRUE; + + } +#endif + + return FALSE; +} +#endif + +void p2pFuncSwitchSapChannel( + IN struct ADAPTER *prAdapter) +{ + u_int8_t fgEnable = FALSE; + u_int8_t fgDbDcModeEn = FALSE; + u_int8_t fgIsSapDfs = FALSE; + struct BSS_INFO *prP2pBssInfo = + (struct BSS_INFO *) NULL; + struct BSS_INFO *prAisBssInfo = + (struct BSS_INFO *) NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + uint8_t ucStaChannelNum = 0; + uint8_t ucSapChannelNum = 0; + enum ENUM_BAND eStaBand = BAND_NULL; + enum ENUM_BAND eSapBand = BAND_NULL; + +#if CFG_SUPPORT_DFS_MASTER && CFG_SUPPORT_IDC_CH_SWITCH + fgEnable = TRUE; +#endif + + if (!prAdapter + || !cnmSapIsConcurrent(prAdapter) + || !fgEnable) { + DBGLOG(P2P, TRACE, "Not support concurrent STA + SAP\n"); + goto exit; + } + + prAisBssInfo = aisGetConnectedBssInfo(prAdapter); + if (!prAisBssInfo) { + ucStaChannelNum = 0; +#if CFG_SUPPORT_SAP_DFS_CHANNEL + /* restore DFS channels table */ + wlanUpdateDfsChannelTable(prAdapter->prGlueInfo, + -1, /* p2p role index */ + 0, /* primary channel */ + 0, /* bandwidth */ + 0, /* sco */ + 0 /* center frequency */); +#endif + } else { + /* Get current channel info */ + ucStaChannelNum = prAisBssInfo->ucPrimaryChannel; + eStaBand = (prAisBssInfo->ucPrimaryChannel <= 14) + ? BAND_2G4 : BAND_5G; +#if CFG_SUPPORT_SAP_DFS_CHANNEL + /* restore DFS channels table */ + wlanUpdateDfsChannelTable(prAdapter->prGlueInfo, + -1, /* p2p role index */ + ucStaChannelNum, /* primary channel */ + 0, /* bandwidth */ + 0, /* sco */ + 0 /* center frequency */); +#endif + if (eStaBand != BAND_2G4 && eStaBand != BAND_5G) { + DBGLOG(P2P, WARN, "STA has invalid band\n"); + goto exit; + } + } + + /* Assume only one sap bss info */ + prP2pBssInfo = cnmGetSapBssInfo(prAdapter); + if (!prP2pBssInfo) { + DBGLOG(P2P, TRACE, "SAP is not active\n"); + goto exit; + } + if (prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) { + DBGLOG(P2P, TRACE, "SAP is during initialization\n"); + goto exit; + } + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData); + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, WARN, "SAP is not active\n"); + goto exit; + } + + ucSapChannelNum = prP2pBssInfo->ucPrimaryChannel; + eSapBand = prP2pBssInfo->eBand; + if (eSapBand != BAND_2G4 && eSapBand != BAND_5G) { + DBGLOG(P2P, WARN, "SAP has invalid band\n"); + goto exit; + } + + if (eSapBand == BAND_5G) + fgIsSapDfs = rlmDomainIsLegalDfsChannel(prAdapter, + eSapBand, ucSapChannelNum); + + /* STA is not connected */ + if (ucStaChannelNum == 0) { + if (fgIsSapDfs) { + /* Choose one 5G channel */ + ucStaChannelNum = 36; + eStaBand = BAND_5G; + DBGLOG(P2P, INFO, "[SCC] Choose a channel\n"); + } else { + DBGLOG(P2P, WARN, "STA is not connected\n"); + goto exit; + } + } + +#if CFG_TC1_FEATURE + if (p2pFuncSwitchSapChannelToDbdc( + prAdapter, prP2pBssInfo, + ucStaChannelNum, ucSapChannelNum, + eStaBand, eSapBand)) { + goto exit; + } +#endif + +#if CFG_SUPPORT_DBDC + fgDbDcModeEn = prAdapter->rWifiVar.fgDbDcModeEn; +#endif + + /* Check channel no */ + if (ucStaChannelNum == ucSapChannelNum) { + /* Do nothing, i.e. SCC */ + DBGLOG(P2P, INFO, "[SCC] Keep StaCH(%d)\n", ucStaChannelNum); + goto exit; + } else if (fgDbDcModeEn == TRUE + && (eStaBand != eSapBand) && !fgIsSapDfs) { + /* Do nothing, i.e. DBDC */ + DBGLOG(P2P, INFO, + "[DBDC] Keep StaCH(%d), SapCH(%d)(dfs: %u)\n", + ucStaChannelNum, ucSapChannelNum, fgIsSapDfs); + goto exit; + } else { + /* Otherwise, switch to STA channel, i.e. SCC */ + + struct RF_CHANNEL_INFO rRfChnlInfo; + + /* Use sta ch info to do sap ch switch */ + rRfChnlInfo.ucChannelNum = ucStaChannelNum; + rRfChnlInfo.eBand = eStaBand; + rRfChnlInfo.ucChnlBw = + rlmGetBssOpBwByVhtAndHtOpInfo(prP2pBssInfo); + + DBGLOG(P2P, INFO, + "[SCC] StaCH(%d), SapCH(%d)(dfs: %u)\n", + ucStaChannelNum, ucSapChannelNum, fgIsSapDfs); + + cnmSapChannelSwitchReq(prAdapter, + &rRfChnlInfo, + prP2pBssInfo->u4PrivateData); + + } + +exit: + + DBGLOG(P2P, TRACE, "Check done\n"); + /* return; */ +} + +uint32_t +p2pFunGetPreferredFreqList(IN struct ADAPTER *prAdapter, + IN enum ENUM_IFTYPE eIftype, OUT uint32_t *freq_list, + OUT uint32_t *num_freq_list) +{ + struct BSS_INFO *prAisBssInfo; + uint8_t ucNumOfChannel; + uint32_t i; + struct RF_CHANNEL_INFO *aucChannelList; +#if (CFG_SUPPORT_P2PGO_ACS == 1) + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; +#endif + prAisBssInfo = aisGetConnectedBssInfo(prAdapter); + + aucChannelList = (struct RF_CHANNEL_INFO *) kalMemAlloc( + sizeof(struct RF_CHANNEL_INFO) * MAX_CHN_NUM, + VIR_MEM_TYPE); + if (!aucChannelList) { + DBGLOG(P2P, ERROR, + "Allocate buffer for channel list fail\n"); + return -ENOMEM; + } + kalMemZero(aucChannelList, + sizeof(struct RF_CHANNEL_INFO) * MAX_CHN_NUM); + + + DBGLOG(P2P, INFO, "iftype: %d\n", eIftype); + + if (!prAisBssInfo) { + /* Prefer 5G if STA is NOT connected */ +#if (CFG_SUPPORT_P2PGO_ACS == 1) + if (prWifiVar->ucP2pGoACS == TRUE) { + p2pFunGetAcsBestChList(prAdapter, + BIT(BAND_2G4) | BIT(BAND_5G) + , MAX_BW_20MHZ, BITS(0, 14) + , BITS(0, 14), BITS(0, 14), + &ucNumOfChannel, aucChannelList); + + } else +#endif + { + rlmDomainGetChnlList(prAdapter, BAND_5G, TRUE, + MAX_CHN_NUM, &ucNumOfChannel, aucChannelList); + } + DBGLOG(P2P, INFO, + "ucNumOfChannel: %d\n", + ucNumOfChannel); + for (i = 0; i < ucNumOfChannel; i++) { + freq_list[i] = nicChannelNum2Freq( + aucChannelList[i].ucChannelNum) / 1000; + (*num_freq_list)++; + } + } else if (prAdapter->rWifiVar.eDbdcMode == + ENUM_DBDC_MODE_DISABLED) { + /* DBDC disabled */ + DBGLOG(P2P, INFO, + "Prefer SCC, STA operating channel: %d, conn state: %d", + prAisBssInfo->ucPrimaryChannel, + prAisBssInfo->eConnectionState); + freq_list[0] = nicChannelNum2Freq( + prAisBssInfo->ucPrimaryChannel) / 1000; + (*num_freq_list)++; + } else { + /* DBDC enabled */ + DBGLOG(P2P, INFO, + "STA operating channel: %d, band: %d, conn state: %d", + prAisBssInfo->ucPrimaryChannel, + prAisBssInfo->eBand, + prAisBssInfo->eConnectionState); + if (prAisBssInfo->eBand == BAND_2G4) { + /* Prefer 5G if STA is connected at 2G band */ + rlmDomainGetChnlList(prAdapter, BAND_5G, TRUE, + MAX_CHN_NUM, + &ucNumOfChannel, + aucChannelList); + for (i = 0; i < ucNumOfChannel; i++) { + freq_list[i] = nicChannelNum2Freq( + aucChannelList[i].ucChannelNum) / 1000; + (*num_freq_list)++; + } + + /* Add SCC channel */ + freq_list[i] = nicChannelNum2Freq( + prAisBssInfo->ucPrimaryChannel) / 1000; + (*num_freq_list)++; + } else { + /* Prefer SCC if STA is connected at 5G band */ + freq_list[0] = nicChannelNum2Freq( + prAisBssInfo->ucPrimaryChannel) / 1000; + (*num_freq_list)++; +#if (CFG_SUPPORT_P2PGO_ACS == 1) + if (prWifiVar->ucP2pGoACS == TRUE) { + p2pFunGetAcsBestChList(prAdapter, + BAND_2G4, MAX_BW_20MHZ, + BITS(0, 14), BITS(0, 14), + BITS(0, 14), + &ucNumOfChannel, aucChannelList); + } else +#endif + /* Add 2G channels */ + rlmDomainGetChnlList(prAdapter, BAND_2G4, TRUE, + MAX_CHN_NUM, + &ucNumOfChannel, + aucChannelList); + for (i = 0; i < ucNumOfChannel; i++) { + freq_list[i + 1] = nicChannelNum2Freq( + aucChannelList[i].ucChannelNum) / 1000; + (*num_freq_list)++; + } + } + } + + kalMemFree(aucChannelList, VIR_MEM_TYPE, + sizeof(struct RF_CHANNEL_INFO) * MAX_CHN_NUM); + + return WLAN_STATUS_SUCCESS; +} + +enum ENUM_P2P_CONNECT_STATE +p2pFuncGetP2pActionFrameType(IN struct MSDU_INFO *prMgmtMsdu) +{ + struct WLAN_MAC_HEADER *prWlanHdr = (struct WLAN_MAC_HEADER *) NULL; + struct WLAN_ACTION_FRAME *prActFrame; + uint8_t *pucVendor = NULL; + + prWlanHdr = (struct WLAN_MAC_HEADER *) + ((unsigned long) prMgmtMsdu->prPacket + + MAC_TX_RESERVED_FIELD); + if ((prWlanHdr->u2FrameCtrl & MASK_FRAME_TYPE) != MAC_FRAME_ACTION) + return P2P_CNN_NORMAL; + prActFrame = (struct WLAN_ACTION_FRAME *) prWlanHdr; + if (prActFrame->ucCategory != WLAN_ACTION_PUBLIC) + return P2P_CNN_NORMAL; + if (prActFrame->ucAction != WLAN_PA_VENDOR_SPECIFIC) + return P2P_CNN_NORMAL; + pucVendor = (uint8_t *) prActFrame + 26; + if (*(pucVendor + 0) == 0x50 && + *(pucVendor + 1) == 0x6f && + *(pucVendor + 2) == 0x9a && + *(pucVendor + 3) == 0x09) + return ((uint8_t) *(pucVendor + 4)) + 1; + else + return P2P_CNN_NORMAL; +} + +u_int8_t +p2pFuncCheckOnRocChnl(IN struct RF_CHANNEL_INFO *prTxChnl, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo) +{ + if (prTxChnl == NULL || prChnlReqInfo == NULL) + return FALSE; + + if (prTxChnl->ucChannelNum == prChnlReqInfo->ucReqChnlNum && + prChnlReqInfo->fgIsChannelRequested) + return TRUE; + + return FALSE; +} + +u_int8_t +p2pFuncNeedWaitRsp(IN struct ADAPTER *prAdapter, + IN enum ENUM_P2P_CONNECT_STATE eConnState) +{ + switch (eConnState) { + case P2P_CNN_GO_NEG_REQ: + case P2P_CNN_GO_NEG_RESP: + case P2P_CNN_INVITATION_REQ: + case P2P_CNN_INVITATION_RESP: + case P2P_CNN_DEV_DISC_REQ: + case P2P_CNN_PROV_DISC_REQ: + return TRUE; + default: + return FALSE; + } +} + +void +p2pFunClearAllTxReq(IN struct ADAPTER *prAdapter, + IN struct P2P_MGMT_TX_REQ_INFO *prP2pMgmtTxInfo) +{ + struct P2P_OFF_CHNL_TX_REQ_INFO *prOffChnlTxPkt = + (struct P2P_OFF_CHNL_TX_REQ_INFO *) NULL; + + while (!LINK_IS_EMPTY(&(prP2pMgmtTxInfo->rTxReqLink))) { + LINK_REMOVE_HEAD(&(prP2pMgmtTxInfo->rTxReqLink), + prOffChnlTxPkt, + struct P2P_OFF_CHNL_TX_REQ_INFO *); + if (!prOffChnlTxPkt) + continue; + kalP2PIndicateMgmtTxStatus( + prAdapter->prGlueInfo, + prOffChnlTxPkt->prMgmtTxMsdu, + FALSE); + cnmPktFree(prAdapter, prOffChnlTxPkt->prMgmtTxMsdu); + cnmMemFree(prAdapter, prOffChnlTxPkt); + } +} + +uint8_t p2pFunGetAcsBestCh(IN struct ADAPTER *prAdapter, + IN enum ENUM_BAND eBand, + IN enum ENUM_MAX_BANDWIDTH_SETTING eChnlBw, + IN uint32_t u4LteSafeChnMask_2G, + IN uint32_t u4LteSafeChnMask_5G_1, + IN uint32_t u4LteSafeChnMask_5G_2) +{ + struct RF_CHANNEL_INFO aucChannelList[MAX_CHN_NUM]; + uint8_t ucNumOfChannel; + struct PARAM_GET_CHN_INFO *prGetChnLoad; + uint8_t i; + struct PARAM_PREFER_CHN_INFO rPreferChannel; + + /* reset */ + rPreferChannel.ucChannel = 0; + rPreferChannel.u4Dirtiness = 0xFFFFFFFF; + + kalMemZero(aucChannelList, + sizeof(struct RF_CHANNEL_INFO) * MAX_CHN_NUM); + + rlmDomainGetChnlList(prAdapter, eBand, TRUE, MAX_CHN_NUM, + &ucNumOfChannel, aucChannelList); + + /* + * 2. Calculate each channel's dirty score + */ + prGetChnLoad = &(prAdapter->rWifiVar.rChnLoadInfo); + + DBGLOG(P2P, INFO, "acs chnl mask=[0x%08x][0x%08x][0x%08x]\n", + u4LteSafeChnMask_2G, + u4LteSafeChnMask_5G_1, + u4LteSafeChnMask_5G_2); + + for (i = 0; i < ucNumOfChannel; i++) { + uint8_t ucIdx; + + ucIdx = wlanGetChannelIndex(aucChannelList[i].ucChannelNum); + if (ucIdx >= MAX_CHN_NUM) + continue; + + DBGLOG(P2P, TRACE, "idx: %u, ch: %u, d: %d\n", + ucIdx, + aucChannelList[i].ucChannelNum, + prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtiness); + + if (aucChannelList[i].ucChannelNum <= 14) { + if (!(u4LteSafeChnMask_2G & BIT( + aucChannelList[i].ucChannelNum))) + continue; + } else if ((aucChannelList[i].ucChannelNum >= 36) && + (aucChannelList[i].ucChannelNum <= 144)) { + if (!(u4LteSafeChnMask_5G_1 & BIT( + (aucChannelList[i].ucChannelNum - 36) / 4))) + continue; + } else if ((aucChannelList[i].ucChannelNum >= 149) && + (aucChannelList[i].ucChannelNum <= 181)) { + if (!(u4LteSafeChnMask_5G_2 & BIT( + (aucChannelList[i].ucChannelNum - 149) / 4))) + continue; + } + + if (eBand == BAND_5G && eChnlBw >= MAX_BW_80MHZ && + nicGetVhtS1(aucChannelList[i].ucChannelNum, + VHT_OP_CHANNEL_WIDTH_80) == 0) + continue; + + if (rPreferChannel.u4Dirtiness > + prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtiness) { + rPreferChannel.ucChannel = + prGetChnLoad->rEachChnLoad[ucIdx].ucChannel; + rPreferChannel.u4Dirtiness = + prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtiness; + } + } + + return rPreferChannel.ucChannel; +} +#if (CFG_SUPPORT_P2PGO_ACS == 1) + +void p2pFunGetAcsBestChList(IN struct ADAPTER *prAdapter, + IN uint8_t eBandSel, + IN enum ENUM_MAX_BANDWIDTH_SETTING eChnlBw, + IN uint32_t u4LteSafeChnMask_2G, + IN uint32_t u4LteSafeChnMask_5G_1, + IN uint32_t u4LteSafeChnMask_5G_2, + OUT uint8_t *pucSortChannelNumber, + OUT struct RF_CHANNEL_INFO *paucSortChannelList) +{ + struct PARAM_GET_CHN_INFO *prGetChnLoad; + uint8_t i, ucInUsedCHNumber = 0, ucBandIdx = BAND_2G4; + bool bIs2Gsupport = FALSE, bIs5Gsupport = FALSE; + /* + *Set 2G/5G support + */ + bIs2Gsupport = (eBandSel & BIT(BAND_2G4)) >> 1 ? TRUE : FALSE; + bIs5Gsupport = (eBandSel & BIT(BAND_5G)) >> 2 ? TRUE : FALSE; + /* + * 1. Sort all channels (which are support by current domain) + */ + wlanSortChannel(prAdapter, CHNL_SORT_POLICY_BY_CH_DOMAIN); + /* + * 2. Calculate each channel's dirty score + */ + prGetChnLoad = &(prAdapter->rWifiVar.rChnLoadInfo); + DBGLOG(P2P, INFO, "acs Band=5G[%d]2G[%d]", + bIs5Gsupport, bIs2Gsupport); + DBGLOG(P2P, INFO, "[0x%08x][0x%08x][0x%08x]\n", + u4LteSafeChnMask_2G, + u4LteSafeChnMask_5G_1, + u4LteSafeChnMask_5G_2); + /* + * 3. Skip some un-safe channels + */ + for (i = 0; i < MAX_CHN_NUM; i++) { + DBGLOG(P2P, TRACE, "idx:%x ch: %u, d: %d\n", + i, + prGetChnLoad->rChnRankList[i].ucChannel, + prGetChnLoad->rChnRankList[i].u4Dirtiness); + if ((bIs2Gsupport == TRUE) && + (prGetChnLoad->rChnRankList[i].ucChannel <= 14)) { + ucBandIdx = BAND_2G4; + if (!(u4LteSafeChnMask_2G & BIT( + prGetChnLoad-> + rChnRankList[i].ucChannel))) + continue; + } else if ((bIs5Gsupport == TRUE) && + (prGetChnLoad->rChnRankList[i].ucChannel >= 36) && + (prGetChnLoad->rChnRankList[i].ucChannel <= 144)) { + ucBandIdx = BAND_5G; + if (!(u4LteSafeChnMask_5G_1 & BIT( + (prGetChnLoad-> + rChnRankList[i].ucChannel - 36) / 4))) + continue; + } else if ((bIs5Gsupport == TRUE) && + (prGetChnLoad->rChnRankList[i].ucChannel >= 149) && + (prGetChnLoad->rChnRankList[i].ucChannel <= 181)) { + ucBandIdx = BAND_5G; + if (!(u4LteSafeChnMask_5G_2 & BIT( + (prGetChnLoad-> + rChnRankList[i].ucChannel - 149) / 4))) + continue; + } else { + continue; + } + + if (ucBandIdx == BAND_5G && eChnlBw >= MAX_BW_80MHZ && + nicGetVhtS1(prGetChnLoad->rChnRankList[i].ucChannel, + VHT_OP_CHANNEL_WIDTH_80) == 0) + continue; + (paucSortChannelList+ucInUsedCHNumber)-> + ucChannelNum = + prGetChnLoad-> + rChnRankList[i].ucChannel; + (paucSortChannelList+ucInUsedCHNumber)-> + eBand = ucBandIdx; + DBGLOG(P2P, TRACE, "ACS Usedidx=%d,ch[%d] Dirty=%x\n", + ucInUsedCHNumber, + (paucSortChannelList+ucInUsedCHNumber)-> + ucChannelNum, + prGetChnLoad-> + rChnRankList[i].u4Dirtiness); + ucInUsedCHNumber++; + } + /* + * 4. Dump the Result + */ + *pucSortChannelNumber = ucInUsedCHNumber; + for (i = 0; i < ucInUsedCHNumber; i++) { + DBGLOG(P2P, INFO, "ACS idx=%d,ch[%d] Dirty=%x\n", + i, + (paucSortChannelList+i)->ucChannelNum, + prGetChnLoad->rChnRankList[i].u4Dirtiness); + } + /*return rPreferChannel.ucChannel*/ +} +#endif + +void p2pFunProcessAcsReport(IN struct ADAPTER *prAdapter, + IN uint8_t ucRoleIndex, + IN struct PARAM_GET_CHN_INFO *prLteSafeChnInfo, + IN struct P2P_ACS_REQ_INFO *prAcsReqInfo) +{ + enum ENUM_BAND eBand; + uint32_t u4LteSafeChnMask_2G = -1; + + if (!prAdapter || !prAcsReqInfo) + return; + + if (prAcsReqInfo->eHwMode == P2P_VENDOR_ACS_HW_MODE_11B || + prAcsReqInfo->eHwMode == P2P_VENDOR_ACS_HW_MODE_11G) + eBand = BAND_2G4; + else + eBand = BAND_5G; + + if (prLteSafeChnInfo && (eBand == BAND_2G4)) { + struct LTE_SAFE_CHN_INFO *prLteSafeChnList; + struct RF_CHANNEL_INFO aucChannelList[MAX_2G_BAND_CHN_NUM]; + uint8_t ucNumOfChannel; + uint8_t i; + u_int8_t fgIsMaskValid = FALSE; + + kalMemZero(aucChannelList, + sizeof(struct RF_CHANNEL_INFO) * MAX_2G_BAND_CHN_NUM); + + rlmDomainGetChnlList(prAdapter, eBand, TRUE, + MAX_2G_BAND_CHN_NUM, &ucNumOfChannel, aucChannelList); + + prLteSafeChnList = &prLteSafeChnInfo->rLteSafeChnList; + u4LteSafeChnMask_2G = prLteSafeChnList->au4SafeChannelBitmask[ + ENUM_SAFE_CH_MASK_BAND_2G4]; + + prAcsReqInfo->u4LteSafeChnMask_2G &= u4LteSafeChnMask_2G; + for (i = 0; i < ucNumOfChannel; i++) { + if ((prAcsReqInfo->u4LteSafeChnMask_2G & + BIT(aucChannelList[i].ucChannelNum))) + fgIsMaskValid = TRUE; + } + if (!fgIsMaskValid) { + DBGLOG(P2P, WARN, + "All mask invalid, mark all as valid\n"); + prAcsReqInfo->u4LteSafeChnMask_2G = BITS(1, 14); + } +#if CFG_TC1_FEATURE + /* Restrict 2.4G band channel selection range + * to 1/6/11 per customer's request + */ + prAcsReqInfo->u4LteSafeChnMask_2G &= 0x0842; +#elif CFG_TC10_FEATURE + /* Restrict 2.4G band channel selection range + * to 1~11 per customer's request + */ + prAcsReqInfo->u4LteSafeChnMask_2G &= 0x0FFE; +#endif + } else if (prLteSafeChnInfo && (eBand == BAND_5G)) { + /* Add support for 5G FW mask */ + struct LTE_SAFE_CHN_INFO *prLteSafeChnList = + &prLteSafeChnInfo->rLteSafeChnList; + uint32_t u4LteSafeChnMask_5G_1 = + prLteSafeChnList->au4SafeChannelBitmask + [ENUM_SAFE_CH_MASK_BAND_5G_0]; + uint32_t u4LteSafeChnMask_5G_2 = + prLteSafeChnList->au4SafeChannelBitmask + [ENUM_SAFE_CH_MASK_BAND_5G_1]; + + prAcsReqInfo->u4LteSafeChnMask_5G_1 &= u4LteSafeChnMask_5G_1; + prAcsReqInfo->u4LteSafeChnMask_5G_1 &= u4LteSafeChnMask_5G_2; +#if 1 + /* Restrict 5G band channel selection range + * to 149~161 per customer's request + * 0x0001F means 165~149 + * 0x0000F means 161~149 + */ + prAcsReqInfo->u4LteSafeChnMask_5G_2 &= 0x0000F; +#endif + } + + prAcsReqInfo->ucPrimaryCh = p2pFunGetAcsBestCh(prAdapter, + eBand, + prAcsReqInfo->eChnlBw, + prAcsReqInfo->u4LteSafeChnMask_2G, + prAcsReqInfo->u4LteSafeChnMask_5G_1, + prAcsReqInfo->u4LteSafeChnMask_5G_2); + + p2pFunIndicateAcsResult(prAdapter->prGlueInfo, + prAcsReqInfo); +} + +enum ENUM_CHNL_EXT p2pFunGetSco(IN struct ADAPTER *prAdapter, + enum ENUM_BAND eBand, uint8_t ucPrimaryCh) { + enum ENUM_CHNL_EXT eSCO = CHNL_EXT_SCN; + + if (eBand == BAND_2G4) { + if (ucPrimaryCh != 14) + eSCO = (ucPrimaryCh > 7) ? CHNL_EXT_SCB : CHNL_EXT_SCA; + } else { + if (regd_is_single_sku_en()) { + if (rlmDomainIsLegalChannel(prAdapter, + eBand, + ucPrimaryCh)) + eSCO = rlmSelectSecondaryChannelType(prAdapter, + eBand, + ucPrimaryCh); + } else { + struct DOMAIN_INFO_ENTRY *prDomainInfo = + rlmDomainGetDomainInfo(prAdapter); + struct DOMAIN_SUBBAND_INFO *prSubband; + uint8_t i, j; + + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubband = &prDomainInfo->rSubBand[i]; + if (prSubband->ucBand != eBand) + continue; + for (j = 0; j < prSubband->ucNumChannels; j++) { + if ((prSubband->ucFirstChannelNum + + j * prSubband->ucChannelSpan) == + ucPrimaryCh) { + eSCO = (j & 1) ? + CHNL_EXT_SCB : + CHNL_EXT_SCA; + break; + } + } + + if (j < prSubband->ucNumChannels) + break; /* Found */ + } + } + } + + return eSCO; +} + +uint8_t p2pFunGetSecCh(IN struct ADAPTER *prAdapter, + IN enum ENUM_BAND eBand, + IN enum ENUM_CHNL_EXT eSCO, + IN uint8_t ucPrimaryCh) +{ + uint8_t ucSecondCh; + + if (eSCO == CHNL_EXT_SCN) + return 0; + + if (eSCO == CHNL_EXT_SCA) + ucSecondCh = ucPrimaryCh + CHNL_SPAN_20; + else + ucSecondCh = ucPrimaryCh - CHNL_SPAN_20; + + if (!rlmDomainIsLegalChannel(prAdapter, eBand, ucSecondCh)) + ucSecondCh = 0; + + return ucSecondCh; +} + +void p2pFunIndicateAcsResult(IN struct GLUE_INFO *prGlueInfo, + IN struct P2P_ACS_REQ_INFO *prAcsReqInfo) +{ + uint8_t ucVhtBw = VHT_OP_CHANNEL_WIDTH_20_40; + + if (prAcsReqInfo->ucPrimaryCh == 0) { + if (prAcsReqInfo->eHwMode == P2P_VENDOR_ACS_HW_MODE_11B || + prAcsReqInfo->eHwMode == + P2P_VENDOR_ACS_HW_MODE_11G) { + prAcsReqInfo->ucPrimaryCh = AP_DEFAULT_CHANNEL_2G; + } else { + prAcsReqInfo->ucPrimaryCh = AP_DEFAULT_CHANNEL_5G; + } + DBGLOG(P2P, WARN, "No chosed channel, use default channel %d\n", + prAcsReqInfo->ucPrimaryCh); + } + + if (prAcsReqInfo->eChnlBw > MAX_BW_20MHZ) { + enum ENUM_BAND eBand; + enum ENUM_CHNL_EXT eSCO; + + eBand = prAcsReqInfo->ucPrimaryCh <= 14 ? BAND_2G4 : BAND_5G; + eSCO = p2pFunGetSco(prGlueInfo->prAdapter, + eBand, + prAcsReqInfo->ucPrimaryCh); + + prAcsReqInfo->ucSecondCh = p2pFunGetSecCh( + prGlueInfo->prAdapter, + eBand, + eSCO, + prAcsReqInfo->ucPrimaryCh); + } + + switch (prAcsReqInfo->eChnlBw) { + case MAX_BW_20MHZ: + case MAX_BW_40MHZ: + ucVhtBw = VHT_OP_CHANNEL_WIDTH_20_40; + break; + case MAX_BW_80MHZ: + ucVhtBw = VHT_OP_CHANNEL_WIDTH_80; + break; + case MAX_BW_160MHZ: + ucVhtBw = VHT_OP_CHANNEL_WIDTH_160; + break; + case MAX_BW_80_80_MHZ: + ucVhtBw = VHT_OP_CHANNEL_WIDTH_80P80; + break; + default: + ucVhtBw = VHT_OP_CHANNEL_WIDTH_20_40; + break; + } + prAcsReqInfo->ucCenterFreqS1 = nicGetVhtS1( + prAcsReqInfo->ucPrimaryCh, + ucVhtBw); + + if (prAcsReqInfo->eChnlBw != VHT_OP_CHANNEL_WIDTH_80P80) + prAcsReqInfo->ucCenterFreqS2 = 0; + else + DBGLOG(P2P, ERROR, "Not support 80+80 bw.\n"); + + prAcsReqInfo->fgIsProcessing = FALSE; + kalP2pIndicateAcsResult(prGlueInfo, + prAcsReqInfo->ucRoleIdx, + prAcsReqInfo->ucPrimaryCh, + prAcsReqInfo->ucSecondCh, + prAcsReqInfo->ucCenterFreqS1, + prAcsReqInfo->ucCenterFreqS2, + prAcsReqInfo->eChnlBw); +} + +void p2pFunCalAcsChnScores(IN struct ADAPTER *prAdapter) +{ + struct BSS_DESC *prBssDesc = NULL; + struct PARAM_GET_CHN_INFO *prChnLoadInfo; + struct LINK *prBSSDescList = NULL; + struct SCAN_INFO *prgScanInfo = NULL; + + if (!prAdapter) + return; + + prgScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prgScanInfo->rBSSDescList; + prChnLoadInfo = &prAdapter->rWifiVar.rChnLoadInfo; + + /* Clear old ACS data (APNum, Dirtiness, ...) + * and initialize the ch number + */ + kalMemZero(&(prAdapter->rWifiVar.rChnLoadInfo), + sizeof(prAdapter->rWifiVar.rChnLoadInfo)); + wlanInitChnLoadInfoChannelList(prAdapter); + + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, + rLinkEntry, struct BSS_DESC) { + uint8_t ucIdx = wlanGetChannelIndex( + prBssDesc->ucChannelNum); + + if (ucIdx >= MAX_CHN_NUM) + continue; + prChnLoadInfo->rEachChnLoad[ucIdx].u2APNum++; + } + + wlanCalculateAllChannelDirtiness(prAdapter); + wlanSortChannel(prAdapter, CHNL_SORT_POLICY_ALL_CN); +} + +enum ENUM_CHNL_SWITCH_POLICY +p2pFunDetermineChnlSwitchPolicy(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct RF_CHANNEL_INFO *prNewChannelInfo) +{ + enum ENUM_CHNL_SWITCH_POLICY ePolicy = CHNL_SWITCH_POLICY_CSA; + +#if CFG_SEND_DEAUTH_DURING_CHNL_SWITCH + struct BSS_INFO *prBssInfo; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + + /* Send deauth frame to clients: + * 1. Cross band + * 2. BW > 20MHz + */ + if (prNewChannelInfo->eBand == BAND_5G || + (prBssInfo && prBssInfo->eBand == BAND_5G && + prNewChannelInfo->eBand == BAND_2G4)) + ePolicy = CHNL_SWITCH_POLICY_DEAUTH; +#endif + + return ePolicy; +} + +void +p2pFunNotifyChnlSwitch(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + enum ENUM_CHNL_SWITCH_POLICY ePolicy, + IN struct RF_CHANNEL_INFO *prNewChannelInfo) +{ + struct BSS_INFO *prBssInfo; + struct LINK *prClientList; + struct STA_RECORD *prCurrStaRec; + + DBGLOG(P2P, INFO, "bss index: %d, policy: %d\n", ucBssIdx, ePolicy); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + prClientList = &prBssInfo->rStaRecOfClientList; + + switch (ePolicy) { + case CHNL_SWITCH_POLICY_DEAUTH: + if (prClientList && prClientList->u4NumElem > 0) { + LINK_FOR_EACH_ENTRY(prCurrStaRec, prClientList, + rLinkEntry, struct STA_RECORD) { + struct TIMER *prTimer; + + if (!prCurrStaRec) + break; + + prTimer = &(prCurrStaRec->rDeauthTxDoneTimer); + + p2pFuncDisconnect(prAdapter, prBssInfo, + prCurrStaRec, TRUE, + REASON_CODE_DEAUTH_LEAVING_BSS); + + if (!timerPendingTimer(prTimer)) { + cnmTimerInitTimer(prAdapter, + prTimer, + (PFN_MGMT_TIMEOUT_FUNC) + p2pRoleFsmDeauthTimeout, + (unsigned long) prCurrStaRec); + cnmTimerStartTimer(prAdapter, + prTimer, + P2P_DEAUTH_TIMEOUT_TIME_MS); + } + } + /* wait for deauth TX done & switch channel */ + } else { + p2pFunChnlSwitchNotifyDone(prAdapter); + } + break; + case CHNL_SWITCH_POLICY_CSA: + /* Set CSA IE */ + prAdapter->rWifiVar.fgCsaInProgress = TRUE; + prAdapter->rWifiVar.ucChannelSwitchMode = 1; + prAdapter->rWifiVar.ucNewChannelNumber = + prNewChannelInfo->ucChannelNum; + prAdapter->rWifiVar.ucChannelSwitchCount = 5; + + /* Send Action Frame */ + rlmSendChannelSwitchFrame(prAdapter, prBssInfo->ucBssIndex); + + /* Update Beacon */ + bssUpdateBeaconContent(prAdapter, prBssInfo->ucBssIndex); + break; + default: + DBGLOG(P2P, WARN, "invalid policy for channel switch: %d\n", + ePolicy); + break; + } +} + +void +p2pFunChnlSwitchNotifyDone(IN struct ADAPTER *prAdapter) +{ + struct BSS_INFO *prBssInfo; + struct MSG_P2P_CSA_DONE *prP2pCsaDoneMsg; + + if (!prAdapter) + return; + + prBssInfo = cnmGetSapBssInfo(prAdapter); + if (!prBssInfo) + return; + + prP2pCsaDoneMsg = (struct MSG_P2P_CSA_DONE *) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(*prP2pCsaDoneMsg)); + + if (!prP2pCsaDoneMsg) { + log_dbg(CNM, ERROR, "allocate for prP2pCsaDoneMsg failed!\n"); + return; + } + + DBGLOG(CNM, INFO, "ucBssIndex = %d\n", prBssInfo->ucBssIndex); + + prP2pCsaDoneMsg->rMsgHdr.eMsgId = MID_CNM_P2P_CSA_DONE; + prP2pCsaDoneMsg->ucBssIndex = prBssInfo->ucBssIndex; + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *) prP2pCsaDoneMsg, + MSG_SEND_METHOD_BUF); +} + +uint8_t p2pFuncIsBufferableMMPDU(IN struct ADAPTER *prAdapter, + IN enum ENUM_P2P_CONNECT_STATE eConnState, + IN struct MSDU_INFO *prMgmtTxMsdu) +{ + struct WLAN_MAC_HEADER *prWlanHdr = (struct WLAN_MAC_HEADER *) NULL; + uint16_t u2TxFrameCtrl; + uint8_t fgIsBufferableMMPDU = FALSE; + + prWlanHdr = (struct WLAN_MAC_HEADER *) + ((unsigned long) prMgmtTxMsdu->prPacket + + MAC_TX_RESERVED_FIELD); + + if (!prWlanHdr) { + DBGLOG(P2P, ERROR, "prWlanHdr is NULL\n"); + return FALSE; + } + u2TxFrameCtrl = prWlanHdr->u2FrameCtrl & MASK_FRAME_TYPE; + + switch (u2TxFrameCtrl) { + case MAC_FRAME_ACTION: + switch (eConnState) { + case P2P_CNN_GO_NEG_REQ: + case P2P_CNN_GO_NEG_RESP: + case P2P_CNN_GO_NEG_CONF: + case P2P_CNN_INVITATION_REQ: + case P2P_CNN_INVITATION_RESP: + fgIsBufferableMMPDU = FALSE; + break; + default: + fgIsBufferableMMPDU = TRUE; + break; + } + break; + case MAC_FRAME_DISASSOC: + case MAC_FRAME_DEAUTH: + fgIsBufferableMMPDU = TRUE; + break; + default: + fgIsBufferableMMPDU = FALSE; + break; + } + DBGLOG(P2P, TRACE, "fgIsBufferableMMPDU = %u\n", fgIsBufferableMMPDU); + return fgIsBufferableMMPDU; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_ie.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_ie.c new file mode 100644 index 0000000000000..b780c05164def --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_ie.c @@ -0,0 +1,238 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#include "precomp.h" + +uint32_t p2pCalculate_IEForAssocReq(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct STA_RECORD *prStaRec) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct P2P_CONNECTION_REQ_INFO *prConnReqInfo = + (struct P2P_CONNECTION_REQ_INFO *) NULL; + uint32_t u4RetValue = 0; + + do { + ASSERT_BREAK((prStaRec != NULL) && (prAdapter != NULL)); + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + (uint8_t) prP2pBssInfo->u4PrivateData); + + prConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + + u4RetValue = prConnReqInfo->u4BufLength; + + /* ADD WMM Information Element */ + u4RetValue += (ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_INFO); + + /* ADD HT Capability */ + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet + & PHY_TYPE_SET_802_11N) + && (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) { + u4RetValue += (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP); + } +#if CFG_SUPPORT_802_11AC + /* ADD VHT Capability */ + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet + & PHY_TYPE_SET_802_11AC) + && (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11AC)) { + u4RetValue += (ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP); + } +#endif + +#if CFG_SUPPORT_802_11AX + /* ADD HE Capability */ + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet + & PHY_TYPE_SET_802_11AX) + && (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11AX)) { + u4RetValue += heRlmCalculateHeCapIELen(prAdapter, + prStaRec->ucBssIndex, prStaRec); + } +#endif + +#if CFG_SUPPORT_MTK_SYNERGY + if (prAdapter->rWifiVar.ucMtkOui == FEATURE_ENABLED) + u4RetValue += (ELEM_HDR_LEN + ELEM_MIN_LEN_MTK_OUI); +#endif + } 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 struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct P2P_CONNECTION_REQ_INFO *prConnReqInfo = + (struct P2P_CONNECTION_REQ_INFO *) NULL; + uint8_t *pucIEBuf = (uint8_t *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + prBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, + prMsduInfo->ucBssIndex); + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + (uint8_t) prBssInfo->u4PrivateData); + + prConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + + pucIEBuf = (uint8_t *) ((unsigned long) prMsduInfo->prPacket + + (unsigned long) prMsduInfo->u2FrameLength); + + kalMemCopy(pucIEBuf, prConnReqInfo->aucIEBuf, + prConnReqInfo->u4BufLength); + + prMsduInfo->u2FrameLength += prConnReqInfo->u4BufLength; + + /* Add WMM IE */ + mqmGenerateWmmInfoIE(prAdapter, prMsduInfo); + + /* Add HT IE */ + rlmReqGenerateHtCapIE(prAdapter, prMsduInfo); + +#if CFG_SUPPORT_802_11AC + /* Add VHT IE */ + rlmReqGenerateVhtCapIE(prAdapter, prMsduInfo); +#endif + +#if CFG_SUPPORT_802_11AX + /* Add HE IE */ + heRlmReqGenerateHeCapIE(prAdapter, prMsduInfo); +#endif + +#if CFG_SUPPORT_MTK_SYNERGY + rlmGenerateMTKOuiIE(prAdapter, prMsduInfo); +#endif + } while (FALSE); + + return; + +} /* p2pGenerate_IEForAssocReq */ + +uint32_t +wfdFuncAppendAttriDevInfo(IN struct ADAPTER *prAdapter, + IN u_int8_t fgIsAssocFrame, + IN uint16_t *pu2Offset, + IN uint8_t *pucBuf, + IN uint16_t u2BufSize) +{ + uint32_t u4AttriLen = 0; + uint8_t *pucBuffer = NULL; + struct WFD_DEVICE_INFORMATION_IE *prWfdDevInfo = + (struct WFD_DEVICE_INFORMATION_IE *) NULL; + struct WFD_CFG_SETTINGS *prWfdCfgSettings = + (struct WFD_CFG_SETTINGS *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (pucBuf != NULL) && (pu2Offset != NULL)); + + prWfdCfgSettings = &(prAdapter->rWifiVar.rWfdConfigureSettings); + + ASSERT_BREAK((prWfdCfgSettings != NULL)); + + if ((prWfdCfgSettings->ucWfdEnable == 0) || + ((prWfdCfgSettings->u4WfdFlag + & WFD_FLAGS_DEV_INFO_VALID) == 0)) { + break; + } + + pucBuffer = (uint8_t *) ((unsigned long) pucBuf + + (unsigned long) (*pu2Offset)); + + ASSERT_BREAK(pucBuffer != NULL); + + prWfdDevInfo = (struct WFD_DEVICE_INFORMATION_IE *) 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) += (uint16_t) u4AttriLen; + + return u4AttriLen; +} + +/* wfdFuncAppendAttriDevInfo */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_rlm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_rlm.c new file mode 100644 index 0000000000000..3244291e1eadd --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_rlm.c @@ -0,0 +1,1399 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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" +#include "rlm.h" + +/****************************************************************************** + * C O N S T A N T S + ****************************************************************************** + */ + +/****************************************************************************** + * D A T A T Y P E S + ****************************************************************************** + */ + +/****************************************************************************** + * P U B L I C D A T A + ****************************************************************************** + */ + +/****************************************************************************** + * P R I V A T E D A T A + ****************************************************************************** + */ + +/****************************************************************************** + * M A C R O S + ****************************************************************************** + */ + +/****************************************************************************** + * F U N C T I O N D E C L A R A T I O N S + ****************************************************************************** + */ + +/****************************************************************************** + * F U N C T I O N S + ****************************************************************************** + */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Init AP Bss + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmBssInitForAP(struct ADAPTER *prAdapter, struct BSS_INFO *prBssInfo) +{ + uint8_t i; + uint8_t ucMaxBw = 0; + + 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; + + /* Check if AP can set its bw to 40MHz + * But if any of BSS is setup in 40MHz, + * the second BSS would prefer to use 20MHz + * in order to remain in SCC case + */ + if (cnmBss40mBwPermitted(prAdapter, prBssInfo->ucBssIndex)) { + + prBssInfo->eBssSCO = rlmGetScoForAP(prAdapter, prBssInfo); + + if (prBssInfo->eBssSCO != CHNL_EXT_SCN) { + prBssInfo->fg40mBwAllowed = TRUE; + prBssInfo->fgAssoc40mBwAllowed = TRUE; + + prBssInfo->ucHtOpInfo1 = (uint8_t) + (((uint32_t) prBssInfo->eBssSCO) + | HT_OP_INFO1_STA_CHNL_WIDTH); + + rlmUpdateBwByChListForAP(prAdapter, prBssInfo); + } + } + + /* Filled the VHT BW/S1/S2 and MCS rate set */ + if (prBssInfo->ucPhyTypeSet & PHY_TYPE_BIT_VHT) { + for (i = 0; i < 8; i++) + prBssInfo->u2VhtBasicMcsSet |= BITS(2 * i, (2 * i + 1)); + prBssInfo->u2VhtBasicMcsSet &= + (VHT_CAP_INFO_MCS_MAP_MCS9 + << VHT_CAP_INFO_MCS_1SS_OFFSET); + + ucMaxBw = cnmGetDbdcBwCapability(prAdapter, + prBssInfo->ucBssIndex); + rlmFillVhtOpInfoByBssOpBw(prBssInfo, ucMaxBw); + + /* If the S1 is invalid, force to change bandwidth */ + if (prBssInfo->ucVhtChannelFrequencyS1 == 0) + prBssInfo->ucVhtChannelWidth = + VHT_OP_CHANNEL_WIDTH_20_40; + } else { + prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_20_40; + prBssInfo->ucVhtChannelFrequencyS1 = 0; + prBssInfo->ucVhtChannelFrequencyS2 = 0; + } + +#if (CFG_SUPPORT_802_11AX == 1) + /* Filled the HE Operation IE */ + if (prBssInfo->ucPhyTypeSet & PHY_TYPE_BIT_HE) { + memset(prBssInfo->ucHeOpParams, 0, HE_OP_BYTE_NUM); + + /* Disable BSS color support*/ + prBssInfo->ucBssColorInfo |= + BIT(HE_OP_BSSCOLOR_BSS_COLOR_DISABLE_SHFT); + + prBssInfo->ucBssColorInfo |= + BIT(HE_OP_BSSCOLOR_BSS_COLOR_SHFT); + + prBssInfo->u2HeBasicMcsSet |= (HE_CAP_INFO_MCS_MAP_MCS7 << 0); + for (i = 1; i < 8; i++) + prBssInfo->u2HeBasicMcsSet |= + (HE_CAP_INFO_MCS_NOT_SUPPORTED << 2 * i); + } else { + memset(prBssInfo->ucHeOpParams, 0, HE_OP_BYTE_NUM); + prBssInfo->ucBssColorInfo = 0; + prBssInfo->u2HeBasicMcsSet = 0; + } +#endif + + /*ERROR HANDLE*/ + if ((prBssInfo->ucVhtChannelWidth == VHT_OP_CHANNEL_WIDTH_80) + || (prBssInfo->ucVhtChannelWidth + == VHT_OP_CHANNEL_WIDTH_160) + || (prBssInfo->ucVhtChannelWidth + == VHT_OP_CHANNEL_WIDTH_80P80)) { + + if (prBssInfo->ucVhtChannelFrequencyS1 == 0) { + DBGLOG(RLM, INFO, + "Wrong AP S1 parameter setting, back to BW20!!!\n"); + + prBssInfo->ucVhtChannelWidth = + VHT_OP_CHANNEL_WIDTH_20_40; + prBssInfo->ucVhtChannelFrequencyS1 = 0; + prBssInfo->ucVhtChannelFrequencyS2 = 0; + } + } + + /* We may limit AP/GO Nss by RfBand in some case, ex CoAnt. + * Recalculte Nss when channel is selected. + */ + cnmOpModeGetTRxNss(prAdapter, + prBssInfo->ucBssIndex, + &prBssInfo->ucOpRxNss, + &prBssInfo->ucOpTxNss); + + DBGLOG(RLM, INFO, + "WLAN AP SCO=%d BW=%d S1=%d S2=%d CH=%d Band=%d TxN=%d RxN=%d\n", + prBssInfo->eBssSCO, + prBssInfo->ucVhtChannelWidth, + prBssInfo->ucVhtChannelFrequencyS1, + prBssInfo->ucVhtChannelFrequencyS2, + prBssInfo->ucPrimaryChannel, + prBssInfo->eBand, + prBssInfo->ucOpTxNss, + prBssInfo->ucOpRxNss); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief For probe response (GO, IBSS) and association response + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmRspGenerateObssScanIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct IE_OBSS_SCAN_PARAM *prObssScanIe; + struct STA_RECORD *prStaRec = + (struct STA_RECORD *) NULL; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prMsduInfo->ucBssIndex); + + if (!prBssInfo) + return; + + if (!IS_BSS_ACTIVE(prBssInfo)) + return; + + /* !RLM_NET_IS_BOW(prBssInfo) && FIXME. */ + if (RLM_NET_IS_11N(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 = (struct IE_OBSS_SCAN_PARAM *) + (((uint8_t *) prMsduInfo->prPacket) + + prMsduInfo->u2FrameLength); + + /* Add 20/40 BSS coexistence IE */ + prObssScanIe->ucId = ELEM_ID_OBSS_SCAN_PARAMS; + prObssScanIe->ucLength = + sizeof(struct IE_OBSS_SCAN_PARAM) - 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rlmUpdateBwByChListForAP(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo) +{ + uint8_t ucLevel; + u_int8_t 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 != (uint8_t) CHNL_EXT_SCN) { + prBssInfo->ucHtOpInfo1 = (uint8_t) 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(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb) +{ + struct ACTION_20_40_COEXIST_FRAME *prRxFrame; + struct IE_20_40_COEXIST *prCoexist; + struct IE_INTOLERANT_CHNL_REPORT *prChnlReport; + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint8_t *pucIE; + uint16_t u2IELength, u2Offset; + uint8_t i, j; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxFrame = (struct ACTION_20_40_COEXIST_FRAME *) prSwRfb->pvHeader; + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (!(prSwRfb->prStaRec)) { + return; + } + + if (prRxFrame->ucAction != ACTION_PUBLIC_20_40_COEXIST + || !prStaRec + || prStaRec->ucStaState != STA_STATE_3 + || prSwRfb->u2PacketLen < (WLAN_MAC_MGMT_HEADER_LEN + 5) + || prSwRfb->prStaRec->ucBssIndex != + /* HIF_RX_HDR_GET_NETWORK_IDX(prSwRfb->prHifRxHdr) != */ + prStaRec->ucBssIndex) { + return; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + 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 = (uint8_t *) &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 = + (struct IE_INTOLERANT_CHNL_REPORT *) 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->ucBssIndex); + 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 rlmHandleObssStatusEventPkt(struct ADAPTER *prAdapter, + struct EVENT_AP_OBSS_STATUS *prObssStatus) +{ + struct BSS_INFO *prBssInfo; + + ASSERT(prAdapter); + ASSERT(prObssStatus); + ASSERT(prObssStatus->ucBssIndex + < prAdapter->ucHwBssIdNum); + + prBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, prObssStatus->ucBssIndex); + + if (prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) + return; + + prBssInfo->fgObssErpProtectMode = + (u_int8_t) prObssStatus->ucObssErpProtectMode; + prBssInfo->eObssHtProtectMode = + (enum ENUM_HT_PROTECT_MODE) prObssStatus->ucObssHtProtectMode; + prBssInfo->eObssGfOperationMode = + (enum ENUM_GF_MODE) prObssStatus->ucObssGfOperationMode; + prBssInfo->fgObssRifsOperationMode = + (u_int8_t) prObssStatus->ucObssRifsOperationMode; + prBssInfo->fgObssBeaconForcedTo20M = + (u_int8_t) 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(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + u_int8_t fgUpdateBeacon) +{ + struct LINK *prStaList; + struct STA_RECORD *prStaRec; + u_int8_t fgErpProtectMode, fgSta40mIntolerant; + u_int8_t fgUseShortPreamble, fgUseShortSlotTime; + enum ENUM_HT_PROTECT_MODE eHtProtectMode; + enum ENUM_GF_MODE eGfOperationMode; + uint8_t 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 = (uint8_t) CHNL_EXT_SCN; + + prStaList = &prBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH_ENTRY(prStaRec, + prStaList, rLinkEntry, struct STA_RECORD) { + if (!prStaRec) { + DBGLOG(P2P, WARN, + "NULL STA_REC ptr in BSS client list\n"); + bssDumpClientList(prAdapter, prBssInfo); + break; + } + + if (prStaRec->fgIsInUse + && prStaRec->ucStaState == STA_STATE_3 + && prStaRec->ucBssIndex == prBssInfo->ucBssIndex) { + 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 (prBssInfo->fg40mBwAllowed && + !(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 1 + /* ap mode throughput enhancement + * only 2.4G with B mode client connecion + * use long slot time + */ + if ((!(prStaRec->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME)) + && fgErpProtectMode + && prBssInfo->eBand == BAND_2G4) + fgUseShortSlotTime = FALSE; +#else + if (!(prStaRec->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME)) + fgUseShortSlotTime = FALSE; +#endif + 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 = (uint8_t) + (((uint32_t) 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->ucBssIndex); +} +#if 0 +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct ADAPTER *prAdapter) +{ + struct P2P_CONNECTION_SETTINGS *prP2pConnSetting = + (struct P2P_CONNECTION_SETTINGS *) NULL; + struct DOMAIN_INFO_ENTRY *prDomainInfoEntry = + (struct DOMAIN_INFO_ENTRY *) NULL; + struct DOMAIN_SUBBAND_INFO *prDomainSubBand = + (struct DOMAIN_SUBBAND_INFO *) NULL; + struct CHANNEL_ENTRY_FIELD *prChannelEntryField = + (struct CHANNEL_ENTRY_FIELD *) NULL; + uint32_t u4Idx = 0, u4IdxII = 0; + uint8_t ucBufferSize = P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE; +#if 0 + uint8_t 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 = + (struct CHANNEL_ENTRY_FIELD *) + 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 = + (struct CHANNEL_ENTRY_FIELD *) + ((unsigned long) prChannelEntryField + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (unsigned long) + 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 + /* User not set OPERATE channel. */ + if (prP2pConnSetting->ucOperatingChnl == 0) { + + if (scnQuerySparseChannel(prAdapter, NULL, &ucAutoChnl)) + break; /* while */ + + ucBufferSize = prP2pConnSetting->ucRfChannelListSize; + + prChannelEntryField = + (struct CHANNEL_ENTRY_FIELD *) + prP2pConnSetting->aucChannelEntriesField; + + while (ucBufferSize != 0) { + if (prChannelEntryField + ->ucNumberOfChannels != 0) { + ucAutoChnl = + prChannelEntryField->aucChannelList[0]; + break; /* while */ + } + + else { + prChannelEntryField = + (struct CHANNEL_ENTRY_FIELD *) + ((uint32_t) prChannelEntryField + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (uint32_t) + prChannelEntryField + ->ucNumberOfChannels); + + ucBufferSize -= + (P2P_ATTRI_LEN_CHANNEL_ENTRY + + + prChannelEntryField + ->ucNumberOfChannels); + } + + } + + } +#endif + /* We assume user would not set a channel + * not in the channel list. + * If so, the operating channel still depends + * on target device supporting capability. + */ + + /* TODO: 20110921 frog - */ + /* If the Operating channel is not set, + * a channel from supported channel list is set automatically. + * If there is no supported channel in channel list, + * a DEFAULT channel is set. + */ + + } while (FALSE); + +#if 0 + prP2pConnSetting->ucOperatingChnl = ucAutoChnl; +#endif +} /* rlmFuncInitialChannelList */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Find a common channel list from the local channel list info + * & target channel list info. + * + * \param[in] prAdapter Pointer of ADAPTER_T + * + * \return boolean value if probe response frame is + */ +/*----------------------------------------------------------------------------*/ +void +rlmFuncCommonChannelList(IN struct ADAPTER *prAdapter, + IN struct CHANNEL_ENTRY_FIELD *prChannelEntryII, + IN uint8_t ucChannelListSize) +{ + struct P2P_CONNECTION_SETTINGS *prP2pConnSetting = + (struct P2P_CONNECTION_SETTINGS *) NULL; + struct CHANNEL_ENTRY_FIELD *prChannelEntryI = + (struct CHANNEL_ENTRY_FIELD *) NULL, + prChannelEntryIII = (struct CHANNEL_ENTRY_FIELD *) NULL; + uint8_t aucCommonChannelList[P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE]; + uint8_t ucOriChnlSize = 0, ucNewChnlSize = 0; + + do { + + ASSERT_BREAK(prAdapter != NULL); + + prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings; + + prChannelEntryIII = + (struct CHANNEL_ENTRY_FIELD *) aucCommonChannelList; + + while (ucChannelListSize > 0) { + + prChannelEntryI = + (struct CHANNEL_ENTRY_FIELD *) + 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 = + (struct CHANNEL_ENTRY_FIELD *) + ((unsigned long) + prChannelEntryIII + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (unsigned long) + prChannelEntryIII + ->ucNumberOfChannels); + } + + ucOriChnlSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + + prChannelEntryI->ucNumberOfChannels); + + prChannelEntryI = + (struct CHANNEL_ENTRY_FIELD *) + ((unsigned long) prChannelEntryI + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (unsigned long) + prChannelEntryI->ucNumberOfChannels); + + } + + ucChannelListSize -= + (P2P_ATTRI_LEN_CHANNEL_ENTRY + + prChannelEntryII->ucNumberOfChannels); + + prChannelEntryII = (struct CHANNEL_ENTRY_FIELD *) + ((unsigned long) prChannelEntryII + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (unsigned long) + prChannelEntryII->ucNumberOfChannels); + + } + + kalMemCopy(prP2pConnSetting->aucChannelEntriesField, + aucCommonChannelList, + ucNewChnlSize); + prP2pConnSetting->ucRfChannelListSize = ucNewChnlSize; + + } while (FALSE); +} /* rlmFuncCommonChannelList */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +uint8_t rlmFuncFindOperatingClass(IN struct ADAPTER *prAdapter, + IN uint8_t ucChannelNum) +{ + uint8_t ucRegulatoryClass = 0, ucBufferSize = 0; + struct P2P_CONNECTION_SETTINGS *prP2pConnSetting = + (struct P2P_CONNECTION_SETTINGS *) NULL; + struct CHANNEL_ENTRY_FIELD *prChannelEntryField = + (struct CHANNEL_ENTRY_FIELD *) NULL; + uint32_t u4Idx = 0; + + do { + ASSERT_BREAK(prAdapter != NULL); + + prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings; + ucBufferSize = prP2pConnSetting->ucRfChannelListSize; + prChannelEntryField = + (struct CHANNEL_ENTRY_FIELD *) + prP2pConnSetting->aucChannelEntriesField; + + while (ucBufferSize != 0) { + + for (u4Idx = 0; + u4Idx < prChannelEntryField->ucNumberOfChannels; + u4Idx++) { + if (prChannelEntryField->aucChannelList[u4Idx] + == ucChannelNum) { + ucRegulatoryClass = + prChannelEntryField + ->ucRegulatoryClass; + break; + } + + } + + if (ucRegulatoryClass != 0) + break; /* while */ + + prChannelEntryField = + (struct CHANNEL_ENTRY_FIELD *) + ((unsigned long) prChannelEntryField + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (unsigned long) + prChannelEntryField->ucNumberOfChannels); + + ucBufferSize -= + (P2P_ATTRI_LEN_CHANNEL_ENTRY + + prChannelEntryField->ucNumberOfChannels); + + } + + } while (FALSE); + + return ucRegulatoryClass; +} /* rlmFuncFindOperatingClass */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +u_int8_t +rlmFuncFindAvailableChannel(IN struct ADAPTER *prAdapter, + IN uint8_t ucCheckChnl, + IN uint8_t *pucSuggestChannel, + IN u_int8_t fgIsSocialChannel, + IN u_int8_t fgIsDefaultChannel) +{ + u_int8_t fgIsResultAvailable = FALSE; + struct CHANNEL_ENTRY_FIELD *prChannelEntry = + (struct CHANNEL_ENTRY_FIELD *) NULL; + struct P2P_CONNECTION_SETTINGS *prP2pConnSetting = + (struct P2P_CONNECTION_SETTINGS *) NULL; + uint8_t 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 = + (struct CHANNEL_ENTRY_FIELD *) + 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 = + (struct CHANNEL_ENTRY_FIELD *) + ((unsigned long) prChannelEntry + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (unsigned long) + prChannelEntry->ucNumberOfChannels); + + } + + if ((!fgIsResultAvailable) + && (pucSuggestChannel != NULL)) { + log_dbg(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; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +enum ENUM_CHNL_EXT rlmDecideScoForAP(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo) +{ + struct DOMAIN_SUBBAND_INFO *prSubband; + struct DOMAIN_INFO_ENTRY *prDomainInfo; + uint8_t ucSecondChannel, i, j; + enum ENUM_CHNL_EXT eSCO; + enum ENUM_CHNL_EXT eTempSCO; + /*chip capability*/ + uint8_t ucMaxBandwidth = MAX_BW_80_80_MHZ; + + eSCO = CHNL_EXT_SCN; + eTempSCO = CHNL_EXT_SCN; + + if (prBssInfo->eBand == BAND_2G4) { + if (prBssInfo->ucPrimaryChannel != 14) + eSCO = (prBssInfo->ucPrimaryChannel > 7) + ? CHNL_EXT_SCB : CHNL_EXT_SCA; + } else { + if (regd_is_single_sku_en()) { + if (rlmDomainIsLegalChannel(prAdapter, + prBssInfo->eBand, + prBssInfo->ucPrimaryChannel)) + eSCO = rlmSelectSecondaryChannelType(prAdapter, + prBssInfo->eBand, + prBssInfo->ucPrimaryChannel); + } 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 + CHNL_SPAN_20) + : (prBssInfo->ucPrimaryChannel - CHNL_SPAN_20); + + if (!rlmDomainIsLegalChannel(prAdapter, + prBssInfo->eBand, + ucSecondChannel)) + eSCO = CHNL_EXT_SCN; + } + + /* Overwrite SCO settings by wifi cfg */ + if (IS_BSS_P2P(prBssInfo)) { + /* AP mode */ + if (p2pFuncIsAPMode(prAdapter->rWifiVar + .prP2PConnSettings[prBssInfo->u4PrivateData])) { + if (prAdapter->rWifiVar.ucApSco == CHNL_EXT_SCA + || prAdapter->rWifiVar.ucApSco == CHNL_EXT_SCB) + eTempSCO = + (enum ENUM_CHNL_EXT) + prAdapter->rWifiVar.ucApSco; + } + /* P2P mode */ + else { + if (prAdapter->rWifiVar.ucP2pGoSco == CHNL_EXT_SCA || + prAdapter->rWifiVar.ucP2pGoSco == CHNL_EXT_SCB) { + eTempSCO = + (enum ENUM_CHNL_EXT) + prAdapter->rWifiVar.ucP2pGoSco; + } + } + + /* Check again if it is boundary channel + * and 40MHz BW is permitted + */ + if (eTempSCO != CHNL_EXT_SCN) { + ucSecondChannel = (eTempSCO == CHNL_EXT_SCA) + ? (prBssInfo->ucPrimaryChannel + 4) + : (prBssInfo->ucPrimaryChannel - 4); + if (rlmDomainIsLegalChannel(prAdapter, + prBssInfo->eBand, + ucSecondChannel)) + eSCO = eTempSCO; + } + } + + /* Overwrite SCO settings by wifi cfg bandwidth setting */ + if (IS_BSS_P2P(prBssInfo)) { + /* AP mode */ + if (p2pFuncIsAPMode(prAdapter->rWifiVar + .prP2PConnSettings[prBssInfo->u4PrivateData])) { + if (prBssInfo->eBand == BAND_2G4) + ucMaxBandwidth = + prAdapter->rWifiVar.ucAp2gBandwidth; + else + ucMaxBandwidth = + prAdapter->rWifiVar.ucAp5gBandwidth; + } + /* P2P mode */ + else { + if (prBssInfo->eBand == BAND_2G4) + ucMaxBandwidth = + prAdapter->rWifiVar.ucP2p2gBandwidth; + else + ucMaxBandwidth = + prAdapter->rWifiVar.ucP2p5gBandwidth; + } + + if (ucMaxBandwidth < MAX_BW_40MHZ) + eSCO = CHNL_EXT_SCN; + } + + return eSCO; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief: Get AP secondary channel offset from cfg80211 or wifi.cfg + * + * \param[in] prAdapter Pointer of ADAPTER_T, prBssInfo Pointer of BSS_INFO_T, + * + * \return ENUM_CHNL_EXT_T AP secondary channel offset + */ +/*----------------------------------------------------------------------------*/ +enum ENUM_CHNL_EXT rlmGetScoForAP(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo) +{ + enum ENUM_BAND eBand; + uint8_t ucChannel; + enum ENUM_CHNL_EXT eSCO; + int32_t i4DeltaBw; + uint32_t u4AndOneSCO; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct P2P_CONNECTION_REQ_INFO *prP2pConnReqInfo = + (struct P2P_CONNECTION_REQ_INFO *) NULL; + + prP2pRoleFsmInfo = p2pFuncGetRoleByBssIdx(prAdapter, + prBssInfo->ucBssIndex); + + if (!prAdapter->rWifiVar.ucApChnlDefFromCfg + && prP2pRoleFsmInfo) { + + prP2pConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + eSCO = CHNL_EXT_SCN; + + if (cnmGetBssMaxBw(prAdapter, + prBssInfo->ucBssIndex) == MAX_BW_40MHZ) { + /* If BW 40, compare S0 and primary channel freq */ + if (prP2pConnReqInfo->u4CenterFreq1 + > prP2pConnReqInfo->u2PriChnlFreq) + eSCO = CHNL_EXT_SCA; + else + eSCO = CHNL_EXT_SCB; + } else if (cnmGetBssMaxBw(prAdapter, + prBssInfo->ucBssIndex) > MAX_BW_40MHZ) { + /* P: PriChnlFreq, + * A:CHNL_EXT_SCA, + * B: CHNL_EXT_SCB, -:BW SPAN 5M + */ + /* --|----|--CenterFreq1--|----|-- */ + /* --|----|--CenterFreq1--B----P-- */ + /* --|----|--CenterFreq1--P----A-- */ + i4DeltaBw = prP2pConnReqInfo->u2PriChnlFreq + - prP2pConnReqInfo->u4CenterFreq1; + u4AndOneSCO = CHNL_EXT_SCB; + eSCO = CHNL_EXT_SCA; + if (i4DeltaBw < 0) { + /* --|----|--CenterFreq1--|----|-- */ + /* --P----A--CenterFreq1--|----|-- */ + /* --B----P--CenterFreq1--|----|-- */ + u4AndOneSCO = CHNL_EXT_SCA; + eSCO = CHNL_EXT_SCB; + i4DeltaBw = -i4DeltaBw; + } + i4DeltaBw = i4DeltaBw - (CHANNEL_SPAN_20 >> 1); + if ((i4DeltaBw/CHANNEL_SPAN_20) & 1) + eSCO = u4AndOneSCO; + } + } else { + /* 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)) + eSCO = rlmDecideScoForAP(prAdapter, prBssInfo); + } + return eSCO; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief: Get AP channel number of Channel Center Frequency Segment 0 + * from cfg80211 or wifi.cfg + * + * \param[in] prAdapter Pointer of ADAPTER_T, prBssInfo Pointer of BSS_INFO_T, + * + * \return UINT_8 AP channel number of Channel Center Frequency Segment 0 + */ +/*----------------------------------------------------------------------------*/ +uint8_t rlmGetVhtS1ForAP(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo) +{ + uint32_t ucFreq1Channel; + uint8_t ucPrimaryChannel = prBssInfo->ucPrimaryChannel; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct P2P_CONNECTION_REQ_INFO *prP2pConnReqInfo = + (struct P2P_CONNECTION_REQ_INFO *) NULL; + + prP2pRoleFsmInfo = + p2pFuncGetRoleByBssIdx(prAdapter, prBssInfo->ucBssIndex); + + if (prBssInfo->ucVhtChannelWidth == VHT_OP_CHANNEL_WIDTH_20_40) + return 0; + + if (!prAdapter->rWifiVar.ucApChnlDefFromCfg && prP2pRoleFsmInfo) { + prP2pConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + ucFreq1Channel = + nicFreq2ChannelNum( + prP2pConnReqInfo->u4CenterFreq1 * 1000); + } else + ucFreq1Channel = + nicGetVhtS1(ucPrimaryChannel, + prBssInfo->ucVhtChannelWidth); + + return ucFreq1Channel; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_rlm_obss.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_rlm_obss.c new file mode 100644 index 0000000000000..548c004366396 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_rlm_obss.c @@ -0,0 +1,396 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 uint8_t rlmObssChnlLevelIn2G4(struct BSS_INFO *prBssInfo, + uint8_t ucPriChannel, enum ENUM_CHNL_EXT eExtend); + +static uint8_t rlmObssChnlLevelIn5G(struct BSS_INFO *prBssInfo, + uint8_t ucPriChannel, enum ENUM_CHNL_EXT 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 + */ +/*----------------------------------------------------------------------------*/ +uint8_t rlmObssChnlLevel(struct BSS_INFO *prBssInfo, + enum ENUM_BAND eBand, + uint8_t ucPriChannel, + enum ENUM_CHNL_EXT eExtend) +{ + uint8_t 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 uint8_t rlmObssChnlLevelIn2G4(struct BSS_INFO *prBssInfo, + uint8_t ucPriChannel, + enum ENUM_CHNL_EXT eExtend) +{ + uint8_t i, ucChannelLevel; + uint8_t ucSecChannel, ucCenterChannel; + uint8_t 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 uint8_t rlmObssChnlLevelIn5G(struct BSS_INFO *prBssInfo, + uint8_t ucPriChannel, + enum ENUM_CHNL_EXT eExtend) +{ + uint8_t i, ucChannelLevel; + uint8_t 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(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct SW_RFB *prSwRfb) +{ + struct MSDU_INFO *prMsduInfo; + struct ACTION_20_40_COEXIST_FRAME *prTxFrame; + + /* To do: need an algorithm to do judgement. + * Now always reject request + */ + + prMsduInfo = (struct MSDU_INFO *) + cnmMgtPktAlloc(prAdapter, PUBLIC_ACTION_MAX_LEN); + if (prMsduInfo == NULL) + return; + + DBGLOG(RLM, INFO, "Send 20/40 coexistence rsp frame!\n"); + + prTxFrame = (struct ACTION_20_40_COEXIST_FRAME *) prMsduInfo->prPacket; + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + COPY_MAC_ADDR(prTxFrame->aucDestAddr, + ((struct 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); + + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prBssInfo->ucBssIndex, + prSwRfb->ucStaRecIdx, + WLAN_MAC_MGMT_HEADER_LEN, WLAN_MAC_MGMT_HEADER_HTC_LEN + 5, + NULL, MSDU_RATE_MODE_AUTO); + + /* Send them to HW queue */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_role_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_role_fsm.c new file mode 100644 index 0000000000000..7584df46e17c1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_role_fsm.c @@ -0,0 +1,4123 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#include "precomp.h" +#include "p2p_role_state.h" +#include "gl_p2p_os.h" + +#if 1 +/*lint -save -e64 Type mismatch */ +static uint8_t *apucDebugP2pRoleState[P2P_ROLE_STATE_NUM] = { + (uint8_t *) DISP_STRING("P2P_ROLE_STATE_IDLE"), + (uint8_t *) DISP_STRING("P2P_ROLE_STATE_SCAN"), + (uint8_t *) DISP_STRING("P2P_ROLE_STATE_REQING_CHANNEL"), + (uint8_t *) DISP_STRING("P2P_ROLE_STATE_AP_CHNL_DETECTION"), + (uint8_t *) DISP_STRING("P2P_ROLE_STATE_GC_JOIN"), + (uint8_t *) DISP_STRING("P2P_ROLE_STATE_OFF_CHNL_TX"), +#if (CFG_SUPPORT_DFS_MASTER == 1) + (uint8_t *) DISP_STRING("P2P_ROLE_STATE_DFS_CAC"), + (uint8_t *) DISP_STRING("P2P_ROLE_STATE_SWITCH_CHANNEL"), +#endif +}; + +uint8_t * + p2pRoleFsmGetFsmState( + IN enum ENUM_P2P_ROLE_STATE eCurrentState) { + if (eCurrentState >= 0 && eCurrentState < P2P_ROLE_STATE_NUM) + return apucDebugP2pRoleState[eCurrentState]; + + return (uint8_t *) DISP_STRING("UNKNOWN"); +} + +/*lint -restore */ +#endif /* DBG */ + +void +p2pRoleFsmStateTransition(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN enum ENUM_P2P_ROLE_STATE eNextState); +static u_int8_t +p2pRoleFsmIsAcsProcessing(IN struct ADAPTER *prAdapter, + uint8_t ucRoleIdx); +static void +p2pRoleFsmAbortCurrentAcsReq(IN struct ADAPTER *prAdapter, + IN struct MSG_P2P_ACS_REQUEST *prMsgAcsRequest); + +uint8_t p2pRoleFsmInit(IN struct ADAPTER *prAdapter, + IN uint8_t ucRoleIdx) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct P2P_CHNL_REQ_INFO *prP2pChnlReqInfo = + (struct P2P_CHNL_REQ_INFO *) NULL; + struct P2P_MGMT_TX_REQ_INFO *prP2pMgmtTxReqInfo = + (struct P2P_MGMT_TX_REQ_INFO *) NULL; + struct GL_P2P_INFO *prP2PInfo = NULL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + ASSERT_BREAK( + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, ucRoleIdx) + == NULL); + + prP2pRoleFsmInfo = kalMemAlloc( + sizeof(struct P2P_ROLE_FSM_INFO), + VIR_MEM_TYPE); + + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, ucRoleIdx) = + prP2pRoleFsmInfo; + + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, ERROR, + "Error allocating fsm Info Structure\n"); + break; + } + + kalMemZero(prP2pRoleFsmInfo, sizeof(struct P2P_ROLE_FSM_INFO)); + + prP2pRoleFsmInfo->ucRoleIndex = ucRoleIdx; + + prP2pRoleFsmInfo->eCurrentState = P2P_ROLE_STATE_IDLE; + + prP2pRoleFsmInfo->u4P2pPacketFilter = + PARAM_PACKET_FILTER_SUPPORTED; + + prP2pChnlReqInfo = &prP2pRoleFsmInfo->rChnlReqInfo; + LINK_INITIALIZE(&(prP2pChnlReqInfo->rP2pChnlReqLink)); + + prP2pMgmtTxReqInfo = &prP2pRoleFsmInfo->rMgmtTxInfo; + LINK_INITIALIZE(&prP2pMgmtTxReqInfo->rTxReqLink); + + cnmTimerInitTimer(prAdapter, + &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer), + (PFN_MGMT_TIMEOUT_FUNC) p2pRoleFsmRunEventTimeout, + (unsigned long) prP2pRoleFsmInfo); + +#if CFG_ENABLE_PER_STA_STATISTICS_LOG + cnmTimerInitTimer(prAdapter, + &(prP2pRoleFsmInfo->rP2pRoleFsmGetStatisticsTimer), + (PFN_MGMT_TIMEOUT_FUNC) p2pRoleFsmGetStaStatistics, + (unsigned long) prP2pRoleFsmInfo); +#endif + +#if (CFG_SUPPORT_DFS_MASTER == 1) + cnmTimerInitTimer(prAdapter, + &(prP2pRoleFsmInfo->rDfsShutDownTimer), + (PFN_MGMT_TIMEOUT_FUNC) + p2pRoleFsmRunEventDfsShutDownTimeout, + (unsigned long) prP2pRoleFsmInfo); +#endif + + prP2pBssInfo = cnmGetBssInfoAndInit(prAdapter, + NETWORK_TYPE_P2P, + FALSE); + + if (!prP2pBssInfo) { + DBGLOG(P2P, ERROR, + "Error allocating BSS Info Structure\n"); + break; + } + + BSS_INFO_INIT(prAdapter, prP2pBssInfo); + prP2pRoleFsmInfo->ucBssIndex = prP2pBssInfo->ucBssIndex; + + /* For state identify, not really used. */ + prP2pBssInfo->eIntendOPMode = OP_MODE_P2P_DEVICE; + + /* glRegisterP2P has setup the mac address */ + /* For wlan0 as AP mode case, this function will be called when + * changing interface type. And the MAC Addr overwrite by Role + * isn't expected. + * Maybe only using ucRoleIdx to calc MAC addr is better than + * using Role type. + */ + prP2PInfo = prAdapter->prGlueInfo->prP2PInfo[ucRoleIdx]; + COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, + prP2PInfo->prDevHandler->dev_addr); + + /* For BSS_INFO back trace to P2P Role & get Role FSM. */ + prP2pBssInfo->u4PrivateData = ucRoleIdx; + + if (p2pFuncIsAPMode( + prAdapter->rWifiVar.prP2PConnSettings[ucRoleIdx])) { + prP2pBssInfo->ucConfigAdHocAPMode = AP_MODE_11G; + prP2pBssInfo->u2HwDefaultFixedRateCode = + RATE_CCK_1M_LONG; + } else { + prP2pBssInfo->ucConfigAdHocAPMode = AP_MODE_11G_P2P; + prP2pBssInfo->u2HwDefaultFixedRateCode = RATE_OFDM_6M; + } + + prP2pBssInfo->ucNonHTBasicPhyType = (uint8_t) + 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(struct WLAN_BEACON_FRAME, aucInfoElem[0]) + + MAX_IE_LENGTH); + + if (prP2pBssInfo->prBeacon) { + prP2pBssInfo->prBeacon->eSrc = TX_PACKET_MGMT; + /* NULL STA_REC */ + prP2pBssInfo->prBeacon->ucStaRecIndex = + STA_REC_INDEX_BMCAST; + prP2pBssInfo->prBeacon->ucBssIndex = + prP2pBssInfo->ucBssIndex; + } else { + /* Out of memory. */ + ASSERT(FALSE); + } + + 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; + prP2pBssInfo->ucOpRxNss = prP2pBssInfo->ucOpTxNss = + wlanGetSupportNss(prAdapter, prP2pBssInfo->ucBssIndex); +#if (CFG_HW_WMM_BY_BSS == 0) + prP2pBssInfo->ucWmmQueSet = (prAdapter->rWifiVar.eDbdcMode == + ENUM_DBDC_MODE_DISABLED) + ? DBDC_5G_WMM_INDEX + : DBDC_2G_WMM_INDEX; +#endif + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) + prP2pBssInfo->fgIsQBSS = TRUE; + else + prP2pBssInfo->fgIsQBSS = FALSE; + +#if (CFG_SUPPORT_DFS_MASTER == 1) + p2pFuncRadarInfoInit(); +#endif + + /* SET_NET_PWR_STATE_IDLE(prAdapter, + * prP2pBssInfo->ucBssIndex); + */ + + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_IDLE); + + LINK_INITIALIZE(&prP2pBssInfo->rPmkidCache); + } while (FALSE); + + if (prP2pBssInfo) + return prP2pBssInfo->ucBssIndex; + else + return prAdapter->ucP2PDevBssIdx; +} /* p2pFsmInit */ + +void p2pRoleFsmUninit(IN struct ADAPTER *prAdapter, IN uint8_t ucRoleIdx) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + DEBUGFUNC("p2pRoleFsmUninit()"); + DBGLOG(P2P, INFO, "->p2pRoleFsmUninit()\n"); + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, ucRoleIdx); + + ASSERT_BREAK(prP2pRoleFsmInfo != NULL); + + if (!prP2pRoleFsmInfo) + return; + + prP2pBssInfo = + prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex]; + + p2pFuncDissolve(prAdapter, + prP2pBssInfo, TRUE, + REASON_CODE_DEAUTH_LEAVING_BSS); + + SET_NET_PWR_STATE_IDLE(prAdapter, prP2pBssInfo->ucBssIndex); + + /* Function Dissolve should already enter IDLE state. */ + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_IDLE); + + p2pRoleFsmRunEventAbort(prAdapter, prP2pRoleFsmInfo); + + p2pFunClearAllTxReq(prAdapter, + &(prP2pRoleFsmInfo->rMgmtTxInfo)); + + /* Clear CmdQue */ + kalClearMgmtFramesByBssIdx(prAdapter->prGlueInfo, + prP2pBssInfo->ucBssIndex); + kalClearSecurityFramesByBssIdx(prAdapter->prGlueInfo, + prP2pBssInfo->ucBssIndex); + /* Clear PendingCmdQue */ + wlanReleasePendingCMDbyBssIdx(prAdapter, + prP2pBssInfo->ucBssIndex); + /* Clear PendingTxMsdu */ + nicFreePendingTxMsduInfo(prAdapter, + prP2pBssInfo->ucBssIndex, MSDU_REMOVE_BY_BSS_INDEX); + + /* Deactivate BSS. */ + UNSET_NET_ACTIVE(prAdapter, prP2pRoleFsmInfo->ucBssIndex); + + nicDeactivateNetwork(prAdapter, prP2pRoleFsmInfo->ucBssIndex); + + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, ucRoleIdx) = NULL; + + if (prP2pBssInfo->prBeacon) { + cnmMgtPktFree(prAdapter, prP2pBssInfo->prBeacon); + prP2pBssInfo->prBeacon = NULL; + } + + cnmFreeBssInfo(prAdapter, prP2pBssInfo); + + /* ensure the timer be stopped */ + cnmTimerStopTimer(prAdapter, + &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer)); + +#if CFG_ENABLE_PER_STA_STATISTICS_LOG + cnmTimerStopTimer(prAdapter, + &prP2pRoleFsmInfo->rP2pRoleFsmGetStatisticsTimer); +#endif + +#if (CFG_SUPPORT_DFS_MASTER == 1) + cnmTimerStopTimer(prAdapter, + &(prP2pRoleFsmInfo->rDfsShutDownTimer)); +#endif + + if (prP2pRoleFsmInfo) + kalMemFree(prP2pRoleFsmInfo, VIR_MEM_TYPE, + sizeof(struct P2P_ROLE_FSM_INFO)); + + rsnFlushPmkid(prAdapter, prP2pBssInfo->ucBssIndex); + } while (FALSE); + + return; +#if 0 + struct P2P_FSM_INFO *prP2pFsmInfo = (struct P2P_FSM_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) 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. + */ + kalClearMgmtFramesByBssIdx(prAdapter->prGlueInfo, + NETWORK_TYPE_P2P_INDEX); + + /* Clear PendingCmdQue */ + wlanReleasePendingCMDbyBssIdx(prAdapter, + NETWORK_TYPE_P2P_INDEX); + + if (prP2pBssInfo->prBeacon) { + cnmMgtPktFree(prAdapter, prP2pBssInfo->prBeacon); + prP2pBssInfo->prBeacon = NULL; + } + + } while (FALSE); + + return; +#endif +} /* p2pRoleFsmUninit */ + +void +p2pRoleFsmStateTransition(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN enum ENUM_P2P_ROLE_STATE eNextState) +{ + u_int8_t fgIsTransitionOut = (u_int8_t) FALSE; + struct BSS_INFO *prP2pRoleBssInfo = (struct BSS_INFO *) NULL; + struct P2P_CHNL_REQ_INFO *prChnlReqInfo = + (struct P2P_CHNL_REQ_INFO *) NULL; + + prP2pRoleBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, prP2pRoleFsmInfo->ucBssIndex); + prChnlReqInfo = &(prP2pRoleFsmInfo->rChnlReqInfo); + + do { + if (!IS_BSS_ACTIVE(prP2pRoleBssInfo)) { + if (!cnmP2PIsPermitted(prAdapter)) + return; + +#if CFG_SUPPORT_DBDC + if (cnmDBDCIsReqPeivilegeLock() && + ((eNextState == P2P_ROLE_STATE_REQING_CHANNEL && + (prChnlReqInfo->eChnlReqType == + CH_REQ_TYPE_GO_START_BSS || + prChnlReqInfo->eChnlReqType == + CH_REQ_TYPE_JOIN)) + || (eNextState == P2P_ROLE_STATE_IDLE && + prP2pRoleFsmInfo->eCurrentState == + P2P_ROLE_STATE_IDLE) +#if (CFG_SUPPORT_DFS_MASTER == 1) + || eNextState == P2P_ROLE_STATE_SWITCH_CHANNEL +#endif + )) { + /* Do not activate network ruring DBDC HW + * switch. Otherwise, BSS may use incorrect + * CR and result in TRx problems. + */ + DBGLOG(P2P, STATE, + "[P2P_ROLE][%d](Bss%d): Skip activate network [%s]\n", + prP2pRoleFsmInfo->ucRoleIndex, + prP2pRoleFsmInfo->ucBssIndex, + p2pRoleFsmGetFsmState(eNextState)); + } else +#endif + { + SET_NET_ACTIVE(prAdapter, + prP2pRoleBssInfo->ucBssIndex); + nicActivateNetwork(prAdapter, + prP2pRoleBssInfo->ucBssIndex); + } + } + + fgIsTransitionOut = fgIsTransitionOut ? FALSE : TRUE; + + if (!fgIsTransitionOut) { + /* Print log with state changed */ + if (prP2pRoleFsmInfo->eCurrentState != eNextState) + DBGLOG(P2P, STATE, + "[P2P_ROLE][%d]TRANSITION(Bss%d): [%s] -> [%s]\n", + prP2pRoleFsmInfo->ucRoleIndex, + prP2pRoleFsmInfo->ucBssIndex, + p2pRoleFsmGetFsmState + (prP2pRoleFsmInfo->eCurrentState), + p2pRoleFsmGetFsmState(eNextState)); + + /* Transition into current state. */ + prP2pRoleFsmInfo->eCurrentState = eNextState; + } + + switch (prP2pRoleFsmInfo->eCurrentState) { + case P2P_ROLE_STATE_IDLE: + if (!fgIsTransitionOut) + p2pRoleStateInit_IDLE(prAdapter, + prP2pRoleFsmInfo, + prP2pRoleBssInfo); + else + p2pRoleStateAbort_IDLE(prAdapter, + prP2pRoleFsmInfo, + &(prP2pRoleFsmInfo->rChnlReqInfo)); + break; + case P2P_ROLE_STATE_SCAN: + if (!fgIsTransitionOut) { + p2pRoleStateInit_SCAN(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rScanReqInfo)); + } else { + p2pRoleStateAbort_SCAN(prAdapter, + prP2pRoleFsmInfo); + } + break; + case P2P_ROLE_STATE_REQING_CHANNEL: + if (!fgIsTransitionOut) { + p2pRoleStateInit_REQING_CHANNEL(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rChnlReqInfo)); + } else { + p2pRoleStateAbort_REQING_CHANNEL(prAdapter, + prP2pRoleBssInfo, + prP2pRoleFsmInfo, eNextState); + } + break; + case P2P_ROLE_STATE_AP_CHNL_DETECTION: + if (!fgIsTransitionOut) { + p2pRoleStateInit_AP_CHNL_DETECTION(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rScanReqInfo), + &(prP2pRoleFsmInfo->rConnReqInfo)); + } else { + p2pRoleStateAbort_AP_CHNL_DETECTION(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rConnReqInfo), + &(prP2pRoleFsmInfo->rChnlReqInfo), + &(prP2pRoleFsmInfo->rScanReqInfo), + eNextState); + } + break; + case P2P_ROLE_STATE_GC_JOIN: + if (!fgIsTransitionOut) { + p2pRoleStateInit_GC_JOIN(prAdapter, + prP2pRoleFsmInfo, + &(prP2pRoleFsmInfo->rChnlReqInfo)); + } else { + p2pRoleStateAbort_GC_JOIN(prAdapter, + prP2pRoleFsmInfo, + &(prP2pRoleFsmInfo->rJoinInfo), + eNextState); + } + break; + case P2P_ROLE_STATE_OFF_CHNL_TX: + if (!fgIsTransitionOut) { + fgIsTransitionOut = + p2pRoleStateInit_OFF_CHNL_TX(prAdapter, + prP2pRoleFsmInfo, + &(prP2pRoleFsmInfo->rChnlReqInfo), + &(prP2pRoleFsmInfo->rMgmtTxInfo), + &eNextState); + } else { + p2pRoleStateAbort_OFF_CHNL_TX(prAdapter, + prP2pRoleFsmInfo, + &(prP2pRoleFsmInfo->rMgmtTxInfo), + &(prP2pRoleFsmInfo->rChnlReqInfo), + eNextState); + } + break; + +#if (CFG_SUPPORT_DFS_MASTER == 1) + case P2P_ROLE_STATE_DFS_CAC: + if (!fgIsTransitionOut) { + p2pRoleStateInit_DFS_CAC(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rChnlReqInfo)); + } else { + p2pRoleStateAbort_DFS_CAC(prAdapter, + prP2pRoleBssInfo, + prP2pRoleFsmInfo, + eNextState); + } + break; + case P2P_ROLE_STATE_SWITCH_CHANNEL: + if (!fgIsTransitionOut) { + p2pRoleStateInit_SWITCH_CHANNEL(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rChnlReqInfo)); + } else { + p2pRoleStateAbort_SWITCH_CHANNEL(prAdapter, + prP2pRoleBssInfo, + prP2pRoleFsmInfo, + eNextState); + } + break; +#endif + default: + ASSERT(FALSE); + break; + } + } while (fgIsTransitionOut); + +} /* p2pRoleFsmStateTransition */ + +void p2pRoleFsmRunEventTimeout(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) ulParamPtr; + struct P2P_CHNL_REQ_INFO *prP2pChnlReqInfo = + (struct P2P_CHNL_REQ_INFO *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pRoleFsmInfo != NULL)); + + switch (prP2pRoleFsmInfo->eCurrentState) { + case P2P_ROLE_STATE_IDLE: + prP2pChnlReqInfo = &(prP2pRoleFsmInfo->rChnlReqInfo); + if (prP2pChnlReqInfo->fgIsChannelRequested) { + p2pFuncReleaseCh(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + prP2pChnlReqInfo); + if (IS_NET_PWR_STATE_IDLE(prAdapter, + prP2pRoleFsmInfo->ucBssIndex)) + ASSERT(FALSE); + } + + if (IS_NET_PWR_STATE_IDLE(prAdapter, + prP2pRoleFsmInfo->ucBssIndex) && + IS_NET_ACTIVE(prAdapter, + prP2pRoleFsmInfo->ucBssIndex)) { + DBGLOG(P2P, TRACE, + "Role BSS IDLE, deactive network.\n"); + UNSET_NET_ACTIVE(prAdapter, + prP2pRoleFsmInfo->ucBssIndex); + nicDeactivateNetwork(prAdapter, + prP2pRoleFsmInfo->ucBssIndex); + nicUpdateBss(prAdapter, + prP2pRoleFsmInfo->ucBssIndex); + } + break; + case P2P_ROLE_STATE_GC_JOIN: + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_IDLE); + break; + case P2P_ROLE_STATE_OFF_CHNL_TX: + p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, + P2P_ROLE_STATE_OFF_CHNL_TX); + break; +#if (CFG_SUPPORT_DFS_MASTER == 1) + case P2P_ROLE_STATE_DFS_CAC: + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_IDLE); + kalP2PCacFinishedUpdate(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex); + p2pFuncSetDfsState(DFS_STATE_ACTIVE); + cnmTimerStartTimer(prAdapter, + &(prP2pRoleFsmInfo->rDfsShutDownTimer), + 5000); + break; +#endif + default: + DBGLOG(P2P, ERROR, + "Current P2P Role State %d is unexpected for FSM timeout event.\n", + prP2pRoleFsmInfo->eCurrentState); + ASSERT(FALSE); + break; + } + } while (FALSE); +} /* p2pRoleFsmRunEventTimeout */ + +static void +p2pRoleFsmDeauthComplete(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + enum ENUM_PARAM_MEDIA_STATE eOriMediaStatus; + struct GL_P2P_INFO *prP2PInfo; + + if (!prAdapter) { + DBGLOG(P2P, ERROR, "prAdapter shouldn't be NULL!\n"); + return; + } + + if (!prStaRec) { + DBGLOG(P2P, ERROR, "prStaRec shouldn't be NULL!\n"); + return; + } + + DBGLOG(P2P, INFO, "Deauth TX Complete!\n"); + + prP2pBssInfo = prAdapter->aprBssInfo[prStaRec->ucBssIndex]; + ASSERT_BREAK(prP2pBssInfo != NULL); + eOriMediaStatus = prP2pBssInfo->eConnectionState; + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData); + prP2PInfo = prAdapter->prGlueInfo->prP2PInfo[ + prP2pRoleFsmInfo->ucRoleIndex]; + + /* + * After EAP exchange, GO/GC will disconnect + * and re-connect in short time. + * GC's new station record will be removed unexpectedly at GO's side + * if new GC's connection happens + * when previous GO's disconnection flow is + * processing. 4-way handshake will NOT be triggered. + */ + if ((prStaRec->eAuthAssocState == AAA_STATE_SEND_AUTH2 || + prStaRec->eAuthAssocState == AAA_STATE_SEND_ASSOC2) && + (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) && + (p2pFuncIsAPMode(prAdapter->rWifiVar + .prP2PConnSettings[prP2pBssInfo->u4PrivateData]) == FALSE)) { + DBGLOG(P2P, WARN, + "Skip deauth tx done since AAA fsm is in progress.\n"); + return; + } else if (prStaRec->eAuthAssocState == SAA_STATE_SEND_AUTH1 || + prStaRec->eAuthAssocState == SAA_STATE_SEND_ASSOC1) { + DBGLOG(P2P, WARN, + "Skip deauth tx done since SAA fsm is in progress.\n"); + return; + } + + ASSERT_BREAK(prP2pRoleFsmInfo != NULL); + + /* Change station state. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + /* Reset Station Record Status. */ + p2pFuncResetStaRecStatus(prAdapter, prStaRec); + + /* Try to remove StaRec in BSS client list before free it */ + bssRemoveClient(prAdapter, prP2pBssInfo, prStaRec); + + /* STA_RECORD free */ + cnmStaRecFree(prAdapter, prStaRec); + + if ((prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) || + (bssGetClientCount(prAdapter, prP2pBssInfo) == 0)) { + if (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) + DBGLOG(P2P, TRACE, + "No More Client, Media Status DISCONNECTED\n"); + else + DBGLOG(P2P, TRACE, + "Deauth done, Media Status DISCONNECTED\n"); + p2pChangeMediaState(prAdapter, + prP2pBssInfo, + MEDIA_STATE_DISCONNECTED); + if (prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, + NULL, NULL, 0, 0, + WLAN_STATUS_MEDIA_DISCONNECT); +#else + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, + NULL, NULL, 0, 0); +#endif + } + if (prP2PInfo && prP2PInfo->eChnlSwitchPolicy == + CHNL_SWITCH_POLICY_DEAUTH) { + prP2PInfo->eChnlSwitchPolicy = CHNL_SWITCH_POLICY_NONE; + p2pFunChnlSwitchNotifyDone(prAdapter); + } + } + + /* STOP BSS if power is IDLE */ + if (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + if (IS_NET_PWR_STATE_IDLE(prAdapter, + prP2pRoleFsmInfo->ucBssIndex) + && (bssGetClientCount(prAdapter, prP2pBssInfo) == 0)) { + /* All Peer disconnected !! Stop BSS now!! */ + p2pFuncStopComplete(prAdapter, prP2pBssInfo); + } else if (eOriMediaStatus != prP2pBssInfo->eConnectionState) + /* Update the Media State if necessary */ + nicUpdateBss(prAdapter, prP2pBssInfo->ucBssIndex); + } else /* GC : Stop BSS when Deauth done */ + p2pFuncStopComplete(prAdapter, prP2pBssInfo); + +} + +void p2pRoleFsmDeauthTimeout(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr) +{ + struct STA_RECORD *prStaRec = (struct STA_RECORD *) ulParamPtr; + + p2pRoleFsmDeauthComplete(prAdapter, prStaRec); +} /* p2pRoleFsmRunEventTimeout */ + +void p2pRoleFsmRunEventAbort(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo) +{ + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pRoleFsmInfo != NULL)); + + if (prP2pRoleFsmInfo->eCurrentState != P2P_ROLE_STATE_IDLE) { + /* Get into IDLE state. */ + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_IDLE); + } + + /* Abort IDLE. */ + p2pRoleStateAbort_IDLE(prAdapter, + prP2pRoleFsmInfo, + &(prP2pRoleFsmInfo->rChnlReqInfo)); + + } while (FALSE); +} /* p2pRoleFsmRunEventAbort */ + +uint32_t +p2pRoleFsmRunEventDeauthTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + DBGLOG(P2P, INFO, + "Deauth TX Done, seq = %d, sta = %d, status = %d\n", + prMsduInfo->ucTxSeqNum, + prMsduInfo->ucStaRecIndex, + rTxDoneStatus); + + prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + + if (prStaRec == NULL) { + DBGLOG(P2P, TRACE, + "Station Record NULL, Index:%d\n", + prMsduInfo->ucStaRecIndex); + break; + } + + p2pRoleFsmDeauthComplete(prAdapter, prStaRec); + /* Avoid re-entry */ + cnmTimerStopTimer(prAdapter, &(prStaRec->rDeauthTxDoneTimer)); + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; + +} /* p2pRoleFsmRunEventDeauthTxDone */ + +void p2pRoleFsmRunEventRxDeauthentication(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct SW_RFB *prSwRfb) +{ + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + uint16_t u2ReasonCode = 0; + /* flag to send deauth when rx sta disassc/deauth */ + u_int8_t fgSendDeauth = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + + if (prStaRec == NULL) + prStaRec = cnmGetStaRecByIndex(prAdapter, + prSwRfb->ucStaRecIdx); + + if (!prStaRec) + break; + + prP2pBssInfo = prAdapter->aprBssInfo[prStaRec->ucBssIndex]; + + 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) { + struct WLAN_DEAUTH_FRAME *prDeauthFrame = + (struct WLAN_DEAUTH_FRAME *) + prSwRfb->pvHeader; + uint16_t u2IELength = 0; + + if (prP2pBssInfo->prStaRecOfAP != prStaRec) + break; + + prStaRec->u2ReasonCode = u2ReasonCode; + u2IELength = prSwRfb->u2PacketLen + - (WLAN_MAC_HEADER_LEN + + REASON_CODE_FIELD_LEN); + +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) +/* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus( + prAdapter->prGlueInfo, + (uint8_t) prP2pBssInfo->u4PrivateData, + NULL, + prDeauthFrame->aucInfoElem, + u2IELength, + u2ReasonCode, + WLAN_STATUS_MEDIA_DISCONNECT); + +#else +/* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus( + prAdapter->prGlueInfo, + (uint8_t) prP2pBssInfo->u4PrivateData, + NULL, + prDeauthFrame->aucInfoElem, + u2IELength, + u2ReasonCode); +#endif + + prP2pBssInfo->prStaRecOfAP = NULL; + + p2pFuncDisconnect(prAdapter, + prP2pBssInfo, + prStaRec, + FALSE, + u2ReasonCode); + + SET_NET_PWR_STATE_IDLE(prAdapter, + prP2pBssInfo->ucBssIndex); + + p2pRoleFsmStateTransition(prAdapter, + P2P_ROLE_INDEX_2_ROLE_FSM_INFO( + prAdapter, + prP2pBssInfo->u4PrivateData), + P2P_ROLE_STATE_IDLE); + + p2pFuncStopComplete(prAdapter, prP2pBssInfo); + } + break; + case OP_MODE_ACCESS_POINT: + /* Delete client from client list. */ + if (authProcessRxDeauthFrame(prSwRfb, + prP2pBssInfo->aucBSSID, + &u2ReasonCode) == WLAN_STATUS_SUCCESS) { +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if (rsnCheckBipKeyInstalled(prAdapter, + prStaRec)) { + if (prSwRfb->fgIsCipherMS || + prSwRfb->fgIsCipherLenMS) { + /* if cipher mismatch, + * or incorrect encrypt, + * just drop + */ + DBGLOG(P2P, ERROR, + "Rx deauth CM/CLM=1\n"); + return; + } + + /* 4.3.3.1 send unprotected deauth + * reason 6/7 + */ + DBGLOG(P2P, INFO, "deauth reason=6\n"); + fgSendDeauth = TRUE; + u2ReasonCode = REASON_CODE_CLASS_2_ERR; + prStaRec->rPmfCfg.fgRxDeauthResp = TRUE; + } +#endif + + if (bssRemoveClient(prAdapter, + prP2pBssInfo, prStaRec)) { + /* Indicate disconnect to Host. */ + p2pFuncDisconnect(prAdapter, + prP2pBssInfo, + prStaRec, + fgSendDeauth, + u2ReasonCode); + /* Deactive BSS + * if PWR is IDLE and no peer + */ + if (IS_NET_PWR_STATE_IDLE(prAdapter, + prP2pBssInfo->ucBssIndex) && + (bssGetClientCount(prAdapter, + prP2pBssInfo) == 0)) { + /* All Peer disconnected !! + * Stop BSS now!! + */ + p2pFuncStopComplete(prAdapter, + prP2pBssInfo); + } + } + } + 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); +} /* p2pRoleFsmRunEventRxDeauthentication */ + +void p2pRoleFsmRunEventRxDisassociation(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct SW_RFB *prSwRfb) +{ + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + uint16_t u2ReasonCode = 0; + /* flag to send deauth when rx sta disassc/deauth */ + u_int8_t fgSendDeauth = FALSE; + + + if (prStaRec == NULL) + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (!prStaRec) { + DBGLOG(P2P, ERROR, + "prStaRec of prSwRfb->ucStaRecIdx %d is NULL!\n", + prSwRfb->ucStaRecIdx); + return; + } + + prP2pBssInfo = prAdapter->aprBssInfo[prStaRec->ucBssIndex]; + + if (prStaRec->ucStaState == STA_STATE_1) + return; + + DBGLOG(P2P, TRACE, "RX Disassoc\n"); + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_INFRASTRUCTURE: + if (assocProcessRxDisassocFrame(prAdapter, + prSwRfb, + prStaRec->aucMacAddr, + &prStaRec->u2ReasonCode) == WLAN_STATUS_SUCCESS) { + + struct WLAN_DISASSOC_FRAME *prDisassocFrame = + (struct WLAN_DISASSOC_FRAME *) + prSwRfb->pvHeader; + uint16_t u2IELength = 0; + + if (prP2pBssInfo->prStaRecOfAP != prStaRec) + break; + + u2IELength = prSwRfb->u2PacketLen + - (WLAN_MAC_HEADER_LEN + REASON_CODE_FIELD_LEN); + +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) + /* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + (uint8_t) prP2pBssInfo->u4PrivateData, NULL, + prDisassocFrame->aucInfoElem, + u2IELength, prStaRec->u2ReasonCode, + WLAN_STATUS_MEDIA_DISCONNECT); + +#else + /* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + (uint8_t) prP2pBssInfo->u4PrivateData, NULL, + prDisassocFrame->aucInfoElem, + u2IELength, prStaRec->u2ReasonCode); +#endif + + prP2pBssInfo->prStaRecOfAP = NULL; + + p2pFuncDisconnect(prAdapter, + prP2pBssInfo, + prStaRec, + FALSE, + prStaRec->u2ReasonCode); + + SET_NET_PWR_STATE_IDLE(prAdapter, + prP2pBssInfo->ucBssIndex); + + p2pRoleFsmStateTransition(prAdapter, + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData), + P2P_ROLE_STATE_IDLE); + + p2pFuncStopComplete(prAdapter, prP2pBssInfo); + } + break; + case OP_MODE_ACCESS_POINT: + /* Delete client from client list. */ + if (assocProcessRxDisassocFrame(prAdapter, + prSwRfb, + prP2pBssInfo->aucBSSID, + &u2ReasonCode) == WLAN_STATUS_SUCCESS) { + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + if (prSwRfb->fgIsCipherMS || + prSwRfb->fgIsCipherLenMS) { + /* if cipher mismatch, + * or incorrect encrypt, just drop + */ + DBGLOG(P2P, ERROR, + "Rx disassoc CM/CLM=1\n"); + return; + } + + /* 4.3.3.1 send unprotected deauth + * reason 6/7 + */ + DBGLOG(P2P, INFO, "deauth reason=6\n"); + fgSendDeauth = TRUE; + u2ReasonCode = REASON_CODE_CLASS_2_ERR; + prStaRec->rPmfCfg.fgRxDeauthResp = TRUE; + } +#endif + + if (bssRemoveClient(prAdapter, + prP2pBssInfo, prStaRec)) { + /* Indicate disconnect to Host. */ + p2pFuncDisconnect(prAdapter, + prP2pBssInfo, + prStaRec, + fgSendDeauth, + u2ReasonCode); + /* Deactive BSS if PWR is IDLE and no peer */ + if (IS_NET_PWR_STATE_IDLE(prAdapter, + prP2pBssInfo->ucBssIndex) && + (bssGetClientCount(prAdapter, + prP2pBssInfo) == 0)) { + /* All Peer disconnected !! + * Stop BSS now!! + */ + p2pFuncStopComplete(prAdapter, + prP2pBssInfo); + } + + } + } + break; + case OP_MODE_P2P_DEVICE: + default: + ASSERT(FALSE); + break; + } + +} /* p2pRoleFsmRunEventRxDisassociation */ + +void p2pRoleFsmRunEventBeaconTimeout(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData); + + /* Only client mode would have beacon lost event. */ + if (prP2pBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) { + DBGLOG(P2P, ERROR, + "Error case, P2P BSS %d not INFRA mode but beacon timeout\n", + prP2pRoleFsmInfo->ucRoleIndex); + break; + } + + DBGLOG(P2P, TRACE, + "p2pFsmRunEventBeaconTimeout: BSS %d Beacon Timeout\n", + prP2pRoleFsmInfo->ucRoleIndex); + + if (prP2pBssInfo->eConnectionState + == MEDIA_STATE_CONNECTED) { + +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) + /* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, + NULL, NULL, 0, + REASON_CODE_DEAUTH_LEAVING_BSS, + WLAN_STATUS_MEDIA_DISCONNECT); + + +#else + /* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, + NULL, NULL, 0, + REASON_CODE_DEAUTH_LEAVING_BSS); +#endif + + if (prP2pBssInfo->prStaRecOfAP != NULL) { + struct STA_RECORD *prStaRec = + prP2pBssInfo->prStaRecOfAP; + + prP2pBssInfo->prStaRecOfAP = NULL; + + p2pFuncDisconnect(prAdapter, + prP2pBssInfo, + prStaRec, FALSE, + REASON_CODE_DISASSOC_LEAVING_BSS); + + SET_NET_PWR_STATE_IDLE(prAdapter, + prP2pBssInfo->ucBssIndex); + /* 20120830 moved into p2pFuncDisconnect() */ + /* cnmStaRecFree(prAdapter, + * prP2pBssInfo->prStaRecOfAP); + */ + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_IDLE); + + p2pFuncStopComplete(prAdapter, prP2pBssInfo); + } + } + } while (FALSE); +} /* p2pFsmRunEventBeaconTimeout */ + +/*================== Message Event ==================*/ +void p2pRoleFsmRunEventStartAP(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct MSG_P2P_START_AP *prP2pStartAPMsg = + (struct MSG_P2P_START_AP *) NULL; + struct P2P_CONNECTION_REQ_INFO *prP2pConnReqInfo = + (struct P2P_CONNECTION_REQ_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo = + (struct P2P_SPECIFIC_BSS_INFO *) NULL; + + DBGLOG(P2P, TRACE, "p2pRoleFsmRunEventStartAP\n"); + + prP2pStartAPMsg = (struct MSG_P2P_START_AP *) prMsgHdr; + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pStartAPMsg->ucRoleIdx); + + prAdapter->prP2pInfo->eConnState = P2P_CNN_NORMAL; + + DBGLOG(P2P, TRACE, + "p2pRoleFsmRunEventStartAP with Role(%d)\n", + prP2pStartAPMsg->ucRoleIdx); + + + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, ERROR, + "p2pRoleFsmRunEventStartAP: Corresponding P2P Role FSM empty: %d.\n", + prP2pStartAPMsg->ucRoleIdx); + goto error; + } + + prP2pBssInfo = prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex]; + prP2pSpecificBssInfo = + prAdapter->rWifiVar + .prP2pSpecificBssInfo[prP2pBssInfo->u4PrivateData]; + prP2pConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + + if (prP2pStartAPMsg->u4BcnInterval) { + DBGLOG(P2P, TRACE, + "Beacon interval updated to :%u\n", + prP2pStartAPMsg->u4BcnInterval); + prP2pBssInfo->u2BeaconInterval = + (uint16_t) prP2pStartAPMsg->u4BcnInterval; + } else if (prP2pBssInfo->u2BeaconInterval == 0) { + prP2pBssInfo->u2BeaconInterval = DOT11_BEACON_PERIOD_DEFAULT; + } + + if (prP2pStartAPMsg->u4DtimPeriod) { + DBGLOG(P2P, TRACE, + "DTIM interval updated to :%u\n", + prP2pStartAPMsg->u4DtimPeriod); + prP2pBssInfo->ucDTIMPeriod = + (uint8_t) prP2pStartAPMsg->u4DtimPeriod; + } else if (prP2pBssInfo->ucDTIMPeriod == 0) { + prP2pBssInfo->ucDTIMPeriod = DOT11_DTIM_PERIOD_DEFAULT; + } + + if (prP2pStartAPMsg->u2SsidLen != 0) { + kalMemCopy(prP2pConnReqInfo->rSsidStruct.aucSsid, + prP2pStartAPMsg->aucSsid, + prP2pStartAPMsg->u2SsidLen); + prP2pConnReqInfo->rSsidStruct.ucSsidLen = + prP2pSpecificBssInfo->u2GroupSsidLen = + prP2pStartAPMsg->u2SsidLen; + kalMemCopy(prP2pSpecificBssInfo->aucGroupSsid, + prP2pStartAPMsg->aucSsid, + prP2pStartAPMsg->u2SsidLen); + } + + if (p2pFuncIsAPMode(prAdapter->rWifiVar + .prP2PConnSettings[prP2pStartAPMsg->ucRoleIdx])) { + prP2pConnReqInfo->eConnRequest = P2P_CONNECTION_TYPE_PURE_AP; + + /* Overwrite AP channel */ + if (prAdapter->rWifiVar.ucApChannel && + prAdapter->rWifiVar.ucApChnlDefFromCfg) { + prP2pConnReqInfo->rChannelInfo.ucChannelNum = + prAdapter->rWifiVar.ucApChannel; + + if (prAdapter->rWifiVar.ucApChannel <= 14) + prP2pConnReqInfo->rChannelInfo.eBand = BAND_2G4; + else + prP2pConnReqInfo->rChannelInfo.eBand = BAND_5G; + } + } else { + prP2pConnReqInfo->eConnRequest = P2P_CONNECTION_TYPE_GO; +#if CFG_P2P_DEFAULT_CLIENT_COUNT + kalP2PSetMaxClients(prAdapter->prGlueInfo, + P2P_DEFAULT_CLIENT_COUNT, + prP2pStartAPMsg->ucRoleIdx); +#endif + } + + /* Clear list to ensure no client staRec */ + if (bssGetClientCount(prAdapter, prP2pBssInfo) != 0) { + DBGLOG(P2P, WARN, + "Clear list to ensure no empty/client staRec\n"); + bssInitializeClientList(prAdapter, prP2pBssInfo); + } + + /* The supplicant may start AP + * before rP2pRoleFsmTimeoutTimer is time out + */ + /* We need to make sure the BSS was deactivated + * and all StaRec can be free + */ + if (timerPendingTimer(&(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer))) { + /* call p2pRoleFsmRunEventTimeout() + * to deactive BSS and free channel + */ + p2pRoleFsmRunEventTimeout(prAdapter, + (unsigned long)prP2pRoleFsmInfo); + cnmTimerStopTimer(prAdapter, + &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer)); + } + +#if (CFG_SUPPORT_DFS_MASTER == 1) + if (timerPendingTimer(&(prP2pRoleFsmInfo->rDfsShutDownTimer))) { + DBGLOG(P2P, INFO, + "p2pRoleFsmRunEventStartAP: Stop DFS shut down timer.\n"); + cnmTimerStopTimer(prAdapter, + &(prP2pRoleFsmInfo->rDfsShutDownTimer)); + } +#endif + + prP2pBssInfo->eBand = prP2pConnReqInfo->rChannelInfo.eBand; + if (prP2pBssInfo->fgIsWmmInited == FALSE) + prP2pBssInfo->ucWmmQueSet = cnmWmmIndexDecision(prAdapter, + prP2pBssInfo); +#if CFG_SUPPORT_DBDC + /* DBDC decsion.may change OpNss */ + cnmDbdcPreConnectionEnableDecision(prAdapter, + prP2pBssInfo->ucBssIndex, + prP2pConnReqInfo->rChannelInfo.eBand, + prP2pConnReqInfo->rChannelInfo.ucChannelNum, + prP2pBssInfo->ucWmmQueSet); +#endif /*CFG_SUPPORT_DBDC*/ + + cnmOpModeGetTRxNss( + prAdapter, prP2pBssInfo->ucBssIndex, + &prP2pBssInfo->ucOpRxNss, &prP2pBssInfo->ucOpTxNss); + prP2pBssInfo->eHiddenSsidType = prP2pStartAPMsg->ucHiddenSsidType; + + DBGLOG(P2P, TRACE, + "p2pRoleFsmRunEventStartAP: start AP CH[%u]", + prP2pConnReqInfo->rChannelInfo.ucChannelNum); + DBGLOG(P2P, TRACE, "RxNSS[%u]TxNss[%u].\n", + prP2pBssInfo->ucOpRxNss, prP2pBssInfo->ucOpTxNss); + /* + * beacon content is related with Nss number , + * need to update because of modification + */ + bssUpdateBeaconContent(prAdapter, prP2pBssInfo->ucBssIndex); + + if ((prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) || + (prP2pBssInfo->eIntendOPMode != OP_MODE_NUM)) { + /* 1. No switch to AP mode. + * 2. Not started yet. + */ + + if (prP2pRoleFsmInfo->eCurrentState + != P2P_ROLE_STATE_AP_CHNL_DETECTION + && + prP2pRoleFsmInfo->eCurrentState + != P2P_ROLE_STATE_IDLE) { + /* Make sure the state is in IDLE state. */ + p2pRoleFsmRunEventAbort(prAdapter, prP2pRoleFsmInfo); + } else if (prP2pRoleFsmInfo->eCurrentState + == P2P_ROLE_STATE_AP_CHNL_DETECTION) { + goto error; + } + + /* Leave IDLE state. */ + SET_NET_PWR_STATE_ACTIVE(prAdapter, prP2pBssInfo->ucBssIndex); + + prP2pBssInfo->eIntendOPMode = OP_MODE_ACCESS_POINT; + +#if 0 + prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.ucChannelNum = 8; + prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.eBand = BAND_2G4; + /* prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.ucBandwidth = + * 0; + */ + /* prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.eSCO = + * CHNL_EXT_SCN; + */ +#endif + + if (prP2pRoleFsmInfo->rConnReqInfo + .rChannelInfo.ucChannelNum != 0) { + DBGLOG(P2P, INFO, + "Role(%d) StartAP at CH[%u]RxNSS[%u]TxNss[%u]\n", + prP2pStartAPMsg->ucRoleIdx, + prP2pRoleFsmInfo->rConnReqInfo + .rChannelInfo.ucChannelNum, + prP2pBssInfo->ucOpRxNss, + prP2pBssInfo->ucOpTxNss); + + p2pRoleStatePrepare_To_REQING_CHANNEL_STATE( + prAdapter, + GET_BSS_INFO_BY_INDEX(prAdapter, + prP2pRoleFsmInfo->ucBssIndex), + &(prP2pRoleFsmInfo->rConnReqInfo), + &(prP2pRoleFsmInfo->rChnlReqInfo)); + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_REQING_CHANNEL); + } else { + DBGLOG(P2P, INFO, + "Role(%d) StartAP Scan for working channel\n", + prP2pStartAPMsg->ucRoleIdx); + + /* For AP/GO mode with specific channel + * or non-specific channel. + */ + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_AP_CHNL_DETECTION); + } + } + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pRoleFsmRunEventStartAP */ + + +void p2pRoleFsmRunEventDelIface(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct MSG_P2P_DEL_IFACE *prP2pDelIfaceMsg = + (struct MSG_P2P_DEL_IFACE *) NULL; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + uint8_t ucRoleIdx; + struct GL_P2P_INFO *prP2pInfo = (struct GL_P2P_INFO *) NULL; + + + DBGLOG(P2P, INFO, "p2pRoleFsmRunEventDelIface\n"); + + prGlueInfo = prAdapter->prGlueInfo; + if (prGlueInfo == NULL) { + DBGLOG(P2P, ERROR, "prGlueInfo shouldn't be NULL!\n"); + goto error; + } + + prP2pDelIfaceMsg = (struct MSG_P2P_DEL_IFACE *) prMsgHdr; + ucRoleIdx = prP2pDelIfaceMsg->ucRoleIdx; + prAdapter = prGlueInfo->prAdapter; + prP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, ucRoleIdx); + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, ERROR, + "p2pRoleFsmRunEventDelIface: Corresponding P2P Role FSM empty: %d.\n", + prP2pDelIfaceMsg->ucRoleIdx); + goto error; + } + + prP2pBssInfo = prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex]; + + /* The state is in disconnecting and can not change any BSS status */ + if (IS_NET_PWR_STATE_IDLE(prAdapter, prP2pBssInfo->ucBssIndex) && + IS_NET_ACTIVE(prAdapter, prP2pBssInfo->ucBssIndex)) { + DBGLOG(P2P, TRACE, "under deauth procedure, Quit.\n"); + } else { + /*p2pFuncDissolve(prAdapter, + * prP2pBssInfo, TRUE, + * REASON_CODE_DEAUTH_LEAVING_BSS); + */ + + SET_NET_PWR_STATE_IDLE(prAdapter, prP2pBssInfo->ucBssIndex); + + /* Function Dissolve should already enter IDLE state. */ + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_IDLE); + + p2pRoleFsmRunEventAbort(prAdapter, prP2pRoleFsmInfo); + + /* Clear CmdQue */ + kalClearMgmtFramesByBssIdx(prAdapter->prGlueInfo, + prP2pBssInfo->ucBssIndex); + kalClearSecurityFramesByBssIdx(prAdapter->prGlueInfo, + prP2pBssInfo->ucBssIndex); + /* Clear PendingCmdQue */ + wlanReleasePendingCMDbyBssIdx(prAdapter, + prP2pBssInfo->ucBssIndex); + /* Clear PendingTxMsdu */ + nicFreePendingTxMsduInfo(prAdapter, + prP2pBssInfo->ucBssIndex, MSDU_REMOVE_BY_BSS_INDEX); + + /* Deactivate BSS. */ + UNSET_NET_ACTIVE(prAdapter, prP2pRoleFsmInfo->ucBssIndex); + + nicDeactivateNetwork(prAdapter, prP2pRoleFsmInfo->ucBssIndex); + nicUpdateBss(prAdapter, prP2pRoleFsmInfo->ucBssIndex); + } + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pRoleFsmRunEventStartAP */ + + +void p2pRoleFsmRunEventStopAP(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct MSG_P2P_STOP_AP *prP2pStopApMsg; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct STA_RECORD *prCurrStaRec; + struct LINK *prClientList; + + prP2pStopApMsg = (struct MSG_P2P_STOP_AP *) prMsgHdr; + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pStopApMsg->ucRoleIdx); + + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, ERROR, + "p2pRoleFsmRunEventStopAP: Corresponding P2P Role FSM empty: %d.\n", + prP2pStopApMsg->ucRoleIdx); + goto error; + } + + prP2pBssInfo = prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex]; + + if (!prP2pBssInfo) { + DBGLOG(P2P, ERROR, + "prP2pBssInfo of prP2pRoleFsmInfo->ucBssIndex %d is NULL!\n", + prP2pRoleFsmInfo->ucBssIndex); + goto error; + } + +#if (CFG_SUPPORT_DFS_MASTER == 1) + p2pFuncSetDfsState(DFS_STATE_INACTIVE); + p2pFuncStopRdd(prAdapter, prP2pBssInfo->ucBssIndex); +#endif + + rsnFlushPmkid(prAdapter, prP2pBssInfo->ucBssIndex); + + kalP2PResetBlackList(prAdapter->prGlueInfo, + prP2pStopApMsg->ucRoleIdx); + + if (prP2pRoleFsmInfo->eCurrentState != P2P_ROLE_STATE_REQING_CHANNEL) { + p2pFuncStopGO(prAdapter, prP2pBssInfo); + + /* Start all Deauth done timer for all client */ + prClientList = &prP2pBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH_ENTRY(prCurrStaRec, + prClientList, rLinkEntry, struct STA_RECORD) { + if (!prCurrStaRec) + break; + /* Do not restart timer if the timer is pending, */ + /* (start in p2pRoleFsmRunEventConnectionAbort()) */ + if (!timerPendingTimer( + &(prCurrStaRec->rDeauthTxDoneTimer))) { + cnmTimerInitTimer(prAdapter, + &(prCurrStaRec->rDeauthTxDoneTimer), + (PFN_MGMT_TIMEOUT_FUNC) + p2pRoleFsmDeauthTimeout, + (unsigned long) prCurrStaRec); + + cnmTimerStartTimer(prAdapter, + &(prCurrStaRec->rDeauthTxDoneTimer), + P2P_DEAUTH_TIMEOUT_TIME_MS); + } + } + } + + SET_NET_PWR_STATE_IDLE(prAdapter, prP2pBssInfo->ucBssIndex); + + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_IDLE); + +error: + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pRoleFsmRunEventStopAP */ + +#if (CFG_SUPPORT_DFS_MASTER == 1) +void p2pRoleFsmRunEventDfsCac(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct MSG_P2P_DFS_CAC *prP2pDfsCacMsg = + (struct MSG_P2P_DFS_CAC *) NULL; + struct P2P_CONNECTION_REQ_INFO *prP2pConnReqInfo = + (struct P2P_CONNECTION_REQ_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + enum ENUM_CHANNEL_WIDTH rChannelWidth; + + DBGLOG(P2P, INFO, "p2pRoleFsmRunEventDfsCac\n"); + + prP2pDfsCacMsg = (struct MSG_P2P_DFS_CAC *) prMsgHdr; + + rChannelWidth = prP2pDfsCacMsg->eChannelWidth; + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pDfsCacMsg->ucRoleIdx); + + DBGLOG(P2P, INFO, + "p2pRoleFsmRunEventDfsCac with Role(%d)\n", + prP2pDfsCacMsg->ucRoleIdx); + + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, ERROR, + "p2pRoleFsmRunEventDfsCac: Corresponding P2P Role FSM empty: %d.\n", + prP2pDfsCacMsg->ucRoleIdx); + goto error; + } + + if (timerPendingTimer(&(prP2pRoleFsmInfo->rDfsShutDownTimer))) { + DBGLOG(P2P, INFO, + "p2pRoleFsmRunEventDfsCac: Stop DFS shut down timer.\n"); + cnmTimerStopTimer(prAdapter, + &(prP2pRoleFsmInfo->rDfsShutDownTimer)); + } + + prP2pBssInfo = prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex]; + + prP2pConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + + if (p2pFuncIsAPMode(prAdapter->rWifiVar + .prP2PConnSettings[prP2pDfsCacMsg->ucRoleIdx])) + prP2pConnReqInfo->eConnRequest = P2P_CONNECTION_TYPE_PURE_AP; + else + prP2pConnReqInfo->eConnRequest = P2P_CONNECTION_TYPE_GO; + + prP2pBssInfo->eBand = prP2pConnReqInfo->rChannelInfo.eBand; + if (prP2pBssInfo->fgIsWmmInited == FALSE) + prP2pBssInfo->ucWmmQueSet = cnmWmmIndexDecision(prAdapter, + prP2pBssInfo); + +#if CFG_SUPPORT_DBDC + /* DBDC decsion.may change OpNss */ + cnmDbdcPreConnectionEnableDecision(prAdapter, + prP2pBssInfo->ucBssIndex, + prP2pConnReqInfo->rChannelInfo.eBand, + prP2pConnReqInfo->rChannelInfo.ucChannelNum, + prP2pBssInfo->ucWmmQueSet + ); +#endif /*CFG_SUPPORT_DBDC*/ + + cnmOpModeGetTRxNss( + prAdapter, prP2pBssInfo->ucBssIndex, + &prP2pBssInfo->ucOpRxNss, &prP2pBssInfo->ucOpTxNss); + + DBGLOG(P2P, INFO, + "p2pRoleFsmRunEventDfsCac: CH[%u]RxNSS[%u]TxNss[%u].\n", + prP2pConnReqInfo->rChannelInfo.ucChannelNum, + prP2pBssInfo->ucOpRxNss, + prP2pBssInfo->ucOpTxNss); + + if (prP2pRoleFsmInfo->eCurrentState != P2P_ROLE_STATE_IDLE) { + /* Make sure the state is in IDLE state. */ + p2pRoleFsmRunEventAbort(prAdapter, prP2pRoleFsmInfo); + } + + /* Leave IDLE state. */ + SET_NET_PWR_STATE_ACTIVE(prAdapter, prP2pBssInfo->ucBssIndex); + + prP2pBssInfo->eIntendOPMode = OP_MODE_ACCESS_POINT; + prP2pBssInfo->fgIsDfsActive = TRUE; + + if (prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.ucChannelNum != 0) { + DBGLOG(P2P, INFO, "Role(%d) Set channel at CH(%d)\n", + prP2pDfsCacMsg->ucRoleIdx, + prP2pRoleFsmInfo->rConnReqInfo + .rChannelInfo.ucChannelNum); + + p2pRoleStatePrepare_To_DFS_CAC_STATE(prAdapter, + GET_BSS_INFO_BY_INDEX(prAdapter, + prP2pRoleFsmInfo->ucBssIndex), + rChannelWidth, + &(prP2pRoleFsmInfo->rConnReqInfo), + &(prP2pRoleFsmInfo->rChnlReqInfo)); + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_DFS_CAC); + } else { + DBGLOG(P2P, ERROR, + "prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.ucChannelNum shouldn't be 0\n"); + } + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /*p2pRoleFsmRunEventDfsCac*/ + +void p2pRoleFsmRunEventRadarDet(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct MSG_P2P_RADAR_DETECT *prMsgP2pRddDetMsg; + + + DBGLOG(P2P, INFO, "p2pRoleFsmRunEventRadarDet\n"); + + prMsgP2pRddDetMsg = (struct MSG_P2P_RADAR_DETECT *) prMsgHdr; + + prP2pBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, + prMsgP2pRddDetMsg->ucBssIndex); + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData); + + DBGLOG(P2P, INFO, + "p2pRoleFsmRunEventRadarDet with Role(%d)\n", + prP2pRoleFsmInfo->ucRoleIndex); + + if (prP2pRoleFsmInfo->eCurrentState != P2P_ROLE_STATE_DFS_CAC && + prP2pRoleFsmInfo->eCurrentState != P2P_ROLE_STATE_IDLE) { + DBGLOG(P2P, ERROR, + "Wrong prP2pRoleFsmInfo->eCurrentState \"%s\"!", + (prP2pRoleFsmInfo->eCurrentState < P2P_ROLE_STATE_NUM + ? (const char *) + p2pRoleFsmGetFsmState(prP2pRoleFsmInfo->eCurrentState) + : "")); + goto error; + } + + if (p2pFuncGetRadarDetectMode()) { + DBGLOG(P2P, INFO, + "p2pRoleFsmRunEventRadarDet: Ignore radar event\n"); + if (prP2pRoleFsmInfo->eCurrentState == P2P_ROLE_STATE_DFS_CAC) + p2pFuncSetDfsState(DFS_STATE_CHECKING); + else + p2pFuncSetDfsState(DFS_STATE_ACTIVE); + } else { + if (prP2pRoleFsmInfo->eCurrentState == P2P_ROLE_STATE_DFS_CAC) + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_IDLE); + + kalP2PRddDetectUpdate(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex); + cnmTimerStartTimer(prAdapter, + &(prP2pRoleFsmInfo->rDfsShutDownTimer), + 5000); + } + + p2pFuncShowRadarInfo(prAdapter, prMsgP2pRddDetMsg->ucBssIndex); + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /*p2pRoleFsmRunEventRadarDet*/ + +void p2pRoleFsmRunEventSetNewChannel(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct MSG_P2P_SET_NEW_CHANNEL *prMsgP2pSetNewChannelMsg; + + + DBGLOG(P2P, INFO, "p2pRoleFsmRunEventSetNewChannel\n"); + + prMsgP2pSetNewChannelMsg = (struct MSG_P2P_SET_NEW_CHANNEL *) prMsgHdr; + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prMsgP2pSetNewChannelMsg->ucBssIndex); + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prMsgP2pSetNewChannelMsg->ucRoleIdx); + + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, ERROR, + "Corresponding P2P Role FSM empty: %d.\n", + prMsgP2pSetNewChannelMsg->ucRoleIdx); + goto error; + } + + prP2pRoleFsmInfo->rChnlReqInfo.ucReqChnlNum = + prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.ucChannelNum; + prP2pRoleFsmInfo->rChnlReqInfo.eBand = + prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.eBand; + prP2pRoleFsmInfo->rChnlReqInfo.eChannelWidth = + prMsgP2pSetNewChannelMsg->eChannelWidth; + + prP2pRoleFsmInfo->rChnlReqInfo.ucCenterFreqS1 = + nicGetVhtS1(prP2pRoleFsmInfo->rChnlReqInfo.ucReqChnlNum, + prP2pRoleFsmInfo->rChnlReqInfo.eChannelWidth); + + prP2pRoleFsmInfo->rChnlReqInfo.ucCenterFreqS2 = 0; + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /*p2pRoleFsmRunEventSetNewChannel*/ + +void p2pRoleFsmRunEventCsaDone(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct GLUE_INFO *prGlueInfo; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct MSG_P2P_CSA_DONE *prMsgP2pCsaDoneMsg; + uint8_t role_idx = 0; + struct BSS_INFO *prAisBssInfo; + struct GL_P2P_INFO *prP2PInfo = (struct GL_P2P_INFO *) NULL; + + DBGLOG(P2P, TRACE, "p2pRoleFsmRunEventCsaDone\n"); + + prMsgP2pCsaDoneMsg = (struct MSG_P2P_CSA_DONE *) prMsgHdr; + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prMsgP2pCsaDoneMsg->ucBssIndex); + prAisBssInfo = aisGetConnectedBssInfo(prAdapter); + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData); + prP2PInfo = prAdapter->prGlueInfo->prP2PInfo[ + prP2pRoleFsmInfo->ucRoleIndex]; + + if (prP2PInfo) + prP2PInfo->eChnlSwitchPolicy = CHNL_SWITCH_POLICY_NONE; + + if (prAdapter->rWifiVar.eDbdcMode != ENUM_DBDC_MODE_DISABLED && + prP2pBssInfo->eBand != prP2pRoleFsmInfo->rChnlReqInfo.eBand) { + nicDeactivateNetwork(prAdapter, prP2pBssInfo->ucBssIndex); + nicUpdateBss(prAdapter, prP2pBssInfo->ucBssIndex); + nicActivateNetwork(prAdapter, prP2pBssInfo->ucBssIndex); + +#if CFG_SUPPORT_DBDC + cnmDbdcPreConnectionEnableDecision(prAdapter, + prP2pBssInfo->ucBssIndex, + prP2pRoleFsmInfo->rChnlReqInfo.eBand, + prP2pRoleFsmInfo->rChnlReqInfo.ucReqChnlNum, + prP2pBssInfo->ucWmmQueSet); +#endif /*CFG_SUPPORT_DBDC*/ + + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_SWITCH_CHANNEL); + } else { + prGlueInfo = prAdapter->prGlueInfo; + role_idx = prP2pRoleFsmInfo->ucRoleIndex; + /* Skip channel request/abort for STA+SAP/MCC concurrent case */ + if (prAisBssInfo && + (prAisBssInfo->ucPrimaryChannel != + prP2pBssInfo->ucPrimaryChannel) && + (prAisBssInfo->eConnectionState == + MEDIA_STATE_CONNECTED)) { + p2pFuncDfsSwitchCh(prAdapter, + prP2pBssInfo, + prP2pRoleFsmInfo->rChnlReqInfo); + } else { + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_SWITCH_CHANNEL); + } + } + + cnmMemFree(prAdapter, prMsgHdr); +} /*p2pRoleFsmRunEventCsaDone*/ + +void p2pRoleFsmRunEventDfsShutDownTimeout(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) ulParamPtr; + + DBGLOG(P2P, INFO, + "p2pRoleFsmRunEventDfsShutDownTimeout: DFS shut down.\n"); + + p2pFuncSetDfsState(DFS_STATE_INACTIVE); + p2pFuncStopRdd(prAdapter, prP2pRoleFsmInfo->ucBssIndex); + +} /* p2pRoleFsmRunEventDfsShutDownTimeout */ + +#endif + +void +p2pRoleFsmScanTargetBss(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN uint8_t ucChannelNum, + IN struct P2P_SSID_STRUCT *prSsid) +{ + /* Update scan parameter... to scan target device. */ + struct P2P_SCAN_REQ_INFO *prScanReqInfo = + &(prP2pRoleFsmInfo->rScanReqInfo); + + prScanReqInfo->ucNumChannelList = 1; + prScanReqInfo->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prScanReqInfo->eChannelSet = SCAN_CHANNEL_SPECIFIED; + prScanReqInfo->arScanChannelList[0].ucChannelNum = ucChannelNum; + prScanReqInfo->ucSsidNum = 1; + kalMemCopy(&(prScanReqInfo->arSsidStruct[0]), prSsid, + sizeof(struct P2P_SSID_STRUCT)); + /* Prevent other P2P ID in IE. */ + prScanReqInfo->u4BufLength = 0; + prScanReqInfo->fgIsAbort = TRUE; + + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_SCAN); +} + +void p2pRoleFsmRunEventConnectionRequest(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct MSG_P2P_CONNECTION_REQUEST *prP2pConnReqMsg = + (struct MSG_P2P_CONNECTION_REQUEST *) NULL; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + + struct P2P_CONNECTION_REQ_INFO *prConnReqInfo = + (struct P2P_CONNECTION_REQ_INFO *) NULL; + struct P2P_CHNL_REQ_INFO *prChnlReqInfo = + (struct P2P_CHNL_REQ_INFO *) NULL; + struct P2P_JOIN_INFO *prJoinInfo = (struct P2P_JOIN_INFO *) NULL; + uint8_t ucRfBw; + + prP2pConnReqMsg = (struct MSG_P2P_CONNECTION_REQUEST *) prMsgHdr; + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pConnReqMsg->ucRoleIdx); + + prAdapter->prP2pInfo->eConnState = P2P_CNN_NORMAL; + + + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, ERROR, + "Corresponding P2P Role FSM empty: %d.\n", + prP2pConnReqMsg->ucRoleIdx); + goto error; + } + + prP2pBssInfo = prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex]; + + if (!prP2pBssInfo) { + DBGLOG(P2P, ERROR, + "prP2pRoleFsmInfo->ucBssIndex %d of prAdapter->aprBssInfo is NULL!\n", + prP2pRoleFsmInfo->ucBssIndex); + goto error; + } + + prConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + prChnlReqInfo = &(prP2pRoleFsmInfo->rChnlReqInfo); + prJoinInfo = &(prP2pRoleFsmInfo->rJoinInfo); + + DBGLOG(P2P, TRACE, "p2pFsmRunEventConnectionRequest\n"); + + if (prP2pBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + goto error; + + SET_NET_PWR_STATE_ACTIVE(prAdapter, prP2pBssInfo->ucBssIndex); + + /* In P2P GC case, the interval of + * two ASSOC flow could be very short, + * we must start to connect directly before Deauth done + */ + prStaRec = prP2pBssInfo->prStaRecOfAP; + if (prStaRec) { + if (timerPendingTimer(&prStaRec->rDeauthTxDoneTimer)) { + cnmTimerStopTimer(prAdapter, + &(prStaRec->rDeauthTxDoneTimer)); + /* Force to stop */ + p2pRoleFsmDeauthComplete(prAdapter, prStaRec); + } + } + /* Make sure the state is in IDLE state. */ + if (prP2pRoleFsmInfo->eCurrentState != P2P_ROLE_STATE_IDLE) + p2pRoleFsmRunEventAbort(prAdapter, prP2pRoleFsmInfo); + /* Update connection request information. */ + prConnReqInfo->eConnRequest = P2P_CONNECTION_TYPE_GC; + COPY_MAC_ADDR(prConnReqInfo->aucBssid, + prP2pConnReqMsg->aucBssid); + COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, + prP2pConnReqMsg->aucSrcMacAddr); + kalMemCopy(&(prConnReqInfo->rSsidStruct), + &(prP2pConnReqMsg->rSsid), + sizeof(struct P2P_SSID_STRUCT)); + kalMemCopy(prConnReqInfo->aucIEBuf, + prP2pConnReqMsg->aucIEBuf, + prP2pConnReqMsg->u4IELen); + prConnReqInfo->u4BufLength = prP2pConnReqMsg->u4IELen; + + /* Find BSS Descriptor first. */ + prJoinInfo->prTargetBssDesc = + scanP2pSearchDesc(prAdapter, prConnReqInfo); + + if (prJoinInfo->prTargetBssDesc == NULL) { + p2pRoleFsmScanTargetBss(prAdapter, + prP2pRoleFsmInfo, + prP2pConnReqMsg->rChannelInfo.ucChannelNum, + &(prP2pConnReqMsg->rSsid)); + } else { + prChnlReqInfo->u8Cookie = 0; + prChnlReqInfo->ucReqChnlNum = + prP2pConnReqMsg->rChannelInfo.ucChannelNum; + prChnlReqInfo->eBand = prP2pConnReqMsg->rChannelInfo.eBand; + prChnlReqInfo->eChnlSco = prP2pConnReqMsg->eChnlSco; + prChnlReqInfo->u4MaxInterval = AIS_JOIN_CH_REQUEST_INTERVAL; + prChnlReqInfo->eChnlReqType = CH_REQ_TYPE_JOIN; + + rlmReviseMaxBw(prAdapter, + prP2pBssInfo->ucBssIndex, + &prChnlReqInfo->eChnlSco, + (enum ENUM_CHANNEL_WIDTH *) + &prChnlReqInfo->eChannelWidth, + &prChnlReqInfo->ucCenterFreqS1, + &prChnlReqInfo->ucReqChnlNum); + + prP2pBssInfo->eBand = prChnlReqInfo->eBand; + if (prP2pBssInfo->fgIsWmmInited == FALSE) + prP2pBssInfo->ucWmmQueSet = + cnmWmmIndexDecision(prAdapter, prP2pBssInfo); + +#if CFG_SUPPORT_DBDC + /* DBDC decsion.may change OpNss */ + cnmDbdcPreConnectionEnableDecision(prAdapter, + prP2pBssInfo->ucBssIndex, + prChnlReqInfo->eBand, + prChnlReqInfo->ucReqChnlNum, + prP2pBssInfo->ucWmmQueSet); +#endif /* CFG_SUPPORT_DBDC */ + + cnmOpModeGetTRxNss( + prAdapter, prP2pBssInfo->ucBssIndex, + &prP2pBssInfo->ucOpRxNss, &prP2pBssInfo->ucOpTxNss); + + DBGLOG(P2P, INFO, + "p2pRoleFsmRunEventConnectionRequest: start GC CH[%u]RxNSS[%u]TxNss[%u]\n", + prChnlReqInfo->ucReqChnlNum, + prP2pBssInfo->ucOpRxNss, + prP2pBssInfo->ucOpTxNss); + + + /* Decide RF BW by own OP and Peer OP BW */ + ucRfBw = cnmGetDbdcBwCapability(prAdapter, + prP2pBssInfo->ucBssIndex); + /* Revise to VHT OP BW */ + ucRfBw = rlmGetVhtOpBwByBssOpBw(ucRfBw); + if (ucRfBw > prJoinInfo->prTargetBssDesc->eChannelWidth) + ucRfBw = prJoinInfo->prTargetBssDesc->eChannelWidth; + + prChnlReqInfo->eChannelWidth = ucRfBw; + /* TODO: BW80+80 support */ + prChnlReqInfo->ucCenterFreqS1 = + nicGetVhtS1(prChnlReqInfo->ucReqChnlNum, + prChnlReqInfo->eChannelWidth); + prChnlReqInfo->ucCenterFreqS2 = 0; + + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_REQING_CHANNEL); + } + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pRoleFsmRunEventConnectionRequest */ + +void p2pRoleFsmRunEventConnectionAbort(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct MSG_P2P_CONNECTION_ABORT *prDisconnMsg = + (struct MSG_P2P_CONNECTION_ABORT *) NULL; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + + + prDisconnMsg = (struct MSG_P2P_CONNECTION_ABORT *) prMsgHdr; + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prDisconnMsg->ucRoleIdx); + + DBGLOG(P2P, TRACE, + "p2pFsmRunEventConnectionAbort: Connection Abort.\n"); + + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, ERROR, + "p2pRoleFsmRunEventConnectionAbort: Corresponding P2P Role FSM empty: %d.\n", + prDisconnMsg->ucRoleIdx); + goto error; + } + + prP2pBssInfo = prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex]; + + if (!prP2pBssInfo) { + DBGLOG(P2P, ERROR, + "prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex(%d)] is NULL!", + prP2pRoleFsmInfo->ucBssIndex); + goto error; + } + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_INFRASTRUCTURE: + { + uint8_t aucBCBSSID[] = BC_BSSID; + + if (!prP2pBssInfo->prStaRecOfAP) { + struct P2P_JOIN_INFO *prJoinInfo; + + DBGLOG(P2P, TRACE, "GO's StaRec is NULL\n"); + /* Receive disconnection request during GC join. + * Abort GC join to prevent STA record leak. + */ + prJoinInfo = &(prP2pRoleFsmInfo->rJoinInfo); + if (prJoinInfo->prTargetStaRec) { + p2pFuncDisconnect(prAdapter, + prP2pBssInfo, + prJoinInfo->prTargetStaRec, + FALSE, + REASON_CODE_DEAUTH_LEAVING_BSS); + + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_IDLE); + } + 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; + } + + prStaRec = prP2pBssInfo->prStaRecOfAP; + + /* Stop rejoin timer if it is started. */ + /* TODO: If it has. */ + + p2pFuncDisconnect(prAdapter, prP2pBssInfo, + prStaRec, + prDisconnMsg->fgSendDeauth, + prDisconnMsg->u2ReasonCode); + + cnmTimerStopTimer(prAdapter, + &(prStaRec->rDeauthTxDoneTimer)); + + cnmTimerInitTimer(prAdapter, + &(prStaRec->rDeauthTxDoneTimer), + (PFN_MGMT_TIMEOUT_FUNC) p2pRoleFsmDeauthTimeout, + (unsigned long) prStaRec); + + cnmTimerStartTimer(prAdapter, + &(prStaRec->rDeauthTxDoneTimer), + P2P_DEAUTH_TIMEOUT_TIME_MS); + + SET_NET_PWR_STATE_IDLE(prAdapter, + prP2pBssInfo->ucBssIndex); + + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_IDLE); + } + break; + case OP_MODE_ACCESS_POINT: + { + /* Search specific client device, and disconnect. */ + /* 1. Send deauthentication frame. */ + /* 2. Indication: Device disconnect. */ + struct STA_RECORD *prCurrStaRec = + (struct STA_RECORD *) NULL; + + DBGLOG(P2P, TRACE, + "Disconnecting with Target ID: " MACSTR "\n", + MAC2STR(prDisconnMsg->aucTargetID)); + + prCurrStaRec = bssGetClientByMac(prAdapter, + prP2pBssInfo, + prDisconnMsg->aucTargetID); + + if (prCurrStaRec) { + DBGLOG(P2P, TRACE, + "Disconnecting: " MACSTR "\n", + MAC2STR(prCurrStaRec->aucMacAddr)); + + /* Glue layer indication. */ + /* kalP2PGOStationUpdate(prAdapter->prGlueInfo, + * prCurrStaRec, FALSE); + */ + + /* Send deauth & do indication. */ + p2pFuncDisconnect(prAdapter, + prP2pBssInfo, + prCurrStaRec, + prDisconnMsg->fgSendDeauth, + prDisconnMsg->u2ReasonCode); + + cnmTimerStopTimer(prAdapter, + &(prCurrStaRec->rDeauthTxDoneTimer)); + + cnmTimerInitTimer(prAdapter, + &(prCurrStaRec->rDeauthTxDoneTimer), + (PFN_MGMT_TIMEOUT_FUNC) + p2pRoleFsmDeauthTimeout, + (unsigned long) prCurrStaRec); + + cnmTimerStartTimer(prAdapter, + &(prCurrStaRec->rDeauthTxDoneTimer), + P2P_DEAUTH_TIMEOUT_TIME_MS); + } +#if 0 + LINK_FOR_EACH(prLinkEntry, prStaRecOfClientList) { + prCurrStaRec = LINK_ENTRY(prLinkEntry, + struct STA_RECORD, 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, + prP2pBssInfo, + prCurrStaRec, + prDisconnMsg->fgSendDeauth, + prDisconnMsg->u2ReasonCode); + + /* prTargetStaRec = prCurrStaRec; */ + + break; + } + } +#endif + + } + break; + case OP_MODE_P2P_DEVICE: + default: + ASSERT(FALSE); + break; + } + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pRoleFsmRunEventConnectionAbort */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is called when JOIN complete message event + * is received from SAA. + * + * \param[in] prAdapter Pointer of ADAPTER_T + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void p2pRoleFsmRunEventJoinComplete(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct P2P_JOIN_INFO *prJoinInfo = + (struct P2P_JOIN_INFO *) NULL; + struct MSG_SAA_FSM_COMP *prJoinCompMsg = + (struct MSG_SAA_FSM_COMP *) NULL; + struct SW_RFB *prAssocRspSwRfb = (struct SW_RFB *) NULL; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + + prJoinCompMsg = (struct MSG_SAA_FSM_COMP *) prMsgHdr; + prStaRec = prJoinCompMsg->prStaRec; + prAssocRspSwRfb = prJoinCompMsg->prSwRfb; + + ASSERT(prStaRec); + if (!prStaRec) { + DBGLOG(P2P, ERROR, "prJoinCompMsg->prStaRec is NULL!\n"); + goto error; + } + + DBGLOG(P2P, INFO, + "P2P BSS %d [" MACSTR "], Join Complete, status: %d\n", + prStaRec->ucBssIndex, + MAC2STR(prStaRec->aucMacAddr), + prJoinCompMsg->rJoinStatus); + + ASSERT(prStaRec->ucBssIndex < prAdapter->ucP2PDevBssIdx); + if (!(prStaRec->ucBssIndex < prAdapter->ucP2PDevBssIdx)) { + DBGLOG(P2P, ERROR, + "prStaRec->ucBssIndex %d should < prAdapter->ucP2PDevBssIdx(%d)!\n", + prStaRec->ucBssIndex, prAdapter->ucP2PDevBssIdx); + goto error; + } + + prP2pBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + if (prP2pBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) { + DBGLOG(P2P, ERROR, + "prP2pBssInfo->eCurrentOPMode %d != OP_MODE_INFRASTRUCTURE(%d)!\n", + prP2pBssInfo->eCurrentOPMode, + OP_MODE_INFRASTRUCTURE); + goto error; + } + + ASSERT(prP2pBssInfo->u4PrivateData < BSS_P2P_NUM); + if (!(prP2pBssInfo->u4PrivateData < BSS_P2P_NUM)) { + DBGLOG(P2P, ERROR, + "prP2pBssInfo->u4PrivateData %d should < BSS_P2P_NUM(%d)!\n", + prP2pBssInfo->u4PrivateData, + BSS_P2P_NUM); + goto error; + } + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData); + + prJoinInfo = &(prP2pRoleFsmInfo->rJoinInfo); + + /* 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, + prP2pBssInfo, + 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); + + prP2pBssInfo->prStaRecOfAP = NULL; + } + /* 4 <1.3> Update BSS_INFO_T */ + if (prAssocRspSwRfb) { + p2pFuncUpdateBssInfoForJOIN(prAdapter, + prJoinInfo->prTargetBssDesc, + prStaRec, prP2pBssInfo, prAssocRspSwRfb); + } else { + DBGLOG(P2P, INFO, + "prAssocRspSwRfb is NULL! Skip p2pFuncUpdateBssInfoForJOIN\n"); + } + + /* 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, prP2pBssInfo->ucBssIndex, + (int8_t) (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, + * MEDIA_STATE_CONNECTED, + * prStaRec->aucMacAddr); + */ + if (prJoinInfo->prTargetBssDesc) + scanReportBss2Cfg80211(prAdapter, + BSS_TYPE_P2P_DEVICE, + prJoinInfo->prTargetBssDesc); +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, + &prP2pRoleFsmInfo->rConnReqInfo, + prJoinInfo->aucIEBuf, + prJoinInfo->u4BufLength, + prStaRec->u2StatusCode, + WLAN_STATUS_MEDIA_DISCONNECT); +#else + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, + &prP2pRoleFsmInfo->rConnReqInfo, + prJoinInfo->aucIEBuf, + prJoinInfo->u4BufLength, + prStaRec->u2StatusCode); + +#endif + + + + } else { + /* Join Fail */ + /* 4 <2.1> Redo JOIN process + * with other Auth Type if possible + */ + if (p2pFuncRetryJOIN(prAdapter, + prStaRec, prJoinInfo) == FALSE) { + + struct BSS_DESC *prBssDesc; + + prBssDesc = prJoinInfo->prTargetBssDesc; + + if (!prBssDesc) { + DBGLOG(P2P, WARN, + "prTargetBssDesc is NULL! Skip retry join\n"); + goto error; + } + + ASSERT(prBssDesc->fgIsConnecting); + prBssDesc->fgIsConnecting = FALSE; + + /* Increase Failure Count */ + prStaRec->ucJoinFailureCount++; + + if (prStaRec->ucJoinFailureCount >= + P2P_SAA_RETRY_COUNT) { +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) + kalP2PGCIndicateConnectionStatus( + prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, + &prP2pRoleFsmInfo->rConnReqInfo, + prJoinInfo->aucIEBuf, + prJoinInfo->u4BufLength, + prStaRec->u2StatusCode, + WLAN_STATUS_MEDIA_DISCONNECT); +#else + kalP2PGCIndicateConnectionStatus( + prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, + &prP2pRoleFsmInfo->rConnReqInfo, + prJoinInfo->aucIEBuf, + prJoinInfo->u4BufLength, + prStaRec->u2StatusCode); +#endif + } + + } + + } + } + + if (prP2pRoleFsmInfo->eCurrentState == P2P_ROLE_STATE_GC_JOIN) { + if (prP2pBssInfo->eConnectionState == + MEDIA_STATE_CONNECTED) { + /* do nothing & wait for timeout or EAPOL 4/4 TX done */ + } else { + struct BSS_DESC *prBssDesc; + struct P2P_SSID_STRUCT rSsid; + + prBssDesc = prJoinInfo->prTargetBssDesc; + + COPY_SSID(rSsid.aucSsid, + rSsid.ucSsidLen, + prBssDesc->aucSSID, + prBssDesc->ucSSIDLen); + p2pRoleFsmScanTargetBss(prAdapter, + prP2pRoleFsmInfo, + prBssDesc->ucChannelNum, + &rSsid); + } + } + +error: + if (prAssocRspSwRfb) + nicRxReturnRFB(prAdapter, prAssocRspSwRfb); + + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pRoleFsmRunEventJoinComplete */ + +void p2pRoleFsmRunEventScanRequest(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_P2P_SCAN_REQUEST *prP2pScanReqMsg = + (struct MSG_P2P_SCAN_REQUEST *) NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct P2P_SCAN_REQ_INFO *prScanReqInfo = + (struct P2P_SCAN_REQ_INFO *) NULL; + uint32_t u4ChnlListSize = 0; + struct P2P_SSID_STRUCT *prP2pSsidStruct = + (struct P2P_SSID_STRUCT *) NULL; + struct BSS_INFO *prP2pBssInfo = NULL; + + + prP2pScanReqMsg = (struct MSG_P2P_SCAN_REQUEST *) prMsgHdr; + + prP2pBssInfo = prAdapter->aprBssInfo[prP2pScanReqMsg->ucBssIdx]; + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData); + + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, ERROR, "prP2pRoleFsmInfo is NULL!"); + goto error; + } + + prP2pScanReqMsg = (struct MSG_P2P_SCAN_REQUEST *) prMsgHdr; + prScanReqInfo = &(prP2pRoleFsmInfo->rScanReqInfo); + + DBGLOG(P2P, TRACE, "p2pDevFsmRunEventScanRequest\n"); + + /* Do we need to be in IDLE state? */ + /* p2pDevFsmRunEventAbort(prAdapter, prP2pDevFsmInfo); */ + + ASSERT(prScanReqInfo->fgIsScanRequest == FALSE); + + prScanReqInfo->fgIsAbort = TRUE; + prScanReqInfo->eScanType = prP2pScanReqMsg->eScanType; + + if (prP2pScanReqMsg->u4NumChannel) { + 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(struct RF_CHANNEL_INFO) + * prScanReqInfo->ucNumChannelList; + kalMemCopy(prScanReqInfo->arScanChannelList, + prP2pScanReqMsg->arChannelListInfo, u4ChnlListSize); + } else { + /* If channel number is ZERO. + * It means do a FULL channel scan. + */ + prScanReqInfo->eChannelSet = SCAN_CHANNEL_FULL; + } + + /* SSID */ + prP2pSsidStruct = prP2pScanReqMsg->prSSID; + for (prScanReqInfo->ucSsidNum = 0; + prScanReqInfo->ucSsidNum < prP2pScanReqMsg->i4SsidNum; + prScanReqInfo->ucSsidNum++) { + + kalMemCopy( + prScanReqInfo->arSsidStruct[prScanReqInfo->ucSsidNum] + .aucSsid, + prP2pSsidStruct->aucSsid, prP2pSsidStruct->ucSsidLen); + + prScanReqInfo->arSsidStruct[prScanReqInfo->ucSsidNum] + .ucSsidLen = + prP2pSsidStruct->ucSsidLen; + + prP2pSsidStruct++; + } + + /* IE Buffer */ + kalMemCopy(prScanReqInfo->aucIEBuf, + prP2pScanReqMsg->pucIEBuf, + prP2pScanReqMsg->u4IELen); + + prScanReqInfo->u4BufLength = prP2pScanReqMsg->u4IELen; + prScanReqInfo->eScanReason = prP2pScanReqMsg->eScanReason; + + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_SCAN); + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventScanRequest */ + +void +p2pRoleFsmRunEventScanDone(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo) +{ + struct MSG_SCN_SCAN_DONE *prScanDoneMsg = + (struct MSG_SCN_SCAN_DONE *) prMsgHdr; + struct P2P_SCAN_REQ_INFO *prScanReqInfo = + (struct P2P_SCAN_REQ_INFO *) NULL; + enum ENUM_P2P_ROLE_STATE eNextState = P2P_ROLE_STATE_NUM; + struct P2P_CONNECTION_REQ_INFO *prConnReqInfo = + &(prP2pRoleFsmInfo->rConnReqInfo); + struct P2P_JOIN_INFO *prP2pJoinInfo = + &(prP2pRoleFsmInfo->rJoinInfo); + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct P2P_CHNL_REQ_INFO *prChnlReqInfo = + (struct P2P_CHNL_REQ_INFO *) NULL; + struct P2P_SCAN_REQ_INFO *prScanInfo; + + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, TRACE, "prP2pRoleFsmInfo is NULL\n"); + goto error; + } + + DBGLOG(P2P, TRACE, "P2P Role Scan Done Event\n"); + + prScanReqInfo = &(prP2pRoleFsmInfo->rScanReqInfo); + prScanDoneMsg = (struct MSG_SCN_SCAN_DONE *) prMsgHdr; + prScanInfo = &prP2pRoleFsmInfo->rScanReqInfo; + + 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 Role Scan Don SeqNum Received:%d <-> P2P Role Fsm SCAN Seq Issued:%d\n", + prScanDoneMsg->ucSeqNum, + prScanReqInfo->ucSeqNumOfScnMsg); + + goto error; + } + + switch (prP2pRoleFsmInfo->eCurrentState) { + case P2P_ROLE_STATE_SCAN: + prScanReqInfo->fgIsAbort = FALSE; + + if (prConnReqInfo->eConnRequest == P2P_CONNECTION_TYPE_GC) { + + prP2pJoinInfo->prTargetBssDesc = + p2pFuncKeepOnConnection(prAdapter, + prAdapter->aprBssInfo + [prP2pRoleFsmInfo->ucBssIndex], + prConnReqInfo, + &prP2pRoleFsmInfo->rChnlReqInfo, + &prP2pRoleFsmInfo->rScanReqInfo); + if ((prP2pJoinInfo->prTargetBssDesc) == NULL) { + eNextState = P2P_ROLE_STATE_SCAN; + } else { + prP2pBssInfo = + prAdapter->aprBssInfo + [prP2pRoleFsmInfo->ucBssIndex]; + if (!prP2pBssInfo) + break; + prChnlReqInfo = + &(prP2pRoleFsmInfo->rChnlReqInfo); + if (!prChnlReqInfo) + break; + + prP2pBssInfo->eBand = prChnlReqInfo->eBand; + if (prP2pBssInfo->fgIsWmmInited == FALSE) + prP2pBssInfo->ucWmmQueSet = + cnmWmmIndexDecision(prAdapter, + prP2pBssInfo); +#if CFG_SUPPORT_DBDC + /* DBDC decsion.may change OpNss */ + cnmDbdcPreConnectionEnableDecision(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + prChnlReqInfo->eBand, + prChnlReqInfo->ucReqChnlNum, + prP2pBssInfo->ucWmmQueSet); +#endif /* CFG_SUPPORT_DBDC */ + + cnmOpModeGetTRxNss( + prAdapter, prP2pRoleFsmInfo->ucBssIndex, + &prP2pBssInfo->ucOpRxNss, + &prP2pBssInfo->ucOpTxNss); + + DBGLOG(P2P, INFO, + "p2pRoleFsmRunEventScanDone: start GC CH[%u]RxNSS[%u]TxNss[%u]\n", + prChnlReqInfo->ucReqChnlNum, + prP2pBssInfo->ucOpRxNss, + prP2pBssInfo->ucOpTxNss); + + /* For GC join. */ + eNextState = P2P_ROLE_STATE_REQING_CHANNEL; + } + } else if (prScanInfo->eScanReason == SCAN_REASON_ACS) { + struct P2P_ACS_REQ_INFO *prAcsReqInfo; + + prAcsReqInfo = &prP2pRoleFsmInfo->rAcsReqInfo; + prScanInfo->eScanReason = SCAN_REASON_UNKNOWN; + p2pFunCalAcsChnScores(prAdapter); + if (wlanQueryLteSafeChannel(prAdapter, + prP2pRoleFsmInfo->ucRoleIndex) == + WLAN_STATUS_SUCCESS) { + /* do nothing & wait for FW event */ + } else { + DBGLOG(P2P, WARN, "query safe chn fail.\n"); + p2pFunProcessAcsReport(prAdapter, + prP2pRoleFsmInfo->ucRoleIndex, + NULL, + prAcsReqInfo); + } + eNextState = P2P_ROLE_STATE_IDLE; + } else { + eNextState = P2P_ROLE_STATE_IDLE; + } + break; + case P2P_ROLE_STATE_AP_CHNL_DETECTION: + eNextState = P2P_ROLE_STATE_REQING_CHANNEL; + break; + default: + /* Unexpected channel scan done event + * without being chanceled. + */ + ASSERT(FALSE); + break; + } + + prScanReqInfo->fgIsScanRequest = FALSE; + + p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, eNextState); + +error: + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pRoleFsmRunEventScanDone */ + +void +p2pRoleFsmRunEventChnlGrant(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo) +{ + struct P2P_CHNL_REQ_INFO *prChnlReqInfo = + (struct P2P_CHNL_REQ_INFO *) NULL; + struct MSG_CH_GRANT *prMsgChGrant = (struct MSG_CH_GRANT *) NULL; +#if (CFG_SUPPORT_DFS_MASTER == 1) + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + uint32_t u4CacTimeMs; +#endif + uint8_t ucTokenID = 0; + + + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, ERROR, "prP2pRoleFsmInfo is NULL!\n"); + goto error; + } + + DBGLOG(P2P, TRACE, "P2P Run Event Role Channel Grant\n"); + + prMsgChGrant = (struct MSG_CH_GRANT *) prMsgHdr; + ucTokenID = prMsgChGrant->ucTokenID; + prChnlReqInfo = &(prP2pRoleFsmInfo->rChnlReqInfo); + +#if (CFG_SUPPORT_DFS_MASTER == 1) + prP2pBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, + prMsgChGrant->ucBssIndex); +#endif + if (prChnlReqInfo->u4MaxInterval != prMsgChGrant->u4GrantInterval) { + DBGLOG(P2P, WARN, + "P2P Role:%d Request Channel Interval:%d, Grant Interval:%d\n", + prP2pRoleFsmInfo->ucRoleIndex, + prChnlReqInfo->u4MaxInterval, + prMsgChGrant->u4GrantInterval); + prChnlReqInfo->u4MaxInterval = prMsgChGrant->u4GrantInterval; + } + + if (ucTokenID == prChnlReqInfo->ucSeqNumOfChReq) { + enum ENUM_P2P_ROLE_STATE eNextState = P2P_ROLE_STATE_NUM; + + switch (prP2pRoleFsmInfo->eCurrentState) { + case P2P_ROLE_STATE_REQING_CHANNEL: + switch (prChnlReqInfo->eChnlReqType) { + case CH_REQ_TYPE_JOIN: + eNextState = P2P_ROLE_STATE_GC_JOIN; + break; + case CH_REQ_TYPE_GO_START_BSS: + eNextState = P2P_ROLE_STATE_IDLE; + break; + case CH_REQ_TYPE_OFFCHNL_TX: + eNextState = P2P_ROLE_STATE_OFF_CHNL_TX; + break; + default: + DBGLOG(P2P, WARN, + "p2pRoleFsmRunEventChnlGrant: Invalid Channel Request Type:%d\n", + prChnlReqInfo->eChnlReqType); + GL_RESET_TRIGGER(prAdapter, + RST_FLAG_CHIP_RESET); + break; + } + + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, eNextState); + break; + +#if (CFG_SUPPORT_DFS_MASTER == 1) + case P2P_ROLE_STATE_DFS_CAC: + p2pFuncStartRdd(prAdapter, prMsgChGrant->ucBssIndex); + + if (p2pFuncCheckWeatherRadarBand(prChnlReqInfo)) + u4CacTimeMs = + P2P_AP_CAC_WEATHER_CHNL_HOLD_TIME_MS; + else + u4CacTimeMs = + prP2pRoleFsmInfo->rChnlReqInfo + .u4MaxInterval; + + if (p2pFuncIsManualCac()) + u4CacTimeMs = p2pFuncGetDriverCacTime() * 1000; + else + p2pFuncSetDriverCacTime(u4CacTimeMs/1000); + + cnmTimerStartTimer(prAdapter, + &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer), + u4CacTimeMs); + + p2pFuncRecordCacStartBootTime(); + + p2pFuncSetDfsState(DFS_STATE_CHECKING); + + DBGLOG(P2P, INFO, + "p2pRoleFsmRunEventChnlGrant: CAC time = %ds\n", + u4CacTimeMs/1000); + break; + case P2P_ROLE_STATE_SWITCH_CHANNEL: + p2pFuncDfsSwitchCh(prAdapter, + prP2pBssInfo, + prP2pRoleFsmInfo->rChnlReqInfo); + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_IDLE); + break; +#endif + case P2P_ROLE_STATE_OFF_CHNL_TX: + if (prMsgChGrant->eReqType == CH_REQ_TYPE_OFFCHNL_TX) { + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_OFF_CHNL_TX); + } else { + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_IDLE); + } + break; + default: + /* Channel is granted under unexpected state. + * Driver should cancel channel privileagea + * before leaving the states. + */ + if (IS_BSS_ACTIVE( + prAdapter->aprBssInfo + [prP2pRoleFsmInfo->ucBssIndex])) { + DBGLOG(P2P, WARN, + "p2pRoleFsmRunEventChnlGrant: Invalid CurrentState:%d\n", + prP2pRoleFsmInfo->eCurrentState); + GL_RESET_TRIGGER(prAdapter, + RST_FLAG_CHIP_RESET); + } + break; + } + } else { + DBGLOG(P2P, ERROR, + "p2pRoleFsmRunEventChnlGrant: Token mismatch, Chreq: %d, ChGrant: %d\n", + prChnlReqInfo->ucSeqNumOfChReq, ucTokenID); + } + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pRoleFsmRunEventChnlGrant */ + +/* ////////////////////////////////////// */ +void p2pRoleFsmRunEventDissolve(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + /* TODO: */ + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pRoleFsmRunEventDissolve */ + +/*----------------------------------------------------------------------------*/ +/*! + * @ This routine update the current MAC table based on the current ACL. + * If ACL change causing an associated STA become un-authorized. This STA + * will be kicked out immediately. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] ucBssIdx Bss index. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void p2pRoleUpdateACLEntry(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIdx) +{ + u_int8_t bMatchACL = FALSE; + int32_t i = 0; + struct LINK *prClientList; + struct STA_RECORD *prCurrStaRec, *prNextStaRec; + struct BSS_INFO *prP2pBssInfo; + + ASSERT(prAdapter); + + if ((!prAdapter) || (ucBssIdx > prAdapter->ucHwBssIdNum)) + return; + + DBGLOG(P2P, TRACE, "Update ACL Entry ucBssIdx = %d\n", ucBssIdx); + prP2pBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + /* ACL is disabled. Do nothing about the MAC table. */ + if (prP2pBssInfo->rACL.ePolicy == PARAM_CUSTOM_ACL_POLICY_DISABLE) + return; + + prClientList = &prP2pBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH_ENTRY_SAFE(prCurrStaRec, + prNextStaRec, prClientList, rLinkEntry, struct STA_RECORD) { + if (!prCurrStaRec) + break; + bMatchACL = FALSE; + for (i = 0; i < prP2pBssInfo->rACL.u4Num; i++) { + if (EQUAL_MAC_ADDR(prCurrStaRec->aucMacAddr, + prP2pBssInfo->rACL.rEntry[i].aucAddr)) { + bMatchACL = TRUE; + break; + } + } + + if (((!bMatchACL) && + (prP2pBssInfo->rACL.ePolicy + == PARAM_CUSTOM_ACL_POLICY_ACCEPT)) + || ((bMatchACL) && + (prP2pBssInfo->rACL.ePolicy + == PARAM_CUSTOM_ACL_POLICY_DENY))) { + struct MSG_P2P_CONNECTION_ABORT *prDisconnectMsg = + (struct MSG_P2P_CONNECTION_ABORT *) NULL; + + DBGLOG(P2P, TRACE, + "ucBssIdx=%d, ACL Policy=%d\n", + ucBssIdx, prP2pBssInfo->rACL.ePolicy); + + prDisconnectMsg = + (struct MSG_P2P_CONNECTION_ABORT *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_P2P_CONNECTION_ABORT)); + if (prDisconnectMsg == NULL) + return; + prDisconnectMsg->rMsgHdr.eMsgId + = MID_MNY_P2P_CONNECTION_ABORT; + prDisconnectMsg->ucRoleIdx + = (uint8_t) prP2pBssInfo->u4PrivateData; + COPY_MAC_ADDR(prDisconnectMsg->aucTargetID, + prCurrStaRec->aucMacAddr); + prDisconnectMsg->u2ReasonCode + = STATUS_CODE_REQ_DECLINED; + prDisconnectMsg->fgSendDeauth = TRUE; + mboxSendMsg(prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prDisconnectMsg, + MSG_SEND_METHOD_BUF); + } + } +} /* p2pRoleUpdateACLEntry */ + +/*----------------------------------------------------------------------------*/ +/*! + * @ Check if the specified STA pass the Access Control List inspection. + * If fails to pass the checking, + * then no authentication or association is allowed. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] pMacAddr Pointer to the mac address. + * @param[in] ucBssIdx Bss index. + * + * @return TRUE - pass ACL inspection, FALSE - ACL inspection fail + */ +/*----------------------------------------------------------------------------*/ +u_int8_t p2pRoleProcessACLInspection(IN struct ADAPTER *prAdapter, + IN uint8_t *pMacAddr, + IN uint8_t ucBssIdx) +{ + u_int8_t bPassACL = TRUE; + int32_t i = 0; + struct BSS_INFO *prP2pBssInfo; + + ASSERT(prAdapter); + + if ((!prAdapter) || (!pMacAddr) || (ucBssIdx > prAdapter->ucHwBssIdNum)) + return FALSE; + + prP2pBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + if (prP2pBssInfo->rACL.ePolicy == PARAM_CUSTOM_ACL_POLICY_DISABLE) + return TRUE; + + if (prP2pBssInfo->rACL.ePolicy == PARAM_CUSTOM_ACL_POLICY_ACCEPT) + bPassACL = FALSE; + else + bPassACL = TRUE; + + for (i = 0; i < prP2pBssInfo->rACL.u4Num; i++) { + if (EQUAL_MAC_ADDR(pMacAddr, + prP2pBssInfo->rACL.rEntry[i].aucAddr)) { + bPassACL = !bPassACL; + break; + } + } + + if (bPassACL == FALSE) + DBGLOG(P2P, WARN, + "this mac [" MACSTR "] is fail to pass ACL inspection.\n", + MAC2STR(pMacAddr)); + + return bPassACL; +} /* p2pRoleProcessACLInspection */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will indicate the Event + * of Successful Completion of AAA Module. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] prStaRec Pointer to the STA_RECORD_T + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +uint32_t +p2pRoleFsmRunEventAAAComplete(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct BSS_INFO *prP2pBssInfo) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + enum ENUM_PARAM_MEDIA_STATE eOriMediaState; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prStaRec != NULL) && (prP2pBssInfo != NULL)); + + eOriMediaState = prP2pBssInfo->eConnectionState; + + bssRemoveClient(prAdapter, prP2pBssInfo, prStaRec); + + if (prP2pBssInfo->rStaRecOfClientList.u4NumElem + >= P2P_MAXIMUM_CLIENT_COUNT + || !p2pRoleProcessACLInspection(prAdapter, + prStaRec->aucMacAddr, + prP2pBssInfo->ucBssIndex) +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + || kalP2PMaxClients(prAdapter->prGlueInfo, + prP2pBssInfo->rStaRecOfClientList.u4NumElem, + (uint8_t) prP2pBssInfo->u4PrivateData) +#endif + ) { + rStatus = WLAN_STATUS_RESOURCES; + break; + } + + bssAddClient(prAdapter, prP2pBssInfo, prStaRec); + + prStaRec->u2AssocId = bssAssignAssocID(prStaRec); + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + p2pChangeMediaState(prAdapter, + prP2pBssInfo, + MEDIA_STATE_CONNECTED); + + /* Update Connected state to FW. */ + if (eOriMediaState != prP2pBssInfo->eConnectionState) + nicUpdateBss(prAdapter, prP2pBssInfo->ucBssIndex); + + } while (FALSE); + + return rStatus; +} /* p2pRunEventAAAComplete */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will indicate the Event + * of Successful Completion of AAA Module. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] prStaRec Pointer to the STA_RECORD_T + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +uint32_t +p2pRoleFsmRunEventAAASuccess(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct BSS_INFO *prP2pBssInfo) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prStaRec != NULL) && (prP2pBssInfo != NULL)); + + if ((prP2pBssInfo->eNetworkType != NETWORK_TYPE_P2P) + || (prP2pBssInfo->u4PrivateData >= BSS_P2P_NUM)) { + ASSERT(FALSE); + rStatus = WLAN_STATUS_INVALID_DATA; + break; + } + + ASSERT(prP2pBssInfo->ucBssIndex < prAdapter->ucP2PDevBssIdx); + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData); + + /* Glue layer indication. */ + kalP2PGOStationUpdate(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, prStaRec, TRUE); + + } while (FALSE); + + return rStatus; +} /* p2pRoleFsmRunEventAAASuccess */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will indicate the Event + * of Tx Fail of AAA Module. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] prStaRec Pointer to the STA_RECORD_T + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void p2pRoleFsmRunEventAAATxFail(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct BSS_INFO *prP2pBssInfo) +{ + ASSERT(prAdapter); + ASSERT(prStaRec); + + bssRemoveClient(prAdapter, prP2pBssInfo, prStaRec); + + p2pFuncDisconnect(prAdapter, + prP2pBssInfo, prStaRec, FALSE, + prStaRec->eAuthAssocState == AAA_STATE_SEND_AUTH2 + ? STATUS_CODE_AUTH_TIMEOUT + : STATUS_CODE_ASSOC_TIMEOUT); + + /* 20120830 moved into p2puUncDisconnect. */ + /* cnmStaRecFree(prAdapter, prStaRec); */ +} /* p2pRoleFsmRunEventAAATxFail */ + +void p2pRoleFsmRunEventSwitchOPMode(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct MSG_P2P_SWITCH_OP_MODE *prSwitchOpMode = + (struct MSG_P2P_SWITCH_OP_MODE *) prMsgHdr; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct P2P_CONNECTION_REQ_INFO *prConnReqInfo = + (struct P2P_CONNECTION_REQ_INFO *) NULL; + + ASSERT(prSwitchOpMode->ucRoleIdx < BSS_P2P_NUM); + if (!(prSwitchOpMode->ucRoleIdx < BSS_P2P_NUM)) { + DBGLOG(P2P, ERROR, + "prSwitchOpMode->ucRoleIdx %d should < BSS_P2P_NUM(%d)\n", + prSwitchOpMode->ucRoleIdx, BSS_P2P_NUM); + goto error; + } + + prP2pRoleFsmInfo = + prAdapter->rWifiVar + .aprP2pRoleFsmInfo[prSwitchOpMode->ucRoleIdx]; + prConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + + ASSERT(prP2pRoleFsmInfo->ucBssIndex < prAdapter->ucP2PDevBssIdx); + if (!(prP2pRoleFsmInfo->ucBssIndex < prAdapter->ucP2PDevBssIdx)) { + DBGLOG(P2P, ERROR, + "prP2pRoleFsmInfo->ucBssIndex %d should < prAdapter->ucP2PDevBssIdx(%d)\n", + prP2pRoleFsmInfo->ucBssIndex, + prAdapter->ucP2PDevBssIdx); + goto error; + } + + prP2pBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, + prP2pRoleFsmInfo->ucBssIndex); + + if (!(prSwitchOpMode->eOpMode < OP_MODE_NUM)) { + DBGLOG(P2P, ERROR, + "prSwitchOpMode->eOpMode %d should < OP_MODE_NUM(%d)\n", + prSwitchOpMode->eOpMode, OP_MODE_NUM); + goto error; + } + + /* P2P Device / GC. */ + p2pFuncSwitchOPMode(prAdapter, + prP2pBssInfo, + prSwitchOpMode->eOpMode, + TRUE); + + if (prP2pBssInfo->eIftype == IFTYPE_P2P_CLIENT && + prSwitchOpMode->eIftype == IFTYPE_STATION) { + kalP2pUnlinkBss(prAdapter->prGlueInfo, prConnReqInfo->aucBssid); + } + prP2pBssInfo->eIftype = prSwitchOpMode->eIftype; + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pRoleFsmRunEventSwitchOPMode */ + +/* /////////////////////////////// TO BE REFINE //////////////////////////// */ + +void p2pRoleFsmRunEventBeaconUpdate(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct P2P_ROLE_FSM_INFO *prRoleP2pFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct MSG_P2P_BEACON_UPDATE *prBcnUpdateMsg = + (struct MSG_P2P_BEACON_UPDATE *) NULL; + struct P2P_BEACON_UPDATE_INFO *prBcnUpdateInfo = + (struct P2P_BEACON_UPDATE_INFO *) NULL; + + + DBGLOG(P2P, TRACE, "p2pRoleFsmRunEventBeaconUpdate\n"); + + prBcnUpdateMsg = (struct MSG_P2P_BEACON_UPDATE *) prMsgHdr; + if (prBcnUpdateMsg->ucRoleIndex >= BSS_P2P_NUM) + goto error; + + prRoleP2pFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prBcnUpdateMsg->ucRoleIndex); + if (!prRoleP2pFsmInfo) + goto error; + + prP2pBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, + prRoleP2pFsmInfo->ucBssIndex); + + prP2pBssInfo->fgIsWepCipherGroup = prBcnUpdateMsg->fgIsWepCipher; + + prBcnUpdateInfo = &(prRoleP2pFsmInfo->rBeaconUpdateInfo); + + DBGLOG(P2P, TRACE, "Dump beacon content from supplicant.\n"); + if (aucDebugModule[DBG_P2P_IDX] & DBG_CLASS_TRACE) { + dumpMemory8((uint8_t *) prBcnUpdateMsg->pucBcnBody, + (uint32_t) prBcnUpdateMsg->u4BcnBodyLen); + } + + p2pFuncBeaconUpdate(prAdapter, + prP2pBssInfo, + prBcnUpdateInfo, + prBcnUpdateMsg->pucBcnHdr, + prBcnUpdateMsg->u4BcnHdrLen, + prBcnUpdateMsg->pucBcnBody, + prBcnUpdateMsg->u4BcnBodyLen); + + if (prBcnUpdateMsg->pucAssocRespIE != NULL + && prBcnUpdateMsg->u4AssocRespLen > 0) { + DBGLOG(P2P, TRACE, + "Copy extra IEs for assoc resp (Length= %d)\n", + prBcnUpdateMsg->u4AssocRespLen); + DBGLOG_MEM8(P2P, TRACE, + prBcnUpdateMsg->pucAssocRespIE, + prBcnUpdateMsg->u4AssocRespLen); + + if (p2pFuncAssocRespUpdate(prAdapter, + prP2pBssInfo, + prBcnUpdateMsg->pucAssocRespIE, + prBcnUpdateMsg->u4AssocRespLen) == WLAN_STATUS_FAILURE) + DBGLOG(P2P, ERROR, + "Update extra IEs for asso resp fail!\n"); + } + + + if ((prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) && + (prP2pBssInfo->eIntendOPMode == OP_MODE_NUM)) { + /* AP is created, Beacon Update. */ + /* nicPmIndicateBssAbort(prAdapter, NETWORK_TYPE_P2P_INDEX); */ + + + DBGLOG(P2P, TRACE, + "p2pRoleFsmRunEventBeaconUpdate with Bssidex(%d)\n", + prRoleP2pFsmInfo->ucBssIndex); + + bssUpdateBeaconContent(prAdapter, prRoleP2pFsmInfo->ucBssIndex); + +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP + if (p2pFuncProbeRespUpdate(prAdapter, + prP2pBssInfo, + prBcnUpdateMsg->pucProbeRespIE, + prBcnUpdateMsg->u4ProbeRespLen) == WLAN_STATUS_FAILURE) + DBGLOG(P2P, ERROR, + "Update extra IEs for probe resp fail!\n"); +#endif + /* nicPmIndicateBssCreated(prAdapter, + * NETWORK_TYPE_P2P_INDEX); + */ + } +error: + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pRoleFsmRunEventBeaconUpdate */ + +void +p2pProcessEvent_UpdateNOAParam(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct EVENT_UPDATE_NOA_PARAMS *prEventUpdateNoaParam) +{ + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo; + uint32_t i; + u_int8_t fgNoaAttrExisted = FALSE; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + prP2pSpecificBssInfo = + prAdapter->rWifiVar + .prP2pSpecificBssInfo[prBssInfo->u4PrivateData]; + + prP2pSpecificBssInfo->fgEnableOppPS = + prEventUpdateNoaParam->ucEnableOppPS; + 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].ucIsInUse; + /* 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; + + DBGLOG(P2P, INFO, "Update NoA param, count=%d, ucBssIdx=%d\n", + prEventUpdateNoaParam->ucNoATimingCount, + ucBssIdx); + + /* update beacon content by the change */ + bssUpdateBeaconContent(prAdapter, ucBssIdx); +} /* p2pProcessEvent_UpdateNOAParam */ + +#if CFG_ENABLE_PER_STA_STATISTICS_LOG +void +p2pRoleFsmGetStaStatistics(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr) +{ + uint32_t u4BufLen; + struct PARAM_GET_STA_STATISTICS *prQueryStaStatistics; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) ulParamPtr; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + + if ((!prAdapter) || (!prP2pRoleFsmInfo)) { + DBGLOG(P2P, ERROR, "prAdapter=NULL || prP2pRoleFsmInfo=NULL\n"); + return; + } + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prP2pRoleFsmInfo->ucBssIndex); + if (!prP2pBssInfo) { + DBGLOG(P2P, ERROR, "prP2pBssInfo=NULL\n"); + return; + } + + prQueryStaStatistics = + prAdapter->rWifiVar.prP2pQueryStaStatistics + [prP2pRoleFsmInfo->ucRoleIndex]; + if (!prQueryStaStatistics) { + DBGLOG(P2P, ERROR, "prQueryStaStatistics=NULL\n"); + return; + } + + if (prP2pBssInfo->eConnectionState == MEDIA_STATE_CONNECTED) { + if ((prP2pBssInfo->eCurrentOPMode + != OP_MODE_INFRASTRUCTURE) && + (prP2pBssInfo->eCurrentOPMode + != OP_MODE_ACCESS_POINT)) { + DBGLOG(P2P, ERROR, "Invalid OPMode=%d\n", + prP2pBssInfo->eCurrentOPMode); + return; + } + if (prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE + && prP2pBssInfo->prStaRecOfAP) { + COPY_MAC_ADDR( + prQueryStaStatistics->aucMacAddr, + prP2pBssInfo->prStaRecOfAP->aucMacAddr); + } else if (prP2pBssInfo->eCurrentOPMode + == OP_MODE_ACCESS_POINT) { + struct STA_RECORD *prCurrStaRec; + struct LINK *prClientList = + &prP2pBssInfo->rStaRecOfClientList; + if (!prClientList) { + DBGLOG(P2P, ERROR, "prClientList=NULL\n"); + return; + } + LINK_FOR_EACH_ENTRY(prCurrStaRec, + prClientList, rLinkEntry, struct STA_RECORD) { + if (!prCurrStaRec) + break; + COPY_MAC_ADDR( + prQueryStaStatistics->aucMacAddr, + prCurrStaRec->aucMacAddr); + /* break for LINK_FOR_EACH_ENTRY */ + break; + } + } + + prQueryStaStatistics->ucReadClear = TRUE; + wlanQueryStaStatistics(prAdapter, + prQueryStaStatistics, + sizeof(struct PARAM_GET_STA_STATISTICS), + &u4BufLen, + FALSE); + + } + + cnmTimerStartTimer(prAdapter, + &(prP2pRoleFsmInfo->rP2pRoleFsmGetStatisticsTimer), + P2P_ROLE_GET_STATISTICS_TIME); +} +#endif + +void p2pRoleFsmNotifyEapolTxStatus(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN enum ENUM_EAPOL_KEY_TYPE_T rEapolKeyType, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + + if (prAdapter == NULL) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (prBssInfo == NULL || prBssInfo->eNetworkType != NETWORK_TYPE_P2P) + return; + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prBssInfo->u4PrivateData); + + if (prP2pRoleFsmInfo == NULL) + return; + + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + return; + if (prP2pRoleFsmInfo->eCurrentState != P2P_ROLE_STATE_GC_JOIN) + return; + + if (rEapolKeyType == EAPOL_KEY_4_OF_4 && + rTxDoneStatus == TX_RESULT_SUCCESS) { + /* Finish GC connection process. */ + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_IDLE); + } +} + +static u_int8_t +p2pRoleNeedOffchnlTx(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct MSG_MGMT_TX_REQUEST *prMgmtTxMsg) +{ + u_int8_t fgNeedOffchnlTx = FALSE; + struct WLAN_MAC_HEADER *prWlanHdr = (struct WLAN_MAC_HEADER *) NULL; + + if (prAdapter == NULL || prBssInfo == NULL || prMgmtTxMsg == NULL) + return FALSE; + + fgNeedOffchnlTx = prMgmtTxMsg->fgIsOffChannel; + + if (fgNeedOffchnlTx) { + prWlanHdr = (struct WLAN_MAC_HEADER *) + ((unsigned long) prMgmtTxMsg->prMgmtMsduInfo->prPacket + + MAC_TX_RESERVED_FIELD); + if (prMgmtTxMsg->rChannelInfo.ucChannelNum == + prBssInfo->ucPrimaryChannel) + fgNeedOffchnlTx = FALSE; + else if ((prWlanHdr->u2FrameCtrl & MASK_FRAME_TYPE) == + MAC_FRAME_PROBE_RSP) + fgNeedOffchnlTx = FALSE; + } + + return fgNeedOffchnlTx; +} /* p2pRoleNeedOffchnlTx */ + + +static void +p2pRoleAdjustChnlTime(IN struct MSG_MGMT_TX_REQUEST *prMgmtTxMsg, + IN struct P2P_OFF_CHNL_TX_REQ_INFO *prOffChnlTxReq) +{ + if (prMgmtTxMsg == NULL || prOffChnlTxReq == NULL) + return; + + if (!prMgmtTxMsg->fgIsOffChannel) + return; + + if (prMgmtTxMsg->u4Duration < MIN_TX_DURATION_TIME_MS) { + /* + * The wait time requested from Supplicant is too short + * to TX a frame, eg. nego.conf.. Overwrite the wait time + * as driver's min TX time. + */ + DBGLOG(P2P, INFO, "Overwrite channel duration from %d to %d\n", + prMgmtTxMsg->u4Duration, + MIN_TX_DURATION_TIME_MS); + prOffChnlTxReq->u4Duration = MIN_TX_DURATION_TIME_MS; + } else { + prOffChnlTxReq->u4Duration = prMgmtTxMsg->u4Duration; + } +} /* p2pRoleAdjustChnlTime */ + +static void +p2pRoleChnlReqByOffChnl(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + struct P2P_OFF_CHNL_TX_REQ_INFO *prOffChnlTxReq) +{ + struct P2P_CHNL_REQ_INFO *prP2pChnlReqInfo = + (struct P2P_CHNL_REQ_INFO *) NULL; + + if (prAdapter == NULL || prP2pRoleFsmInfo == NULL || + prOffChnlTxReq == NULL) + return; + + prP2pChnlReqInfo = &(prP2pRoleFsmInfo->rChnlReqInfo); + + prP2pChnlReqInfo->u8Cookie = prOffChnlTxReq->u8Cookie; + prP2pChnlReqInfo->eChnlReqType = CH_REQ_TYPE_OFFCHNL_TX; + prP2pChnlReqInfo->eBand = prOffChnlTxReq->rChannelInfo.eBand; + prP2pChnlReqInfo->ucReqChnlNum = + prOffChnlTxReq->rChannelInfo.ucChannelNum; + prP2pChnlReqInfo->eChnlSco = prOffChnlTxReq->eChnlExt; + prP2pChnlReqInfo->u4MaxInterval = prOffChnlTxReq->u4Duration; + prP2pChnlReqInfo->eChannelWidth = prOffChnlTxReq->rChannelInfo.ucChnlBw; + prP2pChnlReqInfo->ucCenterFreqS1 = + prOffChnlTxReq->rChannelInfo.u4CenterFreq1; + prP2pChnlReqInfo->ucCenterFreqS2 = + prOffChnlTxReq->rChannelInfo.u4CenterFreq2; + + p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, + P2P_ROLE_STATE_REQING_CHANNEL); +} /* p2pRoleChnlReqByOffChnl */ + +static u_int8_t +p2pRoleAddTxReq2Queue(IN struct ADAPTER *prAdapter, + IN struct P2P_MGMT_TX_REQ_INFO *prP2pMgmtTxReqInfo, + IN struct MSG_MGMT_TX_REQUEST *prMgmtTxMsg, + OUT struct P2P_OFF_CHNL_TX_REQ_INFO **pprOffChnlTxReq) +{ + struct P2P_OFF_CHNL_TX_REQ_INFO *prTmpOffChnlTxReq = + (struct P2P_OFF_CHNL_TX_REQ_INFO *) NULL; + + prTmpOffChnlTxReq = cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(struct P2P_OFF_CHNL_TX_REQ_INFO)); + + if (prTmpOffChnlTxReq == NULL) { + DBGLOG(P2P, ERROR, + "Allocate TX request buffer fails.\n"); + return FALSE; + } + + prTmpOffChnlTxReq->ucBssIndex = prMgmtTxMsg->ucBssIdx; + prTmpOffChnlTxReq->u8Cookie = prMgmtTxMsg->u8Cookie; + prTmpOffChnlTxReq->prMgmtTxMsdu = prMgmtTxMsg->prMgmtMsduInfo; + prTmpOffChnlTxReq->fgNoneCckRate = prMgmtTxMsg->fgNoneCckRate; + kalMemCopy(&prTmpOffChnlTxReq->rChannelInfo, + &prMgmtTxMsg->rChannelInfo, + sizeof(struct RF_CHANNEL_INFO)); + prTmpOffChnlTxReq->eChnlExt = prMgmtTxMsg->eChnlExt; + prTmpOffChnlTxReq->fgIsWaitRsp = prMgmtTxMsg->fgIsWaitRsp; + + p2pRoleAdjustChnlTime(prMgmtTxMsg, prTmpOffChnlTxReq); + + LINK_INSERT_TAIL(&prP2pMgmtTxReqInfo->rTxReqLink, + &prTmpOffChnlTxReq->rLinkEntry); + + *pprOffChnlTxReq = prTmpOffChnlTxReq; + + return TRUE; +} + +static void +p2pRoleAbortChlReqIfNeed(IN struct ADAPTER *prAdapter, + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + struct P2P_CHNL_REQ_INFO *prChnlReqInfo) +{ + if (prAdapter == NULL || prP2pRoleFsmInfo == NULL || + prChnlReqInfo == NULL) + return; + + /* Cancel ongoing channel request whose type is not offchannel-tx*/ + if (prP2pRoleFsmInfo->eCurrentState != P2P_ROLE_STATE_REQING_CHANNEL || + prChnlReqInfo->eChnlReqType == CH_REQ_TYPE_OFFCHNL_TX) + return; + + p2pRoleFsmRunEventAbort(prAdapter, prP2pRoleFsmInfo); +} + +static void +p2pRoleHandleOffchnlTxReq(IN struct ADAPTER *prAdapter, + IN struct MSG_MGMT_TX_REQUEST *prMgmtTxMsg) +{ + struct BSS_INFO *prP2pRoleBssInfo = (struct BSS_INFO *) NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct P2P_MGMT_TX_REQ_INFO *prP2pMgmtTxReqInfo = + (struct P2P_MGMT_TX_REQ_INFO *) NULL; + struct P2P_OFF_CHNL_TX_REQ_INFO *prOffChnlTxReq = + (struct P2P_OFF_CHNL_TX_REQ_INFO *) NULL; + struct P2P_CHNL_REQ_INFO *prChnlReqInfo = + (struct P2P_CHNL_REQ_INFO *) NULL; + + if (prAdapter == NULL || prMgmtTxMsg == NULL) + return; + + prP2pRoleBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prMgmtTxMsg->ucBssIdx); + prP2pRoleFsmInfo = prP2pRoleBssInfo != NULL ? + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pRoleBssInfo->u4PrivateData) : NULL; + + if (prP2pRoleFsmInfo == NULL) + return; + + prP2pMgmtTxReqInfo = &(prP2pRoleFsmInfo->rMgmtTxInfo); + prChnlReqInfo = &(prP2pRoleFsmInfo->rChnlReqInfo); + + if (prP2pMgmtTxReqInfo == NULL || prChnlReqInfo == NULL) + + p2pRoleAbortChlReqIfNeed(prAdapter, prP2pRoleFsmInfo, prChnlReqInfo); + + if (p2pRoleAddTxReq2Queue(prAdapter, prP2pMgmtTxReqInfo, + prMgmtTxMsg, &prOffChnlTxReq) == FALSE) + goto error; + + switch (prP2pRoleFsmInfo->eCurrentState) { + case P2P_ROLE_STATE_IDLE: + p2pRoleChnlReqByOffChnl(prAdapter, prP2pRoleFsmInfo, + prOffChnlTxReq); + break; + case P2P_ROLE_STATE_REQING_CHANNEL: + if (prChnlReqInfo->eChnlReqType != CH_REQ_TYPE_OFFCHNL_TX) { + DBGLOG(P2P, WARN, + "channel already requested by others\n"); + goto error; + } + break; + case P2P_ROLE_STATE_OFF_CHNL_TX: + if (p2pFuncCheckOnRocChnl(&(prMgmtTxMsg->rChannelInfo), + prChnlReqInfo) && + prP2pMgmtTxReqInfo->rTxReqLink.u4NumElem == 1) { + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_OFF_CHNL_TX); + } else { + log_dbg(P2P, INFO, "tx ch: %d, current ch: %d, requested: %d, tx link num: %d", + prMgmtTxMsg->rChannelInfo.ucChannelNum, + prChnlReqInfo->ucReqChnlNum, + prChnlReqInfo->fgIsChannelRequested, + prP2pMgmtTxReqInfo->rTxReqLink.u4NumElem); + } + break; + default: + DBGLOG(P2P, WARN, "Unknown state (%s) for offchannel-tx.\n", + p2pRoleFsmGetFsmState( + prP2pRoleFsmInfo->eCurrentState)); + goto error; + } + + return; + +error: + LINK_REMOVE_KNOWN_ENTRY( + &(prP2pMgmtTxReqInfo->rTxReqLink), + &prOffChnlTxReq->rLinkEntry); + cnmMgtPktFree(prAdapter, prOffChnlTxReq->prMgmtTxMsdu); + cnmMemFree(prAdapter, prOffChnlTxReq); +} /* p2pRoleHandleOffchnlTxReq */ + +void p2pRoleFsmRunEventMgmtTx(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct BSS_INFO *prP2pRoleBssInfo = (struct BSS_INFO *) NULL; + struct MSG_MGMT_TX_REQUEST *prMgmtTxMsg = + (struct MSG_MGMT_TX_REQUEST *) NULL; + u_int8_t fgNeedOffchnlTx; + + if (prAdapter == NULL || prMsgHdr == NULL) + goto error; + + prMgmtTxMsg = (struct MSG_MGMT_TX_REQUEST *) prMsgHdr; + prP2pRoleBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prMgmtTxMsg->ucBssIdx); + + fgNeedOffchnlTx = p2pRoleNeedOffchnlTx(prAdapter, prP2pRoleBssInfo, + prMgmtTxMsg); + DBGLOG(P2P, INFO, "fgNeedOffchnlTx: %d\n", fgNeedOffchnlTx); + + if (!fgNeedOffchnlTx) + p2pFuncTxMgmtFrame(prAdapter, + prMgmtTxMsg->ucBssIdx, + prMgmtTxMsg->prMgmtMsduInfo, + prMgmtTxMsg->fgNoneCckRate); + else + p2pRoleHandleOffchnlTxReq(prAdapter, prMgmtTxMsg); + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pRoleFsmRunEventMgmtTx */ + +void p2pRoleFsmRunEventTxCancelWait(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct BSS_INFO *prP2pRoleBssInfo = (struct BSS_INFO *) NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct P2P_MGMT_TX_REQ_INFO *prP2pMgmtTxInfo = + (struct P2P_MGMT_TX_REQ_INFO *) NULL; + struct MSG_CANCEL_TX_WAIT_REQUEST *prCancelTxWaitMsg = + (struct MSG_CANCEL_TX_WAIT_REQUEST *) NULL; + struct P2P_OFF_CHNL_TX_REQ_INFO *prOffChnlTxPkt = + (struct P2P_OFF_CHNL_TX_REQ_INFO *) NULL; + u_int8_t fgIsCookieFound = FALSE; + + if (prAdapter == NULL || prMsgHdr == NULL) + goto exit; + + prCancelTxWaitMsg = (struct MSG_CANCEL_TX_WAIT_REQUEST *) prMsgHdr; + prP2pRoleBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prCancelTxWaitMsg->ucBssIdx); + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pRoleBssInfo->u4PrivateData); + prP2pMgmtTxInfo = prP2pRoleFsmInfo != NULL ? + &(prP2pRoleFsmInfo->rMgmtTxInfo) : NULL; + + if (prCancelTxWaitMsg == NULL || prP2pRoleFsmInfo == NULL || + prP2pMgmtTxInfo == NULL || prP2pMgmtTxInfo == NULL) + goto exit; + + LINK_FOR_EACH_ENTRY(prOffChnlTxPkt, + &(prP2pMgmtTxInfo->rTxReqLink), + rLinkEntry, + struct P2P_OFF_CHNL_TX_REQ_INFO) { + if (!prOffChnlTxPkt) + break; + if (prOffChnlTxPkt->u8Cookie == prCancelTxWaitMsg->u8Cookie) { + fgIsCookieFound = TRUE; + break; + } + } + + if (fgIsCookieFound || prP2pRoleFsmInfo->eCurrentState == + P2P_ROLE_STATE_OFF_CHNL_TX) { + p2pFunClearAllTxReq(prAdapter, + &(prP2pRoleFsmInfo->rMgmtTxInfo)); + p2pRoleFsmRunEventAbort(prAdapter, prP2pRoleFsmInfo); + } + +exit: + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pRoleFsmRunEventTxCancelWait */ + +static void initAcsParams(IN struct ADAPTER *prAdapter, + IN struct MSG_P2P_ACS_REQUEST *prMsgAcsRequest, + IN struct P2P_ACS_REQ_INFO *prAcsReqInfo) { + struct RF_CHANNEL_INFO *prRfChannelInfo; + uint8_t i; + + if (!prAdapter || !prMsgAcsRequest || !prAcsReqInfo) + return; + + kalMemSet(prAcsReqInfo, 0, sizeof(struct P2P_ACS_REQ_INFO)); + prAcsReqInfo->fgIsProcessing = TRUE; + prAcsReqInfo->ucRoleIdx = prMsgAcsRequest->ucRoleIdx; + prAcsReqInfo->fgIsHtEnable = prMsgAcsRequest->fgIsHtEnable; + prAcsReqInfo->fgIsHt40Enable = prMsgAcsRequest->fgIsHt40Enable; + prAcsReqInfo->fgIsVhtEnable = prMsgAcsRequest->fgIsVhtEnable; + prAcsReqInfo->eChnlBw = prMsgAcsRequest->eChnlBw; + prAcsReqInfo->eHwMode = prMsgAcsRequest->eHwMode; + + if (prAcsReqInfo->eChnlBw == MAX_BW_UNKNOWN) { + if (prAcsReqInfo->fgIsHtEnable && + prAcsReqInfo->fgIsHt40Enable) { + prAcsReqInfo->eChnlBw = MAX_BW_40MHZ; + } else { + prAcsReqInfo->eChnlBw = MAX_BW_20MHZ; + } + } + if (!prAcsReqInfo->fgIsVhtEnable && + (prAcsReqInfo->eChnlBw == MAX_BW_80MHZ || + prAcsReqInfo->eChnlBw == MAX_BW_160MHZ)) { + if (prAcsReqInfo->fgIsHtEnable && + prAcsReqInfo->fgIsHt40Enable) { + prAcsReqInfo->eChnlBw = MAX_BW_40MHZ; + } else { + prAcsReqInfo->eChnlBw = MAX_BW_20MHZ; + } + } + + DBGLOG(P2P, INFO, "idx=%d, ht=%d, ht40=%d, vht=%d, bw=%d, m=%d, c=%d", + prMsgAcsRequest->ucRoleIdx, + prMsgAcsRequest->fgIsHtEnable, + prMsgAcsRequest->fgIsHt40Enable, + prMsgAcsRequest->fgIsVhtEnable, + prMsgAcsRequest->eChnlBw, + prMsgAcsRequest->eHwMode, + prMsgAcsRequest->u4NumChannel); + if (prMsgAcsRequest->u4NumChannel) { + for (i = 0; i < prMsgAcsRequest->u4NumChannel; i++) { + prRfChannelInfo = + &(prMsgAcsRequest->arChannelListInfo[i]); + DBGLOG(REQ, INFO, "[%d] band=%d, ch=%d\n", i, + prRfChannelInfo->eBand, + prRfChannelInfo->ucChannelNum); + prRfChannelInfo++; + } + } +} + +static void indicateAcsResultByAisCh(IN struct ADAPTER *prAdapter, + IN struct P2P_ACS_REQ_INFO *prAcsReqInfo, + IN struct BSS_INFO *prAisBssInfo) +{ + if (!prAdapter || !prAcsReqInfo) + return; + + prAcsReqInfo->ucPrimaryCh = prAisBssInfo->ucPrimaryChannel; + if (prAisBssInfo->ucVhtChannelWidth == VHT_OP_CHANNEL_WIDTH_20_40) { + if (prAisBssInfo->eBssSCO == CHNL_EXT_SCN) + prAcsReqInfo->eChnlBw = MAX_BW_20MHZ; + else + prAcsReqInfo->eChnlBw = MAX_BW_40MHZ; + } else if (prAisBssInfo->ucVhtChannelWidth == VHT_OP_CHANNEL_WIDTH_80) { + prAcsReqInfo->eChnlBw = MAX_BW_80MHZ; + } else if (prAisBssInfo->ucVhtChannelWidth == + VHT_OP_CHANNEL_WIDTH_160) { + prAcsReqInfo->eChnlBw = MAX_BW_160MHZ; + } else if (prAisBssInfo->ucVhtChannelWidth == + VHT_OP_CHANNEL_WIDTH_80P80) { + prAcsReqInfo->eChnlBw = MAX_BW_80_80_MHZ; + } else { + prAcsReqInfo->eChnlBw = MAX_BW_20MHZ; + } + p2pFunIndicateAcsResult(prAdapter->prGlueInfo, + prAcsReqInfo); +} + +static void trimAcsScanList(IN struct ADAPTER *prAdapter, + IN struct MSG_P2P_ACS_REQUEST *prMsgAcsRequest, + IN struct P2P_ACS_REQ_INFO *prAcsReqInfo, + IN enum ENUM_BAND eDesiredBand) +{ + uint32_t u4NumChannel = 0; + uint8_t i; + struct RF_CHANNEL_INFO *prRfChannelInfo1; + struct RF_CHANNEL_INFO *prRfChannelInfo2; + + if (!prAdapter || !prAcsReqInfo) + return; + + for (i = 0; i < prMsgAcsRequest->u4NumChannel; i++) { + prRfChannelInfo1 = + &(prMsgAcsRequest->arChannelListInfo[i]); + if (eDesiredBand != prRfChannelInfo1->eBand) + continue; + DBGLOG(P2P, INFO, "acs trim scan list, [%d]=%d %d\n", + u4NumChannel, + prRfChannelInfo1->eBand, + prRfChannelInfo1->ucChannelNum); + prRfChannelInfo2 = &(prMsgAcsRequest->arChannelListInfo[ + u4NumChannel]); + prRfChannelInfo2->eBand = prRfChannelInfo1->eBand; + prRfChannelInfo2->u4CenterFreq1 = + prRfChannelInfo1->u4CenterFreq1; + prRfChannelInfo2->u4CenterFreq2 = + prRfChannelInfo1->u4CenterFreq2; + prRfChannelInfo2->u2PriChnlFreq = + prRfChannelInfo1->u2PriChnlFreq; + prRfChannelInfo2->ucChnlBw = prRfChannelInfo1->ucChnlBw; + prRfChannelInfo2->ucChannelNum = + prRfChannelInfo1->ucChannelNum; + u4NumChannel++; + prRfChannelInfo1++; + } + prMsgAcsRequest->u4NumChannel = u4NumChannel; +} + +static void initAcsChnlMask(IN struct ADAPTER *prAdapter, + IN struct MSG_P2P_ACS_REQUEST *prMsgAcsRequest, + IN struct P2P_ACS_REQ_INFO *prAcsReqInfo) +{ + uint8_t i; + struct RF_CHANNEL_INFO *prRfChannelInfo; + + prAcsReqInfo->u4LteSafeChnMask_2G = 0; + prAcsReqInfo->u4LteSafeChnMask_5G_1 = 0; + prAcsReqInfo->u4LteSafeChnMask_5G_2 = 0; + + for (i = 0; i < prMsgAcsRequest->u4NumChannel; i++) { + prRfChannelInfo = &(prMsgAcsRequest->arChannelListInfo[i]); + if (prRfChannelInfo->ucChannelNum <= 14) { + prAcsReqInfo->u4LteSafeChnMask_2G |= BIT( + prRfChannelInfo->ucChannelNum); + } else if (prRfChannelInfo->ucChannelNum >= 36 && + prRfChannelInfo->ucChannelNum <= 144) { + prAcsReqInfo->u4LteSafeChnMask_5G_1 |= BIT( + (prRfChannelInfo->ucChannelNum - 36) / 4); + } else if (prRfChannelInfo->ucChannelNum >= 149 && + prRfChannelInfo->ucChannelNum <= 181) { + prAcsReqInfo->u4LteSafeChnMask_5G_2 |= BIT( + (prRfChannelInfo->ucChannelNum - 149) / 4); + } + } + + DBGLOG(P2P, INFO, "acs chnl mask=[0x%08x][0x%08x][0x%08x]\n", + prAcsReqInfo->u4LteSafeChnMask_2G, + prAcsReqInfo->u4LteSafeChnMask_5G_1, + prAcsReqInfo->u4LteSafeChnMask_5G_2); +} + +void p2pRoleFsmRunEventAcs(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_P2P_ACS_REQUEST *prMsgAcsRequest; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo; + struct MSG_P2P_SCAN_REQUEST *prP2pScanReqMsg; + struct P2P_ACS_REQ_INFO *prAcsReqInfo; + uint32_t u4MsgSize = 0; + + if (!prAdapter || !prMsgHdr) + return; + + prMsgAcsRequest = (struct MSG_P2P_ACS_REQUEST *) prMsgHdr; + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prMsgAcsRequest->ucRoleIdx); + prAcsReqInfo = &prP2pRoleFsmInfo->rAcsReqInfo; + + p2pRoleFsmAbortCurrentAcsReq(prAdapter, prMsgAcsRequest); + + initAcsParams(prAdapter, prMsgAcsRequest, prAcsReqInfo); + +#if CFG_HOTSPOT_SUPPORT_FORCE_ACS_SCC + if (prAdapter->rWifiVar.eDbdcMode == ENUM_DBDC_MODE_DISABLED) { + struct BSS_INFO *prAisBssInfo; + + DBGLOG(P2P, INFO, "Report SCC channel\n"); + + prAisBssInfo = aisGetConnectedBssInfo(prAdapter); + if (prAisBssInfo) { + /* Force SCC, indicate channel directly */ + indicateAcsResultByAisCh(prAdapter, prAcsReqInfo, + prAisBssInfo); + goto exit; + } + } +#endif + + if (prAcsReqInfo->eHwMode == P2P_VENDOR_ACS_HW_MODE_11ANY) { + struct BSS_INFO *prAisBssInfo; + + prAisBssInfo = aisGetAisBssInfo(prAdapter, + AIS_DEFAULT_INDEX); + if (prAisBssInfo->eConnectionState == MEDIA_STATE_CONNECTED) { + /* Force SCC, indicate channel directly */ + indicateAcsResultByAisCh(prAdapter, prAcsReqInfo, + prAisBssInfo); + goto exit; + } else if (prAdapter->fgEnable5GBand) { + /* Prefer 5G band first */ + trimAcsScanList(prAdapter, prMsgAcsRequest, + prAcsReqInfo, BAND_5G); + prAcsReqInfo->eHwMode = P2P_VENDOR_ACS_HW_MODE_11A; + } else { + trimAcsScanList(prAdapter, prMsgAcsRequest, + prAcsReqInfo, BAND_2G4); + prAcsReqInfo->eHwMode = P2P_VENDOR_ACS_HW_MODE_11G; + } + } + + initAcsChnlMask(prAdapter, prMsgAcsRequest, prAcsReqInfo); + + u4MsgSize = sizeof(struct MSG_P2P_SCAN_REQUEST) + ( + prMsgAcsRequest->u4NumChannel * + sizeof(struct RF_CHANNEL_INFO)); + + prP2pScanReqMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, u4MsgSize); + if (prP2pScanReqMsg == NULL) { + DBGLOG(P2P, ERROR, "alloc scan req. fail\n"); + return; + } + kalMemSet(prP2pScanReqMsg, 0, u4MsgSize); + prP2pScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prP2pScanReqMsg->ucBssIdx = prP2pRoleFsmInfo->ucBssIndex; + prP2pScanReqMsg->i4SsidNum = 0; + prP2pScanReqMsg->u4NumChannel = prMsgAcsRequest->u4NumChannel; + prP2pScanReqMsg->u4IELen = 0; + prP2pScanReqMsg->eScanReason = SCAN_REASON_ACS; + kalMemCopy(&(prP2pScanReqMsg->arChannelListInfo), + &(prMsgAcsRequest->arChannelListInfo), + (prMsgAcsRequest->u4NumChannel * + sizeof(struct RF_CHANNEL_INFO))); + p2pRoleFsmRunEventScanRequest(prAdapter, + (struct MSG_HDR *) prP2pScanReqMsg); + +exit: + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} + +static u_int8_t +p2pRoleFsmIsAcsProcessing(IN struct ADAPTER *prAdapter, + uint8_t ucRoleIdx) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo; + struct P2P_ACS_REQ_INFO *prAcsReqInfo; + + if (!prAdapter) + return FALSE; + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + ucRoleIdx); + if (!prP2pRoleFsmInfo) + return FALSE; + + prAcsReqInfo = &prP2pRoleFsmInfo->rAcsReqInfo; + if (!prAcsReqInfo) + return FALSE; + + return prAcsReqInfo->fgIsProcessing; +} + +static void +p2pRoleFsmAbortCurrentAcsReq(IN struct ADAPTER *prAdapter, + IN struct MSG_P2P_ACS_REQUEST *prMsgAcsRequest) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = NULL; + struct P2P_SCAN_REQ_INFO *prScanReqInfo = NULL; + + if (!prAdapter || !prMsgAcsRequest) + return; + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prMsgAcsRequest->ucRoleIdx); + prScanReqInfo = &(prP2pRoleFsmInfo->rScanReqInfo); + + if (!p2pRoleFsmIsAcsProcessing(prAdapter, prMsgAcsRequest->ucRoleIdx)) + return; + + if (prP2pRoleFsmInfo->eCurrentState == P2P_ROLE_STATE_SCAN && + prScanReqInfo->eScanReason == SCAN_REASON_ACS) { + DBGLOG(P2P, INFO, "Cancel current ACS scan.\n"); + p2pRoleFsmRunEventAbort(prAdapter, prP2pRoleFsmInfo); + } +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_role_state.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_role_state.c new file mode 100644 index 0000000000000..073a0a93d7da9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_role_state.c @@ -0,0 +1,744 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#include "precomp.h" + +void +p2pRoleStateInit_IDLE(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN struct BSS_INFO *prP2pBssInfo) +{ + +#if CFG_HOTSPOT_SUPPORT_ADJUST_SCC + if (p2pFuncIsAPMode( + prAdapter->rWifiVar.prP2PConnSettings + [prP2pRoleFsmInfo->ucRoleIndex])) { + struct GL_P2P_INFO *prP2PInfo = + prAdapter->prGlueInfo->prP2PInfo[ + prP2pRoleFsmInfo->ucRoleIndex]; + struct P2P_CHNL_REQ_INFO *prP2pChnlReqInfo = + &(prP2pRoleFsmInfo->rChnlReqInfo); + + prP2PInfo->eChnlSwitchPolicy = CHNL_SWITCH_POLICY_NONE; + p2pFuncSwitchSapChannel(prAdapter); + if (prP2PInfo->eChnlSwitchPolicy != + CHNL_SWITCH_POLICY_NONE) { + if (prP2pChnlReqInfo->fgIsChannelRequested) { + p2pFuncReleaseCh(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + prP2pChnlReqInfo); + } + return; + } + } +#endif + + cnmTimerStartTimer(prAdapter, + &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer), + P2P_AP_CHNL_HOLD_TIME_MS); +} /* p2pRoleStateInit_IDLE */ + +void +p2pRoleStateAbort_IDLE(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN struct P2P_CHNL_REQ_INFO *prP2pChnlReqInfo) +{ + + /* AP mode channel hold time. */ + if (prP2pChnlReqInfo->fgIsChannelRequested) + p2pFuncReleaseCh(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + prP2pChnlReqInfo); + + DBGLOG(P2P, TRACE, "stop role idle timer.\n"); + cnmTimerStopTimer(prAdapter, + &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer)); +} /* p2pRoleStateAbort_IDLE */ + +void p2pRoleStateInit_SCAN(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct P2P_SCAN_REQ_INFO *prScanReqInfo) +{ + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) NULL; + struct P2P_SCAN_REQ_INFO *prDevScanReqInfo = NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prScanReqInfo != NULL)); + + prScanReqInfo->fgIsScanRequest = TRUE; + if (prScanReqInfo->u4BufLength == 0) { + /* If we let u4BufLength be zero, + * scan module will copy the IE buf from ScanParam + * Sometime this content is from AIS, + * so we need copy it from P2Pdev + */ + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + if (prP2pDevFsmInfo) { + prDevScanReqInfo = + &(prP2pDevFsmInfo->rScanReqInfo); + if (prDevScanReqInfo->u4BufLength != 0) { + /* IE Buffer */ + kalMemCopy(prScanReqInfo->aucIEBuf, + prDevScanReqInfo->aucIEBuf, + prDevScanReqInfo->u4BufLength); + prScanReqInfo->u4BufLength = + prDevScanReqInfo->u4BufLength; + DBGLOG(P2P, TRACE, + "p2pRoleStateInit_SCAN Copy p2p IE from P2P dev\n"); + } + } else + DBGLOG(P2P, ERROR, "No prP2pDevFsmInfo ptr\n"); + } + p2pFuncRequestScan(prAdapter, ucBssIndex, prScanReqInfo); + } while (FALSE); +} /* p2pRoleStateInit_SCAN */ + +void p2pRoleStateAbort_SCAN(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo) +{ + struct P2P_SCAN_REQ_INFO *prScanInfo = + (struct P2P_SCAN_REQ_INFO *) NULL; + + do { + prScanInfo = &prP2pRoleFsmInfo->rScanReqInfo; + + p2pFuncCancelScan(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + prScanInfo); + + /* TODO: May need indicate port index to upper layer. */ + kalP2PIndicateScanDone(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, + prScanInfo->fgIsAbort); + + } while (FALSE); +} /* p2pRoleStateAbort_SCAN */ + +void +p2pRoleStateInit_REQING_CHANNEL(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo) +{ + + do { + ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL)); + + p2pFuncAcquireCh(prAdapter, ucBssIdx, prChnlReqInfo); + + } while (FALSE); +} /* p2pRoleStateInit_REQING_CHANNEL */ + +void +p2pRoleStateAbort_REQING_CHANNEL(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pRoleBssInfo, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN enum ENUM_P2P_ROLE_STATE eNextState) +{ + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prP2pRoleBssInfo != NULL) + && (prP2pRoleFsmInfo != NULL)); + + if (eNextState == P2P_ROLE_STATE_IDLE) { + if (prP2pRoleBssInfo->eIntendOPMode + == OP_MODE_ACCESS_POINT) { + struct P2P_CHNL_REQ_INFO *prP2pChnlReqInfo = + &(prP2pRoleFsmInfo->rChnlReqInfo); + + if (IS_NET_PWR_STATE_ACTIVE(prAdapter, + prP2pRoleFsmInfo->ucBssIndex)) + p2pFuncStartGO(prAdapter, + prP2pRoleBssInfo, + &(prP2pRoleFsmInfo->rConnReqInfo), + &(prP2pRoleFsmInfo->rChnlReqInfo)); + else if (prP2pChnlReqInfo->fgIsChannelRequested) + p2pFuncReleaseCh(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + prP2pChnlReqInfo); + } else { + p2pFuncReleaseCh(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rChnlReqInfo)); + } + } + } while (FALSE); +} /* p2pRoleStateAbort_REQING_CHANNEL */ + +void +p2pRoleStateInit_AP_CHNL_DETECTION(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct P2P_SCAN_REQ_INFO *prScanReqInfo, + IN struct P2P_CONNECTION_REQ_INFO *prConnReqInfo) +{ + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo = + (struct P2P_SPECIFIC_BSS_INFO *) NULL; + struct BSS_INFO *prBssInfo = NULL; + uint8_t ucPreferedChnl = 0; + enum ENUM_BAND eBand = BAND_NULL; + enum ENUM_CHNL_EXT eSco = CHNL_EXT_SCN; + + do { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + ASSERT_BREAK((prAdapter != NULL) && (prScanReqInfo != NULL) + && (prConnReqInfo != NULL) && (prBssInfo != NULL)); + + prP2pSpecificBssInfo = + prAdapter->rWifiVar + .prP2pSpecificBssInfo[prBssInfo->u4PrivateData]; + + if ((cnmPreferredChannel(prAdapter, + &eBand, + &ucPreferedChnl, + &eSco) == FALSE) + && (prConnReqInfo->rChannelInfo.ucChannelNum == 0)) { + + /* Sparse channel detection. */ + prP2pSpecificBssInfo->ucPreferredChannel = 0; + + prScanReqInfo->eScanType = SCAN_TYPE_PASSIVE_SCAN; + /* 50ms for passive channel load detection */ + prScanReqInfo->u2PassiveDewellTime = 50; + } else { + /* Active scan to shorten scan time. */ + prScanReqInfo->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prScanReqInfo->u2PassiveDewellTime = 0; + + if (prConnReqInfo->rChannelInfo.ucChannelNum != 0) { + prP2pSpecificBssInfo->ucPreferredChannel = + prConnReqInfo->rChannelInfo + .ucChannelNum; + prP2pSpecificBssInfo->eRfBand = + prConnReqInfo->rChannelInfo + .eBand; + prP2pSpecificBssInfo->eRfSco = CHNL_EXT_SCN; + } else { + prP2pSpecificBssInfo->ucPreferredChannel = + ucPreferedChnl; + prP2pSpecificBssInfo->eRfBand = eBand; + prP2pSpecificBssInfo->eRfSco = eSco; + } + + } + + /* TODO: See if channel set to include 5G or only 2.4G */ + prScanReqInfo->eChannelSet = SCAN_CHANNEL_2G4; + + prScanReqInfo->fgIsAbort = TRUE; + prScanReqInfo->fgIsScanRequest = TRUE; + prScanReqInfo->ucNumChannelList = 0; + prScanReqInfo->u4BufLength = 0; + prScanReqInfo->ucSsidNum = 1; + prScanReqInfo->arSsidStruct[0].ucSsidLen = 0; + + p2pFuncRequestScan(prAdapter, ucBssIndex, prScanReqInfo); + + } while (FALSE); + + return; + +} /* p2pRoleStateInit_AP_CHNL_DETECTION */ + +void +p2pRoleStateAbort_AP_CHNL_DETECTION(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct P2P_CONNECTION_REQ_INFO *prP2pConnReqInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN struct P2P_SCAN_REQ_INFO *prP2pScanReqInfo, + IN enum ENUM_P2P_ROLE_STATE eNextState) +{ + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo = + (struct P2P_SPECIFIC_BSS_INFO *) NULL; + struct BSS_INFO *prBssInfo = NULL; + + do { + if (eNextState == P2P_ROLE_STATE_REQING_CHANNEL) { + prBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + prP2pSpecificBssInfo = + prAdapter->rWifiVar + .prP2pSpecificBssInfo[prBssInfo->u4PrivateData]; + + if (prP2pSpecificBssInfo->ucPreferredChannel == 0) { + if (scnQuerySparseChannel(prAdapter, + &prP2pSpecificBssInfo + ->eRfBand, + &prP2pSpecificBssInfo + ->ucPreferredChannel)) { + prP2pSpecificBssInfo->eRfSco = + CHNL_EXT_SCN; + } else { + DBGLOG(P2P, ERROR, + "Sparse Channel Error, use default settings\n"); + /* Sparse channel false. */ + prP2pSpecificBssInfo->ucPreferredChannel + = P2P_DEFAULT_LISTEN_CHANNEL; + prP2pSpecificBssInfo->eRfBand + = BAND_2G4; + prP2pSpecificBssInfo->eRfSco + = CHNL_EXT_SCN; + } + } + + prChnlReqInfo->u8Cookie = 0; + prChnlReqInfo->ucReqChnlNum = + prP2pSpecificBssInfo->ucPreferredChannel; + prChnlReqInfo->eBand = prP2pSpecificBssInfo->eRfBand; + prChnlReqInfo->eChnlSco = prP2pSpecificBssInfo->eRfSco; + prChnlReqInfo->u4MaxInterval = P2P_AP_CHNL_HOLD_TIME_MS; + prChnlReqInfo->eChnlReqType = CH_REQ_TYPE_GO_START_BSS; + + prChnlReqInfo->eChannelWidth = CW_20_40MHZ; + prChnlReqInfo->ucCenterFreqS1 = 0; + prChnlReqInfo->ucCenterFreqS2 = 0; + + } else { + p2pFuncCancelScan(prAdapter, + ucBssIndex, + prP2pScanReqInfo); + } + } while (FALSE); +} + +void +p2pRoleStateInit_GC_JOIN(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo) +{ + /* P_MSG_JOIN_REQ_T prJoinReqMsg = (P_MSG_JOIN_REQ_T)NULL; */ + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prP2pRoleFsmInfo != NULL) + && (prChnlReqInfo != NULL)); + + prP2pBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, + prP2pRoleFsmInfo->ucBssIndex); + + /* Setup a join timer. */ + DBGLOG(P2P, TRACE, "Start a join init timer\n"); + cnmTimerStartTimer(prAdapter, + &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer), + (prChnlReqInfo->u4MaxInterval + - AIS_JOIN_CH_GRANT_THRESHOLD)); + + p2pFuncGCJoin(prAdapter, + prP2pBssInfo, + &(prP2pRoleFsmInfo->rJoinInfo)); + + } while (FALSE); +} /* p2pRoleStateInit_GC_JOIN */ + +void +p2pRoleStateAbort_GC_JOIN(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN struct P2P_JOIN_INFO *prJoinInfo, + IN enum ENUM_P2P_ROLE_STATE eNextState) +{ + do { + + if (prJoinInfo->fgIsJoinComplete == FALSE) { + struct MSG_SAA_FSM_ABORT *prJoinAbortMsg = + (struct MSG_SAA_FSM_ABORT *) NULL; + struct BSS_DESC *prBssDesc = + (struct BSS_DESC *) NULL; + + prJoinAbortMsg = + (struct MSG_SAA_FSM_ABORT *) cnmMemAlloc( + prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_SAA_FSM_ABORT)); + 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; + + /* Reset the flag to clear target BSS state */ + prBssDesc = prJoinInfo->prTargetBssDesc; + if (prBssDesc != NULL) { + prBssDesc->fgIsConnecting = FALSE; + } + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prJoinAbortMsg, + MSG_SEND_METHOD_BUF); + + } + + /* Stop Join Timer. */ + cnmTimerStopTimer(prAdapter, + &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer)); + + /* Release channel requested. */ + p2pFuncReleaseCh(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rChnlReqInfo)); + + } while (FALSE); +} + +#if (CFG_SUPPORT_DFS_MASTER == 1) +void +p2pRoleStateInit_DFS_CAC(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo) +{ + + do { + ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL)); + + p2pFuncAcquireCh(prAdapter, ucBssIdx, prChnlReqInfo); + } while (FALSE); +} /* p2pRoleStateInit_DFS_CAC */ + +void +p2pRoleStateAbort_DFS_CAC(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pRoleBssInfo, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN enum ENUM_P2P_ROLE_STATE eNextState) +{ + do { + cnmTimerStopTimer(prAdapter, + &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer)); + + p2pFuncReleaseCh(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rChnlReqInfo)); + + } while (FALSE); +} /* p2pRoleStateAbort_DFS_CAC */ + +void +p2pRoleStateInit_SWITCH_CHANNEL(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo) +{ + + do { + ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL)); + + p2pFuncAcquireCh(prAdapter, ucBssIdx, prChnlReqInfo); + } while (FALSE); +} /* p2pRoleStateInit_SWITCH_CHANNEL */ + +void +p2pRoleStateAbort_SWITCH_CHANNEL(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pRoleBssInfo, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN enum ENUM_P2P_ROLE_STATE eNextState) +{ + do { + p2pFuncReleaseCh(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rChnlReqInfo)); + } while (FALSE); +} /* p2pRoleStateAbort_SWITCH_CHANNEL */ +#endif + +void +p2pRoleStatePrepare_To_REQING_CHANNEL_STATE(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct P2P_CONNECTION_REQ_INFO *prConnReqInfo, + OUT struct P2P_CHNL_REQ_INFO *prChnlReqInfo) +{ + enum ENUM_BAND eBandBackup; + uint8_t ucChannelBackup; + enum ENUM_CHNL_EXT eSCOBackup; + uint8_t ucRfBw; + + do { + /* P2P BSS info is for temporarily use + * Request a 80MHz channel before starting AP/GO + * to prevent from STA/GC connected too early (before CH abort) + * Therefore, STA/GC Rate will drop during DHCP exchange packets + */ + + /* Previous issue: + * Always request 20MHz channel, + * but carry 40MHz HT cap/80MHz VHT cap, + * then if GC/STA connected before CH abort, + * GO/AP cannot listen to GC/STA's 40MHz/80MHz packets. + */ + + eBandBackup = prBssInfo->eBand; + ucChannelBackup = prBssInfo->ucPrimaryChannel; + eSCOBackup = prBssInfo->eBssSCO; + + prBssInfo->ucPrimaryChannel = + prConnReqInfo->rChannelInfo.ucChannelNum; + prBssInfo->eBand = prConnReqInfo->rChannelInfo.eBand; + + prBssInfo->eBssSCO = rlmGetScoForAP(prAdapter, prBssInfo); + + ASSERT_BREAK((prAdapter != NULL) + && (prConnReqInfo != NULL) + && (prChnlReqInfo != NULL)); + + prChnlReqInfo->u8Cookie = 0; + prChnlReqInfo->ucReqChnlNum = + prConnReqInfo->rChannelInfo.ucChannelNum; + prChnlReqInfo->eBand = prConnReqInfo->rChannelInfo.eBand; + prChnlReqInfo->eChnlSco = prBssInfo->eBssSCO; + prChnlReqInfo->u4MaxInterval = P2P_AP_CHNL_HOLD_TIME_MS; + prChnlReqInfo->eChnlReqType = CH_REQ_TYPE_GO_START_BSS; + + if (prBssInfo->eBand == BAND_5G) { + /* Decide RF BW by own OP BW */ + ucRfBw = cnmGetDbdcBwCapability(prAdapter, + prBssInfo->ucBssIndex); + /* Revise to VHT OP BW */ + ucRfBw = rlmGetVhtOpBwByBssOpBw(ucRfBw); + prChnlReqInfo->eChannelWidth = ucRfBw; + } else + prChnlReqInfo->eChannelWidth = CW_20_40MHZ; + + /* TODO: BW80+80 support */ + prChnlReqInfo->ucCenterFreqS1 = + nicGetVhtS1(prBssInfo->ucPrimaryChannel, + prChnlReqInfo->eChannelWidth); + prChnlReqInfo->ucCenterFreqS2 = 0; + + /* If the S1 is invalid, force to change bandwidth */ + if ((prBssInfo->eBand == BAND_5G) && + (prChnlReqInfo->ucCenterFreqS1 == 0)) + prChnlReqInfo->eChannelWidth = + VHT_OP_CHANNEL_WIDTH_20_40; + + DBGLOG(P2P, TRACE, + "p2pRoleStatePrepare_To_REQING_CHANNEL_STATE\n"); + + /* Reset */ + prBssInfo->ucPrimaryChannel = ucChannelBackup; + prBssInfo->eBand = eBandBackup; + prBssInfo->eBssSCO = eSCOBackup; + } while (FALSE); +} + +#if (CFG_SUPPORT_DFS_MASTER == 1) +void +p2pRoleStatePrepare_To_DFS_CAC_STATE(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN enum ENUM_CHANNEL_WIDTH rChannelWidth, + IN struct P2P_CONNECTION_REQ_INFO *prConnReqInfo, + OUT struct P2P_CHNL_REQ_INFO *prChnlReqInfo) +{ + enum ENUM_BAND eBandBackup; + uint8_t ucChannelBackup; + enum ENUM_CHNL_EXT eSCOBackup; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + + do { + + eBandBackup = prBssInfo->eBand; + ucChannelBackup = prBssInfo->ucPrimaryChannel; + eSCOBackup = prBssInfo->eBssSCO; + + prBssInfo->ucPrimaryChannel = + prConnReqInfo->rChannelInfo.ucChannelNum; + prBssInfo->eBand = prConnReqInfo->rChannelInfo.eBand; + + prBssInfo->eBssSCO = rlmGetScoForAP(prAdapter, prBssInfo); + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prBssInfo->u4PrivateData); + + ASSERT_BREAK((prAdapter != NULL) + && (prConnReqInfo != NULL) + && (prChnlReqInfo != NULL)); + + prChnlReqInfo->u8Cookie = 0; + prChnlReqInfo->ucReqChnlNum = + prConnReqInfo->rChannelInfo.ucChannelNum; + prChnlReqInfo->eBand = prConnReqInfo->rChannelInfo.eBand; + prChnlReqInfo->eChnlSco = prBssInfo->eBssSCO; + prChnlReqInfo->u4MaxInterval = + prAdapter->prGlueInfo + ->prP2PInfo[prP2pRoleFsmInfo->ucRoleIndex] + ->cac_time_ms; + prChnlReqInfo->eChnlReqType = CH_REQ_TYPE_DFS_CAC; + + prBssInfo->ucVhtChannelWidth = + cnmGetBssMaxBwToChnlBW(prAdapter, + prBssInfo->ucBssIndex); + prChnlReqInfo->eChannelWidth = prBssInfo->ucVhtChannelWidth; + + if (prChnlReqInfo->eChannelWidth + == VHT_OP_CHANNEL_WIDTH_80P80) { + /* TODO: BW80+80 support */ + log_dbg(RLM, WARN, "BW80+80 not support. Fallback to VHT_OP_CHANNEL_WIDTH_20_40\n"); + prChnlReqInfo->eChannelWidth = + VHT_OP_CHANNEL_WIDTH_20_40; + prChnlReqInfo->ucCenterFreqS1 = 0; + prChnlReqInfo->ucCenterFreqS2 = 0; + } else { + prChnlReqInfo->ucCenterFreqS1 = + rlmGetVhtS1ForAP(prAdapter, prBssInfo); + prChnlReqInfo->ucCenterFreqS2 = 0; + } + + DBGLOG(P2P, TRACE, + "p2pRoleStatePrepare_To_REQING_CHANNEL_STATE\n"); + + /* Reset */ + prBssInfo->ucPrimaryChannel = ucChannelBackup; + prBssInfo->eBand = eBandBackup; + prBssInfo->eBssSCO = eSCOBackup; + } while (FALSE); +} +#endif + +u_int8_t +p2pRoleStateInit_OFF_CHNL_TX(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN struct P2P_MGMT_TX_REQ_INFO *prP2pMgmtTxInfo, + OUT enum ENUM_P2P_ROLE_STATE *peNextState) +{ + struct P2P_OFF_CHNL_TX_REQ_INFO *prOffChnlTxPkt = + (struct P2P_OFF_CHNL_TX_REQ_INFO *) NULL; + + if (prAdapter == NULL || prP2pMgmtTxInfo == NULL || peNextState == NULL) + return FALSE; + + if (LINK_IS_EMPTY(&(prP2pMgmtTxInfo->rTxReqLink))) { + p2pFuncReleaseCh(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + prChnlReqInfo); + /* Link is empty, return back to IDLE. */ + *peNextState = P2P_ROLE_STATE_IDLE; + return TRUE; + } + + prOffChnlTxPkt = + LINK_PEEK_HEAD(&(prP2pMgmtTxInfo->rTxReqLink), + struct P2P_OFF_CHNL_TX_REQ_INFO, + rLinkEntry); + + if (prOffChnlTxPkt == NULL) { + DBGLOG(P2P, ERROR, + "Fatal Error, Link not empty but get NULL pointer.\n"); + ASSERT(FALSE); + return FALSE; + } + + if (!p2pFuncCheckOnRocChnl(&(prOffChnlTxPkt->rChannelInfo), + prChnlReqInfo)) { + DBGLOG(P2P, WARN, + "req channel(%d) != TX channel(%d), request chnl again", + prChnlReqInfo->ucReqChnlNum, + prOffChnlTxPkt->rChannelInfo.ucChannelNum); + + prChnlReqInfo->u8Cookie = prOffChnlTxPkt->u8Cookie; + prChnlReqInfo->eChnlReqType = CH_REQ_TYPE_OFFCHNL_TX; + prChnlReqInfo->eBand = prOffChnlTxPkt->rChannelInfo.eBand; + prChnlReqInfo->ucReqChnlNum = + prOffChnlTxPkt->rChannelInfo.ucChannelNum; + prChnlReqInfo->eChnlSco = prOffChnlTxPkt->eChnlExt; + prChnlReqInfo->u4MaxInterval = prOffChnlTxPkt->u4Duration; + prChnlReqInfo->eChannelWidth = + prOffChnlTxPkt->rChannelInfo.ucChnlBw; + prChnlReqInfo->ucCenterFreqS1 = + prOffChnlTxPkt->rChannelInfo.u4CenterFreq1; + prChnlReqInfo->ucCenterFreqS2 = + prOffChnlTxPkt->rChannelInfo.u4CenterFreq2; + + p2pFuncAcquireCh(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + prChnlReqInfo); + } else { + cnmTimerStartTimer(prAdapter, + &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer), + prOffChnlTxPkt->u4Duration); + p2pFuncTxMgmtFrame(prAdapter, + prOffChnlTxPkt->ucBssIndex, + prOffChnlTxPkt->prMgmtTxMsdu, + prOffChnlTxPkt->fgNoneCckRate); + + LINK_REMOVE_HEAD(&(prP2pMgmtTxInfo->rTxReqLink), + prOffChnlTxPkt, + struct P2P_OFF_CHNL_TX_REQ_INFO *); + cnmMemFree(prAdapter, prOffChnlTxPkt); + } + + return FALSE; +} + +void +p2pRoleStateAbort_OFF_CHNL_TX(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN struct P2P_MGMT_TX_REQ_INFO *prP2pMgmtTxInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN enum ENUM_P2P_ROLE_STATE eNextState) +{ + cnmTimerStopTimer(prAdapter, + &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer)); + + if (eNextState == P2P_ROLE_STATE_OFF_CHNL_TX) + return; + + p2pFunClearAllTxReq(prAdapter, prP2pMgmtTxInfo); + p2pFuncReleaseCh(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + prChnlReqInfo); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_scan.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_scan.c new file mode 100644 index 0000000000000..bbc43254ab5be --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/p2p_scan.c @@ -0,0 +1,348 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 + ****************************************************************************** + */ + +void +scanP2pProcessBeaconAndProbeResp(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint32_t *prStatus, + IN struct BSS_DESC *prBssDesc, + IN struct WLAN_BEACON_FRAME *prWlanBeaconFrame) +{ + u_int8_t fgIsBeacon = FALSE; + u_int8_t fgIsSkipThisBeacon = FALSE; + + /* Indicate network to kernel for P2P interface when: + * 1. This is P2P network + * 2. Driver is configured to report all bss networks + */ + if (!prBssDesc->fgIsP2PPresent && + !prAdapter->p2p_scan_report_all_bss) + return; + + fgIsBeacon = (prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) == + MAC_FRAME_BEACON; + + if (prBssDesc->fgIsConnected && fgIsBeacon) { + uint32_t u4Idx = 0; + struct BSS_INFO *prP2pBssInfo = + (struct BSS_INFO *) NULL; + + for (u4Idx = 0; u4Idx < prAdapter->ucHwBssIdNum; u4Idx++) { + /* Check BSS for P2P. */ + /* Check BSSID. */ + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + (uint8_t) u4Idx); + + if (!IS_BSS_ACTIVE(prP2pBssInfo)) + continue; + + if ((prP2pBssInfo->eNetworkType != NETWORK_TYPE_P2P) || + (UNEQUAL_MAC_ADDR(prP2pBssInfo->aucBSSID, + prBssDesc->aucBSSID) || + (!EQUAL_SSID(prP2pBssInfo->aucSSID, + prP2pBssInfo->ucSSIDLen, + prBssDesc->aucSSID, + prBssDesc->ucSSIDLen)))) { + continue; + } + /* P2P GC */ + /* Connected */ + if ((prP2pBssInfo->eCurrentOPMode == + OP_MODE_INFRASTRUCTURE) && + (prP2pBssInfo->eConnectionState == + MEDIA_STATE_CONNECTED)) { + fgIsSkipThisBeacon = TRUE; + /* First Time. */ + if ((!prP2pBssInfo->ucDTIMPeriod)) { + prP2pBssInfo->ucDTIMPeriod = + prBssDesc->ucDTIMPeriod; + nicPmIndicateBssConnected( + prAdapter, + prP2pBssInfo->ucBssIndex); + } + } + + } + + } + + /* Skip report beacon to upper layer if no p2p scan */ + if (prAdapter->prGlueInfo->prP2PDevInfo->prScanRequest == NULL && + fgIsBeacon) + fgIsSkipThisBeacon = TRUE; + + if (fgIsBeacon && fgIsSkipThisBeacon) { + /* Only report Probe Response frame + * to supplicant except passive scan. + */ + /* Probe response collect + * much more information. + */ + DBGLOG(P2P, TRACE, "Skip beacon [" MACSTR "][%s][ch %d]\n", + MAC2STR(prWlanBeaconFrame->aucBSSID), + prBssDesc->aucSSID, + prBssDesc->ucChannelNum); + return; + } + + do { + struct RF_CHANNEL_INFO rChannelInfo; + + ASSERT_BREAK((prSwRfb != NULL) && (prBssDesc != NULL)); + + rChannelInfo.ucChannelNum = prBssDesc->ucChannelNum; + rChannelInfo.eBand = prBssDesc->eBand; + prBssDesc->fgIsP2PReport = TRUE; + + DBGLOG(P2P, INFO, + "indicate [" MACSTR "][%s][%s][ch %d][r %d][t %u]\n", + MAC2STR(prWlanBeaconFrame->aucBSSID), + fgIsBeacon ? "Beacon" : "Probe Response", + prBssDesc->aucSSID, + prBssDesc->ucChannelNum, + prBssDesc->ucRCPI, + prBssDesc->rUpdateTime); + + kalP2PIndicateBssInfo(prAdapter->prGlueInfo, + (uint8_t *) prSwRfb->pvHeader, + (uint32_t) prSwRfb->u2PacketLen, + &rChannelInfo, + RCPI_TO_dBm(prBssDesc->ucRCPI)); + + } while (FALSE); +} + +void scnEventReturnChannel(IN struct ADAPTER *prAdapter, + IN uint8_t ucScnSeqNum) +{ + + struct CMD_SCAN_CANCEL rCmdScanCancel; + + /* send cancel message to firmware domain */ + rCmdScanCancel.ucSeqNum = ucScnSeqNum; + rCmdScanCancel.ucIsExtChannel = (uint8_t) FALSE; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SCAN_CANCEL, + TRUE, + FALSE, FALSE, NULL, NULL, + sizeof(struct CMD_SCAN_CANCEL), + (uint8_t *)&rCmdScanCancel, NULL, 0); +} /* scnEventReturnChannel */ + +void scanRemoveAllP2pBssDesc(IN struct ADAPTER *prAdapter) +{ + struct LINK *prBSSDescList; + struct BSS_DESC *prBssDesc; + struct BSS_DESC *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, struct BSS_DESC) { + scanRemoveP2pBssDesc(prAdapter, prBssDesc); + } +} /* scanRemoveAllP2pBssDesc */ + +void scanRemoveP2pBssDesc(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc) +{ +} /* scanRemoveP2pBssDesc */ + +struct BSS_DESC *scanP2pSearchDesc(IN struct ADAPTER *prAdapter, + IN struct P2P_CONNECTION_REQ_INFO *prConnReqInfo) +{ + struct BSS_DESC *prCandidateBssDesc = (struct BSS_DESC *) NULL, + *prBssDesc = (struct BSS_DESC *) NULL; + struct LINK *prBssDescList = (struct LINK *) NULL; + + do { + if ((prAdapter == 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", + HIDE(prConnReqInfo->rSsidStruct.aucSsid), + prConnReqInfo->rSsidStruct.ucSsidLen); + + LINK_FOR_EACH_ENTRY(prBssDesc, prBssDescList, + rLinkEntry, struct BSS_DESC) { + 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", + HIDE( + prConnReqInfo->rSsidStruct.aucSsid), + prConnReqInfo->rSsidStruct.ucSsidLen); + DBGLOG(P2P, TRACE, + "Checking SSID:%s, length:%d\n", + HIDE(prBssDesc->aucSSID), + prBssDesc->ucSSIDLen); + DBGLOG(P2P, TRACE, + "Ignore mismatch SSID, (But BSSID match).\n"); + /* ASSERT(FALSE); *//*let p2p re-scan again */ + continue; + } + + if (!prBssDesc->fgIsP2PPresent) { + DBGLOG(P2P, ERROR, + "SSID, BSSID, BSSTYPE match, but no P2P IE present.\n"); +#if CFG_P2P_CONNECT_ALL_BSS + /* Force return */ +#else + continue; +#endif + } + + /* Final decision. */ + prCandidateBssDesc = prBssDesc; + break; + } + + } while (FALSE); + + return prCandidateBssDesc; +} /* scanP2pSearchDesc */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/privacy.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/privacy.c new file mode 100644 index 0000000000000..f11d7edeaf5a8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/privacy.c @@ -0,0 +1,1445 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: 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 + * + */ + +/******************************************************************************* + * C O M P I L E 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 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 struct ADAPTER *prAdapter, IN uint8_t ucBssIndex) +{ + uint8_t i; + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_INFO *prBssInfo; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecBssInfo; + struct IEEE_802_11_MIB *prMib; + + DEBUGFUNC("secInit"); + + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + prAisSpecBssInfo = + aisGetAisSpecBssInfo(prAdapter, ucBssIndex); + prMib = aisGetMib(prAdapter, ucBssIndex); + + prBssInfo->u4RsnSelectedGroupCipher = 0; + prBssInfo->u4RsnSelectedPairwiseCipher = 0; + prBssInfo->u4RsnSelectedAKMSuite = 0; + +#if 0 /* CFG_ENABLE_WIFI_DIRECT */ + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P]; + + prBssInfo->u4RsnSelectedGroupCipher = RSN_CIPHER_SUITE_CCMP; + prBssInfo->u4RsnSelectedPairwiseCipher = RSN_CIPHER_SUITE_CCMP; + prBssInfo->u4RsnSelectedAKMSuite = RSN_AKM_SUITE_PSK; +#endif + +#if 0 /* CFG_ENABLE_BT_OVER_WIFI */ + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW]; + + prBssInfo->u4RsnSelectedGroupCipher = RSN_CIPHER_SUITE_CCMP; + prBssInfo->u4RsnSelectedPairwiseCipher = RSN_CIPHER_SUITE_CCMP; + prBssInfo->u4RsnSelectedAKMSuite = RSN_AKM_SUITE_PSK; +#endif + + prMib-> + dot11RSNAConfigPairwiseCiphersTable[0].dot11RSNAConfigPairwiseCipher + = WPA_CIPHER_SUITE_WEP40; + prMib-> + dot11RSNAConfigPairwiseCiphersTable[1].dot11RSNAConfigPairwiseCipher + = WPA_CIPHER_SUITE_TKIP; + prMib-> + dot11RSNAConfigPairwiseCiphersTable[2].dot11RSNAConfigPairwiseCipher + = WPA_CIPHER_SUITE_CCMP; + prMib-> + dot11RSNAConfigPairwiseCiphersTable[3].dot11RSNAConfigPairwiseCipher + = WPA_CIPHER_SUITE_WEP104; + + prMib-> + dot11RSNAConfigPairwiseCiphersTable[4].dot11RSNAConfigPairwiseCipher + = RSN_CIPHER_SUITE_WEP40; + prMib-> + dot11RSNAConfigPairwiseCiphersTable[5].dot11RSNAConfigPairwiseCipher + = RSN_CIPHER_SUITE_TKIP; + prMib-> + dot11RSNAConfigPairwiseCiphersTable[6].dot11RSNAConfigPairwiseCipher + = RSN_CIPHER_SUITE_CCMP; + prMib-> + dot11RSNAConfigPairwiseCiphersTable[7].dot11RSNAConfigPairwiseCipher + = RSN_CIPHER_SUITE_WEP104; + prMib-> + dot11RSNAConfigPairwiseCiphersTable[8].dot11RSNAConfigPairwiseCipher + = RSN_CIPHER_SUITE_GROUP_NOT_USED; + prMib-> + dot11RSNAConfigPairwiseCiphersTable[9].dot11RSNAConfigPairwiseCipher + = RSN_CIPHER_SUITE_GCMP_256; + + for (i = 0; i < MAX_NUM_SUPPORTED_CIPHER_SUITES; i++) + prMib->dot11RSNAConfigPairwiseCiphersTable + [i].dot11RSNAConfigPairwiseCipherEnabled = FALSE; + + prMib->dot11RSNAConfigAuthenticationSuitesTable + [0].dot11RSNAConfigAuthenticationSuite = WPA_AKM_SUITE_NONE; + prMib->dot11RSNAConfigAuthenticationSuitesTable + [1].dot11RSNAConfigAuthenticationSuite = WPA_AKM_SUITE_802_1X; + prMib->dot11RSNAConfigAuthenticationSuitesTable + [2].dot11RSNAConfigAuthenticationSuite = WPA_AKM_SUITE_PSK; + prMib->dot11RSNAConfigAuthenticationSuitesTable + [3].dot11RSNAConfigAuthenticationSuite = RSN_AKM_SUITE_NONE; + prMib->dot11RSNAConfigAuthenticationSuitesTable + [4].dot11RSNAConfigAuthenticationSuite = RSN_AKM_SUITE_802_1X; + prMib->dot11RSNAConfigAuthenticationSuitesTable + [5].dot11RSNAConfigAuthenticationSuite = RSN_AKM_SUITE_PSK; + + prMib->dot11RSNAConfigAuthenticationSuitesTable + [6].dot11RSNAConfigAuthenticationSuite = RSN_AKM_SUITE_FT_802_1X; + prMib->dot11RSNAConfigAuthenticationSuitesTable + [7].dot11RSNAConfigAuthenticationSuite = RSN_AKM_SUITE_FT_PSK; + prMib->dot11RSNAConfigAuthenticationSuitesTable + [8].dot11RSNAConfigAuthenticationSuite = WFA_AKM_SUITE_OSEN; + +#if CFG_SUPPORT_802_11W + prMib->dot11RSNAConfigAuthenticationSuitesTable + [9].dot11RSNAConfigAuthenticationSuite = + RSN_AKM_SUITE_802_1X_SHA256; + prMib->dot11RSNAConfigAuthenticationSuitesTable + [10].dot11RSNAConfigAuthenticationSuite = RSN_AKM_SUITE_PSK_SHA256; + prMib->dot11RSNAConfigAuthenticationSuitesTable + [11].dot11RSNAConfigAuthenticationSuite = RSN_AKM_SUITE_SAE; + prMib->dot11RSNAConfigAuthenticationSuitesTable + [12].dot11RSNAConfigAuthenticationSuite = RSN_AKM_SUITE_OWE; +#endif + + for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) { + prMib->dot11RSNAConfigAuthenticationSuitesTable + [i].dot11RSNAConfigAuthenticationSuiteEnabled = FALSE; + } + +#if CFG_SUPPORT_802_11W + cnmTimerInitTimer(prAdapter, + &prAisSpecBssInfo->rSaQueryTimer, + (PFN_MGMT_TIMEOUT_FUNC) rsnStartSaQueryTimer, + (unsigned long)ucBssIndex); +#endif + + prAisSpecBssInfo->fgCounterMeasure = FALSE; + prBssInfo->ucBcDefaultKeyIdx = 0xff; + prBssInfo->fgBcDefaultKeyExist = FALSE; + +#if 0 + for (i = 0; i < WTBL_SIZE; i++) { + g_prWifiVar->arWtbl[i].ucUsed = FALSE; + g_prWifiVar->arWtbl[i].prSta = NULL; + g_prWifiVar->arWtbl[i].ucNetTypeIdx = NETWORK_TYPE_INDEX_NUM; + + } + nicPrivacyInitialize((uint8_t) 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t secCheckClassError(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN struct STA_RECORD *prStaRec) +{ + void *prRxStatus; + struct RX_DESC_OPS_T *prRxDescOps; + + prRxDescOps = prAdapter->chip_info->prRxDescOps; + prRxStatus = prSwRfb->prRxStatus; + + if (prRxDescOps->nic_rxd_get_sw_class_error_bit(prRxStatus) + || (IS_STA_IN_AIS(prStaRec) + && aisGetAisBssInfo(prAdapter, + prStaRec->ucBssIndex)->eConnectionState == + MEDIA_STATE_DISCONNECTED)) { + + DBGLOG_LIMITED(RSN, WARN, + "RX_CLASSERR: prStaRec=%p PktTYpe=0x%x, WlanIdx=%d,", + prStaRec, + prSwRfb->ucPacketType, prSwRfb->ucWlanIdx); + DBGLOG_LIMITED(RSN, WARN, + "StaRecIdx=%d, eDst=%d, prStaRec->eStaType=%d\n", + prSwRfb->ucStaRecIdx, + prSwRfb->eDst, prStaRec->eStaType); + + DBGLOG_MEM8(RX, ERROR, prSwRfb->pucRecvBuff, + (prSwRfb->u2RxByteCount > 64) ? 64 : + prSwRfb->u2RxByteCount); + + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_4)) { + DBGLOG(RX, ERROR, + "secchk:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + prSwRfb->prRxStatusGroup4->u2FrameCtl, + prSwRfb->prRxStatusGroup4->aucTA[0], + prSwRfb->prRxStatusGroup4->aucTA[1], + prSwRfb->prRxStatusGroup4->aucTA[2], + prSwRfb->prRxStatusGroup4->aucTA[3], + prSwRfb->prRxStatusGroup4->aucTA[4], + prSwRfb->prRxStatusGroup4->aucTA[5], + prSwRfb->prRxStatusGroup4->u2SeqFrag, + prSwRfb->prRxStatusGroup4->u2Qos, + prSwRfb->prRxStatusGroup4->u4HTC); + } + + if (EAPOL_KEY_NOT_KEY != + secGetEapolKeyType((uint8_t *) prSwRfb->pvHeader)) { + DBGLOG(RSN, WARN, + "EAPOL key found, return TRUE back"); + + return TRUE; + } + + /* if (IS_NET_ACTIVE(prAdapter, ucBssIndex)) { */ + authSendDeauthFrame(prAdapter, + NULL, NULL, prSwRfb, + REASON_CODE_CLASS_3_ERR, + (PFN_TX_DONE_HANDLER) NULL); + return FALSE; + /* } */ + } + + return TRUE; + +} /* 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 struct ADAPTER *prAdapter, + IN struct STA_RECORD *prSta, IN u_int8_t fgPortBlock) +{ +#if 0 /* Marked for MT6630 */ + if (prSta == NULL) + return; + + prSta->fgPortBlock = fgPortBlock; + + DBGLOG(RSN, TRACE, + "The STA " MACSTR " port %s\n", MAC2STR(prSta->aucMacAddr), + fgPortBlock == TRUE ? "BLOCK" : " OPEN"); +#endif +} + +#if 0 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + * + */ +/*----------------------------------------------------------------------------*/ +u_int8_t secGetPortStatus(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prSta, + OUT u_int8_t *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 + * + */ +/*----------------------------------------------------------------------------*/ +u_int8_t /* ENUM_PORT_CONTROL_RESULT */ +secTxPortControlCheck(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN struct STA_RECORD *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; +} +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t secRxPortControlCheck(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSWRfb) +{ + ASSERT(prSWRfb); + + 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 struct ADAPTER *prAdapter, + IN uint32_t u4CipherSuitesFlags, + IN uint8_t ucBssIndex) +{ + + uint32_t i; + struct DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY *prEntry; + struct IEEE_802_11_MIB *prMib; + + prMib = aisGetMib(prAdapter, ucBssIndex); + + 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 RSN_CIPHER_SUITE_GCMP_256: + if (u4CipherSuitesFlags & CIPHER_FLAG_GCMP256) + prEntry->dot11RSNAConfigPairwiseCipherEnabled = + TRUE; + else + prEntry->dot11RSNAConfigPairwiseCipherEnabled = + FALSE; + break; + + 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 RSN_CIPHER_SUITE_GROUP_NOT_USED: + if (u4CipherSuitesFlags & + (CIPHER_FLAG_CCMP | CIPHER_FLAG_TKIP)) + 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, ucBssIndex)) + prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_CCMP; + else if (rsnSearchSupportedCipher(prAdapter, + WPA_CIPHER_SUITE_TKIP, &i, ucBssIndex)) + prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_TKIP; + else if (rsnSearchSupportedCipher(prAdapter, + WPA_CIPHER_SUITE_WEP104, &i, ucBssIndex)) + prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_WEP104; + else if (rsnSearchSupportedCipher(prAdapter, + WPA_CIPHER_SUITE_WEP40, &i, ucBssIndex)) + prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_WEP40; + else if (rsnSearchSupportedCipher(prAdapter, + RSN_CIPHER_SUITE_GROUP_NOT_USED, &i, ucBssIndex)) + prMib->dot11RSNAConfigGroupCipher = + RSN_CIPHER_SUITE_GROUP_NOT_USED; + else if (rsnSearchSupportedCipher(prAdapter, + RSN_CIPHER_SUITE_GCMP_256, &i, ucBssIndex)) + prMib->dot11RSNAConfigGroupCipher = + RSN_CIPHER_SUITE_GCMP_256; + else + prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_NONE; + +} /* secSetCipherSuite */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Whether 802.11 privacy is enabled. + * + * \param[in] prAdapter Pointer to the Adapter structure + * + * \retval BOOLEAN + */ +/*----------------------------------------------------------------------------*/ +u_int8_t secEnabledInAis(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + enum ENUM_WEP_STATUS eEncStatus; + + eEncStatus = aisGetEncStatus(prAdapter, ucBssIndex); + + DEBUGFUNC("secEnabledInAis"); + + switch (eEncStatus) { + case ENUM_ENCRYPTION_DISABLED: + return FALSE; + case ENUM_ENCRYPTION1_ENABLED: + case ENUM_ENCRYPTION2_ENABLED: + case ENUM_ENCRYPTION3_ENABLED: + case ENUM_ENCRYPTION4_ENABLED: + return TRUE; + default: + DBGLOG(RSN, TRACE, "Unknown encryption setting %d\n", + eEncStatus); + break; + } + return FALSE; + +} /* secEnabledInAis */ + +u_int8_t secIsProtected1xFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + struct BSS_INFO *prBssInfo; + + if (prStaRec) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + if (prBssInfo && prBssInfo->eNetworkType == NETWORK_TYPE_AIS) { +#if CFG_SUPPORT_WAPI + if (aisGetWapiMode(prAdapter, + prStaRec->ucBssIndex)) + return FALSE; +#endif + } + + return prStaRec->fgTransmitKeyExist; + } + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t secIsProtectedFrame(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsdu, + IN struct STA_RECORD *prStaRec) +{ +#if CFG_SUPPORT_802_11W + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec) && + (secIsRobustActionFrame(prAdapter, prMsdu->prPacket) + || (IS_BSS_INDEX_AIS(prAdapter, prMsdu->ucBssIndex) && + secIsRobustMgmtFrame(prAdapter, prMsdu->prPacket)))) + return TRUE; +#endif + if (prMsdu->ucPacketType == TX_PACKET_TYPE_MGMT) + return FALSE; + + return secIsProtectedBss(prAdapter, + GET_BSS_INFO_BY_INDEX(prAdapter, + prMsdu->ucBssIndex)); +} + +u_int8_t secIsProtectedBss(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo) +{ + uint8_t ucBssIndex = 0; + + ucBssIndex = prBssInfo->ucBssIndex; + + if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) { +#if CFG_SUPPORT_WAPI + if (aisGetWapiMode(prAdapter, ucBssIndex)) + return TRUE; +#endif + return secEnabledInAis(prAdapter, + ucBssIndex); + } +#if CFG_ENABLE_WIFI_DIRECT + else if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) + return kalP2PGetCipher(prAdapter->prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData); +#endif + else if (prBssInfo->eNetworkType == NETWORK_TYPE_BOW) + return TRUE; + + return FALSE; +} + +u_int8_t secIsRobustMgmtFrame(IN struct ADAPTER *prAdapter, IN void *prPacket) +{ + struct WLAN_MAC_HEADER *prWlanHeader = NULL; + uint16_t u2TxFrameCtrl; + + if (!prPacket) + return FALSE; + + prWlanHeader = (struct WLAN_MAC_HEADER *) + ((unsigned long) prPacket + MAC_TX_RESERVED_FIELD); + u2TxFrameCtrl = prWlanHeader->u2FrameCtrl & MASK_FRAME_TYPE; + if (u2TxFrameCtrl == MAC_FRAME_DISASSOC + || u2TxFrameCtrl == MAC_FRAME_DEAUTH) + return TRUE; + return FALSE; +} + +u_int8_t secIsRobustActionFrame(IN struct ADAPTER *prAdapter, IN void *prPacket) +{ + struct WLAN_MAC_HEADER *prWlanHeader = NULL; + struct WLAN_ACTION_FRAME *prActFrame = NULL; + uint8_t ucCategory; + uint16_t u2TxFrameCtrl; + + if (!prPacket) + return FALSE; + + prWlanHeader = (struct WLAN_MAC_HEADER *) + ((unsigned long) prPacket + MAC_TX_RESERVED_FIELD); + u2TxFrameCtrl = prWlanHeader->u2FrameCtrl & MASK_FRAME_TYPE; + if (u2TxFrameCtrl != MAC_FRAME_ACTION) + return FALSE; + + prActFrame = (struct WLAN_ACTION_FRAME *)prWlanHeader; + ucCategory = prActFrame->ucCategory; + return ucCategory == CATEGORY_SPEC_MGT || + ucCategory == CATEGORY_QOS_ACTION || + ucCategory == CATEGORY_DLS_ACTION || + ucCategory == CATEGORY_BLOCK_ACK_ACTION || + ucCategory == CATEGORY_RM_ACTION || + ucCategory == CATEGORY_FT_ACTION || + ucCategory == CATEGORY_SA_QUERY_ACTION || + ucCategory == CATEGORY_PROTECTED_DUAL_OF_PUBLIC_ACTION || + ucCategory == CATEGORY_WNM_ACTION || + ucCategory == CATEGORY_TDLS_ACTION || + ucCategory == CATEGORY_MESH_ACTION || + ucCategory == CATEGORY_MULTIHOP_ACTION || + ucCategory == CATEGORY_DMG_ACTION || + ucCategory == CATEGORY_FST_ACTION || + ucCategory == CATEGORY_ROBUST_AV_STREAMING_ACTION || + ucCategory == CATEGORY_VENDOR_SPECIFIC_PROTECTED_ACTION + ? TRUE : FALSE; +} + +u_int8_t secIsWepBss(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo) +{ + enum ENUM_WEP_STATUS eEncStatus; + + eEncStatus = aisGetEncStatus(prAdapter, + prBssInfo->ucBssIndex); + + if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) { + if (eEncStatus == + ENUM_ENCRYPTION1_ENABLED) + return TRUE; + } +#if CFG_ENABLE_WIFI_DIRECT + else if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) + return kalP2PGetWepCipher(prAdapter->prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData); +#endif + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used before add/update a WLAN entry. + * Info the WLAN Table has available entry for this request + * + * \param[in] prAdapter Pointer to the Adapter structure + * \param[in] prSta the P_STA_RECORD_T for store + * + * \return TRUE Free Wlan table is reserved for this request + * FALSE No free entry for this request + * + * \note + */ +/*----------------------------------------------------------------------------*/ +u_int8_t secPrivacySeekForEntry( + IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prSta) +{ + struct BSS_INFO *prP2pBssInfo; + uint8_t ucEntry = WTBL_RESERVED_ENTRY; + uint8_t i; + uint8_t ucStartIDX = 0, ucMaxIDX = 0; + struct WLAN_TABLE *prWtbl; + uint8_t ucRoleIdx = 0; + + if (!prSta->fgIsInUse) { + DBGLOG(RSN, ERROR, "sta is not in use\n"); + return FALSE; + } + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prSta->ucBssIndex); + ucRoleIdx = prP2pBssInfo->u4PrivateData; + + prWtbl = prAdapter->rWifiVar.arWtbl; + + ucStartIDX = 1; + ucMaxIDX = prAdapter->ucTxDefaultWlanIndex - 1; + + for (i = ucStartIDX; i <= ucMaxIDX; i++) { +#if CFG_WIFI_SW_WTBL_SEARCH_FAIL + if (i % 8 == 0) + continue; +#endif + if (prWtbl[i].ucUsed + && EQUAL_MAC_ADDR(prSta->aucMacAddr, prWtbl[i].aucMacAddr) + && prWtbl[i].ucPairwise + /* This function for ucPairwise only */ + && prWtbl[i].ucBssIndex == prSta->ucBssIndex) { + ucEntry = i; + DBGLOG(RSN, TRACE, + "[Wlan index]: Reuse entry #%d\n", i); + break; + } + } + + if (i == (ucMaxIDX + 1)) { + for (i = ucStartIDX; i <= ucMaxIDX; i++) { +#if CFG_WIFI_SW_WTBL_SEARCH_FAIL + if (i % 8 == 0) + continue; +#endif + if (prWtbl[i].ucUsed == FALSE) { + ucEntry = i; + DBGLOG(RSN, TRACE, + "[Wlan index]: Assign entry #%d\n", i); + break; + } + } + } + + /* Save to the driver maintain table */ + if (ucEntry < prAdapter->ucTxDefaultWlanIndex) { + + prWtbl[ucEntry].ucUsed = TRUE; + prWtbl[ucEntry].ucBssIndex = prSta->ucBssIndex; + prWtbl[ucEntry].ucKeyId = 0xFF; + prWtbl[ucEntry].ucPairwise = 1; + COPY_MAC_ADDR(prWtbl[ucEntry].aucMacAddr, prSta->aucMacAddr); + prWtbl[ucEntry].ucStaIndex = prSta->ucIndex; + + prSta->ucWlanIndex = ucEntry; + + { + struct BSS_INFO *prBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, prSta->ucBssIndex); + /* for AP mode , if wep key exist, peer sta should also + * fgTransmitKeyExist + */ + if (IS_BSS_P2P(prBssInfo) + && kalP2PGetRole(prAdapter->prGlueInfo, + ucRoleIdx) == 2) { + if (prBssInfo->fgBcDefaultKeyExist + && + !(kalP2PGetCcmpCipher + (prAdapter->prGlueInfo, ucRoleIdx) + || + kalP2PGetTkipCipher(prAdapter->prGlueInfo, + ucRoleIdx))) { + prSta->fgTransmitKeyExist = TRUE; + prWtbl[ucEntry].ucKeyId = + prBssInfo->ucBcDefaultKeyIdx; + DBGLOG(RSN, INFO, + "peer sta set fgTransmitKeyExist\n"); + } + } + } + + DBGLOG(RSN, INFO, + "[Wlan index] BSS#%d keyid#%d P=%d use WlanIndex#%d STAIdx=%d " + MACSTR + " staType=%x\n", prSta->ucBssIndex, 0, + prWtbl[ucEntry].ucPairwise, ucEntry, + prSta->ucIndex, MAC2STR(prSta->aucMacAddr), + prSta->eStaType); +#if 1 /* DBG */ + secCheckWTBLAssign(prAdapter); +#endif + return TRUE; + } +#if DBG + secCheckWTBLAssign(prAdapter); +#endif + DBGLOG(RSN, WARN, + "[Wlan index] No more wlan table entry available!!!!\n"); + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used free a WLAN entry. + * + * \param[in] prAdapter Pointer to the Adapter structure + * \param[in] ucEntry the wlan table index to free + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void secPrivacyFreeForEntry(IN struct ADAPTER *prAdapter, IN uint8_t ucEntry) +{ + struct WLAN_TABLE *prWtbl; + + if (ucEntry >= WTBL_SIZE) + return; + + DBGLOG(RSN, TRACE, "secPrivacyFreeForEntry %d", ucEntry); + + prWtbl = prAdapter->rWifiVar.arWtbl; + + if (prWtbl[ucEntry].ucUsed) { + prWtbl[ucEntry].ucUsed = FALSE; + prWtbl[ucEntry].ucKeyId = 0xff; + prWtbl[ucEntry].ucBssIndex = prAdapter->ucHwBssIdNum + 1; + prWtbl[ucEntry].ucPairwise = 0; + kalMemZero(prWtbl[ucEntry].aucMacAddr, MAC_ADDR_LEN); + prWtbl[ucEntry].ucStaIndex = STA_REC_INDEX_NOT_FOUND; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used free a STA WLAN entry. + * + * \param[in] prAdapter Pointer to the Adapter structure + * \param[in] prStaRec the sta which want to free + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void secPrivacyFreeSta(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + uint32_t entry; + struct WLAN_TABLE *prWtbl; + + if (!prStaRec) + return; + + prWtbl = prAdapter->rWifiVar.arWtbl; + + for (entry = 0; entry < WTBL_SIZE; entry++) { + /* Consider GTK case !! */ + if (prWtbl[entry].ucUsed && + EQUAL_MAC_ADDR(prStaRec->aucMacAddr, + prWtbl[entry].aucMacAddr) + && prWtbl[entry].ucPairwise + && prWtbl[entry].ucBssIndex == prStaRec->ucBssIndex) { +#if 1 /* DBG */ + DBGLOG(RSN, INFO, "Free STA entry (%d)!\n", entry); +#endif + secPrivacyFreeForEntry(prAdapter, entry); + prStaRec->ucWlanIndex = WTBL_RESERVED_ENTRY; + /* prStaRec->ucBMCWlanIndex = WTBL_RESERVED_ENTRY; */ + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used for remove the BC entry of the BSS + * + * \param[in] prAdapter Pointer to the Adapter structure + * \param[in] ucBssIndex The BSS index + * + * \note + */ +/*----------------------------------------------------------------------------*/ +void secRemoveBssBcEntry(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, IN u_int8_t fgRoam) +{ + int i; + + if (!prBssInfo) + return; + + DBGLOG_LIMITED(RSN, TRACE, "remove all the key related with BSS!"); + + if (fgRoam) { + struct CONNECTION_SETTINGS *prConnSettings = + aisGetConnSettings(prAdapter, + prBssInfo->ucBssIndex); + + if (IS_BSS_AIS(prBssInfo) && + prBssInfo->prStaRecOfAP + && (prConnSettings->eAuthMode >= AUTH_MODE_WPA && + prConnSettings->eAuthMode != AUTH_MODE_WPA_NONE)) { + + for (i = 0; i < MAX_KEY_NUM; i++) { + if (prBssInfo->ucBMCWlanIndexSUsed[i]) + secPrivacyFreeForEntry(prAdapter, + prBssInfo->ucBMCWlanIndexS[i]); + + prBssInfo->ucBMCWlanIndexSUsed[i] = FALSE; + prBssInfo->ucBMCWlanIndexS[i] = WTBL_RESERVED_ENTRY; + + } + + prBssInfo->fgBcDefaultKeyExist = FALSE; + prBssInfo->ucBcDefaultKeyIdx = 0xff; + } + } else { + /* According to discussion, it's ok to change to + * reserved_entry here so that the entry is _NOT_ freed at all. + * In this way, the same BSS(ucBssIndex) could reuse the same + * entry next time in secPrivacySeekForBcEntry(), and we could + * see the following log: "[Wlan index]: Reuse entry ...". + */ + prBssInfo->ucBMCWlanIndex = WTBL_RESERVED_ENTRY; + secPrivacyFreeForEntry(prAdapter, prBssInfo->ucBMCWlanIndex); + + for (i = 0; i < MAX_KEY_NUM; i++) { + if (prBssInfo->ucBMCWlanIndexSUsed[i]) + secPrivacyFreeForEntry(prAdapter, + prBssInfo->ucBMCWlanIndexS[i]); + + prBssInfo->ucBMCWlanIndexSUsed[i] = FALSE; + prBssInfo->ucBMCWlanIndexS[i] = WTBL_RESERVED_ENTRY; + } + for (i = 0; i < MAX_KEY_NUM; i++) { + if (prBssInfo->wepkeyUsed[i]) + secPrivacyFreeForEntry(prAdapter, + prBssInfo->wepkeyWlanIdx); + prBssInfo->wepkeyUsed[i] = FALSE; + } + prBssInfo->wepkeyWlanIdx = WTBL_RESERVED_ENTRY; + prBssInfo->fgBcDefaultKeyExist = FALSE; + prBssInfo->ucBcDefaultKeyIdx = 0xff; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used for adding the broadcast key used, to assign + * a wlan table entry for reserved the specific entry for these key for + * + * \param[in] prAdapter Pointer to the Adapter structure + * \param[in] ucBssIndex The BSS index + * \param[in] ucNetTypeIdx The Network index + * \param[in] ucAlg the entry assign related with algorithm + * \param[in] ucKeyId The key id + * \param[in] ucTxRx The Type of the key + * + * \return ucEntryIndex The entry to be used, WTBL_ALLOC_FAIL for allocation + * fail + * + * \note + */ +/*----------------------------------------------------------------------------*/ +uint8_t +secPrivacySeekForBcEntry(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN uint8_t *pucAddr, IN uint8_t ucStaIdx, + IN uint8_t ucAlg, IN uint8_t ucKeyId) +{ + uint8_t ucEntry = WTBL_ALLOC_FAIL; + uint8_t ucStartIDX = 0, ucMaxIDX = 0; + uint8_t i; + u_int8_t fgCheckKeyId = TRUE; + struct WLAN_TABLE *prWtbl; + struct BSS_INFO *prBSSInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + prWtbl = prAdapter->rWifiVar.arWtbl; + + if (ucAlg == CIPHER_SUITE_WPI || /* CIPHER_SUITE_GCM_WPI || */ + ucAlg == CIPHER_SUITE_WEP40 || + ucAlg == CIPHER_SUITE_WEP104 + || ucAlg == CIPHER_SUITE_WEP128 || ucAlg == CIPHER_SUITE_NONE) + fgCheckKeyId = FALSE; + + if (ucKeyId == 0xFF || ucAlg == CIPHER_SUITE_BIP) + fgCheckKeyId = FALSE; + + if (prBSSInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) + fgCheckKeyId = FALSE; + + DBGLOG_LIMITED(INIT, INFO, "OpMode:%d, NetworkType:%d, CheckKeyId:%d\n", + prBSSInfo->eCurrentOPMode, prBSSInfo->eNetworkType, + fgCheckKeyId); + + ucStartIDX = 1; + ucMaxIDX = prAdapter->ucTxDefaultWlanIndex - 1; + + if (ucAlg == CIPHER_SUITE_BIP) { + ucEntry = 0; + } else { + for (i = ucStartIDX; i <= ucMaxIDX; i++) { + + if (prWtbl[i].ucUsed && !prWtbl[i].ucPairwise + && prWtbl[i].ucBssIndex == ucBssIndex) { + if (!fgCheckKeyId) { + ucEntry = i; + DBGLOG(RSN, TRACE, + "[Wlan index]: Reuse entry #%d for open/wep/wpi\n", + i); + break; + } + + if (fgCheckKeyId + && (prWtbl[i].ucKeyId == ucKeyId + || prWtbl[i].ucKeyId == 0xFF)) { + ucEntry = i; + DBGLOG(RSN, TRACE, + "[Wlan index]: Reuse entry #%d\n", + i); + break; + } + } + } + + if (i == (ucMaxIDX + 1)) { + for (i = ucStartIDX; i <= ucMaxIDX; i++) { + if (prWtbl[i].ucUsed == FALSE) { + ucEntry = i; + DBGLOG(RSN, TRACE, + "[Wlan index]: Assign entry #%d\n", + i); + break; + } + } + } + } + + if (ucEntry < prAdapter->ucTxDefaultWlanIndex) { + prWtbl[ucEntry].ucUsed = TRUE; + prWtbl[ucEntry].ucKeyId = ucKeyId; + prWtbl[ucEntry].ucBssIndex = ucBssIndex; + prWtbl[ucEntry].ucPairwise = 0; + kalMemCopy(prWtbl[ucEntry].aucMacAddr, pucAddr, + MAC_ADDR_LEN); + prWtbl[ucEntry].ucStaIndex = ucStaIdx; + + DBGLOG_LIMITED(RSN, INFO, + "[Wlan index] BSS#%d keyid#%d P=%d use WlanIndex#%d STAIdx=%d " + MACSTR + "\n", ucBssIndex, ucKeyId, prWtbl[ucEntry].ucPairwise, + ucEntry, ucStaIdx, MAC2STR(pucAddr)); + + /* DBG */ + secCheckWTBLAssign(prAdapter); + + } else { + secCheckWTBLAssign(prAdapter); + DBGLOG(RSN, ERROR, + "[Wlan index] No more wlan entry available!!!!\n"); + } + + return ucEntry; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] prAdapter Pointer to the Adapter structure + * + * \return ucEntryIndex The entry to be used, WTBL_ALLOC_FAIL for allocation + * fail + * + * \note + */ +/*----------------------------------------------------------------------------*/ +u_int8_t secCheckWTBLAssign(IN struct ADAPTER *prAdapter) +{ + secPrivacyDumpWTBL(prAdapter); + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Got the STA record index by wlan index + * + * \param[in] prAdapter Pointer to the Adapter structure + * \param[in] ucWlanIdx The Rx wlan index + * + * \return The STA record index, 0xff for invalid sta index + */ +/*----------------------------------------------------------------------------*/ +uint8_t secGetStaIdxByWlanIdx(struct ADAPTER *prAdapter, uint8_t ucWlanIdx) +{ + struct WLAN_TABLE *prWtbl; + + if (ucWlanIdx >= WTBL_SIZE) + return STA_REC_INDEX_NOT_FOUND; + + prWtbl = prAdapter->rWifiVar.arWtbl; + + /* DBGLOG(RSN, TRACE, ("secGetStaIdxByWlanIdx=%d "MACSTR" used=%d\n", + * ucWlanIdx, MAC2STR(prWtbl[ucWlanIdx].aucMacAddr), + * prWtbl[ucWlanIdx].ucUsed)); + */ + + if (prWtbl[ucWlanIdx].ucUsed) + return prWtbl[ucWlanIdx].ucStaIndex; + else + return STA_REC_INDEX_NOT_FOUND; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief At Sw wlan table, got the BSS index by wlan index + * + * \param[in] prAdapter Pointer to the Adapter structure + * \param[in] ucWlanIdx The Rx wlan index + * + * \return The BSS index, 0xff for invalid bss index + */ +/*----------------------------------------------------------------------------*/ +uint8_t secGetBssIdxByWlanIdx(struct ADAPTER *prAdapter, uint8_t ucWlanIdx) +{ + struct WLAN_TABLE *prWtbl; + + if (ucWlanIdx >= WTBL_SIZE) + return WTBL_RESERVED_ENTRY; + + prWtbl = prAdapter->rWifiVar.arWtbl; + + if (prWtbl[ucWlanIdx].ucUsed) + return prWtbl[ucWlanIdx].ucBssIndex; + else + return WTBL_RESERVED_ENTRY; +} + +uint8_t secGetBssIdxByRfb(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) { + + if (prAdapter && prSwRfb) { + uint8_t ucBssIndex = + secGetBssIdxByWlanIdx(prAdapter, + prSwRfb->ucWlanIdx); + struct STA_RECORD *prStaRec = + cnmGetStaRecByIndex(prAdapter, + prSwRfb->ucStaRecIdx); + + + if (ucBssIndex != WTBL_RESERVED_ENTRY) + return ucBssIndex; + + + if (prStaRec) { + DBGLOG(RSN, LOUD, + "prStaRec->ucBssIndex = %d\n", + prStaRec->ucBssIndex); + return prStaRec->ucBssIndex; + } + } + + DBGLOG(RSN, LOUD, "Return default index\n"); + + return AIS_DEFAULT_INDEX; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Got the STA record index by mac addr + * + * \param[in] prAdapter Pointer to the Adapter structure + * \param[in] pucMacAddress MAC Addr + * + * \return The STA record index, 0xff for invalid sta index + */ +/*----------------------------------------------------------------------------*/ +uint8_t secLookupStaRecIndexFromTA( + struct ADAPTER *prAdapter, uint8_t *pucMacAddress) +{ + int i; + struct WLAN_TABLE *prWtbl; + + prWtbl = prAdapter->rWifiVar.arWtbl; + + for (i = 0; i < WTBL_SIZE; i++) { + if (prWtbl[i].ucUsed) { + if (EQUAL_MAC_ADDR(pucMacAddress, prWtbl[i].aucMacAddr) + && prWtbl[i].ucPairwise) + return prWtbl[i].ucStaIndex; + } + } + + return STA_REC_INDEX_NOT_FOUND; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] prAdapter Pointer to the Adapter structure + * + * \note + */ +/*----------------------------------------------------------------------------*/ +void secPrivacyDumpWTBL(IN struct ADAPTER *prAdapter) +{ + struct WLAN_TABLE *prWtbl; + uint8_t i; + + prWtbl = prAdapter->rWifiVar.arWtbl; + + DBGLOG(RSN, TRACE, "The Wlan index\n"); + + for (i = 0; i < WTBL_SIZE; i++) { + if (prWtbl[i].ucUsed) + DBGLOG(RSN, TRACE, + "#%d Used=%d BSSIdx=%d keyid=%d P=%d STA=%d Addr=" + MACSTR "\n", i, prWtbl[i].ucUsed, + prWtbl[i].ucBssIndex, prWtbl[i].ucKeyId, + prWtbl[i].ucPairwise, prWtbl[i].ucStaIndex, + MAC2STR(prWtbl[i].aucMacAddr)); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Assin the wlan table with the join AP info + * + * \param[in] prAdapter Pointer to the Adapter structure + * + * \note + */ +/*----------------------------------------------------------------------------*/ +void secPostUpdateAddr(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo) +{ + struct WLAN_TABLE *prWtbl; + + if (IS_BSS_AIS(prBssInfo) && prBssInfo->prStaRecOfAP) { + struct CONNECTION_SETTINGS *prConnSettings = + aisGetConnSettings(prAdapter, + prBssInfo->ucBssIndex); + + if (prConnSettings->eEncStatus == ENUM_ENCRYPTION1_ENABLED) { + + if (prBssInfo->fgBcDefaultKeyExist) { + + prWtbl = + &prAdapter->rWifiVar. + arWtbl[prBssInfo->wepkeyWlanIdx]; + + kalMemCopy(prWtbl->aucMacAddr, + prBssInfo->prStaRecOfAP->aucMacAddr, + MAC_ADDR_LEN); + prWtbl->ucStaIndex = + prBssInfo->prStaRecOfAP->ucIndex; + DBGLOG(RSN, INFO, + "secPostUpdateAddr at [%d] " MACSTR + "= STA Index=%d\n", + prBssInfo->wepkeyWlanIdx, + MAC2STR(prWtbl->aucMacAddr), + prBssInfo->prStaRecOfAP->ucIndex); + + /* Update the wlan table of the prStaRecOfAP */ + prWtbl = + &prAdapter->rWifiVar.arWtbl + [prBssInfo->prStaRecOfAP->ucWlanIndex]; + prWtbl->ucKeyId = prBssInfo->ucBcDefaultKeyIdx; + prBssInfo->prStaRecOfAP->fgTransmitKeyExist = + TRUE; + } + } + if (prConnSettings->eEncStatus == ENUM_ENCRYPTION_DISABLED) { + prWtbl = + &prAdapter->rWifiVar. + arWtbl[prBssInfo->ucBMCWlanIndex]; + + kalMemCopy(prWtbl->aucMacAddr, + prBssInfo->prStaRecOfAP->aucMacAddr, + MAC_ADDR_LEN); + prWtbl->ucStaIndex = prBssInfo->prStaRecOfAP->ucIndex; + DBGLOG(RSN, INFO, "secPostUpdateAddr at [%d] " MACSTR + "= STA Index=%d\n", + prBssInfo->ucBMCWlanIndex, + MAC2STR(prWtbl->aucMacAddr), + prBssInfo->prStaRecOfAP->ucIndex); + } + } +} + +/* return the type of Eapol frame. */ +enum ENUM_EAPOL_KEY_TYPE_T secGetEapolKeyType(uint8_t *pucPkt) +{ + uint8_t *pucEthBody = NULL; + uint8_t ucEapolType; + uint16_t u2EtherTypeLen; + uint8_t ucEthTypeLenOffset = ETHER_HEADER_LEN - ETHER_TYPE_LEN; + uint16_t u2KeyInfo = 0; + + do { + ASSERT_BREAK(pucPkt != NULL); + WLAN_GET_FIELD_BE16(&pucPkt[ucEthTypeLenOffset], + &u2EtherTypeLen); + if (u2EtherTypeLen == ETH_P_VLAN) { + ucEthTypeLenOffset += ETH_802_1Q_HEADER_LEN; + WLAN_GET_FIELD_BE16(&pucPkt[ucEthTypeLenOffset], + &u2EtherTypeLen); + } + if (u2EtherTypeLen != ETH_P_1X) + break; + pucEthBody = &pucPkt[ucEthTypeLenOffset + ETHER_TYPE_LEN]; + ucEapolType = pucEthBody[1]; + if (ucEapolType != 3) /* eapol key type */ + break; + u2KeyInfo = *((uint16_t *) (&pucEthBody[5])); + switch (u2KeyInfo) { + case 0x8a00: + return EAPOL_KEY_1_OF_4; + case 0x0a01: + return EAPOL_KEY_2_OF_4; + case 0xca13: + return EAPOL_KEY_3_OF_4; + case 0x0a03: + return EAPOL_KEY_4_OF_4; + } + } while (FALSE); + + return EAPOL_KEY_NOT_KEY; +} + +void secHandleNoWtbl(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + /* Wtbl error handling. if no Wtbl */ + struct WLAN_ACTION_FRAME *prMgmtHdr = + (struct WLAN_ACTION_FRAME *)prSwRfb->pvHeader; + + prSwRfb->ucStaRecIdx = + secLookupStaRecIndexFromTA(prAdapter, prMgmtHdr->aucSrcAddr); + + prSwRfb->prStaRec = + cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prSwRfb->prStaRec) { + prSwRfb->ucWlanIdx = prSwRfb->prStaRec->ucWlanIndex; + DBGLOG(RX, INFO, + "[%d] current wlan index is %d\n", + prSwRfb->ucStaRecIdx, + prSwRfb->ucWlanIdx); + } else + DBGLOG(RX, TRACE, + "not find station record base on TA\n"); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/qosmap.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/qosmap.c new file mode 100644 index 0000000000000..b5239eabf63b4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/qosmap.c @@ -0,0 +1,281 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "qosmap.c" + * \brief This file including the qosmap related function. + * + * This file provided the macros and functions library support for the + * protocol layer qosmap related function. + * + */ + +/******************************************************************************* + * C O M P I L E 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_PPR2 + +/******************************************************************************* + * 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 process the qos category action frame. + * + * + * \note + * Called by: Handle Rx mgmt request + */ +/*----------------------------------------------------------------------------*/ +void handleQosMapConf(IN struct ADAPTER *prAdapter, IN struct SW_RFB *prSwRfb) +{ + struct WLAN_ACTION_FRAME *prRxFrame; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxFrame = (struct WLAN_ACTION_FRAME *) prSwRfb->pvHeader; + + switch (prRxFrame->ucAction) { + case ACTION_ADDTS_REQ: + case ACTION_ADDTS_RSP: + case ACTION_SCHEDULE: + log_dbg(INIT, INFO, "qos action frame received, action: %d\n", + prRxFrame->ucAction); + break; + case ACTION_QOS_MAP_CONFIGURE: + qosHandleQosMapConfigure(prAdapter, prSwRfb); + log_dbg(INIT, INFO, "qos map configure frame received, action: %d\n", + prRxFrame->ucAction); + break; + default: + log_dbg(INIT, INFO, "qos action frame: %d, try to send to supplicant\n", + prRxFrame->ucAction); + break; + } +} + +int qosHandleQosMapConfigure(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct _ACTION_QOS_MAP_CONFIGURE_FRAME *prRxFrame = NULL; + struct STA_RECORD *prStaRec; + + prRxFrame = + (struct _ACTION_QOS_MAP_CONFIGURE_FRAME *) prSwRfb->pvHeader; + if (!prRxFrame) + return -1; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if ((!prStaRec) || (!prStaRec->fgIsInUse)) + return -1; + + log_dbg(INIT, INFO, + "IEEE 802.11: Received Qos Map Configure Frame from " MACSTR "\n", + MAC2STR(prStaRec->aucMacAddr)); + + qosParseQosMapSet(prAdapter, prStaRec, prRxFrame->qosMapSet); + + return 0; +} + +void qosParseQosMapSet(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN uint8_t *qosMapSet) +{ + uint8_t dscpExcNum = 0; + int i = 0; + uint8_t *tempq = qosMapSet + 2; + uint8_t *qosmapping = prStaRec->qosMapSet; + uint8_t excTable[64]; + + if (IE_ID(qosMapSet) != ELEM_ID_QOS_MAP_SET) { + DBGLOG(INIT, WARN, + "Wrong QosMapSet IE ID: %d\n", IE_ID(qosMapSet)); + return; + } + if ((IE_LEN(qosMapSet) < 16) || (IE_LEN(qosMapSet) > 58)) { + DBGLOG(INIT, WARN, + "Error in QosMapSet IE len: %d\n", IE_LEN(qosMapSet)); + return; + } + + qosMapSetInit(prStaRec); + kalMemSet(excTable, 0, 64); + + dscpExcNum = (IE_LEN(qosMapSet) - WMM_UP_INDEX_NUM * 2) / 2; + for (i = 0; i < dscpExcNum; i++) { + uint8_t dscp = *tempq++; + uint8_t up = *tempq++; + + if (dscp < 64 && up < WMM_UP_INDEX_NUM) { + qosmapping[dscp] = up; + excTable[dscp] = TRUE; + } + } + + for (i = 0; i < WMM_UP_INDEX_NUM; i++) { + uint8_t lDscp = *tempq++; + uint8_t hDscp = *tempq++; + uint8_t dscp; + + if (lDscp == 255 && hDscp == 255) { + log_dbg(INIT, WARN, "UP %d is not used\n", i); + continue; + } + + if (hDscp < lDscp) { + log_dbg(INIT, WARN, "CHECK: UP %d, h %d, l %d\n", + i, hDscp, lDscp); + continue; + } + + for (dscp = lDscp; dscp < 64 && dscp <= hDscp; dscp++) { + if (!excTable[dscp]) + qosmapping[dscp] = i; + } + } + + DBGLOG(INIT, INFO, "QosMapSet DSCP Exception number: %d\n", dscpExcNum); +} + +void qosMapSetInit(IN struct STA_RECORD *prStaRec) +{ + /* DSCP to UP maaping based on RFC8325 in the range 0 to 63 */ + static uint8_t dscp2up[64] = { + [0 ... 63] = 0xFF, + [0] = WMM_UP_BE_INDEX, + [8] = WMM_UP_BK_INDEX, + [10] = WMM_UP_BE_INDEX, + [12] = WMM_UP_BE_INDEX, + [14] = WMM_UP_BE_INDEX, + [16] = WMM_UP_BE_INDEX, + [18] = WMM_UP_EE_INDEX, + [20] = WMM_UP_EE_INDEX, + [22] = WMM_UP_EE_INDEX, + [24] = WMM_UP_CL_INDEX, + [26] = WMM_UP_CL_INDEX, + [28] = WMM_UP_CL_INDEX, + [30] = WMM_UP_CL_INDEX, + [32] = WMM_UP_CL_INDEX, + [34] = WMM_UP_CL_INDEX, + [36] = WMM_UP_CL_INDEX, + [38] = WMM_UP_CL_INDEX, + [40] = WMM_UP_VI_INDEX, + [44] = WMM_UP_VO_INDEX, + [46] = WMM_UP_VO_INDEX, + [48] = WMM_UP_VO_INDEX, + [56] = WMM_UP_NC_INDEX, + }; + + kalMemCopy(prStaRec->qosMapSet, dscp2up, 64); +} + +uint8_t getUpFromDscp(IN struct GLUE_INFO *prGlueInfo, IN int type, IN int dscp) +{ + struct BSS_INFO *prAisBssInfo; + struct STA_RECORD *prStaRec; + + prAisBssInfo = aisGetAisBssInfo( + prGlueInfo->prAdapter, type); + if (prAisBssInfo) + prStaRec = prAisBssInfo->prStaRecOfAP; + else + return 0xFF; + + if (prStaRec && dscp >= 0 && dscp < 64) + return prStaRec->qosMapSet[dscp]; + + return 0xFF; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rate.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rate.c new file mode 100644 index 0000000000000..2f0c9c75fbeee --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rate.c @@ -0,0 +1,364 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + +/******************************************************************************* + * C O M P I L E 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 uint8_t 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_VHT_PHY, /* RATE_VHT_PHY_INDEX */ + RATE_HT_PHY /* RATE_HT_PHY_INDEX */ +}; + +static const uint8_t aucDefaultAckCtsRateIndex[RATE_NUM_SW] = { + RATE_1M_SW_INDEX, /* RATE_1M_SW_INDEX = 0 */ + RATE_2M_SW_INDEX, /* RATE_2M_SW_INDEX */ + RATE_5_5M_SW_INDEX, /* RATE_5_5M_SW_INDEX */ + RATE_11M_SW_INDEX, /* RATE_11M_SW_INDEX */ + RATE_1M_SW_INDEX, /* RATE_22M_SW_INDEX - Not supported */ + RATE_1M_SW_INDEX, /* RATE_33M_SW_INDEX - Not supported */ + RATE_6M_SW_INDEX, /* RATE_6M_SW_INDEX */ + RATE_6M_SW_INDEX, /* RATE_9M_SW_INDEX */ + RATE_12M_SW_INDEX, /* RATE_12M_SW_INDEX */ + RATE_12M_SW_INDEX, /* RATE_18M_SW_INDEX */ + RATE_24M_SW_INDEX, /* RATE_24M_SW_INDEX */ + RATE_24M_SW_INDEX, /* RATE_36M_SW_INDEX */ + RATE_24M_SW_INDEX, /* RATE_48M_SW_INDEX */ + RATE_24M_SW_INDEX /* RATE_54M_SW_INDEX */ +}; + +const u_int8_t afgIsOFDMRate[RATE_NUM_SW] = { + 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 struct IE_SUPPORTED_RATE_IOT *prIeSupportedRate, + IN struct IE_EXT_SUPPORTED_RATE *prIeExtSupportedRate, + OUT uint16_t *pu2OperationalRateSet, + OUT uint16_t *pu2BSSBasicRateSet, + OUT u_int8_t *pfgIsUnknownBSSBasicRate) +{ + uint16_t u2OperationalRateSet = 0; + uint16_t u2BSSBasicRateSet = 0; + u_int8_t fgIsUnknownBSSBasicRate = FALSE; + uint8_t ucRate; + uint32_t i, j; + + 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_SW); + + 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(uint8_t); + j++) { + if (ucRate == aucDataRate[j]) { + u2OperationalRateSet |= BIT(j); + + if (prIeSupportedRate->aucSupportedRates + [i] & RATE_BASIC_BIT) + u2BSSBasicRateSet |= BIT(j); + + break; + } + } + + if ((j == sizeof(aucDataRate) / sizeof(uint8_t)) && + (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(uint8_t); + j++) { + if (ucRate == aucDataRate[j]) { + u2OperationalRateSet |= BIT(j); + + if (prIeExtSupportedRate-> + aucExtSupportedRates[i] + & RATE_BASIC_BIT) + u2BSSBasicRateSet |= BIT(j); + + break; + } + } + + if ((j == sizeof(aucDataRate) / sizeof(uint8_t)) && + (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 uint16_t u2OperationalRateSet, + IN uint16_t u2BSSBasicRateSet, + OUT uint8_t *pucDataRates, + OUT uint8_t *pucDataRatesLen) +{ + uint32_t i, j; + + for (i = RATE_1M_SW_INDEX, j = 0; i < RATE_NUM_SW; i++) { + if (u2OperationalRateSet & BIT(i)) { + + *(pucDataRates + j) = aucDataRate[i]; + + if (u2BSSBasicRateSet & BIT(i)) + *(pucDataRates + j) |= RATE_BASIC_BIT; + + j++; + } + } + + *pucDataRatesLen = (uint8_t) 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rateGetHighestRateIndexFromRateSet(IN uint16_t u2RateSet, + OUT uint8_t *pucHighestRateIndex) +{ + int32_t i; + + for (i = RATE_54M_SW_INDEX; i >= RATE_1M_SW_INDEX; i--) { + if (u2RateSet & BIT(i)) { + *pucHighestRateIndex = (uint8_t) 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rateGetLowestRateIndexFromRateSet(IN uint16_t u2RateSet, + OUT uint8_t *pucLowestRateIndex) +{ + uint32_t i; + + for (i = RATE_1M_SW_INDEX; i <= RATE_54M_SW_INDEX; i++) { + if (u2RateSet & BIT(i)) { + *pucLowestRateIndex = (uint8_t) i; + return TRUE; + } + } + + return FALSE; + +} /* end of rateGetLowestRateIndexFromRateSet() */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/reg_rule.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/reg_rule.c new file mode 100644 index 0000000000000..ebf60705de628 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/reg_rule.c @@ -0,0 +1,336 @@ +/******************************************************************************* + * C O M P I L E 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_SINGLE_SKU == 1) +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) +#include "rlm_domain.h" + +#if 0 +/** + * enum ieee80211_channel_flags - channel flags + * + * Channel flags set by the regulatory control code. + * + * @IEEE80211_CHAN_DISABLED: This channel is disabled. + * @IEEE80211_CHAN_NO_IR: do not initiate radiation, this includes + * sending probe requests or beaconing. + * @IEEE80211_CHAN_RADAR: Radar detection is required on this channel. + * @IEEE80211_CHAN_NO_HT40PLUS: extension channel above this channel + * is not permitted. + * @IEEE80211_CHAN_NO_HT40MINUS: extension channel below this channel + * is not permitted. + * @IEEE80211_CHAN_NO_OFDM: OFDM is not allowed on this channel. + * @IEEE80211_CHAN_NO_80MHZ: If the driver supports 80 MHz on the band, + * this flag indicates that an 80 MHz channel cannot use this + * channel as the control or any of the secondary channels. + * This may be due to the driver or due to regulatory bandwidth + * restrictions. + * @IEEE80211_CHAN_NO_160MHZ: If the driver supports 160 MHz on the band, + * this flag indicates that an 160 MHz channel cannot use this + * channel as the control or any of the secondary channels. + * This may be due to the driver or due to regulatory bandwidth + * restrictions. + * @IEEE80211_CHAN_INDOOR_ONLY: see %NL80211_FREQUENCY_ATTR_INDOOR_ONLY + * @IEEE80211_CHAN_GO_CONCURRENT: see %NL80211_FREQUENCY_ATTR_GO_CONCURRENT + * @IEEE80211_CHAN_NO_20MHZ: 20 MHz bandwidth is not permitted + * on this channel. + * @IEEE80211_CHAN_NO_10MHZ: 10 MHz bandwidth is not permitted + * on this channel. + * + */ +enum ieee80211_channel_flags { + IEEE80211_CHAN_DISABLED = 1<<0, + IEEE80211_CHAN_NO_IR = 1<<1, + /* hole at 1<<2 */ + IEEE80211_CHAN_RADAR = 1<<3, + IEEE80211_CHAN_NO_HT40PLUS = 1<<4, + IEEE80211_CHAN_NO_HT40MINUS = 1<<5, + IEEE80211_CHAN_NO_OFDM = 1<<6, + IEEE80211_CHAN_NO_80MHZ = 1<<7, + IEEE80211_CHAN_NO_160MHZ = 1<<8, + IEEE80211_CHAN_INDOOR_ONLY = 1<<9, + IEEE80211_CHAN_GO_CONCURRENT = 1<<10, + IEEE80211_CHAN_NO_20MHZ = 1<<11, + IEEE80211_CHAN_NO_10MHZ = 1<<12, +}; + +#define IEEE80211_CHAN_NO_HT40 \ + (IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS) + + +struct ieee80211_freq_range { + u32 start_freq_khz; + u32 end_freq_khz; + u32 max_bandwidth_khz; +}; + +struct ieee80211_power_rule { + u32 max_antenna_gain; + u32 max_eirp; +}; + +/** + * enum reg_flags (the same as nl80211_reg_rule_flags) - regulatory rule flags + * + * @NL80211_RRF_NO_OFDM: OFDM modulation not allowed + * @NL80211_RRF_NO_CCK: CCK modulation not allowed + * @NL80211_RRF_NO_INDOOR: indoor operation not allowed + * @NL80211_RRF_NO_OUTDOOR: outdoor operation not allowed + * @NL80211_RRF_DFS: DFS support is required to be used + * @NL80211_RRF_PTP_ONLY: this is only for Point To Point links + * @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links + * @NL80211_RRF_NO_IR: no mechanisms that initiate radiation are allowed, + * this includes probe requests or modes of operation that + * require beaconing. + * @NL80211_RRF_AUTO_BW: maximum available bandwidth should be calculated + * base on contiguous rules and wider channels will be + * allowed to cross multiple contiguous/overlapping + * frequency ranges. + * @NL80211_RRF_IR_CONCURRENT: See &NL80211_FREQUENCY_ATTR_IR_CONCURRENT + * @NL80211_RRF_NO_HT40MINUS: channels can't be used in HT40- operation + * @NL80211_RRF_NO_HT40PLUS: channels can't be used in HT40+ operation + * @NL80211_RRF_NO_80MHZ: 80MHz operation not allowed + * @NL80211_RRF_NO_160MHZ: 160MHz operation not allowed + */ +enum reg_flags { + NL80211_RRF_NO_OFDM = 1<<0, + NL80211_RRF_NO_CCK = 1<<1, + NL80211_RRF_NO_INDOOR = 1<<2, + NL80211_RRF_NO_OUTDOOR = 1<<3, + NL80211_RRF_DFS = 1<<4, + NL80211_RRF_PTP_ONLY = 1<<5, + NL80211_RRF_PTMP_ONLY = 1<<6, + NL80211_RRF_NO_IR = 1<<7, + NL80211_RRF_NO_IBSS = 1<<8, + NL80211_RRF_AUTO_BW = 1<<11, + NL80211_RRF_IR_CONCURRENT = 1<<12, + NL80211_RRF_NO_HT40MINUS = 1<<13, + NL80211_RRF_NO_HT40PLUS = 1<<14, + NL80211_RRF_NO_80MHZ = 1<<15, + NL80211_RRF_NO_160MHZ = 1<<16, +}; + +#define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR +#define NL80211_RRF_NO_IBSS NL80211_RRF_NO_IR +#define NL80211_RRF_NO_IR NL80211_RRF_NO_IR +#define NL80211_RRF_NO_HT40 (NL80211_RRF_NO_HT40MINUS | \ + NL80211_RRF_NO_HT40PLUS) +#define NL80211_RRF_GO_CONCURRENT NL80211_RRF_IR_CONCURRENT + +/* For backport compatibility with older userspace */ +#define NL80211_RRF_NO_IR_ALL (NL80211_RRF_NO_IR | \ + __NL80211_RRF_NO_IBSS) + +struct ieee80211_reg_rule { + struct ieee80211_freq_range freq_range; + struct ieee80211_power_rule power_rule; + u32 reg_flags; /*enum reg_flags*/ + u32 dfs_cac_ms; +}; + +#define MAX_NUMER_REG_RULES 6 + +struct ieee80211_regdomain { + char alpha2[3]; + u32 n_reg_rules; + enum nl80211_dfs_regions dfs_region; + struct ieee80211_reg_rule reg_rules[MAX_NUMER_REG_RULES]; +}; + + +#define MHZ_TO_KHZ(freq) ((freq) * 1000) +#define KHZ_TO_MHZ(freq) ((freq) / 1000) +#define DBI_TO_MBI(gain) ((gain) * 100) +#define MBI_TO_DBI(gain) ((gain) / 100) +#define DBM_TO_MBM(gain) ((gain) * 100) +#define MBM_TO_DBM(gain) ((gain) / 100) + +#define REG_RULE_EXT(start, end, bw, gain, eirp, dfs_cac, reg_flags) \ +{ \ + .freq_range.start_freq_khz = MHZ_TO_KHZ(start), \ + .freq_range.end_freq_khz = MHZ_TO_KHZ(end), \ + .freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw), \ + .power_rule.max_eirp = DBM_TO_MBM(eirp), \ + .flags = reg_flags, \ + .dfs_cac_ms = dfs_cac, \ +} + +#define REG_RULE(start, end, bw, gain, eirp, reg_flags) \ +{ \ + .freq_range.start_freq_khz = MHZ_TO_KHZ(start), \ + .freq_range.end_freq_khz = MHZ_TO_KHZ(end), \ + .freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw), \ + .power_rule.max_antenna_gain = DBI_TO_MBI(gain),\ + .power_rule.max_eirp = DBM_TO_MBM(eirp), \ + .flags = reg_flags, \ +} +#endif + +/*************************************************** + * Here to describe the regulatory rules of yours. + *************************************************** + */ + +/* + * Step1. Decclare struct ieee80211_regdomain + */ +const struct ieee80211_regdomain regdom_us01 = { + .n_reg_rules = 6, + .reg_rules = { + /* channels 1..11 */ + REG_RULE_LIGHT(2412-10, 2462+10, 40, 0), + /* channels 36..48 */ + REG_RULE_LIGHT(5180-10, 5240+10, 40, 0), + /* channels 56..64 */ + REG_RULE_LIGHT(5260-10, 5320+10, 40, KAL_RRF_DFS), + /* channels 100..118 */ + REG_RULE_LIGHT(5500-10, 5590+10, 40, KAL_RRF_DFS), + /* channels 132..140 */ + REG_RULE_LIGHT(5660-10, 5700+10, 40, KAL_RRF_DFS), + /* channels 149..165 */ + REG_RULE_LIGHT(5745-10, 5825+10, 40, 0) } +}; + +const struct ieee80211_regdomain regdom_us = { + .n_reg_rules = 5, + .dfs_region = NL80211_DFS_FCC, + .reg_rules = { + /* channels 1..11 */ + REG_RULE_LIGHT(2412-10, 2462+10, 40, 0), + /* channels 36..48 */ + REG_RULE_LIGHT(5180-10, 5240+10, 80, KAL_RRF_AUTO_BW), + /* channels 52..64 */ + REG_RULE_LIGHT(5260-10, 5320+10, 80, KAL_RRF_DFS | KAL_RRF_AUTO_BW), + /* channels 100..140 */ + REG_RULE_LIGHT(5500-10, 5720+10, 160, KAL_RRF_DFS), + /* channels 149..165 */ + REG_RULE_LIGHT(5745-10, 5825+10, 80, 0) } +}; + +const struct ieee80211_regdomain regdom_cn = { + .n_reg_rules = 4, + .dfs_region = NL80211_DFS_FCC, + .reg_rules = { + /* channels 1..13 */ + REG_RULE_LIGHT(2412-10, 2472+10, 40, 0), + /* channels 36..48 */ + REG_RULE_LIGHT(5180-10, 5240+10, 80, KAL_RRF_AUTO_BW), + /* channels 52..64 */ + REG_RULE_LIGHT(5260-10, 5320+10, 80, KAL_RRF_DFS | KAL_RRF_AUTO_BW), + /* channels 149..165 */ + REG_RULE_LIGHT(5745-10, 5825+10, 80, 0) } +}; + +const struct ieee80211_regdomain regdom_cz_nl = { + .n_reg_rules = 5, + .reg_rules = { + /* channels 1..11 */ + REG_RULE_LIGHT(2412-10, 2462+10, 40, 0), + /* channels 12,13 */ + REG_RULE_LIGHT(2467-10, 2472+10, 40, 0), + /* channels 36..48 */ + REG_RULE_LIGHT(5180-10, 5240+10, 80, 0), + /* channels 52..64 */ + REG_RULE_LIGHT(5260-10, 5320+10, 80, KAL_RRF_DFS), + /* channels 100..140 */ + REG_RULE_LIGHT(5500-10, 5700+10, 160, KAL_RRF_DFS) } +}; + +const struct ieee80211_regdomain regdom_jp = { + .n_reg_rules = 7, + .dfs_region = NL80211_DFS_JP, + .reg_rules = { + /* channels 1..13 */ + REG_RULE_LIGHT(2412-10, 2472+10, 40, 0), + /* channels 14 */ + REG_RULE_LIGHT(2484-10, 2484+10, 20, KAL_RRF_NO_OFDM), + /* channels 184..196 */ + REG_RULE_LIGHT(4920-10, 4980+10, 40, 0), + /* channels 8..16 */ + REG_RULE_LIGHT(5040-10, 5080+10, 40, 0), + /* channels 36..48 */ + REG_RULE_LIGHT(5180-10, 5240+10, 80, KAL_RRF_AUTO_BW), + /* channels 52..64 */ + REG_RULE_LIGHT(5260-10, 5320+10, 80, KAL_RRF_DFS | KAL_RRF_AUTO_BW), + /* channels 100..140 */ + REG_RULE_LIGHT(5500-10, 5700+10, 160, KAL_RRF_DFS) } +}; + +const struct ieee80211_regdomain regdom_tr = { + .n_reg_rules = 4, + .dfs_region = NL80211_DFS_ETSI, + .reg_rules = { + /* channels 1..13 */ + REG_RULE_LIGHT(2412-10, 2472+10, 40, 0), + /* channels 36..48 */ + REG_RULE_LIGHT(5180-10, 5240+10, 80, KAL_RRF_AUTO_BW), + /* channels 52..64 */ + REG_RULE_LIGHT(5260-10, 5320+10, 80, KAL_RRF_DFS | KAL_RRF_AUTO_BW), + /* channels 100..140 */ + REG_RULE_LIGHT(5500-10, 5700+10, 160, KAL_RRF_DFS) } +}; + +/* + * Step2. Decclare struct mtk_regdomain + */ +const struct mtk_regdomain my_regdom_us01 = { + .country_code = "US01", + .prRegdRules = ®dom_us01 +}; + +const struct mtk_regdomain my_regdom_us = { + .country_code = "US", + .prRegdRules = ®dom_us +}; + +const struct mtk_regdomain my_regdom_cn = { + .country_code = "CN", + .prRegdRules = ®dom_cn +}; + +const struct mtk_regdomain my_regdom_nl = { + .country_code = "NL", + .prRegdRules = ®dom_cz_nl +}; + +const struct mtk_regdomain my_regdom_cz = { + .country_code = "CZ", + .prRegdRules = ®dom_cz_nl +}; + +const struct mtk_regdomain my_regdom_jp = { + .country_code = "JP", + .prRegdRules = ®dom_jp +}; + +const struct mtk_regdomain my_regdom_tr = { + .country_code = "TR", + .prRegdRules = ®dom_tr +}; + +/* + * Step3. Register to table + */ +const struct mtk_regdomain *g_prRegRuleTable[] = { + &my_regdom_us01, + &my_regdom_us, + &my_regdom_cn, + &my_regdom_nl, + &my_regdom_cz, + &my_regdom_jp, + &my_regdom_tr, + NULL /* this NULL SHOULD be at the end of the array */ +}; + +#endif +#endif + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rlm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rlm.c new file mode 100644 index 0000000000000..661041cbbe491 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rlm.c @@ -0,0 +1,6588 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rlm.c#3 + */ + +/*! \file "rlm.c" + * \brief + * + */ + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/* Retry limit of sending operation notification frame */ +#define OPERATION_NOTICATION_TX_LIMIT 2 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +enum ENUM_OP_NOTIFY_STATE_T { + OP_NOTIFY_STATE_KEEP = 0, /* Won't change OP mode */ + OP_NOTIFY_STATE_SENDING, /* Sending OP notification frame */ + OP_NOTIFY_STATE_SUCCESS, /* OP notification Tx success */ + OP_NOTIFY_STATE_FAIL, /* OP notification Tx fail(over retry limit)*/ + OP_NOTIFY_STATE_NUM +}; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +/* +** Should Not Force to BW 20 after Channel Switch. +** Enable for DFS Certification +*/ +#ifdef CFG_DFS_CHSW_FORCE_BW20 +u_int8_t g_fgHasChannelSwitchIE = FALSE; +#endif +u_int8_t g_fgHasStopTx = FALSE; + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +struct RLM_CAL_RESULT_ALL_V2 g_rBackupCalDataAllV2; +#endif + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +static void rlmFillHtCapIE(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct MSDU_INFO *prMsduInfo); + +static void rlmFillExtCapIE(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct MSDU_INFO *prMsduInfo); + +static void rlmFillHtOpIE(struct ADAPTER *prAdapter, struct BSS_INFO *prBssInfo, + struct MSDU_INFO *prMsduInfo); + +static uint8_t rlmRecIeInfoForClient(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, uint8_t *pucIE, + uint16_t u2IELength); + +static u_int8_t rlmRecBcnFromNeighborForClient(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct SW_RFB *prSwRfb, + uint8_t *pucIE, + uint16_t u2IELength); + +static u_int8_t rlmRecBcnInfoForClient(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct SW_RFB *prSwRfb, uint8_t *pucIE, + uint16_t u2IELength); + +static void rlmBssReset(struct ADAPTER *prAdapter, struct BSS_INFO *prBssInfo); + +#if CFG_SUPPORT_802_11AC +static void rlmFillVhtCapIE(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct MSDU_INFO *prMsduInfo); +static void rlmFillVhtOpNotificationIE(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct MSDU_INFO *prMsduInfo, + u_int8_t fgIsMaxCap); + +#endif + +/* Operating BW/Nss change and notification */ +static void rlmOpModeTxDoneHandler(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + uint8_t ucOpChangeType, + u_int8_t fgIsSuccess); +static void rlmChangeOwnOpInfo(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo); +static void rlmCompleteOpModeChange(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + u_int8_t fgIsSuccess); +static void rlmRollbackOpChangeParam(struct BSS_INFO *prBssInfo, + u_int8_t fgIsRollbackBw, + u_int8_t fgIsRollbackNss); +static uint8_t rlmGetOpModeBwByVhtAndHtOpInfo(struct BSS_INFO *prBssInfo); +static u_int8_t rlmCheckOpChangeParamValid(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + uint8_t ucChannelWidth, + uint8_t ucOpRxNss, + uint8_t ucOpTxNss); +static void rlmRecOpModeBwForClient(uint8_t ucVhtOpModeChannelWidth, + struct BSS_INFO *prBssInfo); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmFsmEventInit(struct ADAPTER *prAdapter) +{ + ASSERT(prAdapter); + + /* Note: assume struct TIMER structures are reset to zero or stopped + * before invoking this function. + */ + + /* Initialize OBSS FSM */ + rlmObssInit(prAdapter); + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + rlmDomainCheckCountryPowerLimitTable(prAdapter); +#endif + +#ifdef CFG_DFS_CHSW_FORCE_BW20 + g_fgHasChannelSwitchIE = FALSE; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmFsmEventUninit(struct ADAPTER *prAdapter) +{ + struct BSS_INFO *prBssInfo; + uint8_t i; + + ASSERT(prAdapter); + + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + + /* Note: all RLM timers will also be stopped. + * Now only one OBSS scan timer. + */ + rlmBssReset(prAdapter, prBssInfo); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief For association request, power capability + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmReqGeneratePowerCapIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + uint8_t *pucBuffer; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + pucBuffer = + (uint8_t *)(prMsduInfo->prPacket + prMsduInfo->u2FrameLength); + + POWER_CAP_IE(pucBuffer)->ucId = ELEM_ID_PWR_CAP; + POWER_CAP_IE(pucBuffer)->ucLength = ELEM_MAX_LEN_POWER_CAP; + POWER_CAP_IE(pucBuffer)->cMinTxPowerCap = RLM_MIN_TX_PWR; + POWER_CAP_IE(pucBuffer)->cMaxTxPowerCap = RLM_MAX_TX_PWR; + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief For association request, supported channels + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmReqGenerateSupportedChIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + uint8_t *pucBuffer; + struct BSS_INFO *prBssInfo; + struct RF_CHANNEL_INFO auc2gChannelList[MAX_2G_BAND_CHN_NUM]; + struct RF_CHANNEL_INFO auc5gChannelList[MAX_5G_BAND_CHN_NUM]; + uint8_t ucNumOf2gChannel = 0; + uint8_t ucNumOf5gChannel = 0; + uint8_t ucChIdx = 0; + uint8_t ucIdx = 0; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + kalMemZero(&auc2gChannelList[0], sizeof(auc2gChannelList)); + kalMemZero(&auc5gChannelList[0], sizeof(auc5gChannelList)); + + /* We should add supported channels IE in assoc/reassoc request + * if the spectrum management bit is set to 1 in Capability Info + * field, or the connection will be rejected by Marvell APs in + * some TGn items. (e.g. 5.2.3). Spectrum management related + * feature (802.11h) is for 5G band. + */ + if (!prBssInfo || prBssInfo->eBand != BAND_5G) + return; + + pucBuffer = + (uint8_t *)(prMsduInfo->prPacket + prMsduInfo->u2FrameLength); + + rlmDomainGetChnlList(prAdapter, BAND_2G4, TRUE, MAX_2G_BAND_CHN_NUM, + &ucNumOf2gChannel, auc2gChannelList); + rlmDomainGetChnlList(prAdapter, BAND_5G, TRUE, MAX_5G_BAND_CHN_NUM, + &ucNumOf5gChannel, auc5gChannelList); + + SUP_CH_IE(pucBuffer)->ucId = ELEM_ID_SUP_CHS; + SUP_CH_IE(pucBuffer)->ucLength = + (ucNumOf2gChannel + ucNumOf5gChannel) * 2; + + for (ucIdx = 0; ucIdx < ucNumOf2gChannel; ucIdx++, ucChIdx += 2) { + SUP_CH_IE(pucBuffer)->ucChannelNum[ucChIdx] = + auc2gChannelList[ucIdx].ucChannelNum; + SUP_CH_IE(pucBuffer)->ucChannelNum[ucChIdx + 1] = 1; + } + + for (ucIdx = 0; ucIdx < ucNumOf5gChannel; ucIdx++, ucChIdx += 2) { + SUP_CH_IE(pucBuffer)->ucChannelNum[ucChIdx] = + auc5gChannelList[ucIdx].ucChannelNum; + SUP_CH_IE(pucBuffer)->ucChannelNum[ucChIdx + 1] = 1; + } + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief For probe request, association request + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmReqGenerateHtCapIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + 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(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; +#if CFG_SUPPORT_PASSPOINT + struct HS20_INFO *prHS20Info; +#endif + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + +#if CFG_SUPPORT_PASSPOINT + prHS20Info = aisGetHS20Info(prAdapter, + prBssInfo->ucBssIndex); + if (!prHS20Info) + return; +#endif + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & + PHY_TYPE_SET_802_11N) && + (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N))) + rlmFillExtCapIE(prAdapter, prBssInfo, prMsduInfo); +#if CFG_SUPPORT_PASSPOINT + else if (prHS20Info->fgConnectHS20AP == TRUE) + hs20FillExtCapIE(prAdapter, prBssInfo, prMsduInfo); +#endif /* CFG_SUPPORT_PASSPOINT */ +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief For probe response (GO, IBSS) and association response + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmRspGenerateHtCapIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint8_t ucPhyTypeSet; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + if (!IS_BSS_ACTIVE(prBssInfo)) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + /* Decide PHY type set source */ + if (prStaRec) { + /* Get PHY type set from target STA */ + ucPhyTypeSet = prStaRec->ucPhyTypeSet; + } else { + /* Get PHY type set from current BSS */ + ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + } + + if (RLM_NET_IS_11N(prBssInfo) && + (ucPhyTypeSet & PHY_TYPE_SET_802_11N) && + (!prBssInfo->fgIsWepCipherGroup)) + rlmFillHtCapIE(prAdapter, prBssInfo, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief For probe response (GO, IBSS) and association response + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmRspGenerateExtCapIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint8_t ucPhyTypeSet; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + if (!IS_BSS_ACTIVE(prBssInfo)) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + /* Decide PHY type set source */ + if (prStaRec) { + /* Get PHY type set from target STA */ + ucPhyTypeSet = prStaRec->ucPhyTypeSet; + } else { + /* Get PHY type set from current BSS */ + ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + } + + if (RLM_NET_IS_11N(prBssInfo) && (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(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint8_t ucPhyTypeSet; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + if (!IS_BSS_ACTIVE(prBssInfo)) + return; + + /* Decide PHY type set source */ + if (prStaRec) { + /* Get PHY type set from target STA */ + ucPhyTypeSet = prStaRec->ucPhyTypeSet; + } else { + /* Get PHY type set from current BSS */ + ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + } + + if (RLM_NET_IS_11N(prBssInfo) && + (ucPhyTypeSet & PHY_TYPE_SET_802_11N) && + (!prBssInfo->fgIsWepCipherGroup)) + rlmFillHtOpIE(prAdapter, prBssInfo, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief For probe response (GO, IBSS) and association response + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmRspGenerateErpIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + struct IE_ERP *prErpIe; + uint8_t ucPhyTypeSet; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + if (!IS_BSS_ACTIVE(prBssInfo)) + return; + + /* Decide PHY type set source */ + if (prStaRec) { + /* Get PHY type set from target STA */ + ucPhyTypeSet = prStaRec->ucPhyTypeSet; + } else { + /* Get PHY type set from current BSS */ + ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + } + + if (RLM_NET_IS_11GN(prBssInfo) && prBssInfo->eBand == BAND_2G4 && + (ucPhyTypeSet & PHY_TYPE_SET_802_11GN)) { + prErpIe = (struct IE_ERP *)(((uint8_t *)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); + } +} + +#if CFG_SUPPORT_MTK_SYNERGY +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is used to generate MTK Vendor Specific OUI + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmGenerateMTKOuiIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + uint8_t *pucBuffer; + uint8_t aucMtkOui[] = VENDOR_OUI_MTK; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + if (prAdapter->rWifiVar.ucMtkOui == FEATURE_DISABLED) + return; + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + pucBuffer = (uint8_t *)((unsigned long)prMsduInfo->prPacket + + (unsigned long)prMsduInfo->u2FrameLength); + + MTK_OUI_IE(pucBuffer)->ucId = ELEM_ID_VENDOR; + MTK_OUI_IE(pucBuffer)->ucLength = ELEM_MIN_LEN_MTK_OUI; + MTK_OUI_IE(pucBuffer)->aucOui[0] = aucMtkOui[0]; + MTK_OUI_IE(pucBuffer)->aucOui[1] = aucMtkOui[1]; + MTK_OUI_IE(pucBuffer)->aucOui[2] = aucMtkOui[2]; + MTK_OUI_IE(pucBuffer)->aucCapability[0] = + MTK_SYNERGY_CAP0 & (prAdapter->rWifiVar.aucMtkFeature[0]); + MTK_OUI_IE(pucBuffer)->aucCapability[1] = + MTK_SYNERGY_CAP1 & (prAdapter->rWifiVar.aucMtkFeature[1]); + MTK_OUI_IE(pucBuffer)->aucCapability[2] = + MTK_SYNERGY_CAP2 & (prAdapter->rWifiVar.aucMtkFeature[2]); + MTK_OUI_IE(pucBuffer)->aucCapability[3] = + MTK_SYNERGY_CAP3 & (prAdapter->rWifiVar.aucMtkFeature[3]); + + /* Disable the 2.4G 256QAM feature bit if chip doesn't support AC*/ + if (prAdapter->rWifiVar.ucHwNotSupportAC) { + MTK_OUI_IE(pucBuffer)->aucCapability[0] &= + ~(MTK_SYNERGY_CAP_SUPPORT_24G_MCS89); + DBGLOG(INIT, WARN, + "Disable 2.4G 256QAM support if N only chip\n"); + } + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); +} /* rlmGenerateMTKOuiIE */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is used to check MTK Vendor Specific OUI + * + * + * @return true: correct MTK OUI + * false: incorrect MTK OUI + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rlmParseCheckMTKOuiIE(IN struct ADAPTER *prAdapter, IN uint8_t *pucBuf, + IN uint32_t *pu4Cap) +{ + uint8_t aucMtkOui[] = VENDOR_OUI_MTK; + struct IE_MTK_OUI *prMtkOuiIE = (struct IE_MTK_OUI *)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL)); + + prMtkOuiIE = (struct IE_MTK_OUI *)pucBuf; + + if (prAdapter->rWifiVar.ucMtkOui == FEATURE_DISABLED) + break; + else if (IE_LEN(pucBuf) < ELEM_MIN_LEN_MTK_OUI) + break; + else if (prMtkOuiIE->aucOui[0] != aucMtkOui[0] || + prMtkOuiIE->aucOui[1] != aucMtkOui[1] || + prMtkOuiIE->aucOui[2] != aucMtkOui[2]) + break; + /* apply NvRam setting */ + prMtkOuiIE->aucCapability[0] = + prMtkOuiIE->aucCapability[0] & + (prAdapter->rWifiVar.aucMtkFeature[0]); + prMtkOuiIE->aucCapability[1] = + prMtkOuiIE->aucCapability[1] & + (prAdapter->rWifiVar.aucMtkFeature[1]); + prMtkOuiIE->aucCapability[2] = + prMtkOuiIE->aucCapability[2] & + (prAdapter->rWifiVar.aucMtkFeature[2]); + prMtkOuiIE->aucCapability[3] = + prMtkOuiIE->aucCapability[3] & + (prAdapter->rWifiVar.aucMtkFeature[3]); + + /* Disable the 2.4G 256QAM feature bit if chip doesn't support + * AC. Otherwise, FW would choose wrong max rate of auto rate. + */ + if (prAdapter->rWifiVar.ucHwNotSupportAC) { + prMtkOuiIE->aucCapability[0] &= + ~(MTK_SYNERGY_CAP_SUPPORT_24G_MCS89); + DBGLOG(INIT, WARN, + "Disable 2.4G 256QAM support if N only chip\n"); + } + + kalMemCopy(pu4Cap, prMtkOuiIE->aucCapability, sizeof(uint32_t)); + + return TRUE; + } while (FALSE); + + return FALSE; +} /* rlmParseCheckMTKOuiIE */ + +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmGenerateCsaIE(struct ADAPTER *prAdapter, struct MSDU_INFO *prMsduInfo) +{ + uint8_t *pucBuffer; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + if (prAdapter->rWifiVar.fgCsaInProgress) { + + pucBuffer = + (uint8_t *)((unsigned long)prMsduInfo->prPacket + + (unsigned long)prMsduInfo->u2FrameLength); + + CSA_IE(pucBuffer)->ucId = ELEM_ID_CH_SW_ANNOUNCEMENT; + CSA_IE(pucBuffer)->ucLength = ELEM_MIN_LEN_CSA; + CSA_IE(pucBuffer)->ucChannelSwitchMode = + prAdapter->rWifiVar.ucChannelSwitchMode; + CSA_IE(pucBuffer)->ucNewChannelNum = + prAdapter->rWifiVar.ucNewChannelNumber; + CSA_IE(pucBuffer)->ucChannelSwitchCount = + prAdapter->rWifiVar.ucChannelSwitchCount; + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static void rlmFillHtCapIE(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct MSDU_INFO *prMsduInfo) +{ + struct IE_HT_CAP *prHtCap; + struct SUP_MCS_SET_FIELD *prSupMcsSet; + u_int8_t fg40mAllowed; + uint8_t ucIdx; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(prMsduInfo); + + fg40mAllowed = prBssInfo->fgAssoc40mBwAllowed; + + prHtCap = (struct IE_HT_CAP *)(((uint8_t *)prMsduInfo->prPacket) + + prMsduInfo->u2FrameLength); + + /* Add HT capabilities IE */ + prHtCap->ucId = ELEM_ID_HT_CAP; + prHtCap->ucLength = sizeof(struct IE_HT_CAP) - ELEM_HDR_LEN; + + prHtCap->u2HtCapInfo = HT_CAP_INFO_DEFAULT_VAL; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxShortGI)) + prHtCap->u2HtCapInfo |= + (HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxLdpc)) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_LDPC_CAP; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucTxStbc) && + prBssInfo->ucOpTxNss >= 2) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_TX_STBC; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxStbc)) { + + uint8_t tempRxStbcNss; + + tempRxStbcNss = prAdapter->rWifiVar.ucRxStbcNss; + tempRxStbcNss = + (tempRxStbcNss > + wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex)) + ? wlanGetSupportNss(prAdapter, + prBssInfo->ucBssIndex) + : (tempRxStbcNss); + if (tempRxStbcNss != prAdapter->rWifiVar.ucRxStbcNss) { + DBGLOG(RLM, WARN, "Apply Nss:%d as RxStbcNss in HT Cap", + wlanGetSupportNss(prAdapter, + prBssInfo->ucBssIndex)); + DBGLOG(RLM, WARN, + " due to set RxStbcNss more than Nss is not appropriate.\n"); + } + if (tempRxStbcNss == 1) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_RX_STBC_1_SS; + else if (tempRxStbcNss == 2) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_RX_STBC_2_SS; + else if (tempRxStbcNss >= 3) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_RX_STBC_3_SS; + } + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxGf)) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + + if (prAdapter->rWifiVar.ucRxMaxMpduLen > VHT_CAP_INFO_MAX_MPDU_LEN_3K) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_MAX_AMSDU_LEN; + + if (!fg40mAllowed) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | + HT_CAP_INFO_SHORT_GI_40M | + HT_CAP_INFO_DSSS_CCK_IN_40M); + + /* SM power saving (IEEE 802.11, 2016, 10.2.4) + * A non-AP HT STA may also use SM Power Save bits in the HT + * Capabilities element of its Association Request to achieve + * the same purpose. The latter allows the STA to use only a + * single receive chain immediately after association. + */ + if (prBssInfo->ucOpRxNss < + wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex)) + prHtCap->u2HtCapInfo &= + ~HT_CAP_INFO_SM_POWER_SAVE; /*Set as static power save*/ + + prHtCap->ucAmpduParam = AMPDU_PARAM_DEFAULT_VAL; + + prSupMcsSet = &prHtCap->rSupMcsSet; + kalMemZero((void *)&prSupMcsSet->aucRxMcsBitmask[0], + SUP_MCS_RX_BITMASK_OCTET_NUM); + + for (ucIdx = 0; + ucIdx < wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex); + ucIdx++) + prSupMcsSet->aucRxMcsBitmask[ucIdx] = BITS(0, 7); + + /* prSupMcsSet->aucRxMcsBitmask[0] = BITS(0, 7); */ + + if (fg40mAllowed && IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucMCS32)) + 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; + if ((prAdapter->rWifiVar.eDbdcMode == ENUM_DBDC_MODE_DISABLED) || + (prBssInfo->eBand == BAND_5G)) { + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaHtBfee)) + prHtCap->u4TxBeamformingCap = TX_BEAMFORMING_CAP_BFEE; + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaHtBfer)) + prHtCap->u4TxBeamformingCap |= TX_BEAMFORMING_CAP_BFER; + } + + 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(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct MSDU_INFO *prMsduInfo) +{ +#if CFG_SUPPORT_PASSPOINT + struct IE_HS20_EXT_CAP_T *prHsExtCap; + struct HS20_INFO *prHS20Info; +#else + struct IE_EXT_CAP *prExtCap; +#endif + u_int8_t fg40mAllowed, fgAppendVhtCap; + struct STA_RECORD *prStaRec; + struct CONNECTION_SETTINGS *prConnSettings; + const uint8_t *extCapConn; + uint32_t extCapIeLen = 0; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + fg40mAllowed = prBssInfo->fgAssoc40mBwAllowed; + prConnSettings = aisGetConnSettings(prAdapter, prBssInfo->ucBssIndex); + extCapConn = kalFindIeMatchMask(ELEM_ID_EXTENDED_CAP, + prConnSettings->pucAssocIEs, + prConnSettings->assocIeLen, + NULL, 0, 0, NULL); + if (extCapConn) { + extCapIeLen = ELEM_HDR_LEN + RSN_IE(extCapConn)->ucLength; + DBGLOG_MEM8(SAA, INFO, extCapConn, extCapIeLen); + } + +#if CFG_SUPPORT_PASSPOINT + prHS20Info = aisGetHS20Info(prAdapter, + prBssInfo->ucBssIndex); + if (!prHS20Info) + return; + + prHsExtCap = + (struct IE_HS20_EXT_CAP_T *)(((uint8_t *)prMsduInfo->prPacket) + + prMsduInfo->u2FrameLength); + prHsExtCap->ucId = ELEM_ID_EXTENDED_CAP; + + if (prHS20Info->fgConnectHS20AP == TRUE) + prHsExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + else + prHsExtCap->ucLength = 3 - ELEM_HDR_LEN; + + kalMemZero(prHsExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP); + + prHsExtCap->aucCapabilities[0] = ELEM_EXT_CAP_DEFAULT_VAL; + + if (!fg40mAllowed) + prHsExtCap->aucCapabilities[0] &= + ~ELEM_EXT_CAP_20_40_COEXIST_SUPPORT; + + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + prHsExtCap->aucCapabilities[0] &= ~ELEM_EXT_CAP_PSMP_CAP; + +#if CFG_SUPPORT_802_11AC + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + fgAppendVhtCap = FALSE; + + /* Check append rule */ + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet + & PHY_TYPE_SET_802_11AC) { + /* Note: For AIS connecting state, + * structure in BSS_INFO will not be inited + * So, we check StaRec instead of BssInfo + */ + if (prStaRec) { + if (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11AC) + fgAppendVhtCap = TRUE; + } else if (RLM_NET_IS_11AC(prBssInfo) && + ((prBssInfo->eCurrentOPMode == + OP_MODE_INFRASTRUCTURE) || + (prBssInfo->eCurrentOPMode == + OP_MODE_ACCESS_POINT))) { + fgAppendVhtCap = TRUE; + } + + } + + if (fgAppendVhtCap) { + if (prHsExtCap->ucLength < ELEM_MAX_LEN_EXT_CAP) + prHsExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + + SET_EXT_CAP(prHsExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, + ELEM_EXT_CAP_OP_MODE_NOTIFICATION_BIT); + } +#endif + + if (prHS20Info->fgConnectHS20AP == TRUE) { + SET_EXT_CAP(prHsExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, + ELEM_EXT_CAP_INTERWORKING_BIT); + SET_EXT_CAP(prHsExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, + ELEM_EXT_CAP_QOSMAPSET_BIT); + SET_EXT_CAP(prHsExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, + ELEM_EXT_CAP_BSS_TRANSITION_BIT); + /* For R2 WNM-Notification */ + SET_EXT_CAP(prHsExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, + ELEM_EXT_CAP_WNM_NOTIFICATION_BIT); + } + +#if CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT + prHsExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + SET_EXT_CAP(prHsExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, + ELEM_EXT_CAP_BSS_TRANSITION_BIT); +#endif + +#if (CFG_SUPPORT_802_11V_MBSSID == 1) + if (prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) { + prExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + SET_EXT_CAP(prHsExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, + ELEM_EXT_CAP_MBSSID_BIT); + } +#endif + + if ((extCapIeLen - ELEM_HDR_LEN) > prHsExtCap->ucLength) + prHsExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + + if (extCapConn) + rlmSyncExtCapIEwithSupplicant(prHsExtCap->aucCapabilities, + extCapConn, extCapIeLen); + else + DBGLOG(RLM, WARN, "extCapConn = NULL!"); + + ASSERT(IE_SIZE(prHsExtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP)); + + prMsduInfo->u2FrameLength += IE_SIZE(prHsExtCap); + +#else + /* Add Extended Capabilities IE */ + prExtCap = (struct IE_EXT_CAP *)(((uint8_t *)prMsduInfo->prPacket) + + prMsduInfo->u2FrameLength); + + prExtCap->ucId = ELEM_ID_EXTENDED_CAP; + + prExtCap->ucLength = 3 - ELEM_HDR_LEN; + kalMemZero(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP); + + 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; + +#if CFG_SUPPORT_802_11AC + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + fgAppendVhtCap = FALSE; + + /* Check append rule */ + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet + & PHY_TYPE_SET_802_11AC) { + /* Note: For AIS connecting state, + * structure in BSS_INFO will not be inited + * So, we check StaRec instead of BssInfo + */ + if (prStaRec) { + if (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11AC) + fgAppendVhtCap = TRUE; + } else if (RLM_NET_IS_11AC(prBssInfo) && + ((prBssInfo->eCurrentOPMode == + OP_MODE_INFRASTRUCTURE) || + (prBssInfo->eCurrentOPMode == + OP_MODE_ACCESS_POINT))) { + fgAppendVhtCap = TRUE; + } + } + + if (fgAppendVhtCap) { + if (prExtCap->ucLength < ELEM_MAX_LEN_EXT_CAP) + prExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, + ELEM_EXT_CAP_OP_MODE_NOTIFICATION_BIT); + } +#endif + +#if (CFG_SUPPORT_TWT == 1) + prExtCap->aucCapabilities[ELEM_EXT_CAP_TWT_REQUESTER_BIT >> 3] |= + BIT(ELEM_EXT_CAP_TWT_REQUESTER_BIT % 8); +#endif + +#if CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT + prExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, + ELEM_EXT_CAP_BSS_TRANSITION_BIT); +#endif + +#if (CFG_SUPPORT_802_11V_MBSSID == 1) + if (prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) { + prExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, + ELEM_EXT_CAP_MBSSID_BIT); + } +#endif + +#if (CFG_SUPPORT_802_11AX == 1) + if ((prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) + && (prBssInfo->eBand == BAND_2G4) + && !RLM_NET_IS_11AX(prBssInfo)) + prExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP_11ABGNAC; +#endif + + if ((extCapIeLen - ELEM_HDR_LEN) > prExtCap->ucLength) + prExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + + if (extCapConn) + rlmSyncExtCapIEwithSupplicant(prExtCap->aucCapabilities, + extCapConn, extCapIeLen); + else + DBGLOG(RLM, WARN, "extCapConn = NULL!"); + + ASSERT(IE_SIZE(prExtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP)); + + prMsduInfo->u2FrameLength += IE_SIZE(prExtCap); +#endif +} + +void rlmSyncExtCapIEwithSupplicant(uint8_t *aucCapabilities, + const uint8_t *supExtCapIEs, size_t IElen) { + uint32_t i; + + for (i = ELEM_HDR_LEN * 8; i < IElen * 8; i++) { + if (supExtCapIEs[i / 8] & BIT(i % 8)) { + SET_EXT_CAP(aucCapabilities, ELEM_MAX_LEN_EXT_CAP, + i-ELEM_HDR_LEN*8); + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static void rlmFillHtOpIE(struct ADAPTER *prAdapter, struct BSS_INFO *prBssInfo, + struct MSDU_INFO *prMsduInfo) +{ + struct IE_HT_OP *prHtOp; + uint16_t i; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(prMsduInfo); + + prHtOp = (struct IE_HT_OP *)(((uint8_t *)prMsduInfo->prPacket) + + prMsduInfo->u2FrameLength); + + /* Add HT operation IE */ + prHtOp->ucId = ELEM_ID_HT_OP; + prHtOp->ucLength = sizeof(struct IE_HT_OP) - 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 = (uint8_t)HT_PROTECT_MODE_NON_HT; + else if (prBssInfo->eObssHtProtectMode == HT_PROTECT_MODE_NON_MEMBER) + prHtOp->u2Info2 = (uint8_t)HT_PROTECT_MODE_NON_MEMBER; + else { + /* It may be SYS_PROTECT_MODE_NONE or SYS_PROTECT_MODE_20M */ + prHtOp->u2Info2 = (uint8_t)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); +} + +#if CFG_SUPPORT_802_11AC + +/*----------------------------------------------------------------------------*/ +/*! + * \brief For probe request, association request + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmReqGenerateVhtCapIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; +#if CFG_SUPPORT_VHT_IE_IN_2G + struct BSS_DESC *prBssDesc = NULL; + u_int8_t fgIsVHTPresent = FALSE; +#endif + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + if (prAdapter) { + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; +#if CFG_SUPPORT_VHT_IE_IN_2G + prBssDesc = aisGetTargetBssDesc(prAdapter, + prMsduInfo->ucBssIndex); + if (prBssDesc) { + fgIsVHTPresent = prBssDesc->fgIsVHTPresent; + DBGLOG(RLM, TRACE, + "fgIsVHTPresent=%d", fgIsVHTPresent); + } +#endif + } else { + DBGLOG(RLM, ERROR, "prAdapter is NULL, return!"); + return; + } + + if (!prBssInfo) { + DBGLOG(RLM, ERROR, "prBssInfo is NULL, return!"); + return; + } + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (!prStaRec) { + DBGLOG(RLM, ERROR, "prStaRec is NULL, return!"); + return; + } + + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AC) + && (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11AC)) + rlmFillVhtCapIE(prAdapter, prBssInfo, prMsduInfo); +#if CFG_SUPPORT_VHT_IE_IN_2G + else if ((prBssInfo->eBand == BAND_2G4) && + (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N) && + ((prAdapter->rWifiVar.ucVhtIeIn2g + == FEATURE_FORCE_ENABLED) || + ((prAdapter->rWifiVar.ucVhtIeIn2g + == FEATURE_ENABLED) && fgIsVHTPresent))) { + DBGLOG(RLM, TRACE, + "Add VHT IE in 2.4G, ucPhyTypeSet=%02x, ucVhtIeIn2g=%02x", + prStaRec->ucPhyTypeSet, + prAdapter->rWifiVar.ucVhtIeIn2g); + rlmFillVhtCapIE(prAdapter, prBssInfo, prMsduInfo); + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief For probe response (GO, IBSS) and association response + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmRspGenerateVhtCapIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint8_t ucPhyTypeSet; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + if (!IS_BSS_ACTIVE(prBssInfo)) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + /* Decide PHY type set source */ + if (prStaRec) { + /* Get PHY type set from target STA */ + ucPhyTypeSet = prStaRec->ucPhyTypeSet; + } else { + /* Get PHY type set from current BSS */ + ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + } + + if (RLM_NET_IS_11AC(prBssInfo) && + (ucPhyTypeSet & PHY_TYPE_SET_802_11AC)) + rlmFillVhtCapIE(prAdapter, prBssInfo, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmRspGenerateVhtOpIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint8_t ucPhyTypeSet; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + if (!IS_BSS_ACTIVE(prBssInfo)) + return; + + /* Decide PHY type set source */ + if (prStaRec) { + /* Get PHY type set from target STA */ + ucPhyTypeSet = prStaRec->ucPhyTypeSet; + } else { + /* Get PHY type set from current BSS */ + ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + } + + if (RLM_NET_IS_11AC(prBssInfo) && + (ucPhyTypeSet & PHY_TYPE_SET_802_11AC)) + rlmFillVhtOpIE(prAdapter, prBssInfo, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief For probe request, association request + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmReqGenerateVhtOpNotificationIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + /* [TGac 5.2.46 STBC Receive Test with UCC 9.2.x] + * Operating Notification IE of Nss=2 will make Ralink testbed send data + * frames without STBC + * Enable the Operating Notification IE only for DBDC enable case. + */ + if (!prAdapter->rWifiVar.fgDbDcModeEn) + return; + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & + PHY_TYPE_SET_802_11AC) && + (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11AC))) { + /* Fill own capability in channel width field in OP mode element + * since we haven't filled in channel width info in BssInfo at + * current state + */ + rlmFillVhtOpNotificationIE(prAdapter, prBssInfo, prMsduInfo, + TRUE); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmRspGenerateVhtOpNotificationIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint8_t ucPhyTypeSet; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + if (!IS_BSS_ACTIVE(prBssInfo)) + return; + + if (!prBssInfo->fgIsOpChangeRxNss) + return; + + /* Decide PHY type set source */ + if (prStaRec) { + /* Get PHY type set from target STA */ + ucPhyTypeSet = prStaRec->ucPhyTypeSet; + } else { + /* Get PHY type set from current BSS */ + ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + } + + if (RLM_NET_IS_11AC(prBssInfo) && + (ucPhyTypeSet & PHY_TYPE_SET_802_11AC)) + rlmFillVhtOpNotificationIE(prAdapter, prBssInfo, prMsduInfo, + FALSE); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * add VHT operation notification IE for VHT-BW40 case specific + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static void rlmFillVhtOpNotificationIE(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct MSDU_INFO *prMsduInfo, + u_int8_t fgIsOwnCap) +{ + struct IE_VHT_OP_MODE_NOTIFICATION *prVhtOpMode; + uint8_t ucOpModeBw = VHT_OP_MODE_CHANNEL_WIDTH_20; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(prMsduInfo); + + prVhtOpMode = (struct IE_VHT_OP_MODE_NOTIFICATION + *)(((uint8_t *)prMsduInfo->prPacket) + + prMsduInfo->u2FrameLength); + + kalMemZero((void *)prVhtOpMode, + sizeof(struct IE_VHT_OP_MODE_NOTIFICATION)); + + prVhtOpMode->ucId = ELEM_ID_OP_MODE; + prVhtOpMode->ucLength = + sizeof(struct IE_VHT_OP_MODE_NOTIFICATION) - ELEM_HDR_LEN; + + DBGLOG(RLM, TRACE, "rlmFillVhtOpNotificationIE(%d) %u %u\n", + prBssInfo->ucBssIndex, fgIsOwnCap, prBssInfo->ucOpRxNss); + + if (fgIsOwnCap) { + ucOpModeBw = cnmGetDbdcBwCapability(prAdapter, + prBssInfo->ucBssIndex); + + /*handle 80P80 case*/ + if (ucOpModeBw >= MAX_BW_160MHZ) + ucOpModeBw = VHT_OP_MODE_CHANNEL_WIDTH_160_80P80; + + prVhtOpMode->ucOperatingMode |= ucOpModeBw; + prVhtOpMode->ucOperatingMode |= + (((prBssInfo->ucOpRxNss - 1) + << VHT_OP_MODE_RX_NSS_OFFSET) & + VHT_OP_MODE_RX_NSS); + + } else { + + ucOpModeBw = rlmGetOpModeBwByVhtAndHtOpInfo(prBssInfo); + + prVhtOpMode->ucOperatingMode |= ucOpModeBw; + prVhtOpMode->ucOperatingMode |= + (((prBssInfo->ucOpRxNss - 1) + << VHT_OP_MODE_RX_NSS_OFFSET) & + VHT_OP_MODE_RX_NSS); + } + + prMsduInfo->u2FrameLength += IE_SIZE(prVhtOpMode); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static void rlmFillVhtCapIE(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct MSDU_INFO *prMsduInfo) +{ + struct IE_VHT_CAP *prVhtCap; + struct VHT_SUPPORTED_MCS_FIELD *prVhtSupportedMcsSet; + uint8_t i; + uint8_t ucMaxBw; + struct STA_RECORD *prStaRec; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(prMsduInfo); + + prVhtCap = (struct IE_VHT_CAP *)(((uint8_t *)prMsduInfo->prPacket) + + prMsduInfo->u2FrameLength); + + prVhtCap->ucId = ELEM_ID_VHT_CAP; + prVhtCap->ucLength = sizeof(struct IE_VHT_CAP) - ELEM_HDR_LEN; + prVhtCap->u4VhtCapInfo = VHT_CAP_INFO_DEFAULT_VAL; + + ucMaxBw = cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex); + + prVhtCap->u4VhtCapInfo |= (prAdapter->rWifiVar.ucRxMaxMpduLen & + VHT_CAP_INFO_MAX_MPDU_LEN_MASK); +#if CFG_SUPPORT_VHT_IE_IN_2G + if (prBssInfo->eBand == BAND_2G4) { + prVhtCap->u4VhtCapInfo |= + VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_SET_NONE; + } else { +#endif + if (ucMaxBw == MAX_BW_160MHZ) + prVhtCap->u4VhtCapInfo |= + VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_SET_160; + else if (ucMaxBw == MAX_BW_80_80_MHZ) + prVhtCap->u4VhtCapInfo |= + VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_SET_160_80P80; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaVhtBfee)) { + prVhtCap->u4VhtCapInfo |= FIELD_VHT_CAP_INFO_BFEE; +#if CFG_SUPPORT_BFEE + prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + + if (prStaRec && + (prStaRec->ucVhtCapNumSoundingDimensions == 0x2) && + !prAdapter->rWifiVar.fgForceSTSNum) { + /* For the compatibility with netgear R7000 AP */ + prVhtCap->u4VhtCapInfo |= + (((uint32_t)prStaRec->ucVhtCapNumSoundingDimensions) +<< VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF_BEAMFORMER_ANTENNAS_SUP_OFF); + DBGLOG(RLM, INFO, "Set VHT Cap BFEE STS CAP=%d\n", + prStaRec->ucVhtCapNumSoundingDimensions); + } else { + /* For 11ac cert. VHT-5.2.63C MU-BFee step3, + * it requires STAUT to set its maximum STS capability here + */ + prVhtCap->u4VhtCapInfo |= +VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF_BEAMFORMER_ANTENNAS_4_SUP; + DBGLOG(RLM, TRACE, "Set VHT Cap BFEE STS CAP=%d\n", + VHT_CAP_INFO_BEAMFORMEE_STS_CAP_MAX); + } +/* DBGLOG(RLM, INFO, "VhtCapInfo=%x\n", prVhtCap->u4VhtCapInfo); */ +#endif + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaVhtMuBfee)) + prVhtCap->u4VhtCapInfo |= + VHT_CAP_INFO_MU_BEAMFOMEE_CAPABLE; + } + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaVhtBfer)) + prVhtCap->u4VhtCapInfo |= FIELD_VHT_CAP_INFO_BFER; +#if CFG_SUPPORT_VHT_IE_IN_2G + } +#endif + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxShortGI)) { + if (ucMaxBw >= MAX_BW_80MHZ) + prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_SHORT_GI_80; + + if (ucMaxBw >= MAX_BW_160MHZ) + prVhtCap->u4VhtCapInfo |= + VHT_CAP_INFO_SHORT_GI_160_80P80; + } + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxLdpc)) + prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_RX_LDPC; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxStbc)) { + uint8_t tempRxStbcNss; + + if (prAdapter->rWifiVar.u4SwTestMode == + ENUM_SW_TEST_MODE_SIGMA_AC) { + tempRxStbcNss = 1; + DBGLOG(RLM, INFO, + "Set RxStbcNss to 1 for 11ac certification.\n"); + } else { + tempRxStbcNss = prAdapter->rWifiVar.ucRxStbcNss; + tempRxStbcNss = + (tempRxStbcNss > + wlanGetSupportNss(prAdapter, + prBssInfo->ucBssIndex)) + ? wlanGetSupportNss( + prAdapter, + prBssInfo->ucBssIndex) + : (tempRxStbcNss); + if (tempRxStbcNss != prAdapter->rWifiVar.ucRxStbcNss) { + DBGLOG(RLM, WARN, + "Apply Nss:%d as RxStbcNss in VHT Cap", + wlanGetSupportNss( + prAdapter, + prBssInfo->ucBssIndex)); + DBGLOG(RLM, WARN, + "due to set RxStbcNss more than Nss is not appropriate.\n"); + } + } + prVhtCap->u4VhtCapInfo |= + ((tempRxStbcNss << VHT_CAP_INFO_RX_STBC_OFFSET) & + VHT_CAP_INFO_RX_STBC_MASK); + } + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucTxStbc) && + prBssInfo->ucOpTxNss >= 2) + prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_TX_STBC; + + /*set MCS map */ + prVhtSupportedMcsSet = &prVhtCap->rVhtSupportedMcsSet; + kalMemZero((void *)prVhtSupportedMcsSet, + sizeof(struct VHT_SUPPORTED_MCS_FIELD)); + + for (i = 0; i < 8; i++) { + uint8_t ucOffset = i * 2; + uint8_t ucMcsMap; + + if (i < wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex)) + ucMcsMap = VHT_CAP_INFO_MCS_MAP_MCS9; + else + ucMcsMap = VHT_CAP_INFO_MCS_NOT_SUPPORTED; + + prVhtSupportedMcsSet->u2RxMcsMap |= (ucMcsMap << ucOffset); + prVhtSupportedMcsSet->u2TxMcsMap |= (ucMcsMap << ucOffset); + } + +#if 0 + for (i = 0; i < wlanGetSupportNss(prAdapter, + prBssInfo->ucBssIndex); i++) { + uint8_t ucOffset = i * 2; + + prVhtSupportedMcsSet->u2RxMcsMap &= + ((VHT_CAP_INFO_MCS_MAP_MCS9 << ucOffset) & + BITS(ucOffset, ucOffset + 1)); + prVhtSupportedMcsSet->u2TxMcsMap &= + ((VHT_CAP_INFO_MCS_MAP_MCS9 << ucOffset) & + BITS(ucOffset, ucOffset + 1)); + } +#endif + + prVhtSupportedMcsSet->u2RxHighestSupportedDataRate = + VHT_CAP_INFO_DEFAULT_HIGHEST_DATA_RATE; + prVhtSupportedMcsSet->u2TxHighestSupportedDataRate = + VHT_CAP_INFO_DEFAULT_HIGHEST_DATA_RATE; + + ASSERT(IE_SIZE(prVhtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP)); + + prMsduInfo->u2FrameLength += IE_SIZE(prVhtCap); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmFillVhtOpIE(struct ADAPTER *prAdapter, struct BSS_INFO *prBssInfo, + struct MSDU_INFO *prMsduInfo) +{ + struct IE_VHT_OP *prVhtOp; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(prMsduInfo); + + prVhtOp = (struct IE_VHT_OP *)(((uint8_t *)prMsduInfo->prPacket) + + prMsduInfo->u2FrameLength); + + /* Add HT operation IE */ + prVhtOp->ucId = ELEM_ID_VHT_OP; + prVhtOp->ucLength = sizeof(struct IE_VHT_OP) - ELEM_HDR_LEN; + + ASSERT(IE_SIZE(prVhtOp) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP)); + + /* (UINT8)VHT_OP_CHANNEL_WIDTH_80; */ + prVhtOp->ucVhtOperation[0] = prBssInfo->ucVhtChannelWidth; + prVhtOp->ucVhtOperation[1] = prBssInfo->ucVhtChannelFrequencyS1; + prVhtOp->ucVhtOperation[2] = prBssInfo->ucVhtChannelFrequencyS2; + +#if 0 + if (cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex) < MAX_BW_80MHZ) { + prVhtOp->ucVhtOperation[0] = VHT_OP_CHANNEL_WIDTH_20_40; + prVhtOp->ucVhtOperation[1] = 0; + prVhtOp->ucVhtOperation[2] = 0; + } else if (cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex) == + MAX_BW_80MHZ) { + prVhtOp->ucVhtOperation[0] = VHT_OP_CHANNEL_WIDTH_80; + prVhtOp->ucVhtOperation[1] = + nicGetVhtS1(prBssInfo->ucPrimaryChannel); + prVhtOp->ucVhtOperation[2] = 0; + } else { + /* TODO: BW80 + 80/160 support */ + } +#endif + + prVhtOp->u2VhtBasicMcsSet = prBssInfo->u2VhtBasicMcsSet; + + prMsduInfo->u2FrameLength += IE_SIZE(prVhtOp); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Get RxNss from VHT CAP IE. + * + * \param[in] prVhtCap + * + * \return ucRxNss + */ +/*----------------------------------------------------------------------------*/ +uint8_t +rlmGetSupportRxNssInVhtCap(struct IE_VHT_CAP *prVhtCap) +{ + uint8_t ucRxNss = 1; + + if (prVhtCap) { + if (((prVhtCap->rVhtSupportedMcsSet.u2RxMcsMap & + VHT_CAP_INFO_MCS_2SS_MASK) >> + VHT_CAP_INFO_MCS_2SS_OFFSET) + != VHT_CAP_INFO_MCS_NOT_SUPPORTED) + ucRxNss = 2; + if (((prVhtCap->rVhtSupportedMcsSet.u2RxMcsMap & + VHT_CAP_INFO_MCS_3SS_MASK) + >> VHT_CAP_INFO_MCS_3SS_OFFSET) + != VHT_CAP_INFO_MCS_NOT_SUPPORTED) + ucRxNss = 3; + if (((prVhtCap->rVhtSupportedMcsSet.u2RxMcsMap & + VHT_CAP_INFO_MCS_4SS_MASK) + >> VHT_CAP_INFO_MCS_4SS_OFFSET) + != VHT_CAP_INFO_MCS_NOT_SUPPORTED) + ucRxNss = 4; + if (((prVhtCap->rVhtSupportedMcsSet.u2RxMcsMap & + VHT_CAP_INFO_MCS_5SS_MASK) + >> VHT_CAP_INFO_MCS_5SS_OFFSET) + != VHT_CAP_INFO_MCS_NOT_SUPPORTED) + ucRxNss = 5; + if (((prVhtCap->rVhtSupportedMcsSet.u2RxMcsMap & + VHT_CAP_INFO_MCS_6SS_MASK) + >> VHT_CAP_INFO_MCS_6SS_OFFSET) + != VHT_CAP_INFO_MCS_NOT_SUPPORTED) + ucRxNss = 6; + if (((prVhtCap->rVhtSupportedMcsSet.u2RxMcsMap & + VHT_CAP_INFO_MCS_7SS_MASK) + >> VHT_CAP_INFO_MCS_7SS_OFFSET) + != VHT_CAP_INFO_MCS_NOT_SUPPORTED) + ucRxNss = 7; + if (((prVhtCap->rVhtSupportedMcsSet.u2RxMcsMap & + VHT_CAP_INFO_MCS_8SS_MASK) + >> VHT_CAP_INFO_MCS_8SS_OFFSET) + != VHT_CAP_INFO_MCS_NOT_SUPPORTED) + ucRxNss = 8; + } else + DBGLOG(RLM, WARN, "null prVhtCap, assume RxNss=1\n"); + + return ucRxNss; +} + +#endif + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmGenerateCountryIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo = + prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + unsigned char *pucBuf = + (((unsigned char *) prMsduInfo->prPacket) + + prMsduInfo->u2FrameLength); + + if (prBssInfo->aucCountryStr[0] == 0) + return; + + COUNTRY_IE(pucBuf)->ucId = ELEM_ID_COUNTRY_INFO; + COUNTRY_IE(pucBuf)->ucLength = prBssInfo->ucCountryIELen; + COUNTRY_IE(pucBuf)->aucCountryStr[0] = prBssInfo->aucCountryStr[0]; + COUNTRY_IE(pucBuf)->aucCountryStr[1] = prBssInfo->aucCountryStr[1]; + COUNTRY_IE(pucBuf)->aucCountryStr[2] = prBssInfo->aucCountryStr[2]; + kalMemCopy(COUNTRY_IE(pucBuf)->arCountryStr, + prBssInfo->aucSubbandTriplet, + prBssInfo->ucCountryIELen - 3); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuf); +} + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +uint32_t rlmCalBackup(struct ADAPTER *prAdapter, uint8_t ucReason, + uint8_t ucAction, uint8_t ucRomRam) +{ + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CAL_BACKUP_STRUCT_V2 rCalBackupDataV2; + uint32_t u4BufLen = 0; + + ASSERT(prAdapter); + ASSERT(prAdapter->prGlueInfo); + + prGlueInfo = prAdapter->prGlueInfo; + + rCalBackupDataV2.ucReason = ucReason; + rCalBackupDataV2.ucAction = ucAction; + rCalBackupDataV2.ucNeedResp = 1; + rCalBackupDataV2.ucFragNum = 0; + rCalBackupDataV2.ucRomRam = ucRomRam; + rCalBackupDataV2.u4ThermalValue = 0; + rCalBackupDataV2.u4Address = 0; + rCalBackupDataV2.u4Length = 0; + rCalBackupDataV2.u4RemainLength = 0; + + if (ucReason == 0 && ucAction == 0) { + DBGLOG(RFTEST, INFO, "RLM CMD : Get Thermal Temp from FW.\n"); + /* Step 1 : Get Thermal Temp from FW */ + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryCalBackupV2, + &rCalBackupDataV2, + sizeof(struct PARAM_CAL_BACKUP_STRUCT_V2), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Get Thermal Temp from FW Return Fail (0x%08x)!!!!!!!!!!!\n", + rStatus); + return rStatus; + } + + DBGLOG(RFTEST, INFO, + "CMD : Get Thermal Temp (%d) from FW. Finish!!!!!!!!!!!\n", + rCalBackupDataV2.u4ThermalValue); + } else if (ucReason == 1 && ucAction == 2) { + DBGLOG(RFTEST, INFO, "RLM CMD : Trigger FW Do All Cal.\n"); + /* Step 2 : Trigger All Cal Function */ + + rStatus = kalIoctl(prGlueInfo, wlanoidSetCalBackup, + &rCalBackupDataV2, + sizeof(struct PARAM_CAL_BACKUP_STRUCT_V2), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Trigger FW Do All Cal Return Fail (0x%08x)!!!!!!!!!!!\n", + rStatus); + return rStatus; + } + + DBGLOG(RFTEST, INFO, + "CMD : Trigger FW Do All Cal. Finish!!!!!!!!!!!\n"); + } else if (ucReason == 0 && ucAction == 1) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Get Cal Data (%s) Size from FW.\n", + ucRomRam == 0 ? "ROM" : "RAM"); + /* Step 3 : Get Cal Data Size from FW */ + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryCalBackupV2, + &rCalBackupDataV2, + sizeof(struct PARAM_CAL_BACKUP_STRUCT_V2), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Get Cal Data (%s) Size from FW Return Fail (0x%08x)!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM", rStatus); + return rStatus; + } + + DBGLOG(RFTEST, INFO, + "CMD : Get Cal Data (%s) Size from FW. Finish!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM"); + } else if (ucReason == 2 && ucAction == 4) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Get Cal Data from FW (%s). Start!!!!!!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM"); + DBGLOG(RFTEST, INFO, "Thermal Temp = %d\n", + g_rBackupCalDataAllV2.u4ThermalInfo); + /* Step 4 : Get Cal Data from FW */ + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryCalBackupV2, + &rCalBackupDataV2, + sizeof(struct PARAM_CAL_BACKUP_STRUCT_V2), + TRUE, TRUE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Get Cal Data (%s) Size from FW Return Fail (0x%08x)!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM", rStatus); + return rStatus; + } + + DBGLOG(RFTEST, INFO, + "CMD : Get Cal Data from FW (%s). Finish!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM"); + + if (ucRomRam == 0) { + DBGLOG(RFTEST, INFO, + "Check some of elements (0x%08x), (0x%08x), (0x%08x), (0x%08x), (0x%08x)\n", + g_rBackupCalDataAllV2.au4RomCalData[670], + g_rBackupCalDataAllV2.au4RomCalData[671], + g_rBackupCalDataAllV2.au4RomCalData[672], + g_rBackupCalDataAllV2.au4RomCalData[673], + g_rBackupCalDataAllV2.au4RomCalData[674]); + DBGLOG(RFTEST, INFO, + "Check some of elements (0x%08x), (0x%08x), (0x%08x), (0x%08x), (0x%08x)\n", + g_rBackupCalDataAllV2.au4RomCalData[675], + g_rBackupCalDataAllV2.au4RomCalData[676], + g_rBackupCalDataAllV2.au4RomCalData[677], + g_rBackupCalDataAllV2.au4RomCalData[678], + g_rBackupCalDataAllV2.au4RomCalData[679]); + } + } else if (ucReason == 4 && ucAction == 6) { + DBGLOG(RFTEST, INFO, "RLM CMD : Print Cal Data in FW (%s).\n", + ucRomRam == 0 ? "ROM" : "RAM"); + /* Debug Use : Print Cal Data in FW */ + + rStatus = kalIoctl(prGlueInfo, wlanoidSetCalBackup, + &rCalBackupDataV2, + sizeof(struct PARAM_CAL_BACKUP_STRUCT_V2), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Print Cal Data in FW (%s) Return Fail (0x%08x)!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM", rStatus); + return rStatus; + } + + DBGLOG(RFTEST, INFO, + "CMD : Print Cal Data in FW (%s). Finish!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM"); + } else if (ucReason == 3 && ucAction == 5) { + DBGLOG(RFTEST, INFO, "RLM CMD : Send Cal Data to FW (%s).\n", + ucRomRam == 0 ? "ROM" : "RAM"); + /* Send Cal Data to FW */ + + rStatus = kalIoctl(prGlueInfo, wlanoidSetCalBackup, + &rCalBackupDataV2, + sizeof(struct PARAM_CAL_BACKUP_STRUCT_V2), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Send Cal Data to FW (%s) Return Fail (0x%08x)!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM", rStatus); + return rStatus; + } + + DBGLOG(RFTEST, INFO, + "CMD : Send Cal Data to FW (%s). Finish!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM"); + } else { + DBGLOG(RFTEST, INFO, + "CMD : Undefined Reason (%d) and Action (%d) for Cal Backup in Host Side!\n", + ucReason, ucAction); + + return rStatus; + } + + return rStatus; +} + +uint32_t rlmTriggerCalBackup(struct ADAPTER *prAdapter, + u_int8_t fgIsCalDataBackuped) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + if (!fgIsCalDataBackuped) { + DBGLOG(RFTEST, INFO, + "======== Boot Time Wi-Fi Enable........\n"); + DBGLOG(RFTEST, INFO, + "Step 0 : Reset All Cal Data in Driver.\n"); + memset(&g_rBackupCalDataAllV2, 1, + sizeof(struct RLM_CAL_RESULT_ALL_V2)); + g_rBackupCalDataAllV2.u4MagicNum1 = 6632; + g_rBackupCalDataAllV2.u4MagicNum2 = 6632; + + DBGLOG(RFTEST, INFO, "Step 1 : Get Thermal Temp from FW.\n"); + if (rlmCalBackup(prAdapter, 0, 0, 0) == WLAN_STATUS_FAILURE) { + DBGLOG(RFTEST, INFO, "Step 1 : Return Failure.\n"); + return WLAN_STATUS_FAILURE; + } + + DBGLOG(RFTEST, INFO, + "Step 2 : Get Rom Cal Data Size from FW.\n"); + if (rlmCalBackup(prAdapter, 0, 1, 0) == WLAN_STATUS_FAILURE) { + DBGLOG(RFTEST, INFO, "Step 2 : Return Failure.\n"); + return WLAN_STATUS_FAILURE; + } + + DBGLOG(RFTEST, INFO, + "Step 3 : Get Ram Cal Data Size from FW.\n"); + if (rlmCalBackup(prAdapter, 0, 1, 1) == WLAN_STATUS_FAILURE) { + DBGLOG(RFTEST, INFO, "Step 3 : Return Failure.\n"); + return WLAN_STATUS_FAILURE; + } + + DBGLOG(RFTEST, INFO, "Step 4 : Trigger FW Do Full Cal.\n"); + if (rlmCalBackup(prAdapter, 1, 2, 0) == WLAN_STATUS_FAILURE) { + DBGLOG(RFTEST, INFO, "Step 4 : Return Failure.\n"); + return WLAN_STATUS_FAILURE; + } + } else { + DBGLOG(RFTEST, INFO, "======== Normal Wi-Fi Enable........\n"); + DBGLOG(RFTEST, INFO, "Step 0 : Sent Rom Cal data to FW.\n"); + if (rlmCalBackup(prAdapter, 3, 5, 0) == WLAN_STATUS_FAILURE) { + DBGLOG(RFTEST, INFO, "Step 0 : Return Failure.\n"); + return WLAN_STATUS_FAILURE; + } + + DBGLOG(RFTEST, INFO, "Step 1 : Sent Ram Cal data to FW.\n"); + if (rlmCalBackup(prAdapter, 3, 5, 1) == WLAN_STATUS_FAILURE) { + DBGLOG(RFTEST, INFO, "Step 1 : Return Failure.\n"); + return WLAN_STATUS_FAILURE; + } + } + + return rStatus; +} +#endif + +void rlmModifyVhtBwPara(uint8_t *pucVhtChannelFrequencyS1, + uint8_t *pucVhtChannelFrequencyS2, + uint8_t *pucVhtChannelWidth) +{ + uint8_t i = 0, ucTempS = 0; + + if ((*pucVhtChannelFrequencyS1 != 0) && + (*pucVhtChannelFrequencyS2 != 0)) { + + uint8_t ucBW160Inteval = 8; + + if (((*pucVhtChannelFrequencyS2 - *pucVhtChannelFrequencyS1) == + ucBW160Inteval) || + ((*pucVhtChannelFrequencyS1 - *pucVhtChannelFrequencyS2) == + ucBW160Inteval)) { + /*C160 case*/ + + /* NEW spec should set central ch of bw80 at S1, + * set central ch of bw160 at S2 + */ + for (i = 0; i < 2; i++) { + + if (i == 0) + ucTempS = *pucVhtChannelFrequencyS1; + else + ucTempS = *pucVhtChannelFrequencyS2; + + if ((ucTempS == 50) || (ucTempS == 82) || + (ucTempS == 114) || (ucTempS == 163)) + break; + } + + if (ucTempS == 0) { + DBGLOG(RLM, WARN, + "please check BW160 setting, find central freq fail\n"); + return; + } + + *pucVhtChannelFrequencyS1 = ucTempS; + *pucVhtChannelFrequencyS2 = 0; + *pucVhtChannelWidth = CW_160MHZ; + } else { + /*real 80P80 case*/ + } + } +} + +static void rlmRevisePreferBandwidthNss(struct ADAPTER *prAdapter, + uint8_t ucBssIndex, + struct STA_RECORD *prStaRec) +{ + enum ENUM_CHANNEL_WIDTH eChannelWidth = CW_20_40MHZ; + struct BSS_INFO *prBssInfo; + +#define VHT_MCS_TX_RX_MAX_2SS BITS(2, 3) +#define VHT_MCS_TX_RX_MAX_2SS_SHIFT 2 + +#define AR_STA_2AC_MCS(prStaRec) \ + (((prStaRec)->u2VhtRxMcsMap & VHT_MCS_TX_RX_MAX_2SS) >> \ + VHT_MCS_TX_RX_MAX_2SS_SHIFT) + +#define AR_IS_STA_2SS_AC(prStaRec) ((AR_STA_2AC_MCS(prStaRec) != BITS(0, 1))) + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + eChannelWidth = prBssInfo->ucVhtChannelWidth; + + /* + * Prefer setting modification + * 80+80 1x1 and 80 2x2 have the same phy rate, choose the 80 2x2 + */ + + if (AR_IS_STA_2SS_AC(prStaRec)) { + /* + * DBGLOG(RLM, WARN, "support 2ss\n"); + */ + + if ((eChannelWidth == CW_80P80MHZ && + prBssInfo->ucVhtChannelFrequencyS2 != 0)) { + DBGLOG(RLM, WARN, "support (2Nss) and (80+80)\n"); + DBGLOG(RLM, WARN, + "choose (2Nss) and (80) for Bss_info\n"); + prBssInfo->ucVhtChannelWidth = CW_80MHZ; + prBssInfo->ucVhtChannelFrequencyS2 = 0; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Revise operating BW by own maximum bandwidth capability + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmReviseMaxBw(struct ADAPTER *prAdapter, uint8_t ucBssIndex, + enum ENUM_CHNL_EXT *peExtend, + enum ENUM_CHANNEL_WIDTH *peChannelWidth, uint8_t *pucS1, + uint8_t *pucPrimaryCh) +{ + uint8_t ucMaxBandwidth = MAX_BW_80MHZ; + uint8_t ucCurrentBandwidth = MAX_BW_20MHZ; + uint8_t ucOffset = (MAX_BW_80MHZ - CW_80MHZ); + + ucMaxBandwidth = cnmGetDbdcBwCapability(prAdapter, ucBssIndex); + + if (*peChannelWidth > CW_20_40MHZ) { + /*case BW > 80 , 160 80P80 */ + ucCurrentBandwidth = (uint8_t)*peChannelWidth + ucOffset; + } else { + /*case BW20 BW40 */ + if (*peExtend != CHNL_EXT_SCN) { + /*case BW40 */ + ucCurrentBandwidth = MAX_BW_40MHZ; + } + } + + if (ucCurrentBandwidth > ucMaxBandwidth) { + DBGLOG(RLM, INFO, "Decreasse the BW to (%d)\n", ucMaxBandwidth); + + if (ucMaxBandwidth <= MAX_BW_40MHZ) { + /*BW20 * BW40*/ + *peChannelWidth = CW_20_40MHZ; + + if (ucMaxBandwidth == MAX_BW_20MHZ) + *peExtend = CHNL_EXT_SCN; + } else { + /* BW80, BW160, BW80P80 + * ucMaxBandwidth Must be + * MAX_BW_80MHZ,MAX_BW_160MHZ,MAX_BW_80MHZ + * peExtend should not change + */ + *peChannelWidth = (ucMaxBandwidth - ucOffset); + + if (ucMaxBandwidth == MAX_BW_80MHZ) { + /* modify S1 for Bandwidth 160 downgrade 80 case + */ + if (ucCurrentBandwidth == MAX_BW_160MHZ) { + if ((*pucPrimaryCh >= 36) && + (*pucPrimaryCh <= 48)) + *pucS1 = 42; + else if ((*pucPrimaryCh >= 52) && + (*pucPrimaryCh <= 64)) + *pucS1 = 58; + else if ((*pucPrimaryCh >= 100) && + (*pucPrimaryCh <= 112)) + *pucS1 = 106; + else if ((*pucPrimaryCh >= 116) && + (*pucPrimaryCh <= 128)) + *pucS1 = 122; + else if ((*pucPrimaryCh >= 132) && + (*pucPrimaryCh <= 144)) + /* 160 downgrade should not in + * this case + */ + *pucS1 = 138; + else if ((*pucPrimaryCh >= 149) && + (*pucPrimaryCh <= 161)) + /* 160 downgrade should not in + * this case + */ + *pucS1 = 155; + else + DBGLOG(RLM, INFO, + "Check connect 160 downgrde (%d) case\n", + ucMaxBandwidth); + + DBGLOG(RLM, INFO, + "Decreasse the BW160 to BW80, shift S1 to (%d)\n", + *pucS1); + } + } + } + + DBGLOG(RLM, INFO, "Modify ChannelWidth (%d) and Extend (%d)\n", + *peChannelWidth, *peExtend); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Fill VHT Operation Information(VHT BW, S1, S2) by BSS operating + * channel width + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmFillVhtOpInfoByBssOpBw(struct BSS_INFO *prBssInfo, uint8_t ucBssOpBw) +{ + ASSERT(prBssInfo); + + if (ucBssOpBw < MAX_BW_80MHZ || prBssInfo->eBand == BAND_2G4) { + prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_20_40; + prBssInfo->ucVhtChannelFrequencyS1 = 0; + prBssInfo->ucVhtChannelFrequencyS2 = 0; + } else if (ucBssOpBw == MAX_BW_80MHZ) { + prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_80; + prBssInfo->ucVhtChannelFrequencyS1 = nicGetVhtS1( + prBssInfo->ucPrimaryChannel, VHT_OP_CHANNEL_WIDTH_80); + prBssInfo->ucVhtChannelFrequencyS2 = 0; + } else if (ucBssOpBw == MAX_BW_160MHZ) { + prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_160; + prBssInfo->ucVhtChannelFrequencyS1 = nicGetVhtS1( + prBssInfo->ucPrimaryChannel, VHT_OP_CHANNEL_WIDTH_160); + prBssInfo->ucVhtChannelFrequencyS2 = 0; + } else { + /* 4 TODO: / BW80+80 support */ + DBGLOG(RLM, INFO, "Unsupport BW setting, back to VHT20_40\n"); + + prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_20_40; + prBssInfo->ucVhtChannelFrequencyS1 = 0; + prBssInfo->ucVhtChannelFrequencyS2 = 0; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function should be invoked to update parameters of associated AP. + * (Association response and Beacon) + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static uint8_t rlmRecIeInfoForClient(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, uint8_t *pucIE, + uint16_t u2IELength) +{ + uint16_t u2Offset; + struct STA_RECORD *prStaRec; + struct IE_HT_CAP *prHtCap; + struct IE_HT_OP *prHtOp; + struct IE_OBSS_SCAN_PARAM *prObssScnParam; + uint8_t ucERP, ucPrimaryChannel; + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; +#if CFG_SUPPORT_QUIET && 0 + u_int8_t fgHasQuietIE = FALSE; +#endif + u_int8_t IsfgHtCapChange = FALSE; + +#if CFG_SUPPORT_802_11AC + struct IE_VHT_OP *prVhtOp; + struct IE_VHT_CAP *prVhtCap = NULL; + struct IE_OP_MODE_NOTIFICATION *prOPNotif; + uint8_t fgHasOPModeIE = FALSE; + uint8_t fgHasNewOPModeIE = FALSE; + uint8_t ucVhtOpModeChannelWidth = 0; + uint8_t ucVhtOpModeRxNss = 0; + uint8_t ucMaxBwAllowed; + uint8_t ucInitVhtOpMode = 0; +#endif + +#if CFG_SUPPORT_DFS + u_int8_t fgHasWideBandIE = FALSE; + u_int8_t fgHasSCOIE = FALSE; + u_int8_t fgHasChannelSwitchIE = FALSE; + u_int8_t fgNeedSwitchChannel = FALSE; + uint8_t ucChannelAnnouncePri; + enum ENUM_CHNL_EXT eChannelAnnounceSco; + uint8_t ucChannelAnnounceChannelS1 = 0; + uint8_t ucChannelAnnounceChannelS2 = 0; + uint8_t ucChannelAnnounceVhtBw; + struct IE_CHANNEL_SWITCH *prChannelSwitchAnnounceIE; + struct IE_SECONDARY_OFFSET *prSecondaryOffsetIE; + struct IE_WIDE_BAND_CHANNEL *prWideBandChannelIE; +#endif + uint8_t *pucDumpIE; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(pucIE); + + prStaRec = prBssInfo->prStaRecOfAP; + if (!prStaRec) + return 0; + + prBssInfo->fgUseShortPreamble = prBssInfo->fgIsShortPreambleAllowed; + ucPrimaryChannel = 0; + prObssScnParam = NULL; + ucMaxBwAllowed = cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex); + pucDumpIE = pucIE; + + /* Note: HT-related members in staRec may not be zero before, so + * if following IE does not exist, they are still not zero. + * These HT-related parameters are valid only when the + * corresponding + * BssInfo supports 802.11n, i.e., RLM_NET_IS_11N() + */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) + { + switch (IE_ID(pucIE)) { + case ELEM_ID_HT_CAP: + if (!RLM_NET_IS_11N(prBssInfo) || + IE_LEN(pucIE) != (sizeof(struct IE_HT_CAP) - 2)) + break; + prHtCap = (struct IE_HT_CAP *)pucIE; + prStaRec->ucMcsSet = + prHtCap->rSupMcsSet.aucRxMcsBitmask[0]; + prStaRec->fgSupMcs32 = + (prHtCap->rSupMcsSet.aucRxMcsBitmask[32 / 8] & + BIT(0)) + ? TRUE + : FALSE; + + kalMemCopy( + prStaRec->aucRxMcsBitmask, + prHtCap->rSupMcsSet.aucRxMcsBitmask, + /*SUP_MCS_RX_BITMASK_OCTET_NUM */ + sizeof(prStaRec->aucRxMcsBitmask)); + + prStaRec->u2RxHighestSupportedRate = + prHtCap->rSupMcsSet.u2RxHighestSupportedRate; + prStaRec->u4TxRateInfo = + prHtCap->rSupMcsSet.u4TxRateInfo; + + if ((prStaRec->u2HtCapInfo & + HT_CAP_INFO_SM_POWER_SAVE) != + (prHtCap->u2HtCapInfo & HT_CAP_INFO_SM_POWER_SAVE)) + /* Purpose : To detect SMPS change */ + IsfgHtCapChange = TRUE; + + prStaRec->u2HtCapInfo = prHtCap->u2HtCapInfo; + /* Set LDPC Tx capability */ + if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxLdpc)) + prStaRec->u2HtCapInfo |= HT_CAP_INFO_LDPC_CAP; + else if (IS_FEATURE_DISABLED(prWifiVar->ucTxLdpc)) + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_LDPC_CAP; + + /* Set STBC Tx capability */ + if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxStbc)) + prStaRec->u2HtCapInfo |= HT_CAP_INFO_RX_STBC; + else if (IS_FEATURE_DISABLED(prWifiVar->ucTxStbc)) + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_RX_STBC; + + /* Set Short GI Tx capability */ + if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxShortGI)) { + prStaRec->u2HtCapInfo |= + HT_CAP_INFO_SHORT_GI_20M; + prStaRec->u2HtCapInfo |= + HT_CAP_INFO_SHORT_GI_40M; + } else if (IS_FEATURE_DISABLED( + prWifiVar->ucTxShortGI)) { + prStaRec->u2HtCapInfo &= + ~HT_CAP_INFO_SHORT_GI_20M; + prStaRec->u2HtCapInfo &= + ~HT_CAP_INFO_SHORT_GI_40M; + } + + /* Set HT Greenfield Tx capability */ + if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxGf)) + prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + else if (IS_FEATURE_DISABLED(prWifiVar->ucTxGf)) + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_HT_GF; + + 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(struct IE_HT_OP) - 2)) + break; + prHtOp = (struct IE_HT_OP *)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; + + /*Backup peer HT OP Info*/ + prStaRec->ucHtPeerOpInfo1 = prHtOp->ucInfo1; + + 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 ENUM_CHNL_EXT)( + prBssInfo->ucHtOpInfo1 & + HT_OP_INFO1_SCO); + + /* Revise by own OP BW */ + if (prBssInfo->fgIsOpChangeChannelWidth && + prBssInfo->ucOpChangeChannelWidth == MAX_BW_20MHZ) { + prBssInfo->ucHtOpInfo1 &= + ~(HT_OP_INFO1_SCO | + HT_OP_INFO1_STA_CHNL_WIDTH); + prBssInfo->eBssSCO = CHNL_EXT_SCN; + } + + prBssInfo->eHtProtectMode = (enum ENUM_HT_PROTECT_MODE)( + 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; + +#if CFG_SUPPORT_802_11AC + case ELEM_ID_VHT_CAP: + if (!RLM_NET_IS_11AC(prBssInfo) || + IE_LEN(pucIE) != (sizeof(struct IE_VHT_CAP) - 2)) + break; + + prVhtCap = (struct IE_VHT_CAP *)pucIE; + + prStaRec->u4VhtCapInfo = prVhtCap->u4VhtCapInfo; + /* Set Tx LDPC capability */ + if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxLdpc)) + prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_RX_LDPC; + else if (IS_FEATURE_DISABLED(prWifiVar->ucTxLdpc)) + prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_RX_LDPC; + + /* Set Tx STBC capability */ + if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxStbc)) + prStaRec->u4VhtCapInfo |= + VHT_CAP_INFO_RX_STBC_MASK; + else if (IS_FEATURE_DISABLED(prWifiVar->ucTxStbc)) + prStaRec->u4VhtCapInfo &= + ~VHT_CAP_INFO_RX_STBC_MASK; + + /* Set Tx TXOP PS capability */ + if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxopPsTx)) + prStaRec->u4VhtCapInfo |= + VHT_CAP_INFO_VHT_TXOP_PS; + else if (IS_FEATURE_DISABLED(prWifiVar->ucTxopPsTx)) + prStaRec->u4VhtCapInfo &= + ~VHT_CAP_INFO_VHT_TXOP_PS; + + /* Set Tx Short GI capability */ + if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxShortGI)) { + prStaRec->u4VhtCapInfo |= + VHT_CAP_INFO_SHORT_GI_80; + prStaRec->u4VhtCapInfo |= + VHT_CAP_INFO_SHORT_GI_160_80P80; + } else if (IS_FEATURE_DISABLED( + prWifiVar->ucTxShortGI)) { + prStaRec->u4VhtCapInfo &= + ~VHT_CAP_INFO_SHORT_GI_80; + prStaRec->u4VhtCapInfo &= + ~VHT_CAP_INFO_SHORT_GI_160_80P80; + } + + prStaRec->u2VhtRxMcsMap = + prVhtCap->rVhtSupportedMcsSet.u2RxMcsMap; + prStaRec->u2VhtRxMcsMapAssoc = + prStaRec->u2VhtRxMcsMap; + + prStaRec->u2VhtRxHighestSupportedDataRate = + prVhtCap->rVhtSupportedMcsSet + .u2RxHighestSupportedDataRate; + prStaRec->u2VhtTxMcsMap = + prVhtCap->rVhtSupportedMcsSet.u2TxMcsMap; + prStaRec->u2VhtTxHighestSupportedDataRate = + prVhtCap->rVhtSupportedMcsSet + .u2TxHighestSupportedDataRate; + + break; + + case ELEM_ID_VHT_OP: + if (!RLM_NET_IS_11AC(prBssInfo) || + IE_LEN(pucIE) != (sizeof(struct IE_VHT_OP) - 2)) + break; + + prVhtOp = (struct IE_VHT_OP *)pucIE; + + /*Backup peer VHT OpInfo*/ + prStaRec->ucVhtOpChannelWidth = + prVhtOp->ucVhtOperation[0]; + prStaRec->ucVhtOpChannelFrequencyS1 = + prVhtOp->ucVhtOperation[1]; + prStaRec->ucVhtOpChannelFrequencyS2 = + prVhtOp->ucVhtOperation[2]; + + rlmModifyVhtBwPara(&prStaRec->ucVhtOpChannelFrequencyS1, + &prStaRec->ucVhtOpChannelFrequencyS2, + &prStaRec->ucVhtOpChannelWidth); + + prBssInfo->ucVhtChannelWidth = + prVhtOp->ucVhtOperation[0]; + prBssInfo->ucVhtChannelFrequencyS1 = + prVhtOp->ucVhtOperation[1]; + prBssInfo->ucVhtChannelFrequencyS2 = + prVhtOp->ucVhtOperation[2]; + prBssInfo->u2VhtBasicMcsSet = prVhtOp->u2VhtBasicMcsSet; + + rlmModifyVhtBwPara(&prBssInfo->ucVhtChannelFrequencyS1, + &prBssInfo->ucVhtChannelFrequencyS2, + &prBssInfo->ucVhtChannelWidth); + + /* Revise by own OP BW if needed */ + if ((prBssInfo->fgIsOpChangeChannelWidth) && + (rlmGetVhtOpBwByBssOpBw( + prBssInfo->ucOpChangeChannelWidth) < + prBssInfo->ucVhtChannelWidth)) { + rlmFillVhtOpInfoByBssOpBw( + prBssInfo, + prBssInfo->ucOpChangeChannelWidth); + } + + break; + case ELEM_ID_OP_MODE: + if (!RLM_NET_IS_11AC(prBssInfo) || + IE_LEN(pucIE) != + (sizeof(struct IE_OP_MODE_NOTIFICATION) - + 2)) + break; + prOPNotif = (struct IE_OP_MODE_NOTIFICATION *) pucIE; + + /* NOTE: An AP always sets this field to 0, + * so break it if this bit is set. + */ + if ((prOPNotif->ucOpMode & VHT_OP_MODE_RX_NSS_TYPE) + == VHT_OP_MODE_RX_NSS_TYPE) { + break; + } + fgHasOPModeIE = TRUE; + + /* Same OP mode, no need to update. + * Let the further flow not to update VhtOpMode. + */ + if (prStaRec->ucVhtOpMode == prOPNotif->ucOpMode) { + ucInitVhtOpMode = prStaRec->ucVhtOpMode; + break; + } + + fgHasNewOPModeIE = TRUE; + prStaRec->ucVhtOpMode = prOPNotif->ucOpMode; + ucVhtOpModeChannelWidth = + (prOPNotif->ucOpMode & + VHT_OP_MODE_CHANNEL_WIDTH); + ucVhtOpModeRxNss = + (prOPNotif->ucOpMode & VHT_OP_MODE_RX_NSS) + >> VHT_OP_MODE_RX_NSS_OFFSET; + + if (ucVhtOpModeRxNss == VHT_OP_MODE_NSS_2) { + prStaRec->u2VhtRxMcsMap = BITS(0, 15) & + (~(VHT_CAP_INFO_MCS_1SS_MASK | + VHT_CAP_INFO_MCS_2SS_MASK)); + + prStaRec->u2VhtRxMcsMap |= + (prStaRec->u2VhtRxMcsMapAssoc & + (VHT_CAP_INFO_MCS_1SS_MASK | + VHT_CAP_INFO_MCS_2SS_MASK)); + } else { + prStaRec->u2VhtRxMcsMap = BITS(0, 15) & + (~VHT_CAP_INFO_MCS_1SS_MASK); + + prStaRec->u2VhtRxMcsMap |= + (prStaRec->u2VhtRxMcsMapAssoc & + VHT_CAP_INFO_MCS_1SS_MASK); + } + DBGLOG(RLM, INFO, + "NSS=%x RxMcsMap:0x%x, McsMapAssoc:0x%x\n", + ucVhtOpModeRxNss, prStaRec->u2VhtRxMcsMap, + prStaRec->u2VhtRxMcsMapAssoc); + break; +#if CFG_SUPPORT_DFS + case ELEM_ID_WIDE_BAND_CHANNEL_SWITCH: + if (!RLM_NET_IS_11AC(prBssInfo) || + IE_LEN(pucIE) != + (sizeof(struct IE_WIDE_BAND_CHANNEL) - 2)) + break; + DBGLOG(RLM, INFO, + "[Channel Switch] ELEM_ID_WIDE_BAND_CHANNEL_SWITCH, 11AC\n"); + prWideBandChannelIE = + (struct IE_WIDE_BAND_CHANNEL *)pucIE; + ucChannelAnnounceVhtBw = + prWideBandChannelIE->ucNewChannelWidth; + ucChannelAnnounceChannelS1 = + prWideBandChannelIE->ucChannelS1; + ucChannelAnnounceChannelS2 = + prWideBandChannelIE->ucChannelS2; + fgHasWideBandIE = TRUE; + DBGLOG(RLM, INFO, "[Ch] BW=%d, s1=%d, s2=%d\n", + ucChannelAnnounceVhtBw, + ucChannelAnnounceChannelS1, + ucChannelAnnounceChannelS2); + break; +#endif + +#endif + 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(struct IE_OBSS_SCAN_PARAM) - 2)) + break; + /* Store OBSS parameters to BssInfo */ + prObssScnParam = (struct IE_OBSS_SCAN_PARAM *)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(struct IE_ERP) - 2) || + prBssInfo->eBand != BAND_2G4) + break; + ucERP = ERP_INFO_IE(pucIE)->ucERP; + prBssInfo->fgErpProtectMode = + (ucERP & ERP_INFO_USE_PROTECTION) ? TRUE + : FALSE; + + if (ucERP & ERP_INFO_BARKER_PREAMBLE_MODE) + prBssInfo->fgUseShortPreamble = FALSE; + break; + + case ELEM_ID_DS_PARAM_SET: + if (IE_LEN(pucIE) == ELEM_MAX_LEN_DS_PARAMETER_SET) + ucPrimaryChannel = + DS_PARAM_IE(pucIE)->ucCurrChnl; + break; +#if CFG_SUPPORT_DFS + case ELEM_ID_CH_SW_ANNOUNCEMENT: + if (IE_LEN(pucIE) != + (sizeof(struct IE_CHANNEL_SWITCH) - 2)) + break; + + prChannelSwitchAnnounceIE = + (struct IE_CHANNEL_SWITCH *)pucIE; + + DBGLOG(RLM, INFO, "[Ch] Count=%d\n", + prChannelSwitchAnnounceIE->ucChannelSwitchCount); + + if (prChannelSwitchAnnounceIE + ->ucChannelSwitchMode == 1) { + /* Need to stop data transmission immediately */ + fgHasChannelSwitchIE = TRUE; + if (!g_fgHasStopTx) { + g_fgHasStopTx = TRUE; + /* AP */ + qmSetStaRecTxAllowed(prAdapter, + prStaRec, + FALSE); + DBGLOG(RLM, EVENT, + "[Ch] TxAllowed = FALSE\n"); + } + + if (prChannelSwitchAnnounceIE + ->ucChannelSwitchCount <= 5) { + DBGLOG(RLM, INFO, + "[Ch] switch channel [%d]->[%d]\n", + prBssInfo->ucPrimaryChannel, + prChannelSwitchAnnounceIE + ->ucNewChannelNum); + ucChannelAnnouncePri = + prChannelSwitchAnnounceIE + ->ucNewChannelNum; + fgNeedSwitchChannel = TRUE; +#ifdef CFG_DFS_CHSW_FORCE_BW20 + g_fgHasChannelSwitchIE = TRUE; +#endif + } +#ifdef CFG_DFS_CHSW_FORCE_BW20 + if (RLM_NET_IS_11AC(prBssInfo)) { + DBGLOG(RLM, INFO, + "Send Operation Action Frame"); + rlmSendOpModeNotificationFrame( + prAdapter, prStaRec, + VHT_OP_MODE_CHANNEL_WIDTH_20, + 1); + } else { + DBGLOG(RLM, INFO, + "Skip Send Operation Action Frame"); + } +#endif + } + + break; + case ELEM_ID_SCO: + if (IE_LEN(pucIE) != + (sizeof(struct IE_SECONDARY_OFFSET) - 2)) + break; + + prSecondaryOffsetIE = + (struct IE_SECONDARY_OFFSET *)pucIE; + DBGLOG(RLM, INFO, "[Channel Switch] SCO [%d]->[%d]\n", + prBssInfo->eBssSCO, + prSecondaryOffsetIE->ucSecondaryOffset); + eChannelAnnounceSco = + (enum ENUM_CHNL_EXT) + prSecondaryOffsetIE->ucSecondaryOffset; + fgHasSCOIE = TRUE; + break; +#endif + +#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, + (struct IE_QUIET *)pucIE); + fgHasQuietIE = TRUE; + break; +#endif + +#if (CFG_SUPPORT_802_11AX == 1) + case ELEM_ID_RESERVED: + if (fgEfuseCtrlAxOn == 1) { + if (IE_ID_EXT(pucIE) == ELEM_EXT_ID_HE_CAP) + heRlmRecHeCapInfo(prAdapter, prStaRec, pucIE); + else if (IE_ID_EXT(pucIE) == ELEM_EXT_ID_HE_OP) + heRlmRecHeOperation(prAdapter, + prBssInfo, pucIE); + } + break; +#endif + + default: + break; + } /* end of switch */ + } /* end of IE_FOR_EACH */ + + if (IsfgHtCapChange && (prStaRec->ucStaState == STA_STATE_3)) + cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); + + /* 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_802_11AC + /* Check whether the Operation Mode IE is exist or not. + * If exists, then the channel bandwidth of VHT operation field is + * changed + * with the channel bandwidth setting of Operation Mode field. + * The channel bandwidth of OP Mode IE is 0, represent as 20MHz. + * The channel bandwidth of OP Mode IE is 1, represent as 40MHz. + * The channel bandwidth of OP Mode IE is 2, represent as 80MHz. + * The channel bandwidth of OP Mode IE is 3, represent as + * 160/80+80MHz. + */ + if (fgHasNewOPModeIE == TRUE) { + if (prStaRec->ucStaState == STA_STATE_3) { + /* 1. Modify channel width parameters */ + rlmRecOpModeBwForClient(ucVhtOpModeChannelWidth, + prBssInfo); + + /* 2. Update StaRec to FW (BssInfo will be updated after + * return from this function) + */ + DBGLOG(RLM, INFO, + "Update OpMode to 0x%x, to FW due to OpMode Notificaition", + prStaRec->ucVhtOpMode); + cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); + + /* 3. Revise by own OP BW if needed */ + if ((prBssInfo->fgIsOpChangeChannelWidth)) { + /* VHT */ + if (rlmGetVhtOpBwByBssOpBw( + prBssInfo->ucOpChangeChannelWidth) < + prBssInfo->ucVhtChannelWidth) + rlmFillVhtOpInfoByBssOpBw( + prBssInfo, + prBssInfo + ->ucOpChangeChannelWidth); + /* HT */ + if (prBssInfo->fgIsOpChangeChannelWidth && + prBssInfo->ucOpChangeChannelWidth == + MAX_BW_20MHZ) { + prBssInfo->ucHtOpInfo1 &= + ~(HT_OP_INFO1_SCO | + HT_OP_INFO1_STA_CHNL_WIDTH); + prBssInfo->eBssSCO = CHNL_EXT_SCN; + } + } + } + } else { /* Set Default if the VHT OP mode field is not present */ + if (!fgHasOPModeIE) { + ucInitVhtOpMode |= + rlmGetOpModeBwByVhtAndHtOpInfo(prBssInfo); + ucInitVhtOpMode |= + ((rlmGetSupportRxNssInVhtCap(prVhtCap) - 1) + << VHT_OP_MODE_RX_NSS_OFFSET) & + VHT_OP_MODE_RX_NSS; + } + if ((prStaRec->ucVhtOpMode != ucInitVhtOpMode) && + (prStaRec->ucStaState == STA_STATE_3)) { + prStaRec->ucVhtOpMode = ucInitVhtOpMode; + DBGLOG(RLM, INFO, "Update OpMode to 0x%x", + prStaRec->ucVhtOpMode); + DBGLOG(RLM, INFO, + "to FW due to NO OpMode Notificaition\n"); + cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); + } else + prStaRec->ucVhtOpMode = ucInitVhtOpMode; + } +#endif + +#if CFG_SUPPORT_DFS + /* Check whether Channel Announcement IE, Secondary Offset IE & + * Wide Bandwidth Channel Switch IE exist or not. If exist, the + * priority is + * the highest. + */ + + if (fgNeedSwitchChannel) { + struct BSS_DESC *prBssDesc; + struct PARAM_SSID rSsid; + + prBssInfo->ucPrimaryChannel = ucChannelAnnouncePri; + prBssInfo->eBand = + (prBssInfo->ucPrimaryChannel <= 14) + ? BAND_2G4 + : BAND_5G; + /* Change to BW20 for certification issue due to signal sidelope + * leakage + */ + prBssInfo->ucVhtChannelWidth = 0; + prBssInfo->ucVhtChannelFrequencyS1 = 0; + prBssInfo->ucVhtChannelFrequencyS2 = 0; + prBssInfo->eBssSCO = 0; + + if (fgHasWideBandIE != FALSE) { + prBssInfo->ucVhtChannelWidth = ucChannelAnnounceVhtBw; + prBssInfo->ucVhtChannelFrequencyS1 = + ucChannelAnnounceChannelS1; + prBssInfo->ucVhtChannelFrequencyS2 = + ucChannelAnnounceChannelS2; + + /* Revise by own OP BW if needed */ + if ((prBssInfo->fgIsOpChangeChannelWidth) && + (rlmGetVhtOpBwByBssOpBw( + prBssInfo->ucOpChangeChannelWidth) < + prBssInfo->ucVhtChannelWidth)) { + + DBGLOG(RLM, LOUD, + "Change to w:%d s1:%d s2:%d since own changed BW < peer's WideBand BW", + prBssInfo->ucVhtChannelWidth, + prBssInfo->ucVhtChannelFrequencyS1, + prBssInfo->ucVhtChannelFrequencyS2); + rlmFillVhtOpInfoByBssOpBw( + prBssInfo, + prBssInfo->ucOpChangeChannelWidth); + } + } + if (fgHasSCOIE != FALSE) + prBssInfo->eBssSCO = eChannelAnnounceSco; + + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, prBssInfo->aucSSID, + prBssInfo->ucSSIDLen); + prBssDesc = scanSearchBssDescByBssidAndSsid( + prAdapter, prBssInfo->aucBSSID, TRUE, &rSsid); + + if (prBssDesc) { + DBGLOG(RLM, INFO, + "DFS: BSS: " MACSTR + " Desc found, channel from %u to %u\n ", + MAC2STR(prBssInfo->aucBSSID), + prBssDesc->ucChannelNum, ucChannelAnnouncePri); + prBssDesc->ucChannelNum = ucChannelAnnouncePri; + prBssDesc->eChannelWidth = prBssInfo->ucVhtChannelWidth; + prBssDesc->ucCenterFreqS1 = + prBssInfo->ucVhtChannelFrequencyS1; + prBssDesc->ucCenterFreqS2 = + prBssInfo->ucVhtChannelFrequencyS2; + kalIndicateChannelSwitch( + prAdapter->prGlueInfo, + prBssInfo->eBssSCO, + prBssDesc->ucChannelNum); + } else { + DBGLOG(RLM, INFO, + "DFS: BSS: " MACSTR " Desc is not found\n ", + MAC2STR(prBssInfo->aucBSSID)); + } + } +#endif + + if (!fgHasChannelSwitchIE && g_fgHasStopTx) { + /* AP */ + qmSetStaRecTxAllowed(prAdapter, prStaRec, TRUE); + + DBGLOG(RLM, EVENT, "[Ch] TxAllowed = TRUE\n"); + g_fgHasStopTx = FALSE; + } + +#if CFG_SUPPORT_DFS +#ifdef CFG_DFS_CHSW_FORCE_BW20 + /*DFS Certification for Channel Bandwidth 20MHz */ + DBGLOG(RLM, INFO, "Ch : SwitchIE = %d\n", g_fgHasChannelSwitchIE); + if (g_fgHasChannelSwitchIE == TRUE) { + prBssInfo->eBssSCO = CHNL_EXT_SCN; + prBssInfo->ucVhtChannelWidth = CW_20_40MHZ; + prBssInfo->ucVhtChannelFrequencyS1 = 0; + prBssInfo->ucVhtChannelFrequencyS2 = 255; + prBssInfo->ucHtOpInfo1 &= + ~(HT_OP_INFO1_SCO | HT_OP_INFO1_STA_CHNL_WIDTH); + DBGLOG(RLM, INFO, "Ch : DFS has Appeared\n"); + } +#endif +#endif + rlmReviseMaxBw(prAdapter, prBssInfo->ucBssIndex, &prBssInfo->eBssSCO, + (enum ENUM_CHANNEL_WIDTH *)&prBssInfo->ucVhtChannelWidth, + &prBssInfo->ucVhtChannelFrequencyS1, + &prBssInfo->ucPrimaryChannel); + + rlmRevisePreferBandwidthNss(prAdapter, prBssInfo->ucBssIndex, prStaRec); + + /* printk("Modify ChannelWidth (%d) and Extend + * (%d)\n",prBssInfo->eBssSCO, + * prBssInfo->ucVhtChannelWidth); + */ + + if (!rlmDomainIsValidRfSetting( + prAdapter, prBssInfo->eBand, prBssInfo->ucPrimaryChannel, + prBssInfo->eBssSCO, prBssInfo->ucVhtChannelWidth, + prBssInfo->ucVhtChannelFrequencyS1, + prBssInfo->ucVhtChannelFrequencyS2)) { + + /*Dump IE Inforamtion */ + DBGLOG(RLM, WARN, "rlmRecIeInfoForClient IE Information\n"); + DBGLOG(RLM, WARN, "IE Length = %d\n", u2IELength); + DBGLOG_MEM8(RLM, WARN, pucDumpIE, u2IELength); + + /*Error Handling for Non-predicted IE - Fixed to set 20MHz */ + prBssInfo->ucVhtChannelWidth = CW_20_40MHZ; + prBssInfo->ucVhtChannelFrequencyS1 = 0; + prBssInfo->ucVhtChannelFrequencyS2 = 0; + prBssInfo->eBssSCO = CHNL_EXT_SCN; + prBssInfo->ucHtOpInfo1 &= + ~(HT_OP_INFO1_SCO | HT_OP_INFO1_STA_CHNL_WIDTH); + + /* Check SAP channel */ + p2pFuncSwitchSapChannel(prAdapter); + + } +#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 Update parameters from channel width field in OP Mode IE/action frame + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static void rlmRecOpModeBwForClient(uint8_t ucVhtOpModeChannelWidth, + struct BSS_INFO *prBssInfo) +{ + + struct STA_RECORD *prStaRec = NULL; + + if (!prBssInfo) + return; + + prStaRec = prBssInfo->prStaRecOfAP; + if (!prStaRec) + return; + + switch (ucVhtOpModeChannelWidth) { + case VHT_OP_MODE_CHANNEL_WIDTH_20: + prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_20_40; + prBssInfo->ucHtOpInfo1 &= ~HT_OP_INFO1_STA_CHNL_WIDTH; + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SUP_CHNL_WIDTH; + +#if CFG_OPMODE_CONFLICT_OPINFO + if (prBssInfo->eBssSCO != CHNL_EXT_SCN) { + DBGLOG(RLM, WARN, + "HT_OP_Info != OPmode_Notifify, follow OPmode_Notify to BW20.\n"); + prBssInfo->eBssSCO = CHNL_EXT_SCN; + } +#endif + break; + case VHT_OP_MODE_CHANNEL_WIDTH_40: + prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_20_40; + prBssInfo->ucHtOpInfo1 |= HT_OP_INFO1_STA_CHNL_WIDTH; + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; + +#if CFG_OPMODE_CONFLICT_OPINFO + if (prBssInfo->eBssSCO == CHNL_EXT_SCN) { + prBssInfo->ucHtOpInfo1 &= ~HT_OP_INFO1_STA_CHNL_WIDTH; + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SUP_CHNL_WIDTH; + DBGLOG(RLM, WARN, + "HT_OP_Info != OPmode_Notifify, follow HT_OP_Info to BW20.\n"); + } +#endif + break; + case VHT_OP_MODE_CHANNEL_WIDTH_80: +#if CFG_OPMODE_CONFLICT_OPINFO + if (prBssInfo->ucVhtChannelWidth != + VHT_OP_MODE_CHANNEL_WIDTH_80) { + DBGLOG(RLM, WARN, + "VHT_OP != OPmode:%d, follow VHT_OP to VHT_OP:%d HT_OP:%d\n", + ucVhtOpModeChannelWidth, + prBssInfo->ucVhtChannelWidth, + (uint8_t)(prBssInfo->ucHtOpInfo1 & + HT_OP_INFO1_STA_CHNL_WIDTH) >> + HT_OP_INFO1_STA_CHNL_WIDTH_OFFSET); + } else +#endif + { + prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_80; + prBssInfo->ucHtOpInfo1 |= HT_OP_INFO1_STA_CHNL_WIDTH; + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; + } + break; + case VHT_OP_MODE_CHANNEL_WIDTH_160_80P80: +/* Determine BW160 or BW80+BW80 by VHT OP Info */ +#if CFG_OPMODE_CONFLICT_OPINFO + if ((prBssInfo->ucVhtChannelWidth != + VHT_OP_CHANNEL_WIDTH_160) && + (prBssInfo->ucVhtChannelWidth != + VHT_OP_CHANNEL_WIDTH_80P80)) { + DBGLOG(RLM, WARN, + "VHT_OP != OPmode:%d, follow VHT_OP to VHT_OP:%d HT_OP:%d\n", + ucVhtOpModeChannelWidth, + prBssInfo->ucVhtChannelWidth, + (uint8_t)(prBssInfo->ucHtOpInfo1 & + HT_OP_INFO1_STA_CHNL_WIDTH) >> + HT_OP_INFO1_STA_CHNL_WIDTH_OFFSET); + } else +#endif + { + prBssInfo->ucHtOpInfo1 |= HT_OP_INFO1_STA_CHNL_WIDTH; + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; + } + break; + default: + break; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Update parameters from Association Response frame + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static void rlmRecAssocRespIeInfoForClient(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + uint8_t *pucIE, uint16_t u2IELength) +{ + uint16_t u2Offset; + struct STA_RECORD *prStaRec; + u_int8_t fgIsHasHtCap = FALSE; + u_int8_t fgIsHasVhtCap = FALSE; +#if (CFG_SUPPORT_802_11AX == 1) + u_int8_t fgIsHasHeCap = FALSE; +#endif + struct BSS_DESC *prBssDesc; + struct PARAM_SSID rSsid; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(pucIE); + + prStaRec = prBssInfo->prStaRecOfAP; + + if (!prStaRec) + return; + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, prBssInfo->aucSSID, + prBssInfo->ucSSIDLen); + prBssDesc = scanSearchBssDescByBssidAndSsid( + prAdapter, prStaRec->aucMacAddr, TRUE, &rSsid); + + 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(struct IE_HT_CAP) - 2)) + break; + fgIsHasHtCap = TRUE; + break; +#if CFG_SUPPORT_802_11AC + case ELEM_ID_VHT_CAP: + if (!RLM_NET_IS_11AC(prBssInfo) || + IE_LEN(pucIE) != (sizeof(struct IE_VHT_CAP) - 2)) + break; + fgIsHasVhtCap = TRUE; + break; +#endif +#if (CFG_SUPPORT_802_11AX == 1) + case ELEM_ID_RESERVED: + if (fgEfuseCtrlAxOn == 1) { + if (IE_ID_EXT(pucIE) != ELEM_EXT_ID_HE_CAP || + !RLM_NET_IS_11AX(prBssInfo)) + break; + fgIsHasHeCap = TRUE; + } + break; +#endif + + default: + break; + } /* end of switch */ + } /* end of IE_FOR_EACH */ + + if (!fgIsHasHtCap) { + prStaRec->ucDesiredPhyTypeSet &= ~PHY_TYPE_BIT_HT; + if (prBssDesc) { + if (prBssDesc->ucPhyTypeSet & PHY_TYPE_BIT_HT) { + DBGLOG(RLM, WARN, + "PhyTypeSet in Beacon and AssocResp are unsync. "); + DBGLOG(RLM, WARN, + "Follow AssocResp to disable HT.\n"); + } + } + } + if (!fgIsHasVhtCap) { + prStaRec->ucDesiredPhyTypeSet &= ~PHY_TYPE_BIT_VHT; + if (prBssDesc) { + if (prBssDesc->ucPhyTypeSet & PHY_TYPE_BIT_VHT) { + DBGLOG(RLM, WARN, + "PhyTypeSet in Beacon and AssocResp are unsync. "); + DBGLOG(RLM, WARN, + "Follow AssocResp to disable VHT.\n"); + } + } + } +#if (CFG_SUPPORT_802_11AX == 1) + if (fgEfuseCtrlAxOn == 1) { + if (!fgIsHasHeCap) { + prStaRec->ucDesiredPhyTypeSet &= ~PHY_TYPE_BIT_HE; + if (prBssDesc) { + if (prBssDesc->ucPhyTypeSet & PHY_TYPE_BIT_HE) { + DBGLOG(RLM, WARN, "PhyTypeSet are unsync. "); + DBGLOG(RLM, WARN, "Disable HE per assoc.\n"); + } + } + } + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief AIS or P2P GC. + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static u_int8_t rlmRecBcnFromNeighborForClient(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct SW_RFB *prSwRfb, + uint8_t *pucIE, + uint16_t u2IELength) +{ + uint16_t u2Offset, i; + uint8_t ucPriChannel, ucSecChannel; + enum ENUM_CHNL_EXT eSCO; + u_int8_t fgHtBss, fg20mReq; + enum ENUM_BAND eBand = 0; + struct RX_DESC_OPS_T *prRxDescOps; + + ASSERT(prAdapter); + ASSERT(prBssInfo && prSwRfb); + ASSERT(pucIE); + prRxDescOps = prAdapter->chip_info->prRxDescOps; + + /* 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: { + struct IE_HT_CAP *prHtCap; + + if (IE_LEN(pucIE) != (sizeof(struct IE_HT_CAP) - 2)) + break; + + prHtCap = (struct IE_HT_CAP *)pucIE; + if (prHtCap->u2HtCapInfo & HT_CAP_INFO_40M_INTOLERANT) + fg20mReq = TRUE; + fgHtBss = TRUE; + break; + } + case ELEM_ID_HT_OP: { + struct IE_HT_OP *prHtOp; + + if (IE_LEN(pucIE) != (sizeof(struct IE_HT_OP) - 2)) + break; + + prHtOp = (struct IE_HT_OP *)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 ENUM_CHNL_EXT)(prHtOp->ucInfo1 & + HT_OP_INFO1_SCO); + break; + } + case ELEM_ID_20_40_BSS_COEXISTENCE: { + struct IE_20_40_COEXIST *prCoexist; + + if (IE_LEN(pucIE) != + (sizeof(struct IE_20_40_COEXIST) - 2)) + break; + + prCoexist = (struct IE_20_40_COEXIST *)pucIE; + if (prCoexist->ucData & BSS_COEXIST_40M_INTOLERANT) + fg20mReq = TRUE; + break; + } + case ELEM_ID_DS_PARAM_SET: + if (IE_LEN(pucIE) != + (sizeof(struct IE_DS_PARAM_SET) - 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. + */ + RX_STATUS_GET(prRxDescOps, eBand, get_rf_band, prSwRfb->prRxStatus); + if (eBand != BAND_2G4) + return FALSE; + + if (ucPriChannel == 0 || ucPriChannel > 14) { + RX_STATUS_GET( + prRxDescOps, + ucPriChannel, + get_ch_num, + prSwRfb->prRxStatus); + } + + 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 u_int8_t rlmRecBcnInfoForClient(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct SW_RFB *prSwRfb, uint8_t *pucIE, + uint16_t u2IELength) +{ + /* For checking if syncing params are different from + * last syncing and need to sync again + */ + struct CMD_SET_BSS_RLM_PARAM rBssRlmParam; + u_int8_t fgNewParameter = FALSE; + + 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 = + ((struct WLAN_BEACON_FRAME *)(prSwRfb->pvHeader))->u2CapInfo; + prBssInfo->fgUseShortSlotTime = + ((prBssInfo->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME) || + (prBssInfo->eBand != BAND_2G4)) + ? TRUE + : FALSE; + + /* Check if syncing params are different from last syncing and need to + * sync again + * If yes, return TRUE and sync with FW; Otherwise, return FALSE. + */ + rBssRlmParam.ucRfBand = (u_int8_t)prBssInfo->eBand; + rBssRlmParam.ucPrimaryChannel = prBssInfo->ucPrimaryChannel; + rBssRlmParam.ucRfSco = (u_int8_t)prBssInfo->eBssSCO; + rBssRlmParam.ucErpProtectMode = (u_int8_t)prBssInfo->fgErpProtectMode; + rBssRlmParam.ucHtProtectMode = (u_int8_t)prBssInfo->eHtProtectMode; + rBssRlmParam.ucGfOperationMode = (u_int8_t)prBssInfo->eGfOperationMode; + rBssRlmParam.ucTxRifsMode = (u_int8_t)prBssInfo->eRifsOperationMode; + rBssRlmParam.u2HtOpInfo3 = prBssInfo->u2HtOpInfo3; + rBssRlmParam.u2HtOpInfo2 = prBssInfo->u2HtOpInfo2; + rBssRlmParam.ucHtOpInfo1 = prBssInfo->ucHtOpInfo1; + rBssRlmParam.ucUseShortPreamble = prBssInfo->fgUseShortPreamble; + rBssRlmParam.ucUseShortSlotTime = prBssInfo->fgUseShortSlotTime; + rBssRlmParam.ucVhtChannelWidth = prBssInfo->ucVhtChannelWidth; + rBssRlmParam.ucVhtChannelFrequencyS1 = + prBssInfo->ucVhtChannelFrequencyS1; + rBssRlmParam.ucVhtChannelFrequencyS2 = + prBssInfo->ucVhtChannelFrequencyS2; + rBssRlmParam.u2VhtBasicMcsSet = prBssInfo->u2VhtBasicMcsSet; + rBssRlmParam.ucRxNss = prBssInfo->ucOpRxNss; + rBssRlmParam.ucTxNss = prBssInfo->ucOpTxNss; + + rlmRecIeInfoForClient(prAdapter, prBssInfo, pucIE, u2IELength); + + if (rBssRlmParam.ucRfBand != prBssInfo->eBand || + rBssRlmParam.ucPrimaryChannel != prBssInfo->ucPrimaryChannel || + rBssRlmParam.ucRfSco != prBssInfo->eBssSCO || + rBssRlmParam.ucErpProtectMode != prBssInfo->fgErpProtectMode || + rBssRlmParam.ucHtProtectMode != prBssInfo->eHtProtectMode || + rBssRlmParam.ucGfOperationMode != prBssInfo->eGfOperationMode || + rBssRlmParam.ucTxRifsMode != prBssInfo->eRifsOperationMode || + rBssRlmParam.u2HtOpInfo3 != prBssInfo->u2HtOpInfo3 || + rBssRlmParam.u2HtOpInfo2 != prBssInfo->u2HtOpInfo2 || + rBssRlmParam.ucHtOpInfo1 != prBssInfo->ucHtOpInfo1 || + rBssRlmParam.ucUseShortPreamble != + prBssInfo->fgUseShortPreamble || + rBssRlmParam.ucUseShortSlotTime != + prBssInfo->fgUseShortSlotTime || + rBssRlmParam.ucVhtChannelWidth != + prBssInfo->ucVhtChannelWidth || + rBssRlmParam.ucVhtChannelFrequencyS1 != + prBssInfo->ucVhtChannelFrequencyS1 || + rBssRlmParam.ucVhtChannelFrequencyS2 != + prBssInfo->ucVhtChannelFrequencyS2 || + rBssRlmParam.u2VhtBasicMcsSet != prBssInfo->u2VhtBasicMcsSet || + rBssRlmParam.ucRxNss != prBssInfo->ucOpRxNss || + rBssRlmParam.ucTxNss != prBssInfo->ucOpTxNss) + fgNewParameter = TRUE; + else { + DBGLOG(RLM, TRACE, + "prBssInfo's params are all the same! not to sync!\n"); + fgNewParameter = FALSE; + } + + return fgNewParameter; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmProcessBcn(struct ADAPTER *prAdapter, struct SW_RFB *prSwRfb, + uint8_t *pucIE, uint16_t u2IELength) +{ + struct BSS_INFO *prBssInfo; + u_int8_t fgNewParameter; +#if (CFG_SUPPORT_802_11AX == 1) + u_int8_t fgNewSRParam = FALSE; +#endif + uint8_t i; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + ASSERT(pucIE); + + fgNewParameter = FALSE; + + /* When concurrent networks exist, GO shall have the same handle as + * the other BSS, so the Beacon shall be processed for bandwidth and + * protection mechanism. + * Note1: we do not have 2 AP (GO) cases simultaneously now. + * Note2: If we are GO, concurrent AIS AP should detect it and reflect + * action in its Beacon, so AIS STA just follows Beacon from AP. + */ + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + + if (IS_BSS_BOW(prBssInfo)) + continue; + + if (IS_BSS_ACTIVE(prBssInfo)) { + if (prBssInfo->eCurrentOPMode == + OP_MODE_INFRASTRUCTURE && + prBssInfo->eConnectionState == + MEDIA_STATE_CONNECTED) { + /* P2P client or AIS infra STA */ + if (EQUAL_MAC_ADDR( + prBssInfo->aucBSSID, + ((struct WLAN_MAC_MGMT_HEADER + *)(prSwRfb->pvHeader)) + ->aucBSSID)) { + + fgNewParameter = rlmRecBcnInfoForClient( + prAdapter, prBssInfo, prSwRfb, + pucIE, u2IELength); +#if (CFG_SUPPORT_802_11AX == 1) + if (fgEfuseCtrlAxOn == 1) { + fgNewSRParam = heRlmRecHeSRParams( + prAdapter, prBssInfo, + prSwRfb, pucIE, u2IELength); + } +#endif + } 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: Nothing */ + /* To do: Ad-hoc */ + } + + /* Appy new parameters if necessary */ + if (fgNewParameter) { + rlmSyncOperationParams(prAdapter, prBssInfo); + fgNewParameter = FALSE; + } +#if (CFG_SUPPORT_802_11AX == 1) + if (fgEfuseCtrlAxOn == 1) { + if (fgNewSRParam) { + nicRlmUpdateSRParams(prAdapter, + prBssInfo->ucBssIndex); + fgNewSRParam = FALSE; + } + } +#endif + + } /* end of IS_BSS_ACTIVE() */ + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function should be invoked after judging successful association. + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmProcessAssocRsp(struct ADAPTER *prAdapter, struct SW_RFB *prSwRfb, + uint8_t *pucIE, uint16_t u2IELength) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint8_t ucPriChannel; +#if (CFG_SUPPORT_802_11AX == 1) + uint8_t fgNewSRParam; +#endif + + ASSERT(prAdapter); + ASSERT(prSwRfb); + ASSERT(pucIE); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (!prStaRec) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + if (!prBssInfo) + return; + + if (prStaRec != prBssInfo->prStaRecOfAP) + return; + + /* 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) || + (prBssInfo->eBand != BAND_2G4)) + ? TRUE + : FALSE; + ucPriChannel = + rlmRecIeInfoForClient(prAdapter, prBssInfo, pucIE, u2IELength); + + /*Update the parameters from Association Response only, + *if the parameters need to be updated by both Beacon and Association + *Response, + *user should use another function, rlmRecIeInfoForClient() + */ + rlmRecAssocRespIeInfoForClient(prAdapter, prBssInfo, pucIE, u2IELength); + + if (prBssInfo->ucPrimaryChannel != ucPriChannel) { + DBGLOG(RLM, INFO, + "Use RF pri channel[%u].Pri channel in HT OP IE is :[%u]\n", + prBssInfo->ucPrimaryChannel, ucPriChannel); + } + /* Avoid wrong primary channel info in HT operation + * IE info when accept association response + */ +#if 0 + if (ucPriChannel > 0) + prBssInfo->ucPrimaryChannel = ucPriChannel; +#endif + + if (!RLM_NET_IS_11N(prBssInfo) || + !(prStaRec->u2HtCapInfo & HT_CAP_INFO_SUP_CHNL_WIDTH)) + prBssInfo->fg40mBwAllowed = FALSE; + +#if (CFG_SUPPORT_802_11AX == 1) + if (fgEfuseCtrlAxOn == 1) { + fgNewSRParam = heRlmRecHeSRParams(prAdapter, prBssInfo, + prSwRfb, pucIE, u2IELength); + /* ASSERT(fgNewSRParam); */ + nicRlmUpdateSRParams(prAdapter, prBssInfo->ucBssIndex); + } +#endif + + /* Note: Update its capabilities to WTBL by cnmStaRecChangeState(), + * which + * shall be invoked afterwards. + * Update channel, bandwidth and protection mode by nicUpdateBss() + */ +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmProcessHtAction(struct ADAPTER *prAdapter, struct SW_RFB *prSwRfb) +{ + struct ACTION_NOTIFY_CHNL_WIDTH_FRAME *prRxFrame; + struct ACTION_SM_POWER_SAVE_FRAME *prRxSmpsFrame; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + uint16_t u2HtCapInfoBitmask = 0; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxFrame = (struct ACTION_NOTIFY_CHNL_WIDTH_FRAME *)prSwRfb->pvHeader; + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (!prStaRec) + return; + + switch (prRxFrame->ucAction) { + case ACTION_HT_NOTIFY_CHANNEL_WIDTH: + if (prStaRec->ucStaState != STA_STATE_3 || + prSwRfb->u2PacketLen < + sizeof(struct 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 + */ + /* 1. Update StaRec for AP/STA mode */ + if (prRxFrame->ucChannelWidth == HT_NOTIFY_CHANNEL_WIDTH_20) + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SUP_CHNL_WIDTH; + else if (prRxFrame->ucChannelWidth == + HT_NOTIFY_CHANNEL_WIDTH_ANY_SUPPORT_CAHNNAEL_WIDTH) + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; + + cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); + + /* 2. Update BssInfo for STA mode */ + prBssInfo = prAdapter->aprBssInfo[prStaRec->ucBssIndex]; + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + if (prRxFrame->ucChannelWidth == + HT_NOTIFY_CHANNEL_WIDTH_20) { + prBssInfo->ucHtOpInfo1 &= + ~HT_OP_INFO1_STA_CHNL_WIDTH; + prBssInfo->eBssSCO = CHNL_EXT_SCN; + } else if ( + prRxFrame->ucChannelWidth == + HT_NOTIFY_CHANNEL_WIDTH_ANY_SUPPORT_CAHNNAEL_WIDTH) + prBssInfo->ucHtOpInfo1 |= + HT_OP_INFO1_STA_CHNL_WIDTH; + + /* Revise by own OP BW if needed */ + if (prBssInfo->fgIsOpChangeChannelWidth && + prBssInfo->ucOpChangeChannelWidth == MAX_BW_20MHZ) { + prBssInfo->ucHtOpInfo1 &= + ~(HT_OP_INFO1_SCO | + HT_OP_INFO1_STA_CHNL_WIDTH); + prBssInfo->eBssSCO = CHNL_EXT_SCN; + } + + /* 3. Update OP BW to FW */ + rlmSyncOperationParams(prAdapter, prBssInfo); + } + break; + /* Support SM power save */ /* TH3_Huang */ + case ACTION_HT_SM_POWER_SAVE: + prRxSmpsFrame = + (struct ACTION_SM_POWER_SAVE_FRAME *)prSwRfb->pvHeader; + if (prStaRec->ucStaState != STA_STATE_3 || + prSwRfb->u2PacketLen < + sizeof(struct ACTION_SM_POWER_SAVE_FRAME)) { + return; + } + + /* The SM power enable bit is different definition in HtCap and + * SMpower IE field + */ + if (!(prRxSmpsFrame->ucSmPowerCtrl & + (HT_SM_POWER_SAVE_CONTROL_ENABLED | + HT_SM_POWER_SAVE_CONTROL_SM_MODE))) + u2HtCapInfoBitmask |= HT_CAP_INFO_SM_POWER_SAVE; + + /* Support SMPS action frame, TH3_Huang */ + /* Update StaRec if SM power state changed */ + if ((prStaRec->u2HtCapInfo & HT_CAP_INFO_SM_POWER_SAVE) != + u2HtCapInfoBitmask) { + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SM_POWER_SAVE; + prStaRec->u2HtCapInfo |= u2HtCapInfoBitmask; + DBGLOG(RLM, INFO, + "rlmProcessHtAction -- SMPS change u2HtCapInfo to (%x)\n", + prStaRec->u2HtCapInfo); + cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); + } + break; + default: + break; + } +} + +#if CFG_SUPPORT_802_11AC +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmProcessVhtAction(struct ADAPTER *prAdapter, struct SW_RFB *prSwRfb) +{ + struct ACTION_OP_MODE_NOTIFICATION_FRAME *prRxFrame; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + uint8_t ucVhtOpModeChannelWidth = 0; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxFrame = + (struct ACTION_OP_MODE_NOTIFICATION_FRAME *)prSwRfb->pvHeader; + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (!prStaRec) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + if (!prBssInfo) + return; + + switch (prRxFrame->ucAction) { + /* Support Operating mode notification action frame, TH3_Huang */ + case ACTION_OPERATING_MODE_NOTIFICATION: + if (prStaRec->ucStaState != STA_STATE_3 || + prSwRfb->u2PacketLen < + sizeof(struct ACTION_OP_MODE_NOTIFICATION_FRAME)) { + return; + } + + if (((prRxFrame->ucOperatingMode & VHT_OP_MODE_RX_NSS_TYPE) != + VHT_OP_MODE_RX_NSS_TYPE) && + (prStaRec->ucVhtOpMode != prRxFrame->ucOperatingMode)) { + /* 1. Fill OP mode notification info */ + prStaRec->ucVhtOpMode = prRxFrame->ucOperatingMode; + DBGLOG(RLM, INFO, + "rlmProcessVhtAction -- Update ucVhtOpMode to 0x%x\n", + prStaRec->ucVhtOpMode); + + /* 2. Modify channel width parameters */ + ucVhtOpModeChannelWidth = prRxFrame->ucOperatingMode & + VHT_OP_MODE_CHANNEL_WIDTH; + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + if (ucVhtOpModeChannelWidth == + VHT_OP_MODE_CHANNEL_WIDTH_20) + prStaRec->u2HtCapInfo &= + ~HT_CAP_INFO_SUP_CHNL_WIDTH; + else /* for other 3 VHT cases: 40/80/160 */ + prStaRec->u2HtCapInfo |= + HT_CAP_INFO_SUP_CHNL_WIDTH; + } else if (prBssInfo->eCurrentOPMode == + OP_MODE_INFRASTRUCTURE) + rlmRecOpModeBwForClient(ucVhtOpModeChannelWidth, + prBssInfo); + + /* 3. Update StaRec to FW */ + /* As defined in spec, 11 means not support this MCS */ + if (((prRxFrame->ucOperatingMode & VHT_OP_MODE_RX_NSS) + >> VHT_OP_MODE_RX_NSS_OFFSET) == + VHT_OP_MODE_NSS_2) { + prStaRec->u2VhtRxMcsMap = BITS(0, 15) & + (~(VHT_CAP_INFO_MCS_1SS_MASK | + VHT_CAP_INFO_MCS_2SS_MASK)); + + prStaRec->u2VhtRxMcsMap |= + (prStaRec->u2VhtRxMcsMapAssoc & + (VHT_CAP_INFO_MCS_1SS_MASK | + VHT_CAP_INFO_MCS_2SS_MASK)); + + DBGLOG(RLM, INFO, + "NSS=2 RxMcsMap:0x%x, McsMapAssoc:0x%x\n", + prStaRec->u2VhtRxMcsMap, + prStaRec->u2VhtRxMcsMapAssoc); + } else { + /* NSS = 1 or others */ + prStaRec->u2VhtRxMcsMap = BITS(0, 15) & + (~VHT_CAP_INFO_MCS_1SS_MASK); + + prStaRec->u2VhtRxMcsMap |= + (prStaRec->u2VhtRxMcsMapAssoc & + VHT_CAP_INFO_MCS_1SS_MASK); + + DBGLOG(RLM, INFO, + "NSS=1 RxMcsMap:0x%x, McsMapAssoc:0x%x\n", + prStaRec->u2VhtRxMcsMap, + prStaRec->u2VhtRxMcsMapAssoc); + } + cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); + + /* 4. Update BW parameters in BssInfo for STA mode only + */ + if (prBssInfo->eCurrentOPMode == + OP_MODE_INFRASTRUCTURE) { + /* 4.1 Revise by own OP BW if needed for STA + * mode only + */ + if (prBssInfo->fgIsOpChangeChannelWidth) { + /* VHT */ + if (rlmGetVhtOpBwByBssOpBw( + prBssInfo + ->ucOpChangeChannelWidth) < + prBssInfo->ucVhtChannelWidth) + rlmFillVhtOpInfoByBssOpBw( + prBssInfo, + prBssInfo + ->ucOpChangeChannelWidth); + /* HT */ + if (prBssInfo + ->fgIsOpChangeChannelWidth && + prBssInfo->ucOpChangeChannelWidth == + MAX_BW_20MHZ) { + prBssInfo->ucHtOpInfo1 &= ~( + HT_OP_INFO1_SCO | + HT_OP_INFO1_STA_CHNL_WIDTH); + prBssInfo->eBssSCO = + CHNL_EXT_SCN; + } + } + + /* 4.2 Check if OP BW parameter valid */ + if (!rlmDomainIsValidRfSetting( + prAdapter, prBssInfo->eBand, + prBssInfo->ucPrimaryChannel, + prBssInfo->eBssSCO, + prBssInfo->ucVhtChannelWidth, + prBssInfo->ucVhtChannelFrequencyS1, + prBssInfo->ucVhtChannelFrequencyS2)) { + + DBGLOG(RLM, WARN, + "rlmProcessVhtAction invalid RF settings\n"); + + /* Error Handling for Non-predicted IE - + * Fixed to set 20MHz + */ + prBssInfo->ucVhtChannelWidth = + CW_20_40MHZ; + prBssInfo->ucVhtChannelFrequencyS1 = 0; + prBssInfo->ucVhtChannelFrequencyS2 = 0; + prBssInfo->eBssSCO = CHNL_EXT_SCN; + prBssInfo->ucHtOpInfo1 &= + ~(HT_OP_INFO1_SCO | + HT_OP_INFO1_STA_CHNL_WIDTH); + } + + /* 4.3 Update BSS OP BW to FW for STA mode only + */ + rlmSyncOperationParams(prAdapter, prBssInfo); + } + } + break; + default: + break; + } +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function should be invoked after judging successful association. + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmFillSyncCmdParam(struct CMD_SET_BSS_RLM_PARAM *prCmdBody, + struct BSS_INFO *prBssInfo) +{ + if (!prCmdBody || !prBssInfo) + return; + + prCmdBody->ucBssIndex = prBssInfo->ucBssIndex; + prCmdBody->ucRfBand = (uint8_t)prBssInfo->eBand; + prCmdBody->ucPrimaryChannel = prBssInfo->ucPrimaryChannel; + prCmdBody->ucRfSco = (uint8_t)prBssInfo->eBssSCO; + prCmdBody->ucErpProtectMode = (uint8_t)prBssInfo->fgErpProtectMode; + prCmdBody->ucHtProtectMode = (uint8_t)prBssInfo->eHtProtectMode; + prCmdBody->ucGfOperationMode = (uint8_t)prBssInfo->eGfOperationMode; + prCmdBody->ucTxRifsMode = (uint8_t)prBssInfo->eRifsOperationMode; + prCmdBody->u2HtOpInfo3 = prBssInfo->u2HtOpInfo3; + prCmdBody->u2HtOpInfo2 = prBssInfo->u2HtOpInfo2; + prCmdBody->ucHtOpInfo1 = prBssInfo->ucHtOpInfo1; + prCmdBody->ucUseShortPreamble = prBssInfo->fgUseShortPreamble; + prCmdBody->ucUseShortSlotTime = prBssInfo->fgUseShortSlotTime; + prCmdBody->ucVhtChannelWidth = prBssInfo->ucVhtChannelWidth; + prCmdBody->ucVhtChannelFrequencyS1 = prBssInfo->ucVhtChannelFrequencyS1; + prCmdBody->ucVhtChannelFrequencyS2 = prBssInfo->ucVhtChannelFrequencyS2; + prCmdBody->u2VhtBasicMcsSet = prBssInfo->u2BSSBasicRateSet; + prCmdBody->ucTxNss = prBssInfo->ucOpTxNss; + prCmdBody->ucRxNss = prBssInfo->ucOpRxNss; + + 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 w=%d s1=%d s2=%d RxN=%d, TxN=%d\n", + prCmdBody->ucBssIndex, prCmdBody->ucRfBand, + prCmdBody->ucPrimaryChannel, prCmdBody->ucRfSco, + prCmdBody->ucErpProtectMode, prCmdBody->ucHtProtectMode, + prCmdBody->ucHtOpInfo1, prCmdBody->ucUseShortSlotTime, + prCmdBody->ucUseShortPreamble, + prCmdBody->ucVhtChannelWidth, + prCmdBody->ucVhtChannelFrequencyS1, + prCmdBody->ucVhtChannelFrequencyS2, + prCmdBody->ucRxNss, + prCmdBody->ucTxNss); + } else { + DBGLOG(RLM, INFO, "N=%d closed\n", prCmdBody->ucBssIndex); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo) +{ + struct CMD_SET_BSS_RLM_PARAM *prCmdBody; + uint32_t rStatus; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + + prCmdBody = (struct CMD_SET_BSS_RLM_PARAM *)cnmMemAlloc( + prAdapter, RAM_TYPE_BUF, sizeof(struct CMD_SET_BSS_RLM_PARAM)); + + /* ASSERT(prCmdBody); */ + /* To do: exception handle */ + if (!prCmdBody) { + DBGLOG(RLM, WARN, "No buf for sync RLM params (Net=%d)\n", + prBssInfo->ucBssIndex); + 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(struct CMD_SET_BSS_RLM_PARAM), /* u4SetQueryInfoLen */ + (uint8_t *)prCmdBody, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + /* ASSERT(rStatus == WLAN_STATUS_PENDING); */ + if (rStatus != WLAN_STATUS_PENDING) + DBGLOG(RLM, WARN, "rlmSyncOperationParams set cmd fail\n"); + + cnmMemFree(prAdapter, prCmdBody); +} + +#if CFG_SUPPORT_AAA +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function should be invoked after judging successful association. + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmProcessAssocReq(struct ADAPTER *prAdapter, struct SW_RFB *prSwRfb, + uint8_t *pucIE, uint16_t u2IELength) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint16_t u2Offset; + struct IE_HT_CAP *prHtCap; +#if CFG_SUPPORT_802_11AC + struct IE_VHT_CAP *prVhtCap = NULL; + struct IE_OP_MODE_NOTIFICATION + *prOPModeNotification; /* Operation Mode Notification */ + u_int8_t fgHasOPModeIE = FALSE; +#endif + + ASSERT(prAdapter); + ASSERT(prSwRfb); + ASSERT(pucIE); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (!prStaRec) + return; + ASSERT(prStaRec->ucBssIndex <= prAdapter->ucHwBssIdNum); + + prBssInfo = prAdapter->aprBssInfo[prStaRec->ucBssIndex]; + + 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(struct IE_HT_CAP) - 2)) + break; + prHtCap = (struct IE_HT_CAP *)pucIE; + prStaRec->ucMcsSet = + prHtCap->rSupMcsSet.aucRxMcsBitmask[0]; + prStaRec->fgSupMcs32 = + (prHtCap->rSupMcsSet.aucRxMcsBitmask[32 / 8] & + BIT(0)) + ? TRUE + : FALSE; + + kalMemCopy( + prStaRec->aucRxMcsBitmask, + prHtCap->rSupMcsSet.aucRxMcsBitmask, + /*SUP_MCS_RX_BITMASK_OCTET_NUM */ + sizeof(prStaRec->aucRxMcsBitmask)); + + prStaRec->u2HtCapInfo = prHtCap->u2HtCapInfo; + + /* Set Short LDPC Tx capability */ + if (IS_FEATURE_FORCE_ENABLED( + prAdapter->rWifiVar.ucTxLdpc)) + prStaRec->u2HtCapInfo |= HT_CAP_INFO_LDPC_CAP; + else if (IS_FEATURE_DISABLED( + prAdapter->rWifiVar.ucTxLdpc)) + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_LDPC_CAP; + + /* Set STBC Tx capability */ + if (IS_FEATURE_FORCE_ENABLED( + prAdapter->rWifiVar.ucTxStbc)) + prStaRec->u2HtCapInfo |= HT_CAP_INFO_TX_STBC; + else if (IS_FEATURE_DISABLED( + prAdapter->rWifiVar.ucTxStbc)) + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_TX_STBC; + /* Set Short GI Tx capability */ + if (IS_FEATURE_FORCE_ENABLED( + prAdapter->rWifiVar.ucTxShortGI)) { + prStaRec->u2HtCapInfo |= + HT_CAP_INFO_SHORT_GI_20M; + prStaRec->u2HtCapInfo |= + HT_CAP_INFO_SHORT_GI_40M; + } else if (IS_FEATURE_DISABLED( + prAdapter->rWifiVar.ucTxShortGI)) { + prStaRec->u2HtCapInfo &= + ~HT_CAP_INFO_SHORT_GI_20M; + prStaRec->u2HtCapInfo &= + ~HT_CAP_INFO_SHORT_GI_40M; + } + + /* Set HT Greenfield Tx capability */ + if (IS_FEATURE_FORCE_ENABLED( + prAdapter->rWifiVar.ucTxGf)) + prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + else if (IS_FEATURE_DISABLED( + prAdapter->rWifiVar.ucTxGf)) + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_HT_GF; + + prStaRec->ucAmpduParam = prHtCap->ucAmpduParam; + prStaRec->u2HtExtendedCap = prHtCap->u2HtExtendedCap; + prStaRec->u4TxBeamformingCap = + prHtCap->u4TxBeamformingCap; + prStaRec->ucAselCap = prHtCap->ucAselCap; + break; + +#if (CFG_SUPPORT_802_11AX == 1) + case ELEM_ID_RESERVED: + if (IE_ID_EXT(pucIE) == ELEM_EXT_ID_HE_CAP) + heRlmRecHeCapInfo(prAdapter, prStaRec, pucIE); + break; +#endif + +#if CFG_SUPPORT_802_11AC + case ELEM_ID_VHT_CAP: + if (!RLM_NET_IS_11AC(prBssInfo) || + IE_LEN(pucIE) != (sizeof(struct IE_VHT_CAP) - 2)) + break; + + prVhtCap = (struct IE_VHT_CAP *)pucIE; + + prStaRec->u4VhtCapInfo = prVhtCap->u4VhtCapInfo; + + /* Set Tx LDPC capability */ + if (IS_FEATURE_FORCE_ENABLED( + prAdapter->rWifiVar.ucTxLdpc)) + prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_RX_LDPC; + else if (IS_FEATURE_DISABLED( + prAdapter->rWifiVar.ucTxLdpc)) + prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_RX_LDPC; + + /* Set Tx STBC capability */ + if (IS_FEATURE_FORCE_ENABLED( + prAdapter->rWifiVar.ucTxStbc)) + prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_TX_STBC; + else if (IS_FEATURE_DISABLED( + prAdapter->rWifiVar.ucTxStbc)) + prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_TX_STBC; + + /* Set Tx TXOP PS capability */ + if (IS_FEATURE_FORCE_ENABLED( + prAdapter->rWifiVar.ucTxopPsTx)) + prStaRec->u4VhtCapInfo |= + VHT_CAP_INFO_VHT_TXOP_PS; + else if (IS_FEATURE_DISABLED( + prAdapter->rWifiVar.ucTxopPsTx)) + prStaRec->u4VhtCapInfo &= + ~VHT_CAP_INFO_VHT_TXOP_PS; + + /* Set Tx Short GI capability */ + if (IS_FEATURE_FORCE_ENABLED( + prAdapter->rWifiVar.ucTxShortGI)) { + prStaRec->u4VhtCapInfo |= + VHT_CAP_INFO_SHORT_GI_80; + prStaRec->u4VhtCapInfo |= + VHT_CAP_INFO_SHORT_GI_160_80P80; + } else if (IS_FEATURE_DISABLED( + prAdapter->rWifiVar.ucTxShortGI)) { + prStaRec->u4VhtCapInfo &= + ~VHT_CAP_INFO_SHORT_GI_80; + prStaRec->u4VhtCapInfo &= + ~VHT_CAP_INFO_SHORT_GI_160_80P80; + } + + prStaRec->u2VhtRxMcsMap = + prVhtCap->rVhtSupportedMcsSet.u2RxMcsMap; + + prStaRec->u2VhtRxMcsMapAssoc = + prStaRec->u2VhtRxMcsMap; + + prStaRec->u2VhtRxHighestSupportedDataRate = + prVhtCap->rVhtSupportedMcsSet + .u2RxHighestSupportedDataRate; + prStaRec->u2VhtTxMcsMap = + prVhtCap->rVhtSupportedMcsSet.u2TxMcsMap; + prStaRec->u2VhtTxHighestSupportedDataRate = + prVhtCap->rVhtSupportedMcsSet + .u2TxHighestSupportedDataRate; + + /* Set initial value of VHT OP mode */ + prStaRec->ucVhtOpMode = 0; + prStaRec->ucVhtOpMode |= + rlmGetOpModeBwByVhtAndHtOpInfo(prBssInfo); + prStaRec->ucVhtOpMode |= + ((rlmGetSupportRxNssInVhtCap(prVhtCap) - 1) + << VHT_OP_MODE_RX_NSS_OFFSET) & + VHT_OP_MODE_RX_NSS; + + break; + case ELEM_ID_OP_MODE: + if (!RLM_NET_IS_11AC(prBssInfo) || + IE_LEN(pucIE) != + (sizeof(struct IE_OP_MODE_NOTIFICATION) - + 2)) + break; + prOPModeNotification = + (struct IE_OP_MODE_NOTIFICATION *)pucIE; + + if ((prOPModeNotification->ucOpMode & + VHT_OP_MODE_RX_NSS_TYPE) != + VHT_OP_MODE_RX_NSS_TYPE) { + fgHasOPModeIE = TRUE; + } + + break; + +#endif + + default: + break; + } /* end of switch */ + } /* end of IE_FOR_EACH */ +#if CFG_SUPPORT_802_11AC + /*Fill by OP Mode IE after completing parsing all IE to make sure it + * won't be overwrite + */ + if (fgHasOPModeIE == TRUE) + prStaRec->ucVhtOpMode = prOPModeNotification->ucOpMode; +#endif +} +#endif /* CFG_SUPPORT_AAA */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief It is for both STA and AP modes + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmBssInitForAPandIbss(struct ADAPTER *prAdapter, + struct BSS_INFO *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(struct ADAPTER *prAdapter, struct BSS_INFO *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(struct ADAPTER *prAdapter, struct BSS_INFO *prBssInfo) +{ + ASSERT(prAdapter); + ASSERT(prBssInfo); + + /* HT related parameters */ + prBssInfo->ucHtOpInfo1 = 0; /* RIFS disabled. 20MHz */ + prBssInfo->u2HtOpInfo2 = 0; + prBssInfo->u2HtOpInfo3 = 0; + +#if CFG_SUPPORT_802_11AC + prBssInfo->ucVhtChannelWidth = 0; /* VHT_OP_CHANNEL_WIDTH_80; */ + prBssInfo->ucVhtChannelFrequencyS1 = 0; /* 42; */ + prBssInfo->ucVhtChannelFrequencyS2 = 0; + prBssInfo->u2VhtBasicMcsSet = 0; /* 0xFFFF; */ +#endif + + 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 */ + + /* OP mode change control parameters */ + prBssInfo->fgIsOpChangeChannelWidth = FALSE; + prBssInfo->fgIsOpChangeRxNss = FALSE; + prBssInfo->fgIsOpChangeTxNss = FALSE; + +#if (CFG_SUPPORT_802_11AX == 1) + if (fgEfuseCtrlAxOn == 1) { + /* MU EDCA params */ + prBssInfo->ucMUEdcaUpdateCnt = 0; + kalMemSet(&prBssInfo->arMUEdcaParams[0], 0, + sizeof(struct _CMD_MU_EDCA_PARAMS_T) * WMM_AC_INDEX_NUM); + + /* Spatial Reuse params */ + prBssInfo->ucSRControl = 0; + prBssInfo->ucNonSRGObssPdMaxOffset = 0; + prBssInfo->ucSRGObssPdMinOffset = 0; + prBssInfo->ucSRGObssPdMaxOffset = 0; + prBssInfo->u8SRGBSSColorBitmap = 0; + prBssInfo->u8SRGPartialBSSIDBitmap = 0; + + /* HE Operation */ + memset(prBssInfo->ucHeOpParams, 0, HE_OP_BYTE_NUM); + /* set TXOP to 0x3FF (Spec. define default value) */ + prBssInfo->ucHeOpParams[0] + |= HE_OP_PARAM0_TXOP_DUR_RTS_THRESHOLD_MASK; + prBssInfo->ucHeOpParams[1] + |= HE_OP_PARAM1_TXOP_DUR_RTS_THRESHOLD_MASK; + prBssInfo->ucBssColorInfo = 0; + prBssInfo->u2HeBasicMcsSet = 0; + } +#endif + +#ifdef CFG_DFS_CHSW_FORCE_BW20 + g_fgHasChannelSwitchIE = FALSE; +#endif +} + +#if CFG_SUPPORT_TDLS +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +uint32_t rlmFillVhtCapIEByAdapter(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, uint8_t *pOutBuf) +{ + struct IE_VHT_CAP *prVhtCap; + struct VHT_SUPPORTED_MCS_FIELD *prVhtSupportedMcsSet; + uint8_t i; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + /* ASSERT(prMsduInfo); */ + + prVhtCap = (struct IE_VHT_CAP *)pOutBuf; + + prVhtCap->ucId = ELEM_ID_VHT_CAP; + prVhtCap->ucLength = sizeof(struct IE_VHT_CAP) - ELEM_HDR_LEN; + prVhtCap->u4VhtCapInfo = VHT_CAP_INFO_DEFAULT_VAL; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxShortGI)) + prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_SHORT_GI_80; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxLdpc)) + prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_RX_LDPC; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxStbc)) + prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_RX_STBC_ONE_STREAM; + + /*set MCS map */ + prVhtSupportedMcsSet = &prVhtCap->rVhtSupportedMcsSet; + kalMemZero((void *)prVhtSupportedMcsSet, + sizeof(struct VHT_SUPPORTED_MCS_FIELD)); + + for (i = 0; i < 8; i++) { + prVhtSupportedMcsSet->u2RxMcsMap |= BITS(2 * i, (2 * i + 1)); + prVhtSupportedMcsSet->u2TxMcsMap |= BITS(2 * i, (2 * i + 1)); + } + + prVhtSupportedMcsSet->u2RxMcsMap &= + (VHT_CAP_INFO_MCS_MAP_MCS9 << VHT_CAP_INFO_MCS_1SS_OFFSET); + prVhtSupportedMcsSet->u2TxMcsMap &= + (VHT_CAP_INFO_MCS_MAP_MCS9 << VHT_CAP_INFO_MCS_1SS_OFFSET); + prVhtSupportedMcsSet->u2RxHighestSupportedDataRate = + VHT_CAP_INFO_DEFAULT_HIGHEST_DATA_RATE; + prVhtSupportedMcsSet->u2TxHighestSupportedDataRate = + VHT_CAP_INFO_DEFAULT_HIGHEST_DATA_RATE; + + ASSERT(IE_SIZE(prVhtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP)); + + return IE_SIZE(prVhtCap); +} +#endif + +#if CFG_SUPPORT_TDLS +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +uint32_t rlmFillHtCapIEByParams(u_int8_t fg40mAllowed, + u_int8_t fgShortGIDisabled, + uint8_t u8SupportRxSgi20, + uint8_t u8SupportRxSgi40, uint8_t u8SupportRxGf, + enum ENUM_OP_MODE eCurrentOPMode, + uint8_t *pOutBuf) +{ + struct IE_HT_CAP *prHtCap; + struct SUP_MCS_SET_FIELD *prSupMcsSet; + + ASSERT(pOutBuf); + + prHtCap = (struct IE_HT_CAP *)pOutBuf; + + /* Add HT capabilities IE */ + prHtCap->ucId = ELEM_ID_HT_CAP; + prHtCap->ucLength = sizeof(struct IE_HT_CAP) - ELEM_HDR_LEN; + + prHtCap->u2HtCapInfo = HT_CAP_INFO_DEFAULT_VAL; + if (!fg40mAllowed) { + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | + HT_CAP_INFO_SHORT_GI_40M | + HT_CAP_INFO_DSSS_CCK_IN_40M); + } + if (fgShortGIDisabled) + prHtCap->u2HtCapInfo &= + ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); + + if (u8SupportRxSgi20 == 2) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_20M); + if (u8SupportRxSgi40 == 2) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_40M); + if (u8SupportRxGf == 2) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_HT_GF); + + prHtCap->ucAmpduParam = AMPDU_PARAM_DEFAULT_VAL; + + prSupMcsSet = &prHtCap->rSupMcsSet; + kalMemZero((void *)&prSupMcsSet->aucRxMcsBitmask[0], + SUP_MCS_RX_BITMASK_OCTET_NUM); + + prSupMcsSet->aucRxMcsBitmask[0] = BITS(0, 7); + + if (fg40mAllowed) + prSupMcsSet->aucRxMcsBitmask[32 / 8] = BIT(0); /* MCS32 */ + prSupMcsSet->u2RxHighestSupportedRate = SUP_MCS_RX_DEFAULT_HIGHEST_RATE; + prSupMcsSet->u4TxRateInfo = SUP_MCS_TX_DEFAULT_VAL; + + prHtCap->u2HtExtendedCap = HT_EXT_CAP_DEFAULT_VAL; + if (!fg40mAllowed || eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + prHtCap->u2HtExtendedCap &= + ~(HT_EXT_CAP_PCO | HT_EXT_CAP_PCO_TRANS_TIME_NONE); + + prHtCap->u4TxBeamformingCap = TX_BEAMFORMING_CAP_DEFAULT_VAL; + + prHtCap->ucAselCap = ASEL_CAP_DEFAULT_VAL; + + ASSERT(IE_SIZE(prHtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP)); + + return IE_SIZE(prHtCap); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +uint32_t rlmFillHtCapIEByAdapter(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, uint8_t *pOutBuf) +{ + struct IE_HT_CAP *prHtCap; + struct SUP_MCS_SET_FIELD *prSupMcsSet; + u_int8_t fg40mAllowed; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(pOutBuf); + + fg40mAllowed = prBssInfo->fgAssoc40mBwAllowed; + + prHtCap = (struct IE_HT_CAP *)pOutBuf; + + /* Add HT capabilities IE */ + prHtCap->ucId = ELEM_ID_HT_CAP; + prHtCap->ucLength = sizeof(struct IE_HT_CAP) - 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 (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxShortGI)) + prHtCap->u2HtCapInfo |= + (HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxLdpc)) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_LDPC_CAP; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxStbc)) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_RX_STBC_1_SS; + + prHtCap->ucAmpduParam = AMPDU_PARAM_DEFAULT_VAL; + + prSupMcsSet = &prHtCap->rSupMcsSet; + kalMemZero((void *)&prSupMcsSet->aucRxMcsBitmask[0], + SUP_MCS_RX_BITMASK_OCTET_NUM); + + prSupMcsSet->aucRxMcsBitmask[0] = BITS(0, 7); + + if (fg40mAllowed && IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucMCS32)) + 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)); + + return IE_SIZE(prHtCap); +} + +#endif + +#if CFG_SUPPORT_DFS +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will compose the TPC Report frame. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] prStaRec Pointer to the STA_RECORD_T. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +static void tpcComposeReportFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + struct MSDU_INFO *prMsduInfo; + struct BSS_INFO *prBssInfo; + struct ACTION_TPC_REPORT_FRAME *prTxFrame; + uint16_t u2PayloadLen; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + prBssInfo = &prAdapter->rWifiVar.arBssInfoPool[prStaRec->ucBssIndex]; + ASSERT(prBssInfo); + + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc( + prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + prTxFrame = (struct ACTION_TPC_REPORT_FRAME + *)((unsigned long)(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_SPEC_MGT; + prTxFrame->ucAction = ACTION_TPC_REPORT; + + /* 3 Compose the frame body's frame. */ + prTxFrame->ucDialogToken = prStaRec->ucSmDialogToken; + prTxFrame->ucElemId = ELEM_ID_TPC_REPORT; + prTxFrame->ucLength = + sizeof(prTxFrame->ucLinkMargin) + sizeof(prTxFrame->ucTransPwr); + prTxFrame->ucTransPwr = prAdapter->u4GetTxPower; + prTxFrame->ucLinkMargin = + prAdapter->rLinkQuality.rLq[prStaRec->ucBssIndex]. + cRssi - (0 - MIN_RCV_PWR); + + u2PayloadLen = ACTION_SM_TPC_REPORT_LEN; + + /* 4 Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, prMsduInfo, prStaRec->ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, pfTxDoneHandler, + MSDU_RATE_MODE_AUTO); + + DBGLOG(RLM, TRACE, "ucDialogToken %d ucTransPwr %d ucLinkMargin %d\n", + prTxFrame->ucDialogToken, prTxFrame->ucTransPwr, + prTxFrame->ucLinkMargin); + + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return; + +} /* end of tpcComposeReportFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will compose the Measurement Report frame. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] prStaRec Pointer to the STA_RECORD_T. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +static void msmtComposeReportFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + struct MSDU_INFO *prMsduInfo; + struct BSS_INFO *prBssInfo; + struct ACTION_SM_REQ_FRAME *prTxFrame; + struct IE_MEASUREMENT_REPORT *prMeasurementRepIE; + uint8_t *pucIE; + uint16_t u2PayloadLen; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + prBssInfo = &prAdapter->rWifiVar.arBssInfoPool[prStaRec->ucBssIndex]; + ASSERT(prBssInfo); + + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc( + prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + prTxFrame = (struct ACTION_SM_REQ_FRAME + *)((unsigned long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + pucIE = prTxFrame->aucInfoElem; + prMeasurementRepIE = SM_MEASUREMENT_REP_IE(pucIE); + + 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_SPEC_MGT; + prTxFrame->ucAction = ACTION_MEASUREMENT_REPORT; + + /* 3 Compose the frame body's frame. */ + prTxFrame->ucDialogToken = prStaRec->ucSmDialogToken; + prMeasurementRepIE->ucId = ELEM_ID_MEASUREMENT_REPORT; + +#if 0 + if (prStaRec->ucSmMsmtRequestMode == ELEM_RM_TYPE_BASIC_REQ) { + prMeasurementRepIE->ucLength = + sizeof(struct SM_BASIC_REPORT) + 3; + u2PayloadLen = ACTION_SM_MEASURE_REPORT_LEN+ + ACTION_SM_BASIC_REPORT_LEN; + } else if (prStaRec->ucSmMsmtRequestMode == ELEM_RM_TYPE_CCA_REQ) { + prMeasurementRepIE->ucLength = sizeof(struct SM_CCA_REPORT) + 3; + u2PayloadLen = ACTION_SM_MEASURE_REPORT_LEN+ + ACTION_SM_CCA_REPORT_LEN; + } else if (prStaRec->ucSmMsmtRequestMode == + ELEM_RM_TYPE_RPI_HISTOGRAM_REQ) { + prMeasurementRepIE->ucLength = sizeof(struct SM_RPI_REPORT) + 3; + u2PayloadLen = ACTION_SM_MEASURE_REPORT_LEN+ + ACTION_SM_PRI_REPORT_LEN; + } else { + prMeasurementRepIE->ucLength = 3; + u2PayloadLen = ACTION_SM_MEASURE_REPORT_LEN; + } +#else + prMeasurementRepIE->ucLength = 3; + u2PayloadLen = ACTION_SM_MEASURE_REPORT_LEN; + prMeasurementRepIE->ucToken = prStaRec->ucSmMsmtToken; + prMeasurementRepIE->ucReportMode = BIT(1); + prMeasurementRepIE->ucMeasurementType = prStaRec->ucSmMsmtRequestMode; +#endif + + /* 4 Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, prMsduInfo, prStaRec->ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, pfTxDoneHandler, + MSDU_RATE_MODE_AUTO); + + DBGLOG(RLM, TRACE, + "ucDialogToken %d ucToken %d ucReportMode %d ucMeasurementType %d\n", + prTxFrame->ucDialogToken, prMeasurementRepIE->ucToken, + prMeasurementRepIE->ucReportMode, + prMeasurementRepIE->ucMeasurementType); + + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return; + +} /* end of msmtComposeReportFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function handle spectrum management action frame + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmProcessSpecMgtAction(struct ADAPTER *prAdapter, struct SW_RFB *prSwRfb) +{ + uint8_t *pucIE; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + uint16_t u2IELength; + uint16_t u2Offset = 0; + struct IE_CHANNEL_SWITCH *prChannelSwitchAnnounceIE; + struct IE_SECONDARY_OFFSET *prSecondaryOffsetIE; + struct IE_WIDE_BAND_CHANNEL *prWideBandChannelIE; + struct IE_TPC_REQ *prTpcReqIE; + struct IE_TPC_REPORT *prTpcRepIE; + struct IE_MEASUREMENT_REQ *prMeasurementReqIE; + struct IE_MEASUREMENT_REPORT *prMeasurementRepIE; + struct ACTION_SM_REQ_FRAME *prRxFrame; + u_int8_t fgHasWideBandIE = FALSE; + u_int8_t fgHasSCOIE = FALSE; + u_int8_t fgHasChannelSwitchIE = FALSE; + + DBGLOG(RLM, INFO, "[Mgt Action]rlmProcessSpecMgtAction\n"); + ASSERT(prAdapter); + ASSERT(prSwRfb); + + u2IELength = + prSwRfb->u2PacketLen - + (uint16_t)OFFSET_OF(struct ACTION_SM_REQ_FRAME, aucInfoElem[0]); + + prRxFrame = (struct ACTION_SM_REQ_FRAME *)prSwRfb->pvHeader; + pucIE = prRxFrame->aucInfoElem; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (!prStaRec) + return; + + if (prStaRec->ucBssIndex > prAdapter->ucHwBssIdNum) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + prStaRec->ucSmDialogToken = prRxFrame->ucDialogToken; + + DBGLOG_MEM8(RLM, INFO, pucIE, u2IELength); + switch (prRxFrame->ucAction) { + case ACTION_MEASUREMENT_REQ: + DBGLOG(RLM, INFO, "[Mgt Action] Measure Request\n"); + prMeasurementReqIE = SM_MEASUREMENT_REQ_IE(pucIE); + if (prMeasurementReqIE->ucId == ELEM_ID_MEASUREMENT_REQ) { + /* Check IE length is valid */ + if (prMeasurementReqIE->ucLength != 0 && + (prMeasurementReqIE->ucLength >= + sizeof(struct IE_MEASUREMENT_REQ) - 2)) { + prStaRec->ucSmMsmtRequestMode = + prMeasurementReqIE->ucRequestMode; + prStaRec->ucSmMsmtToken = + prMeasurementReqIE->ucToken; + msmtComposeReportFrame(prAdapter, prStaRec, + NULL); + } + } + + break; + case ACTION_MEASUREMENT_REPORT: + DBGLOG(RLM, INFO, "[Mgt Action] Measure Report\n"); + prMeasurementRepIE = SM_MEASUREMENT_REP_IE(pucIE); + if (prMeasurementRepIE->ucId == ELEM_ID_MEASUREMENT_REPORT) + DBGLOG(RLM, TRACE, + "[Mgt Action] Correct Measurement report IE !!\n"); + break; + case ACTION_TPC_REQ: + DBGLOG(RLM, INFO, "[Mgt Action] TPC Request\n"); + prTpcReqIE = SM_TPC_REQ_IE(pucIE); + + if (prTpcReqIE->ucId == ELEM_ID_TPC_REQ) + tpcComposeReportFrame(prAdapter, prStaRec, NULL); + + break; + case ACTION_TPC_REPORT: + DBGLOG(RLM, INFO, "[Mgt Action] TPC Report\n"); + prTpcRepIE = SM_TPC_REP_IE(pucIE); + + if (prTpcRepIE->ucId == ELEM_ID_TPC_REPORT) + DBGLOG(RLM, TRACE, + "[Mgt Action] Correct TPC report IE !!\n"); + + break; + case ACTION_CHNL_SWITCH: + IE_FOR_EACH(pucIE, u2IELength, u2Offset) + { + switch (IE_ID(pucIE)) { + + case ELEM_ID_WIDE_BAND_CHANNEL_SWITCH: + if (!RLM_NET_IS_11AC(prBssInfo) || + IE_LEN(pucIE) != + (sizeof(struct + IE_WIDE_BAND_CHANNEL) - + 2)) { + DBGLOG(RLM, INFO, + "[Mgt Action] ELEM_ID_WIDE_BAND_CHANNEL_SWITCH, Length\n"); + break; + } + DBGLOG(RLM, INFO, + "[Mgt Action] ELEM_ID_WIDE_BAND_CHANNEL_SWITCH, 11AC\n"); + prWideBandChannelIE = + (struct IE_WIDE_BAND_CHANNEL *)pucIE; + prBssInfo->ucVhtChannelWidth = + prWideBandChannelIE->ucNewChannelWidth; + prBssInfo->ucVhtChannelFrequencyS1 = + prWideBandChannelIE->ucChannelS1; + prBssInfo->ucVhtChannelFrequencyS2 = + prWideBandChannelIE->ucChannelS2; + + /* Revise by own OP BW if needed */ + if ((prBssInfo->fgIsOpChangeChannelWidth) && + (rlmGetVhtOpBwByBssOpBw( + prBssInfo + ->ucOpChangeChannelWidth) < + prBssInfo->ucVhtChannelWidth)) { + + DBGLOG(RLM, LOUD, + "Change to w:%d s1:%d s2:%d since own changed BW < peer's WideBand BW", + prBssInfo->ucVhtChannelWidth, + prBssInfo->ucVhtChannelFrequencyS1, + prBssInfo->ucVhtChannelFrequencyS2); + rlmFillVhtOpInfoByBssOpBw( + prBssInfo, + prBssInfo + ->ucOpChangeChannelWidth); + } + + fgHasWideBandIE = TRUE; + break; + + case ELEM_ID_CH_SW_ANNOUNCEMENT: + if (IE_LEN(pucIE) != + (sizeof(struct IE_CHANNEL_SWITCH) - 2)) { + DBGLOG(RLM, INFO, + "[Mgt Action] ELEM_ID_CH_SW_ANNOUNCEMENT, Length\n"); + break; + } + + prChannelSwitchAnnounceIE = + (struct IE_CHANNEL_SWITCH *)pucIE; + + if (prChannelSwitchAnnounceIE + ->ucChannelSwitchMode == 1) { + + /* Need to stop data + * transmission immediately + */ + if (!g_fgHasStopTx) { + g_fgHasStopTx = TRUE; + /* AP */ + qmSetStaRecTxAllowed(prAdapter, + prStaRec, + FALSE); + DBGLOG(RLM, EVENT, + "[Ch] TxAllowed = FALSE\n"); + } + + if (prChannelSwitchAnnounceIE + ->ucChannelSwitchCount <= 5) { + DBGLOG(RLM, INFO, + "[Mgt Action] switch channel [%d]->[%d]\n", + prBssInfo->ucPrimaryChannel, + prChannelSwitchAnnounceIE + ->ucNewChannelNum); + prBssInfo->ucPrimaryChannel = + prChannelSwitchAnnounceIE + ->ucNewChannelNum; + prBssInfo->eBand = + (prBssInfo + ->ucPrimaryChannel + <= 14) ? BAND_2G4 : + BAND_5G; + } + } else { + DBGLOG(RLM, INFO, + "[Mgt Action] ucChannelSwitchMode = 0\n"); + } + + fgHasChannelSwitchIE = TRUE; + break; + case ELEM_ID_SCO: + if (IE_LEN(pucIE) != + (sizeof(struct IE_SECONDARY_OFFSET) - 2)) { + DBGLOG(RLM, INFO, + "[Mgt Action] ELEM_ID_SCO, Length\n"); + break; + } + prSecondaryOffsetIE = + (struct IE_SECONDARY_OFFSET *)pucIE; + DBGLOG(RLM, INFO, + "[Mgt Action] SCO [%d]->[%d]\n", + prBssInfo->eBssSCO, + prSecondaryOffsetIE->ucSecondaryOffset); + prBssInfo->eBssSCO = + prSecondaryOffsetIE->ucSecondaryOffset; + fgHasSCOIE = TRUE; + break; + default: + break; + } /*end of switch IE_ID */ + } /*end of IE_FOR_EACH */ + if (fgHasChannelSwitchIE != FALSE) { + struct BSS_DESC *prBssDesc; + struct PARAM_SSID rSsid; + + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, + prBssInfo->aucSSID, prBssInfo->ucSSIDLen); + prBssDesc = scanSearchBssDescByBssidAndSsid( + prAdapter, prBssInfo->aucBSSID, TRUE, &rSsid); + + if (fgHasWideBandIE == FALSE) { + prBssInfo->ucVhtChannelWidth = 0; + prBssInfo->ucVhtChannelFrequencyS1 = + prBssInfo->ucPrimaryChannel; + prBssInfo->ucVhtChannelFrequencyS2 = 0; + } + if (fgHasSCOIE == FALSE) + prBssInfo->eBssSCO = CHNL_EXT_SCN; + + /* Check SAP channel */ + p2pFuncSwitchSapChannel(prAdapter); + if (prBssDesc) { + prBssDesc->ucChannelNum = + prBssInfo->ucPrimaryChannel; + prBssDesc->eChannelWidth = + prBssInfo->ucVhtChannelWidth; + prBssDesc->ucCenterFreqS1 = prBssInfo-> + ucVhtChannelFrequencyS1; + prBssDesc->ucCenterFreqS2 = prBssInfo-> + ucVhtChannelFrequencyS2; + } else { + DBGLOG(RLM, WARN, + "[Mgt Action] BssDesc is not found!\n"); + } + } + nicUpdateBss(prAdapter, prBssInfo->ucBssIndex); + break; + default: + break; + } +} + +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Send OpMode Norification frame (VHT action frame) + * + * \param[in] ucChannelWidth 0:20MHz, 1:40MHz, 2:80MHz, 3:160MHz or 80+80MHz + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +uint32_t rlmSendOpModeNotificationFrame(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t ucChannelWidth, uint8_t ucOpRxNss) +{ + + struct MSDU_INFO *prMsduInfo; + struct ACTION_OP_MODE_NOTIFICATION_FRAME *prTxFrame; + struct BSS_INFO *prBssInfo; + uint16_t u2EstimatedFrameLen; + PFN_TX_DONE_HANDLER pfTxDoneHandler = (PFN_TX_DONE_HANDLER)NULL; + + /* Sanity Check */ + if (!prStaRec) + return WLAN_STATUS_FAILURE; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + if (!prBssInfo) + return WLAN_STATUS_FAILURE; + + /* Calculate MSDU buffer length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + + sizeof(struct ACTION_OP_MODE_NOTIFICATION_FRAME); + + /* Alloc MSDU_INFO */ + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc(prAdapter, + u2EstimatedFrameLen); + + if (!prMsduInfo) + return WLAN_STATUS_FAILURE; + + kalMemZero(prMsduInfo->prPacket, u2EstimatedFrameLen); + + prTxFrame = prMsduInfo->prPacket; + + /* Fill frame ctrl */ + 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); + + /* 3 Compose the frame body's frame */ + prTxFrame->ucCategory = CATEGORY_VHT_ACTION; + prTxFrame->ucAction = ACTION_OPERATING_MODE_NOTIFICATION; + + prTxFrame->ucOperatingMode |= + (ucChannelWidth & VHT_OP_MODE_CHANNEL_WIDTH); + + if (ucOpRxNss == 0) + ucOpRxNss = 1; + prTxFrame->ucOperatingMode |= + (((ucOpRxNss - 1) << 4) & VHT_OP_MODE_RX_NSS); + prTxFrame->ucOperatingMode &= ~VHT_OP_MODE_RX_NSS_TYPE; + + if (prBssInfo->pfOpChangeHandler) + pfTxDoneHandler = rlmNotifyVhtOpModeTxDone; + + /* 4 Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, prMsduInfo, prBssInfo->ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_MGMT_HEADER_LEN, + sizeof(struct ACTION_OP_MODE_NOTIFICATION_FRAME), + pfTxDoneHandler, MSDU_RATE_MODE_AUTO); + + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Send SM Power Save frame (HT action frame) + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +uint32_t rlmSendSmPowerSaveFrame(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, uint8_t ucOpRxNss) +{ + struct MSDU_INFO *prMsduInfo; + struct ACTION_SM_POWER_SAVE_FRAME *prTxFrame; + struct BSS_INFO *prBssInfo; + uint16_t u2EstimatedFrameLen; + PFN_TX_DONE_HANDLER pfTxDoneHandler = (PFN_TX_DONE_HANDLER)NULL; + + /* Sanity Check */ + if (!prStaRec) + return WLAN_STATUS_FAILURE; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + if (!prBssInfo) + return WLAN_STATUS_FAILURE; + + /* Calculate MSDU buffer length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + + sizeof(struct ACTION_SM_POWER_SAVE_FRAME); + + /* Alloc MSDU_INFO */ + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc(prAdapter, + u2EstimatedFrameLen); + + if (!prMsduInfo) + return WLAN_STATUS_FAILURE; + + kalMemZero(prMsduInfo->prPacket, u2EstimatedFrameLen); + + prTxFrame = prMsduInfo->prPacket; + + /* Fill frame ctrl */ + 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); + + /* 3 Compose the frame body's frame */ + prTxFrame->ucCategory = CATEGORY_HT_ACTION; + prTxFrame->ucAction = ACTION_HT_SM_POWER_SAVE; + + if (ucOpRxNss == 1) + prTxFrame->ucSmPowerCtrl |= HT_SM_POWER_SAVE_CONTROL_ENABLED; + else if (ucOpRxNss == 2) + prTxFrame->ucSmPowerCtrl &= ~HT_SM_POWER_SAVE_CONTROL_ENABLED; + else { + DBGLOG(RLM, WARN, + "Can't switch to RxNss = %d since we don't support.\n", + ucOpRxNss); + return WLAN_STATUS_FAILURE; + } + + /* Static SM power save mode */ + prTxFrame->ucSmPowerCtrl &= + (~HT_SM_POWER_SAVE_CONTROL_SM_MODE); + + if (prBssInfo->pfOpChangeHandler) + pfTxDoneHandler = rlmSmPowerSaveTxDone; + + /* 4 Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, prMsduInfo, prBssInfo->ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_MGMT_HEADER_LEN, + sizeof(struct ACTION_SM_POWER_SAVE_FRAME), pfTxDoneHandler, + MSDU_RATE_MODE_AUTO); + + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Send Notify Channel Width frame (HT action frame) + * + * \param[in] ucChannelWidth 0:20MHz, 1:Any channel width + * in the STAs Supported Channel Width Set subfield + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +uint32_t rlmSendNotifyChannelWidthFrame(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t ucChannelWidth) +{ + struct MSDU_INFO *prMsduInfo; + struct ACTION_NOTIFY_CHANNEL_WIDTH_FRAME *prTxFrame; + struct BSS_INFO *prBssInfo; + uint16_t u2EstimatedFrameLen; + PFN_TX_DONE_HANDLER pfTxDoneHandler = (PFN_TX_DONE_HANDLER)NULL; + + /* Sanity Check */ + if (!prStaRec) + return WLAN_STATUS_FAILURE; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + if (!prBssInfo) + return WLAN_STATUS_FAILURE; + + /* Calculate MSDU buffer length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + + sizeof(struct ACTION_NOTIFY_CHANNEL_WIDTH_FRAME); + + /* Alloc MSDU_INFO */ + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc(prAdapter, + u2EstimatedFrameLen); + + if (!prMsduInfo) + return WLAN_STATUS_FAILURE; + + kalMemZero(prMsduInfo->prPacket, u2EstimatedFrameLen); + + prTxFrame = prMsduInfo->prPacket; + + /* Fill frame ctrl */ + 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); + + /* 3 Compose the frame body's frame */ + prTxFrame->ucCategory = CATEGORY_HT_ACTION; + prTxFrame->ucAction = ACTION_HT_NOTIFY_CHANNEL_WIDTH; + + prTxFrame->ucChannelWidth = ucChannelWidth; + + if (prBssInfo->pfOpChangeHandler) + pfTxDoneHandler = rlmNotifyChannelWidthtTxDone; + + /* 4 Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, prMsduInfo, prBssInfo->ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_MGMT_HEADER_LEN, + sizeof(struct ACTION_NOTIFY_CHANNEL_WIDTH_FRAME), + pfTxDoneHandler, MSDU_RATE_MODE_AUTO); + + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t rlmNotifyVhtOpModeTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + u_int8_t fgIsSuccess = FALSE; + + do { + ASSERT((prAdapter != NULL) && (prMsduInfo != NULL)); + + if (rTxDoneStatus == TX_RESULT_SUCCESS) + fgIsSuccess = TRUE; + + } while (FALSE); + + rlmOpModeTxDoneHandler(prAdapter, prMsduInfo, OP_NOTIFY_TYPE_VHT_NSS_BW, + fgIsSuccess); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +uint32_t rlmSmPowerSaveTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + u_int8_t fgIsSuccess = FALSE; + + do { + ASSERT((prAdapter != NULL) && (prMsduInfo != NULL)); + + if (rTxDoneStatus == TX_RESULT_SUCCESS) + fgIsSuccess = TRUE; + + } while (FALSE); + + rlmOpModeTxDoneHandler(prAdapter, prMsduInfo, OP_NOTIFY_TYPE_HT_NSS, + fgIsSuccess); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +uint32_t rlmNotifyChannelWidthtTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + u_int8_t fgIsSuccess = FALSE; + + do { + ASSERT((prAdapter != NULL) && (prMsduInfo != NULL)); + + if (rTxDoneStatus == TX_RESULT_SUCCESS) + fgIsSuccess = TRUE; + + } while (FALSE); + + rlmOpModeTxDoneHandler(prAdapter, prMsduInfo, OP_NOTIFY_TYPE_HT_BW, + fgIsSuccess); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Handle TX done for OP mode noritfication frame + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static void rlmOpModeTxDoneHandler(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN uint8_t ucOpChangeType, + IN u_int8_t fgIsSuccess) +{ + uint32_t u4Status = WLAN_STATUS_SUCCESS; + struct BSS_INFO *prBssInfo = NULL; + struct STA_RECORD *prStaRec = NULL; + u_int8_t fgIsOpModeChangeSuccess = FALSE; /* OP change result */ + uint8_t ucRelatedFrameType = + OP_NOTIFY_TYPE_NUM; /* Used for HT notification frame */ + /* Used for HT notification frame */ + uint8_t *pucCurrOpState = NULL; + uint8_t *pucRelatedOpState = NULL; + + /* Sanity check */ + ASSERT((prAdapter != NULL) && (prMsduInfo != NULL)); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + + ASSERT(prBssInfo); + + prStaRec = prBssInfo->prStaRecOfAP; + + DBGLOG(RLM, INFO, + "OP notification Tx done: BSS[%d] Type[%d] Status[%d] IsSuccess[%d]\n", + prBssInfo->ucBssIndex, ucOpChangeType, + prBssInfo->aucOpModeChangeState[ucOpChangeType], fgIsSuccess); + + do { + /* <1>handle abnormal case */ + if ((prBssInfo->aucOpModeChangeState[ucOpChangeType] != + OP_NOTIFY_STATE_KEEP) && + (prBssInfo->aucOpModeChangeState[ucOpChangeType] != + OP_NOTIFY_STATE_SENDING)) { + DBGLOG(RLM, WARN, + "Unexpected BSS[%d] OpModeChangeState[%d]\n", + prBssInfo->ucBssIndex, + prBssInfo->aucOpModeChangeState[ucOpChangeType]); + rlmRollbackOpChangeParam(prBssInfo, TRUE, TRUE); + fgIsOpModeChangeSuccess = FALSE; + break; + } + + if (ucOpChangeType >= OP_NOTIFY_TYPE_NUM) { + DBGLOG(RLM, WARN, + "Uxexpected Bss[%d] OpChangeType[%d]\n", + prMsduInfo->ucBssIndex, ucOpChangeType); + rlmRollbackOpChangeParam(prBssInfo, TRUE, TRUE); + fgIsOpModeChangeSuccess = FALSE; + break; + } + + pucCurrOpState = &prBssInfo + ->aucOpModeChangeState[ucOpChangeType]; + + /* <2>Assign Op notification Type/State for HT notification + * frame + */ + if ((ucOpChangeType == OP_NOTIFY_TYPE_HT_BW) || + (ucOpChangeType == OP_NOTIFY_TYPE_HT_NSS)) { + + ucRelatedFrameType = + (ucOpChangeType == OP_NOTIFY_TYPE_HT_BW) + ? OP_NOTIFY_TYPE_HT_NSS + : OP_NOTIFY_TYPE_HT_BW; + + pucRelatedOpState = &prBssInfo + ->aucOpModeChangeState[ucRelatedFrameType]; + } + + /* <3.1>handle TX done - SUCCESS */ + if (fgIsSuccess == TRUE) { + + /* Clear retry count */ + prBssInfo->aucOpModeChangeRetryCnt[ucOpChangeType] = 0; + + if (ucOpChangeType == OP_NOTIFY_TYPE_VHT_NSS_BW) { + *pucCurrOpState = OP_NOTIFY_STATE_SUCCESS; + + if (prBssInfo->aucOpModeChangeState + [OP_NOTIFY_TYPE_HT_BW] == + OP_NOTIFY_STATE_SENDING || + prBssInfo->aucOpModeChangeState + [OP_NOTIFY_TYPE_HT_NSS] == + OP_NOTIFY_STATE_SENDING) { + /* Wait for HT BW/Nss notification + * frames Tx done + */ + return; + } + + /* VHT notification frame sent */ + fgIsOpModeChangeSuccess = TRUE; + break; + } + + /* HT notification frame sent */ + if (*pucCurrOpState == + OP_NOTIFY_STATE_SENDING) { /* Change OpMode */ + *pucCurrOpState = OP_NOTIFY_STATE_SUCCESS; + + /* Case1: Wait for VHT notification frame & + * HT BW/Nss notification frame TX done + */ + if (*pucRelatedOpState == + OP_NOTIFY_STATE_SENDING || + prBssInfo->aucOpModeChangeState + [OP_NOTIFY_TYPE_VHT_NSS_BW] == + OP_NOTIFY_STATE_SENDING) + return; + + /* Case2: Both BW and Nss notification TX done + * or only change either BW or Nss + */ + if ((*pucRelatedOpState == + OP_NOTIFY_STATE_KEEP) || + (*pucRelatedOpState == + OP_NOTIFY_STATE_SUCCESS)) { + fgIsOpModeChangeSuccess = TRUE; + + /* Case3: One of the notification TX + * failed, + * re-send a notification frame to + * rollback the successful one + */ + } else if (*pucRelatedOpState == + OP_NOTIFY_STATE_FAIL) { + /*Rollback to keep the original BW/Nss + */ + *pucCurrOpState = OP_NOTIFY_STATE_KEEP; + if (ucOpChangeType == + OP_NOTIFY_TYPE_HT_BW) + u4Status = + rlmSendNotifyChannelWidthFrame( + prAdapter, prStaRec, + rlmGetBssOpBwByVhtAndHtOpInfo( + prBssInfo)); + else if (ucOpChangeType == + OP_NOTIFY_TYPE_HT_NSS) + u4Status = + rlmSendSmPowerSaveFrame( + prAdapter, prStaRec, + prBssInfo->ucOpRxNss); + + DBGLOG(RLM, INFO, + "Bss[%d] OpType[%d] Tx Failed, send OpType", + prMsduInfo->ucBssIndex, + ucRelatedFrameType); + DBGLOG(RLM, INFO, + "[%d] for roll back to BW[%d] RxNss[%d]\n", + ucOpChangeType, + rlmGetBssOpBwByVhtAndHtOpInfo + (prBssInfo), + prBssInfo->ucOpRxNss); + + if (u4Status == WLAN_STATUS_SUCCESS) + return; + } + } else if (*pucCurrOpState == + OP_NOTIFY_STATE_KEEP) { /* Rollback OpMode */ + + /* Case4: Rollback success, keep original OP + * BW/Nss + */ + if (ucOpChangeType == OP_NOTIFY_TYPE_HT_BW) + rlmRollbackOpChangeParam(prBssInfo, + TRUE, FALSE); + else if (ucOpChangeType == + OP_NOTIFY_TYPE_HT_NSS) + rlmRollbackOpChangeParam(prBssInfo, + FALSE, TRUE); + + fgIsOpModeChangeSuccess = FALSE; + } + } /* End of processing TX success */ + /* <3.2>handle TX done - FAIL */ + else { + prBssInfo->aucOpModeChangeRetryCnt[ucOpChangeType]++; + + /* Re-send notification frame */ + if (prBssInfo + ->aucOpModeChangeRetryCnt[ucOpChangeType] <= + OPERATION_NOTICATION_TX_LIMIT) { + if (ucOpChangeType == OP_NOTIFY_TYPE_VHT_NSS_BW) + u4Status = + rlmSendOpModeNotificationFrame( + prAdapter, prStaRec, + prBssInfo->ucOpChangeChannelWidth, + prBssInfo->ucOpChangeRxNss); + else if (ucOpChangeType == + OP_NOTIFY_TYPE_HT_NSS) + u4Status = rlmSendSmPowerSaveFrame( + prAdapter, prStaRec, + prBssInfo->ucOpChangeRxNss); + else if (ucOpChangeType == OP_NOTIFY_TYPE_HT_BW) + u4Status = + rlmSendNotifyChannelWidthFrame( + prAdapter, prStaRec, + prBssInfo + ->ucOpChangeChannelWidth); + + if (u4Status == WLAN_STATUS_SUCCESS) + return; + } + + /* Clear retry count when retry count > TX limit */ + prBssInfo->aucOpModeChangeRetryCnt[ucOpChangeType] = 0; + + /* VHT notification frame sent */ + if (ucOpChangeType == + OP_NOTIFY_TYPE_VHT_NSS_BW) { + *pucCurrOpState = OP_NOTIFY_STATE_FAIL; + + /* Change failed, keep original OP BW/Nss */ + rlmRollbackOpChangeParam(prBssInfo, TRUE, TRUE); + fgIsOpModeChangeSuccess = FALSE; + break; + } + + /* HT notification frame sent */ + if (*pucCurrOpState == + OP_NOTIFY_STATE_SENDING) { /* Change OpMode */ + *pucCurrOpState = OP_NOTIFY_STATE_FAIL; + + /* Change failed, keep original OP BW/Nss */ + if (ucOpChangeType == OP_NOTIFY_TYPE_HT_BW) + rlmRollbackOpChangeParam(prBssInfo, + TRUE, FALSE); + else if (ucOpChangeType == + OP_NOTIFY_TYPE_HT_NSS) + rlmRollbackOpChangeParam(prBssInfo, + FALSE, TRUE); + + /* Case1: Wait for both HT BW/Nss notification + * frame TX done + */ + if (*pucRelatedOpState == + OP_NOTIFY_STATE_SENDING) { + return; + + /* Case2: Both BW and Nss notification + * TX done + * or only change either BW or Nss + */ + } else if ((*pucRelatedOpState == + OP_NOTIFY_STATE_KEEP) || + (*pucRelatedOpState == + OP_NOTIFY_STATE_FAIL)) { + fgIsOpModeChangeSuccess = FALSE; + + /* Case3: One of the notification TX + * failed, + * re-send a notification frame to + * rollback the successful one + */ + } else if (*pucRelatedOpState == + OP_NOTIFY_STATE_SUCCESS) { + /*Rollback to keep the original BW/Nss + */ + *pucRelatedOpState = + OP_NOTIFY_STATE_KEEP; + + if (ucRelatedFrameType == + OP_NOTIFY_TYPE_HT_BW) { + u4Status = + rlmSendNotifyChannelWidthFrame( + prAdapter, prStaRec, + rlmGetBssOpBwByVhtAndHtOpInfo( + prBssInfo)); + } else if (ucRelatedFrameType == + OP_NOTIFY_TYPE_HT_NSS) + u4Status = + rlmSendSmPowerSaveFrame( + prAdapter, prStaRec, + prBssInfo->ucOpRxNss); + + DBGLOG(RLM, INFO, + "Bss[%d] OpType[%d] Tx Failed, send a OpType[%d] for roll back to BW[%d] RxNss[%d]\n", + prMsduInfo->ucBssIndex, + ucOpChangeType, + ucRelatedFrameType, + rlmGetBssOpBwByVhtAndHtOpInfo( + prBssInfo), + prBssInfo->ucOpRxNss); + + if (u4Status == WLAN_STATUS_SUCCESS) + return; + } + } else if (*pucCurrOpState == + OP_NOTIFY_STATE_KEEP) /* Rollback OpMode */ + /* Case4: Rollback failed, keep changing OP + * BW/Nss + */ + fgIsOpModeChangeSuccess = FALSE; + } /* End of processing TX failed */ + + } while (FALSE); + + /* <4>Change own OP info */ + rlmCompleteOpModeChange(prAdapter, prBssInfo, fgIsOpModeChangeSuccess); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static void rlmRollbackOpChangeParam(struct BSS_INFO *prBssInfo, + u_int8_t fgIsRollbackBw, + u_int8_t fgIsRollbackNss) +{ + + ASSERT(prBssInfo); + + if (fgIsRollbackBw == TRUE) { + prBssInfo->fgIsOpChangeChannelWidth = FALSE; + prBssInfo->ucOpChangeChannelWidth = + rlmGetBssOpBwByVhtAndHtOpInfo(prBssInfo); + } + + if (fgIsRollbackNss == TRUE) { + prBssInfo->fgIsOpChangeRxNss = FALSE; + prBssInfo->fgIsOpChangeTxNss = FALSE; + prBssInfo->ucOpChangeRxNss = prBssInfo->ucOpRxNss; + prBssInfo->ucOpChangeTxNss = prBssInfo->ucOpTxNss; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Get BSS operating channel width by VHT and HT OP Info + * + * \param[in] + * + * \return ucBssOpBw 0:20MHz, 1:40MHz, 2:80MHz, 3:160MHz 4:80+80MHz + * + */ +/*----------------------------------------------------------------------------*/ +uint8_t rlmGetBssOpBwByVhtAndHtOpInfo(struct BSS_INFO *prBssInfo) +{ + + uint8_t ucBssOpBw = MAX_BW_20MHZ; + + ASSERT(prBssInfo); + + switch (prBssInfo->ucVhtChannelWidth) { + case VHT_OP_CHANNEL_WIDTH_80P80: + ucBssOpBw = MAX_BW_80_80_MHZ; + break; + + case VHT_OP_CHANNEL_WIDTH_160: + ucBssOpBw = MAX_BW_160MHZ; + break; + + case VHT_OP_CHANNEL_WIDTH_80: + ucBssOpBw = MAX_BW_80MHZ; + break; + + case VHT_OP_CHANNEL_WIDTH_20_40: + if (prBssInfo->eBssSCO != CHNL_EXT_SCN) + ucBssOpBw = MAX_BW_40MHZ; + break; + default: + DBGLOG(RLM, WARN, "%s: unexpected VHT channel width: %d\n", + __func__, prBssInfo->ucVhtChannelWidth); +#if CFG_SUPPORT_802_11AC + if (RLM_NET_IS_11AC(prBssInfo)) + /*VHT default should support BW 80*/ + ucBssOpBw = MAX_BW_80MHZ; +#endif + break; + } + + return ucBssOpBw; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return ucVhtOpBw 0:20M/40Hz, 1:80MHz, 2:160MHz, 3:80+80MHz + * + */ +/*----------------------------------------------------------------------------*/ +uint8_t rlmGetVhtOpBwByBssOpBw(uint8_t ucBssOpBw) +{ + uint8_t ucVhtOpBw = + VHT_OP_CHANNEL_WIDTH_80; /*VHT default should support BW 80*/ + + switch (ucBssOpBw) { + case MAX_BW_20MHZ: + case MAX_BW_40MHZ: + ucVhtOpBw = VHT_OP_CHANNEL_WIDTH_20_40; + break; + + case MAX_BW_80MHZ: + ucVhtOpBw = VHT_OP_CHANNEL_WIDTH_80; + break; + + case MAX_BW_160MHZ: + ucVhtOpBw = VHT_OP_CHANNEL_WIDTH_160; + break; + + case MAX_BW_80_80_MHZ: + ucVhtOpBw = VHT_OP_CHANNEL_WIDTH_80P80; + break; + default: + DBGLOG(RLM, WARN, "%s: unexpected Bss OP BW: %d\n", __func__, + ucBssOpBw); + break; + } + + return ucVhtOpBw; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Get operating notification channel width by VHT and HT operating Info + * + * \param[in] + * + * \return ucOpModeBw 0:20MHz, 1:40MHz, 2:80MHz, 3:160MHz/80+80MHz + * + */ +/*----------------------------------------------------------------------------*/ +static uint8_t rlmGetOpModeBwByVhtAndHtOpInfo(struct BSS_INFO *prBssInfo) +{ + uint8_t ucOpModeBw = VHT_OP_MODE_CHANNEL_WIDTH_20; + + ASSERT(prBssInfo); + + switch (prBssInfo->ucVhtChannelWidth) { + case VHT_OP_CHANNEL_WIDTH_20_40: + if (prBssInfo->eBssSCO != CHNL_EXT_SCN) + ucOpModeBw = VHT_OP_MODE_CHANNEL_WIDTH_40; + break; + case VHT_OP_CHANNEL_WIDTH_80: + ucOpModeBw = VHT_OP_MODE_CHANNEL_WIDTH_80; + break; + case VHT_OP_CHANNEL_WIDTH_160: + case VHT_OP_CHANNEL_WIDTH_80P80: + ucOpModeBw = VHT_OP_MODE_CHANNEL_WIDTH_160_80P80; + break; + default: + DBGLOG(RLM, WARN, "%s: unexpected VHT channel width: %d\n", + __func__, prBssInfo->ucVhtChannelWidth); + /*VHT default IE should support BW 80*/ + ucOpModeBw = VHT_OP_MODE_CHANNEL_WIDTH_80; + break; + } + + return ucOpModeBw; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static void rlmChangeOwnOpInfo(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo) +{ + struct STA_RECORD *prStaRec; + + ASSERT((prAdapter != NULL) && (prBssInfo != NULL)); + + /* Update own operating channel Width */ + if (prBssInfo->fgIsOpChangeChannelWidth) { + if (prBssInfo->ucPhyTypeSet & PHY_TYPE_BIT_HT) { +#if CFG_SUPPORT_802_11AC + /* Update VHT OP Info*/ + if (prBssInfo->ucPhyTypeSet & PHY_TYPE_BIT_VHT) { + rlmFillVhtOpInfoByBssOpBw( + prBssInfo, + prBssInfo->ucOpChangeChannelWidth); + + DBGLOG(RLM, INFO, + "Update BSS[%d] VHT Channel Width Info to w=%d s1=%d s2=%d\n", + prBssInfo->ucBssIndex, + prBssInfo->ucVhtChannelWidth, + prBssInfo->ucVhtChannelFrequencyS1, + prBssInfo->ucVhtChannelFrequencyS2); + } +#endif + + /* Update HT OP Info*/ + if (prBssInfo->ucOpChangeChannelWidth == MAX_BW_20MHZ) { + prBssInfo->ucHtOpInfo1 &= + ~HT_OP_INFO1_STA_CHNL_WIDTH; + prBssInfo->eBssSCO = CHNL_EXT_SCN; + } else { + prBssInfo->ucHtOpInfo1 |= + HT_OP_INFO1_STA_CHNL_WIDTH; + + if (prBssInfo->eCurrentOPMode == + OP_MODE_INFRASTRUCTURE) { + prStaRec = prBssInfo->prStaRecOfAP; + if (!prStaRec) + return; + + if ((prStaRec->ucHtPeerOpInfo1 & + HT_OP_INFO1_SCO) != CHNL_EXT_RES) + prBssInfo->eBssSCO = + (enum ENUM_CHNL_EXT)( + prStaRec->ucHtPeerOpInfo1 & + HT_OP_INFO1_SCO); + } else if (prBssInfo->eCurrentOPMode == + OP_MODE_ACCESS_POINT) { + prBssInfo->eBssSCO = rlmDecideScoForAP( + prAdapter, prBssInfo); + } + } + + DBGLOG(RLM, INFO, + "Update BSS[%d] HT Channel Width Info to bw=%d sco=%d\n", + prBssInfo->ucBssIndex, + (uint8_t)((prBssInfo->ucHtOpInfo1 & + HT_OP_INFO1_STA_CHNL_WIDTH) >> + HT_OP_INFO1_STA_CHNL_WIDTH_OFFSET), + prBssInfo->eBssSCO); + } + } + + /* Update own operating RxNss */ + if (prBssInfo->fgIsOpChangeRxNss) { + prBssInfo->ucOpRxNss = prBssInfo->ucOpChangeRxNss; + DBGLOG(RLM, INFO, "Update OP RxNss[%d]\n", + prBssInfo->ucOpRxNss); + } + + /* Update own operating TxNss */ + if (prBssInfo->fgIsOpChangeTxNss) { + prBssInfo->ucOpTxNss = prBssInfo->ucOpChangeTxNss; + DBGLOG(RLM, INFO, "Update OP TxNss[%d]\n", + prBssInfo->ucOpTxNss); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static void rlmCompleteOpModeChange(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + u_int8_t fgIsSuccess) +{ + PFN_OPMODE_NOTIFY_DONE_FUNC pfnCallback; + + ASSERT((prAdapter != NULL) && (prBssInfo != NULL)); + + if ((prBssInfo->fgIsOpChangeChannelWidth) || + (prBssInfo->fgIsOpChangeRxNss) || + (prBssInfo->fgIsOpChangeTxNss)) { + + /* <1> Update own OP BW/Nss */ + rlmChangeOwnOpInfo(prAdapter, prBssInfo); + + /* <2> Update OP BW/Nss to FW */ + rlmSyncOperationParams(prAdapter, prBssInfo); + + /* <3> Update BCN/Probe Resp IE to notify peers our OP info is + * changed (AP mode) + */ + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) + bssUpdateBeaconContent(prAdapter, + prBssInfo->ucBssIndex); + } + + DBGLOG(RLM, INFO, + "Complete BSS[%d] OP Mode change to BW[%d] RxNss[%d] TxNss[%d]", + prBssInfo->ucBssIndex, + rlmGetBssOpBwByVhtAndHtOpInfo(prBssInfo), + prBssInfo->ucOpRxNss, + prBssInfo->ucOpTxNss); + + /* <4> Tell OpMode change caller the change result + * Allow callback function re-trigger OpModeChange immediately. + */ + pfnCallback = prBssInfo->pfOpChangeHandler; + prBssInfo->pfOpChangeHandler = NULL; + if (pfnCallback) + pfnCallback(prAdapter, prBssInfo->ucBssIndex, + fgIsSuccess); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Change OpMode Nss/Channel Width + * + * \param[in] ucChannelWidth 0:20MHz, 1:40MHz, 2:80MHz, 3:160MHz 4:80+80MHz + * + * \return fgIsChangeOpMode + * TRUE: Can change/Don't need to change operation mode + * FALSE: Can't change operation mode + */ +/*----------------------------------------------------------------------------*/ +enum ENUM_OP_CHANGE_STATUS_T +rlmChangeOperationMode( + struct ADAPTER *prAdapter, uint8_t ucBssIndex, + uint8_t ucChannelWidth, uint8_t ucOpRxNss, uint8_t ucOpTxNss, + #if CFG_SUPPORT_SMART_GEAR + uint8_t eNewReq, + #endif + PFN_OPMODE_NOTIFY_DONE_FUNC pfOpChangeHandler + ) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec = (struct STA_RECORD *)NULL; + u_int8_t fgIsChangeBw = TRUE, + fgIsChangeRxNss = TRUE, /* Indicate if need to change */ + fgIsChangeTxNss = TRUE; + uint8_t i; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + + /* Sanity check */ + if (ucBssIndex >= prAdapter->ucHwBssIdNum) + return OP_CHANGE_STATUS_INVALID; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (!prBssInfo) + return OP_CHANGE_STATUS_INVALID; + + /* <1>Check if OP change parameter is valid */ + if (rlmCheckOpChangeParamValid(prAdapter, prBssInfo, ucChannelWidth, + ucOpRxNss, ucOpTxNss) == FALSE) + return OP_CHANGE_STATUS_INVALID; + + /* <2>Check if OpMode notification is ongoing, if not, register the call + * back function + */ + if (prBssInfo->pfOpChangeHandler) { + DBGLOG(RLM, INFO, + "BSS[%d] OpMode change notification is ongoing\n", + ucBssIndex); + return OP_CHANGE_STATUS_INVALID; + } + + prBssInfo->pfOpChangeHandler = pfOpChangeHandler; + + /* <3>Check if the current operating BW/Nss is the same as the target + * one + */ + if (ucChannelWidth == rlmGetBssOpBwByVhtAndHtOpInfo(prBssInfo)) { + fgIsChangeBw = FALSE; + prBssInfo->fgIsOpChangeChannelWidth = FALSE; + } + if (ucOpRxNss == prBssInfo->ucOpRxNss) { + fgIsChangeRxNss = FALSE; + prBssInfo->fgIsOpChangeRxNss = FALSE; + } + if (ucOpTxNss == prBssInfo->ucOpTxNss) { + fgIsChangeTxNss = FALSE; + prBssInfo->fgIsOpChangeTxNss = FALSE; + } + if ((!fgIsChangeBw) && (!fgIsChangeRxNss) && (!fgIsChangeTxNss)) { + DBGLOG(RLM, INFO, + "BSS[%d] target OpMode BW[%d] RxNss[%d] TxNss[%d] No change, return\n", + ucBssIndex, ucChannelWidth, ucOpRxNss, ucOpTxNss); + rlmCompleteOpModeChange(prAdapter, prBssInfo, TRUE); + return OP_CHANGE_STATUS_VALID_NO_CHANGE; + } + + DBGLOG(RLM, INFO, + "Intend to change BSS[%d] OP Mode to BW[%d] RxNss[%d] TxNss[%d]\n", + ucBssIndex, ucChannelWidth, ucOpRxNss, ucOpTxNss); + + /* <4> Fill OP Change Info into BssInfo*/ + if (fgIsChangeBw) { + prBssInfo->ucOpChangeChannelWidth = ucChannelWidth; + prBssInfo->fgIsOpChangeChannelWidth = TRUE; + DBGLOG(RLM, INFO, "Intend to change BSS[%d] to BW[%d]\n", + ucBssIndex, ucChannelWidth); + } + if (fgIsChangeRxNss) { + prBssInfo->ucOpChangeRxNss = ucOpRxNss; + prBssInfo->fgIsOpChangeRxNss = TRUE; + DBGLOG(RLM, INFO, "Intend to change BSS[%d] to RxNss[%d]\n", + ucBssIndex, ucOpRxNss); + } + if (fgIsChangeTxNss) { + prBssInfo->ucOpChangeTxNss = ucOpTxNss; + prBssInfo->fgIsOpChangeTxNss = TRUE; + DBGLOG(RLM, INFO, "Intend to change BSS[%d] to TxNss[%d]\n", + ucBssIndex, ucOpTxNss); + } + + /* <5>Handling OP Info change for STA/GC */ + if ((prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) && + (prBssInfo->prStaRecOfAP)) { + prStaRec = prBssInfo->prStaRecOfAP; + /* <5.1>Initialize OP mode change parameters related to + * notification Tx done handler (STA mode) + */ + if (prBssInfo->pfOpChangeHandler) { + for (i = 0; i < OP_NOTIFY_TYPE_NUM; i++) { + prBssInfo->aucOpModeChangeState[i] = + OP_NOTIFY_STATE_KEEP; + prBssInfo->aucOpModeChangeRetryCnt[i] = 0; + } + } + +#if CFG_SUPPORT_SMART_GEAR + if (eNewReq != 0x04 /* CNM_OPMODE_REQ_SMARTGEAR_1T2R */) { +#endif /* <5.2> Send operating mode notification frame (STA mode) + * No action frame is needed if we only changed OpTxNss. + */ +#if CFG_SUPPORT_802_11AC + if (RLM_NET_IS_11AC(prBssInfo) && + (fgIsChangeBw || fgIsChangeRxNss)) { + if (prBssInfo->pfOpChangeHandler) + prBssInfo->aucOpModeChangeState + [OP_NOTIFY_TYPE_VHT_NSS_BW] = + OP_NOTIFY_STATE_SENDING; + DBGLOG(RLM, INFO, + "Send VHT OP notification frame: BSS[%d] BW[%d] RxNss[%d]\n", + ucBssIndex, ucChannelWidth, ucOpRxNss); + u4Status = rlmSendOpModeNotificationFrame( + prAdapter, prStaRec, + ucChannelWidth, ucOpRxNss); + } +#endif + if (RLM_NET_IS_11N(prBssInfo) && + (fgIsChangeBw || fgIsChangeRxNss)) { + if (prBssInfo->pfOpChangeHandler) { + if (fgIsChangeRxNss) + prBssInfo->aucOpModeChangeState + [OP_NOTIFY_TYPE_HT_NSS] = + OP_NOTIFY_STATE_SENDING; + if (fgIsChangeBw) + prBssInfo->aucOpModeChangeState + [OP_NOTIFY_TYPE_HT_BW] = + OP_NOTIFY_STATE_SENDING; + } + if (fgIsChangeRxNss) { + u4Status = rlmSendSmPowerSaveFrame( + prAdapter, prStaRec, ucOpRxNss); + DBGLOG(RLM, INFO, + "Send HT SM Power Save frame: "); + DBGLOG(RLM, INFO, "BSS[%d] RxNss[%d]\n", + ucBssIndex, ucOpRxNss); + } + if (fgIsChangeBw) { + u4Status = rlmSendNotifyChannelWidthFrame( + prAdapter, prStaRec, ucChannelWidth); + DBGLOG(RLM, INFO, + "Send HT Notify Channel Width frame: "); + DBGLOG(RLM, INFO, "BSS[%d] BW[%d]\n", + ucBssIndex, ucChannelWidth); + } + } +#if CFG_SUPPORT_SMART_GEAR + } +#endif + /* Error handling */ + if (u4Status != WLAN_STATUS_SUCCESS) { + rlmCompleteOpModeChange(prAdapter, prBssInfo, FALSE); + return OP_CHANGE_STATUS_INVALID; + } + + /* <5.3> Change OP Info w/o waiting for notification Tx done */ + if (prBssInfo->pfOpChangeHandler == NULL || +#if CFG_SUPPORT_SMART_GEAR + eNewReq == 0x04 /* CNM_OPMODE_REQ_SMARTGEAR_1T2R */ || +#endif + (!fgIsChangeBw && !fgIsChangeRxNss)) { + rlmCompleteOpModeChange(prAdapter, prBssInfo, TRUE); + /* No callback */ + return OP_CHANGE_STATUS_VALID_CHANGE_CALLBACK_DONE; + } + + return OP_CHANGE_STATUS_VALID_CHANGE_CALLBACK_WAIT; + } + /* <6>Handling OP Info change for AP/GO */ + else if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + /* Complete OP Info change after notifying client by beacon */ + rlmCompleteOpModeChange(prAdapter, prBssInfo, TRUE); + return OP_CHANGE_STATUS_VALID_CHANGE_CALLBACK_DONE; + } + + /* Complete OP mode change if no sending action frames */ + rlmCompleteOpModeChange(prAdapter, prBssInfo, TRUE); + return OP_CHANGE_STATUS_VALID_CHANGE_CALLBACK_DONE; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Check our desired BW/RxNss is less or equal than peer's capability to + * prevent IOT issue. + * + * \param[in] prBssInfo + * \param[in] ucChannelWidth + * \param[in] ucOpTxNss + * + * \return + * TRUE : Can change to desired BW/RxNss + * FALSE: Should not change operation mode + */ +/*----------------------------------------------------------------------------*/ +static u_int8_t rlmCheckOpChangeParamForClient(struct BSS_INFO *prBssInfo, + uint8_t ucChannelWidth, + uint8_t ucOpRxNss) +{ + struct STA_RECORD *prStaRec; + + prStaRec = prBssInfo->prStaRecOfAP; + + if (!prStaRec) + return FALSE; + +#if CFG_SUPPORT_802_11AC + if (RLM_NET_IS_11AC(prBssInfo)) { /* VHT */ + /* Check peer OP Channel Width */ + switch (ucChannelWidth) { + case MAX_BW_80_80_MHZ: + if (prStaRec->ucVhtOpChannelWidth != + VHT_OP_CHANNEL_WIDTH_80P80) { + DBGLOG(RLM, INFO, + "Can't change BSS[%d] OP BW to:%d for peer VHT OP BW is:%d\n", + prBssInfo->ucBssIndex, ucChannelWidth, + prStaRec->ucVhtOpChannelWidth); + return FALSE; + } + break; + case MAX_BW_160MHZ: + if (prStaRec->ucVhtOpChannelWidth != + VHT_OP_CHANNEL_WIDTH_160) { + DBGLOG(RLM, INFO, + "Can't change BSS[%d] OP BW to:%d for peer VHT OP BW is:%d\n", + prBssInfo->ucBssIndex, ucChannelWidth, + prStaRec->ucVhtOpChannelWidth); + return FALSE; + } + break; + case MAX_BW_80MHZ: + if (prStaRec->ucVhtOpChannelWidth < + VHT_OP_CHANNEL_WIDTH_80) { + DBGLOG(RLM, INFO, + "Can't change BSS[%d] OP BW to:%d for peer VHT OP BW is:%d\n", + prBssInfo->ucBssIndex, ucChannelWidth, + prStaRec->ucVhtOpChannelWidth); + return FALSE; + } + break; + case MAX_BW_40MHZ: + if (!(prStaRec->ucHtPeerOpInfo1 & + HT_OP_INFO1_STA_CHNL_WIDTH) || + (!prBssInfo->fg40mBwAllowed)) { + DBGLOG(RLM, INFO, + "Can't change BSS[%d] OP BW to:%d for PeerOpBw:%d fg40mBwAllowed:%d\n", + prBssInfo->ucBssIndex, ucChannelWidth, + (uint8_t)(prStaRec->ucHtPeerOpInfo1 & + HT_OP_INFO1_STA_CHNL_WIDTH), + prBssInfo->fg40mBwAllowed); + return FALSE; + } + break; + case MAX_BW_20MHZ: + break; + default: + DBGLOG(RLM, WARN, + "BSS[%d] target OP BW:%d is invalid for VHT OpMode change\n", + prBssInfo->ucBssIndex, ucChannelWidth); + return FALSE; + } + + /* Check peer Rx Nss Cap */ + if (ucOpRxNss == 2 && + ((prStaRec->u2VhtRxMcsMap & VHT_CAP_INFO_MCS_2SS_MASK) >> + VHT_CAP_INFO_MCS_2SS_OFFSET) == + VHT_CAP_INFO_MCS_NOT_SUPPORTED) { + DBGLOG(RLM, INFO, + "Don't change Nss since VHT peer doesn't support 2ss\n"); + return FALSE; + } + + } else +#endif + { + if (RLM_NET_IS_11N(prBssInfo)) { /* HT */ + /* Check peer Channel Width */ + if (ucChannelWidth >= MAX_BW_80MHZ) { + DBGLOG(RLM, WARN, + "BSS[%d] target OP BW:%d is invalid for HT OpMode change\n", + prBssInfo->ucBssIndex, ucChannelWidth); + return FALSE; + } else if (ucChannelWidth == + MAX_BW_40MHZ) { + if (!(prStaRec->ucHtPeerOpInfo1 & + HT_OP_INFO1_STA_CHNL_WIDTH) || + (!prBssInfo->fg40mBwAllowed)) { + DBGLOG(RLM, INFO, + "Can't change BSS[%d] OP BW to:%d for PeerOpBw:%d fg40mBwAllowed:%d\n", + prBssInfo->ucBssIndex, + ucChannelWidth, + (uint8_t)( + prStaRec->ucHtPeerOpInfo1 & + HT_OP_INFO1_STA_CHNL_WIDTH), + prBssInfo->fg40mBwAllowed); + return FALSE; + } + } + + /* Check peer Rx Nss Cap */ + if (ucOpRxNss == 2 && + (prStaRec->aucRxMcsBitmask[1] == 0)) { + DBGLOG(RLM, INFO, + "Don't change Nss since HT peer doesn't support 2ss\n"); + return FALSE; + } + } + } + return TRUE; +} + +static u_int8_t rlmCheckOpChangeParamValid(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + uint8_t ucChannelWidth, + uint8_t ucOpRxNss, + uint8_t ucOpTxNss) +{ + uint8_t ucCapNss; + + ASSERT(prBssInfo); + + /* <1>Check if BSS PHY type is legacy mode */ + if (!RLM_NET_IS_11N(prBssInfo)) { + DBGLOG(RLM, WARN, + "Can't change BSS[%d] OP info for legacy BSS\n", + prBssInfo->ucBssIndex); + return FALSE; + } + + /* <2>Check network type */ + if ((prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) && + (prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT)) { + DBGLOG(RLM, WARN, + "Can't change BSS[%d] OP info for OpMode:%d\n", + prBssInfo->ucBssIndex, prBssInfo->eCurrentOPMode); + return FALSE; + } + + /* <3>Check if target OP BW/Nss <= Own Cap BW/Nss */ + ucCapNss = wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex); + if (ucOpRxNss > ucCapNss || ucOpRxNss == 0 || + ucOpTxNss > ucCapNss || ucOpTxNss == 0) { + DBGLOG(RLM, WARN, + "Can't change BSS[%d] OP RxNss[%d]TxNss[%d] due to CapNss[%d]\n", + prBssInfo->ucBssIndex, ucOpRxNss, ucOpTxNss, ucCapNss); + return FALSE; + } + + if (ucChannelWidth > cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex)) { + DBGLOG(RLM, WARN, + "Can't change BSS[%d] OP BW[%d] due to CapBW[%d]\n", + prBssInfo->ucBssIndex, ucChannelWidth, + cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex)); + return FALSE; + } + + /* <4>Check if target OP BW is valid for band and primary channel of + * current BSS + */ + if (prBssInfo->eBand == BAND_2G4) { + if ((ucChannelWidth != MAX_BW_20MHZ) && + (ucChannelWidth != MAX_BW_40MHZ)) { + DBGLOG(RLM, WARN, + "Can't change BSS[%d] OP BW to:%d for 2.4G\n", + prBssInfo->ucBssIndex, ucChannelWidth); + return FALSE; + } + } else { + /* It can only use BW20 for CH165 */ + if ((ucChannelWidth != MAX_BW_20MHZ) && + (prBssInfo->ucPrimaryChannel == 165)) { + DBGLOG(RLM, WARN, + "Can't change BSS[%d] OP BW to:%d for CH165\n", + prBssInfo->ucBssIndex, ucChannelWidth); + return FALSE; + } + + if ((ucChannelWidth == MAX_BW_160MHZ) && + ((prBssInfo->ucPrimaryChannel < 36) || + ((prBssInfo->ucPrimaryChannel > 64) && + (prBssInfo->ucPrimaryChannel < 100)) || + (prBssInfo->ucPrimaryChannel > 128))) { + DBGLOG(RLM, WARN, + "Can't change BSS[%d] to OP BW160 for primary CH%d\n", + prBssInfo->ucBssIndex, + prBssInfo->ucPrimaryChannel); + return FALSE; + } + } + + /* <5>Check if target OP BW/Nss <= peer's BW/Nss (STA mode) */ + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + if (rlmCheckOpChangeParamForClient(prBssInfo, ucChannelWidth, + ucOpRxNss) == FALSE) + return FALSE; + } + + return TRUE; +} + +void rlmDummyChangeOpHandler(struct ADAPTER *prAdapter, uint8_t ucBssIndex, + bool fgIsChangeSuccess) +{ + DBGLOG(RLM, INFO, "OP change done for BSS[%d] IsSuccess[%d]\n", + ucBssIndex, fgIsChangeSuccess); +} + +void rlmSetMaxTxPwrLimit(IN struct ADAPTER *prAdapter, int8_t cLimit, + uint8_t ucEnable) +{ + struct CMD_SET_AP_CONSTRAINT_PWR_LIMIT rTxPwrLimit; + + kalMemZero(&rTxPwrLimit, sizeof(rTxPwrLimit)); + rTxPwrLimit.ucCmdVer = 0x1; + rTxPwrLimit.ucPwrSetEnable = ucEnable; + if (ucEnable) { + if (cLimit > RLM_MAX_TX_PWR) { + DBGLOG(RLM, INFO, + "LM: Target MaxPwr %d Higher than Capability, reset to capability\n", + cLimit); + cLimit = RLM_MAX_TX_PWR; + } + if (cLimit < RLM_MIN_TX_PWR) { + DBGLOG(RLM, INFO, + "LM: Target MinPwr %d Lower than Capability, reset to capability\n", + cLimit); + cLimit = RLM_MIN_TX_PWR; + } + DBGLOG(RLM, INFO, + "LM: Set Max Tx Power Limit %d, Min Limit %d\n", cLimit, + RLM_MIN_TX_PWR); + rTxPwrLimit.cMaxTxPwr = + cLimit * 2; /* unit of cMaxTxPwr is 0.5 dBm */ + rTxPwrLimit.cMinTxPwr = RLM_MIN_TX_PWR * 2; + } else + DBGLOG(RLM, TRACE, "LM: Disable Tx Power Limit\n"); + wlanSendSetQueryCmd(prAdapter, CMD_ID_SET_AP_CONSTRAINT_PWR_LIMIT, TRUE, + FALSE, FALSE, nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_SET_AP_CONSTRAINT_PWR_LIMIT), + (uint8_t *)&rTxPwrLimit, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Send channel switch frame + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +uint32_t rlmSendChannelSwitchTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + DBGLOG(P2P, INFO, + "CSA TX Done Status: %d, seqNo: %d\n", + rTxDoneStatus, + prMsduInfo->ucTxSeqNum); + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; +} + +void rlmSendChannelSwitchFrame(struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + struct MSDU_INFO *prMsduInfo; + struct ACTION_CHANNEL_SWITCH_FRAME *prTxFrame; + struct BSS_INFO *prBssInfo; + uint16_t u2EstimatedFrameLen; + PFN_TX_DONE_HANDLER pfTxDoneHandler = (PFN_TX_DONE_HANDLER)NULL; + uint8_t aucBMC[] = BC_MAC_ADDR; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + if (!prBssInfo) + return; + + /* Calculate MSDU buffer length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + + sizeof(struct ACTION_CHANNEL_SWITCH_FRAME); + + /* Alloc MSDU_INFO */ + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc(prAdapter, + u2EstimatedFrameLen); + if (!prMsduInfo) + return; + + kalMemZero(prMsduInfo->prPacket, u2EstimatedFrameLen); + + prTxFrame = prMsduInfo->prPacket; + + /* Fill frame ctrl */ + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + + COPY_MAC_ADDR(prTxFrame->aucDestAddr, aucBMC); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); + + /* 3 Compose the frame body's frame */ + prTxFrame->ucCategory = CATEGORY_SPEC_MGT; + prTxFrame->ucAction = ACTION_CHNL_SWITCH; + + prTxFrame->aucInfoElem[0] = ELEM_ID_CH_SW_ANNOUNCEMENT; + prTxFrame->aucInfoElem[1] = 3; + prTxFrame->aucInfoElem[2] + = prAdapter->rWifiVar.ucChannelSwitchMode; + prTxFrame->aucInfoElem[3] + = prAdapter->rWifiVar.ucNewChannelNumber; + prTxFrame->aucInfoElem[4] + = prAdapter->rWifiVar.ucChannelSwitchCount; + + pfTxDoneHandler = rlmSendChannelSwitchTxDone; + + /* 4 Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, prMsduInfo, prBssInfo->ucBssIndex, + STA_REC_INDEX_BMCAST, WLAN_MAC_MGMT_HEADER_LEN, + sizeof(struct ACTION_CHANNEL_SWITCH_FRAME), + pfTxDoneHandler, + MSDU_RATE_MODE_AUTO); + + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rlm_domain.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rlm_domain.c new file mode 100644 index 0000000000000..540c40e569c33 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rlm_domain.c @@ -0,0 +1,5555 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rlm_domain.c#2 + */ + +/*! \file "rlm_domain.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" +#include "rlm_txpwr_init.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#if CFG_SUPPORT_DYNAMIC_PWR_LIMIT +/* dynamic tx power control */ +char *g_au1TxPwrChlTypeLabel[] = { + "NORMAL", + "ALL", + "RANGE", + "2G4", + "5G", + "BANDEDGE_2G4", + "BANDEDGE_5G", + "5GBAND1", + "5GBAND2", + "5GBAND3", + "5GBAND4", +}; + +char *g_au1TxPwrAppliedWayLabel[] = { + "wifi on", + "ioctl" +}; + +char *g_au1TxPwrOperationLabel[] = { + "power level", + "power offset" +}; +#endif + +#define PWR_BUF_LEN 200 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +#if CFG_SUPPORT_DYNAMIC_PWR_LIMIT +/* dynamic tx power control */ +char *g_au1TxPwrDefaultSetting[] = { +#if (CFG_SUPPORT_DYNA_TX_PWR_CTRL_OFDM_SETTING == 1) + "_SAR_PwrLevel;1;2;1;[2G4,,,,,,,,,,,][5G,,,,,,,,,,,]", + "_G_Scenario;1;2;1;[ALL,,,,,,,,,,,]", + "_G_Scenario;2;2;1;[ALL,,,,,,,,,,,]", + "_G_Scenario;3;2;1;[ALL,,,,,,,,,,,]", + "_G_Scenario;4;2;1;[ALL,,,,,,,,,,,]", + "_G_Scenario;5;2;1;[ALL,,,,,,,,,,,]", +#else + "DSI-0;1;2;1;[2G4,46,46,46,46,46,,,,][5GBAND1,46,46,46,46,46,46,46,,][5GBAND2,46,46,46,46,46,46,46,,][5GBAND3,46,46,46,46,46,46,46,,][5GBAND4,46,46,46,46,46,46,46,,][2G4,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND1,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND2,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND3,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND4,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46]", + "DSI-1;1;2;1;[2G4,46,46,46,46,46,,,,][5GBAND1,46,46,46,46,46,46,46,,][5GBAND2,46,46,46,46,46,46,46,,][5GBAND3,46,46,46,46,46,46,46,,][5GBAND4,46,46,46,46,46,46,46,,][2G4,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND1,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND2,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND3,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND4,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46]", + "DSI-2;1;2;1;[2G4,46,46,46,46,46,,,,][5GBAND1,46,46,46,46,46,46,46,,][5GBAND2,46,46,46,46,46,46,46,,][5GBAND3,46,46,46,46,46,46,46,,][5GBAND4,46,46,46,46,46,46,46,,][2G4,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND1,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND2,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND3,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND4,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46]", + "DSI-3;1;2;1;[2G4,46,46,46,46,46,,,,][5GBAND1,46,46,46,46,46,46,46,,][5GBAND2,46,46,46,46,46,46,46,,][5GBAND3,46,46,46,46,46,46,46,,][5GBAND4,46,46,46,46,46,46,46,,][2G4,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND1,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND2,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND3,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND4,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46]", + "DSI-4;1;2;1;[2G4,46,46,46,46,46,,,,][5GBAND1,46,46,46,46,46,46,46,,][5GBAND2,46,46,46,46,46,46,46,,][5GBAND3,46,46,46,46,46,46,46,,][5GBAND4,46,46,46,46,46,46,46,,][2G4,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND1,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND2,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND3,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND4,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46]", + "DSI-5;1;2;1;[2G4,46,46,46,46,46,,,,][5GBAND1,46,46,46,46,46,46,46,,][5GBAND2,46,46,46,46,46,46,46,,][5GBAND3,46,46,46,46,46,46,46,,][5GBAND4,46,46,46,46,46,46,46,,][2G4,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND1,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND2,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND3,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND4,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46]", + "DSI-6;1;2;1;[2G4,46,46,46,46,46,,,,][5GBAND1,46,46,46,46,46,46,46,,][5GBAND2,46,46,46,46,46,46,46,,][5GBAND3,46,46,46,46,46,46,46,,][5GBAND4,46,46,46,46,46,46,46,,][2G4,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND1,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND2,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND3,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND4,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46]", + "DSI-7;1;2;1;[2G4,46,46,46,46,46,,,,][5GBAND1,46,46,46,46,46,46,46,,][5GBAND2,46,46,46,46,46,46,46,,][5GBAND3,46,46,46,46,46,46,46,,][5GBAND4,46,46,46,46,46,46,46,,][2G4,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND1,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND2,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND3,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND4,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46]", + "DSI-8;1;2;1;[2G4,46,46,46,46,46,,,,][5GBAND1,46,46,46,46,46,46,46,,][5GBAND2,46,46,46,46,46,46,46,,][5GBAND3,46,46,46,46,46,46,46,,][5GBAND4,46,46,46,46,46,46,46,,][2G4,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND1,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND2,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND3,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND4,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46]", + "DSI-9;1;2;1;[2G4,46,46,46,46,46,,,,][5GBAND1,46,46,46,46,46,46,46,,][5GBAND2,46,46,46,46,46,46,46,,][5GBAND3,46,46,46,46,46,46,46,,][5GBAND4,46,46,46,46,46,46,46,,][2G4,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND1,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND2,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND3,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND4,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46]", + "DSI-10;1;2;1;[2G4,46,46,46,46,46,,,,][5GBAND1,46,46,46,46,46,46,46,,][5GBAND2,46,46,46,46,46,46,46,,][5GBAND3,46,46,46,46,46,46,46,,][5GBAND4,46,46,46,46,46,46,46,,][2G4,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND1,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND2,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND3,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND4,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46]", + "DSI-11;1;2;1;[2G4,46,46,46,46,46,,,,][5GBAND1,46,46,46,46,46,46,46,,][5GBAND2,46,46,46,46,46,46,46,,][5GBAND3,46,46,46,46,46,46,46,,][5GBAND4,46,46,46,46,46,46,46,,][2G4,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND1,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND2,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND3,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND4,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46]", + "DSI-12;1;2;1;[2G4,46,46,46,46,46,,,,][5GBAND1,46,46,46,46,46,46,46,,][5GBAND2,46,46,46,46,46,46,46,,][5GBAND3,46,46,46,46,46,46,46,,][5GBAND4,46,46,46,46,46,46,46,,][2G4,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND1,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND2,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND3,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46][5GBAND4,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46]", +#endif /* CFG_SUPPORT_DYNA_TX_PWR_CTRL_OFDM_SETTING */ +}; +#endif +/* 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 uint16_t g_u2CountryGroup0[] = { COUNTRY_CODE_JP }; + +static const uint16_t g_u2CountryGroup1[] = { + COUNTRY_CODE_AS, COUNTRY_CODE_AI, COUNTRY_CODE_BM, COUNTRY_CODE_KY, + COUNTRY_CODE_GU, COUNTRY_CODE_FM, COUNTRY_CODE_PR, COUNTRY_CODE_VI, + COUNTRY_CODE_AZ, COUNTRY_CODE_BW, COUNTRY_CODE_KH, COUNTRY_CODE_CX, + COUNTRY_CODE_CO, COUNTRY_CODE_CR, COUNTRY_CODE_GD, COUNTRY_CODE_GT, + COUNTRY_CODE_KI, COUNTRY_CODE_LB, COUNTRY_CODE_LR, COUNTRY_CODE_MN, + COUNTRY_CODE_AN, COUNTRY_CODE_NI, COUNTRY_CODE_PW, COUNTRY_CODE_WS, + COUNTRY_CODE_LK, COUNTRY_CODE_TT, COUNTRY_CODE_MM +}; + +static const uint16_t g_u2CountryGroup2[] = { + COUNTRY_CODE_AW, COUNTRY_CODE_LA, COUNTRY_CODE_AE, COUNTRY_CODE_UG +}; + +static const uint16_t g_u2CountryGroup3[] = { + COUNTRY_CODE_AR, COUNTRY_CODE_BR, COUNTRY_CODE_HK, COUNTRY_CODE_OM, + COUNTRY_CODE_PH, COUNTRY_CODE_SA, COUNTRY_CODE_SG, COUNTRY_CODE_ZA, + COUNTRY_CODE_VN, COUNTRY_CODE_KR, COUNTRY_CODE_DO, COUNTRY_CODE_FK, + COUNTRY_CODE_KZ, COUNTRY_CODE_MZ, COUNTRY_CODE_NA, COUNTRY_CODE_LC, + COUNTRY_CODE_VC, COUNTRY_CODE_UA, COUNTRY_CODE_UZ, COUNTRY_CODE_ZW, + COUNTRY_CODE_MP +}; + +static const uint16_t g_u2CountryGroup4[] = { + COUNTRY_CODE_AT, COUNTRY_CODE_BE, COUNTRY_CODE_BG, COUNTRY_CODE_HR, + COUNTRY_CODE_CZ, COUNTRY_CODE_DK, COUNTRY_CODE_FI, COUNTRY_CODE_FR, + COUNTRY_CODE_GR, COUNTRY_CODE_HU, COUNTRY_CODE_IS, COUNTRY_CODE_IE, + COUNTRY_CODE_IT, COUNTRY_CODE_LU, COUNTRY_CODE_NL, COUNTRY_CODE_NO, + COUNTRY_CODE_PL, COUNTRY_CODE_PT, COUNTRY_CODE_RO, COUNTRY_CODE_SK, + COUNTRY_CODE_SI, COUNTRY_CODE_ES, COUNTRY_CODE_SE, COUNTRY_CODE_CH, + COUNTRY_CODE_GB, COUNTRY_CODE_AL, COUNTRY_CODE_AD, COUNTRY_CODE_BY, + COUNTRY_CODE_BA, COUNTRY_CODE_VG, COUNTRY_CODE_CV, COUNTRY_CODE_CY, + COUNTRY_CODE_EE, COUNTRY_CODE_ET, COUNTRY_CODE_GF, COUNTRY_CODE_PF, + COUNTRY_CODE_TF, COUNTRY_CODE_GE, COUNTRY_CODE_DE, COUNTRY_CODE_GH, + COUNTRY_CODE_GP, COUNTRY_CODE_IQ, COUNTRY_CODE_KE, COUNTRY_CODE_LV, + COUNTRY_CODE_LS, COUNTRY_CODE_LI, COUNTRY_CODE_LT, COUNTRY_CODE_MK, + COUNTRY_CODE_MT, COUNTRY_CODE_MQ, COUNTRY_CODE_MR, COUNTRY_CODE_MU, + COUNTRY_CODE_YT, COUNTRY_CODE_MD, COUNTRY_CODE_MC, COUNTRY_CODE_ME, + COUNTRY_CODE_MS, COUNTRY_CODE_RE, COUNTRY_CODE_MF, COUNTRY_CODE_SM, + COUNTRY_CODE_SN, COUNTRY_CODE_RS, COUNTRY_CODE_TR, COUNTRY_CODE_TC, + COUNTRY_CODE_VA, COUNTRY_CODE_EU, COUNTRY_CODE_DZ +}; + +static const uint16_t g_u2CountryGroup5[] = { + COUNTRY_CODE_AU, COUNTRY_CODE_NZ, COUNTRY_CODE_EC, COUNTRY_CODE_PY, + COUNTRY_CODE_PE, COUNTRY_CODE_TH, COUNTRY_CODE_UY +}; + +static const uint16_t g_u2CountryGroup6[] = { COUNTRY_CODE_RU }; + +static const uint16_t g_u2CountryGroup7[] = { + COUNTRY_CODE_CL, COUNTRY_CODE_EG, COUNTRY_CODE_IN, COUNTRY_CODE_AG, + COUNTRY_CODE_BS, COUNTRY_CODE_BH, COUNTRY_CODE_BB, COUNTRY_CODE_BN, + COUNTRY_CODE_MV, COUNTRY_CODE_PA, COUNTRY_CODE_ZM, COUNTRY_CODE_CN +}; + +static const uint16_t g_u2CountryGroup8[] = { COUNTRY_CODE_MY }; + +static const uint16_t g_u2CountryGroup9[] = { COUNTRY_CODE_NP }; + +static const uint16_t g_u2CountryGroup10[] = { + COUNTRY_CODE_IL, COUNTRY_CODE_AM, COUNTRY_CODE_KW, COUNTRY_CODE_MA, + COUNTRY_CODE_NE, COUNTRY_CODE_TN +}; + +static const uint16_t g_u2CountryGroup11[] = { + COUNTRY_CODE_JO, COUNTRY_CODE_PG +}; + +static const uint16_t g_u2CountryGroup12[] = { COUNTRY_CODE_AF }; + +static const uint16_t g_u2CountryGroup13[] = { COUNTRY_CODE_NG }; + +static const uint16_t g_u2CountryGroup14[] = { + COUNTRY_CODE_PK, COUNTRY_CODE_QA, COUNTRY_CODE_BF, COUNTRY_CODE_GY, + COUNTRY_CODE_HT, COUNTRY_CODE_JM, COUNTRY_CODE_MO, COUNTRY_CODE_MW, + COUNTRY_CODE_RW, COUNTRY_CODE_KN, COUNTRY_CODE_TZ, COUNTRY_CODE_BD +}; + +static const uint16_t g_u2CountryGroup15[] = { COUNTRY_CODE_ID }; + +static const uint16_t g_u2CountryGroup16[] = { + COUNTRY_CODE_AO, COUNTRY_CODE_BZ, COUNTRY_CODE_BJ, COUNTRY_CODE_BT, + COUNTRY_CODE_BO, COUNTRY_CODE_BI, COUNTRY_CODE_CM, COUNTRY_CODE_CF, + COUNTRY_CODE_TD, COUNTRY_CODE_KM, COUNTRY_CODE_CD, COUNTRY_CODE_CG, + COUNTRY_CODE_CI, COUNTRY_CODE_DJ, COUNTRY_CODE_GQ, COUNTRY_CODE_ER, + COUNTRY_CODE_FJ, COUNTRY_CODE_GA, COUNTRY_CODE_GM, COUNTRY_CODE_GN, + COUNTRY_CODE_GW, COUNTRY_CODE_RKS, COUNTRY_CODE_KG, COUNTRY_CODE_LY, + COUNTRY_CODE_MG, COUNTRY_CODE_ML, COUNTRY_CODE_NR, COUNTRY_CODE_NC, + COUNTRY_CODE_ST, COUNTRY_CODE_SC, COUNTRY_CODE_SL, COUNTRY_CODE_SB, + COUNTRY_CODE_SO, COUNTRY_CODE_SR, COUNTRY_CODE_SZ, COUNTRY_CODE_TJ, + COUNTRY_CODE_TG, COUNTRY_CODE_TO, COUNTRY_CODE_TM, COUNTRY_CODE_TV, + COUNTRY_CODE_VU, COUNTRY_CODE_YE +}; + +static const uint16_t g_u2CountryGroup17[] = { + COUNTRY_CODE_US, COUNTRY_CODE_CA, COUNTRY_CODE_TW +}; + +static const uint16_t g_u2CountryGroup18[] = { + COUNTRY_CODE_DM, COUNTRY_CODE_SV, COUNTRY_CODE_HN +}; + +static const uint16_t g_u2CountryGroup19[] = { + COUNTRY_CODE_MX, COUNTRY_CODE_VE +}; + +static const uint16_t g_u2CountryGroup20[] = { + COUNTRY_CODE_CK, COUNTRY_CODE_CU, COUNTRY_CODE_TL, COUNTRY_CODE_FO, + COUNTRY_CODE_GI, COUNTRY_CODE_GG, COUNTRY_CODE_IR, COUNTRY_CODE_IM, + COUNTRY_CODE_JE, COUNTRY_CODE_KP, COUNTRY_CODE_MH, COUNTRY_CODE_NU, + COUNTRY_CODE_NF, COUNTRY_CODE_PS, COUNTRY_CODE_PN, COUNTRY_CODE_PM, + COUNTRY_CODE_SS, COUNTRY_CODE_SD, COUNTRY_CODE_SY +}; + +#if (CFG_SUPPORT_SINGLE_SKU == 1) +struct mtk_regd_control g_mtk_regd_control = { + .en = FALSE, + .state = REGD_STATE_UNDEFINED +}; + +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) +const struct ieee80211_regdomain default_regdom_ww = { + .n_reg_rules = 4, + .alpha2 = "99", + .reg_rules = { + /* channels 1..13 */ + REG_RULE_LIGHT(2412-10, 2472+10, 40, 0), + /* channels 14 */ + REG_RULE_LIGHT(2484-10, 2484+10, 20, 0), + /* channel 36..64 */ + REG_RULE_LIGHT(5150-10, 5350+10, 80, 0), + /* channel 100..165 */ + REG_RULE_LIGHT(5470-10, 5850+10, 80, 0), + } +}; +#endif + +struct TX_PWR_LIMIT_SECTION { + uint8_t ucSectionNum; + const char *arSectionNames[TX_PWR_LIMIT_SECTION_NUM]; +} gTx_Pwr_Limit_Section[] = { + {5, + {"legacy", "ht20", "ht40", "vht20", "offset"} + }, + {9, + {"cck", "ofdm", "ht20", "ht40", "vht20", "vht40", + "vht80", "vht160", "txbf_backoff"} + }, +}; + + +const u8 gTx_Pwr_Limit_Element_Num[][TX_PWR_LIMIT_SECTION_NUM] = { + {7, 6, 7, 7, 5}, + {POWER_LIMIT_SKU_CCK_NUM, POWER_LIMIT_SKU_OFDM_NUM, + POWER_LIMIT_SKU_HT20_NUM, POWER_LIMIT_SKU_HT40_NUM, + POWER_LIMIT_SKU_VHT20_NUM, POWER_LIMIT_SKU_VHT40_NUM, + POWER_LIMIT_SKU_VHT80_NUM, POWER_LIMIT_SKU_VHT160_NUM, + POWER_LIMIT_TXBF_BACKOFF_PARAM_NUM}, +}; + +const char *gTx_Pwr_Limit_Element[] + [TX_PWR_LIMIT_SECTION_NUM] + [TX_PWR_LIMIT_ELEMENT_NUM] = { + { + {"cck1_2", "cck_5_11", "ofdm6_9", "ofdm12_18", "ofdm24_36", + "ofdm48", "ofdm54"}, + {"mcs0_8", "mcs1_2_9_10", "mcs3_4_11_12", "mcs5_13", "mcs6_14", + "mcs7_15"}, + {"mcs0_8", "mcs1_2_9_10", "mcs3_4_11_12", "mcs5_13", "mcs6_14", + "mcs7_15", "mcs32"}, + {"mcs0", "mcs1_2", "mcs3_4", "mcs5_6", "mcs7", "mcs8", "mcs9"}, + {"lg40", "lg80", "vht40", "vht80", "vht160nc"}, + }, + { + {"c1", "c2", "c5", "c11"}, + {"o6", "o9", "o12", "o18", + "o24", "o36", "o48", "o54"}, + {"m0", "m1", "m2", "m3", "m4", "m5", "m6", "m7"}, + {"m0", "m1", "m2", "m3", "m4", "m5", "m6", "m7", "m32"}, + {"m0", "m1", "m2", "m3", "m4", "m5", "m6", "m7", "m8", "m9"}, + {"m0", "m1", "m2", "m3", "m4", "m5", "m6", "m7", "m8", "m9"}, + {"m0", "m1", "m2", "m3", "m4", "m5", "m6", "m7", "m8", "m9"}, + {"m0", "m1", "m2", "m3", "m4", "m5", "m6", "m7", "m8", "m9"}, + {"2to1"}, + }, +}; + +static const int8_t gTx_Pwr_Limit_2g_Ch[] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; +static const int8_t gTx_Pwr_Limit_5g_Ch[] = { + 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 100, 102, + 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 132, + 134, 136, 138, 140, 142, 144, 149, 151, 153, 155, 157, 159, 161, 165}; + +#define TX_PWR_LIMIT_2G_CH_NUM (ARRAY_SIZE(gTx_Pwr_Limit_2g_Ch)) +#define TX_PWR_LIMIT_5G_CH_NUM (ARRAY_SIZE(gTx_Pwr_Limit_5g_Ch)) + +u_int8_t g_bTxBfBackoffExists = FALSE; + +#endif + +struct DOMAIN_INFO_ENTRY arSupportedRegDomains[] = { + { + (uint16_t *) g_u2CountryGroup0, sizeof(g_u2CountryGroup0) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {82, BAND_2G4, CHNL_SPAN_5, 14, 1, FALSE} + , /* CH_SET_2G4_14_14 */ + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_NULL, 0, 0, 0, FALSE} + /* CH_SET_UNII_UPPER_NA */ + } + } + , + { + (uint16_t *) 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, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup2, sizeof(g_u2CountryGroup2) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE} + , /* CH_SET_UNII_UPPER_149_161 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup3, sizeof(g_u2CountryGroup3) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup4, sizeof(g_u2CountryGroup4) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup5, sizeof(g_u2CountryGroup5) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 5, TRUE} + , /* CH_SET_UNII_WW_100_116 */ + {121, BAND_5G, CHNL_SPAN_20, 132, 3, TRUE} + , /* CH_SET_UNII_WW_132_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + /* CH_SET_UNII_UPPER_149_165 */ + } + } + , + { + (uint16_t *) g_u2CountryGroup6, sizeof(g_u2CountryGroup6) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 132, 3, TRUE} + , /* CH_SET_UNII_WW_132_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup7, sizeof(g_u2CountryGroup7) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup8, sizeof(g_u2CountryGroup8) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 8, TRUE} + , /* 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} + } + } + , + { + (uint16_t *) g_u2CountryGroup9, sizeof(g_u2CountryGroup9) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE} + , /* CH_SET_UNII_UPPER_149_161 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup10, sizeof(g_u2CountryGroup10) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup11, sizeof(g_u2CountryGroup11) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_MID_NA */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) 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} + } + } + , + { + (uint16_t *) g_u2CountryGroup13, sizeof(g_u2CountryGroup13) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_LOW_NA */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup14, sizeof(g_u2CountryGroup14) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_LOW_NA */ + {118, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_MID_NA */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup15, sizeof(g_u2CountryGroup15) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + {115, BAND_5G, CHNL_SPAN_20, 36, 4, TRUE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE} + , /* CH_SET_UNII_UPPER_149_161 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup16, sizeof(g_u2CountryGroup16) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + {115, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_LOW_NA */ + {118, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_MID_NA */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup17, sizeof(g_u2CountryGroup17) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 11, FALSE} + , /* CH_SET_2G4_1_11 */ + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + /* CH_SET_UNII_UPPER_149_165 */ + } + } + , + { + (uint16_t *) g_u2CountryGroup18, sizeof(g_u2CountryGroup18) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 11, FALSE} + , /* CH_SET_2G4_1_11 */ + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 5, TRUE} + , /* CH_SET_UNII_WW_100_116 */ + {121, BAND_5G, CHNL_SPAN_20, 132, 3, TRUE} + , /* CH_SET_UNII_WW_132_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + /* CH_SET_UNII_UPPER_149_165 */ + } + } + , + { + (uint16_t *) g_u2CountryGroup19, sizeof(g_u2CountryGroup19) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 11, FALSE} + , /* CH_SET_2G4_1_11 */ + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_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} + } + } + , + { + (uint16_t *) g_u2CountryGroup20, sizeof(g_u2CountryGroup20) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + /* Note: Default group if no matched country code */ + NULL, 0, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } +}; + +static const uint16_t g_u2CountryGroup0_Passive[] = { + COUNTRY_CODE_TW +}; + +struct DOMAIN_INFO_ENTRY arSupportedRegDomains_Passive[] = { + { + (uint16_t *) g_u2CountryGroup0_Passive, + sizeof(g_u2CountryGroup0_Passive) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 0, FALSE} + , /* CH_SET_2G4_1_14_NA */ + {82, BAND_2G4, CHNL_SPAN_5, 14, 0, FALSE} + , + + {115, BAND_5G, CHNL_SPAN_20, 36, 0, FALSE} + , /* CH_SET_UNII_LOW_NA */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + } + } + , + { + /* Default passive scan channel table: ch52~64, ch100~144 */ + NULL, + 0, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 0, FALSE} + , /* CH_SET_2G4_1_14_NA */ + {82, BAND_2G4, CHNL_SPAN_5, 14, 0, FALSE} + , + + {115, BAND_5G, CHNL_SPAN_20, 36, 0, FALSE} + , /* CH_SET_UNII_LOW_NA */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + } + } +}; + +#if (CFG_SUPPORT_PWR_LIMIT_COUNTRY == 1) +struct SUBBAND_CHANNEL g_rRlmSubBand[] = { + + {BAND_2G4_LOWER_BOUND, BAND_2G4_UPPER_BOUND, 1, 0} + , /* 2.4G */ + {UNII1_LOWER_BOUND, UNII1_UPPER_BOUND, 2, 0} + , /* ch36,38,40,..,48 */ + {UNII2A_LOWER_BOUND, UNII2A_UPPER_BOUND, 2, 0} + , /* ch52,54,56,..,64 */ + {UNII2C_LOWER_BOUND, UNII2C_UPPER_BOUND, 2, 0} + , /* ch100,102,104,...,144 */ + {UNII3_LOWER_BOUND, UNII3_UPPER_BOUND, 2, 0} + /* ch149,151,153,....,165 */ +}; +#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 + */ +/*----------------------------------------------------------------------------*/ +struct DOMAIN_INFO_ENTRY *rlmDomainGetDomainInfo(struct ADAPTER *prAdapter) +{ +#define REG_DOMAIN_GROUP_NUM \ + (sizeof(arSupportedRegDomains) / sizeof(struct DOMAIN_INFO_ENTRY)) +#define REG_DOMAIN_DEF_IDX (REG_DOMAIN_GROUP_NUM - 1) + + struct DOMAIN_INFO_ENTRY *prDomainInfo; + struct REG_INFO *prRegInfo; + uint16_t u2TargetCountryCode; + uint16_t i, j; + + ASSERT(prAdapter); + + if (prAdapter->prDomainInfo) + return prAdapter->prDomainInfo; + + prRegInfo = &prAdapter->prGlueInfo->rRegInfo; + + DBGLOG(RLM, TRACE, "eRegChannelListMap=%d, u2CountryCode=0x%04x\n", + prRegInfo->eRegChannelListMap, + prAdapter->rWifiVar.u2CountryCode); + + /* + * Domain info can be specified by given idx of arSupportedRegDomains + * table, customized, or searched by country code, + * only one is set among these three methods in NVRAM. + */ + if (prRegInfo->eRegChannelListMap == REG_CH_MAP_TBL_IDX && + prRegInfo->ucRegChannelListIndex < REG_DOMAIN_GROUP_NUM) { + /* by given table idx */ + DBGLOG(RLM, TRACE, "ucRegChannelListIndex=%d\n", + prRegInfo->ucRegChannelListIndex); + prDomainInfo = &arSupportedRegDomains + [prRegInfo->ucRegChannelListIndex]; + } else if (prRegInfo->eRegChannelListMap == REG_CH_MAP_CUSTOMIZED) { + /* by customized */ + prDomainInfo = &prRegInfo->rDomainInfo; + } else { + /* by country code */ + u2TargetCountryCode = + prAdapter->rWifiVar.u2CountryCode; + + for (i = 0; i < REG_DOMAIN_GROUP_NUM; i++) { + prDomainInfo = &arSupportedRegDomains[i]; + + if ((prDomainInfo->u4CountryNum && + prDomainInfo->pu2CountryGroup) || + prDomainInfo->u4CountryNum == 0) { + for (j = 0; + j < prDomainInfo->u4CountryNum; + j++) { + if (prDomainInfo->pu2CountryGroup[j] == + u2TargetCountryCode) + break; + } + if (j < prDomainInfo->u4CountryNum) + break; /* Found */ + } + } + + /* If no matched country code, + * use the default regulatory domain + */ + if (i >= REG_DOMAIN_GROUP_NUM) { + DBGLOG(RLM, INFO, + "No matched country code, use the default regulatory domain\n"); + prDomainInfo = &arSupportedRegDomains + [REG_DOMAIN_DEF_IDX]; + } + } + + prAdapter->prDomainInfo = prDomainInfo; + return prDomainInfo; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Retrieve the supported channel list of specified band + * + * \param[in/out] eSpecificBand: BAND_2G4, BAND_5G or BAND_NULL + * (both 2.4G and 5G) + * fgNoDfs: whether to exculde DFS channels + * ucMaxChannelNum: max array size + * pucNumOfChannel: pointer to returned channel number + * paucChannelList: pointer to returned channel list array + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void +rlmDomainGetChnlList_V2(struct ADAPTER *prAdapter, + enum ENUM_BAND eSpecificBand, u_int8_t fgNoDfs, + uint8_t ucMaxChannelNum, uint8_t *pucNumOfChannel, + struct RF_CHANNEL_INFO *paucChannelList) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + enum ENUM_BAND band; + uint8_t max_count, i, ucNum; + struct CMD_DOMAIN_CHANNEL *prCh; + + if (eSpecificBand == BAND_2G4) { + i = 0; + max_count = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + } else if (eSpecificBand == BAND_5G) { + i = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + max_count = rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ) + + rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + } else { + i = 0; + max_count = rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ) + + rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + } + + ucNum = 0; + for (; i < max_count; i++) { + prCh = rlmDomainGetActiveChannels() + i; + if (fgNoDfs && (prCh->eFlags & IEEE80211_CHAN_RADAR)) + continue; /*not match*/ + + if (i < rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ)) + band = BAND_2G4; + else + band = BAND_5G; + + paucChannelList[ucNum].eBand = band; + paucChannelList[ucNum].ucChannelNum = prCh->u2ChNum; + + ucNum++; + if (ucMaxChannelNum == ucNum) + break; + } + + *pucNumOfChannel = ucNum; +#else + *pucNumOfChannel = 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Check if Channel supported by HW + * + * \param[in/out] eBand: BAND_2G4, BAND_5G or BAND_NULL + * (both 2.4G and 5G) + * ucNumOfChannel: channel number + * + * \return TRUE/FALSE + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rlmIsValidChnl(struct ADAPTER *prAdapter, uint8_t ucNumOfChannel, + enum ENUM_BAND eBand) +{ + struct ieee80211_supported_band *channelList; + int i, chSize; + struct GLUE_INFO *prGlueInfo; + struct wiphy *prWiphy; + + prGlueInfo = prAdapter->prGlueInfo; + prWiphy = priv_to_wiphy(prGlueInfo); + + if (eBand == BAND_5G) { + channelList = prWiphy->bands[KAL_BAND_5GHZ]; + chSize = channelList->n_channels; + } else if (eBand == BAND_2G4) { + channelList = prWiphy->bands[KAL_BAND_2GHZ]; + chSize = channelList->n_channels; + } else + return FALSE; + + for (i = 0; i < chSize; i++) { + if ((channelList->channels[i]).hw_value == ucNumOfChannel) + return TRUE; + } + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Retrieve the supported channel list of specified band + * + * \param[in/out] eSpecificBand: BAND_2G4, BAND_5G or BAND_NULL + * (both 2.4G and 5G) + * fgNoDfs: whether to exculde DFS channels + * ucMaxChannelNum: max array size + * pucNumOfChannel: pointer to returned channel number + * paucChannelList: pointer to returned channel list array + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void +rlmDomainGetChnlList(struct ADAPTER *prAdapter, + enum ENUM_BAND eSpecificBand, u_int8_t fgNoDfs, + uint8_t ucMaxChannelNum, uint8_t *pucNumOfChannel, + struct RF_CHANNEL_INFO *paucChannelList) +{ + uint8_t i, j, ucNum, ch; + struct DOMAIN_SUBBAND_INFO *prSubband; + struct DOMAIN_INFO_ENTRY *prDomainInfo; + + ASSERT(prAdapter); + ASSERT(paucChannelList); + ASSERT(pucNumOfChannel); + + if (regd_is_single_sku_en()) + return rlmDomainGetChnlList_V2(prAdapter, eSpecificBand, + fgNoDfs, ucMaxChannelNum, + pucNumOfChannel, + paucChannelList); + + /* 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; + + /* repoert to upper layer only non-DFS channel + * for ap mode usage + */ + if (fgNoDfs == TRUE && prSubband->fgDfs == TRUE) + continue; + + if (eSpecificBand == BAND_NULL || + prSubband->ucBand == eSpecificBand) { + for (j = 0; j < prSubband->ucNumChannels; j++) { + if (ucNum >= ucMaxChannelNum) + break; + + ch = prSubband->ucFirstChannelNum + + j * prSubband->ucChannelSpan; + if (!rlmIsValidChnl(prAdapter, ch, + prSubband->ucBand)) { + DBGLOG(RLM, INFO, + "Not support ch%d!\n", ch); + continue; + } + paucChannelList[ucNum].eBand = + prSubband->ucBand; + paucChannelList[ucNum].ucChannelNum = ch; + paucChannelList[ucNum].eDFS = prSubband->fgDfs; + ucNum++; + } + } + } + + *pucNumOfChannel = ucNum; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Retrieve DFS channels from 5G band + * + * \param[in/out] ucMaxChannelNum: max array size + * pucNumOfChannel: pointer to returned channel number + * paucChannelList: pointer to returned channel list array + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmDomainGetDfsChnls(struct ADAPTER *prAdapter, + uint8_t ucMaxChannelNum, uint8_t *pucNumOfChannel, + struct RF_CHANNEL_INFO *paucChannelList) +{ + uint8_t i, j, ucNum, ch; + struct DOMAIN_SUBBAND_INFO *prSubband; + struct DOMAIN_INFO_ENTRY *prDomainInfo; + + ASSERT(prAdapter); + ASSERT(paucChannelList); + ASSERT(pucNumOfChannel); + + prDomainInfo = rlmDomainGetDomainInfo(prAdapter); + ASSERT(prDomainInfo); + + ucNum = 0; + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubband = &prDomainInfo->rSubBand[i]; + + if (prSubband->ucBand == BAND_5G) { + if (!prAdapter->fgEnable5GBand) + continue; + + if (prSubband->fgDfs == TRUE) { + for (j = 0; j < prSubband->ucNumChannels; j++) { + if (ucNum >= ucMaxChannelNum) + break; + + ch = prSubband->ucFirstChannelNum + + j * prSubband->ucChannelSpan; + if (!rlmIsValidChnl(prAdapter, ch, + prSubband->ucBand)) { + DBGLOG(RLM, INFO, + "Not support ch%d!\n", ch); + continue; + } + + paucChannelList[ucNum].eBand = + prSubband->ucBand; + paucChannelList[ucNum].ucChannelNum = + ch; + ucNum++; + } + } + } + } + + *pucNumOfChannel = ucNum; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param[in] + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void rlmDomainSendCmd(struct ADAPTER *prAdapter) +{ + if (!regd_is_single_sku_en()) + rlmDomainSendPassiveScanInfoCmd(prAdapter); + rlmDomainSendDomainInfoCmd(prAdapter); +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + rlmDomainSendPwrLimitCmd(prAdapter); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param[in] + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void rlmDomainSendDomainInfoCmd_V2(struct ADAPTER *prAdapter) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + u8 max_channel_count = 0; + u32 buff_max_size, buff_valid_size; + struct CMD_SET_DOMAIN_INFO_V2 *prCmd; + struct CMD_DOMAIN_ACTIVE_CHANNEL_LIST *prChs; + struct wiphy *pWiphy; + + + pWiphy = priv_to_wiphy(prAdapter->prGlueInfo); + if (pWiphy->bands[KAL_BAND_2GHZ] != NULL) + max_channel_count += pWiphy->bands[KAL_BAND_2GHZ]->n_channels; + if (pWiphy->bands[KAL_BAND_5GHZ] != NULL) + max_channel_count += pWiphy->bands[KAL_BAND_5GHZ]->n_channels; + + if (max_channel_count == 0) { + DBGLOG(RLM, ERROR, "%s, invalid channel count.\n", __func__); + ASSERT(0); + } + + + buff_max_size = sizeof(struct CMD_SET_DOMAIN_INFO_V2) + + max_channel_count * sizeof(struct CMD_DOMAIN_CHANNEL); + + prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, buff_max_size); + if (!prCmd) { + DBGLOG(RLM, ERROR, "Alloc cmd buffer failed\n"); + return; + } + prChs = &(prCmd->arActiveChannels); + + + /* + * Fill in the active channels + */ + rlmExtractChannelInfo(max_channel_count, prChs); + + prCmd->u4CountryCode = rlmDomainGetCountryCode(); + prCmd->uc2G4Bandwidth = prAdapter->rWifiVar.uc2G4BandwidthMode; + prCmd->uc5GBandwidth = prAdapter->rWifiVar.uc5GBandwidthMode; + prCmd->aucPadding[0] = 0; + prCmd->aucPadding[1] = 0; + + buff_valid_size = sizeof(struct CMD_SET_DOMAIN_INFO_V2) + + (prChs->u1ActiveChNum2g + prChs->u1ActiveChNum5g) * + sizeof(struct CMD_DOMAIN_CHANNEL); + + DBGLOG(RLM, INFO, + "rlmDomainSendDomainInfoCmd_V2(), buff_valid_size = 0x%x\n", + buff_valid_size); + + + /* Set domain info to chip */ + wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_DOMAIN_INFO, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + buff_valid_size, + (uint8_t *) prCmd, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + cnmMemFree(prAdapter, prCmd); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param[in] + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void rlmDomainSendDomainInfoCmd(struct ADAPTER *prAdapter) +{ + struct DOMAIN_INFO_ENTRY *prDomainInfo; + struct CMD_SET_DOMAIN_INFO *prCmd; + struct DOMAIN_SUBBAND_INFO *prSubBand; + uint8_t i; + + if (regd_is_single_sku_en()) + return rlmDomainSendDomainInfoCmd_V2(prAdapter); + + + prDomainInfo = rlmDomainGetDomainInfo(prAdapter); + ASSERT(prDomainInfo); + + prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, + sizeof(struct CMD_SET_DOMAIN_INFO)); + if (!prCmd) { + DBGLOG(RLM, ERROR, "Alloc cmd buffer failed\n"); + return; + } + kalMemZero(prCmd, sizeof(struct CMD_SET_DOMAIN_INFO)); + + prCmd->u2CountryCode = + prAdapter->rWifiVar.u2CountryCode; + prCmd->u2IsSetPassiveScan = 0; + prCmd->uc2G4Bandwidth = + prAdapter->rWifiVar.uc2G4BandwidthMode; + prCmd->uc5GBandwidth = + prAdapter->rWifiVar.uc5GBandwidthMode; + prCmd->aucReserved[0] = 0; + prCmd->aucReserved[1] = 0; + + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubBand = &prDomainInfo->rSubBand[i]; + + prCmd->rSubBand[i].ucRegClass = prSubBand->ucRegClass; + prCmd->rSubBand[i].ucBand = prSubBand->ucBand; + + if (prSubBand->ucBand != BAND_NULL && prSubBand->ucBand + < BAND_NUM) { + prCmd->rSubBand[i].ucChannelSpan + = prSubBand->ucChannelSpan; + prCmd->rSubBand[i].ucFirstChannelNum + = prSubBand->ucFirstChannelNum; + prCmd->rSubBand[i].ucNumChannels + = prSubBand->ucNumChannels; + } + } + + /* Set domain info to chip */ + wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_DOMAIN_INFO, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct CMD_SET_DOMAIN_INFO), /* u4SetQueryInfoLen */ + (uint8_t *) prCmd, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + cnmMemFree(prAdapter, prCmd); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param[in] + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void rlmDomainSendPassiveScanInfoCmd(struct ADAPTER *prAdapter) +{ +#define REG_DOMAIN_PASSIVE_DEF_IDX 1 +#define REG_DOMAIN_PASSIVE_GROUP_NUM \ + (sizeof(arSupportedRegDomains_Passive) \ + / sizeof(struct DOMAIN_INFO_ENTRY)) + + struct DOMAIN_INFO_ENTRY *prDomainInfo; + struct CMD_SET_DOMAIN_INFO *prCmd; + struct DOMAIN_SUBBAND_INFO *prSubBand; + uint16_t u2TargetCountryCode; + uint8_t i, j; + + prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, + sizeof(struct CMD_SET_DOMAIN_INFO)); + if (!prCmd) { + DBGLOG(RLM, ERROR, "Alloc cmd buffer failed\n"); + return; + } + kalMemZero(prCmd, sizeof(struct CMD_SET_DOMAIN_INFO)); + + prCmd->u2CountryCode = prAdapter->rWifiVar.u2CountryCode; + prCmd->u2IsSetPassiveScan = 1; + prCmd->uc2G4Bandwidth = + prAdapter->rWifiVar.uc2G4BandwidthMode; + prCmd->uc5GBandwidth = + prAdapter->rWifiVar.uc5GBandwidthMode; + prCmd->aucReserved[0] = 0; + prCmd->aucReserved[1] = 0; + + DBGLOG(RLM, TRACE, "u2CountryCode=0x%04x\n", + prAdapter->rWifiVar.u2CountryCode); + + u2TargetCountryCode = prAdapter->rWifiVar.u2CountryCode; + + for (i = 0; i < REG_DOMAIN_PASSIVE_GROUP_NUM; i++) { + prDomainInfo = &arSupportedRegDomains_Passive[i]; + + for (j = 0; j < prDomainInfo->u4CountryNum; j++) { + if (prDomainInfo->pu2CountryGroup[j] == + u2TargetCountryCode) + break; + } + if (j < prDomainInfo->u4CountryNum) + break; /* Found */ + } + + if (i >= REG_DOMAIN_PASSIVE_GROUP_NUM) + prDomainInfo = &arSupportedRegDomains_Passive + [REG_DOMAIN_PASSIVE_DEF_IDX]; + + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubBand = &prDomainInfo->rSubBand[i]; + + prCmd->rSubBand[i].ucRegClass = prSubBand->ucRegClass; + prCmd->rSubBand[i].ucBand = prSubBand->ucBand; + + if (prSubBand->ucBand != BAND_NULL && prSubBand->ucBand + < BAND_NUM) { + prCmd->rSubBand[i].ucChannelSpan = + prSubBand->ucChannelSpan; + prCmd->rSubBand[i].ucFirstChannelNum = + prSubBand->ucFirstChannelNum; + prCmd->rSubBand[i].ucNumChannels = + prSubBand->ucNumChannels; + } + } + + /* Set passive scan channel info to chip */ + wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_DOMAIN_INFO, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct CMD_SET_DOMAIN_INFO), /* u4SetQueryInfoLen */ + (uint8_t *) prCmd, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + cnmMemFree(prAdapter, prCmd); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in/out] + * + * \return TRUE Legal channel + * FALSE Illegal channel for current regulatory domain + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rlmDomainIsLegalChannel_V2(struct ADAPTER *prAdapter, + enum ENUM_BAND eBand, + uint8_t ucChannel) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + uint8_t idx, start_idx, end_idx; + struct CMD_DOMAIN_CHANNEL *prCh; + + if (eBand == BAND_2G4) { + start_idx = 0; + end_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + } else { + start_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + end_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ) + + rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ); + } + + for (idx = start_idx; idx < end_idx; idx++) { + prCh = rlmDomainGetActiveChannels() + idx; + + if (prCh->u2ChNum == ucChannel) + return TRUE; + } + + return FALSE; +#else + return FALSE; +#endif +} + +u_int8_t rlmDomainIsLegalChannel(struct ADAPTER *prAdapter, + enum ENUM_BAND eBand, uint8_t ucChannel) +{ + uint8_t i, j; + struct DOMAIN_SUBBAND_INFO *prSubband; + struct DOMAIN_INFO_ENTRY *prDomainInfo; + + if (regd_is_single_sku_en()) + return rlmDomainIsLegalChannel_V2(prAdapter, eBand, ucChannel); + + + 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) { + if (!rlmIsValidChnl(prAdapter, + ucChannel, + prSubband->ucBand)) { + DBGLOG(RLM, INFO, + "Not support ch%d!\n", + ucChannel); + return FALSE; + } else + return TRUE; + + } + } + } + } + + return FALSE; +} + +u_int8_t rlmDomainIsLegalDfsChannel(struct ADAPTER *prAdapter, + enum ENUM_BAND eBand, uint8_t ucChannel) +{ + uint8_t i, j; + struct DOMAIN_SUBBAND_INFO *prSubband; + struct 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 + && prSubband->fgDfs == TRUE) { + for (j = 0; j < prSubband->ucNumChannels; j++) { + if ((prSubband->ucFirstChannelNum + j * + prSubband->ucChannelSpan) + == ucChannel) { + return TRUE; + } + } + } + } + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in/out] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ + +uint32_t rlmDomainSupOperatingClassIeFill(uint8_t *pBuf) +{ + /* + * The Country element should only be included for + * Status Code 0 (Successful). + */ + uint32_t u4IeLen; + uint8_t aucClass[12] = { 0x01, 0x02, 0x03, 0x05, 0x16, 0x17, 0x19, 0x1b, + 0x1c, 0x1e, 0x20, 0x21 + }; + + /* + * The Supported Operating Classes element is used by a STA to + * advertise the operating classes that it is capable of operating + * with in this country. + * The Country element (see 8.4.2.10) allows a STA to configure its + * PHY and MAC for operation when the operating triplet of Operating + * Extension Identifier, Operating Class, and Coverage Class fields + * is present. + */ + SUP_OPERATING_CLASS_IE(pBuf)->ucId = ELEM_ID_SUP_OPERATING_CLASS; + SUP_OPERATING_CLASS_IE(pBuf)->ucLength = 1 + sizeof(aucClass); + SUP_OPERATING_CLASS_IE(pBuf)->ucCur = 0x0c; /* 0x51 */ + kalMemCopy(SUP_OPERATING_CLASS_IE(pBuf)->ucSup, aucClass, + sizeof(aucClass)); + u4IeLen = (SUP_OPERATING_CLASS_IE(pBuf)->ucLength + 2); + pBuf += u4IeLen; + + COUNTRY_IE(pBuf)->ucId = ELEM_ID_COUNTRY_INFO; + COUNTRY_IE(pBuf)->ucLength = 6; + COUNTRY_IE(pBuf)->aucCountryStr[0] = 0x55; + COUNTRY_IE(pBuf)->aucCountryStr[1] = 0x53; + COUNTRY_IE(pBuf)->aucCountryStr[2] = 0x20; + COUNTRY_IE(pBuf)->arCountryStr[0].ucFirstChnlNum = 1; + COUNTRY_IE(pBuf)->arCountryStr[0].ucNumOfChnl = 11; + COUNTRY_IE(pBuf)->arCountryStr[0].cMaxTxPwrLv = 0x1e; + u4IeLen += (COUNTRY_IE(pBuf)->ucLength + 2); + + return u4IeLen; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param[in] + * + * @return (fgValid) : 0 -> inValid, 1 -> Valid + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rlmDomainCheckChannelEntryValid(struct ADAPTER *prAdapter, + uint8_t ucCentralCh) +{ + u_int8_t fgValid = FALSE; + uint8_t ucTemp = 0xff; + uint8_t i; + /*Check Power limit table channel efficient or not */ + + /* CH50 is not located in any FCC subbands + * but it's a valid central channel for 160C + */ + if (ucCentralCh == 50) { + fgValid = TRUE; + return fgValid; + } + + for (i = POWER_LIMIT_2G4; i < POWER_LIMIT_SUBAND_NUM; i++) { + if ((ucCentralCh >= g_rRlmSubBand[i].ucStartCh) && + (ucCentralCh <= g_rRlmSubBand[i].ucEndCh)) + ucTemp = (ucCentralCh - g_rRlmSubBand[i].ucStartCh) % + g_rRlmSubBand[i].ucInterval; + } + + if (ucTemp == 0) + fgValid = TRUE; + return fgValid; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return + */ +/*----------------------------------------------------------------------------*/ +uint8_t rlmDomainGetCenterChannel(enum ENUM_BAND eBand, uint8_t ucPriChannel, + enum ENUM_CHNL_EXT eExtend) +{ + uint8_t ucCenterChannel; + + if (eExtend == CHNL_EXT_SCA) + ucCenterChannel = ucPriChannel + 2; + else if (eExtend == CHNL_EXT_SCB) + ucCenterChannel = ucPriChannel - 2; + else + ucCenterChannel = ucPriChannel; + + return ucCenterChannel; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return + */ +/*----------------------------------------------------------------------------*/ +u_int8_t +rlmDomainIsValidRfSetting(struct ADAPTER *prAdapter, + enum ENUM_BAND eBand, + uint8_t ucPriChannel, + enum ENUM_CHNL_EXT eExtend, + enum ENUM_CHANNEL_WIDTH eChannelWidth, + uint8_t ucChannelS1, uint8_t ucChannelS2) +{ + uint8_t ucCenterCh = 0; + uint8_t ucUpperChannel; + uint8_t ucLowerChannel; + u_int8_t fgValidChannel = TRUE; + u_int8_t fgUpperChannel = TRUE; + u_int8_t fgLowerChannel = TRUE; + u_int8_t fgValidBW = TRUE; + u_int8_t fgValidRfSetting = TRUE; + uint32_t u4PrimaryOffset; + + /*DBG msg for Channel InValid */ + if (eChannelWidth == CW_20_40MHZ) { + ucCenterCh = rlmDomainGetCenterChannel(eBand, ucPriChannel, + eExtend); + + /* Check Central Channel Valid or Not */ + fgValidChannel = rlmDomainCheckChannelEntryValid(prAdapter, + ucCenterCh); + if (fgValidChannel == FALSE) + DBGLOG(RLM, WARN, "Rf20: CentralCh=%d\n", ucCenterCh); + + /* Check Upper Channel and Lower Channel */ + switch (eExtend) { + case CHNL_EXT_SCA: + ucUpperChannel = ucPriChannel + 4; + ucLowerChannel = ucPriChannel; + break; + case CHNL_EXT_SCB: + ucUpperChannel = ucPriChannel; + ucLowerChannel = ucPriChannel - 4; + break; + default: + ucUpperChannel = ucPriChannel; + ucLowerChannel = ucPriChannel; + break; + } + + fgUpperChannel = rlmDomainCheckChannelEntryValid(prAdapter, + ucUpperChannel); + if (fgUpperChannel == FALSE) + DBGLOG(RLM, WARN, "Rf20: UpperCh=%d\n", ucUpperChannel); + + fgLowerChannel = rlmDomainCheckChannelEntryValid(prAdapter, + ucLowerChannel); + if (fgLowerChannel == FALSE) + DBGLOG(RLM, WARN, "Rf20: LowerCh=%d\n", ucLowerChannel); + + } else if ((eChannelWidth == CW_80MHZ) || + (eChannelWidth == CW_160MHZ)) { + ucCenterCh = ucChannelS1; + + /* Check Central Channel Valid or Not */ + if (eChannelWidth != CW_160MHZ) { + /* BW not check , ex: primary 36 and + * central channel 50 will fail the check + */ + fgValidChannel = + rlmDomainCheckChannelEntryValid(prAdapter, + ucCenterCh); + } + + if (fgValidChannel == FALSE) + DBGLOG(RLM, WARN, "Rf80/160C: CentralCh=%d\n", + ucCenterCh); + } else if (eChannelWidth == CW_80P80MHZ) { + ucCenterCh = ucChannelS1; + + fgValidChannel = rlmDomainCheckChannelEntryValid(prAdapter, + ucCenterCh); + + if (fgValidChannel == FALSE) + DBGLOG(RLM, WARN, "Rf160NC: CentralCh1=%d\n", + ucCenterCh); + + ucCenterCh = ucChannelS2; + + fgValidChannel = rlmDomainCheckChannelEntryValid(prAdapter, + ucCenterCh); + + if (fgValidChannel == FALSE) + DBGLOG(RLM, WARN, "Rf160NC: CentralCh2=%d\n", + ucCenterCh); + + /* Check Central Channel Valid or Not */ + } else { + DBGLOG(RLM, ERROR, "Wrong BW =%d\n", eChannelWidth); + fgValidChannel = FALSE; + } + + /* Check BW Setting Correct or Not */ + if (eBand == BAND_2G4) { + if (eChannelWidth != CW_20_40MHZ) { + fgValidBW = FALSE; + DBGLOG(RLM, WARN, "Rf: B=%d, W=%d\n", + eBand, eChannelWidth); + } + } else { + if ((eChannelWidth == CW_80MHZ) || + (eChannelWidth == CW_80P80MHZ)) { + u4PrimaryOffset = CAL_CH_OFFSET_80M(ucPriChannel, + ucChannelS1); + if (u4PrimaryOffset > 4) { + fgValidBW = FALSE; + DBGLOG(RLM, WARN, "Rf: PriOffSet=%d, W=%d\n", + u4PrimaryOffset, eChannelWidth); + } + if (ucPriChannel == 165) { + fgValidBW = FALSE; + DBGLOG(RLM, WARN, + "Rf: PriOffSet=%d, W=%d C=%d\n", + u4PrimaryOffset, eChannelWidth, + ucPriChannel); + } + } else if (eChannelWidth == CW_160MHZ) { + u4PrimaryOffset = CAL_CH_OFFSET_160M(ucPriChannel, + ucCenterCh); + if (u4PrimaryOffset > 8) { + fgValidBW = FALSE; + DBGLOG(RLM, WARN, + "Rf: PriOffSet=%d, W=%d\n", + u4PrimaryOffset, eChannelWidth); + } + } + } + + if ((fgValidBW == FALSE) || (fgValidChannel == FALSE) || + (fgUpperChannel == FALSE) || (fgLowerChannel == FALSE)) + fgValidRfSetting = FALSE; + + return fgValidRfSetting; + +} + +#if (CFG_SUPPORT_SINGLE_SKU == 1) +/* + * This function coverts country code from alphabet chars to u32, + * the caller need to pass country code chars and do size check + */ +uint32_t rlmDomainAlpha2ToU32(uint8_t *pcAlpha2, uint8_t ucAlpha2Size) +{ + uint8_t ucIdx; + uint32_t u4CountryCode = 0; + + if (ucAlpha2Size > TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN) { + DBGLOG(RLM, ERROR, "alpha2 size %d is invalid!(max: %d)\n", + ucAlpha2Size, TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN); + ucAlpha2Size = TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN; + } + + for (ucIdx = 0; ucIdx < ucAlpha2Size; ucIdx++) + u4CountryCode |= (pcAlpha2[ucIdx] << (ucIdx * 8)); + + return u4CountryCode; +} + +uint8_t rlmDomainTxPwrLimitGetTableVersion( + uint8_t *pucBuf, uint32_t u4BufLen) +{ +#define TX_PWR_LIMIT_VERSION_STR_LEN 7 +#define TX_PWR_LIMIT_MAX_VERSION 1 + uint32_t u4TmpPos = 0; + uint8_t ucVersion = 0; + + while (u4TmpPos < u4BufLen && pucBuf[u4TmpPos] != '<') + u4TmpPos++; + + if (u4TmpPos >= (u4BufLen - TX_PWR_LIMIT_VERSION_STR_LEN)) + return ucVersion; + + if (kalStrnCmp(&pucBuf[u4TmpPos + 1], "Ver:", 4) == 0) { + ucVersion = (pucBuf[u4TmpPos + 5] - '0') * 10 + + (pucBuf[u4TmpPos + 6] - '0'); + } + + if (ucVersion > TX_PWR_LIMIT_MAX_VERSION) + ucVersion = 0; + + return ucVersion; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Search the tx power limit setting range of the specified in the text + * file + * + * \param[IN] u4CountryCode The u32 type of the specified country. + * \param[IN] pucBuf The content of the text file. + * \param[IN] u4cBufLen End boundary of the text file. + * \param[OUT] pu4CountryStart Store the start position of the desired country + * settings. + * \param[OUT] pu4CountryEnd Store the end position of the desired country + * settings. + * + * \retval TRUE Success. + * \retval FALSE Failure. + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rlmDomainTxPwrLimitGetCountryRange( + uint32_t u4CountryCode, uint8_t *pucBuf, uint32_t u4BufLen, + uint32_t *pu4CountryStart, uint32_t *pu4CountryEnd) +{ + uint32_t u4TmpPos = 0; + char pcrCountryStr[TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN + 1] = {0}; + uint8_t cIdx = 0; + + while (1) { + while (u4TmpPos < u4BufLen && pucBuf[u4TmpPos] != '[') + u4TmpPos++; + + u4TmpPos++; /* skip the '[' char */ + + cIdx = 0; + while ((u4TmpPos < u4BufLen) && + (cIdx < TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN) && + (pucBuf[u4TmpPos] != ']')) { + pcrCountryStr[cIdx++] = pucBuf[u4TmpPos]; + u4TmpPos++; + } + + u4TmpPos++; /* skip the ']' char */ + + if ((u4TmpPos >= u4BufLen) || + (cIdx > TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN)) + return FALSE; + + if (u4CountryCode == + rlmDomainAlpha2ToU32(pcrCountryStr, cIdx)) { + DBGLOG(RLM, INFO, + "Found TxPwrLimit table for CountryCode \"%s\"\n", + pcrCountryStr); + *pu4CountryStart = u4TmpPos; + /* the location after char ']' */ + break; + } + } + + while (u4TmpPos < u4BufLen && pucBuf[u4TmpPos] != '[') + u4TmpPos++; + + *pu4CountryEnd = u4TmpPos; + + return TRUE; +} + +u_int8_t rlmDomainTxPwrLimitSearchSection(const char *pSectionName, + uint8_t *pucBuf, uint32_t *pu4Pos, uint32_t u4BufEnd) +{ + uint32_t u4TmpPos = *pu4Pos; + uint8_t uSectionNameLen = kalStrLen(pSectionName); + + while (1) { + while (u4TmpPos < u4BufEnd && pucBuf[u4TmpPos] != '<') + u4TmpPos++; + + u4TmpPos++; /* skip char '<' */ + + if (u4TmpPos + uSectionNameLen >= u4BufEnd) + return FALSE; + + if (kalStrnCmp(&pucBuf[u4TmpPos], + pSectionName, uSectionNameLen) == 0) { + + /* Go to the end of section header line */ + while ((u4TmpPos < u4BufEnd) && + (pucBuf[u4TmpPos] != '\n')) + u4TmpPos++; + + *pu4Pos = u4TmpPos; + + break; + } + } + + return TRUE; +} + +u_int8_t rlmDomainTxPwrLimitSectionEnd(uint8_t *pucBuf, + const char *pSectionName, uint32_t *pu4Pos, uint32_t u4BufEnd) +{ + uint32_t u4TmpPos = *pu4Pos; + char cTmpChar = 0; + uint8_t uSectionNameLen = kalStrLen(pSectionName); + + while (u4TmpPos < u4BufEnd) { + cTmpChar = pucBuf[u4TmpPos]; + + /* skip blank lines */ + if (cTmpChar == ' ' || cTmpChar == '\t' || + cTmpChar == '\n' || cTmpChar == '\r') { + u4TmpPos++; + continue; + } + + break; + } + + /* 2 means '/' and '>' */ + if (u4TmpPos + uSectionNameLen + 2 >= u4BufEnd) { + *pu4Pos = u4BufEnd; + return FALSE; + } + + if (pucBuf[u4TmpPos] != '<') + return FALSE; + + if (pucBuf[u4TmpPos + 1] != '/' || + pucBuf[u4TmpPos + 2 + uSectionNameLen] != '>' || + kalStrnCmp(&pucBuf[u4TmpPos + 2], + pSectionName, uSectionNameLen)) { + + *pu4Pos = u4TmpPos + uSectionNameLen + 2; + return FALSE; + } + + /* 3 means go to the location after '>' */ + *pu4Pos = u4TmpPos + uSectionNameLen + 3; + return TRUE; +} + +int8_t rlmDomainTxPwrLimitGetChIdx( + struct TX_PWR_LIMIT_DATA *pTxPwrLimit, uint8_t ucChannel) +{ + int8_t cIdx = 0; + + for (cIdx = 0; cIdx < pTxPwrLimit->ucChNum; cIdx++) + if (ucChannel == + pTxPwrLimit->rChannelTxPwrLimit[cIdx].ucChannel) + return cIdx; + + DBGLOG(RLM, ERROR, + "Can't find idx of channel %d in TxPwrLimit data\n", + ucChannel); + + return -1; +} + +u_int8_t rlmDomainTxPwrLimitIsTxBfBackoffSection( + uint8_t ucVersion, uint8_t ucSectionIdx) +{ + if (ucVersion == 1 && ucSectionIdx == 8) + return TRUE; + + return FALSE; +} +u_int8_t rlmDomainTxPwrLimitLoadChannelSetting( + uint8_t ucVersion, uint8_t *pucBuf, uint32_t *pu4Pos, uint32_t u4BufEnd, + struct TX_PWR_LIMIT_DATA *pTxPwrLimit, uint8_t ucSectionIdx) +{ + uint32_t u4TmpPos = *pu4Pos; + char cTmpChar = 0; + struct CHANNEL_TX_PWR_LIMIT *prChTxPwrLimit = NULL; + u_int8_t bNeg = FALSE; + int8_t cLimitValue = 0, cChIdx = 0; + uint8_t ucIdx = 0, ucChannel = 0; + uint8_t ucElementNum = + gTx_Pwr_Limit_Element_Num[ucVersion][ucSectionIdx]; + + /* skip blank lines */ + while (u4TmpPos < u4BufEnd) { + cTmpChar = pucBuf[u4TmpPos]; + + if (cTmpChar == ' ' || cTmpChar == '\t' || + cTmpChar == '\n' || cTmpChar == '\r') { + u4TmpPos++; + continue; + } + + break; + } + + /* current is at the location of 'c', + * check remaining buf length for 'chxxx' + */ + if (u4TmpPos + 5 >= u4BufEnd) { + DBGLOG(RLM, ERROR, + "Invalid location of ch setting: %u/%u\n", + u4TmpPos, u4BufEnd); + return FALSE; + } + + if (pucBuf[u4TmpPos] == 'c' && pucBuf[u4TmpPos + 1] == 'h') { + ucChannel = (pucBuf[u4TmpPos + 2] - '0') * 100 + + (pucBuf[u4TmpPos + 3] - '0') * 10 + + (pucBuf[u4TmpPos + 4] - '0'); + } else { /* invalid format */ + *pu4Pos = u4TmpPos; + DBGLOG(RLM, ERROR, + "Invalid ch setting starting chars: %c%c\n", + pucBuf[u4TmpPos], pucBuf[u4TmpPos + 1]); + + /* goto next line */ + while (*pu4Pos < u4BufEnd && pucBuf[*pu4Pos] != '\n') + (*pu4Pos)++; + + return TRUE; + } + + cChIdx = rlmDomainTxPwrLimitGetChIdx(pTxPwrLimit, ucChannel); + + if (cChIdx == -1) { + *pu4Pos = u4TmpPos; + DBGLOG(RLM, ERROR, "Invalid ch %u %c%c%c\n", ucChannel, + pucBuf[u4TmpPos + 2], + pucBuf[u4TmpPos + 3], pucBuf[u4TmpPos + 4]); + + /* goto next line */ + while (*pu4Pos < u4BufEnd && pucBuf[*pu4Pos] != '\n') + (*pu4Pos)++; + + return TRUE; + } + + u4TmpPos += 5; + + prChTxPwrLimit = &pTxPwrLimit->rChannelTxPwrLimit[cChIdx]; + + /* read the channel TxPwrLimit settings */ + for (ucIdx = 0; ucIdx < ucElementNum; ucIdx++) { + + /* skip blank and comma */ + while (u4TmpPos < u4BufEnd) { + cTmpChar = pucBuf[u4TmpPos]; + + if ((cTmpChar == ' ') || + (cTmpChar == '\t') || + (cTmpChar == ',')) { + u4TmpPos++; + continue; + } + break; + } + + if (u4TmpPos >= u4BufEnd) { + *pu4Pos = u4BufEnd; + DBGLOG(RLM, ERROR, + "Invalid location of ch tx pwr limit val: %u/%u\n", + u4TmpPos, u4BufEnd); + return FALSE; + } + + bNeg = FALSE; + + cTmpChar = pucBuf[u4TmpPos]; + + if (cTmpChar == '-') { + bNeg = TRUE; + u4TmpPos++; + } else { + if (cTmpChar == 'x') { + if (!rlmDomainTxPwrLimitIsTxBfBackoffSection( + ucVersion, ucSectionIdx)) { + prChTxPwrLimit-> + rTxPwrLimitValue + [ucSectionIdx][ucIdx] = + TX_PWR_LIMIT_MAX_VAL; + } else { + prChTxPwrLimit->rTxBfBackoff[ucIdx] = + TX_PWR_LIMIT_MAX_VAL; + } + u4TmpPos++; + continue; + } + } + + cLimitValue = 0; + while (u4TmpPos < u4BufEnd) { + cTmpChar = pucBuf[u4TmpPos]; + + if (cTmpChar < '0' || cTmpChar > '9') + break; + + cLimitValue = (cLimitValue * 10) + (cTmpChar - '0'); + u4TmpPos++; + } + + if (bNeg) + cLimitValue = -cLimitValue; + if (!rlmDomainTxPwrLimitIsTxBfBackoffSection( + ucVersion, ucSectionIdx)) { + prChTxPwrLimit->rTxPwrLimitValue[ucSectionIdx][ucIdx] = + cLimitValue; + } else { + prChTxPwrLimit->rTxBfBackoff[ucIdx] = + cLimitValue; + } + } + + *pu4Pos = u4TmpPos; + return TRUE; +} + +void rlmDomainTxPwrLimitRemoveComments( + uint8_t *pucBuf, uint32_t u4BufLen) +{ + uint32_t u4TmpPos = 0; + char cTmpChar = 0; + + while (u4TmpPos < u4BufLen) { + cTmpChar = pucBuf[u4TmpPos]; + + if (cTmpChar == '#') { + while (cTmpChar != '\n') { + pucBuf[u4TmpPos] = ' '; + + u4TmpPos++; + if (u4TmpPos >= u4BufLen) + break; + + cTmpChar = pucBuf[u4TmpPos]; + } + } + u4TmpPos++; + } +} + +u_int8_t rlmDomainTxPwrLimitLoad( + struct ADAPTER *prAdapter, uint8_t *pucBuf, uint32_t u4BufLen, + uint8_t ucVersion, uint32_t u4CountryCode, + struct TX_PWR_LIMIT_DATA *pTxPwrLimitData) +{ + uint8_t uSecIdx = 0; + uint8_t ucSecNum = gTx_Pwr_Limit_Section[ucVersion].ucSectionNum; + uint32_t u4CountryStart = 0, u4CountryEnd = 0, u4Pos = 0; + struct TX_PWR_LIMIT_SECTION *prSection = + &gTx_Pwr_Limit_Section[ucVersion]; + uint8_t *prFileName = prAdapter->chip_info->prTxPwrLimitFile; + + + if (!rlmDomainTxPwrLimitGetCountryRange(u4CountryCode, pucBuf, + u4BufLen, &u4CountryStart, &u4CountryEnd)) { + DBGLOG(RLM, ERROR, "Can't find specified table in %s\n", + prFileName); + return FALSE; + } + u4Pos = u4CountryStart; + + for (uSecIdx = 0; uSecIdx < ucSecNum; uSecIdx++) { + const uint8_t *pSecName = + prSection->arSectionNames[uSecIdx]; + if (!rlmDomainTxPwrLimitSearchSection( + pSecName, pucBuf, &u4Pos, + u4CountryEnd)) { + DBGLOG(RLM, ERROR, + "Can't find specified section %s in %s\n", + pSecName, + prFileName); + continue; + } + + DBGLOG(RLM, INFO, "Find specified section %s in %s\n", + pSecName, + prFileName); + + while (!rlmDomainTxPwrLimitSectionEnd(pucBuf, + pSecName, + &u4Pos, u4CountryEnd) && + u4Pos < u4CountryEnd) { + if (!rlmDomainTxPwrLimitLoadChannelSetting( + ucVersion, pucBuf, &u4Pos, u4CountryEnd, + pTxPwrLimitData, uSecIdx)) + return FALSE; + if (rlmDomainTxPwrLimitIsTxBfBackoffSection( + ucVersion, uSecIdx)) + g_bTxBfBackoffExists = TRUE; + } + } + + DBGLOG(RLM, INFO, "Load %s finished\n", prFileName); + return TRUE; +} + +void rlmDomainTxPwrLimitSetChValues( + uint8_t ucVersion, + struct CMD_CHANNEL_POWER_LIMIT_V2 *pCmd, + struct CHANNEL_TX_PWR_LIMIT *pChTxPwrLimit) +{ + uint8_t section = 0, e = 0; + uint8_t ucElementNum = 0; + + pCmd->tx_pwr_dsss_cck = pChTxPwrLimit->rTxPwrLimitValue[0][0]; + pCmd->tx_pwr_dsss_bpsk = pChTxPwrLimit->rTxPwrLimitValue[0][1]; + + /* 6M, 9M */ + pCmd->tx_pwr_ofdm_bpsk = pChTxPwrLimit->rTxPwrLimitValue[0][2]; + /* 12M, 18M */ + pCmd->tx_pwr_ofdm_qpsk = pChTxPwrLimit->rTxPwrLimitValue[0][3]; + /* 24M, 36M */ + pCmd->tx_pwr_ofdm_16qam = pChTxPwrLimit->rTxPwrLimitValue[0][4]; + pCmd->tx_pwr_ofdm_48m = pChTxPwrLimit->rTxPwrLimitValue[0][5]; + pCmd->tx_pwr_ofdm_54m = pChTxPwrLimit->rTxPwrLimitValue[0][6]; + + /* MCS0*/ + pCmd->tx_pwr_ht20_bpsk = pChTxPwrLimit->rTxPwrLimitValue[1][0]; + /* MCS1, MCS2*/ + pCmd->tx_pwr_ht20_qpsk = pChTxPwrLimit->rTxPwrLimitValue[1][1]; + /* MCS3, MCS4*/ + pCmd->tx_pwr_ht20_16qam = pChTxPwrLimit->rTxPwrLimitValue[1][2]; + /* MCS5*/ + pCmd->tx_pwr_ht20_mcs5 = pChTxPwrLimit->rTxPwrLimitValue[1][3]; + /* MCS6*/ + pCmd->tx_pwr_ht20_mcs6 = pChTxPwrLimit->rTxPwrLimitValue[1][4]; + /* MCS7*/ + pCmd->tx_pwr_ht20_mcs7 = pChTxPwrLimit->rTxPwrLimitValue[1][5]; + + /* MCS0*/ + pCmd->tx_pwr_ht40_bpsk = pChTxPwrLimit->rTxPwrLimitValue[2][0]; + /* MCS1, MCS2*/ + pCmd->tx_pwr_ht40_qpsk = pChTxPwrLimit->rTxPwrLimitValue[2][1]; + /* MCS3, MCS4*/ + pCmd->tx_pwr_ht40_16qam = pChTxPwrLimit->rTxPwrLimitValue[2][2]; + /* MCS5*/ + pCmd->tx_pwr_ht40_mcs5 = pChTxPwrLimit->rTxPwrLimitValue[2][3]; + /* MCS6*/ + pCmd->tx_pwr_ht40_mcs6 = pChTxPwrLimit->rTxPwrLimitValue[2][4]; + /* MCS7*/ + pCmd->tx_pwr_ht40_mcs7 = pChTxPwrLimit->rTxPwrLimitValue[2][5]; + /* MCS32*/ + pCmd->tx_pwr_ht40_mcs32 = pChTxPwrLimit->rTxPwrLimitValue[2][6]; + + /* MCS0*/ + pCmd->tx_pwr_vht20_bpsk = pChTxPwrLimit->rTxPwrLimitValue[3][0]; + /* MCS1, MCS2*/ + pCmd->tx_pwr_vht20_qpsk = pChTxPwrLimit->rTxPwrLimitValue[3][1]; + /* MCS3, MCS4*/ + pCmd->tx_pwr_vht20_16qam = pChTxPwrLimit->rTxPwrLimitValue[3][2]; + /* MCS5, MCS6*/ + pCmd->tx_pwr_vht20_64qam = pChTxPwrLimit->rTxPwrLimitValue[3][3]; + pCmd->tx_pwr_vht20_mcs7 = pChTxPwrLimit->rTxPwrLimitValue[3][4]; + pCmd->tx_pwr_vht20_mcs8 = pChTxPwrLimit->rTxPwrLimitValue[3][5]; + pCmd->tx_pwr_vht20_mcs9 = pChTxPwrLimit->rTxPwrLimitValue[3][6]; + + pCmd->tx_pwr_vht_40 = pChTxPwrLimit->rTxPwrLimitValue[4][2]; + pCmd->tx_pwr_vht_80 = pChTxPwrLimit->rTxPwrLimitValue[4][3]; + pCmd->tx_pwr_vht_160c = pChTxPwrLimit->rTxPwrLimitValue[4][5]; + pCmd->tx_pwr_vht_160nc = pChTxPwrLimit->rTxPwrLimitValue[4][4]; + pCmd->tx_pwr_lg_40 = pChTxPwrLimit->rTxPwrLimitValue[4][0]; + pCmd->tx_pwr_lg_80 = pChTxPwrLimit->rTxPwrLimitValue[4][1]; + + + DBGLOG(RLM, TRACE, "ch %d\n", pCmd->ucCentralCh); + for (section = 0; section < TX_PWR_LIMIT_SECTION_NUM; section++) { + struct TX_PWR_LIMIT_SECTION *pSection = + &gTx_Pwr_Limit_Section[ucVersion]; + ucElementNum = gTx_Pwr_Limit_Element_Num[ucVersion][section]; + for (e = 0; e < ucElementNum; e++) + DBGLOG(RLM, TRACE, "TxPwrLimit[%s][%s]= %d\n", + pSection->arSectionNames[section], + gTx_Pwr_Limit_Element[ucVersion][section][e], + pChTxPwrLimit->rTxPwrLimitValue[section][e]); + } +} + +void rlmDomainTxPwrLimitPerRateSetChValues( + uint8_t ucVersion, + struct CMD_TXPOWER_CHANNEL_POWER_LIMIT_PER_RATE *pCmd, + struct CHANNEL_TX_PWR_LIMIT *pChTxPwrLimit) +{ + uint8_t section = 0, e = 0, count = 0; + uint8_t ucElementNum = 0; + + for (section = 0; section < TX_PWR_LIMIT_SECTION_NUM; section++) { + if (rlmDomainTxPwrLimitIsTxBfBackoffSection(ucVersion, section)) + continue; + ucElementNum = gTx_Pwr_Limit_Element_Num[ucVersion][section]; + for (e = 0; e < ucElementNum; e++) { + pCmd->aucTxPwrLimit.i1PwrLimit[count] = + pChTxPwrLimit->rTxPwrLimitValue[section][e]; + count++; + } + } + + DBGLOG(RLM, TRACE, "ch %d\n", pCmd->u1CentralCh); + count = 0; + for (section = 0; section < TX_PWR_LIMIT_SECTION_NUM; section++) { + struct TX_PWR_LIMIT_SECTION *pSection = + &gTx_Pwr_Limit_Section[ucVersion]; + if (rlmDomainTxPwrLimitIsTxBfBackoffSection(ucVersion, section)) + continue; + ucElementNum = gTx_Pwr_Limit_Element_Num[ucVersion][section]; + for (e = 0; e < ucElementNum; e++) { + DBGLOG(RLM, TRACE, "TxPwrLimit[%s][%s]= %d\n", + pSection->arSectionNames[section], + gTx_Pwr_Limit_Element[ucVersion][section][e], + pCmd->aucTxPwrLimit.i1PwrLimit[count]); + count++; + } + } +} + +void rlmDomainTxPwrLimitSetValues( + uint8_t ucVersion, + struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2 *pSetCmd, + struct TX_PWR_LIMIT_DATA *pTxPwrLimit) +{ + uint8_t ucIdx = 0; + int8_t cChIdx = 0; + struct CMD_CHANNEL_POWER_LIMIT_V2 *pCmd = NULL; + struct CHANNEL_TX_PWR_LIMIT *pChTxPwrLimit = NULL; + + if (!pSetCmd || !pTxPwrLimit) { + DBGLOG(RLM, ERROR, "Invalid TxPwrLimit request\n"); + return; + } + + for (ucIdx = 0; ucIdx < pSetCmd->ucNum; ucIdx++) { + pCmd = &(pSetCmd->rChannelPowerLimit[ucIdx]); + cChIdx = rlmDomainTxPwrLimitGetChIdx(pTxPwrLimit, + pCmd->ucCentralCh); + if (cChIdx == -1) { + DBGLOG(RLM, ERROR, + "Invalid ch idx found while assigning values\n"); + continue; + } + pChTxPwrLimit = &pTxPwrLimit->rChannelTxPwrLimit[cChIdx]; + rlmDomainTxPwrLimitSetChValues(ucVersion, pCmd, pChTxPwrLimit); + } +} + +void rlmDomainTxPwrLimitPerRateSetValues( + uint8_t ucVersion, + struct CMD_SET_TXPOWER_COUNTRY_TX_POWER_LIMIT_PER_RATE *pSetCmd, + struct TX_PWR_LIMIT_DATA *pTxPwrLimit) +{ + uint8_t ucIdx = 0; + int8_t cChIdx = 0; + struct CMD_TXPOWER_CHANNEL_POWER_LIMIT_PER_RATE *pChPwrLimit = NULL; + struct CHANNEL_TX_PWR_LIMIT *pChTxPwrLimit = NULL; + + if (pSetCmd == NULL) + return; + + for (ucIdx = 0; ucIdx < pSetCmd->ucNum; ucIdx++) { + pChPwrLimit = &(pSetCmd->rChannelPowerLimit[ucIdx]); + cChIdx = rlmDomainTxPwrLimitGetChIdx(pTxPwrLimit, + pChPwrLimit->u1CentralCh); + + if (cChIdx == -1) { + DBGLOG(RLM, ERROR, + "Invalid ch idx found while assigning values\n"); + continue; + } + pChTxPwrLimit = &pTxPwrLimit->rChannelTxPwrLimit[cChIdx]; + rlmDomainTxPwrLimitPerRateSetChValues(ucVersion, + pChPwrLimit, pChTxPwrLimit); + } +} + +u_int8_t rlmDomainTxPwrLimitLoadFromFile( + struct ADAPTER *prAdapter, + uint8_t *pucConfigBuf, uint32_t *pu4ConfigReadLen) +{ +#define TXPWRLIMIT_FILE_LEN 64 + u_int8_t bRet = TRUE; + uint8_t *prFileName = prAdapter->chip_info->prTxPwrLimitFile; + uint8_t aucPath[4][TXPWRLIMIT_FILE_LEN]; + + kalMemZero(aucPath, sizeof(aucPath)); + kalSnprintf(aucPath[0], TXPWRLIMIT_FILE_LEN, "%s", prFileName); + kalSnprintf(aucPath[1], TXPWRLIMIT_FILE_LEN, + "/data/misc/%s", prFileName); + kalSnprintf(aucPath[2], TXPWRLIMIT_FILE_LEN, + "/data/misc/wifi/%s", prFileName); + kalSnprintf(aucPath[3], TXPWRLIMIT_FILE_LEN, + "/storage/sdcard0/%s", prFileName); + + kalMemZero(pucConfigBuf, WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE); + *pu4ConfigReadLen = 0; + + if (wlanGetFileContent( + prAdapter, + aucPath[0], + pucConfigBuf, + WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE, + pu4ConfigReadLen, TRUE) == 0) { + /* ToDo:: Nothing */ + } else if (wlanGetFileContent( + prAdapter, + aucPath[1], + pucConfigBuf, + WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE, + pu4ConfigReadLen, FALSE) == 0) { + /* ToDo:: Nothing */ + } else if (wlanGetFileContent( + prAdapter, + aucPath[2], + pucConfigBuf, + WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE, + pu4ConfigReadLen, FALSE) == 0) { + /* ToDo:: Nothing */ + } else if (wlanGetFileContent( + prAdapter, + aucPath[3], + pucConfigBuf, + WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE, + pu4ConfigReadLen, FALSE) == 0) { + /* ToDo:: Nothing */ + } else { + bRet = FALSE; + goto error; + } + + if (pucConfigBuf[0] == '\0' || *pu4ConfigReadLen == 0) { + bRet = FALSE; + goto error; + } + +error: + + return bRet; +} + +u_int8_t rlmDomainGetTxPwrLimit( + uint32_t country_code, + uint8_t *pucVersion, + struct GLUE_INFO *prGlueInfo, + struct TX_PWR_LIMIT_DATA *pTxPwrLimitData) +{ + u_int8_t bRet = TRUE; + uint8_t *pucConfigBuf = NULL; + uint32_t u4ConfigReadLen = 0; + + pucConfigBuf = (uint8_t *) kalMemAlloc( + WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE, VIR_MEM_TYPE); + + if (!pucConfigBuf) + return FALSE; + + bRet = rlmDomainTxPwrLimitLoadFromFile(prGlueInfo->prAdapter, + pucConfigBuf, &u4ConfigReadLen); + + rlmDomainTxPwrLimitRemoveComments(pucConfigBuf, u4ConfigReadLen); + *pucVersion = rlmDomainTxPwrLimitGetTableVersion(pucConfigBuf, + u4ConfigReadLen); + + if (!rlmDomainTxPwrLimitLoad(prGlueInfo->prAdapter, + pucConfigBuf, u4ConfigReadLen, *pucVersion, + country_code, pTxPwrLimitData)) { + bRet = FALSE; + goto error; + } + +error: + + kalMemFree(pucConfigBuf, + VIR_MEM_TYPE, WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE); + + return bRet; +} + +#endif + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Check if power limit setting is in the range [MIN_TX_POWER, + * MAX_TX_POWER] + * + * @param[in] + * + * @return (fgValid) : 0 -> inValid, 1 -> Valid + */ +/*----------------------------------------------------------------------------*/ +u_int8_t +rlmDomainCheckPowerLimitValid(struct ADAPTER *prAdapter, + struct COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION + rPowerLimitTableConfiguration, + uint8_t ucPwrLimitNum) +{ + uint16_t i; + u_int8_t fgValid = TRUE; + int8_t *prPwrLimit; + + prPwrLimit = &rPowerLimitTableConfiguration.aucPwrLimit[0]; + + for (i = 0; i < ucPwrLimitNum; i++, prPwrLimit++) { + if (*prPwrLimit > MAX_TX_POWER || *prPwrLimit < MIN_TX_POWER) { + fgValid = FALSE; + break; /*Find out Wrong Power limit */ + } + } + return fgValid; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief 1.Check if power limit configuration table valid(channel intervel) + * 2.Check if power limit configuration/default table entry repeat + * + * @param[in] + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void rlmDomainCheckCountryPowerLimitTable(struct ADAPTER *prAdapter) +{ +#define PwrLmtConf g_rRlmPowerLimitConfiguration + uint16_t i, j; + uint16_t u2CountryCodeTable, u2CountryCodeCheck; + u_int8_t fgChannelValid = FALSE; + u_int8_t fgPowerLimitValid = FALSE; + u_int8_t fgEntryRepetetion = FALSE; + u_int8_t fgTableValid = TRUE; + + /*1.Configuration Table Check */ + for (i = 0; i < sizeof(PwrLmtConf) / + sizeof(struct COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION); i++) { + /*Table Country Code */ + WLAN_GET_FIELD_BE16(&PwrLmtConf[i].aucCountryCode[0], + &u2CountryCodeTable); + + /*<1>Repetition Entry Check */ + for (j = i + 1; j < sizeof(PwrLmtConf) / + sizeof(struct COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION); + j++) { + + WLAN_GET_FIELD_BE16(&PwrLmtConf[j].aucCountryCode[0], + &u2CountryCodeCheck); + if (((PwrLmtConf[i].ucCentralCh) == + PwrLmtConf[j].ucCentralCh) + && (u2CountryCodeTable == u2CountryCodeCheck)) { + fgEntryRepetetion = TRUE; + DBGLOG(RLM, LOUD, + "Domain: Configuration Repetition CC=%c%c, Ch=%d\n", + PwrLmtConf[i].aucCountryCode[0], + PwrLmtConf[i].aucCountryCode[1], + PwrLmtConf[i].ucCentralCh); + } + } + + /*<2>Channel Number Interval Check */ + fgChannelValid = + rlmDomainCheckChannelEntryValid(prAdapter, + PwrLmtConf[i].ucCentralCh); + + /*<3>Power Limit Range Check */ + fgPowerLimitValid = + rlmDomainCheckPowerLimitValid(prAdapter, + PwrLmtConf[i], + PWR_LIMIT_NUM); + + if (fgChannelValid == FALSE || fgPowerLimitValid == FALSE) { + fgTableValid = FALSE; + DBGLOG(RLM, LOUD, + "Domain: CC=%c%c, Ch=%d, Limit: %d,%d,%d,%d,%d,%d,%d,%d,%d, Valid:%d,%d\n", + PwrLmtConf[i].aucCountryCode[0], + PwrLmtConf[i].aucCountryCode[1], + PwrLmtConf[i].ucCentralCh, + PwrLmtConf[i].aucPwrLimit[PWR_LIMIT_CCK], + PwrLmtConf[i].aucPwrLimit[PWR_LIMIT_20M_L], + PwrLmtConf[i].aucPwrLimit[PWR_LIMIT_20M_H], + PwrLmtConf[i].aucPwrLimit[PWR_LIMIT_40M_L], + PwrLmtConf[i].aucPwrLimit[PWR_LIMIT_40M_H], + PwrLmtConf[i].aucPwrLimit[PWR_LIMIT_80M_L], + PwrLmtConf[i].aucPwrLimit[PWR_LIMIT_80M_H], + PwrLmtConf[i].aucPwrLimit[PWR_LIMIT_160M_L], + PwrLmtConf[i].aucPwrLimit[PWR_LIMIT_160M_H], + fgChannelValid, + fgPowerLimitValid); + } + + if (u2CountryCodeTable == COUNTRY_CODE_NULL) { + DBGLOG(RLM, LOUD, "Domain: Full search down\n"); + break; /*End of country table entry */ + } + + } + + if (fgEntryRepetetion == FALSE) + DBGLOG(RLM, TRACE, + "Domain: Configuration Table no Repetiton.\n"); + + /*Configuration Table no error */ + if (fgTableValid == TRUE) + prAdapter->fgIsPowerLimitTableValid = TRUE; + else + prAdapter->fgIsPowerLimitTableValid = FALSE; + + /*2.Default Table Repetition Entry Check */ + fgEntryRepetetion = FALSE; + for (i = 0; i < sizeof(g_rRlmPowerLimitDefault) / + sizeof(struct COUNTRY_POWER_LIMIT_TABLE_DEFAULT); i++) { + + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[i]. + aucCountryCode[0], + &u2CountryCodeTable); + + for (j = i + 1; j < sizeof(g_rRlmPowerLimitDefault) / + sizeof(struct COUNTRY_POWER_LIMIT_TABLE_DEFAULT); j++) { + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[j]. + aucCountryCode[0], + &u2CountryCodeCheck); + if (u2CountryCodeTable == u2CountryCodeCheck) { + fgEntryRepetetion = TRUE; + DBGLOG(RLM, LOUD, + "Domain: Default Repetition CC=%c%c\n", + g_rRlmPowerLimitDefault[j]. + aucCountryCode[0], + g_rRlmPowerLimitDefault[j]. + aucCountryCode[1]); + } + } + } + if (fgEntryRepetetion == FALSE) + DBGLOG(RLM, TRACE, "Domain: Default Table no Repetiton.\n"); +#undef PwrLmtConf +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param[in] + * + * @return (u2TableIndex) : if 0xFFFF -> No Table Match + */ +/*----------------------------------------------------------------------------*/ +uint16_t rlmDomainPwrLimitDefaultTableDecision(struct ADAPTER *prAdapter, + uint16_t u2CountryCode) +{ + + uint16_t i; + uint16_t u2CountryCodeTable = COUNTRY_CODE_NULL; + uint16_t u2TableIndex = POWER_LIMIT_TABLE_NULL; /* No Table Match */ + + /*Default Table Index */ + for (i = 0; i < sizeof(g_rRlmPowerLimitDefault) / + sizeof(struct COUNTRY_POWER_LIMIT_TABLE_DEFAULT); i++) { + + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[i]. + aucCountryCode[0], + &u2CountryCodeTable); + + if (u2CountryCodeTable == u2CountryCode) { + u2TableIndex = i; + break; /*match country code */ + } else if (u2CountryCodeTable == COUNTRY_CODE_NULL) { + u2TableIndex = i; + break; /*find last one country- Default */ + } + } + + return u2TableIndex; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Fill power limit CMD by Power Limit Default Table(regulation) + * + * @param[in] + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void +rlmDomainBuildCmdByDefaultTable(struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT + *prCmd, + uint16_t u2DefaultTableIndex) +{ + uint16_t i, k; + struct COUNTRY_POWER_LIMIT_TABLE_DEFAULT *prPwrLimitSubBand = NULL; + struct CMD_CHANNEL_POWER_LIMIT *prPwrLimit = NULL; + struct CMD_CHANNEL_POWER_LIMIT_HE *prPwrLmtHE = NULL; + enum ENUM_PWR_LIMIT_TYPE eType; + + int8_t cLmtBand = 0; + + ASSERT(prCmd); + + prPwrLimitSubBand = &g_rRlmPowerLimitDefault[u2DefaultTableIndex]; + eType = prCmd->ucLimitType; + + if (eType == PWR_LIMIT_TYPE_COMP_11AX) + prPwrLmtHE = &prCmd->u.rChPwrLimtHE[0]; + else + prPwrLimit = &prCmd->u.rChannelPowerLimit[0]; + + + /*Build power limit cmd by default table information */ + + for (i = POWER_LIMIT_2G4; i < POWER_LIMIT_SUBAND_NUM; i++) { + + cLmtBand = prPwrLimitSubBand->aucPwrLimitSubBand[i]; + + if (prPwrLimitSubBand->aucPwrLimitSubBand[i] > MAX_TX_POWER) { + DBGLOG(RLM, WARN, "SubBand[%d] Pwr(%d) > Max (%d)", + prPwrLimitSubBand->aucPwrLimitSubBand[i], + MAX_TX_POWER); + cLmtBand = MAX_TX_POWER; + } + + for (k = g_rRlmSubBand[i].ucStartCh; + k <= g_rRlmSubBand[i].ucEndCh; + k += g_rRlmSubBand[i].ucInterval) { + + if (eType == PWR_LIMIT_TYPE_COMP_11AX) + prPwrLmtHE->ucCentralCh = k; + else + prPwrLimit->ucCentralCh = k; + + if ((prPwrLimitSubBand->ucPwrUnit + & BIT(i)) == 0) { + + if (eType == PWR_LIMIT_TYPE_COMP_11AX) + kalMemSet(&prPwrLmtHE->cPwrLimitRU26L, + cLmtBand, + PWR_LIMIT_HE_NUM); + else + kalMemSet(&prPwrLimit->cPwrLimitCCK, + cLmtBand, + PWR_LIMIT_NUM); + } else { + /* ex: 40MHz power limit(mW\MHz) + * = 20MHz power limit(mW\MHz) * 2 + * ---> 40MHz power limit(dBm) + * = 20MHz power limit(dBm) + 6; + */ + + if (eType == PWR_LIMIT_TYPE_COMP_11AX) { + /* BW20 */ + prPwrLmtHE->cPwrLimitRU26L = cLmtBand; + prPwrLmtHE->cPwrLimitRU26H = cLmtBand; + prPwrLmtHE->cPwrLimitRU26U = cLmtBand; + + prPwrLmtHE->cPwrLimitRU52L = cLmtBand; + prPwrLmtHE->cPwrLimitRU52H = cLmtBand; + prPwrLmtHE->cPwrLimitRU52U = cLmtBand; + + prPwrLmtHE->cPwrLimitRU106L = cLmtBand; + prPwrLmtHE->cPwrLimitRU106H = cLmtBand; + prPwrLmtHE->cPwrLimitRU106U = cLmtBand; + + prPwrLmtHE->cPwrLimitRU242L = cLmtBand; + prPwrLmtHE->cPwrLimitRU242H = cLmtBand; + prPwrLmtHE->cPwrLimitRU242U = cLmtBand; + + } else { + /* BW20 */ + prPwrLimit->cPwrLimitCCK = cLmtBand; +#if (CFG_SUPPORT_DYNA_TX_PWR_CTRL_OFDM_SETTING == 1) + prPwrLimit->cPwrLimitOFDM_L = cLmtBand; + prPwrLimit->cPwrLimitOFDM_H = cLmtBand; +#endif /* CFG_SUPPORT_DYNA_TX_PWR_CTRL_OFDM_SETTING */ + prPwrLimit->cPwrLimit20L = cLmtBand; + prPwrLimit->cPwrLimit20H = cLmtBand; + } + + /* BW40 */ + cLmtBand += 6; + + if (cLmtBand > MAX_TX_POWER) + cLmtBand = MAX_TX_POWER; + + if (eType == PWR_LIMIT_TYPE_COMP_11AX) { + prPwrLmtHE->cPwrLimitRU484L = cLmtBand; + prPwrLmtHE->cPwrLimitRU484H = cLmtBand; + prPwrLmtHE->cPwrLimitRU484U = cLmtBand; + } else { + prPwrLimit->cPwrLimit40L = cLmtBand; + prPwrLimit->cPwrLimit40H = cLmtBand; + } + + /* BW80 */ + cLmtBand += 6; + if (cLmtBand > MAX_TX_POWER) + cLmtBand = MAX_TX_POWER; + + if (eType == PWR_LIMIT_TYPE_COMP_11AX) { + prPwrLmtHE->cPwrLimitRU996L = cLmtBand; + prPwrLmtHE->cPwrLimitRU996H = cLmtBand; + prPwrLmtHE->cPwrLimitRU996U = cLmtBand; + + } else { + prPwrLimit->cPwrLimit80L = cLmtBand; + prPwrLimit->cPwrLimit80H = cLmtBand; + } + + /* BW160 */ + cLmtBand += 6; + if (cLmtBand > MAX_TX_POWER) + cLmtBand = MAX_TX_POWER; + if (eType == PWR_LIMIT_TYPE_COMP_11AX) { + /* prPwrLmtHE do nothing */ + } else { + prPwrLimit->cPwrLimit160L = cLmtBand; + prPwrLimit->cPwrLimit160H = cLmtBand; + } + + } + /* save to power limit array per + * subband channel + */ + if (eType == PWR_LIMIT_TYPE_COMP_11AX) + prPwrLmtHE++; + else + prPwrLimit++; + + prCmd->ucNum++; + + if (prCmd->ucNum >= MAX_CMD_SUPPORT_CHANNEL_NUM) + DBGLOG(RLM, WARN, "out of MAX CH Num\n"); + + } + } + + DBGLOG(RLM, TRACE, "Build Default Limit(%c%c)ChNum=%d,typde=%d\n", + ((prCmd->u2CountryCode & + 0xff00) >> 8), + (prCmd->u2CountryCode & + 0x00ff), + prCmd->ucNum, + eType); + +} + +void rlmDomainCopyFromConfigTable(struct CMD_CHANNEL_POWER_LIMIT *prCmdPwrLimit, + struct COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION *prPwrLimitConfig) +{ + + +#if (CFG_SUPPORT_DYNA_TX_PWR_CTRL_OFDM_SETTING == 1) + /*remapping from old setting to new setting*/ + prCmdPwrLimit->cPwrLimitCCK = + prPwrLimitConfig->aucPwrLimit[PWR_LIMIT_CCK]; + prCmdPwrLimit->cPwrLimitOFDM_L = + prPwrLimitConfig->aucPwrLimit[PWR_LIMIT_OFDM_L]; + prCmdPwrLimit->cPwrLimitOFDM_H = + prPwrLimitConfig->aucPwrLimit[PWR_LIMIT_OFDM_H]; + kalMemCopy(&prCmdPwrLimit->cPwrLimit20L, + &prPwrLimitConfig->aucPwrLimit[PWR_LIMIT_OFDM_L], + PWR_LIMIT_NUM - 5); +#else + kalMemCopy(&prCmdPwrLimit->cPwrLimitCCK, + &prPwrLimitConfig->aucPwrLimit[0], + PWR_LIMIT_NUM); +#endif /* CFG_SUPPORT_DYNA_TX_PWR_CTRL_OFDM_SETTING */ +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Fill power limit CMD by Power Limit Configurartion Table + * (Bandedge and Customization) + * + * @param[in] + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void rlmDomainBuildCmdByConfigTable(struct ADAPTER *prAdapter, + struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT *prCmd) +{ +#define PwrLmtConf g_rRlmPowerLimitConfiguration +#define PwrLmtConfHE g_rRlmPowerLimitConfigurationHE + uint16_t i, k; + uint16_t u2CountryCodeTable = COUNTRY_CODE_NULL; + enum ENUM_PWR_LIMIT_TYPE eType; + struct CMD_CHANNEL_POWER_LIMIT *prCmdPwrLimit; + struct CMD_CHANNEL_POWER_LIMIT_HE *prCmdPwrLimtHE; + u_int8_t fgChannelValid; + uint8_t ucCentCh; + uint8_t ucPwrLmitConfSize = sizeof(PwrLmtConf) / + sizeof(struct COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION); + + uint8_t ucPwrLmitConfSizeHE = sizeof(PwrLmtConfHE) / + sizeof(struct COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION_HE); + + eType = prCmd->ucLimitType; + /*Build power limit cmd by configuration table information */ + + for (k = 0; k < prCmd->ucNum; k++) { + + if (k >= MAX_CMD_SUPPORT_CHANNEL_NUM) { + DBGLOG(RLM, ERROR, "out of MAX CH Num\n"); + return; + } + + if (eType == PWR_LIMIT_TYPE_COMP_11AX) { + prCmdPwrLimtHE = &prCmd->u.rChPwrLimtHE[k]; + ucCentCh = prCmdPwrLimtHE->ucCentralCh; + + for (i = 0; i < ucPwrLmitConfSizeHE ; i++) { + + WLAN_GET_FIELD_BE16( + &PwrLmtConfHE[i].aucCountryCode[0], + &u2CountryCodeTable); + + fgChannelValid = + rlmDomainCheckChannelEntryValid(prAdapter, + PwrLmtConfHE[i].ucCentralCh); + + if (u2CountryCodeTable == COUNTRY_CODE_NULL) + break; /*end of configuration table */ + else if (u2CountryCodeTable + != prCmd->u2CountryCode) + continue; + else if (fgChannelValid == FALSE) + continue; + else if (ucCentCh + != PwrLmtConfHE[i].ucCentralCh) + continue; + + /* Cmd setting (Default table + * information) and Conf table + * has repetition channel entry, + * ex : Default table (ex: 2.4G, + * limit = 20dBm) --> + * ch1~14 limit =20dBm, + * Conf table (ex: ch1, limit = + * 22dBm) --> ch 1 = 22 dBm + * Cmd final setting --> ch1 = + * 22dBm, ch2~14 = 20dBm + */ + kalMemCopy(&prCmdPwrLimtHE->cPwrLimitRU26L, + &PwrLmtConfHE[i].aucPwrLimit, + PWR_LIMIT_HE_NUM); + } + + + } else { + prCmdPwrLimit = &prCmd->u.rChannelPowerLimit[k]; + ucCentCh = prCmdPwrLimit->ucCentralCh; + + for (i = 0; i < ucPwrLmitConfSize ; i++) { + + WLAN_GET_FIELD_BE16( + &PwrLmtConf[i].aucCountryCode[0], + &u2CountryCodeTable); + + fgChannelValid = + rlmDomainCheckChannelEntryValid( + prAdapter, + PwrLmtConf[i].ucCentralCh); + + if (u2CountryCodeTable == COUNTRY_CODE_NULL) + break; /*end of configuration table */ + else if (u2CountryCodeTable + != prCmd->u2CountryCode) + continue; + else if (fgChannelValid == FALSE) + continue; + else if (ucCentCh != PwrLmtConf[i].ucCentralCh) + continue; + + /* Cmd setting (Default table + * information) and Conf table + * has repetition channel entry, + * ex : Default table (ex: 2.4G, + * limit = 20dBm) --> + * ch1~14 limit =20dBm, + * Conf table (ex: ch1, limit = + * 22dBm) --> ch 1 = 22 dBm + * Cmd final setting --> ch1 = + * 22dBm, ch2~14 = 20dBm + */ + rlmDomainCopyFromConfigTable( + prCmdPwrLimit, + &PwrLmtConf[i] + ); + } + } + } +#undef PwrLmtConf +#undef PwrLmtConfHE + +} + +struct TX_PWR_LIMIT_DATA * +rlmDomainInitTxPwrLimitData(struct ADAPTER *prAdapter) +{ + uint8_t ch_cnt = 0; + uint8_t ch_idx = 0; + uint8_t band_idx = 0; + uint8_t ch_num = 0; + const int8_t *prChannelList = NULL; + struct TX_PWR_LIMIT_DATA *pTxPwrLimitData = NULL; + struct CHANNEL_TX_PWR_LIMIT *prChTxPwrLimit = NULL; + + pTxPwrLimitData = + (struct TX_PWR_LIMIT_DATA *) + kalMemAlloc(sizeof(struct TX_PWR_LIMIT_DATA), + VIR_MEM_TYPE); + + if (!pTxPwrLimitData) { + DBGLOG(RLM, ERROR, + "Alloc buffer for TxPwrLimit main struct failed\n"); + return NULL; + } + + pTxPwrLimitData->ucChNum = + TX_PWR_LIMIT_2G_CH_NUM + TX_PWR_LIMIT_5G_CH_NUM; + + pTxPwrLimitData->rChannelTxPwrLimit = + (struct CHANNEL_TX_PWR_LIMIT *) + kalMemAlloc(sizeof(struct CHANNEL_TX_PWR_LIMIT) * + (pTxPwrLimitData->ucChNum), VIR_MEM_TYPE); + + if (!pTxPwrLimitData->rChannelTxPwrLimit) { + DBGLOG(RLM, ERROR, + "Alloc buffer for TxPwrLimit ch values failed\n"); + + kalMemFree(pTxPwrLimitData, VIR_MEM_TYPE, + sizeof(struct TX_PWR_LIMIT_DATA)); + return NULL; + } + + for (ch_idx = 0; ch_idx < pTxPwrLimitData->ucChNum; ch_idx++) { + prChTxPwrLimit = + &(pTxPwrLimitData->rChannelTxPwrLimit[ch_idx]); + kalMemSet(prChTxPwrLimit->rTxPwrLimitValue, + MAX_TX_POWER, + sizeof(prChTxPwrLimit->rTxPwrLimitValue)); + kalMemSet(prChTxPwrLimit->rTxBfBackoff, + MAX_TX_POWER, + sizeof(prChTxPwrLimit->rTxBfBackoff)); + } + + ch_cnt = 0; + for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { + if (band_idx != KAL_BAND_2GHZ && band_idx != KAL_BAND_5GHZ) + continue; + + prChannelList = (band_idx == KAL_BAND_2GHZ) ? + gTx_Pwr_Limit_2g_Ch : gTx_Pwr_Limit_5g_Ch; + + ch_num = + (band_idx == KAL_BAND_2GHZ) ? + TX_PWR_LIMIT_2G_CH_NUM : + TX_PWR_LIMIT_5G_CH_NUM; + + for (ch_idx = 0; ch_idx < ch_num; ch_idx++) { + pTxPwrLimitData->rChannelTxPwrLimit[ch_cnt].ucChannel = + prChannelList[ch_idx]; + ++ch_cnt; + } + } + + return pTxPwrLimitData; +} + +void +rlmDomainSendTxPwrLimitCmd(struct ADAPTER *prAdapter, + uint8_t ucVersion, + struct TX_PWR_LIMIT_DATA *pTxPwrLimitData) +{ + uint8_t ch_cnt = 0; + uint8_t ch_idx = 0; + uint8_t band_idx = 0; + const int8_t *prChannelList = NULL; + uint32_t rStatus; + uint32_t u4SetQueryInfoLen; + uint32_t u4SetCmdTableMaxSize[KAL_NUM_BANDS] = {0}; + struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2 + *prCmd[KAL_NUM_BANDS] = {0}; + struct CMD_CHANNEL_POWER_LIMIT_V2 *prCmdChPwrLimitV2 = NULL; + uint32_t u4SetCountryCmdSize = + sizeof(struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2); + uint32_t u4ChPwrLimitV2Size = sizeof(struct CMD_CHANNEL_POWER_LIMIT_V2); + const uint8_t ucCmdBatchSize = + prAdapter->chip_info->ucTxPwrLimitBatchSize; + + for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { + if (band_idx != KAL_BAND_2GHZ && band_idx != KAL_BAND_5GHZ) + continue; + + prChannelList = (band_idx == KAL_BAND_2GHZ) ? + gTx_Pwr_Limit_2g_Ch : gTx_Pwr_Limit_5g_Ch; + + ch_cnt = (band_idx == KAL_BAND_2GHZ) ? TX_PWR_LIMIT_2G_CH_NUM : + TX_PWR_LIMIT_5G_CH_NUM; + + if (!ch_cnt) + continue; + + u4SetCmdTableMaxSize[band_idx] = u4SetCountryCmdSize + + ch_cnt * u4ChPwrLimitV2Size; + + prCmd[band_idx] = cnmMemAlloc(prAdapter, + RAM_TYPE_BUF, u4SetCmdTableMaxSize[band_idx]); + + if (!prCmd[band_idx]) { + DBGLOG(RLM, ERROR, "Domain: no buf to send cmd\n"); + goto error; + } + + /*initialize tw pwr table*/ + kalMemSet(prCmd[band_idx], MAX_TX_POWER, + u4SetCmdTableMaxSize[band_idx]); + + prCmd[band_idx]->ucNum = ch_cnt; + prCmd[band_idx]->eband = + (band_idx == KAL_BAND_2GHZ) ? + BAND_2G4 : BAND_5G; + prCmd[band_idx]->countryCode = rlmDomainGetCountryCode(); + + DBGLOG(RLM, INFO, + "%s, active n_channels=%d, band=%d\n", + __func__, ch_cnt, prCmd[band_idx]->eband); + + for (ch_idx = 0; ch_idx < ch_cnt; ch_idx++) { + prCmdChPwrLimitV2 = + &(prCmd[band_idx]->rChannelPowerLimit[ch_idx]); + prCmdChPwrLimitV2->ucCentralCh = + prChannelList[ch_idx]; + } + } + + rlmDomainTxPwrLimitSetValues(ucVersion, + prCmd[KAL_BAND_2GHZ], pTxPwrLimitData); + rlmDomainTxPwrLimitSetValues(ucVersion, + prCmd[KAL_BAND_5GHZ], pTxPwrLimitData); + + for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { + uint8_t ucRemainChNum, i, ucTempChNum, prCmdBatchNum; + uint32_t u4BufSize = 0; + struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2 *prTempCmd = NULL; + enum ENUM_BAND eBand = (band_idx == KAL_BAND_2GHZ) ? + BAND_2G4 : BAND_5G; + uint16_t u2ChIdx = 0; + + if (!prCmd[band_idx]) + continue; + + ucRemainChNum = prCmd[band_idx]->ucNum; + prCmdBatchNum = (ucRemainChNum + + ucCmdBatchSize - 1) / + ucCmdBatchSize; + + for (i = 0; i < prCmdBatchNum; i++) { + if (i == prCmdBatchNum - 1) + ucTempChNum = ucRemainChNum; + else + ucTempChNum = ucCmdBatchSize; + + u4BufSize = u4SetCountryCmdSize + + ucTempChNum * u4ChPwrLimitV2Size; + + prTempCmd = + cnmMemAlloc(prAdapter, + RAM_TYPE_BUF, u4BufSize); + + if (!prTempCmd) { + DBGLOG(RLM, ERROR, + "Domain: no buf to send cmd\n"); + goto error; + } + + /*copy partial tx pwr limit*/ + prTempCmd->ucNum = ucTempChNum; + prTempCmd->eband = eBand; + prTempCmd->countryCode = rlmDomainGetCountryCode(); + u2ChIdx = i * ucCmdBatchSize; + kalMemCopy(&prTempCmd->rChannelPowerLimit[0], + &prCmd[band_idx]->rChannelPowerLimit[u2ChIdx], + ucTempChNum * u4ChPwrLimitV2Size); + + u4SetQueryInfoLen = u4BufSize; + /* Update tx max. power info to chip */ + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_COUNTRY_POWER_LIMIT, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + u4SetQueryInfoLen, + (uint8_t *) prTempCmd, + NULL, + 0); + + cnmMemFree(prAdapter, prTempCmd); + + ucRemainChNum -= ucTempChNum; + } + } + +error: + for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { + if (prCmd[band_idx]) + cnmMemFree(prAdapter, prCmd[band_idx]); + } +} + +u_int32_t rlmDomainInitTxPwrLimitPerRateCmd( + struct ADAPTER *prAdapter, + struct wiphy *prWiphy, + struct CMD_SET_TXPOWER_COUNTRY_TX_POWER_LIMIT_PER_RATE *prCmd[]) +{ + uint8_t ch_cnt = 0; + uint8_t ch_idx = 0; + uint8_t band_idx = 0; + const int8_t *prChannelList = NULL; + uint32_t u4SetCmdTableMaxSize[KAL_NUM_BANDS] = {0}; + uint32_t u4SetCountryTxPwrLimitCmdSize = + sizeof(struct CMD_SET_TXPOWER_COUNTRY_TX_POWER_LIMIT_PER_RATE); + uint32_t u4ChPwrLimitSize = + sizeof(struct CMD_TXPOWER_CHANNEL_POWER_LIMIT_PER_RATE); + struct CMD_TXPOWER_CHANNEL_POWER_LIMIT_PER_RATE *prChPwrLimit = NULL; + + for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { + if (band_idx != KAL_BAND_2GHZ && band_idx != KAL_BAND_5GHZ) + continue; + + prChannelList = (band_idx == KAL_BAND_2GHZ) ? + gTx_Pwr_Limit_2g_Ch : gTx_Pwr_Limit_5g_Ch; + + ch_cnt = (band_idx == KAL_BAND_2GHZ) ? TX_PWR_LIMIT_2G_CH_NUM : + TX_PWR_LIMIT_5G_CH_NUM; + + if (!ch_cnt) + continue; + + u4SetCmdTableMaxSize[band_idx] = u4SetCountryTxPwrLimitCmdSize + + ch_cnt * u4ChPwrLimitSize; + + prCmd[band_idx] = cnmMemAlloc(prAdapter, + RAM_TYPE_BUF, u4SetCmdTableMaxSize[band_idx]); + + if (!prCmd[band_idx]) { + DBGLOG(RLM, ERROR, "Domain: no buf to send cmd\n"); + return WLAN_STATUS_RESOURCES; + } + + /*initialize tx pwr table*/ + kalMemSet(prCmd[band_idx]->rChannelPowerLimit, MAX_TX_POWER, + ch_cnt * u4ChPwrLimitSize); + + prCmd[band_idx]->ucNum = ch_cnt; + prCmd[band_idx]->eBand = + (band_idx == KAL_BAND_2GHZ) ? + BAND_2G4 : BAND_5G; + prCmd[band_idx]->u4CountryCode = rlmDomainGetCountryCode(); + + DBGLOG(RLM, INFO, + "%s, active n_channels=%d, band=%d\n", + __func__, ch_cnt, prCmd[band_idx]->eBand); + + for (ch_idx = 0; ch_idx < ch_cnt; ch_idx++) { + prChPwrLimit = + &(prCmd[band_idx]-> + rChannelPowerLimit[ch_idx]); + prChPwrLimit->u1CentralCh = prChannelList[ch_idx]; + } + + } + + return WLAN_STATUS_SUCCESS; +} + +void rlmDomainTxPwrLimitSendPerRateCmd( + struct ADAPTER *prAdapter, + struct CMD_SET_TXPOWER_COUNTRY_TX_POWER_LIMIT_PER_RATE *prCmd[] +) +{ + uint32_t rStatus; + uint32_t u4SetQueryInfoLen; + uint8_t band_idx = 0; + uint32_t u4SetCountryTxPwrLimitCmdSize = + sizeof(struct CMD_SET_TXPOWER_COUNTRY_TX_POWER_LIMIT_PER_RATE); + uint32_t u4ChPwrLimitSize = + sizeof(struct CMD_TXPOWER_CHANNEL_POWER_LIMIT_PER_RATE); + const uint8_t ucCmdBatchSize = + prAdapter->chip_info->ucTxPwrLimitBatchSize; + + for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { + uint8_t ucRemainChNum, i, ucTempChNum, prCmdBatchNum; + uint32_t u4BufSize = 0; + struct CMD_SET_TXPOWER_COUNTRY_TX_POWER_LIMIT_PER_RATE + *prTempCmd = NULL; + enum ENUM_BAND eBand = (band_idx == KAL_BAND_2GHZ) ? + BAND_2G4 : BAND_5G; + uint16_t u2ChIdx = 0; + u_int8_t bCmdFinished = FALSE; + + if (!prCmd[band_idx]) + continue; + + ucRemainChNum = prCmd[band_idx]->ucNum; + prCmdBatchNum = (ucRemainChNum + + ucCmdBatchSize - 1) / + ucCmdBatchSize; + + for (i = 0; i < prCmdBatchNum; i++) { + if (i == prCmdBatchNum - 1) { + ucTempChNum = ucRemainChNum; + bCmdFinished = TRUE; + } else { + ucTempChNum = ucCmdBatchSize; + } + + u4BufSize = u4SetCountryTxPwrLimitCmdSize + + ucTempChNum * u4ChPwrLimitSize; + + prTempCmd = + cnmMemAlloc(prAdapter, + RAM_TYPE_BUF, u4BufSize); + + if (!prTempCmd) { + DBGLOG(RLM, ERROR, + "Domain: no buf to send cmd\n"); + return; + } + + /*copy partial tx pwr limit*/ + prTempCmd->ucNum = ucTempChNum; + prTempCmd->eBand = eBand; + prTempCmd->u4CountryCode = + rlmDomainGetCountryCode(); + prTempCmd->bCmdFinished = bCmdFinished; + u2ChIdx = i * ucCmdBatchSize; + kalMemCopy( + &prTempCmd->rChannelPowerLimit[0], + &prCmd[band_idx]-> + rChannelPowerLimit[u2ChIdx], + ucTempChNum * u4ChPwrLimitSize); + + u4SetQueryInfoLen = u4BufSize; + /* Update tx max. power info to chip */ + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_COUNTRY_POWER_LIMIT_PER_RATE, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + u4SetQueryInfoLen, + (uint8_t *) prTempCmd, + NULL, + 0); + + cnmMemFree(prAdapter, prTempCmd); + + ucRemainChNum -= ucTempChNum; + } + } +} + +u_int32_t rlmDomainInitTxBfBackoffCmd( + struct ADAPTER *prAdapter, + struct wiphy *prWiphy, + struct CMD_TXPWR_TXBF_SET_BACKOFF **prCmd +) +{ + uint8_t ucChNum = TX_PWR_LIMIT_2G_CH_NUM + TX_PWR_LIMIT_5G_CH_NUM; + uint8_t ucChIdx = 0; + uint8_t ucChCnt = 0; + uint8_t ucBandIdx = 0; + uint8_t ucAisIdx = 0; + uint8_t ucCnt = 0; + const int8_t *prChannelList = NULL; + uint32_t u4SetCmdSize = sizeof(struct CMD_TXPWR_TXBF_SET_BACKOFF); + struct CMD_TXPWR_TXBF_CHANNEL_BACKOFF *prChTxBfBackoff = NULL; + + if (ucChNum >= CMD_POWER_LIMIT_TABLE_SUPPORT_CHANNEL_NUM) { + DBGLOG(RLM, ERROR, "ChNum %d should <= %d\n", + ucChNum, CMD_POWER_LIMIT_TABLE_SUPPORT_CHANNEL_NUM); + return WLAN_STATUS_FAILURE; + } + + *prCmd = cnmMemAlloc(prAdapter, + RAM_TYPE_BUF, u4SetCmdSize); + + if (!*prCmd) { + DBGLOG(RLM, ERROR, "Domain: no buf to send cmd\n"); + return WLAN_STATUS_RESOURCES; + } + + /*initialize backoff table*/ + kalMemSet((*prCmd)->rChannelTxBfBackoff, MAX_TX_POWER, + sizeof((*prCmd)->rChannelTxBfBackoff)); + + (*prCmd)->ucNum = ucChNum; + (*prCmd)->ucBssIdx = prAdapter->prAisBssInfo[ucAisIdx]->ucBssIndex; + + for (ucBandIdx = 0; ucBandIdx < KAL_NUM_BANDS; ucBandIdx++) { + if (ucBandIdx != KAL_BAND_2GHZ && ucBandIdx != KAL_BAND_5GHZ) + continue; + + prChannelList = (ucBandIdx == KAL_BAND_2GHZ) ? + gTx_Pwr_Limit_2g_Ch : gTx_Pwr_Limit_5g_Ch; + ucChCnt = (ucBandIdx == KAL_BAND_2GHZ) ? + TX_PWR_LIMIT_2G_CH_NUM : TX_PWR_LIMIT_5G_CH_NUM; + + for (ucChIdx = 0; ucChIdx < ucChCnt; ucChIdx++) { + prChTxBfBackoff = + &((*prCmd)->rChannelTxBfBackoff[ucCnt++]); + prChTxBfBackoff->ucCentralCh = prChannelList[ucChIdx]; + } + } + + return WLAN_STATUS_SUCCESS; +} + +void rlmDomainTxPwrTxBfBackoffSetValues( + uint8_t ucVersion, + struct CMD_TXPWR_TXBF_SET_BACKOFF *prTxBfBackoffCmd, + struct TX_PWR_LIMIT_DATA *pTxPwrLimitData) +{ + uint8_t ucIdx = 0; + int8_t cChIdx = 0; + struct CMD_TXPWR_TXBF_CHANNEL_BACKOFF *pChTxBfBackoff = NULL; + struct CHANNEL_TX_PWR_LIMIT *pChTxPwrLimit = NULL; + + if (prTxBfBackoffCmd == NULL || + pTxPwrLimitData == NULL) + return; + + for (ucIdx = 0; ucIdx < prTxBfBackoffCmd->ucNum; ucIdx++) { + pChTxBfBackoff = + &(prTxBfBackoffCmd->rChannelTxBfBackoff[ucIdx]); + cChIdx = rlmDomainTxPwrLimitGetChIdx(pTxPwrLimitData, + pChTxBfBackoff->ucCentralCh); + + if (cChIdx == -1) { + DBGLOG(RLM, ERROR, + "Invalid ch idx found while assigning values\n"); + return; + } + pChTxPwrLimit = &pTxPwrLimitData->rChannelTxPwrLimit[cChIdx]; + + kalMemCopy(&pChTxBfBackoff->acTxBfBackoff, + pChTxPwrLimit->rTxBfBackoff, + sizeof(pChTxBfBackoff->acTxBfBackoff)); + } + + for (ucIdx = 0; ucIdx < prTxBfBackoffCmd->ucNum; ucIdx++) { + pChTxBfBackoff = + &(prTxBfBackoffCmd->rChannelTxBfBackoff[ucIdx]); + + DBGLOG(RLM, ERROR, + "ch %d TxBf backoff 2to1 %d\n", + pChTxBfBackoff->ucCentralCh, + pChTxBfBackoff->acTxBfBackoff[0]); + + } + +} + +void rlmDomainTxPwrSendTxBfBackoffCmd( + struct ADAPTER *prAdapter, + struct CMD_TXPWR_TXBF_SET_BACKOFF *prCmd) +{ + uint32_t rStatus; + uint32_t u4SetQueryInfoLen; + uint32_t u4SetCmdSize = sizeof(struct CMD_TXPWR_TXBF_SET_BACKOFF); + + u4SetQueryInfoLen = u4SetCmdSize; + /* Update tx max. power info to chip */ + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_TXBF_BACKOFF, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + u4SetQueryInfoLen, + (uint8_t *) prCmd, + NULL, + 0); + +} + +void +rlmDomainSendTxPwrLimitPerRateCmd(struct ADAPTER *prAdapter, + uint8_t ucVersion, + struct TX_PWR_LIMIT_DATA *pTxPwrLimitData) +{ + struct wiphy *wiphy; + uint8_t band_idx = 0; + struct CMD_SET_TXPOWER_COUNTRY_TX_POWER_LIMIT_PER_RATE + *prTxPwrLimitPerRateCmd[KAL_NUM_BANDS] = {0}; + + wiphy = priv_to_wiphy(prAdapter->prGlueInfo); + if (rlmDomainInitTxPwrLimitPerRateCmd( + prAdapter, wiphy, prTxPwrLimitPerRateCmd) != + WLAN_STATUS_SUCCESS) + goto error; + + rlmDomainTxPwrLimitPerRateSetValues(ucVersion, + prTxPwrLimitPerRateCmd[KAL_BAND_2GHZ], pTxPwrLimitData); + rlmDomainTxPwrLimitPerRateSetValues(ucVersion, + prTxPwrLimitPerRateCmd[KAL_BAND_5GHZ], pTxPwrLimitData); + rlmDomainTxPwrLimitSendPerRateCmd(prAdapter, prTxPwrLimitPerRateCmd); + +error: + for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) + if (prTxPwrLimitPerRateCmd[band_idx]) + cnmMemFree(prAdapter, prTxPwrLimitPerRateCmd[band_idx]); +} + +void +rlmDomainSendTxBfBackoffCmd(struct ADAPTER *prAdapter, + uint8_t ucVersion, + struct TX_PWR_LIMIT_DATA *pTxPwrLimitData) +{ + struct wiphy *wiphy; + struct CMD_TXPWR_TXBF_SET_BACKOFF + *prTxBfBackoffCmd = NULL; + + wiphy = priv_to_wiphy(prAdapter->prGlueInfo); + + if (rlmDomainInitTxBfBackoffCmd( + prAdapter, wiphy, &prTxBfBackoffCmd) != + WLAN_STATUS_SUCCESS) + goto error; + + rlmDomainTxPwrTxBfBackoffSetValues( + ucVersion, prTxBfBackoffCmd, pTxPwrLimitData); + rlmDomainTxPwrSendTxBfBackoffCmd(prAdapter, prTxBfBackoffCmd); + +error: + + if (prTxBfBackoffCmd) + cnmMemFree(prAdapter, prTxBfBackoffCmd); +} + +void rlmDomainSendPwrLimitCmd_V2(struct ADAPTER *prAdapter) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + uint8_t ucVersion = 0; + struct TX_PWR_LIMIT_DATA *pTxPwrLimitData = NULL; + + DBGLOG(RLM, INFO, "rlmDomainSendPwrLimitCmd()\n"); + pTxPwrLimitData = rlmDomainInitTxPwrLimitData(prAdapter); + + if (!pTxPwrLimitData) { + DBGLOG(RLM, ERROR, + "Init TxPwrLimitData failed\n"); + goto error; + } + + /* + * Get Max Tx Power from MT_TxPwrLimit.dat + */ + rlmDomainGetTxPwrLimit(rlmDomainGetCountryCode(), + &ucVersion, + prAdapter->prGlueInfo, + pTxPwrLimitData); + + /* Prepare to send CMD to FW */ + if (ucVersion == 0) { + rlmDomainSendTxPwrLimitCmd(prAdapter, + ucVersion, pTxPwrLimitData); + } else if (ucVersion == 1) { + rlmDomainSendTxPwrLimitPerRateCmd(prAdapter, + ucVersion, pTxPwrLimitData); + + if (g_bTxBfBackoffExists) + rlmDomainSendTxBfBackoffCmd(prAdapter, + ucVersion, pTxPwrLimitData); + + } else { + DBGLOG(RLM, WARN, "Unsupported TxPwrLimit dat version %u\n", + ucVersion); + } + +error: + if (pTxPwrLimitData && pTxPwrLimitData->rChannelTxPwrLimit) + kalMemFree(pTxPwrLimitData->rChannelTxPwrLimit, VIR_MEM_TYPE, + sizeof(struct CHANNEL_TX_PWR_LIMIT) * + pTxPwrLimitData->ucChNum); + + if (pTxPwrLimitData) + kalMemFree(pTxPwrLimitData, VIR_MEM_TYPE, + sizeof(struct TX_PWR_LIMIT_DATA)); +#endif +} + +#if CFG_SUPPORT_DYNAMIC_PWR_LIMIT +/* dynamic tx power control: begin ********************************************/ +uint32_t txPwrParseNumber(char **pcContent, char *delim, uint8_t *op, + int8_t *value) { + u_int8_t fgIsNegtive = FALSE; + char *pcTmp = NULL; + char *result = NULL; + + if ((!pcContent) || (*pcContent == NULL)) + return -1; + + if (**pcContent == '-') { + fgIsNegtive = TRUE; + *pcContent = *pcContent + 1; + } + pcTmp = *pcContent; + + result = kalStrSep(pcContent, delim); + if (result == NULL) { + return -1; + } else if ((result != NULL) && (kalStrLen(result) == 0)) { + if (fgIsNegtive) + return -1; + *value = 0; + *op = 0; + } else { + if (kalkStrtou8(pcTmp, 0, value) != 0) { + DBGLOG(RLM, ERROR, + "parse number error: invalid number [%s]\n", + pcTmp); + return -1; + } + if (fgIsNegtive) + *op = 2; + else + *op = 1; + } + + return 0; +} + +void txPwrOperate(enum ENUM_TX_POWER_CTRL_TYPE eCtrlType, + int8_t *operand1, int8_t *operand2) +{ + switch (eCtrlType) { + case PWR_CTRL_TYPE_WIFION_POWER_LEVEL: + case PWR_CTRL_TYPE_IOCTL_POWER_LEVEL: + if (*operand1 > *operand2) + *operand1 = *operand2; + break; + case PWR_CTRL_TYPE_WIFION_POWER_OFFSET: + case PWR_CTRL_TYPE_IOCTL_POWER_OFFSET: + *operand1 += *operand2; + break; + default: + break; + } + + if (*operand1 > MAX_TX_POWER) + *operand1 = MAX_TX_POWER; + else if (*operand1 < MIN_TX_POWER) + *operand1 = MIN_TX_POWER; +} + +uint32_t txPwrArbitrator(enum ENUM_TX_POWER_CTRL_TYPE eCtrlType, + void *pvBuf, + struct TX_PWR_CTRL_CHANNEL_SETTING *prChlSetting, + enum ENUM_PWR_LIMIT_TYPE eType) +{ + struct CMD_CHANNEL_POWER_LIMIT *prPwrLimit; + struct CMD_CHANNEL_POWER_LIMIT_HE *prPwrLimitHE; + uint8_t rateIdx; + int8_t *prRateOfs; + + + + if (eType == PWR_LIMIT_TYPE_COMP_11AX) { + prPwrLimitHE = (struct CMD_CHANNEL_POWER_LIMIT_HE *) pvBuf; + prRateOfs = &prPwrLimitHE->cPwrLimitRU26L; + + for (rateIdx = PWR_LIMIT_RU26_L; + rateIdx < PWR_LIMIT_HE_NUM ; rateIdx++) { + if (prChlSetting->opHE[rateIdx] + != PWR_CTRL_TYPE_NO_ACTION) { + txPwrOperate(eCtrlType, prRateOfs + rateIdx, + &prChlSetting->i8PwrLimitHE[rateIdx]); + } + } + + } else { + prPwrLimit = (struct CMD_CHANNEL_POWER_LIMIT *) pvBuf; + prRateOfs = &prPwrLimit->cPwrLimitCCK; + + for (rateIdx = PWR_LIMIT_CCK; + rateIdx < PWR_LIMIT_NUM ; rateIdx++) { + if (prChlSetting->op[rateIdx] + != PWR_CTRL_TYPE_NO_ACTION) { + txPwrOperate(eCtrlType, prRateOfs + rateIdx, + &prChlSetting->i8PwrLimit[rateIdx]); + } + } + + } + + return 0; +} + +uint32_t txPwrApplyOneSetting(struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT *prCmd, + struct TX_PWR_CTRL_ELEMENT *prCurElement, + uint8_t *bandedgeParam) +{ + struct CMD_CHANNEL_POWER_LIMIT *prCmdPwrLimit = NULL; + struct CMD_CHANNEL_POWER_LIMIT_HE *prCmdPwrLimitHE = NULL; + struct TX_PWR_CTRL_CHANNEL_SETTING *prChlSetting = NULL; + uint8_t i, j, channel, channel2, channel3; + u_int8_t fgDoArbitrator; + enum ENUM_PWR_LIMIT_TYPE eType; + + ASSERT(prCmd); + eType = prCmd->ucLimitType; + + for (i = 0; i < prCmd->ucNum; i++) { + + if (eType == PWR_LIMIT_TYPE_COMP_11AX) { + prCmdPwrLimitHE = &prCmd->u.rChPwrLimtHE[i]; + channel = prCmdPwrLimitHE->ucCentralCh; + + } else { + prCmdPwrLimit = &prCmd->u.rChannelPowerLimit[i]; + channel = prCmdPwrLimit->ucCentralCh; + } + + + + for (j = 0; j < prCurElement->settingCount; j++) { + prChlSetting = &prCurElement->rChlSettingList[j]; + channel2 = prChlSetting->channelParam[0]; + channel3 = prChlSetting->channelParam[1]; + fgDoArbitrator = FALSE; + switch (prChlSetting->eChnlType) { + case PWR_CTRL_CHNL_TYPE_NORMAL: { + if (channel == channel2) + fgDoArbitrator = TRUE; + break; + } + case PWR_CTRL_CHNL_TYPE_ALL: { + fgDoArbitrator = TRUE; + break; + } + case PWR_CTRL_CHNL_TYPE_RANGE: { + if ((channel >= channel2) && + (channel <= channel3)) + fgDoArbitrator = TRUE; + break; + } + case PWR_CTRL_CHNL_TYPE_2G4: { + if (channel <= 14) + fgDoArbitrator = TRUE; + break; + } + case PWR_CTRL_CHNL_TYPE_5G: { + if (channel > 14) + fgDoArbitrator = TRUE; + break; + } + case PWR_CTRL_CHNL_TYPE_BANDEDGE_2G4: { + if ((channel == *bandedgeParam) || + (channel == *(bandedgeParam + 1))) + fgDoArbitrator = TRUE; + break; + } + case PWR_CTRL_CHNL_TYPE_BANDEDGE_5G: { + if ((channel == *(bandedgeParam + 2)) || + (channel == *(bandedgeParam + 3))) + fgDoArbitrator = TRUE; + break; + } + case PWR_CTRL_CHNL_TYPE_5G_BAND1: { + if ((channel >= 30) && (channel <= 50)) + fgDoArbitrator = TRUE; + break; + } + case PWR_CTRL_CHNL_TYPE_5G_BAND2: { + if ((channel >= 51) && (channel <= 70)) + fgDoArbitrator = TRUE; + break; + } + case PWR_CTRL_CHNL_TYPE_5G_BAND3: { + if ((channel >= 71) && (channel <= 145)) + fgDoArbitrator = TRUE; + break; + } + case PWR_CTRL_CHNL_TYPE_5G_BAND4: { + if ((channel >= 146) && + (channel <= 170)) + fgDoArbitrator = TRUE; + break; + } + } + + if (fgDoArbitrator) { + if (eType == PWR_LIMIT_TYPE_COMP_11AX) + txPwrArbitrator(prCurElement->eCtrlType, + prCmdPwrLimitHE, + prChlSetting, + eType); + else + txPwrArbitrator(prCurElement->eCtrlType, + prCmdPwrLimit, + prChlSetting, + eType); + } + } + + } + + return 0; +} + +uint32_t txPwrCtrlApplySettings(struct ADAPTER *prAdapter, + struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT *prCmd, + uint8_t *bandedgeParam) +{ + struct LINK_ENTRY *prCur, *prNext; + struct TX_PWR_CTRL_ELEMENT *element = NULL; + struct LINK *aryprlist[2] = { + &prAdapter->rTxPwr_DefaultList, + &prAdapter->rTxPwr_DynamicList + }; + int32_t i; + + /* show the tx power ctrl applied list */ + txPwrCtrlShowList(prAdapter, 1, "applied list"); + + for (i = 0; i < ARRAY_SIZE(aryprlist); i++) { + LINK_FOR_EACH_SAFE(prCur, prNext, aryprlist[i]) { + element = LINK_ENTRY(prCur, + struct TX_PWR_CTRL_ELEMENT, node); + if (element->fgApplied == TRUE) + txPwrApplyOneSetting( + prCmd, element, bandedgeParam); + } + } + + return 0; +} + +char *txPwrGetString(char **pcContent, char *delim) +{ + char *result = NULL; + + if (pcContent == NULL) + return NULL; + + result = kalStrSep(pcContent, delim); + if ((pcContent == NULL) || (result == NULL) || + ((result != NULL) && (kalStrLen(result) == 0))) + return NULL; + + return result; +} + +struct TX_PWR_CTRL_ELEMENT *txPwrCtrlStringToStruct(char *pcContent, + u_int8_t fgSkipHeader) +{ + struct TX_PWR_CTRL_ELEMENT *prCurElement = NULL; + struct TX_PWR_CTRL_CHANNEL_SETTING *prTmpSetting; + char acTmpName[MAX_TX_PWR_CTRL_ELEMENT_NAME_SIZE]; + char *pcContCur = NULL, *pcContCur2 = NULL, *pcContEnd = NULL; + char *pcContTmp = NULL, *pcContNext = NULL, *pcContOld = NULL; + uint32_t u4MemSize = sizeof(struct TX_PWR_CTRL_ELEMENT); + uint32_t copySize = 0; + uint8_t i, j, op, ucSettingCount = 0; + uint8_t value, value2, count = 0; + uint8_t ucAppliedWay, ucOperation = 0; + char carySeperator[2] = { 0, 0 }; + + char *pacParsePwrAC[PWR_CFG_PRAM_NUM_AC] = { + "CCK", +#if (CFG_SUPPORT_DYNA_TX_PWR_CTRL_OFDM_SETTING == 1) + "OFDML", + "OFDMH", +#endif + "HT20L", + "HT20H", + "HT40L", + "HT40H", + "HT80L", + "HT80H", + "HT160L", + "HT160H" + }; + char *pacParsePwrAX[PWR_CFG_PRAM_NUM_AX] = { + "RU26L", + "RU26H", + "RU26U", + "RU52L", + "RU52H", + "RU52U", + "RU106L", + "RU106H", + "RU106U", + "RU242L", + "RU242H", + "RU242U", + "RU484L", + "RU484H", + "RU484U", + "RU996L", + "RU996H", + "RU996U" + }; + + if (!pcContent) { + DBGLOG(RLM, ERROR, "pcContent is null\n"); + return NULL; + } + + pcContCur = pcContent; + pcContEnd = pcContent + kalStrLen(pcContent); + + if (fgSkipHeader == TRUE) + goto skipLabel; + + /* insert elenemt into prTxPwrCtrlList */ + /* parse scenario name */ + kalMemZero(acTmpName, MAX_TX_PWR_CTRL_ELEMENT_NAME_SIZE); + pcContOld = pcContCur; + pcContTmp = txPwrGetString(&pcContCur, ";"); + if (!pcContTmp) { + DBGLOG(RLM, ERROR, "parse scenario name error: %s\n", + pcContOld); + return NULL; + } + copySize = kalStrLen(pcContTmp); + if (copySize >= MAX_TX_PWR_CTRL_ELEMENT_NAME_SIZE) + copySize = MAX_TX_PWR_CTRL_ELEMENT_NAME_SIZE - 1; + kalMemCopy(acTmpName, pcContTmp, copySize); + acTmpName[copySize] = 0; + + /* parese scenario sub index */ + pcContOld = pcContCur; + if (txPwrParseNumber(&pcContCur, ";", &op, &value)) { + DBGLOG(RLM, ERROR, "parse scenario sub index error: %s\n", + pcContOld); + return NULL; + } + if ((op != 1) || (value < 0)) { + DBGLOG(RLM, ERROR, + "parse scenario sub index error: op=%u, val=%d\n", + op, value); + return NULL; + } + + /* parese scenario applied way */ + pcContOld = pcContCur; + if (txPwrParseNumber(&pcContCur, ";", &op, &ucAppliedWay)) { + DBGLOG(RLM, ERROR, "parse applied way error: %s\n", + pcContOld); + return NULL; + } + if ((ucAppliedWay < PWR_CTRL_TYPE_APPLIED_WAY_WIFION) || + (ucAppliedWay > PWR_CTRL_TYPE_APPLIED_WAY_IOCTL)) { + DBGLOG(RLM, ERROR, + "parse applied way error: value=%u\n", + ucAppliedWay); + return NULL; + } + + /* parese scenario applied type */ + pcContOld = pcContCur; + if (txPwrParseNumber(&pcContCur, ";", &op, &ucOperation)) { + DBGLOG(RLM, ERROR, "parse operation error: %s\n", + pcContOld); + return NULL; + } + if ((ucOperation < PWR_CTRL_TYPE_OPERATION_POWER_LEVEL) || + (ucOperation > PWR_CTRL_TYPE_OPERATION_POWER_OFFSET)) { + DBGLOG(RLM, ERROR, + "parse operation error: value=%u\n", + ucOperation); + return NULL; + } + + switch (ucAppliedWay) { + case PWR_CTRL_TYPE_APPLIED_WAY_WIFION: + if (ucOperation == PWR_CTRL_TYPE_OPERATION_POWER_LEVEL) + value2 = PWR_CTRL_TYPE_WIFION_POWER_LEVEL; + else + value2 = PWR_CTRL_TYPE_WIFION_POWER_OFFSET; + break; + case PWR_CTRL_TYPE_APPLIED_WAY_IOCTL: + if (ucOperation == PWR_CTRL_TYPE_OPERATION_POWER_LEVEL) + value2 = PWR_CTRL_TYPE_IOCTL_POWER_LEVEL; + else + value2 = PWR_CTRL_TYPE_IOCTL_POWER_OFFSET; + break; + } + +skipLabel: + /* decide how many channel setting */ + pcContOld = pcContCur; + while (pcContCur <= pcContEnd) { + if ((*pcContCur) == '[') + ucSettingCount++; + pcContCur++; + } + + if (ucSettingCount == 0) { + DBGLOG(RLM, ERROR, + "power ctrl channel setting is empty\n"); + return NULL; + } + + /* allocate memory for control element */ + u4MemSize += (ucSettingCount == 1) ? 0 : (ucSettingCount - 1) * + sizeof(struct TX_PWR_CTRL_CHANNEL_SETTING); + prCurElement = (struct TX_PWR_CTRL_ELEMENT *)kalMemAlloc( + u4MemSize, VIR_MEM_TYPE); + if (!prCurElement) { + DBGLOG(RLM, ERROR, + "alloc power ctrl element failed\n"); + return NULL; + } + + /* assign values into control element */ + kalMemZero(prCurElement, u4MemSize); + if (fgSkipHeader == FALSE) { + kalMemCopy(prCurElement->name, acTmpName, copySize); + prCurElement->index = (uint8_t)value; + prCurElement->eCtrlType = (enum ENUM_TX_POWER_CTRL_TYPE)value2; + if (prCurElement->eCtrlType <= + PWR_CTRL_TYPE_WIFION_POWER_OFFSET) + prCurElement->fgApplied = TRUE; + } + prCurElement->settingCount = ucSettingCount; + + /* parse channel setting list */ + pcContCur = pcContOld + 1; /* skip '[' */ + + for (i = 0; i < ucSettingCount; i++) { + if (pcContCur >= pcContEnd) { + DBGLOG(RLM, ERROR, + "parse error: out of bound\n"); + goto clearLabel; + } + + prTmpSetting = &prCurElement->rChlSettingList[i]; + + /* verify there is ] symbol */ + pcContNext = kalStrChr(pcContCur, ']'); + if (!pcContNext) { + DBGLOG(RLM, ERROR, + "parse error: miss symbol ']', %s\n", + pcContCur); + goto clearLabel; + } + + /* verify this setting has 9 segment */ + pcContTmp = pcContCur; + count = 0; + while (pcContTmp < pcContNext) { + if (*pcContTmp == ',') + count++; + pcContTmp++; + } + + if ((count != PWR_CFG_PRAM_NUM_AC) && + (count != PWR_CFG_PRAM_NUM_AX) && + (count != PWR_CFG_PRAM_NUM_ALL_RATE)) { + DBGLOG(RLM, ERROR, + "parse error: not segments, %s\n", + pcContCur); + goto clearLabel; + } + + /* parse channel setting type */ + pcContOld = pcContCur; + pcContTmp = txPwrGetString(&pcContCur, ","); + if (!pcContTmp) { + DBGLOG(RLM, ERROR, + "parse channel setting type error, %s\n", + pcContOld); + goto clearLabel; + /* "ALL" */ + } else if (kalStrCmp(pcContTmp, + PWR_CTRL_CHNL_TYPE_KEY_ALL) == 0) + prTmpSetting->eChnlType = + PWR_CTRL_CHNL_TYPE_ALL; + /* "2G4" */ + else if (kalStrCmp(pcContTmp, + PWR_CTRL_CHNL_TYPE_KEY_2G4) == 0) + prTmpSetting->eChnlType = + PWR_CTRL_CHNL_TYPE_2G4; + /* "5G" */ + else if (kalStrCmp(pcContTmp, + PWR_CTRL_CHNL_TYPE_KEY_5G) == 0) + prTmpSetting->eChnlType = + PWR_CTRL_CHNL_TYPE_5G; + /* "BANDEDGE2G4" */ + else if (kalStrCmp(pcContTmp, + PWR_CTRL_CHNL_TYPE_KEY_BANDEDGE_2G4) == 0) + prTmpSetting->eChnlType = + PWR_CTRL_CHNL_TYPE_BANDEDGE_2G4; + /* "BANDEDGE5G" */ + else if (kalStrCmp(pcContTmp, + PWR_CTRL_CHNL_TYPE_KEY_BANDEDGE_5G) == 0) + prTmpSetting->eChnlType = + PWR_CTRL_CHNL_TYPE_BANDEDGE_5G; + /* "5GBAND1" */ + else if (kalStrCmp(pcContTmp, + PWR_CTRL_CHNL_TYPE_KEY_5G_BAND1) == 0) + prTmpSetting->eChnlType = + PWR_CTRL_CHNL_TYPE_5G_BAND1; + /* "5GBAND2" */ + else if (kalStrCmp(pcContTmp, + PWR_CTRL_CHNL_TYPE_KEY_5G_BAND2) == 0) + prTmpSetting->eChnlType = + PWR_CTRL_CHNL_TYPE_5G_BAND2; + /* "5GBAND3" */ + else if (kalStrCmp(pcContTmp, + PWR_CTRL_CHNL_TYPE_KEY_5G_BAND3) == 0) + prTmpSetting->eChnlType = + PWR_CTRL_CHNL_TYPE_5G_BAND3; + /* "5GBAND4" */ + else if (kalStrCmp(pcContTmp, + PWR_CTRL_CHNL_TYPE_KEY_5G_BAND4) == 0) + prTmpSetting->eChnlType = + PWR_CTRL_CHNL_TYPE_5G_BAND4; + else { + pcContCur2 = pcContOld; + pcContTmp = txPwrGetString(&pcContCur2, "-"); + if (!pcContTmp) { + DBGLOG(RLM, ERROR, + "parse channel range error: %s\n"); + goto clearLabel; + } + if (pcContCur2 == NULL) { /* case: normal channel */ + if (kalkStrtou8(pcContOld, 0, &value) != 0) { + DBGLOG(RLM, ERROR, + "parse channel error: %s\n", + pcContOld); + goto clearLabel; + } + prTmpSetting->channelParam[0] = value; + prTmpSetting->eChnlType = + PWR_CTRL_CHNL_TYPE_NORMAL; + } else { /* case: channel range */ + if (kalkStrtou8(pcContTmp, 0, &value) != 0) { + DBGLOG(RLM, ERROR, + "parse first channel error, %s\n", + pcContTmp); + goto clearLabel; + } + if (kalkStrtou8(pcContCur2, 0, &value2) != 0) { + DBGLOG(RLM, ERROR, + "parse second channel error, %s\n", + pcContCur2); + goto clearLabel; + } + prTmpSetting->channelParam[0] = value; + prTmpSetting->channelParam[1] = value2; + prTmpSetting->eChnlType = + PWR_CTRL_CHNL_TYPE_RANGE; + } + } + + if (count == PWR_CFG_PRAM_NUM_ALL_RATE) { + /* parse all rate setting */ + pcContOld = pcContCur; + if (txPwrParseNumber(&pcContCur, "]", &op, &value)) { + DBGLOG(RLM, ERROR, "parse CCK error, %s\n", + pcContOld); + goto clearLabel; + } + + for (j = 0; j < PWR_CFG_PRAM_NUM_AC; j++) { + prTmpSetting->op[j] = op; + prTmpSetting->i8PwrLimit[j] = (op != 2) ? + value : (0 - value); + } + + for (j = 0; j < PWR_CFG_PRAM_NUM_AX; j++) { + prTmpSetting->opHE[j] = op; + prTmpSetting->i8PwrLimitHE[j] = (op != 2) ? + value : (0 - value); + } + goto skipLabel2; + } else if (count == PWR_CFG_PRAM_NUM_AC) { + for (j = 0; j < PWR_CFG_PRAM_NUM_AC; j++) { + /* parse cck/20L/20H .. 160L/160H setting */ + if (j == PWR_CFG_PRAM_NUM_AC - 1) + carySeperator[0] = ']'; + else + carySeperator[0] = ','; + + pcContOld = pcContCur; + if (txPwrParseNumber(&pcContCur, carySeperator, + &op, &value)) { + DBGLOG(RLM, ERROR, + "parse %s error, %s\n", + pacParsePwrAC[j], pcContOld); + goto clearLabel; + } + prTmpSetting->op[j] = + (enum ENUM_TX_POWER_CTRL_VALUE_SIGN)op; + prTmpSetting->i8PwrLimit[j] = + (op != 2) ? value : (0 - value); + if ((prTmpSetting->op[j] + == PWR_CTRL_TYPE_POSITIVE) && + (ucOperation + == PWR_CTRL_TYPE_OPERATION_POWER_OFFSET) + ) { + DBGLOG(RLM, ERROR, + "parse %s error, Power_Offset value cannot be positive: %u\n", + pacParsePwrAC[j], + value); + goto clearLabel; + } + } + + } else if (count == PWR_CFG_PRAM_NUM_AX) { + for (j = 0; j < PWR_CFG_PRAM_NUM_AX; j++) { + /* parse RU26L ... RU996U setting */ + if (j == PWR_CFG_PRAM_NUM_AX - 1) + carySeperator[0] = ']'; + else + carySeperator[0] = ','; + + pcContOld = pcContCur; + if (txPwrParseNumber(&pcContCur, carySeperator, + &op, &value)) { + DBGLOG(RLM, ERROR, + "parse %s error, %s\n", + pacParsePwrAX[j], + pcContOld); + goto clearLabel; + } + prTmpSetting->opHE[j] = + (enum ENUM_TX_POWER_CTRL_VALUE_SIGN)op; + prTmpSetting->i8PwrLimitHE[j] = + (op != 2) ? value : (0 - value); + if ((prTmpSetting->opHE[j] + == PWR_CTRL_TYPE_POSITIVE) && + (ucOperation + == PWR_CTRL_TYPE_OPERATION_POWER_OFFSET) + ) { + DBGLOG(RLM, ERROR, + "parse %s error, Power_Offset value cannot be positive: %u\n", + pacParsePwrAX[j], + value); + goto clearLabel; + } + } + + } + +skipLabel2: + pcContCur = pcContNext + 2; + } + + return prCurElement; + +clearLabel: + if (prCurElement != NULL) + kalMemFree(prCurElement, VIR_MEM_TYPE, u4MemSize); + + return NULL; +} + +/* filterType: 0:no filter, 1:fgEnable is TRUE */ +int txPwrCtrlListSize(struct ADAPTER *prAdapter, uint8_t filterType) +{ + struct LINK_ENTRY *prCur, *prNext; + struct TX_PWR_CTRL_ELEMENT *prCurElement = NULL; + struct LINK *aryprlist[2] = { + &prAdapter->rTxPwr_DefaultList, + &prAdapter->rTxPwr_DynamicList + }; + int i, count = 0; + + for (i = 0; i < ARRAY_SIZE(aryprlist); i++) { + LINK_FOR_EACH_SAFE(prCur, prNext, aryprlist[i]) { + prCurElement = LINK_ENTRY(prCur, + struct TX_PWR_CTRL_ELEMENT, node); + if ((filterType == 1) && + (prCurElement->fgApplied != TRUE)) + continue; + count++; + } + } + + return count; +} + +/* filterType: 0:no filter, 1:fgApplied is TRUE */ +void txPwrCtrlShowList(struct ADAPTER *prAdapter, uint8_t filterType, + char *message) +{ + struct LINK_ENTRY *prCur, *prNext; + struct TX_PWR_CTRL_ELEMENT *prCurElement = NULL; + struct TX_PWR_CTRL_CHANNEL_SETTING *prChlSettingList; + struct LINK *aryprlist[2] = { + &prAdapter->rTxPwr_DefaultList, + &prAdapter->rTxPwr_DynamicList + }; + uint8_t ucAppliedWay, ucOperation; + int i, j, k, count = 0; + char msgLimit[PWR_BUF_LEN]; + int msgOfs = 0; + + if (filterType == 1) + DBGLOG(RLM, TRACE, "Tx Power Ctrl List=[%s], Size=[%d]", + message, txPwrCtrlListSize(prAdapter, filterType)); + else + DBGLOG(RLM, TRACE, "Tx Power Ctrl List=[%s], Size=[%d]", + message, txPwrCtrlListSize(prAdapter, filterType)); + + for (i = 0; i < ARRAY_SIZE(aryprlist); i++) { + LINK_FOR_EACH_SAFE(prCur, prNext, aryprlist[i]) { + prCurElement = LINK_ENTRY(prCur, + struct TX_PWR_CTRL_ELEMENT, node); + if ((filterType == 1) && + (prCurElement->fgApplied != TRUE)) + continue; + + switch (prCurElement->eCtrlType) { + case PWR_CTRL_TYPE_WIFION_POWER_LEVEL: + ucAppliedWay = + PWR_CTRL_TYPE_APPLIED_WAY_WIFION; + ucOperation = + PWR_CTRL_TYPE_OPERATION_POWER_LEVEL; + break; + case PWR_CTRL_TYPE_WIFION_POWER_OFFSET: + ucAppliedWay = + PWR_CTRL_TYPE_APPLIED_WAY_WIFION; + ucOperation = + PWR_CTRL_TYPE_OPERATION_POWER_OFFSET; + break; + case PWR_CTRL_TYPE_IOCTL_POWER_LEVEL: + ucAppliedWay = + PWR_CTRL_TYPE_APPLIED_WAY_IOCTL; + ucOperation = + PWR_CTRL_TYPE_OPERATION_POWER_LEVEL; + break; + case PWR_CTRL_TYPE_IOCTL_POWER_OFFSET: + ucAppliedWay = + PWR_CTRL_TYPE_APPLIED_WAY_IOCTL; + ucOperation = + PWR_CTRL_TYPE_OPERATION_POWER_OFFSET; + break; + default: + ucAppliedWay = 0; + ucOperation = 0; + break; + } + + DBGLOG(RLM, TRACE, + "Tx Power Ctrl Element-%u: name=[%s], index=[%u], appliedWay=[%u:%s], operation=[%u:%s], ChlSettingCount=[%u]\n", + ++count, prCurElement->name, prCurElement->index, + ucAppliedWay, + g_au1TxPwrAppliedWayLabel[ucAppliedWay - 1], + ucOperation, + g_au1TxPwrOperationLabel[ucOperation - 1], + prCurElement->settingCount); + + for (j = 0; j < prCurElement->settingCount; j++) { + prChlSettingList = + &(prCurElement->rChlSettingList[j]); + msgOfs = 0; + + /*Coverity check*/ + if (prChlSettingList->eChnlType < 0) + prChlSettingList->eChnlType = 0; + + /*message head*/ + msgOfs += snprintf(msgLimit + msgOfs, + PWR_BUF_LEN - msgOfs, + "Setting-%u:[%s:%u,%u],Legcy:", + (j + 1), + g_au1TxPwrChlTypeLabel[ + prChlSettingList->eChnlType], + prChlSettingList->channelParam[0], + prChlSettingList->channelParam[1]); + + /*print legacy cfg*/ + for (k = 0; k < PWR_LIMIT_NUM ; k++) + msgOfs += snprintf(msgLimit + msgOfs, + PWR_BUF_LEN - msgOfs, + "[%u,%d]", + prChlSettingList->op[k], + prChlSettingList->i8PwrLimit[k]); + + /*print HE cfg*/ + msgOfs += snprintf(msgLimit + msgOfs, + PWR_BUF_LEN - msgOfs, + "HE:"); + for (k = 0; k < PWR_LIMIT_HE_NUM ; k++) + msgOfs += snprintf(msgLimit + msgOfs, + PWR_BUF_LEN - msgOfs, + "[%u,%d]", + prChlSettingList->opHE[k], + prChlSettingList->i8PwrLimitHE[k]); + + /*message tail*/ + if (msgOfs > 0) + msgLimit[msgOfs-1] = '\0'; + else + msgLimit[0] = '\0'; + + DBGLOG(RLM, TRACE, "%s\n", msgLimit); + } + } + } +} + +/* This function used to delete element by specifying name or index + * if index is 0, deletion only according name + * if index >= 1, deletion according name and index + */ +void _txPwrCtrlDeleteElement(struct ADAPTER *prAdapter, + uint8_t *name, + uint32_t index, + struct LINK *prTxPwrCtrlList) +{ + struct LINK_ENTRY *prCur, *prNext; + struct TX_PWR_CTRL_ELEMENT *prCurElement = NULL; + uint32_t u4MemSize = sizeof(struct TX_PWR_CTRL_ELEMENT); + uint32_t u4MemSize2; + uint32_t u4SettingSize = sizeof(struct TX_PWR_CTRL_CHANNEL_SETTING); + uint8_t ucSettingCount; + u_int8_t fgFind; + + LINK_FOR_EACH_SAFE(prCur, prNext, prTxPwrCtrlList) { + fgFind = FALSE; + prCurElement = LINK_ENTRY(prCur, struct TX_PWR_CTRL_ELEMENT, + node); + if (kalStrCmp(prCurElement->name, name) == 0) { + if (index == 0) + fgFind = TRUE; + else if (prCurElement->index == index) + fgFind = TRUE; + if (fgFind) { + linkDel(prCur); + if (prCurElement != NULL) { + ucSettingCount = + prCurElement->settingCount; + u4MemSize2 = u4MemSize + + ((ucSettingCount == 1) ? 0 : + (ucSettingCount - 1) * + u4SettingSize); + kalMemFree(prCurElement, VIR_MEM_TYPE, + u4MemSize2); + } + } + } + } +} + +void txPwrCtrlDeleteElement(struct ADAPTER *prAdapter, + uint8_t *name, + uint32_t index, + enum ENUM_TX_POWER_CTRL_LIST_TYPE eListType) +{ + if ((eListType == PWR_CTRL_TYPE_ALL_LIST) || + (eListType == PWR_CTRL_TYPE_DEFAULT_LIST)) + _txPwrCtrlDeleteElement(prAdapter, name, index, + &prAdapter->rTxPwr_DefaultList); + + if ((eListType == PWR_CTRL_TYPE_ALL_LIST) || + (eListType == PWR_CTRL_TYPE_DYNAMIC_LIST)) + _txPwrCtrlDeleteElement(prAdapter, name, index, + &prAdapter->rTxPwr_DynamicList); +} + +struct TX_PWR_CTRL_ELEMENT *_txPwrCtrlFindElement(struct ADAPTER *prAdapter, + uint8_t *name, uint32_t index, + u_int8_t fgCheckIsApplied, + struct LINK *prTxPwrCtrlList) +{ + struct LINK_ENTRY *prCur, *prNext; + struct TX_PWR_CTRL_ELEMENT *prCurElement = NULL; + + + LINK_FOR_EACH_SAFE(prCur, prNext, prTxPwrCtrlList) { + u_int8_t fgFind = FALSE; + + prCurElement = LINK_ENTRY( + prCur, struct TX_PWR_CTRL_ELEMENT, node); + if (kalStrCmp(prCurElement->name, name) == 0) { + if ((!fgCheckIsApplied) || + (fgCheckIsApplied && + (prCurElement->fgApplied == TRUE))) { + if (index == 0) + fgFind = TRUE; + else if (prCurElement->index == index) + fgFind = TRUE; + } + if (fgFind) + return prCurElement; + } + } + return NULL; +} + +struct TX_PWR_CTRL_ELEMENT *txPwrCtrlFindElement(struct ADAPTER *prAdapter, + uint8_t *name, uint32_t index, + u_int8_t fgCheckIsApplied, + enum ENUM_TX_POWER_CTRL_LIST_TYPE eListType) +{ + struct LINK *prTxPwrCtrlList = NULL; + + if (eListType == PWR_CTRL_TYPE_DEFAULT_LIST) + prTxPwrCtrlList = &prAdapter->rTxPwr_DefaultList; + if (eListType == PWR_CTRL_TYPE_DYNAMIC_LIST) + prTxPwrCtrlList = &prAdapter->rTxPwr_DynamicList; + if (prTxPwrCtrlList == NULL) + return NULL; + + return _txPwrCtrlFindElement(prAdapter, name, index, fgCheckIsApplied, + prTxPwrCtrlList); +} + +void txPwrCtrlAddElement(struct ADAPTER *prAdapter, + struct TX_PWR_CTRL_ELEMENT *prElement) +{ + struct LINK_ENTRY *prNode = &prElement->node; + + switch (prElement->eCtrlType) { + case PWR_CTRL_TYPE_WIFION_POWER_LEVEL: + linkAdd(prNode, &prAdapter->rTxPwr_DefaultList); + break; + case PWR_CTRL_TYPE_WIFION_POWER_OFFSET: + linkAddTail(prNode, &prAdapter->rTxPwr_DefaultList); + break; + case PWR_CTRL_TYPE_IOCTL_POWER_LEVEL: + linkAdd(prNode, &prAdapter->rTxPwr_DynamicList); + break; + case PWR_CTRL_TYPE_IOCTL_POWER_OFFSET: + linkAddTail(prNode, &prAdapter->rTxPwr_DynamicList); + break; + } +} + +void txPwrCtrlFileBufToList(struct ADAPTER *prAdapter, uint8_t *pucFileBuf) +{ + struct TX_PWR_CTRL_ELEMENT *prNewElement; + char *oneLine; + + if (pucFileBuf == NULL) + return; + + while ((oneLine = kalStrSep((char **)(&pucFileBuf), "\r\n")) + != NULL) { + /* skip comment line and empty line */ + if ((oneLine[0] == '#') || (oneLine[0] == 0)) + continue; + + prNewElement = txPwrCtrlStringToStruct(oneLine, FALSE); + if (prNewElement != NULL) { + /* delete duplicated element + * by checking name and index + */ + txPwrCtrlDeleteElement(prAdapter, + prNewElement->name, prNewElement->index, + PWR_CTRL_TYPE_ALL_LIST); + + /* append to rTxPwr_List */ + txPwrCtrlAddElement(prAdapter, prNewElement); + } + } + + /* show the tx power ctrl list */ + txPwrCtrlShowList(prAdapter, 0, "config list, after loading cfg file"); +} + +void txPwrCtrlGlobalVariableToList(struct ADAPTER *prAdapter) +{ + struct TX_PWR_CTRL_ELEMENT *pcElement; + char *ptr; + int32_t i, u4MemSize; + + for (i = 0; i < ARRAY_SIZE(g_au1TxPwrDefaultSetting); i++) { + /* skip empty line */ + if (g_au1TxPwrDefaultSetting[i][0] == 0) + continue; + u4MemSize = kalStrLen(g_au1TxPwrDefaultSetting[i]) + 1; + ptr = (char *)kalMemAlloc(u4MemSize, VIR_MEM_TYPE); + if (ptr == NULL) { + DBGLOG(RLM, ERROR, "kalMemAlloc fail: %d\n", u4MemSize); + continue; + } + kalMemCopy(ptr, g_au1TxPwrDefaultSetting[i], u4MemSize); + *(ptr + u4MemSize - 1) = 0; + pcElement = txPwrCtrlStringToStruct(ptr, FALSE); + kalMemFree(ptr, VIR_MEM_TYPE, u4MemSize); + if (pcElement != NULL) { + /* delete duplicated element + * by checking name and index + */ + txPwrCtrlDeleteElement(prAdapter, + pcElement->name, pcElement->index, + PWR_CTRL_TYPE_ALL_LIST); + + /* append to rTxPwr_List */ + txPwrCtrlAddElement(prAdapter, pcElement); + } + } + + /* show the tx power ctrl cfg list */ + txPwrCtrlShowList(prAdapter, 0, + "config list, after loadding global variables"); +} + +void txPwrCtrlCfgFileToList(struct ADAPTER *prAdapter) +{ + uint8_t *pucConfigBuf; + uint32_t u4ConfigReadLen = 0; + + pucConfigBuf = (uint8_t *)kalMemAlloc(WLAN_CFG_FILE_BUF_SIZE, + VIR_MEM_TYPE); + kalMemZero(pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE); + if (pucConfigBuf) { + if (kalRequestFirmware("txpowerctrl.cfg", pucConfigBuf, + WLAN_CFG_FILE_BUF_SIZE, &u4ConfigReadLen, + prAdapter->prGlueInfo->prDev) == 0) { + /* ToDo:: Nothing */ + } else if (kalReadToFile("/data/misc/wifi/txpowerctrl.cfg", + pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE, + &u4ConfigReadLen) == 0) { + /* ToDo:: Nothing */ + } else if (kalReadToFile("/storage/sdcard0/txpowerctrl.cfg", + pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE, + &u4ConfigReadLen) == 0) { + /* ToDo:: Nothing */ + } + + if (pucConfigBuf[0] != '\0' && u4ConfigReadLen > 0) { + pucConfigBuf[u4ConfigReadLen] = 0; + txPwrCtrlFileBufToList(prAdapter, pucConfigBuf); + } else + DBGLOG(RLM, INFO, + "no txpowerctrl.cfg or file is empty\n"); + + kalMemFree(pucConfigBuf, VIR_MEM_TYPE, WLAN_CFG_FILE_BUF_SIZE); + } +} + +void txPwrCtrlLoadConfig(struct ADAPTER *prAdapter) +{ + /* 1. add records from global tx power ctrl setting into cfg list */ + txPwrCtrlGlobalVariableToList(prAdapter); + + /* 2. update cfg list by txpowerctrl.cfg */ + txPwrCtrlCfgFileToList(prAdapter); + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + /* 3. send setting to firmware */ + rlmDomainSendPwrLimitCmd(prAdapter); +#endif +} + +void txPwrCtrlInit(struct ADAPTER *prAdapter) +{ + LINK_INITIALIZE(&prAdapter->rTxPwr_DefaultList); + LINK_INITIALIZE(&prAdapter->rTxPwr_DynamicList); +} + +void txPwrCtrlUninit(struct ADAPTER *prAdapter) +{ + struct LINK_ENTRY *prCur, *prNext; + struct TX_PWR_CTRL_ELEMENT *prCurElement = NULL; + struct LINK *aryprlist[2] = { + &prAdapter->rTxPwr_DefaultList, + &prAdapter->rTxPwr_DynamicList + }; + uint32_t u4MemSize = sizeof(struct TX_PWR_CTRL_ELEMENT); + uint32_t u4MemSize2; + uint32_t u4SettingSize = sizeof(struct TX_PWR_CTRL_CHANNEL_SETTING); + uint8_t ucSettingCount; + int32_t i; + + for (i = 0; i < ARRAY_SIZE(aryprlist); i++) { + LINK_FOR_EACH_SAFE(prCur, prNext, aryprlist[i]) { + prCurElement = LINK_ENTRY(prCur, + struct TX_PWR_CTRL_ELEMENT, node); + linkDel(prCur); + if (prCurElement) { + ucSettingCount = prCurElement->settingCount; + u4MemSize2 = u4MemSize + + ((ucSettingCount <= 1) ? 0 : + (ucSettingCount - 1) * u4SettingSize); + kalMemFree(prCurElement, + VIR_MEM_TYPE, u4MemSize2); + } + } + } +} +/* dynamic tx power control: end **********************************************/ +#endif /* CFG_SUPPORT_DYNAMIC_PWR_LIMIT */ + +void rlmDomainShowPwrLimitPerCh(char *message, + struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT *prCmd) +{ + /* for print usage */ + struct CMD_CHANNEL_POWER_LIMIT *prPwrLmt = NULL; + /* for print usage */ + struct CMD_CHANNEL_POWER_LIMIT_HE *prPwrLmtHE = NULL; + enum ENUM_PWR_LIMIT_TYPE eType; + uint8_t i, j; + char msgLimit[PWR_BUF_LEN]; + int msgOfs = 0; + int8_t *prcRatePwr; + + + ASSERT(prCmd); + + eType = prCmd->ucLimitType; + + for (i = 0; i < prCmd->ucNum; i++) { + + if (i >= MAX_CMD_SUPPORT_CHANNEL_NUM) { + DBGLOG(RLM, ERROR, "out of MAX CH Num\n"); + return; + } + + kalMemZero(msgLimit, sizeof(char)*PWR_BUF_LEN); + msgOfs = 0; + if (eType == PWR_LIMIT_TYPE_COMP_11AX) { + prPwrLmtHE = &prCmd->u.rChPwrLimtHE[i]; + prcRatePwr = &prPwrLmtHE->cPwrLimitRU26L; + + /*message head*/ + msgOfs += snprintf(msgLimit + msgOfs, + PWR_BUF_LEN - msgOfs, + "HE ch=%d,Limit=", + prPwrLmtHE->ucCentralCh); + + /*message body*/ + for (j = PWR_LIMIT_RU26_L; j < PWR_LIMIT_HE_NUM ; j++) + msgOfs += snprintf(msgLimit + msgOfs, + PWR_BUF_LEN - msgOfs, + "%d,", + *(prcRatePwr + j)); + /*message tail*/ + if (msgOfs >= 1) + msgLimit[msgOfs-1] = '\0'; + else + msgLimit[0] = '\0'; + + DBGLOG(RLM, TRACE, "%s:%s\n", message, msgLimit); + + } else { + prPwrLmt = &prCmd->u.rChannelPowerLimit[i]; + prcRatePwr = &prPwrLmt->cPwrLimitCCK; + + /*message head*/ + msgOfs += snprintf(msgLimit + msgOfs, + PWR_BUF_LEN - msgOfs, + "legacy ch=%d,Limit=", + prPwrLmt->ucCentralCh); + + /*message body*/ + for (j = PWR_LIMIT_CCK; j < PWR_LIMIT_NUM ; j++) + msgOfs += snprintf(msgLimit + msgOfs, + PWR_BUF_LEN - msgOfs, + "%d,", + *(prcRatePwr + j)); + + /*message tail*/ + if (msgOfs > 0) + msgLimit[msgOfs-1] = '\0'; + else + msgLimit[0] = '\0'; + + DBGLOG(RLM, TRACE, "%s:%s\n", message, msgLimit); + } + } + +} + +void rlmDomainSendPwrLimitCmd(struct ADAPTER *prAdapter) +{ + struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT *prCmd = NULL; + struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT *prCmdHE = NULL; + uint32_t rStatus; + uint16_t u2DefaultTableIndex; + uint32_t u4SetCmdTableMaxSize; + uint32_t u4SetCmdTableMaxSizeHE; + uint32_t u4SetQueryInfoLen; + uint32_t u4SetQueryInfoLenHE; + uint8_t bandedgeParam[4] = { 0, 0, 0, 0 }; + struct DOMAIN_INFO_ENTRY *prDomainInfo; + /* TODO : 5G band edge */ + prDomainInfo = rlmDomainGetDomainInfo(prAdapter); + if (prDomainInfo) { + bandedgeParam[0] = prDomainInfo->rSubBand[0].ucFirstChannelNum; + bandedgeParam[1] = bandedgeParam[0] + + prDomainInfo->rSubBand[0].ucNumChannels - 1; + } + + if (regd_is_single_sku_en()) + return rlmDomainSendPwrLimitCmd_V2(prAdapter); + + + u4SetCmdTableMaxSize = + sizeof(struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT); + + u4SetCmdTableMaxSizeHE = + sizeof(struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT); + + + prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4SetCmdTableMaxSize); + + if (!prCmd) { + DBGLOG(RLM, ERROR, "Domain: Alloc cmd buffer failed\n"); + goto err; + } + + prCmdHE = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4SetCmdTableMaxSizeHE); + + if (!prCmdHE) { + DBGLOG(RLM, ERROR, "Domain: Alloc cmd buffer failed\n"); + goto err; + } + + kalMemZero(prCmd, u4SetCmdTableMaxSize); + kalMemZero(prCmdHE, u4SetCmdTableMaxSize); + + u2DefaultTableIndex = + rlmDomainPwrLimitDefaultTableDecision(prAdapter, + prAdapter->rWifiVar.u2CountryCode); + + if (u2DefaultTableIndex == POWER_LIMIT_TABLE_NULL) { + DBGLOG(RLM, ERROR, + "Can't find any table index!\n"); + goto err; + } + + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault + [u2DefaultTableIndex] + .aucCountryCode[0], + &prCmd->u2CountryCode); + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault + [u2DefaultTableIndex] + .aucCountryCode[0], + &prCmdHE->u2CountryCode); + + if (prCmd->u2CountryCode == COUNTRY_CODE_NULL) + DBGLOG(RLM, TRACE, + "CC={0x00,0x00},Power Limit use Default setting!"); + + + /* Initialize channel number */ + prCmd->ucNum = 0; + prCmd->ucLimitType = PWR_LIMIT_TYPE_COMP_11AC; + + prCmdHE->ucNum = 0; + prCmdHE->fgPwrTblKeep = TRUE; + prCmdHE->ucLimitType = PWR_LIMIT_TYPE_COMP_11AX; + + + /*<1>Command - default table information, + *fill all subband + */ + rlmDomainBuildCmdByDefaultTable(prCmd, + u2DefaultTableIndex); + + /*<2>Command - configuration table information, + * replace specified channel + */ + rlmDomainBuildCmdByConfigTable(prAdapter, + prCmd); + +#if (CFG_SUPPORT_PWR_LIMIT_HE == 1) + /*<1>Command - default table information, + *fill all subband + */ + rlmDomainBuildCmdByDefaultTable(prCmdHE, + u2DefaultTableIndex); + + /*<2>Command - configuration table information, + * replace specified channel + */ + rlmDomainBuildCmdByConfigTable(prAdapter, + prCmdHE); +#endif + + DBGLOG(RLM, TRACE, + "Domain: ValidCC=%c%c, PwrLimitCC=%c%c, PwrLimitChNum=%d\n", + (prAdapter->rWifiVar.u2CountryCode & 0xff00) >> 8, + (prAdapter->rWifiVar.u2CountryCode & 0x00ff), + ((prCmd->u2CountryCode & 0xff00) >> 8), + (prCmd->u2CountryCode & 0x00ff), + prCmd->ucNum); + +#if CFG_SUPPORT_DYNAMIC_PWR_LIMIT + rlmDomainShowPwrLimitPerCh("Old", prCmd); + /* apply each setting into country channel power table */ + txPwrCtrlApplySettings(prAdapter, prCmd, bandedgeParam); + /* show tx power table after applying setting */ + rlmDomainShowPwrLimitPerCh("Final", prCmd); + +#if (CFG_SUPPORT_PWR_LIMIT_HE == 1) + rlmDomainShowPwrLimitPerCh("Old", prCmdHE); + txPwrCtrlApplySettings(prAdapter, prCmdHE, bandedgeParam); + rlmDomainShowPwrLimitPerCh("Final", prCmdHE); +#endif /*#if (CFG_SUPPORT_PWR_LIMIT_HE == 1)*/ +#endif + + + u4SetQueryInfoLen = + sizeof(struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT); + + u4SetQueryInfoLenHE = + sizeof(struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT); + + + /* Update domain info to chip */ + if (prCmd->ucNum <= MAX_CMD_SUPPORT_CHANNEL_NUM) { + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_COUNTRY_POWER_LIMIT, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + u4SetQueryInfoLen, /* u4SetQueryInfoLen */ + (uint8_t *) prCmd, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); +#if (CFG_SUPPORT_PWR_LIMIT_HE == 1) + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_COUNTRY_POWER_LIMIT, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + u4SetQueryInfoLenHE, /* u4SetQueryInfoLen */ + (uint8_t *) prCmdHE, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); +#endif + } else { + DBGLOG(RLM, ERROR, "Domain: illegal power limit table\n"); + } + + /* ASSERT(rStatus == WLAN_STATUS_PENDING); */ +err: + cnmMemFree(prAdapter, prCmd); + cnmMemFree(prAdapter, prCmdHE); + +} +#endif +u_int8_t regd_is_single_sku_en(void) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + return g_mtk_regd_control.en; +#else + return FALSE; +#endif +} + +#if (CFG_SUPPORT_SINGLE_SKU == 1) +u_int8_t rlmDomainIsCtrlStateEqualTo(enum regd_state state) +{ + return (g_mtk_regd_control.state == state) ? TRUE : FALSE; +} + +enum regd_state rlmDomainGetCtrlState(void) +{ + return g_mtk_regd_control.state; +} + + +void rlmDomainResetActiveChannel(void) +{ + g_mtk_regd_control.n_channel_active_2g = 0; + g_mtk_regd_control.n_channel_active_5g = 0; +} + +void rlmDomainAddActiveChannel(u8 band) + +{ + if (band == KAL_BAND_2GHZ) + g_mtk_regd_control.n_channel_active_2g += 1; + else if (band == KAL_BAND_5GHZ) + g_mtk_regd_control.n_channel_active_5g += 1; +} + +u8 rlmDomainGetActiveChannelCount(u8 band) +{ + if (band == KAL_BAND_2GHZ) + return g_mtk_regd_control.n_channel_active_2g; + else if (band == KAL_BAND_5GHZ) + return g_mtk_regd_control.n_channel_active_5g; + else + return 0; +} + +struct CMD_DOMAIN_CHANNEL *rlmDomainGetActiveChannels(void) +{ + return g_mtk_regd_control.channels; +} + +void rlmDomainSetDefaultCountryCode(void) +{ + g_mtk_regd_control.alpha2 = COUNTRY_CODE_WW; +} + +void rlmDomainResetCtrlInfo(u_int8_t force) +{ + if ((g_mtk_regd_control.state == REGD_STATE_UNDEFINED) || + (force == TRUE)) { + memset(&g_mtk_regd_control, 0, sizeof(struct mtk_regd_control)); + + g_mtk_regd_control.state = REGD_STATE_INIT; + + rlmDomainSetDefaultCountryCode(); + +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) + g_mtk_regd_control.flag |= REGD_CTRL_FLAG_SUPPORT_LOCAL_REGD_DB; +#endif + } +} + +u_int8_t rlmDomainIsUsingLocalRegDomainDataBase(void) +{ +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) + return (g_mtk_regd_control.flag & REGD_CTRL_FLAG_SUPPORT_LOCAL_REGD_DB) + ? TRUE : FALSE; +#else + return FALSE; +#endif +} + +bool rlmDomainIsSameCountryCode(char *alpha2, u8 size_of_alpha2) +{ + u8 idx; + u32 alpha2_hex = 0; + + for (idx = 0; idx < size_of_alpha2; idx++) + alpha2_hex |= (alpha2[idx] << (idx * 8)); + + return (rlmDomainGetCountryCode() == alpha2_hex) ? TRUE : FALSE; +} + +void rlmDomainSetCountryCode(char *alpha2, u8 size_of_alpha2) +{ + u8 max; + u8 buf_size; + + buf_size = sizeof(g_mtk_regd_control.alpha2); + max = (buf_size < size_of_alpha2) ? buf_size : size_of_alpha2; + + g_mtk_regd_control.alpha2 = rlmDomainAlpha2ToU32(alpha2, max); +} +void rlmDomainSetDfsRegion(enum nl80211_dfs_regions dfs_region) +{ + g_mtk_regd_control.dfs_region = dfs_region; +} + +enum nl80211_dfs_regions rlmDomainGetDfsRegion(void) +{ + return g_mtk_regd_control.dfs_region; +} + +void rlmDomainSetTempCountryCode(char *alpha2, u8 size_of_alpha2) +{ + u8 idx, max; + u8 buf_size; + + buf_size = sizeof(g_mtk_regd_control.tmp_alpha2); + max = (buf_size < size_of_alpha2) ? buf_size : size_of_alpha2; + + g_mtk_regd_control.tmp_alpha2 = 0; + + for (idx = 0; idx < max; idx++) + g_mtk_regd_control.tmp_alpha2 |= (alpha2[idx] << (idx * 8)); + +} + +enum regd_state rlmDomainStateTransition(enum regd_state request_state, + struct regulatory_request *pRequest) +{ + enum regd_state next_state, old_state; + bool the_same = 0; + + old_state = g_mtk_regd_control.state; + next_state = REGD_STATE_INVALID; + + if (old_state == REGD_STATE_INVALID) + DBGLOG(RLM, ERROR, + "%s(): invalid state. trasntion is not allowed.\n", + __func__); + + switch (request_state) { + case REGD_STATE_SET_WW_CORE: + if ((old_state == REGD_STATE_SET_WW_CORE) || + (old_state == REGD_STATE_INIT) || + (old_state == REGD_STATE_SET_COUNTRY_USER) || + (old_state == REGD_STATE_SET_COUNTRY_IE)) + next_state = request_state; + break; + case REGD_STATE_SET_COUNTRY_USER: + /* Allow user to set multiple times */ + if ((old_state == REGD_STATE_SET_WW_CORE) || + (old_state == REGD_STATE_INIT) || + (old_state == REGD_STATE_SET_COUNTRY_USER) || + (old_state == REGD_STATE_SET_COUNTRY_IE)) + next_state = request_state; + else + DBGLOG(RLM, ERROR, "Invalid old state = %d\n", + old_state); + break; + case REGD_STATE_SET_COUNTRY_DRIVER: + if (old_state == REGD_STATE_SET_COUNTRY_USER) { + /* + * Error. + * Mixing using set_country_by_user and + * set_country_by_driver is not allowed. + */ + break; + } + + next_state = request_state; + break; + case REGD_STATE_SET_COUNTRY_IE: + next_state = request_state; + break; + default: + break; + } + + if (next_state == REGD_STATE_INVALID) { + DBGLOG(RLM, ERROR, + "%s(): ERROR. trasntion to invalid state. o=%x, r=%x, s=%x\n", + __func__, old_state, request_state, the_same); + } else + DBGLOG(RLM, INFO, "%s(): trasntion to state = %x (old = %x)\n", + __func__, next_state, g_mtk_regd_control.state); + + g_mtk_regd_control.state = next_state; + + return g_mtk_regd_control.state; +} + +/** + * rlmDomainChannelFlagString - Transform channel flags to readable string + * + * @ flags: the ieee80211_channel->flags for a channel + * @ buf: string buffer to put the transformed string + * @ buf_size: size of the buf + **/ +void rlmDomainChannelFlagString(u32 flags, char *buf, size_t buf_size) +{ + int32_t buf_written = 0; + + if (!flags || !buf || !buf_size) + return; + + if (flags & IEEE80211_CHAN_DISABLED) { + LOGBUF(buf, ((int32_t)buf_size), buf_written, "DISABLED "); + /* If DISABLED, don't need to check other flags */ + return; + } + if (flags & IEEE80211_CHAN_PASSIVE_FLAG) + LOGBUF(buf, ((int32_t)buf_size), buf_written, + IEEE80211_CHAN_PASSIVE_STR " "); + if (flags & IEEE80211_CHAN_RADAR) + LOGBUF(buf, ((int32_t)buf_size), buf_written, "RADAR "); + if (flags & IEEE80211_CHAN_NO_HT40PLUS) + LOGBUF(buf, ((int32_t)buf_size), buf_written, "NO_HT40PLUS "); + if (flags & IEEE80211_CHAN_NO_HT40MINUS) + LOGBUF(buf, ((int32_t)buf_size), buf_written, "NO_HT40MINUS "); + if (flags & IEEE80211_CHAN_NO_80MHZ) + LOGBUF(buf, ((int32_t)buf_size), buf_written, "NO_80MHZ "); + if (flags & IEEE80211_CHAN_NO_160MHZ) + LOGBUF(buf, ((int32_t)buf_size), buf_written, "NO_160MHZ "); +} + +void rlmDomainParsingChannel(IN struct wiphy *pWiphy) +{ + u32 band_idx, ch_idx; + u32 ch_count; + struct ieee80211_supported_band *sband; + struct ieee80211_channel *chan; + struct CMD_DOMAIN_CHANNEL *pCh; + char chan_flag_string[64] = {0}; +#if (CFG_SUPPORT_REGD_UPDATE_DISCONNECT_ALLOWED == 1) + struct GLUE_INFO *prGlueInfo; + bool fgDisconnection = FALSE; + uint8_t ucChannelNum = 0; + uint32_t rStatus, u4BufLen; +#endif + + if (!pWiphy) { + DBGLOG(RLM, ERROR, "%s(): ERROR. pWiphy = NULL.\n", __func__); + ASSERT(0); + return; + } + +#if (CFG_SUPPORT_REGD_UPDATE_DISCONNECT_ALLOWED == 1) + /* Retrieve connected channel */ + prGlueInfo = rlmDomainGetGlueInfo(); + if (prGlueInfo && kalGetMediaStateIndicated(prGlueInfo) == + MEDIA_STATE_CONNECTED) { + ucChannelNum = + wlanGetChannelNumberByNetwork(prGlueInfo->prAdapter, + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex); + } +#endif + /* + * Ready to parse the channel for bands + */ + + rlmDomainResetActiveChannel(); + + ch_count = 0; + for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { + sband = pWiphy->bands[band_idx]; + if (!sband) + continue; + + for (ch_idx = 0; ch_idx < sband->n_channels; ch_idx++) { + chan = &sband->channels[ch_idx]; + pCh = (rlmDomainGetActiveChannels() + ch_count); + /* Parse flags and get readable string */ + rlmDomainChannelFlagString(chan->flags, + chan_flag_string, + sizeof(chan_flag_string)); + + if (chan->flags & IEEE80211_CHAN_DISABLED) { + DBGLOG(RLM, INFO, + "channels[%d][%d]: ch%d (freq = %d) flags=0x%x [ %s]\n", + band_idx, ch_idx, chan->hw_value, + chan->center_freq, chan->flags, + chan_flag_string); +#if (CFG_SUPPORT_REGD_UPDATE_DISCONNECT_ALLOWED == 1) + /* Disconnect AP in the end of this function*/ + if (chan->hw_value == ucChannelNum) + fgDisconnection = TRUE; +#endif + continue; + } + + /* Allowable channel */ + if (ch_count == MAX_SUPPORTED_CH_COUNT) { + DBGLOG(RLM, ERROR, + "%s(): no buffer to store channel information.\n", + __func__); + break; + } + + rlmDomainAddActiveChannel(band_idx); + + DBGLOG(RLM, INFO, + "channels[%d][%d]: ch%d (freq = %d) flgs=0x%x [%s]\n", + band_idx, ch_idx, chan->hw_value, + chan->center_freq, chan->flags, + chan_flag_string); + + pCh->u2ChNum = chan->hw_value; + pCh->eFlags = chan->flags; + + ch_count += 1; + } + + } +#if (CFG_SUPPORT_REGD_UPDATE_DISCONNECT_ALLOWED == 1) + /* Disconnect with AP if connected channel is disabled in new country */ + if (fgDisconnection) { + DBGLOG(RLM, STATE, "%s(): Disconnect! CH%d is DISABLED\n", + __func__, ucChannelNum); + rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, + NULL, 0, FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(RLM, WARN, "disassociate error:%lx\n", rStatus); + } +#endif +} +void rlmExtractChannelInfo(u32 max_ch_count, + struct CMD_DOMAIN_ACTIVE_CHANNEL_LIST *prBuff) +{ + u32 ch_count, idx; + struct CMD_DOMAIN_CHANNEL *pCh; + + prBuff->u1ActiveChNum2g = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + prBuff->u1ActiveChNum5g = rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ); + ch_count = prBuff->u1ActiveChNum2g + prBuff->u1ActiveChNum5g; + + if (ch_count > max_ch_count) { + ch_count = max_ch_count; + DBGLOG(RLM, WARN, + "%s(); active channel list is not a complete one.\n", + __func__); + } + + for (idx = 0; idx < ch_count; idx++) { + pCh = &(prBuff->arChannels[idx]); + + pCh->u2ChNum = (rlmDomainGetActiveChannels() + idx)->u2ChNum; + pCh->eFlags = (rlmDomainGetActiveChannels() + idx)->eFlags; + } + +} + +const struct ieee80211_regdomain +*rlmDomainSearchRegdomainFromLocalDataBase(char *alpha2) +{ +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) + u8 idx; + const struct mtk_regdomain *prRegd; + + idx = 0; + while (g_prRegRuleTable[idx]) { + prRegd = g_prRegRuleTable[idx]; + + if ((prRegd->country_code[0] == alpha2[0]) && + (prRegd->country_code[1] == alpha2[1]) && + (prRegd->country_code[2] == alpha2[2]) && + (prRegd->country_code[3] == alpha2[3])) + return prRegd->prRegdRules; + + idx++; + } + + DBGLOG(RLM, ERROR, + "%s(): Error, Cannot find the correct RegDomain. country = %s\n", + __func__, alpha2); + DBGLOG(RLM, INFO, " Set as default WW.\n"); + + return &default_regdom_ww; /*default world wide*/ +#else + return NULL; +#endif +} + + +const struct ieee80211_regdomain *rlmDomainGetLocalDefaultRegd(void) +{ +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) + return &default_regdom_ww; +#else + return NULL; +#endif +} +struct GLUE_INFO *rlmDomainGetGlueInfo(void) +{ + return g_mtk_regd_control.pGlueInfo; +} + +bool rlmDomainIsEfuseUsed(void) +{ + return g_mtk_regd_control.isEfuseCountryCodeUsed; +} + +uint8_t rlmDomainGetChannelBw(uint8_t channelNum) +{ + uint32_t ch_idx = 0, start_idx = 0, end_idx = 0; + uint8_t channelBw = MAX_BW_80_80_MHZ; + struct CMD_DOMAIN_CHANNEL *pCh; + + end_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ) + + rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ); + + for (ch_idx = start_idx; ch_idx < end_idx; ch_idx++) { + pCh = (rlmDomainGetActiveChannels() + ch_idx); + + if (pCh->u2ChNum != channelNum) + continue; + + /* Max BW */ + if ((pCh->eFlags & IEEE80211_CHAN_NO_160MHZ) + == IEEE80211_CHAN_NO_160MHZ) + channelBw = MAX_BW_80MHZ; + if ((pCh->eFlags & IEEE80211_CHAN_NO_80MHZ) + == IEEE80211_CHAN_NO_80MHZ) + channelBw = MAX_BW_40MHZ; + if ((pCh->eFlags & IEEE80211_CHAN_NO_HT40) + == IEEE80211_CHAN_NO_HT40) + channelBw = MAX_BW_20MHZ; + } + + DBGLOG(RLM, TRACE, "ch=%d, BW=%d\n", channelNum, channelBw); + return channelBw; +} +#endif + +uint32_t rlmDomainExtractSingleSkuInfoFromFirmware(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + struct SINGLE_SKU_INFO *prSkuInfo = + (struct SINGLE_SKU_INFO *) pucEventBuf; + + g_mtk_regd_control.en = TRUE; + + if (prSkuInfo->isEfuseValid) { + if (!rlmDomainIsUsingLocalRegDomainDataBase()) { + + DBGLOG(RLM, ERROR, + "%s(): Error. In efuse mode, must use local data base.\n", + __func__); + + ASSERT(0); + /* force using local db if getting + * country code from efuse + */ + return WLAN_STATUS_NOT_SUPPORTED; + } + + rlmDomainSetCountryCode((char *) &prSkuInfo->u4EfuseCountryCode, + sizeof(prSkuInfo->u4EfuseCountryCode)); + g_mtk_regd_control.isEfuseCountryCodeUsed = TRUE; + + } +#endif + + return WLAN_STATUS_SUCCESS; +} + +void rlmDomainSendInfoToFirmware(IN struct ADAPTER *prAdapter) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + struct regulatory_request request; + struct regulatory_request *prReq = NULL; + + if (!regd_is_single_sku_en()) + return; /*not support single sku*/ + + if (g_mtk_regd_control.isEfuseCountryCodeUsed) { + request.initiator = NL80211_REGDOM_SET_BY_DRIVER; + prReq = &request; + } + + g_mtk_regd_control.pGlueInfo = prAdapter->prGlueInfo; + mtk_reg_notify(priv_to_wiphy(prAdapter->prGlueInfo), prReq); +#endif +} + +enum ENUM_CHNL_EXT rlmSelectSecondaryChannelType(struct ADAPTER *prAdapter, + enum ENUM_BAND band, + u8 primary_ch) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + u8 below_ch, above_ch; + + below_ch = primary_ch - CHNL_SPAN_20; + above_ch = primary_ch + CHNL_SPAN_20; + + if (rlmDomainIsLegalChannel(prAdapter, band, above_ch)) + return CHNL_EXT_SCA; + + if (rlmDomainIsLegalChannel(prAdapter, band, below_ch)) + return CHNL_EXT_SCB; + +#endif + + return CHNL_EXT_SCN; +} + +void rlmDomainOidSetCountry(IN struct ADAPTER *prAdapter, char *country, + u8 size_of_country) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + struct regulatory_request request; + kalMemZero(&request, sizeof(request)); + + if (rlmDomainIsUsingLocalRegDomainDataBase()) { + rlmDomainSetTempCountryCode(country, size_of_country); + request.initiator = NL80211_REGDOM_SET_BY_DRIVER; + mtk_reg_notify(priv_to_wiphy(prAdapter->prGlueInfo), &request); + } else { + DBGLOG(RLM, INFO, + "%s(): Using driver hint to query CRDA getting regd.\n", + __func__); + regulatory_hint(priv_to_wiphy(prAdapter->prGlueInfo), country); + } +#endif +} + +u32 rlmDomainGetCountryCode(void) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + return g_mtk_regd_control.alpha2; +#else + return 0; +#endif +} + +u32 rlmDomainGetTempCountryCode(void) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + return g_mtk_regd_control.tmp_alpha2; +#else + return 0; +#endif +} + +void rlmDomainAssert(u_int8_t cond) +{ + /* bypass this check because single sku is not enable */ + if (!regd_is_single_sku_en()) + return; + + if (!cond) { + WARN_ON(1); + DBGLOG(RLM, ERROR, "[WARNING!!] RLM unexpected case.\n"); + } + +} + + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rlm_obss.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rlm_obss.c new file mode 100644 index 0000000000000..783917236729d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rlm_obss.c @@ -0,0 +1,402 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rlm_obss.c#2 + */ + +/*! \file "rlm_obss.c" + * \brief + * + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +static void rlmObssScanTimeout(struct ADAPTER *prAdapter, + unsigned long ulParamPtr); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmObssInit(struct ADAPTER *prAdapter) +{ + struct BSS_INFO *prBssInfo; + uint8_t i; + + ASSERT(prAdapter); + + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + + cnmTimerInitTimer(prAdapter, &prBssInfo->rObssScanTimer, + (PFN_MGMT_TIMEOUT_FUNC) rlmObssScanTimeout, + (unsigned long) prBssInfo); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rlmObssUpdateChnlLists(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb) +{ + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmObssScanDone(struct ADAPTER *prAdapter, struct MSG_HDR *prMsgHdr) +{ + struct MSG_SCN_SCAN_DONE *prScanDoneMsg; + struct BSS_INFO *prBssInfo; + struct MSDU_INFO *prMsduInfo; + struct ACTION_20_40_COEXIST_FRAME *prTxFrame; + uint16_t i, u2PayloadLen; + + ASSERT(prMsgHdr); + + prScanDoneMsg = (struct MSG_SCN_SCAN_DONE *) prMsgHdr; + prBssInfo = prAdapter->aprBssInfo[prScanDoneMsg->ucBssIndex]; + ASSERT(prBssInfo); + + DBGLOG(RLM, INFO, "OBSS Scan Done (NetIdx=%d, Mode=%d)\n", + prScanDoneMsg->ucBssIndex, prBssInfo->eCurrentOPMode); + + cnmMemFree(prAdapter, prMsgHdr); + +#if CFG_ENABLE_WIFI_DIRECT + /* AP mode */ + if ((prAdapter->fgIsP2PRegistered) && + (IS_NET_ACTIVE(prAdapter, prBssInfo->ucBssIndex)) && + (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->ucBssIndex); + 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) { + + DBGLOG(RLM, INFO, + "Send 20/40 coexistence mgmt(20mReq=%d, NonHt=%d)\n", + prBssInfo->auc2G_20mReqChnlList[0], + prBssInfo->auc2G_NonHtChnlList[0]); + + prMsduInfo = (struct MSDU_INFO *) cnmMgtPktAlloc(prAdapter, + MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + + if (prMsduInfo) { + prTxFrame = (struct ACTION_20_40_COEXIST_FRAME *) + ((unsigned long) (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; + /* 2.4GHz, ch1~13 */ + prTxFrame->rChnlReport.ucRegulatoryClass = 81; + 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 */ + + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prBssInfo->ucBssIndex, + prBssInfo->prStaRecOfAP->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, + NULL, MSDU_RATE_MODE_AUTO); + + /* 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->ucBssIndex, prBssInfo->u2ObssScanInterval); + + cnmTimerStartTimer(prAdapter, &prBssInfo->rObssScanTimer, + prBssInfo-> + u2ObssScanInterval * MSEC_PER_SEC); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static void rlmObssScanTimeout(struct ADAPTER *prAdapter, + unsigned long ulParamPtr) +{ + struct BSS_INFO *prBssInfo; + + prBssInfo = (struct BSS_INFO *) ulParamPtr; + ASSERT(prBssInfo); + +#if CFG_ENABLE_WIFI_DIRECT + /* AP mode */ + if (prAdapter->fgIsP2PRegistered && + (IS_NET_ACTIVE(prAdapter, prBssInfo->ucBssIndex)) && + (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { + + prBssInfo->fgObssActionForcedTo20M = FALSE; + + /* Check if Beacon content need to be updated */ + rlmUpdateParamsForAP(prAdapter, prBssInfo, FALSE); + + return; + } +#if CFG_SUPPORT_WFD + /* WFD streaming */ + else { + struct WFD_CFG_SETTINGS *prWfdCfgSettings = + &prAdapter->rWifiVar.rWfdConfigureSettings; + + /* If WFD is enabled & connected */ + if (prWfdCfgSettings->ucWfdEnable) { + + /* Skip OBSS scan */ + prBssInfo->u2ObssScanInterval = 0; + DBGLOG(RLM, INFO, "WFD is running. Stop OBSS scan.\n"); + return; + } /* WFD is enabled */ + } +#endif +#endif /* end of CFG_ENABLE_WIFI_DIRECT */ + + /* STA mode */ + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE || + !RLM_NET_PARAM_VALID(prBssInfo) || + prBssInfo->u2ObssScanInterval == 0) { + DBGLOG(RLM, WARN, + "OBSS Scan timeout (NetIdx=%d) -- Aborted!!\n", + prBssInfo->ucBssIndex); + return; + } + + rlmObssTriggerScan(prAdapter, prBssInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmObssTriggerScan(struct ADAPTER *prAdapter, struct BSS_INFO *prBssInfo) +{ + struct MSG_SCN_SCAN_REQ_V2 *prScanReqMsg; + + if (prBssInfo == NULL) { + DBGLOG(RLM, WARN, "BssInfo = NULL!"); + return; + } + + prScanReqMsg = (struct MSG_SCN_SCAN_REQ_V2 *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_SCN_SCAN_REQ_V2)); + + if (!prScanReqMsg) { + DBGLOG(RLM, WARN, "No buf for OBSS scan (NetIdx=%d)!!\n", + prBssInfo->ucBssIndex); + + 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 + */ + kalMemZero(prScanReqMsg, sizeof(struct MSG_SCN_SCAN_REQ_V2)); + prScanReqMsg->rMsgHdr.eMsgId = MID_RLM_SCN_SCAN_REQ_V2; + prScanReqMsg->ucSeqNum = 0x33; + prScanReqMsg->ucBssIndex = prBssInfo->ucBssIndex; + prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_WILDCARD; + prScanReqMsg->ucSSIDNum = 0; + prScanReqMsg->eScanChannel = SCAN_CHANNEL_2G4; + prScanReqMsg->u2IELen = 0; + + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *) prScanReqMsg, + MSG_SEND_METHOD_BUF); + + DBGLOG(RLM, INFO, "Timeout to trigger OBSS scan (NetIdx=%d)!!\n", + prBssInfo->ucBssIndex); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rlm_protection.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rlm_protection.c new file mode 100644 index 0000000000000..b6375a44c5abc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rlm_protection.c @@ -0,0 +1,105 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/ + * rlm_protection.c#1 + */ + +/*! \file "rlm_protection.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 + ******************************************************************************* + */ + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/roaming_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/roaming_fsm.c new file mode 100644 index 0000000000000..37a87a3819afd --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/roaming_fsm.c @@ -0,0 +1,816 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: + */ + +/*! \file "roaming_fsm.c" + * \brief This file defines the FSM for Roaming MODULE. + * + * This file defines the FSM for Roaming MODULE. + */ + + +/******************************************************************************* + * C O M P I L E 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 + ******************************************************************************* + */ +static uint8_t *apucDebugRoamingState[ROAMING_STATE_NUM] = { + (uint8_t *) DISP_STRING("IDLE"), + (uint8_t *) DISP_STRING("DECISION"), + (uint8_t *) DISP_STRING("DISCOVERY"), + (uint8_t *) DISP_STRING("REQ_CAND_LIST"), + (uint8_t *) DISP_STRING("ROAM") +}; + + +/******************************************************************************* + * M A 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 void roamingWaitCandidateTimeout(IN struct ADAPTER *prAdapter, + unsigned long ulParamPtr) +{ + uint8_t ucBssIndex = (uint8_t) ulParamPtr; + struct ROAMING_INFO *prRoamingFsmInfo; + + prRoamingFsmInfo = aisGetRoamingInfo(prAdapter, ucBssIndex); + if (prRoamingFsmInfo->eCurrentState == ROAMING_STATE_DECISION) { + aisResetNeighborApList(prAdapter, ucBssIndex); + aisSendNeighborRequest(prAdapter, ucBssIndex); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Initialize the value in ROAMING_FSM_INFO_T for ROAMING FSM operation + * + * @param [IN P_ADAPTER_T] prAdapter + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void roamingFsmInit(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIndex) +{ + struct ROAMING_INFO *prRoamingFsmInfo; + struct CONNECTION_SETTINGS *prConnSettings; + + DBGLOG(ROAMING, LOUD, + "[%d]->roamingFsmInit(): Current Time = %d\n", + ucBssIndex, + kalGetTimeTick()); + + prRoamingFsmInfo = + aisGetRoamingInfo(prAdapter, ucBssIndex); + prConnSettings = + aisGetConnSettings(prAdapter, ucBssIndex); + + /* 4 <1> Initiate FSM */ + prRoamingFsmInfo->fgIsEnableRoaming = + prConnSettings->fgIsEnableRoaming; + prRoamingFsmInfo->eCurrentState = ROAMING_STATE_IDLE; + prRoamingFsmInfo->rRoamingDiscoveryUpdateTime = 0; + prRoamingFsmInfo->fgDrvRoamingAllow = TRUE; + cnmTimerInitTimer(prAdapter, &prRoamingFsmInfo->rWaitCandidateTimer, + (PFN_MGMT_TIMEOUT_FUNC) roamingWaitCandidateTimeout, + (unsigned long) ucBssIndex); +} /* 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 struct ADAPTER *prAdapter, IN uint8_t ucBssIndex) +{ + struct ROAMING_INFO *prRoamingFsmInfo; + + DBGLOG(ROAMING, LOUD, + "[%d]->roamingFsmUninit(): Current Time = %d\n", + ucBssIndex, + kalGetTimeTick()); + + prRoamingFsmInfo = + aisGetRoamingInfo(prAdapter, ucBssIndex); + + prRoamingFsmInfo->eCurrentState = ROAMING_STATE_IDLE; + cnmTimerStopTimer(prAdapter, &prRoamingFsmInfo->rWaitCandidateTimer); +} /* 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 struct ADAPTER *prAdapter, + IN struct CMD_ROAMING_TRANSIT *prTransit) +{ + struct ROAMING_INFO *prRoamingFsmInfo; + uint32_t rStatus; + uint8_t ucBssIndex = prTransit->ucBssidx; + + DBGLOG(ROAMING, LOUD, + "[%d]->roamingFsmSendCmd(): Current Time = %d\n", + ucBssIndex, + kalGetTimeTick()); + + prRoamingFsmInfo = + aisGetRoamingInfo(prAdapter, ucBssIndex); + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_ROAMING_TRANSIT, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct CMD_ROAMING_TRANSIT), + /* u4SetQueryInfoLen */ + (uint8_t *)prTransit, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + /* ASSERT(rStatus == WLAN_STATUS_PENDING); */ +} /* end of roamingFsmSendCmd() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Update the recent time when ScanDone occurred + * + * @param [IN P_ADAPTER_T] prAdapter + * + * @return none + */ +/*----------------------------------------------------------------------------*/ +void roamingFsmScanResultsUpdate( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + DBGLOG(ROAMING, LOUD, + "[%d]->roamingFsmScanResultsUpdate(): Current Time = %d\n", + ucBssIndex, kalGetTimeTick()); + + /* try driver roaming */ + if (scanCheckNeedDriverRoaming(prAdapter, ucBssIndex)) { + struct ROAMING_INFO *roam; + + DBGLOG(ROAMING, INFO, "Request driver roaming"); + roam = aisGetRoamingInfo(prAdapter, ucBssIndex); + roam->eReason = ROAMING_REASON_INACTIVE; + aisFsmRemoveRoamingRequest(prAdapter, ucBssIndex); + aisFsmInsertRequest(prAdapter, + AIS_REQUEST_ROAMING_CONNECT, ucBssIndex); + } +} /* end of roamingFsmScanResultsUpdate() */ + +/*----------------------------------------------------------------------------*/ +/* + * @brief Check if need to do scan for roaming + * + * @param[out] fgIsNeedScan Set to TRUE if need to scan since + * there is roaming candidate in current scan result + * or skip roaming times > limit times + * @return + */ +/*----------------------------------------------------------------------------*/ +static u_int8_t roamingFsmIsNeedScan( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + struct AIS_SPECIFIC_BSS_INFO *asbi = NULL; + struct LINK *prEssLink = NULL; + u_int8_t fgIsNeedScan = TRUE; + + asbi = aisGetAisSpecBssInfo(prAdapter, ucBssIndex); + if (asbi == NULL) { + DBGLOG(ROAMING, WARN, "ais specific bss info is NULL\n"); + return TRUE; + } + + prEssLink = &asbi->rCurEssLink; + +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + /* + * Start skip roaming scan mechanism if only one ESSID AP + */ + if (prEssLink->u4NumElem == 1) { + struct BSS_DESC *prBssDesc; + + /* Get current BssDesc */ + prBssDesc = aisGetTargetBssDesc(prAdapter, ucBssIndex); + if (prBssDesc) { + DBGLOG(ROAMING, INFO, + "roamingFsmSteps: RCPI:%d RoamSkipTimes:%d\n", + prBssDesc->ucRCPI, asbi->ucRoamSkipTimes); + if (prBssDesc->ucRCPI > 90) { + /* Set parameters related to Good Area */ + asbi->ucRoamSkipTimes = 3; + asbi->fgGoodRcpiArea = TRUE; + asbi->fgPoorRcpiArea = FALSE; + } else { + if (asbi->fgGoodRcpiArea) { + asbi->ucRoamSkipTimes--; + } else if (prBssDesc->ucRCPI > 67) { + /*Set parameters related to Poor Area*/ + if (!asbi->fgPoorRcpiArea) { + asbi->ucRoamSkipTimes = 2; + asbi->fgPoorRcpiArea = TRUE; + asbi->fgGoodRcpiArea = FALSE; + } else { + asbi->ucRoamSkipTimes--; + } + } else { + asbi->fgPoorRcpiArea = FALSE; + asbi->fgGoodRcpiArea = FALSE; + asbi->ucRoamSkipTimes--; + } + } + + if (asbi->ucRoamSkipTimes == 0) { + asbi->ucRoamSkipTimes = 3; + asbi->fgPoorRcpiArea = FALSE; + asbi->fgGoodRcpiArea = FALSE; + DBGLOG(ROAMING, INFO, "Need Scan\n"); + } else { + struct CMD_ROAMING_SKIP_ONE_AP cmd = {0}; + + cmd.fgIsRoamingSkipOneAP = 1; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_ROAMING_SKIP, + TRUE, + FALSE, + FALSE, NULL, NULL, + sizeof(struct CMD_ROAMING_SKIP_ONE_AP), + (uint8_t *)&cmd, NULL, 0); + + fgIsNeedScan = FALSE; + } + } else { + DBGLOG(ROAMING, WARN, "Target BssDesc is NULL\n"); + } + } +#endif + + if (cnmP2pIsActive(prAdapter)) + fgIsNeedScan = FALSE; + + return fgIsNeedScan; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN enum ENUM_ROAMING_STATE eNextState, + IN uint8_t ucBssIndex) +{ + struct ROAMING_INFO *prRoamingFsmInfo; + enum ENUM_ROAMING_STATE ePreviousState; + u_int8_t fgIsTransition = (u_int8_t) FALSE; + u_int32_t u4ScnResultsTimeout = prAdapter->rWifiVar.u4DiscoverTimeout; + + prRoamingFsmInfo = aisGetRoamingInfo(prAdapter, ucBssIndex); + do { + + /* Do entering Next State */ + DBGLOG(ROAMING, STATE, + "[ROAMING%d] TRANSITION: [%s] -> [%s]\n", + ucBssIndex, + apucDebugRoamingState[prRoamingFsmInfo->eCurrentState], + apucDebugRoamingState[eNextState]); + + /* NOTE(Kevin): This is the only place to + * change the eCurrentState(except initial) + */ + ePreviousState = prRoamingFsmInfo->eCurrentState; + prRoamingFsmInfo->eCurrentState = eNextState; + + fgIsTransition = (u_int8_t) 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: + cnmTimerStopTimer( + prAdapter, + &prRoamingFsmInfo->rWaitCandidateTimer); + break; + case ROAMING_STATE_DECISION: +#if CFG_SUPPORT_DRIVER_ROAMING + GET_CURRENT_SYSTIME( + &prRoamingFsmInfo->rRoamingLastDecisionTime); +#endif + prRoamingFsmInfo->eReason = ROAMING_REASON_POOR_RCPI; + break; + + case ROAMING_STATE_DISCOVERY: { + OS_SYSTIME rCurrentTime; + u_int8_t fgIsNeedScan = FALSE; + +#if CFG_SUPPORT_NCHO + if (prAdapter->rNchoInfo.fgNCHOEnabled == TRUE) + u4ScnResultsTimeout = 0; +#endif + + GET_CURRENT_SYSTIME(&rCurrentTime); + if (CHECK_FOR_TIMEOUT(rCurrentTime, + prRoamingFsmInfo->rRoamingDiscoveryUpdateTime, + SEC_TO_SYSTIME(u4ScnResultsTimeout))) { + DBGLOG(ROAMING, LOUD, + "roamingFsmSteps: DiscoveryUpdateTime Timeout\n"); + + fgIsNeedScan = roamingFsmIsNeedScan(prAdapter, + ucBssIndex); + } + aisFsmRunEventRoamingDiscovery( + prAdapter, fgIsNeedScan, ucBssIndex); + } + break; + case ROAMING_STATE_REQ_CAND_LIST: + { +#if CFG_SUPPORT_802_11K + struct BSS_INFO *prBssInfo = + aisGetAisBssInfo(prAdapter, ucBssIndex); + struct BSS_DESC *prBssDesc = + aisGetTargetBssDesc(prAdapter, ucBssIndex); + /* if AP supports Neighbor AP report, then it can used + * to assist roaming candicate selection + */ + if (prBssInfo && prBssInfo->prStaRecOfAP) { + if (prBssDesc && + (prBssDesc->aucRrmCap[0] & + BIT(RRM_CAP_INFO_NEIGHBOR_REPORT_BIT))) { + cnmTimerStartTimer(prAdapter, + &prRoamingFsmInfo->rWaitCandidateTimer, + AIS_JOIN_CH_REQUEST_INTERVAL); + } + } +#endif + fgIsTransition = TRUE; + eNextState = ROAMING_STATE_DECISION; + 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 struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + struct ROAMING_INFO *prRoamingFsmInfo; + enum ENUM_ROAMING_STATE eNextState; + struct BSS_INFO *prAisBssInfo; + struct CMD_ROAMING_TRANSIT rTransit; + + prRoamingFsmInfo = + aisGetRoamingInfo(prAdapter, ucBssIndex); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + + prAisBssInfo = aisGetAisBssInfo(prAdapter, + ucBssIndex); + if (prAisBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + return; + + DBGLOG(ROAMING, EVENT, + "[%d] EVENT-ROAMING START: Current Time = %d\n", + ucBssIndex, + kalGetTimeTick()); + + /* IDLE, ROAM -> DECISION */ + /* Errors as DECISION, DISCOVERY -> DECISION */ + if (!(prRoamingFsmInfo->eCurrentState == ROAMING_STATE_IDLE + || prRoamingFsmInfo->eCurrentState == ROAMING_STATE_ROAM)) + return; + + eNextState = ROAMING_STATE_REQ_CAND_LIST; + if (eNextState != prRoamingFsmInfo->eCurrentState) { + rTransit.u2Event = ROAMING_EVENT_START; + rTransit.u2Data = prAisBssInfo->ucBssIndex; + rTransit.ucBssidx = ucBssIndex; + roamingFsmSendCmd(prAdapter, + (struct CMD_ROAMING_TRANSIT *) &rTransit); + + /* Step to next state */ + roamingFsmSteps(prAdapter, eNextState, ucBssIndex); + } +} /* 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 struct ADAPTER *prAdapter, + IN struct CMD_ROAMING_TRANSIT *prTransit) +{ + struct ROAMING_INFO *prRoamingFsmInfo; + enum ENUM_ROAMING_STATE eNextState; + uint8_t ucBssIndex = prTransit->ucBssidx; + + prRoamingFsmInfo = + aisGetRoamingInfo(prAdapter, ucBssIndex); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + DBGLOG(ROAMING, EVENT, + "[%d] EVENT-ROAMING DISCOVERY: Current Time = %d\n", + ucBssIndex, + 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) { + struct BSS_INFO *prAisBssInfo; + struct BSS_DESC *prBssDesc; + struct BSS_DESC *prBssDescTarget; + uint8_t arBssid[PARAM_MAC_ADDR_LEN]; + struct PARAM_SSID rSsid; + struct AIS_FSM_INFO *prAisFsmInfo; + struct CONNECTION_SETTINGS *prConnSettings; + + kalMemZero(&rSsid, sizeof(struct PARAM_SSID)); + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, ucBssIndex); + prConnSettings = + aisGetConnSettings(prAdapter, ucBssIndex); + + /* sync. rcpi with firmware */ + prAisBssInfo = + &(prAdapter->rWifiVar.arBssInfoPool[NETWORK_TYPE_AIS]); + prBssDesc = prAisFsmInfo->prTargetBssDesc; + if (prBssDesc) { + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + COPY_MAC_ADDR(arBssid, prBssDesc->aucBSSID); + } else { + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, + prConnSettings->aucSSID, + prConnSettings->ucSSIDLen); + COPY_MAC_ADDR(arBssid, prConnSettings->aucBSSID); + } + + prRoamingFsmInfo->ucRcpi = (uint8_t)(prTransit->u2Data & 0xff); + prRoamingFsmInfo->ucThreshold = prTransit->u2RcpiLowThreshold; + + prBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, + arBssid, TRUE, &rSsid); + if (prBssDesc) { + prBssDesc->ucRCPI = prRoamingFsmInfo->ucRcpi; + DBGLOG(ROAMING, INFO, "RCPI %u(%d)\n", + prBssDesc->ucRCPI, RCPI_TO_dBm(prBssDesc->ucRCPI)); + } + + prBssDescTarget = aisGetTargetBssDesc(prAdapter, ucBssIndex); + if (prBssDescTarget && prBssDescTarget != prBssDesc) { + prBssDescTarget->ucRCPI = prRoamingFsmInfo->ucRcpi; + DBGLOG(ROAMING, WARN, "update target bss\n"); + } + + /* Save roaming reason code and PER value for AP selection */ + prRoamingFsmInfo->eReason = prTransit->eReason; + if (prTransit->eReason == ROAMING_REASON_TX_ERR) { + prRoamingFsmInfo->ucPER = + (prTransit->u2Data >> 8) & 0xff; + DBGLOG(ROAMING, INFO, "ucPER %u\n", + prRoamingFsmInfo->ucPER); + } else { + prRoamingFsmInfo->ucPER = 0; + } + +#if CFG_SUPPORT_NCHO + if (prRoamingFsmInfo->eReason == ROAMING_REASON_RETRY) + DBGLOG(ROAMING, INFO, + "NCHO enable=%d,trigger=%d,delta=%d,period=%d\n", + prAdapter->rNchoInfo.fgNCHOEnabled, + prAdapter->rNchoInfo.i4RoamTrigger, + prAdapter->rNchoInfo.i4RoamDelta, + prAdapter->rNchoInfo.u4RoamScanPeriod); +#endif + + roamingFsmSteps(prAdapter, eNextState, ucBssIndex); + } +} /* end of roamingFsmRunEventDiscovery() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Transit to Roam state after Scan Done + * + * @param [IN P_ADAPTER_T] prAdapter + * + * @return none + */ +/*----------------------------------------------------------------------------*/ +void roamingFsmRunEventRoam(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + struct ROAMING_INFO *prRoamingFsmInfo; + enum ENUM_ROAMING_STATE eNextState; + struct CMD_ROAMING_TRANSIT rTransit; + + prRoamingFsmInfo = + aisGetRoamingInfo(prAdapter, ucBssIndex); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + + DBGLOG(ROAMING, EVENT, + "[%d] EVENT-ROAMING ROAM: Current Time = %d\n", + ucBssIndex, + 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) { + rTransit.u2Event = ROAMING_EVENT_ROAM; + rTransit.ucBssidx = ucBssIndex; + roamingFsmSendCmd(prAdapter, + (struct CMD_ROAMING_TRANSIT *) &rTransit); + + /* Step to next state */ + roamingFsmSteps(prAdapter, eNextState, ucBssIndex); + } +} /* 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 struct ADAPTER *prAdapter, + IN uint32_t u4Param, IN uint8_t ucBssIndex) +{ + struct ROAMING_INFO *prRoamingFsmInfo; + enum ENUM_ROAMING_STATE eNextState; + struct CMD_ROAMING_TRANSIT rTransit; + + prRoamingFsmInfo = + aisGetRoamingInfo(prAdapter, ucBssIndex); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + + DBGLOG(ROAMING, STATE, + "[%d] EVENT-ROAMING FAIL: reason %x Current Time = %d\n", + ucBssIndex, + 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) { + rTransit.u2Event = ROAMING_EVENT_FAIL; + rTransit.u2Data = (uint16_t) (u4Param & 0xffff); + rTransit.ucBssidx = ucBssIndex; + roamingFsmSendCmd(prAdapter, + (struct CMD_ROAMING_TRANSIT *) &rTransit); + + /* Step to next state */ + roamingFsmSteps(prAdapter, eNextState, ucBssIndex); + } +} /* 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 struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + struct ROAMING_INFO *prRoamingFsmInfo; + enum ENUM_ROAMING_STATE eNextState; + struct CMD_ROAMING_TRANSIT rTransit; + + prRoamingFsmInfo = + aisGetRoamingInfo(prAdapter, ucBssIndex); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + + DBGLOG(ROAMING, EVENT, + "[%d] EVENT-ROAMING ABORT: Current Time = %d\n", + ucBssIndex, + kalGetTimeTick()); + + eNextState = ROAMING_STATE_IDLE; + /* IDLE, DECISION, DISCOVERY, ROAM -> IDLE */ + if (eNextState != prRoamingFsmInfo->eCurrentState) { + rTransit.u2Event = ROAMING_EVENT_ABORT; + rTransit.ucBssidx = ucBssIndex; + roamingFsmSendCmd(prAdapter, + (struct CMD_ROAMING_TRANSIT *) &rTransit); + + /* Step to next state */ + roamingFsmSteps(prAdapter, eNextState, ucBssIndex); + } +} /* end of roamingFsmRunEventAbort() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Process events from firmware + * + * @param [IN P_ADAPTER_T] prAdapter + * [IN P_ROAMING_PARAM_T] prParam + * + * @return none + */ +/*----------------------------------------------------------------------------*/ +uint32_t roamingFsmProcessEvent(IN struct ADAPTER *prAdapter, + IN struct CMD_ROAMING_TRANSIT *prTransit) +{ + uint8_t ucBssIndex = prTransit->ucBssidx; + + DBGLOG(ROAMING, LOUD, + "[%d] ROAMING Process Events: Current Time = %d\n", + ucBssIndex, + kalGetTimeTick()); + + if (prTransit->u2Event == ROAMING_EVENT_DISCOVERY) { + DBGLOG(ROAMING, INFO, + "ROAMING_EVENT_DISCOVERY Data[%d] RCPI[%d(%d)] PER[%d] Thr[%d(%d)] Reason[%d] Time[%ld]\n", + prTransit->u2Data, + (prTransit->u2Data) & 0xff, /* L[8], RCPI */ + RCPI_TO_dBm((prTransit->u2Data) & 0xff), + (prTransit->u2Data >> 8) & 0xff, /* H[8], PER */ + prTransit->u2RcpiLowThreshold, + RCPI_TO_dBm(prTransit->u2RcpiLowThreshold), + prTransit->eReason, + prTransit->u4RoamingTriggerTime); + roamingFsmRunEventDiscovery(prAdapter, prTransit); + } else if (prTransit->u2Event == ROAMING_EVENT_THRESHOLD_UPDATE) { + DBGLOG(ROAMING, INFO, + "ROAMING_EVENT_THRESHOLD_UPDATE RCPI H[%d(%d)] L[%d(%d)]\n", + prTransit->u2RcpiHighThreshold, + RCPI_TO_dBm(prTransit->u2RcpiHighThreshold), + prTransit->u2RcpiLowThreshold, + RCPI_TO_dBm(prTransit->u2RcpiLowThreshold)); + } + + return WLAN_STATUS_SUCCESS; +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rrm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rrm.c new file mode 100644 index 0000000000000..0ebbcfbcec1ad --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rrm.c @@ -0,0 +1,1667 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +/******************************************************************************* + * C O M P I L E 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 + ******************************************************************************* + */ + +struct TIMER rBeaconReqTimer; + +struct REF_TSF { + uint32_t au4Tsf[2]; + OS_SYSTIME rTime; +}; +static struct REF_TSF rTsf; + +/******************************************************************************* + * M A 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 u_int8_t rrmAllMeasurementIssued( + struct RADIO_MEASUREMENT_REQ_PARAMS *prReq); + +static void rrmCalibrateRepetions( + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq); + +static void rrmHandleBeaconReqSubelem( + IN struct ADAPTER *prAdapter, IN uint8_t ucBssIndex); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rrmParamInit(struct ADAPTER *prAdapter, uint8_t ucBssIndex) +{ + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReqParam = + aisGetRmReqParam(prAdapter, ucBssIndex); + struct RADIO_MEASUREMENT_REPORT_PARAMS *prRmRepParam = + aisGetRmReportParam(prAdapter, ucBssIndex); + + kalMemZero(prRmRepParam, sizeof(*prRmRepParam)); + kalMemZero(prRmReqParam, sizeof(*prRmReqParam)); + prRmReqParam->rBcnRmParam.eState = RM_NO_REQUEST; + prRmReqParam->fgRmIsOngoing = FALSE; + LINK_INITIALIZE(&prRmRepParam->rReportLink); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rrmParamUninit(struct ADAPTER *prAdapter, uint8_t ucBssIndex) +{ + rrmFreeMeasurementResources(prAdapter, ucBssIndex); +} + +void rrmProcessNeighborReportResonse(struct ADAPTER *prAdapter, + struct WLAN_ACTION_FRAME *prAction, + struct SW_RFB *prSwRfb) +{ + struct ACTION_NEIGHBOR_REPORT_FRAME *prNeighborResponse = + (struct ACTION_NEIGHBOR_REPORT_FRAME *)prAction; + uint8_t ucBssIndex = secGetBssIdxByRfb(prAdapter, + prSwRfb); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + ASSERT(prNeighborResponse); + + DBGLOG(RRM, INFO, + "[%d] Neighbor Resp From " MACSTR ", DialogToken %d\n", + ucBssIndex, + MAC2STR(prNeighborResponse->aucSrcAddr), + prNeighborResponse->ucDialogToken); +#if CFG_SUPPORT_802_11K + aisCollectNeighborAP( + prAdapter, &prNeighborResponse->aucInfoElem[0], + prSwRfb->u2PacketLen + - OFFSET_OF(struct ACTION_NEIGHBOR_REPORT_FRAME, + aucInfoElem), + 0, + ucBssIndex); +#endif +} + +void rrmTxNeighborReportRequest(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + struct SUB_ELEMENT_LIST *prSubIEs) +{ + static uint8_t ucDialogToken = 1; + struct MSDU_INFO *prMsduInfo = NULL; + struct BSS_INFO *prBssInfo = NULL; + uint8_t *pucPayload = NULL; + struct ACTION_NEIGHBOR_REPORT_FRAME *prTxFrame = NULL; + uint16_t u2TxFrameLen = 500; + uint16_t u2FrameLen = 0; + + if (!prStaRec) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + ASSERT(prBssInfo); + /* 1 Allocate MSDU Info */ + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc( + prAdapter, MAC_TX_RESERVED_FIELD + u2TxFrameLen); + if (!prMsduInfo) + return; + prTxFrame = (struct ACTION_NEIGHBOR_REPORT_FRAME + *)((unsigned long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + + /* 2 Compose The Mac Header. */ + 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_RM_ACTION; + prTxFrame->ucAction = RM_ACTION_NEIGHBOR_REQUEST; + u2FrameLen = + OFFSET_OF(struct ACTION_NEIGHBOR_REPORT_FRAME, aucInfoElem); + /* 3 Compose the frame body's frame. */ + prTxFrame->ucDialogToken = ucDialogToken++; + u2TxFrameLen -= sizeof(*prTxFrame) - 1; + pucPayload = &prTxFrame->aucInfoElem[0]; + while (prSubIEs && u2TxFrameLen >= (prSubIEs->rSubIE.ucLength + 2)) { + kalMemCopy(pucPayload, &prSubIEs->rSubIE, + prSubIEs->rSubIE.ucLength + 2); + pucPayload += prSubIEs->rSubIE.ucLength + 2; + u2FrameLen += prSubIEs->rSubIE.ucLength + 2; + prSubIEs = prSubIEs->prNext; + } + nicTxSetMngPacket(prAdapter, prMsduInfo, prStaRec->ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_MGMT_HEADER_LEN, + u2FrameLen, NULL, MSDU_RATE_MODE_AUTO); + + /* 5 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); +} + +void rrmFreeMeasurementResources(struct ADAPTER *prAdapter, + uint8_t ucBssIndex) +{ + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq = + aisGetRmReqParam(prAdapter, ucBssIndex); + struct RADIO_MEASUREMENT_REPORT_PARAMS *prRmRep = + aisGetRmReportParam(prAdapter, ucBssIndex); + struct RM_MEASURE_REPORT_ENTRY *prReportEntry = NULL; + struct LINK *prReportLink = &prRmRep->rReportLink; + u_int8_t fgHasBcnReqTimer = timerPendingTimer(&rBeaconReqTimer); + + DBGLOG(RRM, TRACE, "Free measurement, Beacon Req timer is %d\n", + fgHasBcnReqTimer); + if (fgHasBcnReqTimer) + cnmTimerStopTimer(prAdapter, &rBeaconReqTimer); + + kalMemFree(prRmReq->pucReqIeBuf, VIR_MEM_TYPE, prRmReq->u2ReqIeBufLen); + kalMemFree(prRmRep->pucReportFrameBuff, VIR_MEM_TYPE, + RM_REPORT_FRAME_MAX_LENGTH); + while (!LINK_IS_EMPTY(prReportLink)) { + LINK_REMOVE_HEAD(prReportLink, prReportEntry, + struct RM_MEASURE_REPORT_ENTRY *); + kalMemFree(prReportEntry->pucMeasReport, + VIR_MEM_TYPE, prReportEntry->u2MeasReportLen); + kalMemFree(prReportEntry, VIR_MEM_TYPE, sizeof(*prReportEntry)); + } + kalMemZero(prRmReq, sizeof(*prRmReq)); + kalMemZero(prRmRep, sizeof(*prRmRep)); + prRmReq->rBcnRmParam.eState = RM_NO_REQUEST; + prRmReq->fgRmIsOngoing = FALSE; + LINK_INITIALIZE(&prRmRep->rReportLink); +} + +/* purpose: check if Radio Measurement is done */ +static u_int8_t rrmAllMeasurementIssued( + struct RADIO_MEASUREMENT_REQ_PARAMS *prReq) +{ + return prReq->u2RemainReqLen > IE_SIZE(prReq->prCurrMeasElem) ? FALSE + : TRUE; +} + +void rrmComposeIncapableRmRep(struct RADIO_MEASUREMENT_REPORT_PARAMS *prRep, + uint8_t ucToken, uint8_t ucMeasType) +{ + struct IE_MEASUREMENT_REPORT *prRepIE = + (struct IE_MEASUREMENT_REPORT *)(prRep->pucReportFrameBuff + + prRep->u2ReportFrameLen); + + prRepIE->ucId = ELEM_ID_MEASUREMENT_REPORT; + prRepIE->ucToken = ucToken; + prRepIE->ucMeasurementType = ucMeasType; + prRepIE->ucLength = 3; + prRepIE->ucReportMode = RM_REP_MODE_INCAPABLE; + prRep->u2ReportFrameLen += 5; +} + +int rrmBeaconRepUpdateLastFrame(struct ADAPTER *prAdapter, + uint8_t ucBssIndex) +{ + struct RADIO_MEASUREMENT_REQ_PARAMS *rmReqParam = + aisGetRmReqParam(prAdapter, ucBssIndex); + struct RADIO_MEASUREMENT_REPORT_PARAMS *prRmRepParam = + aisGetRmReportParam(prAdapter, ucBssIndex); + struct IE_MEASUREMENT_REQ *request = rmReqParam->prCurrMeasElem; + uint8_t *pos = prRmRepParam->pucReportFrameBuff + + OFFSET_OF(struct ACTION_RM_REPORT_FRAME, aucInfoElem); + size_t len = prRmRepParam->u2ReportFrameLen - + OFFSET_OF(struct ACTION_RM_REPORT_FRAME, aucInfoElem); + struct IE_MEASUREMENT_REPORT *msr_rep; + uint8_t *end = pos + len; + uint8_t *msr_rep_end; + struct RM_BCN_REPORT *rep = NULL; + uint8_t *subelem; + + if (request->ucMeasurementType != ELEM_RM_TYPE_BEACON_REQ) + return -EINVAL; + + /* Find the last beacon report element */ + while (end - pos >= (int) sizeof(*msr_rep)) { + msr_rep = (struct IE_MEASUREMENT_REPORT *) pos; + msr_rep_end = pos + msr_rep->ucLength + 2; + + if (msr_rep->ucId != ELEM_ID_MEASUREMENT_REPORT || + msr_rep_end > end) { +#define TEMP_LOG_TEMPLATE \ + "non-measurement report element in measurement report frame\n" + /* Should not happen. This indicates a bug. */ + DBGLOG(RRM, ERROR, TEMP_LOG_TEMPLATE); +#undef TEMP_LOG_TEMPLATE + return -EINVAL; + } + + if (msr_rep->ucMeasurementType == ELEM_RM_TYPE_BEACON_REPORT) + rep = (struct RM_BCN_REPORT *) + msr_rep->aucReportFields; + + pos += pos[1] + 2; + } + + if (!rep) + return 0; + + subelem = rep->aucOptElem; + while (subelem + 2 < msr_rep_end && + subelem[0] != BEACON_REPORT_SUBELEM_LAST_INDICATION) + subelem += 2 + subelem[1]; + + if (subelem + 2 < msr_rep_end && + subelem[0] == BEACON_REPORT_SUBELEM_LAST_INDICATION && + subelem[1] == 1 && + subelem + BEACON_REPORT_LAST_INDICATION_SUBELEM_LEN <= end) { + subelem[2] = 1; + DBGLOG(RRM, INFO, "update last indication subelem\n"); + } + + return 0; +} + +/* Purpose: Interative processing Measurement Request Element. If it is not the + ** first element, + ** will copy all collected report element to the report frame buffer. and + ** may tx the radio report frame. + ** prAdapter: pointer to the Adapter + ** fgNewStarted: if it is the first element in measurement request frame + */ +void rrmStartNextMeasurement(struct ADAPTER *prAdapter, u_int8_t fgNewStarted, + uint8_t ucBssIndex) +{ + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq = + aisGetRmReqParam(prAdapter, ucBssIndex); + struct RADIO_MEASUREMENT_REPORT_PARAMS *prRmRep = + aisGetRmReportParam(prAdapter, ucBssIndex); + struct IE_MEASUREMENT_REQ *prCurrReq = prRmReq->prCurrMeasElem; + uint16_t u2RandomTime = 0; + +schedule_next: + if (!prRmReq->fgRmIsOngoing) { + DBGLOG(RRM, INFO, "Rm has been stopped\n"); + return; + } + /* we don't support parallel measurement now */ + if (prCurrReq->ucRequestMode & RM_REQ_MODE_PARALLEL_BIT) { + DBGLOG(RRM, WARN, + "Parallel request, compose incapable report\n"); + if (prRmRep->u2ReportFrameLen + 5 > RM_REPORT_FRAME_MAX_LENGTH) + rrmTxRadioMeasurementReport(prAdapter, ucBssIndex); + rrmComposeIncapableRmRep(prRmRep, prCurrReq->ucToken, + prCurrReq->ucMeasurementType); + if (rrmAllMeasurementIssued(prRmReq)) { + rrmTxRadioMeasurementReport(prAdapter, ucBssIndex); + + /* repeat measurement if repetitions is required and not + * only parallel measurements. + * otherwise, no need to repeat, it is not make sense to + * do that. + */ + if (prRmReq->u2Repetitions > 0) { + prRmReq->fgInitialLoop = FALSE; + prRmReq->u2Repetitions--; + prCurrReq = prRmReq->prCurrMeasElem = + (struct IE_MEASUREMENT_REQ *) + prRmReq->pucReqIeBuf; + prRmReq->u2RemainReqLen = + prRmReq->u2ReqIeBufLen; + rrmHandleBeaconReqSubelem( + prAdapter, ucBssIndex); + } else { + rrmFreeMeasurementResources(prAdapter, + ucBssIndex); + DBGLOG(RRM, INFO, + "Radio Measurement done\n"); + return; + } + } else { + uint16_t u2IeSize = IE_SIZE(prRmReq->prCurrMeasElem); + + prCurrReq = prRmReq->prCurrMeasElem = + (struct IE_MEASUREMENT_REQ + *)((uint8_t *)prRmReq->prCurrMeasElem + + u2IeSize); + prRmReq->u2RemainReqLen -= u2IeSize; + rrmHandleBeaconReqSubelem( + prAdapter, ucBssIndex); + } + fgNewStarted = FALSE; + goto schedule_next; + } + /* copy collected measurement report for specific measurement type */ + if (!fgNewStarted) { + struct RM_MEASURE_REPORT_ENTRY *prReportEntry = NULL; + struct LINK *prReportLink = &prRmRep->rReportLink; + uint8_t *pucReportFrame = + prRmRep->pucReportFrameBuff + prRmRep->u2ReportFrameLen; + uint16_t u2IeSize = 0; + u_int8_t fgNewLoop = FALSE; + + DBGLOG(RRM, INFO, + "total %u report element for current request\n", + prReportLink->u4NumElem); + /* copy collected report into the Measurement Report Frame + ** Buffer. + */ + while (1) { + LINK_REMOVE_HEAD(prReportLink, prReportEntry, + struct RM_MEASURE_REPORT_ENTRY *); + if (!prReportEntry) + break; + u2IeSize = prReportEntry->u2MeasReportLen; + /* if reach the max length of a MMPDU size, send a Rm + ** report first + */ + if (u2IeSize + prRmRep->u2ReportFrameLen > + RM_REPORT_FRAME_MAX_LENGTH) { + rrmTxRadioMeasurementReport(prAdapter, + ucBssIndex); + pucReportFrame = prRmRep->pucReportFrameBuff + + prRmRep->u2ReportFrameLen; + } + kalMemCopy(pucReportFrame, prReportEntry->pucMeasReport, + u2IeSize); + pucReportFrame += u2IeSize; + prRmRep->u2ReportFrameLen += u2IeSize; + + kalMemFree(prReportEntry->pucMeasReport, + VIR_MEM_TYPE, u2IeSize); + kalMemFree(prReportEntry, + VIR_MEM_TYPE, sizeof(*prReportEntry)); + } + rrmBeaconRepUpdateLastFrame(prAdapter, ucBssIndex); + /* if Measurement is done, free report element memory */ + if (rrmAllMeasurementIssued(prRmReq)) { + rrmTxRadioMeasurementReport(prAdapter, ucBssIndex); + /* repeat measurement if repetitions is required */ + if (prRmReq->u2Repetitions > 0) { + fgNewLoop = TRUE; + prRmReq->fgInitialLoop = FALSE; + prRmReq->u2Repetitions--; + prRmReq->prCurrMeasElem = + (struct IE_MEASUREMENT_REQ *) + prRmReq->pucReqIeBuf; + prRmReq->u2RemainReqLen = + prRmReq->u2ReqIeBufLen; + rrmHandleBeaconReqSubelem( + prAdapter, ucBssIndex); + } else { + /* don't free radio measurement resource due to + ** TSM is running + */ + if (!wmmTsmIsOngoing(prAdapter, ucBssIndex)) { + rrmFreeMeasurementResources(prAdapter, + ucBssIndex); + DBGLOG(RRM, INFO, + "Radio Measurement done\n"); + } + return; + } + } + if (!fgNewLoop) { + u2IeSize = IE_SIZE(prRmReq->prCurrMeasElem); + prCurrReq = prRmReq->prCurrMeasElem = + (struct IE_MEASUREMENT_REQ + *)((uint8_t *)prRmReq->prCurrMeasElem + + u2IeSize); + prRmReq->u2RemainReqLen -= u2IeSize; + rrmHandleBeaconReqSubelem(prAdapter, ucBssIndex); + } + } + + /* do specific measurement */ + switch (prCurrReq->ucMeasurementType) { + case ELEM_RM_TYPE_BEACON_REQ: { + struct RM_BCN_REQ *prBeaconReq = + (struct RM_BCN_REQ *)&prCurrReq->aucRequestFields[0]; + + if (!prRmReq->fgInitialLoop) { + /* If this is the repeating measurement, then wait next + ** scan done + */ + prRmReq->rBcnRmParam.eState = RM_WAITING; + break; + } + if (prBeaconReq->u2RandomInterval == 0) + rrmDoBeaconMeasurement(prAdapter, ucBssIndex); + else { + get_random_bytes(&u2RandomTime, 2); + u2RandomTime = + (u2RandomTime * prBeaconReq->u2RandomInterval) / + 65535; + u2RandomTime = TU_TO_MSEC(u2RandomTime); + if (u2RandomTime > 0) { + cnmTimerStopTimer(prAdapter, &rBeaconReqTimer); + cnmTimerInitTimer(prAdapter, &rBeaconReqTimer, + rrmDoBeaconMeasurement, ucBssIndex); + cnmTimerStartTimer(prAdapter, &rBeaconReqTimer, + u2RandomTime); + } else + rrmDoBeaconMeasurement(prAdapter, ucBssIndex); + } + break; + } +#if 0 + case ELEM_RM_TYPE_TSM_REQ: + { + struct RM_TS_MEASURE_REQ *prTsmReqIE = + (struct RM_TS_MEASURE_REQ *) + &prCurrReq->aucRequestFields[0]; + struct RM_TSM_REQ *prTsmReq = NULL; + uint16_t u2OffSet = 0; + uint8_t *pucIE = prTsmReqIE->aucSubElements; + struct ACTION_RM_REPORT_FRAME *prReportFrame = NULL; + + /* In case of repeating measurement, no need to start + ** triggered measurement again. According to current + ** specification of Radio Measurement, only TSM has the + ** triggered type of measurement. + */ + if ((prCurrReq->ucRequestMode & RM_REQ_MODE_ENABLE_BIT) && + !prRmReq->fgInitialLoop) + goto schedule_next; + + /* if enable bit is 1 and report bit is 0, need to stop all + ** triggered TSM measurement + */ + if ((prCurrReq->ucRequestMode & + (RM_REQ_MODE_ENABLE_BIT|RM_REQ_MODE_REPORT_BIT)) == + RM_REQ_MODE_ENABLE_BIT) { + wmmRemoveAllTsmMeasurement(prAdapter, TRUE); + break; + } + prTsmReq = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, + sizeof(struct RM_TSM_REQ)); + if (!prTsmReq) { + DBGLOG(RLM, ERROR, "No memory\n"); + break; + } + prTsmReq->ucToken = prCurrReq->ucToken; + prTsmReq->u2Duration = prTsmReqIE->u2Duration; + prTsmReq->ucTID = (prTsmReqIE->ucTrafficID & 0xf0) >> 4; + prTsmReq->ucB0Range = prTsmReqIE->ucBin0Range; + prReportFrame = (struct ACTION_RM_REPORT_FRAME *) + prRmRep->pucReportFrameBuff; + COPY_MAC_ADDR(prTsmReq->aucPeerAddr, + prReportFrame->aucDestAddr); + IE_FOR_EACH(pucIE, prCurrReq->ucLength - 3, u2OffSet) { + switch (IE_ID(pucIE)) { + case 1: /* Triggered Reporting */ + kalMemCopy(&prTsmReq->rTriggerCond, + pucIE+2, IE_LEN(pucIE)); + break; + case 221: /* Vendor Specified */ + break; /* No vendor IE now */ + default: + break; + } + } + if (!prTsmReqIE->u2RandomInterval) { + wmmStartTsmMeasurement(prAdapter, + (unsigned long)prTsmReq); + break; + } + get_random_bytes(&u2RandomTime, 2); + u2RandomTime = + (u2RandomTime * prTsmReqIE->u2RandomInterval) / 65535; + u2RandomTime = TU_TO_MSEC(u2RandomTime); + cnmTimerStopTimer(prAdapter, &rTSMReqTimer); + cnmTimerInitTimer(prAdapter, &rTSMReqTimer, + wmmStartTsmMeasurement, (unsigned long)prTsmReq); + cnmTimerStartTimer(prAdapter, &rTSMReqTimer, u2RandomTime); + break; + } +#endif + default: { + if (prRmRep->u2ReportFrameLen + 5 > RM_REPORT_FRAME_MAX_LENGTH) + rrmTxRadioMeasurementReport(prAdapter, + ucBssIndex); + rrmComposeIncapableRmRep(prRmRep, prCurrReq->ucToken, + prCurrReq->ucMeasurementType); + fgNewStarted = FALSE; + DBGLOG(RRM, INFO, + "RM type %d is not supported on this chip\n", + prCurrReq->ucMeasurementType); + goto schedule_next; + } + } +} + +u_int8_t rrmFillScanMsg(struct ADAPTER *prAdapter, + struct MSG_SCN_SCAN_REQ_V2 *prMsg) +{ + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq = NULL; + struct IE_MEASUREMENT_REQ *prCurrReq = NULL; + struct RM_BCN_REQ *prBeaconReq = NULL; + uint16_t u2RemainLen = 0; + uint8_t *pucSubIE = NULL; + + static struct PARAM_SSID rBcnReqSsid; + + if (!prMsg) + return FALSE; + + prRmReq = aisGetRmReqParam(prAdapter, + prMsg->ucBssIndex); + + if (prRmReq->rBcnRmParam.eState != RM_ON_GOING) + return FALSE; + + prCurrReq = prRmReq->prCurrMeasElem; + prBeaconReq = (struct RM_BCN_REQ *)&prCurrReq->aucRequestFields[0]; + prMsg->ucSSIDType = SCAN_REQ_SSID_WILDCARD; + switch (prBeaconReq->ucMeasurementMode) { + case RM_BCN_REQ_PASSIVE_MODE: + prMsg->eScanType = SCAN_TYPE_PASSIVE_SCAN; + break; + case RM_BCN_REQ_ACTIVE_MODE: + prMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; + break; + default: + DBGLOG(RRM, WARN, + "Unexpect measure mode %d, use active mode as default\n", + prBeaconReq->ucMeasurementMode); + prMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; + break; + } + + WLAN_GET_FIELD_16(&prBeaconReq->u2Duration, &prMsg->u2ChannelDwellTime); + + COPY_MAC_ADDR(prMsg->aucBSSID, prBeaconReq->aucBssid); + + prMsg->u2ProbeDelay = 0; + prMsg->u2TimeoutValue = 0; + prMsg->ucSSIDNum = 0; + prMsg->u2IELen = 0; + /* if mandatory bit is set, we should do */ + if (prCurrReq->ucRequestMode & RM_REQ_MODE_DURATION_MANDATORY_BIT) + prMsg->u2ChannelMinDwellTime = prMsg->u2ChannelDwellTime; + else + prMsg->u2ChannelMinDwellTime = + (prMsg->u2ChannelDwellTime * 2) / 3; + if (prBeaconReq->ucChannel == 0) + prMsg->eScanChannel = SCAN_CHANNEL_FULL; + else if (prBeaconReq->ucChannel == 255) { /* latest Ap Channel Report */ + struct BSS_DESC *prBssDesc = + aisGetTargetBssDesc(prAdapter, + prMsg->ucBssIndex); + uint8_t *pucChnl = NULL; + uint8_t ucChnlNum = 0; + uint8_t ucIndex = 0; + struct RF_CHANNEL_INFO *prChnlInfo = prMsg->arChnlInfoList; + + prMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; + prMsg->ucChannelListNum = 0; + if (prBssDesc) { + uint8_t *pucIE = NULL; + uint16_t u2IELength = 0; + uint16_t u2Offset = 0; + + pucIE = prBssDesc->aucIEBuf; + u2IELength = prBssDesc->u2IELength; + IE_FOR_EACH(pucIE, u2IELength, u2Offset) + { + if (IE_ID(pucIE) != ELEM_ID_AP_CHANNEL_REPORT) + continue; + pucChnl = ((struct IE_AP_CHNL_REPORT *)pucIE) + ->aucChnlList; + ucChnlNum = pucIE[1] - 1; + DBGLOG(RRM, INFO, + "Channel number in latest AP channel report %d\n", + ucChnlNum); + while (ucIndex < ucChnlNum && + prMsg->ucChannelListNum < + MAXIMUM_OPERATION_CHANNEL_LIST) { + if (pucChnl[ucIndex] <= 14) + prChnlInfo + [prMsg->ucChannelListNum] + .eBand = + BAND_2G4; + else + prChnlInfo + [prMsg->ucChannelListNum] + .eBand = + BAND_5G; + prChnlInfo[prMsg->ucChannelListNum] + .ucChannelNum = + pucChnl[ucIndex]; + prMsg->ucChannelListNum++; + ucIndex++; + } + } + } + } else { + prMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; + prMsg->ucChannelListNum = 1; + prMsg->arChnlInfoList[0].ucChannelNum = prBeaconReq->ucChannel; + if (prBeaconReq->ucChannel <= 14) + prMsg->arChnlInfoList[0].eBand = BAND_2G4; + else + prMsg->arChnlInfoList[0].eBand = BAND_5G; + } + u2RemainLen = prCurrReq->ucLength - 3 - + OFFSET_OF(struct RM_BCN_REQ, aucSubElements); + pucSubIE = &prBeaconReq->aucSubElements[0]; + while (u2RemainLen > 0) { + if (IE_SIZE(pucSubIE) > u2RemainLen) + break; + switch (pucSubIE[0]) { + case BEACON_REQUEST_SUBELEM_SSID: /* SSID */ + /* length of sub-element ssid is 0 or first byte is 0, + ** means wildcard ssid matching + */ + if (!IE_LEN(pucSubIE) || !pucSubIE[2]) + break; + prMsg->ucSSIDNum = 1; + prMsg->prSsid = &rBcnReqSsid; + COPY_SSID(&rBcnReqSsid.aucSsid[0], + rBcnReqSsid.u4SsidLen, &pucSubIE[2], + pucSubIE[1]); + prMsg->ucSSIDType = SCAN_REQ_SSID_SPECIFIED_ONLY; + break; + case BEACON_REQUEST_SUBELEM_AP_CHANNEL: /* AP channel report */ + { + struct IE_AP_CHNL_REPORT *prApChnl = + (struct IE_AP_CHNL_REPORT *)pucSubIE; + uint8_t ucChannelCnt = prApChnl->ucLength - 1; + uint8_t ucIndex = 0; + + if (prBeaconReq->ucChannel == 0) + break; + prMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; + DBGLOG(RRM, INFO, + "Channel number in measurement AP channel report %d\n", + ucChannelCnt); + while (ucIndex < ucChannelCnt && + prMsg->ucChannelListNum < + MAXIMUM_OPERATION_CHANNEL_LIST) { + if (prApChnl->aucChnlList[ucIndex] <= 14) + prMsg->arChnlInfoList + [prMsg->ucChannelListNum] + .eBand = BAND_2G4; + else + prMsg->arChnlInfoList + [prMsg->ucChannelListNum] + .eBand = BAND_5G; + prMsg->arChnlInfoList[prMsg->ucChannelListNum] + .ucChannelNum = + prApChnl->aucChnlList[ucIndex]; + prMsg->ucChannelListNum++; + ucIndex++; + } + break; + } + } + u2RemainLen -= IE_SIZE(pucSubIE); + pucSubIE += IE_SIZE(pucSubIE); + } + + GET_CURRENT_SYSTIME(&prRmReq->rScanStartTime); + DBGLOG(RRM, INFO, + "SSIDtype %d, ScanType %d, Dwell %d, MinDwell %d, ChnlType %d, ChnlNum %d\n", + prMsg->ucSSIDType, prMsg->eScanType, prMsg->u2ChannelDwellTime, + prMsg->u2ChannelMinDwellTime, prMsg->eScanChannel, + prMsg->ucChannelListNum); + + return TRUE; +} + +void rrmDoBeaconMeasurement(struct ADAPTER *prAdapter, unsigned long ulParam) +{ + uint8_t ucBssIndex = (uint8_t) ulParam; + struct CONNECTION_SETTINGS *prConnSettings = + aisGetConnSettings(prAdapter, ucBssIndex); + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq = + aisGetRmReqParam(prAdapter, ucBssIndex); + struct RM_BCN_REQ *prBcnReq = + (struct RM_BCN_REQ *)&prRmReq->prCurrMeasElem + ->aucRequestFields[0]; + + if (prBcnReq->ucMeasurementMode == RM_BCN_REQ_TABLE_MODE) { + struct LINK *prBSSDescList = + &prAdapter->rWifiVar.rScanInfo.rBSSDescList; + struct BSS_DESC *prBssDesc = NULL; + + prRmReq->rBcnRmParam.eState = RM_ON_GOING; + prBcnReq->ucChannel = 0; + DBGLOG(RRM, INFO, + "Beacon Table Mode, Beacon Table Num %u\n", + prBSSDescList->u4NumElem); + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, + struct BSS_DESC) + { + rrmCollectBeaconReport(prAdapter, + prBssDesc, ucBssIndex); + } + rrmStartNextMeasurement(prAdapter, FALSE, ucBssIndex); + return; + } + if (prConnSettings->fgIsScanReqIssued) { + prRmReq->rBcnRmParam.eState = RM_WAITING; + } else { + prRmReq->rBcnRmParam.eState = RM_ON_GOING; + GET_CURRENT_SYSTIME(&prRmReq->rStartTime); + aisFsmScanRequest(prAdapter, NULL, NULL, 0, + ucBssIndex); + } +} + +static u_int8_t rrmRmFrameIsValid(struct SW_RFB *prSwRfb) +{ + uint16_t u2ElemLen = 0; + uint16_t u2Offset = + (uint16_t)OFFSET_OF(struct ACTION_RM_REQ_FRAME, aucInfoElem); + uint8_t *pucIE = (uint8_t *)prSwRfb->pvHeader; + struct IE_MEASUREMENT_REQ *prCurrMeasElem = NULL; + uint16_t u2CalcIELen = 0; + uint16_t u2IELen = 0; + + if (prSwRfb->u2PacketLen <= u2Offset) { + DBGLOG(RRM, ERROR, "Rm Packet length %d is too short\n", + prSwRfb->u2PacketLen); + return FALSE; + } + pucIE += u2Offset; + u2ElemLen = prSwRfb->u2PacketLen - u2Offset; + IE_FOR_EACH(pucIE, u2ElemLen, u2Offset) + { + u2IELen = IE_LEN(pucIE); + + /* The minimum value of the Length field is 3 (based on a + ** minimum length for the Measurement Request field + ** of 0 octets + */ + if (u2IELen < 3) { + DBGLOG(RRM, ERROR, "Abnormal RM IE length is %d\n", + u2IELen); + return FALSE; + } + + /* Check whether the length of each measurment request element + ** is reasonable + */ + prCurrMeasElem = (struct IE_MEASUREMENT_REQ *)pucIE; + switch (prCurrMeasElem->ucMeasurementType) { + case ELEM_RM_TYPE_BEACON_REQ: + if (u2IELen < (3 + OFFSET_OF(struct RM_BCN_REQ, + aucSubElements))) { + DBGLOG(RRM, ERROR, + "Abnormal Becaon Req IE length is %d\n", + u2IELen); + return FALSE; + } + break; + case ELEM_RM_TYPE_TSM_REQ: + if (u2IELen < (3 + OFFSET_OF(struct RM_TS_MEASURE_REQ, + aucSubElements))) { + DBGLOG(RRM, ERROR, + "Abnormal TSM Req IE length is %d\n", + u2IELen); + return FALSE; + } + break; + default: + DBGLOG(RRM, ERROR, + "Not support: MeasurementType is %d, IE length is %d\n", + prCurrMeasElem->ucMeasurementType, u2IELen); + return FALSE; + } + + u2CalcIELen += IE_SIZE(pucIE); + } + if (u2CalcIELen != u2ElemLen) { + DBGLOG(RRM, ERROR, + "Calculated Total IE len is not equal to received length\n"); + return FALSE; + } + return TRUE; +} + +void rrmProcessRadioMeasurementRequest(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb) +{ + struct ACTION_RM_REQ_FRAME *prRmReqFrame = NULL; + struct ACTION_RM_REPORT_FRAME *prReportFrame = NULL; + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReqParam = NULL; + struct RADIO_MEASUREMENT_REPORT_PARAMS *prRmRepParam = NULL; + enum RM_REQ_PRIORITY eNewPriority; + struct BSS_INFO *prAisBssInfo = NULL; + struct STA_RECORD *prStaRec = NULL; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prAisBssInfo = aisGetAisBssInfo(prAdapter, + secGetBssIdxByRfb(prAdapter, prSwRfb)); + if (prAisBssInfo == NULL) { + DBGLOG(RRM, INFO, "Ignored due to AIS isn't created\n"); + return; + } + + prRmReqFrame = (struct ACTION_RM_REQ_FRAME *)prSwRfb->pvHeader; + prRmReqParam = aisGetRmReqParam(prAdapter, + prAisBssInfo->ucBssIndex); + prRmRepParam = aisGetRmReportParam(prAdapter, + prAisBssInfo->ucBssIndex); + + if (!rrmRmFrameIsValid(prSwRfb)) + return; + prStaRec = prAisBssInfo->prStaRecOfAP; + if (!prStaRec) { + DBGLOG(RRM, INFO, "StaRec is NULL, ignore request\n"); + return; + } + DBGLOG(RRM, INFO, "RM Request From "MACSTR", DialogToken %d\n", + MAC2STR(prRmReqFrame->aucSrcAddr), + prRmReqFrame->ucDialogToken); + eNewPriority = rrmGetRmRequestPriority(prRmReqFrame->aucDestAddr); + if (prRmReqParam->ePriority > eNewPriority) { + DBGLOG(RRM, INFO, "ignore lower precedence rm request\n"); + return; + } + prRmReqParam->ePriority = eNewPriority; + /* */ + if (prRmReqParam->fgRmIsOngoing) { + DBGLOG(RRM, INFO, "Old RM is on-going, cancel it first\n"); + rrmTxRadioMeasurementReport(prAdapter, + prAisBssInfo->ucBssIndex); + wmmRemoveAllTsmMeasurement(prAdapter, FALSE, + prAisBssInfo->ucBssIndex); + rrmFreeMeasurementResources(prAdapter, + prAisBssInfo->ucBssIndex); + } + prRmReqParam->fgRmIsOngoing = TRUE; + /* Step1: Save Measurement Request Params */ + prRmReqParam->u2ReqIeBufLen = prRmReqParam->u2RemainReqLen = + prSwRfb->u2PacketLen - + OFFSET_OF(struct ACTION_RM_REQ_FRAME, aucInfoElem); + if (prRmReqParam->u2RemainReqLen < sizeof(struct IE_MEASUREMENT_REQ)) { + DBGLOG(RRM, ERROR, + "empty Radio Measurement Request Frame, Elem Len %d\n", + prRmReqParam->u2RemainReqLen); + return; + } + WLAN_GET_FIELD_BE16(&prRmReqFrame->u2Repetitions, + &prRmReqParam->u2Repetitions); + prRmReqParam->pucReqIeBuf = + kalMemAlloc(prRmReqParam->u2RemainReqLen, VIR_MEM_TYPE); + if (!prRmReqParam->pucReqIeBuf) { + DBGLOG(RRM, ERROR, + "Alloc %d bytes Req IE Buffer failed, No Memory\n", + prRmReqParam->u2RemainReqLen); + return; + } + kalMemCopy(prRmReqParam->pucReqIeBuf, &prRmReqFrame->aucInfoElem[0], + prRmReqParam->u2RemainReqLen); + prRmReqParam->prCurrMeasElem = + (struct IE_MEASUREMENT_REQ *)prRmReqParam->pucReqIeBuf; + prRmReqParam->fgInitialLoop = TRUE; + rrmHandleBeaconReqSubelem(prAdapter, prAisBssInfo->ucBssIndex); + + /* Step2: Prepare Report Frame and fill in Frame Header */ + prRmRepParam->pucReportFrameBuff = + kalMemAlloc(RM_REPORT_FRAME_MAX_LENGTH, VIR_MEM_TYPE); + if (!prRmRepParam->pucReportFrameBuff) { + DBGLOG(RRM, ERROR, + "Alloc Memory for Measurement Report Frame buffer failed\n"); + return; + } + kalMemZero(prRmRepParam->pucReportFrameBuff, + RM_REPORT_FRAME_MAX_LENGTH); + prReportFrame = (struct ACTION_RM_REPORT_FRAME *) + prRmRepParam->pucReportFrameBuff; + prReportFrame->u2FrameCtrl = MAC_FRAME_ACTION; + COPY_MAC_ADDR(prReportFrame->aucDestAddr, prRmReqFrame->aucSrcAddr); + COPY_MAC_ADDR(prReportFrame->aucSrcAddr, + prAisBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prReportFrame->aucBSSID, prRmReqFrame->aucBSSID); + prReportFrame->ucCategory = CATEGORY_RM_ACTION; + prReportFrame->ucAction = RM_ACTION_RM_REPORT; + prReportFrame->ucDialogToken = prRmReqFrame->ucDialogToken; + prRmRepParam->u2ReportFrameLen = + OFFSET_OF(struct ACTION_RM_REPORT_FRAME, aucInfoElem); + rrmCalibrateRepetions(prRmReqParam); + /* Step3: Start to process Measurement Request Element */ + rrmStartNextMeasurement(prAdapter, TRUE, prAisBssInfo->ucBssIndex); +} + +void rrmTxRadioMeasurementReport(struct ADAPTER *prAdapter, + uint8_t ucBssIndex) +{ + struct MSDU_INFO *prMsduInfo = NULL; + struct RADIO_MEASUREMENT_REPORT_PARAMS *prRmRepParam = + aisGetRmReportParam(prAdapter, ucBssIndex); + struct STA_RECORD *prStaRec = NULL; + struct BSS_INFO *prAisBssInfo = NULL; + + if (prRmRepParam->u2ReportFrameLen <= + OFFSET_OF(struct ACTION_RM_REPORT_FRAME, aucInfoElem)) { + DBGLOG(RRM, INFO, "report frame length is too short, %d\n", + prRmRepParam->u2ReportFrameLen); + goto out; + } + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + if (!prAisBssInfo) { + DBGLOG(RRM, INFO, "ais bss info is NULL\n"); + goto out; + } + prStaRec = prAisBssInfo->prStaRecOfAP; + if (!prStaRec) { + DBGLOG(RRM, INFO, "StaRec of Ais is NULL\n"); + goto out; + } + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc( + prAdapter, prRmRepParam->u2ReportFrameLen); + if (!prMsduInfo) { + DBGLOG(RRM, INFO, + "Alloc MSDU Info failed, frame length %d\n", + prRmRepParam->u2ReportFrameLen); + goto out; + } + DBGLOG(RRM, INFO, "frame length %d\n", + prRmRepParam->u2ReportFrameLen); + kalMemCopy(prMsduInfo->prPacket, prRmRepParam->pucReportFrameBuff, + prRmRepParam->u2ReportFrameLen); + + /* 2 Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, prMsduInfo, prStaRec->ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_MGMT_HEADER_LEN, + prRmRepParam->u2ReportFrameLen, NULL, MSDU_RATE_MODE_AUTO); + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + +out: + /* reset u2ReportFrameLen after tx frame */ + prRmRepParam->u2ReportFrameLen = + OFFSET_OF(struct ACTION_RM_REPORT_FRAME, aucInfoElem); +} + +void rrmGenerateRRMEnabledCapIE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct IE_RRM_ENABLED_CAP *prRrmEnabledCap = NULL; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prRrmEnabledCap = (struct IE_RRM_ENABLED_CAP *) + (((uint8_t *) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + prRrmEnabledCap->ucId = ELEM_ID_RRM_ENABLED_CAP; + prRrmEnabledCap->ucLength = ELEM_MAX_LEN_RRM_CAP; + kalMemZero(&prRrmEnabledCap->aucCap[0], ELEM_MAX_LEN_RRM_CAP); + rrmFillRrmCapa(&prRrmEnabledCap->aucCap[0]); + prMsduInfo->u2FrameLength += IE_SIZE(prRrmEnabledCap); +} + +void rrmFillRrmCapa(uint8_t *pucCapa) +{ + uint8_t ucIndex = 0; + uint8_t aucEnabledBits[] = {RRM_CAP_INFO_LINK_MEASURE_BIT, + RRM_CAP_INFO_NEIGHBOR_REPORT_BIT, + RRM_CAP_INFO_REPEATED_MEASUREMENT, + RRM_CAP_INFO_BEACON_PASSIVE_MEASURE_BIT, + RRM_CAP_INFO_BEACON_ACTIVE_MEASURE_BIT, + RRM_CAP_INFO_BEACON_TABLE_BIT, + RRM_CAP_INFO_RRM_BIT}; + + for (; ucIndex < sizeof(aucEnabledBits); ucIndex++) + SET_EXT_CAP(pucCapa, ELEM_MAX_LEN_RRM_CAP, + aucEnabledBits[ucIndex]); +} + +enum RM_REQ_PRIORITY rrmGetRmRequestPriority(uint8_t *pucDestAddr) +{ + if (IS_UCAST_MAC_ADDR(pucDestAddr)) + return RM_PRI_UNICAST; + else if (EQUAL_MAC_ADDR(pucDestAddr, "\xff\xff\xff\xff\xff\xff")) + return RM_PRI_BROADCAST; + return RM_PRI_MULTICAST; +} + +static void rrmCalibrateRepetions(struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq) +{ + uint16_t u2IeSize = 0; + uint16_t u2RemainReqLen = prRmReq->u2ReqIeBufLen; + struct IE_MEASUREMENT_REQ *prCurrReq = + (struct IE_MEASUREMENT_REQ *)prRmReq->prCurrMeasElem; + + if (prRmReq->u2Repetitions == 0) + return; + + u2IeSize = IE_SIZE(prCurrReq); + while (u2RemainReqLen >= u2IeSize) { + /* 1. If all measurement request has enable bit, no need to + ** repeat + ** see 11.10.6 Measurement request elements with the enable bit + ** set to 1 shall be processed once + ** regardless of the value in the number of repetitions in the + ** measurement request. + ** 2. Due to we don't support parallel measurement, if all + ** request has parallel bit, no need to repeat + ** measurement, to avoid frequent composing incapable response + ** IE and exhauste CPU resource + ** and then cause watch dog timeout. + ** 3. if all measurements are not supported, no need to repeat. + ** currently we only support Beacon request + ** on this chip. + */ + if (!(prCurrReq->ucRequestMode & + (RM_REQ_MODE_ENABLE_BIT | RM_REQ_MODE_PARALLEL_BIT))) { + if (prCurrReq->ucMeasurementType == + ELEM_RM_TYPE_BEACON_REQ) + return; + } + u2RemainReqLen -= u2IeSize; + prCurrReq = (struct IE_MEASUREMENT_REQ *)((uint8_t *)prCurrReq + + u2IeSize); + u2IeSize = IE_SIZE(prCurrReq); + } + DBGLOG(RRM, INFO, + "All Measurement has set enable bit, or all are parallel or not supported, don't repeat\n"); + prRmReq->u2Repetitions = 0; +} + +void rrmRunEventProcessNextRm(struct ADAPTER *prAdapter, + struct MSG_HDR *prMsgHdr) +{ + struct MSG_SCN_SCAN_DONE *prMsg; + uint8_t ucBssIndex = 0; + + ASSERT(prMsgHdr); + + prMsg = (struct MSG_SCN_SCAN_DONE *)prMsgHdr; + ucBssIndex = prMsg->ucBssIndex; + cnmMemFree(prAdapter, prMsgHdr); + rrmStartNextMeasurement(prAdapter, FALSE, ucBssIndex); +} + +void rrmScheduleNextRm(struct ADAPTER *prAdapter, + uint8_t ucBssIndex) +{ + struct MSG_SCN_SCAN_DONE *prMsg = NULL; + + prMsg = (struct MSG_SCN_SCAN_DONE *) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(struct MSG_SCN_SCAN_DONE)); + if (!prMsg) { + DBGLOG(RRM, ERROR, "[RRM] No memory\n"); + return; + } + prMsg->rMsgHdr.eMsgId = MID_RRM_REQ_SCHEDULE; + prMsg->ucBssIndex = ucBssIndex; + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *)prMsg, MSG_SEND_METHOD_BUF); +} + +static void rrmHandleBeaconReqSubelem( + IN struct ADAPTER *prAdapter, IN uint8_t ucBssIndex) +{ + struct RADIO_MEASUREMENT_REQ_PARAMS *rmReqParam = NULL; + struct IE_MEASUREMENT_REQ *request = NULL; + struct RM_BCN_REQ *prBcnReq = NULL; + struct BCN_RM_PARAMS *data = NULL; + uint16_t elemsLen = 0; + uint8_t *subelems = NULL; + uint8_t slen = 0; + uint8_t reportInfo = 0; + + rmReqParam = aisGetRmReqParam(prAdapter, ucBssIndex); + request = rmReqParam->prCurrMeasElem; + prBcnReq = (struct RM_BCN_REQ *)&request->aucRequestFields[0]; + data = &rmReqParam->rBcnRmParam; + + if (request->ucMeasurementType != ELEM_RM_TYPE_BEACON_REQ) + return; + + /* reset data */ + data->token = request->ucToken; + data->lastIndication = 0; + data->ssidLen = 0; + data->reportDetail = BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS; + data->reportIeIdsLen = 0; + data->apChannelsLen = 0; + + elemsLen = request->ucLength - 3 - + OFFSET_OF(struct RM_BCN_REQ, aucSubElements); + subelems = &prBcnReq->aucSubElements[0]; + while (elemsLen >= 2) { + slen = subelems[1]; + if (slen > elemsLen - 2) { + DBGLOG(RRM, WARN, + "Beacon Request: Truncated subelement"); + return; + } + + switch (subelems[0]) { + case BEACON_REQUEST_SUBELEM_SSID: + { + if (!slen) { + DBGLOG(RRM, WARN, "Wildcard SSID"); + break; + } + + if (slen > ELEM_MAX_LEN_SSID) { + DBGLOG(RRM, WARN, + "Invalid SSID length: %u", slen); + break; + } + + COPY_SSID(data->ssid, data->ssidLen, + &subelems[2], slen); + break; + } + case BEACON_REQUEST_SUBELEM_INFO: + { + if (slen != 2) { + DBGLOG(RRM, WARN, + "%u Invalid reporting len: %u", + subelems[0], slen); + break; + } + /* Beacon reporting data field format + * Reporting condition 1, Threshold/Offset Reference 1 + */ + reportInfo = subelems[2]; + if (reportInfo != 0) { + DBGLOG(RRM, WARN, + "reporting info=%u not supported", + reportInfo); + break; + } + break; + } + case BEACON_REQUEST_SUBELEM_DETAIL: + { + if (slen != 1) { + DBGLOG(RRM, WARN, "%u Wrong len %u", + subelems[0], slen); + break; + } + + if (subelems[2] > + BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS) { + DBGLOG(RRM, WARN, + "Invalid detail: %u", subelems[2]); + break; + } + + data->reportDetail = subelems[2]; + + break; + } + case BEACON_REQUEST_SUBELEM_REQUEST: + { + if (data->reportDetail != + BEACON_REPORT_DETAIL_REQUESTED_ONLY) { + DBGLOG(RRM, WARN, + "unexpected report detail is %u", + data->reportDetail); + break; + } + + if (!slen) { + DBGLOG(RRM, WARN, "subelem %u Wrong len %u", + subelems[0], slen); + break; + } + + data->reportIeIds = &subelems[2]; + data->reportIeIdsLen = slen; + break; + } + case BEACON_REQUEST_SUBELEM_AP_CHANNEL: + { + uint8_t *strbuf, *pos, *end; + uint8_t i; + + if (slen < 2) { + DBGLOG(RRM, WARN, "subelem %u Wrong len %u", + subelems[0], slen); + break; + } + + /* AP Channel Report element + * EleID 1, Length 1, Op class 1, channel List N + */ + data->apChannels = &subelems[3]; + data->apChannelsLen = slen - 1; + + strbuf = kalMemAlloc(slen * 4, VIR_MEM_TYPE); + if (strbuf) { + pos = strbuf; + end = pos + slen * 4; + for (i = 0; i < data->apChannelsLen; i++) { + pos += kalSnprintf(pos, end - pos, + " %d", data->apChannels[i]); + } + *pos = '\0'; + DBGLOG(RRM, INFO, "AP chnls %s", strbuf); + kalMemFree(strbuf, VIR_MEM_TYPE, slen * 4); + } + break; + } + case BEACON_REQUEST_SUBELEM_LAST_INDICATION: + { + if (slen != 1) { + DBGLOG(RRM, WARN, "Wrong len %u", slen); + break; + } + + data->lastIndication = subelems[2]; + break; + } + default: + DBGLOG(RRM, WARN, "Unknown subelem id %u", subelems[0]); + break; + } + elemsLen -= 2 + slen; + subelems += 2 + slen; + } +} + +uint8_t rrmCheckReportId(uint8_t id, uint8_t *ie, uint8_t len) +{ + uint8_t i; + + if (ie && len > 0) { + for (i = 0; i < len; i++) { + if (id == ie[i]) + return TRUE; + } + } + return FALSE; +} + +int rrmBeaconRepAddFrameBody(struct BCN_RM_PARAMS *data, + struct BSS_DESC *bss, uint8_t *buf, + uint32_t buf_len, uint8_t **ies_buf, + uint32_t *ie_len, int add_fixed) +{ + uint8_t *ies = *ies_buf; + uint32_t ies_len = *ie_len; + uint32_t old_ies_len = ies_len; + uint8_t *pos = buf; + int rem_len; + enum BEACON_REPORT_DETAIL detail = data->reportDetail; + + rem_len = 255 - sizeof(struct RM_BCN_REPORT) - + sizeof(struct IE_MEASUREMENT_REPORT) - 2 - + REPORTED_FRAME_BODY_SUBELEM_LEN; + + if (detail > BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS) { + DBGLOG(RRM, WARN, "Invalid reporting detail: %d", detail); + return -EINVAL; + } + + if (detail == BEACON_REPORT_DETAIL_NONE) + return 0; + + /* + * Minimal frame body subelement size: EID(1) + length(1) + TSF(8) + + * beacon interval(2) + capabilities(2) = 14 bytes + */ + if (add_fixed && buf_len < 14) + return -EINVAL; + + *pos++ = BEACON_REPORT_SUBELEM_FRAME_BODY; + /* The length will be filled later */ + pos++; + + if (add_fixed) { + WLAN_SET_FIELD_64(pos, bss->u8TimeStamp.QuadPart); + pos += 8; + WLAN_SET_FIELD_16(pos, bss->u2BeaconInterval); + pos += 2; + WLAN_SET_FIELD_16(pos, bss->u2CapInfo); + pos += 2; + } + + rem_len -= pos - buf; + + /* + * According to IEEE Std 802.11-2016, 9.4.2.22.7, if the reported frame + * body subelement causes the element to exceed the maximum element + * size, the subelement is truncated so that the last IE is a complete + * IE. So even when required to report all IEs, add elements one after + * the other and stop once there is no more room in the measurement + * element. + */ + while (ies_len > 2 && 2U + ies[1] <= ies_len && rem_len > 0) { + if (detail == BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS || + rrmCheckReportId(ies[0], data->reportIeIds, + data->reportIeIdsLen)) { + uint8_t elen = ies[1]; + + if (2 + elen > buf + buf_len - pos || + 2 + elen > rem_len) + break; + + *pos++ = ies[0]; + *pos++ = elen; + kalMemCopy(pos, ies + 2, elen); + pos += elen; + rem_len -= 2 + elen; + } + + ies_len -= 2 + ies[1]; + ies += 2 + ies[1]; + } + + *ie_len = ies_len; + *ies_buf = ies; + + /* Now the length is known */ + buf[1] = pos - buf - 2; + return old_ies_len != ies_len ? pos - buf : -EINVAL; +} + +int rrmReportElem(struct RM_MEASURE_REPORT_ENTRY *reportEntry, + uint8_t token, uint8_t mode, uint8_t type, + const uint8_t *data, uint32_t data_len) +{ + uint8_t *report = reportEntry->pucMeasReport; + uint8_t len = reportEntry->u2MeasReportLen; + uint32_t size = len + 5 + data_len; + uint8_t *buf; + + buf = kalMemAlloc(size, VIR_MEM_TYPE); + if (!buf) { + DBGLOG(RRM, ERROR, "alloc report elem fail\n"); + return -ENOMEM; + } + reportEntry->u2MeasReportLen = size; + reportEntry->pucMeasReport = buf; + + if (len) { + kalMemCopy(buf, report, len); + kalMemFree(report, VIR_MEM_TYPE, len); + buf += len; + } + + *buf++ = ELEM_ID_MEASUREMENT_REPORT; + *buf++ = 3 + data_len; + *buf++ = token; + *buf++ = mode; + *buf++ = type; + + if (data_len) { + kalMemCopy(buf, data, data_len); + buf += data_len; + } + + return 0; +} + +int rrmAddBeaconRepElem(IN struct ADAPTER *prAdapter, + struct BCN_RM_PARAMS *data, + struct BSS_DESC *bss, + struct RM_MEASURE_REPORT_ENTRY *reportEntry, + struct RM_BCN_REPORT *rep, + uint8_t **ie, uint32_t *ie_len, uint8_t idx) +{ + int ret; + uint8_t *buf, *pos; + uint8_t ve = prAdapter->rWifiVar.u4SwTestMode == + ENUM_SW_TEST_MODE_SIGMA_VOICE_ENT; + uint32_t subelems_len = + (!ve ? REPORTED_FRAME_BODY_SUBELEM_LEN : 0) + + (data->lastIndication ? + BEACON_REPORT_LAST_INDICATION_SUBELEM_LEN : 0); + uint32_t size = sizeof(*rep) + 14 + *ie_len + subelems_len; + + /* Maximum element length: Beacon Report element + Reported Frame Body + * subelement + all IEs of the reported Beacon frame + Reported Frame + * Body Fragment ID subelement + */ + buf = kalMemAlloc(size, VIR_MEM_TYPE); + if (!buf) { + DBGLOG(RRM, ERROR, "alloc beacon report elem fail\n"); + return -ENOMEM; + } + + kalMemCopy(buf, rep, sizeof(*rep)); + + ret = rrmBeaconRepAddFrameBody(data, + bss, buf + sizeof(*rep), + 14 + *ie_len, ie, ie_len, + idx == 0); + if (ret < 0) + goto out; + + pos = buf + ret + sizeof(*rep); + + + if (!ve) { + pos[0] = BEACON_REPORT_SUBELEM_FRAME_BODY_FRAGMENT_ID; + pos[1] = 2; + + /* + * Only one Beacon Report Measurement is supported at a time, + * so the Beacon Report ID can always be set to 1. + */ + pos[2] = 1; + + /* Fragment ID Number (bits 0..6) and + * More Frame Body Fragments (bit 7) + */ + pos[3] = idx; + if (data->reportDetail != BEACON_REPORT_DETAIL_NONE && *ie_len) + pos[3] |= REPORTED_FRAME_BODY_MORE_FRAGMENTS; + else + pos[3] &= ~REPORTED_FRAME_BODY_MORE_FRAGMENTS; + + pos += REPORTED_FRAME_BODY_SUBELEM_LEN; + } + + if (data->lastIndication) { + pos[0] = BEACON_REPORT_SUBELEM_LAST_INDICATION; + pos[1] = 1; + + /* This field will be updated later if this is the last frame */ + pos[2] = 0; + } + + ret = rrmReportElem(reportEntry, data->token, + MEASUREMENT_REPORT_MODE_ACCEPT, + ELEM_RM_TYPE_BEACON_REPORT, buf, + ret + sizeof(*rep) + subelems_len); +out: + kalMemFree(buf, VIR_MEM_TYPE, size); + return ret; +} + +void rrmCollectBeaconReport(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc, IN uint8_t ucBssIndex) +{ + struct RADIO_MEASUREMENT_REQ_PARAMS *rmReq = + aisGetRmReqParam(prAdapter, ucBssIndex); + struct RADIO_MEASUREMENT_REPORT_PARAMS *rmRep = + aisGetRmReportParam(prAdapter, ucBssIndex); + struct RM_BCN_REQ *bcnReq = + (struct RM_BCN_REQ *)&rmReq->prCurrMeasElem->aucRequestFields[0]; + struct BCN_RM_PARAMS *data = &rmReq->rBcnRmParam; + uint8_t *bssid = prBssDesc->aucBSSID; + uint8_t *pos = prBssDesc->aucIEBuf; + uint32_t ies_len = prBssDesc->u2IELength; + struct RM_BCN_REPORT rep; + struct RM_MEASURE_REPORT_ENTRY *reportEntry = NULL; + struct RM_MEASURE_REPORT_ENTRY *tmp = NULL; + u_int8_t idx = 0; + u_int8_t validChannel = FALSE; + OS_SYSTIME rCurrent; + uint64_t u8Tsf = 0; + + /* sanity check 1: bssid */ + if (!EQUAL_MAC_ADDR(bcnReq->aucBssid, "\xff\xff\xff\xff\xff\xff") && + !EQUAL_MAC_ADDR(bcnReq->aucBssid, bssid)) { + DBGLOG(RRM, INFO, + "bssid mismatch, req "MACSTR", actual "MACSTR"\n", + MAC2STR(bcnReq->aucBssid), MAC2STR(bssid)); + return; + } + + /* sanity check 2: channel */ + if (prBssDesc->ucChannelNum == bcnReq->ucChannel) + validChannel = TRUE; + if (!validChannel) { + uint8_t i = 0; + + for (i = 0; i < data->apChannelsLen; i++) { + if (prBssDesc->ucChannelNum == data->apChannels[i]) { + validChannel = TRUE; + break; + } + } + } + if (!validChannel && + bcnReq->ucChannel > 0 && bcnReq->ucChannel < 255) { + DBGLOG(RRM, INFO, ""MACSTR" chnl %d invalid, req %d\n", + MAC2STR(bssid), prBssDesc->ucChannelNum, + bcnReq->ucChannel); + return; + } + + /* sanity check 3: ssid */ + if (data->ssidLen && + UNEQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, + data->ssid, data->ssidLen)) { + uint8_t reqSsid[ELEM_MAX_LEN_SSID + 1] = {0}; + uint8_t bcnSsid[ELEM_MAX_LEN_SSID + 1] = {0}; + + kalMemCopy(reqSsid, data->ssid, + min_t(uint8_t, data->ssidLen, ELEM_MAX_LEN_SSID)); + kalMemCopy(bcnSsid, prBssDesc->aucSSID, + min_t(uint8_t, prBssDesc->ucSSIDLen, ELEM_MAX_LEN_SSID)); + DBGLOG(RRM, TRACE, + ""MACSTR" SSID mismatch, req(%d, %s), bcn(%d, %s)\n", + MAC2STR(bssid), data->ssidLen, HIDE(reqSsid), + prBssDesc->ucSSIDLen, HIDE(bcnSsid)); + return; + } + + /* Compose Beacon Report in a temp buffer, search in saved + * reported link, check if we have saved a report for this AP + */ + LINK_FOR_EACH_ENTRY(tmp, &rmRep->rReportLink, rLinkEntry, + struct RM_MEASURE_REPORT_ENTRY) + { + if (EQUAL_MAC_ADDR(tmp->aucBSSID, bssid)) { + reportEntry = tmp; + break; + } + } + /* not found a entry in collected report link */ + if (!reportEntry) { + reportEntry = kalMemAlloc(sizeof(*reportEntry), + VIR_MEM_TYPE); + if (!reportEntry)/* no memory to allocate in OS */ { + DBGLOG(RRM, ERROR, + "Alloc entry failed, No Memory\n"); + return; + } + COPY_MAC_ADDR(reportEntry->aucBSSID, bssid); + reportEntry->u2MeasReportLen = 0; + reportEntry->pucMeasReport = NULL; + DBGLOG(RRM, TRACE, + "allocate entry for Bss "MACSTR", total entry %u\n", + MAC2STR(bssid), rmRep->rReportLink.u4NumElem); + LINK_INSERT_TAIL(&rmRep->rReportLink, + &reportEntry->rLinkEntry); + } else { + if (reportEntry->u2MeasReportLen) { + kalMemFree(reportEntry->pucMeasReport, + VIR_MEM_TYPE, reportEntry->u2MeasReportLen); + reportEntry->u2MeasReportLen = 0; + reportEntry->pucMeasReport = NULL; + } + } + + /* Fixed length field */ + rep.ucRegulatoryClass = bcnReq->ucRegulatoryClass; + rep.ucChannel = prBssDesc->ucChannelNum; + rep.u2Duration = bcnReq->u2Duration; + /* ucReportInfo: Bit 0 is the type of frame, 0 means beacon/probe + ** response, bit 1~7 means phy type + */ + rep.ucReportInfo = 0; + rep.ucRCPI = prBssDesc->ucRCPI; + rep.ucRSNI = 255; /* 255 = RSNI not available. see 7.3.2.41 */ + COPY_MAC_ADDR(rep.aucBSSID, bssid); + rep.ucAntennaID = 1; + u8Tsf = *(uint64_t *)&rTsf.au4Tsf[0]; + GET_CURRENT_SYSTIME(&rCurrent); + if (rmReq->rStartTime >= rTsf.rTime) + u8Tsf += rmReq->rStartTime - rTsf.rTime; + else + u8Tsf += rTsf.rTime - rmReq->rStartTime; + kalMemCopy(rep.aucStartTime, &u8Tsf, 8); + u8Tsf = *(uint64_t *)&rTsf.au4Tsf[0] + rCurrent - rTsf.rTime; + kalMemCopy(rep.aucParentTSF, &u8Tsf, 4); /* low part of TSF */ + + do { + int ret; + + ret = rrmAddBeaconRepElem(prAdapter, data, prBssDesc, + reportEntry, &rep, &pos, &ies_len, idx++); + if (ret) + break; + } while (data->reportDetail != BEACON_REPORT_DETAIL_NONE && + ies_len >= 2); + + DBGLOG(RRM, TRACE, + "Bss "MACSTR", ReportDeail %d, IncludeIE Num %d, chnl %d\n", + MAC2STR(bssid), data->reportDetail, data->reportIeIdsLen, + prBssDesc->ucChannelNum); +} + +void rrmUpdateBssTimeTsf(struct ADAPTER *prAdapter, struct BSS_DESC *prBssDesc) +{ + ASSERT(prAdapter); + ASSERT(prBssDesc); + + rTsf.rTime = prBssDesc->rUpdateTime; + kalMemCopy(&rTsf.au4Tsf[0], &prBssDesc->u8TimeStamp, 8); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rsn.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rsn.c new file mode 100644 index 0000000000000..8feedb59b568b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/rsn.c @@ -0,0 +1,3709 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: mgmt/rsn.c#3 + */ + +/*! \file "rsn.c" + * \brief This file including the 802.11i, wpa and wpa2(rsn) related function. + * + * This file provided the macros and functions library to support + * the wpa/rsn ie parsing, cipher and AKM check to help the AP seleced + * deciding, tkip mic error handler and rsn PMKID support. + */ + +/******************************************************************************* + * C O M P I L E 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 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rsnParseRsnIE(IN struct ADAPTER *prAdapter, + IN struct RSN_INFO_ELEM *prInfoElem, + OUT struct RSN_INFO *prRsnInfo) +{ + uint32_t i; + int32_t u4RemainRsnIeLen; + uint16_t u2Version; + uint16_t u2Cap = 0; + uint32_t u4GroupSuite = RSN_CIPHER_SUITE_CCMP; + uint16_t u2PairSuiteCount = 0; + uint16_t u2AuthSuiteCount = 0; + uint8_t *pucPairSuite = NULL; + uint8_t *pucAuthSuite = NULL; + uint16_t u2PmkidCount = 0; + uint8_t *cp; + + DEBUGFUNC("rsnParseRsnIE"); + + /* 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 = (uint8_t *) &prInfoElem->u4GroupKeyCipherSuite; + u4RemainRsnIeLen = (int32_t) 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 = (uint32_t) u2PairSuiteCount * 4; + if (u4RemainRsnIeLen < (int32_t) 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 -= (int32_t) 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 = (uint32_t) u2AuthSuiteCount * 4; + if (u4RemainRsnIeLen < (int32_t) 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 -= (int32_t) 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); + cp += 2; + u4RemainRsnIeLen -= 2; + + if (u4RemainRsnIeLen == 0) + break; + + if (u4RemainRsnIeLen < 2) { + DBGLOG(RSN, TRACE, + "Fail to parse PMKID count in RSN iE\n"); + return FALSE; + } + + WLAN_GET_FIELD_16(cp, &u2PmkidCount); + cp += 2; + u4RemainRsnIeLen -= 2; + + if (u2PmkidCount > 4) { + DBGLOG(RSN, TRACE, + "Bad RSN IE due to PMKID count(%d)\n", + u2PmkidCount); + return FALSE; + } + + if (u2PmkidCount > 0 && u4RemainRsnIeLen < 16 * u2PmkidCount) { + DBGLOG(RSN, TRACE, + "Fail to parse PMKID in RSN iE, count: %d\n", + u2PmkidCount); + return FALSE; + } + + if (u2PmkidCount > 0) { + kalMemCopy(prRsnInfo->aucPmkid, cp, IW_PMKID_LEN); + cp += IW_PMKID_LEN; + u4RemainRsnIeLen -= IW_PMKID_LEN; + } + } 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 0x%x\n", + u2Version, SWAP32(u4GroupSuite)); + + 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 = + (uint32_t) u2PairSuiteCount; + + for (i = 0; i < (uint32_t) u2PairSuiteCount; i++) { + WLAN_GET_FIELD_32(pucPairSuite, + &prRsnInfo->au4PairwiseKeyCipherSuite + [i]); + pucPairSuite += 4; + + DBGLOG(RSN, LOUD, + "RSN: pairwise key cipher suite [%d]: 0x%x\n", i, + SWAP32(prRsnInfo->au4PairwiseKeyCipherSuite[i])); + } + } 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: 0x%x (default)\n", + SWAP32(prRsnInfo->au4PairwiseKeyCipherSuite[0])); + } + + 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 = (uint32_t) + u2AuthSuiteCount; + + for (i = 0; i < (uint32_t) u2AuthSuiteCount; i++) { + WLAN_GET_FIELD_32(pucAuthSuite, + &prRsnInfo->au4AuthKeyMgtSuite[i]); + pucAuthSuite += 4; + + DBGLOG(RSN, LOUD, "RSN: AKM suite [%d]: 0x%x\n", i, + SWAP32(prRsnInfo->au4AuthKeyMgtSuite[i])); + } + } 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: 0x%x (default)\n", + SWAP32(prRsnInfo->au4AuthKeyMgtSuite[0])); + } + + prRsnInfo->u2RsnCap = u2Cap; + prRsnInfo->fgRsnCapPresent = TRUE; + prRsnInfo->u2PmkidCount = u2PmkidCount; + DBGLOG(RSN, LOUD, "RSN cap: 0x%04x, PMKID count: %d\n", + prRsnInfo->u2RsnCap, prRsnInfo->u2PmkidCount); + + 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. + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rsnParseWpaIE(IN struct ADAPTER *prAdapter, + IN struct WPA_INFO_ELEM *prInfoElem, + OUT struct RSN_INFO *prWpaInfo) +{ + uint32_t i; + int32_t u4RemainWpaIeLen; + uint16_t u2Version; + uint16_t u2Cap = 0; + uint32_t u4GroupSuite = WPA_CIPHER_SUITE_TKIP; + uint16_t u2PairSuiteCount = 0; + uint16_t u2AuthSuiteCount = 0; + uint8_t *pucPairSuite = NULL; + uint8_t *pucAuthSuite = NULL; + uint8_t *cp; + u_int8_t fgCapPresent = FALSE; + + DEBUGFUNC("rsnParseWpaIE"); + + /* 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 = (uint8_t *) &prInfoElem->u4GroupKeyCipherSuite; + u4RemainWpaIeLen = (int32_t) 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 = (uint32_t) u2PairSuiteCount * 4; + if (u4RemainWpaIeLen < (int32_t) 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 -= (int32_t) 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 = (uint32_t) u2AuthSuiteCount * 4; + if (u4RemainWpaIeLen < (int32_t) 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 -= (int32_t) 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 0x%x\n", + u2Version, SWAP32(u4GroupSuite)); + + 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 = + (uint32_t) u2PairSuiteCount; + + for (i = 0; i < (uint32_t) u2PairSuiteCount; i++) { + WLAN_GET_FIELD_32(pucPairSuite, + &prWpaInfo->au4PairwiseKeyCipherSuite + [i]); + pucPairSuite += 4; + + DBGLOG(RSN, LOUD, + "WPA: pairwise key cipher suite [%d]: 0x%x\n", i, + SWAP32(prWpaInfo->au4PairwiseKeyCipherSuite[i])); + } + } 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: 0x%x (default)\n", + SWAP32(prWpaInfo->au4PairwiseKeyCipherSuite[0])); + } + + 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 = (uint32_t) + u2AuthSuiteCount; + + for (i = 0; i < (uint32_t) u2AuthSuiteCount; i++) { + WLAN_GET_FIELD_32(pucAuthSuite, + &prWpaInfo->au4AuthKeyMgtSuite[i]); + pucAuthSuite += 4; + + DBGLOG(RSN, LOUD, + "WPA: AKM suite [%d]: 0x%x\n", i, + SWAP32(prWpaInfo->au4AuthKeyMgtSuite[i])); + } + } 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: 0x%x (default)\n", + SWAP32(prWpaInfo->au4AuthKeyMgtSuite[0])); + } + + 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. + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rsnSearchSupportedCipher(IN struct ADAPTER *prAdapter, + IN uint32_t u4Cipher, OUT uint32_t *pu4Index, + IN uint8_t ucBssIndex) +{ + uint8_t i; + struct DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY *prEntry; + struct IEEE_802_11_MIB *prMib; + + DEBUGFUNC("rsnSearchSupportedCipher"); + + prMib = aisGetMib(prAdapter, ucBssIndex); + + for (i = 0; i < MAX_NUM_SUPPORTED_CIPHER_SUITES; i++) { + prEntry = + &prMib->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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rsnIsSuitableBSS(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBss, + IN struct RSN_INFO *prBssRsnInfo, + IN uint8_t ucBssIndex) +{ + uint32_t i, c, s, k; + struct CONNECTION_SETTINGS *prConnSettings; + + DEBUGFUNC("rsnIsSuitableBSS"); + + prConnSettings = + aisGetConnSettings(prAdapter, ucBssIndex); + + s = prConnSettings->rRsnInfo.u4GroupKeyCipherSuite; + k = prBssRsnInfo->u4GroupKeyCipherSuite; + + if ((s & 0x000000FF) != GET_SELECTOR_TYPE(k)) { + DBGLOG(RSN, WARN, "Break by GroupKey s=0x%x k=0x%x\n", + s, SWAP32(k)); + return FALSE; + } + + c = prBssRsnInfo->u4PairwiseKeyCipherSuiteCount; + for (i = 0; i < c; i++) { + s = prConnSettings-> + rRsnInfo.au4PairwiseKeyCipherSuite[0]; + k = prBssRsnInfo->au4PairwiseKeyCipherSuite[i]; + if ((s & 0x000000FF) == GET_SELECTOR_TYPE(k)) { + break; + } else if (i == c - 1) { + DBGLOG(RSN, WARN, "Break by PairwisKey s=0x%x k=0x%x\n", + s, SWAP32(k)); + return FALSE; + } + } + + if (aisGetAuthMode(prAdapter, ucBssIndex) == AUTH_MODE_WPA3_SAE) { + DBGLOG(RSN, WARN, "Don't check AuthKeyMgtSuite with SAE\n"); + return TRUE; + } + + /* check akm */ + s = prConnSettings->rRsnInfo.au4AuthKeyMgtSuite[0]; + if (prBss->ucIsAdaptive11r && + (s == WLAN_AKM_SUITE_FT_8021X || s == WLAN_AKM_SUITE_FT_PSK)) + return TRUE; + + c = prBssRsnInfo->u4AuthKeyMgtSuiteCount; + for (i = 0; i < c; i++) { + k = prBssRsnInfo->au4AuthKeyMgtSuite[i]; + if ((s & 0x000000FF) == GET_SELECTOR_TYPE(k)) { + break; + } else if (i == c - 1) { + DBGLOG(RSN, WARN, "Break by AuthKey s=0x%x k=0x%x\n", + s, SWAP32(k)); + return FALSE; + } + } + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rsnSearchAKMSuite(IN struct ADAPTER *prAdapter, + IN uint32_t u4AkmSuite, OUT uint32_t *pu4Index, + IN uint8_t ucBssIndex) +{ + uint8_t i; + struct DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY + *prEntry; + struct IEEE_802_11_MIB *prMib; + + DEBUGFUNC("rsnSearchAKMSuite"); + + prMib = aisGetMib(prAdapter, ucBssIndex); + + for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) { + prEntry = &prMib-> + dot11RSNAConfigAuthenticationSuitesTable[i]; + if (prEntry->dot11RSNAConfigAuthenticationSuite == + u4AkmSuite && + prEntry->dot11RSNAConfigAuthenticationSuiteEnabled) { + *pu4Index = i; + return TRUE; + } + } + return FALSE; +} /* rsnSearchAKMSuite */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief refer to wpa_supplicant wpa_key_mgmt_wpa + */ + +uint8_t rsnKeyMgmtWpa(IN struct ADAPTER *prAdapter, + IN enum ENUM_PARAM_AUTH_MODE eAuthMode, + IN uint8_t bssidx) +{ + uint32_t i; + + return eAuthMode == AUTH_MODE_WPA2 || + eAuthMode == AUTH_MODE_WPA2_PSK || + eAuthMode == AUTH_MODE_WPA2_FT_PSK || + eAuthMode == AUTH_MODE_WPA2_FT || + eAuthMode == AUTH_MODE_WPA3_SAE || + eAuthMode == AUTH_MODE_WPA3_OWE || + rsnSearchAKMSuite(prAdapter, RSN_AKM_SUITE_OWE, &i, bssidx) || + rsnSearchAKMSuite(prAdapter, RSN_AKM_SUITE_SAE, &i, bssidx); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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. + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rsnPerformPolicySelection( + IN struct ADAPTER *prAdapter, IN struct BSS_DESC *prBss, + IN uint8_t ucBssIndex) +{ +#if CFG_SUPPORT_802_11W + int32_t i; + uint32_t j; +#else + uint32_t i, j; +#endif + u_int8_t fgSuiteSupported; + uint32_t u4PairwiseCipher = 0; + uint32_t u4GroupCipher = 0; + uint32_t u4AkmSuite = 0; + struct RSN_INFO *prBssRsnInfo; + u_int8_t fgIsWpsActive = (u_int8_t) FALSE; + enum ENUM_PARAM_AUTH_MODE eAuthMode; + enum ENUM_PARAM_OP_MODE eOPMode; + enum ENUM_WEP_STATUS eEncStatus; + + DEBUGFUNC("rsnPerformPolicySelection"); + + prBss->u4RsnSelectedPairwiseCipher = 0; + prBss->u4RsnSelectedGroupCipher = 0; + prBss->u4RsnSelectedAKMSuite = 0; + prBss->ucEncLevel = 0; + + aisGetAisSpecBssInfo(prAdapter, + ucBssIndex)->fgMgmtProtection = FALSE; + eAuthMode = + aisGetAuthMode(prAdapter, ucBssIndex); + eOPMode = + aisGetOPMode(prAdapter, ucBssIndex); + eEncStatus = + aisGetEncStatus(prAdapter, ucBssIndex); + +#if CFG_SUPPORT_WPS + fgIsWpsActive = aisGetConnSettings(prAdapter, + ucBssIndex)->fgWpsActive; + + /* CR1640, disable the AP select privacy check */ + if (fgIsWpsActive && + (eAuthMode < + AUTH_MODE_WPA) && + (eOPMode == NET_TYPE_INFRA)) { + DBGLOG(RSN, INFO, "-- 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, + ucBssIndex) == FALSE) { + DBGLOG(RSN, INFO, "-- No Protected BSS\n"); + return TRUE; + } + DBGLOG(RSN, INFO, "-- Protected BSS but No need\n"); + return FALSE; + } + + /* Protection is required in this BSS. */ + if ((prBss->u2CapInfo & CAP_INFO_PRIVACY) != 0) { + if (secEnabledInAis(prAdapter, + ucBssIndex) == FALSE) { + DBGLOG(RSN, INFO, "-- Protected BSS\n"); + return FALSE; + } + } + + if (eAuthMode == AUTH_MODE_WPA || + eAuthMode == AUTH_MODE_WPA_PSK || + eAuthMode == AUTH_MODE_WPA_NONE) { + + if (prBss->fgIEWPA) { + prBssRsnInfo = &prBss->rWPAInfo; + } else { + DBGLOG(RSN, INFO, + "WPA Information Element does not exist.\n"); + return FALSE; + } + } else if (rsnKeyMgmtWpa(prAdapter, eAuthMode, ucBssIndex)) { + + if (prBss->fgIERSN) { + prBssRsnInfo = &prBss->rRSNInfo; + } else { + DBGLOG(RSN, INFO, + "RSN Information Element does not exist.\n"); + return FALSE; + } +#if CFG_SUPPORT_PASSPOINT + } else if (eAuthMode == + AUTH_MODE_WPA_OSEN) { + /* OSEN is mutual exclusion with RSN, + * so we can reuse RSN's flag and variables + */ + if (prBss->fgIEOsen) { + prBssRsnInfo = &prBss->rRSNInfo; + } else { + DBGLOG(RSN, WARN, + "OSEN Information Element does not exist.\n"); + return FALSE; + } +#endif + } else if (eEncStatus != ENUM_ENCRYPTION1_ENABLED) { + /* If the driver is configured to use WEP only, + * ignore this BSS. + */ + return FALSE; + } else if (eEncStatus == + ENUM_ENCRYPTION1_ENABLED) { + /* If the driver is configured to use WEP only, use this BSS. */ + DBGLOG(RSN, INFO, "-- WEP-only legacy BSS\n"); + return TRUE; + } else { + DBGLOG(RSN, INFO, "unknown\n"); + return FALSE; + } + + if (!rsnIsSuitableBSS(prAdapter, prBss, prBssRsnInfo, ucBssIndex)) { +#if CFG_SUPPORT_RSN_SCORE + prBss->fgIsRSNSuitableBss = FALSE; + } else + prBss->fgIsRSNSuitableBss = TRUE; +#else + + return FALSE; + } +#endif + /* end Support AP Selection */ + + 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 RSN_CIPHER_SUITE_GCMP_256: + if (eEncStatus == + ENUM_ENCRYPTION4_ENABLED) + fgSuiteSupported = TRUE; + break; + case WPA_CIPHER_SUITE_CCMP: + case RSN_CIPHER_SUITE_CCMP: + if (eEncStatus == + ENUM_ENCRYPTION3_ENABLED) + fgSuiteSupported = TRUE; + break; + + case WPA_CIPHER_SUITE_TKIP: + case RSN_CIPHER_SUITE_TKIP: + if (eEncStatus == + ENUM_ENCRYPTION2_ENABLED) + fgSuiteSupported = TRUE; + break; + + case WPA_CIPHER_SUITE_WEP40: + case WPA_CIPHER_SUITE_WEP104: + if (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", + eEncStatus); + } +#endif + } else { + fgSuiteSupported = FALSE; + + DBGLOG(RSN, TRACE, + "eEncStatus %d %d 0x%08x\n", + eEncStatus, + prBssRsnInfo->u4PairwiseKeyCipherSuiteCount, + prBssRsnInfo->au4PairwiseKeyCipherSuite[0]); + /* Select pairwise/group ciphers */ + switch (eEncStatus) { + case ENUM_ENCRYPTION4_ENABLED: + for (i = 0; i < prBssRsnInfo->u4PairwiseKeyCipherSuiteCount; + i++) { + /* TODO: WTBL cipher filed cannot + * 1-1 mapping to spec cipher suite number + */ + if (prBssRsnInfo->au4PairwiseKeyCipherSuite[i] == + RSN_CIPHER_SUITE_GCMP_256) { + u4PairwiseCipher = + prBssRsnInfo-> + au4PairwiseKeyCipherSuite[i]; + } + } + u4GroupCipher = prBssRsnInfo->u4GroupKeyCipherSuite; + break; + + 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, INFO, + "Failed to select pairwise/group cipher (0x%08x/0x%08x)\n", + u4PairwiseCipher, u4GroupCipher); + return FALSE; + } +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && + (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType == NETWORK_TYPE_P2P)) { + if (u4PairwiseCipher != RSN_CIPHER_SUITE_CCMP || + u4GroupCipher != RSN_CIPHER_SUITE_CCMP + || u4AkmSuite != RSN_AKM_SUITE_PSK) { + DBGLOG(RSN, INFO, + "Failed to select pairwise/group cipher for P2P network (0x%08x/0x%08x)\n", + u4PairwiseCipher, u4GroupCipher); + return FALSE; + } + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + if (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType == NETWORK_TYPE_BOW) { + if (u4PairwiseCipher != RSN_CIPHER_SUITE_CCMP || + u4GroupCipher != RSN_CIPHER_SUITE_CCMP + || u4AkmSuite != RSN_AKM_SUITE_PSK) { + DBGLOG(RSN, INFO, + "Failed to select pairwise/group cipher for BT over Wi-Fi network (0x%08x/0x%08x)\n", + u4PairwiseCipher, u4GroupCipher); + return FALSE; + } + } +#endif + + /* Verify if selected pairwisse cipher is supported */ + fgSuiteSupported = rsnSearchSupportedCipher(prAdapter, + u4PairwiseCipher, &i, ucBssIndex); + + /* Verify if selected group cipher is supported */ + if (fgSuiteSupported) + fgSuiteSupported = rsnSearchSupportedCipher(prAdapter, + u4GroupCipher, &i, ucBssIndex); + + if (!fgSuiteSupported) { + DBGLOG(RSN, INFO, + "Failed to support selected pairwise/group cipher (0x%08x/0x%08x)\n", + u4PairwiseCipher, u4GroupCipher); + return FALSE; + } + + /* Select AKM */ + /* If the driver cannot support any authentication suites advertised in + * the given BSS, we fail to perform RSNA policy selection. + */ + /* Attempt to find any overlapping supported AKM suite. */ + if (eAuthMode == + AUTH_MODE_WPA2_FT_PSK && + rsnSearchAKMSuite(prAdapter, + RSN_AKM_SUITE_FT_PSK, &j, ucBssIndex)) + u4AkmSuite = RSN_AKM_SUITE_FT_PSK; + else if (eAuthMode == + AUTH_MODE_WPA2_FT && + rsnSearchAKMSuite(prAdapter, + RSN_AKM_SUITE_FT_802_1X, &j, ucBssIndex)) + u4AkmSuite = RSN_AKM_SUITE_FT_802_1X; + else +#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, + ucBssIndex)) { + 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: 0x%x/0x%x\n", + SWAP32(u4PairwiseCipher), SWAP32(u4GroupCipher)); + + DBGLOG(RSN, TRACE, + "Selected AKM suite: 0x%x\n", SWAP32(u4AkmSuite)); + +#if CFG_SUPPORT_802_11W + DBGLOG(RSN, TRACE, "[MFP] MFP setting = %d\n", + kalGetMfpSetting(prAdapter->prGlueInfo, ucBssIndex)); + + if (kalGetMfpSetting(prAdapter->prGlueInfo, + ucBssIndex) == RSN_AUTH_MFP_REQUIRED) { + if (!prBssRsnInfo->fgRsnCapPresent) { + DBGLOG(RSN, TRACE, + "[MFP] Skip RSN IE, No MFP Required Capability.\n"); + return FALSE; + } else if (!(prBssRsnInfo->u2RsnCap & ELEM_WPA_CAP_MFPC)) { + DBGLOG(RSN, WARN, + "[MFP] Skip RSN IE, No MFP Required\n"); + return FALSE; + } + aisGetAisSpecBssInfo(prAdapter, ucBssIndex) + ->fgMgmtProtection = TRUE; + } else if (kalGetMfpSetting(prAdapter->prGlueInfo, + ucBssIndex) == + RSN_AUTH_MFP_OPTIONAL) { + if (prBssRsnInfo->u2RsnCap & (ELEM_WPA_CAP_MFPR | + ELEM_WPA_CAP_MFPC)) + aisGetAisSpecBssInfo(prAdapter, ucBssIndex) + ->fgMgmtProtection = TRUE; + } else { + if ((prBssRsnInfo->fgRsnCapPresent) && + (prBssRsnInfo->u2RsnCap & ELEM_WPA_CAP_MFPR)) { + DBGLOG(RSN, INFO, + "[MFP] Skip RSN IE, No MFP Required Capability\n"); + return FALSE; + } + } + + DBGLOG(RSN, TRACE, + "setting=%d, Cap=%d, CapPresent=%d, MgmtProtection = %d\n", + kalGetMfpSetting(prAdapter->prGlueInfo, ucBssIndex), + prBssRsnInfo->u2RsnCap, + prBssRsnInfo->fgRsnCapPresent, + aisGetAisSpecBssInfo(prAdapter, ucBssIndex) + ->fgMgmtProtection); +#endif + + /* TODO: WTBL cipher filed cannot + * 1-1 mapping to spec cipher suite number + */ + if (u4GroupCipher == RSN_CIPHER_SUITE_GCMP_256) { + prBss->ucEncLevel = 4; + } else 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 { + DBGLOG(RSN, WARN, + "GroupCipher not in CCMP/TKIP/WEP40/WEP104\n"); + } + 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 struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + uint32_t i; + struct WPA_INFO_ELEM *prWpaIE; + uint32_t u4Suite; + uint16_t u2SuiteCount; + uint8_t *cp, *cp2; + uint8_t ucExpendedLen = 0; + uint8_t *pucBuffer; + uint8_t ucBssIndex; + + DEBUGFUNC("rsnGenerateWpaNoneIE"); + + ucBssIndex = prMsduInfo->ucBssIndex; + + if (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType != NETWORK_TYPE_AIS) + return; + + if (aisGetAuthMode(prAdapter, ucBssIndex) != AUTH_MODE_WPA_NONE) + return; + + pucBuffer = (uint8_t *) ((unsigned long) + prMsduInfo->prPacket + (unsigned long) + prMsduInfo->u2FrameLength); + prWpaIE = (struct WPA_INFO_ELEM *)(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 = (uint8_t *) &prWpaIE->aucPairwiseKeyCipherSuite1[0]; + + if (rsnSearchSupportedCipher(prAdapter, + WPA_CIPHER_SUITE_CCMP, &i, ucBssIndex)) + u4Suite = WPA_CIPHER_SUITE_CCMP; + else if (rsnSearchSupportedCipher(prAdapter, + WPA_CIPHER_SUITE_TKIP, &i, ucBssIndex)) + u4Suite = WPA_CIPHER_SUITE_TKIP; + else if (rsnSearchSupportedCipher(prAdapter, + WPA_CIPHER_SUITE_WEP104, &i, ucBssIndex)) + u4Suite = WPA_CIPHER_SUITE_WEP104; + else if (rsnSearchSupportedCipher(prAdapter, + WPA_CIPHER_SUITE_WEP40, &i, ucBssIndex)) + u4Suite = WPA_CIPHER_SUITE_WEP40; + else + u4Suite = WPA_CIPHER_SUITE_TKIP; + + WLAN_SET_FIELD_32(cp, u4Suite); + u2SuiteCount++; + ucExpendedLen += 4; + + cp = pucBuffer + sizeof(struct WPA_INFO_ELEM); + + /* 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, ucBssIndex)) + u4Suite = WPA_AKM_SUITE_802_1X; + else if (rsnSearchAKMSuite(prAdapter, + WPA_AKM_SUITE_PSK, &i, ucBssIndex)) + u4Suite = WPA_AKM_SUITE_PSK; + else + u4Suite = WPA_AKM_SUITE_NONE; + + /* This shall be the only available value for current implementation */ + ASSERT(u4Suite == WPA_AKM_SUITE_NONE); + + WLAN_SET_FIELD_32(cp, u4Suite); + u2SuiteCount++; + ucExpendedLen += 4; + cp += 4; + + /* Fill the Authentication and Key Management Suite Count field. */ + WLAN_SET_FIELD_16(cp2, u2SuiteCount); + ucExpendedLen += 2; + + /* Fill the Length field. */ + prWpaIE->ucLength = (uint8_t) ucExpendedLen; + + /* Increment the total IE length for the Element ID + * and Length fields. + */ + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + +} /* rsnGenerateWpaNoneIE */ + +uint32_t _addWPAIE_impl(IN struct ADAPTER *prAdapter, + IN OUT struct MSDU_INFO *prMsduInfo) +{ + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecBssInfo; + struct BSS_INFO *prBssInfo; + uint8_t ucBssIndex; + + ucBssIndex = prMsduInfo->ucBssIndex; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (!prAdapter->rWifiVar.fgReuseRSNIE) + return FALSE; + + if (!prBssInfo) + return FALSE; + + /* AP + GO */ + if (!IS_BSS_APGO(prBssInfo)) + return FALSE; + + /* AP only */ + if (!p2pFuncIsAPMode( + prAdapter->rWifiVar. + prP2PConnSettings[prBssInfo->u4PrivateData])) + return FALSE; + + /* PMF only */ + if (!prBssInfo->rApPmfCfg.fgMfpc) + return FALSE; + + prP2pSpecBssInfo = + prAdapter->rWifiVar. + prP2pSpecificBssInfo[prBssInfo->u4PrivateData]; + + if (prP2pSpecBssInfo && + (prP2pSpecBssInfo->u2WpaIeLen != 0)) { + uint8_t *pucBuffer = + (uint8_t *) ((unsigned long) + prMsduInfo->prPacket + (unsigned long) + prMsduInfo->u2FrameLength); + + kalMemCopy(pucBuffer, + prP2pSpecBssInfo->aucWpaIeBuffer, + prP2pSpecBssInfo->u2WpaIeLen); + prMsduInfo->u2FrameLength += prP2pSpecBssInfo->u2WpaIeLen; + + DBGLOG(RSN, INFO, + "Keep supplicant WPA IE content w/o update\n"); + + return TRUE; + } + + return FALSE; +} + + +uint32_t _addRSNIE_impl(IN struct ADAPTER *prAdapter, + IN OUT struct MSDU_INFO *prMsduInfo) +{ + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecBssInfo; + struct BSS_INFO *prBssInfo; + uint8_t ucBssIndex; + + ucBssIndex = prMsduInfo->ucBssIndex; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (!prAdapter->rWifiVar.fgReuseRSNIE) + return FALSE; + + if (!prBssInfo) + return FALSE; + + /* AP + GO */ + if (!IS_BSS_APGO(prBssInfo)) + return FALSE; + + /* AP only */ + if (!p2pFuncIsAPMode( + prAdapter->rWifiVar. + prP2PConnSettings[prBssInfo->u4PrivateData])) + return FALSE; + + /* PMF only */ + if (!prBssInfo->rApPmfCfg.fgMfpc) + return FALSE; + + prP2pSpecBssInfo = + prAdapter->rWifiVar. + prP2pSpecificBssInfo[prBssInfo->u4PrivateData]; + + if (prP2pSpecBssInfo && + (prP2pSpecBssInfo->u2RsnIeLen != 0)) { + uint8_t *pucBuffer = + (uint8_t *) ((unsigned long) + prMsduInfo->prPacket + (unsigned long) + prMsduInfo->u2FrameLength); + + kalMemCopy(pucBuffer, + prP2pSpecBssInfo->aucRsnIeBuffer, + prP2pSpecBssInfo->u2RsnIeLen); + prMsduInfo->u2FrameLength += prP2pSpecBssInfo->u2RsnIeLen; + + DBGLOG(RSN, INFO, + "Keep supplicant RSN IE content w/o update\n"); + + return TRUE; + } + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * + * \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 struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + uint8_t *cp; + uint8_t *pucBuffer; + uint8_t ucBssIndex; + struct BSS_INFO *prBssInfo; + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo; + enum ENUM_PARAM_AUTH_MODE eAuthMode; + + DEBUGFUNC("rsnGenerateWPAIE"); + + pucBuffer = (uint8_t *) ((unsigned long) + prMsduInfo->prPacket + (unsigned long) + prMsduInfo->u2FrameLength); + ucBssIndex = prMsduInfo->ucBssIndex; + eAuthMode = + aisGetAuthMode(prAdapter, ucBssIndex); + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + prP2pSpecificBssInfo = + prAdapter->rWifiVar. + prP2pSpecificBssInfo[prBssInfo->u4PrivateData]; + + /* if (eNetworkId != NETWORK_TYPE_AIS_INDEX) */ + /* return; */ + if (_addWPAIE_impl(prAdapter, prMsduInfo)) + return; + +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered && + GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)-> + eNetworkType == NETWORK_TYPE_P2P && + kalP2PGetTkipCipher(prAdapter->prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData)) || + (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)-> + eNetworkType == NETWORK_TYPE_AIS && + (eAuthMode == + AUTH_MODE_WPA || + eAuthMode == + AUTH_MODE_WPA_PSK))) { +#else + if (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)-> + eNetworkType == NETWORK_TYPE_AIS && + (eAuthMode == + AUTH_MODE_WPA || + eAuthMode == + AUTH_MODE_WPA_PSK)) { +#endif + if (prAdapter->fgIsP2PRegistered && prP2pSpecificBssInfo + && (prP2pSpecificBssInfo->u2WpaIeLen != 0)) { + kalMemCopy(pucBuffer, + prP2pSpecificBssInfo->aucWpaIeBuffer, + prP2pSpecificBssInfo->u2WpaIeLen); + prMsduInfo->u2FrameLength += + prP2pSpecificBssInfo->u2WpaIeLen; + return; + } + /* Construct a WPA IE for association request frame. */ + WPA_IE(pucBuffer)->ucElemId = ELEM_ID_WPA; + WPA_IE(pucBuffer)->ucLength = ELEM_ID_WPA_LEN_FIXED; + WPA_IE(pucBuffer)->aucOui[0] = 0x00; + WPA_IE(pucBuffer)->aucOui[1] = 0x50; + WPA_IE(pucBuffer)->aucOui[2] = 0xF2; + WPA_IE(pucBuffer)->ucOuiType = VENDOR_OUI_TYPE_WPA; + WLAN_SET_FIELD_16(&WPA_IE(pucBuffer)->u2Version, 1); + +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered + && GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType == NETWORK_TYPE_P2P) { + WLAN_SET_FIELD_32( + &WPA_IE(pucBuffer)->u4GroupKeyCipherSuite, + WPA_CIPHER_SUITE_TKIP); + } else +#endif + WLAN_SET_FIELD_32( + &WPA_IE(pucBuffer)->u4GroupKeyCipherSuite, + prBssInfo-> + u4RsnSelectedGroupCipher); + + cp = (uint8_t *) & + WPA_IE(pucBuffer)->aucPairwiseKeyCipherSuite1[0]; + + WLAN_SET_FIELD_16(&WPA_IE(pucBuffer)-> + u2PairwiseKeyCipherSuiteCount, 1); +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered + && GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)-> + eNetworkType == NETWORK_TYPE_P2P) { + WLAN_SET_FIELD_32(cp, WPA_CIPHER_SUITE_TKIP); + } else +#endif + WLAN_SET_FIELD_32(cp, prBssInfo + ->u4RsnSelectedPairwiseCipher); + + cp = pucBuffer + sizeof(struct WPA_INFO_ELEM); + + WLAN_SET_FIELD_16(cp, 1); + cp += 2; +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered + && GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)-> + eNetworkType == NETWORK_TYPE_P2P) { + WLAN_SET_FIELD_32(cp, WPA_AKM_SUITE_PSK); + } else +#endif + WLAN_SET_FIELD_32(cp, prBssInfo + ->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 struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct PMKID_ENTRY *entry = NULL; + uint8_t *cp; + /* UINT_8 ucExpendedLen = 0; */ + uint8_t *pucBuffer; + uint8_t ucBssIndex; + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + enum ENUM_PARAM_AUTH_MODE eAuthMode; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecBssInfo; + + DEBUGFUNC("rsnGenerateRSNIE"); + + pucBuffer = (uint8_t *) ((unsigned long) + prMsduInfo->prPacket + (unsigned long) + prMsduInfo->u2FrameLength); + /* Todo:: network id */ + ucBssIndex = prMsduInfo->ucBssIndex; + prAisSpecBssInfo = aisGetAisSpecBssInfo(prAdapter, ucBssIndex); + eAuthMode = aisGetAuthMode(prAdapter, ucBssIndex); + + /* For FT, we reuse the RSN Element composed in userspace */ + if (authAddRSNIE_impl(prAdapter, prMsduInfo)) + return; + + if (_addRSNIE_impl(prAdapter, prMsduInfo)) + return; + + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + + if ( +#if CFG_ENABLE_WIFI_DIRECT + ((prAdapter->fgIsP2PRegistered) && + (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType == NETWORK_TYPE_P2P) + && (kalP2PGetCcmpCipher(prAdapter->prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData))) || +#endif +#if CFG_ENABLE_BT_OVER_WIFI + (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType == NETWORK_TYPE_BOW) + || +#endif + (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType == + NETWORK_TYPE_AIS /* prCurrentBss->fgIERSN */ && + rsnKeyMgmtWpa(prAdapter, eAuthMode, ucBssIndex))) { + /* Construct a RSN IE for association request frame. */ + RSN_IE(pucBuffer)->ucElemId = ELEM_ID_RSN; + RSN_IE(pucBuffer)->ucLength = ELEM_ID_RSN_LEN_FIXED; + /* Version */ + WLAN_SET_FIELD_16(&RSN_IE(pucBuffer)->u2Version, 1); + WLAN_SET_FIELD_32(&RSN_IE(pucBuffer)->u4GroupKeyCipherSuite, + GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)-> + u4RsnSelectedGroupCipher); + /* Group key suite */ + cp = (uint8_t *) &RSN_IE( + pucBuffer)->aucPairwiseKeyCipherSuite1[0]; + WLAN_SET_FIELD_16(&RSN_IE( + pucBuffer)->u2PairwiseKeyCipherSuiteCount, 1); + WLAN_SET_FIELD_32(cp, GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->u4RsnSelectedPairwiseCipher); + + cp = pucBuffer + sizeof(struct RSN_INFO_ELEM); + + if ((prBssInfo->eNetworkType == NETWORK_TYPE_P2P) && + (prBssInfo->u4RsnSelectedAKMSuite == + RSN_AKM_SUITE_SAE)) { + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecBssInfo = + prAdapter->rWifiVar.prP2pSpecificBssInfo + [prBssInfo->u4PrivateData]; + uint8_t i = 0; + + /* AKM suite count */ + WLAN_SET_FIELD_16(cp, + prP2pSpecBssInfo->u4KeyMgtSuiteCount); + cp += 2; + + /* AKM suite */ + for (i = 0; + i < prP2pSpecBssInfo->u4KeyMgtSuiteCount; + i++) { + DBGLOG(RSN, TRACE, "KeyMgtSuite 0x%04x\n", + prP2pSpecBssInfo->au4KeyMgtSuite[i]); + WLAN_SET_FIELD_32(cp, + prP2pSpecBssInfo->au4KeyMgtSuite[i]); + cp += 4; + } + + RSN_IE(pucBuffer)->ucLength += + (prP2pSpecBssInfo->u4KeyMgtSuiteCount - 1) * 4; + } else { + WLAN_SET_FIELD_16(cp, 1); /* AKM suite count */ + cp += 2; + /* AKM suite */ + WLAN_SET_FIELD_32(cp, GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->u4RsnSelectedAKMSuite); + cp += 4; + } + + /* Capabilities */ + WLAN_SET_FIELD_16(cp, GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->u2RsnSelectedCapInfo); + DBGLOG(RSN, TRACE, + "Gen RSN IE = %x\n", GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->u2RsnSelectedCapInfo); + #if CFG_SUPPORT_802_11W + if (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType == NETWORK_TYPE_AIS) { + if (kalGetRsnIeMfpCap(prAdapter->prGlueInfo, + ucBssIndex) == + RSN_AUTH_MFP_REQUIRED) { + WLAN_SET_FIELD_16(cp, + ELEM_WPA_CAP_MFPC | ELEM_WPA_CAP_MFPR); + /* Capabilities */ + DBGLOG(RSN, TRACE, + "RSN_AUTH_MFP - MFPC & MFPR\n"); + } else if (kalGetRsnIeMfpCap(prAdapter->prGlueInfo, + ucBssIndex) == + RSN_AUTH_MFP_OPTIONAL) { + WLAN_SET_FIELD_16(cp, ELEM_WPA_CAP_MFPC); + /* Capabilities */ + DBGLOG(RSN, TRACE, "RSN_AUTH_MFP - MFPC\n"); + } else { + DBGLOG(RSN, TRACE, + "!RSN_AUTH_MFP - No MFPC!\n"); + } + } else if ((GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)-> + eNetworkType == NETWORK_TYPE_P2P) && + (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eCurrentOPMode == + (uint8_t) OP_MODE_ACCESS_POINT)) { + /* AP PMF */ + /* for AP mode, keep origin RSN IE content w/o update */ + } +#endif + cp += 2; + + /* Fill PMKID and Group Management Cipher for AIS */ + if (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType == NETWORK_TYPE_AIS) { + prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + + if (!prStaRec) { + DBGLOG(RSN, ERROR, "prStaRec is NULL!"); + } else { + entry = rsnSearchPmkidEntry(prAdapter, + prStaRec->aucMacAddr, ucBssIndex); + } + /* Fill PMKID Count and List field */ + if (entry) { + uint8_t *pmk = entry->rBssidInfo.arPMKID; + + RSN_IE(pucBuffer)->ucLength = 38; + /* Fill PMKID Count field */ + WLAN_SET_FIELD_16(cp, 1); + cp += 2; + DBGLOG(RSN, INFO, "BSSID " MACSTR + "use PMKID " PMKSTR "\n", + MAC2STR(entry->rBssidInfo.arBSSID), + pmk[0], pmk[1], pmk[2], pmk[3], pmk[4], + pmk[5], pmk[6], pmk[7], pmk[8], pmk[9], + pmk[10], pmk[11], pmk[12] + pmk[13], + pmk[14], pmk[15]); + /* Fill PMKID List field */ + kalMemCopy(cp, entry->rBssidInfo.arPMKID, + IW_PMKID_LEN); + cp += IW_PMKID_LEN; + } +#if CFG_SUPPORT_802_11W + else { + /* Follow supplicant flow to + * fill PMKID Count field = 0 only when + * Group Management Cipher field + * need to be filled + */ + if (prAisSpecBssInfo + ->fgMgmtProtection) { + WLAN_SET_FIELD_16(cp, 0) + + cp += 2; + RSN_IE(pucBuffer)->ucLength += 2; + } + } + + /* Fill Group Management Cipher field */ + if (prAisSpecBssInfo->fgMgmtProtection) { + 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 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t +rsnParseCheckForWFAInfoElem(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, OUT uint8_t *pucOuiType, + OUT uint16_t *pu2SubTypeVersion) +{ + uint8_t aucWfaOui[] = VENDOR_OUI_WFA; + struct IE_WFA *prWfaIE; + + prWfaIE = (struct IE_WFA *)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(struct ADAPTER *prAdapter, + struct RSN_INFO_ELEM *prIe, + struct STA_RECORD *prStaRec, + uint16_t *pu2StatusCode) +{ + + struct RSN_INFO rRsnIe; + struct BSS_INFO *prBssInfo; + uint8_t i; + uint16_t statusCode; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + *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; + } + /* When softap's conf support both TKIP&CCMP, + * the Group Cipher Suite would be TKIP + * If we check the Group Cipher Suite == CCMP + * about peer's Asso Req + * The connection would be fail + * due to STATUS_CODE_INVALID_GROUP_CIPHER + */ + if (rRsnIe.u4GroupKeyCipherSuite != RSN_CIPHER_SUITE_CCMP && + !prAdapter->rWifiVar.fgReuseRSNIE) { + *pu2StatusCode = STATUS_CODE_INVALID_GROUP_CIPHER; + return; + } + + if ((rRsnIe.u4AuthKeyMgtSuiteCount != 1) + || ((rRsnIe.au4AuthKeyMgtSuite[0] != RSN_AKM_SUITE_PSK) +#if CFG_SUPPORT_SOFTAP_WPA3 + && (rRsnIe.au4AuthKeyMgtSuite[0] != RSN_AKM_SUITE_SAE) +#endif + )) { + DBGLOG(RSN, WARN, "RSN with invalid AKMP\n"); + *pu2StatusCode = STATUS_CODE_INVALID_AKMP; + return; + } + + if (prAdapter->rWifiVar.fgSapCheckPmkidInDriver + && prBssInfo->u4RsnSelectedAKMSuite + == RSN_AKM_SUITE_SAE + && rRsnIe.u2PmkidCount > 0) { + struct PMKID_ENTRY *entry = + rsnSearchPmkidEntry(prAdapter, + prStaRec->aucMacAddr, + prStaRec->ucBssIndex); + + DBGLOG(RSN, LOUD, + "Parse PMKID " PMKSTR " from " MACSTR "\n", + rRsnIe.aucPmkid[0], rRsnIe.aucPmkid[1], + rRsnIe.aucPmkid[2], rRsnIe.aucPmkid[3], + rRsnIe.aucPmkid[4], rRsnIe.aucPmkid[5], + rRsnIe.aucPmkid[6], rRsnIe.aucPmkid[7], + rRsnIe.aucPmkid[8], rRsnIe.aucPmkid[9], + rRsnIe.aucPmkid[10], rRsnIe.aucPmkid[11], + rRsnIe.aucPmkid[12] + rRsnIe.aucPmkid[13], + rRsnIe.aucPmkid[14], rRsnIe.aucPmkid[15], + MAC2STR(prStaRec->aucMacAddr)); + + if (!entry) { + DBGLOG(RSN, WARN, "RSN with no PMKID\n"); + *pu2StatusCode = STATUS_INVALID_PMKID; + return; + } else if (kalMemCmp( + rRsnIe.aucPmkid, + entry->rBssidInfo.arPMKID, + IW_PMKID_LEN) != 0) { + DBGLOG(RSN, WARN, "RSN with invalid PMKID\n"); + *pu2StatusCode = STATUS_INVALID_PMKID; + return; + } + + } + + DBGLOG(RSN, TRACE, "RSN with CCMP-PSK\n"); + *pu2StatusCode = WLAN_STATUS_SUCCESS; + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + /* 1st check: if already PMF connection, reject assoc req: + * error 30 ASSOC_REJECTED_TEMPORARILY + */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(AAA, INFO, + "Drop RxAssoc\n"); + *pu2StatusCode = STATUS_CODE_ASSOC_REJECTED_TEMPORARILY; + return; + } + + /* if RSN capability not exist, just return */ + if (!rRsnIe.fgRsnCapPresent) { + *pu2StatusCode = WLAN_STATUS_SUCCESS; + return; + } + + prStaRec->rPmfCfg.fgMfpc = (rRsnIe.u2RsnCap & + ELEM_WPA_CAP_MFPC) ? 1 : 0; + prStaRec->rPmfCfg.fgMfpr = (rRsnIe.u2RsnCap & + ELEM_WPA_CAP_MFPR) ? 1 : 0; + + prStaRec->rPmfCfg.fgSaeRequireMfp = FALSE; + + for (i = 0; i < rRsnIe.u4AuthKeyMgtSuiteCount; i++) { + if ((rRsnIe.au4AuthKeyMgtSuite[i] == + RSN_AKM_SUITE_802_1X_SHA256) || + (rRsnIe.au4AuthKeyMgtSuite[i] == + RSN_AKM_SUITE_PSK_SHA256)) { + DBGLOG(RSN, INFO, "STA SHA256 support\n"); + prStaRec->rPmfCfg.fgSha256 = TRUE; + break; + } else if (rRsnIe.au4AuthKeyMgtSuite[i] == + RSN_AKM_SUITE_SAE) { + DBGLOG(RSN, INFO, "STA SAE support\n"); + prStaRec->rPmfCfg.fgSaeRequireMfp = TRUE; + break; + } + } + + DBGLOG(RSN, INFO, + "STA Assoc req mfpc:%d, mfpr:%d, sha256:%d, bssIndex:%d, applyPmf:%d\n", + prStaRec->rPmfCfg.fgMfpc, prStaRec->rPmfCfg.fgMfpr, + prStaRec->rPmfCfg.fgSha256, prStaRec->ucBssIndex, + prStaRec->rPmfCfg.fgApplyPmf); + + /* if PMF validation fail, return success as legacy association + */ + statusCode = rsnPmfCapableValidation(prAdapter, prBssInfo, + prStaRec); + *pu2StatusCode = statusCode; +#endif + } + +} +#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 struct ADAPTER *prAdapter, + IN struct STA_RECORD *prSta, IN u_int8_t fgFlags) +{ + struct PARAM_INDICATION_EVENT authEvent; + struct BSS_INFO *prAisBssInfo; + uint8_t ucBssIndex = 0; + + DEBUGFUNC("rsnGenMicErrorEvent"); + + ucBssIndex = prSta->ucBssIndex; + + prAisBssInfo = + aisGetAisBssInfo(prAdapter, + ucBssIndex); + + /* Status type: Authentication Event */ + authEvent.rStatus.eStatusType = ENUM_STATUS_TYPE_AUTHENTICATION; + + /* Authentication request */ + authEvent.rAuthReq.u4Length = sizeof(struct PARAM_AUTH_REQUEST); + COPY_MAC_ADDR(authEvent.rAuthReq.arBssid, + prAisBssInfo->aucBSSID); + if (fgFlags == TRUE) + authEvent.rAuthReq.u4Flags = PARAM_AUTH_REQUEST_GROUP_ERROR; + else + authEvent.rAuthReq.u4Flags = PARAM_AUTH_REQUEST_PAIRWISE_ERROR; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (void *)&authEvent, + sizeof(struct PARAM_INDICATION_EVENT), + ucBssIndex); +} /* 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 struct ADAPTER *prAdapter, + IN struct STA_RECORD *prSta, + IN u_int8_t fgErrorKeyType) +{ + /* UINT_32 u4RsnaCurrentMICFailTime; */ + /* P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; */ + + DEBUGFUNC("rsnTkipHandleMICFailure"); + +#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 = aisGetAisSpecBssInfo(prAdapter, prSta->ucBssIndex); + + /* 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 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 + */ +/*----------------------------------------------------------------------------*/ +struct PMKID_ENTRY *rsnSearchPmkidEntry(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBssid, + IN uint8_t ucBssIndex) +{ + struct BSS_INFO *prBssInfo; + + struct PMKID_ENTRY *entry; + struct LINK *cache; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex); + cache = &prBssInfo->rPmkidCache; + + LINK_FOR_EACH_ENTRY(entry, cache, rLinkEntry, struct PMKID_ENTRY) { + if (EQUAL_MAC_ADDR(entry->rBssidInfo.arBSSID, pucBssid)) + return entry; + } + + return NULL; +} /* rsnSearchPmkidEntry */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to check the BSS Desc at scan result + * with pre-auth cap at wpa2 mode. If there is no cache entry, + * notify the PMKID indication. + * + * \param[in] prBss The BSS Desc at scan result + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rsnCheckPmkidCache(IN struct ADAPTER *prAdapter, IN struct BSS_DESC *prBss, + IN uint8_t ucBssIndex) +{ + struct BSS_INFO *prAisBssInfo; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecBssInfo; + struct CONNECTION_SETTINGS *prConnSettings; + + if (!prBss) + return; + + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + prAisSpecBssInfo = + aisGetAisSpecBssInfo(prAdapter, ucBssIndex); + + /* Generate pmkid candidate indications for other APs which are + * also belong to the same SSID with the current connected AP or + * beacon timeout AP but have no available pmkid. + */ + if ((prAisBssInfo->eConnectionState == MEDIA_STATE_CONNECTED || + (prAisBssInfo->eConnectionState == MEDIA_STATE_DISCONNECTED && + aisFsmIsInProcessPostpone(prAdapter, ucBssIndex))) && + prConnSettings->eAuthMode == AUTH_MODE_WPA2 && + EQUAL_SSID(prBss->aucSSID, prBss->ucSSIDLen, + prConnSettings->aucSSID, prConnSettings->ucSSIDLen) && + UNEQUAL_MAC_ADDR(prBss->aucBSSID, prAisBssInfo->aucBSSID) && + !rsnSearchPmkidEntry(prAdapter, prBss->aucBSSID, + ucBssIndex)) { + struct PARAM_PMKID_CANDIDATE candidate; + + COPY_MAC_ADDR(candidate.arBSSID, prBss->aucBSSID); + candidate.u4Flags = prBss->u2RsnCap & MASK_RSNIE_CAP_PREAUTH; + rsnGeneratePmkidIndication(prAdapter, &candidate, + ucBssIndex); + + DBGLOG(RSN, TRACE, "[%d] Generate " MACSTR + " with preauth %d to pmkid candidate list\n", + ucBssIndex, + MAC2STR(prBss->aucBSSID), candidate.u4Flags); + } +} /* rsnCheckPmkidCache */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to add/update pmkid. + * + * \param[in] prPmkid The new pmkid + * + * \return status + */ +/*----------------------------------------------------------------------------*/ +uint32_t rsnSetPmkid(IN struct ADAPTER *prAdapter, + IN struct PARAM_PMKID *prPmkid) +{ + struct BSS_INFO *prBssInfo; + struct PMKID_ENTRY *entry; + struct LINK *cache; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prPmkid->ucBssIdx); + cache = &prBssInfo->rPmkidCache; + + entry = rsnSearchPmkidEntry(prAdapter, prPmkid->arBSSID, + prPmkid->ucBssIdx); + if (!entry) { + entry = kalMemAlloc(sizeof(struct PMKID_ENTRY), VIR_MEM_TYPE); + if (!entry) + return -ENOMEM; + LINK_INSERT_TAIL(cache, &entry->rLinkEntry); + } + + DBGLOG(RSN, INFO, + "[%d] Set " MACSTR ", total %d, PMKID " PMKSTR "\n", + prPmkid->ucBssIdx, + MAC2STR(prPmkid->arBSSID), cache->u4NumElem, + prPmkid->arPMKID[0], prPmkid->arPMKID[1], prPmkid->arPMKID[2], + prPmkid->arPMKID[3], prPmkid->arPMKID[4], prPmkid->arPMKID[5], + prPmkid->arPMKID[6], prPmkid->arPMKID[7], prPmkid->arPMKID[8], + prPmkid->arPMKID[9], prPmkid->arPMKID[10], prPmkid->arPMKID[11], + prPmkid->arPMKID[12] + prPmkid->arPMKID[13], + prPmkid->arPMKID[14], prPmkid->arPMKID[15]); + + kalMemCopy(&entry->rBssidInfo, prPmkid, sizeof(struct PARAM_PMKID)); + return WLAN_STATUS_SUCCESS; +} /* rsnSetPmkid */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to del pmkid. + * + * \param[in] prPmkid pmkid should be deleted + * + * \return status + */ +/*----------------------------------------------------------------------------*/ +uint32_t rsnDelPmkid(IN struct ADAPTER *prAdapter, + IN struct PARAM_PMKID *prPmkid) +{ + struct BSS_INFO *prBssInfo; + struct PMKID_ENTRY *entry; + struct LINK *cache; + + if (!prPmkid) + return WLAN_STATUS_INVALID_DATA; + + DBGLOG(RSN, TRACE, "[%d] Del " MACSTR " pmkid\n", + prPmkid->ucBssIdx, + MAC2STR(prPmkid->arBSSID)); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prPmkid->ucBssIdx); + cache = &prBssInfo->rPmkidCache; + entry = rsnSearchPmkidEntry(prAdapter, prPmkid->arBSSID, + prPmkid->ucBssIdx); + if (entry) { + if (kalMemCmp(prPmkid->arPMKID, + entry->rBssidInfo.arPMKID, IW_PMKID_LEN)) { + DBGLOG(RSN, WARN, "Del " MACSTR " pmkid but mismatch\n", + MAC2STR(prPmkid->arBSSID)); + } + LINK_REMOVE_KNOWN_ENTRY(cache, entry); + kalMemFree(entry, VIR_MEM_TYPE, sizeof(struct PMKID_ENTRY)); + } + + return WLAN_STATUS_SUCCESS; +} /* rsnDelPmkid */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to delete all pmkid. + * + * \return status + */ +/*----------------------------------------------------------------------------*/ +uint32_t rsnFlushPmkid(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIndex) +{ + struct BSS_INFO *prBssInfo; + struct PMKID_ENTRY *entry; + struct LINK *cache; + + prBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + cache = &prBssInfo->rPmkidCache; + + DBGLOG(RSN, TRACE, "[%d] Flush Pmkid total:%d\n", + ucBssIndex, + cache->u4NumElem); + + while (!LINK_IS_EMPTY(cache)) { + LINK_REMOVE_HEAD(cache, entry, struct PMKID_ENTRY *); + kalMemFree(entry, VIR_MEM_TYPE, sizeof(struct PMKID_ENTRY)); + } + return WLAN_STATUS_SUCCESS; +} /* rsnDelPmkid */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct ADAPTER *prAdapter, + IN struct PARAM_PMKID_CANDIDATE *prCandi, + IN uint8_t ucBssIndex) +{ + struct PARAM_INDICATION_EVENT pmkidEvent; + + DEBUGFUNC("rsnGeneratePmkidIndication"); + + /* Status type: PMKID Candidatelist Event */ + pmkidEvent.rStatus.eStatusType = ENUM_STATUS_TYPE_CANDIDATE_LIST; + kalMemCopy(&pmkidEvent.rCandi, prCandi, + sizeof(struct PARAM_PMKID_CANDIDATE)); + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (void *) &pmkidEvent, + sizeof(struct PARAM_INDICATION_EVENT), + ucBssIndex); +} /* rsnGeneratePmkidIndication */ + +#if CFG_SUPPORT_802_11W + +/*----------------------------------------------------------------------------*/ +/*! + * \brief to check if the Bip Key installed or not + * + * \param[in] + * prAdapter + * + * \return + * TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +uint32_t rsnCheckBipKeyInstalled(IN struct ADAPTER + *prAdapter, IN struct STA_RECORD *prStaRec) +{ + /* caution: prStaRec might be null ! */ + if (prStaRec) { + if (GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex) + ->eNetworkType == (uint8_t) NETWORK_TYPE_AIS) { + return aisGetAisSpecBssInfo(prAdapter, + prStaRec->ucBssIndex) + ->fgBipKeyInstalled; + } else if ((GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex) + ->eNetworkType == NETWORK_TYPE_P2P) + && + (GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex) + ->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { + if (prStaRec->rPmfCfg.fgApplyPmf) + DBGLOG(RSN, INFO, "AP-STA PMF capable\n"); + return prStaRec->rPmfCfg.fgApplyPmf; + } else { + return FALSE; + } + } else + return FALSE; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * + * \brief This routine is called to check the Sa query timeout. + * + * + * \note + * Called by: AIS module, Handle by Sa Quert timeout + */ +/*----------------------------------------------------------------------------*/ +uint8_t rsnCheckSaQueryTimeout( + IN struct ADAPTER *prAdapter, IN uint8_t ucBssIdx) +{ + struct AIS_SPECIFIC_BSS_INFO *prBssSpecInfo; + struct BSS_INFO *prAisBssInfo; + uint32_t now; + + prBssSpecInfo = + aisGetAisSpecBssInfo(prAdapter, ucBssIdx); + prAisBssInfo = + aisGetAisBssInfo(prAdapter, ucBssIdx); + + GET_CURRENT_SYSTIME(&now); + + if (CHECK_FOR_TIMEOUT(now, prBssSpecInfo->u4SaQueryStart, + TU_TO_MSEC(1000))) { + DBGLOG(RSN, INFO, "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); +#if 1 + if (prAisBssInfo == NULL) { + DBGLOG(RSN, ERROR, "prAisBssInfo is NULL"); + } else if (prAisBssInfo->eConnectionState == + MEDIA_STATE_CONNECTED) { + struct MSG_AIS_ABORT *prAisAbortMsg; + + prAisAbortMsg = + (struct MSG_AIS_ABORT *) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_AIS_ABORT)); + if (!prAisAbortMsg) + return 0; + prAisAbortMsg->rMsgHdr.eMsgId = MID_SAA_AIS_FSM_ABORT; + prAisAbortMsg->ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_DISASSOCIATED; + prAisAbortMsg->fgDelayIndication = FALSE; + prAisAbortMsg->ucBssIndex = ucBssIdx; + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prAisAbortMsg, + MSG_SEND_METHOD_BUF); + } +#else + /* Re-connect */ + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); +#endif + 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 struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr) +{ + struct BSS_INFO *prBssInfo; + struct AIS_SPECIFIC_BSS_INFO *prBssSpecInfo; + struct MSDU_INFO *prMsduInfo; + struct ACTION_SA_QUERY_FRAME *prTxFrame; + uint16_t u2PayloadLen; + uint8_t *pucTmp = NULL; + uint8_t ucTransId[ACTION_SA_QUERY_TR_ID_LEN]; + uint8_t ucBssIndex = (uint8_t) ulParamPtr; + + prBssInfo = aisGetAisBssInfo(prAdapter, + ucBssIndex); + prBssSpecInfo = aisGetAisSpecBssInfo(prAdapter, ucBssIndex); + + DBGLOG(RSN, INFO, "MFP: Start Sa Query\n"); + + if (prBssInfo->prStaRecOfAP == NULL) { + DBGLOG(RSN, INFO, "MFP: unassociated AP!\n"); + return; + } + + if (prBssSpecInfo->u4SaQueryCount > 0 + && rsnCheckSaQueryTimeout(prAdapter, + ucBssIndex)) { + DBGLOG(RSN, INFO, "MFP: u4SaQueryCount count =%d\n", + prBssSpecInfo->u4SaQueryCount); + return; + } + + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc(prAdapter, + MAC_TX_RESERVED_FIELD + + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + prTxFrame = (struct ACTION_SA_QUERY_FRAME *) + ((unsigned long)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + if (rsnCheckBipKeyInstalled(prAdapter, prBssInfo->prStaRecOfAP)) + 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_QUERY_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"); + cnmMgtPktFree(prAdapter, prMsduInfo); + 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] = (uint8_t) (kalRandomNumber() & 0xFF); + ucTransId[1] = (uint8_t) (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) { + kalMemFree(pucTmp, VIR_MEM_TYPE, + (prBssSpecInfo->u4SaQueryCount - 1) * + ACTION_SA_QUERY_TR_ID_LEN); + DBGLOG(RSN, INFO, + "MFP: Fail to alloc buffer for sa query id list\n"); + cnmMgtPktFree(prAdapter, prMsduInfo); + 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 <3> Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prBssInfo->prStaRecOfAP->ucBssIndex, + prBssInfo->prStaRecOfAP->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, NULL, + MSDU_RATE_MODE_AUTO); + + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + DBGLOG(RSN, INFO, "Set SA Query timer %d (%d Tu)", + prBssSpecInfo->u4SaQueryCount, 201); + + 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 struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx) +{ + struct AIS_SPECIFIC_BSS_INFO *prBssSpecInfo; + + prBssSpecInfo = aisGetAisSpecBssInfo(prAdapter, ucBssIdx); + + if (prBssSpecInfo->u4SaQueryCount == 0) + rsnStartSaQueryTimer(prAdapter, (unsigned long) ucBssIdx); +} + +/*----------------------------------------------------------------------------*/ +/*! + * + * \brief This routine is called to stop the 802.11w sa query. + * + * + * \note + * Called by: AIS module, Handle Rx mgmt request + */ +/*----------------------------------------------------------------------------*/ +void rsnStopSaQuery(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx) +{ + struct AIS_SPECIFIC_BSS_INFO *prBssSpecInfo; + + prBssSpecInfo = aisGetAisSpecBssInfo(prAdapter, ucBssIdx); + + cnmTimerStopTimer(prAdapter, &prBssSpecInfo->rSaQueryTimer); + + if (prBssSpecInfo->pucSaQueryTransId) { + 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 struct ADAPTER *prAdapter, IN struct SW_RFB *prSwRfb) +{ + struct BSS_INFO *prBssInfo; + struct MSDU_INFO *prMsduInfo; + struct ACTION_SA_QUERY_FRAME *prRxFrame = NULL; + uint16_t u2PayloadLen; + struct STA_RECORD *prStaRec; + struct ACTION_SA_QUERY_FRAME *prTxFrame; + uint8_t ucBssIndex = secGetBssIdxByRfb(prAdapter, + prSwRfb); + + prBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + if (!prSwRfb) + return; + + prRxFrame = (struct ACTION_SA_QUERY_FRAME *) + prSwRfb->pvHeader; + if (!prRxFrame) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (!prStaRec) /* Todo:: for not AIS check */ + return; + + DBGLOG(RSN, INFO, + "IEEE 802.11: Received SA Query Request from " MACSTR "\n", + MAC2STR(prStaRec->aucMacAddr)); + + DBGLOG_MEM8(RSN, INFO, prRxFrame->ucTransId, ACTION_SA_QUERY_TR_ID_LEN); + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo, + ucBssIndex) == + MEDIA_STATE_DISCONNECTED) { + DBGLOG(RSN, INFO, + "IEEE 802.11: Ignore SA Query Request from unassociated STA " + MACSTR "\n", MAC2STR(prStaRec->aucMacAddr)); + return; + } + + DBGLOG(RSN, INFO, + "IEEE 802.11: Sending SA Query Response to " MACSTR "\n", + MAC2STR(prStaRec->aucMacAddr)); + + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc(prAdapter, + MAC_TX_RESERVED_FIELD + + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + prTxFrame = (struct ACTION_SA_QUERY_FRAME *) + ((unsigned long)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + if (rsnCheckBipKeyInstalled(prAdapter, prBssInfo->prStaRecOfAP)) + 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_QUERY_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 <3> Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prBssInfo->prStaRecOfAP->ucBssIndex, + prBssInfo->prStaRecOfAP->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, NULL, + MSDU_RATE_MODE_AUTO); + +#if 0 + /* 4 Update information of MSDU_INFO_T */ + /* Management frame */ + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + 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->ucPID = nicAssignPID(prAdapter); + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->fgIsBasicRate = FALSE; +#endif + /* 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 struct ADAPTER *prAdapter, IN struct SW_RFB *prSwRfb) +{ + struct AIS_SPECIFIC_BSS_INFO *prBssSpecInfo; + struct ACTION_SA_QUERY_FRAME *prRxFrame; + struct STA_RECORD *prStaRec; + uint32_t i; + uint8_t ucBssIndex = secGetBssIdxByRfb(prAdapter, + prSwRfb); + + prBssSpecInfo = + aisGetAisSpecBssInfo(prAdapter, ucBssIndex); + + prRxFrame = (struct ACTION_SA_QUERY_FRAME *) + prSwRfb->pvHeader; + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (!prStaRec) + return; + + if (prSwRfb->u2PacketLen < ACTION_SA_QUERY_TR_ID_LEN) { + DBGLOG(RSN, INFO, + "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, INFO, + "IEEE 802.11: Unexpected SA Query Action %d\n", + prRxFrame->ucAction); + return; + } + + DBGLOG(RSN, INFO, + "IEEE 802.11: Received SA Query Response from " MACSTR "\n", + MAC2STR(prStaRec->aucMacAddr)); + + DBGLOG_MEM8(RSN, INFO, 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, INFO, + "IEEE 802.11: No matching SA Query transaction identifier found\n"); + return; + } + + DBGLOG(RSN, INFO, "Reply to pending SA Query received\n"); + + rsnStopSaQuery(prAdapter, ucBssIndex); +} +#endif + +static u_int8_t rsnCheckWpaRsnInfo(struct BSS_INFO *prBss, + struct BSS_DESC *prBssDesc, + struct RSN_INFO *prWpaRsnInfo) +{ + uint32_t i = 0, s; + + if (prWpaRsnInfo->u4GroupKeyCipherSuite != + prBss->u4RsnSelectedGroupCipher) { + DBGLOG(RSN, INFO, + "GroupCipherSuite change, old=0x%04x, new=0x%04x\n", + prBss->u4RsnSelectedGroupCipher, + prWpaRsnInfo->u4GroupKeyCipherSuite); + return TRUE; + } + + /* check akm */ + s = SWAP32(prBss->u4RsnSelectedAKMSuite); + if (prBssDesc->ucIsAdaptive11r && + (s == WLAN_AKM_SUITE_FT_8021X || s == WLAN_AKM_SUITE_FT_PSK)) + return FALSE; + + for (; i < prWpaRsnInfo->u4AuthKeyMgtSuiteCount; i++) + if (prBss->u4RsnSelectedAKMSuite == + prWpaRsnInfo->au4AuthKeyMgtSuite[i]) + break; + + if (i == prWpaRsnInfo->u4AuthKeyMgtSuiteCount) { + DBGLOG(RSN, INFO, + "KeyMgmt change, not find 0x%04x in new beacon\n", + prBss->u4RsnSelectedAKMSuite); + return TRUE; + } + + for (i = 0; i < prWpaRsnInfo->u4PairwiseKeyCipherSuiteCount; i++) + if (prBss->u4RsnSelectedPairwiseCipher == + prWpaRsnInfo->au4PairwiseKeyCipherSuite[i]) + break; + if (i == prWpaRsnInfo->u4PairwiseKeyCipherSuiteCount) { + DBGLOG(RSN, INFO, + "Pairwise Cipher change, not find 0x%04x in new beacon\n", + prBss->u4RsnSelectedPairwiseCipher); + return TRUE; + } + + return FALSE; +} + +u_int8_t rsnCheckSecurityModeChanged( + struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct BSS_DESC *prBssDesc) +{ + uint8_t ucBssIdx = 0; + enum ENUM_PARAM_AUTH_MODE eAuthMode; + struct GL_WPA_INFO *prWpaInfo; + + if (!prBssInfo) { + DBGLOG(RSN, ERROR, "Empty prBssInfo\n"); + return FALSE; + } + ucBssIdx = prBssInfo->ucBssIndex; + eAuthMode = aisGetAuthMode(prAdapter, ucBssIdx); + prWpaInfo = aisGetWpaInfo(prAdapter, ucBssIdx); + + switch (eAuthMode) { + case AUTH_MODE_OPEN: /* original is open system */ + if ((prBssDesc->u2CapInfo & CAP_INFO_PRIVACY) && + !prWpaInfo->fgPrivacyInvoke) { + DBGLOG(RSN, INFO, "security change, open->privacy\n"); + return TRUE; + } + break; + case AUTH_MODE_SHARED: /* original is WEP */ + case AUTH_MODE_AUTO_SWITCH: + if ((prBssDesc->u2CapInfo & CAP_INFO_PRIVACY) == 0) { + DBGLOG(RSN, INFO, "security change, WEP->open\n"); + return TRUE; + } else if (prBssDesc->fgIERSN || prBssDesc->fgIEWPA) { + DBGLOG(RSN, INFO, "security change, WEP->WPA/WPA2\n"); + return TRUE; + } + break; + case AUTH_MODE_WPA: /*original is WPA */ + case AUTH_MODE_WPA_PSK: + case AUTH_MODE_WPA_NONE: + if (prBssDesc->fgIEWPA) + return rsnCheckWpaRsnInfo(prBssInfo, prBssDesc, + &prBssDesc->rWPAInfo); + DBGLOG(RSN, INFO, "security change, WPA->%s\n", + prBssDesc->fgIERSN ? "WPA2" : + (prBssDesc->u2CapInfo & CAP_INFO_PRIVACY ? + "WEP" : "OPEN")); + return TRUE; + case AUTH_MODE_WPA2: /*original is WPA2 */ + case AUTH_MODE_WPA2_PSK: + case AUTH_MODE_WPA2_FT: + case AUTH_MODE_WPA2_FT_PSK: + case AUTH_MODE_WPA3_SAE: + if (prBssDesc->fgIERSN) + return rsnCheckWpaRsnInfo(prBssInfo, prBssDesc, + &prBssDesc->rRSNInfo); + DBGLOG(RSN, INFO, "security change, WPA2->%s\n", + prBssDesc->fgIEWPA ? "WPA" : + (prBssDesc->u2CapInfo & CAP_INFO_PRIVACY ? + "WEP" : "OPEN")); + return TRUE; + default: + DBGLOG(RSN, WARN, "unknowned eAuthMode=%d\n", eAuthMode); + break; + } + return FALSE; +} + +#if CFG_SUPPORT_AAA +#define WPS_DEV_OUI_WFA 0x0050f204 +#define ATTR_RESPONSE_TYPE 0x103b + +#define ATTR_VERSION 0x104a +#define ATTR_VENDOR_EXT 0x1049 +#define WPS_VENDOR_ID_WFA 14122 + +void rsnGenerateWSCIEForAssocRsp(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct WIFI_VAR *prWifiVar = NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *)NULL; + uint16_t u2IELen = 0; + + prWifiVar = &(prAdapter->rWifiVar); + + DBGLOG(RSN, TRACE, "WPS: Building WPS IE for (Re)Association Response"); + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + + if (prP2pBssInfo->eNetworkType != NETWORK_TYPE_P2P) + return; + + u2IELen = kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 3, + (uint8_t) prP2pBssInfo->u4PrivateData); + + kalP2PGenWSC_IE(prAdapter->prGlueInfo, + 3, + (uint8_t *) ((unsigned long) prMsduInfo->prPacket + + (unsigned long) prMsduInfo->u2FrameLength), + (uint8_t) prP2pBssInfo->u4PrivateData); + prMsduInfo->u2FrameLength += (uint16_t) kalP2PCalWSC_IELen( + prAdapter->prGlueInfo, 3, + (uint8_t) prP2pBssInfo->u4PrivateData); +} + +#endif + +#if CFG_SUPPORT_802_11W +/* AP PMF */ +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to validate setting if PMF connection capable + * or not. If AP MFPC=1, and STA MFPC=1, we let this as PMF connection + * + * + * \return status code + */ +/*----------------------------------------------------------------------------*/ +uint16_t rsnPmfCapableValidation(IN struct ADAPTER + *prAdapter, IN struct BSS_INFO *prBssInfo, + IN struct STA_RECORD *prStaRec) +{ + u_int8_t selfMfpc, selfMfpr, peerMfpc, peerMfpr; + + selfMfpc = prBssInfo->rApPmfCfg.fgMfpc; + selfMfpr = prBssInfo->rApPmfCfg.fgMfpr; + peerMfpc = prStaRec->rPmfCfg.fgMfpc; + peerMfpr = prStaRec->rPmfCfg.fgMfpr; + + DBGLOG(RSN, INFO, + "AP mfpc:%d, mfpr:%d / STA mfpc:%d, mfpr:%d\n", + selfMfpc, selfMfpr, peerMfpc, peerMfpr); + + if ((selfMfpc == TRUE) && (peerMfpc == FALSE)) { + if ((selfMfpr == TRUE) && (peerMfpr == FALSE)) { + DBGLOG(RSN, ERROR, + "PMF policy violation for case 4\n"); + return STATUS_CODE_ROBUST_MGMT_FRAME_POLICY_VIOLATION; + } + + if (peerMfpr == TRUE) { + DBGLOG(RSN, ERROR, + "PMF policy violation for case 7\n"); + return STATUS_CODE_ROBUST_MGMT_FRAME_POLICY_VIOLATION; + } + + if ((prBssInfo->u4RsnSelectedAKMSuite == + RSN_AKM_SUITE_SAE) && + prStaRec->rPmfCfg.fgSaeRequireMfp) { + DBGLOG(RSN, ERROR, + "PMF policy violation for case sae_require_mfp\n"); + return STATUS_CODE_ROBUST_MGMT_FRAME_POLICY_VIOLATION; + } + } + + if ((selfMfpc == TRUE) && (peerMfpc == TRUE)) { + DBGLOG(RSN, ERROR, "PMF Connection\n"); + prStaRec->rPmfCfg.fgApplyPmf = TRUE; + } + + return STATUS_CODE_SUCCESSFUL; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to generate TIMEOUT INTERVAL IE + * for association resp. + * Add Timeout interval IE (56) when PMF invalid association. + * + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void rsnPmfGenerateTimeoutIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct IE_TIMEOUT_INTERVAL *prTimeout; + struct STA_RECORD *prStaRec = NULL; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (!prStaRec) + return; + + prTimeout = (struct IE_TIMEOUT_INTERVAL *) + (((uint8_t *) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + + /* only when PMF connection, and association error code is 30 */ + if ((rsnCheckBipKeyInstalled(prAdapter, prStaRec) == TRUE) + && + (prStaRec->u2StatusCode == + STATUS_CODE_ASSOC_REJECTED_TEMPORARILY)) { + + DBGLOG(RSN, INFO, "rsnPmfGenerateTimeoutIE TRUE\n"); + prTimeout->ucId = ELEM_ID_TIMEOUT_INTERVAL; + prTimeout->ucLength = ELEM_MAX_LEN_TIMEOUT_IE; + prTimeout->ucType = IE_TIMEOUT_INTERVAL_TYPE_ASSOC_COMEBACK; + prTimeout->u4Value = 1 << 10; + prMsduInfo->u2FrameLength += IE_SIZE(prTimeout); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * + * \brief This routine is called to check the Sa query timeout. + * check if total retry time is greater than 1000ms + * + * \retval 1: retry max timeout. 0: not timeout + * \note + * Called by: AAA module, Handle by Sa Query timeout + */ +/*----------------------------------------------------------------------------*/ +uint8_t rsnApCheckSaQueryTimeout(IN struct ADAPTER + *prAdapter, IN struct STA_RECORD *prStaRec) +{ + struct BSS_INFO *prBssInfo; + uint32_t now; + + GET_CURRENT_SYSTIME(&now); + + if (CHECK_FOR_TIMEOUT(now, prStaRec->rPmfCfg.u4SAQueryStart, + TU_TO_MSEC(1000))) { + DBGLOG(RSN, INFO, "association SA Query timed out\n"); + + /* XXX PMF TODO how to report STA REC disconnect?? */ + /* when SAQ retry count timeout, clear this STA */ + prStaRec->rPmfCfg.ucSAQueryTimedOut = 1; + prStaRec->rPmfCfg.u2TransactionID = 0; + prStaRec->rPmfCfg.u4SAQueryCount = 0; + cnmTimerStopTimer(prAdapter, &prStaRec->rPmfCfg.rSAQueryTimer); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + /* refer to p2pRoleFsmRunEventRxDeauthentication */ + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + if (bssRemoveClient(prAdapter, prBssInfo, prStaRec)) { + /* Indicate disconnect to Host. */ + p2pFuncDisconnect(prAdapter, prBssInfo, + prStaRec, FALSE, 0); + /* Deactive BSS if PWR is IDLE and no peer */ + if (IS_NET_PWR_STATE_IDLE(prAdapter, + prBssInfo->ucBssIndex) + && + (bssGetClientCount(prAdapter, prBssInfo) + == 0)) { + /* All Peer disconnected !! + * Stop BSS now!! + */ + p2pFuncStopComplete(prAdapter, + prBssInfo); + } + } + } + + return 1; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * + * \brief This routine is called to start the 802.11w sa query timer. + * This routine is triggered every 201ms, and every time enter function, + * check max timeout + * + * \note + * Called by: AAA module, Handle TX SAQ request + */ +/*----------------------------------------------------------------------------*/ +void rsnApStartSaQueryTimer(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN unsigned long ulParamPtr) +{ + struct BSS_INFO *prBssInfo; + struct MSDU_INFO *prMsduInfo; + struct ACTION_SA_QUERY_FRAME *prTxFrame; + uint16_t u2PayloadLen; + + DBGLOG(RSN, INFO, "MFP: AP Start Sa Query timer\n"); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + if (prStaRec->rPmfCfg.u4SAQueryCount > 0 + && rsnApCheckSaQueryTimeout(prAdapter, prStaRec)) { + DBGLOG(RSN, INFO, + "MFP: retry max timeout, u4SaQueryCount count =%d\n", + prStaRec->rPmfCfg.u4SAQueryCount); + return; + } + + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc(prAdapter, + MAC_TX_RESERVED_FIELD + + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + prTxFrame = (struct ACTION_SA_QUERY_FRAME *) + ((unsigned long)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) + prTxFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + COPY_MAC_ADDR(prTxFrame->aucDestAddr, prStaRec->aucMacAddr); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucBSSID); + COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); + + prTxFrame->ucCategory = CATEGORY_SA_QUERY_ACTION; + prTxFrame->ucAction = ACTION_SA_QUERY_REQUEST; + + if (prStaRec->rPmfCfg.u4SAQueryCount == 0) + GET_CURRENT_SYSTIME(&prStaRec->rPmfCfg.u4SAQueryStart); + + /* if retry, transcation id ++ */ + if (prStaRec->rPmfCfg.u4SAQueryCount) { + prStaRec->rPmfCfg.u2TransactionID++; + } else { + /* if first SAQ request, random pick transaction id */ + prStaRec->rPmfCfg.u2TransactionID = + (uint16_t) (kalRandomNumber() & 0xFFFF); + } + + DBGLOG(RSN, INFO, "SAQ transaction id:%d\n", + prStaRec->rPmfCfg.u2TransactionID); + + /* trnsform U16 to U8 array */ + prTxFrame->ucTransId[0] = ((prStaRec->rPmfCfg.u2TransactionID + & 0xff00) >> 8); + prTxFrame->ucTransId[1] = ((prStaRec->rPmfCfg.u2TransactionID + & 0x00ff) >> 0); + + prStaRec->rPmfCfg.u4SAQueryCount++; + + u2PayloadLen = 2 + ACTION_SA_QUERY_TR_ID_LEN; + + /* 4 <3> Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, NULL, + MSDU_RATE_MODE_AUTO); + + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + DBGLOG(RSN, INFO, "AP Set SA Query timer %d (%d Tu)\n", + prStaRec->rPmfCfg.u4SAQueryCount, 201); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rPmfCfg.rSAQueryTimer, TU_TO_MSEC(201)); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * + * \brief This routine is called to start the 802.11w TX SA query. + * + * + * \note + * Called by: AAA module, Handle Tx action frame request + */ +/*----------------------------------------------------------------------------*/ +void rsnApStartSaQuery(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + DBGLOG(RSN, INFO, "rsnApStartSaQuery\n"); + + if (prStaRec) { + cnmTimerStopTimer(prAdapter, + &prStaRec->rPmfCfg.rSAQueryTimer); + cnmTimerInitTimer(prAdapter, + &prStaRec->rPmfCfg.rSAQueryTimer, + (PFN_MGMT_TIMEOUT_FUNC)rsnApStartSaQueryTimer, + (unsigned long) prStaRec); + + if (prStaRec->rPmfCfg.u4SAQueryCount == 0) + rsnApStartSaQueryTimer(prAdapter, prStaRec, + (unsigned long)NULL); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * + * \brief This routine is called to stop the 802.11w SA query. + * + * + * \note + * Called by: AAA module, stop TX SAQ if receive correct SAQ response + */ +/*----------------------------------------------------------------------------*/ +void rsnApStopSaQuery(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + cnmTimerStopTimer(prAdapter, &prStaRec->rPmfCfg.rSAQueryTimer); + prStaRec->rPmfCfg.u2TransactionID = 0; + prStaRec->rPmfCfg.u4SAQueryCount = 0; + prStaRec->rPmfCfg.ucSAQueryTimedOut = 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * + * \brief This routine is called to process the 802.11w sa query action frame. + * + * + * \note + * Called by: AAA module, Handle Rx action request + */ +/*----------------------------------------------------------------------------*/ +void rsnApSaQueryRequest(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct BSS_INFO *prBssInfo; + struct MSDU_INFO *prMsduInfo; + struct ACTION_SA_QUERY_FRAME *prRxFrame = NULL; + uint16_t u2PayloadLen; + struct STA_RECORD *prStaRec; + struct ACTION_SA_QUERY_FRAME *prTxFrame; + + if (!prSwRfb) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (!prStaRec) /* Todo:: for not AIS check */ + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + prRxFrame = (struct ACTION_SA_QUERY_FRAME *) + prSwRfb->pvHeader; + if (!prRxFrame) + return; + + DBGLOG(RSN, INFO, + "IEEE 802.11: AP Received SA Query Request from " MACSTR + "\n", MAC2STR(prStaRec->aucMacAddr)); + + DBGLOG_MEM8(RSN, INFO, prRxFrame->ucTransId, ACTION_SA_QUERY_TR_ID_LEN); + + if (!rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(RSN, INFO, + "IEEE 802.11: AP Ignore SA Query Request non-PMF STA " + MACSTR "\n", MAC2STR(prStaRec->aucMacAddr)); + return; + } + + DBGLOG(RSN, INFO, + "IEEE 802.11: Sending SA Query Response to " MACSTR "\n", + MAC2STR(prStaRec->aucMacAddr)); + + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc(prAdapter, + MAC_TX_RESERVED_FIELD + + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + /* drop cipher mismatch */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + if (prSwRfb->fgIsCipherMS || + prSwRfb->fgIsCipherLenMS) { + /* if cipher mismatch, or incorrect encrypt, + * just drop + */ + DBGLOG(RSN, ERROR, "drop SAQ req CM/CLM=1\n"); + return; + } + } + + prTxFrame = (struct ACTION_SA_QUERY_FRAME *) + ((unsigned long)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + prTxFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + DBGLOG(RSN, INFO, "AP SAQ resp set FC PF bit\n"); + } + COPY_MAC_ADDR(prTxFrame->aucDestAddr, prStaRec->aucMacAddr); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucBSSID); + COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); + + prTxFrame->ucCategory = CATEGORY_SA_QUERY_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 <3> Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, NULL, + MSDU_RATE_MODE_AUTO); + + /* 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: AAA module, Handle Rx action request + */ +/*----------------------------------------------------------------------------*/ +void rsnApSaQueryAction(IN struct ADAPTER *prAdapter, IN struct SW_RFB *prSwRfb) +{ + struct ACTION_SA_QUERY_FRAME *prRxFrame; + struct STA_RECORD *prStaRec; + uint16_t u2SwapTrID; + + prRxFrame = (struct ACTION_SA_QUERY_FRAME *) + prSwRfb->pvHeader; + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prStaRec == NULL) { + DBGLOG(RSN, INFO, "rsnApSaQueryAction: prStaRec is NULL"); + return; + } + + DBGLOG(RSN, TRACE, + "AP PMF SAQ action enter from " MACSTR "\n", + MAC2STR(prStaRec->aucMacAddr)); + if (prSwRfb->u2PacketLen < ACTION_SA_QUERY_TR_ID_LEN) { + DBGLOG(RSN, INFO, + "IEEE 802.11: Too short SA Query Action frame (len=%lu)\n", + (unsigned long)prSwRfb->u2PacketLen); + return; + } + + if (prRxFrame->ucAction == ACTION_SA_QUERY_REQUEST) { + rsnApSaQueryRequest(prAdapter, prSwRfb); + return; + } + + if (prRxFrame->ucAction != ACTION_SA_QUERY_RESPONSE) { + DBGLOG(RSN, INFO, + "IEEE 802.11: Unexpected SA Query Action %d\n", + prRxFrame->ucAction); + return; + } + + DBGLOG(RSN, INFO, + "IEEE 802.11: Received SA Query Response from " MACSTR "\n", + MAC2STR(prStaRec->aucMacAddr)); + + DBGLOG_MEM8(RSN, INFO, prRxFrame->ucTransId, ACTION_SA_QUERY_TR_ID_LEN); + + /* MLME-SAQuery.confirm */ + /* transform to network byte order */ + u2SwapTrID = htons(prStaRec->rPmfCfg.u2TransactionID); + if (kalMemCmp((uint8_t *) &u2SwapTrID, prRxFrame->ucTransId, + ACTION_SA_QUERY_TR_ID_LEN) == 0) { + DBGLOG(RSN, INFO, "AP Reply to SA Query received\n"); + rsnApStopSaQuery(prAdapter, prStaRec); + } else { + DBGLOG(RSN, INFO, + "IEEE 802.11: AP No matching SA Query transaction identifier found\n"); + } + +} + +#endif /* CFG_SUPPORT_802_11W */ + +#if CFG_SUPPORT_PASSPOINT +u_int8_t rsnParseOsenIE(struct ADAPTER *prAdapter, + struct IE_WFA_OSEN *prInfoElem, + struct RSN_INFO *prOsenInfo) +{ + uint32_t i; + int32_t u4RemainRsnIeLen; + uint16_t u2Version = 0; + uint16_t u2Cap = 0; + uint32_t u4GroupSuite = RSN_CIPHER_SUITE_CCMP; + uint16_t u2PairSuiteCount = 0; + uint16_t u2AuthSuiteCount = 0; + uint8_t *pucPairSuite = NULL; + uint8_t *pucAuthSuite = NULL; + uint8_t *cp; + + cp = ((uint8_t *) prInfoElem) + 6; + u4RemainRsnIeLen = (int32_t) prInfoElem->ucLength - 4; + do { + if (u4RemainRsnIeLen == 0) + break; + + /* Parse the Group Key Cipher Suite field. */ + if (u4RemainRsnIeLen < 4) { + DBGLOG(RSN, WARN, + "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, WARN, + "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 = (uint32_t) u2PairSuiteCount * 4; + if (u4RemainRsnIeLen < (int32_t) i) { + DBGLOG(RSN, WARN, + "Fail to parse RSN IE in pairwise cipher suite list (IE len: %d, Remain %u, Cnt %d GS %x)\n", + prInfoElem->ucLength, u4RemainRsnIeLen, + u2PairSuiteCount, u4GroupSuite); + return FALSE; + } + + pucPairSuite = cp; + + cp += i; + u4RemainRsnIeLen -= (int32_t) i; + + if (u4RemainRsnIeLen == 0) + break; + + /* Parse the Authentication and Key Management Cipher Suite + * Count field. + */ + if (u4RemainRsnIeLen < 2) { + DBGLOG(RSN, WARN, + "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 = (uint32_t) u2AuthSuiteCount * 4; + if (u4RemainRsnIeLen < (int32_t) i) { + DBGLOG(RSN, WARN, + "Fail to parse RSN IE in auth & key mgt suite list (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + pucAuthSuite = cp; + + cp += i; + u4RemainRsnIeLen -= (int32_t) i; + + if (u4RemainRsnIeLen == 0) + break; + + /* Parse the RSN u2Capabilities field. */ + if (u4RemainRsnIeLen < 2) { + DBGLOG(RSN, WARN, + "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. */ + prOsenInfo->ucElemId = ELEM_ID_VENDOR; + + prOsenInfo->u2Version = 0; + + prOsenInfo->u4GroupKeyCipherSuite = u4GroupSuite; + + DBGLOG(RSN, TRACE, + "RSN: version %d, group key cipher suite 0x%x\n", + u2Version, SWAP32(u4GroupSuite)); + + 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; + + prOsenInfo->u4PairwiseKeyCipherSuiteCount = + (uint32_t) u2PairSuiteCount; + + for (i = 0; i < (uint32_t) u2PairSuiteCount; i++) { + WLAN_GET_FIELD_32(pucPairSuite, + &prOsenInfo->au4PairwiseKeyCipherSuite[i]); + pucPairSuite += 4; + + DBGLOG(RSN, TRACE, + "RSN: pairwise key cipher suite [%d]: 0x%x\n", i, + SWAP32(prOsenInfo->au4PairwiseKeyCipherSuite[i])); + } + } else { + /* The information about the pairwise key cipher suites + * is not present. Use the default chipher suite for RSN: CCMP + */ + + prOsenInfo->u4PairwiseKeyCipherSuiteCount = 1; + prOsenInfo->au4PairwiseKeyCipherSuite[0] = + RSN_CIPHER_SUITE_CCMP; + + DBGLOG(RSN, WARN, + "No Pairwise Cipher Suite found, using default (CCMP)\n"); + } + + 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; + + prOsenInfo->u4AuthKeyMgtSuiteCount = (uint32_t) + u2AuthSuiteCount; + + for (i = 0; i < (uint32_t) u2AuthSuiteCount; i++) { + WLAN_GET_FIELD_32(pucAuthSuite, + &prOsenInfo->au4AuthKeyMgtSuite[i]); + pucAuthSuite += 4; + + DBGLOG(RSN, TRACE, "RSN: AKM suite [%d]: 0x%x\n", i + SWAP32(prOsenInfo->au4AuthKeyMgtSuite[i])); + } + } else { + /* The information about the authentication and + * key management suites is not present. + * Use the default AKM suite for RSN. + */ + prOsenInfo->u4AuthKeyMgtSuiteCount = 1; + prOsenInfo->au4AuthKeyMgtSuite[0] = RSN_AKM_SUITE_802_1X; + + DBGLOG(RSN, WARN, "No AKM found, using default (802.1X)\n"); + } + + prOsenInfo->u2RsnCap = u2Cap; +#if CFG_SUPPORT_802_11W + prOsenInfo->fgRsnCapPresent = TRUE; +#endif + DBGLOG(RSN, TRACE, "RSN cap: 0x%04x\n", prOsenInfo->u2RsnCap); + + return TRUE; +} +#endif /* CFG_SUPPORT_PASSPOINT */ + +uint32_t rsnCalculateFTIELen(struct ADAPTER *prAdapter, uint8_t ucBssIdx, + struct STA_RECORD *prStaRec) +{ + struct FT_IES *prFtIEs = aisGetFtIe(prAdapter, ucBssIdx); + + if (!prFtIEs->prFTIE || + !rsnIsFtOverTheAir(prAdapter, ucBssIdx, prStaRec->ucIndex)) + return 0; + return IE_SIZE(prFtIEs->prFTIE); +} + +void rsnGenerateFTIE(IN struct ADAPTER *prAdapter, + IN OUT struct MSDU_INFO *prMsduInfo) +{ + uint8_t *pucBuffer = + (uint8_t *)prMsduInfo->prPacket + prMsduInfo->u2FrameLength; + uint32_t ucFtIeSize = 0; + uint8_t ucBssIdx = prMsduInfo->ucBssIndex; + struct FT_IES *prFtIEs = aisGetFtIe(prAdapter, ucBssIdx); + + if (!prFtIEs->prFTIE || + !rsnIsFtOverTheAir(prAdapter, ucBssIdx, prMsduInfo->ucStaRecIndex)) + return; + ucFtIeSize = IE_SIZE(prFtIEs->prFTIE); + prMsduInfo->u2FrameLength += ucFtIeSize; + kalMemCopy(pucBuffer, prFtIEs->prFTIE, ucFtIeSize); +} + +u_int8_t rsnIsFtOverTheAir(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIdx, + IN uint8_t ucStaRecIdx) +{ + struct STA_RECORD *prStaRec; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIdx); + if (IS_BSS_INDEX_VALID(ucBssIdx) && + IS_BSS_AIS(GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx)) && + prStaRec && prStaRec->ucAuthAlgNum == + (uint8_t) AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION) + return TRUE; + + return FALSE; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/saa_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/saa_fsm.c new file mode 100644 index 0000000000000..89f6633dc7a1c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/saa_fsm.c @@ -0,0 +1,2182 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +static uint8_t *apucDebugAAState[AA_STATE_NUM] = { + (uint8_t *) DISP_STRING("AA_IDLE"), + (uint8_t *) DISP_STRING("SAA_SEND_AUTH1"), + (uint8_t *) DISP_STRING("SAA_WAIT_AUTH2"), + (uint8_t *) DISP_STRING("SAA_SEND_AUTH3"), + (uint8_t *) DISP_STRING("SAA_WAIT_AUTH4"), + (uint8_t *) DISP_STRING("SAA_EXTERNAL_AUTH"), + (uint8_t *) DISP_STRING("SAA_SEND_ASSOC1"), + (uint8_t *) DISP_STRING("SAA_WAIT_ASSOC2"), + (uint8_t *) DISP_STRING("AAA_SEND_AUTH2"), + (uint8_t *) DISP_STRING("AAA_SEND_AUTH4"), + (uint8_t *) DISP_STRING("AAA_SEND_ASSOC2"), + (uint8_t *) DISP_STRING("AA_RESOURCE") +}; + +/******************************************************************************* + * M A 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 struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, IN enum ENUM_AA_STATE eNextState, + IN struct SW_RFB *prRetainedSwRfb) +{ + uint32_t rStatus = WLAN_STATUS_FAILURE; + enum ENUM_AA_STATE ePreviousState; + u_int8_t fgIsTransition; + + if (!prStaRec) + return; + + do { + + if (prStaRec->eAuthAssocState >= 0 + && prStaRec->eAuthAssocState < AA_STATE_NUM + && eNextState >= 0 + && eNextState < AA_STATE_NUM) { + DBGLOG(SAA, STATE, "[SAA]TRANSITION: [%s] -> [%s]\n", + apucDebugAAState[prStaRec->eAuthAssocState], + apucDebugAAState[eNextState]); + } + + ePreviousState = prStaRec->eAuthAssocState; + + /* NOTE(Kevin): This is the only place to change the + * eAuthAssocState(except initial) + */ + prStaRec->eAuthAssocState = eNextState; + + fgIsTransition = (u_int8_t) FALSE; + switch (prStaRec->eAuthAssocState) { + case AA_STATE_IDLE: + DBGLOG(SAA, TRACE, + "FT: authAlgNum %d, AuthTranNum %d\n", + prStaRec->ucAuthAlgNum, + prStaRec->ucAuthTranNum); + if (prStaRec->ucAuthAlgNum == + AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION && + prStaRec->ucAuthTranNum == + AUTH_TRANSACTION_SEQ_2 && + prStaRec->ucStaState == STA_STATE_1) { + struct PARAM_STATUS_INDICATION rStatus = { + .eStatusType = + ENUM_STATUS_TYPE_FT_AUTH_STATUS}; + struct cfg80211_ft_event_params *prFtEvent = + aisGetFtEventParam(prAdapter, + prStaRec->ucBssIndex); + + prFtEvent->target_ap = prStaRec->aucMacAddr; + /* now, we don't support RIC first */ + prFtEvent->ric_ies = NULL; + prFtEvent->ric_ies_len = 0; + DBGLOG(SAA, INFO, + "[%d] FT: notify supplicant to update FT IEs\n", + prStaRec->ucBssIndex); + kalIndicateStatusAndComplete( + prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + &rStatus, sizeof(rStatus), + prStaRec->ucBssIndex); + break; + /* wait supplicant update ft ies and then + * continue to send assoc 1 + */ + } + + /* Only trigger this event once */ + if (ePreviousState != prStaRec->eAuthAssocState) { + + if (prRetainedSwRfb) { + if (saaFsmSendEventJoinComplete( + prAdapter, + WLAN_STATUS_SUCCESS, + prStaRec, + prRetainedSwRfb) == + WLAN_STATUS_SUCCESS) { + /* ToDo:: Nothing */ + } else { + eNextState = AA_STATE_RESOURCE; + fgIsTransition = TRUE; + } + } else { + if (saaFsmSendEventJoinComplete( + prAdapter, + WLAN_STATUS_FAILURE, + prStaRec, NULL) == + WLAN_STATUS_RESOURCES) { + eNextState = AA_STATE_RESOURCE; + fgIsTransition = TRUE; + } + } + + } + + /* Free allocated TCM memory */ + if (prStaRec->prChallengeText) { + cnmMemFree(prAdapter, + prStaRec->prChallengeText); + prStaRec->prChallengeText = + (struct IE_CHALLENGE_TEXT *) NULL; + } + + break; + + case SAA_STATE_SEND_AUTH1: + + /* Do tasks in INIT STATE */ + if (prStaRec->ucTxAuthAssocRetryCount >= + prStaRec->ucTxAuthAssocRetryLimit) { + + /* Record the Status Code of Auth Request */ + prStaRec->u2StatusCode = + STATUS_CODE_AUTH_TIMEOUT; + + eNextState = AA_STATE_IDLE; + fgIsTransition = TRUE; + } else { + prStaRec->ucTxAuthAssocRetryCount++; + prStaRec->ucAuthTranNum = + AUTH_TRANSACTION_SEQ_1; + /* Update Station Record - Class 1 Flag */ + cnmStaRecChangeState(prAdapter, prStaRec, + STA_STATE_1); + +#if !CFG_SUPPORT_AAA + rStatus = authSendAuthFrame(prAdapter, prStaRec, + AUTH_TRANSACTION_SEQ_1); +#else + rStatus = authSendAuthFrame(prAdapter, + prStaRec, + prStaRec->ucBssIndex, + NULL, + AUTH_TRANSACTION_SEQ_1, + STATUS_CODE_RESERVED); +#endif /* CFG_SUPPORT_AAA */ + if (rStatus != WLAN_STATUS_SUCCESS) { + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC) + saaFsmRunEventTxReqTimeOut, + (unsigned long) 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 Auth Request */ + prStaRec->u2StatusCode = + STATUS_CODE_AUTH_TIMEOUT; + + eNextState = AA_STATE_IDLE; + fgIsTransition = TRUE; + } else { + prStaRec->ucTxAuthAssocRetryCount++; + prStaRec->ucAuthTranNum = + AUTH_TRANSACTION_SEQ_3; + +#if !CFG_SUPPORT_AAA + rStatus = authSendAuthFrame(prAdapter, + prStaRec, + AUTH_TRANSACTION_SEQ_3); +#else + rStatus = authSendAuthFrame(prAdapter, + prStaRec, + prStaRec->ucBssIndex, + NULL, + AUTH_TRANSACTION_SEQ_3, + STATUS_CODE_RESERVED); +#endif /* CFG_SUPPORT_AAA */ + if (rStatus != WLAN_STATUS_SUCCESS) { + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC) + saaFsmRunEventTxReqTimeOut, + (unsigned long) prStaRec); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC( + TX_AUTHENTICATION_RETRY_TIMEOUT_TU)); + } + } + + break; + + case SAA_STATE_WAIT_AUTH4: + break; + +#if CFG_SUPPORT_WPA3 + case SAA_STATE_EXTERNAL_AUTH: + kalExternalAuthRequest(prAdapter, prStaRec->ucBssIndex); + break; +#endif + + case SAA_STATE_SEND_ASSOC1: + /* Do tasks in INIT STATE */ + if (prStaRec->ucTxAuthAssocRetryCount >= + prStaRec->ucTxAuthAssocRetryLimit) { + + /* Record the Status Code of Auth Request */ + prStaRec->u2StatusCode = + STATUS_CODE_ASSOC_TIMEOUT; + + eNextState = AA_STATE_IDLE; + fgIsTransition = TRUE; + } else { + prStaRec->ucTxAuthAssocRetryCount++; + + rStatus = assocSendReAssocReqFrame(prAdapter, + prStaRec); + if (rStatus != WLAN_STATUS_SUCCESS) { + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC) + saaFsmRunEventTxReqTimeOut, + (unsigned long) 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) + */ +/*----------------------------------------------------------------------------*/ +uint32_t +saaFsmSendEventJoinComplete(IN struct ADAPTER *prAdapter, + IN uint32_t rJoinStatus, + IN struct STA_RECORD *prStaRec, + IN struct SW_RFB *prSwRfb) +{ + struct BSS_INFO *prBssInfo; + + if (!prStaRec) { + DBGLOG(SAA, ERROR, "[%s]prStaRec is NULL\n", __func__); + return WLAN_STATUS_INVALID_PACKET; + } + if (!prAdapter) { + DBGLOG(SAA, ERROR, "[%s]prAdapter is NULL\n", __func__); + return WLAN_STATUS_INVALID_PACKET; + } + + /* Store limitation about 40Mhz bandwidth capability during + * association. + */ + if (prStaRec->ucBssIndex < prAdapter->ucHwBssIdNum) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + if (prBssInfo != NULL) { + if (rJoinStatus == WLAN_STATUS_SUCCESS) + prBssInfo->fg40mBwAllowed = + prBssInfo->fgAssoc40mBwAllowed; + prBssInfo->fgAssoc40mBwAllowed = FALSE; + } + } + + /* For wlan0 (AP) + p2p0, don't check the prAisBssInfo for the P2P. */ +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) { + struct MSG_SAA_FSM_COMP *prSaaFsmCompMsg; + + prSaaFsmCompMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_SAA_FSM_COMP)); + if (!prSaaFsmCompMsg) + return WLAN_STATUS_RESOURCES; + + if (rJoinStatus == WLAN_STATUS_SUCCESS) + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + + 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, + (struct MSG_HDR *) prSaaFsmCompMsg, + MSG_SEND_METHOD_UNBUF); + + return WLAN_STATUS_SUCCESS; + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + + if (IS_STA_IN_AIS(prStaRec)) { + struct MSG_SAA_FSM_COMP *prSaaFsmCompMsg; + + prSaaFsmCompMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_SAA_FSM_COMP)); + if (!prSaaFsmCompMsg) + return WLAN_STATUS_RESOURCES; + + if (rJoinStatus == WLAN_STATUS_SUCCESS) + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + + 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, + (struct MSG_HDR *) prSaaFsmCompMsg, + MSG_SEND_METHOD_UNBUF); + + return WLAN_STATUS_SUCCESS; + } +#if CFG_ENABLE_BT_OVER_WIFI + else if (IS_STA_BOW_TYPE(prStaRec)) { + /* @TODO: BOW handler */ + + struct MSG_SAA_FSM_COMP *prSaaFsmCompMsg; + + prSaaFsmCompMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_SAA_FSM_COMP)); + 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, + (struct MSG_HDR *) prSaaFsmCompMsg, + MSG_SEND_METHOD_UNBUF); + + return WLAN_STATUS_SUCCESS; + } +#endif + else { + DBGLOG(SAA, ERROR, "Invalid case in %s.\n", __func__); + 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 struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_SAA_FSM_START *prSaaFsmStartMsg; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + + prSaaFsmStartMsg = (struct MSG_SAA_FSM_START *) prMsgHdr; + prStaRec = prSaaFsmStartMsg->prStaRec; + + if ((!prStaRec) || (prStaRec->fgIsInUse == FALSE)) { + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + DBGLOG(SAA, LOUD, "EVENT-START: Trigger SAA FSM.\n"); + + /* record sequence number of request message */ + prStaRec->ucAuthAssocReqSeqNum = prSaaFsmStartMsg->ucSeqNum; + + cnmMemFree(prAdapter, prMsgHdr); + if (prStaRec->ucAuthAlgNum == AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION && + prStaRec->ucAuthTranNum == AUTH_TRANSACTION_SEQ_2) { + DBGLOG(SAA, ERROR, + "FT: current is waiting FT auth, don't reentry\n"); + return; + } + + /* 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_UNSPECIFIED_FAILURE; + + /* Update the record join time. */ + GET_CURRENT_SYSTIME(&prStaRec->rLastJoinTime); + + prStaRec->ucTxAuthAssocRetryCount = 0; + + if (prStaRec->prChallengeText) { + cnmMemFree(prAdapter, prStaRec->prChallengeText); + prStaRec->prChallengeText = (struct IE_CHALLENGE_TEXT *) NULL; + } + + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + + /* 4 <4> Init the sec fsm */ + /* secFsmInit(prAdapter, prStaRec); */ + + /* 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 struct STA_RECORD 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->ucBssIndex < prAdapter->ucHwBssIdNum) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & + PHY_TYPE_SET_802_11N) && + (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) { + prBssInfo->fgAssoc40mBwAllowed = + cnmBss40mBwPermitted(prAdapter, + prBssInfo->ucBssIndex); + } else { + prBssInfo->fgAssoc40mBwAllowed = FALSE; + } + DBGLOG(RLM, TRACE, "STA 40mAllowed=%d\n", + prBssInfo->fgAssoc40mBwAllowed); + } + /* 4 <7> Trigger SAA FSM */ + if (prStaRec->ucStaState == STA_STATE_1) { + if (prStaRec->ucAuthAlgNum == AUTH_ALGORITHM_NUM_SAE) + saaFsmSteps(prAdapter, prStaRec, + SAA_STATE_EXTERNAL_AUTH, + (struct SW_RFB *) NULL); + else + saaFsmSteps(prAdapter, prStaRec, SAA_STATE_SEND_AUTH1, + (struct SW_RFB *) NULL); + } else if (prStaRec->ucStaState == STA_STATE_2 || + prStaRec->ucStaState == STA_STATE_3) + saaFsmSteps(prAdapter, prStaRec, + SAA_STATE_SEND_ASSOC1, (struct SW_RFB *) NULL); +} /* end of saaFsmRunEventStart() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will handle the Continue Event to SAA FSM. + * + * @param[in] prMsgHdr Message of Join Request for a particular STA. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void saaFsmRunEventFTContinue(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_SAA_FT_CONTINUE *prSaaFsmMsg = NULL; + struct STA_RECORD *prStaRec; + u_int8_t fgFtRicRequest = FALSE; + + prSaaFsmMsg = (struct MSG_SAA_FT_CONTINUE *)prMsgHdr; + prStaRec = prSaaFsmMsg->prStaRec; + fgFtRicRequest = prSaaFsmMsg->fgFTRicRequest; + cnmMemFree(prAdapter, prMsgHdr); + if ((!prStaRec) || (prStaRec->fgIsInUse == FALSE)) { + DBGLOG(SAA, ERROR, "No Sta Record or it is not in use\n"); + return; + } + if (prStaRec->eAuthAssocState != AA_STATE_IDLE) { + DBGLOG(SAA, ERROR, + "FT: Wrong SAA FSM state %d to continue auth/assoc\n", + prStaRec->eAuthAssocState); + return; + } + DBGLOG(SAA, TRACE, "Continue to do auth/assoc\n"); + if (fgFtRicRequest) + saaFsmSteps(prAdapter, prStaRec, SAA_STATE_SEND_AUTH3, + (struct SW_RFB *)NULL); + else { + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + saaFsmSteps(prAdapter, prStaRec, SAA_STATE_SEND_ASSOC1, + (struct SW_RFB *)NULL); + } +} /* end of saaFsmRunEventFTContinue() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +saaFsmRunEventTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + + struct STA_RECORD *prStaRec; + enum ENUM_AA_STATE eNextState; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (!prStaRec) + return WLAN_STATUS_INVALID_PACKET; + + if (rTxDoneStatus) + DBGLOG(SAA, INFO, + "EVENT-TX DONE [status: %d][seq: %d]: Current Time = %d\n", + rTxDoneStatus, prMsduInfo->ucTxSeqNum, kalGetTimeTick()); + + /* Trigger statistics log if Auth/Assoc Tx failed */ + if (rTxDoneStatus != TX_RESULT_SUCCESS) + wlanTriggerStatsLog(prAdapter, + prAdapter->rWifiVar.u4StatsLogDuration); + + 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, + (unsigned long) 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, + (struct SW_RFB *) 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, + (unsigned long) 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, + (struct SW_RFB *) 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, + (unsigned long) 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, + (struct SW_RFB *) 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 struct ADAPTER *prAdapter, + IN unsigned long plParamPtr) +{ + struct STA_RECORD *prStaRec = (struct STA_RECORD *) plParamPtr; + + if (!prStaRec) + return; + + DBGLOG(SAA, LOUD, "EVENT-TIMER: TX REQ TIMEOUT, Current Time = %d\n", + kalGetTimeTick()); + + /* Trigger statistics log if Auth/Assoc Tx timeout */ + wlanTriggerStatsLog(prAdapter, prAdapter->rWifiVar.u4StatsLogDuration); + + switch (prStaRec->eAuthAssocState) { + case SAA_STATE_SEND_AUTH1: + case SAA_STATE_SEND_AUTH3: + case SAA_STATE_SEND_ASSOC1: + saaFsmSteps(prAdapter, prStaRec, + prStaRec->eAuthAssocState, (struct SW_RFB *) NULL); + break; + + default: + return; + } +} /* end of saaFsmRunEventTxReqTimeOut() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will send Rx Response Timeout Event to SAA FSM. + * + * @param[in] prStaRec Pointer to the STA_RECORD_T + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void saaFsmRunEventRxRespTimeOut(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr) +{ + struct STA_RECORD *prStaRec = (struct STA_RECORD *) ulParamPtr; + enum ENUM_AA_STATE eNextState; + + DBGLOG(SAA, LOUD, "EVENT-TIMER: RX RESP TIMEOUT, Current Time = %d\n", + kalGetTimeTick()); + + 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, + (struct SW_RFB *) NULL); +} /* end of saaFsmRunEventRxRespTimeOut() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will process the Rx Auth Response Frame and then + * trigger SAA FSM. + * + * @param[in] prSwRfb Pointer to the SW_RFB_T structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void saaFsmRunEventRxAuth(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct STA_RECORD *prStaRec; + uint16_t u2StatusCode; + enum ENUM_AA_STATE eNextState; + uint8_t ucWlanIdx; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ucWlanIdx = prSwRfb->ucWlanIdx; + + /* We should have the corresponding Sta Record. */ + if (!prStaRec) { + DBGLOG(SAA, WARN, + "Received a AuthResp: wlanIdx[%d] w/o corresponding staRec\n", + ucWlanIdx); + 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); + + prStaRec->ucAuthTranNum = + AUTH_TRANSACTION_SEQ_2; + /* after received Auth2 for FT, should indicate + * to supplicant + * and wait response from supplicant + */ + if (prStaRec->ucAuthAlgNum == + AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION) + eNextState = AA_STATE_IDLE; + else if ( + prStaRec->ucAuthAlgNum == + (uint8_t) + AUTH_ALGORITHM_NUM_SHARED_KEY) { + + eNextState = SAA_STATE_SEND_AUTH3; + } else { + /* Update Station Record - Class 2 */ + 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, + (struct SW_RFB *) 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) { + + /* Add for 802.11r handling */ + uint32_t rStatus = + authProcessRxAuth2_Auth4Frame(prAdapter, + prSwRfb); + + prStaRec->ucAuthTranNum = + AUTH_TRANSACTION_SEQ_4; + /* if Auth4 check is failed(check mic in Auth + * ack frame), should disconnect + */ + if (prStaRec->ucAuthAlgNum == + AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION && + rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(SAA, INFO, + "Rx Auth4 fail [" MACSTR + "], status %d, maybe MIC error\n", + MAC2STR(prStaRec->aucMacAddr), + u2StatusCode); + /* Reset Send Auth/(Re)Assoc Frame Count + */ + prStaRec->ucTxAuthAssocRetryCount = 0; + saaFsmSteps(prAdapter, prStaRec, + AA_STATE_IDLE, + (struct SW_RFB *)NULL); + break; + } + + /* 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, (struct SW_RFB *) NULL); + } + break; + + case SAA_STATE_EXTERNAL_AUTH: + kalIndicateRxMgmtFrame(prAdapter->prGlueInfo, prSwRfb, + prStaRec->ucBssIndex); + break; + + default: + break; /* Ignore other cases */ + } +} /* end of saaFsmRunEventRxAuth() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will process the Rx (Re)Association Response Frame and + * then trigger SAA FSM. + * + * @param[in] prSwRfb Pointer to the SW_RFB_T structure. + * + * @retval WLAN_STATUS_SUCCESS if the status code was not success + * @retval WLAN_STATUS_BUFFER_RETAINED if the status code was success + */ +/*----------------------------------------------------------------------------*/ +uint32_t saaFsmRunEventRxAssoc(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct STA_RECORD *prStaRec; + uint16_t u2StatusCode; + enum ENUM_AA_STATE eNextState; + struct SW_RFB *prRetainedSwRfb = (struct SW_RFB *) NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint8_t ucWlanIdx; + struct WLAN_MAC_MGMT_HEADER *prWlanMgmtHdr; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ucWlanIdx = prSwRfb->ucWlanIdx; + + /* We should have the corresponding Sta Record. */ + if (!prStaRec) { + /* ASSERT(0); */ + DBGLOG(SAA, WARN, + "Received a AssocResp: wlanIdx[%d] w/o corresponding staRec\n", + ucWlanIdx); + 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 struct + * STA_RECORD of previous AP before activate + * new one in Driver. + */ + /* cnmStaRecChangeState(prStaRec, + * STA_STATE_3); + */ + + /* Clear history. */ + prStaRec->ucJoinFailureCount = 0; + + prRetainedSwRfb = prSwRfb; + rStatus = WLAN_STATUS_PENDING; + } else { + cnmStaRecChangeState(prAdapter, prStaRec, + STA_STATE_1); + DBGLOG(SAA, INFO, + "Assoc Req was rejected by [" MACSTR + "], Status Code = %d\n", + MAC2STR(prStaRec->aucMacAddr), + u2StatusCode); + } + /* Assoc Resp's BSSID doesn't match target, ignore */ + prWlanMgmtHdr = (struct WLAN_MAC_MGMT_HEADER *) + (prSwRfb->pvHeader); + if (!EQUAL_MAC_ADDR(prWlanMgmtHdr->aucBSSID, + prStaRec->aucMacAddr)) { + DBGLOG(SAA, ERROR, "Unknown BSSID\n"); + rStatus = WLAN_STATUS_FAILURE; + prRetainedSwRfb = NULL; + } + + /* Reset Send Auth/(Re)Assoc Frame Count */ + prStaRec->ucTxAuthAssocRetryCount = 0; + + /* update RCPI */ + ASSERT(prSwRfb->prRxStatusGroup3); + prStaRec->ucRCPI = + nicRxGetRcpiValueFromRxv( + prAdapter, RCPI_MODE_MAX, prSwRfb); + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t saaFsmRunEventRxDeauth(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct STA_RECORD *prStaRec; + struct WLAN_DEAUTH_FRAME *prDeauthFrame; + uint8_t ucWlanIdx; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + prDeauthFrame = (struct WLAN_DEAUTH_FRAME *) prSwRfb->pvHeader; + ucWlanIdx = prSwRfb->ucWlanIdx; + + DBGLOG(SAA, INFO, "Rx Deauth frame ,DA[" MACSTR "] SA[" MACSTR + "] BSSID[" MACSTR "] ReasonCode[0x%x]\n", + MAC2STR(prDeauthFrame->aucDestAddr), + MAC2STR(prDeauthFrame->aucSrcAddr), + MAC2STR(prDeauthFrame->aucBSSID), prDeauthFrame->u2ReasonCode); + + do { + + /* We should have the corresponding Sta Record. */ + if (!prStaRec) { + DBGLOG(SAA, WARN, + "Received a Deauth: wlanIdx[%d] w/o corresponding staRec\n", + ucWlanIdx); + break; + } + + if (IS_STA_IN_AIS(prStaRec)) { + struct BSS_INFO *prAisBssInfo; + uint8_t ucBssIndex = 0; + + if (!IS_AP_STA(prStaRec)) + break; + + ucBssIndex = prStaRec->ucBssIndex; + + prAisBssInfo = aisGetAisBssInfo(prAdapter, + ucBssIndex); + + /* if state != CONNECTED, don't do disconnect again */ + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo, + ucBssIndex) != + MEDIA_STATE_CONNECTED) + break; + + 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 CFG_SUPPORT_802_11W + struct AIS_SPECIFIC_BSS_INFO + *prAisSpecBssInfo; + + prAisSpecBssInfo = + aisGetAisSpecBssInfo(prAdapter, + ucBssIndex); + + DBGLOG(RSN, INFO, + "QM RX MGT: Deauth frame, P=%d Sec=%d CM=%d BC=%d fc=%02x\n", + prAisSpecBssInfo-> + fgMgmtProtection, (uint8_t) + prSwRfb->ucSecMode, + prSwRfb->fgIsCipherMS, + IS_BMCAST_MAC_ADDR + (prDeauthFrame->aucDestAddr), + prDeauthFrame->u2FrameCtrl); + if (prAisSpecBssInfo->fgMgmtProtection + && prSwRfb->fgIsCipherMS + /* HAL_RX_STATUS_GET_SEC_MODE + * (prSwRfb->prRxStatus) != + * CIPHER_SUITE_BIP + */ + ) { + saaChkDeauthfrmParamHandler( + prAdapter, prSwRfb, + prStaRec); + return WLAN_STATUS_SUCCESS; + } +#endif + saaSendDisconnectMsgHandler(prAdapter, + prStaRec, + prAisBssInfo, + FRM_DEAUTH); + } + } + } +#if CFG_ENABLE_WIFI_DIRECT + else if (prAdapter->fgIsP2PRegistered && + IS_STA_IN_P2P(prStaRec)) { + /* TODO(Kevin) */ + p2pRoleFsmRunEventRxDeauthentication(prAdapter, + prStaRec, + prSwRfb); + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (IS_STA_BOW_TYPE(prStaRec)) + bowRunEventRxDeAuth(prAdapter, prStaRec, prSwRfb); +#endif + else + ASSERT(0); + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; + +} /* end of saaFsmRunEventRxDeauth() */ + +/* for AOSP */ +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will check param of deauth frame and reson code for + * deauth. + * + * @param[in] + * + * @retval + */ +/*----------------------------------------------------------------------------*/ + +void saaChkDeauthfrmParamHandler(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN struct STA_RECORD *prStaRec) +{ + struct WLAN_DEAUTH_FRAME *prDeauthFrame; + + do { + prDeauthFrame = (struct WLAN_DEAUTH_FRAME *) prSwRfb->pvHeader; + if (!IS_BMCAST_MAC_ADDR(prDeauthFrame->aucDestAddr)) { + DBGLOG(RSN, INFO, + "[%d] QM RX MGT: rsnStartSaQuery\n", + prStaRec->ucBssIndex); + /* MFP test plan 5.3.3.5 */ + rsnStartSaQuery(prAdapter, prStaRec->ucBssIndex); + } else { + DBGLOG(RSN, INFO, "RXM: Drop unprotected Mgmt frame\n"); + DBGLOG(RSN, INFO, + "RXM:(MACRX Done)RX(ucSecMode=0x%x)(ucWlanIdx=0x%x)\n", + prSwRfb->ucSecMode, prSwRfb->ucWlanIdx); + } + } while (0); +} + +/* for AOSP */ +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will check and send disconnect message to AIS module + * + * @param[in] + * + * @retval + */ +/*----------------------------------------------------------------------------*/ +void +saaSendDisconnectMsgHandler(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct BSS_INFO *prAisBssInfo, + IN enum ENUM_AA_FRM_TYPE eFrmType) +{ + if (prStaRec->ucStaState == STA_STATE_3) { + struct MSG_AIS_ABORT *prAisAbortMsg; + u_int8_t fgIsTxAllowed; + + /* Backup txallowed status here because + * cnmStaRecChangeState will change it + */ + fgIsTxAllowed = prStaRec->fgIsTxAllowed; + + /* 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, + eFrmType == FRM_DEAUTH ? STA_STATE_1 : STA_STATE_2); + + prAisAbortMsg = + (struct MSG_AIS_ABORT *) + cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_AIS_ABORT)); + if (!prAisAbortMsg) + return; + + prAisAbortMsg->rMsgHdr.eMsgId = + MID_SAA_AIS_FSM_ABORT; + prAisAbortMsg->ucReasonOfDisconnect = + eFrmType == FRM_DEAUTH ? + DISCONNECT_REASON_CODE_DEAUTHENTICATED : + DISCONNECT_REASON_CODE_DISASSOCIATED; + prAisAbortMsg->fgDelayIndication = fgIsTxAllowed; + prAisAbortMsg->ucBssIndex = + prStaRec->ucBssIndex; + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prAisAbortMsg, + MSG_SEND_METHOD_BUF); + } + if (prAisBssInfo) + prAisBssInfo->u2DeauthReason = prStaRec->u2ReasonCode; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t saaFsmRunEventRxDisassoc(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct STA_RECORD *prStaRec; + struct WLAN_DISASSOC_FRAME *prDisassocFrame; + uint8_t ucWlanIdx; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + prDisassocFrame = (struct WLAN_DISASSOC_FRAME *) prSwRfb->pvHeader; + ucWlanIdx = prSwRfb->ucWlanIdx; + + DBGLOG(SAA, INFO, + "Rx Disassoc frame from SA[" MACSTR "] BSSID[" MACSTR + "] DA[" MACSTR "] ReasonCode[0x%x]\n", + MAC2STR(prDisassocFrame->aucSrcAddr), + MAC2STR(prDisassocFrame->aucBSSID), + MAC2STR(prDisassocFrame->aucDestAddr), + prDisassocFrame->u2ReasonCode); + + do { + + /* We should have the corresponding Sta Record. */ + if (!prStaRec) { + DBGLOG(SAA, WARN, + "Received a DisAssoc: wlanIdx[%d] w/o corresponding staRec\n", + ucWlanIdx); + break; + } + + if (IS_STA_IN_AIS(prStaRec)) { + struct BSS_INFO *prAisBssInfo; + uint8_t ucBssIndex = 0; + + if (!IS_AP_STA(prStaRec)) + break; + + ucBssIndex = prStaRec->ucBssIndex; + + prAisBssInfo = aisGetAisBssInfo(prAdapter, + ucBssIndex); + + 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 CFG_SUPPORT_802_11W + struct AIS_SPECIFIC_BSS_INFO + *prAisSpecBssInfo; + + prAisSpecBssInfo = + aisGetAisSpecBssInfo(prAdapter, + ucBssIndex); + + DBGLOG(RSN, INFO, + "QM RX MGT: Disassoc frame, P=%d Sec=%d CM=%d BC=%d fc=%02x\n", + prAisSpecBssInfo-> + fgMgmtProtection, (uint8_t) + prSwRfb->ucSecMode, + prSwRfb->fgIsCipherMS, + IS_BMCAST_MAC_ADDR + (prDisassocFrame->aucDestAddr), + prDisassocFrame->u2FrameCtrl); + if (IS_STA_IN_AIS(prStaRec) && + prAisSpecBssInfo->fgMgmtProtection + && prSwRfb->fgIsCipherMS + /* HAL_RX_STATUS_GET_SEC_MODE( + * prSwRfb->prRxStatus) != + * CIPHER_SUITE_CCMP + */ + ) { + /* prDisassocFrame = + * (P_WLAN_DISASSOC_FRAME_T) + * prSwRfb->pvHeader; + */ + saaChkDisassocfrmParamHandler( + prAdapter, + prDisassocFrame, prStaRec, + prSwRfb); + return WLAN_STATUS_SUCCESS; + } +#endif + saaSendDisconnectMsgHandler(prAdapter, + prStaRec, + prAisBssInfo, + FRM_DISASSOC); + } + } + } +#if CFG_ENABLE_WIFI_DIRECT + else if (prAdapter->fgIsP2PRegistered && + (IS_STA_IN_P2P(prStaRec))) { + /* TODO(Kevin) */ + p2pRoleFsmRunEventRxDisassociation(prAdapter, + prStaRec, prSwRfb); + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (IS_STA_BOW_TYPE(prStaRec)) { + /* ToDo:: nothing */ + /* TODO(Kevin) */ + } +#endif + else + ASSERT(0); + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; + +} /* end of saaFsmRunEventRxDisassoc() */ + +/* for AOSP */ +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will check param of Disassoc frame and reson code for + * Disassoc. + * + * @param[in] + * + * @retval + */ +/*----------------------------------------------------------------------------*/ + +void +saaChkDisassocfrmParamHandler(IN struct ADAPTER *prAdapter, + IN struct WLAN_DISASSOC_FRAME *prDisassocFrame, + IN struct STA_RECORD *prStaRec, + IN struct SW_RFB *prSwRfb) +{ + if (!IS_BMCAST_MAC_ADDR(prDisassocFrame->aucDestAddr)) { + /* MFP test plan 5.3.3.5 */ + DBGLOG(RSN, INFO, + "[%d] QM RX MGT: rsnStartSaQuery\n", + prStaRec->ucBssIndex); + rsnStartSaQuery(prAdapter, prStaRec->ucBssIndex); + } else { + DBGLOG(RSN, INFO, "RXM: Drop unprotected Mgmt frame\n"); + DBGLOG(RSN, INFO, + "RXM:(MACRX Done)RX(ucSecMode=0x%x)(ucWlanIdx=0x%x)\n", + prSwRfb->ucSecMode, prSwRfb->ucWlanIdx); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_SAA_FSM_ABORT *prSaaFsmAbortMsg; + struct STA_RECORD *prStaRec; + + prSaaFsmAbortMsg = (struct MSG_SAA_FSM_ABORT *) prMsgHdr; + prStaRec = prSaaFsmAbortMsg->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 (prStaRec->eAuthAssocState >= 0 + && prStaRec->eAuthAssocState < AA_STATE_NUM) { + DBGLOG(SAA, LOUD, + "EVENT-ABORT: Previous Auth/Assoc State == %s.\n", + apucDebugAAState[prStaRec->eAuthAssocState]); + } + } +#if 0 + /* For the Auth/Assoc State to IDLE */ + prStaRec->eAuthAssocState = AA_STATE_IDLE; +#else + /* Free this StaRec */ + cnmStaRecFree(prAdapter, prStaRec); +#endif +} /* end of saaFsmRunEventAbort() */ + +void saaFsmRunEventExternalAuthDone(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_SAA_EXTERNAL_AUTH_DONE *prSaaFsmMsg = NULL; + struct STA_RECORD *prStaRec; + uint16_t status; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prSaaFsmMsg = (struct MSG_SAA_EXTERNAL_AUTH_DONE *)prMsgHdr; + prStaRec = prSaaFsmMsg->prStaRec; + status = prSaaFsmMsg->status; + + cnmMemFree(prAdapter, prMsgHdr); + + if (status != WLAN_STATUS_SUCCESS) + saaFsmSteps(prAdapter, prStaRec, AA_STATE_IDLE, + (struct SW_RFB *)NULL); + else if (prStaRec->eAuthAssocState != SAA_STATE_EXTERNAL_AUTH) + DBGLOG(SAA, WARN, + "Receive External Auth DONE at wrong state\n"); + else + saaFsmSteps(prAdapter, prStaRec, SAA_STATE_SEND_ASSOC1, + (struct SW_RFB *)NULL); +} /* end of saaFsmRunEventExternalAuthDone() */ + +/* 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t joinFsmRunEventJoinTimeOut(IN struct ADAPTER *prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + struct STA_RECORD *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 struct ADAPTER *prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + struct BSS_DESC *prBssDesc; + + DEBUGFUNC("joinAdoptParametersFromPeerBss"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + prBssDesc = prJoinInfo->prBssDesc; + + /* 4 <1> Adopt Peer BSS' PHY TYPE */ + prAdapter->eCurrentPhyType = prBssDesc->ePhyType; + + DBGLOG(JOIN, INFO, "Target BSS[%s]'s PhyType = %s\n", + prBssDesc->aucSSID, (prBssDesc->ePhyType == PHY_TYPE_ERP_INDEX) ? + "ERP" : "HR_DSSS"); + + /* 4 <2> Adopt Peer BSS' Frequency(Band/Channel) */ + DBGLOG(JOIN, INFO, "Target BSS's Channel = %d, Band = %d\n", + prBssDesc->ucChannelNum, prBssDesc->eBand); + + nicSwitchChannel(prAdapter, prBssDesc->eBand, + prBssDesc->ucChannelNum, 10); + + prJoinInfo->fgIsParameterAdopted = TRUE; +} /* end of joinAdoptParametersFromPeerBss() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will adopt the parameters from current associated BSS. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void joinAdoptParametersFromCurrentBss(IN struct ADAPTER *prAdapter) +{ + /* P_JOIN_INFO_T prJoinInfo = &prAdapter->rJoinInfo; */ + struct BSS_INFO *prBssInfo; + + ASSERT(prAdapter); + prBssInfo = &prAdapter->rBssInfo; + + /* 4 <1> Adopt current BSS' PHY TYPE */ + prAdapter->eCurrentPhyType = prBssInfo->ePhyType; + + /* 4 <2> Adopt current BSS' Frequency(Band/Channel) */ + DBGLOG(JOIN, INFO, "Current BSS's Channel = %d, Band = %d\n", + prBssInfo->ucChnl, prBssInfo->eBand); + + nicSwitchChannel(prAdapter, prBssInfo->eBand, prBssInfo->ucChnl, 10); +} /* end of joinAdoptParametersFromCurrentBss() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will update all the SW variables and HW MCR registers + * after the association with target BSS. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void joinComplete(IN struct ADAPTER *prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + struct BSS_DESC *prBssDesc; + P_PEER_BSS_INFO_T prPeerBssInfo; + struct BSS_INFO *prBssInfo; + struct CONNECTION_SETTINGS *prConnSettings; + struct STA_RECORD *prStaRec; + struct TX_CTRL *prTxCtrl; +#if CFG_SUPPORT_802_11D + struct IE_COUNTRY *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 */ + /* Our BSS's PHY_TYPE is ERP now. */ + if ((prBssInfo->ePhyType == PHY_TYPE_ERP_INDEX) && + (prBssDesc->fgIsERPPresent)) { + + prBssInfo->fgIsERPPresent = TRUE; + /* Save the ERP for later check */ + prBssInfo->ucERP = prBssDesc->ucERP; + } 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) { + struct DOMAIN_INFO_ENTRY rDomainInfo; + + if (domainGetDomainInfoByScanResult(prAdapter, &rDomainInfo)) { + if (prBssDesc->prIECountry) { + prIECountry = prBssDesc->prIECountry; + + domainParseCountryInfoElem(prIECountry, + &prBssInfo->rDomainInfo); + + /* use the domain get from the BSS info */ + prBssInfo->fgIsCountryInfoPresent = TRUE; + nicSetupOpChnlList(prAdapter, + prBssInfo->rDomainInfo.u2CountryCode, FALSE); + } else { + /* use the domain get from the scan result */ + prBssInfo->fgIsCountryInfoPresent = TRUE; + nicSetupOpChnlList(prAdapter, + rDomainInfo.u2CountryCode, + FALSE); + } + } + } +#endif + + /* 4 <2.K> Signal Power of the associated AP */ + prBssInfo->rRcpi = prBssDesc->rRcpi; + prBssInfo->rRssi = RCPI_TO_dBm(prBssInfo->rRcpi); + GET_CURRENT_SYSTIME(&prBssInfo->rRssiLastUpdateTime); + + /* 4 <2.L> Capability Field of the associated AP */ + prBssInfo->u2CapInfo = prBssDesc->u2CapInfo; + + DBGLOG(JOIN, INFO, + "prBssInfo-> fgIsERPPresent = %d, ucERP = %02x, rRcpi = %d, rRssi = %ld\n", + prBssInfo->fgIsERPPresent, prBssInfo->ucERP, + prBssInfo->rRcpi, prBssInfo->rRssi); + +/* 4 <3> Update BSS_INFO_T from PEER_BSS_INFO_T & NIC RATE FUNC */ + /* 4 <3.A> Association ID */ + prBssInfo->u2AssocId = prPeerBssInfo->u2AssocId; + + /* 4 <3.B> WMM Information */ + if (prAdapter->fgIsEnableWMM && + (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_SUPPORT_WMM)) { + + prBssInfo->fgIsWmmAssoc = TRUE; + prTxCtrl->rTxQForVoipAccess = TXQ_AC3; + + qosWmmInfoInit(&prBssInfo->rWmmInfo, + (prBssInfo->ePhyType == PHY_TYPE_HR_DSSS_INDEX) + ? TRUE : FALSE); + + if (prPeerBssInfo->rWmmInfo.ucWmmFlag & + WMM_FLAG_AC_PARAM_PRESENT) { + kalMemCopy(&prBssInfo->rWmmInfo, + &prPeerBssInfo->rWmmInfo, + sizeof(WMM_INFO_T)); + } else { + kalMemCopy(&prBssInfo->rWmmInfo, + &prPeerBssInfo->rWmmInfo, + sizeof(WMM_INFO_T) - + sizeof(prPeerBssInfo-> + rWmmInfo.arWmmAcParams)); + } + } else { + prBssInfo->fgIsWmmAssoc = FALSE; + prTxCtrl->rTxQForVoipAccess = TXQ_AC1; + + kalMemZero(&prBssInfo->rWmmInfo, sizeof(WMM_INFO_T)); + } + + /* 4 <3.C> Operational Rate Set & BSS Basic Rate Set */ + prBssInfo->u2OperationalRateSet = prPeerBssInfo->u2OperationalRateSet; + prBssInfo->u2BSSBasicRateSet = prPeerBssInfo->u2BSSBasicRateSet; + + /* 4 <3.D> Short Preamble */ + if (prBssInfo->fgIsERPPresent) { + + /* NOTE(Kevin 2007/12/24): Truth Table. + * Short Preamble Bit in + * Final Drv Set + * TRUE FALSE FALSE FALSE(#1) + * TRUE FALSE TRUE FALSE + * FALSE FALSE FALSE FALSE(#1) + * FALSE FALSE TRUE FALSE + * TRUE TRUE FALSE TRUE(#2) + * TRUE TRUE TRUE FALSE(#2) + * FALSE TRUE FALSE FALSE(#3) + * FALSE TRUE TRUE FALSE(#4) + * #1: shouldn't have such case, use the AssocResp + * #2: follow ERP + * #3: shouldn't have such case, and we should set to FALSE + * #4: we should set to FALSE + */ + if ((prPeerBssInfo->fgIsShortPreambleAllowed) && + ((prConnSettings->ePreambleType == PREAMBLE_TYPE_SHORT) || + /* Short Preamble Option Enable is TRUE */ + ((prConnSettings->ePreambleType == PREAMBLE_TYPE_AUTO) && + (prBssDesc->u2CapInfo & CAP_INFO_SHORT_PREAMBLE)))) { + + prBssInfo->fgIsShortPreambleAllowed = TRUE; + + if (prBssInfo->ucERP & ERP_INFO_BARKER_PREAMBLE_MODE) + prBssInfo->fgUseShortPreamble = FALSE; + else + prBssInfo->fgUseShortPreamble = TRUE; + } else { + prBssInfo->fgIsShortPreambleAllowed = FALSE; + prBssInfo->fgUseShortPreamble = FALSE; + } + } else { + /* NOTE(Kevin 2007/12/24): Truth Table. + * Short Preamble Bit in + * Final Driver Setting(Short) + * TRUE FALSE FALSE + * FALSE FALSE FALSE + * TRUE TRUE TRUE + * FALSE TRUE(status success) TRUE + * --> Honor the result of prPeerBssInfo. + */ + + prBssInfo->fgIsShortPreambleAllowed = + prBssInfo->fgUseShortPreamble = + prPeerBssInfo->fgIsShortPreambleAllowed; + } + + DBGLOG(JOIN, INFO, + "prBssInfo->fgIsShortPreambleAllowed = %d, prBssInfo->fgUseShortPreamble = %d\n", + prBssInfo->fgIsShortPreambleAllowed, + prBssInfo->fgUseShortPreamble); + + /* 4 <3.E> Short Slot Time */ + /* AP support Short Slot Time */ + prBssInfo->fgUseShortSlotTime = prPeerBssInfo->fgUseShortSlotTime; + + 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) { + uint16_t 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, (uint8_t) TXQ_DATA_MASK, + (uint8_t) 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, + (void *) NULL, 0); +} /* end of joinComplete() */ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/scan.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/scan.c new file mode 100644 index 0000000000000..c768a41feecb0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/scan.c @@ -0,0 +1,4296 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + + +/******************************************************************************* + * C O M P I L E 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_STRENGTH_THRESHOLD (32) +#define ROAMING_NO_SWING_RCPI_STEP (10) +#define REPLICATED_BEACON_FRESH_PERIOD (10000) +#define REPLICATED_BEACON_TIME_THRESHOLD (3000) + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +/* The order of aucScanLogPrefix should be aligned the order + * of enum ENUM_SCAN_LOG_PREFIX + */ +const char aucScanLogPrefix[][SCAN_LOG_PREFIX_MAX_LEN] = { + /* Scan */ + "[SCN:100:K2D]", /* LOG_SCAN_REQ_K2D */ + "[SCN:200:D2F]", /* LOG_SCAN_REQ_D2F */ + "[SCN:300:F2D]", /* LOG_SCAN_RESULT_F2D */ + "[SCN:400:D2K]", /* LOG_SCAN_RESULT_D2K */ + "[SCN:500:F2D]", /* LOG_SCAN_DONE_F2D */ + "[SCN:600:D2K]", /* LOG_SCAN_DONE_D2K */ + + /* Sched scan */ + "[SCN:700:K2D]", /* LOG_SCHED_SCAN_REQ_START_K2D */ + "[SCN:800:D2F]", /* LOG_SCHED_SCAN_REQ_START_D2F */ + "[SCN:750:K2D]", /* LOG_SCHED_SCAN_REQ_STOP_K2D */ + "[SCN:850:D2F]", /* LOG_SCHED_SCAN_REQ_STOP_D2F */ + "[SCN:900:F2D]", /* LOG_SCHED_SCAN_DONE_F2D */ + "[SCN:1000:D2K]", /* LOG_SCHED_SCAN_DONE_D2K */ + + /* Scan abort */ + "[SCN:1100:K2D]", /* LOG_SCAN_ABORT_REQ_K2D */ + "[SCN:1200:D2F]", /* LOG_SCAN_ABORT_REQ_D2F */ + "[SCN:1300:D2K]", /* LOG_SCAN_ABORT_DONE_D2K */ + + /* Driver only */ + "[SCN:0:D2D]", /* LOG_SCAN_D2D */ + + /* Last one */ + "" /* LOG_SCAN_MAX */ +}; + +/******************************************************************************* + * 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 struct ADAPTER *prAdapter) +{ + struct SCAN_INFO *prScanInfo; + struct BSS_DESC *prBSSDesc; + uint8_t *pucBSSBuff; + uint32_t i; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + pucBSSBuff = &prScanInfo->aucScanBuffer[0]; + + log_dbg(SCN, TRACE, "->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((void *) pucBSSBuff, SCN_MAX_BUFFER_SIZE); + + LINK_INITIALIZE(&prScanInfo->rFreeBSSDescList); + LINK_INITIALIZE(&prScanInfo->rBSSDescList); + + for (i = 0; i < CFG_MAX_NUM_BSS_LIST; i++) { + + prBSSDesc = (struct BSS_DESC *) pucBSSBuff; + + scanInsertBssDescToList(&prScanInfo->rFreeBSSDescList, + prBSSDesc, + FALSE); + + pucBSSBuff += ALIGN_4(sizeof(struct BSS_DESC)); + } + /* Check if the memory allocation consist with + * this initialization function + */ + ASSERT(((unsigned long) pucBSSBuff + - (unsigned long)&prScanInfo->aucScanBuffer[0]) + == SCN_MAX_BUFFER_SIZE); + + /* reset freest channel information */ + prScanInfo->fgIsSparseChannelValid = FALSE; + + prScanInfo->fgIsScanForFull2Partial = FALSE; + + /* reset Sched scan state */ + prScanInfo->fgSchedScanning = FALSE; + /*Support AP Selection */ + prScanInfo->u4ScanUpdateIdx = 0; +} /* end of scnInit() */ + +void scnFreeAllPendingScanRquests(IN struct ADAPTER *prAdapter) +{ + struct SCAN_INFO *prScanInfo; + struct MSG_HDR *prMsgHdr; + struct MSG_SCN_SCAN_REQ *prScanReqMsg; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + /* check for pending scanning requests */ + while (!LINK_IS_EMPTY(&(prScanInfo->rPendingMsgList))) { + + /* load next message from pending list as scan parameters */ + LINK_REMOVE_HEAD(&(prScanInfo->rPendingMsgList), + prMsgHdr, struct MSG_HDR *); + if (prMsgHdr) { + prScanReqMsg = (struct MSG_SCN_SCAN_REQ *) prMsgHdr; + + log_dbg(SCN, INFO, "Free scan request eMsgId[%d] ucSeqNum [%d] BSSID[%d]!!\n", + prMsgHdr->eMsgId, + prScanReqMsg->ucSeqNum, + prScanReqMsg->ucBssIndex); + + cnmMemFree(prAdapter, prMsgHdr); + } else { + /* should not deliver to this function */ + ASSERT(0); + } + /* switch to next state */ + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is used by SCN to uninitialize its variables + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void scnUninit(IN struct ADAPTER *prAdapter) +{ + struct SCAN_INFO *prScanInfo; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + log_dbg(SCN, INFO, "%s()\n", __func__); + + scnFreeAllPendingScanRquests(prAdapter); + + /* 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); +} /* 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 + */ +/*----------------------------------------------------------------------------*/ +struct BSS_DESC *scanSearchBssDescByBssid(IN struct ADAPTER *prAdapter, + IN uint8_t aucBSSID[]) +{ + return scanSearchBssDescByBssidAndSsid(prAdapter, aucBSSID, + FALSE, NULL); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Check if the bit of the given bitmap is set + * The bitmap should be unsigned int based, which means that this function + * doesn't support other format bitmap, e.g. char array or short array + * + * @param[in] bit which bit to check. + * @param[in] bitMap bitmap array + * @param[in] bitMapSize bytes of bitmap + * + * @return TRUE if the bit of the given bitmap is set, FALSE otherwise + */ +/*----------------------------------------------------------------------------*/ +u_int8_t scanIsBitSet(IN uint32_t bit, IN uint32_t bitMap[], + IN uint32_t bitMapSize) +{ + if (bit >= bitMapSize * BITS_OF_BYTE) { + log_dbg(SCN, WARN, "bit %u is out of array range(%u bits)\n", + bit, bitMapSize * BITS_OF_BYTE); + return FALSE; + } else { + return (bitMap[bit/BITS_OF_UINT] & + (1 << (bit % BITS_OF_UINT))) ? TRUE : FALSE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Set the bit of the given bitmap. + * The bitmap should be unsigned int based, which means that this function + * doesn't support other format bitmap, e.g. char array or short array + * + * @param[in] bit which bit to set. + * @param[out] bitMap bitmap array + * @param[in] bitMapSize bytes of bitmap + * + * @return void + */ +/*----------------------------------------------------------------------------*/ +void scanSetBit(IN uint32_t bit, OUT uint32_t bitMap[], IN uint32_t bitMapSize) +{ + if (bit >= bitMapSize * BITS_OF_BYTE) { + log_dbg(SCN, WARN, "set bit %u to array(%u bits) failed\n", + bit, bitMapSize * BITS_OF_BYTE); + } else + bitMap[bit/BITS_OF_UINT] |= 1 << (bit % BITS_OF_UINT); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Return number of bit which is set to 1 in the given bitmap. + * The bitmap should be unsigned int based, which means that this function + * doesn't support other format bitmap, e.g. char array or short array + * + * @param[in] bitMap bitmap array + * @param[in] bitMapSize bytes of bitmap + * + * @return number of bit which is set to 1 + */ +/*----------------------------------------------------------------------------*/ + +uint32_t scanCountBits(IN uint32_t bitMap[], IN uint32_t bitMapSize) +{ + uint32_t count = 0; + uint32_t value; + int32_t arrayLen = bitMapSize/sizeof(uint32_t); + int32_t i; + + for (i = arrayLen - 1; i >= 0; i--) { + value = bitMap[i]; + log_dbg(SCN, TRACE, "array[%d]:%08X\n", i, value); + while (value) { + count += (value & 1); + value >>= 1; + } + } + return count; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Set scan channel to scanReqMsg. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] u4ScanChannelNum number of input channels + * @param[in] arChannel channel list + * @param[in] fgIsOnlineScan online scan or not + * @param[out] prScanReqMsg scan request msg. Set channel number and + * channel list for output + * + * @return + */ +/*----------------------------------------------------------------------------*/ +void scanSetRequestChannel(IN struct ADAPTER *prAdapter, + IN uint32_t u4ScanChannelNum, + IN struct RF_CHANNEL_INFO arChannel[], + IN uint32_t u4ScanFlags, + IN uint8_t fgIsOnlineScan, + OUT struct MSG_SCN_SCAN_REQ_V2 *prScanReqMsg) +{ + uint32_t i, u4Channel, eBand, u4Index; + /*print channel info for debugging */ + uint32_t au4ChannelBitMap[SCAN_CHANNEL_BITMAP_ARRAY_LEN]; + struct SCAN_INFO *prScanInfo; + bool fgIsLowSpanScan = FALSE; +#if CFG_SUPPORT_FULL2PARTIAL_SCAN + uint8_t fgIsFull2Partial = FALSE; + OS_SYSTIME rCurrentTime; + + GET_CURRENT_SYSTIME(&rCurrentTime); +#endif /* CFG_SUPPORT_FULL2PARTIAL_SCAN */ + + ASSERT(u4ScanChannelNum <= MAXIMUM_OPERATION_CHANNEL_LIST); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + i = u4Index = 0; + kalMemZero(au4ChannelBitMap, sizeof(au4ChannelBitMap)); + fgIsLowSpanScan = (u4ScanFlags & NL80211_SCAN_FLAG_LOW_SPAN) >> 8; + +#if CFG_SUPPORT_FULL2PARTIAL_SCAN + /* fgIsCheckingFull2Partial should be true if it's an online scan. + * Next, enable full2partial if channel number to scan is + * larger than SCAN_FULL2PARTIAL_CHANNEL_NUM + */ + if (fgIsOnlineScan && (u4ScanChannelNum == 0 || + u4ScanChannelNum > SCAN_FULL2PARTIAL_CHANNEL_NUM)) { + + /* Do full scan when + * 1. did not do full scan yet OR + * 2. not APP scan and it's been 60s after last full scan + */ + if (prScanInfo->u4LastFullScanTime == 0 || + (!fgIsLowSpanScan && + (CHECK_FOR_TIMEOUT(rCurrentTime, + prScanInfo->u4LastFullScanTime, + SEC_TO_SYSTIME(CFG_SCAN_FULL2PARTIAL_PERIOD))))) { + prScanInfo->fgIsScanForFull2Partial = TRUE; + prScanInfo->ucFull2PartialSeq = prScanReqMsg->ucSeqNum; + prScanInfo->u4LastFullScanTime = rCurrentTime; + kalMemZero(prScanInfo->au4ChannelBitMap, + sizeof(prScanInfo->au4ChannelBitMap)); + log_dbg(SCN, INFO, + "Full2partial: 1st full scan start, low span=%d\n", + fgIsLowSpanScan); + } else { + log_dbg(SCN, INFO, + "Full2partial: enable full2partial, low span=%d\n", + fgIsLowSpanScan); + fgIsFull2Partial = TRUE; + } + } + + if (u4ScanChannelNum == 0) { + /* We don't have channel info when u4ScanChannelNum is 0. + * check full2partial bitmap and set scan channels + */ + uint32_t start = 1; + uint32_t end = HW_CHNL_NUM_MAX_4G_5G; + + if (prScanReqMsg->eScanChannel == SCAN_CHANNEL_2G4) + end = HW_CHNL_NUM_MAX_2G4; + else if (prScanReqMsg->eScanChannel == SCAN_CHANNEL_5G) + start = HW_CHNL_NUM_MAX_2G4 + 1; + + u4Index = 0; + /* If partial scan list are too old, do full scan */ + if (!CHECK_FOR_TIMEOUT(rCurrentTime, + prScanInfo->u4LastFullScanTime, + SEC_TO_SYSTIME(CFG_SCAN_FULL2PARTIAL_PERIOD))) { + for (u4Channel = start; u4Channel <= end; u4Channel++) { + if (scanIsBitSet(u4Channel, + prScanInfo->au4ChannelBitMap, + sizeof(prScanInfo->au4ChannelBitMap))) { + eBand = (u4Channel <= + HW_CHNL_NUM_MAX_2G4) ? + BAND_2G4 : BAND_5G; + prScanReqMsg->arChnlInfoList[u4Index]. + ucChannelNum = u4Channel; + prScanReqMsg->arChnlInfoList[u4Index]. + eBand = eBand; + scanSetBit(u4Channel, au4ChannelBitMap, + sizeof(au4ChannelBitMap)); + u4Index++; + } + } + } + + prScanReqMsg->ucChannelListNum = u4Index; + if (u4Index == 0) { + log_dbg(SCN, WARN, "No channel to scan, set to full scan\n"); + prScanReqMsg->eScanChannel = SCAN_CHANNEL_FULL; + } else + prScanReqMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; + } else +#endif /* CFG_SUPPORT_FULL2PARTIAL_SCAN */ + { + u4Index = 0; + for (i = 0; i < u4ScanChannelNum; i++) { + u4Channel = arChannel[i].ucChannelNum; + eBand = arChannel[i].eBand; + if (prScanReqMsg->eScanChannel == SCAN_CHANNEL_2G4 && + eBand != BAND_2G4) + continue; + else if (prScanReqMsg->eScanChannel == + SCAN_CHANNEL_5G && eBand != BAND_5G) + continue; +#if CFG_SUPPORT_FULL2PARTIAL_SCAN + if (fgIsFull2Partial && !scanIsBitSet(u4Channel, + prScanInfo->au4ChannelBitMap, + sizeof(prScanInfo->au4ChannelBitMap))) + continue; +#endif /* CFG_SUPPORT_FULL2PARTIAL_SCAN */ + kalMemCopy(&prScanReqMsg->arChnlInfoList[u4Index], + &arChannel[i], + sizeof(struct RF_CHANNEL_INFO)); + scanSetBit(u4Channel, au4ChannelBitMap, + sizeof(au4ChannelBitMap)); + + u4Index++; + } + if (u4Index == 0) { + log_dbg(SCN, WARN, "No channel to scan, set to full scan\n"); + prScanReqMsg->ucChannelListNum = 0; + prScanReqMsg->eScanChannel = SCAN_CHANNEL_FULL; + } else { + prScanReqMsg->ucChannelListNum = u4Index; + prScanReqMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; + } + } + + log_dbg(SCN, INFO, + "channel num(%u=>%u) %08X %08X %08X %08X %08X %08X %08X %08X\n", + u4ScanChannelNum, prScanReqMsg->ucChannelListNum, + au4ChannelBitMap[7], au4ChannelBitMap[6], + au4ChannelBitMap[5], au4ChannelBitMap[4], + au4ChannelBitMap[3], au4ChannelBitMap[2], + au4ChannelBitMap[1], au4ChannelBitMap[0]); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Find the corresponding BSS Descriptor according to given BSSID + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] aucBSSID Given BSSID. + * @param[in] fgCheckSsid Need to check SSID or not. (for multiple SSID + * with single BSSID cases) + * @param[in] prSsid Specified SSID + * + * @return Pointer to BSS Descriptor, if found. NULL, if not found + */ +/*----------------------------------------------------------------------------*/ +struct BSS_DESC * +scanSearchBssDescByBssidAndSsid(IN struct ADAPTER *prAdapter, + IN uint8_t aucBSSID[], + IN u_int8_t fgCheckSsid, + IN struct PARAM_SSID *prSsid) +{ + struct SCAN_INFO *prScanInfo; + struct LINK *prBSSDescList; + struct BSS_DESC *prBssDesc; + struct BSS_DESC *prDstBssDesc = (struct BSS_DESC *) 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, struct BSS_DESC) { + + if (!(EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID))) + continue; + if (fgCheckSsid == FALSE || prSsid == NULL) + return prBssDesc; + if (EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, + prSsid->aucSsid, prSsid->u4SsidLen)) { + return prBssDesc; + } + if (prDstBssDesc == NULL && prBssDesc->fgIsHiddenSSID == TRUE) { + prDstBssDesc = prBssDesc; + continue; + } + if (prBssDesc->eBSSType == BSS_TYPE_P2P_DEVICE) { + /* 20120206 frog: Equal BSSID but not SSID, + * SSID not hidden, SSID must be updated. + */ + COPY_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, + prSsid->aucSsid, (uint8_t) (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 + */ +/*----------------------------------------------------------------------------*/ +struct BSS_DESC *scanSearchBssDescByTA(IN struct ADAPTER *prAdapter, + IN uint8_t 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 + */ +/*----------------------------------------------------------------------------*/ +struct BSS_DESC * +scanSearchBssDescByTAAndSsid(IN struct ADAPTER *prAdapter, + IN uint8_t aucSrcAddr[], + IN u_int8_t fgCheckSsid, + IN struct PARAM_SSID *prSsid) +{ + struct SCAN_INFO *prScanInfo; + struct LINK *prBSSDescList; + struct BSS_DESC *prBssDesc; + struct BSS_DESC *prDstBssDesc = (struct BSS_DESC *) 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, struct BSS_DESC) { + + if (EQUAL_MAC_ADDR(prBssDesc->aucSrcAddr, aucSrcAddr)) { + if (fgCheckSsid == FALSE || prSsid == NULL) + return prBssDesc; + if (EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, + prSsid->aucSsid, prSsid->u4SsidLen)) { + return prBssDesc; + } else if (prDstBssDesc == NULL + && prBssDesc->fgIsHiddenSSID == TRUE) { + prDstBssDesc = prBssDesc; + } + } + } + + return prDstBssDesc; + +} /* end of scanSearchBssDescByTA() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +struct BSS_DESC * +scanSearchExistingBssDesc(IN struct ADAPTER *prAdapter, + IN enum ENUM_BSS_TYPE eBSSType, + IN uint8_t aucBSSID[], + IN uint8_t 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 + */ +/*----------------------------------------------------------------------------*/ +struct BSS_DESC * +scanSearchExistingBssDescWithSsid(IN struct ADAPTER *prAdapter, + IN enum ENUM_BSS_TYPE eBSSType, + IN uint8_t aucBSSID[], + IN uint8_t aucSrcAddr[], + IN u_int8_t fgCheckSsid, + IN struct PARAM_SSID *prSsid) +{ + struct SCAN_INFO *prScanInfo; + struct BSS_DESC *prBssDesc, *prIBSSBssDesc; + /* CASE III */ + struct LINK *prBSSDescList; + struct LINK *prFreeBSSDescList; + + ASSERT(prAdapter); + ASSERT(aucSrcAddr); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + switch (eBSSType) { + case BSS_TYPE_P2P_DEVICE: + fgCheckSsid = FALSE; + /* fall through */ + case BSS_TYPE_INFRASTRUCTURE: + /* fall through */ + 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; + } + + + prBSSDescList = &prScanInfo->rBSSDescList; + prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; + + /* Remove this BSS Desc from the BSS Desc list */ + scanRemoveBssDescFromList(prBSSDescList, + prBssDesc, + prAdapter); + + /* Return this BSS Desc to the free BSS Desc list. */ + scanInsertBssDescToList(prFreeBSSDescList, + prBssDesc, + FALSE); + + return prIBSSBssDesc; + } + + if (prIBSSBssDesc) { /* CASE IV */ + + return prIBSSBssDesc; + } + /* CASE V */ + break; /* Return NULL; */ + default: + break; + } + + return (struct BSS_DESC *) 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 struct ADAPTER *prAdapter, + IN uint32_t u4RemovePolicy) +{ + struct SCAN_INFO *prScanInfo; + struct LINK *prBSSDescList; + struct LINK *prFreeBSSDescList; + struct BSS_DESC *prBssDesc; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; + +#if 0 /* TODO: Remove this */ + log_dbg(SCN, TRACE, ("Before Remove - Number Of SCAN Result = %ld\n", + prBSSDescList->u4NumElem)); +#endif + + if (u4RemovePolicy & SCN_RM_POLICY_TIMEOUT) { + struct BSS_DESC *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, struct BSS_DESC) { + + 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(wlanWfdEnabled(prAdapter) ? + SCN_BSS_DESC_STALE_SEC_WFD : + SCN_BSS_DESC_STALE_SEC))) { + +#if 0 /* TODO: Remove this */ + log_dbg(SCN, TRACE, "Remove TIMEOUT BSS DESC(%#x):MAC: " + MACSTR + ", Current Time = %08lx, Update Time = %08lx\n", + prBssDesc, + MAC2STR(prBssDesc->aucBSSID), + rCurrentTime, prBssDesc->rUpdateTime)); +#endif + scanRemoveBssDescFromList(prBSSDescList, + prBssDesc, + prAdapter); + + /* Return this BSS Desc to the + * free BSS Desc list. + */ + scanInsertBssDescToList(prFreeBSSDescList, + prBssDesc, + FALSE); + } + } + } + if (u4RemovePolicy & SCN_RM_POLICY_OLDEST_HIDDEN) { + struct BSS_DESC *prBssDescOldest = (struct BSS_DESC *) NULL; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, + rLinkEntry, struct BSS_DESC) { + + 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) { +#if 0 /* TODO: Remove this */ + log_dbg(SCN, TRACE, "Remove OLDEST HIDDEN BSS DESC(%#x): MAC: " + MACSTR + ", Update Time = %08lx\n", + prBssDescOldest, + MAC2STR(prBssDescOldest->aucBSSID), + prBssDescOldest->rUpdateTime); +#endif + scanRemoveBssDescFromList(prBSSDescList, + prBssDescOldest, + prAdapter); + + /* Return this BSS Desc to the free BSS Desc list. */ + scanInsertBssDescToList(prFreeBSSDescList, + prBssDescOldest, + FALSE); + } + } + if (u4RemovePolicy & SCN_RM_POLICY_SMART_WEAKEST) { + struct BSS_DESC *prBssDescWeakest = (struct BSS_DESC *) NULL; + struct BSS_DESC *prBssDescWeakestSameSSID + = (struct BSS_DESC *) NULL; + uint32_t u4SameSSIDCount = 0; + uint8_t j; + uint8_t fgIsSameSSID; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, + rLinkEntry, struct BSS_DESC) { + + if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) + && (prBssDesc->fgIsConnected + || prBssDesc->fgIsConnecting)) { + /* Don't remove the one currently + * we are connected. + */ + continue; + } + + fgIsSameSSID = FALSE; + for (j = 0; j < KAL_AIS_NUM; j++) { + + struct CONNECTION_SETTINGS *prConnSettings = + aisGetConnSettings(prAdapter, j); + + if (!prConnSettings) + 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; + + fgIsSameSSID = TRUE; + } + } + + if (fgIsSameSSID && + u4SameSSIDCount + < SCN_BSS_DESC_SAME_SSID_THRESHOLD) + continue; + + 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) { +#if 0 /* TODO: Remove this */ + log_dbg(SCN, TRACE, "Remove WEAKEST BSS DESC(%#x): MAC: " + MACSTR + ", Update Time = %08lx\n", + prBssDescOldest, + MAC2STR(prBssDescOldest->aucBSSID), + prBssDescOldest->rUpdateTime); +#endif + + scanRemoveBssDescFromList(prBSSDescList, + prBssDescWeakest, + prAdapter); + + /* Return this BSS Desc to the free BSS Desc list. */ + scanInsertBssDescToList(prFreeBSSDescList, + prBssDescWeakest, + FALSE); + } + } + if (u4RemovePolicy & SCN_RM_POLICY_ENTIRE) { + struct BSS_DESC *prBSSDescNext; + + LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, + prBSSDescList, rLinkEntry, struct BSS_DESC) { + + if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) + && (prBssDesc->fgIsConnected + || prBssDesc->fgIsConnecting)) { + /* Don't remove the one currently + * we are connected. + */ + continue; + } + + scanRemoveBssDescFromList(prBSSDescList, + prBssDesc, + prAdapter); + + /* Return this BSS Desc to the free BSS Desc list. */ + scanInsertBssDescToList(prFreeBSSDescList, + prBssDesc, + FALSE); + } + + } +} /* 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 struct ADAPTER *prAdapter, + IN uint8_t aucBSSID[]) +{ + struct SCAN_INFO *prScanInfo; + struct LINK *prBSSDescList; + struct LINK *prFreeBSSDescList; + struct BSS_DESC *prBssDesc = (struct BSS_DESC *) NULL; + struct BSS_DESC *prBSSDescNext; + uint8_t ucTargetChNum = 0; + enum ENUM_BAND eTargetBand = BAND_NULL; + + 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, struct BSS_DESC) { + + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { + /* Because BSS descriptor will be cleared in next step, + * so we need to keep them temporarily. + */ + ucTargetChNum = prBssDesc->ucChannelNum; + eTargetBand = prBssDesc->eBand; + + /* Clear BSS descriptor */ + scanRemoveBssDescFromList(prBSSDescList, + prBssDesc, + prAdapter); + + /* Return this BSS Desc to the free BSS Desc list. */ + scanInsertBssDescToList(prFreeBSSDescList, + prBssDesc, + FALSE); + + /* We should notify kernel to unlink BSS */ + kalRemoveBss( + prAdapter->prGlueInfo, + aucBSSID, + ucTargetChNum, + eTargetBand); + + /* BSSID is not unique, so need to traverse + * whols link-list + */ + } + } +} /* end of scanRemoveBssDescByBssid() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Delete BSS Descriptors from current list according to given + * band configuration + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] eBand Given band + * @param[in] ucBssIndex AIS - Remove IBSS/Infrastructure BSS + * BOW - Remove BOW BSS + * P2P - Remove P2P BSS + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void scanRemoveBssDescByBandAndNetwork(IN struct ADAPTER *prAdapter, + IN enum ENUM_BAND eBand, + IN uint8_t ucBssIndex) +{ + struct SCAN_INFO *prScanInfo; + struct LINK *prBSSDescList; + struct LINK *prFreeBSSDescList; + struct BSS_DESC *prBssDesc = (struct BSS_DESC *) NULL; + struct BSS_DESC *prBSSDescNext; + u_int8_t fgToRemove; + + ASSERT(prAdapter); + ASSERT(eBand <= BAND_NUM); + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; + + if (eBand == BAND_NULL) { + /* no need to do anything, keep all scan result */ + return; + } + + /* Check if such BSS Descriptor exists in a valid list */ + LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, + rLinkEntry, struct BSS_DESC) { + fgToRemove = FALSE; + + if (prBssDesc->eBand == eBand) { + switch (GET_BSS_INFO_BY_INDEX( + prAdapter, ucBssIndex)->eNetworkType) { + case NETWORK_TYPE_AIS: + if ((prBssDesc->eBSSType + == BSS_TYPE_INFRASTRUCTURE) + || (prBssDesc->eBSSType == BSS_TYPE_IBSS)) { + fgToRemove = TRUE; + } + break; + + case NETWORK_TYPE_P2P: + if (prBssDesc->eBSSType == BSS_TYPE_P2P_DEVICE) + fgToRemove = TRUE; + break; + + case NETWORK_TYPE_BOW: + if (prBssDesc->eBSSType == BSS_TYPE_BOW_DEVICE) + fgToRemove = TRUE; + break; + + default: + ASSERT(0); + break; + } + } + + if (fgToRemove == TRUE) { + scanRemoveBssDescFromList(prBSSDescList, + prBssDesc, + prAdapter); + + /* Return this BSS Desc to the free BSS Desc list. */ + scanInsertBssDescToList(prFreeBSSDescList, + prBssDesc, + FALSE); + } + } +} /* end of scanRemoveBssDescByBand() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Clear the CONNECTION FLAG of a specified BSS Descriptor. + * + * @param[in] aucBSSID Given BSSID. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void scanRemoveConnFlagOfBssDescByBssid(IN struct ADAPTER *prAdapter, + IN uint8_t aucBSSID[]) +{ + struct SCAN_INFO *prScanInfo; + struct LINK *prBSSDescList; + struct BSS_DESC *prBssDesc = (struct BSS_DESC *) 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, struct BSS_DESC) { + + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { + prBssDesc->fgIsConnected = FALSE; + prBssDesc->fgIsConnecting = FALSE; + + /* BSSID is not unique, so need to + * traverse whols link-list + */ + } + } +} /* end of scanRemoveConnectionFlagOfBssDescByBssid() */ + + +#if (CFG_SUPPORT_802_11V_MBSSID == 1) +/*----------------------------------------------------------------------------*/ +/*! + * @brief Allocate new BSS_DESC structure + * + * @param[in] prAdapter Pointer to the Adapter structure. + * + * @return Pointer to BSS Descriptor, if has + * free space. NULL, if has no space. + */ +/*----------------------------------------------------------------------------*/ +void scanParsingMBSSIDSubelement(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prTransBSS, IN struct IE_MBSSID *prMbssidIe) +{ + uint8_t *pucIE; + uint16_t u2IELength, u2Offset; + uint8_t *pucProfileIE; + uint16_t u2ProfileLen, u2ProfileOffset; + struct BSS_DESC *prBssDesc; + struct IE_MBSSID_INDEX *prMbssidIdxIe; + uint8_t aucBSSID[MAC_ADDR_LEN]; + int8_t ucBssidLsb; + + if (prMbssidIe->ucMaxBSSIDIndicator == 0) /* invalid mbssid ie*/ + return; + + prTransBSS->ucMaxBSSIDIndicator = prMbssidIe->ucMaxBSSIDIndicator; + u2Offset = 0; + pucIE = &prMbssidIe->ucSubelements[0]; + u2IELength = IE_SIZE(prMbssidIe) - + OFFSET_OF(struct IE_MBSSID, ucSubelements); + IE_FOR_EACH(pucIE, u2IELength, u2Offset) + { + pucProfileIE = NULL; + /*search for each nontransmitted bssid profile*/ + if (IE_ID(pucIE) == NON_TX_BSSID_PROFILE) { + pucProfileIE = &((struct IE_HDR *)pucIE)->aucInfo[0]; + u2ProfileLen = IE_LEN(pucIE); + u2ProfileOffset = 0; + } + if (pucProfileIE == NULL) + continue; + + /*search for mbssid index ie in each profile*/ + prMbssidIdxIe = NULL; + IE_FOR_EACH(pucProfileIE, u2ProfileLen, u2ProfileOffset) { + if (IE_ID(pucProfileIE) == ELEM_ID_MBSSID_INDEX) { + prMbssidIdxIe = MBSSID_INDEX_IE(pucProfileIE); + break; + } + } + if (prMbssidIdxIe == NULL) + continue; + + /*calculate BSSID of this profile*/ + kalMemCopy(aucBSSID, &prTransBSS->aucBSSID[0], MAC_ADDR_LEN); + ucBssidLsb = aucBSSID[5] & + ((1 << prMbssidIe->ucMaxBSSIDIndicator) - 1); + aucBSSID[5] &= ~((1 << prMbssidIe->ucMaxBSSIDIndicator) - 1); + aucBSSID[5] |= (ucBssidLsb + prMbssidIdxIe->ucBSSIDIndex) % + (1 << prMbssidIe->ucMaxBSSIDIndicator); + + prBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, + aucBSSID, FALSE, NULL); + if (prBssDesc) { + prBssDesc->ucMaxBSSIDIndicator = + prMbssidIe->ucMaxBSSIDIndicator; + prBssDesc->ucMBSSIDIndex = + prMbssidIdxIe->ucBSSIDIndex; + } + } +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Allocate new BSS_DESC structure + * + * @param[in] prAdapter Pointer to the Adapter structure. + * + * @return Pointer to BSS Descriptor, if has + * free space. NULL, if has no space. + */ +/*----------------------------------------------------------------------------*/ +struct BSS_DESC *scanAllocateBssDesc(IN struct ADAPTER *prAdapter) +{ + struct SCAN_INFO *prScanInfo; + struct LINK *prFreeBSSDescList; + struct BSS_DESC *prBssDesc; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; + + LINK_REMOVE_HEAD(prFreeBSSDescList, prBssDesc, struct BSS_DESC *); + + if (prBssDesc) { + struct LINK *prBSSDescList; + + prBSSDescList = &prScanInfo->rBSSDescList; + + /* NOTE(Kevin): In current design, this new empty + * struct BSS_DESC will be inserted to BSSDescList immediately. + */ + scanInsertBssDescToList(prBSSDescList, + prBssDesc, + TRUE); + } + + return prBssDesc; + +} /* end of scanAllocateBssDesc() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This API parses Beacon/ProbeResp frame and insert extracted + * BSS_DESC structure 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 + */ +/*----------------------------------------------------------------------------*/ +struct BSS_DESC *scanAddToBssDesc(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct BSS_DESC *prBssDesc = NULL; + uint16_t u2CapInfo; + enum ENUM_BSS_TYPE eBSSType = BSS_TYPE_INFRASTRUCTURE; + + uint8_t *pucIE; + uint16_t u2IELength; + uint16_t u2Offset = 0; + + struct WLAN_BEACON_FRAME *prWlanBeaconFrame + = (struct WLAN_BEACON_FRAME *) NULL; + struct IE_SSID *prIeSsid = (struct IE_SSID *) NULL; + struct IE_SUPPORTED_RATE_IOT *prIeSupportedRate + = (struct IE_SUPPORTED_RATE_IOT *) NULL; + struct IE_EXT_SUPPORTED_RATE *prIeExtSupportedRate + = (struct IE_EXT_SUPPORTED_RATE *) NULL; + uint8_t ucHwChannelNum = 0; + uint8_t ucIeDsChannelNum = 0; + uint8_t ucIeHtChannelNum = 0; + u_int8_t fgIsValidSsid = FALSE; + struct PARAM_SSID rSsid; + uint64_t u8Timestamp; + u_int8_t fgIsNewBssDesc = FALSE; + + uint32_t i; + uint8_t ucSSIDChar; + /* PUINT_8 pucDumpIE; */ + enum ENUM_BAND eHwBand = BAND_NULL; + u_int8_t fgBandMismatch = FALSE; + uint8_t ucSubtype; + u_int8_t fgIsProbeResp = FALSE; + u_int8_t ucPowerConstraint = 0; + struct IE_COUNTRY *prCountryIE = NULL; + struct RX_DESC_OPS_T *prRxDescOps; +#if ((CFG_SUPPORT_802_11AX == 1) && (CFG_SUPPORT_HE_ER == 1)) + struct _IE_HE_OP_T *prHeOp; + struct _IE_HE_CAP_T *prHeCap; +#endif + + ASSERT(prAdapter); + ASSERT(prSwRfb); + prRxDescOps = prAdapter->chip_info->prRxDescOps; + + RX_STATUS_GET(prRxDescOps, eHwBand, get_rf_band, prSwRfb->prRxStatus); + prWlanBeaconFrame = (struct WLAN_BEACON_FRAME *) prSwRfb->pvHeader; + ucSubtype = (*(uint8_t *) (prSwRfb->pvHeader) & + MASK_FC_SUBTYPE) >> OFFSET_OF_FC_SUBTYPE; + + 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: + log_dbg(SCN, WARN, "Skip unknown bss type(%u)\n", u2CapInfo); + return NULL; + } + + /* 4 <1.1> Pre-parse SSID IE and channel info */ + pucIE = prWlanBeaconFrame->aucInfoElem; + u2IELength = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - + (uint16_t) OFFSET_OF(struct WLAN_BEACON_FRAME_BODY, aucInfoElem[0]); + + if (u2IELength > CFG_IE_BUFFER_SIZE) { + /* Give an warning msg when IE is going to be + * truncated. + */ + DBGLOG(SCN, ERROR, + "IE len(%u) > Max IE buffer size(%u), truncate IE!\n", + u2IELength, CFG_IE_BUFFER_SIZE); + u2IELength = CFG_IE_BUFFER_SIZE; + } + kalMemZero(&rSsid, sizeof(rSsid)); + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + /* Error handling for disorder IE that IE length is 0 */ + if (IE_ID(pucIE) != ELEM_ID_SSID && IE_LEN(pucIE) == 0) + continue; + switch (IE_ID(pucIE)) { + case ELEM_ID_SSID: + if (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID) { + ucSSIDChar = '\0'; + + /* D-Link DWL-900AP+ */ + if (IE_LEN(pucIE) == 0) + fgIsValidSsid = FALSE; + /* Cisco AP1230A - + * (IE_LEN(pucIE) == 1) + * && (SSID_IE(pucIE)->aucSSID[0] == '\0') + */ + /* Linksys WRK54G/WL520g - + * (IE_LEN(pucIE) == n) + * && (SSID_IE(pucIE)->aucSSID[0~(n-1)] == '\0') + */ + else { + for (i = 0; i < IE_LEN(pucIE); i++) { + ucSSIDChar + |= SSID_IE(pucIE) + ->aucSSID[i]; + } + + if (ucSSIDChar) + fgIsValidSsid = TRUE; + } + + /* Update SSID to BSS Descriptor only if + * SSID is not hidden. + */ + if (fgIsValidSsid == TRUE) { + COPY_SSID(rSsid.aucSsid, + rSsid.u4SsidLen, + SSID_IE(pucIE)->aucSSID, + SSID_IE(pucIE)->ucLength); + } + } + 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_HT_OP: + if (IE_LEN(pucIE) == (sizeof(struct IE_HT_OP) - 2)) + ucIeHtChannelNum = ((struct IE_HT_OP *) pucIE) + ->ucPrimaryChannel; + break; + default: + break; + } + } + + /** + * Set band mismatch flag if we receive Beacon/ProbeResp in 2.4G band, + * but the channel num in IE info is 5G, and vice versa + * We can get channel num from different IE info, we select + * ELEM_ID_DS_PARAM_SET first, and then ELEM_ID_HT_OP + * If we don't have any channel info, we set it as HW channel, which is + * the channel we get this Beacon/ProbeResp from. + */ + if (ucIeDsChannelNum > 0) { + if (ucIeDsChannelNum <= HW_CHNL_NUM_MAX_2G4) + fgBandMismatch = (eHwBand != BAND_2G4); + else if (ucIeDsChannelNum < HW_CHNL_NUM_MAX_4G_5G) + fgBandMismatch = (eHwBand != BAND_5G); + } else if (ucIeHtChannelNum > 0) { + if (ucIeHtChannelNum <= HW_CHNL_NUM_MAX_2G4) + fgBandMismatch = (eHwBand != BAND_2G4); + else if (ucIeHtChannelNum < HW_CHNL_NUM_MAX_4G_5G) + fgBandMismatch = (eHwBand != BAND_5G); + } + + if (fgBandMismatch) { + log_dbg(SCN, INFO, MACSTR "Band mismatch, HW band %d, DS chnl %d, HT chnl %d\n", + MAC2STR(prWlanBeaconFrame->aucBSSID), eHwBand, + ucIeDsChannelNum, ucIeHtChannelNum); + return NULL; + } + + /* 4 <1.2> Replace existing BSS_DESC structure or allocate a new one */ + prBssDesc = scanSearchExistingBssDescWithSsid( + prAdapter, + eBSSType, + (uint8_t *) prWlanBeaconFrame->aucBSSID, + (uint8_t *) prWlanBeaconFrame->aucSrcAddr, + fgIsValidSsid, fgIsValidSsid == TRUE ? &rSsid : NULL); + + log_dbg(SCN, TRACE, "Receive type %u in chnl %u %u %u (" MACSTR + ") valid(%u) found(%u)\n", + ucSubtype, ucIeDsChannelNum, ucIeHtChannelNum, + prSwRfb->ucChnlNum, + MAC2STR((uint8_t *)prWlanBeaconFrame->aucBSSID), fgIsValidSsid, + (prBssDesc != NULL) ? 1 : 0); + + if ((prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) + == MAC_FRAME_PROBE_RSP) + fgIsProbeResp = TRUE; + + if (prBssDesc == (struct BSS_DESC *) 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 + | SCN_RM_POLICY_TIMEOUT)); + + /* 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 */ + log_dbg(SCN, WARN, "alloc new BssDesc for " + MACSTR " failed\n", + MAC2STR((uint8_t *) + prWlanBeaconFrame->aucBSSID)); + 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); + + ASSERT(prSwRfb->prRxStatusGroup3); + + if (prBssDesc->eBSSType != eBSSType) { + prBssDesc->eBSSType = eBSSType; + } else if (prSwRfb->ucChnlNum != + prBssDesc->ucChannelNum + && prBssDesc->ucRCPI + > nicRxGetRcpiValueFromRxv( + prAdapter, RCPI_MODE_MAX, prSwRfb)) { + uint8_t ucRcpi = 0; + + /* for signal strength is too much weaker and + * previous beacon is not stale + */ + ASSERT(prSwRfb->prRxStatusGroup3); + ucRcpi = nicRxGetRcpiValueFromRxv(prAdapter, + RCPI_MODE_MAX, + prSwRfb); + if ((prBssDesc->ucRCPI - ucRcpi) + >= REPLICATED_BEACON_STRENGTH_THRESHOLD + && rCurrentTime - prBssDesc->rUpdateTime + <= REPLICATED_BEACON_FRESH_PERIOD) { + log_dbg(SCN, TRACE, "rssi(%u) is too much weaker and previous one(%u) is fresh\n", + ucRcpi, prBssDesc->ucRCPI); + return prBssDesc; + } + /* for received beacons too close in time domain */ + else if (rCurrentTime - prBssDesc->rUpdateTime + <= REPLICATED_BEACON_TIME_THRESHOLD) { + log_dbg(SCN, TRACE, "receive beacon/probe responses too soon(%u:%u)\n", + prBssDesc->rUpdateTime, rCurrentTime); + 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 + && prBssDesc->fgIsConnecting == FALSE) { + u_int8_t fgIsConnected, fgIsConnecting; + + if (aisGetTargetBssDesc(prAdapter, AIS_DEFAULT_INDEX) + == prBssDesc) { + log_dbg(SCN, TRACE, "Timestamap reset. Reset prTargetBssDesc BSS:" + MACSTR " connected:%x connecting:%x", + MAC2STR(prBssDesc->aucBSSID), + prBssDesc->fgIsConnected, + prBssDesc->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; + + /* Connected BSS descriptor still be used by other + * functions. Thus, we should re-initialize the BSS_DESC + * structure instead of re-allocating the BSS_DESC + * structure. + */ + scanResetBssDesc(prAdapter, prBssDesc); + + /* restore */ + prBssDesc->fgIsConnected = fgIsConnected; + prBssDesc->fgIsConnecting = fgIsConnecting; + } + } + + prBssDesc->u2RawLength = prSwRfb->u2PacketLen; + if (prBssDesc->u2RawLength > CFG_RAW_BUFFER_SIZE) { + prBssDesc->u2RawLength = CFG_RAW_BUFFER_SIZE; + /* Give an warning msg when content is going to be + * truncated. + */ + DBGLOG(SCN, WARN, + "Pkt len(%u) > Max RAW buffer size(%u), truncate it!\n", + prSwRfb->u2PacketLen, CFG_RAW_BUFFER_SIZE); + } + kalMemCopy(prBssDesc->aucRawBuf, + prWlanBeaconFrame, prBssDesc->u2RawLength); + + /* NOTE: Keep consistency of Scan Record during JOIN process */ + if (fgIsNewBssDesc == FALSE && prBssDesc->fgIsConnecting) { + log_dbg(SCN, TRACE, "we're connecting this BSS(" + MACSTR ") now, don't update it\n", + MAC2STR(prBssDesc->aucBSSID)); + return prBssDesc; + } + /* 4 <2> Get information from Fixed Fields */ + /* Update the latest BSS type information. */ + prBssDesc->eBSSType = eBSSType; + + 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) - + (uint16_t) OFFSET_OF(struct WLAN_BEACON_FRAME_BODY, aucInfoElem[0]); + + if (u2IELength > CFG_IE_BUFFER_SIZE) { + u2IELength = CFG_IE_BUFFER_SIZE; + prBssDesc->fgIsIEOverflow = TRUE; + DBGLOG(SCN, WARN, "IE is truncated!\n"); + } else { + prBssDesc->fgIsIEOverflow = FALSE; + } + prBssDesc->u2IELength = u2IELength; + + if (fgIsProbeResp || fgIsValidSsid) { + kalMemCopy(prBssDesc->aucIEBuf, prWlanBeaconFrame->aucInfoElem, + u2IELength); + } + /* 4 <2.2> reset prBssDesc variables in case that AP + * has been reconfigured + */ +#if (CFG_SUPPORT_HE_ER == 1) + prBssDesc->fgIsERSUDisable = TRUE; + prBssDesc->ucDCMMaxConRx = 0; +#endif + prBssDesc->fgIsERPPresent = FALSE; + prBssDesc->fgIsHTPresent = FALSE; + prBssDesc->fgIsVHTPresent = FALSE; +#if (CFG_SUPPORT_802_11AX == 1) + if (fgEfuseCtrlAxOn == 1) + prBssDesc->fgIsHEPresent = FALSE; +#endif + prBssDesc->eSco = CHNL_EXT_SCN; + prBssDesc->fgIEWAPI = FALSE; + prBssDesc->fgIERSN = FALSE; + prBssDesc->fgIEWPA = FALSE; + + /*Reset VHT OP IE relative settings */ + prBssDesc->eChannelWidth = CW_20_40MHZ; + + prBssDesc->ucCenterFreqS1 = 0; + prBssDesc->ucCenterFreqS2 = 0; + + /* Support AP Selection */ + prBssDesc->fgExsitBssLoadIE = FALSE; + prBssDesc->fgMultiAnttenaAndSTBC = FALSE; +#if CFG_SUPPORT_MBO + prBssDesc->fgIsDisallowed = FALSE; +#endif + + if (fgIsProbeResp == FALSE) { + /* Probe response doesn't have TIM IE. Thus, we should + * reset TIM when handling beacon frame only. + */ + prBssDesc->fgTIMPresent = FALSE; + prBssDesc->ucDTIMPeriod = 0; + } + + /* The cPowerLimit should be set as invalid value while BSS description + * is reallocated + */ + if (fgIsNewBssDesc) { + prBssDesc->cPowerLimit = RLM_INVALID_POWER_LIMIT; + DBGLOG(SCN, LOUD, + "LM: New reallocated BSSDesc [" MACSTR "]\n", + MAC2STR(prBssDesc->aucBSSID)); + } + + /* 4 <3.1> Full IE parsing on SW_RFB_T */ + pucIE = prWlanBeaconFrame->aucInfoElem; + /* pucDumpIE = pucIE; */ + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + /* Error handling for disorder IE that IE length is 0*/ + if (IE_ID(pucIE) != ELEM_ID_SSID && IE_LEN(pucIE) == 0) + continue; + switch (IE_ID(pucIE)) { + case ELEM_ID_SSID: + if ((!prIeSsid) && /* NOTE(Kevin): for Atheros IOT #1 */ + (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) { + u_int8_t fgIsHiddenSSID = FALSE; + + ucSSIDChar = '\0'; + + prIeSsid = (struct IE_SSID *) pucIE; + + /* D-Link DWL-900AP+ */ + if (IE_LEN(pucIE) == 0) + fgIsHiddenSSID = TRUE; + /* Cisco AP1230A - + * (IE_LEN(pucIE) == 1) + * && (SSID_IE(pucIE)->aucSSID[0] == '\0') + */ + /* Linksys WRK54G/WL520g - + * (IE_LEN(pucIE) == n) + * && (SSID_IE(pucIE)->aucSSID[0~(n-1)] == '\0') + */ + else { + for (i = 0; i < IE_LEN(pucIE); i++) { + ucSSIDChar + |= SSID_IE(pucIE) + ->aucSSID[i]; + } + + if (!ucSSIDChar) + fgIsHiddenSSID = TRUE; + } + + /* Update SSID to BSS Descriptor only if + * SSID is not hidden. + */ + if (!fgIsHiddenSSID) { + COPY_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, + SSID_IE(pucIE)->aucSSID, + SSID_IE(pucIE)->ucLength); + } else if (fgIsProbeResp) { + /* SSID should be updated + * if it is ProbeResp + */ + kalMemZero(prBssDesc->aucSSID, + sizeof(prBssDesc->aucSSID)); + prBssDesc->ucSSIDLen = 0; + } + + } + 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_SW)) + prIeSupportedRate = SUP_RATES_IOT_IE(pucIE); + break; + + case ELEM_ID_TIM: + if (IE_LEN(pucIE) <= ELEM_MAX_LEN_TIM) { + prBssDesc->fgTIMPresent = TRUE; + 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; + + case ELEM_ID_COUNTRY_INFO: + prCountryIE = (struct IE_COUNTRY *) pucIE; + break; + + 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; + + case ELEM_ID_RSN: + if (rsnParseRsnIE(prAdapter, RSN_IE(pucIE), + &prBssDesc->rRSNInfo)) { + uint8_t i; + + prBssDesc->fgIERSN = TRUE; + prBssDesc->u2RsnCap + = prBssDesc->rRSNInfo.u2RsnCap; + + for (i = 0; i < KAL_AIS_NUM; i++) { + rsnCheckPmkidCache(prAdapter, + prBssDesc, + i); + } + } + break; + + case ELEM_ID_HT_CAP: + { + /* Support AP Selection */ + struct IE_HT_CAP *prHtCap = (struct IE_HT_CAP *)pucIE; + uint8_t ucSpatial = 0; + uint8_t i = 0; + /* end Support AP Selection */ + if (IE_LEN(pucIE) != (sizeof(struct IE_HT_CAP) - 2)) { + DBGLOG(SCN, WARN, + "HT_CAP wrong length(%d)->(%d)\n", + (sizeof(struct IE_HT_CAP) - 2), + IE_LEN(prHtCap)); + break; + } + prBssDesc->fgIsHTPresent = TRUE; + + /* Support AP Selection */ + if (prBssDesc->fgMultiAnttenaAndSTBC) + break; + + for (; i < 4; i++) { + if (prHtCap->rSupMcsSet.aucRxMcsBitmask[i] > 0) + ucSpatial++; + } + + prBssDesc->fgMultiAnttenaAndSTBC = + ((ucSpatial > 1) && + (prHtCap->u2HtCapInfo & HT_CAP_INFO_TX_STBC)); + /* end Support AP Selection */ + + break; + } + case ELEM_ID_HT_OP: + if (IE_LEN(pucIE) != (sizeof(struct IE_HT_OP) - 2)) + break; + + if ((((struct IE_HT_OP *) pucIE)->ucInfo1 + & HT_OP_INFO1_SCO) != CHNL_EXT_RES) { + prBssDesc->eSco = (enum ENUM_CHNL_EXT) + (((struct IE_HT_OP *) pucIE)->ucInfo1 + & HT_OP_INFO1_SCO); + } + break; + case ELEM_ID_VHT_CAP: + scanParseVHTCapIE(pucIE, prBssDesc); + break; + + case ELEM_ID_VHT_OP: + scanParseVHTOpIE(pucIE, prBssDesc); + break; + +#if CFG_SUPPORT_WAPI + case ELEM_ID_WAPI: + if (wapiParseWapiIE(WAPI_IE(pucIE), + &prBssDesc->rIEWAPI)) + prBssDesc->fgIEWAPI = TRUE; + break; +#endif + /* Support AP Selection */ + case ELEM_ID_BSS_LOAD: + { + struct IE_BSS_LOAD *prBssLoad = + (struct IE_BSS_LOAD *)pucIE; + if (IE_LEN(prBssLoad) != + (sizeof(struct IE_BSS_LOAD) - 2)) { + DBGLOG(SCN, WARN, + "HE_CAP IE_LEN err(%d)->(%d)!\n", + (sizeof(struct IE_BSS_LOAD) - 2), + IE_LEN(prBssLoad)); + break; + } + + prBssDesc->u2StaCnt = prBssLoad->u2StaCnt; + prBssDesc->ucChnlUtilization = + prBssLoad->ucChnlUtilizaion; + prBssDesc->u2AvaliableAC = prBssLoad->u2AvailabeAC; + prBssDesc->fgExsitBssLoadIE = TRUE; + break; + } + /* end Support AP Selection */ + + case ELEM_ID_VENDOR: /* ELEM_ID_P2P, ELEM_ID_WMM */ + { + uint8_t ucOuiType; + uint16_t u2SubTypeVersion; + + if (rsnParseCheckForWFAInfoElem(prAdapter, + pucIE, &ucOuiType, &u2SubTypeVersion)) { + if ((ucOuiType == VENDOR_OUI_TYPE_WPA) + && (u2SubTypeVersion + == VERSION_WPA) + && (rsnParseWpaIE(prAdapter, + WPA_IE(pucIE), + &prBssDesc + ->rWPAInfo))) { + prBssDesc->fgIEWPA = TRUE; + } + } + + if (prBssDesc->fgIsVHTPresent == FALSE) + scanCheckEpigramVhtIE(pucIE, prBssDesc); +#if CFG_SUPPORT_PASSPOINT + /* since OSEN is mutual exclusion with RSN, so + * we reuse RSN here + */ + if ((pucIE[1] >= 10) + && (kalMemCmp(pucIE+2, + "\x50\x6f\x9a\x12", 4) == 0) + && (rsnParseOsenIE(prAdapter, + (struct IE_WFA_OSEN *)pucIE, + &prBssDesc->rRSNInfo))) + prBssDesc->fgIEOsen = TRUE; +#endif +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { + if ((p2pFuncParseCheckForP2PInfoElem( + prAdapter, pucIE, &ucOuiType)) + && (ucOuiType + == VENDOR_OUI_TYPE_P2P)) { + prBssDesc->fgIsP2PPresent + = TRUE; + } + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ +#if CFG_SUPPORT_MBO + if (pucIE[1] >= 4 && + kalMemCmp(pucIE + 2, "\x50\x6f\x9a\x16", 4) == 0) { + struct IE_MBO_OCE *mbo = + (struct IE_MBO_OCE *)pucIE; + const uint8_t *disallow = NULL; + + disallow = kalFindIeMatchMask( + MBO_ATTR_ID_ASSOC_DISALLOW, + mbo->aucSubElements, + mbo->ucLength - 4, + NULL, 0, 0, NULL); + if (disallow && disallow[1] >= 1) { + prBssDesc->fgIsDisallowed = TRUE; + DBGLOG(SCN, INFO, + MACSTR " disallow reason %d\n", + MAC2STR(prBssDesc->aucBSSID), + disallow[2]); + } + } +#endif + scanCheckAdaptive11rIE(pucIE, prBssDesc); + break; + } +#if (CFG_SUPPORT_802_11AX == 1) + case ELEM_ID_RESERVED: + if (fgEfuseCtrlAxOn == 1) { +#if (CFG_SUPPORT_HE_ER == 1) + if (IE_ID_EXT(pucIE) == ELEM_EXT_ID_HE_CAP) { + prHeCap = (struct _IE_HE_CAP_T *) pucIE; + if (IE_SIZE(prHeCap) + < (sizeof(struct _IE_HE_CAP_T))) { + DBGLOG(SCN, WARN, + "HE_CAP IE_LEN err(%d)!\n", + IE_LEN(prHeCap)); + break; + } + prBssDesc->fgIsHEPresent = TRUE; + prBssDesc->ucDCMMaxConRx = + HE_GET_PHY_CAP_DCM_MAX_CONSTELLATION_RX( + prHeCap->ucHePhyCap); + } + if (IE_ID_EXT(pucIE) == ELEM_EXT_ID_HE_OP) { + prHeOp = (struct _IE_HE_OP_T *) pucIE; + if (IE_SIZE(prHeOp) + < (sizeof(struct _IE_HE_OP_T))) { + DBGLOG(SCN, WARN, + "HE_OP IE_LEN err(%d)!\n", + IE_LEN(prHeOp)); + break; + } + prBssDesc->fgIsERSUDisable = + HE_IS_ER_SU_DISABLE( + prHeOp->ucHeOpParams); + } + DBGLOG(SCN, INFO, + "ER: BSSID:" MACSTR + " SSID:%s,rx:%x, er:%x\n", + MAC2STR(prBssDesc->aucBSSID), + prBssDesc->aucSSID, + prBssDesc->ucDCMMaxConRx, + prBssDesc->fgIsERSUDisable); +#else + if (IE_ID_EXT(pucIE) == ELEM_EXT_ID_HE_CAP) + prBssDesc->fgIsHEPresent = TRUE; +#endif + } + break; +#endif + case ELEM_ID_PWR_CONSTRAINT: + { + struct IE_POWER_CONSTRAINT *prPwrConstraint = + (struct IE_POWER_CONSTRAINT *)pucIE; + + if (IE_LEN(pucIE) != 1) + break; + ucPowerConstraint = + prPwrConstraint->ucLocalPowerConstraint; + break; + } + case ELEM_ID_RRM_ENABLED_CAP: + if (IE_LEN(pucIE) == 5) { + /* RRM Capability IE is always 5 bytes */ + kalMemZero(prBssDesc->aucRrmCap, + sizeof(prBssDesc->aucRrmCap)); + kalMemCopy(prBssDesc->aucRrmCap, pucIE + 2, + sizeof(prBssDesc->aucRrmCap)); + } + break; +#if (CFG_SUPPORT_802_11V_MBSSID == 1) + case ELEM_ID_MBSSID: + if (MBSSID_IE(pucIE)->ucMaxBSSIDIndicator <= 0 || + MBSSID_IE(pucIE)->ucMaxBSSIDIndicator > 8) { + /* invalid Multiple BSSID ie + * (must in range 1~8) + */ + break; + } + + scanParsingMBSSIDSubelement(prAdapter, + prBssDesc, MBSSID_IE(pucIE)); + break; +#endif + + /* 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 */ + { + void *prRxStatus; + uint8_t ucRxRCPI; + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + /* 4 <4.1> Get TSF comparison result */ + RX_STATUS_GET( + prRxDescOps, + prBssDesc->fgIsLargerTSF, + get_tcl, + prRxStatus); + + /* 4 <4.2> Get Band information */ + prBssDesc->eBand = eHwBand; + + /* 4 <4.2> Get channel and RCPI information */ + RX_STATUS_GET( + prRxDescOps, + ucHwChannelNum, + get_ch_num, + prRxStatus); + + ASSERT(prSwRfb->prRxStatusGroup3); + ucRxRCPI = nicRxGetRcpiValueFromRxv(prAdapter, + RCPI_MODE_MAX, prSwRfb); + if (prBssDesc->eBand == BAND_2G4) { + + /* Update RCPI if in right channel */ + + if (ucIeDsChannelNum >= 1 && ucIeDsChannelNum <= 14) { + + /* Receive Beacon/ProbeResp frame + * from adjacent channel. + */ + if ((ucIeDsChannelNum == ucHwChannelNum) + || (ucRxRCPI > prBssDesc->ucRCPI)) + prBssDesc->ucRCPI = ucRxRCPI; + /* 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) + || (ucRxRCPI > prBssDesc->ucRCPI)) + prBssDesc->ucRCPI = ucRxRCPI; + /* trust channel information brought by IE */ + prBssDesc->ucChannelNum = ucIeHtChannelNum; + } else { + prBssDesc->ucRCPI = ucRxRCPI; + + prBssDesc->ucChannelNum = ucHwChannelNum; + } + } + /* 5G Band */ + else { + if (ucIeHtChannelNum >= 1 && ucIeHtChannelNum < 200) { + /* Receive Beacon/ProbeResp frame + * from adjacent channel. + */ + if ((ucIeHtChannelNum == ucHwChannelNum) + || (ucRxRCPI > prBssDesc->ucRCPI)) + prBssDesc->ucRCPI = ucRxRCPI; + /* trust channel information brought by IE */ + prBssDesc->ucChannelNum = ucIeHtChannelNum; + } else { + /* Always update RCPI */ + prBssDesc->ucRCPI = ucRxRCPI; + + prBssDesc->ucChannelNum = ucHwChannelNum; + } + } + } + + /* 4 <5> Check IE information corret or not */ + if (!rlmDomainIsValidRfSetting(prAdapter, prBssDesc->eBand, + prBssDesc->ucChannelNum, prBssDesc->eSco, + prBssDesc->eChannelWidth, + prBssDesc->ucCenterFreqS1, + prBssDesc->ucCenterFreqS2)) { +#if 0 /* TODO: Remove this */ + /* Dump IE Inforamtion */ + log_dbg(RLM, WARN, "ScanAddToBssDesc IE Information\n"); + log_dbg(RLM, WARN, "IE Length = %d\n", u2IELength); + log_mem8_dbg(RLM, WARN, pucDumpIE, u2IELength); +#endif + + /* Error Handling for Non-predicted IE - Fixed to set 20MHz */ + prBssDesc->eChannelWidth = CW_20_40MHZ; + prBssDesc->ucCenterFreqS1 = 0; + prBssDesc->ucCenterFreqS2 = 0; + prBssDesc->eSco = CHNL_EXT_SCN; + } +#if CFG_SUPPORT_802_11K + if (prCountryIE && prCountryIE->ucLength == + (sizeof(struct IE_COUNTRY) - 2)) { + uint8_t ucRemainLen = prCountryIE->ucLength - 3; + struct COUNTRY_INFO_SUBBAND_TRIPLET *prSubBand = + &prCountryIE->arCountryStr[0]; + const uint8_t ucSubBandSize = + (uint8_t)sizeof(struct COUNTRY_INFO_SUBBAND_TRIPLET); + int8_t cNewPwrLimit = RLM_INVALID_POWER_LIMIT; + + DBGLOG(SCN, LOUD, + "LM: Country IE of BSSID[" MACSTR "] is present\n", + MAC2STR(prBssDesc->aucBSSID)); + + /* Try to find a country subband base on our channel */ + while (ucRemainLen >= ucSubBandSize) { + if (prSubBand->ucFirstChnlNum < 201 && + prBssDesc->ucChannelNum >= + prSubBand->ucFirstChnlNum && + prBssDesc->ucChannelNum <= + (prSubBand->ucFirstChnlNum + + prSubBand->ucNumOfChnl - 1)) + break; + ucRemainLen -= ucSubBandSize; + prSubBand++; + } + /* Found a right country band */ + if (ucRemainLen >= ucSubBandSize) { + cNewPwrLimit = + prSubBand->cMaxTxPwrLv - ucPowerConstraint; + /* Limit Tx power changed */ + if (prBssDesc->cPowerLimit != cNewPwrLimit) { + prBssDesc->cPowerLimit = cNewPwrLimit; + DBGLOG(SCN, TRACE, + "LM: Old TxPwrLimit %d,New: CountryMax %d, Constraint %d\n", + prBssDesc->cPowerLimit, + prSubBand->cMaxTxPwrLv, + ucPowerConstraint); + /* should tell firmware to restrict tx power if + ** connected a BSS + */ + if (prBssDesc->fgIsConnected) { + if (prBssDesc->cPowerLimit != + RLM_INVALID_POWER_LIMIT) + rlmSetMaxTxPwrLimit( + prAdapter, + prBssDesc->cPowerLimit, + 1); + else + rlmSetMaxTxPwrLimit(prAdapter, + 0, 0); + } + } + } else if (prBssDesc->cPowerLimit != RLM_INVALID_POWER_LIMIT) { + DBGLOG(SCN, LOUD, + "LM: The channel of BSSID[" MACSTR + "] doesn't match with country IE, prBssDesc->cPowerLimit=%d\n", + MAC2STR(prBssDesc->aucBSSID), + prBssDesc->cPowerLimit); + prBssDesc->cPowerLimit = RLM_INVALID_POWER_LIMIT; + rlmSetMaxTxPwrLimit(prAdapter, 0, 0); + } + } else if (prBssDesc->cPowerLimit != RLM_INVALID_POWER_LIMIT) { + DBGLOG(SCN, LOUD, + "LM: Country IE of BSSID[" MACSTR + "] isn't present, prBssDesc->cPowerLimit=%d\n", + MAC2STR(prBssDesc->aucBSSID), + prBssDesc->cPowerLimit); + prBssDesc->cPowerLimit = RLM_INVALID_POWER_LIMIT; + rlmSetMaxTxPwrLimit(prAdapter, 0, 0); + } +#endif + + /* 4 <6> PHY type setting */ + prBssDesc->ucPhyTypeSet = 0; + + /* check if support 11n */ + if (prBssDesc->fgIsVHTPresent) + prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_VHT; + + if (prBssDesc->fgIsHTPresent) + prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_HT; + +#if (CFG_SUPPORT_802_11AX == 1) + if (fgEfuseCtrlAxOn == 1) { + if (prBssDesc->fgIsHEPresent) + prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_HE; + } +#endif + + /* if not 11n only */ + if (!(prBssDesc->u2BSSBasicRateSet & RATE_SET_BIT_HT_PHY)) { + if (prBssDesc->eBand == BAND_2G4) { + /* 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 { + prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_OFDM; + } + } + + /* Support AP Selection */ + /* update update-index and reset seen-probe-response */ + if (prBssDesc->u4UpdateIdx != + prAdapter->rWifiVar.rScanInfo.u4ScanUpdateIdx) { + prBssDesc->fgSeenProbeResp = FALSE; + prBssDesc->u4UpdateIdx = + prAdapter->rWifiVar.rScanInfo.u4ScanUpdateIdx; + } + + /* check if it is a probe response frame */ + if (fgIsProbeResp) + prBssDesc->fgSeenProbeResp = TRUE; + /* end Support AP Selection */ + /* 4 <7> Update BSS_DESC_T's Last Update TimeStamp. */ + if (fgIsProbeResp || fgIsValidSsid) + GET_CURRENT_SYSTIME(&prBssDesc->rUpdateTime); + +#if CFG_SUPPORT_802_11K + if (prBssDesc->fgIsConnected) + rrmUpdateBssTimeTsf(prAdapter, prBssDesc); +#endif + + return prBssDesc; +} + +/* clear all ESS scan result */ +void scanInitEssResult(struct ADAPTER *prAdapter) +{ + prAdapter->rWlanInfo.u4ScanResultEssNum = 0; + prAdapter->rWlanInfo.u4ScanDbgTimes1 = 0; + prAdapter->rWlanInfo.u4ScanDbgTimes2 = 0; + prAdapter->rWlanInfo.u4ScanDbgTimes3 = 0; + prAdapter->rWlanInfo.u4ScanDbgTimes4 = 0; + kalMemZero(prAdapter->rWlanInfo.arScanResultEss, + sizeof(prAdapter->rWlanInfo.arScanResultEss)); +} +/* print all ESS into log system once scan done + * it is useful to log that, otherwise, we have no information to + * identify if hardware has seen a specific AP, + * if user complained some AP were not found in scan result list + */ +void scanLogEssResult(struct ADAPTER *prAdapter) +{ + struct ESS_SCAN_RESULT_T *prEssResult + = &prAdapter->rWlanInfo.arScanResultEss[0]; + uint32_t u4ResultNum = prAdapter->rWlanInfo.u4ScanResultEssNum; + uint32_t u4Index = 0; + char *strbuf = NULL, *pos = NULL, *end = NULL; + int slen = 0; + u_int8_t first = TRUE; + + if (u4ResultNum == 0) { + scanlog_dbg(LOG_SCAN_DONE_D2K, INFO, "0 Bss is found, %d, %d, %d, %d\n", + prAdapter->rWlanInfo.u4ScanDbgTimes1, + prAdapter->rWlanInfo.u4ScanDbgTimes2, + prAdapter->rWlanInfo.u4ScanDbgTimes3, + prAdapter->rWlanInfo.u4ScanDbgTimes4); + return; + } + + for (u4Index = 0; u4Index < u4ResultNum; u4Index++) { + if (prEssResult[u4Index].u2SSIDLen > 0) + slen += prEssResult[u4Index].u2SSIDLen + 2; /* _ssid;*/ + } + + slen = min(slen + 1, SCAN_LOG_MSG_MAX_LEN); /* 1 for null end*/ + pos = strbuf = kalMemAlloc(slen, VIR_MEM_TYPE); + if (strbuf == NULL) { + scanlog_dbg(LOG_SCAN_DONE_D2K, INFO, "Can't allocate memory\n"); + return; + } + end = strbuf + slen; + for (u4Index = 0; u4Index < u4ResultNum; u4Index++) { + uint8_t len = prEssResult[u4Index].u2SSIDLen; + char ssid[PARAM_MAX_LEN_SSID + 1] = {0}; + + if (len == 0) + continue; + if (pos + len + 3 > end) { /* _ssid;nul */ + pos = strbuf; + if (first) { + scanlog_dbg(LOG_SCAN_DONE_D2K, INFO, + "Total:%u/%u %s", u4ResultNum, + prAdapter->rWlanInfo.u4ScanResultNum, + strbuf); + first = FALSE; + } else { + scanlog_dbg(LOG_SCAN_DONE_D2K, INFO, + "%s", strbuf); + } + } + kalStrnCpy(ssid, prEssResult[u4Index].aucSSID, sizeof(ssid)); + ssid[sizeof(ssid) - 1] = '\0'; + pos += kalSnprintf(pos, end - pos, " %s;", ssid); + } + if (pos != strbuf) { + if (first) + scanlog_dbg(LOG_SCAN_DONE_D2K, INFO, + "Total:%u/%u %s", u4ResultNum, + prAdapter->rWlanInfo.u4ScanResultNum, strbuf); + else + scanlog_dbg(LOG_SCAN_DONE_D2K, INFO, "%s", strbuf); + } + kalMemFree(strbuf, VIR_MEM_TYPE, slen); +} + +/* record all Scanned ESS, only one BSS was saved for each ESS, and AP who + * is hidden ssid was excluded. + */ +/* maximum we only support record 64 ESSes */ +static void scanAddEssResult(struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc) +{ + struct ESS_SCAN_RESULT_T *prEssResult + = &prAdapter->rWlanInfo.arScanResultEss[0]; + uint32_t u4Index = 0; + + if (prBssDesc->fgIsHiddenSSID) + return; + if (prAdapter->rWlanInfo.u4ScanResultEssNum >= CFG_MAX_NUM_BSS_LIST) + return; + for (; u4Index < prAdapter->rWlanInfo.u4ScanResultEssNum; u4Index++) { + if (EQUAL_SSID(prEssResult[u4Index].aucSSID, + (uint8_t)prEssResult[u4Index].u2SSIDLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen)) + return; + } + + COPY_SSID(prEssResult[u4Index].aucSSID, prEssResult[u4Index].u2SSIDLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + COPY_MAC_ADDR(prEssResult[u4Index].aucBSSID, prBssDesc->aucBSSID); + prAdapter->rWlanInfo.u4ScanResultEssNum++; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t scanAddScanResult(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc, + IN struct SW_RFB *prSwRfb) +{ + struct SCAN_INFO *prScanInfo; + uint8_t aucRatesEx[PARAM_MAX_LEN_RATES_EX]; + struct WLAN_BEACON_FRAME *prWlanBeaconFrame; + uint8_t rMacAddr[PARAM_MAC_ADDR_LEN]; + struct PARAM_SSID rSsid; + enum ENUM_PARAM_NETWORK_TYPE eNetworkType; + struct PARAM_802_11_CONFIG rConfiguration; + enum ENUM_PARAM_OP_MODE eOpMode; + uint8_t ucRateLen = 0; + uint32_t 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) */ + log_dbg(SCN, INFO, "Bss Desc type is P2P\n"); + return WLAN_STATUS_FAILURE; + } + + prWlanBeaconFrame = (struct WLAN_BEACON_FRAME *) prSwRfb->pvHeader; + COPY_MAC_ADDR(rMacAddr, prWlanBeaconFrame->aucBSSID); + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + + rConfiguration.u4Length = sizeof(struct PARAM_802_11_CONFIG); + rConfiguration.u4BeaconPeriod + = (uint32_t) prWlanBeaconFrame->u2BeaconInterval; + rConfiguration.u4ATIMWindow = prBssDesc->u2ATIMWindow; + rConfiguration.u4DSConfig = nicChannelNum2Freq(prBssDesc->ucChannelNum); + rConfiguration.rFHConfig.u4Length + = sizeof(struct PARAM_802_11_CONFIG_FH); + + 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 < ARRAY_SIZE(aucRatesEx); 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; + } + + log_dbg(SCN, LOUD, "ind %s %d %d\n", prBssDesc->aucSSID, + prBssDesc->ucChannelNum, prBssDesc->ucRCPI); + + scanAddEssResult(prAdapter, prBssDesc); + if (prAdapter->rWifiVar.rScanInfo.fgSchedScanning && + test_bit(SUSPEND_FLAG_CLEAR_WHEN_RESUME, + &prAdapter->ulSuspendFlag)) { + uint8_t i = 0; + struct BSS_DESC **pprPendBssDesc + = &prScanInfo->rSchedScanParam. + aprPendingBssDescToInd[0]; + + for (; i < SCN_SSID_MATCH_MAX_NUM; i++) { + if (pprPendBssDesc[i]) + continue; + log_dbg(SCN, INFO, "indicate bss[" + MACSTR + "] before wiphy resume, need to indicate again after wiphy resume\n", + MAC2STR(prBssDesc->aucBSSID)); + pprPendBssDesc[i] = prBssDesc; + break; + } + } + + if (prBssDesc->u2RawLength != 0) { + kalIndicateBssInfo(prAdapter->prGlueInfo, + prBssDesc->aucRawBuf, + prBssDesc->u2RawLength, + prBssDesc->ucChannelNum, + RCPI_TO_dBm(prBssDesc->ucRCPI)); + } + + nicAddScanResult(prAdapter, + rMacAddr, + &rSsid, + prWlanBeaconFrame->u2CapInfo, + RCPI_TO_dBm(prBssDesc->ucRCPI), + eNetworkType, + &rConfiguration, + eOpMode, + aucRatesEx, + prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen, + (uint8_t *) ((unsigned long) (prSwRfb->pvHeader) + + WLAN_MAC_MGMT_HEADER_LEN)); + + return WLAN_STATUS_SUCCESS; + +} /* end of scanAddScanResult() */ + +u_int8_t scanCheckBssIsLegal(IN struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc) +{ + u_int8_t fgAddToScanResult = FALSE; + enum ENUM_BAND eBand; + uint8_t ucChannel; + + ASSERT(prAdapter); + /* check the channel is in the legal doamin */ + if (rlmDomainIsLegalChannel(prAdapter, prBssDesc->eBand, + prBssDesc->ucChannelNum) == TRUE) { + /* check ucChannelNum/eBand for adjacement channel filtering */ + if (cnmAisInfraChannelFixed(prAdapter, + &eBand, &ucChannel) == TRUE && + (eBand != prBssDesc->eBand + || ucChannel != prBssDesc->ucChannelNum)) { + fgAddToScanResult = FALSE; + } else { + fgAddToScanResult = TRUE; + } + } + + return fgAddToScanResult; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t scanProcessBeaconAndProbeResp(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct SCAN_INFO *prScanInfo; + struct BSS_DESC *prBssDesc = (struct BSS_DESC *) NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct WLAN_BEACON_FRAME *prWlanBeaconFrame + = (struct WLAN_BEACON_FRAME *) NULL; +#if CFG_SLT_SUPPORT + struct SLT_INFO *prSltInfo = (struct SLT_INFO *) NULL; +#endif + uint32_t u4Idx = 0; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + /* 4 <0> Ignore invalid Beacon Frame */ + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < + (TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + + CAP_INFO_FIELD_LEN)) { + log_dbg(SCN, ERROR, "Ignore invalid Beacon Frame\n"); + return rStatus; + } + + scanResultLog(prAdapter, prSwRfb); + +#if CFG_SLT_SUPPORT + prSltInfo = &prAdapter->rWifiVar.rSltInfo; + + if (prSltInfo->fgIsDUT) { + log_dbg(P2P, INFO, "\n\rBCN: RX\n"); + prSltInfo->u4BeaconReceiveCnt++; + return WLAN_STATUS_SUCCESS; + } else { + return WLAN_STATUS_SUCCESS; + } +#endif + + prWlanBeaconFrame = (struct WLAN_BEACON_FRAME *) prSwRfb->pvHeader; + + /* 4 <1> Parse and add into BSS_DESC_T */ + prBssDesc = scanAddToBssDesc(prAdapter, prSwRfb); + prAdapter->rWlanInfo.u4ScanDbgTimes1++; + + if (prBssDesc) { + /* Full2Partial: save channel info for later scan */ + if (prScanInfo->fgIsScanForFull2Partial) { + log_dbg(SCN, TRACE, "Full2Partial: set channel=%d\n", + prBssDesc->ucChannelNum); + scanSetBit(prBssDesc->ucChannelNum, + prScanInfo->au4ChannelBitMap, + sizeof(prScanInfo->au4ChannelBitMap)); + } + + for (u4Idx = 0; u4Idx < KAL_AIS_NUM; u4Idx++) { + struct CONNECTION_SETTINGS *prConnSettings = + aisGetConnSettings(prAdapter, u4Idx); + struct BSS_INFO *prAisBssInfo = + aisGetAisBssInfo(prAdapter, u4Idx); + + /* 4 <1.1> Beacon Change Detection for Connected BSS */ + if ((prAisBssInfo != NULL) && + (prAisBssInfo->eConnectionState == + 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)) { + +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE + if (rsnCheckSecurityModeChanged(prAdapter, + prAisBssInfo, prBssDesc) +#if CFG_SUPPORT_WAPI + || (aisGetWapiMode(prAdapter, + u4Idx) && + !wapiPerformPolicySelection(prAdapter, + prBssDesc, u4Idx)) +#endif + ) { + + log_dbg(SCN, INFO, "Beacon security mode change detected\n"); + log_mem8_dbg(SCN, INFO, + prSwRfb->pvHeader, + prSwRfb->u2PacketLen); + if (!prConnSettings + ->fgSecModeChangeStartTimer) { + cnmTimerStartTimer(prAdapter, + aisGetSecModeChangeTimer( + prAdapter, + u4Idx), + SEC_TO_MSEC(3)); + prConnSettings + ->fgSecModeChangeStartTimer + = TRUE; + } + } else { + if (prConnSettings->fgSecModeChangeStartTimer) { + cnmTimerStopTimer(prAdapter, + aisGetSecModeChangeTimer( + prAdapter, + u4Idx)); + prConnSettings + ->fgSecModeChangeStartTimer + = FALSE; + } + } +#endif + } + /* 4 <1.1> Update AIS_BSS_INFO */ + if ((prAisBssInfo != NULL) && + ((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE && + prConnSettings->eOPMode != NET_TYPE_IBSS) + || (prBssDesc->eBSSType == BSS_TYPE_IBSS + && prConnSettings->eOPMode != NET_TYPE_INFRA))) { + if (prAisBssInfo->eConnectionState + == MEDIA_STATE_CONNECTED) { + + /* *not* checking prBssDesc->fgIsConnected + * anymore, due to Linksys AP uses " " as + * hidden SSID, and would have different + * BSS descriptor + */ + log_dbg(SCN, TRACE, "DTIMPeriod[%u] Present[%u] BSSID[" + MACSTR "]\n", + prAisBssInfo->ucDTIMPeriod, + prAisBssInfo->fgTIMPresent, + MAC2STR(prBssDesc->aucBSSID)); + if ((!prAisBssInfo->ucDTIMPeriod) && + prAisBssInfo->fgTIMPresent && + EQUAL_MAC_ADDR(prBssDesc->aucBSSID, + prAisBssInfo->aucBSSID) && + (prAisBssInfo->eCurrentOPMode + == OP_MODE_INFRASTRUCTURE) && + ((prWlanBeaconFrame->u2FrameCtrl + & MASK_FRAME_TYPE) + == MAC_FRAME_BEACON)) { + prAisBssInfo->ucDTIMPeriod + = prBssDesc->ucDTIMPeriod; + prAisBssInfo->fgTIMPresent + = prBssDesc->fgTIMPresent; + + /* Handle No TIM IE information case */ + if (!prAisBssInfo->fgTIMPresent) { + enum PARAM_POWER_MODE ePwrMode + = Param_PowerModeCAM; + + log_dbg(SCN, WARN, "IE TIM absence, set to CAM mode!\n"); + nicConfigPowerSaveProfile( + prAdapter, + prAisBssInfo-> + ucBssIndex, ePwrMode, + FALSE, + PS_CALLER_NO_TIM); + } + /* sync with firmware for + * beacon information + */ + nicPmIndicateBssConnected(prAdapter, + prAisBssInfo->ucBssIndex); + } + } +#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)) { + + ASSERT(prSwRfb->prRxStatusGroup3); + + ibssProcessMatchedBeacon(prAdapter, + prAisBssInfo, + prBssDesc, + nicRxGetRcpiValueFromRxv( + prAdapter, + RCPI_MODE_MAX, + prSwRfb)); + } +#endif /* CFG_SUPPORT_ADHOC */ + } + } + + rlmProcessBcn(prAdapter, + prSwRfb, + ((struct WLAN_BEACON_FRAME *) (prSwRfb->pvHeader)) + ->aucInfoElem, + (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - + (uint16_t) (OFFSET_OF(struct WLAN_BEACON_FRAME_BODY, + aucInfoElem[0]))); + + mqmProcessBcn(prAdapter, + prSwRfb, + ((struct WLAN_BEACON_FRAME *) (prSwRfb->pvHeader)) + ->aucInfoElem, + (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - + (uint16_t) (OFFSET_OF(struct WLAN_BEACON_FRAME_BODY, + aucInfoElem[0]))); + + prAdapter->rWlanInfo.u4ScanDbgTimes2++; + + /* 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 */ + prAdapter->rWlanInfo.u4ScanDbgTimes3++; + if (prScanInfo->eCurrentState == SCAN_STATE_SCANNING + || prScanInfo->fgSchedScanning) { + u_int8_t fgAddToScanResult = FALSE; + + fgAddToScanResult + = scanCheckBssIsLegal(prAdapter, + prBssDesc); + prAdapter->rWlanInfo.u4ScanDbgTimes4++; + + 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 + */ +/*----------------------------------------------------------------------------*/ +struct BSS_DESC *scanSearchBssDescByPolicy( + IN struct ADAPTER *prAdapter, IN uint8_t ucBssIndex) +{ + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_INFO *prBssInfo; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecBssInfo; + struct SCAN_INFO *prScanInfo; + + struct LINK *prBSSDescList; + + struct BSS_DESC *prBssDesc = (struct BSS_DESC *) NULL; + struct BSS_DESC *prPrimaryBssDesc = (struct BSS_DESC *) NULL; + struct BSS_DESC *prCandidateBssDesc = (struct BSS_DESC *) NULL; + + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + struct STA_RECORD *prPrimaryStaRec; + struct STA_RECORD *prCandidateStaRec = (struct STA_RECORD *) NULL; + + OS_SYSTIME rCurrentTime; + + /* The first one reach the check point will be our candidate */ + u_int8_t fgIsFindFirst = (u_int8_t) FALSE; + + u_int8_t fgIsFindBestRSSI = (u_int8_t) FALSE; + u_int8_t fgIsFindBestEncryptionLevel = (u_int8_t) FALSE; + /* u_int8_t fgIsFindMinChannelLoad = (u_int8_t) FALSE; */ + + /* TODO(Kevin): Support Min Channel Load */ + /* uint8_t aucChannelLoad[CHANNEL_NUM] = {0}; */ + + u_int8_t fgIsFixedChannel = (u_int8_t) FALSE; + enum ENUM_BAND eBand = BAND_2G4; + uint8_t ucChannel = 0; + uint32_t u4ScnAdhocBssDescTimeout = 0; +#if CFG_SUPPORT_NCHO + uint8_t ucRCPIStep = ROAMING_NO_SWING_RCPI_STEP; +#endif + + ASSERT(prAdapter); + + prConnSettings = + aisGetConnSettings(prAdapter, ucBssIndex); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + prAisSpecBssInfo = + aisGetAisSpecBssInfo(prAdapter, ucBssIndex); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + + GET_CURRENT_SYSTIME(&rCurrentTime); + + /* check for fixed channel operation */ + if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) { +#if CFG_SUPPORT_CHNL_CONFLICT_REVISE + fgIsFixedChannel = + cnmAisDetectP2PChannel(prAdapter, &eBand, &ucChannel); +#else + fgIsFixedChannel = + cnmAisInfraChannelFixed(prAdapter, &eBand, &ucChannel); +#endif + } else + fgIsFixedChannel = FALSE; + +#if DBG + if (prConnSettings->ucSSIDLen < ELEM_MAX_LEN_SSID) + prConnSettings->aucSSID[prConnSettings->ucSSIDLen] = '\0'; +#endif + + log_dbg(SCN, INFO, "SEARCH: Bss Num: %d, Look for SSID: %s, " + MACSTR " Band=%d, channel=%d\n", + (uint32_t) prBSSDescList->u4NumElem, + HIDE(prConnSettings->aucSSID), + MAC2STR(prConnSettings->aucBSSID), eBand, ucChannel); + + /* 4 <1> The outer loop to search for a candidate. */ + LINK_FOR_EACH_ENTRY( + prBssDesc, prBSSDescList, rLinkEntry, struct BSS_DESC) { + + /* TODO(Kevin): Update Minimum Channel Load Information here */ + +#if 0 + log_dbg(SCN, INFO, "SEARCH: [" MACSTR "], SSID:%s\n", + MAC2STR(prBssDesc->aucBSSID), prBssDesc->aucSSID); +#endif + + /* 4 <2> Check PHY Type and attributes */ + /* 4 <2.1> Check Unsupported BSS PHY Type */ + if (!(prBssDesc->ucPhyTypeSet + & (prAdapter->rWifiVar.ucAvailablePhyTypeSet))) { + log_dbg(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) { + log_dbg(SCN, LOUD, "SEARCH: Ignore Unknown Bss Basic Rate\n"); + continue; + } + /* 4 <2.3> Check if fixed operation cases should be aware */ + if (fgIsFixedChannel == TRUE + && (prBssDesc->eBand != eBand + || prBssDesc->ucChannelNum != ucChannel)) { + log_dbg(SCN, LOUD, "SEARCH: Ignore BssBand[%d] != FixBand[%d] or BssCH[%d] != FixCH[%d]\n", + 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) { + log_dbg(SCN, LOUD, "SEARCH: Ignore illegal CH Band[%d] CH[%d]\n", + prBssDesc->eBand, prBssDesc->ucChannelNum); + continue; + } + /* 4 <2.5> Check if this BSS_DESC_T is stale */ + u4ScnAdhocBssDescTimeout = SCN_BSS_DESC_STALE_SEC; +#if CFG_ENABLE_WIFI_DIRECT +#if CFG_SUPPORT_WFD + if (prAdapter->rWifiVar.rWfdConfigureSettings.ucWfdEnable) + u4ScnAdhocBssDescTimeout = SCN_BSS_DESC_STALE_SEC_WFD; +#endif +#endif + if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, + SEC_TO_SYSTIME(u4ScnAdhocBssDescTimeout))) { + log_dbg(SCN, LOUD, "SEARCH: Ignore stale Bss, CurrTime[%u] BssUpdateTime[%u]\n", + rCurrentTime, prBssDesc->rUpdateTime); + continue; + } + /* 4 <3> Check if reach the excessive join retry limit */ + /* NOTE(Kevin): STA_RECORD_T is recorded by TA. */ + prStaRec = cnmGetStaRecByAddress( + prAdapter, ucBssIndex, prBssDesc->aucSrcAddr); + + /* 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 + && prStaRec->u2ReasonCode != REASON_CODE_RESERVED) { + log_dbg(SCN, INFO, "SEARCH: Ignore BSS with previous Reason Code = %d\n", + prStaRec->u2ReasonCode); + continue; + } else +#endif + if (prStaRec + && 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; + } + + log_dbg(SCN, INFO, "SEARCH:Try to join BSS again,Status Code=%u(Curr=%u/Last Join=%u)\n", + prStaRec->u2StatusCode, rCurrentTime, + prStaRec->rLastJoinTime); + } else { + log_dbg(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 (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) { + enum ENUM_BSS_TYPE eBSSType = + prBssDesc->eBSSType; + enum ENUM_PARAM_OP_MODE eOPMode = + prConnSettings->eOPMode; + /* 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 (eOPMode == NET_TYPE_INFRA + && eBSSType != BSS_TYPE_INFRASTRUCTURE) { + log_dbg(SCN, INFO, "SEARCH: Ignore eBSSType = IBSS\n"); + continue; + } + if ((eOPMode == NET_TYPE_IBSS + || eOPMode == NET_TYPE_DEDICATED_IBSS) + && eBSSType != BSS_TYPE_IBSS) { + log_dbg(SCN, INFO, "SEARCH: Ignore eBSSType = INFRASTRUCTURE\n"); + continue; + } + /* 4 <4.2> Check AP's BSSID if OID_802_11_BSSID has been + * set. + */ + if (prConnSettings->fgIsConnByBssidIssued && + eBSSType == BSS_TYPE_INFRASTRUCTURE) { + if (UNEQUAL_MAC_ADDR(prConnSettings->aucBSSID, + prBssDesc->aucBSSID)) { + log_dbg(SCN, TRACE, "SEARCH: Ignore due to BSSID was not matched!\n"); + continue; + } + } +#if CFG_SUPPORT_ADHOC + /* 4 <4.3> Check for AdHoc Mode */ + if (eBSSType == BSS_TYPE_IBSS) { + OS_SYSTIME rCurrentTime; + + u4ScnAdhocBssDescTimeout = + SCN_ADHOC_BSS_DESC_TIMEOUT_SEC; + + /* 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 CFG_ENABLE_WIFI_DIRECT +#if CFG_SUPPORT_WFD + if (prAdapter->rWifiVar + .rWfdConfigureSettings.ucWfdEnable) { +#define __LOCAL_VAR__ SCN_ADHOC_BSS_DESC_TIMEOUT_SEC_WFD + u4ScnAdhocBssDescTimeout + = __LOCAL_VAR__; +#undef __LOCAL_VAR__ + } +#endif +#endif + if (CHECK_FOR_TIMEOUT(rCurrentTime, + prBssDesc->rUpdateTime, + SEC_TO_SYSTIME( + u4ScnAdhocBssDescTimeout))) { + log_dbg(SCN, LOUD, "SEARCH: Now(%u) Skip old record of BSS Descriptor(%u) - BSSID:[" + MACSTR "]\n", + rCurrentTime, + prBssDesc->rUpdateTime, + MAC2STR(prBssDesc->aucBSSID)); + continue; + } + + /* 4 <4.3.2> Check Peer's capability */ + if (ibssCheckCapabilityForAdHocMode(prAdapter, + prBssDesc, ucBssIndex) + == WLAN_STATUS_FAILURE) { + + log_dbg(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)) { + + log_dbg(SCN, LOUD, "SEARCH: prBssDesc->fgIsLargerTSF = %d\n", + prBssDesc->fgIsLargerTSF); + + if (!prBssDesc->fgIsLargerTSF) { + log_dbg(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) + )){ + log_dbg(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))) { + log_dbg(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) { + + log_dbg(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); + + log_dbg(SCAN, TRACE, "\n\nCurrent TSF : %08lx-%08lx\n\n", + rCurrentTsf.u.HighPart, + rCurrentTsf.u.LowPart); + } + + if (rCurrentTsf.QuadPart + > prPrimaryBssDesc + ->u8TimeStamp.QuadPart) { + log_dbg(SCAN, TRACE, "Ignore BSS DESC MAC: [" + MACSTR"], Current BSSID: [" + MACSTR "].\n", + MAC2STR(prPrimaryBssDesc + ->aucBSSID), + MAC2STR(prBssInfo->aucBSSID)); + + log_dbg(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 = (struct BSS_DESC *) 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; + + log_dbg(SCN, LOUD, "SEARCH: Found BSS by SSID, [" + MACSTR "], SSID:%s\n", + MAC2STR(prBssDesc->aucBSSID), + HIDE(prBssDesc->aucSSID)); + } + 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 struct BSS_DESC + * 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)) { + + /* Make sure to match with SSID if supplied. + * Some old dualband APs share a single BSSID + * among different BSSes. + */ + if ((prBssDesc->ucSSIDLen > 0 && + prConnSettings->ucSSIDLen > 0 && + EQUAL_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, + prConnSettings->aucSSID, + prConnSettings->ucSSIDLen)) || + prConnSettings->ucSSIDLen == 0) { + log_dbg(SCN, LOUD, "%s: BSSID/SSID pair matched\n", + __func__); + prPrimaryBssDesc = prBssDesc; + } else + log_dbg(SCN, ERROR, "%s: BSSID/SSID pair unmatched (" + MACSTR + ")\n", __func__, + MAC2STR(prBssDesc->aucBSSID)); + } + 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 (aisGetWapiMode(prAdapter, ucBssIndex)) { + if (wapiPerformPolicySelection(prAdapter, + prPrimaryBssDesc, ucBssIndex)) { + fgIsFindFirst = TRUE; + } else { + /* Can't pass the Encryption Status + * Check, get next one + */ + log_dbg(RSN, INFO, "Ignore BSS can't pass WAPI policy selection\n"); + continue; + } + } else +#endif + if (rsnPerformPolicySelection(prAdapter, + prPrimaryBssDesc, ucBssIndex)) { + if (prAisSpecBssInfo->fgCounterMeasure) { + log_dbg(RSN, INFO, "Skip while at counter measure period!!!\n"); + continue; + } + + if (prPrimaryBssDesc->ucEncLevel > 0) { + fgIsFindBestEncryptionLevel = TRUE; + + fgIsFindFirst = FALSE; + } + } else { + /* Can't pass the Encryption Status Check, + * get next one + */ + log_dbg(RSN, INFO, "Ignore BSS can't pass Encryption Status Check\n"); + continue; + } + } 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 { + /* 4 <6D> Condition - Visible SSID win Hidden SSID. */ + if (prCandidateBssDesc->fgIsHiddenSSID) { + if (!prPrimaryBssDesc->fgIsHiddenSSID) { + /* The non Hidden SSID win. */ + prCandidateBssDesc = prPrimaryBssDesc; + + 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. + */ + log_dbg(SCN, TRACE, "Candidate [" + MACSTR + "]: uint8_t = %d, joinFailCnt=%d, Primary [" + MACSTR "]: uint8_t = %d, joinFailCnt=%d\n", + MAC2STR(prCandidateBssDesc->aucBSSID), + prCandidateBssDesc->ucRCPI, + prCandidateBssDesc->ucJoinFailureCount, + MAC2STR(prPrimaryBssDesc->aucBSSID), + prPrimaryBssDesc->ucRCPI, + prPrimaryBssDesc->ucJoinFailureCount); + + ASSERT(!(prCandidateBssDesc->fgIsConnected + && prPrimaryBssDesc->fgIsConnected)); + if (prPrimaryBssDesc->ucJoinFailureCount + > SCN_BSS_JOIN_FAIL_THRESOLD) { + /* give a chance to do join if join + * fail before + * SCN_BSS_DECRASE_JOIN_FAIL_CNT_SEC + * seconds + */ +#define __LOCAL_VAR__ \ +SCN_BSS_JOIN_FAIL_CNT_RESET_SEC + if (CHECK_FOR_TIMEOUT(rCurrentTime, + prBssDesc->rJoinFailTime, + SEC_TO_SYSTIME( + __LOCAL_VAR__))) { +#define __LOCAL_VAR2__ \ +SCN_BSS_JOIN_FAIL_RESET_STEP + + prBssDesc->ucJoinFailureCount + -= __LOCAL_VAR2__; +#undef __LOCAL_VAR2__ + + log_dbg(AIS, INFO, "decrease join fail count for Bss " + MACSTR + " to %u, timeout second %d\n", + MAC2STR( + prBssDesc->aucBSSID), + prBssDesc + ->ucJoinFailureCount, + __LOCAL_VAR__); + } +#undef __LOCAL_VAR__ + } + /* NOTE: To prevent SWING, we do roaming only + * if target AP has at least 5dBm larger + * than us. + */ +#if CFG_SUPPORT_NCHO + if (prAdapter->rNchoInfo.fgNCHOEnabled + == TRUE) { + ucRCPIStep = 2 * prAdapter + ->rNchoInfo.i4RoamDelta; + } +#endif + if (prCandidateBssDesc->fgIsConnected) { + if ((prCandidateBssDesc->ucRCPI + + ROAMING_NO_SWING_RCPI_STEP <= + prPrimaryBssDesc->ucRCPI) + && prPrimaryBssDesc + ->ucJoinFailureCount + <= SCN_BSS_JOIN_FAIL_THRESOLD) { + + prCandidateBssDesc + = prPrimaryBssDesc; + prCandidateStaRec + = prPrimaryStaRec; + continue; + } + } else if (prPrimaryBssDesc->fgIsConnected) { + if ((prCandidateBssDesc->ucRCPI < + prPrimaryBssDesc->ucRCPI + + ROAMING_NO_SWING_RCPI_STEP) + || (prCandidateBssDesc + ->ucJoinFailureCount + > SCN_BSS_JOIN_FAIL_THRESOLD)) { + + prCandidateBssDesc + = prPrimaryBssDesc; + prCandidateStaRec + = prPrimaryStaRec; + continue; + } + } else if (prPrimaryBssDesc + ->ucJoinFailureCount + > SCN_BSS_JOIN_FAIL_THRESOLD) + continue; + else if (prCandidateBssDesc + ->ucJoinFailureCount + > SCN_BSS_JOIN_FAIL_THRESOLD || + prCandidateBssDesc->ucRCPI + < prPrimaryBssDesc->ucRCPI) { + + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } +#if 0 + /* If reach here, that means they have the same + * Encryption Score, and both RSSI value are close too. + */ + /* 4 <6F> Seek the minimum Channel Load for less + * interference. + */ + if (fgIsFindMinChannelLoad) { + /* ToDo:: Nothing */ + /* TODO(Kevin): Check which one has minimum + * channel load in its channel + */ + } +#endif + } + } + + return prCandidateBssDesc; + +} /* end of scanSearchBssDescByPolicy() */ + +void scanReportBss2Cfg80211(IN struct ADAPTER *prAdapter, + IN enum ENUM_BSS_TYPE eBSSType, + IN struct BSS_DESC *SpecificprBssDesc) +{ + struct SCAN_INFO *prScanInfo = NULL; + struct LINK *prBSSDescList = NULL; + struct BSS_DESC *prBssDesc = NULL; + struct RF_CHANNEL_INFO rChannelInfo; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prBSSDescList = &prScanInfo->rBSSDescList; + + log_dbg(SCN, TRACE, "eBSSType: %d\n", eBSSType); + + if (SpecificprBssDesc) { + { + /* check BSSID is legal channel */ + if (!scanCheckBssIsLegal(prAdapter, + SpecificprBssDesc)) { + log_dbg(SCN, TRACE, + "Remove specific SSID[%s %d]\n", + HIDE(SpecificprBssDesc->aucSSID), + SpecificprBssDesc->ucChannelNum); + return; + } + + log_dbg(SCN, TRACE, "Report specific SSID[%s]\n", + SpecificprBssDesc->aucSSID); + + if (eBSSType == BSS_TYPE_INFRASTRUCTURE) { + kalIndicateBssInfo( + prAdapter->prGlueInfo, + (uint8_t *) + SpecificprBssDesc->aucRawBuf, + SpecificprBssDesc->u2RawLength, + SpecificprBssDesc->ucChannelNum, + RCPI_TO_dBm( + SpecificprBssDesc->ucRCPI)); + } else { + + rChannelInfo.ucChannelNum + = SpecificprBssDesc->ucChannelNum; + rChannelInfo.eBand = SpecificprBssDesc->eBand; + kalP2PIndicateBssInfo(prAdapter->prGlueInfo, + (uint8_t *) + SpecificprBssDesc->aucRawBuf, + SpecificprBssDesc->u2RawLength, + &rChannelInfo, + RCPI_TO_dBm(SpecificprBssDesc->ucRCPI)); + + } + +#if CFG_ENABLE_WIFI_DIRECT + SpecificprBssDesc->fgIsP2PReport = FALSE; +#endif + } + } else { + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, + rLinkEntry, struct BSS_DESC) { + /* check BSSID is legal channel */ + if (!scanCheckBssIsLegal(prAdapter, prBssDesc)) { + log_dbg(SCN, TRACE, "Remove SSID[%s %d]\n", + HIDE(prBssDesc->aucSSID), + prBssDesc->ucChannelNum); + continue; + } + + if ((prBssDesc->eBSSType == eBSSType) +#if CFG_ENABLE_WIFI_DIRECT + || ((eBSSType == BSS_TYPE_P2P_DEVICE) + && (prBssDesc->fgIsP2PReport == TRUE)) +#endif + ) { +#define TEMP_LOG_TEMPLATE "Report " MACSTR " SSID[%s %u] eBSSType[%d] " \ + "u2RawLength[%d] fgIsP2PReport[%d]\n" + log_dbg(SCN, TRACE, TEMP_LOG_TEMPLATE, + MAC2STR(prBssDesc->aucBSSID), + HIDE(prBssDesc->aucSSID), + prBssDesc->ucChannelNum, + prBssDesc->eBSSType, + prBssDesc->u2RawLength, + prBssDesc->fgIsP2PReport); +#undef TEMP_LOG_TEMPLATE + + if (eBSSType == BSS_TYPE_INFRASTRUCTURE) { + if (prBssDesc->u2RawLength != 0) { + kalIndicateBssInfo( + prAdapter->prGlueInfo, + (uint8_t *) + prBssDesc->aucRawBuf, + prBssDesc->u2RawLength, + prBssDesc->ucChannelNum, + RCPI_TO_dBm( + prBssDesc->ucRCPI)); + } + kalMemZero(prBssDesc->aucRawBuf, + CFG_RAW_BUFFER_SIZE); + prBssDesc->u2RawLength = 0; +#if CFG_ENABLE_WIFI_DIRECT + prBssDesc->fgIsP2PReport = FALSE; +#endif + } else { +#if CFG_ENABLE_WIFI_DIRECT + if ((prBssDesc->fgIsP2PReport == TRUE) + && prBssDesc->u2RawLength != 0) { +#endif + rChannelInfo.ucChannelNum + = prBssDesc + ->ucChannelNum; + rChannelInfo.eBand + = prBssDesc->eBand; + + kalP2PIndicateBssInfo( + prAdapter->prGlueInfo, + (uint8_t *) + prBssDesc->aucRawBuf, + prBssDesc->u2RawLength, + &rChannelInfo, + RCPI_TO_dBm( + prBssDesc->ucRCPI)); + + /* do not clear it then we can + * pass the bss in + * Specific report + */ +#if 0 /* TODO: Remove this */ + kalMemZero(prBssDesc->aucRawBuf, + CFG_RAW_BUFFER_SIZE); +#endif + + /* the BSS entry will not be + * cleared after scan done. + * So if we dont receive the BSS + * in next scan, we cannot pass + * it. We use u2RawLength for + * the purpose. + */ +#if 0 + prBssDesc->u2RawLength = 0; +#endif + +#if CFG_ENABLE_WIFI_DIRECT + prBssDesc->fgIsP2PReport + = FALSE; + } +#endif + } + } + + } + p2pFunCalAcsChnScores(prAdapter); + } + +} + +#if CFG_SUPPORT_PASSPOINT +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +struct BSS_DESC *scanSearchBssDescByBssidAndLatestUpdateTime( + IN struct ADAPTER *prAdapter, IN uint8_t aucBSSID[]) +{ + struct SCAN_INFO *prScanInfo; + struct LINK *prBSSDescList; + struct BSS_DESC *prBssDesc; + struct BSS_DESC *prDstBssDesc = (struct BSS_DESC *) NULL; + OS_SYSTIME rLatestUpdateTime = 0; + + ASSERT(prAdapter); + ASSERT(aucBSSID); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prBSSDescList = &prScanInfo->rBSSDescList; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY( + prBssDesc, prBSSDescList, rLinkEntry, struct BSS_DESC) { + + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { + if (!rLatestUpdateTime + || CHECK_FOR_EXPIRATION(prBssDesc->rUpdateTime, + rLatestUpdateTime)) { + prDstBssDesc = prBssDesc; + COPY_SYSTIME(rLatestUpdateTime, + prBssDesc->rUpdateTime); + } + } + } + + return prDstBssDesc; + +} /* end of scanSearchBssDescByBssid() */ + +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_AGPS_ASSIST +void scanReportScanResultToAgps(struct ADAPTER *prAdapter) +{ + struct LINK *prBSSDescList = + &prAdapter->rWifiVar.rScanInfo.rBSSDescList; + struct BSS_DESC *prBssDesc = NULL; + struct AGPS_AP_LIST *prAgpsApList = + kalMemAlloc(sizeof(struct AGPS_AP_LIST), VIR_MEM_TYPE); + struct AGPS_AP_INFO *prAgpsInfo = &prAgpsApList->arApInfo[0]; + struct SCAN_INFO *prScanInfo = &prAdapter->rWifiVar.rScanInfo; + uint8_t ucIndex = 0; + + LINK_FOR_EACH_ENTRY( + prBssDesc, prBSSDescList, rLinkEntry, struct BSS_DESC) { + + if (prBssDesc->rUpdateTime < prScanInfo->rLastScanCompletedTime) + continue; + COPY_MAC_ADDR(prAgpsInfo->aucBSSID, prBssDesc->aucBSSID); + prAgpsInfo->ePhyType = AGPS_PHY_G; + prAgpsInfo->u2Channel = prBssDesc->ucChannelNum; + prAgpsInfo->i2ApRssi = RCPI_TO_dBm(prBssDesc->ucRCPI); + prAgpsInfo++; + ucIndex++; + if (ucIndex == SCN_AGPS_AP_LIST_MAX_NUM) + break; + } + prAgpsApList->ucNum = ucIndex; + GET_CURRENT_SYSTIME(&prScanInfo->rLastScanCompletedTime); + /* log_dbg(SCN, INFO, ("num of scan list:%d\n", ucIndex)); */ + kalIndicateAgpsNotify(prAdapter, AGPS_EVENT_WLAN_AP_LIST, + (uint8_t *) prAgpsApList, sizeof(struct AGPS_AP_LIST)); + kalMemFree(prAgpsApList, VIR_MEM_TYPE, sizeof(struct AGPS_AP_LIST)); +} +#endif /* CFG_SUPPORT_AGPS_ASSIST */ + +void scanReqLog(struct CMD_SCAN_REQ_V2 *prCmdScanReq) +{ + struct CMD_SCAN_REQ_V2 *req = prCmdScanReq; + char *strbuf = NULL, *pos = NULL, *end = NULL; + uint32_t slen = 0; + int i, j; + int snum[2] = {req->ucSSIDNum, req->ucSSIDExtNum}; + struct PARAM_SSID *slist[2] = {req->arSSID, req->arSSIDExtend}; + int cnum[2] = {req->ucChannelListNum, req->ucChannelListExtNum}; + struct CHANNEL_INFO *clist[2] = { + req->arChannelList, req->arChannelListExtend}; + + /* ssid and space */ + for (i = 0; i < 2; ++i) + for (j = 0; j < snum[i]; ++j) + slen += slist[i][j].u4SsidLen + 1; + + /* The length should be added 6 + 10 + 4 + 8 + 1 for the format + * ",Ssid:", * ",Ext ssid:", ",Ch:", ",Ext Ch:" and null byte. + */ + slen += 29 + 4 * (req->ucChannelListNum + req->ucChannelListExtNum); + pos = strbuf = kalMemAlloc(slen, VIR_MEM_TYPE); + if (strbuf == NULL) { + scanlog_dbg(LOG_SCAN_REQ_K2D, INFO, "Can't allocate memory\n"); + return; + } + end = strbuf + slen; + + for (i = 0; i < 2; ++i) { + if (snum[i] > 0) { + pos += kalSnprintf(pos, end - pos, "%s", + i == 0 ? ",Ssid:" : ",Ext Ssid:"); + for (j = 0; j < snum[i]; ++j) { + char ssid[PARAM_MAX_LEN_SSID + 1] = {0}; + + kalStrnCpy(ssid, + slist[i][j].aucSsid, sizeof(ssid)); + ssid[sizeof(ssid) - 1] = '\0'; + pos += kalSnprintf(pos, end - pos, " %s", ssid); + } + } + } + + for (i = 0; i < 2; ++i) { + if (cnum[i] > 0) { + pos += kalSnprintf(pos, end - pos, "%s", + i == 0 ? ",Ch:" : ",Ext Ch:"); + for (j = 0; j < cnum[i]; ++j) + pos += kalSnprintf(pos, end - pos, " %u", + clist[i][j].ucChannelNum % 1000); + } + } +#define TEMP_LOG_TEMPLATE \ + "ScanReqV2: ScanType=%d,BSS=%u,SSIDType=%d,Num=%u,Ext=%u," \ + "ChannelType=%d,Num=%d,Ext=%u,Seq=%u,Ver=%u,Dw=%u,Min=%u," \ + "Func=0x%X,Mac="MACSTR",BSSID="MACSTR",%s\n" + scanlog_dbg(LOG_SCAN_REQ_D2F, INFO, TEMP_LOG_TEMPLATE, + prCmdScanReq->ucScanType, + prCmdScanReq->ucBssIndex, + prCmdScanReq->ucSSIDType, + prCmdScanReq->ucSSIDNum, + prCmdScanReq->ucSSIDExtNum, + prCmdScanReq->ucChannelType, + prCmdScanReq->ucChannelListNum, + prCmdScanReq->ucChannelListExtNum, + prCmdScanReq->ucSeqNum, prCmdScanReq->auVersion[0], + prCmdScanReq->u2ChannelDwellTime, + prCmdScanReq->u2ChannelMinDwellTime, + prCmdScanReq->ucScnFuncMask, + MAC2STR(prCmdScanReq->aucRandomMac), + MAC2STR(prCmdScanReq->aucBSSID), + strbuf != pos ? strbuf : ""); +#undef TEMP_LOG_TEMPLATE + kalMemFree(strbuf, VIR_MEM_TYPE, slen); +} + +void scanResultLog(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb) +{ + struct WLAN_BEACON_FRAME *pFrame = + (struct WLAN_BEACON_FRAME *) prSwRfb->pvHeader; + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BSSLIST_FW); + scanLogCacheAddBSS( + &(prAdapter->rWifiVar.rScanInfo.rScanLogCache.rBSSListFW), + prAdapter->rWifiVar.rScanInfo.rScanLogCache.arBSSListBufFW, + LOG_SCAN_RESULT_F2D, + pFrame->aucBSSID, + pFrame->u2SeqCtrl); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BSSLIST_FW); +} + +void scanLogCacheAddBSS(struct LINK *prList, + struct SCAN_LOG_ELEM_BSS *prListBuf, + enum ENUM_SCAN_LOG_PREFIX prefix, + uint8_t bssId[], uint16_t seq) +{ + struct SCAN_LOG_ELEM_BSS *pSavedBss = NULL; + struct SCAN_LOG_ELEM_BSS *pBss = NULL; + + if (LINK_IS_INVALID(prList)) { + LINK_INITIALIZE(prList); + } + + LINK_FOR_EACH_ENTRY(pSavedBss, prList, + rLinkEntry, struct SCAN_LOG_ELEM_BSS) { + if (pSavedBss && bssId) { + if (EQUAL_MAC_ADDR(pSavedBss->aucBSSID, bssId)) + return; + } else { + scanlog_dbg(prefix, ERROR, + "pSavedBss(0x%x) or bssid(0x%x) is NULL\n", + pSavedBss, bssId); + return; + } + } + + if (prList->u4NumElem < SCAN_LOG_BUFF_SIZE) { + if (prListBuf != NULL) { + pBss = &(prListBuf[prList->u4NumElem]); + } else { + scanlog_dbg(prefix, INFO, "Buffer is NULL\n"); + return; + } + } else { + scanlog_dbg(prefix, INFO, "Need more buffer\n"); + return; + } + kalMemZero(pBss, sizeof(struct SCAN_LOG_ELEM_BSS)); + + COPY_MAC_ADDR(pBss->aucBSSID, bssId); + pBss->u2SeqCtrl = seq; + + LINK_INSERT_TAIL(prList, &(pBss->rLinkEntry)); +} + +void scanLogCacheFlushBSS(struct LINK *prList, enum ENUM_SCAN_LOG_PREFIX prefix) +{ + char arlogBuf[SCAN_LOG_MSG_MAX_LEN]; + uint32_t idx = 0; + struct SCAN_LOG_ELEM_BSS *pBss = NULL; +#if CFG_SHOW_FULL_MACADDR + /* XXXXXXXXXXXX */ + const uint8_t dataLen = 12; +#else + /* XXXXsumXX */ + const uint8_t dataLen = 9; +#endif + + if (LINK_IS_INVALID(prList)) { + LINK_INITIALIZE(prList); + } + + if (LINK_IS_EMPTY(prList)) + return; + + kalMemZero(arlogBuf, SCAN_LOG_MSG_MAX_LEN); + /* The maximum characters of uint32_t could be 10. Thus, the + * mininum size should be 10+3 for the format "%u: ". + */ + if (dataLen + 1 > SCAN_LOG_MSG_MAX_LEN) { + scanlog_dbg(prefix, INFO, "Scan log buffer is too small.\n"); + while (!LINK_IS_EMPTY(prList)) { + LINK_REMOVE_HEAD(prList, + pBss, struct SCAN_LOG_ELEM_BSS *); + } + return; + } + idx += kalSnprintf(arlogBuf, SCAN_LOG_MSG_MAX_LEN, "%u: ", + prList->u4NumElem); + + while (!LINK_IS_EMPTY(prList)) { + if (idx+dataLen+1 > SCAN_LOG_MSG_MAX_LEN) { + arlogBuf[idx] = 0; /* terminating null byte */ + if (prefix != LOG_SCAN_D2D) + scanlog_dbg(prefix, INFO, "%s\n", arlogBuf); + idx = 0; + } + + LINK_REMOVE_HEAD(prList, + pBss, struct SCAN_LOG_ELEM_BSS *); + +#if CFG_SHOW_FULL_MACADDR + idx += kalSnprintf(arlogBuf+idx, dataLen+1, + "%02x%02x%02x%02x%02x%02x", + ((uint8_t *)pBss->aucBSSID)[0], + ((uint8_t *)pBss->aucBSSID)[1], + ((uint8_t *)pBss->aucBSSID)[2], + ((uint8_t *)pBss->aucBSSID)[3], + ((uint8_t *)pBss->aucBSSID)[4], + ((uint8_t *)pBss->aucBSSID)[5]); +#else + idx += kalSnprintf(arlogBuf+idx, dataLen+1, + "%02x%02x%03x%02x", + ((uint8_t *)pBss->aucBSSID)[0], + ((uint8_t *)pBss->aucBSSID)[1], + ((uint8_t *)pBss->aucBSSID)[2] + + ((uint8_t *)pBss->aucBSSID)[3] + + ((uint8_t *)pBss->aucBSSID)[4], + ((uint8_t *)pBss->aucBSSID)[5]); +#endif + + } + if (idx != 0) { + arlogBuf[idx] = 0; /* terminating null byte */ + if (prefix != LOG_SCAN_D2D) + scanlog_dbg(prefix, INFO, "%s\n", arlogBuf); + idx = 0; + } +} + +void scanLogCacheFlushAll(struct ADAPTER *prAdapter, + struct SCAN_LOG_CACHE *prScanLogCache, + enum ENUM_SCAN_LOG_PREFIX prefix) +{ + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BSSLIST_FW); + scanLogCacheFlushBSS(&(prScanLogCache->rBSSListFW), + prefix); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BSSLIST_FW); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BSSLIST_CFG); + scanLogCacheFlushBSS(&(prScanLogCache->rBSSListCFG), + prefix); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BSSLIST_CFG); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Remove and clean BSS Descriptors from the list. + * + * @param[in] prBSSDescList Pointer to the LINK structure. + * @param[in] prBssDesc Pointer to the BSS_DESC structure. + * @param[in] prAdapter Pointer to the Adapter structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void scanRemoveBssDescFromList(IN struct LINK *prBSSDescList, + IN struct BSS_DESC *prBssDesc, + IN struct ADAPTER *prAdapter) +{ + if (prAdapter != NULL && prBssDesc != NULL) { + uint8_t j; + + /* Support AP Selection */ + if (!prBssDesc->prBlack) + aisQueryBlackList(prAdapter, prBssDesc); + + /* Remove this BSS Desc from the Ess Desc List */ + for (j = 0; j < KAL_AIS_NUM; j++) { + struct AIS_SPECIFIC_BSS_INFO *prSpecBssInfo = + aisGetAisSpecBssInfo( + prAdapter, j); + struct LINK *prEssList; + + if (!prSpecBssInfo) + continue; + prEssList = + &prSpecBssInfo->rCurEssLink; + if (!prEssList) + continue; + + if (!LINK_ENTRY_IS_VALID(&prBssDesc->rLinkEntryEss[j])) + continue; + + LINK_REMOVE_KNOWN_ENTRY(prEssList, + &prBssDesc->rLinkEntryEss[j]); + } + /* end Support AP Selection */ + + /* Remove this BSS Desc from the BSS Desc list */ + if (prBSSDescList != NULL) + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); + } +} /* end of scanRemoveBssDescFromList() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Insert and initialize the BSS Descriptors to the list. + * + * @param[in] prBSSDescList Pointer to the LINK structure. + * @param[in] prBssDesc Pointer to the BSS_DESC structure. + * @param[in] init TRUE for initializing the BSS_DESC. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void scanInsertBssDescToList(IN struct LINK *prBSSDescList, + IN struct BSS_DESC *prBssDesc, + IN u_int8_t init) +{ + if (prBssDesc != NULL) { + if (init == TRUE) { + /* This will reset the link relationship */ + kalMemZero(prBssDesc, sizeof(struct BSS_DESC)); + +#if CFG_ENABLE_WIFI_DIRECT + LINK_INITIALIZE(&(prBssDesc->rP2pDeviceList)); + prBssDesc->fgIsP2PPresent = FALSE; +#endif /* CFG_ENABLE_WIFI_DIRECT */ + } + + /* Insert this BSS Desc to the BSS Desc list */ + if (prBSSDescList != NULL) + LINK_INSERT_TAIL(prBSSDescList, &prBssDesc->rLinkEntry); + } +} /* end of scanInsertBssDescToList() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Reset the BSS Descriptors. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] prBssDesc Pointer to the BSS_DESC structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void scanResetBssDesc(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc) +{ + struct LINK *prBSSDescList = + &prAdapter->rWifiVar.rScanInfo.rBSSDescList; + + scanRemoveBssDescFromList(prBSSDescList, + prBssDesc, + prAdapter); + scanInsertBssDescToList(prBSSDescList, + prBssDesc, + TRUE); +} /* end of scanResetBssDesc() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Check if VHT IE exists in Vendor Epigram IE. + * + * @param[in] pucBuf Pointer to the Vendor IE. + * @param[in] prBssDesc Pointer to the BSS_DESC structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void scanCheckEpigramVhtIE(IN uint8_t *pucBuf, IN struct BSS_DESC *prBssDesc) +{ + uint32_t u4EpigramOui; + uint16_t u2EpigramVendorType; + struct IE_VENDOR_EPIGRAM_IE *prEpiIE; + uint8_t *pucIE; + uint16_t u2IELength; + uint16_t u2Offset = 0; + + if (pucBuf == NULL) { + DBGLOG(RLM, WARN, "[Epigram] pucBuf is NULL, skip!\n"); + return; + } + if (prBssDesc == NULL) { + DBGLOG(RLM, WARN, "[Epigram] prBssDesc is NULL, skip!\n"); + return; + } + + prEpiIE = (struct IE_VENDOR_EPIGRAM_IE *) pucBuf; + u2IELength = prEpiIE->ucLength; + WLAN_GET_FIELD_BE24(prEpiIE->aucOui, &u4EpigramOui); + WLAN_GET_FIELD_BE16(prEpiIE->aucVendorType, &u2EpigramVendorType); + if (u4EpigramOui != VENDOR_IE_EPIGRAM_OUI) + return; + if (u2EpigramVendorType != VENDOR_IE_EPIGRAM_VHTTYPE1 && + u2EpigramVendorType != VENDOR_IE_EPIGRAM_VHTTYPE2 && + u2EpigramVendorType != VENDOR_IE_EPIGRAM_VHTTYPE3) + return; + + pucIE = prEpiIE->pucData; + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_VHT_CAP: + scanParseVHTCapIE(pucIE, prBssDesc); + break; + case ELEM_ID_VHT_OP: + scanParseVHTOpIE(pucIE, prBssDesc); + break; + default: + break; + } + } +} + +void scanParseVHTCapIE(IN uint8_t *pucIE, IN struct BSS_DESC *prBssDesc) +{ + struct IE_VHT_CAP *prVhtCap = NULL; + uint16_t u2TxMcsSet = 0; + uint8_t ucSpatial = 0; + uint8_t j = 0; + + prVhtCap = (struct IE_VHT_CAP *) pucIE; + /* Error handling */ + if (IE_LEN(prVhtCap) != (sizeof(struct IE_VHT_CAP) - 2)) { + DBGLOG(SCN, WARN, + "VhtCap wrong length!(%d)->(%d)\n", + (sizeof(struct IE_VHT_CAP) - 2), + IE_LEN(prVhtCap)); + return; + } + + u2TxMcsSet = prVhtCap->rVhtSupportedMcsSet.u2TxMcsMap; + prBssDesc->fgIsVHTPresent = TRUE; +#if CFG_SUPPORT_BFEE +#define __LOCAL_VAR__ \ +VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS_OFFSET + + prBssDesc->ucVhtCapNumSoundingDimensions = + (prVhtCap->u4VhtCapInfo + & VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS) + >> __LOCAL_VAR__; +#undef __LOCAL_VAR__ +#endif + /* Support AP Selection*/ + if (prBssDesc->fgMultiAnttenaAndSTBC) + return; + + for (; j < 8; j++) { + if ((u2TxMcsSet & BITS(2 * j, 2 * j + 1)) != 3) + ucSpatial++; + } + prBssDesc->fgMultiAnttenaAndSTBC = + ((ucSpatial > 1) && (prVhtCap->u4VhtCapInfo & + VHT_CAP_INFO_TX_STBC)); +} + +void scanParseVHTOpIE(IN uint8_t *pucIE, IN struct BSS_DESC *prBssDesc) +{ + struct IE_VHT_OP *prVhtOp = NULL; + + prVhtOp = (struct IE_VHT_OP *) pucIE; + if (IE_LEN(prVhtOp) != (sizeof(struct IE_VHT_OP) - 2)) + return; + prBssDesc->eChannelWidth = (enum ENUM_CHANNEL_WIDTH) + (prVhtOp->ucVhtOperation[0]); + prBssDesc->ucCenterFreqS1 = (enum ENUM_CHANNEL_WIDTH) + (prVhtOp->ucVhtOperation[1]); + prBssDesc->ucCenterFreqS2 = (enum ENUM_CHANNEL_WIDTH) + (prVhtOp->ucVhtOperation[2]); + + /*add IEEE BW160 patch*/ + rlmModifyVhtBwPara(&prBssDesc->ucCenterFreqS1, + &prBssDesc->ucCenterFreqS2, + (uint8_t *)&prBssDesc->eChannelWidth); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Check if Adaptive 11r IE exists in Vendor Cisco IE. + * + * @param[in] pucBuf Pointer to the Vendor IE. + * @param[in] prBssDesc Pointer to the BSS_DESC structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void scanCheckAdaptive11rIE(IN uint8_t *pucBuf, IN struct BSS_DESC *prBssDesc) +{ + uint32_t oui; + struct IE_VENDOR_ADAPTIVE_11R_IE *ie; + uint8_t data; + uint16_t len; + + if (pucBuf == NULL || prBssDesc == NULL) { + DBGLOG(SCN, WARN, "adp11r pucBuf %p, prBssDesc %p, skip!\n", + pucBuf, prBssDesc); + return; + } + + ie = (struct IE_VENDOR_ADAPTIVE_11R_IE *) pucBuf; + len = ie->ucLength; + if (len < 5 || len > 8) + return; + + WLAN_GET_FIELD_BE24(ie->aucOui, &oui); + if (oui != VENDOR_IE_CISCO_OUI || + *(ie->aucVendorType) != VENDOR_IE_CISCO_TYPE) + return; + + data = *(ie->pucData); + prBssDesc->ucIsAdaptive11r = data & BIT(0); + DBGLOG(SCN, TRACE, "BSSDesc [" MACSTR "] adaptive11r = %d\n", + MAC2STR(prBssDesc->aucBSSID), prBssDesc->ucIsAdaptive11r); +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/scan_cache.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/scan_cache.c new file mode 100644 index 0000000000000..037636f4c0ff3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/scan_cache.c @@ -0,0 +1,289 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/******************************************************************************* + * C O M P I L E 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_SCAN_CACHE_RESULT +/******************************************************************************* + * 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 OS_SYSTIME getCurrentScanTime(void); + +static OS_SYSTIME getLastScanTime(struct GL_SCAN_CACHE_INFO *prScanCache); + +static void setLastScanTime(struct GL_SCAN_CACHE_INFO *prScanCache, + OS_SYSTIME rCurrentTime); + +static uint32_t getNumberOfScanChannels(struct GL_SCAN_CACHE_INFO *prScanCache); + +static u_int8_t isMediaConnected(struct GL_SCAN_CACHE_INFO *prScanCache); + +static u_int8_t isScanCacheChannels(struct GL_SCAN_CACHE_INFO *prScanCache); + +static u_int8_t isScanCacheTimeReady(struct GL_SCAN_CACHE_INFO *prScanCache); +static u_int8_t isScanCacheLowSpanScan(struct GL_SCAN_CACHE_INFO *prScanCache); +static u_int8_t isFull2PartialTimeout(struct GL_SCAN_CACHE_INFO *prScanCache); +static u_int8_t isScanCacheTimeOverflow(struct GL_SCAN_CACHE_INFO *prScanCache, + OS_SYSTIME rCurrentTime); + +static u_int8_t doScanCache(struct GL_SCAN_CACHE_INFO *prScanCache); + +static void updateScanCacheLastScanTime(struct GL_SCAN_CACHE_INFO *prScanCache, + OS_SYSTIME rCurrentTime); + +static void resetScanCacheLastScanTime(struct GL_SCAN_CACHE_INFO *prScanCache); + +static u_int8_t inScanCachePeriod(struct GL_SCAN_CACHE_INFO *prScanCache, + OS_SYSTIME rCurrentTime); + +static u_int8_t matchScanCache(struct GL_SCAN_CACHE_INFO *prScanCache, + OS_SYSTIME rCurrentTime); + +static u_int8_t matchLastScanTimeUpdate(struct GL_SCAN_CACHE_INFO *prScanCache, + OS_SYSTIME rCurrentTime); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +static OS_SYSTIME getCurrentScanTime(void) +{ + OS_SYSTIME rCurrentTime = 0; + + GET_CURRENT_SYSTIME(&rCurrentTime); + return rCurrentTime; +} + +static OS_SYSTIME getLastScanTime(struct GL_SCAN_CACHE_INFO *prScanCache) +{ + return prScanCache->u4LastScanTime; +} + +static void setLastScanTime(struct GL_SCAN_CACHE_INFO *prScanCache, + OS_SYSTIME rCurrentTime) +{ + prScanCache->u4LastScanTime = rCurrentTime; +} + +static uint32_t getNumberOfScanChannels(struct GL_SCAN_CACHE_INFO *prScanCache) +{ + return (uint32_t) prScanCache->n_channels; +} + +static u_int8_t isMediaConnected(struct GL_SCAN_CACHE_INFO *prScanCache) +{ + return MEDIA_STATE_CONNECTED == + kalGetMediaStateIndicated(prScanCache->prGlueInfo, + prScanCache->ucBssIndex); +} + +static u_int8_t isScanCacheChannels(struct GL_SCAN_CACHE_INFO *prScanCache) +{ + return getNumberOfScanChannels(prScanCache) >= + CFG_SCAN_CACHE_MIN_CHANNEL_NUM; +} + +static u_int8_t isScanCacheTimeReady(struct GL_SCAN_CACHE_INFO *prScanCache) +{ + return prScanCache->u4LastScanTime != 0; +} + +static u_int8_t isScanCacheLowSpanScan(struct GL_SCAN_CACHE_INFO *prScanCache) +{ + return (prScanCache->u4Flags & NL80211_SCAN_FLAG_LOW_SPAN) >> 8; +} + +/* + * @brief This routine is to check the interval of full scan + * + * @param prScanCache - pointer of struct GL_SCAN_CACHE_INFO + * + * @retval TRUE: time diff between now and last full scan >= + * CFG_SCAN_FULL2PARTIAL_PERIOD + * FALSE: time diff between now and last full scan < + * CFG_SCAN_FULL2PARTIAL_PERIOD + */ +static u_int8_t isFull2PartialTimeout(struct GL_SCAN_CACHE_INFO *prScanCache) +{ + struct ADAPTER *prAdapter = NULL; + struct SCAN_INFO *prScanInfo; + u_int8_t fgLastFullScanTimeout = FALSE; + OS_SYSTIME rCurrentTime; + + GET_CURRENT_SYSTIME(&rCurrentTime); + + prAdapter = prScanCache->prGlueInfo->prAdapter; + if (prAdapter == NULL) { + DBGLOG(REQ, ERROR, "prScanCache->prGlueInfo->prAdapter NULL"); + return FALSE; + } + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + if (prScanInfo == NULL) { + DBGLOG(REQ, ERROR, "prAdapter->rWifiVar.rScanInfo NULL"); + return FALSE; + } + +#if CFG_SUPPORT_FULL2PARTIAL_SCAN + if (CHECK_FOR_TIMEOUT(rCurrentTime, prScanInfo->u4LastFullScanTime, + SEC_TO_SYSTIME(CFG_SCAN_FULL2PARTIAL_PERIOD))) + fgLastFullScanTimeout = TRUE; +#endif + + return fgLastFullScanTimeout; +} + +static u_int8_t isScanCacheTimeOverflow(struct GL_SCAN_CACHE_INFO *prScanCache, + OS_SYSTIME rCurrentTime) +{ + return getLastScanTime(prScanCache) > rCurrentTime; +} + +static u_int8_t doScanCache(struct GL_SCAN_CACHE_INFO *prScanCache) +{ + GLUE_SPIN_LOCK_DECLARATION(); + + kalUpdateBssTimestamp(prScanCache->prGlueInfo); + GLUE_ACQUIRE_SPIN_LOCK(prScanCache->prGlueInfo, SPIN_LOCK_NET_DEV); + kalCfg80211ScanDone(prScanCache->prRequest, FALSE); + GLUE_RELEASE_SPIN_LOCK(prScanCache->prGlueInfo, SPIN_LOCK_NET_DEV); + return TRUE; +} + +static void updateScanCacheLastScanTime(struct GL_SCAN_CACHE_INFO *prScanCache, + OS_SYSTIME rCurrentTime) +{ + setLastScanTime(prScanCache, rCurrentTime); +} + +static void resetScanCacheLastScanTime(struct GL_SCAN_CACHE_INFO *prScanCache) +{ + setLastScanTime(prScanCache, 0); +} + +static u_int8_t inScanCachePeriod(struct GL_SCAN_CACHE_INFO *prScanCache, + OS_SYSTIME rCurrentTime) +{ + if (isScanCacheTimeReady(prScanCache) == FALSE) + return FALSE; + + if (isScanCacheTimeOverflow(prScanCache, rCurrentTime) == TRUE) + return FALSE; + + if (CHECK_FOR_TIMEOUT(rCurrentTime, getLastScanTime(prScanCache), + CFG_SCAN_CACHE_RESULT_PERIOD) == FALSE) + return TRUE; + + return FALSE; +} + +static u_int8_t matchScanCache(struct GL_SCAN_CACHE_INFO *prScanCache, + OS_SYSTIME rCurrentTime) +{ + + if (isMediaConnected(prScanCache) == TRUE) { + /* If scan not triggered by APP and it has been > + * CFG_SCAN_FULL2PARTIAL_PERIOD for last full scan, + * not to do scan cache + */ + if (!isScanCacheLowSpanScan(prScanCache) && + isFull2PartialTimeout(prScanCache)) + return FALSE; + else if (inScanCachePeriod(prScanCache, rCurrentTime) == TRUE && + isScanCacheChannels(prScanCache) == TRUE) + return TRUE; + } + return FALSE; +} + +static u_int8_t matchLastScanTimeUpdate(struct GL_SCAN_CACHE_INFO *prScanCache, + OS_SYSTIME rCurrentTime) +{ + if (isMediaConnected(prScanCache) == TRUE && + inScanCachePeriod(prScanCache, rCurrentTime) == FALSE && + isScanCacheChannels(prScanCache) == TRUE) + return TRUE; + + return FALSE; +} + +/* + * @brief This routine is responsible for checking scan cache + * + * @param prScanCache - pointer of struct GL_SCAN_CACHE_INFO + * + * @retval TRUE: do scan cache successful + * FALSE: didn't report scan cache + */ +u_int8_t isScanCacheDone(struct GL_SCAN_CACHE_INFO *prScanCache) +{ + OS_SYSTIME rCurrentTime = getCurrentScanTime(); + + if (matchScanCache(prScanCache, rCurrentTime) == TRUE) { + log_limited_dbg(REQ, INFO, "SCAN_CACHE: Skip scan too frequently(%u, %u). Call cfg80211_scan_done directly\n", + rCurrentTime, + getLastScanTime(prScanCache)); + + return doScanCache(prScanCache); + } + + if (matchLastScanTimeUpdate(prScanCache, rCurrentTime) == TRUE) { + log_dbg(REQ, INFO, "SCAN_CACHE: set scan cache time (%u)->(%u)\n", + getLastScanTime(prScanCache), + rCurrentTime); + + updateScanCacheLastScanTime(prScanCache, rCurrentTime); + } + + if (isMediaConnected(prScanCache) == FALSE) { + log_dbg(REQ, TRACE, "SCAN_CACHE: reset scan cache time (%u)->(0)\n", + getLastScanTime(prScanCache)); + + resetScanCacheLastScanTime(prScanCache); + } + return FALSE; +} +#endif /* CFG_SUPPORT_SCAN_CACHE_RESULT */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/scan_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/scan_fsm.c new file mode 100644 index 0000000000000..5ff01e829df9c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/scan_fsm.c @@ -0,0 +1,1350 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/scan_fsm.c#2 + */ + +/*! \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. + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +static uint8_t *apucDebugScanState[SCAN_STATE_NUM] = { + (uint8_t *) DISP_STRING("IDLE"), + (uint8_t *) DISP_STRING("SCANNING"), +}; + +/******************************************************************************* + * M A 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 struct ADAPTER *prAdapter, + IN enum ENUM_SCAN_STATE eNextState) +{ + struct SCAN_INFO *prScanInfo; + struct SCAN_PARAM *prScanParam; + struct MSG_HDR *prMsgHdr; + + u_int8_t fgIsTransition = (u_int8_t) FALSE; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + do { + /* Coverity */ + if (prScanInfo->eCurrentState >= 0 && eNextState >= 0) { + log_dbg(SCN, STATE, "[SCAN]TRANSITION: [%s] -> [%s]\n", + apucDebugScanState[prScanInfo->eCurrentState], + apucDebugScanState[eNextState]); + } + /* NOTE(Kevin): This is the only place to change the + * eCurrentState(except initial) + */ + prScanInfo->eCurrentState = eNextState; + + fgIsTransition = (u_int8_t) 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, struct MSG_HDR *); + +#define __MSG_ID__ prMsgHdr->eMsgId + if (__MSG_ID__ == MID_AIS_SCN_SCAN_REQ + || __MSG_ID__ == MID_BOW_SCN_SCAN_REQ + || __MSG_ID__ == MID_P2P_SCN_SCAN_REQ + || __MSG_ID__ == MID_RLM_SCN_SCAN_REQ) { + scnFsmHandleScanMsg(prAdapter, + (struct MSG_SCN_SCAN_REQ *) + prMsgHdr); + + eNextState = SCAN_STATE_SCANNING; + fgIsTransition = TRUE; + } else if (__MSG_ID__ == MID_AIS_SCN_SCAN_REQ_V2 + || __MSG_ID__ == MID_BOW_SCN_SCAN_REQ_V2 + || __MSG_ID__ == MID_P2P_SCN_SCAN_REQ_V2 + || __MSG_ID__ == MID_RLM_SCN_SCAN_REQ_V2 + ) { + scnFsmHandleScanMsgV2(prAdapter, + (struct MSG_SCN_SCAN_REQ_V2 *) + prMsgHdr); + + eNextState = SCAN_STATE_SCANNING; + fgIsTransition = TRUE; + } else { + /* should not happen */ + ASSERT(0); + } +#undef __MSG_ID__ + + /* switch to next state */ + cnmMemFree(prAdapter, prMsgHdr); + } + break; + + case SCAN_STATE_SCANNING: + /* Support AP Selection */ + prScanInfo->u4ScanUpdateIdx++; + if (prScanParam->fgIsScanV2 == FALSE) + scnSendScanReq(prAdapter); + else + scnSendScanReqV2(prAdapter); + break; + + default: + ASSERT(0); + break; + + } + } while (fgIsTransition); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Generate CMD_ID_SCAN_REQ command + * + * Because CMD_ID_SCAN_REQ is deprecated, + * wrap this command to CMD_ID_SCAN_REQ_V2 + * + * \param[in] prAdapter adapter + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void scnSendScanReq(IN struct ADAPTER *prAdapter) +{ + log_dbg(SCN, WARN, + "CMD_ID_SCAN_REQ is deprecated, use CMD_ID_SCAN_REQ_V2\n"); + scnSendScanReqV2(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Generate CMD_ID_SCAN_REQ_V2 command + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void scnSendScanReqV2(IN struct ADAPTER *prAdapter) +{ + struct SCAN_INFO *prScanInfo; + struct SCAN_PARAM *prScanParam; + /* CMD_SCAN_REQ_V2 rCmdScanReq; */ + struct CMD_SCAN_REQ_V2 *prCmdScanReq; + uint32_t i; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &(prScanInfo->rScanParam); + + prCmdScanReq = kalMemAlloc( + sizeof(struct CMD_SCAN_REQ_V2), VIR_MEM_TYPE); + if (!prCmdScanReq) { + log_dbg(SCN, ERROR, "alloc CmdScanReq V2 fail\n"); + return; + } + /* send command packet for scan */ + kalMemZero(prCmdScanReq, sizeof(struct CMD_SCAN_REQ_V2)); + /* Modify channelList number from 32 to 54 */ + COPY_MAC_ADDR(prCmdScanReq->aucBSSID, prScanParam->aucBSSID); + + prCmdScanReq->ucSeqNum = prScanParam->ucSeqNum; + prCmdScanReq->ucBssIndex = prScanParam->ucBssIndex; + prCmdScanReq->ucScanType = (uint8_t) prScanParam->eScanType; + prCmdScanReq->ucSSIDType = prScanParam->ucSSIDType; + prCmdScanReq->auVersion[0] = 1; + prCmdScanReq->ucScnFuncMask |= prScanParam->ucScnFuncMask; + if (kalIsValidMacAddr(prScanParam->aucRandomMac)) { + prCmdScanReq->ucScnFuncMask |= (ENUM_SCN_RANDOM_MAC_EN | + ENUM_SCN_RANDOM_SN_EN); + kalMemCopy(prCmdScanReq->aucRandomMac, + prScanParam->aucRandomMac, MAC_ADDR_LEN); + } + if (prAdapter->rWifiVar.eDbdcMode == ENUM_DBDC_MODE_DISABLED) + prCmdScanReq->ucScnFuncMask |= ENUM_SCN_DBDC_SCAN_DIS; + + /* Set SSID to scan request */ + if (prScanParam->ucSSIDNum <= SCAN_CMD_SSID_NUM) { + prCmdScanReq->ucSSIDNum = prScanParam->ucSSIDNum; + prCmdScanReq->ucSSIDExtNum = 0; + } else if (prScanParam->ucSSIDNum <= CFG_SCAN_SSID_MAX_NUM) { + prCmdScanReq->ucSSIDNum = SCAN_CMD_SSID_NUM; + prCmdScanReq->ucSSIDExtNum = prScanParam->ucSSIDNum + - SCAN_CMD_SSID_NUM; + } else { + log_dbg(SCN, WARN, "Too many SSID %u\n", + prScanParam->ucSSIDNum); + prCmdScanReq->ucSSIDNum = SCAN_CMD_SSID_NUM; + prCmdScanReq->ucSSIDExtNum = SCAN_CMD_EXT_SSID_NUM; + } + + for (i = 0; i < prCmdScanReq->ucSSIDNum; i++) { + COPY_SSID(prCmdScanReq->arSSID[i].aucSsid, + prCmdScanReq->arSSID[i].u4SsidLen, + prScanParam->aucSpecifiedSSID[i], + prScanParam->ucSpecifiedSSIDLen[i]); + log_dbg(SCN, TRACE, + "Ssid=%s, SsidLen=%d\n", + HIDE(prCmdScanReq->arSSID[i].aucSsid), + prCmdScanReq->arSSID[i].u4SsidLen); + } + for (i = 0; i < prCmdScanReq->ucSSIDExtNum; i++) { + COPY_SSID(prCmdScanReq->arSSIDExtend[i].aucSsid, + prCmdScanReq->arSSIDExtend[i].u4SsidLen, + prScanParam->aucSpecifiedSSID + [prCmdScanReq->ucSSIDNum+i], + prScanParam->ucSpecifiedSSIDLen + [prCmdScanReq->ucSSIDNum+i]); + log_dbg(SCN, TRACE, + "Ssid=%s, SsidLen=%d\n", + prCmdScanReq->arSSIDExtend[i].aucSsid, + prCmdScanReq->arSSIDExtend[i].u4SsidLen); + } + + prCmdScanReq->u2ProbeDelayTime + = (uint8_t) prScanParam->u2ProbeDelayTime; + prCmdScanReq->ucChannelType + = (uint8_t) prScanParam->eScanChannel; + + /* Set channel info to scan request */ + if (prScanParam->eScanChannel == SCAN_CHANNEL_SPECIFIED) { + if (prScanParam->ucChannelListNum <= SCAN_CMD_CHNL_NUM) { + prCmdScanReq->ucChannelListNum = + prScanParam->ucChannelListNum; + prCmdScanReq->ucChannelListExtNum = 0; + } else if (prScanParam->ucChannelListNum <= + MAXIMUM_OPERATION_CHANNEL_LIST) { + prCmdScanReq->ucChannelListNum = + SCAN_CMD_CHNL_NUM; + prCmdScanReq->ucChannelListExtNum = + prScanParam->ucChannelListNum - + SCAN_CMD_CHNL_NUM; + } else { + log_dbg(SCN, WARN, "Too many Channel %u\n", + prScanParam->ucChannelListNum); + prCmdScanReq->ucChannelListNum = 0; + prCmdScanReq->ucChannelListExtNum = 0; + prCmdScanReq->ucChannelType = SCAN_CHANNEL_FULL; + } + + for (i = 0; i < prCmdScanReq->ucChannelListNum; i++) { + prCmdScanReq->arChannelList[i].ucBand + = (uint8_t) prScanParam->arChnlInfoList[i] + .eBand; + + prCmdScanReq->arChannelList[i].ucChannelNum + = (uint8_t) prScanParam->arChnlInfoList[i] + .ucChannelNum; + } + for (i = 0; i < prCmdScanReq->ucChannelListExtNum; i++) { + prCmdScanReq->arChannelListExtend[i].ucBand + = (uint8_t)prScanParam + ->arChnlInfoList + [prCmdScanReq->ucChannelListNum+i] + .eBand; + + prCmdScanReq->arChannelListExtend[i].ucChannelNum + = (uint8_t) prScanParam + ->arChnlInfoList + [prCmdScanReq->ucChannelListNum+i] + .ucChannelNum; + } + } + + prCmdScanReq->u2ChannelDwellTime = prScanParam->u2ChannelDwellTime; + prCmdScanReq->u2ChannelMinDwellTime = + prScanParam->u2ChannelMinDwellTime; + prCmdScanReq->u2TimeoutValue = prScanParam->u2TimeoutValue; + + if (prScanParam->u2IELen <= MAX_IE_LENGTH) + prCmdScanReq->u2IELen = prScanParam->u2IELen; + else + prCmdScanReq->u2IELen = MAX_IE_LENGTH; + + if (prScanParam->u2IELen) + kalMemCopy(prCmdScanReq->aucIE, prScanParam->aucIE, + sizeof(uint8_t) * prCmdScanReq->u2IELen); + + log_dbg(SCN, TRACE, "ScanReqV2: ScanType=%d,BSS=%u,SSIDType=%d,Num=%u,Ext=%u,ChannelType=%d,Num=%d,Ext=%u,Seq=%u,Ver=%u,Dw=%u,Min=%u,Func=0x%X,Mac=" + MACSTR ",BSSID:"MACSTR"\n", + prCmdScanReq->ucScanType, + prCmdScanReq->ucBssIndex, + prCmdScanReq->ucSSIDType, + prCmdScanReq->ucSSIDNum, + prCmdScanReq->ucSSIDExtNum, + prCmdScanReq->ucChannelType, + prCmdScanReq->ucChannelListNum, + prCmdScanReq->ucChannelListExtNum, + prCmdScanReq->ucSeqNum, prCmdScanReq->auVersion[0], + prCmdScanReq->u2ChannelDwellTime, + prCmdScanReq->u2ChannelMinDwellTime, + prCmdScanReq->ucScnFuncMask, + MAC2STR(prCmdScanReq->aucRandomMac), + MAC2STR(prCmdScanReq->aucBSSID)); + + scanLogCacheFlushAll(prAdapter, &(prScanInfo->rScanLogCache), + LOG_SCAN_REQ_D2F); + scanReqLog(prCmdScanReq); + if (prCmdScanReq->ucBssIndex == KAL_NETWORK_TYPE_AIS_INDEX) + scanInitEssResult(prAdapter); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SCAN_REQ_V2, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_SCAN_REQ_V2), + (uint8_t *)prCmdScanReq, NULL, 0); + log_dbg(SCN, TRACE, "Send %zu bytes\n", sizeof(struct CMD_SCAN_REQ_V2)); + + + kalMemFree(prCmdScanReq, VIR_MEM_TYPE, sizeof(struct CMD_SCAN_REQ_V2)); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void scnFsmMsgStart(IN struct ADAPTER *prAdapter, IN struct MSG_HDR *prMsgHdr) +{ + struct SCAN_INFO *prScanInfo; + struct SCAN_PARAM *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, + (struct 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, + (struct MSG_SCN_SCAN_REQ_V2 *) prMsgHdr); + } else { + /* should not deliver to this function */ + ASSERT(0); + } + + cnmMemFree(prAdapter, prMsgHdr); + scnFsmSteps(prAdapter, SCAN_STATE_SCANNING); + } else { + LINK_INSERT_TAIL(&prScanInfo->rPendingMsgList, + &prMsgHdr->rLinkEntry); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void scnFsmMsgAbort(IN struct ADAPTER *prAdapter, IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_SCN_SCAN_CANCEL *prScanCancel; + struct SCAN_INFO *prScanInfo; + struct SCAN_PARAM *prScanParam; + struct CMD_SCAN_CANCEL rCmdScanCancel; + + ASSERT(prMsgHdr); + + prScanCancel = (struct MSG_SCN_SCAN_CANCEL *) prMsgHdr; + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + if (prScanInfo->eCurrentState != SCAN_STATE_IDLE) { + if (prScanCancel->ucSeqNum == prScanParam->ucSeqNum && + prScanCancel->ucBssIndex == prScanParam->ucBssIndex) { + enum ENUM_SCAN_STATUS eStatus = SCAN_STATUS_DONE; + + /* send cancel message to firmware domain */ + rCmdScanCancel.ucSeqNum = prScanParam->ucSeqNum; + rCmdScanCancel.ucIsExtChannel + = (uint8_t) prScanCancel->fgIsChannelExt; + + scanlog_dbg(LOG_SCAN_ABORT_REQ_D2F, INFO, "Scan Abort#%u to Q: isExtCh=%u", + rCmdScanCancel.ucSeqNum, + rCmdScanCancel.ucIsExtChannel); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SCAN_CANCEL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_SCAN_CANCEL), + (uint8_t *) &rCmdScanCancel, + NULL, + 0); + + /* Full2Partial: ignore this statistics */ + if (prScanInfo->fgIsScanForFull2Partial) { + prScanInfo->fgIsScanForFull2Partial = FALSE; + prScanInfo->u4LastFullScanTime = 0; + log_dbg(SCN, INFO, + "Full2Partial: scan canceled(%u)\n", + prScanParam->ucSeqNum); + } + + /* generate scan-done event for caller */ + if (prScanCancel->fgIsOidRequest) + eStatus = SCAN_STATUS_CANCELLED; + else + eStatus = SCAN_STATUS_DONE; + scnFsmGenerateScanDoneMsg(prAdapter, + prScanParam->eMsgId, + prScanParam->ucSeqNum, + prScanParam->ucBssIndex, + eStatus); + + /* switch to next pending scan */ + scnFsmSteps(prAdapter, SCAN_STATE_IDLE); + } else { + scnFsmRemovePendingMsg(prAdapter, + prScanCancel->ucSeqNum, + prScanCancel->ucBssIndex); + } + } + + cnmMemFree(prAdapter, prMsgHdr); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Scan Message Parsing (Legacy) + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void scnFsmHandleScanMsg(IN struct ADAPTER *prAdapter, + IN struct MSG_SCN_SCAN_REQ *prScanReqMsg) +{ + struct SCAN_INFO *prScanInfo; + struct SCAN_PARAM *prScanParam; + uint32_t i; + + ASSERT(prAdapter); + ASSERT(prScanReqMsg); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + kalMemZero(prScanParam, sizeof(*prScanParam)); + prScanParam->eScanType = prScanReqMsg->eScanType; + prScanParam->ucBssIndex = prScanReqMsg->ucBssIndex; + 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(struct RF_CHANNEL_INFO) + * 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); + } + + prScanParam->u2ChannelDwellTime = prScanReqMsg->u2ChannelDwellTime; + prScanParam->u2TimeoutValue = prScanReqMsg->u2TimeoutValue; + prScanParam->ucSeqNum = prScanReqMsg->ucSeqNum; + prScanParam->eMsgId = prScanReqMsg->rMsgHdr.eMsgId; + prScanParam->fgIsScanV2 = FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Scan Message Parsing - V2 with multiple SSID support + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void scnFsmHandleScanMsgV2(IN struct ADAPTER *prAdapter, + IN struct MSG_SCN_SCAN_REQ_V2 *prScanReqMsg) +{ + struct SCAN_INFO *prScanInfo; + struct SCAN_PARAM *prScanParam; + uint32_t i; + + ASSERT(prAdapter); + ASSERT(prScanReqMsg); + ASSERT(prScanReqMsg->ucSSIDNum <= SCN_SSID_MAX_NUM); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + kalMemZero(prScanParam, sizeof(*prScanParam)); + prScanParam->eScanType = prScanReqMsg->eScanType; + prScanParam->ucBssIndex = prScanReqMsg->ucBssIndex; + prScanParam->ucSSIDType = prScanReqMsg->ucSSIDType; + prScanParam->ucSSIDNum = prScanReqMsg->ucSSIDNum; + prScanParam->ucScnFuncMask |= prScanReqMsg->ucScnFuncMask; + kalMemCopy(prScanParam->aucRandomMac, prScanReqMsg->aucRandomMac, + MAC_ADDR_LEN); + + if (prScanParam->ucSSIDType & SCAN_REQ_SSID_SPECIFIED_ONLY) { + prScanParam->ucSSIDNum = 1; + kalMemZero(prScanParam->ucSpecifiedSSIDLen, + sizeof(prScanParam->ucSpecifiedSSIDLen)); + COPY_SSID(prScanParam->aucSpecifiedSSID[0], + prScanParam->ucSpecifiedSSIDLen[0], + &prScanReqMsg->prSsid[0].aucSsid[0], + prScanReqMsg->prSsid[0].u4SsidLen); + } else { + for (i = 0; i < prScanReqMsg->ucSSIDNum; i++) { + COPY_SSID(prScanParam->aucSpecifiedSSID[i], + prScanParam->ucSpecifiedSSIDLen[i], + prScanReqMsg->prSsid[i].aucSsid, + (uint8_t) 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(struct RF_CHANNEL_INFO) + * 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); + } + + prScanParam->u2ChannelDwellTime = prScanReqMsg->u2ChannelDwellTime; + prScanParam->u2ChannelMinDwellTime = + prScanReqMsg->u2ChannelMinDwellTime; + prScanParam->u2TimeoutValue = prScanReqMsg->u2TimeoutValue; + prScanParam->ucSeqNum = prScanReqMsg->ucSeqNum; + prScanParam->eMsgId = prScanReqMsg->rMsgHdr.eMsgId; + prScanParam->fgIsScanV2 = TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Remove pending scan request + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void scnFsmRemovePendingMsg(IN struct ADAPTER *prAdapter, IN uint8_t ucSeqNum, + IN uint8_t ucBssIndex) +{ + struct SCAN_INFO *prScanInfo; + struct SCAN_PARAM *prScanParam; + struct MSG_HDR *prPendingMsgHdr = NULL; + struct MSG_HDR *prPendingMsgHdrNext = NULL; + struct MSG_HDR *prRemoveMsgHdr = NULL; + struct LINK_ENTRY *prRemoveLinkEntry = NULL; + u_int8_t fgIsRemovingScan = FALSE; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + /* traverse through rPendingMsgList for removal */ + LINK_FOR_EACH_ENTRY_SAFE(prPendingMsgHdr, + prPendingMsgHdrNext, &(prScanInfo->rPendingMsgList), + rLinkEntry, struct MSG_HDR) { + +#define __MSG_ID__ prPendingMsgHdr->eMsgId + if (__MSG_ID__ == MID_AIS_SCN_SCAN_REQ + || __MSG_ID__ == MID_BOW_SCN_SCAN_REQ + || __MSG_ID__ == MID_P2P_SCN_SCAN_REQ + || __MSG_ID__ == MID_RLM_SCN_SCAN_REQ) { + struct MSG_SCN_SCAN_REQ *prScanReqMsg + = (struct MSG_SCN_SCAN_REQ *) + prPendingMsgHdr; + + if (ucSeqNum == prScanReqMsg->ucSeqNum + && ucBssIndex == prScanReqMsg->ucBssIndex) { + prRemoveLinkEntry + = &(prScanReqMsg->rMsgHdr.rLinkEntry); + prRemoveMsgHdr = prPendingMsgHdr; + fgIsRemovingScan = TRUE; + } + } else if (__MSG_ID__ == MID_AIS_SCN_SCAN_REQ_V2 + || __MSG_ID__ == MID_BOW_SCN_SCAN_REQ_V2 + || __MSG_ID__ == MID_P2P_SCN_SCAN_REQ_V2 + || __MSG_ID__ == MID_RLM_SCN_SCAN_REQ_V2) { + struct MSG_SCN_SCAN_REQ_V2 *prScanReqMsgV2 + = (struct MSG_SCN_SCAN_REQ_V2 *) + prPendingMsgHdr; + + if (ucSeqNum == prScanReqMsgV2->ucSeqNum + && ucBssIndex == prScanReqMsgV2->ucBssIndex) { + prRemoveLinkEntry + = &(prScanReqMsgV2->rMsgHdr.rLinkEntry); + prRemoveMsgHdr = prPendingMsgHdr; + fgIsRemovingScan = TRUE; + } + } +#undef __MSG_ID__ + + if (prRemoveLinkEntry) { + if (fgIsRemovingScan == TRUE) { + /* generate scan-done event for caller */ + scnFsmGenerateScanDoneMsg(prAdapter, + prPendingMsgHdr->eMsgId, ucSeqNum, + ucBssIndex, SCAN_STATUS_CANCELLED); + } + + /* remove from pending list */ + LINK_REMOVE_KNOWN_ENTRY(&(prScanInfo->rPendingMsgList), + prRemoveLinkEntry); + cnmMemFree(prAdapter, prRemoveMsgHdr); + + break; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void scnEventScanDone(IN struct ADAPTER *prAdapter, + IN struct EVENT_SCAN_DONE *prScanDone, u_int8_t fgIsNewVersion) +{ + struct SCAN_INFO *prScanInfo; + struct SCAN_PARAM *prScanParam; + uint32_t u4ChCnt = 0; + KAL_SPIN_LOCK_DECLARATION(); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + if (fgIsNewVersion) { + scanlog_dbg(LOG_SCAN_DONE_F2D, INFO, "scnEventScanDone Version%u!size of ScanDone%zu,ucCompleteChanCount[%u],ucCurrentState%u, u4ScanDurBcnCnt[%u],Seq[%u]\n", + prScanDone->ucScanDoneVersion, + sizeof(struct EVENT_SCAN_DONE), + prScanDone->ucCompleteChanCount, + prScanDone->ucCurrentState, + prScanDone->u4ScanDurBcnCnt, + prScanDone->ucSeqNum); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BSSLIST_FW); + scanLogCacheFlushBSS(&(prScanInfo->rScanLogCache.rBSSListFW), + LOG_SCAN_DONE_F2D); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BSSLIST_FW); + + if (prScanDone->ucCurrentState != FW_SCAN_STATE_SCAN_DONE) { + log_dbg(SCN, INFO, "FW Scan timeout!generate ScanDone event at State%d complete chan count%d ucChannelListNum%d\n", + prScanDone->ucCurrentState, + prScanDone->ucCompleteChanCount, + prScanParam->ucChannelListNum); + + } else { + log_dbg(SCN, TRACE, " scnEventScanDone at FW_SCAN_STATE_SCAN_DONE state\n"); + } + } else { + scanlog_dbg(LOG_SCAN_DONE_F2D, INFO, "Old scnEventScanDone Version\n"); + } + + /* buffer empty channel information */ + if (prScanDone->ucSparseChannelValid) { + int num = 0; + char strbuf[SCN_SCAN_DONE_PRINT_BUFFER_LENGTH]; + + prScanInfo->fgIsSparseChannelValid = TRUE; + prScanInfo->rSparseChannel.eBand + = (enum ENUM_BAND) prScanDone->rSparseChannel.ucBand; + prScanInfo->rSparseChannel.ucChannelNum + = prScanDone->rSparseChannel.ucChannelNum; + num = prScanInfo->ucSparseChannelArrayValidNum + = prScanDone->ucSparseChannelArrayValidNum; + log_dbg(SCN, INFO, "Country Code = %c%c, Detected_Channel_Num = %d\n", + ((prAdapter->rWifiVar.u2CountryCode + & 0xff00) >> 8), + (prAdapter->rWifiVar.u2CountryCode + & 0x00ff), num); + +#define print_info(_Mod, _Clz, _Fmt, var) \ + do { \ + int written = 0; \ + int totalLen = SCN_SCAN_DONE_PRINT_BUFFER_LENGTH; \ + for (u4ChCnt = 0; u4ChCnt < num; u4ChCnt++) { \ + prScanInfo->var[u4ChCnt] \ + = prScanDone->var[u4ChCnt]; \ + written += kalSnprintf(strbuf + written, \ + totalLen - written, "%7d", \ + prScanInfo->var[u4ChCnt]); \ + } \ + log_dbg(_Mod, _Clz, _Fmt, strbuf); \ + } while (0) + + print_info(SCN, INFO, "Channel : %s\n", aucChannelNum); + print_info(SCN, INFO, "IdleTime : %s\n", au2ChannelIdleTime); + print_info(SCN, INFO, "MdrdyCnt : %s\n", aucChannelMDRDYCnt); + print_info(SCN, INFO, "BAndPCnt : %s\n", aucChannelBAndPCnt); + if (prScanDone->ucScanDoneVersion >= 4) + print_info(SCN, LOUD, + "ScanTime : %s\n", au2ChannelScanTime); +#undef print_scan_info + } else { + prScanInfo->fgIsSparseChannelValid = FALSE; + } + + /* Full2Partial */ + if (prScanInfo->fgIsScanForFull2Partial && + prScanInfo->ucFull2PartialSeq == prScanDone->ucSeqNum) { + uint32_t *pu4BitMap = &(prScanInfo->au4ChannelBitMap[0]); + + log_dbg(SCN, INFO, + "Full2Partial(%u):%08X %08X %08X %08X %08X %08X %08X %08X\n", + scanCountBits(prScanInfo->au4ChannelBitMap, + sizeof(prScanInfo->au4ChannelBitMap)), + pu4BitMap[7], pu4BitMap[6], pu4BitMap[5], pu4BitMap[4], + pu4BitMap[3], pu4BitMap[2], pu4BitMap[1], pu4BitMap[0]); + + prScanInfo->fgIsScanForFull2Partial = FALSE; + } + + if (prScanInfo->eCurrentState == SCAN_STATE_SCANNING + && prScanDone->ucSeqNum == prScanParam->ucSeqNum) { + scanRemoveBssDescsByPolicy(prAdapter, + SCN_RM_POLICY_EXCLUDE_CONNECTED | SCN_RM_POLICY_TIMEOUT); + + /* generate scan-done event for caller */ + scnFsmGenerateScanDoneMsg(prAdapter, + prScanParam->eMsgId, prScanParam->ucSeqNum, + prScanParam->ucBssIndex, SCAN_STATUS_DONE); + + /* switch to next pending scan */ + scnFsmSteps(prAdapter, SCAN_STATE_IDLE); + } else { + log_dbg(SCN, INFO, "Unexpected SCAN-DONE event: SeqNum = %d, Current State = %d\n", + prScanDone->ucSeqNum, + prScanInfo->eCurrentState); + } +} /* end of scnEventScanDone */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void +scnFsmGenerateScanDoneMsg(IN struct ADAPTER *prAdapter, + IN enum ENUM_MSG_ID eMsgId, IN uint8_t ucSeqNum, IN uint8_t ucBssIndex, + IN enum ENUM_SCAN_STATUS eScanStatus) +{ + struct SCAN_INFO *prScanInfo; + struct SCAN_PARAM *prScanParam; + struct MSG_SCN_SCAN_DONE *prScanDoneMsg; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + prScanDoneMsg = (struct MSG_SCN_SCAN_DONE *) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(struct MSG_SCN_SCAN_DONE)); + if (!prScanDoneMsg) { + ASSERT(0); /* Can't indicate SCAN FSM Complete */ + return; + } + + switch (eMsgId) { + case MID_AIS_SCN_SCAN_REQ: + case MID_AIS_SCN_SCAN_REQ_V2: + prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_AIS_SCAN_DONE; + break; + case MID_P2P_SCN_SCAN_REQ: + case MID_P2P_SCN_SCAN_REQ_V2: + prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_P2P_SCAN_DONE; + break; + case MID_BOW_SCN_SCAN_REQ: + case MID_BOW_SCN_SCAN_REQ_V2: + prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_BOW_SCAN_DONE; + break; + case MID_RLM_SCN_SCAN_REQ: + case MID_RLM_SCN_SCAN_REQ_V2: + prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_RLM_SCAN_DONE; + break; + default: + log_dbg(SCN, ERROR, "Unexpected Network Type: %d\n"); + cnmMemFree(prAdapter, prScanDoneMsg); + return; + } + + prScanDoneMsg->ucSeqNum = ucSeqNum; + prScanDoneMsg->ucBssIndex = ucBssIndex; + prScanDoneMsg->eScanStatus = eScanStatus; + + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prScanDoneMsg, MSG_SEND_METHOD_BUF); + +} /* end of scnFsmGenerateScanDoneMsg() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Query for most sparse channel + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +u_int8_t scnQuerySparseChannel(IN struct ADAPTER *prAdapter, + enum ENUM_BAND *prSparseBand, uint8_t *pucSparseChannel) +{ + struct SCAN_INFO *prScanInfo; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + if (prScanInfo->fgIsSparseChannelValid == TRUE) { + if (prSparseBand) + *prSparseBand = prScanInfo->rSparseChannel.eBand; + + if (pucSparseChannel) { + *pucSparseChannel + = prScanInfo->rSparseChannel.ucChannelNum; + } + + return TRUE; + } else { + return FALSE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Event handler for schedule scan done event + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void scnEventSchedScanDone(IN struct ADAPTER *prAdapter, + IN struct EVENT_SCHED_SCAN_DONE *prSchedScanDone) +{ + struct SCAN_INFO *prScanInfo; + struct SCHED_SCAN_PARAM *prSchedScanParam; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prSchedScanParam = &prScanInfo->rSchedScanParam; + + if (prScanInfo->fgSchedScanning == TRUE) { + scanlog_dbg(LOG_SCHED_SCAN_DONE_F2D, INFO, "scnEventSchedScanDone seq %u\n", + prSchedScanDone->ucSeqNum); + + kalSchedScanResults(prAdapter->prGlueInfo); + } else { + scanlog_dbg(LOG_SCHED_SCAN_DONE_F2D, INFO, "Unexpected SCHEDSCANDONE event: Seq = %u, Current State = %d\n", + prSchedScanDone->ucSeqNum, prScanInfo->eCurrentState); + } +} + +#if CFG_SUPPORT_SCHED_SCAN +/*----------------------------------------------------------------------------*/ +/*! + * \brief handler for starting schedule scan + * + * \param[in] + * + * \return TRUE if send sched scan successfully. FALSE otherwise + */ +/*----------------------------------------------------------------------------*/ +u_int8_t +scnFsmSchedScanRequest(IN struct ADAPTER *prAdapter, + IN struct PARAM_SCHED_SCAN_REQUEST *prRequest) +{ + struct SCAN_INFO *prScanInfo; + struct SCHED_SCAN_PARAM *prSchedScanParam; + struct CMD_SCHED_SCAN_REQ *prSchedScanCmd = NULL; + struct SSID_MATCH_SETS *prMatchSets = NULL; + struct PARAM_SSID *prSsid = NULL; + uint32_t i; + uint16_t u2IeLen; + enum ENUM_BAND ePreferedChnl = BAND_NULL; + struct BSS_INFO *prAisBssInfo; + + ASSERT(prAdapter); + ASSERT(prRequest); + ASSERT(prRequest->u4SsidNum <= CFG_SCAN_HIDDEN_SSID_MAX_NUM); + ASSERT(prRequest->u4MatchSsidNum <= CFG_SCAN_SSID_MATCH_MAX_NUM); + log_dbg(SCN, TRACE, "scnFsmSchedScanRequest\n"); + + prAisBssInfo = aisGetAisBssInfo(prAdapter, + prRequest->ucBssIndex); + if (prAisBssInfo == NULL) { + log_dbg(SCN, WARN, "prAisBssInfo is NULL\n"); + return FALSE; + } + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prSchedScanParam = &prScanInfo->rSchedScanParam; + + if (prScanInfo->fgSchedScanning) { + log_dbg(SCN, WARN, "prScanInfo->fgSchedScanning = TRUE already scanning\n"); + + return FALSE; + } + + /* 0. allocate memory for schedule scan command */ + if (prRequest->u4IELength <= MAX_IE_LENGTH) + u2IeLen = (uint16_t)prRequest->u4IELength; + else + u2IeLen = MAX_IE_LENGTH; + + prSchedScanCmd = (struct CMD_SCHED_SCAN_REQ *) cnmMemAlloc(prAdapter, + RAM_TYPE_BUF, sizeof(struct CMD_SCHED_SCAN_REQ) + u2IeLen); + if (!prSchedScanCmd) { + log_dbg(SCN, ERROR, "alloc CMD_SCHED_SCAN_REQ (%zu+%u) fail\n", + sizeof(struct CMD_SCHED_SCAN_REQ), u2IeLen); + return FALSE; + } + kalMemZero(prSchedScanCmd, sizeof(struct CMD_SCHED_SCAN_REQ) + u2IeLen); + prMatchSets = &(prSchedScanCmd->auMatchSsid[0]); + prSsid = &(prSchedScanCmd->auSsid[0]); + + /* 1 Set Sched scan param parameters */ + prSchedScanParam->ucSeqNum++; + prSchedScanParam->ucBssIndex = prAisBssInfo->ucBssIndex; + prSchedScanParam->fgStopAfterIndication = FALSE; + + prSchedScanCmd->ucBssIndex = prSchedScanParam->ucBssIndex; + if (!IS_NET_ACTIVE(prAdapter, prAisBssInfo->ucBssIndex)) { + SET_NET_ACTIVE(prAdapter, prAisBssInfo->ucBssIndex); + /* sync with firmware */ + nicActivateNetwork(prAdapter, + prAisBssInfo->ucBssIndex); + } + + /* 2.1 Prepare command. Set FW struct SSID_MATCH_SETS */ + /* ssid in ssid list will be send in probe request in advance */ + prSchedScanCmd->ucSsidNum = prRequest->u4SsidNum; + for (i = 0; i < prSchedScanCmd->ucSsidNum; i++) { + kalMemCopy(&(prSsid[i]), &(prRequest->arSsid[i]), + sizeof(struct PARAM_SSID)); + log_dbg(SCN, TRACE, "ssid set(%d) %s\n", i, + HIDE(prSsid[i].aucSsid)); + } + + prSchedScanCmd->ucMatchSsidNum = prRequest->u4MatchSsidNum; + for (i = 0; i < prSchedScanCmd->ucMatchSsidNum; i++) { + COPY_SSID(prMatchSets[i].aucSsid, prMatchSets[i].ucSsidLen, + prRequest->arMatchSsid[i].aucSsid, + prRequest->arMatchSsid[i].u4SsidLen); + prMatchSets[i].i4RssiThresold = prRequest->ai4RssiThold[i]; + log_dbg(SCN, TRACE, "Match set(%d) %s, rssi>%d\n", + i, prMatchSets[i].aucSsid, + prMatchSets[i].i4RssiThresold); + } + + /* 2.2 Prepare command. Set channel */ + + ePreferedChnl + = prAdapter->aePreferBand[NETWORK_TYPE_AIS]; + if (ePreferedChnl == BAND_2G4) { + prSchedScanCmd->ucChannelType = + SCHED_SCAN_CHANNEL_TYPE_2G4_ONLY; + prSchedScanCmd->ucChnlNum = 0; + } else if (ePreferedChnl == BAND_5G) { + prSchedScanCmd->ucChannelType = + SCHED_SCAN_CHANNEL_TYPE_5G_ONLY; + prSchedScanCmd->ucChnlNum = 0; + } else if (prRequest->ucChnlNum > 0 && + prRequest->ucChnlNum <= MAXIMUM_OPERATION_CHANNEL_LIST) { + prSchedScanCmd->ucChannelType = + SCHED_SCAN_CHANNEL_TYPE_SPECIFIED; + prSchedScanCmd->ucChnlNum = prRequest->ucChnlNum; + for (i = 0; i < prRequest->ucChnlNum; i++) { + prSchedScanCmd->aucChannel[i].ucChannelNum = + prRequest->pucChannels[i]; + prSchedScanCmd->aucChannel[i].ucBand = + (prSchedScanCmd->aucChannel[i].ucChannelNum <= + HW_CHNL_NUM_MAX_2G4) ? BAND_2G4 : BAND_5G; + } + } else { + prSchedScanCmd->ucChnlNum = 0; + prSchedScanCmd->ucChannelType = + SCHED_SCAN_CHANNEL_TYPE_DUAL_BAND; + } + + prSchedScanCmd->ucSeqNum = prSchedScanParam->ucSeqNum; + prSchedScanCmd->fgStopAfterIndication = + prSchedScanParam->fgStopAfterIndication; + prSchedScanCmd->u2IELen = u2IeLen; + prSchedScanCmd->ucVersion = SCHED_SCAN_CMD_VERSION; + if (prSchedScanCmd->u2IELen) { + kalMemCopy(prSchedScanCmd->aucIE, prRequest->pucIE, + prSchedScanCmd->u2IELen); + } + + prSchedScanCmd->ucScnFuncMask |= prRequest->ucScnFuncMask; + + scnSetSchedScanPlan(prAdapter, prSchedScanCmd); + + log_dbg(SCN, INFO, "V(%u)seq(%u)sz(%zu)chT(%u)chN(%u)ssid(%u)match(%u)IE(%u=>%u)MSP(%u)Func(0x%X)\n", + prSchedScanCmd->ucVersion, + prSchedScanCmd->ucSeqNum, sizeof(struct CMD_SCHED_SCAN_REQ), + prSchedScanCmd->ucChannelType, prSchedScanCmd->ucChnlNum, + prSchedScanCmd->ucSsidNum, prSchedScanCmd->ucMatchSsidNum, + prRequest->u4IELength, prSchedScanCmd->u2IELen, + prSchedScanCmd->ucMspEntryNum, + prSchedScanCmd->ucScnFuncMask); + + /* 3. send command packet to FW */ + do { + if (!scnFsmSchedScanSetCmd(prAdapter, prSchedScanCmd)) { + log_dbg(SCN, TRACE, "scnFsmSchedScanSetCmd failed\n"); + break; + } + if (!scnFsmSchedScanSetAction(prAdapter, + SCHED_SCAN_ACT_ENABLE)) { + log_dbg(SCN, TRACE, "scnFsmSchedScanSetAction failed\n"); + break; + } + prScanInfo->fgSchedScanning = TRUE; + } while (0); + + if (!prScanInfo->fgSchedScanning) + nicDeactivateNetwork(prAdapter, + prAisBssInfo->ucBssIndex); + + cnmMemFree(prAdapter, (void *) prSchedScanCmd); + + return prScanInfo->fgSchedScanning; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief handler for stopping scheduled scan + * + * \param[in] + * + * \return TRUE if send stop command successfully. FALSE otherwise + */ +/*----------------------------------------------------------------------------*/ +u_int8_t scnFsmSchedScanStopRequest(IN struct ADAPTER *prAdapter) +{ + uint8_t ucBssIndex = 0; + + ASSERT(prAdapter); + + ucBssIndex = + prAdapter->rWifiVar.rScanInfo.rSchedScanParam.ucBssIndex; + + if (aisGetAisBssInfo(prAdapter, + ucBssIndex) == NULL) { + log_dbg(SCN, WARN, + "prAisBssInfo%d is NULL\n", + ucBssIndex); + return FALSE; + } + + if (!scnFsmSchedScanSetAction(prAdapter, SCHED_SCAN_ACT_DISABLE)) { + log_dbg(SCN, TRACE, "scnFsmSchedScanSetAction failed\n"); + return FALSE; + } + + prAdapter->rWifiVar.rScanInfo.fgSchedScanning = FALSE; + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief handler for setting schedule scan action + * \param prAdapter adapter + * \param ucSchedScanAct schedule scan action. set enable/disable to FW + * + * \return TRUE if send query command successfully. FALSE otherwise + */ +/*----------------------------------------------------------------------------*/ +u_int8_t +scnFsmSchedScanSetAction(IN struct ADAPTER *prAdapter, + IN enum ENUM_SCHED_SCAN_ACT ucSchedScanAct) +{ + struct CMD_SET_SCHED_SCAN_ENABLE rCmdSchedScanAction; + uint32_t rStatus; + + ASSERT(prAdapter); + + kalMemZero(&rCmdSchedScanAction, + sizeof(struct CMD_SET_SCHED_SCAN_ENABLE)); + + /* 0:enable, 1:disable */ + rCmdSchedScanAction.ucSchedScanAct = ucSchedScanAct; + + if (ucSchedScanAct == SCHED_SCAN_ACT_ENABLE) { + scanlog_dbg(LOG_SCHED_SCAN_REQ_START_D2F, INFO, "sched scan action = %d\n", + rCmdSchedScanAction.ucSchedScanAct); + } else { + scanlog_dbg(LOG_SCHED_SCAN_REQ_STOP_D2F, INFO, "sched scan action = %d\n", + rCmdSchedScanAction.ucSchedScanAct); + } + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_SCAN_SCHED_ENABLE, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_SET_SCHED_SCAN_ENABLE), + (uint8_t *)&rCmdSchedScanAction, NULL, 0); + + return (rStatus != WLAN_STATUS_FAILURE) ? TRUE : FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief handler for setting schedule scan command + * \param prAdapter adapter + * \param prSchedScanCmd schedule scan command + * + * \return TRUE if send query command successfully. + * FAIL otherwise + */ +/*----------------------------------------------------------------------------*/ +u_int8_t +scnFsmSchedScanSetCmd(IN struct ADAPTER *prAdapter, + IN struct CMD_SCHED_SCAN_REQ *prSchedScanCmd) +{ + uint16_t u2IeSize = 0; + uint32_t rStatus; + + ASSERT(prAdapter); + + log_dbg(SCN, TRACE, "--> %s()\n", __func__); + + if (prSchedScanCmd) + u2IeSize = prSchedScanCmd->u2IELen; + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_SCAN_SCHED_REQ, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_SCHED_SCAN_REQ) + u2IeSize, + (uint8_t *) prSchedScanCmd, NULL, 0); + + return (rStatus != WLAN_STATUS_FAILURE) ? TRUE : FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Set schedule scan multiple scan plan (scan interval) + * \param prAdapter adapter + * \param prSchedScanCmd schedule scan command request + * + * \return void + */ +/*----------------------------------------------------------------------------*/ +void +scnSetSchedScanPlan(IN struct ADAPTER *prAdapter, + IN struct CMD_SCHED_SCAN_REQ *prSchedScanCmd) +{ + /* Set Multiple Scan Plan here */ + log_dbg(SCN, TRACE, "--> %s()\n", __func__); + + ASSERT(prAdapter); + + prSchedScanCmd->ucMspEntryNum = 0; + kalMemZero(prSchedScanCmd->au2MspList, + sizeof(prSchedScanCmd->au2MspList)); +} + +#endif /* CFG_SUPPORT_SCHED_SCAN */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/stats.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/stats.c new file mode 100644 index 0000000000000..e53cfe234cc60 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/stats.c @@ -0,0 +1,809 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License version 2 as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. + * If not, see . + */ + +/******************************************************************************* + * C O M P I L E 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_STATISTICS == 1) + +enum EVENT_TYPE { + EVENT_RX, + EVENT_TX, +}; +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E F U N C T I O N S + ******************************************************************************* + */ + +uint32_t u4TotalTx; +uint32_t u4NoDelayTx; +uint32_t u4TotalRx; +uint32_t u4NoDelayRx; + +static uint8_t g_ucTxRxFlag; +static uint8_t g_ucTxIpProto; +static uint16_t g_u2TxUdpPort; +static uint32_t g_u4TxDelayThreshold; +static uint8_t g_ucRxIpProto; +static uint16_t g_u2RxUdpPort; +static uint32_t g_u4RxDelayThreshold; + +void StatsResetTxRx(void) +{ + u4TotalRx = 0; + u4TotalTx = 0; + u4NoDelayRx = 0; + u4NoDelayTx = 0; +} + +uint64_t StatsEnvTimeGet(void) +{ + uint64_t u8Clk; + + u8Clk = sched_clock(); /* unit: naro seconds */ + + return (uint64_t) u8Clk; /* sched_clock *//* jiffies size = 4B */ +} + +void StatsEnvGetPktDelay(OUT uint8_t *pucTxRxFlag, + OUT uint8_t *pucTxIpProto, OUT uint16_t *pu2TxUdpPort, + OUT uint32_t *pu4TxDelayThreshold, OUT uint8_t *pucRxIpProto, + OUT uint16_t *pu2RxUdpPort, OUT uint32_t *pu4RxDelayThreshold) +{ + *pucTxRxFlag = g_ucTxRxFlag; + *pucTxIpProto = g_ucTxIpProto; + *pu2TxUdpPort = g_u2TxUdpPort; + *pu4TxDelayThreshold = g_u4TxDelayThreshold; + *pucRxIpProto = g_ucRxIpProto; + *pu2RxUdpPort = g_u2RxUdpPort; + *pu4RxDelayThreshold = g_u4RxDelayThreshold; +} + +void StatsEnvSetPktDelay(IN uint8_t ucTxOrRx, IN uint8_t ucIpProto, + IN uint16_t u2UdpPort, uint32_t u4DelayThreshold) +{ +#define MODULE_RESET 0 +#define MODULE_TX 1 +#define MODULE_RX 2 + + if (ucTxOrRx == MODULE_TX) { + g_ucTxRxFlag |= BIT(0); + g_ucTxIpProto = ucIpProto; + g_u2TxUdpPort = u2UdpPort; + g_u4TxDelayThreshold = u4DelayThreshold; + } else if (ucTxOrRx == MODULE_RX) { + g_ucTxRxFlag |= BIT(1); + g_ucRxIpProto = ucIpProto; + g_u2RxUdpPort = u2UdpPort; + g_u4RxDelayThreshold = u4DelayThreshold; + } else if (ucTxOrRx == MODULE_RESET) { + g_ucTxRxFlag = 0; + g_ucTxIpProto = 0; + g_u2TxUdpPort = 0; + g_u4TxDelayThreshold = 0; + g_ucRxIpProto = 0; + g_u2RxUdpPort = 0; + g_u4RxDelayThreshold = 0; + } +} + +void StatsEnvRxTime2Host(IN struct ADAPTER *prAdapter, struct sk_buff *prSkb) +{ + uint8_t *pucEth = prSkb->data; + uint16_t u2EthType = 0; + uint8_t ucIpVersion = 0; + uint8_t ucIpProto = 0; + uint16_t u2IPID = 0; + uint16_t u2UdpDstPort = 0; + uint16_t u2UdpSrcPort = 0; + uint64_t u8IntTime = 0; + uint64_t u8RxTime = 0; + uint32_t u4Delay = 0; + struct timeval tval; + struct rtc_time tm; + + u2EthType = (pucEth[ETH_TYPE_LEN_OFFSET] << 8) + | (pucEth[ETH_TYPE_LEN_OFFSET + 1]); + pucEth += ETH_HLEN; + u2IPID = pucEth[4] << 8 | pucEth[5]; + + DBGLOG(RX, LOUD, "StatsEnvRxTime2Host: u2IpId after:%d\n", u2IPID); + + if ((g_ucTxRxFlag & BIT(1)) == 0) + return; + if (prSkb->len <= 24 + ETH_HLEN) + return; + if (u2EthType != ETH_P_IPV4) + return; + ucIpProto = pucEth[9]; + if (g_ucRxIpProto && (ucIpProto != g_ucRxIpProto)) + return; + ucIpVersion = (pucEth[0] & IPVH_VERSION_MASK) >> IPVH_VERSION_OFFSET; + if (ucIpVersion != IPVERSION) + return; + u2IPID = pucEth[4] << 8 | pucEth[5]; + u8IntTime = GLUE_RX_GET_PKT_INT_TIME(prSkb); + u4Delay = ((uint32_t)(sched_clock() - u8IntTime))/NSEC_PER_USEC; + u8RxTime = GLUE_RX_GET_PKT_RX_TIME(prSkb); + do_gettimeofday(&tval); + rtc_time_to_tm(tval.tv_sec, &tm); + + switch (ucIpProto) { + case IP_PRO_TCP: + case IP_PRO_UDP: + u2UdpSrcPort = (pucEth[20] << 8) | pucEth[21]; + u2UdpDstPort = (pucEth[22] << 8) | pucEth[23]; + if (g_u2RxUdpPort && (u2UdpSrcPort != g_u2RxUdpPort)) + break; + case IP_PRO_ICMP: + u4TotalRx++; + if (g_u4RxDelayThreshold && (u4Delay <= g_u4RxDelayThreshold)) { + u4NoDelayRx++; + break; + } + DBGLOG(RX, INFO, + "IPID 0x%04x src %d dst %d UP %d,delay %u us,int2rx %lu us,IntTime %llu,%u/%u,leave at %02d:%02d:%02d.%06ld\n", + u2IPID, u2UdpSrcPort, u2UdpDstPort, + ((pucEth[1] & IPTOS_PREC_MASK) >> IPTOS_PREC_OFFSET), + u4Delay, + ((uint32_t)(u8RxTime - u8IntTime))/NSEC_PER_USEC, + u8IntTime, u4NoDelayRx, u4TotalRx, + tm.tm_hour, tm.tm_min, tm.tm_sec, tval.tv_usec); + break; + default: + break; + } +} + +void StatsEnvTxTime2Hif(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + uint64_t u8SysTime, u8SysTimeIn; + uint32_t u4TimeDiff; + uint8_t *pucEth; + uint32_t u4PacketLen; + uint8_t ucIpVersion = 0; + uint8_t ucIpProto = 0; + uint8_t *pucEthBody = NULL; + uint16_t u2EthType = 0; + uint8_t *pucAheadBuf = NULL; + uint16_t u2IPID = 0; + uint16_t u2UdpDstPort = 0; + uint16_t u2UdpSrcPort = 0; + + if (prMsduInfo == NULL) { + DBGLOG(TX, ERROR, "prMsduInfo=NULL"); + return; + } + + if (prMsduInfo->prPacket == NULL) { + DBGLOG(TX, ERROR, "prMsduInfo->prPacket=NULL"); + return; + } + + kalTraceEvent("Move id=0x%04x sn=%d", + GLUE_GET_PKT_IP_ID(prMsduInfo->prPacket), + GLUE_GET_PKT_SEQ_NO(prMsduInfo->prPacket)); + + pucEth = ((struct sk_buff *)prMsduInfo->prPacket)->data; + + if (pucEth == NULL) { + DBGLOG(TX, ERROR, "pucEth=NULL"); + return; + } + + u4PacketLen = ((struct sk_buff *)prMsduInfo->prPacket)->len; + + u8SysTime = StatsEnvTimeGet(); + u8SysTimeIn = GLUE_GET_PKT_XTIME(prMsduInfo->prPacket); + + if ((g_ucTxRxFlag & BIT(0)) == 0) + return; + + if ((u8SysTimeIn == 0) || (u8SysTime <= u8SysTimeIn)) + return; + + /* units of u4TimeDiff is micro seconds (us) */ + if (u4PacketLen < 24 + ETH_HLEN) + return; + pucAheadBuf = &pucEth[76]; + u2EthType = (pucAheadBuf[ETH_TYPE_LEN_OFFSET] << 8) + | (pucAheadBuf[ETH_TYPE_LEN_OFFSET + 1]); + pucEthBody = &pucAheadBuf[ETH_HLEN]; + if (u2EthType != ETH_P_IPV4) + return; + ucIpProto = pucEthBody[9]; + if (g_ucTxIpProto && (ucIpProto != g_ucTxIpProto)) + return; + ucIpVersion = (pucEthBody[0] & IPVH_VERSION_MASK) + >> IPVH_VERSION_OFFSET; + if (ucIpVersion != IPVERSION) + return; + u2IPID = pucEthBody[4]<<8 | pucEthBody[5]; + u8SysTime = u8SysTime - u8SysTimeIn; + u4TimeDiff = (uint32_t) u8SysTime; + u4TimeDiff = u4TimeDiff / 1000; /* ns to us */ + + switch (ucIpProto) { + case IP_PRO_TCP: + case IP_PRO_UDP: + u2UdpDstPort = (pucEthBody[22] << 8) | pucEthBody[23]; + u2UdpSrcPort = (pucEthBody[20] << 8) | pucEthBody[21]; + if (g_u2TxUdpPort && (u2UdpDstPort != g_u2TxUdpPort)) + break; + case IP_PRO_ICMP: + u4TotalTx++; + if (g_u4TxDelayThreshold + && (u4TimeDiff <= g_u4TxDelayThreshold)) { + u4NoDelayTx++; + break; + } + DBGLOG(TX, INFO, + "IPID 0x%04x src %d dst %d UP %d,delay %u us,u8SysTimeIn %llu, %u/%u\n", + u2IPID, u2UdpSrcPort, u2UdpDstPort, + ((pucEthBody[1] & IPTOS_PREC_MASK) + >> IPTOS_PREC_OFFSET), + u4TimeDiff, u8SysTimeIn, u4NoDelayTx, u4TotalTx); + break; + default: + break; + } +} + +void statsParseARPInfo(struct sk_buff *skb, + uint8_t *pucEthBody, uint8_t eventType) +{ + uint16_t u2OpCode = (pucEthBody[6] << 8) | pucEthBody[7]; + + switch (eventType) { + case EVENT_RX: + GLUE_SET_INDEPENDENT_PKT(skb, TRUE); + if (u2OpCode == ARP_PRO_REQ) + DBGLOG(RX, INFO, + " Arp Req From IP: %d.%d.%d.%d\n", + pucEthBody[14], pucEthBody[15], + pucEthBody[16], pucEthBody[17]); + else if (u2OpCode == ARP_PRO_RSP) + DBGLOG(RX, INFO, + " Arp Rsp from IP: %d.%d.%d.%d\n", + pucEthBody[14], pucEthBody[15], + pucEthBody[16], pucEthBody[17]); + break; + case EVENT_TX: + DBGLOG(TX, INFO, + "ARP %s SRC MAC/IP[" + MACSTR "]/[" IPV4STR "], TAR MAC/IP[" + MACSTR "]/[" IPV4STR "], SeqNo: %d\n", + u2OpCode == ARP_OPERATION_REQUEST ? "REQ" : "RSP", + MAC2STR(&pucEthBody[ARP_SENDER_MAC_OFFSET]), + IPV4TOSTR(&pucEthBody[ARP_SENDER_IP_OFFSET]), + MAC2STR(&pucEthBody[ARP_TARGET_MAC_OFFSET]), + IPV4TOSTR(&pucEthBody[ARP_TARGET_IP_OFFSET]), + GLUE_GET_PKT_SEQ_NO(skb)); + break; + } +} + +void statsParseUDPInfo(struct sk_buff *skb, uint8_t *pucEthBody, + uint8_t eventType, uint16_t u2IpId) +{ + /* the number of DHCP packets is seldom so we print log here */ + uint8_t *pucUdp = &pucEthBody[20]; + uint8_t *pucBootp = &pucUdp[UDP_HDR_LEN]; + struct BOOTP_PROTOCOL *prBootp = NULL; + uint16_t u2UdpDstPort; + uint16_t u2UdpSrcPort; + uint32_t u4TransID; + uint32_t u4DhcpMagicCode; + char buf[50] = {0}; + + prBootp = (struct BOOTP_PROTOCOL *) &pucUdp[UDP_HDR_LEN]; + u2UdpDstPort = (pucUdp[2] << 8) | pucUdp[3]; + u2UdpSrcPort = (pucUdp[0] << 8) | pucUdp[1]; + if (u2UdpDstPort == UDP_PORT_DHCPS || u2UdpDstPort == UDP_PORT_DHCPC) { + WLAN_GET_FIELD_BE32(&prBootp->u4TransId, &u4TransID); + switch (eventType) { + case EVENT_RX: + GLUE_SET_INDEPENDENT_PKT(skb, TRUE); + + WLAN_GET_FIELD_BE32(&prBootp->aucOptions[0], + &u4DhcpMagicCode); + if (u4DhcpMagicCode == DHCP_MAGIC_NUMBER) { + uint32_t u4Opt; + + WLAN_GET_FIELD_BE32(&prBootp->aucOptions[4], + &u4Opt); + switch (u4Opt & 0xffffff00) { + case 0x35010100: + kalSnprintf(buf, 49, "DISCOVERY"); + break; + case 0x35010200: + kalSnprintf(buf, 49, "OFFER"); + break; + case 0x35010300: + kalSnprintf(buf, 49, "REQUEST"); + break; + case 0x35010500: + kalSnprintf(buf, 49, "ACK"); + break; + case 0x35010600: + kalSnprintf(buf, 49, "NAK"); + break; + } + } + DBGLOG_LIMITED(RX, INFO, + " DHCP: Recv %s IPID 0x%02x, MsgType 0x%x, TransID 0x%04x\n", + buf, u2IpId, prBootp->aucOptions[6], + u4TransID); + break; + case EVENT_TX: + { + uint32_t u4Xid = 0; + uint32_t u4Opt = 0; + + WLAN_GET_FIELD_BE32(&prBootp->aucOptions[0], + &u4DhcpMagicCode); + if (u4DhcpMagicCode == DHCP_MAGIC_NUMBER) { + WLAN_GET_FIELD_BE32(&prBootp->u4TransId, + &u4Xid); + WLAN_GET_FIELD_BE32(&prBootp->aucOptions[4], + &u4Opt); + + switch (u4Opt & 0xffffff00) { + case 0x35010100: + kalSnprintf(buf, 49, + "client DISCOVERY"); + break; + case 0x35010200: + kalSnprintf(buf, 49, "server OFFER"); + break; + case 0x35010300: + kalSnprintf(buf, 49, "client REQUEST"); + break; + case 0x35010500: + kalSnprintf(buf, 49, "server ACK"); + break; + case 0x35010600: + kalSnprintf(buf, 49, "server NAK"); + break; + } + } + + DBGLOG_LIMITED(TX, INFO, + " DHCP %s, XID[0x%08x] OPT[0x%08x] TYPE[%u], SeqNo: %d\n", + buf, u4Xid, u4Opt, prBootp->aucOptions[6], + GLUE_GET_PKT_SEQ_NO(skb)); + } + break; + } + } else if (u2UdpSrcPort == UDP_PORT_DNS) { /* tx dns */ + uint16_t u2TransId = + (pucBootp[0] << 8) | pucBootp[1]; + if (eventType == EVENT_RX) { + GLUE_SET_INDEPENDENT_PKT(skb, TRUE); + DBGLOG_LIMITED(RX, INFO, + " DNS: IPID 0x%02x, TransID 0x%04x\n", + u2IpId, u2TransId); + } else if (eventType == EVENT_TX) { + DBGLOG_LIMITED(TX, INFO, + " DNS: IPID[0x%02x] TransID[0x%04x] SeqNo[%d]\n", + u2IpId, u2TransId, GLUE_GET_PKT_SEQ_NO(skb)); + } + } +} + +void statsParseIPV4Info(struct sk_buff *skb, + uint8_t *pucEthBody, uint8_t eventType) +{ + /* IP header without options */ + uint8_t ucIpProto = pucEthBody[9]; + uint8_t ucIpVersion = + (pucEthBody[0] & IPVH_VERSION_MASK) + >> IPVH_VERSION_OFFSET; + uint16_t u2IpId = GLUE_GET_PKT_IP_ID(skb); + + if (ucIpVersion != IPVERSION) + return; + switch (ucIpProto) { + case IP_PRO_ICMP: + { + /* the number of ICMP packets is seldom so we print log here */ + uint8_t ucIcmpType; + uint16_t u2IcmpId, u2IcmpSeq; + uint8_t *pucIcmp = &pucEthBody[20]; + + ucIcmpType = pucIcmp[0]; + /* don't log network unreachable packet */ + if (ucIcmpType == 3) + break; + u2IcmpId = *(uint16_t *) &pucIcmp[4]; + u2IcmpSeq = *(uint16_t *) &pucIcmp[6]; + switch (eventType) { + case EVENT_RX: + GLUE_SET_INDEPENDENT_PKT(skb, TRUE); + DBGLOG_LIMITED(RX, INFO, + " ICMP: Type %d, Id BE 0x%04x, Seq BE 0x%04x\n", + ucIcmpType, u2IcmpId, u2IcmpSeq); + break; + case EVENT_TX: + DBGLOG_LIMITED(TX, INFO, + " ICMP: IPID[0x%04x] Type %d, Id 0x%04x, Seq BE 0x%04x, SeqNo: %d\n", + u2IpId, ucIcmpType, u2IcmpId, u2IcmpSeq, + GLUE_GET_PKT_SEQ_NO(skb)); + break; + } + break; + } + case IP_PRO_UDP: + statsParseUDPInfo(skb, pucEthBody, eventType, u2IpId); + } +} + +void statsLogData(uint8_t eventType, enum WAKE_DATA_TYPE wakeType) +{ + if (eventType == EVENT_TX) + wlanLogTxData(wakeType); + else if (eventType == EVENT_RX) + wlanLogRxData(wakeType); +} + +static void statsParsePktInfo(uint8_t *pucPkt, struct sk_buff *skb, + uint8_t status, uint8_t eventType) +{ + /* get ethernet protocol */ + uint16_t u2EtherType = + (pucPkt[ETH_TYPE_LEN_OFFSET] << 8) + | (pucPkt[ETH_TYPE_LEN_OFFSET + 1]); + uint8_t *pucEthBody = &pucPkt[ETH_HLEN]; + + switch (u2EtherType) { + case ETH_P_ARP: + { + statsLogData(eventType, WLAN_WAKE_ARP); + statsParseARPInfo(skb, pucEthBody, eventType); + break; + } + case ETH_P_IPV4: + { + statsLogData(eventType, WLAN_WAKE_IPV4); + statsParseIPV4Info(skb, pucEthBody, eventType); + break; + } + case ETH_P_IPV6: + { + /* IPv6 header without options */ + uint8_t ucIpv6Proto = + pucEthBody[IPV6_HDR_PROTOCOL_OFFSET]; + uint8_t ucIpVersion = + (pucEthBody[0] & IPVH_VERSION_MASK) + >> IPVH_VERSION_OFFSET; + + if (ucIpVersion != IP_VERSION_6) + break; + + statsLogData(eventType, WLAN_WAKE_IPV6); + switch (ucIpv6Proto) { + case 0x06:/*tcp*/ + switch (eventType) { + case EVENT_RX: + DBGLOG(RX, TRACE, " tcp packet\n"); + break; + case EVENT_TX: + DBGLOG(TX, TRACE, " tcp packet\n"); + break; + } + break; + + case 0x11:/*UDP*/ + switch (eventType) { + case EVENT_RX: + { + uint16_t ucIpv6UDPSrcPort = 0; + + /* IPv6 header without options */ + ucIpv6UDPSrcPort = pucEthBody[IPV6_HDR_LEN]; + ucIpv6UDPSrcPort = ucIpv6UDPSrcPort << 8; + ucIpv6UDPSrcPort += + pucEthBody[IPV6_HDR_LEN + 1]; + + switch (ucIpv6UDPSrcPort) { + case 53:/*dns port*/ + DBGLOG(RX, TRACE, + " dns packet\n"); + GLUE_SET_INDEPENDENT_PKT(skb, TRUE); + break; + case 547:/*dhcp*/ + case 546: + DBGLOG(RX, INFO, + " dhcp packet\n"); + GLUE_SET_INDEPENDENT_PKT(skb, TRUE); + break; + case 123:/*ntp port*/ + DBGLOG(RX, INFO, + " ntp packet\n"); + GLUE_SET_INDEPENDENT_PKT(skb, TRUE); + break; + default: + DBGLOG(RX, TRACE, + " other packet srtport=%u\n", + ucIpv6UDPSrcPort); + break; + } + } + break; + case EVENT_TX: + DBGLOG(TX, INFO, " UDP packet\n"); + break; + } + break; + + case 0x00:/*IPv6 hop-by-hop*/ + switch (eventType) { + case EVENT_RX: + /*need chech detai pakcet type*/ + /*130 mlti listener query*/ + /*143 multi listener report v2*/ + GLUE_SET_INDEPENDENT_PKT(skb, TRUE); + + DBGLOG(RX, INFO, + " hop-by-hop packet\n"); + break; + case EVENT_TX: + DBGLOG(TX, INFO, + " hop-by-hop packet\n"); + break; + } + break; + + case 0x3a:/*ipv6 ICMPV6*/ + switch (eventType) { + case EVENT_RX: + { + uint8_t ucICMPv6Type = 0; + + /* IPv6 header without options */ + ucICMPv6Type = pucEthBody[IPV6_HDR_LEN]; + GLUE_SET_INDEPENDENT_PKT(skb, TRUE); + + switch (ucICMPv6Type) { + case 0x85: /*ICMPV6_TYPE_ROUTER_SOLICITATION*/ + DBGLOG_LIMITED(RX, INFO, + " ICMPV6 Router Solicitation\n"); + break; + + case 0x86: /*ICMPV6_TYPE_ROUTER_ADVERTISEMENT*/ + DBGLOG_LIMITED(RX, INFO, + " ICMPV6 Router Advertisement\n"); + break; + + case ICMPV6_TYPE_NEIGHBOR_SOLICITATION: + DBGLOG_LIMITED(RX, INFO, + " ICMPV6 Neighbor Solicitation\n"); + break; + + case ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT: + DBGLOG_LIMITED(RX, INFO, + " ICMPV6 Neighbor Advertisement\n"); + break; + default: + DBGLOG_LIMITED(RX, INFO, + " ICMPV6 type=%u\n", + ucICMPv6Type); + break; + } + } + break; + case EVENT_TX: + DBGLOG_LIMITED(TX, INFO, + " ICMPV6 packet\n"); + break; + } + break; + default: + if (eventType == EVENT_RX) + DBGLOG(RX, INFO, + " default protocol=%u\n", + ucIpv6Proto); + break; + } + break; + } + case ETH_P_1X: + { + uint8_t *pucEapol = pucEthBody; + uint8_t ucEapolType = pucEapol[1]; + uint16_t u2KeyInfo = 0; + uint8_t m = 0; + + statsLogData(eventType, WLAN_WAKE_1X); + switch (ucEapolType) { + case 0: /* eap packet */ + switch (eventType) { + case EVENT_RX: + DBGLOG(RX, INFO, + " EAP Packet: code %d, id %d, type %d\n", + pucEapol[4], pucEapol[5], pucEapol[7]); + break; + case EVENT_TX: + DBGLOG(TX, INFO, + " EAP Packet: code %d, id %d, type %d, SeqNo: %d\n", + pucEapol[4], pucEapol[5], pucEapol[7], + GLUE_GET_PKT_SEQ_NO(skb)); + break; + } + break; + case 1: /* eapol start */ + switch (eventType) { + case EVENT_RX: + DBGLOG(RX, INFO, + " EAPOL: start\n"); + break; + case EVENT_TX: + DBGLOG(TX, INFO, + " EAPOL: start, SeqNo: %d\n", + GLUE_GET_PKT_SEQ_NO(skb)); + break; + } + break; + case ETH_EAPOL_KEY: /* key */ + WLAN_GET_FIELD_BE16(&pucEapol[5], &u2KeyInfo); + switch (eventType) { + case EVENT_RX: + if ((u2KeyInfo & 0xfff0) == 0x0080) + m = 1; + else if ((u2KeyInfo & 0xfff0) == 0x13c0) + m = 3; + DBGLOG(RX, INFO, + " EAPOL: key, M%d, KeyInfo 0x%04x\n", + m, u2KeyInfo); + break; + case EVENT_TX: + if ((u2KeyInfo & 0xfff0) == 0x0100) + m = 2; + else if ((u2KeyInfo & 0xfff0) == 0x0300) + m = 4; + DBGLOG(TX, INFO, + " EAPOL: key, M%d, KeyInfo 0x%04x SeqNo: %d\n", + m, u2KeyInfo, GLUE_GET_PKT_SEQ_NO(skb)); + break; + } + break; + } + break; + } +#if CFG_SUPPORT_WAPI + case ETH_WPI_1X: + { + uint8_t ucSubType = pucEthBody[3]; /* sub type filed*/ + uint16_t u2Length = *(uint16_t *)&pucEthBody[6]; + uint16_t u2Seq = *(uint16_t *)&pucEthBody[8]; + + statsLogData(eventType, WLAN_WAKE_1X); + switch (eventType) { + case EVENT_RX: + DBGLOG(RX, INFO, + " WAPI: subType %d, Len %d, Seq %d\n", + ucSubType, u2Length, u2Seq); + break; + case EVENT_TX: + DBGLOG(TX, INFO, + " WAPI: subType %d, Len %d, Seq %d, SeqNo: %d\n", + ucSubType, u2Length, u2Seq, + GLUE_GET_PKT_SEQ_NO(skb)); + break; + } + break; + } +#endif + case ETH_PRO_TDLS: + statsLogData(eventType, WLAN_WAKE_TDLS); + switch (eventType) { + case EVENT_RX: + DBGLOG(RX, INFO, + " TDLS type %d, category %d, Action %d, Token %d\n", + pucEthBody[0], pucEthBody[1], + pucEthBody[2], pucEthBody[3]); + break; + case EVENT_TX: + DBGLOG(TX, INFO, + " TDLS type %d, category %d, Action %d, Token %d\n", + pucEthBody[0], pucEthBody[1], + pucEthBody[2], pucEthBody[3]); + break; + } + break; + default: + statsLogData(eventType, WLAN_WAKE_OTHER); + break; + } +} +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to display rx packet information. + * + * \param[in] pPkt Pointer to the packet + * \param[out] None + * + * \retval None + */ +/*----------------------------------------------------------------------------*/ +void StatsRxPktInfoDisplay(struct SW_RFB *prSwRfb) +{ + uint8_t *pPkt = NULL; + struct sk_buff *skb = NULL; + + if (prSwRfb->u2PacketLen <= ETHER_HEADER_LEN) + return; + + pPkt = prSwRfb->pvHeader; + if (!pPkt) + return; + + skb = (struct sk_buff *)(prSwRfb->pvPacket); + if (!skb) + return; + + statsParsePktInfo(pPkt, skb, 0, EVENT_RX); + + kalTraceEvent("Pkt id=0x%04x sn=%d", + GLUE_GET_PKT_IP_ID(skb), + GLUE_GET_PKT_SEQ_NO(skb)); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to display tx packet information. + * + * \param[in] pPkt Pointer to the packet + * \param[out] None + * + * \retval None + */ +/*----------------------------------------------------------------------------*/ +void StatsTxPktInfoDisplay(struct sk_buff *prSkb) +{ + uint8_t *pPkt; + + pPkt = prSkb->data; + statsParsePktInfo(pPkt, prSkb, 0, EVENT_TX); +} + +#endif /* CFG_SUPPORT_STATISTICS */ + +/* End of stats.c */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/swcr.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/swcr.c new file mode 100644 index 0000000000000..e7b3121958235 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/swcr.c @@ -0,0 +1,1470 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/swcr.c#1 + */ + +/*! \file "swcr.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" +#include "swcr.h" + +#if CFG_SUPPORT_SWCR + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +uint32_t g_au4SwCr[SWCR_CR_NUM]; /*: 0: command other: data */ + +/* JB mDNS Filter*/ +uint32_t g_u4RXFilter; /* [31] 0: stop 1: start, [3] IPv6 [2] IPv4 */ + +static struct TIMER g_rSwcrDebugTimer; +static u_int8_t g_fgSwcrDebugTimer = FALSE; +static uint32_t g_u4SwcrDebugCheckTimeout; +static enum ENUM_SWCR_DBG_TYPE g_ucSwcrDebugCheckType; +static uint32_t g_u4SwcrDebugFrameDumpType; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +static const PFN_CMD_RW_T g_arSwCtrlCmd[] = { + swCtrlCmdCategory0, + swCtrlCmdCategory1 +#if TEST_PS + , testPsCmdCategory0, testPsCmdCategory1 +#endif +#if CFG_SUPPORT_802_11V +#if (CFG_SUPPORT_802_11V_TIMING_MEASUREMENT == 1) && (WNM_UNIT_TEST == 1) + , testWNMCmdCategory0 +#endif +#endif +}; + +const PFN_SWCR_RW_T g_arSwCrModHandle[] = { + swCtrlSwCr, + NULL +}; + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +enum { + SWCTRL_MAGIC, + SWCTRL_DEBUG, + SWCTRL_WIFI_VAR, + SWCTRL_ENABLE_INT, + SWCTRL_DISABLE_INT, + SWCTRL_TXM_INFO, + SWCTRL_RXM_INFO, + SWCTRL_DUMP_BSS, + SWCTRL_QM_INFO, + SWCTRL_DUMP_ALL_QUEUE_LEN, + SWCTRL_DUMP_MEM, + SWCTRL_TX_CTRL_INFO, + SWCTRL_DUMP_QUEUE, + SWCTRL_DUMP_QM_DBG_CNT, + SWCTRL_QM_DBG_CNT, + SWCTRL_RX_PKTS_DUMP, + SWCTRL_RX_FILTER, +#if CFG_INIT_ENABLE_PATTERN_FILTER_ARP + SWCTRL_RX_ARP_OFFLOAD, +#endif + SWCTRL_PS_DTIM_SKIP, + SWCTRL_ROAMING, + SWCTRL_CATA0_INDEX_NUM +}; + +enum { + SWCTRL_STA_INFO, + SWCTRL_DUMP_STA, + SWCTRL_STA_QUE_INFO, + SWCTRL_CATA1_INDEX_NUM +}; + +/* JB mDNS Filter*/ +#define RX_FILTER_START (1<<31) +#define RX_FILTER_IPV4 (1<<2) +#define RX_FILTER_IPV6 (1<<3) +enum ENUM_SWCR_RX_FILTER_CMD { + SWCR_RX_FILTER_CMD_STOP = 0, + SWCR_RX_FILTER_CMD_START, + SWCR_RX_FILTER_CMD_ADD, + SWCR_RX_FILTER_CMD_REMOVE, + SWCR_RX_FILTER_NUM +}; + +#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(struct ADAPTER *prAdapter) +{ + + struct TX_CTRL *prTxCtrl; + struct QUE_MGT *prQM; + struct GLUE_INFO *prGlueInfo; + uint32_t i; + uint32_t j; + + DEBUGFUNC("dumpQueue"); + + prTxCtrl = &prAdapter->rTxCtrl; + prQM = &prAdapter->rQM; + prGlueInfo = prAdapter->prGlueInfo; +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + for (i = TC0_INDEX; i < TC_NUM; i++) { + DBGLOG(SW4, INFO, "TC %u\n", i); + DBGLOG(SW4, INFO, "Max %u Free %u\n", + prTxCtrl->rTc.au4MaxNumOfBuffer[i], + prTxCtrl->rTc.au4FreeBufferCount[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]); + + } +#endif + +#if QM_FORWARDING_FAIRNESS + 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->au4ResourceUsedCount[i]); + } +#endif + + 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(struct ADAPTER *prAdapter, struct STA_RECORD *prStaRec) +{ + uint8_t ucWTEntry; + uint32_t i; + struct BSS_INFO *prBssInfo; + + DEBUGFUNC("dumpSTA"); + + ASSERT(prStaRec); + ucWTEntry = prStaRec->ucWlanIndex; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + 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->aprTargetQueue[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(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo) +{ + + DBGLOG(SW4, INFO, "SSID %s\n", HIDE(prBssInfo->aucSSID)); + DBGLOG(SW4, INFO, "OWN " MACSTR "\n", + MAC2STR(prBssInfo->aucOwnMacAddr)); + DBGLOG(SW4, INFO, "BSSID " MACSTR "\n", + MAC2STR(prBssInfo->aucBSSID)); + DBGLOG(SW4, INFO, "eNetworkType %u\n", + prBssInfo->eNetworkType); + DBGLOG(SW4, INFO, "ucBssIndex %u\n", prBssInfo->ucBssIndex); + 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(struct ADAPTER *prAdapter, + uint8_t ucCate, uint8_t ucAction, uint8_t ucOpt0, + uint8_t ucOpt1) +{ + uint8_t ucIndex, ucRead; + uint32_t i; + struct CMD_RX_PACKET_FILTER rSetRxPacketFilter; + + 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: + 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: + prAdapter->rRxCtrl.u4RxPktsDumpTypeMask = g_au4SwCr[1]; + break; +#endif + case SWCTRL_RX_FILTER: { + uint32_t u4rxfilter; + u_int8_t fgUpdate = FALSE; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + if (ucOpt0 == SWCR_RX_FILTER_CMD_STOP) { + g_u4RXFilter &= ~(RX_FILTER_START); + /* changed by jeffrey to align + * Android behavior + */ +#if 0 + if (prAdapter->fgAllMulicastFilter == FALSE) + prAdapter->u4OsPacketFilter &= + ~PARAM_PACKET_FILTER_ALL_MULTICAST; +#endif + prAdapter->u4OsPacketFilter &= + ~PARAM_PACKET_FILTER_MULTICAST; + u4rxfilter = prAdapter->u4OsPacketFilter; + fgUpdate = TRUE; + } else if (ucOpt0 == SWCR_RX_FILTER_CMD_START) { + g_u4RXFilter |= (RX_FILTER_START); + + if ((g_u4RXFilter & RX_FILTER_IPV4) + || (g_u4RXFilter & RX_FILTER_IPV6)) { +#if 0 + prAdapter->u4OsPacketFilter |= + PARAM_PACKET_FILTER_ALL_MULTICAST; +#endif + prAdapter->u4OsPacketFilter |= + PARAM_PACKET_FILTER_MULTICAST; + } + u4rxfilter = prAdapter->u4OsPacketFilter; + fgUpdate = TRUE; + } else if (ucOpt0 == SWCR_RX_FILTER_CMD_ADD) { + if (ucOpt1 < 31) + g_u4RXFilter |= (1 << ucOpt1); + } else if (ucOpt0 == SWCR_RX_FILTER_CMD_REMOVE) { + if (ucOpt1 < 31) + g_u4RXFilter &= ~(1 << ucOpt1); + } + + if (fgUpdate == TRUE) { + rSetRxPacketFilter. + u4RxPacketFilter = u4rxfilter; + rStatus = + wlanoidSetPacketFilter( + prAdapter, &rSetRxPacketFilter, + FALSE, NULL, 0); + } + /* DBGLOG(SW4, INFO,("SWCTRL_RX_FILTER: + * g_u4RXFilter %x ucOpt0 %x ucOpt1 %x fgUpdate %x + * u4rxfilter %x, rStatus %x\n", + * g_u4RXFilter, ucOpt0, ucOpt1, + * fgUpdate, u4rxfilter, rStatus)); + */ + } + break; + +#if CFG_INIT_ENABLE_PATTERN_FILTER_ARP + case SWCTRL_RX_ARP_OFFLOAD: { + uint32_t rStatus = WLAN_STATUS_FAILURE; + uint32_t u4SetInfoLen = 0; + uint32_t u4Len = OFFSET_OF(struct + PARAM_NETWORK_ADDRESS_LIST, arAddress); + uint32_t u4NumIPv4 = 0, u4NumIPv6 = 0; + uint32_t i = 0; + uint8_t *pucBufIpAddr = NULL; + struct PARAM_NETWORK_ADDRESS_LIST *prParamNetAddrList = + NULL; + struct PARAM_NETWORK_ADDRESS_IP *prParamIpAddr = NULL; + uint8_t *pucIp = NULL; + /* PUINT_8 pucIpv6 = NULL; */ + uint32_t bufSize = + u4Len + (OFFSET_OF(struct PARAM_NETWORK_ADDRESS, + aucAddress) + + sizeof( + struct PARAM_NETWORK_ADDRESS_IP)) * 3; + struct PARAM_NETWORK_ADDRESS *prParamNetAddr = NULL; + + /* <1> allocate IP address buffer */ + pucBufIpAddr = kalMemAlloc(bufSize, VIR_MEM_TYPE); + /* TODO: replace 3 to macro */ + pucIp = kalMemAlloc(3 * 4, VIR_MEM_TYPE); + + prParamNetAddrList = + (struct PARAM_NETWORK_ADDRESS_LIST *) + pucBufIpAddr; + prParamNetAddr = prParamNetAddrList->arAddress; + /* <2> clear IP address buffer */ + kalMemZero(pucBufIpAddr, bufSize); + kalMemZero(pucIp, 3 * 4); + + /* <3> setup the number of IP address */ + if (ucOpt1 == 1) { + /* TODO: repleace 3 to macro */ + if (wlanGetIPV4Address( + prAdapter->prGlueInfo, pucIp, + &u4NumIPv4) && u4NumIPv4 > 3) + u4NumIPv4 = 3; + } else if (ucOpt1 == 0) { + u4NumIPv4 = u4NumIPv6 = 0; + } + DBGLOG(INIT, INFO, "u4Len:%d bufSize:%d u4NumIPv4:%d\n", + u4Len, bufSize, u4NumIPv4); + + prParamNetAddrList->u4AddressCount = + u4NumIPv6 + u4NumIPv4; + prParamNetAddrList->u2AddressType = + PARAM_PROTOCOL_ID_TCP_IP; + + for (i = 0; i < u4NumIPv4; i++) { + prParamNetAddr->u2AddressLength = sizeof(struct + PARAM_NETWORK_ADDRESS_IP); + prParamNetAddr->u2AddressType = + PARAM_PROTOCOL_ID_TCP_IP; + prParamIpAddr = + (struct PARAM_NETWORK_ADDRESS_IP *) + prParamNetAddr->aucAddress; + kalMemCopy(&prParamIpAddr->in_addr, + pucIp + (i * 4), 4); + prParamNetAddr = + (struct PARAM_NETWORK_ADDRESS *) + ((uint32_t) prParamNetAddr + + OFFSET_OF + (struct + PARAM_NETWORK_ADDRESS, + aucAddress) + + sizeof( + struct + PARAM_NETWORK_ADDRESS_IP + )); + u4Len += + OFFSET_OF(struct PARAM_NETWORK_ADDRESS, + aucAddress) + + sizeof( + struct + PARAM_NETWORK_ADDRESS_IP); + } + +#if 0 +#ifdef CONFIG_IPV6 + if (!wlanGetIPV6Address(prAdapter->prGlueInfo, pucIp, + &u4NumIPv6) + || (u4NumIPv6 + u4NumIPv4) > 3) { + goto bailout; + } + + pucIpv6 = kalMemAlloc(u4NumIPv6 * 16, VIR_MEM_TYPE); + + for (i = 0; i < u4NumIPv6; i++) { + prParamNetAddr->u2AddressLength = 6; + prParamNetAddr->u2AddressType = + PARAM_PROTOCOL_ID_TCP_IP; + kalMemCopy(prParamNetAddr->aucAddress, + pucIpv6 + (i * 16), + 16); + prParamNetAddr = + (struct PARAM_NETWORK_ADDRESS *) + ((uint32_t) prParamNetAddr + + sizeof(ip6)); + u4Len += OFFSET_OF(struct PARAM_NETWORK_ADDRESS, + aucAddress) + sizeof(ip6); + } +#endif +#endif + + ASSERT(u4Len <= bufSize); + + rStatus = wlanoidSetNetworkAddress(prAdapter, + (void *) prParamNetAddrList, + u4Len, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, + "set HW packet filter fail 0x%1x\n", + rStatus); + + /* TODO: replace 3 to marco */ + if (pucIp) + kalMemFree(pucIp, VIR_MEM_TYPE, 3 * 4); + if (pucBufIpAddr) + kalMemFree(pucBufIpAddr, VIR_MEM_TYPE, bufSize); + + } + break; +#endif + case SWCTRL_PS_DTIM_SKIP: + break; + case SWCTRL_ROAMING: + break; + default: + break; + } + } else { + switch (ucIndex) { + case SWCTRL_DEBUG: + break; + case SWCTRL_MAGIC: + g_au4SwCr[1] = _SWCTRL_MAGIC; + break; + case SWCTRL_QM_INFO: { + struct QUE_MGT *prQM = &prAdapter->rQM; + + switch (ucOpt0) { + case 0: +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + 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]; +#endif + break; + + case 1: +#if QM_FORWARDING_FAIRNESS + g_au4SwCr[1] = + prQM->au4ResourceUsedCount[ucOpt1]; + g_au4SwCr[2] = prQM->au4HeadStaRecIndex[ucOpt1]; +#endif + break; + + case 2: + /* only one */ + g_au4SwCr[1] = + prQM->arTxQueue[ucOpt1].u4NumElem; + + break; + } + } + break; + case SWCTRL_TX_CTRL_INFO: { + struct TX_CTRL *prTxCtrl; + + prTxCtrl = &prAdapter->rTxCtrl; + switch (ucOpt0) { + case 0: + g_au4SwCr[1] = + prAdapter->rTxCtrl.rTc. + au4FreeBufferCount[ucOpt1]; + g_au4SwCr[2] = + prAdapter->rTxCtrl.rTc. + au4MaxNumOfBuffer[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, GET_BSS_INFO_BY_INDEX(prAdapter, + ucOpt0)); + } + break; + + default: + break; + } + + } +} + +void swCtrlCmdCategory1(struct ADAPTER *prAdapter, + uint8_t ucCate, uint8_t ucAction, uint8_t ucOpt0, + uint8_t ucOpt1) +{ + uint8_t ucIndex, ucRead; + uint8_t ucWTEntry; + struct STA_RECORD *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->ucWlanIndex; + if (ucRead == SWCR_WRITE) { + /* ToDo:: Nothing */ + } else { + /* Read */ + switch (ucIndex) { + case SWCTRL_STA_QUE_INFO: { + g_au4SwCr[1] = prStaRec->arTxQueue[ucOpt1].u4NumElem; + } + break; + case SWCTRL_STA_INFO: + switch (ucOpt1) { + case 0: + g_au4SwCr[1] = prStaRec->fgIsInPS; + break; + } + + break; + + case SWCTRL_DUMP_STA: { + dumpSTA(prAdapter, prStaRec); + } + break; + + default: + + break; + } + } + +} + +#if TEST_PS + +void +testPsSendQoSNullFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN uint8_t ucUP, + IN uint8_t ucBssIndex, + IN u_int8_t fgBMC, + IN u_int8_t fgIsBurstEnd, IN u_int8_t ucPacketType, + IN u_int8_t ucPsSessionID, IN u_int8_t fgSetEOSP) +{ + struct MSDU_INFO *prMsduInfo; + uint16_t u2EstimatedFrameLen; + struct WLAN_MAC_HEADER_QOS *prQoSNullFrame; + + DEBUGFUNC("testPsSendQoSNullFrame"); + DBGLOG(SW4, LOUD, "\n"); + + /* 4 <1> Allocate a PKT_INFO_T for Null Frame */ + /* Init with MGMT Header Length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + + WLAN_MAC_HEADER_QOS_LEN; + + /* Allocate a MSDU_INFO_T */ + + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + + if (prMsduInfo == NULL) { + DBGLOG(SW4, WARN, + "No PKT_INFO_T for sending Null Frame.\n"); + return; + } + /* 4 <2> Compose Null frame in MSDU_INfO_T. */ + bssComposeQoSNullFrame(prAdapter, + (uint8_t *) ((unsigned long) (prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD), + prStaRec, ucUP, fgSetEOSP); + + TX_SET_MMPDU(prAdapter, + prMsduInfo, + ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_HEADER_QOS_LEN, + WLAN_MAC_HEADER_QOS_LEN, NULL, MSDU_RATE_MODE_AUTO); + + prMsduInfo->ucUserPriority = ucUP; + prMsduInfo->ucPacketType = ucPacketType; + + prQoSNullFrame = (struct WLAN_MAC_HEADER_QOS *) ((uint8_t *) + ((unsigned long) (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 struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + struct BSS_INFO *prBssInfo; + uint8_t _aucZeroMacAddr[] = NULL_MAC_ADDR; + + DEBUGFUNC("testPsSetupBss()"); + DBGLOG(SW4, INFO, "index %d\n", ucBssIndex); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + /* 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, prBssInfo); + + prBssInfo->eConnectionState = + MEDIA_STATE_DISCONNECTED; + prBssInfo->eConnectionStateIndicated = + MEDIA_STATE_DISCONNECTED; + prBssInfo->eCurrentOPMode = OP_MODE_ACCESS_POINT; + prBssInfo->fgIsNetActive = TRUE; + prBssInfo->ucBssIndex = ucBssIndex; + prBssInfo->ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_RESERVED; + + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = + PHY_TYPE_SET_802_11BG; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = + AP_MODE_MIXED_11BG; + 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->u2HwDefaultFixedRateCode = 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 = (struct STA_RECORD *) NULL; + + /* prBssInfo->fgErpProtectMode = eErpProectMode; */ + /* prBssInfo->eHtProtectMode = eHtProtectMode; */ + /* prBssInfo->eGfOperationMode = eGfOperationMode; */ + + /* 4 <4> Allocate MSDU_INFO_T for Beacon */ + prBssInfo->prBeacon = cnmMgtPktAlloc(prAdapter, + OFFSET_OF(struct WLAN_BEACON_FRAME, + aucInfoElem[0]) + MAX_IE_LENGTH); + + if (prBssInfo->prBeacon) { + prBssInfo->prBeacon->eSrc = TX_PACKET_MGMT; + prBssInfo->prBeacon->ucBssIndex = ucBssIndex; + } 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 = + (uint8_t) prAdapter->u4UapsdAcBmp; + prBssInfo->rPmProfSetupInfo.ucBmpTriggerAC = + (uint8_t) prAdapter->u4UapsdAcBmp; + prBssInfo->rPmProfSetupInfo.ucUapsdSp = (uint8_t) + prAdapter->u4MaxSpLen; +#endif + +#if 0 + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + + prBssInfo->arACQueParms[eAci].ucIsACMSet = FALSE; + prBssInfo->arACQueParms[eAci].u2Aifsn = (uint16_t) 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].ucIsACMSet, + prBssInfo->arACQueParms[eAci].u2Aifsn, + prBssInfo->arACQueParms[eAci].u2CWmin, + prBssInfo->arACQueParms[eAci].u2CWmax, + prBssInfo->arACQueParms[eAci].u2TxopLimit); + + } +#endif + + DBGLOG(SW4, INFO, + "[2] ucBmpDeliveryAC:0x%x, ucBmpTriggerAC:0x%x, ucUapsdSp:0x%x", + prBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC, + prBssInfo->rPmProfSetupInfo.ucBmpTriggerAC, + prBssInfo->rPmProfSetupInfo.ucUapsdSp); +} + +void testPsCmdCategory0(struct ADAPTER *prAdapter, + uint8_t ucCate, uint8_t ucAction, uint8_t ucOpt0, + uint8_t ucOpt1) +{ + uint8_t ucIndex, ucRead; + struct STA_RECORD *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: { + if (prStaRec == NULL) + break; + testPsSendQoSNullFrame(prAdapter, prStaRec, + /* UP */ + (uint8_t) (g_au4SwCr[1] & 0xFF), + /* BMC */ + ucOpt0, (u_int8_t) ((g_au4SwCr[1] >> 8) & 0xFF), + /* BurstEnd */ + (u_int8_t) ((g_au4SwCr[1] >> 16) & 0xFF), + /* Packet type */ + (u_int8_t) ((g_au4SwCr[1] >> 24) & 0xFF), + /* PS sesson ID 7: NOACK */ + (uint8_t) ((g_au4SwCr[2]) & 0xFF), + /* EOSP */ + FALSE + ); + } + break; + case TEST_PS_BUFFER_BMC: + 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(struct ADAPTER *prAdapter, + uint8_t ucCate, uint8_t ucAction, uint8_t ucOpt0, + uint8_t ucOpt1) +{ + uint8_t ucIndex, ucRead; + uint8_t ucWTEntry; + struct STA_RECORD *prStaRec; + + DEBUGFUNC("testPsCmdCategory1"); + + SWCR_GET_RW_INDEX(ucAction, ucRead, ucIndex); + + if (ucOpt0 >= CFG_STA_REC_NUM) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucOpt0); + + if (!prStaRec) { + DBGLOG(SW4, INFO, "prStaRec is NULL, ucOpt0:%d\n", ucOpt0); + return; + } + + ucWTEntry = prStaRec->ucWlanIndex; + if (ucRead == SWCR_WRITE) { + + switch (ucIndex) { + case TEST_PS_STA_PS: + prStaRec->fgIsInPS = (u_int8_t) (g_au4SwCr[1] & 0x1); + prStaRec->fgIsQoS = + (u_int8_t) (g_au4SwCr[1] >> 8 & 0xFF); + prStaRec->fgIsUapsdSupported = + (u_int8_t) (g_au4SwCr[1] >> 16 & 0xFF); + prStaRec->ucBmpDeliveryAC = + (u_int8_t) (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(struct ADAPTER *prAdapter, + uint8_t ucCate, uint8_t ucAction, uint8_t ucOpt0, + uint8_t ucOpt1) +{ + uint8_t ucIndex, ucRead; + struct STA_RECORD *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(struct ADAPTER *prAdapter, uint8_t ucRead, + uint16_t u2Addr, uint32_t *pu4Data) +{ + /* According other register STAIDX */ + uint8_t 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 */ + uint8_t ucCate; + uint32_t u4Cmd; + + u4Cmd = g_au4SwCr[0]; + ucCate = (uint8_t) (u4Cmd >> 24); + if (ucCate < ARRAY_SIZE(g_arSwCtrlCmd)) { + if (g_arSwCtrlCmd[ucCate] != NULL) { + g_arSwCtrlCmd[ucCate] ( + prAdapter, ucCate, + (uint8_t) (u4Cmd >> 16 & 0xFF), + (uint8_t) ((u4Cmd >> 8) & 0xFF), + (uint8_t) (u4Cmd & 0xFF)); + } + } + } + } else { + *pu4Data = g_au4SwCr[ucOffset]; + } +} + +void swCrReadWriteCmd(struct ADAPTER *prAdapter, + uint8_t ucRead, uint16_t u2Addr, uint32_t *pu4Data) +{ + uint8_t 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 < (ARRAY_SIZE(g_arSwCrModHandle))) { + + if (g_arSwCrModHandle[ucMod] != NULL) + g_arSwCrModHandle[ucMod] (prAdapter, ucRead, u2Addr, + pu4Data); + } /* ucMod */ +} + +/* Debug Support */ +void swCrFrameCheckEnable(struct ADAPTER *prAdapter, + uint32_t u4DumpType) +{ + g_u4SwcrDebugFrameDumpType = u4DumpType; +#if CFG_RX_PKTS_DUMP + prAdapter->rRxCtrl.u4RxPktsDumpTypeMask = u4DumpType; +#endif +} + +void swCrDebugInit(struct ADAPTER *prAdapter) +{ + /* frame dump */ + if (g_u4SwcrDebugFrameDumpType) + swCrFrameCheckEnable(prAdapter, g_u4SwcrDebugFrameDumpType); + /* debug counter */ + g_fgSwcrDebugTimer = FALSE; + + cnmTimerInitTimer(prAdapter, &g_rSwcrDebugTimer, + (PFN_MGMT_TIMEOUT_FUNC) swCrDebugCheckTimeout, + (unsigned long) NULL); + + if (g_u4SwcrDebugCheckTimeout) + swCrDebugCheckEnable(prAdapter, TRUE, + g_ucSwcrDebugCheckType, g_u4SwcrDebugCheckTimeout); +} + +void swCrDebugUninit(struct ADAPTER *prAdapter) +{ + cnmTimerStopTimer(prAdapter, &g_rSwcrDebugTimer); + + g_fgSwcrDebugTimer = FALSE; +} + +void swCrDebugCheckEnable(struct ADAPTER *prAdapter, + u_int8_t fgIsEnable, uint8_t ucType, uint32_t 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(struct ADAPTER *prAdapter, + struct CMD_SW_DBG_CTRL *prCmdSwCtrl) +{ + struct RX_CTRL *prRxCtrl; + struct TX_CTRL *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", + (uint32_t) TX_GET_CNT(prTxCtrl, + TX_INACTIVE_BSS_DROP), + (uint32_t) TX_GET_CNT(prTxCtrl, + TX_INACTIVE_STA_DROP), + (uint32_t) TX_GET_CNT(prTxCtrl, + TX_FORWARD_OVERFLOW_DROP), + (uint32_t) 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", + (uint32_t) RX_GET_CNT(prRxCtrl, + RX_MPDU_TOTAL_COUNT), + (uint32_t) RX_GET_CNT(prRxCtrl, + RX_DATA_INDICATION_COUNT), + (uint32_t) RX_GET_CNT(prRxCtrl, + RX_DATA_RETURNED_COUNT), + (uint32_t) RX_GET_CNT(prRxCtrl, + RX_DATA_RETAINED_COUNT), + (uint32_t) RX_GET_CNT(prRxCtrl, + RX_DROP_TOTAL_COUNT), + (uint32_t) RX_GET_CNT(prRxCtrl, + RX_TYPE_ERR_DROP_COUNT), + (uint32_t) RX_GET_CNT(prRxCtrl, + RX_CLASS_ERR_DROP_COUNT), + (uint32_t) 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 struct ADAPTER *prAdapter, + unsigned long ulParamPtr) +{ + struct CMD_SW_DBG_CTRL rCmdSwCtrl; + uint32_t 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(struct CMD_SW_DBG_CTRL), /* u4SetQueryInfoLen */ + (uint8_t *) &rCmdSwCtrl, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); +} + +void swCrDebugQuery(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + ASSERT(prAdapter); + + swCrDebugCheck(prAdapter, + (struct CMD_SW_DBG_CTRL *) (pucEventBuf)); +} + +void swCrDebugQueryTimeout(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo) +{ + ASSERT(prAdapter); + + swCrDebugCheck(prAdapter, NULL); +} + +#endif /* CFG_SUPPORT_SWCR */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/tdls.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/tdls.c new file mode 100644 index 0000000000000..b5358ec116f2b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/tdls.c @@ -0,0 +1,1636 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: tdls.c#1 + */ + +/*! \file tdls.c + * \brief This file includes IEEE802.11z TDLS support. + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" + +#if CFG_SUPPORT_TDLS +#include "tdls.h" +#include "queue.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 + ******************************************************************************* + */ +uint8_t g_arTdlsLink[MAXNUM_TDLS_PEER] = { + 0, + 0, + 0, + 0 + }; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +static u_int8_t fgIsPtiTimeoutSkip = FALSE; +static u_int8_t fgIsWaitForTxDone = FALSE; + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +#define ELEM_ID_LINK_IDENTIFIER_LENGTH 16 + +#define TDLS_KEY_TIMEOUT_INTERVAL 43200 + +#define TDLS_REASON_CODE_UNREACHABLE 25 +#define TDLS_REASON_CODE_UNSPECIFIED 26 + +#define WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE 25 +#define WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED 26 + +/******************************************************************************* + * 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 hadel TDLS link oper from nl80211. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[in] + * \param[in] + * \param[in] buf includes RSN IE + FT IE + Lifetimeout IE + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t TdlsexLinkMgt(struct ADAPTER *prAdapter, + void *pvSetBuffer, uint32_t u4SetBufferLen, + uint32_t *pu4SetInfoLen) +{ + uint32_t rResult = TDLS_STATUS_SUCCESS; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + struct TDLS_CMD_LINK_MGT *prCmd; + + prCmd = (struct TDLS_CMD_LINK_MGT *) pvSetBuffer; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prCmd->ucBssIdx); + if (prBssInfo == NULL) { + DBGLOG(TDLS, ERROR, "prBssInfo %d is NULL!\n" + , prCmd->ucBssIdx); + return -EINVAL; + } + + DBGLOG(TDLS, INFO, "u4SetBufferLen=%d", u4SetBufferLen); + +#if 1 + /* AIS only */ + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + prStaRec = prBssInfo->prStaRecOfAP; + if (prStaRec == NULL) + return 0; + } else { + return -EINVAL; + } +#endif + + DBGLOG(TDLS, INFO, "prCmd->ucActionCode=%d, prCmd->ucDialogToken=%d", + prCmd->ucActionCode, prCmd->ucDialogToken); + + prStaRec = prBssInfo->prStaRecOfAP; + + switch (prCmd->ucActionCode) { + + case TDLS_FRM_ACTION_DISCOVERY_REQ: + if (prStaRec == NULL) + return 0; + rResult = TdlsDataFrameSend_DISCOVERY_REQ(prAdapter, + prStaRec, + prCmd->aucPeer, + prCmd->ucActionCode, + prCmd->ucDialogToken, + prCmd->u2StatusCode, + (uint8_t *) (prCmd->aucSecBuf), + prCmd->u4SecBufLen); + break; + + case TDLS_FRM_ACTION_SETUP_REQ: + if (prStaRec == NULL) + return 0; + prStaRec = cnmGetTdlsPeerByAddress(prAdapter, + prBssInfo->ucBssIndex, + prCmd->aucPeer); + g_arTdlsLink[prStaRec->ucTdlsIndex] = 0; + rResult = TdlsDataFrameSend_SETUP_REQ(prAdapter, + prStaRec, + prCmd->aucPeer, + prCmd->ucActionCode, + prCmd->ucDialogToken, + prCmd->u2StatusCode, + (uint8_t *) (prCmd->aucSecBuf), + prCmd->u4SecBufLen); + break; + + case TDLS_FRM_ACTION_SETUP_RSP: + /* fix sigma bug 5.2.4.2, 5.2.4.7, we sent Status code decline, + * but the sigma recogniezis it as scucess, and it will fail + */ + /* if(prCmd->u2StatusCode != 0) */ + if (prBssInfo->fgTdlsIsProhibited) + return 0; + + rResult = TdlsDataFrameSend_SETUP_RSP(prAdapter, + prStaRec, + prCmd->aucPeer, + prCmd->ucActionCode, + prCmd->ucDialogToken, + prCmd->u2StatusCode, + (uint8_t *) (prCmd->aucSecBuf), + prCmd->u4SecBufLen); + break; + + case TDLS_FRM_ACTION_DISCOVERY_RSP: + rResult = TdlsDataFrameSend_DISCOVERY_RSP(prAdapter, + prStaRec, + prCmd->aucPeer, + prCmd->ucActionCode, + prCmd->ucDialogToken, + prCmd->u2StatusCode, + (uint8_t *) (prCmd->aucSecBuf), + prCmd->u4SecBufLen); + break; + + case TDLS_FRM_ACTION_CONFIRM: + rResult = TdlsDataFrameSend_CONFIRM(prAdapter, + prStaRec, + prCmd->aucPeer, + prCmd->ucActionCode, + prCmd->ucDialogToken, + prCmd->u2StatusCode, + (uint8_t *) (prCmd->aucSecBuf), + prCmd->u4SecBufLen); + break; + + case TDLS_FRM_ACTION_TEARDOWN: + prStaRec = cnmGetTdlsPeerByAddress(prAdapter, + prBssInfo->ucBssIndex, + prCmd->aucPeer); + if (prCmd->u2StatusCode == TDLS_REASON_CODE_UNREACHABLE) + g_arTdlsLink[prStaRec->ucTdlsIndex] = 0; + + rResult = TdlsDataFrameSend_TearDown(prAdapter, + prStaRec, + prCmd->aucPeer, + prCmd->ucActionCode, + prCmd->ucDialogToken, + prCmd->u2StatusCode, + (uint8_t *) (prCmd->aucSecBuf), + prCmd->u4SecBufLen); + break; + + default: + DBGLOG(TDLS, INFO, "default=%d", prCmd->ucActionCode); + return -EINVAL; + } + + if (rResult == TDLS_STATUS_PENDING) + fgIsWaitForTxDone = TRUE; + + DBGLOG(TDLS, INFO, "rResult=%d", rResult); + + return rResult; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to hadel TDLS link mgt from nl80211. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[in] + * \param[in] + * \param[in] buf includes RSN IE + FT IE + Lifetimeout IE + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t TdlsexLinkOper(struct ADAPTER *prAdapter, + void *pvSetBuffer, uint32_t u4SetBufferLen, + uint32_t *pu4SetInfoLen) +{ + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + uint16_t i; + struct STA_RECORD *prStaRec; + + struct TDLS_CMD_LINK_OPER *prCmd; + + struct BSS_INFO *prBssInfo; + + prCmd = (struct TDLS_CMD_LINK_OPER *) pvSetBuffer; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prCmd->ucBssIdx); + if (prBssInfo == NULL) { + DBGLOG(TDLS, ERROR, "prBssInfo %d is NULL!\n" + , prCmd->ucBssIdx); + return 0; + } + + DBGLOG(TDLS, INFO, "prCmd->oper=%d, u4SetBufferLen=%d", + prCmd->oper, u4SetBufferLen); + + switch (prCmd->oper) { + + case TDLS_ENABLE_LINK: + + for (i = 0; i < MAXNUM_TDLS_PEER; i++) { + if (!g_arTdlsLink[i]) { + g_arTdlsLink[i] = 1; + prStaRec = + cnmGetTdlsPeerByAddress(prAdapter, + prBssInfo->ucBssIndex, + prCmd->aucPeerMac); + prStaRec->ucTdlsIndex = i; + break; + } + } + + /* printk("TDLS_ENABLE_LINK %d\n", i); */ + break; + case TDLS_DISABLE_LINK: + + prStaRec = cnmGetTdlsPeerByAddress(prAdapter, + prBssInfo->ucBssIndex, + prCmd->aucPeerMac); + + /* printk("TDLS_ENABLE_LINK %d\n", prStaRec->ucTdlsIndex); */ + g_arTdlsLink[prStaRec->ucTdlsIndex] = 0; + if (IS_DLS_STA(prStaRec)) + cnmStaRecFree(prAdapter, prStaRec); + + break; + default: + return 0; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to append general IEs. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[in] + * + * \retval append length + */ +/*----------------------------------------------------------------------------*/ +uint32_t TdlsFrameGeneralIeAppend(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, uint8_t *pPkt) +{ + struct GLUE_INFO *prGlueInfo; + struct BSS_INFO *prBssInfo; + struct PM_PROFILE_SETUP_INFO *prPmProfSetupInfo; + uint16_t u2SupportedRateSet; + uint8_t aucAllSupportedRates[RATE_NUM_SW] = { 0 }; + uint8_t ucAllSupportedRatesLen; + uint8_t ucSupRatesLen; + uint8_t ucExtSupRatesLen; + uint32_t u4PktLen, u4IeLen; + + /* init */ + prGlueInfo = (struct GLUE_INFO *) prAdapter->prGlueInfo; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + if (prBssInfo == NULL) { + DBGLOG(TDLS, ERROR, "prBssInfo %d is NULL!\n" + , prStaRec->ucBssIndex); + return 0; + } + + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + + /* 3. Frame Formation - (5) Supported Rates element */ + /* use all sup rate we can support */ + u2SupportedRateSet = prStaRec->u2OperationalRateSet; + rateGetDataRatesFromRateSet(u2SupportedRateSet, 0, + aucAllSupportedRates, + &ucAllSupportedRatesLen); + + ucSupRatesLen = ((ucAllSupportedRatesLen > + ELEM_MAX_LEN_SUP_RATES) ? + ELEM_MAX_LEN_SUP_RATES : ucAllSupportedRatesLen); + + ucExtSupRatesLen = ucAllSupportedRatesLen - ucSupRatesLen; + + if (ucSupRatesLen) { + SUP_RATES_IE(pPkt)->ucId = ELEM_ID_SUP_RATES; + SUP_RATES_IE(pPkt)->ucLength = ucSupRatesLen; + kalMemCopy(SUP_RATES_IE(pPkt)->aucSupportedRates, + aucAllSupportedRates, ucSupRatesLen); + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + } + + /* 3. Frame Formation - (7) Extended sup rates element */ + if (ucExtSupRatesLen) { + + EXT_SUP_RATES_IE(pPkt)->ucId = ELEM_ID_EXTENDED_SUP_RATES; + EXT_SUP_RATES_IE(pPkt)->ucLength = ucExtSupRatesLen; + + kalMemCopy(EXT_SUP_RATES_IE(pPkt)->aucExtSupportedRates, + &aucAllSupportedRates[ucSupRatesLen], + ucExtSupRatesLen); + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + } + + /* 3. Frame Formation - (8) Supported channels element */ + SUPPORTED_CHANNELS_IE(pPkt)->ucId = ELEM_ID_SUP_CHS; + SUPPORTED_CHANNELS_IE(pPkt)->ucLength = 2; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[0] = 1; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[1] = 13; + + if (prAdapter->fgEnable5GBand == TRUE) { + SUPPORTED_CHANNELS_IE(pPkt)->ucLength = 10; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[2] = 36; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[3] = 4; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[4] = 52; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[5] = 4; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[6] = 149; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[7] = 4; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[8] = 165; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[9] = 1; + } + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + + return u4PktLen; +} + +/*! + * \brief This routine is called to transmit a TDLS data frame. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[in] + * \param[in] + * \param[in] buf includes RSN IE + FT IE + Lifetimeout IE + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t +TdlsDataFrameSend_TearDown(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t *pPeerMac, + uint8_t ucActionCode, + uint8_t ucDialogToken, uint16_t u2StatusCode, + uint8_t *pAppendIe, uint32_t AppendIeLen) +{ + + struct GLUE_INFO *prGlueInfo; + struct BSS_INFO *prBssInfo; + struct PM_PROFILE_SETUP_INFO *prPmProfSetupInfo; + struct sk_buff *prMsduInfo; + uint8_t *pPkt; + uint32_t u4PktLen, u4IeLen; + uint16_t ReasonCode; + + /* allocate/init packet */ + prGlueInfo = (struct GLUE_INFO *) prAdapter->prGlueInfo; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + if (prBssInfo == NULL) { + DBGLOG(TDLS, ERROR, "prBssInfo %d is NULL!\n" + , prStaRec->ucBssIndex); + return 0; + } + + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + + prMsduInfo = kalPacketAllocWithHeadroom(prGlueInfo, 1600, + &pPkt); + if (prMsduInfo == NULL) + return TDLS_STATUS_RESOURCES; + + prMsduInfo->dev = wlanGetNetDev(prGlueInfo, + prStaRec->ucBssIndex); + if (prMsduInfo->dev == NULL) { + kalPacketFree(prGlueInfo, prMsduInfo); + return TDLS_STATUS_FAIL; + } + + /* make up frame content */ + /* 1. 802.3 header */ + kalMemCopy(pPkt, pPeerMac, TDLS_FME_MAC_ADDR_LEN); + pPkt += TDLS_FME_MAC_ADDR_LEN; + kalMemCopy(pPkt, prBssInfo->aucOwnMacAddr, + TDLS_FME_MAC_ADDR_LEN); + pPkt += TDLS_FME_MAC_ADDR_LEN; + *(uint16_t *) pPkt = htons(TDLS_FRM_PROT_TYPE); + pPkt += 2; + u4PktLen += TDLS_FME_MAC_ADDR_LEN * 2 + 2; + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + pPkt++; + u4PktLen++; + + /* 3. Frame Formation - (1) Category */ + *pPkt = TDLS_FRM_CATEGORY; + pPkt++; + u4PktLen++; + + /* 3. Frame Formation - (2) Action */ + *pPkt = ucActionCode; + pPkt++; + u4PktLen++; + + /* 3. Frame Formation - status code */ + + ReasonCode = u2StatusCode; + + /* printk("\n\n ReasonCode = %u\n\n",ReasonCode ); */ + + kalMemCopy(pPkt, &ReasonCode, 2); + pPkt = pPkt + 2; + u4PktLen = u4PktLen + 2; + + if (pAppendIe != NULL) { + kalMemCopy(pPkt, pAppendIe, AppendIeLen); + LR_TDLS_FME_FIELD_FILL(AppendIeLen); + } + + /* 7. Append Supported Operating Classes IE */ + if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { + /* Note: if we do not put the IE, Marvell STA will + * decline our TDLS setup request + */ + u4IeLen = rlmDomainSupOperatingClassIeFill(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } + + /* 3. Frame Formation - (16) Link identifier element */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = + ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, + prBssInfo->aucBSSID, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, + prBssInfo->aucOwnMacAddr, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, + pPeerMac, 6); + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + + /* 5. Update packet length */ + prMsduInfo->len = u4PktLen; + + /* printk(" TdlsDataFrameSend_TearDown !!\n"); */ + + /* 5. send the data frame */ + wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); + + return TDLS_STATUS_PENDING; +} + +/*! + * \brief This routine is called to transmit a TDLS data frame. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[in] + * \param[in] + * \param[in] buf includes RSN IE + FT IE + Lifetimeout IE + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t /* TDLS_STATUS */ +TdlsDataFrameSend_SETUP_REQ(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t *pPeerMac, + uint8_t ucActionCode, + uint8_t ucDialogToken, uint16_t u2StatusCode, + uint8_t *pAppendIe, uint32_t AppendIeLen) +{ + + struct GLUE_INFO *prGlueInfo; + struct BSS_INFO *prBssInfo; + struct PM_PROFILE_SETUP_INFO *prPmProfSetupInfo; + struct sk_buff *prMsduInfo; + uint8_t *pPkt; + uint32_t u4PktLen, u4IeLen; + uint16_t u2CapInfo; + + /* allocate/init packet */ + prGlueInfo = (struct GLUE_INFO *) prAdapter->prGlueInfo; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + if (prBssInfo == NULL) { + DBGLOG(TDLS, ERROR, "prBssInfo %d is NULL!\n" + , prStaRec->ucBssIndex); + return 0; + } + + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + + prMsduInfo = kalPacketAllocWithHeadroom(prGlueInfo, 512, &pPkt); + if (prMsduInfo == NULL) + return TDLS_STATUS_RESOURCES; + + prMsduInfo->dev = wlanGetNetDev(prGlueInfo, + prStaRec->ucBssIndex); + if (prMsduInfo->dev == NULL) { + kalPacketFree(prGlueInfo, prMsduInfo); + return TDLS_STATUS_FAIL; + } + + /* make up frame content */ + /* 1. 802.3 header */ + kalMemCopy(pPkt, pPeerMac, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(pPkt, prBssInfo->aucOwnMacAddr, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + *(uint16_t *) pPkt = htons(TDLS_FRM_PROT_TYPE); + LR_TDLS_FME_FIELD_FILL(2); + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + LR_TDLS_FME_FIELD_FILL(1); + + /* + * 3.1 Category + * 3.2 Action + * 3.3 Dialog Token + * 3.4 Capability + * 3.5 Supported rates + * 3.6 Country + * 3.7 Extended supported rates + * 3.8 Supported Channels (optional) + * 3.9 RSNIE (optional) + * 3.10 Extended Capabilities + * 3.11 QoS Capability + * 3.12 FTIE (optional) + * 3.13 Timeout Interval (optional) + * 3.14 Supported Regulatory Classes (optional) + * 3.15 HT Capabilities + * 3.16 20/40 BSS Coexistence + * 3.17 Link Identifier + */ + + /* 3.1 Category */ + *pPkt = TDLS_FRM_CATEGORY; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3.2 Action */ + *pPkt = ucActionCode; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3.3 Dialog Token */ + *pPkt = ucDialogToken; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3.4 Capability */ + u2CapInfo = assocBuildCapabilityInfo(prAdapter, prStaRec); + WLAN_SET_FIELD_16(pPkt, u2CapInfo); + LR_TDLS_FME_FIELD_FILL(2); + + /* + * 3.5 Supported rates + * 3.7 Extended supported rates + * 3.8 Supported Channels (optional) + */ + u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, prStaRec, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3.6 Country */ + /* 3.14 Supported Regulatory Classes (optional) */ + /* Note: if we do not put the IE, Marvell STA will decline + * our TDLS setup request + */ + u4IeLen = rlmDomainSupOperatingClassIeFill(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3.10 Extended Capabilities */ + EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP; + EXT_CAP_IE(pPkt)->ucLength = 5; + + EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */ + EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */ + EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */ + + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24)); + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24)); + EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32)); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* Append extra IEs */ + /* + * 3.9 RSNIE (optional) + * 3.12 FTIE (optional) + * 3.13 Timeout Interval (optional) + */ + if (pAppendIe != NULL) { + kalMemCopy(pPkt, pAppendIe, AppendIeLen); + LR_TDLS_FME_FIELD_FILL(AppendIeLen); + } + + /* 3.11 QoS Capability */ + /* HT WMM IE append */ + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) { + u4IeLen = mqmGenerateWmmInfoIEByStaRec(prAdapter, prBssInfo, + prStaRec, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + u4IeLen = mqmGenerateWmmParamIEByParam(prAdapter, prBssInfo, + pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } + + /* 3.15 HT Capabilities */ + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & + PHY_TYPE_SET_802_11N)) { + u4IeLen = rlmFillHtCapIEByAdapter(prAdapter, prBssInfo, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } +#if 0 /* TODO: VHT support */ +#if CFG_SUPPORT_802_11AC + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & + PHY_TYPE_SET_802_11AC) { + u4IeLen = rlmFillVhtCapIEByAdapter(prAdapter, prBssInfo, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } +#endif +#endif + + /* 3.16 20/40 BSS Coexistence */ + BSS_20_40_COEXIST_IE(pPkt)->ucId = ELEM_ID_20_40_BSS_COEXISTENCE; + BSS_20_40_COEXIST_IE(pPkt)->ucLength = 1; + BSS_20_40_COEXIST_IE(pPkt)->ucData = 0x01; + LR_TDLS_FME_FIELD_FILL(3); + + /* 3.17 Link Identifier */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, + prBssInfo->aucBSSID, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, + prBssInfo->aucOwnMacAddr, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, + pPeerMac, 6); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 4. Update packet length */ + prMsduInfo->len = u4PktLen; + + DBGLOG(TDLS, INFO, "wlanHardStartXmit, u4PktLen=%d", u4PktLen); + + /* 5. send the data frame */ + wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); + + return TDLS_STATUS_PENDING; +} + +uint32_t +TdlsDataFrameSend_SETUP_RSP(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t *pPeerMac, + uint8_t ucActionCode, + uint8_t ucDialogToken, uint16_t u2StatusCode, + uint8_t *pAppendIe, uint32_t AppendIeLen) +{ + struct GLUE_INFO *prGlueInfo; + struct BSS_INFO *prBssInfo; + struct PM_PROFILE_SETUP_INFO *prPmProfSetupInfo; + struct sk_buff *prMsduInfo; + uint8_t *pPkt; + uint32_t u4PktLen, u4IeLen; + uint16_t u2CapInfo; + + /* allocate/init packet */ + prGlueInfo = (struct GLUE_INFO *) prAdapter->prGlueInfo; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + if (prBssInfo == NULL) { + DBGLOG(TDLS, ERROR, "prBssInfo %d is NULL!\n" + , prStaRec->ucBssIndex); + return 0; + } + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + + prMsduInfo = kalPacketAllocWithHeadroom(prGlueInfo, 512, &pPkt); + if (prMsduInfo == NULL) + return TDLS_STATUS_RESOURCES; + + prMsduInfo->dev = wlanGetNetDev(prGlueInfo, + prStaRec->ucBssIndex); + if (prMsduInfo->dev == NULL) { + kalPacketFree(prGlueInfo, prMsduInfo); + return TDLS_STATUS_FAIL; + } + + /* make up frame content */ + /* 1. 802.3 header */ + kalMemCopy(pPkt, pPeerMac, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(pPkt, prBssInfo->aucOwnMacAddr, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + *(uint16_t *) pPkt = htons(TDLS_FRM_PROT_TYPE); + LR_TDLS_FME_FIELD_FILL(2); + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + LR_TDLS_FME_FIELD_FILL(1); + + /* + * 3.1 Category + * 3.2 Action + * 3.3 Status Code + * 3.4 Dialog Token + *** Below IE should be only included for Status Code=0 (Successful) + * 3.5 Capability + * 3.6 Supported rates + * 3.7 Country + * 3.8 Extended supported rates + * 3.9 Supported Channels (optional) + * 3.10 RSNIE (optional) + * 3.11 Extended Capabilities + * 3.12 QoS Capability + * 3.13 FTIE (optional) + * 3.14 Timeout Interval (optional) + * 3.15 Supported Regulatory Classes (optional) + * 3.16 HT Capabilities + * 3.17 20/40 BSS Coexistence + * 3.18 Link Identifier + */ + + /* 3.1 Category */ + *pPkt = TDLS_FRM_CATEGORY; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3.2 Action */ + *pPkt = ucActionCode; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3.3 Status Code */ + kalMemCopy(pPkt, &u2StatusCode, 2); + LR_TDLS_FME_FIELD_FILL(2); + + /* 3.4 Dialog Token */ + *pPkt = ucDialogToken; + LR_TDLS_FME_FIELD_FILL(1); + + if (u2StatusCode == 0) { + /* 3.5 Capability */ + u2CapInfo = assocBuildCapabilityInfo(prAdapter, prStaRec); + WLAN_SET_FIELD_16(pPkt, u2CapInfo); + LR_TDLS_FME_FIELD_FILL(2); + + /* + * 3.6 Supported rates + * 3.8 Extended supported rates + * 3.9 Supported Channels (optional) + */ + u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, prStaRec, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3.7 Country */ + /* 3.15 Supported Regulatory Classes (optional) */ + /* Note: if we do not put the IE, Marvell STA will decline + * our TDLS setup request + */ + u4IeLen = rlmDomainSupOperatingClassIeFill(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3.11 Extended Capabilities */ + EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP; + EXT_CAP_IE(pPkt)->ucLength = 5; + + EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */ + EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */ + EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */ + + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24)); + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24)); + EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32)); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3.12 QoS Capability */ + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) { + /* Add WMM IE *//* try to reuse p2p path */ + u4IeLen = mqmGenerateWmmInfoIEByStaRec(prAdapter, + prBssInfo, prStaRec, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + u4IeLen = mqmGenerateWmmParamIEByParam(prAdapter, + prBssInfo, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } + + /* 3.16 HT Capabilities */ + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & + PHY_TYPE_SET_802_11N) { + u4IeLen = rlmFillHtCapIEByAdapter(prAdapter, prBssInfo, + pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } +#if 0 /* TODO: VHT support */ +#if CFG_SUPPORT_802_11AC + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & + PHY_TYPE_SET_802_11AC) { + u4IeLen = rlmFillVhtCapIEByAdapter(prAdapter, prBssInfo, + pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } +#endif +#endif + + /* 3.17 20/40 BSS Coexistence */ + BSS_20_40_COEXIST_IE(pPkt)->ucId = + ELEM_ID_20_40_BSS_COEXISTENCE; + BSS_20_40_COEXIST_IE(pPkt)->ucLength = 1; + BSS_20_40_COEXIST_IE(pPkt)->ucData = 0x01; + LR_TDLS_FME_FIELD_FILL(3); + + /* 3.18 Link Identifier */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, + prBssInfo->aucBSSID, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, + pPeerMac, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, + prBssInfo->aucOwnMacAddr, 6); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* Append extra IEs */ + /* + * 3.10 RSNIE (optional) + * 3.13 FTIE (optional) + * 3.14 Timeout Interval (optional) + */ + if (pAppendIe != NULL) { + kalMemCopy(pPkt, pAppendIe, AppendIeLen); + LR_TDLS_FME_FIELD_FILL(AppendIeLen); + } + } + + /* 4. Update packet length */ + prMsduInfo->len = u4PktLen; + + /* 5. send the data frame */ + wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); + + return TDLS_STATUS_PENDING; +} + +uint32_t +TdlsDataFrameSend_CONFIRM(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t *pPeerMac, + uint8_t ucActionCode, + uint8_t ucDialogToken, uint16_t u2StatusCode, + uint8_t *pAppendIe, uint32_t AppendIeLen) +{ + + struct GLUE_INFO *prGlueInfo; + struct BSS_INFO *prBssInfo; + struct PM_PROFILE_SETUP_INFO *prPmProfSetupInfo; + struct sk_buff *prMsduInfo; + uint8_t *pPkt; + uint32_t u4PktLen, u4IeLen; + + /* allocate/init packet */ + prGlueInfo = (struct GLUE_INFO *) prAdapter->prGlueInfo; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + if (prBssInfo == NULL) { + DBGLOG(TDLS, ERROR, "prBssInfo %d is NULL!\n" + , prStaRec->ucBssIndex); + return 0; + } + + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + + prMsduInfo = kalPacketAllocWithHeadroom(prGlueInfo, 512, &pPkt); + if (prMsduInfo == NULL) + return TDLS_STATUS_RESOURCES; + + prMsduInfo->dev = wlanGetNetDev(prGlueInfo, + prStaRec->ucBssIndex); + if (prMsduInfo->dev == NULL) { + kalPacketFree(prGlueInfo, prMsduInfo); + return TDLS_STATUS_FAIL; + } + + /* make up frame content */ + /* 1. 802.3 header */ + kalMemCopy(pPkt, pPeerMac, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(pPkt, prBssInfo->aucOwnMacAddr, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + *(uint16_t *) pPkt = htons(TDLS_FRM_PROT_TYPE); + LR_TDLS_FME_FIELD_FILL(2); + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + LR_TDLS_FME_FIELD_FILL(1); + + /* + * 3.1 Category + * 3.2 Action + * 3.3 Status Code + * 3.4 Dialog Token + *** 3.5 - 3.9 should be only included for Status Code=0 (Successful) + * 3.5 RSNIE (optional) + * 3.6 EDCA Parameter Set + * 3.7 FTIE (optional) + * 3.8 Timeout Interval (optional) + * 3.9 HT Operation (optional) + * 3.10 Link Identifier + */ + + /* 3.1 Category */ + *pPkt = TDLS_FRM_CATEGORY; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3.2 Action */ + *pPkt = ucActionCode; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3.3 Status Code */ + kalMemCopy(pPkt, &u2StatusCode, 2); + LR_TDLS_FME_FIELD_FILL(2); + + /* 3.4 Dialog Token */ + *pPkt = ucDialogToken; + LR_TDLS_FME_FIELD_FILL(1); + + if (u2StatusCode == 0) { + /* + * 3.5 RSNIE (optional) + * 3.7 FTIE (optional) + * 3.8 Timeout Interval (optional) + */ + if (pAppendIe) { + kalMemCopy(pPkt, pAppendIe, AppendIeLen); + LR_TDLS_FME_FIELD_FILL(AppendIeLen); + } + + /* 3.6 EDCA Parameter Set */ + /* HT WMM IE append */ + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) { + u4IeLen = mqmGenerateWmmInfoIEByStaRec(prAdapter, + prBssInfo, prStaRec, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + u4IeLen = mqmGenerateWmmParamIEByParam(prAdapter, + prBssInfo, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } + } + + /* 3.10 Link Identifier */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, + prBssInfo->aucBSSID, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, + prBssInfo->aucOwnMacAddr, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, + pPeerMac, 6); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 4. Update packet length */ + prMsduInfo->len = u4PktLen; + + /* 5. send the data frame */ + wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); + + return TDLS_STATUS_PENDING; +} + +/* + * \brief This routine is called to transmit a TDLS data frame. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[in] + * \param[in] + * \param[in] buf includes RSN IE + FT IE + Lifetimeout IE + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t /* TDLS_STATUS */ +TdlsDataFrameSend_DISCOVERY_REQ(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t *pPeerMac, + uint8_t ucActionCode, + uint8_t ucDialogToken, uint16_t u2StatusCode, + uint8_t *pAppendIe, uint32_t AppendIeLen) +{ + struct GLUE_INFO *prGlueInfo; + struct BSS_INFO *prBssInfo; + struct PM_PROFILE_SETUP_INFO *prPmProfSetupInfo; + struct sk_buff *prMsduInfo; + struct MSDU_INFO *prMsduInfoMgmt; + uint8_t *pPkt, *pucInitiator, *pucResponder; + uint32_t u4PktLen, u4IeLen; + + prGlueInfo = (struct GLUE_INFO *) prAdapter->prGlueInfo; + + if (prStaRec != NULL) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + if (prBssInfo == NULL) { + DBGLOG(TDLS, ERROR, "prBssInfo %d is NULL!\n" + , prStaRec->ucBssIndex); + return TDLS_STATUS_FAIL; + } + } else + return TDLS_STATUS_FAIL; + + /* allocate/init packet */ + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + prMsduInfo = NULL; + prMsduInfoMgmt = NULL; + + /* make up frame content */ + prMsduInfo = kalPacketAllocWithHeadroom(prGlueInfo, 512, &pPkt); + if (prMsduInfo == NULL) + return TDLS_STATUS_RESOURCES; + + prMsduInfo->dev = wlanGetNetDev(prGlueInfo, + prStaRec->ucBssIndex); + if (prMsduInfo->dev == NULL) { + kalPacketFree(prGlueInfo, prMsduInfo); + return TDLS_STATUS_FAIL; + } + + /* 1. 802.3 header */ + kalMemCopy(pPkt, pPeerMac, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(pPkt, prBssInfo->aucOwnMacAddr, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + *(uint16_t *) pPkt = htons(TDLS_FRM_PROT_TYPE); + LR_TDLS_FME_FIELD_FILL(2); + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + LR_TDLS_FME_FIELD_FILL(1); + + /* + * 3.1 Category + * 3.2 Action + * 3.3 Dialog Token + * 3.4 Link Identifier + */ + + /* 3.1 Category */ + *pPkt = TDLS_FRM_CATEGORY; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3.2 Action */ + *pPkt = ucActionCode; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3.3 Dialog Token */ + *pPkt = ucDialogToken; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3.4 Link Identifier */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, + prBssInfo->aucBSSID, 6); + pucInitiator = prBssInfo->aucOwnMacAddr; + pucResponder = pPeerMac; + prStaRec->flgTdlsIsInitiator = TRUE; + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, pucInitiator, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, pucResponder, 6); + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 4. Update packet length */ + prMsduInfo->len = u4PktLen; + + /* 5. send the data frame */ + wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); + + return TDLS_STATUS_PENDING; +} + +uint32_t +TdlsDataFrameSend_DISCOVERY_RSP(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t *pPeerMac, + uint8_t ucActionCode, + uint8_t ucDialogToken, uint16_t u2StatusCode, + uint8_t *pAppendIe, uint32_t AppendIeLen) +{ + struct GLUE_INFO *prGlueInfo; + struct BSS_INFO *prBssInfo; + struct PM_PROFILE_SETUP_INFO *prPmProfSetupInfo; + struct MSDU_INFO *prMsduInfoMgmt; + uint8_t *pPkt, *pucInitiator, *pucResponder; + uint32_t u4PktLen, u4IeLen; + uint16_t u2CapInfo; + struct WLAN_MAC_HEADER *prHdr; + + prGlueInfo = (struct GLUE_INFO *) prAdapter->prGlueInfo; + + /* sanity check */ + if (prStaRec != NULL) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + if (prBssInfo == NULL) { + DBGLOG(TDLS, ERROR, "prBssInfo %d is NULL!\n" + , prStaRec->ucBssIndex); + return TDLS_STATUS_FAIL; + } + } else + return TDLS_STATUS_FAIL; + + /* allocate/init packet */ + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + prMsduInfoMgmt = NULL; + + /* make up frame content */ + prMsduInfoMgmt = (struct MSDU_INFO *) cnmMgtPktAlloc(prAdapter, + PUBLIC_ACTION_MAX_LEN); + if (prMsduInfoMgmt == NULL) + return TDLS_STATUS_RESOURCES; + + pPkt = (uint8_t *) prMsduInfoMgmt->prPacket; + prHdr = (struct WLAN_MAC_HEADER *) pPkt; + + /* 1. 802.11 header */ + prHdr->u2FrameCtrl = MAC_FRAME_ACTION; + prHdr->u2DurationID = 0; + kalMemCopy(prHdr->aucAddr1, pPeerMac, TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(prHdr->aucAddr2, prBssInfo->aucOwnMacAddr, + TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(prHdr->aucAddr3, prBssInfo->aucBSSID, TDLS_FME_MAC_ADDR_LEN); + prHdr->u2SeqCtrl = 0; + LR_TDLS_FME_FIELD_FILL(sizeof(struct WLAN_MAC_HEADER)); + + + /* + * 3.1 Category + * 3.2 Action + * 3.3 Dialog Token + * 3.4 Capability + * 3.5 Supported rates + * 3.6 Extended supported rates + * 3.7 Supported Channels (optional) + * 3.8 RSNIE + * 3.9 Extended Capabilities + * 3.10 FTIE + * 3.11 Timeout Interval (optional) + * 3.12 Supported Regulatory Classes (optional) + * 3.13 HT Capabilities + * 3.14 20/40 BSS Coexistence + * 3.15 Link Identifier + */ + + /* 3.1 Category */ + *pPkt = CATEGORY_PUBLIC_ACTION; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3.2 Action */ + *pPkt = ucActionCode; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3.3 Dialog Token */ + *pPkt = ucDialogToken; + LR_TDLS_FME_FIELD_FILL(1); + + + /* 3.4 Capability */ + u2CapInfo = assocBuildCapabilityInfo(prAdapter, prStaRec); + WLAN_SET_FIELD_16(pPkt, u2CapInfo); + LR_TDLS_FME_FIELD_FILL(2); + + /* + * 3.5 Supported rates + * 3.6 Extended supported rates + * 3.7 Supported Channels (optional) + */ + u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, prStaRec, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3.9 Extended Capabilities */ + EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP; + EXT_CAP_IE(pPkt)->ucLength = 5; + + EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */ + EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */ + EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */ + + /* bit 28 TDLS_EX_CAP_PEER_UAPSD */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24)); + /* bit 30 TDLS_EX_CAP_CHAN_SWITCH */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24)); + /* bit 37 TDLS_EX_CAP_TDLS */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32)); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* + * 3.8 RSNIE + * 3.10 FTIE + * 3.11 Timeout Interval (optional) + */ + if (pAppendIe != NULL) { + kalMemCopy(pPkt, pAppendIe, AppendIeLen); + LR_TDLS_FME_FIELD_FILL(AppendIeLen); + } + + /* 3.12 Supported Regulatory Classes (optional) */ + /* Note: if we do not put the IE, Marvell STA will + * decline our TDLS setup request + */ + u4IeLen = rlmDomainSupOperatingClassIeFill(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3.13 HT Capabilities */ + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) { + u4IeLen = rlmFillHtCapIEByAdapter(prAdapter, prBssInfo, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } + +#if 0 /* TODO: VHT support */ +#if CFG_SUPPORT_802_11AC + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AC) { + u4IeLen = rlmFillVhtCapIEByAdapter(prAdapter, prBssInfo, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } +#endif +#endif + + /* 3.14 20/40 BSS Coexistence */ + BSS_20_40_COEXIST_IE(pPkt)->ucId = ELEM_ID_20_40_BSS_COEXISTENCE; + BSS_20_40_COEXIST_IE(pPkt)->ucLength = 1; + BSS_20_40_COEXIST_IE(pPkt)->ucData = 0x01; + LR_TDLS_FME_FIELD_FILL(3); + + /* 3.15 Link Identifier */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, + prBssInfo->aucBSSID, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, + pPeerMac, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, + prBssInfo->aucOwnMacAddr, 6); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + pucInitiator = pPeerMac; + pucResponder = prBssInfo->aucOwnMacAddr; + if (prStaRec != NULL) + prStaRec->flgTdlsIsInitiator = FALSE; + + if (prMsduInfoMgmt != NULL) { + prMsduInfoMgmt->ucPacketType = TX_PACKET_TYPE_MGMT; + prMsduInfoMgmt->ucStaRecIndex = + prBssInfo->prStaRecOfAP->ucIndex; + prMsduInfoMgmt->ucBssIndex = prBssInfo->ucBssIndex; + prMsduInfoMgmt->ucMacHeaderLength = + WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfoMgmt->fgIs802_1x = FALSE; + prMsduInfoMgmt->fgIs802_11 = TRUE; + prMsduInfoMgmt->u2FrameLength = u4PktLen; + prMsduInfoMgmt->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfoMgmt->pfTxDoneHandler = NULL; + + /* Send them to HW queue */ + nicTxEnqueueMsdu(prAdapter, prMsduInfoMgmt); + } + + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to send a command to TDLS module. + * + * \param[in] prGlueInfo Pointer to the Adapter structure + * \param[in] prInBuf A pointer to the command string buffer + * \param[in] u4InBufLen The length of the buffer + * \param[out] None + * + * \retval None + */ +/*----------------------------------------------------------------------------*/ +void TdlsexEventHandle(struct GLUE_INFO *prGlueInfo, + uint8_t *prInBuf, uint32_t u4InBufLen) +{ + uint32_t u4EventId; + + DBGLOG(TDLS, INFO, "TdlsexEventHandle\n"); + + /* sanity check */ + if ((prGlueInfo == NULL) || (prInBuf == NULL)) + return; /* shall not be here */ + + /* handle */ + u4EventId = *(uint32_t *) prInBuf; + u4InBufLen -= 4; + + switch (u4EventId) { + case TDLS_HOST_EVENT_TEAR_DOWN: + DBGLOG(TDLS, INFO, "TDLS_HOST_EVENT_TEAR_DOWN\n"); + TdlsEventTearDown(prGlueInfo, prInBuf + 4, u4InBufLen); + break; + + case TDLS_HOST_EVENT_TX_DONE: + + break; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to do tear down. + * + * \param[in] prGlueInfo Pointer to the Adapter structure + * \param[in] prInBuf A pointer to the command string buffer, + * from u4EventSubId + * \param[in] u4InBufLen The length of the buffer + * \param[out] None + * + * \retval None + * + */ +/*----------------------------------------------------------------------------*/ +void TdlsEventTearDown(struct GLUE_INFO *prGlueInfo, + uint8_t *prInBuf, uint32_t u4InBufLen) +{ + struct STA_RECORD *prStaRec; + uint16_t u2ReasonCode = TDLS_REASON_CODE_NONE; + uint32_t u4TearDownSubId; + uint8_t *pMac, aucZeroMac[6]; + struct net_device *prDev = NULL; + + /* init */ + u4TearDownSubId = *(uint32_t *) prInBuf; + kalMemZero(aucZeroMac, sizeof(aucZeroMac)); + pMac = aucZeroMac; + + prStaRec = cnmGetStaRecByIndex(prGlueInfo->prAdapter, + *(prInBuf + 4)); + + /* sanity check */ + if (prStaRec == NULL) + return; + + pMac = prStaRec->aucMacAddr; + + if (fgIsPtiTimeoutSkip == TRUE) { + /* skip PTI timeout event */ + if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_TIMEOUT) + return; + } + + prDev = wlanGetNetDev(prGlueInfo, prStaRec->ucBssIndex); + if (prDev == NULL) + return; + + if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_TIMEOUT) { + DBGLOG(TDLS, INFO, + "TDLS_HOST_EVENT_TD_PTI_TIMEOUT TDLS_REASON_CODE_UNSPECIFIED\n"); + u2ReasonCode = TDLS_REASON_CODE_UNSPECIFIED; + + cfg80211_tdls_oper_request(prDev, + prStaRec->aucMacAddr, + NL80211_TDLS_TEARDOWN, + WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE, + GFP_ATOMIC); + } + + if (u4TearDownSubId == TDLS_HOST_EVENT_TD_AGE_TIMEOUT) { + DBGLOG(TDLS, INFO, + "TDLS_HOST_EVENT_TD_AGE_TIMEOUT TDLS_REASON_CODE_UNREACHABLE\n"); + u2ReasonCode = TDLS_REASON_CODE_UNREACHABLE; + + cfg80211_tdls_oper_request(prDev, + prStaRec->aucMacAddr, NL80211_TDLS_TEARDOWN, + WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE, + GFP_ATOMIC); + + } + + DBGLOG(TDLS, INFO, "\n\n u2ReasonCode = %u\n\n", + u2ReasonCode); +} + +void TdlsBssExtCapParse(struct STA_RECORD *prStaRec, + uint8_t *pucIE) +{ + uint8_t *pucIeExtCap; + + /* sanity check */ + if ((prStaRec == NULL) || (pucIE == NULL)) + return; + + if (IE_ID(pucIE) != ELEM_ID_EXTENDED_CAP) + return; + + /* + * from bit0 ~ + * bit 38: TDLS Prohibited + * The TDLS Prohibited subfield indicates whether the use of TDLS is + * prohibited. + * The field is set to 1 to indicate that TDLS is prohibited + * and to 0 to indicate that TDLS is allowed. + */ + if (IE_LEN(pucIE) < 5) + return; /* we need 39/8 = 5 bytes */ + + /* init */ + prStaRec->fgTdlsIsProhibited = FALSE; + prStaRec->fgTdlsIsChSwProhibited = FALSE; + + /* parse */ + pucIeExtCap = pucIE + 2; + pucIeExtCap += 4; /* shift to the byte we care about */ + + if ((*pucIeExtCap) & BIT(38 - 32)) + prStaRec->fgTdlsIsProhibited = TRUE; + if ((*pucIeExtCap) & BIT(39 - 32)) + prStaRec->fgTdlsIsChSwProhibited = TRUE; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Generate CMD_ID_SET_TDLS_CH_SW command + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +uint32_t +TdlsSendChSwControlCmd(struct ADAPTER *prAdapter, + void *pvSetBuffer, uint32_t u4SetBufferLen, + uint32_t *pu4SetInfoLen) +{ + + struct CMD_TDLS_CH_SW rCmdTdlsChSwCtrl; + struct BSS_INFO *prBssInfo; + + prBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, AIS_DEFAULT_INDEX); + + /* send command packet for scan */ + kalMemZero(&rCmdTdlsChSwCtrl, + sizeof(struct CMD_TDLS_CH_SW)); + + rCmdTdlsChSwCtrl.fgIsTDLSChSwProhibit = + prBssInfo->fgTdlsIsChSwProhibited; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_TDLS_CH_SW, + TRUE, + FALSE, FALSE, NULL, NULL, + sizeof(struct CMD_TDLS_CH_SW), + (uint8_t *)&rCmdTdlsChSwCtrl, NULL, 0); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to handle TX done for TDLS data packet. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[in] rTxDoneStatus TX Done status + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +void TdlsHandleTxDoneStatus(struct ADAPTER *prAdapter, + enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + DBGLOG(TDLS, INFO, "TdlsHandleTxDoneStatus=%d, fgIsWaitForTxDone=%d", + rTxDoneStatus, fgIsWaitForTxDone); + if (fgIsWaitForTxDone == TRUE) { + kalOidComplete(prAdapter->prGlueInfo, 0, 0, + WLAN_STATUS_SUCCESS); + fgIsWaitForTxDone = FALSE; + } +} + +#endif /* CFG_SUPPORT_TDLS */ + +/* End of tdls.c */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/tkip_mic.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/tkip_mic.c new file mode 100644 index 0000000000000..70af23b16c4c7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/tkip_mic.c @@ -0,0 +1,571 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/TRUNK/MT6620_WiFi_Firmware/ + * mcu/wifi/mgmt/tkip_mic.c#7 + */ + +/*! \file tkip_sw.c + * \brief This file include the tkip encrypted / decrypted mic function. + */ +/******************************************************************************* + * Copyright (c) 2003-2004 Inprocomm, 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 + * Inprocomm, Inc. + ******************************************************************************* + */ + +/******************************************************************************* + * C O M P I L E 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 + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/* length of TKIP and CCMP MIC field */ +#define WLAN_MAC_MIC_LEN 8 + +#define MK16_TKIP(x, y) (((uint16_t) (x) << 8) | (uint16_t) (y)) + +/* obtain low 8-bit from 16-bit value */ +#define LO_8BITS(x) ((x) & 0x00ff) + +/* obtain high 8-bit from 16-bit value */ +#define HI_8BITS(x) ((x) >> 8) + +#define ROTR32(x, y) (((x) >> (y)) | ((x) << (32 - (y)))) +#define ROTL32(x, y) (((x) << (y)) | ((x) >> (32 - (y)))) +#define ROTR16(x, y) (((x) >> (y)) | ((x) << (16 - (y)))) +#define ROTL16(x, y) (((x) << (y)) | ((x) >> (16 - (y)))) + +#define XSWAP32(x) ((((x) & 0xFF00FF00) >> 8) | (((x) & 0x00FF00FF) << 8)) + +/* obtain 16-bit entries SBOX form two 8-bit entries SBOX1 and SBOX2 */ +#define SBOX(x) (tkipSBOX1[LO_8BITS(x)] ^ tkipSBOX2[HI_8BITS(x)]) + + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +const uint16_t tkipSBOX1[256] = { + 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, + 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A, + 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B, + 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B, + 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F, + 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F, + 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5, + 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F, + 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB, + 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397, + 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED, + 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A, + 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194, + 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3, + 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104, + 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D, + 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39, + 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695, + 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83, + 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76, + 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4, + 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B, + 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0, + 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018, + 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751, + 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85, + 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12, + 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9, + 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7, + 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A, + 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8, + 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A +}; + +const uint16_t tkipSBOX2[256] = { + 0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491, + 0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC, + 0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB, + 0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B, + 0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83, + 0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A, + 0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F, + 0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA, + 0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B, + 0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713, + 0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6, + 0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85, + 0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411, + 0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B, + 0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1, + 0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF, + 0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E, + 0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6, + 0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B, + 0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD, + 0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8, + 0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2, + 0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049, + 0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810, + 0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197, + 0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F, + 0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C, + 0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927, + 0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733, + 0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5, + 0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0, + 0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C +}; + +/******************************************************************************* + * 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 + ******************************************************************************* + */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief TKIP Michael block function + * + * \param[in][out] pu4L - pointer to left value + * \param[in][out] pu4PR - pointer to right value + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void tkipMicB(IN OUT uint32_t *pu4L, IN OUT uint32_t *pu4R) +{ + *pu4R = *pu4R ^ ROTL32(*pu4L, 17); /* r <- r ^ (l<<<17) */ + *pu4L = (*pu4L + *pu4R); /* l <- (l+r) mod 2^32 */ + *pu4R = *pu4R ^ XSWAP32(*pu4L); /* r <- r ^ XSWAP(l) */ + *pu4L = (*pu4L + *pu4R); /* l <- (l+r) mod 2^32 */ + *pu4R = *pu4R ^ ROTL32(*pu4L, 3); /* r <- r ^ (l<<<3) */ + *pu4L = (*pu4L + *pu4R); /* l <- (l+r) mod 2^32 */ + *pu4R = *pu4R ^ ROTR32(*pu4L, 2); /* r <- r ^ (l>>>2) */ + *pu4L = (*pu4L + *pu4R); /* l <- (l+r) mod 2^32 */ +} /* tkipMicB */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief TKIP Michael generation function + * + * \param[in] pucMickey Pointer to MIC key + * \param[in] pucData Pointer to message + * \param[in] u4DataLen Message length, in byte(s) + * \param[in] pucSa Pointer to source address SA + * \param[in] pucDa Pointer to destination address DA + * \param[in] ucPriority Priority of IEEE 802.11 traffic class + * \param[out] pucMic Pointer to 64-bit MIC + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void +tkipMicGen(IN uint8_t *pucMickey, + IN uint8_t *pucData, + IN uint32_t u4DataLen, IN uint8_t *pucSa, IN uint8_t *pucDa, + IN uint8_t ucPriority, OUT uint8_t *pucMic) +{ + + uint32_t i; + uint32_t l, r; + uint32_t au4Msg[3]; + + WLAN_GET_FIELD_32(pucMickey, &l); + WLAN_GET_FIELD_32(pucMickey + 4, &r); + + /* Michael message processing for DA and SA. */ + WLAN_GET_FIELD_32(pucDa, &au4Msg[0]); + au4Msg[1] = ((uint32_t) pucDa[4]) | ((uint32_t) pucDa[5] << + 8) | + ((uint32_t) pucSa[0] << 16) | ((uint32_t) pucSa[1] << 24); + WLAN_GET_FIELD_32(pucSa + 2, &au4Msg[2]); + + for (i = 0; i < 3; i++) { + l = l ^ au4Msg[i]; + tkipMicB(&l, &r); + } + + /* Michael message processing for priority. */ + au4Msg[0] = (uint32_t) ucPriority; + + l = l ^ au4Msg[0]; + tkipMicB(&l, &r); + + /* Michael message processing for MSDU data playload except + * the last octets which cannot be partitioned into a 32-bit word. + */ + for (i = 0; i < (uint32_t) u4DataLen / 4; i++) { + WLAN_GET_FIELD_32(pucData + i * 4, &au4Msg[0]); + l = l ^ au4Msg[0]; + tkipMicB(&l, &r); + } + + /* Michael message processing for the last uncomplete octets, + * if present, and the padding. + */ + switch (u4DataLen & 3) { + case 1: + au4Msg[0] = ((uint32_t) pucData[u4DataLen - 1]) | + 0x00005A00; + break; + + case 2: + au4Msg[0] = ((uint32_t) pucData[u4DataLen - 2]) | (( + uint32_t) pucData[u4DataLen - 1] << 8) | 0x005A0000; + break; + + case 3: + au4Msg[0] = ((uint32_t) pucData[u4DataLen - 3]) | + ((uint32_t) pucData[u4DataLen - 2] << 8) | (( + uint32_t) pucData[u4DataLen - 1] << 16) | 0x5A000000; + break; + + default: + au4Msg[0] = 0x0000005A; + } + au4Msg[1] = 0; + for (i = 0; i < 2; i++) { + l = l ^ au4Msg[i]; + tkipMicB(&l, &r); + } + + /* return ( l, r ), i.e. MIC */ + WLAN_SET_FIELD_32(pucMic, l); + WLAN_SET_FIELD_32(pucMic + 4, r); + +} /* tkipMicGen */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief this function decapsulate MSDU frame body( with MIC ) according + * to IEEE 802.11i TKIP sepcification. + * + * \param[in] prAdapter Pointer to the adapter object data area. + * \param[in] pucDa Pointer to destination address DA + * \param[in] pucSa Pointer to source address SA + * \param[in] ucPriority Priority of IEEE 802.11 traffic class + * \param[in] pucPayload Pointer to message + * \param[in] u2PayloadLen Message length, in byte(s) + * \param[out] pucMic Pointer to 64-bit MIC + * + * \retval NONE + */ +/*----------------------------------------------------------------------------*/ +void +tkipMicEncapsulate(IN uint8_t *pucDa, + IN uint8_t *pucSa, + IN uint8_t ucPriority, + IN uint16_t u2PayloadLen, IN uint8_t *pucPayload, + IN uint8_t *pucMic, IN uint8_t *pucMicKey) +{ + uint8_t aucMic[8]; /* MIC' */ + + DEBUGFUNC("tkipSwMsduEncapsulate"); + DBGLOG(RSN, LOUD, + "MIC key %02x-%02x-%02x-%02x %02x-%02x-%02x-%02x\n", + pucMicKey[0], pucMicKey[1], pucMicKey[2], pucMicKey[3], + pucMicKey[4], pucMicKey[5], pucMicKey[6], pucMicKey[7]); + + tkipMicGen(pucMicKey, (uint8_t *) pucPayload, u2PayloadLen, + pucSa, pucDa, ucPriority, aucMic); + + kalMemCopy((uint8_t *) pucMic, &aucMic[0], + WLAN_MAC_MIC_LEN); + + DBGLOG(RSN, LOUD, + "Mic %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n", + pucMic[0], pucMic[1], pucMic[2], pucMic[3], pucMic[4], + pucMic[5], pucMic[6], pucMic[7]); + +} /* tkipSwMsduEncapsulate */ + +/*----------------------------------------------------------------------------*/ +u_int8_t tkipMicDecapsulate(IN struct SW_RFB *prSwRfb, + IN uint8_t *pucMicKey) +{ + uint8_t *pucMic1; /* MIC */ + uint8_t aucMic2[8]; /* MIC' */ + uint8_t ucPriority; + u_int8_t fgStatus; + uint8_t *pucSa, *pucDa; + /* PUCHAR pucMickey; */ + uint8_t *pucFrameBody; + uint16_t u2FrameBodyLen; + struct WLAN_MAC_HEADER *prMacHeader; + + DEBUGFUNC("tkipMicDecapsulate"); + + /* prRxStatus = prSwRfb->prRxStatus; */ + pucFrameBody = prSwRfb->pucPayload; + u2FrameBodyLen = prSwRfb->u2PayloadLength; + + if (!pucFrameBody) { + DBGLOG(RSN, INFO, "pucPayload is NULL, drop this packet"); + return FALSE; + } + + DBGLOG(RSN, LOUD, "Before TKIP MSDU Decapsulate:\n"); + DBGLOG(RSN, LOUD, "MIC key:\n"); + /* DBGLOG_MEM8(RSN, LOUD, pucMicKey, 8); */ + + prMacHeader = (struct WLAN_MAC_HEADER *) prSwRfb->pvHeader; + pucDa = prMacHeader->aucAddr1; + pucSa = prMacHeader->aucAddr3; + + switch (prMacHeader->u2FrameCtrl & MASK_TO_DS_FROM_DS) { + case 0: + pucDa = prMacHeader->aucAddr1; + pucSa = prMacHeader->aucAddr2; + break; + case MASK_FC_FROM_DS: + pucDa = prMacHeader->aucAddr1; + pucSa = prMacHeader->aucAddr3; + break; + default: + ASSERT((prMacHeader->u2FrameCtrl & MASK_FC_TO_DS) == 0); + return TRUE; + } + + if (RXM_IS_QOS_DATA_FRAME(prSwRfb->u2FrameCtrl)) + ucPriority = (uint8_t) ((((struct WLAN_MAC_HEADER_QOS *) + prSwRfb->pvHeader)->u2QosCtrl) & MASK_QC_TID); + else + ucPriority = 0; + + /* generate MIC' */ + tkipMicGen(pucMicKey, pucFrameBody, + u2FrameBodyLen - WLAN_MAC_MIC_LEN, pucSa, pucDa, ucPriority, + aucMic2); + + /* verify MIC and MIC' */ + pucMic1 = &pucFrameBody[u2FrameBodyLen - WLAN_MAC_MIC_LEN]; + if (pucMic1[0] == aucMic2[0] && pucMic1[1] == aucMic2[1] && + pucMic1[2] == aucMic2[2] && pucMic1[3] == aucMic2[3] && + pucMic1[4] == aucMic2[4] && pucMic1[5] == aucMic2[5] && + pucMic1[6] == aucMic2[6] && pucMic1[7] == aucMic2[7]) { + u2FrameBodyLen -= WLAN_MAC_MIC_LEN; + fgStatus = TRUE; + } else { + fgStatus = FALSE; + } + + /* DBGLOG(RSN, LOUD, ("TKIP MIC:\n")); */ + /* DBGLOG_MEM8(RSN, LOUD, pucMic1, 8); */ + /* DBGLOG(RSN, LOUD, ("TKIP MIC':\n")); */ + /* DBGLOG_MEM8(RSN, LOUD, aucMic2, 8); */ + + prSwRfb->u2PayloadLength = u2FrameBodyLen; + + DBGLOG(RSN, LOUD, "After TKIP MSDU Decapsulate:\n"); + DBGLOG(RSN, LOUD, "Frame body: (length = %u)\n", + u2FrameBodyLen); + /* DBGLOG_MEM8(RSN, LOUD, pucFrameBody, u2FrameBodyLen); */ + + return fgStatus; + +} /* tkipMicDecapsulate */ + + +/*----------------------------------------------------------------------------*/ +u_int8_t tkipMicDecapsulateInRxHdrTransMode( + IN struct SW_RFB *prSwRfb, IN uint8_t *pucMicKey) +{ + uint8_t *pucMic1; /* MIC */ + uint8_t aucMic2[8]; /* MIC' */ + u_int8_t fgStatus = FALSE; + /* PUCHAR pucMickey; */ + uint8_t *pucFrameBody; + uint16_t u2FrameBodyLen; + struct sk_buff *prSkb = NULL; +#if 0 + struct WLAN_MAC_HEADER *prMacHeader; + uint8_t *pucSa, *pucDa; + uint8_t ucPriority; + uint8_t aucDA[6]; + uint8_t aucSA[6]; + uint8_t aucType[2]; +#endif + + DEBUGFUNC("tkipMicDecapsulateInRxHdrTransMode"); + + /* prRxStatus = prSwRfb->prRxStatus; */ + pucFrameBody = prSwRfb->pucPayload; + u2FrameBodyLen = prSwRfb->u2PayloadLength; + + if (!pucFrameBody) { + DBGLOG(RSN, INFO, "pucPayload is NULL, drop this packet"); + return FALSE; + } + + DBGLOG(RSN, LOUD, "Before TKIP MSDU Decapsulate:\n"); + DBGLOG(RSN, LOUD, "MIC key:\n"); + /* DBGLOG_MEM8(RSN, LOUD, pucMicKey, 8); */ + + prSkb = dev_alloc_skb(u2FrameBodyLen + ETHERNET_HEADER_SZ * + 4); + if (prSkb) { + /* copy to etherhdr + payload to skb data */ + kalMemCopy(prSkb->data, prSwRfb->pvHeader, + u2FrameBodyLen + ETHERNET_HEADER_SZ); + *(prSkb->data + 6) = ETH_LLC_DSAP_SNAP; + *(prSkb->data + 7) = ETH_LLC_SSAP_SNAP; + *(prSkb->data + 8) = ETH_LLC_CONTROL_UNNUMBERED_INFORMATION; + *(prSkb->data + 9) = 0x00; + *(prSkb->data + 10) = 0x00; + *(prSkb->data + 11) = 0x00; + *(prSkb->data + 12) = *(uint8_t *)(prSwRfb->pvHeader + 12); + *(prSkb->data + 13) = *(uint8_t *)(prSwRfb->pvHeader + 13); + + tkipMicGen(pucMicKey, + prSkb->data + 6, + u2FrameBodyLen - WLAN_MAC_MIC_LEN + 8, + prSwRfb->pvHeader + 6, + prSwRfb->pvHeader, + prSwRfb->ucTid, aucMic2); + + if (prSkb) + kfree_skb((struct sk_buff *)prSkb); + } else { + DBGLOG(RX, ERROR, "MIC SW DEC1\n"); + return fgStatus; + } + + + /* verify MIC and MIC' */ + pucMic1 = &pucFrameBody[u2FrameBodyLen - WLAN_MAC_MIC_LEN]; + if (pucMic1[0] == aucMic2[0] && pucMic1[1] == aucMic2[1] && + pucMic1[2] == aucMic2[2] && pucMic1[3] == aucMic2[3] && + pucMic1[4] == aucMic2[4] && pucMic1[5] == aucMic2[5] && + pucMic1[6] == aucMic2[6] && pucMic1[7] == aucMic2[7]) { + u2FrameBodyLen -= WLAN_MAC_MIC_LEN; + fgStatus = TRUE; + } else { + fgStatus = FALSE; + DBGLOG(RX, ERROR, "MIC SW DEC2\n"); + } + +#if 0 + /* perform header transfer for tkip defragment frame, + * if receiving 802.11 pkt + */ + if (fgStatus == TRUE) { + /* reassign payload address */ + prSwRfb->pucPayload += (ETH_LLC_LEN + ETH_SNAP_LEN); + + /* reassign payload length */ + u2FrameBodyLen -= (ETH_LLC_LEN + ETH_SNAP_LEN); + + prSwRfb->pvHeader = prSwRfb->pucPayload - + (ETHERNET_HEADER_SZ); + + kalMemCopy(&aucDA[0], pucDa, MAC_ADDR_LEN); + kalMemCopy(&aucSA[0], pucSa, MAC_ADDR_LEN); + kalMemCopy(&aucType[0], prSwRfb->pucPayload - 2, 2); + + kalMemCopy(prSwRfb->pvHeader, &aucDA[0], MAC_ADDR_LEN); + kalMemCopy(prSwRfb->pvHeader + MAC_ADDR_LEN, &aucSA[0], + MAC_ADDR_LEN); + kalMemCopy(prSwRfb->pvHeader + MAC_ADDR_LEN + 2, + &aucType[0], 2); + + prSwRfb->u2HeaderLen = ETHERNET_HEADER_SZ; + } +#endif + + /* DBGLOG(RSN, LOUD, ("TKIP MIC:\n")); */ + /* DBGLOG_MEM8(RSN, LOUD, pucMic1, 8); */ + /* DBGLOG(RSN, LOUD, ("TKIP MIC':\n")); */ + /* DBGLOG_MEM8(RSN, LOUD, aucMic2, 8); */ + + prSwRfb->u2PayloadLength = u2FrameBodyLen; + + DBGLOG(RSN, LOUD, "After TKIP MSDU Decapsulate:\n"); + DBGLOG(RSN, LOUD, "Frame body: (length = %u)\n", + u2FrameBodyLen); + /* DBGLOG_MEM8(RSN, LOUD, pucFrameBody, u2FrameBodyLen); */ + + return fgStatus; + +} /* tkipMicDecapsulate */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/twt.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/twt.c new file mode 100644 index 0000000000000..776a70070b058 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/twt.c @@ -0,0 +1,597 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2017 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2017 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "twt.c" +* \brief Functions for processing TWT related elements and frames. +*/ + +/******************************************************************************* +* C O M P I L E 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 twtFillTWTElement( + struct _IE_TWT_T *prTWTBuf, + uint8_t ucTWTFlowId, + struct _TWT_PARAMS_T *prTWTParams); + +static void twtParseTWTElement( + struct _IE_TWT_T *prTWTIE, + struct _TWT_PARAMS_T *prTWTParams); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* \brief Send TWT Setup frame (S1G action frame) +* +* \param[in] prAdapter ADAPTER structure +* prStaRec station record structure +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +uint32_t twtSendSetupFrame( + struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t ucTWTFlowId, + struct _TWT_PARAMS_T *prTWTParams, + PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + struct MSDU_INFO *prMsduInfo; + struct _ACTION_TWT_SETUP_FRAME *prTxFrame; + struct BSS_INFO *prBssInfo; + uint16_t u2EstimatedFrameLen; + struct _IE_TWT_T *prTWTBuf; + + ASSERT(prAdapter); + ASSERT(prStaRec); + ASSERT(prTWTParams); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + ASSERT(prBssInfo); + + /* Calculate MSDU buffer length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + + sizeof(struct _ACTION_TWT_SETUP_FRAME); + + /* Alloc MSDU_INFO */ + prMsduInfo = (struct MSDU_INFO *) + cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + + if (!prMsduInfo) { + DBGLOG(TWT_REQUESTER, WARN, + "No MSDU_INFO_T for sending TWT Setup Frame.\n"); + return WLAN_STATUS_RESOURCES; + } + + kalMemZero(prMsduInfo->prPacket, u2EstimatedFrameLen); + + prTxFrame = prMsduInfo->prPacket; + + /* Fill frame ctrl */ + 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); + + /* Compose the frame body's frame */ + prTxFrame->ucCategory = CATEGORY_S1G_ACTION; + prTxFrame->ucAction = ACTION_S1G_TWT_SETUP; + + prTWTBuf = &(prTxFrame->rTWT); + twtFillTWTElement(prTWTBuf, ucTWTFlowId, prTWTParams); + + /* Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prBssInfo->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + sizeof(struct _ACTION_TWT_SETUP_FRAME), + pfTxDoneHandler, MSDU_RATE_MODE_AUTO); + + /* Enqueue the frame to send this action frame */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t twtSendTeardownFrame( + struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t ucTWTFlowId, + PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + struct MSDU_INFO *prMsduInfo; + struct _ACTION_TWT_TEARDOWN_FRAME *prTxFrame; + struct BSS_INFO *prBssInfo; + uint16_t u2EstimatedFrameLen; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + ASSERT(prBssInfo); + + /* Calculate MSDU buffer length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + + sizeof(struct _ACTION_TWT_TEARDOWN_FRAME); + + /* Alloc MSDU_INFO */ + prMsduInfo = (struct MSDU_INFO *) cnmMgtPktAlloc( + prAdapter, u2EstimatedFrameLen); + + if (!prMsduInfo) { + DBGLOG(TWT_REQUESTER, WARN, + "No MSDU_INFO_T for sending TWT Teardown Frame.\n"); + return WLAN_STATUS_RESOURCES; + } + + kalMemZero(prMsduInfo->prPacket, u2EstimatedFrameLen); + + prTxFrame = prMsduInfo->prPacket; + + /* Fill frame ctrl */ + 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); + + /* Compose the frame body's frame */ + prTxFrame->ucCategory = CATEGORY_S1G_ACTION; + prTxFrame->ucAction = ACTION_S1G_TWT_TEARDOWN; + prTxFrame->ucTWTFlow = ucTWTFlowId; + + /* Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prBssInfo->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + sizeof(struct _ACTION_TWT_TEARDOWN_FRAME), + pfTxDoneHandler, MSDU_RATE_MODE_AUTO); + + /* Enqueue the frame to send this action frame */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t twtSendInfoFrame( + struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t ucTWTFlowId, + struct _NEXT_TWT_INFO_T *prNextTWTInfo, + PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + struct MSDU_INFO *prMsduInfo; + struct _ACTION_TWT_INFO_FRAME *prTxFrame; + uint32_t u4Pos = + OFFSET_OF(struct _ACTION_TWT_INFO_FRAME, aucNextTWT[0]); + struct BSS_INFO *prBssInfo; + uint16_t u2EstimatedFrameLen; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + ASSERT(prBssInfo); + + /* Calculate MSDU buffer length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + + sizeof(struct _ACTION_TWT_INFO_FRAME) + + twtGetNextTWTByteCnt(prNextTWTInfo->ucNextTWTSize); + + /* Alloc MSDU_INFO */ + prMsduInfo = (struct MSDU_INFO *) cnmMgtPktAlloc( + prAdapter, u2EstimatedFrameLen); + + if (!prMsduInfo) { + DBGLOG(TWT_REQUESTER, WARN, + "No MSDU_INFO_T for sending TWT Info Frame.\n"); + return WLAN_STATUS_RESOURCES; + } + + kalMemZero(prMsduInfo->prPacket, u2EstimatedFrameLen); + + prTxFrame = prMsduInfo->prPacket; + + /* Fill frame ctrl */ + 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); + + /* Compose the frame body's frame */ + prTxFrame->ucCategory = CATEGORY_S1G_ACTION; + prTxFrame->ucAction = ACTION_S1G_TWT_INFORMATION; + prTxFrame->ucNextTWTCtrl = (ucTWTFlowId & TWT_INFO_FLOW_ID) | + ((prNextTWTInfo->ucNextTWTSize & TWT_INFO_NEXT_TWT_SIZE) << + TWT_INFO_NEXT_TWT_SIZE_OFFSET); + + switch (prNextTWTInfo->ucNextTWTSize) { + case NEXT_TWT_SUBFIELD_64_BITS: + { + uint64_t *pu8NextTWT = + (uint64_t *)(((uint8_t *)prTxFrame) + u4Pos); + *pu8NextTWT = CPU_TO_LE64(prNextTWTInfo->u8NextTWT); + break; + } + + case NEXT_TWT_SUBFIELD_32_BITS: + { + uint32_t *pu4NextTWT = + (uint32_t *)(((uint8_t *)prTxFrame) + u4Pos); + *pu4NextTWT = CPU_TO_LE32( + (uint32_t)(prNextTWTInfo->u8NextTWT & 0xFFFFFFFF)); + break; + } + + case NEXT_TWT_SUBFIELD_48_BITS: + { + uint8_t *pucMem = ((uint8_t *)prTxFrame) + u4Pos; + /* little endian placement */ + *pucMem = prNextTWTInfo->u8NextTWT & 0xFF; + *(pucMem + 1) = (prNextTWTInfo->u8NextTWT >> 8) & 0xFF; + *(pucMem + 2) = (prNextTWTInfo->u8NextTWT >> 16) & 0xFF; + *(pucMem + 3) = (prNextTWTInfo->u8NextTWT >> 24) & 0xFF; + *(pucMem + 4) = (prNextTWTInfo->u8NextTWT >> 32) & 0xFF; + *(pucMem + 5) = (prNextTWTInfo->u8NextTWT >> 40) & 0xFF; + break; + } + + default: + break; + } + + /* Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prBssInfo->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + (sizeof(struct _ACTION_TWT_INFO_FRAME) + + prNextTWTInfo->ucNextTWTSize), + pfTxDoneHandler, MSDU_RATE_MODE_AUTO); + + /* Enqueue the frame to send this action frame */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; +} + +static void twtFillTWTElement( + struct _IE_TWT_T *prTWTBuf, + uint8_t ucTWTFlowId, + struct _TWT_PARAMS_T *prTWTParams) +{ + ASSERT(prTWTBuf); + ASSERT(prTWTParams); + + /* Add TWT element */ + prTWTBuf->ucId = ELEM_ID_TWT; + prTWTBuf->ucLength = sizeof(struct _IE_TWT_T) - ELEM_HDR_LEN; + + /* Request Type */ + prTWTBuf->u2ReqType |= SET_TWT_RT_REQUEST(prTWTParams->fgReq) | + SET_TWT_RT_SETUP_CMD(prTWTParams->ucSetupCmd) | + SET_TWT_RT_TRIGGER(prTWTParams->fgTrigger) | + TWT_REQ_TYPE_IMPLICIT_LAST_BCAST_PARAM | + SET_TWT_RT_FLOW_TYPE(prTWTParams->fgUnannounced) | + SET_TWT_RT_FLOW_ID(ucTWTFlowId) | + SET_TWT_RT_WAKE_INTVAL_EXP(prTWTParams->ucWakeIntvalExponent) | + SET_TWT_RT_PROTECTION(prTWTParams->fgProtect); + + prTWTBuf->u8TWT = CPU_TO_LE64(prTWTParams->u8TWT); + prTWTBuf->ucMinWakeDur = prTWTParams->ucMinWakeDur; + prTWTBuf->u2WakeIntvalMantiss = + CPU_TO_LE16(prTWTParams->u2WakeIntvalMantiss); +} + +static void twtParseTWTElement( + struct _IE_TWT_T *prTWTIE, + struct _TWT_PARAMS_T *prTWTParams) +{ + uint16_t u2ReqType; + + u2ReqType = LE16_TO_CPU(prTWTIE->u2ReqType); + + prTWTParams->fgReq = GET_TWT_RT_REQUEST(u2ReqType); + prTWTParams->ucSetupCmd = GET_TWT_RT_SETUP_CMD(u2ReqType); + prTWTParams->fgTrigger = GET_TWT_RT_TRIGGER(u2ReqType); + prTWTParams->fgUnannounced = GET_TWT_RT_FLOW_TYPE(u2ReqType); + + prTWTParams->ucWakeIntvalExponent = + GET_TWT_RT_WAKE_INTVAL_EXP(u2ReqType); + + prTWTParams->fgProtect = GET_TWT_RT_PROTECTION(u2ReqType); + prTWTParams->u8TWT = LE64_TO_CPU(prTWTIE->u8TWT); + prTWTParams->ucMinWakeDur = prTWTIE->ucMinWakeDur; + + prTWTParams->u2WakeIntvalMantiss = + LE16_TO_CPU(prTWTIE->u2WakeIntvalMantiss); +} + +uint8_t twtGetTxSetupFlowId( + struct MSDU_INFO *prMsduInfo) +{ + uint8_t ucFlowId; + struct _ACTION_TWT_SETUP_FRAME *prTxFrame; + + ASSERT(prMsduInfo); + + prTxFrame = (struct _ACTION_TWT_SETUP_FRAME *)(prMsduInfo->prPacket); + ucFlowId = GET_TWT_RT_FLOW_ID(prTxFrame->rTWT.u2ReqType); + + return ucFlowId; +} + +uint8_t twtGetTxTeardownFlowId( + struct MSDU_INFO *prMsduInfo) +{ + uint8_t ucFlowId; + struct _ACTION_TWT_TEARDOWN_FRAME *prTxFrame; + + ASSERT(prMsduInfo); + + prTxFrame = (struct _ACTION_TWT_TEARDOWN_FRAME *)(prMsduInfo->prPacket); + ucFlowId = (prTxFrame->ucTWTFlow & TWT_TEARDOWN_FLOW_ID); + + return ucFlowId; +} + +uint8_t twtGetTxInfoFlowId( + struct MSDU_INFO *prMsduInfo) +{ + uint8_t ucFlowId; + struct _ACTION_TWT_INFO_FRAME *prTxFrame; + + ASSERT(prMsduInfo); + + prTxFrame = (struct _ACTION_TWT_INFO_FRAME *)(prMsduInfo->prPacket); + ucFlowId = GET_TWT_INFO_FLOW_ID(prTxFrame->ucNextTWTCtrl); + + return ucFlowId; +} + +uint8_t twtGetRxSetupFlowId( + struct _IE_TWT_T *prTWTIE) +{ + uint16_t u2ReqType; + + ASSERT(prTWTIE); + + u2ReqType = LE16_TO_CPU(prTWTIE->u2ReqType); + + return GET_TWT_RT_FLOW_ID(u2ReqType); +} + +void twtProcessS1GAction( + struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb) +{ + struct WLAN_ACTION_FRAME *prRxFrame; + struct _ACTION_TWT_SETUP_FRAME *prRxSetupFrame = NULL; + struct _ACTION_TWT_TEARDOWN_FRAME *prRxTeardownFrame = NULL; + struct _ACTION_TWT_INFO_FRAME *prRxInfoFrame = NULL; + struct STA_RECORD *prStaRec; + struct RX_DESC_OPS_T *prRxDescOps; + + uint8_t ucTWTFlowId; + uint32_t u4Offset; + uint16_t u2ReqType; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxDescOps = prAdapter->chip_info->prRxDescOps; + ASSERT(prRxDescOps->nic_rxd_get_rx_byte_count); + ASSERT(prRxDescOps->nic_rxd_get_pkt_type); + ASSERT(prRxDescOps->nic_rxd_get_wlan_idx); + + prRxFrame = (struct WLAN_ACTION_FRAME *) prSwRfb->pvHeader; + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (!prStaRec) { + DBGLOG(TWT_REQUESTER, WARN, + "Received an S1G Action: wlanIdx[%d] w/o corresponding staRec\n" + , prRxDescOps->nic_rxd_get_wlan_idx(prSwRfb->prRxStatus)); + return; + } + + switch (prRxFrame->ucAction) { + case ACTION_S1G_TWT_SETUP: + prRxSetupFrame = + (struct _ACTION_TWT_SETUP_FRAME *) prSwRfb->pvHeader; + if (prStaRec->ucStaState != STA_STATE_3 || + prSwRfb->u2PacketLen < + sizeof(struct _ACTION_TWT_SETUP_FRAME)) { + DBGLOG(TWT_REQUESTER, WARN, + "Received improper TWT Setup frame\n"); + return; + } + + /* Parse TWT element */ + ucTWTFlowId = twtGetRxSetupFlowId(&(prRxSetupFrame->rTWT)); + twtParseTWTElement(&(prRxSetupFrame->rTWT), + &(prStaRec->arTWTFlow[ucTWTFlowId].rTWTPeerParams)); + + /* Notify TWT Requester FSM upon reception of a TWT response */ + u2ReqType = prRxSetupFrame->rTWT.u2ReqType; + if (!(u2ReqType & TWT_REQ_TYPE_TWT_REQUEST)) { + twtReqFsmRunEventRxSetup(prAdapter, + prSwRfb, prStaRec, ucTWTFlowId); + } + + break; + + case ACTION_S1G_TWT_TEARDOWN: + prRxTeardownFrame = (struct _ACTION_TWT_TEARDOWN_FRAME *) + prSwRfb->pvHeader; + if (prStaRec->ucStaState != STA_STATE_3 || + prSwRfb->u2PacketLen < + sizeof(struct _ACTION_TWT_TEARDOWN_FRAME)) { + DBGLOG(TWT_REQUESTER, WARN, + "Received improper TWT Teardown frame\n"); + return; + } + + ucTWTFlowId = prRxTeardownFrame->ucTWTFlow; + + /* Notify TWT Requester FSM */ + twtReqFsmRunEventRxTeardown( + prAdapter, prSwRfb, prStaRec, ucTWTFlowId); + + break; + + case ACTION_S1G_TWT_INFORMATION: + { + uint8_t ucNextTWTSize = 0; + uint8_t *pucMem; + struct _NEXT_TWT_INFO_T rNextTWTInfo; + + prRxInfoFrame = (struct _ACTION_TWT_INFO_FRAME *) + prSwRfb->pvHeader; + if (prStaRec->ucStaState != STA_STATE_3 || + prSwRfb->u2PacketLen < + sizeof(struct _ACTION_TWT_INFO_FRAME)) { + DBGLOG(TWT_REQUESTER, WARN, + "Received improper TWT Info frame\n"); + return; + } + + ucTWTFlowId = GET_TWT_INFO_FLOW_ID( + prRxInfoFrame->ucNextTWTCtrl); + ucNextTWTSize = GET_TWT_INFO_NEXT_TWT_SIZE( + prRxInfoFrame->ucNextTWTCtrl); + + u4Offset = OFFSET_OF(struct _ACTION_TWT_INFO_FRAME, + aucNextTWT[0]); + pucMem = ((uint8_t *)prRxInfoFrame) + u4Offset; + + if (ucNextTWTSize == NEXT_TWT_SUBFIELD_64_BITS && + prSwRfb->u2PacketLen >= + (sizeof(struct _ACTION_TWT_INFO_FRAME) + 8)) { + rNextTWTInfo.u8NextTWT = + LE64_TO_CPU(*((uint64_t *)pucMem)); + } else if (ucNextTWTSize == NEXT_TWT_SUBFIELD_32_BITS && + prSwRfb->u2PacketLen >= + (sizeof(struct _ACTION_TWT_INFO_FRAME) + 4)) { + rNextTWTInfo.u8NextTWT = + LE32_TO_CPU(*((uint32_t *)pucMem)); + } else if (ucNextTWTSize == NEXT_TWT_SUBFIELD_48_BITS && + prSwRfb->u2PacketLen >= + (sizeof(struct _ACTION_TWT_INFO_FRAME) + 6)) { + rNextTWTInfo.u8NextTWT = + GET_48_BITS_NEXT_TWT_FROM_PKT(pucMem); + } else { + DBGLOG(TWT_REQUESTER, WARN, + "TWT Info frame with imcorrect size\n"); + return; + } + + rNextTWTInfo.ucNextTWTSize = ucNextTWTSize; + + /* Notify TWT Requester FSM */ + twtReqFsmRunEventRxInfoFrm( + prAdapter, prSwRfb, prStaRec, ucTWTFlowId, + &rNextTWTInfo); + + break; + } + default: + break; + } +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/twt_planner.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/twt_planner.c new file mode 100644 index 0000000000000..e93626ffa3e3d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/twt_planner.c @@ -0,0 +1,1382 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2017 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2017 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "twt_planner.c" +* \brief TWT Planner to determine TWT negotiation policy +*/ + + +/******************************************************************************* +* C O M P I L E 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 +******************************************************************************** +*/ + +static uint32_t +_twtPlannerDrvAgrtAdd(struct _TWT_PLANNER_T *prTWTPlanner, + uint8_t ucBssIdx, uint8_t ucFlowId, + struct _TWT_PARAMS_T *prTWTParams, uint8_t ucIdx) +{ + struct _TWT_AGRT_T *prTWTAgrt = &(prTWTPlanner->arTWTAgrtTbl[ucIdx]); + + prTWTAgrt->fgValid = TRUE; + prTWTAgrt->ucBssIdx = ucBssIdx; + prTWTAgrt->ucFlowId = ucFlowId; + prTWTAgrt->ucAgrtTblIdx = ucIdx; + kalMemCopy(&(prTWTAgrt->rTWTAgrt), prTWTParams, + sizeof(struct _TWT_PARAMS_T)); + + return WLAN_STATUS_SUCCESS; +} + +static uint32_t +_twtPlannerDrvAgrtDel( + struct _TWT_PLANNER_T *prTWTPlanner, uint8_t ucIdx) +{ + struct _TWT_AGRT_T *prTWTAgrt = &(prTWTPlanner->arTWTAgrtTbl[ucIdx]); + + kalMemSet(prTWTAgrt, 0, sizeof(struct _TWT_AGRT_T)); + + return WLAN_STATUS_SUCCESS; +} + +static uint32_t +_twtPlannerDrvAgrtModify( + struct _TWT_PLANNER_T *prTWTPlanner, + struct _NEXT_TWT_INFO_T *prNextTWTInfo, + uint64_t u8CurTsf, uint8_t ucIdx, + struct _TWT_PARAMS_T *prTWTParams) +{ + struct _TWT_AGRT_T *prTWTAgrt = &(prTWTPlanner->arTWTAgrtTbl[ucIdx]); + + if (!prNextTWTInfo || !prTWTParams) + return WLAN_STATUS_FAILURE; + + if (prNextTWTInfo->ucNextTWTSize == NEXT_TWT_SUBFIELD_64_BITS) { + prTWTAgrt->rTWTAgrt.u8TWT = prNextTWTInfo->u8NextTWT; + } else if (prNextTWTInfo->ucNextTWTSize == NEXT_TWT_SUBFIELD_32_BITS) { + prTWTAgrt->rTWTAgrt.u8TWT = + ((u8CurTsf & ((uint64_t)0xFFFFFFFF << 32)) | + prNextTWTInfo->u8NextTWT); + } else if (prNextTWTInfo->ucNextTWTSize == NEXT_TWT_SUBFIELD_48_BITS) { + prTWTAgrt->rTWTAgrt.u8TWT = + ((u8CurTsf & ((uint64_t)0xFFFF << 48)) | + prNextTWTInfo->u8NextTWT); + } else { + /* Zero bit Next TWT is not acceptable */ + return WLAN_STATUS_FAILURE; + } + + kalMemCopy(prTWTParams, &(prTWTAgrt->rTWTAgrt), + sizeof(struct _TWT_PARAMS_T)); + + return WLAN_STATUS_SUCCESS; +} + +static uint32_t +_twtPlannerDrvAgrtGet( + struct _TWT_PLANNER_T *prTWTPlanner, + uint8_t ucIdx, struct _TWT_PARAMS_T *prTWTParams) +{ + struct _TWT_AGRT_T *prTWTAgrt = &(prTWTPlanner->arTWTAgrtTbl[ucIdx]); + + if (!prTWTParams) + return WLAN_STATUS_FAILURE; + + kalMemCopy(prTWTParams, &(prTWTAgrt->rTWTAgrt), + sizeof(struct _TWT_PARAMS_T)); + + return WLAN_STATUS_SUCCESS; +} + +static uint8_t +twtPlannerDrvAgrtFind(struct ADAPTER *prAdapter, uint8_t ucBssIdx, + uint8_t ucFlowId) +{ + uint8_t i; + struct _TWT_PLANNER_T *prTWTPlanner = &(prAdapter->rTWTPlanner); + struct _TWT_AGRT_T *prTWTAgrt = &(prTWTPlanner->arTWTAgrtTbl[0]); + + for (i = 0; i < TWT_AGRT_MAX_NUM; i++, prTWTAgrt++) { + if (prTWTAgrt->fgValid == TRUE && + prTWTAgrt->ucFlowId == ucFlowId && + prTWTAgrt->ucBssIdx == ucBssIdx) + break; + } + + return i; +} + +uint32_t +twtPlannerDrvAgrtAdd(struct ADAPTER *prAdapter, + uint8_t ucBssIdx, uint8_t ucFlowId, + struct _TWT_PARAMS_T *prTWTParams, uint8_t *pucIdx) +{ + uint8_t ucIdx; + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct _TWT_PLANNER_T *prTWTPlanner = &(prAdapter->rTWTPlanner); + struct _TWT_AGRT_T *prTWTAgrt = &(prTWTPlanner->arTWTAgrtTbl[0]); + + for (ucIdx = 0; ucIdx < TWT_AGRT_MAX_NUM; ucIdx++, prTWTAgrt++) { + if (prTWTAgrt->fgValid == FALSE) + break; + } + + if (ucIdx < TWT_AGRT_MAX_NUM) { + _twtPlannerDrvAgrtAdd(prTWTPlanner, ucBssIdx, + ucFlowId, prTWTParams, ucIdx); + *pucIdx = ucIdx; + rStatus = WLAN_STATUS_SUCCESS; + } + + return rStatus; +} + +uint32_t +twtPlannerDrvAgrtModify( + struct ADAPTER *prAdapter, + uint8_t ucBssIdx, uint8_t ucFlowId, + struct _NEXT_TWT_INFO_T *prNextTWTInfo, + uint8_t *pucIdx, struct _TWT_PARAMS_T *prTWTParams) +{ + uint8_t ucIdx; + uint64_t u8CurTsf; + struct _TWT_PLANNER_T *prTWTPlanner = &(prAdapter->rTWTPlanner); + uint32_t rStatus; + + ucIdx = twtPlannerDrvAgrtFind(prAdapter, ucBssIdx, ucFlowId); + if (ucIdx >= TWT_AGRT_MAX_NUM) { + DBGLOG(TWT_PLANNER, ERROR, "Can't find agrt bss %u flow %u\n", + ucBssIdx, ucFlowId); + return WLAN_STATUS_FAILURE; + } + + /* TODO: get current TSF from FW */ + u8CurTsf = 0; + + rStatus = _twtPlannerDrvAgrtModify(prTWTPlanner, prNextTWTInfo, + u8CurTsf, ucIdx, prTWTParams); + if (rStatus == WLAN_STATUS_SUCCESS) + *pucIdx = ucIdx; + + return rStatus; +} + +uint32_t +twtPlannerDrvAgrtGet(struct ADAPTER *prAdapter, + uint8_t ucBssIdx, uint8_t ucFlowId, + uint8_t *pucIdx, struct _TWT_PARAMS_T *prTWTParams) +{ + uint8_t ucIdx; + struct _TWT_PLANNER_T *prTWTPlanner = &(prAdapter->rTWTPlanner); + uint32_t rStatus; + + ucIdx = twtPlannerDrvAgrtFind(prAdapter, ucBssIdx, ucFlowId); + if (ucIdx >= TWT_AGRT_MAX_NUM) { + DBGLOG(TWT_PLANNER, ERROR, "Can't find agrt bss %u flow %u\n", + ucBssIdx, ucFlowId); + return WLAN_STATUS_FAILURE; + } + + rStatus = _twtPlannerDrvAgrtGet(prTWTPlanner, ucIdx, prTWTParams); + if (rStatus == WLAN_STATUS_SUCCESS) + *pucIdx = ucIdx; + + return rStatus; +} + +bool +twtPlannerIsDrvAgrtExisting(struct ADAPTER *prAdapter) +{ + bool ret = FALSE; + uint8_t i; + struct _TWT_PLANNER_T *prTWTPlanner = &(prAdapter->rTWTPlanner); + struct _TWT_AGRT_T *prTWTAgrt = &(prTWTPlanner->arTWTAgrtTbl[0]); + + for (i = 0; i < TWT_AGRT_MAX_NUM; i++, prTWTAgrt++) { + if (prTWTAgrt->fgValid == TRUE) { + ret = TRUE; + break; + } + } + + return ret; +} + +void twtPlannerInit(IN struct _TWT_PLANNER_T *pTWTPlanner) +{ + ASSERT(pTWTPlanner); + + kalMemSet(&(pTWTPlanner->arTWTAgrtTbl[0]), 0, + TWT_AGRT_MAX_NUM * sizeof(struct _TWT_AGRT_T)); +} + +static struct _TWT_FLOW_T *twtPlannerFlowFindById( + struct STA_RECORD *prStaRec, uint8_t ucFlowId) +{ + struct _TWT_FLOW_T *prTWTFlow = NULL; + + ASSERT(prStaRec); + + if (ucFlowId >= TWT_MAX_FLOW_NUM) { + DBGLOG(TWT_PLANNER, ERROR, "Invalid TWT flow id %u\n", + ucFlowId); + return NULL; + } + + prTWTFlow = &(prStaRec->arTWTFlow[ucFlowId]); + + return prTWTFlow; +} + +static uint32_t +twtPlannerSendReqStart( + struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t ucTWTFlowId) +{ + struct _MSG_TWT_REQFSM_START_T *prTWTReqFsmStartMsg; + + prTWTReqFsmStartMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct _MSG_TWT_REQFSM_START_T)); + if (prTWTReqFsmStartMsg) { + prTWTReqFsmStartMsg->rMsgHdr.eMsgId = MID_TWT_REQ_FSM_START; + prTWTReqFsmStartMsg->prStaRec = prStaRec; + prTWTReqFsmStartMsg->ucTWTFlowId = ucTWTFlowId; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prTWTReqFsmStartMsg, + MSG_SEND_METHOD_BUF); + } else + return WLAN_STATUS_RESOURCES; + + return WLAN_STATUS_SUCCESS; +} + +static uint32_t +twtPlannerSendReqTeardown(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t ucTWTFlowId) +{ + struct _MSG_TWT_REQFSM_TEARDOWN_T *prTWTReqFsmTeardownMsg; + + prTWTReqFsmTeardownMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct _MSG_TWT_REQFSM_TEARDOWN_T)); + if (prTWTReqFsmTeardownMsg) { + prTWTReqFsmTeardownMsg->rMsgHdr.eMsgId = + MID_TWT_REQ_FSM_TEARDOWN; + prTWTReqFsmTeardownMsg->prStaRec = prStaRec; + prTWTReqFsmTeardownMsg->ucTWTFlowId = ucTWTFlowId; + + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prTWTReqFsmTeardownMsg, + MSG_SEND_METHOD_BUF); + } else + return WLAN_STATUS_RESOURCES; + + return WLAN_STATUS_SUCCESS; +} + +static uint32_t +twtPlannerSendReqSuspend(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t ucTWTFlowId) +{ + struct _MSG_TWT_REQFSM_SUSPEND_T *prTWTReqFsmSuspendMsg; + + prTWTReqFsmSuspendMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct _MSG_TWT_REQFSM_SUSPEND_T)); + if (prTWTReqFsmSuspendMsg) { + prTWTReqFsmSuspendMsg->rMsgHdr.eMsgId = + MID_TWT_REQ_FSM_SUSPEND; + prTWTReqFsmSuspendMsg->prStaRec = prStaRec; + prTWTReqFsmSuspendMsg->ucTWTFlowId = ucTWTFlowId; + + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prTWTReqFsmSuspendMsg, + MSG_SEND_METHOD_BUF); + } else + return WLAN_STATUS_RESOURCES; + + return WLAN_STATUS_SUCCESS; +} + +static uint32_t +twtPlannerSendReqResume(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t ucTWTFlowId, + uint64_t u8NextTWT, + uint8_t ucNextTWTSize) +{ + struct _MSG_TWT_REQFSM_RESUME_T *prTWTReqFsmResumeMsg; + + prTWTReqFsmResumeMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct _MSG_TWT_REQFSM_RESUME_T)); + if (prTWTReqFsmResumeMsg) { + prTWTReqFsmResumeMsg->rMsgHdr.eMsgId = + MID_TWT_REQ_FSM_RESUME; + prTWTReqFsmResumeMsg->prStaRec = prStaRec; + prTWTReqFsmResumeMsg->ucTWTFlowId = ucTWTFlowId; + prTWTReqFsmResumeMsg->u8NextTWT = u8NextTWT; + prTWTReqFsmResumeMsg->ucNextTWTSize = ucNextTWTSize; + + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prTWTReqFsmResumeMsg, + MSG_SEND_METHOD_BUF); + } else + return WLAN_STATUS_RESOURCES; + + return WLAN_STATUS_SUCCESS; +} + +static uint32_t +twtPlannerAddAgrtTbl( + struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct STA_RECORD *prStaRec, + struct _TWT_PARAMS_T *prTWTParams, + uint8_t ucFlowId, + uint8_t fgIsOid, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler) +{ + uint8_t ucAgrtTblIdx; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct _EXT_CMD_TWT_ARGT_UPDATE_T *prTWTAgrtUpdate; + + if (prBssInfo == NULL) { + DBGLOG(TWT_PLANNER, ERROR, "No bssinfo to add agrt\n"); + return WLAN_STATUS_INVALID_DATA; + } + + rWlanStatus = twtPlannerDrvAgrtAdd(prAdapter, prBssInfo->ucBssIndex, + ucFlowId, prTWTParams, &ucAgrtTblIdx); + if (rWlanStatus) { + DBGLOG(TWT_PLANNER, ERROR, + "Agreement table is full\n"); + return WLAN_STATUS_FAILURE; + } + + prTWTAgrtUpdate = cnmMemAlloc( + prAdapter, + RAM_TYPE_MSG, + sizeof(struct _EXT_CMD_TWT_ARGT_UPDATE_T)); + if (!prTWTAgrtUpdate) { + DBGLOG( + TWT_PLANNER, + ERROR, + "Allocate _EXT_CMD_TWT_ARGT_UPDATE_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prTWTAgrtUpdate->ucAgrtTblIdx = ucAgrtTblIdx; + prTWTAgrtUpdate->ucAgrtCtrlFlag = TWT_AGRT_CTRL_ADD; + prTWTAgrtUpdate->ucOwnMacId = + (prBssInfo) ? prBssInfo->ucOwnMacIndex : 0; + prTWTAgrtUpdate->ucFlowId = ucFlowId; + prTWTAgrtUpdate->u2PeerIdGrpId = + (prStaRec) ? CPU_TO_LE16(prStaRec->ucWlanIndex) : 1; + prTWTAgrtUpdate->ucAgrtSpDuration = prTWTParams->ucMinWakeDur; + prTWTAgrtUpdate->ucBssIndex = prBssInfo ? prBssInfo->ucBssIndex : 0; + prTWTAgrtUpdate->u4AgrtSpStartTsfLow = + CPU_TO_LE32(prTWTParams->u8TWT & 0xFFFFFFFF); + prTWTAgrtUpdate->u4AgrtSpStartTsfHigh = + CPU_TO_LE32((uint32_t)(prTWTParams->u8TWT >> 32)); + prTWTAgrtUpdate->u2AgrtSpWakeIntvlMantissa = + CPU_TO_LE16(prTWTParams->u2WakeIntvalMantiss); + prTWTAgrtUpdate->ucAgrtSpWakeIntvlExponent = + prTWTParams->ucWakeIntvalExponent; + prTWTAgrtUpdate->ucIsRoleAp = 0; /* STA role */ + + prTWTAgrtUpdate->ucAgrtParaBitmap = + ((prTWTParams->fgProtect << TWT_AGRT_PARA_BITMAP_PROTECT_OFFSET) | + ((!prTWTParams->fgUnannounced) << TWT_AGRT_PARA_BITMAP_ANNCE_OFFSET) | + (prTWTParams->fgTrigger << TWT_AGRT_PARA_BITMAP_TRIGGER_OFFSET)); + + prTWTAgrtUpdate->ucGrpMemberCnt = 0; + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_TWT_AGRT_UPDATE, + TRUE, + TRUE, + fgIsOid, + pfCmdDoneHandler, + pfCmdTimeoutHandler, + sizeof(struct _EXT_CMD_TWT_ARGT_UPDATE_T), + (uint8_t *) (prTWTAgrtUpdate), + NULL, 0); + + return rWlanStatus; +} + +static uint32_t +twtPlannerResumeAgrtTbl(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, struct STA_RECORD *prStaRec, + uint8_t ucFlowId, uint8_t fgIsOid, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler) +{ + uint8_t ucAgrtTblIdx; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct _EXT_CMD_TWT_ARGT_UPDATE_T *prTWTAgrtUpdate; + struct _TWT_PARAMS_T rTWTParams; + + if (prBssInfo == NULL) { + DBGLOG(TWT_PLANNER, ERROR, "No bssinfo to resume agrt\n"); + return WLAN_STATUS_INVALID_DATA; + } + + rWlanStatus = twtPlannerDrvAgrtGet(prAdapter, prBssInfo->ucBssIndex, + ucFlowId, &ucAgrtTblIdx, &rTWTParams); + if (rWlanStatus) { + DBGLOG(TWT_PLANNER, ERROR, "No agrt to resume Bss %u flow %u\n", + prBssInfo->ucBssIndex, ucFlowId); + return WLAN_STATUS_FAILURE; + } + + prTWTAgrtUpdate = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct _EXT_CMD_TWT_ARGT_UPDATE_T)); + if (!prTWTAgrtUpdate) { + DBGLOG(TWT_PLANNER, ERROR, + "Allocate _EXT_CMD_TWT_ARGT_UPDATE_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prTWTAgrtUpdate->ucAgrtTblIdx = ucAgrtTblIdx; + prTWTAgrtUpdate->ucAgrtCtrlFlag = TWT_AGRT_CTRL_ADD; + prTWTAgrtUpdate->ucOwnMacId = (prBssInfo) ? + prBssInfo->ucOwnMacIndex : 0; + prTWTAgrtUpdate->ucFlowId = ucFlowId; + prTWTAgrtUpdate->u2PeerIdGrpId = (prStaRec) ? + CPU_TO_LE16(prStaRec->ucWlanIndex) : 1; + prTWTAgrtUpdate->ucAgrtSpDuration = rTWTParams.ucMinWakeDur; + prTWTAgrtUpdate->ucBssIndex = prBssInfo->ucBssIndex; + prTWTAgrtUpdate->u4AgrtSpStartTsfLow = + CPU_TO_LE32(rTWTParams.u8TWT & 0xFFFFFFFF); + prTWTAgrtUpdate->u4AgrtSpStartTsfHigh = + CPU_TO_LE32((uint32_t)(rTWTParams.u8TWT >> 32)); + prTWTAgrtUpdate->u2AgrtSpWakeIntvlMantissa = + CPU_TO_LE16(rTWTParams.u2WakeIntvalMantiss); + prTWTAgrtUpdate->ucAgrtSpWakeIntvlExponent = + rTWTParams.ucWakeIntvalExponent; + prTWTAgrtUpdate->ucIsRoleAp = 0; /* STA role */ + prTWTAgrtUpdate->ucAgrtParaBitmap = + ((rTWTParams.fgProtect << TWT_AGRT_PARA_BITMAP_PROTECT_OFFSET) | + ((!rTWTParams.fgUnannounced) << TWT_AGRT_PARA_BITMAP_ANNCE_OFFSET) | + (rTWTParams.fgTrigger << TWT_AGRT_PARA_BITMAP_TRIGGER_OFFSET)); + prTWTAgrtUpdate->ucGrpMemberCnt = 0; + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_TWT_AGRT_UPDATE, + TRUE, + TRUE, + fgIsOid, + pfCmdDoneHandler, + pfCmdTimeoutHandler, + sizeof(struct _EXT_CMD_TWT_ARGT_UPDATE_T), + (uint8_t *) (prTWTAgrtUpdate), + NULL, 0); + + return rWlanStatus; +} + +static uint32_t +twtPlannerModifyAgrtTbl(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, struct STA_RECORD *prStaRec, + struct _NEXT_TWT_INFO_T *prNextTWTInfo, + uint8_t ucFlowId, uint8_t fgIsOid, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler) +{ + uint8_t ucAgrtTblIdx; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct _EXT_CMD_TWT_ARGT_UPDATE_T *prTWTAgrtUpdate; + struct _TWT_PARAMS_T rTWTParams; + + if (prBssInfo == NULL) { + DBGLOG(TWT_PLANNER, ERROR, "No bssinfo to modify agrt\n"); + return WLAN_STATUS_INVALID_DATA; + } + + /* Handle driver agreement table */ + rWlanStatus = twtPlannerDrvAgrtModify(prAdapter, prBssInfo->ucBssIndex, + ucFlowId, prNextTWTInfo, &ucAgrtTblIdx, &rTWTParams); + + if (rWlanStatus) { + DBGLOG(TWT_PLANNER, ERROR, "No agrt to modify Bss %u flow %u\n", + prBssInfo->ucBssIndex, ucFlowId); + return WLAN_STATUS_FAILURE; + } + + /* Handle FW agreement table */ + prTWTAgrtUpdate = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct _EXT_CMD_TWT_ARGT_UPDATE_T)); + if (!prTWTAgrtUpdate) { + DBGLOG(TWT_PLANNER, ERROR, + "Allocate _EXT_CMD_TWT_ARGT_UPDATE_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prTWTAgrtUpdate->ucAgrtTblIdx = ucAgrtTblIdx; + prTWTAgrtUpdate->ucAgrtCtrlFlag = TWT_AGRT_CTRL_MODIFY; + prTWTAgrtUpdate->ucOwnMacId = (prBssInfo) ? + prBssInfo->ucOwnMacIndex : 0; + prTWTAgrtUpdate->ucFlowId = ucFlowId; + prTWTAgrtUpdate->u2PeerIdGrpId = (prStaRec) ? + CPU_TO_LE16(prStaRec->ucWlanIndex) : 1; + prTWTAgrtUpdate->ucAgrtSpDuration = rTWTParams.ucMinWakeDur; + prTWTAgrtUpdate->u4AgrtSpStartTsfLow = + CPU_TO_LE32(rTWTParams.u8TWT & 0xFFFFFFFF); + prTWTAgrtUpdate->u4AgrtSpStartTsfHigh = + CPU_TO_LE32((uint32_t)(rTWTParams.u8TWT >> 32)); + prTWTAgrtUpdate->ucGrpMemberCnt = 0; + prTWTAgrtUpdate->ucBssIndex = prBssInfo->ucBssIndex; + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_TWT_AGRT_UPDATE, + TRUE, + TRUE, + fgIsOid, + pfCmdDoneHandler, + pfCmdTimeoutHandler, + sizeof(struct _EXT_CMD_TWT_ARGT_UPDATE_T), + (uint8_t *) (prTWTAgrtUpdate), + NULL, 0); + + return rWlanStatus; +} + +static uint32_t +twtPlannerDelAgrtTbl(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, struct STA_RECORD *prStaRec, + uint8_t ucFlowId, uint8_t fgIsOid, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + uint8_t fgDelDrvEntry) +{ + uint8_t ucAgrtTblIdx; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct _TWT_PLANNER_T *prTWTPlanner = &(prAdapter->rTWTPlanner); + struct _EXT_CMD_TWT_ARGT_UPDATE_T *prTWTAgrtUpdate; + + if (prBssInfo == NULL) { + DBGLOG(TWT_PLANNER, ERROR, "No bssinfo to delete agrt\n"); + return WLAN_STATUS_INVALID_DATA; + } + + /* Find and delete the agreement entry in the driver */ + ucAgrtTblIdx = twtPlannerDrvAgrtFind(prAdapter, + prBssInfo->ucBssIndex, ucFlowId); + + if (ucAgrtTblIdx >= TWT_AGRT_MAX_NUM) { + DBGLOG(TWT_PLANNER, ERROR, + "Cannot find the flow %u to be deleted\n", ucFlowId); + return WLAN_STATUS_FAILURE; + + } + + if (fgDelDrvEntry) + _twtPlannerDrvAgrtDel(prTWTPlanner, ucAgrtTblIdx); + + /* Send cmd to delete agreement entry in FW */ + prTWTAgrtUpdate = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct _EXT_CMD_TWT_ARGT_UPDATE_T)); + if (!prTWTAgrtUpdate) { + DBGLOG(TWT_PLANNER, ERROR, + "Alloc _EXT_CMD_TWT_ARGT_UPDATE_T for del FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prTWTAgrtUpdate->ucAgrtTblIdx = ucAgrtTblIdx; + prTWTAgrtUpdate->ucAgrtCtrlFlag = TWT_AGRT_CTRL_DELETE; + prTWTAgrtUpdate->ucOwnMacId = (prBssInfo) ? + prBssInfo->ucOwnMacIndex : 0; + prTWTAgrtUpdate->ucFlowId = ucFlowId; + prTWTAgrtUpdate->u2PeerIdGrpId = (prStaRec) ? + CPU_TO_LE16(prStaRec->ucWlanIndex) : 1; + prTWTAgrtUpdate->ucIsRoleAp = 0; /* STA role */ + prTWTAgrtUpdate->ucBssIndex = prBssInfo ? prBssInfo->ucBssIndex : 0; + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_TWT_AGRT_UPDATE, + TRUE, + TRUE, + fgIsOid, + pfCmdDoneHandler, + pfCmdTimeoutHandler, + sizeof(struct _EXT_CMD_TWT_ARGT_UPDATE_T), + (uint8_t *) (prTWTAgrtUpdate), + NULL, 0); + + return rWlanStatus; +} + +static uint32_t +twtPlannerTeardownAgrtTbl(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t fgIsOid, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct _EXT_CMD_TWT_ARGT_UPDATE_T *prTWTAgrtUpdate; + + /* Send cmd to teardown this STA in FW */ + prTWTAgrtUpdate = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct _EXT_CMD_TWT_ARGT_UPDATE_T)); + if (!prTWTAgrtUpdate) { + DBGLOG(TWT_PLANNER, ERROR, + "Alloc _EXT_CMD_TWT_ARGT_UPDATE_T for del FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* Don't care about other fields of the cmd */ + prTWTAgrtUpdate->ucAgrtCtrlFlag = TWT_AGRT_CTRL_TEARDOWN; + prTWTAgrtUpdate->u2PeerIdGrpId = (prStaRec) ? + CPU_TO_LE16(prStaRec->ucWlanIndex) : 1; + prTWTAgrtUpdate->ucIsRoleAp = 0; /* STA role */ + prTWTAgrtUpdate->ucBssIndex = prStaRec ? prStaRec->ucBssIndex : 0; + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_TWT_AGRT_UPDATE, + TRUE, + TRUE, + fgIsOid, + pfCmdDoneHandler, + pfCmdTimeoutHandler, + sizeof(struct _EXT_CMD_TWT_ARGT_UPDATE_T), + (uint8_t *) (prTWTAgrtUpdate), + NULL, 0); + + return rWlanStatus; +} + +uint32_t twtPlannerReset( + struct ADAPTER *prAdapter, struct BSS_INFO *prBssInfo) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct STA_RECORD *prStaRec; + struct _EXT_CMD_TWT_ARGT_UPDATE_T *prTWTAgrtUpdate; + + /* If no agrt exits, don't bother resetting */ + if (twtPlannerIsDrvAgrtExisting(prAdapter) == FALSE) + return rWlanStatus; + + prTWTAgrtUpdate = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct _EXT_CMD_TWT_ARGT_UPDATE_T)); + if (!prTWTAgrtUpdate) { + DBGLOG(TWT_PLANNER, ERROR, + "Alloc _EXT_CMD_TWT_ARGT_UPDATE_T for reset FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* send cmd to reset FW agreement table */ + ASSERT(prBssInfo); + prStaRec = prBssInfo->prStaRecOfAP; + + prTWTAgrtUpdate->ucAgrtCtrlFlag = TWT_AGRT_CTRL_RESET; + prTWTAgrtUpdate->u2PeerIdGrpId = (prStaRec) ? + CPU_TO_LE16(prStaRec->ucWlanIndex) : 1; + prTWTAgrtUpdate->ucIsRoleAp = 0; /* STA role */ + prTWTAgrtUpdate->ucBssIndex = prBssInfo ? prBssInfo->ucBssIndex : 0; + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_TWT_AGRT_UPDATE, + TRUE, + TRUE, + FALSE, + NULL, + NULL, + sizeof(struct _EXT_CMD_TWT_ARGT_UPDATE_T), + (uint8_t *) (prTWTAgrtUpdate), + NULL, 0); + + + /* reset driver agreement table */ + memset(&(prAdapter->rTWTPlanner), 0, sizeof(prAdapter->rTWTPlanner)); + + /* Enable scan after TWT agrt reset */ + prAdapter->fgEnOnlineScan = TRUE; + + return rWlanStatus; +} + +uint64_t twtPlannerAdjustNextTWT(struct ADAPTER *prAdapter, + uint8_t ucBssIdx, uint8_t ucFlowId, + uint64_t u8NextTWTOrig) +{ + uint8_t ucAgrtTblIdx; + struct _TWT_PARAMS_T rTWTParams = {0x0}; + uint64_t u8Diff; + uint32_t u4WakeIntvl; + + twtPlannerDrvAgrtGet(prAdapter, ucBssIdx, ucFlowId, + &ucAgrtTblIdx, &rTWTParams); + + u4WakeIntvl = rTWTParams.u2WakeIntvalMantiss << + rTWTParams.ucWakeIntvalExponent; + u8Diff = u8NextTWTOrig - rTWTParams.u8TWT; + /* TODO: move div_u64 to os-dependent file */ + return (rTWTParams.u8TWT + + (div_u64(u8Diff, u4WakeIntvl) + 1) * u4WakeIntvl); +} + +void twtPlannerGetTsfDone( + struct ADAPTER *prAdapter, + struct CMD_INFO *prCmdInfo, + uint8_t *pucEventBuf) +{ + struct EXT_EVENT_MAC_INFO_T *prEventMacInfo; + struct _TWT_GET_TSF_CONTEXT_T *prGetTsfCtxt; + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + struct TSF_RESULT_T *prTsfResult; + uint64_t u8CurTsf; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + if (!pucEventBuf) { + DBGLOG(TWT_PLANNER, ERROR, "pucEventBuf is NULL.\n"); + return; + } + if (!prCmdInfo->pvInformationBuffer) { + DBGLOG(TWT_PLANNER, ERROR, + "prCmdInfo->pvInformationBuffer is NULL.\n"); + return; + } + + prEventMacInfo = (struct EXT_EVENT_MAC_INFO_T *) (pucEventBuf); + prGetTsfCtxt = (struct _TWT_GET_TSF_CONTEXT_T *) + prCmdInfo->pvInformationBuffer; + + ASSERT(prGetTsfCtxt); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prGetTsfCtxt->ucBssIdx); + ASSERT(prBssInfo); + prStaRec = prBssInfo->prStaRecOfAP; + ASSERT(prStaRec); + + prTsfResult = &(prEventMacInfo->rMacInfoResult.rTsfResult); + u8CurTsf = LE32_TO_CPU(prTsfResult->u4TsfBitsLow) | + (((uint64_t)(LE32_TO_CPU(prTsfResult->u4TsfBitsHigh))) << 32); + + switch (prGetTsfCtxt->ucReason) { + case TWT_GET_TSF_FOR_ADD_AGRT_BYPASS: + prGetTsfCtxt->rTWTParams.u8TWT = u8CurTsf + TSF_OFFSET_FOR_EMU; + twtPlannerAddAgrtTbl(prAdapter, prBssInfo, + prStaRec, &(prGetTsfCtxt->rTWTParams), + prGetTsfCtxt->ucTWTFlowId, + prGetTsfCtxt->fgIsOid, + NULL, NULL); + break; + + case TWT_GET_TSF_FOR_ADD_AGRT: + { + struct _TWT_PARAMS_T *prTWTParams; + struct _TWT_FLOW_T *prTWTFlow = twtPlannerFlowFindById(prStaRec, + prGetTsfCtxt->ucTWTFlowId); + + if (prTWTFlow == NULL) { + DBGLOG(TWT_PLANNER, ERROR, "prTWTFlow is NULL.\n"); + + kalMemFree(prGetTsfCtxt, + VIR_MEM_TYPE, sizeof(*prGetTsfCtxt)); + + return; + } + + prGetTsfCtxt->rTWTParams.u8TWT = + u8CurTsf + TSF_OFFSET_FOR_AGRT_ADD; + + prTWTParams = &(prTWTFlow->rTWTParams); + + kalMemCopy(prTWTParams, &(prGetTsfCtxt->rTWTParams), + sizeof(struct _TWT_PARAMS_T)); + + /* Start the process to nego for a new agreement */ + twtPlannerSendReqStart(prAdapter, + prStaRec, prGetTsfCtxt->ucTWTFlowId); + + break; + } + case TWT_GET_TSF_FOR_RESUME_AGRT: + { + uint8_t ucNextTWTSize = NEXT_TWT_SUBFIELD_64_BITS; + uint64_t u8NextTWT = u8CurTsf + TSF_OFFSET_FOR_AGRT_RESUME; + + /* Adjust next TWT if 'Flexible TWT Sched' is not supported */ + if (!HE_IS_MAC_CAP_FLEXIBLE_TWT_SHDL( + prStaRec->ucHeMacCapInfo)) { + u8NextTWT = twtPlannerAdjustNextTWT(prAdapter, + prBssInfo->ucBssIndex, + prGetTsfCtxt->ucTWTFlowId, + u8NextTWT); + } + + /* Start the process to resume this TWT agreement */ + twtPlannerSendReqResume(prAdapter, + prStaRec, prGetTsfCtxt->ucTWTFlowId, + u8NextTWT, ucNextTWTSize); + + break; + } + + default: + DBGLOG(TWT_PLANNER, ERROR, + "Unknown reason to get TSF %u\n", + prGetTsfCtxt->ucReason); + break; + } + + /* free memory */ + kalMemFree(prGetTsfCtxt, VIR_MEM_TYPE, sizeof(*prGetTsfCtxt)); +} + +static uint32_t +twtPlannerGetCurrentTSF( + struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + void *pvSetBuffer, + uint32_t u4SetBufferLen) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct _EXT_CMD_GET_MAC_INFO_T *prMacInfoCmd; + struct _EXTRA_ARG_TSF_T *prTsfArg; + + prMacInfoCmd = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct _EXT_CMD_GET_MAC_INFO_T)); + if (!prMacInfoCmd) { + DBGLOG(TWT_PLANNER, ERROR, + "Alloc _EXT_CMD_GET_MAC_INFO_T FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prTsfArg = &(prMacInfoCmd->rExtraArgument.rTsfArg); + prMacInfoCmd->u2MacInfoId = CPU_TO_LE16(MAC_INFO_TYPE_TSF); + prTsfArg->ucHwBssidIndex = prBssInfo->ucOwnMacIndex; + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_GET_MAC_INFO, + FALSE, + TRUE, + FALSE, + twtPlannerGetTsfDone, + NULL, + sizeof(struct _EXT_CMD_GET_MAC_INFO_T), + (uint8_t *) (prMacInfoCmd), + pvSetBuffer, u4SetBufferLen); + + return rWlanStatus; +} + +void twtPlannerSetParams( + struct ADAPTER *prAdapter, struct MSG_HDR *prMsgHdr) +{ + struct _MSG_TWT_PARAMS_SET_T *prTWTParamSetMsg; + struct _TWT_CTRL_T rTWTCtrl, *prTWTCtrl = &rTWTCtrl; + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint8_t ucBssIdx, ucFlowId; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prTWTParamSetMsg = (struct _MSG_TWT_PARAMS_SET_T *) prMsgHdr; + kalMemCopy(prTWTCtrl, &prTWTParamSetMsg->rTWTCtrl, sizeof(*prTWTCtrl)); + + cnmMemFree(prAdapter, prMsgHdr); + + /* Find the BSS info */ + ucBssIdx = prTWTCtrl->ucBssIdx; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE || + prBssInfo->eConnectionState != MEDIA_STATE_CONNECTED) { + DBGLOG(TWT_PLANNER, ERROR, + "Current op mode %d connection state %d\n", + prBssInfo->eCurrentOPMode, prBssInfo->eConnectionState); + return; + } + + /* Get the STA Record */ + prStaRec = prBssInfo->prStaRecOfAP; + if (!prStaRec) { + DBGLOG(TWT_PLANNER, ERROR, "No AP STA Record\n"); + return; + } + + /* If bypassing TWT nego, this ctrl param is treated as a TWT agrt*/ + if (IS_TWT_PARAM_ACTION_ADD_BYPASS(prTWTCtrl->ucCtrlAction)) { + struct _TWT_GET_TSF_CONTEXT_T *prGetTsfCtxt = + kalMemAlloc(sizeof(struct _TWT_GET_TSF_CONTEXT_T), + VIR_MEM_TYPE); + if (prGetTsfCtxt == NULL) { + DBGLOG(TWT_PLANNER, ERROR, "mem alloc failed\n"); + return; + } + + prGetTsfCtxt->ucReason = TWT_GET_TSF_FOR_ADD_AGRT_BYPASS; + prGetTsfCtxt->ucBssIdx = ucBssIdx; + prGetTsfCtxt->ucTWTFlowId = prTWTCtrl->ucTWTFlowId; + prGetTsfCtxt->fgIsOid = FALSE; + kalMemCopy(&(prGetTsfCtxt->rTWTParams), + &(prTWTCtrl->rTWTParams), + sizeof(struct _TWT_PARAMS_T)); + twtPlannerGetCurrentTSF(prAdapter, + prBssInfo, prGetTsfCtxt, sizeof(*prGetTsfCtxt)); + + return; + } + + /* Check if peer has TWT responder capability and local config */ + if (!HE_IS_MAC_CAP_TWT_RSP(prStaRec->ucHeMacCapInfo) || + !IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucTWTRequester)) { + DBGLOG(TWT_PLANNER, ERROR, + "Peer cap 0x%x user config of TWT req %u\n", + prStaRec->ucHeMacCapInfo[0], + prAdapter->rWifiVar.ucTWTRequester); + return; + } + + /* For COEX concern, suppose only 5G is allowed */ + if ((prAdapter->rWifiVar.ucTWTStaBandBitmap & prBssInfo->eBand) + != prBssInfo->eBand) { + DBGLOG(TWT_PLANNER, ERROR, + "TWT BAND support bitmaps(%u)!=%u\n", + prAdapter->rWifiVar.ucTWTStaBandBitmap, + prBssInfo->eBand); + return; + } + + ucFlowId = prTWTCtrl->ucTWTFlowId; + + switch (prTWTCtrl->ucCtrlAction) { + case TWT_PARAM_ACTION_ADD: + if (twtPlannerDrvAgrtFind( + prAdapter, ucBssIdx, ucFlowId) >= TWT_AGRT_MAX_NUM) { + + struct _TWT_GET_TSF_CONTEXT_T *prGetTsfCtxt = + kalMemAlloc( + sizeof(struct _TWT_GET_TSF_CONTEXT_T), + VIR_MEM_TYPE); + if (prGetTsfCtxt == NULL) { + DBGLOG(TWT_PLANNER, ERROR, + "mem alloc failed\n"); + return; + } + + prGetTsfCtxt->ucReason = TWT_GET_TSF_FOR_ADD_AGRT; + prGetTsfCtxt->ucBssIdx = ucBssIdx; + prGetTsfCtxt->ucTWTFlowId = prTWTCtrl->ucTWTFlowId; + prGetTsfCtxt->fgIsOid = FALSE; + kalMemCopy(&(prGetTsfCtxt->rTWTParams), + &(prTWTCtrl->rTWTParams), + sizeof(struct _TWT_PARAMS_T)); + twtPlannerGetCurrentTSF(prAdapter, prBssInfo, + prGetTsfCtxt, sizeof(*prGetTsfCtxt)); + + return; + } + + DBGLOG(TWT_PLANNER, ERROR, + "BSS %u TWT flow %u already exists\n", + ucBssIdx, ucFlowId); + break; + + case TWT_PARAM_ACTION_DEL: + if (twtPlannerDrvAgrtFind( + prAdapter, ucBssIdx, ucFlowId) < TWT_AGRT_MAX_NUM) { + /* Start the process to tear down this TWT agreement */ + twtPlannerSendReqTeardown(prAdapter, + prStaRec, ucFlowId); + } else { + DBGLOG(TWT_PLANNER, ERROR, + "BSS %u TWT flow %u doesn't exist\n", + ucBssIdx, ucFlowId); + } + break; + + case TWT_PARAM_ACTION_SUSPEND: + if (twtPlannerDrvAgrtFind( + prAdapter, ucBssIdx, ucFlowId) < TWT_AGRT_MAX_NUM) { + /* Start the process to suspend this TWT agreement */ + twtPlannerSendReqSuspend(prAdapter, + prStaRec, ucFlowId); + } else { + DBGLOG(TWT_PLANNER, ERROR, + "BSS %u TWT flow %u doesn't exist\n", + ucBssIdx, ucFlowId); + } + break; + + case TWT_PARAM_ACTION_RESUME: + if (twtPlannerDrvAgrtFind( + prAdapter, ucBssIdx, ucFlowId) < TWT_AGRT_MAX_NUM) { + struct _TWT_GET_TSF_CONTEXT_T *prGetTsfCtxt = + kalMemAlloc( + sizeof(struct _TWT_GET_TSF_CONTEXT_T), + VIR_MEM_TYPE); + if (prGetTsfCtxt == NULL) { + DBGLOG(TWT_PLANNER, ERROR, + "mem alloc failed\n"); + return; + } + + prGetTsfCtxt->ucReason = TWT_GET_TSF_FOR_RESUME_AGRT; + prGetTsfCtxt->ucBssIdx = ucBssIdx; + prGetTsfCtxt->ucTWTFlowId = prTWTCtrl->ucTWTFlowId; + prGetTsfCtxt->fgIsOid = FALSE; + twtPlannerGetCurrentTSF(prAdapter, prBssInfo, + prGetTsfCtxt, sizeof(*prGetTsfCtxt)); + } else { + DBGLOG(TWT_PLANNER, ERROR, + "BSS %u TWT flow %u doesn't exist\n", + ucBssIdx, ucFlowId); + } + + break; + + default: + DBGLOG(TWT_PLANNER, ERROR, + "Action %u not supported\n", prTWTCtrl->ucCtrlAction); + break; + } +} + +void twtPlannerRxNegoResult( + struct ADAPTER *prAdapter, + struct MSG_HDR *prMsgHdr) +{ + struct _MSG_TWT_REQFSM_IND_RESULT_T *prTWTFsmResultMsg; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + uint8_t ucTWTFlowId; + struct _TWT_PARAMS_T *prTWTResult, *prTWTParams; + struct _TWT_FLOW_T *prTWTFlow; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prTWTFsmResultMsg = (struct _MSG_TWT_REQFSM_IND_RESULT_T *) prMsgHdr; + prStaRec = prTWTFsmResultMsg->prStaRec; + ucTWTFlowId = prTWTFsmResultMsg->ucTWTFlowId; + + if ((!prStaRec) || (prStaRec->fgIsInUse == FALSE)) { + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + cnmMemFree(prAdapter, prMsgHdr); + + if (!IS_AP_STA(prStaRec)) { + DBGLOG(TWT_PLANNER, ERROR, + "Rx nego result: invalid STA Type %d\n", + prStaRec->eStaType); + return; + } + + prTWTFlow = &(prStaRec->arTWTFlow[ucTWTFlowId]); + prTWTResult = &(prTWTFlow->rTWTPeerParams); + + switch (prTWTResult->ucSetupCmd) { + case TWT_SETUP_CMD_ACCEPT: + /* Update agreement table */ + twtPlannerAddAgrtTbl(prAdapter, prBssInfo, prStaRec, + prTWTResult, ucTWTFlowId, FALSE, + NULL, NULL /* handle TWT cmd timeout? */); + + /* Disable SCAN during TWT activity */ + prAdapter->fgEnOnlineScan = FALSE; + + break; + + case TWT_SETUP_CMD_ALTERNATE: + case TWT_SETUP_CMD_DICTATE: + /* Use AP's suggestions */ + prTWTParams = &(prTWTFlow->rTWTParams); + kalMemCopy(prTWTParams, + prTWTResult, sizeof(struct _TWT_PARAMS_T)); + prTWTParams->ucSetupCmd = TWT_SETUP_CMD_SUGGEST; + prTWTParams->fgReq = 1; + twtPlannerSendReqStart(prAdapter, prStaRec, ucTWTFlowId); + break; + + case TWT_SETUP_CMD_REJECT: + /* Clear TWT flow in StaRec */ + break; + + default: + DBGLOG(TWT_PLANNER, ERROR, + "Unknown setup command %u\n", prTWTResult->ucSetupCmd); + ASSERT(0); + break; + + } +} + +void twtPlannerSuspendDone( + struct ADAPTER *prAdapter, struct MSG_HDR *prMsgHdr) +{ + struct _MSG_TWT_REQFSM_IND_RESULT_T *prTWTFsmResultMsg; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + uint8_t ucTWTFlowId; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prTWTFsmResultMsg = (struct _MSG_TWT_REQFSM_IND_RESULT_T *) prMsgHdr; + prStaRec = prTWTFsmResultMsg->prStaRec; + ucTWTFlowId = prTWTFsmResultMsg->ucTWTFlowId; + + if ((!prStaRec) || (prStaRec->fgIsInUse == FALSE)) { + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + cnmMemFree(prAdapter, prMsgHdr); + + if (!IS_AP_STA(prStaRec)) { + DBGLOG(TWT_PLANNER, ERROR, + "Rx suspend result: invalid STA Type %d\n", + prStaRec->eStaType); + return; + } + + /* Delete only FW TWT agreement entry */ + twtPlannerDelAgrtTbl(prAdapter, prBssInfo, prStaRec, + ucTWTFlowId, FALSE, + NULL, NULL /* handle TWT cmd timeout? */, FALSE); + + /* Teardown FW TWT agreement entry */ + twtPlannerTeardownAgrtTbl(prAdapter, prStaRec, + FALSE, NULL, NULL /* handle TWT cmd timeout? */); + +} + +void twtPlannerResumeDone( + struct ADAPTER *prAdapter, struct MSG_HDR *prMsgHdr) +{ + struct _MSG_TWT_REQFSM_IND_RESULT_T *prTWTFsmResultMsg; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + uint8_t ucTWTFlowId; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prTWTFsmResultMsg = (struct _MSG_TWT_REQFSM_IND_RESULT_T *) prMsgHdr; + prStaRec = prTWTFsmResultMsg->prStaRec; + ucTWTFlowId = prTWTFsmResultMsg->ucTWTFlowId; + + if ((!prStaRec) || (prStaRec->fgIsInUse == FALSE)) { + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + cnmMemFree(prAdapter, prMsgHdr); + + if (!IS_AP_STA(prStaRec)) { + DBGLOG(TWT_PLANNER, ERROR, + "Rx suspend result: invalid STA Type %d\n", + prStaRec->eStaType); + return; + } + + /* Add back the FW TWT agreement entry */ + twtPlannerResumeAgrtTbl(prAdapter, prBssInfo, prStaRec, + ucTWTFlowId, FALSE, + NULL, NULL /* handle TWT cmd timeout? */); + +} + +void twtPlannerTeardownDone( + struct ADAPTER *prAdapter, struct MSG_HDR *prMsgHdr) +{ + struct _MSG_TWT_REQFSM_IND_RESULT_T *prTWTFsmResultMsg; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + uint8_t ucTWTFlowId; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prTWTFsmResultMsg = (struct _MSG_TWT_REQFSM_IND_RESULT_T *) prMsgHdr; + prStaRec = prTWTFsmResultMsg->prStaRec; + ucTWTFlowId = prTWTFsmResultMsg->ucTWTFlowId; + + if ((!prStaRec) || (prStaRec->fgIsInUse == FALSE)) { + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + cnmMemFree(prAdapter, prMsgHdr); + + if (!IS_AP_STA(prStaRec)) { + DBGLOG(TWT_PLANNER, ERROR, + "Rx teardown result: invalid STA Type %d\n", + prStaRec->eStaType); + return; + } + + /* Delete driver & FW TWT agreement entry */ + twtPlannerDelAgrtTbl(prAdapter, prBssInfo, prStaRec, + ucTWTFlowId, FALSE, + NULL, NULL /* handle TWT cmd timeout? */, TRUE); + + /* Teardown FW TWT agreement entry */ + twtPlannerTeardownAgrtTbl(prAdapter, prStaRec, + FALSE, NULL, NULL /* handle TWT cmd timeout? */); + + /* Enable SCAN after TWT agrt has been tear down */ + prAdapter->fgEnOnlineScan = TRUE; +} + +void twtPlannerRxInfoFrm( + struct ADAPTER *prAdapter, struct MSG_HDR *prMsgHdr) +{ + struct _MSG_TWT_REQFSM_IND_INFOFRM_T *prTWTFsmInfoFrmMsg; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + uint8_t ucTWTFlowId; + struct _NEXT_TWT_INFO_T rNextTWTInfo; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prTWTFsmInfoFrmMsg = (struct _MSG_TWT_REQFSM_IND_INFOFRM_T *) prMsgHdr; + prStaRec = prTWTFsmInfoFrmMsg->prStaRec; + ucTWTFlowId = prTWTFsmInfoFrmMsg->ucTWTFlowId; + + if ((!prStaRec) || (prStaRec->fgIsInUse == FALSE)) { + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + if (!IS_AP_STA(prStaRec)) { + DBGLOG(TWT_PLANNER, ERROR, + "Rx info frame: invalid STA Type %d\n", + prStaRec->eStaType); + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + kalMemCopy(&(rNextTWTInfo), &(prTWTFsmInfoFrmMsg->rNextTWTInfo), + sizeof(struct _NEXT_TWT_INFO_T)); + + cnmMemFree(prAdapter, prMsgHdr); + + /* Modify the TWT agreement entry */ + twtPlannerModifyAgrtTbl(prAdapter, prBssInfo, prStaRec, + &rNextTWTInfo, ucTWTFlowId, FALSE, + NULL, NULL /* handle TWT cmd timeout? */); + +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/twt_req_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/twt_req_fsm.c new file mode 100644 index 0000000000000..1056155f865a3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/twt_req_fsm.c @@ -0,0 +1,669 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2017 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2017 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "twt_req_fsm.c" +* \brief FSM for TWT Requesting STA negotiation +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +static uint8_t *apucDebugTWTReqState[TWT_REQ_STATE_NUM] = { + (uint8_t *) DISP_STRING("TWT_REQ_STATE_IDLE"), + (uint8_t *) DISP_STRING("TWT_REQ_STATE_REQTX"), + (uint8_t *) DISP_STRING("TWT_REQ_STATE_WAIT_RSP"), + (uint8_t *) DISP_STRING("TWT_REQ_STATE_SUSPENDING"), + (uint8_t *) DISP_STRING("TWT_REQ_STATE_SUSPENDED"), + (uint8_t *) DISP_STRING("TWT_REQ_STATE_RESUMING"), + (uint8_t *) DISP_STRING("TWT_REQ_STATE_TEARING_DOWN"), +}; + +/******************************************************************************* +* M A 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 uint32_t +twtReqFsmSendEvent( + struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t ucTWTFlowId, + enum ENUM_MSG_ID eMsgId); + +static uint32_t +twtReqFsmSendEventRxInfoFrm( + struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t ucTWTFlowId, + struct _NEXT_TWT_INFO_T *prNextTWTInfo); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief The Core FSM engine of TWT Requester Module. +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] eNextState The value of Next State +* @param[in] prRetainedSwRfb SW_RFB_T for JOIN Success +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void +twtReqFsmSteps( + struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + enum _ENUM_TWT_REQUESTER_STATE_T eNextState, + uint8_t ucTWTFlowId, + void *pParam) +{ + uint32_t rStatus = WLAN_STATUS_FAILURE; + enum _ENUM_TWT_REQUESTER_STATE_T ePreState; + uint8_t fgIsTransition; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + do { + + DBGLOG(TWT_REQUESTER, STATE, + "[TWT_REQ] Flow %d TRANSITION: [%s] -> [%s]\n", + ucTWTFlowId, + apucDebugTWTReqState[prStaRec->aeTWTReqState], + apucDebugTWTReqState[eNextState]); + + ePreState = prStaRec->aeTWTReqState; + + prStaRec->aeTWTReqState = eNextState; + fgIsTransition = (uint8_t) FALSE; + + switch (prStaRec->aeTWTReqState) { + case TWT_REQ_STATE_IDLE: + /* Notify TWT Planner of the negotiation result */ + if (ePreState == TWT_REQ_STATE_WAIT_RSP) { + twtReqFsmSendEvent(prAdapter, prStaRec, + ucTWTFlowId, MID_TWT_REQ_IND_RESULT); + /* TODO: how to handle failures */ + } else if (ePreState == TWT_REQ_STATE_TEARING_DOWN) { + twtReqFsmSendEvent(prAdapter, prStaRec, + ucTWTFlowId, + MID_TWT_REQ_IND_TEARDOWN_DONE); + } else if (ePreState == TWT_REQ_STATE_RESUMING) { + twtReqFsmSendEvent(prAdapter, prStaRec, + ucTWTFlowId, + MID_TWT_REQ_IND_RESUME_DONE); + } + break; + + case TWT_REQ_STATE_REQTX: + { + struct _TWT_PARAMS_T *prTWTParams = + (struct _TWT_PARAMS_T *)pParam; + ASSERT(prTWTParams); + rStatus = twtSendSetupFrame( + prAdapter, prStaRec, ucTWTFlowId, + prTWTParams, twtReqFsmRunEventTxDone); + if (rStatus != WLAN_STATUS_SUCCESS) { + eNextState = TWT_REQ_STATE_IDLE; + fgIsTransition = TRUE; + } + break; + } + + case TWT_REQ_STATE_WAIT_RSP: + break; + + case TWT_REQ_STATE_TEARING_DOWN: + rStatus = twtSendTeardownFrame( + prAdapter, prStaRec, ucTWTFlowId, + twtReqFsmRunEventTxDone); + if (rStatus != WLAN_STATUS_SUCCESS) { + eNextState = TWT_REQ_STATE_IDLE; + fgIsTransition = TRUE; + } + break; + + case TWT_REQ_STATE_SUSPENDING: + { + struct _NEXT_TWT_INFO_T rNextTWTInfo = {0}; + + rStatus = twtSendInfoFrame( + prAdapter, prStaRec, ucTWTFlowId, &rNextTWTInfo, + twtReqFsmRunEventTxDone); + if (rStatus != WLAN_STATUS_SUCCESS) { + eNextState = TWT_REQ_STATE_IDLE; + fgIsTransition = TRUE; + } + break; + } + + case TWT_REQ_STATE_RESUMING: + { + struct _NEXT_TWT_INFO_T *prNextTWTInfo = + (struct _NEXT_TWT_INFO_T *)pParam; + rStatus = twtSendInfoFrame( + prAdapter, prStaRec, ucTWTFlowId, prNextTWTInfo, + twtReqFsmRunEventTxDone); + if (rStatus != WLAN_STATUS_SUCCESS) { + eNextState = TWT_REQ_STATE_IDLE; + fgIsTransition = TRUE; + } + + break; + } + + case TWT_REQ_STATE_SUSPENDED: + twtReqFsmSendEvent(prAdapter, prStaRec, + ucTWTFlowId, MID_TWT_REQ_IND_SUSPEND_DONE); + break; + + case TWT_REQ_STATE_RX_TEARDOWN: + twtReqFsmSendEvent(prAdapter, prStaRec, + ucTWTFlowId, MID_TWT_REQ_IND_TEARDOWN_DONE); + break; + + case TWT_REQ_STATE_RX_INFOFRM: + { + struct _NEXT_TWT_INFO_T *prNextTWTInfo = + (struct _NEXT_TWT_INFO_T *)pParam; + twtReqFsmSendEventRxInfoFrm(prAdapter, prStaRec, + ucTWTFlowId, prNextTWTInfo); + break; + } + + default: + DBGLOG(TWT_REQUESTER, ERROR, + "Unknown TWT_REQUESTER STATE\n"); + ASSERT(0); + break; + } + + } while (fgIsTransition); +} + +static uint32_t +twtReqFsmSendEvent( + struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t ucTWTFlowId, + enum ENUM_MSG_ID eMsgId) +{ + struct _MSG_TWT_REQFSM_IND_RESULT_T *prTWTFsmResultMsg; + + prTWTFsmResultMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct _MSG_TWT_REQFSM_IND_RESULT_T)); + if (prTWTFsmResultMsg) { + prTWTFsmResultMsg->rMsgHdr.eMsgId = eMsgId; + prTWTFsmResultMsg->prStaRec = prStaRec; + prTWTFsmResultMsg->ucTWTFlowId = ucTWTFlowId; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prTWTFsmResultMsg, + MSG_SEND_METHOD_BUF); + } else + return WLAN_STATUS_RESOURCES; + + return WLAN_STATUS_SUCCESS; +} + +static uint32_t +twtReqFsmSendEventRxInfoFrm( + struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t ucTWTFlowId, + struct _NEXT_TWT_INFO_T *prNextTWTInfo) +{ + struct _MSG_TWT_REQFSM_IND_INFOFRM_T *prTWTFsmInfoFrmMsg; + + prTWTFsmInfoFrmMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct _MSG_TWT_REQFSM_IND_INFOFRM_T)); + if (prTWTFsmInfoFrmMsg) { + prTWTFsmInfoFrmMsg->rMsgHdr.eMsgId = MID_TWT_REQ_IND_INFOFRM; + prTWTFsmInfoFrmMsg->prStaRec = prStaRec; + prTWTFsmInfoFrmMsg->ucTWTFlowId = ucTWTFlowId; + kalMemCopy(&(prTWTFsmInfoFrmMsg->rNextTWTInfo), prNextTWTInfo, + sizeof(struct _NEXT_TWT_INFO_T)); + + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prTWTFsmInfoFrmMsg, + MSG_SEND_METHOD_BUF); + } else + return WLAN_STATUS_RESOURCES; + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Start Event to TWT FSM. +* +* @param[in] prMsgHdr Message of Request for a particular STA. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void twtReqFsmRunEventStart( + struct ADAPTER *prAdapter, + struct MSG_HDR *prMsgHdr) +{ + struct _MSG_TWT_REQFSM_START_T *prTWTReqFsmStartMsg; + struct STA_RECORD *prStaRec; + struct _TWT_PARAMS_T *prTWTParams; + uint8_t ucTWTFlowId; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prTWTReqFsmStartMsg = (struct _MSG_TWT_REQFSM_START_T *) prMsgHdr; + prStaRec = prTWTReqFsmStartMsg->prStaRec; + ucTWTFlowId = prTWTReqFsmStartMsg->ucTWTFlowId; + prTWTParams = &(prStaRec->arTWTFlow[ucTWTFlowId].rTWTParams); + + if ((!prStaRec) || (prStaRec->fgIsInUse == FALSE)) { + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + ASSERT(prStaRec); + ASSERT(prTWTParams); + + DBGLOG(TWT_REQUESTER, LOUD, + "EVENT-START: TWT Requester FSM %d\n", ucTWTFlowId); + + cnmMemFree(prAdapter, prMsgHdr); + + /* Validation of TWT Requester Start Event */ + if (!IS_AP_STA(prStaRec)) { + DBGLOG(TWT_REQUESTER, ERROR, + "EVENT-START: Invalid Type %d\n", + prStaRec->eStaType); + + /* TODO: Notify TWT Planner */ + + return; + } + + twtReqFsmSteps(prAdapter, prStaRec, + TWT_REQ_STATE_REQTX, ucTWTFlowId, prTWTParams); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Teardown Event to TWT FSM. +* +* @param[in] prMsgHdr Message of Request for a particular STA. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void twtReqFsmRunEventTeardown( + struct ADAPTER *prAdapter, struct MSG_HDR *prMsgHdr) +{ + struct _MSG_TWT_REQFSM_TEARDOWN_T *prTWTReqFsmTeardownMsg; + struct STA_RECORD *prStaRec; + uint8_t ucTWTFlowId; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prTWTReqFsmTeardownMsg = (struct _MSG_TWT_REQFSM_TEARDOWN_T *) prMsgHdr; + prStaRec = prTWTReqFsmTeardownMsg->prStaRec; + ucTWTFlowId = prTWTReqFsmTeardownMsg->ucTWTFlowId; + + if ((!prStaRec) || (prStaRec->fgIsInUse == FALSE)) { + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + ASSERT(prStaRec); + + DBGLOG(TWT_REQUESTER, LOUD, "EVENT-TEARDOWN: TWT Requester FSM %d\n", + ucTWTFlowId); + + cnmMemFree(prAdapter, prMsgHdr); + + /* Validation of TWT Requester Teardown Event */ + if (!IS_AP_STA(prStaRec)) { + DBGLOG(TWT_REQUESTER, ERROR, "Invalid STA Type %d\n", + prStaRec->eStaType); + + /* TODO: Notify TWT Planner */ + + return; + } + + twtReqFsmSteps(prAdapter, prStaRec, TWT_REQ_STATE_TEARING_DOWN, + ucTWTFlowId, NULL); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Suspend Event to TWT FSM. +* +* @param[in] prMsgHdr Message of Request for a particular STA. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void twtReqFsmRunEventSuspend( + struct ADAPTER *prAdapter, struct MSG_HDR *prMsgHdr) +{ + struct _MSG_TWT_REQFSM_SUSPEND_T *prTWTReqFsmSuspendMsg; + struct STA_RECORD *prStaRec; + uint8_t ucTWTFlowId; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prTWTReqFsmSuspendMsg = (struct _MSG_TWT_REQFSM_SUSPEND_T *) prMsgHdr; + prStaRec = prTWTReqFsmSuspendMsg->prStaRec; + ucTWTFlowId = prTWTReqFsmSuspendMsg->ucTWTFlowId; + + if ((!prStaRec) || (prStaRec->fgIsInUse == FALSE)) { + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + ASSERT(prStaRec); + + DBGLOG(TWT_REQUESTER, LOUD, "EVENT-SUSPEND: TWT Requester FSM %d\n", + ucTWTFlowId); + + cnmMemFree(prAdapter, prMsgHdr); + + /* Validation of TWT Requester Suspend Event */ + if (!IS_AP_STA(prStaRec)) { + DBGLOG(TWT_REQUESTER, ERROR, "Invalid STA Type %d\n", + prStaRec->eStaType); + + /* TODO: Notify TWT Planner */ + + return; + } + + twtReqFsmSteps(prAdapter, prStaRec, TWT_REQ_STATE_SUSPENDING, + ucTWTFlowId, NULL); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Suspend Event to TWT FSM. +* +* @param[in] prMsgHdr Message of Request for a particular STA. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void twtReqFsmRunEventResume( + struct ADAPTER *prAdapter, struct MSG_HDR *prMsgHdr) +{ + struct _MSG_TWT_REQFSM_RESUME_T *prTWTReqFsmResumeMsg; + struct STA_RECORD *prStaRec; + uint8_t ucTWTFlowId; + struct _NEXT_TWT_INFO_T rNextTWTInfo; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prTWTReqFsmResumeMsg = (struct _MSG_TWT_REQFSM_RESUME_T *) prMsgHdr; + prStaRec = prTWTReqFsmResumeMsg->prStaRec; + ucTWTFlowId = prTWTReqFsmResumeMsg->ucTWTFlowId; + rNextTWTInfo.u8NextTWT = prTWTReqFsmResumeMsg->u8NextTWT; + rNextTWTInfo.ucNextTWTSize = prTWTReqFsmResumeMsg->ucNextTWTSize; + + if ((!prStaRec) || (prStaRec->fgIsInUse == FALSE)) { + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + ASSERT(prStaRec); + + DBGLOG(TWT_REQUESTER, LOUD, "EVENT-RESUME: TWT Requester FSM %d\n", + ucTWTFlowId); + + cnmMemFree(prAdapter, prMsgHdr); + + /* Validation of TWT Requester Teardown Event */ + if (!IS_AP_STA(prStaRec)) { + DBGLOG(TWT_REQUESTER, ERROR, "Invalid STA Type %d\n", + prStaRec->eStaType); + + /* TODO: Notify TWT Planner */ + + return; + } + + twtReqFsmSteps(prAdapter, prStaRec, TWT_REQ_STATE_RESUMING, + ucTWTFlowId, (void *)&rNextTWTInfo); +} + +uint32_t +twtReqFsmRunEventTxDone( + struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + struct STA_RECORD *prStaRec; + enum _ENUM_TWT_REQUESTER_STATE_T eNextState; + uint8_t ucTWTFlowId; + + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + if (!prStaRec) { + DBGLOG(TWT_REQUESTER, ERROR, + "EVENT-TXDONE: No valid STA Record\n"); + return WLAN_STATUS_INVALID_PACKET; + } + + if (rTxDoneStatus) + DBGLOG(TWT_REQUESTER, INFO, + "EVENT-TX DONE [status: %d][seq: %d]: Current Time = %d\n", + rTxDoneStatus, prMsduInfo->ucTxSeqNum, kalGetTimeTick()); + + /* Next state is set to current state + *by default and check Tx done status to transition if possible + */ + eNextState = prStaRec->aeTWTReqState; + + switch (prStaRec->aeTWTReqState) { + case TWT_REQ_STATE_REQTX: + + if (rTxDoneStatus == TX_RESULT_SUCCESS) + eNextState = TWT_REQ_STATE_WAIT_RSP; + else + eNextState = TWT_REQ_STATE_IDLE; + + ucTWTFlowId = twtGetTxSetupFlowId(prMsduInfo); + twtReqFsmSteps(prAdapter, + prStaRec, eNextState, ucTWTFlowId, NULL); + + break; + + case TWT_REQ_STATE_TEARING_DOWN: + + if (rTxDoneStatus == TX_RESULT_SUCCESS) + eNextState = TWT_REQ_STATE_IDLE; + + ucTWTFlowId = twtGetTxTeardownFlowId(prMsduInfo); + twtReqFsmSteps(prAdapter, prStaRec, eNextState, + ucTWTFlowId, NULL); + + break; + + case TWT_REQ_STATE_SUSPENDING: + if (rTxDoneStatus == TX_RESULT_SUCCESS) + eNextState = TWT_REQ_STATE_SUSPENDED; + + ucTWTFlowId = twtGetTxInfoFlowId(prMsduInfo); + twtReqFsmSteps(prAdapter, prStaRec, eNextState, + ucTWTFlowId, NULL); + + break; + + case TWT_REQ_STATE_RESUMING: + if (rTxDoneStatus == TX_RESULT_SUCCESS) + eNextState = TWT_REQ_STATE_IDLE; + + ucTWTFlowId = twtGetTxInfoFlowId(prMsduInfo); + twtReqFsmSteps(prAdapter, prStaRec, eNextState, + ucTWTFlowId, NULL); + + break; + + default: + break; /* Ignore other cases */ + } + + return WLAN_STATUS_SUCCESS; +} + +void twtReqFsmRunEventRxSetup( + struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb, + struct STA_RECORD *prStaRec, + uint8_t ucTWTFlowId) +{ + if (!IS_AP_STA(prStaRec)) + return; + + switch (prStaRec->aeTWTReqState) { + case TWT_REQ_STATE_WAIT_RSP: + /* transition to the IDLE state */ + twtReqFsmSteps(prAdapter, + prStaRec, TWT_REQ_STATE_IDLE, ucTWTFlowId, NULL); + break; + + default: + break; /* Ignore other cases */ + } +} + +void twtReqFsmRunEventRxTeardown( + struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb, + struct STA_RECORD *prStaRec, + uint8_t ucTWTFlowId) +{ + if (!IS_AP_STA(prStaRec)) + return; + + switch (prStaRec->aeTWTReqState) { + case TWT_REQ_STATE_IDLE: + /* transition to the RX TEARDOWN state */ + twtReqFsmSteps(prAdapter, prStaRec, TWT_REQ_STATE_RX_TEARDOWN, + ucTWTFlowId, NULL); + break; + + default: + break; /* Ignore other cases */ + } +} + +void twtReqFsmRunEventRxInfoFrm( + struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb, + struct STA_RECORD *prStaRec, + uint8_t ucTWTFlowId, + struct _NEXT_TWT_INFO_T *prNextTWTInfo) +{ + if (!IS_AP_STA(prStaRec)) + return; + + switch (prStaRec->aeTWTReqState) { + case TWT_REQ_STATE_IDLE: + /* transition to the RX Info frame state */ + twtReqFsmSteps(prAdapter, prStaRec, TWT_REQ_STATE_RX_INFOFRM, + ucTWTFlowId, prNextTWTInfo); + break; + + default: + break; /* Ignore other cases */ + } +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/wapi.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/wapi.c new file mode 100644 index 0000000000000..0d434b2c9c12a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/wapi.c @@ -0,0 +1,484 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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 + */ + +/****************************************************************************** + * C O M P I L E 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 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wapiParseWapiIE(IN struct WAPI_INFO_ELEM *prInfoElem, + OUT struct WAPI_INFO *prWapiInfo) +{ + uint32_t i; + int32_t u4RemainWapiIeLen; + uint16_t u2Version; + uint16_t u2Cap = 0; + uint32_t u4GroupSuite = WAPI_CIPHER_SUITE_WPI; + uint16_t u2PairSuiteCount = 0; + uint16_t u2AuthSuiteCount = 0; + uint8_t *pucPairSuite = NULL; + uint8_t *pucAuthSuite = NULL; + uint8_t *cp; + + DEBUGFUNC("wapiParseWapiIE"); + + /* 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 = (uint8_t *) &prInfoElem->u2AKMSuiteCount; + u4RemainWapiIeLen = (int32_t) 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 = (uint32_t) u2AuthSuiteCount * 4; + if (u4RemainWapiIeLen < (int32_t) 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 -= (int32_t) 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 = (uint32_t) u2PairSuiteCount * 4; + if (u4RemainWapiIeLen < (int32_t) 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 -= (int32_t) 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, (uint8_t) (u4GroupSuite & 0x000000FF), + (uint8_t) ((u4GroupSuite >> 8) & 0x000000FF), + (uint8_t) ((u4GroupSuite >> 16) & 0x000000FF), + (uint8_t) ((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 = + (uint32_t) u2PairSuiteCount; + + for (i = 0; i < (uint32_t) 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", + (uint8_t) i, + (uint8_t) (prWapiInfo->au4PairwiseKeyCipherSuite + [i] & 0x000000FF), + (uint8_t) ((prWapiInfo->au4PairwiseKeyCipherSuite + [i] >> 8) & 0x000000FF), + (uint8_t) ((prWapiInfo->au4PairwiseKeyCipherSuite + [i] >> 16) & 0x000000FF), + (uint8_t) ((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", + (uint8_t) (prWapiInfo->au4PairwiseKeyCipherSuite[0] & + 0x000000FF), + (uint8_t) ((prWapiInfo->au4PairwiseKeyCipherSuite[0] >> + 8) & 0x000000FF), + (uint8_t) ((prWapiInfo->au4PairwiseKeyCipherSuite[0] >> + 16) & 0x000000FF), + (uint8_t) ((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 = + (uint32_t) u2AuthSuiteCount; + + for (i = 0; i < (uint32_t) u2AuthSuiteCount; i++) { + WLAN_GET_FIELD_32(pucAuthSuite, + &prWapiInfo->au4AuthKeyMgtSuite[i]); + pucAuthSuite += 4; + + DBGLOG(SEC, LOUD, + "WAPI: AKM suite [%d]: %02x-%02x-%02x-%02x\n", + (uint8_t) i, + (uint8_t) (prWapiInfo->au4AuthKeyMgtSuite[i] & + 0x000000FF), + (uint8_t) ((prWapiInfo->au4AuthKeyMgtSuite[i] >> + 8) & 0x000000FF), + (uint8_t) ((prWapiInfo->au4AuthKeyMgtSuite[i] >> + 16) & 0x000000FF), + (uint8_t) ((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", + (uint8_t) (prWapiInfo->au4AuthKeyMgtSuite[0] & + 0x000000FF), + (uint8_t) ((prWapiInfo->au4AuthKeyMgtSuite[0] >> 8) & + 0x000000FF), + (uint8_t) ((prWapiInfo->au4AuthKeyMgtSuite[0] >> 16) & + 0x000000FF), + (uint8_t) ((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. + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wapiPerformPolicySelection(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBss, IN uint8_t ucBssIndex) +{ + uint32_t i; + uint32_t u4PairwiseCipher = 0; + uint32_t u4GroupCipher = 0; + uint32_t u4AkmSuite = 0; + struct WAPI_INFO *prBssWapiInfo; + struct WLAN_INFO *prWlanInfo; + struct CONNECTION_SETTINGS *prConnSettings; + + DEBUGFUNC("wapiPerformPolicySelection"); + + /* Notice!!!! WAPI AP not set the privacy bit for WAI + * and WAI-PSK at WZC configuration mode + */ + prWlanInfo = &prAdapter->rWlanInfo; + + prConnSettings = + aisGetConnSettings(prAdapter, ucBssIndex); + + if (prBss->fgIEWAPI) { + prBssWapiInfo = &prBss->rIEWAPI; + } else { + if (prConnSettings->fgWapiMode == FALSE) { + DBGLOG(SEC, TRACE, "-- No Protected BSS\n"); + return TRUE; + } + DBGLOG(SEC, TRACE, + "WAPI Information Element does not exist.\n"); + return FALSE; + } + + /* Select pairwise/group ciphers */ + for (i = 0; i < prBssWapiInfo->u4PairwiseKeyCipherSuiteCount; i++) { + if (prBssWapiInfo->au4PairwiseKeyCipherSuite[i] == + prConnSettings->u4WapiSelectedPairwiseCipher) { + u4PairwiseCipher = + prBssWapiInfo->au4PairwiseKeyCipherSuite[i]; + } + } + if (prBssWapiInfo->u4GroupKeyCipherSuite == + prConnSettings->u4WapiSelectedGroupCipher) + u4GroupCipher = prBssWapiInfo->u4GroupKeyCipherSuite; + + /* Exception handler */ + /* If we cannot find proper pairwise and group cipher suites to join the + * BSS, do not check the supported AKM suites. + */ + if (u4PairwiseCipher == 0 || u4GroupCipher == 0) { + DBGLOG(SEC, TRACE, + "Failed to select pairwise/group cipher (0x%08x/0x%08x)\n", + u4PairwiseCipher, u4GroupCipher); + return FALSE; + } + + /* Select AKM */ + /* If the driver cannot support any authentication suites advertised in + * the given BSS, we fail to perform RSNA policy selection. + */ + /* Attempt to find any overlapping supported AKM suite. */ + for (i = 0; i < prBssWapiInfo->u4AuthKeyMgtSuiteCount; i++) { + if (prBssWapiInfo->au4AuthKeyMgtSuite[i] == + prConnSettings->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", + (uint8_t) (u4PairwiseCipher & 0x000000FF), + (uint8_t) ((u4PairwiseCipher >> 8) & 0x000000FF), + (uint8_t) ((u4PairwiseCipher >> 16) & 0x000000FF), + (uint8_t) ((u4PairwiseCipher >> 24) & 0x000000FF), + (uint8_t) (u4GroupCipher & 0x000000FF), + (uint8_t) ((u4GroupCipher >> 8) & 0x000000FF), + (uint8_t) ((u4GroupCipher >> 16) & 0x000000FF), + (uint8_t) ((u4GroupCipher >> 24) & 0x000000FF)); + + DBGLOG(SEC, TRACE, "Selected AKM suite: %02x-%02x-%02x-%02x\n", + (uint8_t) (u4AkmSuite & 0x000000FF), + (uint8_t) ((u4AkmSuite >> 8) & 0x000000FF), + (uint8_t) ((u4AkmSuite >> 16) & 0x000000FF), + (uint8_t) ((u4AkmSuite >> 24) & 0x000000FF)); + + return TRUE; +} /* wapiPerformPolicySelection */ + + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/wmm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/wmm.c new file mode 100644 index 0000000000000..9630adf936f5d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/wmm.c @@ -0,0 +1,1880 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. + * If not, see . + */ + +#include "precomp.h" + +static void wmmTxTspecFrame(struct ADAPTER *prAdapter, uint8_t ucTid, + enum TSPEC_OP_CODE eOpCode, + struct PARAM_QOS_TSPEC *prTsParam, + uint8_t ucBssIndex); +static void wmmSyncAcParamWithFw(struct ADAPTER *prAdapter, uint8_t ucAc, + uint16_t u2MediumTime, uint32_t u4PhyRate, uint8_t ucBssIndex); + +static void wmmGetTsmRptTimeout(struct ADAPTER *prAdapter, + unsigned long ulParam); + +static void wmmQueryTsmResult(struct ADAPTER *prAdapter, unsigned long ulParam); +static void wmmRemoveTSM(struct ADAPTER *prAdapter, + struct ACTIVE_RM_TSM_REQ *prActiveTsm, + u_int8_t fgNeedStop, + uint8_t ucBssIndex); +static struct ACTIVE_RM_TSM_REQ *wmmGetActiveTsmReq(struct ADAPTER *prAdapter, + uint8_t ucTid, + u_int8_t fgTriggered, + u_int8_t fgAllocIfNotExist, + uint8_t ucBssIndex); +static uint32_t wmmRunEventActionTxDone(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + enum ENUM_TX_RESULT_CODE rTxDoneStatus); +static void wmmMayDoTsReplacement(struct ADAPTER *prAdapter, + uint8_t ucNewTid, uint8_t ucBssIndex); + +#if 0 +static void DumpData(PUINT8 prAddr, UINT8 uLen, char *tag); +#endif + +#if CFG_SUPPORT_SOFT_ACM +static uint16_t wmmAcmTxTimeCal(uint16_t u2SecExtra, uint16_t u2EthBodyLen, + uint16_t u2DataRate, uint16_t u2BasicRate, + uint8_t ucFlags); + +static uint16_t wmmAcmTxTimeHtCal(uint16_t u2SecExtra, uint16_t u2EthBodyLen, + uint8_t ucMcsId, uint8_t ucFlags); + +static void wmmAcmDequeueTimeOut(IN struct ADAPTER *prAdapter, + unsigned long ulParamPtr); + +#define FLAG_S_PREAMBLE BIT(0) +#define FLAG_CTS_SELF BIT(1) +#define FLAG_RTS_CTS BIT(2) +#define FLAG_G_MODE BIT(3) +#define FLAG_SHORT_GI BIT(4) +#define FLAG_40M_BW BIT(5) +#define FLAG_GF_HT BIT(6) +#define FLAG_ONLY_DATA BIT(7) + +#define TIME_LONG_PREAMBLE 192 +#define TIME_SHORT_PREAMBLE 96 +#define TIME_SIFSG 0x10 +#define TIME_SIFS 0x0A +#define FRM_LENGTH_BLOCK_ACK 30 +#define TIME_SIFSGx2 0x20 /* support Clause 18 STA exists */ +#define TIME_SIFSx2 0x14 +#define FRM_LENGTH_RTS 0x14 +#define FRM_LENGTH_ACK 0x0E +/* aggregation related */ +#define FRM_LENGTH_AGG_AMSDU_HDR 17 +#define FRM_LENGTH_AGG_RAILNK_HDR 14 + +#define LMR_PREAMBL_TIME(__fgIsGmode, __fgIsSpreamble) \ + ({ \ + uint8_t ucTime; \ + if (__fgIsGmode) \ + ucTime = 20; \ + else \ + ucTime = __fgIsSpreamble ? TIME_SHORT_PREAMBLE \ + : TIME_LONG_PREAMBLE; \ + ucTime; \ + }) +#endif + +uint8_t const aucUp2ACIMap[8] = {ACI_BE, ACI_BK, ACI_BK, ACI_BE, + ACI_VI, ACI_VI, ACI_VO, ACI_VO}; + +void wmmInit(IN struct ADAPTER *prAdapter) +{ + uint8_t i; + + for (i = 0; i < KAL_AIS_NUM; i++) { + struct WMM_INFO *prWmmInfo = + aisGetWMMInfo(prAdapter, i); + struct TSPEC_INFO *prTspecInfo = &prWmmInfo->arTsInfo[0]; + uint8_t ucTid = 0; + + for (ucTid = 0; ucTid < WMM_TSPEC_ID_NUM; + ucTid++, prTspecInfo++) { + prTspecInfo->ucTid = ucTid; + cnmTimerInitTimer(prAdapter, + &prTspecInfo->rAddTsTimer, + (PFN_MGMT_TIMEOUT_FUNC) + wmmSetupTspecTimeOut, + (unsigned long)prTspecInfo); + } +#if CFG_SUPPORT_SOFT_ACM + cnmTimerInitTimer(prAdapter, &prWmmInfo->rAcmDeqTimer, + wmmAcmDequeueTimeOut, i); + kalMemZero(&prWmmInfo->arAcmCtrl[0], + sizeof(prWmmInfo->arAcmCtrl)); +#endif + LINK_INITIALIZE(&prWmmInfo->rActiveTsmReq); + prWmmInfo->rTriggeredTsmRptTime = 0; + } + DBGLOG(WMM, TRACE, "wmm init done\n"); +} + +void wmmUnInit(IN struct ADAPTER *prAdapter) +{ + uint8_t i; + + for (i = 0; i < KAL_AIS_NUM; i++) { + struct WMM_INFO *prWmmInfo = + aisGetWMMInfo(prAdapter, i); + struct TSPEC_INFO *prTspecInfo = &prWmmInfo->arTsInfo[0]; + uint8_t ucTid = 0; + + for (ucTid = 0; ucTid < WMM_TSPEC_ID_NUM; + ucTid++, prTspecInfo++) + cnmTimerStopTimer(prAdapter, + &prTspecInfo->rAddTsTimer); +#if CFG_SUPPORT_SOFT_ACM + cnmTimerStopTimer(prAdapter, &prWmmInfo->rAcmDeqTimer); +#endif + wmmRemoveAllTsmMeasurement(prAdapter, FALSE, i); + } + DBGLOG(WMM, TRACE, "wmm uninit done\n"); +} + +void wmmFillTsinfo(struct PARAM_QOS_TSINFO *prTsInfo, uint8_t *pucTsInfo) +{ + uint32_t u4TsInfoValue = 0; + /* | 0 |1-4 | 5-6 | 7-8 | 9 | + *10 | 11-13 | 14-23 | + ** Traffic Type|TSID| Dir |Access Policy|Reserved | PSB| UP + *|reserved| + */ + + u4TsInfoValue = prTsInfo->ucTrafficType & 0x1; + u4TsInfoValue |= (prTsInfo->ucTid & 0xf) << 1; + u4TsInfoValue |= (prTsInfo->ucDirection & 0x3) << 5; + u4TsInfoValue |= (prTsInfo->ucAccessPolicy & 0x3) << 7; + u4TsInfoValue |= (prTsInfo->ucApsd & 0x1) << 10; + u4TsInfoValue |= (prTsInfo->ucuserPriority) << 11; + u4TsInfoValue |= BIT(7); /* Fixed bit in spec */ + + pucTsInfo[0] = u4TsInfoValue & 0xFF; + pucTsInfo[1] = (u4TsInfoValue >> 8) & 0xff; + pucTsInfo[2] = (u4TsInfoValue >> 16) & 0xff; +} + +void wmmComposeTspecIE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + struct PARAM_QOS_TSPEC *prParamQosTspec) +{ + struct IE_WMM_TSPEC *prIeWmmTspec = NULL; + uint8_t *pucTemp = NULL; + uint8_t aucWfaOui[] = VENDOR_OUI_WFA; + + prIeWmmTspec = (struct IE_WMM_TSPEC *)((uint8_t *)prMsduInfo->prPacket + + prMsduInfo->u2FrameLength); + pucTemp = prIeWmmTspec->aucTspecBodyPart; + + /*fill WMM head*/ + prIeWmmTspec->ucId = ELEM_ID_VENDOR; + prIeWmmTspec->ucLength = ELEM_MAX_LEN_WMM_TSPEC; + kalMemCopy(prIeWmmTspec->aucOui, aucWfaOui, sizeof(aucWfaOui)); + prIeWmmTspec->ucOuiType = VENDOR_OUI_TYPE_WMM; + prIeWmmTspec->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_TSPEC; + prIeWmmTspec->ucVersion = VERSION_WMM; + + /*fill tsinfo*/ + wmmFillTsinfo(&prParamQosTspec->rTsInfo, prIeWmmTspec->aucTsInfo); + /*1.2 BODY*/ + /*nominal size*/ + /* DumpData(prParamQosTspec, sizeof(struct PARAM_QOS_TSPEC), + ** "QosTspc"); + */ + WLAN_SET_FIELD_16(pucTemp, prParamQosTspec->u2NominalMSDUSize); + pucTemp += 2; + WLAN_SET_FIELD_16(pucTemp, prParamQosTspec->u2MaxMSDUsize); + pucTemp += 2; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4MinSvcIntv); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4MaxSvcIntv); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4InactIntv); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4SpsIntv); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4SvcStartTime); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4MinDataRate); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4MeanDataRate); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4PeakDataRate); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4MaxBurstSize); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4DelayBound); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4MinPHYRate); + pucTemp += 4; + WLAN_SET_FIELD_16(pucTemp, prParamQosTspec->u2Sba); + pucTemp += 2; + WLAN_SET_FIELD_16(pucTemp, prParamQosTspec->u2MediumTime); + /*DumpData(prIeWmmTspec->aucTsInfo, 55, "tspec ie");*/ + + prMsduInfo->u2FrameLength += IE_SIZE(prIeWmmTspec); +} + +static uint8_t wmmNewDlgToken(void) +{ + static uint8_t sWmmDlgToken; + + return sWmmDlgToken++; +} + +/* follow WMM spec, send add/del tspec request frame */ +static void wmmTxTspecFrame(struct ADAPTER *prAdapter, uint8_t ucTid, + enum TSPEC_OP_CODE eOpCode, + struct PARAM_QOS_TSPEC *prTsParam, + uint8_t ucBssIndex) +{ + struct BSS_INFO *prBssInfo = + aisGetAisBssInfo(prAdapter, ucBssIndex); + uint16_t u2PayLoadLen = WLAN_MAC_HEADER_LEN + 4; /*exclude TSPEC IE*/ + struct STA_RECORD *prStaRec = + aisGetTargetStaRec(prAdapter, ucBssIndex); + struct MSDU_INFO *prMsduInfo = NULL; + struct WMM_ACTION_TSPEC_FRAME *prActionFrame = NULL; + uint16_t u2FrameCtrl = MAC_FRAME_ACTION; + + if (!prStaRec || !prTsParam || !prBssInfo) { + DBGLOG(WMM, ERROR, "prStaRec NULL %d, prTsParam NULL %d\n", + !prStaRec, !prTsParam); + return; + } + /*build ADDTS for TID*/ + /*1 compose Action frame Fix field*/ + DBGLOG(WMM, INFO, "Tspec Action to AP=" MACSTR "\n", + MAC2STR(prStaRec->aucMacAddr)); + + prMsduInfo = cnmMgtPktAlloc(prAdapter, ACTION_ADDTS_REQ_FRAME_LEN); + if (!prMsduInfo) { + DBGLOG(WMM, ERROR, "Failed to allocate msdu info\n"); + return; + } + TX_SET_MMPDU(prAdapter, prMsduInfo, prStaRec->ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_MGMT_HEADER_LEN, u2PayLoadLen, + wmmRunEventActionTxDone, MSDU_RATE_MODE_AUTO); + + kalMemZero(prMsduInfo->prPacket, ACTION_ADDTS_REQ_FRAME_LEN); + + prActionFrame = (struct WMM_ACTION_TSPEC_FRAME *)prMsduInfo->prPacket; + + /*********frame header**********************/ + WLAN_SET_FIELD_16(&prActionFrame->u2FrameCtrl, u2FrameCtrl); + COPY_MAC_ADDR(prActionFrame->aucDestAddr, prStaRec->aucMacAddr); + COPY_MAC_ADDR(prActionFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prActionFrame->aucBSSID, prStaRec->aucMacAddr); + prActionFrame->u2SeqCtrl = 0; + + /********Frame body*************/ + prActionFrame->ucCategory = + CATEGORY_WME_MGT_NOTIFICATION; /*CATEGORY_QOS_ACTION;*/ + if (eOpCode == TX_ADDTS_REQ) { + prActionFrame->ucAction = ACTION_ADDTS_REQ; + prActionFrame->ucDlgToken = (prTsParam->ucDialogToken == 0) + ? wmmNewDlgToken() + : prTsParam->ucDialogToken; + } else if (eOpCode == TX_DELTS_REQ) { + prActionFrame->ucAction = ACTION_DELTS; + prActionFrame->ucDlgToken = + 0; /* dialog token should be always 0 in delts frame */ + } + + /* this field only meanful in ADD TS response, otherwise set to 0 */ + prActionFrame->ucStatusCode = 0; + + /*DumpData((PUINT_8)prMsduInfo->prPacket,u2PayLoadLen, "ADDTS-FF");*/ + + /********Information Element *************/ + wmmComposeTspecIE(prAdapter, prMsduInfo, prTsParam); + + /******** Insert into Msdu Queue *************/ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); +#if 0 + DumpData(((uint8_t *)prMsduInfo->prPacket) + u2PayLoadLen, + prMsduInfo->u2FrameLength - u2PayLoadLen, "TSPEC-IE"); +#endif +} + +void wmmSetupTspecTimeOut(struct ADAPTER *prAdapter, unsigned long ulParam) +{ + struct TSPEC_INFO *prTsInfo = (struct TSPEC_INFO *)ulParam; + + if (!prTsInfo) { + DBGLOG(WMM, INFO, "Wrong TS info\n"); + return; + } + + switch (prTsInfo->eState) { + case QOS_TS_ACTIVE: + DBGLOG(WMM, INFO, "Update TS TIMEOUT for TID %d\n", + prTsInfo->ucTid); + break; + case QOS_TS_SETUPING: + DBGLOG(WMM, INFO, "ADD TS TIMEOUT for TID %d\n", + prTsInfo->ucTid); + prTsInfo->eState = QOS_TS_INACTIVE; + break; + default: + DBGLOG(WMM, INFO, + "Shouldn't start this timer when Ts %d in state %d\n", + prTsInfo->ucTid, prTsInfo->eState); + break; + } +} + +uint8_t wmmCalculateUapsdSetting(struct ADAPTER *prAdapter, + uint8_t ucBssIndex) +{ + struct PM_PROFILE_SETUP_INFO *prPmProf = NULL; + struct WMM_INFO *prWmmInfo = + aisGetWMMInfo(prAdapter, ucBssIndex); + struct TSPEC_INFO *prCurTs; + uint8_t ucTid = 0; + uint8_t ucFinalSetting = 0; + struct BSS_INFO *prAisBssInfo; + + prAisBssInfo = + aisGetAisBssInfo(prAdapter, + ucBssIndex); + + if (!prAisBssInfo || !prWmmInfo) { + DBGLOG(WMM, INFO, "prWmmInfo is null %d\n", ucBssIndex); + return 0; + } + + prCurTs = &prWmmInfo->arTsInfo[0]; + prPmProf = &prAisBssInfo->rPmProfSetupInfo; + ucFinalSetting = + (prPmProf->ucBmpDeliveryAC << 4) | prPmProf->ucBmpTriggerAC; + for (ucTid = 0; ucTid < WMM_TSPEC_ID_NUM; ucTid++, prCurTs++) { + uint8_t ucPsd = 0; + + if (prCurTs->eState != QOS_TS_ACTIVE) + continue; + switch (prCurTs->eDir) { + case UPLINK_TS: + ucPsd = BIT(prCurTs->eAC); + break; + case DOWNLINK_TS: + ucPsd = BIT(prCurTs->eAC + 4); + break; + case BI_DIR_TS: + ucPsd = BIT(prCurTs->eAC) | BIT(prCurTs->eAC + 4); + break; + } + if (prCurTs->fgUapsd) + ucFinalSetting |= ucPsd; + else + ucFinalSetting &= ~ucPsd; + } + return ucFinalSetting; +} + +void wmmSyncAcParamWithFw(struct ADAPTER *prAdapter, uint8_t ucAc, + uint16_t u2MediumTime, uint32_t u4PhyRate, + uint8_t ucBssIndex) +{ + struct CMD_SET_WMM_PS_TEST_STRUCT rSetWmmPsTestParam; +#if CFG_SUPPORT_SOFT_ACM + struct SOFT_ACM_CTRL *prAcmCtrl = NULL; +#endif + struct CMD_UPDATE_AC_PARAMS rCmdUpdateAcParam; + struct BSS_INFO *prAisBssInfo; + struct WMM_INFO *prWmmInfo = + aisGetWMMInfo(prAdapter, ucBssIndex); + + prAisBssInfo = + aisGetAisBssInfo(prAdapter, + ucBssIndex); + ASSERT(prAisBssInfo); +#if CFG_SUPPORT_SOFT_ACM + prAcmCtrl = &prWmmInfo->arAcmCtrl[ucAc]; +/* admitted time is in unit 32-us */ +#if 0 /* UT/IT code */ + if (u2MediumTime) + u2MediumTime = 153; +#endif + prAcmCtrl->u4AdmittedTime = u2MediumTime * 32; + prAcmCtrl->u4IntervalEndSec = 0; +#endif + kalMemZero(&rCmdUpdateAcParam, sizeof(rCmdUpdateAcParam)); + rCmdUpdateAcParam.ucAcIndex = ucAc; + rCmdUpdateAcParam.ucBssIdx = prAisBssInfo->ucBssIndex; + rCmdUpdateAcParam.u2MediumTime = u2MediumTime; + rCmdUpdateAcParam.u4PhyRate = u4PhyRate; + wlanSendSetQueryCmd(prAdapter, CMD_ID_UPDATE_AC_PARMS, TRUE, FALSE, + FALSE, NULL, NULL, sizeof(struct CMD_UPDATE_AC_PARAMS), + (uint8_t *)&rCmdUpdateAcParam, NULL, 0); + kalMemZero(&rSetWmmPsTestParam, sizeof(rSetWmmPsTestParam)); + rSetWmmPsTestParam.ucBssIndex = prAisBssInfo->ucBssIndex; + rSetWmmPsTestParam.bmfgApsdEnAc = + wmmCalculateUapsdSetting(prAdapter, + prAisBssInfo->ucBssIndex); + wlanSendSetQueryCmd(prAdapter, CMD_ID_SET_WMM_PS_TEST_PARMS, TRUE, + FALSE, FALSE, NULL, NULL, + sizeof(struct CMD_SET_WMM_PS_TEST_STRUCT), + (uint8_t *)&rSetWmmPsTestParam, NULL, 0); + + DBGLOG(WMM, INFO, "Ac=%d, MediumTime=%d PhyRate=%u Uapsd 0x%02x\n", + ucAc, u2MediumTime, u4PhyRate, rSetWmmPsTestParam.bmfgApsdEnAc); +} + +/* Return: AC List in bit map if this ac has active tspec */ +uint8_t wmmHasActiveTspec(struct WMM_INFO *prWmmInfo) +{ + uint8_t ucTid = 0; + uint8_t ucACList = 0; + + if (!prWmmInfo) { + DBGLOG(WMM, INFO, "prWmmInfo is null\n"); + return 0; + } + + /* if any tspec is active, it means */ + for (; ucTid < WMM_TSPEC_ID_NUM; ucTid++) + if (prWmmInfo->arTsInfo[ucTid].eState == QOS_TS_ACTIVE) + ucACList |= 1 << prWmmInfo->arTsInfo[ucTid].eAC; + return ucACList; +} + +void wmmRunEventTSOperate(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_TS_OPERATE *prMsgTsOperate = + (struct MSG_TS_OPERATE *)prMsgHdr; + uint8_t ucBssIndex = prMsgTsOperate->ucBssIdx; + + wmmTspecSteps(prAdapter, prMsgTsOperate->ucTid, prMsgTsOperate->eOpCode, + (void *)&prMsgTsOperate->rTspecParam, + ucBssIndex); + cnmMemFree(prAdapter, prMsgHdr); +} + +void wmmTspecSteps(struct ADAPTER *prAdapter, uint8_t ucTid, + enum TSPEC_OP_CODE eOpCode, void *prStepParams, + uint8_t ucBssIndex) +{ + struct AIS_FSM_INFO *prAisFsmInfo = + aisGetAisFsmInfo(prAdapter, ucBssIndex); + struct WMM_INFO *prWmmInfo = + aisGetWMMInfo(prAdapter, ucBssIndex); + struct TSPEC_INFO *prCurTs = NULL; + struct BSS_INFO *prAisBssInfo = + aisGetAisBssInfo(prAdapter, ucBssIndex); + + ASSERT(prAisBssInfo); + if (prAisBssInfo->eConnectionState != + MEDIA_STATE_CONNECTED || + prAisFsmInfo->eCurrentState == AIS_STATE_DISCONNECTING) { + DBGLOG(WMM, INFO, + "ignore OP code %d when medium disconnected\n", eOpCode); + return; + } + + if (ucTid >= WMM_TSPEC_ID_NUM) { + DBGLOG(WMM, INFO, "Invalid TID %d\n", ucTid); + return; + } + + prCurTs = &prWmmInfo->arTsInfo[ucTid]; + DBGLOG(WMM, TRACE, "TID %d, State %d, Oper %d\n", ucTid, + prCurTs->eState, eOpCode); + + switch (prCurTs->eState) { + case QOS_TS_INACTIVE: { + struct PARAM_QOS_TSPEC *prQosTspec = + (struct PARAM_QOS_TSPEC *)prStepParams; + + if (eOpCode != TX_ADDTS_REQ) + break; + if (!prQosTspec) { + DBGLOG(WMM, INFO, "Lack of Tspec Param\n"); + break; + } + /*Send ADDTS req Frame*/ + wmmTxTspecFrame(prAdapter, ucTid, TX_ADDTS_REQ, prQosTspec, + ucBssIndex); + + /*start ADDTS timer*/ + cnmTimerStartTimer(prAdapter, &prCurTs->rAddTsTimer, 1000); + prCurTs->eState = QOS_TS_SETUPING; + prCurTs->eAC = aucUp2ACIMap[prQosTspec->rTsInfo.ucuserPriority]; + prCurTs->ucToken = prQosTspec->ucDialogToken; + break; + } + case QOS_TS_SETUPING: { + struct WMM_ADDTS_RSP_STEP_PARAM *prParam = + (struct WMM_ADDTS_RSP_STEP_PARAM *)prStepParams; + + if (eOpCode == TX_DELTS_REQ || eOpCode == RX_DELTS_REQ || + eOpCode == DISC_DELTS_REQ) { + cnmTimerStopTimer(prAdapter, &prCurTs->rAddTsTimer); + prCurTs->eState = QOS_TS_INACTIVE; + DBGLOG(WMM, INFO, "Del Ts %d in setuping state\n", + ucTid); + break; + } else if (eOpCode != RX_ADDTS_RSP || + prParam->ucDlgToken != + prWmmInfo->arTsInfo[ucTid].ucToken) + break; + + cnmTimerStopTimer(prAdapter, &prCurTs->rAddTsTimer); + if (prParam->ucStatusCode == WMM_TS_STATUS_ADMISSION_ACCEPTED) { + struct ACTIVE_RM_TSM_REQ *prActiveTsmReq = NULL; + + prCurTs->eState = QOS_TS_ACTIVE; + prCurTs->eDir = prParam->eDir; + prCurTs->fgUapsd = !!prParam->ucApsd; + prCurTs->u2MediumTime = prParam->u2MediumTime; + prCurTs->u4PhyRate = prParam->u4PhyRate; + wmmSyncAcParamWithFw(prAdapter, prCurTs->eAC, + prParam->u2MediumTime, + prParam->u4PhyRate, + ucBssIndex); + wmmMayDoTsReplacement(prAdapter, ucTid, ucBssIndex); + /* start pending TSM if it was requested before admitted + */ + prActiveTsmReq = wmmGetActiveTsmReq(prAdapter, ucTid, + TRUE, FALSE, ucBssIndex); + if (prActiveTsmReq) + wmmStartTsmMeasurement( + prAdapter, (unsigned long)prActiveTsmReq + ->prTsmReq, + ucBssIndex); + prActiveTsmReq = wmmGetActiveTsmReq(prAdapter, ucTid, + FALSE, FALSE, ucBssIndex); + if (prActiveTsmReq) + wmmStartTsmMeasurement( + prAdapter, (unsigned long)prActiveTsmReq + ->prTsmReq, + ucBssIndex); + + /* nicTxChangeDataPortByAc( + ** prAisBssInfo->prStaRecOfAP, + ** prCurTs->eAC, TRUE); + */ + } else { + prCurTs->eState = QOS_TS_INACTIVE; + DBGLOG(WMM, ERROR, "ADD TS is rejected, status=%d\n", + prParam->ucStatusCode); + } + break; + } + case QOS_TS_ACTIVE: { + struct ACTIVE_RM_TSM_REQ *prActiveTsm = NULL; + + switch (eOpCode) { + case TX_DELTS_REQ: + case RX_DELTS_REQ: + case DISC_DELTS_REQ: + prActiveTsm = wmmGetActiveTsmReq(prAdapter, ucTid, TRUE, + FALSE, ucBssIndex); + if (prActiveTsm) + wmmRemoveTSM(prAdapter, prActiveTsm, TRUE, + ucBssIndex); + prActiveTsm = wmmGetActiveTsmReq(prAdapter, ucTid, + FALSE, FALSE, ucBssIndex); + if (prActiveTsm) + wmmRemoveTSM(prAdapter, prActiveTsm, TRUE, + ucBssIndex); + prCurTs->eState = QOS_TS_INACTIVE; +#if CFG_SUPPORT_SOFT_ACM + /* Need to change tx queue, due to we do soft ACM */ + qmHandleDelTspec(prAdapter, + prAisFsmInfo->prTargetStaRec, + prCurTs->eAC); +#endif + wmmSyncAcParamWithFw(prAdapter, prCurTs->eAC, 0, 0, + ucBssIndex); + wmmDumpActiveTspecs(prAdapter, NULL, 0, + ucBssIndex); + if (eOpCode == TX_DELTS_REQ) + wmmTxTspecFrame( + prAdapter, ucTid, TX_DELTS_REQ, + (struct PARAM_QOS_TSPEC *)prStepParams, + ucBssIndex); + break; + case TX_ADDTS_REQ: + /*Send ADDTS req Frame*/ + wmmTxTspecFrame(prAdapter, ucTid, TX_ADDTS_REQ, + (struct PARAM_QOS_TSPEC *)prStepParams, + ucBssIndex); + prCurTs->eAC = + aucUp2ACIMap[((struct PARAM_QOS_TSPEC *) + prStepParams) + ->rTsInfo.ucuserPriority]; + prCurTs->ucToken = + ((struct PARAM_QOS_TSPEC *)prStepParams) + ->ucDialogToken; + /*start ADDTS timer*/ + cnmTimerStartTimer(prAdapter, &prCurTs->rAddTsTimer, + 1000); + break; + /* for case: TS of tid N has existed, then setup TS with this + ** tid again. + */ + case RX_ADDTS_RSP: { + struct WMM_ADDTS_RSP_STEP_PARAM *prParam = + (struct WMM_ADDTS_RSP_STEP_PARAM *)prStepParams; + + if (prParam->ucStatusCode != + WMM_TS_STATUS_ADMISSION_ACCEPTED) { + DBGLOG(WMM, INFO, + "Update TS %d request was rejected by BSS\n", + ucTid); + break; + } + prCurTs->eDir = prParam->eDir; + prCurTs->fgUapsd = !!prParam->ucApsd; + prCurTs->u2MediumTime = prParam->u2MediumTime; + prCurTs->u4PhyRate = prParam->u4PhyRate; + wmmSyncAcParamWithFw(prAdapter, prCurTs->eAC, + prParam->u2MediumTime, + prParam->u4PhyRate, + ucBssIndex); + wmmMayDoTsReplacement(prAdapter, ucTid, ucBssIndex); + break; + } + default: + break; + } + break; + } + default: + break; + } +} + +static uint32_t wmmRunEventActionTxDone(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + DBGLOG(WMM, INFO, "Status %d\n", rTxDoneStatus); + return WLAN_STATUS_SUCCESS; +} + +void DumpData(uint8_t *prAddr, uint8_t uLen, char *tag) +{ + uint16_t k = 0; + char buf[16 * 3 + 1]; + uint16_t loop = 0; + uint8_t *p = prAddr; + static char const charmap[16] = {'0', '1', '2', '3', '4', '5', + '6', '7', '8', '9', 'A', 'B', + 'C', 'D', 'E', 'F'}; + + uLen = (uLen > 128) ? 128 : uLen; + loop = uLen / 16; + if (tag) + DBGLOG(WMM, INFO, "++++++++ dump data \"%s\" p=%p len=%d\n", + tag, prAddr, uLen); + else + DBGLOG(WMM, INFO, "++++++ dump data p=%p, len=%d\n", prAddr, + uLen); + + while (loop) { + for (k = 0; k < 16; k++) { + buf[k * 3] = charmap[((*(p + k) & 0xF0) >> 4)]; + buf[k * 3 + 1] = charmap[(*(p + k) & 0x0F)]; + buf[k * 3 + 2] = ' '; + } + buf[16 * 3] = 0; + DBGLOG(WMM, INFO, "%s\n", buf); + loop--; + p += 16; + } + uLen = uLen % 16; + k = 0; + while (uLen) { + buf[k * 3] = charmap[((*(p + k) & 0xF0) >> 4)]; + buf[k * 3 + 1] = charmap[(*(p + k) & 0x0F)]; + buf[k * 3 + 2] = ' '; + k++; + uLen--; + } + buf[k * 3] = 0; + DBGLOG(WMM, INFO, "%s\n", buf); + DBGLOG(WMM, INFO, "====== end dump data\n"); +} + +/* TSM related */ +static void wmmQueryTsmResult(struct ADAPTER *prAdapter, + unsigned long ulParam) +{ + uint8_t ucBssIndex = + ((struct ACTIVE_RM_TSM_REQ *)ulParam)->ucBssIdx; + struct RM_TSM_REQ *prTsmReq = + ((struct ACTIVE_RM_TSM_REQ *)ulParam)->prTsmReq; + struct WMM_INFO *prWmmInfo = + aisGetWMMInfo(prAdapter, ucBssIndex); + struct CMD_GET_TSM_STATISTICS rGetTsmStatistics; + + DBGLOG(WMM, INFO, "[%d] Query TSM statistics, tid = %d\n", + ucBssIndex, + prTsmReq->ucTID); + DBGLOG(WMM, INFO, "%p , aci %d, duration %d\n", prTsmReq, + prTsmReq->ucACI, prTsmReq->u2Duration); + + rGetTsmStatistics.ucBssIdx = ucBssIndex; + rGetTsmStatistics.ucAcIndex = prTsmReq->ucACI; + rGetTsmStatistics.ucTid = prTsmReq->ucTID; + COPY_MAC_ADDR(rGetTsmStatistics.aucPeerAddr, prTsmReq->aucPeerAddr); + + wlanSendSetQueryCmd(prAdapter, CMD_ID_GET_TSM_STATISTICS, FALSE, TRUE, + FALSE, wmmComposeTsmRpt, NULL, + sizeof(struct CMD_GET_TSM_STATISTICS), + (uint8_t *)&rGetTsmStatistics, NULL, 0); + cnmTimerInitTimer(prAdapter, &prWmmInfo->rTsmTimer, + wmmGetTsmRptTimeout, + ulParam); + cnmTimerStartTimer(prAdapter, &prWmmInfo->rTsmTimer, 2000); + +} + +static struct ACTIVE_RM_TSM_REQ *wmmGetActiveTsmReq(struct ADAPTER *prAdapter, + uint8_t ucTid, + u_int8_t fgTriggered, + u_int8_t fgAllocIfNotExist, + uint8_t ucBssIndex) +{ + struct WMM_INFO *prWMMInfo = + aisGetWMMInfo(prAdapter, ucBssIndex); + struct ACTIVE_RM_TSM_REQ *prActiveReq = NULL; + u_int8_t fgFound = FALSE; + + LINK_FOR_EACH_ENTRY(prActiveReq, &prWMMInfo->rActiveTsmReq, rLinkEntry, + struct ACTIVE_RM_TSM_REQ) + { + if ((!!prActiveReq->prTsmReq->u2Duration) == fgTriggered && + ucTid == prActiveReq->prTsmReq->ucTID) { + fgFound = TRUE; + break; + } + } + if (!fgFound && fgAllocIfNotExist) { + fgFound = TRUE; + prActiveReq = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, + sizeof(struct ACTIVE_RM_TSM_REQ)); + if (!prActiveReq) + return NULL; + LINK_INSERT_TAIL(&prWMMInfo->rActiveTsmReq, + &prActiveReq->rLinkEntry); + } + return fgFound ? prActiveReq : NULL; +} + +static void wmmRemoveTSM(struct ADAPTER *prAdapter, + struct ACTIVE_RM_TSM_REQ *prActiveTsm, + u_int8_t fgNeedStop, + uint8_t ucBssIndex) +{ + struct WMM_INFO *prWMMInfo = + aisGetWMMInfo(prAdapter, ucBssIndex); + struct LINK *prActiveTsmLink = &prWMMInfo->rActiveTsmReq; + + LINK_REMOVE_KNOWN_ENTRY(prActiveTsmLink, prActiveTsm); + if (fgNeedStop) { + struct CMD_SET_TSM_STATISTICS_REQUEST rTsmStatistics; + struct STA_RECORD *prStaRec = NULL; + struct BSS_INFO *prAisBssInfo; + + prAisBssInfo = + aisGetAisBssInfo(prAdapter, + ucBssIndex); + if (!prAisBssInfo) { + DBGLOG(WMM, ERROR, "prAisBssInfo is NULL\n"); + return; + } + prStaRec = prAisBssInfo->prStaRecOfAP; + nicTxChangeDataPortByAc(prAdapter, + prStaRec, + prActiveTsm->prTsmReq->ucACI, + FALSE); + rTsmStatistics.ucBssIdx = prAisBssInfo->ucBssIndex; + rTsmStatistics.ucEnabled = FALSE; + rTsmStatistics.ucAcIndex = prActiveTsm->prTsmReq->ucACI; + rTsmStatistics.ucTid = prActiveTsm->prTsmReq->ucTID; + COPY_MAC_ADDR(rTsmStatistics.aucPeerAddr, + prActiveTsm->prTsmReq->aucPeerAddr); + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_TSM_STATISTICS_REQUEST, TRUE, + FALSE, FALSE, NULL, NULL, + sizeof(struct CMD_SET_TSM_STATISTICS_REQUEST), + (uint8_t *)&rTsmStatistics, NULL, 0); + } + cnmMemFree(prAdapter, prActiveTsm->prTsmReq); + cnmMemFree(prAdapter, prActiveTsm); +} + +void wmmStartTsmMeasurement(struct ADAPTER *prAdapter, unsigned long ulParam, + uint8_t ucBssIndex) +{ + struct WMM_INFO *prWMMInfo = + aisGetWMMInfo(prAdapter, ucBssIndex); + struct CMD_SET_TSM_STATISTICS_REQUEST rTsmStatistics; + struct RM_TSM_REQ *prTsmReq = (struct RM_TSM_REQ *)ulParam; + uint8_t ucTid = prTsmReq->ucTID; + struct ACTIVE_RM_TSM_REQ *prActiveTsmReq = NULL; + struct STA_RECORD *prStaRec = NULL; + struct TSPEC_INFO *prCurTs = NULL; + struct BSS_INFO *prAisBssInfo; + + prAisBssInfo = + aisGetAisBssInfo(prAdapter, ucBssIndex); + + ASSERT(prAisBssInfo); + if (!prTsmReq->u2Duration && + !(prTsmReq->rTriggerCond.ucCondition & TSM_TRIGGER_CONDITION_ALL)) { + DBGLOG(WMM, WARN, "Duration is %d, Trigger Condition %d\n", + prTsmReq->u2Duration, + prTsmReq->rTriggerCond.ucCondition); + cnmMemFree(prAdapter, prTsmReq); + rrmScheduleNextRm(prAdapter, + ucBssIndex); + return; + } + prStaRec = prAisBssInfo->prStaRecOfAP; + if (!prStaRec) { + DBGLOG(WMM, INFO, "No station record found for "MACSTR"\n", + MAC2STR(prTsmReq->aucPeerAddr)); + cnmMemFree(prAdapter, prTsmReq); + rrmScheduleNextRm(prAdapter, + ucBssIndex); + return; + } + /* if there's a active tspec, then TID means TS ID */ + prCurTs = &prWMMInfo->arTsInfo[ucTid]; + if (prCurTs->eState == QOS_TS_ACTIVE) + prTsmReq->ucACI = prCurTs->eAC; + else { /* otherwise TID means TC ID */ + uint8_t ucTsAcs = wmmHasActiveTspec(prWMMInfo); + + prTsmReq->ucACI = aucUp2ACIMap[ucTid]; + /* if current TID is not admitted, don't start measurement, only + ** save this requirement + */ + if (prStaRec->afgAcmRequired[prTsmReq->ucACI] && + !(ucTsAcs & BIT(prTsmReq->ucACI))) { + DBGLOG(WMM, INFO, + "ACM is set for UP %d, but No tspec is setup\n", + ucTid); + rrmScheduleNextRm(prAdapter, + ucBssIndex); + return; + } + } + + kalMemZero(&rTsmStatistics, sizeof(rTsmStatistics)); + if (prTsmReq->u2Duration) { + /* If a non-AP QoS STa receives a Transmit Stream/Category + *Measurement Request for a TC, or + ** TS that is already being measured using a triggered transmit + *stream/category measurement, + ** the triggered traffic stream measurement shall be suspended + *for the duration of the requested + ** traffic stream measurement. When triggered measurement + *resumes, the traffic stream metrics + ** shall be reset. See end part of 802.11k 11.10.8.8 + **/ + LINK_FOR_EACH_ENTRY(prActiveTsmReq, &prWMMInfo->rActiveTsmReq, + rLinkEntry, struct ACTIVE_RM_TSM_REQ) + { + if (prActiveTsmReq->prTsmReq->u2Duration || + prActiveTsmReq->prTsmReq->ucACI != prTsmReq->ucACI) + continue; + nicTxChangeDataPortByAc( + prAdapter, + prStaRec, + prTsmReq->ucACI, + FALSE); + rTsmStatistics.ucBssIdx = + ucBssIndex; + rTsmStatistics.ucEnabled = FALSE; + rTsmStatistics.ucAcIndex = prTsmReq->ucACI; + rTsmStatistics.ucTid = prActiveTsmReq->prTsmReq->ucTID; + COPY_MAC_ADDR(rTsmStatistics.aucPeerAddr, + prActiveTsmReq->prTsmReq->aucPeerAddr); + wlanSendSetQueryCmd( + prAdapter, CMD_ID_SET_TSM_STATISTICS_REQUEST, + TRUE, FALSE, FALSE, NULL, NULL, + sizeof(struct CMD_SET_TSM_STATISTICS_REQUEST), + (uint8_t *)&rTsmStatistics, NULL, 0); + } + prActiveTsmReq = wmmGetActiveTsmReq( + prAdapter, ucTid, !!prTsmReq->u2Duration, TRUE, + ucBssIndex); + /* if exist normal tsm on the same ts, replace it */ + if (prActiveTsmReq->prTsmReq) + cnmMemFree(prAdapter, prActiveTsmReq->prTsmReq); + DBGLOG(WMM, INFO, "%p tid %d, aci %d, duration %d\n", prTsmReq, + prTsmReq->ucTID, prTsmReq->ucACI, prTsmReq->u2Duration); + prActiveTsmReq->ucBssIdx = ucBssIndex; + cnmTimerInitTimer(prAdapter, &prWMMInfo->rTsmTimer, + wmmQueryTsmResult, + (unsigned long)prActiveTsmReq); + cnmTimerStartTimer(prAdapter, &prWMMInfo->rTsmTimer, + TU_TO_MSEC(prTsmReq->u2Duration)); + } else { + prActiveTsmReq = wmmGetActiveTsmReq( + prAdapter, ucTid, !prTsmReq->u2Duration, TRUE, + ucBssIndex); + /* if exist triggered tsm on the same ts, replace it */ + if (prActiveTsmReq->prTsmReq) { + cnmTimerStopTimer(prAdapter, + &prActiveTsmReq->rTsmTimer); + cnmMemFree(prAdapter, prActiveTsmReq->prTsmReq); + } + rTsmStatistics.ucTriggerCondition = + prTsmReq->rTriggerCond.ucCondition; + rTsmStatistics.ucMeasureCount = + prTsmReq->rTriggerCond.ucMeasureCount; + rTsmStatistics.ucTriggerTimeout = + prTsmReq->rTriggerCond.ucTriggerTimeout; + rTsmStatistics.ucAvgErrThreshold = + prTsmReq->rTriggerCond.ucAvgErrThreshold; + rTsmStatistics.ucConsecutiveErrThreshold = + prTsmReq->rTriggerCond.ucConsecutiveErr; + rTsmStatistics.ucDelayThreshold = + prTsmReq->rTriggerCond.ucDelayThreshold; + rTsmStatistics.ucBin0Range = prTsmReq->ucB0Range; + } + nicTxChangeDataPortByAc(prAdapter, prStaRec, prTsmReq->ucACI, TRUE); + prActiveTsmReq->prTsmReq = prTsmReq; + rTsmStatistics.ucBssIdx = ucBssIndex; + rTsmStatistics.ucAcIndex = prTsmReq->ucACI; + rTsmStatistics.ucTid = prTsmReq->ucTID; + rTsmStatistics.ucEnabled = TRUE; + COPY_MAC_ADDR(rTsmStatistics.aucPeerAddr, prTsmReq->aucPeerAddr); + DBGLOG(WMM, INFO, "enabled=%d, tid=%d\n", rTsmStatistics.ucEnabled, + ucTid); + wlanSendSetQueryCmd(prAdapter, CMD_ID_SET_TSM_STATISTICS_REQUEST, TRUE, + FALSE, FALSE, NULL, NULL, + sizeof(struct CMD_SET_TSM_STATISTICS_REQUEST), + (uint8_t *)&rTsmStatistics, NULL, 0); +} + +void wmmRemoveAllTsmMeasurement(struct ADAPTER *prAdapter, + u_int8_t fgOnlyTriggered, uint8_t ucBssIndex) +{ + struct WMM_INFO *prWmmInfo = + aisGetWMMInfo(prAdapter, ucBssIndex); + struct LINK *prActiveTsmLink = + &prWmmInfo->rActiveTsmReq; + struct ACTIVE_RM_TSM_REQ *prActiveTsm = NULL; + struct ACTIVE_RM_TSM_REQ *prHead = LINK_PEEK_HEAD( + prActiveTsmLink, struct ACTIVE_RM_TSM_REQ, rLinkEntry); + u_int8_t fgFinished = FALSE; + + if (!fgOnlyTriggered) + cnmTimerStopTimer(prAdapter, + &prWmmInfo->rTsmTimer); + do { + prActiveTsm = LINK_PEEK_TAIL( + prActiveTsmLink, struct ACTIVE_RM_TSM_REQ, rLinkEntry); + if (!prActiveTsm) + break; + if (prActiveTsm == prHead) + fgFinished = TRUE; + if (fgOnlyTriggered && prActiveTsm->prTsmReq->u2Duration) + continue; + wmmRemoveTSM(prAdapter, prActiveTsm, TRUE, ucBssIndex); + } while (!fgFinished); + prWmmInfo->rTriggeredTsmRptTime = 0; +} + +u_int8_t wmmParseQosAction(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct WLAN_ACTION_FRAME *prWlanActionFrame = NULL; + uint8_t *pucIE = NULL; + struct PARAM_QOS_TSPEC rTspec; + uint16_t u2Offset = 0; + uint16_t u2IEsBufLen = 0; + uint8_t ucTid = WMM_TSPEC_ID_NUM; + struct WMM_ADDTS_RSP_STEP_PARAM rStepParam; + u_int8_t ret = FALSE; + uint8_t ucBssIndex = secGetBssIdxByRfb(prAdapter, + prSwRfb); + + prWlanActionFrame = (struct WLAN_ACTION_FRAME *)prSwRfb->pvHeader; + DBGLOG(WMM, INFO, "[%d] Action=%d\n", + ucBssIndex, + prWlanActionFrame->ucAction); + switch (prWlanActionFrame->ucAction) { + case ACTION_ADDTS_RSP: { + kalMemZero(&rStepParam, sizeof(rStepParam)); + if (prWlanActionFrame->ucCategory == + CATEGORY_WME_MGT_NOTIFICATION) { + struct WMM_ACTION_TSPEC_FRAME *prAddTsRsp = + (struct WMM_ACTION_TSPEC_FRAME *) + prWlanActionFrame; + + rStepParam.ucDlgToken = prAddTsRsp->ucDlgToken; + rStepParam.ucStatusCode = prAddTsRsp->ucStatusCode; + pucIE = (uint8_t *)prAddTsRsp->aucInfoElem; + } else if (prWlanActionFrame->ucCategory == + CATEGORY_QOS_ACTION) { + struct ACTION_ADDTS_RSP_FRAME *prAddTsRsp = + (struct ACTION_ADDTS_RSP_FRAME *) + prWlanActionFrame; + + rStepParam.ucDlgToken = prAddTsRsp->ucDialogToken; + rStepParam.ucStatusCode = prAddTsRsp->ucStatusCode; + pucIE = (uint8_t *)prAddTsRsp->aucInfoElem; + } else { + DBGLOG(WMM, INFO, + "Not supported category %d for action %d\n", + prWlanActionFrame->ucCategory, + prWlanActionFrame->ucAction); + break; + } + + /*for each IE*/ + u2IEsBufLen = + prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen - + (uint16_t)(OFFSET_OF(struct ACTION_ADDTS_RSP_FRAME, + aucInfoElem) - + WLAN_MAC_HEADER_LEN); + + IE_FOR_EACH(pucIE, u2IEsBufLen, u2Offset) + { + switch (IE_ID(pucIE)) { + case ELEM_ID_TSPEC: + case ELEM_ID_VENDOR: + if (wmmParseTspecIE(prAdapter, pucIE, + &rTspec)) { + rStepParam.u2MediumTime = + rTspec.u2MediumTime; + ucTid = rTspec.rTsInfo.ucTid; + rStepParam.eDir = + rTspec.rTsInfo.ucDirection; + rStepParam.u4PhyRate = + rTspec.u4MinPHYRate; + rStepParam.ucApsd = + rTspec.rTsInfo.ucApsd; + } else { + DBGLOG(WMM, INFO, + "can't parse Tspec IE?!\n"); + } + break; + default: + break; + } + } + wmmTspecSteps(prAdapter, ucTid, RX_ADDTS_RSP, &rStepParam, + ucBssIndex); + ret = TRUE; + break; + } + case ACTION_DELTS: { + if (prWlanActionFrame->ucCategory == + CATEGORY_WME_MGT_NOTIFICATION) { + /* wmm Tspec */ + struct WMM_ACTION_TSPEC_FRAME *prDelTs = + (struct WMM_ACTION_TSPEC_FRAME *) + prWlanActionFrame; + + u2IEsBufLen = prSwRfb->u2PacketLen - + (uint16_t)OFFSET_OF( + struct WMM_ACTION_TSPEC_FRAME, + aucInfoElem); + u2Offset = 0; + pucIE = prDelTs->aucInfoElem; + IE_FOR_EACH(pucIE, u2IEsBufLen, u2Offset) + { + if (!wmmParseTspecIE(prAdapter, pucIE, &rTspec)) + continue; + ucTid = rTspec.rTsInfo.ucTid; + break; + } + } else if (prWlanActionFrame->ucCategory == + CATEGORY_QOS_ACTION) { + /* IEEE 802.11 Tspec */ + struct ACTION_DELTS_FRAME *prDelTs = + (struct ACTION_DELTS_FRAME *)prWlanActionFrame; + + ucTid = WMM_TSINFO_TSID(prDelTs->aucTsInfo[0]); + } + + wmmTspecSteps(prAdapter, ucTid, RX_DELTS_REQ, NULL, + ucBssIndex); + ret = TRUE; + break; + } + default: + break; + } + return ret; +} + +u_int8_t wmmParseTspecIE(struct ADAPTER *prAdapter, uint8_t *pucIE, + struct PARAM_QOS_TSPEC *prTspec) +{ + uint32_t u4TsInfoValue = 0; + uint8_t *pucTemp = NULL; + + if (IE_ID(pucIE) == ELEM_ID_TSPEC) { + DBGLOG(WMM, INFO, "found 802.11 Tspec Information Element\n"); + /* todo: implement 802.11 Tspec here, assign value to + ** u4TsInfoValue and pucTemp + */ + u4TsInfoValue = 0; + pucTemp = NULL; + return FALSE; /* we didn't support IEEE 802.11 Tspec now */ + } + { + struct IE_WMM_TSPEC *prIeWmmTspec = + (struct IE_WMM_TSPEC *)pucIE; + uint8_t aucWfaOui[] = VENDOR_OUI_WFA; + + if (prIeWmmTspec->ucId != ELEM_ID_VENDOR || + kalMemCmp(prIeWmmTspec->aucOui, aucWfaOui, + sizeof(aucWfaOui)) || + prIeWmmTspec->ucOuiType != VENDOR_OUI_TYPE_WMM || + prIeWmmTspec->ucOuiSubtype != + VENDOR_OUI_SUBTYPE_WMM_TSPEC) { + return FALSE; + } + u4TsInfoValue |= prIeWmmTspec->aucTsInfo[0]; + u4TsInfoValue |= (prIeWmmTspec->aucTsInfo[1] << 8); + u4TsInfoValue |= (prIeWmmTspec->aucTsInfo[2] << 16); + pucTemp = prIeWmmTspec->aucTspecBodyPart; + } + + prTspec->rTsInfo.ucTrafficType = WMM_TSINFO_TRAFFIC_TYPE(u4TsInfoValue); + prTspec->rTsInfo.ucTid = WMM_TSINFO_TSID(u4TsInfoValue); + prTspec->rTsInfo.ucDirection = WMM_TSINFO_DIR(u4TsInfoValue); + prTspec->rTsInfo.ucAccessPolicy = WMM_TSINFO_AC(u4TsInfoValue); + prTspec->rTsInfo.ucApsd = WMM_TSINFO_PSB(u4TsInfoValue); + prTspec->rTsInfo.ucuserPriority = WMM_TSINFO_UP(u4TsInfoValue); + + /* nominal size*/ + WLAN_GET_FIELD_16(pucTemp, &prTspec->u2NominalMSDUSize); + pucTemp += 2; + WLAN_GET_FIELD_16(pucTemp, &prTspec->u2MaxMSDUsize); + pucTemp += 2; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4MinSvcIntv); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4MaxSvcIntv); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4InactIntv); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4SpsIntv); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4SvcStartTime); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4MinDataRate); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4MeanDataRate); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4PeakDataRate); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4MaxBurstSize); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4DelayBound); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4MinPHYRate); + pucTemp += 4; + WLAN_GET_FIELD_16(pucTemp, &prTspec->u2Sba); + pucTemp += 2; + WLAN_GET_FIELD_16(pucTemp, &prTspec->u2MediumTime); + pucTemp += 2; + ASSERT((pucTemp == (IE_SIZE(pucIE) + pucIE))); + DBGLOG(WMM, INFO, "TsId=%d, TrafficType=%d, PSB=%d, MediumTime=%d\n", + prTspec->rTsInfo.ucTid, prTspec->rTsInfo.ucTrafficType, + prTspec->rTsInfo.ucApsd, prTspec->u2MediumTime); + return TRUE; +} + +static void wmmGetTsmRptTimeout(struct ADAPTER *prAdapter, + unsigned long ulParam) +{ + uint8_t ucBssIndex = + ((struct ACTIVE_RM_TSM_REQ *)ulParam)->ucBssIdx; + DBGLOG(WMM, ERROR, + "[%d] timeout to get Tsm Rpt from firmware\n", ucBssIndex); + wlanReleasePendingCmdById(prAdapter, CMD_ID_GET_TSM_STATISTICS); + wmmRemoveTSM(prAdapter, (struct ACTIVE_RM_TSM_REQ *)ulParam, TRUE, + ucBssIndex); + /* schedule next measurement after a duration based TSM done */ + rrmStartNextMeasurement(prAdapter, FALSE, ucBssIndex); +} + +void wmmComposeTsmRpt(struct ADAPTER *prAdapter, struct CMD_INFO *prCmdInfo, + uint8_t *pucEventBuf) +{ + struct CMD_GET_TSM_STATISTICS *prTsmStatistic = + (struct CMD_GET_TSM_STATISTICS *)pucEventBuf; + uint8_t ucBssIndex = prTsmStatistic->ucBssIdx; + struct RADIO_MEASUREMENT_REPORT_PARAMS *prRmRep = + aisGetRmReportParam(prAdapter, ucBssIndex); + struct IE_MEASUREMENT_REPORT *prTsmRpt = NULL; + struct RM_TSM_REPORT *prTsmRptField = NULL; + uint16_t u2IeSize = + OFFSET_OF(struct IE_MEASUREMENT_REPORT, aucReportFields) + + sizeof(*prTsmRptField); + struct ACTIVE_RM_TSM_REQ *prCurrentTsmReq = NULL; + struct WMM_INFO *prWMMInfo = + aisGetWMMInfo(prAdapter, ucBssIndex); + struct BSS_INFO *prAisBssInfo = + aisGetAisBssInfo(prAdapter, ucBssIndex); + + if (!prAisBssInfo) { + DBGLOG(WMM, ERROR, "prAisBssInfo is NULL\n"); + return; + } + prCurrentTsmReq = + wmmGetActiveTsmReq(prAdapter, prTsmStatistic->ucTid, + !prTsmStatistic->ucReportReason, FALSE, + ucBssIndex); + /* prCmdInfo is not NULL or report reason is 0 means it is a command + ** reply, so we need to stop the timer + */ + if (prCmdInfo || !prTsmStatistic->ucReportReason) + cnmTimerStopTimer(prAdapter, &prWMMInfo->rTsmTimer); + if (!prCurrentTsmReq) { + DBGLOG(WMM, ERROR, "unexpected Tsm statistic event, tid %d\n", + prTsmStatistic->ucTid); + /* schedule next measurement after a duration based TSM done */ + rrmScheduleNextRm(prAdapter, + ucBssIndex); + return; + } + + /* Put the report IE into report frame */ + if (u2IeSize + prRmRep->u2ReportFrameLen > RM_REPORT_FRAME_MAX_LENGTH) + rrmTxRadioMeasurementReport(prAdapter, ucBssIndex); + + DBGLOG(WMM, INFO, "tid %d, aci %d\n", prCurrentTsmReq->prTsmReq->ucTID, + prCurrentTsmReq->prTsmReq->ucACI); + prTsmRpt = + (struct IE_MEASUREMENT_REPORT *)(prRmRep->pucReportFrameBuff + + prRmRep->u2ReportFrameLen); + prTsmRpt->ucId = ELEM_ID_MEASUREMENT_REPORT; + prTsmRpt->ucToken = prCurrentTsmReq->prTsmReq->ucToken; + prTsmRpt->ucMeasurementType = ELEM_RM_TYPE_TSM_REPORT; + prTsmRpt->ucReportMode = 0; + prTsmRpt->ucLength = u2IeSize - 2; + prTsmRptField = (struct RM_TSM_REPORT *)&prTsmRpt->aucReportFields[0]; + prTsmRptField->u8ActualStartTime = prTsmStatistic->u8StartTime; + prTsmRptField->u2Duration = prCurrentTsmReq->prTsmReq->u2Duration; + COPY_MAC_ADDR(prTsmRptField->aucPeerAddress, + prTsmStatistic->aucPeerAddr); + /* TID filed: bit0~bit3 reserved, bit4~bit7: real tid */ + prTsmRptField->ucTID = (prCurrentTsmReq->prTsmReq->ucTID & 0xf) << 4; + prTsmRptField->ucReason = prTsmStatistic->ucReportReason; + prTsmRptField->u4TransmittedMsduCnt = prTsmStatistic->u4PktTxDoneOK; + prTsmRptField->u4DiscardedMsduCnt = prTsmStatistic->u4PktDiscard; + prTsmRptField->u4FailedMsduCnt = prTsmStatistic->u4PktFail; + prTsmRptField->u4MultiRetryCnt = prTsmStatistic->u4PktRetryTxDoneOK; + prTsmRptField->u4CfPollLostCnt = prTsmStatistic->u4PktQosCfPollLost; + prTsmRptField->u4AvgQueDelay = prTsmStatistic->u4AvgPktQueueDelay; + prTsmRptField->u4AvgDelay = prTsmStatistic->u4AvgPktTxDelay; + prTsmRptField->ucBin0Range = prCurrentTsmReq->prTsmReq->ucB0Range; + kalMemCopy(&prTsmRptField->u4Bin[0], &prTsmStatistic->au4PktCntBin[0], + sizeof(prTsmStatistic->au4PktCntBin)); + prRmRep->u2ReportFrameLen += u2IeSize; + /* For normal TSM, only once measurement */ + if (prCurrentTsmReq->prTsmReq->u2Duration) { + struct RM_TSM_REQ *prTsmReq = NULL; + struct CMD_SET_TSM_STATISTICS_REQUEST rTsmStatistics; + + wmmRemoveTSM(prAdapter, prCurrentTsmReq, FALSE, ucBssIndex); + /* Resume all triggered tsm whose TC is same with this normal + ** tsm + */ + LINK_FOR_EACH_ENTRY(prCurrentTsmReq, &prWMMInfo->rActiveTsmReq, + rLinkEntry, struct ACTIVE_RM_TSM_REQ) + { + prTsmReq = prCurrentTsmReq->prTsmReq; + if (prTsmReq->u2Duration || + prTsmReq->ucACI != prTsmStatistic->ucAcIndex) + continue; + + nicTxChangeDataPortByAc( + prAdapter, + prAisBssInfo->prStaRecOfAP, + prTsmReq->ucACI, TRUE); + kalMemZero(&rTsmStatistics, sizeof(rTsmStatistics)); + rTsmStatistics.ucBssIdx = + ucBssIndex; + rTsmStatistics.ucEnabled = TRUE; + rTsmStatistics.ucAcIndex = prTsmReq->ucACI; + rTsmStatistics.ucTid = prTsmReq->ucTID; + COPY_MAC_ADDR(rTsmStatistics.aucPeerAddr, + prTsmReq->aucPeerAddr); + rTsmStatistics.ucTriggerCondition = + prTsmReq->rTriggerCond.ucCondition; + rTsmStatistics.ucMeasureCount = + prTsmReq->rTriggerCond.ucMeasureCount; + rTsmStatistics.ucTriggerTimeout = + prTsmReq->rTriggerCond.ucTriggerTimeout; + rTsmStatistics.ucAvgErrThreshold = + prTsmReq->rTriggerCond.ucAvgErrThreshold; + rTsmStatistics.ucConsecutiveErrThreshold = + prTsmReq->rTriggerCond.ucConsecutiveErr; + rTsmStatistics.ucDelayThreshold = + prTsmReq->rTriggerCond.ucDelayThreshold; + rTsmStatistics.ucBin0Range = prTsmReq->ucB0Range; + wlanSendSetQueryCmd( + prAdapter, CMD_ID_SET_TSM_STATISTICS_REQUEST, + TRUE, FALSE, FALSE, NULL, NULL, + sizeof(rTsmStatistics), + (uint8_t *)&rTsmStatistics, NULL, 0); + } + /* schedule next measurement after a duration based TSM done */ + rrmScheduleNextRm(prAdapter, ucBssIndex); + } else { + /* Triggered TSM, we should send TSM report to peer if the first + ** report time to now more than 10 second + */ + OS_SYSTIME rCurrent = kalGetTimeTick(); + + if (prWMMInfo->rTriggeredTsmRptTime == 0) + prWMMInfo->rTriggeredTsmRptTime = rCurrent; + else if (CHECK_FOR_TIMEOUT(rCurrent, + prWMMInfo->rTriggeredTsmRptTime, + 10000)) { + rrmTxRadioMeasurementReport(prAdapter, ucBssIndex); + prWMMInfo->rTriggeredTsmRptTime = 0; + } + } +} + +void wmmNotifyDisconnected(struct ADAPTER *prAdapter, + uint8_t ucBssIndex) +{ + struct WMM_INFO *prWmmInfo = + aisGetWMMInfo(prAdapter, ucBssIndex); + uint8_t ucTid = 0; + + for (; ucTid < WMM_TSPEC_ID_NUM; ucTid++) + wmmTspecSteps(prAdapter, ucTid, DISC_DELTS_REQ, NULL, + ucBssIndex); + wmmRemoveAllTsmMeasurement(prAdapter, FALSE, + ucBssIndex); +#if CFG_SUPPORT_SOFT_ACM + kalMemZero(&prWmmInfo->arAcmCtrl[0], + sizeof(prWmmInfo->arAcmCtrl)); +#endif +} + +u_int8_t wmmTsmIsOngoing(struct ADAPTER *prAdapter, + uint8_t ucBssIndex) +{ + struct WMM_INFO *prWmmInfo = + aisGetWMMInfo(prAdapter, ucBssIndex); + + return !LINK_IS_EMPTY(&prWmmInfo->rActiveTsmReq); +} + +/* This function implements TS replacement rule + ** Replace case base on same AC: + ** 1. old: Uni-dir; New: Bi-dir or same dir with old + ** 2. old: Bi-dir; New: Bi-dir or Uni-dir + ** 3. old: two diff Uni-dir; New: Bi-dir + ** for detail, see WMM spec V1.2.0, section 3.5 + */ +static void wmmMayDoTsReplacement(struct ADAPTER *prAdapter, + uint8_t ucNewTid, uint8_t ucBssIndex) +{ + struct WMM_INFO *prWmmInfo = + aisGetWMMInfo(prAdapter, ucBssIndex); + struct TSPEC_INFO *prTspec = &prWmmInfo->arTsInfo[0]; + uint8_t ucTid = 0; + + for (; ucTid < WMM_TSPEC_ID_NUM; ucTid++) { + if (ucTid == ucNewTid) + continue; + if (prTspec[ucTid].eState != QOS_TS_ACTIVE || + prTspec[ucTid].eAC != prTspec[ucNewTid].eAC) + continue; + if (prTspec[ucNewTid].eDir != prTspec[ucTid].eDir && + prTspec[ucNewTid].eDir < BI_DIR_TS && + prTspec[ucTid].eDir < BI_DIR_TS) + continue; + prTspec[ucTid].eAC = ACI_NUM; + prTspec[ucTid].eState = QOS_TS_INACTIVE; + } + wmmDumpActiveTspecs(prAdapter, NULL, 0, ucBssIndex); +} + +uint32_t wmmDumpActiveTspecs(struct ADAPTER *prAdapter, uint8_t *pucBuffer, + uint16_t u2BufferLen, uint8_t ucBssIndex) +{ + uint8_t ucTid = 0; + int32_t i4BytesWritten = 0; + struct WMM_INFO *prWmmInfo = + aisGetWMMInfo(prAdapter, ucBssIndex); + struct TSPEC_INFO *prTspec = &prWmmInfo->arTsInfo[0]; + + for (; ucTid < WMM_TSPEC_ID_NUM; ucTid++, prTspec++) { + if (prTspec->eState != QOS_TS_ACTIVE) + continue; + if (u2BufferLen > 0 && pucBuffer) { + i4BytesWritten += kalSnprintf( + pucBuffer + i4BytesWritten, u2BufferLen, + "Tid %d, AC %d, Dir %d, Uapsd %d, MediumTime %d, PhyRate %u\n", + ucTid, prTspec->eAC, prTspec->eDir, + prTspec->fgUapsd, prTspec->u2MediumTime, + prTspec->u4PhyRate); + if (i4BytesWritten <= 0) + break; + u2BufferLen -= (uint16_t)i4BytesWritten; + } else + DBGLOG(WMM, INFO, + "Tid %d, AC %d, Dir %d, Uapsd %d, MediumTime %d, PhyRate %u\n", + ucTid, prTspec->eAC, prTspec->eDir, + prTspec->fgUapsd, prTspec->u2MediumTime, + prTspec->u4PhyRate); + } + if (u2BufferLen > 0 && pucBuffer) { + struct STA_RECORD *prStaRec = + aisGetStaRecOfAP(prAdapter, ucBssIndex); + + if (prStaRec) { + i4BytesWritten += kalSnprintf( + pucBuffer + i4BytesWritten, u2BufferLen, + "\nACM status for AP "MACSTR + ":\nBE %d; BK %d; VI %d; VO %d\n", + MAC2STR(prStaRec->aucMacAddr), + prStaRec->afgAcmRequired[ACI_BE], + prStaRec->afgAcmRequired[ACI_BK], + prStaRec->afgAcmRequired[ACI_VI], + prStaRec->afgAcmRequired[ACI_VO]); + } else + i4BytesWritten += kalSnprintf( + pucBuffer + i4BytesWritten, u2BufferLen, "%s\n", + "Didn't connect to a AP"); + } + return (uint32_t)i4BytesWritten; +} + +#if CFG_SUPPORT_SOFT_ACM +/* u2PktLen: Ethernet payload length, exclude eth header. + ** Return value: estimated tx time in unit us. + */ +uint32_t wmmCalculatePktUsedTime(struct BSS_INFO *prBssInfo, + struct STA_RECORD *prStaRec, uint16_t u2PktLen) +{ + uint8_t ucSecurityPadding = 0; + int8_t i = 0; + uint32_t u4TxTime = 0; + uint8_t ucFlags = 0; + + ASSERT(prBssInfo); + ASSERT(prStaRec); + switch (prBssInfo->u4RsnSelectedPairwiseCipher) { + case RSN_CIPHER_SUITE_CCMP: + ucSecurityPadding = 16; + break; + case RSN_CIPHER_SUITE_TKIP: + ucSecurityPadding = 20; + break; + case RSN_CIPHER_SUITE_WEP104: + case RSN_CIPHER_SUITE_WEP40: + ucSecurityPadding = 8; + break; + default: + ucSecurityPadding = 0; + break; + } + /* ToDo: 802.11AC? WMM-AC didn't support 802.11AC now */ + if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11N) { + if (prBssInfo->fg40mBwAllowed) { + if (prStaRec->u2HtCapInfo & HT_CAP_INFO_SHORT_GI_40M) + ucFlags |= FLAG_SHORT_GI; + ucFlags |= FLAG_40M_BW; + } else if (prStaRec->u2HtCapInfo & HT_CAP_INFO_SHORT_GI_20M) + ucFlags |= FLAG_SHORT_GI; + + u4TxTime = wmmAcmTxTimeHtCal(ucSecurityPadding, u2PktLen, 7, + ucFlags); + DBGLOG(WMM, INFO, + "MCS 7, Tx %d bytes, SecExtra %d bytes, Flags %02x, Time %u us\n", + u2PktLen, ucSecurityPadding, ucFlags, u4TxTime); + } else { + uint16_t u2DataRate = RATE_54M; + + if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_802_11G) { + u2DataRate = RATE_54M; + for (i = 13; i >= 4; i--) { + if ((prStaRec->u2BSSBasicRateSet & BIT(i)) && + aucDataRate[i] <= u2DataRate) + break; + } + ucFlags |= FLAG_G_MODE; + } else if (prStaRec->ucDesiredPhyTypeSet & + (PHY_TYPE_802_11B | PHY_CONFIG_802_11A)) { + u2DataRate = RATE_11M; + for (i = 3; i >= 0; i--) { + if ((prStaRec->u2BSSBasicRateSet & BIT(i)) && + aucDataRate[i] <= u2DataRate) + break; + } + } + + if (i >= 0) { + if (prBssInfo->fgUseShortPreamble) + ucFlags |= FLAG_S_PREAMBLE; + u4TxTime = wmmAcmTxTimeCal(ucSecurityPadding, u2PktLen, + u2DataRate, aucDataRate[i], ucFlags); + DBGLOG(WMM, INFO, + "DataRate %d, BasicRate %d, Tx %d bytes, SecExtra %d bytes, Flags %02x, Time %u us\n", + u2DataRate, aucDataRate[i], u2PktLen, + ucSecurityPadding, ucFlags, u4TxTime); + } else { + u4TxTime = 0; + DBGLOG(WMM, ERROR, "i is %d !!", i); + } + } + return u4TxTime; +} + +/* 1. u4PktTxTime is 0, this function give a fast check if remain medium time is + *enough to Deq + ** 2. u4PktTxTime is not 0, if remain medium time is greater than u4PktTxTime, + *statistic deq number + ** and remain time. Otherwise, start a timer to schedule next dequeue + *interval + ** return value: + ** TRUE: Can dequeue + ** FALSE: No time to dequeue + */ +u_int8_t wmmAcmCanDequeue(struct ADAPTER *prAdapter, uint8_t ucAc, + uint32_t u4PktTxTime, uint8_t ucBssIndex) +{ + struct SOFT_ACM_CTRL *prAcmCtrl = NULL; + struct WMM_INFO *prWmmInfo = + aisGetWMMInfo(prAdapter, ucBssIndex); + uint32_t u4CurTime = 0; +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + struct timespec64 ts; +#else + struct timespec ts; +#endif + if (!prWmmInfo) { + DBGLOG(WMM, INFO, "prWmmInfo is null %d\n", ucBssIndex); + return FALSE; + } + + prAcmCtrl = &prWmmInfo->arAcmCtrl[ucAc]; + if (!prAcmCtrl->u4AdmittedTime) + return FALSE; +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + ktime_get_boottime_ts64(&ts); +#else + get_monotonic_boottime(&ts); +#endif + u4CurTime = ts.tv_sec; + if (!TIME_BEFORE(u4CurTime, prAcmCtrl->u4IntervalEndSec)) { + u4CurTime++; + DBGLOG(WMM, INFO, + "AC %d, Admitted %u, LastEnd %u, NextEnd %u, LastUsed %u, LastDeq %d\n", + ucAc, prAcmCtrl->u4AdmittedTime, + prAcmCtrl->u4IntervalEndSec, u4CurTime, + prAcmCtrl->u4AdmittedTime - prAcmCtrl->u4RemainTime, + prAcmCtrl->u2DeqNum); + prAcmCtrl->u4IntervalEndSec = u4CurTime; + prAcmCtrl->u4RemainTime = prAcmCtrl->u4AdmittedTime; + prAcmCtrl->u2DeqNum = 0; + /* Stop the next dequeue timer due to we will dequeue right now. + */ + if (timerPendingTimer(&prWmmInfo->rAcmDeqTimer)) + cnmTimerStopTimer(prAdapter, &prWmmInfo->rAcmDeqTimer); + } + if (!u4PktTxTime) { + DBGLOG(WMM, TRACE, "AC %d, can dq %d\n", ucAc, + (prAcmCtrl->u4RemainTime > 0)); + return (prAcmCtrl->u4RemainTime > 0); + } + /* If QM request to dequeue, and have enough medium time, then dequeue + */ + if (prAcmCtrl->u4RemainTime >= u4PktTxTime) { + prAcmCtrl->u2DeqNum++; + prAcmCtrl->u4RemainTime -= u4PktTxTime; + DBGLOG(WMM, INFO, "AC %d, Remain %u, DeqNum %d\n", ucAc, + prAcmCtrl->u4RemainTime, prAcmCtrl->u2DeqNum); + if (prAcmCtrl->u4RemainTime > 0) + return TRUE; + } + /* If not enough medium time to dequeue next packet, should start a + * timer to schedue next dequeue + * We didn't consider the case u4RemainTime is enough to dequeue + * packets except the head of the + * station tx queue, because it is too complex to implement dequeue + * routine. + * We should reset u4RemainTime to 0, used to skip next dequeue request + * if still in this deq interval. + * the dequeue interval is 1 second according to WMM-AC specification. + */ + prAcmCtrl->u4RemainTime = 0; + /* Start a timer to schedule next dequeue interval, since application + * may stop sending data to driver, + * but driver still pending some data to dequeue + */ + if (!timerPendingTimer(&prWmmInfo->rAcmDeqTimer)) { + uint32_t u4EndMsec = prAcmCtrl->u4IntervalEndSec * 1000; +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + ktime_get_boottime_ts64(&ts); +#else + get_monotonic_boottime(&ts); +#endif + u4CurTime = ts.tv_sec * MSEC_PER_SEC; + u4CurTime += ts.tv_nsec / NSEC_PER_MSEC; + /* It is impossible that u4EndMsec is less than u4CurTime */ + u4EndMsec = u4EndMsec - u4CurTime + + 20; /* the timeout duration at least 2 jiffies */ + cnmTimerStartTimer(prAdapter, &prWmmInfo->rAcmDeqTimer, + u4EndMsec); + DBGLOG(WMM, INFO, + "AC %d, will start next deq interval after %u ms\n", + ucAc, u4EndMsec); + } + return FALSE; +} + +static uint16_t wmmAcmTxTimePLCPCal(uint16_t u2Length, uint16_t u2Rate, + uint8_t FlgIsGmode) +{ + uint16_t u2PLCP; + + if (FlgIsGmode) { + u2Rate <<= 1; + /* EX1: BodyLen = 30B and rate = 54Mbps, + * 1. additional 22 bit in PSDU + * PLCP = 30*8 + 22 = 262 bits + * 2. round_up{X / 4} * 4 means OFDM symbol is in unit of 4 + * usec + * PLCP = (262/54) = 4.8xxx us + * 4.8xxx / 4 = 1.2xxx + * 3. PLCP = round up(1.2xxx) * 4 = 2 * 4 = 8 us + * EX2: BodyLen = 14B and rate = 6Mbps, + * 1. additional 22 bit in PSDU + * PLCP = 14*8 + 22 = 134 bits + * 2. round_up{X / 4} * 4 means OFDM symbol is in unit of 4 + * usec + * PLCP = (134/6) = 22.3xxx us + * 22.3xxx / 4 = 5.583xxx + * 3. PLCP = round up(5.583xxx) * 4 = 6 * 4 = 24 us + */ + u2PLCP = (u2Length << 3) + 22; /* need to add 22 bits in 11g */ + u2PLCP = (u2PLCP % u2Rate) ? (u2PLCP / u2Rate) + 1 + : (u2PLCP / u2Rate); + return u2PLCP << 2; + } + + /* ex: BodyLen = 30B and rate = 11Mbps, PLCP = 30 * 8 / 11 = 22us */ + return (u2Length << 4) / u2Rate; +} + +/* For G mode, no long or short preamble time, only long (20us) or short slot + ** time (9us). + */ +static uint16_t wmmAcmTxTimeCal(uint16_t u2SecExtra, uint16_t u2EthBodyLen, + uint16_t u2DataRate, uint16_t u2BasicRate, + uint8_t ucFlags) +{ + uint16_t u2TxTime = 0; + uint16_t u2PreambleTime = 0; + u_int8_t fgIsGMode = !!(ucFlags & FLAG_G_MODE); + + u2PreambleTime = + LMR_PREAMBL_TIME(fgIsGMode, !!(ucFlags & FLAG_S_PREAMBLE)); + + /* CTS-self */ + if (ucFlags & FLAG_CTS_SELF) { + u2TxTime = u2PreambleTime + TIME_SIFSG; + u2TxTime += wmmAcmTxTimePLCPCal(FRM_LENGTH_ACK, u2BasicRate, + fgIsGMode); + } else if (ucFlags & FLAG_RTS_CTS) { /* CTS + RTS */ + u2TxTime = 2 * u2PreambleTime + + (fgIsGMode ? TIME_SIFSGx2 : TIME_SIFSx2); + u2TxTime += wmmAcmTxTimePLCPCal(FRM_LENGTH_RTS + FRM_LENGTH_ACK, + u2BasicRate, fgIsGMode); + } + /* Data Pkt Preamble Time + RTS/CTS time + 802.11 QoS hdr + LLC header + + ** Ethernet Payload + sec extra + FCS + */ + u2TxTime += u2PreambleTime + + wmmAcmTxTimePLCPCal(WLAN_MAC_HEADER_QOS_LEN + 8 + + u2EthBodyLen + u2SecExtra + 4, + u2DataRate, fgIsGMode); + /* Ack frame for data packet. Preamble + Ack + SIFS */ + u2TxTime += + wmmAcmTxTimePLCPCal(FRM_LENGTH_ACK, u2BasicRate, fgIsGMode) + + (fgIsGMode ? TIME_SIFSG : TIME_SIFS) + u2PreambleTime; + return u2TxTime; +} + +/* Reference to Draft802.11n_D3.07, Transmission Time = + ** 1. Mix mode, short GI + ** TXTIME = T_LEG_PREAMBLE + T_L_SIG + T_HT_PREAMBLE + T_HT_SIG + + ** T_SYM * Ceiling{T_SYMS * N_SYM / T_SYM} + ** 2. Mix mode, regular GI + ** TXTIME = T_LEG_PREAMBLE + T_L_SIG + T_HT_PREAMBLE + T_HT_SIG + + ** T_SYM * N_SYM + ** 3. GreenField mode, short GI + ** TXTIME = T_GF_HT_PREAMBLE + T_HT_SIG + T_SYMS * N_SYM + ** 4. GreenField mode, regular GI + ** TXTIME = T_GF_HT_PREAMBLE + T_HT_SIG + T_SYM * N_SYM + ** Where + ** (1) T_LEG_PREAMBLE = T_L_STF + T_L_LTF = 8 + 8 = 16 us + ** (2) T_L_SIG = 4 us + ** (3) T_HT_PREAMBLE = T_HT_STF + T_HT_LTF1 + (N_LTF - 1) * T_HT_LTFS + ** = 4 + 4 + ((N_DLTF + N_ELTF) - 1) * 4 + ** EX: Nss = 2, N_DLTF = 2, Ness = 0, N_ELTF = 0, T_HT_PREAMBLE = 12 us + ** (4) T_HT_SIG = 8 us + ** (5) T_SYM = 4 us + ** (6) T_SYMS = 3.6 us + ** (7) N_SYM = mSTBC * Ceil((8*len+16+6*N_ES)/(mSTBC * + *N_DBPS)) + ** (8) T_GF_HT_PREAMBLE= T_HT_GF_STF + T_HT_LTF1 + (N_LTF - 1) * T_HT_LTFS + ** = 8 + 4 + ((N_DLTF + N_ELTF) - 1) * 4 + */ +static uint16_t wmmAcmTxTimeHtPLCPCal(uint16_t u2Length, uint8_t ucMcsId, + uint8_t ucNess, uint8_t ucFlags) +{ + uint32_t T_LEG_PREAMBLE, T_L_SIG, T_HT_PREAMBLE, T_HT_SIG; + uint32_t T_SYM, T_SYMS, N_SYM; + uint32_t T_GF_HT_PREAMBLE; + uint32_t TxTime; + uint32_t N_DLTF[5] = {1, 1, 2, 4, 4}; + uint32_t N_ELTF[4] = {0, 1, 2, 4}; + uint32_t N_SYM_1_NUM; /* numerator of N_SYM */ + uint8_t ucBwId = (ucFlags & FLAG_40M_BW) ? 1 : 0; + uint8_t ucNss = 0; + static const uint16_t gAcmRateNdbps[2][32] = { + /* MCS0 ~ MCS31 */ + /* 20MHz */ + {26, 52, 78, 104, 156, 208, 234, 260, 52, 104, 156, + 208, 312, 416, 468, 520, 78, 156, 234, 312, 468, 624, + 702, 780, 104, 208, 312, 416, 624, 832, 936, 1040}, + + /* MCS0 ~ MCS31 */ + /* 40MHz */ + {54, 108, 162, 216, 324, 432, 486, 540, 108, 216, 324, + 432, 648, 864, 972, 1080, 162, 324, 486, 648, 972, 1296, + 1458, 1620, 216, 432, 648, 864, 1296, 1728, 1944, 2160}, + }; + + /* init */ + T_LEG_PREAMBLE = 16; + T_L_SIG = 4; + T_HT_SIG = 8; + T_SYM = 4; + T_SYMS = 36; /* unit: 0.1us */ + TxTime = 0; + + if (ucMcsId < 8) + ucNss = 1; + else if (ucMcsId < 16) + ucNss = 2; + else if (ucMcsId < 24) + ucNss = 3; + else if (ucMcsId < 32) + ucNss = 4; + else { + ucMcsId = 31; + ucNss = 1; + } + /* calculate N_SYM */ + /* ex: 1538B, 1st MPDU of AMPDU, (1538 * 8 + 22)/1080 + 1 = 12 */ + /* STBC is not used, BCC is used */ + N_SYM = ((u2Length << 3) + 16 + 6) / gAcmRateNdbps[ucBwId][ucMcsId] + 1; + + /* calculate transmission time */ + if (!(ucFlags & FLAG_GF_HT)) { + /* ex: 1538B, 1st MPDU of AMPDU, 4 + 4 + 2*4 = 16us */ + T_HT_PREAMBLE = + 4 + 4 + ((N_DLTF[ucNss] + N_ELTF[ucNess] - 1) << 2); + + /* ex: 1538B, 1st MPDU of AMPDU, 16 + 4 + 16 + 8 = 44us */ + if (!(ucFlags & FLAG_ONLY_DATA)) + TxTime = T_LEG_PREAMBLE + T_L_SIG + T_HT_PREAMBLE + + T_HT_SIG; + + /* End of if */ + + /* ex: 1538B, 1st MPDU of AMPDU, 4 * 12 = 48us */ + if (!(ucFlags & FLAG_SHORT_GI)) + TxTime += T_SYM * N_SYM; + else { + N_SYM_1_NUM = (T_SYMS * N_SYM) / (T_SYM * 10); + + if ((T_SYMS * N_SYM) % (T_SYM * 10)) + N_SYM_1_NUM++; + + TxTime += T_SYM * N_SYM_1_NUM; + } /* End of if */ + } else { + T_GF_HT_PREAMBLE = + 8 + 4 + ((N_DLTF[ucNss] + N_ELTF[ucNess] - 1) << 2); + + if (!(ucFlags & FLAG_ONLY_DATA)) + TxTime = T_GF_HT_PREAMBLE + T_HT_SIG; + + TxTime += (ucFlags & FLAG_SHORT_GI) ? ((T_SYMS * N_SYM) / 10) + : (T_SYM * N_SYM); + } /* End of if */ + + return TxTime; +} /* End of ACM_TX_TimePlcpCalHT */ + +static uint16_t wmmAcmTxTimeHtCal(uint16_t u2SecExtra, uint16_t u2EthBodyLen, + uint8_t ucMcsId, uint8_t ucFlags) +{ + uint16_t u2PreambleTime = 0; + uint16_t u2TxTime = 0; + + u2PreambleTime = LMR_PREAMBL_TIME(TRUE, !!(ucFlags & FLAG_S_PREAMBLE)); + if (ucFlags & FLAG_RTS_CTS) { + /* add RTS/CTS 24Mbps time */ + u2TxTime += 2 * u2PreambleTime + TIME_SIFSGx2; + u2TxTime += wmmAcmTxTimePLCPCal(FRM_LENGTH_RTS + FRM_LENGTH_ACK, + RATE_24M, TRUE); + } + /* SIFS + ACK, always use G mode to calculate preamble */ + + u2TxTime += TIME_SIFSG + u2PreambleTime; + /* always use block ack to calculate ack time */ + u2TxTime += wmmAcmTxTimePLCPCal(FRM_LENGTH_BLOCK_ACK, RATE_24M, TRUE); + + /* Data Pkt Preamble Time + RTS/CTS time + 802.11 QoS hdr + LLC header + + ** Ethernet Payload + sec extra + FCS + ** Nss always set to 1 due to only + */ + u2TxTime += wmmAcmTxTimeHtPLCPCal(WLAN_MAC_HEADER_QOS_LEN + 8 + + u2EthBodyLen + u2SecExtra + 4, + ucMcsId, 0, ucFlags); + + return u2TxTime; +} /* End of ACM_TX_TimeCalHT */ + +static void wmmAcmDequeueTimeOut(IN struct ADAPTER *prAdapter, + unsigned long ulParamPtr) +{ + DBGLOG(WMM, INFO, "Timeout, trigger to do ACM dequeue\n"); + kalSetEvent(prAdapter->prGlueInfo); +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/wnm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/wnm.c new file mode 100644 index 0000000000000..597a3fe1c2ce1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/mgmt/wnm.c @@ -0,0 +1,651 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + +/******************************************************************************* + * C O M P I L E 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 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 + ******************************************************************************* + */ +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT +static uint8_t ucTimingMeasToken; +#endif +static uint8_t ucBtmMgtToken = 1; + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT +static uint32_t +wnmRunEventTimgingMeasTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +static void wnmComposeTimingMeasFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler); + +static void wnmTimingMeasRequest(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); +#endif +/******************************************************************************* + * 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 struct ADAPTER *prAdapter, IN struct SW_RFB *prSwRfb) +{ + struct WLAN_ACTION_FRAME *prRxFrame; + + prRxFrame = (struct WLAN_ACTION_FRAME *)prSwRfb->pvHeader; + + DBGLOG(WNM, TRACE, "WNM action frame: %d from " MACSTR "\n", + prRxFrame->ucAction, MAC2STR(prRxFrame->aucSrcAddr)); + + switch (prRxFrame->ucAction) { +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT + case ACTION_WNM_TIMING_MEASUREMENT_REQUEST: + wnmTimingMeasRequest(prAdapter, prSwRfb); + break; +#endif +#if CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT + case ACTION_WNM_BSS_TRANSITION_MANAGEMENT_REQ: +#if CFG_TC3_FEATURE + /* Ignore BTM REQ for TC3 */ + DBGLOG(RX, TRACE, "WNM: BTM request is ignored"); + break; +#endif +#endif + case ACTION_WNM_NOTIFICATION_REQUEST: + default: + DBGLOG(RX, INFO, + "WNM: action frame %d, try to send to supplicant\n", + prRxFrame->ucAction); + aisFuncValidateRxActionFrame(prAdapter, prSwRfb); + break; + } +} + +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT +/*----------------------------------------------------------------------------*/ +/*! + * + * \brief This routine is called to report timing measurement data. + * + */ +/*----------------------------------------------------------------------------*/ +void wnmReportTimingMeas(IN struct ADAPTER *prAdapter, IN uint8_t ucStaRecIndex, + IN uint32_t u4ToD, IN uint32_t u4ToA) +{ + struct STA_RECORD *prStaRec; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIndex); + + if ((!prStaRec) || (!prStaRec->fgIsInUse)) + return; + + DBGLOG(WNM, TRACE, "WNM: 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 + */ +/*----------------------------------------------------------------------------*/ +static uint32_t +wnmRunEventTimgingMeasTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + struct STA_RECORD *prStaRec; + + DBGLOG(WNM, LOUD, "WNM: 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, + "WNM: 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) + */ +/*----------------------------------------------------------------------------*/ +static void wnmComposeTimingMeasFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + struct MSDU_INFO *prMsduInfo; + struct BSS_INFO *prBssInfo; + struct ACTION_UNPROTECTED_WNM_TIMING_MEAS_FRAME *prTxFrame; + uint16_t u2PayloadLen; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc( + prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + prTxFrame = (struct ACTION_UNPROTECTED_WNM_TIMING_MEAS_FRAME + *)((uint32_t)(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 */ + TX_SET_MMPDU(prAdapter, prMsduInfo, prStaRec->ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, pfTxDoneHandler, + MSDU_RATE_MODE_AUTO); + + DBGLOG(WNM, TRACE, + "WNM: 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 + */ +/*----------------------------------------------------------------------------*/ +static void wnmTimingMeasRequest(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct ACTION_WNM_TIMING_MEAS_REQ_FRAME *prRxFrame = NULL; + struct STA_RECORD *prStaRec; + + prRxFrame = + (struct ACTION_WNM_TIMING_MEAS_REQ_FRAME *)prSwRfb->pvHeader; + if (!prRxFrame) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if ((!prStaRec) || (!prStaRec->fgIsInUse)) + return; + + DBGLOG(WNM, TRACE, + "WNM: 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(struct ADAPTER *prAdapter, uint8_t ucStaRecIndex) +{ + struct STA_RECORD *prStaRec; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIndex); + if ((!prStaRec) || (!prStaRec->fgIsInUse)) + return; + DBGLOG(WNM, INFO, + "WNM: 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 */ + +uint8_t wnmGetBtmToken(void) +{ + return ucBtmMgtToken++; +} + +static uint32_t wnmBTMQueryTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + DBGLOG(WNM, INFO, "BTM: Query Frame Tx Done, Status %d\n", + rTxDoneStatus); + return WLAN_STATUS_SUCCESS; +} + +static uint32_t wnmBTMResponseTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + uint8_t ucBssIndex = 0; + struct BSS_TRANSITION_MGT_PARAM_T *prBtm; + struct AIS_FSM_INFO *prAisFsmInfo; + + ucBssIndex = + prMsduInfo->ucBssIndex; + prBtm = + aisGetBTMParam(prAdapter, ucBssIndex); + prAisFsmInfo = + aisGetAisFsmInfo(prAdapter, ucBssIndex); + + DBGLOG(WNM, INFO, "BTM: Response Frame Tx Done Status %d\n", + rTxDoneStatus); + if (prBtm->fgPendingResponse && + prAisFsmInfo->eCurrentState == AIS_STATE_SEARCH) { + prBtm->fgPendingResponse = FALSE; + aisFsmSteps(prAdapter, AIS_STATE_REQ_CHANNEL_JOIN, + ucBssIndex); + } + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will compose the BTM Response frame. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] prStaRec Pointer to the STA_RECORD_T. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void wnmSendBTMResponseFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + struct MSDU_INFO *prMsduInfo = NULL; + struct BSS_INFO *prBssInfo = NULL; + struct ACTION_BTM_RSP_FRAME *prTxFrame = NULL; + uint16_t u2PayloadLen = 0; + struct BSS_TRANSITION_MGT_PARAM_T *prBtmParam; + uint8_t *pucOptInfo = NULL; + + if (!prStaRec) { + DBGLOG(WNM, INFO, "BTM: No station record found\n"); + return; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + prBtmParam = + aisGetBTMParam(prAdapter, prStaRec->ucBssIndex); + + /* 1 Allocate MSDU Info */ + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc( + prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + if (!prMsduInfo) + return; + prTxFrame = (struct ACTION_BTM_RSP_FRAME + *)((unsigned long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + + /* 2 Compose The Mac Header. */ + 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_WNM_ACTION; + prTxFrame->ucAction = ACTION_WNM_BSS_TRANSITION_MANAGEMENT_RSP; + + /* 3 Compose the frame body's frame. */ + prTxFrame->ucDialogToken = prBtmParam->ucDialogToken; + prBtmParam->ucDialogToken = 0; /* reset dialog token */ + prTxFrame->ucStatusCode = prBtmParam->ucStatusCode; + prTxFrame->ucBssTermDelay = prBtmParam->ucTermDelay; + pucOptInfo = &prTxFrame->aucOptInfo[0]; + if (prBtmParam->ucStatusCode == BSS_TRANSITION_MGT_STATUS_ACCEPT) { + COPY_MAC_ADDR(pucOptInfo, prBtmParam->aucTargetBssid); + pucOptInfo += MAC_ADDR_LEN; + u2PayloadLen += MAC_ADDR_LEN; + } + if (prBtmParam->u2OurNeighborBssLen > 0) { + kalMemCopy(pucOptInfo, prBtmParam->pucOurNeighborBss, + prBtmParam->u2OurNeighborBssLen); + kalMemFree(prBtmParam->pucOurNeighborBss, VIR_MEM_TYPE, + prBtmParam->u2OurNeighborBssLen); + prBtmParam->u2OurNeighborBssLen = 0; + u2PayloadLen += prBtmParam->u2OurNeighborBssLen; + } + + /* 4 Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, prMsduInfo, prStaRec->ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_MGMT_HEADER_LEN, + OFFSET_OF(struct ACTION_BTM_RSP_FRAME, aucOptInfo) + + u2PayloadLen, + wnmBTMResponseTxDone, MSDU_RATE_MODE_AUTO); + + /* 5 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); +} /* end of wnmComposeBTMResponseFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will compose the BTM Query frame. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] prStaRec Pointer to the STA_RECORD_T. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void wnmSendBTMQueryFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + struct MSDU_INFO *prMsduInfo = NULL; + struct BSS_INFO *prBssInfo = NULL; + struct ACTION_BTM_QUERY_FRAME *prTxFrame = NULL; + struct BSS_TRANSITION_MGT_PARAM_T *prBtmParam; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + prBtmParam = + aisGetBTMParam(prAdapter, prStaRec->ucBssIndex); + + /* 1 Allocate MSDU Info */ + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc( + prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + if (!prMsduInfo) + return; + prTxFrame = (struct ACTION_BTM_QUERY_FRAME + *)((unsigned long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + + /* 2 Compose The Mac Header. */ + 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_WNM_ACTION; + prTxFrame->ucAction = ACTION_WNM_BSS_TRANSITION_MANAGEMENT_QUERY; + + /* 3 Compose the frame body's frame. */ + prTxFrame->ucDialogToken = prBtmParam->ucDialogToken; + prTxFrame->ucQueryReason = prBtmParam->ucQueryReason; + if (prBtmParam->u2OurNeighborBssLen > 0) { + kalMemCopy(prTxFrame->pucNeighborBss, + prBtmParam->pucOurNeighborBss, + prBtmParam->u2OurNeighborBssLen); + kalMemFree(prBtmParam->pucOurNeighborBss, VIR_MEM_TYPE, + prBtmParam->u2OurNeighborBssLen); + prBtmParam->u2OurNeighborBssLen = 0; + } + + /* 4 Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, prMsduInfo, prStaRec->ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + 4 + + prBtmParam->u2OurNeighborBssLen, + wnmBTMQueryTxDone, MSDU_RATE_MODE_AUTO); + + /* 5 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); +} /* end of wnmComposeBTMQueryFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! + * + * \brief This routine is called to process the 802.11v BTM request. + * + * + * \note + * Handle Rx mgmt request + */ +/*----------------------------------------------------------------------------*/ +void wnmRecvBTMRequest(IN struct ADAPTER *prAdapter, IN struct SW_RFB *prSwRfb) +{ + struct ACTION_BTM_REQ_FRAME *prRxFrame = NULL; + struct BSS_TRANSITION_MGT_PARAM_T *prBtmParam; + uint8_t *pucOptInfo = NULL; + uint8_t ucRequestMode = 0; + uint16_t u2TmpLen = 0; + struct MSG_AIS_BSS_TRANSITION_T *prMsg = NULL; + enum WNM_AIS_BSS_TRANSITION eTransType = BSS_TRANSITION_NO_MORE_ACTION; + uint8_t ucBssIndex = secGetBssIdxByRfb(prAdapter, prSwRfb); + + prRxFrame = (struct ACTION_BTM_REQ_FRAME *) prSwRfb->pvHeader; + if (!prRxFrame) + return; + if (prSwRfb->u2PacketLen < + OFFSET_OF(struct ACTION_BTM_REQ_FRAME, aucOptInfo)) { + DBGLOG(WNM, WARN, + "BTM: Request frame length is less than a standard BTM frame\n"); + return; + } + prMsg = (struct MSG_AIS_BSS_TRANSITION_T *)cnmMemAlloc( + prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_AIS_BSS_TRANSITION_T)); + if (!prMsg) { + DBGLOG(WNM, WARN, "BTM: Msg Hdr is NULL\n"); + return; + } + + prBtmParam = + aisGetBTMParam(prAdapter, ucBssIndex); + kalMemZero(prMsg, sizeof(*prMsg)); + prBtmParam->ucRequestMode = prRxFrame->ucRequestMode; + prMsg->ucToken = prRxFrame->ucDialogToken; + prBtmParam->u2DisassocTimer = prRxFrame->u2DisassocTimer; + prBtmParam->ucDialogToken = prRxFrame->ucDialogToken; + pucOptInfo = &prRxFrame->aucOptInfo[0]; + ucRequestMode = prBtmParam->ucRequestMode; + u2TmpLen = OFFSET_OF(struct ACTION_BTM_REQ_FRAME, aucOptInfo); + if (ucRequestMode & BTM_REQ_MODE_DISC_IMM) + eTransType = BSS_TRANSITION_REQ_ROAMING; + if (ucRequestMode & BTM_REQ_MODE_BSS_TERM_INCLUDE) { + struct SUB_IE_BSS_TERM_DURATION *prBssTermDuration = + (struct SUB_IE_BSS_TERM_DURATION *)pucOptInfo; + + prBtmParam->u2TermDuration = prBssTermDuration->u2Duration; + kalMemCopy(prBtmParam->aucTermTsf, + prBssTermDuration->aucTermTsf, 8); + pucOptInfo += sizeof(*prBssTermDuration); + u2TmpLen += sizeof(*prBssTermDuration); + eTransType = BSS_TRANSITION_REQ_ROAMING; + } + if (ucRequestMode & BTM_REQ_MODE_ESS_DISC_IMM) { + kalMemCopy(prBtmParam->aucSessionURL, &pucOptInfo[1], + pucOptInfo[0]); + prBtmParam->ucSessionURLLen = pucOptInfo[0]; + u2TmpLen += pucOptInfo[0]; + pucOptInfo += pucOptInfo[0] + 1; + eTransType = BSS_TRANSITION_DISASSOC; + } + if (ucRequestMode & BTM_REQ_MODE_CAND_INCLUDED_BIT) { + if (!(ucRequestMode & BTM_REQ_MODE_ESS_DISC_IMM)) + eTransType = BSS_TRANSITION_REQ_ROAMING; + if (prSwRfb->u2PacketLen > u2TmpLen) { + prMsg->u2CandListLen = prSwRfb->u2PacketLen - u2TmpLen; + prMsg->pucCandList = pucOptInfo; + prMsg->ucValidityInterval = + prRxFrame->ucValidityInterval; + } else + DBGLOG(WNM, WARN, + "BTM: Candidate Include bit is set, but no candidate list\n"); + } + + DBGLOG(WNM, INFO, + "BTM: Req %d, VInt %d, DiscTimer %d, Token %d, TransType %d\n", + prBtmParam->ucRequestMode, prRxFrame->ucValidityInterval, + prBtmParam->u2DisassocTimer, prMsg->ucToken, eTransType); + + prMsg->eTransitionType = eTransType; + prMsg->rMsgHdr.eMsgId = MID_WNM_AIS_BSS_TRANSITION; + prMsg->ucBssIndex = ucBssIndex; + /* if BTM Request is dest for broadcast, don't send BTM Response */ + if (kalMemCmp(prRxFrame->aucDestAddr, "\xff\xff\xff\xff\xff\xff", + MAC_ADDR_LEN)) + prMsg->fgNeedResponse = TRUE; + else + prMsg->fgNeedResponse = FALSE; + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *)prMsg, + MSG_SEND_METHOD_BUF); +} From b8afe75858c9db5def6ddeba36d8cad9f9e823bf Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 22:09:17 +0800 Subject: [PATCH 20/32] Update Kconfig --- drivers/misc/mediatek/connectivity/Kconfig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/misc/mediatek/connectivity/Kconfig b/drivers/misc/mediatek/connectivity/Kconfig index 4f1b307eb1f6c..26389849c25df 100644 --- a/drivers/misc/mediatek/connectivity/Kconfig +++ b/drivers/misc/mediatek/connectivity/Kconfig @@ -440,3 +440,10 @@ config MTK_CONNSYS_DEDICATED_LOG_PATH (by EMI or other specific path) 2. The scope may include (but not limited) Wi-Fi firmware log, BT firmware log, GPS firmware log etc. + +config WLAN_DRV_BUILD_IN + bool "Build Wlan module in kernel" + help + This will build the wlan driver and the corresponding componenets + into the kernel. + If unsure say n From 8fcf8576e92f77c0d7edab4ee9af6d9c0bb48a24 Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 22:10:55 +0800 Subject: [PATCH 21/32] Update Makefile --- drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/Makefile b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/Makefile index 4aed1179ec859..53b6d8883e766 100644 --- a/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/Makefile +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/connac2/Makefile @@ -84,7 +84,7 @@ endif # Objects List # --------------------------------------------------- MODULE_NAME := bt_drv -obj-m += $(MODULE_NAME).o +obj-y += $(MODULE_NAME).o #PLAT_DIR := plat/$(MTK_PLATFORM) From ca7132334f8d2a92aa4f875c81c4d17498f36c70 Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 22:11:05 +0800 Subject: [PATCH 22/32] Add files via upload --- .../wlan/core/gen4m/os/linux/gl_ate_agent.c | 2688 +++ .../wlan/core/gen4m/os/linux/gl_bow.c | 1175 ++ .../wlan/core/gen4m/os/linux/gl_cfg80211.c | 7636 ++++++++ .../wlan/core/gen4m/os/linux/gl_hook_api.c | 4696 +++++ .../wlan/core/gen4m/os/linux/gl_init.c | 5643 ++++++ .../wlan/core/gen4m/os/linux/gl_kal.c | 8943 ++++++++++ .../wlan/core/gen4m/os/linux/gl_p2p.c | 2252 +++ .../core/gen4m/os/linux/gl_p2p_cfg80211.c | 4262 +++++ .../wlan/core/gen4m/os/linux/gl_p2p_init.c | 291 + .../wlan/core/gen4m/os/linux/gl_p2p_kal.c | 2343 +++ .../wlan/core/gen4m/os/linux/gl_proc.c | 1836 ++ .../wlan/core/gen4m/os/linux/gl_qa_agent.c | 9655 +++++++++++ .../wlan/core/gen4m/os/linux/gl_rst.c | 1129 ++ .../wlan/core/gen4m/os/linux/gl_sec.o.new | Bin 0 -> 19504 bytes .../wlan/core/gen4m/os/linux/gl_sys.c | 568 + .../wlan/core/gen4m/os/linux/gl_vendor.c | 1981 +++ .../wlan/core/gen4m/os/linux/gl_wext.c | 5002 ++++++ .../wlan/core/gen4m/os/linux/gl_wext_priv.c | 14361 ++++++++++++++++ .../wlan/core/gen4m/os/linux/hif/axi/axi.c | 1590 ++ .../core/gen4m/os/linux/hif/axi/include/hif.h | 409 + .../core/gen4m/os/linux/hif/common/dbg_pdma.c | 913 + .../core/gen4m/os/linux/hif/common/hal_pdma.c | 3089 ++++ .../os/linux/hif/common/include/hif_pdma.h | 504 + .../core/gen4m/os/linux/hif/common/kal_pdma.c | 1009 ++ .../wlan/core/gen4m/os/linux/hif/ehpi/arm.c | 536 + .../core/gen4m/os/linux/hif/ehpi/colibri.c | 536 + .../wlan/core/gen4m/os/linux/hif/ehpi/ehpi.c | 414 + .../gen4m/os/linux/hif/ehpi/include/colibri.h | 190 + .../gen4m/os/linux/hif/ehpi/include/hif.h | 142 + .../gen4m/os/linux/hif/pcie/include/hif.h | 329 + .../wlan/core/gen4m/os/linux/hif/pcie/pcie.c | 901 + .../wlan/core/gen4m/os/linux/hif/sdio/arm.c | 62 + .../core/gen4m/os/linux/hif/sdio/hal_api.c | 2940 ++++ .../gen4m/os/linux/hif/sdio/include/hif.h | 403 + .../os/linux/hif/sdio/include/hif_sdio.h | 267 + .../os/linux/hif/sdio/include/mtk_porting.h | 89 + .../hif/sdio/include/test_driver_sdio_ops.h | 48 + .../wlan/core/gen4m/os/linux/hif/sdio/sdio.c | 1730 ++ .../os/linux/hif/sdio/sdio_test_driver_core.c | 448 + .../os/linux/hif/sdio/sdio_test_driver_ops.c | 194 + .../wlan/core/gen4m/os/linux/hif/sdio/x86.c | 62 + .../core/gen4m/os/linux/hif/usb/hal_api.c | 1945 +++ .../os/linux/hif/usb/include/cust_usb_id.h | 116 + .../core/gen4m/os/linux/hif/usb/include/hif.h | 461 + .../gen4m/os/linux/hif/usb/include/hif_usb.h | 131 + .../wlan/core/gen4m/os/linux/hif/usb/usb.c | 1658 ++ .../gen4m/os/linux/include/gl_ate_agent.h | 300 + .../core/gen4m/os/linux/include/gl_cfg80211.h | 779 + .../core/gen4m/os/linux/include/gl_hook_api.h | 353 + .../wlan/core/gen4m/os/linux/include/gl_kal.h | 1846 ++ .../wlan/core/gen4m/os/linux/include/gl_os.h | 1435 ++ .../gen4m/os/linux/include/gl_p2p_ioctl.h | 852 + .../core/gen4m/os/linux/include/gl_p2p_kal.h | 388 + .../core/gen4m/os/linux/include/gl_p2p_os.h | 387 + .../core/gen4m/os/linux/include/gl_qa_agent.h | 438 + .../wlan/core/gen4m/os/linux/include/gl_rst.h | 313 + .../wlan/core/gen4m/os/linux/include/gl_sec.h | 79 + .../core/gen4m/os/linux/include/gl_typedef.h | 322 + .../core/gen4m/os/linux/include/gl_vendor.h | 797 + .../core/gen4m/os/linux/include/gl_wext.h | 390 + .../gen4m/os/linux/include/gl_wext_priv.h | 414 + .../gen4m/os/linux/plat/mt6885/plat_priv.c | 178 + .../gen4m/os/linux/plat/mt6893/plat_priv.c | 183 + .../wlan/core/gen4m/os/linux/platform.c | 679 + .../wlan/core/gen4m/os/none/gl_ate_agent.c | 118 + .../wlan/core/gen4m/os/none/gl_dependent.c | 369 + .../wlan/core/gen4m/os/none/gl_init.c | 125 + .../wlan/core/gen4m/os/none/gl_kal.c | 130 + .../wlan/core/gen4m/os/none/gl_qa_agent.c | 156 + .../core/gen4m/os/none/hif/none/include/hif.h | 264 + .../wlan/core/gen4m/os/none/hif/none/none.c | 333 + .../core/gen4m/os/none/include/gl_ate_agent.h | 288 + .../core/gen4m/os/none/include/gl_cfg80211.h | 762 + .../core/gen4m/os/none/include/gl_dependent.h | 1100 ++ .../wlan/core/gen4m/os/none/include/gl_kal.h | 1978 +++ .../wlan/core/gen4m/os/none/include/gl_os.h | 1277 ++ .../core/gen4m/os/none/include/gl_p2p_ioctl.h | 857 + .../core/gen4m/os/none/include/gl_p2p_kal.h | 479 + .../core/gen4m/os/none/include/gl_p2p_os.h | 386 + .../core/gen4m/os/none/include/gl_qa_agent.h | 349 + .../wlan/core/gen4m/os/none/include/gl_rst.h | 218 + .../core/gen4m/os/none/include/gl_typedef.h | 310 + .../core/gen4m/os/none/include/gl_vendor.h | 714 + .../core/gen4m/os/none/include/gl_wext_priv.h | 402 + .../connectivity/wlan/core/gen4m/os/version.h | 138 + 85 files changed, 116463 insertions(+) create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_ate_agent.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_bow.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_cfg80211.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_hook_api.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_init.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_kal.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_p2p.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_p2p_cfg80211.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_p2p_init.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_p2p_kal.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_proc.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_qa_agent.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_rst.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_sec.o.new create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_sys.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_vendor.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_wext.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_wext_priv.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/axi/axi.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/axi/include/hif.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/common/dbg_pdma.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/common/hal_pdma.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/common/include/hif_pdma.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/common/kal_pdma.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/ehpi/arm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/ehpi/colibri.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/ehpi/ehpi.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/ehpi/include/colibri.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/ehpi/include/hif.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/pcie/include/hif.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/pcie/pcie.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/arm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/hal_api.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/include/hif.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/include/hif_sdio.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/include/mtk_porting.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/include/test_driver_sdio_ops.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/sdio.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/sdio_test_driver_core.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/sdio_test_driver_ops.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/x86.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/usb/hal_api.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/usb/include/cust_usb_id.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/usb/include/hif.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/usb/include/hif_usb.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/usb/usb.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_ate_agent.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_cfg80211.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_hook_api.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_kal.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_os.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_p2p_ioctl.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_p2p_kal.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_p2p_os.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_qa_agent.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_rst.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_sec.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_typedef.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_vendor.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_wext.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_wext_priv.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/plat/mt6885/plat_priv.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/plat/mt6893/plat_priv.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/platform.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/gl_ate_agent.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/gl_dependent.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/gl_init.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/gl_kal.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/gl_qa_agent.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/hif/none/include/hif.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/hif/none/none.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_ate_agent.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_cfg80211.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_dependent.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_kal.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_os.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_p2p_ioctl.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_p2p_kal.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_p2p_os.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_qa_agent.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_rst.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_typedef.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_vendor.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_wext_priv.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/version.h diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_ate_agent.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_ate_agent.c new file mode 100644 index 0000000000000..9f2a1578c786a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_ate_agent.c @@ -0,0 +1,2688 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + Module Name: + gl_ate_agent.c +*/ +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ + +#include "precomp.h" +#if CFG_SUPPORT_QA_TOOL +#include "gl_wext.h" +#include "gl_cfg80211.h" +#include "gl_ate_agent.h" +#include "gl_hook_api.h" +#include "gl_qa_agent.h" +#if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE +#include +#endif + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +#if CFG_SUPPORT_TX_BF +union PFMU_PROFILE_TAG1 g_rPfmuTag1; +union PFMU_PROFILE_TAG2 g_rPfmuTag2; +union PFMU_DATA g_rPfmuData; +#endif + +struct ATE_PRIV_CMD { + uint8_t *name; + int (*set_proc)(struct net_device *prNetDev, + uint8_t *prInBuf); +}; + +struct ATE_PRIV_CMD rAtePrivCmdTable[] = { + {"ResetCounter", Set_ResetStatCounter_Proc}, + {"ATE", SetATE}, +#if 0 + {"ADCDump", SetADCDump}, + {"ATEBSSID", SetATEBssid}, +#endif + {"ATEDA", SetATEDa}, + {"ATESA", SetATESa}, + {"ATECHANNEL", SetATEChannel}, + {"ATETXPOW0", SetATETxPower0}, + {"ATETXGI", SetATETxGi}, + {"ATETXBW", SetATETxBw}, + {"ATETXLEN", SetATETxLength}, + {"ATETXCNT", SetATETxCount}, + {"ATETXMCS", SetATETxMcs}, + {"ATETXMODE", SetATETxMode}, + {"ATEIPG", SetATEIpg}, + {"ATEVHTNSS", SetATETxVhtNss}, + {"ATETXANT", SetATETxPath}, + {"ATERXANT", SetATERxPath}, +#if CFG_SUPPORT_ANT_SWAP + {"ATEANTSWP", SetATEAntSwp}, +#endif +#if CFG_SUPPORT_TX_BF + {"TxBfProfileTagHelp", Set_TxBfProfileTag_Help}, + {"TxBfProfileTagInValid", Set_TxBfProfileTag_InValid}, + {"TxBfProfileTagPfmuIdx", Set_TxBfProfileTag_PfmuIdx}, + {"TxBfProfileTagBfType", Set_TxBfProfileTag_BfType}, + {"TxBfProfileTagBw", Set_TxBfProfileTag_DBW}, + {"TxBfProfileTagSuMu", Set_TxBfProfileTag_SuMu}, + {"TxBfProfileTagMemAlloc", Set_TxBfProfileTag_Mem}, + {"TxBfProfileTagMatrix", Set_TxBfProfileTag_Matrix}, + {"TxBfProfileTagSnr", Set_TxBfProfileTag_SNR}, + {"TxBfProfileTagSmtAnt", Set_TxBfProfileTag_SmartAnt}, + {"TxBfProfileTagSeIdx", Set_TxBfProfileTag_SeIdx}, + {"TxBfProfileTagRmsdThrd", Set_TxBfProfileTag_RmsdThrd}, + {"TxBfProfileTagMcsThrd", Set_TxBfProfileTag_McsThrd}, + {"TxBfProfileTagTimeOut", Set_TxBfProfileTag_TimeOut}, + {"TxBfProfileTagDesiredBw", Set_TxBfProfileTag_DesiredBW}, + {"TxBfProfileTagDesiredNc", Set_TxBfProfileTag_DesiredNc}, + {"TxBfProfileTagDesiredNr", Set_TxBfProfileTag_DesiredNr}, + {"TxBfProfileTagRead", Set_TxBfProfileTagRead}, + {"TxBfProfileTagWrite", Set_TxBfProfileTagWrite}, + {"TxBfProfileDataRead", Set_TxBfProfileDataRead}, + {"TxBfProfileDataWrite", Set_TxBfProfileDataWrite}, + {"TxBfProfilePnRead", Set_TxBfProfilePnRead}, + {"TxBfProfilePnWrite", Set_TxBfProfilePnWrite}, + {"TxBfSounding", Set_Trigger_Sounding_Proc}, + {"TxBfSoundingStop", Set_Stop_Sounding_Proc}, + {"TxBfTxApply", Set_TxBfTxApply}, + {"TxBfManualAssoc", Set_TxBfManualAssoc}, + {"TxBfPfmuMemAlloc", Set_TxBfPfmuMemAlloc}, + {"TxBfPfmuMemRelease", Set_TxBfPfmuMemRelease}, + {"StaRecCmmUpdate", Set_StaRecCmmUpdate}, + {"StaRecBfUpdate", Set_StaRecBfUpdate}, + {"DevInfoUpdate", Set_DevInfoUpdate}, + {"BssInfoUpdate", Set_BssInfoUpdate}, +#if CFG_SUPPORT_MU_MIMO + {"MUGetInitMCS", Set_MUGetInitMCS}, + {"MUCalInitMCS", Set_MUCalInitMCS}, + {"MUCalLQ", Set_MUCalLQ}, + {"MUGetLQ", Set_MUGetLQ}, + {"MUSetSNROffset", Set_MUSetSNROffset}, + {"MUSetZeroNss", Set_MUSetZeroNss}, + {"MUSetSpeedUpLQ", Set_MUSetSpeedUpLQ}, + {"MUSetMUTable", Set_MUSetMUTable}, + {"MUSetGroup", Set_MUSetGroup}, + {"MUGetQD", Set_MUGetQD}, + {"MUSetEnable", Set_MUSetEnable}, + {"MUSetGID_UP", Set_MUSetGID_UP}, + {"MUTriggerTx", Set_MUTriggerTx}, +#endif + +#if CFG_SUPPORT_TX_BF_FPGA + {"TxBfProfileSwTagWrite", Set_TxBfProfileSwTagWrite}, +#endif + +#endif + + {"WriteEfuse", WriteEfuse}, + {"TxPower", SetTxTargetPower}, +#if (CFG_SUPPORT_DFS_MASTER == 1) + {"RDDReport", SetRddReport}, + {"ByPassCac", SetByPassCac}, + {"RadarDetectMode", SetRadarDetectMode}, +#endif + + {NULL,} +}; + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Reset RX Statistic Counters. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +int Set_ResetStatCounter_Proc(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + int32_t i4Status; + + DBGLOG(REQ, INFO, + "ATE_AGENT iwpriv Set_ResetStatCounter_Proc\n"); + + i4Status = MT_ATEResetTXRXCounter(prNetDev); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set Start Test Mode / Stop Test Mode + * / Start TX / Stop TX / Start RX / Stop RX. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATE(struct net_device *prNetDev, uint8_t *prInBuf) +{ + int32_t i4Status; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetATE\n"); + + if (!strcmp(prInBuf, "ATESTART")) { + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetATE - ATESTART\n"); + i4Status = MT_ATEStart(prNetDev, prInBuf); + } else if (!strcmp(prInBuf, "ICAPSTART")) { + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetATE - ICAPSTART\n"); + i4Status = MT_ICAPStart(prNetDev, prInBuf); + } else if (prInBuf[0] == '1' || prInBuf[0] == '2' + || prInBuf[0] == '3' || prInBuf[0] == '4' + || prInBuf[0] == '5' || prInBuf[0] == '6') { + DBGLOG(REQ, INFO, + "ATE_AGENT iwpriv SetATE - ICAP COMMAND\n"); + i4Status = MT_ICAPCommand(prNetDev, prInBuf); + } else if (!strcmp(prInBuf, "ATESTOP")) { + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetATE - ATESTOP\n"); + i4Status = MT_ATEStop(prNetDev, prInBuf); + } else if (!strcmp(prInBuf, "TXFRAME")) { + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetATE - TXFRAME\n"); + i4Status = MT_ATEStartTX(prNetDev, prInBuf); + } else if (!strcmp(prInBuf, "TXSTOP")) { + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetATE - TXSTOP\n"); + i4Status = MT_ATEStopTX(prNetDev, prInBuf); + } else if (!strcmp(prInBuf, "RXFRAME")) { + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetATE - RXFRAME\n"); + i4Status = MT_ATEStartRX(prNetDev, prInBuf); + } else if (!strcmp(prInBuf, "RXSTOP")) { + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetATE - RXSTOP\n"); + i4Status = MT_ATEStopRX(prNetDev, prInBuf); + } else { + return -EINVAL; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set TX Destination Address. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATEDa(struct net_device *prNetDev, uint8_t *prInBuf) +{ + int32_t i4Status = 0; + uint32_t addr[MAC_ADDR_LEN]; + uint8_t addr2[MAC_ADDR_LEN]; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "ATE_AGENT iwpriv SetDa\n"); + /* xx:xx:xx:xx:xx:xx */ + rv = sscanf(prInBuf, "%x:%x:%x:%x:%x:%x", &addr[0], + &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]); + if (rv == 6) { + DBGLOG(RFTEST, ERROR, + "ATE_AGENT iwpriv SetATEDa Sa:%02x:%02x:%02x:%02x:%02x:%02x\n", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + + addr2[0] = (uint8_t) addr[0]; + addr2[1] = (uint8_t) addr[1]; + addr2[2] = (uint8_t) addr[2]; + addr2[3] = (uint8_t) addr[3]; + addr2[4] = (uint8_t) addr[4]; + addr2[5] = (uint8_t) addr[5]; + + i4Status = MT_ATESetMACAddress(prNetDev, + RF_AT_FUNCID_SET_MAC_ADDRESS, addr2); + } else { + return -EINVAL; + } + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set TX Source Address. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATESa(struct net_device *prNetDev, uint8_t *prInBuf) +{ + int32_t i4Status = 0; + uint32_t addr[MAC_ADDR_LEN]; + uint8_t addr2[MAC_ADDR_LEN]; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "ATE_AGENT iwpriv SetSa\n"); + /* xx:xx:xx:xx:xx:xx */ + rv = sscanf(prInBuf, "%x:%x:%x:%x:%x:%x", &addr[0], + &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]); + if (rv == 6) { + DBGLOG(RFTEST, ERROR, + "ATE_AGENT iwpriv SetATESa Sa:%02x:%02x:%02x:%02x:%02x:%02x\n", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + + addr2[0] = (uint8_t) addr[0]; + addr2[1] = (uint8_t) addr[1]; + addr2[2] = (uint8_t) addr[2]; + addr2[3] = (uint8_t) addr[3]; + addr2[4] = (uint8_t) addr[4]; + addr2[5] = (uint8_t) addr[5]; + + i4Status = MT_ATESetMACAddress(prNetDev, + RF_AT_FUNCID_SET_TA, addr2); + } else { + return -EINVAL; + } + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set Channel Frequency. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATEChannel(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t i4SetFreq = 0; + int32_t i4Status, i4SetChan = 0; + int32_t rv; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetChannel\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetChan); + if (rv == 0) { + i4SetFreq = nicChannelNum2Freq(i4SetChan); + i4Status = MT_ATESetChannel(prNetDev, 0, i4SetFreq); + } else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set TX WF0 Power. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATETxPower0(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t i4SetTxPower0 = 0; + int32_t i4Status; + int32_t rv; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetTxPower0\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxPower0); + if (rv == 0) + i4Status = MT_ATESetTxPower0(prNetDev, i4SetTxPower0); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set TX Guard Interval. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATETxGi(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t i4SetTxGi = 0; + int32_t i4Status; + int32_t rv; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetTxGi\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxGi); + if (rv == 0) + i4Status = MT_ATESetTxGi(prNetDev, i4SetTxGi); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set TX System Bandwidth. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATETxBw(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t i4SetSystemBW = 0; + int32_t i4Status; + int32_t rv; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetSystemBW\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetSystemBW); + if (rv == 0) + i4Status = MT_ATESetSystemBW(prNetDev, i4SetSystemBW); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set TX Mode (Preamble). + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATETxMode(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t i4SetTxMode = 0; + int32_t i4Status; + int32_t rv; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetTxMode\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxMode); + if (rv == 0) + i4Status = MT_ATESetPreamble(prNetDev, i4SetTxMode); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set TX Length. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATETxLength(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t i4SetTxLength = 0; + int32_t i4Status; + int32_t rv; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetTxLength\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxLength); + if (rv == 0) + i4Status = MT_ATESetTxLength(prNetDev, i4SetTxLength); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set TX Count. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATETxCount(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t i4SetTxCount = 0; + int32_t i4Status; + int32_t rv; + uint8_t addr[MAC_ADDR_LEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetTxCount\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxCount); + if (rv == 0) + i4Status = MT_ATESetTxCount(prNetDev, i4SetTxCount); + else + return -EINVAL; + + i4Status = MT_ATESetMACAddress(prNetDev, + RF_AT_FUNCID_SET_MAC_ADDRESS, addr); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set TX Rate. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATETxMcs(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t i4SetTxMcs = 0; + int32_t i4Status; + int32_t rv; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetTxMcs\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxMcs); + if (rv == 0) + i4Status = MT_ATESetRate(prNetDev, i4SetTxMcs); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set Inter-Packet Guard Interval. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATEIpg(struct net_device *prNetDev, uint8_t *prInBuf) +{ + uint32_t i4SetTxIPG = 0; + int32_t i4Status; + int32_t rv; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetIpg\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxIPG); + if (rv == 0) + i4Status = MT_ATESetTxIPG(prNetDev, i4SetTxIPG); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set Inter-Packet Guard Interval. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATETxVhtNss(struct net_device *prNetDev, uint8_t *prInBuf) +{ + uint32_t i4SetTVhtNSS = 0; + int32_t i4Status; + int32_t rv; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetATETxVhtNss\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTVhtNSS); + if (rv == 0) + i4Status = MT_ATESetTxVhtNss(prNetDev, i4SetTVhtNSS); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set Inter-Packet Guard Interval. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATETxPath(struct net_device *prNetDev, uint8_t *prInBuf) +{ + uint32_t i4TxPath = 0; + int32_t i4Status; + int32_t rv; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetATETxPath\n"); + + rv = kstrtoint(prInBuf, 0, &i4TxPath); + if (rv == 0) + i4Status = MT_ATESetTxPath(prNetDev, i4TxPath); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set Inter-Packet Guard Interval. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATERxPath(struct net_device *prNetDev, uint8_t *prInBuf) +{ + uint32_t i4RxPath = 0; + int32_t i4Status; + int32_t rv; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetATERxPath\n"); + + rv = kstrtoint(prInBuf, 0, &i4RxPath); + if (rv == 0) + i4Status = MT_ATESetRxPath(prNetDev, i4RxPath); + else + return -EINVAL; + + return i4Status; +} + +#if CFG_SUPPORT_ANT_SWAP +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set Antenna Swap + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATEAntSwp(struct net_device *prNetDev, uint8_t *prInBuf) +{ + uint32_t i4SetAntSwp = 0; + int32_t i4Status; + int32_t rv; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetAntSwp\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetAntSwp); + if (rv == 0) { + DBGLOG(REQ, INFO, "i4SetAntSwp = %d\n", i4SetAntSwp); + i4Status = MT_ATESetAntSwap(prNetDev, i4SetAntSwp); + } else + return -EINVAL; + + return i4Status; +} +#endif + +#if CFG_SUPPORT_TX_BF +int Set_TxBfProfileTag_Help(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + DBGLOG(RFTEST, ERROR, + "========================================================================================================================\n" + "TxBfProfile Tag1 setting example :\n" + "iwpriv ra0 set TxBfProfileTagPfmuIdx =xx\n" + "iwpriv ra0 set TxBfProfileTagBfType =xx (0: iBF; 1: eBF)\n" + "iwpriv ra0 set TxBfProfileTagBw =xx (0/1/2/3 : BW20/40/80/160NC)\n" + "iwpriv ra0 set TxBfProfileTagSuMu =xx (0:SU, 1:MU)\n" + "iwpriv ra0 set TxBfProfileTagInvalid =xx (0: valid, 1: invalid)\n" + "iwpriv ra0 set TxBfProfileTagMemAlloc =xx:xx:xx:xx:xx:xx:xx:xx (mem_row, mem_col), ..\n" + "iwpriv ra0 set TxBfProfileTagMatrix =nrow:nol:ng:LM\n" + "iwpriv ra0 set TxBfProfileTagSnr =SNR_STS0:SNR_STS1:SNR_STS2:SNR_STS3\n" + "\n\n" + "TxBfProfile Tag2 setting example :\n" + "iwpriv ra0 set TxBfProfileTagSmtAnt =xx (11:0)\n" + "iwpriv ra0 set TxBfProfileTagSeIdx =xx\n" + "iwpriv ra0 set TxBfProfileTagRmsdThrd =xx\n" + "iwpriv ra0 set TxBfProfileTagMcsThrd =xx:xx:xx:xx:xx:xx (MCS TH L1SS:S1SS:L2SS:....)\n" + "iwpriv ra0 set TxBfProfileTagTimeOut =xx\n" + "iwpriv ra0 set TxBfProfileTagDesiredBw=xx (0/1/2/3 : BW20/40/80/160NC)\n" + "iwpriv ra0 set TxBfProfileTagDesiredNc=xx\n" + "iwpriv ra0 set TxBfProfileTagDesiredNr=xx\n" + "\n\n" + "Read TxBf profile Tag :\n" + "iwpriv ra0 set TxBfProfileTagRead =xx (PFMU ID)\n" + "\n" + "Write TxBf profile Tag :\n" + "iwpriv ra0 set TxBfProfileTagWrite =xx (PFMU ID)\n" + "When you use one of relative CMD to update one of tag parameters, you should call TxBfProfileTagWrite to update Tag\n" + "\n\n" + "Read TxBf profile Data :\n" + "iwpriv ra0 set TxBfProfileDataRead =xx (PFMU ID)\n" + "\n" + "Write TxBf profile Data :\n" + "iwpriv ra0 set TxBfProfileDataWrite =BW :subcarrier:phi11:psi2l:Phi21:Psi31:Phi31:Psi41:Phi22:Psi32:Phi32:Psi42:Phi33:Psi43\n" + "iwpriv ra0 set TxBfProfileDataWriteAll=Profile ID : BW (BW : 0x00 (20M) , 0x01 (40M), 0x02 (80M), 0x3 (160M)\n" + "When you use CMD TxBfProfileDataWrite to update profile data per subcarrier, you should call TxBfProfileDataWriteAll to update all of\n" + "subcarrier's profile data.\n\n" + "Read TxBf profile PN :\n" + "iwpriv ra0 set TxBfProfilePnRead =xx (PFMU ID)\n" + "\n" + "Write TxBf profile PN :\n" + "iwpriv ra0 set TxBfProfilePnWrite =Profile ID:BW:1STS_Tx0:1STS_Tx1:1STS_Tx2:1STS_Tx3:2STS_Tx0:2STS_Tx1:2STS_Tx2:2STS_Tx3:3STS_Tx1:3STS_Tx2:3STS_Tx3\n" + "========================================================================================================================\n"); + return 0; +} + +int Set_TxBfProfileTag_InValid(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t ucInValid; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_InValid\n"); + + rv = kstrtoint(prInBuf, 0, &ucInValid); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTag_InValid prInBuf = %s, ucInValid = %d\n", + prInBuf, + ucInValid); + i4Status = TxBfProfileTag_InValid(prNetDev, &g_rPfmuTag1, + ucInValid); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_PfmuIdx(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t ucProfileIdx; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_PfmuIdx\n"); + + rv = kstrtoint(prInBuf, 0, &ucProfileIdx); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTag_PfmuIdx prInBuf = %s, ucProfileIdx = %d\n", + prInBuf, + ucProfileIdx); + i4Status = TxBfProfileTag_PfmuIdx(prNetDev, &g_rPfmuTag1, + ucProfileIdx); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_BfType(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t ucBFType; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_BfType\n"); + + rv = kstrtoint(prInBuf, 0, &ucBFType); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTag_BfType prInBuf = %s, ucBFType = %d\n", + prInBuf, ucBFType); + i4Status = TxBfProfileTag_TxBfType(prNetDev, &g_rPfmuTag1, + ucBFType); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_DBW(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t ucBW; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_DBW\n"); + + rv = kstrtoint(prInBuf, 0, &ucBW); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTag_DBW prInBuf = %s, ucBW = %d\n", + prInBuf, ucBW); + i4Status = TxBfProfileTag_DBW(prNetDev, &g_rPfmuTag1, ucBW); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_SuMu(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t ucSuMu; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_SuMu\n"); + + rv = kstrtoint(prInBuf, 0, &ucSuMu); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTag_SuMu prInBuf = %s, ucSuMu = %d\n", + prInBuf, ucSuMu); + i4Status = TxBfProfileTag_SuMu(prNetDev, &g_rPfmuTag1, + ucSuMu); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_Mem(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t aucInput[8]; + int32_t i4Status = 0; + uint8_t aucMemAddrColIdx[4], aucMemAddrRowIdx[4]; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_Mem\n"); + + rv = sscanf(prInBuf, "%d:%d:%d:%d:%d:%d:%d:%d", + &aucInput[0], &aucInput[1], &aucInput[2], &aucInput[3], + &aucInput[4], &aucInput[5], &aucInput[6], + &aucInput[7]); + /* mem col0:row0:col1:row1:col2:row2:col3:row3 */ + if (rv == 8) { + DBGLOG(RFTEST, ERROR, + "ATE_AGENT iwpriv Set_TxBfProfileTag_Mem aucInput:%d:%d:%d:%d:%d:%d:%d:%d\n", + aucInput[0], aucInput[1], aucInput[2], aucInput[3], + aucInput[4], aucInput[5], aucInput[6], + aucInput[7]); + + aucMemAddrColIdx[0] = (uint8_t) aucInput[0]; + aucMemAddrRowIdx[0] = (uint8_t) aucInput[1]; + aucMemAddrColIdx[1] = (uint8_t) aucInput[2]; + aucMemAddrRowIdx[1] = (uint8_t) aucInput[3]; + aucMemAddrColIdx[2] = (uint8_t) aucInput[4]; + aucMemAddrRowIdx[2] = (uint8_t) aucInput[5]; + aucMemAddrColIdx[3] = (uint8_t) aucInput[6]; + aucMemAddrRowIdx[3] = (uint8_t) aucInput[7]; + + i4Status = TxBfProfileTag_Mem(prNetDev, &g_rPfmuTag1, + aucMemAddrColIdx, aucMemAddrRowIdx); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_Matrix(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t aucInput[6]; + uint8_t ucNrow, ucNcol, ucNgroup, ucLM, ucCodeBook, + ucHtcExist; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_Matrix\n"); + + rv = sscanf(prInBuf, "%d:%d:%d:%d:%d:%d", + &aucInput[0], &aucInput[1], &aucInput[2], &aucInput[3], + &aucInput[4], &aucInput[5]); + /* nrow:nol:ng:LM:CodeBook:HtcExist */ + if (rv == 6) { + DBGLOG(RFTEST, ERROR, + "ATE_AGENT iwpriv Set_TxBfProfileTag_Matrix aucInput:%d:%d:%d:%d:%d:%d\n", + aucInput[0], aucInput[1], aucInput[2], aucInput[3], + aucInput[4], aucInput[5]); + ucNrow = (uint8_t) aucInput[0]; + ucNcol = (uint8_t) aucInput[1]; + ucNgroup = (uint8_t) aucInput[2]; + ucLM = (uint8_t) aucInput[3]; + ucCodeBook = (uint8_t) aucInput[4]; + ucHtcExist = (uint8_t) aucInput[5]; + + i4Status = TxBfProfileTag_Matrix(prNetDev, &g_rPfmuTag1, ucNrow, + ucNcol, ucNgroup, ucLM, ucCodeBook, ucHtcExist); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_SNR(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t aucInput[4]; + uint8_t ucSNR_STS0, ucSNR_STS1, ucSNR_STS2, ucSNR_STS3; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_SNR\n"); + + rv = sscanf(prInBuf, "%d:%d:%d:%d", &aucInput[0], + &aucInput[1], &aucInput[2], &aucInput[3]); + if (rv == 4) { + DBGLOG(RFTEST, ERROR, + "ATE_AGENT iwpriv Set_TxBfProfileTag_SNR aucInput:%d:%d:%d:%d\n", + aucInput[0], aucInput[1], aucInput[2], aucInput[3]); + + ucSNR_STS0 = (uint8_t) aucInput[0]; + ucSNR_STS1 = (uint8_t) aucInput[1]; + ucSNR_STS2 = (uint8_t) aucInput[2]; + ucSNR_STS3 = (uint8_t) aucInput[3]; + + i4Status = TxBfProfileTag_SNR(prNetDev, &g_rPfmuTag1, + ucSNR_STS0, ucSNR_STS1, ucSNR_STS2, ucSNR_STS3); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_SmartAnt(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + int32_t i4Status = 0; + uint32_t ucSmartAnt; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_SmartAnt\n"); + + rv = kstrtoint(prInBuf, 0, &ucSmartAnt); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTag_SmartAnt prInBuf = %s, ucSmartAnt = %d\n", + prInBuf, + ucSmartAnt); + i4Status = TxBfProfileTag_SmtAnt(prNetDev, &g_rPfmuTag2, + ucSmartAnt); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_SeIdx(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + int32_t i4Status = 0; + uint32_t ucSeIdx; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_SeIdx\n"); + + rv = kstrtoint(prInBuf, 0, &ucSeIdx); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "TxBfProfileTag_SeIdx prInBuf = %s, ucSeIdx = %d\n", + prInBuf, ucSeIdx); + i4Status = TxBfProfileTag_SeIdx(prNetDev, &g_rPfmuTag2, + ucSeIdx); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_RmsdThrd(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + int32_t i4Status = 0; + uint32_t ucRmsdThrd; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_RmsdThrd\n"); + + rv = kstrtoint(prInBuf, 0, &ucRmsdThrd); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTag_RmsdThrd prInBuf = %s, ucRmsdThrd = %d\n", + prInBuf, + ucRmsdThrd); + i4Status = TxBfProfileTag_RmsdThd(prNetDev, &g_rPfmuTag2, + ucRmsdThrd); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_McsThrd(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t aucInput[6]; + uint8_t ucMcsLss[3], ucMcsSss[3]; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_McsThrd\n"); + + rv = sscanf(prInBuf, "%d:%d:%d:%d:%d:%d", + &aucInput[0], &aucInput[1], &aucInput[2], &aucInput[3], + &aucInput[4], &aucInput[5]); + if (rv == 6) { + DBGLOG(RFTEST, ERROR, + "ATE_AGENT iwpriv Set_TxBfProfileTag_McsThrd aucInput:%d:%d:%d:%d:%d:%d\n", + aucInput[0], aucInput[1], aucInput[2], aucInput[3], + aucInput[4], aucInput[5]); + + ucMcsLss[0] = (uint8_t) aucInput[0]; + ucMcsSss[0] = (uint8_t) aucInput[1]; + ucMcsLss[1] = (uint8_t) aucInput[2]; + ucMcsSss[1] = (uint8_t) aucInput[3]; + ucMcsLss[2] = (uint8_t) aucInput[4]; + ucMcsSss[2] = (uint8_t) aucInput[5]; + + i4Status = TxBfProfileTag_McsThd(prNetDev, &g_rPfmuTag2, + ucMcsLss, ucMcsSss); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_TimeOut(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t ucTimeOut; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_TimeOut\n"); + + rv = kstrtouint(prInBuf, 0, &ucTimeOut); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTag_TimeOut prInBuf = %s, ucTimeOut = %d\n", + prInBuf, + ucTimeOut); + i4Status = TxBfProfileTag_TimeOut(prNetDev, &g_rPfmuTag2, + ucTimeOut); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_DesiredBW(struct net_device + *prNetDev, uint8_t *prInBuf) +{ + uint32_t ucDesiredBW; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_DesiredBW\n"); + + rv = kstrtoint(prInBuf, 0, &ucDesiredBW); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTag_DesiredBW prInBuf = %s, ucDesiredBW = %d\n", + prInBuf, + ucDesiredBW); + i4Status = TxBfProfileTag_DesiredBW(prNetDev, &g_rPfmuTag2, + ucDesiredBW); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_DesiredNc(struct net_device + *prNetDev, uint8_t *prInBuf) +{ + uint32_t ucDesiredNc; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_DesiredNc\n"); + + rv = kstrtoint(prInBuf, 0, &ucDesiredNc); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTag_DesiredNc prInBuf = %s, ucDesiredNc = %d\n", + prInBuf, + ucDesiredNc); + i4Status = TxBfProfileTag_DesiredNc(prNetDev, &g_rPfmuTag2, + ucDesiredNc); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_DesiredNr(struct net_device + *prNetDev, uint8_t *prInBuf) +{ + uint32_t ucDesiredNr; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_DesiredNr\n"); + + rv = kstrtoint(prInBuf, 0, &ucDesiredNr); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTag_DesiredNr prInBuf = %s, ucDesiredNr = %d\n", + prInBuf, + ucDesiredNr); + i4Status = TxBfProfileTag_DesiredNr(prNetDev, &g_rPfmuTag2, + ucDesiredNr); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTagWrite(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t profileIdx; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTagWrite\n"); + + rv = kstrtoint(prInBuf, 0, &profileIdx); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTagWrite prInBuf = %s, profileIdx = %d\n", + prInBuf, + profileIdx); + i4Status = TxBfProfileTagWrite(prNetDev, &g_rPfmuTag1, + &g_rPfmuTag2, profileIdx); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTagRead(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t profileIdx, fgBFer; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTagRead\n"); + + rv = sscanf(prInBuf, "%d:%d", &profileIdx, &fgBFer); + if (rv == 2) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTagRead prInBuf = %s, profileIdx = %d, fgBFer = %d\n", + prInBuf, profileIdx, fgBFer); + i4Status = TxBfProfileTagRead(prNetDev, profileIdx, fgBFer); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileDataRead(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t profileIdx, fgBFer, subcarrierIdxMsb, + subcarrierIdxLsb; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileDataRead\n"); + + rv = sscanf(prInBuf, "%d:%d:%x:%x", &profileIdx, &fgBFer, + &subcarrierIdxMsb, &subcarrierIdxLsb); + if (rv == 4) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileDataRead prInBuf = %s, profileIdx = %d, fgBFer = %d, subcarrierIdxMsb:%x, subcarrierIdxLsb:%x\n", + prInBuf, profileIdx, fgBFer, subcarrierIdxMsb, + subcarrierIdxLsb); + i4Status = TxBfProfileDataRead(prNetDev, profileIdx, fgBFer, + subcarrierIdxMsb, subcarrierIdxLsb); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileDataWrite(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + + uint32_t u4ProfileIdx; + uint32_t u4SubcarrierIdx; + uint32_t au4Phi[6]; + uint32_t au4Psi[6]; + uint32_t au4DSnr[4]; + uint16_t au2Phi[6]; + uint8_t aucPsi[6]; + uint8_t aucDSnr[4]; + uint32_t i; + int32_t rv; + + int32_t i4Status = 0; + + DBGLOG(RFTEST, ERROR, "TxBfProfileDataWrite\n"); + + rv = sscanf(prInBuf, + "%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x", + &u4ProfileIdx, &u4SubcarrierIdx, &au4Phi[0], &au4Psi[0], + &au4Phi[1], &au4Psi[1], + &au4Phi[2], &au4Psi[2], &au4Phi[3], &au4Psi[3], &au4Phi[4], + &au4Psi[4], + &au4Phi[5], &au4Psi[5], + &au4DSnr[0], &au4DSnr[1], &au4DSnr[2], &au4DSnr[3]); + + if (rv == 18) { + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite prInBuf = %s, u4ProfileIdx = %x, u4SubcarrierIdx = %x, au4Phi[0]:%x, au4Phi[1]:%x, au4Phi[2]:%x, au4Phi[3]:%x, au4Phi[4]:%x, au4Phi[5]:%x, au4Psi[0]:%x, au4Psi[1]:%x, au4Psi[2]:%x, au4Psi[3]:%x, au4Psi[4]:%x, au4Psi[5]:%x,au4DSnr[0]:%x, au4DSnr[1]:%x, au4DSnr[2]:%x, au4DSnr[3]:%x\n", + prInBuf, u4ProfileIdx, u4SubcarrierIdx, + au4Phi[0], au4Phi[1], au4Phi[2], au4Phi[3], au4Phi[4], + au4Phi[5], + au4Psi[0], au4Psi[1], au4Psi[2], au4Psi[3], au4Psi[4], + au4Psi[5], + au4DSnr[0], au4DSnr[1], au4DSnr[2], au4DSnr[3]); + for (i = 0; i < 6; i++) { + au2Phi[i] = au4Phi[i]; + aucPsi[i] = au4Psi[i]; + } + for (i = 0; i < 4; i++) + aucDSnr[i] = au4DSnr[i]; + + i4Status = TxBfProfileDataWrite(prNetDev, u4ProfileIdx, + u4SubcarrierIdx, au2Phi, aucPsi, aucDSnr); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfilePnRead(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t profileIdx; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfilePnRead\n"); + + rv = kstrtoint(prInBuf, 0, &profileIdx); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfilePnRead prInBuf = %s, profileIdx = %d\n", + prInBuf, profileIdx); + i4Status = TxBfProfilePnRead(prNetDev, profileIdx); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfilePnWrite(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4ProfileIdx; + uint16_t u2bw; + uint16_t au2XSTS[12]; + int32_t rv; + + int32_t i4Status = 0; + + DBGLOG(RFTEST, ERROR, "TxBfProfilePnWrite\n"); + + rv = sscanf(prInBuf, + "%d:%hd:%hd:%hd:%hd:%hd:%hd:%hd:%hd:%hd:%hd:%hd:%hd:%hd", + &u4ProfileIdx, &u2bw, &au2XSTS[0], &au2XSTS[1], &au2XSTS[2], + &au2XSTS[3], + &au2XSTS[4], &au2XSTS[5], &au2XSTS[6], &au2XSTS[7], + &au2XSTS[8], &au2XSTS[9], &au2XSTS[10], + &au2XSTS[11]); + if (rv == 14) { + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite prInBuf = %s, ucProfileIdx = %d, u2bw = %dau2XSTS[0]:%d, au2XSTS[1]:%d, au2XSTS[2]:%d, au2XSTS[3]:%d, au2XSTS[4]:%d, au2XSTS[5]:%d, au2XSTS[6]:%d, au2XSTS[7]:%d, au2XSTS[8]:%d, au2XSTS[9]:%d, au2XSTS[10]:%d, au2XSTS[11]:%d\n", + prInBuf, u4ProfileIdx, u2bw, au2XSTS[0], + au2XSTS[1], au2XSTS[2], au2XSTS[3], au2XSTS[4], + au2XSTS[5], au2XSTS[6], au2XSTS[7], au2XSTS[8], + au2XSTS[9], au2XSTS[10], au2XSTS[11]); + + i4Status = TxBfProfilePnWrite(prNetDev, u4ProfileIdx, u2bw, + au2XSTS); + } else + return -EINVAL; + + return i4Status; +} + +/* Su_Mu:NumSta:SndInterval:WLan0:WLan1:WLan2:WLan3 */ +int Set_Trigger_Sounding_Proc(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t ucSuMu, ucNumSta, ucSndInterval, ucWLan0, ucWLan1, + ucWLan2, ucWLan3; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_Trigger_Sounding_Proc\n"); + + rv = sscanf + (prInBuf, "%x:%x:%x:%x:%x:%x:%x", &ucSuMu, &ucNumSta, + &ucSndInterval, &ucWLan0, &ucWLan1, &ucWLan2, + &ucWLan3); + if (rv == 7) { + DBGLOG(RFTEST, ERROR, + "Set_Trigger_Sounding_Proc prInBuf = %s, ucSuMu = %d, ucNumSta = %d, ucSndInterval = %d, ucWLan0 = %d, ucWLan1 = %d, ucWLan2:%d, ucWLan3:%d\n", + prInBuf, ucSuMu, ucNumSta, ucSndInterval, ucWLan0, + ucWLan1, ucWLan2, ucWLan3); + i4Status = TxBfSounding(prNetDev, ucSuMu, ucNumSta, + ucSndInterval, ucWLan0, ucWLan1, ucWLan2, ucWLan3); + } else + return -EINVAL; + + return i4Status; +} + +int Set_Stop_Sounding_Proc(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + int32_t i4Status = 0; + + DBGLOG(RFTEST, ERROR, "Set_Stop_Sounding_Proc\n"); + + i4Status = TxBfSoundingStop(prNetDev); + + return i4Status; +} + +int Set_TxBfTxApply(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4WlanId, u4ETxBf, u4ITxBf, u4MuTxBf; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "TxBfTxApply\n"); + + rv = sscanf(prInBuf, "%d:%d:%d:%d", &u4WlanId, &u4ETxBf, + &u4ITxBf, &u4MuTxBf); + if (rv == 4) { + DBGLOG(RFTEST, ERROR, + "TxBfTxApply prInBuf = %s, u4WlanId = %d, u4ETxBf = %d, u4ITxBf = %d, u4MuTxBf = %d\n", + prInBuf, u4WlanId, u4ETxBf, u4ITxBf, u4MuTxBf); + i4Status = TxBfTxApply(prNetDev, u4WlanId, u4ETxBf, u4ITxBf, + u4MuTxBf); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfManualAssoc(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + int32_t au4Mac[MAC_ADDR_LEN]; + int32_t u4Type, u4Wtbl, u4Ownmac, u4PhyMode, u4Bw, u4Nss, + u4PfmuId, u4Mode, u4Marate, u4SpeIdx, ucaid, u4Rv; + int8_t aucMac[MAC_ADDR_LEN]; + int32_t i4Status = 0; + int32_t i = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "TxBfManualAssoc\n"); + + rv = sscanf(prInBuf, + "%x:%x:%x:%x:%x:%x:%x:%d:%x:%x:%x:%x:%d:%x:%x:%x:%d:%x", + &au4Mac[0], &au4Mac[1], &au4Mac[2], &au4Mac[3], &au4Mac[4], + &au4Mac[5], + &u4Type, &u4Wtbl, &u4Ownmac, &u4PhyMode, &u4Bw, &u4Nss, + &u4PfmuId, &u4Mode, &u4Marate, &u4SpeIdx, + &ucaid, &u4Rv); + if (rv == 18) { + DBGLOG(RFTEST, ERROR, + "TxBfManualAssoc au4Mac[0] = %x, au4Mac[1] = %x, au4Mac[2] = %xau4Mac[3] = %x, au4Mac[4] = %x, au4Mac[5] = %x, u4Type = %x, u4Wtbl = %d, u4Ownmac = %x, u4PhyMode = %x u4Bw = %x, u4Nss = %x, u4PfmuId = %d, u4Mode = %x, u4Marate = %x, u4SpeIdx = %d, ucaid = %d, u4Rv = %x", + au4Mac[0], au4Mac[1], au4Mac[2], au4Mac[3], au4Mac[4], + au4Mac[5], u4Type, u4Wtbl, u4Ownmac, + u4PhyMode, u4Bw, u4Nss, u4PfmuId, u4Mode, u4Marate, + u4SpeIdx, ucaid, u4Rv); + for (i = 0; i < MAC_ADDR_LEN; i++) + aucMac[i] = au4Mac[i]; + + i4Status = + TxBfManualAssoc(prNetDev, aucMac, u4Type, u4Wtbl, + u4Ownmac, u4Mode, u4Bw, u4Nss, u4PfmuId, + u4Marate, u4SpeIdx, ucaid, u4Rv); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfPfmuMemAlloc(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t ucSuMuMode, ucWlanIdx; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "TxBfPfmuMemAlloc\n"); + + rv = sscanf(prInBuf, "%d:%d", &ucSuMuMode, &ucWlanIdx); + if (rv == 2) { + DBGLOG(RFTEST, ERROR, + "TxBfPfmuMemAlloc ucSuMuMode = %d, ucWlanIdx = %d", + ucSuMuMode, ucWlanIdx); + i4Status = TxBfPfmuMemAlloc(prNetDev, ucSuMuMode, + ucWlanIdx); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfPfmuMemRelease(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t ucWlanId; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "TxBfPfmuMemRelease\n"); + + rv = kstrtoint(prInBuf, 0, &ucWlanId); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "TxBfPfmuMemRelease ucWlanId = %d", + ucWlanId); + i4Status = TxBfPfmuMemRelease(prNetDev, ucWlanId); + } else + return -EINVAL; + + return i4Status; +} + +int Set_DevInfoUpdate(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4OwnMacIdx, fgBand; + uint32_t OwnMacAddr[MAC_ADDR_LEN]; + uint8_t aucMacAddr[MAC_ADDR_LEN]; + int32_t i4Status = 0; + uint32_t i; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "DevInfoUpdate\n"); + + rv = sscanf + (prInBuf, "%d:%x:%x:%x:%x:%x:%x:%d", &u4OwnMacIdx, + &OwnMacAddr[0], &OwnMacAddr[1], &OwnMacAddr[2], + &OwnMacAddr[3], &OwnMacAddr[4], &OwnMacAddr[5], &fgBand); + if (rv == 8) { + DBGLOG(RFTEST, ERROR, + "DevInfoUpdate prInBuf = %s, u4OwnMacIdx = %x, fgBand = %x,OwnMacAddr[0]:%x, OwnMacAddr[1]:%x, OwnMacAddr[2]:%x, OwnMacAddr[3]:%x, OwnMacAddr[4]:%x, OwnMacAddr[5]:%x,", + prInBuf, u4OwnMacIdx, fgBand, + OwnMacAddr[0], OwnMacAddr[1], + OwnMacAddr[2], OwnMacAddr[3], + OwnMacAddr[4], OwnMacAddr[5]); + for (i = 0; i < MAC_ADDR_LEN; i++) + aucMacAddr[i] = OwnMacAddr[i]; + + i4Status = DevInfoUpdate(prNetDev, u4OwnMacIdx, fgBand, + aucMacAddr); + } else + return -EINVAL; + + return i4Status; +} + +int Set_BssInfoUpdate(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4OwnMacIdx, u4BssIdx; + uint32_t au4BssId[MAC_ADDR_LEN]; + uint8_t aucBssId[MAC_ADDR_LEN]; + int32_t i4Status = 0; + uint32_t i; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "BssInfoUpdate\n"); + + rv = sscanf + (prInBuf, "%d:%d:%x:%x:%x:%x:%x:%x", &u4OwnMacIdx, + &u4BssIdx, &au4BssId[0], &au4BssId[1], &au4BssId[2], + &au4BssId[3], &au4BssId[4], &au4BssId[5]); + if (rv == 8) { + DBGLOG(RFTEST, ERROR, + "BssInfoUpdate prInBuf = %s, u4OwnMacIdx = %x, u4BssIdx = %x,au4BssId[0]:%x, au4BssId[1]:%x, au4BssId[2]:%x, au4BssId[3]:%x, au4BssId[4]:%x, au4BssId[5]:%x,", + prInBuf, u4OwnMacIdx, u4BssIdx, au4BssId[0], au4BssId[1], + au4BssId[2], au4BssId[3], au4BssId[4], + au4BssId[5]); + for (i = 0; i < MAC_ADDR_LEN; i++) + aucBssId[i] = au4BssId[i]; + + i4Status = BssInfoUpdate(prNetDev, u4OwnMacIdx, u4BssIdx, + aucBssId); + } else + return -EINVAL; + + return i4Status; +} + +int Set_StaRecCmmUpdate(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4WlanId, u4BssId, u4Aid; + uint32_t au4MacAddr[MAC_ADDR_LEN]; + uint8_t aucMacAddr[MAC_ADDR_LEN]; + int32_t i4Status = 0; + uint32_t i; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_StaRecCmmUpdate\n"); + + rv = sscanf + (prInBuf, "%x:%x:%x:%x:%x:%x:%x:%x:%x", &u4WlanId, &u4BssId, + &u4Aid, &au4MacAddr[0], &au4MacAddr[1], + &au4MacAddr[2], &au4MacAddr[3], &au4MacAddr[4], + &au4MacAddr[5]); + if (rv == 9) { + DBGLOG(RFTEST, ERROR, + "Set_StaRecCmmUpdate prInBuf = %s, u4WlanId = %x, u4BssId = %x, u4Aid = %x,aucMacAddr[0]:%x, aucMacAddr[1]:%x, aucMacAddr[2]:%x, aucMacAddr[3]:%x, aucMacAddr[4]:%x, aucMacAddr[5]:%x,", + prInBuf, u4WlanId, u4BssId, u4Aid, au4MacAddr[0], + au4MacAddr[1], au4MacAddr[2], au4MacAddr[3], + au4MacAddr[4], au4MacAddr[5]); + for (i = 0; i < MAC_ADDR_LEN; i++) + aucMacAddr[i] = au4MacAddr[i]; + + i4Status = StaRecCmmUpdate(prNetDev, u4WlanId, u4BssId, + u4Aid, aucMacAddr); + } else + return -EINVAL; + + return i4Status; +} + +int Set_StaRecBfUpdate(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + struct STA_REC_BF_UPD_ARGUMENT rStaRecBfUpdArg; + uint8_t aucMemRow[4], aucMemCol[4]; + int32_t i4Status = 0; + uint32_t i; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_StaRecBfUpdate\n"); + + rv = sscanf(prInBuf, + "%x:%x:%x:%x:%x:%d:%d:%d:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x", + &rStaRecBfUpdArg.u4WlanId, &rStaRecBfUpdArg.u4BssId, + &rStaRecBfUpdArg.u4PfmuId, + &rStaRecBfUpdArg.u4SuMu, &rStaRecBfUpdArg.u4eTxBfCap, + &rStaRecBfUpdArg.u4NdpaRate, + &rStaRecBfUpdArg.u4NdpRate, &rStaRecBfUpdArg.u4ReptPollRate, + &rStaRecBfUpdArg.u4TxMode, + &rStaRecBfUpdArg.u4Nc, &rStaRecBfUpdArg.u4Nr, + &rStaRecBfUpdArg.u4Bw, &rStaRecBfUpdArg.u4SpeIdx, + &rStaRecBfUpdArg.u4TotalMemReq, + &rStaRecBfUpdArg.u4MemReq20M, &rStaRecBfUpdArg.au4MemRow[0], + &rStaRecBfUpdArg.au4MemCol[0], + &rStaRecBfUpdArg.au4MemRow[1], + &rStaRecBfUpdArg.au4MemCol[1], + &rStaRecBfUpdArg.au4MemRow[2], + &rStaRecBfUpdArg.au4MemCol[2], + &rStaRecBfUpdArg.au4MemRow[3], + &rStaRecBfUpdArg.au4MemCol[3]); + if (rv == 23) { + /* + *DBGLOG(RFTEST, ERROR, + *"Set_StaRecBfUpdate prInBuf = %s, u4WlanId = %x, u4BssId = %x, + * u4Aid = %x, + * aucMacAddr[0]:%x, aucMacAddr[1]:%x, aucMacAddr[2]:%x, + * aucMacAddr[3]:%x, aucMacAddr[4]:%x, aucMacAddr[5]:%x", + * prInBuf, u4OwnMacIdx, u4BssIdx, u4Aid, + * aucMacAddr[0], aucMacAddr[1], aucMacAddr[2], aucMacAddr[3], + * aucMacAddr[4], aucMacAddr[5]); + */ + for (i = 0; i < 4; i++) { + aucMemRow[i] = rStaRecBfUpdArg.au4MemRow[i]; + aucMemCol[i] = rStaRecBfUpdArg.au4MemCol[i]; + } + i4Status = StaRecBfUpdate(prNetDev, rStaRecBfUpdArg, + aucMemRow, aucMemCol); + } else + return -EINVAL; + + return i4Status; +} + +#if CFG_SUPPORT_MU_MIMO +int Set_MUGetInitMCS(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT rMuMimoActionInfo; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + + uint32_t u4groupIdx; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_MUGetInitMCS\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rv = kstrtouint(prInBuf, 0, &u4groupIdx); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "Test\n"); + DBGLOG(RFTEST, ERROR, + "Set_MUGetInitMCS prInBuf = %s, u4groupIdx = %x", + prInBuf, u4groupIdx); + + rMuMimoActionInfo.ucMuMimoCategory = MU_GET_CALC_INIT_MCS; + rMuMimoActionInfo.unMuMimoParam.rMuGetCalcInitMcs.ucgroupIdx + = u4groupIdx; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, + sizeof(rMuMimoActionInfo), + TRUE, TRUE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUCalInitMCS(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT rMuMimoActionInfo; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + + uint32_t u4NumOfUser, u4Bandwidth, u4NssOfUser0, + u4NssOfUser1, u4PfMuIdOfUser0, u4PfMuIdOfUser1, u4NumOfTxer, + u4SpeIndex, u4GroupIndex; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_MUCalInitMCS\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rv = sscanf + (prInBuf, "%x:%x:%x:%x:%x:%x:%x:%x:%x", &u4NumOfUser, + &u4Bandwidth, &u4NssOfUser0, &u4NssOfUser1, + &u4PfMuIdOfUser0, &u4PfMuIdOfUser1, &u4NumOfTxer, + &u4SpeIndex, &u4GroupIndex); + if (rv == 9) { + DBGLOG(RFTEST, ERROR, + "Set_MUCalInitMCS prInBuf = %s, u4NumOfUser = %x, u4Bandwidth = %x, u4NssOfUser0 = %x, u4NssOfUser1 = %x, u4PfMuIdOfUser0 = %x, u4PfMuIdOfUser1 = %x, u4NumOfTxer = %x, u4SpeIndex = %x, u4GroupIndex = %x", + prInBuf, u4NumOfUser, u4Bandwidth, u4NssOfUser0, + u4NssOfUser1, u4PfMuIdOfUser0, u4PfMuIdOfUser1, + u4NumOfTxer, u4SpeIndex, u4GroupIndex); + + rMuMimoActionInfo.ucMuMimoCategory = MU_SET_CALC_INIT_MCS; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucNumOfUser = + u4NumOfUser; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucBandwidth = + u4Bandwidth; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucNssOfUser0 = + u4NssOfUser0; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucNssOfUser1 = + u4NssOfUser1; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucPfMuIdOfUser0 + = u4PfMuIdOfUser0; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucPfMuIdOfUser1 + = u4PfMuIdOfUser1; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucNumOfTxer = + u4NumOfTxer; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucSpeIndex = + u4SpeIndex; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.u4GroupIndex = + u4GroupIndex; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, + sizeof(rMuMimoActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUCalLQ(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT rMuMimoActionInfo; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + + uint32_t u4NumOfUser, u4Bandwidth, u4NssOfUser0, + u4NssOfUser1, u4PfMuIdOfUser0, u4PfMuIdOfUser1, + u4NumOfTxer, u4SpeIndex, u4GroupIndex; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_MUCalLQ\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rv = sscanf + (prInBuf, "%x:%x:%x:%x:%x:%x:%x:%x:%x", &u4NumOfUser, + &u4Bandwidth, &u4NssOfUser0, &u4NssOfUser1, + &u4PfMuIdOfUser0, &u4PfMuIdOfUser1, &u4NumOfTxer, + &u4SpeIndex, &u4GroupIndex); + if (rv == 9) { + DBGLOG(RFTEST, ERROR, + "Set_MUCalLQ prInBuf = %s, u4NumOfUser = %x, u4Bandwidth = %x, u4NssOfUser0 = %x, u4NssOfUser1 = %x, u4PfMuIdOfUser0 = %x, u4PfMuIdOfUser1 = %x, u4NumOfTxer = %x, u4SpeIndex = %x, u4GroupIndex = %x", + prInBuf, u4NumOfUser, u4Bandwidth, u4NssOfUser0, + u4NssOfUser1, u4PfMuIdOfUser0, u4PfMuIdOfUser1, + u4NumOfTxer, u4SpeIndex, u4GroupIndex); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_CALC_LQ; + /* rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucType = + * u4Type; + */ + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucNumOfUser = + u4NumOfUser; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucBandwidth = + u4Bandwidth; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucNssOfUser0 = + u4NssOfUser0; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucNssOfUser1 = + u4NssOfUser1; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucPfMuIdOfUser0 + = u4PfMuIdOfUser0; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucPfMuIdOfUser1 + = u4PfMuIdOfUser1; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucNumOfTxer = + u4NumOfTxer; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucSpeIndex = + u4SpeIndex; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.u4GroupIndex = + u4GroupIndex; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, + sizeof(rMuMimoActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUGetLQ(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT rMuMimoActionInfo; + int32_t i4Status = 0; + /* UINT_32 u4Type; */ + uint32_t u4BufLen = 0; + + DBGLOG(RFTEST, ERROR, "Set_MUGetLQ\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + /* if (sscanf(prInBuf, "%x", &u4Type) == 1) + * { + * DBGLOG(RFTEST, ERROR, "Set_MUGetLQ prInBuf = %s, u4Type = %x", + * prInBuf, u4Type); + */ + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_GET_CALC_LQ; + /* rMuMimoActionInfo.unMuMimoParam.rMuGetLq.ucType = u4Type; */ + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, + sizeof(rMuMimoActionInfo), + TRUE, TRUE, TRUE, &u4BufLen); + /* } + * else + * { + * return -EINVAL; + * } + */ + + return i4Status; +} + +int Set_MUSetSNROffset(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT rMuMimoActionInfo; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + + uint32_t u4Val; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_MUSetSNROffset\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rv = kstrtoint(prInBuf, 0, &u4Val); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_MUSetSNROffset prInBuf = %s, u4Val = %x", prInBuf, + u4Val); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_SNR_OFFSET; + rMuMimoActionInfo.unMuMimoParam.rMuSetSnrOffset.ucVal = + u4Val; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, + sizeof(rMuMimoActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUSetZeroNss(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT rMuMimoActionInfo; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + + uint32_t u4Val; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_MUSetZeroNss\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rv = kstrtouint(prInBuf, 0, &u4Val); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_MUSetZeroNss prInBuf = %s, u4Val = %x", prInBuf, + u4Val); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_ZERO_NSS; + rMuMimoActionInfo.unMuMimoParam.rMuSetZeroNss.ucVal = u4Val; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, + sizeof(rMuMimoActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUSetSpeedUpLQ(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT rMuMimoActionInfo; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + + uint32_t u4Val; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_MUSetSpeedUpLQ\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rv = kstrtouint(prInBuf, 0, &u4Val); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_MUSetSpeedUpLQ prInBuf = %s, u4Val = %x", prInBuf, + u4Val); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_SPEED_UP_LQ; + rMuMimoActionInfo.unMuMimoParam.rMuSpeedUpLq.u4Val = u4Val; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, + sizeof(rMuMimoActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUSetMUTable(struct net_device *prNetDev, + uint8_t *prTable) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT rMuMimoActionInfo; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + /*uint32_t i; + *uint32_t u4Type, u4Length; + */ + + DBGLOG(RFTEST, ERROR, "Set_MUSetMUTable\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + /* if (sscanf(prInBuf, "%x:%x", &u4Type, &u4Length) == 2) */ + /* { */ + /* DBGLOG(RFTEST, ERROR, "Set_MUSetMUTable prInBuf = %s, */ + /* u4Type = %x, u4Length = %x", prInBuf, u4Type, u4Length); */ + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_MU_TABLE; + /* rMuMimoActionInfo.unMuMimoParam.rMuSetMuTable.u2Type = u4Type; */ + /* rMuMimoActionInfo.unMuMimoParam.rMuSetMuTable.u4Length = u4Length; */ + + /* for ( i = 0 ; i < NUM_MUT_NR_NUM * NUM_MUT_FEC * NUM_MUT_MCS + * * NUM_MUT_INDEX ; i++) + * { + */ + memcpy(rMuMimoActionInfo.unMuMimoParam.rMuSetMuTable.aucMetricTable, + prTable, + NUM_MUT_NR_NUM * NUM_MUT_FEC * NUM_MUT_MCS * NUM_MUT_INDEX); + /* } */ + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, + sizeof(rMuMimoActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + /* } */ + /* else */ + /* { */ + /* return -EINVAL; */ + /* } */ + + return i4Status; +} + +int Set_MUSetGroup(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT rMuMimoActionInfo; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + uint32_t i = 0; + + uint32_t aucUser0MacAddr[PARAM_MAC_ADDR_LEN], + aucUser1MacAddr[PARAM_MAC_ADDR_LEN]; + + DBGLOG(RFTEST, ERROR, "Set_MUSetGroup\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (sscanf(prInBuf, + "%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x", + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4GroupIndex, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4NumOfUser, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0Ldpc, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1Ldpc, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4ShortGI, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4Bw, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0Nss, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1Nss, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4GroupId, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0UP, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1UP, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0MuPfId, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1MuPfId, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0InitMCS, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1InitMCS, + &aucUser0MacAddr[0], + &aucUser0MacAddr[1], &aucUser0MacAddr[2], + &aucUser0MacAddr[3], &aucUser0MacAddr[4], + &aucUser0MacAddr[5], &aucUser1MacAddr[0], + &aucUser1MacAddr[1], &aucUser1MacAddr[2], + &aucUser1MacAddr[3], &aucUser1MacAddr[4], + &aucUser1MacAddr[5]) != 27) { + return -EINVAL; + } + + DBGLOG(RFTEST, ERROR, + "Set_MUSetGroup prInBuf = %s,u4GroupIndex = %d, u4NumOfUser = %d, u4User0Ldpc = %d, u4User1Ldpc = %d, u4ShortGI = %d, u4Bw = %d, u4User0Nss = %d, u4User1Nss = %d, u4GroupId = %d, u4User0UP = %d, u4User1UP = %d, u4User0MuPfId = %d, u4User1MuPfId = %d, u4User0InitMCS = %d, u4User1InitMCS = %d,aucUser0MacAddr[0] = %x, aucUser0MacAddr[1] = %x, aucUser0MacAddr[2] = %x, aucUser0MacAddr[3] = %x, aucUser0MacAddr[4] = %x, aucUser0MacAddr[5] = %x,aucUser1MacAddr[0] = %x, aucUser1MacAddr[1] = %x, aucUser1MacAddr[2] = %x, aucUser1MacAddr[3] = %x, aucUser1MacAddr[4] = %x, aucUser1MacAddr[5] = %x,", + prInBuf, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4GroupIndex, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4NumOfUser, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0Ldpc, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1Ldpc, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4ShortGI, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4Bw, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0Nss, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1Nss, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4GroupId, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0UP, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1UP, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0MuPfId, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1MuPfId, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0InitMCS, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1InitMCS, + aucUser0MacAddr[0], aucUser0MacAddr[1], + aucUser0MacAddr[2], aucUser0MacAddr[3], + aucUser0MacAddr[4], aucUser0MacAddr[5], + aucUser1MacAddr[0], aucUser1MacAddr[1], + aucUser1MacAddr[2], aucUser1MacAddr[3], + aucUser1MacAddr[4], aucUser1MacAddr[5]); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_GROUP; + for (i = 0; i < PARAM_MAC_ADDR_LEN; i++) { + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.aucUser0MacAddr[i] + = aucUser0MacAddr[i]; + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.aucUser1MacAddr[i] + = aucUser1MacAddr[i]; + } + + i4Status = kalIoctl(prGlueInfo, wlanoidMuMimoAction, &rMuMimoActionInfo, + sizeof(rMuMimoActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +int Set_MUGetQD(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT rMuMimoActionInfo; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + + uint32_t u4SubcarrierIndex, u4Length; + + DBGLOG(RFTEST, ERROR, "Set_MUGetQD\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (sscanf(prInBuf, "%x:%x", &u4SubcarrierIndex, + &u4Length) == 2) { + DBGLOG(RFTEST, ERROR, + "Set_MUGetQD prInBuf = %s, u4SubcarrierIndex = %x, u4Length = %x", + prInBuf, + u4SubcarrierIndex, u4Length); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_GET_QD; + rMuMimoActionInfo.unMuMimoParam.rMuGetQd.ucSubcarrierIndex = + u4SubcarrierIndex; + /* rMuMimoActionInfo.unMuMimoParam.rMuGetQd.u4Length = + * u4Length; + */ + /* rMuMimoActionInfo.unMuMimoParam.rMuGetQd.ucgroupIdx = + * ucgroupIdx; + */ + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, + sizeof(rMuMimoActionInfo), + TRUE, TRUE, TRUE, &u4BufLen); + } else { + return -EINVAL; + } + + return i4Status; +} + +int Set_MUSetEnable(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT rMuMimoActionInfo; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + + uint32_t u4Val; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_MUSetEnable\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rv = kstrtouint(prInBuf, 0, &u4Val); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_MUSetEnable prInBuf = %s, u4Val = %x", + prInBuf, u4Val); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_ENABLE; + rMuMimoActionInfo.unMuMimoParam.rMuSetEnable.ucVal = u4Val; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, + sizeof(rMuMimoActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUSetGID_UP(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT rMuMimoActionInfo; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + + DBGLOG(RFTEST, ERROR, "Set_MUSetGID_UP\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (sscanf(prInBuf, "%d:%d:%d:%d:%d:%d", + &rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Gid[0], + &rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Gid[1], + &rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[0], + &rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[1], + &rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[2], + &rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[3]) == 6 + ) { + DBGLOG(RFTEST, ERROR, + "Set_MUSetGID_UP prInBuf = %s, au4Gid[0] = %x, au4Gid[1] = %x, au4Up[0] = %x, au4Up[1] = %x, au4Up[2] = %x, au4Up[3] = %x", + prInBuf, + rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Gid[0], + rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Gid[1], + rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[0], + rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[1], + rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[2], + rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[3]); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_STA_PARAM; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, + sizeof(rMuMimoActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + } else { + return -EINVAL; + } + + return i4Status; +} + +int Set_MUTriggerTx(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT rMuMimoActionInfo; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + uint32_t i, j; + + uint32_t u4IsRandomPattern, u4MsduPayloadLength0, + u4MsduPayloadLength1, u4MuPacketCount, u4NumOfSTAs; + uint32_t au4MacAddrs[2][6]; + + DBGLOG(RFTEST, ERROR, "Set_MUTriggerTx\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (sscanf(prInBuf, + "%d:%x:%x:%x:%d:%d:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x", + &u4IsRandomPattern, &u4MsduPayloadLength0, + &u4MsduPayloadLength1, &u4MuPacketCount, &u4NumOfSTAs, + &au4MacAddrs[0][0], &au4MacAddrs[0][1], &au4MacAddrs[0][2], + &au4MacAddrs[0][3], &au4MacAddrs[0][4], + &au4MacAddrs[0][5], &au4MacAddrs[1][0], &au4MacAddrs[1][1], + &au4MacAddrs[1][2], &au4MacAddrs[1][3], + &au4MacAddrs[1][4], &au4MacAddrs[1][5]) == 17) { + DBGLOG(RFTEST, ERROR, + "Set_MUTriggerTx prInBuf = %s, u4IsRandomPattern = %x, u4MsduPayloadLength0 = %x, u4MsduPayloadLength1 = %x, u4MuPacketCount = %x, u4NumOfSTAs = %x, au4MacAddrs[0][0] = %x, au4MacAddrs[0][1] = %x, au4MacAddrs[0][2] = %x, au4MacAddrs[0][3] = %x, au4MacAddrs[0][4] = %x, au4MacAddrs[0][5] = %x,au4MacAddrs[1][0] = %x, au4MacAddrs[1][1] = %x, au4MacAddrs[1][2] = %x, au4MacAddrs[1][3] = %x, au4MacAddrs[1][4] = %x, au4MacAddrs[1][5] = %x", + prInBuf, u4IsRandomPattern, u4MsduPayloadLength0, + u4MsduPayloadLength1, u4MuPacketCount, + u4NumOfSTAs, au4MacAddrs[0][0], au4MacAddrs[0][1], + au4MacAddrs[0][2], au4MacAddrs[0][3], + au4MacAddrs[0][4], au4MacAddrs[0][5], au4MacAddrs[1][0], + au4MacAddrs[1][1], au4MacAddrs[1][2], + au4MacAddrs[1][3], au4MacAddrs[1][4], au4MacAddrs[1][5]); + + rMuMimoActionInfo.ucMuMimoCategory = MU_SET_TRIGGER_MU_TX; + rMuMimoActionInfo.unMuMimoParam.rMuTriggerMuTx + .fgIsRandomPattern + = u4IsRandomPattern; + rMuMimoActionInfo.unMuMimoParam.rMuTriggerMuTx + .u4MsduPayloadLength0 + = u4MsduPayloadLength0; + rMuMimoActionInfo.unMuMimoParam.rMuTriggerMuTx + .u4MsduPayloadLength1 + = u4MsduPayloadLength1; + rMuMimoActionInfo.unMuMimoParam.rMuTriggerMuTx.u4MuPacketCount + = u4MuPacketCount; + rMuMimoActionInfo.unMuMimoParam.rMuTriggerMuTx.u4NumOfSTAs = + u4NumOfSTAs; + + for (i = 0 ; i < 2 ; i++) { + for (j = 0 ; j < PARAM_MAC_ADDR_LEN ; j++) + rMuMimoActionInfo.unMuMimoParam.rMuTriggerMuTx + .aucMacAddrs[i][j] + = au4MacAddrs[i][j]; + } + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, + sizeof(rMuMimoActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + } else { + return -EINVAL; + } + + return i4Status; +} +#endif + +#if CFG_SUPPORT_TX_BF_FPGA +int Set_TxBfProfileSwTagWrite(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + int32_t i4Status = 0; + int32_t rv; + uint32_t u4Lm, u4Nc, u4Nr, u4Bw, u4Codebook, u4Group; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileSwTagWrite\n"); + + rv = sscanf(prInBuf, "%d-%d-%d-%d-%d-%d", &u4Lm, &u4Nr, + &u4Nc, &u4Bw, &u4Codebook, &u4Group); + + if (rv == 6) { + if ((u4Lm > 0) && (u4Group < 3) && (u4Nr < 4) && (u4Nc < 4) + && (u4Codebook < 4)) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileSwTagWrite prInBuf = %s, u4Lm = %d, u4Nr = %d, u4Nc = %d, u4BW = %d, u4CodeBook = %d, u4Group=%d\n", + prInBuf, u4Lm, u4Nr, u4Nc, u4Bw, u4Codebook, + u4Group); + + i4Status = TxBfPseudoTagUpdate(prNetDev, u4Lm, u4Nr, + u4Nc, u4Bw, u4Codebook, u4Group); + } else + return -EINVAL; + } else + return -EINVAL; + + return i4Status; +} +#endif +#endif + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Write Efuse. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int WriteEfuse(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + int32_t i4Status; + int32_t rv; + uint32_t addr[2]; + uint16_t addr2[2]; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv WriteEfuse, buf: %s\n", + prInBuf); + + rv = sscanf(prInBuf, "%x:%x", &addr[0], &addr[1]); + + DBGLOG(REQ, INFO, + "ATE_AGENT iwpriv WriteEfuse, prInBuf: %s\n", prInBuf); + DBGLOG(INIT, ERROR, + "ATE_AGENT iwpriv WriteEfuse :%02x:%02x\n", addr[0], + addr[1]); + + addr2[0] = (uint16_t) addr[0]; + addr2[1] = (uint16_t) addr[1]; + + if (rv == 2) + i4Status = MT_ATEWriteEfuse(prNetDev, addr2[0], addr2[1]); + else + return -EINVAL; + + return i4Status; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set Tx Power. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetTxTargetPower(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + int32_t i4Status; + int32_t rv; + int addr; + uint8_t addr2; + + DBGLOG(REQ, INFO, + "ATE_AGENT iwpriv Set Tx Target Power, buf: %s\n", prInBuf); + + /* rv = sscanf(prInBuf, "%u", &addr);*/ + rv = kstrtoint(prInBuf, 0, &addr); + + DBGLOG(REQ, INFO, + "ATE_AGENT iwpriv Set Tx Target Power, prInBuf: %s\n", + prInBuf); + DBGLOG(INIT, ERROR, + "ATE_AGENT iwpriv Set Tx Target Power :%02x\n", addr); + + addr2 = (uint8_t) addr; + + if (rv == 0) + i4Status = MT_ATESetTxTargetPower(prNetDev, addr2); + else + return -EINVAL; + + return i4Status; +} + +#if (CFG_SUPPORT_DFS_MASTER == 1) +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set RDD Report + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetRddReport(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + int32_t i4Status; + int32_t rv; + int dbdcIdx; + uint8_t ucDbdcIdx; + + DBGLOG(REQ, INFO, + "ATE_AGENT iwpriv Set RDD Report, buf: %s\n", prInBuf); + + /* rv = sscanf(prInBuf, "%u", &addr);*/ + rv = kstrtoint(prInBuf, 0, &dbdcIdx); + + DBGLOG(REQ, INFO, + "ATE_AGENT iwpriv Set RDD Report, prInBuf: %s\n", prInBuf); + DBGLOG(INIT, ERROR, + "ATE_AGENT iwpriv Set RDD Report : Band %d\n", dbdcIdx); + + if (p2pFuncGetDfsState() == DFS_STATE_INACTIVE + || p2pFuncGetDfsState() == DFS_STATE_DETECTED) { + DBGLOG(REQ, ERROR, + "RDD Report is not supported in this DFS state (inactive or deteted)\n"); + return WLAN_STATUS_NOT_SUPPORTED; + } + + if (dbdcIdx != 0 && dbdcIdx != 1) { + DBGLOG(REQ, ERROR, + "RDD index is not \"0\" or \"1\", Invalid data\n"); + return WLAN_STATUS_INVALID_DATA; + } + + ucDbdcIdx = (uint8_t) dbdcIdx; + + if (rv == 0) + i4Status = MT_ATESetRddReport(prNetDev, ucDbdcIdx); + else + return -EINVAL; + + return i4Status; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set By Pass CAC. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetByPassCac(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + int32_t i4Status; + int32_t rv; + int32_t i4ByPassCacTime; + uint32_t u4ByPassCacTime; + + DBGLOG(REQ, INFO, + "ATE_AGENT iwpriv Set By Pass Cac, buf: %s\n", prInBuf); + + rv = kstrtoint(prInBuf, 0, &i4ByPassCacTime); + + DBGLOG(REQ, INFO, + "ATE_AGENT iwpriv Set By Pass Cac, prInBuf: %s\n", prInBuf); + DBGLOG(INIT, ERROR, + "ATE_AGENT iwpriv Set By Pass Cac : %dsec\n", + i4ByPassCacTime); + + if (i4ByPassCacTime < 0) { + DBGLOG(REQ, ERROR, "Cac time < 0, Invalid data\n"); + return WLAN_STATUS_INVALID_DATA; + } + + u4ByPassCacTime = (uint32_t) i4ByPassCacTime; + + p2pFuncEnableManualCac(); + + if (rv == 0) + i4Status = p2pFuncSetDriverCacTime(u4ByPassCacTime); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set Radar Detect Mode. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetRadarDetectMode(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + int32_t i4Status; + int32_t rv; + int radarDetectMode; + uint8_t ucRadarDetectMode; + + DBGLOG(REQ, INFO, + "ATE_AGENT iwpriv Set Radar Detect Mode, buf: %s\n", + prInBuf); + + rv = kstrtoint(prInBuf, 0, &radarDetectMode); + + DBGLOG(REQ, INFO, + "ATE_AGENT iwpriv Set Radar Detect Mode, prInBuf: %s\n", + prInBuf); + DBGLOG(INIT, ERROR, + "ATE_AGENT iwpriv Set Radar Detect Mode : %d\n", + radarDetectMode); + + if (p2pFuncGetDfsState() == DFS_STATE_INACTIVE + || p2pFuncGetDfsState() == DFS_STATE_DETECTED) { + DBGLOG(REQ, ERROR, + "RDD Report is not supported in this DFS state (inactive or deteted)\n"); + return WLAN_STATUS_NOT_SUPPORTED; + } + + if (radarDetectMode != 0 && radarDetectMode != 1) { + DBGLOG(REQ, ERROR, + "Radar Detect Mode is not \"0\" or \"1\", Invalid data\n"); + return WLAN_STATUS_INVALID_DATA; + } + + ucRadarDetectMode = (uint8_t) radarDetectMode; + + p2pFuncSetRadarDetectMode(ucRadarDetectMode); + + if (rv == 0) + i4Status = MT_ATESetRadarDetectMode(prNetDev, + ucRadarDetectMode); + else + return -EINVAL; + + return i4Status; +} + +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to search the corresponding ATE agent + * function. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[in] u4InBufLen The length of the buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int AteCmdSetHandle(struct net_device *prNetDev, + uint8_t *prInBuf, uint32_t u4InBufLen) +{ + uint8_t *this_char, *value; + struct ATE_PRIV_CMD *prAtePrivCmd; + int32_t i4Status = 0; + + while ((this_char = strsep((char **)&prInBuf, + ",")) != NULL) { + if (!*this_char) + continue; + DBGLOG(RFTEST, ERROR, "ATE_AGENT iwpriv this_char = %s\n", + this_char); + DBGLOG(RFTEST, INFO, "ATE_AGENT iwpriv this_char = %s\n", + this_char); + + value = strchr(this_char, '='); + if (value != NULL) + *value++ = 0; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv cmd = %s, value = %s\n", + this_char, value); + + for (prAtePrivCmd = rAtePrivCmdTable; prAtePrivCmd->name; + prAtePrivCmd++) { + if (!strcmp(this_char, prAtePrivCmd->name)) { + /* FALSE: Set private failed then return Invalid + * argument + */ + if (prAtePrivCmd->set_proc(prNetDev, value) + != 0) + i4Status = -EINVAL; + break; /*Exit for loop. */ + } + } + + if (prAtePrivCmd->name == NULL) { /*Not found argument */ + i4Status = -EINVAL; + break; + } + } + return i4Status; +} +#endif /*CFG_SUPPORT_QA_TOOL */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_bow.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_bow.c new file mode 100644 index 0000000000000..2ad16735acc2c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_bow.c @@ -0,0 +1,1175 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "debug.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "precomp.h" +#include +#include "bss.h" + +#if CFG_ENABLE_BT_OVER_WIFI + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* @FIXME if there is command/event with payload length > 28 */ +#define MAX_BUFFER_SIZE (64) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +uint32_t g_u4PrevSysTime; +uint32_t g_u4CurrentSysTime; +uint32_t g_arBowRevPalPacketTime[32]; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/* forward declarations */ +static ssize_t bow_ampc_read(IN struct file *filp, IN char __user *buf, IN size_t size, IN OUT loff_t *ppos); + +static ssize_t bow_ampc_write(IN struct file *filp, OUT const char __user *buf, IN size_t size, IN OUT loff_t *ppos); + +static long bow_ampc_ioctl(IN struct file *filp, IN unsigned int cmd, IN OUT unsigned long arg); + +static unsigned int bow_ampc_poll(IN struct file *filp, IN poll_table * wait); + +static int bow_ampc_open(IN struct inode *inodep, IN struct file *filp); + +static int bow_ampc_release(IN struct inode *inodep, IN struct file *filp); + +/* character file operations */ +static const struct file_operations bow_ampc_fops = { + /* .owner = THIS_MODULE, */ + .read = bow_ampc_read, + .write = bow_ampc_write, + .unlocked_ioctl = bow_ampc_ioctl, + .poll = bow_ampc_poll, + .open = bow_ampc_open, + .release = bow_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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t glRegisterAmpc(IN struct GLUE_INFO *prGlueInfo) +{ + ASSERT(prGlueInfo); + + DBGLOG(BOW, INFO, "Register for character device to communicate with 802.11 PAL.\n"); + + if (prGlueInfo->rBowInfo.fgIsRegistered == TRUE) + return FALSE; +#if 0 + /* 1. allocate major number dynamically */ + + if (alloc_chrdev_region(&(prGlueInfo->rBowInfo.u4DeviceNumber), 0, /* first minor number */ + 1, /* number */ + GLUE_BOW_DEVICE_NAME) != 0) + + return FALSE; +#endif + +#if 1 + +#if defined(CONFIG_AMPC_CDEV_NUM) + prGlueInfo->rBowInfo.u4DeviceNumber = MKDEV(CONFIG_AMPC_CDEV_NUM, 0); +#else + prGlueInfo->rBowInfo.u4DeviceNumber = MKDEV(226, 0); +#endif + + if (register_chrdev_region(prGlueInfo->rBowInfo.u4DeviceNumber, 1, /* number */ + GLUE_BOW_DEVICE_NAME) != 0) + + return FALSE; +#endif + + /* 2. spin-lock initialization */ + /* spin_lock_init(&(prGlueInfo->rBowInfo.rSpinLock)); */ + + /* 3. initialize kfifo */ +#if 0 + prGlueInfo->rBowInfo.prKfifo = kfifo_alloc(GLUE_BOW_KFIFO_DEPTH, + GFP_KERNEL, + &(prGlueInfo->rBowInfo.rSpinLock)); +#endif + 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), &bow_ampc_fops); + /* prGlueInfo->rBowInfo.cdev.owner = THIS_MODULE; */ + prGlueInfo->rBowInfo.cdev.ops = &bow_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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t glUnregisterAmpc(IN struct GLUE_INFO *prGlueInfo) +{ + ASSERT(prGlueInfo); + + DBGLOG(BOW, INFO, "Unregister character device for communicating with 802.11 PAL.\n"); + + if (prGlueInfo->rBowInfo.fgIsRegistered == FALSE) + return FALSE; + + prGlueInfo->rBowInfo.fgIsRegistered = FALSE; + + /* 1. free netdev if necessary */ +#if CFG_BOW_SEPARATE_DATA_PATH + kalUninitBowDevice(prGlueInfo); +#endif + + /* 2. removal of character device */ + cdev_del(&(prGlueInfo->rBowInfo.cdev)); + + /* 3. free kfifo */ +/* kfifo_free(prGlueInfo->rBowInfo.prKfifo); */ + kfifo_free(&(prGlueInfo->rBowInfo.rKfifo)); +/* prGlueInfo->rBowInfo.prKfifo = NULL; */ +/* prGlueInfo->rBowInfo.rKfifo = NULL; */ + + /* 4. free device number */ + unregister_chrdev_region(prGlueInfo->rBowInfo.u4DeviceNumber, 1); + + return TRUE; + +} /* end of glUnregisterAmpc */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief read handler for character device to communicate with 802.11 PAL +* +* \param[in] +* \return +* Follows Linux Character Device Interface +* +*/ +/*----------------------------------------------------------------------------*/ +static ssize_t bow_ampc_read(IN struct file *filp, IN char __user *buf, IN size_t size, IN OUT loff_t *ppos) +{ + uint8_t aucBuffer[MAX_BUFFER_SIZE]; + ssize_t retval; + + struct GLUE_INFO *prGlueInfo; + + prGlueInfo = (struct GLUE_INFO *) (filp->private_data); + + ASSERT(prGlueInfo); + + DBGLOG(BOW, INFO, "BoW EVENT read.\n"); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return -EFAULT; + /* size check */ +/* if(kfifo_len(prGlueInfo->rBowInfo.prKfifo) >= size) */ + if (kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)) >= size) + retval = size; + else + retval = kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)); +/* retval = kfifo_len(prGlueInfo->rBowInfo.prKfifo); */ + +/* kfifo_get(prGlueInfo->rBowInfo.prKfifo, aucBuffer, retval); */ +/* kfifo_out(prGlueInfo->rBowInfo.prKfifo, aucBuffer, retval); */ + if (!(kfifo_out(&(prGlueInfo->rBowInfo.rKfifo), aucBuffer, retval))) + retval = -EIO; + + 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 bow_ampc_write(IN struct file *filp, OUT const char __user *buf, IN size_t size, IN OUT loff_t *ppos) +{ + uint8_t i; + + uint8_t aucBuffer[MAX_BUFFER_SIZE]; + struct BT_OVER_WIFI_COMMAND *prCmd; + struct GLUE_INFO *prGlueInfo; + + prGlueInfo = (struct GLUE_INFO *) (filp->private_data); + ASSERT(prGlueInfo); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return -EFAULT; + + if (size > MAX_BUFFER_SIZE) + return -EINVAL; + else if (copy_from_user(aucBuffer, buf, size)) + return -EIO; + + 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"); + + prCmd = (struct BT_OVER_WIFI_COMMAND *) aucBuffer; + + DBGLOG(BOW, EVENT, "AMP write content payload length : %d.\n", prCmd->rHeader.u2PayloadLength); + + DBGLOG(BOW, EVENT, "AMP write content header length : %d.\n", sizeof(struct BT_OVER_WIFI_COMMAND_HEADER)); + + /* size check */ + if (prCmd->rHeader.u2PayloadLength + sizeof(struct BT_OVER_WIFI_COMMAND_HEADER) != size) { + DBGLOG(BOW, EVENT, "Wrong CMD total length.\n"); + + 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 bow_ampc_ioctl(IN struct file *filp, IN unsigned int cmd, IN OUT unsigned long arg) +{ + int err = 0; + struct GLUE_INFO *prGlueInfo; + + prGlueInfo = (struct GLUE_INFO *) (filp->private_data); + + ASSERT(prGlueInfo); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return -EFAULT; + /* permission check */ + if (_IOC_DIR(cmd) & _IOC_READ) + err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)); + else if (_IOC_DIR(cmd) & _IOC_WRITE) + err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)); + if (err) + return -EFAULT; + + /* no ioctl is implemented yet */ + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief ioctl handler for character device to communicate with 802.11 PAL +* +* \param[in] +* \return +* Follows Linux Character Device Interface +* +*/ +/*----------------------------------------------------------------------------*/ +static unsigned int bow_ampc_poll(IN struct file *filp, IN poll_table * wait) +{ + unsigned int retval; + struct GLUE_INFO *prGlueInfo; + + prGlueInfo = (struct GLUE_INFO *) (filp->private_data); + + ASSERT(prGlueInfo); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return -EFAULT; + + poll_wait(filp, &prGlueInfo->rBowInfo.outq, wait); + + retval = (POLLOUT | POLLWRNORM); /* always accepts incoming command packets */ + +/* DBGLOG(BOW, EVENT, ("bow_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, ("bow_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 bow_ampc_open(IN struct inode *inodep, IN struct file *filp) +{ + struct GLUE_INFO *prGlueInfo; + struct GL_BOW_INFO *prBowInfo; + + DBGLOG(BOW, INFO, "in %s\n", __func__); + + prBowInfo = container_of(inodep->i_cdev, struct GL_BOW_INFO, cdev); + ASSERT(prBowInfo); + + prGlueInfo = container_of(prBowInfo, struct GLUE_INFO, 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 bow_ampc_release(IN struct inode *inodep, IN struct file *filp) +{ + struct GLUE_INFO *prGlueInfo; + + prGlueInfo = (struct GLUE_INFO *) (filp->private_data); + + DBGLOG(BOW, INFO, "in %s\n", __func__); + + ASSERT(prGlueInfo); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to indicate event for Bluetooth over Wi-Fi +* +* \param[in] +* prGlueInfo +* prEvent +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +void kalIndicateBOWEvent(IN struct GLUE_INFO *prGlueInfo, IN struct BT_OVER_WIFI_EVENT *prEvent) +{ + size_t u4AvailSize, u4EventSize; + + ASSERT(prGlueInfo); + ASSERT(prEvent); + + /* check device */ + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return; +#if 0 + u4AvailSize = GLUE_BOW_KFIFO_DEPTH - kfifo_len(prGlueInfo->rBowInfo.prKfifo); +#endif + u4AvailSize = GLUE_BOW_KFIFO_DEPTH - kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)); + + u4EventSize = prEvent->rHeader.u2PayloadLength + sizeof(struct BT_OVER_WIFI_EVENT_HEADER); + + /* 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), (uint8_t *) prEvent, u4EventSize); + wake_up_interruptible(&(prGlueInfo->rBowInfo.outq)); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Bluetooth-over-Wi-Fi state from glue layer +* +* \param[in] +* prGlueInfo +* rPeerAddr +* \return +* ENUM_BOW_DEVICE_STATE +*/ +/*----------------------------------------------------------------------------*/ +enum ENUM_BOW_DEVICE_STATE kalGetBowState(IN struct GLUE_INFO *prGlueInfo, IN uint8_t aucPeerAddress[6]) +{ + uint8_t i; + + ASSERT(prGlueInfo); + + DBGLOG(BOW, EVENT, "kalGetBowState.\n"); + + for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { + if (EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr, aucPeerAddress) == 0) { + 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]); + + 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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalSetBowState(IN struct GLUE_INFO *prGlueInfo, IN enum ENUM_BOW_DEVICE_STATE eBowState, IN uint8_t aucPeerAddress[6]) +{ + uint8_t i; + + ASSERT(prGlueInfo); + DBGLOG(BOW, EVENT, "kalSetBowState, aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + aucPeerAddress[0], + aucPeerAddress[1], aucPeerAddress[2], aucPeerAddress[3], aucPeerAddress[4], aucPeerAddress[5]); + + for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { + if (EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr, aucPeerAddress) == 0) { + prGlueInfo->rBowInfo.aeState[i] = eBowState; + + 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]); + + 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 ENUM_BOW_DEVICE_STATE kalGetBowGlobalState(IN struct GLUE_INFO *prGlueInfo) +{ + uint32_t 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 +*/ +/*----------------------------------------------------------------------------*/ +uint32_t kalGetBowFreqInKHz(IN struct GLUE_INFO *prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->rBowInfo.u4FreqInKHz; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Bluetooth-over-Wi-Fi role +* +* \param[in] +* prGlueInfo +* +* \return +* 0: Responder +* 1: Initiator +*/ +/*----------------------------------------------------------------------------*/ +uint8_t kalGetBowRole(IN struct GLUE_INFO *prGlueInfo, IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN]) +{ + uint32_t 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 struct GLUE_INFO *prGlueInfo, IN uint8_t ucRole, IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN]) +{ + uint32_t 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) { + /* Henry, 0 : Responder, 1 : Initiator */ + prGlueInfo->rBowInfo.aucRole[i] = ucRole; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to get available Bluetooth-over-Wi-Fi physical link number +* +* \param[in] +* prGlueInfo +* \return +* UINT_32 +* how many physical links are aviailable +*/ +/*----------------------------------------------------------------------------*/ +uint8_t kalGetBowAvailablePhysicalLinkCount(IN struct GLUE_INFO *prGlueInfo) +{ + uint8_t i; + uint8_t 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 + DBGLOG(BOW, EVENT, "kalGetBowAvailablePhysicalLinkCount, ucLinkCount, %c.\n", ucLinkCount); +#endif + + return ucLinkCount; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This inline function is to extract some packet information for BoW +* +* @param prGlueInfo Pointer to the glue structure +* @param prNdisPacket Packet descriptor +* @param pfgIs1X 802.1x packet or not +* +* @retval TRUE Success to extract information +* @retval FALSE Fail to extract correct information +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalBowFrameClassifier(IN struct GLUE_INFO *prGlueInfo, IN void *prPacket, OUT u_int8_t *pfgIs1X) +{ + uint32_t u4PacketLen; + uint16_t u2EtherTypeLen; + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + uint8_t *aucLookAheadBuf = NULL; + uint8_t ucEthTypeLenOffset = ETHER_HEADER_LEN - ETHER_TYPE_LEN; + uint8_t *pucNextProtocol = NULL; + uint8_t aucLLC[] = ETH_LLC; + uint8_t aucSnapBtOui[] = ETH_SNAP_BT_SIG_OUI; + uint8_t ucMinLength = ucEthTypeLenOffset + ETHER_TYPE_LEN + ETH_LLC_LEN + ETH_SNAP_LEN; + + DEBUGFUNC("kalQoSFrameClassifierAndPacketInfo"); + + u4PacketLen = prSkb->len; + + if (u4PacketLen < ETHER_HEADER_LEN) { + DBGLOG(INIT, WARN, "Invalid Ether packet length: %lu\n", u4PacketLen); + return FALSE; + } + + aucLookAheadBuf = prSkb->data; + + *pfgIs1X = FALSE; + + /* 4 <0> Obtain Ether Type/Len */ + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[ucEthTypeLenOffset], &u2EtherTypeLen); + + /* 4 <1> Skip 802.1Q header (VLAN Tagging) */ + if (u2EtherTypeLen == ETH_P_VLAN) { + ucEthTypeLenOffset += ETH_802_1Q_HEADER_LEN; + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[ucEthTypeLenOffset], &u2EtherTypeLen); + } + /* 4 <2> Obtain next protocol pointer */ + pucNextProtocol = &aucLookAheadBuf[ucEthTypeLenOffset + ETHER_TYPE_LEN]; + + /* 4 <3> Handle ethernet format */ + if (u2EtherTypeLen > ETH_802_3_MAX_LEN) { + /* Not BoW frame */ + return FALSE; + } + /* 4 <4> Check for PAL (BT over Wi-Fi) */ + /* BoW LLC/SNAP header check */ + if (u4PacketLen >= ucMinLength && + !kalMemCmp(pucNextProtocol, aucLLC, ETH_LLC_LEN) && + !kalMemCmp(pucNextProtocol + ETH_LLC_LEN, aucSnapBtOui, ETH_SNAP_OUI_LEN)) { + uint16_t u2LocalCode; + + WLAN_GET_FIELD_BE16(pucNextProtocol + ETH_LLC_LEN + ETH_SNAP_OUI_LEN, &u2LocalCode); + + if (u2LocalCode == BOW_PROTOCOL_ID_SECURITY_FRAME) + *pfgIs1X = TRUE; + + return TRUE; + } + + return FALSE; +} /* end of kalBoWFrameClassifier() */ + +#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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + + ASSERT(prDev); + + prGlueInfo = *((struct GLUE_INFO **) 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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + + ASSERT(prDev); + + prGlueInfo = *((struct GLUE_INFO **) 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; +}; + +#if 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 netdev_tx_t bowHardStartXmit(IN struct sk_buff *prSkb, + IN struct net_device *prDev) +{ + struct GLUE_INFO *prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + + struct QUE_ENTRY *prQueueEntry = NULL; + struct QUE *prTxQueue = NULL; + uint16_t u2QueueIdx = 0; + uint8_t ucDSAP, ucSSAP, ucControl; + uint8_t aucOUI[3]; + uint8_t *aucLookAheadBuf = NULL; + uint8_t ucBssIndex; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prSkb); + ASSERT(prDev); + ASSERT(prGlueInfo); + + aucLookAheadBuf = prSkb->data; + + ucDSAP = *(uint8_t *) &aucLookAheadBuf[ETH_LLC_OFFSET]; + ucSSAP = *(uint8_t *) &aucLookAheadBuf[ETH_LLC_OFFSET + 1]; + ucControl = *(uint8_t *) &aucLookAheadBuf[ETH_LLC_OFFSET + 2]; + aucOUI[0] = *(uint8_t *) &aucLookAheadBuf[ETH_SNAP_OFFSET]; + aucOUI[1] = *(uint8_t *) &aucLookAheadBuf[ETH_SNAP_OFFSET + 1]; + aucOUI[2] = *(uint8_t *) &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)) { + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(BOW, TRACE, "GLUE_FLAG_HALT skip tx\n"); + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } + + GLUE_SET_PKT_FLAG_PAL(prSkb); + + ucBssIndex = wlanGetBssIdxByNetInterface(prGlueInfo, NET_DEV_BOW_IDX); + + GLUE_SET_PKT_BSS_IDX(prSkb, ucBssIndex); + + prQueueEntry = (struct QUE_ENTRY *) GLUE_GET_PKT_QUEUE_ENTRY(prSkb); + prTxQueue = &prGlueInfo->rTxQueue; + + if (wlanProcessSecurityFrame(prGlueInfo->prAdapter, (void *) 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[ucBssIndex][u2QueueIdx]); + + if (prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex][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; +} +#else +/*----------------------------------------------------------------------------*/ +/*! + * \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 netdev_tx_t bowHardStartXmit(IN struct sk_buff *prSkb, + IN struct net_device *prDev) +{ + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) NULL; + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t ucBssIndex; + u_int8_t fgIs1x; + + ASSERT(prSkb); + ASSERT(prDev); + +#if 1 + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) netdev_priv(prDev); + prGlueInfo = prNetDevPrivate->prGlueInfo; + ucBssIndex = prNetDevPrivate->ucBssIdx; +#else + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + + ucBssIndex = wlanGetBssIdxByNetInterface(prGlueInfo, NET_DEV_BOW_IDX); +#endif + + kalResetPacket(prGlueInfo, (void *) prSkb); + + /* Discard frames not generated by PAL */ + /* Parsing BOW frame info */ + if (!kalBowFrameClassifier(prGlueInfo, (void *) prSkb, &fgIs1x)) { + /* Cannot extract packet */ + DBGLOG(BOW, INFO, "Invalid BOW frame, skip Tx\n"); + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } + + if (fgIs1x) + GLUE_SET_PKT_FLAG(prSkb, ENUM_PKT_1X); + + if (kalHardStartXmit(prSkb, prDev, prGlueInfo, ucBssIndex) == WLAN_STATUS_SUCCESS) { + /* Successfully enqueue to Tx queue */ + /* Successfully enqueue to Tx queue */ + } + + /* For Linux, we'll always return OK FLAG, because we'll free this skb by ourself */ + return NETDEV_TX_OK; +} +#endif + +/* 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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalInitBowDevice(IN struct GLUE_INFO *prGlueInfo, IN const char *prDevName) +{ + struct ADAPTER *prAdapter; + struct GL_HIF_INFO *prHif; + uint8_t rMacAddr[PARAM_MAC_ADDR_LEN]; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPriv = (struct NETDEV_PRIVATE_GLUE_INFO *) NULL; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->rBowInfo.fgIsRegistered == TRUE); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prHif = &prGlueInfo->rHifInfo; + ASSERT(prHif); + + prChipInfo = prGlueInfo->prAdapter->chip_info; + + if (prGlueInfo->rBowInfo.fgIsNetRegistered == FALSE) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) + prGlueInfo->rBowInfo.prDevHandler = + alloc_netdev_mq(sizeof(struct GLUE_INFO *), prDevName, + NET_NAME_PREDICTABLE, ether_setup, CFG_MAX_TXQ_NUM); +#else + prGlueInfo->rBowInfo.prDevHandler = + alloc_netdev_mq(sizeof(struct GLUE_INFO *), prDevName, ether_setup, CFG_MAX_TXQ_NUM); +#endif + if (!prGlueInfo->rBowInfo.prDevHandler) + return FALSE; + + /* 1. setup netdev */ + /* 1.1 Point to shared glue structure */ + /* *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->rBowInfo.prDevHandler)) = prGlueInfo; */ + prNetDevPriv = (struct NETDEV_PRIVATE_GLUE_INFO *) netdev_priv(prGlueInfo->rBowInfo.prDevHandler); + prNetDevPriv->prGlueInfo = prGlueInfo; + + /* 1.2 fill hardware address */ + COPY_MAC_ADDR(rMacAddr, prAdapter->rMyMacAddr); + rMacAddr[0] |= 0x2; /* change to local administrated address */ + kalMemCopy(prGlueInfo->rBowInfo.prDevHandler->dev_addr, rMacAddr, ETH_ALEN); + kalMemCopy(prGlueInfo->rBowInfo.prDevHandler->perm_addr, + prGlueInfo->rBowInfo.prDevHandler->dev_addr, ETH_ALEN); + + /* 1.3 register callback functions */ + prGlueInfo->rBowInfo.prDevHandler->needed_headroom = + NIC_TX_DESC_AND_PADDING_LENGTH + prChipInfo->txd_append_size; + prGlueInfo->rBowInfo.prDevHandler->netdev_ops = &bow_netdev_ops; + +#if defined(_HIF_SDIO) && (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); + + /* 2.1 bind NetDev pointer to NetDev index */ + wlanBindBssIdxToNetInterface(prGlueInfo, bowInit(prAdapter), + (void *) prGlueInfo->rBowInfo.prDevHandler); + prNetDevPriv->ucBssIdx = prAdapter->rWifiVar.rBowFsmInfo.ucBssIndex; + /* wlanBindNetInterface(prGlueInfo, NET_DEV_BOW_IDX, */ + /* (PVOID)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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalUninitBowDevice(IN struct GLUE_INFO *prGlueInfo) +{ + struct ADAPTER *prAdapter; + + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + /* ASSERT(prGlueInfo->rBowInfo.fgIsRegistered == TRUE); */ + + if (prGlueInfo->rBowInfo.fgIsNetRegistered == TRUE) { + + prGlueInfo->rBowInfo.fgIsNetRegistered = FALSE; + + bowUninit(prAdapter); + + if (netif_carrier_ok(prGlueInfo->rBowInfo.prDevHandler)) + netif_carrier_off(prGlueInfo->rBowInfo.prDevHandler); + + netif_tx_stop_all_queues(prGlueInfo->rBowInfo.prDevHandler); + + /* netdevice unregistration & free */ + unregister_netdev(prGlueInfo->rBowInfo.prDevHandler); + free_netdev(prGlueInfo->rBowInfo.prDevHandler); + prGlueInfo->rBowInfo.prDevHandler = NULL; + + return TRUE; + + } else { + return FALSE; + } +} + +#endif /* CFG_BOW_SEPARATE_DATA_PATH */ +#endif /* CFG_ENABLE_BT_OVER_WIFI */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_cfg80211.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_cfg80211.c new file mode 100644 index 0000000000000..4b9a592ccb786 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_cfg80211.c @@ -0,0 +1,7636 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** 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. + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "gl_os.h" +#include "debug.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "precomp.h" +#include +#include +#include +#include "gl_cfg80211.h" +#include "gl_vendor.h" +#include "gl_p2p_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 + ******************************************************************************* + */ + +/******************************************************************************* + * 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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct PARAM_OP_MODE rOpMode; + uint32_t u4BufLen; + struct GL_WPA_INFO *prWpaInfo; + uint8_t ucBssIndex = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + if (type == NL80211_IFTYPE_STATION) + rOpMode.eOpMode = NET_TYPE_INFRA; + else if (type == NL80211_IFTYPE_ADHOC) + rOpMode.eOpMode = NET_TYPE_IBSS; + else + return -EINVAL; + rOpMode.ucBssIdx = ucBssIndex; + rStatus = kalIoctl(prGlueInfo, wlanoidSetInfrastructureMode, + (void *)&rOpMode, sizeof(struct PARAM_OP_MODE), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "set infrastructure mode error:%x\n", + rStatus); + + prWpaInfo = aisGetWpaInfo(prGlueInfo->prAdapter, + ucBssIndex); + + /* reset wpa info */ + prWpaInfo->u4WpaVersion = + IW_AUTH_WPA_VERSION_DISABLED; + prWpaInfo->u4KeyMgmt = 0; + prWpaInfo->u4CipherGroup = IW_AUTH_CIPHER_NONE; + prWpaInfo->u4CipherPairwise = IW_AUTH_CIPHER_NONE; + prWpaInfo->u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; +#if CFG_SUPPORT_802_11W + prWpaInfo->u4Mfp = IW_AUTH_MFP_DISABLED; + prWpaInfo->ucRSNMfpCap = 0; +#endif + + ndev->ieee80211_ptr->iftype = type; + + 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) +{ + struct PARAM_KEY rKey; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + int32_t i4Rslt = -EINVAL; + uint32_t u4BufLen = 0; + uint8_t tmp1[8], tmp2[8]; + uint8_t ucBssIndex = 0; + const uint8_t aucBCAddr[] = BC_MAC_ADDR; + /* const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; */ + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + #if DBG + if (mac_addr) { + DBGLOG(RSN, INFO, + "keyIdx = %d pairwise = %d mac = " MACSTR "\n", + key_index, pairwise, MAC2STR(mac_addr)); + } else { + DBGLOG(RSN, INFO, "keyIdx = %d pairwise = %d null mac\n", + key_index, pairwise); + } + DBGLOG(RSN, INFO, "Cipher = %x\n", params->cipher); + DBGLOG_MEM8(RSN, INFO, params->key, params->key_len); +#endif + + kalMemZero(&rKey, sizeof(struct PARAM_KEY)); + + rKey.u4KeyIndex = key_index; + + if (params->cipher) { + switch (params->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + rKey.ucCipher = CIPHER_SUITE_WEP40; + break; + case WLAN_CIPHER_SUITE_WEP104: + rKey.ucCipher = CIPHER_SUITE_WEP104; + break; +#if 0 + case WLAN_CIPHER_SUITE_WEP128: + rKey.ucCipher = CIPHER_SUITE_WEP128; + break; +#endif + case WLAN_CIPHER_SUITE_TKIP: + rKey.ucCipher = CIPHER_SUITE_TKIP; + break; + case WLAN_CIPHER_SUITE_CCMP: + rKey.ucCipher = CIPHER_SUITE_CCMP; + break; +#if 0 + case WLAN_CIPHER_SUITE_GCMP: + rKey.ucCipher = CIPHER_SUITE_GCMP; + break; + case WLAN_CIPHER_SUITE_CCMP_256: + rKey.ucCipher = CIPHER_SUITE_CCMP256; + break; +#endif + case WLAN_CIPHER_SUITE_SMS4: + rKey.ucCipher = CIPHER_SUITE_WPI; + break; + case WLAN_CIPHER_SUITE_AES_CMAC: + rKey.ucCipher = CIPHER_SUITE_BIP; + break; + case WLAN_CIPHER_SUITE_GCMP_256: + rKey.ucCipher = CIPHER_SUITE_GCMP_256; + break; + case WLAN_CIPHER_SUITE_BIP_GMAC_256: + DBGLOG(RSN, INFO, + "[TODO] Set BIP-GMAC-256, SW should handle it ...\n"); + return 0; + default: + ASSERT(FALSE); + } + } + + if (pairwise) { + ASSERT(mac_addr); + rKey.u4KeyIndex |= BIT(31); + rKey.u4KeyIndex |= BIT(30); + COPY_MAC_ADDR(rKey.arBSSID, mac_addr); + } else { /* Group key */ + COPY_MAC_ADDR(rKey.arBSSID, aucBCAddr); + } + + if (params->key) { + if (params->key_len > sizeof(rKey.aucKeyMaterial)) + return -EINVAL; + + kalMemCopy(rKey.aucKeyMaterial, params->key, + params->key_len); + if (rKey.ucCipher == CIPHER_SUITE_TKIP) { + kalMemCopy(tmp1, ¶ms->key[16], 8); + kalMemCopy(tmp2, ¶ms->key[24], 8); + kalMemCopy(&rKey.aucKeyMaterial[16], tmp2, 8); + kalMemCopy(&rKey.aucKeyMaterial[24], tmp1, 8); + } + } + + rKey.ucBssIdx = ucBssIndex; + + rKey.u4KeyLength = params->key_len; + rKey.u4Length = OFFSET_OF(struct PARAM_KEY, aucKeyMaterial) + + rKey.u4KeyLength; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetAddKey, &rKey, + rKey.u4Length, FALSE, FALSE, TRUE, &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 *) + ) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if 1 + DBGLOG(INIT, INFO, "--> %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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct BSS_INFO *prBssInfo; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct PARAM_REMOVE_KEY rRemoveKey; + uint32_t u4BufLen = 0; + int32_t i4Rslt = -EINVAL; + uint8_t ucBssIndex = 0; + uint32_t waitRet = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + if (g_u4HaltFlag) { + DBGLOG_LIMITED(RSN, WARN, "wlan is halt, skip key deletion\n"); + return WLAN_STATUS_FAILURE; + } + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + if (mac_addr) { + DBGLOG_LIMITED(RSN, TRACE, + "keyIdx = %d pairwise = %d mac = " MACSTR "\n", + key_index, pairwise, MAC2STR(mac_addr)); + } else { + DBGLOG_LIMITED(RSN, TRACE, + "keyIdx = %d pairwise = %d null mac\n", + key_index, pairwise); + } + + kalMemZero(&rRemoveKey, sizeof(struct PARAM_REMOVE_KEY)); + rRemoveKey.u4KeyIndex = key_index; + rRemoveKey.u4Length = sizeof(struct PARAM_REMOVE_KEY); + if (mac_addr) { + COPY_MAC_ADDR(rRemoveKey.arBSSID, mac_addr); + rRemoveKey.u4KeyIndex |= BIT(30); + } + + if (prGlueInfo->prAdapter == NULL) + return i4Rslt; + + rRemoveKey.ucBssIdx = ucBssIndex; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, + ucBssIndex); +#if CFG_SUPPORT_802_11W + /* if encrypted deauth frame is in process, pending remove key */ + if (IS_BSS_INDEX_AIS(prGlueInfo->prAdapter, ucBssIndex) + && prBssInfo->encryptedDeauthIsInProcess == TRUE) { + waitRet = wait_for_completion_timeout( + &prBssInfo->rDeauthComp, + MSEC_TO_JIFFIES(1000)); + if (!waitRet) { + DBGLOG(RSN, WARN, "timeout\n"); + prBssInfo->encryptedDeauthIsInProcess = FALSE; + } else + DBGLOG(RSN, INFO, "complete\n"); + } +#endif + rStatus = kalIoctl(prGlueInfo, wlanoidSetRemoveKey, &rRemoveKey, + rRemoveKey.u4Length, FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG_LIMITED(RSN, WARN, "remove key error:%x\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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_DEFAULT_KEY rDefaultKey; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + int32_t i4Rst = -EINVAL; + uint32_t u4BufLen = 0; + u_int8_t fgDef = FALSE, fgMgtDef = FALSE; + uint8_t ucBssIndex = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + /* For STA, should wep set the default key !! */ + #if DBG + DBGLOG(RSN, INFO, + "keyIdx = %d unicast = %d multicast = %d\n", key_index, + unicast, multicast); +#endif + + rDefaultKey.ucKeyID = key_index; + rDefaultKey.ucUnicast = unicast; + rDefaultKey.ucMulticast = multicast; + if (rDefaultKey.ucUnicast && !rDefaultKey.ucMulticast) + return WLAN_STATUS_SUCCESS; + + if (rDefaultKey.ucUnicast && rDefaultKey.ucMulticast) + fgDef = TRUE; + + if (!rDefaultKey.ucUnicast && rDefaultKey.ucMulticast) + fgMgtDef = TRUE; + + rDefaultKey.ucBssIdx = ucBssIndex; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetDefaultKey, &rDefaultKey, + sizeof(struct PARAM_DEFAULT_KEY), + FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus == WLAN_STATUS_SUCCESS) + i4Rst = 0; + + return i4Rst; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for getting station information such as + * RSSI + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *ndev, const u8 *mac, + struct station_info *sinfo) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint8_t arBssid[PARAM_MAC_ADDR_LEN]; + uint32_t u4BufLen, u4Rate; + int32_t i4Rssi = 0; + struct PARAM_GET_STA_STATISTICS rQueryStaStatistics; + struct PARAM_LINK_SPEED_EX rLinkSpeed; + uint32_t u4TotalError; + struct net_device_stats *prDevStats; + uint8_t ucBssIndex = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_AIS(prGlueInfo->prAdapter, ucBssIndex)) + return -EINVAL; + + kalMemZero(arBssid, MAC_ADDR_LEN); + SET_IOCTL_BSSIDX(prGlueInfo->prAdapter, ucBssIndex); + wlanQueryInformation(prGlueInfo->prAdapter, wlanoidQueryBssid, + &arBssid[0], sizeof(arBssid), &u4BufLen); + + /* 1. check input MAC address */ + /* On Android O, this might be wlan0 address */ + if (UNEQUAL_MAC_ADDR(arBssid, mac) + && UNEQUAL_MAC_ADDR( + prGlueInfo->prAdapter->rWifiVar.aucMacAddress, 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 */ + if (kalGetMediaStateIndicated(prGlueInfo, ucBssIndex) != + MEDIA_STATE_CONNECTED) { + /* not connected */ + DBGLOG(REQ, WARN, "not yet connected\n"); + return 0; + } + + rStatus = kalIoctlByBssIdx(prGlueInfo, + wlanoidQueryLinkSpeedEx, &rLinkSpeed, + sizeof(rLinkSpeed), TRUE, FALSE, FALSE, + &u4BufLen, ucBssIndex); + +#if defined(CFG_REPORT_MAX_TX_RATE) && (CFG_REPORT_MAX_TX_RATE == 1) + /*rewrite LinkSpeed with Max LinkSpeed*/ + rStatus = kalIoctlByBssIdx(prGlueInfo, + wlanoidQueryMaxLinkSpeed, &rLinkSpeed, + sizeof(rLinkSpeed), TRUE, FALSE, FALSE, + &u4BufLen, ucBssIndex); +#endif /* CFG_REPORT_MAX_TX_RATE */ + + if (IS_BSS_INDEX_VALID(ucBssIndex)) { + u4Rate = rLinkSpeed.rLq[ucBssIndex].u2LinkSpeed; + i4Rssi = rLinkSpeed.rLq[ucBssIndex].cRssi; + } +#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE + sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); +#else + sinfo->filled |= STATION_INFO_TX_BITRATE; +#endif + if ((rStatus != WLAN_STATUS_SUCCESS) || (u4Rate == 0)) { + /* unable to retrieve link speed */ + DBGLOG(REQ, WARN, "last link speed\n"); + sinfo->txrate.legacy = prGlueInfo->u4LinkSpeedCache[ucBssIndex]; + } else { + /* convert from 100bps to 100kbps */ + sinfo->txrate.legacy = u4Rate / 1000; + prGlueInfo->u4LinkSpeedCache[ucBssIndex] = u4Rate / 1000; + } + +#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE + sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); +#else + sinfo->filled |= STATION_INFO_SIGNAL; +#endif + + if (rStatus != WLAN_STATUS_SUCCESS || i4Rssi == 0) { + DBGLOG(REQ, WARN, + "Query RSSI failed, use last RSSI %d\n", + prGlueInfo->i4RssiCache[ucBssIndex]); + sinfo->signal = prGlueInfo->i4RssiCache[ucBssIndex] ? + prGlueInfo->i4RssiCache[ucBssIndex] : + PARAM_WHQL_RSSI_INITIAL_DBM; + } else if (i4Rssi == PARAM_WHQL_RSSI_MIN_DBM || + i4Rssi == PARAM_WHQL_RSSI_MAX_DBM) { + DBGLOG(REQ, WARN, + "RSSI abnormal, use last RSSI %d\n", + prGlueInfo->i4RssiCache[ucBssIndex]); + sinfo->signal = prGlueInfo->i4RssiCache[ucBssIndex] ? + prGlueInfo->i4RssiCache[ucBssIndex] : i4Rssi; + } else { + sinfo->signal = i4Rssi; /* dBm */ + prGlueInfo->i4RssiCache[ucBssIndex] = i4Rssi; + } + + /* Get statistics from net_dev */ + prDevStats = (struct net_device_stats *)kalGetStats(ndev); + + if (prDevStats) { + /* 4. fill RX_PACKETS */ +#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE + sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS); + sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES64); +#else + sinfo->filled |= STATION_INFO_RX_PACKETS; + sinfo->filled |= NL80211_STA_INFO_RX_BYTES64; +#endif + sinfo->rx_packets = prDevStats->rx_packets; + sinfo->rx_bytes = prDevStats->rx_bytes; + + /* 5. fill TX_PACKETS */ +#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE + sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS); + sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES64); +#else + sinfo->filled |= STATION_INFO_TX_PACKETS; + sinfo->filled |= NL80211_STA_INFO_TX_BYTES64; +#endif + sinfo->tx_packets = prDevStats->tx_packets; + sinfo->tx_bytes = prDevStats->tx_bytes; + + /* 6. fill TX_FAILED */ + kalMemZero(&rQueryStaStatistics, + sizeof(rQueryStaStatistics)); + COPY_MAC_ADDR(rQueryStaStatistics.aucMacAddr, arBssid); + rQueryStaStatistics.ucReadClear = TRUE; + + rStatus = kalIoctlByBssIdx(prGlueInfo, + wlanoidQueryStaStatistics, + &rQueryStaStatistics, + sizeof(rQueryStaStatistics), + TRUE, FALSE, TRUE, &u4BufLen, ucBssIndex); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, + "link speed=%u, rssi=%d, unable to retrieve link speed,status=%u\n", + sinfo->txrate.legacy, sinfo->signal, rStatus); + } else { + DBGLOG(REQ, INFO, + "link speed=%u, rssi=%d, BSSID:[" MACSTR + "], TxFail=%u, TxTimeOut=%u, TxOK=%u, RxOK=%u\n", + sinfo->txrate.legacy, sinfo->signal, + MAC2STR(arBssid), + rQueryStaStatistics.u4TxFailCount, + rQueryStaStatistics.u4TxLifeTimeoutCount, + sinfo->tx_packets, sinfo->rx_packets); + + u4TotalError = rQueryStaStatistics.u4TxFailCount + + rQueryStaStatistics.u4TxLifeTimeoutCount; + prDevStats->tx_errors += u4TotalError; + } +#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE + sinfo->filled |= BIT(NL80211_STA_INFO_TX_FAILED); +#else + sinfo->filled |= STATION_INFO_TX_FAILED; +#endif + sinfo->tx_failed = prDevStats->tx_errors; + } + + return 0; +} +#else +int mtk_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac, + struct station_info *sinfo) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint8_t arBssid[PARAM_MAC_ADDR_LEN]; + uint32_t u4BufLen, u4Rate; + int32_t i4Rssi; + struct PARAM_GET_STA_STATISTICS rQueryStaStatistics; + struct PARAM_LINK_SPEED_EX rLinkSpeed; + uint32_t u4TotalError; + struct net_device_stats *prDevStats; + uint8_t ucBssIndex = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_AIS(prGlueInfo->prAdapter, ucBssIndex)) + return -EINVAL; + + kalMemZero(arBssid, MAC_ADDR_LEN); + SET_IOCTL_BSSIDX(prGlueInfo->prAdapter, ucBssIndex); + 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 */ + if (kalGetMediaStateIndicated(prGlueInfo, ucBssIndex) != + MEDIA_STATE_CONNECTED) { + /* not connected */ + DBGLOG(REQ, WARN, "not yet connected\n"); + } else { +#if defined(CFG_REPORT_MAX_TX_RATE) && (CFG_REPORT_MAX_TX_RATE == 1) + rStatus = kalIoctlByBssIdx(prGlueInfo, wlanoidQueryMaxLinkSpeed, + &u4Rate, sizeof(u4Rate), TRUE, FALSE, FALSE, + &u4BufLen, + ucBssIndex); +#else + rStatus = kalIoctlByBssIdx(prGlueInfo, + wlanoidQueryLinkSpeedEx, + &rLinkSpeed, sizeof(rLinkSpeed), + TRUE, FALSE, FALSE, + &u4BufLen, ucBssIndex); + if (ucBssIndex < BSSID_NUM) + u4Rate = rLinkSpeed.rLq[ucBssIndex].u2LinkSpeed; +#endif /* CFG_REPORT_MAX_TX_RATE */ + + sinfo->filled |= STATION_INFO_TX_BITRATE; + + if ((rStatus != WLAN_STATUS_SUCCESS) || (u4Rate == 0)) { + /* unable to retrieve link speed */ + DBGLOG(REQ, WARN, "last link speed\n"); + sinfo->txrate.legacy = + prGlueInfo->u4LinkSpeedCache[ucBssIndex]; + } else { + /* convert from 100bps to 100kbps */ + sinfo->txrate.legacy = u4Rate / 1000; + prGlueInfo->u4LinkSpeedCache[ucBssIndex] = + u4Rate / 1000; + } + } + + /* 3. fill RSSI */ + if (kalGetMediaStateIndicated(prGlueInfo, ucBssIndex) != + MEDIA_STATE_CONNECTED) { + /* not connected */ + DBGLOG(REQ, WARN, "not yet connected\n"); + } else { + rStatus = kalIoctlByBssIdx(prGlueInfo, + wlanoidQueryRssi, + &rLinkSpeed, sizeof(rLinkSpeed), + TRUE, FALSE, FALSE, + &u4BufLen, ucBssIndex); + if (IS_BSS_INDEX_VALID(ucBssIndex)) + i4Rssi = rLinkSpeed.rLq[ucBssIndex].cRssi; + + sinfo->filled |= STATION_INFO_SIGNAL; + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, + "Query RSSI failed, use last RSSI %d\n", + prGlueInfo->i4RssiCache[ucBssIndex]); + sinfo->signal = prGlueInfo->i4RssiCache[ucBssIndex] ? + prGlueInfo->i4RssiCache[ucBssIndex] : + PARAM_WHQL_RSSI_INITIAL_DBM; + } else if (i4Rssi == PARAM_WHQL_RSSI_MIN_DBM || + i4Rssi == PARAM_WHQL_RSSI_MAX_DBM) { + DBGLOG(REQ, WARN, + "RSSI abnormal, use last RSSI %d\n", + prGlueInfo->i4RssiCache[ucBssIndex]); + sinfo->signal = prGlueInfo->i4RssiCache[ucBssIndex] ? + prGlueInfo->i4RssiCache[ucBssIndex] : i4Rssi; + } else { + sinfo->signal = i4Rssi; /* dBm */ + prGlueInfo->i4RssiCache[ucBssIndex] = i4Rssi; + } + } + + /* Get statistics from net_dev */ + prDevStats = (struct net_device_stats *)kalGetStats(ndev); + if (prDevStats) { + /* 4. fill RX_PACKETS */ + sinfo->filled |= STATION_INFO_RX_PACKETS; + sinfo->rx_packets = prDevStats->rx_packets; + + /* 5. fill TX_PACKETS */ + sinfo->filled |= STATION_INFO_TX_PACKETS; + sinfo->tx_packets = prDevStats->tx_packets; + + /* 6. fill TX_FAILED */ + kalMemZero(&rQueryStaStatistics, + sizeof(rQueryStaStatistics)); + COPY_MAC_ADDR(rQueryStaStatistics.aucMacAddr, arBssid); + rQueryStaStatistics.ucReadClear = TRUE; + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryStaStatistics, + &rQueryStaStatistics, + sizeof(rQueryStaStatistics), + TRUE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, + "link speed=%u, rssi=%d, unable to get sta statistics: status=%u\n", + sinfo->txrate.legacy, sinfo->signal, rStatus); + } else { + DBGLOG(REQ, INFO, + "link speed=%u, rssi=%d, BSSID=[" MACSTR + "], TxFailCount=%d, LifeTimeOut=%d\n", + sinfo->txrate.legacy, sinfo->signal, + MAC2STR(arBssid), + rQueryStaStatistics.u4TxFailCount, + rQueryStaStatistics.u4TxLifeTimeoutCount); + + u4TotalError = rQueryStaStatistics.u4TxFailCount + + rQueryStaStatistics.u4TxLifeTimeoutCount; + prDevStats->tx_errors += u4TotalError; + } + sinfo->filled |= STATION_INFO_TX_FAILED; + sinfo->tx_failed = prDevStats->tx_errors; + } + + return 0; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for getting statistics for Link layer + * statistics + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_get_link_statistics(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac, + struct station_info *sinfo) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint8_t arBssid[PARAM_MAC_ADDR_LEN]; + uint32_t u4BufLen; + struct PARAM_LINK_SPEED_EX rLinkSpeed; + struct PARAM_GET_STA_STATISTICS rQueryStaStatistics; + struct PARAM_GET_BSS_STATISTICS rQueryBssStatistics; + struct net_device_stats *prDevStats; + uint8_t ucBssIndex = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_AIS(prGlueInfo->prAdapter, ucBssIndex)) + return -EINVAL; + + kalMemZero(arBssid, MAC_ADDR_LEN); + SET_IOCTL_BSSIDX(prGlueInfo->prAdapter, ucBssIndex); + 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 RSSI */ + if (kalGetMediaStateIndicated(prGlueInfo, ucBssIndex) != + MEDIA_STATE_CONNECTED) { + /* not connected */ + DBGLOG(REQ, WARN, "not yet connected\n"); + } else { + rStatus = kalIoctlByBssIdx + (prGlueInfo, + wlanoidQueryRssi, + &rLinkSpeed, sizeof(rLinkSpeed), + TRUE, FALSE, FALSE, + &u4BufLen, ucBssIndex); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "unable to retrieve rssi\n"); + } + + /* Get statistics from net_dev */ + prDevStats = (struct net_device_stats *)kalGetStats(ndev); + + /*3. get link layer statistics from Driver and FW */ + if (prDevStats) { + /* 3.1 get per-STA link statistics */ + kalMemZero(&rQueryStaStatistics, + sizeof(rQueryStaStatistics)); + COPY_MAC_ADDR(rQueryStaStatistics.aucMacAddr, arBssid); + rQueryStaStatistics.ucLlsReadClear = + FALSE; /* dont clear for get BSS statistic */ + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryStaStatistics, + &rQueryStaStatistics, + sizeof(rQueryStaStatistics), + TRUE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, + "unable to retrieve per-STA link statistics\n"); + + /*3.2 get per-BSS link statistics */ + if (rStatus == WLAN_STATUS_SUCCESS) { + kalMemZero(&rQueryBssStatistics, + sizeof(rQueryBssStatistics)); + rQueryBssStatistics.ucBssIndex = ucBssIndex; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryBssStatistics, + &rQueryBssStatistics, + sizeof(rQueryBssStatistics), + TRUE, FALSE, TRUE, &u4BufLen); + } else { + DBGLOG(REQ, WARN, + "unable to retrieve per-BSS link statistics\n"); + } + + } + + 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 cfg80211_scan_request *request) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint32_t i, j, u4BufLen; + struct PARAM_SCAN_REQUEST_ADV *prScanRequest; + uint32_t num_ssid = 0; + uint32_t old_num_ssid = 0; + uint32_t u4ValidIdx = 0; + uint32_t wildcard_flag = 0; +#if (CFG_SUPPORT_QA_TOOL == 1) || (CFG_SUPPORT_LOWLATENCY_MODE == 1) + struct ADAPTER *prAdapter = NULL; +#endif + uint8_t ucBssIndex = 0; + GLUE_SPIN_LOCK_DECLARATION(); + + if (kalIsResetting()) + return -EBUSY; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + if (!prGlueInfo) { + DBGLOG(REQ, ERROR, "prGlueInfo is NULL"); + return -EINVAL; + } + + ucBssIndex = wlanGetBssIdx(request->wdev->netdev); + if (!IS_BSS_INDEX_AIS(prGlueInfo->prAdapter, ucBssIndex)) + return -EINVAL; + +#if (CFG_SUPPORT_QA_TOOL == 1) || (CFG_SUPPORT_LOWLATENCY_MODE == 1) + prAdapter = prGlueInfo->prAdapter; + if (prGlueInfo->prAdapter == NULL) { + DBGLOG(REQ, ERROR, "prGlueInfo->prAdapter is NULL"); + return -EINVAL; + } +#endif + + if (wlanIsChipAssert(prGlueInfo->prAdapter)) + return -EBUSY; + +#if CFG_SUPPORT_QA_TOOL + if (prAdapter->fgTestMode) { + DBGLOG(REQ, ERROR, + "directly return scan done, TestMode running\n"); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + kalCfg80211ScanDone(request, FALSE); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + return 0; + } + if (prAdapter->rIcapInfo.eIcapState != ICAP_STATE_INIT) { + DBGLOG(REQ, ERROR, "skip scan, ICAP In State(%d)\n", + prAdapter->rIcapInfo.eIcapState); + return -EBUSY; + } +#endif + + kalScanReqLog(request); + + /* check if there is any pending scan/sched_scan not yet finished */ + if (prGlueInfo->prScanRequest != NULL) { + DBGLOG(REQ, ERROR, "prGlueInfo->prScanRequest != NULL\n"); + return -EBUSY; + } + +#if CFG_SUPPORT_LOWLATENCY_MODE + if (!prGlueInfo->prAdapter->fgEnCfg80211Scan +#if CFG_SUPPORT_SCAN_EXT_FLAG + && (prGlueInfo->u4ScanExtFlag != TRUE) +#endif + && MEDIA_STATE_CONNECTED + == kalGetMediaStateIndicated(prGlueInfo, ucBssIndex)) { + DBGLOG(REQ, INFO, + "mtk_cfg80211_scan LowLatency reject scan\n"); + return -EBUSY; + } +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ +#if CFG_SUPPORT_SCAN_EXT_FLAG + prGlueInfo->u4ScanExtFlag = 0; +#endif +#if CFG_SUPPORT_SCAN_CACHE_RESULT + prGlueInfo->scanCache.prGlueInfo = prGlueInfo; + prGlueInfo->scanCache.prRequest = request; + prGlueInfo->scanCache.n_channels = (uint32_t) request->n_channels; + prGlueInfo->scanCache.ucBssIndex = ucBssIndex; + prGlueInfo->scanCache.u4Flags = request->flags; + if (isScanCacheDone(&prGlueInfo->scanCache) == TRUE) + return 0; +#endif /* CFG_SUPPORT_SCAN_CACHE_RESULT */ + + prScanRequest = kalMemAlloc(sizeof(struct PARAM_SCAN_REQUEST_ADV), + VIR_MEM_TYPE); + if (prScanRequest == NULL) { + DBGLOG(REQ, ERROR, "alloc scan request fail\n"); + return -ENOMEM; + + } + kalMemZero(prScanRequest, + sizeof(struct PARAM_SCAN_REQUEST_ADV)); + + if (request->n_ssids == 0) { + prScanRequest->u4SsidNum = 0; + prScanRequest->ucScanType = SCAN_TYPE_PASSIVE_SCAN; + } else if ((request->ssids) && (request->n_ssids > 0) + && (request->n_ssids <= (SCN_SSID_MAX_NUM + 1))) { + num_ssid = (uint32_t)request->n_ssids; + old_num_ssid = (uint32_t)request->n_ssids; + u4ValidIdx = 0; + for (i = 0; i < request->n_ssids; i++) { + if ((request->ssids[i].ssid[0] == 0) + || (request->ssids[i].ssid_len == 0)) { + /* remove if this is a wildcard scan */ + num_ssid--; + wildcard_flag |= (1 << i); + DBGLOG(REQ, TRACE, "i=%d, wildcard scan\n", i); + continue; + } + COPY_SSID(prScanRequest->rSsid[u4ValidIdx].aucSsid, + prScanRequest->rSsid[u4ValidIdx].u4SsidLen, + request->ssids[i].ssid, + request->ssids[i].ssid_len); + if (prScanRequest->rSsid[u4ValidIdx].u4SsidLen > + ELEM_MAX_LEN_SSID) { + prScanRequest->rSsid[u4ValidIdx].u4SsidLen = + ELEM_MAX_LEN_SSID; + } + DBGLOG(REQ, TRACE, + "i=%d, u4ValidIdx=%d, Ssid=%s, SsidLen=%d\n", + i, u4ValidIdx, + HIDE(prScanRequest->rSsid[u4ValidIdx].aucSsid), + prScanRequest->rSsid[u4ValidIdx].u4SsidLen); + + u4ValidIdx++; + if (u4ValidIdx == SCN_SSID_MAX_NUM) { + DBGLOG(REQ, TRACE, "SCN_SSID_MAX_NUM\n"); + break; + } + } + /* real SSID number to firmware */ + prScanRequest->u4SsidNum = u4ValidIdx; + prScanRequest->ucScanType = SCAN_TYPE_ACTIVE_SCAN; + } else { + DBGLOG(REQ, ERROR, "request->n_ssids:%d\n", + request->n_ssids); + kalMemFree(prScanRequest, + sizeof(struct PARAM_SCAN_REQUEST_ADV), VIR_MEM_TYPE); + return -EINVAL; + } + + /* Set channel info */ + if (request->n_channels > MAXIMUM_OPERATION_CHANNEL_LIST) { + prScanRequest->u4ChannelNum = 0; + DBGLOG(REQ, INFO, + "Channel list %u exceed maximum support.\n", + request->n_channels); + } else { + j = 0; + for (i = 0; i < request->n_channels; i++) { + uint32_t u4channel = + nicFreq2ChannelNum(request->channels[i]->center_freq * + 1000); + if (u4channel == 0) { + DBGLOG(REQ, WARN, "Wrong Channel[%d] freq=%u\n", + i, request->channels[i]->center_freq); + continue; + } + prScanRequest->arChannel[j].ucChannelNum = u4channel; + switch ((request->channels[i])->band) { + case KAL_BAND_2GHZ: + prScanRequest->arChannel[j].eBand = BAND_2G4; + break; + case KAL_BAND_5GHZ: + prScanRequest->arChannel[j].eBand = BAND_5G; + break; + default: + DBGLOG(REQ, WARN, "UNKNOWN Band %d(chnl=%u)\n", + request->channels[i]->band, + u4channel); + prScanRequest->arChannel[j].eBand = BAND_NULL; + break; + } + j++; + } + prScanRequest->u4ChannelNum = j; + } + + if (kalScanParseRandomMac(request->wdev->netdev, + request, prScanRequest->aucRandomMac)) { + prScanRequest->ucScnFuncMask |= ENUM_SCN_RANDOM_MAC_EN; + } + + if (request->ie_len > 0) { + prScanRequest->u4IELength = request->ie_len; + prScanRequest->pucIE = (uint8_t *) (request->ie); + } + +#define TEMP_LOG_TEMPLATE "n_ssid=(%u->%u) n_channel(%u==>%u) " \ + "wildcard=0x%X flag=0x%x random_mac=" MACSTR "\n" + DBGLOG(REQ, INFO, TEMP_LOG_TEMPLATE, + request->n_ssids, num_ssid, request->n_channels, + prScanRequest->u4ChannelNum, wildcard_flag, + request->flags, + MAC2STR(prScanRequest->aucRandomMac)); +#undef TEMP_LOG_TEMPLATE + + prScanRequest->ucBssIndex = ucBssIndex; + prScanRequest->u4Flags = request->flags; + prGlueInfo->prScanRequest = request; + rStatus = kalIoctl(prGlueInfo, wlanoidSetBssidListScanAdv, + prScanRequest, sizeof(struct PARAM_SCAN_REQUEST_ADV), + FALSE, FALSE, FALSE, &u4BufLen); + + kalMemFree(prScanRequest, + sizeof(struct PARAM_SCAN_REQUEST_ADV), VIR_MEM_TYPE); + if (rStatus != WLAN_STATUS_SUCCESS) { + prGlueInfo->prScanRequest = NULL; + DBGLOG(REQ, WARN, "scan error:%x\n", rStatus); + return -EINVAL; + } + + return 0; +} +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for abort an ongoing scan. The driver + * shall indicate the status of the scan through cfg80211_scan_done() + * + * @param wiphy - pointer of wireless hardware description + * wdev - pointer of wireless device state + * + */ +/*----------------------------------------------------------------------------*/ +void mtk_cfg80211_abort_scan(struct wiphy *wiphy, + struct wireless_dev *wdev) +{ + uint32_t u4SetInfoLen = 0; + uint32_t rStatus; + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t ucBssIndex = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + ucBssIndex = wlanGetBssIdx(wdev->netdev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return; + + scanlog_dbg(LOG_SCAN_ABORT_REQ_K2D, INFO, "mtk_cfg80211_abort_scan\n"); + + rStatus = kalIoctlByBssIdx(prGlueInfo, + wlanoidAbortScan, + NULL, 1, FALSE, FALSE, TRUE, &u4SetInfoLen, + ucBssIndex); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, ERROR, "wlanoidAbortScan fail 0x%x\n", rStatus); +} + +static uint8_t 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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint32_t u4BufLen; + enum ENUM_WEP_STATUS eEncStatus; + enum ENUM_PARAM_AUTH_MODE eAuthMode; + uint32_t cipher; + struct PARAM_CONNECT rNewSsid; + struct PARAM_OP_MODE rOpMode; + uint32_t i, u4AkmSuite = 0; + struct DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY + *prEntry; + struct CONNECTION_SETTINGS *prConnSettings = NULL; +#if CFG_SUPPORT_REPLAY_DETECTION + struct GL_DETECT_REPLAY_INFO *prDetRplyInfo = NULL; +#endif + struct GL_WPA_INFO *prWpaInfo; + struct IEEE_802_11_MIB *prMib; +#if CFG_SUPPORT_PASSPOINT + struct HS20_INFO *prHS20Info; +#endif + uint8_t ucBssIndex = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_AIS(prGlueInfo->prAdapter, ucBssIndex)) + return -EINVAL; + + DBGLOG(REQ, INFO, "[wlan%d] mtk_cfg80211_connect %p %zu\n", + ucBssIndex, sme->ie, sme->ie_len); + + prConnSettings = + aisGetConnSettings(prGlueInfo->prAdapter, + ucBssIndex); + if (prConnSettings->eOPMode > + NET_TYPE_AUTO_SWITCH) + rOpMode.eOpMode = NET_TYPE_AUTO_SWITCH; + else + rOpMode.eOpMode = prConnSettings->eOPMode; + rOpMode.ucBssIdx = ucBssIndex; + rStatus = kalIoctl(prGlueInfo, wlanoidSetInfrastructureMode, + (void *)&rOpMode, sizeof(struct PARAM_OP_MODE), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, + "wlanoidSetInfrastructureMode fail 0x%x\n", rStatus); + return -EFAULT; + } + + /* after set operation mode, key table are cleared */ + +#if CFG_SUPPORT_REPLAY_DETECTION + /* reset Detect replay information */ + prDetRplyInfo = aisGetDetRplyInfo(prGlueInfo->prAdapter, + ucBssIndex); + kalMemZero(prDetRplyInfo, sizeof(struct GL_DETECT_REPLAY_INFO)); +#endif + + prWpaInfo = aisGetWpaInfo(prGlueInfo->prAdapter, + ucBssIndex); + /* <1> Reset WPA info */ + prWpaInfo->u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + prWpaInfo->u4KeyMgmt = 0; + prWpaInfo->u4CipherGroup = IW_AUTH_CIPHER_NONE; + prWpaInfo->u4CipherPairwise = IW_AUTH_CIPHER_NONE; + prWpaInfo->u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; + prWpaInfo->fgPrivacyInvoke = FALSE; +#if CFG_SUPPORT_802_11W + prWpaInfo->u4Mfp = IW_AUTH_MFP_DISABLED; + prWpaInfo->ucRSNMfpCap = RSN_AUTH_MFP_DISABLED; +#endif + + if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) + prWpaInfo->u4WpaVersion = IW_AUTH_WPA_VERSION_WPA; + else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) + prWpaInfo->u4WpaVersion = + IW_AUTH_WPA_VERSION_WPA2; + else + prWpaInfo->u4WpaVersion = + IW_AUTH_WPA_VERSION_DISABLED; + + DBGLOG(REQ, INFO, + "sme->auth_type=%x, sme->crypto.wpa_versions=%x", + sme->auth_type, sme->crypto.wpa_versions); + + switch (sme->auth_type) { + case NL80211_AUTHTYPE_OPEN_SYSTEM: + prWpaInfo->u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; + break; + case NL80211_AUTHTYPE_SHARED_KEY: + prWpaInfo->u4AuthAlg = IW_AUTH_ALG_SHARED_KEY; + break; + case NL80211_AUTHTYPE_FT: + prWpaInfo->u4AuthAlg = IW_AUTH_ALG_FT; + break; + case NL80211_AUTHTYPE_SAE: + prWpaInfo->u4AuthAlg = IW_AUTH_ALG_SAE; + /* To prevent FWKs asks connect without AKM Suite */ + eAuthMode = AUTH_MODE_WPA3_SAE; + u4AkmSuite = RSN_AKM_SUITE_SAE; + break; + default: + prWpaInfo->u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM | + IW_AUTH_ALG_SHARED_KEY; + break; + } + + if (sme->crypto.n_ciphers_pairwise) { + DBGLOG(RSN, INFO, "[wlan] cipher pairwise (%x)\n", + sme->crypto.ciphers_pairwise[0]); + + prConnSettings->rRsnInfo + .au4PairwiseKeyCipherSuite[0] = sme->crypto.ciphers_pairwise[0]; + switch (sme->crypto.ciphers_pairwise[0]) { + case WLAN_CIPHER_SUITE_WEP40: + prWpaInfo->u4CipherPairwise = + IW_AUTH_CIPHER_WEP40; + break; + case WLAN_CIPHER_SUITE_WEP104: + prWpaInfo->u4CipherPairwise = + IW_AUTH_CIPHER_WEP104; + break; + case WLAN_CIPHER_SUITE_TKIP: + prWpaInfo->u4CipherPairwise = + IW_AUTH_CIPHER_TKIP; + break; + case WLAN_CIPHER_SUITE_CCMP: + prWpaInfo->u4CipherPairwise = + IW_AUTH_CIPHER_CCMP; + break; + case WLAN_CIPHER_SUITE_AES_CMAC: + prWpaInfo->u4CipherPairwise = + IW_AUTH_CIPHER_CCMP; + break; + case WLAN_CIPHER_SUITE_BIP_GMAC_256: + prWpaInfo->u4CipherPairwise = + IW_AUTH_CIPHER_GCMP256; + break; + case WLAN_CIPHER_SUITE_GCMP_256: + prWpaInfo->u4CipherPairwise = + IW_AUTH_CIPHER_GCMP256; + break; + case WLAN_CIPHER_SUITE_NO_GROUP_ADDR: + DBGLOG(REQ, INFO, "WLAN_CIPHER_SUITE_NO_GROUP_ADDR\n"); + break; + default: + DBGLOG(REQ, WARN, "invalid cipher pairwise (%d)\n", + sme->crypto.ciphers_pairwise[0]); + return -EINVAL; + } + } + + if (sme->crypto.cipher_group) { + prConnSettings->rRsnInfo + .u4GroupKeyCipherSuite = sme->crypto.cipher_group; + switch (sme->crypto.cipher_group) { + case WLAN_CIPHER_SUITE_WEP40: + prWpaInfo->u4CipherGroup = + IW_AUTH_CIPHER_WEP40; + break; + case WLAN_CIPHER_SUITE_WEP104: + prWpaInfo->u4CipherGroup = + IW_AUTH_CIPHER_WEP104; + break; + case WLAN_CIPHER_SUITE_TKIP: + prWpaInfo->u4CipherGroup = + IW_AUTH_CIPHER_TKIP; + break; + case WLAN_CIPHER_SUITE_CCMP: + prWpaInfo->u4CipherGroup = + IW_AUTH_CIPHER_CCMP; + break; + case WLAN_CIPHER_SUITE_AES_CMAC: + prWpaInfo->u4CipherGroup = + IW_AUTH_CIPHER_CCMP; + break; + case WLAN_CIPHER_SUITE_BIP_GMAC_256: + prWpaInfo->u4CipherGroup = + IW_AUTH_CIPHER_GCMP256; + break; + case WLAN_CIPHER_SUITE_GCMP_256: + prWpaInfo->u4CipherGroup = + IW_AUTH_CIPHER_GCMP256; + break; + case WLAN_CIPHER_SUITE_NO_GROUP_ADDR: + break; + default: + DBGLOG(REQ, WARN, "invalid cipher group (%d)\n", + sme->crypto.cipher_group); + return -EINVAL; + } + } + + if (sme->crypto.n_akm_suites) { + DBGLOG(REQ, INFO, "n_akm_suites=%x, akm_suites=%x", + sme->crypto.n_akm_suites, + sme->crypto.akm_suites[0]); + prConnSettings->rRsnInfo + .au4AuthKeyMgtSuite[0] = sme->crypto.akm_suites[0]; + if (prWpaInfo->u4WpaVersion == + IW_AUTH_WPA_VERSION_WPA) { + switch (sme->crypto.akm_suites[0]) { + case WLAN_AKM_SUITE_8021X: + eAuthMode = AUTH_MODE_WPA; + u4AkmSuite = WPA_AKM_SUITE_802_1X; + break; + case WLAN_AKM_SUITE_PSK: + eAuthMode = AUTH_MODE_WPA_PSK; + u4AkmSuite = WPA_AKM_SUITE_PSK; + break; + default: + DBGLOG(REQ, WARN, "invalid Akm Suite (%08x)\n", + sme->crypto.akm_suites[0]); + return -EINVAL; + } + } else if (prWpaInfo->u4WpaVersion == + IW_AUTH_WPA_VERSION_WPA2) { + switch (sme->crypto.akm_suites[0]) { + case WLAN_AKM_SUITE_8021X: + eAuthMode = AUTH_MODE_WPA2; + u4AkmSuite = RSN_AKM_SUITE_802_1X; + break; + case WLAN_AKM_SUITE_PSK: + eAuthMode = AUTH_MODE_WPA2_PSK; + u4AkmSuite = RSN_AKM_SUITE_PSK; + break; +#if CFG_SUPPORT_802_11R + case WLAN_AKM_SUITE_FT_8021X: + eAuthMode = AUTH_MODE_WPA2_FT; + u4AkmSuite = RSN_AKM_SUITE_FT_802_1X; + break; + case WLAN_AKM_SUITE_FT_PSK: + eAuthMode = AUTH_MODE_WPA2_FT_PSK; + u4AkmSuite = RSN_AKM_SUITE_FT_PSK; + break; +#endif +#if CFG_SUPPORT_802_11W + /* Notice:: Need kernel patch!! */ + case WLAN_AKM_SUITE_8021X_SHA256: + eAuthMode = AUTH_MODE_WPA2; + u4AkmSuite = RSN_AKM_SUITE_802_1X_SHA256; + break; + case WLAN_AKM_SUITE_PSK_SHA256: + eAuthMode = AUTH_MODE_WPA2_PSK; + u4AkmSuite = RSN_AKM_SUITE_PSK_SHA256; + break; +#endif +#if CFG_SUPPORT_PASSPOINT + case WLAN_AKM_SUITE_OSEN: + eAuthMode = AUTH_MODE_WPA_OSEN; + u4AkmSuite = WFA_AKM_SUITE_OSEN; + break; +#endif + case WLAN_AKM_SUITE_SAE: + if (sme->auth_type == NL80211_AUTHTYPE_SAE) + eAuthMode = AUTH_MODE_WPA3_SAE; + else + eAuthMode = AUTH_MODE_OPEN; + u4AkmSuite = RSN_AKM_SUITE_SAE; + break; + + case WLAN_AKM_SUITE_OWE: + eAuthMode = AUTH_MODE_WPA3_OWE; + u4AkmSuite = RSN_AKM_SUITE_OWE; + break; + default: + DBGLOG(REQ, WARN, "invalid Akm Suite (%d)\n", + sme->crypto.akm_suites[0]); + return -EINVAL; + } + } + } + + DBGLOG(REQ, INFO, "u4WpaVersion=%d, u4AuthAlg=%d", + prWpaInfo->u4WpaVersion, + prWpaInfo->u4AuthAlg); + if (prWpaInfo->u4WpaVersion == + IW_AUTH_WPA_VERSION_DISABLED) { + switch (prWpaInfo->u4AuthAlg) { + case IW_AUTH_ALG_FT: + DBGLOG(REQ, INFO, "FT: Non-RSN FT connect\n"); + eAuthMode = AUTH_MODE_OPEN; + break; + case IW_AUTH_ALG_OPEN_SYSTEM: + eAuthMode = AUTH_MODE_OPEN; + break; + default: + eAuthMode = AUTH_MODE_AUTO_SWITCH; + break; + } + } + + prWpaInfo->fgPrivacyInvoke = sme->privacy; + prConnSettings->fgWpsActive = FALSE; + +#if CFG_SUPPORT_PASSPOINT + prHS20Info = aisGetHS20Info(prGlueInfo->prAdapter, + ucBssIndex); + prHS20Info->fgConnectHS20AP = FALSE; +#endif /* CFG_SUPPORT_PASSPOINT */ + + prConnSettings->non_wfa_vendor_ie_len = 0; + if (sme->ie && sme->ie_len > 0) { + uint32_t rStatus; + uint32_t u4BufLen; + uint8_t *prDesiredIE = NULL; + uint8_t *pucIEStart = (uint8_t *)sme->ie; +#if CFG_SUPPORT_WAPI + rStatus = kalIoctlByBssIdx(prGlueInfo, wlanoidSetWapiAssocInfo, + pucIEStart, sme->ie_len, FALSE, FALSE, FALSE, + &u4BufLen, + ucBssIndex); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, TRACE, + "[wapi] wapi not support due to set wapi assoc info error:%x\n", + rStatus); +#endif +#if CFG_SUPPORT_PASSPOINT + if (wextSrchDesiredHS20IE(pucIEStart, sme->ie_len, + (uint8_t **) &prDesiredIE)) { + rStatus = kalIoctlByBssIdx(prGlueInfo, + wlanoidSetHS20Info, + prDesiredIE, IE_SIZE(prDesiredIE), + FALSE, FALSE, TRUE, &u4BufLen, + ucBssIndex); +#if 0 + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, + "[HS20] set HS20 assoc info error:%x\n", + rStatus); +#endif + } else if (wextSrchDesiredOsenIE(pucIEStart, sme->ie_len, + (uint8_t **) &prDesiredIE)) { + /* we can reuse aucHS20AssocInfoIE because hs20 + * indication IE is not present when OSEN exist + */ + kalMemCopy(prGlueInfo->aucHS20AssocInfoIE, + prDesiredIE, IE_SIZE(prDesiredIE)); + prGlueInfo->u2HS20AssocInfoIELen = + (uint16_t)IE_SIZE(prDesiredIE); + } +#endif /* CFG_SUPPORT_PASSPOINT */ + if (wextSrchDesiredWPAIE(pucIEStart, sme->ie_len, 0x30, + (uint8_t **) &prDesiredIE)) { + struct RSN_INFO rRsnInfo; + + if (rsnParseRsnIE(prGlueInfo->prAdapter, + (struct RSN_INFO_ELEM *)prDesiredIE, &rRsnInfo)) { +#if CFG_SUPPORT_802_11W + if (rRsnInfo.u2RsnCap & ELEM_WPA_CAP_MFPC) { + prWpaInfo->ucRSNMfpCap = + RSN_AUTH_MFP_OPTIONAL; + if (rRsnInfo.u2RsnCap & + ELEM_WPA_CAP_MFPR) + prWpaInfo-> + ucRSNMfpCap = + RSN_AUTH_MFP_REQUIRED; + } else + prWpaInfo->ucRSNMfpCap = + RSN_AUTH_MFP_DISABLED; +#endif + } + } + /* Find non-wfa vendor specific ies set from upper layer */ + if (cfg80211_get_non_wfa_vendor_ie(prGlueInfo, pucIEStart, + sme->ie_len, ucBssIndex) > 0) { + DBGLOG(RSN, INFO, "Found non-wfa vendor ie (len=%u)\n", + prConnSettings->non_wfa_vendor_ie_len); + } + } + + /* Fill WPA info - mfp setting */ + /* Must put after paring RSNE from upper layer + * for prWpaInfo->ucRSNMfpCap assignment + */ +#if CFG_SUPPORT_802_11W + switch (sme->mfp) { + case NL80211_MFP_NO: + prWpaInfo->u4Mfp = IW_AUTH_MFP_DISABLED; + /* Change Mfp parameter from DISABLED to OPTIONAL + * if upper layer set MFPC = 1 in RSNE + * since upper layer can't bring MFP OPTIONAL information + * to driver by sme->mfp + */ + if (prWpaInfo->ucRSNMfpCap == RSN_AUTH_MFP_OPTIONAL) + prWpaInfo->u4Mfp = IW_AUTH_MFP_OPTIONAL; + else if (prWpaInfo->ucRSNMfpCap == + RSN_AUTH_MFP_REQUIRED) + DBGLOG(REQ, WARN, + "mfp parameter(DISABLED) conflict with mfp cap(REQUIRED)\n"); + break; + case NL80211_MFP_REQUIRED: + prWpaInfo->u4Mfp = IW_AUTH_MFP_REQUIRED; + break; + default: + prWpaInfo->u4Mfp = IW_AUTH_MFP_DISABLED; + break; + } + /* DBGLOG(REQ, INFO, ("MFP=%d\n", prWpaInfo->u4Mfp)); */ +#endif + + rStatus = kalIoctlByBssIdx(prGlueInfo, wlanoidSetAuthMode, &eAuthMode, + sizeof(eAuthMode), FALSE, FALSE, FALSE, &u4BufLen, + ucBssIndex); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "set auth mode error:%x\n", rStatus); + + prMib = aisGetMib(prGlueInfo->prAdapter, ucBssIndex); + + /* Enable the specific AKM suite only. */ + for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) { + prEntry = &prMib-> + dot11RSNAConfigAuthenticationSuitesTable[i]; + + if (prEntry->dot11RSNAConfigAuthenticationSuite == + u4AkmSuite) { + prEntry->dot11RSNAConfigAuthenticationSuiteEnabled = + TRUE; + /* printk("match AuthenticationSuite = 0x%x", + * u4AkmSuite); + */ + } else { + prEntry->dot11RSNAConfigAuthenticationSuiteEnabled = + FALSE; + } + } + + cipher = prWpaInfo->u4CipherGroup | + prWpaInfo->u4CipherPairwise; + + if (1 /* prWpaInfo->fgPrivacyInvoke */) { + if (cipher & IW_AUTH_CIPHER_GCMP256) { + eEncStatus = ENUM_ENCRYPTION4_ENABLED; + } else 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 (prWpaInfo->fgPrivacyInvoke) + eEncStatus = ENUM_ENCRYPTION1_ENABLED; + else + eEncStatus = ENUM_ENCRYPTION_DISABLED; + } else { + eEncStatus = ENUM_ENCRYPTION_DISABLED; + } + } else { + eEncStatus = ENUM_ENCRYPTION_DISABLED; + } + + rStatus = kalIoctlByBssIdx(prGlueInfo, + wlanoidSetEncryptionStatus, &eEncStatus, + sizeof(eEncStatus), FALSE, FALSE, FALSE, &u4BufLen, + ucBssIndex); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "set encryption mode error:%x\n", + rStatus); + + if (sme->key_len != 0 + && prWpaInfo->u4WpaVersion == + IW_AUTH_WPA_VERSION_DISABLED) { + /* NL80211 only set the Tx wep key while connect, the max 4 wep + * key set prior via add key cmd + */ + struct PARAM_WEP *prWepKey = (struct PARAM_WEP *) wepBuf; + + kalMemZero(prWepKey, sizeof(struct PARAM_WEP)); + prWepKey->u4Length = OFFSET_OF(struct PARAM_WEP, + aucKeyMaterial) + sme->key_len; + prWepKey->u4KeyLength = (uint32_t) sme->key_len; + prWepKey->u4KeyIndex = (uint32_t) sme->key_idx; + prWepKey->u4KeyIndex |= IS_TRANSMIT_KEY; + if (prWepKey->u4KeyLength > MAX_KEY_LEN) { + DBGLOG(REQ, WARN, "Too long key length (%u)\n", + prWepKey->u4KeyLength); + return -EINVAL; + } + kalMemCopy(prWepKey->aucKeyMaterial, sme->key, + prWepKey->u4KeyLength); + + rStatus = kalIoctlByBssIdx(prGlueInfo, + wlanoidAbortScan, + NULL, 1, FALSE, FALSE, TRUE, &u4BufLen, + ucBssIndex); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, ERROR, "wlanoidAbortScan fail 0x%x\n", + rStatus); + + rStatus = kalIoctlByBssIdx(prGlueInfo, + wlanoidSetAddWep, prWepKey, + prWepKey->u4Length, + FALSE, FALSE, TRUE, &u4BufLen, + ucBssIndex); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "wlanoidSetAddWep fail 0x%x\n", + rStatus); + return -EFAULT; + } + } + + /* Avoid dangling pointer, set defatul all zero */ + kalMemZero(&rNewSsid, sizeof(rNewSsid)); + rNewSsid.u4CenterFreq = sme->channel ? + sme->channel->center_freq : 0; + rNewSsid.pucBssid = (uint8_t *)sme->bssid; +#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE + rNewSsid.pucBssidHint = (uint8_t *)sme->bssid_hint; +#endif + rNewSsid.pucSsid = (uint8_t *)sme->ssid; + rNewSsid.u4SsidLen = sme->ssid_len; + rNewSsid.ucBssIdx = ucBssIndex; + + /* Check former assocIE to prevent memory leakage in situations like + * upper layer requests connection without disconnecting first, ... + */ + if (prConnSettings->assocIeLen > 0) { + kalMemFree(prConnSettings->pucAssocIEs, VIR_MEM_TYPE, + prConnSettings->assocIeLen); + prConnSettings->assocIeLen = 0; + } + + if (sme->ie_len > 0) { + prConnSettings->assocIeLen = sme->ie_len; + prConnSettings->pucAssocIEs = + kalMemAlloc(prConnSettings->assocIeLen, VIR_MEM_TYPE); + if (prConnSettings->pucAssocIEs) { + kalMemCopy(prConnSettings->pucAssocIEs, + sme->ie, prConnSettings->assocIeLen); + } else { + DBGLOG(INIT, INFO, + "allocate memory for prConnSettings->pucAssocIEs failed!\n"); + prConnSettings->assocIeLen = 0; + } + } + + rStatus = kalIoctl(prGlueInfo, wlanoidSetConnect, + (void *)&rNewSsid, sizeof(struct PARAM_CONNECT), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set SSID:%x\n", rStatus); + return -EINVAL; + } +#if 0 + if (sme->bssid != NULL + && 1 /* prGlueInfo->fgIsBSSIDSet */) { + /* connect by BSSID */ + if (sme->ssid_len > 0) { + struct CONNECTION_SETTINGS *prConnSettings = NULL; + + prConnSettings = & + (prGlueInfo->prAdapter->rWifiVar.rConnSettings); + /* prGlueInfo->fgIsSSIDandBSSIDSet = TRUE; */ + COPY_SSID(prConnSettings->aucSSID, + prConnSettings->ucSSIDLen, + sme->ssid, sme->ssid_len); + } + rStatus = kalIoctl(prGlueInfo, wlanoidSetBssid, + (void *) sme->bssid, MAC_ADDR_LEN, + FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set BSSID:%x\n", rStatus); + return -EINVAL; + } + } else if (sme->ssid_len > 0) { + /* connect by SSID */ + COPY_SSID(rNewSsid.aucSsid, rNewSsid.u4SsidLen, sme->ssid, + sme->ssid_len); + rNewSsid.ucBssIdx = ucBssIndex; + rStatus = kalIoctl(prGlueInfo, wlanoidSetSsid, + (void *)&rNewSsid, sizeof(struct PARAM_SSID), + FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set SSID:%x\n", rStatus); + return -EINVAL; + } + } +#endif + return 0; +} +#if CFG_SUPPORT_WPA3 +int mtk_cfg80211_external_auth(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_external_auth_params *params) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_FAILURE; + uint32_t u4BufLen; + struct PARAM_EXTERNAL_AUTH auth; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + if (!prGlueInfo) + DBGLOG(REQ, WARN, + "SAE-confirm failed with invalid prGlueInfo\n"); + + COPY_MAC_ADDR(auth.bssid, params->bssid); + auth.status = params->status; + auth.ucBssIdx = wlanGetBssIdx(ndev); + rStatus = kalIoctl(prGlueInfo, wlanoidExternalAuthDone, (void *)&auth, + sizeof(auth), FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(OID, INFO, "SAE-confirm failed with: %d\n", rStatus); + + return 0; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint32_t u4BufLen; + uint8_t ucBssIndex = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + DBGLOG(REQ, INFO, "ucBssIndex = %d\n", ucBssIndex); + rStatus = kalIoctlByBssIdx(prGlueInfo, wlanoidSetDisassociate, NULL, + 0, FALSE, FALSE, TRUE, &u4BufLen, + ucBssIndex); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "disassociate error:%x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to join an IBSS group + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_join_ibss(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_ibss_params *params) +{ + struct PARAM_SSID rNewSsid; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4ChnlFreq; /* Store channel or frequency information */ + uint32_t u4BufLen = 0, u4SsidLen = 0; + uint32_t rStatus; + uint8_t ucBssIndex = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + /* set channel */ + if (params->channel_fixed) { + u4ChnlFreq = params->chandef.center_freq1; + + rStatus = kalIoctlByBssIdx(prGlueInfo, wlanoidSetFrequency, + &u4ChnlFreq, sizeof(u4ChnlFreq), + FALSE, FALSE, FALSE, &u4BufLen, + ucBssIndex); + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + /* set SSID */ + if (params->ssid_len > PARAM_MAX_LEN_SSID) + u4SsidLen = PARAM_MAX_LEN_SSID; + else + u4SsidLen = params->ssid_len; + + kalMemCopy(rNewSsid.aucSsid, params->ssid, + u4SsidLen); + rStatus = kalIoctlByBssIdx(prGlueInfo, + wlanoidSetSsid, (void *)&rNewSsid, + sizeof(struct PARAM_SSID), + FALSE, FALSE, TRUE, &u4BufLen, + ucBssIndex); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set SSID:%x\n", rStatus); + return -EFAULT; + } + + return 0; + + return -EINVAL; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to leave from IBSS group + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_leave_ibss(struct wiphy *wiphy, + struct net_device *ndev) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint32_t u4BufLen; + uint8_t ucBssIndex = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + rStatus = kalIoctlByBssIdx(prGlueInfo, wlanoidSetDisassociate, NULL, + 0, FALSE, FALSE, TRUE, &u4BufLen, + ucBssIndex); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "disassociate error:%x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to configure + * WLAN power managemenet + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_set_power_mgmt(struct wiphy *wiphy, + struct net_device *ndev, bool enabled, int timeout) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint32_t u4BufLen; + struct PARAM_POWER_MODE_ rPowerMode; + uint8_t ucBssIndex = 0; + struct BSS_INFO *prBssInfo; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + if (!prGlueInfo) + return -EFAULT; + + if (prGlueInfo->prAdapter->fgEnDbgPowerMode) { + DBGLOG(REQ, WARN, + "Force power mode enabled, ignore: %d\n", enabled); + return 0; + } + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, + ucBssIndex); + if (!prBssInfo) + return -EINVAL; + + DBGLOG(REQ, INFO, "%d: enabled=%d, timeout=%d, fgTIMPresend=%d\n", + ucBssIndex, enabled, timeout, + prBssInfo->fgTIMPresent); + + if (enabled) { + if (prBssInfo->eConnectionState + == MEDIA_STATE_CONNECTED && + !prBssInfo->fgTIMPresent) + return -EFAULT; + + if (timeout == -1) + rPowerMode.ePowerMode = Param_PowerModeFast_PSP; + else + rPowerMode.ePowerMode = Param_PowerModeMAX_PSP; + } else { + rPowerMode.ePowerMode = Param_PowerModeCAM; + } + + rPowerMode.ucBssIdx = ucBssIndex; + + rStatus = kalIoctl(prGlueInfo, wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, sizeof(struct PARAM_POWER_MODE_), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set_power_mgmt error:%x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to cache + * a PMKID for a BSSID + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_set_pmksa(struct wiphy *wiphy, + struct net_device *ndev, struct cfg80211_pmksa *pmksa) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint32_t u4BufLen; + struct PARAM_PMKID pmkid; + uint8_t ucBssIndex = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, TRACE, "mtk_cfg80211_set_pmksa " MACSTR " pmk\n", + MAC2STR(pmksa->bssid)); + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + COPY_MAC_ADDR(pmkid.arBSSID, pmksa->bssid); + kalMemCopy(pmkid.arPMKID, pmksa->pmkid, IW_PMKID_LEN); + pmkid.ucBssIdx = ucBssIndex; + rStatus = kalIoctl(prGlueInfo, wlanoidSetPmkid, &pmkid, + sizeof(struct PARAM_PMKID), + FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "add pmkid error:%x\n", rStatus); + + 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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint32_t u4BufLen; + struct PARAM_PMKID pmkid; + uint8_t ucBssIndex = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, TRACE, "mtk_cfg80211_del_pmksa " MACSTR "\n", + MAC2STR(pmksa->bssid)); + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + COPY_MAC_ADDR(pmkid.arBSSID, pmksa->bssid); + kalMemCopy(pmkid.arPMKID, pmksa->pmkid, IW_PMKID_LEN); + pmkid.ucBssIdx = ucBssIndex; + rStatus = kalIoctl(prGlueInfo, wlanoidDelPmkid, &pmkid, + sizeof(struct PARAM_PMKID), + FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "add pmkid error:%x\n", rStatus); + + 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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint32_t u4BufLen; + uint8_t ucBssIndex = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + rStatus = kalIoctlByBssIdx(prGlueInfo, wlanoidFlushPmkid, NULL, 0, + FALSE, FALSE, FALSE, &u4BufLen, + ucBssIndex); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "flush pmkid error:%x\n", rStatus); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for setting the rekey data + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_set_rekey_data(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_gtk_rekey_data *data) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4BufLen; + struct PARAM_GTK_REKEY_DATA *prGtkData; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + int32_t i4Rslt = -EINVAL; + struct GL_WPA_INFO *prWpaInfo; + uint8_t ucBssIndex = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + ucBssIndex = wlanGetBssIdx(dev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + prGtkData = + (struct PARAM_GTK_REKEY_DATA *) kalMemAlloc(sizeof( + struct PARAM_GTK_REKEY_DATA), VIR_MEM_TYPE); + + if (!prGtkData) + return WLAN_STATUS_SUCCESS; + + DBGLOG(RSN, INFO, "ucBssIndex = %d, size(%d)\n", + ucBssIndex, + (uint32_t) sizeof(struct cfg80211_gtk_rekey_data)); + + DBGLOG(RSN, TRACE, "kek\n"); + DBGLOG_MEM8(RSN, TRACE, (uint8_t *)data->kek, + NL80211_KEK_LEN); + DBGLOG(RSN, TRACE, "kck\n"); + DBGLOG_MEM8(RSN, TRACE, (uint8_t *)data->kck, + NL80211_KCK_LEN); + DBGLOG(RSN, TRACE, "replay count\n"); + DBGLOG_MEM8(RSN, TRACE, (uint8_t *)data->replay_ctr, + NL80211_REPLAY_CTR_LEN); + + +#if 0 + kalMemCopy(prGtkData, data, sizeof(*data)); +#else + kalMemCopy(prGtkData->aucKek, data->kek, NL80211_KEK_LEN); + kalMemCopy(prGtkData->aucKck, data->kck, NL80211_KCK_LEN); + kalMemCopy(prGtkData->aucReplayCtr, data->replay_ctr, + NL80211_REPLAY_CTR_LEN); +#endif + + prGtkData->ucBssIndex = ucBssIndex; + + prWpaInfo = aisGetWpaInfo(prGlueInfo->prAdapter, + ucBssIndex); + + prGtkData->u4Proto = NL80211_WPA_VERSION_2; + if (prWpaInfo->u4WpaVersion == + IW_AUTH_WPA_VERSION_WPA) + prGtkData->u4Proto = NL80211_WPA_VERSION_1; + + if (prWpaInfo->u4CipherPairwise == + IW_AUTH_CIPHER_TKIP) + prGtkData->u4PairwiseCipher = BIT(3); + else if (prWpaInfo->u4CipherPairwise == + IW_AUTH_CIPHER_CCMP) + prGtkData->u4PairwiseCipher = BIT(4); + else { + kalMemFree(prGtkData, VIR_MEM_TYPE, + sizeof(struct PARAM_GTK_REKEY_DATA)); + return WLAN_STATUS_SUCCESS; + } + + if (prWpaInfo->u4CipherGroup == + IW_AUTH_CIPHER_TKIP) + prGtkData->u4GroupCipher = BIT(3); + else if (prWpaInfo->u4CipherGroup == + IW_AUTH_CIPHER_CCMP) + prGtkData->u4GroupCipher = BIT(4); + else { + kalMemFree(prGtkData, VIR_MEM_TYPE, + sizeof(struct PARAM_GTK_REKEY_DATA)); + return WLAN_STATUS_SUCCESS; + } + + prGtkData->u4KeyMgmt = prWpaInfo->u4KeyMgmt; + prGtkData->u4MgmtGroupCipher = 0; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetGtkRekeyData, prGtkData, + sizeof(struct PARAM_GTK_REKEY_DATA), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "set GTK rekey data error:%x\n", + rStatus); + else + i4Rslt = 0; + + kalMemFree(prGtkData, VIR_MEM_TYPE, + sizeof(struct PARAM_GTK_REKEY_DATA)); + + return i4Rslt; +} + +void mtk_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, + IN struct wireless_dev *wdev, + IN u16 frame_type, + IN bool reg) +{ +#if 0 + struct MSG_P2P_MGMT_FRAME_REGISTER *prMgmtFrameRegister = + (struct MSG_P2P_MGMT_FRAME_REGISTER *) NULL; +#endif + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + + do { + + DBGLOG(INIT, TRACE, "mtk_cfg80211_mgmt_frame_register\n"); + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + switch (frame_type) { + case MAC_FRAME_PROBE_REQ: + if (reg) { + prGlueInfo->u4OsMgmtFrameFilter |= + PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(INIT, TRACE, + "Open packet filer probe request\n"); + } else { + prGlueInfo->u4OsMgmtFrameFilter &= + ~PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(INIT, TRACE, + "Close packet filer probe request\n"); + } + break; + case MAC_FRAME_ACTION: + if (reg) { + prGlueInfo->u4OsMgmtFrameFilter |= + PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(INIT, TRACE, + "Open packet filer action frame.\n"); + } else { + prGlueInfo->u4OsMgmtFrameFilter &= + ~PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(INIT, TRACE, + "Close packet filer action frame.\n"); + } + break; + default: + DBGLOG(INIT, TRACE, + "Ask frog to add code for mgmt:%x\n", + frame_type); + break; + } + + if (prGlueInfo->prAdapter != NULL) { + + set_bit(GLUE_FLAG_FRAME_FILTER_AIS_BIT, + &prGlueInfo->ulFlag); + + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + + if (in_interrupt()) + DBGLOG(INIT, TRACE, + "It is in interrupt level\n"); + } +#if 0 + + prMgmtFrameRegister = + (struct MSG_P2P_MGMT_FRAME_REGISTER *) cnmMemAlloc( + prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_P2P_MGMT_FRAME_REGISTER)); + + 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, + (struct MSG_HDR *) prMgmtFrameRegister, + MSG_SEND_METHOD_BUF); + +#endif + + } while (FALSE); + +} /* mtk_cfg80211_mgmt_frame_register */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to stay on a + * specified channel + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, unsigned int duration, + u64 *cookie) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_REMAIN_ON_CHANNEL *prMsgChnlReq = + (struct MSG_REMAIN_ON_CHANNEL *) NULL; + uint8_t ucBssIndex = 0; + + do { + if ((wiphy == NULL) + || (wdev == NULL) + || (chan == NULL) + || (cookie == NULL)) { + break; + } + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + ucBssIndex = wlanGetBssIdx(wdev->netdev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + *cookie = prGlueInfo->u8Cookie++; + + prMsgChnlReq = cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, sizeof(struct MSG_REMAIN_ON_CHANNEL)); + + if (prMsgChnlReq == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgChnlReq->rMsgHdr.eMsgId = + MID_MNY_AIS_REMAIN_ON_CHANNEL; + prMsgChnlReq->u8Cookie = *cookie; + prMsgChnlReq->u4DurationMs = duration; + prMsgChnlReq->eReqType = CH_REQ_TYPE_ROC; + prMsgChnlReq->ucChannelNum = nicFreq2ChannelNum( + chan->center_freq * 1000); + + switch (chan->band) { + case KAL_BAND_2GHZ: + prMsgChnlReq->eBand = BAND_2G4; + break; + case KAL_BAND_5GHZ: + prMsgChnlReq->eBand = BAND_5G; + break; + default: + prMsgChnlReq->eBand = BAND_2G4; + break; + } + + prMsgChnlReq->eSco = CHNL_EXT_SCN; + + prMsgChnlReq->ucBssIdx = ucBssIndex; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prMsgChnlReq, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to cancel staying + * on a specified channel + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_cancel_remain_on_channel( + struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_CANCEL_REMAIN_ON_CHANNEL *prMsgChnlAbort = + (struct MSG_CANCEL_REMAIN_ON_CHANNEL *) NULL; + uint8_t ucBssIndex = 0; + + do { + if ((wiphy == NULL) + || (wdev == NULL) + ) { + break; + } + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + ucBssIndex = wlanGetBssIdx(wdev->netdev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + prMsgChnlAbort = + cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_CANCEL_REMAIN_ON_CHANNEL)); + + if (prMsgChnlAbort == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgChnlAbort->rMsgHdr.eMsgId = + MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL; + prMsgChnlAbort->u8Cookie = cookie; + + prMsgChnlAbort->ucBssIdx = ucBssIndex; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prMsgChnlAbort, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} + +int _mtk_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, struct ieee80211_channel *chan, + bool offchan, unsigned int wait, const u8 *buf, size_t len, + bool no_cck, bool dont_wait_for_ack, u64 *cookie) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_MGMT_TX_REQUEST *prMsgTxReq = + (struct MSG_MGMT_TX_REQUEST *) NULL; + struct MSDU_INFO *prMgmtFrame = (struct MSDU_INFO *) NULL; + uint8_t *pucFrameBuf = (uint8_t *) NULL; + uint64_t *pu8GlCookie = (uint64_t *) NULL; + + do { + if ((wiphy == NULL) || (wdev == NULL) || (cookie == NULL)) + break; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + *cookie = prGlueInfo->u8Cookie++; + + prMsgTxReq = cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_MGMT_TX_REQUEST)); + + if (prMsgTxReq == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + if (offchan) { + prMsgTxReq->fgIsOffChannel = TRUE; + + kalChannelFormatSwitch(NULL, chan, + &prMsgTxReq->rChannelInfo); + kalChannelScoSwitch(NL80211_CHAN_NO_HT, + &prMsgTxReq->eChnlExt); + } else { + prMsgTxReq->fgIsOffChannel = FALSE; + } + + if (wait) + prMsgTxReq->u4Duration = wait; + else + prMsgTxReq->u4Duration = 0; + + if (no_cck) + prMsgTxReq->fgNoneCckRate = TRUE; + else + prMsgTxReq->fgNoneCckRate = FALSE; + + if (dont_wait_for_ack) + prMsgTxReq->fgIsWaitRsp = FALSE; + else + prMsgTxReq->fgIsWaitRsp = TRUE; + + prMgmtFrame = cnmMgtPktAlloc(prGlueInfo->prAdapter, + (int32_t) (len + sizeof(uint64_t) + + MAC_TX_RESERVED_FIELD)); + prMsgTxReq->prMgmtMsduInfo = prMgmtFrame; + if (prMsgTxReq->prMgmtMsduInfo == NULL) { + /* ASSERT(FALSE); */ + i4Rslt = -ENOMEM; + break; + } + + prMsgTxReq->u8Cookie = *cookie; + prMsgTxReq->rMsgHdr.eMsgId = MID_MNY_AIS_MGMT_TX; + prMsgTxReq->ucBssIdx = wlanGetBssIdx(wdev->netdev); + + pucFrameBuf = + (uint8_t *) + ((unsigned long) prMgmtFrame->prPacket + + MAC_TX_RESERVED_FIELD); + pu8GlCookie = + (uint64_t *) + ((unsigned long) prMgmtFrame->prPacket + + (unsigned long) len + + MAC_TX_RESERVED_FIELD); + + kalMemCopy(pucFrameBuf, buf, len); + + *pu8GlCookie = *cookie; + + prMgmtFrame->u2FrameLength = len; + prMgmtFrame->ucBssIndex = wlanGetBssIdx(wdev->netdev); + +#define TEMP_LOG_TEMPLATE "bssIdx: %d, band: %d, chan: %d, offchan: %d, " \ + "wait: %d, len: %d, no_cck: %d, dont_wait_for_ack: %d, " \ + "cookie: 0x%llx\n" + DBGLOG(P2P, INFO, TEMP_LOG_TEMPLATE, + prMsgTxReq->ucBssIdx, + prMsgTxReq->rChannelInfo.eBand, + prMsgTxReq->rChannelInfo.ucChannelNum, + prMsgTxReq->fgIsOffChannel, + prMsgTxReq->u4Duration, + prMsgTxReq->prMgmtMsduInfo->u2FrameLength, + prMsgTxReq->fgNoneCckRate, + prMsgTxReq->fgIsWaitRsp, + prMsgTxReq->u8Cookie); +#undef TEMP_LOG_TEMPLATE + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prMsgTxReq, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + if ((i4Rslt != 0) && (prMsgTxReq != NULL)) { + if (prMsgTxReq->prMgmtMsduInfo != NULL) + cnmMgtPktFree(prGlueInfo->prAdapter, + prMsgTxReq->prMgmtMsduInfo); + + cnmMemFree(prGlueInfo->prAdapter, prMsgTxReq); + } + + return i4Rslt; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to send a management frame + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie) +{ + if (params == NULL) + return -EINVAL; + + return _mtk_cfg80211_mgmt_tx(wiphy, wdev, params->chan, + params->offchan, params->wait, params->buf, params->len, + params->no_cck, params->dont_wait_for_ack, cookie); +} +#else +int mtk_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, struct ieee80211_channel *channel, + bool offchan, unsigned int wait, const u8 *buf, size_t len, + bool no_cck, bool dont_wait_for_ack, u64 *cookie) +{ + return _mtk_cfg80211_mgmt_tx(wiphy, wdev, channel, offchan, wait, buf, + len, no_cck, dont_wait_for_ack, cookie); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to cancel the wait time + * from transmitting a management frame on another channel + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct wireless_dev *wdev, u64 cookie) +{ + int32_t i4Rslt = -EINVAL; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + struct MSG_CANCEL_TX_WAIT_REQUEST *prMsgCancelTxWait = + (struct MSG_CANCEL_TX_WAIT_REQUEST *) NULL; + uint8_t ucBssIndex = 0; + + do { + ASSERT(wiphy); + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + ucBssIndex = wlanGetBssIdx(wdev->netdev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + DBGLOG(P2P, INFO, "cookie: 0x%llx, ucBssIndex = %d\n", + cookie, ucBssIndex); + + + prMsgCancelTxWait = cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_CANCEL_TX_WAIT_REQUEST)); + + if (prMsgCancelTxWait == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgCancelTxWait->rMsgHdr.eMsgId = + MID_MNY_AIS_MGMT_TX_CANCEL_WAIT; + prMsgCancelTxWait->u8Cookie = cookie; + prMsgCancelTxWait->ucBssIdx = ucBssIndex; + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prMsgCancelTxWait, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} + +#ifdef CONFIG_NL80211_TESTMODE + +#if CFG_SUPPORT_PASSPOINT +int mtk_cfg80211_testmode_hs20_cmd(IN struct wiphy *wiphy, + IN struct wireless_dev *wdev, + IN void *data, IN int len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct wpa_driver_hs20_data_s *prParams = NULL; + uint32_t rstatus = WLAN_STATUS_SUCCESS; + int fgIsValid = 0; + uint32_t u4SetInfoLen = 0; + uint8_t ucBssIndex = 0; + + ASSERT(wiphy); + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + ucBssIndex = wlanGetBssIdx(wdev->netdev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + if (data && len) + prParams = (struct wpa_driver_hs20_data_s *)data; + + if (prParams) { + int i; + + DBGLOG(INIT, INFO, "Cmd Type (%d)\n", prParams->CmdType); + switch (prParams->CmdType) { + case HS20_CMD_ID_SET_BSSID_POOL: + DBGLOG(REQ, TRACE, + "fgBssidPoolIsEnable=%d, ucNumBssidPool=%d\n", + prParams->hs20_set_bssid_pool.fgBssidPoolIsEnable, + prParams->hs20_set_bssid_pool.ucNumBssidPool); + for (i = 0; + i < prParams->hs20_set_bssid_pool.ucNumBssidPool; + i++) { + DBGLOG(REQ, TRACE, + "[%d][ " MACSTR " ]\n", + i, + MAC2STR(prParams-> + hs20_set_bssid_pool. + arBssidPool[i])); + } + rstatus = kalIoctlByBssIdx(prGlueInfo, + (PFN_OID_HANDLER_FUNC) wlanoidSetHS20BssidPool, + &prParams->hs20_set_bssid_pool, + sizeof(struct param_hs20_set_bssid_pool), + FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen, + ucBssIndex); + break; + default: + DBGLOG(REQ, TRACE, + "Unknown Cmd Type (%d)\n", + prParams->CmdType); + rstatus = WLAN_STATUS_FAILURE; + + } + + } + + if (rstatus != WLAN_STATUS_SUCCESS) + fgIsValid = -EFAULT; + + return fgIsValid; +} +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_WAPI +int mtk_cfg80211_testmode_set_key_ext(IN struct wiphy + *wiphy, + IN struct wireless_dev *wdev, + IN void *data, IN int len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct NL80211_DRIVER_SET_KEY_EXTS *prParams = + (struct NL80211_DRIVER_SET_KEY_EXTS *) NULL; + struct iw_encode_exts *prIWEncExt = (struct iw_encode_exts + *)NULL; + uint32_t rstatus = WLAN_STATUS_SUCCESS; + int fgIsValid = 0; + uint32_t u4BufLen = 0; + const uint8_t aucBCAddr[] = BC_MAC_ADDR; + uint8_t ucBssIndex = 0; + + struct PARAM_KEY *prWpiKey = (struct PARAM_KEY *) + keyStructBuf; + + memset(keyStructBuf, 0, sizeof(keyStructBuf)); + + ASSERT(wiphy); + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (data == NULL || len == 0) { + DBGLOG(INIT, TRACE, "%s data or len is invalid\n", __func__); + return -EINVAL; + } + + ucBssIndex = wlanGetBssIdx(wdev->netdev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + ucBssIndex = 0; + + prParams = (struct NL80211_DRIVER_SET_KEY_EXTS *) data; + prIWEncExt = (struct iw_encode_exts *)&prParams->ext; + + if (prIWEncExt->alg == IW_ENCODE_ALG_SMS4) { + /* KeyID */ + prWpiKey->u4KeyIndex = prParams->key_index; + prWpiKey->u4KeyIndex--; + if (prWpiKey->u4KeyIndex > 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; + } + prWpiKey->u4KeyLength = prIWEncExt->key_len; + + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY && + !(prIWEncExt->ext_flags & IW_ENCODE_EXT_GROUP_KEY)) { + /* WAI seems set the STA group key with + * IW_ENCODE_EXT_SET_TX_KEY !!!! + * Ignore the group case + */ + prWpiKey->u4KeyIndex |= BIT(30); + prWpiKey->u4KeyIndex |= BIT(31); + /* BSSID */ + memcpy(prWpiKey->arBSSID, prIWEncExt->addr, 6); + } else { + COPY_MAC_ADDR(prWpiKey->arBSSID, aucBCAddr); + } + + /* PN */ + /* memcpy(prWpiKey->rKeyRSC, prIWEncExt->tx_seq, + * IW_ENCODE_SEQ_MAX_SIZE * 2); + */ + + memcpy(prWpiKey->aucKeyMaterial, prIWEncExt->key, 32); + + prWpiKey->u4Length = sizeof(struct PARAM_KEY); + prWpiKey->ucBssIdx = ucBssIndex; + prWpiKey->ucCipher = CIPHER_SUITE_WPI; + + rstatus = kalIoctl(prGlueInfo, wlanoidSetAddKey, prWpiKey, + sizeof(struct PARAM_KEY), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rstatus != WLAN_STATUS_SUCCESS) { + /* printk(KERN_INFO "[wapi] add key error:%x\n", + * rStatus); + */ + fgIsValid = -EFAULT; + } + + } + return fgIsValid; +} +#endif + +int +mtk_cfg80211_testmode_get_sta_statistics(IN struct wiphy + *wiphy, IN void *data, IN int len, + IN struct GLUE_INFO *prGlueInfo) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen; + uint32_t u4LinkScore; + uint32_t u4TotalError; + uint32_t u4TxExceedThresholdCount; + uint32_t u4TxTotalCount; + + struct NL80211_DRIVER_GET_STA_STATISTICS_PARAMS *prParams = + NULL; + struct PARAM_GET_STA_STATISTICS rQueryStaStatistics; + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(prGlueInfo); + + if (data && len) + prParams = (struct NL80211_DRIVER_GET_STA_STATISTICS_PARAMS + *) data; + + if (prParams == NULL) { + DBGLOG(QM, ERROR, "prParams is NULL, data=%p, len=%d\n", + data, len); + return -EINVAL; + } else if (prParams->aucMacAddr == NULL) { + DBGLOG(QM, ERROR, + "prParams->aucMacAddr is NULL, data=%p, len=%d\n", + data, len); + return -EINVAL; + } + + skb = cfg80211_testmode_alloc_reply_skb(wiphy, + sizeof(struct PARAM_GET_STA_STATISTICS) + 1); + if (!skb) { + DBGLOG(QM, ERROR, "allocate skb failed:%x\n", rStatus); + return -ENOMEM; + } + + DBGLOG(QM, TRACE, "Get [" MACSTR "] STA statistics\n", + MAC2STR(prParams->aucMacAddr)); + + kalMemZero(&rQueryStaStatistics, + sizeof(rQueryStaStatistics)); + COPY_MAC_ADDR(rQueryStaStatistics.aucMacAddr, + prParams->aucMacAddr); + rQueryStaStatistics.ucReadClear = TRUE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStaStatistics, + &rQueryStaStatistics, sizeof(rQueryStaStatistics), + TRUE, FALSE, TRUE, &u4BufLen); + + /* Calcute Link Score */ + u4TxExceedThresholdCount = + rQueryStaStatistics.u4TxExceedThresholdCount; + u4TxTotalCount = rQueryStaStatistics.u4TxTotalCount; + u4TotalError = rQueryStaStatistics.u4TxFailCount + + rQueryStaStatistics.u4TxLifeTimeoutCount; + + /* u4LinkScore 10~100 , ExceedThreshold ratio 0~90 only + * u4LinkScore 0~9 , Drop packet ratio 0~9 and all packets exceed + * threshold + */ + if (u4TxTotalCount) { + if (u4TxExceedThresholdCount <= u4TxTotalCount) + u4LinkScore = (90 - ((u4TxExceedThresholdCount * 90) + / u4TxTotalCount)); + else + u4LinkScore = 0; + } else { + u4LinkScore = 90; + } + + u4LinkScore += 10; + + if (u4LinkScore == 10) { + if (u4TotalError <= u4TxTotalCount) + u4LinkScore = (10 - ((u4TotalError * 10) + / u4TxTotalCount)); + else + u4LinkScore = 0; + + } + + if (u4LinkScore > 100) + u4LinkScore = 100; + { + u8 __tmp = 0; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_INVALID, sizeof(u8), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u8 __tmp = NL80211_DRIVER_TESTMODE_VERSION; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_VERSION, sizeof(u8), + &__tmp) < 0)) + goto nla_put_failure; + } + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_MAC, MAC_ADDR_LEN, + prParams->aucMacAddr) < 0)) + goto nla_put_failure; + { + u32 __tmp = u4LinkScore; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + + { + u32 __tmp = rQueryStaStatistics.u4Flag; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_FLAG, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4EnqueueCounter; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_ENQUEUE, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4DequeueCounter; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_DEQUEUE, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4EnqueueStaCounter; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_STA_ENQUEUE, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4DequeueStaCounter; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_STA_DEQUEUE, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.IsrCnt; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_CNT, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + + { + u32 __tmp = rQueryStaStatistics.IsrPassCnt; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_PASS_CNT, + sizeof(u32), &__tmp) < 0)) + goto nla_put_failure; + } + + { + u32 __tmp = rQueryStaStatistics.TaskIsrCnt; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_IRQ_TASK_CNT, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + + { + u32 __tmp = rQueryStaStatistics.IsrAbnormalCnt; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_IRQ_AB_CNT, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + + { + u32 __tmp = rQueryStaStatistics.IsrSoftWareCnt; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_IRQ_SW_CNT, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + + { + u32 __tmp = rQueryStaStatistics.IsrTxCnt; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_IRQ_TX_CNT, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + + { + u32 __tmp = rQueryStaStatistics.IsrRxCnt; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_IRQ_RX_CNT, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + + /* FW part STA link status */ + { + u8 __tmp = rQueryStaStatistics.ucPer; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_PER, sizeof(u8), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u8 __tmp = rQueryStaStatistics.ucRcpi; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_RSSI, sizeof(u8), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4PhyMode; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_PHY_MODE, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u16 __tmp = rQueryStaStatistics.u2LinkSpeed; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_TX_RATE, sizeof(u16), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4TxFailCount; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4TxLifeTimeoutCount; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4TxAverageAirTime; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + + /* Driver part link status */ + { + u32 __tmp = rQueryStaStatistics.u4TxTotalCount; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4TxExceedThresholdCount; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4TxAverageProcessTime; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME, + sizeof(u32), &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4TxMaxTime; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_MAX_PROCESS_TIME, + sizeof(u32), &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4TxAverageHifTime; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_AVG_HIF_PROCESS_TIME, + sizeof(u32), &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4TxMaxHifTime; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_MAX_HIF_PROCESS_TIME, + sizeof(u32), &__tmp) < 0)) + goto nla_put_failure; + } + + /* Network counter */ + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY, + sizeof(rQueryStaStatistics.au4TcResourceEmptyCount), + rQueryStaStatistics.au4TcResourceEmptyCount) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_NO_TC_ARRAY, + sizeof(rQueryStaStatistics.au4DequeueNoTcResource), + rQueryStaStatistics.au4DequeueNoTcResource) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_RB_ARRAY, + sizeof(rQueryStaStatistics.au4TcResourceBackCount), + rQueryStaStatistics.au4TcResourceBackCount) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_USED_TC_PGCT_ARRAY, + sizeof(rQueryStaStatistics.au4TcResourceUsedPageCount), + rQueryStaStatistics.au4TcResourceUsedPageCount) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_WANTED_TC_PGCT_ARRAY, + sizeof(rQueryStaStatistics.au4TcResourceWantedPageCount), + rQueryStaStatistics.au4TcResourceWantedPageCount) < 0)) + goto nla_put_failure; + + /* Sta queue length */ + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY, + sizeof(rQueryStaStatistics.au4TcQueLen), + rQueryStaStatistics.au4TcQueLen) < 0)) + goto nla_put_failure; + + /* Global QM counter */ + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY, + sizeof(rQueryStaStatistics.au4TcAverageQueLen), + rQueryStaStatistics.au4TcAverageQueLen) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY, + sizeof(rQueryStaStatistics.au4TcCurrentQueLen), + rQueryStaStatistics.au4TcCurrentQueLen) < 0)) + goto nla_put_failure; + + /* Reserved field */ + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY, + sizeof(rQueryStaStatistics.au4Reserved), + rQueryStaStatistics.au4Reserved) < 0)) + goto nla_put_failure; + + return cfg80211_testmode_reply(skb); + +nla_put_failure: + /* nal_put_skb_fail */ + kfree_skb(skb); + return -EFAULT; +} + +int +mtk_cfg80211_testmode_get_link_detection(IN struct wiphy + *wiphy, + IN struct wireless_dev *wdev, + IN void *data, IN int len, + IN struct GLUE_INFO *prGlueInfo) +{ + + uint32_t rStatus = WLAN_STATUS_SUCCESS; + int32_t i4Status = -EINVAL; + uint32_t u4BufLen; + uint8_t u1buf = 0; + uint32_t i = 0; + uint32_t arBugReport[sizeof(struct EVENT_BUG_REPORT)]; + struct PARAM_802_11_STATISTICS_STRUCT rStatistics; + struct EVENT_BUG_REPORT *prBugReport; + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(prGlueInfo); + + prBugReport = (struct EVENT_BUG_REPORT *) kalMemAlloc( + sizeof(struct EVENT_BUG_REPORT), VIR_MEM_TYPE); + if (!prBugReport) { + DBGLOG(QM, TRACE, "%s allocate prBugReport failed\n", + __func__); + return -ENOMEM; + } + skb = cfg80211_testmode_alloc_reply_skb(wiphy, + sizeof(struct PARAM_802_11_STATISTICS_STRUCT) + + sizeof(struct EVENT_BUG_REPORT) + 1); + + if (!skb) { + kalMemFree(prBugReport, VIR_MEM_TYPE, + sizeof(struct EVENT_BUG_REPORT)); + DBGLOG(QM, TRACE, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + kalMemZero(&rStatistics, sizeof(rStatistics)); + kalMemZero(prBugReport, sizeof(struct EVENT_BUG_REPORT)); + kalMemZero(arBugReport, sizeof(struct EVENT_BUG_REPORT)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStatistics, + &rStatistics, sizeof(rStatistics), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "query statistics error:%x\n", rStatus); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryBugReport, + prBugReport, sizeof(struct EVENT_BUG_REPORT), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "query statistics error:%x\n", rStatus); + + kalMemCopy(arBugReport, prBugReport, + sizeof(struct EVENT_BUG_REPORT)); + + rStatistics.u4RstReason = glGetRstReason(); + rStatistics.u8RstTime = u8ResetTime; + rStatistics.u4RoamFailCnt = prGlueInfo->u4RoamFailCnt; + rStatistics.u8RoamFailTime = prGlueInfo->u8RoamFailTime; + rStatistics.u2TxDoneDelayIsARP = + prGlueInfo->fgTxDoneDelayIsARP; + rStatistics.u4ArriveDrvTick = prGlueInfo->u4ArriveDrvTick; + rStatistics.u4EnQueTick = prGlueInfo->u4EnQueTick; + rStatistics.u4DeQueTick = prGlueInfo->u4DeQueTick; + rStatistics.u4LeaveDrvTick = prGlueInfo->u4LeaveDrvTick; + rStatistics.u4CurrTick = prGlueInfo->u4CurrTick; + rStatistics.u8CurrTime = prGlueInfo->u8CurrTime; + + if (!NLA_PUT_U8(skb, NL80211_TESTMODE_LINK_INVALID, &u1buf)) + goto nla_put_failure; + + if (!NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_TX_FAIL_CNT, + &rStatistics.rFailedCount.QuadPart)) + goto nla_put_failure; + + if (!NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_TX_RETRY_CNT, + &rStatistics.rRetryCount.QuadPart)) + goto nla_put_failure; + + if (!NLA_PUT_U64(skb, + NL80211_TESTMODE_LINK_TX_MULTI_RETRY_CNT, + &rStatistics.rMultipleRetryCount.QuadPart)) + goto nla_put_failure; + + if (!NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_ACK_FAIL_CNT, + &rStatistics.rACKFailureCount.QuadPart)) + goto nla_put_failure; + + if (!NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_FCS_ERR_CNT, + &rStatistics.rFCSErrorCount.QuadPart)) + goto nla_put_failure; + + if (!NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_TX_CNT, + &rStatistics.rTransmittedFragmentCount.QuadPart)) + goto nla_put_failure; + + if (!NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_RX_CNT, + &rStatistics.rReceivedFragmentCount.QuadPart)) + goto nla_put_failure; + + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_LINK_RST_REASON, + &rStatistics.u4RstReason)) + goto nla_put_failure; + + if (!NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_RST_TIME, + &rStatistics.u8RstTime)) + goto nla_put_failure; + + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_LINK_ROAM_FAIL_TIMES, + &rStatistics.u4RoamFailCnt)) + goto nla_put_failure; + + if (!NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_ROAM_FAIL_TIME, + &rStatistics.u8RoamFailTime)) + goto nla_put_failure; + + if (!NLA_PUT_U8(skb, + NL80211_TESTMODE_LINK_TX_DONE_DELAY_IS_ARP, + &rStatistics.u2TxDoneDelayIsARP)) + goto nla_put_failure; + + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_LINK_ARRIVE_DRV_TICK, + &rStatistics.u4ArriveDrvTick)) + goto nla_put_failure; + + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_LINK_ENQUE_TICK, + &rStatistics.u4EnQueTick)) + goto nla_put_failure; + + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_LINK_DEQUE_TICK, + &rStatistics.u4DeQueTick)) + goto nla_put_failure; + + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_LINK_LEAVE_DRV_TICK, + &rStatistics.u4LeaveDrvTick)) + goto nla_put_failure; + + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_LINK_CURR_TICK, + &rStatistics.u4CurrTick)) + goto nla_put_failure; + + if (!NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_CURR_TIME, + &rStatistics.u8CurrTime)) + goto nla_put_failure; + + for (i = 0; + i < sizeof(struct EVENT_BUG_REPORT) / sizeof(uint32_t); + i++) { + if (!NLA_PUT_U32(skb, i + NL80211_TESTMODE_LINK_DETECT_NUM, + &arBugReport[i])) + goto nla_put_failure; + } + + i4Status = cfg80211_testmode_reply(skb); + kalMemFree(prBugReport, VIR_MEM_TYPE, + sizeof(struct EVENT_BUG_REPORT)); + return i4Status; + +nla_put_failure: + /* nal_put_skb_fail */ + kfree_skb(skb); + kalMemFree(prBugReport, VIR_MEM_TYPE, + sizeof(struct EVENT_BUG_REPORT)); + return -EFAULT; +} + +int mtk_cfg80211_testmode_sw_cmd(IN struct wiphy *wiphy, + IN struct wireless_dev *wdev, + IN void *data, IN int len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct NL80211_DRIVER_SW_CMD_PARAMS *prParams = + (struct NL80211_DRIVER_SW_CMD_PARAMS *) NULL; + uint32_t rstatus = WLAN_STATUS_SUCCESS; + int fgIsValid = 0; + uint32_t u4SetInfoLen = 0; + + ASSERT(wiphy); + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + +#if 0 + DBGLOG(INIT, INFO, "--> %s()\n", __func__); +#endif + + if (data && len) + prParams = (struct NL80211_DRIVER_SW_CMD_PARAMS *) data; + + if (prParams) { + if (prParams->set == 1) { + rstatus = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC) wlanoidSetSwCtrlWrite, + &prParams->adr, (uint32_t) 8, + FALSE, FALSE, TRUE, &u4SetInfoLen); + } + } + + if (rstatus != WLAN_STATUS_SUCCESS) + fgIsValid = -EFAULT; + + return fgIsValid; +} + +static int mtk_wlan_cfg_testmode_cmd(struct wiphy *wiphy, + struct wireless_dev *wdev, + void *data, int len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct NL80211_DRIVER_TEST_MODE_PARAMS *prParams = NULL; + int32_t i4Status; + + ASSERT(wiphy); + + if (!data || !len) { + DBGLOG(REQ, ERROR, "mtk_cfg80211_testmode_cmd null data\n"); + return -EINVAL; + } + + if (!wiphy) { + DBGLOG(REQ, ERROR, + "mtk_cfg80211_testmode_cmd null wiphy\n"); + return -EINVAL; + } + + prGlueInfo = (struct GLUE_INFO *)wiphy_priv(wiphy); + prParams = (struct NL80211_DRIVER_TEST_MODE_PARAMS *)data; + + /* Clear the version byte */ + prParams->index = prParams->index & ~BITS(24, 31); + DBGLOG(INIT, TRACE, "params index=%x\n", prParams->index); + + switch (prParams->index) { + case TESTMODE_CMD_ID_SW_CMD: /* SW cmd */ + i4Status = mtk_cfg80211_testmode_sw_cmd(wiphy, + wdev, data, len); + break; + case TESTMODE_CMD_ID_WAPI: /* WAPI */ +#if CFG_SUPPORT_WAPI + i4Status = mtk_cfg80211_testmode_set_key_ext(wiphy, + wdev, data, len); +#endif + break; + case 0x10: + i4Status = mtk_cfg80211_testmode_get_sta_statistics(wiphy, + data, len, prGlueInfo); + break; + case 0x20: + i4Status = mtk_cfg80211_testmode_get_link_detection(wiphy, + wdev, data, len, prGlueInfo); + break; +#if CFG_SUPPORT_PASSPOINT + case TESTMODE_CMD_ID_HS20: + i4Status = mtk_cfg80211_testmode_hs20_cmd(wiphy, + wdev, data, len); + break; +#endif /* CFG_SUPPORT_PASSPOINT */ + case TESTMODE_CMD_ID_STR_CMD: + i4Status = mtk_cfg80211_process_str_cmd(wiphy, + wdev, data, len); + break; + + default: + i4Status = -EINVAL; + break; + } + + if (i4Status != 0) + DBGLOG(REQ, TRACE, "prParams->index=%d, status=%d\n", + prParams->index, i4Status); + + return i4Status; +} + +#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_testmode_cmd(struct wiphy *wiphy, + struct wireless_dev *wdev, + void *data, int len) +{ + ASSERT(wdev); + return mtk_wlan_cfg_testmode_cmd(wiphy, wdev, data, len); +} +#else +int mtk_cfg80211_testmode_cmd(struct wiphy *wiphy, + void *data, int len) +{ + return mtk_wlan_cfg_testmode_cmd(wiphy, NULL, data, len); +} +#endif +#endif + +#if CFG_SUPPORT_SCHED_SCAN +int mtk_cfg80211_sched_scan_start(IN struct wiphy *wiphy, + IN struct net_device *ndev, + IN struct cfg80211_sched_scan_request *request) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint32_t i, u4BufLen; + struct PARAM_SCHED_SCAN_REQUEST *prSchedScanRequest; + uint32_t num = 0; + uint8_t ucBssIndex = 0; + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_AIS(prGlueInfo->prAdapter, ucBssIndex)) + return -EINVAL; + + if (likely(request)) { + scanlog_dbg(LOG_SCHED_SCAN_REQ_START_K2D, INFO, "ssid(%d)match(%d)ch(%u)f(%u)rssi(%d)\n", + request->n_ssids, request->n_match_sets, + request->n_channels, request->flags, +#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE + request->min_rssi_thold); +#else + request->rssi_thold); +#endif + } else + scanlog_dbg(LOG_SCHED_SCAN_REQ_START_K2D, INFO, "--> %s()\n", + __func__); + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + if (prGlueInfo->prAdapter == NULL) { + DBGLOG(REQ, ERROR, "prGlueInfo->prAdapter is NULL"); + return -EINVAL; + } + +#if CFG_SUPPORT_LOWLATENCY_MODE + if (!prGlueInfo->prAdapter->fgEnCfg80211Scan + && MEDIA_STATE_CONNECTED + == kalGetMediaStateIndicated(prGlueInfo, ucBssIndex)) { + DBGLOG(REQ, INFO, + "sched_scan_start LowLatency reject scan\n"); + return -EBUSY; + } +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + + if (prGlueInfo->prSchedScanRequest != NULL) { + DBGLOG(SCN, ERROR, + "GlueInfo->prSchedScanRequest != NULL\n"); + return -EBUSY; + } else if (request == NULL) { + DBGLOG(SCN, ERROR, "request == NULL\n"); + return -EINVAL; + } else if (!request->n_match_sets) { + /* invalid scheduled scan request */ + DBGLOG(SCN, ERROR, + "No match sets. No need to do sched scan\n"); + return -EINVAL; + } else if (request->n_match_sets > + CFG_SCAN_SSID_MATCH_MAX_NUM) { + DBGLOG(SCN, WARN, "request->n_match_sets(%d) > %d\n", + request->n_match_sets, + CFG_SCAN_SSID_MATCH_MAX_NUM); + return -EINVAL; + } else if (request->n_ssids > + CFG_SCAN_HIDDEN_SSID_MAX_NUM) { + DBGLOG(SCN, WARN, "request->n_ssids(%d) > %d\n", + request->n_ssids, CFG_SCAN_HIDDEN_SSID_MAX_NUM); + return -EINVAL; + } + + prSchedScanRequest = (struct PARAM_SCHED_SCAN_REQUEST *) + kalMemAlloc(sizeof(struct PARAM_SCHED_SCAN_REQUEST), + VIR_MEM_TYPE); + if (prSchedScanRequest == NULL) { + DBGLOG(SCN, ERROR, "prSchedScanRequest kalMemAlloc fail\n"); + return -ENOMEM; + } + kalMemZero(prSchedScanRequest, + sizeof(struct PARAM_SCHED_SCAN_REQUEST)); + + /* passed in the probe_reqs in active scans */ + if (request->ssids) { + for (i = 0; i < request->n_ssids; i++) { + DBGLOG(SCN, TRACE, "ssids : (%d)[%s]\n", + i, request->ssids[i].ssid); + /* driver ignored the null ssid */ + if (request->ssids[i].ssid_len == 0 + || request->ssids[i].ssid[0] == 0) + DBGLOG(SCN, TRACE, "ignore null ssid(%d)\n", i); + else { + struct PARAM_SSID *prSsid; + + prSsid = &(prSchedScanRequest->arSsid[num]); + COPY_SSID(prSsid->aucSsid, prSsid->u4SsidLen, + request->ssids[i].ssid, + request->ssids[i].ssid_len); + num++; + } + } + } + prSchedScanRequest->u4SsidNum = num; +#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE + prSchedScanRequest->i4MinRssiThold = + request->min_rssi_thold; +#else + prSchedScanRequest->i4MinRssiThold = request->rssi_thold; +#endif + + num = 0; + if (request->match_sets) { + for (i = 0; i < request->n_match_sets; i++) { + DBGLOG(SCN, TRACE, "match : (%d)[%s]\n", i, + request->match_sets[i].ssid.ssid); + /* driver ignored the null ssid */ + if (request->match_sets[i].ssid.ssid_len == 0 + || request->match_sets[i].ssid.ssid[0] == 0) + DBGLOG(SCN, TRACE, "ignore null ssid(%d)\n", i); + else { + struct PARAM_SSID *prSsid = + &(prSchedScanRequest->arMatchSsid[num]); + + COPY_SSID(prSsid->aucSsid, + prSsid->u4SsidLen, + request->match_sets[i].ssid.ssid, + request->match_sets[i].ssid.ssid_len); +#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE + prSchedScanRequest->ai4RssiThold[i] = + request->match_sets[i].rssi_thold; +#else + prSchedScanRequest->ai4RssiThold[i] = + request->rssi_thold; +#endif + num++; + } + } + } + prSchedScanRequest->u4MatchSsidNum = num; + + if (kalSchedScanParseRandomMac(ndev, request, + prSchedScanRequest->aucRandomMac, + prSchedScanRequest->aucRandomMacMask)) { + prSchedScanRequest->ucScnFuncMask |= ENUM_SCN_RANDOM_MAC_EN; + } + + prSchedScanRequest->u4IELength = request->ie_len; + if (request->ie_len > 0) { + prSchedScanRequest->pucIE = + kalMemAlloc(request->ie_len, VIR_MEM_TYPE); + if (prSchedScanRequest->pucIE == NULL) { + DBGLOG(SCN, ERROR, "pucIE kalMemAlloc fail\n"); + } else { + kalMemZero(prSchedScanRequest->pucIE, request->ie_len); + kalMemCopy(prSchedScanRequest->pucIE, + (uint8_t *)request->ie, request->ie_len); + } + } + +#if KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE + prSchedScanRequest->u2ScanInterval = + (uint16_t) (request->scan_plans->interval); +#else + prSchedScanRequest->u2ScanInterval = (uint16_t) ( + request->interval); +#endif + + prSchedScanRequest->ucChnlNum = (uint8_t) + request->n_channels; + prSchedScanRequest->pucChannels = + kalMemAlloc(request->n_channels, VIR_MEM_TYPE); + if (!prSchedScanRequest->pucChannels) { + DBGLOG(SCN, ERROR, "pucChannels kalMemAlloc fail\n"); + prSchedScanRequest->ucChnlNum = 0; + } else { + for (i = 0; i < request->n_channels; i++) { + uint32_t freq = + request->channels[i]->center_freq * 1000; + + prSchedScanRequest->pucChannels[i] = + nicFreq2ChannelNum(freq); + } + } + + prSchedScanRequest->ucBssIndex = ucBssIndex; + rStatus = kalIoctl(prGlueInfo, wlanoidSetStartSchedScan, + prSchedScanRequest, + sizeof(struct PARAM_SCHED_SCAN_REQUEST), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "scheduled scan error:%x\n", rStatus); + kalMemFree(prSchedScanRequest->pucChannels, + VIR_MEM_TYPE, request->n_channels); + kalMemFree(prSchedScanRequest->pucIE, + VIR_MEM_TYPE, request->ie_len); + kalMemFree(prSchedScanRequest, + VIR_MEM_TYPE, sizeof(struct PARAM_SCHED_SCAN_REQUEST)); + return -EINVAL; + } + + /* prSchedScanRequest is owned by oid now, don't free it */ + + return 0; +} + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_sched_scan_stop(IN struct wiphy *wiphy, + IN struct net_device *ndev, + IN u64 reqid) +#else +int mtk_cfg80211_sched_scan_stop(IN struct wiphy *wiphy, + IN struct net_device *ndev) +#endif +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint32_t u4BufLen; + uint8_t ucBssIndex = 0; + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + scanlog_dbg(LOG_SCHED_SCAN_REQ_STOP_K2D, INFO, "--> %s()\n", __func__); + + /* check if there is any pending scan/sched_scan not yet finished */ + if (prGlueInfo->prSchedScanRequest == NULL) + return -EPERM; /* Operation not permitted */ + + rStatus = kalIoctl(prGlueInfo, wlanoidSetStopSchedScan, + NULL, 0, + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_FAILURE) { + DBGLOG(REQ, WARN, "scheduled scan error in IoCtl:%x\n", + rStatus); + return 0; + } else if (rStatus == WLAN_STATUS_RESOURCES) { + DBGLOG(REQ, WARN, "scheduled scan error in Driver:%x\n", + rStatus); + return -EINVAL; + } + + return 0; +} +#endif /* CFG_SUPPORT_SCHED_SCAN */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for handling association request + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_assoc(struct wiphy *wiphy, + struct net_device *ndev, struct cfg80211_assoc_request *req) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t arBssid[PARAM_MAC_ADDR_LEN]; +#if CFG_SUPPORT_PASSPOINT + uint8_t *prDesiredIE = NULL; +#endif /* CFG_SUPPORT_PASSPOINT */ + uint32_t rStatus; + uint32_t u4BufLen; + uint8_t ucBssIndex = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + kalMemZero(arBssid, MAC_ADDR_LEN); + SET_IOCTL_BSSIDX(prGlueInfo->prAdapter, ucBssIndex); + wlanQueryInformation(prGlueInfo->prAdapter, wlanoidQueryBssid, + &arBssid[0], sizeof(arBssid), &u4BufLen); + + /* 1. check BSSID */ + if (UNEQUAL_MAC_ADDR(arBssid, req->bss->bssid)) { + /* wrong MAC address */ + DBGLOG(REQ, WARN, + "incorrect BSSID: [" MACSTR + "] currently connected BSSID[" + MACSTR "]\n", + MAC2STR(req->bss->bssid), MAC2STR(arBssid)); + return -ENOENT; + } + + if (req->ie && req->ie_len > 0) { +#if CFG_SUPPORT_PASSPOINT + if (wextSrchDesiredHS20IE((uint8_t *) req->ie, req->ie_len, + (uint8_t **) &prDesiredIE)) { + rStatus = kalIoctlByBssIdx(prGlueInfo, + wlanoidSetHS20Info, + prDesiredIE, IE_SIZE(prDesiredIE), + FALSE, FALSE, TRUE, &u4BufLen, + ucBssIndex); + if (rStatus != WLAN_STATUS_SUCCESS) { + /* DBGLOG(REQ, TRACE, + * ("[HS20] set HS20 assoc info error:%x\n", + * rStatus)); + */ + } + } +#endif /* CFG_SUPPORT_PASSPOINT */ + } + + rStatus = kalIoctlByBssIdx(prGlueInfo, wlanoidSetBssid, + (void *)req->bss->bssid, MAC_ADDR_LEN, + FALSE, FALSE, TRUE, &u4BufLen, + ucBssIndex); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set BSSID:%x\n", rStatus); + return -EINVAL; + } + + return 0; +} + +#if CFG_SUPPORT_NFC_BEAM_PLUS + +int mtk_cfg80211_testmode_get_scan_done(IN struct wiphy + *wiphy, IN void *data, IN int len, + IN struct GLUE_INFO *prGlueInfo) +{ + int32_t i4Status = -EINVAL; + +#ifdef CONFIG_NL80211_TESTMODE +#define NL80211_TESTMODE_P2P_SCANDONE_INVALID 0 +#define NL80211_TESTMODE_P2P_SCANDONE_STATUS 1 + + uint32_t rStatus = WLAN_STATUS_SUCCESS; + int32_t READY_TO_BEAM = 0; + + struct sk_buff *skb = NULL; + + ASSERT(wiphy); + ASSERT(prGlueInfo); + + skb = cfg80211_testmode_alloc_reply_skb(wiphy, + sizeof(uint32_t)); + + /* READY_TO_BEAM = + * (UINT_32)(prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo + * .fgIsGOInitialDone) + * &(!prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo + * .fgIsScanRequest); + */ + READY_TO_BEAM = 1; + /* DBGLOG(QM, TRACE, + * "NFC:GOInitialDone[%d] and P2PScanning[%d]\n", + * prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo + * .fgIsGOInitialDone, + * prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo + * .fgIsScanRequest)); + */ + + if (!skb) { + DBGLOG(QM, TRACE, "%s allocate skb failed:%x\n", __func__, + rStatus); + return -ENOMEM; + } + { + u8 __tmp = 0; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_P2P_SCANDONE_INVALID, + sizeof(u8), &__tmp) < 0)) { + kfree_skb(skb); + return -EINVAL; + } + } + { + u32 __tmp = READY_TO_BEAM; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_P2P_SCANDONE_STATUS, + sizeof(u32), &__tmp) < 0)) { + kfree_skb(skb); + return -EINVAL; + } + } + + i4Status = cfg80211_testmode_reply(skb); +#else + DBGLOG(QM, WARN, "CONFIG_NL80211_TESTMODE not enabled\n"); +#endif + return i4Status; +} + +#endif + +#if CFG_SUPPORT_TDLS + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for changing a station information + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int +mtk_cfg80211_change_station(struct wiphy *wiphy, + struct net_device *ndev, const u8 *mac, + struct station_parameters *params) +{ + + /* return 0; */ + + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + struct GLUE_INFO *prGlueInfo = NULL; + struct CMD_PEER_UPDATE rCmdUpdate; + uint32_t rStatus; + uint32_t u4BufLen, u4Temp; + struct ADAPTER *prAdapter; + struct BSS_INFO *prBssInfo; + uint8_t ucBssIndex = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + /* make up command */ + + prAdapter = prGlueInfo->prAdapter; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex); + if (!prBssInfo) + return -EINVAL; + + if (params == NULL) + return 0; + else if (params->supported_rates == NULL) + return 0; + + /* init */ + kalMemZero(&rCmdUpdate, sizeof(rCmdUpdate)); + kalMemCopy(rCmdUpdate.aucPeerMac, mac, 6); + + if (params->supported_rates != NULL) { + + u4Temp = params->supported_rates_len; + if (u4Temp > CMD_PEER_UPDATE_SUP_RATE_MAX) + u4Temp = CMD_PEER_UPDATE_SUP_RATE_MAX; + kalMemCopy(rCmdUpdate.aucSupRate, params->supported_rates, + u4Temp); + rCmdUpdate.u2SupRateLen = u4Temp; + } + + /* + * In supplicant, only recognize WLAN_EID_QOS 46, not 0xDD WMM + * So force to support UAPSD here. + */ + rCmdUpdate.UapsdBitmap = 0x0F; /*params->uapsd_queues; */ + rCmdUpdate.UapsdMaxSp = 0; /*params->max_sp; */ + + rCmdUpdate.u2Capability = params->capability; + + if (params->ext_capab != NULL) { + + u4Temp = params->ext_capab_len; + if (u4Temp > CMD_PEER_UPDATE_EXT_CAP_MAXLEN) + u4Temp = CMD_PEER_UPDATE_EXT_CAP_MAXLEN; + kalMemCopy(rCmdUpdate.aucExtCap, params->ext_capab, u4Temp); + rCmdUpdate.u2ExtCapLen = u4Temp; + } + + if (params->ht_capa != NULL) { + + rCmdUpdate.rHtCap.u2CapInfo = params->ht_capa->cap_info; + rCmdUpdate.rHtCap.ucAmpduParamsInfo = + params->ht_capa->ampdu_params_info; + rCmdUpdate.rHtCap.u2ExtHtCapInfo = + params->ht_capa->extended_ht_cap_info; + rCmdUpdate.rHtCap.u4TxBfCapInfo = + params->ht_capa->tx_BF_cap_info; + rCmdUpdate.rHtCap.ucAntennaSelInfo = + params->ht_capa->antenna_selection_info; + kalMemCopy(rCmdUpdate.rHtCap.rMCS.arRxMask, + params->ht_capa->mcs.rx_mask, + sizeof(rCmdUpdate.rHtCap.rMCS.arRxMask)); + + rCmdUpdate.rHtCap.rMCS.u2RxHighest = + params->ht_capa->mcs.rx_highest; + rCmdUpdate.rHtCap.rMCS.ucTxParams = + params->ht_capa->mcs.tx_params; + rCmdUpdate.fgIsSupHt = TRUE; + } + /* vht */ + + if (params->vht_capa != NULL) { + /* rCmdUpdate.rVHtCap */ + /* rCmdUpdate.rVHtCap */ + } + + /* update a TDLS peer record */ + /* sanity check */ + if ((params->sta_flags_set & BIT( + NL80211_STA_FLAG_TDLS_PEER))) + rCmdUpdate.eStaType = STA_TYPE_DLS_PEER; + rCmdUpdate.ucBssIdx = ucBssIndex; + rStatus = kalIoctl(prGlueInfo, cnmPeerUpdate, &rCmdUpdate, + sizeof(struct CMD_PEER_UPDATE), FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EINVAL; + /* for Ch Sw AP prohibit case */ + if (prBssInfo->fgTdlsIsChSwProhibited) { + /* disable TDLS ch sw function */ + + rStatus = kalIoctl(prGlueInfo, + TdlsSendChSwControlCmd, + &TdlsSendChSwControlCmd, + sizeof(struct CMD_TDLS_CH_SW), + FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + } + + return 0; +} +#else +int +mtk_cfg80211_change_station(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac, + struct station_parameters *params) +{ + + /* return 0; */ + + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + struct GLUE_INFO *prGlueInfo = NULL; + struct CMD_PEER_UPDATE rCmdUpdate; + uint32_t rStatus; + uint32_t u4BufLen, u4Temp; + struct ADAPTER *prAdapter; + struct BSS_INFO *prBssInfo; + uint8_t ucBssIndex = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + /* make up command */ + + prAdapter = prGlueInfo->prAdapter; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex); + if (!prBssInfo) + return -EINVAL; + + if (params == NULL) + return 0; + else if (params->supported_rates == NULL) + return 0; + + /* init */ + kalMemZero(&rCmdUpdate, sizeof(rCmdUpdate)); + kalMemCopy(rCmdUpdate.aucPeerMac, mac, 6); + + if (params->supported_rates != NULL) { + + u4Temp = params->supported_rates_len; + if (u4Temp > CMD_PEER_UPDATE_SUP_RATE_MAX) + u4Temp = CMD_PEER_UPDATE_SUP_RATE_MAX; + kalMemCopy(rCmdUpdate.aucSupRate, params->supported_rates, + u4Temp); + rCmdUpdate.u2SupRateLen = u4Temp; + } + + /* + * In supplicant, only recognize WLAN_EID_QOS 46, not 0xDD WMM + * So force to support UAPSD here. + */ + rCmdUpdate.UapsdBitmap = 0x0F; /*params->uapsd_queues; */ + rCmdUpdate.UapsdMaxSp = 0; /*params->max_sp; */ + + rCmdUpdate.u2Capability = params->capability; + + if (params->ext_capab != NULL) { + + u4Temp = params->ext_capab_len; + if (u4Temp > CMD_PEER_UPDATE_EXT_CAP_MAXLEN) + u4Temp = CMD_PEER_UPDATE_EXT_CAP_MAXLEN; + kalMemCopy(rCmdUpdate.aucExtCap, params->ext_capab, u4Temp); + rCmdUpdate.u2ExtCapLen = u4Temp; + } + + if (params->ht_capa != NULL) { + + rCmdUpdate.rHtCap.u2CapInfo = params->ht_capa->cap_info; + rCmdUpdate.rHtCap.ucAmpduParamsInfo = + params->ht_capa->ampdu_params_info; + rCmdUpdate.rHtCap.u2ExtHtCapInfo = + params->ht_capa->extended_ht_cap_info; + rCmdUpdate.rHtCap.u4TxBfCapInfo = + params->ht_capa->tx_BF_cap_info; + rCmdUpdate.rHtCap.ucAntennaSelInfo = + params->ht_capa->antenna_selection_info; + kalMemCopy(rCmdUpdate.rHtCap.rMCS.arRxMask, + params->ht_capa->mcs.rx_mask, + sizeof(rCmdUpdate.rHtCap.rMCS.arRxMask)); + + rCmdUpdate.rHtCap.rMCS.u2RxHighest = + params->ht_capa->mcs.rx_highest; + rCmdUpdate.rHtCap.rMCS.ucTxParams = + params->ht_capa->mcs.tx_params; + rCmdUpdate.fgIsSupHt = TRUE; + } + /* vht */ + + if (params->vht_capa != NULL) { + /* rCmdUpdate.rVHtCap */ + /* rCmdUpdate.rVHtCap */ + } + + /* update a TDLS peer record */ + /* sanity check */ + if ((params->sta_flags_set & BIT( + NL80211_STA_FLAG_TDLS_PEER))) + rCmdUpdate.eStaType = STA_TYPE_DLS_PEER; + rCmdUpdate.ucBssIdx = ucBssIndex; + rStatus = kalIoctl(prGlueInfo, cnmPeerUpdate, &rCmdUpdate, + sizeof(struct CMD_PEER_UPDATE), FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EINVAL; + /* for Ch Sw AP prohibit case */ + if (prBssInfo->fgTdlsIsChSwProhibited) { + /* disable TDLS ch sw function */ + + rStatus = kalIoctl(prGlueInfo, + TdlsSendChSwControlCmd, + &TdlsSendChSwControlCmd, + sizeof(struct CMD_TDLS_CH_SW), + FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + } + + return 0; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for adding a station information + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_add_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, struct station_parameters *params) +{ + /* return 0; */ + + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + struct GLUE_INFO *prGlueInfo = NULL; + struct CMD_PEER_ADD rCmdCreate; + struct ADAPTER *prAdapter; + uint32_t rStatus; + uint32_t u4BufLen; + uint8_t ucBssIndex = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + /* make up command */ + + prAdapter = prGlueInfo->prAdapter; + + /* init */ + kalMemZero(&rCmdCreate, sizeof(rCmdCreate)); + kalMemCopy(rCmdCreate.aucPeerMac, mac, 6); + + /* create a TDLS peer record */ + if ((params->sta_flags_set & BIT( + NL80211_STA_FLAG_TDLS_PEER))) { + rCmdCreate.eStaType = STA_TYPE_DLS_PEER; + rCmdCreate.ucBssIdx = ucBssIndex; + rStatus = kalIoctl(prGlueInfo, cnmPeerAdd, &rCmdCreate, + sizeof(struct CMD_PEER_ADD), + FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EINVAL; + } + + return 0; +} +#else +int mtk_cfg80211_add_station(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac, + struct station_parameters *params) +{ + /* return 0; */ + + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + struct GLUE_INFO *prGlueInfo = NULL; + struct CMD_PEER_ADD rCmdCreate; + struct ADAPTER *prAdapter; + uint32_t rStatus; + uint32_t u4BufLen; + uint8_t ucBssIndex = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + /* make up command */ + + prAdapter = prGlueInfo->prAdapter; + + /* init */ + kalMemZero(&rCmdCreate, sizeof(rCmdCreate)); + kalMemCopy(rCmdCreate.aucPeerMac, mac, 6); + + /* create a TDLS peer record */ + if ((params->sta_flags_set & BIT( + NL80211_STA_FLAG_TDLS_PEER))) { + rCmdCreate.eStaType = STA_TYPE_DLS_PEER; + rCmdCreate.ucBssIdx = ucBssIndex; + rStatus = kalIoctl(prGlueInfo, cnmPeerAdd, &rCmdCreate, + sizeof(struct CMD_PEER_ADD), + FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EINVAL; + } + + return 0; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for deleting a station information + * + * @param + * + * @retval 0: successful + * others: failure + * + * @other + * must implement if you have add_station(). + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +#if KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE +static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +int mtk_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *ndev, + struct station_del_parameters *params) +{ + /* fgIsTDLSlinkEnable = 0; */ + + /* return 0; */ + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + + const u8 *mac = params->mac ? params->mac : bcast_addr; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter; + struct STA_RECORD *prStaRec; + u8 deleteMac[MAC_ADDR_LEN]; + uint8_t ucBssIndex = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + prAdapter = prGlueInfo->prAdapter; + + /* For kernel 3.18 modification, we trasfer to local buff to query + * sta + */ + memset(deleteMac, 0, MAC_ADDR_LEN); + memcpy(deleteMac, mac, MAC_ADDR_LEN); + + prStaRec = cnmGetStaRecByAddress(prAdapter, + (uint8_t) ucBssIndex, deleteMac); + + if (prStaRec != NULL) + cnmStaRecFree(prAdapter, prStaRec); + + return 0; +} +#else +int mtk_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *ndev, const u8 *mac) +{ + /* fgIsTDLSlinkEnable = 0; */ + + /* return 0; */ + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter; + struct STA_RECORD *prStaRec; + u8 deleteMac[MAC_ADDR_LEN]; + uint8_t ucBssIndex = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + prAdapter = prGlueInfo->prAdapter; + + /* For kernel 3.18 modification, we trasfer to local buff to query + * sta + */ + memset(deleteMac, 0, MAC_ADDR_LEN); + memcpy(deleteMac, mac, MAC_ADDR_LEN); + + prStaRec = cnmGetStaRecByAddress(prAdapter, + (uint8_t) ucBssIndex, deleteMac); + + if (prStaRec != NULL) + cnmStaRecFree(prAdapter, prStaRec); + + return 0; +} +#endif +#else +int mtk_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac) +{ + /* fgIsTDLSlinkEnable = 0; */ + + /* return 0; */ + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter; + struct STA_RECORD *prStaRec; + uint8_t ucBssIndex = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + prAdapter = prGlueInfo->prAdapter; + + prStaRec = cnmGetStaRecByAddress(prAdapter, + (uint8_t) ucBssIndex, mac); + + if (prStaRec != NULL) + cnmStaRecFree(prAdapter, prStaRec); + + return 0; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to transmit a TDLS data frame from nl80211. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[in] + * \param[in] + * \param[in] buf includes RSN IE + FT IE + Lifetimeout IE + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE +int +mtk_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, + bool initiator, const u8 *buf, size_t len) +{ + struct GLUE_INFO *prGlueInfo; + struct TDLS_CMD_LINK_MGT rCmdMgt; + uint32_t u4BufLen; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint8_t ucBssIndex = 0; + + ucBssIndex = wlanGetBssIdx(dev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + /* sanity check */ + if ((wiphy == NULL) || (peer == NULL) || (buf == NULL)) + return -EINVAL; + + /* init */ + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + if (prGlueInfo == NULL) + return -EINVAL; + + kalMemZero(&rCmdMgt, sizeof(rCmdMgt)); + rCmdMgt.u2StatusCode = status_code; + rCmdMgt.u4SecBufLen = len; + rCmdMgt.ucDialogToken = dialog_token; + rCmdMgt.ucActionCode = action_code; + kalMemCopy(&(rCmdMgt.aucPeer), peer, 6); + + if (len > TDLS_SEC_BUF_LENGTH) { + DBGLOG(REQ, WARN, "%s:len > TDLS_SEC_BUF_LENGTH\n", __func__); + return -EINVAL; + } + + kalMemCopy(&(rCmdMgt.aucSecBuf), buf, len); + rCmdMgt.ucBssIdx = ucBssIndex; + rStatus = kalIoctl(prGlueInfo, TdlsexLinkMgt, &rCmdMgt, + sizeof(struct TDLS_CMD_LINK_MGT), FALSE, TRUE, FALSE, + &u4BufLen); + + DBGLOG(REQ, INFO, "rStatus: %x", rStatus); + + if (rStatus == WLAN_STATUS_SUCCESS) + return 0; + else + return -EINVAL; +} +#elif KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int +mtk_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, + const u8 *buf, size_t len) +{ + struct GLUE_INFO *prGlueInfo; + struct TDLS_CMD_LINK_MGT rCmdMgt; + uint32_t u4BufLen; + uint8_t ucBssIndex = 0; + + ucBssIndex = wlanGetBssIdx(dev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + /* sanity check */ + if ((wiphy == NULL) || (peer == NULL) || (buf == NULL)) + return -EINVAL; + + /* init */ + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + if (prGlueInfo == NULL) + return -EINVAL; + + kalMemZero(&rCmdMgt, sizeof(rCmdMgt)); + rCmdMgt.u2StatusCode = status_code; + rCmdMgt.u4SecBufLen = len; + rCmdMgt.ucDialogToken = dialog_token; + rCmdMgt.ucActionCode = action_code; + kalMemCopy(&(rCmdMgt.aucPeer), peer, 6); + kalMemCopy(&(rCmdMgt.aucSecBuf), buf, len); + rCmdMgt.ucBssIdx = ucBssIndex; + kalIoctl(prGlueInfo, TdlsexLinkMgt, &rCmdMgt, + sizeof(struct TDLS_CMD_LINK_MGT), FALSE, TRUE, FALSE, + &u4BufLen); + return 0; + +} + +#else +int +mtk_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, const u8 *buf, size_t len) +{ + struct GLUE_INFO *prGlueInfo; + struct TDLS_CMD_LINK_MGT rCmdMgt; + uint32_t u4BufLen; + uint8_t ucBssIndex = 0; + + ucBssIndex = wlanGetBssIdx(dev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + /* sanity check */ + if ((wiphy == NULL) || (peer == NULL) || (buf == NULL)) + return -EINVAL; + + /* init */ + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + if (prGlueInfo == NULL) + return -EINVAL; + + kalMemZero(&rCmdMgt, sizeof(rCmdMgt)); + rCmdMgt.u2StatusCode = status_code; + rCmdMgt.u4SecBufLen = len; + rCmdMgt.ucDialogToken = dialog_token; + rCmdMgt.ucActionCode = action_code; + kalMemCopy(&(rCmdMgt.aucPeer), peer, 6); + if (len > TDLS_SEC_BUF_LENGTH) + DBGLOG(REQ, WARN, + "In mtk_cfg80211_tdls_mgmt , len > TDLS_SEC_BUF_LENGTH, please check\n"); + else + kalMemCopy(&(rCmdMgt.aucSecBuf), buf, len); + rCmdMgt.ucBssIdx = ucBssIndex; + kalIoctl(prGlueInfo, TdlsexLinkMgt, &rCmdMgt, + sizeof(struct TDLS_CMD_LINK_MGT), FALSE, TRUE, FALSE, + &u4BufLen); + return 0; + +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to hadel TDLS link from nl80211. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[in] + * \param[in] + * \param[in] buf includes RSN IE + FT IE + Lifetimeout IE + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_tdls_oper(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, enum nl80211_tdls_operation oper) +{ + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4BufLen; + struct ADAPTER *prAdapter; + struct TDLS_CMD_LINK_OPER rCmdOper; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint8_t ucBssIndex = 0; + + ucBssIndex = wlanGetBssIdx(dev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + DBGLOG(REQ, INFO, "ucBssIndex = %d, oper=%d", + ucBssIndex, oper); + + ASSERT(prGlueInfo); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rCmdOper, sizeof(rCmdOper)); + kalMemCopy(rCmdOper.aucPeerMac, peer, 6); + + rCmdOper.oper = (enum ENUM_TDLS_LINK_OPER)oper; + rCmdOper.ucBssIdx = ucBssIndex; + rStatus = kalIoctl(prGlueInfo, TdlsexLinkOper, &rCmdOper, + sizeof(struct TDLS_CMD_LINK_OPER), FALSE, FALSE, FALSE, + &u4BufLen); + + DBGLOG(REQ, INFO, "rStatus: %x", rStatus); + + if (rStatus == WLAN_STATUS_SUCCESS) + return 0; + else + return -EINVAL; +} +#else +int mtk_cfg80211_tdls_oper(struct wiphy *wiphy, + struct net_device *dev, u8 *peer, + enum nl80211_tdls_operation oper) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4BufLen; + struct ADAPTER *prAdapter; + struct TDLS_CMD_LINK_OPER rCmdOper; + uint8_t ucBssIndex = 0; + + ucBssIndex = wlanGetBssIdx(dev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, INFO, "ucBssIndex = %d, oper=%d", + ucBssIndex, oper); + + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rCmdOper, sizeof(rCmdOper)); + kalMemCopy(rCmdOper.aucPeerMac, peer, 6); + + rCmdOper.oper = oper; + rCmdOper.ucBssIdx = ucBssIndex; + + kalIoctl(prGlueInfo, TdlsexLinkOper, &rCmdOper, + sizeof(struct TDLS_CMD_LINK_OPER), FALSE, FALSE, FALSE, + &u4BufLen); + return 0; +} +#endif +#endif + +#ifdef CONFIG_NL80211_TESTMODE +#if CFG_SUPPORT_NCHO +/* NCHO related command definition. Setting by supplicant */ +#define CMD_NCHO_ROAM_TRIGGER_GET "GETROAMTRIGGER" +#define CMD_NCHO_ROAM_TRIGGER_SET "SETROAMTRIGGER" +#define CMD_NCHO_ROAM_DELTA_GET "GETROAMDELTA" +#define CMD_NCHO_ROAM_DELTA_SET "SETROAMDELTA" +#define CMD_NCHO_ROAM_SCAN_PERIOD_GET "GETROAMSCANPERIOD" +#define CMD_NCHO_ROAM_SCAN_PERIOD_SET "SETROAMSCANPERIOD" +#define CMD_NCHO_ROAM_SCAN_CHANNELS_GET "GETROAMSCANCHANNELS" +#define CMD_NCHO_ROAM_SCAN_CHANNELS_SET "SETROAMSCANCHANNELS" +#define CMD_NCHO_ROAM_SCAN_CHANNELS_ADD "ADDROAMSCANCHANNELS" +#define CMD_NCHO_ROAM_SCAN_CONTROL_GET "GETROAMSCANCONTROL" +#define CMD_NCHO_ROAM_SCAN_CONTROL_SET "SETROAMSCANCONTROL" +#define CMD_NCHO_MODE_SET "SETNCHOMODE" +#define CMD_NCHO_MODE_GET "GETNCHOMODE" + +int testmode_set_ncho_roam_trigger(IN struct wiphy *wiphy, + IN char *pcCommand, IN int i4TotalLen) +{ + int32_t i4Param = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + int32_t i4Ret = -1; + uint32_t u4SetInfoLen = 0; + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)wiphy_priv(wiphy); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, apcArgv[1]); + i4Ret = kalkStrtos32(apcArgv[1], 0, &i4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", + i4Ret); + return WLAN_STATUS_INVALID_DATA; + } + + DBGLOG(INIT, TRACE, "NCHO set roam trigger cmd %d\n", i4Param); + rStatus = kalIoctl(prGlueInfo, wlanoidSetNchoRoamTrigger, + &i4Param, sizeof(int32_t), + FALSE, FALSE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, ERROR, "NCHO set roam trigger fail 0x%x\n", + rStatus); + else + DBGLOG(INIT, TRACE, + "NCHO set roam trigger successed\n"); + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + rStatus = WLAN_STATUS_INVALID_DATA; + } + return rStatus; +} + +int testmode_get_ncho_roam_trigger(IN struct wiphy *wiphy, + IN char *pcCommand, IN int i4TotalLen) +{ + int32_t i4BytesWritten = -1; + int32_t i4Param = 0; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER cmdV1Header; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)wiphy_priv(wiphy); + char buf[512]; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return rStatus; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryNchoRoamTrigger, + &cmdV1Header, sizeof(cmdV1Header), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "NCHO wlanoidQueryNchoRoamTrigger fail 0x%x\n", rStatus); + return rStatus; + } + + i4BytesWritten = kalkStrtou32(cmdV1Header.buffer, 0, &i4Param); + if (i4BytesWritten) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d!\n", + i4BytesWritten); + return WLAN_STATUS_NOT_INDICATING; + } + + i4Param = RCPI_TO_dBm(i4Param); /* RCPI to DB */ + i4BytesWritten = snprintf(buf, 512, + CMD_NCHO_ROAM_TRIGGER_GET" %d", i4Param); + DBGLOG(INIT, INFO, "NCHO query RoamTrigger is [%s][%s]\n", + cmdV1Header.buffer, pcCommand); + + return mtk_cfg80211_process_str_cmd_reply(wiphy, + buf, i4BytesWritten + 1); +} + +int testmode_set_ncho_roam_delta(IN struct wiphy *wiphy, + IN char *pcCommand, IN int i4TotalLen) +{ + int32_t i4Param = 0; + uint32_t u4SetInfoLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + int32_t i4Ret = -1; + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)wiphy_priv(wiphy); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, apcArgv[1]); + i4Ret = kalkStrtos32(apcArgv[1], 0, &i4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, + "NCHO parse u4Param error %d\n", i4Ret); + return WLAN_STATUS_INVALID_DATA; + } + + DBGLOG(INIT, TRACE, "NCHO set roam delta cmd %d\n", i4Param); + rStatus = kalIoctl(prGlueInfo, wlanoidSetNchoRoamDelta, + &i4Param, sizeof(int32_t), + FALSE, FALSE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, ERROR, + "NCHO set roam delta fail 0x%x\n", rStatus); + else + DBGLOG(INIT, TRACE, "NCHO set roam delta successed\n"); + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + rStatus = WLAN_STATUS_INVALID_DATA; + } + return rStatus; +} + +int testmode_get_ncho_roam_delta(IN struct wiphy *wiphy, + IN char *pcCommand, IN int i4TotalLen) +{ + int32_t i4BytesWritten = -1; + int32_t i4Param = 0; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)wiphy_priv(wiphy); + char buf[512]; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return rStatus; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryNchoRoamDelta, + &i4Param, sizeof(int32_t), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "NCHO wlanoidQueryNchoRoamDelta fail 0x%x\n", rStatus); + return rStatus; + } + + i4BytesWritten = snprintf(buf, 512, + CMD_NCHO_ROAM_DELTA_GET" %d", i4Param); + DBGLOG(REQ, TRACE, "NCHO query ok and ret is [%d][%s]\n", + i4Param, buf); + + return mtk_cfg80211_process_str_cmd_reply(wiphy, + buf, i4BytesWritten + 1); +} + +int testmode_set_ncho_roam_scn_period(IN struct wiphy *wiphy, + IN char *pcCommand, IN int i4TotalLen) +{ + uint32_t u4Param = 0; + uint32_t u4SetInfoLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + int32_t i4Ret = -1; + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)wiphy_priv(wiphy); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, apcArgv[1]); + i4Ret = kalkStrtou32(apcArgv[1], 0, &u4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", + i4Ret); + return -1; + } + + DBGLOG(INIT, TRACE, "NCHO set roam period cmd %d\n", u4Param); + rStatus = kalIoctl(prGlueInfo, wlanoidSetNchoRoamScnPeriod, + &u4Param, sizeof(uint32_t), + FALSE, FALSE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, ERROR, "NCHO set roam period fail 0x%x\n", + rStatus); + else + DBGLOG(INIT, TRACE, "NCHO set roam period successed\n"); + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + rStatus = WLAN_STATUS_INVALID_DATA; + } + return rStatus; +} + +int testmode_get_ncho_roam_scn_period(IN struct wiphy *wiphy, + IN char *pcCommand, IN int i4TotalLen) +{ + int32_t i4BytesWritten = -1; + int32_t i4Param = 0; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER cmdV1Header; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)wiphy_priv(wiphy); + char buf[512]; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return rStatus; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryNchoRoamScnPeriod, + &cmdV1Header, sizeof(cmdV1Header), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "NCHO wlanoidQueryNchoRoamTrigger fail 0x%x\n", rStatus); + return rStatus; + } + + i4BytesWritten = kalkStrtou32(cmdV1Header.buffer, 0, &i4Param); + if (i4BytesWritten) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d!\n", + i4BytesWritten); + return WLAN_STATUS_NOT_INDICATING; + } + + i4BytesWritten = snprintf(buf, 512, + CMD_NCHO_ROAM_SCAN_PERIOD_GET" %d", i4Param); + DBGLOG(INIT, INFO, "NCHO query Roam Period is [%s][%s]\n", + cmdV1Header.buffer, buf); + + return mtk_cfg80211_process_str_cmd_reply(wiphy, + buf, i4BytesWritten + 1); +} + +int testmode_set_ncho_roam_scn_chnl(IN struct wiphy *wiphy, + IN char *pcCommand, IN int i4TotalLen, IN uint8_t changeMode) +{ + uint32_t u4ChnlInfo = 0; + uint8_t i = 1; + uint8_t t = 0; + uint32_t u4SetInfoLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + int32_t i4Ret = -1; + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CFG_NCHO_SCAN_CHNL rRoamScnChnl; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)wiphy_priv(wiphy); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, cmd is %s\n", i4Argc, + apcArgv[1]); + i4Ret = kalkStrtou32(apcArgv[1], 0, &u4ChnlInfo); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", + i4Ret); + return WLAN_STATUS_INVALID_DATA; + } + + rRoamScnChnl.ucChannelListNum = u4ChnlInfo; + DBGLOG(REQ, INFO, "NCHO ChannelListNum is %d\n", u4ChnlInfo); + if (i4Argc != u4ChnlInfo + 2) { + DBGLOG(REQ, ERROR, "NCHO param mismatch %d\n", + u4ChnlInfo); + return WLAN_STATUS_INVALID_DATA; + } + for (i = 2; i < i4Argc; i++) { + i4Ret = kalkStrtou32(apcArgv[i], 0, &u4ChnlInfo); + if (i4Ret) { + while (i != 2) { + rRoamScnChnl.arChnlInfoList[i] + .ucChannelNum = 0; + i--; + } + DBGLOG(REQ, ERROR, + "NCHO parse chnl num error %d\n", i4Ret); + return -1; + } + if (u4ChnlInfo != 0) { + DBGLOG(INIT, TRACE, + "NCHO t = %d, channel value=%d\n", + t, u4ChnlInfo); + if ((u4ChnlInfo >= 1) && (u4ChnlInfo <= 14)) + rRoamScnChnl.arChnlInfoList[t].eBand = + BAND_2G4; + else + rRoamScnChnl.arChnlInfoList[t].eBand = + BAND_5G; + + rRoamScnChnl.arChnlInfoList[t].ucChannelNum = + u4ChnlInfo; + t++; + } + + } + + DBGLOG(INIT, TRACE, "NCHO %s roam scan channel cmd\n", + changeMode ? "set" : "add"); + if (changeMode) + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNchoRoamScnChnl, &rRoamScnChnl, + sizeof(struct CFG_NCHO_SCAN_CHNL), + FALSE, FALSE, TRUE, &u4SetInfoLen); + else + rStatus = kalIoctl(prGlueInfo, + wlanoidAddNchoRoamScnChnl, &rRoamScnChnl, + sizeof(struct CFG_NCHO_SCAN_CHNL), + FALSE, FALSE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, ERROR, + "NCHO set roam scan channel fail 0x%x\n", + rStatus); + else + DBGLOG(INIT, TRACE, + "NCHO set roam scan channel successed\n"); + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + rStatus = WLAN_STATUS_INVALID_DATA; + } + return rStatus; +} + +int testmode_get_ncho_roam_scn_chnl(IN struct wiphy *wiphy, + IN char *pcCommand, IN int i4TotalLen) +{ + uint8_t i = 0; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = -1; + int32_t i4Argc = 0; + uint32_t u4ChnlInfo = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + struct CFG_NCHO_SCAN_CHNL rRoamScnChnl; + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)wiphy_priv(wiphy); + char buf[512]; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return rStatus; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryNchoRoamScnChnl, + &rRoamScnChnl, sizeof(struct CFG_NCHO_SCAN_CHNL), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "NCHO wlanoidQueryNchoRoamScnChnl fail 0x%x\n", rStatus); + return rStatus; + } + + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %d\n", + rRoamScnChnl.ucChannelListNum); + u4ChnlInfo = rRoamScnChnl.ucChannelListNum; + i4BytesWritten = 0; + i4BytesWritten += snprintf(buf + i4BytesWritten, + 512 - i4BytesWritten, + CMD_NCHO_ROAM_SCAN_CHANNELS_GET" %u", + u4ChnlInfo); + for (i = 0; i < rRoamScnChnl.ucChannelListNum; i++) { + u4ChnlInfo = + rRoamScnChnl.arChnlInfoList[i].ucChannelNum; + i4BytesWritten += snprintf(buf + i4BytesWritten, + 512 - i4BytesWritten, + " %u", u4ChnlInfo); + } + + DBGLOG(REQ, INFO, "NCHO get scn chl list num is [%d][%s]\n", + rRoamScnChnl.ucChannelListNum, buf); + + return mtk_cfg80211_process_str_cmd_reply(wiphy, + buf, i4BytesWritten + 1); +} + +int testmode_set_ncho_roam_scn_ctrl(IN struct wiphy *wiphy, + IN char *pcCommand, IN int i4TotalLen) +{ + uint32_t u4Param = 0; + uint32_t u4SetInfoLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + int32_t i4Ret = -1; + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)wiphy_priv(wiphy); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, apcArgv[1]); + i4Ret = kalkStrtou32(apcArgv[1], 0, &u4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", + i4Ret); + return -1; + } + + DBGLOG(INIT, TRACE, "NCHO set roam scan control cmd %d\n", + u4Param); + rStatus = kalIoctl(prGlueInfo, wlanoidSetNchoRoamScnCtrl, + &u4Param, sizeof(uint32_t), + FALSE, FALSE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, ERROR, + "NCHO set roam scan control fail 0x%x\n", + rStatus); + else + DBGLOG(INIT, TRACE, + "NCHO set roam scan control successed\n"); + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + rStatus = WLAN_STATUS_INVALID_DATA; + } + return rStatus; +} + +int testmode_get_ncho_roam_scn_ctrl(IN struct wiphy *wiphy, + IN char *pcCommand, IN int i4TotalLen) +{ + int32_t i4BytesWritten = -1; + uint32_t u4Param = 0; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)wiphy_priv(wiphy); + char buf[512]; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return WLAN_STATUS_INVALID_DATA; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryNchoRoamScnCtrl, + &u4Param, sizeof(uint32_t), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "NCHO wlanoidQueryNchoRoamScnCtrl fail 0x%x\n", rStatus); + return rStatus; + } + + i4BytesWritten = snprintf(buf, 512, + CMD_NCHO_ROAM_SCAN_CONTROL_GET" %u", u4Param); + DBGLOG(REQ, INFO, "NCHO query ok and ret is [%u][%s]\n", + u4Param, buf); + return mtk_cfg80211_process_str_cmd_reply(wiphy, + buf, i4BytesWritten + 1); +} + +int testmode_set_ncho_mode(IN struct wiphy *wiphy, IN char *pcCommand, + IN int i4TotalLen) +{ + uint32_t u4Param = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + int32_t i4BytesWritten = -1; + uint32_t u4SetInfoLen = 0; + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)wiphy_priv(wiphy); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, + apcArgv[1]); + i4BytesWritten = kalkStrtou32(apcArgv[1], 0, &u4Param); + if (i4BytesWritten) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", + i4BytesWritten); + i4BytesWritten = -1; + } else { + DBGLOG(INIT, TRACE, "NCHO set enable cmd %d\n", + u4Param); + rStatus = kalIoctl(prGlueInfo, wlanoidSetNchoEnable, + &u4Param, sizeof(uint32_t), + FALSE, FALSE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, ERROR, + "NCHO set enable fail 0x%x\n", rStatus); + else + DBGLOG(INIT, TRACE, + "NCHO set enable successed\n"); + } + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + rStatus = WLAN_STATUS_INVALID_DATA; + } + + return rStatus; +} + +int testmode_get_ncho_mode(IN struct wiphy *wiphy, IN char *pcCommand, + IN int i4TotalLen) +{ + int32_t i4BytesWritten = -1; + uint32_t u4Param = 0; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER cmdV1Header; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)wiphy_priv(wiphy); + char buf[512]; + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return WLAN_STATUS_INVALID_DATA; + } + + /*<2> Query NCHOEnable Satus*/ + rStatus = kalIoctl(prGlueInfo, wlanoidQueryNchoEnable, + &cmdV1Header, sizeof(cmdV1Header), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO wlanoidQueryNchoEnable fail 0x%x\n", + rStatus); + return rStatus; + } + + i4BytesWritten = kalkStrtou32(cmdV1Header.buffer, 0, &u4Param); + if (i4BytesWritten) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d!\n", + i4BytesWritten); + return WLAN_STATUS_INVALID_DATA; + } + + i4BytesWritten = snprintf(buf, 512, CMD_NCHO_MODE_GET" %u", u4Param); + DBGLOG(REQ, INFO, "NCHO query ok and ret is [%u][%s]\n", + u4Param, buf); + + return mtk_cfg80211_process_str_cmd_reply(wiphy, + buf, i4BytesWritten + 1); +} + +#endif /* CFG_SUPPORT_NCHO */ + +int testmode_add_roam_scn_chnl( + IN struct wiphy *wiphy, IN char *pcCommand, IN int i4TotalLen) +{ + uint32_t u4ChnlInfo = 0; + uint8_t i = 1; + uint8_t t = 0; + uint32_t u4SetInfoLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + int32_t i4Ret = -1; + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CFG_SCAN_CHNL *prRoamScnChnl; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)wiphy_priv(wiphy); + + DBGLOG(INIT, TRACE, "command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + prRoamScnChnl = kalMemAlloc(sizeof(struct CFG_SCAN_CHNL), VIR_MEM_TYPE); + if (prRoamScnChnl == NULL) { + DBGLOG(REQ, ERROR, "alloc roaming scan channel fail\n"); + return WLAN_STATUS_RESOURCES; + } + kalMemZero(prRoamScnChnl, sizeof(struct CFG_SCAN_CHNL)); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "argc is %i, cmd is %s\n", i4Argc, + apcArgv[1]); + i4Ret = kalkStrtou32(apcArgv[1], 0, &u4ChnlInfo); + if (i4Ret) { + DBGLOG(REQ, ERROR, "parse u4Param error %d\n", + i4Ret); + rStatus = WLAN_STATUS_INVALID_DATA; + goto label_exit; + } + + prRoamScnChnl->ucChannelListNum = u4ChnlInfo; + DBGLOG(REQ, INFO, "ChannelListNum is %d\n", u4ChnlInfo); + if (i4Argc != u4ChnlInfo + 2) { + DBGLOG(REQ, ERROR, "param mismatch %d\n", + u4ChnlInfo); + rStatus = WLAN_STATUS_INVALID_DATA; + goto label_exit; + + } + for (i = 2; i < i4Argc; i++) { + i4Ret = kalkStrtou32(apcArgv[i], 0, &u4ChnlInfo); + if (i4Ret) { + while (i != 2) { + prRoamScnChnl->arChnlInfoList[i] + .ucChannelNum = 0; + i--; + } + DBGLOG(REQ, ERROR, + "parse chnl num error %d\n", i4Ret); + rStatus = WLAN_STATUS_FAILURE; + goto label_exit; + } + if (u4ChnlInfo != 0) { + DBGLOG(INIT, TRACE, + "t = %d, channel value=%d\n", + t, u4ChnlInfo); + if ((u4ChnlInfo >= 1) && (u4ChnlInfo <= 14)) + prRoamScnChnl->arChnlInfoList[t].eBand = + BAND_2G4; + else + prRoamScnChnl->arChnlInfoList[t].eBand = + BAND_5G; + + prRoamScnChnl->arChnlInfoList[t].ucChannelNum = + u4ChnlInfo; + t++; + } + + } + + rStatus = kalIoctl(prGlueInfo, wlanoidAddRoamScnChnl, + prRoamScnChnl, sizeof(struct CFG_SCAN_CHNL), + FALSE, FALSE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, ERROR, + "add roam scan channel fail 0x%x\n", + rStatus); + else + DBGLOG(INIT, TRACE, + "add roam scan channel successed\n"); + goto label_exit; + } else { + DBGLOG(REQ, ERROR, "add failed\n"); + rStatus = WLAN_STATUS_INVALID_DATA; + goto label_exit; + } + +label_exit: + kalMemFree(prRoamScnChnl, sizeof(struct CFG_SCAN_CHNL), VIR_MEM_TYPE); + return rStatus; +} + +int32_t mtk_cfg80211_process_str_cmd_reply( + IN struct wiphy *wiphy, IN char *data, IN int len) +{ + + struct sk_buff *skb; + + skb = cfg80211_testmode_alloc_reply_skb(wiphy, len); + + if (!skb) { + DBGLOG(REQ, INFO, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + nla_put_nohdr(skb, len, data); + + return cfg80211_testmode_reply(skb); +} + +int32_t mtk_cfg80211_process_str_cmd(IN struct wiphy *wiphy, + struct wireless_dev *wdev, + uint8_t *data, int32_t len) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4SetInfoLen = 0; + uint8_t ucBssIndex = 0; + struct NL80211_DRIVER_STRING_CMD_PARAMS *param = + (struct NL80211_DRIVER_STRING_CMD_PARAMS *) data; + uint8_t *cmd = (uint8_t *) (param + 1); + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)wiphy_priv(wiphy); + + len -= sizeof(struct NL80211_DRIVER_STRING_CMD_PARAMS); + ucBssIndex = wlanGetBssIdx(wdev->netdev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + DBGLOG(REQ, INFO, "cmd: %s\n", cmd); + + if (strnicmp(cmd, "tdls-ps ", 8) == 0) { +#if CFG_SUPPORT_TDLS + rStatus = kalIoctl(prGlueInfo, + wlanoidDisableTdlsPs, + (void *)(cmd + 8), 1, + FALSE, FALSE, TRUE, &u4SetInfoLen); +#else + DBGLOG(REQ, WARN, "not support tdls\n"); + return -EOPNOTSUPP; +#endif + } else if (strncasecmp(cmd, "NEIGHBOR-REQUEST", 16) == 0) { + uint8_t *pucSSID = NULL; + uint32_t u4SSIDLen = 0; + + if (len > 16 && (strncasecmp(cmd+16, " SSID=", 6) == 0)) { + pucSSID = cmd + 22; + u4SSIDLen = len - 22; + DBGLOG(REQ, INFO, "cmd=%s, ssid len %u, ssid=%s\n", cmd, + u4SSIDLen, HIDE(pucSSID)); + } + rStatus = kalIoctlByBssIdx(prGlueInfo, + wlanoidSendNeighborRequest, + (void *)pucSSID, u4SSIDLen, FALSE, FALSE, + TRUE, &u4SetInfoLen, + ucBssIndex); + } else if (strncasecmp(cmd, "BSS-TRANSITION-QUERY", 20) == 0) { + uint8_t *pucReason = NULL; + + if (len > 20 && (strncasecmp(cmd+20, " reason=", 8) == 0)) + pucReason = cmd + 28; + rStatus = kalIoctlByBssIdx(prGlueInfo, wlanoidSendBTMQuery, + (void *)pucReason, 1, FALSE, FALSE, TRUE, + &u4SetInfoLen, + ucBssIndex); + } else if (strnicmp(cmd, "OSHAREMOD ", 10) == 0) { +#if CFG_SUPPORT_OSHARE + struct OSHARE_MODE_T cmdBuf; + struct OSHARE_MODE_T *pCmdHeader = NULL; + struct OSHARE_MODE_SETTING_V1_T *pCmdData = NULL; + + kalMemZero(&cmdBuf, sizeof(cmdBuf)); + + pCmdHeader = &cmdBuf; + pCmdHeader->cmdVersion = OSHARE_MODE_CMD_V1; + pCmdHeader->cmdType = 1; /*1-set 0-query*/ + pCmdHeader->magicCode = OSHARE_MODE_MAGIC_CODE; + pCmdHeader->cmdBufferLen = MAX_OSHARE_MODE_LENGTH; + + pCmdData = (struct OSHARE_MODE_SETTING_V1_T *) & + (pCmdHeader->buffer[0]); + pCmdData->osharemode = *(uint8_t *)(cmd + 10) - '0'; + + DBGLOG(REQ, INFO, "cmd=%s, osharemode=%u\n", cmd, + pCmdData->osharemode); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetOshareMode, + &cmdBuf, + sizeof(struct OSHARE_MODE_T), + FALSE, + FALSE, + TRUE, + &u4SetInfoLen); + + if (rStatus == WLAN_STATUS_SUCCESS) + prGlueInfo->prAdapter->fgEnOshareMode + = pCmdData->osharemode; +#else + DBGLOG(REQ, WARN, "not support OSHAREMOD\n"); + return -EOPNOTSUPP; +#endif + } else if (strnicmp(cmd, "CMD_EXAMPLE", 11) == 0) { + char tmp[] = "CMD_RESPONSE"; + + return mtk_cfg80211_process_str_cmd_reply( + wiphy, tmp, sizeof(tmp)); + } else if (strnicmp(cmd, "ADDROAMSCANCHANNELS_LEGACY", 26) == 0) { + rStatus = testmode_add_roam_scn_chnl(wiphy, cmd, len); +#if CFG_SUPPORT_NCHO + } else if (strnicmp(cmd, CMD_NCHO_ROAM_TRIGGER_SET, + strlen(CMD_NCHO_ROAM_TRIGGER_SET)) == 0) { + rStatus = testmode_set_ncho_roam_trigger(wiphy, cmd, len); + } else if (strnicmp(cmd, CMD_NCHO_ROAM_TRIGGER_GET, + strlen(CMD_NCHO_ROAM_TRIGGER_GET)) == 0) { + return testmode_get_ncho_roam_trigger(wiphy, cmd, len); + } else if (strnicmp(cmd, CMD_NCHO_ROAM_DELTA_SET, + strlen(CMD_NCHO_ROAM_DELTA_SET)) == 0) { + rStatus = testmode_set_ncho_roam_delta(wiphy, cmd, len); + } else if (strnicmp(cmd, CMD_NCHO_ROAM_DELTA_GET, + strlen(CMD_NCHO_ROAM_DELTA_GET)) == 0) { + return testmode_get_ncho_roam_delta(wiphy, cmd, len); + } else if (strnicmp(cmd, CMD_NCHO_ROAM_SCAN_PERIOD_SET, + strlen(CMD_NCHO_ROAM_SCAN_PERIOD_SET)) == 0) { + rStatus = testmode_set_ncho_roam_scn_period(wiphy, cmd, len); + } else if (strnicmp(cmd, CMD_NCHO_ROAM_SCAN_PERIOD_GET, + strlen(CMD_NCHO_ROAM_SCAN_PERIOD_GET)) == 0) { + return testmode_get_ncho_roam_scn_period(wiphy, cmd, len); + } else if (strnicmp(cmd, CMD_NCHO_ROAM_SCAN_CHANNELS_SET, + strlen(CMD_NCHO_ROAM_SCAN_CHANNELS_SET)) == 0) { + rStatus = testmode_set_ncho_roam_scn_chnl(wiphy, cmd, len, 1); + } else if (strnicmp(cmd, CMD_NCHO_ROAM_SCAN_CHANNELS_ADD, + strlen(CMD_NCHO_ROAM_SCAN_CHANNELS_ADD)) == 0) { + rStatus = testmode_set_ncho_roam_scn_chnl(wiphy, cmd, len, 0); + } else if (strnicmp(cmd, CMD_NCHO_ROAM_SCAN_CHANNELS_GET, + strlen(CMD_NCHO_ROAM_SCAN_CHANNELS_GET)) == 0) { + return testmode_get_ncho_roam_scn_chnl(wiphy, cmd, len); + } else if (strnicmp(cmd, CMD_NCHO_ROAM_SCAN_CONTROL_SET, + strlen(CMD_NCHO_ROAM_SCAN_CONTROL_SET)) == 0) { + rStatus = testmode_set_ncho_roam_scn_ctrl(wiphy, cmd, len); + } else if (strnicmp(cmd, CMD_NCHO_ROAM_SCAN_CONTROL_GET, + strlen(CMD_NCHO_ROAM_SCAN_CONTROL_GET)) == 0) { + return testmode_get_ncho_roam_scn_ctrl(wiphy, cmd, len); + } else if (strnicmp(cmd, CMD_NCHO_MODE_SET, + strlen(CMD_NCHO_MODE_SET)) == 0) { + rStatus = testmode_set_ncho_mode(wiphy, cmd, len); + } else if (strnicmp(cmd, CMD_NCHO_MODE_GET, + strlen(CMD_NCHO_MODE_GET)) == 0) { + return testmode_get_ncho_mode(wiphy, cmd, len); +#endif + } else + return -EOPNOTSUPP; + + return rStatus; +} + +#endif /* CONFIG_NL80211_TESTMODE */ + +#if (CFG_SUPPORT_SINGLE_SKU == 1) + +#if (CFG_BUILT_IN_DRIVER == 1) +/* in kernel-x.x/net/wireless/reg.c */ +#else +bool is_world_regdom(const char *alpha2) +{ + if (!alpha2) + return false; + + return (alpha2[0] == '0') && (alpha2[1] == '0'); +} +#endif + +enum regd_state regd_state_machine(IN struct regulatory_request *pRequest) +{ + switch (pRequest->initiator) { + case NL80211_REGDOM_SET_BY_USER: + DBGLOG(RLM, INFO, "regd_state_machine: SET_BY_USER\n"); + + return rlmDomainStateTransition(REGD_STATE_SET_COUNTRY_USER, + pRequest); + + case NL80211_REGDOM_SET_BY_DRIVER: + DBGLOG(RLM, INFO, "regd_state_machine: SET_BY_DRIVER\n"); + + return rlmDomainStateTransition( + REGD_STATE_SET_COUNTRY_DRIVER, pRequest); + + case NL80211_REGDOM_SET_BY_CORE: + DBGLOG(RLM, INFO, + "regd_state_machine: NL80211_REGDOM_SET_BY_CORE\n"); + + return rlmDomainStateTransition(REGD_STATE_SET_WW_CORE, + pRequest); + + case NL80211_REGDOM_SET_BY_COUNTRY_IE: + DBGLOG(RLM, WARN, + "============== WARNING ==============\n"); + DBGLOG(RLM, WARN, + "regd_state_machine: SET_BY_COUNTRY_IE\n"); + DBGLOG(RLM, WARN, "Regulatory rule is updated by IE.\n"); + DBGLOG(RLM, WARN, + "============== WARNING ==============\n"); + + return rlmDomainStateTransition(REGD_STATE_SET_COUNTRY_IE, + pRequest); + + default: + return rlmDomainStateTransition(REGD_STATE_INVALID, + pRequest); + } +} + + +void +mtk_apply_custom_regulatory(IN struct wiphy *pWiphy, + IN const struct ieee80211_regdomain *pRegdom) +{ + u32 band_idx, ch_idx; + struct ieee80211_supported_band *sband; + struct ieee80211_channel *chan; + + DBGLOG(RLM, INFO, "%s()\n", __func__); + + /* to reset cha->flags*/ + for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { + sband = pWiphy->bands[band_idx]; + if (!sband) + continue; + + for (ch_idx = 0; ch_idx < sband->n_channels; ch_idx++) { + chan = &sband->channels[ch_idx]; + + /*reset chan->flags*/ + chan->flags = 0; + } + + } + + /* update to kernel */ + wiphy_apply_custom_regulatory(pWiphy, pRegdom); +} + +void +mtk_reg_notify(IN struct wiphy *pWiphy, + IN struct regulatory_request *pRequest) +{ + struct GLUE_INFO *prGlueInfo; + struct ADAPTER *prAdapter; + enum regd_state old_state; + struct wiphy *pBaseWiphy = wlanGetWiphy(); + + if (g_u4HaltFlag) { + DBGLOG(RLM, WARN, "wlan is halt, skip reg callback\n"); + return; + } + + if (!pWiphy) { + DBGLOG(RLM, ERROR, "pWiphy = NULL!\n"); + return; + } + + /* + * Awlays use wlan0's base wiphy pointer to update reg notifier. + * Because only one reg state machine is handled. + */ + if (pBaseWiphy && (pWiphy != pBaseWiphy)) { + pWiphy = pBaseWiphy; + DBGLOG(RLM, ERROR, "Use base wiphy to update (p=%p)\n", + pBaseWiphy); + } + + old_state = rlmDomainGetCtrlState(); + + /* + * Magic flow for driver to send inband command after kernel's calling + * reg_notifier callback + */ + if (!pRequest) { + /*triggered by our driver in wlan initial process.*/ + + if (old_state == REGD_STATE_INIT) { + if (rlmDomainIsUsingLocalRegDomainDataBase()) { + DBGLOG(RLM, WARN, + "County Code is not assigned. Use default WW.\n"); + goto DOMAIN_SEND_CMD; + + } else { + DBGLOG(RLM, ERROR, + "Invalid REG state happened. state = 0x%x\n", + old_state); + return; + } + } else if ((old_state == REGD_STATE_SET_WW_CORE) || + (old_state == REGD_STATE_SET_COUNTRY_USER) || + (old_state == REGD_STATE_SET_COUNTRY_DRIVER)) { + goto DOMAIN_SEND_CMD; + } else { + DBGLOG(RLM, ERROR, + "Invalid REG state happened. state = 0x%x\n", + old_state); + return; + } + } + + /* + * Ignore the CORE's WW setting when using local data base of regulatory + * rules + */ + if ((pRequest->initiator == NL80211_REGDOM_SET_BY_CORE) && +#if KERNEL_VERSION(3, 14, 0) > CFG80211_VERSION_CODE + (pWiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY)) +#else + (pWiphy->regulatory_flags & REGULATORY_CUSTOM_REG)) +#endif + return;/*Ignore the CORE's WW setting*/ + + /* + * State machine transition + */ + DBGLOG(RLM, INFO, + "request->alpha2=%s, initiator=%x, intersect=%d\n", + pRequest->alpha2, pRequest->initiator, pRequest->intersect); + + regd_state_machine(pRequest); + + if (rlmDomainGetCtrlState() == old_state) { + if (((old_state == REGD_STATE_SET_COUNTRY_USER) + || (old_state == REGD_STATE_SET_COUNTRY_DRIVER)) + && (!(rlmDomainIsSameCountryCode(pRequest->alpha2, + sizeof(pRequest->alpha2))))) + DBGLOG(RLM, INFO, "Set by user to NEW country code\n"); + else + /* Change to same state or same country, ignore */ + return; + } else if (rlmDomainIsCtrlStateEqualTo(REGD_STATE_INVALID)) { + DBGLOG(RLM, ERROR, + "\n%s():\n---> WARNING. Transit to invalid state.\n", + __func__); + DBGLOG(RLM, ERROR, "---> WARNING.\n "); + rlmDomainAssert(0); + } + + /* + * Set country code + */ + if (pRequest->initiator != NL80211_REGDOM_SET_BY_DRIVER) { + rlmDomainSetCountryCode(pRequest->alpha2, + sizeof(pRequest->alpha2)); + } else { + /*SET_BY_DRIVER*/ + + if (rlmDomainIsEfuseUsed()) { + if (!rlmDomainIsUsingLocalRegDomainDataBase()) + DBGLOG(RLM, WARN, + "[WARNING!!!] Local DB must be used if country code from efuse.\n"); + } else { + /* iwpriv case */ + if (rlmDomainIsUsingLocalRegDomainDataBase() && + (!rlmDomainIsEfuseUsed())) { + /*iwpriv set country but local data base*/ + u32 country_code = + rlmDomainGetTempCountryCode(); + + rlmDomainSetCountryCode((char *)&country_code, + sizeof(country_code)); + } else { + /*iwpriv set country but query CRDA*/ + rlmDomainSetCountryCode(pRequest->alpha2, + sizeof(pRequest->alpha2)); + } + } + } + + rlmDomainSetDfsRegion(pRequest->dfs_region); + + +DOMAIN_SEND_CMD: + DBGLOG(RLM, INFO, "g_mtk_regd_control.alpha2 = 0x%x\n", + rlmDomainGetCountryCode()); + + /* + * Check if using customized regulatory rule + */ + if (rlmDomainIsUsingLocalRegDomainDataBase()) { + const struct ieee80211_regdomain *pRegdom; + u32 country_code = rlmDomainGetCountryCode(); + char alpha2[4]; + + /*fetch regulatory rules from local data base*/ + alpha2[0] = country_code & 0xFF; + alpha2[1] = (country_code >> 8) & 0xFF; + alpha2[2] = (country_code >> 16) & 0xFF; + alpha2[3] = (country_code >> 24) & 0xFF; + + pRegdom = rlmDomainSearchRegdomainFromLocalDataBase(alpha2); + if (!pRegdom) { + DBGLOG(RLM, ERROR, + "%s(): Error, Cannot find the correct RegDomain. country = %u\n", + __func__, rlmDomainGetCountryCode()); + + rlmDomainAssert(0); + return; + } + + mtk_apply_custom_regulatory(pWiphy, pRegdom); + } + + /* + * Parsing channels + */ + rlmDomainParsingChannel(pWiphy); /*real regd update*/ + + /* + * Check if firmawre support single sku. + * no need to send information to FW due to FW is not supported. + */ + if (!regd_is_single_sku_en()) + return; + + /* + * Always use the wlan GlueInfo as parameter. + */ + prGlueInfo = rlmDomainGetGlueInfo(); + if (!prGlueInfo) { + DBGLOG(RLM, ERROR, "prGlueInfo is NULL!\n"); + return; /*interface is not up yet.*/ + } + + prAdapter = prGlueInfo->prAdapter; + if (!prAdapter) { + DBGLOG(RLM, ERROR, "prAdapter is NULL!\n"); + return; /*interface is not up yet.*/ + } + + /* + * Send commands to firmware + */ + prAdapter->rWifiVar.u2CountryCode = + (uint16_t)rlmDomainGetCountryCode(); + rlmDomainSendCmd(prAdapter); +} + +void +cfg80211_regd_set_wiphy(IN struct wiphy *prWiphy) +{ + /* + * register callback + */ + prWiphy->reg_notifier = mtk_reg_notify; + + + /* + * clear REGULATORY_CUSTOM_REG flag + */ +#if KERNEL_VERSION(3, 14, 0) > CFG80211_VERSION_CODE + /*tells kernel that assign WW as default*/ + prWiphy->flags &= ~(WIPHY_FLAG_CUSTOM_REGULATORY); +#else + prWiphy->regulatory_flags &= ~(REGULATORY_CUSTOM_REG); + + /*ignore the hint from IE*/ + prWiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE; +#endif + + + /* + * set REGULATORY_CUSTOM_REG flag + */ +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) +#if KERNEL_VERSION(3, 14, 0) > CFG80211_VERSION_CODE + /*tells kernel that assign WW as default*/ + prWiphy->flags |= (WIPHY_FLAG_CUSTOM_REGULATORY); +#else + prWiphy->regulatory_flags |= (REGULATORY_CUSTOM_REG); +#endif + /* assigned a defautl one */ + if (rlmDomainGetLocalDefaultRegd()) + wiphy_apply_custom_regulatory(prWiphy, + rlmDomainGetLocalDefaultRegd()); +#endif + + + /* + * Initialize regd control information + */ + rlmDomainResetCtrlInfo(FALSE); +} + +#else +void +cfg80211_regd_set_wiphy(IN struct wiphy *prWiphy) +{ +} +#endif + +int mtk_cfg80211_suspend(struct wiphy *wiphy, + struct cfg80211_wowlan *wow) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + DBGLOG(REQ, INFO, "mtk_cfg80211_suspend\n"); + +#if (CFG_SUPPORT_STATISTICS == 1) + wlanWakeDumpRes(); +#endif + if (kalHaltTryLock()) + return 0; + + if (kalIsHalted() || !wiphy) + goto end; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + + if (prGlueInfo && prGlueInfo->prAdapter) { + set_bit(SUSPEND_FLAG_FOR_WAKEUP_REASON, + &prGlueInfo->prAdapter->ulSuspendFlag); + set_bit(SUSPEND_FLAG_CLEAR_WHEN_RESUME, + &prGlueInfo->prAdapter->ulSuspendFlag); + if (prGlueInfo->prAdapter->u4HostStatusEmiOffset) + kalSetSuspendFlagToEMI(prGlueInfo->prAdapter, TRUE); + } +end: + kalHaltUnlock(); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief cfg80211 resume callback, will be invoked in wiphy_resume. + * + * @param wiphy: pointer to wiphy + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_resume(struct wiphy *wiphy) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t rStatus, u4InfoLen; + + DBGLOG(REQ, INFO, "mtk_cfg80211_resume\n"); + + if (kalHaltTryLock()) + return 0; + + if (kalIsHalted() || !wiphy) + goto end; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + if (prGlueInfo) + prAdapter = prGlueInfo->prAdapter; + if (prAdapter == NULL) + goto end; + + clear_bit(SUSPEND_FLAG_CLEAR_WHEN_RESUME, + &prAdapter->ulSuspendFlag); + + rStatus = kalIoctl(prGlueInfo, + wlanoidIndicateBssInfo, + (void *) NULL, + 0, + FALSE, FALSE, FALSE, &u4InfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "ScanResultLog error:%x\n", + rStatus); + if (prGlueInfo->prAdapter->u4HostStatusEmiOffset) + kalSetSuspendFlagToEMI(prGlueInfo->prAdapter, FALSE); +end: + kalHaltUnlock(); + + return 0; +} + +#if CFG_ENABLE_UNIFY_WIPHY +/*----------------------------------------------------------------------------*/ +/*! + * @brief Check the net device is P2P net device (P2P GO/GC, AP), or not. + * + * @param prGlueInfo : the driver private data + * ndev : the net device + * + * @retval 0: AIS device (STA/IBSS) + * 1: P2P GO/GC, AP + */ +/*----------------------------------------------------------------------------*/ +int mtk_IsP2PNetDevice(struct GLUE_INFO *prGlueInfo, + struct net_device *ndev) +{ + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = NULL; + int iftype = 0; + int ret = 1; + + if (ndev == NULL) { + DBGLOG(REQ, WARN, "ndev is NULL\n"); + return -1; + } + + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(ndev); + iftype = ndev->ieee80211_ptr->iftype; + + /* P2P device/GO/GC always return 1 */ + if (prNetDevPrivate->ucIsP2p == TRUE) + ret = 1; + else if (iftype == NL80211_IFTYPE_STATION) + ret = 0; + else if (iftype == NL80211_IFTYPE_ADHOC) + ret = 0; + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Initialize the AIS related FSM and data. + * + * @param prGlueInfo : the driver private data + * ndev : the net device + * ucBssIdx : the AIS BSS index adssigned by the driver (wlanProbe) + * + * @retval 0 + * + */ +/*----------------------------------------------------------------------------*/ +int mtk_init_sta_role(struct ADAPTER *prAdapter, + struct net_device *ndev) +{ + struct NETDEV_PRIVATE_GLUE_INFO *prNdevPriv = NULL; + uint8_t ucBssIndex = 0; + + if ((prAdapter == NULL) || (ndev == NULL)) + return -1; + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) + return -1; + + /* init AIS FSM */ + aisFsmInit(prAdapter, ucBssIndex); + +#if CFG_SUPPORT_ROAMING + /* Roaming Module - intiailization */ + roamingFsmInit(prAdapter, ucBssIndex); +#endif /* CFG_SUPPORT_ROAMING */ + + ndev->netdev_ops = wlanGetNdevOps(); + ndev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; + + /* set the ndev's ucBssIdx to the AIS BSS index */ + prNdevPriv = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(ndev); + prNdevPriv->ucBssIdx = ucBssIndex; + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Uninitialize the AIS related FSM and data. + * + * @param prAdapter : the driver private data + * + * @retval 0 + * + */ +/*----------------------------------------------------------------------------*/ +int mtk_uninit_sta_role(struct ADAPTER *prAdapter, + struct net_device *ndev) +{ + struct NETDEV_PRIVATE_GLUE_INFO *prNdevPriv = NULL; + uint8_t ucBssIndex = 0; + + if ((prAdapter == NULL) || (ndev == NULL)) + return -1; + + ucBssIndex = wlanGetBssIdx(ndev); + if (!IS_BSS_INDEX_AIS(prAdapter, ucBssIndex)) + return -1; + +#if CFG_SUPPORT_ROAMING + /* Roaming Module - unintiailization */ + roamingFsmUninit(prAdapter, ucBssIndex); +#endif /* CFG_SUPPORT_ROAMING */ + + /* uninit AIS FSM */ + aisFsmUninit(prAdapter, ucBssIndex); + + /* set the ucBssIdx to the illegal value */ + prNdevPriv = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(ndev); + prNdevPriv->ucBssIdx = 0xff; + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Initialize the AP (P2P) related FSM and data. + * + * @param prGlueInfo : the driver private data + * ndev : net device + * + * @retval 0 : success + * others : can't alloc and setup the AP FSM & data + * + */ +/*----------------------------------------------------------------------------*/ +int mtk_init_ap_role(struct GLUE_INFO *prGlueInfo, + struct net_device *ndev) +{ + uint8_t u4Idx = 0; + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + + for (u4Idx = 0; u4Idx < KAL_P2P_NUM; u4Idx++) { + if (gprP2pRoleWdev[u4Idx] == NULL) + break; + } + + if (u4Idx >= KAL_P2P_NUM) { + DBGLOG(INIT, ERROR, "There is no free gprP2pRoleWdev.\n"); + return -ENOMEM; + } + + if ((u4Idx == 0) || + (prAdapter == NULL) || + (prAdapter->rP2PNetRegState != + ENUM_NET_REG_STATE_REGISTERED)) { + DBGLOG(INIT, ERROR, + "The wlan0 can't set to AP without p2p0\n"); + /* System will crash, if p2p0 isn't existing. */ + return -EFAULT; + } + + /* reference from the glRegisterP2P() */ + gprP2pRoleWdev[u4Idx] = ndev->ieee80211_ptr; + if (glSetupP2P(prGlueInfo, gprP2pRoleWdev[u4Idx], ndev, + u4Idx, TRUE)) { + gprP2pRoleWdev[u4Idx] = NULL; + return -EFAULT; + } + + prGlueInfo->prAdapter->prP2pInfo->u4DeviceNum++; + + /* reference from p2pNetRegister() */ + /* The ndev doesn't need register_netdev, only reassign the gPrP2pDev.*/ + gPrP2pDev[u4Idx] = ndev; + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Unnitialize the AP (P2P) related FSM and data. + * + * @param prGlueInfo : the driver private data + * ndev : net device + * + * @retval 0 : success + * others : can't find the AP information by the ndev + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t +mtk_oid_uninit_ap_role(struct ADAPTER *prAdapter, void *pvSetBuffer, + uint32_t u4SetBufferLen, uint32_t *pu4SetInfoLen) +{ + unsigned char u4Idx = 0; + + if ((prAdapter == NULL) || (pvSetBuffer == NULL) + || (pu4SetInfoLen == NULL)) + return WLAN_STATUS_FAILURE; + + /* init */ + *pu4SetInfoLen = sizeof(unsigned char); + if (u4SetBufferLen < sizeof(unsigned char)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + u4Idx = *(unsigned char *) pvSetBuffer; + + DBGLOG(INIT, INFO, "ucRoleIdx = %d\n", u4Idx); + + glUnregisterP2P(prAdapter->prGlueInfo, u4Idx); + + gPrP2pDev[u4Idx] = NULL; + gprP2pRoleWdev[u4Idx] = NULL; + + return 0; + +} + +int mtk_uninit_ap_role(struct GLUE_INFO *prGlueInfo, + struct net_device *ndev) +{ + unsigned char u4Idx; + uint32_t rStatus; + uint32_t u4BufLen; + + if (!prGlueInfo) { + DBGLOG(INIT, WARN, "prGlueInfo is NULL\n"); + return -EINVAL; + } + if (mtk_Netdev_To_RoleIdx(prGlueInfo, ndev, &u4Idx) != 0) { + DBGLOG(INIT, WARN, + "can't find the matched dev to uninit AP\n"); + return -EFAULT; + } + + rStatus = kalIoctl(prGlueInfo, + mtk_oid_uninit_ap_role, &u4Idx, + sizeof(unsigned char), + FALSE, FALSE, FALSE, + &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + return -EINVAL; + + return 0; +} + +#if (CFG_SUPPORT_DFS_MASTER == 1) +#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_start_radar_detection(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef, + unsigned int cac_time_ms) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, dev) <= 0) { + DBGLOG(REQ, WARN, "STA doesn't support this function\n"); + return -EFAULT; + } + + return mtk_p2p_cfg80211_start_radar_detection(wiphy, + dev, + chandef, + cac_time_ms); + +} +#else +int mtk_cfg_start_radar_detection(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, dev) <= 0) { + DBGLOG(REQ, WARN, "STA doesn't support this function\n"); + return -EFAULT; + } + + return mtk_p2p_cfg80211_start_radar_detection(wiphy, dev, chandef); + +} + +#endif + + +#if KERNEL_VERSION(3, 13, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_channel_switch(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_csa_settings *params) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, dev) <= 0) { + DBGLOG(REQ, WARN, "STA doesn't support this function\n"); + return -EFAULT; + } + + return mtk_p2p_cfg80211_channel_switch(wiphy, dev, params); + +} +#endif +#endif + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +struct wireless_dev *mtk_cfg_add_iface(struct wiphy *wiphy, + const char *name, + unsigned char name_assign_type, + enum nl80211_iftype type, + struct vif_params *params) +#elif KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE +struct wireless_dev *mtk_cfg_add_iface(struct wiphy *wiphy, + const char *name, + unsigned char name_assign_type, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params) +#else +struct wireless_dev *mtk_cfg_add_iface(struct wiphy *wiphy, + const char *name, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params) +#endif +{ + struct GLUE_INFO *prGlueInfo = NULL; +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE + u32 *flags = NULL; +#endif + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return ERR_PTR(-EFAULT); + } + + /* TODO: error handele for the non-P2P interface */ + +#if (CFG_ENABLE_WIFI_DIRECT_CFG_80211 == 0) + DBGLOG(REQ, WARN, "P2P is not supported\n"); + return ERR_PTR(-EINVAL); +#else /* CFG_ENABLE_WIFI_DIRECT_CFG_80211 */ +#if KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE + return mtk_p2p_cfg80211_add_iface(wiphy, name, + name_assign_type, type, + flags, params); +#else /* KERNEL_VERSION > (4, 1, 0) */ + return mtk_p2p_cfg80211_add_iface(wiphy, name, type, flags, + params); +#endif /* KERNEL_VERSION */ +#endif /* CFG_ENABLE_WIFI_DIRECT_CFG_80211 */ +} + +int mtk_cfg_del_iface(struct wiphy *wiphy, + struct wireless_dev *wdev) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + /* TODO: error handele for the non-P2P interface */ +#if (CFG_ENABLE_WIFI_DIRECT_CFG_80211 == 0) + DBGLOG(REQ, WARN, "P2P is not supported\n"); + return -EINVAL; +#else /* CFG_ENABLE_WIFI_DIRECT_CFG_80211 */ + return mtk_p2p_cfg80211_del_iface(wiphy, wdev); +#endif /* CFG_ENABLE_WIFI_DIRECT_CFG_80211 */ +} + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_change_iface(struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type, + struct vif_params *params) +#else +int mtk_cfg_change_iface(struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params) +#endif +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct NETDEV_PRIVATE_GLUE_INFO *prNetdevPriv = NULL; + struct P2P_INFO *prP2pInfo = NULL; +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE + u32 *flags = NULL; +#endif + + GLUE_SPIN_LOCK_DECLARATION(); + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (!ndev) { + DBGLOG(REQ, WARN, "ndev is NULL\n"); + return -EINVAL; + } + + prNetdevPriv = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(ndev); + +#if (CFG_ENABLE_WIFI_DIRECT_CFG_80211) + /* for p2p0(GO/GC) & ap0(SAP): mtk_p2p_cfg80211_change_iface + * for wlan0 (STA/SAP): the following mtk_cfg_change_iface process + */ + if (!wlanIsAisDev(ndev)) { + return mtk_p2p_cfg80211_change_iface(wiphy, ndev, type, + flags, params); + } +#endif /* CFG_ENABLE_WIFI_DIRECT_CFG_80211 */ + + DBGLOG(P2P, INFO, "ndev=%p, new type=%d\n", ndev, type); + + prAdapter = prGlueInfo->prAdapter; + + if (ndev->ieee80211_ptr->iftype == type) { + DBGLOG(REQ, INFO, "ndev type is not changed (%d)\n", type); + return 0; + } + + netif_carrier_off(ndev); + /* stop ap will stop all queue, and kalIndicateStatusAndComplete only do + * netif_carrier_on. So that, the following STA can't send 4-way M2 to + * AP. + */ + netif_tx_start_all_queues(ndev); + + /* flush scan */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if ((prGlueInfo->prScanRequest != NULL) && + (prGlueInfo->prScanRequest->wdev == ndev->ieee80211_ptr)) { + kalCfg80211ScanDone(prGlueInfo->prScanRequest, TRUE); + prGlueInfo->prScanRequest = NULL; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + /* expect that only AP & STA will be handled here (excluding IBSS) */ + + if (type == NL80211_IFTYPE_AP) { + /* STA mode change to AP mode */ + prP2pInfo = prAdapter->prP2pInfo; + + if (prP2pInfo == NULL) { + DBGLOG(INIT, ERROR, "prP2pInfo is NULL\n"); + return -EFAULT; + } + + if (prP2pInfo->u4DeviceNum >= KAL_P2P_NUM) { + DBGLOG(INIT, ERROR, "resource invalid, u4DeviceNum=%d\n" + , prP2pInfo->u4DeviceNum); + return -EFAULT; + } + + mtk_uninit_sta_role(prAdapter, ndev); + + if (mtk_init_ap_role(prGlueInfo, ndev) != 0) { + DBGLOG(INIT, ERROR, "mtk_init_ap_role FAILED\n"); + + /* Only AP/P2P resource has the failure case. */ + /* So, just re-init AIS. */ + mtk_init_sta_role(prAdapter, ndev); + return -EFAULT; + } + } else { + /* AP mode change to STA mode */ + if (mtk_uninit_ap_role(prGlueInfo, ndev) != 0) { + DBGLOG(INIT, ERROR, "mtk_uninit_ap_role FAILED\n"); + return -EFAULT; + } + + mtk_init_sta_role(prAdapter, ndev); + + /* continue the mtk_cfg80211_change_iface() process */ + mtk_cfg80211_change_iface(wiphy, ndev, type, flags, params); + } + + return 0; +} + +int mtk_cfg_add_key(struct wiphy *wiphy, + struct net_device *ndev, u8 key_index, + bool pairwise, const u8 *mac_addr, + struct key_params *params) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + return mtk_p2p_cfg80211_add_key(wiphy, ndev, key_index, + pairwise, mac_addr, params); + } + /* STA Mode */ + return mtk_cfg80211_add_key(wiphy, ndev, key_index, + pairwise, + mac_addr, params); +} + +int mtk_cfg_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 *)) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + return mtk_p2p_cfg80211_get_key(wiphy, ndev, key_index, + pairwise, mac_addr, cookie, callback); + } + /* STA Mode */ + return mtk_cfg80211_get_key(wiphy, ndev, key_index, + pairwise, mac_addr, cookie, callback); +} + +int mtk_cfg_del_key(struct wiphy *wiphy, + struct net_device *ndev, u8 key_index, + bool pairwise, const u8 *mac_addr) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + return mtk_p2p_cfg80211_del_key(wiphy, ndev, key_index, + pairwise, mac_addr); + } + /* STA Mode */ + return mtk_cfg80211_del_key(wiphy, ndev, key_index, + pairwise, mac_addr); +} + +int mtk_cfg_set_default_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, bool unicast, bool multicast) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + return mtk_p2p_cfg80211_set_default_key(wiphy, ndev, + key_index, unicast, multicast); + } + /* STA Mode */ + return mtk_cfg80211_set_default_key(wiphy, ndev, + key_index, unicast, multicast); +} + +int mtk_cfg_set_default_mgmt_key(struct wiphy *wiphy, + struct net_device *ndev, u8 key_index) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) + return mtk_p2p_cfg80211_set_mgmt_key(wiphy, ndev, key_index); + /* STA Mode */ + DBGLOG(REQ, WARN, "STA don't support this function\n"); + return -EFAULT; +} + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_get_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, struct station_info *sinfo) +#else +int mtk_cfg_get_station(struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, struct station_info *sinfo) +#endif +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) + return mtk_p2p_cfg80211_get_station(wiphy, ndev, mac, + sinfo); + /* STA Mode */ + return mtk_cfg80211_get_station(wiphy, ndev, mac, sinfo); +} + +#if CFG_SUPPORT_TDLS +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_change_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, struct station_parameters *params) +#else +int mtk_cfg_change_station(struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, struct station_parameters *params) +#endif +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + DBGLOG(REQ, WARN, "P2P/AP don't support this function\n"); + return -EFAULT; + } + /* STA Mode */ + return mtk_cfg80211_change_station(wiphy, ndev, mac, + params); +} + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_add_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, struct station_parameters *params) +#else +int mtk_cfg_add_station(struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, struct station_parameters *params) +#endif +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + DBGLOG(REQ, WARN, "P2P/AP don't support this function\n"); + return -EFAULT; + } + /* STA Mode */ + return mtk_cfg80211_add_station(wiphy, ndev, mac, params); +} + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_tdls_oper(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *peer, enum nl80211_tdls_operation oper) +#else +int mtk_cfg_tdls_oper(struct wiphy *wiphy, + struct net_device *ndev, + u8 *peer, enum nl80211_tdls_operation oper) +#endif +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + DBGLOG(REQ, WARN, "P2P/AP don't support this function\n"); + return -EFAULT; + } + /* STA Mode */ + return mtk_cfg80211_tdls_oper(wiphy, ndev, peer, oper); +} + +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, + bool initiator, const u8 *buf, size_t len) +#elif KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, + const u8 *buf, size_t len) +#else +int mtk_cfg_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, + const u8 *buf, size_t len) +#endif +{ + struct GLUE_INFO *prGlueInfo; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, dev) > 0) { + DBGLOG(REQ, WARN, "P2P/AP don't support this function\n"); + return -EFAULT; + } + +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE + return mtk_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code, + dialog_token, status_code, peer_capability, initiator, + buf, len); +#elif KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE + return mtk_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code, + dialog_token, status_code, peer_capability, + buf, len); +#else + return mtk_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code, + dialog_token, status_code, + buf, len); +#endif +} +#endif /* CFG_SUPPORT_TDLS */ + +#if KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_del_station(struct wiphy *wiphy, + struct net_device *ndev, + struct station_del_parameters *params) +#elif KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_del_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac) +#else +int mtk_cfg_del_station(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac) +#endif +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { +#if KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE + return mtk_p2p_cfg80211_del_station(wiphy, ndev, params); +#else + return mtk_p2p_cfg80211_del_station(wiphy, ndev, mac); +#endif + } + /* STA Mode */ +#if CFG_SUPPORT_TDLS +#if KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE + return mtk_cfg80211_del_station(wiphy, ndev, params); +#else /* CFG80211_VERSION_CODE > KERNEL_VERSION(3, 19, 0) */ + return mtk_cfg80211_del_station(wiphy, ndev, mac); +#endif /* CFG80211_VERSION_CODE */ +#else /* CFG_SUPPORT_TDLS == 0 */ + /* AIS only support this function when CFG_SUPPORT_TDLS */ + return -EFAULT; +#endif /* CFG_SUPPORT_TDLS */ +} + +int mtk_cfg_scan(struct wiphy *wiphy, + struct cfg80211_scan_request *request) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, + request->wdev->netdev) > 0) + return mtk_p2p_cfg80211_scan(wiphy, request); + /* STA Mode */ + return mtk_cfg80211_scan(wiphy, request); +} + +#if KERNEL_VERSION(4, 5, 0) <= CFG80211_VERSION_CODE +void mtk_cfg_abort_scan(struct wiphy *wiphy, + struct wireless_dev *wdev) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, wdev->netdev) > 0) + mtk_p2p_cfg80211_abort_scan(wiphy, wdev); + else /* STA Mode */ + mtk_cfg80211_abort_scan(wiphy, wdev); +} +#endif + +#if CFG_SUPPORT_SCHED_SCAN +int mtk_cfg_sched_scan_start(IN struct wiphy *wiphy, + IN struct net_device *ndev, + IN struct cfg80211_sched_scan_request *request) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + DBGLOG(REQ, WARN, "P2P/AP don't support this function\n"); + return -EFAULT; + } + + return mtk_cfg80211_sched_scan_start(wiphy, ndev, request); + +} + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_sched_scan_stop(IN struct wiphy *wiphy, + IN struct net_device *ndev, + IN u64 reqid) +#else +int mtk_cfg_sched_scan_stop(IN struct wiphy *wiphy, + IN struct net_device *ndev) +#endif +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return 0; + } +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE + return mtk_cfg80211_sched_scan_stop(wiphy, ndev, reqid); +#else + return mtk_cfg80211_sched_scan_stop(wiphy, ndev); +#endif +} +#endif /* CFG_SUPPORT_SCHED_SCAN */ + +int mtk_cfg_connect(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_connect_params *sme) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) + return mtk_p2p_cfg80211_connect(wiphy, ndev, sme); + /* STA Mode */ + return mtk_cfg80211_connect(wiphy, ndev, sme); +} + +int mtk_cfg_disconnect(struct wiphy *wiphy, + struct net_device *ndev, + u16 reason_code) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) + return mtk_p2p_cfg80211_disconnect(wiphy, ndev, + reason_code); + /* STA Mode */ + return mtk_cfg80211_disconnect(wiphy, ndev, reason_code); +} + +int mtk_cfg_join_ibss(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_ibss_params *params) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) + return mtk_p2p_cfg80211_join_ibss(wiphy, ndev, params); + /* STA Mode */ + return mtk_cfg80211_join_ibss(wiphy, ndev, params); +} + +int mtk_cfg_leave_ibss(struct wiphy *wiphy, + struct net_device *ndev) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) + return mtk_p2p_cfg80211_leave_ibss(wiphy, ndev); + /* STA Mode */ + return mtk_cfg80211_leave_ibss(wiphy, ndev); +} + +int mtk_cfg_set_power_mgmt(struct wiphy *wiphy, + struct net_device *ndev, + bool enabled, int timeout) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + return mtk_p2p_cfg80211_set_power_mgmt(wiphy, ndev, + enabled, timeout); + } + /* STA Mode */ + return mtk_cfg80211_set_power_mgmt(wiphy, ndev, enabled, + timeout); +} + +int mtk_cfg_set_pmksa(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_pmksa *pmksa) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + DBGLOG(REQ, WARN, "P2P/AP don't support this function\n"); + return -EFAULT; + } + + return mtk_cfg80211_set_pmksa(wiphy, ndev, pmksa); +} + +int mtk_cfg_del_pmksa(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_pmksa *pmksa) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + DBGLOG(REQ, WARN, "P2P/AP don't support this function\n"); + return -EFAULT; + } + + return mtk_cfg80211_del_pmksa(wiphy, ndev, pmksa); +} + +int mtk_cfg_flush_pmksa(struct wiphy *wiphy, + struct net_device *ndev) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + DBGLOG(REQ, TRACE, "P2P/AP don't support this function\n"); + return -EFAULT; + } + + return mtk_cfg80211_flush_pmksa(wiphy, ndev); +} + +#if CONFIG_SUPPORT_GTK_REKEY +int mtk_cfg_set_rekey_data(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_gtk_rekey_data *data) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, dev) > 0) { + DBGLOG(REQ, WARN, "P2P/AP don't support this function\n"); + return -EFAULT; + } + + return mtk_cfg80211_set_rekey_data(wiphy, dev, data); +} +#endif /* CONFIG_SUPPORT_GTK_REKEY */ + +int mtk_cfg_suspend(struct wiphy *wiphy, + struct cfg80211_wowlan *wow) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!wlanIsDriverReady(prGlueInfo)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return 0; + } + + /* TODO: AP/P2P do not support this function, should take that case. */ + return mtk_cfg80211_suspend(wiphy, wow); +} + +int mtk_cfg_resume(struct wiphy *wiphy) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!wlanIsDriverReady(prGlueInfo)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return 0; + } + + /* TODO: AP/P2P do not support this function, should take that case. */ + return mtk_cfg80211_resume(wiphy); +} + +int mtk_cfg_assoc(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_assoc_request *req) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + DBGLOG(REQ, WARN, "P2P/AP don't support this function\n"); + return -EFAULT; + } + /* STA Mode */ + return mtk_cfg80211_assoc(wiphy, ndev, req); +} + +int mtk_cfg_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, + unsigned int duration, u64 *cookie) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, wdev->netdev) > 0) { + return mtk_p2p_cfg80211_remain_on_channel(wiphy, wdev, chan, + duration, cookie); + } + /* STA Mode */ + return mtk_cfg80211_remain_on_channel(wiphy, wdev, chan, + duration, cookie); +} + +int mtk_cfg_cancel_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, u64 cookie) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, wdev->netdev) > 0) { + return mtk_p2p_cfg80211_cancel_remain_on_channel(wiphy, + wdev, + cookie); + } + /* STA Mode */ + return mtk_cfg80211_cancel_remain_on_channel(wiphy, wdev, + cookie); +} + +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, u64 *cookie) +#else +int mtk_cfg_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, + struct ieee80211_channel *channel, bool offchan, + unsigned int wait, const u8 *buf, size_t len, bool no_cck, + bool dont_wait_for_ack, u64 *cookie) +#endif +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE + if (mtk_IsP2PNetDevice(prGlueInfo, wdev->netdev) > 0) + return mtk_p2p_cfg80211_mgmt_tx(wiphy, wdev, params, + cookie); + /* STA Mode */ + return mtk_cfg80211_mgmt_tx(wiphy, wdev, params, cookie); +#else /* KERNEL_VERSION(3, 14, 0) > CFG80211_VERSION_CODE */ + if (mtk_IsP2PNetDevice(prGlueInfo, wdev->netdev) > 0) { + return mtk_p2p_cfg80211_mgmt_tx(wiphy, wdev, channel, offchan, + wait, buf, len, no_cck, dont_wait_for_ack, cookie); + } + /* STA Mode */ + return mtk_cfg80211_mgmt_tx(wiphy, wdev, channel, offchan, wait, buf, + len, no_cck, dont_wait_for_ack, cookie); +#endif +} + +void mtk_cfg_mgmt_frame_register(struct wiphy *wiphy, + struct wireless_dev *wdev, + u16 frame_type, bool reg) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, wdev->netdev) > 0) { + mtk_p2p_cfg80211_mgmt_frame_register(wiphy, wdev, + frame_type, + reg); + } else { + mtk_cfg80211_mgmt_frame_register(wiphy, wdev, frame_type, + reg); + } +} + +#ifdef CONFIG_NL80211_TESTMODE +#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_testmode_cmd(struct wiphy *wiphy, + struct wireless_dev *wdev, + void *data, int len) +#else +int mtk_cfg_testmode_cmd(struct wiphy *wiphy, void *data, + int len) +#endif +{ +#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, wdev->netdev) > 0) { + return mtk_p2p_cfg80211_testmode_cmd(wiphy, wdev, data, + len); + } + + return mtk_cfg80211_testmode_cmd(wiphy, wdev, data, len); +#else + /* XXX: no information can to check the mtk_IsP2PNetDevice */ + /* return mtk_p2p_cfg80211_testmode_cmd(wiphy, data, len); */ + return mtk_cfg80211_testmode_cmd(wiphy, data, len); +#endif +} +#endif /* CONFIG_NL80211_TESTMODE */ + +#if (CFG_ENABLE_WIFI_DIRECT_CFG_80211 != 0) +int mtk_cfg_change_bss(struct wiphy *wiphy, + struct net_device *dev, + struct bss_parameters *params) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, dev) <= 0) { + DBGLOG(REQ, WARN, "STA doesn't support this function\n"); + return -EFAULT; + } + + return mtk_p2p_cfg80211_change_bss(wiphy, dev, params); +} + +int mtk_cfg_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, wdev->netdev) <= 0) { + return mtk_cfg80211_mgmt_tx_cancel_wait(wiphy, wdev, cookie); + } + + return mtk_p2p_cfg80211_mgmt_tx_cancel_wait(wiphy, wdev, + cookie); +} + +int mtk_cfg_deauth(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_deauth_request *req) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, dev) <= 0) { + DBGLOG(REQ, WARN, "STA doesn't support this function\n"); + return -EFAULT; + } + + return mtk_p2p_cfg80211_deauth(wiphy, dev, req); +} + +int mtk_cfg_disassoc(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_disassoc_request *req) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, dev) <= 0) { + DBGLOG(REQ, WARN, "STA doesn't support this function\n"); + return -EFAULT; + } + + return mtk_p2p_cfg80211_disassoc(wiphy, dev, req); +} + +int mtk_cfg_start_ap(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ap_settings *settings) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, dev) <= 0) { + DBGLOG(REQ, WARN, "STA doesn't support this function\n"); + return -EFAULT; + } + + return mtk_p2p_cfg80211_start_ap(wiphy, dev, settings); +} + +int mtk_cfg_change_beacon(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_beacon_data *info) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, dev) <= 0) { + DBGLOG(REQ, WARN, "STA doesn't support this function\n"); + return -EFAULT; + } + + return mtk_p2p_cfg80211_change_beacon(wiphy, dev, info); +} + +int mtk_cfg_stop_ap(struct wiphy *wiphy, + struct net_device *dev) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, dev) <= 0) { + DBGLOG(REQ, WARN, "STA doesn't support this function\n"); + return -EFAULT; + } + + return mtk_p2p_cfg80211_stop_ap(wiphy, dev); +} + +int mtk_cfg_set_wiphy_params(struct wiphy *wiphy, + u32 changed) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + /* TODO: AIS not support this function */ + return mtk_p2p_cfg80211_set_wiphy_params(wiphy, changed); +} + +int mtk_cfg_set_bitrate_mask(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, + const struct cfg80211_bitrate_mask *mask) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, dev) <= 0) { + DBGLOG(REQ, WARN, "STA doesn't support this function\n"); + return -EFAULT; + } + + return mtk_p2p_cfg80211_set_bitrate_mask(wiphy, dev, peer, + mask); +} + +int mtk_cfg_set_txpower(struct wiphy *wiphy, + struct wireless_dev *wdev, + enum nl80211_tx_power_setting type, int mbm) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, wdev->netdev) <= 0) { + DBGLOG(REQ, WARN, "STA doesn't support this function\n"); + return -EFAULT; + } + + return mtk_p2p_cfg80211_set_txpower(wiphy, wdev, type, mbm); +} + +int mtk_cfg_get_txpower(struct wiphy *wiphy, + struct wireless_dev *wdev, + int *dbm) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if ((!prGlueInfo) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG_LIMITED(REQ, TRACE, "driver is not ready\n"); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, wdev->netdev) <= 0) { + DBGLOG_LIMITED(REQ, TRACE, + "STA doesn't support this function\n"); + return -EFAULT; + } + + return mtk_p2p_cfg80211_get_txpower(wiphy, wdev, dbm); +} +#endif /* (CFG_ENABLE_WIFI_DIRECT_CFG_80211 != 0) */ +#endif /* CFG_ENABLE_UNIFY_WIPHY */ + +/*-----------------------------------------------------------------------*/ +/*! + * @brief This function goes through the provided ies buffer, and + * collects those non-wfa vendor specific ies into driver's + * internal buffer (non_wfa_vendor_ie_buf), to be sent in + * AssocReq in AIS mode. + * The non-wfa vendor specific ies are those with ie_id = 0xdd + * and ouis are different from wfa's oui. (i.e., it could be + * customer's vendor ie ...etc. + * + * @param prGlueInfo driver's private glueinfo + * ies ie buffer + * len length of ie + * + * @retval length of the non_wfa vendor ie + */ +/*-----------------------------------------------------------------------*/ +uint16_t cfg80211_get_non_wfa_vendor_ie(struct GLUE_INFO *prGlueInfo, + uint8_t *ies, int32_t len, uint8_t ucBssIndex) +{ + const uint8_t *pos = ies, *end = ies+len; + struct ieee80211_vendor_ie *ie; + int32_t ie_oui = 0; + uint16_t *ret_len, max_len; + uint8_t *w_pos; + struct CONNECTION_SETTINGS *prConnSettings; + + if (!prGlueInfo || !ies || !len) + return 0; + + prConnSettings = + aisGetConnSettings(prGlueInfo->prAdapter, + ucBssIndex); + if (!prConnSettings) + return 0; + + w_pos = prConnSettings->non_wfa_vendor_ie_buf; + ret_len = &prConnSettings->non_wfa_vendor_ie_len; + max_len = (uint16_t)sizeof(prConnSettings->non_wfa_vendor_ie_buf); + + while (pos < end) { + pos = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, pos, + end - pos); + if (!pos) + break; + + ie = (struct ieee80211_vendor_ie *)pos; + + /* Make sure we can access ie->len */ + BUILD_BUG_ON(offsetof(struct ieee80211_vendor_ie, len) != 1); + + if (ie->len < sizeof(*ie)) + goto cont; + + ie_oui = ie->oui[0] << 16 | ie->oui[1] << 8 | ie->oui[2]; + /* + * If oui is other than: 0x0050f2 & 0x506f9a, + * we consider it is non-wfa oui. + */ + if (ie_oui != WLAN_OUI_MICROSOFT && ie_oui != WLAN_OUI_WFA) { + /* + * If remaining buf len is capable, we copy + * this ie to the buf. + */ + if (max_len-(*ret_len) >= ie->len+2) { + DBGLOG(AIS, TRACE, + "vendor ie(len=%d, oui=0x%06x)\n", + ie->len, ie_oui); + memcpy(w_pos, pos, ie->len+2); + w_pos += (ie->len+2); + (*ret_len) += ie->len+2; + } else { + /* Otherwise we give an error msg + * and return. + */ + DBGLOG(AIS, ERROR, + "Insufficient buf for vendor ie, exit!\n"); + break; + } + } +cont: + pos += 2 + ie->len; + } + return *ret_len; +} + +int mtk_cfg80211_update_ft_ies(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_update_ft_ies_params *ftie) +{ +#if CFG_SUPPORT_802_11R + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4InfoBufLen = 0; + uint32_t rStatus = WLAN_STATUS_FAILURE; + uint8_t ucBssIndex = 0; + + if (!wiphy) + return -1; + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + ucBssIndex = wlanGetBssIdx(dev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return -EINVAL; + + rStatus = kalIoctlByBssIdx(prGlueInfo, wlanoidUpdateFtIes, (void *)ftie, + sizeof(*ftie), FALSE, FALSE, FALSE, &u4InfoBufLen, + ucBssIndex); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(OID, INFO, "FT: update Ft IE failed\n"); +#else + DBGLOG(OID, INFO, "FT: 802.11R is not enabled\n"); +#endif + + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_hook_api.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_hook_api.c new file mode 100644 index 0000000000000..f6424c317730a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_hook_api.c @@ -0,0 +1,4696 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + Module Name: + gl_ate_agent.c +*/ +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" +#if CFG_SUPPORT_QA_TOOL +#include "gl_wext.h" +#include "gl_cfg80211.h" +#include "gl_ate_agent.h" +#include "gl_qa_agent.h" +#if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE +#include +#endif + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +enum { + ATE_LOG_RXV = 1, + ATE_LOG_RDD, + ATE_LOG_RE_CAL, + ATE_LOG_TYPE_NUM, + ATE_LOG_RXINFO, + ATE_LOG_TXDUMP, + ATE_LOG_TEST, +}; + +enum { + ATE_LOG_OFF, + ATE_LOG_ON, + ATE_LOG_DUMP, + ATE_LOG_CTRL_NUM, +}; + +/* Maximum rxv vectors under 2048-2 bytes */ +#define MAX_RXV_DUMP_COUNT (56) +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Enter Test Mode. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEStart(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetTestMode, /* pfnOidHandler */ + NULL, /* pvInfoBuf */ + 0, /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Enter ICAP Mode. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ICAPStart(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetTestIcapMode, /* pfnOidHandler */ + NULL, /* pvInfoBuf */ + 0, /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Enter ICAP Mode. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ICAPCommand(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct mt66xx_chip_info *prChipInfo = NULL; + struct ATE_OPS_T *prAteOps = NULL; + uint32_t *buf = NULL; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prChipInfo = prGlueInfo->prAdapter->chip_info; + ASSERT(prChipInfo); + prAteOps = prChipInfo->prAteOps; + ASSERT(prAteOps); + + if (prInBuf[0] == '1') { + if (prAteOps->setICapStart) + i4Status = prAteOps->setICapStart(prGlueInfo, + 1, + 0, + 0, + 0x10000006, + 0, + 10, + 0, + 0x2000, + 0xefefefef, + 0x0001efef, + 0); + else + i4Status = 1; + } else if (prInBuf[0] == '2') { + if (prAteOps->getICapStatus) + i4Status = prAteOps->getICapStatus(prGlueInfo); + else + i4Status = 1; + } else if (prInBuf[0] == '3') { + if (prAteOps->getICapIQData) { + buf = kalMemAlloc(1024, VIR_MEM_TYPE); + if (buf) { + i4Status = prAteOps->getICapIQData(prGlueInfo, + (uint8_t *) buf, CAP_I_TYPE, 0); + dumpMemory32((uint32_t *)buf, i4Status); + kalMemFree(buf, VIR_MEM_TYPE, 1024); + } + } else + i4Status = 1; + } else if (prInBuf[0] == '4') { + if (prAteOps->getICapIQData) { + buf = (uint32_t *) kalMemAlloc(1024, VIR_MEM_TYPE); + if (buf) { + i4Status = prAteOps->getICapIQData(prGlueInfo, + (uint8_t *) buf, CAP_Q_TYPE, 0); + dumpMemory32((uint32_t *)buf, i4Status); + kalMemFree(buf, VIR_MEM_TYPE, 1024); + } + } else + i4Status = 1; + } else if (prInBuf[0] == '5') { + if (prAteOps->getICapIQData) { + buf = (uint32_t *) kalMemAlloc(1024, VIR_MEM_TYPE); + if (buf) { + i4Status = prAteOps->getICapIQData(prGlueInfo, + (uint8_t *) buf, CAP_I_TYPE, 1); + dumpMemory32((uint32_t *)buf, i4Status); + kalMemFree(buf, VIR_MEM_TYPE, 1024); + } + } else + i4Status = 1; + } else if (prInBuf[0] == '6') { + if (prAteOps->getICapIQData) { + buf = (uint32_t *) kalMemAlloc(1024, VIR_MEM_TYPE); + if (buf) { + i4Status = prAteOps->getICapIQData(prGlueInfo, + (uint8_t *) buf, CAP_Q_TYPE, 1); + dumpMemory32((uint32_t *)buf, i4Status); + kalMemFree(buf, VIR_MEM_TYPE, 1024); + } + } else + i4Status = 1; + } + + return i4Status; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Abort Test Mode. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEStop(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAbortTestMode, /* pfnOidHandler */ + NULL, /* pvInfoBuf */ + 0, /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Start auto Tx test in packet format and the driver will + * enter auto Tx test mode. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEStartTX(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_STARTTX; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Stop TX/RX test action if the driver is in any test + * mode. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEStopTX(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_STOPTEST; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Start auto Rx test and the driver will enter auto Rx + * test mode. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEStartRX(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_STARTRX; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Stop TX/RX test action if the driver is in any test + * mode. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEStopRX(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_STOPTEST; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Channel Frequency. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4SetFreq Center frequency in unit of KHz + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetChannel(struct net_device *prNetDev, + uint32_t u4SXIdx, uint32_t u4SetFreq) +{ + uint32_t u4BufLen = 0; + uint32_t i4SetChan; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + i4SetChan = nicFreq2ChannelNum(u4SetFreq); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetChannel=%d, Freq=%d\n", + i4SetChan, u4SetFreq); + + if (u4SetFreq == 0) + return -EINVAL; + + if (u4SXIdx == 0) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_CHNL_FREQ; + rRfATInfo.u4FuncData = u4SetFreq; + } else { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_CHNL_FREQ | BIT(16); + rRfATInfo.u4FuncData = u4SetFreq; + } + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Preamble. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4Mode depends on Rate. 0--> normal, + * 1--> CCK short preamble, + * 2: 11n MM, + * 3: 11n GF + * 4: 11ac VHT + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetPreamble(struct net_device *prNetDev, + uint32_t u4Mode) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetPreamble=%d\n", + u4Mode); + + if (u4Mode > 4) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_PREAMBLE; + rRfATInfo.u4FuncData = u4Mode; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Channel Bandwidth. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4BW Choose Channel Bandwidth + * 0: 20 / 1: 40 / 2: 80 / 3: 160 + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetSystemBW(struct net_device *prNetDev, + uint32_t u4BW) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t u4BWMapping = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetSystemBW=%d\n", u4BW); + + if (u4BW > 6) + return -EINVAL; + + /* BW Mapping in QA Tool + * 0: BW20 + * 1: BW40 + * 2: BW80 + * 3: BW10 + * 4: BW5 + * 5: BW160C + * 6: BW160NC + */ + /* BW Mapping in FW + * 0: BW20 + * 1: BW40 + * 2: BW80 + * 3: BW160C + * 4: BW160NC + * 5: BW5 + * 6: BW10 + */ + if (u4BW == 0) + u4BWMapping = 0; + else if (u4BW == 1) + u4BWMapping = 1; + else if (u4BW == 2) + u4BWMapping = 2; + else if (u4BW == 3) + u4BWMapping = 6; + else if (u4BW == 4) + u4BWMapping = 5; + else if (u4BW == 5) + u4BWMapping = 3; + else if (u4BW == 6) + u4BWMapping = 4; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_CBW; + rRfATInfo.u4FuncData = u4BWMapping; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set TX Length. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4TxLength Packet length (MPDU) + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetTxLength(struct net_device *prNetDev, + uint32_t u4TxLength) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetTxLength=%d\n", + u4TxLength); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_PKTLEN; + rRfATInfo.u4FuncData = u4TxLength; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set TX Count. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4TxCount Total packet count to send. 0 : unlimited, + * until stopped + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetTxCount(struct net_device *prNetDev, + uint32_t u4TxCount) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetTxCount=%d\n", + u4TxCount); + + if (u4TxCount < 0) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_PKTCNT; + rRfATInfo.u4FuncData = u4TxCount; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set TX Inter-Packet Guard. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4TxIPG In unit of us. The min value is 19us and max + * value is 2314us. + * \ It will be round-up to (19+9n) us. + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetTxIPG(struct net_device *prNetDev, + uint32_t u4TxIPG) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetTxIPG=%d\n", u4TxIPG); + + if (u4TxIPG > 2314 || u4TxIPG < 19) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_PKTINTERVAL; + rRfATInfo.u4FuncData = u4TxIPG; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set WF0 TX Power. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4TxPower0 Tx Gain of RF. The value is signed absolute + * power + * (2's complement representation) in unit of 0.5 dBm. + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetTxPower0(struct net_device *prNetDev, + uint32_t u4TxPower0) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetTxPower0=0x%02x\n", + u4TxPower0); + + if (u4TxPower0 > 0x3F) { + u4TxPower0 += 128; + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK Negative Power =0x%02x\n", + u4TxPower0); + } + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_POWER; + rRfATInfo.u4FuncData = u4TxPower0; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Per Packet BW. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4BW 0: 20 / 1: 40 / 2: 80 / 3: 160 + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetPerPacketBW(struct net_device *prNetDev, + uint32_t u4BW) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t u4BWMapping = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetPerPacketBW=%d\n", + u4BW); + + if (u4BW > 6) + return -EINVAL; + + /* BW Mapping in QA Tool + * 0: BW20 + * 1: BW40 + * 2: BW80 + * 3: BW10 + * 4: BW5 + * 5: BW160C + * 6: BW160NC + */ + /* BW Mapping in FW + * 0: BW20 + * 1: BW40 + * 2: BW80 + * 3: BW160C + * 4: BW160NC + * 5: BW5 + * 6: BW10 + */ + if (u4BW == 0) + u4BWMapping = 0; + else if (u4BW == 1) + u4BWMapping = 1; + else if (u4BW == 2) + u4BWMapping = 2; + else if (u4BW == 3) + u4BWMapping = 6; + else if (u4BW == 4) + u4BWMapping = 5; + else if (u4BW == 5) + u4BWMapping = 3; + else if (u4BW == 6) + u4BWMapping = 4; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_DBW; + rRfATInfo.u4FuncData = u4BWMapping; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Primary Channel Setting. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4PrimaryCh The range is from 0~7 + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEPrimarySetting(struct net_device *prNetDev, + uint32_t u4PrimaryCh) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK PrimarySetting=%d\n", + u4PrimaryCh); + + if (u4PrimaryCh > 7) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_PRIMARY_CH; + rRfATInfo.u4FuncData = u4PrimaryCh; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set TX Guard Interval. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4SetTxGi 0: Normal GI, 1: Short GI + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetTxGi(struct net_device *prNetDev, + uint32_t u4SetTxGi) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetTxGi=%d\n", u4SetTxGi); + + if (u4SetTxGi != 0 && u4SetTxGi != 1) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_GI; + rRfATInfo.u4FuncData = u4SetTxGi; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set TX Path. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4Tx_path 0: All Tx, 1: WF0, 2: WF1, 3: WF0+WF1 + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetTxPath(struct net_device *prNetDev, + uint32_t u4Tx_path) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK u4Tx_path=%d\n", + u4Tx_path); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TX_PATH; + rRfATInfo.u4FuncData = u4Tx_path; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set RX Path. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4Tx_path + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetRxPath(struct net_device *prNetDev, uint32_t u4Rx_path) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK u4Rx_path=%d\n", u4Rx_path); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_RX_PATH; + rRfATInfo.u4FuncData = u4Rx_path; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set TX Payload Fix/Random. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4Stbc 0: Disable , 1 : Enable + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetTxPayLoad(struct net_device *prNetDev, + uint32_t u4Gen_payload_rule, uint8_t ucPayload) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK rule=%d, len =0x%x\n", + u4Gen_payload_rule, ucPayload); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_PAYLOAD; + rRfATInfo.u4FuncData = ((u4Gen_payload_rule << 16) | + ucPayload); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set TX STBC. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4Stbc 0: Disable , 1 : Enable + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetTxSTBC(struct net_device *prNetDev, + uint32_t u4Stbc) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK u4Stbc=%d\n", u4Stbc); + + if (u4Stbc > 1) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_STBC; + rRfATInfo.u4FuncData = u4Stbc; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set TX Nss. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4Nss 1/2 + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetTxVhtNss(struct net_device *prNetDev, + uint32_t u4VhtNss) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK u4Nss=%d\n", u4VhtNss); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_NSS; + rRfATInfo.u4FuncData = u4VhtNss; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Rate. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4Rate Rate + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetRate(struct net_device *prNetDev, + uint32_t u4Rate) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetRate=0x%08x\n", + u4Rate); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_RATE; + rRfATInfo.u4FuncData = u4Rate; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Encode Mode. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4Ldpc 0: BCC / 1: LDPC + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetEncodeMode(struct net_device *prNetDev, + uint32_t u4Ldpc) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetEncodeMode=%d\n", + u4Ldpc); + + if (u4Ldpc != 0 && u4Ldpc != 1) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ENCODE_MODE; + rRfATInfo.u4FuncData = u4Ldpc; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set iBF Enable. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4iBF 0: disable / 1: enable + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetiBFEnable(struct net_device *prNetDev, + uint32_t u4iBF) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetiBFEnable=%d\n", + u4iBF); + + if (u4iBF != 0 && u4iBF != 1) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_IBF_ENABLE; + rRfATInfo.u4FuncData = u4iBF; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set eBF Enable. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4eBF 0: disable / 1: enable + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESeteBFEnable(struct net_device *prNetDev, + uint32_t u4eBF) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SeteBFEnable=%d\n", + u4eBF); + + if (u4eBF != 0 && u4eBF != 1) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_EBF_ENABLE; + rRfATInfo.u4FuncData = u4eBF; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set MAC Address. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4Type Address type + * \param[in] ucAddr Address ready to set + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetMACAddress(struct net_device *prNetDev, + uint32_t u4Type, uint8_t *ucAddr) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, ERROR, + "QA_ATE_HOOK SetMACAddress Type = %d, Addr = %02x:%02x:%02x:%02x:%02x:%02x\n", + u4Type, ucAddr[0], ucAddr[1], ucAddr[2], ucAddr[3], + ucAddr[4], ucAddr[5]); + +#if 1 + rRfATInfo.u4FuncIndex = u4Type; + memcpy(&rRfATInfo.u4FuncData, ucAddr, 4); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; +#endif + rRfATInfo.u4FuncIndex = u4Type | BIT(18); + memset(&rRfATInfo.u4FuncData, 0, + sizeof(rRfATInfo.u4FuncData)); + memcpy(&rRfATInfo.u4FuncData, ucAddr + 4, 2); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for RX Vector Dump. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4Type + * \param[in] u4On_off + * \param[in] u4Size + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATELogOnOff(struct net_device *prNetDev, + uint32_t u4Type, uint32_t u4On_off, uint32_t u4Size) +{ + int32_t i4Status = 0, i, i4TargetLength = 0, + i4MaxDumpRXVCnt = 500; + uint32_t u4BufLen = 0, rxv; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATELogOnOff\n"); + + switch (u4Type) { + case ATE_LOG_RXV: + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATELogOnOff : ATE_LOG_RXV\n\n"); + break; + case ATE_LOG_RDD: + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATELogOnOff : ATE_LOG_RDD\n\n"); + break; + case ATE_LOG_RE_CAL: + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATELogOnOff : ATE_LOG_RE_CAL\n\n"); + break; + case ATE_LOG_RXINFO: + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATELogOnOff : ATE_LOG_RXINFO\n\n"); + break; + case ATE_LOG_TXDUMP: + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATELogOnOff : ATE_LOG_TXDUMP\n\n"); + break; + case ATE_LOG_TEST: + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATELogOnOff : ATE_LOG_TEST\n\n"); + break; + default: + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK log type %d not supported\n\n", u4Type); + } + + if ((u4On_off == ATE_LOG_DUMP) && (u4Type == ATE_LOG_RXV)) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_RESULT_INFO; + rRfATInfo.u4FuncData = RF_AT_FUNCID_RXV_DUMP; + + i4Status = kalIoctl(prGlueInfo, wlanoidRftestQueryAutoTest, + &rRfATInfo, sizeof(rRfATInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + i4TargetLength = rRfATInfo.u4FuncData * 36; + DBGLOG(RFTEST, ERROR, + "QA_ATE_HOOK Get RX Vector Total size = %d\n", + i4TargetLength); + + if (i4TargetLength >= (i4MaxDumpRXVCnt * 36)) + i4TargetLength = (i4MaxDumpRXVCnt * 36); + } else { + DBGLOG(RFTEST, ERROR, + "QA_ATE_HOOK Get RX Vector Total Size Error!!!!\n\n"); + } + + TOOL_PRINTLOG(RFTEST, ERROR, "[LOG DUMP START]\n"); + + for (i = 0; i < i4TargetLength; i += 4) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_RXV_DUMP; + rRfATInfo.u4FuncData = i; + + i4Status = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, + &rRfATInfo, sizeof(rRfATInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + rxv = rRfATInfo.u4FuncData; + + if (i % 36 == 0) + TOOL_PRINTLOG(RFTEST, ERROR, + "%%[RXV DUMP START][%d]\n", + (i / 36) + 1); + + TOOL_PRINTLOG(RFTEST, ERROR, "[RXVD%d]%08x\n", + ((i % 36) / 4) + 1, rxv); + + if (((i % 36) / 4) + 1 == 9) + TOOL_PRINTLOG(RFTEST, ERROR, + "[RXV DUMP END]\n"); + } + } + + TOOL_PRINTLOG(RFTEST, ERROR, "[LOG DUMP END]\n"); + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Get RX Vector Dump. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[out] pucData Pointer to the output data buffer +* \param[out] pCount Pointer to the length of data +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEGetDumpRXV(struct net_device *prNetDev, + uint8_t *pucData, + int32_t *pCount) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t i = 0, u4BufLen = 0, u4Value = 0; + uint32_t u4RespLen = 2, i4TargetLength = 0; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_RESULT_INFO; + rRfATInfo.u4FuncData = RF_AT_FUNCID_RXV_DUMP; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + + i4Status = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, + &rRfATInfo, + sizeof(rRfATInfo), + TRUE, + TRUE, + TRUE, + &u4BufLen); + + if (i4Status == 0) { + DBGLOG(RFTEST, INFO, "Get RX Vector Total count = %d\n", + rRfATInfo.u4FuncData); + if (rRfATInfo.u4FuncData > MAX_RXV_DUMP_COUNT) + rRfATInfo.u4FuncData = MAX_RXV_DUMP_COUNT; + + i4TargetLength = rRfATInfo.u4FuncData * 36; + u4Value = ntohl(rRfATInfo.u4FuncData); + kalMemCopy(pucData + u4RespLen, + (uint8_t *)&u4Value, + sizeof(u4Value)); + u4RespLen += sizeof(u4Value); + } else { + DBGLOG(RFTEST, ERROR, "Get RX Vector Total Size Error!!\n"); + return -EFAULT; + } + + for (i = 0; i < i4TargetLength; i += 4) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_RXV_DUMP; + rRfATInfo.u4FuncData = i; + + i4Status = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, + &rRfATInfo, + sizeof(rRfATInfo), + TRUE, + TRUE, + TRUE, + &u4BufLen); + + if (i4Status == 0) { + u4Value = ntohl(rRfATInfo.u4FuncData); + kalMemCopy(pucData + u4RespLen, + (uint8_t *)&u4Value, + sizeof(u4Value)); + u4RespLen += sizeof(u4Value); + } else { + DBGLOG(RFTEST, ERROR, + "Error getting index[%d]'s RXV dump data!!\n", i); + return -EFAULT; + } + } + + *pCount = i4TargetLength; + /* dumpMemory32((PUINT_32)pucData, i4TargetLength + 8); */ + + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Reset Counter. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEResetTXRXCounter(struct net_device *prNetDev) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATEResetTXRXCounter\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_RESETTXRXCOUNTER; + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set DBDC Band Index. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4BandIdx Band Index Number ready to set + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetDBDCBandIndex(struct net_device *prNetDev, + uint32_t u4BandIdx) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATESetDBDCBandIndex\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_DBDC_BAND_IDX; + rRfATInfo.u4FuncData = u4BandIdx; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Band. (2G or 5G) + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] i4Band Band to set + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetBand(struct net_device *prNetDev, + int32_t i4Band) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATESetBand\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_BAND; + rRfATInfo.u4FuncData = i4Band; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Tx Tone Type. (2G or 5G) + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] i4ToneType Set Single or Two Tone. + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetTxToneType(struct net_device *prNetDev, + int32_t i4ToneType) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATESetTxToneType\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TONE_TYPE; + rRfATInfo.u4FuncData = i4ToneType; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Tx Tone Frequency. (DC/5M/10M/20M/40M) + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] i4ToneFreq Set Tx Tone Frequency. + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetTxToneBW(struct net_device *prNetDev, + int32_t i4ToneFreq) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATESetTxToneBW\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TONE_BW; + rRfATInfo.u4FuncData = i4ToneFreq; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Tx Tone DC Offset. (DC Offset I / DC Offset Q) + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] i4DcOffsetI Set Tx Tone DC Offset I. + * \param[in] i4DcOffsetQ Set Tx Tone DC Offset Q. + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetTxToneDCOffset(struct net_device *prNetDev, + int32_t i4DcOffsetI, int32_t i4DcOffsetQ) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATESetTxToneDCOffset\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TONE_DC_OFFSET; + rRfATInfo.u4FuncData = i4DcOffsetQ << 16 | i4DcOffsetI; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Tx Tone Power. (RF and Digital) + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] i4AntIndex + * \param[in] i4RF_Power + * \param[in] i4Digi_Power + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetDBDCTxTonePower(struct net_device *prNetDev, + int32_t i4AntIndex, int32_t i4RF_Power, int32_t i4Digi_Power) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATESetDBDCTxTonePower\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TONE_RF_GAIN; + rRfATInfo.u4FuncData = i4AntIndex << 16 | i4RF_Power; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TONE_DIGITAL_GAIN; + rRfATInfo.u4FuncData = i4AntIndex << 16 | i4Digi_Power; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Start Tx Tone. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] i4Control Start or Stop TX Tone. + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEDBDCTxTone(struct net_device *prNetDev, + int32_t i4Control) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATEDBDCTxTone\n"); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (i4Control) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_SINGLE_TONE; + } else { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_STOPTEST; + } + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set TX Mac Header. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4BandIdx Band Index Number ready to set + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetMacHeader(struct net_device *prNetDev, + uint32_t u4FrameCtrl, uint32_t u4DurationID, + uint32_t u4SeqCtrl) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATESetMacHeader\n"); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MAC_HEADER; + rRfATInfo.u4FuncData = u4FrameCtrl || (u4DurationID << 16); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_SEQ_CTRL; + rRfATInfo.u4FuncData = u4SeqCtrl; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for IRR Set ADC. (RF_AT_FUNCID_SET_ADC) + * + * \param[in] prNetDev Pointer to the Net Device + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATE_IRRSetADC(struct net_device *prNetDev, + uint32_t u4WFIdx, + uint32_t u4ChFreq, + uint32_t u4BW, uint32_t u4Sx, uint32_t u4Band, + uint32_t u4RunType, uint32_t u4FType) +{ + uint32_t u4BufLen = 0, i = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t au4Param[7]; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATE_IRRSetADC\n"); + + if (u4BW == 3 || u4BW == 4 || u4BW > 5) + return -EINVAL; + + if (u4BW == 5) /* For BW160, UI will pass "5" */ + u4BW = 3; + + au4Param[0] = u4ChFreq; + au4Param[1] = u4WFIdx; + au4Param[2] = u4BW; + au4Param[3] = u4Sx; + au4Param[4] = u4Band; + au4Param[5] = u4RunType; + au4Param[6] = u4FType; + + for (i = 0; i < 8; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ADC | (i << 16); + if (i < 7) + rRfATInfo.u4FuncData = au4Param[i]; + else + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for IRR Set RX Gain. (RF_AT_FUNCID_SET_RX_GAIN) + * + * \param[in] prNetDev Pointer to the Net Device + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATE_IRRSetRxGain(struct net_device *prNetDev, + uint32_t u4PgaLpfg, uint32_t u4Lna, uint32_t u4Band, + uint32_t u4WF_inx, uint32_t u4Rfdgc) +{ + uint32_t u4BufLen = 0, i = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t au4Param[5]; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATE_IRRSetRxGain\n"); + + au4Param[0] = u4PgaLpfg; + au4Param[1] = u4Lna; + au4Param[2] = u4Band; + au4Param[3] = u4WF_inx; + au4Param[4] = u4Rfdgc; + + for (i = 0; i < 6; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_RX_GAIN | + (i << 16); + if (i < 5) + rRfATInfo.u4FuncData = au4Param[i]; + else + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for IRR Set TTG. (RF_AT_FUNCID_SET_TTG) + * + * \param[in] prNetDev Pointer to the Net Device + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATE_IRRSetTTG(struct net_device *prNetDev, + uint32_t u4TTGPwrIdx, uint32_t u4ChFreq, + uint32_t u4FIToneFreq, uint32_t u4Band) +{ + uint32_t u4BufLen = 0, i = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t au4Param[4]; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATE_IRRSetTTG\n"); + + au4Param[0] = u4ChFreq; + au4Param[1] = u4FIToneFreq; + au4Param[2] = u4TTGPwrIdx; + au4Param[3] = u4Band; + + for (i = 0; i < 5; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TTG | (i << 16); + if (i < 4) + rRfATInfo.u4FuncData = au4Param[i]; + else + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for IRR Set TTG On/Off. (RF_AT_FUNCID_TTG_ON_OFF) + * + * \param[in] prNetDev Pointer to the Net Device + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATE_IRRSetTrunOnTTG(struct net_device *prNetDev, + uint32_t u4TTGOnOff, uint32_t u4Band, uint32_t u4WF_inx) +{ + uint32_t u4BufLen = 0, i = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t au4Param[3]; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATE_IRRSetTrunOnTTG\n"); + + au4Param[0] = u4TTGOnOff; + au4Param[1] = u4Band; + au4Param[2] = u4WF_inx; + + for (i = 0; i < 4; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_TTG_ON_OFF | (i << 16); + if (i < 3) + rRfATInfo.u4FuncData = au4Param[i]; + else + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for IRR Set TTG On/Off. + * + * \param[in] prNetDev Pointer to the Net Device + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATE_TMRSetting(struct net_device *prNetDev, uint32_t u4Setting, + uint32_t u4Version, uint32_t u4MPThres, uint32_t u4MPIter) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATE_TMRSetting\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TMR_ROLE; + rRfATInfo.u4FuncData = u4Setting; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TMR_MODULE; + rRfATInfo.u4FuncData = u4Version; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TMR_DBM; + rRfATInfo.u4FuncData = u4MPThres; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TMR_ITER; + rRfATInfo.u4FuncData = u4MPIter; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for MPS Setting. (Set Seq Data) + * + * \param[in] prNetDev Pointer to the Net Device + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEMPSSetSeqData(struct net_device *prNetDev, + uint32_t u4TestNum, uint32_t *pu4Phy, uint32_t u4Band) +{ + uint32_t u4BufLen = 0, i; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATEMPSSetSeqData\n"); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_SIZE; + rRfATInfo.u4FuncData = u4TestNum; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + for (i = 0 ; i < u4TestNum ; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_SEQ_DATA | + (i << 16); + rRfATInfo.u4FuncData = pu4Phy[i]; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for MPS Setting. (Set Payload Length) + * + * \param[in] prNetDev Pointer to the Net Device + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEMPSSetPayloadLength(struct net_device *prNetDev, + uint32_t u4TestNum, uint32_t *pu4Length, uint32_t u4Band) +{ + uint32_t u4BufLen = 0, i; + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATEMPSSetPayloadLength\n"); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + for (i = 0 ; i < u4TestNum ; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_PAYLOAD_LEN | + (i << 16); + rRfATInfo.u4FuncData = pu4Length[i]; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for MPS Setting. (Set Packet Count) + * + * \param[in] prNetDev Pointer to the Net Device + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEMPSSetPacketCount(struct net_device *prNetDev, + uint32_t u4TestNum, uint32_t *pu4PktCnt, uint32_t u4Band) +{ + uint32_t u4BufLen = 0, i; + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATEMPSSetPacketCount\n"); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + for (i = 0 ; i < u4TestNum ; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_PKT_CNT | + (i << 16); + rRfATInfo.u4FuncData = pu4PktCnt[i]; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for MPS Setting. (Set Power Gain) + * + * \param[in] prNetDev Pointer to the Net Device + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEMPSSetPowerGain(struct net_device *prNetDev, + uint32_t u4TestNum, uint32_t *pu4PwrGain, uint32_t u4Band) +{ + uint32_t u4BufLen = 0, i; + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATEMPSSetPowerGain\n"); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + for (i = 0 ; i < u4TestNum ; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_PWR_GAIN | + (i << 16); + rRfATInfo.u4FuncData = pu4PwrGain[i]; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for MPS Setting. (Set NSS) + * + * \param[in] prNetDev Pointer to the Net Device + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEMPSSetNss(struct net_device *prNetDev, + uint32_t u4TestNum, uint32_t *pu4Nss, uint32_t u4Band) +{ + uint32_t u4BufLen = 0, i; + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATEMPSSetNss\n"); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + for (i = 0 ; i < u4TestNum ; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_NSS | + (i << 16); + rRfATInfo.u4FuncData = pu4Nss[i]; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for MPS Setting. (Set NSS) + * + * \param[in] prNetDev Pointer to the Net Device + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEMPSSetPerpacketBW(struct net_device *prNetDev, + uint32_t u4TestNum, uint32_t *pu4PerPktBW, uint32_t u4Band) +{ + uint32_t u4BufLen = 0, i; + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATEMPSSetPerpacketBW\n"); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + for (i = 0 ; i < u4TestNum ; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_PACKAGE_BW | + (i << 16); + rRfATInfo.u4FuncData = pu4PerPktBW[i]; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Start RDD. + * + * \param[in] prNetDev Pointer to the Net Device + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATERDDStart(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4BufLen = 0; + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_RDD; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Stop RDD. + * + * \param[in] prNetDev Pointer to the Net Device + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATERDDStop(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4BufLen = 0; + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_RDD_OFF; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; + +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Write Efuse. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u2Offset Efuse offset + * \param[in] u2Content Efuse content + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEWriteEfuse(struct net_device *prNetDev, + uint16_t u2Offset, uint16_t u2Content) +{ + uint32_t u4BufLen = 0; + struct PARAM_CUSTOM_ACCESS_EFUSE rAccessEfuseInfoRead, + rAccessEfuseInfoWrite; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t i4Status = WLAN_STATUS_SUCCESS; + uint8_t u4Index = 0, u4Loop = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + if (!prGlueInfo) { + log_dbg(RFTEST, ERROR, "prGlueInfo is NULL\n"); + return -EFAULT; + } + kalMemSet(&rAccessEfuseInfoRead, 0, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + kalMemSet(&rAccessEfuseInfoWrite, 0, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + + if (prGlueInfo && + prGlueInfo->prAdapter && + prGlueInfo->prAdapter->chip_info && + !prGlueInfo->prAdapter->chip_info->is_support_efuse) { + log_dbg(RFTEST, WARN, "Efuse not support\n"); + return -EFAULT; + } + + /* Read */ + DBGLOG(INIT, INFO, "QA_AGENT HQA_WriteBulkEEPROM Read\n"); + kalMemSet(&rAccessEfuseInfoRead, 0, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + rAccessEfuseInfoRead.u4Address = (u2Offset / + EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + i4Status = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfoRead, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), + TRUE, TRUE, TRUE, &u4BufLen); + + + /* Write */ + kalMemSet(&rAccessEfuseInfoWrite, 0, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + u4Index = u2Offset % EFUSE_BLOCK_SIZE; + + if (u4Index >= EFUSE_BLOCK_SIZE - 1) { + DBGLOG(INIT, INFO, "u4Index [%d] overrun\n", u4Index); + return -EFAULT; + } + + prGlueInfo->prAdapter->aucEepromVaule[u4Index] = u2Content; + prGlueInfo->prAdapter->aucEepromVaule[u4Index + 1] = + u2Content >> 8 & 0xff; + + kalMemCopy(rAccessEfuseInfoWrite.aucData, + prGlueInfo->prAdapter->aucEepromVaule, 16); + + for (u4Loop = 0; u4Loop < (EFUSE_BLOCK_SIZE); u4Loop++) { + DBGLOG(INIT, INFO, + "QA_AGENT aucEepromVaule u4Loop=%d u4Value=%x\n", + u4Loop, prGlueInfo->prAdapter->aucEepromVaule[u4Loop]); + + DBGLOG(INIT, INFO, + "QA_AGENT rAccessEfuseInfoWrite.aucData u4Loop=%d u4Value=%x\n", + u4Loop, rAccessEfuseInfoWrite.aucData[u4Loop]); + } + + rAccessEfuseInfoWrite.u4Address = (u2Offset / + EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + + i4Status = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseWrite, + &rAccessEfuseInfoWrite, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), + FALSE, TRUE, TRUE, &u4BufLen); + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Tx Target Power. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u2TxTargetPower TxTarget Power + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetTxTargetPower(struct net_device *prNetDev, + uint8_t ucTxTargetPower) +{ + uint32_t u4BufLen = 0; + struct PARAM_CUSTOM_SET_TX_TARGET_POWER rSetTxTargetPwr; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t i4Status = WLAN_STATUS_SUCCESS; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + kalMemSet(&rSetTxTargetPwr, 0, + sizeof(struct PARAM_CUSTOM_SET_TX_TARGET_POWER)); + + + /* Set Target Power Base */ + DBGLOG(INIT, INFO, "QA_AGENT Set Tx Target Power= %x dbm\n", + ucTxTargetPower); + rSetTxTargetPwr.ucTxTargetPwr = ucTxTargetPower; + + i4Status = kalIoctl(prGlueInfo, + wlanoidQuerySetTxTargetPower, + &rSetTxTargetPwr, + sizeof(struct PARAM_CUSTOM_SET_TX_TARGET_POWER), + FALSE, FALSE, TRUE, &u4BufLen); + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +#if CFG_SUPPORT_ANT_SWAP +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Antenna swap + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4Ant The antenna to choose (0 for main, 1 for aux) + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetAntSwap(struct net_device *prNetDev, + uint32_t u4Ant) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t u4BufLen = 0; + int32_t i4Status = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + if (!prGlueInfo) { + DBGLOG(RFTEST, ERROR, "prGlueInfo is NULL\n"); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + DBGLOG(RFTEST, INFO, + "QA_AGENT MT_ATESetAntSwap u4Ant : %d\n", u4Ant); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ANT_SWP; + rRfATInfo.u4FuncData = (uint32_t) u4Ant; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; + +} +#endif /* CFG_SUPPORT_ANT_SWAP */ + +#if (CFG_SUPPORT_DFS_MASTER == 1) +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Rdd Report. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] ucDbdcIdx Dbdc Index + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetRddReport(struct net_device *prNetDev, + uint8_t ucDbdcIdx) +{ + uint32_t u4BufLen = 0; + struct PARAM_CUSTOM_SET_RDD_REPORT rSetRddReport; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t i4Status = WLAN_STATUS_SUCCESS; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + kalMemSet(&rSetRddReport, 0, + sizeof(struct PARAM_CUSTOM_SET_RDD_REPORT)); + + /* Set Rdd Report */ + DBGLOG(INIT, INFO, "QA_AGENT Set RDD Report - Band: %d\n", + ucDbdcIdx); + rSetRddReport.ucDbdcIdx = ucDbdcIdx; + + i4Status = kalIoctl(prGlueInfo, + wlanoidQuerySetRddReport, + &rSetRddReport, + sizeof(struct PARAM_CUSTOM_SET_RDD_REPORT), + FALSE, FALSE, TRUE, &u4BufLen); + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Radar Detect Mode. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] ucRadarDetectMode Radar Detect Mode + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetRadarDetectMode(struct net_device + *prNetDev, uint8_t ucRadarDetectMode) +{ + uint32_t u4BufLen = 0; + struct PARAM_CUSTOM_SET_RADAR_DETECT_MODE + rSetRadarDetectMode; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t i4Status = WLAN_STATUS_SUCCESS; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + kalMemSet(&rSetRadarDetectMode, 0, + sizeof(struct PARAM_CUSTOM_SET_RADAR_DETECT_MODE)); + + /* Set Rdd Report */ + DBGLOG(INIT, INFO, "QA_AGENT Set Radar Detect Mode: %d\n", + ucRadarDetectMode); + rSetRadarDetectMode.ucRadarDetectMode = ucRadarDetectMode; + + i4Status = kalIoctl(prGlueInfo, + wlanoidQuerySetRadarDetectMode, + &rSetRadarDetectMode, + sizeof(struct PARAM_CUSTOM_SET_RADAR_DETECT_MODE), + FALSE, FALSE, TRUE, &u4BufLen); + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +#endif + +#if CFG_SUPPORT_TX_BF +int32_t TxBfProfileTag_InValid(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + uint8_t ucInValid) +{ + int32_t i4Status = 0; + + prPfmuTag1->rField.ucInvalidProf = ucInValid; + + return i4Status; +} + +int32_t TxBfProfileTag_PfmuIdx(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + uint8_t ucProfileIdx) +{ + int32_t i4Status = 0; + + prPfmuTag1->rField.ucProfileID = ucProfileIdx; + + return i4Status; +} + +int32_t TxBfProfileTag_TxBfType(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + uint8_t ucBFType) +{ + int32_t i4Status = 0; + + prPfmuTag1->rField.ucTxBf = ucBFType; + + return i4Status; +} + +int32_t TxBfProfileTag_DBW(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, uint8_t ucBW) +{ + int32_t i4Status = 0; + + prPfmuTag1->rField.ucDBW = ucBW; + + return i4Status; +} + +int32_t TxBfProfileTag_SuMu(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, uint8_t ucSuMu) +{ + int32_t i4Status = 0; + + prPfmuTag1->rField.ucSU_MU = ucSuMu; + + return i4Status; +} + +int32_t TxBfProfileTag_Mem(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + uint8_t *aucMemAddrColIdx, uint8_t *aucMemAddrRowIdx) +{ + int32_t i4Status = 0; + + prPfmuTag1->rField.ucMemAddr1ColIdx = aucMemAddrColIdx[0]; + prPfmuTag1->rField.ucMemAddr1RowIdx = aucMemAddrRowIdx[0]; + prPfmuTag1->rField.ucMemAddr2ColIdx = aucMemAddrColIdx[1]; + prPfmuTag1->rField.ucMemAddr2RowIdx = aucMemAddrRowIdx[1] & + 0x1F; + prPfmuTag1->rField.ucMemAddr2RowIdxMsb = aucMemAddrRowIdx[1] + >> 5; + prPfmuTag1->rField.ucMemAddr3ColIdx = aucMemAddrColIdx[2]; + prPfmuTag1->rField.ucMemAddr3RowIdx = aucMemAddrRowIdx[2]; + prPfmuTag1->rField.ucMemAddr4ColIdx = aucMemAddrColIdx[3]; + prPfmuTag1->rField.ucMemAddr4RowIdx = aucMemAddrRowIdx[3]; + + return i4Status; +} + +int32_t TxBfProfileTag_Matrix(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + uint8_t ucNrow, + uint8_t ucNcol, uint8_t ucNgroup, uint8_t ucLM, + uint8_t ucCodeBook, uint8_t ucHtcExist) +{ + int32_t i4Status = 0; + + prPfmuTag1->rField.ucNrow = ucNrow; + prPfmuTag1->rField.ucNcol = ucNcol; + prPfmuTag1->rField.ucNgroup = ucNgroup; + prPfmuTag1->rField.ucLM = ucLM; + prPfmuTag1->rField.ucCodeBook = ucCodeBook; + prPfmuTag1->rField.ucHtcExist = ucHtcExist; + + return i4Status; +} + +int32_t TxBfProfileTag_SNR(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + uint8_t ucSNR_STS0, uint8_t ucSNR_STS1, + uint8_t ucSNR_STS2, uint8_t ucSNR_STS3) +{ + int32_t i4Status = 0; + + prPfmuTag1->rField.ucSNR_STS0 = ucSNR_STS0; + prPfmuTag1->rField.ucSNR_STS1 = ucSNR_STS1; + prPfmuTag1->rField.ucSNR_STS2 = ucSNR_STS2; + prPfmuTag1->rField.ucSNR_STS3 = ucSNR_STS3; + + return i4Status; +} + +int32_t TxBfProfileTag_SmtAnt(struct net_device *prNetDev, + union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t ucSmartAnt) +{ + int32_t i4Status = 0; + + prPfmuTag2->rField.u2SmartAnt = ucSmartAnt; + + return i4Status; +} + +int32_t TxBfProfileTag_SeIdx(struct net_device *prNetDev, + union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t ucSeIdx) +{ + int32_t i4Status = 0; + + prPfmuTag2->rField.ucSEIdx = ucSeIdx; + + return i4Status; +} + +int32_t TxBfProfileTag_RmsdThd(struct net_device *prNetDev, + union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t ucRmsdThrd) +{ + int32_t i4Status = 0; + + prPfmuTag2->rField.ucRMSDThd = ucRmsdThrd; + + return i4Status; +} + +int32_t TxBfProfileTag_McsThd(struct net_device *prNetDev, + union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t *pMCSThLSS, uint8_t *pMCSThSSS) +{ + int32_t i4Status = 0; + + prPfmuTag2->rField.ucMCSThL1SS = pMCSThLSS[0]; + prPfmuTag2->rField.ucMCSThS1SS = pMCSThSSS[0]; + prPfmuTag2->rField.ucMCSThL2SS = pMCSThLSS[1]; + prPfmuTag2->rField.ucMCSThS2SS = pMCSThSSS[1]; + prPfmuTag2->rField.ucMCSThL3SS = pMCSThLSS[2]; + prPfmuTag2->rField.ucMCSThS3SS = pMCSThSSS[2]; + + return i4Status; +} + +int32_t TxBfProfileTag_TimeOut(struct net_device *prNetDev, + union PFMU_PROFILE_TAG2 *prPfmuTag2, uint8_t ucTimeOut) +{ + int32_t i4Status = 0; + + prPfmuTag2->rField.uciBfTimeOut = ucTimeOut; + + return i4Status; +} + +int32_t TxBfProfileTag_DesiredBW(struct net_device + *prNetDev, union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t ucDesiredBW) +{ + int32_t i4Status = 0; + + prPfmuTag2->rField.uciBfDBW = ucDesiredBW; + + return i4Status; +} + +int32_t TxBfProfileTag_DesiredNc(struct net_device + *prNetDev, union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t ucDesiredNc) +{ + int32_t i4Status = 0; + + prPfmuTag2->rField.uciBfNcol = ucDesiredNc; + + return i4Status; +} + +int32_t TxBfProfileTag_DesiredNr(struct net_device + *prNetDev, union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t ucDesiredNr) +{ + int32_t i4Status = 0; + + prPfmuTag2->rField.uciBfNrow = ucDesiredNr; + + return i4Status; +} + +int32_t TxBfProfileTagWrite(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t profileIdx) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : au4RawData[0] = 0x%08x\n", + prPfmuTag1->au4RawData[0]); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : au4RawData[1] = 0x%08x\n", + prPfmuTag1->au4RawData[1]); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : au4RawData[2] = 0x%08x\n", + prPfmuTag1->au4RawData[2]); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : au4RawData[3] = 0x%08x\n", + prPfmuTag1->au4RawData[3]); + + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : au4RawData[0] = 0x%08x\n", + prPfmuTag2->au4RawData[0]); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : au4RawData[1] = 0x%08x\n", + prPfmuTag2->au4RawData[1]); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : au4RawData[2] = 0x%08x\n", + prPfmuTag2->au4RawData[2]); + + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucProfileID= %d\n", + prPfmuTag1->rField.ucProfileID); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucTxBf= %d\n", + prPfmuTag1->rField.ucTxBf); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucDBW= %d\n", + prPfmuTag1->rField.ucDBW); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucSU_MU= %d\n", + prPfmuTag1->rField.ucSU_MU); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucInvalidProf= %d\n", + prPfmuTag1->rField.ucInvalidProf); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucRMSD= %d\n", + prPfmuTag1->rField.ucRMSD); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr1ColIdx= %d\n", + prPfmuTag1->rField.ucMemAddr1ColIdx); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr1RowIdx= %d\n", + prPfmuTag1->rField.ucMemAddr1RowIdx); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr2ColIdx= %d\n", + prPfmuTag1->rField.ucMemAddr2ColIdx); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr2RowIdx= %d\n", + prPfmuTag1->rField.ucMemAddr2RowIdx); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr2RowIdxMsb= %d\n", + prPfmuTag1->rField.ucMemAddr2RowIdxMsb); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr3ColIdx= %d\n", + prPfmuTag1->rField.ucMemAddr3ColIdx); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr3RowIdx= %d\n", + prPfmuTag1->rField.ucMemAddr3RowIdx); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr4ColIdx= %d\n", + prPfmuTag1->rField.ucMemAddr4ColIdx); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr4RowIdx= %d\n", + prPfmuTag1->rField.ucMemAddr4RowIdx); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucReserved= %d\n", + prPfmuTag1->rField.ucReserved); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucNrow= %d\n", + prPfmuTag1->rField.ucNrow); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucNcol= %d\n", + prPfmuTag1->rField.ucNcol); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucNgroup= %d\n", + prPfmuTag1->rField.ucNgroup); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucLM= %d\n", + prPfmuTag1->rField.ucLM); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucCodeBook= %d\n", + prPfmuTag1->rField.ucCodeBook); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucHtcExist= %d\n", + prPfmuTag1->rField.ucHtcExist); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucReserved1= %d\n", + prPfmuTag1->rField.ucReserved1); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucSNR_STS0= %d\n", + prPfmuTag1->rField.ucSNR_STS0); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucSNR_STS1= %d\n", + prPfmuTag1->rField.ucSNR_STS1); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucSNR_STS2= %d\n", + prPfmuTag1->rField.ucSNR_STS2); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucSNR_STS3= %d\n", + prPfmuTag1->rField.ucSNR_STS3); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucIBfLnaIdx= %d\n", + prPfmuTag1->rField.ucIBfLnaIdx); + + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.u2SmartAnt = %d\n", + prPfmuTag2->rField.u2SmartAnt); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucReserved0 = %d\n", + prPfmuTag2->rField.ucReserved0); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucSEIdx = %d\n", + prPfmuTag2->rField.ucSEIdx); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucRMSDThd = %d\n", + prPfmuTag2->rField.ucRMSDThd); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucReserved1 = %d\n", + prPfmuTag2->rField.ucReserved1); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucMCSThL1SS = %d\n", + prPfmuTag2->rField.ucMCSThL1SS); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucMCSThS1SS = %d\n", + prPfmuTag2->rField.ucMCSThS1SS); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucMCSThL2SS = %d\n", + prPfmuTag2->rField.ucMCSThL2SS); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucMCSThS2SS = %d\n", + prPfmuTag2->rField.ucMCSThS2SS); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucMCSThL3SS = %d\n", + prPfmuTag2->rField.ucMCSThL3SS); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucMCSThS3SS = %d\n", + prPfmuTag2->rField.ucMCSThS3SS); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.uciBfTimeOut = %d\n", + prPfmuTag2->rField.uciBfTimeOut); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucReserved2 = %d\n", + prPfmuTag2->rField.ucReserved2); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucReserved3 = %d\n", + prPfmuTag2->rField.ucReserved3); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucReserved4 = %d\n", + prPfmuTag2->rField.ucReserved4); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.uciBfDBW = %d\n", + prPfmuTag2->rField.uciBfDBW); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.uciBfNcol = %d\n", + prPfmuTag2->rField.uciBfNcol); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.uciBfNrow = %d\n", + prPfmuTag2->rField.uciBfNrow); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.u2Reserved5 = %d\n", + prPfmuTag2->rField.u2Reserved5); + + rTxBfActionInfo.rProfileTagWrite.ucTxBfCategory = + BF_PFMU_TAG_WRITE; + rTxBfActionInfo.rProfileTagWrite.ucPfmuId = profileIdx; + memcpy(&rTxBfActionInfo.rProfileTagWrite.ucBuffer, + prPfmuTag1, sizeof(union PFMU_PROFILE_TAG1)); + memcpy(&rTxBfActionInfo.rProfileTagWrite.ucBuffer[16], + prPfmuTag2, sizeof(union PFMU_PROFILE_TAG2)); + + i4Status = kalIoctl(prGlueInfo, wlanoidTxBfAction, &rTxBfActionInfo, + sizeof(rTxBfActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +int32_t TxBfProfileTagRead(struct net_device *prNetDev, + uint8_t profileIdx, uint8_t fgBFer) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, + "TxBfProfileTagRead : profileIdx = 0x%08x\n", profileIdx); + DBGLOG(RFTEST, ERROR, + "TxBfProfileTagRead : fgBFer = 0x%08x\n", fgBFer); + + rTxBfActionInfo.rProfileTagRead.ucTxBfCategory = + BF_PFMU_TAG_READ; + rTxBfActionInfo.rProfileTagRead.ucProfileIdx = profileIdx; + rTxBfActionInfo.rProfileTagRead.fgBfer = fgBFer; + + i4Status = kalIoctl(prGlueInfo, wlanoidTxBfAction, &rTxBfActionInfo, + sizeof(rTxBfActionInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + return i4Status; +} + +int32_t StaRecCmmUpdate(struct net_device *prNetDev, + uint8_t ucWlanId, uint8_t ucBssId, uint8_t u4Aid, + uint8_t aucMacAddr[MAC_ADDR_LEN] + ) +{ + struct STAREC_COMMON rStaRecCmm; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + int32_t i4Status = 0; + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rStaRecCmm, sizeof(struct STAREC_COMMON)); + /* Tag assignment */ + rStaRecCmm.u2Tag = STA_REC_BASIC; + rStaRecCmm.u2Length = sizeof(struct STAREC_COMMON); + + /* content */ + kalMemCopy(rStaRecCmm.aucPeerMacAddr, aucMacAddr, + MAC_ADDR_LEN); + rStaRecCmm.ucConnectionState = TRUE; + rStaRecCmm.u2AID = u4Aid; + rStaRecCmm.u2Reserve1 = ucWlanId; + + DBGLOG(RFTEST, ERROR, "ucWlanId = 0x%08x\n", ucWlanId); + + i4Status = kalIoctl(prGlueInfo, wlanoidStaRecUpdate, &rStaRecCmm, + sizeof(struct STAREC_COMMON), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +int32_t StaRecBfUpdate(struct net_device *prNetDev, + struct STA_REC_BF_UPD_ARGUMENT rStaRecBfUpdArg, + uint8_t aucMemRow[4], uint8_t aucMemCol[4] + ) +{ + struct CMD_STAREC_BF rStaRecBF; + /* PARAM_CUSTOM_STA_REC_UPD_STRUCT_T rStaRecUpdateInfo = {0}; */ + /* P_STA_RECORD_T prStaRec; */ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + int32_t i4Status = 0; + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rStaRecBF, sizeof(struct CMD_STAREC_BF)); + /* Tag assignment */ + rStaRecBF.u2Tag = STA_REC_BF; + rStaRecBF.u2Length = sizeof(struct CMD_STAREC_BF); + rStaRecBF.ucReserved[0] = rStaRecBfUpdArg.u4BssId; + rStaRecBF.ucReserved[1] = rStaRecBfUpdArg.u4WlanId; + /* content */ + rStaRecBF.rTxBfPfmuInfo.u2PfmuId = rStaRecBfUpdArg.u4PfmuId; + rStaRecBF.rTxBfPfmuInfo.ucTotMemRequire = + rStaRecBfUpdArg.u4TotalMemReq; + rStaRecBF.rTxBfPfmuInfo.ucMemRequire20M = + rStaRecBfUpdArg.u4MemReq20M; + rStaRecBF.rTxBfPfmuInfo.ucMemRow0 = aucMemRow[0]; + rStaRecBF.rTxBfPfmuInfo.ucMemCol0 = aucMemCol[0]; + rStaRecBF.rTxBfPfmuInfo.ucMemRow1 = aucMemRow[1]; + rStaRecBF.rTxBfPfmuInfo.ucMemCol1 = aucMemCol[1]; + rStaRecBF.rTxBfPfmuInfo.ucMemRow2 = aucMemRow[2]; + rStaRecBF.rTxBfPfmuInfo.ucMemCol2 = aucMemCol[2]; + rStaRecBF.rTxBfPfmuInfo.ucMemRow3 = aucMemRow[3]; + rStaRecBF.rTxBfPfmuInfo.ucMemCol3 = aucMemCol[3]; + /* 0 : SU, 1 : MU */ + rStaRecBF.rTxBfPfmuInfo.fgSU_MU = rStaRecBfUpdArg.u4SuMu; + /* 0: iBF, 1: eBF */ + rStaRecBF.rTxBfPfmuInfo.fgETxBfCap = + rStaRecBfUpdArg.u4eTxBfCap; + /* 0: legacy, 1: OFDM, 2: HT, 4: VHT */ + rStaRecBF.rTxBfPfmuInfo.ucSoundingPhy = 1; + rStaRecBF.rTxBfPfmuInfo.ucNdpaRate = + rStaRecBfUpdArg.u4NdpaRate; + rStaRecBF.rTxBfPfmuInfo.ucNdpRate = + rStaRecBfUpdArg.u4NdpRate; + rStaRecBF.rTxBfPfmuInfo.ucReptPollRate = + rStaRecBfUpdArg.u4ReptPollRate; + /* 0: legacy, 1: OFDM, 2: HT, 4: VHT */ + rStaRecBF.rTxBfPfmuInfo.ucTxMode = rStaRecBfUpdArg.u4TxMode; + rStaRecBF.rTxBfPfmuInfo.ucNc = rStaRecBfUpdArg.u4Nc; + rStaRecBF.rTxBfPfmuInfo.ucNr = rStaRecBfUpdArg.u4Nr; + /* 0 : 20M, 1 : 40M, 2 : 80M, 3 : 80 + 80M */ + rStaRecBF.rTxBfPfmuInfo.ucCBW = rStaRecBfUpdArg.u4Bw; + rStaRecBF.rTxBfPfmuInfo.ucSEIdx = rStaRecBfUpdArg.u4SpeIdx; + /* Default setting */ + rStaRecBF.rTxBfPfmuInfo.u2SmartAnt = 0; + rStaRecBF.rTxBfPfmuInfo.uciBfTimeOut = 0; + rStaRecBF.rTxBfPfmuInfo.uciBfDBW = 0; + rStaRecBF.rTxBfPfmuInfo.uciBfNcol = 0; + rStaRecBF.rTxBfPfmuInfo.uciBfNrow = 0; + + i4Status = kalIoctl(prGlueInfo, + wlanoidStaRecBFUpdate, &rStaRecBF, + sizeof(struct CMD_STAREC_BF), FALSE, FALSE, TRUE, + &u4BufLen); + + return i4Status; +} + +int32_t DevInfoUpdate(struct net_device *prNetDev, + uint8_t ucOwnMacIdx, uint8_t fgBand, + uint8_t aucMacAddr[MAC_ADDR_LEN]) +{ + struct CMD_DEVINFO_ACTIVE rDevInfo; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + int32_t i4Status = 0; + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rDevInfo, sizeof(struct CMD_DEVINFO_ACTIVE)); + /* Tag assignment */ + rDevInfo.u2Tag = DEV_INFO_ACTIVE; + rDevInfo.u2Length = sizeof(struct CMD_DEVINFO_ACTIVE); + /* content */ + kalMemCopy(rDevInfo.aucOwnMacAddr, aucMacAddr, + MAC_ADDR_LEN); + rDevInfo.ucActive = TRUE; + rDevInfo.ucBandNum = 0; + rDevInfo.aucReserve[0] = ucOwnMacIdx; + + i4Status = kalIoctl(prGlueInfo, wlanoidDevInfoActive, &rDevInfo, + sizeof(struct CMD_DEVINFO_ACTIVE), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +int32_t BssInfoUpdate(struct net_device *prNetDev, + uint8_t ucOwnMacIdx, uint8_t ucBssIdx, + uint8_t ucBssId[MAC_ADDR_LEN]) +{ + struct BSSINFO_BASIC rBssInfo; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + int32_t i4Status = 0; + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rBssInfo, sizeof(struct BSSINFO_BASIC)); + /* Tag assignment */ + rBssInfo.u2Tag = BSS_INFO_BASIC; + rBssInfo.u2Length = sizeof(struct BSSINFO_BASIC); + /* content */ + kalMemCopy(rBssInfo.aucBSSID, ucBssId, MAC_ADDR_LEN); + rBssInfo.ucBcMcWlanidx = ucBssIdx; + rBssInfo.ucActive = TRUE; + rBssInfo.u4NetworkType = NETWORK_TYPE_AIS; + rBssInfo.u2BcnInterval = 100; + rBssInfo.ucDtimPeriod = 1; + + i4Status = kalIoctl(prGlueInfo, + wlanoidBssInfoBasic, &rBssInfo, + sizeof(struct BSSINFO_BASIC), FALSE, FALSE, TRUE, + &u4BufLen); + + return i4Status; +} + +int32_t TxBfProfileDataRead(struct net_device *prNetDev, + uint8_t profileIdx, uint8_t fgBFer, + uint8_t ucSubCarrIdxMsb, uint8_t ucSubCarrIdxLsb) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataRead : ucPfmuIdx = 0x%08x\n", profileIdx); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataRead : fgBFer = 0x%08x\n", fgBFer); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataRead : ucSubCarrIdxMsb = 0x%08x\n", + ucSubCarrIdxMsb); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataRead : ucSubCarrIdxLsb = 0x%08x\n", + ucSubCarrIdxLsb); + + rTxBfActionInfo.rProfileDataRead.ucTxBfCategory = + BF_PROFILE_READ; + rTxBfActionInfo.rProfileDataRead.ucPfmuIdx = profileIdx; + rTxBfActionInfo.rProfileDataRead.fgBFer = fgBFer; + rTxBfActionInfo.rProfileDataRead.ucSubCarrIdxMsb = + ucSubCarrIdxMsb; + rTxBfActionInfo.rProfileDataRead.ucSubCarrIdxLsb = + ucSubCarrIdxLsb; + + i4Status = kalIoctl(prGlueInfo, wlanoidTxBfAction, &rTxBfActionInfo, + sizeof(rTxBfActionInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + return i4Status; +} + +int32_t TxBfProfileDataWrite(struct net_device *prNetDev, + uint8_t profileIdx, + uint16_t u2SubCarrIdx, uint16_t au2Phi[6], + uint8_t aucPsi[6], uint8_t aucDSnr[4] + ) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : ucPfmuIdx = 0x%08x\n", profileIdx); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : u2SubCarrIdx = 0x%08x\n", + u2SubCarrIdx); + + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : au2Phi[0] = 0x%08x\n", au2Phi[0]); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : au2Phi[1] = 0x%08x\n", au2Phi[1]); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : au2Phi[2] = 0x%08x\n", au2Phi[2]); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : au2Phi[3] = 0x%08x\n", au2Phi[3]); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : au2Phi[4] = 0x%08x\n", au2Phi[4]); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : au2Phi[5] = 0x%08x\n", au2Phi[5]); + + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : aucPsi[0] = 0x%08x\n", aucPsi[0]); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : aucPsi[1] = 0x%08x\n", aucPsi[1]); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : aucPsi[2] = 0x%08x\n", aucPsi[2]); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : aucPsi[3] = 0x%08x\n", aucPsi[3]); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : aucPsi[4] = 0x%08x\n", aucPsi[4]); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : aucPsi[5] = 0x%08x\n", aucPsi[5]); + + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : aucDSnr[0] = 0x%x\n", aucDSnr[0]); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : aucDSnr[1] = 0x%x\n", aucDSnr[1]); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : aucDSnr[2] = 0x%x\n", aucDSnr[2]); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : aucDSnr[3] = 0x%x\n", aucDSnr[3]); + + rTxBfActionInfo.rProfileDataWrite.ucTxBfCategory = + BF_PROFILE_WRITE; + rTxBfActionInfo.rProfileDataWrite.ucPfmuIdx = profileIdx; + rTxBfActionInfo.rProfileDataWrite.u2SubCarrIdxLsb = + u2SubCarrIdx; + rTxBfActionInfo.rProfileDataWrite.u2SubCarrIdxMsb = + u2SubCarrIdx >> 8; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2Phi11 + = au2Phi[0]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2Phi21 + = au2Phi[1]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2Phi31 + = au2Phi[2]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2Phi22 + = au2Phi[3]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2Phi32 + = au2Phi[4]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2Phi33 + = au2Phi[5]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.ucPsi21 + = aucPsi[0]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.ucPsi31 + = aucPsi[1]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.ucPsi41 + = aucPsi[2]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.ucPsi32 + = aucPsi[3]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.ucPsi42 + = aucPsi[4]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.ucPsi43 + = aucPsi[5]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2dSNR00 + = aucDSnr[0]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2dSNR01 + = aucDSnr[1]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2dSNR02 + = aucDSnr[2]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2dSNR03 + = aucDSnr[3]; + + i4Status = kalIoctl(prGlueInfo, wlanoidTxBfAction, &rTxBfActionInfo, + sizeof(rTxBfActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +int32_t TxBfProfilePnRead(struct net_device *prNetDev, + uint8_t profileIdx) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnRead : ucPfmuIdx = 0x%08x\n", profileIdx); + + rTxBfActionInfo.rProfilePnRead.ucTxBfCategory = BF_PN_READ; + rTxBfActionInfo.rProfilePnRead.ucPfmuIdx = profileIdx; + + i4Status = kalIoctl(prGlueInfo, wlanoidTxBfAction, &rTxBfActionInfo, + sizeof(rTxBfActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +int32_t TxBfProfilePnWrite(struct net_device *prNetDev, + uint8_t profileIdx, uint16_t u2bw, uint16_t au2XSTS[12]) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : ucPfmuIdx = 0x%08x\n", profileIdx); + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : u2bw = 0x%08x\n", u2bw); + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : au2XSTS[0] = 0x%08x\n", au2XSTS[0]); + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : au2XSTS[1] = 0x%08x\n", au2XSTS[1]); + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : au2XSTS[2] = 0x%08x\n", au2XSTS[2]); + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : au2XSTS[3] = 0x%08x\n", au2XSTS[3]); + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : au2XSTS[4] = 0x%08x\n", au2XSTS[4]); + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : au2XSTS[5] = 0x%08x\n", au2XSTS[5]); + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : au2XSTS[6] = 0x%08x\n", au2XSTS[6]); + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : au2XSTS[7] = 0x%08x\n", au2XSTS[7]); + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : au2XSTS[8] = 0x%08x\n", au2XSTS[8]); + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : au2XSTS[9] = 0x%08x\n", au2XSTS[9]); + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : au2XSTS[10] = 0x%08x\n", au2XSTS[10]); + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : au2XSTS[11] = 0x%08x\n", au2XSTS[11]); + + rTxBfActionInfo.rProfilePnWrite.ucTxBfCategory = + BF_PN_WRITE; + rTxBfActionInfo.rProfilePnWrite.ucPfmuIdx = profileIdx; + rTxBfActionInfo.rProfilePnWrite.u2bw = u2bw; + memcpy(&rTxBfActionInfo.rProfilePnWrite.ucBuf[0], &au2XSTS[0], + sizeof(uint16_t) * 12); + + i4Status = kalIoctl(prGlueInfo, wlanoidTxBfAction, &rTxBfActionInfo, + sizeof(rTxBfActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +int32_t TxBfSounding(struct net_device *prNetDev, + uint8_t ucSuMu, /* 0/1/2/3 */ + uint8_t ucNumSta, /* 00~04 */ + uint8_t ucSndInterval, /* 00~FF */ + uint8_t ucWLan0, /* 00~7F */ + uint8_t ucWLan1, /* 00~7F */ + uint8_t ucWLan2, /* 00~7F */ + + uint8_t ucWLan3 /* 00~7F */ + ) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, "TxBfSounding : ucSuMu = 0x%08x\n", + ucSuMu); + DBGLOG(RFTEST, ERROR, "TxBfSounding : ucNumSta = 0x%08x\n", + ucNumSta); + DBGLOG(RFTEST, ERROR, + "TxBfSounding : ucSndInterval = 0x%08x\n", ucSndInterval); + DBGLOG(RFTEST, ERROR, "TxBfSounding : ucWLan0 = 0x%08x\n", + ucWLan0); + DBGLOG(RFTEST, ERROR, "TxBfSounding : ucWLan1 = 0x%08x\n", + ucWLan1); + DBGLOG(RFTEST, ERROR, "TxBfSounding : ucWLan2 = 0x%08x\n", + ucWLan2); + DBGLOG(RFTEST, ERROR, "TxBfSounding : ucWLan3 = 0x%08x\n", + ucWLan3); + + switch (ucSuMu) { + case MU_SOUNDING: + + case MU_PERIODIC_SOUNDING: + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding + .rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucCmdCategoryID = + BF_SOUNDING_ON; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding + .rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucSuMuSndMode = ucSuMu; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding + .rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucStaNum = ucNumSta; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding + .rExtCmdExtBfMuSndPeriodicTriggerCtrl.u4SoundingInterval = + ucSndInterval; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding + .rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucWlanId[0] = ucWLan0; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding + .rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucWlanId[1] = ucWLan1; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding + .rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucWlanId[2] = ucWLan2; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding + .rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucWlanId[3] = ucWLan3; + break; + + case SU_SOUNDING: + case SU_PERIODIC_SOUNDING: + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding + .rExtCmdExtBfSndPeriodicTriggerCtrl.ucCmdCategoryID = + BF_SOUNDING_ON; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding + .rExtCmdExtBfSndPeriodicTriggerCtrl.ucSuMuSndMode = ucSuMu; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding + .rExtCmdExtBfSndPeriodicTriggerCtrl.u4SoundingInterval = + ucSndInterval; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding + .rExtCmdExtBfSndPeriodicTriggerCtrl.ucWlanIdx = ucWLan0; + break; + default: + break; + } + + i4Status = kalIoctl(prGlueInfo, wlanoidTxBfAction, &rTxBfActionInfo, + sizeof(rTxBfActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +int32_t TxBfSoundingStop(struct net_device *prNetDev) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, "TxBfSoundingStop\n"); + + rTxBfActionInfo.rTxBfSoundingStop.ucTxBfCategory = + BF_SOUNDING_OFF; + rTxBfActionInfo.rTxBfSoundingStop.ucSndgStop = 1; + + i4Status = kalIoctl(prGlueInfo, wlanoidTxBfAction, &rTxBfActionInfo, + sizeof(rTxBfActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +int32_t TxBfTxApply(struct net_device *prNetDev, + uint8_t ucWlanId, uint8_t fgETxBf, uint8_t fgITxBf, + uint8_t fgMuTxBf) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, + "TxBfTxApply : ucWlanId = 0x%08x, fgETxBf = 0x%08x,fgITxBf = 0x%08x,fgMuTxBf = 0x%08x\n", + ucWlanId, fgETxBf, fgITxBf, fgMuTxBf); + + rTxBfActionInfo.rTxBfTxApply.ucTxBfCategory = + BF_DATA_PACKET_APPLY; + rTxBfActionInfo.rTxBfTxApply.ucWlanId = ucWlanId; + rTxBfActionInfo.rTxBfTxApply.fgETxBf = fgETxBf; + rTxBfActionInfo.rTxBfTxApply.fgITxBf = fgITxBf; + rTxBfActionInfo.rTxBfTxApply.fgMuTxBf = fgMuTxBf; + + i4Status = kalIoctl(prGlueInfo, wlanoidTxBfAction, &rTxBfActionInfo, + sizeof(rTxBfActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +int32_t TxBfPfmuMemAlloc(struct net_device *prNetDev, + uint8_t ucSuMuMode, uint8_t ucWlanIdx) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, + "TxBfPfmuMemAlloc : ucSuMuMode = 0x%08x, ucWlanIdx = 0x%08x\n", + ucSuMuMode, ucWlanIdx); + + rTxBfActionInfo.rTxBfPfmuMemAlloc.ucTxBfCategory = + BF_PFMU_MEM_ALLOCATE; + rTxBfActionInfo.rTxBfPfmuMemAlloc.ucSuMuMode = ucSuMuMode; + rTxBfActionInfo.rTxBfPfmuMemAlloc.ucWlanIdx = ucWlanIdx; + + i4Status = kalIoctl(prGlueInfo, wlanoidTxBfAction, &rTxBfActionInfo, + sizeof(rTxBfActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +int32_t TxBfPfmuMemRelease(struct net_device *prNetDev, + uint8_t ucWlanId) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, + "TxBfPfmuMemRelease : ucWlanId = 0x%08x\n", ucWlanId); + + rTxBfActionInfo.rTxBfPfmuMemRls.ucTxBfCategory = + BF_PFMU_MEM_RELEASE; + rTxBfActionInfo.rTxBfPfmuMemRls.ucWlanId = ucWlanId; + + i4Status = kalIoctl(prGlueInfo, wlanoidTxBfAction, &rTxBfActionInfo, + sizeof(rTxBfActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +int32_t TxBfBssInfoUpdate(struct net_device *prNetDev, + uint8_t ucOwnMacIdx, uint8_t ucBssIdx, + uint8_t ucBssId[MAC_ADDR_LEN]) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + /* UINT_32 u4BufLen = 0; */ + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + struct BSS_INFO *prBssInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, + "TxBfBssInfoUpdate : ucOwnMacIdx = 0x%08x\n", ucOwnMacIdx); + DBGLOG(RFTEST, ERROR, + "TxBfBssInfoUpdate : ucBssIdx = 0x%08x\n", ucBssIdx); + DBGLOG(RFTEST, ERROR, + "TxBfBssInfoUpdate : ucBssId[0] = 0x%08x\n", ucBssId[0]); + DBGLOG(RFTEST, ERROR, + "TxBfBssInfoUpdate : ucBssId[1] = 0x%08x\n", ucBssId[1]); + DBGLOG(RFTEST, ERROR, + "TxBfBssInfoUpdate : ucBssId[2] = 0x%08x\n", ucBssId[2]); + DBGLOG(RFTEST, ERROR, + "TxBfBssInfoUpdate : ucBssId[3] = 0x%08x\n", ucBssId[3]); + DBGLOG(RFTEST, ERROR, + "TxBfBssInfoUpdate : ucBssId[4] = 0x%08x\n", ucBssId[4]); + DBGLOG(RFTEST, ERROR, + "TxBfBssInfoUpdate : ucBssId[5] = 0x%08x\n", ucBssId[5]); + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + if (!prBssInfo) + return WLAN_STATUS_FAILURE; + prBssInfo->ucOwnMacIndex = ucOwnMacIdx; + memcpy(&prBssInfo->aucBSSID, &ucBssId[0], MAC_ADDR_LEN); + + nicUpdateBss(prAdapter, prBssInfo->ucBssIndex); + + return i4Status; +} + +/* iwpriv ra0 set assoc=[mac:hh:hh:hh:hh:hh:hh]-[wtbl:dd]- + * [ownmac:dd]-[type:xx]-[mode:mmm]-[bw:dd]-[nss:ss]-[maxrate:kkk_dd] + */ +int32_t TxBfManualAssoc(struct net_device *prNetDev, + uint8_t aucMac[MAC_ADDR_LEN], + uint8_t ucType, /* no use */ + uint8_t ucWtbl, + uint8_t ucOwnmac, + uint8_t ucMode, + uint8_t ucBw, + uint8_t ucNss, uint8_t ucPfmuId, uint8_t ucMarate, + uint8_t ucSpeIdx, uint8_t ucRca2, uint8_t ucRv) +{ + struct CMD_MANUAL_ASSOC_STRUCT rManualAssoc; + /* P_STA_RECORD_T prStaRec; */ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + int32_t i4Status = 0; + /* uint8_t ucNsts; + * uint32_t i; + */ + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rManualAssoc, + sizeof(struct CMD_MANUAL_ASSOC_STRUCT)); + /* Tag assignment */ + rManualAssoc.u2Tag = STA_REC_MAUNAL_ASSOC; + rManualAssoc.u2Length = sizeof(struct + CMD_MANUAL_ASSOC_STRUCT); + /* content */ + kalMemCopy(rManualAssoc.aucMac, aucMac, MAC_ADDR_LEN); + rManualAssoc.ucType = ucType; + rManualAssoc.ucWtbl = ucWtbl; + rManualAssoc.ucOwnmac = ucOwnmac; + rManualAssoc.ucMode = ucMode; + rManualAssoc.ucBw = ucBw; + rManualAssoc.ucNss = ucNss; + rManualAssoc.ucPfmuId = ucPfmuId; + rManualAssoc.ucMarate = ucMarate; + rManualAssoc.ucSpeIdx = ucSpeIdx; + rManualAssoc.ucaid = ucRca2; + +#if 0 + switch (ucMode) { + case 0: /* abggnanac */ + prStaRec->ucDesiredPhyTypeSet = + aucPhyCfg2PhyTypeSet[PHY_TYPE_SET_802_11ABGNAC]; + break; + case 1: /* bggnan */ + prStaRec->ucDesiredPhyTypeSet = + aucPhyCfg2PhyTypeSet[PHY_TYPE_SET_802_11ABGN]; + break; + case 2: /* aanac */ + prStaRec->ucDesiredPhyTypeSet = + aucPhyCfg2PhyTypeSet[PHY_TYPE_SET_802_11ANAC]; + break; + default: + prStaRec->ucDesiredPhyTypeSet = + aucPhyCfg2PhyTypeSet[PHY_TYPE_SET_802_11ABGNAC]; + break; + } + + prStaRec->rTxBfPfmuStaInfo.u2PfmuId = ucPfmuId; + + memcpy(prStaRec->aucMacAddr, aucMac, MAC_ADDR_LEN); + + i4Status = kalIoctl(prGlueInfo, wlanoidStaRecUpdate, &rStaRecUpdateInfo, + sizeof(struct PARAM_CUSTOM_STA_REC_UPD_STRUCT), + FALSE, FALSE, TRUE, &u4BufLen); +#endif + + i4Status = kalIoctl(prGlueInfo, wlanoidManualAssoc, &rManualAssoc, + sizeof(struct CMD_MANUAL_ASSOC_STRUCT), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +#if CFG_SUPPORT_TX_BF_FPGA +int32_t TxBfPseudoTagUpdate(struct net_device *prNetDev, + uint8_t ucLm, uint8_t ucNr, + uint8_t ucNc, uint8_t ucBw, uint8_t ucCodeBook, + uint8_t ucGroup) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4BufLen = 0; + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, ERROR, + "TxBfPseudoTagUpdate : ucLm = 0x%08x, ucNr = 0x%08x, ucNc = 0x%08x, ucBw = 0x%08x, ucCodeBook = 0x%08x, ucGroup = 0x%08x\n", + ucLm, ucNr, ucNc, ucBw, ucCodeBook, ucGroup); + + rTxBfActionInfo.rTxBfProfileSwTagWrite.ucTxBfCategory = + BF_PFMU_SW_TAG_WRITE; + rTxBfActionInfo.rTxBfProfileSwTagWrite.ucLm = ucLm; + rTxBfActionInfo.rTxBfProfileSwTagWrite.ucNr = ucNr; + rTxBfActionInfo.rTxBfProfileSwTagWrite.ucNc = ucNc; + rTxBfActionInfo.rTxBfProfileSwTagWrite.ucBw = ucBw; + rTxBfActionInfo.rTxBfProfileSwTagWrite.ucCodebook = + ucCodeBook; + rTxBfActionInfo.rTxBfProfileSwTagWrite.ucgroup = ucGroup; + + i4Status = kalIoctl(prGlueInfo, wlanoidTxBfAction, &rTxBfActionInfo, + sizeof(rTxBfActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} +#endif + +#endif +#endif /*CFG_SUPPORT_QA_TOOL */ +#if (CONFIG_WLAN_SERVICE == 1) +uint32_t ServiceRfTestInit(void *winfos) +{ + + uint32_t u4SetInfoLen = 0; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint8_t ucBssIndex = 0; + + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct test_wlan_info *prTestWinfo; + + + ASSERT(winfos); + prTestWinfo = (struct test_wlan_info *)winfos; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prTestWinfo->net_dev)); + ASSERT(prGlueInfo); + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + /*1. do abort Scan, reset AIS FSM to IDLE*/ + + ucBssIndex = wlanGetBssIdx(prTestWinfo->net_dev); + + if (!IS_BSS_INDEX_VALID(ucBssIndex)) { + DBGLOG(REQ, WARN, "Test Abort SCAN invalid BssIndex\n"); + return WLAN_STATUS_FAILURE; + } + + DBGLOG(REQ, WARN, "Test Abort SCAN ucBssIndex = %d\n", ucBssIndex); + + rStatus = kalIoctlByBssIdx(prGlueInfo, + wlanoidAbortScan, + NULL, 1, FALSE, FALSE, TRUE, &u4SetInfoLen, + ucBssIndex); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, ERROR, "wlanoidAbortScan fail 0x%x\n", rStatus); + + return rStatus; + +} +uint32_t ServiceIcapInit(struct ADAPTER *prAdapter) +{ + struct mt66xx_chip_info *prChipInfo = NULL; + struct ATE_OPS_T *prAteOps = NULL; + struct ICAP_INFO_T *prIcapInfo = NULL; + uint32_t u4IQArrayLen = 0; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + ASSERT(prChipInfo); + prAteOps = prChipInfo->prAteOps; + ASSERT(prAteOps); + prIcapInfo = &prAdapter->rIcapInfo; + ASSERT(prIcapInfo); + + u4IQArrayLen = + MAX_ICAP_IQ_DATA_CNT * sizeof(struct _RBIST_IQ_DATA_T); + + /*init IQ data array*/ + if (!prIcapInfo->prIQArray) { + prIcapInfo->prIQArray = + kalMemAlloc(u4IQArrayLen, VIR_MEM_TYPE); + if (!prIcapInfo->prIQArray) { + DBGLOG(RFTEST, ERROR, + "Not enough memory for IQ_Array\n"); + return WLAN_STATUS_NOT_ACCEPTED; + } + } + prIcapInfo->u4IQArrayIndex = 0; + prIcapInfo->u4ICapEventCnt = 0; + + kalMemZero(prIcapInfo->au4ICapDumpIndex, + sizeof(prIcapInfo->au4ICapDumpIndex)); + kalMemZero(prIcapInfo->prIQArray, u4IQArrayLen); + + + if (prIcapInfo->eIcapState == ICAP_STATE_INIT) { + + if (prAteOps->icapRiseVcoreClockRate) + prAteOps->icapRiseVcoreClockRate(); + + u4Status = WLAN_STATUS_SUCCESS; + } else { + DBGLOG(RFTEST, ERROR, "icap start ignore state in %d\n", + prIcapInfo->eIcapState); + u4Status = WLAN_STATUS_NOT_ACCEPTED; + } + + DBGLOG(RFTEST, STATE, "%s done\n", __func__); + + return u4Status; +} +uint32_t ServiceIcapDeInit(struct ADAPTER *prAdapter) +{ + struct mt66xx_chip_info *prChipInfo = NULL; + struct ATE_OPS_T *prAteOps = NULL; + struct ICAP_INFO_T *prIcapInfo = NULL; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + ASSERT(prChipInfo); + prAteOps = prChipInfo->prAteOps; + ASSERT(prAteOps); + prIcapInfo = &prAdapter->rIcapInfo; + ASSERT(prIcapInfo); + + if (prAteOps->icapDownVcoreClockRate) + prAteOps->icapDownVcoreClockRate(); + + if (prIcapInfo->prIQArray != NULL) + kalMemFree(prIcapInfo->prIQArray, + VIR_MEM_TYPE, + 0); + + prIcapInfo->u4IQArrayIndex = 0; + prIcapInfo->u4ICapEventCnt = 0; + prIcapInfo->prIQArray = NULL; + + return u4Status; +} +uint32_t ServiceWlanOid(void *winfos, + uint32_t oidType, + void *param, + uint32_t paramLen, + uint32_t *u4BufLen, + void *rsp_data) +{ + int32_t i4Status = 0; + uint32_t u4BufLen2; + uint32_t *resp; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct RECAL_INFO_T *prReCalInfo = NULL; + boolean fgRead, fgWaitResp, fgCmd; + PFN_OID_HANDLER_FUNC pfnOidHandler = NULL; + struct test_wlan_info *prTestWinfo; + struct hqa_m_rx_stat *prStatsData = NULL; +#if CFG_SUPPORT_ANT_SWAP + struct mt66xx_chip_info *prChipInfo = NULL; +#endif + struct ICAP_INFO_T *prIcapInfo = NULL; + struct test_capability *capability = NULL; + + ASSERT(winfos); + + /* Avoid assert caused by u4BufLen = NULL. */ + if (u4BufLen == NULL) + u4BufLen = &u4BufLen2; + + prTestWinfo = (struct test_wlan_info *)winfos; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prTestWinfo->net_dev)); + ASSERT(prGlueInfo); + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + prReCalInfo = &prAdapter->rReCalInfo; +#if CFG_SUPPORT_ANT_SWAP + prChipInfo = prAdapter->chip_info; + ASSERT(prChipInfo); +#endif + prIcapInfo = &prAdapter->rIcapInfo; + ASSERT(prIcapInfo); + + /* Normal set */ + fgRead = FALSE; + fgWaitResp = FALSE; + fgCmd = TRUE; + + if (prAdapter->fgTestMode == FALSE) { + /* workaround for meta tool */ + DBGLOG(RFTEST, INFO, + "Test Mode Start Workaround for META!\n"); + + ServiceRfTestInit(winfos); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetTestMode, /* pfnOidHandler */ + NULL, /* pvInfoBuf */ + 0, /* u4InfoBufLen */ + fgRead, /* fgRead */ + fgWaitResp, /* fgWaitResp */ + fgCmd, /* fgCmd */ + u4BufLen); /* pu4QryInfoLen */ + + DBGLOG(RFTEST, INFO, + "Test Mode Start Workaround for META2!\n"); + + } + + switch (oidType) { + case OP_WLAN_OID_SET_TEST_MODE_START: + DBGLOG(RFTEST, INFO, "Test Mode Start!\n"); + ServiceRfTestInit(winfos); + pfnOidHandler = wlanoidRftestSetTestMode; + break; + case OP_WLAN_OID_SET_TEST_MODE_ABORT: + DBGLOG(RFTEST, INFO, "Test Mode Abort!\n"); + pfnOidHandler = wlanoidRftestSetAbortTestMode; + break; + case OP_WLAN_OID_RFTEST_SET_AUTO_TEST: + pfnOidHandler = wlanoidRftestSetAutoTest; + break; + case OP_WLAN_OID_RFTEST_QUERY_AUTO_TEST: + pfnOidHandler = wlanoidRftestQueryAutoTest; + fgRead = TRUE; + fgWaitResp = TRUE; + fgCmd = TRUE; + break; + case OP_WLAN_OID_QUERY_RX_STATISTICS: + prStatsData = (struct hqa_m_rx_stat *)rsp_data; + pfnOidHandler = wlanoidQueryRxStatistics; + fgRead = TRUE; + fgWaitResp = TRUE; + fgCmd = TRUE; + break; + case OP_WLAN_OID_GET_CAPABILITY: + capability = (struct test_capability *)rsp_data; + kalMemSet(capability, 0, sizeof(struct test_capability)); + + /* ph_cap.protocol */ + capability->ph_cap.protocol = BIT(0); + if (prAdapter->rWifiVar.ucStaHt) + capability->ph_cap.protocol |= BIT(1); + if (prAdapter->rWifiVar.ucStaVht) + capability->ph_cap.protocol |= BIT(2); +#if (CFG_SUPPORT_802_11AX == 1) + if (prAdapter->rWifiVar.ucStaHe) + capability->ph_cap.protocol |= BIT(3); +#endif /* (CFG_SUPPORT_802_11AX == 1) */ + + /* ph_cap.ant_num */ + capability->ph_cap.ant_num = prAdapter->rWifiVar.ucNSS; + + /* ph_cap.dbdc */ + if (prAdapter->rWifiVar.eDbdcMode != ENUM_DBDC_MODE_DISABLED) + capability->ph_cap.dbdc |= BIT(0); + + /* ph_cap.coding */ + if (prAdapter->rWifiVar.ucTxLdpc) + capability->ph_cap.coding |= BIT(0); + if (prAdapter->rWifiVar.ucRxLdpc) + capability->ph_cap.coding |= BIT(1); + if (prAdapter->rWifiVar.ucTxStbc) + capability->ph_cap.coding |= BIT(2); + if (prAdapter->rWifiVar.ucRxStbc) + capability->ph_cap.coding |= BIT(3); + + /* ph_cap.channel_band */ + capability->ph_cap.channel_band = BIT(0); + if (!prAdapter->fgIsHw5GBandDisabled) + capability->ph_cap.channel_band |= BIT(1); + + /* ph_cap.bandwidth */ + capability->ph_cap.bandwidth = BITS(0, 1); + if (prAdapter->rWifiVar.ucStaVht) + capability->ph_cap.bandwidth |= BIT(2); + + /* ph_cap.channel_band_dbdc */ + if (prAdapter->rWifiVar.eDbdcMode == ENUM_DBDC_MODE_DISABLED) + /* band0 (2.4G + 5G) */ + capability->ph_cap.channel_band_dbdc = 0x00000003; + else + /* 6635: band0 (2.4G); band1 (5G) */ + capability->ph_cap.channel_band_dbdc = 0x00020001; + + /* ext_cap.feature1: BIT0: AntSwap */ +#if CFG_SUPPORT_ANT_SWAP + if (prAdapter->fgIsSupportAntSwp) + capability->ext_cap.feature1 |= BIT(0); +#endif /* CFG_SUPPORT_ANT_SWAP */ + + /* ext_cap.feature1: BIT1: HW TX support */ + /* currently, only AX support */ + if (capability->ph_cap.protocol & BIT(3)) + capability->ext_cap.feature1 |= BIT(1); + + return WLAN_STATUS_SUCCESS; + /* ICAP Operation Function -- Start*/ + case OP_WLAN_OID_SET_TEST_ICAP_MODE: + pfnOidHandler = wlanoidRftestSetTestIcapMode; + break; + case OP_WLAN_OID_SET_TEST_ICAP_START: + ServiceIcapInit(prAdapter); + pfnOidHandler = wlanoidExtRfTestICapStart; + break; + case OP_WLAN_OID_SET_TEST_ICAP_ABORT: + i4Status = ServiceIcapDeInit(prAdapter); + pfnOidHandler = wlanoidExtRfTestICapStart; + break; + case OP_WLAN_OID_SET_TEST_ICAP_STATUS: + + if (!rsp_data) + return WLAN_STATUS_INVALID_DATA; + + resp = (uint32_t *)rsp_data; + + if (prIcapInfo->eIcapState == ICAP_STATE_FW_DUMP_DONE) { + DBGLOG(RFTEST, INFO, "icap capture done!\n"); + *resp = 0; /*response QA TOOL CAPTURE success*/ + return WLAN_STATUS_SUCCESS; + } else if (prIcapInfo->eIcapState == ICAP_STATE_FW_DUMPING) { + DBGLOG(RFTEST, INFO, "icap fw dumping !!!\n"); + *resp = 1; /*response QA TOOL CAPTURE wait*/ + return WLAN_STATUS_SUCCESS; + } + + pfnOidHandler = wlanoidExtRfTestICapStatus; + *resp = 1; /*response QA TOOL CAPTURE wait*/ + + break; + case OP_WLAN_OID_GET_TEST_ICAP_MAX_DATA_LEN: + /* Maximum 1KB = ICAP_EVENT_DATA_SAMPLE (256) slots */ + if (!rsp_data) + return WLAN_STATUS_INVALID_DATA; + + resp = (uint32_t *)rsp_data; + *resp = ICAP_EVENT_DATA_SAMPLE * sizeof(uint32_t); + return WLAN_STATUS_SUCCESS; + case OP_WLAN_OID_GET_TEST_ICAP_DATA: + if ((prIcapInfo->eIcapState != ICAP_STATE_QA_TOOL_CAPTURE) && + (prIcapInfo->eIcapState != ICAP_STATE_FW_DUMP_DONE)) { + DBGLOG(RFTEST, ERROR, "ICAP State = %d don't support\n", + prIcapInfo->eIcapState); + return WLAN_STATUS_NOT_SUPPORTED; + } + pfnOidHandler = wlanoidRfTestICapGetIQData; + fgRead = TRUE; + fgWaitResp = FALSE; + fgCmd = FALSE; + break; + /* ICAP Operation Function -- END*/ + + case OP_WLAN_OID_SET_MCR_WRITE: + pfnOidHandler = wlanoidSetMcrWrite; + fgRead = TRUE; + fgWaitResp = TRUE; + fgCmd = TRUE; + break; + case OP_WLAN_OID_QUERY_MCR_READ: + pfnOidHandler = wlanoidQueryMcrRead; + break; + case OP_WLAN_OID_GET_RECAL_COUNT: + *u4BufLen = prReCalInfo->u4Count; + + return WLAN_STATUS_SUCCESS; + case OP_WLAN_OID_GET_RECAL_CONTENT: + if (!rsp_data) + return WLAN_STATUS_INVALID_DATA; + + if (prReCalInfo->u4Count > 0) { + kalMemCopy(rsp_data, &prReCalInfo->prCalArray[0], + (prReCalInfo->u4Count * sizeof(struct RECAL_DATA_T))); + } + + return WLAN_STATUS_SUCCESS; + case OP_WLAN_OID_GET_ANTSWAP_CAPBILITY: +#if CFG_SUPPORT_ANT_SWAP + if (!prChipInfo) { + DBGLOG(RFTEST, ERROR, "prChipInfo is NULL\n"); + return -EFAULT; + } + + DBGLOG(RFTEST, INFO, "HQA_GetAntSwapCapability [%d]\n", + prGlueInfo->prAdapter->fgIsSupportAntSwp); + + DBGLOG(RFTEST, INFO, "ucMaxSwapAntenna = [%d]\n", + prChipInfo->ucMaxSwapAntenna); + + if (prGlueInfo->prAdapter->fgIsSupportAntSwp) + *u4BufLen = prChipInfo->ucMaxSwapAntenna; + else + *u4BufLen = 0; + + return WLAN_STATUS_SUCCESS; +#endif + case OP_WLAN_OID_RESET_RECAL_COUNT: + kalMemSet(&prReCalInfo->prCalArray[0], 0, + (prReCalInfo->u4Count * sizeof(struct RECAL_DATA_T))); + + prReCalInfo->u4Count = 0; + + return WLAN_STATUS_SUCCESS; + + case OP_WLAN_OID_NUM: + default: + return WLAN_STATUS_FAILURE; + } + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + pfnOidHandler, /* pfnOidHandler */ + param, /* pvInfoBuf */ + paramLen, /* u4InfoBufLen */ + fgRead, /* fgRead */ + fgWaitResp, /* fgWaitResp */ + fgCmd, /* fgCmd */ + u4BufLen); /* pu4QryInfoLen */ + + if ((prStatsData) && + (oidType == OP_WLAN_OID_QUERY_RX_STATISTICS)) { + + /* 264 = 66 items * 4 bytes */ + kalMemCopy(&prStatsData->mac_rx_fcs_err_cnt, + &(g_HqaRxStat.MAC_FCS_Err), 264); + } + + return i4Status; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_init.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_init.c new file mode 100644 index 0000000000000..7b8d9e67434ae --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_init.c @@ -0,0 +1,5643 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux + * /gl_init.c#11 + */ + +/*! \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. + */ + + +/******************************************************************************* + * C O M P I L E 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" +#if CFG_SUPPORT_AGPS_ASSIST +#include "gl_kal.h" +#endif +#if CFG_TC1_FEATURE +#include +#endif +#if CFG_CHIP_RESET_SUPPORT +#include "gl_rst.h" +#endif +#include "gl_vendor.h" +#include "gl_hook_api.h" +#if CFG_MTK_MCIF_WIFI_SUPPORT +#include "mddp.h" +#endif +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +/* #define MAX_IOREQ_NUM 10 */ +struct semaphore g_halt_sem; +int g_u4HaltFlag; +int g_u4WlanInitFlag; +enum ENUM_NVRAM_STATE g_NvramFsm = NVRAM_STATE_INIT; + +uint8_t g_aucNvram[MAX_CFG_FILE_WIFI_REC_SIZE]; +struct wireless_dev *gprWdev[KAL_AIS_NUM]; + +#if CFG_SUPPORT_PERSIST_NETDEV +struct net_device *gprNetdev[KAL_AIS_NUM] = {}; +#endif +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +/* Tasklet mechanism is like buttom-half in Linux. We just want to + * send a signal to OS for interrupt defer processing. All resources + * are NOT allowed reentry, so txPacket, ISR-DPC and ioctl must avoid preempty. + */ +struct WLANDEV_INFO { + struct net_device *prDev; +}; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +MODULE_AUTHOR(NIC_AUTHOR); +MODULE_DESCRIPTION(NIC_DESC); +MODULE_SUPPORTED_DEVICE(NIC_NAME); + +/* MODULE_LICENSE("MTK Propietary"); */ +MODULE_LICENSE("Dual BSD/GPL"); + +#ifdef CFG_DRIVER_INF_NAME_CHANGE +char *gprifnamesta = ""; +char *gprifnamep2p = ""; +char *gprifnameap = ""; +module_param_named(sta, gprifnamesta, charp, 0000); +module_param_named(p2p, gprifnamep2p, charp, 0000); +module_param_named(ap, gprifnameap, charp, 0000); +#endif /* CFG_DRIVER_INF_NAME_CHANGE */ + +/* NIC interface name */ +#define NIC_INF_NAME "wlan%d" + +#ifdef CFG_DRIVER_INF_NAME_CHANGE +/* Kernel IFNAMESIZ is 16, we use 5 in case some protocol might auto gen + * interface name, + */ +/* in that case, the interface name might have risk of over kernel's IFNAMESIZ + */ +#define CUSTOM_IFNAMESIZ 5 +#endif /* CFG_DRIVER_INF_NAME_CHANGE */ + +#if CFG_SUPPORT_SNIFFER +#define NIC_MONITOR_INF_NAME "radiotap%d" +#endif + +uint8_t aucDebugModule[DBG_MODULE_NUM]; +uint32_t au4LogLevel[ENUM_WIFI_LOG_MODULE_NUM] = {ENUM_WIFI_LOG_LEVEL_DEFAULT}; + +/* 4 2007/06/26, mikewu, now we don't use this, we just fix the number of wlan + * device to 1 + */ +static struct WLANDEV_INFO + arWlanDevInfo[CFG_MAX_WLAN_DEVICES] = { {0} }; + +static uint32_t +u4WlanDevNum; /* How many NICs coexist now */ + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +u_int8_t g_fgIsCalDataBackuped = FALSE; +#endif + +/* 20150205 added work queue for sched_scan to avoid cfg80211 stop schedule scan + * dead loack + */ +struct delayed_work sched_workq; + +#define CFG_EEPRM_FILENAME "EEPROM" +#define FILE_NAME_MAX 64 + +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1) +static uint8_t *apucEepromName[] = { + (uint8_t *) CFG_EEPRM_FILENAME "_MT", + NULL +}; +#endif + +/* For running on X86 UT environment */ +#if defined(UT_TEST_MODE) && defined(CFG_BUILD_X86_PLATFORM) +phys_addr_t gConEmiPhyBase; +EXPORT_SYMBOL(gConEmiPhyBase); + +unsigned long long gConEmiSize; +EXPORT_SYMBOL(gConEmiSize); +#endif + +int CFG80211_Suspend(struct wiphy *wiphy, + struct cfg80211_wowlan *wow) +{ + DBGLOG(INIT, INFO, "CFG80211 suspend CB\n"); + + return 0; +} + +int CFG80211_Resume(struct wiphy *wiphy) +{ + DBGLOG(INIT, INFO, "CFG80211 resume CB\n"); + + return 0; +} + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +#define CHAN2G(_channel, _freq, _flags) \ +{ \ + .band = KAL_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 = KAL_BAND_5GHZ, \ + .center_freq = \ + (((_channel >= 182) && (_channel <= 196)) ? \ + (4000 + (5 * (_channel))) : (5000 + (5 * (_channel)))), \ + .hw_value = (_channel), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} +static struct ieee80211_channel mtk_5ghz_channels[] = { + /* UNII-1 */ + CHAN5G(36, 0), + CHAN5G(40, 0), + CHAN5G(44, 0), + CHAN5G(48, 0), + /* UNII-2 */ + CHAN5G(52, IEEE80211_CHAN_RADAR), + CHAN5G(56, IEEE80211_CHAN_RADAR), + CHAN5G(60, IEEE80211_CHAN_RADAR), + CHAN5G(64, IEEE80211_CHAN_RADAR), + /* UNII-2e */ + CHAN5G(100, IEEE80211_CHAN_RADAR), + CHAN5G(104, IEEE80211_CHAN_RADAR), + CHAN5G(108, IEEE80211_CHAN_RADAR), + CHAN5G(112, IEEE80211_CHAN_RADAR), + CHAN5G(116, IEEE80211_CHAN_RADAR), + CHAN5G(120, IEEE80211_CHAN_RADAR), + CHAN5G(124, IEEE80211_CHAN_RADAR), + CHAN5G(128, IEEE80211_CHAN_RADAR), + CHAN5G(132, IEEE80211_CHAN_RADAR), + CHAN5G(136, IEEE80211_CHAN_RADAR), + CHAN5G(140, IEEE80211_CHAN_RADAR), + CHAN5G(144, IEEE80211_CHAN_RADAR), + /* UNII-3 */ + CHAN5G(149, 0), + CHAN5G(153, 0), + CHAN5G(157, 0), + CHAN5G(161, 0), + CHAN5G(165, 0) +}; + +#define RATETAB_ENT(_rate, _rateid, _flags) \ +{ \ + .bitrate = (_rate), \ + .hw_value = (_rateid), \ + .flags = (_flags), \ +} + +/* for cfg80211 - rate table */ +static struct ieee80211_rate mtk_rates[] = { + RATETAB_ENT(10, 0x1000, 0), + RATETAB_ENT(20, 0x1001, 0), + RATETAB_ENT(55, 0x1002, 0), + RATETAB_ENT(110, 0x1003, 0), /* 802.11b */ + RATETAB_ENT(60, 0x2000, 0), + RATETAB_ENT(90, 0x2001, 0), + RATETAB_ENT(120, 0x2002, 0), + RATETAB_ENT(180, 0x2003, 0), + RATETAB_ENT(240, 0x2004, 0), + RATETAB_ENT(360, 0x2005, 0), + RATETAB_ENT(480, 0x2006, 0), + RATETAB_ENT(540, 0x2007, 0), /* 802.11a/g */ +}; + +#define mtk_a_rates (mtk_rates + 4) +#define mtk_a_rates_size (ARRAY_SIZE(mtk_rates) - 4) +#define mtk_g_rates (mtk_rates + 0) +#define mtk_g_rates_size (ARRAY_SIZE(mtk_rates) - 0) + +#define WLAN_MCS_INFO \ +{ \ + .rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \ + .rx_highest = 0, \ + .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ +} + +#define WLAN_VHT_MCS_INFO \ +{ \ + .rx_mcs_map = 0xFFFA, \ + .rx_highest = cpu_to_le16(867), \ + .tx_mcs_map = 0xFFFA, \ + .tx_highest = cpu_to_le16(867), \ +} + + +#define WLAN_HT_CAP \ +{ \ + .ht_supported = true, \ + .cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 \ + | IEEE80211_HT_CAP_SM_PS \ + | IEEE80211_HT_CAP_GRN_FLD \ + | IEEE80211_HT_CAP_SGI_20 \ + | IEEE80211_HT_CAP_SGI_40, \ + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, \ + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE, \ + .mcs = WLAN_MCS_INFO, \ +} + +#define WLAN_VHT_CAP \ +{ \ + .vht_supported = true, \ + .cap = IEEE80211_VHT_CAP_RXLDPC \ + | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK \ + | IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 \ + | IEEE80211_VHT_CAP_RXLDPC \ + | IEEE80211_VHT_CAP_SHORT_GI_80 \ + | IEEE80211_VHT_CAP_TXSTBC \ + | IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE \ + | IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE, \ + .vht_mcs = WLAN_VHT_MCS_INFO, \ +} + +/* public for both Legacy Wi-Fi / P2P access */ +struct ieee80211_supported_band mtk_band_2ghz = { + .band = KAL_BAND_2GHZ, + .channels = mtk_2ghz_channels, + .n_channels = ARRAY_SIZE(mtk_2ghz_channels), + .bitrates = mtk_g_rates, + .n_bitrates = mtk_g_rates_size, + .ht_cap = WLAN_HT_CAP, +}; + +/* public for both Legacy Wi-Fi / P2P access */ +struct ieee80211_supported_band mtk_band_5ghz = { + .band = KAL_BAND_5GHZ, + .channels = mtk_5ghz_channels, + .n_channels = ARRAY_SIZE(mtk_5ghz_channels), + .bitrates = mtk_a_rates, + .n_bitrates = mtk_a_rates_size, + .ht_cap = WLAN_HT_CAP, + .vht_cap = WLAN_VHT_CAP, +}; + +const uint32_t 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, + WLAN_CIPHER_SUITE_GCMP_256, + WLAN_CIPHER_SUITE_BIP_GMAC_256, /* TODO, HW not support, + * SW should handle integrity check + */ + WLAN_CIPHER_SUITE_NO_GROUP_ADDR +}; + +#if (CFG_ENABLE_UNIFY_WIPHY == 0) +static struct cfg80211_ops mtk_wlan_ops = { + .suspend = mtk_cfg80211_suspend, + .resume = mtk_cfg80211_resume, + .change_virtual_intf = mtk_cfg80211_change_iface, + .add_key = mtk_cfg80211_add_key, + .get_key = mtk_cfg80211_get_key, + .del_key = mtk_cfg80211_del_key, + .set_default_key = mtk_cfg80211_set_default_key, + .get_station = mtk_cfg80211_get_station, +#if CFG_SUPPORT_TDLS + .change_station = mtk_cfg80211_change_station, + .add_station = mtk_cfg80211_add_station, + .del_station = mtk_cfg80211_del_station, +#endif + .scan = mtk_cfg80211_scan, +#if KERNEL_VERSION(4, 5, 0) <= CFG80211_VERSION_CODE + .abort_scan = mtk_cfg80211_abort_scan, +#endif + .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, +#if CONFIG_SUPPORT_GTK_REKEY + .set_rekey_data = mtk_cfg80211_set_rekey_data, +#endif + .assoc = mtk_cfg80211_assoc, + + /* Action Frame TX/RX */ + .remain_on_channel = mtk_cfg80211_remain_on_channel, + .cancel_remain_on_channel = mtk_cfg80211_cancel_remain_on_channel, + .mgmt_tx = mtk_cfg80211_mgmt_tx, + /* .mgmt_tx_cancel_wait = mtk_cfg80211_mgmt_tx_cancel_wait, */ + .mgmt_frame_register = mtk_cfg80211_mgmt_frame_register, + +#ifdef CONFIG_NL80211_TESTMODE + .testmode_cmd = mtk_cfg80211_testmode_cmd, +#endif +#if CFG_SUPPORT_SCHED_SCAN + .sched_scan_start = mtk_cfg80211_sched_scan_start, + .sched_scan_stop = mtk_cfg80211_sched_scan_stop, +#endif /* CFG_SUPPORT_SCHED_SCAN */ +#if CFG_SUPPORT_TDLS + .tdls_oper = mtk_cfg80211_tdls_oper, + .tdls_mgmt = mtk_cfg80211_tdls_mgmt, +#endif + .update_ft_ies = mtk_cfg80211_update_ft_ies, + +#if CFG_SUPPORT_WPA3 + .external_auth = mtk_cfg80211_external_auth, +#endif +}; +#else /* CFG_ENABLE_UNIFY_WIPHY */ +static struct cfg80211_ops mtk_cfg_ops = { + .add_virtual_intf = mtk_cfg_add_iface, + .del_virtual_intf = mtk_cfg_del_iface, + .change_virtual_intf = mtk_cfg_change_iface, + .add_key = mtk_cfg_add_key, + .get_key = mtk_cfg_get_key, + .del_key = mtk_cfg_del_key, + .set_default_mgmt_key = mtk_cfg_set_default_mgmt_key, + .set_default_key = mtk_cfg_set_default_key, + .get_station = mtk_cfg_get_station, +#if CFG_SUPPORT_TDLS + .change_station = mtk_cfg_change_station, + .add_station = mtk_cfg_add_station, + .tdls_oper = mtk_cfg_tdls_oper, + .tdls_mgmt = mtk_cfg_tdls_mgmt, +#endif + .del_station = mtk_cfg_del_station, /* AP/P2P use this function */ + .scan = mtk_cfg_scan, +#if KERNEL_VERSION(4, 5, 0) <= CFG80211_VERSION_CODE + .abort_scan = mtk_cfg_abort_scan, +#endif +#if CFG_SUPPORT_SCHED_SCAN + .sched_scan_start = mtk_cfg_sched_scan_start, + .sched_scan_stop = mtk_cfg_sched_scan_stop, +#endif /* CFG_SUPPORT_SCHED_SCAN */ + + .connect = mtk_cfg_connect, + .disconnect = mtk_cfg_disconnect, + .join_ibss = mtk_cfg_join_ibss, + .leave_ibss = mtk_cfg_leave_ibss, + .set_power_mgmt = mtk_cfg_set_power_mgmt, + .set_pmksa = mtk_cfg_set_pmksa, + .del_pmksa = mtk_cfg_del_pmksa, + .flush_pmksa = mtk_cfg_flush_pmksa, +#if CONFIG_SUPPORT_GTK_REKEY + .set_rekey_data = mtk_cfg_set_rekey_data, +#endif + .suspend = mtk_cfg_suspend, + .resume = mtk_cfg_resume, + + .assoc = mtk_cfg_assoc, + + /* Action Frame TX/RX */ + .remain_on_channel = mtk_cfg_remain_on_channel, + .cancel_remain_on_channel = mtk_cfg_cancel_remain_on_channel, + .mgmt_tx = mtk_cfg_mgmt_tx, + /* .mgmt_tx_cancel_wait = mtk_cfg80211_mgmt_tx_cancel_wait, */ + .mgmt_frame_register = mtk_cfg_mgmt_frame_register, + +#ifdef CONFIG_NL80211_TESTMODE + .testmode_cmd = mtk_cfg_testmode_cmd, +#endif + +#if (CFG_SUPPORT_DFS_MASTER == 1) + .start_radar_detection = mtk_cfg_start_radar_detection, +#if KERNEL_VERSION(3, 13, 0) <= CFG80211_VERSION_CODE + .channel_switch = mtk_cfg_channel_switch, +#endif +#endif + +#if (CFG_ENABLE_WIFI_DIRECT_CFG_80211 != 0) + .change_bss = mtk_cfg_change_bss, + .mgmt_tx_cancel_wait = mtk_cfg_mgmt_tx_cancel_wait, + .deauth = mtk_cfg_deauth, + .disassoc = mtk_cfg_disassoc, + .start_ap = mtk_cfg_start_ap, + .change_beacon = mtk_cfg_change_beacon, + .stop_ap = mtk_cfg_stop_ap, + .set_wiphy_params = mtk_cfg_set_wiphy_params, + .set_bitrate_mask = mtk_cfg_set_bitrate_mask, + .set_tx_power = mtk_cfg_set_txpower, + .get_tx_power = mtk_cfg_get_txpower, +#endif + .update_ft_ies = mtk_cfg80211_update_ft_ies, +#if CFG_SUPPORT_WPA3 + .external_auth = mtk_cfg80211_external_auth, +#endif +}; +#endif /* CFG_ENABLE_UNIFY_WIPHY */ + +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE + +static const struct wiphy_vendor_command + mtk_wlan_vendor_ops[] = { + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_GET_CHANNEL_LIST + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_channel_list +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + , + .policy = VENDOR_CMD_RAW_DATA +#endif + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_SET_COUNTRY_CODE + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_country_code +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + , + .policy = VENDOR_CMD_RAW_DATA +#endif + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV + | WIPHY_VENDOR_CMD_NEED_NETDEV + | WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = mtk_cfg80211_vendor_set_scan_mac_oui +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + , + .policy = VENDOR_CMD_RAW_DATA +#endif + }, + { + { + .vendor_id = OUI_QCA, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_band +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + , + .policy = VENDOR_CMD_RAW_DATA +#endif + }, +#if CFG_SUPPORT_MBO + { + { + .vendor_id = OUI_QCA, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_roaming_param +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + , + .policy = VENDOR_CMD_RAW_DATA +#endif + + }, +#endif + { + { + .vendor_id = OUI_QCA, + .subcmd = WIFI_SUBCMD_SET_ROAMING + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_roaming_policy +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + , + .policy = VENDOR_CMD_RAW_DATA +#endif + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_GET_ROAMING_CAPABILITIES + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_roaming_capabilities +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + , + .policy = VENDOR_CMD_RAW_DATA +#endif + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_CONFIG_ROAMING + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_config_roaming +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + , + .policy = VENDOR_CMD_RAW_DATA +#endif + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_ENABLE_ROAMING + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_enable_roaming +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + , + .policy = VENDOR_CMD_RAW_DATA +#endif + }, + /* RTT */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = RTT_SUBCMD_GETCAPABILITY + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_rtt_capabilities +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + , + .policy = VENDOR_CMD_RAW_DATA +#endif + }, + /* Link Layer Statistics */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = LSTATS_SUBCMD_GET_INFO + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_llstats_get_info +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + , + .policy = VENDOR_CMD_RAW_DATA +#endif + }, + /* RSSI Monitoring */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_SET_RSSI_MONITOR + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_rssi_monitoring +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + , + .policy = VENDOR_CMD_RAW_DATA +#endif + }, + /* Packet Keep Alive */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_OFFLOAD_START_MKEEP_ALIVE + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_packet_keep_alive_start +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + , + .policy = VENDOR_CMD_RAW_DATA +#endif + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_OFFLOAD_STOP_MKEEP_ALIVE + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_packet_keep_alive_stop +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + , + .policy = VENDOR_CMD_RAW_DATA +#endif + }, + /* Get Driver Version or Firmware Version */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = LOGGER_GET_VER + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_version +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + , + .policy = VENDOR_CMD_RAW_DATA +#endif + }, + /* Get Supported Feature Set */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_GET_FEATURE_SET + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_supported_feature_set +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + , + .policy = VENDOR_CMD_RAW_DATA +#endif + + }, + /* Set Tx Power Scenario */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_SELECT_TX_POWER_SCENARIO + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_tx_power_scenario +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + , + .policy = VENDOR_CMD_RAW_DATA +#endif + }, +#if CFG_SUPPORT_P2P_PREFERRED_FREQ_LIST + /* P2P get preferred freq list */ + { + { + .vendor_id = OUI_QCA, + .subcmd = NL80211_VENDOR_SUBCMD_GET_PREFER_FREQ_LIST + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV + | WIPHY_VENDOR_CMD_NEED_NETDEV + | WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = mtk_cfg80211_vendor_get_preferred_freq_list +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + , + .policy = VENDOR_CMD_RAW_DATA +#endif + }, +#endif /* CFG_SUPPORT_P2P_PREFERRED_FREQ_LIST */ +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + { + { + .vendor_id = OUI_QCA, + .subcmd = NL80211_VENDOR_SUBCMD_ACS + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV + | WIPHY_VENDOR_CMD_NEED_NETDEV + | WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = mtk_cfg80211_vendor_acs +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + , + .policy = VENDOR_CMD_RAW_DATA +#endif + }, +#endif + { + { + .vendor_id = OUI_QCA, + .subcmd = NL80211_VENDOR_SUBCMD_GET_FEATURES + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV + | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_features +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + , + .policy = VENDOR_CMD_RAW_DATA +#endif + + }, + /* Get Driver Memory Dump */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = LOGGER_DRIVER_MEM_DUMP + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_driver_memory_dump +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + , + .policy = VENDOR_CMD_RAW_DATA +#endif + } +}; + +static const struct nl80211_vendor_cmd_info + mtk_wlan_vendor_events[] = { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_HOTLIST_RESULTS_FOUND + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_SCAN_RESULTS_AVAILABLE + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_FULL_SCAN_RESULTS + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = RTT_EVENT_COMPLETE + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_COMPLETE_SCAN + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_HOTLIST_RESULTS_LOST + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_EVENT_RSSI_MONITOR + }, +#if CFG_SUPPORT_DATA_STALL + { + .vendor_id = OUI_MTK, + .subcmd = WIFI_EVENT_DRIVER_ERROR + }, +#endif +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + { + .vendor_id = OUI_QCA, + .subcmd = NL80211_VENDOR_SUBCMD_ACS + }, +#endif + + { + .vendor_id = OUI_MTK, + .subcmd = WIFI_EVENT_GENERIC_RESPONSE + }, + +#if CFG_SUPPORT_BIGDATA_PIP + { + .vendor_id = OUI_MTK, + .subcmd = WIFI_EVENT_BIGDATA_PIP + }, +#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_ais_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { + [NL80211_IFTYPE_ADHOC] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) + }, + [NL80211_IFTYPE_STATION] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) + }, + [NL80211_IFTYPE_AP] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + | BIT(IEEE80211_STYPE_ACTION >> 4) +#if CFG_SUPPORT_SOFTAP_WPA3 + | BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) +#endif + }, + [NL80211_IFTYPE_AP_VLAN] = { + /* copy AP */ + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) | + BIT(IEEE80211_STYPE_ACTION >> 4) + }, + [NL80211_IFTYPE_P2P_CLIENT] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + }, + [NL80211_IFTYPE_P2P_GO] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_ACTION >> 4) + } +}; + +#ifdef CONFIG_PM +static const struct wiphy_wowlan_support mtk_wlan_wowlan_support = { + .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT | + WIPHY_WOWLAN_ANY, +}; +#endif + +#if CFG_SUPPORT_RM_BEACON_REPORT_BY_SUPPLICANT +/* NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES & NL80211_FEATURE_QUIET + * support in linux kernet version => 3.18 + */ +#if KERNEL_VERSION(3, 18, 0) > CFG80211_VERSION_CODE +#define NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES BIT(19) +#define NL80211_FEATURE_QUIET BIT(21) +#endif +#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 0 +/*----------------------------------------------------------------------------*/ +/*! + * \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; +} +#endif + +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE +u16 wlanSelectQueue(struct net_device *dev, + struct sk_buff *skb, + struct net_device *sb_dev) +{ + return mtk_wlan_ndev_select_queue(dev, skb); +} +#elif KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE +u16 wlanSelectQueue(struct net_device *dev, + struct sk_buff *skb, + struct net_device *sb_dev, select_queue_fallback_t fallback) +{ + return mtk_wlan_ndev_select_queue(dev, skb); +} +#elif KERNEL_VERSION(3, 14, 0) <= LINUX_VERSION_CODE +u16 wlanSelectQueue(struct net_device *dev, + struct sk_buff *skb, + void *accel_priv, select_queue_fallback_t fallback) +{ + return mtk_wlan_ndev_select_queue(dev, skb); +} +#elif KERNEL_VERSION(3, 13, 0) <= LINUX_VERSION_CODE +u16 wlanSelectQueue(struct net_device *dev, + struct sk_buff *skb, + void *accel_priv) +{ + return mtk_wlan_ndev_select_queue(dev, skb); +} +#else +u16 wlanSelectQueue(struct net_device *dev, + struct sk_buff *skb) +{ + return mtk_wlan_ndev_select_queue(dev, skb); +} +#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(struct GLUE_INFO *prGlueInfo, + struct REG_INFO *prRegInfo) +{ + struct WIFI_CFG_PARAM_STRUCT *prNvramSettings; + + ASSERT(prRegInfo); + ASSERT(prGlueInfo); + + DBGLOG(INIT, INFO, "g_NvramFsm = %d\n", g_NvramFsm); + if (g_NvramFsm != NVRAM_STATE_READY) { + DBGLOG(INIT, WARN, "Nvram not available\n"); + return; + } + + if (sizeof(struct WIFI_CFG_PARAM_STRUCT) > + sizeof(g_aucNvram)) { + DBGLOG(INIT, ERROR, + "Size WIFI_CFG_PARAM_STRUCT %zu > size aucNvram %zu\n" + , sizeof(struct WIFI_CFG_PARAM_STRUCT), + sizeof(g_aucNvram)); + return; + } + + prGlueInfo->fgNvramAvailable = TRUE; + + prRegInfo->prNvramSettings = + (struct WIFI_CFG_PARAM_STRUCT *)&g_aucNvram[0]; + prNvramSettings = prRegInfo->prNvramSettings; + +#if CFG_TC1_FEATURE + TC1_FAC_NAME(FacReadWifiMacAddr)(prRegInfo->aucMacAddr); + DBGLOG(INIT, INFO, + "MAC address: " MACSTR, MAC2STR(prRegInfo->aucMacAddr)); +#else + /* load MAC Address */ + kalMemCopy(prRegInfo->aucMacAddr, + prNvramSettings->aucMacAddress, + PARAM_MAC_ADDR_LEN*sizeof(uint8_t)); +#endif + /* load country code */ + /* cast to wide characters */ + prRegInfo->au2CountryCode[0] = + (uint16_t) prNvramSettings->aucCountryCode[0]; + prRegInfo->au2CountryCode[1] = + (uint16_t) prNvramSettings->aucCountryCode[1]; + + prRegInfo->ucSupport5GBand = + prNvramSettings->ucSupport5GBand; + + prRegInfo->ucEnable5GBand = prNvramSettings->ucEnable5GBand; + + /* load regulation subbands */ + prRegInfo->eRegChannelListMap = 0; + prRegInfo->ucRegChannelListIndex = 0; + + if (prRegInfo->eRegChannelListMap == REG_CH_MAP_CUSTOMIZED) { + kalMemCopy(prRegInfo->rDomainInfo.rSubBand, + prNvramSettings->aucRegSubbandInfo, + MAX_SUBBAND_NUM*sizeof(uint8_t)); + } + + log_dbg(INIT, INFO, "u2Part1OwnVersion = %08x, u2Part1PeerVersion = %08x\n", + prNvramSettings->u2Part1OwnVersion, + prNvramSettings->u2Part1PeerVersion); +} + +static void wlanFreeNetDev(void) +{ + uint32_t u4Idx = 0; + + for (u4Idx = 0; u4Idx < KAL_AIS_NUM; u4Idx++) { + if (gprWdev[u4Idx] && gprWdev[u4Idx]->netdev) { + DBGLOG(INIT, INFO, "free_netdev wlan%d netdev start.\n", + u4Idx); + free_netdev(gprWdev[u4Idx]->netdev); + DBGLOG(INIT, INFO, "free_netdev wlan%d netdev end.\n", + u4Idx); + } + } +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Release prDev from wlandev_array and free tasklet object related to + * it. + * + * \param[in] prDev Pointer to struct net_device + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static void wlanClearDevIdx(struct net_device *prDev) +{ + int i; + + ASSERT(prDev); + + for (i = 0; i < CFG_MAX_WLAN_DEVICES; i++) { + if (arWlanDevInfo[i].prDev == prDev) { + arWlanDevInfo[i].prDev = NULL; + u4WlanDevNum--; + } + } + +} /* end of wlanClearDevIdx() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Allocate an unique interface index, net_device::ifindex member for + * this wlan device. Store the net_device in wlandev_array, and + * initialize tasklet object related to it. + * + * \param[in] prDev Pointer to struct net_device + * + * \retval >= 0 The device number. + * \retval -1 Fail to get index. + */ +/*----------------------------------------------------------------------------*/ +static int wlanGetDevIdx(struct net_device *prDev) +{ + int i; + + ASSERT(prDev); + + for (i = 0; i < CFG_MAX_WLAN_DEVICES; i++) { + if (arWlanDevInfo[i].prDev == (struct net_device *)NULL) { + /* Reserve 2 bytes space to store one digit of + * device number and NULL terminator. + */ + arWlanDevInfo[i].prDev = prDev; + u4WlanDevNum++; + return i; + } +#if CFG_SUPPORT_PERSIST_NETDEV + else if (arWlanDevInfo[i].prDev == prDev) + return i; +#endif + } + + 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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int ret = 0; + + /* Verify input parameters for the following functions */ + ASSERT(prDev && prIfReq); + if (!prDev || !prIfReq) { + DBGLOG(INIT, ERROR, "Invalid input data\n"); + return -EINVAL; + } + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + if (!prGlueInfo) { + DBGLOG(INIT, ERROR, "prGlueInfo is NULL\n"); + return -EFAULT; + } + + if (prGlueInfo->u4ReadyFlag == 0) { + DBGLOG(INIT, ERROR, "Adapter is not ready\n"); + return -EINVAL; + } + + if ((i4Cmd >= SIOCIWFIRST) && (i4Cmd < SIOCIWFIRSTPRIV)) { + /* 0x8B00 ~ 0x8BDF, wireless extension region */ + ret = wext_support_ioctl(prDev, prIfReq, i4Cmd); + } else if ((i4Cmd >= SIOCIWFIRSTPRIV) + && (i4Cmd < SIOCIWLASTPRIV)) { + /* 0x8BE0 ~ 0x8BFF, private ioctl region */ + ret = priv_support_ioctl(prDev, prIfReq, i4Cmd); + } else if (i4Cmd == SIOCDEVPRIVATE + 1) { +#ifdef CFG_ANDROID_AOSP_PRIV_CMD + ret = android_private_support_driver_cmd(prDev, prIfReq, i4Cmd); +#else + ret = priv_support_driver_cmd(prDev, prIfReq, i4Cmd); +#endif /* CFG_ANDROID_AOSP_PRIV_CMD */ + } else if (i4Cmd == SIOCDEVPRIVATE + 2) { + ret = priv_support_ioctl(prDev, prIfReq, i4Cmd); + } else { + DBGLOG(INIT, WARN, "Unexpected ioctl command: 0x%04x\n", + i4Cmd); + ret = -EOPNOTSUPP; + } + + return ret; +} /* end of wlanDoIOCTL() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*---------------------------------------------------------------------------*/ +struct GLUE_INFO *wlanGetGlueInfo(void) +{ + struct net_device *prDev = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + + if (u4WlanDevNum == 0) + return NULL; + + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + if (prDev == NULL) + return NULL; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + + return prGlueInfo; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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; +struct net_device *gPrDev; + +static void wlanSetMulticastList(struct net_device *prDev) +{ + struct GLUE_INFO *prGlueInfo; + + if (!prDev) + return; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + + if (!prGlueInfo || !prGlueInfo->u4ReadyFlag) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return; + } + + /* Allow to receive all multicast for WOW */ + DBGLOG(INIT, TRACE, "flags: 0x%x\n", prDev->flags); + prDev->flags |= (IFF_MULTICAST | IFF_ALLMULTI); + 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 + * main_thread, so we can't let tx_thread to do this + */ + +static void wlanSetMulticastListWorkQueue( + struct work_struct *work) +{ + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4PacketFilter = 0; + uint32_t u4SetInfoLen; + struct net_device *prDev = gPrDev; + uint8_t ucBssIndex = 0; + + ucBssIndex = wlanGetBssIdx(prDev); + if (!IS_BSS_INDEX_VALID(ucBssIndex)) + return; + + down(&g_halt_sem); + if (g_u4HaltFlag) { + up(&g_halt_sem); + return; + } + + prGlueInfo = (prDev != NULL) ? *((struct GLUE_INFO **) + 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 (!prGlueInfo->u4ReadyFlag) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + up(&g_halt_sem); + return; + } + + DBGLOG(INIT, TRACE, + "wlanSetMulticastListWorkQueue prDev->flags:0x%x\n", + prDev->flags); + + if (prDev->flags & IFF_PROMISC) + u4PacketFilter |= PARAM_PACKET_FILTER_PROMISCUOUS; + + if (prDev->flags & IFF_BROADCAST) + u4PacketFilter |= PARAM_PACKET_FILTER_BROADCAST; + + if (prDev->flags & IFF_MULTICAST) { + if ((prDev->flags & IFF_ALLMULTI) + || (netdev_mc_count(prDev) > MAX_NUM_GROUP_ADDR)) + u4PacketFilter |= PARAM_PACKET_FILTER_ALL_MULTICAST; + else + u4PacketFilter |= PARAM_PACKET_FILTER_MULTICAST; + } + + up(&g_halt_sem); + + if (kalIoctl(prGlueInfo, + wlanoidSetCurrentPacketFilter, + &u4PacketFilter, + sizeof(u4PacketFilter), FALSE, FALSE, TRUE, + &u4SetInfoLen) != WLAN_STATUS_SUCCESS) { + return; + } + + if (u4PacketFilter & PARAM_PACKET_FILTER_MULTICAST) { + /* Prepare multicast address list */ + struct netdev_hw_addr *ha; + uint8_t *prMCAddrList = NULL; + uint32_t 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 (!prMCAddrList) { + DBGLOG(INIT, WARN, "prMCAddrList memory alloc fail!\n"); + up(&g_halt_sem); + return; + } + + /* Avoid race condition with kernel net subsystem */ + netif_addr_lock_bh(prDev); + + netdev_for_each_mc_addr(ha, prDev) { + if (i < MAX_NUM_GROUP_ADDR) { + kalMemCopy((prMCAddrList + i * ETH_ALEN), + GET_ADDR(ha), ETH_ALEN); + i++; + } + } + + netif_addr_unlock_bh(prDev); + + up(&g_halt_sem); + + kalIoctlByBssIdx(prGlueInfo, + wlanoidSetMulticastList, prMCAddrList, (i * ETH_ALEN), + FALSE, FALSE, TRUE, &u4SetInfoLen, + ucBssIndex); + + kalMemFree(prMCAddrList, VIR_MEM_TYPE, + MAX_NUM_GROUP_ADDR * ETH_ALEN); + } + +} /* end of wlanSetMulticastList() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To indicate scheduled scan has been stopped + * + * \param[in] + * prGlueInfo + * + * \return + * None + */ +/*----------------------------------------------------------------------------*/ +void wlanSchedScanStoppedWorkQueue(struct work_struct *work) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct net_device *prDev = gPrDev; + + DBGLOG(SCN, INFO, "wlanSchedScanStoppedWorkQueue\n"); + prGlueInfo = (prDev != NULL) ? *((struct GLUE_INFO **) + netdev_priv(prDev)) : NULL; + if (!prGlueInfo) { + DBGLOG(SCN, INFO, "prGlueInfo == NULL unexpected\n"); + return; + } + + /* 2. indication to cfg80211 */ + /* 20150205 change cfg80211_sched_scan_stopped to work queue due to + * sched_scan_mtx dead lock issue + */ +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE + cfg80211_sched_scan_stopped(priv_to_wiphy(prGlueInfo), 0); +#else + cfg80211_sched_scan_stopped(priv_to_wiphy(prGlueInfo)); +#endif + DBGLOG(SCN, INFO, + "cfg80211_sched_scan_stopped event send done WorkQueue thread return from wlanSchedScanStoppedWorkQueue\n"); + return; + +} + +/* FIXME: Since we cannot sleep in the wlanSetMulticastList, we arrange + * another workqueue for sleeping. We don't want to block + * main_thread, so we can't let tx_thread to do this + */ + +void p2pSetMulticastListWorkQueueWrapper(struct GLUE_INFO + *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 + +} /* end of p2pSetMulticastListWorkQueueWrapper() */ + +#if ARP_BRUST_OPTIMIZE +static u_int8_t data_is_ipv4_arp_pkt(struct sk_buff *skb) +{ + uint8_t *pPkt; + uint16_t u2EtherType; + + pPkt = skb->data; + u2EtherType = (pPkt[ETH_TYPE_LEN_OFFSET] << 8) + |(pPkt[ETH_TYPE_LEN_OFFSET + 1]); + //DBGLOG(INIT, INFO, "u2EtherType=0x%x", u2EtherType); + if (u2EtherType == ETH_P_ARP) + return TRUE; + else + return FALSE; +} +static u_int8_t data_is_ipv4_arp_req(struct sk_buff *skb) +{ + uint8_t *pPkt; + uint16_t u2OpCode; + + pPkt = skb->data; + u2OpCode = (pPkt[ETH_HLEN+6] << 8)| pPkt[ETH_HLEN+7]; + //DBGLOG(INIT, INFO, "u2OPCode:0x%x\n", u2OpCode); + if (u2OpCode == ARP_PRO_REQ) + return TRUE; + else + return FALSE; +} +static uint32_t get_arp_tgt_ip(struct sk_buff *skb) +{ + uint8_t *pPkt; + uint32_t u4TgtIp; + + pPkt = skb->data; + u4TgtIp = *(uint32_t *)(pPkt + ETH_HLEN + ARP_TARGET_IP_OFFSET); + return u4TgtIp; +} +static void arp_brust_opt_init(struct ADAPTER *adapter) +{ + struct arp_burst_stat *arp_b_s; + + if (adapter == NULL) { + DBGLOG(INIT, WARN, "arp brust opt init fail\n"); + return; + } + arp_b_s = &(adapter->arp_b_stat); + arp_b_s->begin = 0; + arp_b_s->brust = 10; + arp_b_s->brust_signify = 5; + arp_b_s->drop_count = 0; + arp_b_s->pass_count = 0; + arp_b_s->pass_signify_count = 0; + arp_b_s->interval = 100; //ms + arp_b_s->apIp = 0; + arp_b_s->gatewayIp = 0; +} +/* Xiaomi Add + * RETURNS: + * 0:Not limit + * packet isn't arp request or gateway and AP ip aren't 0 + * 1:limit based on brust count + * arp request and target ip is not gatway or AP IP + * 2:limit based on gateway burst count + * arp request and target ip is gatway or AP IP + */ +static int process_pkt_action(struct ADAPTER *adapter, struct sk_buff *skb) +{ + uint32_t u4TgtIp = 0; + struct arp_burst_stat *arp_b_s = &(adapter->arp_b_stat); + + if (arp_b_s->apIp == 0 && arp_b_s->gatewayIp == 0) + return 0; + if (data_is_ipv4_arp_pkt(skb) && data_is_ipv4_arp_req(skb)) { + u4TgtIp = get_arp_tgt_ip(skb); + + if (arp_b_s->apIp == u4TgtIp || arp_b_s->gatewayIp == u4TgtIp) + return 2; + return 1; + } + return 0; +} +/* Xiaomi Add + * RETURNS: + * 0 means drop arp request + * 1 means go ahead + */ +static int arp_rate_limit(struct ADAPTER *adapter, struct sk_buff *skb) +{ + struct arp_burst_stat *arp_b_s = NULL; + int ret; + int action; + + if (adapter == NULL) + return 1; + arp_b_s = &(adapter->arp_b_stat); + action = process_pkt_action(adapter, skb); + if (!action) + return 1; + // init fail, so don't drop arp request + if (arp_b_s->interval == 0 || arp_b_s->brust == 0 || arp_b_s->brust_signify == 0) { + DBGLOG_LIMITED(INIT, TRACE, "init fail\n"); + return 1; + } + if (arp_b_s->begin == 0) + arp_b_s->begin = kalGetTimeTick(); + if (CHECK_FOR_TIMEOUT(kalGetTimeTick(), arp_b_s->begin, arp_b_s->interval)) { + //if (time_is_before_jiffies(arp_b_s->begin + arp_b_s->interval)) { + if (arp_b_s->drop_count) { + DBGLOG_LIMITED(INIT, WARN, "%s: arp too frequency, drop count: %d", + __func__, arp_b_s->drop_count); + arp_b_s->drop_count = 0; + } + arp_b_s->begin = kalGetTimeTick(); + arp_b_s->pass_count = 0; + arp_b_s->pass_signify_count = 0; + + } + if (action == 1) { + if (arp_b_s->pass_count > arp_b_s->brust) { + arp_b_s->drop_count++; + ret = 0; + } else { + arp_b_s->pass_count++; + ret = 1; + } + } else { //for action == 2 + if (arp_b_s->pass_signify_count > arp_b_s->brust_signify) { + arp_b_s->drop_count++; + ret = 0; + } else { + arp_b_s->pass_signify_count++; + ret = 1; + } + + } + return ret; +} +#endif +/*----------------------------------------------------------------------------*/ +/* + * \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. + */ +/*----------------------------------------------------------------------------*/ +netdev_tx_t wlanHardStartXmit(struct sk_buff *prSkb, + struct net_device *prDev) +{ + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = + (struct NETDEV_PRIVATE_GLUE_INFO *) NULL; + struct GLUE_INFO *prGlueInfo = *((struct GLUE_INFO **) + netdev_priv(prDev)); + uint8_t ucBssIndex; + + ASSERT(prSkb); + ASSERT(prDev); + ASSERT(prGlueInfo); + + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prDev); + ASSERT(prNetDevPrivate->prGlueInfo == prGlueInfo); + ucBssIndex = prNetDevPrivate->ucBssIdx; + +#if CFG_SUPPORT_PASSPOINT + if (prGlueInfo->fgIsDad) { + /* kalPrint("[Passpoint R2] Due to ipv4_dad...TX is forbidden\n" + * ); + */ + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } + if (prGlueInfo->fgIs6Dad) { + /* kalPrint("[Passpoint R2] Due to ipv6_dad...TX is forbidden\n" + * ); + */ + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_CHIP_RESET_SUPPORT + if (!wlanIsDriverReady(prGlueInfo)) { + DBGLOG(INIT, WARN, + "u4ReadyFlag:%u, kalIsResetting():%d, dropping the packet\n", + prGlueInfo->u4ReadyFlag, kalIsResetting()); + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } +#endif + kalResetPacket(prGlueInfo, (void *) prSkb); +#if (CFG_SUPPORT_STATISTICS == 1) + STATS_TX_TIME_ARRIVE(prSkb); +#endif +#if ARP_BRUST_OPTIMIZE + if (!arp_rate_limit(prGlueInfo->prAdapter, prSkb)) { + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } +#endif + + if (kalHardStartXmit(prSkb, prDev, prGlueInfo, + ucBssIndex) == WLAN_STATUS_SUCCESS) { + /* Successfully enqueue to Tx queue */ + /* Successfully enqueue to Tx queue */ + if (netif_carrier_ok(prDev)) + kalPerMonStart(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) +{ + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate; + + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prDev); + kalMemCopy(&prNetDevPrivate->stats, &prDev->stats, + sizeof(struct net_device_stats)); +#if CFG_MTK_MCIF_WIFI_SUPPORT + mddpGetMdStats(prDev); +#endif + + return (struct net_device_stats *) kalGetStats(prDev); +} /* end of wlanGetStats() */ + +void wlanDebugInit(void) +{ + /* Set the initial debug level of each module */ +#if DBG + /* enable all */ + wlanSetDriverDbgLevel(DBG_ALL_MODULE_IDX, DBG_CLASS_MASK); +#else +#ifdef CFG_DEFAULT_DBG_LEVEL + wlanSetDriverDbgLevel(DBG_ALL_MODULE_IDX, + CFG_DEFAULT_DBG_LEVEL); +#else + wlanSetDriverDbgLevel(DBG_ALL_MODULE_IDX, + DBG_LOG_LEVEL_DEFAULT); +#endif +#endif /* DBG */ + + LOG_FUNC("Reset ALL DBG module log level to DEFAULT!"); + +} + +#if CFG_SUPPORT_RX_GRO +/*----------------------------------------------------------------------------*/ +/*! + * \brief A method of callback function for napi struct + * + * It just return false because driver indicate Rx packet directly. + * + * \param[in] napi Pointer to struct napi_struct. + * \param[in] budget Polling time interval. + * + * \return false + */ +/*----------------------------------------------------------------------------*/ +static int kal_napi_poll(struct napi_struct *napi, int budget) +{ + return 0; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \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) +{ + struct GLUE_INFO *prGlueInfo = NULL; +#if CFG_SUPPORT_RX_GRO + uint8_t ucBssIndex; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = NULL; +#endif + if (!prDev) + return -ENXIO; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + INIT_DELAYED_WORK(&workq, wlanSetMulticastListWorkQueue); + + /* 20150205 work queue for sched_scan */ + INIT_DELAYED_WORK(&sched_workq, + wlanSchedScanStoppedWorkQueue); + + /* 20161024 init wow port setting */ +#if CFG_WOW_SUPPORT + kalWowInit(prGlueInfo); +#endif + +#if CFG_SUPPORT_RX_GRO + /* Register GRO function to kernel */ + ucBssIndex = wlanGetBssIdx(prDev); + prDev->features |= NETIF_F_GRO; + prDev->hw_features |= NETIF_F_GRO; + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prDev); + spin_lock_init(&prNetDevPrivate->napi_spinlock); + prNetDevPrivate->napi.dev = prDev; + netif_napi_add(prNetDevPrivate->napi.dev, + &prNetDevPrivate->napi, kal_napi_poll, 64); + DBGLOG(INIT, INFO, + "GRO interface added successfully:%p\n", prDev); +#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) +{ +} /* end of wlanUninit() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief A method of struct net_device, to set the randomized mac address + * + * This method is called before Wifi Framework requests a new conenction with + * enabled feature "Connected Random Mac". + * + * \param[in] ndev Pointer to struct net_device. + * \param[in] addr Randomized Mac address passed from WIFI framework. + * + * \return int. + */ +/*----------------------------------------------------------------------------*/ +static int wlanSetMacAddress(struct net_device *ndev, void *addr) +{ + struct ADAPTER *prAdapter = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct sockaddr *sa = NULL; + struct BSS_INFO *prAisBssInfo = NULL; + + /********************************************************************** + * Check if kernel passes valid data to us * + ********************************************************************** + */ + if (!ndev || !addr) { + DBGLOG(INIT, ERROR, "Set macaddr with ndev(%d) and addr(%d)\n", + (ndev == NULL) ? 0 : 1, (addr == NULL) ? 0 : 1); + return -EINVAL; + } + + /********************************************************************** + * 1. Change OwnMacAddr which will be updated to FW through * + * rlmActivateNetwork later. * + * 2. Change dev_addr stored in kernel to notify framework that the * + * mac addr has been changed and what the new value is. * + ********************************************************************** + */ + sa = (struct sockaddr *)addr; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(ndev)); + + if (!prGlueInfo || !prGlueInfo->u4ReadyFlag) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -EFAULT; + } + + prAdapter = prGlueInfo->prAdapter; + prAisBssInfo = aisGetAisBssInfo(prAdapter, + wlanGetBssIdx(ndev)); + + COPY_MAC_ADDR(prAisBssInfo->aucOwnMacAddr, sa->sa_data); + COPY_MAC_ADDR(ndev->dev_addr, sa->sa_data); + DBGLOG(INIT, INFO, + "[wlan%d] Set connect random macaddr to " MACSTR ".\n", + prAisBssInfo->ucBssIndex, + MAC2STR(prAisBssInfo->aucOwnMacAddr)); + + return WLAN_STATUS_SUCCESS; +} /* end of wlanSetMacAddr() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief A function for prDev->open + * + * \param[in] prDev Pointer to struct net_device. + * + * \retval 0 The execution of wlanOpen succeeds. + * \retval < 0 The execution of wlanOpen failed. + */ +/*----------------------------------------------------------------------------*/ +static int wlanOpen(struct net_device *prDev) +{ + ASSERT(prDev); + + netif_tx_start_all_queues(prDev); + + return 0; /* success */ +} /* end of wlanOpen() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief A function for prDev->stop + * + * \param[in] prDev Pointer to struct net_device. + * + * \retval 0 The execution of wlanStop succeeds. + * \retval < 0 The execution of wlanStop failed. + */ +/*----------------------------------------------------------------------------*/ +static int wlanStop(struct net_device *prDev) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prDev); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + + /* CFG80211 down */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if (prGlueInfo->prScanRequest) { + kalCfg80211ScanDone(prGlueInfo->prScanRequest, TRUE); + prGlueInfo->prScanRequest = NULL; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + netif_tx_stop_all_queues(prDev); + + return 0; /* success */ +} /* end of wlanStop() */ + +#if CFG_SUPPORT_SNIFFER +static int wlanMonOpen(struct net_device *prDev) +{ + ASSERT(prDev); + + netif_tx_start_all_queues(prDev); + + return 0; /* success */ +} + +static int wlanMonStop(struct net_device *prDev) +{ + ASSERT(prDev); + + netif_tx_stop_all_queues(prDev); + + return 0; /* success */ +} + +static const struct net_device_ops wlan_mon_netdev_ops = { + .ndo_open = wlanMonOpen, + .ndo_stop = wlanMonStop, +}; + +void wlanMonWorkHandler(struct work_struct *work) +{ + struct GLUE_INFO *prGlueInfo; + + prGlueInfo = container_of(work, struct GLUE_INFO, monWork); + + if (prGlueInfo->fgIsEnableMon) { + if (prGlueInfo->prMonDevHandler) + return; +#if KERNEL_VERSION(3, 18, 0) <= LINUX_VERSION_CODE + prGlueInfo->prMonDevHandler = + alloc_netdev_mq(sizeof(struct NETDEV_PRIVATE_GLUE_INFO), + NIC_MONITOR_INF_NAME, + NET_NAME_PREDICTABLE, ether_setup, + CFG_MAX_TXQ_NUM); +#else + prGlueInfo->prMonDevHandler = + alloc_netdev_mq(sizeof(struct NETDEV_PRIVATE_GLUE_INFO), + NIC_MONITOR_INF_NAME, + ether_setup, CFG_MAX_TXQ_NUM); +#endif + if (prGlueInfo->prMonDevHandler == NULL) { + DBGLOG(INIT, ERROR, + "wlanMonWorkHandler: Allocated prMonDevHandler context FAIL.\n"); + return; + } + + ((struct NETDEV_PRIVATE_GLUE_INFO *) netdev_priv( + prGlueInfo->prMonDevHandler))->prGlueInfo = prGlueInfo; + prGlueInfo->prMonDevHandler->type = + ARPHRD_IEEE80211_RADIOTAP; + prGlueInfo->prMonDevHandler->netdev_ops = + &wlan_mon_netdev_ops; + netif_carrier_off(prGlueInfo->prMonDevHandler); + netif_tx_stop_all_queues(prGlueInfo->prMonDevHandler); + kalResetStats(prGlueInfo->prMonDevHandler); + + if (register_netdev(prGlueInfo->prMonDevHandler) < 0) { + DBGLOG(INIT, ERROR, + "wlanMonWorkHandler: Registered prMonDevHandler context FAIL.\n"); + free_netdev(prGlueInfo->prMonDevHandler); + prGlueInfo->prMonDevHandler = NULL; + } + DBGLOG(INIT, INFO, + "wlanMonWorkHandler: Registered prMonDevHandler context DONE.\n"); + } else { + if (prGlueInfo->prMonDevHandler) { + unregister_netdev(prGlueInfo->prMonDevHandler); + prGlueInfo->prMonDevHandler = NULL; + DBGLOG(INIT, INFO, + "wlanMonWorkHandler: unRegistered prMonDevHandler context DONE.\n"); + } + } +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \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(struct GLUE_INFO *prGlueInfo) +{ + uint8_t i, j; + uint8_t ucNumOfChannel; + struct RF_CHANNEL_INFO aucChannelList[ARRAY_SIZE( + mtk_2ghz_channels) + ARRAY_SIZE(mtk_5ghz_channels)]; + + kalMemZero(aucChannelList, sizeof(aucChannelList)); + + /* 1. Disable all channels */ + for (i = 0; i < ARRAY_SIZE(mtk_2ghz_channels); i++) { + mtk_2ghz_channels[i].flags |= IEEE80211_CHAN_DISABLED; + mtk_2ghz_channels[i].orig_flags |= IEEE80211_CHAN_DISABLED; + } + + for (i = 0; i < ARRAY_SIZE(mtk_5ghz_channels); i++) { + mtk_5ghz_channels[i].flags |= IEEE80211_CHAN_DISABLED; + mtk_5ghz_channels[i].orig_flags |= IEEE80211_CHAN_DISABLED; + } + + /* 2. Get current domain channel list */ + rlmDomainGetChnlList(prGlueInfo->prAdapter, + BAND_NULL, FALSE, + ARRAY_SIZE(mtk_2ghz_channels) + ARRAY_SIZE( + mtk_5ghz_channels), + &ucNumOfChannel, aucChannelList); + + /* 3. Enable specific channel based on domain channel list */ + for (i = 0; i < ucNumOfChannel; i++) { + switch (aucChannelList[i].eBand) { + case BAND_2G4: + for (j = 0; j < ARRAY_SIZE(mtk_2ghz_channels); j++) { + if (mtk_2ghz_channels[j].hw_value == + aucChannelList[i].ucChannelNum) { + mtk_2ghz_channels[j].flags &= + ~IEEE80211_CHAN_DISABLED; + mtk_2ghz_channels[j].orig_flags &= + ~IEEE80211_CHAN_DISABLED; + break; + } + } + break; + + case BAND_5G: + for (j = 0; j < ARRAY_SIZE(mtk_5ghz_channels); j++) { + if (mtk_5ghz_channels[j].hw_value == + aucChannelList[i].ucChannelNum) { + mtk_5ghz_channels[j].flags &= + ~IEEE80211_CHAN_DISABLED; + mtk_5ghz_channels[j].orig_flags &= + ~IEEE80211_CHAN_DISABLED; + mtk_5ghz_channels[j].dfs_state = + (aucChannelList[i].eDFS) ? + NL80211_DFS_USABLE : + NL80211_DFS_UNAVAILABLE; + if (mtk_5ghz_channels[j].dfs_state == + NL80211_DFS_USABLE) + mtk_5ghz_channels[j].flags |= + IEEE80211_CHAN_RADAR; + else + mtk_5ghz_channels[j].flags &= + ~IEEE80211_CHAN_RADAR; + break; + } + } + break; + + default: + DBGLOG(INIT, WARN, "Unknown band %d\n", + aucChannelList[i].eBand); + break; + } + } + +} + +#if CFG_SUPPORT_SAP_DFS_CHANNEL +static u_int8_t wlanIsAdjacentChnl(struct GL_P2P_INFO *prGlueP2pInfo, + uint32_t u4CenterFreq, uint8_t ucBandWidth, + enum ENUM_CHNL_EXT eBssSCO, uint8_t ucAdjacentChannel) +{ + uint32_t u4AdjacentFreq = 0; + uint32_t u4BandWidth = 20; + uint32_t u4StartFreq, u4EndFreq; + struct ieee80211_channel *chnl = NULL; + + u4AdjacentFreq = nicChannelNum2Freq(ucAdjacentChannel) / 1000; + + DBGLOG(INIT, TRACE, + "p2p: %p, center_freq: %d, bw: %d, sco: %d, ad_freq: %d", + prGlueP2pInfo, u4CenterFreq, ucBandWidth, eBssSCO, + u4AdjacentFreq); + + if (!prGlueP2pInfo) + return FALSE; + + if (ucBandWidth == VHT_OP_CHANNEL_WIDTH_20_40 && + eBssSCO == CHNL_EXT_SCN) + return FALSE; + + if (!u4CenterFreq) + return FALSE; + + if (!u4AdjacentFreq) + return FALSE; + + switch (ucBandWidth) { + case VHT_OP_CHANNEL_WIDTH_20_40: + u4BandWidth = 40; + break; + case VHT_OP_CHANNEL_WIDTH_80: + u4BandWidth = 80; + break; + default: + DBGLOG(INIT, WARN, "unsupported bandwidth: %d", ucBandWidth); + return FALSE; + } + u4StartFreq = u4CenterFreq - u4BandWidth / 2 + 10; + u4EndFreq = u4CenterFreq + u4BandWidth / 2 - 10; + DBGLOG(INIT, TRACE, "bw: %d, s_freq: %d, e_freq: %d", + u4BandWidth, u4StartFreq, u4EndFreq); + if (u4AdjacentFreq < u4StartFreq || u4AdjacentFreq > u4EndFreq) + return FALSE; + + /* check valid channel */ + chnl = ieee80211_get_channel(prGlueP2pInfo->prWdev->wiphy, + u4AdjacentFreq); + if (!chnl) { + DBGLOG(INIT, WARN, "invalid channel for freq: %d", + u4AdjacentFreq); + return FALSE; + } + return TRUE; +} + +void wlanUpdateDfsChannelTable(struct GLUE_INFO *prGlueInfo, + uint8_t ucRoleIdx, uint8_t ucChannel, uint8_t ucBandWidth, + enum ENUM_CHNL_EXT eBssSCO, uint32_t u4CenterFreq) +{ + struct GL_P2P_INFO *prGlueP2pInfo = NULL; + uint8_t i, j; + uint8_t ucNumOfChannel; + struct RF_CHANNEL_INFO aucChannelList[ + ARRAY_SIZE(mtk_5ghz_channels)] = {}; + + DBGLOG(INIT, INFO, "r: %d, chnl %u, b: %d, s: %d, freq: %d\n", + ucRoleIdx, ucChannel, ucBandWidth, eBssSCO, + u4CenterFreq); + + /* 1. Get current domain DFS channel list */ + rlmDomainGetDfsChnls(prGlueInfo->prAdapter, + ARRAY_SIZE(mtk_5ghz_channels), + &ucNumOfChannel, aucChannelList); + + if (ucRoleIdx >= 0 && ucRoleIdx < KAL_P2P_NUM) + prGlueP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + + /* 2. Enable specific channel based on domain channel list */ + for (i = 0; i < ucNumOfChannel; i++) { + for (j = 0; j < ARRAY_SIZE(mtk_5ghz_channels); j++) { + if (aucChannelList[i].ucChannelNum != + mtk_5ghz_channels[j].hw_value) + continue; + + if ((aucChannelList[i].ucChannelNum == ucChannel) || + wlanIsAdjacentChnl(prGlueP2pInfo, + u4CenterFreq, + ucBandWidth, + eBssSCO, + aucChannelList[i].ucChannelNum)) { + mtk_5ghz_channels[j].dfs_state + = NL80211_DFS_AVAILABLE; + mtk_5ghz_channels[j].flags &= + ~IEEE80211_CHAN_RADAR; + mtk_5ghz_channels[j].orig_flags &= + ~IEEE80211_CHAN_RADAR; + DBGLOG(INIT, INFO, + "ch (%d), force NL80211_DFS_AVAILABLE.\n", + aucChannelList[i].ucChannelNum); + } else { + mtk_5ghz_channels[j].dfs_state + = NL80211_DFS_USABLE; + mtk_5ghz_channels[j].flags |= + IEEE80211_CHAN_RADAR; + mtk_5ghz_channels[j].orig_flags |= + IEEE80211_CHAN_RADAR; + DBGLOG(INIT, TRACE, + "ch (%d), force NL80211_DFS_USABLE.\n", + aucChannelList[i].ucChannelNum); + } + } + } +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \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 int32_t wlanNetRegister(struct wireless_dev *prWdev) +{ + struct GLUE_INFO *prGlueInfo; + int32_t i4DevIdx = -1; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = + (struct NETDEV_PRIVATE_GLUE_INFO *) NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4Idx = 0; + + ASSERT(prWdev); + + do { + if (!prWdev) + break; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(prWdev->wiphy); + prAdapter = prGlueInfo->prAdapter; + i4DevIdx = wlanGetDevIdx(prWdev->netdev); + if (i4DevIdx < 0) { + DBGLOG(INIT, ERROR, "net_device number exceeds!\n"); + break; + } + + if (prAdapter && prAdapter->rWifiVar.ucWow) + kalInitDevWakeup(prGlueInfo->prAdapter, + wiphy_dev(prWdev->wiphy)); + + for (u4Idx = 0; u4Idx < KAL_AIS_NUM; u4Idx++) { + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(gprWdev[u4Idx]->netdev); + ASSERT(prNetDevPrivate->prGlueInfo == prGlueInfo); + prNetDevPrivate->ucBssIdx = u4Idx; +#if CFG_ENABLE_UNIFY_WIPHY + prNetDevPrivate->ucIsP2p = FALSE; +#endif +#if CFG_MTK_MCIF_WIFI_SUPPORT + /* only wlan0 supports mddp */ + prNetDevPrivate->ucMddpSupport = (u4Idx == 0); +#else + prNetDevPrivate->ucMddpSupport = FALSE; +#endif + wlanBindBssIdxToNetInterface(prGlueInfo, + u4Idx, + (void *)gprWdev[u4Idx]->netdev); +#if CFG_SUPPORT_PERSIST_NETDEV + if (gprNetdev[u4Idx]->reg_state == NETREG_REGISTERED) + continue; +#endif + if (register_netdev(gprWdev[u4Idx]->netdev) + < 0) { + DBGLOG(INIT, ERROR, + "Register net_device %d failed\n", + u4Idx); + wlanClearDevIdx( + gprWdev[u4Idx]->netdev); + i4DevIdx = -1; + break; + } + } + + if (i4DevIdx != -1) + prGlueInfo->fgIsRegistered = TRUE; + else { + /* Unregister the registered netdev if one of netdev + * registered fail + */ + for (u4Idx = 0; u4Idx < KAL_AIS_NUM; u4Idx++) { + if (!gprWdev[u4Idx] || !gprWdev[u4Idx]->netdev) + continue; + if (gprWdev[u4Idx]->netdev->reg_state != + NETREG_REGISTERED) + continue; + wlanClearDevIdx(gprWdev[u4Idx]->netdev); + unregister_netdev(gprWdev[u4Idx]->netdev); + } + } + } 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) +{ + struct GLUE_INFO *prGlueInfo; + + if (!prWdev) { + DBGLOG(INIT, ERROR, "The device context is NULL\n"); + return; + } + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(prWdev->wiphy); + +#if !CFG_SUPPORT_PERSIST_NETDEV + { + uint32_t u4Idx = 0; + + for (u4Idx = 0; u4Idx < KAL_AIS_NUM; u4Idx++) { + if (gprWdev[u4Idx] && gprWdev[u4Idx]->netdev) { + wlanClearDevIdx(gprWdev[u4Idx]->netdev); + unregister_netdev(gprWdev[u4Idx]->netdev); + } + } + + prGlueInfo->fgIsRegistered = FALSE; + } +#endif + +#if CFG_SUPPORT_SNIFFER + if (prGlueInfo->prMonDevHandler) { + unregister_netdev(prGlueInfo->prMonDevHandler); + /* FIXME: Why not free_netdev()? */ + prGlueInfo->prMonDevHandler = NULL; + } + prGlueInfo->fgIsEnableMon = FALSE; +#endif + +} /* end of wlanNetUnregister() */ + +static const struct net_device_ops wlan_netdev_ops = { + .ndo_open = wlanOpen, + .ndo_stop = wlanStop, + .ndo_set_rx_mode = wlanSetMulticastList, + .ndo_get_stats = wlanGetStats, + .ndo_do_ioctl = wlanDoIOCTL, + .ndo_start_xmit = wlanHardStartXmit, + .ndo_init = wlanInit, + .ndo_uninit = wlanUninit, + .ndo_select_queue = wlanSelectQueue, + .ndo_set_mac_address = wlanSetMacAddress, +}; + +#if CFG_ENABLE_UNIFY_WIPHY +const struct net_device_ops *wlanGetNdevOps(void) +{ + return &wlan_netdev_ops; +} +#endif +void wlanNvramSetState(enum ENUM_NVRAM_STATE state) +{ + g_NvramFsm = state; +} +enum ENUM_NVRAM_STATE wlanNvramGetState(void) +{ + return g_NvramFsm; +} +#if CFG_WLAN_ASSISTANT_NVRAM +static void wlanNvramUpdateOnTestMode(void) +{ + struct GLUE_INFO *prGlueInfo = NULL; + enum ENUM_NVRAM_STATE nvrmState; + struct REG_INFO *prRegInfo = NULL; + struct ADAPTER *prAdapter = NULL; + + /* <1> Sanity Check */ + if (u4WlanDevNum == 0) { + DBGLOG(INIT, ERROR, + "wlanNvramUpdateOnTestMode invalid!!\n"); + return; + } + + prGlueInfo = wlanGetGlueInfo(); + if (prGlueInfo == NULL) { + DBGLOG(INIT, WARN, + "prGlueInfo invalid!!\n"); + return; + } + prAdapter = prGlueInfo->prAdapter; + if (prAdapter == NULL) { + DBGLOG(INIT, WARN, + "prAdapter invalid!!\n"); + return; + } + prRegInfo = &prGlueInfo->rRegInfo; + if (prRegInfo == NULL) { + DBGLOG(INIT, WARN, + "prRegInfo invalid!!\n"); + return; + } + + if (prAdapter->fgTestMode == FALSE) { + DBGLOG(INIT, INFO, + "by-pass on Normal mode\n"); + return; + } + + nvrmState = wlanNvramGetState(); + + if (nvrmState == NVRAM_STATE_READY) { + DBGLOG(RFTEST, INFO, + "update nvram to fw on test mode!\n"); + + if (kalIsConfigurationExist(prGlueInfo) == TRUE) + wlanLoadManufactureData(prAdapter, prRegInfo); + else + DBGLOG(INIT, WARN, "%s: load manufacture data fail\n", + __func__); + } +} +static uint8_t wlanNvramBufHandler(void *ctx, + const char *buf, + uint16_t length) +{ + DBGLOG(INIT, INFO, "buf = %p, length = %u\n", buf, length); + if (buf == NULL || length <= 0) + return -EFAULT; + + if (length > sizeof(g_aucNvram)) { + DBGLOG(INIT, ERROR, "is over nvrm size %d\n", + sizeof(g_aucNvram)); + return -EINVAL; + } + + kalMemZero(&g_aucNvram, sizeof(g_aucNvram)); + if (copy_from_user(g_aucNvram, buf, length)) { + DBGLOG(INIT, ERROR, "copy nvram fail\n"); + g_NvramFsm = NVRAM_STATE_INIT; + return -EINVAL; + } + + g_NvramFsm = NVRAM_STATE_READY; + + /*do nvram update on test mode then driver sent new NVRAM to FW*/ + wlanNvramUpdateOnTestMode(); + + return 0; +} + +#endif + +static void wlanCreateWirelessDevice(void) +{ + struct wiphy *prWiphy = NULL; + struct wireless_dev *prWdev[KAL_AIS_NUM] = {NULL}; + unsigned int u4SupportSchedScanFlag = 0; + uint32_t u4Idx = 0; + + /* 4 <1.1> Create wireless_dev */ + for (u4Idx = 0; u4Idx < KAL_AIS_NUM; u4Idx++) { + prWdev[u4Idx] = kzalloc(sizeof(struct wireless_dev), + GFP_KERNEL); + if (!prWdev[u4Idx]) { + DBGLOG(INIT, ERROR, + "Allocating memory to wireless_dev context failed\n"); + return; + } + prWdev[u4Idx]->iftype = NL80211_IFTYPE_STATION; + } + /* 4 <1.2> Create wiphy */ +#if CFG_ENABLE_UNIFY_WIPHY + prWiphy = wiphy_new(&mtk_cfg_ops, sizeof(struct GLUE_INFO)); +#else + prWiphy = wiphy_new(&mtk_wlan_ops, + sizeof(struct GLUE_INFO)); +#endif + + if (!prWiphy) { + DBGLOG(INIT, ERROR, + "Allocating memory to wiphy device failed\n"); + goto free_wdev; + } + + /* 4 <1.3> configure wireless_dev & wiphy */ + prWiphy->iface_combinations = p_mtk_iface_combinations_sta; + prWiphy->n_iface_combinations = + mtk_iface_combinations_sta_num; + prWiphy->max_scan_ssids = SCN_SSID_MAX_NUM + + 1; /* include one wildcard ssid */ + prWiphy->max_scan_ie_len = 512; +#if CFG_SUPPORT_SCHED_SCAN + prWiphy->max_sched_scan_ssids = + CFG_SCAN_HIDDEN_SSID_MAX_NUM; + prWiphy->max_match_sets = + CFG_SCAN_SSID_MATCH_MAX_NUM; + prWiphy->max_sched_scan_ie_len = CFG_CFG80211_IE_BUF_LEN; +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE + /* In kernel 4.12 or newer, + * this is obsoletes - WIPHY_FLAG_SUPPORTS_SCHED_SCAN + */ + prWiphy->max_sched_scan_reqs = 1; +#else + u4SupportSchedScanFlag = + WIPHY_FLAG_SUPPORTS_SCHED_SCAN; +#endif +#endif /* CFG_SUPPORT_SCHED_SCAN */ + prWiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); + prWiphy->bands[KAL_BAND_2GHZ] = &mtk_band_2ghz; + /* always assign 5Ghz bands here, if the chip is not support 5Ghz, + * bands[KAL_BAND_5GHZ] will be assign to NULL + */ + prWiphy->bands[KAL_BAND_5GHZ] = &mtk_band_5ghz; + prWiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + prWiphy->cipher_suites = (const u32 *)mtk_cipher_suites; + prWiphy->n_cipher_suites = ARRAY_SIZE(mtk_cipher_suites); + prWiphy->flags = WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL + | u4SupportSchedScanFlag; + +#if (CFG_SUPPORT_ROAMING == 1) + prWiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; +#endif /* CFG_SUPPORT_ROAMING */ + +#if KERNEL_VERSION(3, 14, 0) > CFG80211_VERSION_CODE + prWiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; +#else + prWiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; +#if (CFG_SUPPORT_DFS_MASTER == 1) + prWiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE + prWiphy->max_num_csa_counters = 2; +#endif +#endif /* CFG_SUPPORT_DFS_MASTER */ +#endif + +#if KERNEL_VERSION(3, 14, 0) < CFG80211_VERSION_CODE + prWiphy->max_ap_assoc_sta = P2P_MAXIMUM_CLIENT_COUNT; +#endif + + cfg80211_regd_set_wiphy(prWiphy); + +#if (CFG_SUPPORT_TDLS == 1) + TDLSEX_WIPHY_FLAGS_INIT(prWiphy->flags); +#endif /* CFG_SUPPORT_TDLS */ + prWiphy->max_remain_on_channel_duration = 5000; + prWiphy->mgmt_stypes = mtk_cfg80211_ais_default_mgmt_stypes; + +#if (CFG_SUPPORT_SCAN_RANDOM_MAC && \ + (KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE)) + prWiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; + prWiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR; +#endif + +#if KERNEL_VERSION(4, 10, 0) < CFG80211_VERSION_CODE + wiphy_ext_feature_set(prWiphy, NL80211_EXT_FEATURE_LOW_SPAN_SCAN); +#endif + prWiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER; + +#if CFG_SUPPORT_WPA3 + prWiphy->features |= NL80211_FEATURE_SAE; +#endif +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE + prWiphy->vendor_commands = mtk_wlan_vendor_ops; + prWiphy->n_vendor_commands = sizeof(mtk_wlan_vendor_ops) / + sizeof(struct wiphy_vendor_command); + prWiphy->vendor_events = mtk_wlan_vendor_events; + prWiphy->n_vendor_events = ARRAY_SIZE( + mtk_wlan_vendor_events); +#endif + /* 4 <1.4> wowlan support */ +#ifdef CONFIG_PM +#if KERNEL_VERSION(3, 11, 0) <= CFG80211_VERSION_CODE + prWiphy->wowlan = &mtk_wlan_wowlan_support; +#else + kalMemCopy(&prWiphy->wowlan, &mtk_wlan_wowlan_support, + sizeof(struct wiphy_wowlan_support)); +#endif +#endif + +#ifdef CONFIG_CFG80211_WEXT + /* 4 <1.5> Use wireless extension to replace IOCTL */ + +#if CFG_ENABLE_UNIFY_WIPHY + prWiphy->wext = NULL; +#else + prWiphy->wext = &wext_handler_def; +#endif +#endif + /* initialize semaphore for halt control */ + sema_init(&g_halt_sem, 1); + +#if CFG_ENABLE_UNIFY_WIPHY + prWiphy->iface_combinations = p_mtk_iface_combinations_p2p; + prWiphy->n_iface_combinations = + mtk_iface_combinations_p2p_num; + + prWiphy->interface_modes |= BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_P2P_CLIENT) | + BIT(NL80211_IFTYPE_P2P_GO) | + BIT(NL80211_IFTYPE_STATION); + prWiphy->software_iftypes |= BIT(NL80211_IFTYPE_P2P_DEVICE); + prWiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; + prWiphy->flags |= WIPHY_FLAG_HAVE_AP_SME; + prWiphy->ap_sme_capa = 1; +#endif + +#if CFG_ENABLE_OFFCHANNEL_TX + prWiphy->flags |= WIPHY_FLAG_OFFCHAN_TX; +#endif /* CFG_ENABLE_OFFCHANNEL_TX */ + +#if CFG_SUPPORT_RM_BEACON_REPORT_BY_SUPPLICANT + /* Enable following to indicate supplicant + * to support Beacon report feature + */ + prWiphy->features |= NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES; + prWiphy->features |= NL80211_FEATURE_QUIET; +#endif + + if (wiphy_register(prWiphy) < 0) { + DBGLOG(INIT, ERROR, "wiphy_register error\n"); + goto free_wiphy; + } + for (u4Idx = 0; u4Idx < KAL_AIS_NUM; u4Idx++) { + prWdev[u4Idx]->wiphy = prWiphy; + gprWdev[u4Idx] = prWdev[u4Idx]; + } +#if CFG_WLAN_ASSISTANT_NVRAM + register_file_buf_handler(wlanNvramBufHandler, (void *)NULL, + ENUM_BUF_TYPE_NVRAM); +#endif + DBGLOG(INIT, INFO, "Create wireless device success\n"); + return; + +free_wiphy: + wiphy_free(prWiphy); +free_wdev: + for (u4Idx = 0; u4Idx < KAL_AIS_NUM; u4Idx++) + kfree(prWdev[u4Idx]); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Destroy all wdev (including the P2P device), and unregister wiphy + * + * \param (none) + * + * \return (none) + * + */ +/*----------------------------------------------------------------------------*/ +static void wlanDestroyAllWdev(void) +{ +#if CFG_ENABLE_UNIFY_WIPHY + /* There is only one wiphy, avoid that double free the wiphy */ + struct wiphy *wiphy = NULL; +#endif +#if CFG_ENABLE_WIFI_DIRECT + int i = 0; +#endif + +#if CFG_ENABLE_WIFI_DIRECT + /* free P2P wdev */ + for (i = 0; i < KAL_P2P_NUM; i++) { + if (gprP2pRoleWdev[i] == NULL) + continue; +#if CFG_ENABLE_UNIFY_WIPHY + if (wlanIsAisDev(gprP2pRoleWdev[i]->netdev)) { + /* This is AIS/AP Interface */ + gprP2pRoleWdev[i] = NULL; + continue; + } +#endif + /* Do wiphy_unregister here. Take care the case that the + * gprP2pRoleWdev[i] is created by the cfg80211 add iface ops, + * And the base P2P dev is in the gprP2pWdev. + * Expect that new created gprP2pRoleWdev[i] is freed in + * unregister_netdev/mtk_vif_destructor. And gprP2pRoleWdev[i] + * is reset as gprP2pWdev in mtk_vif_destructor. + */ + if (gprP2pRoleWdev[i] == gprP2pWdev) + gprP2pWdev = NULL; + +#if CFG_ENABLE_UNIFY_WIPHY + wiphy = gprP2pRoleWdev[i]->wiphy; +#else + set_wiphy_dev(gprP2pRoleWdev[i]->wiphy, NULL); + wiphy_unregister(gprP2pRoleWdev[i]->wiphy); + wiphy_free(gprP2pRoleWdev[i]->wiphy); +#endif + + kfree(gprP2pRoleWdev[i]); + gprP2pRoleWdev[i] = NULL; + } + + if (gprP2pWdev != NULL) { + /* This case is that gprP2pWdev isn't equal to gprP2pRoleWdev[0] + * . The gprP2pRoleWdev[0] is created in the p2p cfg80211 add + * iface ops. The two wdev use the same wiphy. Don't double + * free the same wiphy. + * This part isn't expect occur. Because p2pNetUnregister should + * unregister_netdev the new created wdev, and gprP2pRoleWdev[0] + * is reset as gprP2pWdev. + */ +#if CFG_ENABLE_UNIFY_WIPHY + wiphy = gprP2pWdev->wiphy; +#endif + + kfree(gprP2pWdev); + gprP2pWdev = NULL; + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + + /* free AIS wdev */ + if (gprWdev[0]) { +#if CFG_ENABLE_UNIFY_WIPHY + wiphy = wlanGetWiphy(); +#else + /* trunk doesn't do set_wiphy_dev, but trunk-ce1 does. */ + /* set_wiphy_dev(gprWdev->wiphy, NULL); */ + wiphy_unregister(gprWdev[0]->wiphy); + wiphy_free(gprWdev[0]->wiphy); +#endif + + for (i = 0; i < KAL_AIS_NUM; i++) { + kfree(gprWdev[i]); + gprWdev[i] = NULL; + } + } + +#if CFG_ENABLE_UNIFY_WIPHY + /* unregister & free wiphy */ + if (wiphy) { + /* set_wiphy_dev(wiphy, NULL): set the wiphy->dev->parent = NULL + * The trunk-ce1 does this, but the trunk seems not. + */ + /* set_wiphy_dev(wiphy, NULL); */ + wiphy_unregister(wiphy); + wiphy_free(wiphy); + } +#endif +} + +void wlanWakeLockInit(struct GLUE_INFO *prGlueInfo) +{ +#ifdef CONFIG_ANDROID + KAL_WAKE_LOCK_INIT(NULL, prGlueInfo->rIntrWakeLock, + "WLAN interrupt"); + KAL_WAKE_LOCK_INIT(NULL, prGlueInfo->rTimeoutWakeLock, + "WLAN timeout"); +#endif +} + +void wlanWakeLockUninit(struct GLUE_INFO *prGlueInfo) +{ +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + if (KAL_WAKE_LOCK_ACTIVE(NULL, prGlueInfo->rIntrWakeLock)) + KAL_WAKE_UNLOCK(NULL, prGlueInfo->rIntrWakeLock); + KAL_WAKE_LOCK_DESTROY(NULL, prGlueInfo->rIntrWakeLock); + + if (KAL_WAKE_LOCK_ACTIVE(NULL, + prGlueInfo->rTimeoutWakeLock)) + KAL_WAKE_UNLOCK(NULL, prGlueInfo->rTimeoutWakeLock); + KAL_WAKE_LOCK_DESTROY(NULL, prGlueInfo->rTimeoutWakeLock); +#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]; +struct wireless_dev *wlanNetCreate(void *pvData, + void *pvDriverData) +{ + struct wireless_dev *prWdev = gprWdev[0]; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t i; + struct device *prDev; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = + (struct NETDEV_PRIVATE_GLUE_INFO *) NULL; + struct mt66xx_chip_info *prChipInfo; +#if CFG_ENABLE_UNIFY_WIPHY + struct wiphy *prWiphy = NULL; +#endif + + uint8_t *prInfName = NULL; + + if (prWdev == NULL) { + DBGLOG(INIT, ERROR, + "No wireless dev exist, abort power on\n"); + return NULL; + } + +#if CFG_ENABLE_UNIFY_WIPHY + /* The gprWdev is created at initWlan() and isn't reset when the + * disconnection occur. That cause some issue. + */ + prWiphy = prWdev->wiphy; + for (i = 0; i < KAL_AIS_NUM; i++) { + if (gprWdev[i] +#if CFG_SUPPORT_PERSIST_NETDEV + && !gprNetdev[i] +#endif + ) { + memset(gprWdev[i], 0, sizeof(struct wireless_dev)); + gprWdev[i]->wiphy = prWiphy; + gprWdev[i]->iftype = NL80211_IFTYPE_STATION; + } + } + +#if (CFG_SUPPORT_SINGLE_SKU == 1) + /* XXX: ref from cfg80211_regd_set_wiphy(). + * The error case: Sometimes after unplug/plug usb, the wlan0 STA can't + * scan correctly (FW doesn't do scan). The usb_probe message: + * "mtk_reg_notify:(RLM ERROR) Invalid REG state happened. state = 0x6". + */ + if (rlmDomainGetCtrlState() == REGD_STATE_INVALID) + rlmDomainResetCtrlInfo(TRUE); +#endif +#endif /* CFG_ENABLE_UNIFY_WIPHY */ + + /* 4 <1.3> co-relate wiphy & prDev */ + glGetDev(pvData, &prDev); + if (!prDev) + DBGLOG(INIT, ERROR, "unable to get struct dev for wlan\n"); + /* Some kernel API (ex: cfg80211_get_drvinfo) will use wiphy_dev(). + * Without set_wiphy_dev(prWdev->wiphy, prDev), those API will crash. + */ + set_wiphy_dev(prWdev->wiphy, prDev); + + /* 4 <2> Create Glue structure */ + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(prWdev->wiphy); + kalMemZero(prGlueInfo, sizeof(struct GLUE_INFO)); + + /* 4 <2.1> Create Adapter structure */ + prAdapter = (struct ADAPTER *) wlanAdapterCreate( + prGlueInfo); + + if (!prAdapter) { + DBGLOG(INIT, ERROR, + "Allocating memory to adapter failed\n"); + glClearHifInfo(prGlueInfo); + return NULL; + } + + prChipInfo = ((struct mt66xx_hif_driver_data *) + pvDriverData)->chip_info; + prAdapter->chip_info = prChipInfo; + prGlueInfo->prAdapter = prAdapter; + + /* 4 <3> Initialize Glue structure */ + /* 4 <3.1> Create net device */ + +#ifdef CFG_DRIVER_INF_NAME_CHANGE + + if (kalStrLen(gprifnamesta) > 0) { + prInfName = kalStrCat(gprifnamesta, "%d"); + DBGLOG(INIT, WARN, "Station ifname customized, use %s\n", + prInfName); + } else +#endif /* CFG_DRIVER_INF_NAME_CHANGE */ + prInfName = NIC_INF_NAME; + + for (i = 0; i < KAL_AIS_NUM; i++) { + struct net_device *prDevHandler; + +#if CFG_SUPPORT_PERSIST_NETDEV + if (!gprNetdev[i]) { + prDevHandler = alloc_netdev_mq( + sizeof(struct NETDEV_PRIVATE_GLUE_INFO), + prInfName, +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE + NET_NAME_PREDICTABLE, +#endif + ether_setup, + CFG_MAX_TXQ_NUM); + gprNetdev[i] = prDevHandler; + } else + prDevHandler = gprNetdev[i]; +#else + prDevHandler = alloc_netdev_mq( + sizeof(struct NETDEV_PRIVATE_GLUE_INFO), + prInfName, +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE + NET_NAME_PREDICTABLE, +#endif + ether_setup, + CFG_MAX_TXQ_NUM); +#endif /* end of CFG_SUPPORT_PERSIST_NETDEV */ + + if (!prDevHandler) { + DBGLOG(INIT, ERROR, + "Allocating memory to net_device context failed\n"); + goto netcreate_err; + } + + /* Device can help us to save at most 3000 packets, + * after we stopped queue + */ + prDevHandler->tx_queue_len = 3000; + DBGLOG(INIT, INFO, "net_device prDev(0x%p) allocated\n", + prDevHandler); + + /* 4 <3.1.1> Initialize net device varaiables */ + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prDevHandler); + prNetDevPrivate->prGlueInfo = prGlueInfo; + + prDevHandler->needed_headroom = + NIC_TX_DESC_AND_PADDING_LENGTH + + prChipInfo->txd_append_size; + prDevHandler->netdev_ops = &wlan_netdev_ops; +#ifdef CONFIG_WIRELESS_EXT + prDevHandler->wireless_handlers = + &wext_handler_def; +#endif + netif_carrier_off(prDevHandler); + netif_tx_stop_all_queues(prDevHandler); + kalResetStats(prDevHandler); + + /* 4 <3.1.2> co-relate with wiphy bi-directionally */ + prDevHandler->ieee80211_ptr = gprWdev[i]; + + gprWdev[i]->netdev = prDevHandler; + + /* 4 <3.1.3> co-relate net device & prDev */ + SET_NETDEV_DEV(prDevHandler, + wiphy_dev(prWdev->wiphy)); + + /* 4 <3.1.4> set device to glue */ + prGlueInfo->prDev = prDev; + + /* 4 <3.2> Initialize glue variables */ + kalSetMediaStateIndicated(prGlueInfo, + MEDIA_STATE_DISCONNECTED, + i); + } + + prGlueInfo->prDevHandler = gprWdev[0]->netdev; + +#if CFG_SUPPORT_SNIFFER + INIT_WORK(&(prGlueInfo->monWork), wlanMonWorkHandler); +#endif + + prGlueInfo->ePowerState = ParamDeviceStateD0; +#if !CFG_SUPPORT_PERSIST_NETDEV + prGlueInfo->fgIsRegistered = FALSE; +#endif + prGlueInfo->prScanRequest = NULL; + prGlueInfo->prSchedScanRequest = NULL; + + +#if CFG_SUPPORT_PASSPOINT + /* Init DAD */ + prGlueInfo->fgIsDad = FALSE; + prGlueInfo->fgIs6Dad = FALSE; + kalMemZero(prGlueInfo->aucDADipv4, 4); + kalMemZero(prGlueInfo->aucDADipv6, 16); +#endif /* CFG_SUPPORT_PASSPOINT */ + + init_completion(&prGlueInfo->rScanComp); + init_completion(&prGlueInfo->rHaltComp); + init_completion(&prGlueInfo->rPendComp); + +#if CFG_SUPPORT_MULTITHREAD + init_completion(&prGlueInfo->rHifHaltComp); + init_completion(&prGlueInfo->rRxHaltComp); +#endif + +#if CFG_SUPPORT_NCHO + init_completion(&prGlueInfo->rAisChGrntComp); +#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]); + } + + for (i = 0; i < MUTEX_NUM; i++) + mutex_init(&prGlueInfo->arMutex[i]); + + /* initialize semaphore for ioctl */ + sema_init(&prGlueInfo->ioctl_sem, 1); + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN + /* initialize SDIO read-write pattern control */ + prGlueInfo->fgEnSdioTestPattern = FALSE; + prGlueInfo->fgIsSdioTestInitialized = FALSE; +#endif + + /* 4 <8> Init Queues */ + init_waitqueue_head(&prGlueInfo->waitq); + QUEUE_INITIALIZE(&prGlueInfo->rCmdQueue); + prGlueInfo->i4TxPendingCmdNum = 0; + QUEUE_INITIALIZE(&prGlueInfo->rTxQueue); + glSetHifInfo(prGlueInfo, (unsigned long) pvData); + + /* Init wakelock */ + wlanWakeLockInit(prGlueInfo); + + /* main thread is created in this function */ +#if CFG_SUPPORT_MULTITHREAD + init_waitqueue_head(&prGlueInfo->waitq_rx); + init_waitqueue_head(&prGlueInfo->waitq_hif); + + prGlueInfo->u4TxThreadPid = 0xffffffff; + prGlueInfo->u4RxThreadPid = 0xffffffff; + prGlueInfo->u4HifThreadPid = 0xffffffff; +#endif + + return prWdev; + +netcreate_err: + if (prAdapter != NULL) { + wlanAdapterDestroy(prAdapter); + prAdapter = NULL; + } + prGlueInfo->prDevHandler = NULL; + + 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) + */ +/*----------------------------------------------------------------------------*/ +void wlanNetDestroy(struct wireless_dev *prWdev) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + ASSERT(prWdev); + + if (!prWdev) { + DBGLOG(INIT, ERROR, "The device context is NULL\n"); + return; + } + + /* prGlueInfo is allocated with net_device */ + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(prWdev->wiphy); + ASSERT(prGlueInfo); + + /* prWdev: base AIS dev + * Because the interface dev (ex: usb_device) would be free + * after un-plug event. Should set the wiphy->dev->parent which + * pointer to the interface dev to NULL. Otherwise, the corresponding + * system operation (poweroff, suspend) might reference it. + * set_wiphy_dev(wiphy, NULL): set the wiphy->dev->parent = NULL + * The set_wiphy_dev(prWdev->wiphy, prDev) is done in wlanNetCreate. + * But that is after wiphy_register, and will cause exception in + * wiphy_unregister(), if do not set_wiphy_dev(wiphy, NULL). + */ + set_wiphy_dev(prWdev->wiphy, NULL); + + /* 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(). + */ +#if CFG_SUPPORT_PERSIST_NETDEV +#ifdef CONFIG_WIRELESS_EXT + { + uint32_t u4Idx = 0; + + for (u4Idx = 0; u4Idx < KAL_AIS_NUM; u4Idx++) { + if (gprWdev[u4Idx] && gprWdev[u4Idx]->netdev) { + rtnl_lock(); + gprWdev[u4Idx]->netdev->wireless_handlers = + NULL; + rtnl_unlock(); + } + } + } +#endif +#else + wlanFreeNetDev(); +#endif + /* gPrDev is assigned by prGlueInfo->prDevHandler, + * set NULL to this global variable. + */ + gPrDev = NULL; + +} /* end of wlanNetDestroy() */ + +void wlanSetSuspendMode(struct GLUE_INFO *prGlueInfo, + u_int8_t fgEnable) +{ + struct net_device *prDev = NULL; + uint32_t u4PacketFilter = 0; + uint32_t u4SetInfoLen = 0; + uint32_t u4Idx = 0; + + if (!prGlueInfo) + return; + + + for (u4Idx = 0; u4Idx < KAL_AIS_NUM; u4Idx++) { + prDev = wlanGetNetDev(prGlueInfo, u4Idx); + if (!prDev) + continue; + + /* new filter should not include p2p mask */ +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + u4PacketFilter = + prGlueInfo->prAdapter->u4OsPacketFilter & + (~PARAM_PACKET_FILTER_P2P_MASK); +#endif + if (kalIoctl(prGlueInfo, + wlanoidSetCurrentPacketFilter, + &u4PacketFilter, + sizeof(u4PacketFilter), FALSE, FALSE, TRUE, + &u4SetInfoLen) != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, ERROR, "set packet filter failed.\n"); + +#if !CFG_SUPPORT_DROP_ALL_MC_PACKET + if (fgEnable) { + /* Prepare IPv6 RA packet when suspend */ + uint8_t MC_address[ETH_ALEN] = {0x33, 0x33, 0, 0, 0, 1}; + + kalIoctl(prGlueInfo, + wlanoidSetMulticastList, MC_address, ETH_ALEN, + FALSE, FALSE, TRUE, &u4SetInfoLen); + } else if (u4PacketFilter & PARAM_PACKET_FILTER_MULTICAST) { + /* Prepare multicast address list when resume */ + struct netdev_hw_addr *ha; + uint8_t *prMCAddrList = NULL; + uint32_t 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 (!prMCAddrList) { + DBGLOG(INIT, WARN, + "prMCAddrList memory alloc fail!\n"); + up(&g_halt_sem); + continue; + } + + /* Avoid race condition with kernel net subsystem */ + netif_addr_lock_bh(prDev); + + netdev_for_each_mc_addr(ha, prDev) { + if (i < MAX_NUM_GROUP_ADDR) { + kalMemCopy( + (prMCAddrList + i * ETH_ALEN), + ha->addr, ETH_ALEN); + i++; + } + } + + netif_addr_unlock_bh(prDev); + + up(&g_halt_sem); + + kalIoctl(prGlueInfo, wlanoidSetMulticastList, + prMCAddrList, (i * ETH_ALEN), FALSE, FALSE, + TRUE, &u4SetInfoLen); + + kalMemFree(prMCAddrList, VIR_MEM_TYPE, + MAX_NUM_GROUP_ADDR * ETH_ALEN); + } +#endif + kalSetNetAddressFromInterface(prGlueInfo, prDev, fgEnable); + wlanNotifyFwSuspend(prGlueInfo, prDev, fgEnable); + } +} + +#if CFG_ENABLE_EARLY_SUSPEND +static struct early_suspend wlan_early_suspend_desc = { + .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN, +}; + +static void wlan_early_suspend(struct early_suspend *h) +{ + struct net_device *prDev = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + + /* 4 <1> Sanity Check */ + if ((u4WlanDevNum == 0) + && (u4WlanDevNum > CFG_MAX_WLAN_DEVICES)) { + DBGLOG(INIT, ERROR, + "wlanLateResume u4WlanDevNum==0 invalid!!\n"); + return; + } + + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + if (!prDev) + return; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + if (!prGlueInfo) + return; + + DBGLOG(INIT, INFO, "********<%s>********\n", __func__); + + if (prGlueInfo->fgIsInSuspendMode == TRUE) { + DBGLOG(INIT, INFO, "%s: Already in suspend mode, SKIP!\n", + __func__); + return; + } + + prGlueInfo->fgIsInSuspendMode = TRUE; + + wlanSetSuspendMode(prGlueInfo, TRUE); + p2pSetSuspendMode(prGlueInfo, TRUE); +} + +static void wlan_late_resume(struct early_suspend *h) +{ + struct net_device *prDev = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + + /* 4 <1> Sanity Check */ + if ((u4WlanDevNum == 0) + && (u4WlanDevNum > CFG_MAX_WLAN_DEVICES)) { + DBGLOG(INIT, ERROR, + "wlanLateResume u4WlanDevNum==0 invalid!!\n"); + return; + } + + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + if (!prDev) + return; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + if (!prGlueInfo) + return; + + DBGLOG(INIT, INFO, "********<%s>********\n", __func__); + + if (prGlueInfo->fgIsInSuspendMode == FALSE) { + DBGLOG(INIT, INFO, "%s: Not in suspend mode, SKIP!\n", + __func__); + return; + } + + prGlueInfo->fgIsInSuspendMode = FALSE; + + /* 4 <2> Set suspend mode for each network */ + wlanSetSuspendMode(prGlueInfo, FALSE); + p2pSetSuspendMode(prGlueInfo, FALSE); +} +#endif + +#if (CFG_MTK_ANDROID_WMT || WLAN_INCLUDE_PROC) + +void reset_p2p_mode(struct GLUE_INFO *prGlueInfo) +{ + struct PARAM_CUSTOM_P2P_SET_STRUCT rSetP2P; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + if (!prGlueInfo) + return; + + rSetP2P.u4Enable = 0; + rSetP2P.u4Mode = 0; + + p2pNetUnregister(prGlueInfo, FALSE); + + rWlanStatus = kalIoctl(prGlueInfo, wlanoidSetP2pMode, + (void *) &rSetP2P, + sizeof(struct PARAM_CUSTOM_P2P_SET_STRUCT), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rWlanStatus != WLAN_STATUS_SUCCESS) + prGlueInfo->prAdapter->fgIsP2PRegistered = FALSE; + + DBGLOG(INIT, INFO, + "ret = 0x%08x\n", (uint32_t) rWlanStatus); +} + +int set_p2p_mode_handler(struct net_device *netdev, + struct PARAM_CUSTOM_P2P_SET_STRUCT p2pmode) +{ + struct GLUE_INFO *prGlueInfo = *((struct GLUE_INFO **) + netdev_priv(netdev)); + struct PARAM_CUSTOM_P2P_SET_STRUCT rSetP2P; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + if (!prGlueInfo) + return -1; + +#if (CFG_MTK_ANDROID_WMT) + if (prGlueInfo->u4ReadyFlag == 0) { + DBGLOG(INIT, ERROR, "adapter is not ready\n"); + return -1; + } +#endif /*CFG_MTK_ANDROID_WMT*/ + + /* Remember original ifindex for reset case */ + if (kalIsResetting()) { + struct GL_P2P_INFO *prP2PInfo = NULL; + int i = 0; + + for (i = 0 ; i < KAL_P2P_NUM; i++) { + prP2PInfo = prGlueInfo->prP2PInfo[i]; + + if (!prP2PInfo || !prP2PInfo->prDevHandler) + continue; + + /* Only restore sap part */ + if (prP2PInfo->prWdev->iftype != NL80211_IFTYPE_AP) + continue; + + g_u4DevIdx[i] = + prP2PInfo->prDevHandler->ifindex; + } + } + + /* Resetting p2p mode if registered to avoid launch KE */ + if (p2pmode.u4Enable + && prGlueInfo->prAdapter->fgIsP2PRegistered + && !kalIsResetting()) { + DBGLOG(INIT, WARN, "Resetting p2p mode\n"); + reset_p2p_mode(prGlueInfo); + } + + rSetP2P.u4Enable = p2pmode.u4Enable; + rSetP2P.u4Mode = p2pmode.u4Mode; + + if ((!rSetP2P.u4Enable) && (kalIsResetting() == FALSE)) + p2pNetUnregister(prGlueInfo, FALSE); + + rWlanStatus = kalIoctl(prGlueInfo, wlanoidSetP2pMode, + (void *) &rSetP2P, + sizeof(struct PARAM_CUSTOM_P2P_SET_STRUCT), + FALSE, FALSE, TRUE, &u4BufLen); + + DBGLOG(INIT, INFO, + "ret = 0x%08x, p2p reg = %d, resetting = %d\n", + (uint32_t) rWlanStatus, + prGlueInfo->prAdapter->fgIsP2PRegistered, + kalIsResetting()); + + + /* Need to check fgIsP2PRegistered, in case of whole chip reset. + * in this case, kalIOCTL return success always, + * and prGlueInfo->prP2PInfo[0] may be NULL + */ + if ((rSetP2P.u4Enable) + && (prGlueInfo->prAdapter->fgIsP2PRegistered) + && (kalIsResetting() == FALSE)) + p2pNetRegister(prGlueInfo, FALSE); + + return 0; +} + +#endif + +#if CFG_SUPPORT_EASY_DEBUG +/*----------------------------------------------------------------------------*/ +/*! + * \brief parse config from wifi.cfg + * + * \param[in] prAdapter + * + * \retval VOID + */ +/*----------------------------------------------------------------------------*/ +void wlanGetParseConfig(struct ADAPTER *prAdapter) +{ + uint8_t *pucConfigBuf; + uint32_t u4ConfigReadLen; + + wlanCfgInit(prAdapter, NULL, 0, 0); + pucConfigBuf = (uint8_t *) kalMemAlloc( + WLAN_CFG_FILE_BUF_SIZE, VIR_MEM_TYPE); + kalMemZero(pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE); + u4ConfigReadLen = 0; + if (pucConfigBuf) { + if (kalRequestFirmware("wifi.cfg", pucConfigBuf, + WLAN_CFG_FILE_BUF_SIZE, &u4ConfigReadLen, + prAdapter->prGlueInfo->prDev) == 0) { + /* ToDo:: Nothing */ + } else if (kalReadToFile("/data/misc/wifi.cfg", + pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE, + &u4ConfigReadLen) == 0) { + /* ToDo:: Nothing */ + } else if (kalReadToFile("/data/misc/wifi/wifi.cfg", + pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE, + &u4ConfigReadLen) == 0) { + /* ToDo:: Nothing */ + } else if (kalReadToFile("/storage/sdcard0/wifi.cfg", + pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE, + &u4ConfigReadLen) == 0) { + /* ToDo:: Nothing */ + } + + if (pucConfigBuf[0] != '\0' && u4ConfigReadLen > 0) + wlanCfgParse(prAdapter, pucConfigBuf, u4ConfigReadLen, + TRUE); + + kalMemFree(pucConfigBuf, VIR_MEM_TYPE, + WLAN_CFG_FILE_BUF_SIZE); + } /* pucConfigBuf */ +} + + +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief get config from wifi.cfg + * + * \param[in] prAdapter + * + * \retval VOID + */ +/*----------------------------------------------------------------------------*/ +void wlanGetConfig(struct ADAPTER *prAdapter) +{ + uint8_t *pucConfigBuf; + uint32_t u4ConfigReadLen; + + wlanCfgInit(prAdapter, NULL, 0, 0); + pucConfigBuf = (uint8_t *) kalMemAlloc( + WLAN_CFG_FILE_BUF_SIZE, VIR_MEM_TYPE); + kalMemZero(pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE); + u4ConfigReadLen = 0; + if (pucConfigBuf) { + if (kalRequestFirmware("wifi.cfg", pucConfigBuf, + WLAN_CFG_FILE_BUF_SIZE, &u4ConfigReadLen, + prAdapter->prGlueInfo->prDev) == 0) { + /* ToDo:: Nothing */ + } else if (kalReadToFile("/data/misc/wifi/wifi.cfg", + pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE, + &u4ConfigReadLen) == 0) { + /* ToDo:: Nothing */ + } else if (kalReadToFile("/storage/sdcard0/wifi.cfg", + pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE, + &u4ConfigReadLen) == 0) { + /* ToDo:: Nothing */ + } + + if (pucConfigBuf[0] != '\0' && u4ConfigReadLen > 0) + wlanCfgInit(prAdapter, + pucConfigBuf, u4ConfigReadLen, 0); + + kalMemFree(pucConfigBuf, VIR_MEM_TYPE, + WLAN_CFG_FILE_BUF_SIZE); + } /* pucConfigBuf */ +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief this function send buffer bin EEPROB_MTxxxx.bin to FW. + * + * \param[in] prAdapter + * + * \retval WLAN_STATUS_SUCCESS Success + * \retval WLAN_STATUS_FAILURE Failed + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanDownloadBufferBin(struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo = NULL; +#if (CFG_FW_Report_Efuse_Address) + uint16_t u2InitAddr = prAdapter->u4EfuseStartAddress; +#else + uint16_t u2InitAddr = EFUSE_CONTENT_BUFFER_START; +#endif + uint32_t u4BufLen = 0; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE *prSetEfuseBufModeInfo + = NULL; + uint32_t u4ContentLen; + uint8_t *pucConfigBuf = NULL; + struct mt66xx_chip_info *prChipInfo; + uint32_t chip_id; + uint8_t aucEeprom[32]; + uint32_t retWlanStat = WLAN_STATUS_FAILURE; + + if (prAdapter->fgIsSupportPowerOnSendBufferModeCMD == + TRUE) { + DBGLOG(INIT, INFO, "Start Efuse Buffer Mode ..\n"); + DBGLOG(INIT, INFO, "ucEfuseBUfferModeCal is %x\n", + prAdapter->rWifiVar.ucEfuseBufferModeCal); + + prChipInfo = prAdapter->chip_info; + chip_id = prChipInfo->chip_id; + prGlueInfo = prAdapter->prGlueInfo; + + if (prGlueInfo == NULL || prGlueInfo->prDev == NULL) + goto label_exit; + + /* allocate memory for buffer mode info */ + prSetEfuseBufModeInfo = + (struct PARAM_CUSTOM_EFUSE_BUFFER_MODE *) + kalMemAlloc(sizeof( + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE), + VIR_MEM_TYPE); + if (prSetEfuseBufModeInfo == NULL) + goto label_exit; + kalMemZero(prSetEfuseBufModeInfo, + sizeof(struct PARAM_CUSTOM_EFUSE_BUFFER_MODE)); + + if (prAdapter->rWifiVar.ucEfuseBufferModeCal == TRUE) { + int ret = 0; + + /* Buffer mode */ + /* Only in buffer mode need to access bin file */ + /* 1 <1> Load bin file*/ + pucConfigBuf = (uint8_t *) kalMemAlloc( + MAX_EEPROM_BUFFER_SIZE, VIR_MEM_TYPE); + if (pucConfigBuf == NULL) + goto label_exit; + + kalMemZero(pucConfigBuf, MAX_EEPROM_BUFFER_SIZE); + + /* 1 <2> Construct EEPROM binary name */ + kalMemZero(aucEeprom, sizeof(aucEeprom)); + + ret = kalSnprintf(aucEeprom, 32, "%s%x.bin", + apucEepromName[0], chip_id); + if (ret < 0 || ret >= 32) { + DBGLOG(INIT, ERROR, + "[%u] kalSnprintf failed, ret: %d\n", + __LINE__, ret); + goto label_exit; + } + + /* 1 <3> Request buffer bin */ + if (kalRequestFirmware(aucEeprom, pucConfigBuf, + MAX_EEPROM_BUFFER_SIZE, &u4ContentLen, + prGlueInfo->prDev) == 0) { + DBGLOG(INIT, INFO, "request file done\n"); + } else { + DBGLOG(INIT, INFO, "can't find file\n"); + goto label_exit; + } + + /* 1 <4> Send CMD with bin file content */ + prGlueInfo = prAdapter->prGlueInfo; + + /* Update contents in local table */ + kalMemCopy(uacEEPROMImage, pucConfigBuf, + MAX_EEPROM_BUFFER_SIZE); + + /* copy to the command buffer */ +#if (CFG_FW_Report_Efuse_Address) + u4ContentLen = (prAdapter->u4EfuseEndAddress) - + (prAdapter->u4EfuseStartAddress) + 1; +#else + u4ContentLen = EFUSE_CONTENT_BUFFER_SIZE; +#endif + if (u4ContentLen > MAX_EEPROM_BUFFER_SIZE) + goto label_exit; + kalMemCopy(prSetEfuseBufModeInfo->aBinContent, + &pucConfigBuf[u2InitAddr], u4ContentLen); + + prSetEfuseBufModeInfo->ucSourceMode = 1; + } else { + /* eFuse mode */ + /* Only need to tell FW the content from, contents are + * directly from efuse + */ + prSetEfuseBufModeInfo->ucSourceMode = 0; + } + prSetEfuseBufModeInfo->ucCmdType = 0x1 | + (prAdapter->rWifiVar.ucCalTimingCtrl << 4); + prSetEfuseBufModeInfo->ucCount = + 0xFF; /* ucCmdType 1 don't care the ucCount */ + + rStatus = kalIoctl(prGlueInfo, wlanoidSetEfusBufferMode, + (void *)prSetEfuseBufModeInfo, + sizeof(struct PARAM_CUSTOM_EFUSE_BUFFER_MODE), + FALSE, TRUE, TRUE, &u4BufLen); + } + + retWlanStat = WLAN_STATUS_SUCCESS; + +label_exit: + + /* free memory */ + if (prSetEfuseBufModeInfo != NULL) + kalMemFree(prSetEfuseBufModeInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_CUSTOM_EFUSE_BUFFER_MODE)); + + if (pucConfigBuf != NULL) + kalMemFree(pucConfigBuf, VIR_MEM_TYPE, + MAX_EEPROM_BUFFER_SIZE); + + return retWlanStat; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief this function send buffer bin EEPROB_MTxxxx.bin to FW. + * + * \param[in] prAdapter + * + * \retval WLAN_STATUS_SUCCESS Success + * \retval WLAN_STATUS_FAILURE Failed + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanConnacDownloadBufferBin(struct ADAPTER + *prAdapter) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4BufLen = 0; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE_CONNAC_T + *prSetEfuseBufModeInfo = NULL; + uint32_t u4ContentLen; + uint8_t *pucConfigBuf = NULL; + struct mt66xx_chip_info *prChipInfo; + uint32_t chip_id; + uint8_t aucEeprom[32]; + uint32_t retWlanStat = WLAN_STATUS_FAILURE; + + if (prAdapter->fgIsSupportPowerOnSendBufferModeCMD == FALSE) + return WLAN_STATUS_SUCCESS; + + DBGLOG(INIT, INFO, "Start Efuse Buffer Mode ..\n"); + DBGLOG(INIT, INFO, "ucEfuseBUfferModeCal is %x\n", + prAdapter->rWifiVar.ucEfuseBufferModeCal); + + prChipInfo = prAdapter->chip_info; + chip_id = prChipInfo->chip_id; + prGlueInfo = prAdapter->prGlueInfo; + + if (prGlueInfo == NULL || prGlueInfo->prDev == NULL) + goto label_exit; + + /* allocate memory for buffer mode info */ + prSetEfuseBufModeInfo = + (struct PARAM_CUSTOM_EFUSE_BUFFER_MODE_CONNAC_T *) + kalMemAlloc(sizeof( + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE_CONNAC_T), + VIR_MEM_TYPE); + if (prSetEfuseBufModeInfo == NULL) + goto label_exit; + kalMemZero(prSetEfuseBufModeInfo, + sizeof(struct PARAM_CUSTOM_EFUSE_BUFFER_MODE_CONNAC_T)); + + if (prAdapter->rWifiVar.ucEfuseBufferModeCal == TRUE) { + int ret = 0; + + /* Buffer mode */ + /* Only in buffer mode need to access bin file */ + /* 1 <1> Load bin file*/ + pucConfigBuf = (uint8_t *) kalMemAlloc( + MAX_EEPROM_BUFFER_SIZE, VIR_MEM_TYPE); + if (pucConfigBuf == NULL) + goto label_exit; + + kalMemZero(pucConfigBuf, MAX_EEPROM_BUFFER_SIZE); + + /* 1 <2> Construct EEPROM binary name */ + kalMemZero(aucEeprom, sizeof(aucEeprom)); + + ret = kalSnprintf(aucEeprom, 32, "%s%x.bin", + apucEepromName[0], chip_id); + if (ret < 0 || ret >= 32) { + DBGLOG(INIT, ERROR, + "[%u] kalSnprintf failed, ret: %d\n", + __LINE__, ret); + goto label_exit; + } + + /* 1 <3> Request buffer bin */ + if (kalRequestFirmware(aucEeprom, pucConfigBuf, + MAX_EEPROM_BUFFER_SIZE, &u4ContentLen, prGlueInfo->prDev) + == 0) { + DBGLOG(INIT, INFO, "request file done\n"); + } else { + DBGLOG(INIT, INFO, "can't find file\n"); + goto label_exit; + } + DBGLOG(INIT, INFO, "u4ContentLen = %d\n", u4ContentLen); + + /* 1 <4> Send CMD with bin file content */ + prGlueInfo = prAdapter->prGlueInfo; + + /* Update contents in local table */ + kalMemCopy(uacEEPROMImage, pucConfigBuf, + MAX_EEPROM_BUFFER_SIZE); + + if (u4ContentLen > MAX_EEPROM_BUFFER_SIZE) + goto label_exit; + + kalMemCopy(prSetEfuseBufModeInfo->aBinContent, pucConfigBuf, + u4ContentLen); + + prSetEfuseBufModeInfo->ucSourceMode = 1; + } else { + /* eFuse mode */ + /* Only need to tell FW the content from, contents are directly + * from efuse + */ + prSetEfuseBufModeInfo->ucSourceMode = 0; + u4ContentLen = 0; + } + prSetEfuseBufModeInfo->ucContentFormat = 0x1 | + (prAdapter->rWifiVar.ucCalTimingCtrl << 4); + prSetEfuseBufModeInfo->u2Count = u4ContentLen; + + rStatus = kalIoctl(prGlueInfo, wlanoidConnacSetEfusBufferMode, + (void *)prSetEfuseBufModeInfo, + OFFSET_OF(struct PARAM_CUSTOM_EFUSE_BUFFER_MODE_CONNAC_T, + aBinContent) + u4ContentLen, + FALSE, TRUE, TRUE, &u4BufLen); + + retWlanStat = WLAN_STATUS_SUCCESS; + +label_exit: + + /* free memory */ + if (prSetEfuseBufModeInfo != NULL) + kalMemFree(prSetEfuseBufModeInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_CUSTOM_EFUSE_BUFFER_MODE_CONNAC_T)); + + if (pucConfigBuf != NULL) + kalMemFree(pucConfigBuf, VIR_MEM_TYPE, + MAX_EEPROM_BUFFER_SIZE); + + return retWlanStat; +} +#if (CONFIG_WLAN_SERVICE == 1) +uint32_t wlanServiceInit(struct GLUE_INFO *prGlueInfo) +{ + + struct service_test *prServiceTest; + struct test_wlan_info *winfos; + struct mt66xx_chip_info *prChipInfo; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + DBGLOG(INIT, TRACE, "%s enter!\n", __func__); + + if (prGlueInfo == NULL) + return WLAN_STATUS_FAILURE; + + prChipInfo = prGlueInfo->prAdapter->chip_info; + prGlueInfo->rService.serv_id = SERV_HANDLE_TEST; + prGlueInfo->rService.serv_handle + = kalMemAlloc(sizeof(struct service_test), VIR_MEM_TYPE); + if (prGlueInfo->rService.serv_handle == NULL) { + DBGLOG(INIT, WARN, + "prGlueInfo->rService.serv_handle memory alloc fail!\n"); + return WLAN_STATUS_FAILURE; + } + + prServiceTest = (struct service_test *)prGlueInfo->rService.serv_handle; + prServiceTest->test_winfo + = kalMemAlloc(sizeof(struct test_wlan_info), VIR_MEM_TYPE); + if (prServiceTest->test_winfo == NULL) { + DBGLOG(INIT, WARN, + "prServiceTest->test_winfo memory alloc fail!\n"); + goto label_exit; + } + winfos = prServiceTest->test_winfo; + + prServiceTest->test_winfo->net_dev = gPrDev; + + if (prChipInfo->asicGetChipID) + prServiceTest->test_winfo->chip_id = + prChipInfo->asicGetChipID(prGlueInfo->prAdapter); + else + prServiceTest->test_winfo->chip_id = prChipInfo->chip_id; + + DBGLOG(INIT, WARN, + "%s chip_id = 0x%x\n", __func__, + prServiceTest->test_winfo->chip_id); + +#if (CFG_MTK_ANDROID_EMI == 1) + prServiceTest->test_winfo->emi_phy_base = gConEmiPhyBase; + prServiceTest->test_winfo->emi_phy_size = gConEmiSize; +#else + DBGLOG(RFTEST, WARN, "Platform doesn't support EMI address\n"); +#endif + + prServiceTest->test_op + = kalMemAlloc(sizeof(struct test_operation), VIR_MEM_TYPE); + if (prServiceTest->test_op == NULL) { + DBGLOG(INIT, WARN, + "prServiceTest->test_op memory alloc fail!\n"); + goto label_exit; + } + + prServiceTest->engine_offload = true; + winfos->oid_funcptr = (wlan_oid_handler_t) ServiceWlanOid; + + rStatus = mt_agent_init_service(&prGlueInfo->rService); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, WARN, "%s init fail err:%d\n", __func__, rStatus); + + return rStatus; + +label_exit: + + /* free memory */ + if (prGlueInfo->rService.serv_handle != NULL) { + + if (prServiceTest->test_winfo != NULL) + kalMemFree(prServiceTest->test_winfo, VIR_MEM_TYPE, + sizeof(struct test_wlan_info)); + + if (prServiceTest->test_op != NULL) + kalMemFree(prServiceTest->test_op, VIR_MEM_TYPE, + sizeof(struct test_operation)); + + kalMemFree(prGlueInfo->rService.serv_handle, VIR_MEM_TYPE, + sizeof(struct service_test)); + } + + return WLAN_STATUS_FAILURE; +} +uint32_t wlanServiceExit(struct GLUE_INFO *prGlueInfo) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct service_test *prServiceTest; + + DBGLOG(INIT, TRACE, "%s enter\n", __func__); + + if (prGlueInfo == NULL) + return WLAN_STATUS_FAILURE; + + rStatus = mt_agent_exit_service(&prGlueInfo->rService); + + prServiceTest = (struct service_test *)prGlueInfo->rService.serv_handle; + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, WARN, "wlanServiceExit fail err:%d\n", rStatus); + + if (prGlueInfo->rService.serv_handle) { + if (prServiceTest->test_winfo) + kalMemFree(prServiceTest->test_winfo, + VIR_MEM_TYPE, sizeof(struct test_wlan_info)); + + if (prServiceTest->test_op) + kalMemFree(prServiceTest->test_op, + VIR_MEM_TYPE, sizeof(struct test_operation)); + + kalMemFree(prGlueInfo->rService.serv_handle, + VIR_MEM_TYPE, sizeof(struct service_test)); + } + + prGlueInfo->rService.serv_id = 0; + + return rStatus; +} +#endif + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + +#define FW_LOG_CMD_ON_OFF 0 +#define FW_LOG_CMD_SET_LEVEL 1 +static uint32_t u4LogOnOffCache; +static uint32_t u4LogLevelCache = -1; + +struct CMD_CONNSYS_FW_LOG { + int32_t fgCmd; + int32_t fgValue; +}; + +uint32_t +connsysFwLogControl(struct ADAPTER *prAdapter, void *pvSetBuffer, + uint32_t u4SetBufferLen, uint32_t *pu4SetInfoLen) +{ + struct CMD_CONNSYS_FW_LOG *prCmd; + struct CMD_HEADER rCmdV1Header; + struct CMD_FORMAT_V1 rCmd_v1; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + if ((prAdapter == NULL) || (pvSetBuffer == NULL) + || (pu4SetInfoLen == NULL)) + return WLAN_STATUS_FAILURE; + + /* init */ + *pu4SetInfoLen = sizeof(struct CMD_CONNSYS_FW_LOG); + prCmd = (struct CMD_CONNSYS_FW_LOG *) pvSetBuffer; + + if (prCmd->fgCmd == FW_LOG_CMD_ON_OFF) { + + /*EvtDrvnLogEn 0/1*/ + uint8_t onoff[1] = {'0'}; + + DBGLOG(INIT, TRACE, "FW_LOG_CMD_ON_OFF\n"); + + rCmdV1Header.cmdType = CMD_TYPE_SET; + rCmdV1Header.cmdVersion = CMD_VER_1; + rCmdV1Header.cmdBufferLen = 0; + rCmdV1Header.itemNum = 0; + + kalMemSet(rCmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); + kalMemSet(&rCmd_v1, 0, sizeof(struct CMD_FORMAT_V1)); + + rCmd_v1.itemType = ITEM_TYPE_STR; + + /*send string format to firmware */ + rCmd_v1.itemStringLength = kalStrLen("EnableDbgLog"); + kalMemZero(rCmd_v1.itemString, MAX_CMD_NAME_MAX_LENGTH); + kalMemCopy(rCmd_v1.itemString, "EnableDbgLog", + rCmd_v1.itemStringLength); + + if (prCmd->fgValue == 1) /* other cases, send 'OFF=0' */ + onoff[0] = '1'; + rCmd_v1.itemValueLength = 1; + kalMemZero(rCmd_v1.itemValue, MAX_CMD_VALUE_MAX_LENGTH); + kalMemCopy(rCmd_v1.itemValue, &onoff, 1); + + DBGLOG(INIT, INFO, "Send key word (%s) WITH (%s) to firmware\n", + rCmd_v1.itemString, rCmd_v1.itemValue); + + kalMemCopy(((struct CMD_FORMAT_V1 *)rCmdV1Header.buffer), + &rCmd_v1, sizeof(struct CMD_FORMAT_V1)); + + rCmdV1Header.cmdBufferLen += sizeof(struct CMD_FORMAT_V1); + rCmdV1Header.itemNum = 1; + + rStatus = wlanSendSetQueryCmd( + prAdapter, /* prAdapter */ + CMD_ID_GET_SET_CUSTOMER_CFG, /* 0x70 */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler*/ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct CMD_HEADER), + (uint8_t *)&rCmdV1Header, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + /* keep in cache */ + u4LogOnOffCache = prCmd->fgValue; + } else if (prCmd->fgCmd == FW_LOG_CMD_SET_LEVEL) { + /*ENG_LOAD_OFFSET 1*/ + /*USERDEBUG_LOAD_OFFSET 2 */ + /*USER_LOAD_OFFSET 3 */ + int32_t u4LogLevel = ENUM_WIFI_LOG_LEVEL_DEFAULT; + + DBGLOG(INIT, INFO, "FW_LOG_CMD_SET_LEVEL %d\n", prCmd->fgValue); + switch (prCmd->fgValue) { + case 0: + u4LogLevel = ENUM_WIFI_LOG_LEVEL_DEFAULT; + break; + case 1: + u4LogLevel = ENUM_WIFI_LOG_LEVEL_MORE; + break; + case 2: + u4LogLevel = ENUM_WIFI_LOG_LEVEL_EXTREME; + break; + default: + u4LogLevel = ENUM_WIFI_LOG_LEVEL_DEFAULT; + break; + } + wlanDbgSetLogLevelImpl(prAdapter, + ENUM_WIFI_LOG_LEVEL_VERSION_V1, + ENUM_WIFI_LOG_MODULE_DRIVER, + u4LogLevel); + wlanDbgSetLogLevelImpl(prAdapter, + ENUM_WIFI_LOG_LEVEL_VERSION_V1, + ENUM_WIFI_LOG_MODULE_FW, + u4LogLevel); + /* keep in cache */ + u4LogLevelCache = prCmd->fgValue; + } else { + DBGLOG(INIT, INFO, "command can not parse\n"); + } + return WLAN_STATUS_SUCCESS; +} + +static void consys_log_event_notification(int cmd, int value) +{ + struct CMD_CONNSYS_FW_LOG rFwLogCmd; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct net_device *prDev = gPrDev; + uint32_t rStatus = WLAN_STATUS_FAILURE; + uint32_t u4BufLen; + + DBGLOG(INIT, INFO, "gPrDev=%p, cmd=%d, value=%d\n", + gPrDev, cmd, value); + + if (cmd == FW_LOG_CMD_ON_OFF) + u4LogOnOffCache = value; + if (cmd == FW_LOG_CMD_SET_LEVEL) + u4LogLevelCache = value; + + if (kalIsHalted()) { /* power-off */ + DBGLOG(INIT, INFO, + "Power off return, u4LogOnOffCache=%d\n", + u4LogOnOffCache); + return; + } + + prGlueInfo = (prDev != NULL) ? + *((struct GLUE_INFO **) netdev_priv(prDev)) : NULL; + DBGLOG(INIT, TRACE, "prGlueInfo=%p\n", prGlueInfo); + if (!prGlueInfo) { + DBGLOG(INIT, INFO, + "prGlueInfo == NULL return, u4LogOnOffCache=%d\n", + u4LogOnOffCache); + return; + } + prAdapter = prGlueInfo->prAdapter; + DBGLOG(INIT, TRACE, "prAdapter=%p\n", prAdapter); + if (!prAdapter) { + DBGLOG(INIT, INFO, + "prAdapter == NULL return, u4LogOnOffCache=%d\n", + u4LogOnOffCache); + return; + } + + kalMemZero(&rFwLogCmd, sizeof(rFwLogCmd)); + rFwLogCmd.fgCmd = cmd; + rFwLogCmd.fgValue = value; + + rStatus = kalIoctl(prGlueInfo, + connsysFwLogControl, + &rFwLogCmd, + sizeof(struct CMD_CONNSYS_FW_LOG), + FALSE, FALSE, FALSE, + &u4BufLen); +} +#endif + +static +void wlanOnPreAdapterStart(struct GLUE_INFO *prGlueInfo, + struct ADAPTER *prAdapter, + struct REG_INFO **pprRegInfo, + struct mt66xx_chip_info **pprChipInfo) +{ + uint32_t u4Idx = 0; +#if CFG_WMT_WIFI_PATH_SUPPORT + int32_t i4RetVal = 0; +#endif + + DBGLOG(INIT, TRACE, "start.\n"); + prGlueInfo->u4ReadyFlag = 0; +#if CFG_MTK_ANDROID_WMT + update_driver_loaded_status(prGlueInfo->u4ReadyFlag); +#endif +#if CFG_TCP_IP_CHKSUM_OFFLOAD + prAdapter->fgIsSupportCsumOffload = FALSE; + prAdapter->u4CSUMFlags = CSUM_OFFLOAD_EN_ALL; +#endif + +#if CFG_SUPPORT_CFG_FILE + wlanGetConfig(prAdapter); +#endif + + /* Init Chip Capability */ + *pprChipInfo = prAdapter->chip_info; + if ((*pprChipInfo)->asicCapInit) + (*pprChipInfo)->asicCapInit(prAdapter); + + /* Default support 2.4/5G MIMO */ + prAdapter->rWifiFemCfg.u2WifiPath = ( + WLAN_FLAG_2G4_WF0 | WLAN_FLAG_5G_WF0 | + WLAN_FLAG_2G4_WF1 | WLAN_FLAG_5G_WF1); + +#if CFG_WMT_WIFI_PATH_SUPPORT + i4RetVal = mtk_wcn_wmt_wifi_fem_cfg_report(( + void *)&prAdapter->rWifiFemCfg); + if (i4RetVal) + DBGLOG(INIT, ERROR, "Get WifiPath from WMT drv fail\n"); + else + DBGLOG(INIT, INFO, + "Get WifiPath from WMT drv success, WifiPath=0x%x\n", + prAdapter->rWifiFemCfg.u2WifiPath); +#endif + /* 4 <5> Start Device */ + *pprRegInfo = &prGlueInfo->rRegInfo; + + /* P_REG_INFO_T prRegInfo = (P_REG_INFO_T) kmalloc( + * sizeof(REG_INFO_T), GFP_KERNEL); + */ + kalMemSet(*pprRegInfo, 0, sizeof(struct REG_INFO)); + + /* Trigger the action of switching Pwr state to drv_own */ + prAdapter->fgIsFwOwn = TRUE; + + nicpmWakeUpWiFi(prAdapter); + + /* Load NVRAM content to REG_INFO_T */ + glLoadNvram(prGlueInfo, *pprRegInfo); + + /* kalMemCopy(&prGlueInfo->rRegInfo, prRegInfo, + * sizeof(REG_INFO_T)); + */ + + (*pprRegInfo)->u4PowerMode = CFG_INIT_POWER_SAVE_PROF; +#if 0 + prRegInfo->fgEnArpFilter = TRUE; +#endif + + /* The Init value of u4WpaVersion/u4AuthAlg shall be + * DISABLE/OPEN, not zero! + */ + /* The Init value of u4CipherGroup/u4CipherPairwise shall be + * NONE, not zero! + */ + for (u4Idx = 0; u4Idx < KAL_AIS_NUM; u4Idx++) { + struct GL_WPA_INFO *prWpaInfo = + aisGetWpaInfo(prAdapter, u4Idx); + + if (!prWpaInfo) + continue; + + prWpaInfo->u4WpaVersion = + IW_AUTH_WPA_VERSION_DISABLED; + prWpaInfo->u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; + prWpaInfo->u4CipherGroup = IW_AUTH_CIPHER_NONE; + prWpaInfo->u4CipherPairwise = IW_AUTH_CIPHER_NONE; + } + + tasklet_init(&prGlueInfo->rRxTask, halRxTasklet, + (unsigned long)prGlueInfo); + tasklet_init(&prGlueInfo->rTxCompleteTask, + halTxCompleteTasklet, + (unsigned long)prGlueInfo); +} + +static +void wlanOnPostAdapterStart(struct ADAPTER *prAdapter, + struct GLUE_INFO *prGlueInfo) +{ + DBGLOG(INIT, TRACE, "start.\n"); + if (HAL_IS_TX_DIRECT(prAdapter)) { + if (!prAdapter->fgTxDirectInited) { + skb_queue_head_init( + &prAdapter->rTxDirectSkbQueue); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) + timer_setup(&prAdapter->rTxDirectSkbTimer, + nicTxDirectTimerCheckSkbQ, 0); + timer_setup(&prAdapter->rTxDirectHifTimer, + nicTxDirectTimerCheckHifQ, 0); +#else + init_timer(&prAdapter->rTxDirectSkbTimer); + prAdapter->rTxDirectSkbTimer.data = + (unsigned long)prGlueInfo; + prAdapter->rTxDirectSkbTimer.function = + nicTxDirectTimerCheckSkbQ; + + init_timer(&prAdapter->rTxDirectHifTimer); + prAdapter->rTxDirectHifTimer.data = + (unsigned long)prGlueInfo; + prAdapter->rTxDirectHifTimer.function = + nicTxDirectTimerCheckHifQ; +#endif + prAdapter->fgTxDirectInited = TRUE; + } + } +} + +static int32_t wlanOnPreNetRegister(struct GLUE_INFO *prGlueInfo, + struct ADAPTER *prAdapter, + struct mt66xx_chip_info *prChipInfo, + struct WIFI_VAR *prWifiVar, + const u_int8_t bAtResetFlow) +{ + uint32_t i; + + DBGLOG(INIT, TRACE, "start.\n"); + + if (!bAtResetFlow) { + /* change net device mtu from feature option */ + if (prWifiVar->u4MTU > 0 && prWifiVar->u4MTU <= ETH_DATA_LEN) { + for (i = 0; i < KAL_AIS_NUM; i++) + gprWdev[i]->netdev->mtu = prWifiVar->u4MTU; + } + INIT_DELAYED_WORK(&prGlueInfo->rRxPktDeAggWork, + halDeAggRxPktWorker); + } + INIT_WORK(&prGlueInfo->rTxMsduFreeWork, kalFreeTxMsduWorker); + + prGlueInfo->main_thread = kthread_run(main_thread, + prGlueInfo->prDevHandler, "main_thread"); +#if CFG_SUPPORT_MULTITHREAD + prGlueInfo->hif_thread = kthread_run(hif_thread, + prGlueInfo->prDevHandler, "hif_thread"); + prGlueInfo->rx_thread = kthread_run(rx_thread, + prGlueInfo->prDevHandler, "rx_thread"); +#endif + /* TODO the change schedule API shall be provided by OS glue + * layer + */ + /* Switch the Wi-Fi task priority to higher priority and change + * the scheduling method + */ + if (prGlueInfo->prAdapter->rWifiVar.ucThreadPriority > 0) { +#if KERNEL_VERSION(4, 19, 0) >= LINUX_VERSION_CODE + struct sched_param param = { + .sched_priority = prGlueInfo->prAdapter + ->rWifiVar.ucThreadPriority + }; + sched_setscheduler(prGlueInfo->main_thread, + prGlueInfo->prAdapter->rWifiVar + .ucThreadScheduling, ¶m); +#if CFG_SUPPORT_MULTITHREAD + sched_setscheduler(prGlueInfo->hif_thread, + prGlueInfo->prAdapter->rWifiVar + .ucThreadScheduling, ¶m); + sched_setscheduler(prGlueInfo->rx_thread, + prGlueInfo->prAdapter->rWifiVar + .ucThreadScheduling, ¶m); +#endif +#endif + DBGLOG(INIT, INFO, + "Set pri = %d, sched = %d\n", + prGlueInfo->prAdapter->rWifiVar.ucThreadPriority, + prGlueInfo->prAdapter->rWifiVar + .ucThreadScheduling); + } + + if (!bAtResetFlow) { + g_u4HaltFlag = 0; + +#if CFG_SUPPORT_BUFFER_MODE +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1) + if (prChipInfo->downloadBufferBin) { + if (prChipInfo->downloadBufferBin(prAdapter) != + WLAN_STATUS_SUCCESS) + return -1; + } +#endif +#endif + +#if CFG_SUPPORT_DBDC + /* Update DBDC default setting */ + cnmInitDbdcSetting(prAdapter); +#endif /*CFG_SUPPORT_DBDC*/ + } + + /* send regulatory information to firmware */ + rlmDomainSendInfoToFirmware(prAdapter); + + /* set MAC address */ + if (!bAtResetFlow) { + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct sockaddr MacAddr; + uint32_t u4SetInfoLen = 0; + struct net_device *prDevHandler; + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryCurrentAddr, + &MacAddr.sa_data, PARAM_MAC_ADDR_LEN, + TRUE, TRUE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, WARN, "set MAC addr fail 0x%x\n", + rStatus); + } else { + kalMemCopy(prGlueInfo->prDevHandler->dev_addr, + &MacAddr.sa_data, ETH_ALEN); + kalMemCopy(prGlueInfo->prDevHandler->perm_addr, + prGlueInfo->prDevHandler->dev_addr, + ETH_ALEN); + +#if CFG_SHOW_MACADDR_SOURCE + DBGLOG(INIT, INFO, "MAC address: " MACSTR, + MAC2STR(prAdapter->rWifiVar.aucMacAddress)); +#endif + } + + /* wlan1 */ + if (KAL_AIS_NUM > 1) { + prDevHandler = wlanGetNetDev(prGlueInfo, 1); + if (prDevHandler) { + kalMemCopy(prDevHandler->dev_addr, + &prAdapter->rWifiVar.aucMacAddress1, + ETH_ALEN); + kalMemCopy(prDevHandler->perm_addr, + prDevHandler->dev_addr, + ETH_ALEN); +#if CFG_SHOW_MACADDR_SOURCE + DBGLOG(INIT, INFO, + "MAC1 address: " MACSTR, + MAC2STR(prDevHandler->dev_addr)); +#endif + } + } + } + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + /* set HW checksum offload */ + if (!bAtResetFlow && prAdapter->fgIsSupportCsumOffload) { + uint32_t rStatus = WLAN_STATUS_FAILURE; + uint32_t u4CSUMFlags = CSUM_OFFLOAD_EN_ALL; + uint32_t u4SetInfoLen = 0; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetCSUMOffload, + (void *) &u4CSUMFlags, + sizeof(uint32_t), + FALSE, FALSE, TRUE, &u4SetInfoLen); + + if (rStatus == WLAN_STATUS_SUCCESS) { + for (i = 0; i < KAL_AIS_NUM; i++) + gprWdev[i]->netdev->features |= + NETIF_F_IP_CSUM | + NETIF_F_IPV6_CSUM | + NETIF_F_RXCSUM; + } else { + DBGLOG(INIT, WARN, + "set HW checksum offload fail 0x%x\n", + rStatus); + prAdapter->fgIsSupportCsumOffload = FALSE; + } + } +#endif +#if CFG_SUPPORT_802_11K + { + uint32_t u4Idx = 0; + + for (u4Idx = 0; u4Idx < KAL_AIS_NUM; u4Idx++) { + uint32_t rStatus = WLAN_STATUS_FAILURE; + uint32_t u4SetInfoLen = 0; + + rStatus = kalIoctlByBssIdx(prGlueInfo, + wlanoidSync11kCapabilities, NULL, 0, + FALSE, FALSE, TRUE, &u4SetInfoLen, + u4Idx); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, WARN, + "[%d] Set 11k Capabilities fail 0x%x\n", + u4Idx, rStatus); + } + } +#endif + return 0; +} + +static void wlanOnPostNetRegister(void) +{ + DBGLOG(INIT, TRACE, "start.\n"); + /* 4 <4> Register early suspend callback */ +#if CFG_ENABLE_EARLY_SUSPEND + glRegisterEarlySuspend(&wlan_early_suspend_desc, + wlan_early_suspend, wlan_late_resume); +#endif + /* 4 <5> Register Notifier callback */ + wlanRegisterInetAddrNotifier(); +} + +static +void wlanOnP2pRegistration(struct GLUE_INFO *prGlueInfo, + struct ADAPTER *prAdapter, + struct wireless_dev *prWdev) +{ + DBGLOG(INIT, TRACE, "start.\n"); + +#if (CFG_ENABLE_WIFI_DIRECT && CFG_MTK_ANDROID_WMT) + register_set_p2p_mode_handler(set_p2p_mode_handler); +#endif + +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->rWifiVar.u4RegP2pIfAtProbe) { + struct PARAM_CUSTOM_P2P_SET_STRUCT rSetP2P; + + rSetP2P.u4Enable = 1; + +#ifdef CFG_DRIVER_INITIAL_RUNNING_MODE + rSetP2P.u4Mode = CFG_DRIVER_INITIAL_RUNNING_MODE; +#else + rSetP2P.u4Mode = RUNNING_P2P_MODE; +#endif /* CFG_DRIVER_RUNNING_MODE */ + if (set_p2p_mode_handler(prWdev->netdev, rSetP2P) == 0) + DBGLOG(INIT, INFO, + "%s: p2p device registered\n", + __func__); + else + DBGLOG(INIT, ERROR, + "%s: Failed to register p2p device\n", + __func__); + } +#endif +} + +static +int32_t wlanOnWhenProbeSuccess(struct GLUE_INFO *prGlueInfo, + struct ADAPTER *prAdapter, + const u_int8_t bAtResetFlow) +{ + int32_t u4LogLevel = ENUM_WIFI_LOG_LEVEL_DEFAULT; + + DBGLOG(INIT, TRACE, "start.\n"); + +#if CFG_SUPPORT_EASY_DEBUG + /* move before reading file + * wlanLoadDefaultCustomerSetting(prAdapter); + */ + wlanFeatureToFw(prGlueInfo->prAdapter, WLAN_CFG_DEFAULT); + + /*if driver backup Engineer Mode CFG setting before*/ + wlanResoreEmCfgSetting(prGlueInfo->prAdapter); + wlanFeatureToFw(prGlueInfo->prAdapter, WLAN_CFG_EM); +#endif + +#if CFG_SUPPORT_IOT_AP_BLACKLIST + wlanCfgLoadIotApRule(prAdapter); + wlanCfgDumpIotApRule(prAdapter); +#endif + if (!bAtResetFlow) { +#if CFG_SUPPORT_AGPS_ASSIST + kalIndicateAgpsNotify(prAdapter, AGPS_EVENT_WLAN_ON, NULL, + 0); +#endif + + wlanCfgSetSwCtrl(prGlueInfo->prAdapter); + wlanCfgSetChip(prGlueInfo->prAdapter); +#if (CFG_SUPPORT_CONNINFRA == 1) + wlanCfgSetChipSyncTime(prGlueInfo->prAdapter); +#endif + wlanCfgSetCountryCode(prGlueInfo->prAdapter); + kalPerMonInit(prGlueInfo); +#if CFG_MET_TAG_SUPPORT + if (met_tag_init() != 0) + DBGLOG(INIT, ERROR, "MET_TAG_INIT error!\n"); +#endif + } + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST + /* Calibration Backup Flow */ + if (!g_fgIsCalDataBackuped) { + if (rlmTriggerCalBackup(prGlueInfo->prAdapter, + g_fgIsCalDataBackuped) == WLAN_STATUS_FAILURE) { + DBGLOG(RFTEST, INFO, + "Error : Boot Time Wi-Fi Enable Fail........\n"); + return -1; + } + + g_fgIsCalDataBackuped = TRUE; + } else { + if (rlmTriggerCalBackup(prGlueInfo->prAdapter, + g_fgIsCalDataBackuped) == WLAN_STATUS_FAILURE) { + DBGLOG(RFTEST, INFO, + "Error : Normal Wi-Fi Enable Fail........\n"); + return -1; + } + } +#endif + + /* card is ready */ + prGlueInfo->u4ReadyFlag = 1; +#if CFG_MTK_ANDROID_WMT + update_driver_loaded_status(prGlueInfo->u4ReadyFlag); +#endif + kalSetHalted(FALSE); + + wlanDbgGetGlobalLogLevel(ENUM_WIFI_LOG_MODULE_FW, + &u4LogLevel); + if (u4LogLevel > ENUM_WIFI_LOG_LEVEL_DEFAULT) + wlanDbgSetLogLevelImpl(prAdapter, + ENUM_WIFI_LOG_LEVEL_VERSION_V1, + ENUM_WIFI_LOG_MODULE_FW, + u4LogLevel); + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + /* sync log status with firmware */ + consys_log_event_notification((int)FW_LOG_CMD_ON_OFF, + u4LogOnOffCache); + if (u4LogLevelCache != -1) { + consys_log_event_notification((int)FW_LOG_CMD_SET_LEVEL, + u4LogLevelCache); + } +#endif + +#if CFG_CHIP_RESET_HANG + if (fgIsResetHangState == SER_L0_HANG_RST_TRGING) { + DBGLOG(INIT, STATE, "[SER][L0] SET hang!\n"); + fgIsResetHangState = SER_L0_HANG_RST_HANG; + fgIsResetting = TRUE; + } + DBGLOG(INIT, STATE, "[SER][L0] PASS!!\n"); +#endif + +#if CFG_MTK_MCIF_WIFI_SUPPORT + mddpNotifyDrvMac(prGlueInfo->prAdapter); +#endif + +#if CFG_SUPPORT_LOWLATENCY_MODE + wlanProbeSuccessForLowLatency(prAdapter); +#endif + +#if (CFG_SUPPORT_CONNINFRA == 1) + if (prAdapter->chip_info->checkbushang) { + fw_log_bug_hang_register(prAdapter->chip_info->checkbushang); + } +#endif + + wlanOnP2pRegistration(prGlueInfo, prAdapter, gprWdev[0]); + if (prAdapter->u4HostStatusEmiOffset) + kalSetSuspendFlagToEMI(prAdapter, FALSE); + return 0; +} + +void wlanOffStopWlanThreads(IN struct GLUE_INFO *prGlueInfo) +{ + DBGLOG(INIT, TRACE, "start.\n"); + + if (prGlueInfo->main_thread == NULL && + prGlueInfo->hif_thread == NULL && + prGlueInfo->rx_thread == NULL) { + DBGLOG(INIT, INFO, + "Threads are already NULL, skip stop and free\n"); + return; + } + +#if CFG_SUPPORT_MULTITHREAD + wake_up_interruptible(&prGlueInfo->waitq_hif); + wait_for_completion_interruptible( + &prGlueInfo->rHifHaltComp); + wake_up_interruptible(&prGlueInfo->waitq_rx); + wait_for_completion_interruptible(&prGlueInfo->rRxHaltComp); +#endif + + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + /* wait main thread stops */ + wait_for_completion_interruptible(&prGlueInfo->rHaltComp); + + DBGLOG(INIT, INFO, "wlan thread stopped\n"); + + /* prGlueInfo->rHifInfo.main_thread = NULL; */ + prGlueInfo->main_thread = NULL; +#if CFG_SUPPORT_MULTITHREAD + prGlueInfo->hif_thread = NULL; + prGlueInfo->rx_thread = NULL; + + prGlueInfo->u4TxThreadPid = 0xffffffff; + prGlueInfo->u4HifThreadPid = 0xffffffff; +#endif + + if (test_and_clear_bit(GLUE_FLAG_OID_BIT, &prGlueInfo->ulFlag) && + !completion_done(&prGlueInfo->rPendComp)) { + struct GL_IO_REQ *prIoReq; + + DBGLOG(INIT, INFO, "Complete on-going ioctl as failure.\n"); + prIoReq = &(prGlueInfo->OidEntry); + prIoReq->rStatus = WLAN_STATUS_FAILURE; + complete(&prGlueInfo->rPendComp); + } +} + + +#if CFG_CHIP_RESET_SUPPORT +/*----------------------------------------------------------------------------*/ +/*! + * \brief slight off procedure for chip reset + * + * \return + * WLAN_STATUS_FAILURE - reset off fail + * WLAN_STATUS_SUCCESS - reset off success + */ +/*----------------------------------------------------------------------------*/ +static int32_t wlanOffAtReset(void) +{ + struct ADAPTER *prAdapter = NULL; + struct net_device *prDev = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + + DBGLOG(INIT, INFO, "Driver Off during Reset\n"); + + if (u4WlanDevNum > 0 + && u4WlanDevNum <= CFG_MAX_WLAN_DEVICES) { + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + } + + if (prDev == NULL) { + DBGLOG(INIT, ERROR, "prDev is NULL\n"); + return WLAN_STATUS_FAILURE; + } + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + if (prGlueInfo == NULL) { + DBGLOG(INIT, INFO, "prGlueInfo is NULL\n"); + wlanFreeNetDev(); + return WLAN_STATUS_FAILURE; + } + + prAdapter = prGlueInfo->prAdapter; + if (prAdapter == NULL) { + DBGLOG(INIT, INFO, "prAdapter is NULL\n"); + wlanFreeNetDev(); + return WLAN_STATUS_FAILURE; + } + + /* to avoid that wpa_supplicant/hostapd triogger new cfg80211 command */ + prGlueInfo->u4ReadyFlag = 0; +#if CFG_MTK_ANDROID_WMT + update_driver_loaded_status(prGlueInfo->u4ReadyFlag); +#endif + kalPerMonDestroy(prGlueInfo); + + /* complete possible pending oid, which may block wlanRemove some time + * and then whole chip reset may failed + */ + wlanReleasePendingOid(prGlueInfo->prAdapter, 1); + + flush_delayed_work(&workq); + + flush_delayed_work(&sched_workq); + + /* 4 <2> Mark HALT, notify main thread to stop, and clean up queued + * requests + */ + set_bit(GLUE_FLAG_HALT_BIT, &prGlueInfo->ulFlag); + + /* Stop works */ + flush_work(&prGlueInfo->rTxMsduFreeWork); + + wlanOffStopWlanThreads(prGlueInfo); + + wlanAdapterStop(prAdapter, TRUE); + + /* 4 Stopping handling interrupt and free IRQ */ + glBusFreeIrq(prDev, prGlueInfo); + +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanDebugTC4Uninit(); +#endif + +#if (CFG_SUPPORT_STATISTICS == 1) + wlanWakeStaticsUninit(); +#endif + + fgSimplifyResetFlow = TRUE; + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief A slight wlan on for chip reset + * + * \return + * WLAN_STATUS_FAILURE - reset on fail + * WLAN_STATUS_SUCCESS - reset on success + */ +/*----------------------------------------------------------------------------*/ +static int32_t wlanOnAtReset(void) +{ + struct net_device *prDev = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + uint32_t u4DisconnectReason = DISCONNECT_REASON_CODE_CHIPRESET; + uint32_t u4Idx = 0; + + enum ENUM_PROBE_FAIL_REASON { + BUS_INIT_FAIL, + NET_CREATE_FAIL, + BUS_SET_IRQ_FAIL, + ADAPTER_START_FAIL, + NET_REGISTER_FAIL, + PROC_INIT_FAIL, + FAIL_MET_INIT_PROCFS, + FAIL_REASON_NUM + } eFailReason = FAIL_REASON_NUM; + + DBGLOG(INIT, INFO, "Driver On during Reset\n"); + + if (u4WlanDevNum > 0 + && u4WlanDevNum <= CFG_MAX_WLAN_DEVICES) { + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + } + + if (prDev == NULL) { + DBGLOG(INIT, ERROR, "prDev is NULL\n"); + return WLAN_STATUS_FAILURE; + } + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + if (prGlueInfo == NULL) { + DBGLOG(INIT, INFO, "prGlueInfo is NULL\n"); + wlanFreeNetDev(); + return WLAN_STATUS_FAILURE; + } + + prAdapter = prGlueInfo->prAdapter; + if (prAdapter == NULL) { + DBGLOG(INIT, INFO, "prAdapter is NULL\n"); + return WLAN_STATUS_FAILURE; + } + + prGlueInfo->ulFlag = 0; + fgSimplifyResetFlow = FALSE; + do { +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanDebugTC4Init(); +#endif +#if (CFG_SUPPORT_STATISTICS == 1) + wlanWakeStaticsInit(); +#endif + /* wlanNetCreate partial process */ + QUEUE_INITIALIZE(&prGlueInfo->rCmdQueue); + prGlueInfo->i4TxPendingCmdNum = 0; + QUEUE_INITIALIZE(&prGlueInfo->rTxQueue); + + rStatus = glBusSetIrq(prDev, NULL, prGlueInfo); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "Set IRQ error\n"); + eFailReason = BUS_SET_IRQ_FAIL; + break; + } + + /* Trigger the action of switching Pwr state to drv_own */ + prAdapter->fgIsFwOwn = TRUE; + + /* wlanAdapterStart Section Start */ + rStatus = wlanAdapterStart(prAdapter, + &prGlueInfo->rRegInfo, + TRUE); + if (rStatus != WLAN_STATUS_SUCCESS) { + eFailReason = ADAPTER_START_FAIL; + break; + } + + wlanOnPreNetRegister(prGlueInfo, prAdapter, + prAdapter->chip_info, + &prAdapter->rWifiVar, + TRUE); + + /* Resend schedule scan */ + prAdapter->rWifiVar.rScanInfo.fgSchedScanning = FALSE; +#if CFG_SUPPORT_SCHED_SCAN + if (prGlueInfo->prSchedScanRequest) { + rStatus = kalIoctl(prGlueInfo, wlanoidSetStartSchedScan, + prGlueInfo->prSchedScanRequest, + sizeof(struct PARAM_SCHED_SCAN_REQUEST), + false, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, WARN, + "SCN: Start sched scan failed after chip reset 0x%x\n", + rStatus); + } +#endif + + for (u4Idx = 0; u4Idx < KAL_AIS_NUM; u4Idx++) { + struct FT_IES *prFtIEs = + aisGetFtIe(prAdapter, u4Idx); + struct CONNECTION_SETTINGS *prConnSettings = + aisGetConnSettings(prAdapter, u4Idx); + + kalMemZero(prFtIEs, + sizeof(*prFtIEs)); + prConnSettings->fgIsScanReqIssued = FALSE; + } + + } while (FALSE); + + if (rStatus == WLAN_STATUS_SUCCESS) { + wlanOnWhenProbeSuccess(prGlueInfo, prAdapter, TRUE); + DBGLOG(INIT, INFO, "reset success\n"); + + /* Send disconnect */ + for (u4Idx = 0; u4Idx < KAL_AIS_NUM; u4Idx++) { + rStatus = kalIoctlByBssIdx(prGlueInfo, + wlanoidSetDisassociate, + &u4DisconnectReason, + 0, FALSE, FALSE, TRUE, &u4BufLen, + u4Idx); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, + "disassociate error:%x\n", rStatus); + continue; + } + DBGLOG(INIT, INFO, + "%d inform disconnected\n", u4Idx); + } + } else { + prAdapter->u4HifDbgFlag |= DEG_HIF_DEFAULT_DUMP; + halPrintHifDbgInfo(prAdapter); + DBGLOG(INIT, WARN, "Fail reason: %d\n", eFailReason); + + /* Remove error handling here, leave it to coming wlanRemove + * for full clean. + * + * If WMT being removed in the future, you should invoke + * wlanRemove directly from here + */ +#if 0 + switch (eFailReason) { + case ADAPTER_START_FAIL: + glBusFreeIrq(prDev, + *((struct GLUE_INFO **) + netdev_priv(prDev))); + /* fallthrough */ + case BUS_SET_IRQ_FAIL: + wlanWakeLockUninit(prGlueInfo); + wlanNetDestroy(prDev->ieee80211_ptr); + /* prGlueInfo->prAdapter is released in + * wlanNetDestroy + */ + /* Set NULL value for local prAdapter as well */ + prAdapter = NULL; + break; + default: + break; + } +#endif + } + return rStatus; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \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 int32_t wlanProbe(void *pvData, void *pvDriverData) +{ + struct wireless_dev *prWdev = NULL; + enum ENUM_PROBE_FAIL_REASON { + BUS_INIT_FAIL, + NET_CREATE_FAIL, + BUS_SET_IRQ_FAIL, + ADAPTER_START_FAIL, + NET_REGISTER_FAIL, + PROC_INIT_FAIL, + FAIL_MET_INIT_PROCFS, + FAIL_BY_RESET, + FAIL_REASON_NUM + } eFailReason; + struct WLANDEV_INFO *prWlandevInfo = NULL; + int32_t i4DevIdx = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + int32_t i4Status = 0; + u_int8_t bRet = FALSE; + u_int8_t i = 0; + struct REG_INFO *prRegInfo; + struct mt66xx_chip_info *prChipInfo; + struct WIFI_VAR *prWifiVar; + uint32_t u4Idx = 0; + +#if CFG_MTK_MCIF_WIFI_SUPPORT + mddpNotifyWifiOnStart(); +#endif + +#if CFG_CHIP_RESET_SUPPORT + if (fgSimplifyResetFlow) { + i4Status = wlanOnAtReset(); +#if CFG_MTK_MCIF_WIFI_SUPPORT + if (i4Status == WLAN_STATUS_SUCCESS) + mddpNotifyWifiOnEnd(); +#endif + return i4Status; + } +#endif + +#if 0 + uint8_t *pucConfigBuf = NULL, pucCfgBuf = NULL; + uint32_t u4ConfigReadLen = 0; +#endif + + eFailReason = FAIL_REASON_NUM; + do { + /* 4 <1> Initialize the IO port of the interface */ + /* GeorgeKuo: pData has different meaning for _HIF_XXX: + * _HIF_EHPI: pointer to memory base variable, which will be + * initialized by glBusInit(). + * _HIF_SDIO: bus driver handle + */ + + DBGLOG(INIT, INFO, "enter wlanProbe\n"); + + bRet = glBusInit(pvData); + +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanDebugTC4Init(); +#endif + +#if (CFG_SUPPORT_STATISTICS == 1) + wlanWakeStaticsInit(); +#endif + /* Cannot get IO address from interface */ + if (bRet == FALSE) { + DBGLOG(INIT, ERROR, "wlanProbe: glBusInit() fail\n"); + i4Status = -EIO; + eFailReason = BUS_INIT_FAIL; + break; + } + /* 4 <2> Create network device, Adapter, KalInfo, + * prDevHandler(netdev) + */ + prWdev = wlanNetCreate(pvData, pvDriverData); + if (prWdev == NULL) { + DBGLOG(INIT, ERROR, + "wlanProbe: No memory for dev and its private\n"); + i4Status = -ENOMEM; + eFailReason = NET_CREATE_FAIL; + break; + } + /* 4 <2.5> Set the ioaddr to HIF Info */ + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(prWdev->wiphy); + gPrDev = prGlueInfo->prDevHandler; + + /* 4 <4> Setup IRQ */ + prWlandevInfo = &arWlanDevInfo[i4DevIdx]; + + i4Status = glBusSetIrq(prWdev->netdev, NULL, prGlueInfo); + + if (i4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "wlanProbe: Set IRQ error\n"); + eFailReason = BUS_SET_IRQ_FAIL; + break; + } + + prGlueInfo->i4DevIdx = i4DevIdx; + + prAdapter = prGlueInfo->prAdapter; + prWifiVar = &prAdapter->rWifiVar; + + wlanOnPreAdapterStart(prGlueInfo, + prAdapter, + &prRegInfo, + &prChipInfo); + + if (wlanAdapterStart(prAdapter, + prRegInfo, FALSE) != WLAN_STATUS_SUCCESS) + i4Status = -EIO; + + wlanOnPostAdapterStart(prAdapter, prGlueInfo); + + /* kfree(prRegInfo); */ + + if (i4Status < 0) { + eFailReason = ADAPTER_START_FAIL; + break; + } + + wlanOnPreNetRegister(prGlueInfo, prAdapter, prChipInfo, + prWifiVar, FALSE); + + /* 4 <3> Register the card */ + i4DevIdx = wlanNetRegister(prWdev); + if (i4DevIdx < 0) { + i4Status = -ENXIO; + DBGLOG(INIT, ERROR, + "wlanProbe: Cannot register the net_device context to the kernel\n"); + eFailReason = NET_REGISTER_FAIL; + break; + } + + wlanOnPostNetRegister(); + + /* 4 <6> Initialize /proc filesystem */ +#if WLAN_INCLUDE_PROC + i4Status = procCreateFsEntry(prGlueInfo); + if (i4Status < 0) { + DBGLOG(INIT, ERROR, "wlanProbe: init procfs failed\n"); + eFailReason = PROC_INIT_FAIL; + break; + } +#endif /* WLAN_INCLUDE_PROC */ +#if WLAN_INCLUDE_SYS + i4Status = sysCreateFsEntry(prGlueInfo); + if (i4Status < 0) { + DBGLOG(INIT, ERROR, "wlanProbe: init sysfs failed\n"); + eFailReason = PROC_INIT_FAIL; + break; + } +#endif /* WLAN_INCLUDE_SYS */ + +#if CFG_MET_PACKET_TRACE_SUPPORT + kalMetInit(prGlueInfo); +#endif + + kalWlanUeventInit(); + +#if CFG_ENABLE_BT_OVER_WIFI + prGlueInfo->rBowInfo.fgIsNetRegistered = FALSE; + prGlueInfo->rBowInfo.fgIsRegistered = FALSE; + glRegisterAmpc(prGlueInfo); +#endif + +#if (CONFIG_WLAN_SERVICE == 1) + wlanServiceInit(prGlueInfo); +#endif + +#if (CFG_MET_PACKET_TRACE_SUPPORT == 1) + DBGLOG(INIT, TRACE, "init MET procfs...\n"); + i4Status = kalMetInitProcfs(prGlueInfo); + if (i4Status < 0) { + DBGLOG(INIT, ERROR, + "wlanProbe: init MET procfs failed\n"); + eFailReason = FAIL_MET_INIT_PROCFS; + break; + } +#endif + + for (u4Idx = 0; u4Idx < KAL_AIS_NUM; u4Idx++) { + struct FT_IES *prFtIEs = + aisGetFtIe(prAdapter, u4Idx); + + kalMemZero(prFtIEs, + sizeof(*prFtIEs)); + } + + /* Configure 5G band for registered wiphy */ + if (prAdapter->fgEnable5GBand) + prWdev->wiphy->bands[KAL_BAND_5GHZ] = &mtk_band_5ghz; + else + prWdev->wiphy->bands[KAL_BAND_5GHZ] = NULL; + + for (i = 0 ; i < KAL_P2P_NUM; i++) { + if (gprP2pRoleWdev[i] == NULL) + continue; + + if (prAdapter->fgEnable5GBand) + gprP2pRoleWdev[i]->wiphy->bands[KAL_BAND_5GHZ] = + &mtk_band_5ghz; + else + gprP2pRoleWdev[i]->wiphy->bands[KAL_BAND_5GHZ] = + NULL; + } + } while (FALSE); + + if (i4Status == 0 && kalIsResetting()) { + DBGLOG(INIT, WARN, "Fake wlan on success due to reset.\n"); + eFailReason = FAIL_BY_RESET; + i4Status = WLAN_STATUS_FAILURE; + } + + if (i4Status == 0) { + wlanOnWhenProbeSuccess(prGlueInfo, prAdapter, FALSE); + DBGLOG(INIT, INFO, + "wlanProbe: probe success, feature set: 0x%llx, persistNetdev: %d\n", + wlanGetSupportedFeatureSet(prGlueInfo), + CFG_SUPPORT_PERSIST_NETDEV); +#if CFG_MTK_MCIF_WIFI_SUPPORT + mddpNotifyWifiOnEnd(); +#endif +#if ARP_BRUST_OPTIMIZE + arp_brust_opt_init(prAdapter); +#endif + } else { + DBGLOG(INIT, ERROR, "wlanProbe: probe failed, reason:%d\n", + eFailReason); + switch (eFailReason) { + case FAIL_BY_RESET: + case FAIL_MET_INIT_PROCFS: + kalMetRemoveProcfs(); + case PROC_INIT_FAIL: + wlanNetUnregister(prWdev); + case NET_REGISTER_FAIL: + set_bit(GLUE_FLAG_HALT_BIT, &prGlueInfo->ulFlag); + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + /* wait main thread stops */ + wait_for_completion_interruptible( + &prGlueInfo->rHaltComp); + wlanAdapterStop(prAdapter, FALSE); + /* fallthrough */ + case ADAPTER_START_FAIL: + glBusFreeIrq(prWdev->netdev, + *((struct GLUE_INFO **) + netdev_priv(prWdev->netdev))); + /* fallthrough */ + case BUS_SET_IRQ_FAIL: + wlanWakeLockUninit(prGlueInfo); + wlanNetDestroy(prWdev); + /* prGlueInfo->prAdapter is released in + * wlanNetDestroy + */ + /* Set NULL value for local prAdapter as well */ + prAdapter = NULL; + break; + case NET_CREATE_FAIL: + break; + case BUS_INIT_FAIL: + break; + default: + break; + } + } + return i4Status; +} /* end of wlanProbe() */ + +void +wlanOffNotifyCfg80211Disconnect(IN struct GLUE_INFO *prGlueInfo) +{ + uint32_t u4Idx = 0; + u_int8_t bNotify = FALSE; + + DBGLOG(INIT, TRACE, "start.\n"); + + for (u4Idx = 0; u4Idx < KAL_AIS_NUM; u4Idx++) { + if (kalGetMediaStateIndicated(prGlueInfo, + u4Idx) == + MEDIA_STATE_CONNECTED) { + struct net_device *prDevHandler = + wlanGetNetDev(prGlueInfo, u4Idx); + if (!prDevHandler) + continue; +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 2, 0) <= CFG80211_VERSION_CODE) + cfg80211_disconnected( + prDevHandler, 0, NULL, 0, + TRUE, GFP_KERNEL); +#else + cfg80211_disconnected( + prDevHandler, 0, NULL, 0, + GFP_KERNEL); +#endif + bNotify = TRUE; + } + } + if (bNotify) + kalMsleep(500); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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; + struct WLANDEV_INFO *prWlandevInfo = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + u_int8_t fgResult = FALSE; + + DBGLOG(INIT, INFO, "Remove wlan!\n"); + + kalSetHalted(TRUE); + + /*reset NVRAM State to ready for the next wifi-no*/ + if (g_NvramFsm == NVRAM_STATE_SEND_TO_FW) + g_NvramFsm = NVRAM_STATE_READY; + + +#if CFG_MTK_MCIF_WIFI_SUPPORT + mddpNotifyWifiOffStart(); +#endif + +#if CFG_CHIP_RESET_SUPPORT + /* During chip reset, use simplify remove flow first + * if anything goes wrong in wlanOffAtReset then goes to normal flow + */ + if (fgSimplifyResetFlow) { + if (wlanOffAtReset() == WLAN_STATUS_SUCCESS) { +#if CFG_MTK_MCIF_WIFI_SUPPORT + mddpNotifyWifiOffEnd(); +#endif + return; + } + } +#endif + + /* 4 <0> Sanity check */ + ASSERT(u4WlanDevNum <= CFG_MAX_WLAN_DEVICES); + if (u4WlanDevNum == 0) { + DBGLOG(INIT, ERROR, "u4WlanDevNum = 0\n"); + return; + } +#if (CFG_ENABLE_WIFI_DIRECT && CFG_MTK_ANDROID_WMT) + register_set_p2p_mode_handler(NULL); +#endif + if (u4WlanDevNum > 0 + && u4WlanDevNum <= CFG_MAX_WLAN_DEVICES) { + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + prWlandevInfo = &arWlanDevInfo[u4WlanDevNum - 1]; + } + + ASSERT(prDev); + if (prDev == NULL) { + DBGLOG(INIT, ERROR, "prDev is NULL\n"); + return; + } + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + ASSERT(prGlueInfo); + if (prGlueInfo == NULL) { + DBGLOG(INIT, INFO, "prGlueInfo is NULL\n"); + wlanFreeNetDev(); + return; + } + +#if (CONFIG_WLAN_SERVICE == 1) + wlanServiceExit(prGlueInfo); +#endif + + /* to avoid that wpa_supplicant/hostapd triogger new cfg80211 command */ + prGlueInfo->u4ReadyFlag = 0; +#if CFG_MTK_ANDROID_WMT + update_driver_loaded_status(prGlueInfo->u4ReadyFlag); +#endif + + /* Have tried to do scan done here, but the exception occurs for */ + /* the P2P scan. Keep the original design that scan done in the */ + /* p2pStop/wlanStop. */ + +#if WLAN_INCLUDE_PROC + procRemoveProcfs(); +#endif /* WLAN_INCLUDE_PROC */ +#if WLAN_INCLUDE_SYS + sysRemoveSysfs(); +#endif /* WLAN_INCLUDE_SYS */ + + prAdapter = prGlueInfo->prAdapter; + kalPerMonDestroy(prGlueInfo); + + /* Unregister notifier callback */ + wlanUnregisterInetAddrNotifier(); + + /*backup EM mode cfg setting*/ + wlanBackupEmCfgSetting(prAdapter); + + /* complete possible pending oid, which may block wlanRemove some time + * and then whole chip reset may failed + */ + if (kalIsResetting()) + wlanReleasePendingOid(prGlueInfo->prAdapter, 1); + + nicSerDeInit(prGlueInfo->prAdapter); + +#if CFG_ENABLE_BT_OVER_WIFI + if (prGlueInfo->rBowInfo.fgIsNetRegistered) { + bowNotifyAllLinkDisconnected(prGlueInfo->prAdapter); + /* wait 300ms for BoW module to send deauth */ + kalMsleep(300); + } +#endif + + wlanOffNotifyCfg80211Disconnect(prGlueInfo); + + /* 20150205 work queue for sched_scan */ + + flush_delayed_work(&sched_workq); + + down(&g_halt_sem); + g_u4HaltFlag = 1; + up(&g_halt_sem); + + /* 4 <2> Mark HALT, notify main thread to stop, and clean up queued + * requests + */ + set_bit(GLUE_FLAG_HALT_BIT, &prGlueInfo->ulFlag); + + /* Stop works */ + flush_work(&prGlueInfo->rTxMsduFreeWork); + cancel_delayed_work_sync(&prGlueInfo->rRxPktDeAggWork); + + wlanOffStopWlanThreads(prGlueInfo); + + if (HAL_IS_TX_DIRECT(prAdapter)) { + if (prAdapter->fgTxDirectInited) { + del_timer_sync(&prAdapter->rTxDirectSkbTimer); + del_timer_sync(&prAdapter->rTxDirectHifTimer); + } + } + + /* Destroy wakelock */ + wlanWakeLockUninit(prGlueInfo); + + kalMemSet(&(prGlueInfo->prAdapter->rWlanInfo), 0, + sizeof(struct WLAN_INFO)); + +#if CFG_ENABLE_WIFI_DIRECT + if (prGlueInfo->prAdapter->fgIsP2PRegistered) { + DBGLOG(INIT, INFO, "p2pNetUnregister...\n"); + p2pNetUnregister(prGlueInfo, FALSE); + DBGLOG(INIT, INFO, "p2pRemove...\n"); + /*p2pRemove must before wlanAdapterStop */ + p2pRemove(prGlueInfo); + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + if (prGlueInfo->rBowInfo.fgIsRegistered) + glUnregisterAmpc(prGlueInfo); +#endif + +#if (CFG_MET_PACKET_TRACE_SUPPORT == 1) + kalMetRemoveProcfs(); +#endif + + kalWlanUeventDeinit(); + +#if CFG_MET_TAG_SUPPORT + if (GL_MET_TAG_UNINIT() != 0) + DBGLOG(INIT, ERROR, "MET_TAG_UNINIT error!\n"); +#endif + + /* 4 <4> wlanAdapterStop */ +#if CFG_SUPPORT_AGPS_ASSIST + kalIndicateAgpsNotify(prAdapter, AGPS_EVENT_WLAN_OFF, NULL, + 0); +#endif + + wlanAdapterStop(prAdapter, FALSE); + + HAL_LP_OWN_SET(prAdapter, &fgResult); + DBGLOG(INIT, INFO, "HAL_LP_OWN_SET(%d)\n", + (uint32_t) fgResult); + + /* 4 Stopping handling interrupt and free IRQ */ + glBusFreeIrq(prDev, prGlueInfo); + + /* 4 <5> Release the Bus */ + glBusRelease(prDev); + +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanDebugTC4Uninit(); +#endif + +#if (CFG_SUPPORT_STATISTICS == 1) + wlanWakeStaticsUninit(); +#endif + + /* 4 <6> Unregister the card */ + wlanNetUnregister(prDev->ieee80211_ptr); + + flush_delayed_work(&workq); + + /* 4 <7> Destroy the device */ + wlanNetDestroy(prDev->ieee80211_ptr); + prDev = NULL; + + tasklet_kill(&prGlueInfo->rTxCompleteTask); + tasklet_kill(&prGlueInfo->rRxTask); + + /* 4 <8> Unregister early suspend callback */ +#if CFG_ENABLE_EARLY_SUSPEND + glUnregisterEarlySuspend(&wlan_early_suspend_desc); +#endif + +#if !CFG_SUPPORT_PERSIST_NETDEV + { + uint32_t u4Idx = 0; + + for (u4Idx = 0; u4Idx < KAL_AIS_NUM; u4Idx++) { + if (gprWdev[u4Idx] && gprWdev[u4Idx]->netdev) + gprWdev[u4Idx]->netdev = NULL; + } + } +#endif + +#if CFG_CHIP_RESET_SUPPORT + fgIsResetting = FALSE; +#if (CFG_SUPPORT_CONNINFRA == 1) + update_driver_reset_status(fgIsResetting); +#endif +#endif + +#if CFG_MTK_MCIF_WIFI_SUPPORT + mddpNotifyWifiOffEnd(); +#endif +} /* end of wlanRemove() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Driver entry point when the driver is configured as a Linux Module, + * and is called once at module load time, by the user-level modutils + * application: insmod or modprobe. + * + * \retval 0 Success + */ +/*----------------------------------------------------------------------------*/ +/* 1 Module Entry Point */ +static int initWlan(void) +{ + int ret = 0; + struct GLUE_INFO *prGlueInfo = NULL; + +#if defined(UT_TEST_MODE) && defined(CFG_BUILD_X86_PLATFORM) + /* Refer 6765 dts setting */ + char *ptr = NULL; + + gConEmiSize = 0x400000; + ptr = kmalloc(gConEmiSize, GFP_KERNEL); + if (!ptr) { + DBGLOG(INIT, INFO, + "initWlan try to allocate 0x%x bytes memory error\n", + gConEmiSize); + return -EINVAL; + } + memset(ptr, 0, gConEmiSize); + gConEmiPhyBase = (phys_addr_t)ptr; +#endif + + + + DBGLOG(INIT, INFO, "initWlan\n"); + +#ifdef CFG_DRIVER_INF_NAME_CHANGE + + if (kalStrLen(gprifnamesta) > CUSTOM_IFNAMESIZ || + kalStrLen(gprifnamep2p) > CUSTOM_IFNAMESIZ || + kalStrLen(gprifnameap) > CUSTOM_IFNAMESIZ) { + DBGLOG(INIT, ERROR, "custom infname len illegal > %d\n", + CUSTOM_IFNAMESIZ); + return -EINVAL; + } + +#endif /* CFG_DRIVER_INF_NAME_CHANGE */ + + wlanDebugInit(); + + /* memory pre-allocation */ +#if CFG_PRE_ALLOCATION_IO_BUFFER + kalInitIOBuffer(TRUE); +#else + kalInitIOBuffer(FALSE); +#endif + + +#if WLAN_INCLUDE_PROC + procInitFs(); +#endif +#if WLAN_INCLUDE_SYS + sysInitFs(); +#endif + + wlanCreateWirelessDevice(); + if (gprWdev[0] == NULL) + return -ENOMEM; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv( + wlanGetWiphy()); + if (gprWdev[0]) { + /* P2PDev and P2PRole[0] share the same Wdev */ + if (glP2pCreateWirelessDevice(prGlueInfo) == TRUE) + gprP2pWdev = gprP2pRoleWdev[0]; + } + gPrDev = NULL; + +#if CFG_MTK_ANDROID_WMT && (CFG_SUPPORT_CONNINFRA == 0) + mtk_wcn_wmt_mpu_lock_aquire(); +#endif + ret = ((glRegisterBus(wlanProbe, + wlanRemove) == WLAN_STATUS_SUCCESS) ? 0 : -EIO); +#ifdef CONFIG_MTK_EMI + /* Set WIFI EMI protection to consys permitted on system boot up */ + kalSetEmiMpuProtection(gConEmiPhyBase, true); +#endif +#if CFG_MTK_ANDROID_WMT && (CFG_SUPPORT_CONNINFRA == 0) + mtk_wcn_wmt_mpu_lock_release(); +#endif + + if (ret == -EIO) { + kalUninitIOBuffer(); + return ret; + } +#if (CFG_CHIP_RESET_SUPPORT) + glResetInit(prGlueInfo); +#endif + kalFbNotifierReg((struct GLUE_INFO *) wiphy_priv( + wlanGetWiphy())); + wlanRegisterNetdevNotifier(); + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + wifi_fwlog_event_func_register(consys_log_event_notification); +#endif + +#if CFG_MTK_MCIF_WIFI_SUPPORT + mddpInit(); +#endif + + g_u4WlanInitFlag = 1; + DBGLOG(INIT, INFO, "initWlan::End\n"); + + return ret; +} /* end of initWlan() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Driver exit point when the driver as a Linux Module is removed. Called + * at module unload time, by the user level modutils application: rmmod. + * This is our last chance to clean up after ourselves. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +/* 1 Module Leave Point */ +static void exitWlan(void) +{ +#if CFG_SUPPORT_PERSIST_NETDEV + uint32_t u4Idx = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct wiphy *wiphy = NULL; + + wiphy = wlanGetWiphy(); + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + for (u4Idx = 0; u4Idx < KAL_AIS_NUM; u4Idx++) { + if (gprNetdev[u4Idx]) { + wlanClearDevIdx(gprWdev[u4Idx]->netdev); + DBGLOG(INIT, INFO, "Unregister wlan%d netdev start.\n", + u4Idx); + unregister_netdev(gprWdev[u4Idx]->netdev); + DBGLOG(INIT, INFO, "Unregister wlan%d netdev end.\n", + u4Idx); + gprWdev[u4Idx]->netdev = gprNetdev[u4Idx] = NULL; + } + } + + prGlueInfo->fgIsRegistered = FALSE; + + DBGLOG(INIT, INFO, "Free wlan device..\n"); + wlanFreeNetDev(); +#endif + kalFbNotifierUnReg(); + wlanUnregisterNetdevNotifier(); + + /* printk("remove %p\n", wlanRemove); */ +#if CFG_CHIP_RESET_SUPPORT + glResetUninit(); +#endif + + glUnregisterBus(wlanRemove); + + /* free pre-allocated memory */ + kalUninitIOBuffer(); + + /* For single wiphy case, it's hardly to free wdev & wiphy in 2 func. + * So that, use wlanDestroyAllWdev to replace wlanDestroyWirelessDevice + * and glP2pDestroyWirelessDevice. + */ + wlanDestroyAllWdev(); + +#if WLAN_INCLUDE_PROC + procUninitProcFs(); +#endif +#if WLAN_INCLUDE_SYS + sysUninitSysFs(); +#endif +#if defined(UT_TEST_MODE) && defined(CFG_BUILD_X86_PLATFORM) + kfree((const void *)gConEmiPhyBase); +#endif + + g_u4WlanInitFlag = 0; + DBGLOG(INIT, INFO, "exitWlan\n"); + +} /* end of exitWlan() */ + +#if ((MTK_WCN_HIF_SDIO == 1) && (CFG_BUILT_IN_DRIVER == 1)) || \ + ((MTK_WCN_HIF_AXI == 1) && (CFG_BUILT_IN_DRIVER == 1)) + +int mtk_wcn_wlan_gen4_init(void) +{ + return initWlan(); +} +EXPORT_SYMBOL(mtk_wcn_wlan_gen4_init); + +void mtk_wcn_wlan_gen4_exit(void) +{ + return exitWlan(); +} +EXPORT_SYMBOL(mtk_wcn_wlan_gen4_exit); + +#elif ((MTK_WCN_HIF_SDIO == 0) && (CFG_BUILT_IN_DRIVER == 1)) + +device_initcall(initWlan); + +#else + +module_init(initWlan); +module_exit(exitWlan); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_kal.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_kal.c new file mode 100644 index 0000000000000..8f4a3af99e360 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_kal.c @@ -0,0 +1,8943 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux + * /gl_kal.c#10 + */ + +/*! \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. + */ + + +/******************************************************************************* + * C O M P I L E 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 "gl_wext.h" +#include "precomp.h" +#include + +#if CFG_SUPPORT_AGPS_ASSIST +#include +#endif + +#if CFG_TC1_FEATURE +#include +#endif + +/* for rps */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* for uevent */ +#include /* for misc_register, and SYNTH_MINOR */ +#include + +/* for wifi standalone log */ +#define CREATE_TRACE_POINTS +#include "mtk_wifi_trace.h" +#include +#include +#include + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +/* the maximum length of a file name */ +#define FILE_NAME_MAX CFG_FW_NAME_MAX_LEN + +/* the maximum number of all possible file name */ +#define FILE_NAME_TOTAL 8 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +#if DBG +int allocatedMemSize; +#endif + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +static void *pvIoBuffer; +static uint32_t pvIoBufferSize; +static uint32_t pvIoBufferUsage; + +static struct KAL_HALT_CTRL_T rHaltCtrl = { + .lock = __SEMAPHORE_INITIALIZER(rHaltCtrl.lock, 1), + .owner = NULL, + .fgHalt = TRUE, + .fgHeldByKalIoctl = FALSE, + .u4HoldStart = 0, +}; +/* framebuffer callback related variable and status flag */ +u_int8_t wlan_fb_power_down = FALSE; + +#if CFG_FORCE_ENABLE_PERF_MONITOR +u_int8_t wlan_perf_monitor_force_enable = TRUE; +#else +u_int8_t wlan_perf_monitor_force_enable = FALSE; +#endif + +static struct notifier_block wlan_fb_notifier; +void *wlan_fb_notifier_priv_data; + +static struct miscdevice wlan_object; + +static unsigned long rtc_update; +/******************************************************************************* + * M A 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 kalDumpHifStats(IN struct ADAPTER *prAdapter); +static uint32_t kalPerMonUpdate(IN struct ADAPTER *prAdapter); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#if CFG_ENABLE_FW_DOWNLOAD + +#if (defined(CONFIG_UIDGID_STRICT_TYPE_CHECKS) || \ + (KERNEL_VERSION(3, 14, 0) <= LINUX_VERSION_CODE)) +#define KUIDT_VALUE(v) (v.val) +#define KGIDT_VALUE(v) (v.val) +#else +#define KUIDT_VALUE(v) v +#define KGIDT_VALUE(v) v +#endif + +const struct firmware *fw_entry; + +/* Default */ +static uint8_t *apucFwName[] = { + (uint8_t *) CFG_FW_FILENAME "_MT", + (uint8_t *) CFG_FW_FILENAME "_", + NULL +}; + +static uint8_t *apucCr4FwName[] = { + (uint8_t *) CFG_CR4_FW_FILENAME "_MT", + NULL +}; + +#if CFG_ASSERT_DUMP +/* Core dump debug usage */ +#if MTK_WCN_HIF_SDIO +uint8_t *apucCorDumpN9FileName = + "/data/misc/wifi/FW_DUMP_N9"; +uint8_t *apucCorDumpCr4FileName = + "/data/misc/wifi/FW_DUMP_Cr4"; +#else +uint8_t *apucCorDumpN9FileName = "/tmp/FW_DUMP_N9"; +uint8_t *apucCorDumpCr4FileName = "/tmp/FW_DUMP_Cr4"; +#endif +#endif + +#if !CONFIG_WLAN_DRV_BUILD_IN +/*----------------------------------------------------------------------------*/ +/*! + * \brief To leverage systrace, use the same name, i.e. tracing_mark_write, + * which ftrace would write when systrace writes msg to + * /sys/kernel/debug/tracing/trace_marker with trace_options enabling + * print-parent + * + */ +/*----------------------------------------------------------------------------*/ +void tracing_mark_write(const char *fmt, ...) +{ + const uint32_t BUFFER_SIZE = 1024; + va_list ap; + char buf[BUFFER_SIZE]; + + if ((aucDebugModule[DBG_TRACE_IDX] & DBG_CLASS_TEMP) == 0) + return; + + va_start(ap, fmt); + vsnprintf(buf, BUFFER_SIZE, fmt, ap); + buf[BUFFER_SIZE - 1] = '\0'; + va_end(ap); + + trace_printk("%s", buf); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \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. + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t kalFirmwareOpen(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t **apucNameTable) +{ + uint8_t ucNameIdx; + /* PPUINT_8 apucNameTable; */ + uint8_t ucCurEcoVer = wlanGetEcoVersion( + prGlueInfo->prAdapter); + u_int8_t fgResult = FALSE; + int ret; + + /* Try to open FW binary */ + for (ucNameIdx = 0; apucNameTable[ucNameIdx]; ucNameIdx++) { + /* + * Driver support request_firmware() to get files + * Android path: "/etc/firmware", "/vendor/firmware", + * "/firmware/image" + * Linux path: "/lib/firmware", "/lib/firmware/update" + */ + ret = _kalRequestFirmware(&fw_entry, apucNameTable[ucNameIdx], + prGlueInfo->prDev); + + if (ret) { + DBGLOG(INIT, TRACE, + "Request FW image: %s failed, errno[%d]\n", + apucNameTable[ucNameIdx], fgResult); + continue; + } else { + DBGLOG(INIT, INFO, "Request FW image: %s done\n", + apucNameTable[ucNameIdx]); + fgResult = TRUE; + break; + } + } + + + /* Check result */ + if (!fgResult) + goto error_open; + + + return WLAN_STATUS_SUCCESS; + +error_open: + DBGLOG(INIT, ERROR, + "Request FW image failed! Cur ECO Ver[E%u]\n", + ucCurEcoVer); + + 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. + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t kalFirmwareClose(IN struct GLUE_INFO *prGlueInfo) +{ + release_firmware(fw_entry); + + 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. + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t kalFirmwareLoad(IN struct GLUE_INFO *prGlueInfo, + OUT void *prBuf, IN uint32_t u4Offset, + OUT uint32_t *pu4Size) +{ + ASSERT(prGlueInfo); + ASSERT(pu4Size); + ASSERT(prBuf); + + if ((fw_entry == NULL) || (fw_entry->size == 0) + || (fw_entry->data == NULL)) { + goto error_read; + } else { + memcpy(prBuf, fw_entry->data, fw_entry->size); + *pu4Size = fw_entry->size; + } + + 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. + * + */ +/*----------------------------------------------------------------------------*/ + +uint32_t kalFirmwareSize(IN struct GLUE_INFO *prGlueInfo, + OUT uint32_t *pu4Size) +{ + ASSERT(prGlueInfo); + ASSERT(pu4Size); + + *pu4Size = fw_entry->size; + + return WLAN_STATUS_SUCCESS; +} + +void +kalConstructDefaultFirmwarePrio(struct GLUE_INFO + *prGlueInfo, uint8_t **apucNameTable, + uint8_t **apucName, uint8_t *pucNameIdx, + uint8_t ucMaxNameIdx) +{ + struct mt66xx_chip_info *prChipInfo = + prGlueInfo->prAdapter->chip_info; + uint32_t chip_id = prChipInfo->chip_id; + uint8_t sub_idx = 0; + int ret = 0; + + for (sub_idx = 0; apucNameTable[sub_idx]; sub_idx++) { + if ((*pucNameIdx + 3) >= ucMaxNameIdx) { + /* the table is not large enough */ + DBGLOG(INIT, ERROR, + "kalFirmwareImageMapping >> file name array is not enough.\n"); + ASSERT(0); + continue; + } + + /* Type 1. WIFI_RAM_CODE_MTxxxx */ + ret = kalSnprintf(*(apucName + (*pucNameIdx)), FILE_NAME_MAX, + "%s%x", apucNameTable[sub_idx], chip_id); + if (ret >= 0 && ret < CFG_FW_NAME_MAX_LEN) + (*pucNameIdx) += 1; + else + DBGLOG(INIT, ERROR, + "[%u] kalSnprintf failed, ret: %d\n", + __LINE__, ret); + + /* Type 2. WIFI_RAM_CODE_MTxxxx.bin */ + ret = kalSnprintf(*(apucName + (*pucNameIdx)), FILE_NAME_MAX, + "%s%x.bin", + apucNameTable[sub_idx], chip_id); + if (ret >= 0 && ret < CFG_FW_NAME_MAX_LEN) + (*pucNameIdx) += 1; + else + DBGLOG(INIT, ERROR, + "[%u] kalSnprintf failed, ret: %d\n", + __LINE__, ret); + + /* Type 3. WIFI_RAM_CODE_MTxxxx_Ex */ + ret = kalSnprintf(*(apucName + (*pucNameIdx)), FILE_NAME_MAX, + "%s%x_E%u", + apucNameTable[sub_idx], chip_id, + wlanGetEcoVersion(prGlueInfo->prAdapter)); + if (ret >= 0 && ret < CFG_FW_NAME_MAX_LEN) + (*pucNameIdx) += 1; + else + DBGLOG(INIT, ERROR, + "[%u] kalSnprintf failed, ret: %d\n", + __LINE__, ret); + + /* Type 4. WIFI_RAM_CODE_MTxxxx_Ex.bin */ + ret = kalSnprintf(*(apucName + (*pucNameIdx)), FILE_NAME_MAX, + "%s%x_E%u.bin", + apucNameTable[sub_idx], chip_id, + wlanGetEcoVersion(prGlueInfo->prAdapter)); + if (ret >= 0 && ret < CFG_FW_NAME_MAX_LEN) + (*pucNameIdx) += 1; + else + DBGLOG(INIT, ERROR, + "[%u] kalSnprintf failed, ret: %d\n", + __LINE__, ret); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ + +void * +kalFirmwareImageMapping(IN struct GLUE_INFO *prGlueInfo, + OUT void **ppvMapFileBuf, OUT uint32_t *pu4FileLength, + IN enum ENUM_IMG_DL_IDX_T eDlIdx) +{ + uint8_t **apucNameTable = NULL; + uint8_t *apucName[FILE_NAME_TOTAL + + 1]; /* extra +1, for the purpose of + * detecting the end of the array + */ + uint8_t idx = 0, max_idx, + aucNameBody[FILE_NAME_TOTAL][FILE_NAME_MAX], sub_idx = 0; + struct mt66xx_chip_info *prChipInfo = + prGlueInfo->prAdapter->chip_info; + uint32_t chip_id = prChipInfo->chip_id; + + DEBUGFUNC("kalFirmwareImageMapping"); + + ASSERT(prGlueInfo); + ASSERT(ppvMapFileBuf); + ASSERT(pu4FileLength); + + *ppvMapFileBuf = NULL; + *pu4FileLength = 0; + + do { + /* <0.0> Get FW name prefix table */ + switch (eDlIdx) { + case IMG_DL_IDX_N9_FW: + apucNameTable = apucFwName; + break; + + case IMG_DL_IDX_CR4_FW: + apucNameTable = apucCr4FwName; + break; + + case IMG_DL_IDX_PATCH: + break; + + default: + ASSERT(0); + break; + } + + /* <0.2> Construct FW name */ + memset(apucName, 0, sizeof(apucName)); + + /* magic number 1: reservation for detection + * of the end of the array + */ + max_idx = (sizeof(apucName) / sizeof(uint8_t *)) - 1; + + idx = 0; + apucName[idx] = (uint8_t *)(aucNameBody + idx); + + if (eDlIdx == IMG_DL_IDX_PATCH) { + /* construct the file name for patch */ + + /* mtxxxx_patch_ex_hdr.bin*/ + if (prChipInfo->fw_dl_ops->constructPatchName) + prChipInfo->fw_dl_ops->constructPatchName( + prGlueInfo, apucName, &idx); + else + kalSnprintf(apucName[idx], FILE_NAME_MAX, + "mt%x_patch_e%x_hdr.bin", chip_id, + wlanGetEcoVersion( + prGlueInfo->prAdapter)); + idx += 1; + } else { + for (sub_idx = 0; sub_idx < max_idx; sub_idx++) + apucName[sub_idx] = + (uint8_t *)(aucNameBody + sub_idx); + + if (prChipInfo->fw_dl_ops->constructFirmwarePrio) + prChipInfo->fw_dl_ops->constructFirmwarePrio( + prGlueInfo, apucNameTable, apucName, + &idx, max_idx); + else + kalConstructDefaultFirmwarePrio( + prGlueInfo, apucNameTable, apucName, + &idx, max_idx); + } + + /* let the last pointer point to NULL + * so that we can detect the end of the array in + * kalFirmwareOpen(). + */ + apucName[idx] = NULL; + + apucNameTable = apucName; + + /* <1> Open firmware */ + if (kalFirmwareOpen(prGlueInfo, + apucNameTable) != WLAN_STATUS_SUCCESS) + break; + { + uint32_t u4FwSize = 0; + void *prFwBuffer = NULL; + /* <2> Query firmare size */ + kalFirmwareSize(prGlueInfo, &u4FwSize); + /* <3> Use vmalloc for allocating large memory trunk */ + prFwBuffer = vmalloc(ALIGN_4(u4FwSize)); + if (!prFwBuffer) { + DBGLOG(INIT, ERROR, "vmalloc(%u) failed\n", + ALIGN_4(u4FwSize)); + kalFirmwareClose(prGlueInfo); + break; + } + /* <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 struct GLUE_INFO + *prGlueInfo, IN void *prFwHandle, IN void *pvMapFileBuf) +{ + DEBUGFUNC("kalFirmwareImageUnmapping"); + + ASSERT(prGlueInfo); + + /* pvMapFileBuf might be NULL when file doesn't exist */ + if (pvMapFileBuf) + vfree(pvMapFileBuf); + + kalFirmwareClose(prGlueInfo); +} +#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 struct GLUE_INFO *prGlueInfo, + IN enum ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, + OUT unsigned long *plFlags) +{ + unsigned long ulFlags = 0; + + ASSERT(prGlueInfo); + ASSERT(plFlags); + + if (rLockCategory < SPIN_LOCK_NUM) { + /*DBGLOG(INIT, LOUD, "SPIN_LOCK[%u] Acq\n", rLockCategory);*/ +#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], + ulFlags); +#endif /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + + *plFlags = ulFlags; + + /*DBGLOG(INIT, LOUD, "SPIN_LOCK[%u] Acqed\n", rLockCategory);*/ + } + +} /* end of kalAcquireSpinLock() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is provided by GLUE Layer for internal driver stack to + * release OS SPIN_LOCK. + * + * \param[in] prGlueInfo Pointer of GLUE Data Structure + * \param[in] rLockCategory Specify which SPIN_LOCK + * \param[in] u4Flags Saved IRQ flags + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void kalReleaseSpinLock(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, + IN unsigned long ulFlags) +{ + 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], ulFlags); +#endif /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + /* DBGLOG(INIT, LOUD, "SPIN_UNLOCK[%u]\n", rLockCategory); */ + } + +} /* end of kalReleaseSpinLock() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is provided by GLUE Layer for internal driver stack to + * acquire OS MUTEX. + * + * \param[in] prGlueInfo Pointer of GLUE Data Structure + * \param[in] rMutexCategory Specify which MUTEX + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void kalAcquireMutex(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_MUTEX_CATEGORY_E rMutexCategory) +{ + ASSERT(prGlueInfo); + + if (rMutexCategory < MUTEX_NUM) { + DBGLOG(INIT, TEMP, + "MUTEX_LOCK[%u] Try to acquire\n", rMutexCategory); + mutex_lock(&prGlueInfo->arMutex[rMutexCategory]); + DBGLOG(INIT, TEMP, "MUTEX_LOCK[%u] Acquired\n", rMutexCategory); + } + +} /* end of kalAcquireMutex() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is provided by GLUE Layer for internal driver stack to + * release OS MUTEX. + * + * \param[in] prGlueInfo Pointer of GLUE Data Structure + * \param[in] rMutexCategory Specify which MUTEX + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void kalReleaseMutex(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_MUTEX_CATEGORY_E rMutexCategory) +{ + ASSERT(prGlueInfo); + + if (rMutexCategory < MUTEX_NUM) { + mutex_unlock(&prGlueInfo->arMutex[rMutexCategory]); + DBGLOG(INIT, TEMP, "MUTEX_UNLOCK[%u]\n", rMutexCategory); + } + +} /* end of kalReleaseMutex() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucMacAddr) +{ + ASSERT(prGlueInfo); + ASSERT(pucMacAddr); + + DBGLOG(INIT, INFO, + MACSTR ", " MACSTR ".\n", + prGlueInfo->prDevHandler->dev_addr, + MAC2STR(pucMacAddr)); + + if (UNEQUAL_MAC_ADDR(prGlueInfo->prDevHandler->dev_addr, + pucMacAddr)) + memcpy(prGlueInfo->prDevHandler->dev_addr, pucMacAddr, + PARAM_MAC_ADDR_LEN); +} + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +/*----------------------------------------------------------------------------*/ +/*! + * \brief To query the packet information for offload related parameters. + * + * \param[in] pvPacket Pointer to the packet descriptor. + * \param[in] pucFlag Points to the offload related parameter. + * + * \return (none) + * + */ +/*----------------------------------------------------------------------------*/ +void kalQueryTxChksumOffloadParam(IN void *pvPacket, + OUT uint8_t *pucFlag) +{ + struct sk_buff *skb = (struct sk_buff *)pvPacket; + uint8_t ucFlag = 0; + + ASSERT(pvPacket); + ASSERT(pucFlag); + + if (skb->ip_summed == CHECKSUM_PARTIAL) { +#if DBG + /* Kevin: do double check, we can remove this part in Normal + * Driver. + * Because we register NIC feature with NETIF_F_IP_CSUM for + * MT5912B MAC, so we'll process IP packet only. + */ + if (skb->protocol != htons(ETH_P_IP)) { + /* printk("Wrong skb->protocol( = %08x) for TX Checksum + * Offload.\n", skb->protocol); + */ + } else +#endif + ucFlag |= (TX_CS_IP_GEN | TX_CS_TCP_UDP_GEN); + } + + *pucFlag = ucFlag; + +} /* kalQueryChksumOffloadParam */ + +/* 4 2007/10/8, mikewu, this is rewritten by Mike */ +/*----------------------------------------------------------------------------*/ +/*! + * \brief To update the checksum offload status to the packet to be indicated to + * OS. + * + * \param[in] pvPacket Pointer to the packet descriptor. + * \param[in] pucFlag Points to the offload related parameter. + * + * \return (none) + * + */ +/*----------------------------------------------------------------------------*/ +void kalUpdateRxCSUMOffloadParam(IN void *pvPacket, + IN enum ENUM_CSUM_RESULT 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"); + +#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 struct GLUE_INFO *prGlueInfo, + IN void *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 + */ +/*----------------------------------------------------------------------------*/ +void *kalPacketAlloc(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Size, OUT uint8_t **ppucData) +{ + struct mt66xx_chip_info *prChipInfo; + struct sk_buff *prSkb; + uint32_t u4TxHeadRoomSize; + + prChipInfo = prGlueInfo->prAdapter->chip_info; + u4TxHeadRoomSize = NIC_TX_DESC_AND_PADDING_LENGTH + + prChipInfo->txd_append_size; + + if (in_interrupt()) + prSkb = __dev_alloc_skb(u4Size + u4TxHeadRoomSize, + GFP_ATOMIC | __GFP_NOWARN); + else + prSkb = __dev_alloc_skb(u4Size + u4TxHeadRoomSize, + GFP_KERNEL); + + if (prSkb) { + skb_reserve(prSkb, u4TxHeadRoomSize); + + *ppucData = (uint8_t *) (prSkb->data); + + kalResetPacket(prGlueInfo, (void *) prSkb); + } +#if DBG + { + uint32_t *pu4Head = (uint32_t *) &prSkb->cb[0]; + *pu4Head = (uint32_t) prSkb->head; + DBGLOG(RX, TRACE, "prSkb->head = %#lx, prSkb->cb = %#lx\n", + (uint32_t) prSkb->head, *pu4Head); + } +#endif + return (void *) prSkb; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +void *kalPacketAllocWithHeadroom(IN struct GLUE_INFO + *prGlueInfo, IN uint32_t u4Size, OUT uint8_t **ppucData) +{ + struct sk_buff *prSkb = dev_alloc_skb(u4Size); + + if (!prSkb) { + DBGLOG(TX, WARN, "alloc skb failed\n"); + return NULL; + } + + /* + * Reserve NIC_TX_HEAD_ROOM as this skb + * is allocated by driver instead of kernel. + */ + skb_reserve(prSkb, NIC_TX_HEAD_ROOM); + + *ppucData = (uint8_t *) (prSkb->data); + + kalResetPacket(prGlueInfo, (void *) prSkb); +#if DBG + { + uint32_t *pu4Head = (uint32_t *) &prSkb->cb[0]; + *pu4Head = (uint32_t) prSkb->head; + DBGLOG(RX, TRACE, "prSkb->head = %#lx, prSkb->cb = %#lx\n", + (uint32_t) prSkb->head, *pu4Head); + } +#endif + return (void *) 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. + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t +kalProcessRxPacket(IN struct GLUE_INFO *prGlueInfo, + IN void *pvPacket, IN uint8_t *pucPacketStart, + IN uint32_t u4PacketLen, + /* IN PBOOLEAN pfgIsRetain, */ + IN u_int8_t fgIsRetain, IN enum ENUM_CSUM_RESULT aerCSUM[]) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct sk_buff *skb = (struct sk_buff *)pvPacket; + + skb->data = (unsigned char *)pucPacketStart; + + /* Reset skb */ + skb_reset_tail_pointer(skb); + skb_trim(skb, 0); + + if (skb_tailroom(skb) < 0 || u4PacketLen > skb_tailroom(skb)) { + DBGLOG(RX, ERROR, +#ifdef NET_SKBUFF_DATA_USES_OFFSET + "[skb:0x%p][skb->len:%d][skb->protocol:0x%02X] tail:%u, end:%u, data:%p\n", +#else + "[skb:0x%p][skb->len:%d][skb->protocol:0x%02X] tail:%p, end:%p, data:%p\n", +#endif + (uint8_t *) skb, + skb->len, + skb->protocol, + skb->tail, + skb->end, + skb->data); + DBGLOG_MEM32(RX, ERROR, (uint32_t *) skb->data, skb->len); + return WLAN_STATUS_FAILURE; + } + + /* Put data */ + skb_put(skb, u4PacketLen); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + if (prGlueInfo->prAdapter->fgIsSupportCsumOffload) + 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. + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t kalRxIndicatePkts(IN struct GLUE_INFO *prGlueInfo, + IN void *apvPkts[], IN uint8_t ucPktNum) +{ + uint8_t ucIdx = 0; + + ASSERT(prGlueInfo); + ASSERT(apvPkts); + + for (ucIdx = 0; ucIdx < ucPktNum; ucIdx++) + kalRxIndicateOnePkt(prGlueInfo, apvPkts[ucIdx]); + + KAL_WAKE_LOCK_TIMEOUT(prGlueInfo->prAdapter, + prGlueInfo->rTimeoutWakeLock, MSEC_TO_JIFFIES( + prGlueInfo->prAdapter->rWifiVar.u4WakeLockRxTimeout)); + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_SUPPORT_RX_GRO +/*----------------------------------------------------------------------------*/ +/*! + * \brief To indicate Tput is higher than ucGROEnableTput or not. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * + * \retval TRUE Success. + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t kal_is_skb_gro(struct ADAPTER *prAdapter, uint8_t ucBssIdx) +{ + struct PERF_MONITOR *prPerMonitor; + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; + + prPerMonitor = &prAdapter->rPerMonitor; + if (prPerMonitor->ulRxTp[ucBssIdx] > prWifiVar->ucGROEnableTput) + return 1; + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief flush Rx packet to kernel if kernel buffer is full or timeout(1ms) + * + * @param[in] prAdapter Pointer to the Adapter structure. + * + * @retval VOID + * + */ +/*----------------------------------------------------------------------------*/ +void kal_gro_flush(struct ADAPTER *prAdapter, struct net_device *prDev) +{ + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = + (struct NETDEV_PRIVATE_GLUE_INFO *) netdev_priv(prDev); + + if (CHECK_FOR_TIMEOUT(kalGetTimeTick(), + prNetDevPrivate->tmGROFlushTimeout, + prWifiVar->ucGROFlushTimeout)) { + napi_gro_flush(&prNetDevPrivate->napi, false); + DBGLOG_LIMITED(INIT, TRACE, "napi_gro_flush:%p\n", prDev); + } + GET_CURRENT_SYSTIME(&prNetDevPrivate->tmGROFlushTimeout); +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * \brief To indicate one received packets is available for higher + * level protocol uses. + * + * \param[in] prGlueInfo Pointer to the Adapter structure. + * \param[in] pvPkt The packet to be indicated + * + * \retval TRUE Success. + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t kalRxIndicateOnePkt(IN struct GLUE_INFO + *prGlueInfo, IN void *pvPkt) +{ + struct net_device *prNetDev = prGlueInfo->prDevHandler; + struct sk_buff *prSkb = NULL; + struct mt66xx_chip_info *prChipInfo; + uint8_t ucBssIdx; +#if CFG_SUPPORT_RX_GRO + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = NULL; +#endif + + ASSERT(prGlueInfo); + ASSERT(pvPkt); + + prSkb = pvPkt; + prChipInfo = prGlueInfo->prAdapter->chip_info; + ucBssIdx = GLUE_GET_PKT_BSS_IDX(prSkb); +#if DBG && 0 + do { + uint8_t *pu4Head = (uint8_t *) &prSkb->cb[0]; + uint32_t 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 1 + + if (ucBssIdx < MAX_BSSID_NUM) { + prNetDev = (struct net_device *)wlanGetNetInterfaceByBssIdx( + prGlueInfo, ucBssIdx); + } else { + DBGLOG(RX, WARN, "Error ucBssIdx =%x\n", ucBssIdx); + DBGLOG(RX, WARN, "Error pkt info =%x:%x:%x:%x:%x:%x:%x:%x\n", + GLUE_GET_PKT_TID(prSkb), + GLUE_IS_PKT_FLAG_SET(prSkb), + GLUE_GET_PKT_HEADER_LEN(prSkb), + GLUE_GET_PKT_FRAME_LEN(prSkb), + GLUE_GET_PKT_ARRIVAL_TIME(prSkb), + GLUE_GET_PKT_IP_ID(prSkb), + GLUE_GET_PKT_SEQ_NO(prSkb), + GLUE_GET_PKT_IS_PROF_MET(prSkb)); + } + if (!prNetDev) + prNetDev = prGlueInfo->prDevHandler; +#if CFG_SUPPORT_SNIFFER + if (prGlueInfo->fgIsEnableMon) + prNetDev = prGlueInfo->prMonDevHandler; +#endif + if (prNetDev->dev_addr == NULL) { + DBGLOG(RX, WARN, "dev_addr == NULL\n"); + return WLAN_STATUS_FAILURE; + } + + prNetDev->stats.rx_bytes += prSkb->len; + prNetDev->stats.rx_packets++; +#if CFG_SUPPORT_PERF_IND + if (GLUE_GET_PKT_BSS_IDX(prSkb) < BSS_DEFAULT_NUM) { + /* update Performance Indicator statistics*/ + prGlueInfo->PerfIndCache.u4CurRxBytes + [GLUE_GET_PKT_BSS_IDX(prSkb)] += prSkb->len; + } +#endif + +#else + 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[0]->rNetDevStats.rx_bytes += + prSkb->len; + prGlueInfo->prP2PInfo[0]->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++; + + } +#endif + +#if (CFG_SUPPORT_STATISTICS == 1) + StatsEnvRxTime2Host(prGlueInfo->prAdapter, prSkb); +#endif + +#if KERNEL_VERSION(4, 11, 0) <= CFG80211_VERSION_CODE + /* ToDo jiffies assignment */ +#else + prNetDev->last_rx = jiffies; +#endif + +#if CFG_SUPPORT_SNIFFER + if (prGlueInfo->fgIsEnableMon) { + skb_reset_mac_header(prSkb); + prSkb->ip_summed = CHECKSUM_UNNECESSARY; + prSkb->pkt_type = PACKET_OTHERHOST; + prSkb->protocol = htons(ETH_P_802_2); + } else { + prSkb->protocol = eth_type_trans(prSkb, prNetDev); + } +#else + prSkb->protocol = eth_type_trans(prSkb, prNetDev); +#endif + prSkb->dev = prNetDev; + /* DBGLOG_MEM32(RX, TRACE, (PUINT_32)prSkb->data, prSkb->len); */ + /* DBGLOG(RX, EVENT, ("kalRxIndicatePkts len = %d\n", prSkb->len)); */ + if (prSkb->tail > prSkb->end) { + DBGLOG(RX, ERROR, +#ifdef NET_SKBUFF_DATA_USES_OFFSET + "kalRxIndicateOnePkt [prSkb = 0x%p][prSkb->len = %d][prSkb->protocol = 0x%02x] %u,%u\n", +#else + "kalRxIndicateOnePkt [prSkb = 0x%p][prSkb->len = %d][prSkb->protocol = 0x%02x] %p,%p\n", +#endif + prSkb, prSkb->len, prSkb->protocol, prSkb->tail, + prSkb->end); + DBGLOG_MEM32(RX, ERROR, (uint32_t *) prSkb->data, + prSkb->len); + } + + if (prSkb->protocol == NTOHS(ETH_P_8021Q) + && !FEAT_SUP_LLC_VLAN_RX(prChipInfo)) { + /* + * DA-MAC + SA-MAC + 0x8100 was removed in eth_type_trans() + * pkt format here is + * TCI(2-bytes) + Len(2-btyes) + payload-type(2-bytes) + payload + * Remove "Len" field inserted by RX VLAN header translation + * Note: TCI+payload-type is a standard 8021Q header + * + * This format update is based on RX VLAN HW header translation. + * If the setting was changed, you may need to change rules here + * as well. + */ + const uint8_t vlan_skb_mem_move = 2; + + /* Remove "Len" and shift data pointer 2 bytes */ + kalMemCopy(prSkb->data + vlan_skb_mem_move, prSkb->data, + vlan_skb_mem_move); + skb_pull_rcsum(prSkb, vlan_skb_mem_move); + + /* Have to update MAC header properly. Otherwise, wrong MACs + * woud be passed up + */ + kalMemMove(prSkb->data - ETH_HLEN, + prSkb->data - ETH_HLEN - vlan_skb_mem_move, + ETH_HLEN); + prSkb->mac_header += vlan_skb_mem_move; + + skb_reset_network_header(prSkb); + skb_reset_transport_header(prSkb); + kal_skb_reset_mac_len(prSkb); + } + + kalTraceEvent("Rx id=0x%04x sn=%d", + GLUE_GET_PKT_IP_ID(prSkb), + GLUE_GET_PKT_SEQ_NO(prSkb)); + +#if CFG_SUPPORT_RX_GRO + if (ucBssIdx < MAX_BSSID_NUM && + kal_is_skb_gro(prGlueInfo->prAdapter, ucBssIdx)) { + /* GRO receive function can't be interrupt so it need to + * disable preempt and protect by spin lock + */ + preempt_disable(); + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prNetDev); + spin_lock_bh(&prNetDevPrivate->napi_spinlock); + napi_gro_receive(&prNetDevPrivate->napi, prSkb); + kal_gro_flush(prGlueInfo->prAdapter, prNetDev); + spin_unlock_bh(&prNetDevPrivate->napi_spinlock); + preempt_enable(); + DBGLOG_LIMITED(INIT, INFO, "napi_gro_receive:%p\n", prNetDev); + return WLAN_STATUS_SUCCESS; + } +#endif + if (!in_interrupt()) + netif_rx_ni(prSkb); + else + netif_rx(prSkb); + + 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 struct GLUE_INFO + *prGlueInfo, IN uint32_t eStatus, IN void *pvBuf, + IN uint32_t u4BufLen, IN uint8_t ucBssIndex) +{ + + uint32_t bufLen; + struct PARAM_STATUS_INDICATION *pStatus; + struct PARAM_AUTH_EVENT *pAuth; + struct PARAM_PMKID_CANDIDATE_LIST *pPmkid; + uint8_t arBssid[PARAM_MAC_ADDR_LEN]; + struct PARAM_SSID ssid = {0}; + struct ieee80211_channel *prChannel = NULL; + struct cfg80211_bss *bss = NULL; + uint8_t ucChannelNum; + struct BSS_DESC *prBssDesc = NULL; + struct ADAPTER *prAdapter = NULL; + uint8_t fgScanAborted = FALSE; + struct net_device *prDevHandler; + struct CONNECTION_SETTINGS *prConnSettings = NULL; + struct FT_IES *prFtIEs; + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE + struct cfg80211_roam_info rRoamInfo = { 0 }; +#endif + + GLUE_SPIN_LOCK_DECLARATION(); + + kalMemZero(arBssid, MAC_ADDR_LEN); + + ASSERT(prGlueInfo); + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + pStatus = (struct PARAM_STATUS_INDICATION *)pvBuf; + pAuth = (struct PARAM_AUTH_EVENT *)pStatus; + pPmkid = (struct PARAM_PMKID_CANDIDATE_LIST *)(pStatus + 1); + + prDevHandler = wlanGetNetDev(prGlueInfo, ucBssIndex); + + switch (eStatus) { + case WLAN_STATUS_ROAM_OUT_FIND_BEST: + case WLAN_STATUS_MEDIA_CONNECT: +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + /* clear the count */ + prGlueInfo->prAdapter->rLinkQualityInfo.u8TxTotalCount = 0; + prGlueInfo->prAdapter->rLinkQualityInfo.u8RxTotalCount = 0; + prGlueInfo->prAdapter->rLinkQualityInfo.u8RxErrCount = 0; +#endif /* CFG_SUPPORT_LINK_QUALITY_MONITOR */ + kalSetMediaStateIndicated(prGlueInfo, + MEDIA_STATE_CONNECTED, + ucBssIndex); + + /* indicate assoc event */ + SET_IOCTL_BSSIDX(prGlueInfo->prAdapter, ucBssIndex); + wlanQueryInformation(prGlueInfo->prAdapter, wlanoidQueryBssid, + &arBssid[0], sizeof(arBssid), &bufLen); + wext_indicate_wext_event(prGlueInfo, SIOCGIWAP, arBssid, + bufLen, ucBssIndex); + + /* switch netif on */ + netif_carrier_on(prDevHandler); + + do { + + uint8_t aucSsid[PARAM_MAX_LEN_SSID + 1] = {0}; + + /* print message on console */ + SET_IOCTL_BSSIDX(prGlueInfo->prAdapter, ucBssIndex); + wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQuerySsid, &ssid, sizeof(ssid), &bufLen); + + kalStrnCpy(aucSsid, ssid.aucSsid, sizeof(aucSsid) - 1); + aucSsid[sizeof(aucSsid) - 1] = '\0'; + + DBGLOG(INIT, INFO, + "[wifi] %s netif_carrier_on [ssid:%s " MACSTR + "], Mac:" MACSTR "\n", + prGlueInfo->prDevHandler->name, aucSsid, + MAC2STR(arBssid), + MAC2STR( + prGlueInfo->prAdapter->rWifiVar.aucMacAddress)); + + } while (0); + + if (prGlueInfo->fgIsRegistered == TRUE) { + struct cfg80211_bss *bss_others = NULL; + uint8_t ucLoopCnt = + 15; /* only loop 15 times to avoid dead loop */ + + /* retrieve channel */ + ucChannelNum = + wlanGetChannelNumberByNetwork( + prGlueInfo->prAdapter, + ucBssIndex); + if (ucChannelNum <= 14) { + prChannel = + ieee80211_get_channel( + priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency + (ucChannelNum, KAL_BAND_2GHZ)); + } else { + prChannel = + ieee80211_get_channel( + priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency + (ucChannelNum, KAL_BAND_5GHZ)); + } + + if (!prChannel) + DBGLOG(SCN, ERROR, + "prChannel is NULL and ucChannelNum is %d\n", + ucChannelNum); + + /* ensure BSS exists */ +#if KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE + bss = cfg80211_get_bss( + priv_to_wiphy(prGlueInfo), prChannel, arBssid, + ssid.aucSsid, ssid.u4SsidLen, + IEEE80211_BSS_TYPE_ESS, + IEEE80211_PRIVACY_ANY); +#else + bss = cfg80211_get_bss( + priv_to_wiphy(prGlueInfo), prChannel, arBssid, + ssid.aucSsid, ssid.u4SsidLen, + WLAN_CAPABILITY_ESS, + WLAN_CAPABILITY_ESS); +#endif + if (bss == NULL) { + /* create BSS on-the-fly */ + prBssDesc = + aisGetTargetBssDesc(prAdapter, + ucBssIndex); + + if (prBssDesc != NULL && prChannel != NULL) { +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE + bss = cfg80211_inform_bss( + priv_to_wiphy(prGlueInfo), + prChannel, + CFG80211_BSS_FTYPE_PRESP, + arBssid, + 0, /* TSF */ + prBssDesc->u2CapInfo, + prBssDesc->u2BeaconInterval, /* beacon interval */ + prBssDesc->aucIEBuf, /* IE */ + prBssDesc->u2IELength, /* IE Length */ + RCPI_TO_dBm(prBssDesc->ucRCPI) * 100, /* MBM */ + GFP_KERNEL); +#else + bss = cfg80211_inform_bss( + priv_to_wiphy(prGlueInfo), + prChannel, + arBssid, + 0, /* TSF */ + prBssDesc->u2CapInfo, + prBssDesc->u2BeaconInterval, /* beacon interval */ + prBssDesc->aucIEBuf, /* IE */ + prBssDesc->u2IELength, /* IE Length */ + RCPI_TO_dBm(prBssDesc->ucRCPI) * 100, /* MBM */ + GFP_KERNEL); +#endif + } + } + +#if (CFG_SUPPORT_STATISTICS == 1) + StatsResetTxRx(); +#endif + /* remove all bsses that before and only channel + * different with the current connected one + * if without this patch, UI will show channel A is + * connected even if AP has change channel from A to B + */ + while (ucLoopCnt--) { +#if KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE + bss_others = cfg80211_get_bss( + priv_to_wiphy(prGlueInfo), + NULL, arBssid, ssid.aucSsid, + ssid.u4SsidLen, + IEEE80211_BSS_TYPE_ESS, + IEEE80211_PRIVACY_ANY); +#else + bss_others = cfg80211_get_bss( + priv_to_wiphy(prGlueInfo), + NULL, arBssid, ssid.aucSsid, + ssid.u4SsidLen, + WLAN_CAPABILITY_ESS, + WLAN_CAPABILITY_ESS); +#endif + if (bss && bss_others && bss_others != bss) { + DBGLOG(SCN, INFO, + "remove BSSes that only channel different\n"); + cfg80211_unlink_bss( + priv_to_wiphy(prGlueInfo), + bss_others); + cfg80211_put_bss( + priv_to_wiphy(prGlueInfo), + bss_others); + } else + break; + } + + /* CFG80211 Indication */ + prConnSettings = + aisGetConnSettings(prAdapter, ucBssIndex); + if (eStatus == WLAN_STATUS_ROAM_OUT_FIND_BEST) { +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE + rRoamInfo.bss = bss; + rRoamInfo.req_ie = prConnSettings->aucReqIe; + rRoamInfo.req_ie_len = + prConnSettings->u4ReqIeLength; + rRoamInfo.resp_ie = prConnSettings->aucRspIe; + rRoamInfo.resp_ie_len = + prConnSettings->u4RspIeLength; + + cfg80211_roamed(prDevHandler, + &rRoamInfo, GFP_KERNEL); +#else + cfg80211_roamed_bss( + prDevHandler, + bss, + prConnSettings->aucReqIe, + prConnSettings->u4ReqIeLength, + prConnSettings->aucRspIe, + prConnSettings->u4RspIeLength, + GFP_KERNEL); +#endif + } else { + cfg80211_connect_result( + prDevHandler, + arBssid, + prConnSettings->aucReqIe, + prConnSettings->u4ReqIeLength, + prConnSettings->aucRspIe, + prConnSettings->u4RspIeLength, + WLAN_STATUS_SUCCESS, + GFP_KERNEL); + } + + /* Check SAP channel */ + p2pFuncSwitchSapChannel(prGlueInfo->prAdapter); + + } + + break; + + case WLAN_STATUS_MEDIA_DISCONNECT: + case WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY: +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + /* clear the count */ + prGlueInfo->prAdapter->rLinkQualityInfo.u8TxTotalCount = 0; + prGlueInfo->prAdapter->rLinkQualityInfo.u8RxTotalCount = 0; + prGlueInfo->prAdapter->rLinkQualityInfo.u8RxErrCount = 0; +#endif + /* indicate disassoc event */ + wext_indicate_wext_event(prGlueInfo, SIOCGIWAP, NULL, 0 + , ucBssIndex); + /* 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", + prDevHandler->name); +#endif + + netif_carrier_off(prDevHandler); + + /* Full2Partial: reset */ + if (prGlueInfo->prAdapter) { + struct SCAN_INFO *prScanInfo = + &(prGlueInfo->prAdapter->rWifiVar.rScanInfo); + prScanInfo->fgIsScanForFull2Partial = FALSE; + prScanInfo->u4LastFullScanTime = 0; + } + + if (prGlueInfo->fgIsRegistered == TRUE) { + struct BSS_INFO *prBssInfo = + aisGetAisBssInfo(prAdapter, ucBssIndex); + uint16_t u2DeauthReason = 0; +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) + + if (prBssInfo) + u2DeauthReason = prBssInfo->u2DeauthReason; + +#if CFG_SUPPORT_BIGDATA_PIP + { + struct _REPORT_DISCONNECT { + uint16_t u2Id; + uint16_t u2Len; + uint8_t ucReasonType; + uint16_t u2ReasonCode; + int8_t cRssi; + uint16_t u2DataRate; + uint8_t ucChannelNo; + } __KAL_ATTRIB_PACKED__; + + struct _REPORT_DISCONNECT rPayload = {0}; + struct BSS_DESC *prTemp = NULL; + int8_t ret = 0; + + /* u2Id: Define category of report data. + * 0 - Antswp + * 1 - GPS Blank On + * 2 - Disconnect Reason + * others - Reserved + * + * u2Len: length of data. + * Report data format: + * | u2Id | u2Len | data | + */ + rPayload.u2Id = 2; + rPayload.u2Len = 7; + + if (eStatus == + WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY) { + rPayload.ucReasonType = 2; + rPayload.u2ReasonCode = 0; + } else if (u2DeauthReason >= + REASON_CODE_BEACON_TIMEOUT*100) { + rPayload.ucReasonType = 0; + rPayload.u2ReasonCode = + u2DeauthReason - REASON_CODE_BEACON_TIMEOUT*100; + } else { + rPayload.ucReasonType = 1; + rPayload.u2ReasonCode = u2DeauthReason; + } + + if (prGlueInfo->prAdapter) { + rPayload.cRssi = + prGlueInfo->prAdapter->rLinkQuality + .rLq[ucBssIndex].cRssi; + rPayload.u2DataRate = + prGlueInfo->prAdapter->rLinkQuality + .rLq[ucBssIndex].u2LinkSpeed; + + prTemp = + aisGetTargetBssDesc( + prGlueInfo->prAdapter, + ucBssIndex); + + if (prTemp) + rPayload.ucChannelNo = + prTemp->ucChannelNum; + + DBGLOG(INIT, TRACE, + "[D2F]type(%u)-reason(%u)-rssi(%d)-speed(%u)-channel(%u)\n", + rPayload.ucReasonType, + rPayload.u2ReasonCode, + rPayload.cRssi, + rPayload.u2DataRate, + rPayload.ucChannelNo); + + /* dumpMemory8((uint8_t *)&rPayload, + * sizeof(rPayload)); + */ + + ret = kalBigDataPip(prGlueInfo->prAdapter, + (uint8_t *)&rPayload, + sizeof(rPayload)); + + if ((ret != 1) && (ret != -ETIME)) + DBGLOG(INIT, ERROR, + "[D2F]data pip report fail(%d).\n", + ret); + + } + } +#endif + /* CFG80211 Indication */ + DBGLOG(INIT, INFO, + "[wifi]Indicate disconnection: Reason=%d Locally[%d]\n", + u2DeauthReason, + (eStatus == + WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY)); + cfg80211_disconnected(prDevHandler, + u2DeauthReason, NULL, 0, + eStatus == WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY, + GFP_KERNEL); + +#else + +#ifdef CONFIG_ANDROID +#if KERNEL_VERSION(3, 10, 0) == LINUX_VERSION_CODE + /* Don't indicate disconnection to upper layer for + * ANDROID kernel 3.10 + */ + /* since cfg80211 will indicate disconnection to + * wpa_supplicant for this kernel + */ + if (eStatus == WLAN_STATUS_MEDIA_DISCONNECT) +#endif +#endif + { + + + if (prBssInfo) + u2DeauthReason = + prBssInfo->u2DeauthReason; + /* CFG80211 Indication */ + cfg80211_disconnected(prDevHandler, + u2DeauthReason, NULL, 0, + GFP_KERNEL); + } + + +#endif + } + prConnSettings = aisGetConnSettings(prAdapter, ucBssIndex); + if (prConnSettings && prConnSettings->assocIeLen > 0) { + kalMemFree(prConnSettings->pucAssocIEs, VIR_MEM_TYPE, + prConnSettings->assocIeLen); + prConnSettings->assocIeLen = 0; + } + + prFtIEs = aisGetFtIe(prAdapter, ucBssIndex); + if (prFtIEs) { + kalMemFree(prFtIEs->pucIEBuf, + VIR_MEM_TYPE, + prFtIEs->u4IeLength); + kalMemZero(prFtIEs, + sizeof(*prFtIEs)); + } + + kalSetMediaStateIndicated(prGlueInfo, + MEDIA_STATE_DISCONNECTED, + ucBssIndex); + + /* Check SAP channel */ + p2pFuncSwitchSapChannel(prGlueInfo->prAdapter); + + break; + + case WLAN_STATUS_SCAN_COMPLETE: + if (pvBuf && u4BufLen == sizeof(uint8_t)) + fgScanAborted = *(uint8_t *)pvBuf; + + /* indicate scan complete event */ + wext_indicate_wext_event(prGlueInfo, SIOCGIWSCAN, NULL, 0, + ucBssIndex); + + if (fgScanAborted == FALSE) { + kalScanLogCacheFlushBSS(prGlueInfo->prAdapter, + SCAN_LOG_MSG_MAX_LEN); + scanlog_dbg(LOG_SCAN_DONE_D2K, INFO, "Call cfg80211_scan_done (aborted=%u)\n", + fgScanAborted); + } else { + scanlog_dbg(LOG_SCAN_ABORT_DONE_D2K, INFO, "Call cfg80211_scan_done (aborted=%u)\n", + fgScanAborted); + } + + /* 1. reset first for newly incoming request */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if (prGlueInfo->prScanRequest != NULL) { + kalCfg80211ScanDone(prGlueInfo->prScanRequest, + fgScanAborted); + prGlueInfo->prScanRequest = NULL; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + break; + +#if 0 + case WLAN_STATUS_MSDU_OK: + if (netif_running(prDevHandler)) + netif_wake_queue(prDevHandler); + break; +#endif + + case WLAN_STATUS_MEDIA_SPECIFIC_INDICATION: + if (pStatus) { + switch (pStatus->eStatusType) { + case ENUM_STATUS_TYPE_AUTHENTICATION: + { + struct PARAM_INDICATION_EVENT *prEvent = + (struct PARAM_INDICATION_EVENT *) pvBuf; + + /* + * printk(KERN_NOTICE + * "ENUM_STATUS_TYPE_AUTHENTICATION: + * L(%d) [" 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 ((prEvent->rAuthReq.u4Flags == + PARAM_AUTH_REQUEST_PAIRWISE_ERROR) || + (prEvent->rAuthReq.u4Flags == + PARAM_AUTH_REQUEST_GROUP_ERROR)) { + cfg80211_michael_mic_failure( + prDevHandler, NULL, + (prEvent->rAuthReq.u4Flags == + PARAM_AUTH_REQUEST_PAIRWISE_ERROR) + ? NL80211_KEYTYPE_PAIRWISE : + NL80211_KEYTYPE_GROUP, + 0, NULL, GFP_KERNEL); + wext_indicate_wext_event(prGlueInfo, + IWEVMICHAELMICFAILURE, + (unsigned char *) + &prEvent->rAuthReq, + prEvent->rAuthReq.u4Length, + ucBssIndex); + } + break; + } + case ENUM_STATUS_TYPE_CANDIDATE_LIST: + { + struct PARAM_INDICATION_EVENT *prEvent = + (struct PARAM_INDICATION_EVENT *) pvBuf; + + cfg80211_pmksa_candidate_notify( + prDevHandler, + 1000, + prEvent->rCandi.arBSSID, + prEvent->rCandi.u4Flags, + GFP_KERNEL); + + wext_indicate_wext_event( + prGlueInfo, + IWEVPMKIDCAND, + (unsigned char *) &prEvent->rCandi, + sizeof(struct PARAM_PMKID_CANDIDATE), + ucBssIndex); + + break; + } + case ENUM_STATUS_TYPE_FT_AUTH_STATUS: { + struct cfg80211_ft_event_params *prFtEvent = + aisGetFtEventParam(prAdapter, + ucBssIndex); + + cfg80211_ft_event(prDevHandler, + prFtEvent); + } + 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(struct PTA_IPC), ucBssIndex); + } + + break; + +#endif + case WLAN_STATUS_JOIN_FAILURE: { + struct BSS_DESC *prBssDesc = + aisGetTargetBssDesc(prAdapter, ucBssIndex); + struct CONNECTION_SETTINGS *prConnSettings = + aisGetConnSettings(prAdapter, ucBssIndex); + + if (prBssDesc) { + DBGLOG(INIT, INFO, "JOIN Failure: u2JoinStatus=%d", + prBssDesc->u2JoinStatus); + COPY_MAC_ADDR(arBssid, prBssDesc->aucBSSID); + } else { + DBGLOG(INIT, INFO, "JOIN Failure: No TargetBssDesc"); + COPY_MAC_ADDR(arBssid, + prConnSettings->aucBSSID); + } + if (prBssDesc && prBssDesc->u2JoinStatus + && prBssDesc->u2JoinStatus != STATUS_CODE_AUTH_TIMEOUT + && prBssDesc->u2JoinStatus != STATUS_CODE_ASSOC_TIMEOUT) + cfg80211_connect_result(prDevHandler, + arBssid, + prConnSettings->aucReqIe, + prConnSettings->u4ReqIeLength, + prConnSettings->aucRspIe, + prConnSettings->u4RspIeLength, + prBssDesc->u2JoinStatus, + GFP_KERNEL); + else + cfg80211_connect_result(prDevHandler, + arBssid, + prConnSettings->aucReqIe, + prConnSettings->u4ReqIeLength, + prConnSettings->aucRspIe, + prConnSettings->u4RspIeLength, + WLAN_STATUS_AUTH_TIMEOUT, + GFP_KERNEL); + kalSetMediaStateIndicated(prGlueInfo, + MEDIA_STATE_DISCONNECTED, + ucBssIndex); + + /* Check SAP channel */ + p2pFuncSwitchSapChannel(prGlueInfo->prAdapter); + + break; + } + 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 struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucFrameBody, IN uint32_t u4FrameBodyLen, + IN u_int8_t fgReassocRequest, + IN uint8_t ucBssIndex) +{ + uint8_t *cp; + struct CONNECTION_SETTINGS *prConnSettings = NULL; + + ASSERT(prGlueInfo); + + prConnSettings = aisGetConnSettings( + prGlueInfo->prAdapter, + ucBssIndex); + + /* reset */ + prConnSettings->u4ReqIeLength = 0; + + if (fgReassocRequest) { + if (u4FrameBodyLen < 15) { + /* + * printk(KERN_WARNING "frameBodyLen too short:%d\n", + * frameBodyLen); + */ + return; + } + } else { + if (u4FrameBodyLen < 9) { + /* + * printk(KERN_WARNING "frameBodyLen too short:%d\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, ucBssIndex); + + if (u4FrameBodyLen <= CFG_CFG80211_IE_BUF_LEN) { + prConnSettings->u4ReqIeLength = u4FrameBodyLen; + kalMemCopy(prConnSettings->aucReqIe, cp, u4FrameBodyLen); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is called to update the (re)association + * response information to the structure used to reply with + * cfg80211_connect_result + * + * @param prGlueInfo Pointer to adapter descriptor + * @param pucFrameBody Pointer to the frame body of the last (Re)Association + * Response frame from the AP + * @param u4FrameBodyLen The length of the frame body of the last + * (Re)Association Response frame + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void kalUpdateReAssocRspInfo(IN struct GLUE_INFO + *prGlueInfo, IN uint8_t *pucFrameBody, + IN uint32_t u4FrameBodyLen, + IN uint8_t ucBssIndex) +{ + uint32_t u4IEOffset = + 6; /* cap_info, status_code & assoc_id */ + uint32_t u4IELength = u4FrameBodyLen - u4IEOffset; + struct CONNECTION_SETTINGS *prConnSettings = NULL; + + ASSERT(prGlueInfo); + + prConnSettings = aisGetConnSettings( + prGlueInfo->prAdapter, + ucBssIndex); + + /* reset */ + prConnSettings->u4RspIeLength = 0; + + if (u4IELength <= CFG_CFG80211_IE_BUF_LEN) { + prConnSettings->u4RspIeLength = u4IELength; + kalMemCopy(prConnSettings->aucRspIe, pucFrameBody + u4IEOffset, + u4IELength); + } + +} /* kalUpdateReAssocRspInfo */ + +void kalResetPacket(IN struct GLUE_INFO *prGlueInfo, + IN void *prPacket) +{ + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + + /* Reset cb */ + kalMemZero(prSkb->cb, sizeof(prSkb->cb)); +} + +/*----------------------------------------------------------------------------*/ +/* + * \brief This function is to check the pairwise eapol and wapi 1x. + * + * \param[in] prPacket Pointer to struct net_device + * + * \retval WLAN_STATUS + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalIsPairwiseEapolPacket(IN void *prPacket) +{ + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + uint8_t *pucPacket = (uint8_t *)prSkb->data; + uint16_t u2EthType = 0; + uint16_t u2KeyInfo = 0; + + WLAN_GET_FIELD_BE16(&pucPacket[ETHER_HEADER_LEN - ETHER_TYPE_LEN], + &u2EthType); +#if CFG_SUPPORT_WAPI + /* prBssInfo && prBssInfo->eNetworkType == NETWORK_TYPE_AIS && + * wlanQueryWapiMode(prAdapter) + */ + if (u2EthType == ETH_WPI_1X) + return TRUE; +#endif + if (u2EthType != ETH_P_1X) + return FALSE; + u2KeyInfo = pucPacket[5 + ETHER_HEADER_LEN] << 8 | + pucPacket[6 + ETHER_HEADER_LEN]; +#if 1 + /* BIT3 is pairwise key bit, and check SM is 0. it means this is 4-way + * handshake frame + */ + DBGLOG(RSN, INFO, "u2KeyInfo=%d\n", u2KeyInfo); + if ((u2KeyInfo & BIT(3)) && !(u2KeyInfo & BIT(13))) + return TRUE; +#else + /* BIT3 is pairwise key bit, bit 8 is key mic bit. + * only the two bits are set, it means this is 4-way handshake 4/4 or + * 2/4 frame + */ + DBGLOG(RSN, INFO, "u2KeyInfo=%d\n", u2KeyInfo); + if ((u2KeyInfo & (BIT(3) | BIT(8))) == (BIT(3) | BIT(8))) + return TRUE; +#endif + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/* + * \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 + * \param[in] prGlueInfo Pointer of prGlueInfo + * \param[in] ucBssIndex BSS index of this net device + * + * \retval WLAN_STATUS + */ +/*----------------------------------------------------------------------------*/ +uint32_t +kalHardStartXmit(struct sk_buff *prOrgSkb, + IN struct net_device *prDev, struct GLUE_INFO *prGlueInfo, + uint8_t ucBssIndex) +{ + struct QUE_ENTRY *prQueueEntry = NULL; + struct QUE *prTxQueue = NULL; + uint16_t u2QueueIdx = 0; + struct sk_buff *prSkbNew = NULL; + struct sk_buff *prSkb = NULL; + uint32_t u4SkbLen = 0; + struct mt66xx_chip_info *prChipInfo; + uint32_t u4TxHeadRoomSize = 0; + struct ADAPTER *prAdapter = NULL; + + ASSERT(prOrgSkb); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + prChipInfo = prGlueInfo->prAdapter->chip_info; + u4TxHeadRoomSize = NIC_TX_DESC_AND_PADDING_LENGTH + + prChipInfo->txd_append_size; + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(INIT, INFO, "GLUE_FLAG_HALT skip tx\n"); + dev_kfree_skb(prOrgSkb); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + if (prGlueInfo->prAdapter->fgIsEnableLpdvt) { + DBGLOG(INIT, INFO, "LPDVT enable, skip this frame\n"); + dev_kfree_skb(prOrgSkb); + return WLAN_STATUS_NOT_ACCEPTED; + } + +#if CFG_SUPPORT_WIFI_SYSDVT + if (prAdapter->u2TxTest != TX_TEST_UNLIMITIED) { + if (prAdapter->u2TxTestCount < prAdapter->u2TxTest) { + DBGLOG(INIT, STATE, + "DVT TX Test enable, skip this frame\n"); + dev_kfree_skb(prOrgSkb); + return WLAN_STATUS_SUCCESS; + } + prAdapter->u2TxTestCount++; + } +#endif /* CFG_SUPPORT_WIFI_SYSDVT */ + + if (skb_headroom(prOrgSkb) < u4TxHeadRoomSize) { + /* + * Should not happen + * kernel crash may happen as skb shared info + * channged. + * offer an change for lucky anyway + */ + prSkbNew = skb_realloc_headroom(prOrgSkb, u4TxHeadRoomSize); + if (!prSkbNew) { + dev_kfree_skb(prOrgSkb); + DBGLOG(INIT, ERROR, + "prChipInfo = %pM, u4TxHeadRoomSize: %u\n", + prChipInfo, u4TxHeadRoomSize); + return WLAN_STATUS_NOT_ACCEPTED; + } + dev_kfree_skb(prOrgSkb); + prSkb = prSkbNew; + } else + prSkb = prOrgSkb; + + prQueueEntry = (struct QUE_ENTRY *) + GLUE_GET_PKT_QUEUE_ENTRY(prSkb); + prTxQueue = &prGlueInfo->rTxQueue; + + GLUE_SET_PKT_BSS_IDX(prSkb, ucBssIndex); + + /* Parsing frame info */ + if (!wlanProcessTxFrame(prGlueInfo->prAdapter, + (void *) prSkb)) { + /* Cannot extract packet */ + DBGLOG(INIT, INFO, + "Cannot extract content, skip this frame\n"); + dev_kfree_skb(prSkb); + return WLAN_STATUS_INVALID_PACKET; + } + + /* Tx profiling */ + wlanTxProfilingTagPacket(prGlueInfo->prAdapter, + (void *) prSkb, TX_PROF_TAG_OS_TO_DRV); + + /* Handle normal data frame */ + u2QueueIdx = skb_get_queue_mapping(prSkb); + u4SkbLen = prSkb->len; + + if (u2QueueIdx >= CFG_MAX_TXQ_NUM) { + DBGLOG(INIT, INFO, + "Incorrect queue index, skip this frame\n"); + dev_kfree_skb(prSkb); + return WLAN_STATUS_INVALID_PACKET; + } + + if (!HAL_IS_TX_DIRECT(prGlueInfo->prAdapter)) { + GLUE_SPIN_LOCK_DECLARATION(); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_INSERT_TAIL(prTxQueue, prQueueEntry); + kalTraceInt(prTxQueue->u4NumElem, "TxQueue"); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + } + + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingFrameNum); + GLUE_INC_REF_CNT( + prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex] + [u2QueueIdx]); + + if (GLUE_GET_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue + [ucBssIndex][u2QueueIdx]) >= + prGlueInfo->prAdapter->rWifiVar.u4NetifStopTh) { + netif_stop_subqueue(prDev, u2QueueIdx); + + DBGLOG(TX, INFO, + "Stop subqueue for BSS[%u] QIDX[%u] PKT_LEN[%u] TOT_CNT[%d] PER-Q_CNT[%d]\n", + ucBssIndex, u2QueueIdx, u4SkbLen, + GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum), + GLUE_GET_REF_CNT( + prGlueInfo->ai4TxPendingFrameNumPerQueue + [ucBssIndex][u2QueueIdx])); + } + + /* Update NetDev statisitcs */ + prDev->stats.tx_bytes += u4SkbLen; + prDev->stats.tx_packets++; +#if CFG_SUPPORT_PERF_IND + /* update Performance Indicator statistics*/ + prGlueInfo->PerfIndCache.u4CurTxBytes[ucBssIndex] += u4SkbLen; +#endif + + DBGLOG(TX, LOUD, + "Enqueue frame for BSS[%u] QIDX[%u] PKT_LEN[%u] TOT_CNT[%d] PER-Q_CNT[%d]\n", + ucBssIndex, u2QueueIdx, u4SkbLen, + GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum), + GLUE_GET_REF_CNT( + prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex] + [u2QueueIdx])); + + if (HAL_IS_TX_DIRECT(prGlueInfo->prAdapter)) + return nicTxDirectStartXmit(prSkb, prGlueInfo); + + kalSetEvent(prGlueInfo); + + return WLAN_STATUS_SUCCESS; +} /* end of kalHardStartXmit() */ + +uint32_t kalResetStats(IN struct net_device *prDev) +{ + DBGLOG(QM, LOUD, "Reset NetDev[0x%p] statistics\n", prDev); + + kalMemZero(kalGetStats(prDev), + sizeof(struct net_device_stats)); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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. + */ +/*----------------------------------------------------------------------------*/ +void *kalGetStats(IN struct net_device *prDev) +{ + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate; + + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prDev); + return (void *) &prNetDevPrivate->stats; +} /* end of wlanGetStats() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct GLUE_INFO + *prGlueInfo, IN void *pvPacket) +{ + struct net_device *prDev = NULL; + struct sk_buff *prSkb = NULL; + uint16_t u2QueueIdx = 0; + uint8_t ucBssIndex = 0; + u_int8_t fgIsValidDevice = TRUE; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(pvPacket); + /* ASSERT(prGlueInfo->i4TxPendingFrameNum); */ + + prSkb = (struct sk_buff *)pvPacket; + u2QueueIdx = skb_get_queue_mapping(prSkb); + ASSERT(u2QueueIdx < CFG_MAX_TXQ_NUM); + + ucBssIndex = GLUE_GET_PKT_BSS_IDX(pvPacket); + +#if 0 + if ((GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum) <= + 0)) { + uint8_t ucBssIdx; + uint16_t u2QIdx; + + DBGLOG(INIT, INFO, "TxPendingFrameNum[%u] CurFrameId[%u]\n", + prGlueInfo->i4TxPendingFrameNum, + GLUE_GET_PKT_ARRIVAL_TIME(pvPacket)); + + for (ucBssIdx = 0; ucBssIdx < prAdapter->ucHwBssIdNum; + ucBssIdx++) { + for (u2QIdx = 0; u2QIdx < CFG_MAX_TXQ_NUM; u2QIdx++) { + DBGLOG(INIT, INFO, + "BSS[%u] Q[%u] TxPendingFrameNum[%u]\n", + ucBssIdx, u2QIdx, + prGlueInfo->ai4TxPendingFrameNumPerQueue + [ucBssIdx][u2QIdx]); + } + } + } + + ASSERT((GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum) > + 0)); +#endif + + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingFrameNum); + GLUE_DEC_REF_CNT( + prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex] + [u2QueueIdx]); + + DBGLOG(TX, LOUD, + "Release frame for BSS[%u] QIDX[%u] PKT_LEN[%u] TOT_CNT[%d] PER-Q_CNT[%d]\n", + ucBssIndex, u2QueueIdx, prSkb->len, + GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum), + GLUE_GET_REF_CNT( + prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex] + [u2QueueIdx])); + + prDev = prSkb->dev; + + ASSERT(prDev); + +#if CFG_ENABLE_WIFI_DIRECT + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + { + struct BSS_INFO *prBssInfo = GET_BSS_INFO_BY_INDEX( + prGlueInfo->prAdapter, ucBssIndex); + struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) + NULL; + struct net_device *prNetdevice = NULL; + + /* in case packet was sent after P2P device is unregistered or + * the net_device was be free + */ + if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) { + if (prGlueInfo->prAdapter->fgIsP2PRegistered == FALSE) + fgIsValidDevice = FALSE; + else { + ASSERT(prBssInfo->u4PrivateData < KAL_P2P_NUM); + prGlueP2pInfo = + prGlueInfo->prP2PInfo[ + prBssInfo->u4PrivateData]; + if (prGlueP2pInfo) { + prNetdevice = + prGlueP2pInfo->aprRoleHandler; + /* The net_device may be free */ + if ((prDev != prNetdevice) + && (prDev != + prGlueP2pInfo->prDevHandler)) { + fgIsValidDevice = FALSE; + DBGLOG(TX, LOUD, + "kalSendCompleteAndAwakeQueue net device deleted! ucBssIndex = %u\n", + ucBssIndex); + } + } + } + } + } +#endif + + if (fgIsValidDevice == TRUE) { + uint32_t u4StartTh = + prGlueInfo->prAdapter->rWifiVar.u4NetifStartTh; + + if (netif_subqueue_stopped(prDev, prSkb) && + prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex] + [u2QueueIdx] <= u4StartTh) { + netif_wake_subqueue(prDev, u2QueueIdx); + DBGLOG(TX, INFO, + "WakeUp Queue BSS[%u] QIDX[%u] PKT_LEN[%u] TOT_CNT[%d] PER-Q_CNT[%d]\n", + ucBssIndex, u2QueueIdx, prSkb->len, + GLUE_GET_REF_CNT( + prGlueInfo->i4TxPendingFrameNum), + GLUE_GET_REF_CNT( + prGlueInfo-> + ai4TxPendingFrameNumPerQueue + [ucBssIndex][u2QueueIdx])); + } + } + +#if CFG_ENABLE_WIFI_DIRECT + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); +#endif + + dev_kfree_skb_any((struct sk_buff *)pvPacket); + + DBGLOG(TX, LOUD, "----- pending frame %d -----\n", + prGlueInfo->i4TxPendingFrameNum); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Copy Mac Address setting from registry. It's All Zeros in Linux. + * + * \param[in] prAdapter Pointer to the Adapter structure + * + * \param[out] paucMacAddr Pointer to the Mac Address buffer + * + * \retval WLAN_STATUS_SUCCESS + * + * \note + */ +/*----------------------------------------------------------------------------*/ +void kalQueryRegistryMacAddr(IN struct GLUE_INFO + *prGlueInfo, OUT uint8_t *paucMacAddr) +{ + uint8_t aucZeroMac[MAC_ADDR_LEN] = { 0, 0, 0, 0, 0, 0 } + + DEBUGFUNC("kalQueryRegistryMacAddr"); + + ASSERT(prGlueInfo); + ASSERT(paucMacAddr); + + kalMemCopy((void *) paucMacAddr, (void *) aucZeroMac, + MAC_ADDR_LEN); + +} /* end of kalQueryRegistryMacAddr() */ + +#if CFG_SUPPORT_EXT_CONFIG +/*----------------------------------------------------------------------------*/ +/*! + * \brief Read external configuration, ex. NVRAM or file + * + * \param[in] prGlueInfo Pointer of GLUE Data Structure + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +uint32_t kalReadExtCfg(IN struct GLUE_INFO *prGlueInfo) +{ + ASSERT(prGlueInfo); + + /* External data is given from user space by ioctl or /proc, not read by + * driver. + */ + if (prGlueInfo->u4ExtCfgLength != 0) + DBGLOG(INIT, TRACE, + "Read external configuration data -- OK\n"); + else + DBGLOG(INIT, TRACE, + "Read external configuration data -- fail\n"); + + return prGlueInfo->u4ExtCfgLength; +} +#endif + +u_int8_t +kalIPv4FrameClassifier(IN struct GLUE_INFO *prGlueInfo, + IN void *prPacket, IN uint8_t *pucIpHdr, + OUT struct TX_PACKET_INFO *prTxPktInfo) +{ + uint8_t ucIpVersion, ucIcmpType; + uint8_t ucIpProto; + uint8_t ucSeqNo; + uint8_t *pucUdpHdr, *pucIcmp; + uint16_t u2DstPort; + struct BOOTP_PROTOCOL *prBootp; + uint32_t u4DhcpMagicCode; + uint16_t u2IpId; +#if CFG_SUPPORT_WIFI_SYSDVT +#if (CFG_TCP_IP_CHKSUM_OFFLOAD) + struct ADAPTER *prAdapter = NULL; +#endif +#endif /* Automation */ + + /* IPv4 version check */ + ucIpVersion = (pucIpHdr[0] & IP_VERSION_MASK) >> + IP_VERSION_OFFSET; + if (ucIpVersion != IP_VERSION_4) { + DBGLOG(TX, WARN, "Invalid IPv4 packet version: %u\n", + ucIpVersion); + return FALSE; + } + + ucIpProto = pucIpHdr[IPV4_HDR_IP_PROTOCOL_OFFSET]; + u2IpId = (pucIpHdr[IPV4_ADDR_LEN] << 8) | pucIpHdr[IPV4_ADDR_LEN + 1]; + GLUE_SET_PKT_IP_ID(prPacket, u2IpId); + +#if CFG_SUPPORT_WIFI_SYSDVT +#if (CFG_TCP_IP_CHKSUM_OFFLOAD) + prAdapter = prGlueInfo->prAdapter; + + /* set IP CHECKSUM to 0xff for verify CSO function */ + if (prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_TX_IP + && CSO_TX_IPV4_ENABLED(prAdapter)) { + pucIpHdr[IPV4_HDR_IP_CSUM_OFFSET] = 0xff; + pucIpHdr[IPV4_HDR_IP_CSUM_OFFSET+1] = 0xff; + } +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ +#endif /* Automation */ + + if (ucIpProto == IP_PRO_UDP) { + pucUdpHdr = &pucIpHdr[IPV4_HDR_LEN]; + +#if CFG_SUPPORT_WIFI_SYSDVT +#if (CFG_TCP_IP_CHKSUM_OFFLOAD) + /* set UDP CHECKSUM to 0xff for verify CSO function */ + if (prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_TX_UDP + && CSO_TX_UDP_ENABLED(prAdapter)) { + pucUdpHdr[UDP_HDR_UDP_CSUM_OFFSET] = 0xff; + pucUdpHdr[UDP_HDR_UDP_CSUM_OFFSET+1] = 0xff; + } +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ +#endif /* Automation */ + + /* Get UDP DST port */ + WLAN_GET_FIELD_BE16(&pucUdpHdr[UDP_HDR_DST_PORT_OFFSET], + &u2DstPort); + + /* BOOTP/DHCP protocol */ + if ((u2DstPort == IP_PORT_BOOTP_SERVER) || + (u2DstPort == IP_PORT_BOOTP_CLIENT)) { + prBootp = (struct BOOTP_PROTOCOL *) + &pucUdpHdr[UDP_HDR_LEN]; + WLAN_GET_FIELD_BE32(&prBootp->aucOptions[0], + &u4DhcpMagicCode); + if (u4DhcpMagicCode == DHCP_MAGIC_NUMBER) { + ucSeqNo = nicIncreaseTxSeqNum( + prGlueInfo->prAdapter); + GLUE_SET_PKT_SEQ_NO(prPacket, ucSeqNo); + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_DHCP); + } + } else if (u2DstPort == UDP_PORT_DNS) { + ucSeqNo = nicIncreaseTxSeqNum(prGlueInfo->prAdapter); + GLUE_SET_PKT_SEQ_NO(prPacket, ucSeqNo); + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_DNS); + } + } else if (ucIpProto == IP_PRO_ICMP) { + pucIcmp = &pucIpHdr[20]; + ucIcmpType = pucIcmp[0]; + if (ucIcmpType == 3) /* don't log network unreachable packet */ + return FALSE; + ucSeqNo = nicIncreaseTxSeqNum(prGlueInfo->prAdapter); + GLUE_SET_PKT_SEQ_NO(prPacket, ucSeqNo); + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_ICMP); + } +#if CFG_SUPPORT_WIFI_SYSDVT +#if (CFG_TCP_IP_CHKSUM_OFFLOAD) + else if (ucIpProto == IP_PRO_TCP) { + uint8_t *pucTcpHdr; + + pucTcpHdr = &pucIpHdr[IPV4_HDR_LEN]; + /* set TCP CHECKSUM to 0xff for verify CSO function */ + if (prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_TX_TCP + && CSO_TX_TCP_ENABLED(prAdapter)) { + pucTcpHdr[TCP_HDR_TCP_CSUM_OFFSET] = 0xff; + pucTcpHdr[TCP_HDR_TCP_CSUM_OFFSET+1] = 0xff; + } + } +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ +#endif /* Automation */ + + return TRUE; +} + +u_int8_t +kalIPv6FrameClassifier(IN struct GLUE_INFO *prGlueInfo, + IN void *prPacket, IN uint8_t *pucIpv6Hdr, + OUT struct TX_PACKET_INFO *prTxPktInfo) +{ + uint8_t ucIpv6Proto; + uint8_t *pucL3Hdr; + struct ADAPTER *prAdapter = NULL; + + prAdapter = prGlueInfo->prAdapter; + ucIpv6Proto = pucIpv6Hdr[IPV6_HDR_IP_PROTOCOL_OFFSET]; + + if (ucIpv6Proto == IP_PRO_UDP) { + pucL3Hdr = &pucIpv6Hdr[IPV6_HDR_LEN]; +#if CFG_SUPPORT_WIFI_SYSDVT +#if (CFG_TCP_IP_CHKSUM_OFFLOAD) + /* set UDP CHECKSUM to 0xff for verify CSO function */ + if ((prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_TX_UDP) + && CSO_TX_UDP_ENABLED(prAdapter)) { + pucL3Hdr[UDP_HDR_UDP_CSUM_OFFSET] = 0xff; + pucL3Hdr[UDP_HDR_UDP_CSUM_OFFSET+1] = 0xff; + } +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ +#endif /* Automation */ + } else if (ucIpv6Proto == IP_PRO_TCP) { + pucL3Hdr = &pucIpv6Hdr[IPV6_HDR_LEN]; +#if CFG_SUPPORT_WIFI_SYSDVT +#if (CFG_TCP_IP_CHKSUM_OFFLOAD) + /* set TCP CHECKSUM to 0xff for verify CSO function */ + if ((prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_TX_TCP) + && CSO_TX_TCP_ENABLED(prAdapter)) { + pucL3Hdr[TCP_HDR_TCP_CSUM_OFFSET] = 0xff; + pucL3Hdr[TCP_HDR_TCP_CSUM_OFFSET+1] = 0xff; + } +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ +#endif /* Automation */ + } + + return TRUE; +} + +u_int8_t +kalArpFrameClassifier(IN struct GLUE_INFO *prGlueInfo, + IN void *prPacket, IN uint8_t *pucIpHdr, + OUT struct TX_PACKET_INFO *prTxPktInfo) +{ + uint8_t ucSeqNo; + ucSeqNo = nicIncreaseTxSeqNum(prGlueInfo->prAdapter); + GLUE_SET_PKT_SEQ_NO(prPacket, ucSeqNo); + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_ARP); + return TRUE; +} + +u_int8_t +kalTdlsFrameClassifier(IN struct GLUE_INFO *prGlueInfo, + IN void *prPacket, IN uint8_t *pucIpHdr, + OUT struct TX_PACKET_INFO *prTxPktInfo) +{ + uint8_t ucSeqNo; + + ucSeqNo = nicIncreaseTxSeqNum(prGlueInfo->prAdapter); + GLUE_SET_PKT_SEQ_NO(prPacket, ucSeqNo); + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_TDLS); + + return TRUE; +} + +u_int8_t +kalSecurityFrameClassifier(IN struct GLUE_INFO *prGlueInfo, + IN void *prPacket, IN uint8_t *pucIpHdr, + IN uint16_t u2EthType, IN uint8_t *aucLookAheadBuf, + OUT struct TX_PACKET_INFO *prTxPktInfo) +{ + uint8_t *pucEapol; + uint8_t ucEapolType; + uint8_t ucSeqNo; + uint8_t ucEAPoLKey = 0; + uint8_t ucEapOffset = ETHER_HEADER_LEN; + uint16_t u2KeyInfo = 0; + + pucEapol = pucIpHdr; + + if (u2EthType == ETH_P_1X) { + + ucEapolType = pucEapol[1]; + + /* Leave EAP to check */ + ucEAPoLKey = aucLookAheadBuf[1 + ucEapOffset]; + if (ucEAPoLKey != ETH_EAPOL_KEY) + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_NON_PROTECTED_1X); + else { + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[5 + ucEapOffset], + &u2KeyInfo); + /* BIT3 is pairwise key bit */ + DBGLOG(TX, INFO, "u2KeyInfo=%d\n", u2KeyInfo); + if (u2KeyInfo & BIT(3)) + prTxPktInfo->u2Flag |= + BIT(ENUM_PKT_NON_PROTECTED_1X); + } + + ucSeqNo = nicIncreaseTxSeqNum(prGlueInfo->prAdapter); + GLUE_SET_PKT_SEQ_NO(prPacket, ucSeqNo); +#if CFG_SUPPORT_WAPI + } else if (u2EthType == ETH_WPI_1X) { + ucSeqNo = nicIncreaseTxSeqNum(prGlueInfo->prAdapter); + GLUE_SET_PKT_SEQ_NO(prPacket, ucSeqNo); + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_NON_PROTECTED_1X); +#endif + } + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_1X); + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 prPacket Packet descriptor + * @param prTxPktInfo Extracted packet info + * + * @retval TRUE Success to extract information + * @retval FALSE Fail to extract correct information + */ +/*----------------------------------------------------------------------------*/ +u_int8_t +kalQoSFrameClassifierAndPacketInfo(IN struct GLUE_INFO *prGlueInfo, + IN void *prPacket, OUT struct TX_PACKET_INFO *prTxPktInfo) +{ + uint32_t u4PacketLen; + uint16_t u2EtherTypeLen; + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + uint8_t *aucLookAheadBuf = NULL; + uint8_t ucEthTypeLenOffset = ETHER_HEADER_LEN - + ETHER_TYPE_LEN; + uint8_t *pucNextProtocol = NULL; +#if DSCP_SUPPORT + uint8_t ucUserPriority; +#endif + + u4PacketLen = prSkb->len; + + if (u4PacketLen < ETHER_HEADER_LEN) { + DBGLOG(INIT, WARN, "Invalid Ether packet length: %u\n", + u4PacketLen); + return FALSE; + } + + aucLookAheadBuf = prSkb->data; + + /* Reset Packet Info */ + kalMemZero(prTxPktInfo, sizeof(struct TX_PACKET_INFO)); + + /* 4 <0> Obtain Ether Type/Len */ + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[ucEthTypeLenOffset], + &u2EtherTypeLen); + + /* 4 <1> Skip 802.1Q header (VLAN Tagging) */ + if (u2EtherTypeLen == ETH_P_VLAN) { + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_VLAN_EXIST); + ucEthTypeLenOffset += ETH_802_1Q_HEADER_LEN; + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[ucEthTypeLenOffset], + &u2EtherTypeLen); + } + /* 4 <2> Obtain next protocol pointer */ + pucNextProtocol = &aucLookAheadBuf[ucEthTypeLenOffset + + ETHER_TYPE_LEN]; + + /* 4 <3> Handle ethernet format */ + switch (u2EtherTypeLen) { + case ETH_P_IPV4: + /* IPv4 header length check */ + if (u4PacketLen < (ucEthTypeLenOffset + ETHER_TYPE_LEN + + IPV4_HDR_LEN)) { + DBGLOG(INIT, WARN, "Invalid IPv4 packet length: %u\n", + u4PacketLen); + break; + } +#if DSCP_SUPPORT + if (GLUE_GET_PKT_BSS_IDX(prSkb) != P2P_DEV_BSS_INDEX) { + ucUserPriority = getUpFromDscp( + prGlueInfo, + GLUE_GET_PKT_BSS_IDX(prSkb), + (pucNextProtocol[1] >> 2) & 0x3F); + if (ucUserPriority != 0xFF) + prSkb->priority = ucUserPriority; + } +#endif + kalIPv4FrameClassifier(prGlueInfo, prPacket, + pucNextProtocol, prTxPktInfo); + break; + + case ETH_P_ARP: + kalArpFrameClassifier(prGlueInfo, prPacket, pucNextProtocol, + prTxPktInfo); + break; + + case ETH_P_1X: + case ETH_P_PRE_1X: +#if CFG_SUPPORT_WAPI + case ETH_WPI_1X: +#endif + kalSecurityFrameClassifier(prGlueInfo, prPacket, + pucNextProtocol, u2EtherTypeLen, aucLookAheadBuf, + prTxPktInfo); + break; + + case ETH_PRO_TDLS: + kalTdlsFrameClassifier(prGlueInfo, prPacket, + pucNextProtocol, prTxPktInfo); + break; + + case ETH_P_IPV6: +#if CFG_SUPPORT_WIFI_SYSDVT +#if (CFG_TCP_IP_CHKSUM_OFFLOAD) + kalIPv6FrameClassifier(prGlueInfo, prPacket, + pucNextProtocol, prTxPktInfo); +#endif +#endif + +#if DSCP_SUPPORT + if (GLUE_GET_PKT_BSS_IDX(prSkb) != P2P_DEV_BSS_INDEX) { + uint16_t u2Tmp; + uint8_t ucIpTos; + + WLAN_GET_FIELD_BE16(pucNextProtocol, &u2Tmp); + ucIpTos = u2Tmp >> 4; + + ucUserPriority = getUpFromDscp( + prGlueInfo, + GLUE_GET_PKT_BSS_IDX(prSkb), + (ucIpTos >> 2) & 0x3F); + if (ucUserPriority != 0xFF) + prSkb->priority = ucUserPriority; + } +#endif + break; + + default: + /* 4 <4> Handle 802.3 format if LEN <= 1500 */ + if (u2EtherTypeLen <= ETH_802_3_MAX_LEN) + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_802_3); + break; + } + + STATS_TX_PKT_INFO_DISPLAY(prSkb); + + /* 4 <4.1> Check for PAL (BT over Wi-Fi) */ + /* Move to kalBowFrameClassifier */ + + /* 4 <5> Return the value of Priority Parameter. */ + /* prSkb->priority is assigned by Linux wireless utility + * function(cfg80211_classify8021d) + */ + /* at net_dev selection callback (ndo_select_queue) */ + prTxPktInfo->ucPriorityParam = prSkb->priority; + +#if CFG_CHANGE_PRIORITY_BY_SKB_MARK_FIELD + /* Raise priority for special packet if skb mark filed + * marked with pre-defined value. + */ + if (prSkb->mark == NIC_TX_SKB_PRIORITY_MARK1 || + (prSkb->mark & BIT(NIC_TX_SKB_PRIORITY_MARK_BIT))) { + prTxPktInfo->ucPriorityParam = NIC_TX_PRIORITY_DATA_TID; + DBGLOG_LIMITED(INIT, TRACE, + "skb mark field=[%x]", prSkb->mark); + } +#endif + + /* 4 <6> Retrieve Packet Information - DA */ + /* Packet Length/ Destination Address */ + prTxPktInfo->u4PacketLen = u4PacketLen; + + kalMemCopy(prTxPktInfo->aucEthDestAddr, aucLookAheadBuf, + PARAM_MAC_ADDR_LEN); + + return TRUE; +} /* end of kalQoSFrameClassifier() */ + +u_int8_t kalGetEthDestAddr(IN struct GLUE_INFO *prGlueInfo, + IN void *prPacket, OUT uint8_t *pucEthDestAddr) +{ + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + uint8_t *aucLookAheadBuf = NULL; + + /* Sanity Check */ + if (!prPacket || !prGlueInfo) + return FALSE; + + aucLookAheadBuf = prSkb->data; + + kalMemCopy(pucEthDestAddr, aucLookAheadBuf, + PARAM_MAC_ADDR_LEN); + + return TRUE; +} + +void +kalOidComplete(IN struct GLUE_INFO *prGlueInfo, + IN u_int8_t fgSetQuery, IN uint32_t u4SetQueryInfoLen, + IN uint32_t rOidStatus) +{ + + ASSERT(prGlueInfo); + /* remove timeout check timer */ + wlanoidClearTimeoutCheck(prGlueInfo->prAdapter); + + prGlueInfo->rPendStatus = rOidStatus; + + prGlueInfo->u4OidCompleteFlag = 1; + /* complete ONLY if there are waiters */ + if (!completion_done(&prGlueInfo->rPendComp)) { + complete(&prGlueInfo->rPendComp); + } else { + DBGLOG(INIT, WARN, "SKIP multiple OID complete!\n"); + /* WARN_ON(TRUE); */ + } + + if (rOidStatus == WLAN_STATUS_SUCCESS) + DBGLOG(INIT, TRACE, "Complete OID, status:success\n"); + else + DBGLOG(INIT, WARN, "Complete OID, status:0x%08x\n", + rOidStatus); + + /* else let it timeout on kalIoctl entry */ +} + +void kalOidClearance(IN struct GLUE_INFO *prGlueInfo) +{ + +} + +void kalGetLocalTime(unsigned long long *sec, unsigned long *nsec) +{ + if (sec != NULL && nsec != NULL) { + *sec = local_clock(); + *nsec = do_div(*sec, 1000000000)/1000; + } else + DBGLOG(INIT, ERROR, + "The input parameters error when get local time\n"); +} + +/* + * kalThreadSchedRetrieve + * Retrieve thread's current scheduling statistics and + * stored in output "sched". + * Return value: + * 0 : Schedstats successfully retrieved + * -1 : Kernel's schedstats feature not enabled + * -2 : pThread not yet initialized or sched is a NULL pointer + */ +static int32_t kalThreadSchedRetrieve(struct task_struct *pThread, + struct KAL_THREAD_SCHEDSTATS *pSched) +{ +#ifdef CONFIG_SCHEDSTATS + struct sched_entity se; + unsigned long long sec; + unsigned long usec; + + if (!pSched) + return -2; + + /* always clear sched to simplify error handling at caller side */ + memset(pSched, 0, sizeof(struct KAL_THREAD_SCHEDSTATS)); + + if (!pThread || kalIsResetting()) + return -2; + + memcpy(&se, &pThread->se, sizeof(struct sched_entity)); + kalGetLocalTime(&sec, &usec); + + pSched->time = sec*1000 + usec/1000; + pSched->exec = se.sum_exec_runtime; + pSched->runnable = se.statistics.wait_sum; + pSched->iowait = se.statistics.iowait_sum; + + return 0; +#else + /* always clear sched to simplify error handling at caller side */ + if (pSched) + memset(pSched, 0, sizeof(struct KAL_THREAD_SCHEDSTATS)); + return -1; +#endif +} + +/* + * kalThreadSchedMark + * Record the thread's current schedstats and stored in + * output "schedstats" parameter for profiling at later time. + * Return value: + * 0 : Schedstats successfully recorded + * -1 : Kernel's schedstats feature not enabled + * -2 : pThread not yet initialized or invalid parameters + */ +int32_t kalThreadSchedMark(struct task_struct *pThread, + struct KAL_THREAD_SCHEDSTATS *pSchedstats) +{ + return kalThreadSchedRetrieve(pThread, pSchedstats); +} + +/* + * kalThreadSchedUnmark + * Calculate scheduling statistics against the previously marked point. + * The result will be filled back into the schedstats output parameter. + * Return value: + * 0 : Schedstats successfully calculated + * -1 : Kernel's schedstats feature not enabled + * -2 : pThread not yet initialized or invalid parameters + */ +int32_t kalThreadSchedUnmark(struct task_struct *pThread, + struct KAL_THREAD_SCHEDSTATS *pSchedstats) +{ + int32_t ret; + struct KAL_THREAD_SCHEDSTATS sched_now; + + if (unlikely(!pSchedstats)) { + ret = -2; + } else { + ret = kalThreadSchedRetrieve(pThread, &sched_now); + if (ret == 0) { + pSchedstats->time = + sched_now.time - pSchedstats->time; + pSchedstats->exec = + sched_now.exec - pSchedstats->exec; + pSchedstats->runnable = + sched_now.runnable - pSchedstats->runnable; + pSchedstats->iowait = + sched_now.iowait - pSchedstats->iowait; + } + } + return ret; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @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; */ + +uint8_t GET_IOCTL_BSSIDX( + IN struct ADAPTER *prAdapter) +{ + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + if (prAdapter) { + struct GL_IO_REQ *prIoReq = NULL; + + prIoReq = + &(prAdapter->prGlueInfo + ->OidEntry); + + ucBssIndex = prIoReq->ucBssIndex; + } + + return ucBssIndex; +} + +void SET_IOCTL_BSSIDX( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + if (prAdapter) { + struct GL_IO_REQ *prIoReq = NULL; + + prIoReq = + &(prAdapter->prGlueInfo + ->OidEntry); + + prIoReq->ucBssIndex = ucBssIndex; + } +} + +uint32_t +kalIoctl(IN struct GLUE_INFO *prGlueInfo, + IN PFN_OID_HANDLER_FUNC pfnOidHandler, + IN void *pvInfoBuf, + IN uint32_t u4InfoBufLen, IN u_int8_t fgRead, + IN u_int8_t fgWaitResp, IN u_int8_t fgCmd, + OUT uint32_t *pu4QryInfoLen) +{ + return kalIoctlByBssIdx( + prGlueInfo, + pfnOidHandler, + pvInfoBuf, + u4InfoBufLen, + fgRead, + fgWaitResp, + fgCmd, + pu4QryInfoLen, + AIS_DEFAULT_INDEX); +} + +uint32_t +kalIoctlByBssIdx(IN struct GLUE_INFO *prGlueInfo, + IN PFN_OID_HANDLER_FUNC pfnOidHandler, + IN void *pvInfoBuf, + IN uint32_t u4InfoBufLen, IN u_int8_t fgRead, + IN u_int8_t fgWaitResp, IN u_int8_t fgCmd, + OUT uint32_t *pu4QryInfoLen, + IN uint8_t ucBssIndex) +{ + struct GL_IO_REQ *prIoReq = NULL; + struct KAL_THREAD_SCHEDSTATS schedstats; + uint32_t ret = WLAN_STATUS_SUCCESS; + uint32_t waitRet = 0; + + KAL_TIME_INTERVAL_DECLARATION(); + + KAL_REC_TIME_START(); + + if (kalIsResetting()) + return WLAN_STATUS_SUCCESS; + + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prAdapter); + + if (wlanIsChipAssert(prGlueInfo->prAdapter)) + return WLAN_STATUS_SUCCESS; + + /* GLUE_SPIN_LOCK_DECLARATION(); */ + + /* <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; + } + + if (prGlueInfo->main_thread == NULL) { + dump_stack(); + DBGLOG(OID, WARN, "skip executing request.\n"); + up(&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; + SET_IOCTL_BSSIDX( + prGlueInfo->prAdapter, + ucBssIndex); + + /* <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 + * Use memory barrier to ensure OidEntry is written done and then set + * bit. + */ + smp_mb(); + set_bit(GLUE_FLAG_OID_BIT, &prGlueInfo->ulFlag); + + /* <7.1> Hold wakelock to ensure OS won't be suspended */ + KAL_WAKE_LOCK_TIMEOUT(prGlueInfo->prAdapter, + prGlueInfo->rTimeoutWakeLock, MSEC_TO_JIFFIES( + prGlueInfo->prAdapter->rWifiVar.u4WakeLockThreadWakeup)); + + /* <8> Wake up main thread to handle kick start the I/O request. + * Use memory barrier to ensure set bit is done and then wake up main + * thread. + */ + smp_mb(); + wake_up_interruptible(&prGlueInfo->waitq); + + /* <9> Block and wait for event or timeout, + * current the timeout is 30 secs + */ + kalThreadSchedMark(prGlueInfo->main_thread, &schedstats); + waitRet = wait_for_completion_timeout(&prGlueInfo->rPendComp, + MSEC_TO_JIFFIES(30*1000)); + kalThreadSchedUnmark(prGlueInfo->main_thread, &schedstats); + if (waitRet > 0) { + /* 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; + } else { + +#if 0 + /* Case 2: timeout */ + /* clear pending OID's cmd in CMD queue */ + if (fgCmd) { + prGlueInfo->u4TimeoutFlag = 1; + wlanReleasePendingOid(prGlueInfo->prAdapter, 0); + } +#endif + /* note: do not dump main_thread's call stack here, */ + /* because it may be running on other cpu. */ + DBGLOG(OID, WARN, + "wait main_thread timeout, duration:%llums, sched(x%llu/r%llu/i%llu)\n", + schedstats.time, schedstats.exec, + schedstats.runnable, schedstats.iowait); + + ret = WLAN_STATUS_FAILURE; + } + + /* <10> Clear bit for error handling */ + clear_bit(GLUE_FLAG_OID_BIT, &prGlueInfo->ulFlag); + + up(&prGlueInfo->ioctl_sem); + up(&g_halt_sem); + + KAL_REC_TIME_END(); + if (ret != WLAN_STATUS_SUCCESS) + DBGLOG(OID, WARN, "ret(%x) time: %lu us\n", + ret, + KAL_GET_TIME_INTERVAL()); + + 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 struct GLUE_INFO *prGlueInfo) +{ + struct QUE *prCmdQue; + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue = &rTempCmdQue; + struct QUE rReturnCmdQue; + struct QUE *prReturnCmdQue = &rReturnCmdQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + QUEUE_INITIALIZE(prReturnCmdQue); + /* Clear pending security frames in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME || + prCmdInfo->eCmdType == COMMAND_TYPE_DATA_FRAME) { + if (prCmdInfo->pfCmdTimeoutHandler) + prCmdInfo->pfCmdTimeoutHandler( + prGlueInfo->prAdapter, prCmdInfo); + else + wlanReleaseCommand(prGlueInfo->prAdapter, + prCmdInfo, TX_RESULT_QUEUE_CLEARANCE); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingCmdNum); + } else { + QUEUE_INSERT_TAIL(prReturnCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(prCmdQue, prReturnCmdQue); + 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 kalClearSecurityFramesByBssIdx(IN struct GLUE_INFO + *prGlueInfo, IN uint8_t ucBssIndex) +{ + struct QUE *prCmdQue; + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue = &rTempCmdQue; + struct QUE rReturnCmdQue; + struct QUE *prReturnCmdQue = &rReturnCmdQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) NULL; + struct MSDU_INFO *prMsduInfo; + u_int8_t fgFree; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + QUEUE_INITIALIZE(prReturnCmdQue); + /* Clear pending security frames in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + prMsduInfo = prCmdInfo->prMsduInfo; + fgFree = FALSE; + + if ((prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME || + prCmdInfo->eCmdType == COMMAND_TYPE_DATA_FRAME) + && prMsduInfo) { + if (prMsduInfo->ucBssIndex == ucBssIndex) + fgFree = TRUE; + } + + if (fgFree) { + if (prCmdInfo->pfCmdTimeoutHandler) + prCmdInfo->pfCmdTimeoutHandler( + prGlueInfo->prAdapter, prCmdInfo); + else + wlanReleaseCommand(prGlueInfo->prAdapter, + prCmdInfo, TX_RESULT_QUEUE_CLEARANCE); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingCmdNum); + } else + QUEUE_INSERT_TAIL(prReturnCmdQue, prQueueEntry); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(prCmdQue, prReturnCmdQue); + 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 struct GLUE_INFO *prGlueInfo) +{ + struct QUE *prCmdQue; + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue = &rTempCmdQue; + struct QUE rReturnCmdQue; + struct QUE *prReturnCmdQue = &rReturnCmdQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + QUEUE_INITIALIZE(prReturnCmdQue); + /* Clear pending management frames in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) { + wlanReleaseCommand(prGlueInfo->prAdapter, prCmdInfo, + TX_RESULT_QUEUE_CLEARANCE); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingCmdNum); + } else { + QUEUE_INSERT_TAIL(prReturnCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(prCmdQue, prReturnCmdQue); + 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 kalClearMgmtFramesByBssIdx(IN struct GLUE_INFO + *prGlueInfo, IN uint8_t ucBssIndex) +{ + struct QUE *prCmdQue; + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue = &rTempCmdQue; + struct QUE rReturnCmdQue; + struct QUE *prReturnCmdQue = &rReturnCmdQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) NULL; + struct MSDU_INFO *prMsduInfo; + u_int8_t fgFree; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + QUEUE_INITIALIZE(prReturnCmdQue); + /* Clear pending management frames in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + prMsduInfo = prCmdInfo->prMsduInfo; + fgFree = FALSE; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME + && prMsduInfo) { + if (prMsduInfo->ucBssIndex == ucBssIndex) + fgFree = TRUE; + } + + if (fgFree) { + wlanReleaseCommand(prGlueInfo->prAdapter, prCmdInfo, + TX_RESULT_QUEUE_CLEARANCE); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingCmdNum); + } else { + QUEUE_INSERT_TAIL(prReturnCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(prCmdQue, prReturnCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); +} /* kalClearMgmtFramesByBssIdx */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to clear all commands in command queue + * \param prGlueInfo Pointer of GLUE Data Structure + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +void kalClearCommandQueue(IN struct GLUE_INFO *prGlueInfo) +{ + struct QUE *prCmdQue; + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue = &rTempCmdQue; + struct QUE rReturnCmdQue; + struct QUE *prReturnCmdQue = &rReturnCmdQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + QUEUE_INITIALIZE(prReturnCmdQue); + + /* Clear ALL in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + + if (prCmdInfo->pfCmdTimeoutHandler) + prCmdInfo->pfCmdTimeoutHandler(prGlueInfo->prAdapter, + prCmdInfo); + else + wlanReleaseCommand(prGlueInfo->prAdapter, prCmdInfo, + TX_RESULT_QUEUE_CLEARANCE); + + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingCmdNum); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } +} + +#if CFG_SUPPORT_LOWLATENCY_MODE +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to check use packet data into command Queue flow + * + * \param prAdapter Pointer of prAdapter Structure + * \param prAdapter Pointer of prAdapter Structure + * \retval is TRUE (run command Data path flow) or FALSE (not use) + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalIsCommandDataPath(IN struct ADAPTER + *prAdapter, IN void *prPacket) +{ + struct sk_buff *skb = (struct sk_buff *)prPacket; + + if (prAdapter->rWifiVar.ucLowLatencyCmdData == 0) + return FALSE; + + if (!prAdapter->fgTxDupCertificate) + return FALSE; + + if (!prAdapter->fgEnTxDupDetect) + return FALSE; + + /* Only detect for special mark packet */ + if (!prAdapter->rWifiVar.ucLowLatencyCmdDataAllPacket && + !(skb->mark & BIT(NIC_TX_SKB_DUP_DETECT_MARK_BIT))) { + DBGLOG_LIMITED(TX, TRACE, + "mark flag=[%x]\n", skb->mark); + return FALSE; + } + + /* Not send special mark flag packets via command path */ + if (GLUE_IS_PKT_FLAG_SET(prPacket)) { + DBGLOG_LIMITED(TX, TRACE, + "Packet flag=[%d]\n", GLUE_IS_PKT_FLAG_SET(prPacket)); + return FALSE; + } + + /* Only handle checksum calculated packets, must not enable + * checksum offload for command data packet. Refer to + * kalQueryTxChksumOffloadParam() + */ + if (skb->ip_summed != CHECKSUM_NONE) { + DBGLOG_LIMITED(TX, TRACE, + "Packet checksum not calculated, ip_summed=[%d]", + skb->ip_summed); + return FALSE; + } + + if (prAdapter->tmTxDataInterval > 0 && + !CHECK_FOR_TIMEOUT(kalGetTimeTick(), + prAdapter->tmTxDataInterval, 10)) { + DBGLOG_LIMITED(TX, TRACE, "Packet interval too close"); + return FALSE; + } + GET_CURRENT_SYSTIME(&prAdapter->tmTxDataInterval); + + DBGLOG_LIMITED(TX, INFO, + "Change data to cmd data frame. Packet flag=[%d], ip_summed=[%d] mark=[%x]\n", + GLUE_IS_PKT_FLAG_SET(prPacket), + skb->ip_summed, + skb->mark); + + DBGLOG_LIMITED(TX, INFO, + "Change data to cmd data frame. Packet flag=[%d], ip_summed=[%d] mark=[%x]\n", + GLUE_IS_PKT_FLAG_SET(prPacket), + skb->ip_summed, + skb->mark); + + return TRUE; +} +#endif + +uint32_t kalProcessTxPacket(struct GLUE_INFO *prGlueInfo, + struct sk_buff *prSkb) +{ + uint32_t u4Status = WLAN_STATUS_SUCCESS; + + if (prSkb == NULL) { + DBGLOG(INIT, WARN, "prSkb == NULL in tx\n"); + return u4Status; + } + + /* Handle security frame */ + if (0 /* GLUE_TEST_PKT_FLAG(prSkb, ENUM_PKT_1X) */ + /* No more sending via cmd */) { + if (wlanProcessSecurityFrame(prGlueInfo->prAdapter, + (void *) prSkb)) { + u4Status = WLAN_STATUS_SUCCESS; + GLUE_INC_REF_CNT( + prGlueInfo->i4TxPendingSecurityFrameNum); + } else { + u4Status = WLAN_STATUS_RESOURCES; + } + } +#if CFG_SUPPORT_LOWLATENCY_MODE + /* Data frame use command path */ + else if (kalIsCommandDataPath(prGlueInfo->prAdapter, + (void *) prSkb)) { + u4Status = wlanProcessCmdDataFrame(prGlueInfo->prAdapter, + (void *) prSkb); + if (u4Status == WLAN_STATUS_SUCCESS) + GLUE_INC_REF_CNT( + prGlueInfo->i4TxPendingSecurityFrameNum); + + } +#endif + /* Handle normal frame */ + else + u4Status = wlanEnqueueTxPacket(prGlueInfo->prAdapter, + (void *) prSkb); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to process Tx request to main_thread + * + * \param prGlueInfo Pointer of GLUE Data Structure + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +void kalProcessTxReq(struct GLUE_INFO *prGlueInfo, + u_int8_t *pfgNeedHwAccess) +{ + struct QUE *prCmdQue = NULL; + struct QUE *prTxQueue = NULL; + struct QUE rTempQue; + struct QUE *prTempQue = &rTempQue; + struct QUE rTempReturnQue; + struct QUE *prTempReturnQue = &rTempReturnQue; + struct QUE_ENTRY *prQueueEntry = NULL; + /* struct sk_buff *prSkb = NULL; */ + uint32_t u4Status; +#if CFG_SUPPORT_MULTITHREAD + uint32_t u4CmdCount = 0; +#endif + uint32_t u4TxLoopCount; + + /* for spin lock acquire and release */ + GLUE_SPIN_LOCK_DECLARATION(); + + prTxQueue = &prGlueInfo->rTxQueue; + prCmdQue = &prGlueInfo->rCmdQueue; + + QUEUE_INITIALIZE(prTempQue); + QUEUE_INITIALIZE(prTempReturnQue); + + u4TxLoopCount = + prGlueInfo->prAdapter->rWifiVar.u4TxFromOsLoopCount; + + /* Process Mailbox Messages */ + wlanProcessMboxMessage(prGlueInfo->prAdapter); + + /* Process CMD request */ +#if CFG_SUPPORT_MULTITHREAD + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + u4CmdCount = prCmdQue->u4NumElem; + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + if (u4CmdCount > 0) + wlanProcessCommandQueue(prGlueInfo->prAdapter, prCmdQue); + +#else + if (prCmdQue->u4NumElem > 0) { + if (*pfgNeedHwAccess == FALSE) { + *pfgNeedHwAccess = TRUE; + + wlanAcquirePowerControl(prGlueInfo->prAdapter); + } + wlanProcessCommandQueue(prGlueInfo->prAdapter, prCmdQue); + } +#endif + + while (u4TxLoopCount--) { + while (QUEUE_IS_NOT_EMPTY(prTxQueue)) { + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_MOVE_ALL(prTempQue, prTxQueue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + + kalTraceBegin("Move TxQueue %d", prTempQue->u4NumElem); + /* Handle Packet Tx */ + while (QUEUE_IS_NOT_EMPTY(prTempQue)) { + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, + struct QUE_ENTRY *); + + if (prQueueEntry == NULL) + break; + + u4Status = kalProcessTxPacket(prGlueInfo, + (struct sk_buff *) + GLUE_GET_PKT_DESCRIPTOR( + prQueueEntry)); +#if 0 + prSkb = (struct sk_buff *) + GLUE_GET_PKT_DESCRIPTOR(prQueueEntry); + ASSERT(prSkb); + if (prSkb == NULL) { + DBGLOG(INIT, WARN, + "prSkb == NULL in tx\n"); + continue; + } + + /* Handle security frame */ + if (GLUE_GET_PKT_IS_1X(prSkb)) { + if (wlanProcessSecurityFrame( + prGlueInfo->prAdapter, + (void *)prSkb)) { + u4Status = WLAN_STATUS_SUCCESS; + GLUE_INC_REF_CNT(prGlueInfo-> + i4TxPendingSecurityFrameNum); + } else { + u4Status = + WLAN_STATUS_RESOURCES; + } + } + /* Handle normal frame */ + else + u4Status = wlanEnqueueTxPacket( + prGlueInfo->prAdapter, + (void *) prSkb); +#endif + /* Enqueue packet back into TxQueue if resource + * is not enough + */ + if (u4Status == WLAN_STATUS_RESOURCES) { + QUEUE_INSERT_TAIL(prTempReturnQue, + prQueueEntry); + break; + } + + if (wlanGetTxPendingFrameCount( + prGlueInfo->prAdapter) > 0) + wlanTxPendingPackets( + prGlueInfo->prAdapter, + pfgNeedHwAccess); + } + kalTraceEnd(); + + /* Enqueue packet back into TxQueue if resource is not + * enough + */ + if (QUEUE_IS_NOT_EMPTY(prTempReturnQue)) { + QUEUE_CONCATENATE_QUEUES(prTempReturnQue, + prTempQue); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, + SPIN_LOCK_TX_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(prTxQueue, + prTempReturnQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, + SPIN_LOCK_TX_QUE); + + break; + } + } + if (wlanGetTxPendingFrameCount(prGlueInfo->prAdapter) > 0) + wlanTxPendingPackets(prGlueInfo->prAdapter, + pfgNeedHwAccess); + } + +} + +#if CFG_SUPPORT_MULTITHREAD + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param data data pointer to private data of hif_thread + * + * @retval If the function succeeds, the return value is 0. + * Otherwise, an error code is returned. + * + */ +/*----------------------------------------------------------------------------*/ + +int hif_thread(void *data) +{ + struct net_device *dev = data; + struct GLUE_INFO *prGlueInfo = *((struct GLUE_INFO **) + netdev_priv(dev)); + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + int ret = 0; + bool fgEnInt; +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + KAL_WAKE_LOCK_T *prHifThreadWakeLock; + + KAL_WAKE_LOCK_INIT(prGlueInfo->prAdapter, + prHifThreadWakeLock, "WLAN hif_thread"); + KAL_WAKE_LOCK(prGlueInfo->prAdapter, prHifThreadWakeLock); +#endif + + DBGLOG(INIT, INFO, "%s:%u starts running...\n", + KAL_GET_CURRENT_THREAD_NAME(), KAL_GET_CURRENT_THREAD_ID()); + + prGlueInfo->u4HifThreadPid = KAL_GET_CURRENT_THREAD_ID(); + + set_user_nice(current, prAdapter->rWifiVar.cThreadNice); + + while (TRUE) { + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT + || kalIsResetting() + ) { + DBGLOG(INIT, INFO, "hif_thread should stop now...\n"); + break; + } + + /* Unlock wakelock if hif_thread going to idle */ + if (!(prGlueInfo->ulFlag & GLUE_FLAG_HIF_PROCESS)) + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, + prHifThreadWakeLock); + + /* + * 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 + * + */ + do { + ret = wait_event_interruptible(prGlueInfo->waitq_hif, + ((prGlueInfo->ulFlag & GLUE_FLAG_HIF_PROCESS) + != 0)); + } while (ret != 0); + + kalTraceBegin("hif_thread"); + +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + if (!KAL_WAKE_LOCK_ACTIVE(prGlueInfo->prAdapter, + prHifThreadWakeLock)) + KAL_WAKE_LOCK(prGlueInfo->prAdapter, + prHifThreadWakeLock); +#endif + if (prAdapter->fgIsFwOwn + && (prGlueInfo->ulFlag == GLUE_FLAG_HIF_FW_OWN)) { + DBGLOG(INIT, INFO, + "Only FW OWN request, but now already done FW OWN\n"); + clear_bit(GLUE_FLAG_HIF_FW_OWN_BIT, + &prGlueInfo->ulFlag); + continue; + } + wlanAcquirePowerControl(prAdapter); + + /* Handle Interrupt */ + fgEnInt = (prGlueInfo->ulFlag | GLUE_FLAG_INT_BIT) != 0; + if (test_and_clear_bit(GLUE_FLAG_INT_BIT, + &prGlueInfo->ulFlag) || + test_and_clear_bit(GLUE_FLAG_DRV_INT_BIT, + &prGlueInfo->ulFlag)) { + kalTraceBegin("INT"); + /* the Wi-Fi interrupt is already disabled in mmc + * thread, so we set the flag only to enable the + * interrupt later + */ + prAdapter->fgIsIntEnable = FALSE; + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT + || kalIsResetting() + ) { + /* Should stop now... skip pending interrupt */ + DBGLOG(INIT, INFO, + "ignore pending interrupt\n"); + } else { + /* DBGLOG(INIT, INFO, ("HIF Interrupt!\n")); */ + prGlueInfo->TaskIsrCnt++; + wlanIST(prAdapter, fgEnInt); + } + kalTraceEnd(); + } + + /* Skip Tx request if SER is operating */ + if ((prAdapter->fgIsFwOwn == FALSE) && + !nicSerIsTxStop(prAdapter)) { + /* TX Commands */ + if (test_and_clear_bit(GLUE_FLAG_HIF_TX_CMD_BIT, + &prGlueInfo->ulFlag)) + TRACE(wlanTxCmdMthread(prAdapter), "TX_CMD"); + + /* Process TX data packet to HIF */ + if (test_and_clear_bit(GLUE_FLAG_HIF_TX_BIT, + &prGlueInfo->ulFlag)) + TRACE(nicTxMsduQueueMthread(prAdapter), "TX"); + } + + /* Read chip status when chip no response */ + if (test_and_clear_bit(GLUE_FLAG_HIF_PRT_HIF_DBG_INFO_BIT, + &prGlueInfo->ulFlag)) + TRACE(halPrintHifDbgInfo(prAdapter), "DBG_INFO"); + + /* Update Tx Quota */ + if (test_and_clear_bit(GLUE_FLAG_UPDATE_WMM_QUOTA_BIT, + &prGlueInfo->ulFlag)) + TRACE(halUpdateTxMaxQuota(prAdapter), "UPDATE_WMM"); + + /* Set FW own */ + if (test_and_clear_bit(GLUE_FLAG_HIF_FW_OWN_BIT, + &prGlueInfo->ulFlag)) + prAdapter->fgWiFiInSleepyState = TRUE; + + kalDumpHifStats(prAdapter); + + /* Release to FW own */ + wlanReleasePowerControl(prAdapter); + kalTraceEnd(); /* hif_thread */ + } + + complete(&prGlueInfo->rHifHaltComp); +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + if (KAL_WAKE_LOCK_ACTIVE(prGlueInfo->prAdapter, + prHifThreadWakeLock)) + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, prHifThreadWakeLock); + KAL_WAKE_LOCK_DESTROY(prGlueInfo->prAdapter, + prHifThreadWakeLock); +#endif + + DBGLOG(INIT, TRACE, "%s:%u stopped!\n", + KAL_GET_CURRENT_THREAD_NAME(), KAL_GET_CURRENT_THREAD_ID()); + +#if CFG_CHIP_RESET_HANG + while (fgIsResetHangState == SER_L0_HANG_RST_HANG) { + kalMsleep(SER_L0_HANG_LOG_TIME_INTERVAL); + DBGLOG(INIT, STATE, "[SER][L0] SQC hang!\n"); + } +#endif + + return 0; +} + +int rx_thread(void *data) +{ + struct net_device *dev = data; + struct GLUE_INFO *prGlueInfo = *((struct GLUE_INFO **) + netdev_priv(dev)); + + struct QUE rTempRxQue; + struct QUE *prTempRxQue = NULL; + struct QUE_ENTRY *prQueueEntry = NULL; + + int ret = 0; +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + KAL_WAKE_LOCK_T *prRxThreadWakeLock; +#endif + uint32_t u4LoopCount; + + /* for spin lock acquire and release */ + KAL_SPIN_LOCK_DECLARATION(); + +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + KAL_WAKE_LOCK_INIT(prGlueInfo->prAdapter, + prRxThreadWakeLock, "WLAN rx_thread"); + KAL_WAKE_LOCK(prGlueInfo->prAdapter, prRxThreadWakeLock); +#endif + + DBGLOG(INIT, INFO, "%s:%u starts running...\n", + KAL_GET_CURRENT_THREAD_NAME(), KAL_GET_CURRENT_THREAD_ID()); + + prGlueInfo->u4RxThreadPid = KAL_GET_CURRENT_THREAD_ID(); + + set_user_nice(current, + prGlueInfo->prAdapter->rWifiVar.cThreadNice); + + prTempRxQue = &rTempRxQue; + + while (TRUE) { + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT + || kalIsResetting() + ) { + DBGLOG(INIT, INFO, "rx_thread should stop now...\n"); + break; + } + + /* Unlock wakelock if rx_thread going to idle */ + if (!(prGlueInfo->ulFlag & GLUE_FLAG_RX_PROCESS)) + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, + prRxThreadWakeLock); + + /* + * sleep on waitqueue if no events occurred. + */ + do { + ret = wait_event_interruptible(prGlueInfo->waitq_rx, + ((prGlueInfo->ulFlag & GLUE_FLAG_RX_PROCESS) != 0)); + } while (ret != 0); + + kalTraceBegin("rx_thread"); + +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + if (!KAL_WAKE_LOCK_ACTIVE(prGlueInfo->prAdapter, + prRxThreadWakeLock)) + KAL_WAKE_LOCK(prGlueInfo->prAdapter, + prRxThreadWakeLock); +#endif + if (test_and_clear_bit(GLUE_FLAG_RX_TO_OS_BIT, + &prGlueInfo->ulFlag)) { + kalTraceBegin("RX_TO_OS"); + u4LoopCount = + prGlueInfo->prAdapter->rWifiVar.u4Rx2OsLoopCount; + + while (u4LoopCount--) { + while (QUEUE_IS_NOT_EMPTY( + &prGlueInfo->prAdapter->rRxQueue)) { + QUEUE_INITIALIZE(prTempRxQue); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, + SPIN_LOCK_RX_TO_OS_QUE); + QUEUE_MOVE_ALL(prTempRxQue, + &prGlueInfo->prAdapter->rRxQueue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, + SPIN_LOCK_RX_TO_OS_QUE); + + while (QUEUE_IS_NOT_EMPTY( + prTempRxQue)) { + QUEUE_REMOVE_HEAD(prTempRxQue, + prQueueEntry, + struct QUE_ENTRY *); + kalRxIndicateOnePkt(prGlueInfo, + (void *) + GLUE_GET_PKT_DESCRIPTOR( + prQueueEntry)); + } + + KAL_WAKE_LOCK_TIMEOUT(prGlueInfo->prAdapter, + prGlueInfo->rTimeoutWakeLock, + MSEC_TO_JIFFIES(prGlueInfo->prAdapter + ->rWifiVar.u4WakeLockRxTimeout)); + } + } + kalTraceEnd(); /* RX_TO_OS */ + } + + kalTraceEnd(); /* rx_thread*/ + } + + complete(&prGlueInfo->rRxHaltComp); +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + if (KAL_WAKE_LOCK_ACTIVE(prGlueInfo->prAdapter, + prRxThreadWakeLock)) + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, prRxThreadWakeLock); + KAL_WAKE_LOCK_DESTROY(prGlueInfo->prAdapter, + prRxThreadWakeLock); +#endif + + DBGLOG(INIT, TRACE, "%s:%u stopped!\n", + KAL_GET_CURRENT_THREAD_NAME(), KAL_GET_CURRENT_THREAD_ID()); + +#if CFG_CHIP_RESET_HANG + while (fgIsResetHangState == SER_L0_HANG_RST_HANG) { + kalMsleep(SER_L0_HANG_LOG_TIME_INTERVAL); + DBGLOG(INIT, STATE, "[SER][L0] SQC hang!\n"); + } +#endif + + return 0; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @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 main_thread + * + * @retval If the function succeeds, the return value is 0. + * Otherwise, an error code is returned. + * + */ +/*----------------------------------------------------------------------------*/ + +int main_thread(void *data) +{ + struct net_device *dev = data; + struct GLUE_INFO *prGlueInfo = *((struct GLUE_INFO **) + netdev_priv(dev)); + struct GL_IO_REQ *prIoReq = NULL; + int ret = 0; + u_int8_t fgNeedHwAccess = FALSE; +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + KAL_WAKE_LOCK_T *prTxThreadWakeLock; +#endif + +#if CFG_SUPPORT_MULTITHREAD + prGlueInfo->u4TxThreadPid = KAL_GET_CURRENT_THREAD_ID(); +#endif + + current->flags |= PF_NOFREEZE; + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prAdapter); + set_user_nice(current, + prGlueInfo->prAdapter->rWifiVar.cThreadNice); + +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + KAL_WAKE_LOCK_INIT(prGlueInfo->prAdapter, + prTxThreadWakeLock, "WLAN main_thread"); + KAL_WAKE_LOCK(prGlueInfo->prAdapter, prTxThreadWakeLock); +#endif + + DBGLOG(INIT, INFO, "%s:%u starts running...\n", + KAL_GET_CURRENT_THREAD_NAME(), KAL_GET_CURRENT_THREAD_ID()); + + rtc_update = jiffies; /* update rtc_update time base */ + + while (TRUE) { +#ifdef UT_TEST_MODE + testThreadBegin(prGlueInfo->prAdapter); +#endif + +#if CFG_ENABLE_WIFI_DIRECT + /*run p2p multicast list work. */ + if (test_and_clear_bit(GLUE_FLAG_SUB_MOD_MULTICAST_BIT, + &prGlueInfo->ulFlag)) + p2pSetMulticastListWorkQueueWrapper(prGlueInfo); +#endif + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT + || kalIsResetting() + ) { + DBGLOG(INIT, INFO, "%s should stop now...\n", + KAL_GET_CURRENT_THREAD_NAME()); + break; + } + + /* Unlock wakelock if main_thread going to idle */ + if (!(prGlueInfo->ulFlag & GLUE_FLAG_MAIN_PROCESS)) + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, + prTxThreadWakeLock); + + /* + * 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 + */ + do { + ret = wait_event_interruptible(prGlueInfo->waitq, + ((prGlueInfo->ulFlag & GLUE_FLAG_MAIN_PROCESS) + != 0)); + } while (ret != 0); +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + if (!KAL_WAKE_LOCK_ACTIVE(prGlueInfo->prAdapter, + prTxThreadWakeLock)) + KAL_WAKE_LOCK(prGlueInfo->prAdapter, + prTxThreadWakeLock); +#endif + kalTraceBegin("main_thread"); + +#if CFG_ENABLE_WIFI_DIRECT + /*run p2p multicast list work. */ + if (test_and_clear_bit(GLUE_FLAG_SUB_MOD_MULTICAST_BIT, + &prGlueInfo->ulFlag)) + p2pSetMulticastListWorkQueueWrapper(prGlueInfo); + + if (test_and_clear_bit(GLUE_FLAG_FRAME_FILTER_BIT, + &prGlueInfo->ulFlag) + && prGlueInfo->prP2PDevInfo) { + /* P2p info will be null after p2p removed. */ + p2pFuncUpdateMgmtFrameRegister(prGlueInfo->prAdapter, + prGlueInfo->prP2PDevInfo->u4OsMgmtFrameFilter); + } +#endif + + if (test_and_clear_bit(GLUE_FLAG_FRAME_FILTER_AIS_BIT, + &prGlueInfo->ulFlag)) { + uint32_t i; + + kalTraceBegin("FRAME_FILTER_AIS"); + for (i = 0; i < KAL_AIS_NUM; i++) { + struct AIS_FSM_INFO *prAisFsmInfo = + (struct AIS_FSM_INFO *)NULL; + + /* printk("prGlueInfo->u4OsMgmtFrameFilter = %x", + * prGlueInfo->u4OsMgmtFrameFilter); + */ + prAisFsmInfo = + aisGetAisFsmInfo(prGlueInfo->prAdapter, + i); + + if (!prAisFsmInfo) + continue; + + prAisFsmInfo->u4AisPacketFilter = + prGlueInfo->u4OsMgmtFrameFilter; + } + kalTraceEnd(); + } + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT + || kalIsResetting() + ) { + DBGLOG(INIT, INFO, "%s should stop now...\n", + KAL_GET_CURRENT_THREAD_NAME()); + break; + } + + fgNeedHwAccess = FALSE; + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN + if (prGlueInfo->fgEnSdioTestPattern == TRUE) { + if (fgNeedHwAccess == FALSE) { + fgNeedHwAccess = TRUE; + + wlanAcquirePowerControl(prGlueInfo->prAdapter); + } + + if (prGlueInfo->fgIsSdioTestInitialized == FALSE) { + /* enable PRBS mode */ + kalDevRegWrite(prGlueInfo, MCR_WTMCR, + 0x00080002); + prGlueInfo->fgIsSdioTestInitialized = TRUE; + } + + if (prGlueInfo->fgSdioReadWriteMode == TRUE) { + /* read test */ + kalDevPortRead(prGlueInfo, MCR_WTMDR, 256, + prGlueInfo->aucSdioTestBuffer, + sizeof(prGlueInfo->aucSdioTestBuffer)); + } else { + /* write test */ + kalDevPortWrite(prGlueInfo, MCR_WTMDR, 172, + prGlueInfo->aucSdioTestBuffer, + sizeof(prGlueInfo->aucSdioTestBuffer)); + } + } +#endif +#if CFG_SUPPORT_MULTITHREAD +#else + + /* Handle Interrupt */ + if (test_and_clear_bit(GLUE_FLAG_INT_BIT, + &prGlueInfo->ulFlag)) { + kalTraceBegin("INT"); + if (fgNeedHwAccess == FALSE) { + fgNeedHwAccess = TRUE; + + wlanAcquirePowerControl(prGlueInfo->prAdapter); + } + + /* the Wi-Fi interrupt is already disabled in mmc + * thread, so we set the flag only to enable the + * interrupt later + */ + prGlueInfo->prAdapter->fgIsIntEnable = FALSE; + /* wlanISR(prGlueInfo->prAdapter, TRUE); */ + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT + || kalIsResetting() + ) { + /* Should stop now... skip pending interrupt */ + DBGLOG(INIT, INFO, + "ignore pending interrupt\n"); + } else { + prGlueInfo->TaskIsrCnt++; + wlanIST(prGlueInfo->prAdapter, true); + } + kalTraceEnd(); + } + + if (test_and_clear_bit(GLUE_FLAG_UPDATE_WMM_QUOTA_BIT, + &prGlueInfo->ulFlag)) + TRACE(halUpdateTxMaxQuota(prGlueInfo->prAdapter), + "UPDATE_WMM"); +#endif + /* transfer ioctl to OID request */ +#ifdef UT_TEST_MODE + testProcessOid(prGlueInfo->prAdapter); +#endif + if (test_and_clear_bit(GLUE_FLAG_OID_BIT, + &prGlueInfo->ulFlag)) { + kalTraceBegin("OID"); + /* get current prIoReq */ + prIoReq = &(prGlueInfo->OidEntry); + if (prIoReq->fgRead == FALSE) { + 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 ONLY if there are waiters */ + if (!completion_done( + &prGlueInfo->rPendComp)) + complete( + &prGlueInfo->rPendComp); + else + DBGLOG(INIT, WARN, + "SKIP multiple OID complete!\n" + ); + } else { + wlanoidTimeoutCheck( + prGlueInfo->prAdapter, + prIoReq->pfnOidHandler); + } + kalTraceEnd(); + } + + /* + * + * if TX request, clear the TXREQ flag. TXREQ set by + * kalSetEvent/GlueSetEvent + * indicates the following requests occur + * + */ + +#ifdef UT_TEST_MODE + testProcessTxReq(prGlueInfo->prAdapter); +#endif + + if (test_and_clear_bit(GLUE_FLAG_TXREQ_BIT, + &prGlueInfo->ulFlag)) + TRACE(kalProcessTxReq(prGlueInfo, &fgNeedHwAccess), + "TXREQ"); + +#if CFG_SUPPORT_MULTITHREAD + /* Process RX */ +#ifdef UT_TEST_MODE + testProcessRFBs(prGlueInfo->prAdapter); +#endif + + if (test_and_clear_bit(GLUE_FLAG_RX_BIT, + &prGlueInfo->ulFlag)) + TRACE(nicRxProcessRFBs(prGlueInfo->prAdapter), "RX"); + + if (test_and_clear_bit(GLUE_FLAG_TX_CMD_DONE_BIT, + &prGlueInfo->ulFlag)) + TRACE(wlanTxCmdDoneMthread(prGlueInfo->prAdapter), + "TX_CMD"); +#endif + + /* 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 CFG_SUPPORT_MULTITHREAD +#else + if (fgNeedHwAccess == TRUE) + wlanReleasePowerControl(prGlueInfo->prAdapter); +#endif + /* handle cnmTimer time out */ +#ifdef UT_TEST_MODE + testTimeoutCheck(prGlueInfo->prAdapter); +#endif + + /* update current throughput */ + kalPerMonUpdate(prGlueInfo->prAdapter); + + if (test_and_clear_bit(GLUE_FLAG_TIMEOUT_BIT, + &prGlueInfo->ulFlag)) + TRACE(wlanTimerTimeoutCheck(prGlueInfo->prAdapter), + "TIMEOUT"); + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN + if (prGlueInfo->fgEnSdioTestPattern == TRUE) + kalSetEvent(prGlueInfo); +#endif +#ifdef UT_TEST_MODE + testThreadEnd(prGlueInfo->prAdapter); +#endif +#if (CFG_SUPPORT_CONNINFRA == 1) + if (test_and_clear_bit(GLUE_FLAG_SER_TIMEOUT_BIT, + &prGlueInfo->ulFlag)) + GL_RESET_TRIGGER(prGlueInfo->prAdapter, + RST_FLAG_DO_CORE_DUMP); +#endif + kalTraceEnd(); /* main_thread */ + } + +#if 0 + if (fgNeedHwAccess == TRUE) + wlanReleasePowerControl(prGlueInfo->prAdapter); +#endif + + /* flush the pending TX packets */ + if (GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum) > 0) + kalFlushPendingTxPackets(prGlueInfo); + + /* flush pending security frames */ + if (GLUE_GET_REF_CNT( + prGlueInfo->i4TxPendingSecurityFrameNum) > 0) + kalClearSecurityFrames(prGlueInfo); + + /* remove pending oid */ + wlanReleasePendingOid(prGlueInfo->prAdapter, 0); + + complete(&prGlueInfo->rHaltComp); +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + if (KAL_WAKE_LOCK_ACTIVE(prGlueInfo->prAdapter, + prTxThreadWakeLock)) + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, prTxThreadWakeLock); + KAL_WAKE_LOCK_DESTROY(prGlueInfo->prAdapter, + prTxThreadWakeLock); +#endif + + DBGLOG(INIT, TRACE, "%s:%u stopped!\n", + KAL_GET_CURRENT_THREAD_NAME(), KAL_GET_CURRENT_THREAD_ID()); + +#if CFG_CHIP_RESET_HANG + while (fgIsResetHangState == SER_L0_HANG_RST_HANG) { + kalMsleep(SER_L0_HANG_LOG_TIME_INTERVAL); + DBGLOG(INIT, STATE, "[SER][L0] SQC hang!\n"); + } +#endif + + 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalIsCardRemoved(IN struct GLUE_INFO *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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalRetrieveNetworkAddress(IN struct GLUE_INFO *prGlueInfo, + IN OUT uint8_t *prMacAddr) +{ + ASSERT(prGlueInfo); + + /* Get MAC address override from wlan feature option */ + prGlueInfo->fgIsMacAddrOverride = + prGlueInfo->prAdapter->rWifiVar.ucMacAddrOverride; + + wlanHwAddrToBin( + prGlueInfo->prAdapter->rWifiVar.aucMacAddrStr, + prGlueInfo->rMacAddrOverride); + + if (prGlueInfo->fgIsMacAddrOverride == FALSE) { + +#ifdef CFG_ENABLE_EFUSE_MAC_ADDR + if (prGlueInfo->prAdapter->fgIsEmbbededMacAddrValid) { + COPY_MAC_ADDR(prMacAddr, + prGlueInfo->prAdapter->rWifiVar.aucMacAddress); + return TRUE; + } else { + return FALSE; + } +#else +#if CFG_TC1_FEATURE + /*LGE_FacReadWifiMacAddr(prMacAddr);*/ + TC1_FAC_NAME(FacReadWifiMacAddr)(prMacAddr); + DBGLOG(INIT, INFO, + "MAC address: " MACSTR, MAC2STR(prMacAddr)); +#else + if (prGlueInfo->fgNvramAvailable == FALSE) { + DBGLOG(INIT, INFO, "glLoadNvram fail\n"); + return FALSE; + } + kalMemCopy(prMacAddr, prGlueInfo->rRegInfo.aucMacAddr, + PARAM_MAC_ADDR_LEN * sizeof(uint8_t)); +#endif + return TRUE; +#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 struct GLUE_INFO + *prGlueInfo) +{ + struct QUE *prTxQue; + struct QUE_ENTRY *prQueueEntry; + void *prPacket; + + ASSERT(prGlueInfo); + + prTxQue = &(prGlueInfo->rTxQueue); + + if (GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum) == 0) + return; + + if (HAL_IS_TX_DIRECT()) { + nicTxDirectClearSkbQ(prGlueInfo->prAdapter); + } else { + GLUE_SPIN_LOCK_DECLARATION(); + + while (TRUE) { + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_REMOVE_HEAD(prTxQue, prQueueEntry, + struct QUE_ENTRY *); + 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 ENUM_PARAM_MEDIA_STATE kalGetMediaStateIndicated( + IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucBssIndex) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->eParamMediaStateIndicated[ucBssIndex]; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to set indicated media state + * + * \param pvGlueInfo Pointer of GLUE Data Structure + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +void kalSetMediaStateIndicated(IN struct GLUE_INFO + *prGlueInfo, IN enum ENUM_PARAM_MEDIA_STATE + eParamMediaStateIndicate, + IN uint8_t ucBssIndex) +{ + ASSERT(prGlueInfo); + ASSERT(ucBssIndex >= 0 && ucBssIndex < KAL_AIS_NUM) + prGlueInfo->eParamMediaStateIndicated[ucBssIndex] = + 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 struct GLUE_INFO *prGlueInfo) +{ + struct QUE *prCmdQue; + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue = &rTempCmdQue; + struct QUE rReturnCmdQue; + struct QUE *prReturnCmdQue = &rReturnCmdQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + QUEUE_INITIALIZE(prReturnCmdQue); + + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + while (prQueueEntry) { + + if (((struct CMD_INFO *) prQueueEntry)->fgIsOid) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + break; + } + QUEUE_INSERT_TAIL(prReturnCmdQue, prQueueEntry); + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(prCmdQue, prReturnCmdQue); + QUEUE_CONCATENATE_QUEUES_HEAD(prCmdQue, prTempCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + if (prCmdInfo) { + DBGLOG(OID, INFO, "Clear pending OID CMD ID[0x%02X] SEQ[%u]\n", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + 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); + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingCmdNum); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct GLUE_INFO *prGlueInfo, + IN struct QUE_ENTRY *prQueueEntry) +{ + struct QUE *prCmdQue; + struct CMD_INFO *prCmdInfo; +#if CFG_DBG_MGT_BUF + struct MEM_TRACK *prMemTrack = NULL; +#endif + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + ASSERT(prQueueEntry); + + prCmdQue = &prGlueInfo->rCmdQueue; + + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + +#if CFG_DBG_MGT_BUF + if (prCmdInfo->pucInfoBuffer && + !IS_FROM_BUF(prGlueInfo->prAdapter, + prCmdInfo->pucInfoBuffer)) { + prMemTrack = (struct MEM_TRACK *) + ((uint8_t *)prCmdInfo->pucInfoBuffer - + sizeof(struct MEM_TRACK)); + prMemTrack->u2CmdIdAndWhere = 0; + prMemTrack->u2CmdIdAndWhere |= prCmdInfo->ucCID; + } +#endif + + DBGLOG_LIMITED(INIT, TRACE, + "EN-Q CMD TYPE[%u] ID[0x%02X] SEQ[%u] to CMD Q\n", + prCmdInfo->eCmdType, prCmdInfo->ucCID, + prCmdInfo->ucCmdSeqNum); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingCmdNum); + 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 struct GLUE_INFO *prGlueInfo, + IN struct EVENT_ASSOC_INFO *prAssocInfo) +{ + /* to do */ +} + +/*----------------------------------------------------------------------------*/ +/*! + * * @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 struct GLUE_INFO + *prGlueInfo, IN void *pvPacket, IN uint32_t rStatus) +{ + ASSERT(pvPacket); + + /* dev_kfree_skb((struct sk_buff *) pvPacket); */ + kalSendCompleteAndAwakeQueue(prGlueInfo, pvPacket); + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum); +} + +uint32_t kalGetTxPendingFrameCount(IN struct GLUE_INFO + *prGlueInfo) +{ + ASSERT(prGlueInfo); + + return (uint32_t) (GLUE_GET_REF_CNT( + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t kalGetTxPendingCmdCount(IN struct GLUE_INFO + *prGlueInfo) +{ + ASSERT(prGlueInfo); + + return (uint32_t)GLUE_GET_REF_CNT( + prGlueInfo->i4TxPendingCmdNum); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct GLUE_INFO *prGlueInfo, + IN void *prTimerHandler) +{ + + ASSERT(prGlueInfo); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) + timer_setup(&(prGlueInfo->tickfn), prTimerHandler, 0); +#else + init_timer(&(prGlueInfo->tickfn)); + prGlueInfo->tickfn.function = prTimerHandler; + prGlueInfo->tickfn.data = (unsigned long)prGlueInfo; +#endif +} + +/* 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. + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalSetTimer(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Interval) +{ + ASSERT(prGlueInfo); + + if (HAL_IS_RX_DIRECT(prGlueInfo->prAdapter)) { + mod_timer(&prGlueInfo->tickfn, + jiffies + u4Interval * HZ / MSEC_PER_SEC); + } else { + 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalCancelTimer(IN struct GLUE_INFO *prGlueInfo) +{ + ASSERT(prGlueInfo); + + clear_bit(GLUE_FLAG_TIMEOUT_BIT, &prGlueInfo->ulFlag); + + if (del_timer_sync(&(prGlueInfo->tickfn)) >= 0) + return TRUE; + else + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is a callback function for scanning done + * + * \param[in] prGlueInfo Pointer to GLUE Data Structure + * + * \retval none + * + */ +/*----------------------------------------------------------------------------*/ +void kalScanDone(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucBssIndex, + IN uint32_t status) +{ + uint8_t fgAborted = (status != WLAN_STATUS_SUCCESS) ? TRUE : FALSE; + ASSERT(prGlueInfo); + + if (IS_BSS_INDEX_AIS(prGlueInfo->prAdapter, ucBssIndex)) + scanLogEssResult(prGlueInfo->prAdapter); + + scanReportBss2Cfg80211(prGlueInfo->prAdapter, + BSS_TYPE_INFRASTRUCTURE, NULL); + + /* check for system configuration for generating error message on scan + * list + */ + wlanCheckSystemConfiguration(prGlueInfo->prAdapter); + + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_SCAN_COMPLETE, + &fgAborted, sizeof(fgAborted), ucBssIndex); +} + +#if CFG_SUPPORT_SCAN_CACHE_RESULT +/*----------------------------------------------------------------------------*/ +/*! + * @brief update timestamp information of bss cache in kernel + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @return status 0 if success, error code otherwise + */ +/*----------------------------------------------------------------------------*/ +uint8_t kalUpdateBssTimestamp(IN struct GLUE_INFO *prGlueInfo) +{ + struct wiphy *wiphy; + struct cfg80211_registered_device *rdev; + struct cfg80211_internal_bss *bss = NULL; + struct cfg80211_bss_ies *ies; + uint64_t new_timestamp = kalGetBootTime(); + + ASSERT(prGlueInfo); + wiphy = priv_to_wiphy(prGlueInfo); + if (!wiphy) { + log_dbg(REQ, ERROR, "wiphy is null\n"); + return 1; + } + rdev = container_of(wiphy, struct cfg80211_registered_device, wiphy); + + log_dbg(REQ, INFO, "Update scan timestamp: %llu (%llu)\n", + new_timestamp, le64_to_cpu(new_timestamp)); + + /* add 1 ms to prevent scan time too short */ + new_timestamp += 1000; + + spin_lock_bh(&rdev->bss_lock); + list_for_each_entry(bss, &rdev->bss_list, list) { + ies = *(struct cfg80211_bss_ies **) + (((size_t)&(bss->pub)) + offsetof(struct cfg80211_bss, ies)); + if (rcu_access_pointer(bss->pub.ies) == ies) { + ies->tsf = le64_to_cpu(new_timestamp); + } else { + log_limited_dbg(REQ, WARN, "Update tsf fail. bss->pub.ies=%p ies=%p\n", + bss->pub.ies, ies); + } + } + spin_unlock_bh(&rdev->bss_lock); + + return 0; +} +#endif /* CFG_SUPPORT_SCAN_CACHE_RESULT */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to generate a random number + * + * \param none + * + * \retval UINT_32 + */ +/*----------------------------------------------------------------------------*/ +uint32_t kalRandomNumber(void) +{ + uint32_t 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) + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE +void kalTimeoutHandler(struct timer_list *timer) +#else +void kalTimeoutHandler(unsigned long arg) +#endif +{ +#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE + struct GLUE_INFO *prGlueInfo = + from_timer(prGlueInfo, timer, tickfn); +#else + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)arg; +#endif + + ASSERT(prGlueInfo); + + /* Notify tx thread for timeout event */ + set_bit(GLUE_FLAG_TIMEOUT_BIT, &prGlueInfo->ulFlag); + wake_up_interruptible(&prGlueInfo->waitq); + +} + +void kalSetEvent(struct GLUE_INFO *pr) +{ + set_bit(GLUE_FLAG_TXREQ_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq); +} + +void kalSetSerTimeoutEvent(struct GLUE_INFO *pr) +{ + set_bit(GLUE_FLAG_SER_TIMEOUT_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq); +} + +void kalSetIntEvent(struct GLUE_INFO *pr) +{ + KAL_WAKE_LOCK(pr->prAdapter, pr->rIntrWakeLock); + + set_bit(GLUE_FLAG_INT_BIT, &pr->ulFlag); + + /* when we got interrupt, we wake up servie thread */ +#if CFG_SUPPORT_MULTITHREAD + wake_up_interruptible(&pr->waitq_hif); +#else + wake_up_interruptible(&pr->waitq); +#endif +} + +void kalSetDrvIntEvent(struct GLUE_INFO *pr) +{ + KAL_WAKE_LOCK(pr->prAdapter, pr->rIntrWakeLock); + + set_bit(GLUE_FLAG_DRV_INT_BIT, &pr->ulFlag); + + /* when we got interrupt, we wake up servie thread */ +#if CFG_SUPPORT_MULTITHREAD + wake_up_interruptible(&pr->waitq_hif); +#else + wake_up_interruptible(&pr->waitq); +#endif +} + +void kalSetWmmUpdateEvent(struct GLUE_INFO *pr) +{ + set_bit(GLUE_FLAG_UPDATE_WMM_QUOTA_BIT, &pr->ulFlag); +#if CFG_SUPPORT_MULTITHREAD + wake_up_interruptible(&pr->waitq_hif); +#endif +} + +void kalSetHifDbgEvent(struct GLUE_INFO *pr) +{ + set_bit(GLUE_FLAG_HIF_PRT_HIF_DBG_INFO_BIT, &(pr->ulFlag)); +#if CFG_SUPPORT_MULTITHREAD + wake_up_interruptible(&pr->waitq_hif); +#endif +} + +#if CFG_SUPPORT_MULTITHREAD +void kalSetTxEvent2Hif(struct GLUE_INFO *pr) +{ + if (!pr->hif_thread) + return; + + KAL_WAKE_LOCK_TIMEOUT(pr->prAdapter, pr->rTimeoutWakeLock, + MSEC_TO_JIFFIES( + pr->prAdapter->rWifiVar.u4WakeLockThreadWakeup)); + + set_bit(GLUE_FLAG_HIF_TX_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq_hif); +} + +void kalSetFwOwnEvent2Hif(struct GLUE_INFO *pr) +{ + if (!pr->hif_thread) + return; + + KAL_WAKE_LOCK_TIMEOUT(pr->prAdapter, pr->rTimeoutWakeLock, + MSEC_TO_JIFFIES( + pr->prAdapter->rWifiVar.u4WakeLockThreadWakeup)); + + set_bit(GLUE_FLAG_HIF_FW_OWN_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq_hif); +} + +void kalSetTxEvent2Rx(struct GLUE_INFO *pr) +{ + if (!pr->rx_thread) + return; + + KAL_WAKE_LOCK_TIMEOUT(pr->prAdapter, pr->rTimeoutWakeLock, + MSEC_TO_JIFFIES( + pr->prAdapter->rWifiVar.u4WakeLockThreadWakeup)); + + set_bit(GLUE_FLAG_RX_TO_OS_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq_rx); +} + +void kalSetTxCmdEvent2Hif(struct GLUE_INFO *pr) +{ + if (!pr->hif_thread) + return; + + KAL_WAKE_LOCK_TIMEOUT(pr->prAdapter, pr->rTimeoutWakeLock, + MSEC_TO_JIFFIES( + pr->prAdapter->rWifiVar.u4WakeLockThreadWakeup)); + + set_bit(GLUE_FLAG_HIF_TX_CMD_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq_hif); +} + +void kalSetTxCmdDoneEvent(struct GLUE_INFO *pr) +{ + /* do we need wake lock here */ + set_bit(GLUE_FLAG_TX_CMD_DONE_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq); +} + +void kalSetRxProcessEvent(struct GLUE_INFO *pr) +{ + /* do we need wake lock here ? */ + set_bit(GLUE_FLAG_RX_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq); +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * \brief to check if configuration file (NVRAM/Registry) exists + * + * \param[in] + * prGlueInfo + * + * \return + * TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalIsConfigurationExist(IN struct GLUE_INFO + *prGlueInfo) +{ +#if !defined(CONFIG_X86) + ASSERT(prGlueInfo); + + return prGlueInfo->fgNvramAvailable; +#else + /* there is no configuration data for x86-linux */ + /*return FALSE;*/ + + + /*Modify for Linux PC support NVRAM Setting*/ + return prGlueInfo->fgNvramAvailable; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief to retrieve Registry information + * + * \param[in] + * prGlueInfo + * + * \return + * Pointer of REG_INFO_T + */ +/*----------------------------------------------------------------------------*/ +struct REG_INFO *kalGetConfiguration(IN struct GLUE_INFO + *prGlueInfo) +{ + ASSERT(prGlueInfo); + + return &(prGlueInfo->rRegInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief update RSSI and LinkQuality to GLUE layer + * + * \param[in] + * prGlueInfo + * eNetTypeIdx + * cRssi + * cLinkQuality + * + * \return + * None + */ +/*----------------------------------------------------------------------------*/ +void +kalUpdateRSSI(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucBssIndex, + IN int8_t cRssi, IN int8_t cLinkQuality) +{ + struct iw_statistics *pStats = (struct iw_statistics *)NULL; + struct ADAPTER *prAdapter = NULL; + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + + ASSERT(prGlueInfo); + prAdapter = prGlueInfo->prAdapter; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (IS_BSS_AIS(prBssInfo)) + pStats = (struct iw_statistics *) + (&(prGlueInfo->rIwStats[ucBssIndex])); +#if CFG_ENABLE_WIFI_DIRECT +#if CFG_SUPPORT_P2P_RSSI_QUERY + else if (IS_BSS_P2P(prBssInfo)) + pStats = (struct iw_statistics *) + (&(prGlueInfo->rP2pIwStats)); +#endif +#endif + 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; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Pre-allocate I/O buffer + * + * \param[in] + * none + * + * \return + * TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalInitIOBuffer(u_int8_t is_pre_alloc) +{ + uint32_t u4Size; + + /* not pre-allocation for all memory usage */ + if (!is_pre_alloc) { + pvIoBuffer = NULL; + return FALSE; + } + + /* pre-allocation for all memory usage */ + if (HIF_TX_COALESCING_BUFFER_SIZE > + HIF_RX_COALESCING_BUFFER_SIZE) + u4Size = HIF_TX_COALESCING_BUFFER_SIZE; + else + u4Size = HIF_RX_COALESCING_BUFFER_SIZE; + + u4Size += HIF_EXTRA_IO_BUFFER_SIZE; + + 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) +{ + kfree(pvIoBuffer); + + pvIoBuffer = (void *) NULL; + pvIoBufferSize = 0; + pvIoBufferUsage = 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Dispatch pre-allocated I/O buffer + * + * \param[in] + * u4AllocSize + * + * \return + * PVOID for pointer of pre-allocated I/O buffer + */ +/*----------------------------------------------------------------------------*/ +void *kalAllocateIOBuffer(IN uint32_t u4AllocSize) +{ + void *ret = (void *) NULL; + + if (pvIoBuffer) { + if (u4AllocSize <= (pvIoBufferSize - pvIoBufferUsage)) { + ret = (void *) + &(((uint8_t *) (pvIoBuffer))[pvIoBufferUsage]); + pvIoBufferUsage += u4AllocSize; + } + } else { + /* fault tolerance */ + ret = (void *) kalMemAlloc(u4AllocSize, PHY_MEM_TYPE); + } + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Release all dispatched I/O buffer + * + * \param[in] + * none + * + * \return + * none + */ +/*----------------------------------------------------------------------------*/ +void kalReleaseIOBuffer(IN void *pvAddr, IN uint32_t 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 struct GLUE_INFO *prGlueInfo, + IN enum ENUM_BAND eSpecificBand, + IN uint8_t ucMaxChannelNum, IN uint8_t *pucNumOfChannel, + IN struct RF_CHANNEL_INFO *paucChannelList) +{ + rlmDomainGetChnlList(prGlueInfo->prAdapter, eSpecificBand, + FALSE, + ucMaxChannelNum, pucNumOfChannel, paucChannelList); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] prAdapter Pointer of ADAPTER_T + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalIsAPmode(IN struct GLUE_INFO *prGlueInfo) +{ +#if 0 /* Marked for MT6630 (New ucBssIndex) */ +#if CFG_ENABLE_WIFI_DIRECT + if (IS_NET_ACTIVE(prGlueInfo->prAdapter, + NETWORK_TYPE_P2P_INDEX) && + p2pFuncIsAPMode( + prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo)) + return TRUE; +#endif +#endif + + return FALSE; +} + +#if CFG_SUPPORT_802_11W +/*----------------------------------------------------------------------------*/ +/*! + * \brief to check if the MFP is DISABLD/OPTIONAL/REQUIRED + * + * \param[in] + * prGlueInfo + * + * \return + * RSN_AUTH_MFP_DISABLED + * RSN_AUTH_MFP_OPTIONAL + * RSN_AUTH_MFP_DISABLED + */ +/*----------------------------------------------------------------------------*/ +uint32_t kalGetMfpSetting(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucBssIndex) +{ + uint32_t u4RsnMfp = RSN_AUTH_MFP_DISABLED; + struct GL_WPA_INFO *prWpaInfo; + + prWpaInfo = aisGetWpaInfo(prGlueInfo->prAdapter, + ucBssIndex); + + ASSERT(prGlueInfo); + + switch (prWpaInfo->u4Mfp) { + case IW_AUTH_MFP_DISABLED: + u4RsnMfp = RSN_AUTH_MFP_DISABLED; + break; + case IW_AUTH_MFP_OPTIONAL: + u4RsnMfp = RSN_AUTH_MFP_OPTIONAL; + break; + case IW_AUTH_MFP_REQUIRED: + u4RsnMfp = RSN_AUTH_MFP_REQUIRED; + break; + default: + u4RsnMfp = RSN_AUTH_MFP_DISABLED; + break; + } + + return u4RsnMfp; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief to check if the RSN IE CAP setting from supplicant + * + * \param[in] + * prGlueInfo + * + * \return + * TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +uint8_t kalGetRsnIeMfpCap(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucBssIndex) +{ + struct GL_WPA_INFO *prWpaInfo; + + ASSERT(prGlueInfo); + + prWpaInfo = aisGetWpaInfo(prGlueInfo->prAdapter, + ucBssIndex); + + return prWpaInfo->ucRSNMfpCap; +} +#endif + +struct file *kalFileOpen(const char *filePath, int openModes, + int createModes) +{ + struct file *prFile = NULL; + mm_segment_t oldFs; + long errval = 0; + + oldFs = get_fs(); + set_fs(get_ds()); + prFile = filp_open(filePath, openModes, createModes); + set_fs(oldFs); + if (IS_ERR(prFile)) { + errval = PTR_ERR(prFile); + DBGLOG(INIT, TRACE, "kalFileOpen() fail: %ld\n", errval); + return NULL; + } + return prFile; +} + +void kalFileClose(struct file *prFile) +{ + filp_close(prFile, NULL); +} + +uint32_t kalFileRead(struct file *prFile, + unsigned long long pos, unsigned char *buffer, + unsigned int len) +{ + mm_segment_t oldFs; + int retval; + + oldFs = get_fs(); + set_fs(get_ds()); + +#if KERNEL_VERSION(4, 13, 0) <= CFG80211_VERSION_CODE + retval = kernel_read(prFile, buffer, len, &pos); +#else + retval = vfs_read(prFile, buffer, len, &pos); +#endif + + set_fs(oldFs); + return retval; +} + +uint32_t kalFileWrite(struct file *prFile, + unsigned long long pos, unsigned char *buffer, + unsigned int len) +{ + mm_segment_t oldFs; + int retval; + + oldFs = get_fs(); + set_fs(get_ds()); + +#if KERNEL_VERSION(4, 13, 0) <= CFG80211_VERSION_CODE + retval = kernel_write(prFile, buffer, len, &pos); +#else + retval = vfs_write(prFile, buffer, len, &pos); +#endif + + set_fs(oldFs); + return retval; +} + +uint32_t kalWriteToFile(const uint8_t *pucPath, + u_int8_t fgDoAppend, uint8_t *pucData, uint32_t u4Size) +{ + struct file *file = NULL; + int32_t ret = -1; + uint32_t u4Flags = 0; + + if (fgDoAppend) + u4Flags = O_APPEND; + + file = kalFileOpen(pucPath, O_WRONLY | O_CREAT | u4Flags, 0700); + if (file != NULL) { + kalFileWrite(file, 0, pucData, u4Size); + kalFileClose(file); + ret = 0; + } + return ret; +} + +int32_t kalReadToFile(const uint8_t *pucPath, + uint8_t *pucData, uint32_t u4Size, uint32_t *pu4ReadSize) +{ + struct file *file = NULL; + int32_t ret = -1; + uint32_t u4ReadSize = 0; + + DBGLOG(INIT, TRACE, "kalReadToFile() path %s\n", pucPath); + + file = kalFileOpen(pucPath, O_RDONLY, 0); + + if ((file != NULL) && !IS_ERR(file)) { + u4ReadSize = kalFileRead(file, 0, pucData, u4Size); + kalFileClose(file); + if (pu4ReadSize) + *pu4ReadSize = u4ReadSize; + ret = 0; + } + return ret; +} + +uint32_t kalCheckPath(const uint8_t *pucPath) +{ + struct file *file = NULL; + uint32_t u4Flags = 0; + + file = kalFileOpen(pucPath, O_WRONLY | O_CREAT | u4Flags, 0700); + if (!file) + return -1; + + kalFileClose(file); + return 1; +} + +uint32_t kalTrunkPath(const uint8_t *pucPath) +{ + struct file *file = NULL; + uint32_t u4Flags = O_TRUNC; + + file = kalFileOpen(pucPath, O_WRONLY | O_CREAT | u4Flags, 0700); + if (!file) + return -1; + + kalFileClose(file); + return 1; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief read request firmware file binary to pucData + * + * \param[in] pucPath file name + * \param[out] pucData Request file output buffer + * \param[in] u4Size read size + * \param[out] pu4ReadSize real read size + * \param[in] dev + * + * \return + * 0 success + * >0 fail + */ +/*----------------------------------------------------------------------------*/ +int32_t kalRequestFirmware(const uint8_t *pucPath, + uint8_t *pucData, uint32_t u4Size, + uint32_t *pu4ReadSize, struct device *dev) +{ + const struct firmware *fw; + int ret = 0; + + /* + * Driver support request_firmware() to get files + * Android path: "/etc/firmware", "/vendor/firmware", "/firmware/image" + * Linux path: "/lib/firmware", "/lib/firmware/update" + */ + ret = _kalRequestFirmware(&fw, pucPath, dev); + + if (ret != 0) { + DBGLOG(INIT, TRACE, "kalRequestFirmware %s Fail, errno[%d]!!\n", + pucPath, ret); + pucData = NULL; + *pu4ReadSize = 0; + return ret; + } + + DBGLOG(INIT, INFO, "kalRequestFirmware(): %s OK\n", + pucPath); + + if (fw->size < u4Size) + u4Size = fw->size; + + memcpy(pucData, fw->data, u4Size); + if (pu4ReadSize) + *pu4ReadSize = u4Size; + + release_firmware(fw); + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To indicate BSS-INFO to NL80211 as scanning result + * + * \param[in] + * prGlueInfo + * pucBeaconProbeResp + * u4FrameLen + * + * + * + * \return + * none + */ +/*----------------------------------------------------------------------------*/ +void +kalIndicateBssInfo(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucBeaconProbeResp, + IN uint32_t u4FrameLen, IN uint8_t ucChannelNum, + IN int32_t 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, + KAL_BAND_2GHZ)); + } else { + prChannel = ieee80211_get_channel(wiphy, + ieee80211_channel_to_frequency(ucChannelNum, + KAL_BAND_5GHZ)); + } + + if (prChannel != NULL + && prGlueInfo->fgIsRegistered == TRUE) { + struct cfg80211_bss *bss; + struct ieee80211_mgmt *prMgmtFrame = (struct ieee80211_mgmt + *)pucBeaconProbeResp; + char *pucBssSubType = + ieee80211_is_beacon(prMgmtFrame->frame_control) ? + "beacon" : "probe_resp"; + +#if CFG_SUPPORT_TSF_USING_BOOTTIME + prMgmtFrame->u.beacon.timestamp = kalGetBootTime(); +#endif + + kalScanResultLog(prGlueInfo->prAdapter, + (struct ieee80211_mgmt *)pucBeaconProbeResp); + + log_dbg(SCN, TRACE, "cfg80211_inform_bss_frame %s bss=" MACSTR + " sn=%u ch=%u rssi=%d len=%u tsf=%llu\n", pucBssSubType, + MAC2STR(prMgmtFrame->bssid), prMgmtFrame->seq_ctrl, + ucChannelNum, i4SignalStrength, u4FrameLen, + prMgmtFrame->u.beacon.timestamp); + + /* indicate to NL80211 subsystem */ + bss = cfg80211_inform_bss_frame(wiphy, prChannel, + (struct ieee80211_mgmt *)pucBeaconProbeResp, + u4FrameLen, i4SignalStrength * 100, GFP_KERNEL); + + if (!bss) { + /* ToDo:: DBGLOG */ + DBGLOG(REQ, WARN, + "cfg80211_inform_bss_frame() returned with NULL\n"); + } else + cfg80211_put_bss(wiphy, bss); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To indicate channel ready + * + * \param[in] + * prGlueInfo + * + * \return + * none + */ +/*----------------------------------------------------------------------------*/ +void +kalReadyOnChannel(IN struct GLUE_INFO *prGlueInfo, + IN uint64_t u8Cookie, + IN enum ENUM_BAND eBand, IN enum ENUM_CHNL_EXT eSco, + IN uint8_t ucChannelNum, IN uint32_t u4DurationMs, + IN uint8_t ucBssIndex) +{ + struct ieee80211_channel *prChannel = NULL; + enum nl80211_channel_type rChannelType; + + /* ucChannelNum = wlanGetChannelNumberByNetwork(prGlueInfo->prAdapter, + * NETWORK_TYPE_AIS_INDEX); + */ + + if (prGlueInfo->fgIsRegistered == TRUE) { + struct net_device *prDevHandler = + wlanGetNetDev(prGlueInfo, ucBssIndex); + + if (ucChannelNum <= 14) { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, + KAL_BAND_2GHZ)); + } else { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, + KAL_BAND_5GHZ)); + } + + switch (eSco) { + case CHNL_EXT_SCN: + rChannelType = NL80211_CHAN_NO_HT; + break; + + case CHNL_EXT_SCA: + rChannelType = NL80211_CHAN_HT40MINUS; + break; + + case CHNL_EXT_SCB: + rChannelType = NL80211_CHAN_HT40PLUS; + break; + + case CHNL_EXT_RES: + default: + rChannelType = NL80211_CHAN_HT20; + break; + } + + if (!prChannel) { + DBGLOG(AIS, ERROR, "prChannel is NULL, return!"); + return; + } + + cfg80211_ready_on_channel( + prDevHandler->ieee80211_ptr, + u8Cookie, prChannel, u4DurationMs, GFP_KERNEL); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To indicate channel expiration + * + * \param[in] + * prGlueInfo + * + * \return + * none + */ +/*----------------------------------------------------------------------------*/ +void +kalRemainOnChannelExpired(IN struct GLUE_INFO *prGlueInfo, + IN uint64_t u8Cookie, IN enum ENUM_BAND eBand, + IN enum ENUM_CHNL_EXT eSco, IN uint8_t ucChannelNum, + IN uint8_t ucBssIndex) +{ + struct ieee80211_channel *prChannel = NULL; + enum nl80211_channel_type rChannelType; + + ucChannelNum = + wlanGetChannelNumberByNetwork(prGlueInfo->prAdapter, + ucBssIndex); + + if (prGlueInfo->fgIsRegistered == TRUE) { + struct net_device *prDevHandler = + wlanGetNetDev(prGlueInfo, ucBssIndex); + + if (ucChannelNum <= 14) { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, + KAL_BAND_2GHZ)); + } else { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, + KAL_BAND_5GHZ)); + } + + switch (eSco) { + case CHNL_EXT_SCN: + rChannelType = NL80211_CHAN_NO_HT; + break; + + case CHNL_EXT_SCA: + rChannelType = NL80211_CHAN_HT40MINUS; + break; + + case CHNL_EXT_SCB: + rChannelType = NL80211_CHAN_HT40PLUS; + break; + + case CHNL_EXT_RES: + default: + rChannelType = NL80211_CHAN_HT20; + break; + } + + if (!prChannel) { + DBGLOG(AIS, ERROR, "prChannel is NULL, return!"); + return; + } + + cfg80211_remain_on_channel_expired( + prDevHandler->ieee80211_ptr, + u8Cookie, prChannel, GFP_KERNEL); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To indicate Mgmt tx status + * + * \param[in] + * prGlueInfo + * + * \return + * none + */ +/*----------------------------------------------------------------------------*/ +void +kalIndicateMgmtTxStatus(IN struct GLUE_INFO *prGlueInfo, + IN uint64_t u8Cookie, IN u_int8_t fgIsAck, + IN uint8_t *pucFrameBuf, IN uint32_t u4FrameLen, + IN uint8_t ucBssIndex) +{ + + do { + struct net_device *prDevHandler; + + if ((prGlueInfo == NULL) + || (pucFrameBuf == NULL) + || (u4FrameLen == 0)) { + DBGLOG(AIS, TRACE, + "Unexpected pointer PARAM. 0x%lx, 0x%lx, %d.", + prGlueInfo, pucFrameBuf, u4FrameLen); + ASSERT(FALSE); + break; + } + + prDevHandler = + wlanGetNetDev(prGlueInfo, ucBssIndex); + + cfg80211_mgmt_tx_status( + prDevHandler->ieee80211_ptr, + u8Cookie, pucFrameBuf, u4FrameLen, fgIsAck, GFP_KERNEL); + + } while (FALSE); + +} /* kalIndicateMgmtTxStatus */ + +void kalIndicateRxMgmtFrame(IN struct GLUE_INFO *prGlueInfo, + IN struct SW_RFB *prSwRfb, + IN uint8_t ucBssIndex) +{ + int32_t i4Freq = 0; + uint8_t ucChnlNum = 0; + + do { + struct net_device *prDevHandler; + + if ((prGlueInfo == NULL) || (prSwRfb == NULL)) { + ASSERT(FALSE); + break; + } + + ucChnlNum = prSwRfb->ucChnlNum; + + i4Freq = nicChannelNum2Freq(ucChnlNum) / 1000; + + if (!prGlueInfo->fgIsRegistered) { + DBGLOG(AIS, WARN, + "Net dev is not ready!\n"); + break; + } + + if (prGlueInfo->u4OsMgmtFrameFilter == 0) { + DBGLOG(AIS, WARN, + "The cfg80211 hasn't do mgmt register!\n"); + break; + } + + prDevHandler = + wlanGetNetDev(prGlueInfo, ucBssIndex); + +#if (KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE) + cfg80211_rx_mgmt(prDevHandler->ieee80211_ptr, + i4Freq, /* in MHz */ + RCPI_TO_dBm((uint8_t) nicRxGetRcpiValueFromRxv( + prGlueInfo->prAdapter, + RCPI_MODE_MAX, prSwRfb)), + prSwRfb->pvHeader, prSwRfb->u2PacketLen, + NL80211_RXMGMT_FLAG_ANSWERED); + +#elif (KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE) + cfg80211_rx_mgmt(prDevHandler->ieee80211_ptr, + i4Freq, /* in MHz */ + RCPI_TO_dBm((uint8_t) + nicRxGetRcpiValueFromRxv( + prGlueInfo->prAdapter, RCPI_MODE_WF0, prSwRfb)), + prSwRfb->pvHeader, prSwRfb->u2PacketLen, + NL80211_RXMGMT_FLAG_ANSWERED, + GFP_ATOMIC); +#else + cfg80211_rx_mgmt(prDevHandler->ieee80211_ptr, + i4Freq, /* in MHz */ + RCPI_TO_dBm((uint8_t) + nicRxGetRcpiValueFromRxv( + prGlueInfo->prAdapter, RCPI_MODE_WF0, prSwRfb)), + prSwRfb->pvHeader, prSwRfb->u2PacketLen, + GFP_ATOMIC); +#endif + + } while (FALSE); + +} /* kalIndicateRxMgmtFrame */ + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN +/*----------------------------------------------------------------------------*/ +/*! + * \brief To configure SDIO test pattern mode + * + * \param[in] + * prGlueInfo + * fgEn + * fgRead + * + * \return + * TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalSetSdioTestPattern(IN struct GLUE_INFO + *prGlueInfo, IN u_int8_t fgEn, IN u_int8_t fgRead) +{ + const uint8_t aucPattern[] = { + 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, + 0xaa, 0x55, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x80, + 0x80, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, + 0x40, 0x40, 0x40, 0xbf, 0x40, 0x40, 0x40, 0xbf, + 0xbf, 0xbf, 0x40, 0xbf, 0xbf, 0xbf, 0x20, 0x20, + 0x20, 0xdf, 0x20, 0x20, 0x20, 0xdf, 0xdf, 0xdf, + 0x20, 0xdf, 0xdf, 0xdf, 0x10, 0x10, 0x10, 0xef, + 0x10, 0x10, 0x10, 0xef, 0xef, 0xef, 0x10, 0xef, + 0xef, 0xef, 0x08, 0x08, 0x08, 0xf7, 0x08, 0x08, + 0x08, 0xf7, 0xf7, 0xf7, 0x08, 0xf7, 0xf7, 0xf7, + 0x04, 0x04, 0x04, 0xfb, 0x04, 0x04, 0x04, 0xfb, + 0xfb, 0xfb, 0x04, 0xfb, 0xfb, 0xfb, 0x02, 0x02, + 0x02, 0xfd, 0x02, 0x02, 0x02, 0xfd, 0xfd, 0xfd, + 0x02, 0xfd, 0xfd, 0xfd, 0x01, 0x01, 0x01, 0xfe, + 0x01, 0x01, 0x01, 0xfe, 0xfe, 0xfe, 0x01, 0xfe, + 0xfe, 0xfe, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff + }; + uint32_t i; + + ASSERT(prGlueInfo); + + /* access to MCR_WTMCR to engage PRBS mode */ + prGlueInfo->fgEnSdioTestPattern = fgEn; + prGlueInfo->fgSdioReadWriteMode = fgRead; + + if (fgRead == FALSE) { + /* fill buffer for data to be written */ + for (i = 0; i < sizeof(aucPattern); i++) + prGlueInfo->aucSdioTestBuffer[i] = aucPattern[i]; + } + + return TRUE; +} +#endif + +#if (CFG_MET_PACKET_TRACE_SUPPORT == 1) +#define PROC_MET_PROF_CTRL "met_ctrl" +#define PROC_MET_PROF_PORT "met_port" + +struct proc_dir_entry *pMetProcDir; +void *pMetGlobalData; + +#endif +/*----------------------------------------------------------------------------*/ +/*! + * \brief To indicate scheduled scan results are avilable + * + * \param[in] + * prGlueInfo + * + * \return + * None + */ +/*----------------------------------------------------------------------------*/ +void kalSchedScanResults(IN struct GLUE_INFO *prGlueInfo) +{ + ASSERT(prGlueInfo); + scanReportBss2Cfg80211(prGlueInfo->prAdapter, + BSS_TYPE_INFRASTRUCTURE, NULL); + + scanlog_dbg(LOG_SCHED_SCAN_DONE_D2K, INFO, "Call cfg80211_sched_scan_results\n"); +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE + cfg80211_sched_scan_results(priv_to_wiphy(prGlueInfo), 0); +#else + cfg80211_sched_scan_results(priv_to_wiphy(prGlueInfo)); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To indicate scheduled scan has been stopped + * + * \param[in] + * prGlueInfo + * + * \return + * None + */ +/*----------------------------------------------------------------------------*/ +void kalSchedScanStopped(IN struct GLUE_INFO *prGlueInfo, + u_int8_t fgDriverTriggerd) +{ + /* DBGLOG(SCN, INFO, ("-->kalSchedScanStopped\n" )); */ + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + +#if 1 + /* 1. reset first for newly incoming request */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if (prGlueInfo->prSchedScanRequest != NULL) + prGlueInfo->prSchedScanRequest = NULL; + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); +#endif + DBGLOG(SCN, INFO, "Driver triggerd %d\n", fgDriverTriggerd); + + /* 2. indication to cfg80211 */ + /* 20150205 change cfg80211_sched_scan_stopped to work queue to use K + * thread to send event instead of Tx thread + * due to sched_scan_mtx dead lock issue by Tx thread serves oid cmds + * and send event in the same time + */ + if (fgDriverTriggerd) { + DBGLOG(SCN, INFO, "start work queue to send event\n"); + schedule_delayed_work(&sched_workq, 0); + DBGLOG(SCN, INFO, "main_thread return from %s\n", __func__); + } +} + +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG +/*----------------------------------------------------------------------------*/ +/*! + * \brief To check if device if wake up by wlan + * + * \param[in] + * prAdapter + * + * \return + * TRUE: wake up by wlan; otherwise, FALSE + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalIsWakeupByWlan(struct ADAPTER *prAdapter) +{ + /* + * SUSPEND_FLAG_FOR_WAKEUP_REASON is set means system has suspended, + * but may be failed duo to some driver suspend failed. so we need + * help of function slp_get_wake_reason + */ + if (test_and_clear_bit(SUSPEND_FLAG_FOR_WAKEUP_REASON, + &prAdapter->ulSuspendFlag) == 0) + return FALSE; + + return TRUE; +} +#endif + + + +u_int8_t +kalGetIPv4Address(IN struct net_device *prDev, + IN uint32_t u4MaxNumOfAddr, OUT uint8_t *pucIpv4Addrs, + OUT uint32_t *pu4NumOfIpv4Addr) +{ + uint32_t u4NumIPv4 = 0; + uint32_t u4AddrLen = IPV4_ADDR_LEN; + struct in_ifaddr *prIfa; + + /* 4 <1> Sanity check of netDevice */ + if (!prDev || !(prDev->ip_ptr) + || !((struct in_device *)(prDev->ip_ptr))->ifa_list) { + DBGLOG(INIT, INFO, + "IPv4 address is not available for dev(0x%p)\n", prDev); + + *pu4NumOfIpv4Addr = 0; + return FALSE; + } + + prIfa = ((struct in_device *)(prDev->ip_ptr))->ifa_list; + + /* 4 <2> copy the IPv4 address */ + while ((u4NumIPv4 < u4MaxNumOfAddr) && prIfa) { + kalMemCopy(&pucIpv4Addrs[u4NumIPv4 * u4AddrLen], + &prIfa->ifa_local, u4AddrLen); + kalMemCopy(&pucIpv4Addrs[(u4NumIPv4+1) * u4AddrLen], + &prIfa->ifa_mask, u4AddrLen); + prIfa = prIfa->ifa_next; + + DBGLOG(INIT, INFO, + "IPv4 addr [%u][" IPV4STR "] mask [" IPV4STR "]\n", + u4NumIPv4, + IPV4TOSTR(&pucIpv4Addrs[u4NumIPv4*u4AddrLen]), + IPV4TOSTR(&pucIpv4Addrs[(u4NumIPv4+1)*u4AddrLen])); + + u4NumIPv4++; + } + + *pu4NumOfIpv4Addr = u4NumIPv4; + + return TRUE; +} + +#if IS_ENABLED(CONFIG_IPV6) +u_int8_t +kalGetIPv6Address(IN struct net_device *prDev, + IN uint32_t u4MaxNumOfAddr, OUT uint8_t *pucIpv6Addrs, + OUT uint32_t *pu4NumOfIpv6Addr) +{ + uint32_t u4NumIPv6 = 0; + uint32_t u4AddrLen = IPV6_ADDR_LEN; + struct inet6_ifaddr *prIfa; + + /* 4 <1> Sanity check of netDevice */ + if (!prDev || !(prDev->ip6_ptr)) { + DBGLOG(INIT, INFO, + "IPv6 address is not available for dev(0x%p)\n", prDev); + + *pu4NumOfIpv6Addr = 0; + return FALSE; + } + + + /* 4 <2> copy the IPv6 address */ + LIST_FOR_EACH_IPV6_ADDR(prIfa, prDev->ip6_ptr) { + kalMemCopy(&pucIpv6Addrs[u4NumIPv6 * u4AddrLen], + &prIfa->addr, u4AddrLen); + + DBGLOG(INIT, INFO, + "IPv6 addr [%u][" IPV6STR "]\n", u4NumIPv6, + IPV6TOSTR(&pucIpv6Addrs[u4NumIPv6 * u4AddrLen])); + + if ((u4NumIPv6 + 1) >= u4MaxNumOfAddr) + break; + u4NumIPv6++; + } + + *pu4NumOfIpv6Addr = u4NumIPv6; + + return TRUE; +} +#endif /* IS_ENABLED(CONFIG_IPV6) */ + +void +kalSetNetAddress(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucBssIdx, + IN uint8_t *pucIPv4Addr, IN uint32_t u4NumIPv4Addr, + IN uint8_t *pucIPv6Addr, IN uint32_t u4NumIPv6Addr) +{ + uint32_t rStatus = WLAN_STATUS_FAILURE; + uint32_t u4SetInfoLen = 0; + uint32_t u4Len = OFFSET_OF(struct + PARAM_NETWORK_ADDRESS_LIST, arAddress); + struct PARAM_NETWORK_ADDRESS_LIST *prParamNetAddrList; + struct PARAM_NETWORK_ADDRESS *prParamNetAddr; + uint32_t i, u4AddrLen; + + /* 4 <1> Calculate buffer size */ + /* IPv4 */ + u4Len += (((sizeof(struct PARAM_NETWORK_ADDRESS) - 1) + + IPV4_ADDR_LEN) * u4NumIPv4Addr * 2); + /* IPv6 */ + u4Len += (((sizeof(struct PARAM_NETWORK_ADDRESS) - 1) + + IPV6_ADDR_LEN) * u4NumIPv6Addr); + + /* 4 <2> Allocate buffer */ + prParamNetAddrList = (struct PARAM_NETWORK_ADDRESS_LIST *) + kalMemAlloc(u4Len, VIR_MEM_TYPE); + + if (!prParamNetAddrList) { + DBGLOG(INIT, WARN, + "Fail to alloc buffer for setting BSS[%u] network address!\n", + ucBssIdx); + return; + } + /* 4 <3> Fill up network address */ + prParamNetAddrList->u2AddressType = + PARAM_PROTOCOL_ID_TCP_IP; + prParamNetAddrList->u4AddressCount = 0; + prParamNetAddrList->ucBssIdx = ucBssIdx; + + /* 4 <3.1> Fill up IPv4 address */ + u4AddrLen = IPV4_ADDR_LEN; + prParamNetAddr = prParamNetAddrList->arAddress; + for (i = 0; i < u4NumIPv4Addr; i++) { + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + prParamNetAddr->u2AddressLength = u4AddrLen; + kalMemCopy(prParamNetAddr->aucAddress, + &pucIPv4Addr[i*u4AddrLen*2], u4AddrLen*2); + + prParamNetAddr = (struct PARAM_NETWORK_ADDRESS *) + ((unsigned long) prParamNetAddr + + (unsigned long) (u4AddrLen*2 + + OFFSET_OF(struct PARAM_NETWORK_ADDRESS, aucAddress))); + } + prParamNetAddrList->u4AddressCount += u4NumIPv4Addr; + + /* 4 <3.2> Fill up IPv6 address */ + u4AddrLen = IPV6_ADDR_LEN; + for (i = 0; i < u4NumIPv6Addr; i++) { + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + prParamNetAddr->u2AddressLength = u4AddrLen; + kalMemCopy(prParamNetAddr->aucAddress, + &pucIPv6Addr[i * u4AddrLen], u4AddrLen); + + prParamNetAddr = (struct PARAM_NETWORK_ADDRESS *) (( + unsigned long) prParamNetAddr + (unsigned long) ( + u4AddrLen + OFFSET_OF( + struct PARAM_NETWORK_ADDRESS, aucAddress))); + } + prParamNetAddrList->u4AddressCount += u4NumIPv6Addr; + + /* 4 <4> IOCTL to main_thread */ + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNetworkAddress, + (void *) prParamNetAddrList, u4Len, + FALSE, FALSE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "%s: Fail to set network address\n", + __func__); + + kalMemFree(prParamNetAddrList, VIR_MEM_TYPE, u4Len); + +} + +void kalSetNetAddressFromInterface(IN struct GLUE_INFO + *prGlueInfo, IN struct net_device *prDev, IN u_int8_t fgSet) +{ + uint32_t u4NumIPv4, u4NumIPv6; + uint8_t pucIPv4Addr[IPV4_ADDR_LEN * CFG_PF_ARP_NS_MAX_NUM*2]; + uint8_t pucIPv6Addr[IPV6_ADDR_LEN * CFG_PF_ARP_NS_MAX_NUM]; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = + (struct NETDEV_PRIVATE_GLUE_INFO *) NULL; + + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prDev); + + if (prNetDevPrivate->prGlueInfo != prGlueInfo) + DBGLOG(REQ, WARN, "%s: unexpected prGlueInfo(0x%p)!\n", + __func__, prNetDevPrivate->prGlueInfo); + + u4NumIPv4 = 0; + u4NumIPv6 = 0; + + if (fgSet) { + kalGetIPv4Address(prDev, CFG_PF_ARP_NS_MAX_NUM, pucIPv4Addr, + &u4NumIPv4); + kalGetIPv6Address(prDev, CFG_PF_ARP_NS_MAX_NUM, pucIPv6Addr, + &u4NumIPv6); + } + + if (u4NumIPv4 + u4NumIPv6 > CFG_PF_ARP_NS_MAX_NUM) { + if (u4NumIPv4 >= CFG_PF_ARP_NS_MAX_NUM) { + u4NumIPv4 = CFG_PF_ARP_NS_MAX_NUM; + u4NumIPv6 = 0; + } else { + u4NumIPv6 = CFG_PF_ARP_NS_MAX_NUM - u4NumIPv4; + } + } + + kalSetNetAddress(prGlueInfo, prNetDevPrivate->ucBssIdx, + pucIPv4Addr, u4NumIPv4, pucIPv6Addr, u4NumIPv6); +} + +#if CFG_MET_PACKET_TRACE_SUPPORT + +u_int8_t kalMetCheckProfilingPacket(IN struct GLUE_INFO + *prGlueInfo, IN void *prPacket) +{ + uint32_t u4PacketLen; + uint16_t u2EtherTypeLen; + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + uint8_t *aucLookAheadBuf = NULL; + uint8_t ucEthTypeLenOffset = ETHER_HEADER_LEN - + ETHER_TYPE_LEN; + uint8_t *pucNextProtocol = NULL; + + u4PacketLen = prSkb->len; + + if (u4PacketLen < ETHER_HEADER_LEN) { + DBGLOG(INIT, WARN, "Invalid Ether packet length: %u\n", + u4PacketLen); + return FALSE; + } + + aucLookAheadBuf = prSkb->data; + + /* 4 <0> Obtain Ether Type/Len */ + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[ucEthTypeLenOffset], + &u2EtherTypeLen); + + /* 4 <1> Skip 802.1Q header (VLAN Tagging) */ + if (u2EtherTypeLen == ETH_P_VLAN) { + ucEthTypeLenOffset += ETH_802_1Q_HEADER_LEN; + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[ucEthTypeLenOffset], + &u2EtherTypeLen); + } + /* 4 <2> Obtain next protocol pointer */ + pucNextProtocol = &aucLookAheadBuf[ucEthTypeLenOffset + + ETHER_TYPE_LEN]; + + /* 4 <3> Handle ethernet format */ + switch (u2EtherTypeLen) { + + /* IPv4 */ + case ETH_P_IPV4: { + uint8_t *pucIpHdr = pucNextProtocol; + uint8_t ucIpVersion; + + /* IPv4 header length check */ + if (u4PacketLen < (ucEthTypeLenOffset + ETHER_TYPE_LEN + + IPV4_HDR_LEN)) { + DBGLOG(INIT, WARN, "Invalid IPv4 packet length: %u\n", + u4PacketLen); + return FALSE; + } + + /* IPv4 version check */ + ucIpVersion = (pucIpHdr[0] & IP_VERSION_MASK) >> + IP_VERSION_OFFSET; + if (ucIpVersion != IP_VERSION_4) { + DBGLOG(INIT, WARN, "Invalid IPv4 packet version: %u\n", + ucIpVersion); + return FALSE; + } + + if (pucIpHdr[IPV4_HDR_IP_PROTOCOL_OFFSET] == IP_PRO_UDP) { + uint8_t *pucUdpHdr = &pucIpHdr[IPV4_HDR_LEN]; + uint16_t u2UdpDstPort; + uint16_t u2UdpSrcPort; + + /* Get UDP DST port */ + WLAN_GET_FIELD_BE16(&pucUdpHdr[UDP_HDR_DST_PORT_OFFSET], + &u2UdpDstPort); + + /* Get UDP SRC port */ + WLAN_GET_FIELD_BE16(&pucUdpHdr[UDP_HDR_SRC_PORT_OFFSET], + &u2UdpSrcPort); + + if (u2UdpSrcPort == prGlueInfo->u2MetUdpPort) { + uint16_t u2IpId; + + /* Store IP ID for Tag */ + WLAN_GET_FIELD_BE16( + &pucIpHdr[IPV4_HDR_IP_IDENTIFICATION_OFFSET], + &u2IpId); +#if 0 + DBGLOG(INIT, INFO, + "TX PKT PROTOCOL[0x%x] UDP DST port[%u] IP_ID[%u]\n", + pucIpHdr[IPV4_HDR_IP_PROTOCOL_OFFSET], + u2UdpDstPort, + u2IpId); +#endif + GLUE_SET_PKT_IP_ID(prPacket, u2IpId); + + return TRUE; + } + } + } + break; + + default: + break; + } + + return FALSE; +} + +#if 0 + +static unsigned long __read_mostly tracing_mark_write_addr; + +static int __mt_find_tracing_mark_write_symbol_fn( + void *prData, const char *pcNameBuf, + struct module *prModule, unsigned long ulAddress) +{ + if (strcmp(pcNameBuf, "tracing_mark_write") == 0) { + tracing_mark_write_addr = ulAddress; + return 1; + } + return 0; +} +#endif + +static inline void __mt_update_tracing_mark_write_addr(void) +{ +#if 0 + if (unlikely(tracing_mark_write_addr == 0)) + kallsyms_on_each_symbol( + __mt_find_tracing_mark_write_symbol_fn, NULL); +#endif +} + +void kalMetTagPacket(IN struct GLUE_INFO *prGlueInfo, + IN void *prPacket, IN enum ENUM_TX_PROFILING_TAG eTag) +{ + if (!prGlueInfo->fgMetProfilingEn) + return; + + switch (eTag) { + case TX_PROF_TAG_OS_TO_DRV: + if (kalMetCheckProfilingPacket(prGlueInfo, prPacket)) { + /* trace_printk("S|%d|%s|%d\n", current->pid, + * "WIFI-CHIP", GLUE_GET_PKT_IP_ID(prPacket)); + */ + __mt_update_tracing_mark_write_addr(); +#if 0 /* #ifdef CONFIG_TRACING */ /* #if CFG_MET_PACKET_TRACE_SUPPORT */ + event_trace_printk(tracing_mark_write_addr, + "S|%d|%s|%d\n", + current->tgid, "WIFI-CHIP", + GLUE_GET_PKT_IP_ID(prPacket)); +#endif + GLUE_SET_PKT_FLAG_PROF_MET(prPacket); + } + break; + + case TX_PROF_TAG_DRV_TX_DONE: + if (GLUE_GET_PKT_IS_PROF_MET(prPacket)) { + /* trace_printk("F|%d|%s|%d\n", current->pid, + * "WIFI-CHIP", GLUE_GET_PKT_IP_ID(prPacket)); + */ + __mt_update_tracing_mark_write_addr(); +#if 0 /* #ifdef CONFIG_TRACING */ /* #if CFG_MET_PACKET_TRACE_SUPPORT */ + event_trace_printk(tracing_mark_write_addr, + "F|%d|%s|%d\n", + current->tgid, "WIFI-CHIP", + GLUE_GET_PKT_IP_ID(prPacket)); +#endif + } + break; + + default: + break; + } +} + +void kalMetInit(IN struct GLUE_INFO *prGlueInfo) +{ + prGlueInfo->fgMetProfilingEn = FALSE; + prGlueInfo->u2MetUdpPort = 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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. + */ +/*----------------------------------------------------------------------------*/ +#if 0 +static ssize_t kalMetWriteProcfs(struct file *file, + const char __user *buffer, size_t count, loff_t *off) +{ + char acBuf[128 + 1]; /* + 1 for "\0" */ + uint32_t u4CopySize; + int u16MetUdpPort; + int u8MetProfEnable; + + IN struct GLUE_INFO *prGlueInfo; + ssize_t result; + + u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : + (sizeof(acBuf) - 1); + result = copy_from_user(acBuf, buffer, u4CopySize); + acBuf[u4CopySize] = '\0'; + + if (sscanf(acBuf, " %d %d", &u8MetProfEnable, + &u16MetUdpPort) == 2) + DBGLOG(INIT, INFO, + "MET_PROF: Write MET PROC Enable=%d UDP_PORT=%d\n", + u8MetProfEnable, u16MetUdpPort); + if (pMetGlobalData != NULL) { + prGlueInfo = (struct GLUE_INFO *) pMetGlobalData; + prGlueInfo->fgMetProfilingEn = (u_int8_t) u8MetProfEnable; + prGlueInfo->u2MetUdpPort = (uint16_t) u16MetUdpPort; + } + return count; +} +#endif +static ssize_t kalMetCtrlWriteProcfs(struct file *file, + const char __user *buffer, size_t count, loff_t *off) +{ + char acBuf[128 + 1]; /* + 1 for "\0" */ + uint32_t u4CopySize; + int u8MetProfEnable; + ssize_t result; + + IN struct GLUE_INFO *prGlueInfo; + + u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : + (sizeof(acBuf) - 1); + result = copy_from_user(acBuf, buffer, u4CopySize); + acBuf[u4CopySize] = '\0'; + + if (sscanf(acBuf, " %d", &u8MetProfEnable) == 1) + DBGLOG(INIT, INFO, "MET_PROF: Write MET PROC Enable=%d\n", + u8MetProfEnable); + if (pMetGlobalData != NULL) { + prGlueInfo = (struct GLUE_INFO *) pMetGlobalData; + prGlueInfo->fgMetProfilingEn = (uint8_t) u8MetProfEnable; + } + return count; +} + +static ssize_t kalMetPortWriteProcfs(struct file *file, + const char __user *buffer, size_t count, loff_t *off) +{ + char acBuf[128 + 1]; /* + 1 for "\0" */ + uint32_t u4CopySize; + int u16MetUdpPort; + ssize_t result; + + IN struct GLUE_INFO *prGlueInfo; + + u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : + (sizeof(acBuf) - 1); + result = copy_from_user(acBuf, buffer, u4CopySize); + acBuf[u4CopySize] = '\0'; + + if (sscanf(acBuf, " %d", &u16MetUdpPort) == 1) + DBGLOG(INIT, INFO, "MET_PROF: Write MET PROC UDP_PORT=%d\n", + u16MetUdpPort); + if (pMetGlobalData != NULL) { + prGlueInfo = (struct GLUE_INFO *) pMetGlobalData; + prGlueInfo->u2MetUdpPort = (uint16_t) u16MetUdpPort; + } + return count; +} + +#if 0 +const struct file_operations rMetProcFops = { + .write = kalMetWriteProcfs +}; +#endif +const struct file_operations rMetProcCtrlFops = { + .write = kalMetCtrlWriteProcfs +}; + +const struct file_operations rMetProcPortFops = { + .write = kalMetPortWriteProcfs +}; + +int kalMetInitProcfs(IN struct GLUE_INFO *prGlueInfo) +{ + /* struct proc_dir_entry *pMetProcDir; */ + if (init_net.proc_net == (struct proc_dir_entry *)NULL) { + DBGLOG(INIT, INFO, "init proc fs fail: proc_net == NULL\n"); + return -ENOENT; + } + /* + * Directory: Root (/proc/net/wlan0) + */ + pMetProcDir = proc_mkdir("wlan0", init_net.proc_net); + if (pMetProcDir == NULL) + return -ENOENT; + /* + * /proc/net/wlan0 + * |-- met_ctrl (PROC_MET_PROF_CTRL) + */ + /* proc_create(PROC_MET_PROF_CTRL, 0x0644, pMetProcDir, &rMetProcFops); + */ + proc_create(PROC_MET_PROF_CTRL, 0000, pMetProcDir, + &rMetProcCtrlFops); + proc_create(PROC_MET_PROF_PORT, 0000, pMetProcDir, + &rMetProcPortFops); + + pMetGlobalData = (void *)prGlueInfo; + + return 0; +} + +int kalMetRemoveProcfs(void) +{ + + if (init_net.proc_net == (struct proc_dir_entry *)NULL) { + DBGLOG(INIT, WARN, + "remove proc fs fail: proc_net == NULL\n"); + return -ENOENT; + } + remove_proc_entry(PROC_MET_PROF_CTRL, pMetProcDir); + remove_proc_entry(PROC_MET_PROF_PORT, pMetProcDir); + /* remove root directory (proc/net/wlan0) */ + remove_proc_entry("wlan0", init_net.proc_net); + /* clear MetGlobalData */ + pMetGlobalData = NULL; + + return 0; +} + +#endif + +static u_int8_t kalSendUevent(const char *src) +{ + int ret; + char *envp[2]; + char event_string[32]; + + envp[0] = event_string; + envp[1] = NULL; + + /*send uevent*/ + strlcpy(event_string, src, sizeof(event_string)); + if (event_string[0] == '\0') { /*string is null*/ + return FALSE; + } + ret = kobject_uevent_env( + &wlan_object.this_device->kobj, + KOBJ_CHANGE, envp); + if (ret != 0) { + DBGLOG(INIT, WARN, "uevent failed\n"); + return FALSE; + } + + return TRUE; +} + +int kalWlanUeventInit(void) +{ + int ret = 0; + + /* dev init */ + wlan_object.name = "wlan"; + wlan_object.minor = MISC_DYNAMIC_MINOR; + ret = misc_register(&wlan_object); + if (ret) { + DBGLOG(INIT, WARN, "misc_register error:%d\n", ret); + return ret; + } + + ret = kobject_uevent( + &wlan_object.this_device->kobj, KOBJ_ADD); + + if (ret) { + misc_deregister(&wlan_object); + DBGLOG(INIT, WARN, "uevent creat fail:%d\n", ret); + return ret; + } + + return ret; +} + +void kalWlanUeventDeinit(void) +{ + misc_deregister(&wlan_object); +} + +#if CFG_SUPPORT_DATA_STALL +u_int8_t kalIndicateDriverEvent(struct ADAPTER *prAdapter, + uint32_t event, + uint16_t dataLen, + uint8_t ucBssIdx, + u_int8_t fgForceReport) +{ + struct sk_buff *skb = NULL; + struct wiphy *wiphy; + struct wireless_dev *wdev; + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; + char uevent[30]; + + wiphy = priv_to_wiphy(prAdapter->prGlueInfo); + wdev = (wlanGetNetDev(prAdapter->prGlueInfo, + ucBssIdx))->ieee80211_ptr; + + if (!wiphy || !wdev || !prWifiVar) + return -EINVAL; + + if (!fgForceReport) { + if (prAdapter->tmReportinterval > 0 && + !CHECK_FOR_TIMEOUT(kalGetTimeTick(), + prAdapter->tmReportinterval, + prWifiVar->u4ReportEventInterval*1000)) { + return -ETIME; + } + GET_CURRENT_SYSTIME(&prAdapter->tmReportinterval); + } + + kalSnprintf(uevent, sizeof(uevent), "code=%d", event); + kalSendUevent(uevent); + + skb = cfg80211_vendor_event_alloc(wiphy, wdev, + dataLen, + WIFI_EVENT_DRIVER_ERROR, GFP_KERNEL); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + if (dataLen > 0 && + unlikely(nla_put(skb, WIFI_ATTRIBUTE_ERROR_REASON + , dataLen, &event) < 0)) + goto nla_put_failure; + + DBGLOG(INIT, ERROR, "DPP event to cfg80211[id:%d][len:%d][F:%d]:%d\n", + WIFI_EVENT_DRIVER_ERROR, + dataLen, fgForceReport, event); + + cfg80211_vendor_event(skb, GFP_KERNEL); + return TRUE; +nla_put_failure: + kfree_skb(skb); + return FALSE; +} +#endif + +#if CFG_SUPPORT_BIGDATA_PIP +int8_t kalBigDataPip(struct ADAPTER *prAdapter, + uint8_t *payload, + uint16_t dataLen) +{ + struct sk_buff *skb = NULL; + struct wiphy *wiphy; + struct wireless_dev *wdev; + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; + + wiphy = priv_to_wiphy(prAdapter->prGlueInfo); + wdev = ((prAdapter->prGlueInfo)->prDevHandler)->ieee80211_ptr; + + if (!wiphy || !wdev || !prWifiVar || !payload) + return -EINVAL; + + /* Max length of report data is discussed to 500.*/ + if (dataLen > 500) + return -EINVAL; + + if (prAdapter->tmDataPipReportinterval > 0 && + !CHECK_FOR_TIMEOUT(kalGetTimeTick(), + prAdapter->tmDataPipReportinterval, 20)) { + return -ETIME; + } + GET_CURRENT_SYSTIME(&prAdapter->tmDataPipReportinterval); + + skb = cfg80211_vendor_event_alloc(wiphy, wdev, dataLen, + WIFI_EVENT_BIGDATA_PIP, GFP_KERNEL); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + if (dataLen > 0 && + unlikely(nla_put(skb, WIFI_ATTRIBUTE_PIP_PAYLOAD + , dataLen, payload) < 0)) + goto nla_put_failure; + + cfg80211_vendor_event(skb, GFP_KERNEL); + return TRUE; +nla_put_failure: + kfree_skb(skb); + return FALSE; +} +#endif + +#if CFG_SUPPORT_AGPS_ASSIST +u_int8_t kalIndicateAgpsNotify(struct ADAPTER *prAdapter, + uint8_t cmd, uint8_t *data, uint16_t dataLen) +{ +#ifdef CONFIG_NL80211_TESTMODE + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct sk_buff *skb = NULL; + + skb = cfg80211_testmode_alloc_event_skb(priv_to_wiphy( + prGlueInfo), + dataLen, GFP_KERNEL); + + /* DBGLOG(CCX, INFO, ("WLAN_STATUS_AGPS_NOTIFY, cmd=%d\n", cmd)); */ + if (unlikely(nla_put(skb, MTK_ATTR_AGPS_CMD, sizeof(cmd), + &cmd) < 0)) + goto nla_put_failure; + if (dataLen > 0 && data + && unlikely(nla_put(skb, MTK_ATTR_AGPS_DATA, dataLen, + data) < 0)) + goto nla_put_failure; + if (unlikely(nla_put(skb, MTK_ATTR_AGPS_IFINDEX, + sizeof(uint32_t), &prGlueInfo->prDevHandler->ifindex) < 0)) + goto nla_put_failure; + /* currently, the ifname maybe wlan0, p2p0, so the maximum name length + * will be 5 bytes + */ + if (unlikely(nla_put(skb, MTK_ATTR_AGPS_IFNAME, 5, + prGlueInfo->prDevHandler->name) < 0)) + goto nla_put_failure; + + cfg80211_testmode_event(skb, GFP_KERNEL); + return TRUE; +nla_put_failure: + kfree_skb(skb); +#else + DBGLOG(INIT, WARN, "CONFIG_NL80211_TESTMODE not enabled\n"); +#endif + return FALSE; +} +#endif + +uint64_t kalGetBootTime(void) +{ +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + struct timespec64 ts; +#else + struct timespec ts; +#endif + uint64_t bootTime = 0; + +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + ktime_get_boottime_ts64(&ts); +#elif KERNEL_VERSION(2, 6, 39) <= LINUX_VERSION_CODE + get_monotonic_boottime(&ts); +#else + ts = ktime_to_timespec(ktime_get()); +#endif + + bootTime = ts.tv_sec; + bootTime *= USEC_PER_SEC; + bootTime += ts.tv_nsec / NSEC_PER_USEC; + return bootTime; +} + +#if CFG_ASSERT_DUMP +uint32_t kalOpenCorDumpFile(u_int8_t fgIsN9) +{ + /* Move open-op to kalWriteCorDumpFile(). Empty files only */ + uint32_t ret; + uint8_t *apucFileName; + + if (fgIsN9) + apucFileName = apucCorDumpN9FileName; + else + apucFileName = apucCorDumpCr4FileName; + + ret = kalTrunkPath(apucFileName); + + return (ret >= 0)?WLAN_STATUS_SUCCESS:WLAN_STATUS_FAILURE; +} + +uint32_t kalWriteCorDumpFile(uint8_t *pucBuffer, + uint16_t u2Size, u_int8_t fgIsN9) +{ + uint32_t ret; + uint8_t *apucFileName; + + if (fgIsN9) + apucFileName = apucCorDumpN9FileName; + else + apucFileName = apucCorDumpCr4FileName; + + ret = kalWriteToFile(apucFileName, TRUE, pucBuffer, u2Size); + + return (ret >= 0)?WLAN_STATUS_SUCCESS:WLAN_STATUS_FAILURE; +} + +uint32_t kalCloseCorDumpFile(u_int8_t fgIsN9) +{ + /* Move close-op to kalWriteCorDumpFile(). Do nothing here */ + + return WLAN_STATUS_SUCCESS; +} +#endif + +#if CFG_WOW_SUPPORT +void kalWowInit(IN struct GLUE_INFO *prGlueInfo) +{ + kalMemZero(&prGlueInfo->prAdapter->rWowCtrl.stWowPort, + sizeof(struct WOW_PORT)); +} + +void kalWowCmdEventSetCb(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + + if (prCmdInfo->ucCID == CMD_ID_SET_PF_CAPABILITY) { + DBGLOG(INIT, STATE, "CMD_ID_SET_PF_CAPABILITY cmd done\n"); + prAdapter->fgSetPfCapabilityDone = TRUE; + } + + if (prCmdInfo->ucCID == CMD_ID_SET_WOWLAN) { + DBGLOG(INIT, STATE, "CMD_ID_SET_WOWLAN cmd done\n"); + prAdapter->fgSetWowDone = TRUE; + } + +} + +void kalWowProcess(IN struct GLUE_INFO *prGlueInfo, + uint8_t enable) +{ + struct CMD_WOWLAN_PARAM rCmdWowlanParam; + struct CMD_PACKET_FILTER_CAP rCmdPacket_Filter_Cap; + struct WOW_CTRL *pWOW_CTRL = + &prGlueInfo->prAdapter->rWowCtrl; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t ii, wait = 0; + struct BSS_INFO *prAisBssInfo = NULL; + + kalMemZero(&rCmdWowlanParam, + sizeof(struct CMD_WOWLAN_PARAM)); + + kalMemZero(&rCmdPacket_Filter_Cap, + sizeof(struct CMD_PACKET_FILTER_CAP)); + + prGlueInfo->prAdapter->fgSetPfCapabilityDone = FALSE; + prGlueInfo->prAdapter->fgSetWowDone = FALSE; + + prAisBssInfo = aisGetConnectedBssInfo( + prGlueInfo->prAdapter); + + if (prAisBssInfo) + DBGLOG(PF, INFO, + "PF, pAd ucBssIndex=%d, ucOwnMacIndex=%d\n", + prAisBssInfo->ucBssIndex, + prAisBssInfo->ucOwnMacIndex); + + DBGLOG(PF, INFO, "profile wow=%d, GpioInterval=%d\n", + prGlueInfo->prAdapter->rWifiVar.ucWow, + prGlueInfo->prAdapter->rWowCtrl.astWakeHif[0].u4GpioInterval); + + rCmdPacket_Filter_Cap.packet_cap_type |= + PACKETF_CAP_TYPE_MAGIC; + /* 20160627 Bennett: if receive BMC magic, PF search by bssid index, + * which is different with OM index + */ + /* After discussion, enable all bssid bits */ + /* rCmdPacket_Filter_Cap.ucBssid |= + * BIT(prGlueInfo->prAdapter->prAisBssInfo->ucOwnMacIndex); + */ + rCmdPacket_Filter_Cap.ucBssid |= BITS(0, 3); + + if (enable) + rCmdPacket_Filter_Cap.usEnableBits |= + PACKETF_CAP_TYPE_MAGIC; + else + rCmdPacket_Filter_Cap.usEnableBits &= + ~PACKETF_CAP_TYPE_MAGIC; + + rStatus = wlanSendSetQueryCmd(prGlueInfo->prAdapter, + CMD_ID_SET_PF_CAPABILITY, + TRUE, + FALSE, + FALSE, + kalWowCmdEventSetCb, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_PACKET_FILTER_CAP), + (uint8_t *)&rCmdPacket_Filter_Cap, + NULL, + 0); + + /* ARP offload */ + wlanSetSuspendMode(prGlueInfo, enable); + /* p2pSetSuspendMode(prGlueInfo, TRUE); */ + + /* Let WOW enable/disable as last command, so we can back/restore DMA + * classify filter in FW + */ + rCmdWowlanParam.ucScenarioID = pWOW_CTRL->ucScenarioId; + rCmdWowlanParam.ucBlockCount = pWOW_CTRL->ucBlockCount; + kalMemCopy(&rCmdWowlanParam.astWakeHif[0], + &pWOW_CTRL->astWakeHif[0], sizeof(struct WOW_WAKE_HIF)); + + /* copy UDP/TCP port setting */ + kalMemCopy(&rCmdWowlanParam.stWowPort, + &prGlueInfo->prAdapter->rWowCtrl.stWowPort, + sizeof(struct WOW_PORT)); + + DBGLOG(PF, INFO, + "Cmd: IPV4/UDP=%d, IPV4/TCP=%d, IPV6/UDP=%d, IPV6/TCP=%d\n", + rCmdWowlanParam.stWowPort.ucIPv4UdpPortCnt, + rCmdWowlanParam.stWowPort.ucIPv4TcpPortCnt, + rCmdWowlanParam.stWowPort.ucIPv6UdpPortCnt, + rCmdWowlanParam.stWowPort.ucIPv6TcpPortCnt); + + for (ii = 0; + ii < rCmdWowlanParam.stWowPort.ucIPv4UdpPortCnt; ii++) + DBGLOG(PF, INFO, "IPV4/UDP port[%d]=%d\n", ii, + rCmdWowlanParam.stWowPort.ausIPv4UdpPort[ii]); + + for (ii = 0; + ii < rCmdWowlanParam.stWowPort.ucIPv4TcpPortCnt; ii++) + DBGLOG(PF, INFO, "IPV4/TCP port[%d]=%d\n", ii, + rCmdWowlanParam.stWowPort.ausIPv4TcpPort[ii]); + + for (ii = 0; + ii < rCmdWowlanParam.stWowPort.ucIPv6UdpPortCnt; ii++) + DBGLOG(PF, INFO, "IPV6/UDP port[%d]=%d\n", ii, + rCmdWowlanParam.stWowPort.ausIPv6UdpPort[ii]); + + for (ii = 0; + ii < rCmdWowlanParam.stWowPort.ucIPv6TcpPortCnt; ii++) + DBGLOG(PF, INFO, "IPV6/TCP port[%d]=%d\n", ii, + rCmdWowlanParam.stWowPort.ausIPv6TcpPort[ii]); + + + /* GPIO parameter is necessary in suspend/resume */ + if (enable == 1) { + rCmdWowlanParam.ucCmd = PM_WOWLAN_REQ_START; + rCmdWowlanParam.ucDetectType = WOWLAN_DETECT_TYPE_MAGIC | + WOWLAN_DETECT_TYPE_ONLY_PHONE_SUSPEND; + rCmdWowlanParam.u2FilterFlag = WOWLAN_FF_DROP_ALL | + WOWLAN_FF_SEND_MAGIC_TO_HOST | + WOWLAN_FF_ALLOW_1X | + WOWLAN_FF_ALLOW_ARP_REQ2ME; + } else { + rCmdWowlanParam.ucCmd = PM_WOWLAN_REQ_STOP; + } + + rStatus = wlanSendSetQueryCmd(prGlueInfo->prAdapter, + CMD_ID_SET_WOWLAN, + TRUE, + FALSE, + FALSE, + kalWowCmdEventSetCb, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_WOWLAN_PARAM), + (uint8_t *)&rCmdWowlanParam, + NULL, + 0); + + + while (1) { + kalMsleep(5); + + if (wait > 100) { + DBGLOG(INIT, ERROR, "WoW timeout.PF:%d. WoW:%d\n", + prGlueInfo->prAdapter->fgSetPfCapabilityDone, + prGlueInfo->prAdapter->fgSetWowDone); + break; + } + if ((prGlueInfo->prAdapter->fgSetPfCapabilityDone == TRUE) + && (prGlueInfo->prAdapter->fgSetWowDone == TRUE)) { + DBGLOG(INIT, STATE, "WoW process done\n"); + break; + } + wait++; + } + +} +#endif + +void kalFreeTxMsduWorker(struct work_struct *work) +{ + struct GLUE_INFO *prGlueInfo; + struct ADAPTER *prAdapter; + struct QUE rTmpQue; + struct QUE *prTmpQue = &rTmpQue; + struct MSDU_INFO *prMsduInfo; + + if (g_u4HaltFlag) + return; + + prGlueInfo = ENTRY_OF(work, struct GLUE_INFO, + rTxMsduFreeWork); + prAdapter = prGlueInfo->prAdapter; + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) + return; + + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); + QUEUE_MOVE_ALL(prTmpQue, &prAdapter->rTxDataDoneQueue); + KAL_RELEASE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); + + while (QUEUE_IS_NOT_EMPTY(prTmpQue)) { + QUEUE_REMOVE_HEAD(prTmpQue, prMsduInfo, struct MSDU_INFO *); + nicTxFreePacket(prAdapter, prMsduInfo, FALSE); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } +} + +void kalFreeTxMsdu(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); + QUEUE_INSERT_TAIL(&prAdapter->rTxDataDoneQueue, + (struct QUE_ENTRY *) prMsduInfo); + KAL_RELEASE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); + + schedule_work(&prAdapter->prGlueInfo->rTxMsduFreeWork); +} + +int32_t kalHaltLock(uint32_t waitMs) +{ + int32_t i4Ret = 0; + struct GLUE_INFO *prGlueInfo = NULL; + + if (waitMs) { + i4Ret = down_timeout(&rHaltCtrl.lock, + MSEC_TO_JIFFIES(waitMs)); + if (!i4Ret) + goto success; + if (i4Ret != -ETIME) + return i4Ret; + + prGlueInfo = wlanGetGlueInfo(); + if (rHaltCtrl.fgHeldByKalIoctl) { + DBGLOG(INIT, ERROR, + "kalIoctl was executed longer than %u ms, show backtrace of tx_thread!\n", + kalGetTimeTick() - rHaltCtrl.u4HoldStart); + if (prGlueInfo) + kal_show_stack(prGlueInfo->prAdapter, + prGlueInfo->main_thread, NULL); + } else { + DBGLOG(INIT, ERROR, + "halt lock held by %s pid %d longer than %u ms!\n", + rHaltCtrl.owner->comm, rHaltCtrl.owner->pid, + kalGetTimeTick() - rHaltCtrl.u4HoldStart); + if (prGlueInfo) + kal_show_stack(prGlueInfo->prAdapter, + rHaltCtrl.owner, NULL); + } + return i4Ret; + } + down(&rHaltCtrl.lock); +success: + rHaltCtrl.owner = current; + rHaltCtrl.u4HoldStart = kalGetTimeTick(); + return 0; +} + +int32_t kalHaltTryLock(void) +{ + int32_t i4Ret = 0; + + i4Ret = down_trylock(&rHaltCtrl.lock); + if (i4Ret) + return i4Ret; + rHaltCtrl.owner = current; + rHaltCtrl.u4HoldStart = kalGetTimeTick(); + return 0; +} + +void kalHaltUnlock(void) +{ + if (kalGetTimeTick() - rHaltCtrl.u4HoldStart > + WLAN_OID_TIMEOUT_THRESHOLD * 2 && + rHaltCtrl.owner) + DBGLOG(INIT, ERROR, + "process %s pid %d hold halt lock longer than 4s!\n", + rHaltCtrl.owner->comm, rHaltCtrl.owner->pid); + rHaltCtrl.owner = NULL; + up(&rHaltCtrl.lock); +} + +void kalSetHalted(u_int8_t fgHalt) +{ + rHaltCtrl.fgHalt = fgHalt; +} + +u_int8_t kalIsHalted(void) +{ + return rHaltCtrl.fgHalt; +} + + +#if 0 +void kalPerMonDump(IN struct GLUE_INFO *prGlueInfo) +{ + struct PERF_MONITOR *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + DBGLOG(SW4, WARN, "ulPerfMonFlag:0x%lx\n", + prPerMonitor->ulPerfMonFlag); + DBGLOG(SW4, WARN, "ulLastTxBytes:%d\n", + prPerMonitor->ulLastTxBytes); + DBGLOG(SW4, WARN, "ulLastRxBytes:%d\n", + prPerMonitor->ulLastRxBytes); + DBGLOG(SW4, WARN, "ulP2PLastTxBytes:%d\n", + prPerMonitor->ulP2PLastTxBytes); + DBGLOG(SW4, WARN, "ulP2PLastRxBytes:%d\n", + prPerMonitor->ulP2PLastRxBytes); + DBGLOG(SW4, WARN, "ulThroughput:%d\n", + prPerMonitor->ulThroughput); + DBGLOG(SW4, WARN, "u4UpdatePeriod:%d\n", + prPerMonitor->u4UpdatePeriod); + DBGLOG(SW4, WARN, "u4TarPerfLevel:%d\n", + prPerMonitor->u4TarPerfLevel); + DBGLOG(SW4, WARN, "u4CurrPerfLevel:%d\n", + prPerMonitor->u4CurrPerfLevel); + DBGLOG(SW4, WARN, "netStats tx_bytes:%d\n", + prGlueInfo->prDevHandler->stats.tx_bytes); + DBGLOG(SW4, WARN, "netStats tx_bytes:%d\n", + prGlueInfo->prDevHandler->stats.rx_bytes); + DBGLOG(SW4, WARN, "p2p netStats tx_bytes:%d\n", + prGlueInfo->prP2PInfo->prDevHandler->stats.tx_bytes); + DBGLOG(SW4, WARN, "p2p netStats tx_bytes:%d\n", + prGlueInfo->prP2PInfo->prDevHandler->stats.rx_bytes); +} +#endif + +#define PERF_UPDATE_PERIOD 1000 /* ms */ +#if (CFG_SUPPORT_PERF_IND == 1) +void kalPerfIndReset(IN struct ADAPTER *prAdapter) +{ + uint8_t i; + + for (i = 0; i < BSSID_NUM; i++) { + prAdapter->prGlueInfo->PerfIndCache.u4CurTxBytes[i] = 0; + prAdapter->prGlueInfo->PerfIndCache.u4CurRxBytes[i] = 0; + prAdapter->prGlueInfo->PerfIndCache.u2CurRxRate[i] = 0; + prAdapter->prGlueInfo->PerfIndCache.ucCurRxRCPI0[i] = 0; + prAdapter->prGlueInfo->PerfIndCache.ucCurRxRCPI1[i] = 0; + } +} /* kalPerfIndReset */ + +void kalSetPerfReport(IN struct ADAPTER *prAdapter) +{ + struct CMD_PERF_IND *prCmdPerfReport; + uint8_t i; + uint32_t u4CurrentTp = 0; + + DEBUGFUNC("kalSetPerfReport()"); + + prCmdPerfReport = (struct CMD_PERF_IND *) + cnmMemAlloc(prAdapter, RAM_TYPE_BUF, + sizeof(struct CMD_PERF_IND)); + + if (!prCmdPerfReport) { + DBGLOG(SW4, ERROR, + "cnmMemAlloc for kalSetPerfReport failed!\n"); + return; + } + kalMemZero(prCmdPerfReport, sizeof(struct CMD_PERF_IND)); + + prCmdPerfReport->ucCmdVer = 0; + prCmdPerfReport->u2CmdLen = sizeof(struct CMD_PERF_IND); + + prCmdPerfReport->u4VaildPeriod = PERF_UPDATE_PERIOD; + + for (i = 0; i < BSS_DEFAULT_NUM; i++) { + prCmdPerfReport->ulCurTxBytes[i] = + prAdapter->prGlueInfo->PerfIndCache.u4CurTxBytes[i]; + prCmdPerfReport->ulCurRxBytes[i] = + prAdapter->prGlueInfo->PerfIndCache.u4CurRxBytes[i]; + prCmdPerfReport->u2CurRxRate[i] = + prAdapter->prGlueInfo->PerfIndCache.u2CurRxRate[i]; + prCmdPerfReport->ucCurRxRCPI0[i] = + prAdapter->prGlueInfo->PerfIndCache.ucCurRxRCPI0[i]; + prCmdPerfReport->ucCurRxRCPI1[i] = + prAdapter->prGlueInfo->PerfIndCache.ucCurRxRCPI1[i]; + prCmdPerfReport->ucCurRxNss[i] = + prAdapter->prGlueInfo->PerfIndCache.ucCurRxNss[i]; + u4CurrentTp += (prCmdPerfReport->ulCurTxBytes[i] + + prCmdPerfReport->ulCurRxBytes[i]); + } + if (u4CurrentTp != 0) { + DBGLOG(SW4, TRACE, + "Total TP[%d] TX-Byte[%d][%d][%d][%d],RX-Byte[%d][%d][%d][%d]\n", + u4CurrentTp, + prCmdPerfReport->ulCurTxBytes[0], + prCmdPerfReport->ulCurTxBytes[1], + prCmdPerfReport->ulCurTxBytes[2], + prCmdPerfReport->ulCurTxBytes[3], + prCmdPerfReport->ulCurRxBytes[0], + prCmdPerfReport->ulCurRxBytes[1], + prCmdPerfReport->ulCurRxBytes[2], + prCmdPerfReport->ulCurRxBytes[3]); + DBGLOG(SW4, INFO, + "Rate[%d][%d][%d][%d] RCPI[%d][%d][%d][%d]\n", + prCmdPerfReport->u2CurRxRate[0], + prCmdPerfReport->u2CurRxRate[1], + prCmdPerfReport->u2CurRxRate[2], + prCmdPerfReport->u2CurRxRate[3], + prCmdPerfReport->ucCurRxRCPI0[0], + prCmdPerfReport->ucCurRxRCPI0[1], + prCmdPerfReport->ucCurRxRCPI0[2], + prCmdPerfReport->ucCurRxRCPI0[3]); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_PERF_IND, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(*prCmdPerfReport), + (uint8_t *) prCmdPerfReport, NULL, 0); + } + cnmMemFree(prAdapter, prCmdPerfReport); +} /* kalSetPerfReport */ +#endif + +inline int32_t kalPerMonInit(IN struct GLUE_INFO + *prGlueInfo) +{ + struct PERF_MONITOR *prPerMonitor; + struct net_device *prDevHandler = NULL; + uint8_t i = 0; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + DBGLOG(SW4, TRACE, "enter %s\n", __func__); + if (KAL_TEST_BIT(PERF_MON_RUNNING_BIT, + prPerMonitor->ulPerfMonFlag)) + DBGLOG(SW4, WARN, + "abnormal, perf monitor already running\n"); + KAL_CLR_BIT(PERF_MON_RUNNING_BIT, + prPerMonitor->ulPerfMonFlag); + KAL_CLR_BIT(PERF_MON_DISABLE_BIT, + prPerMonitor->ulPerfMonFlag); + KAL_SET_BIT(PERF_MON_STOP_BIT, prPerMonitor->ulPerfMonFlag); + prPerMonitor->u4UpdatePeriod = + prGlueInfo->prAdapter->rWifiVar.u4PerfMonUpdatePeriod; + cnmTimerInitTimerOption(prGlueInfo->prAdapter, + &prPerMonitor->rPerfMonTimer, + (PFN_MGMT_TIMEOUT_FUNC) kalPerMonHandler, + (unsigned long) NULL, + TIMER_WAKELOCK_NONE); + + /* sync data with netdev */ + GET_CURRENT_SYSTIME(&prPerMonitor->rLastUpdateTime); + for (i = 0; i < BSS_DEFAULT_NUM; i++) { + prDevHandler = wlanGetNetDev(prGlueInfo, i); + if (prDevHandler) { + prPerMonitor->ulLastTxBytes[i] = + prDevHandler->stats.tx_bytes; + prPerMonitor->ulLastRxBytes[i] = + prDevHandler->stats.tx_bytes; + prPerMonitor->ulLastTxPackets[i] = + prDevHandler->stats.tx_packets; + prPerMonitor->ulLastRxPackets[i] = + prDevHandler->stats.rx_packets; + } + } + +#if CFG_SUPPORT_PERF_IND + kalPerfIndReset(prGlueInfo->prAdapter); +#endif + /* enable rps on all cpu cores */ + kalSetRpsMap(prGlueInfo, 0xff); + KAL_SET_BIT(PERF_MON_INIT_BIT, prPerMonitor->ulPerfMonFlag); + DBGLOG(SW4, INFO, "exit %s\n", __func__); + return 0; +} + +inline int32_t kalPerMonDisable(IN struct GLUE_INFO + *prGlueInfo) +{ + struct PERF_MONITOR *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + + DBGLOG(SW4, INFO, "enter %s\n", __func__); + if (KAL_TEST_BIT(PERF_MON_RUNNING_BIT, + prPerMonitor->ulPerfMonFlag)) { + DBGLOG(SW4, TRACE, "need to stop before disable\n"); + kalPerMonStop(prGlueInfo); + } + KAL_SET_BIT(PERF_MON_DISABLE_BIT, + prPerMonitor->ulPerfMonFlag); + DBGLOG(SW4, TRACE, "exit %s\n", __func__); + return 0; +} + +inline int32_t kalPerMonEnable(IN struct GLUE_INFO + *prGlueInfo) +{ + struct PERF_MONITOR *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + + DBGLOG(SW4, INFO, "enter %s\n", __func__); + KAL_CLR_BIT(PERF_MON_DISABLE_BIT, + prPerMonitor->ulPerfMonFlag); + DBGLOG(SW4, TRACE, "exit %s\n", __func__); + return 0; +} + +inline int32_t kalPerMonStart(IN struct GLUE_INFO + *prGlueInfo) +{ + struct PERF_MONITOR *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + DBGLOG(SW4, TEMP, "enter %s\n", __func__); + + if (!wlan_perf_monitor_force_enable && + (wlan_fb_power_down + || prGlueInfo->fgIsInSuspendMode + )) + + return 0; + + if (KAL_TEST_BIT(PERF_MON_DISABLE_BIT, + prPerMonitor->ulPerfMonFlag) || + KAL_TEST_BIT(PERF_MON_RUNNING_BIT, + prPerMonitor->ulPerfMonFlag)) + return 0; + + prPerMonitor->u4CurrPerfLevel = 0; + prPerMonitor->u4TarPerfLevel = 0; + prPerMonitor->u4UpdatePeriod = + prGlueInfo->prAdapter->rWifiVar.u4PerfMonUpdatePeriod; + cnmTimerStartTimer(prGlueInfo->prAdapter, + &prPerMonitor->rPerfMonTimer, prPerMonitor->u4UpdatePeriod); + KAL_SET_BIT(PERF_MON_RUNNING_BIT, + prPerMonitor->ulPerfMonFlag); + KAL_CLR_BIT(PERF_MON_STOP_BIT, prPerMonitor->ulPerfMonFlag); + DBGLOG(SW4, INFO, "perf monitor started\n"); + return 0; +} + +inline int32_t kalPerMonStop(IN struct GLUE_INFO + *prGlueInfo) +{ + struct PERF_MONITOR *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + DBGLOG(SW4, TRACE, "enter %s\n", __func__); + + if (KAL_TEST_BIT(PERF_MON_DISABLE_BIT, + prPerMonitor->ulPerfMonFlag)) { + DBGLOG(SW4, TRACE, "perf monitor disabled\n"); + return 0; + } + + if (KAL_TEST_BIT(PERF_MON_STOP_BIT, + prPerMonitor->ulPerfMonFlag)) { + DBGLOG(SW4, TRACE, "perf monitor already stopped\n"); + return 0; + } + + KAL_SET_BIT(PERF_MON_STOP_BIT, prPerMonitor->ulPerfMonFlag); + if (KAL_TEST_BIT(PERF_MON_RUNNING_BIT, + prPerMonitor->ulPerfMonFlag)) { + cnmTimerStopTimer(prGlueInfo->prAdapter, + &prPerMonitor->rPerfMonTimer); + KAL_CLR_BIT(PERF_MON_RUNNING_BIT, + prPerMonitor->ulPerfMonFlag); + + prPerMonitor->u4CurrPerfLevel = 0; + prPerMonitor->u4TarPerfLevel = 0; + /*Cancel CPU performance mode request*/ + kalBoostCpu(prGlueInfo->prAdapter, + prPerMonitor->u4TarPerfLevel, + prGlueInfo->prAdapter->rWifiVar.u4BoostCpuTh); + } + DBGLOG(SW4, INFO, "perf monitor stopped\n"); + return 0; +} + +inline int32_t kalPerMonDestroy(IN struct GLUE_INFO + *prGlueInfo) +{ + struct PERF_MONITOR *prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + + kalPerMonDisable(prGlueInfo); + KAL_CLR_BIT(PERF_MON_INIT_BIT, prPerMonitor->ulPerfMonFlag); + DBGLOG(SW4, INFO, "exit %s\n", __func__); + return 0; +} + +static uint32_t kalPerMonUpdate(IN struct ADAPTER *prAdapter) +{ + struct PERF_MONITOR *perf = &prAdapter->rPerMonitor; + struct GLUE_INFO *glue = prAdapter->prGlueInfo; + struct BSS_INFO *bss; + struct net_device *ndev = NULL; + struct GL_HIF_INFO *hif = &glue->rHifInfo; + struct WIFI_LINK_QUALITY_INFO *lq = &prAdapter->rLinkQualityInfo; + OS_SYSTIME now, last; + int32_t period; + uint8_t i, j; + signed long txDiffBytes[BSS_DEFAULT_NUM], + rxDiffBytes[BSS_DEFAULT_NUM], + rxDiffPkts[BSS_DEFAULT_NUM], + txDiffPkts[BSS_DEFAULT_NUM]; + signed long lastTxBytes, lastRxBytes, lastTxPkts, lastRxPkts; + unsigned long currentTxBytes, currentRxBytes; + unsigned long currentTxPkts, currentRxPkts; + uint64_t throughput = 0; + char *buf = NULL, *head1, *head2, *head3, *head4; + char *pos = NULL, *end = NULL; + uint32_t slen; + + GET_CURRENT_SYSTIME(&now); + last = perf->rLastUpdateTime; + + if (!KAL_TEST_BIT(PERF_MON_INIT_BIT, perf->ulPerfMonFlag) || + !CHECK_FOR_TIMEOUT(now, last, + MSEC_TO_SYSTIME(perf->u4UpdatePeriod))) + return WLAN_STATUS_PENDING; + + perf->rLastUpdateTime = now; + + period = ((int32_t) now - (int32_t) last) * MSEC_PER_SEC / KAL_HZ; + if (period < 0) { + /* overflow should not happen */ + DBGLOG(SW4, WARN, "wrong period: now=%u, last=%u, period=%d\n", + now, last, period); + goto fail; + } + + for (i = 0; i < BSS_DEFAULT_NUM; i++) { + ndev = wlanGetNetDev(glue, i); + bss = GET_BSS_INFO_BY_INDEX(prAdapter, i); + if (IS_BSS_ALIVE(prAdapter, bss) && ndev) { + currentTxBytes = ndev->stats.tx_bytes; + currentRxBytes = ndev->stats.rx_bytes; + currentTxPkts = ndev->stats.tx_packets; + currentRxPkts = ndev->stats.rx_packets; + } else { + currentTxBytes = perf->ulLastTxBytes[i]; + currentRxBytes = perf->ulLastRxBytes[i]; + currentTxPkts = perf->ulLastTxPackets[i]; + currentRxPkts = perf->ulLastRxPackets[i]; + } + lastTxBytes = (signed long) perf->ulLastTxBytes[i]; + lastRxBytes = (signed long) perf->ulLastRxBytes[i]; + perf->ulLastTxBytes[i] = currentTxBytes; + perf->ulLastRxBytes[i] = currentRxBytes; + txDiffBytes[i] = (signed long) currentTxBytes - lastTxBytes; + rxDiffBytes[i] = (signed long) currentRxBytes - lastRxBytes; + + lastTxPkts = (signed long) perf->ulLastTxPackets[i]; + lastRxPkts = (signed long) perf->ulLastRxPackets[i]; + perf->ulLastTxPackets[i] = currentTxPkts; + perf->ulLastRxPackets[i] = currentRxPkts; + txDiffPkts[i] = (signed long) currentTxPkts - lastTxPkts; + rxDiffPkts[i] = (signed long) currentRxPkts - lastRxPkts; + + if (txDiffBytes[i] < 0 || rxDiffBytes[i] < 0) { + /* overflow should not happen */ + DBGLOG(SW4, WARN, + "[i]wrong bytes: tx[%lu][%ld][%ld], rx[%lu][%ld][%ld],\n", + i, currentTxBytes, lastTxBytes, txDiffBytes[i], + currentRxBytes, lastRxBytes, rxDiffBytes[i]); + goto fail; + } + + /* Divsion first to avoid overflow */ + perf->ulTxTp[i] = (txDiffBytes[i] / period) * MSEC_PER_SEC; + perf->ulRxTp[i] = (rxDiffBytes[i] / period) * MSEC_PER_SEC; + + throughput += txDiffBytes[i] + rxDiffBytes[i]; + } + + perf->ulThroughput = throughput * MSEC_PER_SEC; + do_div(perf->ulThroughput, period); + perf->ulThroughput <<= 3; + + /* The length should include + * 1. "[%ld:%ld:%ld:%ld]" for each bss, %ld range is + * [-2147483647, +2147483647] + * 2. "[%d:...:%d]" for pending frame num, %d range is [-32767, 32767] + * 3. "[%u]" for each TX ring, %u range is [0, 65536] + * 4. ["%lu:%lu:%lu:%lu] dropped packets by each ndev, "%lu" range is + * [0, 4294967295] + */ + slen = (11 * 4 + 5) * BSS_DEFAULT_NUM + 1 + + (6 * CFG_MAX_TXQ_NUM + 2 - 1) * MAX_BSSID_NUM + 1 + + (5 + 2) * NUM_OF_TX_RING + 1 + + (10 * 4 + 5) * BSS_DEFAULT_NUM + 1; + pos = buf = kalMemAlloc(slen, VIR_MEM_TYPE); + if (pos == NULL) { + DBGLOG(SW4, INFO, "Can't allocate memory\n"); + return WLAN_STATUS_RESOURCES; + } + memset(buf, 0, slen); + end = buf + slen; + head1 = pos; + for (i = 0; i < BSS_DEFAULT_NUM; ++i) { + pos += kalSnprintf(pos, end - pos, "[%ld:%ld:%ld:%ld]", + txDiffBytes[i], txDiffPkts[i], + rxDiffBytes[i], rxDiffPkts[i]); + } + pos++; + head2 = pos; + for (i = 0; i < MAX_BSSID_NUM; ++i) { + pos += kalSnprintf(pos, end - pos, "["); + for (j = 0; j < CFG_MAX_TXQ_NUM - 1; ++j) { + pos += kalSnprintf(pos, end - pos, "%d:", + glue->ai4TxPendingFrameNumPerQueue[i][j]); + } + pos += kalSnprintf(pos, end - pos, "%d]", + glue->ai4TxPendingFrameNumPerQueue[i][j]); + } + pos++; + head3 = pos; + for (i = 0; i < NUM_OF_TX_RING; ++i) { + pos += kalSnprintf(pos, end - pos, "[%u]", + hif->TxRing[i].u4UsedCnt); + } + pos++; + head4 = pos; + for (i = 0; i < BSS_DEFAULT_NUM; ++i) { + ndev = wlanGetNetDev(glue, i); + if (ndev) { + pos += kalSnprintf(pos, end - pos, "[%lu:%lu:%lu:%lu]", + ndev->stats.tx_dropped, + atomic_long_read(&ndev->tx_dropped), + ndev->stats.rx_dropped, + atomic_long_read(&ndev->rx_dropped)); + } + } + +#define TEMP_LOG_TEMPLATE \ + "<%dms> Tput: %llu(%lu.%03lumbps) %s Pending: %d/%d %s Used: " \ + "%u/%d/%d %s LQ[%lu:%lu:%lu] Drop: %s lv:%u th:%u fg:0x%lx\n" + DBGLOG(SW4, INFO, TEMP_LOG_TEMPLATE, + period, perf->ulThroughput, + (unsigned long) (perf->ulThroughput >> 20), + (unsigned long) ((perf->ulThroughput >> 10) & BITS(0, 9)), + head1, GLUE_GET_REF_CNT(glue->i4TxPendingFrameNum), + prAdapter->rWifiVar.u4NetifStopTh, head2, + hif->rTokenInfo.u4UsedCnt, HIF_TX_MSDU_TOKEN_NUM, + TX_RING_SIZE, head3, lq->u8TxTotalCount, lq->u8RxTotalCount, + lq->u8DiffIdleSlotCount, head4, perf->u4CurrPerfLevel, + prAdapter->rWifiVar.u4BoostCpuTh, + perf->ulPerfMonFlag); +#undef TEMP_LOG_TEMPLATE + + kalTraceEvent("Tput: %lu.%03lumbps", + (unsigned long) (perf->ulThroughput >> 20), + (unsigned long) ((perf->ulThroughput >> 10) & BITS(0, 9))); + kalMemFree(buf, VIR_MEM_TYPE, slen); + return WLAN_STATUS_SUCCESS; +fail: + return WLAN_STATUS_FAILURE; +} + +void kalPerMonHandler(IN struct ADAPTER *prAdapter, + unsigned long ulParam) +{ + /*Calculate current throughput*/ + struct PERF_MONITOR *prPerMonitor; + uint32_t u4Idx = 0; + uint8_t i = 0; + bool keep_alive = FALSE; + struct net_device *prDevHandler = NULL; + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; +#if CFG_SUPPORT_PERF_IND || CFG_SUPPORT_DATA_STALL + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; +#endif + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) + return; + + prPerMonitor = &prAdapter->rPerMonitor; + DBGLOG(SW4, TRACE, "enter kalPerMonHandler\n"); + +#if (CFG_SUPPORT_PERF_IND == 1) + if (prWifiVar->fgPerfIndicatorEn) + kalSetPerfReport(prAdapter); + + kalPerfIndReset(prAdapter); +#endif + for (i = 0; i < BSS_DEFAULT_NUM; i++) { + struct BSS_INFO *prBssInfo; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, i); + prDevHandler = wlanGetNetDev(prGlueInfo, i); + if (IS_BSS_ALIVE(prAdapter, prBssInfo) && prDevHandler) { + keep_alive |= netif_carrier_ok(prDevHandler); + } + } + +#if CFG_SUPPORT_DATA_STALL + /* test mode event */ + if (prWifiVar->u4ReportEventInterval == 0) + KAL_REPORT_ERROR_EVENT(prAdapter, + EVENT_TEST_MODE, 0, 0, FALSE); +#endif + prPerMonitor->u4TarPerfLevel = PERF_MON_TP_MAX_THRESHOLD; + for (u4Idx = 0; u4Idx < PERF_MON_TP_MAX_THRESHOLD; u4Idx++) { + if ((prPerMonitor->ulThroughput >> 20) < + prAdapter->rWifiVar.u4PerfMonTpTh[u4Idx]) { + prPerMonitor->u4TarPerfLevel = u4Idx; + break; + } + } + + if (!wlan_perf_monitor_force_enable && + (wlan_fb_power_down || + prGlueInfo->fgIsInSuspendMode || + !keep_alive)) + kalPerMonStop(prGlueInfo); + else { + if (kalCheckTputLoad(prAdapter, + prPerMonitor->u4CurrPerfLevel, + prPerMonitor->u4TarPerfLevel, + GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum), + GLUE_GET_REF_CNT(prPerMonitor->u4UsedCnt))) { + + DBGLOG(SW4, INFO, + "PerfMon overloading total:%3lu.%03lu mbps lv:%u th:%u fg:0x%lx Pending[%d], Used[%d]\n", + (unsigned long) (prPerMonitor->ulThroughput >> 20), + (unsigned long) ((prPerMonitor->ulThroughput >> 10) + & BITS(0, 9)), + prPerMonitor->u4TarPerfLevel, + prAdapter->rWifiVar.u4BoostCpuTh, + prPerMonitor->ulPerfMonFlag, + GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum), + GLUE_GET_REF_CNT(prPerMonitor->u4UsedCnt)); + + /* boost current level due to overloading */ + kalBoostCpu(prAdapter, + prPerMonitor->u4TarPerfLevel, + prPerMonitor->u4TarPerfLevel); + } else if ((prPerMonitor->u4TarPerfLevel != + prPerMonitor->u4CurrPerfLevel) && + (prAdapter->rWifiVar.u4BoostCpuTh < + PERF_MON_TP_MAX_THRESHOLD)) { + + DBGLOG(SW4, INFO, + "PerfMon total:%3lu.%03lu mbps lv:%u th:%u fg:0x%lx\n", + (unsigned long) (prPerMonitor->ulThroughput >> 20), + (unsigned long) ((prPerMonitor->ulThroughput >> 10) + & BITS(0, 9)), + prPerMonitor->u4TarPerfLevel, + prAdapter->rWifiVar.u4BoostCpuTh, + prPerMonitor->ulPerfMonFlag); + + kalBoostCpu(prAdapter, prPerMonitor->u4TarPerfLevel, + prAdapter->rWifiVar.u4BoostCpuTh); + } + + prPerMonitor->u4UpdatePeriod = + prAdapter->rWifiVar.u4PerfMonUpdatePeriod; + + cnmTimerStartTimer(prGlueInfo->prAdapter, + &prPerMonitor->rPerfMonTimer, + prPerMonitor->u4UpdatePeriod); + + } + prPerMonitor->u4CurrPerfLevel = + prPerMonitor->u4TarPerfLevel; + +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + prAdapter->u4LinkQualityCounter++; + if ((prAdapter->u4LinkQualityCounter % + CFG_LQ_MONITOR_FREQUENCY) == 0) { + prAdapter->u4LinkQualityCounter = 0; + if (prGlueInfo->fgIsInSuspendMode) + DBGLOG(SW4, TRACE, + "Skip wlanLinkQualityMonitor due to in suspend mode\n"); + else + wlanLinkQualityMonitor(prGlueInfo, FALSE); + } +#endif /* CFG_SUPPORT_LINK_QUALITY_MONITOR */ + + /* check tx hang */ + prAdapter->u4HifChkFlag |= HIF_CHK_TX_HANG; + kalSetHifDbgEvent(prAdapter->prGlueInfo); + + DBGLOG(SW4, TRACE, "exit kalPerMonHandler\n"); +} + +uint32_t kalPerMonGetInfo(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, IN uint32_t u4Max) +{ + struct PERF_MONITOR *prPerMonitor; + uint32_t u4Len = 0; + unsigned long ulWlanTxTpInBits, ulWlanRxTpInBits, + ulP2PTxTpInBits, ulP2PRxTpInBits; + + prPerMonitor = &prAdapter->rPerMonitor; + + ulWlanTxTpInBits = prPerMonitor->ulTxTp[0] << 3; + ulWlanRxTpInBits = prPerMonitor->ulRxTp[0] << 3; + ulP2PTxTpInBits = prPerMonitor->ulTxTp[1] << 3; + ulP2PRxTpInBits = prPerMonitor->ulRxTp[1] << 3; + + LOGBUF(pucBuf, u4Max, u4Len, + "\nWi-Fi Throughput (update period %ums):\n", + prPerMonitor->u4UpdatePeriod); + + LOGBUF(pucBuf, u4Max, u4Len, + "wlan Tx: %3lu.%03lu mbps, Rx %3lu.%03lu mbps\n", + (ulWlanTxTpInBits >> 20), + ((ulWlanTxTpInBits >> 10) & BITS(0, 9)), + (ulWlanRxTpInBits >> 20), + ((ulWlanRxTpInBits >> 10) & BITS(0, 9))); + + LOGBUF(pucBuf, u4Max, u4Len, + "p2p Tx: %3lu.%03lu mbps, Rx %3lu.%03lu mbps\n", + (ulP2PTxTpInBits >> 20), ((ulP2PTxTpInBits >> 10) & BITS(0, + 9)), + (ulP2PRxTpInBits >> 20), ((ulP2PRxTpInBits >> 10) & BITS(0, + 9))); + + LOGBUF(pucBuf, u4Max, u4Len, "Total: %3lu.%03lu mbps\n", + (prPerMonitor->ulThroughput >> 20), + ((prPerMonitor->ulThroughput >> 10) & BITS(0, 9))); + + LOGBUF(pucBuf, u4Max, u4Len, + "Performance level: %u threshold: %u flag: 0x%lx\n", + prPerMonitor->u4CurrPerfLevel, + prAdapter->rWifiVar.u4BoostCpuTh, + prPerMonitor->ulPerfMonFlag); + + return u4Len; +} + +int32_t __weak kalBoostCpu(IN struct ADAPTER *prAdapter, + IN uint32_t u4TarPerfLevel, IN uint32_t u4BoostCpuTh) +{ + DBGLOG(SW4, INFO, "enter kalBoostCpu\n"); + return 0; +} + +uint32_t __weak kalGetCpuBoostThreshold(void) +{ + DBGLOG(SW4, WARN, "enter kalGetCpuBoostThreshold\n"); + /* 1, stands for 20Mbps */ + return 1; +} + +int32_t __weak kalSetCpuNumFreq(uint32_t u4CoreNum, + uint32_t u4Freq) +{ + DBGLOG(SW4, INFO, + "enter weak kalSetCpuNumFreq, u4CoreNum:%d, urFreq:%d\n", + u4CoreNum, u4Freq); + return 0; +} + +int32_t __weak kalGetFwFlavor(uint8_t *flavor) +{ + DBGLOG(SW4, INFO, "NO firmware flavor build.\n"); + return 0; +} + +int32_t __weak kalGetConnsysVerId(void) +{ + DBGLOG(SW4, WARN, "NO CONNSYS version ID.\n"); + return 0; +} + +void __weak kalSetEmiMpuProtection(phys_addr_t emiPhyBase, bool enable) +{ + DBGLOG(SW4, WARN, "EMI MPU function is not defined\n"); +} + +void __weak kalSetDrvEmiMpuProtection(phys_addr_t emiPhyBase, uint32_t offset, + uint32_t size) +{ + DBGLOG(SW4, WARN, "DRV EMI MPU function is not defined\n"); +} + +int32_t __weak kalCheckTputLoad(IN struct ADAPTER *prAdapter, + IN uint32_t u4CurrPerfLevel, + IN uint32_t u4TarPerfLevel, + IN int32_t i4Pending, + IN uint32_t u4Used) +{ + DBGLOG(SW4, TRACE, "enter kalCheckTputLoad\n"); + return FALSE; +} + +/* mimic store_rps_map as net-sysfs.c does */ +int wlan_set_rps_map(struct netdev_rx_queue *queue, unsigned long rps_value) +{ +#if KERNEL_VERSION(4, 14, 0) <= CFG80211_VERSION_CODE + struct rps_map *old_map, *map; + cpumask_var_t mask; + int cpu, i; + static DEFINE_MUTEX(rps_map_mutex); + + if (!alloc_cpumask_var(&mask, GFP_KERNEL)) + return -ENOMEM; + + *cpumask_bits(mask) = rps_value; + map = kzalloc(max_t(unsigned int, + RPS_MAP_SIZE(cpumask_weight(mask)), L1_CACHE_BYTES), + GFP_KERNEL); + if (!map) { + free_cpumask_var(mask); + return -ENOMEM; + } + + i = 0; + for_each_cpu_and(cpu, mask, cpu_online_mask) + map->cpus[i++] = cpu; + + if (i) { + map->len = i; + } else { + kfree(map); + map = NULL; + } + + mutex_lock(&rps_map_mutex); + old_map = rcu_dereference_protected(queue->rps_map, + mutex_is_locked(&rps_map_mutex)); + rcu_assign_pointer(queue->rps_map, map); + if (map) +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + static_branch_inc(&rps_needed); +#else + static_key_slow_inc(&rps_needed); +#endif + if (old_map) +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE + static_branch_dec(&rps_needed); +#else + static_key_slow_dec(&rps_needed); +#endif + mutex_unlock(&rps_map_mutex); + + if (old_map) + kfree_rcu(old_map, rcu); + free_cpumask_var(mask); + + return 0; +#else + return 0; +#endif +} + +void kalSetRpsMap(IN struct GLUE_INFO *glue, IN unsigned long value) +{ + int32_t i = 0, j = 0; + struct net_device *dev = NULL; + + for (i = 0; i < BSS_DEFAULT_NUM; i++) { + dev = wlanGetNetDev(glue, i); + if (dev) { + for (j = 0; j < dev->real_num_rx_queues; ++j) + wlan_set_rps_map(&dev->_rx[j], value); + } + } +} + +int32_t kalPerMonSetForceEnableFlag(uint8_t uFlag) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) + wlan_fb_notifier_priv_data; + + wlan_perf_monitor_force_enable = uFlag == 0 ? FALSE : TRUE; + DBGLOG(SW4, INFO, + "uFlag:%d, wlan_perf_monitor_ctrl_flag:%d\n", uFlag, + wlan_perf_monitor_force_enable); + + if (wlan_perf_monitor_force_enable && prGlueInfo + && !kalIsHalted()) + kalPerMonEnable(prGlueInfo); + + return 0; +} + +static int wlan_fb_notifier_callback(struct notifier_block + *self, unsigned long event, void *data) +{ + struct fb_event *evdata = data; + int32_t blank = 0; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) + wlan_fb_notifier_priv_data; + + /* If we aren't interested in this event, skip it immediately ... */ + if ((event != FB_EVENT_BLANK) || !prGlueInfo) + return 0; + + if (kalHaltTryLock()) + return 0; + + if (kalIsHalted()) { + kalHaltUnlock(); + return 0; + } + + blank = *(int32_t *)evdata->data; + + switch (blank) { + case FB_BLANK_UNBLANK: + kalPerMonEnable(prGlueInfo); + wlan_fb_power_down = FALSE; + break; + case FB_BLANK_POWERDOWN: + wlan_fb_power_down = TRUE; + if (!wlan_perf_monitor_force_enable) + kalPerMonDisable(prGlueInfo); + break; + default: + break; + } + + kalHaltUnlock(); + return 0; +} + +int32_t kalFbNotifierReg(IN struct GLUE_INFO *prGlueInfo) +{ + int32_t i4Ret; + + wlan_fb_notifier_priv_data = prGlueInfo; + wlan_fb_notifier.notifier_call = wlan_fb_notifier_callback; + + i4Ret = fb_register_client(&wlan_fb_notifier); + if (i4Ret) + DBGLOG(SW4, WARN, "Register wlan_fb_notifier failed:%d\n", + i4Ret); + else + DBGLOG(SW4, TRACE, "Register wlan_fb_notifier succeed\n"); + return i4Ret; +} + +void kalFbNotifierUnReg(void) +{ + fb_unregister_client(&wlan_fb_notifier); + wlan_fb_notifier_priv_data = NULL; +} + +#if CFG_SUPPORT_DFS +void kalIndicateChannelSwitch(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_CHNL_EXT eSco, + IN uint8_t ucChannelNum) +{ + struct cfg80211_chan_def chandef; + struct ieee80211_channel *prChannel = NULL; + enum nl80211_channel_type rChannelType; + + if (ucChannelNum <= 14) { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, + KAL_BAND_2GHZ)); + } else { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, + KAL_BAND_5GHZ)); + } + + if (!prChannel) { + DBGLOG(REQ, ERROR, "ieee80211_get_channel fail!\n"); + return; + } + + switch (eSco) { + case CHNL_EXT_SCN: + rChannelType = NL80211_CHAN_NO_HT; + break; + + case CHNL_EXT_SCA: + rChannelType = NL80211_CHAN_HT40MINUS; + break; + + case CHNL_EXT_SCB: + rChannelType = NL80211_CHAN_HT40PLUS; + break; + + case CHNL_EXT_RES: + default: + rChannelType = NL80211_CHAN_HT20; + break; + } + + DBGLOG(REQ, STATE, "DFS channel switch to %d\n", ucChannelNum); + + cfg80211_chandef_create(&chandef, prChannel, rChannelType); + cfg80211_ch_switch_notify(prGlueInfo->prDevHandler, &chandef); +} +#endif + +void kalInitDevWakeup(struct ADAPTER *prAdapter, struct device *prDev) +{ + /* + * The remote wakeup function will be disabled after + * first time resume, we need to call device_init_wakeup() + * to notify usbcore that we support wakeup function, + * so usbcore will re-enable our remote wakeup function + * before entering suspend. + */ + if (prAdapter->rWifiVar.ucWow) + device_init_wakeup(prDev, TRUE); +} + +u_int8_t kalIsOuiMask(const uint8_t pucMacAddrMask[MAC_ADDR_LEN]) +{ + return (pucMacAddrMask[0] == 0xFF && + pucMacAddrMask[1] == 0xFF && + pucMacAddrMask[2] == 0xFF); +} + +u_int8_t kalIsValidMacAddr(const uint8_t *addr) +{ + return (addr != NULL) && is_valid_ether_addr(addr); +} + +#if (KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE) +u_int8_t kalParseRandomMac(const struct net_device *ndev, + uint8_t *pucMacAddr, uint8_t *pucMacAddrMask, + uint8_t *pucRandomMac) +{ + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = NULL; + struct ADAPTER *prAdapter = NULL; + uint8_t ucBssIndex; + struct BSS_INFO *prBssInfo; + uint8_t ucMacAddr[MAC_ADDR_LEN]; + + if (!ndev) { + log_dbg(SCN, ERROR, "Invalid net device\n"); + return FALSE; + } + + prNetDevPrivate = + (struct NETDEV_PRIVATE_GLUE_INFO *) netdev_priv(ndev); + + if (!prNetDevPrivate || !(prNetDevPrivate->prGlueInfo) + || !(prNetDevPrivate->prGlueInfo->prAdapter)) { + log_dbg(SCN, ERROR, "Invalid private param\n"); + return FALSE; + } + + prAdapter = prNetDevPrivate->prGlueInfo->prAdapter; + ucBssIndex = prNetDevPrivate->ucBssIdx; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (!prBssInfo) { + log_dbg(SCN, WARN, "Invalid bss info (ind=%u)\n", ucBssIndex); + return FALSE; + } + + if (pucMacAddr) + COPY_MAC_ADDR(ucMacAddr, pucMacAddr); + else + eth_zero_addr(ucMacAddr); + + /* Randomize all 6-bytes MAC. + * Not to keep first 3-bytes MAC OUI to be constant. + */ + get_random_mask_addr(pucRandomMac, ucMacAddr, pucMacAddrMask); + + return TRUE; +} + +u_int8_t kalScanParseRandomMac(const struct net_device *ndev, + const struct cfg80211_scan_request *request, uint8_t *pucRandomMac) +{ + uint8_t ucMacAddr[MAC_ADDR_LEN]; + uint8_t ucMacAddrMask[MAC_ADDR_LEN]; + + ASSERT(request); + ASSERT(pucRandomMac); + + if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) { + log_dbg(SCN, TRACE, "Scan random mac is not set\n"); + return FALSE; + } +#if KERNEL_VERSION(4, 10, 0) <= CFG80211_VERSION_CODE + { + if (kalIsValidMacAddr(request->bssid)) { + COPY_MAC_ADDR(pucRandomMac, request->bssid); + log_dbg(SCN, INFO, "random mac=" MACSTR "\n", + MAC2STR(pucRandomMac)); + return TRUE; + } + } +#endif + COPY_MAC_ADDR(ucMacAddr, request->mac_addr); + COPY_MAC_ADDR(ucMacAddrMask, request->mac_addr_mask); + + return kalParseRandomMac(ndev, ucMacAddr, ucMacAddrMask, pucRandomMac); +} + +u_int8_t kalSchedScanParseRandomMac(const struct net_device *ndev, + const struct cfg80211_sched_scan_request *request, + uint8_t *pucRandomMac, uint8_t *pucRandomMacMask) +{ + uint8_t ucMacAddr[MAC_ADDR_LEN]; + + ASSERT(request); + ASSERT(pucRandomMac); + ASSERT(pucRandomMacMask); + + if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) { + log_dbg(SCN, TRACE, "Scan random mac is not set\n"); + return FALSE; + } + COPY_MAC_ADDR(ucMacAddr, request->mac_addr); + COPY_MAC_ADDR(pucRandomMacMask, request->mac_addr_mask); + + return kalParseRandomMac(ndev, ucMacAddr, + pucRandomMacMask, pucRandomMac); +} +#else /* if (KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE) */ +u_int8_t kalScanParseRandomMac(const struct net_device *ndev, + const struct cfg80211_scan_request *request, uint8_t *pucRandomMac) +{ + return FALSE; +} + +u_int8_t kalSchedScanParseRandomMac(const struct net_device *ndev, + const struct cfg80211_sched_scan_request *request, + uint8_t *pucRandomMac, uint8_t *pucRandomMacMask) +{ + return FALSE; +} +#endif + +void kalScanReqLog(struct cfg80211_scan_request *request) +{ + char *strbuf = NULL, *pos = NULL, *end = NULL; + uint32_t slen = 0; + int i, snum, cnum; + + snum = min_t(int, request->n_ssids, SCN_SSID_MAX_NUM + 1); + cnum = min_t(u32, request->n_channels, MAXIMUM_OPERATION_CHANNEL_LIST); + + for (i = 0; i < snum; ++i) { + if (request->ssids[i].ssid_len > 0) + slen += request->ssids[i].ssid_len + 1; + } + + /* The length should be added 11 + 15 + 8 + 1 for the format + * "n_ssids=%d:" and " n_channels=%u:" and 2 " ..." and null byte. + */ + slen += 35 + 4 * cnum; + pos = strbuf = kalMemAlloc(slen, VIR_MEM_TYPE); + if (strbuf == NULL) { + scanlog_dbg(LOG_SCAN_REQ_K2D, INFO, "Can't allocate memory\n"); + return; + } + end = strbuf + slen; + + pos += kalSnprintf(pos, end - pos, + "n_ssids=%d:", request->n_ssids % 100); + for (i = 0; i < snum; ++i) { + uint8_t len = request->ssids[i].ssid_len; + char ssid[PARAM_MAX_LEN_SSID + 1] = {0}; + + if (len == 0) + continue; + kalStrnCpy(ssid, request->ssids[i].ssid, sizeof(ssid) - 1); + ssid[sizeof(ssid) - 1] = '\0'; + pos += kalSnprintf(pos, end - pos, " %s", ssid); + } + if (snum < request->n_ssids) + pos += kalSnprintf(pos, end - pos, "%s", " ..."); + + pos += kalSnprintf(pos, end - pos, " n_channels=%u:", + request->n_channels % 100); + for (i = 0; i < cnum; ++i) { + pos += kalSnprintf(pos, end - pos, " %u", + request->channels[i]->hw_value % 1000); + } + if (cnum < request->n_channels) + pos += kalSnprintf(pos, end - pos, "%s", " ..."); + +#if (KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE) + scanlog_dbg(LOG_SCAN_REQ_K2D, INFO, "Scan flags=0x%x [mac]addr=" + MACSTR " mask=" MACSTR " %s\n", + request->flags, + MAC2STR(request->mac_addr), + MAC2STR(request->mac_addr_mask), strbuf); +#else + scanlog_dbg(LOG_SCAN_REQ_K2D, INFO, "Scan flags=0x%x %s\n", + request->flags, strbuf); +#endif + + kalMemFree(strbuf, VIR_MEM_TYPE, slen); +} + +void kalScanResultLog(struct ADAPTER *prAdapter, struct ieee80211_mgmt *mgmt) +{ + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BSSLIST_CFG); + scanLogCacheAddBSS( + &(prAdapter->rWifiVar.rScanInfo.rScanLogCache.rBSSListCFG), + prAdapter->rWifiVar.rScanInfo.rScanLogCache.arBSSListBufCFG, + LOG_SCAN_RESULT_D2K, + mgmt->bssid, + mgmt->seq_ctrl); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BSSLIST_CFG); +} + +void kalScanLogCacheFlushBSS(struct ADAPTER *prAdapter, + const uint16_t logBufLen) +{ + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BSSLIST_CFG); + scanLogCacheFlushBSS( + &(prAdapter->rWifiVar.rScanInfo.rScanLogCache.rBSSListCFG), + LOG_SCAN_DONE_D2K); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BSSLIST_CFG); +} + + +u_int8_t +kalChannelScoSwitch(IN enum nl80211_channel_type channel_type, + IN enum ENUM_CHNL_EXT *prChnlSco) +{ + u_int8_t fgIsValid = FALSE; + + do { + 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; +} + +u_int8_t +kalChannelFormatSwitch(IN struct cfg80211_chan_def *channel_def, + IN struct ieee80211_channel *channel, + IN struct RF_CHANNEL_INFO *prRfChnlInfo) +{ + u_int8_t fgIsValid = FALSE; + + do { + if (channel == NULL) + break; + + DBGLOG(P2P, INFO, "switch channel band: %d, freq: %d\n", + channel->band, channel->center_freq); + + if (prRfChnlInfo) { + prRfChnlInfo->ucChannelNum = + nicFreq2ChannelNum(channel->center_freq * 1000); + + switch (channel->band) { + case KAL_BAND_2GHZ: + prRfChnlInfo->eBand = BAND_2G4; + break; + case KAL_BAND_5GHZ: + prRfChnlInfo->eBand = BAND_5G; + break; + default: + prRfChnlInfo->eBand = BAND_2G4; + break; + } + } + + if (channel_def && prRfChnlInfo) { + switch (channel_def->width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + prRfChnlInfo->ucChnlBw = MAX_BW_20MHZ; + break; + case NL80211_CHAN_WIDTH_40: + prRfChnlInfo->ucChnlBw = MAX_BW_40MHZ; + break; + case NL80211_CHAN_WIDTH_80: + prRfChnlInfo->ucChnlBw = MAX_BW_80MHZ; + break; + case NL80211_CHAN_WIDTH_80P80: + prRfChnlInfo->ucChnlBw = MAX_BW_80_80_MHZ; + break; + case NL80211_CHAN_WIDTH_160: + prRfChnlInfo->ucChnlBw = MAX_BW_160MHZ; + break; + default: + prRfChnlInfo->ucChnlBw = MAX_BW_20MHZ; + break; + } + prRfChnlInfo->u2PriChnlFreq = channel->center_freq; + prRfChnlInfo->u4CenterFreq1 = channel_def->center_freq1; + prRfChnlInfo->u4CenterFreq2 = channel_def->center_freq2; + } + + fgIsValid = TRUE; + } while (FALSE); + + return fgIsValid; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Notify kernel to remove/unlink bss. + * + * \param[in] prGlueInfo Pointer of GLUE Data Structure + * \param[in] prBssDesc Pointer of BSS_DESC we want to remove + * + */ +/*----------------------------------------------------------------------------*/ +void kalRemoveBss(struct GLUE_INFO *prGlueInfo, + uint8_t aucBSSID[], + uint8_t ucChannelNum, + enum ENUM_BAND eBand) +{ + struct cfg80211_bss *bss = NULL; + struct ieee80211_channel *prChannel = NULL; + + if (ucChannelNum <= 14) { + prChannel = ieee80211_get_channel( + priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency( + ucChannelNum, + KAL_BAND_2GHZ) + ); + } else { + prChannel = ieee80211_get_channel( + priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency( + ucChannelNum, + KAL_BAND_5GHZ) + ); + } + +#if (KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE) + bss = cfg80211_get_bss(priv_to_wiphy(prGlueInfo), + prChannel, /* channel */ + aucBSSID, + NULL, /* ssid */ + 0, /* ssid length */ + IEEE80211_BSS_TYPE_ESS, + IEEE80211_PRIVACY_ANY); +#else + bss = cfg80211_get_bss(priv_to_wiphy(prGlueInfo), + prChannel, /* channel */ + aucBSSID, + NULL, /* ssid */ + 0, /* ssid length */ + WLAN_CAPABILITY_ESS, + WLAN_CAPABILITY_ESS); +#endif + + if (bss != NULL) { + cfg80211_unlink_bss(priv_to_wiphy(prGlueInfo), bss); + cfg80211_put_bss(priv_to_wiphy(prGlueInfo), bss); + } +} + +int kalMaskMemCmp(const void *cs, const void *ct, + const void *mask, size_t count) +{ + const uint8_t *su1, *su2, *su3; + int res = 0; + + for (su1 = cs, su2 = ct, su3 = mask; + count > 0; ++su1, ++su2, ++su3, count--) { + if (mask != NULL) + res = ((*su1)&(*su3)) - ((*su2)&(*su3)); + else + res = (*su1) - (*su2); + if (res != 0) + break; + } + return res; +} + +/* + * This func is mainly from bionic's strtok.c + */ +int8_t *strtok_r(int8_t *s, const int8_t *delim, int8_t **last) +{ + char *spanp; + int c, sc; + char *tok; + + + if (s == NULL) { + s = *last; + if (s == 0) + return NULL; + } +cont: + c = *s++; + for (spanp = (char *)delim; (sc = *spanp++) != 0;) { + if (c == sc) + goto cont; + } + + if (c == 0) { /* no non-delimiter characters */ + *last = NULL; + return NULL; + } + tok = s - 1; + + for (;;) { + c = *s++; + spanp = (char *)delim; + do { + sc = *spanp++; + if (sc == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + *last = s; + return tok; + } + } while (sc != 0); + } +} + +int8_t atoi(uint8_t ch) +{ + if (ch >= 'a' && ch <= 'f') + return ch - 87; + else if (ch >= 'A' && ch <= 'F') + return ch - 55; + else if (ch >= '0' && ch <= '9') + return ch - 48; + + return 0; +} + +#if CFG_SUPPORT_WPA3 +int kalExternalAuthRequest(IN struct ADAPTER *prAdapter, + IN uint8_t uBssIndex) +{ + struct cfg80211_external_auth_params params; + struct AIS_FSM_INFO *prAisFsmInfo = NULL; + struct BSS_DESC *prBssDesc = NULL; + struct net_device *ndev = NULL; + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + + prAisFsmInfo = aisGetAisFsmInfo(prAdapter, uBssIndex); + if (!prAisFsmInfo) { + DBGLOG(SAA, WARN, + "SAE auth failed with NULL prAisFsmInfo\n"); + return WLAN_STATUS_INVALID_DATA; + } + + prBssDesc = prAisFsmInfo->prTargetBssDesc; + if (!prBssDesc) { + DBGLOG(SAA, WARN, + "SAE auth failed without prTargetBssDesc\n"); + return WLAN_STATUS_INVALID_DATA; + } + + ndev = wlanGetNetDev(prGlueInfo, uBssIndex); + params.action = NL80211_EXTERNAL_AUTH_START; + COPY_MAC_ADDR(params.bssid, prBssDesc->aucBSSID); + COPY_SSID(params.ssid.ssid, params.ssid.ssid_len, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + params.key_mgmt_suite = RSN_AKM_SUITE_SAE; + DBGLOG(AIS, INFO, "[WPA3] "MACSTR" %s %d %d %02x-%02x-%02x-%02x", + MAC2STR(params.bssid), params.ssid.ssid, + params.ssid.ssid_len, params.action, + (uint8_t) (params.key_mgmt_suite & 0x000000FF), + (uint8_t) ((params.key_mgmt_suite >> 8) & 0x000000FF), + (uint8_t) ((params.key_mgmt_suite >> 16) & 0x000000FF), + (uint8_t) ((params.key_mgmt_suite >> 24) & 0x000000FF)); + return cfg80211_external_auth_request(ndev, ¶ms, GFP_KERNEL); +} +#endif + +const uint8_t *kalFindIeMatchMask(uint8_t eid, + const uint8_t *ies, int len, + const uint8_t *match, + int match_len, int match_offset, + const uint8_t *match_mask) +{ + /* match_offset can't be smaller than 2, unless match_len is + * zero, in which case match_offset must be zero as well. + */ + if (WARN_ON((match_len && match_offset < 2) || + (!match_len && match_offset))) + return NULL; + while (len >= 2 && len >= ies[1] + 2) { + if ((ies[0] == eid) && + (ies[1] + 2 >= match_offset + match_len) && + !kalMaskMemCmp(ies + match_offset, + match, match_mask, match_len)) + return ies; + len -= ies[1] + 2; + ies += ies[1] + 2; + } + return NULL; +} + +int _kalSnprintf(char *buf, size_t size, const char *fmt, ...) +{ + int retval; + va_list ap; + + va_start(ap, fmt); + retval = vsnprintf(buf, size, fmt, ap); + va_end(ap); + return (retval < 0)?(0):(retval); +} + +int _kalSprintf(char *buf, const char *fmt, ...) +{ + int retval; + va_list ap; + + va_start(ap, fmt); + retval = vsprintf(buf, fmt, ap); + va_end(ap); + return (retval < 0)?(0):(retval); +} +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE +void kal_do_gettimeofday(struct timeval *tv) +{ + struct timespec64 now; + + ktime_get_real_ts64(&now); + tv->tv_sec = now.tv_sec; + tv->tv_usec = now.tv_nsec / NSEC_PER_USEC; +} +#endif + +static void kalDumpHifStats(IN struct ADAPTER *prAdapter) +{ + struct HIF_STATS *prHifStats; + struct GL_HIF_INFO *prHifInfo; + struct RTMP_TX_RING *prTxRing; + struct RTMP_RX_RING *prRxRing; + struct RX_CTRL *prRxCtrl; + uint8_t i = 0; + uint32_t u4BufferSize = 512, pos = 0; + char *buf; + + if (!prAdapter) + return; + + prHifStats = &prAdapter->rHifStats; + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + prRxCtrl = &prAdapter->rRxCtrl; + + if (time_before(jiffies, prHifStats->ulUpdatePeriod)) + return; + + buf = (char *) kalMemAlloc(u4BufferSize, VIR_MEM_TYPE); + if (!buf) + return; + kalMemZero(buf, u4BufferSize); + + prHifStats->ulUpdatePeriod = jiffies + + prAdapter->rWifiVar.u4PerfMonUpdatePeriod * HZ / 1000; + + pos += kalSnprintf(buf + pos, u4BufferSize - pos, + "I[%u %u]", + GLUE_GET_REF_CNT(prHifStats->u4HwIsrCount), + GLUE_GET_REF_CNT(prHifStats->u4SwIsrCount)); + pos += kalSnprintf(buf + pos, u4BufferSize - pos, + " T[%u %u %u / %u %u %u %u]", + GLUE_GET_REF_CNT(prHifStats->u4CmdInCount), + GLUE_GET_REF_CNT(prHifStats->u4CmdTxCount), + GLUE_GET_REF_CNT(prHifStats->u4CmdTxdoneCount), + GLUE_GET_REF_CNT(prHifStats->u4DataInCount), + GLUE_GET_REF_CNT(prHifStats->u4DataTxCount), + GLUE_GET_REF_CNT(prHifStats->u4DataTxdoneCount), + GLUE_GET_REF_CNT(prHifStats->u4DataMsduRptCount)); + pos += kalSnprintf(buf + pos, u4BufferSize - pos, + " R[%u / %u]", + GLUE_GET_REF_CNT(prHifStats->u4DataRxCount), + GLUE_GET_REF_CNT(prHifStats->u4EventRxCount)); + for (i = 0; i < NUM_OF_TX_RING; ++i) { + prTxRing = &prHifInfo->TxRing[i]; + pos += kalSnprintf(buf + pos, u4BufferSize - pos, "%s%u%s", + (i == 0) ? " T_R[" : "", + prTxRing->u4UsedCnt, + (i == NUM_OF_TX_RING - 1) ? "] " : " "); + } + for (i = 0; i < NUM_OF_RX_RING; ++i) { + prRxRing = &prHifInfo->RxRing[i]; + pos += kalSnprintf(buf + pos, u4BufferSize - pos, "%s%u%s", + (i == 0) ? " R_R[" : "", + prRxRing->u4PendingCnt, + (i == NUM_OF_RX_RING - 1) ? "]" : " "); + } + pos += kalSnprintf(buf + pos, u4BufferSize - pos, + " Tok[%u/%u] Rfb[%u/%u]", + prHifInfo->rTokenInfo.u4UsedCnt, + HIF_TX_MSDU_TOKEN_NUM, + prRxCtrl->rFreeSwRfbList.u4NumElem, + CFG_RX_MAX_PKT_NUM); + DBGLOG(HAL, INFO, "%s\n", buf); + kalMemFree(buf, VIR_MEM_TYPE, u4BufferSize); +} + +uint32_t kalSetSuspendFlagToEMI(IN struct ADAPTER + *prAdapter, IN u_int8_t fgSuspend) +{ +#if CFG_MTK_ANDROID_EMI + uint32_t u4Offset = prAdapter->u4HostStatusEmiOffset + & WIFI_EMI_ADDR_MASK; + uint32_t suspendFlag = 0; + + if (!gConEmiPhyBase) { +#if (CFG_SUPPORT_CONNINFRA == 1) + conninfra_get_phy_addr( + (unsigned int *)&gConEmiPhyBase, + (unsigned int *)&gConEmiSize); +#endif + + if (!gConEmiPhyBase) { + DBGLOG(INIT, ERROR, + "[EMI_Suspend] gConEmiPhyBase invalid\n"); + return WLAN_STATUS_FAILURE; + } + } + suspendFlag = (fgSuspend == TRUE) ? 0x11111111 : 0x22222222; + + DBGLOG(INIT, TRACE, + "[EMI_Suspend] EmiPhyBase:0x%llx offset:0x%x set 0x%x", + (uint64_t)gConEmiPhyBase, u4Offset, suspendFlag); + + wf_ioremap_write((gConEmiPhyBase + u4Offset), suspendFlag); + +#endif /* CFG_MTK_ANDROID_EMI */ + return WLAN_STATUS_SUCCESS; +} + +void kalPrintUTC(char *msg_buf, int msg_buf_size) +{ + int ret = 0; + struct rtc_time tm; + struct timeval tv = { 0 }; + struct rtc_time tm_android; + struct timeval tv_android = { 0 }; + + do_gettimeofday(&tv); + tv_android = tv; + rtc_time_to_tm(tv.tv_sec, &tm); + tv_android.tv_sec -= sys_tz.tz_minuteswest * 60; + rtc_time_to_tm(tv_android.tv_sec, &tm_android); + if (tm.tm_sec%10 == 0) { + ret = snprintf(msg_buf, msg_buf_size, + "[RT:%lld] %d-%02d-%02d %02d:%02d:%02d.%u UTC;" + "android time %d-%02d-%02d %02d:%02d:%02d.%03d", + sched_clock(), tm.tm_year + 1900, tm.tm_mon + 1, + tm.tm_mday, tm.tm_hour, tm.tm_min, + tm.tm_sec, (unsigned int)tv.tv_usec, + tm_android.tm_year + 1900, tm_android.tm_mon + 1, + tm_android.tm_mday, tm_android.tm_hour, + tm_android.tm_min, tm_android.tm_sec, + (unsigned int)tv_android.tv_usec); + if (ret < 0) { + kalPrintLog("[%u] snprintf failed, ret: %d", + __LINE__, ret); + } else { + trace_wifi_standalone_log(msg_buf); + } + } +} + +void kalPrintTrace(char *buffer, const int len) +{ + if (buffer[len - 1] == '\n') + buffer[len - 1] = '\0'; + + if (len < WIFI_LOG_MSG_MAX) { + trace_wifi_standalone_log(buffer); + } else { + char sub_buffer[WIFI_LOG_MSG_MAX]; + + strncpy(sub_buffer, buffer, + WIFI_LOG_MSG_MAX - 1); + sub_buffer[WIFI_LOG_MSG_MAX - 1] = '\0'; + trace_wifi_standalone_log(sub_buffer); + + strncpy(sub_buffer, buffer + WIFI_LOG_MSG_MAX - 1, + WIFI_LOG_MSG_MAX - 1); + sub_buffer[WIFI_LOG_MSG_MAX - 1] = '\0'; + trace_wifi_standalone_log(sub_buffer); + } + + if (time_after(jiffies, rtc_update)) { + rtc_update = jiffies + (1 * HZ); + kalPrintUTC(buffer, WIFI_LOG_MSG_BUFFER); + } +} + +void kalPrintLog(const char *fmt, ...) +{ + char buffer[WIFI_LOG_MSG_BUFFER]; + int ret = 0; + struct va_format vaf; + va_list args; + + va_start(args, fmt); + vaf.fmt = fmt; + vaf.va = &args; + ret = vsnprintf(buffer, sizeof(buffer), fmt, args); + if (ret < 0) { + kalPrintLog("[%u] vsnprintf failed, ret: %d", + __LINE__, ret); + } else if (get_wifi_standalone_log_mode() == 1) { + kalPrintTrace(buffer, strlen(buffer)); + } else { + pr_info("%s%s", WLAN_TAG, buffer); + } + + va_end(args); +} + +void kalPrintLogLimited(const char *fmt, ...) +{ + #ifdef CONFIG_PRINTK + static DEFINE_RATELIMIT_STATE(_rs, + DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST); + + if (__ratelimit(&_rs)) { + char buffer[WIFI_LOG_MSG_BUFFER]; + int ret = 0; + struct va_format vaf; + va_list args; + + va_start(args, fmt); + vaf.fmt = fmt; + vaf.va = &args; + ret = vsnprintf(buffer, sizeof(buffer), fmt, args); + if (ret < 0) { + kalPrintLog("[%u] vsnprintf failed, ret: %d", + __LINE__, ret); + } else if (get_wifi_standalone_log_mode() == 1) { + kalPrintTrace(buffer, strlen(buffer)); + } else { + pr_info("%s%s", WLAN_TAG, buffer); + } + + va_end(args); + } + #endif +} + +#if KERNEL_VERSION(5, 4, 0) <= CFG80211_VERSION_CODE +MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_p2p.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_p2p.c new file mode 100644 index 0000000000000..bdebd423c2a12 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_p2p.c @@ -0,0 +1,2252 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + + +/****************************************************************************** + * C O M P I L E R F L A G S + ****************************************************************************** + */ + +/****************************************************************************** + * E X T E R N A L R E F E R E N C E S + ****************************************************************************** + */ + +#include + +#include + + +#include "gl_os.h" +#include "debug.h" +#include "wlan_lib.h" +#include "gl_wext.h" + +/* #include */ +#include "gl_p2p_ioctl.h" + +#include "precomp.h" +#include "gl_vendor.h" +#include "gl_cfg80211.h" +#if CFG_MTK_MCIF_WIFI_SUPPORT +#include "mddp.h" +#endif +/****************************************************************************** + * 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) + +#if 0 +#define RUNNING_P2P_MODE 0 +#define RUNNING_AP_MODE 1 +#define RUNNING_DUAL_AP_MODE 2 +#endif +/****************************************************************************** + * 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 + ****************************************************************************** + */ + +struct net_device *g_P2pPrDev; +struct wireless_dev *gprP2pWdev; +struct wireless_dev *gprP2pRoleWdev[KAL_P2P_NUM]; +struct net_device *gPrP2pDev[KAL_P2P_NUM]; +uint32_t g_u4DevIdx[KAL_P2P_NUM]; + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#if (CFG_ENABLE_UNIFY_WIPHY == 0) +static struct cfg80211_ops mtk_p2p_ops = { +#if (CFG_ENABLE_WIFI_DIRECT_CFG_80211 != 0) + /* Froyo */ + .add_virtual_intf = mtk_p2p_cfg80211_add_iface, + .change_virtual_intf = mtk_p2p_cfg80211_change_iface, /* 1 st */ + .del_virtual_intf = mtk_p2p_cfg80211_del_iface, + .change_bss = mtk_p2p_cfg80211_change_bss, + .scan = mtk_p2p_cfg80211_scan, +#if KERNEL_VERSION(4, 5, 0) <= CFG80211_VERSION_CODE + .abort_scan = mtk_p2p_cfg80211_abort_scan, +#endif + .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, + .mgmt_tx_cancel_wait = mtk_p2p_cfg80211_mgmt_tx_cancel_wait, + .connect = mtk_p2p_cfg80211_connect, + .disconnect = mtk_p2p_cfg80211_disconnect, + .deauth = mtk_p2p_cfg80211_deauth, + .disassoc = mtk_p2p_cfg80211_disassoc, + .start_ap = mtk_p2p_cfg80211_start_ap, + .change_beacon = mtk_p2p_cfg80211_change_beacon, + .stop_ap = mtk_p2p_cfg80211_stop_ap, + .set_wiphy_params = mtk_p2p_cfg80211_set_wiphy_params, + .del_station = mtk_p2p_cfg80211_del_station, + .set_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, + .set_default_mgmt_key = mtk_p2p_cfg80211_set_mgmt_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, +#if (CFG_SUPPORT_DFS_MASTER == 1) + .start_radar_detection = mtk_p2p_cfg80211_start_radar_detection, +#if KERNEL_VERSION(3, 13, 0) <= CFG80211_VERSION_CODE + .channel_switch = mtk_p2p_cfg80211_channel_switch, +#endif +#endif +#ifdef CONFIG_NL80211_TESTMODE + .testmode_cmd = mtk_p2p_cfg80211_testmode_cmd, +#endif +#endif +}; +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE + +static const struct wiphy_vendor_command mtk_p2p_vendor_ops[] = { + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_GET_CHANNEL_LIST + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV + | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_channel_list + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_SET_COUNTRY_CODE + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV + | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_country_code + }, +#if CFG_SUPPORT_P2P_PREFERRED_FREQ_LIST + /* P2P get preferred freq list */ + { + { + .vendor_id = OUI_QCA, + .subcmd = NL80211_VENDOR_SUBCMD_GET_PREFER_FREQ_LIST + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV + | WIPHY_VENDOR_CMD_NEED_NETDEV + | WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = mtk_cfg80211_vendor_get_preferred_freq_list + }, +#endif /* CFG_SUPPORT_P2P_PREFERRED_FREQ_LIST */ +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + { + { + .vendor_id = OUI_QCA, + .subcmd = NL80211_VENDOR_SUBCMD_ACS + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV + | WIPHY_VENDOR_CMD_NEED_NETDEV + | WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = mtk_cfg80211_vendor_acs + }, +#endif + { + { + .vendor_id = OUI_QCA, + .subcmd = NL80211_VENDOR_SUBCMD_GET_FEATURES + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV + | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_features + }, +}; + +static const struct nl80211_vendor_cmd_info mtk_p2p_vendor_events[] = { +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + { + .vendor_id = OUI_QCA, + .subcmd = NL80211_VENDOR_SUBCMD_ACS + }, +#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) +#if CFG_SUPPORT_SOFTAP_WPA3 + | BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) +#endif + }, + [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 +#endif + +static const struct iw_priv_args rP2PIwPrivTable[] = { + { + .cmd = IOC_P2P_CFG_DEVICE, + .set_args = IW_PRIV_TYPE_BYTE + | (__u16) sizeof(struct 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(struct 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(struct 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(struct 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(struct 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(struct 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"} +}; + +#if 0 +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 +}; +#endif + +#ifdef CONFIG_PM +static const struct wiphy_wowlan_support mtk_p2p_wowlan_support = { + .flags = WIPHY_WOWLAN_DISCONNECT | WIPHY_WOWLAN_ANY, +}; +#endif + +static const struct ieee80211_iface_limit mtk_p2p_sta_go_limits[] = { + { + .max = 3, + .types = BIT(NL80211_IFTYPE_STATION), + }, + + { + .max = 1, + .types = BIT(NL80211_IFTYPE_P2P_GO) + | BIT(NL80211_IFTYPE_P2P_CLIENT), + }, +}; + +#if (CFG_SUPPORT_DFS_MASTER == 1) +#if (KERNEL_VERSION(3, 17, 0) > CFG80211_VERSION_CODE) + +static const struct ieee80211_iface_limit mtk_ap_limits[] = { + { + .max = 1, + .types = BIT(NL80211_IFTYPE_AP), + }, +}; +#endif +#endif + +static const struct ieee80211_iface_combination +mtk_iface_combinations_sta[] = { + { +#ifdef CFG_NUM_DIFFERENT_CHANNELS_STA + .num_different_channels = CFG_NUM_DIFFERENT_CHANNELS_STA, +#else + .num_different_channels = 2, +#endif /* CFG_NUM_DIFFERENT_CHANNELS_STA */ + .max_interfaces = 3, + /*.beacon_int_infra_match = true,*/ + .limits = mtk_p2p_sta_go_limits, + .n_limits = 1, /* include p2p */ + }, +}; + +static const struct ieee80211_iface_combination +mtk_iface_combinations_p2p[] = { + { +#if CFG_ENABLE_UNIFY_WIPHY + /* The 2 MCC channels case has been verified */ + .num_different_channels = 2, +#elif defined(CFG_NUM_DIFFERENT_CHANNELS_P2P) + .num_different_channels = CFG_NUM_DIFFERENT_CHANNELS_P2P, +#else + .num_different_channels = 2, +#endif /* CFG_NUM_DIFFERENT_CHANNELS_P2P */ + .max_interfaces = 3, + /*.beacon_int_infra_match = true,*/ + .limits = mtk_p2p_sta_go_limits, + .n_limits = ARRAY_SIZE(mtk_p2p_sta_go_limits), /* include p2p */ + }, +#if (CFG_SUPPORT_DFS_MASTER == 1) +#if (KERNEL_VERSION(3, 17, 0) > CFG80211_VERSION_CODE) + /* ONLY for passing checks in cfg80211_can_use_iftype_chan + * before linux-3.17.0 + */ + { + .num_different_channels = 1, + .max_interfaces = 1, + .limits = mtk_ap_limits, + .n_limits = ARRAY_SIZE(mtk_ap_limits), + .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | + BIT(NL80211_CHAN_WIDTH_20) | + BIT(NL80211_CHAN_WIDTH_40) | + BIT(NL80211_CHAN_WIDTH_80) | + BIT(NL80211_CHAN_WIDTH_80P80), + }, +#endif +#endif +}; + + +const struct ieee80211_iface_combination + *p_mtk_iface_combinations_sta = mtk_iface_combinations_sta; +const int32_t mtk_iface_combinations_sta_num = + ARRAY_SIZE(mtk_iface_combinations_sta); + +const struct ieee80211_iface_combination + *p_mtk_iface_combinations_p2p = mtk_iface_combinations_p2p; +const int32_t mtk_iface_combinations_p2p_num = + ARRAY_SIZE(mtk_iface_combinations_p2p); + +/****************************************************************************** + * M A C R O S + ****************************************************************************** + */ + +/****************************************************************************** + * F U N C T I O N D E C L A R A T I O N S + ****************************************************************************** + */ + +/* 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 netdev_tx_t p2pHardStartXmit(IN struct sk_buff *prSkb, + IN struct net_device *prDev); + +static int p2pSetMACAddress(IN struct net_device *prDev, void *addr); + +static int p2pDoIOCTL(struct net_device *prDev, + struct ifreq *prIFReq, + int i4Cmd); + +#if CFG_SUPPORT_RX_GRO +/*----------------------------------------------------------------------------*/ +/*! + * \brief A method of callback function for napi struct + * + * It just return false because driver indicate Rx packet directly. + * + * \param[in] napi Pointer to struct napi_struct. + * \param[in] budget Polling time interval. + * + * \return false + */ +/*----------------------------------------------------------------------------*/ +static int p2p_napi_poll(struct napi_struct *napi, int budget) +{ + return 0; +} +#endif + +/*---------------------------------------------------------------------------*/ +/*! + * \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 CFG_SUPPORT_RX_GRO + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = NULL; +#endif + if (!prDev) + return -ENXIO; +#if CFG_SUPPORT_RX_GRO + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prDev); + prDev->features |= NETIF_F_GRO; + prDev->hw_features |= NETIF_F_GRO; + spin_lock_init(&prNetDevPrivate->napi_spinlock); + prNetDevPrivate->napi.dev = prDev; + netif_napi_add(prNetDevPrivate->napi.dev, + &prNetDevPrivate->napi, p2p_napi_poll, 64); + DBGLOG(INIT, TRACE, + "GRO interface added successfully:%p\n", prDev); +#endif + return 0; /* success */ +} /* end of p2pInit() */ + +/*---------------------------------------------------------------------------*/ +/*! + * \brief A function for prDev->uninit + * + * \param[in] prDev Pointer to struct net_device. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static void p2pUninit(IN struct net_device *prDev) +{ +} /* end of p2pUninit() */ + +const struct net_device_ops p2p_netdev_ops = { + .ndo_open = p2pOpen, + .ndo_stop = p2pStop, + .ndo_set_mac_address = p2pSetMACAddress, + .ndo_set_rx_mode = p2pSetMulticastList, + .ndo_get_stats = p2pGetStats, + .ndo_do_ioctl = p2pDoIOCTL, + .ndo_start_xmit = p2pHardStartXmit, + /* .ndo_select_queue = p2pSelectQueue, */ + .ndo_select_queue = wlanSelectQueue, + .ndo_init = p2pInit, + .ndo_uninit = p2pUninit, +}; + +/****************************************************************************** + * F U N C T I O N S + ****************************************************************************** + */ + +/*---------------------------------------------------------------------------*/ +/*! + * \brief Allocate memory for P2P_INFO, GL_P2P_INFO, P2P_CONNECTION_SETTINGS + * P2P_SPECIFIC_BSS_INFO, P2P_FSM_INFO + * + * \param[in] prGlueInfo Pointer to glue info + * + * \return TRUE + * FALSE + */ +/*---------------------------------------------------------------------------*/ +u_int8_t p2PAllocInfo(IN struct GLUE_INFO *prGlueInfo, IN uint8_t ucIdex) +{ + struct ADAPTER *prAdapter = NULL; + struct WIFI_VAR *prWifiVar = NULL; + /* UINT_32 u4Idx = 0; */ + + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + prWifiVar = &(prAdapter->rWifiVar); + + ASSERT(prAdapter); + ASSERT(prWifiVar); + + do { + if (prGlueInfo->prP2PInfo[ucIdex] == NULL) { + /*alloc memory for p2p info */ + prGlueInfo->prP2PInfo[ucIdex] = + kalMemAlloc(sizeof(struct GL_P2P_INFO), + VIR_MEM_TYPE); + + if (prGlueInfo->prP2PDevInfo == NULL) { + prGlueInfo->prP2PDevInfo = + kalMemAlloc( + sizeof(struct GL_P2P_DEV_INFO), + VIR_MEM_TYPE); + if (prGlueInfo->prP2PDevInfo) { + kalMemZero(prGlueInfo->prP2PDevInfo, + sizeof(struct GL_P2P_DEV_INFO)); + } + } + + if (prAdapter->prP2pInfo == NULL) { + prAdapter->prP2pInfo = + kalMemAlloc(sizeof(struct P2P_INFO), + VIR_MEM_TYPE); + if (prAdapter->prP2pInfo) { + kalMemZero(prAdapter->prP2pInfo, + sizeof(struct P2P_INFO)); + } + } + + if (prWifiVar->prP2pDevFsmInfo == NULL) { + /* Don't only create P2P device for ucIdex 0. + * Avoid the exception that mtk_init_ap_role + * called without p2p0. + */ + prWifiVar->prP2pDevFsmInfo = + kalMemAlloc( + sizeof(struct P2P_DEV_FSM_INFO), + VIR_MEM_TYPE); + if (prWifiVar->prP2pDevFsmInfo) { + kalMemZero(prWifiVar->prP2pDevFsmInfo, + sizeof(struct + P2P_DEV_FSM_INFO)); + } + } + + prWifiVar->prP2PConnSettings[ucIdex] = + kalMemAlloc( + sizeof(struct P2P_CONNECTION_SETTINGS), + VIR_MEM_TYPE); + prWifiVar->prP2pSpecificBssInfo[ucIdex] = + kalMemAlloc( + sizeof(struct P2P_SPECIFIC_BSS_INFO), + VIR_MEM_TYPE); +#if CFG_ENABLE_PER_STA_STATISTICS_LOG + prWifiVar->prP2pQueryStaStatistics[ucIdex] = + kalMemAlloc( + sizeof(struct PARAM_GET_STA_STATISTICS), + VIR_MEM_TYPE); +#endif + /* TODO: It can be moved + * to the interface been created. + */ +#if 0 + for (u4Idx = 0; u4Idx < BSS_P2P_NUM; u4Idx++) { + prWifiVar->aprP2pRoleFsmInfo[u4Idx] = + kalMemAlloc(sizeof(struct P2P_ROLE_FSM_INFO), + VIR_MEM_TYPE); + } +#endif + } else { + ASSERT(prAdapter->prP2pInfo != NULL); + ASSERT(prWifiVar->prP2PConnSettings[ucIdex] != NULL); + /* ASSERT(prWifiVar->prP2pFsmInfo != NULL); */ + ASSERT(prWifiVar->prP2pSpecificBssInfo[ucIdex] != NULL); + } + /*MUST set memory to 0 */ + kalMemZero(prGlueInfo->prP2PInfo[ucIdex], + sizeof(struct GL_P2P_INFO)); + kalMemZero(prWifiVar->prP2PConnSettings[ucIdex], + sizeof(struct P2P_CONNECTION_SETTINGS)); +/* kalMemZero(prWifiVar->prP2pFsmInfo, sizeof(P2P_FSM_INFO_T)); */ + kalMemZero(prWifiVar->prP2pSpecificBssInfo[ucIdex], + sizeof(struct P2P_SPECIFIC_BSS_INFO)); +#if CFG_ENABLE_PER_STA_STATISTICS_LOG + if (prWifiVar->prP2pQueryStaStatistics[ucIdex]) + kalMemZero(prWifiVar->prP2pQueryStaStatistics[ucIdex], + sizeof(struct PARAM_GET_STA_STATISTICS)); +#endif + } while (FALSE); + + if (!prGlueInfo->prP2PDevInfo) + DBGLOG(P2P, ERROR, "prP2PDevInfo error\n"); + else + DBGLOG(P2P, TRACE, "prP2PDevInfo ok\n"); + + if (!prGlueInfo->prP2PInfo[ucIdex]) + DBGLOG(P2P, ERROR, "prP2PInfo error\n"); + else + DBGLOG(P2P, TRACE, "prP2PInfo ok\n"); + + + + /* chk if alloc successful or not */ + if (prGlueInfo->prP2PInfo[ucIdex] && + prGlueInfo->prP2PDevInfo && + prAdapter->prP2pInfo && + prWifiVar->prP2PConnSettings[ucIdex] && +/* prWifiVar->prP2pFsmInfo && */ + prWifiVar->prP2pSpecificBssInfo[ucIdex]) + return TRUE; + + + DBGLOG(P2P, ERROR, "[fail!]p2PAllocInfo :fail\n"); + + if (prWifiVar->prP2pSpecificBssInfo[ucIdex]) { + kalMemFree(prWifiVar->prP2pSpecificBssInfo[ucIdex], + VIR_MEM_TYPE, + sizeof(struct P2P_SPECIFIC_BSS_INFO)); + + prWifiVar->prP2pSpecificBssInfo[ucIdex] = NULL; + } + +#if CFG_ENABLE_PER_STA_STATISTICS_LOG + if (prWifiVar->prP2pQueryStaStatistics[ucIdex]) { + kalMemFree(prWifiVar->prP2pQueryStaStatistics[ucIdex], + VIR_MEM_TYPE, + sizeof(struct PARAM_GET_STA_STATISTICS)); + prWifiVar->prP2pQueryStaStatistics[ucIdex] = NULL; + } +#endif + +/* if (prWifiVar->prP2pFsmInfo) { */ +/* kalMemFree(prWifiVar->prP2pFsmInfo, + * VIR_MEM_TYPE, sizeof(P2P_FSM_INFO_T)); + */ + +/* prWifiVar->prP2pFsmInfo = NULL; */ +/* } */ + if (prWifiVar->prP2PConnSettings[ucIdex]) { + kalMemFree(prWifiVar->prP2PConnSettings[ucIdex], + VIR_MEM_TYPE, sizeof(struct P2P_CONNECTION_SETTINGS)); + + prWifiVar->prP2PConnSettings[ucIdex] = NULL; + } + if (prGlueInfo->prP2PDevInfo) { + kalMemFree(prGlueInfo->prP2PDevInfo, + VIR_MEM_TYPE, sizeof(struct GL_P2P_DEV_INFO)); + + prGlueInfo->prP2PDevInfo = NULL; + } + if (prGlueInfo->prP2PInfo[ucIdex]) { + kalMemFree(prGlueInfo->prP2PInfo[ucIdex], + VIR_MEM_TYPE, sizeof(struct GL_P2P_INFO)); + + prGlueInfo->prP2PInfo[ucIdex] = NULL; + } + if (prAdapter->prP2pInfo) { + kalMemFree(prAdapter->prP2pInfo, + VIR_MEM_TYPE, sizeof(struct P2P_INFO)); + + 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 + * [in] ucIdx The BSS with the idx will be freed. + * "ucIdx == 0xff" will free all BSSs. + * Only has meaning for "CFG_ENABLE_UNIFY_WIPHY == 1" + * + * \return TRUE + * FALSE + */ +/*---------------------------------------------------------------------------*/ +u_int8_t p2PFreeInfo(struct GLUE_INFO *prGlueInfo, uint8_t ucIdx) +{ + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + + ASSERT(prGlueInfo); + ASSERT(prAdapter); + + if (ucIdx >= KAL_P2P_NUM) { + DBGLOG(P2P, ERROR, "ucIdx=%d is invalid\n", ucIdx); + return FALSE; + } + + /* Expect that prAdapter->prP2pInfo must be existing. */ + if (prAdapter->prP2pInfo == NULL) { + DBGLOG(P2P, ERROR, "prAdapter->prP2pInfo is NULL\n"); + return FALSE; + } + + /* TODO: how can I sure that the specific P2P device can be freed? + * The original check is that prGlueInfo->prAdapter->fgIsP2PRegistered. + * For one wiphy feature, this func may be called without + * (fgIsP2PRegistered == FALSE) condition. + */ + + if (prGlueInfo->prP2PInfo[ucIdx] != NULL) { + kalMemFree(prAdapter->rWifiVar.prP2PConnSettings[ucIdx], + VIR_MEM_TYPE, + sizeof(struct P2P_CONNECTION_SETTINGS)); + prAdapter->rWifiVar.prP2PConnSettings[ucIdx] = NULL; + + kalMemFree(prAdapter->rWifiVar.prP2pSpecificBssInfo[ucIdx], + VIR_MEM_TYPE, + sizeof(struct P2P_SPECIFIC_BSS_INFO)); + prAdapter->rWifiVar.prP2pSpecificBssInfo[ucIdx] = NULL; + +#if CFG_ENABLE_PER_STA_STATISTICS_LOG + kalMemFree(prAdapter->rWifiVar.prP2pQueryStaStatistics[ucIdx], + VIR_MEM_TYPE, + sizeof(struct PARAM_GET_STA_STATISTICS)); + prAdapter->rWifiVar.prP2pQueryStaStatistics[ucIdx] = NULL; +#endif + +#if (CFG_SUPPORT_DFS_MASTER == 1) + if (prGlueInfo->prP2PInfo[ucIdx]->chandef) { + if (prGlueInfo->prP2PInfo[ucIdx]->chandef->chan) { + cnmMemFree(prGlueInfo->prAdapter, + prGlueInfo->prP2PInfo[ucIdx] + ->chandef->chan); + prGlueInfo->prP2PInfo[ucIdx] + ->chandef->chan = NULL; + } + cnmMemFree(prGlueInfo->prAdapter, + prGlueInfo->prP2PInfo[ucIdx]->chandef); + prGlueInfo->prP2PInfo[ucIdx]->chandef = NULL; + } +#endif + + kalMemFree(prGlueInfo->prP2PInfo[ucIdx], + VIR_MEM_TYPE, + sizeof(struct GL_P2P_INFO)); + prGlueInfo->prP2PInfo[ucIdx] = NULL; + + prAdapter->prP2pInfo->u4DeviceNum--; + } + + if (prAdapter->prP2pInfo->u4DeviceNum == 0) { + /* all prP2PInfo are freed, and free the general part now */ + + kalMemFree(prAdapter->prP2pInfo, VIR_MEM_TYPE, + sizeof(struct P2P_INFO)); + prAdapter->prP2pInfo = NULL; + + if (prGlueInfo->prP2PDevInfo) { + kalMemFree(prGlueInfo->prP2PDevInfo, VIR_MEM_TYPE, + sizeof(struct GL_P2P_DEV_INFO)); + prGlueInfo->prP2PDevInfo = NULL; + } + if (prAdapter->rWifiVar.prP2pDevFsmInfo) { + kalMemFree(prAdapter->rWifiVar.prP2pDevFsmInfo, + VIR_MEM_TYPE, sizeof(struct P2P_DEV_FSM_INFO)); + prAdapter->rWifiVar.prP2pDevFsmInfo = NULL; + } + + /* Reomve p2p bss scan list */ + scanRemoveAllP2pBssDesc(prAdapter); + } + + return TRUE; +} + +u_int8_t p2pNetRegister(struct GLUE_INFO *prGlueInfo, + u_int8_t fgIsRtnlLockAcquired) +{ + u_int8_t fgDoRegister = FALSE; + u_int8_t fgRollbackRtnlLock = FALSE; + u_int8_t 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(); + } + + /* net device initialize */ + netif_carrier_off(prGlueInfo->prP2PInfo[0]->prDevHandler); + netif_tx_stop_all_queues(prGlueInfo->prP2PInfo[0]->prDevHandler); + + /* register for net device */ + if (g_u4DevIdx[0]) { + prGlueInfo->prP2PInfo[0]->prDevHandler->ifindex = + g_u4DevIdx[0]; + g_u4DevIdx[0] = 0; + } + + if (register_netdev(prGlueInfo->prP2PInfo[0]->prDevHandler) < 0) { + DBGLOG(INIT, WARN, "unable to register netdevice for p2p\n"); + /* free dev in glUnregisterP2P() */ + /* free_netdev(prGlueInfo->prP2PInfo[0]->prDevHandler); */ + ret = FALSE; + } else { + prGlueInfo->prAdapter->rP2PNetRegState = + ENUM_NET_REG_STATE_REGISTERED; + gPrP2pDev[0] = prGlueInfo->prP2PInfo[0]->prDevHandler; + ret = TRUE; + } + + if (prGlueInfo->prAdapter->prP2pInfo->u4DeviceNum == KAL_P2P_NUM) { + /* net device initialize */ + netif_carrier_off(prGlueInfo->prP2PInfo[1]->prDevHandler); + netif_tx_stop_all_queues( + prGlueInfo->prP2PInfo[1]->prDevHandler); + + if (g_u4DevIdx[1]) { + prGlueInfo->prP2PInfo[1]->prDevHandler->ifindex + = g_u4DevIdx[1]; + g_u4DevIdx[1] = 0; + } + + /* register for net device */ + if (register_netdev( + prGlueInfo->prP2PInfo[1]->prDevHandler) < 0) { + + DBGLOG(INIT, WARN, + "unable to register netdevice for p2p\n"); + /* free dev in glUnregisterP2P() */ + /* free_netdev(prP2PInfo[1]->prDevHandler); */ + + ret = FALSE; + } else { + prGlueInfo->prAdapter->rP2PNetRegState = + ENUM_NET_REG_STATE_REGISTERED; + gPrP2pDev[1] = prGlueInfo->prP2PInfo[1]->prDevHandler; + ret = TRUE; + } + + + DBGLOG(P2P, INFO, "P2P 2nd interface work %d %d\n", + prGlueInfo->prP2PInfo[0]->prDevHandler->ifindex, + prGlueInfo->prP2PInfo[1]->prDevHandler->ifindex); + } + if (fgRollbackRtnlLock) + rtnl_lock(); + + return ret; +} + +u_int8_t p2pNetUnregister(struct GLUE_INFO *prGlueInfo, + u_int8_t fgIsRtnlLockAcquired) +{ + u_int8_t fgDoUnregister = FALSE; + u_int8_t fgRollbackRtnlLock = FALSE; + uint8_t ucRoleIdx; + struct ADAPTER *prAdapter = NULL; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPriv = NULL; + struct GL_P2P_INFO *prP2PInfo = NULL; + struct BSS_INFO *prP2pBssInfo = NULL; + int iftype = 0; + struct net_device *prRoleDev = NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + prAdapter = prGlueInfo->prAdapter; + + ASSERT(prGlueInfo); + ASSERT(prAdapter); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if (prAdapter->rP2PNetRegState == ENUM_NET_REG_STATE_REGISTERED) { + prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_UNREGISTERING; + fgDoUnregister = TRUE; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + if (!fgDoUnregister) + return TRUE; + + if (fgIsRtnlLockAcquired && rtnl_is_locked()) + fgRollbackRtnlLock = TRUE; + + for (ucRoleIdx = 0; ucRoleIdx < KAL_P2P_NUM; ucRoleIdx++) { + prP2PInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + if (prP2PInfo == NULL) + continue; + +#if CFG_ENABLE_UNIFY_WIPHY + /* don't unregister the dev that share with the AIS */ + if (wlanIsAisDev(prP2PInfo->prDevHandler)) + continue; +#endif + + prRoleDev = prP2PInfo->aprRoleHandler; + if (prRoleDev != NULL) { + /* info cfg80211 disconnect */ + prNetDevPriv = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prRoleDev); + iftype = prRoleDev->ieee80211_ptr->iftype; + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prNetDevPriv->ucBssIdx); + + /* FIXME: The p2pRoleFsmUninit may call the + * cfg80211_disconnected. + * p2pRemove()->glUnregisterP2P->p2pRoleFsmUninit(), + * it may be too late. + */ + if ((prP2pBssInfo != NULL) && + (prP2pBssInfo->eConnectionState == + MEDIA_STATE_CONNECTED) && + ((iftype == NL80211_IFTYPE_P2P_CLIENT) || + (iftype == NL80211_IFTYPE_STATION))) { +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 2, 0) <= CFG80211_VERSION_CODE) + cfg80211_disconnected(prRoleDev, 0, NULL, 0, + TRUE, GFP_KERNEL); +#else + cfg80211_disconnected(prRoleDev, 0, NULL, 0, + GFP_KERNEL); +#endif + } + + if (prRoleDev != prP2PInfo->prDevHandler) { + if (netif_carrier_ok(prRoleDev)) + netif_carrier_off(prRoleDev); + + netif_tx_stop_all_queues(prRoleDev); + } + } + + if (netif_carrier_ok(prP2PInfo->prDevHandler)) + netif_carrier_off(prP2PInfo->prDevHandler); + + netif_tx_stop_all_queues(prP2PInfo->prDevHandler); + + if (fgRollbackRtnlLock) + rtnl_unlock(); + + /* Here are the functions which need rtnl_lock */ + if ((prRoleDev) && (prP2PInfo->prDevHandler != prRoleDev)) { + DBGLOG(INIT, INFO, "unregister p2p[%d]\n", ucRoleIdx); + if (prRoleDev->reg_state == NETREG_REGISTERED) + unregister_netdev(prRoleDev); + + /* This ndev is created in mtk_p2p_cfg80211_add_iface(), + * and unregister_netdev will also free the ndev. + */ + } + + DBGLOG(INIT, INFO, "unregister p2pdev[%d]\n", ucRoleIdx); + if (prP2PInfo->prDevHandler->reg_state == NETREG_REGISTERED) + unregister_netdev(prP2PInfo->prDevHandler); + + if (fgRollbackRtnlLock) + rtnl_lock(); + } + + prGlueInfo->prAdapter->rP2PNetRegState = + ENUM_NET_REG_STATE_UNREGISTERED; + + return TRUE; +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief Setup the P2P device information + * + * \param[in] prGlueInfo Pointer to glue info + * [in] prP2pWdev Pointer to the wireless device + * [in] prP2pDev Pointer to the net device + * [in] u4Idx The P2P Role index (max : (KAL_P2P_NUM-1)) + * [in] fgIsApMode Indicate that this device is AP Role or not + * + * \return 0 Success + * -1 Failure + */ +/*---------------------------------------------------------------------------*/ +int glSetupP2P(struct GLUE_INFO *prGlueInfo, struct wireless_dev *prP2pWdev, + struct net_device *prP2pDev, uint8_t u4Idx, u_int8_t fgIsApMode) +{ + struct ADAPTER *prAdapter = NULL; + struct GL_P2P_INFO *prP2PInfo = NULL; + struct GL_HIF_INFO *prHif = NULL; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPriv = NULL; + struct mt66xx_chip_info *prChipInfo = NULL; + + DBGLOG(INIT, TRACE, "setup the p2p dev\n"); + + if ((prGlueInfo == NULL) || + (prP2pWdev == NULL) || + (prP2pWdev->wiphy == NULL) || + (prP2pDev == NULL)) { + DBGLOG(INIT, ERROR, "parameter is NULL!!\n"); + return -1; + } + + prHif = &prGlueInfo->rHifInfo; + prAdapter = prGlueInfo->prAdapter; + + if ((prAdapter == NULL) || + (prHif == NULL)) { + DBGLOG(INIT, ERROR, "prAdapter/prHif is NULL!!\n"); + return -1; + } + + /* FIXME: check KAL_P2P_NUM in trunk? */ + if (u4Idx < 0 || u4Idx >= KAL_P2P_NUM) { + DBGLOG(INIT, ERROR, "u4Idx(%d) is out of range!!\n", u4Idx); + return -1; + } + + prChipInfo = prAdapter->chip_info; + + /*0. allocate p2pinfo */ + if (p2PAllocInfo(prGlueInfo, u4Idx) != TRUE) { + DBGLOG(INIT, WARN, "Allocate memory for p2p FAILED\n"); + return -1; + } + + prP2PInfo = prGlueInfo->prP2PInfo[u4Idx]; + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + /* fill wiphy parameters */ + + prP2PInfo->prWdev = prP2pWdev; + + if (!prAdapter->fgEnable5GBand) + prP2pWdev->wiphy->bands[BAND_5G] = NULL; + +#endif /* CFG_ENABLE_WIFI_DIRECT_CFG_80211 */ + + /* setup netdev */ + /* Point to shared glue structure */ + prNetDevPriv = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prP2pDev); + prNetDevPriv->prGlueInfo = prGlueInfo; + + /* set ucIsP2p for P2P function device */ + if (fgIsApMode == TRUE) { + prP2pWdev->iftype = NL80211_IFTYPE_AP; +#if CFG_ENABLE_UNIFY_WIPHY + prNetDevPriv->ucIsP2p = FALSE; +#endif +#if CFG_MTK_MDDP_WH_SUPPORT + prNetDevPriv->ucMddpSupport = TRUE; +#else + prNetDevPriv->ucMddpSupport = FALSE; +#endif + } else { + prP2pWdev->iftype = NL80211_IFTYPE_P2P_CLIENT; +#if CFG_ENABLE_UNIFY_WIPHY + prNetDevPriv->ucIsP2p = TRUE; +#endif + prNetDevPriv->ucMddpSupport = FALSE; + } + + /* register callback functions */ + prP2pDev->needed_headroom = + NIC_TX_DESC_AND_PADDING_LENGTH + prChipInfo->txd_append_size; + prP2pDev->netdev_ops = &p2p_netdev_ops; + +#if defined(_HIF_SDIO) +#if (MTK_WCN_HIF_SDIO == 0) + SET_NETDEV_DEV(prP2pDev, &(prHif->func->dev)); +#endif +#endif + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + prP2pDev->ieee80211_ptr = prP2pWdev; + prP2pWdev->netdev = prP2pDev; +#endif + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + /* set HW checksum offload */ + if (prAdapter->fgIsSupportCsumOffload) { + prP2pDev->features |= NETIF_F_IP_CSUM | + NETIF_F_IPV6_CSUM | + NETIF_F_RXCSUM; + } +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + kalResetStats(prP2pDev); + + /* finish */ + /* bind netdev pointer to netdev index */ + prP2PInfo->prDevHandler = prP2pDev; + + /* XXX: All the P2P/AP devices do p2pDevFsmInit in the original code */ + p2pDevFsmInit(prAdapter); + prP2PInfo->aprRoleHandler = prP2PInfo->prDevHandler; + + DBGLOG(P2P, INFO, + "check prDevHandler = %p, aprRoleHandler = %p\n", + prP2PInfo->prDevHandler, prP2PInfo->aprRoleHandler); + + prNetDevPriv->ucBssIdx = p2pRoleFsmInit(prAdapter, (uint8_t) u4Idx); + init_completion(&prP2PInfo->rStopApComp); + /* Currently wpasupplicant can't support create interface. */ + /* so initial the corresponding data structure here. */ + wlanBindBssIdxToNetInterface(prGlueInfo, prNetDevPriv->ucBssIdx, + (void *) prP2PInfo->aprRoleHandler); + + /* bind netdev pointer to netdev index */ +#if 0 + wlanBindNetInterface(prGlueInfo, NET_DEV_P2P_IDX, + (void *)prGlueInfo->prP2PInfo->prDevHandler); +#endif + + /* setup running mode */ + p2pFuncInitConnectionSettings(prAdapter, + prAdapter->rWifiVar.prP2PConnSettings[u4Idx], fgIsApMode); + + return 0; +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief Register for cfg80211 for Wi-Fi Direct + * + * \param[in] prGlueInfo Pointer to glue info + * + * \return TRUE + * FALSE + */ +/*---------------------------------------------------------------------------*/ +u_int8_t glRegisterP2P(struct GLUE_INFO *prGlueInfo, const char *prDevName, + const char *prDevName2, uint8_t ucApMode) +{ + struct ADAPTER *prAdapter = NULL; + uint8_t rMacAddr[PARAM_MAC_ADDR_LEN]; + u_int8_t fgIsApMode = FALSE; + uint8_t ucRegisterNum = 1, i = 0; + struct wireless_dev *prP2pWdev = NULL; + struct net_device *prP2pDev = NULL; + struct wiphy *prWiphy = NULL; + const char *prSetDevName; +#if (CFG_ENABLE_UNIFY_WIPHY == 0) + struct GL_HIF_INFO *prHif = NULL; + struct device *prDev; +#endif + + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + if ((ucApMode == RUNNING_DUAL_AP_MODE) || + (ucApMode == RUNNING_P2P_AP_MODE)) { + ucRegisterNum = 2; + glP2pCreateWirelessDevice(prGlueInfo); + } + + do { + if (ucApMode == RUNNING_P2P_AP_MODE) { + if (i == 0) { + prSetDevName = prDevName; + fgIsApMode = FALSE; + } else { + prSetDevName = prDevName2; + fgIsApMode = TRUE; + } + } else { + /* RUNNING_AP_MODE + * RUNNING_DUAL_AP_MODE + * RUNNING_P2P_MODE + */ + prSetDevName = prDevName; + + if (ucApMode == RUNNING_P2P_MODE) + fgIsApMode = FALSE; + else + fgIsApMode = TRUE; + } + + if (!gprP2pRoleWdev[i]) { + DBGLOG(P2P, ERROR, "gprP2pRoleWdev[%d] is NULL\n", i); + return FALSE; + } + + prP2pWdev = gprP2pRoleWdev[i]; + DBGLOG(INIT, INFO, "glRegisterP2P(%d), fgIsApMode(%d)\n", + i, fgIsApMode); + + /* Reset prP2pWdev for the issue that the prP2pWdev doesn't + * reset when the usb unplug/plug. + */ + prWiphy = prP2pWdev->wiphy; + memset(prP2pWdev, 0, sizeof(struct wireless_dev)); + prP2pWdev->wiphy = prWiphy; + + /* allocate netdev */ +#if KERNEL_VERSION(3, 17, 0) <= CFG80211_VERSION_CODE + prP2pDev = alloc_netdev_mq( + sizeof(struct NETDEV_PRIVATE_GLUE_INFO), + prSetDevName, NET_NAME_PREDICTABLE, + ether_setup, CFG_MAX_TXQ_NUM); +#else + prP2pDev = alloc_netdev_mq( + sizeof(struct NETDEV_PRIVATE_GLUE_INFO), + prSetDevName, + ether_setup, CFG_MAX_TXQ_NUM); +#endif + if (!prP2pDev) { + DBGLOG(INIT, WARN, "unable to allocate ndev for p2p\n"); + goto err_alloc_netdev; + } + + COPY_MAC_ADDR(rMacAddr, + prAdapter->rWifiVar.aucInterfaceAddress[i]); + + DBGLOG(INIT, INFO, "Set p2p role[%d] mac to " MACSTR "\n", + i, MAC2STR(rMacAddr)); + kalMemCopy(prP2pDev->dev_addr, rMacAddr, ETH_ALEN); + kalMemCopy(prP2pDev->perm_addr, prP2pDev->dev_addr, ETH_ALEN); + + if (glSetupP2P(prGlueInfo, prP2pWdev, prP2pDev, i, fgIsApMode) + != 0) { + DBGLOG(INIT, WARN, "glSetupP2P FAILED\n"); + free_netdev(prP2pDev); + return FALSE; + } + +#if (CFG_ENABLE_UNIFY_WIPHY == 0) + prHif = &prGlueInfo->rHifInfo; + glGetHifDev(prHif, &prDev); + if (!prDev) + DBGLOG(INIT, ERROR, "P2P[%d] parent dev is NULL\n", i); + set_wiphy_dev(prWiphy, prDev); +#endif + + i++; + /* prP2pInfo is alloc at glSetupP2P()->p2PAllocInfo() */ + prAdapter->prP2pInfo->u4DeviceNum++; + + /* set p2p net device register state */ + /* p2pNetRegister() will check prAdapter->rP2PNetRegState. */ + prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_UNREGISTERED; + } while (i < ucRegisterNum); + + return TRUE; +#if 0 +err_reg_netdev: + free_netdev(prGlueInfo->prP2PInfo->prDevHandler); +#endif +err_alloc_netdev: + return FALSE; +} /* end of glRegisterP2P() */ + +#if CFG_ENABLE_UNIFY_WIPHY +u_int8_t glP2pCreateWirelessDevice(struct GLUE_INFO *prGlueInfo) +{ + struct wiphy *prWiphy = wlanGetWiphy(); + struct wireless_dev *prWdev = NULL; + uint8_t i = 0; + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + if (!prWiphy) { + DBGLOG(P2P, ERROR, "unable to allocate wiphy for p2p\n"); + return FALSE; + } + + for (i = 0 ; i < KAL_P2P_NUM; i++) { + if (!gprP2pRoleWdev[i]) + break; + } + + if (i >= KAL_P2P_NUM) { + DBGLOG(INIT, WARN, "fail to register wiphy to driver\n"); + return FALSE; + } + + prWdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (!prWdev) { + DBGLOG(P2P, ERROR, "allocate p2p wdev fail, no memory\n"); + return FALSE; + } + + /* set priv as pointer to glue structure */ + prWdev->wiphy = prWiphy; + + gprP2pRoleWdev[i] = prWdev; + DBGLOG(INIT, TRACE, "glP2pCreateWirelessDevice (%p)\n", + gprP2pRoleWdev[i]->wiphy); + + return TRUE; +#else + return FALSE; +#endif +} +#else /* (CFG_ENABLE_UNIFY_WIPHY == 0) */ +u_int8_t glP2pCreateWirelessDevice(struct GLUE_INFO *prGlueInfo) +{ + struct wiphy *prWiphy = NULL; + struct wireless_dev *prWdev = NULL; + uint8_t i = 0; +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + prWdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (!prWdev) { + DBGLOG(P2P, ERROR, + "allocate p2p wireless device fail, no memory\n"); + return FALSE; + } + /* 1. allocate WIPHY */ + prWiphy = wiphy_new(&mtk_p2p_ops, sizeof(struct GLUE_INFO *)); + if (!prWiphy) { + DBGLOG(P2P, ERROR, "unable to allocate wiphy for p2p\n"); + goto free_wdev; + } + + prWiphy->interface_modes = BIT(NL80211_IFTYPE_AP) + | BIT(NL80211_IFTYPE_P2P_CLIENT) + | BIT(NL80211_IFTYPE_P2P_GO) + | BIT(NL80211_IFTYPE_STATION); + + prWiphy->software_iftypes |= BIT(NL80211_IFTYPE_P2P_DEVICE); + + prWiphy->iface_combinations = p_mtk_iface_combinations_p2p; + prWiphy->n_iface_combinations = mtk_iface_combinations_p2p_num; + + prWiphy->bands[KAL_BAND_2GHZ] = &mtk_band_2ghz; + prWiphy->bands[KAL_BAND_5GHZ] = &mtk_band_5ghz; + + prWiphy->mgmt_stypes = mtk_cfg80211_default_mgmt_stypes; + prWiphy->max_remain_on_channel_duration = 5000; + prWiphy->n_cipher_suites = 5; + prWiphy->cipher_suites = mtk_cipher_suites; +#if KERNEL_VERSION(3, 14, 0) > CFG80211_VERSION_CODE + prWiphy->flags = WIPHY_FLAG_CUSTOM_REGULATORY + | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL + | WIPHY_FLAG_HAVE_AP_SME; +#else +#if (CFG_SUPPORT_DFS_MASTER == 1) + prWiphy->flags = WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL + | WIPHY_FLAG_HAVE_AP_SME + | WIPHY_FLAG_HAS_CHANNEL_SWITCH; + prWiphy->max_num_csa_counters = 2; +#else + prWiphy->flags = WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL + | WIPHY_FLAG_HAVE_AP_SME; +#endif + prWiphy->regulatory_flags = REGULATORY_CUSTOM_REG; +#endif + prWiphy->ap_sme_capa = 1; + +#if CFG_ENABLE_OFFCHANNEL_TX + prWiphy->flags |= WIPHY_FLAG_OFFCHAN_TX; +#endif /* CFG_ENABLE_OFFCHANNEL_TX */ + prWiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER; + + prWiphy->max_scan_ssids = MAX_SCAN_LIST_NUM; + prWiphy->max_scan_ie_len = MAX_SCAN_IE_LEN; + prWiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE + prWiphy->vendor_commands = mtk_p2p_vendor_ops; + prWiphy->n_vendor_commands = sizeof(mtk_p2p_vendor_ops) + / sizeof(struct wiphy_vendor_command); + prWiphy->vendor_events = mtk_p2p_vendor_events; + prWiphy->n_vendor_events = ARRAY_SIZE(mtk_p2p_vendor_events); +#endif + +#ifdef CONFIG_PM +#if KERNEL_VERSION(3, 9, 0) > CFG80211_VERSION_CODE + prWiphy->wowlan = &mtk_p2p_wowlan_support; +#endif +#endif + +#if KERNEL_VERSION(3, 14, 0) < CFG80211_VERSION_CODE + prWiphy->max_ap_assoc_sta = P2P_MAXIMUM_CLIENT_COUNT; +#endif + + cfg80211_regd_set_wiphy(prWiphy); + + /* 2.1 set priv as pointer to glue structure */ + *((struct GLUE_INFO **) wiphy_priv(prWiphy)) = prGlueInfo; + /* Here are functions which need rtnl_lock */ + if (wiphy_register(prWiphy) < 0) { + DBGLOG(INIT, WARN, "fail to register wiphy for p2p\n"); + goto free_wiphy; + } + prWdev->wiphy = prWiphy; + + for (i = 0 ; i < KAL_P2P_NUM; i++) { + if (!gprP2pRoleWdev[i]) { + gprP2pRoleWdev[i] = prWdev; + DBGLOG(INIT, INFO, + "glP2pCreateWirelessDevice (%x)\n", + gprP2pRoleWdev[i]->wiphy); + break; + } + } + + if (i == KAL_P2P_NUM) + DBGLOG(INIT, WARN, "fail to register wiphy to driver\n"); + + return TRUE; + +free_wiphy: + wiphy_free(prWiphy); +free_wdev: + kfree(prWdev); +#endif + return FALSE; +} +#endif /* CFG_ENABLE_UNIFY_WIPHY */ + +/*---------------------------------------------------------------------------*/ +/*! + * \brief Unregister Net Device for Wi-Fi Direct + * + * \param[in] prGlueInfo Pointer to glue info + * [in] ucIdx The BSS with the idx will be freed. + * "ucIdx == 0xff" will free all BSSs. + * Only has meaning for "CFG_ENABLE_UNIFY_WIPHY == 1" + * + * \return TRUE + * FALSE + */ +/*---------------------------------------------------------------------------*/ +u_int8_t glUnregisterP2P(struct GLUE_INFO *prGlueInfo, uint8_t ucIdx) +{ + uint8_t ucRoleIdx; + struct ADAPTER *prAdapter; + struct GL_P2P_INFO *prP2PInfo = NULL; + int i4Start = 0, i4End = 0; + + ASSERT(prGlueInfo); + + if (ucIdx == 0xff) { + i4Start = 0; + i4End = BSS_P2P_NUM; + } else if (ucIdx < BSS_P2P_NUM) { + i4Start = ucIdx; + i4End = ucIdx + 1; + } else { + DBGLOG(INIT, WARN, "The ucIdx (%d) is a wrong value\n", ucIdx); + return FALSE; + } + + prAdapter = prGlueInfo->prAdapter; + + /* 4 <1> Uninit P2P dev FSM */ + /* Uninit P2P device FSM */ + /* only do p2pDevFsmUninit, when unregister all P2P device */ + if (ucIdx == 0xff) + p2pDevFsmUninit(prAdapter); + + /* 4 <2> Uninit P2P role FSM */ + for (ucRoleIdx = i4Start; ucRoleIdx < i4End; ucRoleIdx++) { + if (P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, ucRoleIdx)) { + /* FIXME: The cfg80211_XXX() is following the + * p2pRoleFsmUninit() sub-progress. + * ex: The cfg80211_del_sta() is called in the + * kalP2PGOStationUpdate(). + * But the netdev had be unregistered at + * p2pNetUnregister(). EXCEPTION!! + */ + p2pRoleFsmUninit(prGlueInfo->prAdapter, ucRoleIdx); + } + } + + /* 4 <3> Free Wiphy & netdev */ + for (ucRoleIdx = i4Start; ucRoleIdx < i4End; ucRoleIdx++) { + prP2PInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + + if (prP2PInfo == NULL) + continue; + /* For P2P interfaces, prDevHandler points to the net_device of + * p2p0 interface. And aprRoleHandler points to the net_device + * of p2p virtual interface (i.e., p2p1) when it was created. + * And when p2p virtual interface is deleted, aprRoleHandler + * will change to point to prDevHandler. Hence, when + * aprRoleHandler & prDevHandler are pointing to different + * addresses, it means vif p2p1 exists. Otherwise it means p2p1 + * was already deleted. + */ + if ((prP2PInfo->aprRoleHandler != NULL) && + (prP2PInfo->aprRoleHandler != prP2PInfo->prDevHandler)) { + /* This device is added by the P2P, and use + * ndev->destructor to free. The p2pDevFsmUninit() use + * prP2PInfo->aprRoleHandler to do some check. + */ + prP2PInfo->aprRoleHandler = NULL; + DBGLOG(P2P, INFO, "aprRoleHandler idx %d set NULL\n", + ucRoleIdx); + + /* Expect that gprP2pRoleWdev[ucRoleIdx] has been reset + * as gprP2pWdev or NULL in p2pNetUnregister + * (unregister_netdev). + */ + } + + if (prP2PInfo->prDevHandler) { + /* don't free the dev that share with the AIS */ + if (wlanIsAisDev(prP2PInfo->prDevHandler)) + gprP2pRoleWdev[ucRoleIdx] = NULL; + else { + if (prP2PInfo->prDevHandler->reg_state + == NETREG_REGISTERED) { + DBGLOG(INIT, WARN, + "Force unregister netdev\n"); + unregister_netdev( + prP2PInfo->prDevHandler); + prGlueInfo->prAdapter->rP2PNetRegState = + ENUM_NET_REG_STATE_UNREGISTERED; + } + free_netdev(prP2PInfo->prDevHandler); + } + prP2PInfo->prDevHandler = NULL; + } + + /* 4 <4> Free P2P internal memory */ + if (!p2PFreeInfo(prGlueInfo, ucRoleIdx)) { + /* FALSE: (fgIsP2PRegistered!=FALSE)||(ucRoleIdx err) */ + DBGLOG(INIT, ERROR, "p2PFreeInfo FAILED\n"); + return FALSE; + } + } + + return TRUE; +} /* end of glUnregisterP2P() */ + +/* 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 = *((struct GLUE_INFO **) 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, + (struct MSG_HDR *) prFuncSwitch, + MSG_SEND_METHOD_BUF); +#endif + + /* 2. carrier on & start TX queue */ + /*DFS todo 20161220_DFS*/ +#if (CFG_SUPPORT_DFS_MASTER == 1) + if (prDev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) { + /*netif_carrier_on(prDev);*/ + netif_tx_start_all_queues(prDev); + } +#else + /*netif_carrier_on(prDev);*/ + netif_tx_start_all_queues(prDev); +#endif + +#ifdef CONFIG_WIRELESS_EXT + prDev->wireless_handlers = &wext_handler_def; +#endif + + 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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct GL_P2P_DEV_INFO *prP2pGlueDevInfo = NULL; +/* P_MSG_P2P_FUNCTION_SWITCH_T prFuncSwitch; */ + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prDev); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + /* XXX: The p2pStop may be triggered after the wlanRemove. */ + /* And prGlueInfo->prP2PDevInfo is freed in p2PFreeInfo. */ + if (!prAdapter->fgIsP2PRegistered) + return -EFAULT; + + prP2pGlueDevInfo = prGlueInfo->prP2PDevInfo; + ASSERT(prP2pGlueDevInfo); + + /* 0. Do the scan done and set parameter to abort if the scan pending */ + /*DBGLOG(INIT, INFO, "p2pStop and ucRoleIdx = %u\n", ucRoleIdx);*/ + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if ((prP2pGlueDevInfo->prScanRequest != NULL) && + (prP2pGlueDevInfo->prScanRequest->wdev == prDev->ieee80211_ptr)) { + DBGLOG(INIT, INFO, "p2pStop and abort scan!!\n"); + kalCfg80211ScanDone(prP2pGlueDevInfo->prScanRequest, TRUE); + prP2pGlueDevInfo->prScanRequest = NULL; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + /* zero clear old acs information */ + kalMemZero(&(prGlueInfo->prAdapter->rWifiVar.rChnLoadInfo), + sizeof(prGlueInfo->prAdapter->rWifiVar.rChnLoadInfo)); + wlanInitChnLoadInfoChannelList(prGlueInfo->prAdapter); + + /* 1. stop TX queue */ + netif_tx_stop_all_queues(prDev); +#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 */ + 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, + (struct MSG_HDR *) prFuncSwitch, + MSG_SEND_METHOD_BUF); +#endif + /* 3. stop queue and turn off carrier */ + /* TH3 multiple P2P */ + /*prGlueInfo->prP2PInfo[0]->eState = MEDIA_STATE_DISCONNECTED;*/ + + netif_tx_stop_all_queues(prDev); + if (netif_carrier_ok(prDev)) + netif_carrier_off(prDev); + +#ifdef CONFIG_WIRELESS_EXT + prDev->wireless_handlers = NULL; +#endif + + 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) +{ + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate; + + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prDev); + kalMemCopy(&prNetDevPrivate->stats, &prDev->stats, + sizeof(struct net_device_stats)); +#if CFG_MTK_MDDP_WH_SUPPORT + mddpGetMdStats(prDev); +#endif + + return (struct net_device_stats *) kalGetStats(prDev); +} /* end of p2pGetStats() */ + +static void p2pSetMulticastList(IN struct net_device *prDev) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + + prGlueInfo = (prDev != NULL) + ? *((struct GLUE_INFO **) netdev_priv(prDev)) + : NULL; + + if (!prDev || !prGlueInfo) { + DBGLOG(INIT, WARN, + " abnormal dev or skb: prDev(0x%p), prGlueInfo(0x%p)\n", + prDev, prGlueInfo); + return; + } + + g_P2pPrDev = prDev; + + /* 4 Mark HALT, notify main thread to finish current job */ + set_bit(GLUE_FLAG_SUB_MOD_MULTICAST_BIT, &prGlueInfo->ulFlag); + /* 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(struct GLUE_INFO *prGlueInfo) +{ + uint32_t u4SetInfoLen = 0; + uint32_t u4McCount; + struct net_device *prDev = g_P2pPrDev; + + prGlueInfo = (prDev != NULL) + ? *((struct GLUE_INFO **) netdev_priv(prDev)) + : NULL; + + if (!prDev || !prGlueInfo) { + DBGLOG(INIT, WARN, + " abnormal dev or skb: prDev(0x%p), prGlueInfo(0x%p)\n", + prDev, prGlueInfo); + return; + } + + if (prDev->flags & IFF_PROMISC) + prGlueInfo->prP2PDevInfo->u4PacketFilter + |= PARAM_PACKET_FILTER_PROMISCUOUS; + + if (prDev->flags & IFF_BROADCAST) + prGlueInfo->prP2PDevInfo->u4PacketFilter + |= PARAM_PACKET_FILTER_BROADCAST; + u4McCount = netdev_mc_count(prDev); + + if (prDev->flags & IFF_MULTICAST) { + if ((prDev->flags & IFF_ALLMULTI) + || (u4McCount > MAX_NUM_GROUP_ADDR)) + prGlueInfo->prP2PDevInfo->u4PacketFilter + |= PARAM_PACKET_FILTER_ALL_MULTICAST; + else + prGlueInfo->prP2PDevInfo->u4PacketFilter + |= PARAM_PACKET_FILTER_MULTICAST; + } + + if (prGlueInfo->prP2PDevInfo->u4PacketFilter + & PARAM_PACKET_FILTER_MULTICAST) { + /* Prepare multicast address list */ + struct netdev_hw_addr *ha; + uint32_t i = 0; + + /* Avoid race condition with kernel net subsystem */ + netif_addr_lock_bh(prDev); + + netdev_for_each_mc_addr(ha, prDev) { + /* If ha is null, it will break the loop. */ + /* Check mc count before accessing to ha to + * prevent from kernel crash. + */ + if (i == u4McCount || !ha) + break; + if (i < MAX_NUM_GROUP_ADDR) { + COPY_MAC_ADDR( + &(prGlueInfo->prP2PDevInfo + ->aucMCAddrList[i]), + GET_ADDR(ha)); + i++; + } + } + + netif_addr_unlock_bh(prDev); + + DBGLOG(P2P, TRACE, "SEt Multicast Address List\n"); + + if (i >= MAX_NUM_GROUP_ADDR) + return; + wlanoidSetP2PMulticastList(prGlueInfo->prAdapter, + &(prGlueInfo->prP2PDevInfo->aucMCAddrList[0]), + (i * ETH_ALEN), &u4SetInfoLen); + + } + +} /* 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. + */ +/*---------------------------------------------------------------------------*/ +netdev_tx_t p2pHardStartXmit(IN struct sk_buff *prSkb, + IN struct net_device *prDev) +{ + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = + (struct NETDEV_PRIVATE_GLUE_INFO *) NULL; + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t ucBssIndex; + struct BSS_INFO *prP2pBssInfo = NULL; + + ASSERT(prSkb); + ASSERT(prDev); + + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prDev); + prGlueInfo = prNetDevPrivate->prGlueInfo; + ucBssIndex = prNetDevPrivate->ucBssIdx; + + kalResetPacket(prGlueInfo, (void *) prSkb); + + kalHardStartXmit(prSkb, prDev, prGlueInfo, ucBssIndex); + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, ucBssIndex); + if ((prP2pBssInfo->eConnectionState == MEDIA_STATE_CONNECTED) || + (prP2pBssInfo->rStaRecOfClientList.u4NumElem > 0)) + kalPerMonStart(prGlueInfo); + + return NETDEV_TX_OK; +} /* end of p2pHardStartXmit() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief A method of struct net_device, a primary SOCKET interface to configure + * the interface lively. Handle an ioctl call on one of our devices. + * Everything Linux ioctl specific is done here. + * Then we pass the contents + * of the ifr->data to the request message handler. + * + * \param[in] prDev Linux kernel netdevice + * + * \param[in] prIFReq Our private ioctl request structure, + * typed for the generic struct ifreq + * so we can use ptr to function + * + * \param[in] cmd Command ID + * + * \retval 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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int ret = 0; + /* char *prExtraBuf = NULL; */ + /* UINT_32 u4ExtraSize = 0; */ + /* struct iwreq *prIwReq = (struct iwreq *)prIfReq; */ + /* struct iw_request_info rIwReqInfo; */ + + ASSERT(prDev && prIfReq); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + if (!prGlueInfo) { + DBGLOG(P2P, ERROR, "prGlueInfo is NULL\n"); + return -EFAULT; + } + + if (prGlueInfo->u4ReadyFlag == 0) { + DBGLOG(P2P, ERROR, "Adapter is not ready\n"); + return -EINVAL; + } + + if (i4Cmd == SIOCGIWPRIV) { + ret = wext_support_ioctl(prDev, prIfReq, i4Cmd); + } else if ((i4Cmd >= SIOCIWFIRSTPRIV) && (i4Cmd < SIOCIWLASTPRIV)) { + /* 0x8BE0 ~ 0x8BFF, private ioctl region */ + ret = priv_support_ioctl(prDev, prIfReq, i4Cmd); + } else if (i4Cmd == SIOCDEVPRIVATE + 1) { +#ifdef CFG_ANDROID_AOSP_PRIV_CMD + ret = android_private_support_driver_cmd(prDev, prIfReq, i4Cmd); +#else + ret = priv_support_driver_cmd(prDev, prIfReq, i4Cmd); +#endif /* CFG_ANDROID_AOSP_PRIV_CMD */ + } else { + DBGLOG(INIT, WARN, "Unexpected ioctl command: 0x%04x\n", i4Cmd); + ret = -1; + } + +#if 0 + /* 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)) { + DBGLOG(INIT, 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: +#if 0 + ret = rP2PIwPrivHandler[i4Cmd - SIOCIWFIRSTPRIV](prDev, + &rIwReqInfo, + &(prIwReq->u), + (char *)&(prIwReq->u)); +#endif + 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; + } +#endif /* 0 */ + + return ret; +} /* end of p2pDoIOCTL() */ + + +/*---------------------------------------------------------------------------*/ +/*! + * \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) +{ + struct ADAPTER *prAdapter = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct sockaddr *sa = NULL; + struct BSS_INFO *prBssInfo = NULL; + struct BSS_INFO *prDevBssInfo = NULL; + uint8_t ucRoleIdx = 0, ucBssIdx = 0; + struct GL_P2P_INFO *prP2pInfo = NULL; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + if (!prDev || !addr) { + DBGLOG(INIT, ERROR, "Set macaddr with ndev(%d) and addr(%d)\n", + (prDev == NULL) ? 0 : 1, (addr == NULL) ? 0 : 1); + return -EINVAL; + } + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prDev, &ucRoleIdx) != 0) { + DBGLOG(INIT, ERROR, "can't find the matched dev"); + return -EINVAL; + } + + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, + ucRoleIdx, &ucBssIdx) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "can't find the matched bss"); + return -EINVAL; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + if (!prBssInfo) { + DBGLOG(INIT, ERROR, "bss is not active\n"); + return -EINVAL; + } + + prDevBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prAdapter->ucP2PDevBssIdx); + if (!prDevBssInfo) { + DBGLOG(INIT, ERROR, "dev bss is not active\n"); + return -EINVAL; + } + + prP2pInfo = prGlueInfo->prP2PInfo[0]; + if (!prP2pInfo) { + DBGLOG(INIT, ERROR, "p2p info is null\n"); + return -EINVAL; + } + + sa = (struct sockaddr *)addr; + + COPY_MAC_ADDR(prBssInfo->aucOwnMacAddr, sa->sa_data); + COPY_MAC_ADDR(prDev->dev_addr, sa->sa_data); + COPY_MAC_ADDR(prAdapter->rWifiVar.aucInterfaceAddress[ucRoleIdx], + sa->sa_data); + + if ((prP2pInfo->prDevHandler == prDev) + && mtk_IsP2PNetDevice(prGlueInfo, prDev)) { + COPY_MAC_ADDR(prAdapter->rWifiVar.aucDeviceAddress, + sa->sa_data); + COPY_MAC_ADDR(prDevBssInfo->aucOwnMacAddr, sa->sa_data); + DBGLOG(INIT, INFO, + "[%d][%d] Set random macaddr to " MACSTR ".\n", + ucBssIdx, + prDevBssInfo->ucBssIndex, + MAC2STR(prDevBssInfo->aucOwnMacAddr)); + } else { + DBGLOG(INIT, INFO, + "[%d] Set random macaddr to " MACSTR ".\n", + ucBssIdx, + MAC2STR(prBssInfo->aucOwnMacAddr)); + } + + return WLAN_STATUS_SUCCESS; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_p2p_cfg80211.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_p2p_cfg80211.c new file mode 100644 index 0000000000000..83f6532b218a1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_p2p_cfg80211.c @@ -0,0 +1,4262 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 + ****************************************************************************** + */ + +#include "config.h" + +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#include +#include +#include +#include +#include + +#include "precomp.h" +#include "gl_cfg80211.h" +#include "gl_p2p_os.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 + ****************************************************************************** + */ + +#if CFG_ENABLE_UNIFY_WIPHY +#define P2P_WIPHY_PRIV(_wiphy, _priv) \ + (_priv = (struct GLUE_INFO *) wiphy_priv(_wiphy)) +#else +#define P2P_WIPHY_PRIV(_wiphy, _priv) \ + (_priv = *((struct GLUE_INFO **) wiphy_priv(_wiphy))) +#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 + ****************************************************************************** + */ + +int32_t mtk_Netdev_To_RoleIdx(struct GLUE_INFO *prGlueInfo, + struct net_device *ndev, uint8_t *pucRoleIdx) +{ + int32_t i4Ret = -1; + uint32_t u4Idx = 0; + + if ((pucRoleIdx == NULL) || (ndev == NULL)) + return i4Ret; +#if 0 + for (u4Idx = 0; u4Idx < KAL_P2P_NUM; u4Idx++) { + if (prGlP2pInfo->aprRoleHandler[u4Idx] == ndev) { + *pucRoleIdx = (uint8_t) u4Idx; + i4Ret = 0; + } + } +#if 1 + i4Ret = 0; + *pucRoleIdx = 0; +#endif +#else + /* The prP2PInfo[0] may be removed and prP2PInfo[1] is existing + * under cfg80211 operation. So that check all KAL_P2P_NUM not only + * prGlueInfo->prAdapter->prP2pInfo->u4DeviceNum. + */ + for (u4Idx = 0; u4Idx < KAL_P2P_NUM; u4Idx++) { + if ((prGlueInfo->prP2PInfo[u4Idx] != NULL) && + (prGlueInfo->prP2PInfo[u4Idx]->aprRoleHandler != NULL) && + (prGlueInfo->prP2PInfo[u4Idx]->aprRoleHandler == ndev)) { + *pucRoleIdx = (uint8_t) u4Idx; + i4Ret = 0; + } + } +#endif + + return i4Ret; + +} /* mtk_Netdev_To_RoleIdx */ + +static void mtk_vif_destructor(struct net_device *dev) +{ + struct wireless_dev *prWdev = ERR_PTR(-ENOMEM); + uint32_t u4Idx = 0; + + DBGLOG(P2P, INFO, "mtk_vif_destructor\n"); + if (dev) { + prWdev = dev->ieee80211_ptr; + free_netdev(dev); + /* Expect that the gprP2pWdev isn't freed here */ + if ((prWdev) && (prWdev != gprP2pWdev)) { + /* Role[i] and Dev share the same wdev by default */ + for (u4Idx = 0; u4Idx < KAL_P2P_NUM; u4Idx++) { + if (prWdev != gprP2pRoleWdev[u4Idx]) + continue; + /* In the initWlan gprP2pRoleWdev[0] is equal to + * gprP2pWdev. And other gprP2pRoleWdev[] should + * be NULL, if the 2nd P2P dev isn't created. + */ + if (u4Idx == 0) + gprP2pRoleWdev[u4Idx] = gprP2pWdev; + else + gprP2pRoleWdev[u4Idx] = NULL; + break; + } + kfree(prWdev); + } + } +} + +#if KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE +struct wireless_dev *mtk_p2p_cfg80211_add_iface(struct wiphy *wiphy, + const char *name, unsigned char name_assign_type, + enum nl80211_iftype type, u32 *flags, struct vif_params *params) +#else +struct wireless_dev *mtk_p2p_cfg80211_add_iface(struct wiphy *wiphy, + const char *name, + enum nl80211_iftype type, u32 *flags, struct vif_params *params) +#endif +{ + /* 2 TODO: Fit kernel 3.10 modification */ + struct ADAPTER *prAdapter; + struct GLUE_INFO *prGlueInfo = NULL; + struct net_device *prNewNetDevice = NULL; + uint32_t u4Idx = 0; + struct GL_P2P_INFO *prP2pInfo = NULL; + struct GL_HIF_INFO *prHif = NULL; + struct MSG_P2P_SWITCH_OP_MODE *prSwitchModeMsg = NULL; + struct wireless_dev *prWdev = NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = NULL; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPriv = NULL; + uint8_t rMacAddr[PARAM_MAC_ADDR_LEN]; + struct MSG_P2P_ACTIVE_DEV_BSS *prMsgActiveBss = NULL; + struct mt66xx_chip_info *prChipInfo; + struct wireless_dev *prOrigWdev = NULL; + + do { + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (prGlueInfo == NULL) + return ERR_PTR(-EINVAL); + + prAdapter = prGlueInfo->prAdapter; + prChipInfo = prAdapter->chip_info; + + for (u4Idx = 0; u4Idx < KAL_P2P_NUM; u4Idx++) { + prP2pInfo = prGlueInfo->prP2PInfo[u4Idx]; + /* Expect that only create the new dev with the p2p0 */ + if (prP2pInfo == NULL) + continue; + if (prP2pInfo->aprRoleHandler == + prP2pInfo->prDevHandler) + break; + if (prP2pInfo->aprRoleHandler == NULL) { + p2pRoleFsmInit(prGlueInfo->prAdapter, u4Idx); + init_completion(&prP2pInfo->rStopApComp); + break; + } + } + + /*u4Idx = 0;*/ + DBGLOG(P2P, TRACE, "%s: u4Idx=%d\n", __func__, u4Idx); + + if (u4Idx == KAL_P2P_NUM) { + /* Role port full. */ + return ERR_PTR(-EINVAL); + } + + prP2pInfo = prGlueInfo->prP2PInfo[u4Idx]; + + /* Alloc all resource here to avoid do unregister_netdev for + * error case (kernel exception). + */ +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE + prNewNetDevice = alloc_netdev_mq( + sizeof(struct NETDEV_PRIVATE_GLUE_INFO), name, + NET_NAME_PREDICTABLE, ether_setup, CFG_MAX_TXQ_NUM); +#else + prNewNetDevice = alloc_netdev_mq( + sizeof(struct NETDEV_PRIVATE_GLUE_INFO), name, + ether_setup, CFG_MAX_TXQ_NUM); +#endif + + if (prNewNetDevice == NULL) { + DBGLOG(P2P, ERROR, "can't alloc prNewNetDevice\n"); + break; + } + + prWdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (prWdev == NULL) { + DBGLOG(P2P, ERROR, "can't alloc prWdev\n"); + break; + } + + prSwitchModeMsg = (struct MSG_P2P_SWITCH_OP_MODE *) cnmMemAlloc( + prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_P2P_SWITCH_OP_MODE)); + if (prSwitchModeMsg == NULL) { + DBGLOG(P2P, ERROR, "can't alloc prSwitchModeMsg\n"); + break; + } + + prMsgActiveBss = (struct MSG_P2P_ACTIVE_DEV_BSS *) cnmMemAlloc( + prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_P2P_ACTIVE_DEV_BSS)); + + if (prMsgActiveBss == NULL) { + DBGLOG(P2P, ERROR, "can't alloc prMsgActiveBss\n"); + break; + } + + DBGLOG(P2P, INFO, "type: %d, name = %s, netdev: 0x%p\n", + type, name, prNewNetDevice); + + prP2pInfo->aprRoleHandler = prNewNetDevice; + *((struct GLUE_INFO **) netdev_priv(prNewNetDevice)) = + prGlueInfo; + prNewNetDevice->needed_headroom = + NIC_TX_DESC_AND_PADDING_LENGTH + + prChipInfo->txd_append_size; + prNewNetDevice->netdev_ops = &p2p_netdev_ops; + + prHif = &prGlueInfo->rHifInfo; + ASSERT(prHif); + +#if defined(_HIF_SDIO) +#if (MTK_WCN_HIF_SDIO == 0) + SET_NETDEV_DEV(prNewNetDevice, &(prHif->func->dev)); +#endif +#endif + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + kalMemCopy(prWdev, gprP2pWdev, sizeof(struct wireless_dev)); + prWdev->netdev = prNewNetDevice; + prWdev->iftype = type; + prNewNetDevice->ieee80211_ptr = prWdev; + /* register destructor function for virtual interface */ +#if KERNEL_VERSION(4, 14, 0) <= CFG80211_VERSION_CODE + prNewNetDevice->priv_destructor = mtk_vif_destructor; +#else + prNewNetDevice->destructor = mtk_vif_destructor; +#endif + /* The prOrigWdev is used to do error handle. If return fail, + * set the gprP2pRoleWdev[u4Idx] to original value. + * Expect that the gprP2pRoleWdev[0] = gprP2pWdev, and the + * other is NULL. + */ + prOrigWdev = gprP2pRoleWdev[u4Idx]; + gprP2pRoleWdev[u4Idx] = prWdev; + /*prP2pInfo->prRoleWdev[0] = prWdev;*//* TH3 multiple P2P */ +#endif + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + /* set HW checksum offload */ + if (prAdapter->fgIsSupportCsumOffload) + prNewNetDevice->features |= NETIF_F_IP_CSUM + | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + kalResetStats(prNewNetDevice); + /* net device initialize */ + + /* register for net device */ + if (register_netdevice(prP2pInfo->aprRoleHandler) < 0) { + DBGLOG(INIT, WARN, + "unable to register netdevice for p2p\n"); + break; + + } else { + DBGLOG(P2P, TRACE, "register_netdev OK\n"); + prGlueInfo->prAdapter->rP2PNetRegState = + ENUM_NET_REG_STATE_REGISTERED; + + netif_carrier_off(prP2pInfo->aprRoleHandler); + netif_tx_stop_all_queues(prP2pInfo->aprRoleHandler); + } + prP2pRoleFsmInfo = prAdapter->rWifiVar.aprP2pRoleFsmInfo[u4Idx]; + + /* 13. bind netdev pointer to netdev index */ + wlanBindBssIdxToNetInterface(prGlueInfo, + prP2pRoleFsmInfo->ucBssIndex, + (void *) prP2pInfo->aprRoleHandler); + prNetDevPriv = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prP2pInfo->aprRoleHandler); + prNetDevPriv->prGlueInfo = prGlueInfo; + prNetDevPriv->ucBssIdx = prP2pRoleFsmInfo->ucBssIndex; +#if CFG_ENABLE_UNIFY_WIPHY + /* Expect that only P2P device uses the cfg80211_add_iface */ + prNetDevPriv->ucIsP2p = TRUE; +#endif + + /* 4.2 fill hardware address */ + COPY_MAC_ADDR(rMacAddr, prAdapter->rMyMacAddr); + if (prGlueInfo->prAdapter->rWifiVar.ucP2pShareMacAddr && + (type == NL80211_IFTYPE_P2P_CLIENT + || type == NL80211_IFTYPE_P2P_GO)) { + rMacAddr[0] = gPrP2pDev[0]->dev_addr[0]; + } else { + /* change to local administrated address */ + rMacAddr[0] |= 0x2; + if (u4Idx > 0) + rMacAddr[0] ^= u4Idx << 2; + else + rMacAddr[0] ^= + prGlueInfo->prAdapter + ->prP2pInfo->u4DeviceNum << 2; + } + kalMemCopy(prNewNetDevice->dev_addr, rMacAddr, ETH_ALEN); + kalMemCopy(prNewNetDevice->perm_addr, rMacAddr, ETH_ALEN); + + DBGLOG(P2P, TRACE, + "mtk_p2p_cfg80211_add_iface ucBssIdx=%d\n", + prNetDevPriv->ucBssIdx); + + /* Switch OP MOde. */ + prSwitchModeMsg->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; + prSwitchModeMsg->ucRoleIdx = 0; + switch (type) { + case NL80211_IFTYPE_P2P_CLIENT: + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_P2P_CLIENT.\n"); + prSwitchModeMsg->eIftype = IFTYPE_P2P_CLIENT; + prSwitchModeMsg->eOpMode = OP_MODE_INFRASTRUCTURE; + kalP2PSetRole(prGlueInfo, 1, u4Idx); + break; + case NL80211_IFTYPE_STATION: + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_STATION.\n"); + prSwitchModeMsg->eIftype = IFTYPE_STATION; + prSwitchModeMsg->eOpMode = OP_MODE_INFRASTRUCTURE; + kalP2PSetRole(prGlueInfo, 1, u4Idx); + break; + case NL80211_IFTYPE_AP: + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_AP.\n"); + prSwitchModeMsg->eIftype = IFTYPE_AP; + prSwitchModeMsg->eOpMode = OP_MODE_ACCESS_POINT; + kalP2PSetRole(prGlueInfo, 2, u4Idx); + break; + case NL80211_IFTYPE_P2P_GO: + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_P2P_GO not AP.\n"); + prSwitchModeMsg->eIftype = IFTYPE_P2P_GO; + prSwitchModeMsg->eOpMode = OP_MODE_ACCESS_POINT; + kalP2PSetRole(prGlueInfo, 2, u4Idx); + break; + default: + DBGLOG(P2P, TRACE, "Other type :%d .\n", type); + prSwitchModeMsg->eIftype = IFTYPE_P2P_DEVICE; + prSwitchModeMsg->eOpMode = OP_MODE_P2P_DEVICE; + kalP2PSetRole(prGlueInfo, 0, u4Idx); + break; + } + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prSwitchModeMsg, + MSG_SEND_METHOD_BUF); + + /* Send Msg to DevFsm and active P2P dev BSS */ + prMsgActiveBss->rMsgHdr.eMsgId = MID_MNY_P2P_ACTIVE_BSS; + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prMsgActiveBss, MSG_SEND_METHOD_BUF); + /* Success */ + return prWdev; + } while (FALSE); + + /* Start Error Handle */ + + if (prNewNetDevice != NULL) { + free_netdev(prNewNetDevice); + prP2pInfo->aprRoleHandler = NULL; + } + + if (prWdev != NULL) { + kfree(prWdev); + + if ((gprP2pRoleWdev[u4Idx] != NULL) && + (gprP2pRoleWdev[u4Idx] != gprP2pWdev)) { + gprP2pRoleWdev[u4Idx] = prOrigWdev; + } + } + + if (prSwitchModeMsg != NULL) + cnmMemFree(prAdapter, prSwitchModeMsg); + + if (prMsgActiveBss != NULL) + cnmMemFree(prAdapter, prMsgActiveBss); + + return ERR_PTR(-ENOMEM); +} /* mtk_p2p_cfg80211_add_iface */ + +int mtk_p2p_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev) +{ +#if 0 + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + struct MSG_P2P_DEL_IFACE *prP2pDelIfaceMsg = + (struct MSG_P2P_DEL_IFACE *) NULL; + struct MSG_P2P_ACTIVE_DEV_BSS *prMsgActiveBss = + (struct MSG_P2P_ACTIVE_DEV_BSS *) NULL; + + prGlueInfo = *((struct GLUE_INFO **) wiphy_priv(wiphy)); + if (prGlueInfo == NULL) + return -EINVAL; + + prP2pDelIfaceMsg = (struct MSG_P2P_DEL_IFACE *) + cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_P2P_DEL_IFACE)); + + if (prP2pDelIfaceMsg == NULL) { + ASSERT(FALSE); + DBGLOG(INIT, WARN, "unable to alloc msg\n"); + } else { + prP2pDelIfaceMsg->rMsgHdr.eMsgId = MID_MNY_P2P_DEL_IFACE; + prP2pDelIfaceMsg->ucRoleIdx = 0; + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prP2pDelIfaceMsg, + MSG_SEND_METHOD_BUF); + + /* Send Msg to DevFsm and Deactive P2P dev BSS */ + prMsgActiveBss = cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_P2P_ACTIVE_DEV_BSS)); + prMsgActiveBss->rMsgHdr.eMsgId = MID_MNY_P2P_ACTIVE_BSS; + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prMsgActiveBss, + MSG_SEND_METHOD_BUF); + } + +#else + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + struct MSG_P2P_DEL_IFACE *prP2pDelIfaceMsg = + (struct MSG_P2P_DEL_IFACE *) NULL; + struct ADAPTER *prAdapter; + struct GL_P2P_INFO *prP2pInfo = (struct GL_P2P_INFO *) NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct GL_P2P_DEV_INFO *prP2pGlueDevInfo = + (struct GL_P2P_DEV_INFO *) NULL; + struct net_device *UnregRoleHander = (struct net_device *)NULL; + unsigned char ucBssIdx = 0; + struct BSS_INFO *prP2pBssInfo = NULL; +#if 1 + struct cfg80211_scan_request *prScanRequest = NULL; +#endif + + GLUE_SPIN_LOCK_DECLARATION(); + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_del_iface\n"); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (prGlueInfo == NULL) + return -EINVAL; + + prAdapter = prGlueInfo->prAdapter; + prP2pInfo = prGlueInfo->prP2PInfo[0]; + prP2pGlueDevInfo = prGlueInfo->prP2PDevInfo; + + if ((prP2pInfo == NULL) || + (prP2pInfo->aprRoleHandler == NULL) || + (prP2pInfo->aprRoleHandler == prP2pInfo->prDevHandler)) { + /* This iface isn't added. */ + return -EINVAL; + } + + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_DEL_INF); + + prP2pRoleFsmInfo = prAdapter->rWifiVar.aprP2pRoleFsmInfo[0]; + if (prP2pRoleFsmInfo == NULL) { + KAL_RELEASE_MUTEX(prAdapter, MUTEX_DEL_INF); + return -EINVAL; + } + + ucBssIdx = prP2pRoleFsmInfo->ucBssIndex; + wlanBindBssIdxToNetInterface(prGlueInfo, ucBssIdx, + (void *) prGlueInfo->prP2PInfo[0]->prDevHandler); + + UnregRoleHander = prP2pInfo->aprRoleHandler; + + /* fix that the kernel warning occures when the GC is connected */ + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + if ((prP2pBssInfo != NULL) && + (prP2pBssInfo->eConnectionState == MEDIA_STATE_CONNECTED) && + (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) { +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 2, 0) <= CFG80211_VERSION_CODE) + cfg80211_disconnected(UnregRoleHander, 0, NULL, 0, TRUE, + GFP_KERNEL); +#else + cfg80211_disconnected(UnregRoleHander, 0, NULL, 0, GFP_KERNEL); +#endif + } + + /* Wait for kalSendCompleteAndAwakeQueue() complete */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + prP2pInfo->aprRoleHandler = prP2pInfo->prDevHandler; +#if 1 + prScanRequest = prP2pGlueDevInfo->prScanRequest; + if ((prScanRequest != NULL) && + (prScanRequest->wdev == UnregRoleHander->ieee80211_ptr)) { + kalCfg80211ScanDone(prScanRequest, TRUE); + prP2pGlueDevInfo->prScanRequest = NULL; + } +#else + /* 2017/12/18: This part is for error case that p2p-p2p0-0 which is + * deleted when doing scan causes some exception for scan done action. + * The newest driver doesn't observed this error case, so just do the + * normal scan done process (use prP2pGlueDevInfo->prScanRequest, not + * prP2pGlueDevInfo->rBackupScanRequest). Keep this part for the + * reference, if the exception case occurs again. + * Can reference the related part in the mtk_p2p_cfg80211_scan. + */ + if (prP2pGlueDevInfo->prScanRequest != NULL) { + /* Check the wdev with backup scan req due to */ + /* the kernel will free this request by error handling */ + if (prP2pGlueDevInfo->rBackupScanRequest.wdev + == UnregRoleHander->ieee80211_ptr) { + kalCfg80211ScanDone( + &(prP2pGlueDevInfo->rBackupScanRequest), TRUE); + /* clear the request to avoid the Role FSM + * calls the scan_done again + */ + prP2pGlueDevInfo->prScanRequest = NULL; + } + } +#endif + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + /* prepare for removal */ + if (netif_carrier_ok(UnregRoleHander)) + netif_carrier_off(UnregRoleHander); + + netif_tx_stop_all_queues(UnregRoleHander); + + /* Here are functions which need rtnl_lock */ + unregister_netdevice(UnregRoleHander); + /* free is called at destructor */ + /* free_netdev(UnregRoleHander); */ + + KAL_RELEASE_MUTEX(prAdapter, MUTEX_DEL_INF); + + prP2pDelIfaceMsg = (struct MSG_P2P_DEL_IFACE *) + cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_P2P_DEL_IFACE)); + + if (prP2pDelIfaceMsg == NULL) { + DBGLOG(INIT, WARN, "unable to alloc msg\n"); + } else { + prP2pDelIfaceMsg->rMsgHdr.eMsgId = MID_MNY_P2P_DEL_IFACE; + prP2pDelIfaceMsg->ucRoleIdx = 0; + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prP2pDelIfaceMsg, + MSG_SEND_METHOD_BUF); + } +#endif + return 0; +} /* mtk_p2p_cfg80211_del_iface */ + +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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Rslt = -EINVAL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + struct P2P_PARAM_KEY rKey; + uint8_t ucRoleIdx = 0; + const uint8_t aucBCAddr[] = BC_MAC_ADDR; + /* const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; */ + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, ndev, &ucRoleIdx) != 0) + return -EINVAL; + + DBGLOG(RSN, TRACE, "mtk_p2p_cfg80211_add_key\n"); +#if DBG + if (mac_addr) { + DBGLOG(RSN, INFO, + "keyIdx = %d pairwise = %d mac = " MACSTR "\n", + key_index, pairwise, MAC2STR(mac_addr)); + } else { + DBGLOG(RSN, INFO, + "keyIdx = %d pairwise = %d null mac\n", + key_index, pairwise); + } + DBGLOG(RSN, TRACE, "Cipher = %x\n", params->cipher); + DBGLOG_MEM8(RSN, TRACE, params->key, params->key_len); +#endif + + if (params->key_len > 32) { + DBGLOG(RSN, WARN, "key_len [%d] is invalid!\n", + params->key_len); + return -EINVAL; + } + + /* Todo:: By Cipher to set the key */ + + kalMemZero(&rKey, sizeof(struct P2P_PARAM_KEY)); + + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, + ucRoleIdx, &rKey.ucBssIdx) != WLAN_STATUS_SUCCESS) + return -EINVAL; + + rKey.u4KeyIndex = key_index; + + if (params->cipher) { + switch (params->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + rKey.ucCipher = CIPHER_SUITE_WEP40; + break; + case WLAN_CIPHER_SUITE_WEP104: + rKey.ucCipher = CIPHER_SUITE_WEP104; + break; +#if 0 + case WLAN_CIPHER_SUITE_WEP128: + rKey.ucCipher = CIPHER_SUITE_WEP128; + break; +#endif + case WLAN_CIPHER_SUITE_TKIP: + rKey.ucCipher = CIPHER_SUITE_TKIP; + break; + case WLAN_CIPHER_SUITE_CCMP: + rKey.ucCipher = CIPHER_SUITE_CCMP; + break; +#if 0 + case WLAN_CIPHER_SUITE_GCMP: + rKey.ucCipher = CIPHER_SUITE_GCMP; + break; + case WLAN_CIPHER_SUITE_CCMP_256: + rKey.ucCipher = CIPHER_SUITE_CCMP256; + break; +#endif + case WLAN_CIPHER_SUITE_SMS4: + rKey.ucCipher = CIPHER_SUITE_WPI; + break; + case WLAN_CIPHER_SUITE_AES_CMAC: + rKey.ucCipher = CIPHER_SUITE_BIP; + break; + default: + ASSERT(FALSE); + } + } + + /* For BC addr case: ex: AP mode, + * driver_nl80211 will not have mac_addr + */ + if (pairwise) { + rKey.u4KeyIndex |= BIT(31); /* Tx */ + rKey.u4KeyIndex |= BIT(30); /* Pairwise */ + COPY_MAC_ADDR(rKey.arBSSID, mac_addr); + } else { + COPY_MAC_ADDR(rKey.arBSSID, aucBCAddr); + } + + /* Check if add key under AP mode */ + if (kalP2PGetRole(prGlueInfo, ucRoleIdx) == 2) + rKey.u4KeyIndex |= BIT(28); /* authenticator */ + + + if (params->key) + kalMemCopy(rKey.aucKeyMaterial, params->key, params->key_len); + rKey.u4KeyLength = params->key_len; + rKey.u4Length = OFFSET_OF(struct P2P_PARAM_KEY, aucKeyMaterial) + + rKey.u4KeyLength; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAddKey, + &rKey, rKey.u4Length, FALSE, FALSE, 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 *)) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + /* not implemented yet */ + DBGLOG(RSN, INFO, "not support this func\n"); + + return -EINVAL; +} + +int mtk_p2p_cfg80211_del_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, bool pairwise, const u8 *mac_addr) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_REMOVE_KEY rRemoveKey; + int32_t i4Rslt = -EINVAL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + uint8_t ucRoleIdx = 0; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + DBGLOG(RSN, TRACE, "mtk_p2p_cfg80211_del_key\n"); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, ndev, &ucRoleIdx) < 0) + return -EINVAL; +#if DBG + if (mac_addr) { + DBGLOG(RSN, TRACE, + "keyIdx = %d pairwise = %d mac = " MACSTR "\n", + key_index, pairwise, MAC2STR(mac_addr)); + } else { + DBGLOG(RSN, TRACE, + "keyIdx = %d pairwise = %d null mac\n", + key_index, pairwise); + } +#endif + + kalMemZero(&rRemoveKey, sizeof(struct PARAM_REMOVE_KEY)); + + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, + ucRoleIdx, &rRemoveKey.ucBssIdx) != WLAN_STATUS_SUCCESS) + return -EINVAL; + + if (mac_addr) + COPY_MAC_ADDR(rRemoveKey.arBSSID, mac_addr); + rRemoveKey.u4KeyIndex = key_index; + rRemoveKey.u4Length = sizeof(struct PARAM_REMOVE_KEY); + if (mac_addr) { + COPY_MAC_ADDR(rRemoveKey.arBSSID, mac_addr); + rRemoveKey.u4KeyIndex |= BIT(30); + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRemoveKey, + &rRemoveKey, rRemoveKey.u4Length, + FALSE, FALSE, 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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_DEFAULT_KEY rDefaultKey; + uint8_t ucRoleIdx = 0; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + int32_t i4Rst = -EINVAL; + uint32_t u4BufLen = 0; + u_int8_t fgDef = FALSE, fgMgtDef = FALSE; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + DBGLOG(RSN, TRACE, "mtk_p2p_cfg80211_set_default_key\n"); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, netdev, &ucRoleIdx) != 0) + return -EINVAL; +#if DBG + DBGLOG(RSN, TRACE, + "keyIdx = %d unicast = %d multicast = %d\n", + key_index, unicast, multicast); +#endif + + + /* For wep case, this set the key for tx */ + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, + ucRoleIdx, &rDefaultKey.ucBssIdx) != WLAN_STATUS_SUCCESS) + return -EINVAL; + + + rDefaultKey.ucKeyID = key_index; + rDefaultKey.ucUnicast = unicast; + rDefaultKey.ucMulticast = multicast; + if (rDefaultKey.ucUnicast && !rDefaultKey.ucMulticast) + return WLAN_STATUS_SUCCESS; + + if (rDefaultKey.ucUnicast && rDefaultKey.ucMulticast) + fgDef = TRUE; + + if (!rDefaultKey.ucUnicast && rDefaultKey.ucMulticast) + fgMgtDef = TRUE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetDefaultKey, + &rDefaultKey, + sizeof(struct PARAM_DEFAULT_KEY), + FALSE, FALSE, TRUE, &u4BufLen); + + + if (rStatus == WLAN_STATUS_SUCCESS) + i4Rst = 0; + + + return i4Rst; +} + +/*---------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for setting the default mgmt key index + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*---------------------------------------------------------------------------*/ +int mtk_p2p_cfg80211_set_mgmt_key(struct wiphy *wiphy, + struct net_device *dev, u8 key_index) +{ + DBGLOG(RSN, INFO, "mtk_p2p_cfg80211_set_mgmt_key, kid:%d\n", key_index); + + return 0; +} + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, struct station_info *sinfo) +#else +int mtk_p2p_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, struct station_info *sinfo) +#endif +{ + int32_t i4RetRslt = -EINVAL; + int32_t i4Rssi = 0; + uint8_t ucRoleIdx = 0; + uint8_t ucBssIdx = 0; + uint32_t u4Rate = 0; + uint32_t u4BufLen = 0; + uint32_t rStatus; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + struct GL_P2P_INFO *prP2pGlueInfo = (struct GL_P2P_INFO *) NULL; + struct P2P_STATION_INFO rP2pStaInfo; + struct BSS_INFO *prBssInfo; + struct PARAM_LINK_SPEED_EX rLinkSpeed; + + ASSERT(wiphy); + + do { + if ((wiphy == NULL) || (ndev == NULL) + || (sinfo == NULL) || (mac == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_get_station\n"); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, ndev, &ucRoleIdx) != 0) + return -EINVAL; + + prP2pGlueInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + + /* Get station information. */ + /* 1. Inactive time? */ + p2pFuncGetStationInfo(prGlueInfo->prAdapter, + (uint8_t *)mac, &rP2pStaInfo); + + /* Inactive time. */ +#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE + sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME); +#else + sinfo->filled |= STATION_INFO_INACTIVE_TIME; +#endif + sinfo->inactive_time = rP2pStaInfo.u4InactiveTime; + sinfo->generation = prP2pGlueInfo->i4Generation; + + /* 2. fill TX rate */ + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, + ucRoleIdx, &ucBssIdx) != WLAN_STATUS_SUCCESS) + return -EINVAL; + prBssInfo = + GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, ucBssIdx); + if (!prBssInfo) { + DBGLOG(P2P, WARN, "bss is not active\n"); + return -EINVAL; + } + if (prBssInfo->eConnectionState + != MEDIA_STATE_CONNECTED) { + /* not connected */ + DBGLOG(P2P, WARN, "not yet connected\n"); + return 0; + } + + rStatus = kalIoctlByBssIdx(prGlueInfo, + wlanoidQueryLinkSpeedEx, + &rLinkSpeed, sizeof(rLinkSpeed), + TRUE, FALSE, FALSE, + &u4BufLen, ucBssIdx); + if (rStatus == WLAN_STATUS_SUCCESS + && ucBssIdx < BSSID_NUM) { + u4Rate = rLinkSpeed.rLq[ucBssIdx].u2LinkSpeed; + i4Rssi = rLinkSpeed.rLq[ucBssIdx].cRssi; + } + + if (i4Rssi > PARAM_WHQL_RSSI_MAX_DBM) + i4Rssi = PARAM_WHQL_RSSI_MAX_DBM; + else if (i4Rssi < PARAM_WHQL_RSSI_MIN_DBM) + i4Rssi = PARAM_WHQL_RSSI_MIN_DBM; + /* convert from 100bps to 100kbps */ + sinfo->txrate.legacy = u4Rate / 1000; + sinfo->signal = i4Rssi; + + DBGLOG(P2P, INFO, + "ucRoleIdx = %d, rate = %u, signal = %d\n", + ucRoleIdx, + sinfo->txrate.legacy, + sinfo->signal); + +#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE + sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); + sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); +#else + sinfo->filled |= STATION_INFO_TX_BITRATE; + sinfo->filled |= STATION_INFO_SIGNAL; +#endif + + i4RetRslt = 0; + } while (FALSE); + + return i4RetRslt; +} + +int mtk_p2p_cfg80211_scan(struct wiphy *wiphy, + struct cfg80211_scan_request *request) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + struct GL_P2P_INFO *prP2pGlueInfo = (struct GL_P2P_INFO *) NULL; + struct GL_P2P_DEV_INFO *prP2pGlueDevInfo = + (struct GL_P2P_DEV_INFO *) NULL; + struct MSG_P2P_SCAN_REQUEST *prMsgScanRequest = ( + struct MSG_P2P_SCAN_REQUEST *) NULL; + uint32_t u4MsgSize = 0, u4Idx = 0; + int32_t i4RetRslt = -EINVAL; + struct RF_CHANNEL_INFO *prRfChannelInfo = + (struct RF_CHANNEL_INFO *) NULL; + struct P2P_SSID_STRUCT *prSsidStruct = (struct P2P_SSID_STRUCT *) NULL; + struct ieee80211_channel *prChannel = NULL; + struct cfg80211_ssid *prSsid = NULL; + uint8_t ucBssIdx = 0; + u_int8_t fgIsFullChanScan = FALSE; + + /* [-----Channel-----] [-----SSID-----][-----IE-----] */ + + do { + if ((wiphy == NULL) || (request == NULL)) + break; + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (wlanIsChipAssert(prGlueInfo->prAdapter)) + break; + + prP2pGlueInfo = prGlueInfo->prP2PInfo[0]; + prP2pGlueDevInfo = prGlueInfo->prP2PDevInfo; + + if ((prP2pGlueInfo == NULL) || (prP2pGlueDevInfo == NULL)) { + ASSERT(FALSE); + break; + } + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_scan.\n"); + + if (prP2pGlueDevInfo->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; + } + + prP2pGlueDevInfo->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; + fgIsFullChanScan = TRUE; + DBGLOG(P2P, TRACE, + "Channel list exceed the maximun support.\n"); + } + /* TODO: */ + /* Find a way to distinct DEV port scan & ROLE port scan. + */ + ucBssIdx = prGlueInfo->prAdapter->ucP2PDevBssIdx; + DBGLOG(P2P, TRACE, "Device Port Scan.\n"); + + u4MsgSize = sizeof(struct MSG_P2P_SCAN_REQUEST) + + (request->n_channels * sizeof(struct RF_CHANNEL_INFO)) + + (request->n_ssids * sizeof(struct PARAM_SSID)) + + request->ie_len; + + prMsgScanRequest = cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, u4MsgSize); + + if (prMsgScanRequest == NULL) { + i4RetRslt = -ENOMEM; + break; + } + + DBGLOG(P2P, TRACE, "Generating scan request message.\n"); + + prMsgScanRequest->rMsgHdr.eMsgId = MID_MNY_P2P_DEVICE_DISCOVERY; + prMsgScanRequest->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prMsgScanRequest->ucBssIdx = ucBssIdx; + + DBGLOG(P2P, INFO, + "Requesting channel number:%d.\n", request->n_channels); + + for (u4Idx = 0; u4Idx < request->n_channels; u4Idx++) { + /* Translate Freq from MHz to channel number. */ + prRfChannelInfo = + &(prMsgScanRequest->arChannelListInfo[u4Idx]); + prChannel = request->channels[u4Idx]; + + prRfChannelInfo->ucChannelNum = + nicFreq2ChannelNum( + prChannel->center_freq * 1000); + + DBGLOG(P2P, TRACE, + "Scanning Channel:%d, freq: %d\n", + prRfChannelInfo->ucChannelNum, + prChannel->center_freq); + + switch (prChannel->band) { + case KAL_BAND_2GHZ: + prRfChannelInfo->eBand = BAND_2G4; + break; + case KAL_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; + if (fgIsFullChanScan) { + prMsgScanRequest->u4NumChannel = + SCN_P2P_FULL_SCAN_PARAM; + DBGLOG(P2P, INFO, + "request->n_channels = SCN_P2P_FULL_SCAN_PARAM\n"); + } + DBGLOG(P2P, TRACE, "Finish channel list.\n"); + + /* SSID */ + prSsid = request->ssids; + prSsidStruct = (struct P2P_SSID_STRUCT *) prRfChannelInfo; + if (request->n_ssids) { + ASSERT((unsigned long) prSsidStruct + == (unsigned long) + &(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 = (uint8_t *) prSsidStruct; + if (request->ie_len) { + kalMemCopy(prMsgScanRequest->pucIEBuf, + request->ie, request->ie_len); + prMsgScanRequest->u4IELen = request->ie_len; + } else { + prMsgScanRequest->u4IELen = 0; + } + + DBGLOG(P2P, TRACE, "Finish IE Buffer.\n"); + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prMsgScanRequest, + MSG_SEND_METHOD_BUF); + + /* Backup scan request structure */ + /* The purpose of this backup is due + * to the kernel free the scan req + * when the wpa supplicant down the iface before down, + * and it will free the original scan request structure + * In this case, the scan resoure could be locked by kernel, + * and driver needs this work around to clear the state + */ +#if 0 + kalMemCopy(&(prP2pGlueDevInfo->rBackupScanRequest), + prP2pGlueDevInfo->prScanRequest, + sizeof(struct cfg80211_scan_request)); +#endif + i4RetRslt = 0; + } while (FALSE); + + return i4RetRslt; +} /* mtk_p2p_cfg80211_scan */ + +void mtk_p2p_cfg80211_abort_scan(struct wiphy *wiphy, struct wireless_dev *wdev) +{ + uint32_t u4SetInfoLen = 0; + uint32_t u4Value = 0; + uint32_t rStatus; + struct GLUE_INFO *prGlueInfo = NULL; + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_abort_scan\n"); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidAbortP2pScan, + &u4Value, sizeof(u4Value), + FALSE, FALSE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, ERROR, + "mtk_p2p_cfg80211_abort_scan fail 0x%x\n", + rStatus); +} + +int mtk_p2p_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) +{ + int32_t i4Rslt = -EINVAL; + struct GLUE_INFO *prGlueInfo = NULL; + + do { + if (wiphy == NULL) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_set_wiphy_params\n"); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + 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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + DBGLOG(P2P, INFO, "not support now\n"); + /* not implemented yet */ + + return -EINVAL; +} + +int mtk_p2p_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + DBGLOG(P2P, INFO, "not support now\n"); + /* not implemented yet */ + + return -EINVAL; +} + +int mtk_p2p_cfg80211_set_txpower(struct wiphy *wiphy, + struct wireless_dev *wdev, + enum nl80211_tx_power_setting type, int mbm) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + ASSERT(wiphy); + + DBGLOG(P2P, INFO, "%s: not support now\n", __func__); + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + /* not implemented yet */ + + return -EINVAL; +} + +int mtk_p2p_cfg80211_get_txpower(struct wiphy *wiphy, + struct wireless_dev *wdev, int *dbm) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + ASSERT(wiphy); + + DBGLOG(P2P, TRACE, "%s: not support now\n", __func__); + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + /* not implemented yet */ + + return -EINVAL; +} + +int mtk_p2p_cfg80211_set_power_mgmt(struct wiphy *wiphy, + struct net_device *ndev, bool enabled, int timeout) +{ + struct GLUE_INFO *prGlueInfo = NULL; + enum PARAM_POWER_MODE ePowerMode; + struct PARAM_POWER_MODE_ rPowerMode; + uint32_t rStatus; + uint32_t u4Leng; + uint8_t ucRoleIdx; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (enabled) + ePowerMode = Param_PowerModeFast_PSP; + else + ePowerMode = Param_PowerModeCAM; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_set_power_mgmt ps=%d.\n", enabled); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, + ndev, &ucRoleIdx) != 0) + return -EINVAL; + + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, + ucRoleIdx, &rPowerMode.ucBssIdx) != WLAN_STATUS_SUCCESS) + return -EINVAL; + + rPowerMode.ePowerMode = ePowerMode; + + /* p2p_set_power_save */ + rStatus = kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, sizeof(rPowerMode), + FALSE, FALSE, TRUE, &u4Leng); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set_power_mgmt error:%x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +int mtk_p2p_cfg80211_start_ap(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ap_settings *settings) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_P2P_BEACON_UPDATE *prP2pBcnUpdateMsg = + (struct MSG_P2P_BEACON_UPDATE *) NULL; + struct MSG_P2P_START_AP *prP2pStartAPMsg = + (struct MSG_P2P_START_AP *) NULL; + uint8_t *pucBuffer = (uint8_t *) NULL; + uint8_t ucRoleIdx = 0; + struct cfg80211_chan_def *chandef; + struct RF_CHANNEL_INFO rRfChnlInfo; + + /* RF_CHANNEL_INFO_T rRfChnlInfo; */ +/* P_IE_SSID_T prSsidIE = (P_IE_SSID_T)NULL; */ + + do { + if ((wiphy == NULL) || (settings == NULL)) + break; + + DBGLOG(P2P, INFO, "inactivity_timeout: %d\n", + settings->inactivity_timeout); + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + /*DFS todo 20161220_DFS*/ + netif_carrier_on(dev); + netif_tx_start_all_queues(dev); + + chandef = &settings->chandef; + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + + if (chandef) { + kalChannelFormatSwitch(chandef, chandef->chan, + &rRfChnlInfo); + + DBGLOG(P2P, INFO, "pri: %d, s1: %d, s2: %d, bw: %d\n", + rRfChnlInfo.u2PriChnlFreq, + rRfChnlInfo.u4CenterFreq1, + rRfChnlInfo.u4CenterFreq2, + rRfChnlInfo.ucChnlBw); + + /* Follow the channel info from wifi.cfg + * prior to hostapd.conf + */ + { + struct ADAPTER *prAdapter = + (struct ADAPTER *) NULL; + struct WIFI_VAR *prWifiVar = + (struct WIFI_VAR *)NULL; + + prAdapter = prGlueInfo->prAdapter; + prWifiVar = &prAdapter->rWifiVar; + + if ((prWifiVar->ucApChannel != 0) && + (prWifiVar->ucApChnlDefFromCfg != 0) && + (prWifiVar->ucApChannel != + rRfChnlInfo.ucChannelNum)) { + rRfChnlInfo.ucChannelNum = + prWifiVar->ucApChannel; + rRfChnlInfo.eBand = + (rRfChnlInfo.ucChannelNum <= 14) + ? BAND_2G4 : BAND_5G; + /* [TODO][20160829]If we will set SCO + * by nl80211_channel_type afterward, + * to check if we need to modify SCO + * by wifi.cfg here + */ + } + } + + p2pFuncSetChannel(prGlueInfo->prAdapter, + ucRoleIdx, &rRfChnlInfo); + } else + DBGLOG(P2P, INFO, "!!! no CH def!!!\n"); + + prP2pBcnUpdateMsg = (struct MSG_P2P_BEACON_UPDATE *) + cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + (sizeof(struct MSG_P2P_BEACON_UPDATE) + + + settings->beacon.head_len + + settings->beacon.tail_len + + settings->beacon.assocresp_ies_len +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP + + settings->beacon.proberesp_ies_len +#endif + )); + + if (prP2pBcnUpdateMsg == NULL) { + i4Rslt = -ENOMEM; + break; + } + + prP2pBcnUpdateMsg->ucRoleIndex = ucRoleIdx; + prP2pBcnUpdateMsg->rMsgHdr.eMsgId = MID_MNY_P2P_BEACON_UPDATE; + pucBuffer = prP2pBcnUpdateMsg->aucBuffer; + +#if (CFG_SUPPORT_DFS_MASTER == 1) + if (p2pFuncGetDfsState() == DFS_STATE_DETECTED) + p2pFuncSetDfsState(DFS_STATE_INACTIVE); +#endif + 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 += settings->beacon.head_len; + } else { + prP2pBcnUpdateMsg->u4BcnHdrLen = 0; + + prP2pBcnUpdateMsg->pucBcnHdr = NULL; + } + + if (settings->beacon.tail_len != 0) { + prP2pBcnUpdateMsg->pucBcnBody = pucBuffer; + kalMemCopy(pucBuffer, + settings->beacon.tail, + settings->beacon.tail_len); + + prP2pBcnUpdateMsg->u4BcnBodyLen = + settings->beacon.tail_len; + + pucBuffer += settings->beacon.tail_len; + } else { + prP2pBcnUpdateMsg->u4BcnBodyLen = 0; + + prP2pBcnUpdateMsg->pucBcnBody = NULL; + } + + if ((settings->crypto.cipher_group == + WLAN_CIPHER_SUITE_WEP40) || + (settings->crypto.cipher_group == + WLAN_CIPHER_SUITE_WEP104)) + prP2pBcnUpdateMsg->fgIsWepCipher = TRUE; + else + prP2pBcnUpdateMsg->fgIsWepCipher = FALSE; + + if (settings->beacon.assocresp_ies_len != 0 + && settings->beacon.assocresp_ies != NULL) { + prP2pBcnUpdateMsg->pucAssocRespIE = pucBuffer; + kalMemCopy(pucBuffer, + settings->beacon.assocresp_ies, + settings->beacon.assocresp_ies_len); + prP2pBcnUpdateMsg->u4AssocRespLen = + settings->beacon.assocresp_ies_len; + } else { + prP2pBcnUpdateMsg->u4AssocRespLen = 0; + prP2pBcnUpdateMsg->pucAssocRespIE = NULL; + } + +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP + if (settings->beacon.proberesp_ies_len != 0 + && settings->beacon.proberesp_ies != NULL) { + prP2pBcnUpdateMsg->pucProbeRespIE = pucBuffer; + kalMemCopy(pucBuffer, + settings->beacon.proberesp_ies, + settings->beacon.proberesp_ies_len); + prP2pBcnUpdateMsg->u4ProbeRespLen = + settings->beacon.proberesp_ies_len; + } else { + prP2pBcnUpdateMsg->u4ProbeRespLen = 0; + prP2pBcnUpdateMsg->pucProbeRespIE = NULL; + } +#endif + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prP2pBcnUpdateMsg, + MSG_SEND_METHOD_BUF); + + prP2pStartAPMsg = (struct MSG_P2P_START_AP *) + cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, sizeof(struct MSG_P2P_START_AP)); + + if (prP2pStartAPMsg == NULL) { + 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; + + prP2pStartAPMsg->ucRoleIdx = ucRoleIdx; + + kalP2PSetRole(prGlueInfo, 2, ucRoleIdx); + + COPY_SSID(prP2pStartAPMsg->aucSsid, + prP2pStartAPMsg->u2SsidLen, + settings->ssid, settings->ssid_len); + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) 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; */ +/* }; */ +/* ////////////////// */ +} /* mtk_p2p_cfg80211_start_ap */ + +#if (CFG_SUPPORT_DFS_MASTER == 1) + +static int mtk_p2p_cfg80211_start_radar_detection_impl(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef, + unsigned int cac_time_ms) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_P2P_DFS_CAC *prP2pDfsCacMsg = + (struct MSG_P2P_DFS_CAC *) NULL; + uint8_t ucRoleIdx = 0; + struct RF_CHANNEL_INFO rRfChnlInfo; + + do { + if ((wiphy == NULL) || (chandef == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_start_radar_detection.\n"); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->chandef == NULL) { + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef = + (struct cfg80211_chan_def *) + cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_BUF, + sizeof(struct cfg80211_chan_def)); + if (prGlueInfo->prP2PInfo[ucRoleIdx]->chandef == NULL) { + i4Rslt = -ENOMEM; + break; + } + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->chan = + (struct ieee80211_channel *) + cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_BUF, + sizeof(struct ieee80211_channel)); + if (prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->chan + == NULL) { + i4Rslt = -ENOMEM; + break; + } + } + + /* Copy chan def to local buffer*/ + prGlueInfo->prP2PInfo[ucRoleIdx] + ->chandef->center_freq1 = chandef->center_freq1; + prGlueInfo->prP2PInfo[ucRoleIdx] + ->chandef->center_freq2 = chandef->center_freq2; + prGlueInfo->prP2PInfo[ucRoleIdx] + ->chandef->width = chandef->width; + memcpy(prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->chan, + chandef->chan, sizeof(struct ieee80211_channel)); + prGlueInfo->prP2PInfo[ucRoleIdx]->cac_time_ms = cac_time_ms; + + if (chandef) { + kalChannelFormatSwitch(chandef, chandef->chan, + &rRfChnlInfo); + + p2pFuncSetChannel(prGlueInfo->prAdapter, + ucRoleIdx, &rRfChnlInfo); + } + + DBGLOG(P2P, INFO, + "mtk_p2p_cfg80211_start_radar_detection.(role %d)\n", + ucRoleIdx); + + p2pFuncSetDfsState(DFS_STATE_INACTIVE); + + prP2pDfsCacMsg = (struct MSG_P2P_DFS_CAC *) + cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, sizeof(*prP2pDfsCacMsg)); + + if (prP2pDfsCacMsg == NULL) { + i4Rslt = -ENOMEM; + break; + } + + prP2pDfsCacMsg->rMsgHdr.eMsgId = MID_MNY_P2P_DFS_CAC; + + switch (chandef->width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + case NL80211_CHAN_WIDTH_40: + prP2pDfsCacMsg->eChannelWidth = CW_20_40MHZ; + break; + + case NL80211_CHAN_WIDTH_80: + prP2pDfsCacMsg->eChannelWidth = CW_80MHZ; + break; + + case NL80211_CHAN_WIDTH_80P80: + prP2pDfsCacMsg->eChannelWidth = CW_80P80MHZ; + break; + + default: + DBGLOG(P2P, ERROR, + "mtk_p2p_cfg80211_start_radar_detection. !!!Bandwidth do not support!!!\n"); + ASSERT(FALSE); + break; + } + + prP2pDfsCacMsg->ucRoleIdx = ucRoleIdx; + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prP2pDfsCacMsg, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + + } while (FALSE); + + return i4Rslt; +} + +#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_start_radar_detection(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef, unsigned int cac_time_ms) +{ + return mtk_p2p_cfg80211_start_radar_detection_impl( + wiphy, dev, chandef, cac_time_ms); +} +#else +int mtk_p2p_cfg80211_start_radar_detection(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef) +{ + return mtk_p2p_cfg80211_start_radar_detection_impl( + wiphy, dev, chandef, IEEE80211_DFS_MIN_CAC_TIME_MS); +} +#endif + +#if KERNEL_VERSION(3, 13, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_channel_switch(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_csa_settings *params) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_P2P_BEACON_UPDATE *prP2pBcnUpdateMsg = + (struct MSG_P2P_BEACON_UPDATE *) NULL; + struct MSG_P2P_SET_NEW_CHANNEL *prP2pSetNewChannelMsg = + (struct MSG_P2P_SET_NEW_CHANNEL *) NULL; + uint8_t *pucBuffer = (uint8_t *) NULL; + uint8_t ucRoleIdx = 0; + struct RF_CHANNEL_INFO rRfChnlInfo; + uint8_t ucBssIdx = 0; + uint32_t u4Len = 0; + + do { + if ((wiphy == NULL) || (params == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_channel_switch.\n"); + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) { + DBGLOG(P2P, ERROR, "get role index fail.\n"); + break; + } else { + ASSERT(ucRoleIdx < KAL_P2P_NUM); + /* Role Interface. */ + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, + ucRoleIdx, &ucBssIdx) != WLAN_STATUS_SUCCESS) { + DBGLOG(P2P, ERROR, + "get bss index fail by role(%d).\n", + ucRoleIdx); + break; + } + } + + /*DFS todo 20161220_DFS*/ + netif_carrier_on(dev); + netif_tx_start_all_queues(dev); + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->chandef == NULL) { + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef = + (struct cfg80211_chan_def *) + cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_BUF, sizeof(struct cfg80211_chan_def)); + if (prGlueInfo->prP2PInfo[ucRoleIdx]->chandef == NULL) { + i4Rslt = -ENOMEM; + break; + } + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->chan = + (struct ieee80211_channel *) + cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_BUF, sizeof(struct ieee80211_channel)); + if (prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->chan + == NULL) { + i4Rslt = -ENOMEM; + break; + } + } + /* Copy chan def to local buffer*/ + prGlueInfo->prP2PInfo[ucRoleIdx] + ->chandef->center_freq1 = params->chandef.center_freq1; + prGlueInfo->prP2PInfo[ucRoleIdx] + ->chandef->center_freq2 = params->chandef.center_freq2; + prGlueInfo->prP2PInfo[ucRoleIdx] + ->chandef->width = params->chandef.width; + memcpy(prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->chan, + params->chandef.chan, + sizeof(struct ieee80211_channel)); + + if (params) { + kalChannelFormatSwitch(¶ms->chandef, + params->chandef.chan, &rRfChnlInfo); + + p2pFuncSetChannel(prGlueInfo->prAdapter, + ucRoleIdx, &rRfChnlInfo); + } + + DBGLOG(P2P, INFO, "ucRoleIdx: %d, ucBssIdx: %d\n", + ucRoleIdx, ucBssIdx); + + p2pFuncSetDfsState(DFS_STATE_INACTIVE); + + /* Set CSA IE parameters */ + prGlueInfo->prAdapter->rWifiVar.fgCsaInProgress = TRUE; + prGlueInfo->prAdapter->rWifiVar.ucChannelSwitchMode = 1; + prGlueInfo->prAdapter->rWifiVar.ucNewChannelNumber = + nicFreq2ChannelNum( + params->chandef.chan->center_freq * 1000); + prGlueInfo->prAdapter->rWifiVar.ucChannelSwitchCount = + params->count; + + /* Set new channel parameters */ + prP2pSetNewChannelMsg = (struct MSG_P2P_SET_NEW_CHANNEL *) + cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, sizeof(*prP2pSetNewChannelMsg)); + + if (prP2pSetNewChannelMsg == NULL) { + i4Rslt = -ENOMEM; + break; + } + + prP2pSetNewChannelMsg->rMsgHdr.eMsgId = + MID_MNY_P2P_SET_NEW_CHANNEL; + + switch (params->chandef.width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + case NL80211_CHAN_WIDTH_40: + prP2pSetNewChannelMsg->eChannelWidth = CW_20_40MHZ; + break; + + case NL80211_CHAN_WIDTH_80: + prP2pSetNewChannelMsg->eChannelWidth = CW_80MHZ; + break; + + case NL80211_CHAN_WIDTH_80P80: + prP2pSetNewChannelMsg->eChannelWidth = CW_80P80MHZ; + break; + + default: + DBGLOG(P2P, ERROR, + "mtk_p2p_cfg80211_channel_switch. !!!Bandwidth do not support!!!\n"); + ASSERT(FALSE); + break; + } + + prP2pSetNewChannelMsg->ucRoleIdx = ucRoleIdx; + prP2pSetNewChannelMsg->ucBssIndex = ucBssIdx; + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prP2pSetNewChannelMsg, + MSG_SEND_METHOD_BUF); + + /* Update beacon */ + if ((params->beacon_csa.head_len != 0) + || (params->beacon_csa.tail_len != 0)) { + u4Len = (sizeof(struct MSG_P2P_BEACON_UPDATE) + + params->beacon_csa.head_len + + params->beacon_csa.tail_len); + + prP2pBcnUpdateMsg = (struct MSG_P2P_BEACON_UPDATE *) + cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + u4Len); + + if (prP2pBcnUpdateMsg == NULL) { + i4Rslt = -ENOMEM; + break; + } + + kalMemZero(prP2pBcnUpdateMsg, u4Len); + + prP2pBcnUpdateMsg->ucRoleIndex = ucRoleIdx; + prP2pBcnUpdateMsg->rMsgHdr.eMsgId = + MID_MNY_P2P_BEACON_UPDATE; + pucBuffer = prP2pBcnUpdateMsg->aucBuffer; + + if (params->beacon_csa.head_len != 0) { + kalMemCopy(pucBuffer, + params->beacon_csa.head, + params->beacon_csa.head_len); + + prP2pBcnUpdateMsg->u4BcnHdrLen = + params->beacon_csa.head_len; + + prP2pBcnUpdateMsg->pucBcnHdr = pucBuffer; + + pucBuffer = (uint8_t *) ((unsigned long) + pucBuffer + + (unsigned long) + params->beacon_csa.head_len); + } else { + prP2pBcnUpdateMsg->u4BcnHdrLen = 0; + + prP2pBcnUpdateMsg->pucBcnHdr = NULL; + } + + if (params->beacon_csa.tail_len != 0) { + prP2pBcnUpdateMsg->pucBcnBody = pucBuffer; + kalMemCopy(pucBuffer, + params->beacon_csa.tail, + params->beacon_csa.tail_len); + + prP2pBcnUpdateMsg->u4BcnBodyLen = + params->beacon_csa.tail_len; + } else { + prP2pBcnUpdateMsg->u4BcnBodyLen = 0; + prP2pBcnUpdateMsg->pucBcnBody = NULL; + } + + kalP2PSetRole(prGlueInfo, 2, ucRoleIdx); + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prP2pBcnUpdateMsg, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; /* Return Success */ + } + + } while (FALSE); + + return i4Rslt; +} +#endif +#endif + +#if 0 +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; +}; +#endif + +int mtk_p2p_cfg80211_change_beacon(struct wiphy *wiphy, + struct net_device *dev, struct cfg80211_beacon_data *info) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_P2P_BEACON_UPDATE *prP2pBcnUpdateMsg = + (struct MSG_P2P_BEACON_UPDATE *) NULL; + uint8_t *pucBuffer = (uint8_t *) NULL; + uint8_t ucRoleIdx = 0; + uint32_t u4Len = 0; + + do { + if ((wiphy == NULL) || (info == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_change_beacon.\n"); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + + if ((info->head_len != 0) || (info->tail_len != 0)) { + u4Len = (sizeof(struct MSG_P2P_BEACON_UPDATE) + + info->head_len + + info->tail_len + + info->assocresp_ies_len +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP + + info->proberesp_ies_len +#endif + ); + + prP2pBcnUpdateMsg = (struct MSG_P2P_BEACON_UPDATE *) + cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + u4Len); + + if (prP2pBcnUpdateMsg == NULL) { + i4Rslt = -ENOMEM; + break; + } + + kalMemZero(prP2pBcnUpdateMsg, u4Len); + + prP2pBcnUpdateMsg->ucRoleIndex = ucRoleIdx; + 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 += info->head_len; + } else { + prP2pBcnUpdateMsg->u4BcnHdrLen = 0; + + prP2pBcnUpdateMsg->pucBcnHdr = NULL; + } + + if (info->tail_len != 0) { + prP2pBcnUpdateMsg->pucBcnBody = pucBuffer; + kalMemCopy(pucBuffer, + info->tail, + info->tail_len); + + prP2pBcnUpdateMsg->u4BcnBodyLen = + info->tail_len; + + pucBuffer += info->tail_len; + } else { + prP2pBcnUpdateMsg->u4BcnBodyLen = 0; + prP2pBcnUpdateMsg->pucBcnBody = NULL; + } + + if (info->assocresp_ies_len != 0 + && info->assocresp_ies != NULL) { + + prP2pBcnUpdateMsg->pucAssocRespIE = pucBuffer; + kalMemCopy(pucBuffer, + info->assocresp_ies, + info->assocresp_ies_len); + prP2pBcnUpdateMsg->u4AssocRespLen = + info->assocresp_ies_len; + } else { + prP2pBcnUpdateMsg->u4AssocRespLen = 0; + prP2pBcnUpdateMsg->pucAssocRespIE = NULL; + } + +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP + if (info->proberesp_ies_len != 0 + && info->proberesp_ies != NULL) { + + prP2pBcnUpdateMsg->pucProbeRespIE = pucBuffer; + kalMemCopy(pucBuffer, + info->proberesp_ies, + info->proberesp_ies_len); + prP2pBcnUpdateMsg->u4ProbeRespLen = + info->proberesp_ies_len; + } else { + prP2pBcnUpdateMsg->u4ProbeRespLen = 0; + prP2pBcnUpdateMsg->pucProbeRespIE = NULL; + } +#endif + + kalP2PSetRole(prGlueInfo, 2, ucRoleIdx); + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prP2pBcnUpdateMsg, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; /* Return Success */ + } + + /* TODO: Probe Rsp, Assoc Rsp, Beacon IE update. */ + +/* ////////////////////////// */ +/** + * struct cfg80211_beacon_data - beacon data + * @head: head portion of beacon (before TIM IE) + * or %NULL if not changed + * @tail: tail portion of beacon (after TIM IE) + * or %NULL if not changed + * @head_len: length of @head + * @tail_len: length of @tail + * @beacon_ies: extra information element(s) to add into Beacon frames or %NULL + * @beacon_ies_len: length of beacon_ies in octets + * @proberesp_ies: extra information element(s) to add into Probe Response + * frames or %NULL + * @proberesp_ies_len: length of proberesp_ies in octets + * @assocresp_ies: extra information element(s) to add into (Re)Association + * Response frames or %NULL + * @assocresp_ies_len: length of assocresp_ies in octets + * @probe_resp_len: length of probe response template (@probe_resp) + * @probe_resp: probe response template (AP mode only) + */ +/* struct cfg80211_beacon_data { */ +/* const u8 *head, *tail; */ +/* const u8 *beacon_ies; */ +/* const u8 *proberesp_ies; */ +/* const u8 *assocresp_ies; */ +/* const u8 *probe_resp; */ + +/* size_t head_len, tail_len; */ +/* size_t beacon_ies_len; */ +/* size_t proberesp_ies_len; */ +/* size_t assocresp_ies_len; */ +/* size_t probe_resp_len; */ +/* }; */ + +/* ////////////////////////// */ + + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_change_beacon */ + +int mtk_p2p_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_P2P_STOP_AP *prP2pStopApMsg = + (struct MSG_P2P_STOP_AP *) NULL; + uint8_t ucRoleIdx = 0; + struct GL_P2P_INFO *prP2PInfo; + + do { + if (wiphy == NULL) + break; + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_stop_ap.\n"); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + +#if (CFG_SUPPORT_DFS_MASTER == 1) + if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) { + netif_carrier_off(dev); + netif_tx_stop_all_queues(dev); + } +#endif + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + + prP2pStopApMsg = cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, sizeof(struct MSG_P2P_STOP_AP)); + + if (prP2pStopApMsg == NULL) { + i4Rslt = -ENOMEM; + break; + } + + prP2PInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; +#if KERNEL_VERSION(3, 13, 0) <= CFG80211_VERSION_CODE + reinit_completion(&prP2PInfo->rStopApComp); +#else + prP2PInfo->rStopApComp.done = 0; +#endif + + prP2pStopApMsg->rMsgHdr.eMsgId = MID_MNY_P2P_STOP_AP; + prP2pStopApMsg->ucRoleIdx = ucRoleIdx; + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prP2pStopApMsg, + MSG_SEND_METHOD_BUF); + + if (p2pFuncIsAPMode(prGlueInfo->prAdapter->rWifiVar. + prP2PConnSettings[ucRoleIdx])) { + uint32_t waitRet = 0; + + waitRet = wait_for_completion_timeout( + &prP2PInfo->rStopApComp, + MSEC_TO_JIFFIES(P2P_DEAUTH_TIMEOUT_TIME_MS)); + if (!waitRet) + DBGLOG(P2P, WARN, "timeout\n"); + else + DBGLOG(P2P, INFO, "complete\n"); + } + + 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) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + /* 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) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_disassoc.\n"); + + /* not implemented yet */ + + return -EINVAL; +} /* mtk_p2p_cfg80211_disassoc */ + +int mtk_p2p_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, + unsigned int duration, u64 *cookie) +{ + int32_t i4Rslt = -EINVAL; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + struct GL_P2P_DEV_INFO *prGlueP2pDevInfo = + (struct GL_P2P_DEV_INFO *) NULL; + struct MSG_P2P_CHNL_REQUEST *prMsgChnlReq = + (struct MSG_P2P_CHNL_REQUEST *) NULL; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_remain_on_channel\n"); + + do { + if ((wiphy == NULL) || + /* (dev == NULL) || */ + (chan == NULL) || (cookie == NULL)) { + break; + } + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + prGlueP2pDevInfo = prGlueInfo->prP2PDevInfo; + + *cookie = prGlueP2pDevInfo->u8Cookie++; + + prMsgChnlReq = cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, sizeof(struct MSG_P2P_CHNL_REQUEST)); + + if (prMsgChnlReq == NULL) { + i4Rslt = -ENOMEM; + break; + } + + DBGLOG(P2P, INFO, + "Remain on channel, cookie: 0x%llx\n", + *cookie); + + prMsgChnlReq->rMsgHdr.eMsgId = MID_MNY_P2P_CHNL_REQ; + prMsgChnlReq->u8Cookie = *cookie; + prMsgChnlReq->u4Duration = duration; + prMsgChnlReq->eChnlReqType = CH_REQ_TYPE_ROC; + + kalChannelFormatSwitch(NULL, chan, + &prMsgChnlReq->rChannelInfo); + kalChannelScoSwitch(NL80211_CHAN_NO_HT, + &prMsgChnlReq->eChnlSco); + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prMsgChnlReq, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} + +/* mtk_p2p_cfg80211_remain_on_channel */ + +int mtk_p2p_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, u64 cookie) +{ + int32_t i4Rslt = -EINVAL; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL; + struct MSG_P2P_CHNL_ABORT *prMsgChnlAbort = + (struct MSG_P2P_CHNL_ABORT *) NULL; + + do { + if (wiphy == NULL /* || (dev == NULL) */) + break; + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + prGlueP2pInfo = prGlueInfo->prP2PInfo[0]; + + prMsgChnlAbort = cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, sizeof(struct MSG_P2P_CHNL_ABORT)); + + if (prMsgChnlAbort == NULL) { + i4Rslt = -ENOMEM; + break; + } + + DBGLOG(P2P, INFO, + "Cancel remain on channel, cookie: 0x%llx\n", cookie); + + prMsgChnlAbort->rMsgHdr.eMsgId = MID_MNY_P2P_CHNL_ABORT; + prMsgChnlAbort->u8Cookie = cookie; + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prMsgChnlAbort, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_cancel_remain_on_channel */ + +int _mtk_p2p_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, struct ieee80211_channel *chan, + bool offchan, unsigned int wait, const u8 *buf, size_t len, + bool no_cck, bool dont_wait_for_ack, u64 *cookie) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_MGMT_TX_REQUEST *prMsgTxReq = + (struct MSG_MGMT_TX_REQUEST *) NULL; + struct MSDU_INFO *prMgmtFrame = (struct MSDU_INFO *) NULL; + uint8_t *pucFrameBuf = (uint8_t *) NULL; + uint64_t *pu8GlCookie = (uint64_t *) NULL; + uint8_t ucRoleIdx = 0, ucBssIdx = 0; + struct net_device *dev = NULL; + + do { + if ((wiphy == NULL) || (wdev == NULL) || (cookie == NULL)) + break; + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + dev = wdev->netdev; + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) { + /* Device Interface. */ + ucBssIdx = prGlueInfo->prAdapter->ucP2PDevBssIdx; + } else { + ASSERT(ucRoleIdx < KAL_P2P_NUM); + /* Role Interface. */ + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, + ucRoleIdx, &ucBssIdx) != WLAN_STATUS_SUCCESS) { + /* Can't find BSS index. */ + break; + } + } + + *cookie = prGlueInfo->prP2PDevInfo->u8Cookie++; + + prMsgTxReq = cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_MGMT_TX_REQUEST)); + + if (prMsgTxReq == NULL) { + i4Rslt = -ENOMEM; + DBGLOG(P2P, ERROR, "Allocate TX req msg fails.\n"); + break; + } + + if (offchan) { + prMsgTxReq->fgIsOffChannel = TRUE; + memset(&prMsgTxReq->rChannelInfo, 0, + sizeof(struct RF_CHANNEL_INFO)); + kalChannelFormatSwitch(NULL, chan, + &prMsgTxReq->rChannelInfo); + kalChannelScoSwitch(NL80211_CHAN_NO_HT, + &prMsgTxReq->eChnlExt); + } else { + prMsgTxReq->fgIsOffChannel = FALSE; + } + + if (wait) + prMsgTxReq->u4Duration = wait; + else + prMsgTxReq->u4Duration = 0; + + if (no_cck) + prMsgTxReq->fgNoneCckRate = TRUE; + else + prMsgTxReq->fgNoneCckRate = FALSE; + + if (dont_wait_for_ack) + prMsgTxReq->fgIsWaitRsp = FALSE; + else + prMsgTxReq->fgIsWaitRsp = TRUE; + + prMgmtFrame = cnmMgtPktAlloc(prGlueInfo->prAdapter, + (int32_t) (len + sizeof(uint64_t) + + MAC_TX_RESERVED_FIELD)); + prMsgTxReq->prMgmtMsduInfo = prMgmtFrame; + if (prMsgTxReq->prMgmtMsduInfo == NULL) { + /* ASSERT(FALSE); */ + i4Rslt = -ENOMEM; + DBGLOG(P2P, ERROR, "Allocate TX packet fails.\n"); + break; + } + + prMsgTxReq->u8Cookie = *cookie; + prMsgTxReq->rMsgHdr.eMsgId = MID_MNY_P2P_MGMT_TX; + prMsgTxReq->ucBssIdx = ucBssIdx; + + pucFrameBuf = + (uint8_t *) + ((unsigned long) prMgmtFrame->prPacket + + MAC_TX_RESERVED_FIELD); + + pu8GlCookie = + (uint64_t *) + ((unsigned long) prMgmtFrame->prPacket + + (unsigned long) len + + MAC_TX_RESERVED_FIELD); + + kalMemCopy(pucFrameBuf, buf, len); + + *pu8GlCookie = *cookie; + + prMgmtFrame->u2FrameLength = len; + +#define TEMP_LOG_TEMPLATE "netdev: %p, bssIdx: %d, band: %d, chan: %d, " \ + "offchan: %d, wait: %d, len: %d, no_cck: %d, " \ + "dont_wait_for_ack: %d, cookie: 0x%llx\n" + DBGLOG(P2P, INFO, TEMP_LOG_TEMPLATE, + dev, + prMsgTxReq->ucBssIdx, + prMsgTxReq->rChannelInfo.eBand, + prMsgTxReq->rChannelInfo.ucChannelNum, + prMsgTxReq->fgIsOffChannel, + prMsgTxReq->u4Duration, + prMsgTxReq->prMgmtMsduInfo->u2FrameLength, + prMsgTxReq->fgNoneCckRate, + prMsgTxReq->fgIsWaitRsp, + prMsgTxReq->u8Cookie); +#undef TEMP_LOG_TEMPLATE + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) 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; +} + +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie) +{ + if (params == NULL) + return -EINVAL; + + return _mtk_p2p_cfg80211_mgmt_tx(wiphy, wdev, params->chan, + params->offchan, params->wait, params->buf, + params->len, params->no_cck, params->dont_wait_for_ack, + cookie); +} /* mtk_p2p_cfg80211_mgmt_tx */ +#else +int mtk_p2p_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, bool offchan, + unsigned int wait, const u8 *buf, size_t len, + bool no_cck, bool dont_wait_for_ack, u64 *cookie) +{ + return _mtk_p2p_cfg80211_mgmt_tx(wiphy, wdev, chan, offchan, wait, buf, + len, no_cck, dont_wait_for_ack, cookie); +} /* mtk_p2p_cfg80211_mgmt_tx */ +#endif + +int mtk_p2p_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct wireless_dev *wdev, u64 cookie) +{ + int32_t i4Rslt = -EINVAL; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + uint8_t ucRoleIdx = 0, ucBssIdx = 0; + struct MSG_CANCEL_TX_WAIT_REQUEST *prMsgCancelTxWait = + (struct MSG_CANCEL_TX_WAIT_REQUEST *) NULL; + + do { + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, + wdev->netdev, &ucRoleIdx) < 0) { + /* Device Interface. */ + ucBssIdx = prGlueInfo->prAdapter->ucP2PDevBssIdx; + } else { + ASSERT(ucRoleIdx < KAL_P2P_NUM); + /* Role Interface. */ + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, + ucRoleIdx, + &ucBssIdx) != WLAN_STATUS_SUCCESS) { + /* Can't find BSS index. */ + break; + } + } + + DBGLOG(P2P, INFO, "bssIdx: %d, cookie: 0x%llx\n", + ucBssIdx, + cookie); + + prMsgCancelTxWait = cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_CANCEL_TX_WAIT_REQUEST)); + + if (prMsgCancelTxWait == NULL) { + i4Rslt = -ENOMEM; + break; + } + + prMsgCancelTxWait->rMsgHdr.eMsgId = + MID_MNY_P2P_MGMT_TX_CANCEL_WAIT; + prMsgCancelTxWait->u8Cookie = cookie; + prMsgCancelTxWait->ucBssIdx = ucBssIdx; + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prMsgCancelTxWait, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_mgmt_tx_cancel_wait */ + +int mtk_p2p_cfg80211_change_bss(struct wiphy *wiphy, + struct net_device *dev, + struct bss_parameters *params) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + int32_t i4Rslt = -EINVAL; + + ASSERT(wiphy); + + DBGLOG(P2P, INFO, "%s\n", __func__); + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + 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 */ + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +#if KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE +static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, + struct station_del_parameters *params) +{ + const u8 *mac = params->mac ? params->mac : bcast_addr; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_P2P_CONNECTION_ABORT *prDisconnectMsg = + (struct MSG_P2P_CONNECTION_ABORT *) NULL; + uint8_t aucBcMac[] = BC_MAC_ADDR; + uint8_t ucRoleIdx = 0; + + do { + if ((wiphy == NULL) || (dev == NULL)) + break; + + if (mac == NULL) + mac = aucBcMac; + + DBGLOG(P2P, INFO, + "mtk_p2p_cfg80211_del_station " MACSTR ". reason: %d\n", + MAC2STR(mac), params->reason_code); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + /* prDisconnectMsg = (struct MSG_P2P_CONNECTION_ABORT *) + * kalMemAlloc(sizeof(struct MSG_P2P_CONNECTION_ABORT), + * VIR_MEM_TYPE); + */ + + prDisconnectMsg = (struct MSG_P2P_CONNECTION_ABORT *) + cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_P2P_CONNECTION_ABORT)); + + if (prDisconnectMsg == NULL) { + i4Rslt = -ENOMEM; + break; + } + + prDisconnectMsg->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT; + prDisconnectMsg->ucRoleIdx = ucRoleIdx; + COPY_MAC_ADDR(prDisconnectMsg->aucTargetID, mac); + prDisconnectMsg->u2ReasonCode = params->reason_code; + prDisconnectMsg->fgSendDeauth = TRUE; + + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prDisconnectMsg, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; + +} /* mtk_p2p_cfg80211_del_station */ +#else +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, const u8 *mac) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_P2P_CONNECTION_ABORT *prDisconnectMsg = + (struct MSG_P2P_CONNECTION_ABORT *) NULL; + uint8_t aucBcMac[] = BC_MAC_ADDR; + uint8_t ucRoleIdx = 0; + + do { + if ((wiphy == NULL) || (dev == NULL)) + break; + + if (mac == NULL) + mac = aucBcMac; + + DBGLOG(P2P, INFO, + "mtk_p2p_cfg80211_del_station " MACSTR ".\n", + MAC2STR(mac)); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + /* prDisconnectMsg = (struct MSG_P2P_CONNECTION_ABORT *) + * kalMemAlloc(sizeof(struct MSG_P2P_CONNECTION_ABORT), + * VIR_MEM_TYPE); + */ + + prDisconnectMsg = (struct MSG_P2P_CONNECTION_ABORT *) + cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_P2P_CONNECTION_ABORT)); + + if (prDisconnectMsg == NULL) { + i4Rslt = -ENOMEM; + break; + } + + prDisconnectMsg->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT; + prDisconnectMsg->ucRoleIdx = ucRoleIdx; + COPY_MAC_ADDR(prDisconnectMsg->aucTargetID, mac); + prDisconnectMsg->u2ReasonCode = REASON_CODE_UNSPECIFIED; + prDisconnectMsg->fgSendDeauth = TRUE; + + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prDisconnectMsg, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; + +} /* mtk_p2p_cfg80211_del_station */ +#endif +#else +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, u8 *mac) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_P2P_CONNECTION_ABORT *prDisconnectMsg = + (struct MSG_P2P_CONNECTION_ABORT *) NULL; + uint8_t aucBcMac[] = BC_MAC_ADDR; + uint8_t ucRoleIdx = 0; + + do { + if ((wiphy == NULL) || (dev == NULL)) + break; + + if (mac == NULL) + mac = aucBcMac; + + DBGLOG(P2P, INFO, + "mtk_p2p_cfg80211_del_station " MACSTR ".\n", + MAC2STR(mac)); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + /* prDisconnectMsg = (struct MSG_P2P_CONNECTION_ABORT *) + * kalMemAlloc(sizeof(struct MSG_P2P_CONNECTION_ABORT), + * VIR_MEM_TYPE); + */ + + prDisconnectMsg = + (struct MSG_P2P_CONNECTION_ABORT *) + cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_P2P_CONNECTION_ABORT)); + + if (prDisconnectMsg == NULL) { + i4Rslt = -ENOMEM; + break; + } + + prDisconnectMsg->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT; + prDisconnectMsg->ucRoleIdx = ucRoleIdx; + COPY_MAC_ADDR(prDisconnectMsg->aucTargetID, mac); + prDisconnectMsg->u2ReasonCode = REASON_CODE_UNSPECIFIED; + prDisconnectMsg->fgSendDeauth = TRUE; + + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prDisconnectMsg, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; + +} /* mtk_p2p_cfg80211_del_station */ +#endif + +int mtk_p2p_cfg80211_connect(struct wiphy *wiphy, + struct net_device *dev, struct cfg80211_connect_params *sme) +{ + int32_t i4Rslt = -EINVAL; + struct GLUE_INFO *prGlueInfo = NULL; + struct MSG_P2P_CONNECTION_REQUEST *prConnReqMsg = + (struct MSG_P2P_CONNECTION_REQUEST *) NULL; + uint8_t ucRoleIdx = 0; + const u8 *bssid = NULL; + struct ieee80211_channel *channel = NULL; + struct cfg80211_bss *bss = NULL; + + do { + if ((wiphy == NULL) || (dev == NULL) || (sme == NULL)) + break; + + if (sme->bssid) + bssid = sme->bssid; +#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE + else if (sme->bssid_hint) + bssid = sme->bssid_hint; +#endif + if (sme->channel) + channel = sme->channel; +#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE + else if (sme->channel_hint) + channel = sme->channel_hint; +#endif + + if ((bssid == NULL) || (channel == NULL)) { +#if KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE + bss = cfg80211_get_bss(wiphy, NULL, NULL, + sme->ssid, sme->ssid_len, + IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY); +#else + bss = cfg80211_get_bss(wiphy, NULL, NULL, + sme->ssid, sme->ssid_len, + WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); +#endif + if (bss == NULL) { + DBGLOG(P2P, ERROR, + "Reject connect without bssid/channel/bss.\n"); + break; + } + + bssid = bss->bssid; + channel = bss->channel; + + if ((bssid == NULL) || (channel == NULL)) { + DBGLOG(P2P, ERROR, + "Reject connect: no bssid/channel in bss.\n"); + break; + } + } + + DBGLOG(P2P, INFO, + "bssid: " MACSTR ", band: %d, freq: %d.\n", + MAC2STR(bssid), channel->band, channel->center_freq); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + + prConnReqMsg = + (struct MSG_P2P_CONNECTION_REQUEST *) + cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + (sizeof(struct MSG_P2P_CONNECTION_REQUEST) + + sme->ie_len)); + + if (prConnReqMsg == NULL) { + i4Rslt = -ENOMEM; + break; + } + + prConnReqMsg->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_REQ; + prConnReqMsg->ucRoleIdx = ucRoleIdx; + + COPY_SSID(prConnReqMsg->rSsid.aucSsid, + prConnReqMsg->rSsid.ucSsidLen, + sme->ssid, sme->ssid_len); + + COPY_MAC_ADDR(prConnReqMsg->aucBssid, bssid); + COPY_MAC_ADDR(prConnReqMsg->aucSrcMacAddr, dev->dev_addr); + + DBGLOG(P2P, TRACE, + "Assoc Req IE Buffer Length:%zu\n", sme->ie_len); + + kalMemCopy(prConnReqMsg->aucIEBuf, sme->ie, sme->ie_len); + prConnReqMsg->u4IELen = sme->ie_len; + + kalP2PSetCipher(prGlueInfo, IW_AUTH_CIPHER_NONE, ucRoleIdx); + + if (sme->crypto.n_ciphers_pairwise) { + switch (sme->crypto.ciphers_pairwise[0]) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + kalP2PSetCipher(prGlueInfo, + IW_AUTH_CIPHER_WEP40, ucRoleIdx); + break; + case WLAN_CIPHER_SUITE_TKIP: + kalP2PSetCipher(prGlueInfo, + IW_AUTH_CIPHER_TKIP, ucRoleIdx); + break; + case WLAN_CIPHER_SUITE_CCMP: + case WLAN_CIPHER_SUITE_AES_CMAC: + kalP2PSetCipher(prGlueInfo, + IW_AUTH_CIPHER_CCMP, ucRoleIdx); + break; + default: + cnmMemFree(prGlueInfo->prAdapter, prConnReqMsg); + DBGLOG(REQ, WARN, + "invalid cipher pairwise (%d)\n", + sme->crypto.ciphers_pairwise[0]); + /* do cfg80211_put_bss before return */ + if (bss) + cfg80211_put_bss(wiphy, bss); + return -EINVAL; + } + } + + kalChannelFormatSwitch(NULL, channel, + &prConnReqMsg->rChannelInfo); + kalChannelScoSwitch(NL80211_CHAN_NO_HT, + &prConnReqMsg->eChnlSco); + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prConnReqMsg, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + /* do cfg80211_put_bss before return */ + if (bss) + cfg80211_put_bss(wiphy, bss); + + return i4Rslt; +} /* mtk_p2p_cfg80211_connect */ + +int mtk_p2p_cfg80211_disconnect(struct wiphy *wiphy, + struct net_device *dev, u16 reason_code) +{ + int32_t i4Rslt = -EINVAL; + struct GLUE_INFO *prGlueInfo = NULL; + struct MSG_P2P_CONNECTION_ABORT *prDisconnMsg = + (struct MSG_P2P_CONNECTION_ABORT *) NULL; + uint8_t aucBCAddr[] = BC_MAC_ADDR; + uint8_t ucRoleIdx = 0; + + do { + if ((wiphy == NULL) || (dev == NULL)) + break; + + DBGLOG(P2P, INFO, + "mtk_p2p_cfg80211_disconnect reason: %d.\n", + reason_code); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; +/* prDisconnMsg = (P_MSG_P2P_CONNECTION_ABORT_T) + * MemAlloc(sizeof(P_MSG_P2P_CONNECTION_ABORT_T), VIR_MEM_TYPE); + */ + prDisconnMsg = + (struct MSG_P2P_CONNECTION_ABORT *) + cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_P2P_CONNECTION_ABORT)); + + if (prDisconnMsg == NULL) { + i4Rslt = -ENOMEM; + break; + } + + prDisconnMsg->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT; + prDisconnMsg->ucRoleIdx = ucRoleIdx; + prDisconnMsg->u2ReasonCode = reason_code; + prDisconnMsg->fgSendDeauth = TRUE; + COPY_MAC_ADDR(prDisconnMsg->aucTargetID, aucBCAddr); + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prDisconnMsg, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_disconnect */ + +int +mtk_p2p_cfg80211_change_iface(IN struct wiphy *wiphy, + IN struct net_device *ndev, + IN enum nl80211_iftype type, + IN u32 *flags, + IN struct vif_params *params) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_P2P_SWITCH_OP_MODE *prSwitchModeMsg = + (struct MSG_P2P_SWITCH_OP_MODE *) NULL; + uint8_t ucRoleIdx = 0; + + do { + if ((wiphy == NULL) || (ndev == NULL)) { + DBGLOG(P2P, ERROR, "wiphy=%p, ndev=%p.\n", wiphy, ndev); + break; + } + + DBGLOG(P2P, INFO, + "mtk_p2p_cfg80211_change_iface, type: %d\n", type); + + if (ndev->ieee80211_ptr) + ndev->ieee80211_ptr->iftype = type; + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, ndev, &ucRoleIdx) != 0) { + DBGLOG(P2P, TRACE, + "Device Interface no need to change interface type.\n"); + return 0; + } + /* Switch OP MOde. */ + prSwitchModeMsg = + (struct MSG_P2P_SWITCH_OP_MODE *) + cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_P2P_SWITCH_OP_MODE)); + + if (prSwitchModeMsg == NULL) { + i4Rslt = -ENOMEM; + break; + } + + prSwitchModeMsg->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; + prSwitchModeMsg->ucRoleIdx = ucRoleIdx; + + switch (type) { + case NL80211_IFTYPE_P2P_CLIENT: + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_P2P_CLIENT.\n"); + prSwitchModeMsg->eIftype = IFTYPE_P2P_CLIENT; + /* This case need to fall through */ + case NL80211_IFTYPE_STATION: + if (type == NL80211_IFTYPE_STATION) { + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_STATION.\n"); + prSwitchModeMsg->eIftype = IFTYPE_STATION; + } + prSwitchModeMsg->eOpMode = OP_MODE_INFRASTRUCTURE; + kalP2PSetRole(prGlueInfo, 1, ucRoleIdx); + break; + case NL80211_IFTYPE_AP: + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_AP.\n"); + kalP2PSetRole(prGlueInfo, 2, ucRoleIdx); + prSwitchModeMsg->eIftype = IFTYPE_AP; + /* This case need to fall through */ + case NL80211_IFTYPE_P2P_GO: + if (type == NL80211_IFTYPE_P2P_GO) { + DBGLOG(P2P, TRACE, + "NL80211_IFTYPE_P2P_GO not AP.\n"); + prSwitchModeMsg->eIftype = IFTYPE_P2P_GO; + } + prSwitchModeMsg->eOpMode = OP_MODE_ACCESS_POINT; + kalP2PSetRole(prGlueInfo, 2, ucRoleIdx); + break; + default: + DBGLOG(P2P, TRACE, "Other type :%d .\n", type); + prSwitchModeMsg->eOpMode = OP_MODE_P2P_DEVICE; + kalP2PSetRole(prGlueInfo, 0, ucRoleIdx); + prSwitchModeMsg->eIftype = IFTYPE_P2P_DEVICE; + break; + } + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prSwitchModeMsg, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + + } while (FALSE); + + return i4Rslt; + +} /* mtk_p2p_cfg80211_change_iface */ + +int mtk_p2p_cfg80211_set_channel(IN struct wiphy *wiphy, + struct cfg80211_chan_def *chandef) +{ + int32_t i4Rslt = -EINVAL; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + struct RF_CHANNEL_INFO rRfChnlInfo; + uint8_t ucRoleIdx = 0; + struct net_device *dev = NULL; + + if ((wiphy == NULL) || (chandef == NULL)) + return i4Rslt; + + dev = (struct net_device *) wiphy_dev(wiphy); + + do { + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_set_channel.\n"); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + kalChannelFormatSwitch(chandef, chandef->chan, &rRfChnlInfo); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + + p2pFuncSetChannel(prGlueInfo->prAdapter, + ucRoleIdx, &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) +{ + int32_t i4Rslt = -EINVAL; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + + do { + if ((wiphy == NULL) || (dev == NULL) || (mask == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_set_bitrate_mask\n"); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + /* TODO: Set bitrate mask of the peer? */ + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_set_bitrate_mask */ + +void mtk_p2p_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, + struct wireless_dev *wdev, + IN u16 frame_type, IN bool reg) +{ +#if 0 + struct MSG_P2P_MGMT_FRAME_REGISTER *prMgmtFrameRegister = + (struct MSG_P2P_MGMT_FRAME_REGISTER *) NULL; +#endif + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + uint8_t ucRoleIdx = 0; + uint32_t *pu4P2pPacketFilter = NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + + do { + if ((wiphy == NULL) || (wdev == NULL)) + break; + + DBGLOG(P2P, TRACE, "netdev: 0x%p, frame_type: 0x%x, reg: %d\n", + wdev->netdev, frame_type, reg); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + /* since p2p device share the aprRoleHandler + * so needs to check DevHandler 1st + */ + if (prGlueInfo->prP2PInfo[0]->prDevHandler == wdev->netdev) { + /* P2P device*/ + pu4P2pPacketFilter = + &prGlueInfo->prP2PDevInfo->u4OsMgmtFrameFilter; + } else { + if (mtk_Netdev_To_RoleIdx(prGlueInfo, + wdev->netdev, &ucRoleIdx) < 0) { + DBGLOG(P2P, WARN, "wireless dev match fail!\n"); + break; + } else { + /* Non P2P device*/ + ASSERT(ucRoleIdx < KAL_P2P_NUM); + DBGLOG(P2P, TRACE, + "Open packet filer RoleIdx %u\n", + ucRoleIdx); + prP2pRoleFsmInfo = + prGlueInfo->prAdapter + ->rWifiVar.aprP2pRoleFsmInfo[ucRoleIdx]; + pu4P2pPacketFilter = + &prP2pRoleFsmInfo->u4P2pPacketFilter; + } + } + switch (frame_type) { + case MAC_FRAME_PROBE_REQ: + if (reg) { + *pu4P2pPacketFilter + |= PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(P2P, TRACE, + "Open packet filer probe request\n"); + } else { + *pu4P2pPacketFilter + &= ~PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(P2P, TRACE, + "Close packet filer probe request\n"); + } + break; + case MAC_FRAME_ACTION: + if (reg) { + *pu4P2pPacketFilter + |= PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(P2P, TRACE, + "Open packet filer action frame.\n"); + } else { + *pu4P2pPacketFilter + &= ~PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(P2P, TRACE, + "Close packet filer action frame.\n"); + } + break; +#if CFG_SUPPORT_SOFTAP_WPA3 + case MAC_FRAME_AUTH: + if (reg) { + *pu4P2pPacketFilter + |= PARAM_PACKET_FILTER_AUTH; + DBGLOG(P2P, TRACE, + "Open packet filer auth request\n"); + } else { + *pu4P2pPacketFilter + &= ~PARAM_PACKET_FILTER_AUTH; + DBGLOG(P2P, TRACE, + "Close packet filer auth request\n"); + } + break; + case MAC_FRAME_ASSOC_REQ: + if (reg) { + *pu4P2pPacketFilter + |= PARAM_PACKET_FILTER_ASSOC_REQ; + DBGLOG(P2P, TRACE, + "Open packet filer assoc request\n"); + } else { + *pu4P2pPacketFilter + &= ~PARAM_PACKET_FILTER_ASSOC_REQ; + DBGLOG(P2P, TRACE, + "Close packet filer assoc request\n"); + } + break; +#endif + default: + DBGLOG(P2P, ERROR, + "Ask frog to add code for mgmt:%x\n", + frame_type); + break; + } + + set_bit(GLUE_FLAG_FRAME_FILTER_BIT, &prGlueInfo->ulFlag); + + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + + if (in_interrupt()) + DBGLOG(P2P, TRACE, "It is in interrupt level\n"); +#if 0 + + prMgmtFrameRegister = + (struct MSG_P2P_MGMT_FRAME_REGISTER *) + cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_P2P_MGMT_FRAME_REGISTER)); + + 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, + (struct MSG_HDR *) prMgmtFrameRegister, + MSG_SEND_METHOD_BUF); + +#endif + + } while (FALSE); + +} /* mtk_p2p_cfg80211_mgmt_frame_register */ + +#ifdef CONFIG_NL80211_TESTMODE + +#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_testmode_cmd(struct wiphy *wiphy, + struct wireless_dev *wdev, void *data, + int len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct NL80211_DRIVER_TEST_PARAMS *prParams = + (struct NL80211_DRIVER_TEST_PARAMS *) NULL; + int32_t i4Status = -EINVAL; + + ASSERT(wiphy); + ASSERT(wdev); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_testmode_cmd\n"); + + if (data && len) { + prParams = (struct NL80211_DRIVER_TEST_PARAMS *) data; + } else { + DBGLOG(P2P, ERROR, + "mtk_p2p_cfg80211_testmode_cmd, data is NULL\n"); + return i4Status; + } + if (prParams->index >> 24 == 0x01) { + /* New version */ + prParams->index = prParams->index & ~BITS(24, 31); + } else { + /* Old version */ + mtk_p2p_cfg80211_testmode_p2p_sigma_pre_cmd(wiphy, data, len); + i4Status = 0; + return i4Status; + } + + /* Clear the version byte */ + prParams->index = prParams->index & ~BITS(24, 31); + + if (prParams) { + switch (prParams->index) { + case 1: /* P2P Simga */ +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION + { + struct NL80211_DRIVER_SW_CMD_PARAMS + *prParamsCmd; + + prParamsCmd = + (struct NL80211_DRIVER_SW_CMD_PARAMS *) + data; + + if ((prParamsCmd->adr & 0xffff0000) + == 0xffff0000) { + i4Status = + mtk_p2p_cfg80211_testmode_sw_cmd( + wiphy, data, len); + break; + } + } +#endif + i4Status = mtk_p2p_cfg80211_testmode_p2p_sigma_cmd( + wiphy, data, len); + break; + case 2: /* WFD */ +#if CFG_SUPPORT_WFD + /* use normal driver command wifi_display */ + /* i4Status = + * mtk_p2p_cfg80211_testmode_wfd_update_cmd( + * wiphy, data, len); + */ +#endif + break; + case 3: /* Hotspot Client Management */ +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + i4Status = + mtk_p2p_cfg80211_testmode_hotspot_block_list_cmd( + wiphy, data, len); +#endif + break; + case 0x10: + i4Status = + mtk_cfg80211_testmode_get_sta_statistics( + wiphy, data, len, prGlueInfo); + break; +#if CFG_SUPPORT_NFC_BEAM_PLUS + case 0x11: /*NFC Beam + Indication */ + if (data && len) { + struct NL80211_DRIVER_SET_NFC_PARAMS *prParams = + (struct NL80211_DRIVER_SET_NFC_PARAMS *) + data; + + DBGLOG(P2P, INFO, + "NFC: BEAM[%d]\n", + prParams->NFC_Enable); + } + break; + case 0x12: /*NFC Beam + Indication */ + DBGLOG(P2P, INFO, "NFC: Polling\n"); + i4Status = + mtk_cfg80211_testmode_get_scan_done( + wiphy, data, len, prGlueInfo); + break; +#endif + case TESTMODE_CMD_ID_HS_CONFIG: + i4Status = + mtk_p2p_cfg80211_testmode_hotspot_config_cmd( + wiphy, data, len); + break; + + case TESTMODE_CMD_ID_UPDATE_STA_PMKID: + i4Status = + mtk_p2p_cfg80211_testmode_update_sta_pmkid_cmd( + wiphy, wdev->netdev, data, len); + break; + default: + i4Status = -EINVAL; + break; + } + } + + return i4Status; + +} +#else +int mtk_p2p_cfg80211_testmode_cmd(struct wiphy *wiphy, void *data, int len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct NL80211_DRIVER_TEST_PARAMS *prParams = + (struct NL80211_DRIVER_TEST_PARAMS *) NULL; + int32_t i4Status = -EINVAL; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_testmode_cmd\n"); + + if (data && len) { + prParams = (struct NL80211_DRIVER_TEST_PARAMS *) data; + } else { + DBGLOG(P2P, ERROR, "data is NULL\n"); + return i4Status; + } + 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); + i4Status = 0; + return i4Status; + } + + /* Clear the version byte */ + prParams->index = prParams->index & ~BITS(24, 31); + + if (prParams) { + switch (prParams->index) { + case 1: /* P2P Simga */ +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION + { + struct NL80211_DRIVER_SW_CMD_PARAMS + *prParamsCmd; + + prParamsCmd = + (struct NL80211_DRIVER_SW_CMD_PARAMS *) + data; + + if ((prParamsCmd->adr & 0xffff0000) + == 0xffff0000) { + i4Status = + mtk_p2p_cfg80211_testmode_sw_cmd( + wiphy, data, len); + break; + } + } +#endif + i4Status = mtk_p2p_cfg80211_testmode_p2p_sigma_cmd( + wiphy, data, len); + break; + case 2: /* WFD */ +#if CFG_SUPPORT_WFD + /* use normal driver command wifi_display */ + /* i4Status = mtk_p2p_cfg80211_testmode_wfd_update_cmd( + * wiphy, data, len); + */ +#endif + break; + case 3: /* Hotspot Client Management */ +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + i4Status = + mtk_p2p_cfg80211_testmode_hotspot_block_list_cmd( + wiphy, data, len); +#endif + break; + case 0x10: + i4Status = + mtk_cfg80211_testmode_get_sta_statistics( + wiphy, data, len, prGlueInfo); + break; +#if CFG_SUPPORT_NFC_BEAM_PLUS + case 0x11: /*NFC Beam + Indication */ + if (data && len) { + struct NL80211_DRIVER_SET_NFC_PARAMS *prParams = + (struct NL80211_DRIVER_SET_NFC_PARAMS *) + data; + + DBGLOG(P2P, INFO, + "NFC: BEAM[%d]\n", + prParams->NFC_Enable); + } + break; + case 0x12: /*NFC Beam + Indication */ + DBGLOG(P2P, INFO, "NFC: Polling\n"); + i4Status = + mtk_cfg80211_testmode_get_scan_done( + wiphy, data, len, prGlueInfo); + break; +#endif + case TESTMODE_CMD_ID_HS_CONFIG: + i4Status = + mtk_p2p_cfg80211_testmode_hotspot_config_cmd( + wiphy, data, len); + break; + + default: + i4Status = -EINVAL; + break; + } + } + + return i4Status; + +} +#endif + +int mtk_p2p_cfg80211_testmode_hotspot_config_cmd(IN struct wiphy *wiphy, + IN void *data, IN int len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct NL80211_DRIVER_HOTSPOT_CONFIG_PARAMS *prParams = + (struct NL80211_DRIVER_HOTSPOT_CONFIG_PARAMS *) NULL; + uint32_t index; + uint32_t value; + uint32_t i; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (data && len) { + prParams = (struct NL80211_DRIVER_HOTSPOT_CONFIG_PARAMS *) data; + } else { + DBGLOG(P2P, ERROR, "data is NULL or len is 0\n"); + return -EINVAL; + } + + index = prParams->idx; + value = prParams->value; + + DBGLOG(P2P, INFO, "NL80211_ATTR_TESTDATA, idx=%d value=%d\n", + (uint32_t) prParams->idx, (uint32_t) prParams->value); + + switch (index) { + case 1: /* Max Clients */ + for (i = 0; i < KAL_P2P_NUM; i++) + if (p2pFuncIsAPMode(prGlueInfo->prAdapter + ->rWifiVar.prP2PConnSettings[i])) + kalP2PSetMaxClients(prGlueInfo, value, i); + break; + default: + break; + } + + return 0; +} + +int mtk_p2p_cfg80211_testmode_p2p_sigma_pre_cmd(IN struct wiphy *wiphy, + IN void *data, IN int len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct NL80211_DRIVER_TEST_PRE_PARAMS rParams; + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo = + (struct P2P_SPECIFIC_BSS_INFO *) NULL; + /* P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = + * (P_P2P_CONNECTION_SETTINGS_T)NULL; + */ + uint32_t index_mode; + uint32_t index; + int32_t value; + int status = 0; + uint32_t u4Leng; + uint8_t ucBssIdx; + + if (len > sizeof(struct NL80211_DRIVER_TEST_PRE_PARAMS)) { + DBGLOG(P2P, WARN, "len [%d] is invalid!\n", + len); + return -EINVAL; + } + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + kalMemZero(&rParams, sizeof(struct NL80211_DRIVER_TEST_PRE_PARAMS)); + + prP2pSpecificBssInfo = + prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo[0]; + /* prP2pConnSettings = + * prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings; + */ + + if (data && len) + memcpy(&rParams, data, len); + + DBGLOG(P2P, TRACE, + "NL80211_ATTR_TESTDATA, idx_mode=%d idx=%d value=%u\n", + rParams.idx_mode, + rParams.idx, + rParams.value); + + index_mode = rParams.idx_mode; + index = rParams.idx; + value = rParams.value; + + /* 3 FIX ME: Add p2p role index selection */ + if (p2pFuncRoleToBssIdx( + prGlueInfo->prAdapter, 0, &ucBssIdx) != WLAN_STATUS_SUCCESS) + return -EINVAL; + + 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 */ + { + struct PARAM_POWER_MODE_ rPowerMode; + uint32_t rStatus; + + rPowerMode.ePowerMode = Param_PowerModeMAX_PSP; + rPowerMode.ucBssIdx = ucBssIdx; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, + sizeof(rPowerMode), + FALSE, FALSE, TRUE, &u4Leng); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, + "set_power_mgmt error:%x\n", rStatus); + return -EFAULT; + } + } + 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 */ + { + struct PARAM_POWER_MODE_ rPowerMode; + uint32_t rStatus; + + rPowerMode.ePowerMode = value; + rPowerMode.ucBssIdx = ucBssIdx; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, + sizeof(rPowerMode), + FALSE, FALSE, TRUE, &u4Leng); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, + "set_power_mgmt error:%x\n", rStatus); + return -EFAULT; + } + } + break; + default: + break; + } + + return status; + +} + +int mtk_p2p_cfg80211_testmode_p2p_sigma_cmd(IN struct wiphy *wiphy, + IN void *data, IN int len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct NL80211_DRIVER_P2P_SIGMA_PARAMS *prParams = + (struct NL80211_DRIVER_P2P_SIGMA_PARAMS *) NULL; + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo = + (struct P2P_SPECIFIC_BSS_INFO *) NULL; + /* P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = + * (P_P2P_CONNECTION_SETTINGS_T)NULL; + */ + uint32_t rStatus; + uint32_t index; + int32_t value; + int status = 0; + uint32_t u4Leng; + uint8_t ucBssIdx; + uint32_t i; + struct NL80211_DRIVER_P2P_NOA_PARAMS { + struct NL80211_DRIVER_TEST_PARAMS hdr; + uint32_t idx; + uint32_t value; /* should not be used in this case */ + uint32_t count; + uint32_t interval; + uint32_t duration; + }; + struct NL80211_DRIVER_P2P_NOA_PARAMS *prNoaParams = NULL; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + prP2pSpecificBssInfo = + prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo[0]; + /* prP2pConnSettings = + * prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings; + */ + + if (data && len) + prParams = (struct NL80211_DRIVER_P2P_SIGMA_PARAMS *) data; + else { + DBGLOG(P2P, ERROR, "data is NULL\n"); + return -EINVAL; + } + + index = (int32_t) prParams->idx; + value = (int32_t) prParams->value; + + DBGLOG(P2P, INFO, "NL80211_ATTR_TESTDATA, idx=%u value=%u\n", + prParams->idx, prParams->value); + + /* 3 FIX ME: Add p2p role index selection */ + if (p2pFuncRoleToBssIdx( + prGlueInfo->prAdapter, 0, &ucBssIdx) != WLAN_STATUS_SUCCESS) + return -EINVAL; + + switch (index) { + case 0: /* Listen CH */ + break; + case 1: /* P2p mode */ + break; + case 4: /* Noa duration */ + prNoaParams = data; + prP2pSpecificBssInfo->rNoaParam.u4NoaCount = prNoaParams->count; + prP2pSpecificBssInfo->rNoaParam.u4NoaIntervalMs = + prNoaParams->interval; + prP2pSpecificBssInfo->rNoaParam.u4NoaDurationMs = + prNoaParams->duration; + prP2pSpecificBssInfo->rNoaParam.ucBssIdx = + ucBssIdx; + DBGLOG(P2P, INFO, + "SET NOA[%d]: %d %d %d\n", + ucBssIdx, + prNoaParams->count, + prNoaParams->interval, + prNoaParams->duration); + + /* only to apply setting when setting NOA count */ + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNoaParam, + &prP2pSpecificBssInfo->rNoaParam, + sizeof(struct PARAM_CUSTOM_NOA_PARAM_STRUCT), + FALSE, FALSE, TRUE, &u4Leng); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set_noa error:%x\n", rStatus); + return -EFAULT; + } + 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 */ + { + struct PARAM_POWER_MODE_ rPowerMode; + + rPowerMode.ePowerMode = Param_PowerModeMAX_PSP; + rPowerMode.ucBssIdx = ucBssIdx; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, + sizeof(rPowerMode), + FALSE, FALSE, TRUE, &u4Leng); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, + "set_power_mgmt error:%x\n", rStatus); + return -EFAULT; + } + } + break; + case 107: /* P2P set opps, CTWindowl */ + prP2pSpecificBssInfo->rOppPsParam.u4CTwindowMs = value; + prP2pSpecificBssInfo->rOppPsParam.ucBssIdx = ucBssIdx; + DBGLOG(P2P, INFO, "SET OPPS[%d]: %d\n", ucBssIdx, value); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetOppPsParam, + &prP2pSpecificBssInfo->rOppPsParam, + sizeof(struct PARAM_CUSTOM_OPPPS_PARAM_STRUCT), + FALSE, FALSE, TRUE, &u4Leng); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, + "set_opps error:%x\n", rStatus); + return -EFAULT; + } + break; + case 108: /* p2p_set_power_save */ + { + struct PARAM_POWER_MODE_ rPowerMode; + + rPowerMode.ePowerMode = value; + rPowerMode.ucBssIdx = ucBssIdx; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, sizeof(rPowerMode), + FALSE, FALSE, TRUE, &u4Leng); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, + "set_power_mgmt error:%x\n", rStatus); + return -EFAULT; + } + } + break; + case 109: /* Max Clients */ +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + for (i = 0; i < KAL_P2P_NUM; i++) + if (p2pFuncIsAPMode(prGlueInfo->prAdapter + ->rWifiVar.prP2PConnSettings[i])) + kalP2PSetMaxClients(prGlueInfo, value, i); +#endif + break; + case 110: /* Hotspot WPS mode */ +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + rStatus = kalIoctl(prGlueInfo, + wlanoidSetP2pWPSmode, + &value, sizeof(value), + FALSE, FALSE, TRUE, &u4Leng); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, + "set_wps error:%x\n", rStatus); + return -EFAULT; + } +#endif + break; + default: + break; + } + + return status; + +} + +#if CFG_SUPPORT_WFD && 0 +/* obsolete/decrepated */ +int mtk_p2p_cfg80211_testmode_wfd_update_cmd(IN struct wiphy *wiphy, + IN void *data, IN int len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct NL80211_DRIVER_WFD_PARAMS *prParams = + (struct NL80211_DRIVER_WFD_PARAMS *) NULL; + int status = 0; + struct WFD_CFG_SETTINGS *prWfdCfgSettings = + (struct WFD_CFG_SETTINGS *) NULL; + struct MSG_WFD_CONFIG_SETTINGS_CHANGED *prMsgWfdCfgUpdate = + (struct MSG_WFD_CONFIG_SETTINGS_CHANGED *) NULL; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + prParams = (struct 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.rWfdConfigureSettings); + + kalMemCopy(&prWfdCfgSettings->u4WfdCmdType, + &prParams->WfdCmdType, + sizeof(struct WFD_CFG_SETTINGS)); + + prMsgWfdCfgUpdate = cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_WFD_CONFIG_SETTINGS_CHANGED)); + + if (prMsgWfdCfgUpdate == NULL) { + return status; + } + + prMsgWfdCfgUpdate->rMsgHdr.eMsgId = MID_MNY_P2P_WFD_CFG_UPDATE; + prMsgWfdCfgUpdate->prWfdCfgSettings = prWfdCfgSettings; + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) 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; + { + uint8_t 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 */ + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + +int mtk_p2p_cfg80211_testmode_hotspot_block_list_cmd(IN struct wiphy *wiphy, + IN void *data, IN int len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct NL80211_DRIVER_hotspot_block_PARAMS *prParams = + (struct NL80211_DRIVER_hotspot_block_PARAMS *) NULL; + int fgIsValid = 0; + uint32_t i; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (data && len) + prParams = (struct NL80211_DRIVER_hotspot_block_PARAMS *) data; + else + return fgIsValid; + + DBGLOG(P2P, INFO, + "%s" MACSTR "\n", + prParams->ucblocked?"Block":"Unblock", + MAC2STR(prParams->aucBssid)); + + for (i = 0; i < KAL_P2P_NUM; i++) + fgIsValid |= + kalP2PSetBlackList(prGlueInfo, + prParams->aucBssid, prParams->ucblocked, i); + + return fgIsValid; + +} + +#endif + +int mtk_p2p_cfg80211_testmode_sw_cmd(IN struct wiphy *wiphy, + IN void *data, IN int len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct NL80211_DRIVER_SW_CMD_PARAMS *prParams = + (struct NL80211_DRIVER_SW_CMD_PARAMS *) NULL; + uint32_t rstatus = WLAN_STATUS_SUCCESS; + int fgIsValid = 0; + uint32_t u4SetInfoLen = 0; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + DBGLOG(P2P, TRACE, "--> %s()\n", __func__); + + if (data && len) + prParams = (struct NL80211_DRIVER_SW_CMD_PARAMS *) data; + + if (prParams) { + if (prParams->set == 1) { + rstatus = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC) wlanoidSetSwCtrlWrite, + &prParams->adr, (uint32_t) 8, + FALSE, FALSE, TRUE, &u4SetInfoLen); + } + } + + if (rstatus != WLAN_STATUS_SUCCESS) + fgIsValid = -EFAULT; + + return fgIsValid; +} + +int mtk_p2p_cfg80211_testmode_update_sta_pmkid_cmd(IN struct wiphy *wiphy, + IN struct net_device *nDev, IN void *data, IN int len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct NL80211_DRIVER_UPDATE_STA_PMKID_PARAMS *prParams = + (struct NL80211_DRIVER_UPDATE_STA_PMKID_PARAMS *) NULL; + struct PARAM_PMKID pmkid; + uint8_t ucRoleIdx = 0; + uint8_t ucBssIdx = 0; + uint32_t rStatus; + uint32_t u4BufLen; + int fgIsValid = 0; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (data && len) + prParams = (struct NL80211_DRIVER_UPDATE_STA_PMKID_PARAMS *) + data; + else + return -EFAULT; + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, nDev, &ucRoleIdx) < 0) { + DBGLOG(P2P, WARN, "mtk_Netdev_To_RoleIdx\n"); + return -EINVAL; + } + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, + ucRoleIdx, &ucBssIdx) != WLAN_STATUS_SUCCESS) { + DBGLOG(P2P, WARN, "p2pFuncRoleToBssIdx\n"); + return -EINVAL; + } + + COPY_MAC_ADDR(pmkid.arBSSID, prParams->aucSta); + kalMemCopy(pmkid.arPMKID, prParams->aucPmkid, IW_PMKID_LEN); + pmkid.ucBssIdx = ucBssIdx; + if (prParams->ucAddRemove) { + rStatus = kalIoctl(prGlueInfo, wlanoidSetPmkid, &pmkid, + sizeof(struct PARAM_PMKID), + FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "add pmkid error:%x\n", rStatus); + } else { + rStatus = kalIoctl(prGlueInfo, wlanoidDelPmkid, &pmkid, + sizeof(struct PARAM_PMKID), + FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "remove pmkid error:%x\n", rStatus); + } + + DBGLOG(P2P, LOUD, + "%s " MACSTR " PMKID:" PMKSTR "\n", + prParams->ucAddRemove?"Add":"Remove", + MAC2STR(prParams->aucSta), + prParams->aucPmkid[0], prParams->aucPmkid[1], + prParams->aucPmkid[2], prParams->aucPmkid[3], + prParams->aucPmkid[4], prParams->aucPmkid[5], + prParams->aucPmkid[6], prParams->aucPmkid[7], + prParams->aucPmkid[8], prParams->aucPmkid[9], + prParams->aucPmkid[10], prParams->aucPmkid[11], + prParams->aucPmkid[12] + prParams->aucPmkid[13], + prParams->aucPmkid[14], prParams->aucPmkid[15]); + + return fgIsValid; +} + +#endif + +#endif /* CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_WIFI_DIRECT_CFG_80211 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_p2p_init.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_p2p_init.c new file mode 100644 index 0000000000000..32fcee4734da5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_p2p_init.c @@ -0,0 +1,291 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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_INF_NAME "p2p%d" +#define AP_INF_NAME "ap%d" + +/****************************************************************************** + * 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 uint8_t *ifname = P2P_INF_NAME; +static uint8_t *ifname2 = P2P_INF_NAME; +static uint16_t mode = RUNNING_P2P_MODE; + + +/****************************************************************************** + * M A C R O S + ****************************************************************************** + */ + +/****************************************************************************** + * F U N C T I O N D E C L A R A T I O N S + ****************************************************************************** + */ + +/****************************************************************************** + * F U N C T I O N S + ****************************************************************************** + */ + +void p2pSetSuspendMode(struct GLUE_INFO *prGlueInfo, u_int8_t fgEnable) +{ + struct net_device *prDev = NULL; + struct GL_P2P_INFO *prP2PInfo = NULL; + + if (!prGlueInfo) + return; + + if (!prGlueInfo->prAdapter->fgIsP2PRegistered) { + DBGLOG(INIT, INFO, "%s: P2P is not enabled, SKIP!\n", __func__); + return; + } + + /* For P2P interfaces, prDevHandler points to the net_device of + * p2p0 interface. And aprRoleHandler points to the net_device + * of p2p virtual interface (i.e., p2p1) when it was created. + * And when p2p virtual interface is deleted, aprRoleHandler + * will change to point to prDevHandler. Hence, when + * aprRoleHandler & prDevHandler are pointing to different + * addresses, it means vif p2p1 exists. Otherwise it means p2p1 + * was already deleted. + */ + prP2PInfo = prGlueInfo->prP2PInfo[0]; + if ((prP2PInfo->aprRoleHandler != NULL) && + (prP2PInfo->aprRoleHandler != prP2PInfo->prDevHandler)) { + prDev = prP2PInfo->aprRoleHandler; + } else { + prDev = prP2PInfo->prDevHandler; + } + + if (!prDev) { + DBGLOG(INIT, INFO, + "%s: P2P dev is not available, SKIP!\n", __func__); + return; + } + + kalSetNetAddressFromInterface(prGlueInfo, prDev, fgEnable); + wlanNotifyFwSuspend(prGlueInfo, prDev, fgEnable); +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief + * run p2p init procedure, glue register p2p and set p2p registered flag + * + * \retval 1 Success + */ +/*---------------------------------------------------------------------------*/ +u_int8_t p2pLaunch(struct GLUE_INFO *prGlueInfo) +{ + if (prGlueInfo->prAdapter->fgIsP2PRegistered == TRUE) { + DBGLOG(P2P, INFO, "p2p is already registered\n"); + return FALSE; + } + + if (!glRegisterP2P(prGlueInfo, ifname, ifname2, mode)) { + DBGLOG(P2P, ERROR, "Launch failed\n"); + return FALSE; + } + + prGlueInfo->prAdapter->fgIsP2PRegistered = TRUE; + prGlueInfo->prAdapter->p2p_scan_report_all_bss = + CFG_P2P_SCAN_REPORT_ALL_BSS; + DBGLOG(P2P, TRACE, "Launch success, fgIsP2PRegistered TRUE\n"); + return TRUE; +} + +void p2pSetMode(IN uint8_t ucAPMode) +{ + uint8_t *prAPInfName = AP_INF_NAME; + uint8_t *prP2PInfName = P2P_INF_NAME; + +#ifdef CFG_DRIVER_INF_NAME_CHANGE + + if (kalStrLen(gprifnamep2p) > 0) { + prP2PInfName = kalStrCat(gprifnamep2p, "%d"); + DBGLOG(INIT, WARN, + "P2P ifname customized, use %s\n", prP2PInfName); + } + + if (kalStrLen(gprifnameap) > 0) { + prAPInfName = kalStrCat(gprifnameap, "%d"); + DBGLOG(INIT, WARN, + "AP ifname customized, use %s\n", prAPInfName); + } + +#endif /* CFG_DRIVER_INF_NAME_CHANGE */ + + switch (ucAPMode) { + case 0: + mode = RUNNING_P2P_MODE; + ifname = prP2PInfName; + break; + case 1: + mode = RUNNING_AP_MODE; + ifname = prAPInfName; + break; + case 2: + mode = RUNNING_DUAL_AP_MODE; + ifname = prAPInfName; + break; + case 3: + mode = RUNNING_P2P_AP_MODE; + ifname = prP2PInfName; + ifname2 = prAPInfName; + break; + } +} /* p2pSetMode */ + +/*---------------------------------------------------------------------------*/ +/*! + * \brief + * run p2p exit procedure, glue unregister p2p and set p2p registered flag + * + * \retval 1 Success + */ +/*---------------------------------------------------------------------------*/ +u_int8_t p2pRemove(struct GLUE_INFO *prGlueInfo) +{ + u_int8_t idx = 0; + + if (prGlueInfo->prAdapter->fgIsP2PRegistered == FALSE) { + DBGLOG(P2P, INFO, "p2p is not registered\n"); + return FALSE; + } + + prGlueInfo->prAdapter->fgIsP2PRegistered = FALSE; + prGlueInfo->prAdapter->p2p_scan_report_all_bss = FALSE; + + glUnregisterP2P(prGlueInfo, 0xff); + + /* Release ap0 wdev. + * ap0 wdev is created in wlanProbe. So we need to release it in + * wlanRemove. Other wdevs shall be released in exitWlan. + */ + for (idx = 0 ; idx < KAL_P2P_NUM; idx++) { + if (gprP2pRoleWdev[idx] == NULL) + continue; +#if CFG_ENABLE_UNIFY_WIPHY + if (wlanIsAisDev(gprP2pRoleWdev[idx]->netdev)) { + /* This is AIS/AP Interface */ + gprP2pRoleWdev[idx] = NULL; + continue; + } +#endif + /* free gprP2pWdev in wlanDestroyAllWdev */ + if (gprP2pRoleWdev[idx] == gprP2pWdev) + continue; + + DBGLOG(INIT, INFO, "Unregister gprP2pRoleWdev[%d]\n", idx); +#if (CFG_ENABLE_UNIFY_WIPHY == 0) + set_wiphy_dev(gprP2pRoleWdev[idx]->wiphy, NULL); + wiphy_unregister(gprP2pRoleWdev[idx]->wiphy); + wiphy_free(gprP2pRoleWdev[idx]->wiphy); +#endif + kfree(gprP2pRoleWdev[idx]); + gprP2pRoleWdev[idx] = NULL; + break; + } +#if (CFG_ENABLE_UNIFY_WIPHY == 0) + /* gprP2pWdev: base P2P dev + * Becase the interface dev (ex: usb_device) would be free + * after un-plug event. Should set the wiphy->dev->parent which + * pointer to the interface dev to NULL. Otherwise, the corresponding + * system operation (poweroff, suspend) might reference it. + * set_wiphy_dev(wiphy, NULL): set the wiphy->dev->parent = NULL + */ + if (gprP2pWdev != NULL) + set_wiphy_dev(gprP2pWdev->wiphy, NULL); +#endif + + return TRUE; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_p2p_kal.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_p2p_kal.c new file mode 100644 index 0000000000000..cd59468278afe --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_p2p_kal.c @@ -0,0 +1,2343 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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" +#include "gl_wext.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 + ****************************************************************************** + */ + +struct ieee80211_channel *kalP2pFuncGetChannelEntry( + IN struct GL_P2P_INFO *prP2pInfo, + IN struct RF_CHANNEL_INFO *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 + */ +/*---------------------------------------------------------------------------*/ +#if 0 +enum ENUM_PARAM_MEDIA_STATE kalP2PGetState(IN struct GLUE_INFO *prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->prP2PInfo[0]->eState; +} /* end of kalP2PGetState() */ +#endif +/*---------------------------------------------------------------------------*/ +/*! + * \brief to update the assoc req to p2p + * + * \param[in] + * prGlueInfo + * pucFrameBody + * u4FrameBodyLen + * fgReassocRequest + * \return + * none + */ +/*---------------------------------------------------------------------------*/ +void +kalP2PUpdateAssocInfo(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucFrameBody, + IN uint32_t u4FrameBodyLen, + IN u_int8_t fgReassocRequest, + IN uint8_t ucBssIndex) +{ + struct BSS_INFO *prBssInfo; + union iwreq_data wrqu; + unsigned char *pucExtraInfo = NULL; + unsigned char *pucDesiredIE = NULL; +/* unsigned char aucExtraInfoBuf[200]; */ + uint8_t *cp; + struct net_device *prNetdevice = (struct net_device *)NULL; + + 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 */ + return; + } + + /* IWEVASSOCREQIE, indicate binary string */ + pucExtraInfo = pucDesiredIE; + wrqu.data.length = pucDesiredIE[1] + 2; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, ucBssIndex); + + if (ucBssIndex == prGlueInfo->prAdapter->ucP2PDevBssIdx) + prNetdevice = prGlueInfo->prP2PInfo + [prBssInfo->u4PrivateData]->prDevHandler; + else + prNetdevice = prGlueInfo->prP2PInfo + [prBssInfo->u4PrivateData]->aprRoleHandler; + + /* Send event to user space */ + wireless_send_event(prNetdevice, IWEVASSOCREQIE, &wrqu, pucExtraInfo); +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief to set Wi-Fi Direct state in glue layer + * + * \param[in] + * prGlueInfo + * eBowState + * rPeerAddr + * \return + * none + */ +/*---------------------------------------------------------------------------*/ +#if 0 +void +kalP2PSetState(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_PARAM_MEDIA_STATE eState, + IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN], + IN uint8_t ucRole) +{ + union iwreq_data evt; + uint8_t aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + + if (eState == MEDIA_STATE_CONNECTED) { + prGlueInfo->prP2PInfo[0]->eState = 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[0]->prDevHandler, + IWEVCUSTOM, &evt, aucBuffer); + + } else if (eState == 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[0]->prDevHandler, + IWEVCUSTOM, &evt, aucBuffer); + } else { + ASSERT(0); + } + +} /* end of kalP2PSetState() */ +#endif +/*---------------------------------------------------------------------------*/ +/*! + * \brief to retrieve Wi-Fi Direct operating frequency + * + * \param[in] + * prGlueInfo + * + * \return + * in unit of KHz + */ +/*---------------------------------------------------------------------------*/ +#if 0 +uint32_t kalP2PGetFreqInKHz(IN struct GLUE_INFO *prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->prP2PInfo[0]->u4FreqInKHz; +} /* end of kalP2PGetFreqInKHz() */ +#endif + +/*---------------------------------------------------------------------------*/ +/*! + * \brief to retrieve Bluetooth-over-Wi-Fi role + * + * \param[in] + * prGlueInfo + * + * \return + * 0: P2P Device + * 1: Group Client + * 2: Group Owner + */ +/*----------------------------------------------------------------------------*/ +uint8_t kalP2PGetRole(IN struct GLUE_INFO *prGlueInfo, IN uint8_t ucRoleIdx) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->prP2PInfo[ucRoleIdx]->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 + */ +/*---------------------------------------------------------------------------*/ +#if 1 +void kalP2PSetRole(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRole, IN uint8_t ucRoleIdx) +{ + ASSERT(prGlueInfo); + ASSERT(ucRole <= 2); + + prGlueInfo->prP2PInfo[ucRoleIdx]->ucRole = ucRole; + /* Remove non-used code */ +} /* end of kalP2PSetRole() */ + +#else +void +kalP2PSetRole(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucResult, IN uint8_t *pucSSID, + IN uint8_t ucSSIDLen, IN uint8_t ucRole) +{ + union iwreq_data evt; + uint8_t aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + ASSERT(ucRole <= 2); + + memset(&evt, 0, sizeof(evt)); + + if (ucResult == 0) + prGlueInfo->prP2PInfo[0]->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[0]->prDevHandler, + IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PSetRole() */ + +#endif +/*---------------------------------------------------------------------------*/ +/*! + * \brief to set the cipher for p2p + * + * \param[in] + * prGlueInfo + * u4Cipher + * + * \return + * none + */ +/*---------------------------------------------------------------------------*/ +void kalP2PSetCipher(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Cipher, IN uint8_t ucRoleIdx) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo[ucRoleIdx]); + + /* It can be WEP40 (used to identify cipher is WEP), TKIP and CCMP */ + prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise = u4Cipher; + +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief to get the cipher, return false for security is none + * + * \param[in] + * prGlueInfo + * + * \return + * TRUE: cipher is ccmp + * FALSE: cipher is none + */ +/*---------------------------------------------------------------------------*/ +u_int8_t kalP2PGetCipher(IN struct GLUE_INFO *prGlueInfo, IN uint8_t ucRoleIdx) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo[ucRoleIdx]); + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise + == IW_AUTH_CIPHER_CCMP) + return TRUE; + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise + == IW_AUTH_CIPHER_TKIP) + return TRUE; + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise + == IW_AUTH_CIPHER_WEP40) + return TRUE; + + return FALSE; +} + +u_int8_t kalP2PGetWepCipher(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIdx) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo[ucRoleIdx]); + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise + == IW_AUTH_CIPHER_WEP40) + return TRUE; + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise + == IW_AUTH_CIPHER_WEP104) + return TRUE; + + return FALSE; +} + +u_int8_t kalP2PGetCcmpCipher(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIdx) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo[ucRoleIdx]); + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise + == IW_AUTH_CIPHER_CCMP) + return TRUE; + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise + == IW_AUTH_CIPHER_TKIP) + return FALSE; + + return FALSE; +} + +u_int8_t kalP2PGetTkipCipher(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIdx) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo[ucRoleIdx]); + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise + == IW_AUTH_CIPHER_CCMP) + return FALSE; + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise + == IW_AUTH_CIPHER_TKIP) + return TRUE; + + return FALSE; +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief to set the status of WSC + * + * \param[in] + * prGlueInfo + * + * \return + */ +/*---------------------------------------------------------------------------*/ +void kalP2PSetWscMode(IN struct GLUE_INFO *prGlueInfo, IN uint8_t ucWscMode) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PDevInfo); + + prGlueInfo->prP2PDevInfo->ucWSCRunning = ucWscMode; +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief to get the status of WSC + * + * \param[in] + * prGlueInfo + * + * \return + */ +/*---------------------------------------------------------------------------*/ +uint8_t kalP2PGetWscMode(IN struct GLUE_INFO *prGlueInfo) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PDevInfo); + + return prGlueInfo->prP2PDevInfo->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 + */ +/*---------------------------------------------------------------------------*/ +uint16_t kalP2PCalWSC_IELen(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucType, IN uint8_t ucRoleIdx) +{ + ASSERT(prGlueInfo); + + ASSERT(ucType < 4); + + return prGlueInfo->prP2PInfo[ucRoleIdx]->u2WSCIELen[ucType]; +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief to copy the wsc ie setting from p2p supplicant + * + * \param[in] + * prGlueInfo + * + * \return + * The WPS IE length + */ +/*---------------------------------------------------------------------------*/ +void kalP2PGenWSC_IE(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucType, IN uint8_t *pucBuffer, IN uint8_t ucRoleIdx) +{ + struct GL_P2P_INFO *prGlP2pInfo = (struct GL_P2P_INFO *) NULL; + + do { + if ((prGlueInfo == NULL) + || (ucType >= 4) || (pucBuffer == NULL)) + break; + + prGlP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + + kalMemCopy(pucBuffer, + prGlP2pInfo->aucWSCIE[ucType], + prGlP2pInfo->u2WSCIELen[ucType]); + + } while (FALSE); + +} + +void kalP2PUpdateWSC_IE(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucType, IN uint8_t *pucBuffer, + IN uint16_t u2BufferLength, IN uint8_t ucRoleIdx) +{ + struct GL_P2P_INFO *prGlP2pInfo = (struct GL_P2P_INFO *) NULL; + + do { + if ((prGlueInfo == NULL) || (ucType >= 4) + || ((u2BufferLength > 0) && (pucBuffer == NULL))) + break; + + if (u2BufferLength > 400) { + log_dbg(P2P, ERROR, + "Buffer length is not enough, GLUE only 400 bytes but %d received\n", + u2BufferLength); + ASSERT(FALSE); + break; + } + + prGlP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + + kalMemCopy(prGlP2pInfo->aucWSCIE[ucType], + pucBuffer, u2BufferLength); + + prGlP2pInfo->u2WSCIELen[ucType] = u2BufferLength; + + } while (FALSE); + +} /* kalP2PUpdateWSC_IE */ + +uint16_t kalP2PCalP2P_IELen(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucIndex, IN uint8_t ucRoleIdx) +{ + ASSERT(prGlueInfo); + + ASSERT(ucIndex < MAX_P2P_IE_SIZE); + + return prGlueInfo->prP2PInfo[ucRoleIdx]->u2P2PIELen[ucIndex]; +} + +void kalP2PGenP2P_IE(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucIndex, IN uint8_t *pucBuffer, IN uint8_t ucRoleIdx) +{ + struct GL_P2P_INFO *prGlP2pInfo = (struct GL_P2P_INFO *) NULL; + + do { + if ((prGlueInfo == NULL) || (ucIndex >= MAX_P2P_IE_SIZE) + || (pucBuffer == NULL)) + break; + + prGlP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + + kalMemCopy(pucBuffer, + prGlP2pInfo->aucP2PIE[ucIndex], + prGlP2pInfo->u2P2PIELen[ucIndex]); + + } while (FALSE); +} + +void kalP2PUpdateP2P_IE(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucIndex, IN uint8_t *pucBuffer, + IN uint16_t u2BufferLength, IN uint8_t ucRoleIdx) +{ + struct GL_P2P_INFO *prGlP2pInfo = (struct GL_P2P_INFO *) NULL; + + do { + if ((prGlueInfo == NULL) || + (ucIndex >= MAX_P2P_IE_SIZE) || + ((u2BufferLength > 0) && (pucBuffer == NULL))) + break; + + if (u2BufferLength > 400) { + log_dbg(P2P, ERROR, + "kalP2PUpdateP2P_IE > Buffer length is not enough, GLUE only 400 bytes but %d received\n", + u2BufferLength); + ASSERT(FALSE); + break; + } + + prGlP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + + kalMemCopy(prGlP2pInfo->aucP2PIE[ucIndex], + pucBuffer, u2BufferLength); + + prGlP2pInfo->u2P2PIELen[ucIndex] = u2BufferLength; + + } while (FALSE); + +} + +#if 0 +/*---------------------------------------------------------------------------*/ +/*! + * \brief indicate an event to supplicant for device connection request + * + * \param[in] prGlueInfo Pointer of GLUE_INFO_T + * + * \retval none + */ +/*---------------------------------------------------------------------------*/ +void kalP2PIndicateConnReq(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucDevName, IN int32_t u4NameLength, + IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN], + IN uint8_t ucDevType,/* 0: P2P Device / 1: GC / 2: GO */ + IN int32_t i4ConfigMethod, IN int32_t i4ActiveConfigMethod +) +{ + union iwreq_data evt; + uint8_t aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + /* buffer peer information + * for later IOC_P2P_GET_REQ_DEVICE_INFO access + */ + prGlueInfo->prP2PInfo[0]->u4ConnReqNameLength = + u4NameLength > 32 ? 32 : u4NameLength; + kalMemCopy(prGlueInfo->prP2PInfo[0]->aucConnReqDevName, + pucDevName, + prGlueInfo->prP2PInfo[0]->u4ConnReqNameLength); + COPY_MAC_ADDR(prGlueInfo->prP2PInfo[0]->rConnReqPeerAddr, rPeerAddr); + prGlueInfo->prP2PInfo[0]->ucConnReqDevType = ucDevType; + prGlueInfo->prP2PInfo[0]->i4ConnReqConfigMethod = i4ConfigMethod; + prGlueInfo->prP2PInfo[0]->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[0]->prDevHandler, + IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PIndicateConnReq() */ + +/*---------------------------------------------------------------------------*/ +/*! + * \brief Indicate an event to supplicant + * for device connection request from other device. + * + * \param[in] prGlueInfo Pointer of GLUE_INFO_T + * \param[in] pucGroupBssid Only valid when invitation Type equals to 0. + * + * \retval none + */ +/*---------------------------------------------------------------------------*/ +void +kalP2PInvitationIndication(IN struct GLUE_INFO *prGlueInfo, + IN struct P2P_DEVICE_DESC *prP2pDevDesc, + IN uint8_t *pucSsid, + IN uint8_t ucSsidLen, + IN uint8_t ucOperatingChnl, + IN uint8_t ucInvitationType, + IN uint8_t *pucGroupBssid) +{ +#if 1 + union iwreq_data evt; + uint8_t aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + /* buffer peer information for later IOC_P2P_GET_STRUCT access */ + prGlueInfo->prP2PInfo[0]->u4ConnReqNameLength = + (uint32_t) ((prP2pDevDesc->u2NameLength > 32) + ? 32 : prP2pDevDesc->u2NameLength); + kalMemCopy(prGlueInfo->prP2PInfo[0]->aucConnReqDevName, + prP2pDevDesc->aucName, + prGlueInfo->prP2PInfo[0]->u4ConnReqNameLength); + COPY_MAC_ADDR(prGlueInfo->prP2PInfo[0]->rConnReqPeerAddr, + prP2pDevDesc->aucDeviceAddr); + COPY_MAC_ADDR(prGlueInfo->prP2PInfo[0]->rConnReqGroupAddr, + pucGroupBssid); + prGlueInfo->prP2PInfo[0]->i4ConnReqConfigMethod = (int32_t) + (prP2pDevDesc->u2ConfigMethod); + prGlueInfo->prP2PInfo[0]->ucOperatingChnl = ucOperatingChnl; + prGlueInfo->prP2PInfo[0]->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[0]->prDevHandler, + IWEVCUSTOM, &evt, aucBuffer); + +#else + struct MSG_P2P_CONNECTION_REQUEST *prP2pConnReq = + (struct MSG_P2P_CONNECTION_REQUEST *) NULL; + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo = + (struct P2P_SPECIFIC_BSS_INFO *) NULL; + struct P2P_CONNECTION_SETTINGS *prP2pConnSettings = + (struct P2P_CONNECTION_SETTINGS *) NULL; + + do { + ASSERT_BREAK((prGlueInfo != NULL) && (prP2pDevDesc != NULL)); + + /* Not a real solution */ + + prP2pSpecificBssInfo = + prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo; + prP2pConnSettings = + prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings; + + prP2pConnReq = (struct MSG_P2P_CONNECTION_REQUEST *) + cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_P2P_CONNECTION_REQUEST)); + + if (prP2pConnReq == NULL) + break; + + kalMemZero(prP2pConnReq, + sizeof(struct MSG_P2P_CONNECTION_REQUEST)); + + 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[0]->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, + (struct MSG_HDR *) prP2pConnReq, + MSG_SEND_METHOD_BUF); + + } while (FALSE); + + /* frog add. */ + /* TODO: Invitation Indication */ + +#endif + +} /* kalP2PInvitationIndication */ +#endif + +#if 0 +/*---------------------------------------------------------------------------*/ +/*! + * \brief Indicate an status to supplicant for device invitation status. + * + * \param[in] prGlueInfo Pointer of GLUE_INFO_T + * + * \retval none + */ +/*---------------------------------------------------------------------------*/ +void kalP2PInvitationStatus(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4InvStatus) +{ + union iwreq_data evt; + uint8_t aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + /* buffer peer information for later IOC_P2P_GET_STRUCT access */ + prGlueInfo->prP2PInfo[0]->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[0]->prDevHandler, + IWEVCUSTOM, &evt, aucBuffer); + +} /* kalP2PInvitationStatus */ +#endif + +/*---------------------------------------------------------------------------*/ +/*! + * \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 struct GLUE_INFO *prGlueInfo, + IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN], IN uint8_t ucSeqNum) +{ + union iwreq_data evt; + uint8_t aucBuffer[IW_CUSTOM_MAX]; + int32_t i4Ret = 0; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + + i4Ret = + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, + "P2P_SD_REQ %d", ucSeqNum); + if (i4Ret < 0) { + DBGLOG(INIT, WARN, "sprintf failed:%d\n", i4Ret); + return; + } + + evt.data.length = strlen(aucBuffer); + + /* indicate IWEVP2PSDREQ event */ + wireless_send_event(prGlueInfo->prP2PInfo[0]->prDevHandler, + IWEVCUSTOM, &evt, aucBuffer); +} /* end of kalP2PIndicateSDRequest() */ + +/*---------------------------------------------------------------------------*/ +/*! + * \brief Indicate an event to supplicant for Service Discovery response + * from other device. + * + * \param[in] prGlueInfo Pointer of GLUE_INFO_T + * + * \retval none + */ +/*---------------------------------------------------------------------------*/ +void kalP2PIndicateSDResponse(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN], IN uint8_t ucSeqNum) +{ + union iwreq_data evt; + uint8_t aucBuffer[IW_CUSTOM_MAX]; + int32_t i4Ret = 0; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + + i4Ret = + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, + "P2P_SD_RESP %d", ucSeqNum); + if (i4Ret < 0) { + DBGLOG(INIT, WARN, "sprintf failed:%d\n", i4Ret); + return; + } + evt.data.length = strlen(aucBuffer); + + /* indicate IWEVP2PSDREQ event */ + wireless_send_event(prGlueInfo->prP2PInfo[0]->prDevHandler, + IWEVCUSTOM, &evt, aucBuffer); +} /* end of kalP2PIndicateSDResponse() */ + +/*---------------------------------------------------------------------------*/ +/*! + * \brief Indicate an event to supplicant for Service Discovery TX Done + * from other device. + * + * \param[in] prGlueInfo Pointer of GLUE_INFO_T + * \param[in] ucSeqNum Sequence number of the frame + * \param[in] ucStatus Status code for TX + * + * \retval none + */ +/*---------------------------------------------------------------------------*/ +void kalP2PIndicateTXDone(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucSeqNum, IN uint8_t ucStatus) +{ + union iwreq_data evt; + uint8_t aucBuffer[IW_CUSTOM_MAX]; + int32_t i4Ret = 0; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + + i4Ret = + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, + "P2P_SD_XMITTED: %d %d", ucSeqNum, ucStatus); + if (i4Ret < 0) { + DBGLOG(INIT, WARN, "sprintf failed:%d\n", i4Ret); + return; + } + evt.data.length = strlen(aucBuffer); + + /* indicate IWEVP2PSDREQ event */ + wireless_send_event(prGlueInfo->prP2PInfo[0]->prDevHandler, + IWEVCUSTOM, &evt, aucBuffer); +} /* end of kalP2PIndicateSDResponse() */ + +struct net_device *kalP2PGetDevHdlr(struct GLUE_INFO *prGlueInfo) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo[0]); + return prGlueInfo->prP2PInfo[0]->prDevHandler; +} + +#if CFG_SUPPORT_ANTI_PIRACY +#if 0 +/*---------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] prAdapter Pointer of ADAPTER_T + * + * \return none + */ +/*---------------------------------------------------------------------------*/ +void kalP2PIndicateSecCheckRsp(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucRsp, IN uint16_t u2RspLen) +{ + union iwreq_data evt; + uint8_t aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_SEC_CHECK_RSP="); + + kalMemCopy(prGlueInfo->prP2PInfo[0]->aucSecCheckRsp, pucRsp, u2RspLen); + evt.data.length = strlen(aucBuffer); + +#if DBG + DBGLOG_MEM8(SEC, LOUD, + prGlueInfo->prP2PInfo[0]->aucSecCheckRsp, u2RspLen); +#endif + /* indicate in IWECUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo[0]->prDevHandler, + IWEVCUSTOM, &evt, aucBuffer); +} /* p2pFsmRunEventRxDisassociation */ +#endif +#endif + +/*---------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] prAdapter Pointer of ADAPTER_T + * + * \return none + */ +/*---------------------------------------------------------------------------*/ +void +kalGetChnlList(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_BAND eSpecificBand, + IN uint8_t ucMaxChannelNum, + IN uint8_t *pucNumOfChannel, + IN struct RF_CHANNEL_INFO *paucChannelList) +{ + rlmDomainGetChnlList(prGlueInfo->prAdapter, eSpecificBand, + FALSE, ucMaxChannelNum, pucNumOfChannel, paucChannelList); +} /* kalGetChnlList */ + +/* ////////////////////////////ICS SUPPORT////////////////////////////// */ + +void +kalP2PIndicateChannelReady(IN struct GLUE_INFO *prGlueInfo, + IN uint64_t u8SeqNum, + IN uint32_t u4ChannelNum, + IN enum ENUM_BAND eBand, + IN enum ENUM_CHNL_EXT eSco, + IN uint32_t u4Duration) +{ + struct ieee80211_channel *prIEEE80211ChnlStruct = + (struct ieee80211_channel *)NULL; + struct RF_CHANNEL_INFO rChannelInfo; + enum nl80211_channel_type eChnlType = NL80211_CHAN_NO_HT; + + do { + if (prGlueInfo == NULL) + break; + + kalMemZero(&rChannelInfo, sizeof(struct RF_CHANNEL_INFO)); + + rChannelInfo.ucChannelNum = u4ChannelNum; + rChannelInfo.eBand = eBand; + + prIEEE80211ChnlStruct = + kalP2pFuncGetChannelEntry(prGlueInfo->prP2PInfo[0], + &rChannelInfo); + + kalP2pFuncGetChannelType(eSco, &eChnlType); + + if (!prIEEE80211ChnlStruct) { + DBGLOG(P2P, WARN, "prIEEE80211ChnlStruct is NULL\n"); + break; + } + + cfg80211_ready_on_channel( + /* struct wireless_dev, */ + prGlueInfo->prP2PInfo[0]->prWdev, + /* u64 cookie, */ + u8SeqNum, + /* struct ieee80211_channel * chan, */ + prIEEE80211ChnlStruct, + /* unsigned int duration, */ + u4Duration, + /* gfp_t gfp *//* allocation flags */ + GFP_KERNEL); + } while (FALSE); + +} /* kalP2PIndicateChannelReady */ + +void +kalP2PIndicateChannelExpired(IN struct GLUE_INFO *prGlueInfo, + IN uint64_t u8SeqNum, + IN uint32_t u4ChannelNum, + IN enum ENUM_BAND eBand, + IN enum ENUM_CHNL_EXT eSco) +{ + + struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL; + struct ieee80211_channel *prIEEE80211ChnlStruct = + (struct ieee80211_channel *)NULL; + enum nl80211_channel_type eChnlType = NL80211_CHAN_NO_HT; + struct RF_CHANNEL_INFO rRfChannelInfo; + + do { + if (prGlueInfo == NULL) { + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo[0]; + + if (prGlueP2pInfo == NULL) { + ASSERT(FALSE); + break; + } + + DBGLOG(P2P, TRACE, "kalP2PIndicateChannelExpired\n"); + + rRfChannelInfo.eBand = eBand; + rRfChannelInfo.ucChannelNum = u4ChannelNum; + + prIEEE80211ChnlStruct = + kalP2pFuncGetChannelEntry(prGlueP2pInfo, + &rRfChannelInfo); + + kalP2pFuncGetChannelType(eSco, &eChnlType); + + if (!prIEEE80211ChnlStruct) { + DBGLOG(P2P, WARN, "prIEEE80211ChnlStruct is NULL\n"); + break; + } + + /* struct wireless_dev, */ + cfg80211_remain_on_channel_expired(prGlueP2pInfo->prWdev, + u8SeqNum, prIEEE80211ChnlStruct, GFP_KERNEL); + } while (FALSE); + +} /* kalP2PIndicateChannelExpired */ + +void kalP2PIndicateScanDone(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex, IN u_int8_t fgIsAbort) +{ + struct GL_P2P_DEV_INFO *prP2pGlueDevInfo = + (struct GL_P2P_DEV_INFO *) NULL; + struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL; + struct cfg80211_scan_request *prScanRequest = NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + do { + if (prGlueInfo == NULL) { + + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo[0]; + prP2pGlueDevInfo = prGlueInfo->prP2PDevInfo; + + if ((prGlueP2pInfo == NULL) || (prP2pGlueDevInfo == NULL)) { + ASSERT(FALSE); + break; + } + + DBGLOG(INIT, INFO, + "[p2p] scan complete %p\n", + prP2pGlueDevInfo->prScanRequest); + + KAL_ACQUIRE_MUTEX(prGlueInfo->prAdapter, MUTEX_DEL_INF); + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + if (prP2pGlueDevInfo->prScanRequest != NULL) { + prScanRequest = prP2pGlueDevInfo->prScanRequest; + kalCfg80211ScanDone(prScanRequest, fgIsAbort); + prP2pGlueDevInfo->prScanRequest = NULL; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + if ((prScanRequest != NULL) + && (prGlueInfo->prAdapter->fgIsP2PRegistered == TRUE)) { + + /* report all queued beacon/probe response frames + * to upper layer + */ + scanReportBss2Cfg80211(prGlueInfo->prAdapter, + BSS_TYPE_P2P_DEVICE, NULL); + + DBGLOG(INIT, TRACE, "DBG:p2p_cfg_scan_done\n"); + } + KAL_RELEASE_MUTEX(prGlueInfo->prAdapter, MUTEX_DEL_INF); + + } while (FALSE); + +} /* kalP2PIndicateScanDone */ + +void +kalP2PIndicateBssInfo(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucFrameBuf, + IN uint32_t u4BufLen, + IN struct RF_CHANNEL_INFO *prChannelInfo, + IN int32_t i4SignalStrength) +{ + struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) 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[0]; + + 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; + */ + + if (u4BufLen > 0) { +#if CFG_SUPPORT_TSF_USING_BOOTTIME + prBcnProbeRspFrame->u.beacon.timestamp = + kalGetBootTime(); +#endif + prCfg80211Bss = cfg80211_inform_bss_frame( + /* struct wiphy * wiphy, */ + prGlueP2pInfo->prWdev->wiphy, + prChannelEntry, + prBcnProbeRspFrame, + u4BufLen, i4SignalStrength, GFP_KERNEL); + } + + /* Return this structure. */ + if (prCfg80211Bss) + cfg80211_put_bss(prGlueP2pInfo->prWdev->wiphy, + prCfg80211Bss); + else + DBGLOG(P2P, WARN, + "indicate BSS to cfg80211 failed [" MACSTR + "]: bss channel %d, rcpi %d, frame_len=%d\n", + MAC2STR(prBcnProbeRspFrame->bssid), + prChannelInfo->ucChannelNum, + i4SignalStrength, u4BufLen); + + } while (FALSE); + + return; + +} /* kalP2PIndicateBssInfo */ + +void kalP2PIndicateMgmtTxStatus(IN struct GLUE_INFO *prGlueInfo, + IN struct MSDU_INFO *prMsduInfo, IN u_int8_t fgIsAck) +{ + struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL; + uint64_t *pu8GlCookie = (uint64_t *) NULL; + struct net_device *prNetdevice = (struct net_device *)NULL; + + do { + if ((prGlueInfo == NULL) || (prMsduInfo == NULL)) { + DBGLOG(P2P, WARN, + "Unexpected pointer PARAM. 0x%lx, 0x%lx.\n", + prGlueInfo, prMsduInfo); + ASSERT(FALSE); + break; + } + + pu8GlCookie = + (uint64_t *) ((unsigned long) prMsduInfo->prPacket + + (unsigned long) prMsduInfo->u2FrameLength + + MAC_TX_RESERVED_FIELD); + + if (prMsduInfo->ucBssIndex + == prGlueInfo->prAdapter->ucP2PDevBssIdx) { + + prGlueP2pInfo = prGlueInfo->prP2PInfo[0]; + + if (prGlueP2pInfo == NULL) + return; + + prNetdevice = prGlueP2pInfo->prDevHandler; + + } else { + struct BSS_INFO *prP2pBssInfo = + GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, + prMsduInfo->ucBssIndex); + + prGlueP2pInfo = + prGlueInfo->prP2PInfo + [prP2pBssInfo->u4PrivateData]; + + if (prGlueP2pInfo == NULL) + return; + + prNetdevice = prGlueP2pInfo->aprRoleHandler; + } + + cfg80211_mgmt_tx_status( + /* struct net_device * dev, */ + prNetdevice->ieee80211_ptr, + *pu8GlCookie, + (uint8_t *) ((unsigned long) prMsduInfo->prPacket + + MAC_TX_RESERVED_FIELD), + prMsduInfo->u2FrameLength, fgIsAck, GFP_KERNEL); + + } while (FALSE); + +} /* kalP2PIndicateMgmtTxStatus */ + +void +kalP2PIndicateRxMgmtFrame(IN struct GLUE_INFO *prGlueInfo, + IN struct SW_RFB *prSwRfb, + IN u_int8_t fgIsDevInterface, + IN uint8_t ucRoleIdx) +{ +#define DBG_P2P_MGMT_FRAME_INDICATION 1 + struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL; + int32_t i4Freq = 0; + uint8_t ucChnlNum = 0; +#if DBG_P2P_MGMT_FRAME_INDICATION + struct WLAN_MAC_HEADER *prWlanHeader = (struct WLAN_MAC_HEADER *) NULL; +#endif + struct net_device *prNetdevice = (struct net_device *)NULL; + + do { + if ((prGlueInfo == NULL) || (prSwRfb == NULL)) { + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + + /* ToDo[6630]: Get the following by channel freq */ + /* HAL_RX_STATUS_GET_CHAN_FREQ( prSwRfb->prRxStatus) */ + /* ucChnlNum = prSwRfb->prHifRxHdr->ucHwChannelNum; */ + + ucChnlNum = prSwRfb->ucChnlNum; + +#if DBG_P2P_MGMT_FRAME_INDICATION + + prWlanHeader = (struct WLAN_MAC_HEADER *) 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; + } +#endif + i4Freq = nicChannelNum2Freq(ucChnlNum) / 1000; + + if (fgIsDevInterface) + prNetdevice = prGlueP2pInfo->prDevHandler; + else + prNetdevice = prGlueP2pInfo->aprRoleHandler; + + DBGLOG(P2P, TRACE, "from: " MACSTR ", netdev: %p\n", + MAC2STR(prWlanHeader->aucAddr2), + prNetdevice); + + if (!prGlueInfo->fgIsRegistered || + (prNetdevice == NULL) || + (prNetdevice->ieee80211_ptr == NULL)) { + DBGLOG(P2P, WARN, + "prNetdevice is not ready or NULL!\n"); + break; + } + +#if (KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE) + cfg80211_rx_mgmt( + /* struct net_device * dev, */ + prNetdevice->ieee80211_ptr, + i4Freq, + RCPI_TO_dBm( + nicRxGetRcpiValueFromRxv(prGlueInfo->prAdapter, + RCPI_MODE_MAX, + prSwRfb)), + prSwRfb->pvHeader, + prSwRfb->u2PacketLen, + NL80211_RXMGMT_FLAG_ANSWERED); +#elif (KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE) + cfg80211_rx_mgmt( + /* struct net_device * dev, */ + prNetdevice->ieee80211_ptr, + i4Freq, + RCPI_TO_dBm( + nicRxGetRcpiValueFromRxv(prGlueInfo->prAdapter, + RCPI_MODE_WF0, + prSwRfb)), + prSwRfb->pvHeader, + prSwRfb->u2PacketLen, + NL80211_RXMGMT_FLAG_ANSWERED, + GFP_ATOMIC); +#else + cfg80211_rx_mgmt( + /* struct net_device * dev, */ + prNetdevice->ieee80211_ptr, + i4Freq, + RCPI_TO_dBm( + nicRxGetRcpiValueFromRxv(prGlueInfo->prAdapter, + RCPI_MODE_WF0, + prSwRfb)), + prSwRfb->pvHeader, + prSwRfb->u2PacketLen, + GFP_ATOMIC); +#endif + + + } while (FALSE); + +} /* kalP2PIndicateRxMgmtFrame */ + +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) +void +kalP2PGCIndicateConnectionStatus(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex, + IN struct P2P_CONNECTION_REQ_INFO *prP2pConnInfo, + IN uint8_t *pucRxIEBuf, + IN uint16_t u2RxIELen, + IN uint16_t u2StatusReason, + IN uint32_t eStatus) +{ + struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL; + struct ADAPTER *prAdapter = NULL; + + do { + if (prGlueInfo == NULL) { + ASSERT(FALSE); + break; + } + + prAdapter = prGlueInfo->prAdapter; + prGlueP2pInfo = prGlueInfo->prP2PInfo[ucRoleIndex]; + + /* FIXME: This exception occurs at wlanRemove. */ + if ((prGlueP2pInfo == NULL) || + (prGlueP2pInfo->aprRoleHandler == NULL) || + (prAdapter->rP2PNetRegState != + ENUM_NET_REG_STATE_REGISTERED) || + ((prGlueInfo->ulFlag & GLUE_FLAG_HALT) == 1)) { + break; + } + + if (prP2pConnInfo) { + /* switch netif on */ + netif_carrier_on(prGlueP2pInfo->aprRoleHandler); + + cfg80211_connect_result(prGlueP2pInfo->aprRoleHandler, + /* struct net_device * dev, */ + prP2pConnInfo->aucBssid, + prP2pConnInfo->aucIEBuf, + prP2pConnInfo->u4BufLength, + pucRxIEBuf, u2RxIELen, + u2StatusReason, + /* gfp_t gfp *//* allocation flags */ + GFP_KERNEL); + + prP2pConnInfo->eConnRequest = P2P_CONNECTION_TYPE_IDLE; + } else { + /* Disconnect, what if u2StatusReason == 0? */ + cfg80211_disconnected(prGlueP2pInfo->aprRoleHandler, + /* struct net_device * dev, */ + u2StatusReason, + pucRxIEBuf, u2RxIELen, + eStatus == WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY, + GFP_KERNEL); + } + + } while (FALSE); + +} /* kalP2PGCIndicateConnectionStatus */ + +#else +void +kalP2PGCIndicateConnectionStatus(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex, + IN struct P2P_CONNECTION_REQ_INFO *prP2pConnInfo, + IN uint8_t *pucRxIEBuf, + IN uint16_t u2RxIELen, + IN uint16_t u2StatusReason) +{ + struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL; + struct ADAPTER *prAdapter = NULL; + + do { + if (prGlueInfo == NULL) { + ASSERT(FALSE); + break; + } + + prAdapter = prGlueInfo->prAdapter; + prGlueP2pInfo = prGlueInfo->prP2PInfo[ucRoleIndex]; + + /* FIXME: This exception occurs at wlanRemove. */ + if ((prGlueP2pInfo == NULL) || + (prGlueP2pInfo->aprRoleHandler == NULL) || + (prAdapter->rP2PNetRegState != + ENUM_NET_REG_STATE_REGISTERED) || + ((prGlueInfo->ulFlag & GLUE_FLAG_HALT) == 1)) { + break; + } + + if (prP2pConnInfo) { + /* switch netif on */ + netif_carrier_on(prGlueP2pInfo->aprRoleHandler); + + cfg80211_connect_result(prGlueP2pInfo->aprRoleHandler, + /* struct net_device * dev, */ + prP2pConnInfo->aucBssid, + prP2pConnInfo->aucIEBuf, + prP2pConnInfo->u4BufLength, + pucRxIEBuf, u2RxIELen, + u2StatusReason, + /* gfp_t gfp *//* allocation flags */ + GFP_KERNEL); + + prP2pConnInfo->eConnRequest = P2P_CONNECTION_TYPE_IDLE; + } else { + /* Disconnect, what if u2StatusReason == 0? */ + cfg80211_disconnected(prGlueP2pInfo->aprRoleHandler, + /* struct net_device * dev, */ + u2StatusReason, pucRxIEBuf, + u2RxIELen, GFP_KERNEL); + } + + } while (FALSE); + +} /* kalP2PGCIndicateConnectionStatus */ + +#endif + +void +kalP2PGOStationUpdate(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex, + IN struct STA_RECORD *prCliStaRec, + IN u_int8_t fgIsNew) +{ + struct GL_P2P_INFO *prP2pGlueInfo = (struct GL_P2P_INFO *) NULL; + + do { + if ((prGlueInfo == NULL) || (prCliStaRec == NULL) + || (ucRoleIndex >= 2)) + break; + + prP2pGlueInfo = prGlueInfo->prP2PInfo[ucRoleIndex]; + + if ((prP2pGlueInfo == NULL) || + (prP2pGlueInfo->aprRoleHandler == NULL)) { + /* This case may occur when the usb is unplugged */ + break; + } + + if (fgIsNew) { + struct station_info rStationInfo; + + if (prCliStaRec->fgIsConnected == TRUE) + break; + prCliStaRec->fgIsConnected = TRUE; + + kalMemZero(&rStationInfo, sizeof(rStationInfo)); + +#if KERNEL_VERSION(4, 0, 0) > CFG80211_VERSION_CODE + rStationInfo.filled = STATION_INFO_ASSOC_REQ_IES; +#endif + rStationInfo.generation = ++prP2pGlueInfo->i4Generation; + + rStationInfo.assoc_req_ies = prCliStaRec->pucAssocReqIe; + rStationInfo.assoc_req_ies_len = + prCliStaRec->u2AssocReqIeLen; + + cfg80211_new_sta(prP2pGlueInfo->aprRoleHandler, + /* struct net_device * dev, */ + prCliStaRec->aucMacAddr, + &rStationInfo, GFP_KERNEL); + } else { + ++prP2pGlueInfo->i4Generation; + + /* FIXME: The exception occurs at wlanRemove, and + * check GLUE_FLAG_HALT is the temporarily solution. + */ + if ((prGlueInfo->ulFlag & GLUE_FLAG_HALT) == 0) { + if (prCliStaRec->fgIsConnected == FALSE) + break; + prCliStaRec->fgIsConnected = FALSE; + cfg80211_del_sta(prP2pGlueInfo->aprRoleHandler, + /* struct net_device * dev, */ + prCliStaRec->aucMacAddr, GFP_KERNEL); + } + } + + } while (FALSE); + + return; + +} /* kalP2PGOStationUpdate */ + +#if (CFG_SUPPORT_DFS_MASTER == 1) +void kalP2PRddDetectUpdate(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex) +{ + DBGLOG(INIT, INFO, "Radar Detection event\n"); + + do { + if (prGlueInfo == NULL) { + ASSERT(FALSE); + break; + } + + if (prGlueInfo->prP2PInfo[ucRoleIndex]->chandef == NULL) { + ASSERT(FALSE); + break; + } + + /* cac start disable for next cac slot + * if enable in dfs channel + */ + prGlueInfo->prP2PInfo[ucRoleIndex]->prWdev->cac_started = FALSE; + DBGLOG(INIT, INFO, + "kalP2PRddDetectUpdate: Update to OS\n"); + cfg80211_radar_event( + prGlueInfo->prP2PInfo[ucRoleIndex]->prWdev->wiphy, + prGlueInfo->prP2PInfo[ucRoleIndex]->chandef, + GFP_KERNEL); + DBGLOG(INIT, INFO, + "kalP2PRddDetectUpdate: Update to OS Done\n"); + + netif_carrier_off( + prGlueInfo->prP2PInfo[ucRoleIndex]->prDevHandler); + netif_tx_stop_all_queues( + prGlueInfo->prP2PInfo[ucRoleIndex]->prDevHandler); + + if (prGlueInfo->prP2PInfo[ucRoleIndex]->chandef->chan) + cnmMemFree(prGlueInfo->prAdapter, + prGlueInfo->prP2PInfo + [ucRoleIndex]->chandef->chan); + + prGlueInfo->prP2PInfo[ucRoleIndex]->chandef->chan = NULL; + + if (prGlueInfo->prP2PInfo[ucRoleIndex]->chandef) + cnmMemFree(prGlueInfo->prAdapter, + prGlueInfo->prP2PInfo[ucRoleIndex]->chandef); + + prGlueInfo->prP2PInfo[ucRoleIndex]->chandef = NULL; + + } while (FALSE); + +} /* kalP2PRddDetectUpdate */ + +void kalP2PCacFinishedUpdate(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex) +{ + DBGLOG(INIT, INFO, "CAC Finished event\n"); + + do { + if (prGlueInfo == NULL) { + ASSERT(FALSE); + break; + } + + if (prGlueInfo->prP2PInfo[ucRoleIndex]->chandef == NULL) { + ASSERT(FALSE); + break; + } + + DBGLOG(INIT, INFO, "kalP2PCacFinishedUpdate: Update to OS\n"); +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE + cfg80211_cac_event( + prGlueInfo->prP2PInfo[ucRoleIndex]->prDevHandler, + prGlueInfo->prP2PInfo[ucRoleIndex]->chandef, + NL80211_RADAR_CAC_FINISHED, GFP_KERNEL); +#else + cfg80211_cac_event( + prGlueInfo->prP2PInfo[ucRoleIndex]->prDevHandler, + NL80211_RADAR_CAC_FINISHED, GFP_KERNEL); +#endif + DBGLOG(INIT, INFO, + "kalP2PCacFinishedUpdate: Update to OS Done\n"); + + } while (FALSE); + +} /* kalP2PRddDetectUpdate */ +#endif + +u_int8_t kalP2pFuncGetChannelType(IN enum ENUM_CHNL_EXT rChnlSco, + OUT enum nl80211_channel_type *channel_type) +{ + u_int8_t 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 struct GL_P2P_INFO *prP2pInfo, + IN struct RF_CHANNEL_INFO *prChannelInfo) +{ + struct ieee80211_channel *prTargetChannelEntry = + (struct ieee80211_channel *)NULL; + uint32_t u4TblSize = 0, u4Idx = 0; + struct wiphy *wiphy = NULL; + + if ((prP2pInfo == NULL) || (prChannelInfo == NULL)) + return NULL; + + wiphy = prP2pInfo->prWdev->wiphy; + + do { + + switch (prChannelInfo->eBand) { + case BAND_2G4: + if (wiphy->bands[KAL_BAND_2GHZ] == NULL) + DBGLOG(P2P, ERROR, + "kalP2pFuncGetChannelEntry 2.4G NULL Bands!!\n"); + else { + prTargetChannelEntry = + wiphy->bands[KAL_BAND_2GHZ]->channels; + u4TblSize = + wiphy->bands[KAL_BAND_2GHZ]->n_channels; + } + break; + case BAND_5G: + if (wiphy->bands[KAL_BAND_5GHZ] == NULL) + DBGLOG(P2P, ERROR, + "kalP2pFuncGetChannelEntry 5G NULL Bands!!\n"); + else { + prTargetChannelEntry = + wiphy->bands[KAL_BAND_5GHZ]->channels; + u4TblSize = + wiphy->bands[KAL_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 */ + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + +/*---------------------------------------------------------------------------*/ +/*! + * \brief to set the block list of Hotspot + * + * \param[in] + * prGlueInfo + * + * \return + */ +/*---------------------------------------------------------------------------*/ +u_int8_t kalP2PSetBlackList(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t rbssid[PARAM_MAC_ADDR_LEN], + IN u_int8_t fgIsblock, + IN uint8_t ucRoleIndex) +{ + uint8_t aucNullAddr[] = NULL_MAC_ADDR; + uint32_t i; + + ASSERT(prGlueInfo); + + /*if only one ap mode register, prGlueInfo->prP2PInfo[1] would be null*/ + if (!prGlueInfo->prP2PInfo[ucRoleIndex]) + return FALSE; + + if (EQUAL_MAC_ADDR(rbssid, aucNullAddr)) + return FALSE; + + if (fgIsblock) { + for (i = 0; i < P2P_MAXIMUM_CLIENT_COUNT; i++) { + if (EQUAL_MAC_ADDR( + &(prGlueInfo->prP2PInfo[ucRoleIndex] + ->aucblackMACList[i]), rbssid)) { + DBGLOG(P2P, WARN, MACSTR + " already in black list\n", + MAC2STR(rbssid)); + return FALSE; + } + } + for (i = 0; i < P2P_MAXIMUM_CLIENT_COUNT; i++) { + if (EQUAL_MAC_ADDR( + &(prGlueInfo->prP2PInfo + [ucRoleIndex] + ->aucblackMACList[i]), + aucNullAddr)) { + COPY_MAC_ADDR( + &(prGlueInfo->prP2PInfo + [ucRoleIndex] + ->aucblackMACList[i]), + rbssid); + return FALSE; + } + } + } else { + for (i = 0; i < P2P_MAXIMUM_CLIENT_COUNT; i++) { + if (EQUAL_MAC_ADDR( + &(prGlueInfo->prP2PInfo[ucRoleIndex] + ->aucblackMACList[i]), rbssid)) { + COPY_MAC_ADDR( + &(prGlueInfo->prP2PInfo[ucRoleIndex] + ->aucblackMACList[i]), aucNullAddr); + + return FALSE; + } + } + } + + return FALSE; + +} + +u_int8_t kalP2PResetBlackList(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex) +{ + uint8_t aucNullAddr[] = NULL_MAC_ADDR; + uint32_t i; + + if (!prGlueInfo || !prGlueInfo->prP2PInfo[ucRoleIndex]) + return FALSE; + + for (i = 0; i < P2P_MAXIMUM_CLIENT_COUNT; i++) { + COPY_MAC_ADDR( + &(prGlueInfo->prP2PInfo[ucRoleIndex] + ->aucblackMACList[i]), aucNullAddr); + } + + return TRUE; +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief to compare the black list of Hotspot + * + * \param[in] + * prGlueInfo + * + * \return + */ +/*---------------------------------------------------------------------------*/ +u_int8_t kalP2PCmpBlackList(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t rbssid[PARAM_MAC_ADDR_LEN], + IN uint8_t ucRoleIndex) +{ + uint8_t aucNullAddr[] = NULL_MAC_ADDR; + u_int8_t fgIsExsit = FALSE; + uint32_t i; + + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo[ucRoleIndex]); + + for (i = 0; i < P2P_MAXIMUM_CLIENT_COUNT; i++) { + if (UNEQUAL_MAC_ADDR(rbssid, aucNullAddr)) { + if (EQUAL_MAC_ADDR( + &(prGlueInfo->prP2PInfo + [ucRoleIndex]->aucblackMACList[i]), + rbssid)) { + fgIsExsit = TRUE; + return fgIsExsit; + } + } + } + + return fgIsExsit; + +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief to return the max clients of Hotspot + * + * \param[in] + * prGlueInfo + * + * \return + */ +/*---------------------------------------------------------------------------*/ +void kalP2PSetMaxClients(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4MaxClient, + IN uint8_t ucRoleIndex) +{ + ASSERT(prGlueInfo); + + if (prGlueInfo->prP2PInfo[ucRoleIndex] == NULL) + return; + + if (u4MaxClient == 0 || + u4MaxClient >= P2P_MAXIMUM_CLIENT_COUNT) + prGlueInfo->prP2PInfo[ucRoleIndex]->ucMaxClients = + P2P_MAXIMUM_CLIENT_COUNT; + else + prGlueInfo->prP2PInfo[ucRoleIndex]->ucMaxClients = u4MaxClient; + + DBGLOG(P2P, TRACE, + "Role(%d) max client count = %u\n", + ucRoleIndex, + prGlueInfo->prP2PInfo[ucRoleIndex]->ucMaxClients); +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief to return the max clients of Hotspot + * + * \param[in] + * prGlueInfo + * + * \return + */ +/*---------------------------------------------------------------------------*/ +u_int8_t kalP2PMaxClients(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4NumClient, IN uint8_t ucRoleIndex) +{ + ASSERT(prGlueInfo); + + if (prGlueInfo->prP2PInfo[ucRoleIndex] && + prGlueInfo->prP2PInfo[ucRoleIndex]->ucMaxClients) { + if ((uint8_t) u4NumClient + >= prGlueInfo->prP2PInfo[ucRoleIndex]->ucMaxClients) + return TRUE; + else + return FALSE; + } + + return FALSE; +} + +#endif + +void kalP2pUnlinkBss(IN struct GLUE_INFO *prGlueInfo, IN uint8_t aucBSSID[]) +{ + struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL; + + ASSERT(prGlueInfo); + ASSERT(aucBSSID); + + DBGLOG(P2P, INFO, "bssid: " MACSTR "\n", MAC2STR(aucBSSID)); + + prGlueP2pInfo = prGlueInfo->prP2PInfo[0]; + + if (prGlueP2pInfo == NULL) + return; + + if (scanSearchBssDescByBssidAndSsid(prGlueInfo->prAdapter, + aucBSSID, FALSE, NULL) != NULL) + scanRemoveBssDescByBssid(prGlueInfo->prAdapter, aucBSSID); +} + +void kalP2pIndicateQueuedMgmtFrame(IN struct GLUE_INFO *prGlueInfo, + IN struct P2P_QUEUED_ACTION_FRAME *prFrame) +{ + struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL; + struct net_device *prNetdevice = (struct net_device *) NULL; + + if ((prGlueInfo == NULL) || (prFrame == NULL)) { + ASSERT(FALSE); + return; + } + + DBGLOG(P2P, INFO, "Indicate queued p2p action frame.\n"); + + if (prFrame->prHeader == NULL || prFrame->u2Length == 0) { + DBGLOG(P2P, WARN, "Frame pointer is null or length is 0.\n"); + return; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo[prFrame->ucRoleIdx]; + prNetdevice = prGlueP2pInfo->prDevHandler; + +#if (KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE) + cfg80211_rx_mgmt( + /* struct net_device * dev, */ + prNetdevice->ieee80211_ptr, + prFrame->u4Freq, + 0, + prFrame->prHeader, + prFrame->u2Length, + NL80211_RXMGMT_FLAG_ANSWERED); +#elif (KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE) + cfg80211_rx_mgmt( + /* struct net_device * dev, */ + prNetdevice->ieee80211_ptr, + prFrame->u4Freq, + 0, + prFrame->prHeader, + prFrame->u2Length, + NL80211_RXMGMT_FLAG_ANSWERED, + GFP_ATOMIC); +#else + cfg80211_rx_mgmt( + /* struct net_device * dev, */ + prNetdevice->ieee80211_ptr, + prFrame->u4Freq, + 0, + prFrame->prHeader, + prFrame->u2Length, + GFP_ATOMIC); +#endif +} + +void kalP2pIndicateAcsResult(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex, + IN uint8_t ucPrimaryCh, + IN uint8_t ucSecondCh, + IN uint8_t ucSeg0Ch, + IN uint8_t ucSeg1Ch, + IN enum ENUM_MAX_BANDWIDTH_SETTING eChnlBw) +{ + struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL; + struct sk_buff *vendor_event = NULL; + uint16_t ch_width = MAX_BW_20MHZ; + + prGlueP2pInfo = prGlueInfo->prP2PInfo[ucRoleIndex]; + + if (!prGlueP2pInfo) { + DBGLOG(P2P, ERROR, "p2p glue info null.\n"); + return; + } + + switch (eChnlBw) { + case MAX_BW_20MHZ: + ch_width = 20; + break; + case MAX_BW_40MHZ: + ch_width = 40; + break; + case MAX_BW_80MHZ: + ch_width = 80; + break; + case MAX_BW_160MHZ: + ch_width = 160; + break; + default: + DBGLOG(P2P, ERROR, "unsupport width: %d.\n", ch_width); + break; + } + + DBGLOG(P2P, INFO, "r=%d, c=%d, s=%d, s0=%d, s1=%d, ch_w=%d\n", + ucRoleIndex, + ucPrimaryCh, + ucSecondCh, + ucSeg0Ch, + ucSeg1Ch, + ch_width); + +#if KERNEL_VERSION(3, 14, 0) <= LINUX_VERSION_CODE + vendor_event = cfg80211_vendor_event_alloc(prGlueP2pInfo->prWdev->wiphy, +#if KERNEL_VERSION(4, 1, 0) <= LINUX_VERSION_CODE + prGlueP2pInfo->prWdev, +#endif + 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN, + WIFI_EVENT_ACS, + GFP_KERNEL); +#endif + + if (!vendor_event) { + DBGLOG(P2P, ERROR, "allocate vendor event fail.\n"); + goto nla_put_failure; + } + + if (unlikely(nla_put_u8(vendor_event, + WIFI_VENDOR_ATTR_ACS_PRIMARY_CHANNEL, + ucPrimaryCh) < 0)) { + DBGLOG(P2P, ERROR, "put primary channel fail.\n"); + goto nla_put_failure; + } + + if (unlikely(nla_put_u8(vendor_event, + WIFI_VENDOR_ATTR_ACS_SECONDARY_CHANNEL, + ucSecondCh) < 0)) { + DBGLOG(P2P, ERROR, "put secondary channel fail.\n"); + goto nla_put_failure; + } + + if (unlikely(nla_put_u8(vendor_event, + WIFI_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL, + ucSeg0Ch) < 0)) { + DBGLOG(P2P, ERROR, "put vht seg0 fail.\n"); + goto nla_put_failure; + } + + if (unlikely(nla_put_u8(vendor_event, + WIFI_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL, + ucSeg1Ch) < 0)) { + DBGLOG(P2P, ERROR, "put vht seg1 fail.\n"); + goto nla_put_failure; + } + + if (unlikely(nla_put_u16(vendor_event, + WIFI_VENDOR_ATTR_ACS_CHWIDTH, + ch_width) < 0)) { + DBGLOG(P2P, ERROR, "put ch width fail.\n"); + goto nla_put_failure; + } + + if (unlikely(nla_put_u8(vendor_event, + WIFI_VENDOR_ATTR_ACS_HW_MODE, + ucPrimaryCh > 14 ? + P2P_VENDOR_ACS_HW_MODE_11A : + P2P_VENDOR_ACS_HW_MODE_11G) < 0)) { + DBGLOG(P2P, ERROR, "put hw mode fail.\n"); + goto nla_put_failure; + } +#if KERNEL_VERSION(3, 14, 0) <= LINUX_VERSION_CODE + cfg80211_vendor_event(vendor_event, GFP_KERNEL); +#endif + return; + +nla_put_failure: + if (vendor_event) + kfree_skb(vendor_event); +} + +void kalP2pNotifyStopApComplete(IN struct ADAPTER *prAdapter, + IN uint8_t ucRoleIndex) +{ + struct GL_P2P_INFO *prP2PInfo; + + if (!prAdapter) + return; + + prP2PInfo = prAdapter->prGlueInfo->prP2PInfo[ucRoleIndex]; + if (prP2PInfo && !completion_done(&prP2PInfo->rStopApComp)) + complete(&prP2PInfo->rStopApComp); +} + +void kalP2pIndicateChnlSwitch(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo) +{ + struct GL_P2P_INFO *prP2PInfo; + uint8_t role_idx = 0; + + if (!prAdapter || !prBssInfo) + return; + + role_idx = prBssInfo->u4PrivateData; + prP2PInfo = prAdapter->prGlueInfo->prP2PInfo[role_idx]; + + if (!prP2PInfo) { + DBGLOG(P2P, WARN, "p2p glue info is not active\n"); + return; + } + + /* Compose ch info. */ + if (prP2PInfo->chandef == NULL) { + struct ieee80211_channel *chan; + + prP2PInfo->chandef = (struct cfg80211_chan_def *) + cnmMemAlloc(prAdapter, RAM_TYPE_BUF, + sizeof(struct cfg80211_chan_def)); + if (!prP2PInfo->chandef) { + DBGLOG(P2P, WARN, "cfg80211_chan_def alloc fail\n"); + return; + } + + prP2PInfo->chandef->chan = (struct ieee80211_channel *) + cnmMemAlloc(prAdapter, RAM_TYPE_BUF, + sizeof(struct ieee80211_channel)); + + if (!prP2PInfo->chandef->chan) { + DBGLOG(P2P, WARN, "ieee80211_channel alloc fail\n"); + return; + } + + chan = ieee80211_get_channel(prP2PInfo->prWdev->wiphy, + nicChannelNum2Freq( + prBssInfo->ucPrimaryChannel) / 1000); + if (!chan) { + DBGLOG(P2P, WARN, + "get channel fail\n"); + return; + } + + /* Fill chan def */ + prP2PInfo->chandef->chan->band = + (prBssInfo->eBand == BAND_5G) ? + KAL_BAND_5GHZ : KAL_BAND_2GHZ; + prP2PInfo->chandef->chan->center_freq = nicChannelNum2Freq( + prBssInfo->ucPrimaryChannel) / 1000; + + prP2PInfo->chandef->chan->dfs_state = chan->dfs_state; + + switch (prBssInfo->ucVhtChannelWidth) { + case VHT_OP_CHANNEL_WIDTH_80P80: + prP2PInfo->chandef->width + = NL80211_CHAN_WIDTH_80P80; + prP2PInfo->chandef->center_freq1 + = nicChannelNum2Freq( + prBssInfo->ucVhtChannelFrequencyS1) / 1000; + prP2PInfo->chandef->center_freq2 + = nicChannelNum2Freq( + prBssInfo->ucVhtChannelFrequencyS2) / 1000; + break; + case VHT_OP_CHANNEL_WIDTH_160: + prP2PInfo->chandef->width + = NL80211_CHAN_WIDTH_160; + prP2PInfo->chandef->center_freq1 + = nicChannelNum2Freq( + prBssInfo->ucVhtChannelFrequencyS1) / 1000; + prP2PInfo->chandef->center_freq2 + = nicChannelNum2Freq( + prBssInfo->ucVhtChannelFrequencyS2) / 1000; + break; + case VHT_OP_CHANNEL_WIDTH_80: + prP2PInfo->chandef->width + = NL80211_CHAN_WIDTH_80; + prP2PInfo->chandef->center_freq1 + = nicChannelNum2Freq( + prBssInfo->ucVhtChannelFrequencyS1) / 1000; + prP2PInfo->chandef->center_freq2 + = nicChannelNum2Freq( + prBssInfo->ucVhtChannelFrequencyS2) / 1000; + break; + case VHT_OP_CHANNEL_WIDTH_20_40: + prP2PInfo->chandef->center_freq1 + = prP2PInfo->chandef->chan->center_freq; + if (prBssInfo->eBssSCO == CHNL_EXT_SCA) { + prP2PInfo->chandef->width + = NL80211_CHAN_WIDTH_40; + prP2PInfo->chandef->center_freq1 += 10; + } else if (prBssInfo->eBssSCO == CHNL_EXT_SCB) { + prP2PInfo->chandef->width + = NL80211_CHAN_WIDTH_40; + prP2PInfo->chandef->center_freq1 -= 10; + } else { + prP2PInfo->chandef->width + = NL80211_CHAN_WIDTH_20; + } + prP2PInfo->chandef->center_freq2 = 0; + break; + default: + prP2PInfo->chandef->width + = NL80211_CHAN_WIDTH_20; + prP2PInfo->chandef->center_freq1 + = prP2PInfo->chandef->chan->center_freq; + prP2PInfo->chandef->center_freq2 = 0; + break; + } + + DBGLOG(P2P, INFO, + "role(%d) b=%d f=%d w=%d s1=%d s2=%d dfs=%d\n", + role_idx, + prP2PInfo->chandef->chan->band, + prP2PInfo->chandef->chan->center_freq, + prP2PInfo->chandef->width, + prP2PInfo->chandef->center_freq1, + prP2PInfo->chandef->center_freq2, + prP2PInfo->chandef->chan->dfs_state); + } + + /* Ch notify */ + cfg80211_ch_switch_notify( + prP2PInfo->prDevHandler, + prP2PInfo->chandef); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_proc.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_proc.c new file mode 100644 index 0000000000000..664749efe2cc0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_proc.c @@ -0,0 +1,1836 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: /os/linux/gl_proc.c + */ + +/*! \file "gl_proc.c" + * \brief This file defines the interface which can interact with users + * in /proc fs. + * + * Detail description. + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" +#include "gl_os.h" +#include "gl_kal.h" +#include "debug.h" +#include "wlan_lib.h" +#include "debug.h" +#include "wlan_oid.h" +#include + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define PROC_MCR_ACCESS "mcr" +#define PROC_ROOT_NAME "wlan" + +#if CFG_SUPPORT_DEBUG_FS +#define PROC_ROAM_PARAM "roam_param" +#endif +#define PROC_COUNTRY "country" +#define PROC_DRV_STATUS "status" +#define PROC_RX_STATISTICS "rx_statistics" +#define PROC_TX_STATISTICS "tx_statistics" +#define PROC_DBG_LEVEL_NAME "dbgLevel" +#define PROC_DRIVER_CMD "driver" +#define PROC_CFG "cfg" +#define PROC_EFUSE_DUMP "efuse_dump" +#define PROC_PKT_DELAY_DBG "pktDelay" +#if CFG_SUPPORT_SET_CAM_BY_PROC +#define PROC_SET_CAM "setCAM" +#endif +#define PROC_AUTO_PERF_CFG "autoPerfCfg" + +#if (CFG_SUPPORT_PRE_ON_PHY_ACTION == 1) +#define PROC_CAL_RESULT "cal_result" +#endif /*(CFG_SUPPORT_PRE_ON_PHY_ACTION == 1)*/ + +#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 +#define PROC_UID_SHELL 2000 +#define PROC_GID_WIFI 1010 + +/* notice: str only can be an array */ +#define SNPRINTF(buf, str, arg) {buf += \ + snprintf((char *)(buf), sizeof(str)-kalStrLen(str), PRINTF_ARG arg); } + +/******************************************************************************* + * 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 struct GLUE_INFO *g_prGlueInfo_proc; +static uint32_t u4McrOffset; +static struct proc_dir_entry *gprProcRoot; +static uint8_t aucDbModuleName[][PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN] = { + "INIT", "HAL", "INTR", "REQ", "TX", "RX", "RFTEST", "EMU", + "SW1", "SW2", "SW3", "SW4", "HEM", "AIS", "RLM", "MEM", + "CNM", "RSN", "BSS", "SCN", "SAA", "AAA", "P2P", "QM", + "SEC", "BOW", "WAPI", "ROAMING", "TDLS", "PF", "OID", "NIC" +}; + +/* This buffer could be overwrite by any proc commands */ +static uint8_t g_aucProcBuf[3000]; + +/* This u32 is only for DriverCmdRead/Write, + * should not be used by other function + */ +static int32_t g_i4NextDriverReadLen; +/******************************************************************************* + * M A 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 ssize_t procDbgLevelRead(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + uint8_t *temp = &g_aucProcBuf[0]; + uint8_t *str = NULL; + uint32_t u4CopySize = 0; + uint16_t i; + uint16_t u2ModuleNum = 0; + uint32_t u4StrLen = 0; + uint32_t u4Level1, u4Level2; + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0 || buf == NULL) + return 0; + + str = "\nTEMP|LOUD|INFO|TRACE | EVENT|STATE|WARN|ERROR\n" + "bit7|bit6|bit5|bit4 | bit3|bit2|bit1|bit0\n\n" + "Usage: Module Index:Module Level, such as 0x00:0xff\n\n" + "Debug Module\tIndex\tLevel\tDebug Module\tIndex\tLevel\n\n"; + u4StrLen = kalStrLen(str); + kalStrnCpy(temp, str, u4StrLen); + temp += u4StrLen; + + u2ModuleNum = + (sizeof(aucDbModuleName) / + PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN) & 0xfe; + + for (i = 0; i < u2ModuleNum; i += 2) { + wlanGetDriverDbgLevel(i, &u4Level1); + wlanGetDriverDbgLevel(i + 1, &u4Level2); + SNPRINTF(temp, g_aucProcBuf, + ("DBG_%s_IDX\t(0x%02x):\t0x%02x\t" + "DBG_%s_IDX\t(0x%02x):\t0x%02x\n", + &aucDbModuleName[i][0], i, (uint8_t) u4Level1, + &aucDbModuleName[i + 1][0], i + 1, + (uint8_t) u4Level2)); + } + + if ((sizeof(aucDbModuleName) / + PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN) & 0x1) { + wlanGetDriverDbgLevel(u2ModuleNum, &u4Level1); + SNPRINTF(temp, g_aucProcBuf, + ("DBG_%s_IDX\t(0x%02x):\t0x%02x\n", + &aucDbModuleName[u2ModuleNum][0], u2ModuleNum, + (uint8_t) u4Level1)); + } + + u4CopySize = kalStrLen(g_aucProcBuf); + if (u4CopySize > count) + u4CopySize = count; + if (copy_to_user(buf, g_aucProcBuf, u4CopySize)) { + pr_err("copy to user failed\n"); + return -EFAULT; + } + + *f_pos += u4CopySize; + return (ssize_t) u4CopySize; +} + +#if WLAN_INCLUDE_PROC +#if CFG_SUPPORT_EASY_DEBUG + +static void *procEfuseDump_start(struct seq_file *s, loff_t *pos) +{ + static unsigned long counter; + + if (*pos == 0) + counter = *pos; /* read file init */ + + if (counter >= EFUSE_ADDR_MAX) + return NULL; + return &counter; +} + +static void *procEfuseDump_next(struct seq_file *s, void *v, loff_t *pos) +{ + unsigned long *tmp_v = (unsigned long *)v; + + (*tmp_v) += EFUSE_BLOCK_SIZE; + + if (*tmp_v >= EFUSE_ADDR_MAX) + return NULL; + return tmp_v; +} + +static void procEfuseDump_stop(struct seq_file *s, void *v) +{ + /* nothing to do, we use a static value in start() */ +} + +static int procEfuseDump_show(struct seq_file *s, void *v) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo; + uint32_t idx_addr, idx_value; + struct PARAM_CUSTOM_ACCESS_EFUSE rAccessEfuseInfo = { }; + + prGlueInfo = g_prGlueInfo_proc; + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + if (prGlueInfo == NULL) { + seq_puts(s, "prGlueInfo is null\n"); + return -EPERM; + } + + if (prGlueInfo && + prGlueInfo->prAdapter && + prGlueInfo->prAdapter->chip_info && + !prGlueInfo->prAdapter->chip_info->is_support_efuse) { + seq_puts(s, "efuse ops is invalid\n"); + return -EPERM; /* return negative value to stop read process */ + } + + idx_addr = *(loff_t *) v; + rAccessEfuseInfo.u4Address = + (idx_addr / EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfo, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), TRUE, TRUE, + TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + seq_printf(s, "efuse read fail (0x%03X)\n", + rAccessEfuseInfo.u4Address); + return 0; + } + + for (idx_value = 0; idx_value < EFUSE_BLOCK_SIZE; idx_value++) + seq_printf(s, "0x%03X=0x%02X\n", + rAccessEfuseInfo.u4Address + idx_value, + prGlueInfo->prAdapter->aucEepromVaule[idx_value]); + return 0; +#else + seq_puts(s, "efuse ops is invalid\n"); + return -EPERM; /* return negative value to stop read process */ +#endif +} + +static int procEfuseDumpOpen(struct inode *inode, struct file *file) +{ + static const struct seq_operations procEfuseDump_ops = { + .start = procEfuseDump_start, + .next = procEfuseDump_next, + .stop = procEfuseDump_stop, + .show = procEfuseDump_show + }; + + return seq_open(file, &procEfuseDump_ops); +} + +static ssize_t procCfgRead(struct file *filp, char __user *buf, size_t count, + loff_t *f_pos) +{ + uint8_t *temp = &g_aucProcBuf[0]; + uint8_t *str = NULL; + uint8_t *str2 = "\nERROR DUMP CONFIGURATION:\n"; + uint32_t u4CopySize = 0; + uint32_t i; + uint32_t u4StrLen = 0; + +#define BUFFER_RESERVE_BYTE 50 + + struct GLUE_INFO *prGlueInfo; + + struct WLAN_CFG_ENTRY *prWlanCfgEntry; + struct ADAPTER *prAdapter; + + prGlueInfo = *((struct GLUE_INFO **)netdev_priv(gPrDev)); + + if (!prGlueInfo) { + pr_err("procCfgRead prGlueInfo is NULL????\n"); + return 0; + } + + prAdapter = prGlueInfo->prAdapter; + + if (!prAdapter) { + pr_err("procCfgRead prAdapter is NULL????\n"); + return 0; + } + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0 || buf == NULL) + return 0; + + str = "\nDUMP CONFIGURATION :\n" + " OR \n" + "'D': driver part current setting\n" + "===================================\n"; + u4StrLen = kalStrLen(str); + kalStrnCpy(temp, str, u4StrLen); + temp += u4StrLen; + + for (i = 0; i < WLAN_CFG_ENTRY_NUM_MAX; i++) { + prWlanCfgEntry = + wlanCfgGetEntryByIndex(prAdapter, i, WLAN_CFG_DEFAULT); + + if ((!prWlanCfgEntry) || (prWlanCfgEntry->aucKey[0] == '\0')) + break; + + SNPRINTF(temp, g_aucProcBuf, + ("%s|%s\n", prWlanCfgEntry->aucKey, + prWlanCfgEntry->aucValue)); + + if ((temp - g_aucProcBuf) != kalStrLen(g_aucProcBuf)) { + DBGLOG(INIT, ERROR, + "Dump configuration error: temp offset=%d, buf length=%u, key[%d]=[%u], val[%d]=[%u]\n", + (int)(temp - g_aucProcBuf), + (uint32_t)kalStrLen(g_aucProcBuf), + WLAN_CFG_KEY_LEN_MAX, + (uint32_t)prWlanCfgEntry->aucKey[ + WLAN_CFG_KEY_LEN_MAX - 1], + WLAN_CFG_VALUE_LEN_MAX, + (uint32_t)prWlanCfgEntry->aucValue[ + WLAN_CFG_VALUE_LEN_MAX - 1]); + kalMemSet(g_aucProcBuf, ' ', u4StrLen); + kalStrnCpy(g_aucProcBuf, str2, kalStrLen(str2) + 1); + g_aucProcBuf[u4StrLen-1] = 0; + goto procCfgReadLabel; + } + + if (kalStrLen(g_aucProcBuf) > + (sizeof(g_aucProcBuf) - BUFFER_RESERVE_BYTE)) + break; + } + + for (i = 0; i < WLAN_CFG_REC_ENTRY_NUM_MAX; i++) { + prWlanCfgEntry = + wlanCfgGetEntryByIndex(prAdapter, i, WLAN_CFG_REC); + + if ((!prWlanCfgEntry) || (prWlanCfgEntry->aucKey[0] == '\0')) + break; + + SNPRINTF(temp, g_aucProcBuf, + ("D:%s|%s\n", prWlanCfgEntry->aucKey, + prWlanCfgEntry->aucValue)); + + if ((temp - g_aucProcBuf) != kalStrLen(g_aucProcBuf)) { + DBGLOG(INIT, ERROR, + "D:Dump configuration error: temp offset=%d, buf length=%u, key[%d]=[%u], val[%d]=[%u]\n", + (int)(temp - g_aucProcBuf), + (uint32_t)kalStrLen(g_aucProcBuf), + WLAN_CFG_KEY_LEN_MAX, + (uint32_t)prWlanCfgEntry->aucKey[ + WLAN_CFG_KEY_LEN_MAX - 1], + WLAN_CFG_VALUE_LEN_MAX, + (uint32_t)prWlanCfgEntry->aucValue[ + WLAN_CFG_VALUE_LEN_MAX - 1]); + kalMemSet(g_aucProcBuf, ' ', u4StrLen); + kalStrnCpy(g_aucProcBuf, str2, kalStrLen(str2) + 1); + g_aucProcBuf[u4StrLen-1] = 0; + goto procCfgReadLabel; + } + + if (kalStrLen(g_aucProcBuf) > + (sizeof(g_aucProcBuf) - BUFFER_RESERVE_BYTE)) + break; + } + +procCfgReadLabel: + u4CopySize = kalStrLen(g_aucProcBuf); + if (u4CopySize > count) + u4CopySize = count; + if (copy_to_user(buf, g_aucProcBuf, u4CopySize)) { + pr_err("copy to user failed\n"); + return -EFAULT; + } + + *f_pos += u4CopySize; + return (ssize_t) u4CopySize; +} + +static ssize_t procCfgWrite(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + + /* uint32_t u4DriverCmd, u4DriverValue; + *uint8_t *temp = &g_aucProcBuf[0]; + */ + uint32_t u4CopySize = sizeof(g_aucProcBuf)-8; + struct GLUE_INFO *prGlueInfo; + uint8_t *pucTmp; + /* PARAM_CUSTOM_P2P_SET_STRUCT_T rSetP2P; */ + uint32_t i = 0; + + kalMemSet(g_aucProcBuf, 0, u4CopySize); + u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1); + + pucTmp = g_aucProcBuf; + SNPRINTF(pucTmp, g_aucProcBuf, ("%s ", "set_cfg")); + + if (copy_from_user(pucTmp, buffer, u4CopySize)) { + pr_err("error of copy from user\n"); + return -EFAULT; + } + g_aucProcBuf[u4CopySize + 8] = '\0'; + + for (i = 8 ; i < u4CopySize+8; i++) { + if (!isalnum(g_aucProcBuf[i]) && /* alphanumeric */ + g_aucProcBuf[i] != 0x20 && /* space */ + g_aucProcBuf[i] != 0x0a && /* control char */ + g_aucProcBuf[i] != 0x0d) { + DBGLOG(INIT, ERROR, "wrong char[%d] 0x%x\n", + i, g_aucProcBuf[i]); + return -EFAULT; + } + } + + prGlueInfo = g_prGlueInfo_proc; + /* if g_i4NextDriverReadLen >0, + * the content for next DriverCmdRead will be + * in : g_aucProcBuf with length : g_i4NextDriverReadLen + */ + g_i4NextDriverReadLen = + priv_driver_set_cfg(prGlueInfo->prDevHandler, g_aucProcBuf, + sizeof(g_aucProcBuf)); + + return count; + +} + +static ssize_t procDriverCmdRead(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + /* DriverCmd read should only be executed right after + * a DriverCmd write because content buffer 'g_aucProcBuf' + * is a global buffer for all proc command, otherwise , + * the content could be overwrite by other proc command + */ + uint32_t u4CopySize = 0; + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0 || buf == NULL) + return 0; + + if (g_i4NextDriverReadLen > 0) /* Detect content to show */ + u4CopySize = g_i4NextDriverReadLen; + + if (u4CopySize > count) { + pr_err("count is too small: u4CopySize=%u, count=%u\n", + u4CopySize, (uint32_t)count); + return -EFAULT; + } + + if (copy_to_user(buf, g_aucProcBuf, u4CopySize)) { + pr_err("copy to user failed\n"); + return -EFAULT; + } + g_i4NextDriverReadLen = 0; + + *f_pos += u4CopySize; + return (ssize_t) u4CopySize; +} + + + +static ssize_t procDriverCmdWrite(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ +/* UINT_32 u4DriverCmd, u4DriverValue; + * UINT_8 *temp = &g_aucProcBuf[0]; + */ + uint32_t u4CopySize = sizeof(g_aucProcBuf); + struct GLUE_INFO *prGlueInfo; +/* PARAM_CUSTOM_P2P_SET_STRUCT_T rSetP2P; */ + + kalMemSet(g_aucProcBuf, 0, u4CopySize); + u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1); + + if (copy_from_user(g_aucProcBuf, buffer, u4CopySize)) { + pr_err("error of copy from user\n"); + return -EFAULT; + } + g_aucProcBuf[u4CopySize] = '\0'; + + + prGlueInfo = g_prGlueInfo_proc; + /* if g_u4NextDriverReadLen >0, + * the content for next DriverCmdRead will be + * in : g_aucProcBuf with length : g_u4NextDriverReadLen + */ + if (strlen(g_aucProcBuf) > 0) { + g_i4NextDriverReadLen = + priv_driver_cmds(prGlueInfo->prDevHandler, g_aucProcBuf, + sizeof(g_aucProcBuf)); + } + + return count; +} +#endif +#endif + +static ssize_t procDbgLevelWrite(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + uint32_t u4NewDbgModule, u4NewDbgLevel; + uint8_t *temp = &g_aucProcBuf[0]; + uint32_t u4CopySize = sizeof(g_aucProcBuf); + + kalMemSet(g_aucProcBuf, 0, u4CopySize); + u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1); + + if (copy_from_user(g_aucProcBuf, buffer, u4CopySize)) { + pr_err("error of copy from user\n"); + return -EFAULT; + } + g_aucProcBuf[u4CopySize] = '\0'; + + while (temp) { + if (sscanf(temp, + "0x%x:0x%x", &u4NewDbgModule, &u4NewDbgLevel) != 2) { + pr_info("debug module and debug level should be one byte in length\n"); + break; + } + if (u4NewDbgModule == 0xFF) { + wlanSetDriverDbgLevel(DBG_ALL_MODULE_IDX, + (u4NewDbgLevel & DBG_CLASS_MASK)); + break; + } + if (u4NewDbgModule >= DBG_MODULE_NUM) { + pr_info("debug module index should less than %d\n", + DBG_MODULE_NUM); + break; + } + wlanSetDriverDbgLevel(u4NewDbgModule, + (u4NewDbgLevel & DBG_CLASS_MASK)); + temp = kalStrChr(temp, ','); + if (!temp) + break; + temp++; /* skip ',' */ + } + return count; +} + +static const struct file_operations dbglevel_ops = { + .owner = THIS_MODULE, + .read = procDbgLevelRead, + .write = procDbgLevelWrite, +}; + +#if WLAN_INCLUDE_PROC +#if CFG_SUPPORT_EASY_DEBUG + +static const struct file_operations efusedump_ops = { + .owner = THIS_MODULE, + .open = procEfuseDumpOpen, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static const struct file_operations drivercmd_ops = { + .owner = THIS_MODULE, + .read = procDriverCmdRead, + .write = procDriverCmdWrite, +}; + +static const struct file_operations cfg_ops = { + .owner = THIS_MODULE, + .read = procCfgRead, + .write = procCfgWrite, +}; +#endif +#endif + +/******************************************************************************* + * 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 ssize_t procMCRRead(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + struct GLUE_INFO *prGlueInfo; + struct PARAM_CUSTOM_MCR_RW_STRUCT rMcrInfo; + uint32_t u4BufLen; + uint32_t u4Count; + uint8_t *temp = &g_aucProcBuf[0]; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + /* Kevin: Apply PROC read method 1. */ + if (*f_pos > 0) + return 0; /* To indicate end of file. */ + + prGlueInfo = g_prGlueInfo_proc; + + rMcrInfo.u4McrOffset = u4McrOffset; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryMcrRead, (void *)&rMcrInfo, + sizeof(rMcrInfo), TRUE, TRUE, TRUE, &u4BufLen); + kalMemZero(g_aucProcBuf, sizeof(g_aucProcBuf)); + SNPRINTF(temp, g_aucProcBuf, + ("MCR (0x%08xh): 0x%08x\n", rMcrInfo.u4McrOffset, + rMcrInfo.u4McrData)); + + u4Count = kalStrLen(g_aucProcBuf); + if (copy_to_user(buf, g_aucProcBuf, u4Count)) { + pr_err("copy to user failed\n"); + return -EFAULT; + } + + *f_pos += u4Count; + + 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 ssize_t procMCRWrite(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + struct GLUE_INFO *prGlueInfo; + /* + 1 for "\0" */ + char acBuf[PROC_MCR_ACCESS_MAX_USER_INPUT_LEN + 1]; + int i4CopySize; + struct PARAM_CUSTOM_MCR_RW_STRUCT rMcrInfo; + uint32_t u4BufLen; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + int num = 0; + + ASSERT(data); + + i4CopySize = + (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + if (copy_from_user(acBuf, buffer, i4CopySize) || + i4CopySize < 0 || + i4CopySize > PROC_MCR_ACCESS_MAX_USER_INPUT_LEN) + return 0; + acBuf[i4CopySize] = '\0'; + + num = + sscanf(acBuf, "0x%x 0x%x", &rMcrInfo.u4McrOffset, + &rMcrInfo.u4McrData); + switch (num) { + 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 = g_prGlueInfo_proc; + + u4McrOffset = rMcrInfo.u4McrOffset; + + /* printk("Write 0x%lx to MCR 0x%04lx\n", */ + /* rMcrInfo.u4McrOffset, rMcrInfo.u4McrData); */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetMcrWrite, + (void *)&rMcrInfo, sizeof(rMcrInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + } + break; + case 1: + /* if (IS_ALIGN_4(rMcrInfo.u4McrOffset)) */ + { + u4McrOffset = rMcrInfo.u4McrOffset; + } + break; + + default: + break; + } + + return count; + +} /* end of procMCRWrite() */ + +static const struct file_operations mcr_ops = { + .owner = THIS_MODULE, + .read = procMCRRead, + .write = procMCRWrite, +}; + +#if CFG_SUPPORT_SET_CAM_BY_PROC +static ssize_t procSetCamCfgWrite(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ +#define MODULE_NAME_LEN_1 5 + + uint32_t u4CopySize = sizeof(g_aucProcBuf); + uint8_t *temp = &g_aucProcBuf[0]; + u_int8_t fgSetCamCfg = FALSE; + uint8_t aucModule[MODULE_NAME_LEN_1]; + uint32_t u4Enabled; + uint8_t aucModuleArray[MODULE_NAME_LEN_1] = "CAM"; + u_int8_t fgParamValue = TRUE; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + + kalMemSet(g_aucProcBuf, 0, u4CopySize); + u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1); + + if (copy_from_user(g_aucProcBuf, buffer, u4CopySize)) { + pr_err("error of copy from user\n"); + return -EFAULT; + } + g_aucProcBuf[u4CopySize] = '\0'; + temp = &g_aucProcBuf[0]; + while (temp) { + kalMemSet(aucModule, 0, MODULE_NAME_LEN_1); + + /* pick up a string and teminated after meet : */ + if (sscanf(temp, "%4s %d", aucModule, &u4Enabled) != 2) { + pr_info("read param fail, aucModule=%s\n", aucModule); + fgParamValue = FALSE; + break; + } + + if (kalStrnCmp + (aucModule, aucModuleArray, MODULE_NAME_LEN_1) == 0) { + if (u4Enabled) + fgSetCamCfg = TRUE; + else + fgSetCamCfg = FALSE; + } + temp = kalStrChr(temp, ','); + if (!temp) + break; + temp++; /* skip ',' */ + } + + if (fgParamValue) { + uint8_t i; + + prGlueInfo = wlanGetGlueInfo(); + if (!prGlueInfo) + return count; + + prAdapter = prGlueInfo->prAdapter; + if (!prAdapter) + return count; + + for (i = 0; i < KAL_AIS_NUM; i++) { + nicConfigProcSetCamCfgWrite(prAdapter, + fgSetCamCfg, + i); + } + } + + return count; +} + +static const struct file_operations proc_set_cam_ops = { + .owner = THIS_MODULE, + .write = procSetCamCfgWrite, +}; +#endif /*CFG_SUPPORT_SET_CAM_BY_PROC */ + +static ssize_t procPktDelayDbgCfgRead(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + uint8_t *temp = &g_aucProcBuf[0]; + uint8_t *str = NULL; + uint32_t u4CopySize = 0; + uint8_t ucTxRxFlag = 0; + uint8_t ucTxIpProto = 0; + uint16_t u2TxUdpPort = 0; + uint32_t u4TxDelayThreshold = 0; + uint8_t ucRxIpProto = 0; + uint16_t u2RxUdpPort = 0; + uint32_t u4RxDelayThreshold = 0; + uint32_t u4StrLen = 0; + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0 || buf == NULL) + return 0; + + str = "\nUsage: txLog/rxLog/reset 1(ICMP)/6(TCP)/11(UDP) Dst/SrcPortNum DelayThreshold(us)\n" + "Print tx delay log, such as: echo txLog 0 0 0 > pktDelay\n" + "Print tx UDP delay log, such as: echo txLog 11 0 0 > pktDelay\n" + "Print tx UDP dst port19305 delay log, such as: echo txLog 11 19305 0 > pktDelay\n" + "Print rx UDP src port19305 delay more than 500us log, such as: echo rxLog 11 19305 500 > pktDelay\n" + "Print tx TCP delay more than 500us log, such as: echo txLog 6 0 500 > pktDelay\n" + "Close log, such as: echo reset 0 0 0 > pktDelay\n\n"; + u4StrLen = kalStrLen(str); + kalStrnCpy(temp, str, u4StrLen); + temp += u4StrLen; + +#if (CFG_SUPPORT_STATISTICS == 1) + StatsEnvGetPktDelay(&ucTxRxFlag, &ucTxIpProto, &u2TxUdpPort, + &u4TxDelayThreshold, &ucRxIpProto, &u2RxUdpPort, + &u4RxDelayThreshold); +#endif + + if (ucTxRxFlag & BIT(0)) { + SNPRINTF(temp, g_aucProcBuf, + ("txLog %x %d %d\n", ucTxIpProto, u2TxUdpPort, + u4TxDelayThreshold)); + } + if (ucTxRxFlag & BIT(1)) { + SNPRINTF(temp, g_aucProcBuf, + ("rxLog %x %d %d\n", ucRxIpProto, u2RxUdpPort, + u4RxDelayThreshold)); + } + if (ucTxRxFlag == 0) + SNPRINTF(temp, g_aucProcBuf, + ("reset 0 0 0, there is no tx/rx delay log\n")); + + u4CopySize = kalStrLen(g_aucProcBuf); + if (u4CopySize > count) + u4CopySize = count; + if (copy_to_user(buf, g_aucProcBuf, u4CopySize)) { + pr_err("copy to user failed\n"); + return -EFAULT; + } + + *f_pos += u4CopySize; + return (ssize_t) u4CopySize; +} + +static ssize_t procPktDelayDbgCfgWrite(struct file *file, const char *buffer, + size_t count, loff_t *data) +{ +#define MODULE_NAME_LENGTH 7 +#define MODULE_RESET 0 +#define MODULE_TX 1 +#define MODULE_RX 2 + + uint32_t u4CopySize = sizeof(g_aucProcBuf); + uint8_t *temp = &g_aucProcBuf[0]; + uint8_t aucModule[MODULE_NAME_LENGTH]; + uint32_t u4DelayThreshold = 0; + uint32_t u4PortNum = 0; + uint32_t u4IpProto = 0; + uint8_t aucResetArray[MODULE_NAME_LENGTH] = "reset"; + uint8_t aucTxArray[MODULE_NAME_LENGTH] = "txLog"; + uint8_t aucRxArray[MODULE_NAME_LENGTH] = "rxLog"; + uint8_t ucTxOrRx = 0; + + kalMemSet(g_aucProcBuf, 0, u4CopySize); + u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1); + + if (copy_from_user(g_aucProcBuf, buffer, u4CopySize)) { + pr_err("error of copy from user\n"); + return -EFAULT; + } + g_aucProcBuf[u4CopySize] = '\0'; + + while (temp) { + kalMemSet(aucModule, 0, MODULE_NAME_LENGTH); + + /* pick up a string and teminated after meet : */ + if (sscanf + (temp, "%6s %x %d %d", aucModule, &u4IpProto, &u4PortNum, + &u4DelayThreshold) != 4) { + pr_info("read param fail, aucModule=%s\n", aucModule); + break; + } + + if (kalStrnCmp + (aucModule, aucResetArray, MODULE_NAME_LENGTH) == 0) { + ucTxOrRx = MODULE_RESET; + } else if (kalStrnCmp + (aucModule, aucTxArray, MODULE_NAME_LENGTH) == 0) { + ucTxOrRx = MODULE_TX; + } else if (kalStrnCmp + (aucModule, aucRxArray, MODULE_NAME_LENGTH) == 0) { + ucTxOrRx = MODULE_RX; + } else { + pr_info("input module error!\n"); + break; + } + + temp = kalStrChr(temp, ','); + if (!temp) + break; + temp++; /* skip ',' */ + } + +#if (CFG_SUPPORT_STATISTICS == 1) + StatsEnvSetPktDelay(ucTxOrRx, (uint8_t) u4IpProto, (uint16_t) u4PortNum, + u4DelayThreshold); +#endif + return count; +} + +static const struct file_operations proc_pkt_delay_dbg_ops = { + .owner = THIS_MODULE, + .read = procPktDelayDbgCfgRead, + .write = procPktDelayDbgCfgWrite, +}; + +#if CFG_SUPPORT_DEBUG_FS +static ssize_t procRoamRead(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + uint32_t u4CopySize; + uint32_t rStatus; + uint32_t u4BufLen; + + /* if *f_pos > 0, it means has read successed last time, + * don't try again + */ + if (*f_pos > 0 || buf == NULL) + return 0; + + rStatus = + kalIoctl(g_prGlueInfo_proc, wlanoidGetRoamParams, g_aucProcBuf, + sizeof(g_aucProcBuf), TRUE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "failed to read roam params\n"); + return -EINVAL; + } + + u4CopySize = kalStrLen(g_aucProcBuf); + if (copy_to_user(buf, g_aucProcBuf, u4CopySize)) { + pr_err("copy to user failed\n"); + return -EFAULT; + } + *f_pos += u4CopySize; + + return (int32_t) u4CopySize; +} + +static ssize_t procRoamWrite(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + uint32_t rStatus; + uint32_t u4BufLen = 0; + uint32_t u4CopySize = sizeof(g_aucProcBuf); + + kalMemSet(g_aucProcBuf, 0, u4CopySize); + u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1); + + if (copy_from_user(g_aucProcBuf, buffer, u4CopySize)) { + pr_err("error of copy from user\n"); + return -EFAULT; + } + g_aucProcBuf[u4CopySize] = '\0'; + + if (kalStrnCmp(g_aucProcBuf, "force_roam", 10) == 0) + rStatus = + kalIoctl(g_prGlueInfo_proc, wlanoidSetForceRoam, NULL, 0, + FALSE, FALSE, TRUE, &u4BufLen); + else + rStatus = + kalIoctl(g_prGlueInfo_proc, wlanoidSetRoamParams, + g_aucProcBuf, kalStrLen(g_aucProcBuf), FALSE, + FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "failed to set roam params: %s\n", + g_aucProcBuf); + return -EINVAL; + } + return count; +} + +static const struct file_operations roam_ops = { + .owner = THIS_MODULE, + .read = procRoamRead, + .write = procRoamWrite, +}; +#endif + +static ssize_t procCountryRead(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + uint32_t u4CopySize; + uint32_t country = 0; + + /* if *f_pos > 0, it means has read successed last time */ + if (*f_pos > 0) + return 0; + + country = rlmDomainGetCountryCode(); + + kalMemZero(g_aucProcBuf, sizeof(g_aucProcBuf)); + if (country) + kalSnprintf(g_aucProcBuf, sizeof(g_aucProcBuf), + "Current Country Code: %d\n", country); + else + kalSnprintf(g_aucProcBuf, sizeof(g_aucProcBuf), + "Current Country Code: NULL\n"); + + u4CopySize = kalStrLen(g_aucProcBuf); + if (copy_to_user(buf, g_aucProcBuf, u4CopySize)) { + pr_err("copy to user failed\n"); + return -EFAULT; + } + *f_pos += u4CopySize; + + return (int32_t) u4CopySize; +} + +static ssize_t procCountryWrite(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + uint32_t u4BufLen = 0; + uint32_t rStatus; + uint32_t u4CopySize = sizeof(g_aucProcBuf); + + kalMemSet(g_aucProcBuf, 0, u4CopySize); + u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1); + + if (copy_from_user(g_aucProcBuf, buffer, u4CopySize)) { + pr_err("error of copy from user\n"); + return -EFAULT; + } + g_aucProcBuf[u4CopySize] = '\0'; + + rStatus = kalIoctl(g_prGlueInfo_proc, wlanoidSetCountryCode, + &g_aucProcBuf[0], 2, FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "failed set country code: %s\n", + g_aucProcBuf); + return -EINVAL; + } + return count; +} + +static const struct file_operations country_ops = { + .owner = THIS_MODULE, + .read = procCountryRead, + .write = procCountryWrite, +}; + +static ssize_t procAutoPerfCfgRead(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + uint8_t *temp = &g_aucProcBuf[0]; + uint8_t *str = NULL; + uint32_t u4CopySize = 0; + uint32_t u4StrLen = 0; + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0) + return 0; + + str = "Auto Performance Configure Usage:\n" + "\n" + "echo ForceEnable:0 or 1 > /proc/net/wlan/autoPerfCfg\n" + " 1: always enable performance monitor\n" + " 0: restore performance monitor's default strategy\n"; + u4StrLen = kalStrLen(str); + kalStrnCpy(temp, str, u4StrLen + 1); + + u4CopySize = kalStrLen(g_aucProcBuf); + if (u4CopySize > count) + u4CopySize = count; + + if (copy_to_user(buf, g_aucProcBuf, u4CopySize)) { + DBGLOG(INIT, WARN, "copy_to_user error\n"); + return -EFAULT; + } + + *f_pos += u4CopySize; + return (ssize_t) u4CopySize; +} + +static ssize_t procAutoPerfCfgWrite(struct file *file, const char *buffer, + size_t count, loff_t *data) +{ + uint32_t u4CoreNum = 0; + uint32_t u4CoreFreq = 0; + uint8_t *temp = &g_aucProcBuf[0]; + uint32_t u4CopySize = count; + uint8_t i = 0; + uint32_t u4ForceEnable = 0; + uint8_t aucBuf[32]; + + if (u4CopySize >= sizeof(g_aucProcBuf)) + u4CopySize = sizeof(g_aucProcBuf) - 1; + + kalMemSet(g_aucProcBuf, 0, u4CopySize); + + if (copy_from_user(g_aucProcBuf, buffer, u4CopySize)) { + DBGLOG(INIT, WARN, "copy_from_user error\n"); + return -EFAULT; + } + + g_aucProcBuf[u4CopySize] = '\0'; + + i = sscanf(temp, "%d:%d", &u4CoreNum, &u4CoreFreq); + if (i == 2) { + DBGLOG(INIT, INFO, "u4CoreNum:%d, u4CoreFreq:%d\n", u4CoreNum, + u4CoreFreq); + kalSetCpuNumFreq(u4CoreNum, u4CoreFreq); + return u4CopySize; + } + + if (strlen(temp) > sizeof(aucBuf)) { + DBGLOG(INIT, WARN, + "input string(%s) len is too long, over %d\n", + g_aucProcBuf, (uint32_t) sizeof(aucBuf)); + return -EFAULT; + } + + i = sscanf(temp, "%11s:%d", aucBuf, &u4ForceEnable); + + if ((i == 2) && strstr(aucBuf, "ForceEnable")) { + kalPerMonSetForceEnableFlag(u4ForceEnable); + return u4CopySize; + } + + DBGLOG(INIT, WARN, "parameter format should be ForceEnable:0 or 1\n"); + + return -EFAULT; +} + +static const struct file_operations auto_perf_ops = { + .owner = THIS_MODULE, + .read = procAutoPerfCfgRead, + .write = procAutoPerfCfgWrite, +}; + +#if (CFG_SUPPORT_PRE_ON_PHY_ACTION == 1) +static ssize_t procCalResultRead(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct mt66xx_chip_info *prChipInfo = NULL; + uint32_t u4CalSize = 0; + uint8_t *prCalResult = NULL; + + /* if *f_pos > 0, it means has read successed last time */ + if (*f_pos > 0) + return 0; + + prGlueInfo = wlanGetGlueInfo(); + if (!prGlueInfo) + return 0; + + prAdapter = prGlueInfo->prAdapter; + if (!prAdapter) + return 0; + + prChipInfo = prAdapter->chip_info; + if (!prChipInfo) + return 0; + + if (prChipInfo->getCalResult) + prCalResult = prChipInfo->getCalResult(&u4CalSize); + else + return 0; + + if ((prCalResult == NULL) || (u4CalSize == 0)) { + DBGLOG(INIT, WARN, "prCalResult NULL\n"); + return 0; + } + + if (copy_to_user(buf, prCalResult, u4CalSize)) { + pr_err("copy to user failed\n"); + return -EFAULT; + } + + *f_pos += u4CalSize; + + return (int32_t)u4CalSize; +} + +static ssize_t procCalResultWrite(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + uint32_t u4CopySize = sizeof(g_aucProcBuf); + + kalMemSet(g_aucProcBuf, 0, u4CopySize); + u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1); + + if (copy_from_user(g_aucProcBuf, buffer, u4CopySize)) { + pr_err("error of copy from user\n"); + return -EFAULT; + } + + g_aucProcBuf[u4CopySize] = '\0'; + + return count; +} + +static const struct file_operations cal_result_ops = { + .owner = THIS_MODULE, + .read = procCalResultRead, + .write = procCalResultWrite, +}; +#endif /*(CFG_SUPPORT_PRE_ON_PHY_ACTION == 1)*/ + +int32_t procInitFs(void) +{ + struct proc_dir_entry *prEntry; + + g_i4NextDriverReadLen = 0; + + if (init_net.proc_net == (struct proc_dir_entry *)NULL) { + pr_err("init proc fs fail: proc_net == NULL\n"); + return -ENOENT; + } + + /* + * Directory: Root (/proc/net/wlan0) + */ + + gprProcRoot = proc_mkdir(PROC_ROOT_NAME, init_net.proc_net); + if (!gprProcRoot) { + pr_err("gprProcRoot == NULL\n"); + return -ENOENT; + } + proc_set_user(gprProcRoot, KUIDT_INIT(PROC_UID_SHELL), + KGIDT_INIT(PROC_GID_WIFI)); + + prEntry = + proc_create(PROC_DBG_LEVEL_NAME, 0664, gprProcRoot, &dbglevel_ops); + if (prEntry == NULL) { + pr_err("Unable to create /proc entry dbgLevel\n\r"); + return -1; + } + proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL), + KGIDT_INIT(PROC_GID_WIFI)); + + prEntry = + proc_create(PROC_AUTO_PERF_CFG, 0664, gprProcRoot, &auto_perf_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry %s/n", + PROC_AUTO_PERF_CFG); + return -1; + } + proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL), + KGIDT_INIT(PROC_GID_WIFI)); + +#if (CFG_SUPPORT_PRE_ON_PHY_ACTION == 1) + prEntry = proc_create(PROC_CAL_RESULT, + 0664, + gprProcRoot, + &cal_result_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry %s/n", + PROC_CAL_RESULT); + return -1; + } + proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL), + KGIDT_INIT(PROC_GID_WIFI)); +#endif /*(CFG_SUPPORT_PRE_ON_PHY_ACTION == 1)*/ + + return 0; +} /* end of procInitProcfs() */ + +int32_t procUninitProcFs(void) +{ +#if KERNEL_VERSION(3, 9, 0) <= LINUX_VERSION_CODE + +#if (CFG_SUPPORT_PRE_ON_PHY_ACTION == 1) + remove_proc_subtree(PROC_CAL_RESULT, gprProcRoot); +#endif /*(CFG_SUPPORT_PRE_ON_PHY_ACTION == 1)*/ + + remove_proc_subtree(PROC_AUTO_PERF_CFG, gprProcRoot); + remove_proc_subtree(PROC_DBG_LEVEL_NAME, gprProcRoot); + + /* + * move PROC_ROOT_NAME to last since it's root directory of the others + * incorrect sequence would cause use-after-free error + */ + remove_proc_subtree(PROC_ROOT_NAME, init_net.proc_net); +#else + +#if (CFG_SUPPORT_PRE_ON_PHY_ACTION == 1) + remove_proc_entry(PROC_CAL_RESULT, gprProcRoot); +#endif /*(CFG_SUPPORT_PRE_ON_PHY_ACTION == 1)*/ + + remove_proc_entry(PROC_AUTO_PERF_CFG, gprProcRoot); + remove_proc_entry(PROC_DBG_LEVEL_NAME, gprProcRoot); + + /* + * move PROC_ROOT_NAME to last since it's root directory of the others + * incorrect sequence would cause use-after-free error + */ + remove_proc_entry(PROC_ROOT_NAME, init_net.proc_net); +#endif + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function clean up a PROC fs created by procInitProcfs(). + * + * \param[in] prDev Pointer to the struct net_device. + * \param[in] pucDevName Pointer to the name of net_device. + * + * \return N/A + */ +/*----------------------------------------------------------------------------*/ +int32_t procRemoveProcfs(void) +{ + remove_proc_entry(PROC_MCR_ACCESS, gprProcRoot); + remove_proc_entry(PROC_DRIVER_CMD, gprProcRoot); + remove_proc_entry(PROC_CFG, gprProcRoot); + remove_proc_entry(PROC_EFUSE_DUMP, gprProcRoot); + remove_proc_entry(PROC_PKT_DELAY_DBG, gprProcRoot); +#if CFG_SUPPORT_SET_CAM_BY_PROC + remove_proc_entry(PROC_SET_CAM, gprProcRoot); +#endif +#if CFG_SUPPORT_DEBUG_FS + remove_proc_entry(PROC_ROAM_PARAM, gprProcRoot); +#endif + remove_proc_entry(PROC_COUNTRY, gprProcRoot); + return 0; +} /* end of procRemoveProcfs() */ + +int32_t procCreateFsEntry(struct GLUE_INFO *prGlueInfo) +{ + struct proc_dir_entry *prEntry; + + DBGLOG(INIT, TRACE, "[%s]\n", __func__); + g_prGlueInfo_proc = prGlueInfo; + + prEntry = proc_create(PROC_MCR_ACCESS, 0664, gprProcRoot, &mcr_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry mcr\n\r"); + return -1; + } + + prEntry = + proc_create(PROC_PKT_DELAY_DBG, 0664, gprProcRoot, + &proc_pkt_delay_dbg_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, + "Unable to create /proc entry pktDelay\n\r"); + return -1; + } + proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL), + KGIDT_INIT(PROC_GID_WIFI)); + +#if CFG_SUPPORT_SET_CAM_BY_PROC + prEntry = + proc_create(PROC_SET_CAM, 0664, gprProcRoot, &proc_set_cam_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry SetCAM\n\r"); + return -1; + } + proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL), + KGIDT_INIT(PROC_GID_WIFI)); +#endif +#if CFG_SUPPORT_DEBUG_FS + prEntry = proc_create(PROC_ROAM_PARAM, 0664, gprProcRoot, &roam_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, + "Unable to create /proc entry roam_param\n\r"); + return -1; + } +#endif + prEntry = proc_create(PROC_COUNTRY, 0664, gprProcRoot, &country_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry country\n\r"); + return -1; + } + +#if CFG_SUPPORT_EASY_DEBUG + + prEntry = + proc_create(PROC_DRIVER_CMD, 0664, gprProcRoot, &drivercmd_ops); + if (prEntry == NULL) { + pr_err("Unable to create /proc entry for driver command\n\r"); + return -1; + } + + prEntry = proc_create(PROC_CFG, 0664, gprProcRoot, &cfg_ops); + if (prEntry == NULL) { + pr_err("Unable to create /proc entry for driver cfg\n\r"); + return -1; + } + + prEntry = + proc_create(PROC_EFUSE_DUMP, 0664, gprProcRoot, &efusedump_ops); + if (prEntry == NULL) { + pr_err("Unable to create /proc entry efuse\n\r"); + return -1; + } +#endif + + return 0; +} + +#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) +{ + struct GLUE_INFO *prGlueInfo = ((struct net_device *)data)->priv; + char *p = page; + uint32_t u4Count; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(data); + + /* Kevin: Apply PROC read method 1. */ + if (off != 0) + return 0; /* To indicate end of file. */ + + SNPRINTF(p, page, ("GLUE LAYER STATUS:")); + SNPRINTF(p, page, ("\n==================")); + + SNPRINTF(p, page, + ("\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 += (uint32_t) (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) +{ + struct GLUE_INFO *prGlueInfo = ((struct net_device *)data)->priv; + char *p = page; + uint32_t u4Count; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(data); + + /* Kevin: Apply PROC read method 1. */ + if (off != 0) + return 0; /* To indicate end of file. */ + + SNPRINTF(p, page, ("RX STATISTICS (Write 1 to clear):")); + SNPRINTF(p, page, ("\n=================================\n")); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + wlanoidQueryRxStatisticsForLinuxProc(prGlueInfo->prAdapter, p, + &u4Count); + + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + u4Count += (uint32_t) (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) +{ + struct GLUE_INFO *prGlueInfo = ((struct net_device *)data)->priv; + /* + 1 for "\0" */ + char acBuf[PROC_RX_STATISTICS_MAX_USER_INPUT_LEN + 1]; + uint32_t u4CopySize; + uint32_t u4ClearCounter; + int32_t rv; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(data); + + u4CopySize = + (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + copy_from_user(acBuf, buffer, u4CopySize); + acBuf[u4CopySize] = '\0'; + + rv = kstrtoint(acBuf, 0, &u4ClearCounter); + if (rv == 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) +{ + struct GLUE_INFO *prGlueInfo = ((struct net_device *)data)->priv; + char *p = page; + uint32_t u4Count; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(data); + + /* Kevin: Apply PROC read method 1. */ + if (off != 0) + return 0; /* To indicate end of file. */ + + SNPRINTF(p, page, ("TX STATISTICS (Write 1 to clear):")); + SNPRINTF(p, page, ("\n=================================\n")); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + wlanoidQueryTxStatisticsForLinuxProc(prGlueInfo->prAdapter, p, + &u4Count); + + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + u4Count += (uint32_t) (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) +{ + struct GLUE_INFO *prGlueInfo = ((struct net_device *)data)->priv; + /* + 1 for "\0" */ + char acBuf[PROC_RX_STATISTICS_MAX_USER_INPUT_LEN + 1]; + uint32_t u4CopySize; + uint32_t u4ClearCounter; + int32_t rv; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(data); + + u4CopySize = + (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + copy_from_user(acBuf, buffer, u4CopySize); + acBuf[u4CopySize] = '\0'; + + rv = kstrtoint(acBuf, 0, &u4ClearCounter); + if (rv == 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 + +#ifdef FW_CFG_SUPPORT +#define MAX_CFG_OUTPUT_BUF_LENGTH 1024 +static uint8_t aucCfgBuf[CMD_FORMAT_V1_LENGTH]; +static uint8_t aucCfgQueryKey[MAX_CMD_NAME_MAX_LENGTH]; +static uint8_t aucCfgOutputBuf[MAX_CFG_OUTPUT_BUF_LENGTH]; + +static ssize_t cfgRead(struct file *filp, char __user *buf, size_t count, + loff_t *f_pos) +{ + uint32_t rStatus = WLAN_STATUS_FAILURE; + uint8_t *temp = &aucCfgOutputBuf[0]; + uint32_t u4CopySize = 0; + + struct CMD_HEADER cmdV1Header; + struct CMD_FORMAT_V1 *pr_cmd_v1 = + (struct CMD_FORMAT_V1 *)cmdV1Header.buffer; + + /* if *f_pos > 0, we should return 0 to make cat command exit */ + if (*f_pos > 0 || gprGlueInfo == NULL) + return 0; + if (!kalStrLen(aucCfgQueryKey)) + return 0; + + kalMemSet(aucCfgOutputBuf, 0, MAX_CFG_OUTPUT_BUF_LENGTH); + + SNPRINTF(temp, aucCfgOutputBuf, + ("\nprocCfgRead() %s:\n", aucCfgQueryKey)); + + /* send to FW */ + cmdV1Header.cmdVersion = CMD_VER_1; + cmdV1Header.cmdType = CMD_TYPE_QUERY; + cmdV1Header.itemNum = 1; + cmdV1Header.cmdBufferLen = sizeof(struct CMD_FORMAT_V1); + kalMemSet(cmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); + + pr_cmd_v1->itemStringLength = kalStrLen(aucCfgQueryKey); + + kalMemCopy(pr_cmd_v1->itemString, aucCfgQueryKey, + kalStrLen(aucCfgQueryKey)); + + rStatus = kalIoctl(gprGlueInfo, + wlanoidQueryCfgRead, + (void *)&cmdV1Header, + sizeof(cmdV1Header), TRUE, TRUE, TRUE, &u4CopySize); + if (rStatus == WLAN_STATUS_FAILURE) + DBGLOG(INIT, ERROR, + "kalIoctl wlanoidQueryCfgRead fail 0x%x\n", + rStatus); + + SNPRINTF(temp, aucCfgOutputBuf, + ("%s\n", cmdV1Header.buffer)); + + u4CopySize = kalStrLen(aucCfgOutputBuf); + if (u4CopySize > count) + u4CopySize = count; + + if (copy_to_user(buf, aucCfgOutputBuf, u4CopySize)) + DBGLOG(INIT, ERROR, "copy to user failed\n"); + + *f_pos += u4CopySize; + return (ssize_t) u4CopySize; +} + +static ssize_t cfgWrite(struct file *filp, const char __user *buf, + size_t count, loff_t *f_pos) +{ + /* echo xxx xxx > /proc/net/wlan/cfg */ + uint8_t i = 0; + uint32_t u4CopySize = sizeof(aucCfgBuf); + uint8_t token_num = 1; + + kalMemSet(aucCfgBuf, 0, u4CopySize); + u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1); + + if (copy_from_user(aucCfgBuf, buf, u4CopySize)) { + DBGLOG(INIT, ERROR, "copy from user failed\n"); + return -EFAULT; + } + aucCfgBuf[u4CopySize] = '\0'; + for (; i < u4CopySize; i++) { + if (aucCfgBuf[i] == ' ') { + token_num++; + break; + } + } + + if (token_num == 1) { + kalMemSet(aucCfgQueryKey, 0, sizeof(aucCfgQueryKey)); + /* remove the 0x0a */ + memcpy(aucCfgQueryKey, aucCfgBuf, u4CopySize); + if (aucCfgQueryKey[u4CopySize - 1] == 0x0a) + aucCfgQueryKey[u4CopySize - 1] = '\0'; + } else { + if (u4CopySize) + wlanFwCfgParse(gprGlueInfo->prAdapter, aucCfgBuf); + } + + return count; +} + +static const struct file_operations fwcfg_ops = { + .owner = THIS_MODULE, + .read = cfgRead, + .write = cfgWrite, +}; + +int32_t cfgRemoveProcEntry(void) +{ + remove_proc_entry(PROC_CFG_NAME, gprProcRoot); + return 0; +} + +int32_t cfgCreateProcEntry(struct GLUE_INFO *prGlueInfo) +{ + struct proc_dir_entry *prEntry; + + prGlueInfo->pProcRoot = gprProcRoot; + gprGlueInfo = prGlueInfo; + + prEntry = proc_create(PROC_CFG_NAME, 0664, gprProcRoot, &fwcfg_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry cfg\n\r"); + return -1; + } + proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL), + KGIDT_INIT(PROC_GID_WIFI)); + + return 0; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_qa_agent.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_qa_agent.c new file mode 100644 index 0000000000000..c270dda5f1b60 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_qa_agent.c @@ -0,0 +1,9655 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + Module Name: + gl_ate_agent.c +*/ +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ + +#include "precomp.h" +#if (CFG_SUPPORT_QA_TOOL == 1) +#include "gl_wext.h" +#include "gl_cfg80211.h" +#include "gl_ate_agent.h" +#include "gl_qa_agent.h" +#include "gl_hook_api.h" +#if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE +#include +#endif +#if (CONFIG_WLAN_SERVICE == 1) +#include "agent.h" +#endif + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +struct PARAM_RX_STAT g_HqaRxStat; +uint32_t u4RxStatSeqNum; +u_int8_t g_DBDCEnable = FALSE; +/* For SA Buffer Mode Temp Solution */ +u_int8_t g_BufferDownload = FALSE; +uint32_t u4EepromMode = 4; +uint32_t g_u4Chip_ID; + +static struct hqa_rx_stat_band_format g_backup_band0_info; +static struct hqa_rx_stat_band_format g_backup_band1_info; + +#if CFG_SUPPORT_BUFFER_MODE +uint8_t uacEEPROMImage[MAX_EEPROM_BUFFER_SIZE] = { + /* 0x000 ~ 0x00F */ + 0xAE, 0x86, 0x06, 0x00, 0x18, 0x0D, 0x00, 0x00, + 0xC0, 0x1F, 0xBD, 0x81, 0x3F, 0x01, 0x19, 0x00, + /* 0x010 ~ 0x01F */ + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, + /* 0x020 ~ 0x02F */ + 0x80, 0x02, 0x00, 0x00, 0x32, 0x66, 0xC3, 0x14, + 0x32, 0x66, 0xC3, 0x14, 0x03, 0x22, 0xFF, 0xFF, + /* 0x030 ~ 0x03F */ + 0x23, 0x04, 0x0D, 0xF2, 0x8F, 0x02, 0x00, 0x80, + 0x0A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x040 ~ 0x04F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x33, 0x40, 0x00, 0x00, + /* 0x050 ~ 0x05F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x08, + /* 0x060 ~ 0x06F */ + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x08, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x08, + /* 0x070 ~ 0x07F */ + 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x080 ~ 0x08F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x090 ~ 0x09F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x0A0 ~ 0x0AF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x0B0 ~ 0x0BF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x92, 0x10, 0x10, 0x28, 0x00, 0x00, 0x00, 0x00, + /* 0x0C0 ~ 0x0CF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x0D0 ~ 0x0DF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x0E0 ~ 0x0EF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x0F0 ~ 0x0FF */ + 0x0E, 0x05, 0x06, 0x06, 0x06, 0x0F, 0x00, 0x00, + 0x0E, 0x05, 0x06, 0x05, 0x05, 0x09, 0xFF, 0x00, + /* 0x100 ~ 0x10F */ + 0x12, 0x34, 0x56, 0x78, 0x2C, 0x2C, 0x28, 0x28, + 0x28, 0x26, 0x26, 0x28, 0x28, 0x28, 0x26, 0xFF, + /* 0x110 ~ 0x11F */ + 0x26, 0x25, 0x28, 0x21, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x27, 0x27, 0x27, 0x25, + /* 0x120 ~ 0x12F */ + 0x25, 0x25, 0x25, 0x25, 0x23, 0x23, 0x23, 0x21, + 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, + /* 0x130 ~ 0x13F */ + 0x40, 0x40, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, + 0xD0, 0xD0, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + /* 0x140 ~ 0x14F */ + 0x25, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x150 ~ 0x15F */ + 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, + 0x40, 0x40, 0x40, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, + /* 0x160 ~ 0x16F */ + 0xD0, 0xD0, 0xD0, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x170 ~ 0x17F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC2, 0xC4, 0xC5, 0xC8, + /* 0x180 ~ 0x18F */ + 0x00, 0x26, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x190 ~ 0x19F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x1A0 ~ 0x1AF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0xD0, + 0xD0, 0x0E, 0x05, 0x06, 0x05, 0x09, 0x0E, 0x00, + /* 0x1B0 ~ 0x1BF */ + 0x05, 0x06, 0x05, 0x05, 0x09, 0x00, 0x00, 0x00, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + /* 0x1C0 ~ 0x1CF */ + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, + /* 0x1D0 ~ 0x1DF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x1E0 ~ 0x1EF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x1F0 ~ 0x1FF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x200 ~ 0x20F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x210 ~ 0x21F */ + 0x48, 0xF5, 0x27, 0x49, 0x48, 0xF5, 0x57, 0x12, + 0x4B, 0x71, 0x80, 0x50, 0x91, 0xF6, 0x87, 0x50, + /* 0x220 ~ 0x22F */ + 0x7D, 0x29, 0x09, 0x42, 0x7D, 0x29, 0x41, 0x44, + 0x7D, 0x29, 0x41, 0x3C, 0x7D, 0x29, 0x31, 0x4D, + /* 0x230 ~ 0x23F */ + 0x49, 0x71, 0x24, 0x49, 0x49, 0x71, 0x54, 0x12, + 0x4B, 0x71, 0x80, 0x50, 0x91, 0xF6, 0x87, 0x50, + /* 0x240 ~ 0x24F */ + 0x7D, 0x29, 0x09, 0x42, 0x7D, 0x29, 0x41, 0x04, + 0x7D, 0x29, 0x41, 0x04, 0x7D, 0x29, 0x01, 0x40, + /* 0x250 ~ 0x25F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x260 ~ 0x26F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x270 ~ 0x27F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x280 ~ 0x28F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x290 ~ 0x29F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x2A0 ~ 0x2AF */ + 0x7D, 0x29, 0xC9, 0x16, 0x7D, 0x29, 0xC9, 0x16, + 0x44, 0x22, 0x32, 0x15, 0xEE, 0xEE, 0xEE, 0x08, + /* 0x2B0 ~ 0x2BF */ + 0x78, 0x90, 0x79, 0x1C, 0x78, 0x90, 0x79, 0x1C, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x2C0 ~ 0x2CF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x2D0 ~ 0x2DF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x2E0 ~ 0x2EF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x2F0 ~ 0x2FF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x300 ~ 0x30F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x310 ~ 0x31F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x42, 0x10, 0x42, 0x08, 0x21, + /* 0x320 ~ 0x32F */ + 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x21, + 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x21, + /* 0x330 ~ 0x33F */ + 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x21, + 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x21, + /* 0x340 ~ 0x34F */ + 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x21, + 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x01, + /* 0x350 ~ 0x35F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x360 ~ 0x36F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x370 ~ 0x37F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x380 ~ 0x38F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x390 ~ 0x39F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x3A0 ~ 0x3AF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x3B0 ~ 0x3BF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x3C0 ~ 0x3CF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x3D0 ~ 0x3DF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x3E0 ~ 0x3EF */ + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + /* 0x3F0 ~ 0x3FF */ + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + /* 0x400 ~ 0x40F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x410 ~ 0x41F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x420 ~ 0x42F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x430 ~ 0x43F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x440 ~ 0x44F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x450 ~ 0x45F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x460 ~ 0x46F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x470 ~ 0x47F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x480 ~ 0x48F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x490 ~ 0x49F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x4A0 ~ 0x4AF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Response ACK to QA Tool DLL. + * + * \param[in] HqaCmdFrame Ethernet Frame Format respond to QA Tool DLL + * \param[in] prIwReqData + * \param[in] i4Length Length of Ethernet Frame data field + * \param[in] i4Status Status to respond + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If copy_to_user fail + */ +/*----------------------------------------------------------------------------*/ +static int32_t ResponseToQA(struct HQA_CMD_FRAME + *HqaCmdFrame, + IN union iwreq_data *prIwReqData, int32_t i4Length, + int32_t i4Status) +{ + if (!prIwReqData) + return -EINVAL; + + HqaCmdFrame->Length = ntohs((i4Length)); + i4Status = ntohs((i4Status)); + memcpy(HqaCmdFrame->Data, &i4Status, 2); + + prIwReqData->data.length = sizeof((HqaCmdFrame)->MagicNo) + + sizeof((HqaCmdFrame)->Type) + + sizeof((HqaCmdFrame)->Id) + + sizeof((HqaCmdFrame)->Length) + + sizeof((HqaCmdFrame)->Sequence) + + ntohs((HqaCmdFrame)->Length); + + if (prIwReqData->data.length == 0) + return -EFAULT; + + if (copy_to_user(prIwReqData->data.pointer, + (uint8_t *) (HqaCmdFrame), prIwReqData->data.length)) { + DBGLOG(RFTEST, INFO, "QA_AGENT copy_to_user() fail in %s\n", + __func__); + return -EFAULT; + } + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA command(0x%04x)[Magic number(0x%08x)] is done\n", + ntohs(HqaCmdFrame->Id), ntohl(HqaCmdFrame->MagicNo)); + + return 0; +} + +static int32_t ToDoFunction(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT ToDoFunction\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Open Adapter (called when QA Tool UI Open). + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_OpenAdapter(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_OpenAdapter\n"); + + i4Ret = MT_ATEStart(prNetDev, "ATESTART"); + + /* For SA Buffer Mode Temp Solution */ + g_BufferDownload = FALSE; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Close Adapter (called when QA Tool UI Close). + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_CloseAdapter(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_CloseAdapter\n"); + + i4Ret = MT_ATEStop(prNetDev, "ATESTOP"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Start TX. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_StartTx(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t TxCount; + uint16_t TxLength; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StartTx\n"); + + memcpy((uint8_t *)&TxCount, HqaCmdFrame->Data + 4 * 0, 4); + TxCount = ntohl(TxCount); + memcpy((uint8_t *)&TxLength, HqaCmdFrame->Data + 4 * 1, 2); + TxLength = ntohs(TxLength); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StartTx TxCount = %d\n", + TxCount); + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StartTx TxLength = %d\n", + TxLength); + + i4Ret = MT_ATESetTxCount(prNetDev, TxCount); + i4Ret = MT_ATESetTxLength(prNetDev, (uint32_t) TxLength); + i4Ret = MT_ATEStartTX(prNetDev, "TXFRAME"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +/* 1 todo not support yet */ +static int32_t HQA_StartTxExt(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StartTxExt\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Start Continuous TX. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +/* 1 todo not support yet */ +static int32_t HQA_StartTxContiTx(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StartTxContiTx\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +/* 1 todo not support yets */ +static int32_t HQA_StartTxCarrier(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StartTxCarrier\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Start RX (Legacy function). + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_StartRx(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StartRx\n"); + + MT_ATESetDBDCBandIndex(prNetDev, 0); + MT_ATEStartRX(prNetDev, "RXFRAME"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Stop TX (Legacy function). + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_StopTx(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StopTx\n"); + + MT_ATESetDBDCBandIndex(prNetDev, 0); + MT_ATEStopRX(prNetDev, "RXSTOP"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Stop Continuous TX. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_StopContiTx(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StopContiTx\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_StopTxCarrier(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StopTxCarrier\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Stop RX (Legacy function). + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_StopRx(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StopRx\n"); + + MT_ATESetDBDCBandIndex(prNetDev, 0); + MT_ATEStopRX(prNetDev, "RXSTOP"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set TX Path. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetTxPath(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0, value = 0; + uint8_t band_idx = 0; + uint16_t tx_ant = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t u4BufLen = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetTxPath\n"); + + if (HqaCmdFrame->Length > 2) { + memcpy(&value, HqaCmdFrame->Data + 4 * 0, 4); + tx_ant = ntohl(value); + memcpy(&value, HqaCmdFrame->Data + 4 * 1, 4); + band_idx = ntohl(value); + + if (band_idx && tx_ant > 0x3) + tx_ant >>= 2; + DBGLOG(RFTEST, INFO, "tx_path:%d, band:%d\n", tx_ant, band_idx); + } else { + memcpy(&tx_ant, HqaCmdFrame->Data + 2 * 0, 2); + tx_ant = ntohs(tx_ant); + DBGLOG(RFTEST, INFO, "tx_path:%d, ", tx_ant); + } + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_DBDC_BAND_IDX; + rRfATInfo.u4FuncData = band_idx; + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TX_PATH; + rRfATInfo.u4FuncData = tx_ant; + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set RX Path. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetRxPath(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0, value = 0; + uint8_t band_idx = 0; + uint32_t rx_ant = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t u4BufLen = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetRxPath\n"); + + if (HqaCmdFrame->Length > 2) { + memcpy(&value, HqaCmdFrame->Data + 4 * 0, 4); + rx_ant = ntohl(value); + memcpy(&value, HqaCmdFrame->Data + 4 * 1, 4); + band_idx = ntohl(value); + + if (band_idx && rx_ant > 0x3) + rx_ant >>= 2; + DBGLOG(RFTEST, INFO, "rx_path:%d, band:%d\n", rx_ant, band_idx); + } else { + memcpy(&rx_ant, HqaCmdFrame->Data + 2 * 0, 2); + rx_ant = ntohs(rx_ant); + DBGLOG(RFTEST, INFO, "rx_path:%d, ", rx_ant); + } + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_DBDC_BAND_IDX; + rRfATInfo.u4FuncData = band_idx; + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_RX_PATH; + rRfATInfo.u4FuncData = (uint32_t) ((rx_ant << 16) + || (0 & BITS(0, 15))); + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set TX Inter-Packet Guard. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetTxIPG(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Aifs = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetTxIPG\n"); + + memcpy(&u4Aifs, HqaCmdFrame->Data + 4 * 0, 4); + u4Aifs = ntohs(u4Aifs); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetTxIPG u4Aifs : %d\n", + u4Aifs); + + MT_ATESetTxIPG(prNetDev, u4Aifs); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set TX Power0 (Legacy Function). + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetTxPower0(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetTxPower0\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set TX Power1. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HAQ_SetTxPower1(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HAQ_SetTxPower1\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetTxPowerExt(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Power = 0; + uint32_t u4Channel = 0; + uint32_t u4Dbdc_idx = 0; + uint32_t u4Band_idx = 0; + uint32_t u4Ant_idx = 0; + + memcpy(&u4Power, HqaCmdFrame->Data + 4 * 0, 4); + u4Power = ntohl(u4Power); + memcpy(&u4Dbdc_idx, HqaCmdFrame->Data + 4 * 1, 4); + u4Dbdc_idx = ntohl(u4Dbdc_idx); + memcpy(&u4Channel, HqaCmdFrame->Data + 4 * 2, 4); + u4Channel = ntohl(u4Channel); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 3, 4); + u4Band_idx = ntohl(u4Band_idx); + memcpy(&u4Ant_idx, HqaCmdFrame->Data + 4 * 4, 4); + u4Ant_idx = ntohl(u4Ant_idx); + + DBGLOG(RFTEST, INFO, + " QA_AGENT HQA_SetTxPowerExt u4Power : %u,u4Dbdc_idx:%u, u4Channel:%u,u4Band_idx:%u, u4Ant_idx:%u\n", + u4Power, u4Dbdc_idx, u4Channel, u4Band_idx, u4Ant_idx); + + MT_ATESetDBDCBandIndex(prNetDev, u4Dbdc_idx); + MT_ATESetTxPower0(prNetDev, u4Power); + /* u4Freq = nicChannelNum2Freq(u4Channel); */ + /* i4Ret = MT_ATESetChannel(prNetDev, 0, u4Freq); */ + /* MT_ATESetBand(prNetDev, u4Band_idx); */ + /* Antenna?? */ + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetOnOff(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetOnOff\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Antenna Selection. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_AntennaSel(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_AntennaSel\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_FWPacketCMD_ClockSwitchDisable( + struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_FWPacketCMD_ClockSwitchDisable\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_CMD_SET0[] = { + /* cmd id start from 0x1000 */ + HQA_OpenAdapter, /* 0x1000 */ + HQA_CloseAdapter, /* 0x1001 */ + HQA_StartTx, /* 0x1002 */ + HQA_StartTxExt, /* 0x1003 */ + HQA_StartTxContiTx, /* 0x1004 */ + HQA_StartTxCarrier, /* 0x1005 */ + HQA_StartRx, /* 0x1006 */ + HQA_StopTx, /* 0x1007 */ + HQA_StopContiTx, /* 0x1008 */ + HQA_StopTxCarrier, /* 0x1009 */ + HQA_StopRx, /* 0x100A */ + HQA_SetTxPath, /* 0x100B */ + HQA_SetRxPath, /* 0x100C */ + HQA_SetTxIPG, /* 0x100D */ + HQA_SetTxPower0, /* 0x100E */ + HAQ_SetTxPower1, /* 0x100F */ + ToDoFunction, /* 0x1010 */ + HQA_SetTxPowerExt, /* 0x1011 */ + HQA_SetOnOff, /* 0x1012 */ + HQA_AntennaSel, /* 0x1013 */ + HQA_FWPacketCMD_ClockSwitchDisable, /* 0x1014 */ +}; + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set Channel Frequency (Legacy Function). + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetChannel(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + uint32_t i4SetFreq = 0, i4SetChan = 0; + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetChannel\n"); + + memcpy((uint8_t *)&i4SetChan, HqaCmdFrame->Data, 4); + i4SetChan = ntohl(i4SetChan); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetChannel Channel = %d\n", i4SetChan); + + i4SetFreq = nicChannelNum2Freq(i4SetChan); + i4Ret = MT_ATESetChannel(prNetDev, 0, i4SetFreq); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set Preamble (Legacy Function). + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetPreamble(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Mode = 0; + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetPreamble\n"); + + memcpy((uint8_t *)&i4Mode, HqaCmdFrame->Data, 4); + i4Mode = ntohl(i4Mode); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetPreamble Mode = %d\n", + i4Mode); + + i4Ret = MT_ATESetPreamble(prNetDev, i4Mode); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set Rate (Legacy Function). + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetRate(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + /* INT_32 i4Value = 0; */ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetRate\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set Nss. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetNss(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetNss\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set System BW (Legacy Function). + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetSystemBW(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + uint32_t i4BW; + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetSystemBW\n"); + + memcpy((uint8_t *)&i4BW, HqaCmdFrame->Data, 4); + i4BW = ntohl(i4BW); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetSystemBW BW = %d\n", + i4BW); + + i4Ret = MT_ATESetSystemBW(prNetDev, i4BW); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set Data BW (Legacy Function). + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetPerPktBW(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Perpkt_bw; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetPerPktBW\n"); + + memcpy((uint8_t *)&u4Perpkt_bw, HqaCmdFrame->Data, 4); + u4Perpkt_bw = ntohl(u4Perpkt_bw); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetPerPktBW u4Perpkt_bw = %d\n", u4Perpkt_bw); + + i4Ret = MT_ATESetPerPacketBW(prNetDev, u4Perpkt_bw); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set Primary BW. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetPrimaryBW(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Pri_sel = 0; + + memcpy(&u4Pri_sel, HqaCmdFrame->Data, 4); + u4Pri_sel = ntohl(u4Pri_sel); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetPrimaryBW u4Pri_sel : %d\n", u4Pri_sel); + + i4Ret = MT_ATEPrimarySetting(prNetDev, u4Pri_sel); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set Frequency Offset. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetFreqOffset(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4FreqOffset = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t u4BufLen = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + memcpy(&u4FreqOffset, HqaCmdFrame->Data, 4); + u4FreqOffset = ntohl(u4FreqOffset); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetFreqOffset u4FreqOffset : %d\n", + u4FreqOffset); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_FRWQ_OFFSET; + rRfATInfo.u4FuncData = (uint32_t) u4FreqOffset; + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetAutoResponder(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetAutoResponder\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetTssiOnOff(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetTssiOnOff\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +/* 1 todo not support yet */ + +static int32_t HQA_SetRxHighLowTemperatureCompensation( + struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetRxHighLowTemperatureCompensation\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_LowPower(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_LowPower\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +#if CFG_SUPPORT_ANT_SWAP +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For query ant swap capablity + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetAntSwapCapability(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t value = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct mt66xx_chip_info *prChipInfo = NULL; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + if (!prGlueInfo || !prGlueInfo->prAdapter) { + DBGLOG(RFTEST, ERROR, "prGlueInfo or prAdapter is NULL\n"); + return -EFAULT; + } + + prChipInfo = prGlueInfo->prAdapter->chip_info; + if (!prChipInfo) { + DBGLOG(RFTEST, ERROR, "prChipInfo is NULL\n"); + return -EFAULT; + } + + DBGLOG(RFTEST, INFO, "HQA_GetAntSwapCapability [%d]\n", + prGlueInfo->prAdapter->fgIsSupportAntSwp); + + DBGLOG(RFTEST, INFO, "ucMaxSwapAntenna = [%d]\n", + prChipInfo->ucMaxSwapAntenna); + + if (prGlueInfo->prAdapter->fgIsSupportAntSwp) + value = ntohl(prChipInfo->ucMaxSwapAntenna); + else + value = 0; + + memcpy(HqaCmdFrame->Data + 2, &value, sizeof(value)); + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + sizeof(value), i4Ret); + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For setting antenna swap + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetAntSwap(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Ant = 0, u4Band = 0; + + memcpy(&u4Band, HqaCmdFrame->Data, sizeof(uint32_t)); + memcpy(&u4Ant, HqaCmdFrame->Data + sizeof(uint32_t), sizeof(uint32_t)); + u4Ant = ntohl(u4Ant); + + DBGLOG(RFTEST, INFO, "Band = %d, Ant = %d\n", u4Band, u4Ant); + + i4Ret = MT_ATESetAntSwap(prNetDev, u4Ant); + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + return i4Ret; + +} +#endif + + +static HQA_CMD_HANDLER HQA_CMD_SET1[] = { + /* cmd id start from 0x1100 */ + HQA_SetChannel, /* 0x1100 */ + HQA_SetPreamble, /* 0x1101 */ + HQA_SetRate, /* 0x1102 */ + HQA_SetNss, /* 0x1103 */ + HQA_SetSystemBW, /* 0x1104 */ + HQA_SetPerPktBW, /* 0x1105 */ + HQA_SetPrimaryBW, /* 0x1106 */ + HQA_SetFreqOffset, /* 0x1107 */ + HQA_SetAutoResponder, /* 0x1108 */ + HQA_SetTssiOnOff, /* 0x1109 */ + HQA_SetRxHighLowTemperatureCompensation, /* 0x110A */ + HQA_LowPower, /* 0x110B */ + NULL, /* 0x110C */ +#if CFG_SUPPORT_ANT_SWAP + HQA_GetAntSwapCapability, /* 0x110D */ + HQA_SetAntSwap, /* 0x110E */ +#endif +}; + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Reset TRX Counter + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_ResetTxRxCounter(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + uint32_t i4Status; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_ResetTxRxCounter\n"); + + i4Status = MT_ATEResetTXRXCounter(prNetDev); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetStatistics(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_GetStatistics\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetRxOKData(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_GetRxOKData\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetRxOKOther(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_GetRxOKOther\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetRxAllPktCount(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_GetRxAllPktCount\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetTxTransmitted(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_GetTxTransmitted\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetHwCounter(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_GetHwCounter\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_CalibrationOperation(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_CalibrationOperation\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_CalibrationBypassExt(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Status = 0; + uint32_t u4Item = 0; + uint32_t u4Band_idx = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t u4BufLen = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + memcpy(&u4Item, HqaCmdFrame->Data, 4); + u4Item = ntohl(u4Item); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_CalibrationBypassExt u4Item : 0x%08x\n", + u4Item); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_CalibrationBypassExt u4Band_idx : %d\n", + u4Band_idx); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_BYPASS_CAL_STEP; + rRfATInfo.u4FuncData = u4Item; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetRXVectorIdx(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t band_idx = 0; + uint32_t Group_1 = 0, Group_2 = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t u4BufLen = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + memcpy(&band_idx, HqaCmdFrame->Data + 4 * 0, 4); + band_idx = ntohl(band_idx); + memcpy(&Group_1, HqaCmdFrame->Data + 4 * 1, 4); + Group_1 = ntohl(Group_1); + memcpy(&Group_2, HqaCmdFrame->Data + 4 * 2, 4); + Group_2 = ntohl(Group_2); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetRXVectorIdx band_idx : %d\n", band_idx); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetRXVectorIdx Group_1 : %d\n", Group_1); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetRXVectorIdx Group_2 : %d\n", Group_2); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_RXV_INDEX; + rRfATInfo.u4FuncData = (uint32_t) (Group_1); + rRfATInfo.u4FuncData |= (uint32_t) (Group_2 << 8); + rRfATInfo.u4FuncData |= (uint32_t) (band_idx << 16); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetRXVectorIdx rRfATInfo.u4FuncData : 0x%08x\n", + rRfATInfo.u4FuncData); + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set FAGC Rssi Path + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetFAGCRssiPath(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4band_idx = 0; + uint32_t u4FAGC_Path = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t u4BufLen = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + memcpy(&u4band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4band_idx = ntohl(u4band_idx); + memcpy(&u4FAGC_Path, HqaCmdFrame->Data + 4 * 1, 4); + u4FAGC_Path = ntohl(u4FAGC_Path); + + DBGLOG(RFTEST, INFO, "u4band_idx : %d, u4FAGC_Path : %d\n", + u4band_idx, u4FAGC_Path); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_FAGC_RSSI_PATH; + rRfATInfo.u4FuncData = (uint32_t) ((u4band_idx << 16) | + (u4FAGC_Path & BITS(0, 15))); + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_CMD_SET2[] = { + /* cmd id start from 0x1200 */ + HQA_ResetTxRxCounter, /* 0x1200 */ + HQA_GetStatistics, /* 0x1201 */ + HQA_GetRxOKData, /* 0x1202 */ + HQA_GetRxOKOther, /* 0x1203 */ + HQA_GetRxAllPktCount, /* 0x1204 */ + HQA_GetTxTransmitted, /* 0x1205 */ + HQA_GetHwCounter, /* 0x1206 */ + HQA_CalibrationOperation, /* 0x1207 */ + HQA_CalibrationBypassExt, /* 0x1208 */ + HQA_SetRXVectorIdx, /* 0x1209 */ + HQA_SetFAGCRssiPath, /* 0x120A */ +}; + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For MAC CR Read. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_MacBbpRegRead(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + uint32_t u4Offset, u4Value; + int32_t i4Status; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MCR_RW_STRUCT rMcrInfo; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MacBbpRegRead\n"); + + memcpy(&u4Offset, HqaCmdFrame->Data, 4); + u4Offset = ntohl(u4Offset); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MacBbpRegRead Offset = 0x%08x\n", u4Offset); + + rMcrInfo.u4McrOffset = u4Offset; + rMcrInfo.u4McrData = 0; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, wlanoidQueryMcrRead, + &rMcrInfo, sizeof(rMcrInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + u4Value = rMcrInfo.u4McrData; + + DBGLOG(RFTEST, INFO, + "QA_AGENT Address = 0x%08x, Result = 0x%08x\n", u4Offset, + u4Value); + + u4Value = ntohl(u4Value); + memcpy(HqaCmdFrame->Data + 2, &u4Value, 4); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For MAC CR Write. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_MacBbpRegWrite(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + + /* INT_32 i4Ret = 0; */ + uint32_t u4Offset, u4Value; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MCR_RW_STRUCT rMcrInfo; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MacBbpRegWrite\n"); + + memcpy(&u4Offset, HqaCmdFrame->Data, 4); + memcpy(&u4Value, HqaCmdFrame->Data + 4, 4); + + u4Offset = ntohl(u4Offset); + u4Value = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MacBbpRegWrite Offset = 0x%08x\n", u4Offset); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MacBbpRegWrite Value = 0x%08x\n", u4Value); + + rMcrInfo.u4McrOffset = u4Offset; + rMcrInfo.u4McrData = u4Value; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, wlanoidSetMcrWrite, &rMcrInfo, + sizeof(rMcrInfo), FALSE, FALSE, TRUE, &u4BufLen); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Read Bulk MAC CR. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_MACBbpRegBulkRead(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + uint32_t u4Index, u4Offset, u4Value; + uint16_t u2Len; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MCR_RW_STRUCT rMcrInfo; + + memcpy(&u4Offset, HqaCmdFrame->Data, 4); + u4Offset = ntohl(u4Offset); + memcpy(&u2Len, HqaCmdFrame->Data + 4, 2); + u2Len = ntohs(u2Len); + + DBGLOG(RFTEST, INFO, "Offset = 0x%08x, Len = 0x%08x\n", + u4Offset, u2Len); + + for (u4Index = 0; u4Index < u2Len; u4Index++) { + rMcrInfo.u4McrOffset = u4Offset + u4Index * 4; + rMcrInfo.u4McrData = 0; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, wlanoidQueryMcrRead, + &rMcrInfo, sizeof(rMcrInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + u4Value = rMcrInfo.u4McrData; + + DBGLOG(RFTEST, INFO, + "Address = 0x%08x, Result = 0x%08x\n", + u4Offset + u4Index * 4, u4Value); + + u4Value = ntohl(u4Value); + memcpy(HqaCmdFrame->Data + 2 + (u4Index * 4), &u4Value, + 4); + } + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + (u2Len * 4), + i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Read Bulk RF CR. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_RfRegBulkRead(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + uint32_t u4Index, u4WfSel, u4Offset, u4Length, u4Value; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MCR_RW_STRUCT rMcrInfo; + + memcpy(&u4WfSel, HqaCmdFrame->Data, 4); + u4WfSel = ntohl(u4WfSel); + memcpy(&u4Offset, HqaCmdFrame->Data + 4, 4); + u4Offset = ntohl(u4Offset); + memcpy(&u4Length, HqaCmdFrame->Data + 8, 4); + u4Length = ntohl(u4Length); + + DBGLOG(RFTEST, INFO, " WfSel = %u, Offset = 0x%08x, Length = %u\n", + u4WfSel, u4Offset, u4Length); + + if (u4WfSel == 0) + u4Offset = u4Offset | 0x99900000; + else if (u4WfSel == 1) + u4Offset = u4Offset | 0x99910000; + else if (u4WfSel == 15) + u4Offset = u4Offset | 0x999F0000; + + + for (u4Index = 0; u4Index < u4Length; u4Index++) { + rMcrInfo.u4McrOffset = u4Offset + u4Index * 4; + rMcrInfo.u4McrData = 0; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, wlanoidQueryMcrRead, + &rMcrInfo, sizeof(rMcrInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + u4Value = rMcrInfo.u4McrData; + + DBGLOG(RFTEST, INFO, + "Address = 0x%08x, Result = 0x%08x\n", + u4Offset + u4Index * 4, u4Value); + + u4Value = ntohl(u4Value); + memcpy(HqaCmdFrame->Data + 2 + (u4Index * 4), &u4Value, + 4); + } + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + (u4Length * 4), + i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Write RF CR. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_RfRegBulkWrite(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + uint32_t u4WfSel, u4Offset, u4Length, u4Value; + int32_t i4Status; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MCR_RW_STRUCT rMcrInfo; + + memcpy(&u4WfSel, HqaCmdFrame->Data, 4); + u4WfSel = ntohl(u4WfSel); + memcpy(&u4Offset, HqaCmdFrame->Data + 4, 4); + u4Offset = ntohl(u4Offset); + memcpy(&u4Length, HqaCmdFrame->Data + 8, 4); + u4Length = ntohl(u4Length); + memcpy(&u4Value, HqaCmdFrame->Data + 12, 4); + u4Value = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, + "WfSel = %u, Offset = 0x%08x, Length = %u, Value = 0x%08x\n", + u4WfSel, u4Offset, u4Length, u4Value); + + if (u4WfSel == 0) + u4Offset = u4Offset | 0x99900000; + else if (u4WfSel == 1) + u4Offset = u4Offset | 0x99910000; + + + rMcrInfo.u4McrOffset = u4Offset; + rMcrInfo.u4McrData = u4Value; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, wlanoidSetMcrWrite, + &rMcrInfo, sizeof(rMcrInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_ReadEEPROM(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + + uint16_t Offset; + uint16_t Len; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + uint32_t u4BufLen = 0; + uint8_t u4Index = 0; + uint16_t u4Value = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_ACCESS_EFUSE rAccessEfuseInfo; +#endif + + DBGLOG(INIT, INFO, "QA_AGENT HQA_ReadEEPROM\n"); + + memcpy(&Offset, HqaCmdFrame->Data + 2 * 0, 2); + Offset = ntohs(Offset); + memcpy(&Len, HqaCmdFrame->Data + 2 * 1, 2); + Len = ntohs(Len); + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + if (!prGlueInfo) { + log_dbg(RFTEST, ERROR, "prGlueInfo is NULL\n"); + ResponseToQA(HqaCmdFrame, prIwReqData, 2, rStatus); + return rStatus; + } + + if (prGlueInfo->prAdapter && + prGlueInfo->prAdapter->chip_info && + !prGlueInfo->prAdapter->chip_info->is_support_efuse) { + rStatus = WLAN_STATUS_NOT_SUPPORTED; + log_dbg(RFTEST, WARN, "Efuse not support\n"); + ResponseToQA(HqaCmdFrame, prIwReqData, 2, rStatus); + return rStatus; + } + + kalMemSet(&rAccessEfuseInfo, 0, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + + rAccessEfuseInfo.u4Address = + (Offset / EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfo, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), + TRUE, TRUE, TRUE, &u4BufLen); + + u4Index = Offset % EFUSE_BLOCK_SIZE; + if (u4Index <= 14) + u4Value = + (prGlueInfo->prAdapter->aucEepromVaule[u4Index]) | + (prGlueInfo->prAdapter->aucEepromVaule[u4Index + 1] << 8); + + + /* isVaild = pResult->u4Valid; */ + + if (rStatus == WLAN_STATUS_SUCCESS) { + + DBGLOG(INIT, INFO, "QA_AGENT HQA_ReadEEPROM u4Value = %x\n", + u4Value); + + u4Value = ntohl(u4Value); + memcpy(HqaCmdFrame->Data + 2, &u4Value, sizeof(u4Value)); + } +#endif + + ResponseToQA(HqaCmdFrame, prIwReqData, 4, rStatus); + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_WriteEEPROM(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + uint16_t u4WriteData = 0; + uint32_t u4BufLen = 0; + uint8_t u4Index = 0; + uint16_t Offset; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_ACCESS_EFUSE rAccessEfuseInfoWrite; + + memcpy(&Offset, HqaCmdFrame->Data + 2 * 0, 2); + Offset = ntohs(Offset); + memcpy(&u4WriteData, HqaCmdFrame->Data + 2 * 1, 2); + u4WriteData = ntohs(u4WriteData); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); +#if 0 + /* Read */ + DBGLOG(INIT, INFO, "QA_AGENT HQA_ReadEEPROM\n"); + kalMemSet(&rAccessEfuseInfoRead, 0, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + rAccessEfuseInfoRead.u4Address = (Offset / EFUSE_BLOCK_SIZE) + * EFUSE_BLOCK_SIZE; + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfoRead, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), + FALSE, FALSE, TRUE, &u4BufLen); +#endif + + /* Write */ + DBGLOG(INIT, INFO, "QA_AGENT HQA_WriteEEPROM\n"); + kalMemSet(&rAccessEfuseInfoWrite, 0, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + u4Index = Offset % EFUSE_BLOCK_SIZE; + + if (prGlueInfo->prAdapter->rWifiVar.ucEfuseBufferModeCal == + TRUE && Offset >= 0 && Offset < MAX_EEPROM_BUFFER_SIZE - 1) { + uacEEPROMImage[Offset] = u4WriteData & 0xff; + uacEEPROMImage[Offset + 1] = u4WriteData >> 8 & 0xff; + } else if (u4Index >= EFUSE_BLOCK_SIZE - 1) { + DBGLOG(INIT, ERROR, "u4Index [%d] overrun\n", u4Index); + } else { + prGlueInfo->prAdapter->aucEepromVaule[u4Index] = u4WriteData + & 0xff; /* Note: u4WriteData is UINT_16 */ + prGlueInfo->prAdapter->aucEepromVaule[u4Index + 1] = + u4WriteData >> 8 & 0xff; + + kalMemCopy(rAccessEfuseInfoWrite.aucData, + prGlueInfo->prAdapter->aucEepromVaule, 16); + rAccessEfuseInfoWrite.u4Address = + (Offset / EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseWrite, + &rAccessEfuseInfoWrite, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), + FALSE, FALSE, TRUE, &u4BufLen); + } +#endif + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_ReadBulkEEPROM(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint16_t Offset; + uint16_t Len; +#if (CFG_EEPROM_PAGE_ACCESS == 1) + struct PARAM_CUSTOM_ACCESS_EFUSE rAccessEfuseInfo; + uint32_t u4BufLen = 0; + uint8_t u4Loop = 0; + + uint16_t Buffer; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint8_t tmp = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + kalMemSet(&rAccessEfuseInfo, 0, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); +#endif + + DBGLOG(INIT, INFO, "QA_AGENT HQA_ReadBulkEEPROM\n"); + if (prAdapter->chip_info && + !prAdapter->chip_info->is_support_efuse) { + log_dbg(RFTEST, WARN, "Efuse not support\n"); + rStatus = WLAN_STATUS_NOT_SUPPORTED; + ResponseToQA(HqaCmdFrame, prIwReqData, + 2, rStatus); + return rStatus; + } + + memcpy(&Offset, HqaCmdFrame->Data + 2 * 0, 2); + Offset = ntohs(Offset); + memcpy(&Len, HqaCmdFrame->Data + 2 * 1, 2); + Len = ntohs(Len); + tmp = Offset; + DBGLOG(INIT, INFO, + "QA_AGENT HQA_ReadBulkEEPROM Offset : %d\n", Offset); + DBGLOG(INIT, INFO, "QA_AGENT HQA_ReadBulkEEPROM Len : %d\n", + Len); + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + rAccessEfuseInfo.u4Address = (Offset / EFUSE_BLOCK_SIZE) * + EFUSE_BLOCK_SIZE; + + DBGLOG(INIT, INFO, + "QA_AGENT HQA_ReadBulkEEPROM Address : %d\n", + rAccessEfuseInfo.u4Address); + + if ((prGlueInfo->prAdapter->rWifiVar.ucEfuseBufferModeCal != + TRUE) + && (prGlueInfo->prAdapter->fgIsSupportQAAccessEfuse == + TRUE)) { + + /* Read from Efuse */ + DBGLOG(INIT, INFO, + "QA_AGENT HQA_ReadBulkEEPROM Efuse Mode\n"); + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfo, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_FAILURE) + DBGLOG(INIT, INFO, + "QA_AGENT HQA_ReadBulkEEPROM kal fail\n"); + + Offset = Offset % EFUSE_BLOCK_SIZE; + +#if 0 + for (u4Loop = 0; u4Loop < 16; u4Loop++) { + DBGLOG(INIT, INFO, + "MT6632:QA_AGENT HQA_ReadBulkEEPROM Efuse Offset=%x u4Loop=%d u4Value=%x\n", + Offset, u4Loop, + prGlueInfo->prAdapter->aucEepromVaule[u4Loop]); + } +#endif + for (u4Loop = 0; u4Loop < Len; u4Loop += 2) { + memcpy(&Buffer, prGlueInfo->prAdapter->aucEepromVaule + + Offset + u4Loop, 2); + Buffer = ntohs(Buffer); + DBGLOG(INIT, INFO, + ":From Efuse u4Loop=%d Buffer=%x\n", + u4Loop, Buffer); + memcpy(HqaCmdFrame->Data + 2 + u4Loop, &Buffer, 2); + } + + } else { /* Read from EEPROM */ + for (u4Loop = 0; u4Loop < Len; u4Loop += 2) { + memcpy(&Buffer, uacEEPROMImage + Offset + u4Loop, 2); + Buffer = ntohs(Buffer); + memcpy(HqaCmdFrame->Data + 2 + u4Loop, &Buffer, 2); + DBGLOG(INIT, INFO, + "QA_AGENT HQA_ReadBulkEEPROM u4Loop=%d u4Value=%x\n", + u4Loop, uacEEPROMImage[Offset + u4Loop]); + } + } +#endif + + /*kfree(Buffer);*/ + + /* Read from buffer array in driver */ + /* Pass these data to FW also */ +#if 0 + for (i = 0 ; i < Len ; i += 2) { + memcpy(&u2Temp, uacEEPROMImage + Offset + i, 2); + u2Temp = ntohs(u2Temp); + memcpy(HqaCmdFrame->Data + 2 + i, &u2Temp, 2); + } +#endif + /* For SA Buffer Mode Temp Solution */ +#if 0 + if (Offset == 0x4A0 && !g_BufferDownload) { + + uint16_t u2InitAddr = 0x000; + uint32_t i = 0, j = 0; + uint32_t u4BufLen = 0; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE rSetEfuseBufModeInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + for (i = 0 ; i < MAX_EEPROM_BUFFER_SIZE / 16 ; i++) { + for (j = 0 ; j < 16 ; j++) { + rSetEfuseBufModeInfo.aBinContent[j].u2Addr = + u2InitAddr; + rSetEfuseBufModeInfo.aBinContent[j].ucValue = + uacEEPROMImage[u2InitAddr]; + u2InitAddr += 1; + } + + rSetEfuseBufModeInfo.ucSourceMode = 1; + rSetEfuseBufModeInfo.ucCount = EFUSE_CONTENT_SIZE; + rStatus = kalIoctl(prGlueInfo, wlanoidSetEfusBufferMode, + &rSetEfuseBufModeInfo, + sizeof(struct PARAM_CUSTOM_EFUSE_BUFFER_MODE), + FALSE, FALSE, TRUE, &u4BufLen); + } + + g_BufferDownload = TRUE; + } +#endif + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + Len, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_WriteBulkEEPROM(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint16_t Offset; + uint16_t Len; + struct ADAPTER *prAdapter = NULL; + + uint32_t u4BufLen = 0; + struct PARAM_CUSTOM_ACCESS_EFUSE rAccessEfuseInfoRead, + rAccessEfuseInfoWrite; + uint16_t testBuffer1, testBuffer2, testBuffer; + uint16_t *Buffer = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint8_t u4Loop = 0, u4Index = 0; + uint16_t ucTemp2; + uint16_t i = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + kalMemSet(&rAccessEfuseInfoRead, 0, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + kalMemSet(&rAccessEfuseInfoWrite, 0, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + + DBGLOG(INIT, INFO, "QA_AGENT HQA_WriteBulkEEPROM\n"); + + + memcpy(&Offset, HqaCmdFrame->Data + 2 * 0, 2); + Offset = ntohs(Offset); + memcpy(&Len, HqaCmdFrame->Data + 2 * 1, 2); + Len = ntohs(Len); + + memcpy(&testBuffer1, HqaCmdFrame->Data + 2 * 2, Len); + testBuffer2 = ntohs(testBuffer1); + testBuffer = ntohs(testBuffer1); + + DBGLOG(INIT, INFO, "Offset : %x, Len : %u\n", Offset, Len); + + /* Support Delay Calibraiton */ + if (prGlueInfo->prAdapter->fgIsSupportQAAccessEfuse == + TRUE) { + + Buffer = kmalloc(sizeof(uint8_t) * (EFUSE_BLOCK_SIZE), + GFP_KERNEL); + ASSERT(Buffer); + kalMemSet(Buffer, 0, sizeof(uint8_t) * (EFUSE_BLOCK_SIZE)); + + kalMemCopy((uint8_t *)Buffer, + (uint8_t *)HqaCmdFrame->Data + 4, Len); + + for (u4Loop = 0; u4Loop < (Len); u4Loop++) { + + DBGLOG(INIT, INFO, + "QA_AGENT HQA_WriteBulkEEPROM u4Loop=%d u4Value=%x\n", + u4Loop, Buffer[u4Loop]); + } + + if (prGlueInfo->prAdapter->rWifiVar.ucEfuseBufferModeCal == + TRUE && + Offset >= 0 && Offset < MAX_EEPROM_BUFFER_SIZE - 1) { + /* EEPROM */ + DBGLOG(INIT, INFO, "Direct EEPROM buffer, offset=%x\n", + Offset); +#if 0 + for (i = 0; i < EFUSE_BLOCK_SIZE; i++) + memcpy(uacEEPROMImage + Offset + i, Buffer + i, + 1); + +#endif + *Buffer = ntohs(*Buffer); + uacEEPROMImage[Offset] = *Buffer & 0xff; + uacEEPROMImage[Offset + 1] = *Buffer >> 8 & 0xff; + } else { + /* EFUSE */ + /* Read */ + DBGLOG(INIT, INFO, + "QA_AGENT HQA_WriteBulkEEPROM Read\n"); + if (prAdapter->chip_info && + !prAdapter->chip_info->is_support_efuse) { + log_dbg(RFTEST, WARN, "Efuse not support\n"); + rStatus = WLAN_STATUS_NOT_SUPPORTED; + ResponseToQA(HqaCmdFrame, prIwReqData, + 2, rStatus); + kfree(Buffer); + return rStatus; + } + kalMemSet(&rAccessEfuseInfoRead, 0, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + rAccessEfuseInfoRead.u4Address = + (Offset / EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfoRead, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), + TRUE, TRUE, TRUE, &u4BufLen); + + /* Write */ + kalMemSet(&rAccessEfuseInfoWrite, 0, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + + if (Len > 2) { + for (u4Loop = 0; u4Loop < 8 ; u4Loop++) + Buffer[u4Loop] = ntohs(Buffer[u4Loop]); + memcpy(rAccessEfuseInfoWrite.aucData, Buffer, + 16); + } else { + u4Index = Offset % EFUSE_BLOCK_SIZE; + DBGLOG(INIT, INFO, + "MT6632:QA_AGENT HQA_WriteBulkEEPROM Wr,u4Index=%x,Buffer=%x\n", + u4Index, testBuffer); + + *Buffer = ntohs(*Buffer); + DBGLOG(INIT, INFO, + "Buffer[0]=%x, Buffer[0]&0xff=%x\n", + Buffer[0], Buffer[0] & 0xff); + DBGLOG(INIT, INFO, "Buffer[0] >> 8 & 0xff=%x\n" + , Buffer[0] >> 8 & 0xff); + + if (u4Index < EFUSE_BLOCK_SIZE - 1) { + prGlueInfo->prAdapter + ->aucEepromVaule[u4Index] = + *Buffer & 0xff; + prGlueInfo->prAdapter + ->aucEepromVaule[u4Index + 1] = + *Buffer >> 8 & 0xff; + kalMemCopy( + rAccessEfuseInfoWrite.aucData, + prGlueInfo->prAdapter + ->aucEepromVaule, 16); + } else { + DBGLOG(INIT, ERROR, + "u4Index [%d] overrun\n", + u4Index); + goto end; + } + } + + rAccessEfuseInfoWrite.u4Address = + (Offset / EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + for (u4Loop = 0; u4Loop < (EFUSE_BLOCK_SIZE); + u4Loop++) { + DBGLOG(INIT, INFO, " Loop=%d aucData=%x\n", + u4Loop, + rAccessEfuseInfoWrite.aucData[u4Loop]); + } + + DBGLOG(INIT, INFO, "Going for e-Fuse\n"); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseWrite, + &rAccessEfuseInfoWrite, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), + FALSE, TRUE, TRUE, &u4BufLen); + } + + } else { + + if (Len == 2) { + memcpy(&ucTemp2, HqaCmdFrame->Data + 2 * 2, 2); + ucTemp2 = ntohs(ucTemp2); + memcpy(uacEEPROMImage + Offset, &ucTemp2, Len); + } else { + for (i = 0 ; i < 8 ; i++) { + memcpy(&ucTemp2, + HqaCmdFrame->Data + 2 * 2 + 2 * i, 2); + ucTemp2 = ntohs(ucTemp2); + memcpy(uacEEPROMImage + Offset + 2 * i, + &ucTemp2, 2); + } + + if (!g_BufferDownload) { + uint16_t u2InitAddr = Offset; + uint32_t j = 0; + uint32_t u4BufLen = 0; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE + *prSetEfuseBufModeInfo = NULL; + struct BIN_CONTENT *pBinContent; + + prSetEfuseBufModeInfo = + ( + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE *) + kalMemAlloc(sizeof( + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE), + VIR_MEM_TYPE); + if (prSetEfuseBufModeInfo == NULL) + return 0; + kalMemZero(prSetEfuseBufModeInfo, + sizeof( + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE)); + + prGlueInfo = + *((struct GLUE_INFO **) + netdev_priv(prNetDev)); + pBinContent = (struct BIN_CONTENT *) + prSetEfuseBufModeInfo->aBinContent; + + for (j = 0 ; j < 16 ; j++) { + pBinContent->u2Addr = u2InitAddr; + pBinContent->ucValue = + uacEEPROMImage[u2InitAddr]; + + pBinContent++; + } + + prSetEfuseBufModeInfo->ucSourceMode = 1; + prSetEfuseBufModeInfo->ucCount = + EFUSE_CONTENT_SIZE; + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEfusBufferMode, + (void *)prSetEfuseBufModeInfo, sizeof( + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE), + FALSE, FALSE, TRUE, &u4BufLen); + + kalMemFree(prSetEfuseBufModeInfo, VIR_MEM_TYPE, + sizeof( + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE)); + + if (Offset == 0x4A0) + g_BufferDownload = TRUE; + } + } + } + +end: + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + Len, i4Ret); + kfree(Buffer); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_CheckEfuseMode(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t Value = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_CheckEfuseMode\n"); + + /* Value: 0:eeprom mode, 1:eFuse mode */ + Value = ntohl(Value); + memcpy(HqaCmdFrame->Data + 2, &(Value), sizeof(Value)); + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetFreeEfuseBlock(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + + int32_t i4Ret = 0, u4FreeBlockCount = 0; + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + struct PARAM_CUSTOM_EFUSE_FREE_BLOCK rEfuseFreeBlock; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo = NULL; +#endif + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(INIT, INFO, "QA_AGENT HQA_GetFreeEfuseBlock\n"); + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + if (prGlueInfo->prAdapter->fgIsSupportGetFreeEfuseBlockCount + == TRUE) { + kalMemSet(&rEfuseFreeBlock, 0, + sizeof(struct PARAM_CUSTOM_EFUSE_FREE_BLOCK)); + + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryEfuseFreeBlock, + &rEfuseFreeBlock, + sizeof(struct PARAM_CUSTOM_EFUSE_FREE_BLOCK), + TRUE, TRUE, TRUE, &u4BufLen); + + u4FreeBlockCount = prGlueInfo->prAdapter->u4FreeBlockNum; + u4FreeBlockCount = ntohl(u4FreeBlockCount); + kalMemCopy(HqaCmdFrame->Data + 2, &u4FreeBlockCount, 4); + } +#endif + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetEfuseBlockNr(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_GetEfuseBlockNr\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_WriteEFuseFromBuffer(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_WriteEFuseFromBuffer\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetTxPower(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Channel = 0, u4Band = 0, u4Ch_Band = 0, + u4TxTargetPower = 0; + /* UINT_32 u4EfuseAddr = 0, u4Power = 0; */ + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + struct PARAM_CUSTOM_GET_TX_POWER rGetTxPower; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo = NULL; +#endif + + memcpy(&u4Channel, HqaCmdFrame->Data + 4 * 0, 4); + u4Channel = ntohl(u4Channel); + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 1, 4); + u4Band = ntohl(u4Band); + memcpy(&u4Ch_Band, HqaCmdFrame->Data + 4 * 2, 4); + u4Ch_Band = ntohl(u4Ch_Band); + + DBGLOG(RFTEST, INFO, "u4Channel : %u, u4Band : %u, u4Ch_Band : %u\n", + u4Channel, u4Band, u4Ch_Band); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (prGlueInfo->prAdapter->fgIsSupportGetTxPower == TRUE) { + kalMemSet(&rGetTxPower, 0, + sizeof(struct PARAM_CUSTOM_GET_TX_POWER)); + + rGetTxPower.ucCenterChannel = u4Channel; + rGetTxPower.ucBand = u4Band; + rGetTxPower.ucDbdcIdx = u4Ch_Band; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryGetTxPower, + &rGetTxPower, + sizeof(struct PARAM_CUSTOM_GET_TX_POWER), + TRUE, TRUE, TRUE, &u4BufLen); + + u4TxTargetPower = prGlueInfo->prAdapter->u4GetTxPower; + u4TxTargetPower = ntohl(u4TxTargetPower); + kalMemCopy(HqaCmdFrame->Data + 6, &u4TxTargetPower, 4); + } + ResponseToQA(HqaCmdFrame, prIwReqData, 10, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetCfgOnOff(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t Type, Enable, Band; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t u4BufLen = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + memcpy(&Type, HqaCmdFrame->Data + 4 * 0, 4); + Type = ntohl(Type); + memcpy(&Enable, HqaCmdFrame->Data + 4 * 1, 4); + Enable = ntohl(Enable); + memcpy(&Band, HqaCmdFrame->Data + 4 * 2, 4); + Band = ntohl(Band); + + DBGLOG(RFTEST, INFO, "Type : %u, Enable : %u, Band : %u\n", + Type, Enable, Band); + + switch (Type) { + case 0: /* TSSI */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TSSI; + break; + case 1: /* DPD */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_DPD_MODE; + break; + default: + DBGLOG(RFTEST, WARN, "Type [%d] not support\n", Type); + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + return i4Ret; + } + + + + rRfATInfo.u4FuncData = 0; + + if (Enable == 0) + rRfATInfo.u4FuncData &= ~BIT(0); + else + rRfATInfo.u4FuncData |= BIT(0); + + if (Band == 0) + rRfATInfo.u4FuncData &= ~BIT(1); + else + rRfATInfo.u4FuncData |= BIT(1); + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetFreqOffset(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4FreqOffset = 0; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct mt66xx_chip_info *prChipInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + if (!prGlueInfo) { + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + return i4Ret; + } + + if (prGlueInfo->prAdapter) + prChipInfo = prGlueInfo->prAdapter->chip_info; + + /* Mobile chips don't support GetFreqOffset */ + if (prChipInfo && prChipInfo->u4ChipIpVersion + == CONNAC_CHIP_IP_VERSION) { + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + return i4Ret; + } + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_GET_FREQ_OFFSET; + rRfATInfo.u4FuncData = 0; + + i4Ret = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, &rRfATInfo, + sizeof(rRfATInfo), TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Ret == 0) { + u4FreqOffset = rRfATInfo.u4FuncData; + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_GetFreqOffset u4FreqOffset = %d\n", + u4FreqOffset); + + u4FreqOffset = ntohl(u4FreqOffset); + memcpy(HqaCmdFrame->Data + 2, &u4FreqOffset, + sizeof(u4FreqOffset)); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_DBDCTXTone(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + int32_t i4BandIdx = 0, i4Control = 0, i4AntIndex = 0, + i4ToneType = 0, i4ToneFreq = 0; + int32_t i4DcOffsetI = 0, i4DcOffsetQ = 0, i4Band = 0, + i4RF_Power = 0, i4Digi_Power = 0; + + memcpy(&i4BandIdx, HqaCmdFrame->Data + 4 * 0, + 4); /* DBDC Band Index : Band0, Band1 */ + i4BandIdx = ntohl(i4BandIdx); + memcpy(&i4Control, HqaCmdFrame->Data + 4 * 1, + 4); /* Control TX Tone Start and Stop */ + i4Control = ntohl(i4Control); + memcpy(&i4AntIndex, HqaCmdFrame->Data + 4 * 2, + 4); /* Select TX Antenna */ + i4AntIndex = ntohl(i4AntIndex); + memcpy(&i4ToneType, HqaCmdFrame->Data + 4 * 3, + 4); /* ToneType : Single or Two */ + i4ToneType = ntohl(i4ToneType); + memcpy(&i4ToneFreq, HqaCmdFrame->Data + 4 * 4, + 4); /* ToneFreq: DC/5M/10M/20M/40M */ + i4ToneFreq = ntohl(i4ToneFreq); + memcpy(&i4DcOffsetI, HqaCmdFrame->Data + 4 * 5, + 4); /* DC Offset I : -512~1535 */ + i4DcOffsetI = ntohl(i4DcOffsetI); + memcpy(&i4DcOffsetQ, HqaCmdFrame->Data + 4 * 6, + 4); /* DC Offset Q : -512~1535 */ + i4DcOffsetQ = ntohl(i4DcOffsetQ); + memcpy(&i4Band, HqaCmdFrame->Data + 4 * 7, + 4); /* Band : 2.4G/5G */ + i4Band = ntohl(i4Band); + memcpy(&i4RF_Power, HqaCmdFrame->Data + 4 * 8, + 4); /* RF_Power: (1db) 0~15 */ + i4RF_Power = ntohl(i4RF_Power); + memcpy(&i4Digi_Power, HqaCmdFrame->Data + 4 * 9, + 4); /* Digi_Power: (0.25db) -32~31 */ + i4Digi_Power = ntohl(i4Digi_Power); + + DBGLOG(RFTEST, INFO, "BandIdx = 0x%08x\n", i4BandIdx); + DBGLOG(RFTEST, INFO, "Control = 0x%08x\n", i4Control); + DBGLOG(RFTEST, INFO, "AntIndex = 0x%08x\n", i4AntIndex); + DBGLOG(RFTEST, INFO, "ToneType = 0x%08x\n", i4ToneType); + DBGLOG(RFTEST, INFO, "ToneFreq = 0x%08x\n", i4ToneFreq); + DBGLOG(RFTEST, INFO, "DcOffsetI = 0x%08x\n", i4DcOffsetI); + DBGLOG(RFTEST, INFO, "DcOffsetQ = 0x%08x\n", i4DcOffsetQ); + DBGLOG(RFTEST, INFO, "Band = 0x%08x\n", i4Band); + DBGLOG(RFTEST, INFO, "RF_Power = 0x%08x\n", i4RF_Power); + DBGLOG(RFTEST, INFO, "Digi_Power = 0x%08x\n", i4Digi_Power); + + /* + * Select TX Antenna + * RF_Power: (1db) 0~15 + * Digi_Power: (0.25db) -32~31 + */ + MT_ATESetDBDCTxTonePower(prNetDev, i4AntIndex, i4RF_Power, + i4Digi_Power); + + /* DBDC Band Index : Band0, Band1 */ + MT_ATESetDBDCBandIndex(prNetDev, i4BandIdx); + + if (i4Control) { + /* Band : 2.4G/5G */ + MT_ATESetBand(prNetDev, i4Band); + + /* ToneType : Single or Two */ + MT_ATESetTxToneType(prNetDev, i4ToneType); + + /* ToneFreq: DC/5M/10M/20M/40M */ + MT_ATESetTxToneBW(prNetDev, i4ToneFreq); + + /* DC Offset I, DC Offset Q */ + MT_ATESetTxToneDCOffset(prNetDev, i4DcOffsetI, i4DcOffsetQ); + + /* Control TX Tone Start and Stop */ + MT_ATEDBDCTxTone(prNetDev, i4Control); + } else { + /* Control TX Tone Start and Stop */ + MT_ATEDBDCTxTone(prNetDev, i4Control); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static uint8_t _whPhyGetPrimChOffset(uint32_t u4BW, + uint32_t u4Pri_Ch, + uint32_t u4Cen_ch) +{ + uint8_t ucPrimChOffset = 0; + + /* BW Mapping in QA Tool + * 0: BW20 + * 1: BW40 + * 2: BW80 + * 3: BW10 + * 4: BW5 + * 5: BW160C + * 6: BW160NC + */ + u4Pri_Ch &= 0xFF; + u4Cen_ch &= 0xFF; + switch (u4BW) { + case 1: + ucPrimChOffset = (u4Pri_Ch < u4Cen_ch) ? 0 : 1; + break; + case 2: + ucPrimChOffset = (((u4Pri_Ch - u4Cen_ch) + 6) >> 2); + break; + default: + break; + } + return ucPrimChOffset; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_DBDCContinuousTX(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Band = 0, u4Control = 0, u4AntMask = 0, + u4Phymode = 0, u4BW = 0; + uint32_t u4Pri_Ch = 0, u4Rate = 0, u4Central_Ch = 0, + u4TxfdMode = 0, u4Freq = 0; + uint32_t u4BufLen = 0; + uint8_t ucPriChOffset = 0; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 0, 4); + u4Band = ntohl(u4Band); + memcpy(&u4Control, HqaCmdFrame->Data + 4 * 1, 4); + u4Control = ntohl(u4Control); + memcpy(&u4AntMask, HqaCmdFrame->Data + 4 * 2, 4); + u4AntMask = ntohl(u4AntMask); + memcpy(&u4Phymode, HqaCmdFrame->Data + 4 * 3, 4); + u4Phymode = ntohl(u4Phymode); + memcpy(&u4BW, HqaCmdFrame->Data + 4 * 4, 4); + u4BW = ntohl(u4BW); + memcpy(&u4Pri_Ch, HqaCmdFrame->Data + 4 * 5, 4); + u4Pri_Ch = ntohl(u4Pri_Ch); + memcpy(&u4Rate, HqaCmdFrame->Data + 4 * 6, 4); + u4Rate = ntohl(u4Rate); + memcpy(&u4Central_Ch, HqaCmdFrame->Data + 4 * 7, 4); + u4Central_Ch = ntohl(u4Central_Ch); + memcpy(&u4TxfdMode, HqaCmdFrame->Data + 4 * 8, 4); + u4TxfdMode = ntohl(u4TxfdMode); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_DBDCContinuousTX u4Band : %d\n", + u4Band); /* ok */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_DBDCContinuousTX u4Control : %d\n", + u4Control); /* ok */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_DBDCContinuousTX u4AntMask : %d\n", + u4AntMask); /* ok */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_DBDCContinuousTX u4Phymode : %d\n", + u4Phymode); /* ok */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_DBDCContinuousTX u4BW : %d\n", u4BW); /* ok */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_DBDCContinuousTX u4Pri_Ch : %d\n", + u4Pri_Ch); /* ok */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_DBDCContinuousTX u4Rate : %d\n", + u4Rate); /* ok */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_DBDCContinuousTX u4Central_Ch : %d\n", + u4Central_Ch); /* ok */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_DBDCContinuousTX u4TxfdMode : %d\n", + u4TxfdMode); /* ok */ + + if (u4Control) { + MT_ATESetDBDCBandIndex(prNetDev, u4Band); + u4Freq = nicChannelNum2Freq(u4Central_Ch); + MT_ATESetChannel(prNetDev, 0, u4Freq); + ucPriChOffset = _whPhyGetPrimChOffset(u4BW, + u4Pri_Ch, + u4Central_Ch); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_DBDCContinuousTX ucPriChOffset : %d\n", + ucPriChOffset); /* ok */ + MT_ATEPrimarySetting(prNetDev, ucPriChOffset); + + if (u4Phymode == 1) { + u4Phymode = 0; + u4Rate += 4; + } else if ((u4Phymode == 0) && + ((u4Rate == 9) || (u4Rate == 10) || (u4Rate == 11))) + u4Phymode = 1; + MT_ATESetPreamble(prNetDev, u4Phymode); + + if (u4Phymode == 0) { + u4Rate |= 0x00000000; + + DBGLOG(RFTEST, INFO, + "QA_AGENT CCK/OFDM (normal preamble) rate : %d\n", + u4Rate); + + MT_ATESetRate(prNetDev, u4Rate); + } else if (u4Phymode == 1) { + if (u4Rate == 9) + u4Rate = 1; + else if (u4Rate == 10) + u4Rate = 2; + else if (u4Rate == 11) + u4Rate = 3; + u4Rate |= 0x00000000; + + DBGLOG(RFTEST, INFO, + "QA_AGENT CCK (short preamble) rate : %d\n", + u4Rate); + + MT_ATESetRate(prNetDev, u4Rate); + } else if (u4Phymode >= 2 && u4Phymode <= 4) { + u4Rate |= 0x80000000; + + DBGLOG(RFTEST, INFO, "QA_AGENT HT/VHT rate : %d\n", + u4Rate); + + MT_ATESetRate(prNetDev, u4Rate); + } + + MT_ATESetSystemBW(prNetDev, u4BW); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_CW_MODE; + rRfATInfo.u4FuncData = u4TxfdMode; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ANTMASK; + rRfATInfo.u4FuncData = u4AntMask; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_CW; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + } else { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_STOPTEST; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetRXFilterPktLen(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Band = 0, u4Control = 0, u4RxPktlen = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t u4BufLen = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 0, 4); + u4Band = ntohl(u4Band); + memcpy(&u4Control, HqaCmdFrame->Data + 4 * 1, 4); + u4Control = ntohl(u4Control); + memcpy(&u4RxPktlen, HqaCmdFrame->Data + 4 * 2, 4); + u4RxPktlen = ntohl(u4RxPktlen); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetRXFilterPktLen Band : %d\n", u4Band); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetRXFilterPktLen Control : %d\n", u4Control); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetRXFilterPktLen RxPktlen : %d\n", + u4RxPktlen); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_RX_FILTER_PKT_LEN; + rRfATInfo.u4FuncData = (uint32_t) (u4RxPktlen & BITS(0, + 23)); + rRfATInfo.u4FuncData |= (uint32_t) (u4Band << 24); + + if (u4Control == 1) + rRfATInfo.u4FuncData |= BIT(30); + else + rRfATInfo.u4FuncData &= ~BIT(30); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetRXFilterPktLen rRfATInfo.u4FuncData : 0x%08x\n", + rRfATInfo.u4FuncData); + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetTXInfo(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + uint32_t u4Txed_band0 = 0; + uint32_t u4Txed_band1 = 0; + int32_t i4Status; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_GetTXInfo\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_TXED_COUNT; + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, &rRfATInfo, + sizeof(rRfATInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + u4Txed_band0 = rRfATInfo.u4FuncData; + + DBGLOG(RFTEST, INFO, + "QA_AGENT u4Txed_band0 packet count = %d\n", + u4Txed_band0); + + u4Txed_band0 = ntohl(u4Txed_band0); + memcpy(HqaCmdFrame->Data + 2, &u4Txed_band0, + sizeof(u4Txed_band0)); + } + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_TXED_COUNT; + rRfATInfo.u4FuncIndex |= BIT(8); + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, &rRfATInfo, + sizeof(rRfATInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + u4Txed_band1 = rRfATInfo.u4FuncData; + + DBGLOG(RFTEST, INFO, + "QA_AGENT u4Txed_band1 packet count = %d\n", + u4Txed_band1); + + u4Txed_band1 = ntohl(u4Txed_band1); + memcpy(HqaCmdFrame->Data + 2 + 4, &u4Txed_band1, + sizeof(u4Txed_band1)); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, + 2 + sizeof(u4Txed_band0) + sizeof(u4Txed_band1), i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetCfgOnOff(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_GetCfgOnOff\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_CMD_SET3[] = { + /* cmd id start from 0x1300 */ + HQA_MacBbpRegRead, /* 0x1300 */ + HQA_MacBbpRegWrite, /* 0x1301 */ + HQA_MACBbpRegBulkRead, /* 0x1302 */ + HQA_RfRegBulkRead, /* 0x1303 */ + HQA_RfRegBulkWrite, /* 0x1304 */ + HQA_ReadEEPROM, /* 0x1305 */ + HQA_WriteEEPROM, /* 0x1306 */ + HQA_ReadBulkEEPROM, /* 0x1307 */ + HQA_WriteBulkEEPROM, /* 0x1308 */ + HQA_CheckEfuseMode, /* 0x1309 */ + HQA_GetFreeEfuseBlock, /* 0x130A */ + HQA_GetEfuseBlockNr, /* 0x130B */ + HQA_WriteEFuseFromBuffer, /* 0x130C */ + HQA_GetTxPower, /* 0x130D */ + HQA_SetCfgOnOff, /* 0x130E */ + HQA_GetFreqOffset, /* 0x130F */ + HQA_DBDCTXTone, /* 0x1310 */ + HQA_DBDCContinuousTX, /* 0x1311 */ + HQA_SetRXFilterPktLen, /* 0x1312 */ + HQA_GetTXInfo, /* 0x1313 */ + HQA_GetCfgOnOff, /* 0x1314 */ +}; + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_ReadTempReferenceValue( + struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_ReadTempReferenceValue\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Get Thermal Value. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetThermalValue(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + uint32_t u4Value; + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_TEMP_SENSOR; + rRfATInfo.u4FuncData = 0; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, &rRfATInfo, + sizeof(rRfATInfo), TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + u4Value = rRfATInfo.u4FuncData; + u4Value = u4Value >> 16; + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_GetThermalValue Value = %d\n", u4Value); + + u4Value = ntohl(u4Value); + memcpy(HqaCmdFrame->Data + 2, &u4Value, 4); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetSideBandOption(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetSideBandOption\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_CMD_SET4[] = { + /* cmd id start from 0x1400 */ + HQA_ReadTempReferenceValue, /* 0x1400 */ + HQA_GetThermalValue, /* 0x1401 */ + HQA_SetSideBandOption, /* 0x1402 */ +}; + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetFWInfo(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_GetFWInfo\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_StartContinousTx(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StartContinousTx\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetSTBC(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetSTBC\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set short GI. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetShortGI(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4ShortGi; + + memcpy(&u4ShortGi, HqaCmdFrame->Data, 4); + u4ShortGi = ntohl(u4ShortGi); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetShortGI u4ShortGi = %d\n", u4ShortGi); + + i4Ret = MT_ATESetTxGi(prNetDev, u4ShortGi); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetDPD(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetDPD\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Get Rx Statistics. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetRxStatisticsAll(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4BufLen = 0; + struct PARAM_CUSTOM_ACCESS_RX_STAT rRxStatisticsTest; + + /* memset(&g_HqaRxStat, 0, sizeof(PARAM_RX_STAT_T)); */ + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_GetRxStatisticsAll\n"); + + rRxStatisticsTest.u4SeqNum = u4RxStatSeqNum; + rRxStatisticsTest.u4TotalNum = HQA_RX_STATISTIC_NUM + 6; + + i4Ret = kalIoctl(prGlueInfo, + wlanoidQueryRxStatistics, + &rRxStatisticsTest, sizeof(rRxStatisticsTest), + TRUE, TRUE, TRUE, &u4BufLen); + + /* ASSERT(rRxStatisticsTest.u4SeqNum == u4RxStatSeqNum); */ + + u4RxStatSeqNum++; + + memcpy(HqaCmdFrame->Data + 2, &(g_HqaRxStat), + sizeof(struct PARAM_RX_STAT)); + ResponseToQA(HqaCmdFrame, prIwReqData, + (2 + sizeof(struct PARAM_RX_STAT)), i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_StartContiTxTone(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StartContiTxTone\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_StopContiTxTone(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StopContiTxTone\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_CalibrationTestMode(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Mode = 0; + uint32_t u4IcapLen = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_CalibrationTestMode\n"); + + memcpy(&u4Mode, HqaCmdFrame->Data + 4 * 0, 4); + u4Mode = ntohl(u4Mode); + memcpy(&u4IcapLen, HqaCmdFrame->Data + 4 * 1, 4); + u4IcapLen = ntohl(u4IcapLen); + + if (u4Mode == 2) + i4Ret = MT_ICAPStart(prNetDev, "ICAPSTART"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_DoCalibrationTestItem(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Status = 0; + uint32_t u4Item = 0; + uint32_t u4Band_idx = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + struct ADAPTER *prAdapter; + uint32_t u4BufLen = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + memcpy(&u4Item, HqaCmdFrame->Data, 4); + u4Item = ntohl(u4Item); + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_DoCalibrationTestItem item : 0x%08x\n", + u4Item); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_DoCalibrationTestItem band_idx : %d\n", + u4Band_idx); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_RECAL_CAL_STEP; + rRfATInfo.u4FuncData = u4Item; + + kalMemSet((void *)&prAdapter->rReCalInfo, + 0, + sizeof(struct RECAL_INFO_T)); + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_eFusePhysicalWrite(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_eFusePhysicalWrite\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_eFusePhysicalRead(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_eFusePhysicalRead\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_eFuseLogicalRead(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_eFuseLogicalRead\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_eFuseLogicalWrite(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_eFuseLogicalWrite\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_TMRSetting(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Setting; + uint32_t u4Version; + uint32_t u4MPThres; + uint32_t u4MPIter; + + memcpy(&u4Setting, HqaCmdFrame->Data + 4 * 0, 4); + u4Setting = ntohl(u4Setting); + memcpy(&u4Version, HqaCmdFrame->Data + 4 * 1, 4); + u4Version = ntohl(u4Version); + memcpy(&u4MPThres, HqaCmdFrame->Data + 4 * 2, 4); + u4MPThres = ntohl(u4MPThres); + memcpy(&u4MPIter, HqaCmdFrame->Data + 4 * 3, 4); + u4MPIter = ntohl(u4MPIter); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_TMRSetting u4Setting : %d\n", u4Setting); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_TMRSetting u4Version : %d\n", u4Version); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_TMRSetting u4MPThres : %d\n", u4MPThres); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_TMRSetting u4MPIter : %d\n", u4MPIter); + + i4Ret = MT_ATE_TMRSetting(prNetDev, u4Setting, u4Version, + u4MPThres, u4MPIter); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetRxSNR(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_GetRxSNR\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_WriteBufferDone(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + /* UINT_16 u2InitAddr = 0x000; */ + uint32_t Value; + /* UINT_32 i = 0, j = 0; + * UINT_32 u4BufLen = 0; + */ + /* WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; */ + struct GLUE_INFO *prGlueInfo = NULL; + /* PARAM_CUSTOM_EFUSE_BUFFER_MODE_T rSetEfuseBufModeInfo; */ + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + memcpy(&Value, HqaCmdFrame->Data + 4 * 0, 4); + Value = ntohl(Value); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_WriteBufferDone Value : %d\n", Value); + + u4EepromMode = Value; + +#if 0 + for (i = 0 ; i < MAX_EEPROM_BUFFER_SIZE / 16 ; i++) { + for (j = 0 ; j < 16 ; j++) { + rSetEfuseBufModeInfo.aBinContent[j].u2Addr = u2InitAddr; + rSetEfuseBufModeInfo.aBinContent[j].ucValue = + uacEEPROMImage[u2InitAddr]; + DBGLOG(RFTEST, INFO, "u2Addr = %x\n", + rSetEfuseBufModeInfo.aBinContent[j].u2Addr); + DBGLOG(RFTEST, INFO, "ucValue = %x\n", + rSetEfuseBufModeInfo.aBinContent[j].ucValue); + u2InitAddr += 1; + } + + rSetEfuseBufModeInfo.ucSourceMode = 1; + rSetEfuseBufModeInfo.ucCount = EFUSE_CONTENT_SIZE; + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEfusBufferMode, + &rSetEfuseBufModeInfo, + sizeof(struct PARAM_CUSTOM_EFUSE_BUFFER_MODE), + FALSE, FALSE, TRUE, &u4BufLen); + } +#endif + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_FFT(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_FFT\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetTxTonePower(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetTxTonePower\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetChipID(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4ChipId; + struct mt66xx_chip_info *prChipInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + /* UINT_32 u4BufLen = 0; + * PARAM_CUSTOM_MCR_RW_STRUCT_T rMcrInfo; + */ + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + prChipInfo = prAdapter->chip_info; + g_u4Chip_ID = prChipInfo->chip_id; + DBGLOG(RFTEST, INFO, + "QA_AGENT IPVer= 0x%08x, Adie = 0x%08x\n", + prChipInfo->u4ChipIpVersion, + prChipInfo->u2ADieChipVersion); + + /* Check A-Die information for mobile solution */ + switch (prChipInfo->u2ADieChipVersion) { + case 0x6631: + u4ChipId = 0x00066310; /* use 66310 to diff from gen3 6631 */ + break; + case 0x6635: + u4ChipId = 0x0006635; /* return A die directly */ + break; + default: + u4ChipId = g_u4Chip_ID; + break; + } + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_GetChipID ChipId = 0x%08x\n", u4ChipId); + + u4ChipId = ntohl(u4ChipId); + memcpy(HqaCmdFrame->Data + 2, &u4ChipId, 4); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_MPSSetSeqData(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t *mps_setting = NULL; + uint32_t u4Band_idx = 0; + uint32_t u4Offset = 0; + uint32_t u4Len = 0; + uint32_t i = 0; + uint32_t u4Value = 0; + uint32_t u4Mode = 0; + uint32_t u4TxPath = 0; + uint32_t u4Mcs = 0; + + u4Len = ntohs(HqaCmdFrame->Length) / sizeof(uint32_t) - 1; + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetSeqData u4Len : %d\n", u4Len); + + mps_setting = kmalloc(sizeof(uint32_t) * (u4Len), + GFP_KERNEL); + ASSERT(mps_setting); + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetSeqData u4Band_idx : %d\n", u4Band_idx); + + for (i = 0 ; i < u4Len ; i++) { + u4Offset = 4 + 4 * i; + /* Reserved at least 4 byte availbale data */ + if (u4Offset + 4 > sizeof(HqaCmdFrame->Data)) + break; + memcpy(&u4Value, HqaCmdFrame->Data + 4 + 4 * i, 4); + u4Value = ntohl(u4Value); + + u4Mode = (u4Value & BITS(24, 27)) >> 24; + u4TxPath = (u4Value & BITS(8, 23)) >> 8; + u4Mcs = (u4Value & BITS(0, 7)); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetSeqData mps_setting Case %d (Mode : %d / TX Path : %d / MCS : %d)\n" + , i, u4Mode, u4TxPath, u4Mcs); + + if (u4Mode == 1) { + u4Mode = 0; + u4Mcs += 4; + } else if ((u4Mode == 0) && ((u4Mcs == 9) || (u4Mcs == 10) + || (u4Mcs == 11))) + u4Mode = 1; + + if (u4Mode == 0) { + u4Mcs |= 0x00000000; + + DBGLOG(RFTEST, INFO, + "QA_AGENT CCK/OFDM (normal preamble) rate : %d\n", + u4Mcs); + } else if (u4Mode == 1) { + if (u4Mcs == 9) + u4Mcs = 1; + else if (u4Mcs == 10) + u4Mcs = 2; + else if (u4Mcs == 11) + u4Mcs = 3; + u4Mcs |= 0x00000000; + + DBGLOG(RFTEST, INFO, + "QA_AGENT CCK (short preamble) rate : %d\n", + u4Mcs); + } else if (u4Mode >= 2 && u4Mode <= 4) { + u4Mcs |= 0x80000000; + + DBGLOG(RFTEST, INFO, "QA_AGENT HT/VHT rate : %d\n", + u4Mcs); + } + + mps_setting[i] = (u4Mcs) | (u4TxPath << 8) | (u4Mode << 24); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetSeqData mps_setting Case %d (Mode : %d / TX Path : %d / MCS : %d)\n", + i, + (int)((mps_setting[i] & BITS(24, 27)) >> 24), + (int)((mps_setting[i] & BITS(8, 23)) >> 8), + (int)((mps_setting[i] & BITS(0, 7)))); + + } + + i4Ret = MT_ATEMPSSetSeqData(prNetDev, u4Len, mps_setting, + u4Band_idx); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(mps_setting); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_MPSSetPayloadLength(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t *mps_setting = NULL; + uint32_t u4Band_idx = 0; + uint32_t u4Offset = 0; + uint32_t u4Len = 0; + uint32_t i = 0; + uint32_t u4Value = 0; + + u4Len = ntohs(HqaCmdFrame->Length) / sizeof(uint32_t) - 1; + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetPayloadLength u4Len : %d\n", u4Len); + + mps_setting = kmalloc(sizeof(uint32_t) * (u4Len), + GFP_KERNEL); + ASSERT(mps_setting); + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetPayloadLength u4Band_idx : %d\n", + u4Band_idx); + + for (i = 0 ; i < u4Len ; i++) { + u4Offset = 4 + 4 * i; + /* Reserved at least 4 byte availbale data */ + if (u4Offset + 4 > sizeof(HqaCmdFrame->Data)) + break; + memcpy(&u4Value, HqaCmdFrame->Data + 4 + 4 * i, 4); + mps_setting[i] = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetPayloadLength mps_setting Case %d (Payload Length : %d)\n", + i, mps_setting[i]); + } + + i4Ret = MT_ATEMPSSetPayloadLength(prNetDev, u4Len, + mps_setting, u4Band_idx); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(mps_setting); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_MPSSetPacketCount(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t *mps_setting = NULL; + uint32_t u4Band_idx = 0; + uint32_t u4Offset = 0; + uint32_t u4Len = 0; + uint32_t i = 0; + uint32_t u4Value = 0; + + u4Len = ntohs(HqaCmdFrame->Length) / sizeof(uint32_t) - 1; + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetPacketCount u4Len : %d\n", u4Len); + + mps_setting = kmalloc(sizeof(uint32_t) * (u4Len), + GFP_KERNEL); + ASSERT(mps_setting); + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetPacketCount u4Band_idx : %d\n", + u4Band_idx); + + for (i = 0 ; i < u4Len ; i++) { + u4Offset = 4 + 4 * i; + /* Reserved at least 4 byte availbale data */ + if (u4Offset + 4 > sizeof(HqaCmdFrame->Data)) + break; + memcpy(&u4Value, HqaCmdFrame->Data + 4 + 4 * i, 4); + mps_setting[i] = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetPacketCount mps_setting Case %d (Packet Count : %d)\n", + i, mps_setting[i]); + } + + i4Ret = MT_ATEMPSSetPacketCount(prNetDev, u4Len, + mps_setting, u4Band_idx); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(mps_setting); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_MPSSetPowerGain(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t *mps_setting = NULL; + uint32_t u4Band_idx = 0; + uint32_t u4Offset = 0; + uint32_t u4Len = 0; + uint32_t i = 0; + uint32_t u4Value = 0; + + u4Len = ntohs(HqaCmdFrame->Length) / sizeof(uint32_t) - 1; + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetPowerGain u4Len : %d\n", u4Len); + + mps_setting = kmalloc(sizeof(uint32_t) * (u4Len), + GFP_KERNEL); + ASSERT(mps_setting); + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetPowerGain u4Band_idx : %d\n", + u4Band_idx); + + for (i = 0 ; i < u4Len ; i++) { + u4Offset = 4 + 4 * i; + /* Reserved at least 4 byte availbale data */ + if (u4Offset + 4 > sizeof(HqaCmdFrame->Data)) + break; + memcpy(&u4Value, HqaCmdFrame->Data + 4 + 4 * i, 4); + mps_setting[i] = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetPowerGain mps_setting Case %d (Power : %d)\n", + i, mps_setting[i]); + } + + i4Ret = MT_ATEMPSSetPowerGain(prNetDev, u4Len, mps_setting, + u4Band_idx); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(mps_setting); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_MPSStart(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Band_idx = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MPSStart\n"); + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + MT_ATEStartTX(prNetDev, "TXFRAME"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_MPSStop(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Band_idx = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MPSStop\n"); + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + /* To Do : MPS Stop for Specific Band. */ + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief internal function used by HQA_GetRxStatisticsAllV2. + */ +/*----------------------------------------------------------------------------*/ +int32_t hqa_genStatBandReport( + u_int8_t band_idx, + u_int8_t blk_idx, + struct hqa_rx_stat_band_format *rx_st_band) +{ + + int32_t ret = 0; + + if (band_idx == HQA_M_BAND_0) { + rx_st_band->mac_rx_fcs_err_cnt = + ntohl(g_HqaRxStat.MAC_FCS_Err) + + ntohl(g_backup_band0_info.mac_rx_fcs_err_cnt); + rx_st_band->mac_rx_mdrdy_cnt = + ntohl(g_HqaRxStat.MAC_Mdrdy) + + ntohl(g_backup_band0_info.mac_rx_mdrdy_cnt); + rx_st_band->mac_rx_len_mismatch = + ntohl(g_HqaRxStat.LengthMismatchCount_B0) + + ntohl(g_backup_band0_info.mac_rx_len_mismatch); + rx_st_band->mac_rx_fcs_ok_cnt = 0; + rx_st_band->phy_rx_fcs_err_cnt_cck = + ntohl(g_HqaRxStat.FCSErr_CCK); + rx_st_band->phy_rx_fcs_err_cnt_ofdm = + ntohl(g_HqaRxStat.FCSErr_OFDM); + rx_st_band->phy_rx_pd_cck = + ntohl(g_HqaRxStat.CCK_PD); + rx_st_band->phy_rx_pd_ofdm = + ntohl(g_HqaRxStat.OFDM_PD); + rx_st_band->phy_rx_sig_err_cck = + ntohl(g_HqaRxStat.CCK_SIG_Err); + rx_st_band->phy_rx_sfd_err_cck = + ntohl(g_HqaRxStat.CCK_SFD_Err); + rx_st_band->phy_rx_sig_err_ofdm = + ntohl(g_HqaRxStat.OFDM_SIG_Err); + rx_st_band->phy_rx_tag_err_ofdm = + ntohl(g_HqaRxStat.OFDM_TAG_Err); + rx_st_band->phy_rx_mdrdy_cnt_cck = + ntohl(g_HqaRxStat.PhyMdrdyCCK); + rx_st_band->phy_rx_mdrdy_cnt_ofdm = + ntohl(g_HqaRxStat.PhyMdrdyOFDM); + + /* Backup Band1 info */ + g_backup_band1_info.mac_rx_fcs_err_cnt += + g_HqaRxStat.MAC_FCS_Err1; + + g_backup_band1_info.mac_rx_mdrdy_cnt += + g_HqaRxStat.MAC_Mdrdy1; + + g_backup_band1_info.mac_rx_len_mismatch += + g_HqaRxStat.LengthMismatchCount_B1; + + /* Reset Band0 backup info */ + kalMemZero(&g_backup_band0_info, + sizeof(struct hqa_rx_stat_band_format)); + } else { + rx_st_band->mac_rx_fcs_err_cnt = + ntohl( + g_HqaRxStat.MAC_FCS_Err1) + + ntohl( + g_backup_band1_info.mac_rx_fcs_err_cnt); + rx_st_band->mac_rx_mdrdy_cnt = + ntohl( + g_HqaRxStat.MAC_Mdrdy1) + + ntohl( + g_backup_band1_info.mac_rx_mdrdy_cnt); + rx_st_band->mac_rx_len_mismatch = + ntohl( + g_HqaRxStat.LengthMismatchCount_B1) + + ntohl( + g_backup_band1_info.mac_rx_len_mismatch); + rx_st_band->mac_rx_fcs_ok_cnt = 0; + rx_st_band->phy_rx_fcs_err_cnt_cck = + ntohl( + g_HqaRxStat.CCK_FCS_Err_Band1); + rx_st_band->phy_rx_fcs_err_cnt_ofdm = + ntohl( + g_HqaRxStat.OFDM_FCS_Err_Band1); + rx_st_band->phy_rx_pd_cck = + ntohl( + g_HqaRxStat.CCK_PD_Band1); + rx_st_band->phy_rx_pd_ofdm = + ntohl( + g_HqaRxStat.OFDM_PD_Band1); + rx_st_band->phy_rx_sig_err_cck = + ntohl( + g_HqaRxStat.CCK_SIG_Err_Band1); + rx_st_band->phy_rx_sfd_err_cck = + ntohl( + g_HqaRxStat.CCK_SFD_Err_Band1); + rx_st_band->phy_rx_sig_err_ofdm = + ntohl( + g_HqaRxStat.OFDM_SIG_Err_Band1); + rx_st_band->phy_rx_tag_err_ofdm = + ntohl( + g_HqaRxStat.OFDM_TAG_Err_Band1); + rx_st_band->phy_rx_mdrdy_cnt_cck = + ntohl( + g_HqaRxStat.PHY_CCK_MDRDY_Band1); + rx_st_band->phy_rx_mdrdy_cnt_ofdm = + ntohl( + g_HqaRxStat.PHY_OFDM_MDRDY_Band1); + + + /* Backup Band0 info */ + g_backup_band0_info.mac_rx_fcs_err_cnt += + g_HqaRxStat.MAC_FCS_Err; + + g_backup_band0_info.mac_rx_mdrdy_cnt += + g_HqaRxStat.MAC_Mdrdy; + + g_backup_band0_info.mac_rx_len_mismatch += + g_HqaRxStat.LengthMismatchCount_B0; + + /* Reset Band1 backup info */ + kalMemZero(&g_backup_band1_info, + sizeof(struct hqa_rx_stat_band_format)); + } + + return ret; +} + +int32_t hqa_genStatPathReport( + u_int8_t band_idx, + u_int8_t blk_idx, + struct hqa_rx_stat_path_format *rx_st_path) +{ + int32_t ret = 0; + + switch (blk_idx) { + case HQA_ANT_WF0: + rx_st_path->rcpi = + ntohl(g_HqaRxStat.RCPI0); + rx_st_path->rssi = + ntohl(g_HqaRxStat.RSSI0); + rx_st_path->fagc_ib_rssi = + ntohl(g_HqaRxStat.FAGCRssiIBR0); + rx_st_path->fagc_wb_rssi = + ntohl(g_HqaRxStat.FAGCRssiWBR0); + rx_st_path->inst_ib_rssi = + ntohl(g_HqaRxStat.InstRssiIBR0); + rx_st_path->inst_wb_rssi = + ntohl(g_HqaRxStat.InstRssiWBR0); + break; + case HQA_ANT_WF1: + rx_st_path->rcpi = + ntohl(g_HqaRxStat.RCPI1); + rx_st_path->rssi = + ntohl(g_HqaRxStat.RSSI1); + rx_st_path->fagc_ib_rssi = + ntohl(g_HqaRxStat.FAGCRssiIBR1); + rx_st_path->fagc_wb_rssi = + ntohl(g_HqaRxStat.FAGCRssiWBR1); + rx_st_path->inst_ib_rssi = + ntohl(g_HqaRxStat.InstRssiIBR1); + rx_st_path->inst_wb_rssi = + ntohl(g_HqaRxStat.InstRssiWBR1); + break; + + default: + ret = WLAN_STATUS_INVALID_DATA; + break; + } + + return ret; +} + +int32_t hqa_genStatUserReport( + u_int8_t band_idx, + u_int8_t blk_idx, + struct hqa_rx_stat_user_format *rx_st_user) +{ + int32_t ret = WLAN_STATUS_SUCCESS; + + rx_st_user->freq_offset_from_rx = + ntohl(g_HqaRxStat.FreqOffsetFromRX); + if (band_idx == HQA_M_BAND_0) + rx_st_user->snr = ntohl(g_HqaRxStat.SNR0); + else + rx_st_user->snr = ntohl(g_HqaRxStat.SNR1); + + rx_st_user->fcs_error_cnt = + ntohl(g_HqaRxStat.MAC_FCS_Err); + + return ret; +} + +int32_t hqa_genStatCommReport( + u_int8_t band_idx, + u_int8_t blk_idx, + struct hqa_rx_stat_comm_format *rx_st_comm) +{ + int32_t ret = WLAN_STATUS_SUCCESS; + + rx_st_comm->rx_fifo_full = + ntohl(g_HqaRxStat.OutOfResource); + rx_st_comm->aci_hit_low = + ntohl(g_HqaRxStat.ACIHitLower); + rx_st_comm->aci_hit_high = + ntohl(g_HqaRxStat.ACIHitUpper); + rx_st_comm->mu_pkt_count = + ntohl(g_HqaRxStat.MRURxCount); + rx_st_comm->sig_mcs = + ntohl(g_HqaRxStat.SIGMCS); + rx_st_comm->sinr = + ntohl(g_HqaRxStat.SINR); + if (band_idx == HQA_M_BAND_0) { + rx_st_comm->driver_rx_count = + ntohl(g_HqaRxStat.DriverRxCount); + } else { + rx_st_comm->driver_rx_count = + ntohl(g_HqaRxStat.DriverRxCount1); + } + return ret; +} + + +int32_t hqa_getRxStatisticsByType( + struct GLUE_INFO *prGlueInfo, + u_int8_t band_idx, + u_int8_t blk_idx, + u_int8_t test_rx_stat_cat, + struct hqa_rx_stat_u *st) +{ + int32_t i4Ret = 0; + uint32_t u4BufLen = 0; + struct PARAM_CUSTOM_ACCESS_RX_STAT rx_stat_test; + + rx_stat_test.u4SeqNum = 0; + rx_stat_test.u4TotalNum = 72; + + /* only TEST_RX_STAT_BAND send query command to FW. */ + if (test_rx_stat_cat == HQA_RX_STAT_BAND) { + i4Ret = kalIoctl(prGlueInfo, + wlanoidQueryRxStatistics, + &rx_stat_test, sizeof(rx_stat_test), + TRUE, TRUE, TRUE, &u4BufLen); + } + + switch (test_rx_stat_cat) { + case HQA_RX_STAT_BAND: + i4Ret = hqa_genStatBandReport( + band_idx, + blk_idx, + &(st->u.rx_st_band)); + break; + case HQA_RX_STAT_PATH: + i4Ret = hqa_genStatPathReport( + band_idx, + blk_idx, + &(st->u.rx_st_path)); + break; + case HQA_RX_STAT_USER: + i4Ret = hqa_genStatUserReport( + band_idx, + blk_idx, + &(st->u.rx_st_user)); + break; + case HQA_RX_STAT_COMM: + i4Ret = hqa_genStatCommReport( + band_idx, + blk_idx, + &(st->u.rx_st_comm)); + break; + default: + break; + } + + if (i4Ret) + DBGLOG(RFTEST, INFO, "err=0x%08x\n.", i4Ret); + + return i4Ret; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Get Rx Statistics. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetRxStatisticsAllV2(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + struct GLUE_INFO *prGlueInfo = NULL; + u_int32_t buf_size = 0; + u_int32_t type_mask = 0, band_idx = 0, type_num = 0, length; + u_int32_t blk_idx = 0, type_idx = 0, buf = 0; + u_int32_t dw_idx = 0, dw_cnt = 0; + u_int32_t *ptr2 = NULL; + struct hqa_rx_stat_u *rx_stat = NULL; + u_int8_t path[HQA_ANT_NUM] = {0}; + u_int8_t path_len = 0; + u_int8_t *ptr = NULL; + u_int8_t i = 0; + + struct hqa_rx_stat_resp_field st_form[HQA_SERV_RX_STAT_TYPE_NUM] = { + {HQA_SERV_RX_STAT_TYPE_BAND, 0, 0, 0, + sizeof(struct hqa_rx_stat_band_format)}, + {HQA_SERV_RX_STAT_TYPE_PATH, 0, 0, 0, + sizeof(struct hqa_rx_stat_path_format)}, + {HQA_SERV_RX_STAT_TYPE_USER, 0, 0, 0, + sizeof(struct hqa_rx_stat_user_format)}, + {HQA_SERV_RX_STAT_TYPE_COMM, 0, 0, 0, + sizeof(struct hqa_rx_stat_comm_format)} + }; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_GetRxStatisticsAllV2\n"); + + + /* Request format type */ + memcpy(&type_mask, HqaCmdFrame->Data + 4 * 0, 4); + type_mask = ntohl(type_mask); + + memcpy(&band_idx, HqaCmdFrame->Data + 4 * 1, 4); + band_idx = ntohl(band_idx); + + DBGLOG(RFTEST, INFO, "type_mask = %d, band_idx = %d\n", + type_mask, band_idx); + + /* sanity check for band index param */ + if ((!g_DBDCEnable) && (band_idx != HQA_M_BAND_0)) + goto error2; + + /* check wifi path combination for specific band */ + /* check with Yenchih */ + if (g_DBDCEnable) { + path_len = 1; + if (band_idx == HQA_M_BAND_0) + path[0] = 0; + else + path[0] = 1; + } else { + path_len = 2; + for (i = 0; i < path_len; i++) + path[i] = i; + } + + /* update item mask for each type */ + st_form[HQA_SERV_RX_STAT_TYPE_BAND].item_mask = BIT(band_idx); + for (blk_idx = 0; blk_idx < path_len; blk_idx++) + st_form[HQA_SERV_RX_STAT_TYPE_PATH].item_mask |= + BIT(path[blk_idx]); + for (blk_idx = 0; blk_idx < HQA_USER_NUM; blk_idx++) + st_form[HQA_SERV_RX_STAT_TYPE_USER].item_mask |= + BIT(blk_idx); + st_form[HQA_SERV_RX_STAT_TYPE_COMM].item_mask = BIT(0); + + /* update block count for each type */ + for (type_idx = HQA_SERV_RX_STAT_TYPE_BAND; + type_idx < HQA_SERV_RX_STAT_TYPE_NUM; type_idx++) { + for (blk_idx = 0; blk_idx < 32; blk_idx++) { + if (st_form[type_idx].item_mask & BIT(blk_idx)) + st_form[type_idx].blk_cnt++; + } + } + + ptr = HqaCmdFrame->Data + 2 + sizeof(type_num); + + /* allocate dynamic memory for rx stat info */ + rx_stat = kalMemAlloc(sizeof(struct hqa_rx_stat_u), VIR_MEM_TYPE); + if (!rx_stat) { + i4Ret = WLAN_STATUS_RESOURCES; + goto error1; + } + + for (type_idx = HQA_SERV_RX_STAT_TYPE_BAND; + type_idx < HQA_SERV_RX_STAT_TYPE_NUM; type_idx++) { + if (type_mask & BIT(type_idx)) { + type_num++; + length = st_form[type_idx].blk_cnt * + st_form[type_idx].blk_size; + + /* fill in type */ + buf = htonl(st_form[type_idx].type); + kalMemMove(ptr, &buf, sizeof(buf)); + ptr += sizeof(st_form[type_idx].type); + buf_size += sizeof(st_form[type_idx].type); + + /* fill in version */ + buf = htonl(st_form[type_idx].version); + kalMemMove(ptr, &buf, sizeof(buf)); + ptr += sizeof(st_form[type_idx].version); + buf_size += sizeof(st_form[type_idx].version); + + /* fill in item mask */ + buf = htonl(st_form[type_idx].item_mask); + kalMemMove(ptr, &buf, sizeof(buf)); + ptr += sizeof(st_form[type_idx].item_mask); + buf_size += sizeof(st_form[type_idx].item_mask); + + /* fill in length */ + buf = htonl(length); + kalMemMove(ptr, &buf, sizeof(buf)); + ptr += sizeof(length); + buf_size += sizeof(length); + + for (blk_idx = 0; blk_idx < 32; blk_idx++) { + if (st_form[type_idx].item_mask + & BIT(blk_idx)) { + /* service handle for rx stat info */ + hqa_getRxStatisticsByType(prGlueInfo, + band_idx, + blk_idx, + type_idx, + rx_stat); + ptr2 = (u_int32_t *) rx_stat; + dw_cnt = st_form[type_idx].blk_size + >> 2; + for (dw_idx = 0; dw_idx < dw_cnt; + dw_idx++, ptr2++, + ptr += 4) { + /* endian transform */ + buf = htonl(*ptr2); + /* fill in block content */ + kalMemMove(ptr, &buf, + sizeof(buf)); + } + + buf_size += st_form[type_idx].blk_size; + } + } + } + } + + /* free allocated memory */ + kalMemFree(rx_stat, VIR_MEM_TYPE, sizeof(struct hqa_rx_stat_u)); + + /* fill in type num */ + ptr = HqaCmdFrame->Data + 2; + buf = htonl(type_num); + kalMemMove(ptr, &buf, sizeof(buf)); + buf_size += sizeof(type_num); + + ResponseToQA(HqaCmdFrame, prIwReqData, + (2 + buf_size), i4Ret); + + return i4Ret; + +error1: + DBGLOG(RFTEST, INFO, "memory allocation fail for rx stat."); + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + return i4Ret; + +error2: + DBGLOG(RFTEST, INFO, "invalid band index for non-dbdc mode\n"); + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_MPSSetNss(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t *mps_setting = NULL; + uint32_t u4Band_idx = 0; + uint32_t u4Offset = 0; + uint32_t u4Len = 0; + uint32_t i = 0; + uint32_t u4Value = 0; + + u4Len = ntohs(HqaCmdFrame->Length) / sizeof(uint32_t) - 1; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MPSSetNss u4Len : %d\n", + u4Len); + + mps_setting = kmalloc(sizeof(uint32_t) * (u4Len), + GFP_KERNEL); + ASSERT(mps_setting); + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetNss u4Band_idx : %d\n", u4Band_idx); + + for (i = 0; i < u4Len; i++) { + u4Offset = 4 + 4 * i; + /* Reserved at least 4 byte availbale data */ + if (u4Offset + 4 > sizeof(HqaCmdFrame->Data)) + break; + memcpy(&u4Value, HqaCmdFrame->Data + 4 + 4 * i, 4); + mps_setting[i] = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetNss mps_setting Case %d (Nss : %d)\n", + i, mps_setting[i]); + } + + i4Ret = MT_ATEMPSSetNss(prNetDev, u4Len, mps_setting, + u4Band_idx); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(mps_setting); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_MPSSetPerpacketBW( + struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t *mps_setting = NULL; + uint32_t u4Band_idx = 0; + uint32_t u4Offset = 0; + uint32_t u4Len = 0; + uint32_t i = 0; + uint32_t u4Value = 0; + + u4Len = ntohs(HqaCmdFrame->Length) / sizeof(uint32_t) - 1; + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetPerpacketBW u4Len : %d\n", u4Len); + + mps_setting = kmalloc(sizeof(uint32_t) * (u4Len), + GFP_KERNEL); + ASSERT(mps_setting); + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetPerpacketBW u4Band_idx : %d\n", + u4Band_idx); + + for (i = 0 ; i < u4Len ; i++) { + u4Offset = 4 + 4 * i; + /* Reserved at least 4 byte availbale data */ + if (u4Offset + 4 > sizeof(HqaCmdFrame->Data)) + break; + memcpy(&u4Value, HqaCmdFrame->Data + 4 + 4 * i, 4); + mps_setting[i] = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetPerpacketBW mps_setting Case %d (BW : %d)\n", + i, mps_setting[i]); + } + + i4Ret = MT_ATEMPSSetPerpacketBW(prNetDev, u4Len, + mps_setting, u4Band_idx); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(mps_setting); + + return i4Ret; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetAIFS(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t SlotTime = 0; + uint32_t SifsTime = 0; + + memcpy(&SlotTime, HqaCmdFrame->Data + 4 * 0, 4); + SlotTime = ntohl(SlotTime); + memcpy(&SifsTime, HqaCmdFrame->Data + 4 * 1, 4); + SifsTime = ntohl(SifsTime); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetAIFS SlotTime = %d\n", + SlotTime); + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetAIFS SifsTime = %d\n", + SifsTime); + + i4Ret = MT_ATESetTxIPG(prNetDev, SifsTime); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_CheckEfuseModeType(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t Value = u4EepromMode; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_CheckEfuseModeType\n"); + + /* + * Value: + * 1 -> efuse Mode + * 2 -> flash Mode + * 3 -> eeprom Mode + * 4 -> bin Mode + */ + Value = ntohl(Value); + memcpy(HqaCmdFrame->Data + 2, &(Value), sizeof(Value)); + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_CheckEfuseNativeModeType( + struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_CheckEfuseNativeModeType\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetBandMode(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Band_mode = 0; + uint32_t u4Band_type = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t u4BufLen = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + memcpy((uint8_t *)&u4Band_mode, HqaCmdFrame->Data + 4 * 0, + 4); + u4Band_mode = ntohl(u4Band_mode); + memcpy((uint8_t *)&u4Band_type, HqaCmdFrame->Data + 4 * 1, + 4); + u4Band_type = ntohl(u4Band_type); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetBandMode u4Band_mode : %d\n", u4Band_mode); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetBandMode u4Band_type : %d\n", u4Band_type); + + if (u4Band_mode == 2) + g_DBDCEnable = TRUE; + else if (u4Band_mode == 1) + g_DBDCEnable = FALSE; + + /* notifiy FW */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_DBDC_ENABLE; + if (g_DBDCEnable) + rRfATInfo.u4FuncData = 1; + else + rRfATInfo.u4FuncData = 0; + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_GetBandMode g_DBDCEnable = %d\n", + g_DBDCEnable); + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetBandMode(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Band_mode = 0; + uint32_t u4Band_idx = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t u4BufLen = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + memcpy((uint8_t *)&u4Band_idx, HqaCmdFrame->Data, 4); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_GetBandMode u4Band_idx : %d\n", u4Band_idx); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_DBDC_ENABLE; + if (g_DBDCEnable) + rRfATInfo.u4FuncData = 1; + else + rRfATInfo.u4FuncData = 0; + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_GetBandMode g_DBDCEnable = %d\n", + g_DBDCEnable); + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + + if (u4Band_idx == 0) { + u4Band_mode = 3; + } else { + if (g_DBDCEnable) + u4Band_mode = 3; + else + u4Band_mode = 0; + } + + u4Band_mode = ntohl(u4Band_mode); + + memcpy(HqaCmdFrame->Data + 2, &(u4Band_mode), + sizeof(u4Band_mode)); + + ResponseToQA(HqaCmdFrame, prIwReqData, + 2 + sizeof(u4Band_mode), i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_RDDStartExt(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_RDDStartExt\n"); + + DBGLOG(RFTEST, INFO, "[RDD DUMP START]\n"); + + i4Ret = MT_ATERDDStart(prNetDev, "RDDSTART"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_RDDStopExt(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_RDDStopExt\n"); + + i4Ret = MT_ATERDDStop(prNetDev, "RDDSTOP"); + + DBGLOG(RFTEST, INFO, "[RDD DUMP END]\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_BssInfoUpdate(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t OwnMacIdx = 0, BssIdx = 0; + uint8_t ucAddr1[MAC_ADDR_LEN]; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + memcpy(&OwnMacIdx, HqaCmdFrame->Data + 4 * 0, 4); + OwnMacIdx = ntohl(OwnMacIdx); + memcpy(&BssIdx, HqaCmdFrame->Data + 4 * 1, 4); + BssIdx = ntohl(BssIdx); + memcpy(ucAddr1, HqaCmdFrame->Data + 4 * 2, 6); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_BssInfoUpdate OwnMacIdx : %d\n", OwnMacIdx); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_BssInfoUpdate BssIdx : %d\n", BssIdx); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_BssInfoUpdate addr1:%02x:%02x:%02x:%02x:%02x:%02x\n", + ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], ucAddr1[4], + ucAddr1[5]); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + OwnMacIdx, BssIdx, ucAddr1[0], ucAddr1[1], ucAddr1[2], + ucAddr1[3], ucAddr1[4], ucAddr1[5]); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_BssInfoUpdate(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_DevInfoUpdate(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t Band = 0, OwnMacIdx = 0; + uint8_t ucAddr1[MAC_ADDR_LEN]; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + memcpy(&Band, HqaCmdFrame->Data + 4 * 0, 4); + Band = ntohl(Band); + memcpy(&OwnMacIdx, HqaCmdFrame->Data + 4 * 1, 4); + OwnMacIdx = ntohl(OwnMacIdx); + memcpy(ucAddr1, HqaCmdFrame->Data + 4 * 2, 6); + + DBGLOG(RFTEST, INFO, "Band : %d, OwnMacIdx : %d\n", Band, OwnMacIdx); + DBGLOG(RFTEST, INFO, "addr1:%02x:%02x:%02x:%02x:%02x:%02x\n", + ucAddr1[0], ucAddr1[1], ucAddr1[2], + ucAddr1[3], ucAddr1[4], ucAddr1[5]); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + OwnMacIdx, ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], + ucAddr1[4], ucAddr1[5], Band); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_DevInfoUpdate(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_LogOnOff(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Band_idx = 0; + uint32_t u4Log_type = 0; + uint32_t u4Log_ctrl = 0; + uint32_t u4Log_size = 200; + + memcpy(&u4Band_idx, HqaCmdFrame->Data, 4); + u4Band_idx = ntohl(u4Band_idx); + memcpy(&u4Log_type, HqaCmdFrame->Data + 4, 4); + u4Log_type = ntohl(u4Log_type); + memcpy(&u4Log_ctrl, HqaCmdFrame->Data + 4 + 4, 4); + u4Log_ctrl = ntohl(u4Log_ctrl); + memcpy(&u4Log_size, HqaCmdFrame->Data + 4 + 4 + 4, 4); + u4Log_size = ntohl(u4Log_size); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_LogOnOff band_idx : %d\n", u4Band_idx); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_LogOnOff log_type : %d\n", u4Log_type); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_LogOnOff log_ctrl : %d\n", u4Log_ctrl); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_LogOnOff log_size : %d\n", u4Log_size); + + i4Ret = MT_ATELogOnOff(prNetDev, u4Log_type, u4Log_ctrl, + u4Log_size); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + + +static int32_t HQA_GetDumpRecal(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct RECAL_INFO_T *prReCalInfo = NULL; + struct RECAL_DATA_T *prCalArray = NULL; + uint32_t i = 0, u4Value = 0, u4RespLen = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + prReCalInfo = &prAdapter->rReCalInfo; + prCalArray = prReCalInfo->prCalArray; + + DBGLOG(RFTEST, INFO, "prReCalInfo->u4Count = [%d]\n", + prReCalInfo->u4Count); + if (prReCalInfo->u4Count > 0) { + for (i = 0; i < prReCalInfo->u4Count; i++) { + u4Value = ntohl(prCalArray[i].u4CalId); + kalMemCopy(HqaCmdFrame->Data + 6 + u4RespLen, + &u4Value, + sizeof(u4Value)); + u4RespLen += sizeof(u4Value); + + u4Value = ntohl(prCalArray[i].u4CalAddr); + DBGLOG(RFTEST, INFO, "CalAddr[%d] = [0x%08x]\n", + i, prCalArray[i].u4CalAddr); + kalMemCopy(HqaCmdFrame->Data + 6 + u4RespLen, + &u4Value, + sizeof(u4Value)); + u4RespLen += sizeof(u4Value); + + u4Value = ntohl(prCalArray[i].u4CalValue); + kalMemCopy(HqaCmdFrame->Data + 6 + u4RespLen, + &u4Value, + sizeof(u4Value)); + u4RespLen += sizeof(u4Value); + } + + u4Value = ntohl(prReCalInfo->u4Count); + kalMemCopy(HqaCmdFrame->Data + 2, &u4Value, sizeof(u4Value)); + ResponseToQA(HqaCmdFrame, + prIwReqData, + 6 + prReCalInfo->u4Count * 12, + 0); + } else { + kalMemCopy(HqaCmdFrame->Data + 2, &prReCalInfo->u4Count, 4); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, 0); + } + + /* free resources */ + if (prReCalInfo->prCalArray != NULL) { + kalMemFree(prReCalInfo->prCalArray, + VIR_MEM_TYPE, + 2048 * sizeof(struct RECAL_DATA_T)); + prReCalInfo->prCalArray = 0; + prReCalInfo->u4Count = 0; + } + + return 0; +} + +static int32_t HQA_GetDumpRXV(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Count = 0, i4Ret = 0; + + i4Ret = MT_ATEGetDumpRXV(prNetDev, HqaCmdFrame->Data, &i4Count); + ResponseToQA(HqaCmdFrame, prIwReqData, 6 + i4Count, i4Ret); + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_ReCal_CMDS[] = { + HQA_GetDumpRecal, /*0x1581 */ +}; + +static HQA_CMD_HANDLER HQA_RXV_CMDS[] = { + HQA_GetDumpRXV, /* 0x1581 */ +}; + + +static HQA_CMD_HANDLER HQA_CMD_SET5[] = { + /* cmd id start from 0x1500 */ + HQA_GetFWInfo, /* 0x1500 */ + HQA_StartContinousTx, /* 0x1501 */ + HQA_SetSTBC, /* 0x1502 */ + HQA_SetShortGI, /* 0x1503 */ + HQA_SetDPD, /* 0x1504 */ + HQA_SetTssiOnOff, /* 0x1505 */ + HQA_GetRxStatisticsAll, /* 0x1506 */ + HQA_StartContiTxTone, /* 0x1507 */ + HQA_StopContiTxTone, /* 0x1508 */ + HQA_CalibrationTestMode, /* 0x1509 */ + HQA_DoCalibrationTestItem, /* 0x150A */ + HQA_eFusePhysicalWrite, /* 0x150B */ + HQA_eFusePhysicalRead, /* 0x150C */ + HQA_eFuseLogicalRead, /* 0x150D */ + HQA_eFuseLogicalWrite, /* 0x150E */ + HQA_TMRSetting, /* 0x150F */ + HQA_GetRxSNR, /* 0x1510 */ + HQA_WriteBufferDone, /* 0x1511 */ + HQA_FFT, /* 0x1512 */ + HQA_SetTxTonePower, /* 0x1513 */ + HQA_GetChipID, /* 0x1514 */ + HQA_MPSSetSeqData, /* 0x1515 */ + HQA_MPSSetPayloadLength, /* 0x1516 */ + HQA_MPSSetPacketCount, /* 0x1517 */ + HQA_MPSSetPowerGain, /* 0x1518 */ + HQA_MPSStart, /* 0x1519 */ + HQA_MPSStop, /* 0x151A */ + ToDoFunction, /* 0x151B */ + HQA_GetRxStatisticsAllV2, /* 0x151C */ + ToDoFunction, /* 0x151D */ + ToDoFunction, /* 0x151E */ + ToDoFunction, /* 0x151F */ + ToDoFunction, /* 0x1520 */ + HQA_SetAIFS, /* 0x1521 */ + HQA_CheckEfuseModeType, /* 0x1522 */ + HQA_CheckEfuseNativeModeType, /* 0x1523 */ + ToDoFunction, /* 0x1524 */ + ToDoFunction, /* 0x1525 */ + ToDoFunction, /* 0x1526 */ + ToDoFunction, /* 0x1527 */ + ToDoFunction, /* 0x1528 */ + ToDoFunction, /* 0x1529 */ + ToDoFunction, /* 0x152A */ + ToDoFunction, /* 0x152B */ + HQA_SetBandMode, /* 0x152C */ + HQA_GetBandMode, /* 0x152D */ + HQA_RDDStartExt, /* 0x152E */ + HQA_RDDStopExt, /* 0x152F */ + ToDoFunction, /* 0x1530 */ + HQA_BssInfoUpdate, /* 0x1531 */ + HQA_DevInfoUpdate, /* 0x1532 */ + HQA_LogOnOff, /* 0x1533 */ + ToDoFunction, /* 0x1534 */ + ToDoFunction, /* 0x1535 */ + HQA_MPSSetNss, /* 0x1536 */ + HQA_MPSSetPerpacketBW, /* 0x1537 */ +}; + +#if CFG_SUPPORT_TX_BF +static int32_t HQA_TxBfProfileTagInValid(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t invalid = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(invalid), GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_TxBfProfileTagInValid\n"); + + memcpy(&invalid, HqaCmdFrame->Data, 4); + invalid = ntohl(invalid); + + kalMemSet(prInBuf, 0, sizeof(invalid)); + kalSprintf(prInBuf, "%u", invalid); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_InValid(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagPfmuIdx(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t pfmuidx = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(pfmuidx), GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_TxBfProfileTagPfmuIdx\n"); + + memcpy(&pfmuidx, HqaCmdFrame->Data, 4); + pfmuidx = ntohl(pfmuidx); + + kalMemSet(prInBuf, 0, sizeof(pfmuidx)); + kalSprintf(prInBuf, "%u", pfmuidx); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_PfmuIdx(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagBfType(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t bftype = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(bftype), GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_TxBfProfileTagBfType\n"); + + memcpy(&bftype, HqaCmdFrame->Data, 4); + bftype = ntohl(bftype); + + kalMemSet(prInBuf, 0, sizeof(bftype)); + kalSprintf(prInBuf, "%u", bftype); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_BfType(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagBw(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t tag_bw = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(tag_bw), GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_TxBfProfileTagBw\n"); + + memcpy(&tag_bw, HqaCmdFrame->Data, 4); + tag_bw = ntohl(tag_bw); + + kalMemSet(prInBuf, 0, sizeof(tag_bw)); + kalSprintf(prInBuf, "%u", tag_bw); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_DBW(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagSuMu(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t su_mu = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(su_mu), GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_TxBfProfileTagSuMu\n"); + + memcpy(&su_mu, HqaCmdFrame->Data, 4); + su_mu = ntohl(su_mu); + + kalMemSet(prInBuf, 0, sizeof(su_mu)); + kalSprintf(prInBuf, "%u", su_mu); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_SuMu(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagMemAlloc( + struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t col_idx0, row_idx0, col_idx1, row_idx1; + uint32_t col_idx2, row_idx2, col_idx3, row_idx3; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_TxBfProfileTagMemAlloc\n"); + + memcpy(&col_idx0, HqaCmdFrame->Data + 4 * 0, 4); + col_idx0 = ntohl(col_idx0); + memcpy(&row_idx0, HqaCmdFrame->Data + 4 * 1, 4); + row_idx0 = ntohl(row_idx0); + memcpy(&col_idx1, HqaCmdFrame->Data + 4 * 2, 4); + col_idx1 = ntohl(col_idx1); + memcpy(&row_idx1, HqaCmdFrame->Data + 4 * 3, 4); + row_idx1 = ntohl(row_idx1); + memcpy(&col_idx2, HqaCmdFrame->Data + 4 * 4, 4); + col_idx2 = ntohl(col_idx2); + memcpy(&row_idx2, HqaCmdFrame->Data + 4 * 5, 4); + row_idx2 = ntohl(row_idx2); + memcpy(&col_idx3, HqaCmdFrame->Data + 4 * 6, 4); + col_idx3 = ntohl(col_idx3); + memcpy(&row_idx3, HqaCmdFrame->Data + 4 * 7, 4); + row_idx3 = ntohl(row_idx3); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + col_idx0, row_idx0, col_idx1, row_idx1, col_idx2, row_idx2, + col_idx3, row_idx3); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_Mem(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagMatrix(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t nrow, ncol, ngroup, LM, code_book, htc_exist; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_TxBfProfileTagMatrix\n"); + + memcpy(&nrow, HqaCmdFrame->Data + 4 * 0, 4); + nrow = ntohl(nrow); + memcpy(&ncol, HqaCmdFrame->Data + 4 * 1, 4); + ncol = ntohl(ncol); + memcpy(&ngroup, HqaCmdFrame->Data + 4 * 2, 4); + ngroup = ntohl(ngroup); + memcpy(&LM, HqaCmdFrame->Data + 4 * 3, 4); + LM = ntohl(LM); + memcpy(&code_book, HqaCmdFrame->Data + 4 * 4, 4); + code_book = ntohl(code_book); + memcpy(&htc_exist, HqaCmdFrame->Data + 4 * 5, 4); + htc_exist = ntohl(htc_exist); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x:%02x:%02x:%02x:%02x:%02x", nrow, + ncol, ngroup, LM, code_book, htc_exist); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_Matrix(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagSnr(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t snr_sts0, snr_sts1, snr_sts2, snr_sts3; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_TxBfProfileTagSnr\n"); + + memcpy(&snr_sts0, HqaCmdFrame->Data + 4 * 0, 4); + snr_sts0 = ntohl(snr_sts0); + memcpy(&snr_sts1, HqaCmdFrame->Data + 4 * 1, 4); + snr_sts1 = ntohl(snr_sts1); + memcpy(&snr_sts2, HqaCmdFrame->Data + 4 * 2, 4); + snr_sts2 = ntohl(snr_sts2); + memcpy(&snr_sts3, HqaCmdFrame->Data + 4 * 3, 4); + snr_sts3 = ntohl(snr_sts3); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x:%02x:%02x:%02x", snr_sts0, + snr_sts1, snr_sts2, snr_sts3); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_SNR(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagSmtAnt(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t smt_ant = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(smt_ant), GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_TxBfProfileTagSmtAnt\n"); + + memcpy(&smt_ant, HqaCmdFrame->Data + 4 * 0, 4); + smt_ant = ntohl(smt_ant); + + kalMemSet(prInBuf, 0, sizeof(smt_ant)); + kalSprintf(prInBuf, "%u", smt_ant); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_SmartAnt(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagSeIdx(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t se_idx = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(se_idx), GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_TxBfProfileTagSeIdx\n"); + + memcpy(&se_idx, HqaCmdFrame->Data + 4 * 0, 4); + se_idx = ntohl(se_idx); + + kalMemSet(prInBuf, 0, sizeof(se_idx)); + kalSprintf(prInBuf, "%u", se_idx); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_SeIdx(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagRmsdThrd( + struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t rmsd_thrd = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(rmsd_thrd), GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_TxBfProfileTagRmsdThrd\n"); + + memcpy(&rmsd_thrd, HqaCmdFrame->Data + 4 * 0, 4); + rmsd_thrd = ntohl(rmsd_thrd); + + kalMemSet(prInBuf, 0, sizeof(rmsd_thrd)); + kalSprintf(prInBuf, "%u", rmsd_thrd); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_RmsdThrd(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagMcsThrd(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t mcs_lss0, mcs_sss0, mcs_lss1, mcs_sss1, mcs_lss2, + mcs_sss2; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_TxBfProfileTagMcsThrd\n"); + + memcpy(&mcs_lss0, HqaCmdFrame->Data + 4 * 0, 4); + mcs_lss0 = ntohl(mcs_lss0); + memcpy(&mcs_sss0, HqaCmdFrame->Data + 4 * 1, 4); + mcs_sss0 = ntohl(mcs_sss0); + memcpy(&mcs_lss1, HqaCmdFrame->Data + 4 * 2, 4); + mcs_lss1 = ntohl(mcs_lss1); + memcpy(&mcs_sss1, HqaCmdFrame->Data + 4 * 3, 4); + mcs_sss1 = ntohl(mcs_sss1); + memcpy(&mcs_lss2, HqaCmdFrame->Data + 4 * 4, 4); + mcs_lss2 = ntohl(mcs_lss2); + memcpy(&mcs_sss2, HqaCmdFrame->Data + 4 * 5, 4); + mcs_sss2 = ntohl(mcs_sss2); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x:%02x:%02x:%02x:%02x:%02x", + mcs_lss0, mcs_sss0, mcs_lss1, mcs_sss1, mcs_lss2, + mcs_sss2); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_McsThrd(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagTimeOut(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t bf_tout = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(bf_tout), GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_TxBfProfileTagTimeOut\n"); + + memcpy(&bf_tout, HqaCmdFrame->Data + 4 * 0, 4); + bf_tout = ntohl(bf_tout); + + kalMemSet(prInBuf, 0, sizeof(bf_tout)); + kalSprintf(prInBuf, "%x", bf_tout); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_TimeOut(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagDesiredBw( + struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t desire_bw = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(desire_bw), GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_TxBfProfileTagDesiredBw\n"); + + memcpy(&desire_bw, HqaCmdFrame->Data + 4 * 0, 4); + desire_bw = ntohl(desire_bw); + + kalMemSet(prInBuf, 0, sizeof(desire_bw)); + kalSprintf(prInBuf, "%u", desire_bw); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_DesiredBW(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagDesiredNc( + struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t desire_nc = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(desire_nc), GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_TxBfProfileTagDesiredNc\n"); + + memcpy(&desire_nc, HqaCmdFrame->Data + 4 * 0, 4); + desire_nc = ntohl(desire_nc); + + kalMemSet(prInBuf, 0, sizeof(desire_nc)); + kalSprintf(prInBuf, "%u", desire_nc); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_DesiredNc(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagDesiredNr( + struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t desire_nr = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(desire_nr), GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_TxBfProfileTagDesiredNr\n"); + + memcpy(&desire_nr, HqaCmdFrame->Data + 4 * 0, 4); + desire_nr = ntohl(desire_nr); + + kalMemSet(prInBuf, 0, sizeof(desire_nr)); + kalSprintf(prInBuf, "%u", desire_nr); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_DesiredNr(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagWrite(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t idx = 0; /* WLAN_IDX */ + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(idx), GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_TxBfProfileTagWrite\n"); + + memcpy(&idx, HqaCmdFrame->Data + 4 * 0, 4); + idx = ntohl(idx); + + kalMemSet(prInBuf, 0, sizeof(idx)); + kalSprintf(prInBuf, "%u", idx); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTagWrite(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagRead(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t idx = 0, isBFer = 0; + uint8_t *prInBuf; + union PFMU_PROFILE_TAG1 rPfmuTag1; + union PFMU_PROFILE_TAG2 rPfmuTag2; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_TxBfProfileTagRead\n"); + + memcpy(&idx, HqaCmdFrame->Data + 4 * 0, 4); + idx = ntohl(idx); + memcpy(&isBFer, HqaCmdFrame->Data + 4 * 1, 4); + isBFer = ntohl(isBFer); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x:%02x", idx, isBFer); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTagRead(prNetDev, prInBuf); + + rPfmuTag1.au4RawData[0] = ntohl(g_rPfmuTag1.au4RawData[0]); + rPfmuTag1.au4RawData[1] = ntohl(g_rPfmuTag1.au4RawData[1]); + rPfmuTag1.au4RawData[2] = ntohl(g_rPfmuTag1.au4RawData[2]); + rPfmuTag1.au4RawData[3] = ntohl(g_rPfmuTag1.au4RawData[3]); + + rPfmuTag2.au4RawData[0] = ntohl(g_rPfmuTag2.au4RawData[0]); + rPfmuTag2.au4RawData[1] = ntohl(g_rPfmuTag2.au4RawData[1]); + rPfmuTag2.au4RawData[2] = ntohl(g_rPfmuTag2.au4RawData[2]); + + memcpy(HqaCmdFrame->Data + 2, &rPfmuTag1, + sizeof(union PFMU_PROFILE_TAG1)); + memcpy(HqaCmdFrame->Data + 2 + sizeof(union + PFMU_PROFILE_TAG1), &rPfmuTag2, + sizeof(union PFMU_PROFILE_TAG2)); + + ResponseToQA(HqaCmdFrame, prIwReqData, + 2 + sizeof(union PFMU_PROFILE_TAG1) + sizeof( + union PFMU_PROFILE_TAG2), i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_StaRecCmmUpdate(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t wlan_idx, bss_idx, aid; + uint8_t mac[MAC_ADDR_LEN]; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StaRecCmmUpdate\n"); + + memcpy(&wlan_idx, HqaCmdFrame->Data + 4 * 0, 4); + wlan_idx = ntohl(wlan_idx); + memcpy(&bss_idx, HqaCmdFrame->Data + 4 * 1, 4); + bss_idx = ntohl(bss_idx); + memcpy(&aid, HqaCmdFrame->Data + 4 * 2, 4); + aid = ntohl(aid); + + memcpy(mac, HqaCmdFrame->Data + 4 * 3, 6); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + wlan_idx, bss_idx, aid, mac[0], mac[1], mac[2], mac[3], + mac[4], mac[5]); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_StaRecCmmUpdate(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_StaRecBfUpdate(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t wlan_idx, bss_idx, PfmuId, su_mu, etxbf_cap, + ndpa_rate, ndp_rate; + uint32_t report_poll_rate, tx_mode, nc, nr, cbw, spe_idx, + tot_mem_req; + uint32_t mem_req_20m, mem_row0, mem_col0, mem_row1, + mem_col1; + uint32_t mem_row2, mem_col2, mem_row3, mem_col3; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StaRecBfUpdate\n"); + + memcpy(&wlan_idx, HqaCmdFrame->Data + 4 * 0, 4); + wlan_idx = ntohl(wlan_idx); + memcpy(&bss_idx, HqaCmdFrame->Data + 4 * 1, 4); + bss_idx = ntohl(bss_idx); + memcpy(&PfmuId, HqaCmdFrame->Data + 4 * 2, 4); + PfmuId = ntohl(PfmuId); + memcpy(&su_mu, HqaCmdFrame->Data + 4 * 3, 4); + su_mu = ntohl(su_mu); + memcpy(&etxbf_cap, HqaCmdFrame->Data + 4 * 4, 4); + etxbf_cap = ntohl(etxbf_cap); + memcpy(&ndpa_rate, HqaCmdFrame->Data + 4 * 5, 4); + ndpa_rate = ntohl(ndpa_rate); + memcpy(&ndp_rate, HqaCmdFrame->Data + 4 * 6, 4); + ndp_rate = ntohl(ndp_rate); + memcpy(&report_poll_rate, HqaCmdFrame->Data + 4 * 7, 4); + report_poll_rate = ntohl(report_poll_rate); + memcpy(&tx_mode, HqaCmdFrame->Data + 4 * 8, 4); + tx_mode = ntohl(tx_mode); + memcpy(&nc, HqaCmdFrame->Data + 4 * 9, 4); + nc = ntohl(nc); + memcpy(&nr, HqaCmdFrame->Data + 4 * 10, 4); + nr = ntohl(nr); + memcpy(&cbw, HqaCmdFrame->Data + 4 * 11, 4); + cbw = ntohl(cbw); + memcpy(&spe_idx, HqaCmdFrame->Data + 4 * 12, 4); + spe_idx = ntohl(spe_idx); + memcpy(&tot_mem_req, HqaCmdFrame->Data + 4 * 13, 4); + tot_mem_req = ntohl(tot_mem_req); + memcpy(&mem_req_20m, HqaCmdFrame->Data + 4 * 14, 4); + mem_req_20m = ntohl(mem_req_20m); + memcpy(&mem_row0, HqaCmdFrame->Data + 4 * 15, 4); + mem_row0 = ntohl(mem_row0); + memcpy(&mem_col0, HqaCmdFrame->Data + 4 * 16, 4); + mem_col0 = ntohl(mem_col0); + memcpy(&mem_row1, HqaCmdFrame->Data + 4 * 17, 4); + mem_row1 = ntohl(mem_row1); + memcpy(&mem_col1, HqaCmdFrame->Data + 4 * 18, 4); + mem_col1 = ntohl(mem_col1); + memcpy(&mem_row2, HqaCmdFrame->Data + 4 * 19, 4); + mem_row2 = ntohl(mem_row2); + memcpy(&mem_col2, HqaCmdFrame->Data + 4 * 20, 4); + mem_col2 = ntohl(mem_col2); + memcpy(&mem_row3, HqaCmdFrame->Data + 4 * 21, 4); + mem_row3 = ntohl(mem_row3); + memcpy(&mem_col3, HqaCmdFrame->Data + 4 * 22, 4); + mem_col3 = ntohl(mem_col3); + + /* For Tool wrong memory row and col num 20160501 */ + if (PfmuId == 0) { + mem_row0 = 0; + mem_col0 = 0; + mem_row1 = 1; + mem_col1 = 0; + mem_row2 = 2; + mem_col2 = 0; + mem_row3 = 3; + mem_col3 = 0; + } else if (PfmuId == 1) { + mem_row0 = 0; + mem_col0 = 2; + mem_row1 = 1; + mem_col1 = 2; + mem_row2 = 2; + mem_col2 = 2; + mem_row3 = 3; + mem_col3 = 2; + } + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, + "%02x:%02x:%02x:%02x:%02x:%02d:%02d:%02d:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + wlan_idx, bss_idx, PfmuId, su_mu, etxbf_cap, ndpa_rate, + ndp_rate, report_poll_rate, tx_mode, nc, nr, + cbw, spe_idx, tot_mem_req, mem_req_20m, mem_row0, mem_col0, + mem_row1, mem_col1, mem_row2, mem_col2, + mem_row3, mem_col3); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_StaRecBfUpdate(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_BFProfileDataRead(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t idx = 0, fgBFer = 0, subcarrIdx = 0, + subcarr_start = 0, subcarr_end = 0; + uint32_t NumOfsub = 0; + uint32_t offset = 0; + uint8_t *SubIdx = NULL; + uint8_t *prInBuf; + union PFMU_DATA rPfmuData; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_BFProfileDataRead\n"); + + memcpy(&idx, HqaCmdFrame->Data + 4 * 0, 4); + idx = ntohl(idx); + memcpy(&fgBFer, HqaCmdFrame->Data + 4 * 1, 4); + fgBFer = ntohl(fgBFer); + memcpy(&subcarr_start, HqaCmdFrame->Data + 4 * 2, 4); + subcarr_start = ntohl(subcarr_start); + memcpy(&subcarr_end, HqaCmdFrame->Data + 4 * 3, 4); + subcarr_end = ntohl(subcarr_end); + + NumOfsub = subcarr_end - subcarr_start + 1; + NumOfsub = ntohl(NumOfsub); + + memcpy(HqaCmdFrame->Data + 2, &NumOfsub, sizeof(NumOfsub)); + offset += sizeof(NumOfsub); + + for (subcarrIdx = subcarr_start; subcarrIdx <= subcarr_end; + subcarrIdx++) { + SubIdx = (uint8_t *) &subcarrIdx; + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x:%02x:%02x:%02x", idx, fgBFer, + SubIdx[1], SubIdx[0]); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileDataRead(prNetDev, prInBuf); + + rPfmuData.au4RawData[0] = ntohl(g_rPfmuData.au4RawData[0]); + rPfmuData.au4RawData[1] = ntohl(g_rPfmuData.au4RawData[1]); + rPfmuData.au4RawData[2] = ntohl(g_rPfmuData.au4RawData[2]); + rPfmuData.au4RawData[3] = ntohl(g_rPfmuData.au4RawData[3]); + rPfmuData.au4RawData[4] = ntohl(g_rPfmuData.au4RawData[4]); + + memcpy(HqaCmdFrame->Data + 2 + offset, &rPfmuData, + sizeof(rPfmuData)); + offset += sizeof(rPfmuData); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + offset, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_BFProfileDataWrite(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t pfmuid, subcarrier, phi11, psi21, phi21, psi31, + phi31, psi41; + uint32_t phi22, psi32, phi32, psi42, phi33, psi43, snr00, + snr01, snr02, snr03; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_BFProfileDataWrite\n"); + + memcpy(&pfmuid, HqaCmdFrame->Data + 4 * 0, 4); + pfmuid = ntohl(pfmuid); + memcpy(&subcarrier, HqaCmdFrame->Data + 4 * 1, 4); + subcarrier = ntohl(subcarrier); + memcpy(&phi11, HqaCmdFrame->Data + 4 * 2, 4); + phi11 = ntohl(phi11); + memcpy(&psi21, HqaCmdFrame->Data + 4 * 3, 4); + psi21 = ntohl(psi21); + memcpy(&phi21, HqaCmdFrame->Data + 4 * 4, 4); + phi21 = ntohl(phi21); + memcpy(&psi31, HqaCmdFrame->Data + 4 * 5, 4); + psi31 = ntohl(psi31); + memcpy(&phi31, HqaCmdFrame->Data + 4 * 6, 4); + phi31 = ntohl(phi31); + memcpy(&psi41, HqaCmdFrame->Data + 4 * 7, 4); + psi41 = ntohl(psi41); + memcpy(&phi22, HqaCmdFrame->Data + 4 * 8, 4); + phi22 = ntohl(phi22); + memcpy(&psi32, HqaCmdFrame->Data + 4 * 9, 4); + psi32 = ntohl(psi32); + memcpy(&phi32, HqaCmdFrame->Data + 4 * 10, 4); + phi32 = ntohl(phi32); + memcpy(&psi42, HqaCmdFrame->Data + 4 * 11, 4); + psi42 = ntohl(psi42); + memcpy(&phi33, HqaCmdFrame->Data + 4 * 12, 4); + phi33 = ntohl(phi33); + memcpy(&psi43, HqaCmdFrame->Data + 4 * 13, 4); + psi43 = ntohl(psi43); + memcpy(&snr00, HqaCmdFrame->Data + 4 * 14, 4); + snr00 = ntohl(snr00); + memcpy(&snr01, HqaCmdFrame->Data + 4 * 15, 4); + snr01 = ntohl(snr01); + memcpy(&snr02, HqaCmdFrame->Data + 4 * 16, 4); + snr02 = ntohl(snr02); + memcpy(&snr03, HqaCmdFrame->Data + 4 * 17, 4); + snr03 = ntohl(snr03); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, + "%02x:%03x:%03x:%02x:%03x:%02x:%03x:%02x:%03x:%02x:%03x:%02x:%03x:%02x:%02x:%02x:%02x:%02x", + pfmuid, subcarrier, phi11, psi21, phi21, psi31, phi31, + psi41, + phi22, psi32, phi32, psi42, phi33, psi43, snr00, snr01, + snr02, snr03); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileDataWrite(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_BFSounding(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t su_mu, mu_num, snd_interval, wlan_id0; + uint32_t wlan_id1, wlan_id2, wlan_id3, band_idx; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_BFSounding\n"); + + memcpy(&su_mu, HqaCmdFrame->Data + 4 * 0, 4); + su_mu = ntohl(su_mu); + memcpy(&mu_num, HqaCmdFrame->Data + 4 * 1, 4); + mu_num = ntohl(mu_num); + memcpy(&snd_interval, HqaCmdFrame->Data + 4 * 2, 4); + snd_interval = ntohl(snd_interval); + memcpy(&wlan_id0, HqaCmdFrame->Data + 4 * 3, 4); + wlan_id0 = ntohl(wlan_id0); + memcpy(&wlan_id1, HqaCmdFrame->Data + 4 * 4, 4); + wlan_id1 = ntohl(wlan_id1); + memcpy(&wlan_id2, HqaCmdFrame->Data + 4 * 5, 4); + wlan_id2 = ntohl(wlan_id2); + memcpy(&wlan_id3, HqaCmdFrame->Data + 4 * 6, 4); + wlan_id3 = ntohl(wlan_id3); + memcpy(&band_idx, HqaCmdFrame->Data + 4 * 7, 4); + band_idx = ntohl(band_idx); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x:%02x:%02x:%02x:%02x:%02x:%02x", + su_mu, mu_num, snd_interval, wlan_id0, wlan_id1, wlan_id2, + wlan_id3); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_Trigger_Sounding_Proc(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TXBFSoundingStop(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_TXBFSoundingStop\n"); + + i4Ret = Set_Stop_Sounding_Proc(prNetDev, NULL); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static int32_t HQA_TXBFProfileDataWriteAllExt( + struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static int32_t HQA_TxBfTxApply(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t eBF_enable = 0; + uint32_t iBF_enable = 0; + uint32_t wlan_id = 0; + uint32_t MuTx_enable = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_TxBfTxApply\n"); + + memcpy(&eBF_enable, HqaCmdFrame->Data + 4 * 0, 4); + eBF_enable = ntohl(eBF_enable); + memcpy(&iBF_enable, HqaCmdFrame->Data + 4 * 1, 4); + iBF_enable = ntohl(iBF_enable); + memcpy(&wlan_id, HqaCmdFrame->Data + 4 * 2, 4); + wlan_id = ntohl(wlan_id); + memcpy(&MuTx_enable, HqaCmdFrame->Data + 4 * 3, 4); + MuTx_enable = ntohl(MuTx_enable); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x:%02x:%02x:%02x", wlan_id, + eBF_enable, iBF_enable, MuTx_enable); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfTxApply(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_ManualAssoc(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t type; + uint32_t wtbl_idx; + uint32_t ownmac_idx; + uint32_t phymode; + uint32_t bw; + uint32_t pfmuid; + uint32_t marate_mode; + uint32_t marate_mcs; + uint32_t spe_idx; + uint32_t aid; + uint8_t ucAddr1[MAC_ADDR_LEN]; + uint32_t nss = 1; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_ManualAssoc\n"); + + memcpy(&type, HqaCmdFrame->Data + 4 * 0, 4); + type = ntohl(type); + memcpy(&wtbl_idx, HqaCmdFrame->Data + 4 * 1, 4); + wtbl_idx = ntohl(wtbl_idx); + memcpy(&ownmac_idx, HqaCmdFrame->Data + 4 * 2, 4); + ownmac_idx = ntohl(ownmac_idx); + memcpy(&phymode, HqaCmdFrame->Data + 4 * 3, 4); + phymode = ntohl(phymode); + memcpy(&bw, HqaCmdFrame->Data + 4 * 4, 4); + bw = ntohl(bw); + memcpy(&pfmuid, HqaCmdFrame->Data + 4 * 5, 4); + pfmuid = ntohl(pfmuid); + memcpy(&marate_mode, HqaCmdFrame->Data + 4 * 6, 4); + marate_mode = ntohl(marate_mode); + memcpy(&marate_mcs, HqaCmdFrame->Data + 4 * 7, 4); + marate_mcs = ntohl(marate_mcs); + memcpy(&spe_idx, HqaCmdFrame->Data + 4 * 8, 4); + spe_idx = ntohl(spe_idx); + memcpy(&aid, HqaCmdFrame->Data + 4 * 9, 4); + aid = ntohl(aid); + memcpy(ucAddr1, HqaCmdFrame->Data + 4 * 10, 6); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], ucAddr1[4], + ucAddr1[5], type, wtbl_idx, ownmac_idx, + phymode, bw, nss, pfmuid, marate_mode, marate_mcs, spe_idx, + aid, 0); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfManualAssoc(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_TXBF_CMDS[] = { + HQA_TxBfProfileTagInValid, /* 0x1540 */ + HQA_TxBfProfileTagPfmuIdx, /* 0x1541 */ + HQA_TxBfProfileTagBfType, /* 0x1542 */ + HQA_TxBfProfileTagBw, /* 0x1543 */ + HQA_TxBfProfileTagSuMu, /* 0x1544 */ + HQA_TxBfProfileTagMemAlloc, /* 0x1545 */ + HQA_TxBfProfileTagMatrix, /* 0x1546 */ + HQA_TxBfProfileTagSnr, /* 0x1547 */ + HQA_TxBfProfileTagSmtAnt, /* 0x1548 */ + HQA_TxBfProfileTagSeIdx, /* 0x1549 */ + HQA_TxBfProfileTagRmsdThrd, /* 0x154A */ + HQA_TxBfProfileTagMcsThrd, /* 0x154B */ + HQA_TxBfProfileTagTimeOut, /* 0x154C */ + HQA_TxBfProfileTagDesiredBw, /* 0x154D */ + HQA_TxBfProfileTagDesiredNc, /* 0x154E */ + HQA_TxBfProfileTagDesiredNr, /* 0x154F */ + HQA_TxBfProfileTagWrite, /* 0x1550 */ + HQA_TxBfProfileTagRead, /* 0x1551 */ + HQA_StaRecCmmUpdate, /* 0x1552 */ + HQA_StaRecBfUpdate, /* 0x1553 */ + HQA_BFProfileDataRead, /* 0x1554 */ + HQA_BFProfileDataWrite, /* 0x1555 */ + HQA_BFSounding, /* 0x1556 */ + HQA_TXBFSoundingStop, /* 0x1557 */ + HQA_TXBFProfileDataWriteAllExt, /* 0x1558 */ + HQA_TxBfTxApply, /* 0x1559 */ + HQA_ManualAssoc, /* 0x155A */ +}; + +#if CFG_SUPPORT_MU_MIMO +static int32_t HQA_MUGetInitMCS(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Gid = 0; + uint32_t u4User0InitMCS = 0; + uint32_t u4User1InitMCS = 0; + uint32_t u4User2InitMCS = 0; + uint32_t u4User3InitMCS = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MUGetInitMCS\n"); + + memcpy(&u4Gid, HqaCmdFrame->Data, 4); + u4Gid = ntohl(u4Gid); + + kalMemSet(prInBuf, 0, sizeof(u4Gid)); + kalSprintf(prInBuf, "%u", u4Gid); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUGetInitMCS(prNetDev, prInBuf); + + u4User0InitMCS = ntohl(u4User0InitMCS); + u4User1InitMCS = ntohl(u4User1InitMCS); + u4User2InitMCS = ntohl(u4User2InitMCS); + u4User3InitMCS = ntohl(u4User3InitMCS); + + memcpy(HqaCmdFrame->Data + 2, &u4User0InitMCS, + sizeof(uint32_t)); + memcpy(HqaCmdFrame->Data + 2 + 1 * sizeof(uint32_t), + &u4User1InitMCS, sizeof(uint32_t)); + memcpy(HqaCmdFrame->Data + 2 + 2 * sizeof(uint32_t), + &u4User2InitMCS, sizeof(uint32_t)); + memcpy(HqaCmdFrame->Data + 2 + 3 * sizeof(uint32_t), + &u4User3InitMCS, sizeof(uint32_t)); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_MUCalInitMCS(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Num_of_user; + uint32_t u4Bandwidth; + uint32_t u4Nss_of_user0; + uint32_t u4Nss_of_user1; + uint32_t u4Nss_of_user2; + uint32_t u4Nss_of_user3; + uint32_t u4Pf_mu_id_of_user0; + uint32_t u4Pf_mu_id_of_user1; + uint32_t u4Pf_mu_id_of_user2; + uint32_t u4Pf_mu_id_of_user3; + uint32_t u4Num_of_txer; /* number of antenna */ + uint32_t u4Spe_index; + uint32_t u4Group_index; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MUCalInitMCS\n"); + + memcpy(&u4Num_of_user, HqaCmdFrame->Data + 4 * 0, 4); + u4Num_of_user = ntohl(u4Num_of_user); + memcpy(&u4Bandwidth, HqaCmdFrame->Data + 4 * 1, 4); + u4Bandwidth = ntohl(u4Bandwidth); + memcpy(&u4Nss_of_user0, HqaCmdFrame->Data + 4 * 2, 4); + u4Nss_of_user0 = ntohl(u4Nss_of_user0); + memcpy(&u4Nss_of_user1, HqaCmdFrame->Data + 4 * 3, 4); + u4Nss_of_user1 = ntohl(u4Nss_of_user1); + memcpy(&u4Nss_of_user2, HqaCmdFrame->Data + 4 * 4, 4); + u4Nss_of_user2 = ntohl(u4Nss_of_user2); + memcpy(&u4Nss_of_user3, HqaCmdFrame->Data + 4 * 5, 4); + u4Nss_of_user3 = ntohl(u4Nss_of_user3); + memcpy(&u4Pf_mu_id_of_user0, HqaCmdFrame->Data + 4 * 6, 4); + u4Pf_mu_id_of_user0 = ntohl(u4Pf_mu_id_of_user0); + memcpy(&u4Pf_mu_id_of_user1, HqaCmdFrame->Data + 4 * 7, 4); + u4Pf_mu_id_of_user1 = ntohl(u4Pf_mu_id_of_user1); + memcpy(&u4Pf_mu_id_of_user2, HqaCmdFrame->Data + 4 * 8, 4); + u4Pf_mu_id_of_user2 = ntohl(u4Pf_mu_id_of_user2); + memcpy(&u4Pf_mu_id_of_user3, HqaCmdFrame->Data + 4 * 9, 4); + u4Pf_mu_id_of_user3 = ntohl(u4Pf_mu_id_of_user3); + memcpy(&u4Num_of_txer, HqaCmdFrame->Data + 4 * 10, 4); + u4Num_of_txer = ntohl(u4Num_of_txer); + memcpy(&u4Spe_index, HqaCmdFrame->Data + 4 * 11, 4); + u4Spe_index = ntohl(u4Spe_index); + memcpy(&u4Group_index, HqaCmdFrame->Data + 4 * 12, 4); + u4Group_index = ntohl(u4Group_index); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + u4Num_of_user, u4Bandwidth, u4Nss_of_user0, u4Nss_of_user1, + u4Pf_mu_id_of_user0, u4Pf_mu_id_of_user1, + u4Num_of_txer, u4Spe_index, u4Group_index); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUCalInitMCS(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_MUCalLQ(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Type = 0; + uint32_t u4Num_of_user; + uint32_t u4Bandwidth; + uint32_t u4Nss_of_user0; + uint32_t u4Nss_of_user1; + uint32_t u4Nss_of_user2; + uint32_t u4Nss_of_user3; + uint32_t u4Pf_mu_id_of_user0; + uint32_t u4Pf_mu_id_of_user1; + uint32_t u4Pf_mu_id_of_user2; + uint32_t u4Pf_mu_id_of_user3; + uint32_t u4Num_of_txer; /* number of antenna */ + uint32_t u4Spe_index; + uint32_t u4Group_index; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MUCalLQ\n"); + + memcpy(&u4Type, HqaCmdFrame->Data + 4 * 0, 4); + u4Type = ntohl(u4Type); + memcpy(&u4Num_of_user, HqaCmdFrame->Data + 4 * 1, 4); + u4Num_of_user = ntohl(u4Num_of_user); + memcpy(&u4Bandwidth, HqaCmdFrame->Data + 4 * 2, 4); + u4Bandwidth = ntohl(u4Bandwidth); + memcpy(&u4Nss_of_user0, HqaCmdFrame->Data + 4 * 3, 4); + u4Nss_of_user0 = ntohl(u4Nss_of_user0); + memcpy(&u4Nss_of_user1, HqaCmdFrame->Data + 4 * 4, 4); + u4Nss_of_user1 = ntohl(u4Nss_of_user1); + memcpy(&u4Nss_of_user2, HqaCmdFrame->Data + 4 * 5, 4); + u4Nss_of_user2 = ntohl(u4Nss_of_user2); + memcpy(&u4Nss_of_user3, HqaCmdFrame->Data + 4 * 6, 4); + u4Nss_of_user3 = ntohl(u4Nss_of_user3); + memcpy(&u4Pf_mu_id_of_user0, HqaCmdFrame->Data + 4 * 7, 4); + u4Pf_mu_id_of_user0 = ntohl(u4Pf_mu_id_of_user0); + memcpy(&u4Pf_mu_id_of_user1, HqaCmdFrame->Data + 4 * 8, 4); + u4Pf_mu_id_of_user1 = ntohl(u4Pf_mu_id_of_user1); + memcpy(&u4Pf_mu_id_of_user2, HqaCmdFrame->Data + 4 * 9, 4); + u4Pf_mu_id_of_user2 = ntohl(u4Pf_mu_id_of_user2); + memcpy(&u4Pf_mu_id_of_user3, HqaCmdFrame->Data + 4 * 10, 4); + u4Pf_mu_id_of_user3 = ntohl(u4Pf_mu_id_of_user3); + memcpy(&u4Num_of_txer, HqaCmdFrame->Data + 4 * 11, 4); + u4Num_of_txer = ntohl(u4Num_of_txer); + memcpy(&u4Spe_index, HqaCmdFrame->Data + 4 * 12, 4); + u4Spe_index = ntohl(u4Spe_index); + memcpy(&u4Group_index, HqaCmdFrame->Data + 4 * 13, 4); + u4Group_index = ntohl(u4Group_index); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + u4Num_of_user, u4Bandwidth, u4Nss_of_user0, u4Nss_of_user1, + u4Pf_mu_id_of_user0, u4Pf_mu_id_of_user1, + u4Num_of_txer, u4Spe_index, u4Group_index); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUCalLQ(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_MUGetLQ(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t i; + uint8_t u4LqReport[NUM_OF_USER * NUM_OF_MODUL] = {0}; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MUGetLQ\n"); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUGetLQ(prNetDev, prInBuf); + + for (i = 0; i < NUM_OF_USER * NUM_OF_MODUL; i++) { + u4LqReport[i] = ntohl(u4LqReport[i]); + memcpy(HqaCmdFrame->Data + 2 + i * sizeof(uint32_t), + &u4LqReport[i], sizeof(uint32_t)); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_MUSetSNROffset(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Offset = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MUSetSNROffset\n"); + + memcpy(&u4Offset, HqaCmdFrame->Data + 4 * 0, 4); + u4Offset = ntohl(u4Offset); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x", u4Offset); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUSetSNROffset(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_MUSetZeroNss(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Zero_nss = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MUSetZeroNss\n"); + + memcpy(&u4Zero_nss, HqaCmdFrame->Data + 4 * 0, 4); + u4Zero_nss = ntohl(u4Zero_nss); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x", u4Zero_nss); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUSetZeroNss(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_MUSetSpeedUpLQ(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4SpeedUpLq = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MUSetSpeedUpLQ\n"); + + memcpy(&u4SpeedUpLq, HqaCmdFrame->Data + 4 * 0, 4); + u4SpeedUpLq = ntohl(u4SpeedUpLq); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x", u4SpeedUpLq); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUSetSpeedUpLQ(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; + +} + +static int32_t HQA_MUSetMUTable(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint8_t *prTable; + uint16_t u2Len = 0; + uint32_t u4SuMu = 0; + + prTable = kmalloc_array(u2Len, sizeof(uint8_t), GFP_KERNEL); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MUSetMUTable\n"); + + u2Len = ntohl(HqaCmdFrame->Length) - sizeof(u4SuMu); + + memcpy(&u4SuMu, HqaCmdFrame->Data + 4 * 0, 4); + u4SuMu = ntohl(u4SuMu); + + memcpy(prTable, HqaCmdFrame->Data + 4, u2Len); + + i4Ret = Set_MUSetMUTable(prNetDev, prTable); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static int32_t HQA_MUSetGroup(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4GroupIndex, u4NumOfUser, u4User0Ldpc, + u4User1Ldpc, u4User2Ldpc, u4User3Ldpc; + uint32_t u4ShortGI, u4Bw, u4User0Nss, u4User1Nss, + u4User2Nss, u4User3Nss; + uint32_t u4GroupId, u4User0UP, u4User1UP, u4User2UP, + u4User3UP; + uint32_t u4User0MuPfId, u4User1MuPfId, u4User2MuPfId, + u4User3MuPfId; + uint32_t u4User0InitMCS, u4User1InitMCS, u4User2InitMCS, + u4User3InitMCS; + uint8_t ucAddr1[MAC_ADDR_LEN], ucAddr2[MAC_ADDR_LEN], + ucAddr3[MAC_ADDR_LEN], ucAddr4[MAC_ADDR_LEN]; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MUSetGroup\n"); + + memcpy(&u4GroupIndex, HqaCmdFrame->Data + 4 * 0, 4); + u4GroupIndex = ntohl(u4GroupIndex); + memcpy(&u4NumOfUser, HqaCmdFrame->Data + 4 * 1, 4); + u4NumOfUser = ntohl(u4NumOfUser); + memcpy(&u4User0Ldpc, HqaCmdFrame->Data + 4 * 2, 4); + u4User0Ldpc = ntohl(u4User0Ldpc); + memcpy(&u4User1Ldpc, HqaCmdFrame->Data + 4 * 3, 4); + u4User1Ldpc = ntohl(u4User1Ldpc); + memcpy(&u4User2Ldpc, HqaCmdFrame->Data + 4 * 4, 4); + u4User2Ldpc = ntohl(u4User2Ldpc); + memcpy(&u4User3Ldpc, HqaCmdFrame->Data + 4 * 5, 4); + u4User3Ldpc = ntohl(u4User3Ldpc); + memcpy(&u4ShortGI, HqaCmdFrame->Data + 4 * 6, 4); + u4ShortGI = ntohl(u4ShortGI); + memcpy(&u4Bw, HqaCmdFrame->Data + 4 * 7, 4); + u4Bw = ntohl(u4Bw); + memcpy(&u4User0Nss, HqaCmdFrame->Data + 4 * 8, 4); + u4User0Nss = ntohl(u4User0Nss); + memcpy(&u4User1Nss, HqaCmdFrame->Data + 4 * 9, 4); + u4User1Nss = ntohl(u4User1Nss); + memcpy(&u4User2Nss, HqaCmdFrame->Data + 4 * 10, 4); + u4User2Nss = ntohl(u4User2Nss); + memcpy(&u4User3Nss, HqaCmdFrame->Data + 4 * 11, 4); + u4User3Nss = ntohl(u4User3Nss); + memcpy(&u4GroupId, HqaCmdFrame->Data + 4 * 12, 4); + u4GroupId = ntohl(u4GroupId); + memcpy(&u4User0UP, HqaCmdFrame->Data + 4 * 13, 4); + u4User0UP = ntohl(u4User0UP); + memcpy(&u4User1UP, HqaCmdFrame->Data + 4 * 14, 4); + u4User1UP = ntohl(u4User1UP); + memcpy(&u4User2UP, HqaCmdFrame->Data + 4 * 15, 4); + u4User2UP = ntohl(u4User2UP); + memcpy(&u4User3UP, HqaCmdFrame->Data + 4 * 16, 4); + u4User3UP = ntohl(u4User3UP); + memcpy(&u4User0MuPfId, HqaCmdFrame->Data + 4 * 17, 4); + u4User0MuPfId = ntohl(u4User0MuPfId); + memcpy(&u4User1MuPfId, HqaCmdFrame->Data + 4 * 18, 4); + u4User1MuPfId = ntohl(u4User1MuPfId); + memcpy(&u4User2MuPfId, HqaCmdFrame->Data + 4 * 19, 4); + u4User2MuPfId = ntohl(u4User2MuPfId); + memcpy(&u4User3MuPfId, HqaCmdFrame->Data + 4 * 20, 4); + u4User3MuPfId = ntohl(u4User3MuPfId); + memcpy(&u4User0InitMCS, HqaCmdFrame->Data + 4 * 21, 4); + u4User0InitMCS = ntohl(u4User0InitMCS); + memcpy(&u4User1InitMCS, HqaCmdFrame->Data + 4 * 22, 4); + u4User1InitMCS = ntohl(u4User1InitMCS); + memcpy(&u4User2InitMCS, HqaCmdFrame->Data + 4 * 23, 4); + u4User2InitMCS = ntohl(u4User2InitMCS); + memcpy(&u4User3InitMCS, HqaCmdFrame->Data + 4 * 24, 4); + u4User3InitMCS = ntohl(u4User3InitMCS); + + memcpy(ucAddr1, HqaCmdFrame->Data + 4 * 25, 6); + memcpy(ucAddr2, HqaCmdFrame->Data + 4 * 25 + 6 * 1, 6); + memcpy(ucAddr3, HqaCmdFrame->Data + 4 * 25 + 6 * 2, 6); + memcpy(ucAddr4, HqaCmdFrame->Data + 4 * 25 + 6 * 3, 6); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + u4GroupIndex, u4NumOfUser, u4User0Ldpc, u4User1Ldpc, + u4ShortGI, u4Bw, u4User0Nss, u4User1Nss, + u4GroupId, u4User0UP, u4User1UP, u4User0MuPfId, + u4User1MuPfId, u4User0InitMCS, u4User1InitMCS, + ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], ucAddr1[4], + ucAddr1[5], ucAddr2[0], ucAddr2[1], + ucAddr2[2], ucAddr2[3], ucAddr2[4], ucAddr2[5]); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUSetGroup(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_MUGetQD(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4SubIdx = 0; + + /* TODO */ + uint32_t u4User0InitMCS = 0; + uint32_t u4User1InitMCS = 0; + uint32_t u4User2InitMCS = 0; + uint32_t u4User3InitMCS = 0; + + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MUGetQD\n"); + + memcpy(&u4SubIdx, HqaCmdFrame->Data, 4); + u4SubIdx = ntohl(u4SubIdx); + + kalMemSet(prInBuf, 0, sizeof(u4SubIdx)); + kalSprintf(prInBuf, "%u", u4SubIdx); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUGetQD(prNetDev, prInBuf); + + /* TODO */ + u4User0InitMCS = ntohl(u4User0InitMCS); + u4User1InitMCS = ntohl(u4User1InitMCS); + u4User2InitMCS = ntohl(u4User2InitMCS); + u4User3InitMCS = ntohl(u4User3InitMCS); + + memcpy(HqaCmdFrame->Data + 2, &u4User0InitMCS, + sizeof(uint32_t)); + memcpy(HqaCmdFrame->Data + 2 + 1 * sizeof(uint32_t), + &u4User1InitMCS, sizeof(uint32_t)); + memcpy(HqaCmdFrame->Data + 2 + 2 * sizeof(uint32_t), + &u4User2InitMCS, sizeof(uint32_t)); + memcpy(HqaCmdFrame->Data + 2 + 3 * sizeof(uint32_t), + &u4User3InitMCS, sizeof(uint32_t)); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_MUSetEnable(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Enable = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MUSetEnable\n"); + + memcpy(&u4Enable, HqaCmdFrame->Data + 4 * 0, 4); + u4Enable = ntohl(u4Enable); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x", u4Enable); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUSetEnable(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_MUSetGID_UP(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t au4Gid[2]; + uint32_t au4Up[4]; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MUSetGID_UP\n"); + + memcpy(&au4Gid[0], HqaCmdFrame->Data + 4 * 0, 4); + au4Gid[0] = ntohl(au4Gid[0]); + memcpy(&au4Gid[1], HqaCmdFrame->Data + 4 * 1, 4); + au4Gid[1] = ntohl(au4Gid[1]); + memcpy(&au4Up[0], HqaCmdFrame->Data + 4 * 2, 4); + au4Up[0] = ntohl(au4Up[0]); + memcpy(&au4Up[1], HqaCmdFrame->Data + 4 * 3, 4); + au4Up[1] = ntohl(au4Up[1]); + memcpy(&au4Up[2], HqaCmdFrame->Data + 4 * 4, 4); + au4Up[2] = ntohl(au4Up[2]); + memcpy(&au4Up[3], HqaCmdFrame->Data + 4 * 5, 4); + au4Up[3] = ntohl(au4Up[3]); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x:%02x:%02x:%02x:%02x:%02x", + au4Gid[0], au4Gid[1], au4Up[0], au4Up[1], au4Up[2], + au4Up[3]); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUSetGID_UP(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_MUTriggerTx(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4BandIdx, u4IsRandomPattern; + uint32_t u4MsduPayloadLength0, u4MsduPayloadLength1, + u4MsduPayloadLength2, u4MsduPayloadLength3; + uint32_t u4MuPacketCount, u4NumOfSTAs; + uint8_t ucAddr1[MAC_ADDR_LEN], ucAddr2[MAC_ADDR_LEN], + ucAddr3[MAC_ADDR_LEN], ucAddr4[MAC_ADDR_LEN]; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MUTriggerTx\n"); + + memcpy(&u4BandIdx, HqaCmdFrame->Data + 4 * 0, 4); + u4BandIdx = ntohl(u4BandIdx); + memcpy(&u4IsRandomPattern, HqaCmdFrame->Data + 4 * 1, 4); + u4IsRandomPattern = ntohl(u4IsRandomPattern); + memcpy(&u4MsduPayloadLength0, HqaCmdFrame->Data + 4 * 2, 4); + u4MsduPayloadLength0 = ntohl(u4MsduPayloadLength0); + memcpy(&u4MsduPayloadLength1, HqaCmdFrame->Data + 4 * 3, 4); + u4MsduPayloadLength1 = ntohl(u4MsduPayloadLength1); + memcpy(&u4MsduPayloadLength2, HqaCmdFrame->Data + 4 * 4, 4); + u4MsduPayloadLength2 = ntohl(u4MsduPayloadLength2); + memcpy(&u4MsduPayloadLength3, HqaCmdFrame->Data + 4 * 5, 4); + u4MsduPayloadLength3 = ntohl(u4MsduPayloadLength3); + memcpy(&u4MuPacketCount, HqaCmdFrame->Data + 4 * 6, 4); + u4MuPacketCount = ntohl(u4MuPacketCount); + memcpy(&u4NumOfSTAs, HqaCmdFrame->Data + 4 * 7, 4); + u4NumOfSTAs = ntohl(u4NumOfSTAs); + memcpy(ucAddr1, HqaCmdFrame->Data + 4 * 8, 6); + memcpy(ucAddr2, HqaCmdFrame->Data + 4 * 8 + 6 * 1, 6); + memcpy(ucAddr3, HqaCmdFrame->Data + 4 * 8 + 6 * 2, 6); + memcpy(ucAddr4, HqaCmdFrame->Data + 4 * 8 + 6 * 3, 6); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + u4IsRandomPattern, u4MsduPayloadLength0, + u4MsduPayloadLength1, u4MuPacketCount, u4NumOfSTAs, + ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], ucAddr1[4], + ucAddr1[5], + ucAddr2[0], ucAddr2[1], ucAddr2[2], ucAddr2[3], ucAddr2[4], + ucAddr2[5]); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUTriggerTx(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_TXMU_CMDS[] = { + HQA_MUGetInitMCS, /* 0x1560 */ + HQA_MUCalInitMCS, /* 0x1561 */ + HQA_MUCalLQ, /* 0x1562 */ + HQA_MUGetLQ, /* 0x1563 */ + HQA_MUSetSNROffset, /* 0x1564 */ + HQA_MUSetZeroNss, /* 0x1565 */ + HQA_MUSetSpeedUpLQ, /* 0x1566 */ + HQA_MUSetMUTable, /* 0x1567 */ + HQA_MUSetGroup, /* 0x1568 */ + HQA_MUGetQD, /* 0x1569 */ + HQA_MUSetEnable, /* 0x156A */ + HQA_MUSetGID_UP, /* 0x156B */ + HQA_MUTriggerTx, /* 0x156C */ +}; +#endif +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For ICAP + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_CapWiFiSpectrum(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct mt66xx_chip_info *prChipInfo = NULL; + struct ATE_OPS_T *prAteOps = NULL; + uint32_t u4Control = 0; + uint32_t u4Trigger = 0; + uint32_t u4RingCapEn = 0; + uint32_t u4Event = 0; + uint32_t u4Node = 0; + uint32_t u4Len = 0; + uint32_t u4StopCycle = 0; + uint32_t u4BW = 0; + uint32_t u4MacTriggerEvent = 0; + uint32_t u4SourceAddrLSB = 0; + uint32_t u4SourceAddrMSB = 0; + uint8_t aucSourceAddress[MAC_ADDR_LEN]; + uint32_t u4Band = 0; + uint32_t u4WFNum; + uint32_t u4IQ; + uint32_t u4DataLen = 0, u4TempLen = 0; + int32_t i4Ret = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prChipInfo = prGlueInfo->prAdapter->chip_info; + prAteOps = prChipInfo->prAteOps; + + memcpy((uint8_t *)&u4Control, HqaCmdFrame->Data + 4 * 0, 4); + u4Control = ntohl(u4Control); + + DBGLOG(RFTEST, INFO, "u4Control = %d\n", u4Control); + + if (u4Control == 1) { + if (prAteOps->setICapStart) { + memcpy((uint8_t *)&u4Trigger, + HqaCmdFrame->Data + 4 * 1, 4); + u4Trigger = ntohl(u4Trigger); + memcpy((uint8_t *)&u4RingCapEn, + HqaCmdFrame->Data + 4 * 2, 4); + u4RingCapEn = ntohl(u4RingCapEn); + memcpy((uint8_t *)&u4Event, + HqaCmdFrame->Data + 4 * 3, 4); + u4Event = ntohl(u4Event); + memcpy((uint8_t *)&u4Node, + HqaCmdFrame->Data + 4 * 4, 4); + u4Node = ntohl(u4Node); + memcpy((uint8_t *)&u4Len, HqaCmdFrame->Data + 4 * 5, 4); + u4Len = ntohl(u4Len); + memcpy((uint8_t *)&u4StopCycle, + HqaCmdFrame->Data + 4 * 6, + 4); + u4StopCycle = ntohl(u4StopCycle); + memcpy((uint8_t *)&u4BW, HqaCmdFrame->Data + 4 * 7, 4); + u4BW = ntohl(u4BW); + memcpy((uint8_t *)&u4MacTriggerEvent, + HqaCmdFrame->Data + 4 * 8, 4); + u4MacTriggerEvent = ntohl(u4MacTriggerEvent); + memcpy((uint8_t *)&aucSourceAddress, + HqaCmdFrame->Data + 4 * 9, MAC_ADDR_LEN); + memcpy((uint8_t *)&u4Band, + HqaCmdFrame->Data + 4 * 9 + MAC_ADDR_LEN, 4); + u4Band = ntohl(u4Band); + + /* AT Command #1, Trigger always = 1 */ + DBGLOG(RFTEST, INFO, + "u4Trigger=%u, u4RingCapEn=%u, u4TriggerEvent=%u\n", + u4Trigger, u4RingCapEn, u4Trigger); + /* AT Command #81 */ + DBGLOG(RFTEST, INFO, + "u4Node=%u, u4Len=%u, u4topCycle=%u, u4BW=%u, u4Band=%d", + u4Node, u4Len, u4StopCycle, u4BW, u4Band); + + u4SourceAddrLSB = ((aucSourceAddress[0]) | + (aucSourceAddress[1] << 8) | + (aucSourceAddress[2]) << 16 | + (aucSourceAddress[3]) << 24); + u4SourceAddrMSB = ((aucSourceAddress[4]) | + (aucSourceAddress[5] << 8) | + (0x1 << 16)); + + prGlueInfo->prAdapter->rIcapInfo.u4CapNode = u4Node; + i4Ret = prAteOps->setICapStart(prGlueInfo, u4Trigger, + u4RingCapEn, u4Event, u4Node, + u4Len, u4StopCycle, u4BW, + u4MacTriggerEvent, + u4SourceAddrLSB, + u4SourceAddrMSB, u4Band); + } else + i4Ret = 1; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + } else if (u4Control == 2) { + if (prAteOps->getICapStatus) + i4Ret = prAteOps->getICapStatus(prGlueInfo); + else + i4Ret = 1; + /* Query whether ICAP Done */ + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + } else if (u4Control == 3) { + if (prAteOps->getICapIQData) { + kalMemCopy((uint8_t *)&u4WFNum, + HqaCmdFrame->Data + 4 * 1, + 4); + u4WFNum = ntohl(u4WFNum); + kalMemCopy((uint8_t *)&u4IQ, + HqaCmdFrame->Data + 4 * 2, + 4); + u4IQ = ntohl(u4IQ); + + DBGLOG(RFTEST, INFO, + "u4WFNum = %d, u4IQ = %d\n", u4WFNum, u4IQ); + + u4DataLen = prAteOps->getICapIQData( + prGlueInfo, + &HqaCmdFrame->Data[2 + 4 * 4], + u4IQ, + u4WFNum); + /* tool want data count instead of buff length */ + u4TempLen = u4DataLen / 4; + u4Control = ntohl(u4Control); + kalMemCopy(HqaCmdFrame->Data + 2 + 4 * 0, + (uint8_t *)&u4Control, + sizeof(u4Control)); + u4WFNum = ntohl(u4WFNum); + kalMemCopy(HqaCmdFrame->Data + 2 + 4 * 1, + (uint8_t *)&u4WFNum, + sizeof(u4WFNum)); + u4IQ = ntohl(u4IQ); + kalMemCopy(HqaCmdFrame->Data + 2 + 4 * 2, + (uint8_t *)&u4IQ, + sizeof(u4IQ)); + u4TempLen = ntohl(u4TempLen); + kalMemCopy(HqaCmdFrame->Data + 2 + 4 * 3, + (uint8_t *)&u4TempLen, + sizeof(u4TempLen)); + + } + + i4Ret = 0; + /* Get IQ Data and transmit them to UI DLL */ + ResponseToQA(HqaCmdFrame, + prIwReqData, + 2 + 4 * 4 + u4DataLen, + i4Ret); + } else { + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + } + return 0; +} + +int32_t mt6632SetICapStart(struct GLUE_INFO *prGlueInfo, + uint32_t u4Trigger, uint32_t u4RingCapEn, + uint32_t u4Event, uint32_t u4Node, uint32_t u4Len, + uint32_t u4StopCycle, + uint32_t u4BW, uint32_t u4MacTriggerEvent, + uint32_t u4SourceAddrLSB, + uint32_t u4SourceAddrMSB, uint32_t u4Band) +{ + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + /* iwpriv wlan205 set_test_cmd 75 0 (J mode Setting) */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_J_MODE; + rRfATInfo.u4FuncData = 0; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + /* iwpriv wlan205 set_test_cmd 71 0 (Channel Bandwidth) */ + if (u4BW == 4) + u4BW = 3; + else if (u4BW == 3) + u4BW = 4; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_CBW; + rRfATInfo.u4FuncData = u4BW; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + /* iwpriv wlan205 set_test_cmd 24 0 (ADC clock mode) */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_ADC_CLK_MODE; + rRfATInfo.u4FuncData = 0; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + /* iwpriv wlan205 set_test_cmd 84 18000 + * (Internal Capture Trigger Offset) + */ + rRfATInfo.u4FuncIndex = + RF_AT_FUNCID_SET_ICAP_TRIGGER_OFFSET; + rRfATInfo.u4FuncData = u4StopCycle; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + if (u4Len == 0) + u4Len = 196615;/* 24000; */ + /* iwpriv wlan205 set_test_cmd 83 24576 (Internal Capture Size) */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ICAP_SIZE; + rRfATInfo.u4FuncData = u4Len; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + /* iwpriv wlan205 set_test_cmd 80 0 (Internal Capture Content) */ + if (u4Node == 0x6) + u4Node = 0x10000006; + else if (u4Node == 0x8) + u4Node = 0x49; + else if (u4Node == 0x9) + u4Node = 0x48; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ICAP_CONTENT; + rRfATInfo.u4FuncData = u4Node; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + /* iwpriv wlan205 set_test_cmd 81 0 (Internal Capture Trigger mode) */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ICAP_MODE; + rRfATInfo.u4FuncData = u4Trigger; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ICAP_RING; + rRfATInfo.u4FuncData = u4RingCapEn; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + /* iwpriv wlan205 set_test_cmd 1 13 */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_CH_SWITCH_FOR_ICAP; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + /* iwpriv wlan205 set_test_cmd 1 11 */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_ICAP; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + return 0; +} + +int32_t mt6632GetICapStatus(struct GLUE_INFO *prGlueInfo) +{ + struct ADAPTER *prAdapter; + + ASSERT(prGlueInfo); + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + if (prAdapter->rIcapInfo.eIcapState == ICAP_STATE_FW_DUMP_DONE) { + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_CapWiFiSpectrum Done!!!!!!!!!!!!!!!!!\n"); + return 0; + } + return 1; +} + +int32_t connacSetICapStart(struct GLUE_INFO *prGlueInfo, + uint32_t u4Trigger, uint32_t u4RingCapEn, + uint32_t u4Event, uint32_t u4Node, uint32_t u4Len, + uint32_t u4StopCycle, + uint32_t u4BW, uint32_t u4MacTriggerEvent, + uint32_t u4SourceAddrLSB, + uint32_t u4SourceAddrMSB, uint32_t u4Band) +{ + struct PARAM_MTK_WIFI_TEST_STRUCT_EXT_T rRfATInfo; + struct RBIST_CAP_START_T *prICapInfo = NULL; + uint32_t u4BufLen = 0, u4IQArrayLen = 0; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + if (u4Trigger) { + if (prGlueInfo->prAdapter->rIcapInfo.eIcapState + != ICAP_STATE_INIT) { + log_dbg(RFTEST, ERROR, "Already starting, ignore\n"); + return 1; + } + } else { + log_dbg(RFTEST, INFO, "Shutdown Icap\n"); + prGlueInfo->prAdapter->rIcapInfo.eIcapState = ICAP_STATE_INIT; + if (prGlueInfo->prAdapter->rIcapInfo.prIQArray != NULL) + kalMemFree(prGlueInfo->prAdapter->rIcapInfo.prIQArray, + VIR_MEM_TYPE, + u4IQArrayLen); + prGlueInfo->prAdapter->rIcapInfo.u4IQArrayIndex = 0; + prGlueInfo->prAdapter->rIcapInfo.u4ICapEventCnt = 0; + prGlueInfo->prAdapter->rIcapInfo.prIQArray = NULL; + return 0; + } + + prICapInfo = &(rRfATInfo.Data.rICapInfo); + prICapInfo->u4Trigger = u4Trigger; + prICapInfo->u4TriggerEvent = u4Event; + + u4IQArrayLen = MAX_ICAP_IQ_DATA_CNT * sizeof(struct _RBIST_IQ_DATA_T); +#if 0 + if (prGlueInfo->prAdapter->rIcapInfo.prIQArray != NULL) + kalMemFree(prGlueInfo->prAdapter->rIcapInfo.prIQArray, + VIR_MEM_TYPE, + u4IQArrayLen); +#endif + + if (!prGlueInfo->prAdapter->rIcapInfo.prIQArray) { + prGlueInfo->prAdapter->rIcapInfo.prIQArray = + kalMemAlloc(u4IQArrayLen, VIR_MEM_TYPE); + if (!prGlueInfo->prAdapter->rIcapInfo.prIQArray) { + DBGLOG(RFTEST, ERROR, + "Not enough memory for IQ_Array\n"); + return 0; + } + } + + prGlueInfo->prAdapter->rIcapInfo.u4IQArrayIndex = 0; + prGlueInfo->prAdapter->rIcapInfo.u4ICapEventCnt = 0; + kalMemZero(prGlueInfo->prAdapter->rIcapInfo.au4ICapDumpIndex, + sizeof(prGlueInfo->prAdapter->rIcapInfo.au4ICapDumpIndex)); + kalMemZero(prGlueInfo->prAdapter->rIcapInfo.prIQArray, u4IQArrayLen); + + if (prICapInfo->u4TriggerEvent == CAP_FREE_RUN) + prICapInfo->u4RingCapEn = CAP_RING_MODE_DISABLE; + else + prICapInfo->u4RingCapEn = CAP_RING_MODE_ENABLE; + + prICapInfo->u4CaptureNode = u4Node; + prICapInfo->u4CaptureLen = u4Len; + prICapInfo->u4CapStopCycle = u4StopCycle; + prICapInfo->u4BW = u4BW; + prICapInfo->u4MacTriggerEvent = u4MacTriggerEvent; + prICapInfo->u4SourceAddressLSB = u4SourceAddrLSB; + prICapInfo->u4SourceAddressMSB = u4SourceAddrMSB; + prICapInfo->u4BandIdx = u4Band; + prICapInfo->u4EnBitWidth = 0; + prICapInfo->u4Architech = 1; + prICapInfo->u4PhyIdx = 0; +#if (CFG_MTK_ANDROID_EMI == 1) + prICapInfo->u4EmiStartAddress = + (uint32_t) (gConEmiPhyBase & 0xFFFFFFFF); + prICapInfo->u4EmiEndAddress = + (uint32_t) ((gConEmiPhyBase + gConEmiSize) & 0xFFFFFFFF); + prICapInfo->u4EmiMsbAddress = + (uint32_t) ((((uint64_t) gConEmiPhyBase) >> 32) & 0xFFFFFFFF); + + DBGLOG(RFTEST, INFO, + "startAddr = 0x%08x, endAddress = 0x%08x, MsbAddr = 0x%08x\n", + prICapInfo->u4EmiStartAddress, + prICapInfo->u4EmiEndAddress, + prICapInfo->u4EmiMsbAddress); +#else + DBGLOG(RFTEST, WARN, "Platform doesn't support WMT, no EMI address\n"); +#endif + + DBGLOG(RFTEST, INFO, + "%s :\n prICapInfo->u4Trigger = 0x%08x\n prICapInfo->u4RingCapEn = 0x%08x\n" + "prICapInfo->u4TriggerEvent = 0x%08x\n prICapInfo->u4CaptureNode = 0x%08x\n" + "prICapInfo->u4CaptureLen = 0x%08x\n prICapInfo->u4CapStopCycle = 0x%08x\n" + "prICapInfo->ucBW = 0x%08x\n prICapInfo->u4MacTriggerEvent = 0x%08x\n" + "prICapInfo->u4SourceAddressLSB = 0x%08x\n prICapInfo->u4SourceAddressMSB = 0x%08x\n" + "prICapInfo->u4BandIdx = 0x%08x\n", + __func__, + prICapInfo->u4Trigger, prICapInfo->u4RingCapEn, + prICapInfo->u4TriggerEvent, prICapInfo->u4CaptureNode, + prICapInfo->u4CaptureLen, + prICapInfo->u4CapStopCycle, prICapInfo->u4BW, + prICapInfo->u4MacTriggerEvent, + prICapInfo->u4SourceAddressLSB, + prICapInfo->u4SourceAddressMSB, prICapInfo->u4BandIdx); + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidExtRfTestICapStart, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + return 0; +} + +int32_t connacGetICapStatus(struct GLUE_INFO *prGlueInfo) +{ + struct ADAPTER *prAdapter; + struct PARAM_MTK_WIFI_TEST_STRUCT_EXT_T rRfATInfo; + uint32_t u4BufLen = 0; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + enum ENUM_ICAP_STATE eIcapState = ICAP_STATE_INIT; + + + ASSERT(prGlueInfo); + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + eIcapState = prGlueInfo->prAdapter->rIcapInfo.eIcapState; + + /*FW dump IQ data done*/ + if (eIcapState == ICAP_STATE_FW_DUMP_DONE) { + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_CapWiFiSpectrum Done!!!!!!!!!!!!!!!!!\n"); + return 0; + } + + if (eIcapState != ICAP_STATE_FW_DUMPING) { + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidExtRfTestICapStatus, + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + } + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_CapWiFiSpectrum Wait!!!!!!!!!!!!\n"); + return 1; +} + +int32_t commonGetICapIQData(struct GLUE_INFO *prGlueInfo, + uint8_t *pData, uint32_t u4IQType, uint32_t u4WFNum) +{ + struct ADAPTER *prAdapter; + uint32_t u4TempLen = 0; + uint32_t u4DataLen = 0; + int32_t *prIQAry; + int32_t i = 0; + + ASSERT(prGlueInfo); + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + if (u4WFNum <= 1) { + GetIQData(prAdapter, &prIQAry, &u4DataLen, u4IQType, + u4WFNum); + u4TempLen = u4DataLen; + u4DataLen /= 4; + + u4DataLen = ntohl(u4DataLen); + memcpy(pData + 2 + 4 * 3, (uint8_t *) &u4DataLen, + sizeof(u4DataLen)); + + for (i = 0; i < u4TempLen / sizeof(uint32_t); i++) + prIQAry[i] = ntohl(prIQAry[i]); + + memcpy(pData + 2 + 4 * 4, (uint8_t *) &prIQAry[0], + u4TempLen); + } + return u4TempLen; +} + +int32_t connacGetICapIQData(struct GLUE_INFO *prGlueInfo, + uint8_t *pData, uint32_t u4IQType, uint32_t u4WFNum) +{ + struct RBIST_DUMP_IQ_T rRbistDump; + struct ADAPTER *prAdapter; + struct ICAP_INFO_T *prICapInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + uint32_t i = 0; + uint32_t u4Value = 0; + + ASSERT(prGlueInfo); + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + prICapInfo = &prAdapter->rIcapInfo; + + rRbistDump.u4IQType = u4IQType; + rRbistDump.u4WfNum = u4WFNum; + rRbistDump.u4IcapCnt = 0; + rRbistDump.u4IcapDataLen = 0; + rRbistDump.pucIcapData = pData; + + if ((prICapInfo->eIcapState == ICAP_STATE_FW_DUMP_DONE) || + (prICapInfo->eIcapState == ICAP_STATE_QA_TOOL_CAPTURE)) { + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRfTestICapGetIQData, + &rRbistDump, /* pvInfoBuf */ + sizeof(rRbistDump), /* u4InfoBufLen */ + TRUE, /* fgRead */ + TRUE, /* fgWaitResp */ + FALSE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + } else + DBGLOG(RFTEST, ERROR, "ICAP IQ Dump fail in State = %d\n", + prICapInfo->eIcapState); + + /*IQ data network byte oder transfer to host byte order*/ + /*each (I or Q) data size is 4Byte*/ + if (rStatus == WLAN_STATUS_SUCCESS) { + for (i = 0; i < rRbistDump.u4IcapDataLen; + i += sizeof(uint32_t)) { + u4Value = *(pData + i); + u4Value = ntohl(u4Value); + kalMemCopy((pData + i), + (uint8_t *) &u4Value, + sizeof(u4Value)); + } + } + + return rRbistDump.u4IcapDataLen; +} + + +static HQA_CMD_HANDLER HQA_ICAP_CMDS[] = { + HQA_CapWiFiSpectrum, /* 0x1580 */ +}; + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t hqa_set_channel_ext(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Ext_id = 0; + uint32_t u4Param_num = 0; + uint32_t u4Band_idx = 0; + uint32_t u4Central_ch0 = 0; + uint32_t u4Central_ch1 = 0; + uint32_t u4Sys_bw = 0; + uint32_t u4Perpkt_bw = 0; + uint32_t u4Pri_sel = 0; + uint32_t u4Reason = 0; + uint32_t u4Ch_band = 0; + uint32_t u4SetFreq = 0; + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4Param_num, HqaCmdFrame->Data + 4 * 1, 4); + u4Param_num = ntohl(u4Param_num); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 2, 4); + u4Band_idx = ntohl(u4Band_idx); + memcpy(&u4Central_ch0, HqaCmdFrame->Data + 4 * 3, 4); + u4Central_ch0 = ntohl(u4Central_ch0); + memcpy(&u4Central_ch1, HqaCmdFrame->Data + 4 * 4, 4); + u4Central_ch1 = ntohl(u4Central_ch1); + memcpy(&u4Sys_bw, HqaCmdFrame->Data + 4 * 5, 4); + u4Sys_bw = ntohl(u4Sys_bw); + memcpy(&u4Perpkt_bw, HqaCmdFrame->Data + 4 * 6, 4); + u4Perpkt_bw = ntohl(u4Perpkt_bw); + memcpy(&u4Pri_sel, HqaCmdFrame->Data + 4 * 7, 4); + u4Pri_sel = ntohl(u4Pri_sel); + memcpy(&u4Reason, HqaCmdFrame->Data + 4 * 8, 4); + u4Reason = ntohl(u4Reason); + memcpy(&u4Ch_band, HqaCmdFrame->Data + 4 * 9, 4); + u4Ch_band = ntohl(u4Ch_band); + + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_channel_ext ext_id : %d\n", u4Ext_id); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_channel_ext param_num : %d\n", + u4Param_num); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_channel_ext band_idx : %d\n", u4Band_idx); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_channel_ext central_ch0 : %d\n", + u4Central_ch0); + /* for BW80+80 */ + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_channel_ext central_ch1 : %d\n", + u4Central_ch1); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_channel_ext sys_bw : %d\n", u4Sys_bw); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_channel_ext perpkt_bw : %d\n", + u4Perpkt_bw); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_channel_ext pri_sel : %d\n", u4Pri_sel); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_channel_ext reason : %d\n", u4Reason); + /* 0:2.4G 1:5G */ + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_channel_ext ch_band : %d\n", u4Ch_band); + + /* BW Mapping in QA Tool + * 0: BW20 + * 1: BW40 + * 2: BW80 + * 3: BW10 + * 4: BW5 + * 5: BW160C + * 6: BW160NC + */ + /* BW Mapping in FW + * 0: BW20 + * 1: BW40 + * 2: BW80 + * 3: BW160C + * 4: BW160NC + * 5: BW5 + * 6: BW10 + */ + /* For POR Cal Setting - 20160601 */ + if ((u4Central_ch0 == u4Central_ch1) && (u4Sys_bw == 6) + && (u4Perpkt_bw == 6)) { + DBGLOG(RFTEST, INFO, "Wrong Setting for POR Cal\n"); + goto exit; + } + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + if ((u4Central_ch0 >= 7 && u4Central_ch0 <= 16) + && u4Ch_band == 1) { + /*Ch7 - Ch12, 5G (5035-5060)*/ + u4SetFreq = 1000 * (5000 + u4Central_ch0 * 5); + } else if (u4Central_ch0 == 6 && u4Ch_band == 1) { + u4SetFreq = 1000 * 5032; + } else { + u4SetFreq = nicChannelNum2Freq(u4Central_ch0); + } + MT_ATESetChannel(prNetDev, 0, u4SetFreq); + + if (u4Sys_bw == 6) { + u4SetFreq = nicChannelNum2Freq(u4Central_ch1); + MT_ATESetChannel(prNetDev, 1, u4SetFreq); + } + + MT_ATESetSystemBW(prNetDev, u4Sys_bw); + + /* For POR Cal Setting - 20160601 */ + if ((u4Sys_bw == 6) && (u4Perpkt_bw == 6)) + MT_ATESetPerPacketBW(prNetDev, 5); + else + MT_ATESetPerPacketBW(prNetDev, u4Perpkt_bw); + + MT_ATEPrimarySetting(prNetDev, u4Pri_sel); + /* PeiHsuan Memo : No Set Reason ? */ + MT_ATESetBand(prNetDev, u4Ch_band); + +exit: + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (uint8_t *) &u4Ext_id, + sizeof(u4Ext_id)); + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t hqa_set_txcontent_ext(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Len = 0; + uint32_t u4Ext_id = 0; + uint32_t u4Param_num = 0; + uint32_t u4Band_idx = 0; + uint32_t u4FC = 0; + uint32_t u4Dur = 0; + uint32_t u4Seq = 0; + uint32_t u4Gen_payload_rule = 0; + uint32_t u4Txlen = 0; + uint32_t u4Payload_len = 0; + uint8_t ucAddr1[MAC_ADDR_LEN]; + uint8_t ucAddr2[MAC_ADDR_LEN]; + uint8_t ucAddr3[MAC_ADDR_LEN]; + uint32_t ucPayload = 0; + + u4Len = ntohs(HqaCmdFrame->Length); + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4Param_num, HqaCmdFrame->Data + 4 * 1, 4); + u4Param_num = ntohl(u4Param_num); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 2, 4); + u4Band_idx = ntohl(u4Band_idx); + memcpy(&u4FC, HqaCmdFrame->Data + 4 * 3, 4); + u4FC = ntohl(u4FC); + memcpy(&u4Dur, HqaCmdFrame->Data + 4 * 4, 4); + u4Dur = ntohl(u4Dur); + memcpy(&u4Seq, HqaCmdFrame->Data + 4 * 5, 4); + u4Seq = ntohl(u4Seq); + memcpy(&u4Gen_payload_rule, HqaCmdFrame->Data + 4 * 6, 4); + u4Gen_payload_rule = ntohl(u4Gen_payload_rule); + memcpy(&u4Txlen, HqaCmdFrame->Data + 4 * 7, 4); + u4Txlen = ntohl(u4Txlen); + memcpy(&u4Payload_len, HqaCmdFrame->Data + 4 * 8, 4); + u4Payload_len = ntohl(u4Payload_len); + memcpy(ucAddr1, HqaCmdFrame->Data + 4 * 9, 6); + memcpy(ucAddr2, HqaCmdFrame->Data + 4 * 9 + 6 * 1, 6); + memcpy(ucAddr3, HqaCmdFrame->Data + 4 * 9 + 6 * 2, 6); + memcpy(&ucPayload, HqaCmdFrame->Data + 4 * 9 + 6 * 3, 1); + + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_txcontent_ext ext_id : %d\n", u4Ext_id); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_txcontent_ext param_num : %d\n", + u4Param_num); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_txcontent_ext band_idx : %d\n", + u4Band_idx); + /* Frame Control...0800 : Beacon */ + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_txcontent_ext FC : 0x%x\n", u4FC); + /* Duration....NAV */ + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_txcontent_ext dur : 0x%x\n", u4Dur); + /* Sequence Control */ + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_txcontent_ext seq : 0x%x\n", u4Seq); + /* Normal:0,Repeat:1,Random:2 */ + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_txcontent_ext gen_payload_rule : %d\n", + u4Gen_payload_rule); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_txcontent_ext txlen : %d\n", u4Txlen); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_txcontent_ext payload_len : %d\n", + u4Payload_len); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_txcontent_ext addr1:%02x:%02x:%02x:%02x:%02x:%02x\n", + ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], ucAddr1[4], + ucAddr1[5]); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_txcontent_ext addr2:%02x:%02x:%02x:%02x:%02x:%02x\n", + ucAddr2[0], ucAddr2[1], ucAddr2[2], ucAddr2[3], ucAddr2[4], + ucAddr2[5]); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_txcontent_ext addr3:%02x:%02x:%02x:%02x:%02x:%02x\n", + ucAddr3[0], ucAddr3[1], ucAddr3[2], ucAddr3[3], ucAddr3[4], + ucAddr3[5]); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_tx_ext payload : 0x%x\n", ucPayload); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + MT_ATESetMacHeader(prNetDev, u4FC, u4Dur, u4Seq); + MT_ATESetTxPayLoad(prNetDev, u4Gen_payload_rule, ucPayload); + MT_ATESetTxLength(prNetDev, u4Txlen); + MT_ATESetMACAddress(prNetDev, RF_AT_FUNCID_SET_MAC_ADDRESS, + ucAddr1); + MT_ATESetMACAddress(prNetDev, RF_AT_FUNCID_SET_TA, ucAddr2); + /* PeiHsuan Memo : No Set Addr3 */ + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (uint8_t *) &u4Ext_id, + sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + sizeof(u4Ext_id), + i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t hqa_start_tx_ext(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Ext_id = 0; + uint32_t u4Param_num = 0; + uint32_t u4Band_idx = 0; + uint32_t u4Pkt_cnt = 0; + uint32_t u4Phymode = 0; + uint32_t u4Rate = 0; + uint32_t u4Pwr = 0; + uint32_t u4Stbc = 0; + uint32_t u4Ldpc = 0; + uint32_t u4iBF = 0; + uint32_t u4eBF = 0; + uint32_t u4Wlan_id = 0; + uint32_t u4Aifs = 0; + uint32_t u4Gi = 0; + uint32_t u4Tx_path = 0; + uint32_t u4Nss = 0; + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4Param_num, HqaCmdFrame->Data + 4 * 1, 4); + u4Param_num = ntohl(u4Param_num); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 2, 4); + u4Band_idx = ntohl(u4Band_idx); + memcpy(&u4Pkt_cnt, HqaCmdFrame->Data + 4 * 3, 4); + u4Pkt_cnt = ntohl(u4Pkt_cnt); + memcpy(&u4Phymode, HqaCmdFrame->Data + 4 * 4, 4); + u4Phymode = ntohl(u4Phymode); + memcpy(&u4Rate, HqaCmdFrame->Data + 4 * 5, 4); + u4Rate = ntohl(u4Rate); + memcpy(&u4Pwr, HqaCmdFrame->Data + 4 * 6, 4); + u4Pwr = ntohl(u4Pwr); + memcpy(&u4Stbc, HqaCmdFrame->Data + 4 * 7, 4); + u4Stbc = ntohl(u4Stbc); + memcpy(&u4Ldpc, HqaCmdFrame->Data + 4 * 8, 4); + u4Ldpc = ntohl(u4Ldpc); + memcpy(&u4iBF, HqaCmdFrame->Data + 4 * 9, 4); + u4iBF = ntohl(u4iBF); + memcpy(&u4eBF, HqaCmdFrame->Data + 4 * 10, 4); + u4eBF = ntohl(u4eBF); + memcpy(&u4Wlan_id, HqaCmdFrame->Data + 4 * 11, 4); + u4Wlan_id = ntohl(u4Wlan_id); + memcpy(&u4Aifs, HqaCmdFrame->Data + 4 * 12, 4); + u4Aifs = ntohl(u4Aifs); + memcpy(&u4Gi, HqaCmdFrame->Data + 4 * 13, 4); + u4Gi = ntohl(u4Gi); + memcpy(&u4Tx_path, HqaCmdFrame->Data + 4 * 14, 4); + u4Tx_path = ntohl(u4Tx_path); + memcpy(&u4Nss, HqaCmdFrame->Data + 4 * 15, 4); + u4Nss = ntohl(u4Nss); + + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_tx_ext ext_id : %d\n", u4Ext_id); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_tx_ext param_num : %d\n", u4Param_num); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_tx_ext band_idx : %d\n", u4Band_idx); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_tx_ext pkt_cnt : %d\n", u4Pkt_cnt); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_tx_ext phymode : %d\n", u4Phymode); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_tx_ext rate : %d\n", u4Rate); + DBGLOG(RFTEST, INFO, "QA_AGENT hqa_start_tx_ext pwr : %d\n", + u4Pwr); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_tx_ext stbc : %d\n", u4Stbc); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_tx_ext ldpc : %d\n", u4Ldpc); + DBGLOG(RFTEST, INFO, "QA_AGENT hqa_start_tx_ext ibf : %d\n", + u4iBF); + DBGLOG(RFTEST, INFO, "QA_AGENT hqa_start_tx_ext ebf : %d\n", + u4eBF); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_tx_ext wlan_id : %d\n", u4Wlan_id); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_tx_ext aifs : %d\n", u4Aifs); + DBGLOG(RFTEST, INFO, "QA_AGENT hqa_start_tx_ext gi : %d\n", + u4Gi); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_tx_ext tx_path : %d\n", u4Tx_path); + DBGLOG(RFTEST, INFO, "QA_AGENT hqa_start_tx_ext nss : %d\n", + u4Nss); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + MT_ATESetTxCount(prNetDev, u4Pkt_cnt); + +#if 1 + if (u4Phymode == 1) { + u4Phymode = 0; + u4Rate += 4; + } else if ((u4Phymode == 0) && ((u4Rate == 9) + || (u4Rate == 10) || (u4Rate == 11))) + u4Phymode = 1; + MT_ATESetPreamble(prNetDev, u4Phymode); + + if (u4Phymode == 0) { + u4Rate |= 0x00000000; + + DBGLOG(RFTEST, INFO, + "QA_AGENT CCK/OFDM (normal preamble) rate : %d\n", + u4Rate); + + MT_ATESetRate(prNetDev, u4Rate); + } else if (u4Phymode == 1) { + if (u4Rate == 9) + u4Rate = 1; + else if (u4Rate == 10) + u4Rate = 2; + else if (u4Rate == 11) + u4Rate = 3; + u4Rate |= 0x00000000; + + DBGLOG(RFTEST, INFO, + "QA_AGENT CCK (short preamble) rate : %d\n", u4Rate); + + MT_ATESetRate(prNetDev, u4Rate); + } else if (u4Phymode >= 2 && u4Phymode <= 4) { + u4Rate |= 0x80000000; + + DBGLOG(RFTEST, INFO, "QA_AGENT HT/VHT rate : %d\n", u4Rate); + + MT_ATESetRate(prNetDev, u4Rate); + } +#endif + + MT_ATESetTxPower0(prNetDev, u4Pwr); + MT_ATESetTxSTBC(prNetDev, u4Stbc); + MT_ATESetEncodeMode(prNetDev, u4Ldpc); + MT_ATESetiBFEnable(prNetDev, u4iBF); + MT_ATESeteBFEnable(prNetDev, u4eBF); + /* PeiHsuan Memo : No Set Wlan ID */ + MT_ATESetTxIPG(prNetDev, u4Aifs); + MT_ATESetTxGi(prNetDev, u4Gi); + MT_ATESetTxVhtNss(prNetDev, u4Nss); + MT_ATESetTxPath(prNetDev, u4Tx_path); + MT_ATEStartTX(prNetDev, "TXFRAME"); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (uint8_t *) &u4Ext_id, + sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + sizeof(u4Ext_id), + i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t hqa_start_rx_ext(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Ext_id = 0; + uint32_t u4Param_num = 0; + uint32_t u4Band_idx = 0; + uint32_t u4Rx_path = 0; + uint8_t ucOwn_mac[MAC_ADDR_LEN]; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t u4BufLen = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + memcpy(&u4Ext_id, HqaCmdFrame->Data, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4Param_num, HqaCmdFrame->Data + 4, 4); + u4Param_num = ntohl(u4Param_num); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 + 4, 4); + u4Band_idx = ntohl(u4Band_idx); + memcpy(ucOwn_mac, HqaCmdFrame->Data + 4 + 4 + 4, 6); + memcpy(&u4Rx_path, HqaCmdFrame->Data + 4 + 4 + 4 + 6, 4); + u4Rx_path = ntohl(u4Rx_path); + + memset(&g_HqaRxStat, 0, sizeof(struct PARAM_RX_STAT)); + + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_rx_ext ext_id : %d\n", u4Ext_id); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_rx_ext param_num : %d\n", u4Param_num); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_rx_ext band_idx : %d\n", u4Band_idx); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_rx_ext own_mac:%02x:%02x:%02x:%02x:%02x:%02x\n", + ucOwn_mac[0], ucOwn_mac[1], ucOwn_mac[2], ucOwn_mac[3], + ucOwn_mac[4], ucOwn_mac[5]); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_rx_ext rx_path : 0x%x\n", u4Rx_path); + + u4RxStatSeqNum = 0; + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_RX_PATH; + rRfATInfo.u4FuncData = u4Rx_path << 16 | u4Band_idx; + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + /* PeiHsuan Memo : No Set Own MAC Address */ + MT_ATEStartRX(prNetDev, "RXFRAME"); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (uint8_t *) &u4Ext_id, + sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + sizeof(u4Ext_id), + i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t hqa_stop_tx_ext(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Ext_id = 0; + uint32_t u4Param_num = 0; + uint32_t u4Band_idx = 0; + + memcpy(&u4Ext_id, HqaCmdFrame->Data, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4Param_num, HqaCmdFrame->Data + 4, 4); + u4Param_num = ntohl(u4Param_num); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 + 4, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_stop_tx_ext ext_id : %d\n", u4Ext_id); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_stop_tx_ext param_num : %d\n", u4Param_num); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_stop_tx_ext band_idx : %d\n", u4Band_idx); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + MT_ATEStopTX(prNetDev, "TXSTOP"); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (uint8_t *) &u4Ext_id, + sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t hqa_stop_rx_ext(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Ext_id = 0; + uint32_t u4Param_num = 0; + uint32_t u4Band_idx = 0; + + memcpy(&u4Ext_id, HqaCmdFrame->Data, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4Param_num, HqaCmdFrame->Data + 4, 4); + u4Param_num = ntohl(u4Param_num); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 + 4, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_stop_rx_ext ext_id : %d\n", u4Ext_id); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_stop_rx_ext param_num : %d\n", u4Param_num); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_stop_rx_ext band_idx : %d\n", u4Band_idx); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + MT_ATEStopRX(prNetDev, "RXSTOP"); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (uint8_t *) &u4Ext_id, + sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +static int32_t HQA_iBFInit(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_iBFInit\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static int32_t HQA_iBFSetValue(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_iBFSetValue\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static int32_t HQA_iBFGetStatus(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_iBFGetStatus\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static int32_t HQA_iBFChanProfUpdate(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_iBFChanProfUpdate\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static int32_t HQA_iBFProfileRead(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_iBFProfileRead\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static int32_t HQA_IRRSetADC(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4WFIdx; + uint32_t u4ChFreq; + uint32_t u4BW; + uint32_t u4Sx; + uint32_t u4Band; + uint32_t u4Ext_id; + uint32_t u4RunType; + uint32_t u4FType; + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4WFIdx, HqaCmdFrame->Data + 4 * 1, 4); + u4WFIdx = ntohl(u4WFIdx); + memcpy(&u4ChFreq, HqaCmdFrame->Data + 4 * 2, 4); + u4ChFreq = ntohl(u4ChFreq); + memcpy(&u4BW, HqaCmdFrame->Data + 4 * 3, 4); + u4BW = ntohl(u4BW); + memcpy(&u4Sx, HqaCmdFrame->Data + 4 * 4, 4); + u4Sx = ntohl(u4Sx); + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 5, 4); + u4Band = ntohl(u4Band); + memcpy(&u4RunType, HqaCmdFrame->Data + 4 * 6, 4); + u4RunType = ntohl(u4RunType); + memcpy(&u4FType, HqaCmdFrame->Data + 4 * 7, 4); + u4FType = ntohl(u4FType); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_IRRSetADC ext_id : %d\n", + u4Ext_id); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetADC u4WFIdx : %d\n", u4WFIdx); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetADC u4ChFreq : %d\n", u4ChFreq); + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_IRRSetADC u4BW : %d\n", + u4BW); + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_IRRSetADC u4Sx : %d\n", + u4Sx); /* SX : 0, 2 */ + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_IRRSetADC u4Band : %d\n", + u4Band); + /* RunType : 0 -> QA, 1 -> ATE */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetADC u4RunType : %d\n", u4RunType); + /* FType : 0 -> FI, 1 -> FD */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetADC u4FType : %d\n", u4FType); + + i4Ret = MT_ATE_IRRSetADC(prNetDev, u4WFIdx, u4ChFreq, u4BW, + u4Sx, u4Band, u4RunType, u4FType); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (uint8_t *) &u4Ext_id, + sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +static int32_t HQA_IRRSetRxGain(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4PgaLpfg; + uint32_t u4Lna; + uint32_t u4Band; + uint32_t u4WF_inx; + uint32_t u4Rfdgc; + uint32_t u4Ext_id; + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4PgaLpfg, HqaCmdFrame->Data + 4 * 1, 4); + u4PgaLpfg = ntohl(u4PgaLpfg); + memcpy(&u4Lna, HqaCmdFrame->Data + 4 * 2, 4); + u4Lna = ntohl(u4Lna); + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 3, 4); + u4Band = ntohl(u4Band); + memcpy(&u4WF_inx, HqaCmdFrame->Data + 4 * 4, 4); + u4WF_inx = ntohl(u4WF_inx); + memcpy(&u4Rfdgc, HqaCmdFrame->Data + 4 * 5, 4); + u4Rfdgc = ntohl(u4Rfdgc); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetRxGain ext_id : %d\n", u4Ext_id); + /* PGA is for MT663, LPFG is for MT7615 */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetRxGain u4PgaLpfg : %d\n", u4PgaLpfg); + /* 5 : UH, 4 : H, 3 : M, 2 : L, 1 : UL */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetRxGain u4Lna : %d\n", u4Lna); + /* DBDC band0 or band1 */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetRxGain u4Band : %d\n", u4Band); + /* (each bit for each WF) */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetRxGain u4WF_inx : 0x%x\n", u4WF_inx); + /* only for */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetRxGain u4Rfdgc : %d\n", u4Rfdgc); + + i4Ret = MT_ATE_IRRSetRxGain(prNetDev, u4PgaLpfg, u4Lna, + u4Band, u4WF_inx, u4Rfdgc); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (uint8_t *) &u4Ext_id, + sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +static int32_t HQA_IRRSetTTG(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Ext_id; + uint32_t u4TTGPwrIdx; + uint32_t u4ChFreq; + uint32_t u4FIToneFreq; + uint32_t u4Band; + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4TTGPwrIdx, HqaCmdFrame->Data + 4 * 1, 4); + u4TTGPwrIdx = ntohl(u4TTGPwrIdx); + memcpy(&u4ChFreq, HqaCmdFrame->Data + 4 * 2, 4); + u4ChFreq = ntohl(u4ChFreq); + memcpy(&u4FIToneFreq, HqaCmdFrame->Data + 4 * 3, 4); + u4FIToneFreq = ntohl(u4FIToneFreq); + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 4, 4); + u4Band = ntohl(u4Band); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_IRRSetTTG ext_id : %d\n", + u4Ext_id); + /* TTG Power Index: Power index value 0~15 */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetTTG u4TTGPwrIdx : %d\n", u4TTGPwrIdx); + /* Ch Freq: channel frequency value */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetTTG u4ChFreq : %d\n", u4ChFreq); + /* FI Tone Freq(float): driver calculate TTG Freq(TTG Freq = Ch_freq + + * FI tone freq) + */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetTTG u4FIToneFreq : %d\n", u4FIToneFreq); + /* Band: DBDC band0 or band1 */ + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_IRRSetTTG u4Band : %d\n", + u4Band); + + i4Ret = MT_ATE_IRRSetTTG(prNetDev, u4TTGPwrIdx, u4ChFreq, + u4FIToneFreq, u4Band); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (uint8_t *) &u4Ext_id, + sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +static int32_t HQA_IRRSetTrunOnTTG(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Ext_id; + uint32_t u4TTGOnOff; + uint32_t u4Band; + uint32_t u4WF_inx = 0; + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4TTGOnOff, HqaCmdFrame->Data + 4 * 1, 4); + u4TTGOnOff = ntohl(u4TTGOnOff); + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 2, 4); + u4Band = ntohl(u4Band); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetTrunOnTTG ext_id : %d\n", u4Ext_id); + /* TTG on/off: 0:off, 1: on */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetTrunOnTTG u4TTGOnOff : %d\n", + u4TTGOnOff); + /* Band: DBDC band0 or band1 */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetTrunOnTTG u4Band : %d\n", u4Band); + /* (each bit for each WF) */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetTrunOnTTG u4WF_inx : %d\n", u4WF_inx); + + i4Ret = MT_ATE_IRRSetTrunOnTTG(prNetDev, u4TTGOnOff, u4Band, + u4WF_inx); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (uint8_t *) &u4Ext_id, + sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +static HQA_CMD_HANDLER hqa_ext_cmd_set[] = { + NULL, + hqa_set_channel_ext, /* 0x00000001 */ + hqa_set_txcontent_ext, /* 0x00000002 */ + hqa_start_tx_ext, /* 0x00000003 */ + hqa_start_rx_ext, /* 0x00000004 */ + hqa_stop_tx_ext, /* 0x00000005 */ + hqa_stop_rx_ext, /* 0x00000006 */ + HQA_iBFInit, /* 0x00000007 */ + HQA_iBFSetValue, /* 0x00000008 */ + HQA_iBFGetStatus, /* 0x00000009 */ + HQA_iBFChanProfUpdate, /* 0x0000000A */ + HQA_iBFProfileRead, /* 0x0000000B */ + ToDoFunction, /* 0x0000000C */ + ToDoFunction, /* 0x0000000D */ + ToDoFunction, /* 0x0000000E */ + ToDoFunction, /* 0x0000000F */ + ToDoFunction, /* 0x00000010 */ + ToDoFunction, /* 0x00000011 */ + ToDoFunction, /* 0x00000012 */ + ToDoFunction, /* 0x00000013 */ + ToDoFunction, /* 0x00000014 */ + ToDoFunction, /* 0x00000015 */ + ToDoFunction, /* 0x00000016 */ + ToDoFunction, /* 0x00000017 */ + ToDoFunction, /* 0x00000018 */ + ToDoFunction, /* 0x00000019 */ + ToDoFunction, /* 0x0000001A */ + ToDoFunction, /* 0x0000001B */ + ToDoFunction, /* 0x0000001C */ + ToDoFunction, /* 0x0000001D */ + ToDoFunction, /* 0x0000001E */ + ToDoFunction, /* 0x0000001F */ + HQA_IRRSetADC, /* 0x00000020 */ + HQA_IRRSetRxGain, /* 0x00000021 */ + HQA_IRRSetTTG, /* 0x00000022 */ + HQA_IRRSetTrunOnTTG, /* 0x00000023 */ +}; + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Extension Commands (For MT7615). + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t hqa_ext_cmds(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Idx = 0; + + memmove((uint8_t *)&u4Idx, (uint8_t *)&HqaCmdFrame->Data, + 4); + u4Idx = ntohl(u4Idx); + + DBGLOG(RFTEST, INFO, "QA_AGENT hqa_ext_cmds index : %d\n", + u4Idx); + + if (u4Idx < (sizeof(hqa_ext_cmd_set) / sizeof(HQA_CMD_HANDLER))) { + if (hqa_ext_cmd_set[u4Idx] != NULL) { + /* valid command */ + i4Ret = (*hqa_ext_cmd_set[u4Idx])(prNetDev, + prIwReqData, HqaCmdFrame); + } else { + /* invalid command */ + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_ext_cmds cmd idx is NULL: %d\n", + u4Idx); + } + } else { + /* invalid command */ + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_ext_cmds cmd idx is not supported: %d\n", u4Idx); + } + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_CMD_SET6[] = { + /* cmd id start from 0x1600 */ + hqa_ext_cmds, /* 0x1600 */ +}; + +static struct HQA_CMD_TABLE HQA_CMD_TABLES[] = { + { + HQA_CMD_SET0, + sizeof(HQA_CMD_SET0) / sizeof(HQA_CMD_HANDLER), + 0x1000, + } + , + { + HQA_CMD_SET1, + sizeof(HQA_CMD_SET1) / sizeof(HQA_CMD_HANDLER), + 0x1100, + } + , + { + HQA_CMD_SET2, + sizeof(HQA_CMD_SET2) / sizeof(HQA_CMD_HANDLER), + 0x1200, + } + , + { + HQA_CMD_SET3, + sizeof(HQA_CMD_SET3) / sizeof(HQA_CMD_HANDLER), + 0x1300, + } + , + { + HQA_CMD_SET4, + sizeof(HQA_CMD_SET4) / sizeof(HQA_CMD_HANDLER), + 0x1400, + } + , + { + HQA_CMD_SET5, + sizeof(HQA_CMD_SET5) / sizeof(HQA_CMD_HANDLER), + 0x1500, + } + , +#if CFG_SUPPORT_TX_BF + { + HQA_TXBF_CMDS, + sizeof(HQA_TXBF_CMDS) / sizeof(HQA_CMD_HANDLER), + 0x1540, + } + , +#if CFG_SUPPORT_MU_MIMO + { + HQA_TXMU_CMDS, + sizeof(HQA_TXMU_CMDS) / sizeof(HQA_CMD_HANDLER), + 0x1560, + } + , +#endif +#endif + { + HQA_ICAP_CMDS, + sizeof(HQA_ICAP_CMDS) / sizeof(HQA_CMD_HANDLER), + 0x1580, + } + , + { + HQA_ReCal_CMDS, + sizeof(HQA_ReCal_CMDS) / sizeof(HQA_CMD_HANDLER), + 0x1581, + } + , + { + HQA_RXV_CMDS, + sizeof(HQA_RXV_CMDS) / sizeof(HQA_CMD_HANDLER), + 0x1582, + } + , + { + HQA_CMD_SET6, + sizeof(HQA_CMD_SET6) / sizeof(HQA_CMD_HANDLER), + 0x1600, + } + , +}; + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Handle Ethernet command by Command Idx. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +int HQA_CMDHandler(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Status = 0; + uint32_t u4CmdId; + uint32_t u4TableIndex = 0; + + u4CmdId = ntohs(HqaCmdFrame->Id); + + while (u4TableIndex < (sizeof(HQA_CMD_TABLES) / sizeof( + struct HQA_CMD_TABLE))) { + int CmdIndex = 0; + + CmdIndex = u4CmdId - HQA_CMD_TABLES[u4TableIndex].CmdOffset; + if ((CmdIndex >= 0) + && (CmdIndex < HQA_CMD_TABLES[u4TableIndex].CmdSetSize)) { + HQA_CMD_HANDLER *pCmdSet; + + pCmdSet = HQA_CMD_TABLES[u4TableIndex].CmdSet; + + if (pCmdSet[CmdIndex] != NULL) + i4Status = (*pCmdSet[CmdIndex])(prNetDev, + prIwReqData, HqaCmdFrame); + break; + } + u4TableIndex++; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Ioctl entry from ATE Daemon. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqInfo + * \param[in] prIwReqData + * \param[in] pcExtra + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +int priv_qa_agent(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN char *pcExtra) +{ + int32_t i4Status = 0; + struct HQA_CMD_FRAME *HqaCmdFrame; + uint32_t u4ATEMagicNum, u4ATEId, u4ATEData; + struct GLUE_INFO *prGlueInfo = NULL; +#if (CONFIG_WLAN_SERVICE == 1) + struct hqa_frame_ctrl local_hqa; +#endif + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + + /* workaroud for meta tool */ + if (prGlueInfo->prAdapter->fgTestMode == FALSE) + MT_ATEStart(prNetDev, "ATESTART"); + + if (!prIwReqData || prIwReqData->data.length == 0) { + i4Status = -EINVAL; + goto ERROR0; + } + + HqaCmdFrame = kmalloc(sizeof(*HqaCmdFrame), GFP_KERNEL); + + if (!HqaCmdFrame) { + i4Status = -ENOMEM; + goto ERROR0; + } + + memset(HqaCmdFrame, 0, sizeof(*HqaCmdFrame)); + if (copy_from_user(HqaCmdFrame, prIwReqData->data.pointer, + prIwReqData->data.length)) { + i4Status = -EFAULT; + goto ERROR1; + } + + u4ATEMagicNum = ntohl(HqaCmdFrame->MagicNo); + u4ATEId = ntohs(HqaCmdFrame->Id); + memcpy((uint8_t *)&u4ATEData, HqaCmdFrame->Data, 4); + u4ATEData = ntohl(u4ATEData); + + switch (u4ATEMagicNum) { + case HQA_CMD_MAGIC_NO: +#if (CONFIG_WLAN_SERVICE == 1) + { + local_hqa.type = 0; + local_hqa.hqa_frame_comm.hqa_frame_eth = + (struct hqa_frame *)HqaCmdFrame; + + i4Status = mt_agent_hqa_cmd_handler(&prGlueInfo->rService, + (struct hqa_frame_ctrl *)&local_hqa); + + if (i4Status == WLAN_STATUS_SUCCESS) { + /*Response to QA */ + prIwReqData->data.length + = sizeof((HqaCmdFrame)->MagicNo) + + sizeof((HqaCmdFrame)->Type) + + sizeof((HqaCmdFrame)->Id) + + sizeof((HqaCmdFrame)->Length) + + sizeof((HqaCmdFrame)->Sequence) + + ntohs((HqaCmdFrame)->Length); + + if (copy_to_user(prIwReqData->data.pointer + , (uint8_t *) (HqaCmdFrame) + , prIwReqData->data.length)) { + DBGLOG(RFTEST, INFO + , "QA_AGENT copy_to_user() fail in %s\n" + , __func__); + goto ERROR1; + } + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA cmd(0x%04x)Magic num(0x%08x) is done\n", + ntohs(HqaCmdFrame->Id), + ntohl(HqaCmdFrame->MagicNo)); + } + } +#else + i4Status = HQA_CMDHandler(prNetDev, prIwReqData, HqaCmdFrame); +#endif + break; + default: + i4Status = -EINVAL; + DBGLOG(RFTEST, INFO, "QA_AGENT ATEMagicNum Error!!!\n"); + break; + } + + + +ERROR1: + kfree(HqaCmdFrame); +ERROR0: + return i4Status; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_rst.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_rst.c new file mode 100644 index 0000000000000..c31e96f36386b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_rst.c @@ -0,0 +1,1129 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** 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. + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include +#include + +#include "precomp.h" +#include "gl_rst.h" + +#if (CFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT == 1) +#include "fw_log_wifi.h" +#endif + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + + + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +u_int8_t fgSimplifyResetFlow = FALSE; +uint64_t u8ResetTime; + +#if CFG_CHIP_RESET_HANG +u_int8_t fgIsResetHangState = SER_L0_HANG_RST_NONE; +#endif + +#if (CFG_SUPPORT_CONNINFRA == 1) +uint32_t g_u4WlanRstThreadPid; +wait_queue_head_t g_waitq_rst; +unsigned long g_ulFlag;/* GLUE_FLAG_XXX */ +struct completion g_RstOffComp; +struct completion g_RstOnComp; +struct completion g_triggerComp; +KAL_WAKE_LOCK_T *g_IntrWakeLock; +struct task_struct *wlan_reset_thread; +static int g_rst_data; +u_int8_t g_IsWholeChipRst = FALSE; +u_int8_t g_SubsysRstCnt; +int g_SubsysRstTotalCnt; +int g_WholeChipRstTotalCnt; +bool g_IsTriggerTimeout = FALSE; +u_int8_t g_IsSubsysRstOverThreshold = FALSE; +u_int8_t g_IsWfsysBusHang = FALSE; +char *g_reason; +enum consys_drv_type g_WholeChipRstType; +char *g_WholeChipRstReason; +u_int8_t g_IsWfsysResetOnFail = FALSE; +u_int8_t g_IsWfsysRstDone = TRUE; +u_int8_t g_fgRstRecover = FALSE; +#endif + +#if (CFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT == 1) +static uint8_t *apucRstReason[RST_REASON_MAX] = { + (uint8_t *) DISP_STRING("RST_UNKNOWN"), + (uint8_t *) DISP_STRING("RST_PROCESS_ABNORMAL_INT"), + (uint8_t *) DISP_STRING("RST_DRV_OWN_FAIL"), + (uint8_t *) DISP_STRING("RST_FW_ASSERT"), + (uint8_t *) DISP_STRING("RST_BT_TRIGGER"), + (uint8_t *) DISP_STRING("RST_OID_TIMEOUT"), + (uint8_t *) DISP_STRING("RST_CMD_TRIGGER"), +}; +u_int8_t g_IsNeedWaitCoredump = FALSE; +#endif + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +static enum _ENUM_CHIP_RESET_REASON_TYPE_T eResetReason; + +#if CFG_CHIP_RESET_SUPPORT +static struct RESET_STRUCT wifi_rst; +u_int8_t fgIsResetting = FALSE; +#if (CFG_SUPPORT_CONNINFRA == 1) +enum ENUM_WF_RST_SOURCE g_eWfRstSource = WF_RST_SOURCE_NONE; +#endif +#endif + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +#if CFG_CHIP_RESET_SUPPORT + +#if CFG_WMT_RESET_API_SUPPORT +#if (CFG_SUPPORT_CONNINFRA == 0) +static void mtk_wifi_reset(struct work_struct *work); +static void mtk_wifi_trigger_reset(struct work_struct *work); +static void glResetCallback(enum _ENUM_WMTDRV_TYPE_T eSrcType, + enum _ENUM_WMTDRV_TYPE_T eDstType, + enum _ENUM_WMTMSG_TYPE_T eMsgType, void *prMsgBody, + unsigned int u4MsgLength); +#endif /*end of CFG_SUPPORT_CONNINFRA == 0*/ +#else +static u_int8_t is_bt_exist(void); +static u_int8_t rst_L0_notify_step1(void); +static void wait_core_dump_end(void); +#endif +#endif + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +void glSetRstReason(enum _ENUM_CHIP_RESET_REASON_TYPE_T + eReason) +{ + if (kalIsResetting()) + return; + + u8ResetTime = sched_clock(); + eResetReason = eReason; +} + +int glGetRstReason(void) +{ + return eResetReason; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is called for checking if connectivity chip is resetting + * + * @param None + * + * @retval TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalIsResetting(void) +{ +#if CFG_CHIP_RESET_SUPPORT + return fgIsResetting; +#else + return FALSE; +#endif +} + +#if CFG_CHIP_RESET_SUPPORT + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for + * 1. register wifi reset callback + * 2. initialize wifi reset work + * + * @param none + * + * @retval none + */ +/*----------------------------------------------------------------------------*/ +void glResetInit(struct GLUE_INFO *prGlueInfo) +{ +#if CFG_WMT_RESET_API_SUPPORT + /* 1. Register reset callback */ +#if (CFG_SUPPORT_CONNINFRA == 0) + mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_WIFI, glResetCallback); + /* 2. Initialize reset work */ + INIT_WORK(&(wifi_rst.rst_trigger_work), + mtk_wifi_trigger_reset); + INIT_WORK(&(wifi_rst.rst_work), mtk_wifi_reset); +#endif +#endif + fgIsResetting = FALSE; + wifi_rst.prGlueInfo = prGlueInfo; + +#if (CFG_SUPPORT_CONNINFRA == 1) + +#if (CFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT == 1) + fw_log_connsys_coredump_init(); +#endif + update_driver_reset_status(fgIsResetting); + KAL_WAKE_LOCK_INIT(NULL, g_IntrWakeLock, "WLAN Reset"); + init_waitqueue_head(&g_waitq_rst); + init_completion(&g_RstOffComp); + init_completion(&g_RstOnComp); + init_completion(&g_triggerComp); + wlan_reset_thread = kthread_run(wlan_reset_thread_main, + &g_rst_data, "wlan_rst_thread"); + g_SubsysRstCnt = 0; + +#endif /* CFG_SUPPORT_CONNINFRA */ +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for + * 1. deregister wifi reset callback + * + * @param none + * + * @retval none + */ +/*----------------------------------------------------------------------------*/ +void glResetUninit(void) +{ +#if CFG_WMT_RESET_API_SUPPORT + /* 1. Deregister reset callback */ +#if (CFG_SUPPORT_CONNINFRA == 0) + mtk_wcn_wmt_msgcb_unreg(WMTDRV_TYPE_WIFI); +#else + +#if (CFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT == 1) + fw_log_connsys_coredump_deinit(); +#endif + + set_bit(GLUE_FLAG_HALT_BIT, &g_ulFlag); + wake_up_interruptible(&g_waitq_rst); +#endif +#endif +} +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is called for generating reset request to WMT + * + * @param None + * + * @retval None + */ +/*----------------------------------------------------------------------------*/ +void glSendResetRequest(void) +{ +#if CFG_WMT_RESET_API_SUPPORT + + /* WMT thread would trigger whole chip reset itself */ +#endif +} + +u_int8_t glResetTrigger(struct ADAPTER *prAdapter, + uint32_t u4RstFlag, const uint8_t *pucFile, uint32_t u4Line) +{ + u_int8_t fgResult = TRUE; + uint16_t u2FwOwnVersion; + uint16_t u2FwPeerVersion; +#if (CFG_SUPPORT_CONNINFRA == 1) + struct mt66xx_chip_info *prChipInfo; +#endif + dump_stack(); + if (kalIsResetting()) + return fgResult; + + fgIsResetting = TRUE; +#if (CFG_SUPPORT_CONNINFRA == 1) + update_driver_reset_status(fgIsResetting); +#endif +#if (CFG_SUPPORT_CONNINFRA == 0) + if (eResetReason != RST_BT_TRIGGER) + DBGLOG(INIT, STATE, "[SER][L0] wifi trigger eResetReason=%d\n", + eResetReason); + else + DBGLOG(INIT, STATE, "[SER][L0] BT trigger\n"); +#endif + +#if CFG_WMT_RESET_API_SUPPORT + if (u4RstFlag & RST_FLAG_DO_CORE_DUMP) + if (glIsWmtCodeDump()) + DBGLOG(INIT, WARN, "WMT is code dumping !\n"); +#endif + if (prAdapter == NULL) + prAdapter = wifi_rst.prGlueInfo->prAdapter; +#if (CFG_SUPPORT_CONNINFRA == 1) + prChipInfo = prAdapter->chip_info; +#endif + u2FwOwnVersion = prAdapter->rVerInfo.u2FwOwnVersion; + u2FwPeerVersion = prAdapter->rVerInfo.u2FwPeerVersion; + + DBGLOG(INIT, ERROR, + "Trigger chip reset in %s line %u! Chip[%04X E%u] FW Ver DEC[%u.%u] HEX[%x.%x], Driver Ver[%u.%u]\n", + pucFile, u4Line, MTK_CHIP_REV, + wlanGetEcoVersion(prAdapter), + (uint16_t)(u2FwOwnVersion >> 8), + (uint16_t)(u2FwOwnVersion & BITS(0, 7)), + (uint16_t)(u2FwOwnVersion >> 8), + (uint16_t)(u2FwOwnVersion & BITS(0, 7)), + (uint16_t)(u2FwPeerVersion >> 8), + (uint16_t)(u2FwPeerVersion & BITS(0, 7))); + + prAdapter->u4HifDbgFlag |= DEG_HIF_DEFAULT_DUMP; + halPrintHifDbgInfo(prAdapter); + +#if CFG_WMT_RESET_API_SUPPORT +#if (CFG_SUPPORT_CONNINFRA == 0) + wifi_rst.rst_trigger_flag = u4RstFlag; + schedule_work(&(wifi_rst.rst_trigger_work)); +#else + if (u4RstFlag & RST_FLAG_DO_CORE_DUMP) + g_fgRstRecover = FALSE; + else + g_fgRstRecover = TRUE; + + if (u4RstFlag & RST_FLAG_DO_WHOLE_RESET) { + if (prChipInfo->trigger_wholechiprst) + prChipInfo->trigger_wholechiprst(g_reason); + } else { + if (prChipInfo->triggerfwassert) + prChipInfo->triggerfwassert(); + } +#endif /*end of CFG_SUPPORT_CONNINFRA == 0*/ + +#else + wifi_rst.prGlueInfo = prAdapter->prGlueInfo; + schedule_work(&(wifi_rst.rst_work)); +#endif + + return fgResult; +} + + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is called for wifi reset + * + * @param skb + * info + * + * @retval 0 + * nonzero + */ +/*----------------------------------------------------------------------------*/ +static void mtk_wifi_reset_main(struct RESET_STRUCT *rst) +{ + u_int8_t fgResult = FALSE; + int32_t ret; +#if CFG_WMT_RESET_API_SUPPORT + /* wlanOnAtReset(); */ + ret = wifi_reset_end(rst->rst_data); +#if (CFG_SUPPORT_CONNINFRA == 1) + update_driver_reset_status(fgIsResetting); + if (g_IsWholeChipRst == TRUE) { + g_IsWholeChipRst = FALSE; + g_IsWfsysBusHang = FALSE; + complete(&g_RstOnComp); + } +#endif +#else + fgResult = rst_L0_notify_step1(); + + wait_core_dump_end(); + + fgResult = rst->prGlueInfo->prAdapter->chip_info->rst_L0_notify_step2(); + +#if CFG_CHIP_RESET_HANG + if (fgIsResetHangState == SER_L0_HANG_RST_NONE) + fgIsResetHangState = SER_L0_HANG_RST_TRGING; +#endif + + if (is_bt_exist() == FALSE) + kalRemoveProbe(rst->prGlueInfo); + +#endif + if (fgSimplifyResetFlow) { + DBGLOG(INIT, INFO, "Force down the reset flag.\n"); + fgSimplifyResetFlow = FALSE; + } +#if (CFG_SUPPORT_CONNINFRA == 1) + if (ret != 0) { + g_IsWfsysResetOnFail = TRUE; + fgSimplifyResetFlow = TRUE; + DBGLOG(INIT, STATE, + "Wi-Fi reset on fail, set flag(%d).\n", + g_IsWfsysResetOnFail); + } else { + g_IsWfsysResetOnFail = FALSE; + DBGLOG(INIT, STATE, + "Wi-Fi reset on success, set flag(%d).\n", + g_IsWfsysResetOnFail); + } +#endif + DBGLOG(INIT, STATE, "[SER][L0] flow end, fgResult=%d\n", fgResult); +} + +#if CFG_WMT_RESET_API_SUPPORT +#if (CFG_SUPPORT_CONNINFRA == 0) +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is called for wifi reset + * + * @param skb + * info + * + * @retval 0 + * nonzero + */ +/*----------------------------------------------------------------------------*/ +static void mtk_wifi_reset(struct work_struct *work) +{ + struct RESET_STRUCT *rst = container_of(work, + struct RESET_STRUCT, rst_work); + mtk_wifi_reset_main(rst); +} + +static void mtk_wifi_trigger_reset(struct work_struct *work) +{ + u_int8_t fgResult = FALSE; + struct RESET_STRUCT *rst = container_of(work, + struct RESET_STRUCT, rst_trigger_work); + + fgIsResetting = TRUE; + /* Set the power off flag to FALSE in WMT to prevent chip power off + * after wlanProbe return failure, because we need to do core dump + * afterward. + */ + if (rst->rst_trigger_flag & RST_FLAG_PREVENT_POWER_OFF) + mtk_wcn_set_connsys_power_off_flag(FALSE); + + fgResult = mtk_wcn_wmt_assert_timeout(WMTDRV_TYPE_WIFI, 0x40, 0); + DBGLOG(INIT, INFO, "reset result %d, trigger flag 0x%x\n", + fgResult, rst->rst_trigger_flag); +} +#endif +/* Weak reference for those platform doesn't support wmt functions */ +int32_t __weak mtk_wcn_stp_coredump_start_get(void) +{ + return FALSE; +} + + +/*0= f/w assert flag is not set, others=f/w assert flag is set */ +int32_t glIsWmtCodeDump(void) +{ + return mtk_wcn_stp_coredump_start_get(); +} + +static void triggerHifDumpIfNeed(void) +{ + struct GLUE_INFO *prGlueInfo; + struct ADAPTER *prAdapter; + + if (fgIsResetting) + return; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wlanGetWiphy()); + if (!prGlueInfo || !prGlueInfo->u4ReadyFlag || !prGlueInfo->prAdapter) + return; + + prAdapter = prGlueInfo->prAdapter; + prAdapter->u4HifDbgFlag |= DEG_HIF_DEFAULT_DUMP; + kalSetHifDbgEvent(prAdapter->prGlueInfo); + /* wait for hif_thread finish dump */ + kalMsleep(100); +} + +#if (CFG_SUPPORT_CONNINFRA == 0) +static void dumpWlanThreadsIfNeed(void) +{ + struct GLUE_INFO *prGlueInfo; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wlanGetWiphy()); + if (!prGlueInfo || !prGlueInfo->u4ReadyFlag || !prGlueInfo->prAdapter) + return; + + if (fgIsResetting) + return; + + DBGLOG(INIT, INFO, "prGlueInfo->ulFlag: 0x%lx\n", prGlueInfo->ulFlag); + + if (prGlueInfo->main_thread) { + DBGLOG(INIT, INFO, "Show backtrace of main_thread.\n"); + kal_show_stack(prGlueInfo->prAdapter, prGlueInfo->main_thread, + NULL); + } + if (prGlueInfo->rx_thread) { + DBGLOG(INIT, INFO, "Show backtrace of rx_thread.\n"); + kal_show_stack(prGlueInfo->prAdapter, prGlueInfo->rx_thread, + NULL); + } + if (prGlueInfo->hif_thread) { + DBGLOG(INIT, INFO, "Show backtrace of hif_thread.\n"); + kal_show_stack(prGlueInfo->prAdapter, prGlueInfo->hif_thread, + NULL); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is invoked when there is reset messages indicated + * + * @param eSrcType + * eDstType + * eMsgType + * prMsgBody + * u4MsgLength + * + * @retval + */ +/*----------------------------------------------------------------------------*/ +static void glResetCallback(enum _ENUM_WMTDRV_TYPE_T eSrcType, + enum _ENUM_WMTDRV_TYPE_T eDstType, + enum _ENUM_WMTMSG_TYPE_T eMsgType, void *prMsgBody, + unsigned int u4MsgLength) +{ + switch (eMsgType) { + case WMTMSG_TYPE_RESET: + if (u4MsgLength == sizeof(enum _ENUM_WMTRSTMSG_TYPE_T)) { + enum _ENUM_WMTRSTMSG_TYPE_T *prRstMsg = + (enum _ENUM_WMTRSTMSG_TYPE_T *) prMsgBody; + + switch (*prRstMsg) { + case WMTRSTMSG_RESET_START: + DBGLOG(INIT, WARN, "Whole chip reset start!\n"); + dumpWlanThreadsIfNeed(); + triggerHifDumpIfNeed(); + fgIsResetting = TRUE; + fgSimplifyResetFlow = TRUE; + wifi_reset_start(); + break; + + case WMTRSTMSG_RESET_END: + DBGLOG(INIT, WARN, "Whole chip reset end!\n"); + wifi_rst.rst_data = RESET_SUCCESS; + fgIsResetting = FALSE; + schedule_work(&(wifi_rst.rst_work)); + break; + + case WMTRSTMSG_RESET_END_FAIL: + DBGLOG(INIT, WARN, "Whole chip reset fail!\n"); + fgIsResetting = FALSE; + wifi_rst.rst_data = RESET_FAIL; + schedule_work(&(wifi_rst.rst_work)); + break; + + default: + break; + } + } + break; + + default: + break; + } +} +#else + +void glSetRstReasonString(char *reason) +{ + g_reason = reason; +} + + +static u_int8_t glResetMsgHandler(enum ENUM_WMTMSG_TYPE eMsgType, + enum ENUM_WMTRSTMSG_TYPE MsgBody) +{ + switch (eMsgType) { + case WMTMSG_TYPE_RESET: + + switch (MsgBody) { + case WMTRSTMSG_RESET_START: + DBGLOG(INIT, WARN, "Whole chip reset start!\n"); + fgIsResetting = TRUE; + fgSimplifyResetFlow = TRUE; + wifi_reset_start(); + hifAxiRemove(); + complete(&g_RstOffComp); + break; + + case WMTRSTMSG_RESET_END: + DBGLOG(INIT, WARN, "WF reset end!\n"); + fgIsResetting = FALSE; + wifi_rst.rst_data = RESET_SUCCESS; + mtk_wifi_reset_main(&wifi_rst); + break; + + case WMTRSTMSG_RESET_END_FAIL: + DBGLOG(INIT, WARN, "Whole chip reset fail!\n"); + fgIsResetting = FALSE; + wifi_rst.rst_data = RESET_FAIL; + schedule_work(&(wifi_rst.rst_work)); + break; + case WMTRSTMSG_0P5RESET_START: + DBGLOG(INIT, WARN, "WF chip reset start!\n"); + fgIsResetting = TRUE; + fgSimplifyResetFlow = TRUE; + wifi_reset_start(); + hifAxiRemove(); + break; + default: + break; + } + break; + + default: + break; + } + + return TRUE; +} +bool glRstCheckRstCriteria(void) +{ + /* + * for those cases which need to trigger whole chip reset + * when fgIsResetting = TRUE + */ + if (g_IsSubsysRstOverThreshold || g_IsWfsysBusHang) + return FALSE; + else + return TRUE; +} +void glRstWholeChipRstParamInit(void) +{ + g_IsSubsysRstOverThreshold = FALSE; + g_SubsysRstCnt = 0; + g_IsTriggerTimeout = FALSE; + g_WholeChipRstTotalCnt++; +} +void glRstSetRstEndEvent(void) +{ + KAL_WAKE_LOCK(NULL, g_IntrWakeLock); + + set_bit(GLUE_FLAG_RST_END_BIT, &g_ulFlag); + + /* when we got interrupt, we wake up servie thread */ + wake_up_interruptible(&g_waitq_rst); + +} + +int glRstwlanPreWholeChipReset(enum consys_drv_type type, char *reason) +{ + bool bRet = 0; + struct GLUE_INFO *prGlueInfo; + struct ADAPTER *prAdapter = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wlanGetWiphy()); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(INIT, INFO, + "Enter glRstwlanPreWholeChipReset.\n"); + while (get_wifi_process_status() == 1) { + DBGLOG(REQ, WARN, + "Wi-Fi on/off process is ongoing, wait here.\n"); + msleep(100); + } + if (!get_wifi_powered_status()) { + DBGLOG(REQ, WARN, "wifi driver is off now\n"); + return bRet; + } + + triggerHifDumpIfNeed(); + + g_WholeChipRstType = type; + g_WholeChipRstReason = reason; + + if (glRstCheckRstCriteria()) { + while (kalIsResetting()) { + DBGLOG(REQ, WARN, "wifi driver is resetting\n"); + msleep(100); + } + while ((!prGlueInfo) || + (prGlueInfo->u4ReadyFlag == 0) || + (g_IsWfsysRstDone == FALSE)) { + prGlueInfo = + (struct GLUE_INFO *) wiphy_priv(wlanGetWiphy()); + DBGLOG(REQ, WARN, "wifi driver is not ready\n"); + if (g_IsWfsysResetOnFail == TRUE) { + DBGLOG(REQ, WARN, + "wifi driver reset fail, need whole chip reset.\n"); + g_IsWholeChipRst = TRUE; + return bRet; + } + msleep(100); + } + g_IsWholeChipRst = TRUE; + DBGLOG(INIT, INFO, + "Wi-Fi Driver processes whole chip reset start.\n"); + GL_RESET_TRIGGER(prGlueInfo->prAdapter, + RST_FLAG_WF_RESET); + } else { + if (g_IsSubsysRstOverThreshold) + DBGLOG(INIT, INFO, "Reach subsys reset threshold!!!\n"); + else if (g_IsWfsysBusHang) + DBGLOG(INIT, INFO, "WFSYS bus hang!!!\n"); + g_IsWholeChipRst = TRUE; +#if (CFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT == 1) + if (!prAdapter->prGlueInfo->u4ReadyFlag) + g_IsNeedWaitCoredump = TRUE; +#endif + kalSetRstEvent(); + } + wait_for_completion(&g_RstOffComp); + DBGLOG(INIT, INFO, "Wi-Fi is off successfully.\n"); + + return bRet; +} + +int glRstwlanPostWholeChipReset(void) +{ + while (get_wifi_process_status() == 1) { + DBGLOG(REQ, WARN, + "Wi-Fi on/off process is ongoing, wait here.\n"); + msleep(100); + } + if (!get_wifi_powered_status()) { + DBGLOG(REQ, WARN, "wifi driver is off now\n"); + return 0; + } + glRstSetRstEndEvent(); + DBGLOG(INIT, INFO, "Wait Wi-Fi state recover.\n"); + wait_for_completion(&g_RstOnComp); + + DBGLOG(INIT, INFO, + "Leave glRstwlanPostWholeChipReset (%d).\n", + g_IsWholeChipRst); + return 0; +} +u_int8_t kalIsWholeChipResetting(void) +{ +#if CFG_CHIP_RESET_SUPPORT + return g_IsWholeChipRst; +#else + return FALSE; +#endif +} +void glReset_timeinit(struct timeval *rNowTs, struct timeval *rLastTs) +{ + rNowTs->tv_sec = 0; + rNowTs->tv_usec = 0; + rLastTs->tv_sec = 0; + rLastTs->tv_usec = 0; +} + +bool IsOverRstTimeThreshold(struct timeval *rNowTs, struct timeval *rLastTs) +{ + struct timeval rTimeout, rTime = {0}; + bool fgIsTimeout = FALSE; + + rTimeout.tv_sec = 30; + rTimeout.tv_usec = 0; + do_gettimeofday(rNowTs); + DBGLOG(INIT, INFO, + "Reset happen time :%d.%d, last happen time :%d.%d\n", + rNowTs->tv_sec, + rNowTs->tv_usec, + rLastTs->tv_sec, + rLastTs->tv_usec); + if (rLastTs->tv_sec != 0) { + /* Ignore now time < token time */ + if (halTimeCompare(rNowTs, rLastTs) > 0) { + rTime.tv_sec = rNowTs->tv_sec - rLastTs->tv_sec; + rTime.tv_usec = rNowTs->tv_usec; + if (rLastTs->tv_usec > rNowTs->tv_usec) { + rTime.tv_sec -= 1; + rTime.tv_usec += SEC_TO_USEC(1); + } + rTime.tv_usec -= rLastTs->tv_usec; + if (halTimeCompare(&rTime, &rTimeout) >= 0) + fgIsTimeout = TRUE; + else + fgIsTimeout = FALSE; + } + DBGLOG(INIT, INFO, + "Reset rTimeout :%d.%d, calculate time :%d.%d\n", + rTimeout.tv_sec, + rTimeout.tv_usec, + rTime.tv_sec, + rTime.tv_usec); + } + return fgIsTimeout; +} +void glResetSubsysRstProcedure( + struct ADAPTER *prAdapter, + struct timeval *rNowTs, + struct timeval *rLastTs) +{ + bool fgIsTimeout; + struct mt66xx_chip_info *prChipInfo; + struct WIFI_VAR *prWifiVar = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wlanGetWiphy()); + if (prGlueInfo && prGlueInfo->u4ReadyFlag) { + prWifiVar = &prAdapter->rWifiVar; + if (prWifiVar->fgRstRecover == 1) + g_fgRstRecover = TRUE; + } +#if 0 + if (prAdapter->chip_info->checkbushang) + prAdapter->chip_info->checkbushang(FALSE); +#endif + fgIsTimeout = IsOverRstTimeThreshold(rNowTs, rLastTs); + if (g_IsWfsysBusHang == TRUE) { + if (prGlueInfo && prGlueInfo->u4ReadyFlag) { + /* dump host cr */ + if (prAdapter->chip_info->dumpBusHangCr) + prAdapter->chip_info->dumpBusHangCr(prAdapter); + glSetRstReasonString( + "fw detect bus hang"); + prChipInfo = prAdapter->chip_info; + if (prChipInfo->trigger_wholechiprst) + prChipInfo->trigger_wholechiprst(g_reason); + g_IsTriggerTimeout = FALSE; + } else { + DBGLOG(INIT, INFO, + "Don't trigger whole chip reset due to driver is not ready\n"); + } + return; + } + if (g_SubsysRstCnt > 3) { + if (fgIsTimeout == TRUE) { + /* + * g_SubsysRstCnt > 3, > 30 sec, + * need to update rLastTs, still do wfsys reset + */ +#if (CFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT == 1) + if (eResetReason >= RST_REASON_MAX) + eResetReason = 0; + if (g_fgRstRecover == TRUE) + g_fgRstRecover = FALSE; + else { + if (g_eWfRstSource == WF_RST_SOURCE_FW) + fw_log_connsys_coredump_start( + -1, NULL); + else + fw_log_connsys_coredump_start( + CONNDRV_TYPE_WIFI, + apucRstReason[eResetReason]); + } +#endif + if (prGlueInfo && prGlueInfo->u4ReadyFlag) { + glResetMsgHandler(WMTMSG_TYPE_RESET, + WMTRSTMSG_0P5RESET_START); + glResetMsgHandler(WMTMSG_TYPE_RESET, + WMTRSTMSG_RESET_END); + } else { + DBGLOG(INIT, INFO, + "Don't trigger subsys reset due to driver is not ready\n"); + } + g_SubsysRstTotalCnt++; + g_SubsysRstCnt = 1; + } else { + /*g_SubsysRstCnt > 3, < 30 sec, do whole chip reset */ + g_IsSubsysRstOverThreshold = TRUE; + /*coredump is done, no need do again*/ + g_IsTriggerTimeout = TRUE; + glSetRstReasonString( + "subsys reset more than 3 times"); + prChipInfo = prAdapter->chip_info; + if (prChipInfo->trigger_wholechiprst) + prChipInfo->trigger_wholechiprst(g_reason); + } + } else { +#if (CFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT == 1) + if (eResetReason >= RST_REASON_MAX) + eResetReason = 0; + if (g_fgRstRecover == TRUE) + g_fgRstRecover = FALSE; + else { + if (g_eWfRstSource == WF_RST_SOURCE_FW) + fw_log_connsys_coredump_start(-1, NULL); + else + fw_log_connsys_coredump_start( + CONNDRV_TYPE_WIFI, + apucRstReason[eResetReason]); + } + +#endif + if (prGlueInfo && prGlueInfo->u4ReadyFlag) { + glResetMsgHandler(WMTMSG_TYPE_RESET, + WMTRSTMSG_0P5RESET_START); + glResetMsgHandler(WMTMSG_TYPE_RESET, + WMTRSTMSG_RESET_END); + } else { + DBGLOG(INIT, INFO, + "Don't trigger subsys reset due to driver is not ready\n"); + } + g_SubsysRstTotalCnt++; + /*g_SubsysRstCnt < 3, but >30 sec,need to update rLastTs*/ + if (fgIsTimeout == TRUE) + g_SubsysRstCnt = 1; + } + if (g_SubsysRstCnt == 1) { + rLastTs->tv_sec = rNowTs->tv_sec; + rLastTs->tv_usec = rNowTs->tv_usec; + } + g_IsTriggerTimeout = FALSE; +#if (CFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT == 1) + g_eWfRstSource = WF_RST_SOURCE_NONE; +#endif +} +int wlan_reset_thread_main(void *data) +{ + int ret = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct timeval rNowTs, rLastTs; + +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + KAL_WAKE_LOCK_T *prWlanRstThreadWakeLock; + + KAL_WAKE_LOCK_INIT(NULL, + prWlanRstThreadWakeLock, "WLAN rst_thread"); + KAL_WAKE_LOCK(NULL, prWlanRstThreadWakeLock); +#endif + + glReset_timeinit(&rNowTs, &rLastTs); + + DBGLOG(INIT, INFO, "%s:%u starts running...\n", + KAL_GET_CURRENT_THREAD_NAME(), KAL_GET_CURRENT_THREAD_ID()); + + g_u4WlanRstThreadPid = KAL_GET_CURRENT_THREAD_ID(); + + while (TRUE) { + /* Unlock wakelock if hif_thread going to idle */ + KAL_WAKE_UNLOCK(NULL, prWlanRstThreadWakeLock); + /* + * sleep on waitqueue if no events occurred. Event contain + * (1) GLUE_FLAG_HALT (2) GLUE_FLAG_RST + * + */ + do { + ret = wait_event_interruptible(g_waitq_rst, + ((g_ulFlag & GLUE_FLAG_RST_PROCESS) + != 0)); + } while (ret != 0); +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + if (!KAL_WAKE_LOCK_ACTIVE(NULL, + prWlanRstThreadWakeLock)) + KAL_WAKE_LOCK(NULL, + prWlanRstThreadWakeLock); +#endif + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wlanGetWiphy()); + if (test_and_clear_bit(GLUE_FLAG_RST_START_BIT, &g_ulFlag)) { + if (KAL_WAKE_LOCK_ACTIVE(NULL, g_IntrWakeLock)) + KAL_WAKE_UNLOCK(NULL, g_IntrWakeLock); + + if (g_IsWholeChipRst) { +#if (CFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT == 1) + if (eResetReason >= RST_REASON_MAX) + eResetReason = 0; + fw_log_connsys_coredump_start( + g_WholeChipRstType, + g_WholeChipRstReason); +#endif + if (prGlueInfo && prGlueInfo->u4ReadyFlag) { + glResetMsgHandler(WMTMSG_TYPE_RESET, + WMTRSTMSG_RESET_START); + glRstWholeChipRstParamInit(); + glReset_timeinit(&rNowTs, &rLastTs); + } else { + DBGLOG(INIT, INFO, + "Don't trigger whole chip reset due to driver is not ready\n"); + } + } else { + /*wfsys reset start*/ + g_IsWfsysRstDone = FALSE; + g_SubsysRstCnt++; + DBGLOG(INIT, INFO, + "WF reset count = %d.\n", + g_SubsysRstCnt); + glResetSubsysRstProcedure(prGlueInfo->prAdapter, + &rNowTs, + &rLastTs); + /*wfsys reset done*/ + g_IsWfsysRstDone = TRUE; + } +#if (CFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT == 1) + g_IsNeedWaitCoredump = FALSE; +#endif + DBGLOG(INIT, INFO, + "Whole Chip rst count /WF reset total count = (%d)/(%d).\n", + g_WholeChipRstTotalCnt, + g_SubsysRstTotalCnt); + } + if (test_and_clear_bit(GLUE_FLAG_RST_END_BIT, &g_ulFlag)) { + if (KAL_WAKE_LOCK_ACTIVE(NULL, g_IntrWakeLock)) + KAL_WAKE_UNLOCK(NULL, g_IntrWakeLock); + DBGLOG(INIT, INFO, "Whole chip reset end start\n"); + glResetMsgHandler(WMTMSG_TYPE_RESET, + WMTRSTMSG_RESET_END); + } + if (test_and_clear_bit(GLUE_FLAG_HALT_BIT, &g_ulFlag)) { + DBGLOG(INIT, INFO, "rst_thread should stop now...\n"); + break; + } + } + +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + if (KAL_WAKE_LOCK_ACTIVE(NULL, + prWlanRstThreadWakeLock)) + KAL_WAKE_UNLOCK(NULL, prWlanRstThreadWakeLock); + KAL_WAKE_LOCK_DESTROY(NULL, + prWlanRstThreadWakeLock); +#endif + + DBGLOG(INIT, TRACE, "%s:%u stopped!\n", + KAL_GET_CURRENT_THREAD_NAME(), KAL_GET_CURRENT_THREAD_ID()); + + return 0; +} +#endif +#else +static u_int8_t is_bt_exist(void) +{ + typedef int (*p_bt_fun_type) (int); + p_bt_fun_type bt_func; + char *bt_func_name = "WF_rst_L0_notify_BT_step1"; + + bt_func = (p_bt_fun_type) kallsyms_lookup_name(bt_func_name); + if (bt_func) + return TRUE; + + DBGLOG(INIT, ERROR, "[SER][L0] %s does not exist\n", bt_func_name); + return FALSE; + +} + +static u_int8_t rst_L0_notify_step1(void) +{ + if (eResetReason != RST_BT_TRIGGER) { + typedef int (*p_bt_fun_type) (int); + p_bt_fun_type bt_func; + char *bt_func_name = "WF_rst_L0_notify_BT_step1"; + + DBGLOG(INIT, STATE, "[SER][L0] %s\n", bt_func_name); + bt_func = (p_bt_fun_type) kallsyms_lookup_name(bt_func_name); + if (bt_func) { + bt_func(0); + } else { + DBGLOG(INIT, ERROR, + "[SER][L0] %s does not exist\n", bt_func_name); + return FALSE; + } + } + + return TRUE; +} + +static void wait_core_dump_end(void) +{ +#ifdef CFG_SUPPORT_CONNAC2X + if (eResetReason == RST_OID_TIMEOUT) + return; + DBGLOG(INIT, WARN, "[SER][L0] not support..\n"); +#endif +} + +int32_t BT_rst_L0_notify_WF_step1(int32_t reserved) +{ + glSetRstReason(RST_BT_TRIGGER); + GL_RESET_TRIGGER(NULL, RST_FLAG_CHIP_RESET); + + return 0; +} +EXPORT_SYMBOL(BT_rst_L0_notify_WF_step1); + +int32_t BT_rst_L0_notify_WF_2(int32_t reserved) +{ + DBGLOG(INIT, WARN, "[SER][L0] not support...\n"); + + return 0; +} +EXPORT_SYMBOL(BT_rst_L0_notify_WF_2); + +#endif +#endif + + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_sec.o.new b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_sec.o.new new file mode 100644 index 0000000000000000000000000000000000000000..0756dd14f46395dfcdf67ae6ef41c2c0d3563772 GIT binary patch literal 19504 zcmchf3wTu3x%b!3Op+m)2POn00_s2l1c+fGL8G7q0fj@r+`y>8BqV{Pgk(%65Grbr zpi!a*!BZ?)rUfe=u+mDat@M}*6%@26*iy0WOolXGsK*|$atfO7|6lvvGei2dPcPqh z_VcX#)_YlNz3Z~~UVHC>`)23eWEh6B4nw7@h@{k-tF$FHTO(bKP$?>*%O6xHul&%y zH?LcHkXPy>!?UhixsUfKRTw(o*Eigz$^&ZGQyvk#wF4U=%KSZ+bPk(2|;XF3K+v(}- zQTd%cE?4J=)g}I5rNbYrn&S`F9rg$N+J7GEYdIL|+tn57t2r9#Ydsw5^BxNI`QHfj z6~i_QHal$PuZ8*!!d?np9&}FVjvfuAxA}wPeE#5so&Mm3tnEExtNg*(;`X3@)`LN1 ze>mto_&~6={QhoFd18+$f4s-(O$)@8j|-^sv4K8+T=&>^e{d|y_q95@`@HepW9yFh zCisu{I$DqS#(R(V#??I>w0Az<5Taf0Zp&oZ&+0Dq$O4Ie(|A9K4(RFqqwqGC}K{}KX7|@A04`u}H<>Ld+ zf1pm6`~Gf6JNw=qj8}+lkUQWhAJMZc5&3v`AP(zencW?D25XCRYt3sp=D4o~bF~F? zm5zDK!F+LEJ6{j=xnB+Sc@9M8m-EUww&oV|%K7EIj^FGLj!yFjQ?s$2?dvd~_hW7! z3dZ^#3_87Qdkojw4;;B`d(w~1>;Ck4u0br?sP*S4$J%S{?6G@0dzRMtgEg4%zQb5c zC0J)&Xs7D6(6Scj>Y&RZctDx$W@7ywpLq*;|7( zqqg_dV9my1T>oFJ&Dead>x@9}ZDRtx|Kggo=Z@2Bv3G7-p!Z)~i_Wfbf!^1#2Fnqb zUV~%*={2a-xIj+%_MYAW?m#cr9oL`AUyEzY+7F#dvwJtzBGgCXsdDY8rgVdb zkL}RKLpQ+f4^mFZ_Xh`cIlAq+TYJ*)hi|z*G#J-WS72z*G|z~hfu7WW%VY1!LEZ@+ zWhdlp$PSSmkUfy?BHJN%btU$&{;n?gsYN*dBJCRG4|Kco*LS;e+qzHp^<8IoZ|!lQ zZHMdr0IvNZN9)6ZY3_NrR;!O}>SV7i_nls)(gHU1vtHg4oVbRcLpffvt#e18H@}Wt zw~a3JMdgQLRB5t8e`9j}L0h>$c%xG9@qU8)M6$~FCmZ>G+w~Z)b834}jB9Ooj61K} zyK--F!dJt#(%1aV(Vi1D20 zjp;hpYv7v1`1L)=?GHLVhzsk$iSe+(57z|ryCBq!bubKdIWc!tp6xx4XN?N97i{c_ zMHyTsK4Lw}^A7HfMf%>D!}#6R0mjPs8G9`H+=TeGKk8SWcfJ+i-MGI_j&T-*oG$;j4Ohnt3i07ynGzmHH^$NJw?XGf@7msz?m{dx zHul7T%T<7aC&+DG?);zst>|J@?Ttlksk)EL#_iXoeoG06RVv{!Y z4pH;E4OeSG4Jqh}b-mhaaQ&-=p)WWdSo6x$)-wci;n8~$rQC?o6Jw6c|F0O&eD$xz z=s}ELiP74-aSVChU7-q+W3Z0mW$a?n6`qG~%)JZa=EAseoQ@y{C;H8O9qVJijU;2t zz~n^Rz!3wJjKPL0PN|q=!!|H6@w&vRi3Wz=mY{3{Da=jI!P#X`Q;CT;pny`bgOHsI zm$?C8eC%Q3Bkvk{Mra z977rytFn?~5bB_8W)PK2YmiBbt~gR+u*89ISq@uRt4}OFB+@XgLnBR7yhOT{$Vekq z4uhAB3+qUUh)P`=5m>`;!D5b_EqL5N!qy2EF)T0P}dQ_|E z()g%WAx@A^F$jngbziX7G9sOw?xaN>!wh4s;;rv8*!O8eX%@lgZpv9REUS+Ij22NFU+F&|eiDHROS&(T=Y`V(I)g!}5Rl-UB#gSn`6`{z$k04Ay8uS_d z7)2_9tr!Nl0#_F1J8a$g0-(qKf zf|T4B7L9@-jmu%8*PAdo8>| zkT^bmR*n&6wMoWn&>C+T3@-z#=m5l5VIMNDdNuS6@efexsNT>88Gj!B7;mtGWaJp+ z(MXUwI~IB!q?T^i5`xsyIxQhcE$z_~g4EKxkQn4q-PR>}Xu>$F=aA9m;_Ube9?v1# z!FpMpWrXPzv!OS%SU~X$_UkO8YM|%~Tena=uB|NlBZ$MUruZk;8nZEX*cdkY1p_cj zhE0qJ1u2hGcaFtUo`__(g|nB=qWAx>Rc>uAvc&$2Ssjg6$8L4b(w1MldQXRO@WT7Hl+tuZ~x5L25?tt!cp4^ZR z0&SGJF2w#Ep%-Tbqie>U;YgZQIH z^TgQ;?=B=`vhf(bZ$$m6mNJbe531$4Lnmx5==ftex>^`W$-ujS8_@Kq8f284ReI1r z-X4wV#&4}E$IO93svAqEayWUBj2VX6rllCiHXBhRj#&Fa{JqS$oo(SY4M$Gl+PD?w zCZu#ddN=9OGxE)`yGf76&tWyk&a|GSw;sEj433>q#F3k$eLsebMy7I#N)3Yz_>jJW zS{KuelwQ--O{?{5X6hph{3>PtYM8rI2ap8hs8u^30( zXBp72?@(LVYif~?<26K=yAiGZl~(9<`uoH5G0uhElQC zRPf9jJ_djC(FeICWh`P9jZ2_0B%oa6hx6=OWw{Mf8N3P^Ee}PxEkiy--xXK;`>R*8 z(yzbRU;Q$BdG}lW)G7y~7^4=k1>;YjC*UtmH3*rRlU7t$)mHebmrrVHXl|^mp0vEW zvA())QdMK^%Ie0ZNtF#NmNY|x*Tj1eLKi< zTfpJqHZTeFgKT#vNc%33?d<^vgL}okPvnoE_8=gN$RO z&<(O&n#dW#VquBc%SEmMZB6W19de^UZbwW_i)hw_HLb|8_iZ3sZ5MV3J3-FZW|6lD zxecMeU+gnRnv9OQXc1-if*(bs{j&nvPIWIZh)<6Hx>Tq{VwHjw>n7kdZDb~b}7$Biic zwt;MCC#cVF(eD8VLBAK|xa<@AOCbICgRJK$$a>C#tp6Oyc$D4L+l3C0{dI|)BFqI@ zZWhRLd7{r37K1ETDsq*u17x{Qkma_B-Y?t5Yk`|Evy2nD3DEE{fgaPqkzg+91m}pH57J%^vW6;YYNraIdgScue>{$oc{x>pLUz1(46ym=|oAt_FvI9JdsZ zEpUHGIR|9PT#!A>2U)HdJ&5iyqz!s2G)B$oTw}70I!ysc1fb{21hI($r*%v2Bc^XK+ zVvv62B6By*`r1K`Ne4*(Eg<{8O=NC@ZQs3*F5C;>4Sou;stX{iwqu*ZVd8d|p=NON z2YNsb=QNP3Ay;JXQf(V_mE5dufoU_yD*Yg<+y$~qZctg}QIJ)g09n;Zk-68jeWJ&b zTh6^O>32PbaVc)hF{l%Njq?K|dnbm5{fn3UXvnMS=QCm_F8k)n3IAz7 z@E^01$Ig8q?#XR8=AYg8Ut7LDxj1p=AAYfC$>|qHKKr`kgC|;lxB1V_k4^vX&GFA% z_^fHzPuATw?b6?`zhzg=^0hy>tLnWC=RO`Z&%5ZUDVL`WytA_8?eB~ky=JO0s^!5G z>ZV(_A0JnkcXdp!|KQdw4>=^N!;<5PDh6fJ0Y_tZ7BfBWU5lWcuoYg|!xN5LZ_o`3x1-|W9H>DQ$* zu5jIcGT~=g?N7gX_fN0%9UJ^o&%V76)qdmOod3S+-s&I!alp^(Uu#SG^qw=sBBj?{VJ*Rfb9mVVKUFH4uH#c?s^heL{`t>_U4u1YgZy+hb zcHzpgSES6nacXw;oww$%{d!Z~Q~&;0`;ULHd*{1v9qRhyN1^u<;`+{wA3b8o>>IA} zRNP*achAa(nkOIM(DuXcJ>!4-jRX7t@cZAL91wHgw%liyGU;#zYA$A@(&=bLGmCSLUKWW8_11+ z3epZF)-?s`4y5%+Iq>-&_%srIaJf~uov2kv$C3DSb{EnUNLL`yMjytyPV#sqttN}^ zYA^|j<+xw{spMIAA`<(03TZVG{nC)GMEVWVV@R(evEQuw>q0)4PCzQVwWh&c(OB(X z-OxO}OwBKza_v=FWizT~czxB4Wo7ey^UBIn(-vG$#|oe2+33dm#OlVS6_wQ}l$$zj z{({+MWks{*Hk6fBR;G@*bL@f}rmM0!4XfNMnk#GERSnfmY{6aG(BwmjvU=ad)ZEn6 z)Cm*PZd}lETk*m>Q}4|(3pCVKSlDe8u79T~{XN^s6f8W@8mmy~FqL0lKTspJwCS)9EBKlH?`p-9XUhSrB!s{NsPioj?R`6 zoZ{%h^kfJqTnumokZlFp%q;%ug9ST~P$jWhXG;mresq=e+@sB`SRYi4#Dp2DP&CQ| zagJ6k;=|WAGt1|xPt9xw7Zj4ApWSsaKmMLTGSoso64q$Pg?xtNlL@ri3xE7bCy@+Q z%xlp{(5ArZ($-S0Wj@1R(X(Bf!$U?D_pXL2h^~)Y`lwOlPX4r3E#l_fqYEtJ zetV6XjcD%I%$k&d=rD4bLD5k)gqa7EO z0^77>DR=Q^jp0$ugLSiZEaEc?_wQJ3+_amH;oej9=x7!bIXYWP@Z66cI(p`5b3VaM zH|Cc+UwTGOH68P{wSX|K{BWd?h_#Sb?%54h5~-#n+L1edLls4=MbXwySYy;iMbd@Q zTCUVv2ivgg7{isfLUjTO3y-^hGsf`fbwK6R1r`yeHQY4CS=zdo$kW+Ug1g@6A){xV zHs=%VI$OX!GCiXf939I|E3r*yOCyfq$Rafsvc^{JSWI;2Y#~viD=&@|53ip{@uEoa zMJ&!I5sWlp#>V$}`tU=QW`-N7F?_1f%4Zd_nfyqZ@S019g-;wf1Bf{~ zTS)j!t<^Lm>C~#l#1@?`C3q8w9%*{+(dKYuR2|f+@TKqs#7{3)u_8MXul@j^LwNNE zcn^whf}U<|4mUwnj#h=6m;T^o&|B zbmXHCR797~mPQ=I>xGW{wY4x}4F?-(uZZpK(~iZ&L7gok%%;Ojh~h{c&0->5XG;m* zWTSgS&so}>Pk42x9<#wY88qt+S=X z8B&3>_}_; z&5Ct86fJ3JQM!3cGjpB{a8sdq7#IZ#)0=Xa@}G2ZeFm^J=2|?nVsp;A#+CS zFgxHa%|3>1PAVom`pomznX}(7;4HfK$SF5-HJktzX&@E#rG(wJA3?n8i)9ovh5PXxF8U z6)WIt)>GF|8Ex}6FR6zW4M&=)XsoDTMwMCOVhPo&Oq?StshpV3&BQh@H`pD%=o~VOu z@tBB2|7gEl$kt)C>w&^5LmTT`XkJjYt7W^fpWhQs^RA?wqHH%HAKj0fX{ZyOXFoUw zRzG-ex9Ub#)egmbvZ#WVZ2@diYSn^3_M&5~kNvaiTY@~xSfL-pYUMXK>#+KJClt~3 zrO!ir(6K%arB&b8kY{~YA@T5yQtCg=to}+41#GmZZxb@Q@ht=+C$kFZApj~Tz zquYHLeo@7hJ5A|LpjDq`d$ONjAOm}O%NS+jJHzO9Q}WDlV}D&pR)3$1Dub-DXDa1p zMh>g$XCX(|=SF?3hxH9cvg+H9yj2ESm4^DtnUTY?y#bkdu0tMe@Ov|A-e_ZbR|x2% zAj@pelCAoF3kBA^*V0$QZ@eXdmS2+T7q)c3?~||;@uPoKIBFkWuKLlyaOioCvA^s; z$HY3^^^69tQ}1M zI-b~3vag@)3@<>_pN|L8{(Jk$++|1G?cqU)9(|5y0)873cGbNLyJ~fUo^wu1D`c~E z@ds>p#dxv59p4tsgKNaVd`$AAy{IOFjgV^Sx8-d4Ye zGS?~JhFbCnzM#+&MCZ$!Vw5oo4a%(51cbArcjb(WM7unrM9t^@y16BcS zEw~Ae67{w&dhdAAhP2;CF{}TM?k~1@llyyQ_g75muP~p?5R!g8G54L;0|AM>ZS;=Q z%Il{vJLWqEHvl)T17w;oU04N<#C6?A;zJW(&yl=N#NZOvMxtE1kk<$5`O7-$c|D-) zB_Z?tr|c3AA))7aPyIgOOQPrbPQ63OeMk&qaFXffH!zZC1Bt3s4A#VD!cin*87p?~ z3FwzATp;B4CF<`It`xQlc`nfI7w!?hBs?K}Psp1A{dpf@Jp92lc^#RC-MX+u^rgab z(XSBRPokcO#QunIqu9SG_MIX>EAlHM|4P^+{7h&d7RJFJ+>>KSw8PI1jFaaXnN2cY zA@`S*`2%(O^YuSvzW*m57H$!KSI93EwDULUEcX_P^p5bCB<#NO_ z!v%)@8%RP<7Ws0KQ$@}cdAi6&B4|#xuYH+A*#qwheW>Se!pVuk$-=3^nZkL(BH-!XVrN~o+*9&J0=L_}y3i-t%R|{7Nn}zoX*9#vJJ|TQc__Xjj;SYtc2oDM07XDfo z5`HZFOn6>svzh%%6ebJx{R}>-B2N@f7ETq;6wVVC3GWbA3YQD@eGc{BE%G|y2H_^* zR^bleZs7~UmxTv}M})_Pr-UKl$HLEq=Y=+08#urEehBhkd{Nf-Loik3iNeXkslu7U zdBP&$9l}bXb>D0f`EKDl;RfL*;a1@e;cnpz!k2{yghzzOg{Ooe;m5+ygy)4exi8`0 z66<~^3r7f3g%gF7g;Rwyh4X|(!aIbO!sWsy;oZV@!VSVr!mYv`!rj6bgf9yZ2#*Ml z3r`7qgntlzA?y>z^L~bT9wfX}I7&EPm?gYcI72vBSRlMj$baa?dTWJu3Hgt-s9!65 zNVrk>r10CqXNBJv{#f`k;p@V;g{Ooe;m5+yg#5>2Y~RNFBbX>m7LE|63i(gJ=r>t7 zRXAHXU&!xX^eY$E2))7iq!xXNjCAEEbjutAzTw6aIW3!FJXN+k|@G z0R1;a-Y$Gb_`Hz+%!=h-5gro$Lij6Tx9}t3e+&OCjN$Vv>PZj|77iDV7G5cwBIJ+5 zV(>8AF6xJDxqCeRp^LMb6_46$3*7NKdvGY9-?fN+tb{!|=qhjZe(`d(Oq4+-sSaeCd F{|DzCfT#cf literal 0 HcmV?d00001 diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_sys.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_sys.c new file mode 100644 index 0000000000000..62229ee690b5c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_sys.c @@ -0,0 +1,568 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +/* + ** Id: /os/linux/gl_sys.c + */ + +/*! \file "gl_sys.c" + * \brief This file defines the interface which can interact with users + * in /sys fs. + * + * Detail description. + */ + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" +#include "gl_os.h" +#include "gl_kal.h" +#include "debug.h" +#include "wlan_lib.h" +#include "debug.h" +#include "wlan_oid.h" +#include +#include +#include +#include +#include +#include + +#if WLAN_INCLUDE_SYS + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define MTK_INFO_MAX_SIZE 128 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +static struct GLUE_INFO *g_prGlueInfo; +static struct kobject *wifi_kobj; +static uint8_t aucMacAddrOverride[] = "FF:FF:FF:FF:FF:FF"; +static uint8_t aucDefaultFWVersion[] = "Unknown"; +static u_int8_t fgIsMacAddrOverride = FALSE; +static int32_t g_i4PM = -1; +static char acVerInfo[MTK_INFO_MAX_SIZE]; +static char acSoftAPInfo[MTK_INFO_MAX_SIZE]; + +#if BUILD_QA_DBG +static uint32_t g_u4Memdump = 3; +#else +static uint32_t g_u4Memdump = 2; +#endif + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +static ssize_t pm_show( + struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + return snprintf(buf, + sizeof(g_i4PM), + "%d", g_i4PM); +} + +static void pm_EnterCtiaMode(void) +{ + if (!g_prGlueInfo) + DBGLOG(INIT, ERROR, "g_prGlueInfo is null\n"); + else if (g_i4PM == -1) + DBGLOG(INIT, TRACE, "keep default\n"); + else { + g_prGlueInfo->prAdapter->fgEnDbgPowerMode = !g_i4PM; + nicEnterCtiaMode(g_prGlueInfo->prAdapter, + !g_i4PM, + FALSE); + } +} + +static ssize_t pm_store( + struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, + size_t count) +{ + int32_t i4Ret = 0; + + i4Ret = kstrtoint(buf, 10, &g_i4PM); + + if (i4Ret) + DBGLOG(INIT, ERROR, "sscanf pm fail u4Ret=%d\n", i4Ret); + else { + DBGLOG(INIT, INFO, + "Set PM to %d.\n", + g_i4PM); + + pm_EnterCtiaMode(); + } + + return (i4Ret == 0) ? count : 0; +} + +static ssize_t macaddr_show( + struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + return snprintf(buf, + sizeof(aucMacAddrOverride), + "%s", aucMacAddrOverride); +} + +static ssize_t macaddr_store( + struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, + size_t count) +{ + int32_t i4Ret = 0; + + i4Ret = sscanf(buf, "%18s", (uint8_t *)&aucMacAddrOverride); + + if (!i4Ret) + DBGLOG(INIT, ERROR, "sscanf mac format fail u4Ret=%d\n", i4Ret); + else { + DBGLOG(INIT, INFO, + "Set macaddr to %s.\n", + aucMacAddrOverride); + } + + fgIsMacAddrOverride = TRUE; + + return (i4Ret > 0) ? count : 0; +} + +static ssize_t wifiver_show( + struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + return snprintf(buf, + sizeof(acVerInfo), "%s", + acVerInfo); +} + +static ssize_t softap_show( + struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + return snprintf(buf, sizeof(acSoftAPInfo), "%s", acSoftAPInfo); +} + +static ssize_t memdump_show( + struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + return snprintf(buf, + sizeof(g_u4Memdump), + "%d", g_u4Memdump); +} + +static ssize_t memdump_store( + struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, + size_t count) +{ + int32_t i4Ret = 0; + + i4Ret = kstrtouint(buf, 10, &g_u4Memdump); + + if (i4Ret) + DBGLOG(INIT, ERROR, "sscanf memdump fail u4Ret=%d\n", i4Ret); + else { + DBGLOG(INIT, INFO, + "Set memdump to %d.\n", + g_u4Memdump); + } + + return (i4Ret == 0) ? count : 0; +} + + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +static struct kobj_attribute macaddr_attr + = __ATTR(mac_addr, 0664, macaddr_show, macaddr_store); + +static struct kobj_attribute wifiver_attr + = __ATTR(wifiver, 0664, wifiver_show, NULL); + +static struct kobj_attribute softap_attr + = __ATTR(softap, 0664, softap_show, NULL); + +static struct kobj_attribute pm_attr + = __ATTR(pm, 0664, pm_show, pm_store); + +static struct kobj_attribute memdump_attr + = __ATTR(memdump, 0664, memdump_show, memdump_store); + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +void sysCreateMacAddr(void) +{ + if (g_prGlueInfo) { + uint8_t rMacAddr[MAC_ADDR_LEN]; + + COPY_MAC_ADDR(rMacAddr, + g_prGlueInfo->prAdapter->rWifiVar.aucMacAddress); + + kalSnprintf(aucMacAddrOverride, + sizeof(aucMacAddrOverride), + "%pM", + MAC2STR(rMacAddr)); + + DBGLOG(INIT, TRACE, + "Init macaddr to " MACSTR ".\n", + MAC2STR(rMacAddr)); + } +} + +void sysInitMacAddr(void) +{ + int32_t i4Ret = 0; + + if (!wifi_kobj) { + DBGLOG(INIT, ERROR, "wifi_kobj is null\n"); + return; + } + + i4Ret = sysfs_create_file(wifi_kobj, &macaddr_attr.attr); + if (i4Ret) + DBGLOG(INIT, ERROR, "Unable to create macaddr entry\n"); +} + +void sysUninitMacAddr(void) +{ + if (!wifi_kobj) { + DBGLOG(INIT, ERROR, "wifi_kobj is null\n"); + return; + } + + sysfs_remove_file(wifi_kobj, &macaddr_attr.attr); +} + +void sysInitPM(void) +{ + int32_t i4Ret = 0; + + if (!wifi_kobj) { + DBGLOG(INIT, ERROR, "wifi_kobj is null\n"); + return; + } + + i4Ret = sysfs_create_file(wifi_kobj, &pm_attr.attr); + if (i4Ret) + DBGLOG(INIT, ERROR, "Unable to create macaddr entry\n"); +} + +void sysUninitPM(void) +{ + if (!wifi_kobj) { + DBGLOG(INIT, ERROR, "wifi_kobj is null\n"); + return; + } + + sysfs_remove_file(wifi_kobj, &pm_attr.attr); +} + +void sysCreateWifiVer(void) +{ +#define STR_HELPER(x) #x +#define STR(x) STR_HELPER(x) + + char aucDriverVersionStr[] = STR(NIC_DRIVER_MAJOR_VERSION) "_" + STR(NIC_DRIVER_MINOR_VERSION) "_" + STR(NIC_DRIVER_SERIAL_VERSION) "-" + DRIVER_BUILD_DATE; + uint16_t u2NvramVer = 0; + uint8_t ucOffset = 0; + + kalMemZero(acVerInfo, sizeof(acVerInfo)); + + ucOffset += kalSnprintf(acVerInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "%s\n", "Mediatek"); + + ucOffset += kalSnprintf(acVerInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "DRIVER_VER: %s\n", aucDriverVersionStr); + + if (g_prGlueInfo) + ucOffset += kalSnprintf(acVerInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "FW_VER: %s\n" + , g_prGlueInfo->prAdapter->rVerInfo.aucReleaseManifest); + else { + ucOffset += kalSnprintf(acVerInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "FW_VER: %s\n" + , aucDefaultFWVersion); + } + + if (g_prGlueInfo) { + kalCfgDataRead16(g_prGlueInfo, + OFFSET_OF(struct WIFI_CFG_PARAM_STRUCT, + u2Part1OwnVersion), &u2NvramVer); + ucOffset += kalSnprintf(acVerInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "NVRAM: 0x%x\n", u2NvramVer); + } else { + ucOffset += kalSnprintf(acVerInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "NVRAM: Unknown\n"); + } +} + +void sysInitWifiVer(void) +{ + int32_t i4Ret = 0; + + if (!wifi_kobj) { + DBGLOG(INIT, ERROR, "wifi_kobj is null\n"); + return; + } + + i4Ret = sysfs_create_file(wifi_kobj, &wifiver_attr.attr); + if (i4Ret) + DBGLOG(INIT, ERROR, "Unable to create wifiver entry\n"); + + sysCreateWifiVer(); +} + +void sysUninitWifiVer(void) +{ + if (!wifi_kobj) { + DBGLOG(INIT, ERROR, "wifi_kobj is null\n"); + return; + } + + sysfs_remove_file(wifi_kobj, &wifiver_attr.attr); +} + +void sysCreateSoftap(void) +{ + struct REG_INFO *prRegInfo = NULL; + + uint8_t ucOffset = 0; + u_int8_t fgDbDcModeEn = FALSE; + + /* Log SoftAP/hotspot information into .softap.info + * #Support wifi and hotspot at the same time? + * DualBandConcurrency=no + * # Supporting 5Ghz + * 5G=check NVRAM ucEnable5GBand + * # Max support client count + * maxClient=P2P_MAXIMUM_CLIENT_COUNT + * #Supporting android_net_wifi_set_Country_Code_Hal + * HalFn_setCountryCodeHal=yes , + * call mtk_cfg80211_vendor_set_country_code + * #Supporting android_net_wifi_getValidChannels + * HalFn_getValidChannels=yes, + * call mtk_cfg80211_vendor_get_channel_list + */ + + if (g_prGlueInfo) { + prRegInfo = &(g_prGlueInfo->rRegInfo); +#if CFG_SUPPORT_DBDC + fgDbDcModeEn = g_prGlueInfo->prAdapter->rWifiVar.fgDbDcModeEn; +#endif + } + + kalMemZero(acSoftAPInfo, sizeof(acSoftAPInfo)); + + ucOffset = 0; + + if (g_prGlueInfo) { + ucOffset += kalSnprintf(acSoftAPInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "DualBandConcurrency=%s\n" + , fgDbDcModeEn ? "yes" : "no"); + } else + ucOffset += kalSnprintf(acSoftAPInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "DualBandConcurrency=no\n"); + + if (prRegInfo) + ucOffset += kalSnprintf(acSoftAPInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "5G=%s\n", prRegInfo->ucEnable5GBand ? "yes" : "no"); + else + ucOffset += kalSnprintf(acSoftAPInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "5G=yes\n"); + + ucOffset += kalSnprintf(acSoftAPInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "maxClient=%d\n", P2P_MAXIMUM_CLIENT_COUNT); + + ucOffset += kalSnprintf(acSoftAPInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "HalFn_setCountryCodeHal=%s\n", "yes"); + + ucOffset += kalSnprintf(acSoftAPInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "HalFn_getValidChannels=%s\n", "yes"); + + ucOffset += kalSnprintf(acSoftAPInfo + ucOffset + , MTK_INFO_MAX_SIZE - ucOffset + , "DualInterface=%s\n", "yes"); +} + +void sysInitSoftap(void) +{ + int32_t i4Ret = 0; + + if (!wifi_kobj) { + DBGLOG(INIT, ERROR, "wifi_kobj is null\n"); + return; + } + + i4Ret = sysfs_create_file(wifi_kobj, &softap_attr.attr); + if (i4Ret) + DBGLOG(INIT, ERROR, "Unable to create softap entry\n"); + + sysCreateSoftap(); +} + +void sysUninitSoftap(void) +{ + if (!wifi_kobj) { + DBGLOG(INIT, ERROR, "wifi_kobj is null\n"); + return; + } + + sysfs_remove_file(wifi_kobj, &softap_attr.attr); +} + +void sysInitMemdump(void) +{ + int32_t i4Ret = 0; + + if (!wifi_kobj) { + DBGLOG(INIT, ERROR, "wifi_kobj is null\n"); + return; + } + + i4Ret = sysfs_create_file(wifi_kobj, &memdump_attr.attr); + if (i4Ret) + DBGLOG(INIT, ERROR, "Unable to create softap entry\n"); +} + +void sysUninitMemdump(void) +{ + if (!wifi_kobj) { + DBGLOG(INIT, ERROR, "wifi_kobj is null\n"); + return; + } + + sysfs_remove_file(wifi_kobj, &memdump_attr.attr); +} + +int32_t sysCreateFsEntry(struct GLUE_INFO *prGlueInfo) +{ + DBGLOG(INIT, TRACE, "[%s]\n", __func__); + + g_prGlueInfo = prGlueInfo; + + sysCreateMacAddr(); + pm_EnterCtiaMode(); + sysCreateWifiVer(); + sysCreateSoftap(); + + return 0; +} + +int32_t sysRemoveSysfs(void) +{ + g_prGlueInfo = NULL; + + return 0; +} + +int32_t sysInitFs(void) +{ + DBGLOG(INIT, TRACE, "[%s]\n", __func__); + + wifi_kobj = kobject_create_and_add("wifi", NULL); + kobject_get(wifi_kobj); + kobject_uevent(wifi_kobj, KOBJ_ADD); + + sysInitMacAddr(); + sysInitWifiVer(); + sysInitSoftap(); + sysInitPM(); + sysInitMemdump(); + + return 0; +} + +int32_t sysUninitSysFs(void) +{ + DBGLOG(INIT, TRACE, "[%s]\n", __func__); + + sysUninitMemdump(); + sysUninitPM(); + sysUninitSoftap(); + sysUninitWifiVer(); + sysUninitMacAddr(); + + kobject_put(wifi_kobj); + kobject_uevent(wifi_kobj, KOBJ_REMOVE); + wifi_kobj = NULL; + + return 0; +} + +void sysMacAddrOverride(uint8_t *prMacAddr) +{ + DBGLOG(INIT, TRACE, + "Override=%d\n", fgIsMacAddrOverride); + + if (!fgIsMacAddrOverride) + return; + + wlanHwAddrToBin( + aucMacAddrOverride, + prMacAddr); + + DBGLOG(INIT, TRACE, + "Init macaddr to " MACSTR ".\n", + MAC2STR(prMacAddr)); +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_vendor.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_vendor.c new file mode 100644 index 0000000000000..14e048ba6b47b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_vendor.c @@ -0,0 +1,1981 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** gl_vendor.c + ** + ** + */ + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "gl_os.h" +#include "debug.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "precomp.h" +#include +#include +#include +#include "gl_cfg80211.h" +#include "gl_vendor.h" +#include "wlan_oid.h" + +#if KERNEL_VERSION(3, 16, 0) <= LINUX_VERSION_CODE + +/******************************************************************************* + * 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 + ******************************************************************************* + */ +uint8_t g_GetResultsBufferedCnt; +uint8_t g_GetResultsCmdCnt; + +static struct nla_policy nla_parse_wifi_policy[ + WIFI_ATTRIBUTE_ROAMING_STATE + 1] = { + [WIFI_ATTRIBUTE_BAND] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_NUM_CHANNELS] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_CHANNEL_LIST] = {.type = NLA_UNSPEC}, + + [WIFI_ATTRIBUTE_NUM_FEATURE_SET] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_FEATURE_SET] = {.type = NLA_UNSPEC}, + [WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI] = {.type = NLA_UNSPEC}, + [WIFI_ATTRIBUTE_NODFS_VALUE] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_COUNTRY_CODE] = {.type = NLA_STRING}, + + [WIFI_ATTRIBUTE_MAX_RSSI] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_MIN_RSSI] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_RSSI_MONITOR_START] = {.type = NLA_U32}, + + [WIFI_ATTRIBUTE_ROAMING_CAPABILITIES] = {.type = NLA_UNSPEC}, + [WIFI_ATTRIBUTE_ROAMING_BLACKLIST_NUM] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_ROAMING_BLACKLIST_BSSID] = {.type = NLA_UNSPEC}, + [WIFI_ATTRIBUTE_ROAMING_WHITELIST_NUM] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_ROAMING_WHITELIST_SSID] = {.type = NLA_UNSPEC}, + [WIFI_ATTRIBUTE_ROAMING_STATE] = {.type = NLA_U32}, +}; + +static struct nla_policy nla_parse_offloading_policy[ + MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC + 1] = { + [MKEEP_ALIVE_ATTRIBUTE_ID] = {.type = NLA_U8}, + [MKEEP_ALIVE_ATTRIBUTE_IP_PKT] = {.type = NLA_UNSPEC}, + [MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN] = {.type = NLA_U16}, + [MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR] = {.type = NLA_UNSPEC}, + [MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR] = {.type = NLA_UNSPEC}, + [MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC] = {.type = NLA_U32}, +}; + +static struct nla_policy nla_get_preferred_freq_list_policy[ + WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_MAX] = { + [WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_IFACE_TYPE] = {.type = NLA_U32}, +}; + +static const struct nla_policy nla_get_acs_policy[ + WIFI_VENDOR_ATTR_ACS_MAX + 1] = { + [WIFI_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 }, + [WIFI_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG }, + [WIFI_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG }, + [WIFI_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG }, + [WIFI_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 }, + [WIFI_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_UNSPEC }, + [WIFI_VENDOR_ATTR_ACS_FREQ_LIST] = { .type = NLA_UNSPEC }, +}; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +int mtk_cfg80211_NLA_PUT(struct sk_buff *skb, int attrtype, + int attrlen, const void *data) +{ + if (unlikely(nla_put(skb, attrtype, attrlen, data) < 0)) + return 0; + return 1; +} + +int mtk_cfg80211_nla_put_type(struct sk_buff *skb, + enum ENUM_NLA_PUT_DATE_TYPE type, int attrtype, + const void *value) +{ + u8 u8data = 0; + u16 u16data = 0; + u32 u32data = 0; + u64 u64data = 0; + + switch (type) { + case NLA_PUT_DATE_U8: + u8data = *(u8 *)value; + return mtk_cfg80211_NLA_PUT(skb, attrtype, sizeof(u8), + &u8data); + case NLA_PUT_DATE_U16: + u16data = *(u16 *)value; + return mtk_cfg80211_NLA_PUT(skb, attrtype, sizeof(u16), + &u16data); + case NLA_PUT_DATE_U32: + u32data = *(u32 *)value; + return mtk_cfg80211_NLA_PUT(skb, attrtype, sizeof(u32), + &u32data); + case NLA_PUT_DATE_U64: + u64data = *(u64 *)value; + return mtk_cfg80211_NLA_PUT(skb, attrtype, sizeof(u64), + &u64data); + default: + break; + } + + return 0; +} + +int mtk_cfg80211_vendor_get_channel_list(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + struct GLUE_INFO *prGlueInfo; + struct nlattr *attr; + uint32_t band = 0; + uint8_t ucNumOfChannel, i, j; + struct RF_CHANNEL_INFO *aucChannelList; + uint32_t num_channels; + uint32_t channels[MAX_CHN_NUM]; + struct sk_buff *skb; + uint16_t u2CountryCode; + + ASSERT(wiphy && wdev); + if ((data == NULL) || !data_len) + return -EINVAL; + + DBGLOG(REQ, TRACE, "data_len=%d, iftype=%d\n", data_len, wdev->iftype); + + attr = (struct nlattr *)data; + if (attr->nla_type == WIFI_ATTRIBUTE_BAND) + band = nla_get_u32(attr); + + DBGLOG(REQ, TRACE, "Get channel list for band: %d\n", band); + + prGlueInfo = wlanGetGlueInfo(); + if (!prGlueInfo) + return -EFAULT; + + aucChannelList = (struct RF_CHANNEL_INFO *) + kalMemAlloc(sizeof(struct RF_CHANNEL_INFO)*MAX_CHN_NUM, + VIR_MEM_TYPE); + if (!aucChannelList) { + DBGLOG(REQ, ERROR, + "Can not alloc memory for rf channel info\n"); + return -ENOMEM; + } + kalMemZero(aucChannelList, + sizeof(struct RF_CHANNEL_INFO)*MAX_CHN_NUM); + + switch (band) { + case 1: /* 2.4G band */ + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_2G4, TRUE, + MAX_CHN_NUM, &ucNumOfChannel, aucChannelList); + break; + case 2: /* 5G band without DFS channels */ + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_5G, TRUE, + MAX_CHN_NUM, &ucNumOfChannel, aucChannelList); + break; + case 4: /* 5G band DFS channels only */ + rlmDomainGetDfsChnls(prGlueInfo->prAdapter, MAX_CHN_NUM, + &ucNumOfChannel, aucChannelList); + break; + default: + ucNumOfChannel = 0; + break; + } + + kalMemZero(channels, sizeof(channels)); + u2CountryCode = prGlueInfo->prAdapter->rWifiVar.u2CountryCode; + for (i = 0, j = 0; i < ucNumOfChannel; i++) { + /* We need to report frequency list to HAL */ + channels[j] = + nicChannelNum2Freq(aucChannelList[i].ucChannelNum) / 1000; + if (channels[j] == 0) + continue; + else if ((u2CountryCode == COUNTRY_CODE_TW) && + (channels[j] >= 5180 && channels[j] <= 5260)) { + /* Taiwan NCC has resolution to follow FCC spec + * to support 5G Band 1/2/3/4 + * (CH36~CH48, CH52~CH64, CH100~CH140, CH149~CH165) + * Filter CH36~CH52 for compatible with some old + * devices. + */ + DBGLOG(REQ, TRACE, "skip channels[%d]=%d, country=%d\n", + j, channels[j], u2CountryCode); + continue; + } else { + DBGLOG(REQ, TRACE, "channels[%d] = %d\n", j, + channels[j]); + j++; + } + } + num_channels = j; + DBGLOG(REQ, INFO, "Get channel list for band: %d, num_channels=%d\n", + band, num_channels); + + kalMemFree(aucChannelList, VIR_MEM_TYPE, + sizeof(struct RF_CHANNEL_INFO)*MAX_CHN_NUM); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(channels)); + if (!skb) { + DBGLOG(REQ, ERROR, "Allocate skb failed\n"); + return -ENOMEM; + } + + if (unlikely(nla_put_u32(skb, WIFI_ATTRIBUTE_NUM_CHANNELS, + num_channels) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put(skb, WIFI_ATTRIBUTE_CHANNEL_LIST, + (sizeof(uint32_t) * num_channels), channels) < 0)) + goto nla_put_failure; + + return cfg80211_vendor_cmd_reply(skb); + +nla_put_failure: + kfree_skb(skb); + return -EFAULT; +} + +int mtk_cfg80211_vendor_set_country_code(struct wiphy + *wiphy, struct wireless_dev *wdev, const void *data, + int data_len) +{ + struct GLUE_INFO *prGlueInfo; + uint32_t rStatus; + uint32_t u4BufLen; + struct nlattr *attr; + uint8_t country[2] = {0}; + + ASSERT(wiphy && wdev); + if ((data == NULL) || (data_len == 0)) + return -EINVAL; + + DBGLOG(REQ, INFO, + "vendor command: data_len=%d, iftype=%d\n", data_len, + wdev->iftype); + + attr = (struct nlattr *)data; + if (attr->nla_type == WIFI_ATTRIBUTE_COUNTRY_CODE) { + country[0] = *((uint8_t *)nla_data(attr)); + country[1] = *((uint8_t *)nla_data(attr) + 1); + } + + DBGLOG(REQ, INFO, "Set country code: %c%c\n", country[0], + country[1]); + + prGlueInfo = wlanGetGlueInfo(); + if (!prGlueInfo) + return -EFAULT; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetCountryCode, + country, 2, FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "Set country code error: %x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +int mtk_cfg80211_vendor_set_scan_mac_oui(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct nlattr *attr; + uint32_t i = 0; + struct PARAM_BSS_MAC_OUI rParamMacOui; + uint32_t u4BufLen = 0; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = NULL; + + ASSERT(wiphy); + ASSERT(wdev); + + if (data == NULL || data_len <= 0) { + log_dbg(REQ, ERROR, "data error(len=%d)\n", data_len); + return -EINVAL; + } + + prGlueInfo = wlanGetGlueInfo(); + if (!prGlueInfo) { + log_dbg(REQ, ERROR, "Invalid glue info\n"); + return -EFAULT; + } + prNetDevPrivate = + (struct NETDEV_PRIVATE_GLUE_INFO *) netdev_priv(wdev->netdev); + if (!prNetDevPrivate) { + log_dbg(REQ, ERROR, "Invalid net device private\n"); + return -EFAULT; + } + rParamMacOui.ucBssIndex = prNetDevPrivate->ucBssIdx; + + attr = (struct nlattr *)data; + kalMemZero(rParamMacOui.ucMacOui, MAC_OUI_LEN); + if (nla_type(attr) != WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI) { + log_dbg(REQ, ERROR, "Set MAC oui type error(%u)\n", + nla_type(attr)); + return -EINVAL; + } + + if (nla_len(attr) != MAC_OUI_LEN) { + log_dbg(REQ, ERROR, "Set MAC oui length error(%u), %u needed\n", + nla_len(attr), MAC_OUI_LEN); + return -EINVAL; + } + + for (i = 0; i < MAC_OUI_LEN; i++) + rParamMacOui.ucMacOui[i] = *((uint8_t *)nla_data(attr) + i); + + log_dbg(REQ, INFO, "Set MAC oui: %02x-%02x-%02x\n", + rParamMacOui.ucMacOui[0], rParamMacOui.ucMacOui[1], + rParamMacOui.ucMacOui[2]); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetScanMacOui, + &rParamMacOui, sizeof(rParamMacOui), + FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + log_dbg(REQ, ERROR, "Set MAC oui error: 0x%X\n", rStatus); + return -EFAULT; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is to answer FWK that we can support FW Roaming. + * + * \param[in] wiphy wiphy for AIS STA. + * + * \param[in] wdev (not used here). + * + * \param[in] data (not used here). + * + * \param[in] data_len (not used here). + * + * \retval TRUE Success. + * + * \note we use cfg80211_vendor_cmd_reply to send the max number of our + * blacklist and whiltlist directly without receiving any data + * from the upper layer. + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_vendor_get_roaming_capabilities(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + uint32_t maxNumOfList[2] = { MAX_FW_ROAMING_BLACKLIST_SIZE, + MAX_FW_ROAMING_WHITELIST_SIZE }; + struct sk_buff *skb; + + ASSERT(wiphy); + + DBGLOG(REQ, INFO, + "Get roaming capabilities: max black/whitelist=%d/%d", + maxNumOfList[0], maxNumOfList[1]); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(maxNumOfList)); + if (!skb) { + DBGLOG(REQ, ERROR, "Allocate skb failed\n"); + return -ENOMEM; + } + + if (unlikely(nla_put(skb, WIFI_ATTRIBUTE_ROAMING_BLACKLIST_NUM, + sizeof(uint32_t), &maxNumOfList[0]) < 0)) + goto nla_put_failure; + if (unlikely(nla_put(skb, WIFI_ATTRIBUTE_ROAMING_WHITELIST_NUM, + sizeof(uint32_t), &maxNumOfList[1]) < 0)) + goto nla_put_failure; + + return cfg80211_vendor_cmd_reply(skb); + +nla_put_failure: + kfree_skb(skb); + return -EFAULT; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is to receive the black/whiltelist. from FWK. + * + * \param[in] wiphy wiphy for AIS STA. + * + * \param[in] wdev (not used here). + * + * \param[in] data BSSIDs in the FWK blact&whitelist. + * + * \param[in] data_len the byte-length of the FWK blact&whitelist. + * + * \retval TRUE Success. + * + * \note we iterate each BSSID in 'data' and put it into driver blacklist. + * For now, whiltelist doesn't be implemented by the FWK currently. + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_vendor_config_roaming(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct nlattr *attrlist; + struct AIS_BLACKLIST_ITEM *prBlackList; + struct BSS_DESC *prBssDesc = NULL; + uint32_t len_shift = 0; + uint32_t numOfList[2] = { 0 }; + uint8_t *aucBSSID = NULL; + int i; + + DBGLOG(REQ, INFO, + "Receives roaming blacklist & whitelist with data_len=%d\n", + data_len); + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || (data_len == 0)) + return -EINVAL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + if (!prGlueInfo) + return -EINVAL; + + if (prGlueInfo->u4FWRoamingEnable == 0) { + DBGLOG(REQ, INFO, + "FWRoaming is disabled (FWRoamingEnable=%d)\n", + prGlueInfo->u4FWRoamingEnable); + return WLAN_STATUS_SUCCESS; + } + + attrlist = (struct nlattr *)((uint8_t *) data); + + /* get the number of blacklist and copy those mac addresses from HAL */ + if (attrlist->nla_type == + WIFI_ATTRIBUTE_ROAMING_BLACKLIST_NUM) { + numOfList[0] = nla_get_u32(attrlist); + len_shift += NLA_ALIGN(attrlist->nla_len); + } + DBGLOG(REQ, INFO, "Get the number of blacklist=%d\n", + numOfList[0]); + + if (numOfList[0] < 0 + || numOfList[0] > MAX_FW_ROAMING_BLACKLIST_SIZE) + return -EINVAL; + + /*Refresh all the FWKBlacklist */ + aisRefreshFWKBlacklist(prGlueInfo->prAdapter); + + /* Start to receive blacklist mac addresses and set to FWK blacklist */ + attrlist = (struct nlattr *)((uint8_t *) data + len_shift); + for (i = 0; i < numOfList[0]; i++) { + if (attrlist->nla_type == + WIFI_ATTRIBUTE_ROAMING_BLACKLIST_BSSID) { + prBssDesc = + scanSearchBssDescByBssid(prGlueInfo->prAdapter, + nla_data(attrlist)); + len_shift += NLA_ALIGN(attrlist->nla_len); + attrlist = + (struct nlattr *)((uint8_t *) data + len_shift); + + if (prBssDesc == NULL) { + aucBSSID = nla_data(attrlist); + DBGLOG(REQ, ERROR, "No found blacklist BSS=" + MACSTR "\n", + MAC2STR(aucBSSID)); + continue; + } + + prBlackList = aisAddBlacklist(prGlueInfo->prAdapter, + prBssDesc); + + if (prBlackList) { + prBlackList->fgIsInFWKBlacklist = TRUE; + DBGLOG(REQ, INFO, + "Gets roaming blacklist SSID=%s addr=" + MACSTR "\n", + HIDE(prBssDesc->aucSSID), + MAC2STR(prBssDesc->aucBSSID)); + } else { + DBGLOG(REQ, ERROR, + "prBlackList is NULL, return -EINVAL!"); + return -EINVAL; + } + } + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is to turn on/off FW Roaming. + * + * \param[in] wiphy wiphy for AIS STA. + * + * \param[in] wdev (not used here). + * + * \param[in] data 1 for ON / 0 for OFF. + * + * \param[in] data_len the byte-length of the data. + * + * \retval TRUE Success. + * + * \note we only receive the data and make the interface available to FWK. + * For now, this SUBCMD woundn't be sent from the FWK currently. + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_vendor_enable_roaming(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct nlattr *attr; + + ASSERT(wiphy); /* change to if (wiphy == NULL) then return? */ + ASSERT(wdev); /* change to if (wiphy == NULL) then return? */ + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + if (!prGlueInfo) + return -EFAULT; + + attr = (struct nlattr *)data; + if (attr->nla_type == WIFI_ATTRIBUTE_ROAMING_STATE) + prGlueInfo->u4FWRoamingEnable = nla_get_u32(attr); + + DBGLOG(REQ, INFO, "FWK set FWRoamingEnable = %d\n", + prGlueInfo->u4FWRoamingEnable); + + return WLAN_STATUS_SUCCESS; +} + +int mtk_cfg80211_vendor_get_rtt_capabilities( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Status = -EINVAL; + struct PARAM_WIFI_RTT_CAPABILITIES rRttCapabilities; + struct sk_buff *skb; + + DBGLOG(REQ, TRACE, "vendor command\r\n"); + + ASSERT(wiphy); + ASSERT(wdev); + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, + sizeof(rRttCapabilities)); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed:%x\n", + __func__, i4Status); + return -ENOMEM; + } + + kalMemZero(&rRttCapabilities, sizeof(rRttCapabilities)); + + /* RTT Capabilities return from driver not firmware */ + rRttCapabilities.rtt_one_sided_supported = 0; + rRttCapabilities.rtt_ftm_supported = 1; + rRttCapabilities.lci_support = 1; + rRttCapabilities.lcr_support = 1; + rRttCapabilities.preamble_support = 0x07; + rRttCapabilities.bw_support = 0x1c; + + if (unlikely(nla_put(skb, RTT_ATTRIBUTE_CAPABILITIES, + sizeof(rRttCapabilities), &rRttCapabilities) < 0)) + goto nla_put_failure; + + i4Status = cfg80211_vendor_cmd_reply(skb); + return i4Status; + +nla_put_failure: + kfree_skb(skb); + return i4Status; +} + +int mtk_cfg80211_vendor_llstats_get_info( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + int32_t i4Status = -EINVAL; + struct WIFI_RADIO_STAT *pRadioStat = NULL; + struct sk_buff *skb = NULL; + uint32_t u4BufLen = 0; + + ASSERT(wiphy); + ASSERT(wdev); + + u4BufLen = sizeof(struct WIFI_RADIO_STAT) + sizeof( + struct WIFI_IFACE_STAT); + pRadioStat = kalMemAlloc(u4BufLen, VIR_MEM_TYPE); + if (!pRadioStat) { + DBGLOG(REQ, ERROR, "%s kalMemAlloc pRadioStat failed\n", + __func__); + i4Status = -ENOMEM; + goto nla_put_failure; + } + kalMemZero(pRadioStat, u4BufLen); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, u4BufLen); + if (!skb) { + DBGLOG(REQ, TRACE, "%s allocate skb failed:%x\n", __func__, + i4Status); + i4Status = -ENOMEM; + goto nla_put_failure; + } + +#if 0 + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStatistics, + &rRadioStat, + sizeof(rRadioStat), + TRUE, + TRUE, + TRUE, + FALSE, + &u4BufLen); +#endif + /* only for test */ + pRadioStat->radio = 10; + pRadioStat->on_time = 11; + pRadioStat->tx_time = 12; + pRadioStat->num_channels = 4; + + /*NLA_PUT(skb, LSTATS_ATTRIBUTE_STATS, u4BufLen, pRadioStat);*/ + if (unlikely(nla_put(skb, LSTATS_ATTRIBUTE_STATS, u4BufLen, + pRadioStat) < 0)) + goto nla_put_failure; + + i4Status = cfg80211_vendor_cmd_reply(skb); + kalMemFree(pRadioStat, VIR_MEM_TYPE, u4BufLen); + return -1; /* not support LLS now*/ + /* return i4Status; */ + +nla_put_failure: + if (skb != NULL) + kfree_skb(skb); + if (pRadioStat != NULL) + kalMemFree(pRadioStat, VIR_MEM_TYPE, u4BufLen); + return i4Status; +} + +int mtk_cfg80211_vendor_set_band(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct nlattr *attr; + uint8_t setBand = 0; + enum ENUM_BAND band; + + ASSERT(wiphy); + ASSERT(wdev); + + DBGLOG(REQ, INFO, "%s()\n", __func__); + + if ((data == NULL) || !data_len) + goto nla_put_failure; + + DBGLOG(REQ, TRACE, + "vendor command: data_len=%d, data=0x%x 0x%x\r\n", + data_len, *((uint32_t *) data), *((uint32_t *) data + 1)); + + attr = (struct nlattr *)data; + setBand = nla_get_u32(attr); + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, INFO, "Vendor Set Band value=%d\r\n", setBand); + + if (setBand == QCA_SETBAND_5G) + band = BAND_5G; + else if (setBand == QCA_SETBAND_2G) + band = BAND_2G4; + else + band = BAND_NULL; + + prGlueInfo->prAdapter->aePreferBand[NETWORK_TYPE_AIS] = + band; + return 0; + +nla_put_failure: + return -1; +} + +#if CFG_SUPPORT_MBO +static const struct nla_policy +qca_roaming_param_policy[QCA_ATTR_ROAMING_PARAM_MAX + 1] = { + [QCA_ATTR_ROAMING_SUBCMD] = {.type = NLA_U32}, + [QCA_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID] = {.type = NLA_U32}, + [QCA_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS] = {.type = NLA_NESTED}, + [QCA_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID] = { + .type = NLA_BINARY, + .len = MAC_ADDR_LEN}, +}; + +#define SET_BSSID_PARAMS_NUM_BSSID \ + QCA_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID +#define SET_BSSID_PARAMS \ + QCA_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS +#define SET_BSSID_PARAMS_BSSID \ + QCA_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID + +int mtk_cfg80211_vendor_set_roaming_param(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct nlattr *tb[QCA_ATTR_ROAMING_PARAM_MAX + 1] = {}; + struct nlattr *tb2[QCA_ATTR_ROAMING_PARAM_MAX + 1] = {}; + struct nlattr *attr; + uint32_t rStatus, u4BufLen, cmd_type, count, index; + int tmp; + uint8_t i = 0; + + ASSERT(wiphy); + ASSERT(wdev); + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + if (!prGlueInfo) + return -EFAULT; + + if ((data == NULL) || (data_len == 0)) + goto fail; + + if (NLA_PARSE(tb, QCA_ATTR_ROAMING_PARAM_MAX, + data, data_len, qca_roaming_param_policy)) { + DBGLOG(REQ, ERROR, "Wrong ROAM ATTR.\n"); + goto fail; + } + + /* Parse and fetch Command Type*/ + if (!tb[QCA_ATTR_ROAMING_SUBCMD]) { + DBGLOG(REQ, ERROR, "Invalid roam cmd type\n"); + goto fail; + } + + cmd_type = nla_get_u32(tb[QCA_ATTR_ROAMING_SUBCMD]); + if (cmd_type == QCA_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID) { + struct PARAM_BSS_DISALLOWED_LIST request = {}; + + /* Parse and fetch number of blacklist BSSID */ + if (!tb[SET_BSSID_PARAMS_NUM_BSSID]) { + DBGLOG(REQ, ERROR, "Invlaid num of blacklist bssid\n"); + goto fail; + } + count = nla_get_u32(tb[SET_BSSID_PARAMS_NUM_BSSID]); + if (count > MAX_FW_ROAMING_BLACKLIST_SIZE) { + DBGLOG(REQ, ERROR, "Count %u exceeds\n", count); + goto fail; + } + request.u4NumBssDisallowed = count; + i = 0; + if (count && tb[SET_BSSID_PARAMS]) { + nla_for_each_nested(attr, tb[SET_BSSID_PARAMS], tmp) { + char *bssid = NULL; + + if (i == count) { + DBGLOG(REQ, ERROR, "Excess num\n"); + break; + } + if (NLA_PARSE(tb2, + QCA_ATTR_ROAMING_PARAM_MAX, + nla_data(attr), nla_len(attr), + qca_roaming_param_policy)) { + DBGLOG(REQ, ERROR, "Wrong ROAM ATTR\n"); + goto fail; + } + /* Parse and fetch MAC address */ + if (!tb2[SET_BSSID_PARAMS_BSSID]) { + DBGLOG(REQ, ERROR, "addr failed\n"); + goto fail; + } + bssid = nla_data(tb2[SET_BSSID_PARAMS_BSSID]); + index = i * MAC_ADDR_LEN; + COPY_MAC_ADDR(&request.aucList[index], bssid); + DBGLOG(REQ, INFO, "disallow #%d " MACSTR "\n", + i, MAC2STR(bssid)); + i++; + } + } + if (i != count) + DBGLOG(REQ, ERROR, "Count %u, expected %u\n", i, count); + + rStatus = kalIoctl(prGlueInfo, wlanoidBssDisallowedList, + &request, + sizeof(struct PARAM_BSS_DISALLOWED_LIST), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "disallowed error:%x\n", rStatus); + return -EFAULT; + } + } else { + DBGLOG(REQ, INFO, "unhandled cmd_type %d\n", cmd_type); + goto fail; + } + + return WLAN_STATUS_SUCCESS; +fail: + return -EINVAL; +} + +#undef SET_BSSID_PARAMS_NUM_BSSID +#undef SET_BSSID_PARAMS +#undef SET_BSSID_PARAMS_BSSID + +#endif + +int mtk_cfg80211_vendor_set_roaming_policy( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct nlattr *attr; + uint32_t setRoaming = 0; + uint32_t u4BufLen = 0; + int32_t i4Status = -EINVAL; + uint8_t ucBssIndex = 0; + + ASSERT(wiphy); + ASSERT(wdev); + + if ((data == NULL) || !data_len) + goto nla_put_failure; + + attr = (struct nlattr *)data; + setRoaming = nla_get_u32(attr); + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ucBssIndex = wlanGetBssIdx(wdev->netdev); + ASSERT(prGlueInfo); + + DBGLOG(REQ, INFO, + "vendor command: data_len=%d, data=0x%x 0x%x, roaming policy=%d\r\n", + data_len, *((uint32_t *) data), *((uint32_t *) data + 1), + setRoaming); + + rStatus = kalIoctlByBssIdx(prGlueInfo, + wlanoidSetDrvRoamingPolicy, + &setRoaming, sizeof(uint32_t), FALSE, FALSE, TRUE, + &u4BufLen, + ucBssIndex); + + return rStatus; + +nla_put_failure: + return i4Status; + +} + +int mtk_cfg80211_vendor_set_rssi_monitoring( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo = NULL; + + int32_t i4Status = -EINVAL; + struct PARAM_RSSI_MONITOR_T rRSSIMonitor; + struct nlattr *attr[WIFI_ATTRIBUTE_RSSI_MONITOR_START + 1]; + uint32_t i = 0; + + ASSERT(wiphy); + ASSERT(wdev); + + DBGLOG(REQ, TRACE, "vendor command: data_len=%d\r\n", + data_len); + kalMemZero(&rRSSIMonitor, + sizeof(struct PARAM_RSSI_MONITOR_T)); + if ((data == NULL) || !data_len) + goto nla_put_failure; + kalMemZero(attr, sizeof(struct nlattr *) * + (WIFI_ATTRIBUTE_RSSI_MONITOR_START + 1)); + if (NLA_PARSE_NESTED(attr, + WIFI_ATTRIBUTE_RSSI_MONITOR_START, + (struct nlattr *)(data - NLA_HDRLEN), + nla_parse_wifi_policy) < 0) { + DBGLOG(REQ, ERROR, "%s nla_parse_nested failed\n", + __func__); + goto nla_put_failure; + } + + for (i = WIFI_ATTRIBUTE_MAX_RSSI; + i <= WIFI_ATTRIBUTE_RSSI_MONITOR_START; i++) { + if (attr[i]) { + switch (i) { + case WIFI_ATTRIBUTE_MAX_RSSI: + rRSSIMonitor.max_rssi_value = + nla_get_u32(attr[i]); + break; + case WIFI_ATTRIBUTE_MIN_RSSI: + rRSSIMonitor.min_rssi_value + = nla_get_u32(attr[i]); + break; + case WIFI_ATTRIBUTE_RSSI_MONITOR_START: + rRSSIMonitor.enable = nla_get_u32(attr[i]); + break; + } + } + } + + DBGLOG(REQ, TRACE, + "mMax_rssi=%d, mMin_rssi=%d enable=%d\r\n", + rRSSIMonitor.max_rssi_value, rRSSIMonitor.min_rssi_value, + rRSSIMonitor.enable); + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidRssiMonitor, + &rRSSIMonitor, sizeof(struct PARAM_RSSI_MONITOR_T), + FALSE, FALSE, TRUE, &u4BufLen); + return rStatus; + +nla_put_failure: + return i4Status; +} + +int mtk_cfg80211_vendor_packet_keep_alive_start( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + unsigned short u2IpPktLen = 0; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo = NULL; + + int32_t i4Status = -EINVAL; + struct PARAM_PACKET_KEEPALIVE_T *prPkt = NULL; + struct nlattr *attr[MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC + 1]; + uint32_t i = 0; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + + DBGLOG(REQ, TRACE, "vendor command: data_len=%d\r\n", + data_len); + prPkt = (struct PARAM_PACKET_KEEPALIVE_T *) + kalMemAlloc(sizeof(struct PARAM_PACKET_KEEPALIVE_T), + VIR_MEM_TYPE); + if (!prPkt) { + DBGLOG(REQ, ERROR, + "Can not alloc memory for struct PARAM_PACKET_KEEPALIVE_T\n"); + return -ENOMEM; + } + kalMemZero(prPkt, sizeof(struct PARAM_PACKET_KEEPALIVE_T)); + kalMemZero(attr, sizeof(struct nlattr *) + * (MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC + 1)); + + prPkt->enable = TRUE; /*start packet keep alive*/ + if (NLA_PARSE_NESTED(attr, + MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC, + (struct nlattr *)(data - NLA_HDRLEN), + nla_parse_offloading_policy) < 0) { + DBGLOG(REQ, ERROR, "%s nla_parse_nested failed\n", + __func__); + goto nla_put_failure; + } + + for (i = MKEEP_ALIVE_ATTRIBUTE_ID; + i <= MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC; i++) { + if (attr[i]) { + switch (i) { + case MKEEP_ALIVE_ATTRIBUTE_ID: + prPkt->index = nla_get_u8(attr[i]); + break; + case MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN: + prPkt->u2IpPktLen = nla_get_u16(attr[i]); + break; + case MKEEP_ALIVE_ATTRIBUTE_IP_PKT: + u2IpPktLen = prPkt->u2IpPktLen <= 256 + ? prPkt->u2IpPktLen : 256; + kalMemCopy(prPkt->pIpPkt, nla_data(attr[i]), + u2IpPktLen); + break; + case MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR: + kalMemCopy(prPkt->ucSrcMacAddr, + nla_data(attr[i]), sizeof(uint8_t) * 6); + break; + case MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR: + kalMemCopy(prPkt->ucDstMacAddr, + nla_data(attr[i]), sizeof(uint8_t) * 6); + break; + case MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC: + prPkt->u4PeriodMsec = nla_get_u32(attr[i]); + break; + } + } + } + + DBGLOG(REQ, INFO, + "enable=%d, index=%d, u2IpPktLen=%d u4PeriodMsec=%d\n", + prPkt->enable, prPkt->index, + prPkt->u2IpPktLen, prPkt->u4PeriodMsec); + DBGLOG(REQ, TRACE, "prPkt->pIpPkt=0x%02x%02x%02x%02x\n", + prPkt->pIpPkt[0], prPkt->pIpPkt[1], + prPkt->pIpPkt[2], prPkt->pIpPkt[3]); + DBGLOG(REQ, TRACE, "%02x%02x%02x%02x, %02x%02x%02x%02x\n", + prPkt->pIpPkt[4], prPkt->pIpPkt[5], + prPkt->pIpPkt[6], prPkt->pIpPkt[7], + prPkt->pIpPkt[8], prPkt->pIpPkt[9], + prPkt->pIpPkt[10], prPkt->pIpPkt[11]); + DBGLOG(REQ, TRACE, "%02x%02x%02x%02x\n", + prPkt->pIpPkt[12], prPkt->pIpPkt[13], + prPkt->pIpPkt[14], prPkt->pIpPkt[15]); + DBGLOG(REQ, TRACE, + "prPkt->srcMAC=%02x:%02x:%02x:%02x:%02x:%02x\n", + prPkt->ucSrcMacAddr[0], prPkt->ucSrcMacAddr[1], + prPkt->ucSrcMacAddr[2], prPkt->ucSrcMacAddr[3], + prPkt->ucSrcMacAddr[4], prPkt->ucSrcMacAddr[5]); + DBGLOG(REQ, TRACE, "dstMAC=%02x:%02x:%02x:%02x:%02x:%02x\n", + prPkt->ucDstMacAddr[0], prPkt->ucDstMacAddr[1], + prPkt->ucDstMacAddr[2], prPkt->ucDstMacAddr[3], + prPkt->ucDstMacAddr[4], prPkt->ucDstMacAddr[5]); + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidPacketKeepAlive, + prPkt, sizeof(struct PARAM_PACKET_KEEPALIVE_T), + FALSE, FALSE, TRUE, &u4BufLen); + kalMemFree(prPkt, VIR_MEM_TYPE, + sizeof(struct PARAM_PACKET_KEEPALIVE_T)); + return rStatus; + +nla_put_failure: + if (prPkt != NULL) + kalMemFree(prPkt, VIR_MEM_TYPE, + sizeof(struct PARAM_PACKET_KEEPALIVE_T)); + return i4Status; +} + +int mtk_cfg80211_vendor_packet_keep_alive_stop( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo = NULL; + + int32_t i4Status = -EINVAL; + struct PARAM_PACKET_KEEPALIVE_T *prPkt = NULL; + struct nlattr *attr; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + + DBGLOG(REQ, TRACE, "vendor command: data_len=%d\r\n", + data_len); + prPkt = (struct PARAM_PACKET_KEEPALIVE_T *) + kalMemAlloc(sizeof(struct PARAM_PACKET_KEEPALIVE_T), + VIR_MEM_TYPE); + if (!prPkt) { + DBGLOG(REQ, ERROR, + "Can not alloc memory for PARAM_PACKET_KEEPALIVE_T\n"); + return -ENOMEM; + } + kalMemZero(prPkt, sizeof(struct PARAM_PACKET_KEEPALIVE_T)); + + prPkt->enable = FALSE; /*stop packet keep alive*/ + attr = (struct nlattr *)data; + if (attr->nla_type == MKEEP_ALIVE_ATTRIBUTE_ID) + prPkt->index = nla_get_u8(attr); + + DBGLOG(REQ, INFO, "enable=%d, index=%d\r\n", + prPkt->enable, prPkt->index); + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidPacketKeepAlive, + prPkt, sizeof(struct PARAM_PACKET_KEEPALIVE_T), + FALSE, FALSE, TRUE, &u4BufLen); + kalMemFree(prPkt, VIR_MEM_TYPE, + sizeof(struct PARAM_PACKET_KEEPALIVE_T)); + return rStatus; + +nla_put_failure: + if (prPkt != NULL) + kalMemFree(prPkt, VIR_MEM_TYPE, + sizeof(struct PARAM_PACKET_KEEPALIVE_T)); + return i4Status; +} + +int mtk_cfg80211_vendor_get_version(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct sk_buff *skb = NULL; + struct nlattr *attrlist = NULL; + char aucVersionBuf[256]; + uint16_t u2CopySize = 0; + uint16_t u2Len = 0; + + ASSERT(wiphy); + ASSERT(wdev); + + if ((data == NULL) || !data_len) + return -ENOMEM; + + kalMemZero(aucVersionBuf, 256); + attrlist = (struct nlattr *)((uint8_t *) data); + if (attrlist->nla_type == LOGGER_ATTRIBUTE_DRIVER_VER) { + char aucDriverVersionStr[] = STR(NIC_DRIVER_MAJOR_VERSION) "_" + STR(NIC_DRIVER_MINOR_VERSION) "_" + STR(NIC_DRIVER_SERIAL_VERSION) "-" + STR(DRIVER_BUILD_DATE); + + u2Len = kalStrLen(aucDriverVersionStr); + DBGLOG(REQ, TRACE, "Get driver version len: %d\n", u2Len); + u2CopySize = (u2Len >= 256) ? 255 : u2Len; + if (u2CopySize > 0) + kalMemCopy(aucVersionBuf, &aucDriverVersionStr[0], + u2CopySize); + } else if (attrlist->nla_type == LOGGER_ATTRIBUTE_FW_VER) { + struct ADAPTER *prAdapter; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + prAdapter = prGlueInfo->prAdapter; + if (prAdapter) { + u2Len = kalStrLen( + prAdapter->rVerInfo.aucReleaseManifest); + DBGLOG(REQ, TRACE, + "Get FW manifest version len: %d\n", u2Len); + u2CopySize = (u2Len >= 256) ? 255 : u2Len; + if (u2CopySize > 0) + kalMemCopy(aucVersionBuf, + prAdapter->rVerInfo.aucReleaseManifest, + u2CopySize); + } + } + + DBGLOG(REQ, TRACE, "Get version(%d)=[%s]\n", u2CopySize, aucVersionBuf); + + if (u2CopySize == 0) + return -EFAULT; + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, u2CopySize); + if (!skb) { + DBGLOG(REQ, ERROR, "Allocate skb failed\n"); + return -ENOMEM; + } + + if (unlikely(nla_put_nohdr(skb, u2CopySize, &aucVersionBuf[0]) < 0)) + goto nla_put_failure; + + return cfg80211_vendor_cmd_reply(skb); + +nla_put_failure: + kfree_skb(skb); + return -EFAULT; +} + +int mtk_cfg80211_vendor_event_generic_response( + struct wiphy *wiphy, struct wireless_dev *wdev, + uint32_t len, uint8_t *data) +{ + struct sk_buff *skb; + + if (!wiphy || !wdev || !data || len <= 0) { + DBGLOG(REQ, ERROR, "%s wrong input parameters\n", __func__); + return -EINVAL; + } + + skb = cfg80211_vendor_event_alloc(wiphy, +#if KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE + wdev, +#endif + len, WIFI_EVENT_GENERIC_RESPONSE, GFP_KERNEL); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + /* Do not use nla_put_nohdr because it aligns buffer + * + * if (unlikely(nla_put_nohdr(skb, len, data) < 0)) + * goto nla_put_failure; + */ + kalMemCopy(skb_put(skb, len), data, len); + + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; +} + +int mtk_cfg80211_vendor_get_supported_feature_set(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + uint64_t u8FeatureSet; + struct GLUE_INFO *prGlueInfo; + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(wdev); + + prGlueInfo = wlanGetGlueInfo(); + if (!prGlueInfo) + return -EFAULT; + + u8FeatureSet = wlanGetSupportedFeatureSet(prGlueInfo); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u8FeatureSet)); + if (!skb) { + DBGLOG(REQ, ERROR, "Allocate skb failed\n"); + return -ENOMEM; + } + + if (unlikely( + nla_put_nohdr(skb, sizeof(u8FeatureSet), &u8FeatureSet) < 0)) { + DBGLOG(REQ, ERROR, "nla_put_nohdr failed\n"); + goto nla_put_failure; + } + + DBGLOG(REQ, TRACE, "supported feature set=0x%llx\n", u8FeatureSet); + + return cfg80211_vendor_cmd_reply(skb); + +nla_put_failure: + kfree_skb(skb); + return -EFAULT; +} + +int mtk_cfg80211_vendor_event_rssi_beyond_range( + struct wiphy *wiphy, struct wireless_dev *wdev, int rssi) +{ + struct sk_buff *skb; + struct PARAM_RSSI_MONITOR_EVENT rRSSIEvt; + struct BSS_INFO *prAisBssInfo; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + ASSERT(wiphy); + ASSERT(wdev); + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, TRACE, "vendor command rssi=%d\r\n", rssi); + kalMemZero(&rRSSIEvt, + sizeof(struct PARAM_RSSI_MONITOR_EVENT)); + +#if KERNEL_VERSION(4, 4, 0) <= LINUX_VERSION_CODE + skb = cfg80211_vendor_event_alloc(wiphy, wdev, + sizeof(struct PARAM_RSSI_MONITOR_EVENT), + WIFI_EVENT_RSSI_MONITOR, GFP_KERNEL); +#else + skb = cfg80211_vendor_event_alloc(wiphy, + sizeof(struct PARAM_RSSI_MONITOR_EVENT), + WIFI_EVENT_RSSI_MONITOR, GFP_KERNEL); +#endif /* KERNEL_VERSION(4, 4, 0) <= LINUX_VERSION_CODE */ + + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + prAdapter = prGlueInfo->prAdapter; + prAisBssInfo = aisGetAisBssInfo(prAdapter, ucBssIndex); + kalMemCopy(rRSSIEvt.BSSID, prAisBssInfo->aucBSSID, + sizeof(uint8_t) * MAC_ADDR_LEN); + + rRSSIEvt.version = 1; /* RSSI_MONITOR_EVT_VERSION = 1 */ + if (rssi > PARAM_WHQL_RSSI_MAX_DBM) + rssi = PARAM_WHQL_RSSI_MAX_DBM; + else if (rssi < -120) + rssi = -120; + rRSSIEvt.rssi = (int8_t)rssi; + DBGLOG(REQ, INFO, + "RSSI Event: version=%d, rssi=%d, BSSID=" MACSTR "\r\n", + rRSSIEvt.version, rRSSIEvt.rssi, MAC2STR(rRSSIEvt.BSSID)); + + /*NLA_PUT_U32(skb, GOOGLE_RSSI_MONITOR_EVENT, rssi);*/ + { + /* unsigned int __tmp = rssi; */ + + if (unlikely(nla_put(skb, WIFI_EVENT_RSSI_MONITOR, + sizeof(struct PARAM_RSSI_MONITOR_EVENT), + &rRSSIEvt) < 0)) + goto nla_put_failure; + } + + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -ENOMEM; +} + +int mtk_cfg80211_vendor_set_tx_power_scenario(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ +#if CFG_SUPPORT_DYNAMIC_PWR_LIMIT + struct PARAM_TX_PWR_CTRL_IOCTL rPwrCtrlParam = { 0 }; + struct GLUE_INFO *prGlueInfo; + struct nlattr *attr; + struct sk_buff *skb; + uint32_t u4Scenario; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4SetInfoLen = 0; + uint8_t index = 0; + char name[] = { "_G_Scenario" }; + + ASSERT(wiphy); + ASSERT(wdev); + +#if CFG_ENABLE_UNIFY_WIPHY + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); +#else /* CFG_ENABLE_UNIFY_WIPHY */ + if (wdev == gprWdev) /* wlan0 */ + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + else + prGlueInfo = *((struct GLUE_INFO **) wiphy_priv(wiphy)); +#endif /* CFG_ENABLE_UNIFY_WIPHY */ + + if (!prGlueInfo) + return -EFAULT; + + attr = (struct nlattr *)data; + if (attr->nla_type == WIFI_ATTRIBUTE_TX_POWER_SCENARIO) + u4Scenario = nla_get_u32(attr); + else + return -EINVAL; + + if (u4Scenario == UINT_MAX) { + index = 0; + } else if ((u4Scenario >= 0) && (u4Scenario <= 4)) { + index = u4Scenario + 1; + } else { + DBGLOG(REQ, ERROR, "invalid scenario index: %u\n", u4Scenario); + return -EINVAL; + } + + rPwrCtrlParam.fgApplied = (index == 0) ? FALSE : TRUE; + rPwrCtrlParam.name = name; + rPwrCtrlParam.index = index; + + DBGLOG(REQ, INFO, + "applied=[%d], name=[%s], index=[%u], setting=[%s], UINT_MAX=[%u], iftype=[%d]\n", + rPwrCtrlParam.fgApplied, + rPwrCtrlParam.name, + rPwrCtrlParam.index, + rPwrCtrlParam.newSetting, + UINT_MAX, + wdev->iftype); + + rStatus = kalIoctl(prGlueInfo, + wlanoidTxPowerControl, + (void *)&rPwrCtrlParam, + sizeof(struct PARAM_TX_PWR_CTRL_IOCTL), + FALSE, + FALSE, + TRUE, + &u4SetInfoLen); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(rStatus)); + if (!skb) { + DBGLOG(REQ, ERROR, "Allocate skb failed\n"); + return -ENOMEM; + } + + if (unlikely( + nla_put_nohdr(skb, sizeof(rStatus), &rStatus) < 0)) { + DBGLOG(REQ, ERROR, "nla_put_nohdr failed\n"); + goto errHandleLabel; + } + + DBGLOG(REQ, INFO, "rStatus=0x%x\n", rStatus); + + return cfg80211_vendor_cmd_reply(skb); + +errHandleLabel: + kfree_skb(skb); +#endif + return -EFAULT; +} + +int mtk_cfg80211_vendor_get_preferred_freq_list(struct wiphy + *wiphy, struct wireless_dev *wdev, const void *data, + int data_len) +{ + struct GLUE_INFO *prGlueInfo; + struct sk_buff *skb; + struct nlattr *tb[WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_LAST] = {}; + uint32_t freq_list[MAX_CHN_NUM] = {}; + uint32_t num_freq_list = 0; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + enum CONN_MODE_IFACE_TYPE type; + enum ENUM_IFTYPE eIftype; + uint32_t i; + + ASSERT(wiphy); + ASSERT(wdev); + + if ((data == NULL) || !data_len) + return -EINVAL; + + prGlueInfo = wlanGetGlueInfo(); + if (!prGlueInfo) + return -EFAULT; + + if (NLA_PARSE(tb, WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_MAX, + data, data_len, nla_get_preferred_freq_list_policy)) { + DBGLOG(REQ, ERROR, "Invalid ATTR.\n"); + return -EINVAL; + } + + type = nla_get_u32(tb[WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_IFACE_TYPE]); + + DBGLOG(REQ, INFO, "type: %d\n", type); + + switch (type) { + case CONN_MODE_IFACE_TYPE_STA: + eIftype = IFTYPE_STATION; + break; + case CONN_MODE_IFACE_TYPE_SAP: + eIftype = IFTYPE_AP; + break; + case CONN_MODE_IFACE_TYPE_P2P_GC: + eIftype = IFTYPE_P2P_CLIENT; + break; + case CONN_MODE_IFACE_TYPE_P2P_GO: + eIftype = IFTYPE_P2P_GO; + break; + default: + eIftype = IFTYPE_NUM; + break; + } + + if (eIftype != IFTYPE_P2P_CLIENT && eIftype != IFTYPE_P2P_GO) { + DBGLOG(REQ, ERROR, "Only support p2p gc/go type.\n"); + return -EINVAL; + } + + rStatus = p2pFunGetPreferredFreqList(prGlueInfo->prAdapter, eIftype, + freq_list, &num_freq_list); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "get preferred freq list failed.\n"); + return -EINVAL; + } + + DBGLOG(P2P, INFO, "num. of preferred freq list = %d\n", num_freq_list); + for (i = 0; i < num_freq_list; i++) + DBGLOG(P2P, INFO, "dump preferred freq list[%d] = %d\n", + i, freq_list[i]); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) + + sizeof(uint32_t) * num_freq_list + NLMSG_HDRLEN); + if (!skb) { + DBGLOG(REQ, ERROR, "Allocate skb failed.\n"); + return -ENOMEM; + } + + if (unlikely(nla_put_u32(skb, + WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_IFACE_TYPE, + type) < 0)) { + DBGLOG(REQ, ERROR, "put iface into skb failed.\n"); + goto nla_put_failure; + } + + if (unlikely(nla_put(skb, WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_GET, + sizeof(uint32_t) * num_freq_list, freq_list) < 0)) { + DBGLOG(REQ, ERROR, "put freq list into skb failed.\n"); + goto nla_put_failure; + } + + return cfg80211_vendor_cmd_reply(skb); + +nla_put_failure: + kfree_skb(skb); + return -EFAULT; +} + +int mtk_cfg80211_vendor_acs(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + struct GLUE_INFO *prGlueInfo; + struct nlattr *tb[WIFI_VENDOR_ATTR_ACS_MAX + 1] = {}; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + bool ht_enabled, ht40_enabled, vht_enabled; + uint8_t ch_width = 0; + enum P2P_VENDOR_ACS_HW_MODE hw_mode; + uint8_t *ch_list = NULL; + uint8_t ch_list_count = 0; + uint8_t i; + uint32_t msg_size; + struct MSG_P2P_ACS_REQUEST *prMsgAcsRequest; + struct RF_CHANNEL_INFO *prRfChannelInfo; + struct sk_buff *reply_skb; + uint8_t role_idx; + + if (!wiphy || !wdev || !data || !data_len) { + DBGLOG(REQ, ERROR, "input data null.\n"); + rStatus = -EINVAL; + goto exit; + } + +#if CFG_ENABLE_UNIFY_WIPHY + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); +#else /* CFG_ENABLE_UNIFY_WIPHY */ + if (wdev == gprWdev) /* wlan0 */ + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + else + prGlueInfo = *((struct GLUE_INFO **) wiphy_priv(wiphy)); +#endif /* CFG_ENABLE_UNIFY_WIPHY */ + + if (!prGlueInfo) { + DBGLOG(REQ, ERROR, "get glue structure fail.\n"); + rStatus = -EFAULT; + goto exit; + } + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, wdev->netdev, &role_idx) < 0) { + DBGLOG(REQ, ERROR, "get role index fail.\n"); + rStatus = -EFAULT; + goto exit; + } + + if (NLA_PARSE(tb, WIFI_VENDOR_ATTR_ACS_MAX, data, data_len, + nla_get_acs_policy)) { + DBGLOG(REQ, ERROR, "parse acs attr fail.\n"); + rStatus = -EINVAL; + goto exit; + } + + if (!tb[WIFI_VENDOR_ATTR_ACS_HW_MODE]) { + DBGLOG(REQ, ERROR, "attr hw_mode failed.\n"); + rStatus = -EINVAL; + goto exit; + } + hw_mode = nla_get_u8(tb[WIFI_VENDOR_ATTR_ACS_HW_MODE]); + + if (tb[WIFI_VENDOR_ATTR_ACS_HT_ENABLED]) + ht_enabled = + nla_get_flag(tb[WIFI_VENDOR_ATTR_ACS_HT_ENABLED]); + else + ht_enabled = 0; + + if (tb[WIFI_VENDOR_ATTR_ACS_HT40_ENABLED]) + ht40_enabled = + nla_get_flag(tb[WIFI_VENDOR_ATTR_ACS_HT40_ENABLED]); + else + ht40_enabled = 0; + + if (tb[WIFI_VENDOR_ATTR_ACS_VHT_ENABLED]) + vht_enabled = + nla_get_flag(tb[WIFI_VENDOR_ATTR_ACS_VHT_ENABLED]); + else + vht_enabled = 0; + + if (tb[WIFI_VENDOR_ATTR_ACS_CHWIDTH]) + ch_width = nla_get_u16(tb[WIFI_VENDOR_ATTR_ACS_CHWIDTH]); + + if (tb[WIFI_VENDOR_ATTR_ACS_CH_LIST]) { + char *tmp = nla_data(tb[WIFI_VENDOR_ATTR_ACS_CH_LIST]); + + ch_list_count = nla_len(tb[WIFI_VENDOR_ATTR_ACS_CH_LIST]); + if (ch_list_count) { + if (ch_list_count > MAX_CHN_NUM) { + DBGLOG(REQ, ERROR, "Invalid channel count.\n"); + rStatus = -EINVAL; + goto exit; + } + ch_list = kalMemAlloc(sizeof(uint8_t) * ch_list_count, + VIR_MEM_TYPE); + if (ch_list == NULL) { + DBGLOG(REQ, ERROR, "allocate ch_list fail.\n"); + rStatus = -ENOMEM; + goto exit; + } + + kalMemCopy(ch_list, tmp, ch_list_count); + } + } else if (tb[WIFI_VENDOR_ATTR_ACS_FREQ_LIST]) { + uint32_t *freq = + nla_data(tb[WIFI_VENDOR_ATTR_ACS_FREQ_LIST]); + + ch_list_count = nla_len(tb[WIFI_VENDOR_ATTR_ACS_FREQ_LIST]) / + sizeof(uint32_t); + if (ch_list_count) { + if (ch_list_count > MAX_CHN_NUM) { + DBGLOG(REQ, ERROR, "Invalid freq count.\n"); + rStatus = -EINVAL; + goto exit; + } + ch_list = kalMemAlloc(sizeof(uint8_t) * ch_list_count, + VIR_MEM_TYPE); + if (ch_list == NULL) { + DBGLOG(REQ, ERROR, "allocate ch_list fail.\n"); + rStatus = -ENOMEM; + goto exit; + } + + for (i = 0; i < ch_list_count; i++) + ch_list[i] = + ieee80211_frequency_to_channel(freq[i]); + } + } + + if (!ch_list_count) { + DBGLOG(REQ, ERROR, "channel list count can NOT be 0\n"); + rStatus = -EINVAL; + goto exit; + } + + msg_size = sizeof(struct MSG_P2P_ACS_REQUEST) + + (ch_list_count * sizeof(struct RF_CHANNEL_INFO)); + + prMsgAcsRequest = cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, msg_size); + + if (prMsgAcsRequest == NULL) { + DBGLOG(REQ, ERROR, "allocate msg acs req. fail.\n"); + rStatus = -ENOMEM; + goto exit; + } + + kalMemSet(prMsgAcsRequest, 0, msg_size); + prMsgAcsRequest->rMsgHdr.eMsgId = MID_MNY_P2P_ACS; + prMsgAcsRequest->ucRoleIdx = role_idx; + prMsgAcsRequest->fgIsHtEnable = ht_enabled; + prMsgAcsRequest->fgIsHt40Enable = ht40_enabled; + prMsgAcsRequest->fgIsVhtEnable = vht_enabled; + switch (ch_width) { + case 20: + prMsgAcsRequest->eChnlBw = MAX_BW_20MHZ; + break; + case 40: + prMsgAcsRequest->eChnlBw = MAX_BW_40MHZ; + break; + case 80: + prMsgAcsRequest->eChnlBw = MAX_BW_80MHZ; + break; + case 160: + prMsgAcsRequest->eChnlBw = MAX_BW_160MHZ; + break; + default: + DBGLOG(REQ, ERROR, "unsupport width: %d.\n", ch_width); + prMsgAcsRequest->eChnlBw = MAX_BW_UNKNOWN; + break; + } + prMsgAcsRequest->eHwMode = hw_mode; + prMsgAcsRequest->u4NumChannel = ch_list_count; + + for (i = 0; i < ch_list_count; i++) { + /* Translate Freq from MHz to channel number. */ + prRfChannelInfo = + &(prMsgAcsRequest->arChannelListInfo[i]); + + prRfChannelInfo->ucChannelNum = ch_list[i]; + + if (prRfChannelInfo->ucChannelNum <= 14) + prRfChannelInfo->eBand = BAND_2G4; + else + prRfChannelInfo->eBand = BAND_5G; + + /* Iteration. */ + prRfChannelInfo++; + } + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prMsgAcsRequest, + MSG_SEND_METHOD_BUF); + +exit: + if (ch_list) + kalMemFree(ch_list, VIR_MEM_TYPE, + sizeof(uint8_t) * ch_list_count); + if (rStatus == WLAN_STATUS_SUCCESS) { + reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, + NLMSG_HDRLEN); + if (reply_skb != NULL) + return cfg80211_vendor_cmd_reply(reply_skb); + } + return rStatus; +} + +int mtk_cfg80211_vendor_get_features(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + struct sk_buff *reply_skb; + uint8_t feature_flags[(NUM_VENDOR_FEATURES + 7) / 8] = {0}; + uint8_t i; + + ASSERT(wiphy); + ASSERT(wdev); + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + feature_flags[(VENDOR_FEATURE_SUPPORT_HW_MODE_ANY / 8)] |= + (1 << (VENDOR_FEATURE_SUPPORT_HW_MODE_ANY % 8)); +#endif + + for (i = 0; i < ((NUM_VENDOR_FEATURES + 7) / 8); i++) { + DBGLOG(REQ, TRACE, "Dump feature flags[%d]=0x%x.\n", i, + feature_flags[i]); + } + + reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, + sizeof(feature_flags) + NLMSG_HDRLEN); + + if (!reply_skb) + goto nla_put_failure; + + if (nla_put(reply_skb, WIFI_VENDOR_ATTR_FEATURE_FLAGS, + sizeof(feature_flags), feature_flags)) + goto nla_put_failure; + + return cfg80211_vendor_cmd_reply(reply_skb); + +nla_put_failure: + kfree_skb(reply_skb); + return -EINVAL; +} + +int mtk_cfg80211_vendor_driver_memory_dump(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + struct LINK_QUALITY_INFO_OUTPUT_DATA { + uint16_t u2Tag01; /* cur tx rate */ + uint16_t u2Len01; + uint32_t u4CurTxRate; + uint16_t u2Tag02; /* tx total count */ + uint16_t u2Len02; + uint64_t u8TxTotalCount; + uint16_t u2Tag03; /* tx retry count */ + uint16_t u2Len03; + uint64_t u8TxRetryCount; + uint16_t u2Tag04; /* tx fail Count */ + uint16_t u2Len04; + uint64_t u8TxFailCount; + uint16_t u2Tag05; /* Rts fail count */ + uint16_t u2Len05; + uint64_t u8TxRtsFailCount; + uint16_t u2Tag06; /* Ack fail count */ + uint16_t u2Len06; + uint64_t u8TxAckFailCount; + uint16_t u2Tag07; /* cur rx rate */ + uint16_t u2Len07; + uint32_t u4CurRxRate; + uint16_t u2Tag08; /* Rx total count */ + uint16_t u2Len08; + uint64_t u8RxTotalCount; + uint16_t u2Tag09; /* Rx dup count */ + uint16_t u2Len09; + uint32_t u4RxDupCount; + uint16_t u2Tag10; /* Rx err count */ + uint16_t u2Len10; + uint64_t u8RxErrCount; + uint16_t u2Tag11; /* Idle slot count */ + uint16_t u2Len11; + uint64_t u8IdleSlotCount; + uint16_t u2Tag12; /* Awake duration */ + uint16_t u2Len12; + uint64_t u8HwMacAwakeDuration; + uint16_t u2Tag13; /* Scan Flag */ + uint16_t u2Len13; + uint16_t u2FlagScanning; + } __packed outputData = { + .u2Tag01 = 1, /* tag: 1, cur tx rate */ + .u2Len01 = 4, /* len: 4, bytes */ + .u2Tag02 = 2, /* tag: 2, tx total count */ + .u2Len02 = 8, /* len: 8, bytes */ + .u2Tag03 = 3, /* tag: 3, tx retry count */ + .u2Len03 = 8, /* len: 8, bytes */ + .u2Tag04 = 4, /* tag: 4, tx fail count */ + .u2Len04 = 8, /* len: 8, bytes */ + .u2Tag05 = 5, /* tag: 5, tx rts fail count */ + .u2Len05 = 8, /* len: 8, bytes */ + .u2Tag06 = 6, /* tag: 6, tx ack fail count */ + .u2Len06 = 8, /* len: 8, bytes */ + .u2Tag07 = 7, /* tag: 7, cur rx rate */ + .u2Len07 = 4, /* len: 4, bytes */ + .u2Tag08 = 8, /* tag: 8, rx total count */ + .u2Len08 = 8, /* len: 8, bytes */ + .u2Tag09 = 9, /* tag: 9, rx dup count */ + .u2Len09 = 4, /* len: 4, bytes */ + .u2Tag10 = 10, /* tag: 10, rx err count */ + .u2Len10 = 8, /* len: 8, bytes */ + .u2Tag11 = 11, + .u2Len11 = 8, + .u2Tag12 = 12, /* tag: 12, Hw Mac Awake Duration */ + .u2Len12 = 8, /* len: 8, bytes */ + .u2Tag13 = 13, /* tag: 13, Scanning Flag */ + .u2Len13 = 2, /* len: 2, bytes */ + }; + struct PARAM_GET_LINK_QUALITY_INFO rParam; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate; + struct WIFI_LINK_QUALITY_INFO rLinkQualityInfo; + struct GLUE_INFO *prGlueInfo; +#endif + struct sk_buff *skb = NULL; + uint32_t *puBuffer = NULL; + int32_t i4Status = -EINVAL; + uint32_t u4BufLen; + uint16_t u2CopySize = 0; + + ASSERT(wiphy); + ASSERT(wdev); +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + prNetDevPrivate = + (struct NETDEV_PRIVATE_GLUE_INFO *) netdev_priv(wdev->netdev); + if (!prNetDevPrivate) { + DBGLOG(REQ, ERROR, "Invalid net device private\n"); + return -EFAULT; + } + rParam.ucBssIdx = 0; /* prNetDevPrivate->ucBssIdx; */ + rParam.prLinkQualityInfo = &rLinkQualityInfo; + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + i4Status = kalIoctl(prGlueInfo, wlanoidGetLinkQualityInfo, + &rParam, sizeof(struct PARAM_GET_LINK_QUALITY_INFO), + TRUE, FALSE, FALSE, &u4BufLen); + if (i4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "wlanoidGetLinkQualityInfo error\n"); + goto err_handle_label; + } + + outputData.u4CurTxRate = rLinkQualityInfo.u4CurTxRate; + outputData.u8TxTotalCount = rLinkQualityInfo.u8TxTotalCount; + outputData.u8TxRetryCount = rLinkQualityInfo.u8TxRetryCount; + outputData.u8TxFailCount = rLinkQualityInfo.u8TxFailCount; + outputData.u8TxRtsFailCount = rLinkQualityInfo.u8TxRtsFailCount; + outputData.u8TxAckFailCount = rLinkQualityInfo.u8TxAckFailCount; + outputData.u4CurRxRate = rLinkQualityInfo.u4CurRxRate; + outputData.u8RxTotalCount = rLinkQualityInfo.u8RxTotalCount; + outputData.u4RxDupCount = rLinkQualityInfo.u4RxDupCount; + outputData.u8RxErrCount = rLinkQualityInfo.u8RxErrCount; + outputData.u8IdleSlotCount = rLinkQualityInfo.u8IdleSlotCount; + outputData.u8HwMacAwakeDuration = rLinkQualityInfo.u4HwMacAwakeDuration; + outputData.u2FlagScanning = rLinkQualityInfo.u2FlagScanning; + + DBGLOG(REQ, INFO, + "LQ: Tx(rate:%u, total:%u, Rty:%lu, fail:%lu, RTSF:%lu, ACKF:%lu), Rx(rate:%u, total:%u, dup:%u, error:%lu), Idle:%lu AwakeDur:%lu\n", + outputData.u4CurTxRate, /* tx rate, current tx link speed */ + outputData.u8TxTotalCount, /* tx total packages */ + outputData.u8TxRetryCount, /* tx retry count */ + outputData.u8TxFailCount, /* tx fail count */ + outputData.u8TxRtsFailCount, /* tx RTS fail count */ + outputData.u8TxAckFailCount, /* tx ACK fail count */ + outputData.u4CurRxRate, /* current rx rate */ + outputData.u8RxTotalCount, /* rx total packages */ + outputData.u4RxDupCount, /* rx duplicate package count */ + outputData.u8RxErrCount, /* rx error count */ + outputData.u8IdleSlotCount, + outputData.u8HwMacAwakeDuration + ); + + u2CopySize = sizeof(struct LINK_QUALITY_INFO_OUTPUT_DATA); + puBuffer = (uint32_t *)&outputData; +#endif + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, u2CopySize); + if (!skb) { + DBGLOG(REQ, ERROR, "allocate skb failed\n"); + i4Status = -ENOMEM; + goto err_handle_label; + } + + if (unlikely(nla_put_nohdr(skb, u2CopySize, puBuffer) < 0)) { + DBGLOG(REQ, ERROR, "nla_put_nohdr failed: len=%u, ptr=%p\n", + u2CopySize, puBuffer); + i4Status = -EINVAL; + goto err_handle_label; + } + + return cfg80211_vendor_cmd_reply(skb); + +err_handle_label: + kfree_skb(skb); + return i4Status; +} + +#endif /* KERNEL_VERSION(3, 16, 0) <= LINUX_VERSION_CODE */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_wext.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_wext.c new file mode 100644 index 0000000000000..59a99640f36e0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_wext.c @@ -0,0 +1,5002 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux + * /gl_wext.c#5 + */ + +/*! \file gl_wext.c + * \brief ioctl() (mostly Linux Wireless Extensions) routines for STA + * driver. + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ + +#include "gl_os.h" + +#include "config.h" +#include "wlan_oid.h" + +#include "gl_wext.h" +#include "gl_wext_priv.h" + +#include "precomp.h" + +#if CFG_SUPPORT_WAPI +#include "gl_sec.h" +#endif + +/* compatibility to wireless extensions */ +#ifdef WIRELESS_EXT + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +const long channel_freq[] = { + 2412, 2417, 2422, 2427, 2432, 2437, 2442, + 2447, 2452, 2457, 2462, 2467, 2472, 2484 +}; + +#define NUM_CHANNELS (ARRAY_SIZE(channel_freq)) + +#define MAX_SSID_LEN 32 +#define COUNTRY_CODE_LEN 10 /* country code length */ + +/******************************************************************************* + * 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, ""}, + + {IOCTL_GET_DRIVER, IW_PRIV_TYPE_CHAR | 2000, IW_PRIV_TYPE_CHAR | + 2000, "driver"}, + +#if CFG_SUPPORT_QA_TOOL + /* added for ATE iwpriv Command */ + {IOCTL_IWPRIV_ATE, IW_PRIV_TYPE_CHAR | 2000, 0, ""}, +#endif + {IOC_AP_SET_CFG, IW_PRIV_TYPE_CHAR | 256, + IW_PRIV_TYPE_CHAR | 1024, "AP_SET_CFG"}, + {IOC_AP_GET_STA_LIST, IW_PRIV_TYPE_CHAR | 1024, + IW_PRIV_TYPE_CHAR | 1024, "AP_GET_STA_LIST"}, + {IOC_AP_SET_MAC_FLTR, IW_PRIV_TYPE_CHAR | 256, + IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 1024, "AP_SET_MAC_FLTR"}, + {IOC_AP_STA_DISASSOC, IW_PRIV_TYPE_CHAR | 256, + IW_PRIV_TYPE_CHAR | 1024, "AP_STA_DISASSOC"}, + {IOC_AP_SET_NSS, IW_PRIV_TYPE_CHAR | 256, + IW_PRIV_TYPE_CHAR | 1024, "AP_SET_NSS"}, + + /* 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 + +#if CFG_SUPPORT_QA_TOOL + {PRIV_QACMD_SET, IW_PRIV_TYPE_CHAR | 2000, 0, "set"}, +#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_GET_CH_LIST, 0, IW_PRIV_TYPE_INT | 50, "get_ch_list"}, + { + PRIV_CMD_DUMP_MEM, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_mem" + }, + +#if CFG_ENABLE_WIFI_DIRECT + {PRIV_CMD_P2P_MODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | + 2, 0, "set_p2p_mode"}, +#endif + {PRIV_CMD_MET_PROFILING, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | + 2, 0, "set_met_prof"}, + {PRIV_CMD_SET_SER, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | + 1, 0, "set_ser"}, + +}; + +static const iw_handler rIwPrivHandler[] = { + [IOCTL_SET_INT - SIOCIWFIRSTPRIV] = priv_set_int, + [IOCTL_GET_INT - SIOCIWFIRSTPRIV] = priv_get_int, + [IOCTL_SET_ADDRESS - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_GET_ADDRESS - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_SET_STR - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_GET_STR - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_SET_KEY - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_GET_KEY - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_SET_STRUCT - SIOCIWFIRSTPRIV] = priv_set_struct, + [IOCTL_GET_STRUCT - SIOCIWFIRSTPRIV] = priv_get_struct, + [IOCTL_SET_STRUCT_FOR_EM - SIOCIWFIRSTPRIV] = priv_set_struct, + [IOCTL_SET_INTS - SIOCIWFIRSTPRIV] = priv_set_ints, + [IOCTL_GET_INTS - SIOCIWFIRSTPRIV] = priv_get_ints, + [IOCTL_GET_DRIVER - SIOCIWFIRSTPRIV] = priv_set_driver, + [IOC_AP_GET_STA_LIST - SIOCIWFIRSTPRIV] = priv_set_ap, + [IOC_AP_SET_MAC_FLTR - SIOCIWFIRSTPRIV] = priv_set_ap, + [IOC_AP_SET_CFG - SIOCIWFIRSTPRIV] = priv_set_ap, + [IOC_AP_STA_DISASSOC - SIOCIWFIRSTPRIV] = priv_set_ap, + [IOC_AP_SET_NSS - SIOCIWFIRSTPRIV] = priv_set_ap, +#if CFG_SUPPORT_QA_TOOL + [IOCTL_QA_TOOL_DAEMON - SIOCIWFIRSTPRIV] = priv_qa_agent, + [IOCTL_IWPRIV_ATE - SIOCIWFIRSTPRIV] = priv_ate_set +#endif +}; + +/* standard ioctls */ +static int std_get_name(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_freq(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_freq(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_mode(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_mode(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_ap(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_ap(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_rate(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_rts(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_rts(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_frag(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_txpow(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_txpow(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_power(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_power(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_range(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_priv(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_priv(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_mlme(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_scan(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_scan(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_essid(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_essid(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_encode(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_encode(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_auth(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +#if (WIRELESS_EXT > 17) +static int std_set_genie(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); +#endif + +static int std_set_encode_ext(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_pmska(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static const iw_handler mtk_std_handler[] = { + IW_HANDLER(SIOCGIWNAME, std_get_name), /* factory mode used */ + IW_HANDLER(SIOCSIWFREQ, std_set_freq), + IW_HANDLER(SIOCGIWFREQ, std_get_freq), /* factory mode used */ + IW_HANDLER(SIOCSIWMODE, std_set_mode), /* factory mode used */ + IW_HANDLER(SIOCGIWMODE, std_get_mode), /* factory mode used */ + IW_HANDLER(SIOCGIWRANGE, std_get_range), /* factory mode used */ + IW_HANDLER(SIOCSIWPRIV, std_set_priv), + IW_HANDLER(SIOCGIWPRIV, std_get_priv), + IW_HANDLER(SIOCSIWAP, std_set_ap), + IW_HANDLER(SIOCGIWAP, std_get_ap), /* factory mode used */ + IW_HANDLER(SIOCSIWMLME, std_set_mlme), + IW_HANDLER(SIOCSIWSCAN, std_set_scan), /* factory mode used */ + IW_HANDLER(SIOCGIWSCAN, std_get_scan), /* factory mode used */ + IW_HANDLER(SIOCSIWESSID, std_set_essid), /* factory mode used */ + IW_HANDLER(SIOCGIWESSID, std_get_essid), /* factory mode used */ + IW_HANDLER(SIOCGIWRATE, std_get_rate), /* factory mode used */ + IW_HANDLER(SIOCSIWRTS, std_set_rts), + IW_HANDLER(SIOCGIWRTS, std_get_rts), /* factory mode used */ + IW_HANDLER(SIOCGIWFRAG, std_get_frag), /* factory mode used */ + IW_HANDLER(SIOCSIWTXPOW, std_set_txpow), + IW_HANDLER(SIOCGIWTXPOW, std_get_txpow), /* factory mode used */ + IW_HANDLER(SIOCSIWENCODE, std_set_encode), + IW_HANDLER(SIOCGIWENCODE, std_get_encode),/* factory mode used */ + IW_HANDLER(SIOCSIWPOWER, std_set_power), + IW_HANDLER(SIOCGIWPOWER, std_get_power), /* factory mode used */ + IW_HANDLER(SIOCSIWAUTH, std_set_auth), +#if (WIRELESS_EXT > 17) + IW_HANDLER(SIOCSIWGENIE, std_set_genie), +#endif + IW_HANDLER(SIOCSIWENCODEEXT, std_set_encode_ext), + IW_HANDLER(SIOCSIWPMKSA, std_set_pmska), +}; + +const struct iw_handler_def wext_handler_def = { + .num_standard = (__u16) sizeof(mtk_std_handler) / sizeof(iw_handler), +#ifdef CONFIG_WEXT_PRIV + .num_private = (__u16) sizeof(rIwPrivHandler) / sizeof(iw_handler), + .num_private_args = (__u16) sizeof(rIwPrivTable) / + sizeof(struct iw_priv_args), +#endif + .standard = (iw_handler *) mtk_std_handler, +#ifdef CONFIG_WEXT_PRIV + .private = rIwPrivHandler, + .private_args = rIwPrivTable, +#endif + .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 + ******************************************************************************* + */ +static void wext_support_ioctl_SIOCSIWGENIE( + IN struct net_device *prDev, IN char *prExtraBuf, + IN uint32_t u4ExtraSize); + +static void +wext_support_ioctl_SIOCSIWPMKSA_Action(IN struct net_device + *prDev, IN char *prExtraBuf, IN int ioMode, OUT int *ret); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#if 0 /* not in use */ +void MAP_CHANNEL_ID_TO_KHZ(uint32_t ch, uint32_t 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: + khz = 5220000; + break; + case 48: + khz = 5240000; + break; + case 52: + khz = 5260000; + break; + case 56: + khz = 5280000; + break; + case 60: + khz = 5300000; + break; + case 64: + khz = 5320000; + break; + case 149: + khz = 5745000; + break; + case 153: + khz = 5765000; + break; + case 157: + 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; + } +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t +wextSrchDesiredWPAIE(IN uint8_t *pucIEStart, + IN int32_t i4TotalIeLen, IN uint8_t ucDesiredElemId, + OUT uint8_t **ppucDesiredIE) +{ + int32_t i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (int32_t) pucIEStart[1] + 2; + + if (pucIEStart[0] == ucDesiredElemId + && i4InfoElemLen <= i4TotalIeLen) { + if (ucDesiredElemId != 0xDD) { + /* Non 0xDD, OK! */ + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } /* EID == 0xDD, check WPA IE */ + if (pucIEStart[1] >= 4) { + if (memcmp(&pucIEStart[2], "\x00\x50\xf2\x01", + 4) == 0) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + } /* check WPA IE length */ + /* check EID == 0xDD */ + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* parseSearchDesiredWPAIE */ + +#if CFG_SUPPORT_WAPI +/*----------------------------------------------------------------------------*/ +/*! + * \brief Find the desired WAPI Information Element . + * + * \param[in] pucIEStart IE starting address. + * \param[in] i4TotalIeLen Total length of all the IE. + * \param[out] ppucDesiredIE Pointer to the desired IE. + * + * \retval TRUE Find the desired IE. + * \retval FALSE Desired IE not found. + * + * \note + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wextSrchDesiredWAPIIE(IN uint8_t *pucIEStart, + IN int32_t i4TotalIeLen, OUT uint8_t **ppucDesiredIE) +{ + int32_t i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (int32_t) 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_PASSPOINT +/*----------------------------------------------------------------------------*/ +/*! + * \brief Check if exist the desired HS2.0 Information Element according to + * desiredElemID. + * + * \param[in] pucIEStart IE starting address. + * \param[in] i4TotalIeLen Total length of all the IE. + * \param[in] ucDesiredElemId Desired element ID. + * \param[out] ppucDesiredIE Pointer to the desired IE. + * + * \retval TRUE Find the desired IE. + * \retval FALSE Desired IE not found. + * + * \note + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wextIsDesiredHS20IE(IN uint8_t *pucCurIE, + IN int32_t i4TotalIeLen) +{ + int32_t i4InfoElemLen; + + ASSERT(pucCurIE); + + i4InfoElemLen = (int32_t) pucCurIE[1] + 2; + + if (pucCurIE[0] == ELEM_ID_VENDOR + && i4InfoElemLen <= i4TotalIeLen) { + if (pucCurIE[1] >= ELEM_MIN_LEN_HS20_INDICATION) { + if (memcmp(&pucCurIE[2], "\x50\x6f\x9a\x10", 4) == 0) + return TRUE; + } + } + /* check desired EID */ + return FALSE; +} /* wextIsDesiredHS20IE */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Check if exist the desired interworking Information Element according + * to desiredElemID. + * + * \param[in] pucIEStart IE starting address. + * \param[in] i4TotalIeLen Total length of all the IE. + * \param[in] ucDesiredElemId Desired element ID. + * \param[out] ppucDesiredIE Pointer to the desired IE. + * + * \retval TRUE Find the desired IE. + * \retval FALSE Desired IE not found. + * + * \note + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wextIsDesiredInterworkingIE(IN uint8_t *pucCurIE, + IN int32_t i4TotalIeLen) +{ + int32_t i4InfoElemLen; + + ASSERT(pucCurIE); + + i4InfoElemLen = (int32_t) pucCurIE[1] + 2; + + if (pucCurIE[0] == ELEM_ID_INTERWORKING + && i4InfoElemLen <= i4TotalIeLen) { + switch (pucCurIE[1]) { + case IW_IE_LENGTH_ANO: + case IW_IE_LENGTH_ANO_HESSID: + case IW_IE_LENGTH_ANO_VENUE: + case IW_IE_LENGTH_ANO_VENUE_HESSID: + return TRUE; + default: + break; + } + + } + /* check desired EID */ + return FALSE; +} /* wextIsDesiredInterworkingIE */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Check if exist the desired Adv Protocol Information Element according + * to desiredElemID. + * + * \param[in] pucIEStart IE starting address. + * \param[in] i4TotalIeLen Total length of all the IE. + * \param[in] ucDesiredElemId Desired element ID. + * \param[out] ppucDesiredIE Pointer to the desired IE. + * + * \retval TRUE Find the desired IE. + * \retval FALSE Desired IE not found. + * + * \note + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wextIsDesiredAdvProtocolIE(IN uint8_t *pucCurIE, + IN int32_t i4TotalIeLen) +{ + int32_t i4InfoElemLen; + + ASSERT(pucCurIE); + + i4InfoElemLen = (int32_t) pucCurIE[1] + 2; + + if (pucCurIE[0] == ELEM_ID_ADVERTISEMENT_PROTOCOL + && i4InfoElemLen <= i4TotalIeLen) + return TRUE; + /* check desired EID */ + return FALSE; +} /* wextIsDesiredAdvProtocolIE */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Check if exist the desired Roaming Consortium Information Element + * according to desiredElemID. + * + * \param[in] pucIEStart IE starting address. + * \param[in] i4TotalIeLen Total length of all the IE. + * \param[in] ucDesiredElemId Desired element ID. + * \param[out] ppucDesiredIE Pointer to the desired IE. + * + * \retval TRUE Find the desired IE. + * \retval FALSE Desired IE not found. + * + * \note + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wextIsDesiredRoamingConsortiumIE( + IN uint8_t *pucCurIE, IN int32_t i4TotalIeLen) +{ + int32_t i4InfoElemLen; + + ASSERT(pucCurIE); + + i4InfoElemLen = (int32_t) pucCurIE[1] + 2; + + if (pucCurIE[0] == ELEM_ID_ROAMING_CONSORTIUM + && i4InfoElemLen <= i4TotalIeLen) + return TRUE; + /* check desired EID */ + return FALSE; +} /* wextIsDesiredRoamingConsortiumIE */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Find the desired HS2.0 Information Element according to desiredElemID. + * + * \param[in] pucIEStart IE starting address. + * \param[in] i4TotalIeLen Total length of all the IE. + * \param[in] ucDesiredElemId Desired element ID. + * \param[out] ppucDesiredIE Pointer to the desired IE. + * + * \retval TRUE Find the desired IE. + * \retval FALSE Desired IE not found. + * + * \note + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wextSrchDesiredHS20IE(IN uint8_t *pucIEStart, + IN int32_t i4TotalIeLen, OUT uint8_t **ppucDesiredIE) +{ + int32_t i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (int32_t) pucIEStart[1] + 2; + + if (pucIEStart[0] == ELEM_ID_VENDOR + && i4InfoElemLen <= i4TotalIeLen) { + if (pucIEStart[1] >= ELEM_MIN_LEN_HS20_INDICATION) { + if (memcmp(&pucIEStart[2], "\x50\x6f\x9a\x10", + 4) == 0) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + } + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* wextSrchDesiredHS20IE */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Find the desired HS2.0 Information Element according to desiredElemID. + * + * \param[in] pucIEStart IE starting address. + * \param[in] i4TotalIeLen Total length of all the IE. + * \param[in] ucDesiredElemId Desired element ID. + * \param[out] ppucDesiredIE Pointer to the desired IE. + * + * \retval TRUE Find the desired IE. + * \retval FALSE Desired IE not found. + * + * \note + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wextSrchDesiredOsenIE(IN uint8_t *pucIEStart, + IN int32_t i4TotalIeLen, OUT uint8_t **ppucDesiredIE) +{ + int32_t i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (int32_t) pucIEStart[1] + 2; + if (pucIEStart[0] == ELEM_ID_VENDOR + && i4InfoElemLen <= i4TotalIeLen) { + if (pucIEStart[1] >= 4) { + if (memcmp(&pucIEStart[2], "\x50\x6f\x9a\x12", + 4) == 0) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + } + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Find the desired Adv Protocol Information Element according to + * desiredElemID. + * + * \param[in] pucIEStart IE starting address. + * \param[in] i4TotalIeLen Total length of all the IE. + * \param[in] ucDesiredElemId Desired element ID. + * \param[out] ppucDesiredIE Pointer to the desired IE. + * + * \retval TRUE Find the desired IE. + * \retval FALSE Desired IE not found. + * + * \note + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wextSrchDesiredAdvProtocolIE(IN uint8_t + *pucIEStart, IN int32_t i4TotalIeLen, + OUT uint8_t **ppucDesiredIE) +{ + int32_t i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (int32_t) pucIEStart[1] + 2; + + if (pucIEStart[0] == ELEM_ID_ADVERTISEMENT_PROTOCOL + && i4InfoElemLen <= i4TotalIeLen) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* wextSrchDesiredAdvProtocolIE */ + +#endif /* CFG_SUPPORT_PASSPOINT */ + +#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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t +wextSrchDesiredWPSIE(IN uint8_t *pucIEStart, + IN int32_t i4TotalIeLen, IN uint8_t ucDesiredElemId, + OUT uint8_t **ppucDesiredIE) +{ + int32_t i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (int32_t) pucIEStart[1] + 2; + + if (pucIEStart[0] == ucDesiredElemId + && i4InfoElemLen <= i4TotalIeLen) { + if (ucDesiredElemId != 0xDD) { + /* Non 0xDD, OK! */ + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + /* EID == 0xDD, check WPS IE */ + if (pucIEStart[1] >= 4) { + if (memcmp(&pucIEStart[2], "\x00\x50\xf2\x04", + 4) == 0) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + } /* check WPS IE length */ + /* check EID == 0xDD */ + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* parseSearchDesiredWPSIE */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Get the name of the protocol used on the air. + * + * \param[in] prDev Net device requested. + * \param[in] prIwrInfo NULL. + * \param[out] pcName Buffer to store protocol name string + * \param[in] pcExtra NULL. + * + * \retval 0 For success. + * + * \note If netif_carrier_ok, protocol name is returned; + * otherwise, "disconnected" is returned. + */ +/*----------------------------------------------------------------------------*/ +static int +wext_get_name(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + OUT char *pcName, IN uint32_t pcNameSize, IN char *pcExtra) +{ + enum ENUM_PARAM_NETWORK_TYPE eNetWorkType; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(pcName); + if (GLUE_CHK_PR2(prNetDev, pcName) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (netif_carrier_ok(prNetDev)) { + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryNetworkTypeInUse, + &eNetWorkType, sizeof(eNetWorkType), + TRUE, FALSE, FALSE, &u4BufLen); + + switch (eNetWorkType) { + case PARAM_NETWORK_TYPE_DS: + strncpy(pcName, "IEEE 802.11b", pcNameSize); + break; + case PARAM_NETWORK_TYPE_OFDM24: + strncpy(pcName, "IEEE 802.11bgn", pcNameSize); + break; + case PARAM_NETWORK_TYPE_AUTOMODE: + case PARAM_NETWORK_TYPE_OFDM5: + strncpy(pcName, "IEEE 802.11abgn", pcNameSize); + break; + case PARAM_NETWORK_TYPE_FH: + default: + strncpy(pcName, "IEEE 802.11", pcNameSize); + break; + } + } else { + strncpy(pcName, "Disconnected", pcNameSize); + } + + pcName[pcNameSize - 1] = '\0'; + + 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 + uint32_t u4ChnlFreq; /* Store channel or frequency information */ + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prIwFreq); + if (GLUE_CHK_PR2(prNetDev, prIwFreq) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) 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 >= 2.412e8) + && (prIwFreq->m <= 2.484e8)) { + + /* Change to KHz format */ + u4ChnlFreq = (uint32_t) (prIwFreq->m / (KILO / 10)); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetFrequency, &u4ChnlFreq, + sizeof(u4ChnlFreq), + FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EINVAL; + } + /* Setting by channel number */ + else if ((prIwFreq->m > KILO) || (prIwFreq->e > 0)) + return -EOPNOTSUPP; + /* Change to channel number format */ + u4ChnlFreq = (uint32_t) prIwFreq->m; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetChannel, &u4ChnlFreq, + sizeof(u4ChnlFreq), FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + 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) +{ + uint32_t u4Channel = 0; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prIwFreq); + if (GLUE_CHK_PR2(prNetDev, prIwFreq) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) 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, &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) +{ + struct PARAM_OP_MODE rOpMode; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + struct GL_WPA_INFO *prWpaInfo; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + ASSERT(prNetDev); + ASSERT(pu4Mode); + if (GLUE_CHK_PR2(prNetDev, pu4Mode) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + switch (*pu4Mode) { + case IW_MODE_AUTO: + rOpMode.eOpMode = NET_TYPE_AUTO_SWITCH; + break; + + case IW_MODE_ADHOC: + rOpMode.eOpMode = NET_TYPE_IBSS; + break; + + case IW_MODE_INFRA: + rOpMode.eOpMode = NET_TYPE_INFRA; + break; + + default: + DBGLOG(INIT, INFO, "%s(): Set UNSUPPORTED Mode = %d.\n", + __func__, *pu4Mode); + return -EOPNOTSUPP; + } + + /* printk("%s(): Set Mode = %d\n", __FUNCTION__, *pu4Mode); */ + rOpMode.ucBssIdx = ucBssIndex; + rStatus = kalIoctl(prGlueInfo, wlanoidSetInfrastructureMode, + (void *)&rOpMode, sizeof(struct PARAM_OP_MODE), + FALSE, FALSE, TRUE, &u4BufLen); + + /* after set operation mode, key table are cleared */ + + prWpaInfo = aisGetWpaInfo(prGlueInfo->prAdapter, + ucBssIndex); + + /* reset wpa info */ + prWpaInfo->u4WpaVersion = + IW_AUTH_WPA_VERSION_DISABLED; + prWpaInfo->u4KeyMgmt = 0; + prWpaInfo->u4CipherGroup = IW_AUTH_CIPHER_NONE; + prWpaInfo->u4CipherPairwise = IW_AUTH_CIPHER_NONE; + prWpaInfo->u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; +#if CFG_SUPPORT_802_11W + prWpaInfo->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 ENUM_PARAM_OP_MODE eOpMode; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(pu4Mode); + if (GLUE_CHK_PR2(prNetDev, pu4Mode) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryInfrastructureMode, &eOpMode, + sizeof(eOpMode), TRUE, 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", __func__); + return -EINVAL; + } + + return 0; +} /* wext_get_mode */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To get the valid range for each configurable STA setting value. + * + * \param[in] prDev Net device requested. + * \param[in] prIwrInfo NULL. + * \param[in] prData Pointer to iw_point structure, not used. + * \param[out] pcExtra Pointer to buffer which is allocated by caller of this + * function, wext_support_ioctl() or ioctl_standard_call() + * in wireless.c. + * + * \retval 0 If data is valid. + * + * \note The extra buffer (pcExtra) is filled with information from driver. + */ +/*----------------------------------------------------------------------------*/ +static int +wext_get_range(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + IN struct iw_point *prData, OUT char *pcExtra) +{ + struct iw_range *prRange = NULL; + uint8_t aucSuppRate[PARAM_MAX_LEN_RATES_EX] = { 0 }; /* data buffers */ + int i = 0; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(pcExtra); + if (GLUE_CHK_PR2(prNetDev, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) 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, &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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + ASSERT(prNetDev); + ASSERT(prAddr); + if (GLUE_CHK_PR2(prNetDev, prAddr) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + /* if (!netif_carrier_ok(prNetDev)) { */ + /* return -ENOTCONN; */ + /* } */ + + if (kalGetMediaStateIndicated(prGlueInfo, + ucBssIndex) == + MEDIA_STATE_DISCONNECTED) { + memset(prAddr, 0, sizeof(struct sockaddr)); + return 0; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryBssid, prAddr->sa_data, + ETH_ALEN, TRUE, 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; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(pcExtra); + if (GLUE_CHK_PR2(prNetDev, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) 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, &u4BufLen); + return 0; + } + 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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int essid_len = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_DEV(prNetDev) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) 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, &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) +{ + uint32_t i = 0; + uint32_t j = 0; + struct PARAM_BSSID_LIST_EX *prList = NULL; + struct PARAM_BSSID_EX *prBss = NULL; + struct PARAM_VARIABLE_IE *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 */ + + uint32_t u4AllocBufLen = 0; + + /* arrange rate information */ + uint32_t u4HighestRate = 0; + char aucRatesBuf[64]; + uint32_t u4BufIndex; + + /* return value */ + int ret = 0; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prData); + ASSERT(pcExtra); + if (GLUE_CHK_PR3(prNetDev, prData, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) 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, &u4BufLen); + + if (rStatus == WLAN_STATUS_INVALID_LENGTH) { + /* Buffer length is not large enough. */ + /* printk(KERN_INFO "[wifi] buf:%d result:%d\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 :%d\n", + u4BufLen); + ret = -ENOMEM; + goto error; + } + prList->NumberOfItems = 0; + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryBssidList, prList, + u4AllocBufLen, + TRUE, FALSE, FALSE, &u4BufLen); + + if (rStatus == WLAN_STATUS_INVALID_LENGTH) { + DBGLOG(INIT, INFO, "[wifi] larger buf:%d result:%d\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:%d\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; + kalMemCopy(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 = snprintf(aucRatesBuf, sizeof(aucRatesBuf), + "Rates (Mb/s):"); + u4HighestRate = 0; + for (j = 0; j < PARAM_MAX_LEN_RATES_EX; ++j) { + uint8_t curRate = prBss->rSupportedRates[j] & 0x7F; + + if (curRate == 0) + break; + + if (curRate > u4HighestRate) + u4HighestRate = curRate; + + if (curRate == RATE_5_5M) + u4BufIndex += snprintf(aucRatesBuf + u4BufIndex, + sizeof(aucRatesBuf) + - u4BufIndex, " 5.5"); + else + u4BufIndex += snprintf(aucRatesBuf + u4BufIndex, + sizeof(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( + struct PARAM_FIXED_IEs)], + prBss->u4IELength - sizeof(struct PARAM_FIXED_IEs), 0xDD, + (uint8_t **) &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( + struct PARAM_FIXED_IEs)], + prBss->u4IELength - sizeof(struct PARAM_FIXED_IEs), 0xDD, + (uint8_t **) &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( + struct PARAM_FIXED_IEs)], + prBss->u4IELength - sizeof(struct PARAM_FIXED_IEs), 0x30, + (uint8_t **) &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(struct PARAM_FIXED_IEs)], + prBss->u4IELength - sizeof(struct PARAM_FIXED_IEs), + (uint8_t **) &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, + (uint8_t *) 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 = (struct PARAM_BSSID_EX *) ((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:%d\n", + * pData->length, u4BufLen); + */ + + /* kalIndicateStatusAndComplete(prGlueInfo, + * WLAN_STATUS_SCAN_COMPLETE, NULL, 0); + */ + +error: + /* free local query buffer */ + if (prList) + kalMemFree(prList, VIR_MEM_TYPE, u4AllocBufLen); + + return ret; +} /* wext_get_scan */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To set desired network name ESSID. + * + * \param[in] prDev Net device requested. + * \param[in] prIwrInfo NULL. + * \param[in] prEssid Pointer of iw_point header. + * \param[in] pcExtra Pointer to buffer srtoring essid string. + * + * \retval 0 If netif_carrier_ok. + * \retval -E2BIG Essid string length is too big. + * \retval -EINVAL pcExtra is null pointer. + * \retval -EFAULT Driver fail to set new essid. + * + * \note If string length is ok, device will try connecting to the new network. + */ +/*----------------------------------------------------------------------------*/ +static int +wext_set_essid(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + IN struct iw_point *prEssid, IN char *pcExtra) +{ + struct PARAM_SSID rNewSsid; + uint32_t cipher; + enum ENUM_WEP_STATUS eEncStatus; + enum ENUM_PARAM_AUTH_MODE eAuthMode; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + struct GL_WPA_INFO *prWpaInfo; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + ASSERT(prNetDev); + ASSERT(prEssid); + ASSERT(pcExtra); + if (GLUE_CHK_PR3(prNetDev, prEssid, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (prEssid->length > IW_ESSID_MAX_SIZE) + return -E2BIG; + + prWpaInfo = aisGetWpaInfo(prGlueInfo->prAdapter, + ucBssIndex); + + /* set auth mode */ + if (prWpaInfo->u4WpaVersion == + IW_AUTH_WPA_VERSION_DISABLED) { + eAuthMode = (prWpaInfo->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 (prWpaInfo->u4KeyMgmt) { + case IW_AUTH_KEY_MGMT_802_1X: + eAuthMode = + (prWpaInfo->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 = + (prWpaInfo->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 : %d set auto switch\n", + * prWpaInfo->u4KeyMgmt); + */ + eAuthMode = AUTH_MODE_AUTO_SWITCH; + break; + } + } + + rStatus = kalIoctl(prGlueInfo, wlanoidSetAuthMode, &eAuthMode, + sizeof(eAuthMode), FALSE, FALSE, FALSE, &u4BufLen); + + /* set encryption status */ + cipher = prWpaInfo->u4CipherGroup | + prWpaInfo->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 (prWpaInfo->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, &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(%u): %s\n", rNewSsid.u4SsidLen, rNewSsid.aucSsid); + */ + if (kalIoctl(prGlueInfo, + wlanoidSetSsid, + (void *)&rNewSsid, sizeof(struct PARAM_SSID), FALSE, FALSE, + TRUE, &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; */ + + struct PARAM_SSID *prSsid; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prEssid); + ASSERT(pcExtra); + + if (GLUE_CHK_PR3(prNetDev, prEssid, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + /* if (!netif_carrier_ok(prNetDev)) { */ + /* return -ENOTCONN; */ + /* } */ + + prSsid = kalMemAlloc(sizeof(struct PARAM_SSID), + VIR_MEM_TYPE); + + if (!prSsid) + return -ENOMEM; + rStatus = kalIoctl(prGlueInfo, wlanoidQuerySsid, prSsid, + sizeof(struct PARAM_SSID), + TRUE, 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(struct PARAM_SSID)); + + 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) +{ + uint8_t aucSuppRate[PARAM_MAX_LEN_RATES_EX] = { 0 }; + uint8_t aucNewRate[PARAM_MAX_LEN_RATES_EX] = { 0 }; + uint32_t u4NewRateLen = 0; + uint32_t i; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prRate); + if (GLUE_CHK_PR2(prNetDev, prRate) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) 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 = %d\n", + * u4BufLen); + */ + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetDesiredRates, + &aucSuppRate, + sizeof(aucSuppRate), + &u4BufLen); + return 0; + } + /* iwconfig wlan0 rate fixed */ + + /* fix rate to what? DO NOTHING */ + return -EINVAL; + } + + aucNewRate[0] = prRate->value / + 500000; /* In unit of 500k */ + + for (i = 0; i < PARAM_MAX_LEN_RATES_EX; i++) { + /* check the given value is supported */ + if (aucSuppRate[i] == 0) + break; + + if (aucNewRate[0] == aucSuppRate[i]) { + u4NewRateLen = 1; + break; + } + } + + if (u4NewRateLen == 0) { + /* the given value is not supported */ + /* return error or use given rate as upper bound? */ + return -EINVAL; + } + + if (prRate->fixed == 0) { + /* add all rates lower than desired rate */ + for (i = 0; i < PARAM_MAX_LEN_RATES_EX; ++i) { + if (aucSuppRate[i] == 0) + break; + + if (aucSuppRate[i] < aucNewRate[0]) + aucNewRate[u4NewRateLen++] = aucSuppRate[i]; + } + } + + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetDesiredRates, &aucNewRate, + sizeof(aucNewRate), &u4BufLen); + return 0; +} /* wext_set_rate */ + +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To get current tx bit rate. + * + * \param[in] prDev Net device requested. + * \param[in] prIwrInfo NULL. + * \param[out] prRate Pointer to iw_param structure to store current tx rate. + * \param[in] pcExtra NULL. + * + * \retval 0 If netif_carrier_ok. + * \retval -ENOTCONN Otherwise. + * + * \note If netif_carrier_ok, current tx rate is stored in pRate. + */ +/*----------------------------------------------------------------------------*/ +static int +wext_get_rate(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + OUT struct iw_param *prRate, IN char *pcExtra) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_LINK_SPEED_EX rLinkSpeed; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + uint32_t u4Rate = 0; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + ASSERT(prNetDev); + ASSERT(prRate); + if (GLUE_CHK_PR2(prNetDev, prRate) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ucBssIndex = wlanGetBssIdx(prNetDev); + + if (!netif_carrier_ok(prNetDev)) + return -ENOTCONN; + + if (ucBssIndex >= BSSID_NUM) + return -EFAULT; + + rStatus = kalIoctlByBssIdx(prGlueInfo, wlanoidQueryLinkSpeedEx, + &rLinkSpeed, sizeof(rLinkSpeed), + TRUE, FALSE, FALSE, + &u4BufLen, ucBssIndex); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + u4Rate = rLinkSpeed.rLq[ucBssIndex].u2LinkSpeed; + /* u4Rate is in unit of 100bps */ + prRate->value = u4Rate * 100; + 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) +{ + uint32_t u4RtsThresh; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prRts); + if (GLUE_CHK_PR2(prNetDev, prRts) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (prRts->value < 0 || prRts->value > 2347) + return -EINVAL; + + if (prRts->disabled == 1) + u4RtsThresh = 2347; + else + u4RtsThresh = (uint32_t) prRts->value; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetRtsThreshold, &u4RtsThresh, + sizeof(u4RtsThresh), + 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) +{ + uint32_t u4RtsThresh; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prRts); + if (GLUE_CHK_PR2(prNetDev, prRts) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryRtsThreshold, &u4RtsThresh, + sizeof(u4RtsThresh), TRUE, 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; */ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prTxPow); + if (GLUE_CHK_PR2(prNetDev, prTxPow) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (prTxPow->disabled) { + /* <1> disconnect */ + rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, NULL, + 0, FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + /* ToDo:: DBGLOG */ + DBGLOG(INIT, INFO, "######set disassoc failed\n"); + } else { + DBGLOG(INIT, INFO, "######set assoc ok\n"); + } + /* <2> mark to power state flag */ + DBGLOG(INIT, INFO, "set to acpi d3(0)\n"); + wlanSetAcpiState(prGlueInfo->prAdapter, ACPI_STATE_D0); + + } else { + DBGLOG(INIT, INFO, "set to acpi d0\n"); + wlanSetAcpiState(prGlueInfo->prAdapter, ACPI_STATE_D0); + } + + prGlueInfo->ePowerState = ParamDeviceStateD0; + 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; */ + + struct GLUE_INFO *prGlueInfo = NULL; + + ASSERT(prNetDev); + ASSERT(prTxPow); + if (GLUE_CHK_PR2(prNetDev, prTxPow) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + /* GeorgeKuo: wlanoidQueryAcpiDevicePowerState() reports capability, not + * current state. Use struct GLUE_INFO 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 ENUM_WEP_STATUS eEncMode; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prEnc); + if (GLUE_CHK_PR2(prNetDev, prEnc) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryEncryptionStatus, &eEncMode, + sizeof(eEncMode), TRUE, 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 uint8_t 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 ENUM_WEP_STATUS eEncStatus; + enum ENUM_PARAM_AUTH_MODE eAuthMode; + /* UINT_8 wepBuf[48]; */ + struct PARAM_WEP *prWepKey = (struct PARAM_WEP *) wepBuf; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + struct GL_WPA_INFO *prWpaInfo; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + ASSERT(prNetDev); + ASSERT(prEnc); + ASSERT(pcExtra); + if (GLUE_CHK_PR3(prNetDev, prEnc, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + prWpaInfo = aisGetWpaInfo(prGlueInfo->prAdapter, + ucBssIndex); + + /* reset to default mode */ + prWpaInfo->u4WpaVersion = + IW_AUTH_WPA_VERSION_DISABLED; + prWpaInfo->u4KeyMgmt = 0; + prWpaInfo->u4CipherPairwise = IW_AUTH_CIPHER_NONE; + prWpaInfo->u4CipherGroup = IW_AUTH_CIPHER_NONE; + prWpaInfo->u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; +#if CFG_SUPPORT_802_11W + prWpaInfo->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, &u4BufLen); + + eEncStatus = ENUM_ENCRYPTION_DISABLED; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetEncryptionStatus, + &eEncStatus, sizeof(eEncStatus), + 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, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "wlanoidSetAddWep fail 0x%x\n", + rStatus); + return -EFAULT; + } + + /* change to auto switch */ + prWpaInfo->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, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + /* printk(KERN_INFO DRV_NAME + * "wlanoidSetAuthMode fail 0x%x\n", rStatus); + */ + return -EFAULT; + } + + prWpaInfo->u4CipherPairwise = + IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40; + prWpaInfo->u4CipherGroup = IW_AUTH_CIPHER_WEP104 | + IW_AUTH_CIPHER_WEP40; + + eEncStatus = ENUM_WEP_ENABLED; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEncryptionStatus, + &eEncStatus, sizeof(enum ENUM_WEP_STATUS), + FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + /* printk(KERN_INFO DRV_NAME + * "wlanoidSetEncryptionStatus fail 0x%x\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 + enum PARAM_POWER_MODE ePowerMode; + int32_t i4PowerValue; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + struct PARAM_POWER_MODE_ rPowerMode; + + ASSERT(prNetDev); + ASSERT(prPower); + if (GLUE_CHK_PR2(prNetDev, prPower) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (!prGlueInfo) + return -EFAULT; + + /* 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", + __func__, prPower->value); + + return -EINVAL; + } + } + + rPowerMode.ePowerMode = ePowerMode; + rPowerMode.ucBssIdx = wlanGetBssIdx(prNetDev); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, sizeof(struct PARAM_POWER_MODE_), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + /* printk(KERN_INFO DRV_NAME + * "wlanoidSet802dot11PowerSaveProfile fail 0x%x\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) +{ + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + enum PARAM_POWER_MODE ePowerMode = Param_PowerModeCAM; + + ASSERT(prNetDev); + ASSERT(prPower); + if (GLUE_CHK_PR2(prNetDev, prPower) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) 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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct GL_WPA_INFO *prWpaInfo; + struct CONNECTION_SETTINGS *prConnSettings; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + ASSERT(prNetDev); + ASSERT(prAuth); + if (GLUE_CHK_PR2(prNetDev, prAuth) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + prWpaInfo = aisGetWpaInfo(prGlueInfo->prAdapter, + ucBssIndex); + prConnSettings = aisGetConnSettings(prGlueInfo->prAdapter, + ucBssIndex); + + /* 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 (aisGetWapiMode(prGlueInfo->prAdapter, + ucBssIndex)) { + prWpaInfo->u4WpaVersion = + IW_AUTH_WPA_VERSION_DISABLED; + prWpaInfo->u4AuthAlg = + IW_AUTH_ALG_OPEN_SYSTEM; + } else { + prWpaInfo->u4WpaVersion = prAuth->value; + } +#else + prWpaInfo->u4WpaVersion = prAuth->value; +#endif + break; + + case IW_AUTH_CIPHER_PAIRWISE: + prWpaInfo->u4CipherPairwise = prAuth->value; + break; + + case IW_AUTH_CIPHER_GROUP: + prWpaInfo->u4CipherGroup = prAuth->value; + break; + + case IW_AUTH_KEY_MGMT: + prWpaInfo->u4KeyMgmt = prAuth->value; +#if CFG_SUPPORT_WAPI + if (prWpaInfo->u4KeyMgmt == + IW_AUTH_KEY_MGMT_WAPI_PSK || + prWpaInfo->u4KeyMgmt == + IW_AUTH_KEY_MGMT_WAPI_CERT) { + uint32_t u4BufLen; + uint32_t rStatus; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetWapiMode, + &prAuth->value, sizeof(uint32_t), + FALSE, FALSE, TRUE, &u4BufLen); + DBGLOG(INIT, INFO, "IW_AUTH_WAPI_ENABLED :%d\n", + prAuth->value); + } +#endif + if (prWpaInfo->u4KeyMgmt == IW_AUTH_KEY_MGMT_WPS) + prConnSettings->fgWpsActive = TRUE; + else + prConnSettings->fgWpsActive = FALSE; + break; + + case IW_AUTH_80211_AUTH_ALG: + prWpaInfo->u4AuthAlg = prAuth->value; + break; + + case IW_AUTH_PRIVACY_INVOKED: + prWpaInfo->fgPrivacyInvoke = prAuth->value; + break; +#if CFG_SUPPORT_802_11W + case IW_AUTH_MFP: + /* printk("wext_set_auth IW_AUTH_MFP=%d\n", prAuth->value); */ + prWpaInfo->u4Mfp = prAuth->value; + break; +#endif +#if CFG_SUPPORT_WAPI + case IW_AUTH_WAPI_ENABLED: { + uint32_t u4BufLen; + uint32_t rStatus; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetWapiMode, + &prAuth->value, sizeof(uint32_t), + FALSE, FALSE, TRUE, &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 +uint8_t keyStructBuf[1024]; /* add/remove key shared buffer */ +#else +uint8_t 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) +{ + struct PARAM_REMOVE_KEY *prRemoveKey = + (struct PARAM_REMOVE_KEY *) keyStructBuf; + struct PARAM_KEY *prKey = (struct PARAM_KEY *) keyStructBuf; + + struct PARAM_WEP *prWepKey = (struct PARAM_WEP *) wepBuf; + + struct iw_encode_ext *prIWEncExt = (struct iw_encode_ext *) + pcExtra; + + enum ENUM_WEP_STATUS eEncStatus; + enum ENUM_PARAM_AUTH_MODE eAuthMode; + /* ENUM_PARAM_OP_MODE_T eOpMode = NET_TYPE_AUTO_SWITCH; */ + +#if CFG_SUPPORT_WAPI + struct PARAM_WPI_KEY *prWpiKey = (struct PARAM_WPI_KEY *) + keyStructBuf; +#endif + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + struct GL_WPA_INFO *prWpaInfo; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + ASSERT(prNetDev); + ASSERT(prEnc); + if (GLUE_CHK_PR3(prNetDev, prEnc, pcExtra) == FALSE) + return -EINVAL; + + if (prIWEncExt == NULL) { + DBGLOG(REQ, ERROR, "prIWEncExt is NULL!\n"); + return -EINVAL; + } + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + prWpaInfo = aisGetWpaInfo(prGlueInfo->prAdapter, + ucBssIndex); + + 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[0], &prIWEncExt->tx_seq[0], + IW_ENCODE_SEQ_MAX_SIZE); + memcpy(&prWpiKey->aucPN[IW_ENCODE_SEQ_MAX_SIZE], + &prIWEncExt->rx_seq[0], IW_ENCODE_SEQ_MAX_SIZE); + + /* 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; + prWpiKey->ucBssIdx = ucBssIndex; + rStatus = kalIoctl(prGlueInfo, wlanoidSetWapiKey, prWpiKey, + sizeof(struct PARAM_WPI_KEY), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + /* do nothing */ + /* printk(KERN_INFO "[wapi] add key error:%x\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)); + */ + prRemoveKey->ucBssIdx = ucBssIndex; + rStatus = kalIoctl(prGlueInfo, wlanoidSetRemoveKey, + prRemoveKey, prRemoveKey->u4Length, + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "remove key error:%x\n", + rStatus); + return 0; + } + /* return 0; */ + /* printk ("alg %x\n", prIWEncExt->alg); */ + + switch (prIWEncExt->alg) { + case IW_ENCODE_ALG_NONE: + break; + case IW_ENCODE_ALG_WEP: + /* iwconfig wlan0 key 0123456789 */ + /* iwconfig wlan0 key s:abcde */ + /* iwconfig wlan0 key 0123456789 [1] */ + /* iwconfig wlan0 key 01234567890123456789012345 [1] */ + /* check key size for WEP */ + if (prIWEncExt->key_len == 5 || + prIWEncExt->key_len == 13 || + prIWEncExt->key_len == 16) { + /* prepare PARAM_WEP key structure */ + prWepKey->u4KeyIndex = + (prEnc->flags & IW_ENCODE_INDEX) ? + (prEnc->flags & IW_ENCODE_INDEX) - 1 : + 0; + if (prWepKey->u4KeyIndex > 3) { + /* key id is out of range */ + return -EINVAL; + } + prWepKey->u4KeyIndex |= 0x80000000; + prWepKey->u4Length = 12 + prIWEncExt->key_len; + prWepKey->u4KeyLength = prIWEncExt->key_len; + /* kalMemCopy(prWepKey->aucKeyMaterial, pcExtra, + * prIWEncExt->key_len); + */ + kalMemCopy(prWepKey->aucKeyMaterial, + prIWEncExt->key, + prIWEncExt->key_len); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAddWep, + prWepKey, prWepKey->u4Length, + FALSE, FALSE, TRUE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, + "wlanoidSetAddWep fail 0x%x\n", + rStatus); + return -EFAULT; + } + + /* change to auto switch */ + prWpaInfo->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, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, + "wlanoidSetAuthMode fail 0x%x\n", + rStatus); + return -EFAULT; + } + + prWpaInfo->u4CipherPairwise = + IW_AUTH_CIPHER_WEP104 | + IW_AUTH_CIPHER_WEP40; + prWpaInfo->u4CipherGroup = + IW_AUTH_CIPHER_WEP104 | + IW_AUTH_CIPHER_WEP40; + + eEncStatus = ENUM_WEP_ENABLED; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEncryptionStatus, + &eEncStatus, + sizeof(enum ENUM_WEP_STATUS), + FALSE, FALSE, FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, + "wlanoidSetEncryptionStatus fail 0x%x\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%x\n", + prKey->u4KeyIndex); + /* key id is out of range */ + return -EINVAL; + } + + /* bit(31) and bit(30) are shared by pKey and + * pRemoveKey + */ + /* Tx Key Bit(31) */ + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + prKey->u4KeyIndex |= 0x1UL << 31; + + /* 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(((uint8_t *) prKey->aucKeyMaterial) + 16, + prIWEncExt->key + 24, 8); + memcpy((prKey->aucKeyMaterial) + 24, + prIWEncExt->key + 16, 8); + } else { + if (prIWEncExt->key_len > + sizeof(prKey->aucKeyMaterial)) { + DBGLOG(REQ, ERROR, + "prIWEncExt->key_len: %u is too long!\n", + prIWEncExt->key_len); + return -EINVAL; + } + memcpy(prKey->aucKeyMaterial, prIWEncExt->key, + prIWEncExt->key_len); + } + + prKey->u4KeyLength = prIWEncExt->key_len; + prKey->u4Length = ((unsigned long) &(((struct PARAM_KEY *) + 0)->aucKeyMaterial)) + prKey->u4KeyLength; + prKey->ucBssIdx = ucBssIndex; + rStatus = kalIoctl(prGlueInfo, wlanoidSetAddKey, prKey, + prKey->u4Length, + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "add key error:%x\n", rStatus); + return -EFAULT; + } + break; + } + } + + return 0; +} /* wext_set_encode_ext */ + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Set country code + * + * \param[in] prNetDev Net device requested. + * \param[in] prData iwreq.u.data carries country code value. + * + * \retval 0 For success. + * \retval -EEFAULT For fail. + * + * \note Country code is stored and channel list is updated based on current + * country domain. + */ +/*----------------------------------------------------------------------------*/ +static int wext_set_country(IN struct net_device *prNetDev, + IN struct iw_point *prData) +{ + struct GLUE_INFO *prGlueInfo; + uint32_t rStatus; + uint32_t u4BufLen; + uint8_t aucCountry[COUNTRY_CODE_LEN]; + + ASSERT(prNetDev); + + /* prData->pointer should be like "COUNTRY US", "COUNTRY EU" + * and "COUNTRY JP" + */ + if (GLUE_CHK_PR2(prNetDev, prData) == FALSE + || !prData->pointer || prData->length < COUNTRY_CODE_LEN) + return -EINVAL; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (copy_from_user(aucCountry, prData->pointer, + COUNTRY_CODE_LEN)) + return -EFAULT; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetCountryCode, + &aucCountry[COUNTRY_CODE_LEN - 2], 2, + FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "Set country code error: %x\n", rStatus); + return -EFAULT; + } + + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To report the iw private args table to user space. + * + * \param[in] prNetDev Net device requested. + * \param[out] prData iwreq.u.data to carry the private args table. + * + * \retval 0 For success. + * \retval -E2BIG For user's buffer size is too small. + * \retval -EFAULT For fail. + * + */ +/*----------------------------------------------------------------------------*/ +int wext_get_priv(IN struct net_device *prNetDev, + OUT struct iw_point *prData) +{ + uint16_t u2BufferSize = prData->length; + + /* Update our private args table size */ + prData->length = (__u16)sizeof(rIwPrivTable); + if (u2BufferSize < prData->length) + return -E2BIG; + + if (prData->length) { + if (copy_to_user(prData->pointer, rIwPrivTable, + sizeof(rIwPrivTable))) + return -EFAULT; + } + + return 0; +} /* wext_get_priv */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief ioctl() (Linux Wireless Extensions) routines + * + * \param[in] prDev Net device requested. + * \param[in] ifr The ifreq structure for seeting the wireless extension. + * \param[in] i4Cmd The wireless extension ioctl command. + * + * \retval zero On success. + * \retval -EOPNOTSUPP If the cmd is not supported. + * \retval -EFAULT If copy_to_user goes wrong. + * \retval -EINVAL If any value's out of range. + * + * \note + */ +/*----------------------------------------------------------------------------*/ +int wext_support_ioctl(IN struct net_device *prDev, + IN struct ifreq *prIfReq, IN int i4Cmd) +{ + /* 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; + uint32_t 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, + sizeof(iwr->u.name), NULL); + break; + + /* case SIOCSIWNWID: 0x8B02, deprecated */ + /* case SIOCGIWNWID: 0x8B03, deprecated */ + + case SIOCSIWFREQ: /* 0x8B04, set channel */ + ret = wext_set_freq(prDev, NULL, &iwr->u.freq, NULL); + break; + + case SIOCGIWFREQ: /* 0x8B05, get channel */ + ret = wext_get_freq(prDev, NULL, &iwr->u.freq, NULL); + break; + + case SIOCSIWMODE: /* 0x8B06, set operation mode */ + ret = wext_set_mode(prDev, NULL, &iwr->u.mode, NULL); + /* ret = 0; */ + break; + + case SIOCGIWMODE: /* 0x8B07, get operation mode */ + ret = wext_get_mode(prDev, NULL, &iwr->u.mode, NULL); + break; + + /* case SIOCSIWSENS: 0x8B08, unsupported */ + /* case SIOCGIWSENS: 0x8B09, unsupported */ + + /* case SIOCSIWRANGE: 0x8B0A, unused */ + case SIOCGIWRANGE: /* 0x8B0B, get range of parameters */ + if (iwr->u.data.pointer != NULL) { + /* Buffer size should be large enough */ + if (iwr->u.data.length < sizeof(struct iw_range)) { + ret = -E2BIG; + break; + } + + prExtraBuf = kalMemAlloc(sizeof(struct iw_range), + VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + /* reset all fields */ + memset(prExtraBuf, 0, sizeof(struct iw_range)); + iwr->u.data.length = sizeof(struct iw_range); + + ret = wext_get_range(prDev, NULL, &iwr->u.data, + prExtraBuf); + /* Push up to the caller */ + if (copy_to_user(iwr->u.data.pointer, prExtraBuf, + iwr->u.data.length)) + ret = -EFAULT; + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, + sizeof(struct iw_range)); + prExtraBuf = NULL; + } else { + ret = -EINVAL; + } + break; + + case SIOCSIWPRIV: /* 0x8B0C, set country code */ + ret = wext_set_country(prDev, &iwr->u.data); + break; + + case SIOCGIWPRIV: /* 0x8B0D, get private args table */ + ret = wext_get_priv(prDev, &iwr->u.data); + break; + + /* 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; + } + 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)) { + struct iw_scan_req iw; + + if (copy_from_user(&iw, + (struct iw_scan_req *)(iwr->u.data.pointer), + sizeof(struct iw_scan_req))) { + ret = -EFAULT; + break; + } + + if (iw.essid_len > MAX_SSID_LEN) { + ret = -EFAULT; + break; + } + + prExtraBuf = kalMemAlloc(MAX_SSID_LEN, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, &iw.essid, + iw.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 > %d)\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) */ + u4ExtraSize = iwr->u.essid.length; + if (u4ExtraSize > 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, + u4ExtraSize)) { + 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 */ + u4ExtraSize = iwr->u.essid.length; + if (!iwr->u.essid.pointer) { + ret = -EINVAL; + break; + } + + if (u4ExtraSize != IW_ESSID_MAX_SIZE + && u4ExtraSize != IW_ESSID_MAX_SIZE + 1) { + 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 + 1, + 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 + 1); + 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 */ + u4ExtraSize = iwr->u.encoding.length; + if (iwr->u.encoding.pointer) { + if (u4ExtraSize > 16) { + ret = -E2BIG; + break; + } + + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, iwr->u.encoding.pointer, + u4ExtraSize)) + ret = -EFAULT; + + if (ret == 0) + ret = wext_set_encode(prDev, NULL, + &iwr->u.encoding, + prExtraBuf); + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); + prExtraBuf = NULL; + + } else if (u4ExtraSize != 0) + ret = -EINVAL; + 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) { + u4ExtraSize = iwr->u.data.length; + if (1 /* wlanQueryWapiMode(prGlueInfo->prAdapter) */) { + /* Fixed length structure */ +#if CFG_SUPPORT_WAPI + if (u4ExtraSize > 42 /* The max wapi ie buffer + */ + ) { + ret = -EINVAL; + break; + } +#endif + if (u4ExtraSize) { + prExtraBuf = kalMemAlloc(u4ExtraSize, + VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + if (copy_from_user(prExtraBuf, + iwr->u.data.pointer, u4ExtraSize)) + ret = -EFAULT; + else + wext_support_ioctl_SIOCSIWGENIE( + prDev, prExtraBuf, + u4ExtraSize); + 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; + if (u4ExtraSize > sizeof(struct iw_encode_ext)) { + ret = -EINVAL; + break; + } + + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, iwr->u.encoding.pointer, + u4ExtraSize)) + 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)); + */ + { + wext_support_ioctl_SIOCSIWPMKSA_Action( + prDev, prExtraBuf, + IW_PMKSA_ADD, &ret); + } + 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"); + */ + { + wext_support_ioctl_SIOCSIWPMKSA_Action( + prDev, prExtraBuf, + IW_PMKSA_FLUSH, &ret); + } + 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("%d CMD:0x%x ret:%d\n", jiffies_to_msecs(jiffies), + * i4Cmd, ret); + */ + + return ret; +} /* wext_support_ioctl */ + +static void wext_support_ioctl_SIOCSIWGENIE( + IN struct net_device *prDev, IN char *prExtraBuf, + IN uint32_t u4ExtraSize) +{ + struct GLUE_INFO *prGlueInfo = *((struct GLUE_INFO **) + netdev_priv(prDev)); + uint32_t rStatus; + uint32_t u4BufLen; + +#if CFG_SUPPORT_WAPI + rStatus = kalIoctl(prGlueInfo, wlanoidSetWapiAssocInfo, prExtraBuf, + u4ExtraSize, FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + /* do nothing */ + /* printk(KERN_INFO + * "[WSC] set WSC assoc info error:%x\n", + * rStatus); + */ + } +#endif + +} + +static void +wext_support_ioctl_SIOCSIWPMKSA_Action(IN struct net_device + *prDev, IN char *prExtraBuf, IN int ioMode, OUT int *ret) +{ + struct GLUE_INFO *prGlueInfo = *((struct GLUE_INFO **) + netdev_priv(prDev)); + uint32_t rStatus; + uint32_t u4BufLen; + struct PARAM_PMKID pmkid; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + pmkid.ucBssIdx = ucBssIndex; + + switch (ioMode) { + case IW_PMKSA_ADD: + kalMemCopy(pmkid.arBSSID, + ((struct iw_pmksa *)prExtraBuf)->bssid.sa_data, + PARAM_MAC_ADDR_LEN); + kalMemCopy(pmkid.arPMKID, + ((struct iw_pmksa *)prExtraBuf)->pmkid, IW_PMKID_LEN); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetPmkid, &pmkid, + sizeof(struct PARAM_PMKID), + FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "add pmkid error:%x\n", rStatus); + break; + case IW_PMKSA_FLUSH: + rStatus = kalIoctl(prGlueInfo, wlanoidFlushPmkid, NULL, 0, + FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "flush pmkid error:%x\n", rStatus); + break; + default: + break; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To send an event (RAW socket pacekt) to user process actively. + * + * \param[in] prGlueInfo Glue layer info. + * \param[in] u4cmd Which event command we want to indicate to user process. + * \param[in] pData Data buffer to be indicated. + * \param[in] dataLen Available data size in pData. + * + * \return (none) + * + * \note Event is indicated to upper layer if cmd is supported and data is + * valid. Using of kernel symbol wireless_send_event(), which is defined + * in after WE-14 (2.4.20). + */ +/*----------------------------------------------------------------------------*/ +void +wext_indicate_wext_event(IN struct GLUE_INFO *prGlueInfo, + IN unsigned int u4Cmd, IN unsigned char *pucData, + IN unsigned int u4dataLen, + IN uint8_t ucBssIndex) +{ + 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 + struct GL_WPA_INFO *prWpaInfo; + struct net_device *prDevHandler; + + memset(&wrqu, 0, sizeof(wrqu)); + + prWpaInfo = aisGetWpaInfo(prGlueInfo->prAdapter, + ucBssIndex); + + prDevHandler = + wlanGetNetDev(prGlueInfo, ucBssIndex); + + switch (u4Cmd) { + case SIOCGIWTXPOW: + memcpy(&wrqu.power, pucData, u4dataLen); + break; + case SIOCGIWSCAN: + complete_all(&prGlueInfo->rScanComp); + break; + + case SIOCGIWAP: + if (pucData) + kalMemCopy(&wrqu.ap_addr.sa_data, pucData, ETH_ALEN); + else + eth_zero_addr((u8 *)&wrqu.ap_addr.sa_data); + 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 */ + /* RSN IE found */ + } +#if 0 + else if (wextSrchDesiredWPSIE(pucData, u4dataLen, 0xDD, + &pucDesiredIE)) { + /* WPS IE found */ + /* WPS IE found */ + } +#endif + else if (wextSrchDesiredWPAIE(pucData, u4dataLen, 0xDD, + &pucDesiredIE)) { + /* WPA IE found */ + /* 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) { + struct PARAM_AUTH_REQUEST *pAuthReq = + (struct PARAM_AUTH_REQUEST *) pucData; + uint32_t nleft = 0, nsize = 0; + /* under WE-18, only IWEVCUSTOM can be used */ + u4Cmd = IWEVCUSTOM; + pucExtraInfo = aucExtraInfoBuf; + nleft = sizeof(aucExtraInfoBuf); + nsize = snprintf(pucExtraInfo, nleft, + "MLME-MICHAELMICFAILURE.indication "); + if (nsize < nleft) { + nleft -= nsize; + pucExtraInfo += nsize; + } + + nsize = snprintf(pucExtraInfo, + nleft, "%s", + (pAuthReq->u4Flags == + PARAM_AUTH_REQUEST_GROUP_ERROR) ? + "groupcast " : "unicast "); + + if (nsize < nleft) { + nleft -= nsize; + pucExtraInfo += nsize; + } + wrqu.data.length = sizeof(aucExtraInfoBuf) - nleft; + pucExtraInfo = aucExtraInfoBuf; + } +#endif /* WIRELESS_EXT < 15 */ + break; + + case IWEVPMKIDCAND: + if (prWpaInfo->u4WpaVersion == + IW_AUTH_WPA_VERSION_WPA2 && + prWpaInfo->u4KeyMgmt == IW_AUTH_KEY_MGMT_802_1X) { + + /* only used in WPA2 */ +#if WIRELESS_EXT >= 18 + struct PARAM_PMKID_CANDIDATE *prPmkidCand = + (struct PARAM_PMKID_CANDIDATE *) 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, (uint8_t *) &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(struct PTA_IPC)); + wrqu.data.length = sizeof(struct PTA_IPC); + break; + + default: + /* printk(KERN_INFO "Unsupported wext event:%x\n", cmd); */ + goto skip_indicate_event; + } + + /* Send event to user space */ + wireless_send_event(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) +{ + + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct GLUE_INFO *prGlueInfo = NULL; + struct iw_statistics *pStats = NULL; + struct PARAM_LINK_SPEED_EX rLinkSpeed; + uint32_t bufLen = 0; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) + goto stat_out; + + ucBssIndex = wlanGetBssIdx(prDev); + if (IS_BSS_INDEX_VALID(ucBssIndex)) + pStats = (struct iw_statistics *) + (&(prGlueInfo->rIwStats[ucBssIndex])); + + if (!prDev || !netif_carrier_ok(prDev)) { + /* network not connected */ + goto stat_out; + } + + rStatus = kalIoctlByBssIdx(prGlueInfo, + wlanoidQueryRssi, + &rLinkSpeed, sizeof(rLinkSpeed), + TRUE, TRUE, TRUE, + &bufLen, ucBssIndex); + +stat_out: + return pStats; +} /* wlan_get_wireless_stats */ + + +/* Standard call implementations */ +static int std_get_name(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_name(prDev, NULL, (char *)(&(prData->name)), + sizeof(prData->name), NULL); +} + +static int std_set_freq(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_freq(prDev, NULL, &(prData->freq), NULL); +} + +static int std_get_freq(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_freq(prDev, NULL, &(prData->freq), NULL); +} + +static int std_set_mode(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_mode(prDev, NULL, &prData->mode, NULL); +} + +static int std_get_mode(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_mode(prDev, NULL, &prData->mode, NULL); +} + +static int std_set_ap(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + int ret = 0; + + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + + if (prData->ap_addr.sa_data[0] == 0 && + prData->ap_addr.sa_data[1] == 0 && + prData->ap_addr.sa_data[2] == 0 && + prData->ap_addr.sa_data[3] == 0 && + prData->ap_addr.sa_data[4] == 0 + && prData->ap_addr.sa_data[5] == 0) { + /* WPA Supplicant will set 000000000000 in + * wpa_driver_wext_deinit(), do nothing here or + * disassoc again? + */ + ret = 0; + } else { + ret = wext_set_ap(prDev, NULL, &(prData->ap_addr), NULL); + } + return ret; +} + +static int std_get_ap(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_ap(prDev, NULL, &(prData->ap_addr), NULL); +} + +static int std_get_rate(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_rate(prDev, NULL, &prData->bitrate, NULL); +} + +static int std_set_rts(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_rts(prDev, NULL, &(prData->rts), NULL); +} + +static int std_get_rts(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_rts(prDev, NULL, &prData->rts, NULL); +} + +static int std_get_frag(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_frag(prDev, NULL, &prData->frag, NULL); +} + +static int std_set_txpow(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_txpow(prDev, NULL, &(prData->txpower), NULL); +} + +static int std_get_txpow(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_txpow(prDev, NULL, &prData->txpower, NULL); +} + +static int std_set_power(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_power(prDev, NULL, &prData->power, NULL); +} + +static int std_get_power(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_power(prDev, NULL, &prData->power, NULL); +} + +static int std_get_range(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_range(prDev, NULL, &(prData->data), + pcExtra); +} + +static int std_set_priv(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); +#ifdef CONFIG_COMPAT + if (rIwReqInfo->flags & IW_REQUEST_FLAG_COMPAT) { + int ret = 0; + struct compat_iw_point *iwp_compat = NULL; + struct iw_point iwp; + + iwp_compat = (struct compat_iw_point *) &prData->data; + iwp.pointer = compat_ptr(iwp_compat->pointer); + iwp.length = iwp_compat->length; + iwp.flags = iwp_compat->flags; + + ret = wext_set_country(prDev, &iwp); + + iwp_compat->pointer = ptr_to_compat(iwp.pointer); + iwp_compat->length = iwp.length; + iwp_compat->flags = iwp.flags; + + return ret; + } +#endif /* CONFIG_COMPAT */ + return wext_set_country(prDev, &(prData->data)); +} + +static int std_get_priv(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_priv(prDev, &(prData->data)); +} + +static int std_set_scan(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_scan(prDev, NULL, NULL, NULL); +} + +static int std_set_mlme(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_mlme(prDev, NULL, &(prData->data), pcExtra); +} + +static int std_get_scan(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_scan(prDev, NULL, &(prData->data), pcExtra); +} + +static int std_set_essid(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_essid(prDev, NULL, &(prData->essid), pcExtra); +} + +static int std_get_essid(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_essid(prDev, NULL, &(prData->essid), pcExtra); +} + +static int std_set_encode(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_encode(prDev, NULL, + &(prData->encoding), + pcExtra); +} + +static int std_get_encode(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_encode(prDev, NULL, &(prData->encoding), NULL); +} + +static int std_set_auth(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_auth(prDev, NULL, &(prData->param), NULL); +} + +#if WIRELESS_EXT > 17 +static int std_set_genie(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + uint32_t u4ExtraSize = prData->data.length; + struct GLUE_INFO *prGlueInfo = NULL; + + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + +#if CFG_SUPPORT_WAPI + /* The max wapi ie buffer */ + if (u4ExtraSize > 42) + return -EINVAL; +#endif + + if (prData->data.pointer) { + u4ExtraSize = prData->data.length; + prGlueInfo = *((struct GLUE_INFO **) + netdev_priv(prDev)); + wext_support_ioctl_SIOCSIWGENIE( + prDev, pcExtra, + u4ExtraSize); + } + + return 0; +} +#endif /* end of WIRELESS_EXT */ + +static int std_set_encode_ext(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_encode_ext(prDev, NULL, &(prData->encoding), + pcExtra); +} + +static int std_set_pmska(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + int ret = 0; + + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + + switch (((struct iw_pmksa *)pcExtra)->cmd) { + case IW_PMKSA_ADD: + wext_support_ioctl_SIOCSIWPMKSA_Action( + prDev, pcExtra, + IW_PMKSA_ADD, &ret); + break; + case IW_PMKSA_REMOVE: + break; + case IW_PMKSA_FLUSH: + wext_support_ioctl_SIOCSIWPMKSA_Action( + prDev, pcExtra, + IW_PMKSA_FLUSH, &ret); + break; + default: + DBGLOG(INIT, INFO, + "UNKNOWN iw_pmksa command:%d\n", + ((struct iw_pmksa *)pcExtra) + ->cmd); + ret = -EFAULT; + break; + } + return ret; +} + + +#endif /* WIRELESS_EXT */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_wext_priv.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_wext_priv.c new file mode 100644 index 0000000000000..bab32be63b202 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/gl_wext_priv.c @@ -0,0 +1,14361 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux + * /gl_wext_priv.c#8 + */ + +/*! \file gl_wext_priv.c + * \brief This file includes private ioctl support. + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" +#include "gl_os.h" +#include "gl_wext_priv.h" + +#if CFG_SUPPORT_QA_TOOL +#include "gl_ate_agent.h" +#include "gl_qa_agent.h" +#endif + +#if CFG_SUPPORT_WAPI +#include "gl_sec.h" +#endif +#if CFG_ENABLE_WIFI_DIRECT +#include "gl_p2p_os.h" +#endif + +/* + * #if CFG_SUPPORT_QA_TOOL + * extern UINT_16 g_u2DumpIndex; + * #endif + */ + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define NUM_SUPPORTED_OIDS (sizeof(arWlanOidReqTable) / \ + sizeof(struct WLAN_REQ_ENTRY)) +#define CMD_OID_BUF_LENGTH 4096 + +#if (CFG_SUPPORT_TWT == 1) +#define CMD_TWT_ACTION_TEN_PARAMS 10 +#define CMD_TWT_ACTION_THREE_PARAMS 3 +#define CMD_TWT_MAX_PARAMS CMD_TWT_ACTION_TEN_PARAMS +#endif + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +static int +priv_get_ndis(IN struct net_device *prNetDev, + IN struct NDIS_TRANSPORT_STRUCT *prNdisReq, + OUT uint32_t *pu4OutputLen); + +static int +priv_set_ndis(IN struct net_device *prNetDev, + IN struct NDIS_TRANSPORT_STRUCT *prNdisReq, + OUT uint32_t *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 u_int8_t reqSearchSupportedOidEntry(IN uint32_t rOid, + OUT struct WLAN_REQ_ENTRY **ppWlanReqEntry); + +#if 0 +static uint32_t +reqExtQueryConfiguration(IN struct GLUE_INFO *prGlueInfo, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +static uint32_t +reqExtSetConfiguration(IN struct GLUE_INFO *prGlueInfo, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif + +static uint32_t +reqExtSetAcpiDevicePowerState(IN struct GLUE_INFO + *prGlueInfo, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#if CFG_SUPPORT_DYNAMIC_PWR_LIMIT +/* dynamic tx power control */ +static int priv_driver_set_power_control(IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen); +#endif +#if CFG_SUPPORT_ANT_SWAP +/* set ant swap */ +static int priv_driver_set_ant_swap(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen); +#endif +#if CFG_SUPPORT_SCAN_EXT_FLAG +static int priv_driver_set_scan_ext_flag(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen); +#endif + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +static uint8_t aucOidBuf[CMD_OID_BUF_LENGTH] = { 0 }; + +/* OID processing table */ +/* Order is important here because the OIDs should be in order of + * increasing value for binary searching. + */ +static struct WLAN_REQ_ENTRY arWlanOidReqTable[] = { +#if 0 + { + (NDIS_OID)rOid, + (uint8_t *)pucOidName, + fgQryBufLenChecking, fgSetBufLenChecking, + fgIsHandleInGlueLayerOnly, u4InfoBufLen, + pfOidQueryHandler, + pfOidSetHandler + } +#endif + /* 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(uint8_t) * PARAM_MAX_LEN_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(struct PARAM_802_11_CONFIG), + * (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(enum 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 0 +#if PTA_ENABLED + { + OID_CUSTOM_BT_COEXIST_CTRL, + DISP_STRING("OID_CUSTOM_BT_COEXIST_CTRL"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, + sizeof(PARAM_CUSTOM_BT_COEXIST_T), + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetBtCoexistCtrl + }, +#endif + + { + OID_CUSTOM_POWER_MANAGEMENT_PROFILE, + DISP_STRING("OID_CUSTOM_POWER_MANAGEMENT_PROFILE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryPwrMgmtProfParam, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetPwrMgmtProfParam}, + { + OID_CUSTOM_PATTERN_CONFIG, + DISP_STRING("OID_CUSTOM_PATTERN_CONFIG"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, + sizeof(PARAM_CUSTOM_PATTERN_SEARCH_CONFIG_STRUCT_T), + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetPatternConfig + }, + { + OID_CUSTOM_BG_SSID_SEARCH_CONFIG, + DISP_STRING("OID_CUSTOM_BG_SSID_SEARCH_CONFIG"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetBgSsidParam + }, + { + OID_CUSTOM_VOIP_SETUP, + DISP_STRING("OID_CUSTOM_VOIP_SETUP"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryVoipConnectionStatus, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetVoipConnectionStatus + }, + { + OID_CUSTOM_ADD_TS, + DISP_STRING("OID_CUSTOM_ADD_TS"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidAddTS + }, + { + OID_CUSTOM_DEL_TS, + DISP_STRING("OID_CUSTOM_DEL_TS"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidDelTS + }, + +#if CFG_LP_PATTERN_SEARCH_SLT + { + OID_CUSTOM_SLT, + DISP_STRING("OID_CUSTOM_SLT"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQuerySltResult, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetSltMode + }, +#endif + + { + OID_CUSTOM_ROAMING_EN, + DISP_STRING("OID_CUSTOM_ROAMING_EN"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryRoamingFunction, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetRoamingFunction}, + { + OID_CUSTOM_WMM_PS_TEST, + DISP_STRING("OID_CUSTOM_WMM_PS_TEST"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetWiFiWmmPsTest + }, + { + OID_CUSTOM_COUNTRY_STRING, + DISP_STRING("OID_CUSTOM_COUNTRY_STRING"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryCurrentCountry, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetCurrentCountry + }, + +#if CFG_SUPPORT_802_11D + { + OID_CUSTOM_MULTI_DOMAIN_CAPABILITY, + DISP_STRING("OID_CUSTOM_MULTI_DOMAIN_CAPABILITY"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryMultiDomainCap, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetMultiDomainCap + }, +#endif + + { + OID_CUSTOM_GPIO2_MODE, + DISP_STRING("OID_CUSTOM_GPIO2_MODE"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, + sizeof(ENUM_PARAM_GPIO2_MODE_T), + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetGPIO2Mode}, + { + OID_CUSTOM_CONTINUOUS_POLL, + DISP_STRING("OID_CUSTOM_CONTINUOUS_POLL"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, + sizeof(PARAM_CONTINUOUS_POLL_T), + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryContinuousPollInterval, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetContinuousPollProfile + }, + { + OID_CUSTOM_DISABLE_BEACON_DETECTION, + DISP_STRING("OID_CUSTOM_DISABLE_BEACON_DETECTION"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, 4, + (PFN_OID_HANDLER_FUNC_REQ) + wlanoidQueryDisableBeaconDetectionFunc, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetDisableBeaconDetectionFunc + }, + + /* WPS */ + { + OID_CUSTOM_DISABLE_PRIVACY_CHECK, + DISP_STRING("OID_CUSTOM_DISABLE_PRIVACY_CHECK"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, 4, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetDisablePriavcyCheck + }, +#endif + + { + OID_CUSTOM_MCR_RW, + DISP_STRING("OID_CUSTOM_MCR_RW"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, + sizeof(struct PARAM_CUSTOM_MCR_RW_STRUCT), + (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(struct PARAM_CUSTOM_EEPROM_RW_STRUCT), + (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(struct PARAM_CUSTOM_SW_CTRL_STRUCT), + (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(struct PARAM_CUSTOM_MEM_DUMP_STRUCT), + (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 + } + , + +#if 0 + { + OID_CUSTOM_TEST_RX_STATUS, + DISP_STRING("OID_CUSTOM_TEST_RX_STATUS"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, + sizeof(struct PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT), + (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(struct PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT), + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryRfTestTxStatus, + NULL + }, +#endif + { + 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"), + /* PeiHsuan Temp Remove this check for workaround Gen2/Gen3 EM + * Mode Modification + */ + /* TRUE, TRUE, ENUM_OID_DRIVER_CORE, + * sizeof(PARAM_MTK_WIFI_TEST_STRUCT_T), + */ + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestQueryAutoTest, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestSetAutoTest + } + , + { + OID_CUSTOM_TEST_ICAP_MODE, + DISP_STRING("OID_CUSTOM_TEST_ICAP_MODE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + NULL, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestSetTestIcapMode + } + , + + /* 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(struct PTA_IPC), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryBT, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetBT + } + , +#endif +#if 0 + { + 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 + }, +#endif + + { + OID_CUSTOM_MTK_NVRAM_RW, + DISP_STRING("OID_CUSTOM_MTK_NVRAM_RW"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, + sizeof(struct PARAM_CUSTOM_EEPROM_RW_STRUCT), + (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 ENUM_CFG_SRC_TYPE), + (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 ENUM_EEPROM_TYPE), + (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(struct PARAM_WPI_KEY), + NULL, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetWapiKey + } + , +#endif + +#if CFG_SUPPORT_LOWLATENCY_MODE + /* Note: we should put following code in order */ + { + OID_CUSTOM_LOWLATENCY_MODE, /* 0xFFA0CC00 */ + DISP_STRING("OID_CUSTOM_LOWLATENCY_MODE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(uint32_t), + NULL, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetLowLatencyMode + } + , +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + + { + OID_IPC_WIFI_LOG_UI, + DISP_STRING("OID_IPC_WIFI_LOG_UI"), + FALSE, + FALSE, + ENUM_OID_DRIVER_CORE, + sizeof(struct PARAM_WIFI_LOG_LEVEL_UI), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryWifiLogLevelSupport, + NULL + } + , + + { + OID_IPC_WIFI_LOG_LEVEL, + DISP_STRING("OID_IPC_WIFI_LOG_LEVEL"), + FALSE, + FALSE, + ENUM_OID_DRIVER_CORE, + sizeof(struct PARAM_WIFI_LOG_LEVEL), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryWifiLogLevel, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetWifiLogLevel + } + , +#if CFG_SUPPORT_ANT_SWAP + { + OID_CUSTOM_QUERY_ANT_SWAP_CAPABILITY, /* 0xFFA0CD00 */ + DISP_STRING("OID_CUSTOM_QUERY_ANT_SWAP_CAPABILITY"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(uint32_t), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryAntennaSwap, + NULL + } + , +#endif +}; + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +static int compat_priv(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN char *pcExtra, + int (*priv_func)(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN char *pcExtra)) +{ + struct iw_point *prIwp; + int ret = 0; +#ifdef CONFIG_COMPAT + struct compat_iw_point *iwp_compat = NULL; + struct iw_point iwp = {0}; +#endif + + if (!prIwReqData) + return -EINVAL; + +#ifdef CONFIG_COMPAT + if (prIwReqInfo->flags & IW_REQUEST_FLAG_COMPAT) { + iwp_compat = (struct compat_iw_point *) &prIwReqData->data; + iwp.pointer = compat_ptr(iwp_compat->pointer); + iwp.length = iwp_compat->length; + iwp.flags = iwp_compat->flags; + prIwp = &iwp; + } else +#endif + prIwp = &prIwReqData->data; + + + ret = priv_func(prNetDev, prIwReqInfo, + (union iwreq_data *)prIwp, pcExtra); + +#ifdef CONFIG_COMPAT + if (prIwReqInfo->flags & IW_REQUEST_FLAG_COMPAT) { + iwp_compat->pointer = ptr_to_compat(iwp.pointer); + iwp_compat->length = iwp.length; + iwp_compat->flags = iwp.flags; + } +#endif + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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; + + /* prNetDev 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)); + +#if (CFG_SUPPORT_QA_TOOL) + case IOCTL_QA_TOOL_DAEMON: + case SIOCDEVPRIVATE+2: + return priv_qa_agent(prNetDev, &rIwReqInfo, &(prIwReq->u), + (char *) &(prIwReq->u)); +#endif + + /* This case need to fall through */ + case IOC_AP_GET_STA_LIST: + /* This case need to fall through */ + case IOC_AP_SET_MAC_FLTR: + /* This case need to fall through */ + case IOC_AP_SET_CFG: + /* This case need to fall through */ + case IOC_AP_STA_DISASSOC: + /* This case need to fall through */ + case IOC_AP_SET_NSS: + return priv_set_ap(prNetDev, &rIwReqInfo, &(prIwReq->u), + (char *) &(prIwReq->u)); + + case IOCTL_GET_STR: + + default: + return -EOPNOTSUPP; + + } /* end of switch */ + +} /* priv_support_ioctl */ + +#if CFG_SUPPORT_BATCH_SCAN + +struct EVENT_BATCH_RESULT + g_rEventBatchResult[CFG_BATCH_MAX_MSCAN]; + +uint32_t batchChannelNum2Freq(uint32_t u4ChannelNum) +{ + uint32_t u4ChannelInMHz; + + if (u4ChannelNum >= 1 && u4ChannelNum <= 13) + u4ChannelInMHz = 2412 + (u4ChannelNum - 1) * 5; + else if (u4ChannelNum == 14) + u4ChannelInMHz = 2484; + else if (u4ChannelNum == 133) + u4ChannelInMHz = 3665; /* 802.11y */ + else if (u4ChannelNum == 137) + u4ChannelInMHz = 3685; /* 802.11y */ + else if (u4ChannelNum >= 34 && u4ChannelNum <= 165) + u4ChannelInMHz = 5000 + u4ChannelNum * 5; + else if (u4ChannelNum >= 183 && u4ChannelNum <= 196) + u4ChannelInMHz = 4000 + u4ChannelNum * 5; + else + u4ChannelInMHz = 0; + + return u4ChannelInMHz; +} + +#define TMP_TEXT_LEN_S 40 +#define TMP_TEXT_LEN_L 60 +static uint8_t text1[TMP_TEXT_LEN_S], text2[TMP_TEXT_LEN_L], + text3[TMP_TEXT_LEN_L]; /* A safe len */ + +uint32_t +batchConvertResult(IN struct EVENT_BATCH_RESULT + *prEventBatchResult, + OUT void *pvBuffer, IN uint32_t u4MaxBufferLen, + OUT uint32_t *pu4RetLen) +{ + int8_t *p = pvBuffer; + int8_t ssid[ELEM_MAX_LEN_SSID + 1]; + int32_t nsize, nsize1, nsize2, nsize3, scancount; + int32_t i, j, nleft; + uint32_t freq; + + struct EVENT_BATCH_RESULT_ENTRY *prEntry; + struct EVENT_BATCH_RESULT *pBr; + + nsize = 0; + nleft = u4MaxBufferLen - 5; /* -5 for "----\n" */ + + pBr = prEventBatchResult; + scancount = 0; + for (j = 0; j < CFG_BATCH_MAX_MSCAN; j++) { + scancount += pBr->ucScanCount; + pBr++; + } + + nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, + "scancount=%d\nnextcount=%d\n", scancount, + scancount); + if (nsize1 < nleft) { + kalStrnCpy(p, text1, nsize1); + p += nsize1; + nleft -= nsize1; + } else + goto short_buf; + + pBr = prEventBatchResult; + for (j = 0; j < CFG_BATCH_MAX_MSCAN; j++) { + DBGLOG(SCN, TRACE, + "convert mscan = %d, apcount=%d, nleft=%d\n", j, + pBr->ucScanCount, nleft); + + if (pBr->ucScanCount == 0) { + pBr++; + continue; + } + + nleft -= 5; /* -5 for "####\n" */ + + /* We only support one round scan result now. */ + nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "apcount=%d\n", + pBr->ucScanCount); + if (nsize1 < nleft) { + kalStrnCpy(p, text1, nsize1); + p += nsize1; + nleft -= nsize1; + } else + goto short_buf; + + for (i = 0; i < pBr->ucScanCount; i++) { + prEntry = &pBr->arBatchResult[i]; + + nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, + "bssid=" MACSTR "\n", + MAC2STR(prEntry->aucBssid)); + kalMemCopy(ssid, + prEntry->aucSSID, + (prEntry->ucSSIDLen < ELEM_MAX_LEN_SSID ? + prEntry->ucSSIDLen : ELEM_MAX_LEN_SSID)); + ssid[(prEntry->ucSSIDLen < + (ELEM_MAX_LEN_SSID - 1) ? prEntry->ucSSIDLen : + (ELEM_MAX_LEN_SSID - 1))] = '\0'; + nsize2 = kalSnprintf(text2, TMP_TEXT_LEN_L, "ssid=%s\n", + ssid); + + freq = batchChannelNum2Freq(prEntry->ucFreq); + nsize3 = + kalSnprintf(text3, TMP_TEXT_LEN_L, + "freq=%u\nlevel=%d\ndist=%u\ndistSd=%u\n====\n", + freq, prEntry->cRssi, prEntry->u4Dist, + prEntry->u4Distsd); + + nsize = nsize1 + nsize2 + nsize3; + if (nsize < nleft) { + + kalStrnCpy(p, text1, TMP_TEXT_LEN_S); + p += nsize1; + + kalStrnCpy(p, text2, TMP_TEXT_LEN_L); + p += nsize2; + + kalStrnCpy(p, text3, TMP_TEXT_LEN_L); + p += nsize3; + + nleft -= nsize; + } else { + DBGLOG(SCN, TRACE, + "Warning: Early break! (%d)\n", i); + break; /* discard following entries, + * TODO: apcount? + */ + } + } + + nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "%s", "####\n"); + if (nsize1 < nleft) { + kalStrnCpy(p, text1, nsize1); + p += nsize1; + nleft -= nsize1; + } + + pBr++; + } + + nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "%s", "----\n"); + if (nsize1 < nleft) { + kalStrnCpy(p, text1, nsize1); + p += nsize1; + nleft -= nsize1; + } + + *pu4RetLen = u4MaxBufferLen - nleft; + DBGLOG(SCN, TRACE, "total len = %d (max len = %d)\n", + *pu4RetLen, u4MaxBufferLen); + + return WLAN_STATUS_SUCCESS; + +short_buf: + DBGLOG(SCN, TRACE, + "Short buffer issue! %d > %d, %s\n", + u4MaxBufferLen + (nsize - nleft), u4MaxBufferLen, + (char *)pvBuffer); + return WLAN_STATUS_INVALID_LENGTH; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \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) +{ + uint32_t u4SubCmd; + uint32_t *pu4IntBuf; + struct NDIS_TRANSPORT_STRUCT *prNdisReq; + struct GLUE_INFO *prGlueInfo; + uint32_t u4BufLen = 0; + int status = 0; + struct PTA_IPC *prPtaIpc; + + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + + if (GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + u4SubCmd = (uint32_t) prIwReqData->mode; + pu4IntBuf = (uint32_t *) pcExtra; + + switch (u4SubCmd) { + case PRIV_CMD_TEST_MODE: + /* printk("TestMode=%ld\n", pu4IntBuf[1]); */ + prNdisReq = (struct 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 if (pu4IntBuf[1] == PRIV_CMD_TEST_MAGIC_KEY_ICAP) { + prNdisReq->ndisOidCmd = OID_CUSTOM_TEST_ICAP_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 = (struct 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 = (struct 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; + } + + if (pu4IntBuf[1] == PRIV_CMD_TEST_MAGIC_KEY + && pu4IntBuf[2] == PRIV_CMD_TEST_MAGIC_KEY) { + 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 = (struct 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: + /* pu4IntBuf[0] is used as input SubCmd */ + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetBeaconInterval, (void *)&pu4IntBuf[1], + sizeof(uint32_t), &u4BufLen); + break; +#endif + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + case PRIV_CMD_CSUM_OFFLOAD: { + uint32_t u4CSUMFlags; + + if (pu4IntBuf[1] == 1) + u4CSUMFlags = CSUM_OFFLOAD_EN_ALL; + else if (pu4IntBuf[1] == 0) + u4CSUMFlags = 0; + else + return -EINVAL; + + if (kalIoctl(prGlueInfo, wlanoidSetCSUMOffload, + (void *)&u4CSUMFlags, sizeof(uint32_t), FALSE, FALSE, TRUE, + &u4BufLen) == WLAN_STATUS_SUCCESS) { + if (pu4IntBuf[1] == 1) + prNetDev->features |= NETIF_F_IP_CSUM | + NETIF_F_IPV6_CSUM | + NETIF_F_RXCSUM; + else if (pu4IntBuf[1] == 0) + prNetDev->features &= ~(NETIF_F_IP_CSUM | + NETIF_F_IPV6_CSUM | + NETIF_F_RXCSUM); + } + } + break; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + case PRIV_CMD_POWER_MODE: { + struct PARAM_POWER_MODE_ rPowerMode; + + rPowerMode.ePowerMode = (enum PARAM_POWER_MODE) + pu4IntBuf[1]; + rPowerMode.ucBssIdx = wlanGetBssIdx(prNetDev); + + /* pu4IntBuf[0] is used as input SubCmd */ + kalIoctl(prGlueInfo, wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, sizeof(struct PARAM_POWER_MODE_), + FALSE, FALSE, TRUE, &u4BufLen); + } + break; + + case PRIV_CMD_WMM_PS: { + struct PARAM_CUSTOM_WMM_PS_TEST_STRUCT rWmmPsTest; + + rWmmPsTest.bmfgApsdEnAc = (uint8_t) pu4IntBuf[1]; + rWmmPsTest.ucIsEnterPsAtOnce = (uint8_t) pu4IntBuf[2]; + rWmmPsTest.ucIsDisableUcTrigger = (uint8_t) pu4IntBuf[3]; + rWmmPsTest.reserved = 0; + rWmmPsTest.ucBssIdx = wlanGetBssIdx(prNetDev); + kalIoctl(prGlueInfo, wlanoidSetWiFiWmmPsTest, + (void *)&rWmmPsTest, + sizeof(struct PARAM_CUSTOM_WMM_PS_TEST_STRUCT), + FALSE, FALSE, TRUE, &u4BufLen); + } + break; + +#if 0 + case PRIV_CMD_ADHOC_MODE: + /* pu4IntBuf[0] is used as input SubCmd */ + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetAdHocMode, (void *)&pu4IntBuf[1], + sizeof(uint32_t), &u4BufLen); + break; +#endif + + case PRIV_CUSTOM_BWCS_CMD: + + DBGLOG(REQ, INFO, + "pu4IntBuf[1] = %x, size of struct PTA_IPC = %d.\n", + pu4IntBuf[1], (uint32_t) sizeof(struct PTA_IPC)); + + prPtaIpc = (struct PTA_IPC *) aucOidBuf; + prPtaIpc->u.aucBTPParams[0] = (uint8_t) (pu4IntBuf[1] >> + 24); + prPtaIpc->u.aucBTPParams[1] = (uint8_t) (pu4IntBuf[1] >> + 16); + prPtaIpc->u.aucBTPParams[2] = (uint8_t) (pu4IntBuf[1] >> 8); + prPtaIpc->u.aucBTPParams[3] = (uint8_t) (pu4IntBuf[1]); + + DBGLOG(REQ, INFO, + "BCM BWCS CMD : PRIV_CUSTOM_BWCS_CMD : aucBTPParams[0] = %02x, aucBTPParams[1] = %02x.\n", + prPtaIpc->u.aucBTPParams[0], + prPtaIpc->u.aucBTPParams[1]); + DBGLOG(REQ, INFO, + "BCM BWCS CMD : PRIV_CUSTOM_BWCS_CMD : aucBTPParams[2] = %02x, aucBTPParams[3] = %02x.\n", + prPtaIpc->u.aucBTPParams[2], + prPtaIpc->u.aucBTPParams[3]); + +#if 0 + status = wlanSetInformation(prGlueInfo->prAdapter, wlanoidSetBT, + (void *)&aucOidBuf[0], u4CmdLen, &u4BufLen); +#endif + + status = wlanoidSetBT(prGlueInfo->prAdapter, + (void *)&aucOidBuf[0], sizeof(struct PTA_IPC), + &u4BufLen); + + if (status != WLAN_STATUS_SUCCESS) + status = -EFAULT; + + break; + + case PRIV_CMD_BAND_CONFIG: { + DBGLOG(INIT, INFO, "CMD set_band = %u\n", + (uint32_t) pu4IntBuf[1]); + } + break; + +#if CFG_ENABLE_WIFI_DIRECT + case PRIV_CMD_P2P_MODE: { + struct PARAM_CUSTOM_P2P_SET_STRUCT rSetP2P; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + rSetP2P.u4Enable = pu4IntBuf[1]; + rSetP2P.u4Mode = pu4IntBuf[2]; +#if 1 + if (!rSetP2P.u4Enable) + p2pNetUnregister(prGlueInfo, TRUE); + + /* pu4IntBuf[0] is used as input SubCmd */ + rWlanStatus = kalIoctl(prGlueInfo, wlanoidSetP2pMode, + (void *)&rSetP2P, + sizeof(struct PARAM_CUSTOM_P2P_SET_STRUCT), + FALSE, FALSE, TRUE, &u4BufLen); + + if ((rSetP2P.u4Enable) + && (rWlanStatus == WLAN_STATUS_SUCCESS)) + p2pNetRegister(prGlueInfo, TRUE); +#endif + + } + break; +#endif + +#if (CFG_MET_PACKET_TRACE_SUPPORT == 1) + case PRIV_CMD_MET_PROFILING: { + /* PARAM_CUSTOM_WFD_DEBUG_STRUCT_T rWfdDebugModeInfo; */ + /* rWfdDebugModeInfo.ucWFDDebugMode=(UINT_8)pu4IntBuf[1]; */ + /* rWfdDebugModeInfo.u2SNPeriod=(UINT_16)pu4IntBuf[2]; */ + /* DBGLOG(REQ, INFO, ("WFD Debug Mode:%d Period:%d\n", + * rWfdDebugModeInfo.ucWFDDebugMode, + * rWfdDebugModeInfo.u2SNPeriod)); + */ + prGlueInfo->fgMetProfilingEn = (uint8_t) pu4IntBuf[1]; + prGlueInfo->u2MetUdpPort = (uint16_t) pu4IntBuf[2]; + /* DBGLOG(INIT, INFO, ("MET_PROF: Enable=%d UDP_PORT=%d\n", + * prGlueInfo->fgMetProfilingEn, prGlueInfo->u2MetUdpPort); + */ + + } + break; + +#endif + case PRIV_CMD_SET_SER: + kalIoctl(prGlueInfo, wlanoidSetSer, (void *)&pu4IntBuf[1], + sizeof(uint32_t), FALSE, FALSE, TRUE, &u4BufLen); + break; + + default: + return -EOPNOTSUPP; + } + + return status; +} /* __priv_set_int */ + +int +priv_set_int(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + DBGLOG(REQ, LOUD, "cmd=%x, flags=%x\n", + prIwReqInfo->cmd, prIwReqInfo->flags); + DBGLOG(REQ, LOUD, "mode=%x, flags=%x\n", + prIwReqData->mode, prIwReqData->data.flags); + + return compat_priv(prNetDev, prIwReqInfo, + prIwReqData, pcExtra, __priv_set_int); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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) +{ + uint32_t u4SubCmd; + uint32_t *pu4IntBuf; + struct GLUE_INFO *prGlueInfo; + uint32_t u4BufLen = 0; + int status = 0; + struct NDIS_TRANSPORT_STRUCT *prNdisReq; + int32_t ch[50] = {0}; + + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + if (GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + u4SubCmd = (uint32_t) prIwReqData->mode; + pu4IntBuf = (uint32_t *) pcExtra; + + switch (u4SubCmd) { + case PRIV_CMD_TEST_CMD: + /* printk("CMD=0x%08lx, data=0x%08lx\n", pu4IntBuf[1], + * pu4IntBuf[2]); + */ + prNdisReq = (struct 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", + * *(uint32_t *)&prNdisReq->ndisOidContent[4]); + */ + prIwReqData->mode = *(uint32_t *) + &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 = (struct 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", + * *(uint32_t *)&prNdisReq->ndisOidContent[4]); + */ + prIwReqData->mode = *(uint32_t *) + &prNdisReq->ndisOidContent[4]; + } + return status; +#endif + + case PRIV_CMD_DUMP_MEM: + prNdisReq = (struct 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 = sizeof(struct + PARAM_CUSTOM_MEM_DUMP_STRUCT); + prNdisReq->outNdisOidLength = sizeof(struct + PARAM_CUSTOM_MEM_DUMP_STRUCT); + + status = priv_get_ndis(prNetDev, prNdisReq, &u4BufLen); + if (status == 0) + prIwReqData->mode = *(uint32_t *) + &prNdisReq->ndisOidContent[0]; + return status; + + case PRIV_CMD_SW_CTRL: + /* printk(" addr=0x%08lx\n", pu4IntBuf[1]); */ + + prNdisReq = (struct 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", + * *(uint32_t *)&prNdisReq->ndisOidContent[4]); + */ + prIwReqData->mode = *(uint32_t *) + &prNdisReq->ndisOidContent[4]; + } + return status; + +#if 0 + case PRIV_CMD_BEACON_PERIOD: + status = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryBeaconInterval, (void *) pu4IntBuf, + sizeof(uint32_t), &u4BufLen); + return status; + + case PRIV_CMD_POWER_MODE: + status = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQuery802dot11PowerSaveProfile, + (void *)pu4IntBuf, sizeof(uint32_t), &u4BufLen); + return status; + + case PRIV_CMD_ADHOC_MODE: + status = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryAdHocMode, (void *) pu4IntBuf, + sizeof(uint32_t), &u4BufLen); + return status; +#endif + + case PRIV_CMD_BAND_CONFIG: + DBGLOG(INIT, INFO, "CMD get_band=\n"); + prIwReqData->mode = 0; + return status; + + default: + break; + } + + u4SubCmd = (uint32_t) prIwReqData->data.flags; + + switch (u4SubCmd) { + case PRIV_CMD_GET_CH_LIST: { + uint16_t i, j = 0; + uint8_t NumOfChannel = 50; + uint8_t ucMaxChannelNum = 50; + struct RF_CHANNEL_INFO *aucChannelList; + + DBGLOG(RLM, INFO, "Domain: Query Channel List.\n"); + aucChannelList = (struct RF_CHANNEL_INFO *) + kalMemAlloc(sizeof(struct RF_CHANNEL_INFO) + *ucMaxChannelNum, VIR_MEM_TYPE); + if (!aucChannelList) { + DBGLOG(REQ, ERROR, + "Can not alloc memory for rf channel info\n"); + return -ENOMEM; + } + kalMemZero(aucChannelList, + sizeof(struct RF_CHANNEL_INFO)*ucMaxChannelNum); + + kalGetChannelList(prGlueInfo, BAND_NULL, ucMaxChannelNum, + &NumOfChannel, aucChannelList); + if (NumOfChannel > ucMaxChannelNum) + NumOfChannel = ucMaxChannelNum; + + 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] = (int32_t) aucChannelList[i] + .ucChannelNum; + j++; + } + } + } else { + for (j = 0; j < NumOfChannel; j++) + ch[j] = (int32_t)aucChannelList[j].ucChannelNum; + } + kalMemFree(aucChannelList, VIR_MEM_TYPE, + sizeof(struct RF_CHANNEL_INFO)*ucMaxChannelNum); + + prIwReqData->data.length = j; + if (copy_to_user(prIwReqData->data.pointer, ch, + NumOfChannel * sizeof(int32_t))) + return -EFAULT; + else + return status; + } + case PRIV_CMD_GET_FW_VERSION: { + uint16_t u2Len = 0; + struct ADAPTER *prAdapter; + + prAdapter = prGlueInfo->prAdapter; + if (prAdapter) { + u2Len = kalStrLen( + prAdapter->rVerInfo.aucReleaseManifest); + DBGLOG(REQ, INFO, + "Get FW manifest version: %d\n", u2Len); + prIwReqData->data.length = u2Len; + if (copy_to_user(prIwReqData->data.pointer, + prAdapter->rVerInfo.aucReleaseManifest, + u2Len * sizeof(uint8_t))) + return -EFAULT; + else + return status; + } + DBGLOG(REQ, WARN, "Fail to get FW manifest version\n"); + return status; + } + default: + return -EOPNOTSUPP; + } + + return status; +} /* __priv_get_int */ + +int +priv_get_int(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + DBGLOG(REQ, LOUD, "cmd=%x, flags=%x\n", + prIwReqInfo->cmd, prIwReqInfo->flags); + DBGLOG(REQ, LOUD, "mode=%x, flags=%x\n", + prIwReqData->mode, prIwReqData->data.flags); + + return compat_priv(prNetDev, prIwReqInfo, + prIwReqData, pcExtra, __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) +{ + DBGLOG(REQ, LOUD, "not support now"); + return -EINVAL; +} /* __priv_set_ints */ + +int +priv_set_ints(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + DBGLOG(REQ, LOUD, "cmd=%x, flags=%x\n", + prIwReqInfo->cmd, prIwReqInfo->flags); + DBGLOG(REQ, LOUD, "mode=%x, flags=%x\n", + prIwReqData->mode, prIwReqData->data.flags); + + return compat_priv(prNetDev, prIwReqInfo, + prIwReqData, pcExtra, __priv_set_ints); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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) +{ + uint32_t u4SubCmd; + struct GLUE_INFO *prGlueInfo; + int status = 0; + int32_t ch[50]; + + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + if (GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + u4SubCmd = (uint32_t) prIwReqData->data.flags; + + switch (u4SubCmd) { + case PRIV_CMD_GET_CH_LIST: { + uint16_t i; + uint8_t NumOfChannel = 50; + uint8_t ucMaxChannelNum = 50; + struct RF_CHANNEL_INFO *aucChannelList; + + aucChannelList = (struct RF_CHANNEL_INFO *) + kalMemAlloc(sizeof(struct RF_CHANNEL_INFO) + *ucMaxChannelNum, VIR_MEM_TYPE); + if (!aucChannelList) { + DBGLOG(REQ, ERROR, + "Can not alloc memory for rf channel info\n"); + return -ENOMEM; + } + kalMemZero(aucChannelList, + sizeof(struct RF_CHANNEL_INFO)*ucMaxChannelNum); + + kalGetChannelList(prGlueInfo, BAND_NULL, ucMaxChannelNum, + &NumOfChannel, aucChannelList); + if (NumOfChannel > ucMaxChannelNum) + NumOfChannel = ucMaxChannelNum; + + for (i = 0; i < NumOfChannel; i++) + ch[i] = (int32_t) aucChannelList[i].ucChannelNum; + + kalMemFree(aucChannelList, VIR_MEM_TYPE, + sizeof(struct RF_CHANNEL_INFO)*ucMaxChannelNum); + + prIwReqData->data.length = NumOfChannel; + if (copy_to_user(prIwReqData->data.pointer, ch, + NumOfChannel * sizeof(int32_t))) + return -EFAULT; + else + return status; + } + default: + break; + } + + return status; +} /* __priv_get_ints */ + +int +priv_get_ints(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + DBGLOG(REQ, LOUD, "cmd=%x, flags=%x\n", + prIwReqInfo->cmd, prIwReqInfo->flags); + DBGLOG(REQ, LOUD, "mode=%x, flags=%x\n", + prIwReqData->mode, prIwReqData->data.flags); + + return compat_priv(prNetDev, prIwReqInfo, + prIwReqData, pcExtra, __priv_get_ints); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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) +{ + uint32_t u4SubCmd = 0; + int status = 0; + /* WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; */ + uint32_t u4CmdLen = 0; + struct NDIS_TRANSPORT_STRUCT *prNdisReq; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4BufLen = 0; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + ASSERT(prNetDev); + /* ASSERT(prIwReqInfo); */ + ASSERT(prIwReqData); + /* ASSERT(pcExtra); */ + + kalMemZero(&aucOidBuf[0], sizeof(aucOidBuf)); + + if (GLUE_CHK_PR2(prNetDev, prIwReqData) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + u4SubCmd = (uint32_t) prIwReqData->data.flags; + +#if 0 + DBGLOG(INIT, INFO, + "priv_set_struct(): prIwReqInfo->cmd(0x%X), u4SubCmd(%ld)\n", + prIwReqInfo->cmd, u4SubCmd); +#endif + + switch (u4SubCmd) { +#if 0 /* PTA_ENABLED */ + case PRIV_CMD_BT_COEXIST: + u4CmdLen = prIwReqData->data.length * sizeof(uint32_t); + 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, (void *)&aucOidBuf[0], + u4CmdLen, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + status = -EFAULT; + break; +#endif + + case PRIV_CUSTOM_BWCS_CMD: + u4CmdLen = prIwReqData->data.length * sizeof(uint32_t); + ASSERT(sizeof(struct PTA_IPC) >= u4CmdLen); + if (sizeof(struct PTA_IPC) < u4CmdLen) + return -EFAULT; +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS && CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(REQ, INFO, + "ucCmdLen = %d, size of struct PTA_IPC = %d, prIwReqData->data = 0x%x.\n", + u4CmdLen, sizeof(struct PTA_IPC), 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, + (void *)&aucOidBuf[0], u4CmdLen, &u4BufLen); +#endif + +#if 1 + status = wlanoidSetBT(prGlueInfo->prAdapter, + (void *)&aucOidBuf[0], u4CmdLen, &u4BufLen); +#endif + + if (status != WLAN_STATUS_SUCCESS) + status = -EFAULT; + + break; + +#if CFG_SUPPORT_WPS2 + case PRIV_CMD_WSC_PROBE_REQ: { + struct CONNECTION_SETTINGS *prConnSettings = + aisGetConnSettings(prGlueInfo->prAdapter, + ucBssIndex); + + /* retrieve IE for Probe Request */ + u4CmdLen = prIwReqData->data.length; + if (u4CmdLen > GLUE_INFO_WSCIE_LENGTH) { + DBGLOG(REQ, ERROR, "Input data length is invalid %u\n", + u4CmdLen); + return -EINVAL; + } + + if (prIwReqData->data.length > 0) { + if (copy_from_user(prConnSettings->aucWSCIE, + prIwReqData->data.pointer, + u4CmdLen)) { + status = -EFAULT; + break; + } + prConnSettings->u2WSCIELen = u4CmdLen; + } else { + prConnSettings->u2WSCIELen = 0; + } + } + break; +#endif + case PRIV_CMD_OID: + u4CmdLen = prIwReqData->data.length; + if (u4CmdLen > CMD_OID_BUF_LENGTH) { + DBGLOG(REQ, ERROR, "Input data length is invalid %u\n", + u4CmdLen); + return -EINVAL; + } + if (copy_from_user(&aucOidBuf[0], prIwReqData->data.pointer, + u4CmdLen)) { + status = -EFAULT; + break; + } + if (!kalMemCmp(&aucOidBuf[0], pcExtra, u4CmdLen)) { + /* ToDo:: DBGLOG */ + 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, + (struct NDIS_TRANSPORT_STRUCT *) &aucOidBuf[0], + &u4BufLen); + /* Copy result to user space */ + ((struct NDIS_TRANSPORT_STRUCT *) + &aucOidBuf[0])->outNdisOidLength = u4BufLen; + + if (copy_to_user(prIwReqData->data.pointer, &aucOidBuf[0], + OFFSET_OF(struct NDIS_TRANSPORT_STRUCT, ndisOidContent))) { + DBGLOG(REQ, INFO, "copy_to_user oidBuf fail\n"); + status = -EFAULT; + } + + break; + + case PRIV_CMD_SW_CTRL: + u4CmdLen = prIwReqData->data.length; + prNdisReq = (struct NDIS_TRANSPORT_STRUCT *) &aucOidBuf[0]; + + if (u4CmdLen > sizeof(prNdisReq->ndisOidContent)) { + DBGLOG(REQ, ERROR, "Input data length is invalid %u\n", + u4CmdLen); + return -EINVAL; + } + + if (copy_from_user(&prNdisReq->ndisOidContent[0], + prIwReqData->data.pointer, u4CmdLen)) { + 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; + + case PRIV_CMD_GET_WIFI_TYPE: + { + int32_t i4ResultLen; + + u4CmdLen = prIwReqData->data.length; + if (u4CmdLen >= CMD_OID_BUF_LENGTH) { + DBGLOG(REQ, ERROR, + "u4CmdLen:%u >= CMD_OID_BUF_LENGTH:%d\n", + u4CmdLen, CMD_OID_BUF_LENGTH); + return -EINVAL; + } + if (copy_from_user(&aucOidBuf[0], + prIwReqData->data.pointer, + u4CmdLen)) { + DBGLOG(REQ, ERROR, "copy_from_user fail\n"); + return -EFAULT; + } + aucOidBuf[u4CmdLen] = 0; + i4ResultLen = priv_driver_cmds(prNetDev, aucOidBuf, + u4CmdLen); + if (i4ResultLen > 1) { + if (copy_to_user(prIwReqData->data.pointer, + &aucOidBuf[0], i4ResultLen)) { + DBGLOG(REQ, ERROR, + "copy_to_user fail\n"); + return -EFAULT; + } + prIwReqData->data.length = i4ResultLen; + } else { + DBGLOG(REQ, ERROR, + "i4ResultLen:%d <= 1\n", i4ResultLen); + return -EFAULT; + } + } + break; /* case PRIV_CMD_GET_WIFI_TYPE: */ + + /* dynamic tx power control */ + case PRIV_CMD_SET_PWR_CTRL: + { + char *pCommand = NULL; + + u4CmdLen = prIwReqData->data.length; + if (u4CmdLen >= CMD_OID_BUF_LENGTH) + return -EINVAL; + if (copy_from_user(&aucOidBuf[0], + prIwReqData->data.pointer, + u4CmdLen)) { + status = -EFAULT; + break; + } + aucOidBuf[u4CmdLen] = 0; + if (strlen(aucOidBuf) <= 0) { + status = -EFAULT; + break; + } + pCommand = kalMemAlloc(u4CmdLen + 1, VIR_MEM_TYPE); + if (pCommand == NULL) { + DBGLOG(REQ, INFO, "alloc fail\n"); + return -EINVAL; + } + kalMemZero(pCommand, u4CmdLen + 1); + kalMemCopy(pCommand, aucOidBuf, u4CmdLen); + priv_driver_cmds(prNetDev, pCommand, u4CmdLen); + kalMemFree(pCommand, VIR_MEM_TYPE, i4TotalLen); + } + break; + + case PRIV_CMD_SET_ANT_SWAP_CTRL: + { + char *pCommand = NULL; + + u4CmdLen = prIwReqData->data.length; + if (u4CmdLen >= CMD_OID_BUF_LENGTH) + return -EINVAL; + if (copy_from_user(&aucOidBuf[0], + prIwReqData->data.pointer, + u4CmdLen)) { + status = -EFAULT; + break; + } + aucOidBuf[u4CmdLen] = 0; + if (strlen(aucOidBuf) <= 0) { + status = -EFAULT; + break; + } + pCommand = kalMemAlloc(u4CmdLen + 1, VIR_MEM_TYPE); + if (pCommand == NULL) { + DBGLOG(REQ, INFO, "alloc fail\n"); + return -EINVAL; + } + kalMemZero(pCommand, u4CmdLen + 1); + kalMemCopy(pCommand, aucOidBuf, u4CmdLen); + priv_driver_cmds(prNetDev, pCommand, u4CmdLen); + kalMemFree(pCommand, VIR_MEM_TYPE, i4TotalLen); + } + break; + + default: + return -EOPNOTSUPP; + } + + return status; +} /* __priv_set_struct */ + +int +priv_set_struct(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + DBGLOG(REQ, LOUD, "cmd=%x, flags=%x\n", + prIwReqInfo->cmd, prIwReqInfo->flags); + DBGLOG(REQ, LOUD, "mode=%x, flags=%x\n", + prIwReqData->mode, prIwReqData->data.flags); + + return compat_priv(prNetDev, prIwReqInfo, + prIwReqData, pcExtra, __priv_set_struct); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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) +{ + uint32_t u4SubCmd = 0; + struct NDIS_TRANSPORT_STRUCT *prNdisReq = NULL; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4BufLen = 0; + /* uint32_t *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 = (uint32_t) prIwReqData->data.flags; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, + "priv_get_struct(): invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, + *((struct GLUE_INFO **) netdev_priv(prNetDev))); + return -EINVAL; + } +#if 0 + DBGLOG(INIT, INFO, + "priv_get_struct(): prIwReqInfo->cmd(0x%X), u4SubCmd(%ld)\n", + prIwReqInfo->cmd, u4SubCmd); +#endif + memset(aucOidBuf, 0, sizeof(aucOidBuf)); + + switch (u4SubCmd) { + case PRIV_CMD_OID: + if (copy_from_user(&aucOidBuf[0], prIwReqData->data.pointer, + sizeof(struct NDIS_TRANSPORT_STRUCT))) { + DBGLOG(REQ, INFO, + "priv_get_struct() copy_from_user oidBuf fail\n"); + return -EFAULT; + } + + prNdisReq = (struct NDIS_TRANSPORT_STRUCT *) &aucOidBuf[0]; +#if 0 + DBGLOG(INIT, INFO, + "\n priv_get_struct cmd 0x%02x len:%d OID:0x%08x OID Len:%d\n", + cmd, + pIwReq->u.data.length, ndisReq->ndisOidCmd, + ndisReq->inNdisOidlength); +#endif + if (priv_get_ndis(prNetDev, prNdisReq, &u4BufLen) == 0) { + prNdisReq->outNdisOidLength = u4BufLen; + if (copy_to_user(prIwReqData->data.pointer, + &aucOidBuf[0], u4BufLen + + sizeof(struct NDIS_TRANSPORT_STRUCT) - + sizeof(prNdisReq->ndisOidContent))) { + DBGLOG(REQ, INFO, + "priv_get_struct() copy_to_user oidBuf fail(1)\n" + ); + return -EFAULT; + } + return 0; + } + prNdisReq->outNdisOidLength = u4BufLen; + if (copy_to_user(prIwReqData->data.pointer, + &aucOidBuf[0], OFFSET_OF(struct NDIS_TRANSPORT_STRUCT, + ndisOidContent))) { + DBGLOG(REQ, INFO, + "priv_get_struct() copy_to_user oidBuf fail(2)\n" + ); + } + return -EFAULT; + + case PRIV_CMD_SW_CTRL: + /* pu4IntBuf = (uint32_t *) prIwReqData->data.pointer; */ + prNdisReq = (struct NDIS_TRANSPORT_STRUCT *) &aucOidBuf[0]; + + if (prIwReqData->data.length > (sizeof(aucOidBuf) - + OFFSET_OF(struct NDIS_TRANSPORT_STRUCT, ndisOidContent))) { + DBGLOG(REQ, INFO, + "priv_get_struct() exceeds length limit\n"); + return -EFAULT; + } + + /* if (copy_from_user(&prNdisReq->ndisOidContent[0], + * prIwReqData->data.pointer, + */ + /* Coverity uanble to detect real size of ndisOidContent, + * it's 4084 bytes instead of 16 bytes + */ + if (copy_from_user(&aucOidBuf[OFFSET_OF(struct + NDIS_TRANSPORT_STRUCT, ndisOidContent)], + 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, + * *(uint32_t *)&prNdisReq->ndisOidContent[4]); + */ + + if (copy_to_user(prIwReqData->data.pointer, + &prNdisReq->ndisOidContent[4], 4)) + DBGLOG(REQ, INFO, + "priv_get_struct() copy_to_user oidBuf fail(2)\n" + ); + } + return 0; + default: + DBGLOG(REQ, WARN, "get struct cmd:0x%x\n", u4SubCmd); + return -EOPNOTSUPP; + } +} /* __priv_get_struct */ + +int +priv_get_struct(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + DBGLOG(REQ, LOUD, "cmd=%x, flags=%x\n", + prIwReqInfo->cmd, prIwReqInfo->flags); + DBGLOG(REQ, LOUD, "mode=%x, flags=%x\n", + prIwReqData->mode, prIwReqData->data.flags); + + return compat_priv(prNetDev, prIwReqInfo, + prIwReqData, pcExtra, __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 struct NDIS_TRANSPORT_STRUCT *prNdisReq, + OUT uint32_t *pu4OutputLen) +{ + struct WLAN_REQ_ENTRY *prWlanReqEntry = NULL; + uint32_t status = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t 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 = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, + "priv_set_ndis(): invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, + *((struct GLUE_INFO **) netdev_priv(prNetDev))); + return -EINVAL; + } +#if 0 + DBGLOG(INIT, INFO, + "priv_set_ndis(): prNdisReq->ndisOidCmd(0x%lX)\n", + prNdisReq->ndisOidCmd); +#endif + + if (reqSearchSupportedOidEntry(prNdisReq->ndisOidCmd, + &prWlanReqEntry) == FALSE) { + /* WARNLOG( + * ("Set OID: 0x%08lx (unknown)\n", + * prNdisReq->ndisOidCmd)); + */ + return -EOPNOTSUPP; + } + + if (prWlanReqEntry->pfOidSetHandler == NULL) { + /* WARNLOG( + * ("Set %s: Null set handler\n", + * prWlanReqEntry->pucOidName)); + */ + return -EOPNOTSUPP; + } +#if 0 + DBGLOG(INIT, INFO, "priv_set_ndis(): %s\n", + prWlanReqEntry->pucOidName); +#endif + + if (prWlanReqEntry->fgSetBufLenChecking) { + if (prNdisReq->inNdisOidlength != + prWlanReqEntry->u4InfoBufLen) { + DBGLOG(REQ, WARN, + "Set %s: Invalid length (current=%d, needed=%d)\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, &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 (status != WLAN_STATUS_SUCCESS) + 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 struct NDIS_TRANSPORT_STRUCT *prNdisReq, + OUT uint32_t *pu4OutputLen) +{ + struct WLAN_REQ_ENTRY *prWlanReqEntry = NULL; + uint32_t u4BufLen = 0; + uint32_t status = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *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 = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, + "priv_get_ndis(): invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, + *((struct GLUE_INFO **) netdev_priv(prNetDev))); + return -EINVAL; + } +#if 0 + DBGLOG(INIT, INFO, + "priv_get_ndis(): prNdisReq->ndisOidCmd(0x%lX)\n", + prNdisReq->ndisOidCmd); +#endif + + if (reqSearchSupportedOidEntry(prNdisReq->ndisOidCmd, + &prWlanReqEntry) == FALSE) { + /* WARNLOG( + * ("Query OID: 0x%08lx (unknown)\n", + * prNdisReq->ndisOidCmd)); + */ + return -EOPNOTSUPP; + } + + if (prWlanReqEntry->pfOidQueryHandler == NULL) { + /* WARNLOG( + * ("Query %s: Null query handler\n", + * prWlanReqEntry->pucOidName)); + */ + return -EOPNOTSUPP; + } +#if 0 + DBGLOG(INIT, INFO, "priv_get_ndis(): %s\n", + prWlanReqEntry->pucOidName); +#endif + + if (prWlanReqEntry->fgQryBufLenChecking) { + if (prNdisReq->inNdisOidlength < + prWlanReqEntry->u4InfoBufLen) { + /* Not enough room in InformationBuffer. Punt */ + /* WARNLOG( + * ("Query %s: Buffer too short (current=%ld, + * needed=%ld)\n", + * prWlanReqEntry->pucOidName, + * prNdisReq->inNdisOidlength, + * prWlanReqEntry->u4InfoBufLen)); + */ + + *pu4OutputLen = prWlanReqEntry->u4InfoBufLen; + + status = WLAN_STATUS_INVALID_LENGTH; + return -EINVAL; + } + } + + if (prWlanReqEntry->eOidMethod == ENUM_OID_GLUE_ONLY) { + /* GLUE sw info only */ + status = prWlanReqEntry->pfOidQueryHandler(prGlueInfo, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, &u4BufLen); + } else if (prWlanReqEntry->eOidMethod == + ENUM_OID_GLUE_EXTENSION) { + /* multiple sw operations */ + status = prWlanReqEntry->pfOidQueryHandler(prGlueInfo, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, &u4BufLen); + } else if (prWlanReqEntry->eOidMethod == + ENUM_OID_DRIVER_CORE) { + /* driver core */ + + status = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC)prWlanReqEntry->pfOidQueryHandler, + prNdisReq->ndisOidContent, prNdisReq->inNdisOidlength, + TRUE, TRUE, TRUE, &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 (status != WLAN_STATUS_SUCCESS) + return -EOPNOTSUPP; + + return 0; +} /* priv_get_ndis */ + +#if CFG_SUPPORT_QA_TOOL +/*----------------------------------------------------------------------------*/ +/*! + * \brief The routine handles ATE set operation. + * + * \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 -EFAULT If copy from user space buffer fail. + * + */ +/*----------------------------------------------------------------------------*/ +int +__priv_ate_set(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, + IN char *pcExtra) +{ + int32_t i4Status; + /* uint8_t *InBuf; + * uint8_t *addr_str, *value_str; + * uint32_t InBufLen; + */ + uint32_t u4SubCmd; + /* u_int8_t isWrite = 0; + * uint32_t u4BufLen = 0; + * struct NDIS_TRANSPORT_STRUCT *prNdisReq; + * uint32_t pu4IntBuf[2]; + */ + uint32_t u4CopySize = sizeof(aucOidBuf); + + /* sanity check */ + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + + if (GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra) == FALSE) + return -EINVAL; + + u4SubCmd = (uint32_t) prIwReqData->data.flags; + DBGLOG(REQ, INFO, "MT6632: %s, u4SubCmd=%d mode=%d\n", __func__, + u4SubCmd, (uint32_t) prIwReqData->mode); + + switch (u4SubCmd) { + case PRIV_QACMD_SET: + u4CopySize = (prIwReqData->data.length < u4CopySize) + ? prIwReqData->data.length : (u4CopySize - 1); + if (copy_from_user(&aucOidBuf[0], prIwReqData->data.pointer, + u4CopySize)) + return -EFAULT; + aucOidBuf[u4CopySize] = '\0'; + DBGLOG(REQ, INFO, + "PRIV_QACMD_SET: priv_set_string=(%s)(%u,%d)\n", + aucOidBuf, u4CopySize, + (int32_t)prIwReqData->data.length); + i4Status = AteCmdSetHandle(prNetDev, &aucOidBuf[0], + u4CopySize); + break; + default: + return -EOPNOTSUPP; + } + return 0; +} + +int +priv_ate_set(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + DBGLOG(REQ, LOUD, "cmd=%x, flags=%x\n", + prIwReqInfo->cmd, prIwReqInfo->flags); + DBGLOG(REQ, LOUD, "mode=%x, flags=%x\n", + prIwReqData->mode, prIwReqData->data.flags); + + return compat_priv(prNetDev, prIwReqInfo, + prIwReqData, pcExtra, __priv_ate_set); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \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 u_int8_t reqSearchSupportedOidEntry(IN uint32_t rOid, + OUT struct WLAN_REQ_ENTRY **ppWlanReqEntry) +{ + int32_t i, j, k; + + i = 0; + j = NUM_SUPPORTED_OIDS - 1; + + while (i <= j) { + k = i + (j - i) / 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 */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Private ioctl driver 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_set_driver(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + uint32_t u4SubCmd = 0; + uint16_t u2Cmd = 0; + + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + + ASSERT(prNetDev); + ASSERT(prIwReqData); + if (!prNetDev || !prIwReqData) { + DBGLOG(REQ, INFO, + "priv_set_driver(): invalid param(0x%p, 0x%p)\n", + prNetDev, prIwReqData); + return -EINVAL; + } + + u2Cmd = prIwReqInfo->cmd; + DBGLOG(REQ, INFO, "prIwReqInfo->cmd %u\n", u2Cmd); + + u4SubCmd = (uint32_t) prIwReqData->data.flags; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, + "priv_set_driver(): invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, + *((struct GLUE_INFO **) netdev_priv(prNetDev))); + return -EINVAL; + } + + /* trick,hack in ./net/wireless/wext-priv.c ioctl_private_iw_point */ + /* because the cmd number is odd (get), the input string will not be + * copy_to_user + */ + + DBGLOG(REQ, INFO, "prIwReqData->data.length %u\n", + prIwReqData->data.length); + + /* Use GET type becauase large data by iwpriv. */ + + ASSERT(IW_IS_GET(u2Cmd)); + if (prIwReqData->data.length != 0) { + if (!kal_access_ok(VERIFY_READ, prIwReqData->data.pointer, + prIwReqData->data.length)) { + DBGLOG(REQ, INFO, + "%s access_ok Read fail written = %d\n", + __func__, i4BytesWritten); + return -EFAULT; + } + if (copy_from_user(pcExtra, prIwReqData->data.pointer, + prIwReqData->data.length)) { + DBGLOG(REQ, INFO, + "%s copy_form_user fail written = %d\n", + __func__, prIwReqData->data.length); + return -EFAULT; + } + /* prIwReqData->data.length include the terminate '\0' */ + pcExtra[prIwReqData->data.length] = 0; + } + + if (pcExtra) { + DBGLOG(REQ, INFO, "pcExtra %s\n", pcExtra); + /* Please check max length in rIwPrivTable */ + DBGLOG(REQ, INFO, "%s prIwReqData->data.length = %d\n", + __func__, prIwReqData->data.length); + i4BytesWritten = priv_driver_cmds(prNetDev, pcExtra, + 2000 /*prIwReqData->data.length */); + DBGLOG(REQ, INFO, "%s i4BytesWritten = %d\n", __func__, + i4BytesWritten); + } + + DBGLOG(REQ, INFO, "pcExtra done\n"); + + if (i4BytesWritten > 0) { + + if (i4BytesWritten > 2000) + i4BytesWritten = 2000; + prIwReqData->data.length = + i4BytesWritten; /* the iwpriv will use the length */ + + } else if (i4BytesWritten == 0) { + prIwReqData->data.length = i4BytesWritten; + } +#if 0 + /* trick,hack in ./net/wireless/wext-priv.c ioctl_private_iw_point */ + /* because the cmd number is even (set), the return string will not be + * copy_to_user + */ + ASSERT(IW_IS_SET(u2Cmd)); + if (!access_ok(VERIFY_WRITE, prIwReqData->data.pointer, + i4BytesWritten)) { + DBGLOG(REQ, INFO, "%s access_ok Write fail written = %d\n", + __func__, i4BytesWritten); + return -EFAULT; + } + if (copy_to_user(prIwReqData->data.pointer, pcExtra, + i4BytesWritten)) { + DBGLOG(REQ, INFO, "%s copy_to_user fail written = %d\n", + __func__, i4BytesWritten); + return -EFAULT; + } + DBGLOG(RSN, INFO, "%s copy_to_user written = %d\n", + __func__, i4BytesWritten); +#endif + return 0; + +} /* priv_set_driver */ +#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 uint32_t +reqExtQueryConfiguration(IN struct GLUE_INFO *prGlueInfo, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + struct PARAM_802_11_CONFIG *prQueryConfig = + (struct PARAM_802_11_CONFIG *) pvQueryBuffer; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4QueryInfoLen = 0; + + DEBUGFUNC("wlanoidQueryConfiguration"); + + ASSERT(prGlueInfo); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(struct PARAM_802_11_CONFIG); + if (u4QueryBufferLen < sizeof(struct PARAM_802_11_CONFIG)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvQueryBuffer); + + kalMemZero(prQueryConfig, + sizeof(struct PARAM_802_11_CONFIG)); + + /* Update the current radio configuration. */ + prQueryConfig->u4Length = sizeof(struct PARAM_802_11_CONFIG); + +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidSetBeaconInterval, + &prQueryConfig->u4BeaconPeriod, sizeof(uint32_t), + TRUE, TRUE, &u4QueryInfoLen); +#else + rStatus = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryBeaconInterval, + &prQueryConfig->u4BeaconPeriod, + sizeof(uint32_t), &u4QueryInfoLen); +#endif + if (rStatus != WLAN_STATUS_SUCCESS) + return rStatus; +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidQueryAtimWindow, + &prQueryConfig->u4ATIMWindow, sizeof(uint32_t), + TRUE, TRUE, &u4QueryInfoLen); +#else + rStatus = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryAtimWindow, + &prQueryConfig->u4ATIMWindow, + sizeof(uint32_t), + &u4QueryInfoLen); +#endif + if (rStatus != WLAN_STATUS_SUCCESS) + return rStatus; +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidQueryFrequency, + &prQueryConfig->u4DSConfig, sizeof(uint32_t), + TRUE, TRUE, &u4QueryInfoLen); +#else + rStatus = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryFrequency, + &prQueryConfig->u4DSConfig, + sizeof(uint32_t), + &u4QueryInfoLen); +#endif + if (rStatus != WLAN_STATUS_SUCCESS) + return rStatus; + + prQueryConfig->rFHConfig.u4Length = sizeof( + struct PARAM_802_11_CONFIG_FH); + + 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 uint32_t +reqExtSetConfiguration(IN struct GLUE_INFO *prGlueInfo, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct PARAM_802_11_CONFIG *prNewConfig = + (struct PARAM_802_11_CONFIG *) pvSetBuffer; + uint32_t u4SetInfoLen = 0; + + DEBUGFUNC("wlanoidSetConfiguration"); + + ASSERT(prGlueInfo); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_802_11_CONFIG); + + if (u4SetBufferLen < *pu4SetInfoLen) + return WLAN_STATUS_INVALID_LENGTH; + + /* OID_802_11_CONFIGURATION. If associated, NOT_ACCEPTED shall be + * returned. + */ + if (prGlueInfo->eParamMediaStateIndicated == + MEDIA_STATE_CONNECTED) + return WLAN_STATUS_NOT_ACCEPTED; + + ASSERT(pvSetBuffer); + +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidSetBeaconInterval, + &prNewConfig->u4BeaconPeriod, sizeof(uint32_t), + FALSE, TRUE, &u4SetInfoLen); +#else + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetBeaconInterval, + &prNewConfig->u4BeaconPeriod, + sizeof(uint32_t), + &u4SetInfoLen); +#endif + if (rStatus != WLAN_STATUS_SUCCESS) + return rStatus; +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidSetAtimWindow, + &prNewConfig->u4ATIMWindow, sizeof(uint32_t), + FALSE, TRUE, &u4SetInfoLen); +#else + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetAtimWindow, + &prNewConfig->u4ATIMWindow, + sizeof(uint32_t), &u4SetInfoLen); +#endif + if (rStatus != WLAN_STATUS_SUCCESS) + return rStatus; +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, wlanoidSetFrequency, + &prNewConfig->u4DSConfig, sizeof(uint32_t), + FALSE, TRUE, &u4SetInfoLen); +#else + rStatus = wlanSetInformation(prGlueInfo->prAdapter, wlanoidSetFrequency, + &prNewConfig->u4DSConfig, + sizeof(uint32_t), &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 uint32_t +reqExtSetAcpiDevicePowerState(IN struct GLUE_INFO + *prGlueInfo, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t 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; +} + +#define CMD_START "START" +#define CMD_STOP "STOP" +#define CMD_SCAN_ACTIVE "SCAN-ACTIVE" +#define CMD_SCAN_PASSIVE "SCAN-PASSIVE" +#define CMD_RSSI "RSSI" +#define CMD_LINKSPEED "LINKSPEED" +#define CMD_RXFILTER_START "RXFILTER-START" +#define CMD_RXFILTER_STOP "RXFILTER-STOP" +#define CMD_RXFILTER_ADD "RXFILTER-ADD" +#define CMD_RXFILTER_REMOVE "RXFILTER-REMOVE" +#define CMD_BTCOEXSCAN_START "BTCOEXSCAN-START" +#define CMD_BTCOEXSCAN_STOP "BTCOEXSCAN-STOP" +#define CMD_BTCOEXMODE "BTCOEXMODE" +#define CMD_SETSUSPENDOPT "SETSUSPENDOPT" +#define CMD_SETSUSPENDMODE "SETSUSPENDMODE" +#define CMD_P2P_DEV_ADDR "P2P_DEV_ADDR" +#define CMD_SETFWPATH "SETFWPATH" +#define CMD_SETBAND "SETBAND" +#define CMD_GETBAND "GETBAND" +#define CMD_AP_START "AP_START" + +#if CFG_SUPPORT_QA_TOOL +#define CMD_GET_RX_STATISTICS "GET_RX_STATISTICS" +#endif +#define CMD_GET_STAT "GET_STAT" +#define CMD_GET_BSS_STATISTICS "GET_BSS_STATISTICS" +#define CMD_GET_STA_STATISTICS "GET_STA_STATISTICS" +#define CMD_GET_WTBL_INFO "GET_WTBL" +#define CMD_GET_MIB_INFO "GET_MIB" +#define CMD_GET_STA_INFO "GET_STA" +#define CMD_SET_FW_LOG "SET_FWLOG" +#define CMD_GET_QUE_INFO "GET_QUE" +#define CMD_GET_MEM_INFO "GET_MEM" +#define CMD_GET_HIF_INFO "GET_HIF" +#define CMD_GET_TP_INFO "GET_TP" +#define CMD_GET_STA_KEEP_CNT "KEEPCOUNTER" +#define CMD_STAT_RESET_CNT "RESETCOUNTER" +#define CMD_STAT_NOISE_SEL "NOISESELECT" +#define CMD_STAT_GROUP_SEL "GROUP" + +#define CMD_SET_TXPOWER "SET_TXPOWER" +#define CMD_COUNTRY "COUNTRY" +#define CMD_CSA "CSA" +#define CMD_GET_COUNTRY "GET_COUNTRY" +#define CMD_GET_CHANNELS "GET_CHANNELS" +#define CMD_P2P_SET_NOA "P2P_SET_NOA" +#define CMD_P2P_GET_NOA "P2P_GET_NOA" +#define CMD_P2P_SET_PS "P2P_SET_PS" +#define CMD_SET_AP_WPS_P2P_IE "SET_AP_WPS_P2P_IE" +#define CMD_SETROAMMODE "SETROAMMODE" +#define CMD_MIRACAST "MIRACAST" + +#if (CFG_SUPPORT_DFS_MASTER == 1) +#define CMD_SHOW_DFS_STATE "SHOW_DFS_STATE" +#define CMD_SHOW_DFS_RADAR_PARAM "SHOW_DFS_RADAR_PARAM" +#define CMD_SHOW_DFS_HELP "SHOW_DFS_HELP" +#define CMD_SHOW_DFS_CAC_TIME "SHOW_DFS_CAC_TIME" +#endif + +#define CMD_PNOSSIDCLR_SET "PNOSSIDCLR" +#define CMD_PNOSETUP_SET "PNOSETUP " +#define CMD_PNOENABLE_SET "PNOFORCE" +#define CMD_PNODEBUG_SET "PNODEBUG" +#define CMD_WLS_BATCHING "WLS_BATCHING" + +#define CMD_OKC_SET_PMK "SET_PMK" +#define CMD_OKC_ENABLE "OKC_ENABLE" + +#define CMD_SETMONITOR "MONITOR" +#define CMD_SETBUFMODE "BUFFER_MODE" + +#define CMD_GET_CH_RANK_LIST "GET_CH_RANK_LIST" +#define CMD_GET_CH_DIRTINESS "GET_CH_DIRTINESS" + +#if CFG_CHIP_RESET_HANG +#define CMD_SET_RST_HANG "RST_HANG_SET" + +#define CMD_SET_RST_HANG_ARG_NUM 2 +#endif + + +#define CMD_EFUSE "EFUSE" + +#if (CFG_SUPPORT_TWT == 1) +#define CMD_SET_TWT_PARAMS "SET_TWT_PARAMS" +#endif + +#define CMD_CCCR "CCCR" + +/* miracast related definition */ +#define MIRACAST_MODE_OFF 0 +#define MIRACAST_MODE_SOURCE 1 +#define MIRACAST_MODE_SINK 2 + +#ifndef MIRACAST_AMPDU_SIZE +#define MIRACAST_AMPDU_SIZE 8 +#endif + +#ifndef MIRACAST_MCHAN_ALGO +#define MIRACAST_MCHAN_ALGO 1 +#endif + +#ifndef MIRACAST_MCHAN_BW +#define MIRACAST_MCHAN_BW 25 +#endif + +#define CMD_BAND_TYPE_AUTO 0 +#define CMD_BAND_TYPE_5G 1 +#define CMD_BAND_TYPE_2G 2 +#define CMD_BAND_TYPE_ALL 3 + +/* Mediatek private command */ +#define CMD_SET_MCR "SET_MCR" +#define CMD_GET_MCR "GET_MCR" +#define CMD_SET_NVRAM "SET_NVRAM" +#define CMD_GET_NVRAM "GET_NVRAM" +#define CMD_SET_DRV_MCR "SET_DRV_MCR" +#define CMD_GET_DRV_MCR "GET_DRV_MCR" +#define CMD_SET_SW_CTRL "SET_SW_CTRL" +#define CMD_GET_SW_CTRL "GET_SW_CTRL" +#define CMD_SET_CFG "SET_CFG" +#define CMD_GET_CFG "GET_CFG" +#define CMD_SET_EM_CFG "SET_EM_CFG" +#define CMD_GET_EM_CFG "GET_EM_CFG" +#define CMD_SET_CHIP "SET_CHIP" +#define CMD_GET_CHIP "GET_CHIP" +#define CMD_SET_DBG_LEVEL "SET_DBG_LEVEL" +#define CMD_GET_DBG_LEVEL "GET_DBG_LEVEL" +#define CMD_ADD_TS "addts" +#define CMD_DEL_TS "delts" +#define CMD_DUMP_TS "dumpts" +#define CMD_RM_IT "RM-IT" +#define CMD_DUMP_UAPSD "dumpuapsd" +#define CMD_FW_EVENT "FW-EVENT " +#define CMD_GET_WIFI_TYPE "GET_WIFI_TYPE" +#define CMD_SET_PWR_CTRL "SET_PWR_CTRL" +#define CMD_SET_ANT_SWAP "SET_ANT_SWAP" +#define PRIV_CMD_SIZE 512 +#define CMD_SET_FIXED_RATE "FixedRate" +#define CMD_GET_VERSION "VER" +#define CMD_SET_TEST_MODE "SET_TEST_MODE" +#define CMD_SET_TEST_CMD "SET_TEST_CMD" +#define CMD_GET_TEST_RESULT "GET_TEST_RESULT" +#define CMD_GET_STA_STAT "STAT" +#define CMD_GET_STA_STAT2 "STAT2" +#define CMD_GET_STA_RX_STAT "RX_STAT" +#define CMD_SET_ACL_POLICY "SET_ACL_POLICY" +#define CMD_ADD_ACL_ENTRY "ADD_ACL_ENTRY" +#define CMD_DEL_ACL_ENTRY "DEL_ACL_ENTRY" +#define CMD_SHOW_ACL_ENTRY "SHOW_ACL_ENTRY" +#define CMD_CLEAR_ACL_ENTRY "CLEAR_ACL_ENTRY" +#define CMD_SET_RA_DBG "RADEBUG" +#define CMD_SET_FIXED_FALLBACK "FIXEDRATEFALLBACK" +#define CMD_GET_STA_IDX "GET_STA_IDX" +#define CMD_GET_TX_POWER_INFO "TxPowerInfo" +#define CMD_TX_POWER_MANUAL_SET "TxPwrManualSet" +#if CFG_SUPPORT_SCAN_EXT_FLAG +#define CMD_SET_SCAN_EXT_FLAG "SetScanExtFlag" +#endif + + +/* neptune doens't support "show" entry, use "driver" to handle + * MU GET request, and MURX_PKTCNT comes from RX_STATS, + * so this command will reuse RX_STAT's flow + */ +#define CMD_GET_MU_RX_PKTCNT "hqa_get_murx_pktcnt" +#define CMD_RUN_HQA "hqa" +#define CMD_CALIBRATION "cal" + +#if CFG_WOW_SUPPORT +#define CMD_WOW_START "WOW_START" +#define CMD_SET_WOW_ENABLE "SET_WOW_ENABLE" +#define CMD_SET_WOW_PAR "SET_WOW_PAR" +#define CMD_SET_WOW_UDP "SET_WOW_UDP" +#define CMD_SET_WOW_TCP "SET_WOW_TCP" +#define CMD_GET_WOW_PORT "GET_WOW_PORT" +#endif +#define CMD_SET_ADV_PWS "SET_ADV_PWS" +#define CMD_SET_MDTIM "SET_MDTIM" + +#define CMD_SET_DBDC "SET_DBDC" +#define CMD_SET_STA1NSS "SET_STA1NSS" + +#define CMD_SET_AMPDU_TX "SET_AMPDU_TX" +#define CMD_SET_AMPDU_RX "SET_AMPDU_RX" +#define CMD_SET_BF "SET_BF" +#define CMD_SET_NSS "SET_NSS" +#define CMD_SET_AMSDU_TX "SET_AMSDU_TX" +#define CMD_SET_AMSDU_RX "SET_AMSDU_RX" +#define CMD_SET_QOS "SET_QOS" +#if (CFG_SUPPORT_802_11AX == 1) +#define CMD_SET_BA_SIZE "SET_BA_SIZE" +#define CMD_SET_TP_TEST_MODE "SET_TP_TEST_MODE" +#define CMD_SET_MUEDCA_OVERRIDE "MUEDCA_OVERRIDE" +#define CMD_SET_TX_MCSMAP "SET_MCS_MAP" +#define CMD_SET_TX_PPDU "TX_PPDU" +#define CMD_SET_LDPC "SET_LDPC" +#define CMD_FORCE_AMSDU_TX "FORCE_AMSDU_TX" +#define CMD_SET_OM_CH_BW "SET_OM_CHBW" +#define CMD_SET_OM_RX_NSS "SET_OM_RXNSS" +#define CMD_SET_OM_TX_NSS "SET_OM_TXNSTS" +#define CMD_SET_OM_MU_DISABLE "SET_OM_MU_DISABLE" +#define CMD_SET_TX_OM_PACKET "TX_OM_PACKET" +#define CMD_SET_TX_CCK_1M_PWR "TX_CCK_1M_PWR" +#define CMD_SET_PAD_DUR "SET_PAD_DUR" +#endif /* CFG_SUPPORT_802_11AX == 1 */ + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +#define CMD_SET_CALBACKUP_TEST_DRV_FW "SET_CALBACKUP_TEST_DRV_FW" +#endif + +#define CMD_GET_CNM "GET_CNM" +#define CMD_GET_CAPAB_RSDB "GET_CAPAB_RSDB" + +#ifdef UT_TEST_MODE +#define CMD_RUN_UT "UT" +#endif + +#if CFG_SUPPORT_ADVANCE_CONTROL +#define CMD_SW_DBGCTL_ADVCTL_SET_ID 0xa1260000 +#define CMD_SW_DBGCTL_ADVCTL_GET_ID 0xb1260000 +#define CMD_SET_NOISE "SET_NOISE" +#define CMD_GET_NOISE "GET_NOISE" +#define CMD_SET_POP "SET_POP" +#define CMD_SET_ED "SET_ED" +#define CMD_SET_PD "SET_PD" +#define CMD_SET_MAX_RFGAIN "SET_MAX_RFGAIN" +#endif + +#if CFG_SUPPORT_WIFI_SYSDVT +#define CMD_WIFI_SYSDVT "DVT" +#define CMD_SET_TXS_TEST "TXS_TEST" +#define CMD_SET_TXS_TEST_RESULT "TXS_RESULT" +#define CMD_SET_RXV_TEST "RXV_TEST" +#define CMD_SET_RXV_TEST_RESULT "RXV_RESULT" +#if CFG_TCP_IP_CHKSUM_OFFLOAD +#define CMD_SET_CSO_TEST "CSO_TEST" +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ +#define CMD_SET_TX_TEST "TX_TEST" +#define CMD_SET_TX_AC_TEST "TX_AC_TEST" +#define CMD_SET_SKIP_CH_CHECK "SKIP_CH_CHECK" + +#if (CFG_SUPPORT_DMASHDL_SYSDVT) +#define CMD_SET_DMASHDL_DUMP "DMASHDL_DUMP_MEM" +#define CMD_SET_DMASHDL_DVT_ITEM "DMASHDL_DVT_ITEM" +#endif /* CFG_SUPPORT_DMASHDL_SYSDVT */ +#endif /* CFG_SUPPORT_WIFI_SYSDVT */ + +#define CMD_SET_SW_AMSDU_NUM "SET_SW_AMSDU_NUM" +#define CMD_SET_SW_AMSDU_SIZE "SET_SW_AMSDU_SIZE" + +#define CMD_SET_DRV_SER "SET_DRV_SER" + +#define CMD_GET_WFDMA_INFO "GET_WFDMA_INFO" +#define CMD_GET_PLE_INFO "GET_PLE_INFO" +#define CMD_GET_PSE_INFO "GET_PSE_INFO" +#define CMD_GET_DMASCH_INFO "GET_DMASCH_INFO" +#define CMD_SHOW_TXD_INFO "SHOW_TXD_INFO" + +#if (CFG_SUPPORT_CONNAC2X == 1) +#define CMD_GET_FWTBL_UMAC "GET_UMAC_FWTBL" +#endif /* CFG_SUPPORT_CONNAC2X == 1 */ + +/* Debug for consys */ +#define CMD_DBG_SHOW_TR_INFO "show-tr" +#define CMD_DBG_SHOW_PLE_INFO "show-ple" +#define CMD_DBG_SHOW_PSE_INFO "show-pse" +#define CMD_DBG_SHOW_CSR_INFO "show-csr" +#define CMD_DBG_SHOW_DMASCH_INFO "show-dmasch" + +#if CFG_SUPPORT_EASY_DEBUG +#define CMD_FW_PARAM "set_fw_param" +#endif /* CFG_SUPPORT_EASY_DEBUG */ + +#if (CFG_SUPPORT_CONNINFRA == 1) +#define CMD_SET_WHOLE_CHIP_RESET "SET_WHOLE_CHIP_RESET" +#define CMD_SET_WFSYS_RESET "SET_WFSYS_RESET" +#endif +static uint8_t g_ucMiracastMode = MIRACAST_MODE_OFF; + +struct cmd_tlv { + char prefix; + char version; + char subver; + char reserved; +}; + +struct priv_driver_cmd_s { + char buf[PRIV_CMD_SIZE]; + int used_len; + int total_len; +}; + +#ifdef CFG_ANDROID_AOSP_PRIV_CMD +struct android_wifi_priv_cmd { + char *buf; + int used_len; + int total_len; +}; +#endif /* CFG_ANDROID_AOSP_PRIV_CMD */ + +int priv_driver_get_dbg_level(IN struct net_device + *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4DbgIdx = DBG_MODULE_NUM, u4DbgMask = 0; + u_int8_t fgIsCmdAccept = FALSE; + int32_t u4Ret = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= 2) { + /* u4DbgIdx = kalStrtoul(apcArgv[1], NULL, 0); */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4DbgIdx); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + + if (wlanGetDriverDbgLevel(u4DbgIdx, &u4DbgMask) == + WLAN_STATUS_SUCCESS) { + fgIsCmdAccept = TRUE; + i4BytesWritten = + kalSnprintf(pcCommand, i4TotalLen, + "Get DBG module[%u] log level => [0x%02x]!", + u4DbgIdx, + (uint8_t) u4DbgMask); + } + } + + if (!fgIsCmdAccept) + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, + "Get DBG module log level failed!"); + + return i4BytesWritten; + +} /* priv_driver_get_sw_ctrl */ + +static int priv_cmd_not_support(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + DBGLOG(REQ, WARN, "not support priv command: %s\n", pcCommand); + + return -EOPNOTSUPP; +} + +#if CFG_SUPPORT_QA_TOOL +#if CFG_SUPPORT_BUFFER_MODE +static int priv_driver_set_efuse_buffer_mode( + IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int32_t i4BytesWritten = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE + *prSetEfuseBufModeInfo = NULL; +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 0) + struct BIN_CONTENT *pBinContent; + int i = 0; +#endif + uint8_t *pucConfigBuf = NULL; + uint32_t u4ConfigReadLen; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + pucConfigBuf = (uint8_t *) kalMemAlloc(2048, VIR_MEM_TYPE); + + if (!pucConfigBuf) { + DBGLOG(INIT, INFO, "allocate pucConfigBuf failed\n"); + i4BytesWritten = -1; + goto out; + } + + kalMemZero(pucConfigBuf, 2048); + u4ConfigReadLen = 0; + + if (kalReadToFile("/MT6632_eFuse_usage_table.xlsm.bin", + pucConfigBuf, 2048, &u4ConfigReadLen) == 0) { + /* ToDo:: Nothing */ + } else { + DBGLOG(INIT, INFO, "can't find file\n"); + i4BytesWritten = -1; + goto out; + } + + /* pucConfigBuf */ + prSetEfuseBufModeInfo = + (struct PARAM_CUSTOM_EFUSE_BUFFER_MODE *) kalMemAlloc( + sizeof(struct PARAM_CUSTOM_EFUSE_BUFFER_MODE), + VIR_MEM_TYPE); + + if (prSetEfuseBufModeInfo == NULL) { + DBGLOG(INIT, INFO, + "allocate prSetEfuseBufModeInfo failed\n"); + i4BytesWritten = -1; + goto out; + } + + kalMemZero(prSetEfuseBufModeInfo, + sizeof(struct PARAM_CUSTOM_EFUSE_BUFFER_MODE)); + + prSetEfuseBufModeInfo->ucSourceMode = 1; + prSetEfuseBufModeInfo->ucCount = (uint8_t) + EFUSE_CONTENT_SIZE; + +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 0) + pBinContent = (struct BIN_CONTENT *) + prSetEfuseBufModeInfo->aBinContent; + for (i = 0; i < EFUSE_CONTENT_SIZE; i++) { + pBinContent->u2Addr = i; + pBinContent->ucValue = *(pucConfigBuf + i); + + pBinContent++; + } + + for (i = 0; i < 20; i++) + DBGLOG(INIT, INFO, "%x\n", + prSetEfuseBufModeInfo->aBinContent[i].ucValue); +#endif + + rStatus = kalIoctl(prGlueInfo, wlanoidSetEfusBufferMode, + prSetEfuseBufModeInfo, + sizeof(struct PARAM_CUSTOM_EFUSE_BUFFER_MODE), + FALSE, FALSE, TRUE, &u4BufLen); + + i4BytesWritten = + kalSnprintf(pcCommand, i4TotalLen, "set buffer mode %s", + (rStatus == WLAN_STATUS_SUCCESS) ? "success" : "fail"); + +out: + if (pucConfigBuf) + kalMemFree(pucConfigBuf, VIR_MEM_TYPE, 2048); + + if (prSetEfuseBufModeInfo) + kalMemFree(prSetEfuseBufModeInfo, VIR_MEM_TYPE, + sizeof(truct PARAM_CUSTOM_EFUSE_BUFFER_MODE)); + + return i4BytesWritten; +} +#endif /* CFG_SUPPORT_BUFFER_MODE */ + +static int priv_driver_get_rx_statistics(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + int32_t u4Ret = 0; + struct PARAM_CUSTOM_ACCESS_RX_STAT rRxStatisticsTest; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + DBGLOG(INIT, ERROR, + "MT6632 : priv_driver_get_rx_statistics\n"); + + if (i4Argc >= 2) { + u4Ret = kalkStrtou32(apcArgv[1], 0, + &(rRxStatisticsTest.u4SeqNum)); + rRxStatisticsTest.u4TotalNum = sizeof(struct + PARAM_RX_STAT) / 4; + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryRxStatistics, + &rRxStatisticsTest, sizeof(rRxStatisticsTest), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } + + return i4BytesWritten; +} +#endif /* CFG_SUPPORT_QA_TOOL */ + +#if CFG_SUPPORT_MSP +#if 0 +static int priv_driver_get_stat(IN struct net_device + *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t i4ArgNum = 2; + struct PARAM_GET_STA_STATISTICS rQueryStaStatistics; + int32_t rRssi; + uint16_t u2LinkSpeed; + uint32_t u4Per; + UINTT_8 i; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + kalMemZero(&rQueryStaStatistics, + sizeof(rQueryStaStatistics)); + + if (i4Argc >= i4ArgNum) { + wlanHwAddrToBin(apcArgv[1], + &rQueryStaStatistics.aucMacAddr[0]); + + rQueryStaStatistics.ucReadClear = TRUE; + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryStaStatistics, + &rQueryStaStatistics, + sizeof(rQueryStaStatistics), + TRUE, FALSE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_SUCCESS) { + rRssi = RCPI_TO_dBm(rQueryStaStatistics.ucRcpi); + u2LinkSpeed = rQueryStaStatistics.u2LinkSpeed == 0 ? 0 : + rQueryStaStatistics.u2LinkSpeed / 2; + + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, + "%s", "\n\nSTA Stat:\n"); + + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "CurrentTemperature = %d\n", 0); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Tx success = %lu\n", 0); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Tx fail count = %ld, PER=%ld.%1ld%%\n", + 0, 0, 0); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Rx success = %lu\n", 0); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Rx with CRC = %ld, PER=%ld.%1ld%%\n", + 0, 0, 0); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Rx with PhyErr = %lu\n", 0); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Rx with PlcpErr = %lu\n", 0); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Rx drop due to out of resource= %lu\n", 0); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Rx duplicate frame = %lu\n", 0); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "False CCA = %lu\n", 0); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "RSSI = %d %d %d %d\n", + 0, 0, 0, 0); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Last TX Rate = %s, %s, %s, %s, %s\n", + "NA", "NA", "NA", "NA", "NA"); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Last RX Rate = %s, %s, %s, %s, %s\n", + "NA", "NA", "NA", "NA", "NA"); + + for (i = 0; i < 2 /* band num */; i++) { + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "BandIdx: = %d\n", i); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s", + "\tRange: 1 2~5 6~15 16~22 23~33 34~49 50~57 58~64\n" + ); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\t\t%d \t%d \t%d \t%d \t%d \t%d \t%d \t%d\n", + 0, 0, 0, 0, 0, 0, 0, 0); + } + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Tx success = %ld\n", + rQueryStaStatistics.u4TransmitCount - + rQueryStaStatistics.u4TransmitFailCount); + + u4Per = rQueryStaStatistics.u4TransmitFailCount == 0 ? + 0 : + (1000 * (rQueryStaStatistics.u4TransmitFailCount)) + / rQueryStaStatistics.u4TransmitCount; + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Tx fail count = %ld, PER=%ld.%1ld%%\n", + rQueryStaStatistics.u4TransmitFailCount, + u4Per / 10, u4Per % 10); + + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "RSSI = %d\n", rRssi); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "LinkSpeed = %d\n", u2LinkSpeed); + } + } else + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, "%s", + "\n\nNo STA Stat:\n"); + + return i4BytesWritten; +} +#endif + + +static int priv_driver_get_sta_statistics( + IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t i4ArgNum = 3; + struct PARAM_GET_STA_STATISTICS rQueryStaStatistics; + int32_t rRssi; + uint16_t u2LinkSpeed; + uint32_t u4Per; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + kalMemZero(&rQueryStaStatistics, + sizeof(rQueryStaStatistics)); + rQueryStaStatistics.ucReadClear = TRUE; + + if (i4Argc >= i4ArgNum) { + if (strnicmp(apcArgv[1], CMD_GET_STA_KEEP_CNT, + strlen(CMD_GET_STA_KEEP_CNT)) == 0) { + wlanHwAddrToBin(apcArgv[2], + &rQueryStaStatistics.aucMacAddr[0]); + rQueryStaStatistics.ucReadClear = FALSE; + } else if (strnicmp(apcArgv[2], CMD_GET_STA_KEEP_CNT, + strlen(CMD_GET_STA_KEEP_CNT)) == 0) { + wlanHwAddrToBin(apcArgv[1], + &rQueryStaStatistics.aucMacAddr[0]); + rQueryStaStatistics.ucReadClear = FALSE; + } + } else { + struct BSS_INFO *prAisBssInfo = aisGetAisBssInfo( + prGlueInfo->prAdapter, wlanGetBssIdx(prNetDev)); + + /* Get AIS AP address for no argument */ + if (prAisBssInfo->prStaRecOfAP) { + COPY_MAC_ADDR(rQueryStaStatistics.aucMacAddr, + prAisBssInfo + ->prStaRecOfAP->aucMacAddr); + DBGLOG(RSN, INFO, "use ais ap "MACSTR"\n", + MAC2STR(prAisBssInfo + ->prStaRecOfAP->aucMacAddr)); + } else { + DBGLOG(RSN, INFO, "not connect to ais ap %lx\n", + prAisBssInfo + ->prStaRecOfAP); + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, + "%s", "\n\nNo STA Stat:\n"); + return i4BytesWritten; + } + + if (i4Argc == 2) { + if (strnicmp(apcArgv[1], CMD_GET_STA_KEEP_CNT, + strlen(CMD_GET_STA_KEEP_CNT)) == 0) + rQueryStaStatistics.ucReadClear = FALSE; + } + } + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryStaStatistics, + &rQueryStaStatistics, sizeof(rQueryStaStatistics), + TRUE, FALSE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_SUCCESS) { + rRssi = RCPI_TO_dBm(rQueryStaStatistics.ucRcpi); + u2LinkSpeed = rQueryStaStatistics.u2LinkSpeed == 0 ? 0 : + rQueryStaStatistics.u2LinkSpeed / 2; + + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, "%s", + "\n\nSTA Stat:\n"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Tx total cnt = %d\n", + rQueryStaStatistics.u4TransmitCount); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Tx success = %d\n", + rQueryStaStatistics.u4TransmitCount - + rQueryStaStatistics.u4TransmitFailCount); + + u4Per = rQueryStaStatistics.u4TransmitCount == 0 ? 0 : + (1000 * (rQueryStaStatistics.u4TransmitFailCount)) / + rQueryStaStatistics.u4TransmitCount; + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Tx fail count = %d, PER=%d.%d%%\n", + rQueryStaStatistics.u4TransmitFailCount, u4Per / 10, + u4Per % 10); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "RSSI = %d\n", rRssi); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "LinkSpeed = %d\n", u2LinkSpeed); + + } else + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, "%s", + "\n\nNo STA Stat:\n"); + + return i4BytesWritten; + +} + + +static int priv_driver_get_bss_statistics( + IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint8_t arBssid[PARAM_MAC_ADDR_LEN]; + uint32_t u4BufLen; + struct PARAM_LINK_SPEED_EX *prLinkSpeed; + struct PARAM_GET_BSS_STATISTICS rQueryBssStatistics; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + int32_t i4BytesWritten = 0; +#if 0 + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i4Argc = 0; + uint32_t u4Index; +#endif + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + + kalMemZero(arBssid, MAC_ADDR_LEN); + wlanQueryInformation(prGlueInfo->prAdapter, wlanoidQueryBssid, + &arBssid[0], sizeof(arBssid), &u4BufLen); + +#if 0 /* Todo:: Get the none-AIS statistics */ + if (i4Argc >= 2) + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Index); +#endif + ucBssIndex = wlanGetBssIdx(prNetDev); + if (!IS_BSS_INDEX_AIS(prGlueInfo->prAdapter, ucBssIndex)) + return WLAN_STATUS_FAILURE; + + /* 2. fill RSSI */ + if (kalGetMediaStateIndicated(prGlueInfo, + ucBssIndex) != + MEDIA_STATE_CONNECTED) { + /* not connected */ + DBGLOG(REQ, WARN, "not yet connected\n"); + return WLAN_STATUS_SUCCESS; + } + rStatus = kalIoctlByBssIdx(prGlueInfo, + wlanoidQueryRssi, + &prLinkSpeed, sizeof(prLinkSpeed), + TRUE, FALSE, FALSE, + &u4BufLen, ucBssIndex); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "unable to retrieve rssi\n"); + + + /* 3 get per-BSS link statistics */ + if (rStatus == WLAN_STATUS_SUCCESS) { + kalMemZero(&rQueryBssStatistics, + sizeof(rQueryBssStatistics)); + rQueryBssStatistics.ucBssIndex = ucBssIndex; + + rQueryBssStatistics.ucReadClear = TRUE; + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryBssStatistics, + &rQueryBssStatistics, + sizeof(rQueryBssStatistics), + TRUE, FALSE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_SUCCESS) { + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, + "%s", "\n\nStat:\n"); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "CurrentTemperature = -\n"); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Tx success = %d\n", + rQueryBssStatistics.u4TransmitCount - + rQueryBssStatistics.u4TransmitFailCount); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Tx fail count = %d\n", + rQueryBssStatistics.u4TransmitFailCount); +#if 0 + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Rx success = %ld\n", 0); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Rx with CRC = %ld\n", + prStatistics->rFCSErrorCount.QuadPart); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "Rx with PhyErr = 0\n"); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + "%s", "Rx with PlcpErr = 0\n"); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "Rx drop due to out of resource = 0\n"); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Rx duplicate frame = %ld\n", + prStatistics->rFrameDuplicateCount.QuadPart); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "False CCA = 0\n"); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "RSSI = %d\n", i4Rssi); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Last TX Rate = %s, %s, %s, %s, %s\n", + "NA", "NA", "NA", "NA", "NA"); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Last RX Rate = %s, %s, %s, %s, %s\n", + "NA", "NA", "NA", "NA", "NA"); +#endif + + } + + } else { + DBGLOG(REQ, WARN, + "unable to retrieve per-BSS link statistics\n"); + } + + + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, + pcCommand); + + return i4BytesWritten; + +} + +static u_int8_t priv_driver_get_sgi_info( + IN struct PARAM_PEER_CAP *prWtblPeerCap) +{ + if (!prWtblPeerCap) + return FALSE; + + switch (prWtblPeerCap->ucFrequencyCapability) { + case BW_20: + return prWtblPeerCap->fgG2; + case BW_40: + return prWtblPeerCap->fgG4; + case BW_80: + return prWtblPeerCap->fgG8; + case BW_160: + return prWtblPeerCap->fgG16; + default: + return FALSE; + } +} + +static u_int8_t priv_driver_get_ldpc_info( + IN struct PARAM_TX_CONFIG *prWtblTxConfig) +{ + if (!prWtblTxConfig) + return FALSE; + + if (prWtblTxConfig->fgIsVHT) + return prWtblTxConfig->fgVhtLDPC; + else + return prWtblTxConfig->fgLDPC; +} + +int32_t priv_driver_rate_to_string(IN char *pcCommand, + IN int i4TotalLen, uint8_t TxRx, + struct PARAM_HW_WLAN_INFO *prHwWlanInfo) +{ + uint8_t i, txmode, rate, stbc; + uint8_t nss; + int32_t i4BytesWritten = 0; + + for (i = 0; i < AUTO_RATE_NUM; i++) { + + txmode = HW_TX_RATE_TO_MODE( + prHwWlanInfo->rWtblRateInfo.au2RateCode[i]); + if (txmode >= ENUM_TX_MODE_NUM) + txmode = ENUM_TX_MODE_NUM - 1; + rate = HW_TX_RATE_TO_MCS( + prHwWlanInfo->rWtblRateInfo.au2RateCode[i]); + nss = HW_TX_RATE_TO_NSS( + prHwWlanInfo->rWtblRateInfo.au2RateCode[i]) + 1; + stbc = HW_TX_RATE_TO_STBC( + prHwWlanInfo->rWtblRateInfo.au2RateCode[i]); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRate index[%d] ", i); + + if (prHwWlanInfo->rWtblRateInfo.ucRateIdx == i) { + if (TxRx == 0) + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "[Last RX Rate] "); + else + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "[Last TX Rate] "); + } else + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", " "); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + rate < 4 ? HW_TX_RATE_CCK_STR[rate] : + HW_TX_RATE_CCK_STR[4]); + else if (txmode == TX_RATE_MODE_OFDM) + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + nicHwRateOfdmStr(rate)); + else { + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "NSS%d_MCS%d, ", nss, rate); + } + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", HW_TX_RATE_BW[ + prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability]); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + rate < 4 ? "LP" : "SP"); + else if (txmode == TX_RATE_MODE_OFDM) + ; + else + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + priv_driver_get_sgi_info( + &prHwWlanInfo->rWtblPeerCap) == 0 ? + "LGI" : "SGI"); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s%s %s\n", + HW_TX_MODE_STR[txmode], stbc ? "STBC" : " ", + priv_driver_get_ldpc_info(&prHwWlanInfo->rWtblTxConfig) + == 0 ? "BCC" : "LDPC"); + } + + return i4BytesWritten; +} + +static int32_t priv_driver_dump_helper_wtbl_info(IN char *pcCommand, + IN int i4TotalLen, struct PARAM_HW_WLAN_INFO *prHwWlanInfo) +{ + uint8_t i; + int32_t i4BytesWritten = 0; + + if (!pcCommand) { + DBGLOG(HAL, ERROR, "%s: pcCommand is NULL.\n", + __func__); + return i4BytesWritten; + } + + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, "%s", + "\n\nwtbl:\n"); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Dump WTBL info of WLAN_IDX = %d\n", + prHwWlanInfo->u4Index); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tAddr="MACSTR"\n", + MAC2STR(prHwWlanInfo->rWtblTxConfig.aucPA)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tMUAR_Idx = %d\n", + prHwWlanInfo->rWtblSecConfig.ucMUARIdx); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\trc_a1/rc_a2:%d/%d\n", + prHwWlanInfo->rWtblSecConfig.fgRCA1, + prHwWlanInfo->rWtblSecConfig.fgRCA2); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tKID:%d/RCID:%d/RKV:%d/RV:%d/IKV:%d/WPI_FLAG:%d\n", + prHwWlanInfo->rWtblSecConfig.ucKeyID, + prHwWlanInfo->rWtblSecConfig.fgRCID, + prHwWlanInfo->rWtblSecConfig.fgRKV, + prHwWlanInfo->rWtblSecConfig.fgRV, + prHwWlanInfo->rWtblSecConfig.fgIKV, + prHwWlanInfo->rWtblSecConfig.fgEvenPN); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s", "\tGID_SU:NA"); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tsw/DIS_RHTR:%d/%d\n", + prHwWlanInfo->rWtblTxConfig.fgSW, + prHwWlanInfo->rWtblTxConfig.fgDisRxHdrTran); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tHT/VHT/HT-LDPC/VHT-LDPC/DYN_BW/MMSS:%d/%d/%d/%d/%d/%d\n", + prHwWlanInfo->rWtblTxConfig.fgIsHT, + prHwWlanInfo->rWtblTxConfig.fgIsVHT, + prHwWlanInfo->rWtblTxConfig.fgLDPC, + prHwWlanInfo->rWtblTxConfig.fgVhtLDPC, + prHwWlanInfo->rWtblTxConfig.fgDynBw, + prHwWlanInfo->rWtblPeerCap.ucMMSS); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tFCAP/G2/G4/G8/G16/CBRN:%d/%d/%d/%d/%d/%d\n", + prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability, + prHwWlanInfo->rWtblPeerCap.fgG2, + prHwWlanInfo->rWtblPeerCap.fgG4, + prHwWlanInfo->rWtblPeerCap.fgG8, + prHwWlanInfo->rWtblPeerCap.fgG16, + prHwWlanInfo->rWtblPeerCap.ucChangeBWAfterRateN); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tHT-TxBF(tibf/tebf):%d/%d, VHT-TxBF(tibf/tebf):%d/%d, PFMU_IDX=%d\n", + prHwWlanInfo->rWtblTxConfig.fgTIBF, + prHwWlanInfo->rWtblTxConfig.fgTEBF, + prHwWlanInfo->rWtblTxConfig.fgVhtTIBF, + prHwWlanInfo->rWtblTxConfig.fgVhtTEBF, + prHwWlanInfo->rWtblTxConfig.ucPFMUIdx); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s", "\tSPE_IDX=NA\n"); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tBA Enable:0x%x, BAFail Enable:%d\n", + prHwWlanInfo->rWtblBaConfig.ucBaEn, + prHwWlanInfo->rWtblTxConfig.fgBAFEn); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tQoS Enable:%d\n", prHwWlanInfo->rWtblTxConfig.fgIsQoS); + if (prHwWlanInfo->rWtblTxConfig.fgIsQoS) { + for (i = 0; i < 8; i += 2) { + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\t\tBA WinSize: TID 0 - %d, TID 1 - %d\n", + (uint32_t) + ((prHwWlanInfo->rWtblBaConfig.u4BaWinSize >> + (i * 3)) & BITS(0, 2)), + (uint32_t) + ((prHwWlanInfo->rWtblBaConfig.u4BaWinSize >> + ((i + 1) * 3)) & BITS(0, 2))); + } + } + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tpartial_aid:%d\n", + prHwWlanInfo->rWtblTxConfig.u2PartialAID); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\twpi_even:%d\n", + prHwWlanInfo->rWtblSecConfig.fgEvenPN); + i4BytesWritten += scnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tAAD_OM/CipherSuit:%d/%d\n", + prHwWlanInfo->rWtblTxConfig.fgAADOM, + prHwWlanInfo->rWtblSecConfig.ucCipherSuit); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\taf:%d\n", + prHwWlanInfo->rWtblPeerCap.ucAmpduFactor); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\trdg_ba:%d/rdg capability:%d\n", + prHwWlanInfo->rWtblTxConfig.fgRdgBA, + prHwWlanInfo->rWtblTxConfig.fgRDG); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tcipher_suit:%d\n", + prHwWlanInfo->rWtblSecConfig.ucCipherSuit); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tFromDS:%d\n", + prHwWlanInfo->rWtblTxConfig.fgIsFromDS); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tToDS:%d\n", + prHwWlanInfo->rWtblTxConfig.fgIsToDS); +#if 0 + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRCPI = %d %d %d %d\n", + prHwWlanInfo->rWtblRxCounter.ucRxRcpi0, + prHwWlanInfo->rWtblRxCounter.ucRxRcpi1, + prHwWlanInfo->rWtblRxCounter.ucRxRcpi2, + prHwWlanInfo->rWtblRxCounter.ucRxRcpi3); +#endif + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRSSI = %d %d %d %d\n", + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi0), + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi1), + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi2), + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi3)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s", "\tRate Info\n"); + + i4BytesWritten += priv_driver_rate_to_string(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, 1, prHwWlanInfo); + +#if 0 + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, i4TotalLen - + i4BytesWritten, + "%s", "\t===Key======\n"); + for (i = 0; i < 32; i += 8) { + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\t0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", + prHwWlanInfo->rWtblKeyConfig.aucKey[i + 0], + prHwWlanInfo->rWtblKeyConfig.aucKey[i + 1], + prHwWlanInfo->rWtblKeyConfig.aucKey[i + 2], + prHwWlanInfo->rWtblKeyConfig.aucKey[i + 3], + prHwWlanInfo->rWtblKeyConfig.aucKey[i + 4], + prHwWlanInfo->rWtblKeyConfig.aucKey[i + 5], + prHwWlanInfo->rWtblKeyConfig.aucKey[i + 6], + prHwWlanInfo->rWtblKeyConfig.aucKey[i + 7]); + } +#endif + + return i4BytesWritten; +} + +static int priv_driver_get_wtbl_info_default( + IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Index, + IN char *pcCommand, + IN int i4TotalLen) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + struct PARAM_HW_WLAN_INFO *prHwWlanInfo; + + prHwWlanInfo = (struct PARAM_HW_WLAN_INFO *)kalMemAlloc( + sizeof(struct PARAM_HW_WLAN_INFO), VIR_MEM_TYPE); + if (!prHwWlanInfo) + return i4BytesWritten; + + prHwWlanInfo->u4Index = u4Index; + DBGLOG(REQ, INFO, "%s : index = %d\n", + __func__, + prHwWlanInfo->u4Index); + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryWlanInfo, + prHwWlanInfo, + sizeof(struct PARAM_HW_WLAN_INFO), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, INFO, "rStatus %u u4BufLen = %d\n", rStatus, u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + kalMemFree(prHwWlanInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_HW_WLAN_INFO)); + return i4BytesWritten; + } + i4BytesWritten = priv_driver_dump_helper_wtbl_info( + pcCommand, + i4TotalLen, + prHwWlanInfo); + + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + + kalMemFree(prHwWlanInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_HW_WLAN_INFO)); + + return i4BytesWritten; +} + +static int priv_driver_get_wtbl_info(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Argc = 0; + int32_t u4Ret = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Index = 0; + struct CHIP_DBG_OPS *prDbgOps; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= 2) + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Index); + + if (u4Ret) + return -1; + + prDbgOps = prGlueInfo->prAdapter->chip_info->prDebugOps; + + if (prDbgOps->showWtblInfo) + return prDbgOps->showWtblInfo( + prGlueInfo->prAdapter, u4Index, pcCommand, i4TotalLen); + else + return priv_driver_get_wtbl_info_default( + prGlueInfo, u4Index, pcCommand, i4TotalLen); +} + +static int priv_driver_get_sta_info(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint8_t aucMacAddr[MAC_ADDR_LEN]; + uint8_t ucWlanIndex = 0; + uint8_t *pucMacAddr = NULL; + struct PARAM_HW_WLAN_INFO *prHwWlanInfo; + struct PARAM_GET_STA_STATISTICS rQueryStaStatistics; + int32_t rRssi; + uint16_t u2LinkSpeed; + uint32_t u4Per; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + kalMemZero(&rQueryStaStatistics, sizeof(rQueryStaStatistics)); + rQueryStaStatistics.ucReadClear = TRUE; + + /* DBGLOG(RSN, INFO, "MT6632 : priv_driver_get_sta_info\n"); */ + if (i4Argc >= 3) { + if (strnicmp(apcArgv[1], CMD_GET_STA_KEEP_CNT, + strlen(CMD_GET_STA_KEEP_CNT)) == 0) { + wlanHwAddrToBin(apcArgv[2], &aucMacAddr[0]); + rQueryStaStatistics.ucReadClear = FALSE; + } else if (strnicmp(apcArgv[2], CMD_GET_STA_KEEP_CNT, + strlen(CMD_GET_STA_KEEP_CNT)) == 0) { + wlanHwAddrToBin(apcArgv[1], &aucMacAddr[0]); + rQueryStaStatistics.ucReadClear = FALSE; + } + + if (!wlanGetWlanIdxByAddress(prGlueInfo->prAdapter, + &aucMacAddr[0], &ucWlanIndex)) + return i4BytesWritten; + } else { + struct BSS_INFO *prAisBssInfo = aisGetAisBssInfo( + prGlueInfo->prAdapter, wlanGetBssIdx(prNetDev)); + + /* Get AIS AP address for no argument */ + if (prAisBssInfo->prStaRecOfAP) + ucWlanIndex = prAisBssInfo + ->prStaRecOfAP->ucWlanIndex; + else if (!wlanGetWlanIdxByAddress(prGlueInfo->prAdapter, NULL, + &ucWlanIndex)) /* try get a peer */ + return i4BytesWritten; + + if (i4Argc == 2) { + if (strnicmp(apcArgv[1], CMD_GET_STA_KEEP_CNT, + strlen(CMD_GET_STA_KEEP_CNT)) == 0) + rQueryStaStatistics.ucReadClear = FALSE; + } + } + + prHwWlanInfo = (struct PARAM_HW_WLAN_INFO *)kalMemAlloc( + sizeof(struct PARAM_HW_WLAN_INFO), VIR_MEM_TYPE); + if (prHwWlanInfo == NULL) { + DBGLOG(REQ, INFO, "prHwWlanInfo is null\n"); + return -1; + } + + prHwWlanInfo->u4Index = ucWlanIndex; + + DBGLOG(REQ, INFO, "MT6632 : index = %d i4TotalLen = %d\n", + prHwWlanInfo->u4Index, i4TotalLen); + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryWlanInfo, prHwWlanInfo, + sizeof(struct PARAM_HW_WLAN_INFO), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + kalMemFree(prHwWlanInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_HW_WLAN_INFO)); + return -1; + } + + i4BytesWritten = priv_driver_dump_helper_wtbl_info(pcCommand, + i4TotalLen, prHwWlanInfo); + + pucMacAddr = wlanGetStaAddrByWlanIdx(prGlueInfo->prAdapter, + ucWlanIndex); + if (pucMacAddr) { + COPY_MAC_ADDR(rQueryStaStatistics.aucMacAddr, pucMacAddr); + /* i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + * i4TotalLen - i4BytesWritten, + * "\tAddr="MACSTR"\n", + * MAC2STR(rQueryStaStatistics.aucMacAddr)); + */ + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryStaStatistics, + &rQueryStaStatistics, + sizeof(rQueryStaStatistics), + TRUE, FALSE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_SUCCESS) { + rRssi = RCPI_TO_dBm(rQueryStaStatistics.ucRcpi); + u2LinkSpeed = rQueryStaStatistics.u2LinkSpeed == 0 ? + 0 : rQueryStaStatistics.u2LinkSpeed/2; + + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "\n\nSTA Stat:\n"); + + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Tx total cnt = %d\n", + rQueryStaStatistics.u4TransmitCount); + + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Tx success = %d\n", + rQueryStaStatistics.u4TransmitCount - + rQueryStaStatistics.u4TransmitFailCount); + + u4Per = rQueryStaStatistics.u4TransmitCount == 0 ? 0 : + (1000 * + (rQueryStaStatistics.u4TransmitFailCount)) / + rQueryStaStatistics.u4TransmitCount; + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Tx fail count = %d, PER=%d.%1d%%\n", + rQueryStaStatistics.u4TransmitFailCount, + u4Per/10, u4Per%10); + + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "RSSI = %d\n", rRssi); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "LinkSpeed = %d\n", u2LinkSpeed); + } + } + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + + kalMemFree(prHwWlanInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_HW_WLAN_INFO)); + + return i4BytesWritten; +} + +static int priv_driver_get_mib_info(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + uint8_t i; + uint32_t u4Per; + int32_t u4Ret = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + struct PARAM_HW_MIB_INFO *prHwMibInfo; + struct RX_CTRL *prRxCtrl; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + prRxCtrl = &prGlueInfo->prAdapter->rRxCtrl; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + DBGLOG(REQ, INFO, "MT6632 : priv_driver_get_mib_info\n"); + + prHwMibInfo = (struct PARAM_HW_MIB_INFO *)kalMemAlloc( + sizeof(struct PARAM_HW_MIB_INFO), VIR_MEM_TYPE); + if (!prHwMibInfo) + return -1; + + if (i4Argc == 1) + prHwMibInfo->u4Index = 0; + + if (i4Argc >= 2) + u4Ret = kalkStrtou32(apcArgv[1], 0, &prHwMibInfo->u4Index); + + DBGLOG(REQ, INFO, "MT6632 : index = %d\n", prHwMibInfo->u4Index); + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryMibInfo, prHwMibInfo, + sizeof(struct PARAM_HW_MIB_INFO), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) { + kalMemFree(prHwMibInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_HW_MIB_INFO)); + return -1; + } + + if (prHwMibInfo->u4Index < 2) { + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, "%s", + "\n\nmib state:\n"); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Dump MIB info of IDX = %d\n", + prHwMibInfo->u4Index); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "===Rx Related Counters===\n"); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tRx with CRC=%d\n", + prHwMibInfo->rHwMibCnt.u4RxFcsErrCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx drop due to out of resource=%d\n", + prHwMibInfo->rHwMibCnt.u4RxFifoFullCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tRx Mpdu=%d\n", + prHwMibInfo->rHwMibCnt.u4RxMpduCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tRx AMpdu=%d\n", + prHwMibInfo->rHwMibCnt.u4RxAMPDUCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tRx PF Drop=%d\n", + prHwMibInfo->rHwMibCnt.u4PFDropCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx Len Mismatch=%d\n", + prHwMibInfo->rHwMibCnt.u4RxLenMismatchCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx data indicate total=%llu\n", + RX_GET_CNT(prRxCtrl, RX_DATA_INDICATION_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx data retain total=%llu\n", + RX_GET_CNT(prRxCtrl, RX_DATA_RETAINED_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx drop by SW total=%llu\n", + RX_GET_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tRx reorder miss=%llu\n", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_MISS_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx reorder within=%llu\n", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_WITHIN_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx reorder ahead=%llu\n", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_AHEAD_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx reorder behind=%llu\n", RX_GET_CNT(prRxCtrl, + RX_DATA_REORDER_BEHIND_COUNT)); + + do { + uint32_t u4AmsduCntx100 = 0; + + if (RX_GET_CNT(prRxCtrl, RX_DATA_AMSDU_COUNT)) + u4AmsduCntx100 = + (uint32_t)div64_u64(RX_GET_CNT(prRxCtrl, + RX_DATA_MSDU_IN_AMSDU_COUNT) * 100, + RX_GET_CNT(prRxCtrl, + RX_DATA_AMSDU_COUNT)); + + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx avg MSDU in AMSDU=%1d.%02d\n", + u4AmsduCntx100 / 100, u4AmsduCntx100 % 100); + } while (FALSE); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx total MSDU in AMSDU=%llu\n", RX_GET_CNT(prRxCtrl, + RX_DATA_MSDU_IN_AMSDU_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx AMSDU=%llu\n", RX_GET_CNT(prRxCtrl, + RX_DATA_AMSDU_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tRx AMSDU miss=%llu\n", + RX_GET_CNT(prRxCtrl, RX_DATA_AMSDU_MISS_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx no StaRec drop=%llu\n", + RX_GET_CNT(prRxCtrl, RX_NO_STA_DROP_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx inactive BSS drop=%llu\n", + RX_GET_CNT(prRxCtrl, RX_INACTIVE_BSS_DROP_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx HS20 drop=%llu\n", + RX_GET_CNT(prRxCtrl, RX_HS20_DROP_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx low SwRfb drop=%llu\n", RX_GET_CNT(prRxCtrl, + RX_LESS_SW_RFB_DROP_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx dupicate drop=%llu\n", + RX_GET_CNT(prRxCtrl, RX_DUPICATE_DROP_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tRx MIC err drop=%llu\n", + RX_GET_CNT(prRxCtrl, RX_MIC_ERROR_DROP_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tRx BAR handle=%llu\n", + RX_GET_CNT(prRxCtrl, RX_BAR_DROP_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx non-interest drop=%llu\n", RX_GET_CNT(prRxCtrl, + RX_NO_INTEREST_DROP_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx type err drop=%llu\n", + RX_GET_CNT(prRxCtrl, RX_TYPE_ERR_DROP_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx class err drop=%llu\n", RX_GET_CNT(prRxCtrl, + RX_CLASS_ERR_DROP_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "===Phy/Timing Related Counters===\n"); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tChannelIdleCnt=%d\n", + prHwMibInfo->rHwMibCnt.u4ChannelIdleCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tCCA_NAV_Tx_Time=%d\n", + prHwMibInfo->rHwMibCnt.u4CcaNavTx); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tRx_MDRDY_CNT=%d\n", + prHwMibInfo->rHwMibCnt.u4MdrdyCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tCCK_MDRDY=%d, OFDM_MDRDY=0x%x, OFDM_GREEN_MDRDY=0x%x\n", + prHwMibInfo->rHwMibCnt.u4CCKMdrdyCnt, + prHwMibInfo->rHwMibCnt.u4OFDMLGMixMdrdy, + prHwMibInfo->rHwMibCnt.u4OFDMGreenMdrdy); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tPrim CCA Time=%d\n", + prHwMibInfo->rHwMibCnt.u4PCcaTime); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tSec CCA Time=%d\n", + prHwMibInfo->rHwMibCnt.u4SCcaTime); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tPrim ED Time=%d\n", + prHwMibInfo->rHwMibCnt.u4PEDTime); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s", + "===Tx Related Counters(Generic)===\n"); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tBeaconTxCnt=%d\n", + prHwMibInfo->rHwMibCnt.u4BeaconTxCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tTx 40MHz Cnt=%d\n", + prHwMibInfo->rHwMib2Cnt.u4Tx40MHzCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tTx 80MHz Cnt=%d\n", + prHwMibInfo->rHwMib2Cnt.u4Tx80MHzCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tTx 160MHz Cnt=%d\n", + prHwMibInfo->rHwMib2Cnt.u4Tx160MHzCnt); + for (i = 0; i < BSSID_NUM; i++) { + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\t===BSSID[%d] Related Counters===\n", i); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tBA Miss Cnt=%d\n", + prHwMibInfo->rHwMibCnt.au4BaMissedCnt[i]); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRTS Tx Cnt=%d\n", + prHwMibInfo->rHwMibCnt.au4RtsTxCnt[i]); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tFrame Retry Cnt=%d\n", + prHwMibInfo->rHwMibCnt.au4FrameRetryCnt[i]); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tFrame Retry 2 Cnt=%d\n", + prHwMibInfo->rHwMibCnt.au4FrameRetry2Cnt[i]); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRTS Retry Cnt=%d\n", + prHwMibInfo->rHwMibCnt.au4RtsRetryCnt[i]); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tAck Failed Cnt=%d\n", + prHwMibInfo->rHwMibCnt.au4AckFailedCnt[i]); + } + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "===AMPDU Related Counters===\n"); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tTx AMPDU_Pkt_Cnt=%d\n", + prHwMibInfo->rHwTxAmpduMts.u2TxAmpduCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tTx AMPDU_MPDU_Pkt_Cnt=%d\n", + prHwMibInfo->rHwTxAmpduMts.u4TxSfCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tAMPDU SuccessCnt=%d\n", + prHwMibInfo->rHwTxAmpduMts.u4TxAckSfCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tAMPDU Tx success = %d\n", + prHwMibInfo->rHwTxAmpduMts.u4TxAckSfCnt); + + u4Per = prHwMibInfo->rHwTxAmpduMts.u4TxSfCnt == 0 ? 0 : + (1000 * (prHwMibInfo->rHwTxAmpduMts.u4TxSfCnt - + prHwMibInfo->rHwTxAmpduMts.u4TxAckSfCnt)) / + prHwMibInfo->rHwTxAmpduMts.u4TxSfCnt; + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tAMPDU Tx fail count = %d, PER=%d.%1d%%\n", + prHwMibInfo->rHwTxAmpduMts.u4TxSfCnt - + prHwMibInfo->rHwTxAmpduMts.u4TxAckSfCnt, + u4Per/10, u4Per%10); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s", "\tTx Agg\n"); +#if (CFG_SUPPORT_802_11AX == 1) + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "\tRange: 1 2~9 10~18 19~27 "); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "28~36 37~45 46~54 55~78\n"); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\t\t%d \t%d \t%d \t%d \t%d \t%d \t%d \t%d\n", + prHwMibInfo->rHwTxAmpduMts.u2TxRange1AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange2AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange3AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange4AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange5AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange6AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange7AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange8AmpduCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "\tRange: 79~102 103~126 127~150 151~174 "); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "174~198 199~222 223~246 247~255\n"); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\t\t%d \t%d \t%d \t%d \t%d \t%d \t%d \t%d\n", + prHwMibInfo->rHwTxAmpduMts.u2TxRange9AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange10AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange11AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange12AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange13AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange14AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange15AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange16AmpduCnt); +#else + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s", + "\tRange: 1 2~5 6~15 16~22 23~33 34~49 50~57 58~64\n" + ); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\t\t%d \t%d \t%d \t%d \t%d \t%d \t%d \t%d\n", + prHwMibInfo->rHwTxAmpduMts.u2TxRange1AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange2AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange3AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange4AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange5AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange6AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange7AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange8AmpduCnt); +#endif + } else + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, "%s", + "\nClear All Statistics\n"); + + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + + kalMemFree(prHwMibInfo, VIR_MEM_TYPE, sizeof(struct PARAM_HW_MIB_INFO)); + + nicRxClearStatistics(prGlueInfo->prAdapter); + + return i4BytesWritten; +} + +static int priv_driver_set_fw_log(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4McuDest = 0; + uint32_t u4LogType = 0; + struct CMD_FW_LOG_2_HOST_CTRL *prFwLog2HostCtrl; + uint32_t u4Ret = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RSN, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + DBGLOG(RSN, INFO, "MT6632 : priv_driver_set_fw_log\n"); + + prFwLog2HostCtrl = (struct CMD_FW_LOG_2_HOST_CTRL *)kalMemAlloc( + sizeof(struct CMD_FW_LOG_2_HOST_CTRL), VIR_MEM_TYPE); + if (!prFwLog2HostCtrl) + return -1; + + if (i4Argc == 3) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4McuDest); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse u4McuDest error u4Ret=%d\n", + u4Ret); + + u4Ret = kalkStrtou32(apcArgv[2], 0, &u4LogType); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse u4LogType error u4Ret=%d\n", + u4Ret); + + prFwLog2HostCtrl->ucMcuDest = (uint8_t)u4McuDest; + prFwLog2HostCtrl->ucFwLog2HostCtrl = (uint8_t)u4LogType; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetFwLog2Host, + prFwLog2HostCtrl, + sizeof(struct CMD_FW_LOG_2_HOST_CTRL), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, INFO, "%s: command result is %s (%d %d)\n", + __func__, pcCommand, u4McuDest, u4LogType); + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + + if (rStatus != WLAN_STATUS_SUCCESS) { + kalMemFree(prFwLog2HostCtrl, VIR_MEM_TYPE, + sizeof(struct CMD_FW_LOG_2_HOST_CTRL)); + return -1; + } + } else { + DBGLOG(REQ, ERROR, "argc %i is not equal to 3\n", i4Argc); + i4BytesWritten = -1; + } + + kalMemFree(prFwLog2HostCtrl, VIR_MEM_TYPE, + sizeof(struct CMD_FW_LOG_2_HOST_CTRL)); + return i4BytesWritten; +} +#endif + +static int priv_driver_get_mcr(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret; + int32_t i4ArgNum = 2; + struct CMD_ACCESS_REG rCmdAccessReg; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + rCmdAccessReg.u4Address = 0; + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rCmdAccessReg.u4Address)); + if (u4Ret) + DBGLOG(REQ, LOUD, + "parse get_mcr error (Address) u4Ret=%d\n", + u4Ret); + + /* rCmdAccessReg.u4Address = kalStrtoul(apcArgv[1], NULL, 0); */ + rCmdAccessReg.u4Data = 0; + + DBGLOG(REQ, LOUD, "address is %x\n", rCmdAccessReg.u4Address); + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryMcrRead, + &rCmdAccessReg, sizeof(rCmdAccessReg), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, "0x%08x", + (unsigned int)rCmdAccessReg.u4Data); + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, + pcCommand); + } + + return i4BytesWritten; + +} /* priv_driver_get_mcr */ + +int priv_driver_set_mcr(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Ret; + int32_t i4ArgNum = 3; + struct CMD_ACCESS_REG rCmdAccessReg; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rCmdAccessReg.u4Address)); + if (u4Ret) + DBGLOG(REQ, LOUD, + "parse get_mcr error (Address) u4Ret=%d\n", + u4Ret); + + u4Ret = kalkStrtou32(apcArgv[2], 0, &(rCmdAccessReg.u4Data)); + if (u4Ret) + DBGLOG(REQ, LOUD, + "parse get_mcr error (Data) u4Ret=%d\n", u4Ret); + + /* rCmdAccessReg.u4Address = kalStrtoul(apcArgv[1], NULL, 0); */ + /* rCmdAccessReg.u4Data = kalStrtoul(apcArgv[2], NULL, 0); */ + + rStatus = kalIoctl(prGlueInfo, wlanoidSetMcrWrite, + &rCmdAccessReg, sizeof(rCmdAccessReg), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + } + + return i4BytesWritten; + +} + +static int priv_driver_set_test_mode(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret; + int32_t i4ArgNum = 2, u4MagicKey = -1; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &(u4MagicKey)); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse Magic Key error u4Ret=%d\n", + u4Ret); + + DBGLOG(REQ, LOUD, "The Set Test Mode Magic Key is %d\n", + u4MagicKey); + + if (u4MagicKey == PRIV_CMD_TEST_MAGIC_KEY) { + rStatus = kalIoctl(prGlueInfo, + wlanoidRftestSetTestMode, + NULL, 0, FALSE, FALSE, TRUE, + &u4BufLen); + } else if (u4MagicKey == 0) { + rStatus = kalIoctl(prGlueInfo, + wlanoidRftestSetAbortTestMode, + NULL, 0, FALSE, FALSE, TRUE, + &u4BufLen); + } + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } + + return i4BytesWritten; + +} /* priv_driver_set_test_mode */ + +static int priv_driver_set_test_cmd(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret; + int32_t i4ArgNum = 3; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + rRfATInfo.u4FuncIndex = 0; + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rRfATInfo.u4FuncIndex)); + if (u4Ret) + DBGLOG(REQ, LOUD, + "Parse Test CMD Index error u4Ret=%d\n", u4Ret); + + rRfATInfo.u4FuncData = 0; + u4Ret = kalkStrtou32(apcArgv[2], 0, &(rRfATInfo.u4FuncData)); + if (u4Ret) + DBGLOG(REQ, LOUD, + "Parse Test CMD Data error u4Ret=%d\n", u4Ret); + + DBGLOG(REQ, LOUD, + "Set Test CMD FuncIndex = %d, FuncData = %d\n", + rRfATInfo.u4FuncIndex, rRfATInfo.u4FuncData); + + rStatus = kalIoctl(prGlueInfo, wlanoidRftestSetAutoTest, + &rRfATInfo, sizeof(rRfATInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } + + return i4BytesWritten; + +} /* priv_driver_set_test_cmd */ + +static int priv_driver_get_test_result(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret; + uint32_t u4Data = 0; + int32_t i4ArgNum = 3; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + rRfATInfo.u4FuncIndex = 0; + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rRfATInfo.u4FuncIndex)); + if (u4Ret) + DBGLOG(REQ, LOUD, + "Parse Test CMD Index error u4Ret=%d\n", u4Ret); + + rRfATInfo.u4FuncData = 0; + u4Ret = kalkStrtou32(apcArgv[2], 0, &(rRfATInfo.u4FuncData)); + if (u4Ret) + DBGLOG(REQ, LOUD, + "Parse Test CMD Data error u4Ret=%d\n", u4Ret); + + DBGLOG(REQ, LOUD, + "Get Test CMD FuncIndex = %d, FuncData = %d\n", + rRfATInfo.u4FuncIndex, rRfATInfo.u4FuncData); + + rStatus = kalIoctl(prGlueInfo, wlanoidRftestQueryAutoTest, + &rRfATInfo, sizeof(rRfATInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + u4Data = (unsigned int)rRfATInfo.u4FuncData; + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, + "%d[0x%08x]", u4Data, u4Data); + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, + pcCommand); + } + + return i4BytesWritten; + +} /* priv_driver_get_test_result */ + +#if (CFG_SUPPORT_RA_GEN == 1) + +static int32_t priv_driver_set_ra_debug_proc(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + int8_t *this_char = NULL; + int32_t i4Recv = 0; + uint32_t u4WCID = 0, u4DebugType = 0; + uint32_t u4Id = 0xa0650000; + struct PARAM_CUSTOM_SW_CTRL_STRUCT *prSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %d, apcArgv[0] = %s\n\n", i4Argc, *apcArgv); + + this_char = kalStrStr(*apcArgv, "="); + if (!this_char) + return -1; + this_char++; + + DBGLOG(REQ, LOUD, "string = %s\n", this_char); + + i4Recv = sscanf(this_char, "%d:%d", &(u4WCID), &(u4DebugType)); + if (i4Recv < 0) + return -1; + + prSwCtrlInfo = + (struct PARAM_CUSTOM_SW_CTRL_STRUCT *)kalMemAlloc( + sizeof(struct PARAM_CUSTOM_SW_CTRL_STRUCT), + VIR_MEM_TYPE); + if (!prSwCtrlInfo) + return -1; + + if (i4Recv == 2) { + prSwCtrlInfo->u4Id = u4Id; + prSwCtrlInfo->u4Data = u4WCID | + ((u4DebugType & BITS(0, 15)) << 16); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, + prSwCtrlInfo, + sizeof(struct PARAM_CUSTOM_SW_CTRL_STRUCT), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + kalMemFree(prSwCtrlInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_CUSTOM_SW_CTRL_STRUCT)); + return -1; + } + + DBGLOG(REQ, LOUD, "WlanIdx=%d\nDebugType=%d\nu4Data=0x%08x\n", + u4WCID, u4DebugType, prSwCtrlInfo->u4Data); + } else { + DBGLOG(INIT, ERROR, + "iwpriv wlanXX driver RaDebug=[wlanIdx]:[debugType]\n"); + } + + kalMemFree(prSwCtrlInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_CUSTOM_SW_CTRL_STRUCT)); + + return i4BytesWritten; +} + +int priv_driver_set_fixed_fallback(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + /* INT_32 u4Ret = 0; */ + uint32_t u4WCID = 0; + uint32_t u4Mode = 0, u4Bw = 0, u4Mcs = 0, u4VhtNss = 0, u4Band = 0; + uint32_t u4SGI = 0, u4Preamble = 0, u4STBC = 0, u4LDPC = 0, u4SpeEn = 0; + int32_t i4Recv = 0; + int8_t *this_char = NULL; + uint32_t u4Id = 0xa0660000; + uint32_t u4Data = 0x80000000; + uint32_t u4Id2 = 0xa0600000; + uint8_t u4Nsts = 1; + u_int8_t fgStatus = TRUE; + static uint8_t fgIsUseWCID = FALSE; + + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %d, apcArgv[0] = %s\n\n", i4Argc, *apcArgv); + + this_char = kalStrStr(*apcArgv, "="); + if (!this_char) + return -1; + this_char++; + + DBGLOG(REQ, LOUD, "string = %s\n", this_char); + + if (strnicmp(this_char, "auto", strlen("auto")) == 0) { + i4Recv = 1; + } else if (strnicmp(this_char, "UseWCID", strlen("UseWCID")) == 0) { + i4Recv = 2; + fgIsUseWCID = TRUE; + } else if (strnicmp(this_char, "ApplyAll", strlen("ApplyAll")) == 0) { + i4Recv = 3; + fgIsUseWCID = FALSE; + } else { + i4Recv = sscanf(this_char, "%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d", + &(u4WCID), &(u4Mode), &(u4Bw), &(u4Mcs), + &(u4VhtNss), &(u4SGI), &(u4Preamble), &(u4STBC), + &(u4LDPC), &(u4SpeEn), &(u4Band)); + + DBGLOG(REQ, LOUD, "u4WCID=%d\nu4Mode=%d\nu4Bw=%d\n", + u4WCID, u4Mode, u4Bw); + DBGLOG(REQ, LOUD, "u4Mcs=%d\nu4VhtNss=%d\nu4SGI=%d\n", + u4Mcs, u4VhtNss, u4SGI); + DBGLOG(REQ, LOUD, "u4Preamble=%d\nu4STBC=%d\n", + u4Preamble, u4STBC); + DBGLOG(REQ, LOUD, "u4LDPC=%d\nu4SpeEn=%d\nu4Band=%d\n", + u4LDPC, u4SpeEn, u4Band); + DBGLOG(REQ, LOUD, "fgIsUseWCID=%d\n\n", + fgIsUseWCID); + } + + if (i4Recv == 1) { + rSwCtrlInfo.u4Id = u4Id2; + rSwCtrlInfo.u4Data = 0; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } else if (i4Recv == 2 || i4Recv == 3) { + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, + "Update fgIsUseWCID %d\n", fgIsUseWCID); + } else if (i4Recv == 11) { + rSwCtrlInfo.u4Id = u4Id; + rSwCtrlInfo.u4Data = u4Data; + if (fgIsUseWCID && u4WCID < WTBL_SIZE && + prAdapter->rWifiVar.arWtbl[u4WCID].ucUsed) { + rSwCtrlInfo.u4Id |= u4WCID; + rSwCtrlInfo.u4Id |= BIT(8); + i4BytesWritten = kalSnprintf( + pcCommand, i4TotalLen, + "Apply WCID %d\n", u4WCID); + } else { + i4BytesWritten = kalSnprintf( + pcCommand, i4TotalLen, "Apply All\n"); + } + + if (u4SGI) + rSwCtrlInfo.u4Data |= BIT(30); + if (u4LDPC) + rSwCtrlInfo.u4Data |= BIT(29); + if (u4SpeEn) + rSwCtrlInfo.u4Data |= BIT(28); + if (u4Band) + rSwCtrlInfo.u4Data |= BIT(25); + if (u4STBC) + rSwCtrlInfo.u4Data |= BIT(11); + + if (u4Bw <= 3) + rSwCtrlInfo.u4Data |= ((u4Bw << 26) & BITS(26, 27)); + else { + fgStatus = FALSE; + DBGLOG(INIT, ERROR, + "Wrong BW! BW20=0, BW40=1, BW80=2,BW160=3\n"); + } + if (u4Mode <= 4) { + rSwCtrlInfo.u4Data |= ((u4Mode << 6) & BITS(6, 8)); + + switch (u4Mode) { + case 0: + if (u4Mcs <= 3) + rSwCtrlInfo.u4Data |= u4Mcs; + else { + fgStatus = FALSE; + DBGLOG(INIT, ERROR, + "CCK mode but wrong MCS!\n"); + } + + if (u4Preamble) + rSwCtrlInfo.u4Data |= BIT(2); + else + rSwCtrlInfo.u4Data &= ~BIT(2); + break; + case 1: + switch (u4Mcs) { + case 0: + /* 6'b001011 */ + rSwCtrlInfo.u4Data |= 11; + break; + case 1: + /* 6'b001111 */ + rSwCtrlInfo.u4Data |= 15; + break; + case 2: + /* 6'b001010 */ + rSwCtrlInfo.u4Data |= 10; + break; + case 3: + /* 6'b001110 */ + rSwCtrlInfo.u4Data |= 14; + break; + case 4: + /* 6'b001001 */ + rSwCtrlInfo.u4Data |= 9; + break; + case 5: + /* 6'b001101 */ + rSwCtrlInfo.u4Data |= 13; + break; + case 6: + /* 6'b001000 */ + rSwCtrlInfo.u4Data |= 8; + break; + case 7: + /* 6'b001100 */ + rSwCtrlInfo.u4Data |= 12; + break; + default: + fgStatus = FALSE; + DBGLOG(INIT, ERROR, + "OFDM mode but wrong MCS!\n"); + break; + } + break; + case 2: + case 3: + if (u4Mcs <= 32) + rSwCtrlInfo.u4Data |= u4Mcs; + else { + fgStatus = FALSE; + DBGLOG(INIT, ERROR, + "HT mode but wrong MCS!\n"); + } + + if (u4Mcs != 32) { + u4Nsts += (u4Mcs >> 3); + if (u4STBC && (u4Nsts == 1)) + u4Nsts++; + } + break; + case 4: + if (u4Mcs <= 9) + rSwCtrlInfo.u4Data |= u4Mcs; + else { + fgStatus = FALSE; + DBGLOG(INIT, ERROR, + "VHT mode but wrong MCS!\n"); + } + if (u4STBC && (u4VhtNss == 1)) + u4Nsts++; + else + u4Nsts = u4VhtNss; + break; + default: + break; + } + } else { + fgStatus = FALSE; + DBGLOG(INIT, ERROR, + "Wrong TxMode! CCK=0, OFDM=1, HT=2, GF=3, VHT=4\n"); + } + + rSwCtrlInfo.u4Data |= (((u4Nsts - 1) << 9) & BITS(9, 10)); + + if (fgStatus) { + rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + FALSE, FALSE, TRUE, &u4BufLen); + } + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } else { + DBGLOG(INIT, ERROR, "iwpriv wlanXX driver FixedRate=Option\n"); + DBGLOG(INIT, ERROR, + "Option:[WCID]-[Mode]-[BW]-[MCS]-[VhtNss]-[SGI]-[Preamble]-[STBC]-[LDPC]-[SPE_EN]-[BAND]\n"); + DBGLOG(INIT, ERROR, "[WCID]Wireless Client ID\n"); + DBGLOG(INIT, ERROR, "[Mode]CCK=0, OFDM=1, HT=2, GF=3, VHT=4\n"); + DBGLOG(INIT, ERROR, "[BW]BW20=0, BW40=1, BW80=2,BW160=3\n"); + DBGLOG(INIT, ERROR, + "[MCS]CCK=0~3, OFDM=0~7, HT=0~32, VHT=0~9\n"); + DBGLOG(INIT, ERROR, "[VhtNss]VHT=1~4, Other=ignore\n"); + DBGLOG(INIT, ERROR, "[Preamble]Long=0, Other=Short\n"); + DBGLOG(INIT, ERROR, "[BAND]2G=0, Other=5G\n"); + } + + return i4BytesWritten; +} +#endif + +#if (CFG_SUPPORT_TXPOWER_INFO == 1) +static int32_t priv_driver_dump_txpower_info(struct ADAPTER *prAdapter, + IN char *pcCommand, IN int i4TotalLen, + struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T *prTxPowerInfo) +{ + int32_t i4BytesWritten = 0; + + if (prTxPowerInfo->ucTxPowerCategory == + TXPOWER_EVENT_SHOW_ALL_RATE_TXPOWER_INFO) { + uint8_t ucTxPwrIdx = 0, ucTxPwrType = 0, ucIdx = 0, + ucIdxOffset = 0; + + char *rateStr = NULL; + struct FRAME_POWER_CONFIG_INFO_T rRatePowerInfo; + char *cckRateStr[MODULATION_SYSTEM_CCK_NUM] = { + "1M", "2M", "5M", "11M"}; + char *ofdmRateStr[MODULATION_SYSTEM_OFDM_NUM] = { + "6M", "9M", "12M", "18M", "24M", "36M", "48M", "54M" }; + char *ht20RateStr[MODULATION_SYSTEM_HT20_NUM] = { + "M0", "M1", "M2", "M3", "M4", "M5", "M6", "M7" }; + char *ht40RateStr[MODULATION_SYSTEM_HT40_NUM] = { + "M0", "M1", "M2", "M3", "M4", "M5", "M6", + "M7", "M32" }; + char *vhtRateStr[MODULATION_SYSTEM_VHT20_NUM] = { + "M0", "M1", "M2", "M3", "M4", "M5", "M6", + "M7", "M8", "M9" }; + char *ruRateStr[MODULATION_SYSTEM_HE_26_MCS_NUM] = { + "M0", "M1", "M2", "M3", "M4", "M5", "M6", "M7", + "M8", "M9", "M10", "M11" }; + + uint8_t *pucStr = NULL; + uint8_t *POWER_TYPE_STR[] = { + "CCK", "OFDM", "HT20", "HT40", + "VHT20", "VHT40", "VHT80", + "VHT160", "RU26", "RU52", "RU106", + "RU242", "RU484", "RU996"}; + uint8_t ucPwrIdxLen[] = { + MODULATION_SYSTEM_CCK_NUM, + MODULATION_SYSTEM_OFDM_NUM, + MODULATION_SYSTEM_HT20_NUM, + MODULATION_SYSTEM_HT40_NUM, + MODULATION_SYSTEM_VHT20_NUM, + MODULATION_SYSTEM_VHT40_NUM, + MODULATION_SYSTEM_VHT80_NUM, + MODULATION_SYSTEM_VHT160_NUM, + MODULATION_SYSTEM_HE_26_MCS_NUM, + MODULATION_SYSTEM_HE_52_MCS_NUM, + MODULATION_SYSTEM_HE_106_MCS_NUM, + MODULATION_SYSTEM_HE_242_MCS_NUM, + MODULATION_SYSTEM_HE_484_MCS_NUM, + MODULATION_SYSTEM_HE_996_MCS_NUM}; + + uint8_t ucBandIdx; + uint8_t ucFormat; + + if ((sizeof(POWER_TYPE_STR)/sizeof(uint8_t *)) != + (sizeof(ucPwrIdxLen)/sizeof(uint8_t))) + return i4BytesWritten; + + ucBandIdx = prTxPowerInfo->ucBandIdx; + ucFormat = prTxPowerInfo->u1Format; + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s", + "\n====== TX POWER INFO ======\n"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "DBDC Index: %d, Channel Band: %s\n", + ucBandIdx, + (prTxPowerInfo->ucChBand) ? + ("5G") : ("2G")); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "===========================\n"); + + rRatePowerInfo = + prTxPowerInfo->rRatePowerInfo; + + + for (ucTxPwrType = 0; + ucTxPwrType < sizeof(POWER_TYPE_STR)/sizeof(uint8_t *); + ucTxPwrType++) { + + pucStr = POWER_TYPE_STR[ucTxPwrType]; + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "[%6s] > ", pucStr); + + for (ucTxPwrIdx = 0; + ucTxPwrIdx < ucPwrIdxLen[ucTxPwrType]; + ucTxPwrIdx++) { + /*Legcay format*/ + if (kalStrCmp(pucStr, "CCK") == 0) + rateStr = cckRateStr[ucTxPwrIdx]; + else if (kalStrCmp(pucStr, "OFDM") == 0) + rateStr = ofdmRateStr[ucTxPwrIdx]; + else if (kalStrCmp(pucStr, "HT20") == 0) + rateStr = ht20RateStr[ucTxPwrIdx]; + else if (kalStrCmp(pucStr, "HT40") == 0) + rateStr = ht40RateStr[ucTxPwrIdx]; + else if (kalStrnCmp(pucStr, "VHT", 3) == 0) + rateStr = vhtRateStr[ucTxPwrIdx]; + /*HE format*/ + else if ((kalStrnCmp(pucStr, "RU", 2) == 0) + && (ucFormat == TXPOWER_FORMAT_HE)) + rateStr = ruRateStr[ucTxPwrIdx]; + else + continue; + + ucIdx = ucTxPwrIdx + ucIdxOffset; + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%3s:%03d, ", + rateStr, + rRatePowerInfo. + aicFramePowerConfig[ucIdx][ucBandIdx]. + icFramePowerDbm); + } + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\n"); + + ucIdxOffset += ucPwrIdxLen[ucTxPwrType]; + } + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "[MAX][Bound]: 0x%02x (%03d)\n", + prTxPowerInfo->icPwrMaxBnd, + prTxPowerInfo->icPwrMaxBnd); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "[MIN][Bound]: 0x%02x (%03d)\n", + prTxPowerInfo->icPwrMinBnd, + prTxPowerInfo->icPwrMinBnd); + } + + return i4BytesWritten; +} + +static int32_t priv_driver_get_txpower_info(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0, u4Size = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + int8_t *this_char = NULL; + uint32_t u4ParamNum = 0; + uint8_t ucParam = 0; + uint8_t ucBandIdx = 0; + struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T *prTxPowerInfo = NULL; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, INFO, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, INFO, "argc is %d, apcArgv[0] = %s\n\n", i4Argc, *apcArgv); + + this_char = kalStrStr(*apcArgv, "="); + if (!this_char) + return -1; + this_char++; + + DBGLOG(REQ, INFO, "string = %s\n", this_char); + + u4ParamNum = sscanf(this_char, "%d:%d", &ucParam, &ucBandIdx); + if (u4ParamNum < 0) + return -1; + DBGLOG(REQ, INFO, "ParamNum=%d,Param=%d,Band=%d\n", + u4ParamNum, ucParam, ucBandIdx); + + u4Size = sizeof(struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T); + + prTxPowerInfo = + (struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T *)kalMemAlloc( + u4Size, VIR_MEM_TYPE); + if (!prTxPowerInfo) + return -1; + + if (u4ParamNum == TXPOWER_INFO_INPUT_ARG_NUM) { + prTxPowerInfo->ucTxPowerCategory = ucParam; + prTxPowerInfo->ucBandIdx = ucBandIdx; + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryTxPowerInfo, + prTxPowerInfo, + sizeof(struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + kalMemFree(prTxPowerInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T)); + return -1; + } + + i4BytesWritten = priv_driver_dump_txpower_info(prAdapter, + pcCommand, i4TotalLen, prTxPowerInfo); + } else { + DBGLOG(INIT, ERROR, + "[Error]iwpriv wlanXX driver TxPowerInfo=[Param]:[BandIdx]\n"); + } + + kalMemFree(prTxPowerInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T)); + + return i4BytesWritten; +} +#endif +static int32_t priv_driver_txpower_man_set(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0, u4Size = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + int8_t *this_char = NULL; + uint32_t u4ParamNum = 0; + uint8_t ucPhyMode = 0; + uint8_t ucTxRate = 0; + uint8_t ucBw = 0; + int8_t iTargetPwr = 0; + struct PARAM_TXPOWER_BY_RATE_SET_T *prPwrCtl = NULL; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, INFO, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, INFO, "argc is %d, apcArgv[0] = %s\n\n", i4Argc, *apcArgv); + + this_char = kalStrStr(*apcArgv, "="); + if (!this_char) + return -1; + this_char++; + + DBGLOG(REQ, INFO, "string = %s\n", this_char); + + u4ParamNum = sscanf(this_char, "%d:%d:%d:%d", &ucPhyMode, &ucTxRate, + &ucBw, &iTargetPwr); + + if (u4ParamNum < 0) { + DBGLOG(REQ, WARN, "sscanf input fail\n"); + return -1; + } + + DBGLOG(REQ, INFO, "ParamNum=%d,PhyMod=%d,Rate=%d,Bw=%d,Pwr=%d\n", + u4ParamNum, ucPhyMode, ucTxRate, ucBw, iTargetPwr); + + u4Size = sizeof(struct PARAM_TXPOWER_BY_RATE_SET_T); + + prPwrCtl = + (struct PARAM_TXPOWER_BY_RATE_SET_T *)kalMemAlloc( + u4Size, VIR_MEM_TYPE); + if (!prPwrCtl) + return -1; + + if (u4ParamNum == TXPOWER_MAN_SET_INPUT_ARG_NUM) { + prPwrCtl->u1PhyMode = ucPhyMode; + prPwrCtl->u1TxRate = ucTxRate; + prPwrCtl->u1BW = ucBw; + prPwrCtl->i1TxPower = iTargetPwr; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetTxPowerByRateManual, + prPwrCtl, + sizeof(struct PARAM_TXPOWER_BY_RATE_SET_T), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + kalMemFree(prPwrCtl, VIR_MEM_TYPE, + sizeof(struct PARAM_TXPOWER_BY_RATE_SET_T)); + return -1; + } + + } else { + DBGLOG(INIT, ERROR, + "[Error]iwpriv wlanXX driver TxPwrManualSet=PhyMode:Rate:Bw:Pwr\n"); + } + + kalMemFree(prPwrCtl, VIR_MEM_TYPE, + sizeof(struct PARAM_TXPOWER_BY_RATE_SET_T)); + + return i4BytesWritten; +} + +static int priv_driver_get_sta_stat(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0, u4Ret, u4StatGroup = 0xFFFFFFFF; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint8_t aucMacAddr[MAC_ADDR_LEN]; + uint8_t ucWlanIndex = 0; + uint8_t *pucMacAddr = NULL; + struct PARAM_HW_WLAN_INFO *prHwWlanInfo = NULL; + struct PARAM_GET_STA_STATISTICS *prQueryStaStatistics = NULL; + u_int8_t fgResetCnt = FALSE; + u_int8_t fgRxCCSel = FALSE; + u_int8_t fgSearchMacAddr = FALSE; + struct BSS_INFO *prAisBssInfo = NULL; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + prAisBssInfo = aisGetAisBssInfo( + prGlueInfo->prAdapter, wlanGetBssIdx(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= 4) { + if (strnicmp(apcArgv[2], CMD_STAT_GROUP_SEL, + strlen(CMD_STAT_GROUP_SEL)) == 0) { + u4Ret = kalkStrtou32(apcArgv[3], 0, &(u4StatGroup)); + + if (u4Ret) + DBGLOG(REQ, LOUD, + "parse get_sta_stat error (Group) u4Ret=%d\n", + u4Ret); + if (u4StatGroup == 0) + u4StatGroup = 0xFFFFFFFF; + + wlanHwAddrToBin(apcArgv[1], &aucMacAddr[0]); + + if (!wlanGetWlanIdxByAddress(prGlueInfo->prAdapter, + &aucMacAddr[0], &ucWlanIndex)) { + DBGLOG(REQ, INFO, + "wlan index of "MACSTR" is not found!\n", + MAC2STR(aucMacAddr)); + goto out; + } + } else { + goto out; + } + } else if (i4Argc >= 3) { + if (strnicmp(apcArgv[1], CMD_STAT_GROUP_SEL, + strlen(CMD_STAT_GROUP_SEL)) == 0) { + u4Ret = kalkStrtou32(apcArgv[2], 0, &(u4StatGroup)); + + if (u4Ret) + DBGLOG(REQ, LOUD, + "parse get_sta_stat error (Group) u4Ret=%d\n", + u4Ret); + if (u4StatGroup == 0) + u4StatGroup = 0xFFFFFFFF; + + if (prAisBssInfo->prStaRecOfAP) { + ucWlanIndex = prAisBssInfo->prStaRecOfAP + ->ucWlanIndex; + } else if (!wlanGetWlanIdxByAddress( + prGlueInfo->prAdapter, NULL, + &ucWlanIndex)) { + DBGLOG(REQ, INFO, + "wlan index of "MACSTR" is not found!\n", + MAC2STR(aucMacAddr)); + goto out; + } + } else { + if (strnicmp(apcArgv[1], CMD_STAT_RESET_CNT, + strlen(CMD_STAT_RESET_CNT)) == 0) { + wlanHwAddrToBin(apcArgv[2], &aucMacAddr[0]); + fgResetCnt = TRUE; + } else if (strnicmp(apcArgv[2], CMD_STAT_RESET_CNT, + strlen(CMD_STAT_RESET_CNT)) == 0) { + wlanHwAddrToBin(apcArgv[1], &aucMacAddr[0]); + fgResetCnt = TRUE; + } else { + wlanHwAddrToBin(apcArgv[1], &aucMacAddr[0]); + fgResetCnt = FALSE; + } + + if (!wlanGetWlanIdxByAddress(prGlueInfo->prAdapter, + &aucMacAddr[0], &ucWlanIndex)) { + DBGLOG(REQ, INFO, + "wlan index of "MACSTR" is not found!\n", + MAC2STR(aucMacAddr)); + goto out; + } + } + } else { + if (i4Argc == 1) { + fgSearchMacAddr = TRUE; + } else if (i4Argc == 2) { + if (strnicmp(apcArgv[1], CMD_STAT_RESET_CNT, + strlen(CMD_STAT_RESET_CNT)) == 0) { + fgResetCnt = TRUE; + fgSearchMacAddr = TRUE; + } else if (strnicmp(apcArgv[1], CMD_STAT_NOISE_SEL, + strlen(CMD_STAT_NOISE_SEL)) == 0) { + fgRxCCSel = TRUE; + fgSearchMacAddr = TRUE; + } else { + wlanHwAddrToBin(apcArgv[1], &aucMacAddr[0]); + + if (!wlanGetWlanIdxByAddress(prGlueInfo-> + prAdapter, &aucMacAddr[0], &ucWlanIndex)) { + DBGLOG(REQ, INFO, + "No connected peer found!\n"); + goto out; + } + } + } + + if (fgSearchMacAddr) { + /* Get AIS AP address for no argument */ + if (prAisBssInfo->prStaRecOfAP) { + ucWlanIndex = prAisBssInfo->prStaRecOfAP + ->ucWlanIndex; + } else if (!wlanGetWlanIdxByAddress(prGlueInfo-> + prAdapter, NULL, &ucWlanIndex)) { + DBGLOG(REQ, INFO, "No connected peer found!\n"); + goto out; + } + } + } + + prHwWlanInfo = (struct PARAM_HW_WLAN_INFO *)kalMemAlloc( + sizeof(struct PARAM_HW_WLAN_INFO), VIR_MEM_TYPE); + if (!prHwWlanInfo) { + DBGLOG(REQ, ERROR, + "Allocate prHwWlanInfo failed!\n"); + i4BytesWritten = -1; + goto out; + } + + prHwWlanInfo->u4Index = ucWlanIndex; + if (fgRxCCSel == TRUE) + prHwWlanInfo->rWtblRxCounter.fgRxCCSel = TRUE; + else + prHwWlanInfo->rWtblRxCounter.fgRxCCSel = FALSE; + + DBGLOG(REQ, INFO, "index = %d i4TotalLen = %d\n", + prHwWlanInfo->u4Index, i4TotalLen); + + /* Get WTBL info */ + rStatus = kalIoctl(prGlueInfo, wlanoidQueryWlanInfo, prHwWlanInfo, + sizeof(struct PARAM_HW_WLAN_INFO), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "Query prHwWlanInfo failed!\n"); + i4BytesWritten = -1; + goto out; + } + + /* Get Statistics info */ + prQueryStaStatistics = + (struct PARAM_GET_STA_STATISTICS *)kalMemAlloc( + sizeof(struct PARAM_GET_STA_STATISTICS), VIR_MEM_TYPE); + if (!prQueryStaStatistics) { + DBGLOG(REQ, ERROR, + "Allocate prQueryStaStatistics failed!\n"); + i4BytesWritten = -1; + goto out; + } + + prQueryStaStatistics->ucResetCounter = fgResetCnt; + + pucMacAddr = wlanGetStaAddrByWlanIdx(prGlueInfo->prAdapter, + ucWlanIndex); + + if (!pucMacAddr) { + DBGLOG(REQ, ERROR, "Addr of WlanIndex %d is not found!\n", + ucWlanIndex); + i4BytesWritten = -1; + goto out; + } + COPY_MAC_ADDR(prQueryStaStatistics->aucMacAddr, pucMacAddr); + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryStaStatistics, + prQueryStaStatistics, + sizeof(struct PARAM_GET_STA_STATISTICS), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "Query prQueryStaStatistics failed!\n"); + i4BytesWritten = -1; + goto out; + } + + if (pucMacAddr) { + struct CHIP_DBG_OPS *prChipDbg; + + prChipDbg = prAdapter->chip_info->prDebugOps; + + if (prChipDbg && prChipDbg->show_stat_info) + i4BytesWritten = prChipDbg->show_stat_info(prAdapter, + pcCommand, i4TotalLen, prHwWlanInfo, + prQueryStaStatistics, fgResetCnt, u4StatGroup); + } + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + +out: + if (prHwWlanInfo) + kalMemFree(prHwWlanInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_HW_WLAN_INFO)); + + if (prQueryStaStatistics) + kalMemFree(prQueryStaStatistics, VIR_MEM_TYPE, + sizeof(struct PARAM_GET_STA_STATISTICS)); + + + if (fgResetCnt) + nicRxClearStatistics(prGlueInfo->prAdapter); + + return i4BytesWritten; +} + +static int32_t priv_driver_dump_stat2_info(struct ADAPTER *prAdapter, + IN char *pcCommand, IN int i4TotalLen, + struct UMAC_STAT2_GET *prUmacStat2GetInfo, + struct PARAM_GET_DRV_STATISTICS *prQueryDrvStatistics) +{ + int32_t i4BytesWritten = 0; + uint16_t u2PleTotalRevPage = 0; + uint16_t u2PleTotalSrcPage = 0; + uint16_t u2PseTotalRevPage = 0; + uint16_t u2PseTotalSrcPage = 0; + + u2PleTotalRevPage = prUmacStat2GetInfo->u2PleRevPgHif0Group0 + + prUmacStat2GetInfo->u2PleRevPgCpuGroup2; + + u2PleTotalSrcPage = prUmacStat2GetInfo->u2PleSrvPgHif0Group0 + + prUmacStat2GetInfo->u2PleSrvPgCpuGroup2; + + u2PseTotalRevPage = prUmacStat2GetInfo->u2PseRevPgHif0Group0 + + prUmacStat2GetInfo->u2PseRevPgHif1Group1 + + prUmacStat2GetInfo->u2PseRevPgCpuGroup2 + + prUmacStat2GetInfo->u2PseRevPgLmac0Group3 + + prUmacStat2GetInfo->u2PseRevPgLmac1Group4 + + prUmacStat2GetInfo->u2PseRevPgLmac2Group5 + + prUmacStat2GetInfo->u2PseRevPgPleGroup6; + + u2PseTotalSrcPage = prUmacStat2GetInfo->u2PseSrvPgHif0Group0 + + prUmacStat2GetInfo->u2PseSrvPgHif1Group1 + + prUmacStat2GetInfo->u2PseSrvPgCpuGroup2 + + prUmacStat2GetInfo->u2PseSrvPgLmac0Group3 + + prUmacStat2GetInfo->u2PseSrvPgLmac1Group4 + + prUmacStat2GetInfo->u2PseSrvPgLmac2Group5 + + prUmacStat2GetInfo->u2PseSrvPgPleGroup6; + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "\n----- Stat2 Info -----\n"); + + + /* Rev Page number Info. */ + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "\n----- PLE Reservation Page Info. -----\n"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Ple Hif0 Group0 RevPage", " = ", + prUmacStat2GetInfo->u2PleRevPgHif0Group0); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Ple Cpu Group2 RevPage", " = ", + prUmacStat2GetInfo->u2PleRevPgCpuGroup2); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Ple Total RevPage", " = ", + u2PleTotalRevPage); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "\n----- PLE Source Page Info. ----------\n"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Ple Hif0 Group0 SrcPage", " = ", + prUmacStat2GetInfo->u2PleSrvPgHif0Group0); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Ple Cpu Group2 SrcPage", " = ", + prUmacStat2GetInfo->u2PleSrvPgCpuGroup2); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Ple Total SrcPage", " = ", + u2PleTotalSrcPage); + + /* umac MISC Info. */ + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "\n----- PLE Misc Info. -----------------\n"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "ple Total Page Number", " = ", + prUmacStat2GetInfo->u2PleTotalPageNum); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "ple Free Page Number", " = ", + prUmacStat2GetInfo->u2PleFreePageNum); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "ple FFA Page Number", " = ", + prUmacStat2GetInfo->u2PleFfaNum); + + /* PSE Info. */ + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "\n----- PSE Reservation Page Info. -----\n"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Hif0 Group0 RevPage", " = ", + prUmacStat2GetInfo->u2PseRevPgHif0Group0); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Hif1 Group1 RevPage", " = ", + prUmacStat2GetInfo->u2PseRevPgHif1Group1); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Cpu Group2 RevPage", " = ", + prUmacStat2GetInfo->u2PseRevPgCpuGroup2); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Lmac0 Group3 RevPage", " = ", + prUmacStat2GetInfo->u2PseRevPgLmac0Group3); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Lmac1 Group4 RevPage", " = ", + prUmacStat2GetInfo->u2PseRevPgLmac1Group4); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Lmac2 Group5 RevPage", " = ", + prUmacStat2GetInfo->u2PseRevPgLmac2Group5); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Ple Group6 RevPage", " = ", + prUmacStat2GetInfo->u2PseRevPgPleGroup6); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Total RevPage", " = ", + u2PseTotalRevPage); + + /* PSE Info. */ + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "\n----- PSE Source Page Info. ----------\n"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Hif0 Group0 SrcPage", " = ", + prUmacStat2GetInfo->u2PseSrvPgHif0Group0); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Hif1 Group1 SrcPage", " = ", + prUmacStat2GetInfo->u2PseSrvPgHif1Group1); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Cpu Group2 SrcPage", " = ", + prUmacStat2GetInfo->u2PseSrvPgCpuGroup2); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Lmac0 Group3 SrcPage", " = ", + prUmacStat2GetInfo->u2PseSrvPgLmac0Group3); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Lmac1 Group4 SrcPage", " = ", + prUmacStat2GetInfo->u2PseSrvPgLmac1Group4); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Lmac2 Group5 SrcPage", " = ", + prUmacStat2GetInfo->u2PseSrvPgLmac2Group5); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Ple Group6 SrcPage", " = ", + prUmacStat2GetInfo->u2PseSrvPgPleGroup6); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Total SrcPage", " = ", + u2PseTotalSrcPage); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "\n----- PSE Misc Info. -----------------\n"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "pse Total Page Number", " = ", + prUmacStat2GetInfo->u2PseTotalPageNum); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "pse Free Page Number", " = ", + prUmacStat2GetInfo->u2PseFreePageNum); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "pse FFA Page Number", " = ", + prUmacStat2GetInfo->u2PseFfaNum); + + + /* driver info */ + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "\n\n----- DRV Stat -----------------------\n\n"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pending Data", " = ", + prQueryDrvStatistics->i4TxPendingFrameNum); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pending Sec", " = ", + prQueryDrvStatistics->i4TxPendingSecurityFrameNum); +#if 0 + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%s\n", "Tx Pending Cmd Number", " = ", + prQueryDrvStatistics->i4TxPendingCmdNum); +#endif + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Tx Pending For-pkt Number", " = ", + prQueryDrvStatistics->i4PendingFwdFrameCount); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "MsduInfo Available Number", " = ", + prQueryDrvStatistics->u4MsduNumElem); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "MgmtTxRing Pending Number", " = ", + prQueryDrvStatistics->u4TxMgmtTxringQueueNumElem); + + /* Driver Rx Info. */ + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Rx Free Sw Rfb Number", " = ", + prQueryDrvStatistics->u4RxFreeSwRfbMsduNumElem); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Rx Received Sw Rfb Number", " = ", + prQueryDrvStatistics->u4RxReceivedRfbNumElem); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Rx Indicated Sw Rfb Number", " = ", + prQueryDrvStatistics->u4RxIndicatedNumElem); + + return i4BytesWritten; +} + +static int priv_driver_get_sta_stat2(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + int32_t i4BytesWritten = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + int32_t i4ArgNum = 1; + struct UMAC_STAT2_GET *prUmacStat2GetInfo; + struct PARAM_GET_DRV_STATISTICS *prQueryDrvStatistics; + struct QUE *prQueList, *prTxMgmtTxRingQueList; + struct RX_CTRL *prRxCtrl; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc < i4ArgNum) + return -1; + + prQueList = &prAdapter->rTxCtrl.rFreeMsduInfoList; + + prTxMgmtTxRingQueList = &prAdapter->rTxCtrl.rTxMgmtTxingQueue; + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + /* to do for UMAC Dump */ + prUmacStat2GetInfo = (struct UMAC_STAT2_GET *)kalMemAlloc( + sizeof(struct UMAC_STAT2_GET), VIR_MEM_TYPE); + if (prUmacStat2GetInfo == NULL) + return -1; + + halUmacInfoGetMiscStatus(prAdapter, prUmacStat2GetInfo); + + + /* Get Driver stat info */ + prQueryDrvStatistics = + (struct PARAM_GET_DRV_STATISTICS *)kalMemAlloc(sizeof( + struct PARAM_GET_DRV_STATISTICS), VIR_MEM_TYPE); + if (prQueryDrvStatistics == NULL) { + kalMemFree(prUmacStat2GetInfo, VIR_MEM_TYPE, + sizeof(struct UMAC_STAT2_GET)); + return -1; + } + + prQueryDrvStatistics->i4TxPendingFrameNum = + (uint32_t) GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum); + prQueryDrvStatistics->i4TxPendingSecurityFrameNum = + (uint32_t) GLUE_GET_REF_CNT( + prGlueInfo->i4TxPendingSecurityFrameNum); +#if 0 + prQueryDrvStatistics->i4TxPendingCmdNum = + (uint32_t) GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingCmdNum); +#endif + + prQueryDrvStatistics->i4PendingFwdFrameCount = + prAdapter->rTxCtrl.i4PendingFwdFrameCount; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + prQueryDrvStatistics->u4MsduNumElem = prQueList->u4NumElem; + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + prQueryDrvStatistics->u4TxMgmtTxringQueueNumElem = + prTxMgmtTxRingQueList->u4NumElem; + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + prQueryDrvStatistics->u4RxFreeSwRfbMsduNumElem = + prRxCtrl->rFreeSwRfbList.u4NumElem; + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + prQueryDrvStatistics->u4RxReceivedRfbNumElem = + prRxCtrl->rReceivedRfbList.u4NumElem; + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + prQueryDrvStatistics->u4RxIndicatedNumElem = + prRxCtrl->rIndicatedRfbList.u4NumElem; + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + i4BytesWritten = priv_driver_dump_stat2_info(prAdapter, pcCommand, + i4TotalLen, prUmacStat2GetInfo, prQueryDrvStatistics); + + kalMemFree(prUmacStat2GetInfo, VIR_MEM_TYPE, + sizeof(struct UMAC_STAT2_GET)); + kalMemFree(prQueryDrvStatistics, VIR_MEM_TYPE, + sizeof(struct PARAM_GET_DRV_STATISTICS)); + + return i4BytesWritten; +} + + +static int32_t priv_driver_dump_rx_stat_info(struct ADAPTER *prAdapter, + IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen, + IN u_int8_t fgResetCnt) +{ + int32_t i4BytesWritten = 0; + uint32_t u4RxVector0 = 0, u4RxVector2 = 0, u4RxVector3 = 0, + u4RxVector4 = 0; + uint8_t ucStaIdx, ucWlanIndex = 0, cbw; + u_int8_t fgWlanIdxFound = TRUE, fgSkipRxV = FALSE; + uint32_t u4FAGCRssiWBR0, u4FAGCRssiIBR0; + uint32_t u4Value, u4Foe, foe_const; + static uint32_t au4MacMdrdy[ENUM_BAND_NUM] = {0}; + static uint32_t au4FcsError[ENUM_BAND_NUM] = {0}; + static uint32_t au4OutOfResource[ENUM_BAND_NUM] = {0}; + static uint32_t au4LengthMismatch[ENUM_BAND_NUM] = {0}; + struct STA_RECORD *prStaRecOfAP; + + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + prStaRecOfAP = + aisGetStaRecOfAP(prAdapter, ucBssIndex); + + au4MacMdrdy[ENUM_BAND_0] += htonl(g_HqaRxStat.MAC_Mdrdy); + au4MacMdrdy[ENUM_BAND_1] += htonl(g_HqaRxStat.MAC_Mdrdy1); + au4FcsError[ENUM_BAND_0] += htonl(g_HqaRxStat.MAC_FCS_Err); + au4FcsError[ENUM_BAND_1] += htonl(g_HqaRxStat.MAC_FCS_Err1); + au4OutOfResource[ENUM_BAND_0] += htonl(g_HqaRxStat.OutOfResource); + au4OutOfResource[ENUM_BAND_1] += htonl(g_HqaRxStat.OutOfResource1); + au4LengthMismatch[ENUM_BAND_0] += htonl( + g_HqaRxStat.LengthMismatchCount_B0); + au4LengthMismatch[ENUM_BAND_1] += htonl( + g_HqaRxStat.LengthMismatchCount_B1); + + DBGLOG(INIT, INFO, "fgResetCnt = %d\n", fgResetCnt); + if (fgResetCnt) { + kalMemZero(au4MacMdrdy, sizeof(au4MacMdrdy)); + kalMemZero(au4FcsError, sizeof(au4FcsError)); + kalMemZero(au4OutOfResource, sizeof(au4OutOfResource)); + kalMemZero(au4LengthMismatch, sizeof(au4LengthMismatch)); + } + + if (prStaRecOfAP) + ucWlanIndex = + prStaRecOfAP->ucWlanIndex; + else if (!wlanGetWlanIdxByAddress(prAdapter, NULL, &ucWlanIndex)) + fgWlanIdxFound = FALSE; + + if (fgWlanIdxFound) { + if (wlanGetStaIdxByWlanIdx(prAdapter, ucWlanIndex, &ucStaIdx) + == WLAN_STATUS_SUCCESS) { + u4RxVector0 = prAdapter->arStaRec[ucStaIdx].u4RxVector0; + u4RxVector2 = prAdapter->arStaRec[ucStaIdx].u4RxVector2; + u4RxVector3 = prAdapter->arStaRec[ucStaIdx].u4RxVector3; + u4RxVector4 = prAdapter->arStaRec[ucStaIdx].u4RxVector4; + } else{ + fgSkipRxV = TRUE; + } + } else{ + fgSkipRxV = TRUE; + } + DBGLOG(INIT, INFO, "g_HqaRxStat.MAC_Mdrdy = %d\n", + htonl(g_HqaRxStat.MAC_Mdrdy)); + DBGLOG(INIT, INFO, "au4MacMdrdy[ENUM_BAND_0] = %d\n", + au4MacMdrdy[ENUM_BAND_0]); + DBGLOG(INIT, INFO, "g_HqaRxStat.PhyMdrdyOFDM = %d\n", + htonl(g_HqaRxStat.PhyMdrdyOFDM)); + DBGLOG(INIT, INFO, "g_HqaRxStat.MAC_FCS_Err= %d\n", + htonl(g_HqaRxStat.MAC_FCS_Err)); + DBGLOG(INIT, INFO, "au4FcsError[ENUM_BAND_0]= %d\n", + au4FcsError[ENUM_BAND_0]); + DBGLOG(INIT, INFO, "g_HqaRxStat.FCSErr_OFDM = %d\n", + htonl(g_HqaRxStat.FCSErr_OFDM)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "\n\nRX Stat:\n"); +#if 1 + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "PER0", " = ", + htonl(g_HqaRxStat.PER0)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "PER1", " = ", + htonl(g_HqaRxStat.PER1)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RX OK0", " = ", + au4MacMdrdy[ENUM_BAND_0] - au4FcsError[ENUM_BAND_0]); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RX OK1", " = ", + au4MacMdrdy[ENUM_BAND_1] - au4FcsError[ENUM_BAND_1]); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RCPI0", " = ", + htonl(g_HqaRxStat.RCPI0)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RCPI1", " = ", + htonl(g_HqaRxStat.RCPI1)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "MuRxCnt", " = ", + htonl(g_HqaRxStat.MRURxCount)); +#endif + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "MAC Mdrdy0 diff", " = ", + htonl(g_HqaRxStat.MAC_Mdrdy)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "MAC Mdrdy0", " = ", + au4MacMdrdy[ENUM_BAND_0]); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "MAC Mdrdy1 diff", " = ", + htonl(g_HqaRxStat.MAC_Mdrdy1)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "MAC Mdrdy1", " = ", + au4MacMdrdy[ENUM_BAND_1]); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "FCS Err0", " = ", + au4FcsError[ENUM_BAND_0]); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "FCS Err1", " = ", + au4FcsError[ENUM_BAND_1]); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK PD Cnt B0", " = ", + htonl(g_HqaRxStat.CCK_PD)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK PD Cnt B1", " = ", + htonl(g_HqaRxStat.CCK_PD_Band1)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK SIG Err B0", " = ", + htonl(g_HqaRxStat.CCK_SIG_Err)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK SIG Err B1", " = ", + htonl(g_HqaRxStat.CCK_SIG_Err_Band1)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM PD Cnt B0", " = ", + htonl(g_HqaRxStat.OFDM_PD)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM PD Cnt B1", " = ", + htonl(g_HqaRxStat.OFDM_PD_Band1)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM TAG Error", " = ", + htonl(g_HqaRxStat.OFDM_TAG_Err)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK SFD Err B0", " = ", + htonl(g_HqaRxStat.CCK_SFD_Err)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK SFD Err B1", " = ", + htonl(g_HqaRxStat.CCK_SFD_Err_Band1)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM SIG Err B0", " = ", + htonl(g_HqaRxStat.OFDM_SIG_Err)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM SIG Err B1", " = ", + htonl(g_HqaRxStat.OFDM_SIG_Err_Band1)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK FCS Err B0", " = ", + htonl(g_HqaRxStat.FCSErr_CCK)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK FCS Err B1", " = ", + htonl(g_HqaRxStat.CCK_FCS_Err_Band1)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM FCS Err B0", " = ", + htonl(g_HqaRxStat.FCSErr_OFDM)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM FCS Err B1", " = ", + htonl(g_HqaRxStat.OFDM_FCS_Err_Band1)); + + if (!fgSkipRxV) { + u4FAGCRssiIBR0 = (u4RxVector2 & BITS(16, 23)) >> 16; + u4FAGCRssiWBR0 = (u4RxVector2 & BITS(24, 31)) >> 24; + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "FAGC RSSI W", " = ", + (u4FAGCRssiWBR0 >= 128) ? (u4FAGCRssiWBR0 - 256) : + (u4FAGCRssiWBR0)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "FAGC RSSI I", " = ", + (u4FAGCRssiIBR0 >= 128) ? (u4FAGCRssiIBR0 - 256) : + (u4FAGCRssiIBR0)); + } else{ + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "FAGC RSSI W", " = ", + htonl(g_HqaRxStat.FAGCRssiWBR0)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "FAGC RSSI I", " = ", + htonl(g_HqaRxStat.FAGCRssiIBR0)); + } + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK MDRDY B0", " = ", + htonl(g_HqaRxStat.PhyMdrdyCCK)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK MDRDY B1", " = ", + htonl(g_HqaRxStat.PHY_CCK_MDRDY_Band1)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM MDRDY B0", " = ", + htonl(g_HqaRxStat.PhyMdrdyOFDM)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM MDRDY B1", " = ", + htonl(g_HqaRxStat.PHY_OFDM_MDRDY_Band1)); + + if (!fgSkipRxV) { +#if 0 + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Driver RX Cnt0", " = ", + htonl(g_HqaRxStat.DriverRxCount)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Driver RX Cnt1", " = ", + htonl(g_HqaRxStat.DriverRxCount1)); +#endif + u4Value = (u4RxVector0 & BITS(12, 14)) >> 12; + if (u4Value == 0) { + u4Foe = (((u4RxVector4 & BITS(7, 31)) >> 7) & 0x7ff); + u4Foe = (u4Foe * 1000)>>11; + } else{ + cbw = ((u4RxVector0 & BITS(15, 16)) >> 15); + foe_const = ((1 << (cbw + 1)) & 0xf) * 10000; + u4Foe = (((u4RxVector4 & BITS(7, 31)) >> 7) & 0xfff); + u4Foe = (u4Foe * foe_const) >> 15; + } + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Freq Offset From RX", " = ", u4Foe); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RX SNR (dB)", " = ", + (uint32_t)(((u4RxVector4 & BITS(26, 31)) >> 26) - 16)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "uint8_t RX0", " = ", + (uint32_t)(u4RxVector3 & BITS(0, 7))); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "uint8_t RX1", " = ", + (uint32_t)((u4RxVector3 & BITS(8, 15)) >> 8)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "uint8_t RX2", " = ", + ((u4RxVector3 & BITS(16, 23)) >> 16) == 0xFF ? + (0) : ((uint32_t)(u4RxVector3 & BITS(16, 23)) >> 16)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "uint8_t RX3", " = ", + ((u4RxVector3 & BITS(24, 31)) >> 24) == 0xFF ? + (0) : ((uint32_t)(u4RxVector3 & BITS(24, 31)) >> 24)); + } else{ +#if 1 + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Driver RX Cnt0", + " = ", + htonl(g_HqaRxStat.DriverRxCount)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Driver RX Cnt1", + " = ", + htonl(g_HqaRxStat.DriverRxCount1)); +#endif + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", + "Freq Offset From RX", + " = ", + htonl(g_HqaRxStat.FreqOffsetFromRX)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "RX SNR (dB)", + " = ", "N/A"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "uint8_t RX0", + " = ", "N/A"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "uint8_t RX1", + " = ", "N/A"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "uint8_t RX2", + " = ", "N/A"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "uint8_t RX3", + " = ", "N/A"); + } + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Inst RSSI IB R0", " = ", + htonl(g_HqaRxStat.InstRssiIBR0)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Inst RSSI WB R0", " = ", + htonl(g_HqaRxStat.InstRssiWBR0)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Inst RSSI IB R1", " = ", + htonl(g_HqaRxStat.InstRssiIBR1)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Inst RSSI WB R1", " = ", + htonl(g_HqaRxStat.InstRssiWBR1)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Inst RSSI IB R2", " = ", + htonl(g_HqaRxStat.InstRssiIBR2)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Inst RSSI WB R2", " = ", + htonl(g_HqaRxStat.InstRssiWBR2)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Inst RSSI IB R3", " = ", + htonl(g_HqaRxStat.InstRssiIBR3)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Inst RSSI WB R3", " = ", + htonl(g_HqaRxStat.InstRssiWBR3)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "ACI Hit Lower", " = ", + htonl(g_HqaRxStat.ACIHitLower)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "ACI Hit Higher", + " = ", htonl(g_HqaRxStat.ACIHitUpper)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OutOf Resource Pkt0", + " = ", au4OutOfResource[ENUM_BAND_0]); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OutOf Resource Pkt1", + " = ", au4OutOfResource[ENUM_BAND_1]); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Len Mismatch Cnt B0", + " = ", au4LengthMismatch[ENUM_BAND_0]); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Len Mismatch Cnt B1", + " = ", au4LengthMismatch[ENUM_BAND_1]); +#if 0 + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "MU RX Cnt", " = ", + htonl(g_HqaRxStat.MRURxCount)); +#endif + return i4BytesWritten; +} + + +static int priv_driver_show_rx_stat(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + struct PARAM_CUSTOM_ACCESS_RX_STAT *prRxStatisticsTest; + u_int8_t fgResetCnt = FALSE; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + uint32_t u4Id = 0x99980000; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + DBGLOG(INIT, ERROR, + "MT6632 : priv_driver_show_rx_stat %s, i4Argc[%d]\n", + pcCommand, i4Argc); + + if (i4Argc >= 2) { + if (strnicmp(apcArgv[1], CMD_STAT_RESET_CNT, + strlen(CMD_STAT_RESET_CNT)) == 0) + fgResetCnt = TRUE; + } + + if (i4Argc >= 1) { + if (fgResetCnt) { + rSwCtrlInfo.u4Id = u4Id; + rSwCtrlInfo.u4Data = 0; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } + + prRxStatisticsTest = + (struct PARAM_CUSTOM_ACCESS_RX_STAT *)kalMemAlloc( + sizeof(struct PARAM_CUSTOM_ACCESS_RX_STAT), + VIR_MEM_TYPE); + if (!prRxStatisticsTest) + return -1; + + prRxStatisticsTest->u4SeqNum = u4RxStatSeqNum; + prRxStatisticsTest->u4TotalNum = + sizeof(struct PARAM_RX_STAT) / 4; + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryRxStatistics, + prRxStatisticsTest, + sizeof(struct PARAM_CUSTOM_ACCESS_RX_STAT), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + kalMemFree(prRxStatisticsTest, VIR_MEM_TYPE, + sizeof(struct PARAM_CUSTOM_ACCESS_RX_STAT)); + return -1; + } + + i4BytesWritten = priv_driver_dump_rx_stat_info(prAdapter, + prNetDev, pcCommand, i4TotalLen, fgResetCnt); + + kalMemFree(prRxStatisticsTest, VIR_MEM_TYPE, + sizeof(struct PARAM_CUSTOM_ACCESS_RX_STAT)); + } + + return i4BytesWritten; +} + +/*----------------------------------------------------------------------------*/ +/* + * @ The function will set policy of ACL. + * 0: disable ACL + * 1: enable accept list + * 2: enable deny list + * example: iwpriv p2p0 driver "set_acl_policy 1" + */ +/*----------------------------------------------------------------------------*/ +static int priv_driver_set_acl_policy(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct BSS_INFO *prBssInfo = NULL; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + int32_t i4Argc = 0, i4BytesWritten = 0, i4Ret = 0, i4Policy = 0; + uint8_t ucRoleIdx = 0, ucBssIdx = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + /* get Bss Index from ndev */ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prNetDev, &ucRoleIdx) != 0) + return -1; + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) + return -1; + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + DBGLOG(REQ, LOUD, "ucRoleIdx %hhu ucBssIdx %hhu\n", ucRoleIdx, + ucBssIdx); + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc < 2) + return -1; + + i4Ret = kalkStrtou32(apcArgv[1], 0, &i4Policy); + if (i4Ret) { + DBGLOG(REQ, ERROR, "integer format error i4Ret=%d\n", i4Ret); + return -1; + } + + switch (i4Policy) { + case PARAM_CUSTOM_ACL_POLICY_DISABLE: + case PARAM_CUSTOM_ACL_POLICY_ACCEPT: + case PARAM_CUSTOM_ACL_POLICY_DENY: + prBssInfo->rACL.ePolicy = i4Policy; + break; + default: /*Invalid argument */ + DBGLOG(REQ, ERROR, "Invalid ACL Policy=%d\n", i4Policy); + return -1; + } + + DBGLOG(REQ, TRACE, "ucBssIdx[%hhu] ACL Policy=%d\n", ucBssIdx, + prBssInfo->rACL.ePolicy); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "ucBssIdx[%hhu] ACL Policy=%d\n", + ucBssIdx, prBssInfo->rACL.ePolicy); + + /* check if the change in ACL affects any existent association */ + if (prBssInfo->rACL.ePolicy != PARAM_CUSTOM_ACL_POLICY_DISABLE) + p2pRoleUpdateACLEntry(prAdapter, ucBssIdx); + + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + + return i4BytesWritten; +} /* priv_driver_set_acl_policy */ + +static int32_t priv_driver_inspect_mac_addr(IN char *pcMacAddr) +{ + int32_t i = 0; + + if (pcMacAddr == NULL) + return -1; + + for (i = 0; i < 17; i++) { + if ((i % 3 != 2) && (!kalIsXdigit(pcMacAddr[i]))) { + DBGLOG(REQ, ERROR, "[%c] is not hex digit\n", + pcMacAddr[i]); + return -1; + } + if ((i % 3 == 2) && (pcMacAddr[i] != ':')) { + DBGLOG(REQ, ERROR, "[%c]separate symbol is error\n", + pcMacAddr[i]); + return -1; + } + } + + if (pcMacAddr[17] != '\0') { + DBGLOG(REQ, ERROR, "no null-terminated character\n"); + return -1; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/* + * @ The function will add entry to ACL for accept or deny list. + * example: iwpriv p2p0 driver "add_acl_entry 01:02:03:04:05:06" + */ +/*----------------------------------------------------------------------------*/ +static int priv_driver_add_acl_entry(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct BSS_INFO *prBssInfo = NULL; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint8_t aucMacAddr[MAC_ADDR_LEN] = {0}; + int32_t i = 0, i4Argc = 0, i4BytesWritten = 0, i4Ret = 0; + uint8_t ucRoleIdx = 0, ucBssIdx = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + /* get Bss Index from ndev */ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prNetDev, &ucRoleIdx) != 0) + return -1; + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) + return -1; + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + DBGLOG(REQ, LOUD, "ucRoleIdx %hhu ucBssIdx %hhu\n", ucRoleIdx, + ucBssIdx); + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc < 2) + return -1; + + i4Ret = priv_driver_inspect_mac_addr(apcArgv[1]); + if (i4Ret) { + DBGLOG(REQ, ERROR, "inspect mac format error u4Ret=%d\n", + i4Ret); + return -1; + } + + i4Ret = sscanf(apcArgv[1], "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", + &aucMacAddr[0], &aucMacAddr[1], &aucMacAddr[2], + &aucMacAddr[3], &aucMacAddr[4], &aucMacAddr[5]); + + if (i4Ret != MAC_ADDR_LEN) { + DBGLOG(REQ, ERROR, "sscanf mac format fail u4Ret=%d\n", i4Ret); + return -1; + } + + for (i = 0; i <= prBssInfo->rACL.u4Num; i++) { + if (memcmp(prBssInfo->rACL.rEntry[i].aucAddr, &aucMacAddr, + MAC_ADDR_LEN) == 0) { + DBGLOG(REQ, ERROR, "add this mac [" MACSTR + "] is duplicate.\n", MAC2STR(aucMacAddr)); + return -1; + } + } + + if ((i < 1) || (i > MAX_NUMBER_OF_ACL)) { + DBGLOG(REQ, ERROR, "idx[%d] error or ACL is full.\n", i); + return -1; + } + + memcpy(prBssInfo->rACL.rEntry[i-1].aucAddr, &aucMacAddr, MAC_ADDR_LEN); + prBssInfo->rACL.u4Num = i; + DBGLOG(REQ, TRACE, "add mac addr [" MACSTR "] to ACL(%d).\n", + MAC2STR(prBssInfo->rACL.rEntry[i-1].aucAddr), i); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "add mac addr [" MACSTR "] to ACL(%d)\n", + MAC2STR(prBssInfo->rACL.rEntry[i-1].aucAddr), + i); + + /* Check if the change in ACL affects any existent association. */ + if (prBssInfo->rACL.ePolicy == PARAM_CUSTOM_ACL_POLICY_DENY) + p2pRoleUpdateACLEntry(prAdapter, ucBssIdx); + + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + + return i4BytesWritten; +} /* priv_driver_add_acl_entry */ + +/*----------------------------------------------------------------------------*/ +/* + * @ The function will delete entry to ACL for accept or deny list. + * example: iwpriv p2p0 driver "add_del_entry 01:02:03:04:05:06" + */ +/*----------------------------------------------------------------------------*/ +static int priv_driver_del_acl_entry(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct BSS_INFO *prBssInfo = NULL; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint8_t aucMacAddr[MAC_ADDR_LEN] = {0}; + int32_t i = 0, j = 0, i4Argc = 0, i4BytesWritten = 0, i4Ret = 0; + uint8_t ucRoleIdx = 0, ucBssIdx = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + /* get Bss Index from ndev */ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prNetDev, &ucRoleIdx) != 0) + return -1; + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) + return -1; + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + DBGLOG(REQ, LOUD, "ucRoleIdx %hhu ucBssIdx %hhu\n", ucRoleIdx, + ucBssIdx); + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc < 2) + return -1; + + i4Ret = priv_driver_inspect_mac_addr(apcArgv[1]); + if (i4Ret) { + DBGLOG(REQ, ERROR, "inspect mac format error u4Ret=%d\n", + i4Ret); + return -1; + } + + i4Ret = sscanf(apcArgv[1], "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", + &aucMacAddr[0], &aucMacAddr[1], &aucMacAddr[2], + &aucMacAddr[3], &aucMacAddr[4], &aucMacAddr[5]); + + if (i4Ret != MAC_ADDR_LEN) { + DBGLOG(REQ, ERROR, "sscanf mac format fail u4Ret=%d\n", i4Ret); + return -1; + } + + for (i = 0; i < prBssInfo->rACL.u4Num; i++) { + if (memcmp(prBssInfo->rACL.rEntry[i].aucAddr, &aucMacAddr, + MAC_ADDR_LEN) == 0) { + memset(&prBssInfo->rACL.rEntry[i], 0x00, + sizeof(struct PARAM_CUSTOM_ACL_ENTRY)); + DBGLOG(REQ, TRACE, "delete this mac [" MACSTR "]\n", + MAC2STR(aucMacAddr)); + + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "delete this mac [" MACSTR "] from ACL(%d)\n", + MAC2STR(aucMacAddr), i+1); + break; + } + } + + if ((prBssInfo->rACL.u4Num == 0) || (i == MAX_NUMBER_OF_ACL)) { + DBGLOG(REQ, ERROR, "delete entry fail, num of entries=%d\n", i); + return -1; + } + + for (j = i+1; j < prBssInfo->rACL.u4Num; j++) + memcpy(prBssInfo->rACL.rEntry[j-1].aucAddr, + prBssInfo->rACL.rEntry[j].aucAddr, MAC_ADDR_LEN); + + prBssInfo->rACL.u4Num = j-1; + memset(prBssInfo->rACL.rEntry[j-1].aucAddr, 0x00, MAC_ADDR_LEN); + + /* check if the change in ACL affects any existent association */ + if (prBssInfo->rACL.ePolicy == PARAM_CUSTOM_ACL_POLICY_ACCEPT) + p2pRoleUpdateACLEntry(prAdapter, ucBssIdx); + + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + + return i4BytesWritten; +} /* priv_driver_del_acl_entry */ + +/*----------------------------------------------------------------------------*/ +/* + * @ The function will show all entries to ACL for accept or deny list. + * example: iwpriv p2p0 driver "show_acl_entry" + */ +/*----------------------------------------------------------------------------*/ +static int priv_driver_show_acl_entry(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct BSS_INFO *prBssInfo = NULL; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + int32_t i = 0, i4Argc = 0, i4BytesWritten = 0; + uint8_t ucRoleIdx = 0, ucBssIdx = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + /* get Bss Index from ndev */ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prNetDev, &ucRoleIdx) != 0) + return -1; + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) + return -1; + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + DBGLOG(REQ, TRACE, "ACL Policy = %d\n", prBssInfo->rACL.ePolicy); + DBGLOG(REQ, TRACE, "Total ACLs = %d\n", prBssInfo->rACL.u4Num); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "ACL Policy = %d, Total ACLs = %d\n", + prBssInfo->rACL.ePolicy, + prBssInfo->rACL.u4Num); + + for (i = 0; i < prBssInfo->rACL.u4Num; i++) { + DBGLOG(REQ, TRACE, "ACL(%d): [" MACSTR "]\n", i+1, + MAC2STR(prBssInfo->rACL.rEntry[i].aucAddr)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "ACL(%d): [" MACSTR + "]\n", i+1, MAC2STR(prBssInfo->rACL.rEntry[i].aucAddr)); + } + + return i4BytesWritten; +} /* priv_driver_show_acl_entry */ + +/*----------------------------------------------------------------------------*/ +/* + * @ The function will clear all entries to ACL for accept or deny list. + * example: iwpriv p2p0 driver "clear_acl_entry" + */ +/*----------------------------------------------------------------------------*/ +static int priv_driver_clear_acl_entry(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct BSS_INFO *prBssInfo = NULL; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + int32_t i4Argc = 0, i4BytesWritten = 0; + uint8_t ucRoleIdx = 0, ucBssIdx = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + /* get Bss Index from ndev */ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prNetDev, &ucRoleIdx) != 0) + return -1; + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) + return -1; + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (prBssInfo->rACL.u4Num) { + memset(&prBssInfo->rACL.rEntry[0], 0x00, + sizeof(struct PARAM_CUSTOM_ACL_ENTRY) * MAC_ADDR_LEN); + prBssInfo->rACL.u4Num = 0; + } + + DBGLOG(REQ, TRACE, "ACL Policy = %d\n", prBssInfo->rACL.ePolicy); + DBGLOG(REQ, TRACE, "Total ACLs = %d\n", prBssInfo->rACL.u4Num); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "ACL Policy = %d, Total ACLs = %d\n", + prBssInfo->rACL.ePolicy, + prBssInfo->rACL.u4Num); + + /* check if the change in ACL affects any existent association */ + if (prBssInfo->rACL.ePolicy == PARAM_CUSTOM_ACL_POLICY_ACCEPT) + p2pRoleUpdateACLEntry(prAdapter, ucBssIdx); + + return i4BytesWritten; +} /* priv_driver_clear_acl_entry */ + +static int priv_driver_get_drv_mcr(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret; + + /* Add Antenna Selection Input */ + /* INT_32 i4ArgNum_with_ant_sel = 3; */ + + int32_t i4ArgNum = 2; + + struct CMD_ACCESS_REG rCmdAccessReg; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + rCmdAccessReg.u4Address = 0; + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rCmdAccessReg.u4Address)); + if (u4Ret) + DBGLOG(REQ, LOUD, + "parse get_drv_mcr error (Address) u4Ret=%d\n", + u4Ret); + + /* rCmdAccessReg.u4Address = kalStrtoul(apcArgv[1], NULL, 0); */ + rCmdAccessReg.u4Data = 0; + + DBGLOG(REQ, LOUD, "address is %x\n", rCmdAccessReg.u4Address); + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryDrvMcrRead, + &rCmdAccessReg, sizeof(rCmdAccessReg), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, "0x%08x", + (unsigned int)rCmdAccessReg.u4Data); + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, + pcCommand); + } + + return i4BytesWritten; + +} /* priv_driver_get_drv_mcr */ + +int priv_driver_set_drv_mcr(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Ret; + + /* Add Antenna Selection Input */ + /* INT_32 i4ArgNum_with_ant_sel = 4; */ + + int32_t i4ArgNum = 3; + + struct CMD_ACCESS_REG rCmdAccessReg; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rCmdAccessReg.u4Address)); + if (u4Ret) + DBGLOG(REQ, LOUD, + "parse get_drv_mcr error (Address) u4Ret=%d\n", + u4Ret); + + u4Ret = kalkStrtou32(apcArgv[2], 0, &(rCmdAccessReg.u4Data)); + if (u4Ret) + DBGLOG(REQ, LOUD, + "parse get_drv_mcr error (Data) u4Ret=%d\n", + u4Ret); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetDrvMcrWrite, + &rCmdAccessReg, sizeof(rCmdAccessReg), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + } + + return i4BytesWritten; + +} + +static int priv_driver_get_sw_ctrl(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + int32_t u4Ret = 0; + + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= 2) { + rSwCtrlInfo.u4Id = 0; + rSwCtrlInfo.u4Data = 0; + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rSwCtrlInfo.u4Id)); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse rSwCtrlInfo error u4Ret=%d\n", + u4Ret); + + DBGLOG(REQ, LOUD, "id is %x\n", rSwCtrlInfo.u4Id); + + rStatus = kalIoctl(prGlueInfo, wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, "0x%08x", + (unsigned int)rSwCtrlInfo.u4Data); + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, + pcCommand); + } + + return i4BytesWritten; + +} /* priv_driver_get_sw_ctrl */ + + +int priv_driver_set_sw_ctrl(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t u4Ret = 0; + + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= 3) { + /* rSwCtrlInfo.u4Id = kalStrtoul(apcArgv[1], NULL, 0); + * rSwCtrlInfo.u4Data = kalStrtoul(apcArgv[2], NULL, 0); + */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rSwCtrlInfo.u4Id)); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse rSwCtrlInfo error u4Ret=%d\n", + u4Ret); + u4Ret = kalkStrtou32(apcArgv[2], 0, &(rSwCtrlInfo.u4Data)); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse rSwCtrlInfo error u4Ret=%d\n", + u4Ret); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + } + + return i4BytesWritten; + +} /* priv_driver_set_sw_ctrl */ + + + +int priv_driver_set_fixed_rate(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + /* INT_32 u4Ret = 0; */ + uint32_t u4WCID = 0; + int32_t i4Recv = 0; + int8_t *this_char = NULL; + uint32_t u4Id = 0xa0610000; + uint32_t u4Id2 = 0xa0600000; + static uint8_t fgIsUseWCID = FALSE; + struct FIXED_RATE_INFO rFixedRate; + + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %d, apcArgv[0] = %s\n\n", i4Argc, *apcArgv); + + this_char = kalStrStr(*apcArgv, "="); + if (!this_char) + return -1; + this_char++; + kalMemZero(&rFixedRate, sizeof(struct FIXED_RATE_INFO)); + DBGLOG(REQ, LOUD, "string = %s\n", this_char); + + if (strnicmp(this_char, "auto", strlen("auto")) == 0) { + i4Recv = 1; + } else if (strnicmp(this_char, "UseWCID", strlen("UseWCID")) == 0) { + i4Recv = 2; + fgIsUseWCID = TRUE; + } else if (strnicmp(this_char, "ApplyAll", strlen("ApplyAll")) == 0) { + i4Recv = 3; + fgIsUseWCID = FALSE; + } else { + i4Recv = sscanf(this_char, + "%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d", + &(u4WCID), + &(rFixedRate.u4Mode), + &(rFixedRate.u4Bw), + &(rFixedRate.u4Mcs), + &(rFixedRate.u4VhtNss), + &(rFixedRate.u4SGI), + &(rFixedRate.u4Preamble), + &(rFixedRate.u4STBC), + &(rFixedRate.u4LDPC), + &(rFixedRate.u4SpeEn), + &(rFixedRate.u4HeLTF), + &(rFixedRate.u4HeErDCM), + &(rFixedRate.u4HeEr106t)); + + + DBGLOG(REQ, LOUD, "u4WCID=%d\nu4Mode=%d\nu4Bw=%d\n", u4WCID, + rFixedRate.u4Mode, rFixedRate.u4Bw); + DBGLOG(REQ, LOUD, "u4Mcs=%d\nu4VhtNss=%d\nu4GI=%d\n", + rFixedRate.u4Mcs, + rFixedRate.u4VhtNss, rFixedRate.u4SGI); + DBGLOG(REQ, LOUD, "u4Preamble=%d\nu4STBC=%d\n", + rFixedRate.u4Preamble, + rFixedRate.u4STBC); + DBGLOG(REQ, LOUD, "u4LDPC=%d\nu4SpeEn=%d\nu4HeLTF=%d\n", + rFixedRate.u4LDPC, rFixedRate.u4SpeEn, + rFixedRate.u4HeLTF); + DBGLOG(REQ, LOUD, "u4HeErDCM=%d\nu4HeEr106t=%d\n", + rFixedRate.u4HeErDCM, rFixedRate.u4HeEr106t); + DBGLOG(REQ, LOUD, "fgIsUseWCID=%d\n", fgIsUseWCID); + } + + if (i4Recv == 1) { + rSwCtrlInfo.u4Id = u4Id2; + rSwCtrlInfo.u4Data = 0; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } else if (i4Recv == 2 || i4Recv == 3) { + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, + "Update fgIsUseWCID %d\n", fgIsUseWCID); + } else if (i4Recv == 10 || i4Recv == 13) { + rSwCtrlInfo.u4Id = u4Id; + if (fgIsUseWCID && u4WCID < prAdapter->ucWtblEntryNum && + prAdapter->rWifiVar.arWtbl[u4WCID].ucUsed) { + rSwCtrlInfo.u4Id |= u4WCID; + rSwCtrlInfo.u4Id |= BIT(8); + i4BytesWritten = kalSnprintf( + pcCommand, i4TotalLen, + "Apply WCID %d\n", u4WCID); + } else { + i4BytesWritten = kalSnprintf( + pcCommand, i4TotalLen, "Apply All\n"); + } + + if (rFixedRate.u4Mode >= TX_RATE_MODE_HE_SU) { + if (i4Recv == 10) { + /* Give default value */ + rFixedRate.u4HeLTF = HE_LTF_4X; + rFixedRate.u4HeErDCM = 0; + rFixedRate.u4HeEr106t = 0; + } + /* check HE-LTF and HE GI combinations */ + rStatus = nicRateHeLtfCheckGi(&rFixedRate); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } + + rStatus = nicSetFixedRateData(&rFixedRate, &rSwCtrlInfo.u4Data); + + if (rStatus == WLAN_STATUS_SUCCESS) { + rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + FALSE, FALSE, TRUE, &u4BufLen); + } + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } else { + DBGLOG(REQ, ERROR, "iwpriv wlanXX driver FixedRate=Option\n"); + DBGLOG(REQ, ERROR, "Option support 10 or 13 parameters\n"); + DBGLOG(REQ, ERROR, + "Option:[WCID]-[Mode]-[BW]-[MCS]-[VhtHeNss]-[GI]-[Preamble]-[STBC]-[LDPC]-[SPE_EN]\n"); + DBGLOG(REQ, ERROR, + "13 param support another [HE-LTF]-[HE-ER-DCM]-[HE-ER-106]\n"); + DBGLOG(REQ, ERROR, "[WCID]Wireless Client ID\n"); + DBGLOG(REQ, ERROR, "[Mode]CCK=0, OFDM=1, HT=2, GF=3, VHT=4"); + DBGLOG(REQ, ERROR, + "PLR=5, HE_SU=8, HE_ER_SU=9, HE_TRIG=10, HE_MU=11\n"); + DBGLOG(REQ, ERROR, "[BW]BW20=0, BW40=1, BW80=2,BW160=3\n"); + DBGLOG(REQ, ERROR, + "[MCS]CCK=0~3, OFDM=0~7, HT=0~32, VHT=0~9, HE=0~11\n"); + DBGLOG(REQ, ERROR, "[VhtHeNss]1~8, Other=ignore\n"); + DBGLOG(REQ, ERROR, "[GI]HT/VHT: 0:Long, 1:Short, "); + DBGLOG(REQ, ERROR, + "HE: SGI=0(0.8us), MGI=1(1.6us), LGI=2(3.2us)\n"); + DBGLOG(REQ, ERROR, "[Preamble]Long=0, Other=Short\n"); + DBGLOG(REQ, ERROR, "[STBC]Enable=1, Disable=0\n"); + DBGLOG(REQ, ERROR, "[LDPC]BCC=0, LDPC=1\n"); + DBGLOG(REQ, ERROR, "[HE-LTF]1X=0, 2X=1, 4X=2\n"); + DBGLOG(REQ, ERROR, "[HE-ER-DCM]Enable=1, Disable=0\n"); + DBGLOG(REQ, ERROR, "[HE-ER-106]106-tone=1\n"); + } + + return i4BytesWritten; +} /* priv_driver_set_fixed_rate */ + +int priv_driver_set_em_cfg(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4CfgSetNum = 0, u4Ret = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4BufLen; + + struct PARAM_CUSTOM_KEY_CFG_STRUCT rKeyCfgInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + prAdapter = prGlueInfo->prAdapter; + if (prAdapter == NULL) + return -1; /* WLAN_STATUS_ADAPTER_NOT_READY */ + + kalMemZero(&rKeyCfgInfo, sizeof(rKeyCfgInfo)); + + wlanCleanAllEmCfgSetting(prAdapter); + + + if (i4Argc >= 3) { + + uint8_t i = 0; + + u4Ret = kalkStrtou32(apcArgv[1], 10, &u4CfgSetNum); + + if (u4Ret != 0) { + DBGLOG(REQ, ERROR, + "apcArgv[2] format fail erro code:%d\n", + u4Ret); + return -1; + } + + if (u4CfgSetNum*2 > i4Argc) { + DBGLOG(REQ, ERROR, + "Set Num(%d) over input arg num(%d)\n", + u4CfgSetNum, i4Argc); + return -1; + } + + DBGLOG(REQ, INFO, "Total Cfg Num=%d\n", u4CfgSetNum); + + for (i = 0; i < (u4CfgSetNum*2); i += 2) { + + kalStrnCpy(rKeyCfgInfo.aucKey, apcArgv[2+i], + WLAN_CFG_KEY_LEN_MAX - 1); + kalStrnCpy(rKeyCfgInfo.aucValue, apcArgv[2+(i+1)], + WLAN_CFG_VALUE_LEN_MAX - 1); + rKeyCfgInfo.u4Flag = WLAN_CFG_EM; + + DBGLOG(REQ, INFO, + "Update to driver EM CFG [%s]:[%s],OP:%d\n", + rKeyCfgInfo.aucKey, + rKeyCfgInfo.aucValue, + rKeyCfgInfo.u4Flag); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetKeyCfg, + &rKeyCfgInfo, + sizeof(rKeyCfgInfo), + FALSE, + FALSE, + TRUE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + + } + + } + + return i4BytesWritten; + +} /* priv_driver_set_cfg_em */ + +int priv_driver_get_em_cfg(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + struct WLAN_CFG_ENTRY *prWlanCfgEntry; + int32_t i = 0; + uint32_t u4Offset = 0; + uint32_t u4CfgNum = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, INFO, + "command is %s, i4TotalLen=%d\n", + pcCommand, + i4TotalLen); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, INFO, "argc is %i\n", i4Argc); + prAdapter = prGlueInfo->prAdapter; + + if (i4Argc >= 1) { + + u4CfgNum = wlanCfgGetTotalCfgNum(prAdapter, WLAN_CFG_EM); + + DBGLOG(REQ, INFO, + "Total cfg Num:%d\n", u4CfgNum); + + u4Offset += snprintf(pcCommand + u4Offset, + (i4TotalLen - u4Offset), + "%d,", + u4CfgNum); + + for (i = 0; i < u4CfgNum; i++) { + prWlanCfgEntry = wlanCfgGetEntryByIndex( + prAdapter, + i, + WLAN_CFG_EM); + + if ((!prWlanCfgEntry) + || (prWlanCfgEntry->aucKey[0] == '\0')) + break; + + DBGLOG(REQ, INFO, + "cfg dump:(%s,%s)\n", + prWlanCfgEntry->aucKey, + prWlanCfgEntry->aucValue); + + if (u4Offset >= i4TotalLen) { + DBGLOG(REQ, ERROR, + "out of bound\n"); + break; + } + + u4Offset += snprintf(pcCommand + u4Offset, + (i4TotalLen - u4Offset), + "%s,%s,", + prWlanCfgEntry->aucKey, + prWlanCfgEntry->aucValue); + + } + + pcCommand[u4Offset-1] = '\n'; + pcCommand[u4Offset] = '\0'; + + } + + return (int32_t)u4Offset; + +} /* priv_driver_get_cfg_em */ + + +int priv_driver_set_cfg(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + + struct PARAM_CUSTOM_KEY_CFG_STRUCT rKeyCfgInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + prAdapter = prGlueInfo->prAdapter; + if (prAdapter == NULL) + return -1; /* WLAN_STATUS_ADAPTER_NOT_READY */ + + kalMemZero(&rKeyCfgInfo, sizeof(rKeyCfgInfo)); + + if (i4Argc >= 3) { + + int8_t ucTmp[WLAN_CFG_VALUE_LEN_MAX]; + uint8_t *pucCurrBuf = ucTmp; + uint8_t i = 0; + uint32_t offset = 0; + + pucCurrBuf = ucTmp; + kalMemZero(ucTmp, WLAN_CFG_VALUE_LEN_MAX); + + if (i4Argc == 3) { + /* no space for it, driver can't accept space in the end + * of the line + */ + /* ToDo: skip the space when parsing */ + u4BufLen = kalStrLen(apcArgv[2]); + if (offset + u4BufLen > WLAN_CFG_VALUE_LEN_MAX - 1) { + DBGLOG(INIT, ERROR, + "apcArgv[2] length [%d] overrun\n", + u4BufLen); + return -1; + } + kalStrnCpy(pucCurrBuf + offset, apcArgv[2], u4BufLen); + offset += u4BufLen; + } else { + for (i = 2; i < i4Argc; i++) { + u4BufLen = kalStrLen(apcArgv[i]); + if (offset + u4BufLen > + WLAN_CFG_VALUE_LEN_MAX - 1) { + DBGLOG(INIT, ERROR, + "apcArgv[%d] length [%d] overrun\n", + i, u4BufLen); + return -1; + } + kalStrnCpy(pucCurrBuf + offset, apcArgv[i], + u4BufLen); + offset += u4BufLen; + } + } + + DBGLOG(INIT, WARN, "Update to driver temp buffer as [%s]\n", + ucTmp); + + /* wlanCfgSet(prAdapter, apcArgv[1], apcArgv[2], 0); */ + /* Call by wlanoid because the set_cfg will trigger callback */ + kalStrnCpy(rKeyCfgInfo.aucKey, apcArgv[1], + WLAN_CFG_KEY_LEN_MAX - 1); + kalStrnCpy(rKeyCfgInfo.aucValue, ucTmp, + WLAN_CFG_VALUE_LEN_MAX - 1); + + rKeyCfgInfo.u4Flag = WLAN_CFG_DEFAULT; + rStatus = kalIoctl(prGlueInfo, wlanoidSetKeyCfg, &rKeyCfgInfo, + sizeof(rKeyCfgInfo), FALSE, FALSE, TRUE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } + + return i4BytesWritten; + +} /* priv_driver_set_cfg */ + +int priv_driver_get_cfg(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int8_t aucValue[WLAN_CFG_VALUE_LEN_MAX]; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + prAdapter = prGlueInfo->prAdapter; + + if (i4Argc >= 2) { + /* by wlanoid ? */ + if (wlanCfgGet(prAdapter, apcArgv[1], aucValue, "", 0) == + WLAN_STATUS_SUCCESS) { + kalStrnCpy(pcCommand, aucValue, WLAN_CFG_VALUE_LEN_MAX); + i4BytesWritten = kalStrnLen(pcCommand, + WLAN_CFG_VALUE_LEN_MAX); + } + } + + return i4BytesWritten; + +} /* priv_driver_get_cfg */ + +int priv_driver_set_chip_config(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + uint32_t u4CmdLen = 0; + uint32_t u4PrefixLen = 0; + /* INT_32 i4Argc = 0; */ + /* PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = {0}; */ + + struct PARAM_CUSTOM_CHIP_CONFIG_STRUCT rChipConfigInfo = {0}; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + if ((!prGlueInfo) || + (prGlueInfo->u4ReadyFlag == 0) || + kalIsResetting()) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -1; + } + + prAdapter = prGlueInfo->prAdapter; + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + /* wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); */ + /* DBGLOG(REQ, LOUD,("argc is %i\n",i4Argc)); */ + /* */ + u4CmdLen = kalStrnLen(pcCommand, i4TotalLen); + u4PrefixLen = kalStrLen(CMD_SET_CHIP) + 1 /*space */; + + kalMemZero(&rChipConfigInfo, sizeof(rChipConfigInfo)); + + /* if(i4Argc >= 2) { */ + if (u4CmdLen > u4PrefixLen) { + rChipConfigInfo.ucType = CHIP_CONFIG_TYPE_WO_RESPONSE; + /* rChipConfigInfo.u2MsgSize = kalStrnLen(apcArgv[1], + * CHIP_CONFIG_RESP_SIZE); + */ + rChipConfigInfo.u2MsgSize = u4CmdLen - u4PrefixLen; + /* kalStrnCpy(rChipConfigInfo.aucCmd, apcArgv[1], + * CHIP_CONFIG_RESP_SIZE); + */ + kalStrnCpy(rChipConfigInfo.aucCmd, pcCommand + u4PrefixLen, + CHIP_CONFIG_RESP_SIZE - 1); + rChipConfigInfo.aucCmd[CHIP_CONFIG_RESP_SIZE - 1] = '\0'; + +#if (CFG_SUPPORT_802_11AX == 1) + if (kalStrnCmp("FrdHeTrig2Host", + pcCommand, kalStrLen("FrdHeTrig2Host"))) { + uint32_t idx = kalStrLen("set_chip FrdHeTrig2Host "); + + prAdapter->fgEnShowHETrigger = pcCommand[idx] - 0x30; + DBGLOG(REQ, STATE, "set flag fgEnShowHETrigger:%x\n", + prAdapter->fgEnShowHETrigger); + } +#endif /* CFG_SUPPORT_802_11AX == 1 */ + + rStatus = kalIoctl(prGlueInfo, wlanoidSetChipConfig, + &rChipConfigInfo, sizeof(rChipConfigInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, INFO, "%s: kalIoctl ret=%d\n", __func__, + rStatus); + i4BytesWritten = -1; + } + } + + return i4BytesWritten; + +} /* priv_driver_set_chip_config */ + +void +priv_driver_get_chip_config_16(uint8_t *pucStartAddr, uint32_t u4Length, + uint32_t u4Line, int i4TotalLen, + int32_t i4BytesWritten, char *pcCommand) +{ + + while (u4Length >= 16) { + if (i4TotalLen > i4BytesWritten) { + i4BytesWritten += + kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%04x %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x %02x %02x %02x\n", + u4Line, 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]); + } + + pucStartAddr += 16; + u4Length -= 16; + u4Line += 16; + } /* u4Length */ +} + + +void +priv_driver_get_chip_config_4(uint32_t *pu4StartAddr, uint32_t u4Length, + uint32_t u4Line, int i4TotalLen, + int32_t i4BytesWritten, char *pcCommand) +{ + while (u4Length >= 16) { + if (i4TotalLen > i4BytesWritten) { + i4BytesWritten += + kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%04x %08x %08x %08x %08x\n", u4Line, + pu4StartAddr[0], pu4StartAddr[1], + pu4StartAddr[2], pu4StartAddr[3]); + } + + pu4StartAddr += 4; + u4Length -= 16; + u4Line += 4; + } /* u4Length */ +} + +int priv_driver_get_chip_config(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + int32_t i4BytesWritten = 0; + uint32_t u4BufLen = 0; + uint32_t u2MsgSize = 0; + uint32_t u4CmdLen = 0; + uint32_t u4PrefixLen = 0; + /* INT_32 i4Argc = 0; */ + /* PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; */ + + struct PARAM_CUSTOM_CHIP_CONFIG_STRUCT rChipConfigInfo = {0}; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + /* wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); */ + /* DBGLOG(REQ, LOUD,("argc is %i\n",i4Argc)); */ + + u4CmdLen = kalStrnLen(pcCommand, i4TotalLen); + u4PrefixLen = kalStrLen(CMD_GET_CHIP) + 1 /*space */; + + /* if(i4Argc >= 2) { */ + if (u4CmdLen > u4PrefixLen) { + rChipConfigInfo.ucType = CHIP_CONFIG_TYPE_ASCII; + /* rChipConfigInfo.u2MsgSize = kalStrnLen(apcArgv[1], + * CHIP_CONFIG_RESP_SIZE); + */ + rChipConfigInfo.u2MsgSize = u4CmdLen - u4PrefixLen; + /* kalStrnCpy(rChipConfigInfo.aucCmd, apcArgv[1], + * CHIP_CONFIG_RESP_SIZE); + */ + kalStrnCpy(rChipConfigInfo.aucCmd, pcCommand + u4PrefixLen, + CHIP_CONFIG_RESP_SIZE - 1); + rChipConfigInfo.aucCmd[CHIP_CONFIG_RESP_SIZE - 1] = '\0'; + rStatus = kalIoctl(prGlueInfo, wlanoidQueryChipConfig, + &rChipConfigInfo, sizeof(rChipConfigInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, INFO, "%s: kalIoctl ret=%d\n", __func__, + rStatus); + return -1; + } + + /* Check respType */ + u2MsgSize = rChipConfigInfo.u2MsgSize; + DBGLOG(REQ, INFO, "%s: RespTyep %u\n", __func__, + rChipConfigInfo.ucRespType); + DBGLOG(REQ, INFO, "%s: u2MsgSize %u\n", __func__, + rChipConfigInfo.u2MsgSize); + + if (u2MsgSize > sizeof(rChipConfigInfo.aucCmd)) { + DBGLOG(REQ, INFO, "%s: u2MsgSize error ret=%u\n", + __func__, rChipConfigInfo.u2MsgSize); + return -1; + } + + if (u2MsgSize > 0) { + + if (rChipConfigInfo.ucRespType == + CHIP_CONFIG_TYPE_ASCII) { + i4BytesWritten = + kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen, "%s", + rChipConfigInfo.aucCmd); + } else { + uint32_t u4Length; + uint32_t u4Line; + + if (rChipConfigInfo.ucRespType == + CHIP_CONFIG_TYPE_MEM8) { + uint8_t *pucStartAddr = NULL; + + pucStartAddr = (uint8_t *) + rChipConfigInfo.aucCmd; + /* align 16 bytes because one print line + * is 16 bytes + */ + u4Length = (((u2MsgSize + 15) >> 4)) + << 4; + u4Line = 0; + priv_driver_get_chip_config_16( + pucStartAddr, u4Length, u4Line, + i4TotalLen, i4BytesWritten, + pcCommand); + } else { + uint32_t *pu4StartAddr = NULL; + + pu4StartAddr = (uint32_t *) + rChipConfigInfo.aucCmd; + /* align 16 bytes because one print line + * is 16 bytes + */ + u4Length = (((u2MsgSize + 15) >> 4)) + << 4; + u4Line = 0; + + if (IS_ALIGN_4( + (unsigned long) pu4StartAddr)) { + priv_driver_get_chip_config_4( + pu4StartAddr, u4Length, + u4Line, i4TotalLen, + i4BytesWritten, + pcCommand); + } else { + DBGLOG(REQ, INFO, + "%s: rChipConfigInfo.aucCmd is not 4 bytes alignment %p\n", + __func__, + rChipConfigInfo.aucCmd); + } + } /* ChipConfigInfo.ucRespType */ + } + } + /* u2MsgSize > 0 */ + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, + pcCommand); + } + /* i4Argc */ + return i4BytesWritten; + +} /* priv_driver_get_chip_config */ + + + +int priv_driver_set_ap_start(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + + struct PARAM_CUSTOM_P2P_SET_STRUCT rSetP2P; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Ret; + int32_t i4ArgNum = 2; + + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rSetP2P.u4Mode)); + if (u4Ret) + DBGLOG(REQ, LOUD, + "parse ap-start error (u4Enable) u4Ret=%d\n", + u4Ret); + + if (rSetP2P.u4Mode >= RUNNING_P2P_MODE_NUM) { + rSetP2P.u4Mode = 0; + rSetP2P.u4Enable = 0; + } else + rSetP2P.u4Enable = 1; + + set_p2p_mode_handler(prNetDev, rSetP2P); + } + + return 0; +} + +int priv_driver_get_linkspeed(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_LINK_SPEED_EX rLinkSpeed; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + uint32_t u4Rate = 0; + int32_t i4BytesWritten = 0; + uint8_t ucBssIndex = AIS_DEFAULT_INDEX; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ucBssIndex = wlanGetBssIdx(prNetDev); + + if (!netif_carrier_ok(prNetDev)) + return -1; + + if (ucBssIndex >= BSSID_NUM) + return -EFAULT; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryLinkSpeedEx, + &rLinkSpeed, sizeof(rLinkSpeed), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + u4Rate = rLinkSpeed.rLq[ucBssIndex].u2LinkSpeed; + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, "LinkSpeed %u", + (unsigned int)(u4Rate * 100)); + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + return i4BytesWritten; + +} /* priv_driver_get_linkspeed */ + +int priv_driver_set_band(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct ADAPTER *prAdapter = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Argc = 0; + uint32_t ucBand = 0; + enum ENUM_BAND eBand = BAND_NULL; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + int32_t u4Ret = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + prAdapter = prGlueInfo->prAdapter; + if (i4Argc >= 2) { + /* ucBand = kalStrtoul(apcArgv[1], NULL, 0); */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &ucBand); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse ucBand error u4Ret=%d\n", + u4Ret); + + eBand = BAND_NULL; + if (ucBand == CMD_BAND_TYPE_5G) + eBand = BAND_5G; + else if (ucBand == CMD_BAND_TYPE_2G) + eBand = BAND_2G4; + prAdapter->aePreferBand[KAL_NETWORK_TYPE_AIS_INDEX] = eBand; + /* XXX call wlanSetPreferBandByNetwork directly in different + * thread + */ + /* wlanSetPreferBandByNetwork (prAdapter, eBand, ucBssIndex); */ + } + + return 0; +} + + +int priv_driver_set_country(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint8_t aucCountry[2]; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (regd_is_single_sku_en()) { + uint8_t aucCountry_code[4] = {0, 0, 0, 0}; + uint8_t i, count; + + /* command like "COUNTRY US", "COUNTRY US1" and + * "COUNTRY US01" + */ + count = kalStrnLen(apcArgv[1], sizeof(aucCountry_code)); + for (i = 0; i < count; i++) + aucCountry_code[i] = apcArgv[1][i]; + + + rStatus = kalIoctl(prGlueInfo, wlanoidSetCountryCode, + &aucCountry_code[0], count, + FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + return 0; + } + + + if (i4Argc >= 2) { + /* command like "COUNTRY US", "COUNTRY EU" and "COUNTRY JP" */ + aucCountry[0] = apcArgv[1][0]; + aucCountry[1] = apcArgv[1][1]; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetCountryCode, + &aucCountry[0], 2, FALSE, FALSE, TRUE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } + return 0; +} + +int priv_driver_set_csa(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t ch_num = 0; + uint32_t u4Ret = 0; + uint8_t ucRoleIdx = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prNetDev, &ucRoleIdx) != 0) + return -1; + + DBGLOG(REQ, INFO, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, INFO, "argc is %i\n", i4Argc); + + if (i4Argc >= 2) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &ch_num); + u4Ret = cnmIdcCsaReq(prGlueInfo->prAdapter, ch_num, ucRoleIdx); + DBGLOG(REQ, INFO, "u4Ret is %d\n", u4Ret); + } else { + DBGLOG(REQ, INFO, "Input insufficent\n"); + } + + return 0; +} + +int priv_driver_get_country(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t i4BytesWritten = 0; + uint32_t country = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (!regd_is_single_sku_en()) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "Not Supported."); + return i4BytesWritten; + } + + country = rlmDomainGetCountryCode(); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nCountry Code: (0x%x)", + country); + + return i4BytesWritten; +} + +int priv_driver_get_channels(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + uint32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; +#if (CFG_SUPPORT_SINGLE_SKU == 1) + uint32_t ch_idx, start_idx, end_idx; + struct CMD_DOMAIN_CHANNEL *pCh; + uint32_t ch_num = 0; + uint8_t maxbw = 160; + uint32_t u4Ret = 0; +#endif + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (!regd_is_single_sku_en()) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "Not Supported."); + return i4BytesWritten; + } + +#if (CFG_SUPPORT_SINGLE_SKU == 1) + /** + * Usage: iwpriv wlan0 driver "get_channels [2g |5g |ch_num]" + **/ + if (i4Argc >= 2 && (apcArgv[1][0] == '2') && (apcArgv[1][1] == 'g')) { + start_idx = 0; + end_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + } else if (i4Argc >= 2 && (apcArgv[1][0] == '5') && + (apcArgv[1][1] == 'g')) { + start_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + end_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ) + + rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ); + } else { + start_idx = 0; + end_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ) + + rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ); + if (i4Argc >= 2) + /* Dump only specified channel */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &ch_num); + } + + if (regd_is_single_sku_en()) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\n"); + + for (ch_idx = start_idx; ch_idx < end_idx; ch_idx++) { + + pCh = (rlmDomainGetActiveChannels() + ch_idx); + + if (ch_num && (ch_num != pCh->u2ChNum)) + continue; /*show specific channel information*/ + + /* Channel number */ + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "CH-%d:", + pCh->u2ChNum); + + /* Active/Passive */ + if (pCh->eFlags & IEEE80211_CHAN_PASSIVE_FLAG) { + /* passive channel */ + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + " " IEEE80211_CHAN_PASSIVE_STR); + } else + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + " ACTIVE"); + + /* Max BW */ + if ((pCh->eFlags & IEEE80211_CHAN_NO_160MHZ) == + IEEE80211_CHAN_NO_160MHZ) + maxbw = 80; + if ((pCh->eFlags & IEEE80211_CHAN_NO_80MHZ) == + IEEE80211_CHAN_NO_80MHZ) + maxbw = 40; + if ((pCh->eFlags & IEEE80211_CHAN_NO_HT40) == + IEEE80211_CHAN_NO_HT40) + maxbw = 20; + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + " BW_%dMHz", maxbw); + /* Channel flags */ + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + " (flags=0x%x)\n", pCh->eFlags); + } + } +#endif + + return i4BytesWritten; +} + +#if (CFG_SUPPORT_DFS_MASTER == 1) +int priv_driver_show_dfs_state(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + int32_t i4BytesWritten = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nDFS State: \"%s\"", + p2pFuncShowDfsState()); + + return i4BytesWritten; +} + +int priv_driver_show_dfs_radar_param(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + int32_t i4BytesWritten = 0; + uint8_t ucCnt = 0; + struct P2P_RADAR_INFO *prP2pRadarInfo = (struct P2P_RADAR_INFO *) NULL; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + prP2pRadarInfo = (struct P2P_RADAR_INFO *) cnmMemAlloc( + prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(*prP2pRadarInfo)); + if (prP2pRadarInfo == NULL) + return -1; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + p2pFuncGetRadarInfo(prP2pRadarInfo); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nRDD idx: %d\n", + prP2pRadarInfo->ucRddIdx); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nLong Pulse detected: %d\n", prP2pRadarInfo->ucLongDetected); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nPeriodic Pulse detected: %d\n", + prP2pRadarInfo->ucPeriodicDetected); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nLPB Num: %d\n", + prP2pRadarInfo->ucLPBNum); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nPPB Num: %d\n", + prP2pRadarInfo->ucPPBNum); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n==========================="); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nLong Pulse Buffer Contents:\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\npulse_time pulse_width PRI\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\n%-10d %-11d -\n" + , prP2pRadarInfo->arLpbContent[ucCnt].u4LongStartTime + , prP2pRadarInfo->arLpbContent[ucCnt].u2LongPulseWidth); + for (ucCnt = 1; ucCnt < prP2pRadarInfo->ucLPBNum; ucCnt++) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n%-10d %-11d %d\n", + prP2pRadarInfo->arLpbContent[ucCnt].u4LongStartTime, + prP2pRadarInfo->arLpbContent[ucCnt].u2LongPulseWidth, + (prP2pRadarInfo->arLpbContent[ucCnt].u4LongStartTime + - prP2pRadarInfo->arLpbContent[ucCnt-1] + .u4LongStartTime) * 2 / 5); + } + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nLPB Period Valid: %d", prP2pRadarInfo->ucLPBPeriodValid); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nLPB Period Valid: %d\n", prP2pRadarInfo->ucLPBWidthValid); + + ucCnt = 0; + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n==========================="); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nPeriod Pulse Buffer Contents:\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\npulse_time pulse_width PRI\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\n%-10d %-11d -\n" + , prP2pRadarInfo->arPpbContent[ucCnt].u4PeriodicStartTime + , prP2pRadarInfo->arPpbContent[ucCnt].u2PeriodicPulseWidth); + for (ucCnt = 1; ucCnt < prP2pRadarInfo->ucPPBNum; ucCnt++) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n%-10d %-11d %d\n" + , prP2pRadarInfo->arPpbContent[ucCnt].u4PeriodicStartTime + , prP2pRadarInfo->arPpbContent[ucCnt] + .u2PeriodicPulseWidth + , (prP2pRadarInfo->arPpbContent[ucCnt] + .u4PeriodicStartTime + - prP2pRadarInfo->arPpbContent[ucCnt-1] + .u4PeriodicStartTime) * 2 / 5); + } + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nPRI Count M1 TH: %d; PRI Count M1: %d", + prP2pRadarInfo->ucPRICountM1TH, prP2pRadarInfo->ucPRICountM1); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nPRI Count M2 TH: %d; PRI Count M2: %d", + prP2pRadarInfo->ucPRICountM2TH, + prP2pRadarInfo->ucPRICountM2); + + + cnmMemFree(prGlueInfo->prAdapter, prP2pRadarInfo); + + return i4BytesWritten; +} + +int priv_driver_show_dfs_help(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + int32_t i4BytesWritten = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n--iwpriv wlanX driver \"show_dfs_state\"\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nINACTIVE: RDD disable or temporary RDD disable"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nCHECKING: During CAC time"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nACTIVE : In-serive monitoring"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nDETECTED: Has detected radar but hasn't moved to new channel\n"); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n--iwpriv wlanX driver \"show_dfs_radar_param\"\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nShow the latest pulse information\n"); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n--iwpriv wlanX driver \"show_dfs_cac_time\"\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nShow the remaining time of CAC\n"); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n--iwpriv wlanX set ByPassCac=yy\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nValue yy: set the time of CAC\n"); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n--iwpriv wlanX set RDDReport=yy\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nValue yy is \"0\" or \"1\""); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n\"0\": Emulate RDD0 manual radar event"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n\"1\": Emulate RDD1 manual radar event\n"); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n--iwpriv wlanX set RadarDetectMode=yy\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nValue yy is \"0\" or \"1\""); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n\"0\": Switch channel when radar detected (default)"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n\"1\": Do not switch channel when radar detected"); + + return i4BytesWritten; +} + +int priv_driver_show_dfs_cac_time(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + int32_t i4BytesWritten = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (p2pFuncGetDfsState() != DFS_STATE_CHECKING) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nNot in CAC period"); + return i4BytesWritten; + } + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nRemaining time of CAC: %dsec", p2pFuncGetCacRemainingTime()); + + return i4BytesWritten; +} + +#endif +int priv_driver_set_miracast(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + + struct ADAPTER *prAdapter = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t i4BytesWritten = 0; + /* WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; */ + /* UINT_32 u4BufLen = 0; */ + int32_t i4Argc = 0; + uint32_t ucMode = 0; + struct WFD_CFG_SETTINGS *prWfdCfgSettings = + (struct WFD_CFG_SETTINGS *) NULL; + struct MSG_WFD_CONFIG_SETTINGS_CHANGED *prMsgWfdCfgUpdate = + (struct MSG_WFD_CONFIG_SETTINGS_CHANGED *) NULL; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + int32_t u4Ret = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + prAdapter = prGlueInfo->prAdapter; + if (i4Argc >= 2) { + /* ucMode = kalStrtoul(apcArgv[1], NULL, 0); */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &ucMode); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse ucMode error u4Ret=%d\n", + u4Ret); + + if (g_ucMiracastMode == (uint8_t) ucMode) { + /* XXX: continue or skip */ + /* XXX: continue or skip */ + } + + g_ucMiracastMode = (uint8_t) ucMode; + prMsgWfdCfgUpdate = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_WFD_CONFIG_SETTINGS_CHANGED)); + + if (prMsgWfdCfgUpdate != NULL) { + + prWfdCfgSettings = + &(prAdapter->rWifiVar.rWfdConfigureSettings); + prMsgWfdCfgUpdate->rMsgHdr.eMsgId = + MID_MNY_P2P_WFD_CFG_UPDATE; + prMsgWfdCfgUpdate->prWfdCfgSettings = prWfdCfgSettings; + + if (ucMode == MIRACAST_MODE_OFF) { + prWfdCfgSettings->ucWfdEnable = 0; + kalSnprintf(pcCommand, i4TotalLen, + CMD_SET_CHIP " mira 0"); + } else if (ucMode == MIRACAST_MODE_SOURCE) { + prWfdCfgSettings->ucWfdEnable = 1; + kalSnprintf(pcCommand, i4TotalLen, + CMD_SET_CHIP " mira 1"); + } else if (ucMode == MIRACAST_MODE_SINK) { + prWfdCfgSettings->ucWfdEnable = 2; + kalSnprintf(pcCommand, i4TotalLen, + CMD_SET_CHIP " mira 2"); + } else { + prWfdCfgSettings->ucWfdEnable = 0; + kalSnprintf(pcCommand, i4TotalLen, + CMD_SET_CHIP " mira 0"); + } + + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *) + prMsgWfdCfgUpdate, MSG_SEND_METHOD_BUF); + + priv_driver_set_chip_config(prNetDev, pcCommand, + i4TotalLen); + } /* prMsgWfdCfgUpdate */ + else { + ASSERT(FALSE); + i4BytesWritten = -1; + } + } + + /* i4Argc */ + return i4BytesWritten; +} + +int parseValueInString( + IN char **pcCommand, + IN const char *acDelim, + IN void *aucValue, + IN int u4MaxLen) +{ + uint8_t *pcPtr; + uint32_t u4Len; + uint8_t *pucValueHead = NULL; + uint8_t *pucValueTail = NULL; + + if (*pcCommand + && !kalStrnCmp(*pcCommand, acDelim, kalStrLen(acDelim))) { + pcPtr = kalStrSep(pcCommand, "=,"); + pucValueHead = *pcCommand; + pcPtr = kalStrSep(pcCommand, "=,"); + DBGLOG(REQ, TRACE, "pucValueHead = %s\n", pucValueHead); + if (pucValueHead) { + u4Len = kalStrLen(pucValueHead); + if (*pcCommand) { + pucValueTail = *pcCommand - 1; + u4Len = pucValueTail - pucValueHead; + } + if (u4Len > u4MaxLen) + u4Len = u4MaxLen; + + /* MAC */ + if (!kalStrnCmp(acDelim, "MAC=", kalStrLen(acDelim))) { + u8 *addr = aucValue; + + wlanHwAddrToBin(pucValueHead, addr); + DBGLOG(REQ, TRACE, "MAC type"); + } else { + u8 *addr = aucValue; + + kalStrnCpy(addr, pucValueHead, u4Len); + *((char *)aucValue + u4Len) = '\0'; + DBGLOG(REQ, TRACE, + "STR type = %s\n", (char *)aucValue); + } + return 0; + } + } + + return -1; +} + +int priv_driver_set_ap_set_mac_acl(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct BSS_INFO *prBssInfo = NULL; + uint8_t aucValue[WLAN_CFG_ARGV_MAX] = {0}; + uint8_t ucRoleIdx = 0, ucBssIdx = 0; + int32_t i4BytesWritten = 0; + int32_t i4Count = 0, i4Mode = 0; + int i = 0; + + DBGLOG(REQ, INFO, "command is %s\n", pcCommand); + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + goto error; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + /* get Bss Index from ndev */ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prNetDev, &ucRoleIdx) != 0) + goto error; + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) + goto error; + + DBGLOG(REQ, INFO, "ucRoleIdx = %d\n", ucRoleIdx); + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + if (!prBssInfo) { + DBGLOG(REQ, WARN, "bss is not active\n"); + goto error; + } + + /* Mode */ + if (parseValueInString(&pcCommand, + "MAC_MODE=", &aucValue, WLAN_CFG_ARGV_MAX)) { + DBGLOG(REQ, ERROR, "[MODE] parse error\n"); + goto error; + } + if (kalkStrtou32(aucValue, 0, &i4Mode)) { + DBGLOG(REQ, ERROR, "[MODE] convert to int error\n"); + goto error; + } + if (i4Mode == 0) + prBssInfo->rACL.ePolicy = PARAM_CUSTOM_ACL_POLICY_DISABLE; + else if (i4Mode == 1) + prBssInfo->rACL.ePolicy = PARAM_CUSTOM_ACL_POLICY_DENY; + else if (i4Mode == 2) + prBssInfo->rACL.ePolicy = PARAM_CUSTOM_ACL_POLICY_ACCEPT; + else { + DBGLOG(REQ, ERROR, "[MODE] invalid ACL policy= %d\n", i4Mode); + goto error; + } + + /* Count */ + /* No need to parse count for diabled mode */ + if (prBssInfo->rACL.ePolicy != PARAM_CUSTOM_ACL_POLICY_DISABLE) { + if (parseValueInString(&pcCommand, + "MAC_CNT=", &aucValue, WLAN_CFG_ARGV_MAX)) { + DBGLOG(REQ, ERROR, "[CNT] parse count error\n"); + goto error; + } + if (kalkStrtou32(aucValue, 0, &i4Count)) { + DBGLOG(REQ, ERROR, "[CNT] convert to int error\n"); + goto error; + } + if (i4Count > MAX_NUMBER_OF_ACL) { + DBGLOG(REQ, ERROR, "[CNT] invalid count > max ACL\n"); + goto error; + } + } + + /* MAC */ + if (prBssInfo->rACL.u4Num) { + /* Clear */ + kalMemZero(&prBssInfo->rACL.rEntry[0], + sizeof(struct PARAM_CUSTOM_ACL_ENTRY) * MAC_ADDR_LEN); + prBssInfo->rACL.u4Num = 0; + } + + if (prBssInfo->rACL.ePolicy != PARAM_CUSTOM_ACL_POLICY_DISABLE) { + for (i = 0; i < i4Count; i++) { + /* Add */ + if (parseValueInString(&pcCommand, + "MAC=", &aucValue, WLAN_CFG_ARGV_MAX)) + break; + kalMemCopy(prBssInfo->rACL.rEntry[i].aucAddr, + &aucValue, MAC_ADDR_LEN); + DBGLOG(REQ, INFO, + "[MAC] add mac addr " MACSTR " to ACL(%d).\n", + MAC2STR(prBssInfo->rACL.rEntry[i].aucAddr), i); + } + + prBssInfo->rACL.u4Num = i; + /* check ACL affects any existent association */ + p2pRoleUpdateACLEntry(prAdapter, ucBssIdx); + DBGLOG(REQ, INFO, + "[MAC] Mode = %d, #ACL = %d, count = %d\n", + i4Mode, i, i4Count); + } + + return i4BytesWritten; + +error: + return -1; +} + +int priv_driver_set_ap_set_cfg(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct WIFI_VAR *prWifiVar = NULL; + uint8_t aucValue[WLAN_CFG_ARGV_MAX] = {0}; + uint8_t ucRoleIdx = 0; + int32_t i4BytesWritten = 0; + int32_t i4MaxCount = 0, i4Channel = 0; + + DBGLOG(REQ, INFO, "command is %s\n", pcCommand); + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + goto error; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + prWifiVar = &prAdapter->rWifiVar; + + /* get role index from ndev */ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prNetDev, &ucRoleIdx) != 0) + goto error; + + DBGLOG(REQ, INFO, "ucRoleIdx = %d\n", ucRoleIdx); + + /* Cfg */ + if (parseValueInString(&pcCommand, "ASCII_CMD=", + &aucValue, WLAN_CFG_ARGV_MAX)) { + DBGLOG(REQ, ERROR, "[CFG] cmd parse error\n"); + goto error; + } + if (kalStrnCmp(aucValue, "AP_CFG", 6)) { + DBGLOG(REQ, ERROR, "[CFG] sub cmd parse error\n"); + goto error; + } + + /* Channel */ + if (parseValueInString(&pcCommand, "CHANNEL=", + &aucValue, WLAN_CFG_ARGV_MAX)) { + DBGLOG(REQ, ERROR, "[CH] parse error\n"); + goto error; + } + if (kalkStrtou32(aucValue, 0, &i4Channel)) { + DBGLOG(REQ, ERROR, "[CH] convert to int error\n"); + goto error; + } + + /* Max SCB */ + if (parseValueInString(&pcCommand, "MAX_SCB=", + &aucValue, WLAN_CFG_ARGV_MAX)) { + DBGLOG(REQ, ERROR, "[MAX_SCB] parse error\n"); + goto error; + } + if (kalkStrtou32(aucValue, 0, &i4MaxCount)) { + DBGLOG(REQ, ERROR, "[MAX_SCB] convert to int error\n"); + goto error; + } + + /* Overwrite AP channel */ + prWifiVar->ucApChannel = i4Channel; + + /* Set max clients of Hotspot */ + kalP2PSetMaxClients(prGlueInfo, i4MaxCount, ucRoleIdx); + + DBGLOG(REQ, INFO, + "[CFG] CH = %d, MAX_SCB = %d\n", + i4Channel, i4MaxCount); + + /* Stop ap */ +#if 0 + { + struct PARAM_CUSTOM_P2P_SET_STRUCT rSetP2P; + + rSetP2P.u4Mode = 0; + rSetP2P.u4Enable = 0; + set_p2p_mode_handler(prNetDev, rSetP2P); + } +#endif + + return i4BytesWritten; + +error: + return -1; +} + +int priv_driver_set_ap_get_sta_list(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct BSS_INFO *prBssInfo = NULL; + struct LINK *prClientList; + struct STA_RECORD *prCurrStaRec, *prNextStaRec; + uint8_t ucRoleIdx = 0, ucBssIdx = 0; + int32_t i4BytesWritten = 0; + + DBGLOG(REQ, INFO, "command is %s\n", pcCommand); + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + goto error; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + /* get Bss Index from ndev */ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prNetDev, &ucRoleIdx) != 0) + goto error; + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) + goto error; + + DBGLOG(REQ, INFO, "ucRoleIdx = %d\n", ucRoleIdx); + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + if (!prBssInfo) { + DBGLOG(REQ, WARN, "bss is not active\n"); + goto error; + } + + prClientList = &prBssInfo->rStaRecOfClientList; + LINK_FOR_EACH_ENTRY_SAFE(prCurrStaRec, + prNextStaRec, prClientList, rLinkEntry, struct STA_RECORD) { + if (!prCurrStaRec) { + DBGLOG(REQ, WARN, "NULL STA_REC\n"); + break; + } + DBGLOG(SW4, INFO, "STA[%u] [" MACSTR "]\n", + prCurrStaRec->ucIndex, + MAC2STR(prCurrStaRec->aucMacAddr)); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + ""MACSTR"\n", + MAC2STR(prCurrStaRec->aucMacAddr)); + } + + return i4BytesWritten; + +error: + return -1; +} + +int priv_driver_set_ap_sta_disassoc(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint8_t aucValue[WLAN_CFG_ARGV_MAX] = {0}; + uint8_t ucRoleIdx = 0; + int32_t i4BytesWritten = 0; + struct MSG_P2P_CONNECTION_ABORT *prDisconnectMsg = + (struct MSG_P2P_CONNECTION_ABORT *) NULL; + + DBGLOG(REQ, INFO, "command is %s\n", pcCommand); + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + goto error; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + /* get role index from ndev */ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prNetDev, &ucRoleIdx) != 0) + goto error; + + DBGLOG(REQ, INFO, "ucRoleIdx = %d\n", ucRoleIdx); + + if (parseValueInString(&pcCommand, "MAC=", + &aucValue, WLAN_CFG_ARGV_MAX)) { + DBGLOG(REQ, ERROR, "[MAC] parse error\n"); + goto error; + } + + prDisconnectMsg = + (struct MSG_P2P_CONNECTION_ABORT *) + cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_P2P_CONNECTION_ABORT)); + if (prDisconnectMsg == NULL) { + ASSERT(FALSE); + goto error; + } + + prDisconnectMsg->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT; + prDisconnectMsg->ucRoleIdx = ucRoleIdx; + COPY_MAC_ADDR(prDisconnectMsg->aucTargetID, aucValue); + prDisconnectMsg->u2ReasonCode = REASON_CODE_UNSPECIFIED; + prDisconnectMsg->fgSendDeauth = TRUE; + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prDisconnectMsg, + MSG_SEND_METHOD_BUF); + + return i4BytesWritten; + +error: + return -1; +} + +int priv_driver_set_ap_nss(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4Parse = 0; + uint8_t ucNSS; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc == 2) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) { + DBGLOG(REQ, WARN, "parse apcArgv error u4Ret=%d\n", + u4Ret); + goto error; + } + ucNSS = (uint8_t) u4Parse; + + if ((ucNSS == 1) || (ucNSS == 2)) { + prGlueInfo->prAdapter->rWifiVar.ucAp5gNSS = ucNSS; + prGlueInfo->prAdapter->rWifiVar.ucAp2gNSS = ucNSS; + + DBGLOG(REQ, STATE, + "Ap2gNSS = %d\n", + prGlueInfo->prAdapter->rWifiVar.ucAp2gNSS); + } else + DBGLOG(REQ, WARN, "Invalid nss=%d\n", + ucNSS); + } else { + DBGLOG(INIT, ERROR, + "iwpriv wlanXX SET_AP_NSS \n"); + } + + return i4BytesWritten; + +error: + return -1; +} + +int +__priv_set_ap(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + uint32_t u4SubCmd = 0; + uint16_t u2Cmd = 0; + int32_t i4TotalFixLen = 1024; + int32_t i4CmdFound = 0; + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + + ASSERT(prNetDev); + ASSERT(prIwReqData); + if (!prNetDev || !prIwReqData) { + DBGLOG(REQ, INFO, + "invalid param(0x%p, 0x%p)\n", + prNetDev, prIwReqData); + return -EINVAL; + } + + u2Cmd = prIwReqInfo->cmd; + DBGLOG(REQ, INFO, "prIwReqInfo->cmd %x\n", u2Cmd); + + u4SubCmd = (uint32_t) prIwReqData->data.flags; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, + "invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, + *((struct GLUE_INFO **) netdev_priv(prNetDev))); + return -EINVAL; + } + + DBGLOG(REQ, INFO, "prIwReqData->data.length %u\n", + prIwReqData->data.length); + + ASSERT(IW_IS_GET(u2Cmd)); + if (prIwReqData->data.length != 0) { + if (!kal_access_ok(VERIFY_READ, prIwReqData->data.pointer, + prIwReqData->data.length)) { + DBGLOG(REQ, INFO, + "%s access_ok Read fail written = %d\n", + __func__, i4BytesWritten); + return -EFAULT; + } + if (copy_from_user(aucOidBuf, + prIwReqData->data.pointer, + prIwReqData->data.length)) { + DBGLOG(REQ, INFO, + "%s copy_form_user fail written = %d\n", + __func__, + prIwReqData->data.length); + return -EFAULT; + } + /* prIwReqData->data.length include the terminate '\0' */ + aucOidBuf[prIwReqData->data.length - 1] = 0; + } + + DBGLOG(REQ, INFO, "%s aucBuf %s\n", __func__, aucOidBuf); + + if (!pcExtra) + goto exit; + + i4CmdFound = 1; + switch (u2Cmd) { + case IOC_AP_GET_STA_LIST: + i4BytesWritten = + priv_driver_set_ap_get_sta_list( + prNetDev, + pcExtra, + i4TotalFixLen); + break; + case IOC_AP_SET_MAC_FLTR: + i4BytesWritten = + priv_driver_set_ap_set_mac_acl( + prNetDev, + aucOidBuf, + i4TotalFixLen); + break; + case IOC_AP_SET_CFG: + i4BytesWritten = + priv_driver_set_ap_set_cfg( + prNetDev, + aucOidBuf, + i4TotalFixLen); + break; + case IOC_AP_STA_DISASSOC: + i4BytesWritten = + priv_driver_set_ap_sta_disassoc( + prNetDev, + aucOidBuf, + i4TotalFixLen); + break; + case IOC_AP_SET_NSS: + i4BytesWritten = + priv_driver_set_ap_nss( + prNetDev, + aucOidBuf, + i4TotalFixLen); + break; + default: + i4CmdFound = 0; + break; + } + + if (i4CmdFound == 0) + DBGLOG(REQ, INFO, + "Unknown driver command\n"); + + if (i4BytesWritten >= 0) { + if ((i4BytesWritten == 0) && (i4TotalFixLen > 0)) { + /* reset the command buffer */ + pcExtra[0] = '\0'; + } else if (i4BytesWritten >= i4TotalFixLen) { + DBGLOG(REQ, INFO, + "%s: i4BytesWritten %d > i4TotalFixLen < %d\n", + __func__, i4BytesWritten, i4TotalFixLen); + i4BytesWritten = i4TotalFixLen; + } else { + pcExtra[i4BytesWritten] = '\0'; + i4BytesWritten++; + } + } + + DBGLOG(REQ, INFO, "%s i4BytesWritten = %d\n", __func__, + i4BytesWritten); + +exit: + + DBGLOG(REQ, INFO, "pcExtra done\n"); + + if (i4BytesWritten >= 0) + prIwReqData->data.length = i4BytesWritten; + + return 0; +} + +int +priv_set_ap(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ +#if 0 + return compat_priv(prNetDev, prIwReqInfo, + prIwReqData, pcExtra, __priv_set_ap); +#else + return __priv_set_ap(prNetDev, prIwReqInfo, + prIwReqData, pcExtra); +#endif +} + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +/* + * Memo + * 00 : Reset All Cal Data in Driver + * 01 : Trigger All Cal Function + * 02 : Get Thermal Temp from FW + * 03 : Get Cal Data Size from FW + * 04 : Get Cal Data from FW (Rom) + * 05 : Get Cal Data from FW (Ram) + * 06 : Print Cal Data in Driver (Rom) + * 07 : Print Cal Data in Driver (Ram) + * 08 : Print Cal Data in FW (Rom) + * 09 : Print Cal Data in FW (Ram) + * 10 : Send Cal Data to FW (Rom) + * 11 : Send Cal Data to FW (Ram) + */ +static int priv_driver_set_calbackup_test_drv_fw(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4GetInput; + int32_t i4ArgNum = 2; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "%s\r\n", __func__); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4GetInput); + if (u4Ret) + DBGLOG(RFTEST, INFO, + "priv_driver_set_calbackup_test_drv_fw Parsing Fail\n"); + + if (u4GetInput == 0) { + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#0 : Reset All Cal Data in Driver.\n"); + /* (New Flow 20160720) Step 0 : Reset All Cal Data + * Structure + */ + memset(&g_rBackupCalDataAllV2, 1, + sizeof(struct RLM_CAL_RESULT_ALL_V2)); + g_rBackupCalDataAllV2.u4MagicNum1 = 6632; + g_rBackupCalDataAllV2.u4MagicNum2 = 6632; + } else if (u4GetInput == 1) { + DBGLOG(RFTEST, INFO, + "CMD#1 : Trigger FW Do All Cal.\n"); + /* Step 1 : Trigger All Cal Function */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 1, 2, 0); + DBGLOG(RFTEST, INFO, + "Trigger FW Do All Cal, rStatus = 0x%08x\n", + rStatus); + } else if (u4GetInput == 2) { + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#2 : Get Thermal Temp from FW.\n"); + /* (New Flow 20160720) Step 2 : Get Thermal Temp from + * FW + */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 0, 0, 0); + DBGLOG(RFTEST, INFO, + "Get Thermal Temp from FW, rStatus = 0x%08x\n", + rStatus); + + } else if (u4GetInput == 3) { + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#3 : Get Cal Data Size from FW.\n"); + /* (New Flow 20160720) Step 3 : Get Cal Data Size from + * FW + */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 0, 1, 0); + DBGLOG(RFTEST, INFO, + "Get Rom Cal Data Size, rStatus = 0x%08x\n", + rStatus); + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 0, 1, 1); + DBGLOG(RFTEST, INFO, + "Get Ram Cal Data Size, rStatus = 0x%08x\n", + rStatus); + + } else if (u4GetInput == 4) { +#if 1 + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#4 : Print Cal Data in FW (Ram) (Part 1 - [0]~[3327]).\n"); + /* Debug Use : Print Cal Data in FW (Ram) */ + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 4, 6, 1); + DBGLOG(RFTEST, INFO, + "Print Cal Data in FW (Ram), rStatus = 0x%08x\n", + rStatus); +#else /* For Temp Use this Index */ + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#4 : Get Cal Data from FW (Rom). Start!!!!!!!!!!!\n"); + DBGLOG(RFTEST, INFO, "Thermal Temp = %d\n", + g_rBackupCalDataAllV2.u4ThermalInfo); + DBGLOG(RFTEST, INFO, "Total Length (Rom) = %d\n", + g_rBackupCalDataAllV2.u4ValidRomCalDataLength); + /* (New Flow 20160720) Step 3 : Get Cal Data from FW */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 2, 4, 0); + DBGLOG(RFTEST, INFO, + "Get Cal Data from FW (Rom), rStatus = 0x%08x\n", + rStatus); +#endif + } else if (u4GetInput == 5) { +#if 1 + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#5 : Print RAM Cal Data in Driver (Part 1 - [0]~[3327]).\n"); + DBGLOG(RFTEST, INFO, + "==================================================================\n"); + /* RFTEST_INFO_LOGDUMP32( + * &(g_rBackupCalDataAllV2.au4RamCalData[0]), + * 3328*sizeof(uint32_t)); + */ + DBGLOG(RFTEST, INFO, + "==================================================================\n"); + DBGLOG(RFTEST, INFO, + "Dumped Ram Cal Data Szie : %d bytes\n", + 3328*sizeof(uint32_t)); + DBGLOG(RFTEST, INFO, + "Total Ram Cal Data Szie : %d bytes\n", + g_rBackupCalDataAllV2.u4ValidRamCalDataLength); + DBGLOG(RFTEST, INFO, + "==================================================================\n"); +#else /* For Temp Use this Index */ + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#5 : Get Cal Data from FW (Ram). Start!!!!!!!!!!!\n"); + DBGLOG(RFTEST, INFO, "Thermal Temp = %d\n", + g_rBackupCalDataAllV2.u4ThermalInfo); + DBGLOG(RFTEST, INFO, "Total Length (Ram) = %d\n", + g_rBackupCalDataAllV2.u4ValidRamCalDataLength); + /* (New Flow 20160720) Step 3 : Get Cal Data from FW */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 2, 4, 1); + DBGLOG(RFTEST, INFO, + "Get Cal Data from FW (Ram), rStatus = 0x%08x\n", + rStatus); +#endif + } else if (u4GetInput == 6) { + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#6 : Print ROM Cal Data in Driver.\n"); + DBGLOG(RFTEST, INFO, + "==================================================================\n"); + /* RFTEST_INFO_LOGDUMP32( + * &(g_rBackupCalDataAllV2.au4RomCalData[0]), + * g_rBackupCalDataAllV2.u4ValidRomCalDataLength); + */ + DBGLOG(RFTEST, INFO, + "==================================================================\n"); + DBGLOG(RFTEST, INFO, + "Total Rom Cal Data Szie : %d bytes\n", + g_rBackupCalDataAllV2.u4ValidRomCalDataLength); + DBGLOG(RFTEST, INFO, + "==================================================================\n"); + } else if (u4GetInput == 7) { + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#7 : Print RAM Cal Data in Driver (Part 2 - [3328]~[6662]).\n"); + DBGLOG(RFTEST, INFO, + "==================================================================\n"); + /* RFTEST_INFO_LOGDUMP32( + * &(g_rBackupCalDataAllV2.au4RamCalData[3328]), + * (g_rBackupCalDataAllV2.u4ValidRamCalDataLength - + * 3328*sizeof(uint32_t))); + */ + DBGLOG(RFTEST, INFO, + "==================================================================\n"); + DBGLOG(RFTEST, INFO, + "Dumped Ram Cal Data Szie : %d bytes\n", + (g_rBackupCalDataAllV2.u4ValidRamCalDataLength - + 3328*sizeof(uint32_t))); + DBGLOG(RFTEST, INFO, + "Total Ram Cal Data Szie : %d bytes\n", + g_rBackupCalDataAllV2.u4ValidRamCalDataLength); + DBGLOG(RFTEST, INFO, + "==================================================================\n"); + } else if (u4GetInput == 8) { + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#8 : Print Cal Data in FW (Rom).\n"); + /* Debug Use : Print Cal Data in FW (Rom) */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 4, 6, 0); + DBGLOG(RFTEST, INFO, + "Print Cal Data in FW (Rom), rStatus = 0x%08x\n", + rStatus); + + } else if (u4GetInput == 9) { + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#9 : Print Cal Data in FW (Ram) (Part 2 - [3328]~[6662]).\n"); + /* Debug Use : Print Cal Data in FW (Ram) */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 4, 6, 2); + DBGLOG(RFTEST, INFO, + "Print Cal Data in FW (Ram), rStatus = 0x%08x\n", + rStatus); + + } else if (u4GetInput == 10) { + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#10 : Send Cal Data to FW (Rom).\n"); + /* Send Cal Data to FW (Rom) */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 3, 5, 0); + DBGLOG(RFTEST, INFO, + "Send Cal Data to FW (Rom), rStatus = 0x%08x\n", + rStatus); + + } else if (u4GetInput == 11) { + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#11 : Send Cal Data to FW (Ram).\n"); + /* Send Cal Data to FW (Ram) */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 3, 5, 1); + DBGLOG(RFTEST, INFO, + "Send Cal Data to FW (Ram), rStatus = 0x%08x\n", + rStatus); + + } + } + + return i4BytesWritten; +} /* priv_driver_set_calbackup_test_drv_fw */ +#endif + +#if CFG_WOW_SUPPORT +static int priv_driver_set_wow(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct WOW_CTRL *pWOW_CTRL = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Ret = 0; + uint32_t Enable = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + pWOW_CTRL = &prGlueInfo->prAdapter->rWowCtrl; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + u4Ret = kalkStrtou32(apcArgv[1], 0, &Enable); + + if (u4Ret) + DBGLOG(REQ, LOUD, "parse bEnable error u4Ret=%d\n", u4Ret); + + DBGLOG(INIT, INFO, "CMD set_wow_enable = %d\n", Enable); + DBGLOG(INIT, INFO, "Scenario ID %d\n", pWOW_CTRL->ucScenarioId); + DBGLOG(INIT, INFO, "ucBlockCount %d\n", pWOW_CTRL->ucBlockCount); + DBGLOG(INIT, INFO, "interface %d\n", + pWOW_CTRL->astWakeHif[0].ucWakeupHif); + DBGLOG(INIT, INFO, "gpio_pin %d\n", + pWOW_CTRL->astWakeHif[0].ucGpioPin); + DBGLOG(INIT, INFO, "gpio_level 0x%x\n", + pWOW_CTRL->astWakeHif[0].ucTriggerLvl); + DBGLOG(INIT, INFO, "gpio_timer %d\n", + pWOW_CTRL->astWakeHif[0].u4GpioInterval); + kalWowProcess(prGlueInfo, Enable); + + return 0; +} + +static int priv_driver_set_wow_enable(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct WOW_CTRL *pWOW_CTRL = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Ret = 0; + uint8_t ucEnable = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + pWOW_CTRL = &prGlueInfo->prAdapter->rWowCtrl; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + u4Ret = kalkStrtou8(apcArgv[1], 0, &ucEnable); + + if (u4Ret) + DBGLOG(REQ, LOUD, "parse bEnable error u4Ret=%d\n", u4Ret); + + pWOW_CTRL->fgWowEnable = ucEnable; + + DBGLOG(PF, INFO, "WOW enable %d\n", pWOW_CTRL->fgWowEnable); + + return 0; +} + +static int priv_driver_set_wow_par(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct WOW_CTRL *pWOW_CTRL = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t u4Ret = 0; + uint8_t ucWakeupHif = 0, GpioPin = 0, ucGpioLevel = 0, ucBlockCount = 0, + ucScenario = 0; + uint32_t u4GpioTimer = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + pWOW_CTRL = &prGlueInfo->prAdapter->rWowCtrl; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc > 3) { + + u4Ret = kalkStrtou8(apcArgv[1], 0, &ucWakeupHif); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse ucWakeupHif error u4Ret=%d\n", + u4Ret); + pWOW_CTRL->astWakeHif[0].ucWakeupHif = ucWakeupHif; + + u4Ret = kalkStrtou8(apcArgv[2], 0, &GpioPin); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse GpioPin error u4Ret=%d\n", + u4Ret); + pWOW_CTRL->astWakeHif[0].ucGpioPin = GpioPin; + + u4Ret = kalkStrtou8(apcArgv[3], 0, &ucGpioLevel); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse Gpio level error u4Ret=%d\n", + u4Ret); + pWOW_CTRL->astWakeHif[0].ucTriggerLvl = ucGpioLevel; + + u4Ret = kalkStrtou32(apcArgv[4], 0, &u4GpioTimer); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse u4GpioTimer error u4Ret=%d\n", + u4Ret); + pWOW_CTRL->astWakeHif[0].u4GpioInterval = u4GpioTimer; + + u4Ret = kalkStrtou8(apcArgv[5], 0, &ucScenario); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse ucScenario error u4Ret=%d\n", + u4Ret); + pWOW_CTRL->ucScenarioId = ucScenario; + + u4Ret = kalkStrtou8(apcArgv[6], 0, &ucBlockCount); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse ucBlockCnt error u4Ret=%d\n", + u4Ret); + pWOW_CTRL->ucBlockCount = ucBlockCount; + + DBGLOG(INIT, INFO, "gpio_scenario%d\n", + pWOW_CTRL->ucScenarioId); + DBGLOG(INIT, INFO, "interface %d\n", + pWOW_CTRL->astWakeHif[0].ucWakeupHif); + DBGLOG(INIT, INFO, "gpio_pin %d\n", + pWOW_CTRL->astWakeHif[0].ucGpioPin); + DBGLOG(INIT, INFO, "gpio_level %d\n", + pWOW_CTRL->astWakeHif[0].ucTriggerLvl); + DBGLOG(INIT, INFO, "gpio_timer %d\n", + pWOW_CTRL->astWakeHif[0].u4GpioInterval); + + return 0; + } else + return -1; + + +} + +static int priv_driver_set_wow_udpport(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct WOW_CTRL *pWOW_CTRL = NULL; + int32_t i4Argc = 0; + int8_t *apcPortArgv[WLAN_CFG_ARGV_MAX_LONG] = { 0 }; /* to input 20 port + */ + int32_t u4Ret = 0, ii; + uint8_t ucVer = 0, ucCount; + uint16_t u2Port = 0; + uint16_t *pausPortArry; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + pWOW_CTRL = &prGlueInfo->prAdapter->rWowCtrl; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgumentLong(pcCommand, &i4Argc, apcPortArgv); + DBGLOG(REQ, WARN, "argc is %i\n", i4Argc); + + /* example: set_wow_udp 0 5353,8080 (set) */ + /* example: set_wow_udp 1 (clear) */ + + if (i4Argc >= 3) { + + /* Pick Max */ + ucCount = ((i4Argc - 2) > MAX_TCP_UDP_PORT) ? MAX_TCP_UDP_PORT : + (i4Argc - 2); + DBGLOG(PF, INFO, "UDP ucCount=%d\n", ucCount); + + u4Ret = kalkStrtou8(apcPortArgv[1], 0, &ucVer); + if (u4Ret) { + DBGLOG(REQ, LOUD, "parse ucWakeupHif error u4Ret=%d\n", + u4Ret); + return -1; + } + + /* IPv4/IPv6 */ + DBGLOG(PF, INFO, "ucVer=%d\n", ucVer); + if (ucVer == 0) { + pWOW_CTRL->stWowPort.ucIPv4UdpPortCnt = ucCount; + pausPortArry = pWOW_CTRL->stWowPort.ausIPv4UdpPort; + } else { + pWOW_CTRL->stWowPort.ucIPv6UdpPortCnt = ucCount; + pausPortArry = pWOW_CTRL->stWowPort.ausIPv6UdpPort; + } + + /* Port */ + for (ii = 0; ii < ucCount; ii++) { + u4Ret = kalkStrtou16(apcPortArgv[ii+2], 0, &u2Port); + if (u4Ret) { + DBGLOG(PF, ERROR, + "parse u2Port error u4Ret=%d\n", u4Ret); + return -1; + } + + pausPortArry[ii] = u2Port; + DBGLOG(PF, INFO, "ucPort=%d, idx=%d\n", u2Port, ii); + } + + return 0; + } else if (i4Argc == 2) { + + u4Ret = kalkStrtou8(apcPortArgv[1], 0, &ucVer); + if (u4Ret) { + DBGLOG(REQ, LOUD, "parse ucWakeupHif error u4Ret=%d\n", + u4Ret); + return -1; + } + + if (ucVer == 0) { + kalMemZero(prGlueInfo->prAdapter->rWowCtrl.stWowPort + .ausIPv4UdpPort, + sizeof(uint16_t) * MAX_TCP_UDP_PORT); + prGlueInfo->prAdapter->rWowCtrl.stWowPort + .ucIPv4UdpPortCnt = 0; + } else { + kalMemZero(prGlueInfo->prAdapter->rWowCtrl.stWowPort + .ausIPv6UdpPort, + sizeof(uint16_t) * MAX_TCP_UDP_PORT); + prGlueInfo->prAdapter->rWowCtrl.stWowPort + .ucIPv6UdpPortCnt = 0; + } + + return 0; + } else + return -1; + +} + +static int priv_driver_set_wow_tcpport(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct WOW_CTRL *pWOW_CTRL = NULL; + int32_t i4Argc = 0; + int8_t *apcPortArgv[WLAN_CFG_ARGV_MAX_LONG] = { 0 }; /* to input 20 port + */ + int32_t u4Ret = 0, ii; + uint8_t ucVer = 0, ucCount; + uint16_t u2Port = 0; + uint16_t *pausPortArry; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + pWOW_CTRL = &prGlueInfo->prAdapter->rWowCtrl; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgumentLong(pcCommand, &i4Argc, apcPortArgv); + DBGLOG(REQ, WARN, "argc is %i\n", i4Argc); + + /* example: set_wow_tcp 0 5353,8080 (Set) */ + /* example: set_wow_tcp 1 (clear) */ + + if (i4Argc >= 3) { + + /* Pick Max */ + ucCount = ((i4Argc - 2) > MAX_TCP_UDP_PORT) ? MAX_TCP_UDP_PORT : + (i4Argc - 2); + DBGLOG(PF, INFO, "TCP ucCount=%d\n", ucCount); + + u4Ret = kalkStrtou8(apcPortArgv[1], 0, &ucVer); + if (u4Ret) { + DBGLOG(REQ, LOUD, "parse ucWakeupHif error u4Ret=%d\n", + u4Ret); + return -1; + } + + /* IPv4/IPv6 */ + DBGLOG(PF, INFO, "Ver=%d\n", ucVer); + if (ucVer == 0) { + pWOW_CTRL->stWowPort.ucIPv4TcpPortCnt = ucCount; + pausPortArry = pWOW_CTRL->stWowPort.ausIPv4TcpPort; + } else { + pWOW_CTRL->stWowPort.ucIPv6TcpPortCnt = ucCount; + pausPortArry = pWOW_CTRL->stWowPort.ausIPv6TcpPort; + } + + /* Port */ + for (ii = 0; ii < ucCount; ii++) { + u4Ret = kalkStrtou16(apcPortArgv[ii+2], 0, &u2Port); + if (u4Ret) { + DBGLOG(PF, ERROR, + "parse u2Port error u4Ret=%d\n", u4Ret); + return -1; + } + + pausPortArry[ii] = u2Port; + DBGLOG(PF, INFO, "ucPort=%d, idx=%d\n", u2Port, ii); + } + + return 0; + } else if (i4Argc == 2) { + + u4Ret = kalkStrtou8(apcPortArgv[1], 0, &ucVer); + if (u4Ret) { + DBGLOG(REQ, LOUD, "parse ucWakeupHif error u4Ret=%d\n", + u4Ret); + return -1; + } + + if (ucVer == 0) { + kalMemZero( + prGlueInfo->prAdapter->rWowCtrl.stWowPort + .ausIPv4UdpPort, + sizeof(uint16_t) * MAX_TCP_UDP_PORT); + prGlueInfo->prAdapter->rWowCtrl.stWowPort + .ucIPv4UdpPortCnt = 0; + } else { + kalMemZero( + prGlueInfo->prAdapter->rWowCtrl.stWowPort + .ausIPv6UdpPort, + sizeof(uint16_t) * MAX_TCP_UDP_PORT); + prGlueInfo->prAdapter->rWowCtrl.stWowPort + .ucIPv6UdpPortCnt = 0; + } + + return 0; + } else + return -1; + +} + +static int priv_driver_get_wow_port(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct WOW_CTRL *pWOW_CTRL = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t u4Ret = 0, ii; + uint8_t ucVer = 0, ucProto = 0; + uint16_t ucCount; + uint16_t *pausPortArry; + int8_t *aucIp[2] = {"IPv4", "IPv6"}; + int8_t *aucProto[2] = {"UDP", "TCP"}; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + pWOW_CTRL = &prGlueInfo->prAdapter->rWowCtrl; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + /* example: get_wow_port 0 0 (ipv4-udp) */ + /* example: get_wow_port 0 1 (ipv4-tcp) */ + /* example: get_wow_port 1 0 (ipv6-udp) */ + /* example: get_wow_port 1 1 (ipv6-tcp) */ + + if (i4Argc >= 3) { + + /* 0=IPv4, 1=IPv6 */ + u4Ret = kalkStrtou8(apcArgv[1], 0, &ucVer); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse argc[1] error u4Ret=%d\n", + u4Ret); + + /* 0=UDP, 1=TCP */ + u4Ret = kalkStrtou8(apcArgv[2], 0, &ucProto); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse argc[2] error u4Ret=%d\n", + u4Ret); + + if (ucVer > 1) + ucVer = 0; + + if (ucProto > 1) + ucProto = 0; + + if (ucVer == 0) { + if (ucProto == 0) { + /* IPv4/UDP */ + ucCount = pWOW_CTRL->stWowPort.ucIPv4UdpPortCnt; + pausPortArry = + pWOW_CTRL->stWowPort.ausIPv4UdpPort; + } else { + /* IPv4/TCP */ + ucCount = pWOW_CTRL->stWowPort.ucIPv4TcpPortCnt; + pausPortArry = + pWOW_CTRL->stWowPort.ausIPv4TcpPort; + } + } else { + if (ucProto == 0) { + /* IPv6/UDP */ + ucCount = pWOW_CTRL->stWowPort.ucIPv6UdpPortCnt; + pausPortArry = + pWOW_CTRL->stWowPort.ausIPv6UdpPort; + } else { + /* IPv6/TCP */ + ucCount = pWOW_CTRL->stWowPort.ucIPv6TcpPortCnt; + pausPortArry = + pWOW_CTRL->stWowPort.ausIPv6TcpPort; + } + } + + /* Dunp Port */ + for (ii = 0; ii < ucCount; ii++) + DBGLOG(PF, INFO, "ucPort=%d, idx=%d\n", + pausPortArry[ii], ii); + + + DBGLOG(PF, INFO, "[%s/%s] count:%d\n", aucIp[ucVer], + aucProto[ucProto], ucCount); + + return 0; + } else + return -1; + +} +#endif + +static int priv_driver_set_adv_pws(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Ret = 0; + uint8_t ucAdvPws = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + u4Ret = kalkStrtou8(apcArgv[1], 0, &ucAdvPws); + + if (u4Ret) + DBGLOG(REQ, LOUD, "parse bEnable error u4Ret=%d\n", + u4Ret); + + prGlueInfo->prAdapter->rWifiVar.ucAdvPws = ucAdvPws; + + DBGLOG(INIT, INFO, "AdvPws:%d\n", + prGlueInfo->prAdapter->rWifiVar.ucAdvPws); + + return 0; + +} + +static int priv_driver_set_mdtim(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Ret = 0; + uint8_t ucMultiDtim = 0, ucVer = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + /* iwpriv wlan0 driver "set_mdtim 1 3 */ + if (i4Argc >= 3) { + + u4Ret = kalkStrtou8(apcArgv[1], 0, &ucVer); + if (u4Ret) { + DBGLOG(REQ, ERROR, "parse apcArgv1 error u4Ret=%d\n", + u4Ret); + return -1; + } + + u4Ret = kalkStrtou8(apcArgv[2], 0, &ucMultiDtim); + if (u4Ret) { + DBGLOG(REQ, ERROR, "parse apcArgv2 error u4Ret=%d\n", + u4Ret); + return -1; + } + + if (ucVer == 0) { + prGlueInfo->prAdapter->rWifiVar.ucWowOnMdtim = + ucMultiDtim; + DBGLOG(REQ, INFO, "WOW On MDTIM:%d\n", + prGlueInfo->prAdapter->rWifiVar.ucWowOnMdtim); + } else { + prGlueInfo->prAdapter->rWifiVar.ucWowOffMdtim = + ucMultiDtim; + DBGLOG(REQ, INFO, "WOW Off MDTIM:%d\n", + prGlueInfo->prAdapter->rWifiVar.ucWowOffMdtim); + } + } + + return 0; + +} + +int priv_driver_set_suspend_mode(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + u_int8_t fgEnable; + uint32_t u4Enable = 0; + int32_t u4Ret = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= 2) { + /* fgEnable = (kalStrtoul(apcArgv[1], NULL, 0) == 1) ? TRUE : + * FALSE; + */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Enable); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse u4Enable error u4Ret=%d\n", + u4Ret); + if (u4Enable == 1) + fgEnable = TRUE; + else + fgEnable = FALSE; + + if (prGlueInfo->fgIsInSuspendMode == fgEnable) { + DBGLOG(REQ, INFO, + "%s: Already in suspend mode [%u], SKIP!\n", + __func__, fgEnable); + return 0; + } + + DBGLOG(REQ, INFO, "%s: Set suspend mode [%u]\n", __func__, + fgEnable); + + prGlueInfo->fgIsInSuspendMode = fgEnable; + + wlanSetSuspendMode(prGlueInfo, fgEnable); + p2pSetSuspendMode(prGlueInfo, fgEnable); + } + + return 0; +} + +#if CFG_SUPPORT_SNIFFER +int priv_driver_set_monitor(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int32_t i4BytesWritten = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + struct PARAM_CUSTOM_MONITOR_SET_STRUCT rMonitorSetInfo; + uint8_t ucEnable = 0; + uint8_t ucPriChannel = 0; + uint8_t ucChannelWidth = 0; + uint8_t ucExt = 0; + uint8_t ucSco = 0; + uint8_t ucChannelS1 = 0; + uint8_t ucChannelS2 = 0; + u_int8_t fgIsLegalChannel = FALSE; + u_int8_t fgError = FALSE; + u_int8_t fgEnable = FALSE; + enum ENUM_BAND eBand = BAND_NULL; + uint32_t u4Parse = 0; + int32_t u4Ret = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc >= 5) { + /* ucEnable = (uint8_t) (kalStrtoul(apcArgv[1], NULL, 0)); + * ucPriChannel = (uint8_t) (kalStrtoul(apcArgv[2], NULL, 0)); + * ucChannelWidth = (uint8_t) (kalStrtoul(apcArgv[3], NULL, 0)); + * ucExt = (uint8_t) (kalStrtoul(apcArgv[4], NULL, 0)); + */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + ucEnable = (uint8_t) u4Parse; + u4Ret = kalkStrtou32(apcArgv[2], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + ucPriChannel = (uint8_t) u4Parse; + u4Ret = kalkStrtou32(apcArgv[3], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + ucChannelWidth = (uint8_t) u4Parse; + u4Ret = kalkStrtou32(apcArgv[4], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + ucExt = (uint8_t) u4Parse; + + eBand = (ucPriChannel <= 14) ? BAND_2G4 : BAND_5G; + fgIsLegalChannel = rlmDomainIsLegalChannel(prAdapter, eBand, + ucPriChannel); + + if (fgIsLegalChannel == FALSE) { + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, + "Illegal primary channel %d", + ucPriChannel); + return i4BytesWritten; + } + + switch (ucChannelWidth) { + case 160: + ucChannelWidth = (uint8_t) CW_160MHZ; + ucSco = (uint8_t) CHNL_EXT_SCN; + + if (ucPriChannel >= 36 && ucPriChannel <= 64) + ucChannelS2 = 50; + else if (ucPriChannel >= 100 && ucPriChannel <= 128) + ucChannelS2 = 114; + else + fgError = TRUE; + break; + + case 80: + ucChannelWidth = (uint8_t) CW_80MHZ; + ucSco = (uint8_t) CHNL_EXT_SCN; + + if (ucPriChannel >= 36 && ucPriChannel <= 48) + ucChannelS1 = 42; + else if (ucPriChannel >= 52 && ucPriChannel <= 64) + ucChannelS1 = 58; + else if (ucPriChannel >= 100 && ucPriChannel <= 112) + ucChannelS1 = 106; + else if (ucPriChannel >= 116 && ucPriChannel <= 128) + ucChannelS1 = 122; + else if (ucPriChannel >= 132 && ucPriChannel <= 144) + ucChannelS1 = 138; + else if (ucPriChannel >= 149 && ucPriChannel <= 161) + ucChannelS1 = 155; + else + fgError = TRUE; + break; + + case 40: + ucChannelWidth = (uint8_t) CW_20_40MHZ; + ucSco = (ucExt) ? (uint8_t) CHNL_EXT_SCA : + (uint8_t) CHNL_EXT_SCB; + break; + + case 20: + ucChannelWidth = (uint8_t) CW_20_40MHZ; + ucSco = (uint8_t) CHNL_EXT_SCN; + break; + + default: + fgError = TRUE; + break; + } + + if (fgError) { + i4BytesWritten = + kalSnprintf(pcCommand, i4TotalLen, + "Invalid primary channel %d with bandwidth %d", + ucPriChannel, ucChannelWidth); + return i4BytesWritten; + } + + fgEnable = (ucEnable) ? TRUE : FALSE; + + if (prGlueInfo->fgIsEnableMon != fgEnable) { + prGlueInfo->fgIsEnableMon = fgEnable; + schedule_work(&prGlueInfo->monWork); + } + + kalMemZero(&rMonitorSetInfo, sizeof(rMonitorSetInfo)); + + rMonitorSetInfo.ucEnable = ucEnable; + rMonitorSetInfo.ucPriChannel = ucPriChannel; + rMonitorSetInfo.ucSco = ucSco; + rMonitorSetInfo.ucChannelWidth = ucChannelWidth; + rMonitorSetInfo.ucChannelS1 = ucChannelS1; + rMonitorSetInfo.ucChannelS2 = ucChannelS2; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetMonitor, + &rMonitorSetInfo, sizeof(rMonitorSetInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + i4BytesWritten = + kalSnprintf(pcCommand, i4TotalLen, "set monitor config %s", + (rStatus == WLAN_STATUS_SUCCESS) ? + "success" : "fail"); + + return i4BytesWritten; + } + + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, + "monitor [Enable][PriChannel][ChannelWidth][Sco]"); + + return i4BytesWritten; +} +#endif + +int priv_driver_set_bf(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4Parse = 0; + uint8_t ucBfEnable; + /*UINT_8 ucBssIndex;*/ + /*P_BSS_INFO_T prBssInfo;*/ + + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc == 2) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + + ucBfEnable = (uint8_t) u4Parse; + prGlueInfo->prAdapter->rWifiVar.ucStaHtBfee = ucBfEnable; + prGlueInfo->prAdapter->rWifiVar.ucStaVhtBfee = ucBfEnable; +#if (CFG_SUPPORT_802_11AX == 1) + prGlueInfo->prAdapter->rWifiVar.ucStaHeBfee = ucBfEnable; +#endif /* CFG_SUPPORT_802_11AX == 1 */ + prGlueInfo->prAdapter->rWifiVar.ucStaVhtMuBfee = ucBfEnable; + DBGLOG(REQ, ERROR, "ucBfEnable = %d\n", ucBfEnable); + } else { + DBGLOG(INIT, ERROR, "iwpriv wlanXX driver SET_NSS \n"); + } + + return i4BytesWritten; +} + +int priv_driver_set_nss(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4Parse = 0; + uint8_t ucNSS; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc == 2) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + + ucNSS = (uint8_t) u4Parse; + prGlueInfo->prAdapter->rWifiVar.ucNSS = ucNSS; + DBGLOG(REQ, LOUD, "ucNSS = %d\n", ucNSS); + } else { + DBGLOG(INIT, ERROR, "iwpriv wlanXX driver SET_NSS \n"); + } + + return i4BytesWritten; +} + + +int priv_driver_set_amsdu_tx(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4Parse = 0; + uint8_t ucAmsduTx; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc == 2) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + + ucAmsduTx = (uint8_t) u4Parse; + prGlueInfo->prAdapter->rWifiVar.ucAmsduInAmpduTx = ucAmsduTx; + prGlueInfo->prAdapter->rWifiVar.ucHtAmsduInAmpduTx = ucAmsduTx; + prGlueInfo->prAdapter->rWifiVar.ucVhtAmsduInAmpduTx = ucAmsduTx; +#if (CFG_SUPPORT_802_11AX == 1) + prGlueInfo->prAdapter->rWifiVar.ucHeAmsduInAmpduTx = ucAmsduTx; +#endif + DBGLOG(REQ, LOUD, "ucAmsduTx = %d\n", ucAmsduTx); + } else { + DBGLOG(INIT, ERROR, "iwpriv wlanXX driver SET_NSS \n"); + } + + return i4BytesWritten; +} + + +int priv_driver_set_amsdu_rx(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4Parse = 0; + uint8_t ucAmsduRx; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc == 2) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + + ucAmsduRx = (uint8_t) u4Parse; + prGlueInfo->prAdapter->rWifiVar.ucAmsduInAmpduRx = ucAmsduRx; + prGlueInfo->prAdapter->rWifiVar.ucHtAmsduInAmpduRx = ucAmsduRx; + prGlueInfo->prAdapter->rWifiVar.ucVhtAmsduInAmpduRx = ucAmsduRx; +#if (CFG_SUPPORT_802_11AX == 1) + prGlueInfo->prAdapter->rWifiVar.ucHeAmsduInAmpduRx = ucAmsduRx; +#endif + DBGLOG(REQ, LOUD, "ucAmsduRx = %d\n", ucAmsduRx); + } else { + DBGLOG(INIT, ERROR, "iwpriv wlanXX driver SET_NSS \n"); + } + + return i4BytesWritten; +} + +int priv_driver_set_ampdu_tx(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4Parse = 0; + uint8_t ucAmpduEnable; + /*UINT_8 ucBssIndex;*/ + /*P_BSS_INFO_T prBssInfo;*/ + + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc == 2) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + + ucAmpduEnable = (uint8_t) u4Parse; + prGlueInfo->prAdapter->rWifiVar.ucAmpduTx = ucAmpduEnable; + DBGLOG(REQ, ERROR, "ucAmpduTx = %d\n", ucAmpduEnable); + } else { + DBGLOG(INIT, ERROR, "iwpriv wlan0 driver SET_AMPDU_TX \n"); + DBGLOG(INIT, ERROR, " 1: enable. 0: disable.\n"); + } + + return i4BytesWritten; +} + +int priv_driver_set_ampdu_rx(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4Parse = 0; + uint8_t ucAmpduEnable; + /*UINT_8 ucBssIndex;*/ + /*P_BSS_INFO_T prBssInfo;*/ + + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc == 2) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + + ucAmpduEnable = (uint8_t) u4Parse; + prGlueInfo->prAdapter->rWifiVar.ucAmpduRx = ucAmpduEnable; + DBGLOG(REQ, ERROR, "ucAmpduRx = %d\n", + prGlueInfo->prAdapter->rWifiVar.ucAmpduRx); + } else { + DBGLOG(INIT, ERROR, "iwpriv wlan0 driver SET_AMPDU_RX \n"); + DBGLOG(INIT, ERROR, " 1: enable. 0: disable.\n"); + } + + return i4BytesWritten; +} + +int priv_driver_set_qos(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4Parse = 0; + uint8_t ucQoSEnable; + /*UINT_8 ucBssIndex;*/ + /*P_BSS_INFO_T prBssInfo;*/ + + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc == 2) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + + ucQoSEnable = (uint8_t) u4Parse; + prGlueInfo->prAdapter->rWifiVar.ucQoS = ucQoSEnable; + DBGLOG(REQ, ERROR, "ucQoS = %d\n", + prGlueInfo->prAdapter->rWifiVar.ucQoS); + } else { + DBGLOG(INIT, ERROR, "iwpriv wlanXX driver SET_QOS \n"); + DBGLOG(INIT, ERROR, " 1: enable. 0: disable.\n"); + } + + return i4BytesWritten; +} + +#if (CFG_SUPPORT_802_11AX == 1) +int priv_driver_muedca_override( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4Parse = 0; + uint8_t ucMuEdcaOverride; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc == 2) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + + ucMuEdcaOverride = (uint8_t) u4Parse; +#if (CFG_SUPPORT_802_11AX == 1) + prGlueInfo->prAdapter->fgMuEdcaOverride = ucMuEdcaOverride; +#endif + DBGLOG(REQ, LOUD, "ucMuEdcaOverride = %d\n", ucMuEdcaOverride); + } else { + DBGLOG(INIT, ERROR, + "iwpriv wlanXX driver MUEDCA_OVERRIDE \n"); + } + + return i4BytesWritten; +} + +int priv_driver_set_mcsmap(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4Parse = 0; + uint8_t ucTxMcsMap; + struct ADAPTER *prAdapter = NULL; + /*UINT_8 ucBssIndex;*/ + /*P_BSS_INFO_T prBssInfo;*/ + + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc == 2) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + + ucTxMcsMap = (uint8_t) u4Parse; +#if (CFG_SUPPORT_802_11AX == 1) + if (ucTxMcsMap >= 0 && ucTxMcsMap <= 2) { + prAdapter = prGlueInfo->prAdapter; + prAdapter->ucMcsMapSetFromSigma = ucTxMcsMap; + + DBGLOG(REQ, ERROR, "ucMcsMapSetFromSigma = %d\n", + prGlueInfo->prAdapter->ucMcsMapSetFromSigma); + + prGlueInfo->prAdapter->fgMcsMapBeenSet = TRUE; + } else { + prGlueInfo->prAdapter->fgMcsMapBeenSet = FALSE; + } +#endif + } else { + DBGLOG(INIT, ERROR, "iwpriv wlan0 driver SET_TX_MCSMAP \n"); + DBGLOG(INIT, ERROR, " 1: enable. 0: disable.\n"); + } + + return i4BytesWritten; +} + +int priv_driver_set_ba_size(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4Parse = 0; + uint16_t u2HeBaSize; + /*UINT_8 ucBssIndex;*/ + /*P_BSS_INFO_T prBssInfo;*/ + + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc == 2) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + + u2HeBaSize = (uint16_t) u4Parse; + + prGlueInfo->prAdapter->rWifiVar.u2TxHeBaSize = u2HeBaSize; + prGlueInfo->prAdapter->rWifiVar.u2RxHeBaSize = u2HeBaSize; + } else { + DBGLOG(INIT, ERROR, "iwpriv wlanXX driver SET_BA_SIZE\n"); + DBGLOG(INIT, ERROR, " 1: enable. 0: disable.\n"); + } + + return i4BytesWritten; +} + +/* This command is for sigma to disable TpTestMode. */ +int priv_driver_set_tp_test_mode(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4Parse = 0; + uint8_t ucTpTestMode; + /*UINT_8 ucBssIndex;*/ + /*P_BSS_INFO_T prBssInfo;*/ + + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc == 2) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + + ucTpTestMode = (uint8_t) u4Parse; + + prGlueInfo->prAdapter->rWifiVar.ucTpTestMode = ucTpTestMode; + } else { + DBGLOG(INIT, ERROR, "iwpriv wlanXX driver SET_TP_TEST_MODE\n"); + DBGLOG(INIT, ERROR, " 1: enable. 0: disable.\n"); + } + + return i4BytesWritten; +} + +/* This command is for sigma to disable TxPPDU. */ +int priv_driver_set_tx_ppdu(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4Parse = 0; + struct ADAPTER *prAdapter = NULL; + struct STA_RECORD *prStaRec; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + prStaRec = cnmGetStaRecByIndex(prAdapter, 0); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc == 2) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + + if (u4Parse) { + /* HE_SU is allowed. */ + prAdapter->fgTxPPDU = TRUE; + NIC_TX_PPDU_ENABLE(prAdapter); + } else { + /* HE_SU is not allowed. */ + prAdapter->fgTxPPDU = FALSE; + if (prStaRec && prStaRec->fgIsTxAllowed) + NIC_TX_PPDU_DISABLE(prAdapter); + } + + DBGLOG(REQ, STATE, "fgTxPPDU is %d\n", prAdapter->fgTxPPDU); + } else { + DBGLOG(INIT, ERROR, "iwpriv wlanXX driver TX_PPDU\n"); + DBGLOG(INIT, ERROR, " 1: enable. 0: disable.\n"); + } + + return i4BytesWritten; +} + +/* This command is for sigma to disable LDPC capability. */ +int priv_driver_set_ldpc(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4Parse = 0; + struct ADAPTER *prAdapter = NULL; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc == 2) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + if (u4Parse) { + /* LDPC is enabled. */ + prAdapter->rWifiVar.ucTxLdpc = TRUE; + prAdapter->rWifiVar.ucRxLdpc = TRUE; + } else { + /* LDPC is disabled. */ + prAdapter->rWifiVar.ucTxLdpc = FALSE; + prAdapter->rWifiVar.ucRxLdpc = FALSE; + } + + DBGLOG(REQ, STATE, "prAdapter->rWifiVar.ucTxLdpc is %d\n", + prAdapter->rWifiVar.ucTxLdpc); + DBGLOG(REQ, STATE, "prAdapter->rWifiVar.ucRxLdpc is %d\n", + prAdapter->rWifiVar.ucRxLdpc); + } else { + DBGLOG(INIT, ERROR, "iwpriv wlanXX driver TX_PPDU\n"); + DBGLOG(INIT, ERROR, " 1: enable. 0: disable.\n"); + } + + return i4BytesWritten; +} + +/* This command is for sigma to force tx amsdu. */ +int priv_driver_set_tx_force_amsdu(IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4Parse = 0; + struct ADAPTER *prAdapter = NULL; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc == 2) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + if (u4Parse) { + /* forceAmsdu is enabled. */ + prAdapter->rWifiVar.ucHeCertForceAmsdu = TRUE; + } else { + /* forceAmsdu is disabled. */ + prAdapter->rWifiVar.ucHeCertForceAmsdu = FALSE; + } + + DBGLOG(REQ, STATE, + "prAdapter->rWifiVar.ucHeCertForceAmsdu is %d\n", + prAdapter->rWifiVar.ucHeCertForceAmsdu); + } else { + DBGLOG(INIT, ERROR, "iwpriv wlanXX driver FORCE_AMSDU_TX %d\n"); + DBGLOG(INIT, ERROR, " 1: enable. 0: disable.\n"); + } + + return i4BytesWritten; +} + + + + +/* This command is for sigma to change OM CH BW. */ +int priv_driver_set_om_ch_bw(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4Parse = 0; + struct ADAPTER *prAdapter = NULL; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc == 2) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + + DBGLOG(REQ, STATE, + "priv_driver_set_om_ch_bw:: ch bw = %d\n", u4Parse); + if (u4Parse <= CH_BW_160) + HE_SET_HTC_HE_OM_CH_WIDTH( + prAdapter->u4HeHtcOM, u4Parse); + } else { + DBGLOG(INIT, ERROR, + "iwpriv wlanXX driver TX_ACTION \n"); + DBGLOG(INIT, ERROR, " action frame count.\n"); + } + + return i4BytesWritten; +} + +/* This command is for sigma to change OM RX NSS. */ +int priv_driver_set_om_rx_nss( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4Parse = 0; + struct ADAPTER *prAdapter = NULL; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc == 2) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + + DBGLOG(REQ, STATE, + "priv_driver_set_om_rx_nss:: rx nss = %d\n", u4Parse); + HE_SET_HTC_HE_OM_RX_NSS(prAdapter->u4HeHtcOM, u4Parse); + } else { + DBGLOG(INIT, ERROR, + "iwpriv wlanXX driver TX_ACTION \n"); + DBGLOG(INIT, ERROR, " action frame count.\n"); + } + + return i4BytesWritten; +} + +int priv_driver_set_om_tx_nss( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4Parse = 0; + struct ADAPTER *prAdapter = NULL; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc == 2) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + + DBGLOG(REQ, STATE, + "priv_driver_set_om_tx_nss:: tx nss = %d\n", u4Parse); + HE_SET_HTC_HE_OM_TX_NSTS(prAdapter->u4HeHtcOM, u4Parse); + } else { + DBGLOG(INIT, ERROR, + "iwpriv wlanXX driver SET_OM_TXNSTS \n"); + DBGLOG(INIT, ERROR, " action frame count.\n"); + } + + return i4BytesWritten; +} + +int priv_driver_set_om_mu_dis( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4Parse = 0; + struct ADAPTER *prAdapter = NULL; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc == 2) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + + DBGLOG(REQ, STATE, + "priv_driver_set_om_mu_dis:: disable = %d\n", u4Parse); + HE_SET_HTC_HE_OM_UL_MU_DISABLE(prAdapter->u4HeHtcOM, u4Parse); + } else { + DBGLOG(INIT, ERROR, + "iwpriv wlanXX driver SET_OM_MU_DISABLE \n"); + DBGLOG(INIT, ERROR, " action frame count.\n"); + } + + return i4BytesWritten; +} + +int priv_driver_set_tx_om_packet( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4Parse = 0; + struct ADAPTER *prAdapter = NULL; + int32_t index; + struct STA_RECORD *prStaRec = NULL; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc == 2) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + + DBGLOG(REQ, STATE, + "tx om packet:: Send %d htc null frame\n", + u4Parse); + if (u4Parse) { + prStaRec = cnmGetStaRecByIndex(prAdapter, 0); + if (prStaRec != NULL) { + for (index = 0; index < u4Parse; index++) + heRlmSendHtcNullFrame(prAdapter, + prStaRec, 7, NULL); + } + } + } else { + DBGLOG(INIT, ERROR, + "iwpriv wlanXX driver TX_ACTION \n"); + DBGLOG(INIT, ERROR, " action frame count.\n"); + } + + return i4BytesWritten; +} + +int priv_driver_set_tx_cck_1m_pwr( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4Parse = 0; + struct ADAPTER *prAdapter = NULL; + uint8_t pwr; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc == 2) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + + DBGLOG(REQ, STATE, + "priv_driver_set_tx_cck_1m_pwr:: set cck pwr %d\n", + u4Parse); + + if (u4Parse) { + pwr = u4Parse; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_CCK_1M_PWR, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(uint8_t), + (uint8_t *)&pwr, NULL, 0); + } + } else { + DBGLOG(INIT, ERROR, + "iwpriv wlanXX driver TX_CCK_1M_PWR \n"); + DBGLOG(INIT, ERROR, " power of CCK 1M.\n"); + } + + return i4BytesWritten; +} + +#endif /* CFG_SUPPORT_802_11AX == 1 */ + + +static int priv_driver_get_sta_index(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter; + int32_t i4BytesWritten = 0, i4Argc = 0; + uint8_t ucStaIdx, ucWlanIndex = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint8_t aucMacAddr[MAC_ADDR_LEN]; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= 2) { + wlanHwAddrToBin(apcArgv[1], &aucMacAddr[0]); + + if (!wlanGetWlanIdxByAddress(prGlueInfo->prAdapter, + &aucMacAddr[0], &ucWlanIndex)) + return i4BytesWritten; + + if (wlanGetStaIdxByWlanIdx(prAdapter, ucWlanIndex, &ucStaIdx) + != WLAN_STATUS_SUCCESS) + return i4BytesWritten; + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "StaIdx = %d, WlanIdx = %d\n", ucStaIdx, + ucWlanIndex); + } + + return i4BytesWritten; +} + +static int priv_driver_get_version(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter; + int32_t i4BytesWritten = 0; + uint32_t u4Offset = 0; + + ASSERT(prNetDev); + + prGlueInfo = *((struct GLUE_INFO **)netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + u4Offset += fwDlGetFwdlInfo(prAdapter, pcCommand, i4TotalLen); + u4Offset += kalSnprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "WiFi Driver Version %u.%u.%u\n", + NIC_DRIVER_MAJOR_VERSION, + NIC_DRIVER_MINOR_VERSION, + NIC_DRIVER_SERIAL_VERSION); + + i4BytesWritten = (int32_t)u4Offset; + + return i4BytesWritten; +} + +#if CFG_CHIP_RESET_HANG +static int priv_driver_set_rst_hang(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret; + + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc == 0) { + DBGLOG(REQ, INFO, "set_rst_hang Argc = %d\n", i4Argc); + return -EFAULT; + } + + if (strnicmp(apcArgv[0], CMD_SET_RST_HANG, + strlen(CMD_SET_RST_HANG)) == 0) { + if (i4Argc < CMD_SET_RST_HANG_ARG_NUM) { + DBGLOG(REQ, STATE, + "[SER][L0] RST_HANG_SET arg num=%d,must be %d\n", + i4Argc, CMD_SET_RST_HANG_ARG_NUM); + return -EFAULT; + } + u4Ret = kalkStrtou8(apcArgv[1], 0, &fgIsResetHangState); + if (u4Ret) + DBGLOG(REQ, ERROR, "u4Ret=%d\n", u4Ret); + + DBGLOG(REQ, STATE, "[SER][L0] set fgIsResetHangState=%d\n", + fgIsResetHangState); + + if (fgIsResetHangState == SER_L0_HANG_RST_CMD_TRG) { + DBGLOG(REQ, STATE, "[SER][L0] cmd trigger\n"); + glSetRstReason(RST_CMD_TRIGGER); + GL_RESET_TRIGGER(NULL, RST_FLAG_CHIP_RESET); + } + + } else { + DBGLOG(REQ, STATE, "[SER][L0] get fgIsResetSqcState=%d\n", + fgIsResetHangState); + DBGLOG(REQ, ERROR, "[SER][L0] RST HANG subcmd(%s) error !\n", + apcArgv[0]); + + return -EFAULT; + } + + return 0; + +} +#endif + +#if CFG_SUPPORT_DBDC +int priv_driver_set_dbdc(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4Parse = 0; + uint8_t ucDBDCEnable; + /*UINT_8 ucBssIndex;*/ + /*P_BSS_INFO_T prBssInfo;*/ + + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); +#if 0 + for (ucBssIndex = 0; ucBssIndex < (prAdapter->ucHwBssIdNum + 1); + ucBssIndex++) { + prBssInfo = prGlueInfo->prAdapter->aprBssInfo[ucBssIndex]; + pr_info("****BSS %u inUse %u active %u Mode %u priCh %u state %u rfBand %u\n", + ucBssIndex, + prBssInfo->fgIsInUse, + prBssInfo->fgIsNetActive, + prBssInfo->eCurrentOPMode, + prBssInfo->ucPrimaryChannel, + prBssInfo->eConnectionState, + prBssInfo->eBand); + } +#endif + if (prGlueInfo->prAdapter->rWifiVar.eDbdcMode != + ENUM_DBDC_MODE_DYNAMIC) { + DBGLOG(REQ, LOUD, + "Current DBDC mode %u cannot enable/disable DBDC!!\n", + prGlueInfo->prAdapter->rWifiVar.eDbdcMode); + return -1; + } + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc == 2) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + + ucDBDCEnable = (uint8_t) u4Parse; + if ((!prGlueInfo->prAdapter->rWifiVar.fgDbDcModeEn && + !ucDBDCEnable) || + (prGlueInfo->prAdapter->rWifiVar.fgDbDcModeEn && + ucDBDCEnable)) + return i4BytesWritten; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetDbdcEnable, + &ucDBDCEnable, 1, FALSE, FALSE, TRUE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + } else { + DBGLOG(INIT, ERROR, "iwpriv wlanXX driver SET_DBDC \n"); + DBGLOG(INIT, ERROR, " 1: enable. 0: disable.\n"); + } + + return i4BytesWritten; +} + +int priv_driver_set_sta1ss(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4Parse = 0; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc == 2) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + + prGlueInfo->prAdapter->rWifiVar.fgSta1NSS = + (uint8_t) u4Parse; + + } else { + DBGLOG(INIT, ERROR, + "iwpriv wlanXX driver SET_STA1NSS \n"); + DBGLOG(INIT, ERROR, + " 1: enable. 0: disable.\n"); + } + + return i4BytesWritten; +} + +#endif /*CFG_SUPPORT_DBDC*/ + +#if CFG_SUPPORT_BATCH_SCAN +#define CMD_BATCH_SET "WLS_BATCHING SET" +#define CMD_BATCH_GET "WLS_BATCHING GET" +#define CMD_BATCH_STOP "WLS_BATCHING STOP" +#endif + +static int priv_driver_get_que_info(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + return qmDumpQueueStatus(prGlueInfo->prAdapter, pcCommand, i4TotalLen); +} + +static int priv_driver_get_mem_info(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + return cnmDumpMemoryStatus(prGlueInfo->prAdapter, pcCommand, + i4TotalLen); +} + +static int priv_driver_get_hif_info(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + return halDumpHifStatus(prGlueInfo->prAdapter, pcCommand, i4TotalLen); +} + +static int priv_driver_get_capab_rsdb(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + uint32_t u4Offset = 0; + u_int8_t fgDbDcModeEn = FALSE; + + prGlueInfo = wlanGetGlueInfo(); + if (!prGlueInfo) { + DBGLOG(REQ, WARN, "prGlueInfo is NULL\n"); + return -EFAULT; + } + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + +#if CFG_SUPPORT_DBDC + if (prGlueInfo->prAdapter->rWifiVar.eDbdcMode != + ENUM_DBDC_MODE_DISABLED) + fgDbDcModeEn = TRUE; + + if (prGlueInfo->prAdapter->rWifiFemCfg.u2WifiPath == + (WLAN_FLAG_2G4_WF0 | WLAN_FLAG_5G_WF1)) + fgDbDcModeEn = FALSE; +#endif + + DBGLOG(REQ, INFO, "RSDB:%d\n", fgDbDcModeEn); + + u4Offset += kalScnprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "RSDB:%d", + fgDbDcModeEn); + + i4BytesWritten = (int32_t)u4Offset; + + return i4BytesWritten; + +} + +static int priv_driver_get_cnm(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + struct PARAM_GET_CNM_T *prCnmInfo = NULL; + + enum ENUM_DBDC_BN eDbdcIdx, eDbdcIdxMax; + uint8_t ucBssIdx; + struct BSS_INFO *prBssInfo; + enum ENUM_CNM_NETWORK_TYPE_T eNetworkType; + uint8_t ucOpRxNss, ucOpTxNss; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + + prCnmInfo = (struct PARAM_GET_CNM_T *)kalMemAlloc( + sizeof(struct PARAM_GET_CNM_T), VIR_MEM_TYPE); + if (prCnmInfo == NULL) + return -1; + + kalMemZero(prCnmInfo, sizeof(struct PARAM_GET_CNM_T)); + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryCnm, prCnmInfo, + sizeof(struct PARAM_GET_CNM_T), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + if (rStatus != WLAN_STATUS_SUCCESS) { + kalMemFree(prCnmInfo, + VIR_MEM_TYPE, sizeof(struct PARAM_GET_CNM_T)); + return -1; + } + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\n[CNM Info]\n"); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "DBDC Mode : %s\n\n", + (prCnmInfo->fgIsDbdcEnable) ? + "Enable" : "Disable"); + + eDbdcIdxMax = (prCnmInfo->fgIsDbdcEnable)?ENUM_BAND_NUM:ENUM_BAND_1; + for (eDbdcIdx = ENUM_BAND_0; eDbdcIdx < eDbdcIdxMax; eDbdcIdx++) { + /* Do not clean history information */ + /* if argc is bigger than 1 */ + if (i4Argc < 2) { + if (prCnmInfo->ucOpChNum[eDbdcIdx] < 3) + prCnmInfo->ucChList[eDbdcIdx][2] = 0; + if (prCnmInfo->ucOpChNum[eDbdcIdx] < 2) + prCnmInfo->ucChList[eDbdcIdx][1] = 0; + if (prCnmInfo->ucOpChNum[eDbdcIdx] < 1) + prCnmInfo->ucChList[eDbdcIdx][0] = 0; + } + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Band %u OPCH %d [%u, %u, %u]\n", + eDbdcIdx, + prCnmInfo->ucOpChNum[eDbdcIdx], + prCnmInfo->ucChList[eDbdcIdx][0], + prCnmInfo->ucChList[eDbdcIdx][1], + prCnmInfo->ucChList[eDbdcIdx][2]); + } + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\n"); + + for (ucBssIdx = BSSID_0; ucBssIdx < (BSSID_NUM+1); ucBssIdx++) { + + prBssInfo = prGlueInfo->prAdapter->aprBssInfo[ucBssIdx]; + if (!prBssInfo) + continue; + + eNetworkType = cnmGetBssNetworkType(prBssInfo); + if (prCnmInfo->ucBssInuse[ucBssIdx] && + prCnmInfo->ucBssActive[ucBssIdx] && + ((eNetworkType == ENUM_CNM_NETWORK_TYPE_P2P_GO) || + ((eNetworkType == ENUM_CNM_NETWORK_TYPE_AIS || + eNetworkType == ENUM_CNM_NETWORK_TYPE_P2P_GC) && + (prCnmInfo->ucBssConnectState[ucBssIdx] == + MEDIA_STATE_CONNECTED)))) { + ucOpRxNss = prBssInfo->ucOpRxNss; + if (eNetworkType == ENUM_CNM_NETWORK_TYPE_P2P_GO) { + struct STA_RECORD *prCurrStaRec = + (struct STA_RECORD *) NULL; + + prCurrStaRec = LINK_PEEK_HEAD( + &prBssInfo->rStaRecOfClientList, + struct STA_RECORD, rLinkEntry); + + if (prCurrStaRec != NULL && + IS_CONNECTION_NSS2(prBssInfo, + prCurrStaRec)) { + ucOpTxNss = 2; + } else + ucOpTxNss = 1; + + ucOpRxNss = prBssInfo->ucOpRxNss; + } else if (prBssInfo->prStaRecOfAP != NULL && + IS_CONNECTION_NSS2(prBssInfo, + prBssInfo->prStaRecOfAP)) { + ucOpTxNss = 2; + } else + ucOpTxNss = 1; + } else { + eNetworkType = ENUM_CNM_NETWORK_TYPE_OTHER; + ucOpTxNss = prBssInfo->ucOpTxNss; + ucOpRxNss = prBssInfo->ucOpRxNss; + /* Do not show history information */ + /* if argc is 1 */ + if (i4Argc < 2) + continue; + } + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "BSS%u Inuse%u Act%u ConnStat%u [NetType%u][CH%3u][DBDC b%u][WMM%u b%u][OMAC%u b%u][BW%3u][TxNSS%u][RxNss%u]\n", + ucBssIdx, + prCnmInfo->ucBssInuse[ucBssIdx], + prCnmInfo->ucBssActive[ucBssIdx], + prCnmInfo->ucBssConnectState[ucBssIdx], + eNetworkType, + prCnmInfo->ucBssCh[ucBssIdx], + prCnmInfo->ucBssDBDCBand[ucBssIdx], + prCnmInfo->ucBssWmmSet[ucBssIdx], + prCnmInfo->ucBssWmmDBDCBand[ucBssIdx], + prCnmInfo->ucBssOMACSet[ucBssIdx], + prCnmInfo->ucBssOMACDBDCBand[ucBssIdx], + 20 * (0x01 << rlmGetBssOpBwByVhtAndHtOpInfo(prBssInfo)), + ucOpTxNss, + ucOpRxNss); +#ifdef CONFIG_SUPPORT_OPENWRT + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "BW=BW%u\n", + 20 * (0x01 << rlmGetBssOpBwByVhtAndHtOpInfo(prBssInfo)) + ); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "[TxNSS%u][RxNss%u]\n", + ucOpTxNss, ucOpRxNss); + +#if (CFG_SUPPORT_802_11AX == 1) + { + + struct STA_RECORD *prStaRec; + + prStaRec = cnmGetStaRecByAddress(prGlueInfo->prAdapter, + ucBssIdx, prBssInfo->aucBSSID); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "Mcs1=%u\n", + (prStaRec->u2HeRxMcsMapBW80) & 0x3); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "Mcs2=%u\n", + ((prStaRec->u2HeRxMcsMapBW80) >> 2) & 0x3); + } +#endif /* CFG_SUPPORT_802_11AX */ +#endif + + } + + kalMemFree(prCnmInfo, VIR_MEM_TYPE, sizeof(struct PARAM_GET_CNM_T)); + return i4BytesWritten; +} /* priv_driver_get_sw_ctrl */ + +static int priv_driver_get_ch_rank_list(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t i4BytesWritten = 0; + int8_t ucIdx = 0, ucIdx2 = 0, ucChannelNum = 0, + ucNumOf2gChannel = 0, ucNumOf5gChannel = 0; + struct PARAM_GET_CHN_INFO *prChnLoadInfo = NULL; + struct RF_CHANNEL_INFO *prChannelList = NULL, + auc2gChannelList[MAX_2G_BAND_CHN_NUM], + auc5gChannelList[MAX_5G_BAND_CHN_NUM]; + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prChnLoadInfo = &(prGlueInfo->prAdapter->rWifiVar.rChnLoadInfo); + kalMemZero(pcCommand, i4TotalLen); + + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_2G4, TRUE, + MAX_2G_BAND_CHN_NUM, &ucNumOf2gChannel, + auc2gChannelList); + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_5G, TRUE, + MAX_5G_BAND_CHN_NUM, &ucNumOf5gChannel, + auc5gChannelList); + + for (ucIdx = 0; ucIdx < MAX_CHN_NUM; ucIdx++) { + + if (prChnLoadInfo->rChnRankList[ucIdx].ucChannel > 14) { + prChannelList = auc5gChannelList; + ucChannelNum = ucNumOf5gChannel; + } else { + prChannelList = auc2gChannelList; + ucChannelNum = ucNumOf2gChannel; + } + + for (ucIdx2 = 0; ucIdx2 < ucChannelNum; ucIdx2++) { + if (prChnLoadInfo->rChnRankList[ucIdx].ucChannel == + prChannelList[ucIdx2].ucChannelNum) { + pcCommand[i4BytesWritten++] = + prChnLoadInfo->rChnRankList[ucIdx] + .ucChannel; + DBGLOG(SCN, TRACE, "ch %u, dirtiness %d\n", + prChnLoadInfo->rChnRankList[ucIdx] + .ucChannel, + prChnLoadInfo->rChnRankList[ucIdx] + .u4Dirtiness); + break; + } + } + } + + return i4BytesWritten; +} + +static int priv_driver_get_ch_dirtiness(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int8_t cIdx = 0; + uint8_t ucNumOf2gChannel = 0; + uint8_t ucNumOf5gChannel = 0; + uint32_t i4BytesWritten = 0; + struct PARAM_GET_CHN_INFO *prChnLoadInfo = NULL; + struct RF_CHANNEL_INFO ar2gChannelList[MAX_2G_BAND_CHN_NUM]; + struct RF_CHANNEL_INFO ar5gChannelList[MAX_5G_BAND_CHN_NUM]; + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prChnLoadInfo = &(prGlueInfo->prAdapter->rWifiVar.rChnLoadInfo); + kalMemZero(pcCommand, i4TotalLen); + + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_2G4, TRUE, + MAX_2G_BAND_CHN_NUM, &ucNumOf2gChannel, + ar2gChannelList); + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_5G, TRUE, + MAX_5G_BAND_CHN_NUM, &ucNumOf5gChannel, + ar5gChannelList); + + for (cIdx = 0; cIdx < MAX_CHN_NUM; cIdx++) { + int8_t cIdx2 = 0; + uint8_t ucChannelNum = 0; + uint32_t u4Offset = 0; + struct RF_CHANNEL_INFO *prChannelList = NULL; + + if (prChnLoadInfo->rChnRankList[cIdx].ucChannel > 14) { + prChannelList = ar5gChannelList; + ucChannelNum = ucNumOf5gChannel; + } else { + prChannelList = ar2gChannelList; + ucChannelNum = ucNumOf2gChannel; + } + + for (cIdx2 = 0; cIdx2 < ucChannelNum; cIdx2++) { + if (prChnLoadInfo->rChnRankList[cIdx].ucChannel == + prChannelList[cIdx2].ucChannelNum) { + u4Offset = kalSprintf( + pcCommand + i4BytesWritten, + "\nch %03u -> dirtiness %u", + prChnLoadInfo->rChnRankList[cIdx] + .ucChannel, + prChnLoadInfo->rChnRankList[cIdx] + .u4Dirtiness); + i4BytesWritten += u4Offset; + break; + } + } + } + + return i4BytesWritten; +} + +static int priv_driver_efuse_ops(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + enum EFUSE_OP_MODE { + EFUSE_READ, + EFUSE_WRITE, + EFUSE_FREE, + EFUSE_INVALID, + }; + uint8_t ucOpMode = EFUSE_INVALID; + uint8_t ucOpChar; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret; + int32_t i4Parameter = 0; + uint32_t u4Efuse_addr = 0; + uint8_t ucEfuse_value = 0; + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4Offset = 0; + uint32_t u4BufLen = 0; + uint8_t u4Index = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_ACCESS_EFUSE rAccessEfuseInfo; +#endif + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + /* Sanity check */ + if (i4Argc < 2) + goto efuse_op_invalid; + + ucOpChar = (uint8_t)apcArgv[1][0]; + if ((i4Argc == 3) && (ucOpChar == 'r' || ucOpChar == 'R')) + ucOpMode = EFUSE_READ; + else if ((i4Argc == 4) && (ucOpChar == 'w' || ucOpChar == 'W')) + ucOpMode = EFUSE_WRITE; + else if ((ucOpChar == 'f' || ucOpChar == 'F')) + ucOpMode = EFUSE_FREE; + + /* Print out help if input format is wrong */ + if (ucOpMode == EFUSE_INVALID) + goto efuse_op_invalid; + + /* convert address */ + if (ucOpMode == EFUSE_READ || ucOpMode == EFUSE_WRITE) { + u4Ret = kalkStrtos32(apcArgv[2], 16, &i4Parameter); + u4Efuse_addr = (uint32_t)i4Parameter; + } + + /* convert value */ + if (ucOpMode == EFUSE_WRITE) { + u4Ret = kalkStrtos32(apcArgv[3], 16, &i4Parameter); + ucEfuse_value = (uint8_t)i4Parameter; + } + + /* Start operation */ +#if (CFG_EEPROM_PAGE_ACCESS == 1) + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + if (prGlueInfo == NULL) { + DBGLOG(REQ, ERROR, "prGlueInfo is null\n"); + goto efuse_op_invalid; + } + + if (prGlueInfo && + prGlueInfo->prAdapter && + prGlueInfo->prAdapter->chip_info && + !prGlueInfo->prAdapter->chip_info->is_support_efuse) { + u4Offset += kalSnprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "efuse ops is invalid\n"); + return (int32_t)u4Offset; + } + + kalMemSet(&rAccessEfuseInfo, 0, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + rAccessEfuseInfo.u4Address = (u4Efuse_addr / EFUSE_BLOCK_SIZE) + * EFUSE_BLOCK_SIZE; + + u4Index = u4Efuse_addr % EFUSE_BLOCK_SIZE; + + if (ucOpMode == EFUSE_READ) { + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfo, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_SUCCESS) { + u4Offset += kalSnprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "Read success 0x%X = 0x%X\n", u4Efuse_addr, + prGlueInfo->prAdapter->aucEepromVaule[u4Index]); + } + } else if (ucOpMode == EFUSE_WRITE) { + + prGlueInfo->prAdapter->aucEepromVaule[u4Index] = ucEfuse_value; + + kalMemCopy(rAccessEfuseInfo.aucData, + prGlueInfo->prAdapter->aucEepromVaule, 16); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseWrite, + &rAccessEfuseInfo, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), + FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus == WLAN_STATUS_SUCCESS) { + u4Offset += kalSnprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "Write success 0x%X = 0x%X\n", + u4Efuse_addr, ucEfuse_value); + } + } else if (ucOpMode == EFUSE_FREE) { + struct PARAM_CUSTOM_EFUSE_FREE_BLOCK rEfuseFreeBlock = {}; + + if (prGlueInfo->prAdapter->fgIsSupportGetFreeEfuseBlockCount + == FALSE) { + u4Offset += kalSnprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "Cannot read free block size\n"); + return (int32_t)u4Offset; + } + rStatus = kalIoctl(prGlueInfo, wlanoidQueryEfuseFreeBlock, + &rEfuseFreeBlock, + sizeof(struct PARAM_CUSTOM_EFUSE_FREE_BLOCK), + TRUE, TRUE, TRUE, &u4BufLen); + if (rStatus == WLAN_STATUS_SUCCESS) { + u4Offset += kalSnprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "Free block size 0x%X\n", + prGlueInfo->prAdapter->u4FreeBlockNum); + } + } +#else + u4Offset += kalSnprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "efuse ops is invalid\n"); +#endif + + return (int32_t)u4Offset; + +efuse_op_invalid: + + u4Offset += kalSnprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "\nHelp menu\n"); + u4Offset += kalSnprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "\tRead:\t\"efuse read addr_hex\"\n"); + u4Offset += kalSnprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "\tWrite:\t\"efuse write addr_hex val_hex\"\n"); + u4Offset += kalSnprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "\tFree Blocks:\t\"efuse free\"\n"); + return (int32_t)u4Offset; +} + +#if defined(_HIF_SDIO) && (MTK_WCN_HIF_SDIO == 0) +static int priv_driver_cccr_ops(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + enum CCCR_OP_MODE { + CCCR_READ, + CCCR_WRITE, + CCCR_FREE, + CCCR_INVALID, + }; + uint8_t ucOpMode = CCCR_INVALID; + uint8_t ucOpChar; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + int32_t i4Ret; + int32_t i4Parameter; + uint32_t u4CCCR_addr = 0; + uint8_t ucCCCR_value = 0; + + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4Offset = 0; + struct GLUE_INFO *prGlueInfo = NULL; + + struct sdio_func *func; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + + if(!IS_SDIO_INF(prGlueInfo)){ + u4Offset += kalSnprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "Not SDIO bus(%d)\n", + prGlueInfo->u4InfType); + return (int32_t)u4Offset; + } + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + /* Sanity check */ + if (i4Argc < 2) + goto cccr_op_invalid; + + ucOpChar = (uint8_t)apcArgv[1][0]; + if ((i4Argc == 3) && (ucOpChar == 'r' || ucOpChar == 'R')) + ucOpMode = CCCR_READ; + else if ((i4Argc == 4) && (ucOpChar == 'w' || ucOpChar == 'W')) + ucOpMode = CCCR_WRITE; + + /* Print out help if input format is wrong */ + if (ucOpMode == CCCR_INVALID) + goto cccr_op_invalid; + + /* convert address */ + if (ucOpMode == CCCR_READ || ucOpMode == CCCR_WRITE) { + i4Ret = kalkStrtos32(apcArgv[2], 16, &i4Parameter); + /* Valid address 0x0~0xFF */ + u4CCCR_addr = (uint32_t)(i4Parameter & 0xFF); + } + + /* convert value */ + if (ucOpMode == CCCR_WRITE) { + i4Ret = kalkStrtos32(apcArgv[3], 16, &i4Parameter); + ucCCCR_value = (uint8_t)i4Parameter; + } + + /* Set SDIO host reference */ + func = prGlueInfo->rHifInfo.func; + + /* Start operation */ + if (ucOpMode == CCCR_READ) { + sdio_claim_host(func); + ucCCCR_value = sdio_f0_readb(func, u4CCCR_addr, &rStatus); + sdio_release_host(func); + + if (rStatus) /* Fail case */ + u4Offset += kalSnprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "Read Fail 0x%X (ret=%d)\n", + u4CCCR_addr, rStatus); + else + u4Offset += kalSnprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "Read success 0x%X = 0x%X\n", + u4CCCR_addr, ucCCCR_value); + } else if (ucOpMode == CCCR_WRITE) { + uint32_t quirks_bak; + sdio_claim_host(func); + /* Enable capability to write CCCR */ + quirks_bak = func->card->quirks; + func->card->quirks |= MMC_QUIRK_LENIENT_FN0; + /* Write CCCR into card */ + sdio_f0_writeb(func, ucCCCR_value, u4CCCR_addr, &rStatus); + func->card->quirks = quirks_bak; + sdio_release_host(func); + + if (rStatus) /* Fail case */ + u4Offset += kalSnprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "Write Fail 0x%X (ret=%d)\n", + u4CCCR_addr, rStatus); + else + u4Offset += kalSnprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "Write success 0x%X = 0x%X\n", + u4CCCR_addr, ucCCCR_value); + } + + return (int32_t)u4Offset; + +cccr_op_invalid: + + u4Offset += kalSnprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "\nHelp menu\n"); + u4Offset += kalSnprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "\tRead:\t\"cccr read addr_hex\"\n"); + u4Offset += kalSnprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "\tWrite:\t\"cccr write addr_hex val_hex\"\n"); + return (int32_t)u4Offset; +} +#endif /* _HIF_SDIO && (MTK_WCN_HIF_SDIO == 0) */ + +#if CFG_SUPPORT_ADVANCE_CONTROL +static int priv_driver_set_noise(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t u4Ret = 0; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_SET_ID + 1; + uint32_t u4Sel = 0; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + rSwCtrlInfo.u4Id = u4Id; + + if (i4Argc <= 1) { + DBGLOG(REQ, ERROR, "Argc(%d) ERR: SET_NOISE \n", i4Argc); + return -1; + } + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Sel); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + + rSwCtrlInfo.u4Data = u4Sel << 30; + DBGLOG(REQ, LOUD, "u4Sel=%d u4Data=0x%x,\n", u4Sel, rSwCtrlInfo.u4Data); + rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, &rSwCtrlInfo, + sizeof(rSwCtrlInfo), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + return i4BytesWritten; + +} + +static int priv_driver_get_noise(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + 1; + uint32_t u4Offset = 0; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + int16_t u2Wf0AvgPwr, u2Wf1AvgPwr; + + ASSERT(prNetDev); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = u4Id; + + rStatus = kalIoctl(prGlueInfo, wlanoidQuerySwCtrlRead, &rSwCtrlInfo, + sizeof(rSwCtrlInfo), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + u2Wf0AvgPwr = rSwCtrlInfo.u4Data & 0xFFFF; + u2Wf1AvgPwr = (rSwCtrlInfo.u4Data >> 16) & 0xFFFF; + + u4Offset += kalSnprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "Noise Idle Avg. Power: WF0:%ddB WF1:%ddB\n", + u2Wf0AvgPwr, u2Wf1AvgPwr); + + i4BytesWritten = (int32_t)u4Offset; + + return i4BytesWritten; + +} /* priv_driver_get_sw_ctrl */ + +static int priv_driver_set_pop(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t u4Ret = 0; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_SET_ID + 2; + uint32_t u4Sel = 0, u4CckTh = 0, u4OfdmTh = 0; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + rSwCtrlInfo.u4Id = u4Id; + + if (i4Argc <= 3) { + DBGLOG(REQ, ERROR, + "Argc(%d) ERR: SET_POP \n", + i4Argc); + return -1; + } + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Sel); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + u4Ret = kalkStrtou32(apcArgv[2], 0, &u4CckTh); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + u4Ret = kalkStrtou32(apcArgv[3], 0, &u4OfdmTh); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + + rSwCtrlInfo.u4Data = (u4CckTh | (u4OfdmTh<<8) | (u4Sel<<30)); + DBGLOG(REQ, LOUD, "u4Sel=%d u4CckTh=%d u4OfdmTh=%d, u4Data=0x%x,\n", + u4Sel, u4CckTh, u4OfdmTh, rSwCtrlInfo.u4Data); + rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, &rSwCtrlInfo, + sizeof(rSwCtrlInfo), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + return i4BytesWritten; + +} + +static int priv_driver_set_ed(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t u4Ret = 0, u4EdVal = 0; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_SET_ID + 3; + uint32_t u4Sel = 0; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + rSwCtrlInfo.u4Id = u4Id; + + if (i4Argc <= 2) { + DBGLOG(REQ, ERROR, + "Argc(%d) ERR: SET_ED \n", + i4Argc); + return -1; + } + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Sel); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + u4Ret = kalkStrtos32(apcArgv[2], 0, &u4EdVal); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + + rSwCtrlInfo.u4Data = ((u4EdVal & 0xFF) | (u4Sel << 31)); + DBGLOG(REQ, LOUD, "u4Sel=%d u4EdCcaVal=%d, u4Data=0x%x,\n", + u4Sel, u4EdVal, rSwCtrlInfo.u4Data); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, &rSwCtrlInfo, + sizeof(rSwCtrlInfo), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + return i4BytesWritten; + +} + +static int priv_driver_get_tp_info(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + return kalPerMonGetInfo(prGlueInfo->prAdapter, pcCommand, i4TotalLen); +} + +static int priv_driver_set_pd(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t u4Ret = 0; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_SET_ID + 4; + uint32_t u4Sel = 0; + int32_t u4CckTh = 0, u4OfdmTh = 0; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + rSwCtrlInfo.u4Id = u4Id; + + if (i4Argc <= 1) { + DBGLOG(REQ, ERROR, + "Argc(%d) ERR: SET_PD [CCK TH] [OFDM TH]\n", + i4Argc); + return -1; + } + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Sel); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + + if (u4Sel == 1) { + if (i4Argc <= 3) { + DBGLOG(REQ, ERROR, + "Argc(%d) ERR: SET_PD 1 \n", + i4Argc); + return -1; + } + u4Ret = kalkStrtos32(apcArgv[2], 0, &u4CckTh); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", + u4Ret); + u4Ret = kalkStrtos32(apcArgv[3], 0, &u4OfdmTh); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", + u4Ret); + } + + rSwCtrlInfo.u4Data = ((u4OfdmTh & 0xFFFF) | ((u4CckTh & 0xFF) << 16) | + (u4Sel << 30)); + DBGLOG(REQ, LOUD, "u4Sel=%d u4OfdmTh=%d, u4CckTh=%d, u4Data=0x%x,\n", + u4Sel, u4OfdmTh, u4CckTh, rSwCtrlInfo.u4Data); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, &rSwCtrlInfo, + sizeof(rSwCtrlInfo), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + return i4BytesWritten; +} + +static int priv_driver_set_maxrfgain(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t u4Ret = 0; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_SET_ID + 5; + uint32_t u4Sel = 0; + int32_t u4Wf0Gain = 0, u4Wf1Gain = 0; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + rSwCtrlInfo.u4Id = u4Id; + + if (i4Argc <= 1) { + DBGLOG(REQ, ERROR, + "Argc(%d) ERR: SET_RFGAIN \n", + i4Argc); + return -1; + } + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Sel); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + + if (u4Sel == 1) { + if (i4Argc <= 3) { + DBGLOG(REQ, ERROR, + "Argc(%d) ERR: SET_RFGAIN 1 \n", + i4Argc); + return -1; + } + u4Ret = kalkStrtos32(apcArgv[2], 0, &u4Wf0Gain); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", + u4Ret); + u4Ret = kalkStrtos32(apcArgv[3], 0, &u4Wf1Gain); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", + u4Ret); + } + + rSwCtrlInfo.u4Data = ((u4Wf0Gain & 0xFF) | ((u4Wf1Gain & 0xFF) << 8) | + (u4Sel << 31)); + DBGLOG(REQ, LOUD, "u4Sel=%d u4Wf0Gain=%d, u4Wf1Gain=%d, u4Data=0x%x,\n", + u4Sel, u4Wf0Gain, u4Wf1Gain, rSwCtrlInfo.u4Data); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, &rSwCtrlInfo, + sizeof(rSwCtrlInfo), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + return i4BytesWritten; +} + +#endif + + +#if (CFG_SUPPORT_TWT == 1) +static int priv_driver_set_twtparams( + struct net_device *prNetDev, + char *pcCommand, + int i4TotalLen) +{ + struct ADAPTER *prAdapter = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX_LONG] = { 0 }; + struct _TWT_CTRL_T rTWTCtrl; + struct _TWT_PARAMS_T *prTWTParams; + uint16_t i; + int32_t u4Ret = 0; + uint16_t au2Setting[CMD_TWT_MAX_PARAMS]; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = NULL; + struct _MSG_TWT_PARAMS_SET_T *prTWTParamSetMsg; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prNetDevPrivate = + (struct NETDEV_PRIVATE_GLUE_INFO *) netdev_priv(prNetDev); + + DBGLOG(REQ, INFO, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, INFO, "argc is %i\n", i4Argc); + + prAdapter = prNetDevPrivate->prGlueInfo->prAdapter; + + /* Check param number and convert TWT params to integer type */ + if (i4Argc == CMD_TWT_ACTION_TEN_PARAMS || + i4Argc == CMD_TWT_ACTION_THREE_PARAMS) { + for (i = 0; i < (i4Argc - 1); i++) { + + u4Ret = kalkStrtou16(apcArgv[i + 1], + 0, &(au2Setting[i])); + + if (u4Ret) + DBGLOG(REQ, INFO, "Argv error ret=%d\n", u4Ret); + } + } else { + DBGLOG(REQ, INFO, "set_twtparams wrong argc : %d\n", i4Argc); + return -1; + } + + if ((IS_TWT_PARAM_ACTION_DEL(au2Setting[0]) || + IS_TWT_PARAM_ACTION_SUSPEND(au2Setting[0]) || + IS_TWT_PARAM_ACTION_RESUME(au2Setting[0])) && + i4Argc == CMD_TWT_ACTION_THREE_PARAMS) { + + DBGLOG(REQ, INFO, "Action=%d\n", au2Setting[0]); + DBGLOG(REQ, INFO, "TWT Flow ID=%d\n", au2Setting[1]); + + if (au2Setting[1] >= TWT_MAX_FLOW_NUM) { + /* Simple sanity check failure */ + DBGLOG(REQ, INFO, "Invalid TWT Params\n"); + return -1; + } + + rTWTCtrl.ucBssIdx = prNetDevPrivate->ucBssIdx; + rTWTCtrl.ucCtrlAction = au2Setting[0]; + rTWTCtrl.ucTWTFlowId = au2Setting[1]; + + } else if (i4Argc == CMD_TWT_ACTION_TEN_PARAMS) { + DBGLOG(REQ, INFO, "Action bitmap=%d\n", au2Setting[0]); + DBGLOG(REQ, INFO, + "TWT Flow ID=%d Setup Command=%d Trig enabled=%d\n", + au2Setting[1], au2Setting[2], au2Setting[3]); + DBGLOG(REQ, INFO, + "Unannounced enabled=%d Wake Interval Exponent=%d\n", + au2Setting[4], au2Setting[5]); + DBGLOG(REQ, INFO, "Protection enabled=%d Duration=%d\n", + au2Setting[6], au2Setting[7]); + DBGLOG(REQ, INFO, "Wake Interval Mantissa=%d\n", au2Setting[8]); + /* + * au2Setting[0]: Whether bypassing nego or not + * au2Setting[1]: TWT Flow ID + * au2Setting[2]: TWT Setup Command + * au2Setting[3]: Trigger enabled + * au2Setting[4]: Unannounced enabled + * au2Setting[5]: TWT Wake Interval Exponent + * au2Setting[6]: TWT Protection enabled + * au2Setting[7]: Nominal Minimum TWT Wake Duration + * au2Setting[8]: TWT Wake Interval Mantissa + */ + if (au2Setting[1] >= TWT_MAX_FLOW_NUM || + au2Setting[2] > TWT_SETUP_CMD_DEMAND || + au2Setting[5] > TWT_MAX_WAKE_INTVAL_EXP) { + /* Simple sanity check failure */ + DBGLOG(REQ, INFO, "Invalid TWT Params\n"); + return -1; + } + + prTWTParams = &(rTWTCtrl.rTWTParams); + kalMemSet(prTWTParams, 0, sizeof(struct _TWT_PARAMS_T)); + prTWTParams->fgReq = TRUE; + prTWTParams->ucSetupCmd = (uint8_t) au2Setting[2]; + prTWTParams->fgTrigger = (au2Setting[3]) ? TRUE : FALSE; + prTWTParams->fgUnannounced = (au2Setting[4]) ? TRUE : FALSE; + prTWTParams->ucWakeIntvalExponent = (uint8_t) au2Setting[5]; + prTWTParams->fgProtect = (au2Setting[6]) ? TRUE : FALSE; + prTWTParams->ucMinWakeDur = (uint8_t) au2Setting[7]; + prTWTParams->u2WakeIntvalMantiss = au2Setting[8]; + + rTWTCtrl.ucBssIdx = prNetDevPrivate->ucBssIdx; + rTWTCtrl.ucCtrlAction = au2Setting[0]; + rTWTCtrl.ucTWTFlowId = au2Setting[1]; + } else { + DBGLOG(REQ, INFO, "wrong argc for update agrt: %d\n", i4Argc); + return -1; + } + + prTWTParamSetMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct _MSG_TWT_REQFSM_RESUME_T)); + if (prTWTParamSetMsg) { + prTWTParamSetMsg->rMsgHdr.eMsgId = + MID_TWT_PARAMS_SET; + kalMemCopy(&prTWTParamSetMsg->rTWTCtrl, + &rTWTCtrl, sizeof(rTWTCtrl)); + + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prTWTParamSetMsg, + MSG_SEND_METHOD_BUF); + } else + return -1; + + return 0; +} +#endif + +#if (CFG_SUPPORT_802_11AX == 1) +int priv_driver_set_pad_dur(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4Parse = 0; + uint8_t u1HePadDur; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc == 2) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + + u1HePadDur = (uint8_t) u4Parse; + + if (u1HePadDur == 0 || u1HePadDur == 8 || + u1HePadDur == 16) { + prGlueInfo->prAdapter->rWifiVar.ucTrigMacPadDur + = u1HePadDur/8; + } else { + DBGLOG(INIT, ERROR, + "iwpriv wlanXX driver SET_PAD_DUR <0,1,2>\n"); + } + } else { + DBGLOG(INIT, ERROR, + "iwpriv wlanXX driver SET_PAD_DUR <0,1,2>\n"); + } + + return i4BytesWritten; +} +#endif + + +static int priv_driver_get_wifi_type(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct PARAM_GET_WIFI_TYPE rParamGetWifiType; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint32_t u4BytesWritten = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) { + DBGLOG(REQ, ERROR, "GLUE_CHK_PR2 fail\n"); + return -1; + } + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + rParamGetWifiType.prNetDev = prNetDev; + rStatus = kalIoctl(prGlueInfo, + wlanoidGetWifiType, + (void *)&rParamGetWifiType, + sizeof(void *), + FALSE, + FALSE, + FALSE, + &u4BytesWritten); + if (rStatus == WLAN_STATUS_SUCCESS) { + if (u4BytesWritten > 0) { + if (u4BytesWritten > i4TotalLen) + u4BytesWritten = i4TotalLen; + kalMemCopy(pcCommand, rParamGetWifiType.arWifiTypeName, + u4BytesWritten); + } + } else { + DBGLOG(REQ, ERROR, "rStatus=%x\n", rStatus); + u4BytesWritten = 0; + } + + return (int)u4BytesWritten; +} + +#if CFG_ENABLE_WIFI_DIRECT +static int priv_driver_set_p2p_ps(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct BSS_INFO *prBssInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t ucRoleIdx; + uint8_t ucBssIdx; + uint32_t u4CTwindowMs; + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecBssInfo = NULL; + struct PARAM_CUSTOM_OPPPS_PARAM_STRUCT *rOppPsParam = NULL; + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc < 2) { + DBGLOG(REQ, ERROR, + "Expect param: . argc=%d now\n", i4Argc); + return -1; + } + + if (kalkStrtou32(apcArgv[1], 0, &ucRoleIdx)) { + DBGLOG(REQ, ERROR, "parse ucRoleIdx error\n"); + return -1; + } + + if (kalkStrtou32(apcArgv[2], 0, &u4CTwindowMs)) { + DBGLOG(REQ, ERROR, "parse u4CTwindowMs error\n"); + return -1; + } + + /* get Bss Index from ndev */ + if (p2pFuncRoleToBssIdx(prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "can't find ucBssIdx\n"); + return -1; + } + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + if (!(prBssInfo->fgIsInUse) || (prBssInfo->eIftype != IFTYPE_P2P_GO)) { + DBGLOG(REQ, ERROR, "wrong bss InUse=%d, iftype=%d\n", + prBssInfo->fgIsInUse, prBssInfo->eIftype); + return -1; + } + + DBGLOG(REQ, INFO, "ucRoleIdx=%d, ucBssIdx=%d, u4CTwindowMs=%d\n", + ucRoleIdx, ucBssIdx, u4CTwindowMs); + + if (u4CTwindowMs > 0) + u4CTwindowMs |= BIT(7); /* FW checks BIT(7) for enable */ + + prP2pSpecBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo[ucRoleIdx]; + rOppPsParam = &prP2pSpecBssInfo->rOppPsParam; + rOppPsParam->u4CTwindowMs = u4CTwindowMs; + rOppPsParam->ucBssIdx = ucBssIdx; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetOppPsParam, rOppPsParam, + sizeof(struct PARAM_CUSTOM_OPPPS_PARAM_STRUCT), + FALSE, FALSE, TRUE, &u4BufLen); + + return !(rStatus == WLAN_STATUS_SUCCESS); +} + +static int priv_driver_set_p2p_noa(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct BSS_INFO *prBssInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint8_t ucBssIdx; + uint32_t ucRoleIdx; + uint32_t u4NoaDurationMs; + uint32_t u4NoaIntervalMs; + uint32_t u4NoaCount; + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecBssInfo = NULL; + struct PARAM_CUSTOM_NOA_PARAM_STRUCT *rNoaParam = NULL; + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc < 4) { + DBGLOG(REQ, ERROR, + "SET_P2P_NOA \n"); + return -1; + } + + if (kalkStrtou32(apcArgv[1], 0, &ucRoleIdx)) { + DBGLOG(REQ, ERROR, "parse ucRoleIdx error\n"); + return -1; + } + + if (kalkStrtou32(apcArgv[2], 0, &u4NoaCount)) { + DBGLOG(REQ, ERROR, "parse u4NoaCount error\n"); + return -1; + } + + if (kalkStrtou32(apcArgv[3], 0, &u4NoaIntervalMs)) { + DBGLOG(REQ, ERROR, "parse u4NoaIntervalMs error\n"); + return -1; + } + + if (kalkStrtou32(apcArgv[4], 0, &u4NoaDurationMs)) { + DBGLOG(REQ, ERROR, "parse u4NoaDurationMs error\n"); + return -1; + } + + /* get Bss Index from ndev */ + if (p2pFuncRoleToBssIdx(prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "can't find ucBssIdx\n"); + return -1; + } + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + if (!(prBssInfo->fgIsInUse) || (prBssInfo->eIftype != IFTYPE_P2P_GO)) { + DBGLOG(REQ, ERROR, "wrong bss InUse=%d, iftype=%d\n", + prBssInfo->fgIsInUse, prBssInfo->eIftype); + return -1; + } + + DBGLOG(REQ, INFO, + "RoleIdx=%d, BssIdx=%d, count=%d, interval=%d, duration=%d\n", + ucRoleIdx, ucBssIdx, u4NoaCount, u4NoaIntervalMs, + u4NoaDurationMs); + + prP2pSpecBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo[ucRoleIdx]; + rNoaParam = &prP2pSpecBssInfo->rNoaParam; + rNoaParam->u4NoaCount = u4NoaCount; + rNoaParam->u4NoaIntervalMs = u4NoaIntervalMs; + rNoaParam->u4NoaDurationMs = u4NoaDurationMs; + rNoaParam->ucBssIdx = ucBssIdx; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetNoaParam, rNoaParam, + sizeof(struct PARAM_CUSTOM_NOA_PARAM_STRUCT), + FALSE, FALSE, TRUE, &u4BufLen); + + return !(rStatus == WLAN_STATUS_SUCCESS); +} +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +static int priv_driver_set_drv_ser(struct net_device *prNetDev, + char *pcCommand, int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t i4Argc = 0; + int32_t i4BytesWritten = 0; + uint32_t u4Num = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc <= 0) { + DBGLOG(REQ, ERROR, "Argc(%d) ERR: Set driver SER\n", i4Argc); + return -1; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidSetDrvSer, + (void *)&u4Num, sizeof(uint32_t), + FALSE, FALSE, FALSE, &u4BufLen); + + i4BytesWritten += kalSnprintf(pcCommand, i4TotalLen, + "trigger driver SER\n"); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + return i4BytesWritten; +} + +#ifdef UT_TEST_MODE +int priv_driver_run_ut(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + int32_t u4Ret = 0; + uint32_t u4Input = 0; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + if (!prGlueInfo || !prGlueInfo->prAdapter) { + DBGLOG(REQ, ERROR, "prGlueInfo or prAdapter is NULL\n"); + return -1; + } + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc < 2) { + DBGLOG(REQ, ERROR, "Argc(%d) ERR: RUN_UT COMMAND\n", i4Argc); + return -1; + } + + if (strlen(apcArgv[1]) == strlen("all") && + strnicmp(apcArgv[1], "all", strlen("all")) == 0) + testRunAllTestCases(prGlueInfo->prAdapter); + else if (i4Argc >= 3) { + if (strlen(apcArgv[1]) == strlen("tc") && + strnicmp(apcArgv[1], "tc", strlen("tc")) == 0) { + u4Ret = kalkStrtou32(apcArgv[2], 0, &u4Input); + if (u4Ret) { + DBGLOG(REQ, ERROR, "parse error u4Ret=%d\n", + u4Ret); + return -1; + } + testRunTestCase(prGlueInfo->prAdapter, u4Input); + + } else if (strlen(apcArgv[1]) == strlen("group") && + strnicmp(apcArgv[1], "group", + strlen("group")) == 0) { + testRunGroupTestCases(prGlueInfo->prAdapter, + apcArgv[2]); + + } else if (strlen(apcArgv[1]) == strlen("list") && + strnicmp(apcArgv[1], "list", strlen("list")) == 0) { + if (strlen(apcArgv[2]) == strlen("all") && + strnicmp(apcArgv[2], "all", strlen("all")) == 0) { + testRunAllTestCaseLists(prGlueInfo->prAdapter); + } else { + u4Ret = kalkStrtou32(apcArgv[2], 0, &u4Input); + if (u4Ret) { + DBGLOG(REQ, ERROR, + "parse error u4Ret=%d\n", u4Ret); + return -1; + } + testRunTestCaseList(prGlueInfo->prAdapter, + u4Input); + } + } + } + + return 0; +} +#endif /* UT_TEST_MODE */ + +static int priv_driver_set_amsdu_num(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t i4Argc = 0; + int32_t i4BytesWritten = 0; + int32_t u4Ret = 0; + uint32_t u4Num = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc <= 1) { + DBGLOG(REQ, ERROR, "Argc(%d) ERR: Sw Amsdu Num\n", i4Argc); + return -1; + } + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Num); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse amsdu num error u4Ret=%d\n", u4Ret); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAmsduNum, + (void *)&u4Num, sizeof(uint32_t), + FALSE, FALSE, FALSE, &u4BufLen); + + i4BytesWritten += kalSnprintf(pcCommand, i4TotalLen, + "Set Sw Amsdu Num:%u\n", u4Num); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + return i4BytesWritten; + +} + +static int priv_driver_set_amsdu_size(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t i4Argc = 0; + int32_t i4BytesWritten = 0; + int32_t u4Ret = 0; + uint32_t u4Size = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc <= 1) { + DBGLOG(REQ, ERROR, "Argc(%d) ERR: Sw Amsdu Max Size\n", i4Argc); + return -1; + } + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Size); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse amsdu size error u4Ret=%d\n", u4Ret); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAmsduSize, + (void *)&u4Size, sizeof(uint32_t), + FALSE, FALSE, FALSE, &u4BufLen); + + i4BytesWritten += kalSnprintf(pcCommand, i4TotalLen, + "Set Sw Amsdu Max Size:%u\n", u4Size); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + return i4BytesWritten; + +} + +#if (CFG_SUPPORT_CONNINFRA == 1) +static int priv_driver_trigger_whole_chip_reset( + struct net_device *prNetDev, + char *pcCommand, + int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct mt66xx_chip_info *prChipInfo; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if ((!prGlueInfo) || + (prGlueInfo->u4ReadyFlag == 0) || + kalIsResetting()) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -1; + } + prChipInfo = prGlueInfo->prAdapter->chip_info; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + glSetRstReason(RST_CMD_TRIGGER); + glSetRstReasonString( + "cmd test trigger whole chip reset"); + if (prChipInfo->trigger_wholechiprst) + prChipInfo->trigger_wholechiprst(g_reason); + + return i4BytesWritten; +} +static int priv_driver_trigger_wfsys_reset( + struct net_device *prNetDev, + char *pcCommand, + int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if ((!prGlueInfo) || + (prGlueInfo->u4ReadyFlag == 0) || + kalIsResetting()) { + DBGLOG(REQ, WARN, "driver is not ready\n"); + return -1; + } + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + glSetRstReason(RST_CMD_TRIGGER); + GL_RESET_TRIGGER(prGlueInfo->prAdapter, RST_FLAG_WF_RESET); + + return i4BytesWritten; +} +#endif +#if (CFG_SUPPORT_CONNAC2X == 1) +static int priv_driver_get_umac_fwtbl( + struct net_device *prNetDev, + char *pcCommand, + int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Argc = 0; + int32_t u4Ret = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Index = 0; + struct CHIP_DBG_OPS *prDbgOps; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= 2) + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Index); + + if (u4Ret) + return -1; + + prDbgOps = prGlueInfo->prAdapter->chip_info->prDebugOps; + + if (prDbgOps->showUmacFwtblInfo) + return prDbgOps->showUmacFwtblInfo( + prGlueInfo->prAdapter, u4Index, pcCommand, i4TotalLen); + else + return -1; +} +#endif /* CFG_SUPPORT_CONNAC2X == 1 */ + +static int priv_driver_show_txd_info( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen +) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t u4Ret = -1; + int32_t idx = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + struct CHIP_DBG_OPS *prDbgOps; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prDbgOps = prGlueInfo->prAdapter->chip_info->prDebugOps; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= 2) + u4Ret = kalkStrtos32(apcArgv[1], 16, &idx); + + if (!u4Ret && prDbgOps && prDbgOps->showTxdInfo) { + DBGLOG(HAL, INFO, "idx = %d 0x%x\n", idx, idx); + prDbgOps->showTxdInfo(prGlueInfo->prAdapter, idx); + } + return i4BytesWritten; +} +#if (CONFIG_WLAN_SERVICE == 1) +int8_t *RxStatCommonUser[] = { + /* common user stat info */ + "rx_fifo_full : 0x%08x\n", + "aci_hit_low : 0x%08x\n", + "aci_hit_high : 0x%08x\n", + "mu_pkt_cnt : 0x%08x\n", + "sig_mcs : 0x%08x\n", + "sinr : 0x%08x\n", + "driver_rx_count: 0x%08x\n" +}; + +int8_t *RxStatPerUser[] = { + /* per user stat info */ + "freq_ofst_from_rx: 0x%08x\n", + "snr : 0x%08x\n", + "fcs_err_cnt : 0x%08x\n" +}; + +int8_t *RxStatPerAnt[] = { + /* per anternna stat info */ + "rcpi : %d\n", + "rssi : %d\n", + "fagc_ib_rssi : %d\n", + "fagc_wb_rssi : %d\n", + "inst_ib_rssi : %d\n", + "inst_wb_rssi : %d\n" +}; + +int8_t *RxStatPerBand[] = { + /* per band stat info */ + "mac_fcs_err_cnt : 0x%08x\n", + "mac_mdy_cnt : 0x%08x\n", + "mac_len_mismatch: 0x%08x\n", + "mac_fcs_ok_cnt : 0x%08x\n", + "phy_fcs_err_cnt_cck: 0x%08x\n", + "phy_fcs_err_cnt_ofdm: 0x%08x\n", + "phy_pd_cck : 0x%08x\n", + "phy_pd_ofdm : 0x%08x\n", + "phy_sig_err_cck : 0x%08x\n", + "phy_sfd_err_cck : 0x%08x\n", + "phy_sig_err_ofdm: 0x%08x\n", + "phy_tag_err_ofdm: 0x%08x\n", + "phy_mdy_cnt_cck : 0x%08x\n", + "phy_mdy_cnt_ofdm: 0x%08x\n" +}; + +int32_t priv_driver_rx_stat_parser( + IN uint8_t *dataptr, + IN int i4TotalLen, + OUT char *pcCommand +) +{ + int32_t i4BytesWritten = 0; + int32_t i4tmpContent = 0; + int32_t i4TypeNum = 0, i4Type = 0, i4Version = 0; + int32_t i = 0, j = 0, i4ItemMask = 0, i4TypeLen = 0, i4SubLen = 0; + /*Get type num*/ + i4TypeNum = NTOHL(dataptr[3] << 24 | dataptr[2] << 16 | + dataptr[1] << 8 | dataptr[0]); + dataptr += 4; + DBGLOG(REQ, LOUD, "i4TypeNum is %x\n", i4TypeNum); + while (i4TypeNum) { + i4TypeNum--; + /*Get type*/ + i4Type = NTOHL(dataptr[3] << 24 | dataptr[2] << 16 | + dataptr[1] << 8 | dataptr[0]); + dataptr += 4; + DBGLOG(REQ, LOUD, "i4Type is %x\n", i4Type); + + /*Get Version*/ + i4Version = NTOHL(dataptr[3] << 24 | dataptr[2] << 16 | + dataptr[1] << 8 | dataptr[0]); + dataptr += 4; + DBGLOG(REQ, LOUD, "i4Version is %x\n", i4Version); + + /*Get Item Mask*/ + i4ItemMask = NTOHL(dataptr[3] << 24 | dataptr[2] << 16 | + dataptr[1] << 8 | dataptr[0]); + j = i4ItemMask; + dataptr += 4; + DBGLOG(REQ, LOUD, "i4ItemMask is %x\n", i4ItemMask); + + /*Get Len*/ + i4TypeLen = NTOHL(dataptr[3] << 24 | dataptr[2] << 16 | + dataptr[1] << 8 | dataptr[0]); + dataptr += 4; + DBGLOG(REQ, LOUD, "i4TypeLen is %x\n", i4TypeLen); + + /*Get Sub Len*/ + while (j) { + i++; + j = j >> 1; + } + + if (i != 0) + i4SubLen = i4TypeLen / i; + + i = 0; + DBGLOG(REQ, LOUD, "i4SubLen is %x\n", i4SubLen); + + while (i4TypeLen) { + while (i < i4SubLen) { + /*Get Content*/ + i4tmpContent = NTOHL(dataptr[3] << 24 | + dataptr[2] << 16 | dataptr[1] << 8 | + dataptr[0]); + DBGLOG(REQ, LOUD, + "i4tmpContent is %x\n", i4tmpContent); + + if (i4Type == 0) { + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen, RxStatPerBand[i/4], + i4tmpContent); + } else if (i4Type == 1) { + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen, RxStatPerAnt[i/4], + i4tmpContent); + } else if (i4Type == 2) { + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen, RxStatPerUser[i/4], + i4tmpContent); + } else { + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen, + RxStatCommonUser[i/4], + i4tmpContent); + } + i += 4; + dataptr += 4; + } + i = 0; + i4TypeLen -= i4SubLen; + } + } + return i4BytesWritten; +} +#endif + +static int priv_driver_run_hqa( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int8_t *this_char = NULL; +#if (CONFIG_WLAN_SERVICE == 1) + struct hqa_frame_ctrl local_hqa; + bool IsShowRxStat = FALSE; + uint8_t *dataptr = NULL; + uint8_t *oridataptr = NULL; + int32_t datalen = 0; + int32_t oridatalen = 0; + int32_t ret = WLAN_STATUS_FAILURE; + int16_t i2tmpVal = 0; + int32_t i4tmpVal = 0; +#endif + int32_t i = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + + /*Roll over "HQA ", handle xxx=y,y,y,y,y,y....*/ + /* iwpriv wlan0 driver HQA xxx=y,y,y,y,y,y.....*/ + this_char = kalStrStr(pcCommand, "HQA "); + if (!this_char) + return -1; + this_char += strlen("HQA "); + + /*handle white space*/ + i = strspn(this_char, " "); + this_char += i; + + DBGLOG(REQ, LOUD, "this_char is %s\n", this_char); +#if (CONFIG_WLAN_SERVICE == 1) + if (this_char) { + if (strncasecmp(this_char, + "GetRXStatisticsAllNew", + strlen("GetRXStatisticsAllNew")) == 0) + IsShowRxStat = TRUE; + + local_hqa.type = 1; + local_hqa.hqa_frame_comm.hqa_frame_string = this_char; + ret = mt_agent_hqa_cmd_handler(&prGlueInfo->rService, + &local_hqa); + } + + if (ret != WLAN_STATUS_SUCCESS) + return -1; + + datalen = NTOHS(local_hqa.hqa_frame_comm.hqa_frame_eth->length); + dataptr = kalMemAlloc(datalen, VIR_MEM_TYPE); + if (dataptr == NULL) + return -1; + + /* Backup Original Ptr /Len for mem Free */ + oridataptr = dataptr; + oridatalen = datalen; + kalMemCopy(dataptr, + local_hqa.hqa_frame_comm.hqa_frame_eth->data, datalen); + + DBGLOG(REQ, LOUD, + "priv_driver_run_hqa datalen is %d\n", datalen); + DBGLOG_MEM8(REQ, LOUD, dataptr, datalen); + + /*parsing ret 2 bytes*/ + if ((dataptr) && (datalen)) { + i2tmpVal = dataptr[1] << 8 | dataptr[0]; + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, + "Return : 0x%04x\n", i2tmpVal); + + datalen -= 2; + dataptr += 2; + } else { + DBGLOG(REQ, ERROR, + "priv_driver_run_hqa not support\n"); + kalMemFree(oridataptr, VIR_MEM_TYPE, oridatalen); + return -1; + } + + /*parsing remaining data n bytes ( 4 bytes per parameter)*/ + for (i = 0; i < datalen ; i += 4, dataptr += 4) { + if ((dataptr) && (datalen)) { + i4tmpVal = dataptr[3] << 24 | dataptr[2] << 16 | + dataptr[1] << 8 | dataptr[0]; + if (datalen == 4) { + i4BytesWritten += + kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen, "ExtId : 0x%08x\n", i4tmpVal); + } else if (datalen == 8) { + i4BytesWritten += + kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen, "Band%d TX : 0x%08x\n", i/4, + NTOHL(i4tmpVal)); + } else { + if (IsShowRxStat) { + i += datalen; + i4BytesWritten += + priv_driver_rx_stat_parser(dataptr, + i4TotalLen, pcCommand + i4BytesWritten); + } else { + i4BytesWritten += + kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen, "id%d : 0x%08x\n", i/4, + NTOHL(i4tmpVal)); + } + } + } + } + kalMemFree(oridataptr, VIR_MEM_TYPE, oridatalen); +#else + DBGLOG(REQ, ERROR, + "wlan_service not support\n"); +#endif + return i4BytesWritten; + +} + +static int priv_driver_calibration( + struct net_device *prNetDev, + char *pcCommand, + int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct mt66xx_chip_info *prChipInfo; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4GetInput = 0, u4GetInput2 = 0; + int32_t i4ArgNum = 2; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prChipInfo = prGlueInfo->prAdapter->chip_info; + + DBGLOG(RFTEST, INFO, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(RFTEST, INFO, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4GetInput); + if (u4Ret) { + DBGLOG(RFTEST, INFO, + "%s: Parsing Fail\n", __func__); + } else if (u4GetInput == 0) { + + i4BytesWritten = kalSnprintf(pcCommand, + i4TotalLen, + "reset driver calibration result\n"); + + if (prChipInfo->calDebugCmd) + prChipInfo->calDebugCmd(u4GetInput, 0); + + } else if (u4GetInput == 1) { + + u4Ret = kalkStrtou32(apcArgv[2], 0, &u4GetInput2); + if (u4Ret) { + DBGLOG(RFTEST, INFO, + "%s: Parsing 2 Fail\n", __func__); + } else if (u4GetInput2 == 0) { + i4BytesWritten = kalSnprintf(pcCommand, + i4TotalLen, + "driver result write back EMI\n"); + } else { + i4BytesWritten = kalSnprintf(pcCommand, + i4TotalLen, + "FW use EMI original data\n"); + } + + if (prChipInfo->calDebugCmd) + prChipInfo->calDebugCmd(u4GetInput, + u4GetInput2); + } + } else { + i4BytesWritten = kalSnprintf(pcCommand, + i4TotalLen, + "support parameter as below:\n"); + + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "0: reset driver calibration result\n"); + + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "1,0: driver result write back EMI\n"); + + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "1,1: FW use EMI original data\n"); + } + + return i4BytesWritten; +} + +static int priv_driver_get_nvram(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret; + int32_t i4ArgNum = 2; + uint32_t u4Offset = 0; + uint16_t u2Index = 0; + struct PARAM_CUSTOM_EEPROM_RW_STRUCT rNvrRwInfo; + struct WIFI_CFG_PARAM_STRUCT *prNvSet; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + kalMemZero(&rNvrRwInfo, sizeof(rNvrRwInfo)); + + prNvSet = prGlueInfo->rRegInfo.prNvramSettings; + ASSERT(prNvSet); + + + DBGLOG(REQ, INFO, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, INFO, "argc is %i\n", i4Argc); + + + if (i4Argc == i4ArgNum) { + u4Ret = kalkStrtou16(apcArgv[1], 0, &u2Index); + + if (u4Ret) + DBGLOG(REQ, INFO, + "parse get_nvram error (Index) u4Ret=%d\n", + u4Ret); + + + DBGLOG(REQ, INFO, "Index is 0x%x\n", u2Index); + + /* NVRAM Check */ + if (prGlueInfo->fgNvramAvailable == TRUE) + u4Offset += snprintf(pcCommand + u4Offset, + (i4TotalLen - u4Offset), + "NVRAM Version is[%d.%d.%d]\n", + (prNvSet->u2Part1OwnVersion & 0x00FF), + (prNvSet->u2Part1OwnVersion & 0xFF00) >> 8, + (prNvSet->u2Part1PeerVersion & 0xFF)); + else { + u4Offset += snprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "[WARNING] NVRAM is unavailable!\n"); + + return (int32_t) u4Offset; + } + + rNvrRwInfo.ucMethod = PARAM_EEPROM_READ_NVRAM; + rNvrRwInfo.info.rNvram.u2NvIndex = u2Index; + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryNvramRead, + &rNvrRwInfo, sizeof(rNvrRwInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, INFO, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + u4Offset += snprintf(pcCommand + u4Offset, + (i4TotalLen - u4Offset), + "NVRAM [0x%02X] = %d (0x%02X)\n", + (unsigned int)rNvrRwInfo.info.rNvram.u2NvIndex, + (unsigned int)rNvrRwInfo.info.rNvram.u2NvData, + (unsigned int)rNvrRwInfo.info.rNvram.u2NvData); + + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, + pcCommand); + } + + return (int32_t)u4Offset; + +} /* priv_driver_get_nvram */ + +int priv_driver_set_nvram(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Ret; + int32_t i4ArgNum = 3; + + struct PARAM_CUSTOM_EEPROM_RW_STRUCT rNvRwInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, INFO, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, INFO, "argc is %i\n", i4Argc); + + kalMemZero(&rNvRwInfo, sizeof(rNvRwInfo)); + + if (i4Argc >= i4ArgNum) { + + rNvRwInfo.ucMethod = PARAM_EEPROM_WRITE_NVRAM; + + u4Ret = kalkStrtou16(apcArgv[1], 0, + &(rNvRwInfo.info.rNvram.u2NvIndex)); + if (u4Ret) + DBGLOG(REQ, ERROR, + "parse set_nvram error (Add) Ret=%d\n", + u4Ret); + + u4Ret = kalkStrtou16(apcArgv[2], 0, + &(rNvRwInfo.info.rNvram.u2NvData)); + if (u4Ret) + DBGLOG(REQ, ERROR, + "parse set_nvram error (Data) Ret=%d\n", + u4Ret); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetNvramWrite, + &rNvRwInfo, sizeof(rNvRwInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + } else + DBGLOG(INIT, ERROR, + "[Error]iwpriv wlanXX driver set_nvram [addr] [value]\n"); + + + return i4BytesWritten; + +} + +typedef int(*PRIV_CMD_FUNCTION) ( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen); + +struct PRIV_CMD_HANDLER { + uint8_t *pcCmdStr; + PRIV_CMD_FUNCTION pfHandler; +}; + +struct PRIV_CMD_HANDLER priv_cmd_handlers[] = { + {CMD_RSSI, NULL /*wl_android_get_rssi*/}, + {CMD_AP_START, priv_driver_set_ap_start}, + {CMD_LINKSPEED, priv_driver_get_linkspeed}, + {CMD_PNOSSIDCLR_SET, NULL /*Nothing*/}, + {CMD_PNOSETUP_SET, NULL /*Nothing*/}, + {CMD_PNOENABLE_SET, NULL /*Nothing*/}, + {CMD_SETSUSPENDOPT, NULL /*wl_android_set_suspendopt*/}, + {CMD_SETSUSPENDMODE, priv_driver_set_suspend_mode}, + {CMD_SETBAND, priv_driver_set_band}, + {CMD_GETBAND, NULL /*wl_android_get_band*/}, + {CMD_COUNTRY, priv_driver_set_country}, + {CMD_CSA, priv_driver_set_csa}, + {CMD_GET_COUNTRY, priv_driver_get_country}, + {CMD_GET_CHANNELS, priv_driver_get_channels}, + {CMD_MIRACAST, priv_driver_set_miracast}, + /* Mediatek private command */ + {CMD_SET_SW_CTRL, priv_driver_set_sw_ctrl}, +#if (CFG_SUPPORT_RA_GEN == 1) + {CMD_SET_FIXED_FALLBACK, priv_driver_set_fixed_fallback}, + {CMD_SET_RA_DBG, priv_driver_set_ra_debug_proc}, +#endif +#if (CFG_SUPPORT_TXPOWER_INFO == 1) + {CMD_GET_TX_POWER_INFO, priv_driver_get_txpower_info}, +#endif + {CMD_TX_POWER_MANUAL_SET, priv_driver_txpower_man_set}, + {CMD_SET_FIXED_RATE, priv_driver_set_fixed_rate}, + {CMD_GET_SW_CTRL, priv_driver_get_sw_ctrl}, + {CMD_SET_MCR, priv_driver_set_mcr}, + {CMD_GET_MCR, priv_driver_get_mcr}, + {CMD_SET_DRV_MCR, priv_driver_set_drv_mcr}, + {CMD_GET_DRV_MCR, priv_driver_get_drv_mcr}, + {CMD_SET_TEST_MODE, priv_driver_set_test_mode}, + {CMD_SET_TEST_CMD, priv_driver_set_test_cmd}, + {CMD_GET_TEST_RESULT, priv_driver_get_test_result}, + {CMD_GET_STA_STAT2, priv_driver_get_sta_stat2}, + {CMD_GET_STA_STAT, priv_driver_get_sta_stat}, + {CMD_GET_STA_RX_STAT, priv_driver_show_rx_stat}, + {CMD_SET_ACL_POLICY, priv_driver_set_acl_policy}, + {CMD_ADD_ACL_ENTRY, priv_driver_add_acl_entry}, + {CMD_DEL_ACL_ENTRY, priv_driver_del_acl_entry}, + {CMD_SHOW_ACL_ENTRY, priv_driver_show_acl_entry}, + {CMD_CLEAR_ACL_ENTRY, priv_driver_clear_acl_entry}, +#if (CFG_SUPPORT_DFS_MASTER == 1) + {CMD_SHOW_DFS_STATE, priv_driver_show_dfs_state}, + {CMD_SHOW_DFS_RADAR_PARAM, priv_driver_show_dfs_radar_param}, + {CMD_SHOW_DFS_HELP, priv_driver_show_dfs_help}, + {CMD_SHOW_DFS_CAC_TIME, priv_driver_show_dfs_cac_time}, +#endif +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST + {CMD_SET_CALBACKUP_TEST_DRV_FW, priv_driver_set_calbackup_test_drv_fw}, +#endif +#if CFG_WOW_SUPPORT + {CMD_WOW_START, priv_driver_set_wow}, + {CMD_SET_WOW_ENABLE, priv_driver_set_wow_enable}, + {CMD_SET_WOW_PAR, priv_driver_set_wow_par}, + {CMD_SET_WOW_UDP, priv_driver_set_wow_udpport}, + {CMD_SET_WOW_TCP, priv_driver_set_wow_tcpport}, + {CMD_GET_WOW_PORT, priv_driver_get_wow_port}, +#endif + {CMD_SET_ADV_PWS, priv_driver_set_adv_pws}, + {CMD_SET_MDTIM, priv_driver_set_mdtim}, +#if CFG_SUPPORT_QA_TOOL + {CMD_GET_RX_STATISTICS, priv_driver_get_rx_statistics}, +#if CFG_SUPPORT_BUFFER_MODE + {CMD_SETBUFMODE, priv_driver_set_efuse_buffer_mode}, +#endif +#endif +#if CFG_SUPPORT_MSP +#if 0 + {CMD_GET_STAT, priv_driver_get_stat}, +#endif + {CMD_GET_STA_STATISTICS, priv_driver_get_sta_statistics}, + {CMD_GET_BSS_STATISTICS, priv_driver_get_bss_statistics}, + {CMD_GET_STA_IDX, priv_driver_get_sta_index}, + {CMD_GET_STA_INFO, priv_driver_get_sta_info}, + {CMD_GET_WTBL_INFO, priv_driver_get_wtbl_info}, + {CMD_GET_MIB_INFO, priv_driver_get_mib_info}, + {CMD_SET_FW_LOG, priv_driver_set_fw_log}, +#endif + {CMD_SET_CFG, priv_driver_set_cfg}, + {CMD_GET_CFG, priv_driver_get_cfg}, + {CMD_SET_EM_CFG, priv_driver_set_em_cfg}, + {CMD_GET_EM_CFG, priv_driver_get_em_cfg}, + {CMD_SET_CHIP, priv_driver_set_chip_config}, + {CMD_GET_CHIP, priv_driver_get_chip_config}, + {CMD_GET_VERSION, priv_driver_get_version}, + {CMD_GET_CNM, priv_driver_get_cnm}, + {CMD_GET_CAPAB_RSDB, priv_driver_get_capab_rsdb}, +#if CFG_SUPPORT_DBDC + {CMD_SET_DBDC, priv_driver_set_dbdc}, +#endif /*CFG_SUPPORT_DBDC*/ +#if CFG_SUPPORT_SNIFFER + {CMD_SETMONITOR, priv_driver_set_monitor}, +#endif + {CMD_GET_QUE_INFO, priv_driver_get_que_info}, + {CMD_GET_MEM_INFO, priv_driver_get_mem_info}, + {CMD_GET_HIF_INFO, priv_driver_get_hif_info}, + {CMD_GET_TP_INFO, priv_driver_get_tp_info}, + {CMD_GET_CH_RANK_LIST, priv_driver_get_ch_rank_list}, + {CMD_GET_CH_DIRTINESS, priv_driver_get_ch_dirtiness}, + {CMD_EFUSE, priv_driver_efuse_ops}, +#if defined(_HIF_SDIO) && (MTK_WCN_HIF_SDIO == 0) + {CMD_CCCR, priv_driver_cccr_ops}, +#endif /* _HIF_SDIO && (MTK_WCN_HIF_SDIO == 0) */ +#if CFG_SUPPORT_ADVANCE_CONTROL + {CMD_SET_NOISE, priv_driver_set_noise}, + {CMD_GET_NOISE, priv_driver_get_noise}, + {CMD_SET_POP, priv_driver_set_pop}, + {CMD_SET_ED, priv_driver_set_ed}, + {CMD_SET_PD, priv_driver_set_pd}, + {CMD_SET_MAX_RFGAIN, priv_driver_set_maxrfgain}, +#endif + {CMD_SET_DRV_SER, priv_driver_set_drv_ser}, + {CMD_SET_SW_AMSDU_NUM, priv_driver_set_amsdu_num}, + {CMD_SET_SW_AMSDU_SIZE, priv_driver_set_amsdu_size}, +#if CFG_ENABLE_WIFI_DIRECT + {CMD_P2P_SET_PS, priv_driver_set_p2p_ps}, + {CMD_P2P_SET_NOA, priv_driver_set_p2p_noa}, +#endif +#ifdef UT_TEST_MODE + {CMD_RUN_UT, priv_driver_run_ut}, +#endif /* UT_TEST_MODE */ + {CMD_GET_WIFI_TYPE, priv_driver_get_wifi_type}, +#if CFG_SUPPORT_DYNAMIC_PWR_LIMIT + {CMD_SET_PWR_CTRL, priv_driver_set_power_control}, +#endif +#if CFG_SUPPORT_ANT_SWAP + {CMD_SET_ANT_SWAP, priv_driver_set_ant_swap}, +#endif +#if (CFG_SUPPORT_CONNINFRA == 1) + {CMD_SET_WHOLE_CHIP_RESET, priv_driver_trigger_whole_chip_reset}, + {CMD_SET_WFSYS_RESET, priv_driver_trigger_wfsys_reset}, +#endif +#if (CFG_SUPPORT_CONNAC2X == 1) + {CMD_GET_FWTBL_UMAC, priv_driver_get_umac_fwtbl}, +#endif /* CFG_SUPPORT_CONNAC2X == 1 */ + {CMD_SHOW_TXD_INFO, priv_driver_show_txd_info}, + {CMD_GET_MU_RX_PKTCNT, priv_driver_show_rx_stat}, + {CMD_RUN_HQA, priv_driver_run_hqa}, + {CMD_CALIBRATION, priv_driver_calibration}, + {CMD_SET_STA1NSS, priv_driver_set_sta1ss}, + {CMD_SET_NVRAM, priv_driver_set_nvram}, + {CMD_GET_NVRAM, priv_driver_get_nvram}, +#if CFG_SUPPORT_SCAN_EXT_FLAG + {CMD_SET_SCAN_EXT_FLAG, priv_driver_set_scan_ext_flag}, +#endif +}; + +int32_t priv_driver_cmds(IN struct net_device *prNetDev, IN int8_t *pcCommand, + IN int32_t i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4CmdFound = 0; + int i; + + if (g_u4HaltFlag) { + DBGLOG(REQ, WARN, "wlan is halt, skip priv_driver_cmds\n"); + return -1; + } + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + for (i = 0; i < sizeof(priv_cmd_handlers) / sizeof(struct + PRIV_CMD_HANDLER); i++) { + if (strnicmp(pcCommand, + priv_cmd_handlers[i].pcCmdStr, + strlen(priv_cmd_handlers[i].pcCmdStr)) == 0) { + + if (priv_cmd_handlers[i].pfHandler != NULL) { + i4BytesWritten = + priv_cmd_handlers[i].pfHandler( + prNetDev, + pcCommand, + i4TotalLen); + i4CmdFound = 1; + } + } + } + + if (i4CmdFound == 0) { + i4CmdFound = 1; + if (strnicmp(pcCommand, CMD_RSSI, strlen(CMD_RSSI)) == 0) { + /* i4BytesWritten = + * wl_android_get_rssi(net, command, i4TotalLen); + */ +#if CFG_SUPPORT_BATCH_SCAN + } else if (strnicmp(pcCommand, CMD_BATCH_SET, + strlen(CMD_BATCH_SET)) == 0) { + kalIoctl(prGlueInfo, wlanoidSetBatchScanReq, + (void *) pcCommand, i4TotalLen, + FALSE, FALSE, TRUE, &i4BytesWritten); + } else if (strnicmp(pcCommand, CMD_BATCH_GET, + strlen(CMD_BATCH_GET)) == 0) { + /* strcpy(pcCommand, "BATCH SCAN DATA FROM FIRMWARE"); + */ + /* i4BytesWritten = + * strlen("BATCH SCAN DATA FROM FIRMWARE") + * + 1; + */ + /* i4BytesWritten = priv_driver_get_linkspeed (prNetDev, + * pcCommand, i4TotalLen); + */ + + uint32_t u4BufLen; + int i; + /* int rlen=0; */ + + for (i = 0; i < CFG_BATCH_MAX_MSCAN; i++) { + /* for get which mscan */ + g_rEventBatchResult[i].ucScanCount = i + 1; + + kalIoctl(prGlueInfo, + wlanoidQueryBatchScanResult, + (void *)&g_rEventBatchResult[i], + sizeof(struct EVENT_BATCH_RESULT), + TRUE, TRUE, TRUE, &u4BufLen); + } + +#if 0 + DBGLOG(SCN, INFO, + "Batch Scan Results, scan count = %u\n", + g_rEventBatchResult.ucScanCount); + for (i = 0; i < g_rEventBatchResult.ucScanCount; i++) { + prEntry = &g_rEventBatchResult.arBatchResult[i]; + DBGLOG(SCN, INFO, "Entry %u\n", i); + DBGLOG(SCN, INFO, " BSSID = " MACSTR "\n", + MAC2STR(prEntry->aucBssid)); + DBGLOG(SCN, INFO, " SSID = %s\n", + prEntry->aucSSID); + DBGLOG(SCN, INFO, " SSID len = %u\n", + prEntry->ucSSIDLen); + DBGLOG(SCN, INFO, " RSSI = %d\n", + prEntry->cRssi); + DBGLOG(SCN, INFO, " Freq = %u\n", + prEntry->ucFreq); + } +#endif + + batchConvertResult(&g_rEventBatchResult[0], pcCommand, + i4TotalLen, &i4BytesWritten); + + /* Dump for debug */ + /* print_hex_dump(KERN_INFO, + * "BATCH", DUMP_PREFIX_ADDRESS, 16, 1, pcCommand, + * i4BytesWritten, TRUE); + */ + + } else if (strnicmp(pcCommand, CMD_BATCH_STOP, + strlen(CMD_BATCH_STOP)) == 0) { + kalIoctl(prGlueInfo, wlanoidSetBatchScanReq, + (void *) pcCommand, i4TotalLen, + FALSE, FALSE, TRUE, &i4BytesWritten); +#endif + } +#if CFG_SUPPORT_WIFI_SYSDVT + else if (strnicmp(pcCommand, CMD_SET_TXS_TEST, + strlen(CMD_SET_TXS_TEST)) == 0) + i4BytesWritten = + priv_driver_txs_test(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_TXS_TEST_RESULT, + strlen(CMD_SET_TXS_TEST_RESULT)) == 0) + i4BytesWritten = + priv_driver_txs_test_result(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_RXV_TEST, + strlen(CMD_SET_RXV_TEST)) == 0) + i4BytesWritten = + priv_driver_rxv_test(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_RXV_TEST_RESULT, + strlen(CMD_SET_RXV_TEST_RESULT)) == 0) + i4BytesWritten = + priv_driver_rxv_test_result(prNetDev, + pcCommand, i4TotalLen); +#if CFG_TCP_IP_CHKSUM_OFFLOAD + else if (strnicmp(pcCommand, CMD_SET_CSO_TEST, + strlen(CMD_SET_CSO_TEST)) == 0) + i4BytesWritten = + priv_driver_cso_test(prNetDev, pcCommand, i4TotalLen); +#endif + else if (strnicmp(pcCommand, CMD_SET_TX_AC_TEST, + strlen(CMD_SET_TX_AC_TEST)) == 0) + i4BytesWritten = + priv_driver_set_tx_test_ac(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_TX_TEST, + strlen(CMD_SET_TX_TEST)) == 0) + i4BytesWritten = + priv_driver_set_tx_test(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_SKIP_CH_CHECK, + strlen(CMD_SET_SKIP_CH_CHECK)) == 0) + i4BytesWritten = + priv_driver_skip_legal_ch_check(prNetDev, + pcCommand, i4TotalLen); +#if (CFG_SUPPORT_DMASHDL_SYSDVT) + else if (strnicmp(pcCommand, CMD_SET_DMASHDL_DUMP, + strlen(CMD_SET_DMASHDL_DUMP)) == 0) + i4BytesWritten = + priv_driver_show_dmashdl_allcr(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_DMASHDL_DVT_ITEM, + strlen(CMD_SET_DMASHDL_DVT_ITEM)) == 0) + i4BytesWritten = + priv_driver_dmashdl_dvt_item(prNetDev, + pcCommand, i4TotalLen); +#endif /* CFG_SUPPORT_DMASHDL_SYSDVT */ +#endif /* CFG_SUPPORT_WIFI_SYSDVT */ + else if (strnicmp(pcCommand, CMD_DBG_SHOW_TR_INFO, + strlen(CMD_DBG_SHOW_TR_INFO)) == 0) { + kalIoctl(prGlueInfo, + wlanoidShowPdmaInfo, + (void *) pcCommand, i4TotalLen, + FALSE, FALSE, TRUE, &i4BytesWritten); + } else if (strnicmp(pcCommand, CMD_DBG_SHOW_PLE_INFO, + strlen(CMD_DBG_SHOW_PLE_INFO)) == 0) { + kalIoctl(prGlueInfo, + wlanoidShowPleInfo, + (void *) pcCommand, i4TotalLen, + FALSE, FALSE, TRUE, &i4BytesWritten); + } else if (strnicmp(pcCommand, CMD_DBG_SHOW_PSE_INFO, + strlen(CMD_DBG_SHOW_PSE_INFO)) == 0) { + kalIoctl(prGlueInfo, + wlanoidShowPseInfo, + (void *) pcCommand, i4TotalLen, + FALSE, FALSE, TRUE, &i4BytesWritten); + } else if (strnicmp(pcCommand, CMD_DBG_SHOW_CSR_INFO, + strlen(CMD_DBG_SHOW_CSR_INFO)) == 0) { + kalIoctl(prGlueInfo, + wlanoidShowCsrInfo, + (void *) pcCommand, i4TotalLen, + FALSE, FALSE, TRUE, &i4BytesWritten); + } else if (strnicmp(pcCommand, CMD_DBG_SHOW_DMASCH_INFO, + strlen(CMD_DBG_SHOW_DMASCH_INFO)) == 0) { + kalIoctl(prGlueInfo, + wlanoidShowDmaschInfo, + (void *) pcCommand, i4TotalLen, + FALSE, FALSE, TRUE, &i4BytesWritten); +#if CFG_SUPPORT_EASY_DEBUG + } else if (strnicmp(pcCommand, CMD_FW_PARAM, + strlen(CMD_FW_PARAM)) == 0) { + kalIoctl(prGlueInfo, wlanoidSetFwParam, + (void *)(pcCommand + 13), + i4TotalLen - 13, FALSE, FALSE, FALSE, + &i4BytesWritten); +#endif /* CFG_SUPPORT_EASY_DEBUG */ + } else if (strnicmp(pcCommand, CMD_GET_WFDMA_INFO, + strlen(CMD_GET_WFDMA_INFO)) == 0) { + kalIoctl(prGlueInfo, + wlanoidShowPdmaInfo, + (void *) pcCommand, i4TotalLen, + FALSE, FALSE, TRUE, &i4BytesWritten); + } else if (strnicmp(pcCommand, CMD_GET_PLE_INFO, + strlen(CMD_GET_PLE_INFO)) == 0) { + kalIoctl(prGlueInfo, + wlanoidShowPleInfo, + (void *) pcCommand, i4TotalLen, + FALSE, FALSE, TRUE, &i4BytesWritten); + } else if (strnicmp(pcCommand, CMD_GET_PSE_INFO, + strlen(CMD_GET_PSE_INFO)) == 0) { + kalIoctl(prGlueInfo, + wlanoidShowPseInfo, + (void *) pcCommand, i4TotalLen, + FALSE, FALSE, TRUE, &i4BytesWritten); + } else if (strnicmp(pcCommand, CMD_GET_DMASCH_INFO, + strlen(CMD_GET_DMASCH_INFO)) == 0) { + kalIoctl(prGlueInfo, + wlanoidShowDmaschInfo, + (void *) pcCommand, i4TotalLen, + FALSE, FALSE, TRUE, &i4BytesWritten); + } else if (!strnicmp(pcCommand, CMD_DUMP_TS, + strlen(CMD_DUMP_TS)) || + !strnicmp(pcCommand, CMD_ADD_TS, + strlen(CMD_ADD_TS)) || + !strnicmp(pcCommand, CMD_DEL_TS, + strlen(CMD_DEL_TS))) { + kalIoctl(prGlueInfo, wlanoidTspecOperation, + (void *)pcCommand, i4TotalLen, FALSE, FALSE, + FALSE, &i4BytesWritten); + } else if (kalStrStr(pcCommand, "-IT")) { + kalIoctl(prGlueInfo, wlanoidPktProcessIT, + (void *)pcCommand, i4TotalLen, FALSE, FALSE, + FALSE, &i4BytesWritten); + } else if (!strnicmp(pcCommand, CMD_FW_EVENT, 9)) { + kalIoctl(prGlueInfo, wlanoidFwEventIT, + (void *)(pcCommand + 9), i4TotalLen, FALSE, + FALSE, FALSE, &i4BytesWritten); + } else if (!strnicmp(pcCommand, CMD_DUMP_UAPSD, + strlen(CMD_DUMP_UAPSD))) { + kalIoctl(prGlueInfo, wlanoidDumpUapsdSetting, + (void *)pcCommand, i4TotalLen, FALSE, FALSE, + FALSE, &i4BytesWritten); +#if CFG_SUPPORT_DYNAMIC_PWR_LIMIT + } else if (strnicmp(pcCommand, CMD_SET_PWR_CTRL, + strlen(CMD_SET_PWR_CTRL)) == 0) { + priv_driver_set_power_control(prNetDev, + pcCommand, i4TotalLen); +#endif +#if CFG_SUPPORT_ANT_SWAP + } else if (strnicmp(pcCommand, CMD_SET_ANT_SWAP, + strlen(CMD_SET_ANT_SWAP)) == 0) { + priv_driver_set_ant_swap(prNetDev, + pcCommand, i4TotalLen); +#endif + } else if (strnicmp(pcCommand, CMD_SET_BF, + strlen(CMD_SET_BF)) == 0) { + i4BytesWritten = priv_driver_set_bf(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_NSS, + strlen(CMD_SET_NSS)) == 0) { + i4BytesWritten = priv_driver_set_nss(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_AMSDU_TX, + strlen(CMD_SET_AMSDU_TX)) == 0) { + i4BytesWritten = priv_driver_set_amsdu_tx(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_AMSDU_RX, + strlen(CMD_SET_AMSDU_RX)) == 0) { + i4BytesWritten = priv_driver_set_amsdu_rx(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_AMPDU_TX, + strlen(CMD_SET_AMPDU_TX)) == 0) { + i4BytesWritten = priv_driver_set_ampdu_tx(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_AMPDU_RX, + strlen(CMD_SET_AMPDU_RX)) == 0) { + i4BytesWritten = priv_driver_set_ampdu_rx(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_QOS, + strlen(CMD_SET_QOS)) == 0) { + i4BytesWritten = priv_driver_set_qos(prNetDev, + pcCommand, i4TotalLen); +#if (CFG_SUPPORT_802_11AX == 1) + } else if (strnicmp(pcCommand, CMD_SET_MUEDCA_OVERRIDE, + strlen(CMD_SET_MUEDCA_OVERRIDE)) == 0) { + i4BytesWritten = priv_driver_muedca_override(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_BA_SIZE, + strlen(CMD_SET_BA_SIZE)) == 0) { + i4BytesWritten = priv_driver_set_ba_size(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_TP_TEST_MODE, + strlen(CMD_SET_TP_TEST_MODE)) == 0) { + i4BytesWritten = priv_driver_set_tp_test_mode(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_TX_MCSMAP, + strlen(CMD_SET_TX_MCSMAP)) == 0) { + i4BytesWritten = priv_driver_set_mcsmap(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_TX_PPDU, + strlen(CMD_SET_TX_PPDU)) == 0) { + i4BytesWritten = priv_driver_set_tx_ppdu(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_LDPC, + strlen(CMD_SET_LDPC)) == 0) { + i4BytesWritten = priv_driver_set_ldpc(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_FORCE_AMSDU_TX, + strlen(CMD_FORCE_AMSDU_TX)) == 0) { + i4BytesWritten = priv_driver_set_tx_force_amsdu( + prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_OM_CH_BW, + strlen(CMD_SET_OM_CH_BW)) == 0) { + i4BytesWritten = priv_driver_set_om_ch_bw(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_OM_RX_NSS, + strlen(CMD_SET_OM_RX_NSS)) == 0) { + i4BytesWritten = priv_driver_set_om_rx_nss(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_OM_TX_NSS, + strlen(CMD_SET_OM_TX_NSS)) == 0) { + i4BytesWritten = priv_driver_set_om_tx_nss(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_OM_MU_DISABLE, + strlen(CMD_SET_OM_MU_DISABLE)) == 0) { + i4BytesWritten = priv_driver_set_om_mu_dis(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_TX_OM_PACKET, + strlen(CMD_SET_TX_OM_PACKET)) == 0) { + i4BytesWritten = priv_driver_set_tx_om_packet(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_TX_CCK_1M_PWR, + strlen(CMD_SET_TX_CCK_1M_PWR)) == 0) { + i4BytesWritten = priv_driver_set_tx_cck_1m_pwr(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_PAD_DUR, + strlen(CMD_SET_PAD_DUR)) == 0) { + i4BytesWritten = priv_driver_set_pad_dur(prNetDev, + pcCommand, i4TotalLen); +#endif + +#if CFG_CHIP_RESET_HANG + } else if (strnicmp(pcCommand, CMD_SET_RST_HANG, + strlen(CMD_SET_RST_HANG)) == 0) { + i4BytesWritten = priv_driver_set_rst_hang( + prNetDev, pcCommand, i4TotalLen); +#endif + +#if (CFG_SUPPORT_TWT == 1) + } else if (strnicmp(pcCommand, CMD_SET_TWT_PARAMS, + strlen(CMD_SET_TWT_PARAMS)) == 0) { + i4BytesWritten = priv_driver_set_twtparams(prNetDev, + pcCommand, i4TotalLen); +#endif + } else + i4BytesWritten = priv_cmd_not_support + (prNetDev, pcCommand, i4TotalLen); + } + + if (i4BytesWritten >= 0) { + if ((i4BytesWritten == 0) && (i4TotalLen > 0)) { + /* reset the command buffer */ + pcCommand[0] = '\0'; + } + + if (i4BytesWritten >= i4TotalLen) { + DBGLOG(REQ, INFO, + "%s: i4BytesWritten %d > i4TotalLen < %d\n", + __func__, i4BytesWritten, i4TotalLen); + i4BytesWritten = i4TotalLen - 1; + } + pcCommand[i4BytesWritten] = '\0'; + i4BytesWritten++; + + } + + return i4BytesWritten; + +} /* priv_driver_cmds */ + +#ifdef CFG_ANDROID_AOSP_PRIV_CMD +int android_private_support_driver_cmd(IN struct net_device *prNetDev, + IN OUT struct ifreq *prReq, IN int i4Cmd) +{ + struct android_wifi_priv_cmd priv_cmd; + char *command = NULL; + int ret = 0, bytes_written = 0; + + if (!prReq->ifr_data) + return -EINVAL; + + if (copy_from_user(&priv_cmd, prReq->ifr_data, sizeof(priv_cmd))) + return -EFAULT; + /* total_len is controlled by the user. need check length */ + if (priv_cmd.total_len <= 0) + return -EINVAL; + + command = kzalloc(priv_cmd.total_len, GFP_KERNEL); + if (!command) { + DBGLOG(REQ, WARN, "%s, alloc mem failed\n", __func__); + return -ENOMEM; + } + + if (copy_from_user(command, priv_cmd.buf, priv_cmd.total_len)) { + ret = -EFAULT; + goto FREE; + } + + bytes_written = priv_driver_cmds(prNetDev, command, priv_cmd.total_len); + + if (bytes_written == -EOPNOTSUPP) { + /* Report positive status */ + bytes_written = kalSnprintf(command, priv_cmd.total_len, + "%s", "NotSupport"); + } + + if (bytes_written >= 0) { + /* priv_cmd in but no response */ + if ((bytes_written == 0) && (priv_cmd.total_len > 0)) + command[0] = '\0'; + + if (bytes_written >= priv_cmd.total_len) + bytes_written = priv_cmd.total_len; + else + bytes_written++; + + priv_cmd.used_len = bytes_written; + + if (copy_to_user(priv_cmd.buf, command, bytes_written)) + ret = -EFAULT; + } else + ret = bytes_written; + +FREE: + kfree(command); + + return ret; +} +#endif /* CFG_ANDROID_AOSP_PRIV_CMD */ + +int priv_support_driver_cmd(IN struct net_device *prNetDev, + IN OUT struct ifreq *prReq, IN int i4Cmd) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int ret = 0; + char *pcCommand = NULL; + struct priv_driver_cmd_s *priv_cmd = NULL; + int i4BytesWritten = 0; + int i4TotalLen = 0; + + if (!prReq->ifr_data) { + ret = -EINVAL; + goto exit; + } + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + if (!prGlueInfo) { + DBGLOG(REQ, WARN, "No glue info\n"); + ret = -EFAULT; + goto exit; + } + if (prGlueInfo->u4ReadyFlag == 0) { + ret = -EINVAL; + goto exit; + } + + priv_cmd = kzalloc(sizeof(struct priv_driver_cmd_s), GFP_KERNEL); + if (!priv_cmd) { + DBGLOG(REQ, WARN, "%s, alloc mem failed\n", __func__); + return -ENOMEM; + } + + if (copy_from_user(priv_cmd, prReq->ifr_data, + sizeof(struct priv_driver_cmd_s))) { + DBGLOG(REQ, INFO, "%s: copy_from_user fail\n", __func__); + ret = -EFAULT; + goto exit; + } + + i4TotalLen = priv_cmd->total_len; + + if (i4TotalLen <= 0 || i4TotalLen > PRIV_CMD_SIZE) { + ret = -EINVAL; + DBGLOG(REQ, INFO, "%s: i4TotalLen invalid\n", __func__); + goto exit; + } + priv_cmd->buf[PRIV_CMD_SIZE - 1] = '\0'; + pcCommand = priv_cmd->buf; + + DBGLOG(REQ, INFO, "%s: driver cmd \"%s\" on %s\n", __func__, pcCommand, + prReq->ifr_name); + + i4BytesWritten = priv_driver_cmds(prNetDev, pcCommand, i4TotalLen); + + if (i4BytesWritten == -EOPNOTSUPP) { + /* Report positive status */ + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, + "%s", "UNSUPPORTED"); + i4BytesWritten++; + } + + if (i4BytesWritten >= 0) { + priv_cmd->used_len = i4BytesWritten; + if ((i4BytesWritten == 0) && (priv_cmd->total_len > 0)) + pcCommand[0] = '\0'; + if (i4BytesWritten >= priv_cmd->total_len) + i4BytesWritten = priv_cmd->total_len; + else + i4BytesWritten++; + priv_cmd->used_len = i4BytesWritten; + if (copy_to_user(prReq->ifr_data, priv_cmd, + sizeof(struct priv_driver_cmd_s))) { + ret = -EFAULT; + DBGLOG(REQ, INFO, "copy fail"); + } + } else + ret = i4BytesWritten; + +exit: + kfree(priv_cmd); + + return ret; +} /* priv_support_driver_cmd */ + +#if CFG_SUPPORT_DYNAMIC_PWR_LIMIT +/* dynamic tx power control */ +static int priv_driver_set_power_control(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_TX_PWR_CTRL_IOCTL rPwrCtrlParam = { 0 }; + u_int8_t fgIndex = FALSE; + char *ptr = pcCommand, *ptr2 = NULL; + char *str = NULL, *cmd = NULL, *name = NULL, *setting = NULL; + uint8_t index = 0; + uint32_t u4SetInfoLen = 0; + + while ((str = strsep(&ptr, " ")) != NULL) { + if (kalStrLen(str) <= 0) + continue; + if (cmd == NULL) + cmd = str; + else if (name == NULL) + name = str; + else if (fgIndex == FALSE) { + ptr2 = str; + if (kalkStrtou8(str, 0, &index) != 0) { + DBGLOG(REQ, INFO, + "index is wrong: %s\n", ptr2); + return -1; + } + fgIndex = TRUE; + } else if (setting == NULL) { + setting = str; + break; + } + } + + if ((name == NULL) || (fgIndex == FALSE)) { + DBGLOG(REQ, INFO, "name(%s) or fgIndex(%d) is wrong\n", + name, fgIndex); + return -1; + } + + rPwrCtrlParam.fgApplied = (index == 0) ? FALSE : TRUE; + rPwrCtrlParam.name = name; + rPwrCtrlParam.index = index; + rPwrCtrlParam.newSetting = setting; + + DBGLOG(REQ, INFO, "applied=[%d], name=[%s], index=[%u], setting=[%s]\n", + rPwrCtrlParam.fgApplied, + rPwrCtrlParam.name, + rPwrCtrlParam.index, + rPwrCtrlParam.newSetting); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + kalIoctl(prGlueInfo, + wlanoidTxPowerControl, + (void *)&rPwrCtrlParam, + sizeof(struct PARAM_TX_PWR_CTRL_IOCTL), + FALSE, + FALSE, + TRUE, + &u4SetInfoLen); + + return 0; +} +#endif + +#if CFG_SUPPORT_ANT_SWAP +/* set ant swap */ +static int priv_driver_set_ant_swap(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + int ant_swap = 0; + char *chain0_main = "SET_CHIP AntSwapManualCtrl 2 0"; + char *chain0_aux = "SET_CHIP AntSwapManualCtrl 2 1"; + + ant_swap = atoi(pcCommand[13]); + DBGLOG(REQ, INFO, "%s ant_swap = %d \n", __func__, ant_swap); + + i4TotalLen = kalStrLen(chain0_main) + 1; + if (ant_swap == 0) { + priv_driver_set_chip_config(prNetDev, chain0_main, i4TotalLen); + } else if (ant_swap == 1) { + priv_driver_set_chip_config(prNetDev, chain0_aux, i4TotalLen); + } else { + DBGLOG(REQ, ERROR, "%s ant_swap err, value = %d \n", __func__, ant_swap); + return -1; + } + + return 0; +} +#endif +#if CFG_SUPPORT_SCAN_EXT_FLAG +/* Xiaom ADD + * argv: 1 means that force scan on gaming mode + */ +static int priv_driver_set_scan_ext_flag(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t i4Argc = 0; + int32_t u4Ret = 0; + uint32_t u4ScanExtFlag = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, INFO, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc <= 1) { + DBGLOG(REQ, ERROR, "Argc(%d) ERR: Scan Ext Flag\n", i4Argc); + return -1; + } + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4ScanExtFlag); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse scan ext flag error u4Ret=%d\n", u4Ret); + if (prGlueInfo == NULL) { + DBGLOG(REQ, ERROR, "prGlueInfo is null\n"); + return -1; + } + prGlueInfo->u4ScanExtFlag = u4ScanExtFlag; + return WLAN_STATUS_SUCCESS; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/axi/axi.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/axi/axi.c new file mode 100644 index 0000000000000..3f3e4b2d8a839 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/axi/axi.c @@ -0,0 +1,1590 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** + *[File] axi.c + *[Version] v1.0 + *[Revision Date] 2010-03-01 + *[Author] + *[Description] + * The program provides AXI HIF driver + *[Copyright] + * Copyright (C) 2010 MediaTek Incorporation. All Rights Reserved. + ******************************************************************************/ + + +/******************************************************************************* + * C O M P I L E 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 "hif_pdma.h" + +#include "precomp.h" + +#include +#include +#include +#include +#ifndef CONFIG_X86 +#include +#endif +#include +#include + +#include "mt66xx_reg.h" + +#include +#include +#include + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +static const struct platform_device_id mtk_axi_ids[] = { + { .name = "CONNAC", +#ifdef CONNAC + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_connac}, +#endif /* CONNAC */ +#ifdef CONNAC2X2 + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_connac2x2}, +#endif /* CONNAC2X2 */ +#ifdef SOC3_0 + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_soc3_0}, +#endif /* SOC3_0 */ + + { /* end: all zeroes */ }, +}; + +MODULE_DEVICE_TABLE(axi, mtk_axi_ids); + +#ifdef CONFIG_OF +const struct of_device_id mtk_axi_of_ids[] = { + {.compatible = "mediatek,wifi",}, + {} +}; +#endif + +/******************************************************************************* + * 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 probe_card pfWlanProbe; +static remove_card pfWlanRemove; + +static struct platform_driver mtk_axi_driver = { + .driver = { + .name = "wlan", + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = mtk_axi_of_ids, +#endif + }, + .id_table = mtk_axi_ids, + .probe = NULL, + .remove = NULL, +}; + +struct platform_device *g_prPlatDev; + +static struct GLUE_INFO *g_prGlueInfo; +static void *CSRBaseAddress; +static u64 g_u8CsrOffset; +static u32 g_u4CsrSize; +static u_int8_t g_fgDriverProbed = FALSE; + +#if AXI_CFG_PREALLOC_MEMORY_BUFFER +struct HIF_PREALLOC_MEM grMem; +unsigned long long gWifiRsvMemSize; + +struct wifi_rsrv_mem { + phys_addr_t phy_base; + void *vir_base; + unsigned long long size; +}; + +/* Assume reserved memory size < BIT(32) */ +static struct wifi_rsrv_mem wifi_rsrv_mems[32]; +#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 AXI_CFG_PREALLOC_MEMORY_BUFFER +static int _init_resv_mem(struct platform_device *pdev); + +static void axiAllocTxDesc(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing, + uint32_t u4Num); +static void axiAllocRxDesc(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing, + uint32_t u4Num); +static bool axiAllocTxCmdBuf(struct RTMP_DMABUF *prDmaBuf, + uint32_t u4Num, uint32_t u4Idx); +#else +static void axiAllocDesc(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing, + uint32_t u4Num); +static void *axiAllocRuntimeMem(uint32_t u4SrcLen); +static phys_addr_t axiMapTxBuf(struct GL_HIF_INFO *prHifInfo, + void *pucBuf, uint32_t u4Offset, uint32_t u4Len); +static phys_addr_t axiMapRxBuf(struct GL_HIF_INFO *prHifInfo, + void *pucBuf, uint32_t u4Offset, uint32_t u4Len); +static void axiUnmapTxBuf(struct GL_HIF_INFO *prHifInfo, + phys_addr_t rDmaAddr, uint32_t u4Len); +static void axiUnmapRxBuf(struct GL_HIF_INFO *prHifInfo, + phys_addr_t rDmaAddr, uint32_t u4Len); +static void axiFreeDesc(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing); +static void axiFreeBuf(void *pucSrc, uint32_t u4Len); +static void axiFreePacket(void *pvPacket); +#endif /* AXI_CFG_PREALLOC_MEMORY_BUFFER */ + +static void axiAllocTxDataBuf(struct MSDU_TOKEN_ENTRY *prToken, uint32_t u4Idx); +static void *axiAllocRxBuf(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDmaBuf, + uint32_t u4Num, uint32_t u4Idx); +static bool axiCopyCmd(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *prTxCell, void *pucBuf, + void *pucSrc1, uint32_t u4SrcLen1, + void *pucSrc2, uint32_t u4SrcLen2); +static bool axiCopyEvent(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *pRxCell, + struct RXD_STRUCT *pRxD, + struct RTMP_DMABUF *prDmaBuf, + uint8_t *pucDst, uint32_t u4Len); +static bool axiCopyTxData(struct MSDU_TOKEN_ENTRY *prToken, + void *pucSrc, uint32_t u4Len); +static bool axiCopyRxData(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *pRxCell, + struct RTMP_DMABUF *prDmaBuf, + struct SW_RFB *prSwRfb); +static void axiDumpTx(struct GL_HIF_INFO *prHifInfo, + struct RTMP_TX_RING *prTxRing, + uint32_t u4Idx, uint32_t u4DumpLen); +static void axiDumpRx(struct GL_HIF_INFO *prHifInfo, + struct RTMP_RX_RING *prRxRing, + uint32_t u4Idx, uint32_t u4DumpLen); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +static struct mt66xx_hif_driver_data *get_platform_driver_data(void) +{ + ASSERT(g_prPlatDev); + if (!g_prPlatDev) + return NULL; + + return (struct mt66xx_hif_driver_data *) platform_get_drvdata( + g_prPlatDev); +} + +static int hifAxiProbe(void) +{ + int ret = 0; + struct mt66xx_hif_driver_data *prDriverData; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(g_prPlatDev); + + prDriverData = get_platform_driver_data(); + prChipInfo = prDriverData->chip_info; + +#if CFG_MTK_ANDROID_WMT +#if (CFG_SUPPORT_CONNINFRA == 0) + mtk_wcn_consys_hw_wifi_paldo_ctrl(1); +#endif +#endif + if (prChipInfo->wmmcupwron) + ret = prChipInfo->wmmcupwron(); + if (ret != 0) { + DBGLOG(INIT, INFO, "wmmcu pwr on fail!\n"); + if (prChipInfo->wmmcupwroff) + prChipInfo->wmmcupwroff(); + goto out; + } + if (pfWlanProbe((void *) g_prPlatDev, (void *) prDriverData) != + WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "pfWlanProbe fail!\n"); + ret = -1; + if (prChipInfo->wmmcupwroff) + prChipInfo->wmmcupwroff(); + goto out; + } + g_fgDriverProbed = TRUE; +out: + DBGLOG(INIT, TRACE, "hifAxiProbe() done(%d)\n", ret); + + return ret; +} + +int hifAxiRemove(void) +{ + struct mt66xx_hif_driver_data *prDriverData; + struct mt66xx_chip_info *prChipInfo; + + prDriverData = get_platform_driver_data(); + prChipInfo = prDriverData->chip_info; + + if (g_fgDriverProbed) { + pfWlanRemove(); + DBGLOG(INIT, TRACE, "pfWlanRemove done\n"); + } + +#if (CFG_SUPPORT_CONNINFRA == 1) + if (prChipInfo->coexpccifoff) { + prChipInfo->coexpccifoff(); + DBGLOG(INIT, TRACE, "pccif off\n"); + } +#endif + + if (prChipInfo->coantVFE28Dis) + prChipInfo->coantVFE28Dis(); + + if (prChipInfo->wmmcupwroff) + prChipInfo->wmmcupwroff(); +#if CFG_MTK_ANDROID_WMT +#if (CFG_SUPPORT_CONNINFRA == 0) + mtk_wcn_consys_hw_wifi_paldo_ctrl(0); +#endif +#endif + g_fgDriverProbed = FALSE; + + DBGLOG(INIT, TRACE, "hifAxiRemove() done\n"); + return 0; +} + +#if CFG_MTK_ANDROID_WMT +#if (CFG_SUPPORT_CONNINFRA == 0) +static int hifAxiGetBusCnt(void) +{ + if (!g_prGlueInfo) + return 0; + + return g_prGlueInfo->rHifInfo.u4HifCnt; +} + +static int hifAxiClrBusCnt(void) +{ + if (g_prGlueInfo) + g_prGlueInfo->rHifInfo.u4HifCnt = 0; + + return 0; +} + +static int hifAxiSetMpuProtect(bool enable) +{ +#if CFG_MTK_ANDROID_EMI + kalSetEmiMpuProtection(gConEmiPhyBase, enable); +#endif + return 0; +} + + +static int hifAxiIsWifiDrvOwn(void) +{ + if (!g_prGlueInfo || !g_prGlueInfo->prAdapter) + return 0; + + return (g_prGlueInfo->prAdapter->fgIsFwOwn == FALSE) ? 1 : 0; +} +#endif +#endif /* CFG_MTK_ANDROID_WMT */ + +static int axiDmaSetup(struct platform_device *pdev, + struct mt66xx_hif_driver_data *prDriverData) +{ + struct mt66xx_chip_info *prChipInfo; + u64 dma_mask; + int ret = 0; + + prChipInfo = prDriverData->chip_info; + +#if AXI_CFG_PREALLOC_MEMORY_BUFFER + ret = _init_resv_mem(pdev); + if (ret) + goto exit; + ret = of_reserved_mem_device_init(&pdev->dev); + if (ret) { + DBGLOG(INIT, ERROR, "of_reserved_mem_device_init failed(%d).\n", + ret); + goto exit; + } +#else + ret = of_dma_configure(&pdev->dev, pdev->dev.of_node, true); + if (ret) { + DBGLOG(INIT, ERROR, "of_dma_configure failed(%d).\n", + ret); + goto exit; + } +#endif + + dma_mask = DMA_BIT_MASK(prChipInfo->bus_info->u4DmaMask); + ret = dma_set_mask_and_coherent(&pdev->dev, dma_mask); + if (ret) { + DBGLOG(INIT, ERROR, "dma_set_mask_and_coherent failed(%d)\n", + ret); + goto exit; + } + +exit: + return ret; +} + + +static bool axiCsrIoremap(struct platform_device *pdev) +{ +#ifdef CONFIG_OF + struct device_node *node = NULL; + struct resource res; + + node = of_find_compatible_node(NULL, NULL, "mediatek,wifi"); + if (!node) { + DBGLOG(INIT, ERROR, "WIFI-OF: get wifi device node fail\n"); + return false; + } + + if (of_address_to_resource(node, 0, &res)) { + DBGLOG(INIT, ERROR, "WIFI-OF: of_address_to_resource fail\n"); + of_node_put(node); + return false; + } + of_node_put(node); + + g_u8CsrOffset = (u64)res.start; + g_u4CsrSize = resource_size(&res); +#else + g_u8CsrOffset = axi_resource_start(pdev, 0); + g_u4CsrSize = axi_resource_len(pdev, 0); +#endif + if (CSRBaseAddress) { + DBGLOG(INIT, ERROR, "CSRBaseAddress not iounmap!\n"); + return false; + } + + request_mem_region(g_u8CsrOffset, g_u4CsrSize, axi_name(pdev)); + + /* map physical address to virtual address for accessing register */ +#ifdef CONFIG_OF + CSRBaseAddress = of_iomap(node, 0); +#else + CSRBaseAddress = ioremap(g_u8CsrOffset, g_u4CsrSize); +#endif + + if (!CSRBaseAddress) { + DBGLOG(INIT, INFO, + "ioremap failed for device %s, region 0x%X @ 0x%lX\n", + axi_name(pdev), g_u4CsrSize, g_u8CsrOffset); + release_mem_region(g_u8CsrOffset, g_u4CsrSize); + return false; + } + + DBGLOG(INIT, INFO, "CSRBaseAddress:0x%lX ioremap region 0x%X @ 0x%lX\n", + CSRBaseAddress, g_u4CsrSize, g_u8CsrOffset); + + return true; +} + +static void axiCsrIounmap(struct platform_device *pdev) +{ + if (!CSRBaseAddress) + return; + + /* Unmap CSR base address */ + iounmap(CSRBaseAddress); + release_mem_region(g_u8CsrOffset, g_u4CsrSize); + + CSRBaseAddress = NULL; + g_u8CsrOffset = 0; + g_u4CsrSize = 0; +} + +#if AXI_CFG_PREALLOC_MEMORY_BUFFER +static bool axiAllocRsvMem(uint32_t u4Size, struct HIF_MEM *prMem) +{ + /* 8 bytes alignment */ + if (u4Size & 7) + u4Size += 8 - (u4Size & 7); + + if ((grMem.u4Offset + u4Size) >= gWifiRsvMemSize) + return false; + + prMem->pa = grMem.pucRsvMemBase + grMem.u4Offset; + prMem->va = grMem.pucRsvMemVirBase + grMem.u4Offset; + grMem.u4Offset += u4Size; + + return prMem->va != NULL; +} + +static int axiAllocHifMem(struct platform_device *pdev, + struct mt66xx_hif_driver_data *prDriverData) +{ + struct mt66xx_chip_info *prChipInfo; + uint32_t u4Idx; + uint32_t i = sizeof(wifi_rsrv_mems) / sizeof(struct wifi_rsrv_mem); + + prChipInfo = prDriverData->chip_info; + + /* Allocation size should be a power of two */ + while (i > 0) { + i--; + if (!(gWifiRsvMemSize & BIT(i))) + continue; + + wifi_rsrv_mems[i].size = BIT(i); + wifi_rsrv_mems[i].vir_base = KAL_DMA_ALLOC_COHERENT(&pdev->dev, + wifi_rsrv_mems[i].size, + &wifi_rsrv_mems[i].phy_base); + if (!wifi_rsrv_mems[i].vir_base) { + DBGLOG(INIT, ERROR, + "[%d] DMA_ALLOC_COHERENT failed, size: 0x%x\n", + i, wifi_rsrv_mems[i].size); + return -1; + } + if (!grMem.pucRsvMemBase) { + grMem.pucRsvMemBase = wifi_rsrv_mems[i].phy_base; + grMem.pucRsvMemVirBase = wifi_rsrv_mems[i].vir_base; + grMem.u4RsvMemSize = (uint64_t) gWifiRsvMemSize; + } + } + if (!grMem.pucRsvMemBase) + return -1; + DBGLOG(INIT, INFO, "pucRsvMemBase[%pa], pucRsvMemVirBase[%pa]\n", + &grMem.pucRsvMemBase, + &grMem.pucRsvMemVirBase); + + kalSetDrvEmiMpuProtection(grMem.pucRsvMemBase, 0, grMem.u4RsvMemSize); + + for (u4Idx = 0; u4Idx < NUM_OF_TX_RING; u4Idx++) { + if (!axiAllocRsvMem(TX_RING_SIZE * TXD_SIZE, + &grMem.rTxDesc[u4Idx])) + DBGLOG(INIT, ERROR, "TxDesc[%u] alloc fail\n", u4Idx); + } + + if (!axiAllocRsvMem(RX_RING0_SIZE * RXD_SIZE, &grMem.rRxDesc[0])) + DBGLOG(INIT, ERROR, "RxDesc[0] alloc fail\n"); + +#if (CFG_SUPPORT_CONNAC2X == 1) + + if (!axiAllocRsvMem(RX_RING0_SIZE * RXD_SIZE, &grMem.rRxDesc[1])) + DBGLOG(INIT, ERROR, "RxDesc[1] alloc fail\n"); + + if (!axiAllocRsvMem(RX_RING1_SIZE * RXD_SIZE, &grMem.rRxDesc[2])) + DBGLOG(INIT, ERROR, "RxDesc[2] alloc fail\n"); + + if (!axiAllocRsvMem(RX_RING1_SIZE * RXD_SIZE, &grMem.rRxDesc[3])) + DBGLOG(INIT, ERROR, "RxDesc[3] alloc fail\n"); + + if (!axiAllocRsvMem(RX_RING1_SIZE * RXD_SIZE, &grMem.rRxDesc[4])) + DBGLOG(INIT, ERROR, "RxDesc[4] alloc fail\n"); + +#else + + if (!axiAllocRsvMem(RX_RING1_SIZE * RXD_SIZE, &grMem.rRxDesc[1])) + DBGLOG(INIT, ERROR, "RxDesc[1] alloc fail\n"); + +#endif + + for (u4Idx = 0; u4Idx < TX_RING_SIZE; u4Idx++) { + if (!axiAllocRsvMem(AXI_TX_CMD_BUFF_SIZE, + &grMem.rTxCmdBuf[u4Idx])) + DBGLOG(INIT, ERROR, "TxCmdBuf[%u] alloc fail\n", u4Idx); + } + + for (u4Idx = 0; u4Idx < RX_RING0_SIZE; u4Idx++) { + if (!axiAllocRsvMem(CFG_RX_MAX_PKT_SIZE, + &grMem.rRxDataBuf[u4Idx])) + DBGLOG(INIT, ERROR, + "RxDataBuf[%u] alloc fail\n", u4Idx); + } + +#if (CFG_SUPPORT_CONNAC2X == 1) + + for (u4Idx = 0; u4Idx < RX_RING0_SIZE; u4Idx++) { + if (!axiAllocRsvMem(RX_BUFFER_AGGRESIZE, + &grMem.rRxEventBuf[u4Idx])) + DBGLOG(INIT, ERROR, + "RxDataBuf[%u] alloc fail\n", u4Idx); + } + + for (u4Idx = 0; u4Idx < RX_RING1_SIZE; u4Idx++) { + if (!axiAllocRsvMem(RX_BUFFER_AGGRESIZE, + &grMem.wfdma0_rx_ring_idx2[u4Idx])) + DBGLOG(INIT, ERROR, + "RxEventBuf[%u] alloc fail\n", u4Idx); + } + + for (u4Idx = 0; u4Idx < RX_RING1_SIZE; u4Idx++) { + if (!axiAllocRsvMem(RX_BUFFER_AGGRESIZE, + &grMem.wfdma0_rx_ring_idx3[u4Idx])) + DBGLOG(INIT, ERROR, + "RxEventBuf[%u] alloc fail\n", u4Idx); + } + + for (u4Idx = 0; u4Idx < RX_RING1_SIZE; u4Idx++) { + if (!axiAllocRsvMem(RX_BUFFER_AGGRESIZE, + &grMem.wfdma1_rx_ring_idx0[u4Idx])) + DBGLOG(INIT, ERROR, + "RxEventBuf[%u] alloc fail\n", u4Idx); + } +#else + for (u4Idx = 0; u4Idx < RX_RING1_SIZE; u4Idx++) { + if (!axiAllocRsvMem(RX_BUFFER_AGGRESIZE, + &grMem.rRxEventBuf[u4Idx])) + DBGLOG(INIT, ERROR, + "RxEventBuf[%u] alloc fail\n", u4Idx); + } + +#endif + +#if HIF_TX_PREALLOC_DATA_BUFFER + for (u4Idx = 0; u4Idx < HIF_TX_MSDU_TOKEN_NUM; u4Idx++) { + if (!axiAllocRsvMem(AXI_TX_MAX_SIZE_PER_FRAME + + prChipInfo->txd_append_size, + &grMem.rMsduBuf[u4Idx])) + DBGLOG(INIT, ERROR, "MsduBuf[%u] alloc fail\n", u4Idx); + } +#endif + + DBGLOG(INIT, INFO, "grMem.u4Offset[0x%x]\n", grMem.u4Offset); + + return 0; +} + +static void axiFreeHifMem(struct platform_device *pdev) +{ + uint32_t i = 0; + uint32_t count = sizeof(wifi_rsrv_mems) / sizeof(struct wifi_rsrv_mem); + + for (i = 0; i < count; i++) { + if (!wifi_rsrv_mems[i].vir_base) + continue; + KAL_DMA_FREE_COHERENT(&pdev->dev, + wifi_rsrv_mems[i].size, + wifi_rsrv_mems[i].vir_base, + (dma_addr_t) wifi_rsrv_mems[i].phy_base); + } +} + +static int _init_resv_mem(struct platform_device *pdev) +{ +#ifdef CONFIG_OF + int ret = 0; + struct device_node *np; + + np = of_parse_phandle(pdev->dev.of_node, "memory-region", 0); + if (!np) { + DBGLOG(INIT, ERROR, "can NOT find memory-region.\n"); + return -1; + } + + ret = of_property_read_u64_array(np, "size", &gWifiRsvMemSize, 1); + if (ret != 0) + DBGLOG(INIT, ERROR, "get rsrv mem size failed(%d).\n", ret); + else + DBGLOG(INIT, INFO, "gWifiRsvMemSize: 0x%x\n", gWifiRsvMemSize); + + of_node_put(np); + + return ret; +#else + DBGLOG(INIT, ERROR, "kernel option CONFIG_OF not enabled.\n"); + return -1; +#endif +} + +#endif /* AXI_CFG_PREALLOC_MEMORY_BUFFER */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is a AXI interrupt callback function + * + * \param[in] func pointer to AXI handle + * + * \return void + */ +/*----------------------------------------------------------------------------*/ +static irqreturn_t mtk_axi_interrupt(int irq, void *dev_instance) +{ + struct GLUE_INFO *prGlueInfo = NULL; + static DEFINE_RATELIMIT_STATE(_rs, 2 * HZ, 1); + + prGlueInfo = (struct GLUE_INFO *)dev_instance; + if (!prGlueInfo) { + DBGLOG(HAL, INFO, "No glue info in mtk_axi_interrupt()\n"); + return IRQ_NONE; + } + + GLUE_INC_REF_CNT(prGlueInfo->prAdapter->rHifStats.u4HwIsrCount); + halDisableInterrupt(prGlueInfo->prAdapter); + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(HAL, INFO, "GLUE_FLAG_HALT skip INT\n"); + return IRQ_NONE; + } + + kalSetIntEvent(prGlueInfo); + if (__ratelimit(&_rs)) + LOG_FUNC("In HIF ISR.\n"); + + return IRQ_HANDLED; +} +#if (CFG_SUPPORT_CONNINFRA == 1) +void kalSetRstEvent(void) +{ + KAL_WAKE_LOCK(NULL, g_IntrWakeLock); + + set_bit(GLUE_FLAG_RST_START_BIT, &g_ulFlag); + + /* when we got interrupt, we wake up servie thread */ + wake_up_interruptible(&g_waitq_rst); + +} + +static irqreturn_t mtk_sw_interrupt(int irq, void *dev_instance) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct mt66xx_chip_info *prChipInfo; + + prGlueInfo = (struct GLUE_INFO *)dev_instance; + GLUE_INC_REF_CNT(prGlueInfo->prAdapter->rHifStats.u4SwIsrCount); + prChipInfo = prGlueInfo->prAdapter->chip_info; + if (prChipInfo->sw_interrupt_handler) + prChipInfo->sw_interrupt_handler(prGlueInfo->prAdapter); + + return IRQ_HANDLED; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is a AXI probe function + * + * \param[in] func pointer to AXI handle + * \param[in] id pointer to AXI device id table + * + * \return void + */ +/*----------------------------------------------------------------------------*/ +static int mtk_axi_probe(IN struct platform_device *pdev) +{ + struct mt66xx_hif_driver_data *prDriverData; + struct mt66xx_chip_info *prChipInfo; + int ret = 0; +#if CFG_MTK_ANDROID_WMT +#if (CFG_SUPPORT_CONNINFRA == 0) + struct _MTK_WCN_WMT_WLAN_CB_INFO rWmtCb; +#else + struct MTK_WCN_WLAN_CB_INFO rWlanCb; +#endif +#endif + + g_prPlatDev = pdev; + prDriverData = (struct mt66xx_hif_driver_data *) + mtk_axi_ids[0].driver_data; + prChipInfo = prDriverData->chip_info; + prChipInfo->pdev = (void *) pdev; + + platform_set_drvdata(pdev, (void *) prDriverData); + + if (!axiCsrIoremap(pdev)) + goto exit; + + ret = axiDmaSetup(pdev, prDriverData); + if (ret) + goto exit; + +#if AXI_CFG_PREALLOC_MEMORY_BUFFER + ret = axiAllocHifMem(pdev, prDriverData); + if (ret) + goto exit; +#endif + +#if CFG_MTK_ANDROID_WMT +#if (CFG_SUPPORT_CONNINFRA == 0) + memset(&rWmtCb, 0, sizeof(struct _MTK_WCN_WMT_WLAN_CB_INFO)); + rWmtCb.wlan_probe_cb = hifAxiProbe; + rWmtCb.wlan_remove_cb = hifAxiRemove; + rWmtCb.wlan_bus_cnt_get_cb = hifAxiGetBusCnt; + rWmtCb.wlan_bus_cnt_clr_cb = hifAxiClrBusCnt; + rWmtCb.wlan_emi_mpu_set_protection_cb = hifAxiSetMpuProtect; + rWmtCb.wlan_is_wifi_drv_own_cb = hifAxiIsWifiDrvOwn; + mtk_wcn_wmt_wlan_reg(&rWmtCb); +#else + + rWlanCb.wlan_probe_cb = hifAxiProbe; + rWlanCb.wlan_remove_cb = hifAxiRemove; + mtk_wcn_wlan_reg(&rWlanCb); + + if (prChipInfo->conninra_cb_register) + prChipInfo->conninra_cb_register(); + +#endif +#else + hifAxiProbe(); +#endif + +exit: + DBGLOG(INIT, INFO, "mtk_axi_probe() done, ret: %d\n", ret); + return ret; +} + +static int mtk_axi_remove(IN struct platform_device *pdev) +{ + axiCsrIounmap(pdev); + +#if AXI_CFG_PREALLOC_MEMORY_BUFFER + axiFreeHifMem(pdev); +#endif + +#if CFG_MTK_ANDROID_WMT +#if (CFG_SUPPORT_CONNINFRA == 0) + mtk_wcn_wmt_wlan_unreg(); +#else + mtk_wcn_wlan_unreg(); +#endif /*end of CFG_SUPPORT_CONNINFRA == 0*/ +#else + hifAxiRemove(); +#endif + platform_set_drvdata(pdev, NULL); + return 0; +} + +static int mtk_axi_suspend(IN struct platform_device *pdev, + IN pm_message_t state) +{ + return 0; +} + +int mtk_axi_resume(IN struct platform_device *pdev) +{ + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will register pci 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 pci bus + */ +/*----------------------------------------------------------------------------*/ +uint32_t glRegisterBus(probe_card pfProbe, remove_card pfRemove) +{ + int ret = 0; + + ASSERT(pfProbe); + ASSERT(pfRemove); + + pfWlanProbe = pfProbe; + pfWlanRemove = pfRemove; + + mtk_axi_driver.probe = mtk_axi_probe; + mtk_axi_driver.remove = mtk_axi_remove; + + mtk_axi_driver.suspend = mtk_axi_suspend; + mtk_axi_driver.resume = mtk_axi_resume; + + ret = (platform_driver_register(&mtk_axi_driver) == 0) ? + WLAN_STATUS_SUCCESS : WLAN_STATUS_FAILURE; + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will unregister pci bus to the os + * + * \param[in] pfRemove Function pointer to remove card + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void glUnregisterBus(remove_card pfRemove) +{ + if (g_fgDriverProbed) { + pfRemove(); + g_fgDriverProbed = FALSE; + } + platform_driver_unregister(&mtk_axi_driver); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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(struct GLUE_INFO *prGlueInfo, unsigned long ulCookie) +{ + struct GL_HIF_INFO *prHif = NULL; + struct HIF_MEM_OPS *prMemOps; + + g_prGlueInfo = prGlueInfo; + prHif = &prGlueInfo->rHifInfo; + prMemOps = &prHif->rMemOps; + + prHif->pdev = (struct platform_device *)ulCookie; + prHif->prDmaDev = &prHif->pdev->dev; + + prHif->CSRBaseAddress = CSRBaseAddress; + + SET_NETDEV_DEV(prGlueInfo->prDevHandler, &prHif->pdev->dev); + + prGlueInfo->u4InfType = MT_DEV_INF_AXI; + + prHif->fgIsPowerOff = true; + prHif->fgIsDumpLog = false; + +#if AXI_CFG_PREALLOC_MEMORY_BUFFER + prMemOps->allocTxDesc = axiAllocTxDesc; + prMemOps->allocRxDesc = axiAllocRxDesc; + prMemOps->allocTxCmdBuf = axiAllocTxCmdBuf; + prMemOps->allocTxDataBuf = axiAllocTxDataBuf; + prMemOps->allocRxBuf = axiAllocRxBuf; + prMemOps->allocRuntimeMem = NULL; + prMemOps->copyCmd = axiCopyCmd; + prMemOps->copyEvent = axiCopyEvent; + prMemOps->copyTxData = axiCopyTxData; + prMemOps->copyRxData = axiCopyRxData; + prMemOps->mapTxBuf = NULL; + prMemOps->mapRxBuf = NULL; + prMemOps->unmapTxBuf = NULL; + prMemOps->unmapRxBuf = NULL; + prMemOps->freeDesc = NULL; + prMemOps->freeBuf = NULL; + prMemOps->freePacket = NULL; + prMemOps->dumpTx = axiDumpTx; + prMemOps->dumpRx = axiDumpRx; +#else + prMemOps->allocTxDesc = axiAllocDesc; + prMemOps->allocRxDesc = axiAllocDesc; + prMemOps->allocTxCmdBuf = NULL; + prMemOps->allocTxDataBuf = axiAllocTxDataBuf; + prMemOps->allocRxBuf = axiAllocRxBuf; + prMemOps->allocRuntimeMem = axiAllocRuntimeMem; + prMemOps->copyCmd = axiCopyCmd; + prMemOps->copyEvent = axiCopyEvent; + prMemOps->copyTxData = axiCopyTxData; + prMemOps->copyRxData = axiCopyRxData; + prMemOps->mapTxBuf = axiMapTxBuf; + prMemOps->mapRxBuf = axiMapRxBuf; + prMemOps->unmapTxBuf = axiUnmapTxBuf; + prMemOps->unmapRxBuf = axiUnmapRxBuf; + prMemOps->freeDesc = axiFreeDesc; + prMemOps->freeBuf = axiFreeBuf; + prMemOps->freePacket = axiFreePacket; + prMemOps->dumpTx = axiDumpTx; + prMemOps->dumpRx = axiDumpRx; +#endif /* AXI_CFG_PREALLOC_MEMORY_BUFFER */ +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function clears hif related info. + * + * \param[in] prGlueInfo Pointer to glue info structure + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void glClearHifInfo(struct GLUE_INFO *prGlueInfo) +{ +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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) + */ +/*----------------------------------------------------------------------------*/ +u_int8_t glBusInit(void *pvData) +{ + ASSERT(pvData); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Stop bus operation and release resources. + * + * \param[in] pvData A pointer to struct net_device. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void glBusRelease(void *pvData) +{ +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ + +int32_t glBusSetIrq(void *pvData, void *pfnIsr, void *pvCookie) +{ + struct net_device *prNetDevice = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct GL_HIF_INFO *prHifInfo = NULL; + struct platform_device *pdev = NULL; +#ifdef CONFIG_OF + struct device_node *node = NULL; +#endif + int ret = 0; + + ASSERT(pvData); + if (!pvData) + return -1; + + prNetDevice = (struct net_device *)pvData; + prGlueInfo = (struct GLUE_INFO *)pvCookie; + ASSERT(prGlueInfo); + if (!prGlueInfo) + return -1; + + prHifInfo = &prGlueInfo->rHifInfo; + pdev = prHifInfo->pdev; + + prHifInfo->u4IrqId = AXI_WLAN_IRQ_NUMBER; +#ifdef CONFIG_OF + node = of_find_compatible_node(NULL, NULL, "mediatek,wifi"); + if (node) { + prHifInfo->u4IrqId = irq_of_parse_and_map(node, 0); +#if (CFG_SUPPORT_CONNINFRA == 1) + prHifInfo->u4IrqId_1 = irq_of_parse_and_map(node, 1); +#endif + } + else + DBGLOG(INIT, ERROR, + "WIFI-OF: get wifi device node fail\n"); +#endif +#if (CFG_SUPPORT_CONNINFRA == 1) + DBGLOG(INIT, INFO, "glBusSetIrq: request_irq num(%d), num(%d)\n", + prHifInfo->u4IrqId, prHifInfo->u4IrqId_1); +#else + DBGLOG(INIT, INFO, "glBusSetIrq: request_irq num(%d)\n", + prHifInfo->u4IrqId); +#endif /*end of CFG_SUPPORT_CONNINFRA == 1*/ + ret = request_irq(prHifInfo->u4IrqId, mtk_axi_interrupt, IRQF_SHARED, + prNetDevice->name, prGlueInfo); + if (ret != 0) { + DBGLOG(INIT, INFO, "request_irq(%u) ERROR(%d)\n", + prHifInfo->u4IrqId, ret); + goto exit; + } +#if KERNEL_VERSION(5, 4, 0) <= CFG80211_VERSION_CODE + ret = enable_irq_wake(prHifInfo->u4IrqId); + if (ret) { + DBGLOG(INIT, INFO, "enable_irq_wake(%u) ERROR(%d)\n", + prHifInfo->u4IrqId, ret); + goto exit; + } +#endif +#if (CFG_SUPPORT_CONNINFRA == 1) + ret = request_irq(prHifInfo->u4IrqId_1, mtk_sw_interrupt, IRQF_SHARED, + prNetDevice->name, prGlueInfo); + if (ret != 0) { + DBGLOG(INIT, INFO, "request_irq(%u) ERROR(%d)\n", + prHifInfo->u4IrqId_1, ret); + goto exit; + } +#if KERNEL_VERSION(5, 4, 0) <= CFG80211_VERSION_CODE + ret = enable_irq_wake(prHifInfo->u4IrqId_1); + if (ret) { + DBGLOG(INIT, INFO, "enable_irq_wake(%u) ERROR(%d)\n", + prHifInfo->u4IrqId_1, ret); + goto exit; + } +#endif +#endif + +exit: + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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(void *pvData, void *pvCookie) +{ + struct net_device *prNetDevice = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct GL_HIF_INFO *prHifInfo = NULL; + struct platform_device *pdev = NULL; + + ASSERT(pvData); + if (!pvData) { + DBGLOG(INIT, INFO, "%s null pvData\n", __func__); + return; + } + prNetDevice = (struct net_device *)pvData; + prGlueInfo = (struct GLUE_INFO *) pvCookie; + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(INIT, INFO, "%s no glue info\n", __func__); + return; + } + + prHifInfo = &prGlueInfo->rHifInfo; + pdev = prHifInfo->pdev; + + synchronize_irq(prHifInfo->u4IrqId); + free_irq(prHifInfo->u4IrqId, prGlueInfo); +#if (CFG_SUPPORT_CONNINFRA == 1) + synchronize_irq(prHifInfo->u4IrqId_1); + free_irq(prHifInfo->u4IrqId_1, prGlueInfo); +#endif +} + +u_int8_t glIsReadClearReg(uint32_t u4Address) +{ + return TRUE; +} + +void glSetPowerState(IN struct GLUE_INFO *prGlueInfo, IN uint32_t ePowerMode) +{ +} + +void glGetDev(void *ctx, struct device **dev) +{ + *dev = &((struct platform_device *)ctx)->dev; +} + +void glGetHifDev(struct GL_HIF_INFO *prHif, struct device **dev) +{ + *dev = &(prHif->pdev->dev); +} + +#if AXI_CFG_PREALLOC_MEMORY_BUFFER +static void axiAllocTxDesc(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing, + uint32_t u4Num) +{ + prDescRing->AllocVa = grMem.rTxDesc[u4Num].va; + prDescRing->AllocPa = grMem.rTxDesc[u4Num].pa; + if (prDescRing->AllocVa == NULL) + DBGLOG(HAL, ERROR, "prDescRing->AllocVa is NULL\n"); + else + memset(prDescRing->AllocVa, 0, prDescRing->AllocSize); +} + +static void axiAllocRxDesc(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing, + uint32_t u4Num) +{ + prDescRing->AllocVa = grMem.rRxDesc[u4Num].va; + prDescRing->AllocPa = grMem.rRxDesc[u4Num].pa; + if (prDescRing->AllocVa == NULL) + DBGLOG(HAL, ERROR, "prDescRing->AllocVa is NULL\n"); + else + memset(prDescRing->AllocVa, 0, prDescRing->AllocSize); +} + +static bool axiAllocTxCmdBuf(struct RTMP_DMABUF *prDmaBuf, + uint32_t u4Num, uint32_t u4Idx) +{ + /* only for cmd & fw download ring */ + if (u4Num == 2 || u4Num == 3) { + prDmaBuf->AllocSize = AXI_TX_CMD_BUFF_SIZE; + prDmaBuf->AllocPa = grMem.rTxCmdBuf[u4Idx].pa; + prDmaBuf->AllocVa = grMem.rTxCmdBuf[u4Idx].va; + if (prDmaBuf->AllocVa == NULL) { + DBGLOG(HAL, ERROR, "prDescRing->AllocVa is NULL\n"); + return false; + } + memset(prDmaBuf->AllocVa, 0, prDmaBuf->AllocSize); + } + return true; +} + +static void axiAllocTxDataBuf(struct MSDU_TOKEN_ENTRY *prToken, uint32_t u4Idx) +{ + prToken->prPacket = grMem.rMsduBuf[u4Idx].va; + prToken->rDmaAddr = grMem.rMsduBuf[u4Idx].pa; +} + +static void *axiAllocRxBuf(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDmaBuf, + uint32_t u4Num, uint32_t u4Idx) +{ + /* ring 0 for data, ring 1 for event */ + if (u4Num == 0) { + prDmaBuf->AllocPa = grMem.rRxDataBuf[u4Idx].pa; + prDmaBuf->AllocVa = grMem.rRxDataBuf[u4Idx].va; + } else if (u4Num == 1) { + prDmaBuf->AllocPa = grMem.rRxEventBuf[u4Idx].pa; + prDmaBuf->AllocVa = grMem.rRxEventBuf[u4Idx].va; + } + /* Add for connac2x RX ring */ +#if (CFG_SUPPORT_CONNAC2X == 1) + + else if (u4Num == 2) { + prDmaBuf->AllocPa = grMem.wfdma0_rx_ring_idx2[u4Idx].pa; + prDmaBuf->AllocVa = grMem.wfdma0_rx_ring_idx2[u4Idx].va; + } else if (u4Num == 3) { + prDmaBuf->AllocPa = grMem.wfdma0_rx_ring_idx3[u4Idx].pa; + prDmaBuf->AllocVa = grMem.wfdma0_rx_ring_idx3[u4Idx].va; + } else if (u4Num == 4) { + prDmaBuf->AllocPa = grMem.wfdma1_rx_ring_idx0[u4Idx].pa; + prDmaBuf->AllocVa = grMem.wfdma1_rx_ring_idx0[u4Idx].va; + } + +#endif + else { + DBGLOG(RX, ERROR, "RX alloc fail error number=%d\n", u4Num); + return prDmaBuf->AllocVa; + } + if (prDmaBuf->AllocVa == NULL) + DBGLOG(HAL, ERROR, "prDmaBuf->AllocVa is NULL\n"); + else + memset(prDmaBuf->AllocVa, 0, prDmaBuf->AllocSize); + + return prDmaBuf->AllocVa; +} + +static bool axiCopyCmd(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *prTxCell, void *pucBuf, + void *pucSrc1, uint32_t u4SrcLen1, + void *pucSrc2, uint32_t u4SrcLen2) +{ + struct RTMP_DMABUF *prDmaBuf = &prTxCell->DmaBuf; + + memcpy(prDmaBuf->AllocVa, pucSrc1, u4SrcLen1); + if (pucSrc2 != NULL && u4SrcLen2 > 0) + memcpy(prDmaBuf->AllocVa + u4SrcLen1, pucSrc2, u4SrcLen2); + prTxCell->PacketPa = prDmaBuf->AllocPa; + + return true; +} + +static bool axiCopyEvent(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *pRxCell, + struct RXD_STRUCT *pRxD, + struct RTMP_DMABUF *prDmaBuf, + uint8_t *pucDst, uint32_t u4Len) +{ + memcpy(pucDst, prDmaBuf->AllocVa, u4Len); + + return true; +} + +static bool axiCopyTxData(struct MSDU_TOKEN_ENTRY *prToken, + void *pucSrc, uint32_t u4Len) +{ + memcpy(prToken->prPacket, pucSrc, u4Len); + + return true; +} + +static bool axiCopyRxData(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *pRxCell, + struct RTMP_DMABUF *prDmaBuf, + struct SW_RFB *prSwRfb) +{ + struct RXD_STRUCT *pRxD = (struct RXD_STRUCT *)pRxCell->AllocVa; + struct sk_buff *prSkb = ((struct sk_buff *)prSwRfb->pvPacket); + uint32_t u4Size = pRxD->SDLen0; + + if (u4Size > CFG_RX_MAX_PKT_SIZE) { + DBGLOG(RX, ERROR, "Rx Data too large[%u]\n", u4Size); + return false; + } + + memcpy(prSkb->data, prDmaBuf->AllocVa, u4Size); + + return true; +} + +static void axiDumpTx(struct GL_HIF_INFO *prHifInfo, + struct RTMP_TX_RING *prTxRing, + uint32_t u4Idx, uint32_t u4DumpLen) +{ + struct RTMP_DMACB *prTxCell; + struct RTMP_DMABUF *prDmaBuf; + void *prAddr = NULL; + + prTxCell = &prTxRing->Cell[u4Idx]; + prDmaBuf = &prTxCell->DmaBuf; + + if (prTxCell->prToken) + prAddr = prTxCell->prToken->prPacket; + else if (prDmaBuf->AllocVa) + prAddr = prDmaBuf->AllocVa; + + if (prAddr) + DBGLOG_MEM32(HAL, INFO, prAddr, u4DumpLen); +} + +static void axiDumpRx(struct GL_HIF_INFO *prHifInfo, + struct RTMP_RX_RING *prRxRing, + uint32_t u4Idx, uint32_t u4DumpLen) +{ + struct RTMP_DMACB *prRxCell; + struct RTMP_DMABUF *prDmaBuf; + + prRxCell = &prRxRing->Cell[u4Idx]; + prDmaBuf = &prRxCell->DmaBuf; + + if (prRxCell->pPacket) + DBGLOG_MEM32(HAL, INFO, prRxCell->pPacket, u4DumpLen); +} +#else /* AXI_CFG_PREALLOC_MEMORY_BUFFER */ +static void axiAllocDesc(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing, + uint32_t u4Num) +{ + dma_addr_t rAddr; + + prDescRing->AllocVa = (void *)KAL_DMA_ALLOC_COHERENT( + prHifInfo->prDmaDev, prDescRing->AllocSize, &rAddr); + prDescRing->AllocPa = (phys_addr_t)rAddr; + if (prDescRing->AllocVa) + memset(prDescRing->AllocVa, 0, prDescRing->AllocSize); +} + +static void *axiAllocRxBuf(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDmaBuf, + uint32_t u4Num, uint32_t u4Idx) +{ + struct sk_buff *pkt = dev_alloc_skb(prDmaBuf->AllocSize); + dma_addr_t rAddr; + + if (!pkt) { + DBGLOG(HAL, ERROR, "can't allocate rx %u size packet\n", + prDmaBuf->AllocSize); + prDmaBuf->AllocPa = 0; + prDmaBuf->AllocVa = NULL; + return NULL; + } + + prDmaBuf->AllocVa = (void *)pkt->data; + memset(prDmaBuf->AllocVa, 0, prDmaBuf->AllocSize); + + rAddr = KAL_DMA_MAP_SINGLE(prHifInfo->prDmaDev, prDmaBuf->AllocVa, + prDmaBuf->AllocSize, KAL_DMA_FROM_DEVICE); + if (KAL_DMA_MAPPING_ERROR(prHifInfo->prDmaDev, rAddr)) { + DBGLOG(HAL, ERROR, "sk_buff dma mapping error!\n"); + dev_kfree_skb(pkt); + return NULL; + } + prDmaBuf->AllocPa = (phys_addr_t)rAddr; + return (void *)pkt; +} + +static void axiAllocTxDataBuf(struct MSDU_TOKEN_ENTRY *prToken, uint32_t u4Idx) +{ + prToken->prPacket = kalMemAlloc(prToken->u4DmaLength, PHY_MEM_TYPE); + prToken->rDmaAddr = 0; +} + +static void *axiAllocRuntimeMem(uint32_t u4SrcLen) +{ + return kalMemAlloc(u4SrcLen, PHY_MEM_TYPE); +} + +static bool axiCopyCmd(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *prTxCell, void *pucBuf, + void *pucSrc1, uint32_t u4SrcLen1, + void *pucSrc2, uint32_t u4SrcLen2) +{ + dma_addr_t rAddr; + uint32_t u4TotalLen = u4SrcLen1 + u4SrcLen2; + + prTxCell->pBuffer = pucBuf; + + memcpy(pucBuf, pucSrc1, u4SrcLen1); + if (pucSrc2 != NULL && u4SrcLen2 > 0) + memcpy(pucBuf + u4SrcLen1, pucSrc2, u4SrcLen2); + rAddr = KAL_DMA_MAP_SINGLE(prHifInfo->prDmaDev, pucBuf, + u4TotalLen, KAL_DMA_TO_DEVICE); + if (KAL_DMA_MAPPING_ERROR(prHifInfo->prDmaDev, rAddr)) { + DBGLOG(HAL, ERROR, "KAL_DMA_MAP_SINGLE() error!\n"); + return false; + } + + prTxCell->PacketPa = (phys_addr_t)rAddr; + + return true; +} + +static bool axiCopyEvent(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *pRxCell, + struct RXD_STRUCT *pRxD, + struct RTMP_DMABUF *prDmaBuf, + uint8_t *pucDst, uint32_t u4Len) +{ + struct sk_buff *prSkb = NULL; + void *pRxPacket = NULL; + dma_addr_t rAddr; + + KAL_DMA_UNMAP_SINGLE(prHifInfo->prDmaDev, + (dma_addr_t)prDmaBuf->AllocPa, + prDmaBuf->AllocSize, KAL_DMA_FROM_DEVICE); + + pRxPacket = pRxCell->pPacket; + ASSERT(pRxPacket); + + prSkb = (struct sk_buff *)pRxPacket; + memcpy(pucDst, (uint8_t *)prSkb->data, u4Len); + + prDmaBuf->AllocVa = ((struct sk_buff *)pRxCell->pPacket)->data; + rAddr = KAL_DMA_MAP_SINGLE(prHifInfo->prDmaDev, prDmaBuf->AllocVa, + prDmaBuf->AllocSize, KAL_DMA_FROM_DEVICE); + if (KAL_DMA_MAPPING_ERROR(prHifInfo->prDmaDev, rAddr)) { + DBGLOG(HAL, ERROR, "KAL_DMA_MAP_SINGLE() error!\n"); + return false; + } + prDmaBuf->AllocPa = (phys_addr_t)rAddr; + return true; +} + +static bool axiCopyTxData(struct MSDU_TOKEN_ENTRY *prToken, + void *pucSrc, uint32_t u4Len) +{ + memcpy(prToken->prPacket, pucSrc, u4Len); + return true; +} + +static bool axiCopyRxData(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *pRxCell, + struct RTMP_DMABUF *prDmaBuf, + struct SW_RFB *prSwRfb) +{ + void *pRxPacket = NULL; + dma_addr_t rAddr; + + pRxPacket = pRxCell->pPacket; + ASSERT(pRxPacket); + + pRxCell->pPacket = prSwRfb->pvPacket; + + KAL_DMA_UNMAP_SINGLE(prHifInfo->prDmaDev, + (dma_addr_t)prDmaBuf->AllocPa, + prDmaBuf->AllocSize, KAL_DMA_FROM_DEVICE); + prSwRfb->pvPacket = pRxPacket; + + prDmaBuf->AllocVa = ((struct sk_buff *)pRxCell->pPacket)->data; + rAddr = KAL_DMA_MAP_SINGLE(prHifInfo->prDmaDev, + prDmaBuf->AllocVa, prDmaBuf->AllocSize, KAL_DMA_FROM_DEVICE); + if (KAL_DMA_MAPPING_ERROR(prHifInfo->prDmaDev, rAddr)) { + DBGLOG(HAL, ERROR, "KAL_DMA_MAP_SINGLE() error!\n"); + ASSERT(0); + return false; + } + prDmaBuf->AllocPa = (phys_addr_t)rAddr; + + return true; +} + +static phys_addr_t axiMapTxBuf(struct GL_HIF_INFO *prHifInfo, + void *pucBuf, uint32_t u4Offset, uint32_t u4Len) +{ + dma_addr_t rDmaAddr = 0; + + rDmaAddr = KAL_DMA_MAP_SINGLE(prHifInfo->prDmaDev, pucBuf + u4Offset, + u4Len, KAL_DMA_TO_DEVICE); + if (KAL_DMA_MAPPING_ERROR(prHifInfo->prDmaDev, rDmaAddr)) { + DBGLOG(HAL, ERROR, "KAL_DMA_MAP_SINGLE() error!\n"); + return 0; + } + + return (phys_addr_t)rDmaAddr; +} + +static phys_addr_t axiMapRxBuf(struct GL_HIF_INFO *prHifInfo, + void *pucBuf, uint32_t u4Offset, uint32_t u4Len) +{ + dma_addr_t rDmaAddr = 0; + + rDmaAddr = KAL_DMA_MAP_SINGLE(prHifInfo->prDmaDev, pucBuf + u4Offset, + u4Len, KAL_DMA_FROM_DEVICE); + if (KAL_DMA_MAPPING_ERROR(prHifInfo->prDmaDev, rDmaAddr)) { + DBGLOG(HAL, ERROR, "KAL_DMA_MAP_SINGLE() error!\n"); + return 0; + } + + return (phys_addr_t)rDmaAddr; +} + +static void axiUnmapTxBuf(struct GL_HIF_INFO *prHifInfo, + phys_addr_t rDmaAddr, uint32_t u4Len) +{ + KAL_DMA_UNMAP_SINGLE(prHifInfo->prDmaDev, + (dma_addr_t)rDmaAddr, + u4Len, KAL_DMA_TO_DEVICE); +} + +static void axiUnmapRxBuf(struct GL_HIF_INFO *prHifInfo, + phys_addr_t rDmaAddr, uint32_t u4Len) +{ + KAL_DMA_UNMAP_SINGLE(prHifInfo->prDmaDev, + (dma_addr_t)rDmaAddr, + u4Len, KAL_DMA_FROM_DEVICE); +} + +static void axiFreeDesc(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing) +{ + if (prDescRing->AllocVa == NULL) + return; + + KAL_DMA_FREE_COHERENT(prHifInfo->prDmaDev, + prDescRing->AllocSize, + prDescRing->AllocVa, + (dma_addr_t)prDescRing->AllocPa); + memset(prDescRing, 0, sizeof(struct RTMP_DMABUF)); +} + +static void axiFreeBuf(void *pucSrc, uint32_t u4Len) +{ + kalMemFree(pucSrc, PHY_MEM_TYPE, u4Len); +} + +static void axiFreePacket(void *pvPacket) +{ + kalPacketFree(NULL, pvPacket); +} + +static void axiDumpTx(struct GL_HIF_INFO *prHifInfo, + struct RTMP_TX_RING *prTxRing, + uint32_t u4Idx, uint32_t u4DumpLen) +{ + struct RTMP_DMACB *prTxCell; + void *prAddr = NULL; + + prTxCell = &prTxRing->Cell[u4Idx]; + + if (prTxCell->prToken) + prAddr = prTxCell->prToken->prPacket; + else + prAddr = prTxCell->pBuffer; + + if (prAddr) + DBGLOG_MEM32(HAL, INFO, prAddr, u4DumpLen); +} + +static void axiDumpRx(struct GL_HIF_INFO *prHifInfo, + struct RTMP_RX_RING *prRxRing, + uint32_t u4Idx, uint32_t u4DumpLen) +{ + struct RTMP_DMACB *prRxCell; + struct RTMP_DMABUF *prDmaBuf; + + prRxCell = &prRxRing->Cell[u4Idx]; + prDmaBuf = &prRxCell->DmaBuf; + + if (!prRxCell->pPacket) + return; + + axiUnmapRxBuf(prHifInfo, prDmaBuf->AllocPa, prDmaBuf->AllocSize); + + DBGLOG_MEM32(HAL, INFO, ((struct sk_buff *)prRxCell->pPacket)->data, + u4DumpLen); + + prDmaBuf->AllocPa = axiMapRxBuf(prHifInfo, prDmaBuf->AllocVa, + 0, prDmaBuf->AllocSize); +} +#endif /* AXI_CFG_PREALLOC_MEMORY_BUFFER */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/axi/include/hif.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/axi/include/hif.h new file mode 100644 index 0000000000000..0a3680beb8b36 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/axi/include/hif.h @@ -0,0 +1,409 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \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 + */ + +#ifndef _HIF_H +#define _HIF_H + +#include "hif_pdma.h" + +#if defined(_HIF_AXI) +#define HIF_NAME "AXI" +#else +#error "No HIF defined!" +#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 + ******************************************************************************* + */ +#if CFG_MTK_ANDROID_WMT +#if (CFG_SUPPORT_CONNINFRA == 0) +extern int mtk_wcn_consys_hw_wifi_paldo_ctrl(unsigned int enable); +#else +struct MTK_WCN_WLAN_CB_INFO; +extern int mtk_wcn_wlan_reg( + struct MTK_WCN_WLAN_CB_INFO *pWlanCbInfo); +extern int mtk_wcn_wlan_unreg(void); +#endif /*end of CFG_SUPPORT_CONNINFRA == 0*/ +#endif /*end of CFG_MTK_ANDROID_WMT */ + +#if (CFG_SUPPORT_CONNINFRA == 1) +extern wait_queue_head_t g_waitq_rst; +extern unsigned long g_ulFlag; +extern KAL_WAKE_LOCK_T *g_IntrWakeLock; +#endif +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define AXI_CFG_PREALLOC_MEMORY_BUFFER 1 + +#define AXI_TX_MAX_SIZE_PER_FRAME (NIC_TX_MAX_SIZE_PER_FRAME + \ + NIC_TX_DESC_AND_PADDING_LENGTH) + +#define AXI_TX_CMD_BUFF_SIZE 4096 +#define AXI_WLAN_IRQ_NUMBER 16 + +#if (CFG_SUPPORT_CONNINFRA == 1) +#define WIFI_EMI_WFDMA_OFFSET 0x450000 +#define WIFI_EMI_WFDMA_SIZE 0xF20000 +#endif + + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +struct GL_HIF_INFO; + +struct HIF_MEM_OPS { + void (*allocTxDesc)(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing, + uint32_t u4Num); + void (*allocRxDesc)(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing, + uint32_t u4Num); + bool (*allocTxCmdBuf)(struct RTMP_DMABUF *prDmaBuf, + uint32_t u4Num, uint32_t u4Idx); + void (*allocTxDataBuf)(struct MSDU_TOKEN_ENTRY *prToken, + uint32_t u4Idx); + void *(*allocRxBuf)(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDmaBuf, + uint32_t u4Num, uint32_t u4Idx); + void *(*allocRuntimeMem)(uint32_t u4SrcLen); + bool (*copyCmd)(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *prTxCell, void *pucBuf, + void *pucSrc1, uint32_t u4SrcLen1, + void *pucSrc2, uint32_t u4SrcLen2); + bool (*copyEvent)(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *pRxCell, + struct RXD_STRUCT *pRxD, + struct RTMP_DMABUF *prDmaBuf, + uint8_t *pucDst, uint32_t u4Len); + bool (*copyTxData)(struct MSDU_TOKEN_ENTRY *prToken, + void *pucSrc, uint32_t u4Len); + bool (*copyRxData)(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *pRxCell, + struct RTMP_DMABUF *prDmaBuf, + struct SW_RFB *prSwRfb); + phys_addr_t (*mapTxBuf)(struct GL_HIF_INFO *prHifInfo, + void *pucBuf, uint32_t u4Offset, uint32_t u4Len); + phys_addr_t (*mapRxBuf)(struct GL_HIF_INFO *prHifInfo, + void *pucBuf, uint32_t u4Offset, uint32_t u4Len); + void (*unmapTxBuf)(struct GL_HIF_INFO *prHifInfo, + phys_addr_t rDmaAddr, uint32_t u4Len); + void (*unmapRxBuf)(struct GL_HIF_INFO *prHifInfo, + phys_addr_t rDmaAddr, uint32_t u4Len); + void (*freeDesc)(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing); + void (*freeBuf)(void *pucSrc, uint32_t u4Len); + void (*freePacket)(void *pvPacket); + void (*dumpTx)(struct GL_HIF_INFO *prHifInfo, + struct RTMP_TX_RING *prTxRing, + uint32_t u4Idx, uint32_t u4DumpLen); + void (*dumpRx)(struct GL_HIF_INFO *prHifInfo, + struct RTMP_RX_RING *prRxRing, + uint32_t u4Idx, uint32_t u4DumpLen); +}; + +/* host interface's private data structure, which is attached to os glue + ** layer info structure. + */ +struct GL_HIF_INFO { + struct platform_device *pdev; + struct device *prDmaDev; + struct HIF_MEM_OPS rMemOps; + + uint32_t u4IrqId; +#if (CFG_SUPPORT_CONNINFRA == 1) + uint32_t u4IrqId_1; +#endif + int32_t u4HifCnt; + + /* AXI MMIO Base Address, all access will use */ + void *CSRBaseAddress; + + /* Shared memory of all 1st pre-allocated + * TxBuf associated with each TXD + */ + /* Shared memory for Tx descriptors */ + struct RTMP_DMABUF TxDescRing[NUM_OF_TX_RING]; + struct RTMP_TX_RING TxRing[NUM_OF_TX_RING]; /* AC0~3 + HCCA */ + + /* Shared memory for RX descriptors */ + struct RTMP_DMABUF RxDescRing[NUM_OF_RX_RING]; + struct RTMP_RX_RING RxRing[NUM_OF_RX_RING]; + + u_int8_t fgIntReadClear; + u_int8_t fgMbxReadClear; + + uint32_t u4IntStatus; + + struct MSDU_TOKEN_INFO rTokenInfo; + + struct ERR_RECOVERY_CTRL_T rErrRecoveryCtl; + struct timer_list rSerTimer; + u_int64_t rSerTimerData; + struct list_head rTxCmdQ; + struct list_head rTxDataQ; + uint32_t u4TxDataQLen; + + bool fgIsPowerOff; + bool fgIsDumpLog; +}; + +struct BUS_INFO { + const uint32_t top_cfg_base; /* TOP_CFG_BASE address */ + const struct PCIE_CHIP_CR_MAPPING *bus2chip; + const uint32_t tx_ring_cmd_idx; + const uint32_t tx_ring_wa_cmd_idx; + const uint32_t tx_ring_fwdl_idx; + const uint32_t tx_ring0_data_idx; + const uint32_t tx_ring1_data_idx; + const uint32_t max_static_map_addr; + const uint32_t fw_own_clear_addr; + const uint32_t fw_own_clear_bit; + const bool fgCheckDriverOwnInt; + const uint32_t u4DmaMask; + /* host pdma/wfdma0 base address */ + const uint32_t host_dma0_base; + /* host wfdma1 base address */ + const uint32_t host_dma1_base; + /* host ext conn hif wrap */ + const uint32_t host_ext_conn_hif_wrap_base; + const uint32_t host_int_status_addr; + const uint32_t host_int_txdone_bits; + const uint32_t host_int_rxdone_bits; + + /* tx pdma/wfdma ring base address */ + const uint32_t host_tx_ring_base; + /* tx pdma/wfdma ring ext control base address */ + const uint32_t host_tx_ring_ext_ctrl_base; + /* tx pdma/wfdma ring cpu index address */ + const uint32_t host_tx_ring_cidx_addr; + /* tx pdma/wfdma ring dma index address */ + const uint32_t host_tx_ring_didx_addr; + /* tx pdma/wfdma ring count address */ + const uint32_t host_tx_ring_cnt_addr; + + /* rx pdma/wfdma ring base address */ + const uint32_t host_rx_ring_base; + /* rx pdma/wfdma ring ext control base address */ + const uint32_t host_rx_ring_ext_ctrl_base; + /* rx pdma/wfdma ring cpu index address */ + const uint32_t host_rx_ring_cidx_addr; + /* rx pdma/wfdma ring dma index address */ + const uint32_t host_rx_ring_didx_addr; + /* rx pdma/wfdma ring count address */ + const uint32_t host_rx_ring_cnt_addr; + +#if (CFG_SUPPORT_CONNAC2X == 1) + /* rx wfdma_1 ring base address */ + const uint32_t host_wfdma1_rx_ring_base; + /* rx wfdma_1 ring cpu index address */ + const uint32_t host_wfdma1_rx_ring_cidx_addr; + /* rx wfdma_1 ring dma index address */ + const uint32_t host_wfdma1_rx_ring_didx_addr; + /* rx wfdma_1 ring count address */ + const uint32_t host_wfdma1_rx_ring_cnt_addr; + /* rx wfdma_1 ring ext control base address */ + const uint32_t host_wfdma1_rx_ring_ext_ctrl_base; +#endif /* CFG_SUPPORT_CONNAC2X == 1 */ + + void (*pdmaSetup)(struct GLUE_INFO *prGlueInfo, u_int8_t enable, + bool fgResetHif); + uint32_t (*updateTxRingMaxQuota)(struct ADAPTER *prAdapter, + uint16_t u2Port, uint32_t u4MaxQuota); + void (*enableInterrupt)(struct ADAPTER *prAdapter); + void (*disableInterrupt)(struct ADAPTER *prAdapter); + void (*processTxInterrupt)(struct ADAPTER *prAdapter); + void (*processRxInterrupt)(struct ADAPTER *prAdapter); + void (*lowPowerOwnRead)(struct ADAPTER *prAdapter, u_int8_t *pfgResult); + void (*lowPowerOwnSet)(struct ADAPTER *prAdapter, u_int8_t *pfgResult); + void (*lowPowerOwnClear)(struct ADAPTER *prAdapter, + u_int8_t *pfgResult); + void (*wakeUpWiFi)(struct ADAPTER *prAdapter); + bool (*isValidRegAccess)(struct ADAPTER *prAdapter, + uint32_t u4Register); + void (*getMailboxStatus)(struct ADAPTER *prAdapter, uint32_t *pu4Val); + void (*setDummyReg)(struct GLUE_INFO *prGlueInfo); + void (*checkDummyReg)(struct GLUE_INFO *prGlueInfo); + void (*tx_ring_ext_ctrl)(struct GLUE_INFO *prGlueInfo, + struct RTMP_TX_RING *tx_ring, uint32_t index); + void (*rx_ring_ext_ctrl)(struct GLUE_INFO *prGlueInfo, + struct RTMP_RX_RING *rx_ring, uint32_t index); + void (*wfdmaManualPrefetch)(struct GLUE_INFO *prGlueInfo); + void (*processSoftwareInterrupt)(IN struct ADAPTER *prAdapter); + void (*softwareInterruptMcu)(IN struct ADAPTER *prAdapter, + u_int32_t intrBitMask); + void (*hifRst)(struct GLUE_INFO *prGlueInfo); + void (*initPcieInt)(struct GLUE_INFO *prGlueInfo); + void (*devReadIntStatus)(struct ADAPTER *prAdapter, + OUT uint32_t *pu4IntStatus); + void (*DmaShdlInit)(IN struct ADAPTER *prAdapter); + uint8_t (*setRxRingHwAddr)(struct RTMP_RX_RING *prRxRing, + struct BUS_INFO *prBusInfo, + uint32_t u4SwRingIdx); + bool (*wfdmaAllocRxRing)( + struct GLUE_INFO *prGlueInfo, + bool fgAllocMem); + void (*setPdmaIntMask)(struct GLUE_INFO *prGlueInfo, u_int8_t fgEnable); +}; + +struct HIF_MEM { + phys_addr_t pa; + void *va; +}; + +struct HIF_PREALLOC_MEM { + struct HIF_MEM rTxDesc[NUM_OF_TX_RING]; + struct HIF_MEM rRxDesc[NUM_OF_RX_RING]; + /* Tx Command */ + struct HIF_MEM rTxCmdBuf[TX_RING_SIZE]; + /* Rx Data */ + struct HIF_MEM rRxDataBuf[RX_RING0_SIZE]; + +#if (CFG_SUPPORT_CONNAC2X == 1) + /* Connac1.0 = RX Event, Connac2.0 = Rx Data band1 */ + struct HIF_MEM rRxEventBuf[RX_RING0_SIZE]; + /* Band 0 TxFreeDoneEvent */ + struct HIF_MEM wfdma0_rx_ring_idx2[RX_RING1_SIZE]; + /* Band 1 TxFreeDoneEvent */ + struct HIF_MEM wfdma0_rx_ring_idx3[RX_RING1_SIZE]; + /* WM Event */ + struct HIF_MEM wfdma1_rx_ring_idx0[RX_RING1_SIZE]; +#else + /* Connac1.0 = RX Event, Connac2.0 = Rx Data band1 */ + struct HIF_MEM rRxEventBuf[RX_RING1_SIZE]; +#endif /* CFG_SUPPORT_CONNAC2X == 1 */ + +#if HIF_TX_PREALLOC_DATA_BUFFER + /* Tx Data */ + struct HIF_MEM rMsduBuf[HIF_TX_MSDU_TOKEN_NUM]; +#endif + phys_addr_t pucRsvMemBase; + void *pucRsvMemVirBase; + uint64_t u4RsvMemSize; + uint32_t u4Offset; +}; + +#if CFG_MTK_ANDROID_WMT +#if (CFG_SUPPORT_CONNINFRA == 1) +struct MTK_WCN_WLAN_CB_INFO { + int (*wlan_probe_cb)(void); + int (*wlan_remove_cb)(void); +}; + +#endif /*end of CFG_SUPPORT_CONNINFRA == 0*/ +#endif /*end of CFG_MTK_ANDROID_WMT */ + +/******************************************************************************* + * P U B 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 axi_resource_start(d, v) (0x18000000) +#define axi_resource_len(d, v) (0x100000) +#define axi_name(d) ("AXI-BUS") + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +uint32_t glRegisterBus(probe_card pfProbe, remove_card pfRemove); + +void glUnregisterBus(remove_card pfRemove); + +void glSetHifInfo(struct GLUE_INFO *prGlueInfo, unsigned long ulCookie); + +void glClearHifInfo(struct GLUE_INFO *prGlueInfo); + +u_int8_t glBusInit(void *pvData); + +void glBusRelease(void *pData); + +int32_t glBusSetIrq(void *pvData, void *pfnIsr, void *pvCookie); + +void glBusFreeIrq(void *pvData, void *pvCookie); + +void glSetPowerState(IN struct GLUE_INFO *prGlueInfo, IN uint32_t ePowerMode); + +void glGetDev(void *ctx, struct device **dev); + +void glGetHifDev(struct GL_HIF_INFO *prHif, struct device **dev); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#endif /* _HIF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/common/dbg_pdma.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/common/dbg_pdma.c new file mode 100644 index 0000000000000..54a376d7d7215 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/common/dbg_pdma.c @@ -0,0 +1,913 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** + *[File] dbg_pdma.c + *[Version] v1.0 + *[Revision Date] 2015-09-08 + *[Author] + *[Description] + * The program provides PDMA HIF APIs + *[Copyright] + * Copyright (C) 2015 MediaTek Incorporation. All Rights Reserved. + ******************************************************************************/ + +/******************************************************************************* + * C O M P I L E 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 "pse.h" +#include "wf_ple.h" +#include "host_csr.h" +#include "dma_sch.h" +#include "mt_dmac.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +struct wfdma_ring_info { + char name[20]; + uint32_t ring_idx; + bool dump_ring_content; + + /* query from register */ + uint32_t base; + uint32_t base_ext; + uint32_t cnt; + uint32_t cidx; + uint32_t didx; +}; + +/******************************************************************************* + * P U B 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 halCheckHifState(struct ADAPTER *prAdapter); +static void halDumpHifDebugLog(struct ADAPTER *prAdapter); +static bool halIsTxHang(struct ADAPTER *prAdapter); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +void halPrintHifDbgInfo(IN struct ADAPTER *prAdapter) +{ + if (!prAdapter->fgIsFwOwn) { + halCheckHifState(prAdapter); + halDumpHifDebugLog(prAdapter); + } + if (prAdapter->chip_info->dumpwfsyscpupcr) + prAdapter->chip_info->dumpwfsyscpupcr(prAdapter); +} + +static void halCheckHifState(struct ADAPTER *prAdapter) +{ + uint32_t u4DebugLevel = 0; + if (prAdapter->u4HifChkFlag & HIF_CHK_TX_HANG) { + if (halIsTxHang(prAdapter)) { + DBGLOG(HAL, ERROR, + "Tx timeout, set hif debug info flag\n"); + wlanGetDriverDbgLevel(DBG_TX_IDX, &u4DebugLevel); + if (u4DebugLevel & DBG_CLASS_TRACE) { + DBGLOG(HAL, ERROR, "Set debug flag bit\n"); + prAdapter->u4HifDbgFlag |= DEG_HIF_ALL; + } + else { + struct CHIP_DBG_OPS *prDbgOps; + + prDbgOps = prAdapter->chip_info->prDebugOps; + DBGLOG(HAL, ERROR, "Dump debug info\n"); + if (prDbgOps && prDbgOps->showPleInfo) + prDbgOps->showPleInfo(prAdapter, FALSE); + + if (prDbgOps && prDbgOps->showPseInfo) + prDbgOps->showPseInfo(prAdapter); + + if (prDbgOps && prDbgOps->showPdmaInfo) + prDbgOps->showPdmaInfo(prAdapter); + + if (prDbgOps && prDbgOps->showDmaschInfo) + prDbgOps->showDmaschInfo(prAdapter); + + if (prDbgOps && prDbgOps->dumpMacInfo) + prDbgOps->dumpMacInfo(prAdapter); + + } + } + } + + if (prAdapter->u4HifChkFlag & HIF_DRV_SER) + halSetDrvSer(prAdapter); + + prAdapter->u4HifChkFlag = 0; +} + +static void halDumpHifDebugLog(struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct GL_HIF_INFO *prHifInfo = NULL; + struct CHIP_DBG_OPS *prDbgOps; + uint32_t ret = 0; + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + /* Only dump all hif log once */ + if (prAdapter->u4HifDbgFlag & DEG_HIF_ALL) { + if (!prAdapter->fgEnHifDbgInfo) { + DBGLOG(HAL, ERROR, "return due to HifDbg is NULL\n"); + prAdapter->u4HifDbgFlag = 0; + return; + } + prAdapter->fgEnHifDbgInfo = false; + } + + /* Avoid register checking */ + prHifInfo->fgIsDumpLog = true; + + prDbgOps = prAdapter->chip_info->prDebugOps; + + if (prAdapter->u4HifDbgFlag & (DEG_HIF_ALL | DEG_HIF_HOST_CSR)) { + if (prDbgOps->showCsrInfo) { + bool fgIsClkEn = prDbgOps->showCsrInfo(prAdapter); + + if (!fgIsClkEn) + return; + } + } + + /* need to check Bus readable */ + if (prAdapter->chip_info->checkbushang) { + ret = prAdapter->chip_info->checkbushang((void *) prAdapter, + TRUE); + if (ret != 0) { + DBGLOG(HAL, ERROR, + "return due to checkbushang fail %d\n", ret); + return; + } + } + + /* Check Driver own HW CR */ + { + struct BUS_INFO *prBusInfo = NULL; + u_int8_t driver_owen_result = 0; + + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + + if (prBusInfo->lowPowerOwnRead) + prBusInfo->lowPowerOwnRead(prGlueInfo->prAdapter, + &driver_owen_result); + else { + DBGLOG(HAL, ERROR, "retrun due to null API\n"); + return; + } + + if (driver_owen_result == 0) { + DBGLOG(HAL, ERROR, "return, not driver-own[%d]\n", + driver_owen_result); + return; + } + } + + if (prAdapter->u4HifDbgFlag & (DEG_HIF_ALL | DEG_HIF_PLE)) { + if (prDbgOps && prDbgOps->showPleInfo) + prDbgOps->showPleInfo(prAdapter, FALSE); + } + + if (prAdapter->u4HifDbgFlag & (DEG_HIF_ALL | DEG_HIF_PSE)) { + if (prDbgOps && prDbgOps->showPseInfo) + prDbgOps->showPseInfo(prAdapter); + } + + if (prAdapter->u4HifDbgFlag & (DEG_HIF_ALL | DEG_HIF_PDMA)) { + if (prDbgOps && prDbgOps->showPdmaInfo) + prDbgOps->showPdmaInfo(prAdapter); + } + + if (prAdapter->u4HifDbgFlag & (DEG_HIF_ALL | DEG_HIF_DMASCH)) { + if (prDbgOps && prDbgOps->showDmaschInfo) + prDbgOps->showDmaschInfo(prAdapter); + } + + if (prAdapter->u4HifDbgFlag & (DEG_HIF_ALL | DEG_HIF_MAC)) { + if (prDbgOps && prDbgOps->dumpMacInfo) + prDbgOps->dumpMacInfo(prAdapter); + } + + if (prAdapter->u4HifDbgFlag & (DEG_HIF_ALL | DEG_HIF_PHY)) + haldumpPhyInfo(prAdapter); + + prHifInfo->fgIsDumpLog = false; + prAdapter->u4HifDbgFlag = 0; +} + +static void halDumpTxRing(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port, IN uint32_t u4Idx) +{ + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + struct RTMP_TX_RING *prTxRing; + struct TXD_STRUCT *pTxD; + + if (u2Port >= NUM_OF_TX_RING || u4Idx >= TX_RING_SIZE) { + DBGLOG(HAL, INFO, "Dump fail u2Port[%u] u4Idx[%u]\n", + u2Port, u4Idx); + return; + } + + prTxRing = &prHifInfo->TxRing[u2Port]; + + pTxD = (struct TXD_STRUCT *) prTxRing->Cell[u4Idx].AllocVa; + + log_dbg(SW4, INFO, "TX Ring[%u] Idx[%04u] SDP0[0x%08x] SDL0[%u] LS[%u] B[%u] DDONE[%u] SDP0_EXT[%u]\n", + u2Port, u4Idx, pTxD->SDPtr0, pTxD->SDLen0, pTxD->LastSec0, + pTxD->Burst, pTxD->DMADONE, pTxD->SDPtr0Ext); +} + +uint32_t halDumpHifStatus(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, IN uint32_t u4Max) +{ + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + uint32_t u4Idx, u4DmaIdx = 0; + uint32_t u4CpuIdx = 0, u4MaxCnt = 0; + uint32_t u4Len = 0; + struct RTMP_TX_RING *prTxRing; + struct RTMP_RX_RING *prRxRing; + + LOGBUF(pucBuf, u4Max, u4Len, "\n------------\n"); + + for (u4Idx = 0; u4Idx < NUM_OF_TX_RING; u4Idx++) { + prTxRing = &prHifInfo->TxRing[u4Idx]; + kalDevRegRead(prGlueInfo, prTxRing->hw_cnt_addr, &u4MaxCnt); + kalDevRegRead(prGlueInfo, prTxRing->hw_cidx_addr, &u4CpuIdx); + kalDevRegRead(prGlueInfo, prTxRing->hw_didx_addr, &u4DmaIdx); + + LOGBUF(pucBuf, u4Max, u4Len, + "TX[%u] SZ[%04u] CPU[%04u/%04u] DMA[%04u/%04u] SW_UD[%04u] Used[%u]\n", + u4Idx, u4MaxCnt, prTxRing->TxCpuIdx, + u4CpuIdx, prTxRing->TxDmaIdx, + u4DmaIdx, prTxRing->TxSwUsedIdx, prTxRing->u4UsedCnt); + + if (u4Idx == TX_RING_DATA0_IDX_0) { + halDumpTxRing(prGlueInfo, u4Idx, prTxRing->TxCpuIdx); + halDumpTxRing(prGlueInfo, u4Idx, u4CpuIdx); + halDumpTxRing(prGlueInfo, u4Idx, u4DmaIdx); + halDumpTxRing(prGlueInfo, u4Idx, prTxRing->TxSwUsedIdx); + } + + if (u4Idx == TX_RING_DATA1_IDX_1) { + halDumpTxRing(prGlueInfo, u4Idx, prTxRing->TxCpuIdx); + halDumpTxRing(prGlueInfo, u4Idx, u4CpuIdx); + halDumpTxRing(prGlueInfo, u4Idx, u4DmaIdx); + halDumpTxRing(prGlueInfo, u4Idx, prTxRing->TxSwUsedIdx); + } + } + + for (u4Idx = 0; u4Idx < NUM_OF_RX_RING; u4Idx++) { + prRxRing = &prHifInfo->RxRing[u4Idx]; + + kalDevRegRead(prGlueInfo, prRxRing->hw_cnt_addr, &u4MaxCnt); + kalDevRegRead(prGlueInfo, prRxRing->hw_cidx_addr, &u4CpuIdx); + kalDevRegRead(prGlueInfo, prRxRing->hw_didx_addr, &u4DmaIdx); + + LOGBUF(pucBuf, u4Max, u4Len, + "RX[%u] SZ[%04u] CPU[%04u/%04u] DMA[%04u/%04u]\n", + u4Idx, u4MaxCnt, prRxRing->RxCpuIdx, u4CpuIdx, + prRxRing->RxDmaIdx, u4DmaIdx); + } + + LOGBUF(pucBuf, u4Max, u4Len, "MSDU Tok: Free[%u] Used[%u]\n", + halGetMsduTokenFreeCnt(prGlueInfo->prAdapter), + prGlueInfo->rHifInfo.rTokenInfo.u4UsedCnt); + LOGBUF(pucBuf, u4Max, u4Len, "Pending QLen Normal[%u] Sec[%u]\n", + prGlueInfo->i4TxPendingFrameNum, + prGlueInfo->i4TxPendingSecurityFrameNum); + + LOGBUF(pucBuf, u4Max, u4Len, "---------------------------------\n\n"); + + return u4Len; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Compare two struct timeval + * + * @param prTs1 a pointer to timeval + * @param prTs2 a pointer to timeval + * + * + * @retval 0 two time value is equal + * @retval 1 prTs1 value > prTs2 value + * @retval -1 prTs1 value < prTs2 value + */ +/*----------------------------------------------------------------------------*/ +int halTimeCompare(struct timeval *prTs1, struct timeval *prTs2) +{ + if (prTs1->tv_sec > prTs2->tv_sec) + return 1; + else if (prTs1->tv_sec < prTs2->tv_sec) + return -1; + /* sec part is equal */ + else if (prTs1->tv_usec > prTs2->tv_usec) + return 1; + else if (prTs1->tv_usec < prTs2->tv_usec) + return -1; + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Checking tx hang + * + * @param prAdapter a pointer to adapter private data structure. + * + * @retval true tx is hang because msdu report too long + */ +/*----------------------------------------------------------------------------*/ +static bool halIsTxHang(struct ADAPTER *prAdapter) +{ + struct MSDU_TOKEN_INFO *prTokenInfo; + struct MSDU_TOKEN_ENTRY *prToken; + struct MSDU_INFO *prMsduInfo; + struct timeval rNowTs, rTime, rLongest, rTimeout; + uint32_t u4Idx = 0, u4TokenId = 0; + bool fgIsTimeout = false; + struct WIFI_VAR *prWifiVar; + + ASSERT(prAdapter); + ASSERT(prAdapter->prGlueInfo); + + prTokenInfo = &prAdapter->prGlueInfo->rHifInfo.rTokenInfo; + prWifiVar = &prAdapter->rWifiVar; + + rTimeout.tv_sec = prWifiVar->ucMsduReportTimeout; + rTimeout.tv_usec = 0; + rLongest.tv_sec = 0; + rLongest.tv_usec = 0; + do_gettimeofday(&rNowTs); + + for (u4Idx = 0; u4Idx < HIF_TX_MSDU_TOKEN_NUM; u4Idx++) { + prToken = &prTokenInfo->arToken[u4Idx]; + prMsduInfo = prToken->prMsduInfo; + if (!prToken->fgInUsed || !prMsduInfo) + continue; + + /* check tx hang is enabled */ + if ((prAdapter->u4TxHangFlag & + BIT(prMsduInfo->ucBssIndex)) == 0) + continue; + + /* Ignore now time < token time */ + if (halTimeCompare(&rNowTs, &prToken->rTs) < 0) + continue; + + rTime.tv_sec = rNowTs.tv_sec - prToken->rTs.tv_sec; + rTime.tv_usec = rNowTs.tv_usec; + if (prToken->rTs.tv_usec > rNowTs.tv_usec) { + rTime.tv_sec -= 1; + rTime.tv_usec += SEC_TO_USEC(1); + } + rTime.tv_usec -= prToken->rTs.tv_usec; + + if (halTimeCompare(&rTime, &rTimeout) >= 0) + fgIsTimeout = true; + + /* rTime > rLongest */ + if (halTimeCompare(&rTime, &rLongest) > 0) { + rLongest.tv_sec = rTime.tv_sec; + rLongest.tv_usec = rTime.tv_usec; + u4TokenId = u4Idx; + } + } + + if (fgIsTimeout) { + DBGLOG(HAL, INFO, "TokenId[%u] timeout[sec:%ld, usec:%ld]\n", + u4TokenId, rLongest.tv_sec, rLongest.tv_usec); + prToken = &prTokenInfo->arToken[u4TokenId]; + if (prToken->prPacket) + DBGLOG_MEM32(HAL, INFO, prToken->prPacket, 64); + } + + return fgIsTimeout; +} + +void kalDumpTxRing(struct GLUE_INFO *prGlueInfo, + struct RTMP_TX_RING *prTxRing, + uint32_t u4Num, bool fgDumpContent) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct HIF_MEM_OPS *prMemOps; + struct RTMP_DMACB *pTxCell; + struct TXD_STRUCT *pTxD; + uint32_t u4DumpLen = 64; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + + if (u4Num >= TX_RING_SIZE) + return; + + pTxCell = &prTxRing->Cell[u4Num]; + pTxD = (struct TXD_STRUCT *) pTxCell->AllocVa; + + if (!pTxD) + return; + + DBGLOG(HAL, INFO, "Tx Dese Num[%u]\n", u4Num); + DBGLOG_MEM32(HAL, INFO, pTxD, sizeof(struct TXD_STRUCT)); + + if (!fgDumpContent) + return; + + DBGLOG(HAL, INFO, "Tx Contents\n"); + if (prMemOps->dumpTx) + prMemOps->dumpTx(prHifInfo, prTxRing, u4Num, u4DumpLen); + DBGLOG(HAL, INFO, "\n\n"); +} + +void kalDumpRxRing(struct GLUE_INFO *prGlueInfo, + struct RTMP_RX_RING *prRxRing, + uint32_t u4Num, bool fgDumpContent) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct HIF_MEM_OPS *prMemOps; + struct RTMP_DMACB *pRxCell; + struct RXD_STRUCT *pRxD; + uint32_t u4DumpLen = 64; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + + if (u4Num >= prRxRing->u4RingSize) + return; + + pRxCell = &prRxRing->Cell[u4Num]; + pRxD = (struct RXD_STRUCT *) pRxCell->AllocVa; + + if (!pRxD) + return; + + DBGLOG(HAL, INFO, "Rx Dese Num[%u]\n", u4Num); + DBGLOG_MEM32(HAL, INFO, pRxD, sizeof(struct RXD_STRUCT)); + + if (!fgDumpContent) + return; + + if (u4DumpLen > pRxD->SDLen0) + u4DumpLen = pRxD->SDLen0; + + DBGLOG(HAL, INFO, "Rx Contents\n"); + if (prMemOps->dumpRx) + prMemOps->dumpRx(prHifInfo, prRxRing, u4Num, u4DumpLen); + DBGLOG(HAL, INFO, "\n\n"); +} + +void halShowPdmaInfo(IN struct ADAPTER *prAdapter) +{ +#define BUF_SIZE 1024 + + uint32_t i = 0, u4Value = 0, pos = 0; + uint32_t offset, offset_ext, SwIdx; + char *buf; + struct GL_HIF_INFO *prHifInfo = NULL; + struct BUS_INFO *prBus_info = prAdapter->chip_info->bus_info; + struct RTMP_TX_RING *prTxRing; + struct RTMP_RX_RING *prRxRing; + struct wfdma_ring_info wfmda_tx_group[] = { + {"AP DATA0", prBus_info->tx_ring0_data_idx, true}, + {"AP DATA1", prBus_info->tx_ring1_data_idx, true}, + {"AP CMD", prBus_info->tx_ring_cmd_idx, true}, + {"FWDL", prBus_info->tx_ring_fwdl_idx, true}, +#if CFG_MTK_MCIF_WIFI_SUPPORT + {"MD DATA0", 8, false}, + {"MD DATA1", 9, false}, + {"MD CMD", 14, false}, +#endif + }; + struct wfdma_ring_info wfmda_rx_group[] = { + {"AP DATA", 0, true}, + {"AP EVENT", 1, true}, +#if CFG_MTK_MCIF_WIFI_SUPPORT + {"MD DATA", 2, false}, + {"MD EVENT", 3, false}, +#endif + }; + + buf = (char *) kalMemAlloc(BUF_SIZE, VIR_MEM_TYPE); + + /* PDMA HOST_INT */ + HAL_MCR_RD(prAdapter, WPDMA_INT_STA, &u4Value); + DBGLOG(HAL, INFO, "WPDMA HOST_INT:0x%08x = 0x%08x\n", + WPDMA_INT_STA, u4Value); + + /* PDMA GLOBAL_CFG */ + HAL_MCR_RD(prAdapter, WPDMA_GLO_CFG, &u4Value); + DBGLOG(HAL, INFO, "WPDMA GLOBAL_CFG:0x%08x = 0x%08x\n", + WPDMA_GLO_CFG, u4Value); + + HAL_MCR_RD(prAdapter, CONN_HIF_RST, &u4Value); + DBGLOG(HAL, INFO, "WPDMA CONN_HIF_RST:0x%08x = 0x%08x\n", + CONN_HIF_RST, u4Value); + + HAL_MCR_RD(prAdapter, MCU2HOST_SW_INT_STA, &u4Value); + DBGLOG(HAL, INFO, "WPDMA MCU2HOST_SW_INT_STA:0x%08x = 0x%08x\n", + MCU2HOST_SW_INT_STA, u4Value); + +#if CFG_MTK_MCIF_WIFI_SUPPORT + HAL_MCR_RD(prAdapter, MD_INT_STA, &u4Value); + DBGLOG(HAL, INFO, "MD_INT_STA:0x%08x = 0x%08x\n", + MD_INT_STA, u4Value); + HAL_MCR_RD(prAdapter, MD_WPDMA_GLO_CFG, &u4Value); + DBGLOG(HAL, INFO, "MD_WPDMA_GLO_CFG:0x%08x = 0x%08x\n", + MD_WPDMA_GLO_CFG, u4Value); + HAL_MCR_RD(prAdapter, MD_INT_ENA, &u4Value); + DBGLOG(HAL, INFO, "MD_INT_ENA:0x%08x = 0x%08x\n", + MD_INT_ENA, u4Value); + HAL_MCR_RD(prAdapter, MD_WPDMA_DLY_INIT_CFG, &u4Value); + DBGLOG(HAL, INFO, "MD_WPDMA_DLY_INIT_CFG:0x%08x = 0x%08x\n", + MD_WPDMA_DLY_INIT_CFG, u4Value); + HAL_MCR_RD(prAdapter, MD_WPDMA_MISC, &u4Value); + DBGLOG(HAL, INFO, "MD_WPDMA_MISC:0x%08x = 0x%08x\n", + MD_WPDMA_MISC, u4Value); +#endif + + /* PDMA Tx/Rx Ring Info */ + DBGLOG(HAL, INFO, "Tx Ring configuration\n"); + DBGLOG(HAL, INFO, "%10s%10s%12s%20s%10s%10s%10s\n", + "Tx Ring", "Idx", "Reg", "Base", "Cnt", "CIDX", "DIDX"); + + if (buf) { + kalMemZero(buf, BUF_SIZE); + for (i = 0; i < sizeof(wfmda_tx_group) / + sizeof(struct wfdma_ring_info); i++) { + int ret; + + offset = wfmda_tx_group[i].ring_idx * + MT_RINGREG_DIFF; + offset_ext = wfmda_tx_group[i].ring_idx * + MT_RINGREG_EXT_DIFF; + + HAL_MCR_RD(prAdapter, WPDMA_TX_RING0_CTRL0 + offset, + &wfmda_tx_group[i].base); + HAL_MCR_RD(prAdapter, WPDMA_TX_RING0_BASE_PTR_EXT + + offset_ext, + &wfmda_tx_group[i].base_ext); + HAL_MCR_RD(prAdapter, WPDMA_TX_RING0_CTRL1 + offset, + &wfmda_tx_group[i].cnt); + HAL_MCR_RD(prAdapter, WPDMA_TX_RING0_CTRL2 + offset, + &wfmda_tx_group[i].cidx); + HAL_MCR_RD(prAdapter, WPDMA_TX_RING0_CTRL3 + offset, + &wfmda_tx_group[i].didx); + + ret = kalSnprintf(buf, BUF_SIZE, + "%10s%10d 0x%08x 0x%016llx%10d%10d%10d", + wfmda_tx_group[i].name, + wfmda_tx_group[i].ring_idx, + WPDMA_TX_RING0_CTRL0 + offset, + (wfmda_tx_group[i].base + ((uint64_t) + wfmda_tx_group[i].base_ext << 32)), + wfmda_tx_group[i].cnt, + wfmda_tx_group[i].cidx, + wfmda_tx_group[i].didx); + if (ret >= 0 || ret < BUF_SIZE) + DBGLOG(HAL, INFO, "%s\n", buf); + else + DBGLOG(INIT, ERROR, + "[%u] kalSnprintf failed, ret: %d\n", + __LINE__, ret); + } + + DBGLOG(HAL, INFO, "Rx Ring configuration\n"); + DBGLOG(HAL, INFO, "%10s%10s%12s%20s%10s%10s%10s\n", + "Rx Ring", "Idx", "Reg", "Base", "Cnt", "CIDX", "DIDX"); + + kalMemZero(buf, BUF_SIZE); + for (i = 0; i < sizeof(wfmda_rx_group) / + sizeof(struct wfdma_ring_info); i++) { + int ret; + + offset = wfmda_rx_group[i].ring_idx * MT_RINGREG_DIFF; + offset_ext = wfmda_rx_group[i].ring_idx * + MT_RINGREG_EXT_DIFF; + + HAL_MCR_RD(prAdapter, WPDMA_RX_RING0_CTRL0 + offset, + &wfmda_rx_group[i].base); + HAL_MCR_RD(prAdapter, WPDMA_RX_RING0_BASE_PTR_EXT + + offset_ext, + &wfmda_rx_group[i].base_ext); + HAL_MCR_RD(prAdapter, WPDMA_RX_RING0_CTRL1 + offset, + &wfmda_rx_group[i].cnt); + HAL_MCR_RD(prAdapter, WPDMA_RX_RING0_CTRL2 + offset, + &wfmda_rx_group[i].cidx); + HAL_MCR_RD(prAdapter, WPDMA_RX_RING0_CTRL3 + offset, + &wfmda_rx_group[i].didx); + + ret = kalSnprintf(buf, BUF_SIZE, + "%10s%10d 0x%08x 0x%016llx%10d%10d%10d", + wfmda_rx_group[i].name, + wfmda_rx_group[i].ring_idx, + WPDMA_RX_RING0_CTRL0 + offset, + (wfmda_rx_group[i].base + ((uint64_t) + wfmda_rx_group[i].base_ext << 32)), + wfmda_rx_group[i].cnt, + wfmda_rx_group[i].cidx, + wfmda_rx_group[i].didx); + if (ret >= 0 || ret < BUF_SIZE) + DBGLOG(HAL, INFO, "%s\n", buf); + else + DBGLOG(INIT, ERROR, + "[%u] kalSnprintf failed, ret: %d\n", + __LINE__, ret); + } + } + + /* PDMA Tx/Rx descriptor & packet content */ + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + for (i = 0; i < sizeof(wfmda_tx_group) / + sizeof(struct wfdma_ring_info); i++) { + if (!wfmda_tx_group[i].dump_ring_content) + continue; + DBGLOG(HAL, INFO, "Dump PDMA Tx Ring[%u]\n", + wfmda_tx_group[i].ring_idx); + prTxRing = &prHifInfo->TxRing[i]; + SwIdx = wfmda_tx_group[i].didx; + kalDumpTxRing(prAdapter->prGlueInfo, prTxRing, + SwIdx, true); + SwIdx = wfmda_tx_group[i].didx == 0 ? + wfmda_tx_group[i].cnt - 1 : + wfmda_tx_group[i].didx - 1; + kalDumpTxRing(prAdapter->prGlueInfo, prTxRing, + SwIdx, true); + } + + for (i = 0; i < sizeof(wfmda_rx_group) / + sizeof(struct wfdma_ring_info); i++) { + if (!wfmda_rx_group[i].dump_ring_content) + continue; + DBGLOG(HAL, INFO, "Dump PDMA Rx Ring[%u]\n", + wfmda_rx_group[i].ring_idx); + prRxRing = &prHifInfo->RxRing[i]; + SwIdx = wfmda_rx_group[i].didx; + kalDumpRxRing(prAdapter->prGlueInfo, prRxRing, + SwIdx, true); + SwIdx = wfmda_rx_group[i].didx == 0 ? + wfmda_rx_group[i].cnt - 1 : + wfmda_rx_group[i].didx - 1; + kalDumpRxRing(prAdapter->prGlueInfo, prRxRing, + SwIdx, true); + } + + /* PDMA Busy Status */ + HAL_MCR_RD(prAdapter, PDMA_DEBUG_BUSY_STATUS, &u4Value); + DBGLOG(HAL, INFO, "PDMA busy status:0x%08x = 0x%08x\n", + PDMA_DEBUG_STATUS, u4Value); + HAL_MCR_RD(prAdapter, PDMA_DEBUG_HIF_BUSY_STATUS, &u4Value); + DBGLOG(HAL, INFO, "CONN_HIF busy status:0x%08x = 0x%08x\n\n", + PDMA_DEBUG_HIF_BUSY_STATUS, u4Value); + + /* PDMA Debug Flag Info */ + DBGLOG(HAL, INFO, "PDMA core dbg"); + if (buf) { + kalMemZero(buf, BUF_SIZE); + pos = 0; + for (i = 0; i < 24; i++) { + u4Value = 256 + i; + HAL_MCR_WR(prAdapter, PDMA_DEBUG_EN, u4Value); + HAL_MCR_RD(prAdapter, PDMA_DEBUG_STATUS, &u4Value); + pos += kalSnprintf(buf + pos, 40, + "Set:0x%02x, result=0x%08x%s", + i, u4Value, i == 23 ? "\n" : "; "); + mdelay(1); + } + DBGLOG(HAL, INFO, "%s", buf); + } + + /* AXI Debug Flag */ + HAL_MCR_WR(prAdapter, AXI_DEBUG_DEBUG_EN, PDMA_AXI_DEBUG_FLAG); + HAL_MCR_RD(prAdapter, CONN_HIF_DEBUG_STATUS, &u4Value); + DBGLOG(HAL, INFO, "Set:0x%04x, pdma axi dbg:0x%08x", + PDMA_AXI_DEBUG_FLAG, u4Value); + + HAL_MCR_WR(prAdapter, AXI_DEBUG_DEBUG_EN, GALS_AXI_DEBUG_FLAG); + HAL_MCR_RD(prAdapter, CONN_HIF_DEBUG_STATUS, &u4Value); + DBGLOG(HAL, INFO, "Set:0x%04x, gals axi dbg:0x%08x", + GALS_AXI_DEBUG_FLAG, u4Value); + + HAL_MCR_WR(prAdapter, AXI_DEBUG_DEBUG_EN, MCU_AXI_DEBUG_FLAG); + HAL_MCR_RD(prAdapter, CONN_HIF_DEBUG_STATUS, &u4Value); + DBGLOG(HAL, INFO, "Set:0x%04x, mcu axi dbg:0x%08x", + MCU_AXI_DEBUG_FLAG, u4Value); + + /* Rbus Bridge Debug Flag */ + DBGLOG(HAL, INFO, "rbus dbg"); + HAL_MCR_WR(prAdapter, PDMA_DEBUG_EN, RBUS_DEBUG_FLAG); + if (buf) { + kalMemZero(buf, BUF_SIZE); + pos = 0; + for (i = 0; i < 9; i++) { + u4Value = i << 16; + HAL_MCR_WR(prAdapter, AXI_DEBUG_DEBUG_EN, u4Value); + HAL_MCR_RD(prAdapter, PDMA_DEBUG_STATUS, &u4Value); + pos += kalSnprintf(buf + pos, 40, + "Set[19:16]:0x%02x, result = 0x%08x%s", + i, u4Value, i == 8 ? "\n" : "; "); + } + DBGLOG(HAL, INFO, "%s", buf); + } + if (prAdapter->chip_info->prDebugOps->showHifInfo) + prAdapter->chip_info->prDebugOps->showHifInfo(prAdapter); + if (buf) + kalMemFree(buf, VIR_MEM_TYPE, BUF_SIZE); + +#undef BUF_SIZE +} + +bool halShowHostCsrInfo(IN struct ADAPTER *prAdapter) +{ + uint32_t i = 0, u4Value = 0; + bool fgIsDriverOwn = false; + bool fgEnClock = false; + + DBGLOG(HAL, INFO, "Host CSR Configuration Info:\n\n"); + + HAL_MCR_RD(prAdapter, HOST_CSR_BASE, &u4Value); + DBGLOG(HAL, INFO, "Get 0x87654321: 0x%08x = 0x%08x\n", + HOST_CSR_BASE, u4Value); + + HAL_MCR_RD(prAdapter, HOST_CSR_DRIVER_OWN_INFO, &u4Value); + DBGLOG(HAL, INFO, "Driver own info: 0x%08x = 0x%08x\n", + HOST_CSR_BASE, u4Value); + fgIsDriverOwn = (u4Value & PCIE_LPCR_HOST_SET_OWN) == 0; + + for (i = 0; i < 5; i++) { + HAL_MCR_RD(prAdapter, HOST_CSR_MCU_PORG_COUNT, &u4Value); + DBGLOG(HAL, INFO, + "MCU programming Counter info (no sync): 0x%08x = 0x%08x\n", + HOST_CSR_MCU_PORG_COUNT, u4Value); + } + + HAL_MCR_RD(prAdapter, HOST_CSR_RGU, &u4Value); + DBGLOG(HAL, INFO, "RGU Info: 0x%08x = 0x%08x\n", HOST_CSR_RGU, u4Value); + + HAL_MCR_RD(prAdapter, HOST_CSR_HIF_BUSY_CORQ_WFSYS_ON, &u4Value); + DBGLOG(HAL, INFO, "HIF_BUSY / CIRQ / WFSYS_ON info: 0x%08x = 0x%08x\n", + HOST_CSR_HIF_BUSY_CORQ_WFSYS_ON, u4Value); + + HAL_MCR_RD(prAdapter, HOST_CSR_PINMUX_MON_FLAG, &u4Value); + DBGLOG(HAL, INFO, "Pinmux/mon_flag info: 0x%08x = 0x%08x\n", + HOST_CSR_PINMUX_MON_FLAG, u4Value); + + HAL_MCR_RD(prAdapter, HOST_CSR_MCU_PWR_STAT, &u4Value); + DBGLOG(HAL, INFO, "Bit[5] mcu_pwr_stat: 0x%08x = 0x%08x\n", + HOST_CSR_MCU_PWR_STAT, u4Value); + + HAL_MCR_RD(prAdapter, HOST_CSR_FW_OWN_SET, &u4Value); + DBGLOG(HAL, INFO, "Bit[15] fw_own_stat: 0x%08x = 0x%08x\n", + HOST_CSR_FW_OWN_SET, u4Value); + + HAL_MCR_RD(prAdapter, HOST_CSR_MCU_SW_MAILBOX_0, &u4Value); + DBGLOG(HAL, INFO, "WF Mailbox[0]: 0x%08x = 0x%08x\n", + HOST_CSR_MCU_SW_MAILBOX_0, u4Value); + + HAL_MCR_RD(prAdapter, HOST_CSR_MCU_SW_MAILBOX_1, &u4Value); + DBGLOG(HAL, INFO, "MCU Mailbox[1]: 0x%08x = 0x%08x\n", + HOST_CSR_MCU_SW_MAILBOX_1, u4Value); + + HAL_MCR_RD(prAdapter, HOST_CSR_MCU_SW_MAILBOX_2, &u4Value); + DBGLOG(HAL, INFO, "BT Mailbox[2]: 0x%08x = 0x%08x\n", + HOST_CSR_MCU_SW_MAILBOX_2, u4Value); + + HAL_MCR_RD(prAdapter, HOST_CSR_MCU_SW_MAILBOX_3, &u4Value); + DBGLOG(HAL, INFO, "GPS Mailbox[3]: 0x%08x = 0x%08x\n", + HOST_CSR_MCU_SW_MAILBOX_3, u4Value); + + HAL_MCR_RD(prAdapter, HOST_CSR_CONN_CFG_ON, &u4Value); + DBGLOG(HAL, INFO, "Conn_cfg_on info: 0x%08x = 0x%08x\n", + HOST_CSR_CONN_CFG_ON, u4Value); + +#if (CFG_ENABLE_HOST_BUS_TIMEOUT == 1) + HAL_MCR_RD(prAdapter, HOST_CSR_AP2CONN_AHB_HADDR, &u4Value); + DBGLOG(HAL, INFO, "HOST_CSR_AP2CONN_AHB_HADDR: 0x%08x = 0x%08x\n", + HOST_CSR_AP2CONN_AHB_HADDR, u4Value); +#endif + +#if CFG_MTK_MCIF_WIFI_SUPPORT + HAL_MCR_RD(prAdapter, HOST_CSR_CONN_HIF_ON_MD_LPCTL_ADDR, &u4Value); + DBGLOG(HAL, INFO, "CONN_HIF_ON_MD_LPCTL_ADDR: 0x%08x = 0x%08x\n", + HOST_CSR_CONN_HIF_ON_MD_LPCTL_ADDR, u4Value); + HAL_MCR_RD(prAdapter, HOST_CSR_CONN_HIF_ON_MD_IRQ_STAT_ADDR, &u4Value); + DBGLOG(HAL, INFO, "CONN_HIF_ON_MD_IRQ_STAT_ADDR: 0x%08x = 0x%08x\n", + HOST_CSR_CONN_HIF_ON_MD_IRQ_STAT_ADDR, u4Value); + HAL_MCR_RD(prAdapter, HOST_CSR_CONN_HIF_ON_MD_IRQ_ENA_ADDR, &u4Value); + DBGLOG(HAL, INFO, "CONN_HIF_ON_MD_IRQ_ENA_ADDR: 0x%08x = 0x%08x\n", + HOST_CSR_CONN_HIF_ON_MD_IRQ_ENA_ADDR, u4Value); +#endif + + HAL_MCR_WR(prAdapter, HOST_CSR_DRIVER_OWN_INFO, 0x00030000); + kalUdelay(1); + HAL_MCR_RD(prAdapter, HOST_CSR_DRIVER_OWN_INFO, &u4Value); + DBGLOG(HAL, INFO, "Bit[17]/[16], Get HCLK info: 0x%08x = 0x%08x\n", + HOST_CSR_DRIVER_OWN_INFO, u4Value); + + /* check clock is enabled */ + fgEnClock = ((u4Value & BIT(17)) != 0) && ((u4Value & BIT(16)) != 0); + + return fgIsDriverOwn && fgEnClock; +} + +void haldumpPhyInfo(struct ADAPTER *prAdapter) +{ + uint32_t i = 0, value = 0; + + for (i = 0; i < 20; i++) { + HAL_MCR_RD(prAdapter, 0x82072644, &value); + DBGLOG(HAL, INFO, "0x82072644: 0x%08x\n", value); + HAL_MCR_RD(prAdapter, 0x82072654, &value); + DBGLOG(HAL, INFO, "0x82072654: 0x%08x\n", value); + kalMdelay(1); + } +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/common/hal_pdma.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/common/hal_pdma.c new file mode 100644 index 0000000000000..b088f96cacfd0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/common/hal_pdma.c @@ -0,0 +1,3089 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** + *[File] hif_pdma.c + *[Version] v1.0 + *[Revision Date] 2015-09-08 + *[Author] + *[Description] + * The program provides PDMA HIF APIs + *[Copyright] + * Copyright (C) 2015 MediaTek Incorporation. All Rights Reserved. + ******************************************************************************/ + +/******************************************************************************* + * C O M P I L E 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 "hif_pdma.h" + +#include +#ifndef CONFIG_X86 +#include +#endif + +#include "mt66xx_reg.h" +#include "gl_kal.h" +#include "host_csr.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define RX_RESPONSE_TIMEOUT (3000) + + +/******************************************************************************* + * 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 uint8_t halRingDataSelectByWmmIndex( + IN struct ADAPTER *prAdapter, + IN uint8_t ucWmmIndex) +{ + struct BUS_INFO *bus_info; + uint16_t u2Port = TX_RING_DATA0_IDX_0; + + bus_info = prAdapter->chip_info->bus_info; + if (bus_info->tx_ring0_data_idx != bus_info->tx_ring1_data_idx) { + u2Port = (ucWmmIndex == 1) ? + TX_RING_DATA1_IDX_1 : TX_RING_DATA0_IDX_0; + } + return u2Port; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Decide TxRingData number by MsduInfo + * + * @param prGlueInfo + * + * @param prMsduInfo + * + * @return TxRingData number + */ +/*----------------------------------------------------------------------------*/ +uint8_t halTxRingDataSelect(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + ASSERT(prAdapter); + return halRingDataSelectByWmmIndex(prAdapter, prMsduInfo->ucWmmQueSet); +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief check is timeout or not + * + * @param u4StartTime start time + * + * @param u4Timeout timeout value + * + * @return is timeout + */ +/*----------------------------------------------------------------------------*/ +static inline bool halIsTimeout(uint32_t u4StartTime, uint32_t u4Timeout) +{ + uint32_t u4CurTime = kalGetTimeTick(); + uint32_t u4Time = 0; + + if (u4CurTime >= u4StartTime) + u4Time = u4CurTime - u4StartTime; + else + u4Time = u4CurTime + (0xFFFFFFFF - u4StartTime); + + return u4Time > u4Timeout; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t halVerifyChipID(IN struct ADAPTER *prAdapter) +{ + struct mt66xx_chip_info *prChipInfo; + struct BUS_INFO *prBusInfo; + uint32_t u4CIR = 0; + + ASSERT(prAdapter); + + prChipInfo = prAdapter->chip_info; + prBusInfo = prChipInfo->bus_info; + + if (prAdapter->fgIsReadRevID || !prChipInfo->should_verify_chip_id) + return TRUE; + + HAL_MCR_RD(prAdapter, prBusInfo->top_cfg_base + TOP_HW_CONTROL, &u4CIR); + + DBGLOG(INIT, INFO, "WCIR_CHIP_ID = 0x%x, chip_id = 0x%x\n", + (uint32_t)(u4CIR & WCIR_CHIP_ID), prChipInfo->chip_id); + + if ((u4CIR & WCIR_CHIP_ID) != prChipInfo->chip_id) + return FALSE; + + HAL_MCR_RD(prAdapter, prBusInfo->top_cfg_base + TOP_HW_VERSION, &u4CIR); + + prAdapter->ucRevID = (uint8_t)(u4CIR & 0xF); + prAdapter->fgIsReadRevID = TRUE; + + return TRUE; +} + +uint32_t halRxWaitResponse(IN struct ADAPTER *prAdapter, IN uint8_t ucPortIdx, + OUT uint8_t *pucRspBuffer, IN uint32_t u4MaxRespBufferLen, + OUT uint32_t *pu4Length) +{ + struct GLUE_INFO *prGlueInfo; + uint32_t u4PktLen = 0, u4Value = 0, u4Time; + u_int8_t fgStatus; + struct mt66xx_chip_info *prChipInfo; + + DEBUGFUNC("nicRxWaitResponse"); + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + prChipInfo = prAdapter->chip_info; + ASSERT(prGlueInfo); + ASSERT(pucRspBuffer); + + if (prChipInfo->is_support_wfdma1) + ucPortIdx = prChipInfo->rx_event_port; + else { + ASSERT(ucPortIdx < 2); + ucPortIdx = HIF_IMG_DL_STATUS_PORT_IDX; + } + + u4Time = kalGetTimeTick(); + u4PktLen = u4MaxRespBufferLen; + + do { + if (wlanIsChipNoAck(prAdapter)) { + DBGLOG(HAL, ERROR, "Chip No Ack\n"); + return WLAN_STATUS_FAILURE; + } + + fgStatus = kalDevPortRead( + prGlueInfo, ucPortIdx, u4PktLen, + pucRspBuffer, HIF_RX_COALESCING_BUFFER_SIZE); + if (fgStatus) { + *pu4Length = u4PktLen; + break; + } + + if (halIsTimeout(u4Time, RX_RESPONSE_TIMEOUT)) { + kalDevRegRead(prGlueInfo, CONN_HIF_ON_DBGCR01, + &u4Value); + DBGLOG(HAL, ERROR, "CONN_HIF_ON_DBGCR01[0x%x]\n", + u4Value); + return WLAN_STATUS_FAILURE; + } + + /* Response packet is not ready */ + kalUdelay(50); + } while (TRUE); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief enable global interrupt + * + * @param prAdapter pointer to the Adapter handler + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void halEnableInterrupt(IN struct ADAPTER *prAdapter) +{ + struct BUS_INFO *prBusInfo = NULL; + + ASSERT(prAdapter); + + prBusInfo = prAdapter->chip_info->bus_info; + + if (prBusInfo->enableInterrupt) + prBusInfo->enableInterrupt(prAdapter); + + prAdapter->fgIsIntEnable = TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief disable global interrupt + * + * @param prAdapter pointer to the Adapter handler + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void halDisableInterrupt(IN struct ADAPTER *prAdapter) +{ + struct BUS_INFO *prBusInfo; + + ASSERT(prAdapter); + + prBusInfo = prAdapter->chip_info->bus_info; + + if (prBusInfo->disableInterrupt) + prBusInfo->disableInterrupt(prAdapter); + + prAdapter->fgIsIntEnable = FALSE; +} + +static u_int8_t halDriverOwnCheckCR4(struct ADAPTER *prAdapter) +{ + struct mt66xx_chip_info *prChipInfo; + uint32_t u4CurrTick; + uint32_t ready_bits; + u_int8_t fgStatus = TRUE; + u_int8_t fgReady = FALSE; + u_int8_t fgDummyReq = FALSE; + bool fgTimeout; + + ASSERT(prAdapter); + + prChipInfo = prAdapter->chip_info; + ready_bits = prChipInfo->sw_ready_bits; + + HAL_WIFI_FUNC_READY_CHECK(prAdapter, + WIFI_FUNC_DUMMY_REQ, &fgDummyReq); + + u4CurrTick = kalGetTimeTick(); + /* Wait CR4 ready */ + while (1) { + fgTimeout = halIsTimeout(u4CurrTick, + LP_OWN_BACK_TOTAL_DELAY_MS); + HAL_WIFI_FUNC_READY_CHECK(prAdapter, ready_bits, &fgReady); + + if (fgReady) { + break; + } else if (kalIsCardRemoved(prAdapter->prGlueInfo) || + fgIsBusAccessFailed || fgTimeout + || wlanIsChipNoAck(prAdapter)) { + DBGLOG(INIT, INFO, + "Skip waiting CR4 ready for next %ums\n", + LP_OWN_BACK_FAILED_LOG_SKIP_MS); + fgStatus = FALSE; +#if CFG_CHIP_RESET_SUPPORT + glSetRstReason(RST_DRV_OWN_FAIL); + GL_RESET_TRIGGER(prAdapter, + RST_FLAG_CHIP_RESET); +#endif + break; + } + /* Delay for CR4 to complete its operation. */ + kalUsleep_range(LP_OWN_BACK_LOOP_DELAY_MIN_US, + LP_OWN_BACK_LOOP_DELAY_MAX_US); + } + + /* Send dummy cmd and clear flag */ + if (fgDummyReq) { + wlanSendDummyCmd(prAdapter, FALSE); + HAL_CLEAR_DUMMY_REQ(prAdapter); + } + + return fgStatus; +} + +static void halDriverOwnTimeout(struct ADAPTER *prAdapter, + uint32_t u4CurrTick, u_int8_t fgTimeout) +{ + struct mt66xx_chip_info *prChipInfo; + struct CHIP_DBG_OPS *prChipDbgOps; + + prChipInfo = prAdapter->chip_info; + prChipDbgOps = prChipInfo->prDebugOps; + + if ((prAdapter->u4OwnFailedCount == 0) || + CHECK_FOR_TIMEOUT(u4CurrTick, prAdapter->rLastOwnFailedLogTime, + MSEC_TO_SYSTIME(LP_OWN_BACK_FAILED_LOG_SKIP_MS)) + ) { + DBGLOG(INIT, ERROR, + "LP cannot be own back, Timeout[%u](%ums), BusAccessError[%u]", + fgTimeout, + kalGetTimeTick() - u4CurrTick, + fgIsBusAccessFailed); + DBGLOG(INIT, ERROR, + "Resetting[%u], CardRemoved[%u] NoAck[%u] Cnt[%u]\n", + kalIsResetting(), + kalIsCardRemoved(prAdapter->prGlueInfo), + wlanIsChipNoAck(prAdapter), + prAdapter->u4OwnFailedCount); + DBGLOG(INIT, INFO, + "Skip LP own back failed log for next %ums\n", + LP_OWN_BACK_FAILED_LOG_SKIP_MS); + if (prChipInfo->dumpwfsyscpupcr) + prChipInfo->dumpwfsyscpupcr(prAdapter); + + prAdapter->u4OwnFailedLogCount++; + if (prAdapter->u4OwnFailedLogCount > + LP_OWN_BACK_FAILED_RESET_CNT) { + if (prChipDbgOps->showCsrInfo) + prChipDbgOps->showCsrInfo(prAdapter); + if (prChipInfo->dumpBusHangCr) + prChipInfo->dumpBusHangCr(prAdapter); +#if CFG_CHIP_RESET_SUPPORT + /* Trigger RESET */ + glSetRstReason(RST_DRV_OWN_FAIL); +#if (CFG_SUPPORT_CONNINFRA == 0) + GL_RESET_TRIGGER(prAdapter, RST_FLAG_CHIP_RESET); +#else + GL_RESET_TRIGGER(prAdapter, RST_FLAG_WF_RESET); +#endif + +#endif + } + GET_CURRENT_SYSTIME(&prAdapter->rLastOwnFailedLogTime); + } + + prAdapter->u4OwnFailedCount++; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to process the POWER OFF procedure. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +u_int8_t halSetDriverOwn(IN struct ADAPTER *prAdapter) +{ + struct mt66xx_chip_info *prChipInfo; + struct BUS_INFO *prBusInfo; + u_int8_t fgStatus = TRUE; + uint32_t i, u4CurrTick, u4WriteTick, u4WriteTickTemp; + u_int8_t fgTimeout; + u_int8_t fgResult; + + KAL_TIME_INTERVAL_DECLARATION(); + + ASSERT(prAdapter); + + prChipInfo = prAdapter->chip_info; + prBusInfo = prChipInfo->bus_info; + + GLUE_INC_REF_CNT(prAdapter->u4PwrCtrlBlockCnt); + + if (prAdapter->fgIsFwOwn == FALSE) + return fgStatus; + + DBGLOG(INIT, TRACE, "DRIVER OWN Start\n"); + KAL_REC_TIME_START(); + + u4WriteTick = 0; + u4CurrTick = kalGetTimeTick(); + i = 0; + + /* PCIE/AXI need to do clear own, then could start polling status */ + HAL_LP_OWN_CLR(prAdapter, &fgResult); + fgResult = FALSE; + + while (1) { + if (!prBusInfo->fgCheckDriverOwnInt || + test_bit(GLUE_FLAG_INT_BIT, &prAdapter->prGlueInfo->ulFlag)) + HAL_LP_OWN_RD(prAdapter, &fgResult); + + fgTimeout = ((kalGetTimeTick() - u4CurrTick) > + LP_OWN_BACK_TOTAL_DELAY_MS) ? TRUE : FALSE; + + if (fgResult) { + /* Check WPDMA FW own interrupt status and clear */ + if (prBusInfo->fgCheckDriverOwnInt) + HAL_MCR_WR(prAdapter, + prBusInfo->fw_own_clear_addr, + prBusInfo->fw_own_clear_bit); + prAdapter->fgIsFwOwn = FALSE; + prAdapter->u4OwnFailedCount = 0; + prAdapter->u4OwnFailedLogCount = 0; + break; + } else if (wlanIsChipNoAck(prAdapter)) { + DBGLOG(INIT, INFO, + "Driver own return due to chip reset and chip no response.\n"); + fgStatus = FALSE; + break; + } else if ((i > LP_OWN_BACK_FAILED_RETRY_CNT) && + (kalIsCardRemoved(prAdapter->prGlueInfo) || + fgIsBusAccessFailed || fgTimeout)) { + halDriverOwnTimeout(prAdapter, u4CurrTick, fgTimeout); + fgStatus = FALSE; + break; + } + + u4WriteTickTemp = kalGetTimeTick(); + if ((i == 0) || TIME_AFTER(u4WriteTickTemp, + (u4WriteTick + LP_OWN_REQ_CLR_INTERVAL_MS))) { + /* Driver get LP ownership per 200 ms, + * to avoid iteration time not accurate + */ + HAL_LP_OWN_CLR(prAdapter, &fgResult); + u4WriteTick = u4WriteTickTemp; + } + + /* Delay for LP engine to complete its operation. */ + kalUsleep_range(LP_OWN_BACK_LOOP_DELAY_MIN_US, + LP_OWN_BACK_LOOP_DELAY_MAX_US); + i++; + } + + /* For Low power Test */ + /* 1. Driver need to polling until CR4 ready, + * then could do normal Tx/Rx + * 2. After CR4 ready, send a dummy command to change data path + * to store-forward mode + */ + if (prAdapter->fgIsFwDownloaded && prChipInfo->is_support_cr4) + fgStatus &= halDriverOwnCheckCR4(prAdapter); + + if (fgStatus) { + if (prAdapter->fgIsFwDownloaded) { + /*WFDMA re-init flow after chip deep sleep*/ + if (prChipInfo->asicWfdmaReInit) + prChipInfo->asicWfdmaReInit(prAdapter); + } + /* Check consys enter sleep mode DummyReg(0x0F) */ + if (prBusInfo->checkDummyReg) + prBusInfo->checkDummyReg(prAdapter->prGlueInfo); + } + + KAL_REC_TIME_END(); + DBGLOG(INIT, INFO, + "DRIVER OWN Done[%lu us]\n", KAL_GET_TIME_INTERVAL()); + + return fgStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to process the POWER ON procedure. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void halSetFWOwn(IN struct ADAPTER *prAdapter, IN u_int8_t fgEnableGlobalInt) +{ + struct BUS_INFO *prBusInfo; + u_int8_t fgResult; + + ASSERT(prAdapter); + + prBusInfo = prAdapter->chip_info->bus_info; + + /* Decrease Block to Enter Low Power Semaphore count */ + GLUE_DEC_REF_CNT(prAdapter->u4PwrCtrlBlockCnt); + if (!(prAdapter->fgWiFiInSleepyState && + (prAdapter->u4PwrCtrlBlockCnt == 0))) + return; + + if (prAdapter->fgIsFwOwn == TRUE) + return; + + if (nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) { + DBGLOG(INIT, STATE, "Skip FW OWN due to pending INT\n"); + /* pending interrupts */ + return; + } + + if (fgEnableGlobalInt) { + prAdapter->fgIsIntEnableWithLPOwnSet = TRUE; + } else { + /* Write sleep mode magic num to dummy reg */ + if (prBusInfo->setDummyReg) + prBusInfo->setDummyReg(prAdapter->prGlueInfo); + + HAL_LP_OWN_SET(prAdapter, &fgResult); + + prAdapter->fgIsFwOwn = TRUE; + + DBGLOG(INIT, INFO, "FW OWN:%u\n", fgResult); + } +} + +void halWakeUpWiFi(IN struct ADAPTER *prAdapter) +{ + struct BUS_INFO *prBusInfo; + + ASSERT(prAdapter); + + prBusInfo = prAdapter->chip_info->bus_info; + if (prBusInfo->wakeUpWiFi) + prBusInfo->wakeUpWiFi(prAdapter); +} + +void halTxCancelSendingCmd(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo) +{ +} + +u_int8_t halTxIsDataBufEnough(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct RTMP_TX_RING *prTxRing; + uint16_t u2Port; + + u2Port = halTxRingDataSelect(prAdapter, prMsduInfo); + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + prTxRing = &prHifInfo->TxRing[u2Port]; + + if ((prHifInfo->u4TxDataQLen < halGetMsduTokenFreeCnt(prAdapter)) && + (prTxRing->u4UsedCnt + prHifInfo->u4TxDataQLen + 1 < TX_RING_SIZE)) + return TRUE; + + DBGLOG(HAL, TRACE, + "Low Tx Data Resource Tok[%u] Ring%d[%u] List[%u]\n", + halGetMsduTokenFreeCnt(prAdapter), + u2Port, + (TX_RING_SIZE - prTxRing->u4UsedCnt), + prHifInfo->u4TxDataQLen); + kalTraceEvent("Low T[%u]Ring%d[%u]L[%u] id=0x%04x sn=%d", + halGetMsduTokenFreeCnt(prAdapter), + u2Port, + (TX_RING_SIZE - prTxRing->u4UsedCnt), + prHifInfo->u4TxDataQLen, + GLUE_GET_PKT_IP_ID(prMsduInfo->prPacket), + GLUE_GET_PKT_SEQ_NO(prMsduInfo->prPacket)); + return FALSE; +} + +static void halDefaultProcessTxInterrupt(IN struct ADAPTER *prAdapter) +{ + struct BUS_INFO *prBusInfo = prAdapter->chip_info->bus_info; + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + union WPDMA_INT_STA_STRUCT rIntrStatus; + bool fgIsSetHifTxEvent = false; + + rIntrStatus = (union WPDMA_INT_STA_STRUCT)prHifInfo->u4IntStatus; + + if (rIntrStatus.field.tx_done & BIT(prBusInfo->tx_ring_fwdl_idx)) + halWpdmaProcessCmdDmaDone(prAdapter->prGlueInfo, + TX_RING_FWDL_IDX_3); + + if (rIntrStatus.field.tx_done & BIT(prBusInfo->tx_ring_cmd_idx)) + halWpdmaProcessCmdDmaDone(prAdapter->prGlueInfo, + TX_RING_CMD_IDX_2); + + if (rIntrStatus.field.tx_done & BIT(prBusInfo->tx_ring0_data_idx)) { + halWpdmaProcessDataDmaDone(prAdapter->prGlueInfo, + TX_RING_DATA0_IDX_0); + fgIsSetHifTxEvent = true; + } + + if (prBusInfo->tx_ring0_data_idx != prBusInfo->tx_ring1_data_idx && + rIntrStatus.field.tx_done & BIT(prBusInfo->tx_ring1_data_idx)) { + halWpdmaProcessDataDmaDone(prAdapter->prGlueInfo, + TX_RING_DATA1_IDX_1); + fgIsSetHifTxEvent = true; + } + + if (fgIsSetHifTxEvent) + kalSetTxEvent2Hif(prAdapter->prGlueInfo); +} + + +void halProcessTxInterrupt(IN struct ADAPTER *prAdapter) +{ + struct BUS_INFO *prBusInfo = prAdapter->chip_info->bus_info; + + if (prBusInfo->processTxInterrupt) + prBusInfo->processTxInterrupt(prAdapter); + else + halDefaultProcessTxInterrupt(prAdapter); +} + + +void halInitMsduTokenInfo(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo; + struct HIF_MEM_OPS *prMemOps; + struct MSDU_TOKEN_INFO *prTokenInfo; + struct MSDU_TOKEN_ENTRY *prToken; + struct mt66xx_chip_info *prChipInfo; + uint32_t u4Idx; + uint32_t u4TxHeadRoomSize; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + prTokenInfo = &prHifInfo->rTokenInfo; + prChipInfo = prAdapter->chip_info; + + prTokenInfo->u4UsedCnt = 0; + u4TxHeadRoomSize = NIC_TX_DESC_AND_PADDING_LENGTH + + prChipInfo->txd_append_size; + + for (u4Idx = 0; u4Idx < HIF_TX_MSDU_TOKEN_NUM; u4Idx++) { + prToken = &prTokenInfo->arToken[u4Idx]; + prToken->fgInUsed = FALSE; + prToken->prMsduInfo = NULL; + +#if HIF_TX_PREALLOC_DATA_BUFFER + prToken->u4DmaLength = NIC_TX_MAX_SIZE_PER_FRAME + + u4TxHeadRoomSize; + if (prMemOps->allocTxDataBuf) + prMemOps->allocTxDataBuf(prToken, u4Idx); + + if (prToken->prPacket) { + /* DBGLOG(HAL, TRACE, + "Msdu Entry[0x%p] Tok[%u] Buf[0x%p] len[%u]\n", + prToken, u4Idx, prToken->prPacket, + prToken->u4DmaLength); + */ + } else { + prTokenInfo->u4UsedCnt++; + DBGLOG(HAL, WARN, + "Msdu Token Memory alloc failed[%u]\n", + u4Idx); + continue; + } +#else + prToken->prPacket = NULL; + prToken->u4DmaLength = 0; + prToken->rDmaAddr = 0; +#endif + prToken->rPktDmaAddr = 0; + prToken->u4PktDmaLength = 0; + prToken->u4Token = u4Idx; + prToken->u4CpuIdx = TX_RING_SIZE; + + prTokenInfo->aprTokenStack[u4Idx] = prToken; + } + + spin_lock_init(&prTokenInfo->rTokenLock); + + DBGLOG(HAL, INFO, "Msdu Token Init: Tot[%u] Used[%u]\n", + HIF_TX_MSDU_TOKEN_NUM, prTokenInfo->u4UsedCnt); +} + +void halUninitMsduTokenInfo(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo; + struct HIF_MEM_OPS *prMemOps; + struct MSDU_TOKEN_INFO *prTokenInfo; + struct MSDU_TOKEN_ENTRY *prToken; + uint32_t u4Idx; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + prTokenInfo = &prHifInfo->rTokenInfo; + + for (u4Idx = 0; u4Idx < HIF_TX_MSDU_TOKEN_NUM; u4Idx++) { + prToken = &prTokenInfo->arToken[u4Idx]; + + if (prToken->fgInUsed) { + if (prMemOps->unmapTxBuf) { + prMemOps->unmapTxBuf( + prHifInfo, prToken->rPktDmaAddr, + prToken->u4PktDmaLength); + prMemOps->unmapTxBuf( + prHifInfo, prToken->rDmaAddr, + prToken->u4DmaLength); + } + + log_dbg(HAL, TRACE, "Clear pending Tok[%u] Msdu[0x%p] Free[%u]\n", + prToken->u4Token, prToken->prMsduInfo, + halGetMsduTokenFreeCnt(prAdapter)); + +#if !HIF_TX_PREALLOC_DATA_BUFFER + nicTxFreePacket(prAdapter, prToken->prMsduInfo, FALSE); + nicTxReturnMsduInfo(prAdapter, prToken->prMsduInfo); +#endif + } + +#if HIF_TX_PREALLOC_DATA_BUFFER + if (prMemOps->freeBuf) + prMemOps->freeBuf(prToken->prPacket, + prToken->u4DmaLength); + prToken->prPacket = NULL; +#endif + } + + prTokenInfo->u4UsedCnt = 0; + + DBGLOG(HAL, INFO, "Msdu Token Uninit: Tot[%u] Used[%u]\n", + HIF_TX_MSDU_TOKEN_NUM, prTokenInfo->u4UsedCnt); +} + +uint32_t halGetMsduTokenFreeCnt(IN struct ADAPTER *prAdapter) +{ + struct PERF_MONITOR *prPerMonitor; + struct MSDU_TOKEN_INFO *prTokenInfo = + &prAdapter->prGlueInfo->rHifInfo.rTokenInfo; + prPerMonitor = &prAdapter->rPerMonitor; + prPerMonitor->u4UsedCnt = prTokenInfo->u4UsedCnt; + + return HIF_TX_MSDU_TOKEN_NUM - prTokenInfo->u4UsedCnt; +} + +struct MSDU_TOKEN_ENTRY *halGetMsduTokenEntry(IN struct ADAPTER *prAdapter, + uint32_t u4TokenNum) +{ + struct MSDU_TOKEN_INFO *prTokenInfo = + &prAdapter->prGlueInfo->rHifInfo.rTokenInfo; + + return &prTokenInfo->arToken[u4TokenNum]; +} + +struct MSDU_TOKEN_ENTRY *halAcquireMsduToken(IN struct ADAPTER *prAdapter) +{ + struct MSDU_TOKEN_INFO *prTokenInfo = + &prAdapter->prGlueInfo->rHifInfo.rTokenInfo; + struct MSDU_TOKEN_ENTRY *prToken; + unsigned long flags = 0; + + if (!halGetMsduTokenFreeCnt(prAdapter)) { + DBGLOG(HAL, INFO, "No more free MSDU token, Used[%u]\n", + prTokenInfo->u4UsedCnt); + return NULL; + } + + spin_lock_irqsave(&prTokenInfo->rTokenLock, flags); + + prToken = prTokenInfo->aprTokenStack[prTokenInfo->u4UsedCnt]; + do_gettimeofday(&prToken->rTs); + prToken->fgInUsed = TRUE; + prTokenInfo->u4UsedCnt++; + + spin_unlock_irqrestore(&prTokenInfo->rTokenLock, flags); + + DBGLOG_LIMITED(HAL, TRACE, + "Acquire Entry[0x%p] Tok[%u] Buf[%p] Len[%u]\n", + prToken, prToken->u4Token, + prToken->prPacket, prToken->u4DmaLength); + + return prToken; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Reset all msdu token. Return used msdu & re-init token. + * + * @param prAdapter a pointer to adapter private data structure. + * + */ +/*----------------------------------------------------------------------------*/ + +static void halResetMsduToken(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo; + struct HIF_MEM_OPS *prMemOps; + struct MSDU_TOKEN_INFO *prTokenInfo; + struct MSDU_TOKEN_ENTRY *prToken; + uint32_t u4Idx = 0; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + prTokenInfo = &prHifInfo->rTokenInfo; + + for (u4Idx = 0; u4Idx < HIF_TX_MSDU_TOKEN_NUM; u4Idx++) { + prToken = &prTokenInfo->arToken[u4Idx]; + if (prToken->fgInUsed) { + if (prMemOps->unmapTxBuf) { + prMemOps->unmapTxBuf( + prHifInfo, prToken->rPktDmaAddr, + prToken->u4PktDmaLength); + prMemOps->unmapTxBuf( + prHifInfo, prToken->rDmaAddr, + prToken->u4DmaLength); + prToken->rPktDmaAddr = 0; + prToken->u4PktDmaLength = 0; + prToken->rDmaAddr = 0; + } + +#if !HIF_TX_PREALLOC_DATA_BUFFER + nicTxFreePacket(prAdapter, prToken->prMsduInfo, FALSE); + nicTxReturnMsduInfo(prAdapter, prToken->prMsduInfo); +#endif + } + + prToken->fgInUsed = FALSE; + prTokenInfo->aprTokenStack[u4Idx] = prToken; + } + prTokenInfo->u4UsedCnt = 0; +} + +void halReturnMsduToken(IN struct ADAPTER *prAdapter, uint32_t u4TokenNum) +{ + struct MSDU_TOKEN_INFO *prTokenInfo = + &prAdapter->prGlueInfo->rHifInfo.rTokenInfo; + struct MSDU_TOKEN_ENTRY *prToken; + unsigned long flags = 0; + + if (!prTokenInfo->u4UsedCnt) { + DBGLOG(HAL, WARN, "MSDU token is full, Used[%u]\n", + prTokenInfo->u4UsedCnt); + return; + } + + prToken = &prTokenInfo->arToken[u4TokenNum]; + if (!prToken->fgInUsed) { + DBGLOG(HAL, ERROR, "Return unuse token[%u]\n", u4TokenNum); + return; + } + + spin_lock_irqsave(&prTokenInfo->rTokenLock, flags); + + prToken->fgInUsed = FALSE; + prTokenInfo->u4UsedCnt--; + prTokenInfo->aprTokenStack[prTokenInfo->u4UsedCnt] = prToken; + + spin_unlock_irqrestore(&prTokenInfo->rTokenLock, flags); +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Return all timeout msdu token. + * + * @param prAdapter a pointer to adapter private data structure. + * + */ +/*----------------------------------------------------------------------------*/ +void halReturnTimeoutMsduToken(struct ADAPTER *prAdapter) +{ + struct MSDU_TOKEN_INFO *prTokenInfo; + struct MSDU_TOKEN_ENTRY *prToken; + struct timeval rNowTs, rTime; + struct timeval rTimeout; + uint32_t u4Idx = 0; + + ASSERT(prAdapter); + ASSERT(prAdapter->prGlueInfo); + + prTokenInfo = &prAdapter->prGlueInfo->rHifInfo.rTokenInfo; + + rTimeout.tv_sec = HIF_MSDU_REPORT_RETURN_TIMEOUT; + rTimeout.tv_usec = 0; + do_gettimeofday(&rNowTs); + + for (u4Idx = 0; u4Idx < HIF_TX_MSDU_TOKEN_NUM; u4Idx++) { + prToken = &prTokenInfo->arToken[u4Idx]; + if (!prToken->fgInUsed) + continue; + + /* Ignore now time < token time */ + if (halTimeCompare(&rNowTs, &prToken->rTs) < 0) + continue; + + rTime.tv_sec = rNowTs.tv_sec - prToken->rTs.tv_sec; + rTime.tv_usec = rNowTs.tv_usec; + if (prToken->rTs.tv_usec > rNowTs.tv_usec) { + rTime.tv_sec -= 1; + rTime.tv_usec += SEC_TO_USEC(1); + } + rTime.tv_usec -= prToken->rTs.tv_usec; + + /* Return token to free stack */ + if (halTimeCompare(&rTime, &rTimeout) >= 0) { + DBGLOG(HAL, INFO, + "Free TokenId[%u] timeout[sec:%ld, usec:%ld]\n", + u4Idx, rTime.tv_sec, rTime.tv_usec); + halReturnMsduToken(prAdapter, u4Idx); + } + } +} + +bool halHifSwInfoInit(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct BUS_INFO *prBusInfo = NULL; + struct mt66xx_chip_info *prChipInfo; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + prBusInfo = prAdapter->chip_info->bus_info; + if (prBusInfo->DmaShdlInit) + prBusInfo->DmaShdlInit(prAdapter); + + if (!halWpdmaAllocRing(prAdapter->prGlueInfo, true)) + return false; + + halWpdmaInitRing(prAdapter->prGlueInfo, true); + halInitMsduTokenInfo(prAdapter); + /* Initialize wfdma reInit handshake parameters */ + prChipInfo = prAdapter->chip_info; + if ((prChipInfo->asicWfdmaReInit) + && (prChipInfo->asicWfdmaReInit_handshakeInit)) + prChipInfo->asicWfdmaReInit_handshakeInit(prAdapter); + +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + prAdapter->ucSerState = SER_IDLE_DONE; + prHifInfo->rErrRecoveryCtl.eErrRecovState = ERR_RECOV_STOP_IDLE; + prHifInfo->rErrRecoveryCtl.u4Status = 0; + +#if (KERNEL_VERSION(4, 15, 0) <= CFG80211_VERSION_CODE) + timer_setup(&prHifInfo->rSerTimer, halHwRecoveryTimeout, 0); + prHifInfo->rSerTimerData = (unsigned long)prAdapter->prGlueInfo; +#else + init_timer(&prHifInfo->rSerTimer); + prHifInfo->rSerTimer.function = halHwRecoveryTimeout; + prHifInfo->rSerTimer.data = (unsigned long)prAdapter->prGlueInfo; +#endif + prHifInfo->rSerTimer.expires = + jiffies + HIF_SER_TIMEOUT * HZ / MSEC_PER_SEC; + + INIT_LIST_HEAD(&prHifInfo->rTxCmdQ); + INIT_LIST_HEAD(&prHifInfo->rTxDataQ); + prHifInfo->u4TxDataQLen = 0; +#endif + +#if (CFG_ENABLE_HOST_BUS_TIMEOUT == 1) + DBGLOG(HAL, INFO, "Enable Host CSR timeout mechanism.\n"); + HAL_MCR_WR(prAdapter, HOST_CSR_BUS_TIMOUT_CTRL_ADDR, 0x80EFFFFF); +#endif + + prHifInfo->fgIsPowerOff = false; + + return true; +} + +void halHifSwInfoUnInit(IN struct GLUE_INFO *prGlueInfo) +{ +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + struct list_head *prCur, *prNext; + struct TX_CMD_REQ *prTxCmdReq; + struct TX_DATA_REQ *prTxDataReq; + + del_timer_sync(&prHifInfo->rSerTimer); + + halUninitMsduTokenInfo(prGlueInfo->prAdapter); + halWpdmaFreeRing(prGlueInfo); + + list_for_each_safe(prCur, prNext, &prHifInfo->rTxCmdQ) { + prTxCmdReq = list_entry(prCur, struct TX_CMD_REQ, list); + list_del(prCur); + kfree(prTxCmdReq); + } + + list_for_each_safe(prCur, prNext, &prHifInfo->rTxDataQ) { + prTxDataReq = list_entry(prCur, struct TX_DATA_REQ, list); + list_del(prCur); + prHifInfo->u4TxDataQLen--; + } +#endif +} + +void halRxProcessMsduReport(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb) +{ + struct GL_HIF_INFO *prHifInfo; + struct HIF_MEM_OPS *prMemOps; + struct RTMP_DMACB *prTxCell; + struct RTMP_TX_RING *prTxRing; + struct HW_MAC_MSDU_REPORT *prMsduReport; + struct MSDU_TOKEN_ENTRY *prTokenEntry; +#if !HIF_TX_PREALLOC_DATA_BUFFER + struct MSDU_INFO *prMsduInfo; +#endif + struct QUE rFreeQueue; + struct QUE *prFreeQueue; + uint16_t u2TokenCnt, u2TotalTokenCnt; + uint32_t u4Idx, u4Token; + uint8_t ucVer; + + ASSERT(prAdapter); + ASSERT(prAdapter->prGlueInfo); + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + + prFreeQueue = &rFreeQueue; + QUEUE_INITIALIZE(prFreeQueue); + + prMsduReport = (struct HW_MAC_MSDU_REPORT *)prSwRfb->pucRecvBuff; + ucVer = prMsduReport->DW1.field.u4Ver; + if (ucVer == TFD_EVT_VER_3) + u2TotalTokenCnt = prMsduReport->DW0.field_v3.u2MsduCount; + else + u2TotalTokenCnt = prMsduReport->DW0.field.u2MsduCount; + + u4Idx = u2TokenCnt = 0; + while (u2TokenCnt < u2TotalTokenCnt) { + /* Format version of this tx done event. + * 0: MT7615 + * 1: MT7622, CONNAC (X18/P18/MT7663) + * 2: MT7915 E1/Petrus + * 3: MT7915 E2/Buzzard + */ + if (ucVer == TFD_EVT_VER_0) + u4Token = prMsduReport->au4MsduToken[u4Idx >> 1]. + rFormatV0.u2MsduID[u4Idx & 1]; + else if (ucVer == TFD_EVT_VER_1) + u4Token = prMsduReport->au4MsduToken[u4Idx]. + rFormatV1.u2MsduID; + else if (ucVer == TFD_EVT_VER_2) + u4Token = prMsduReport->au4MsduToken[u4Idx]. + rFormatV2.u2MsduID; + else { + if (!prMsduReport->au4MsduToken[u4Idx]. + rFormatV3.rP0.u4Pair) + u4Token = prMsduReport->au4MsduToken[u4Idx]. + rFormatV3.rP0.u4MsduID; + else { + u4Idx++; + continue; + } + } + u4Idx++; + u2TokenCnt++; + + if (u4Token >= HIF_TX_MSDU_TOKEN_NUM) { + DBGLOG(HAL, ERROR, "Error MSDU report[%u]\n", u4Token); + DBGLOG_MEM32(HAL, ERROR, prMsduReport, 64); + prAdapter->u4HifDbgFlag |= DEG_HIF_DEFAULT_DUMP; + halPrintHifDbgInfo(prAdapter); + return; + } + + prTokenEntry = halGetMsduTokenEntry(prAdapter, u4Token); + +#if HIF_TX_PREALLOC_DATA_BUFFER + DBGLOG_LIMITED(HAL, TRACE, + "MsduRpt: Cnt[%u] Tok[%u] Free[%u]\n", + u2TokenCnt, u4Token, + halGetMsduTokenFreeCnt(prAdapter)); +#else + prMsduInfo = prTokenEntry->prMsduInfo; + prMsduInfo->prToken = NULL; + if (!prMsduInfo->pfTxDoneHandler) + QUEUE_INSERT_TAIL(prFreeQueue, + (struct QUE_ENTRY *) prMsduInfo); + + DBGLOG_LIMITED(HAL, TRACE, + "MsduRpt: Cnt[%u] Tok[%u] Msdu[0x%p] TxDone[%u] Free[%u]\n", + u2TokenCnt, u4Token, prMsduInfo, + (prMsduInfo->pfTxDoneHandler ? TRUE : FALSE), + halGetMsduTokenFreeCnt(prAdapter)); +#endif + if (prMemOps->unmapTxBuf) { + prMemOps->unmapTxBuf(prHifInfo, + prTokenEntry->rPktDmaAddr, + prTokenEntry->u4PktDmaLength); + prMemOps->unmapTxBuf(prHifInfo, + prTokenEntry->rDmaAddr, + prTokenEntry->u4DmaLength); + } + + if (prTokenEntry->u4CpuIdx < TX_RING_SIZE) { + prTxRing = &prHifInfo->TxRing[prTokenEntry->u2Port]; + prTxCell = &prTxRing->Cell[prTokenEntry->u4CpuIdx]; + prTxCell->prToken = NULL; + } + prTokenEntry->u4CpuIdx = TX_RING_SIZE; + halReturnMsduToken(prAdapter, u4Token); + GLUE_INC_REF_CNT(prAdapter->rHifStats.u4DataMsduRptCount); + } + +#if !HIF_TX_PREALLOC_DATA_BUFFER + nicTxMsduDoneCb(prAdapter->prGlueInfo, prFreeQueue); +#endif + + /* Indicate Service Thread */ + if (wlanGetTxPendingFrameCount(prAdapter) > 0) + kalSetEvent(prAdapter->prGlueInfo); + + kalSetTxEvent2Hif(prAdapter->prGlueInfo); +} + +void halTxUpdateCutThroughDesc(struct GLUE_INFO *prGlueInfo, + struct MSDU_INFO *prMsduInfo, + struct MSDU_TOKEN_ENTRY *prFillToken, + struct MSDU_TOKEN_ENTRY *prDataToken, + uint32_t u4Idx, bool fgIsLast) +{ + struct GL_HIF_INFO *prHifInfo; + struct HIF_MEM_OPS *prMemOps; + struct mt66xx_chip_info *prChipInfo; + struct TX_DESC_OPS_T *prTxDescOps; + uint8_t *pucBufferTxD; + uint32_t u4TxHeadRoomSize; + phys_addr_t rPhyAddr = 0; + + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + prChipInfo = prGlueInfo->prAdapter->chip_info; + prTxDescOps = prChipInfo->prTxDescOps; + pucBufferTxD = prDataToken->prPacket; + u4TxHeadRoomSize = NIC_TX_DESC_AND_PADDING_LENGTH + + prChipInfo->txd_append_size; + + if (prMemOps->mapTxBuf) { + rPhyAddr = prMemOps->mapTxBuf( + prHifInfo, pucBufferTxD, u4TxHeadRoomSize, + prMsduInfo->u2FrameLength); + } else { + if (prDataToken->rDmaAddr) + rPhyAddr = prDataToken->rDmaAddr + u4TxHeadRoomSize; + } + + if (!rPhyAddr) { + DBGLOG(HAL, ERROR, "Get address error!\n"); + return; + } + + if (prTxDescOps->fillHifAppend) + prTxDescOps->fillHifAppend(prGlueInfo->prAdapter, + prMsduInfo, prDataToken->u4Token, + rPhyAddr, u4Idx, fgIsLast, prFillToken->prPacket); + + prDataToken->rPktDmaAddr = rPhyAddr; + prDataToken->u4PktDmaLength = prMsduInfo->u2FrameLength; +} + +uint32_t halTxGetPageCount(IN struct ADAPTER *prAdapter, + IN uint32_t u4FrameLength, IN u_int8_t fgIncludeDesc) +{ + return 1; +} + +uint32_t halTxPollingResource(IN struct ADAPTER *prAdapter, IN uint8_t ucTC) +{ + nicTxReleaseResource(prAdapter, ucTC, 1, TRUE, FALSE); + return WLAN_STATUS_SUCCESS; +} + +void halSerHifReset(IN struct ADAPTER *prAdapter) +{ +} + +void halRxReceiveRFBs(IN struct ADAPTER *prAdapter, uint32_t u4Port, + uint8_t fgRxData) +{ + struct RX_CTRL *prRxCtrl; + struct SW_RFB *prSwRfb = (struct SW_RFB *) NULL; + uint8_t *pucBuf = NULL; + void *prRxStatus; + u_int8_t fgStatus; + uint32_t u4RxCnt; + struct RX_DESC_OPS_T *prRxDescOps; + struct RTMP_RX_RING *prRxRing; + struct GL_HIF_INFO *prHifInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxPCIeReceiveRFBs"); + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + prRxDescOps = prAdapter->chip_info->prRxDescOps; + ASSERT(prRxDescOps->nic_rxd_get_rx_byte_count); + ASSERT(prRxDescOps->nic_rxd_get_pkt_type); + ASSERT(prRxDescOps->nic_rxd_get_wlan_idx); +#if DBG + ASSERT(prRxDescOps->nic_rxd_get_sec_mode); +#endif /* DBG */ + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + prRxRing = &prHifInfo->RxRing[u4Port]; + + u4RxCnt = halWpdmaGetRxDmaDoneCnt(prAdapter->prGlueInfo, u4Port); + + DBGLOG(RX, LOUD, "halRxReceiveRFBs: u4RxCnt:%d\n", u4RxCnt); + + while (u4RxCnt--) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, + prSwRfb, struct SW_RFB *); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + if (!prSwRfb) { + DBGLOG_LIMITED(RX, WARN, "No More RFB for P[%u]\n", + u4Port); + prAdapter->u4NoMoreRfb |= BIT(u4Port); + break; + } + + /* unset no more rfb port bit */ + prAdapter->u4NoMoreRfb &= ~BIT(u4Port); + + if (fgRxData) { + fgStatus = kalDevReadData(prAdapter->prGlueInfo, + u4Port, prSwRfb); + } else { + pucBuf = prSwRfb->pucRecvBuff; + ASSERT(pucBuf); + + fgStatus = kalDevPortRead(prAdapter->prGlueInfo, + u4Port, CFG_RX_MAX_PKT_SIZE, + pucBuf, CFG_RX_MAX_PKT_SIZE); + } + if (!fgStatus) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_INSERT_TAIL(&prRxCtrl->rFreeSwRfbList, + &prSwRfb->rQueEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + continue; + } + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + prSwRfb->ucPacketType = + prRxDescOps->nic_rxd_get_pkt_type(prRxStatus); +#if DBG + DBGLOG_LIMITED(RX, LOUD, "ucPacketType = %u, ucSecMode = %u\n", + prSwRfb->ucPacketType, + prRxDescOps->nic_rxd_get_sec_mode( + prRxStatus)); +#endif /* DBG */ + + if (prSwRfb->ucPacketType == RX_PKT_TYPE_MSDU_REPORT) { + nicRxProcessMsduReport(prAdapter, prSwRfb); + + continue; + } + + GLUE_RX_SET_PKT_INT_TIME(prSwRfb->pvPacket, + prAdapter->prGlueInfo->u8HifIntTime); + GLUE_RX_SET_PKT_RX_TIME(prSwRfb->pvPacket, sched_clock()); + + kalTraceEvent("Recv id=0x%04x sn=%d", + GLUE_GET_PKT_IP_ID(prSwRfb->pvPacket), + GLUE_GET_PKT_SEQ_NO(prSwRfb->pvPacket)); + + prSwRfb->ucStaRecIdx = + secGetStaIdxByWlanIdx( + prAdapter, + prRxDescOps->nic_rxd_get_wlan_idx(prRxStatus)); + + 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); + } + prRxRing->u4PendingCnt = halWpdmaGetRxDmaDoneCnt(prAdapter->prGlueInfo, + u4Port); +} + +static void halDefaultProcessRxInterrupt(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + union WPDMA_INT_STA_STRUCT rIntrStatus; + + rIntrStatus = (union WPDMA_INT_STA_STRUCT)prHifInfo->u4IntStatus; + prAdapter->prGlueInfo->u8HifIntTime = sched_clock(); + + if (rIntrStatus.field.rx_done_1 || + (prAdapter->u4NoMoreRfb & BIT(RX_RING_EVT_IDX_1))) + halRxReceiveRFBs(prAdapter, RX_RING_EVT_IDX_1, FALSE); + + if (rIntrStatus.field.rx_done_0 || + (prAdapter->u4NoMoreRfb & BIT(RX_RING_DATA_IDX_0))) + halRxReceiveRFBs(prAdapter, RX_RING_DATA_IDX_0, TRUE); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Read frames from the data port for PCIE + * I/F, fill RFB and put each frame into the rReceivedRFBList queue. + * + * @param prAdapter Pointer to the Adapter structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void halProcessRxInterrupt(IN struct ADAPTER *prAdapter) +{ + struct BUS_INFO *prBusInfo = prAdapter->chip_info->bus_info; + + if (prBusInfo->processRxInterrupt) + prBusInfo->processRxInterrupt(prAdapter); + else + halDefaultProcessRxInterrupt(prAdapter); +} + +static int32_t halWpdmaFreeRingDesc(struct GLUE_INFO *prGlueInfo, + struct RTMP_DMABUF *prDescRing) +{ + struct GL_HIF_INFO *prHifInfo; + struct HIF_MEM_OPS *prMemOps; + + ASSERT(prGlueInfo); + + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + + if (prMemOps->freeDesc) + prMemOps->freeDesc(prHifInfo, prDescRing); + + return TRUE; +} + +bool halWpdmaAllocTxRing(struct GLUE_INFO *prGlueInfo, uint32_t u4Num, + uint32_t u4Size, uint32_t u4DescSize, bool fgAllocMem) +{ + struct GL_HIF_INFO *prHifInfo; + struct HIF_MEM_OPS *prMemOps; + struct RTMP_TX_RING *pTxRing; + struct RTMP_DMABUF *prTxDesc; + struct RTMP_DMACB *prTxCell; + phys_addr_t RingBasePa; + void *RingBaseVa; + uint32_t u4Idx; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + prTxDesc = &prHifInfo->TxDescRing[u4Num]; + + /* Don't re-alloc memory when second time call alloc ring */ + prTxDesc->AllocSize = u4Size * u4DescSize; + if (fgAllocMem && prMemOps->allocTxDesc) + prMemOps->allocTxDesc(prHifInfo, prTxDesc, u4Num); + + if (prTxDesc->AllocVa == NULL) { + DBGLOG(HAL, ERROR, "TxDescRing[%d] allocation failed\n", u4Num); + return false; + } + + DBGLOG(HAL, TRACE, "TxDescRing[%p]: total %lu bytes allocated\n", + prTxDesc->AllocVa, prTxDesc->AllocSize); + + /* Save PA & VA for further operation */ + RingBasePa = prTxDesc->AllocPa; + RingBaseVa = prTxDesc->AllocVa; + + /* + * Initialize Tx Ring Descriptor and associated buffer memory + */ + pTxRing = &prHifInfo->TxRing[u4Num]; + for (u4Idx = 0; u4Idx < u4Size; u4Idx++) { + prTxCell = &pTxRing->Cell[u4Idx]; + prTxCell->pPacket = NULL; + prTxCell->pBuffer = NULL; + + /* Init Tx Ring Size, Va, Pa variables */ + prTxCell->AllocSize = u4DescSize; + prTxCell->AllocVa = RingBaseVa; + prTxCell->AllocPa = RingBasePa; + prTxCell->prToken = NULL; + + RingBasePa += u4DescSize; + RingBaseVa += u4DescSize; + + if (fgAllocMem && prMemOps->allocTxCmdBuf) { + bool ret; + + ret = prMemOps->allocTxCmdBuf(&prTxCell->DmaBuf, + u4Num, u4Idx); + if (ret == false) { + DBGLOG(HAL, ERROR, + "TxRing[%u] TxCmd[%u] alloc failed\n", + u4Num, u4Idx); + return false; + } + } + } + + DBGLOG(HAL, TRACE, "TxRing[%d]: total %d entry allocated\n", + u4Num, u4Idx); + + return true; +} + +bool halWpdmaAllocRxRing(struct GLUE_INFO *prGlueInfo, uint32_t u4Num, + uint32_t u4Size, uint32_t u4DescSize, + uint32_t u4BufSize, bool fgAllocMem) +{ + struct GL_HIF_INFO *prHifInfo; + struct HIF_MEM_OPS *prMemOps; + struct RTMP_RX_RING *pRxRing; + struct RTMP_DMABUF *prRxDesc; + struct RTMP_DMABUF *pDmaBuf; + struct RTMP_DMACB *prRxCell; + struct RXD_STRUCT *pRxD; + phys_addr_t RingBasePa; + void *RingBaseVa; + uint32_t u4Idx; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + prRxDesc = &prHifInfo->RxDescRing[u4Num]; + + /* Don't re-alloc memory when second time call alloc ring */ + prRxDesc->AllocSize = u4Size * u4DescSize; + if (fgAllocMem && prMemOps->allocRxDesc) + prMemOps->allocRxDesc(prHifInfo, prRxDesc, u4Num); + + if (prRxDesc->AllocVa == NULL) { + DBGLOG(HAL, ERROR, "RxDescRing allocation failed!!\n"); + return false; + } + + DBGLOG(HAL, TRACE, "RxDescRing[%p]: total %lu bytes allocated\n", + prRxDesc->AllocVa, prRxDesc->AllocSize); + + /* Initialize Rx Ring and associated buffer memory */ + RingBasePa = prRxDesc->AllocPa; + RingBaseVa = prRxDesc->AllocVa; + + pRxRing = &prHifInfo->RxRing[u4Num]; + pRxRing->u4BufSize = u4BufSize; + pRxRing->u4RingSize = u4Size; + pRxRing->fgRxSegPkt = FALSE; + + for (u4Idx = 0; u4Idx < u4Size; u4Idx++) { + /* Init RX Ring Size, Va, Pa variables */ + prRxCell = &pRxRing->Cell[u4Idx]; + prRxCell->AllocSize = u4DescSize; + prRxCell->AllocVa = RingBaseVa; + prRxCell->AllocPa = RingBasePa; + prRxCell->prToken = NULL; + + /* Offset to next ring descriptor address */ + RingBasePa += u4DescSize; + RingBaseVa += u4DescSize; + + /* Setup Rx associated Buffer size & allocate share memory */ + pDmaBuf = &prRxCell->DmaBuf; + pDmaBuf->AllocSize = u4BufSize; + + if (fgAllocMem && prMemOps->allocRxBuf) + prRxCell->pPacket = prMemOps->allocRxBuf( + prHifInfo, pDmaBuf, u4Num, u4Idx); + if (pDmaBuf->AllocVa == NULL) { + log_dbg(HAL, ERROR, "\nFailed to allocate RxRing buffer idx[%u]\n", + u4Idx); + return false; + } + + /* Write RxD buffer address & allocated buffer length */ + pRxD = (struct RXD_STRUCT *)prRxCell->AllocVa; + pRxD->SDPtr0 = ((uint64_t)pDmaBuf->AllocPa) & + DMA_LOWER_32BITS_MASK; +#ifdef CONFIG_PHYS_ADDR_T_64BIT + pRxD->SDPtr1 = (((uint64_t)pDmaBuf->AllocPa >> + DMA_BITS_OFFSET) & DMA_HIGHER_4BITS_MASK); +#else + pRxD->SDPtr1 = 0; +#endif + pRxD->SDLen0 = u4BufSize; + pRxD->DMADONE = 0; + } + + DBGLOG(HAL, TRACE, "Rx[%d] Ring: total %d entry allocated\n", + u4Num, u4Idx); + + return true; +} + +static void halDefaultHifRst(struct GLUE_INFO *prGlueInfo) +{ + /* Reset Conn HIF logic */ + kalDevRegWrite(prGlueInfo, CONN_HIF_RST, 0x00000020); + kalDevRegWrite(prGlueInfo, CONN_HIF_RST, 0x00000030); +} + +void halHifRst(struct GLUE_INFO *prGlueInfo) +{ + struct ADAPTER *prAdapter; + struct BUS_INFO *prBusInfo; + + prAdapter = prGlueInfo->prAdapter; + prBusInfo = prAdapter->chip_info->bus_info; + + /* Reset dmashdl and wpdma */ + if (prBusInfo->hifRst) + prBusInfo->hifRst(prGlueInfo); + else + halDefaultHifRst(prGlueInfo); +} + +bool halWpdmaAllocRing(struct GLUE_INFO *prGlueInfo, bool fgAllocMem) +{ + struct GL_HIF_INFO *prHifInfo; + int32_t u4Num, u4Index; +#if (CFG_SUPPORT_CONNAC2X == 1) + struct BUS_INFO *prBusInfo = NULL; +#endif /* CFG_SUPPORT_CONNAC2X == 1 */ + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; +#if (CFG_SUPPORT_CONNAC2X == 1) + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; +#endif /* CFG_SUPPORT_CONNAC2X == 1 */ + + /* + * Allocate all ring descriptors, include TxD, RxD, MgmtD. + * Although each size is different, to prevent cacheline and alignment + * issue, I intentional set them all to 64 bytes + */ + for (u4Num = 0; u4Num < NUM_OF_TX_RING; u4Num++) { + if (!halWpdmaAllocTxRing(prGlueInfo, u4Num, TX_RING_SIZE, + TXD_SIZE, fgAllocMem)) { + DBGLOG(HAL, ERROR, "AllocTxRing[%d] fail\n", u4Num); + return false; + } + } + + /* Data Rx path */ + if (!halWpdmaAllocRxRing(prGlueInfo, RX_RING_DATA_IDX_0, + RX_RING0_SIZE, RXD_SIZE, + CFG_RX_MAX_PKT_SIZE, fgAllocMem)) { + DBGLOG(HAL, ERROR, "AllocRxRing[0] fail\n"); + return false; + } + + /* For connac & old ic: Event Rx path */ + /* For falcon: TxFreeDoneEvent to Host Rx path */ + /* For buzzard(costdown wfdma): Event Rx path */ + /* Event Rx path */ +#if (CFG_SUPPORT_CONNAC2X_2x2 == 1) + + if (!halWpdmaAllocRxRing(prGlueInfo, RX_RING_EVT_IDX_1, + RX_RING0_SIZE, RXD_SIZE, + RX_BUFFER_AGGRESIZE, fgAllocMem)) { + DBGLOG(HAL, ERROR, "AllocRxRing[1] fail\n"); + return false; + } +#else + if (!halWpdmaAllocRxRing(prGlueInfo, RX_RING_EVT_IDX_1, + RX_RING1_SIZE, RXD_SIZE, + RX_BUFFER_AGGRESIZE, fgAllocMem)) { + DBGLOG(HAL, ERROR, "AllocRxRing[1] fail\n"); + return false; + } +#endif + +#if (CFG_SUPPORT_CONNAC2X == 1) + if (prBusInfo->wfdmaAllocRxRing) + if (!prBusInfo->wfdmaAllocRxRing(prGlueInfo, fgAllocMem)) { + DBGLOG(HAL, ERROR, "wfdmaAllocRxRing fail\n"); + return false; + } +#endif /* CFG_SUPPORT_CONNAC2X == 1 */ + + /* Initialize all transmit related software queues */ + + /* Init TX rings index pointer */ + for (u4Index = 0; u4Index < NUM_OF_TX_RING; u4Index++) { + prHifInfo->TxRing[u4Index].TxSwUsedIdx = 0; + prHifInfo->TxRing[u4Index].TxCpuIdx = 0; + } + + return true; +} + +void halWpdmaFreeRing(struct GLUE_INFO *prGlueInfo) +{ + struct GL_HIF_INFO *prHifInfo; + struct HIF_MEM_OPS *prMemOps; + struct RTMP_TX_RING *pTxRing; + struct RTMP_RX_RING *pRxRing; + struct TXD_STRUCT *pTxD; + struct RTMP_DMACB *prDmaCb; + void *pPacket, *pBuffer; + uint32_t i, j; + + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + + /* Free Tx Ring Packet */ + for (i = 0; i < NUM_OF_TX_RING; i++) { + pTxRing = &prHifInfo->TxRing[i]; + for (j = 0; j < TX_RING_SIZE; j++) { + pTxD = (struct TXD_STRUCT *) (pTxRing->Cell[j].AllocVa); + + pPacket = pTxRing->Cell[j].pPacket; + pBuffer = pTxRing->Cell[j].pBuffer; + if (prMemOps->unmapTxBuf && pPacket) + prMemOps->unmapTxBuf( + prHifInfo, pTxRing->Cell[j].PacketPa, + pTxD->SDLen0); + pTxRing->Cell[j].pPacket = NULL; + + if (prMemOps->freeBuf && pBuffer) + prMemOps->freeBuf(pBuffer, pTxD->SDLen0); + pTxRing->Cell[j].pBuffer = NULL; + } + + halWpdmaFreeRingDesc(prGlueInfo, &prHifInfo->TxDescRing[i]); + } + + for (i = 0; i < NUM_OF_RX_RING; i++) { + pRxRing = &prHifInfo->RxRing[i]; + for (j = 0; j < pRxRing->u4RingSize; j++) { + prDmaCb = &pRxRing->Cell[j]; + if (prMemOps->unmapRxBuf && prDmaCb->DmaBuf.AllocVa) + prMemOps->unmapRxBuf(prHifInfo, + prDmaCb->DmaBuf.AllocPa, + prDmaCb->DmaBuf.AllocSize); + if (prMemOps->freePacket && prDmaCb->pPacket) + prMemOps->freePacket(prDmaCb->pPacket); + } + + halWpdmaFreeRingDesc(prGlueInfo, &prHifInfo->RxDescRing[i]); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief enable firmware download. + * + * @param[in] fgEnable 1 for fw download, 0 for normal data operation. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void halEnableFWDownload(IN struct ADAPTER *prAdapter, IN u_int8_t fgEnable) +{ + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + + prChipInfo = prAdapter->chip_info; + + if (prChipInfo->asicEnableFWDownload) + prChipInfo->asicEnableFWDownload(prAdapter, fgEnable); +} + +u_int8_t halWpdmaWaitIdle(struct GLUE_INFO *prGlueInfo, + int32_t round, int32_t wait_us) +{ + int32_t i = 0; + union WPDMA_GLO_CFG_STRUCT GloCfg; + + do { + kalDevRegRead(prGlueInfo, WPDMA_GLO_CFG, &GloCfg.word); + if ((GloCfg.field.TxDMABusy == 0) && + (GloCfg.field.RxDMABusy == 0)) { + DBGLOG(HAL, TRACE, + "==> DMAIdle, GloCfg=0x%x\n", GloCfg.word); + return TRUE; + } + kalUdelay(wait_us); + } while ((i++) < round); + + DBGLOG(HAL, INFO, "==> DMABusy, GloCfg=0x%x\n", GloCfg.word); + + return FALSE; +} + +void halWpdmaInitRing(struct GLUE_INFO *prGlueInfo, bool fgResetHif) +{ + struct GL_HIF_INFO *prHifInfo; + struct BUS_INFO *prBusInfo; + + ASSERT(prGlueInfo); + + prHifInfo = &prGlueInfo->rHifInfo; + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + + /* Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits */ + if (prBusInfo->pdmaSetup) + prBusInfo->pdmaSetup(prGlueInfo, FALSE, fgResetHif); + + halWpdmaInitTxRing(prGlueInfo); + + /* Init RX Ring0 Base/Size/Index pointer CSR */ + halWpdmaInitRxRing(prGlueInfo); + + if (prBusInfo->wfdmaManualPrefetch) + prBusInfo->wfdmaManualPrefetch(prGlueInfo); + + if (prBusInfo->pdmaSetup) + prBusInfo->pdmaSetup(prGlueInfo, TRUE, fgResetHif); + + /* Write sleep mode magic num to dummy reg */ + if (prBusInfo->setDummyReg) + prBusInfo->setDummyReg(prGlueInfo); +} + +void halWpdmaInitTxRing(IN struct GLUE_INFO *prGlueInfo) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct BUS_INFO *prBusInfo = NULL; + struct RTMP_TX_RING *prTxRing = NULL; + struct RTMP_DMACB *prTxCell; + uint32_t i = 0, offset = 0, phy_addr = 0; + struct mt66xx_chip_info *prChipInfo; + + prHifInfo = &prGlueInfo->rHifInfo; + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + prChipInfo = prGlueInfo->prAdapter->chip_info; + + /* reset all TX Ring register */ + for (i = 0; i < NUM_OF_TX_RING; i++) { + prTxRing = &prHifInfo->TxRing[i]; + prTxCell = &prTxRing->Cell[0]; + + if (i == TX_RING_CMD_IDX_2) + offset = prBusInfo->tx_ring_cmd_idx * MT_RINGREG_DIFF; + else if (i == TX_RING_FWDL_IDX_3) + offset = prBusInfo->tx_ring_fwdl_idx * MT_RINGREG_DIFF; +#if (CFG_SUPPORT_CONNAC2X == 1) + else if (prChipInfo->is_support_wacpu) { + uint32_t idx = 0; + + if (i == TX_RING_DATA0_IDX_0) + idx = prBusInfo->tx_ring0_data_idx; + else if (i == TX_RING_DATA1_IDX_1) + idx = prBusInfo->tx_ring1_data_idx; + else if (i == TX_RING_WA_CMD_IDX_4) + idx = prBusInfo->tx_ring_wa_cmd_idx; + offset = idx * MT_RINGREG_DIFF; + } +#endif /* CFG_SUPPORT_CONNAC2X == 1 */ + else + offset = i * MT_RINGREG_DIFF; + + phy_addr = ((uint64_t)prTxCell->AllocPa) & + DMA_LOWER_32BITS_MASK; + prTxRing->TxSwUsedIdx = 0; + prTxRing->u4UsedCnt = 0; + prTxRing->TxCpuIdx = 0; + + prTxRing->hw_desc_base = + prBusInfo->host_tx_ring_base + offset; + + prTxRing->hw_cidx_addr = + prBusInfo->host_tx_ring_cidx_addr + offset; + prTxRing->hw_didx_addr = + prBusInfo->host_tx_ring_didx_addr + offset; + prTxRing->hw_cnt_addr = + prBusInfo->host_tx_ring_cnt_addr + offset; + + kalDevRegWrite(prGlueInfo, prTxRing->hw_desc_base, phy_addr); + kalDevRegWrite(prGlueInfo, prTxRing->hw_cidx_addr, + prTxRing->TxCpuIdx); + kalDevRegWrite(prGlueInfo, prTxRing->hw_cnt_addr, + TX_RING_SIZE); + + if (prBusInfo->tx_ring_ext_ctrl) + prBusInfo->tx_ring_ext_ctrl(prGlueInfo, prTxRing, i); + + DBGLOG(HAL, TRACE, "-->TX_RING_%d[0x%x]: Base=0x%x, Cnt=%d!\n", + i, prHifInfo->TxRing[i].hw_desc_base, + phy_addr, TX_RING_SIZE); + } +} + +static uint8_t defaultSetRxRingHwAddr( + struct RTMP_RX_RING *prRxRing, + struct BUS_INFO *prBusInfo, + struct mt66xx_chip_info *prChipInfo, + uint32_t u4SwRingIdx) +{ + uint32_t offset = 0; + + if (u4SwRingIdx >= WFDMA1_RX_RING_IDX_0) { +#if (CFG_SUPPORT_CONNAC2X == 1) + if (prChipInfo->is_support_wfdma1) { + offset = (u4SwRingIdx - WFDMA1_RX_RING_IDX_0) + * MT_RINGREG_DIFF; + prRxRing->hw_desc_base = + prBusInfo->host_wfdma1_rx_ring_base + + offset; + prRxRing->hw_cidx_addr = + prBusInfo->host_wfdma1_rx_ring_cidx_addr + + offset; + prRxRing->hw_didx_addr = + prBusInfo->host_wfdma1_rx_ring_didx_addr + + offset; + prRxRing->hw_cnt_addr = + prBusInfo->host_wfdma1_rx_ring_cnt_addr + + offset; + } else +#endif /* CFG_SUPPORT_CONNAC2X == 1 */ + return FALSE; + } else { + offset = u4SwRingIdx * MT_RINGREG_DIFF; + prRxRing->hw_desc_base = + prBusInfo->host_rx_ring_base + offset; + prRxRing->hw_cidx_addr = + prBusInfo->host_rx_ring_cidx_addr + offset; + prRxRing->hw_didx_addr = + prBusInfo->host_rx_ring_didx_addr + offset; + prRxRing->hw_cnt_addr = + prBusInfo->host_rx_ring_cnt_addr + offset; + } + + return TRUE; +} + +void halWpdmaInitRxRing(IN struct GLUE_INFO *prGlueInfo) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct RTMP_RX_RING *prRxRing = NULL; + uint32_t i = 0, phy_addr = 0; + struct BUS_INFO *prBusInfo = NULL; + struct mt66xx_chip_info *prChipInfo; + uint8_t rv; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + prChipInfo = prGlueInfo->prAdapter->chip_info; + prBusInfo = prChipInfo->bus_info; + + /* reset all RX Ring register */ + for (i = 0; i < NUM_OF_RX_RING; i++) { + prRxRing = &prHifInfo->RxRing[i]; + if (prBusInfo->setRxRingHwAddr) + rv = prBusInfo->setRxRingHwAddr(prRxRing, prBusInfo, i); + else + rv = defaultSetRxRingHwAddr( + prRxRing, prBusInfo, prChipInfo, i); + + if (!rv) + break; + phy_addr = ((uint64_t)prRxRing->Cell[0].AllocPa & + DMA_LOWER_32BITS_MASK); + prRxRing->RxCpuIdx = prRxRing->u4RingSize - 1; + kalDevRegWrite(prGlueInfo, prRxRing->hw_desc_base, phy_addr); + kalDevRegWrite(prGlueInfo, prRxRing->hw_cidx_addr, + prRxRing->RxCpuIdx); + kalDevRegWrite(prGlueInfo, prRxRing->hw_cnt_addr, + prRxRing->u4RingSize); + + if (prBusInfo->rx_ring_ext_ctrl) + prBusInfo->rx_ring_ext_ctrl(prGlueInfo, prRxRing, i); + + prRxRing->fgIsDumpLog = false; + + DBGLOG(HAL, TRACE, "-->RX_RING_%d[0x%x]: Base=0x%x, Cnt=%d\n", + i, prRxRing->hw_desc_base, + phy_addr, prRxRing->u4RingSize); + } +} + +void halWpdmaProcessCmdDmaDone(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct HIF_MEM_OPS *prMemOps; + struct RTMP_TX_RING *prTxRing; + struct TXD_STRUCT *pTxD; + phys_addr_t PacketPa = 0; + void *pBuffer = NULL; + uint32_t u4SwIdx, u4DmaIdx = 0; + + ASSERT(prGlueInfo); + + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + prTxRing = &prHifInfo->TxRing[u2Port]; + + kalDevRegRead(prGlueInfo, prTxRing->hw_didx_addr, &u4DmaIdx); + u4SwIdx = prTxRing->TxSwUsedIdx; + + do { + pBuffer = prTxRing->Cell[u4SwIdx].pBuffer; + PacketPa = prTxRing->Cell[u4SwIdx].PacketPa; + pTxD = (struct TXD_STRUCT *) prTxRing->Cell[u4SwIdx].AllocVa; + + if (pTxD->DMADONE == 0) + break; + + log_dbg(HAL, TRACE, "DMA done: port[%u] dma[%u] idx[%u] done[%u] pkt[0x%p] used[%u]\n", + u2Port, u4DmaIdx, u4SwIdx, pTxD->DMADONE, + prTxRing->Cell[u4SwIdx].pPacket, prTxRing->u4UsedCnt); + + if (prMemOps->unmapTxBuf && PacketPa) + prMemOps->unmapTxBuf(prHifInfo, PacketPa, pTxD->SDLen0); + + pTxD->DMADONE = 0; + if (prMemOps->freeBuf && pBuffer) + prMemOps->freeBuf(pBuffer, 0); + prTxRing->Cell[u4SwIdx].pBuffer = NULL; + prTxRing->Cell[u4SwIdx].pPacket = NULL; + prTxRing->u4UsedCnt--; + + GLUE_INC_REF_CNT( + prGlueInfo->prAdapter->rHifStats.u4CmdTxdoneCount); + + INC_RING_INDEX(u4SwIdx, TX_RING_SIZE); + } while (u4SwIdx != u4DmaIdx); + + prTxRing->TxSwUsedIdx = u4SwIdx; + +} + +void halWpdmaProcessDataDmaDone(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + uint32_t u4SwIdx, u4DmaIdx = 0, u4Diff = 0; + struct RTMP_TX_RING *prTxRing; + + ASSERT(prGlueInfo); + + prHifInfo = &prGlueInfo->rHifInfo; + prTxRing = &prHifInfo->TxRing[u2Port]; + + kalDevRegRead(prGlueInfo, prTxRing->hw_didx_addr, &u4DmaIdx); + u4SwIdx = prTxRing->TxSwUsedIdx; + + if (u4DmaIdx > u4SwIdx) { + u4Diff = u4DmaIdx - u4SwIdx; + prTxRing->u4UsedCnt -= u4Diff; + } else if (u4DmaIdx < u4SwIdx) { + u4Diff = (TX_RING_SIZE + u4DmaIdx) - u4SwIdx; + prTxRing->u4UsedCnt -= u4Diff; + } else { + /* DMA index == SW used index */ + if (prTxRing->u4UsedCnt == TX_RING_SIZE) { + u4Diff = TX_RING_SIZE; + prTxRing->u4UsedCnt = 0; + } + } + + DBGLOG_LIMITED(HAL, TRACE, + "DMA done: port[%u] dma[%u] idx[%u] used[%u]\n", u2Port, + u4DmaIdx, u4SwIdx, prTxRing->u4UsedCnt); + + GLUE_ADD_REF_CNT(u4Diff, + prGlueInfo->prAdapter->rHifStats.u4DataTxdoneCount); + + prTxRing->TxSwUsedIdx = u4DmaIdx; +} + +uint32_t halWpdmaGetRxDmaDoneCnt(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRingNum) +{ + struct RTMP_RX_RING *prRxRing; + struct GL_HIF_INFO *prHifInfo; + uint32_t u4MaxCnt = 0, u4CpuIdx = 0, u4DmaIdx = 0, u4RxPktCnt; + + prHifInfo = &prGlueInfo->rHifInfo; + prRxRing = &prHifInfo->RxRing[ucRingNum]; + + kalDevRegRead(prGlueInfo, prRxRing->hw_cnt_addr, &u4MaxCnt); + kalDevRegRead(prGlueInfo, prRxRing->hw_cidx_addr, &u4CpuIdx); + kalDevRegRead(prGlueInfo, prRxRing->hw_didx_addr, &u4DmaIdx); + + if (u4MaxCnt == 0 || u4MaxCnt > RX_RING_SIZE) + return 0; + + if (u4CpuIdx > u4DmaIdx) + u4RxPktCnt = u4MaxCnt + u4DmaIdx - u4CpuIdx - 1; + else if (u4CpuIdx < u4DmaIdx) + u4RxPktCnt = u4DmaIdx - u4CpuIdx - 1; + else + u4RxPktCnt = u4MaxCnt - 1; + + return u4RxPktCnt; +} + +enum ENUM_CMD_TX_RESULT halWpdmaWriteCmd(IN struct GLUE_INFO *prGlueInfo, + IN struct CMD_INFO *prCmdInfo, IN uint8_t ucTC) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct HIF_MEM_OPS *prMemOps; + struct RTMP_TX_RING *prTxRing; + struct RTMP_DMACB *pTxCell; + struct TXD_STRUCT *pTxD; + uint16_t u2Port = TX_RING_CMD_IDX_2; + uint32_t u4TotalLen; + void *pucSrc = NULL; +#if (CFG_SUPPORT_CONNAC2X == 1) + struct mt66xx_chip_info *prChipInfo; +#endif /* CFG_SUPPORT_CONNAC2 == 1 */ + + ASSERT(prGlueInfo); + +#if (CFG_SUPPORT_CONNAC2X == 1) + prChipInfo = prGlueInfo->prAdapter->chip_info; + if (prChipInfo->is_support_wacpu) + u2Port = TX_RING_WA_CMD_IDX_4; +#endif /* CFG_SUPPORT_CONNAC2X == 1 */ + + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + prTxRing = &prHifInfo->TxRing[u2Port]; + + u4TotalLen = prCmdInfo->u4TxdLen + prCmdInfo->u4TxpLen; +#if (CFG_SUPPORT_CONNAC2X == 1) + if (u4TotalLen > prChipInfo->cmd_max_pkt_size) { + DBGLOG(HAL, ERROR, + "type: %u, cid: 0x%x, seq: %u, txd: %u, txp: %u\n", + prCmdInfo->eCmdType, + prCmdInfo->ucCID, + prCmdInfo->ucCmdSeqNum, + prCmdInfo->u4TxdLen, + prCmdInfo->u4TxpLen); + if (prCmdInfo->u4TxdLen) + DBGLOG_MEM32(HAL, ERROR, prCmdInfo->pucTxd, + prCmdInfo->u4TxdLen); + if (prCmdInfo->u4TxpLen) + DBGLOG_MEM32(HAL, ERROR, prCmdInfo->pucTxp, + prCmdInfo->u4TxpLen); + return FALSE; + } +#endif /* CFG_SUPPORT_CONNAC2X == 1 */ + if (prMemOps->allocRuntimeMem) + pucSrc = prMemOps->allocRuntimeMem(u4TotalLen); + + kalDevRegRead(prGlueInfo, prTxRing->hw_cidx_addr, &prTxRing->TxCpuIdx); + if (prTxRing->TxCpuIdx >= TX_RING_SIZE) { + DBGLOG(HAL, ERROR, "Error TxCpuIdx[%u]\n", prTxRing->TxCpuIdx); + if (prMemOps->freeBuf) + prMemOps->freeBuf(pucSrc, u4TotalLen); + return CMD_TX_RESULT_FAILED; + } + + pTxCell = &prTxRing->Cell[prTxRing->TxCpuIdx]; + pTxD = (struct TXD_STRUCT *)pTxCell->AllocVa; + pTxCell->pPacket = (void *)prCmdInfo; + pTxCell->pBuffer = pucSrc; + + if (prMemOps->copyCmd && + !prMemOps->copyCmd(prHifInfo, pTxCell, pucSrc, + prCmdInfo->pucTxd, prCmdInfo->u4TxdLen, + prCmdInfo->pucTxp, prCmdInfo->u4TxpLen)) { + if (prMemOps->freeBuf) + prMemOps->freeBuf(pucSrc, u4TotalLen); + ASSERT(0); + return CMD_TX_RESULT_FAILED; + } + + pTxD->SDPtr0 = (uint64_t)pTxCell->PacketPa & DMA_LOWER_32BITS_MASK; +#ifdef CONFIG_PHYS_ADDR_T_64BIT + pTxD->SDPtr0Ext = ((uint64_t)pTxCell->PacketPa >> DMA_BITS_OFFSET) & + DMA_HIGHER_4BITS_MASK; +#else + pTxD->SDPtr0Ext = 0; +#endif + pTxD->SDLen0 = u4TotalLen; + pTxD->SDPtr1 = 0; + pTxD->SDLen1 = 0; + pTxD->LastSec0 = 1; + pTxD->LastSec1 = 0; + pTxD->Burst = 0; + pTxD->DMADONE = 0; + + /* Increase TX_CTX_IDX, but write to register later. */ + INC_RING_INDEX(prTxRing->TxCpuIdx, TX_RING_SIZE); + + prTxRing->u4UsedCnt++; + kalDevRegWrite(prGlueInfo, prTxRing->hw_cidx_addr, prTxRing->TxCpuIdx); + + GLUE_INC_REF_CNT(prGlueInfo->prAdapter->rHifStats.u4CmdTxCount); + + DBGLOG(HAL, TRACE, + "%s: CmdInfo[0x%p], TxD[0x%p/%u] TxP[0x%p/%u] CPU idx[%u] Used[%u]\n", + __func__, prCmdInfo, prCmdInfo->pucTxd, prCmdInfo->u4TxdLen, + prCmdInfo->pucTxp, prCmdInfo->u4TxpLen, + prTxRing->TxCpuIdx, prTxRing->u4UsedCnt); + DBGLOG_MEM32(HAL, TRACE, prCmdInfo->pucTxd, prCmdInfo->u4TxdLen); + + if (u2Port == TX_RING_CMD_IDX_2 +#if (CFG_SUPPORT_CONNAC2X == 1) + || u2Port == TX_RING_WA_CMD_IDX_4 +#endif /* CFG_SUPPORT_CONNAC2 == 1 */ + ) + nicTxReleaseResource_PSE(prGlueInfo->prAdapter, + TC4_INDEX, + nicTxGetPageCount(prGlueInfo->prAdapter, + pTxD->SDLen0, + TRUE), + TRUE); + + return CMD_TX_RESULT_SUCCESS; +} + +static bool halWpdmaFillTxRing(struct GLUE_INFO *prGlueInfo, + struct MSDU_TOKEN_ENTRY *prToken) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct mt66xx_chip_info *prChipInfo; + struct RTMP_TX_RING *prTxRing; + struct RTMP_DMACB *pTxCell; + struct TXD_STRUCT *pTxD; + uint16_t u2Port = TX_RING_DATA0_IDX_0; + + ASSERT(prGlueInfo); + + prHifInfo = &prGlueInfo->rHifInfo; + prChipInfo = prGlueInfo->prAdapter->chip_info; + + u2Port = halTxRingDataSelect( + prGlueInfo->prAdapter, prToken->prMsduInfo); + prTxRing = &prHifInfo->TxRing[u2Port]; + + kalDevRegRead(prGlueInfo, prTxRing->hw_cidx_addr, &prTxRing->TxCpuIdx); + if (prTxRing->TxCpuIdx >= TX_RING_SIZE) { + DBGLOG(HAL, ERROR, "Error TxCpuIdx[%u]\n", prTxRing->TxCpuIdx); + halReturnMsduToken(prGlueInfo->prAdapter, prToken->u4Token); + return FALSE; + } + + pTxCell = &prTxRing->Cell[prTxRing->TxCpuIdx]; + prToken->u4CpuIdx = prTxRing->TxCpuIdx; + prToken->u2Port = u2Port; + pTxCell->prToken = prToken; + + pTxD = (struct TXD_STRUCT *)pTxCell->AllocVa; + pTxD->SDPtr0 = (uint64_t)prToken->rDmaAddr & DMA_LOWER_32BITS_MASK; +#ifdef CONFIG_PHYS_ADDR_T_64BIT + pTxD->SDPtr0Ext = ((uint64_t)prToken->rDmaAddr >> DMA_BITS_OFFSET) & + DMA_HIGHER_4BITS_MASK; +#else + pTxD->SDPtr0Ext = 0; +#endif + pTxD->SDLen0 = NIC_TX_DESC_AND_PADDING_LENGTH + + prChipInfo->txd_append_size; + if (prChipInfo->is_support_cr4) + pTxD->SDLen0 += HIF_TX_PAYLOAD_LENGTH; + pTxD->SDPtr1 = 0; + pTxD->SDLen1 = 0; + pTxD->LastSec0 = 1; + pTxD->LastSec1 = 0; + pTxD->Burst = 0; + pTxD->DMADONE = 0; + + /* Increase TX_CTX_IDX, but write to register later. */ + INC_RING_INDEX(prTxRing->TxCpuIdx, TX_RING_SIZE); + + /* Update HW Tx DMA ring */ + prTxRing->u4UsedCnt++; + kalDevRegWrite(prGlueInfo, prTxRing->hw_cidx_addr, prTxRing->TxCpuIdx); + + DBGLOG_LIMITED(HAL, TRACE, + "Tx Data:Ring%d CPU idx[0x%x] Used[%u]\n", + u2Port, prTxRing->TxCpuIdx, prTxRing->u4UsedCnt); + + GLUE_INC_REF_CNT(prGlueInfo->prAdapter->rHifStats.u4DataTxCount); + + return TRUE; +} + +static bool halFlushToken(struct GLUE_INFO *prGlueInfo, + struct MSDU_TOKEN_ENTRY *prToken) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct HIF_MEM_OPS *prMemOps; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + + if (prMemOps->mapTxBuf) { + prToken->rDmaAddr = prMemOps->mapTxBuf( + prHifInfo, prToken->prPacket, 0, prToken->u4DmaLength); + if (!prToken->rDmaAddr) + return false; + } + + return true; +} + +static bool halWpdmaWriteData(struct GLUE_INFO *prGlueInfo, + struct MSDU_INFO *prMsduInfo, + struct MSDU_TOKEN_ENTRY *prFillToken, + struct MSDU_TOKEN_ENTRY *prToken, + uint32_t u4Idx, uint32_t u4Num) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct mt66xx_chip_info *prChipInfo; + bool fgIsLast = (u4Idx + 1) == u4Num; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + prChipInfo = prGlueInfo->prAdapter->chip_info; + + /* Update Tx descriptor */ + halTxUpdateCutThroughDesc(prGlueInfo, prMsduInfo, prFillToken, + prToken, u4Idx, fgIsLast); + + /* Update token exclude FillToken */ + if (prToken != prFillToken) { + if (!halFlushToken(prGlueInfo, prToken)) + return false; + } + + /* Update FillToken */ + if (fgIsLast) { + if (!halFlushToken(prGlueInfo, prFillToken)) + return false; + halWpdmaFillTxRing(prGlueInfo, prFillToken); + } + + return true; +} + +void halWpdamFreeMsdu(struct GLUE_INFO *prGlueInfo, + struct MSDU_INFO *prMsduInfo, + bool fgSetEvent) +{ + DBGLOG(HAL, LOUD, "Tx Data: Msdu[0x%p], TokFree[%u] TxDone[%u]\n", + prMsduInfo, halGetMsduTokenFreeCnt(prGlueInfo->prAdapter), + (prMsduInfo->pfTxDoneHandler ? TRUE : FALSE)); + + nicTxReleaseResource_PSE(prGlueInfo->prAdapter, prMsduInfo->ucTC, + nicTxGetPageCount(prGlueInfo->prAdapter, + prMsduInfo->u2FrameLength, TRUE), TRUE); + +#if HIF_TX_PREALLOC_DATA_BUFFER + if (!prMsduInfo->pfTxDoneHandler) { + nicTxFreePacket(prGlueInfo->prAdapter, prMsduInfo, FALSE); + nicTxReturnMsduInfo(prGlueInfo->prAdapter, prMsduInfo); + } +#endif + + if (fgSetEvent && wlanGetTxPendingFrameCount(prGlueInfo->prAdapter)) + kalSetEvent(prGlueInfo); +} + +bool halWpdmaWriteMsdu(struct GLUE_INFO *prGlueInfo, + struct MSDU_INFO *prMsduInfo, + struct list_head *prCurList) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct HIF_MEM_OPS *prMemOps; + struct MSDU_TOKEN_ENTRY *prToken = NULL; + struct sk_buff *prSkb; + uint8_t *pucSrc; + uint32_t u4TotalLen; + + uint32_t u4TxDescAppendSize; + + ASSERT(prGlueInfo); + ASSERT(prMsduInfo); + + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + prSkb = (struct sk_buff *)prMsduInfo->prPacket; + + if (prSkb == NULL || prSkb->data == NULL) { + DBGLOG(HAL, ERROR, "prSkb is 0x%p\n", prSkb); + + if (prCurList) { + list_del(prCurList); + prHifInfo->u4TxDataQLen--; + } + halWpdamFreeMsdu(prGlueInfo, prMsduInfo, true); + + return false; + } + + pucSrc = prSkb->data; + + u4TotalLen = prSkb->len; + + if (prGlueInfo->prAdapter != NULL && + prGlueInfo->prAdapter->chip_info != NULL) { + + u4TxDescAppendSize = + prGlueInfo->prAdapter->chip_info->txd_append_size; + } else { + DBGLOG(HAL, ERROR, "prGlueInfo->prAdapter is null\n"); + + if (prCurList) { + list_del(prCurList); + prHifInfo->u4TxDataQLen--; + } + halWpdamFreeMsdu(prGlueInfo, prMsduInfo, true); + + return false; + } + + if (u4TotalLen <= (AXI_TX_MAX_SIZE_PER_FRAME + u4TxDescAppendSize)) { + + /* Acquire MSDU token */ + prToken = halAcquireMsduToken(prGlueInfo->prAdapter); + if (!prToken) { + DBGLOG(HAL, ERROR, "Write MSDU acquire token fail\n"); + return false; + } + + /* Use MsduInfo to select TxRing */ + prToken->prMsduInfo = prMsduInfo; + +#if HIF_TX_PREALLOC_DATA_BUFFER + if (prMemOps->copyTxData) + prMemOps->copyTxData(prToken, pucSrc, u4TotalLen); +#else + prToken->prPacket = pucSrc; + prToken->u4DmaLength = u4TotalLen; + prMsduInfo->prToken = prToken; +#endif + + if (!halWpdmaWriteData(prGlueInfo, prMsduInfo, prToken, + prToken, 0, 1)) { + halReturnMsduToken(prGlueInfo->prAdapter, + prToken->u4Token); + return false; + } + + } else { + DBGLOG(HAL, ERROR, "u4Len=%u, 0x%p, txd_append_size=%d\n", + u4TotalLen, prSkb, + prGlueInfo->prAdapter->chip_info->txd_append_size); + + DBGLOG(HAL, ERROR, "%u,%u,%u,%u,%u,%u,%u,%u\n", + prMsduInfo->eSrc, prMsduInfo->ucUserPriority, + prMsduInfo->ucTC, prMsduInfo->ucPacketType, + prMsduInfo->ucStaRecIndex, prMsduInfo->ucBssIndex, + prMsduInfo->ucWlanIndex, prMsduInfo->ucPacketFormat); + } + + if (prCurList) { + list_del(prCurList); + prHifInfo->u4TxDataQLen--; + } + if (prMsduInfo->pfHifTxMsduDoneCb) + prMsduInfo->pfHifTxMsduDoneCb(prGlueInfo->prAdapter, + prMsduInfo); + halWpdamFreeMsdu(prGlueInfo, prMsduInfo, true); + + return true; +} + +bool halWpdmaWriteAmsdu(struct GLUE_INFO *prGlueInfo, + struct list_head *prList, + uint32_t u4Num, uint16_t u2Size) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct HIF_MEM_OPS *prMemOps; + struct list_head *prCur, *prNext; + struct TX_DATA_REQ *prTxReq; + struct MSDU_TOKEN_ENTRY *prFillToken = NULL, *prToken = NULL; + struct MSDU_INFO *prMsduInfo; + struct AMSDU_MAC_TX_DESC *prTxD = NULL; + struct sk_buff *prSkb; + uint8_t *pucSrc; + uint32_t u4TotalLen, u4Idx, u4FreeToken, u4FreeRing; + uint16_t u2Port; + bool fgIsLast; + + ASSERT(prGlueInfo); + + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + u4FreeToken = halGetMsduTokenFreeCnt(prGlueInfo->prAdapter); + + /* Peek head to select TxRing */ + prTxReq = list_entry(prList, struct TX_DATA_REQ, list); + u2Port = halTxRingDataSelect( + prGlueInfo->prAdapter, prTxReq->prMsduInfo); + u4FreeRing = TX_RING_SIZE - prHifInfo->TxRing[u2Port].u4UsedCnt; + + if ((u4FreeToken < u4Num) || (u4FreeRing <= 1)) { + DBGLOG(HAL, WARN, + "Amsdu low tx res acquire[%u], tok[%u], ring%d[%u]\n", + u4Num, u4FreeToken, u2Port, u4FreeRing); + return false; + } + + prCur = prList; + for (u4Idx = 0; u4Idx < u4Num; u4Idx++) { + prTxReq = list_entry(prCur, struct TX_DATA_REQ, list); + prMsduInfo = prTxReq->prMsduInfo; + prSkb = (struct sk_buff *)prMsduInfo->prPacket; + pucSrc = prSkb->data; + u4TotalLen = prSkb->len; + fgIsLast = (u4Idx == u4Num - 1); + + /* Acquire MSDU token */ + prToken = halAcquireMsduToken(prGlueInfo->prAdapter); + if (!prToken) { + DBGLOG(HAL, ERROR, "Write AMSDU acquire token fail\n"); + return false; + } + + /* Use MsduInfo to select TxRing */ + prToken->prMsduInfo = prMsduInfo; +#if HIF_TX_PREALLOC_DATA_BUFFER + if (prMemOps->copyTxData) + prMemOps->copyTxData(prToken, pucSrc, u4TotalLen); +#else + prToken->prPacket = pucSrc; + prToken->u4DmaLength = u4TotalLen; + prMsduInfo->prToken = prToken; +#endif + + if (!prFillToken) { + prFillToken = prToken; + prTxD = (struct AMSDU_MAC_TX_DESC *)prToken->prPacket; + } + + if (fgIsLast) { + prTxD->u2TxByteCount = u2Size; + prTxD->u4DW1 |= TXD_DW1_AMSDU_C; + } + + if (!halWpdmaWriteData(prGlueInfo, prMsduInfo, prFillToken, + prToken, u4Idx, u4Num)) { + halReturnMsduToken(prGlueInfo->prAdapter, + prToken->u4Token); + return false; + } + prCur = prCur->next; + } + + prCur = prList; + for (u4Idx = 0; u4Idx < u4Num; u4Idx++) { + prNext = prCur->next; + prTxReq = list_entry(prCur, struct TX_DATA_REQ, list); + prMsduInfo = prTxReq->prMsduInfo; + + list_del(prCur); + prHifInfo->u4TxDataQLen--; + if (prMsduInfo->pfHifTxMsduDoneCb) + prMsduInfo->pfHifTxMsduDoneCb(prGlueInfo->prAdapter, + prMsduInfo); + halWpdamFreeMsdu(prGlueInfo, prMsduInfo, true); + prCur = prNext; + } + + DBGLOG(HAL, LOUD, "Amsdu num:%d tx byte: %d\n", u4Num, u2Size); + return true; +} + +u_int8_t halIsStaticMapBusAddr(IN struct ADAPTER *prAdapter, + IN uint32_t u4Addr) +{ + if (u4Addr < prAdapter->chip_info->bus_info->max_static_map_addr) + return TRUE; + else + return FALSE; +} + +u_int8_t halChipToStaticMapBusAddr(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4ChipAddr, + OUT uint32_t *pu4BusAddr) +{ + struct BUS_INFO *prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + uint32_t u4StartAddr, u4EndAddr, u4BusAddr; + uint32_t u4Idx = 0; + + if (halIsStaticMapBusAddr(prGlueInfo->prAdapter, u4ChipAddr)) { + *pu4BusAddr = u4ChipAddr; + return TRUE; + } + + while (TRUE) { + u4StartAddr = prBusInfo->bus2chip[u4Idx].u4ChipAddr; + u4EndAddr = prBusInfo->bus2chip[u4Idx].u4ChipAddr + + prBusInfo->bus2chip[u4Idx].u4Range; + + /* End of mapping table */ + if (u4EndAddr == 0x0) + return FALSE; + + if ((u4ChipAddr >= u4StartAddr) && (u4ChipAddr <= u4EndAddr)) { + u4BusAddr = (u4ChipAddr - u4StartAddr) + + prBusInfo->bus2chip[u4Idx].u4BusAddr; + break; + } + + u4Idx++; + } + + *pu4BusAddr = u4BusAddr; + return TRUE; +} + +u_int8_t halGetDynamicMapReg(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4ChipAddr, OUT uint32_t *pu4Value) +{ + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + uint32_t u4ReMapReg, u4BusAddr; + + if (!halChipToStaticMapBusAddr(prGlueInfo, MCU_CFG_PCIE_REMAP2, + &u4ReMapReg)) + return FALSE; + + + RTMP_IO_WRITE32(prHifInfo, u4ReMapReg, u4ChipAddr & PCIE_REMAP2_MASK); + u4BusAddr = PCIE_REMAP2_BUS_ADDR + (u4ChipAddr & ~PCIE_REMAP2_MASK); + RTMP_IO_READ32(prHifInfo, u4BusAddr, pu4Value); + + return TRUE; +} + +u_int8_t halSetDynamicMapReg(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4ChipAddr, IN uint32_t u4Value) +{ + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + uint32_t u4ReMapReg, u4BusAddr; + + if (!halChipToStaticMapBusAddr(prGlueInfo, MCU_CFG_PCIE_REMAP2, + &u4ReMapReg)) + return FALSE; + + RTMP_IO_WRITE32(prHifInfo, u4ReMapReg, u4ChipAddr & PCIE_REMAP2_MASK); + u4BusAddr = PCIE_REMAP2_BUS_ADDR + (u4ChipAddr & ~PCIE_REMAP2_MASK); + RTMP_IO_WRITE32(prHifInfo, u4BusAddr, u4Value); + + return TRUE; +} + +u_int8_t halIsPendingRx(IN struct ADAPTER *prAdapter) +{ + /* TODO: check pending Rx + * if previous Rx handling is break due to lack of SwRfb + */ + return FALSE; +} + +uint32_t halGetValidCoalescingBufSize(IN struct ADAPTER *prAdapter) +{ + uint32_t u4BufSize; + + if (HIF_TX_COALESCING_BUFFER_SIZE > HIF_RX_COALESCING_BUFFER_SIZE) + u4BufSize = HIF_TX_COALESCING_BUFFER_SIZE; + else + u4BufSize = HIF_RX_COALESCING_BUFFER_SIZE; + + return u4BufSize; +} + +uint32_t halAllocateIOBuffer(IN struct ADAPTER *prAdapter) +{ + return WLAN_STATUS_SUCCESS; +} + +uint32_t halReleaseIOBuffer(IN struct ADAPTER *prAdapter) +{ + return WLAN_STATUS_SUCCESS; +} + +void halProcessAbnormalInterrupt(IN struct ADAPTER *prAdapter) +{ + +} + +static void halDefaultProcessSoftwareInterrupt( + IN struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo; + struct GL_HIF_INFO *prHifInfo; + struct ERR_RECOVERY_CTRL_T *prErrRecoveryCtrl; + uint32_t u4Status = 0; + + if (prAdapter->prGlueInfo == NULL) { + DBGLOG(HAL, ERROR, "prGlueInfo is NULL\n"); + return; + } + + prGlueInfo = prAdapter->prGlueInfo; + prHifInfo = &prGlueInfo->rHifInfo; + prErrRecoveryCtrl = &prHifInfo->rErrRecoveryCtl; + + kalDevRegRead(prGlueInfo, MCU2HOST_SW_INT_STA, &u4Status); + prErrRecoveryCtrl->u4BackupStatus = u4Status; + if (u4Status & ERROR_DETECT_MASK) { + prErrRecoveryCtrl->u4Status = u4Status; + kalDevRegWrite(prGlueInfo, MCU2HOST_SW_INT_STA, + ERROR_DETECT_MASK); + halHwRecoveryFromError(prAdapter); + } else + DBGLOG(HAL, ERROR, "undefined SER status[0x%x].\n", u4Status); +} + +void halProcessSoftwareInterrupt(IN struct ADAPTER *prAdapter) +{ + struct BUS_INFO *prBusInfo = NULL; + + if (prAdapter == NULL) { + DBGLOG(HAL, ERROR, "prAdapter is NULL\n"); + return; + } + + prBusInfo = prAdapter->chip_info->bus_info; + + if (prBusInfo->processSoftwareInterrupt) + prBusInfo->processSoftwareInterrupt(prAdapter); + else + halDefaultProcessSoftwareInterrupt(prAdapter); +} +#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE +void halHwRecoveryTimeout(struct timer_list *timer) +#else +void halHwRecoveryTimeout(unsigned long arg) +#endif +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) + struct GL_HIF_INFO *prHif = from_timer(prHif, timer, rSerTimer); + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)prHif->rSerTimerData; +#else + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)arg; +#endif + struct ADAPTER *prAdapter = NULL; + struct GL_HIF_INFO *prHifInfo; + struct ERR_RECOVERY_CTRL_T *prErrRecoveryCtrl; + + ASSERT(prGlueInfo); + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prHifInfo = &prGlueInfo->rHifInfo; + prErrRecoveryCtrl = &prHifInfo->rErrRecoveryCtl; + + DBGLOG(HAL, ERROR, + "SER timer Timeout. ErrState[%d] Status[0x%x] Backup[0x%x]\n", + prErrRecoveryCtrl->eErrRecovState, + prErrRecoveryCtrl->u4Status, + prErrRecoveryCtrl->u4BackupStatus); + +#if CFG_CHIP_RESET_SUPPORT +#if (CFG_SUPPORT_CONNINFRA == 0) + GL_RESET_TRIGGER(prAdapter, RST_FLAG_CHIP_RESET); +#else + kalSetSerTimeoutEvent(prGlueInfo); +#endif +#endif +} + +void halSetDrvSer(struct ADAPTER *prAdapter) +{ + struct BUS_INFO *prBusInfo = NULL; + + ASSERT(prAdapter); + ASSERT(prAdapter->prGlueInfo); + + prBusInfo = prAdapter->chip_info->bus_info; + + DBGLOG(HAL, INFO, "Set Driver Ser\n"); + if (prBusInfo->softwareInterruptMcu) + prBusInfo->softwareInterruptMcu(prAdapter, + MCU_INT_DRIVER_SER); + else + kalDevRegWrite(prAdapter->prGlueInfo, HOST2MCU_SW_INT_SET, + MCU_INT_DRIVER_SER); +} + +static void halStartSerTimer(IN struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo; + struct GL_HIF_INFO *prHifInfo; + + prGlueInfo = prAdapter->prGlueInfo; + prHifInfo = &prGlueInfo->rHifInfo; + mod_timer(&prHifInfo->rSerTimer, + jiffies + HIF_SER_TIMEOUT * HZ / MSEC_PER_SEC); + DBGLOG(HAL, INFO, "Start SER timer\n"); +} + +void halHwRecoveryFromError(IN struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo; + struct mt66xx_chip_info *prChipInfo; + struct GL_HIF_INFO *prHifInfo; + struct BUS_INFO *prBusInfo = NULL; + struct ERR_RECOVERY_CTRL_T *prErrRecoveryCtrl; + uint32_t u4Status = 0; + + prGlueInfo = prAdapter->prGlueInfo; + prHifInfo = &prGlueInfo->rHifInfo; + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + prErrRecoveryCtrl = &prHifInfo->rErrRecoveryCtl; + + u4Status = prErrRecoveryCtrl->u4Status; + prErrRecoveryCtrl->u4Status = 0; + + if (prAdapter->rWifiVar.fgEnableSer == FALSE) + return; + + switch (prErrRecoveryCtrl->eErrRecovState) { + case ERR_RECOV_STOP_IDLE: + if (u4Status & ERROR_DETECT_STOP_PDMA) { + prChipInfo = prAdapter->chip_info; + if (prChipInfo->asicDumpSerDummyCR) + prChipInfo->asicDumpSerDummyCR(prAdapter); + halStartSerTimer(prAdapter); + DBGLOG(HAL, INFO, + "SER(E) Host stop PDMA tx/rx ring operation & receive\n"); + nicSerStopTxRx(prAdapter); +#if (CFG_SUPPORT_CONNAC2X == 1) + /*get WFDMA HW data before Layer 1 SER*/ + /*event*/ + halRxReceiveRFBs(prAdapter, WFDMA1_RX_RING_IDX_0, + FALSE); +#endif +#if CFG_SUPPORT_MULTITHREAD + kalSetRxProcessEvent(prAdapter->prGlueInfo); + DBGLOG(HAL, INFO, + "SER(F) kalSetRxProcessEvent\n"); +#else + DBGLOG(HAL, INFO, + "SER(F) nicRxProcessRFBs\n"); + nicRxProcessRFBs(prAdapter); +#endif + + DBGLOG(HAL, INFO, + "SER(F) Host ACK PDMA tx/rx ring stop operation\n"); + + if (prBusInfo->softwareInterruptMcu) { + prBusInfo->softwareInterruptMcu(prAdapter, + MCU_INT_PDMA0_STOP_DONE); + } else { + kalDevRegWrite(prGlueInfo, HOST2MCU_SW_INT_SET, + MCU_INT_PDMA0_STOP_DONE); + } + + /* re-call for change status to stop dma0 */ + prErrRecoveryCtrl->eErrRecovState = + ERR_RECOV_STOP_PDMA0; + } else { + DBGLOG(HAL, ERROR, "SER CurStat=%u Event=%x\n", + prErrRecoveryCtrl->eErrRecovState, u4Status); + } + break; + + case ERR_RECOV_STOP_PDMA0: + if (u4Status & ERROR_DETECT_RESET_DONE) { + DBGLOG(HAL, INFO, "SER(L) Host re-initialize PDMA\n"); + /* only reset TXD & RXD */ + halWpdmaAllocRing(prAdapter->prGlueInfo, false); + nicFreePendingTxMsduInfo(prAdapter, 0xFF, + MSDU_REMOVE_BY_ALL); + wlanClearPendingCommandQueue(prAdapter); + halResetMsduToken(prAdapter); + prAdapter->u4NoMoreRfb = 0; + + DBGLOG(HAL, INFO, "SER(M) Host enable PDMA\n"); + halWpdmaInitRing(prGlueInfo, false); + + /* reset SW value after InitRing */ + prChipInfo = prAdapter->chip_info; + if (prChipInfo->asicWfdmaReInit) + prChipInfo->asicWfdmaReInit(prAdapter); + + DBGLOG(HAL, INFO, + "SER(N) Host interrupt MCU PDMA ring init done\n"); + prErrRecoveryCtrl->eErrRecovState = + ERR_RECOV_RESET_PDMA0; + if (prBusInfo->softwareInterruptMcu) { + prBusInfo->softwareInterruptMcu(prAdapter, + MCU_INT_PDMA0_INIT_DONE); + } else { + kalDevRegWrite(prGlueInfo, HOST2MCU_SW_INT_SET, + MCU_INT_PDMA0_INIT_DONE); + } + } else { + DBGLOG(HAL, ERROR, "SER CurStat=%u Event=%x\n", + prErrRecoveryCtrl->eErrRecovState, u4Status); + } + break; + + case ERR_RECOV_RESET_PDMA0: + if (u4Status & ERROR_DETECT_RECOVERY_DONE) { + DBGLOG(HAL, INFO, + "SER(Q) Host interrupt MCU SER handle done\n"); + prErrRecoveryCtrl->eErrRecovState = + ERR_RECOV_WAIT_MCU_NORMAL; + if (prBusInfo->softwareInterruptMcu) { + prBusInfo->softwareInterruptMcu(prAdapter, + MCU_INT_PDMA0_RECOVERY_DONE); + } else { + kalDevRegWrite(prGlueInfo, HOST2MCU_SW_INT_SET, + MCU_INT_PDMA0_RECOVERY_DONE); + } + } else { + DBGLOG(HAL, ERROR, "SER CurStat=%u Event=%x\n", + prErrRecoveryCtrl->eErrRecovState, u4Status); + } + break; + + case ERR_RECOV_WAIT_MCU_NORMAL: + if (u4Status & ERROR_DETECT_MCU_NORMAL_STATE) { + del_timer_sync(&prHifInfo->rSerTimer); + + /* update Beacon frame if operating in AP mode. */ + DBGLOG(HAL, INFO, "SER(T) Host re-initialize BCN\n"); + nicSerReInitBeaconFrame(prAdapter); + + kalDevKickCmd(prAdapter->prGlueInfo); + kalDevKickData(prAdapter->prGlueInfo); + halRxReceiveRFBs(prAdapter, RX_RING_EVT_IDX_1, FALSE); + halRxReceiveRFBs(prAdapter, RX_RING_DATA_IDX_0, TRUE); + nicSerStartTxRx(prAdapter); +#if CFG_SUPPORT_MULTITHREAD + kalSetTxEvent2Hif(prAdapter->prGlueInfo); +#endif + prErrRecoveryCtrl->eErrRecovState = ERR_RECOV_STOP_IDLE; + } else { + DBGLOG(HAL, ERROR, "SER CurStat=%u Event=%x\n", + prErrRecoveryCtrl->eErrRecovState, u4Status); + } + break; + + default: + DBGLOG(HAL, ERROR, "SER CurStat=%u Event=%x!!!\n", + prErrRecoveryCtrl->eErrRecovState, u4Status); + break; + } +} + +void halDeAggRxPktWorker(struct work_struct *work) +{ + +} + +void halRxTasklet(unsigned long data) +{ + +} + +void halTxCompleteTasklet(unsigned long data) +{ + +} + +/* Hif power off wifi */ +uint32_t halHifPowerOffWifi(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct BUS_INFO *prBusInfo = NULL; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + prBusInfo = prAdapter->chip_info->bus_info; + + DBGLOG(INIT, INFO, "Power off Wi-Fi!\n"); + + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + +#if defined(_HIF_AXI) + if (nicProcessISTWithSpecifiedCount(prAdapter, 5) != + WLAN_STATUS_NOT_INDICATING) + DBGLOG(INIT, INFO, + "Handle pending interrupt\n"); +#endif + /* Power off Wi-Fi */ + wlanSendNicPowerCtrlCmd(prAdapter, TRUE); + + prHifInfo->fgIsPowerOff = true; + + /* prAdapter->fgWiFiInSleepyState = TRUE; */ + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + + rStatus = wlanCheckWifiFunc(prAdapter, FALSE); + + if (prBusInfo->setPdmaIntMask) + prBusInfo->setPdmaIntMask(prAdapter->prGlueInfo, FALSE); + nicDisableInterrupt(prAdapter); + + return rStatus; +} + +u_int8_t halIsTxResourceControlEn(IN struct ADAPTER *prAdapter) +{ + return FALSE; +} + +void halTxResourceResetHwTQCounter(IN struct ADAPTER *prAdapter) +{ +} + +uint32_t halGetHifTxPageSize(IN struct ADAPTER *prAdapter) +{ + return HIF_TX_PAGE_SIZE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Check if HIF state is READY for upper layer cfg80211 +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (TRUE: ready, FALSE: not ready) +*/ +/*----------------------------------------------------------------------------*/ +bool halIsHifStateReady(IN struct ADAPTER *prAdapter, uint8_t *pucState) +{ + /* PCIE owner should implement this function */ + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Check if HIF state is during supend process +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (TRUE: suspend, reject the caller action. FALSE: not suspend) +*/ +/*----------------------------------------------------------------------------*/ +bool halIsHifStateSuspend(IN struct ADAPTER *prAdapter) +{ + /* PCIE owner should implement this function */ + + return FALSE; +} + +void halUpdateTxMaxQuota(IN struct ADAPTER *prAdapter) +{ + struct BUS_INFO *prBusInfo; + uint32_t u4Ret; + uint32_t u4Quota; + uint16_t u2PortIdx; + bool fgRun; + uint8_t ucWmmIndex; + + KAL_SPIN_LOCK_DECLARATION(); + + prBusInfo = prAdapter->chip_info->bus_info; + + for (ucWmmIndex = 0; ucWmmIndex < prAdapter->ucWmmSetNum; + ucWmmIndex++) { + + u4Ret = WLAN_STATUS_SUCCESS; + u2PortIdx = halRingDataSelectByWmmIndex(prAdapter, ucWmmIndex); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_UPDATE_WMM_QUOTA); + u4Quota = prAdapter->rWmmQuotaReqCS[ucWmmIndex].u4Quota; + fgRun = prAdapter->rWmmQuotaReqCS[ucWmmIndex].fgRun; + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_UPDATE_WMM_QUOTA); + + if (fgRun) { + if (prBusInfo->updateTxRingMaxQuota) { + u4Ret = prBusInfo->updateTxRingMaxQuota( + prAdapter, u2PortIdx, u4Quota); + } else { + DBGLOG(HAL, INFO, + "updateTxRingMaxQuota not implemented\n"); + u4Ret = WLAN_STATUS_NOT_ACCEPTED; + } + } + + DBGLOG(HAL, INFO, + "WmmQuota,Run,%u,Wmm,%u,Port,%u,Quota,0x%x,ret=0x%x\n", + fgRun, ucWmmIndex, u2PortIdx, u4Quota, u4Ret); + + if (u4Ret != WLAN_STATUS_PENDING) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, + SPIN_LOCK_UPDATE_WMM_QUOTA); + prAdapter->rWmmQuotaReqCS[ucWmmIndex].fgRun + = false; + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_UPDATE_WMM_QUOTA); + } + } +} + +void halEnableSlpProt(struct GLUE_INFO *prGlueInfo) +{ + uint32_t u4Val = 0; + uint32_t u4WaitDelay = 20000; + + kalDevRegRead(prGlueInfo, CONN_HIF_PDMA_CSR_PDMA_SLP_PROT_ADDR, &u4Val); + u4Val |= CONN_HIF_PDMA_CSR_PDMA_SLP_PROT_PDMA_AXI_SLPPROT_ENABLE_MASK; + kalDevRegWrite(prGlueInfo, CONN_HIF_PDMA_CSR_PDMA_SLP_PROT_ADDR, u4Val); + while (TRUE) { + u4WaitDelay--; + kalDevRegRead(prGlueInfo, CONN_HIF_PDMA_CSR_PDMA_SLP_PROT_ADDR, + &u4Val); + if (CONN_HIF_PDMA_CSR_PDMA_SLP_PROT_PDMA_AXI_SLPPROT_RDY_MASK & + u4Val) + break; + if (u4WaitDelay == 0) { + DBGLOG(HAL, ERROR, "wait for sleep protect timeout.\n"); + GL_RESET_TRIGGER(prGlueInfo->prAdapter, + RST_FLAG_CHIP_RESET); + break; + } + kalUdelay(1); + } +} + +void halDisableSlpProt(struct GLUE_INFO *prGlueInfo) +{ + uint32_t u4Val = 0; + + kalDevRegRead(prGlueInfo, CONN_HIF_PDMA_CSR_PDMA_SLP_PROT_ADDR, &u4Val); + u4Val &= ~CONN_HIF_PDMA_CSR_PDMA_SLP_PROT_PDMA_AXI_SLPPROT_ENABLE_MASK; + kalDevRegWrite(prGlueInfo, CONN_HIF_PDMA_CSR_PDMA_SLP_PROT_ADDR, u4Val); +} + + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/common/include/hif_pdma.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/common/include/hif_pdma.h new file mode 100644 index 0000000000000..1ddfc7161fcc7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/common/include/hif_pdma.h @@ -0,0 +1,504 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + Module Name: + hif_pdma.h + */ + +#ifndef __HIF_PDMA_H__ +#define __HIF_PDMA_H__ + +#include + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define NUM_OF_WFDMA1_TX_RING 0 +#define NUM_OF_WFDMA1_RX_RING 0 + +#if (CFG_SUPPORT_CONNAC2X == 1) +#undef NUM_OF_WFDMA1_TX_RING +#define NUM_OF_WFDMA1_TX_RING (CONFIG_NUM_OF_WFDMA_TX_RING) +#undef NUM_OF_WFDMA1_RX_RING +#define NUM_OF_WFDMA1_RX_RING (CONFIG_NUM_OF_WFDMA_RX_RING) +#endif /* CFG_SUPPORT_CONNAC2X == 1 */ + +#define NUM_OF_TX_RING (4+NUM_OF_WFDMA1_TX_RING) +#define NUM_OF_RX_RING (2+NUM_OF_WFDMA1_RX_RING) + +#if (CFG_SUPPORT_CONNAC2X_2x2 == 1) +#define TX_RING_SIZE 1024 +#define RX_RING_SIZE 1024 /* Max Rx ring size */ +/* Data Rx ring */ +#define RX_RING0_SIZE 1024 +/* Event/MSDU_report Rx ring */ +#define RX_RING1_SIZE 16 +#else +#ifdef CONNAC2X2 +#define TX_RING_SIZE 512 +#define RX_RING_SIZE 512 /* Max Rx ring size */ +/* Data Rx ring */ +#define RX_RING0_SIZE 512 +#else +#define TX_RING_SIZE 256 +#define RX_RING_SIZE 256 /* Max Rx ring size */ +/* Data Rx ring */ +#define RX_RING0_SIZE 256 +#endif /* CONNAC2X2 */ +/* Event/MSDU_report Rx ring */ +#define RX_RING1_SIZE 16 +#endif + +/* TXD_SIZE = TxD + TxInfo */ +#define TXD_SIZE 16 +#define RXD_SIZE 16 + +#define RX_BUFFER_AGGRESIZE 3840 +#define RX_BUFFER_NORMSIZE 3840 +#define TX_BUFFER_NORMSIZE 3840 + +#define HIF_TX_PREALLOC_DATA_BUFFER 1 + +#define HIF_NUM_OF_QM_RX_PKT_NUM 2048 +#define HIF_IST_LOOP_COUNT 32 +/* Min msdu count to trigger Tx during INT polling state */ +#define HIF_IST_TX_THRESHOLD 1 + +#define HIF_TX_BUFF_COUNT_TC0 4096 +#define HIF_TX_BUFF_COUNT_TC1 4096 +#define HIF_TX_BUFF_COUNT_TC2 4096 +#define HIF_TX_BUFF_COUNT_TC3 4096 +#define HIF_TX_BUFF_COUNT_TC4 (TX_RING_SIZE - 1) +#define HIF_TX_BUFF_COUNT_TC5 4096 + +/* enable/disable TX resource control */ +#define HIF_TX_RESOURCE_CTRL 1 +/* enable/disable TX resource control PLE */ +#define HIF_TX_RESOURCE_CTRL_PLE 0 + + +#define HIF_TX_PAGE_SIZE_IN_POWER_OF_2 11 +/* in unit of bytes */ +#define HIF_TX_PAGE_SIZE 2048 + +#define HIF_EXTRA_IO_BUFFER_SIZE 0 + +#define HIF_TX_COALESCING_BUFFER_SIZE (TX_BUFFER_NORMSIZE) +#define HIF_RX_COALESCING_BUFFER_SIZE (RX_BUFFER_AGGRESIZE) + +#define HIF_CR4_FWDL_SECTION_NUM 1 +#define HIF_IMG_DL_STATUS_PORT_IDX 1 + +#define HIF_TX_INIT_CMD_PORT TX_RING_FWDL_IDX_3 + +#ifdef CONNAC2X2 +#define HIF_TX_MSDU_TOKEN_NUM (TX_RING_SIZE * 3) +#else +#define HIF_TX_MSDU_TOKEN_NUM (TX_RING_SIZE * 2) +#endif + +#define HIF_TX_PAYLOAD_LENGTH 72 + +#define HIF_MSDU_REPORT_RETURN_TIMEOUT 10 /* sec */ +#define HIF_SER_TIMEOUT 10000 /* msec */ + +#define MT_RINGREG_DIFF 0x10 +#define MT_RINGREG_EXT_DIFF 0x04 + +#define MT_TX_RING_BASE WPDMA_TX_RING0_CTRL0 +#define MT_TX_RING_PTR WPDMA_TX_RING0_CTRL0 +#define MT_TX_RING_CNT WPDMA_TX_RING0_CTRL1 +#define MT_TX_RING_CIDX WPDMA_TX_RING0_CTRL2 +#define MT_TX_RING_DIDX WPDMA_TX_RING0_CTRL3 + +#define MT_RX_RING_BASE WPDMA_RX_RING0_CTRL0 +#define MT_RX_RING_PTR WPDMA_RX_RING0_CTRL0 +#define MT_RX_RING_CNT WPDMA_RX_RING0_CTRL1 +#define MT_RX_RING_CIDX WPDMA_RX_RING0_CTRL2 +#define MT_RX_RING_DIDX WPDMA_RX_RING0_CTRL3 + +#define DMA_LOWER_32BITS_MASK 0x00000000FFFFFFFF +#define DMA_HIGHER_4BITS_MASK 0x0000000F +#define DMA_BITS_OFFSET 32 + +#define DMA_DONE_WAITING_TIME 10 +#define DMA_DONE_WAITING_COUNT 100 + +#define MT_TX_RING_BASE_EXT WPDMA_TX_RING0_BASE_PTR_EXT +#define MT_RX_RING_BASE_EXT WPDMA_RX_RING0_BASE_PTR_EXT + +#define PDMA_DUMMY_RESET_VALUE 0x0F +#define PDMA_DUMMY_MAGIC_NUM 0x13 + +#define TXD_DW1_RMVL BIT(10) +#define TXD_DW1_VLAN BIT(11) +#define TXD_DW1_ETYP BIT(12) +#define TXD_DW1_AMSDU_C BIT(20) + +#define HIF_DEADFEED_VALUE 0xdeadfeed + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +#define INC_RING_INDEX(_idx, _RingSize) \ +{ \ + (_idx) = (_idx+1) % (_RingSize); \ +} + +#define RTMP_IO_READ32(_A, _R, _pV) \ +{ \ + (*(_pV) = readl((void *)((_A)->CSRBaseAddress + (_R)))); \ +} + +#define RTMP_IO_WRITE32(_A, _R, _V) \ +{ \ + writel(_V, (void *)((_A)->CSRBaseAddress + (_R))); \ +} + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +enum ENUM_TX_RING_IDX { + TX_RING_DATA0_IDX_0 = 0, + TX_RING_DATA1_IDX_1, + TX_RING_CMD_IDX_2, + TX_RING_FWDL_IDX_3, + TX_RING_WA_CMD_IDX_4, +}; + +enum ENUM_RX_RING_IDX { + RX_RING_DATA_IDX_0 = 0, /*Rx Data */ + RX_RING_EVT_IDX_1, + WFDMA0_RX_RING_IDX_2, /* Band0 TxFreeDoneEvent */ + WFDMA0_RX_RING_IDX_3, /* Band1 TxFreeDoneEvent */ + WFDMA1_RX_RING_IDX_0, /* WM Event */ + WFDMA1_RX_RING_IDX_1, /*WA Band 0 Event*/ + WFDMA1_RX_RING_IDX_2, /*WA Band 1 Event*/ +}; + +/* ============================================================================ + * PCI/RBUS TX / RX Frame Descriptors format + * + * Memory Layout + * + * 1. Tx Descriptor + * TxD (12 bytes) + TXINFO (4 bytes) + * 2. Packet Buffer + * TXWI + 802.11 + * 31 0 + * +--------------------------------------------------------------------------+ + * | SDP0[31:0] | + * +-+--+---------------------+-+--+------------------------------------------+ + * |D |L0| SDL0[13:0] |B|L1| SDL1[13:0] | + * +-+--+---------------------+-+--+------------------------------------------+ + * | SDP1[31:0] | + * +--------------------------------------------------------------------------+ + * | TX / RX INFO | + * +--------------------------------------------------------------------------+ + * ========================================================================= + */ +/* + * TX descriptor format for Tx Data/Mgmt Rings + */ +struct TXD_STRUCT { + /* Word 0 */ + uint32_t SDPtr0; + + /* Word 1 */ + uint32_t SDLen1:14; + uint32_t LastSec1:1; + uint32_t Burst:1; + uint32_t SDLen0:14; + uint32_t LastSec0:1; + uint32_t DMADONE:1; + + /*Word2 */ + uint32_t SDPtr1; + + /*Word3 */ + uint16_t SDPtr0Ext; + uint16_t SDPtr1Ext; +}; + +/* + * Rx descriptor format for Rx Rings + */ +struct RXD_STRUCT { + /* Word 0 */ + uint32_t SDPtr0; + + /* Word 1 */ + uint32_t SDLen1:14; + uint32_t LastSec1:1; + uint32_t Burst:1; + uint32_t SDLen0:14; + uint32_t LastSec0:1; + uint32_t DMADONE:1; + + /* Word 2 */ + uint32_t SDPtr1; + + /* Word 3 */ + uint32_t RXINFO; +}; + +/* + * Data buffer for DMA operation, the buffer must be contiguous + * physical memory Both DMA to / from CPU use the same structure. + */ +struct RTMP_DMABUF { + unsigned long AllocSize; + void *AllocVa; /* TxBuf virtual address */ + phys_addr_t AllocPa; /* TxBuf physical address */ +}; + +/* + * Control block (Descriptor) for all ring descriptor DMA operation, + * buffer must be contiguous physical memory. NDIS_PACKET stored the + * binding Rx packet descriptor which won't be released, driver has to + * wait until upper layer return the packet before giveing up this rx + * ring descriptor to ASIC. NDIS_BUFFER is assocaited pair to describe + * the packet buffer. For Tx, NDIS_PACKET stored the tx packet descriptor + * which driver should ACK upper layer when the tx is physically done or + * failed. + */ +struct RTMP_DMACB { + unsigned long AllocSize; /* Control block size */ + void *AllocVa; /* Control block virtual address */ + phys_addr_t AllocPa; /* Control block physical address */ + void *pPacket; + void *pBuffer; + phys_addr_t PacketPa; + struct RTMP_DMABUF DmaBuf; /* Associated DMA buffer structure */ + struct MSDU_TOKEN_ENTRY *prToken; +}; + +struct RTMP_TX_RING { + struct RTMP_DMACB Cell[TX_RING_SIZE]; + uint32_t TxCpuIdx; + uint32_t TxDmaIdx; + uint32_t u4BufSize; + uint32_t TxSwUsedIdx; + uint32_t u4UsedCnt; + uint32_t hw_desc_base; + uint32_t hw_desc_base_ext; + uint32_t hw_cidx_addr; + uint32_t hw_didx_addr; + uint32_t hw_cnt_addr; +}; + +struct RTMP_RX_RING { + struct RTMP_DMACB Cell[RX_RING_SIZE]; + uint32_t RxCpuIdx; + uint32_t RxDmaIdx; + uint32_t u4BufSize; + uint32_t u4RingSize; + u_int8_t fgRxSegPkt; + uint32_t hw_desc_base; + uint32_t hw_desc_base_ext; + uint32_t hw_cidx_addr; + uint32_t hw_didx_addr; + uint32_t hw_cnt_addr; + bool fgIsDumpLog; + uint32_t u4PendingCnt; +}; + +struct PCIE_CHIP_CR_MAPPING { + uint32_t u4ChipAddr; + uint32_t u4BusAddr; + uint32_t u4Range; +}; + +struct MSDU_TOKEN_ENTRY { + uint32_t u4Token; + u_int8_t fgInUsed; + struct timeval rTs; /* token tx timestamp */ + uint32_t u4CpuIdx; /* tx ring cell index */ + struct MSDU_INFO *prMsduInfo; + void *prPacket; + phys_addr_t rDmaAddr; + uint32_t u4DmaLength; + phys_addr_t rPktDmaAddr; + uint32_t u4PktDmaLength; + uint16_t u2Port; /* tx ring number */ +}; + +struct MSDU_TOKEN_INFO { + uint32_t u4UsedCnt; + struct MSDU_TOKEN_ENTRY *aprTokenStack[HIF_TX_MSDU_TOKEN_NUM]; + spinlock_t rTokenLock; + struct MSDU_TOKEN_ENTRY arToken[HIF_TX_MSDU_TOKEN_NUM]; +}; + +struct TX_CMD_REQ { + struct CMD_INFO *prCmdInfo; + uint8_t ucTC; + struct list_head list; +}; + +struct TX_DATA_REQ { + struct MSDU_INFO *prMsduInfo; + struct list_head list; +}; + +struct AMSDU_MAC_TX_DESC { + uint16_t u2TxByteCount; + uint16_t u2DW0; + uint32_t u4DW1; + uint32_t u4DW2:31; + uint32_t u4FR:1; + uint32_t u4DW3; + uint32_t u4DW4; + uint32_t u4DW5_1:9; + uint32_t u4TXS:2; + uint32_t u4DW5_2:21; + uint32_t u4DW6; + uint32_t u4DW7; +}; + + +struct ERR_RECOVERY_CTRL_T { + uint8_t eErrRecovState; + uint32_t u4Status; + uint32_t u4BackupStatus; +}; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +void halHifRst(struct GLUE_INFO *prGlueInfo); +bool halWpdmaAllocRing(struct GLUE_INFO *prGlueInfo, bool fgAllocMem); +void halWpdmaFreeRing(struct GLUE_INFO *prGlueInfo); +void halWpdmaInitRing(struct GLUE_INFO *prGlueInfo, bool fgResetHif); +void halWpdmaInitTxRing(IN struct GLUE_INFO *prGlueInfo); +void halWpdmaInitRxRing(IN struct GLUE_INFO *prGlueInfo); +void halWpdmaProcessCmdDmaDone(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port); +void halWpdmaProcessDataDmaDone(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port); +uint32_t halWpdmaGetRxDmaDoneCnt(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRingNum); +void halInitMsduTokenInfo(IN struct ADAPTER *prAdapter); +void halUninitMsduTokenInfo(IN struct ADAPTER *prAdapter); +uint32_t halGetMsduTokenFreeCnt(IN struct ADAPTER *prAdapter); +struct MSDU_TOKEN_ENTRY *halGetMsduTokenEntry(IN struct ADAPTER *prAdapter, + uint32_t u4TokenNum); +struct MSDU_TOKEN_ENTRY *halAcquireMsduToken(IN struct ADAPTER *prAdapter); +void halReturnMsduToken(IN struct ADAPTER *prAdapter, uint32_t u4TokenNum); +void halReturnTimeoutMsduToken(struct ADAPTER *prAdapter); +void halTxUpdateCutThroughDesc(struct GLUE_INFO *prGlueInfo, + struct MSDU_INFO *prMsduInfo, + struct MSDU_TOKEN_ENTRY *prFillToken, + struct MSDU_TOKEN_ENTRY *prDataToken, + uint32_t u4Idx, bool fgIsLast); +u_int8_t halIsStaticMapBusAddr(IN struct ADAPTER *prAdapter, + IN uint32_t u4Addr); +u_int8_t halChipToStaticMapBusAddr(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4ChipAddr, + OUT uint32_t *pu4BusAddr); +u_int8_t halGetDynamicMapReg(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4ChipAddr, + OUT uint32_t *pu4Value); +u_int8_t halSetDynamicMapReg(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4ChipAddr, + IN uint32_t u4Value); +void halConnacWpdmaConfig(struct GLUE_INFO *prGlueInfo, u_int8_t enable); +void halConnacEnableInterrupt(IN struct ADAPTER *prAdapter); +enum ENUM_CMD_TX_RESULT halWpdmaWriteCmd(struct GLUE_INFO *prGlueInfo, + struct CMD_INFO *prCmdInfo, + uint8_t ucTC); +bool halWpdmaWriteMsdu(struct GLUE_INFO *prGlueInfo, + struct MSDU_INFO *prMsduInfo, + struct list_head *prCurList); +bool halWpdmaWriteAmsdu(struct GLUE_INFO *prGlueInfo, + struct list_head *prList, + uint32_t u4Num, uint16_t u2Size); +void halWpdamFreeMsdu(struct GLUE_INFO *prGlueInfo, + struct MSDU_INFO *prMsduInfo, + bool fgSetEvent); + +bool kalDevReadData(struct GLUE_INFO *prGlueInfo, uint16_t u2Port, + struct SW_RFB *prSwRfb); +bool kalDevKickCmd(struct GLUE_INFO *prGlueInfo); + +/* SER functions */ +void halSetDrvSer(struct ADAPTER *prAdapter); +#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE +void halHwRecoveryTimeout(struct timer_list *timer); +#else +void halHwRecoveryTimeout(unsigned long arg); +#endif +void halHwRecoveryFromError(IN struct ADAPTER *prAdapter); + +/* Debug functions */ +int halTimeCompare(struct timeval *prTs1, struct timeval *prTs2); +void halShowPdmaInfo(IN struct ADAPTER *prAdapter); +bool halShowHostCsrInfo(IN struct ADAPTER *prAdapter); +void kalDumpTxRing(struct GLUE_INFO *prGlueInfo, + struct RTMP_TX_RING *prTxRing, + uint32_t u4Num, bool fgDumpContent); +void kalDumpRxRing(struct GLUE_INFO *prGlueInfo, + struct RTMP_RX_RING *prRxRing, + uint32_t u4Num, bool fgDumpContent); +void haldumpPhyInfo(struct ADAPTER *prAdapter); +int wf_ioremap_read(size_t addr, unsigned int *val); +int wf_ioremap_write(phys_addr_t addr, unsigned int val); +void halEnableSlpProt(struct GLUE_INFO *prGlueInfo); +void halDisableSlpProt(struct GLUE_INFO *prGlueInfo); +#endif /* HIF_PDMA_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/common/kal_pdma.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/common/kal_pdma.c new file mode 100644 index 0000000000000..32b25d8ed9aeb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/common/kal_pdma.c @@ -0,0 +1,1009 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** + *[File] kal_pdma.c + *[Version] v1.0 + *[Revision Date] 2010-03-01 + *[Author] + *[Description] + * The program provides PCIE HIF driver + *[Copyright] + * Copyright (C) 2010 MediaTek Incorporation. All Rights Reserved. + ******************************************************************************/ + + +/******************************************************************************* + * C O M P I L E 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 "hif_pdma.h" + +#include "precomp.h" + +#include +#ifndef CONFIG_X86 +#include +#endif + +#include "mt66xx_reg.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 enum ENUM_CMD_TX_RESULT kalDevWriteCmdByQueue( + struct GLUE_INFO *prGlueInfo, struct CMD_INFO *prCmdInfo, + uint8_t ucTC); +static bool kalDevWriteDataByQueue(struct GLUE_INFO *prGlueInfo, + struct MSDU_INFO *prMsduInfo); +static bool kalDevKickMsduData(struct GLUE_INFO *prGlueInfo); +static bool kalDevKickAmsduData(struct GLUE_INFO *prGlueInfo); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Check connsys is dead or not + * + * \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. + * \param[in] u4Register Register address + * \param[in] pu4Value Pointer to read value + * + * \retval TRUE connsys is dead + * \retval FALSE connsys is alive + */ +/*----------------------------------------------------------------------------*/ +static inline bool kalIsChipDead(struct GLUE_INFO *prGlueInfo, + uint32_t u4Register, uint32_t *pu4Value) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + uint32_t u4Value; + uint32_t u4BusAddr; + + prHifInfo = &prGlueInfo->rHifInfo; + +#if (CFG_ENABLE_HOST_BUS_TIMEOUT == 1) + if (*pu4Value == 0xdead0001) { + DBGLOG(HAL, ERROR, "Host bus hang timeout, CR[0x%08x]\n", + u4Register); + return true; + } +#endif + + if (*pu4Value != HIF_DEADFEED_VALUE) + return false; + + if (!halChipToStaticMapBusAddr(prGlueInfo, CONN_CFG_CHIP_ID_ADDR, + &u4BusAddr)) { + DBGLOG(HAL, ERROR, "Not exist CR read[0x%08x]\n", u4Register); + return false; + } + + RTMP_IO_READ32(prHifInfo, u4BusAddr, &u4Value); + + return u4Value == HIF_DEADFEED_VALUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevRegRead(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Register, OUT uint32_t *pu4Value) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct BUS_INFO *prBusInfo = NULL; + uint32_t u4BusAddr = u4Register; + + ASSERT(prGlueInfo); + ASSERT(pu4Value); + + prHifInfo = &prGlueInfo->rHifInfo; + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + prBusInfo = prAdapter->chip_info->bus_info; + + if (!prHifInfo->fgIsDumpLog && prBusInfo->isValidRegAccess && + !prBusInfo->isValidRegAccess(prAdapter, u4Register)) { + /* Don't printk log when resetting */ + if (!wlanIsChipNoAck(prAdapter)) { + DBGLOG(HAL, ERROR, + "Invalid access! Get CR[0x%08x/0x%08x] value[0x%08x]\n", + u4Register, u4BusAddr, *pu4Value); + } + *pu4Value = HIF_DEADFEED_VALUE; + return FALSE; + } + + /* Static mapping */ + if (halChipToStaticMapBusAddr(prGlueInfo, u4Register, &u4BusAddr)) { + RTMP_IO_READ32(prHifInfo, u4BusAddr, pu4Value); + if (kalIsChipDead(prGlueInfo, u4Register, pu4Value)) { + /* Don't printk log when resetting */ + if (!wlanIsChipNoAck(prAdapter)) { + DBGLOG(HAL, ERROR, + "Read register is deadfeed\n"); + GL_RESET_TRIGGER(prAdapter, + RST_FLAG_CHIP_RESET); + } + return FALSE; + } + } else { + DBGLOG(HAL, ERROR, "Not exist CR read[0x%08x]\n", u4Register); + } + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevRegWrite(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Register, IN uint32_t u4Value) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct BUS_INFO *prBusInfo = NULL; + uint32_t u4BusAddr = u4Register; + + ASSERT(prGlueInfo); + + prHifInfo = &prGlueInfo->rHifInfo; + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + prBusInfo = prAdapter->chip_info->bus_info; + + if (!prHifInfo->fgIsDumpLog && prBusInfo->isValidRegAccess && + !prBusInfo->isValidRegAccess(prAdapter, u4Register)) { + /* Don't printk log when resetting */ + if (!wlanIsChipNoAck(prAdapter)) { + DBGLOG(HAL, ERROR, + "Invalid access! Set CR[0x%08x/0x%08x] value[0x%08x]\n", + u4Register, u4BusAddr, u4Value); + } + return FALSE; + } + + /* Static mapping */ + if (halChipToStaticMapBusAddr(prGlueInfo, u4Register, &u4BusAddr)) { + RTMP_IO_WRITE32(prHifInfo, u4BusAddr, u4Value); + } else { + DBGLOG(HAL, ERROR, "Not exist CR write[0x%08x] value[0x%08x]\n", + u4Register, u4Value); + } + + prHifInfo->u4HifCnt++; + + return TRUE; +} + +static bool kalWaitRxDmaDone(struct GLUE_INFO *prGlueInfo, + struct RTMP_RX_RING *prRxRing, + struct RXD_STRUCT *pRxD, + uint16_t u2Port) +{ + uint32_t u4Count = 0; + + for (u4Count = 0; pRxD->DMADONE == 0; u4Count++) { + kalDevRegRead(prGlueInfo, prRxRing->hw_didx_addr, + &prRxRing->RxDmaIdx); + if (u4Count > DMA_DONE_WAITING_COUNT) { + DBGLOG(HAL, INFO, + "Rx DMA done P[%u] DMA[%u] CPU[%u]\n", + u2Port, prRxRing->RxDmaIdx, prRxRing->RxCpuIdx); + return false; + } + + kalMdelay(DMA_DONE_WAITING_TIME); + } + return true; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevPortRead(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port, IN uint32_t u4Len, + OUT uint8_t *pucBuf, IN uint32_t u4ValidOutBufSize) +{ + struct ADAPTER *prAdapter = NULL; + struct GL_HIF_INFO *prHifInfo = NULL; + struct HIF_MEM_OPS *prMemOps; + struct RTMP_RX_RING *prRxRing; + struct RTMP_DMACB *pRxCell; + struct RXD_STRUCT *pRxD; + struct RTMP_DMABUF *prDmaBuf; + u_int8_t fgRet = TRUE; + uint32_t u4CpuIdx = 0; + + ASSERT(prGlueInfo); + ASSERT(pucBuf); + ASSERT(u4Len <= u4ValidOutBufSize); + + prAdapter = prGlueInfo->prAdapter; + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + prRxRing = &prHifInfo->RxRing[u2Port]; + + kalDevRegRead(prGlueInfo, prRxRing->hw_cidx_addr, &prRxRing->RxCpuIdx); + u4CpuIdx = prRxRing->RxCpuIdx; + INC_RING_INDEX(u4CpuIdx, prRxRing->u4RingSize); + + pRxCell = &prRxRing->Cell[u4CpuIdx]; + pRxD = (struct RXD_STRUCT *)pRxCell->AllocVa; + + if (halWpdmaGetRxDmaDoneCnt(prGlueInfo, u2Port) == 0) + return FALSE; + + if (!kalWaitRxDmaDone(prGlueInfo, prRxRing, pRxD, u2Port)) { + if (!prRxRing->fgIsDumpLog) { + DBGLOG(HAL, ERROR, "RX Done bit not ready(PortRead)\n"); + } + prRxRing->fgIsDumpLog = true; + return FALSE; + } + + if (pRxD->LastSec0 == 0 || prRxRing->fgRxSegPkt) { + /* Rx segmented packet */ + DBGLOG(HAL, WARN, + "Skip Rx segmented packet, SDL0[%u] LS0[%u]\n", + pRxD->SDLen0, pRxD->LastSec0); + if (pRxD->LastSec0 == 1) { + /* Last segmented packet */ + prRxRing->fgRxSegPkt = FALSE; + } else { + /* Segmented packet */ + prRxRing->fgRxSegPkt = TRUE; + } + + fgRet = FALSE; + goto skip; + } + + if (pRxD->SDLen0 > u4Len) { + DBGLOG(HAL, WARN, + "Skip Rx packet, SDL0[%u] > SwRfb max len[%u]\n", + pRxD->SDLen0, u4Len); + goto skip; + } + + prDmaBuf = &pRxCell->DmaBuf; + if (prMemOps->copyEvent && + !prMemOps->copyEvent(prHifInfo, pRxCell, pRxD, + prDmaBuf, pucBuf, u4Len)) { + ASSERT(0); + return FALSE; + } + + pRxD->SDPtr0 = (uint64_t)prDmaBuf->AllocPa & DMA_LOWER_32BITS_MASK; +#ifdef CONFIG_PHYS_ADDR_T_64BIT + pRxD->SDPtr1 = ((uint64_t)prDmaBuf->AllocPa >> DMA_BITS_OFFSET) & + DMA_HIGHER_4BITS_MASK; +#else + pRxD->SDPtr1 = 0; +#endif +skip: + pRxD->SDLen0 = prRxRing->u4BufSize; + pRxD->DMADONE = 0; + + prRxRing->RxCpuIdx = u4CpuIdx; + kalDevRegWrite(prGlueInfo, prRxRing->hw_cidx_addr, prRxRing->RxCpuIdx); + prRxRing->fgIsDumpLog = false; + + GLUE_INC_REF_CNT(prGlueInfo->prAdapter->rHifStats.u4EventRxCount); + + return fgRet; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t +kalDevPortWrite(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port, IN uint32_t u4Len, IN uint8_t *pucBuf, + IN uint32_t u4ValidInBufSize) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct HIF_MEM_OPS *prMemOps; + struct RTMP_TX_RING *prTxRing; + struct RTMP_DMACB *pTxCell; + struct TXD_STRUCT *pTxD; + void *pucDst = NULL; + + ASSERT(prGlueInfo); + ASSERT(pucBuf); + ASSERT(u4Len <= u4ValidInBufSize); + + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + prTxRing = &prHifInfo->TxRing[u2Port]; + + if (prMemOps->allocRuntimeMem) + pucDst = prMemOps->allocRuntimeMem(u4Len); + + kalDevRegRead(prGlueInfo, prTxRing->hw_cidx_addr, &prTxRing->TxCpuIdx); + if (prTxRing->TxCpuIdx >= TX_RING_SIZE) { + DBGLOG(HAL, ERROR, "Error TxCpuIdx[%u]\n", prTxRing->TxCpuIdx); + if (prMemOps->freeBuf) + prMemOps->freeBuf(pucDst, u4Len); + return FALSE; + } + + pTxCell = &prTxRing->Cell[prTxRing->TxCpuIdx]; + pTxD = (struct TXD_STRUCT *)pTxCell->AllocVa; + + pTxCell->pPacket = NULL; + pTxCell->pBuffer = pucDst; + + if (prMemOps->copyCmd && + !prMemOps->copyCmd(prHifInfo, pTxCell, pucDst, + pucBuf, u4Len, NULL, 0)) { + if (prMemOps->freeBuf) + prMemOps->freeBuf(pucDst, u4Len); + ASSERT(0); + return FALSE; + } + + pTxD->LastSec0 = 1; + pTxD->LastSec1 = 0; + pTxD->SDLen0 = u4Len; + pTxD->SDLen1 = 0; + pTxD->SDPtr0 = (uint64_t)pTxCell->PacketPa & DMA_LOWER_32BITS_MASK; +#ifdef CONFIG_PHYS_ADDR_T_64BIT + pTxD->SDPtr0Ext = ((uint64_t)pTxCell->PacketPa >> DMA_BITS_OFFSET) & + DMA_HIGHER_4BITS_MASK; +#else + pTxD->SDPtr0Ext = 0; +#endif + pTxD->SDPtr1 = 0; + pTxD->Burst = 0; + pTxD->DMADONE = 0; + + /* Increase TX_CTX_IDX, but write to register later. */ + INC_RING_INDEX(prTxRing->TxCpuIdx, TX_RING_SIZE); + + prTxRing->u4UsedCnt++; + + kalDevRegWrite(prGlueInfo, prTxRing->hw_cidx_addr, prTxRing->TxCpuIdx); + + GLUE_INC_REF_CNT(prGlueInfo->prAdapter->rHifStats.u4CmdTxCount); + + return TRUE; +} + +void kalDevReadIntStatus(IN struct ADAPTER *prAdapter, + OUT uint32_t *pu4IntStatus) +{ + uint32_t u4RegValue = 0; + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + *pu4IntStatus = 0; + + HAL_MCR_RD(prAdapter, WPDMA_INT_STA, &u4RegValue); + + if (HAL_IS_RX_DONE_INTR(u4RegValue)) + *pu4IntStatus |= WHISR_RX0_DONE_INT; + + if (HAL_IS_TX_DONE_INTR(u4RegValue)) + *pu4IntStatus |= WHISR_TX_DONE_INT; + + if (u4RegValue & CONNAC_MCU_SW_INT) + *pu4IntStatus |= WHISR_D2H_SW_INT; + + prHifInfo->u4IntStatus = u4RegValue; + + /* clear interrupt */ + HAL_MCR_WR(prAdapter, WPDMA_INT_STA, u4RegValue); + +} + +enum ENUM_CMD_TX_RESULT kalDevWriteCmd(IN struct GLUE_INFO *prGlueInfo, + IN struct CMD_INFO *prCmdInfo, IN uint8_t ucTC) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + if (nicSerIsTxStop(prGlueInfo->prAdapter)) + return kalDevWriteCmdByQueue(prGlueInfo, prCmdInfo, ucTC); + + return halWpdmaWriteCmd(prGlueInfo, prCmdInfo, ucTC); +} + +static enum ENUM_CMD_TX_RESULT kalDevWriteCmdByQueue( + struct GLUE_INFO *prGlueInfo, struct CMD_INFO *prCmdInfo, + uint8_t ucTC) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct TX_CMD_REQ *prTxReq; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + prTxReq = kalMemAlloc(sizeof(struct TX_CMD_REQ), PHY_MEM_TYPE); + + if (prTxReq == NULL) { + DBGLOG(HAL, ERROR, "kmalloc() TX_CMD_REQ error\n"); + halWpdmaWriteCmd(prGlueInfo, prCmdInfo, ucTC); + return CMD_TX_RESULT_FAILED; + } + + prTxReq->prCmdInfo = prCmdInfo; + prTxReq->ucTC = ucTC; + list_add_tail(&prTxReq->list, &prHifInfo->rTxCmdQ); + + return CMD_TX_RESULT_QUEUED; +} + +bool kalDevKickCmd(IN struct GLUE_INFO *prGlueInfo) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct list_head *prCur, *prNext; + struct TX_CMD_REQ *prTxReq; + enum ENUM_CMD_TX_RESULT ret; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + list_for_each_safe(prCur, prNext, &prHifInfo->rTxCmdQ) { + prTxReq = list_entry(prCur, struct TX_CMD_REQ, list); + if (prTxReq->prCmdInfo) { + ret = halWpdmaWriteCmd(prGlueInfo, + prTxReq->prCmdInfo, prTxReq->ucTC); + if (ret == CMD_TX_RESULT_SUCCESS) { + if (prTxReq->prCmdInfo->pfHifTxCmdDoneCb) + prTxReq->prCmdInfo->pfHifTxCmdDoneCb( + prGlueInfo->prAdapter, + prTxReq->prCmdInfo); + } else { + DBGLOG(HAL, ERROR, "ret: %d\n", ret); + } + } + list_del(prCur); + kfree(prTxReq); + } + + return true; +} + +static uint8_t kalGetSwAmsduNum(struct GLUE_INFO *prGlueInfo, + struct MSDU_INFO *prMsduInfo) +{ + struct ADAPTER *prAdapter; + struct sk_buff *prSkb; + struct STA_RECORD *prStaRec; + uint8_t ucTid, ucStaRecIndex; + struct TX_DESC_OPS_T *prTxDescOps; + + ASSERT(prGlueInfo); + ASSERT(prMsduInfo); + + prAdapter = prGlueInfo->prAdapter; + prTxDescOps = prAdapter->chip_info->prTxDescOps; + prSkb = (struct sk_buff *)prMsduInfo->prPacket; + + ucTid = prTxDescOps->nic_txd_tid_op((void *)prSkb->data, 0, FALSE); + ucStaRecIndex = prMsduInfo->ucStaRecIndex; + if (ucStaRecIndex >= CFG_STA_REC_NUM || ucTid >= TX_DESC_TID_NUM) + return 0; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIndex); + if (!prStaRec || !(prStaRec->ucAmsduEnBitmap & BIT(ucTid))) + return 0; + + return prStaRec->ucMaxMpduCount; +} + +u_int8_t kalDevWriteData(IN struct GLUE_INFO *prGlueInfo, + IN struct MSDU_INFO *prMsduInfo) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prGlueInfo); + + prHifInfo = &prGlueInfo->rHifInfo; + prChipInfo = prGlueInfo->prAdapter->chip_info; + + if (nicSerIsTxStop(prGlueInfo->prAdapter) || + (prChipInfo->ucMaxSwAmsduNum > 1 && + kalGetSwAmsduNum(prGlueInfo, prMsduInfo) > 1)) + return kalDevWriteDataByQueue(prGlueInfo, prMsduInfo); + + return halWpdmaWriteMsdu(prGlueInfo, prMsduInfo, NULL); +} + +static bool kalDevWriteDataByQueue(IN struct GLUE_INFO *prGlueInfo, + IN struct MSDU_INFO *prMsduInfo) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct TX_DATA_REQ *prTxReq; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + prTxReq = &prMsduInfo->rTxReq; + prTxReq->prMsduInfo = prMsduInfo; + list_add_tail(&prTxReq->list, &prHifInfo->rTxDataQ); + prHifInfo->u4TxDataQLen++; + + return true; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Kick Tx data to device + * + * \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. + * + * \retval TRUE operation success + * \retval FALSE operation fail + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevKickData(IN struct GLUE_INFO *prGlueInfo) +{ + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prGlueInfo); + + prChipInfo = prGlueInfo->prAdapter->chip_info; + + if (prChipInfo->ucMaxSwAmsduNum > 1) + return kalDevKickAmsduData(prGlueInfo); + + return kalDevKickMsduData(prGlueInfo); +} + +static uint16_t kalGetPaddingSize(uint16_t u2TxByteCount) +{ + uint16_t u2Size = 0; + + if (u2TxByteCount & 3) + u2Size = 4 - (u2TxByteCount & 3); + return u2Size; +} + +static uint16_t kalGetMoreSizeForAmsdu(uint32_t u4TxdDW1) +{ + /* + * ETYPE=0/VLAN=0/RMVL=X PLlength = PL length + * ETYPE=0/VLAN=1/RMVL=1 PLlength = PL length - 4 + * ETYPE=0/VLAN=1/RMVL=0 PLlength = PL length + 6 + * ETYPE=1/VLAN=0/RMVL=X PLlength = PL length + 8 + * ETYPE=1/VLAN=1/RMVL=1 PLlength = PL length + 4 + * ETYPE=1/VLAN=1/RMVL=0 PLlength = PL length + 14 + */ + uint16_t u2Size = 0; + + if (u4TxdDW1 & TXD_DW1_ETYP) + u2Size += 8; + if (u4TxdDW1 & TXD_DW1_VLAN) { + if (u4TxdDW1 & TXD_DW1_RMVL) { + if (u2Size >= 4) + u2Size -= 4; + } else + u2Size += 6; + } + return u2Size; +} + +static bool kalDevKickMsduData(struct GLUE_INFO *prGlueInfo) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct BUS_INFO *prBusInfo = NULL; + struct list_head *prCur, *prNext; + struct TX_DATA_REQ *prTxReq; + struct MSDU_INFO *prMsduInfo; + bool fgRet = true; + + ASSERT(prGlueInfo); + + prHifInfo = &prGlueInfo->rHifInfo; + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + + list_for_each_safe(prCur, prNext, &prHifInfo->rTxDataQ) { + prTxReq = list_entry(prCur, struct TX_DATA_REQ, list); + prMsduInfo = prTxReq->prMsduInfo; + if (!prMsduInfo || + !halWpdmaWriteMsdu(prGlueInfo, prMsduInfo, prCur)) { + fgRet = false; + break; + } + } + + return fgRet; +} + +static int kalAmsduTxDCmp(void *prPriv, struct list_head *prList1, + struct list_head *prList2) +{ + struct TX_DATA_REQ *prTxReq1, *prTxReq2; + struct sk_buff *prSkb1, *prSkb2; + struct AMSDU_MAC_TX_DESC *prTxD1, *prTxD2; + + prTxReq1 = list_entry(prList1, struct TX_DATA_REQ, list); + prTxReq2 = list_entry(prList2, struct TX_DATA_REQ, list); + prSkb1 = (struct sk_buff *)prTxReq1->prMsduInfo->prPacket; + prSkb2 = (struct sk_buff *)prTxReq2->prMsduInfo->prPacket; + prTxD1 = (struct AMSDU_MAC_TX_DESC *)prSkb1->data; + prTxD2 = (struct AMSDU_MAC_TX_DESC *)prSkb2->data; + + if (prTxD1->u2DW0 != prTxD2->u2DW0) + return prTxD2->u2DW0 - prTxD1->u2DW0; + + return prTxD1->u4DW1 - prTxD2->u4DW1; +} + +static bool kalIsAggregatedMsdu(struct GLUE_INFO *prGlueInfo, + struct MSDU_INFO *prMsduInfo) +{ + struct sk_buff *prSkb; + struct AMSDU_MAC_TX_DESC *prTxD; + + prSkb = (struct sk_buff *)prMsduInfo->prPacket; + prTxD = (struct AMSDU_MAC_TX_DESC *)prSkb->data; + + if (prTxD->u4FR || prTxD->u4TXS) + return false; + return true; +} + +static uint32_t kalGetNumOfAmsdu(struct GLUE_INFO *prGlueInfo, + struct list_head *prTarget, + struct list_head *prHead, + uint16_t *pu2Size) +{ + struct TX_DATA_REQ *prTxReq; + struct MSDU_INFO *prMsduInfo; + struct sk_buff *prSkb; + struct AMSDU_MAC_TX_DESC *prTxD; + struct STA_RECORD *prStaRec; + struct list_head *prCur; + uint16_t u2TotalSize, u2Size; + uint32_t u4Cnt = 1; + uint8_t ucStaRecIndex; + + prTxReq = list_entry(prTarget, struct TX_DATA_REQ, list); + prMsduInfo = prTxReq->prMsduInfo; + prSkb = (struct sk_buff *)prMsduInfo->prPacket; + prTxD = (struct AMSDU_MAC_TX_DESC *)prSkb->data; + + ucStaRecIndex = prMsduInfo->ucStaRecIndex; + prStaRec = cnmGetStaRecByIndex(prGlueInfo->prAdapter, ucStaRecIndex); + if (!prStaRec) + return 1; + + u2TotalSize = NIC_TX_DESC_LONG_FORMAT_LENGTH; + u2TotalSize += prMsduInfo->u2FrameLength; + u2TotalSize += kalGetMoreSizeForAmsdu(prTxD->u4DW1); + + for (prCur = prTarget->next; prCur != prHead; prCur = prCur->next) { + if (u4Cnt >= kalGetSwAmsduNum(prGlueInfo, prMsduInfo) || + kalAmsduTxDCmp((void *)prGlueInfo, prTarget, prCur)) + break; + + prTxReq = list_entry(prCur, struct TX_DATA_REQ, list); + prMsduInfo = prTxReq->prMsduInfo; + prSkb = (struct sk_buff *)prMsduInfo->prPacket; + prTxD = (struct AMSDU_MAC_TX_DESC *)prSkb->data; + + u2Size = prMsduInfo->u2FrameLength; + u2Size += kalGetMoreSizeForAmsdu(prTxD->u4DW1); + u2Size += kalGetPaddingSize(u2TotalSize); + if ((u2TotalSize + u2Size) > prStaRec->u4MaxMpduLen) + break; + + u2TotalSize += u2Size; + u4Cnt++; + } + + if (u2TotalSize < prStaRec->u4MinMpduLen) + return 1; + + *pu2Size = u2TotalSize; + return u4Cnt; +} + +static bool kalDevKickAmsduData(struct GLUE_INFO *prGlueInfo) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct BUS_INFO *prBusInfo = NULL; + struct list_head *prHead, *prCur, *prNext; + struct TX_DATA_REQ *prTxReq; + struct MSDU_INFO *prMsduInfo; + uint32_t u4Num = 0, u4Idx; + uint16_t u2Size = 0; + bool fgRet = true; + + ASSERT(prGlueInfo); + + prHifInfo = &prGlueInfo->rHifInfo; + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + + prHead = &prHifInfo->rTxDataQ; + list_for_each_safe(prCur, prNext, prHead) { + prTxReq = list_entry(prCur, struct TX_DATA_REQ, list); + prMsduInfo = prTxReq->prMsduInfo; + if (!kalIsAggregatedMsdu(prGlueInfo, prMsduInfo)) { + if (!halWpdmaWriteMsdu(prGlueInfo, prMsduInfo, prCur)) + return false; + } + } + + list_sort((void *)prGlueInfo, prHead, kalAmsduTxDCmp); + + for (prCur = prHead->next; prCur != prHead; prCur = prNext) { + u4Num = kalGetNumOfAmsdu(prGlueInfo, prCur, prHead, &u2Size); + prNext = prCur->next; + if (u4Num > 1) { + for (u4Idx = 1; u4Idx < u4Num; u4Idx++) + prNext = prNext->next; + fgRet = halWpdmaWriteAmsdu(prGlueInfo, prCur, + u4Num, u2Size); + } else { + prTxReq = list_entry(prCur, struct TX_DATA_REQ, list); + prMsduInfo = prTxReq->prMsduInfo; + fgRet = halWpdmaWriteMsdu(prGlueInfo, prMsduInfo, + prCur); + } + if (!fgRet) + break; + } + + return fgRet; +} + +bool kalDevReadData(struct GLUE_INFO *prGlueInfo, uint16_t u2Port, + struct SW_RFB *prSwRfb) +{ + struct ADAPTER *prAdapter = NULL; + struct GL_HIF_INFO *prHifInfo = NULL; + struct HIF_MEM_OPS *prMemOps; + struct RXD_STRUCT *pRxD; + struct RTMP_RX_RING *prRxRing; + struct RTMP_DMACB *pRxCell; + struct RTMP_DMABUF *prDmaBuf; + u_int8_t fgRet = TRUE; + uint32_t u4CpuIdx = 0; + + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + prRxRing = &prHifInfo->RxRing[u2Port]; + + kalDevRegRead(prGlueInfo, prRxRing->hw_cidx_addr, &prRxRing->RxCpuIdx); + u4CpuIdx = prRxRing->RxCpuIdx; + INC_RING_INDEX(u4CpuIdx, prRxRing->u4RingSize); + + pRxCell = &prRxRing->Cell[u4CpuIdx]; + pRxD = (struct RXD_STRUCT *)pRxCell->AllocVa; + + if (halWpdmaGetRxDmaDoneCnt(prGlueInfo, u2Port) == 0) + return FALSE; + + if (!kalWaitRxDmaDone(prGlueInfo, prRxRing, pRxD, u2Port)) { + if (!prRxRing->fgIsDumpLog) { + DBGLOG(HAL, ERROR, "RX Done bit not ready(ReadData)\n"); + } + prRxRing->fgIsDumpLog = true; + return false; + } + + if (pRxD->LastSec0 == 0 || prRxRing->fgRxSegPkt) { + /* Rx segmented packet */ + DBGLOG(HAL, WARN, + "Skip Rx segmented data packet, SDL0[%u] LS0[%u]\n", + pRxD->SDLen0, pRxD->LastSec0); + if (pRxD->LastSec0 == 1) { + /* Last segmented packet */ + prRxRing->fgRxSegPkt = FALSE; + } else { + /* Segmented packet */ + prRxRing->fgRxSegPkt = TRUE; + } + + fgRet = false; + goto skip; + } + + prDmaBuf = &pRxCell->DmaBuf; + + if (prMemOps->copyRxData && + !prMemOps->copyRxData(prHifInfo, pRxCell, prDmaBuf, prSwRfb)) { + fgRet = false; + goto skip; + } + + prSwRfb->pucRecvBuff = ((struct sk_buff *)prSwRfb->pvPacket)->data; + prSwRfb->prRxStatus = (void *)prSwRfb->pucRecvBuff; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + prSwRfb->u4TcpUdpIpCksStatus = pRxD->RXINFO; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + pRxD->SDPtr0 = (uint64_t)prDmaBuf->AllocPa & DMA_LOWER_32BITS_MASK; +#ifdef CONFIG_PHYS_ADDR_T_64BIT + pRxD->SDPtr1 = ((uint64_t)prDmaBuf->AllocPa >> + DMA_BITS_OFFSET) & DMA_HIGHER_4BITS_MASK; +#else + pRxD->SDPtr1 = 0; +#endif +skip: + pRxD->SDLen0 = prRxRing->u4BufSize; + pRxD->DMADONE = 0; + + prRxRing->RxCpuIdx = u4CpuIdx; + kalDevRegWrite(prGlueInfo, prRxRing->hw_cidx_addr, prRxRing->RxCpuIdx); + prRxRing->fgIsDumpLog = false; + + GLUE_INC_REF_CNT(prGlueInfo->prAdapter->rHifStats.u4DataRxCount); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + if (fgRet) + DBGLOG(RX, LOUD, "u4TcpUdpIpCksStatus[0x%02x]\n", + prSwRfb->u4TcpUdpIpCksStatus); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + return fgRet; +} + +int wf_ioremap_read(size_t addr, unsigned int *val) +{ + void *vir_addr = NULL; + + vir_addr = ioremap_nocache(addr, 0x10); + if (!vir_addr) { + DBGLOG(INIT, ERROR, "%s: Cannot remap address.\n", __func__); + return -1; + } + + *val = readl(vir_addr); + iounmap(vir_addr); + DBGLOG(INIT, TRACE, "Read CONSYS 0x%08x=0x%08x.\n", addr, *val); + + return 0; +} + +int wf_ioremap_write(phys_addr_t addr, unsigned int val) +{ + void *vir_addr = NULL; + + vir_addr = ioremap_nocache(addr, 0x10); + if (!vir_addr) { + DBGLOG(INIT, ERROR, "%s: Cannot remap address.\n", __func__); + return -1; + } + + writel(val, vir_addr); + iounmap(vir_addr); + DBGLOG(INIT, TRACE, "Write CONSYS 0x%08x=0x%08x.\n", addr, val); + + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/ehpi/arm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/ehpi/arm.c new file mode 100644 index 0000000000000..2d9cf7e82e100 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/ehpi/arm.c @@ -0,0 +1,536 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/ehpi/arm.c#1 +*/ + +/*! \file "colibri.c" +* \brief Brief description. +* +* Detail description. +*/ + + +/****************************************************************************** +* C O M P I L E R F L A G S +******************************************************************************* +*/ +#if !defined(MCR_EHTCR) +#define MCR_EHTCR 0x0054 +#endif + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "colibri.h" +#include "wlan_lib.h" + +/******************************************************************************* +* 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 void __iomem *mt5931_mcr_base; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#if CFG_EHPI_FASTER_BUS_TIMING +#define EHPI_CONFIG MSC_CS(4, MSC_RBUFF_SLOW | \ + MSC_RRR(4) | \ + MSC_RDN(8) | \ + MSC_RDF(7) | \ + MSC_RBW_16 | \ + MSC_RT_VLIO) +#else +#define EHPI_CONFIG MSC_CS(4, MSC_RBUFF_SLOW | \ + MSC_RRR(7) | \ + MSC_RDN(13) | \ + MSC_RDF(12) | \ + MSC_RBW_16 | \ + MSC_RT_VLIO) +#endif /* CFG_EHPI_FASTER_BUS_TIMING */ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static void collibri_ehpi_reg_init(void); + +static void collibri_ehpi_reg_uninit(void); + +static void mt5931_ehpi_reg_init(void); + +static void mt5931_ehpi_reg_uninit(void); + +static void busSetIrq(void); + +static void busFreeIrq(void); + +static irqreturn_t glEhpiInterruptHandler(int irq, void *dev_id); + +#if DBG +static void initTrig(void); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will register sdio bus to the os +* +* \param[in] pfProbe Function pointer to detect card +* \param[in] pfRemove Function pointer to remove card +* +* \return The result of registering sdio bus +*/ +/*----------------------------------------------------------------------------*/ +uint32_t glRegisterBus(probe_card pfProbe, remove_card pfRemove) +{ + + ASSERT(pfProbe); + ASSERT(pfRemove); + + pr_info("mtk_sdio: MediaTek eHPI WLAN driver\n"); + pr_info("mtk_sdio: Copyright MediaTek Inc.\n"); + + if (pfProbe(NULL) != WLAN_STATUS_SUCCESS) { + pfRemove(); + return WLAN_STATUS_FAILURE; + } + + return WLAN_STATUS_SUCCESS; +} /* 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(); + + /* TODO: eHPI uninitialization */ +} /* 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(struct GLUE_INFO *prGlueInfo, unsigned long ulCookie) +{ + struct GL_HIF_INFO *prHif = NULL; + + ASSERT(prGlueInfo); + + prHif = &prGlueInfo->rHifInfo; + + /* fill some buffered information into prHif */ + prHif->mcr_addr_base = mt5931_mcr_base + EHPI_OFFSET_ADDR; + prHif->mcr_data_base = mt5931_mcr_base + EHPI_OFFSET_DATA; + + prGlueInfo->u4InfType = MT_DEV_INF_EHPI; +} /* end of glSetHifInfo() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function clears hif related info. +* +* \param[in] prGlueInfo Pointer to glue info structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void glClearHifInfo(struct GLUE_INFO *prGlueInfo) +{ + struct GL_HIF_INFO *prHif = NULL; + + ASSERT(prGlueInfo); + + prHif = &prGlueInfo->rHifInfo; + + /* do something */ + prHif->mcr_addr_base = 0; + prHif->mcr_data_base = 0; +} /* 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) +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t glBusInit(void *pvData) +{ +#if DBG + initTrig(); +#endif + + /* 1. initialize eHPI control registers */ + collibri_ehpi_reg_init(); + + /* 2. memory remapping for MT5931 */ + mt5931_ehpi_reg_init(); + + return TRUE; +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus operation and release resources. +* +* \param[in] pvData A pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void glBusRelease(void *pvData) +{ + /* 1. memory unmapping for MT5931 */ + mt5931_ehpi_reg_uninit(); + + /* 2. uninitialize eHPI control registers */ + collibri_ehpi_reg_uninit(); +} /* 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 +*/ +/*----------------------------------------------------------------------------*/ +int32_t glBusSetIrq(void *pvData, void *pfnIsr, void *pvCookie) +{ + struct net_device *pDev = (struct net_device *)pvData; + int i4Status = 0; + + /* 1. enable GPIO pin as IRQ */ + busSetIrq(); + + /* 2. Specify IRQ number into net_device */ + pDev->irq = WLAN_STA_IRQ; + + /* 3. register ISR callback */ + + i4Status = request_irq(pDev->irq, + glEhpiInterruptHandler, + IRQF_DISABLED | IRQF_SHARED | IRQF_TRIGGER_FALLING, pDev->name, pvCookie); + + if (i4Status < 0) + pr_debug("request_irq(%d) failed\n", pDev->irq); + else + pr_info("request_irq(%d) success with dev_id(%x)\n", pDev->irq, (unsigned int)pvCookie); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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(void *pvData, void *pvCookie) +{ + struct net_device *prDev = (struct net_device *)pvData; + + if (!prDev) { + pr_info("Invalid net_device context.\n"); + return; + } + + if (prDev->irq) { + disable_irq(prDev->irq); + free_irq(prDev->irq, pvCookie); + prDev->irq = 0; + } + + busFreeIrq(); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set power state +* +* \param[in] pvGlueInfo A pointer to GLUE_INFO_T +* \param[in] ePowerMode Power Mode Setting +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void glSetPowerState(IN struct GLUE_INFO *prGlueInfo, IN uint32_t ePowerMode) +{ +} + +#if DBG +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setup the GPIO pin. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void setTrig(void) +{ + GPSR1 = (0x1UL << 8); +} /* end of setTrig() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Clear the GPIO pin. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void clearTrig(void) +{ + GPCR1 = (0x1UL << 8); +} /* end of clearTrig() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set a specified GPIO pin to H or L. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static void initTrig(void) +{ + set_GPIO_mode(GPIO40_FFDTR | GPIO_OUT); + clearTrig(); +} /* end of initTrig() */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function congifure platform-dependent interrupt triger type. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void busSetIrq(void) +{ +#if defined(WLAN_STA_IRQ_GPIO) + pxa_gpio_mode(WLAN_STA_IRQ_GPIO | GPIO_IN); + set_irq_type(WLAN_STA_IRQ, IRQT_FALLING); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function should restore settings changed by busSetIrq(). +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void busFreeIrq(void) +{ +#if defined(WLAN_STA_IRQ_GPIO) + pxa_gpio_mode(WLAN_STA_IRQ_GPIO | GPIO_OUT); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function configures colibri memory controller registers +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static void collibri_ehpi_reg_init(void) +{ + uint32_t u4RegValue; + + /* 1. enable nCS as memory controller */ + pxa_gpio_mode(GPIO80_nCS_4_MD); + + /* 2. nCS<4> configuration */ + u4RegValue = MSC2; + u4RegValue &= ~MSC_CS(4, 0xFFFF); + u4RegValue |= EHPI_CONFIG; + MSC2 = u4RegValue; + + pr_info("EHPI new MSC2:0x%08x\n", MSC2); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function restores colibri memory controller registers +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static void collibri_ehpi_reg_uninit(void) +{ + uint32_t u4RegValue; + + /* 1. restore nCS<4> configuration */ + u4RegValue = MSC2; + u4RegValue &= ~MSC_CS(4, 0xFFFF); + MSC2 = u4RegValue; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function configures MT5931 mapped registers on colibri +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static void mt5931_ehpi_reg_init(void) +{ + struct resource *reso = NULL; + + /* 1. request memory regioin */ + reso = request_mem_region((unsigned long)MEM_MAPPED_ADDR, (unsigned long)MEM_MAPPED_LEN, (char *)MODULE_PREFIX); + if (!reso) { + pr_err("request_mem_region(0x%08X) failed.\n", MEM_MAPPED_ADDR); + return; + } + + /* 2. memory regioin remapping */ + mt5931_mcr_base = ioremap_nocache(MEM_MAPPED_ADDR, MEM_MAPPED_LEN); + if (!(mt5931_mcr_base)) { + release_mem_region(MEM_MAPPED_ADDR, MEM_MAPPED_LEN); + pr_err("ioremap_nocache(0x%08X) failed.\n", MEM_MAPPED_ADDR); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function releases MT5931 mapped registers on colibri +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static void mt5931_ehpi_reg_uninit(void) +{ + iounmap(mt5931_mcr_base); + mt5931_mcr_base = NULL; + + release_mem_region(MEM_MAPPED_ADDR, MEM_MAPPED_LEN); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Callback for interrupt coming from device +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static irqreturn_t glEhpiInterruptHandler(int irq, void *dev_id) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) dev_id; + + ASSERT(prGlueInfo); + + if (!prGlueInfo) + return IRQ_HANDLED; + + /* 1. Running for ISR */ + wlanISR(prGlueInfo->prAdapter, TRUE); + + /* 1.1 Halt flag Checking */ + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) + return IRQ_HANDLED; + + /* 2. Flag marking for interrupt */ + set_bit(GLUE_FLAG_INT_BIT, &prGlueInfo->ulFlag); + + /* 3. wake up tx service thread */ + wake_up_interruptible(&prGlueInfo->waitq); + + return IRQ_HANDLED; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/ehpi/colibri.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/ehpi/colibri.c new file mode 100644 index 0000000000000..803a8e8240804 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/ehpi/colibri.c @@ -0,0 +1,536 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/ehpi/colibri.c#1 +*/ + +/*! \file "colibri.c" +* \brief Brief description. +* +* Detail description. +*/ + + +/****************************************************************************** +* C O M P I L E R F L A G S +******************************************************************************* +*/ +#if !defined(MCR_EHTCR) +#define MCR_EHTCR 0x0054 +#endif + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "colibri.h" +#include "wlan_lib.h" + +/******************************************************************************* +* 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 void __iomem *mt5931_mcr_base; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#if CFG_EHPI_FASTER_BUS_TIMING +#define EHPI_CONFIG MSC_CS(4, MSC_RBUFF_SLOW | \ + MSC_RRR(4) | \ + MSC_RDN(8) | \ + MSC_RDF(7) | \ + MSC_RBW_16 | \ + MSC_RT_VLIO) +#else +#define EHPI_CONFIG MSC_CS(4, MSC_RBUFF_SLOW | \ + MSC_RRR(7) | \ + MSC_RDN(13) | \ + MSC_RDF(12) | \ + MSC_RBW_16 | \ + MSC_RT_VLIO) +#endif /* CFG_EHPI_FASTER_BUS_TIMING */ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static void collibri_ehpi_reg_init(void); + +static void collibri_ehpi_reg_uninit(void); + +static void mt5931_ehpi_reg_init(void); + +static void mt5931_ehpi_reg_uninit(void); + +static void busSetIrq(void); + +static void busFreeIrq(void); + +static irqreturn_t glEhpiInterruptHandler(int irq, void *dev_id); + +#if DBG +static void initTrig(void); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will register sdio bus to the os +* +* \param[in] pfProbe Function pointer to detect card +* \param[in] pfRemove Function pointer to remove card +* +* \return The result of registering sdio bus +*/ +/*----------------------------------------------------------------------------*/ +uint32_t glRegisterBus(probe_card pfProbe, remove_card pfRemove) +{ + + ASSERT(pfProbe); + ASSERT(pfRemove); + + pr_info("mtk_sdio: MediaTek eHPI WLAN driver\n"); + pr_info("mtk_sdio: Copyright MediaTek Inc.\n"); + + if (pfProbe(NULL) != WLAN_STATUS_SUCCESS) { + pfRemove(); + return WLAN_STATUS_FAILURE; + } + + return WLAN_STATUS_SUCCESS; +} /* 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(); + + /* TODO: eHPI uninitialization */ +} /* 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(struct GLUE_INFO *prGlueInfo, unsigned long ulCookie) +{ + struct GL_HIF_INFO *prHif = NULL; + + ASSERT(prGlueInfo); + + prHif = &prGlueInfo->rHifInfo; + + /* fill some buffered information into prHif */ + prHif->mcr_addr_base = mt5931_mcr_base + EHPI_OFFSET_ADDR; + prHif->mcr_data_base = mt5931_mcr_base + EHPI_OFFSET_DATA; + + prGlueInfo->u4InfType = MT_DEV_INF_EHPI; +} /* end of glSetHifInfo() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function clears hif related info. +* +* \param[in] prGlueInfo Pointer to glue info structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void glClearHifInfo(struct GLUE_INFO *prGlueInfo) +{ + struct GL_HIF_INFO *prHif = NULL; + + ASSERT(prGlueInfo); + + prHif = &prGlueInfo->rHifInfo; + + /* do something */ + prHif->mcr_addr_base = 0; + prHif->mcr_data_base = 0; +} /* 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) +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t glBusInit(void *pvData) +{ +#if DBG + initTrig(); +#endif + + /* 1. initialize eHPI control registers */ + collibri_ehpi_reg_init(); + + /* 2. memory remapping for MT5931 */ + mt5931_ehpi_reg_init(); + + return TRUE; +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus operation and release resources. +* +* \param[in] pvData A pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void glBusRelease(void *pvData) +{ + /* 1. memory unmapping for MT5931 */ + mt5931_ehpi_reg_uninit(); + + /* 2. uninitialize eHPI control registers */ + collibri_ehpi_reg_uninit(); +} /* 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 +*/ +/*----------------------------------------------------------------------------*/ +int32_t glBusSetIrq(void *pvData, void *pfnIsr, void *pvCookie) +{ + struct net_device *pDev = (struct net_device *)pvData; + int i4Status = 0; + + /* 1. enable GPIO pin as IRQ */ + busSetIrq(); + + /* 2. Specify IRQ number into net_device */ + pDev->irq = WLAN_STA_IRQ; + + /* 3. register ISR callback */ + + i4Status = request_irq(pDev->irq, + glEhpiInterruptHandler, + IRQF_DISABLED | IRQF_SHARED | IRQF_TRIGGER_FALLING, pDev->name, pvCookie); + + if (i4Status < 0) + pr_debug("request_irq(%d) failed\n", pDev->irq); + else + pr_info("request_irq(%d) success with dev_id(%x)\n", pDev->irq, (unsigned int)pvCookie); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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(void *pvData, void *pvCookie) +{ + struct net_device *prDev = (struct net_device *)pvData; + + if (!prDev) { + pr_info("Invalid net_device context.\n"); + return; + } + + if (prDev->irq) { + disable_irq(prDev->irq); + free_irq(prDev->irq, pvCookie); + prDev->irq = 0; + } + + busFreeIrq(); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set power state +* +* \param[in] pvGlueInfo A pointer to GLUE_INFO_T +* \param[in] ePowerMode Power Mode Setting +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void glSetPowerState(IN struct GLUE_INFO *prGlueInfo, IN uint32_t ePowerMode) +{ +} + +#if DBG +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setup the GPIO pin. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void setTrig(void) +{ + GPSR1 = (0x1UL << 8); +} /* end of setTrig() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Clear the GPIO pin. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void clearTrig(void) +{ + GPCR1 = (0x1UL << 8); +} /* end of clearTrig() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set a specified GPIO pin to H or L. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static void initTrig(void) +{ + set_GPIO_mode(GPIO40_FFDTR | GPIO_OUT); + clearTrig(); +} /* end of initTrig() */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function congifure platform-dependent interrupt triger type. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void busSetIrq(void) +{ +#if defined(WLAN_STA_IRQ_GPIO) + pxa_gpio_mode(WLAN_STA_IRQ_GPIO | GPIO_IN); + set_irq_type(WLAN_STA_IRQ, IRQT_FALLING); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function should restore settings changed by busSetIrq(). +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void busFreeIrq(void) +{ +#if defined(WLAN_STA_IRQ_GPIO) + pxa_gpio_mode(WLAN_STA_IRQ_GPIO | GPIO_OUT); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function configures colibri memory controller registers +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static void collibri_ehpi_reg_init(void) +{ + uint32_t u4RegValue; + + /* 1. enable nCS as memory controller */ + pxa_gpio_mode(GPIO80_nCS_4_MD); + + /* 2. nCS<4> configuration */ + u4RegValue = MSC2; + u4RegValue &= ~MSC_CS(4, 0xFFFF); + u4RegValue |= EHPI_CONFIG; + MSC2 = u4RegValue; + + pr_info("EHPI new MSC2:0x%08x\n", MSC2); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function restores colibri memory controller registers +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static void collibri_ehpi_reg_uninit(void) +{ + uint32_t u4RegValue; + + /* 1. restore nCS<4> configuration */ + u4RegValue = MSC2; + u4RegValue &= ~MSC_CS(4, 0xFFFF); + MSC2 = u4RegValue; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function configures MT5931 mapped registers on colibri +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static void mt5931_ehpi_reg_init(void) +{ + struct resource *reso = NULL; + + /* 1. request memory regioin */ + reso = request_mem_region((unsigned long)MEM_MAPPED_ADDR, (unsigned long)MEM_MAPPED_LEN, (char *)MODULE_PREFIX); + if (!reso) { + pr_err("request_mem_region(0x%08X) failed.\n", MEM_MAPPED_ADDR); + return; + } + + /* 2. memory regioin remapping */ + mt5931_mcr_base = ioremap_nocache(MEM_MAPPED_ADDR, MEM_MAPPED_LEN); + if (!(mt5931_mcr_base)) { + release_mem_region(MEM_MAPPED_ADDR, MEM_MAPPED_LEN); + pr_err("ioremap_nocache(0x%08X) failed.\n", MEM_MAPPED_ADDR); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function releases MT5931 mapped registers on colibri +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static void mt5931_ehpi_reg_uninit(void) +{ + iounmap(mt5931_mcr_base); + mt5931_mcr_base = NULL; + + release_mem_region(MEM_MAPPED_ADDR, MEM_MAPPED_LEN); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Callback for interrupt coming from device +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static irqreturn_t glEhpiInterruptHandler(int irq, void *dev_id) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) dev_id; + + ASSERT(prGlueInfo); + + if (!prGlueInfo) + return IRQ_HANDLED; + + /* 1. Running for ISR */ + wlanISR(prGlueInfo->prAdapter, TRUE); + + /* 1.1 Halt flag Checking */ + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) + return IRQ_HANDLED; + + /* 2. Flag marking for interrupt */ + set_bit(GLUE_FLAG_INT_BIT, &prGlueInfo->ulFlag); + + /* 3. wake up tx service thread */ + wake_up_interruptible(&prGlueInfo->waitq); + + return IRQ_HANDLED; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/ehpi/ehpi.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/ehpi/ehpi.c new file mode 100644 index 0000000000000..1ca0aaf9feeed --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/ehpi/ehpi.c @@ -0,0 +1,414 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/ehpi/ehpi.c#1 +*/ + +/*! \file "ehpi.c" +* \brief Brief description. +* +* Detail description. +*/ + + +/****************************************************************************** +* C O M P I L E R F L A G S +******************************************************************************* +*/ +#if !defined(MCR_EHTCR) +#define MCR_EHTCR 0x0054 +#endif + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "colibri.h" +#include "wlan_lib.h" + +/******************************************************************************* +* 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 u_int8_t kalDevRegRead_impl(IN struct GLUE_INFO *prGlueInfo, IN uint32_t u4Register, OUT uint32_t *pu4Value); + +static u_int8_t kalDevRegWrite_impl(IN struct GLUE_INFO *prGlueInfo, IN uint32_t u4Register, IN uint32_t u4Value); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to read a 32 bit register value from device. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u4Register The register offset. +* \param[out] pu4Value Pointer to the 32-bit value of the register been read. +* +* \retval TRUE +* \retval FALSE +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevRegRead(IN struct GLUE_INFO *prGlueInfo, IN uint32_t u4Register, OUT uint32_t *pu4Value) +{ + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + ASSERT(pu4Value); + + /* 0. acquire spinlock */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + /* 1. I/O stuff */ + kalDevRegRead_impl(prGlueInfo, u4Register, pu4Value); + + /* 2. release spin lock */ + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to write a 32 bit register value to device. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u4Register The register offset. +* \param[out] u4Value The 32-bit value of the register to be written. +* +* \retval TRUE +* \retval FALSE +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevRegWrite(struct GLUE_INFO *prGlueInfo, IN uint32_t u4Register, IN uint32_t u4Value) +{ + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + /* 0. acquire spinlock */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + /* 1. I/O stuff */ + kalDevRegWrite_impl(prGlueInfo, u4Register, u4Value); + + /* 2. release spin lock */ + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to read port data from device in unit of byte. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u2Port The register offset. +* \param[in] u2Len The number of byte to be read. +* \param[out] pucBuf Pointer to data buffer for read +* \param[in] u2ValidOutBufSize Length of the buffer valid to be accessed +* +* \retval TRUE +* \retval FALSE +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t +kalDevPortRead(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port, IN uint16_t u2Len, OUT uint8_t *pucBuf, IN uint16_t u2ValidOutBufSize) +{ + uint32_t i; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + /* 0. acquire spinlock */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + /* 1. indicate correct length to HIFSYS if larger than 4-bytes */ + if (u2Len > 4) + kalDevRegWrite_impl(prGlueInfo, MCR_EHTCR, ALIGN_4(u2Len)); + + /* 2. address cycle */ +#if EHPI16 + writew(u2Port, prGlueInfo->rHifInfo.mcr_addr_base); +#elif EHPI8 + writew((u2Port & 0xFF), prGlueInfo->rHifInfo.mcr_addr_base); + writew(((u2Port & 0xFF00) >> 8), prGlueInfo->rHifInfo.mcr_addr_base); +#endif + + /* 3. data cycle */ + for (i = 0; i < ALIGN_4(u2Len); i += 4) { +#if EHPI16 + *((uint16_t *)&(pucBuf[i])) = (uint16_t) (readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFFFF); + *((uint16_t *)&(pucBuf[i + 2])) = (uint16_t) (readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFFFF); +#elif EHPI8 + *((uint8_t *)&(pucBuf[i])) = (uint8_t) (readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF); + *((uint8_t *)&(pucBuf[i + 1])) = (uint8_t) (readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF); + *((uint8_t *)&(pucBuf[i + 2])) = (uint8_t) (readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF); + *((uint8_t *)&(pucBuf[i + 3])) = (uint8_t) (readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF); +#endif + } + + /* 4. restore length to 4 if necessary */ + if (u2Len > 4) + kalDevRegWrite_impl(prGlueInfo, MCR_EHTCR, 4); + + /* 5. release spin lock */ + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to write port data to device in unit of byte. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u2Port The register offset. +* \param[in] u2Len The number of byte to be write. +* \param[out] pucBuf Pointer to data buffer for write +* \param[in] u2ValidOutBufSize Length of the buffer valid to be accessed +* +* \retval TRUE +* \retval FALSE +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t +kalDevPortWrite(struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port, IN uint16_t u2Len, IN uint8_t *pucBuf, IN uint16_t u2ValidInBufSize) +{ + uint32_t i; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + /* 0. acquire spinlock */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + /* 1. indicate correct length to HIFSYS if larger than 4-bytes */ + if (u2Len > 4) + kalDevRegWrite_impl(prGlueInfo, MCR_EHTCR, ALIGN_4(u2Len)); + + /* 2. address cycle */ +#if EHPI16 + writew(u2Port, prGlueInfo->rHifInfo.mcr_addr_base); +#elif EHPI8 + writew((u2Port & 0xFF), prGlueInfo->rHifInfo.mcr_addr_base); + writew(((u2Port & 0xFF00) >> 8), prGlueInfo->rHifInfo.mcr_addr_base); +#endif + + /* 3. data cycle */ + for (i = 0; i < ALIGN_4(u2Len); i += 4) { +#if EHPI16 + writew((uint32_t) (*((uint16_t *)&(pucBuf[i]))), prGlueInfo->rHifInfo.mcr_data_base); + writew((uint32_t) (*((uint16_t *)&(pucBuf[i + 2]))), prGlueInfo->rHifInfo.mcr_data_base); +#elif EHPI8 + writew((uint32_t) (*((uint8_t *)&(pucBuf[i]))), prGlueInfo->rHifInfo.mcr_data_base); + writew((uint32_t) (*((uint8_t *)&(pucBuf[i + 1]))), prGlueInfo->rHifInfo.mcr_data_base); + writew((uint32_t) (*((uint8_t *)&(pucBuf[i + 2]))), prGlueInfo->rHifInfo.mcr_data_base); + writew((uint32_t) (*((uint8_t *)&(pucBuf[i + 3]))), prGlueInfo->rHifInfo.mcr_data_base); +#endif + } + + /* 4. restore length to 4 if necessary */ + if (u2Len > 4) + kalDevRegWrite_impl(prGlueInfo, MCR_EHTCR, 4); + + /* 5. release spin lock */ + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write device I/O port with single byte (for SDIO compatibility) +* +* \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 +* \param[in] u4ValidInBufSize Length of the buffer valid to be accessed +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevWriteWithSdioCmd52(IN struct GLUE_INFO *prGlueInfo, IN uint32_t u4Addr, IN uint8_t ucData) +{ + uint32_t u4RegValue; + u_int8_t bRet; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + /* 0. acquire spinlock */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + /* 1. there is no single byte access support for eHPI, use 4-bytes write-after-read approach instead */ + if (kalDevRegRead_impl(prGlueInfo, u4Addr, &u4RegValue) == TRUE) { + u4RegValue &= 0x00; + u4RegValue |= ucData; + + bRet = kalDevRegWrite_impl(prGlueInfo, u4Addr, u4RegValue); + } else { + bRet = FALSE; + } + + /* 2. release spin lock */ + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + return bRet; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to read a 32 bit register value from device +* without spin lock protection and dedicated for internal use +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u4Register The register offset. +* \param[out] pu4Value Pointer to the 32-bit value of the register been read. +* +* \retval TRUE +* \retval FALSE +*/ +/*----------------------------------------------------------------------------*/ +static u_int8_t kalDevRegRead_impl(IN struct GLUE_INFO *prGlueInfo, IN uint32_t u4Register, OUT uint32_t *pu4Value) +{ + ASSERT(prGlueInfo); + + /* 1. address cycle */ +#if EHPI16 + writew(u4Register, prGlueInfo->rHifInfo.mcr_addr_base); +#elif EHPI8 + writew((u4Register & 0xFF), prGlueInfo->rHifInfo.mcr_addr_base); + writew(((u4Register & 0xFF00) >> 8), prGlueInfo->rHifInfo.mcr_addr_base); +#endif + + /* 2. data cycle */ +#if EHPI16 + *pu4Value = (readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFFFF); + *pu4Value |= ((readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFFFF) << 16); +#elif EHPI8 + *pu4Value = (readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF); + *pu4Value |= ((readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF) << 8); + *pu4Value |= ((readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF) << 16); + *pu4Value |= ((readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF) << 24); +#endif + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to write a 32 bit register value to device. +* without spin lock protection and dedicated for internal use +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u4Register The register offset. +* \param[out] u4Value The 32-bit value of the register to be written. +* +* \retval TRUE +* \retval FALSE +*/ +/*----------------------------------------------------------------------------*/ +static u_int8_t kalDevRegWrite_impl(IN struct GLUE_INFO *prGlueInfo, IN uint32_t u4Register, IN uint32_t u4Value) +{ + ASSERT(prGlueInfo); + + /* 1. address cycle */ +#if EHPI16 + writew(u4Register, prGlueInfo->rHifInfo.mcr_addr_base); +#elif EHPI8 + writew((u4Register & 0xFF), prGlueInfo->rHifInfo.mcr_addr_base); + writew(((u4Register & 0xFF00) >> 8), prGlueInfo->rHifInfo.mcr_addr_base); +#endif + + /* 2. data cycle */ +#if EHPI16 + writew(u4Value, prGlueInfo->rHifInfo.mcr_data_base); + writew((u4Value & 0xFFFF0000) >> 16, prGlueInfo->rHifInfo.mcr_data_base); +#elif EHPI8 + writew((u4Value & 0x000000FF), prGlueInfo->rHifInfo.mcr_data_base); + writew((u4Value & 0x0000FF00) >> 8, prGlueInfo->rHifInfo.mcr_data_base); + writew((u4Value & 0x00FF0000) >> 16, prGlueInfo->rHifInfo.mcr_data_base); + writew((u4Value & 0xFF000000) >> 24, prGlueInfo->rHifInfo.mcr_data_base); +#endif + + return TRUE; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/ehpi/include/colibri.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/ehpi/include/colibri.h new file mode 100644 index 0000000000000..a877b79d8fa96 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/ehpi/include/colibri.h @@ -0,0 +1,190 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/ehpi/include/colibri.h#1 +*/ + +/*! \file "colibri.h" +* \brief This file contains colibri BSP configuration based on eHPI interface +* +* N/A +*/ + +#ifndef _COLIBRI_H +#define _COLIBRI_H +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include +#include +#include +#include +#include + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define WLAN_STA_IRQ_GPIO 23 /* use SSP_EXTCLK as interrupt source */ +#define WLAN_STA_IRQ IRQ_GPIO(WLAN_STA_IRQ_GPIO) + +#define MSC_CS(cs, val) ((val)<<(((cs)&1)<<4)) + +#define MSC_RBUFF_SHIFT 15 +#define MSC_RBUFF(x) ((x)< +#ifndef CONFIG_X86 +#include +#endif + +#include "mt66xx_reg.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +#define MTK_PCI_VENDOR_ID 0x14C3 +#define NIC6632_PCIe_DEVICE_ID 0x6632 +#define NIC7668_PCIe_DEVICE_ID 0x7668 +#define MT7663_PCI_PFGA2_VENDOR_ID 0x0E8D +#define NIC7663_PCIe_DEVICE_ID 0x7663 +#define CONNAC_PCI_VENDOR_ID 0x0E8D +#define CONNAC_PCIe_DEVICE_ID 0x3280 +#define NIC7915_PCIe_DEVICE_ID 0x7915 +#define NICSOC3_0_PCIe_DEVICE_ID 0x0789 +#define NIC7961_PCIe_DEVICE_ID 0x7961 + +static const struct pci_device_id mtk_pci_ids[] = { +#ifdef MT6632 + { PCI_DEVICE(MTK_PCI_VENDOR_ID, NIC6632_PCIe_DEVICE_ID), + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_mt6632}, +#endif /* MT6632 */ +#ifdef MT7668 + { PCI_DEVICE(MTK_PCI_VENDOR_ID, NIC7668_PCIe_DEVICE_ID), + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_mt7668}, +#endif /* MT7668 */ +#ifdef MT7663 + { PCI_DEVICE(MTK_PCI_VENDOR_ID, NIC7663_PCIe_DEVICE_ID), + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_mt7663}, + /* For FPGA2 temparay */ + { PCI_DEVICE(MT7663_PCI_PFGA2_VENDOR_ID, NIC7663_PCIe_DEVICE_ID), + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_mt7663}, +#endif /* MT7663 */ +#ifdef CONNAC + { PCI_DEVICE(CONNAC_PCI_VENDOR_ID, CONNAC_PCIe_DEVICE_ID), + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_connac}, +#endif /* CONNAC */ +#ifdef CONNAC2X2 + { PCI_DEVICE(CONNAC_PCI_VENDOR_ID, CONNAC_PCIe_DEVICE_ID), + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_connac2x2}, +#endif /* CONNAC */ +#ifdef MT7915 + { PCI_DEVICE(MTK_PCI_VENDOR_ID, NIC7915_PCIe_DEVICE_ID), + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_mt7915}, +#endif /* MT7915 */ +#ifdef SOC3_0 + { PCI_DEVICE(MTK_PCI_VENDOR_ID, NICSOC3_0_PCIe_DEVICE_ID), + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_soc3_0 }, +#endif /* SOC3_0 */ +#ifdef MT7961 + { PCI_DEVICE(MTK_PCI_VENDOR_ID, NIC7961_PCIe_DEVICE_ID), + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_mt7961}, +#endif /* MT7961 */ + { /* end: all zeroes */ }, +}; + +MODULE_DEVICE_TABLE(pci, mtk_pci_ids); + +/******************************************************************************* + * 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 probe_card pfWlanProbe; +static remove_card pfWlanRemove; + +static struct pci_driver mtk_pci_driver = { + .name = "wlan", + .id_table = mtk_pci_ids, + .probe = NULL, + .remove = NULL, +}; + +static u_int8_t g_fgDriverProbed = FALSE; +static uint32_t g_u4DmaMask = 32; +/******************************************************************************* + * M A 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 pcieAllocDesc(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing, + uint32_t u4Num); +static void *pcieAllocRxBuf(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDmaBuf, + uint32_t u4Num, uint32_t u4Idx); +static void pcieAllocTxDataBuf(struct MSDU_TOKEN_ENTRY *prToken, + uint32_t u4Idx); +static void *pcieAllocRuntimeMem(uint32_t u4SrcLen); +static bool pcieCopyCmd(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *prTxCell, void *pucBuf, + void *pucSrc1, uint32_t u4SrcLen1, + void *pucSrc2, uint32_t u4SrcLen2); +static bool pcieCopyEvent(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *pRxCell, + struct RXD_STRUCT *pRxD, + struct RTMP_DMABUF *prDmaBuf, + uint8_t *pucDst, uint32_t u4Len); +static bool pcieCopyTxData(struct MSDU_TOKEN_ENTRY *prToken, + void *pucSrc, uint32_t u4Len); +static bool pcieCopyRxData(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *pRxCell, + struct RTMP_DMABUF *prDmaBuf, + struct SW_RFB *prSwRfb); +static phys_addr_t pcieMapTxBuf(struct GL_HIF_INFO *prHifInfo, + void *pucBuf, uint32_t u4Offset, uint32_t u4Len); +static phys_addr_t pcieMapRxBuf(struct GL_HIF_INFO *prHifInfo, + void *pucBuf, uint32_t u4Offset, uint32_t u4Len); +static void pcieUnmapTxBuf(struct GL_HIF_INFO *prHifInfo, + phys_addr_t rDmaAddr, uint32_t u4Len); +static void pcieUnmapRxBuf(struct GL_HIF_INFO *prHifInfo, + phys_addr_t rDmaAddr, uint32_t u4Len); +static void pcieFreeDesc(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing); +static void pcieFreeBuf(void *pucSrc, uint32_t u4Len); +static void pcieFreePacket(void *pvPacket); +static void pcieDumpTx(struct GL_HIF_INFO *prHifInfo, + struct RTMP_TX_RING *prTxRing, + uint32_t u4Idx, uint32_t u4DumpLen); +static void pcieDumpRx(struct GL_HIF_INFO *prHifInfo, + struct RTMP_RX_RING *prRxRing, + uint32_t u4Idx, uint32_t u4DumpLen); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is a PCIE interrupt callback function + * + * \param[in] func pointer to PCIE handle + * + * \return void + */ +/*----------------------------------------------------------------------------*/ +static void *CSRBaseAddress; + +static irqreturn_t mtk_pci_interrupt(int irq, void *dev_instance) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) dev_instance; + if (!prGlueInfo) { + DBGLOG(HAL, INFO, "No glue info in mtk_pci_interrupt()\n"); + return IRQ_NONE; + } + + halDisableInterrupt(prGlueInfo->prAdapter); + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(HAL, INFO, "GLUE_FLAG_HALT skip INT\n"); + return IRQ_NONE; + } + + kalSetIntEvent(prGlueInfo); + + return IRQ_HANDLED; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is a PCIE probe function + * + * \param[in] func pointer to PCIE handle + * \param[in] id pointer to PCIE device id table + * + * \return void + */ +/*----------------------------------------------------------------------------*/ +static int mtk_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + int ret = 0; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(pdev); + ASSERT(id); + + ret = pci_enable_device(pdev); + + if (ret) { + DBGLOG(INIT, INFO, "pci_enable_device failed!\n"); + goto out; + } + +#if defined(SOC3_0) + if ((void *)&mt66xx_driver_data_soc3_0 == (void *)id->driver_data) + DBGLOG(INIT, INFO, + "[MJ]&mt66xx_driver_data_soc3_0 == id->driver_data\n"); +#endif + + DBGLOG(INIT, INFO, "pci_enable_device done!\n"); + + prChipInfo = ((struct mt66xx_hif_driver_data *) + id->driver_data)->chip_info; + prChipInfo->pdev = (void *)pdev; + +#if (CFG_POWER_ON_DOWNLOAD_EMI_ROM_PATCH == 1) + g_fgDriverProbed = TRUE; + g_u4DmaMask = prChipInfo->bus_info->u4DmaMask; +#else + if (pfWlanProbe((void *) pdev, + (void *) id->driver_data) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "pfWlanProbe fail!call pfWlanRemove()\n"); + pfWlanRemove(); + ret = -1; + } else { + g_fgDriverProbed = TRUE; + g_u4DmaMask = prChipInfo->bus_info->u4DmaMask; + } +#endif + +out: + DBGLOG(INIT, INFO, "mtk_pci_probe() done(%d)\n", ret); + + return ret; +} + +static void mtk_pci_remove(struct pci_dev *pdev) +{ + ASSERT(pdev); + + if (g_fgDriverProbed) + pfWlanRemove(); + DBGLOG(INIT, INFO, "pfWlanRemove done\n"); + + /* Unmap CSR base address */ + iounmap(CSRBaseAddress); + + /* release memory region */ + pci_release_regions(pdev); + + pci_disable_device(pdev); + DBGLOG(INIT, INFO, "mtk_pci_remove() done\n"); +} + +static int mtk_pci_suspend(struct pci_dev *pdev, pm_message_t state) +{ + return 0; +} + +int mtk_pci_resume(struct pci_dev *pdev) +{ + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will register pci 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 pci bus + */ +/*----------------------------------------------------------------------------*/ +uint32_t glRegisterBus(probe_card pfProbe, remove_card pfRemove) +{ + int ret = 0; + + ASSERT(pfProbe); + ASSERT(pfRemove); + + pfWlanProbe = pfProbe; + pfWlanRemove = pfRemove; + + mtk_pci_driver.probe = mtk_pci_probe; + mtk_pci_driver.remove = mtk_pci_remove; + + mtk_pci_driver.suspend = mtk_pci_suspend; + mtk_pci_driver.resume = mtk_pci_resume; + + ret = (pci_register_driver(&mtk_pci_driver) == 0) ? + WLAN_STATUS_SUCCESS : WLAN_STATUS_FAILURE; + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will unregister pci bus to the os + * + * \param[in] pfRemove Function pointer to remove card + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void glUnregisterBus(remove_card pfRemove) +{ + if (g_fgDriverProbed) { + pfRemove(); + g_fgDriverProbed = FALSE; + } + pci_unregister_driver(&mtk_pci_driver); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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(struct GLUE_INFO *prGlueInfo, unsigned long ulCookie) +{ + struct GL_HIF_INFO *prHif = NULL; + struct HIF_MEM_OPS *prMemOps; + + prHif = &prGlueInfo->rHifInfo; + + prHif->pdev = (struct pci_dev *)ulCookie; + prMemOps = &prHif->rMemOps; + prHif->prDmaDev = prHif->pdev; + + prHif->CSRBaseAddress = CSRBaseAddress; + + pci_set_drvdata(prHif->pdev, prGlueInfo); + + SET_NETDEV_DEV(prGlueInfo->prDevHandler, &prHif->pdev->dev); + + prGlueInfo->u4InfType = MT_DEV_INF_PCIE; + + prMemOps->allocTxDesc = pcieAllocDesc; + prMemOps->allocRxDesc = pcieAllocDesc; + prMemOps->allocTxCmdBuf = NULL; + prMemOps->allocTxDataBuf = pcieAllocTxDataBuf; + prMemOps->allocRxBuf = pcieAllocRxBuf; + prMemOps->allocRuntimeMem = pcieAllocRuntimeMem; + prMemOps->copyCmd = pcieCopyCmd; + prMemOps->copyEvent = pcieCopyEvent; + prMemOps->copyTxData = pcieCopyTxData; + prMemOps->copyRxData = pcieCopyRxData; + prMemOps->mapTxBuf = pcieMapTxBuf; + prMemOps->mapRxBuf = pcieMapRxBuf; + prMemOps->unmapTxBuf = pcieUnmapTxBuf; + prMemOps->unmapRxBuf = pcieUnmapRxBuf; + prMemOps->freeDesc = pcieFreeDesc; + prMemOps->freeBuf = pcieFreeBuf; + prMemOps->freePacket = pcieFreePacket; + prMemOps->dumpTx = pcieDumpTx; + prMemOps->dumpRx = pcieDumpRx; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function clears hif related info. + * + * \param[in] prGlueInfo Pointer to glue info structure + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void glClearHifInfo(struct GLUE_INFO *prGlueInfo) +{ +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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) + */ +/*----------------------------------------------------------------------------*/ +u_int8_t glBusInit(void *pvData) +{ + int ret = 0; + struct pci_dev *pdev = NULL; + + ASSERT(pvData); + + pdev = (struct pci_dev *)pvData; + + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(g_u4DmaMask)); + if (ret != 0) { + DBGLOG(INIT, INFO, "set DMA mask failed!errno=%d\n", ret); + return FALSE; + } + + ret = pci_request_regions(pdev, pci_name(pdev)); + if (ret != 0) { + DBGLOG(INIT, INFO, + "Request PCI resource failed, errno=%d!\n", ret); + } + + /* map physical address to virtual address for accessing register */ + CSRBaseAddress = ioremap(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + DBGLOG(INIT, INFO, "ioremap for device %s, region 0x%lX @ 0x%lX\n", + pci_name(pdev), (unsigned long) pci_resource_len(pdev, 0), + (unsigned long) pci_resource_start(pdev, 0)); + if (!CSRBaseAddress) { + DBGLOG(INIT, INFO, + "ioremap failed for device %s, region 0x%lX @ 0x%lX\n", + pci_name(pdev), + (unsigned long) pci_resource_len(pdev, 0), + (unsigned long) pci_resource_start(pdev, 0)); + goto err_out_free_res; + } + + /* Set DMA master */ + pci_set_master(pdev); + + return TRUE; + +err_out_free_res: + pci_release_regions(pdev); + + pci_disable_device(pdev); + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Stop bus operation and release resources. + * + * \param[in] pvData A pointer to struct net_device. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void glBusRelease(void *pvData) +{ +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +int32_t glBusSetIrq(void *pvData, void *pfnIsr, void *pvCookie) +{ + struct BUS_INFO *prBusInfo; + struct net_device *prNetDevice = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct GL_HIF_INFO *prHifInfo = NULL; + struct pci_dev *pdev = NULL; + int ret = 0; + + ASSERT(pvData); + if (!pvData) + return -1; + + prNetDevice = (struct net_device *)pvData; + prGlueInfo = (struct GLUE_INFO *)pvCookie; + ASSERT(prGlueInfo); + if (!prGlueInfo) + return -1; + + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + + prHifInfo = &prGlueInfo->rHifInfo; + pdev = prHifInfo->pdev; + + prHifInfo->u4IrqId = pdev->irq; + ret = request_irq(prHifInfo->u4IrqId, mtk_pci_interrupt, + IRQF_SHARED, prNetDevice->name, prGlueInfo); + if (ret != 0) + DBGLOG(INIT, INFO, + "glBusSetIrq: request_irq ERROR(%d)\n", ret); + else if (prBusInfo->initPcieInt) + prBusInfo->initPcieInt(prGlueInfo); + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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(void *pvData, void *pvCookie) +{ + struct net_device *prNetDevice = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct GL_HIF_INFO *prHifInfo = NULL; + struct pci_dev *pdev = NULL; + + ASSERT(pvData); + if (!pvData) { + DBGLOG(INIT, INFO, "%s null pvData\n", __func__); + return; + } + prNetDevice = (struct net_device *)pvData; + prGlueInfo = (struct GLUE_INFO *) pvCookie; + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(INIT, INFO, "%s no glue info\n", __func__); + return; + } + + prHifInfo = &prGlueInfo->rHifInfo; + pdev = prHifInfo->pdev; + + synchronize_irq(pdev->irq); + free_irq(pdev->irq, prGlueInfo); +} + +u_int8_t glIsReadClearReg(uint32_t u4Address) +{ + return TRUE; +} + +void glSetPowerState(IN struct GLUE_INFO *prGlueInfo, IN uint32_t ePowerMode) +{ +} + +void glGetDev(void *ctx, struct device **dev) +{ + + *dev = &((struct pci_dev *)ctx)->dev; +} + +void glGetHifDev(struct GL_HIF_INFO *prHif, struct device **dev) +{ + *dev = &(prHif->pdev->dev); +} + +static void pcieAllocDesc(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing, + uint32_t u4Num) +{ + dma_addr_t rAddr; + + prDescRing->AllocVa = KAL_DMA_ALLOC_COHERENT( + prHifInfo->prDmaDev, prDescRing->AllocSize, &rAddr); + prDescRing->AllocPa = (phys_addr_t)rAddr; + if (prDescRing->AllocVa) + memset(prDescRing->AllocVa, 0, prDescRing->AllocSize); +} + +static void pcieAllocTxDataBuf(struct MSDU_TOKEN_ENTRY *prToken, uint32_t u4Idx) +{ + prToken->prPacket = kalMemAlloc(prToken->u4DmaLength, PHY_MEM_TYPE); + prToken->rDmaAddr = 0; +} + +static void *pcieAllocRxBuf(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDmaBuf, + uint32_t u4Num, uint32_t u4Idx) +{ + struct sk_buff *pkt = dev_alloc_skb(prDmaBuf->AllocSize); + dma_addr_t rAddr; + + if (!pkt) { + DBGLOG(HAL, ERROR, "can't allocate rx %lu size packet\n", + prDmaBuf->AllocSize); + prDmaBuf->AllocPa = 0; + prDmaBuf->AllocVa = NULL; + return NULL; + } + + prDmaBuf->AllocVa = (void *)pkt->data; + memset(prDmaBuf->AllocVa, 0, prDmaBuf->AllocSize); + + rAddr = KAL_DMA_MAP_SINGLE(prHifInfo->prDmaDev, prDmaBuf->AllocVa, + prDmaBuf->AllocSize, KAL_DMA_FROM_DEVICE); + if (KAL_DMA_MAPPING_ERROR(prHifInfo->prDmaDev, rAddr)) { + DBGLOG(HAL, ERROR, "sk_buff dma mapping error!\n"); + dev_kfree_skb(pkt); + return NULL; + } + prDmaBuf->AllocPa = (phys_addr_t)rAddr; + return (void *)pkt; +} + +static void *pcieAllocRuntimeMem(uint32_t u4SrcLen) +{ + return kalMemAlloc(u4SrcLen, PHY_MEM_TYPE); +} + +static bool pcieCopyCmd(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *prTxCell, void *pucBuf, + void *pucSrc1, uint32_t u4SrcLen1, + void *pucSrc2, uint32_t u4SrcLen2) +{ + dma_addr_t rAddr; + uint32_t u4TotalLen = u4SrcLen1 + u4SrcLen2; + + prTxCell->pBuffer = pucBuf; + + memcpy(pucBuf, pucSrc1, u4SrcLen1); + if (pucSrc2 != NULL && u4SrcLen2 > 0) + memcpy(pucBuf + u4SrcLen1, pucSrc2, u4SrcLen2); + rAddr = KAL_DMA_MAP_SINGLE(prHifInfo->prDmaDev, pucBuf, + u4TotalLen, KAL_DMA_TO_DEVICE); + if (KAL_DMA_MAPPING_ERROR(prHifInfo->prDmaDev, rAddr)) { + DBGLOG(HAL, ERROR, "KAL_DMA_MAP_SINGLE() error!\n"); + return false; + } + + prTxCell->PacketPa = (phys_addr_t)rAddr; + + return true; +} + +static bool pcieCopyEvent(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *pRxCell, + struct RXD_STRUCT *pRxD, + struct RTMP_DMABUF *prDmaBuf, + uint8_t *pucDst, uint32_t u4Len) +{ + struct sk_buff *prSkb = NULL; + void *pRxPacket = NULL; + dma_addr_t rAddr; + + KAL_DMA_UNMAP_SINGLE(prHifInfo->prDmaDev, + (dma_addr_t)prDmaBuf->AllocPa, + prDmaBuf->AllocSize, KAL_DMA_FROM_DEVICE); + + pRxPacket = pRxCell->pPacket; + ASSERT(pRxPacket) + + prSkb = (struct sk_buff *)pRxPacket; + memcpy(pucDst, (uint8_t *)prSkb->data, u4Len); + + prDmaBuf->AllocVa = ((struct sk_buff *)pRxCell->pPacket)->data; + rAddr = KAL_DMA_MAP_SINGLE(prHifInfo->prDmaDev, prDmaBuf->AllocVa, + prDmaBuf->AllocSize, KAL_DMA_FROM_DEVICE); + if (KAL_DMA_MAPPING_ERROR(prHifInfo->prDmaDev, rAddr)) { + DBGLOG(HAL, ERROR, "KAL_DMA_MAP_SINGLE() error!\n"); + return false; + } + prDmaBuf->AllocPa = (phys_addr_t)rAddr; + return true; +} + +static bool pcieCopyTxData(struct MSDU_TOKEN_ENTRY *prToken, + void *pucSrc, uint32_t u4Len) +{ + memcpy(prToken->prPacket, pucSrc, u4Len); + return true; +} + +static bool pcieCopyRxData(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *pRxCell, + struct RTMP_DMABUF *prDmaBuf, + struct SW_RFB *prSwRfb) +{ + void *pRxPacket = NULL; + dma_addr_t rAddr; + + pRxPacket = pRxCell->pPacket; + ASSERT(pRxPacket); + + pRxCell->pPacket = prSwRfb->pvPacket; + + KAL_DMA_UNMAP_SINGLE(prHifInfo->prDmaDev, + (dma_addr_t)prDmaBuf->AllocPa, + prDmaBuf->AllocSize, KAL_DMA_FROM_DEVICE); + prSwRfb->pvPacket = pRxPacket; + + prDmaBuf->AllocVa = ((struct sk_buff *)pRxCell->pPacket)->data; + rAddr = KAL_DMA_MAP_SINGLE(prHifInfo->prDmaDev, + prDmaBuf->AllocVa, prDmaBuf->AllocSize, KAL_DMA_FROM_DEVICE); + if (KAL_DMA_MAPPING_ERROR(prHifInfo->prDmaDev, rAddr)) { + DBGLOG(HAL, ERROR, "KAL_DMA_MAP_SINGLE() error!\n"); + ASSERT(0); + return false; + } + prDmaBuf->AllocPa = (phys_addr_t)rAddr; + + return true; +} + +static phys_addr_t pcieMapTxBuf(struct GL_HIF_INFO *prHifInfo, + void *pucBuf, uint32_t u4Offset, uint32_t u4Len) +{ + dma_addr_t rDmaAddr; + + rDmaAddr = KAL_DMA_MAP_SINGLE(prHifInfo->prDmaDev, pucBuf + u4Offset, + u4Len, KAL_DMA_TO_DEVICE); + if (KAL_DMA_MAPPING_ERROR(prHifInfo->prDmaDev, rDmaAddr)) { + DBGLOG(HAL, ERROR, "KAL_DMA_MAP_SINGLE() error!\n"); + return 0; + } + + return (phys_addr_t)rDmaAddr; +} + +static phys_addr_t pcieMapRxBuf(struct GL_HIF_INFO *prHifInfo, + void *pucBuf, uint32_t u4Offset, uint32_t u4Len) +{ + dma_addr_t rDmaAddr; + + rDmaAddr = KAL_DMA_MAP_SINGLE(prHifInfo->prDmaDev, pucBuf + u4Offset, + u4Len, KAL_DMA_FROM_DEVICE); + if (KAL_DMA_MAPPING_ERROR(prHifInfo->prDmaDev, rDmaAddr)) { + DBGLOG(HAL, ERROR, "KAL_DMA_MAP_SINGLE() error!\n"); + return 0; + } + + return (phys_addr_t)rDmaAddr; +} + +static void pcieUnmapTxBuf(struct GL_HIF_INFO *prHifInfo, + phys_addr_t rDmaAddr, uint32_t u4Len) +{ + KAL_DMA_UNMAP_SINGLE(prHifInfo->prDmaDev, + (dma_addr_t)rDmaAddr, + u4Len, KAL_DMA_TO_DEVICE); +} + +static void pcieUnmapRxBuf(struct GL_HIF_INFO *prHifInfo, + phys_addr_t rDmaAddr, uint32_t u4Len) +{ + KAL_DMA_UNMAP_SINGLE(prHifInfo->prDmaDev, + (dma_addr_t)rDmaAddr, + u4Len, KAL_DMA_FROM_DEVICE); +} + +static void pcieFreeDesc(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing) +{ + if (prDescRing->AllocVa == NULL) + return; + + KAL_DMA_FREE_COHERENT(prHifInfo->prDmaDev, + prDescRing->AllocSize, + prDescRing->AllocVa, + (dma_addr_t)prDescRing->AllocPa); + memset(prDescRing, 0, sizeof(struct RTMP_DMABUF)); +} + +static void pcieFreeBuf(void *pucSrc, uint32_t u4Len) +{ + kalMemFree(pucSrc, PHY_MEM_TYPE, u4Len); +} + +static void pcieFreePacket(void *pvPacket) +{ + kalPacketFree(NULL, pvPacket); +} + +static void pcieDumpTx(struct GL_HIF_INFO *prHifInfo, + struct RTMP_TX_RING *prTxRing, + uint32_t u4Idx, uint32_t u4DumpLen) +{ + struct RTMP_DMACB *prTxCell; + void *prAddr = NULL; + + prTxCell = &prTxRing->Cell[u4Idx]; + + if (prTxCell->prToken) + prAddr = prTxCell->prToken->prPacket; + else + prAddr = prTxCell->pBuffer; + + if (prAddr) + DBGLOG_MEM32(HAL, INFO, prAddr, u4DumpLen); +} + +static void pcieDumpRx(struct GL_HIF_INFO *prHifInfo, + struct RTMP_RX_RING *prRxRing, + uint32_t u4Idx, uint32_t u4DumpLen) +{ + struct RTMP_DMACB *prRxCell; + struct RTMP_DMABUF *prDmaBuf; + + prRxCell = &prRxRing->Cell[u4Idx]; + prDmaBuf = &prRxCell->DmaBuf; + + if (!prRxCell->pPacket) + return; + + pcieUnmapRxBuf(prHifInfo, prDmaBuf->AllocPa, prDmaBuf->AllocSize); + + DBGLOG_MEM32(HAL, INFO, ((struct sk_buff *)prRxCell->pPacket)->data, + u4DumpLen); + + prDmaBuf->AllocPa = pcieMapRxBuf(prHifInfo, prDmaBuf->AllocVa, + 0, prDmaBuf->AllocSize); +} + +#if CFG_CHIP_RESET_SUPPORT +void kalRemoveProbe(IN struct GLUE_INFO *prGlueInfo) +{ + DBGLOG(INIT, WARN, "[SER][L0] not support...\n"); +} +#endif + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/arm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/arm.c new file mode 100644 index 0000000000000..7cbc34e29cdef --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/arm.c @@ -0,0 +1,62 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** +*[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. +******************************************************************************/ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/hal_api.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/hal_api.c new file mode 100644 index 0000000000000..5b8d5edad2cec --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/hal_api.c @@ -0,0 +1,2940 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** +*[File] hif_api.c +*[Version] v1.0 +*[Revision Date] 2015-09-08 +*[Author] +*[Description] +* The program provides SDIO HIF APIs +*[Copyright] +* Copyright (C) 2015 MediaTek Incorporation. All Rights Reserved. +******************************************************************************/ + +/******************************************************************************* +* C O M P I L E 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 MTK_WCN_HIF_SDIO +#include "hif_sdio.h" +#else +#include +#include +#include +#include /* sdio_readl(), etc */ +#include +#endif + +#include +#ifndef CONFIG_X86 +#include +#endif + +#include "mt66xx_reg.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define RX_RESPONSE_TIMEOUT (3000) + +/******************************************************************************* +* 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 +******************************************************************************** +*/ +/* + *TX Done Counter Layout + * + * enum HIF_TX_COUNT_IDX_T { + * + * /==== First WMM ====/ + * + * HIF_TXC_IDX_0, ==>AC0 PSE + * HIF_TXC_IDX_1, ==>AC1 PSE + * HIF_TXC_IDX_2, ==>AC2 PSE + * HIF_TXC_IDX_3, ==>AC3 PLE + * HIF_TXC_IDX_4, ==>CPU PSE + * HIF_TXC_IDX_5, ==>AC0 PLE + * HIF_TXC_IDX_6, ==>AC1 PLE + * HIF_TXC_IDX_7, ==>AC2 PLE + * HIF_TXC_IDX_8, ==>AC3 PLE + * + * /==== Second WMM ====/ + * + * HIF_TXC_IDX_9, ==>AC10, AC11 PSE + * HIF_TXC_IDX_10, ==> AC12 PSE + * HIF_TXC_IDX_11, ==>AC13 PSE + * HIF_TXC_IDX_12, ==>AC10, AC11 PLE + * HIF_TXC_IDX_13, ==>AC12 PLE + * HIF_TXC_IDX_14, ==>Reservec + * HIF_TXC_IDX_15, ==>AC13 PLE + * }; +*/ +#define HIF_TXC_IDX_2_TC_IDX_PSE(hif_idx) (hif_idx) +#define HIF_TXC_IDX_2_TC_IDX_PLE(hif_idx) (hif_idx - HIF_TXC_IDX_5) +#define TC_IDX_PSE_2_HIF_TXC_IDX(ucTc) (ucTc) +#define TC_IDX_PLE_2_HIF_TXC_IDX(ucTc) (ucTc + HIF_TXC_IDX_5) + +/******************************************************************************* +* 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 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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t halVerifyChipID(IN struct ADAPTER *prAdapter) +{ + uint32_t u4CIR = 0; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + + if (prAdapter->fgIsReadRevID) + return TRUE; + + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4CIR); + + DBGLOG(INIT, TRACE, "Chip ID: 0x%lx\n", u4CIR & WCIR_CHIP_ID); + DBGLOG(INIT, TRACE, "Revision ID: 0x%lx\n", ((u4CIR & WCIR_REVISION_ID) >> 16)); + + prChipInfo = prAdapter->chip_info; + + if ((u4CIR & WCIR_CHIP_ID) != prChipInfo->chip_id) + return FALSE; + + prAdapter->ucRevID = (uint8_t) (((u4CIR & WCIR_REVISION_ID) >> 16) & 0xF); + prAdapter->fgIsReadRevID = TRUE; + + return TRUE; +} + +uint32_t +halRxWaitResponse(IN struct ADAPTER *prAdapter, IN uint8_t ucPortIdx, OUT uint8_t *pucRspBuffer, + IN uint32_t u4MaxRespBufferLen, OUT uint32_t *pu4Length) +{ + struct mt66xx_chip_info *prChipInfo; + uint32_t u4Value = 0, u4PktLen = 0, i = 0, u4CpyLen; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + uint32_t u4Time, u4Current; + struct RX_CTRL *prRxCtrl; + struct WIFI_EVENT *prEvent; + + DEBUGFUNC("halRxWaitResponse"); + + ASSERT(prAdapter); + ASSERT(pucRspBuffer); + prChipInfo = prAdapter->chip_info; + + prRxCtrl = &prAdapter->rRxCtrl; + + u4Time = (uint32_t) kalGetTimeTick(); + + do { + /* Read the packet length */ + HAL_MCR_RD(prAdapter, MCR_WRPLR, &u4Value); + + if ((u4Value & 0xFFFF) != 0) { + u4PktLen = u4Value & 0xFFFF; + i = 0; + } else { + u4PktLen = (u4Value >> 16) & 0xFFFF; + i = 1; + } + + if (u4PktLen > u4MaxRespBufferLen) { + DBGLOG(RX, ERROR, "Packet length over buffer! Dump Response buffer, length = 0x%x\n", + *pu4Length); + prEvent = (struct WIFI_EVENT *) + (pucRspBuffer + prChipInfo->rxd_size); + DBGLOG(RX, ERROR, "RX EVENT: ID[0x%02X] SEQ[%u] LEN[%u]\n", + prEvent->ucEID, prEvent->ucSeqNum, prEvent->u2PacketLength); + DBGLOG_MEM8(RX, ERROR, pucRspBuffer, u4MaxRespBufferLen); + return WLAN_STATUS_FAILURE; + } + + if (u4PktLen == 0) { + /* timeout exceeding check */ + u4Current = (uint32_t) kalGetTimeTick(); + + if ((u4Current > u4Time) && ((u4Current - u4Time) > RX_RESPONSE_TIMEOUT)) { + DBGLOG(RX, ERROR, "Timeout! %d - %d = %d\n", u4Current, u4Time, (u4Current-u4Time)); + return WLAN_STATUS_FAILURE; + } else if (u4Current < u4Time && ((u4Current + (0xFFFFFFFF - u4Time)) > RX_RESPONSE_TIMEOUT)) { + DBGLOG(RX, ERROR, "Timeout! %d - %d = %d\n", + u4Current, u4Time, (u4Current + (0xFFFFFFFF - u4Time))); + return WLAN_STATUS_FAILURE; + } + + /* Response packet is not ready */ + kalUdelay(50); + } else { + +#if (CFG_ENABLE_READ_EXTRA_4_BYTES == 1) +#if CFG_SDIO_RX_AGG + /* decide copy length */ + if (u4PktLen > u4MaxRespBufferLen) + u4CpyLen = u4MaxRespBufferLen; + else + u4CpyLen = u4PktLen; + + /* read from SDIO to tmp. buffer */ + HAL_PORT_RD(prAdapter, i == 0 ? MCR_WRDR0 : MCR_WRDR1, + ALIGN_4(u4PktLen + 4), prRxCtrl->pucRxCoalescingBufPtr, + HIF_RX_COALESCING_BUFFER_SIZE); + + /* copy to destination buffer */ + kalMemCopy(pucRspBuffer, prRxCtrl->pucRxCoalescingBufPtr, u4CpyLen); + + /* update valid buffer count */ + u4PktLen = u4CpyLen; +#else +#error "Please turn on RX coalescing" +#endif +#else + HAL_PORT_RD(prAdapter, + i == 0 ? MCR_WRDR0 : MCR_WRDR1, u4PktLen, pucRspBuffer, u4MaxRespBufferLen); +#endif + *pu4Length = u4PktLen; + break; + } + } while (TRUE); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief enable global interrupt +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void halEnableInterrupt(IN struct ADAPTER *prAdapter) +{ + u_int8_t fgIsIntEnableCache, fgIsPendingInt; + + ASSERT(prAdapter); + fgIsIntEnableCache = prAdapter->fgIsIntEnable; + /* Not to enable interrupt if there is pending interrupt */ + fgIsPendingInt = prAdapter->prGlueInfo->rHifInfo.fgIsPendingInt; + + if (!fgIsPendingInt) + 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 if (!fgIsPendingInt) { + 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 && !fgIsPendingInt) + HAL_BYTE_WR(prAdapter, MCR_WHLPCR, WHLPCR_INT_EN_SET); + + if (fgIsPendingInt) + kalSetIntEvent(prAdapter->prGlueInfo); +} /* end of nicEnableInterrupt() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief disable global interrupt +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void halDisableInterrupt(IN struct ADAPTER *prAdapter) +{ + + ASSERT(prAdapter); + + HAL_BYTE_WR(prAdapter, MCR_WHLPCR, WHLPCR_INT_EN_CLR); + + prAdapter->fgIsIntEnable = FALSE; + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to process the POWER OFF procedure. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t halSetDriverOwn(IN struct ADAPTER *prAdapter) +{ + u_int8_t fgStatus = TRUE; + uint32_t i, j, u4CurrTick = 0, u4WriteTick, u4WriteTickTemp; + u_int8_t fgTimeout; + u_int8_t fgResult; + u_int8_t fgReady = FALSE; + uint32_t u4DriverOwnTime = 0, u4Cr4ReadyTime = 0; + struct GL_HIF_INFO *prHifInfo; + u_int8_t fgWmtCoreDump = FALSE; + + ASSERT(prAdapter); + + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_SET_OWN); + + GLUE_INC_REF_CNT(prAdapter->u4PwrCtrlBlockCnt); + + if (prAdapter->fgIsFwOwn == FALSE) + goto unlock; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + DBGLOG(INIT, TRACE, "DRIVER OWN\n"); + + u4WriteTick = 0; + u4CurrTick = kalGetTimeTick(); + i = 0; + j = 0; + + glWakeupSdio(prAdapter->prGlueInfo); + + while (1) { + HAL_LP_OWN_RD(prAdapter, &fgResult); + + if (TIME_BEFORE(kalGetTimeTick(), u4CurrTick)) { /* To prevent timer wraparound */ + fgTimeout = + ((kalGetTimeTick() + (~u4CurrTick)) > LP_OWN_BACK_TOTAL_DELAY_MS) ? TRUE : FALSE; + } else { + fgTimeout = + ((kalGetTimeTick() - u4CurrTick) > LP_OWN_BACK_TOTAL_DELAY_MS) ? TRUE : FALSE; + } + + if (fgResult) { + prAdapter->fgIsFwOwn = FALSE; + prAdapter->u4OwnFailedCount = 0; + prAdapter->u4OwnFailedLogCount = 0; + + if (nicSerIsWaitingReset(prAdapter)) { + /* SER is done, start Tx/Rx */ + nicSerStartTxRx(prAdapter); + } + break; + } else if ((i > LP_OWN_BACK_FAILED_RETRY_CNT) && + (kalIsCardRemoved(prAdapter->prGlueInfo) || fgIsBusAccessFailed || fgTimeout + || wlanIsChipNoAck(prAdapter))) { + + /* For driver own back fail debug, get current PC value */ + halPrintMailbox(prAdapter); + halPollDbgCr(prAdapter, LP_OWN_BACK_FAILED_DBGCR_POLL_ROUND); + + if ((prAdapter->u4OwnFailedCount == 0) || + CHECK_FOR_TIMEOUT(u4CurrTick, prAdapter->rLastOwnFailedLogTime, + MSEC_TO_SYSTIME(LP_OWN_BACK_FAILED_LOG_SKIP_MS))) { + + DBGLOG(INIT, ERROR, + "LP cannot be own back, Timeout[%u](%ums), BusAccessError[%u]", + fgTimeout, kalGetTimeTick() - u4CurrTick, fgIsBusAccessFailed); + DBGLOG(INIT, ERROR, + "Resetting[%u], CardRemoved[%u] NoAck[%u] Cnt[%u] fgCoreDump[%u]\n", + kalIsResetting(), + kalIsCardRemoved(prAdapter->prGlueInfo), wlanIsChipNoAck(prAdapter), + prAdapter->u4OwnFailedCount, fgWmtCoreDump); + + DBGLOG(INIT, INFO, + "Skip LP own back failed log for next %ums\n", LP_OWN_BACK_FAILED_LOG_SKIP_MS); + + prAdapter->u4OwnFailedLogCount++; + if (prAdapter->u4OwnFailedLogCount > LP_OWN_BACK_FAILED_RESET_CNT) { + /* Trigger RESET */ + glSetRstReason(RST_DRV_OWN_FAIL); + GL_RESET_TRIGGER(prAdapter, + RST_FLAG_DO_CORE_DUMP); + } + GET_CURRENT_SYSTIME(&prAdapter->rLastOwnFailedLogTime); + } + + prAdapter->u4OwnFailedCount++; + fgStatus = FALSE; + break; + } + + u4WriteTickTemp = kalGetTimeTick(); + if ((i == 0) || TIME_AFTER(u4WriteTickTemp, (u4WriteTick + LP_OWN_REQ_CLR_INTERVAL_MS))) { + /* Driver get LP ownership per 200 ms, to avoid iteration time not accurate */ + HAL_LP_OWN_CLR(prAdapter, &fgResult); + u4WriteTick = u4WriteTickTemp; + } + + /* Delay for LP engine to complete its operation. */ + kalUsleep_range(LP_OWN_BACK_LOOP_DELAY_MIN_US, LP_OWN_BACK_LOOP_DELAY_MAX_US); + i++; + } + u4DriverOwnTime = ((kalGetTimeTick() >= u4CurrTick) ? + (kalGetTimeTick() - u4CurrTick) : (kalGetTimeTick() + (~u4CurrTick))); + + /* 1. Driver need to polling until CR4 ready, then could do normal Tx/Rx */ + /* 2. Send a dummy command to change data path to store-forward mode */ +#if 1 + if (prAdapter->fgIsFwDownloaded) { + const uint32_t ready_bits = prAdapter->chip_info->sw_ready_bits; + + DBGLOG(INIT, INFO, "halSetDriverOwn:: Check ready_bits(=0x%x)\n", ready_bits); + u4CurrTick = kalGetTimeTick(); + while (1) { + HAL_WIFI_FUNC_READY_CHECK(prAdapter, ready_bits/*WIFI_FUNC_READY_BITS*/, &fgReady); + + if (TIME_BEFORE(kalGetTimeTick(), u4CurrTick)) { /* To prevent timer wraparound */ + fgTimeout = + ((kalGetTimeTick() + (~u4CurrTick)) > LP_OWN_BACK_TOTAL_DELAY_MS) + ? TRUE : FALSE; + } else { + fgTimeout = + ((kalGetTimeTick() - u4CurrTick) > LP_OWN_BACK_TOTAL_DELAY_MS) + ? TRUE : FALSE; + } + + if (fgReady) { + break; + } else if (kalIsCardRemoved(prAdapter->prGlueInfo) || fgIsBusAccessFailed || fgTimeout + || wlanIsChipNoAck(prAdapter)) { + + /* For driver own back fail debug, get current PC value */ + halPrintMailbox(prAdapter); + halPollDbgCr(prAdapter, LP_OWN_BACK_FAILED_DBGCR_POLL_ROUND); + + DBGLOG(INIT, ERROR, + "Resetting[%u], CardRemoved[%u] NoAck[%u] Timeout[%u](%u - %u)ms, fgCoreDump[%u]\n", + kalIsResetting(), + kalIsCardRemoved(prAdapter->prGlueInfo), wlanIsChipNoAck(prAdapter), + fgTimeout, kalGetTimeTick(), u4CurrTick, fgWmtCoreDump); + + + DBGLOG(INIT, INFO, + "Skip waiting CR4 ready for next %ums\n", LP_OWN_BACK_FAILED_LOG_SKIP_MS); + fgStatus = FALSE; + + if (fgTimeout) { + /* Trigger RESET */ + glSetRstReason(RST_DRV_OWN_FAIL); + GL_RESET_TRIGGER(prAdapter, + RST_FLAG_DO_CORE_DUMP); + } + + break; + } + /* Delay for CR4 to complete its operation. */ + kalUsleep_range(LP_OWN_BACK_LOOP_DELAY_MIN_US, LP_OWN_BACK_LOOP_DELAY_MAX_US); + } + + halTagIntLog(prAdapter, SDIO_INT_DRV_OWN); + HAL_MCR_RD(prAdapter, MCR_D2HRM1R, &j); + + if (j == 0x77889901) { + + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + + if (halIsPendingTxDone(prAdapter)) { + /* Workaround for missing Tx done */ + halSerHifReset(prAdapter); + } + + /* fgIsWakeupFromDeepSleep */ + wlanSendDummyCmd(prAdapter, FALSE); + + /* Workaround for dummy command which is not count in Tx done count */ + if (prChipInfo->is_support_cr4) + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[TC4_INDEX]--; + halTagIntLog(prAdapter, SDIO_INT_WAKEUP_DSLP); + } + u4Cr4ReadyTime = ((kalGetTimeTick() >= u4CurrTick) ? + (kalGetTimeTick() - u4CurrTick) : (kalGetTimeTick() + (~u4CurrTick))); + } +#endif + + DBGLOG(NIC, INFO, "DRIVER OWN %d, %d, DSLP %s, count %d\n", + u4DriverOwnTime, u4Cr4ReadyTime, ((j == 0x77889901)?"1":"0"), i); + +unlock: + KAL_RELEASE_MUTEX(prAdapter, MUTEX_SET_OWN); + + return fgStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to process the POWER ON procedure. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void halSetFWOwn(IN struct ADAPTER *prAdapter, IN u_int8_t fgEnableGlobalInt) +{ + + u_int8_t fgResult; + struct GL_HIF_INFO *prHifInfo = NULL; + + ASSERT(prAdapter); + ASSERT(prAdapter->u4PwrCtrlBlockCnt != 0); + + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_SET_OWN); + + /* Decrease Block to Enter Low Power Semaphore count */ + GLUE_DEC_REF_CNT(prAdapter->u4PwrCtrlBlockCnt); + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + if (prAdapter->u4PwrCtrlBlockCnt != 0) { + DBGLOG(INIT, INFO, "prAdapter->u4PwrCtrlBlockCnt = %d\n", + prAdapter->u4PwrCtrlBlockCnt); + goto unlock; + } + + if (prHifInfo->fgForceFwOwn == FALSE + && prAdapter->fgWiFiInSleepyState == FALSE) + goto unlock; + + if (prAdapter->fgIsFwOwn == TRUE) + goto unlock; + + if ((nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) && + !nicSerIsWaitingReset(prAdapter)) { + DBGLOG(INIT, INFO, "FW OWN Skipped due to pending INT\n"); + /* pending interrupts */ + goto unlock; + } + + if (fgEnableGlobalInt) { + prAdapter->fgIsIntEnableWithLPOwnSet = TRUE; + } else { + HAL_LP_OWN_SET(prAdapter, &fgResult); + + if (fgResult) { + /* if set firmware own not successful (possibly pending interrupts), */ + /* indicate an own clear event */ + HAL_LP_OWN_CLR(prAdapter, &fgResult); + } else { + prAdapter->fgIsFwOwn = TRUE; + + DBGLOG(INIT, INFO, "FW OWN\n"); + } + } + +unlock: + KAL_RELEASE_MUTEX(prAdapter, MUTEX_SET_OWN); +} + +void halWakeUpWiFi(IN struct ADAPTER *prAdapter) +{ + + u_int8_t fgResult; + + ASSERT(prAdapter); + + HAL_LP_OWN_RD(prAdapter, &fgResult); + + if (fgResult) + prAdapter->fgIsFwOwn = FALSE; + else + HAL_LP_OWN_CLR(prAdapter, &fgResult); +} + +void halDevInit(IN struct ADAPTER *prAdapter) +{ + uint32_t u4Value = 0; + + ASSERT(prAdapter); + +#if CFG_SDIO_INTR_ENHANCE + /* 4 <1> Check STATUS Buffer is DW alignment. */ + ASSERT(IS_ALIGN_4((unsigned long)&prAdapter->prGlueInfo->rHifInfo.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); + } +#endif /* CFG_SDIO_INTR_ENHANCE */ + + HAL_MCR_WR(prAdapter, MCR_WHIER, WHIER_DEFAULT); + + HAL_CFG_MAX_HIF_RX_LEN_NUM(prAdapter, HIF_RX_MAX_AGG_NUM); +} + +void halTxCancelSendingCmd(IN struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo) +{ +} + +u_int8_t halTxIsDataBufEnough(IN struct ADAPTER *prAdapter, IN struct MSDU_INFO *prMsduInfo) +{ + return TRUE; +} + +uint8_t halTxRingDataSelect(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + return 0; +} + +void halUpdateTxMaxQuota(IN struct ADAPTER *prAdapter) +{ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Driver maintain a variable that is synchronous with the usage of individual +* TC Buffer Count. This function will calculate TC page count according to +* the given TX_STATUS COUNTER after TX Done. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] au2TxRlsCnt array of TX STATUS +* \param[in] au2FreeTcResource array of free & available resource count +* +* @return TRUE there are available resource to release +* @return FALSE no available resource to release +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t halTxCalculateResource(IN struct ADAPTER *prAdapter, IN uint16_t *au2TxRlsCnt, OUT uint16_t *au2FreeTcResource) +{ + struct TX_TCQ_STATUS *prTcqStatus; + u_int8_t bStatus = FALSE; + uint8_t ucTcIdx; + uint32_t u4TotalTxDoneCnt = 0; + uint32_t u4TotalExtraTxDone = 0; + uint32_t au4UsedCnt[TC_NUM]; + uint32_t au4ExtraTxDone[TC_NUM]; + + uint32_t *au4TxDoneCnt; + uint32_t *au4PreUsedCnt; + uint32_t u4AvaliableCnt; + u_int8_t fgEnExtraTxDone; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prTcqStatus = &prAdapter->rTxCtrl.rTc; + + au4TxDoneCnt = prTcqStatus->au4TxDonePageCount; + au4PreUsedCnt = prTcqStatus->au4PreUsedPageCount; + u4AvaliableCnt = prTcqStatus->u4AvaliablePageCount; + fgEnExtraTxDone = prAdapter->rWifiVar.ucExtraTxDone; + + /* Get used page count */ + if (fgEnExtraTxDone) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + for (ucTcIdx = TC0_INDEX; ucTcIdx < TC_NUM; ucTcIdx++) { + au4UsedCnt[ucTcIdx] = prTcqStatus->au4MaxNumOfPage[ucTcIdx] - + prTcqStatus->au4FreePageCount[ucTcIdx]; + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + } + + /* Get Tx done & available page count */ + u4AvaliableCnt += au2TxRlsCnt[HIF_TX_FFA_INDEX]; + for (ucTcIdx = TC0_INDEX; ucTcIdx < TC_NUM; ucTcIdx++) { + + /* Get Tx done count from Tx interrupt status */ + au4TxDoneCnt[ucTcIdx] += au2TxRlsCnt[nicTxGetTxQByTc(prAdapter, ucTcIdx)]; + + /* Get available EXTRA Tx done */ + if (fgEnExtraTxDone) { + /* Release Tx done if there are pre-used resource */ + if (au4TxDoneCnt[ucTcIdx] >= au4PreUsedCnt[ucTcIdx]) { + au4TxDoneCnt[ucTcIdx] -= au4PreUsedCnt[ucTcIdx]; + au4PreUsedCnt[ucTcIdx] = 0; + } else { + au4PreUsedCnt[ucTcIdx] -= au4TxDoneCnt[ucTcIdx]; + au4TxDoneCnt[ucTcIdx] = 0; + } + + /* Calculate extra Tx done to share rest FFA resource */ + if (au4TxDoneCnt[ucTcIdx] >= au4UsedCnt[ucTcIdx]) { + au4TxDoneCnt[ucTcIdx] = au4UsedCnt[ucTcIdx]; + au4ExtraTxDone[ucTcIdx] = 0; + } else { + au4ExtraTxDone[ucTcIdx] = au4UsedCnt[ucTcIdx] - au4TxDoneCnt[ucTcIdx]; + } + u4TotalExtraTxDone += au4ExtraTxDone[ucTcIdx]; + } + + u4TotalTxDoneCnt += au4TxDoneCnt[ucTcIdx]; + + } + + DBGLOG(TX, TRACE, "TxDone result, FFA[%u] AC[%u:%u:%u:%u] CPU[%u]\n", + au2TxRlsCnt[HIF_TX_FFA_INDEX], au2TxRlsCnt[HIF_TX_AC0_INDEX], + au2TxRlsCnt[HIF_TX_AC1_INDEX], au2TxRlsCnt[HIF_TX_AC2_INDEX], + au2TxRlsCnt[HIF_TX_AC3_INDEX], au2TxRlsCnt[HIF_TX_CPU_INDEX]); + + DBGLOG(TX, TRACE, "TxDone Page count, TC[%u:%u:%u:%u:%u]\n", + au4TxDoneCnt[TC0_INDEX], au4TxDoneCnt[TC1_INDEX], au4TxDoneCnt[TC2_INDEX], + au4TxDoneCnt[TC3_INDEX], au4TxDoneCnt[TC4_INDEX]); + + /* Calculate free Tc page count */ + if (u4AvaliableCnt && u4TotalTxDoneCnt) { + /* Distribute resource by Tx done counter */ + if (u4AvaliableCnt >= u4TotalTxDoneCnt) { + /* Fulfill all TC resource */ + kalMemCopy(au2FreeTcResource, prTcqStatus->au4TxDonePageCount, + sizeof(prTcqStatus->au4TxDonePageCount)); + + kalMemZero(prTcqStatus->au4TxDonePageCount, sizeof(prTcqStatus->au4TxDonePageCount)); + + u4AvaliableCnt -= u4TotalTxDoneCnt; + } else { + /* Round-robin distribute resource */ + ucTcIdx = prTcqStatus->ucNextTcIdx; + while (u4AvaliableCnt) { + /* Enough resource, fulfill this TC */ + if (u4AvaliableCnt >= au4TxDoneCnt[ucTcIdx]) { + au2FreeTcResource[ucTcIdx] = au4TxDoneCnt[ucTcIdx]; + u4AvaliableCnt -= au4TxDoneCnt[ucTcIdx]; + au4TxDoneCnt[ucTcIdx] = 0; + + /* Round-robin get next TC */ + ucTcIdx++; + ucTcIdx %= TC_NUM; + } + /* no more resource, distribute rest of resource to this TC */ + else { + au2FreeTcResource[ucTcIdx] = u4AvaliableCnt; + au4TxDoneCnt[ucTcIdx] -= u4AvaliableCnt; + u4AvaliableCnt = 0; + } + } + prTcqStatus->ucNextTcIdx = ucTcIdx; + } + bStatus = TRUE; + } + + if (u4AvaliableCnt && u4TotalExtraTxDone && fgEnExtraTxDone) { + /* Distribute resource by EXTRA Tx done counter */ + if (u4AvaliableCnt >= u4TotalExtraTxDone) { + for (ucTcIdx = TC0_INDEX; ucTcIdx < TC_NUM; ucTcIdx++) { + au2FreeTcResource[ucTcIdx] += au4ExtraTxDone[ucTcIdx]; + au4PreUsedCnt[ucTcIdx] += au4ExtraTxDone[ucTcIdx]; + au4ExtraTxDone[ucTcIdx] = 0; + } + + u4AvaliableCnt -= u4TotalExtraTxDone; + } else { + /* Round-robin distribute resource */ + ucTcIdx = prTcqStatus->ucNextTcIdx; + while (u4AvaliableCnt) { + /* Enough resource, fulfill this TC */ + if (u4AvaliableCnt >= au4ExtraTxDone[ucTcIdx]) { + au2FreeTcResource[ucTcIdx] += au4ExtraTxDone[ucTcIdx]; + au4PreUsedCnt[ucTcIdx] += au4ExtraTxDone[ucTcIdx]; + u4AvaliableCnt -= au4ExtraTxDone[ucTcIdx]; + au4ExtraTxDone[ucTcIdx] = 0; + + /* Round-robin get next TC */ + ucTcIdx++; + ucTcIdx %= TC_NUM; + } + /* no more resource, distribute rest of resource to this TC */ + else { + au2FreeTcResource[ucTcIdx] += u4AvaliableCnt; + au4PreUsedCnt[ucTcIdx] += u4AvaliableCnt; + au4ExtraTxDone[ucTcIdx] -= u4AvaliableCnt; + u4AvaliableCnt = 0; + } + } + prTcqStatus->ucNextTcIdx = ucTcIdx; + } + bStatus = TRUE; + } + + prTcqStatus->u4AvaliablePageCount = u4AvaliableCnt; + + return bStatus; +} +u_int8_t halTxReleaseResource(IN struct ADAPTER *prAdapter, IN uint16_t *au2TxRlsCnt) +{ + struct TX_TCQ_STATUS *prTcqStatus; + u_int8_t bStatus = FALSE; + uint32_t i; + struct SDIO_STAT_COUNTER *prStatCnt; + uint16_t au2TxDoneCnt[HIF_TX_NUM] = { 0 }; + + ASSERT(prAdapter); + prTcqStatus = &prAdapter->rTxCtrl.rTc; + prStatCnt = &prAdapter->prGlueInfo->rHifInfo.rStatCounter; + + /* Update Free Tc resource counter */ + halTxGetFreeResource(prAdapter, au2TxDoneCnt, au2TxRlsCnt); + + /* Return free Tc page count */ + halTxReturnFreeResource(prAdapter, au2TxDoneCnt); + bStatus = TRUE; + + /* Update Statistic counter */ + prStatCnt->u4TxDonePendingPktCnt += nicTxGetMsduPendingCnt(prAdapter); + prStatCnt->u4TxDoneIntTotCnt++; + + for (i = HIF_TXC_IDX_0; i < HIF_TXC_IDX_NUM; i++) { + if (au2TxRlsCnt[i]) { + prStatCnt->u4TxDoneCnt[i] += au2TxRlsCnt[i]; + prStatCnt->u4TxDoneIntCnt[i]++; + } + } + + if (!nicTxSanityCheckResource(prAdapter)) + DBGLOG(TX, ERROR, "Tx Done INT result, FFA[%u] AC[%u:%u:%u:%u] CPU[%u]\n", + au2TxRlsCnt[HIF_TX_FFA_INDEX], au2TxRlsCnt[HIF_TX_AC0_INDEX], + au2TxRlsCnt[HIF_TX_AC1_INDEX], au2TxRlsCnt[HIF_TX_AC2_INDEX], + au2TxRlsCnt[HIF_TX_AC3_INDEX], au2TxRlsCnt[HIF_TX_CPU_INDEX]); + + DBGLOG(TX, LOUD, "TCQ Status Free Page <>:Buf[%u:%u, %u:%u, %u:%u, %u:%u, %u:%u]\n", + prTcqStatus->au4FreePageCount[TC0_INDEX], prTcqStatus->au4FreeBufferCount[TC0_INDEX], + prTcqStatus->au4FreePageCount[TC1_INDEX], prTcqStatus->au4FreeBufferCount[TC1_INDEX], + prTcqStatus->au4FreePageCount[TC2_INDEX], prTcqStatus->au4FreeBufferCount[TC2_INDEX], + prTcqStatus->au4FreePageCount[TC3_INDEX], prTcqStatus->au4FreeBufferCount[TC3_INDEX], + prTcqStatus->au4FreePageCount[TC4_INDEX], prTcqStatus->au4FreeBufferCount[TC4_INDEX]); + + + if (prAdapter->rTxCtrl.rTc.fgNeedPleCtrl) + DBGLOG(TX, LOUD, "TCQ Status Free Page <>:Buf[%u:%u, %u:%u, %u:%u, %u:%u, %u:%u]\n", + prTcqStatus->au4FreePageCount_PLE[TC0_INDEX], prTcqStatus->au4FreePageCount_PLE[TC0_INDEX], + prTcqStatus->au4FreePageCount_PLE[TC1_INDEX], prTcqStatus->au4FreePageCount_PLE[TC1_INDEX], + prTcqStatus->au4FreePageCount_PLE[TC2_INDEX], prTcqStatus->au4FreePageCount_PLE[TC2_INDEX], + prTcqStatus->au4FreePageCount_PLE[TC3_INDEX], prTcqStatus->au4FreePageCount_PLE[TC3_INDEX], + prTcqStatus->au4FreePageCount_PLE[TC4_INDEX], prTcqStatus->au4FreePageCount_PLE[TC4_INDEX]); + + return bStatus; +} + +uint32_t halTxPollingResource(IN struct ADAPTER *prAdapter, IN uint8_t ucTC) +{ + struct TX_CTRL *prTxCtrl; + uint32_t u4Status = WLAN_STATUS_RESOURCES; + uint32_t au4WTSR[8]; + struct GL_HIF_INFO *prHifInfo; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + prTxCtrl = &prAdapter->rTxCtrl; + + if (prHifInfo->fgIsPendingInt && (prHifInfo->prSDIOCtrl->u4WHISR & WHISR_TX_DONE_INT)) { + /* Get Tx done resource from pending interrupt status */ + kalMemCopy(au4WTSR, &prHifInfo->prSDIOCtrl->rTxInfo, sizeof(uint32_t) * 8); + + /* Clear pending Tx done interrupt */ + prHifInfo->prSDIOCtrl->u4WHISR &= ~WHISR_TX_DONE_INT; + } else + HAL_READ_TX_RELEASED_COUNT(prAdapter, au4WTSR); + + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + } else if (halTxReleaseResource(prAdapter, (uint16_t *) au4WTSR)) { + if (prTxCtrl->rTc.au4FreeBufferCount[ucTC] > 0) + u4Status = WLAN_STATUS_SUCCESS; + } + + return u4Status; +} + +void halTxInterruptSanityCheck(IN struct ADAPTER *prAdapter, IN uint16_t *au2TxRlsCnt) +{ + uint8_t ucIdx; + u_int8_t fgError = FALSE; + + if (prAdapter->rWifiVar.ucTxDbg & BIT(1)) { + for (ucIdx = HIF_TX_AC0_INDEX; ucIdx < HIF_TX_NUM; ucIdx++) { + if (au2TxRlsCnt[ucIdx] > prAdapter->rTxCtrl.u4TotalPageNum) + fgError = TRUE; + } + + if (fgError) + DBGLOG(TX, ERROR, "Tx Done INT result, FFA[%u] AC[%u:%u:%u:%u] CPU[%u]\n", + au2TxRlsCnt[HIF_TX_FFA_INDEX], au2TxRlsCnt[HIF_TX_AC0_INDEX], + au2TxRlsCnt[HIF_TX_AC1_INDEX], au2TxRlsCnt[HIF_TX_AC2_INDEX], + au2TxRlsCnt[HIF_TX_AC3_INDEX], au2TxRlsCnt[HIF_TX_CPU_INDEX]); + } +} + +#if CFG_SDIO_INTR_ENHANCE +void halProcessEnhanceInterruptStatus(IN struct ADAPTER *prAdapter) +{ + struct ENHANCE_MODE_DATA_STRUCT *prSDIOCtrl = prAdapter->prGlueInfo->rHifInfo.prSDIOCtrl; + + /* Set Tx done interrupt if there are Tx done count */ + if ((prSDIOCtrl->u4WHISR & WHISR_TX_DONE_INT) == 0 && + (prSDIOCtrl->rTxInfo.au4WTSR[0] | prSDIOCtrl->rTxInfo.au4WTSR[1] | + prSDIOCtrl->rTxInfo.au4WTSR[2] | prSDIOCtrl->rTxInfo.au4WTSR[3] | + prSDIOCtrl->rTxInfo.au4WTSR[4] | prSDIOCtrl->rTxInfo.au4WTSR[5] | + prSDIOCtrl->rTxInfo.au4WTSR[6] | prSDIOCtrl->rTxInfo.au4WTSR[7])) { + + prSDIOCtrl->u4WHISR |= WHISR_TX_DONE_INT; + } + + /* Set SW ASSERT INFO interrupt if there are pending mail box */ + if (((prSDIOCtrl->u4WHISR & WHISR_D2H_SW_ASSERT_INFO_INT) == 0) && + HAL_GET_MAILBOX_READ_CLEAR(prAdapter) && + (prSDIOCtrl->u4RcvMailbox0 || prSDIOCtrl->u4RcvMailbox1)) { + + prSDIOCtrl->u4WHISR |= WHISR_D2H_SW_ASSERT_INFO_INT; + } +} +#endif + +void halProcessTxInterrupt(IN struct ADAPTER *prAdapter) +{ + struct TX_CTRL *prTxCtrl; +#if CFG_SDIO_INTR_ENHANCE + struct ENHANCE_MODE_DATA_STRUCT *prSDIOCtrl; +#else + uint32_t au4TxCount[2]; +#endif /* CFG_SDIO_INTR_ENHANCE */ + SDIO_TIME_INTERVAL_DEC(); + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + SDIO_REC_TIME_START(); + + /* Get the TX STATUS */ +#if CFG_SDIO_INTR_ENHANCE + + prSDIOCtrl = prAdapter->prGlueInfo->rHifInfo.prSDIOCtrl; +#if DBG + /* DBGLOG_MEM8(RX, TRACE, (PUINT_8)prSDIOCtrl, sizeof(SDIO_CTRL_T)); */ +#endif + + halTxInterruptSanityCheck(prAdapter, (uint16_t *)&prSDIOCtrl->rTxInfo); + halTxReleaseResource(prAdapter, (uint16_t *)&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]); + + halTxReleaseResource(prAdapter, (uint8_t *) au4TxCount); + +#endif /* CFG_SDIO_INTR_ENHANCE */ + + nicTxAdjustTcq(prAdapter); + + SDIO_REC_TIME_END(); + SDIO_ADD_TIME_INTERVAL(prAdapter->prGlueInfo->rHifInfo.rStatCounter.u4TxDoneIntTime); + +} /* end of nicProcessTxInterrupt() */ + +#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 +* +*/ +/*----------------------------------------------------------------------------*/ +uint32_t halRxReadBuffer(IN struct ADAPTER *prAdapter, IN OUT struct SW_RFB *prSwRfb) +{ + struct RX_CTRL *prRxCtrl; + uint8_t *pucBuf; + void *prRxStatus; + uint32_t u4PktLen = 0, u4ReadBytes; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + u_int8_t fgResult = TRUE; + uint32_t u4RegValue; + uint32_t rxNum; +#if CFG_TCP_IP_CHKSUM_OFFLOAD + uint32_t *pu4HwAppendDW; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + struct RX_DESC_OPS_T *prRxDescOps; + uint16_t u2RxByteCount = 0; + + DEBUGFUNC("halRxReadBuffer"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + pucBuf = prSwRfb->pucRecvBuff; + prRxStatus = prSwRfb->prRxStatus; + + ASSERT(prRxStatus); + ASSERT(pucBuf); + prRxDescOps = prAdapter->chip_info->prRxDescOps; + ASSERT(prRxDescOps->nic_rxd_get_rx_byte_count); + ASSERT(prRxDescOps->nic_rxd_get_pkt_type); + ASSERT(prRxDescOps->nic_rxd_get_wlan_idx); + + u2RxByteCount = prRxDescOps->nic_rxd_get_rx_byte_count(prRxStatus); + 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 != (uint32_t) u2RxByteCount) { + DBGLOG(RX, ERROR, "Read u4PktLen = %d, prHifRxHdr->u2PacketLen: %d\n", + u4PktLen, + u2RxByteCount); +#if DBG + DBGLOG_MEM8(RX, TRACE, (uint8_t *) prRxStatus, + (u2RxByteCount > + 4096) ? 4096 : u2RxByteCount); +#endif + ASSERT(0); + } + /* u4PktLen is byte unit, not inlude HW appended DW */ + + prSwRfb->ucPacketType = + prRxDescOps->nic_rxd_get_pkt_type(prRxStatus); + DBGLOG(RX, TRACE, "ucPacketType = %d\n", prSwRfb->ucPacketType); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + pu4HwAppendDW = (uint32_t *) prRxStatus; + pu4HwAppendDW += (ALIGN_4(u2RxByteCount) >> 2); + prSwRfb->u4TcpUdpIpCksStatus = *pu4HwAppendDW; + DBGLOG(RX, TRACE, "u4TcpUdpIpCksStatus[0x%02x]\n", prSwRfb->u4TcpUdpIpCksStatus); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + prSwRfb->ucStaRecIdx = + secGetStaIdxByWlanIdx( + prAdapter, + prRxDescOps->nic_rxd_get_wlan_idx(prRxStatus)); + + /* 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 halRxSDIOReceiveRFBs(IN struct ADAPTER *prAdapter) +{ + struct RX_CTRL *prRxCtrl; + struct SW_RFB *prSwRfb = (struct SW_RFB *) NULL; + void *prRxStatus; + uint32_t u4HwAppendDW; + uint32_t *pu4Temp; + struct RX_DESC_OPS_T *prRxDescOps; + uint16_t u2RxByteCount; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("halRxSDIOReceiveRFBs"); + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + prRxDescOps = prAdapter->chip_info->prRxDescOps; + ASSERT(prRxDescOps->nic_rxd_get_rx_byte_count); + do { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, struct SW_RFB *); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + if (!prSwRfb) { + DBGLOG(RX, TRACE, "No More RFB\n"); + break; + } + /* need to consider */ + if (halRxReadBuffer(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); + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + pu4Temp = (uint32_t *) prRxStatus; + u2RxByteCount = + prRxDescOps->nic_rxd_get_rx_byte_count(prRxStatus); + u4HwAppendDW = *(pu4Temp + (ALIGN_4(u2RxByteCount) >> 2)); + DBGLOG(RX, TRACE, "u4HwAppendDW = 0x%x\n", u4HwAppendDW); + DBGLOG(RX, TRACE, "u2PacketLen = 0x%x\n", u2RxByteCount); + } while (FALSE); + +} /* 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) +*/ +/*----------------------------------------------------------------------------*/ + +uint32_t +halRxEnhanceReadBuffer(IN struct ADAPTER *prAdapter, + IN uint32_t u4DataPort, IN uint16_t u2RxLength, IN OUT struct SW_RFB *prSwRfb) +{ + struct RX_CTRL *prRxCtrl; + uint8_t *pucBuf; + void *prRxStatus; + uint32_t u4PktLen = 0; + uint32_t u4Status = WLAN_STATUS_FAILURE; + u_int8_t fgResult = TRUE; +#if CFG_TCP_IP_CHKSUM_OFFLOAD + uint32_t *pu4HwAppendDW; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + struct RX_DESC_OPS_T *prRxDescOps; + + DEBUGFUNC("halRxEnhanceReadBuffer"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + pucBuf = prSwRfb->pucRecvBuff; + ASSERT(pucBuf); + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + prRxDescOps = prAdapter->chip_info->prRxDescOps; + ASSERT(prRxDescOps->nic_rxd_get_rx_byte_count); + ASSERT(prRxDescOps->nic_rxd_get_pkt_type); + ASSERT(prRxDescOps->nic_rxd_get_wlan_idx); + + /* 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 = (uint32_t)(prRxDescOps->nic_rxd_get_rx_byte_count( + prRxStatus)); + /* DBGLOG(RX, TRACE, ("u4PktLen = %d\n", u4PktLen)); */ + + prSwRfb->ucPacketType = (uint8_t) + prRxDescOps->nic_rxd_get_pkt_type(prRxStatus); + /* DBGLOG(RX, TRACE, ("ucPacketType = %d\n", prSwRfb->ucPacketType)); */ + + prSwRfb->ucStaRecIdx = + secGetStaIdxByWlanIdx( + prAdapter, + prRxDescOps->nic_rxd_get_wlan_idx(prRxStatus)); + + /* 4 <2> if the RFB dw size or packet size is zero */ + if (u4PktLen == 0) { + DBGLOG(RX, ERROR, "Packet Length = %u\n", + u4PktLen); + ASSERT(0); + break; + } + /* 4 <3> if the packet is too large or too small */ + /* ToDo[6630]: adjust CFG_RX_MAX_PKT_SIZE */ + if (u4PktLen > CFG_RX_MAX_PKT_SIZE) { + DBGLOG(RX, TRACE, "Read RX Packet Lentgh Error (%u)\n", + u4PktLen); + ASSERT(0); + break; + } + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + pu4HwAppendDW = (uint32_t *) prRxStatus; + pu4HwAppendDW += (ALIGN_4(u4PktLen) >> 2); + prSwRfb->u4TcpUdpIpCksStatus = *pu4HwAppendDW; + DBGLOG(RX, TRACE, "u4TcpUdpIpCksStatus[0x%02x]\n", prSwRfb->u4TcpUdpIpCksStatus); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + 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 halRxSDIOEnhanceReceiveRFBs(IN struct ADAPTER *prAdapter) +{ + struct ENHANCE_MODE_DATA_STRUCT *prSDIOCtrl; + struct RX_CTRL *prRxCtrl; + struct SW_RFB *prSwRfb = (struct SW_RFB *) NULL; + uint32_t i, rxNum; + uint16_t u2RxPktNum, u2RxLength = 0, u2Tmp = 0; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("halRxSDIOEnhanceReceiveRFBs"); + + ASSERT(prAdapter); + + prSDIOCtrl = prAdapter->prGlueInfo->rHifInfo.prSDIOCtrl; + ASSERT(prSDIOCtrl); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + for (rxNum = 0; rxNum < 2; rxNum++) { + u2RxPktNum = + (rxNum == 0 ? prSDIOCtrl->rRxInfo.u.u2NumValidRx0Len : prSDIOCtrl->rRxInfo.u.u2NumValidRx1Len); + + if (u2RxPktNum == 0) + continue; + + for (i = 0; i < u2RxPktNum; i++) { + if (rxNum == 0) { + /* HAL_READ_RX_LENGTH */ + HAL_READ_RX_LENGTH(prAdapter, &u2RxLength, &u2Tmp); + } else if (rxNum == 1) { + /* HAL_READ_RX_LENGTH */ + HAL_READ_RX_LENGTH(prAdapter, &u2Tmp, &u2RxLength); + } + + if (!u2RxLength) + break; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, struct SW_RFB *); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + if (!prSwRfb) { + DBGLOG(RX, TRACE, "No More RFB\n"); + break; + } + ASSERT(prSwRfb); + + if (halRxEnhanceReadBuffer(prAdapter, rxNum, u2RxLength, prSwRfb) == WLAN_STATUS_FAILURE) { + DBGLOG(RX, TRACE, "nicRxEnhanceRxReadBuffer failed\n"); + nicRxReturnRFB(prAdapter, prSwRfb); + break; + } + /* prSDIOCtrl->au4RxLength[i] = 0; */ + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_INSERT_TAIL(&prRxCtrl->rReceivedRfbList, &prSwRfb->rQueEntry); + RX_INC_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + } + } + + prSDIOCtrl->rRxInfo.u.u2NumValidRx0Len = 0; + prSDIOCtrl->rRxInfo.u.u2NumValidRx1Len = 0; + +} /* end of nicRxSDIOReceiveRFBs() */ + +#endif /* CFG_SDIO_INTR_ENHANCE */ + +#if CFG_SDIO_RX_AGG +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read frames from the data port for SDIO with Rx aggregation enabled +* I/F, fill RFB and put each frame into the rReceivedRFBList queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void halRxSDIOAggReceiveRFBs(IN struct ADAPTER *prAdapter) +{ + struct ENHANCE_MODE_DATA_STRUCT *prEnhDataStr; + struct RX_CTRL *prRxCtrl; + uint32_t u4RxLength; + uint32_t i, rxNum; + uint32_t u4RxAggCount = 0, u4RxAggLength = 0; + uint32_t u4RxAvailAggLen; + uint8_t *pucSrcAddr; + uint16_t u2RxPktNum; + struct GL_HIF_INFO *prHifInfo; + struct SDIO_RX_COALESCING_BUF *prRxBuf; + u_int8_t fgNoFreeBuf = FALSE; + + SDIO_TIME_INTERVAL_DEC(); + + DEBUGFUNC("halRxSDIOAggReceiveRFBs"); + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + prEnhDataStr = prHifInfo->prSDIOCtrl; + + if (prEnhDataStr->rRxInfo.u.u2NumValidRx0Len == 0 && prEnhDataStr->rRxInfo.u.u2NumValidRx1Len == 0) + return; + + for (rxNum = 0; rxNum < 2; rxNum++) { + u2RxPktNum = (rxNum == 0 ? prEnhDataStr->rRxInfo.u.u2NumValidRx0Len : + prEnhDataStr->rRxInfo.u.u2NumValidRx1Len); + + if (u2RxPktNum > HIF_RX_MAX_AGG_NUM) { + halProcessAbnormalInterrupt(prAdapter); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP); + return; + } + + if (u2RxPktNum == 0) + continue; + +#if CFG_HIF_STATISTICS + prRxCtrl->u4TotalRxAccessNum++; + prRxCtrl->u4TotalRxPacketNum += u2RxPktNum; +#endif + + mutex_lock(&prHifInfo->rRxFreeBufQueMutex); + fgNoFreeBuf = QUEUE_IS_EMPTY(&prHifInfo->rRxFreeBufQueue); + mutex_unlock(&prHifInfo->rRxFreeBufQueMutex); + + if (fgNoFreeBuf) { + DBGLOG(RX, TRACE, "[%s] No free Rx buffer\n", __func__); + prHifInfo->rStatCounter.u4RxBufUnderFlowCnt++; + + if (prAdapter->prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + struct QUE rTempQue; + struct QUE *prTempQue = &rTempQue; + + /* During halt state, move all pending Rx buffer to free queue */ + mutex_lock(&prHifInfo->rRxDeAggQueMutex); + QUEUE_MOVE_ALL(prTempQue, &prHifInfo->rRxDeAggQueue); + mutex_unlock(&prHifInfo->rRxDeAggQueMutex); + + mutex_lock(&prHifInfo->rRxFreeBufQueMutex); + QUEUE_CONCATENATE_QUEUES(&prHifInfo->rRxFreeBufQueue, prTempQue); + mutex_unlock(&prHifInfo->rRxFreeBufQueMutex); + } + + continue; + } + + u4RxAvailAggLen = HIF_RX_COALESCING_BUFFER_SIZE; +#if CFG_SDIO_RX_ENHANCE + u4RxAvailAggLen -= (sizeof(struct ENHANCE_MODE_DATA_STRUCT) + HIF_RX_ENHANCE_MODE_PAD_LEN); +#endif + u4RxAggCount = 0; + + for (i = 0; i < u2RxPktNum; i++) { + u4RxLength = (rxNum == 0 ? (uint32_t) prEnhDataStr->rRxInfo.u.au2Rx0Len[i] : + (uint32_t) prEnhDataStr->rRxInfo.u.au2Rx1Len[i]); + + if (!u4RxLength) { + DBGLOG(RX, ERROR, "[%s] RxLength == 0\n", __func__); + halProcessAbnormalInterrupt(prAdapter); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP); + return; + } + + if (ALIGN_4(u4RxLength + HIF_RX_HW_APPENDED_LEN) < u4RxAvailAggLen) { + u4RxAvailAggLen -= ALIGN_4(u4RxLength + HIF_RX_HW_APPENDED_LEN); + u4RxAggCount++; + } else { + /* CFG_RX_COALESCING_BUFFER_SIZE is not large enough */ + DBGLOG(RX, ERROR, "[%s] Request_len(%d) >= Available_len(%d)\n", + __func__, (ALIGN_4(u4RxLength + HIF_RX_HW_APPENDED_LEN)), u4RxAvailAggLen); + halProcessAbnormalInterrupt(prAdapter); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP); + return; + } + } + + mutex_lock(&prHifInfo->rRxFreeBufQueMutex); + QUEUE_REMOVE_HEAD(&prHifInfo->rRxFreeBufQueue, prRxBuf, struct SDIO_RX_COALESCING_BUF *); + mutex_unlock(&prHifInfo->rRxFreeBufQueMutex); + + prRxBuf->u4PktCount = u4RxAggCount; + + u4RxAggLength = (HIF_RX_COALESCING_BUFFER_SIZE - u4RxAvailAggLen); + + prRxBuf->u4PktTotalLength = u4RxAggLength - sizeof(struct ENHANCE_MODE_DATA_STRUCT); + + prRxBuf->u4IntLogIdx = prHifInfo->u4IntLogIdx; + + SDIO_REC_TIME_START(); + HAL_READ_RX_PORT(prAdapter, rxNum, u4RxAggLength, + prRxBuf->pvRxCoalescingBuf, HIF_RX_COALESCING_BUFFER_SIZE); + SDIO_REC_TIME_END(); + SDIO_ADD_TIME_INTERVAL(prHifInfo->rStatCounter.u4PortReadTime); + +#if CFG_SDIO_RX_ENHANCE + pucSrcAddr = prRxBuf->pvRxCoalescingBuf + u4RxAggLength - sizeof(struct ENHANCE_MODE_DATA_STRUCT); + + /* Sanity check of zero padding before interrupt status */ + if (((uint32_t)*(pucSrcAddr - HIF_RX_ENHANCE_MODE_PAD_LEN)) == 0) { + kalMemCopy(prHifInfo->prSDIOCtrl, pucSrcAddr, sizeof(struct ENHANCE_MODE_DATA_STRUCT)); + + halProcessEnhanceInterruptStatus(prAdapter); + + if (prHifInfo->prSDIOCtrl->u4WHISR) { + /* Interrupt status without Rx done */ + /* Mask Rx done interrupt to avoid recurrsion */ + uint32_t u4IntStatus = prHifInfo->prSDIOCtrl->u4WHISR & + (~(WHISR_RX0_DONE_INT | WHISR_RX1_DONE_INT)); + + if ((rxNum == 0) && prEnhDataStr->rRxInfo.u.u2NumValidRx1Len && u4IntStatus) { + /* Handle interrupt here if there are pending Rx port1 */ + + nicProcessIST_impl(prAdapter, u4IntStatus); + } else { + prAdapter->prGlueInfo->rHifInfo.fgIsPendingInt = TRUE; + } + } + } +#endif + halDeAggRxPkt(prAdapter, prRxBuf); + + /* Update statistic counter */ + prHifInfo->rStatCounter.u4PktReadCnt[rxNum] += u4RxAggCount; + prHifInfo->rStatCounter.u4PortReadCnt[rxNum]++; + } + +} +#endif /* CFG_SDIO_RX_AGG */ + + +void halProcessRxInterrupt(IN struct ADAPTER *prAdapter) +{ + if (prAdapter->prGlueInfo->rHifInfo.fgSkipRx) + return; + +#if CFG_SDIO_INTR_ENHANCE +#if CFG_SDIO_RX_AGG + halRxSDIOAggReceiveRFBs(prAdapter); +#else + halRxSDIOEnhanceReceiveRFBs(prAdapter); +#endif +#else + halRxSDIOReceiveRFBs(prAdapter); +#endif /* CFG_SDIO_INTR_ENHANCE */ +} + +bool halHifSwInfoInit(IN struct ADAPTER *prAdapter) +{ + return true; +} + +void halRxProcessMsduReport(IN struct ADAPTER *prAdapter, IN OUT struct SW_RFB *prSwRfb) +{ + +} + +uint32_t halTxGetPageCountPSE(IN struct ADAPTER *prAdapter, IN uint32_t u4FrameLength) +{ + uint32_t u4PageSize = prAdapter->rTxCtrl.u4PageSize; + + return ((u4FrameLength + prAdapter->nicTxReousrce.ucPpTxAddCnt + u4PageSize - 1)/u4PageSize); +} + +uint32_t halTxGetPageCount(IN struct ADAPTER *prAdapter, IN uint32_t u4FrameLength, IN u_int8_t fgIncludeDesc) +{ + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + + if (prChipInfo->is_support_cr4) + return 1; + + return halTxGetPageCountPSE(prAdapter, u4FrameLength); +} + +uint32_t halDumpHifStatus(IN struct ADAPTER *prAdapter, IN uint8_t *pucBuf, IN uint32_t u4Max) +{ + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + struct SDIO_STAT_COUNTER *prStatCnt = &prHifInfo->rStatCounter; + uint32_t u4Len = 0; + uint32_t u4Idx; + + /* Print out counter */ + LOGBUF(pucBuf, u4Max, u4Len, "\n"); + LOGBUF(pucBuf, u4Max, u4Len, "------------\n"); + + LOGBUF(pucBuf, u4Max, u4Len, "Coalescing buffer size[%u] Rx Cnt[%u/%u] DeAgg[%u] UF Cnt[%u]\n", + prAdapter->u4CoalescingBufCachedSize, prHifInfo->rRxFreeBufQueue.u4NumElem, + HIF_RX_COALESCING_BUF_COUNT, prHifInfo->rRxDeAggQueue.u4NumElem, + prStatCnt->u4RxBufUnderFlowCnt); + + LOGBUF(pucBuf, u4Max, u4Len, "Pkt cnt Tx[%u] RxP0[%u] RxP1[%u] Tx/Rx ratio[%u.%u]\n", + prStatCnt->u4DataPktWriteCnt, prStatCnt->u4PktReadCnt[0], prStatCnt->u4PktReadCnt[1], + DIV2INT(prStatCnt->u4DataPktWriteCnt, prStatCnt->u4PktReadCnt[0]), + DIV2DEC(prStatCnt->u4DataPktWriteCnt, prStatCnt->u4PktReadCnt[0])); + + LOGBUF(pucBuf, u4Max, u4Len, "Tx pkt/wt[%u.%u] pkt/kick[%u.%u] cmd/wt[%u.%u]\n", + DIV2INT(prStatCnt->u4DataPktWriteCnt, prStatCnt->u4DataPortWriteCnt), + DIV2DEC(prStatCnt->u4DataPktWriteCnt, prStatCnt->u4DataPortWriteCnt), + DIV2INT(prStatCnt->u4DataPktWriteCnt, prStatCnt->u4DataPortKickCnt), + DIV2DEC(prStatCnt->u4DataPktWriteCnt, prStatCnt->u4DataPortKickCnt), + DIV2INT(prStatCnt->u4CmdPktWriteCnt, prStatCnt->u4CmdPortWriteCnt), + DIV2DEC(prStatCnt->u4CmdPktWriteCnt, prStatCnt->u4CmdPortWriteCnt)); + + LOGBUF(pucBuf, u4Max, u4Len, "Rx P0 pkt/rd[%u.%u] P1 pkt/rd[%u.%u]\n", + DIV2INT(prStatCnt->u4PktReadCnt[0], prStatCnt->u4PortReadCnt[0]), + DIV2DEC(prStatCnt->u4PktReadCnt[0], prStatCnt->u4PortReadCnt[0]), + DIV2INT(prStatCnt->u4PktReadCnt[1], prStatCnt->u4PortReadCnt[1]), + DIV2DEC(prStatCnt->u4PktReadCnt[1], prStatCnt->u4PortReadCnt[1])); + + LOGBUF(pucBuf, u4Max, u4Len, "Tx done pending cnt HIF_TXC00~04[%u, %u, %u, %u, %u]\n", + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_0], + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_1], + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_2], + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_3], + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_4]); + + LOGBUF(pucBuf, u4Max, u4Len, "Tx done pending cnt HIF_TXC05~09[%u, %u, %u, %u, %u]\n", + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_5], + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_6], + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_7], + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_8], + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_9]); + + LOGBUF(pucBuf, u4Max, u4Len, "Tx done pending cnt HIF_TXC10~15[%u, %u, %u, %u, %u, %u]\n", + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_10], + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_11], + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_12], + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_13], + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_14], + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_15]); + + + LOGBUF(pucBuf, u4Max, u4Len, "Tx done counter/int:\n"); + LOGBUF(pucBuf, u4Max, u4Len, "AC00~03[%u.%u, %u.%u, %u.%u, %u.%u]\n", + DIV2INT(prStatCnt->u4TxDoneCnt[0], prStatCnt->u4TxDoneIntCnt[0]), + DIV2DEC(prStatCnt->u4TxDoneCnt[0], prStatCnt->u4TxDoneIntCnt[0]), + DIV2INT(prStatCnt->u4TxDoneCnt[1], prStatCnt->u4TxDoneIntCnt[1]), + DIV2DEC(prStatCnt->u4TxDoneCnt[1], prStatCnt->u4TxDoneIntCnt[1]), + DIV2INT(prStatCnt->u4TxDoneCnt[2], prStatCnt->u4TxDoneIntCnt[2]), + DIV2DEC(prStatCnt->u4TxDoneCnt[2], prStatCnt->u4TxDoneIntCnt[2]), + DIV2INT(prStatCnt->u4TxDoneCnt[3], prStatCnt->u4TxDoneIntCnt[3]), + DIV2DEC(prStatCnt->u4TxDoneCnt[3], prStatCnt->u4TxDoneIntCnt[3])); + + LOGBUF(pucBuf, u4Max, u4Len, "AC10~13[%u.%u, %u.%u, %u.%u, %u.%u]\n", + DIV2INT(prStatCnt->u4TxDoneCnt[4], prStatCnt->u4TxDoneIntCnt[4]), + DIV2DEC(prStatCnt->u4TxDoneCnt[4], prStatCnt->u4TxDoneIntCnt[4]), + DIV2INT(prStatCnt->u4TxDoneCnt[5], prStatCnt->u4TxDoneIntCnt[5]), + DIV2DEC(prStatCnt->u4TxDoneCnt[5], prStatCnt->u4TxDoneIntCnt[5]), + DIV2INT(prStatCnt->u4TxDoneCnt[6], prStatCnt->u4TxDoneIntCnt[6]), + DIV2DEC(prStatCnt->u4TxDoneCnt[5], prStatCnt->u4TxDoneIntCnt[5]), + DIV2INT(prStatCnt->u4TxDoneCnt[7], prStatCnt->u4TxDoneIntCnt[7]), + DIV2DEC(prStatCnt->u4TxDoneCnt[7], prStatCnt->u4TxDoneIntCnt[7])); + + LOGBUF(pucBuf, u4Max, u4Len, "AC20~23[%u.%u, %u.%u, %u.%u, %u.%u] FFA,CPU[%u.%u, %u.%u]\n", + DIV2INT(prStatCnt->u4TxDoneCnt[8], prStatCnt->u4TxDoneIntCnt[8]), + DIV2DEC(prStatCnt->u4TxDoneCnt[8], prStatCnt->u4TxDoneIntCnt[8]), + DIV2INT(prStatCnt->u4TxDoneCnt[9], prStatCnt->u4TxDoneIntCnt[9]), + DIV2DEC(prStatCnt->u4TxDoneCnt[9], prStatCnt->u4TxDoneIntCnt[9]), + DIV2INT(prStatCnt->u4TxDoneCnt[10], prStatCnt->u4TxDoneIntCnt[10]), + DIV2DEC(prStatCnt->u4TxDoneCnt[10], prStatCnt->u4TxDoneIntCnt[10]), + DIV2INT(prStatCnt->u4TxDoneCnt[11], prStatCnt->u4TxDoneIntCnt[11]), + DIV2DEC(prStatCnt->u4TxDoneCnt[11], prStatCnt->u4TxDoneIntCnt[11]), + DIV2INT(prStatCnt->u4TxDoneCnt[14], prStatCnt->u4TxDoneIntCnt[14]), + DIV2DEC(prStatCnt->u4TxDoneCnt[14], prStatCnt->u4TxDoneIntCnt[14]), + DIV2INT(prStatCnt->u4TxDoneCnt[15], prStatCnt->u4TxDoneIntCnt[15]), + DIV2DEC(prStatCnt->u4TxDoneCnt[15], prStatCnt->u4TxDoneIntCnt[15])); + + LOGBUF(pucBuf, u4Max, u4Len, "Pending pkt/int[%u.%u] kick/int[%u.%u] rx_enh/sts[%u.%u]\n", + DIV2INT(prStatCnt->u4TxDonePendingPktCnt, prStatCnt->u4TxDoneIntTotCnt), + DIV2DEC(prStatCnt->u4TxDonePendingPktCnt, prStatCnt->u4TxDoneIntTotCnt), + DIV2INT(prStatCnt->u4DataPortKickCnt, prStatCnt->u4TxDoneIntTotCnt), + DIV2DEC(prStatCnt->u4DataPortKickCnt, prStatCnt->u4TxDoneIntTotCnt), + DIV2INT((prStatCnt->u4IntCnt - prStatCnt->u4IntReadCnt), prStatCnt->u4IntCnt), + DIV2DEC((prStatCnt->u4IntCnt - prStatCnt->u4IntReadCnt), prStatCnt->u4IntCnt)); + +#if CFG_SDIO_TIMING_PROFILING + LOGBUF(pucBuf, u4Max, u4Len, "Tx cp_t/pkt[%u.%uus] free/pkt[%u.%uus]\n", + DIV2INT(prStatCnt->u4TxDataCpTime, prStatCnt->u4DataPktWriteCnt), + DIV2DEC(prStatCnt->u4TxDataCpTime, prStatCnt->u4DataPktWriteCnt), + DIV2INT(prStatCnt->u4TxDataFreeTime, prStatCnt->u4DataPktWriteCnt), + DIV2DEC(prStatCnt->u4TxDataFreeTime, prStatCnt->u4DataPktWriteCnt)); + + LOGBUF(pucBuf, u4Max, u4Len, "Rx P0 cp_t/pkt[%u.%uus] avg read[%u.%uus]\n", + DIV2INT(prStatCnt->u4RxDataCpTime, prStatCnt->u4PktReadCnt[0]), + DIV2DEC(prStatCnt->u4RxDataCpTime, prStatCnt->u4PktReadCnt[0]), + DIV2INT(prStatCnt->u4PortReadTime, prStatCnt->u4PortReadCnt[0]), + DIV2DEC(prStatCnt->u4PortReadTime, prStatCnt->u4PortReadCnt[0])); + + LOGBUF(pucBuf, u4Max, u4Len, "INT rd_sts/sts[%u.%uus] tx_sts/sts[%u.%uus]\n", + DIV2INT(prStatCnt->u4IntReadTime, prStatCnt->u4IntReadCnt), + DIV2DEC(prStatCnt->u4IntReadTime, prStatCnt->u4IntReadCnt), + DIV2INT(prStatCnt->u4TxDoneIntTime, prStatCnt->u4TxDoneIntTotCnt), + DIV2DEC(prStatCnt->u4TxDoneIntTime, prStatCnt->u4TxDoneIntTotCnt)); +#endif + + LOGBUF(pucBuf, u4Max, u4Len, "---------------------------------\n"); + + for (u4Idx = 0; u4Idx < CFG_SDIO_INT_LOG_CNT; u4Idx++) { + struct SDIO_INT_LOG_T *prIntLog = &prHifInfo->arIntLog[u4Idx]; + struct ENHANCE_MODE_DATA_STRUCT *prIntSts = (struct ENHANCE_MODE_DATA_STRUCT *)&prIntLog->aucIntSts[0]; + uint8_t ucPktIdx; + + LOGBUF(pucBuf, u4Max, u4Len, "INT IDX[%u] STS[0x%08x] FG[0x%08x] Rx Pkt[%u] Sts0/1[%u:%u]\n", + prIntLog->u4Idx, prIntSts->u4WHISR, prIntLog->u4Flag, prIntLog->ucRxPktCnt, + prIntSts->rRxInfo.u.u2NumValidRx0Len, prIntSts->rRxInfo.u.u2NumValidRx1Len); + + if (prIntLog->ucRxPktCnt) { + LOGBUF(pucBuf, u4Max, u4Len, "RxDAggLen["); + for (ucPktIdx = 0; ucPktIdx < prIntLog->ucRxPktCnt; ucPktIdx++) + LOGBUF(pucBuf, u4Max, u4Len, "%4u:", prIntLog->au2RxPktLen[ucPktIdx]); + LOGBUF(pucBuf, u4Max, u4Len, "]\n"); + + LOGBUF(pucBuf, u4Max, u4Len, "RxDAggSn ["); + for (ucPktIdx = 0; ucPktIdx < prIntLog->ucRxPktCnt; ucPktIdx++) + LOGBUF(pucBuf, u4Max, u4Len, "0x%08x: ", prIntLog->au4RxPktInfo[ucPktIdx]); + LOGBUF(pucBuf, u4Max, u4Len, "]\n"); + } + + if (prIntSts->rRxInfo.u.u2NumValidRx0Len) { + LOGBUF(pucBuf, u4Max, u4Len, "Rx0StsLen["); + for (ucPktIdx = 0; ucPktIdx < prIntSts->rRxInfo.u.u2NumValidRx0Len; ucPktIdx++) + LOGBUF(pucBuf, u4Max, u4Len, "%4u:", prIntSts->rRxInfo.u.au2Rx0Len[ucPktIdx]); + LOGBUF(pucBuf, u4Max, u4Len, "]\n"); + } + + if (prIntSts->rRxInfo.u.u2NumValidRx1Len) { + LOGBUF(pucBuf, u4Max, u4Len, "Rx1StsLen["); + for (ucPktIdx = 0; ucPktIdx < HIF_RX_MAX_AGG_NUM; ucPktIdx++) + LOGBUF(pucBuf, u4Max, u4Len, "%4u:", prIntSts->rRxInfo.u.au2Rx1Len[ucPktIdx]); + LOGBUF(pucBuf, u4Max, u4Len, "]\n"); + } + } + + LOGBUF(pucBuf, u4Max, u4Len, "---------------------------------\n"); + + /* Reset statistic counter */ + kalMemZero(prStatCnt, sizeof(struct SDIO_STAT_COUNTER)); + + halDumpIntLog(prAdapter); + + return u4Len; +} + +#if (CFG_SDIO_ACCESS_N9_REGISTER_BY_MAILBOX == 1) +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* This routine is used to get the value of N9 register +* by SDIO SW interrupt and mailbox. +* +* \param[in] +* pvAdapter: Pointer to the Adapter structure. +* addr: the interested address to be read +* prresult: to stored the value of the addr +* +* \return +* the error of the reading operation +*/ +/*----------------------------------------------------------------------------*/ + +u_int8_t halReadN9RegisterByMailBox(IN struct ADAPTER *prAdapter, IN uint32_t addr, IN uint32_t *prresult) +{ + uint32_t ori_whlpcr, temp, counter = 0; + u_int8_t err = TRUE, stop = FALSE; + + /* use polling mode */ + HAL_MCR_RD(prAdapter, MCR_WHLPCR, &ori_whlpcr); /* backup the original setting of W_INT_EN */ + ori_whlpcr &= WHLPCR_INT_EN_SET; + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_INT_EN_CLR); /* disabel interrupt */ + + /* progrqm h2d mailbox0 as interested register address */ + HAL_MCR_WR(prAdapter, MCR_H2DSM0R, addr); + + /* set h2d interrupt to notify firmware (bit16) */ + HAL_MCR_WR(prAdapter, MCR_WSICR, SDIO_MAILBOX_FUNC_READ_REG_IDX); + + /* polling interrupt status for the returned result */ + while (!stop) { + HAL_MCR_RD(prAdapter, MCR_WHISR, &temp); /* read clear mode */ + if (temp & SDIO_MAILBOX_FUNC_READ_REG_IDX) { + /* get the result */ + + /* read d2h mailbox0 for interested register address */ + HAL_MCR_RD(prAdapter, MCR_D2HRM0R, &temp); + if (temp == addr) { + /* read d2h mailbox1 for the value of the register */ + HAL_MCR_RD(prAdapter, MCR_D2HRM1R, prresult); + err = FALSE; + } else { + DBGLOG(HAL, ERROR, "halReadN9RegisterByMailBox >> interested address is not correct.\n"); + } + stop = TRUE; + } else { +counter++; + +if (counter > 300000) { + DBGLOG(HAL, ERROR, "halReadN9RegisterByMailBox >> get response failure.\n"); + ASSERT(0); + break; + } + } + } + + HAL_MCR_WR(prAdapter, MCR_WHLPCR, ori_whlpcr); /* restore the W_INT_EN */ + + return err; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* This routine is used to write the value of N9 register by SDIO SW interrupt and mailbox. +* +* \param[in] +* pvAdapter: Pointer to the Adapter structure. +* addr: the interested address to be write +* value: the value to write into the addr +* +* \return +* the error of the write operation +*/ +/*----------------------------------------------------------------------------*/ + +u_int8_t halWriteN9RegisterByMailBox(IN struct ADAPTER *prAdapter, IN uint32_t addr, IN uint32_t value) +{ + uint32_t ori_whlpcr, temp, counter = 0; + u_int8_t err = TRUE, stop = FALSE; + + /* use polling mode */ + HAL_MCR_RD(prAdapter, MCR_WHLPCR, &ori_whlpcr); /* backup the original setting of W_INT_EN */ + ori_whlpcr &= WHLPCR_INT_EN_SET; + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_INT_EN_CLR); /* disabel interrupt */ + + /* progrqm h2d mailbox0 as interested register address */ + HAL_MCR_WR(prAdapter, MCR_H2DSM0R, addr); + + /* progrqm h2d mailbox1 as the value to write */ + HAL_MCR_WR(prAdapter, MCR_H2DSM1R, value); + + /* set h2d interrupt to notify firmware (bit17) */ + HAL_MCR_WR(prAdapter, MCR_WSICR, SDIO_MAILBOX_FUNC_WRITE_REG_IDX); + + /* polling interrupt status for the returned result */ + while (!stop) { + HAL_MCR_RD(prAdapter, MCR_WHISR, &temp); /* read clear mode */ + + if (temp & SDIO_MAILBOX_FUNC_WRITE_REG_IDX) { + /* get the result */ + + /* read d2h mailbox0 for interested register address */ + HAL_MCR_RD(prAdapter, MCR_D2HRM0R, &temp); + if (temp == addr) + err = FALSE; + else { + DBGLOG(HAL, ERROR, "halWriteN9RegisterByMailBox >> "); + DBGLOG(HAL, ERROR, "interested address is not correct.\n"); + } + stop = TRUE; + } else { + counter++; + +if (counter > 300000) { + DBGLOG(HAL, ERROR, "halWriteN9RegisterByMailBox >> get response failure.\n"); + ASSERT(0); + break; + } + } + } + + HAL_MCR_WR(prAdapter, MCR_WHLPCR, ori_whlpcr); /* restore the W_INT_EN */ + + return err; +} +#endif + +u_int8_t halIsPendingRx(IN struct ADAPTER *prAdapter) +{ + return FALSE; +} + +uint32_t halGetValidCoalescingBufSize(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo; + uint32_t u4BufSize; +#if (MTK_WCN_HIF_SDIO == 0) + struct sdio_func *prSdioFunc; + uint32_t u4RuntimeMaxBuf; + +#endif + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + if (HIF_TX_COALESCING_BUFFER_SIZE > HIF_RX_COALESCING_BUFFER_SIZE) + u4BufSize = HIF_TX_COALESCING_BUFFER_SIZE; + else + u4BufSize = HIF_RX_COALESCING_BUFFER_SIZE; + +#if (MTK_WCN_HIF_SDIO == 0) + prSdioFunc = prHifInfo->func; + + /* Check host capability */ + /* 1. Should less than host-max_req_size */ + if (u4BufSize > prSdioFunc->card->host->max_req_size) + u4BufSize = prSdioFunc->card->host->max_req_size; + + /* 2. Should less than runtime-blksize * host-blk_count */ + u4RuntimeMaxBuf = prSdioFunc->cur_blksize * + prSdioFunc->card->host->max_blk_count; + if (u4BufSize > u4RuntimeMaxBuf) + u4BufSize = u4RuntimeMaxBuf; + + DBGLOG(INIT, TRACE, "\n" + "Final buf : 0x%X\n" + "Default TX buf : 0x%X\n" + "Default RX buf : 0x%X\n" + "Host caps -\n" + "max_req_size : 0x%X\n" + "max_seg_size : 0x%X\n" + "max_segs : 0x%X\n" + "max_blk_size : 0x%X\n" + "max_blk_count : 0x%X\n" + "Runtime -\n" + "cur_blksize : 0x%X\n", + u4BufSize, + HIF_TX_COALESCING_BUFFER_SIZE, + HIF_RX_COALESCING_BUFFER_SIZE, + prSdioFunc->card->host->max_req_size, + prSdioFunc->card->host->max_seg_size, + prSdioFunc->card->host->max_segs, + prSdioFunc->card->host->max_blk_size, + prSdioFunc->card->host->max_blk_count, + prSdioFunc->cur_blksize); +#endif + + return u4BufSize; +} + +uint32_t halAllocateIOBuffer(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo; + uint8_t ucIdx; + struct SDIO_RX_COALESCING_BUF *prRxBuf; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + /* 4 <5> Memory for enhanced interrupt response */ + prHifInfo->prSDIOCtrl = (struct ENHANCE_MODE_DATA_STRUCT *) + kalAllocateIOBuffer(sizeof(struct ENHANCE_MODE_DATA_STRUCT)); + + if (prHifInfo->prSDIOCtrl == NULL) { + DBGLOG(HAL, ERROR, + "Could not allocate %d bytes for interrupt response.\n", + sizeof(struct ENHANCE_MODE_DATA_STRUCT)); + + return WLAN_STATUS_RESOURCES; + } + + /* Alloc coalescing buffer */ + for (ucIdx = 0; ucIdx < HIF_RX_COALESCING_BUF_COUNT; ucIdx++) { + prRxBuf = &prHifInfo->rRxCoalesingBuf[ucIdx]; + + prRxBuf->u4PktCount = 0; + + prRxBuf->u4BufSize = HIF_RX_COALESCING_BUFFER_SIZE; + prRxBuf->pvRxCoalescingBuf = kalAllocateIOBuffer(prRxBuf->u4BufSize); + if (!prRxBuf->pvRxCoalescingBuf) { + DBGLOG(HAL, ERROR, "Rx coalescing alloc failed!\n"); + continue; + } + + QUEUE_INSERT_TAIL(&prHifInfo->rRxFreeBufQueue, &prRxBuf->rQueEntry); + } + + return WLAN_STATUS_SUCCESS; +} + +uint32_t halReleaseIOBuffer(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo; + uint8_t ucIdx; + struct SDIO_RX_COALESCING_BUF *prRxBuf; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + /* Release coalescing buffer */ + for (ucIdx = 0; ucIdx < HIF_RX_COALESCING_BUF_COUNT; ucIdx++) { + prRxBuf = &prHifInfo->rRxCoalesingBuf[ucIdx]; + kalReleaseIOBuffer(prRxBuf->pvRxCoalescingBuf, prRxBuf->u4BufSize); + prRxBuf->pvRxCoalescingBuf = NULL; + } + + /* 4 <5> Memory for enhanced interrupt response */ + if (prHifInfo->prSDIOCtrl) { + kalReleaseIOBuffer((void *) prHifInfo->prSDIOCtrl, sizeof(struct ENHANCE_MODE_DATA_STRUCT)); + prHifInfo->prSDIOCtrl = (struct ENHANCE_MODE_DATA_STRUCT *) NULL; + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief dump firmware Assert message +* +* \param[in] +* prAdapter +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +void halPrintFirmwareAssertInfo(IN struct ADAPTER *prAdapter) +{ + uint32_t u4MailBox0, u4MailBox1; + uint32_t line = 0; + uint8_t aucAssertFile[7]; + /* UINT_32 u4ChipId; */ + +#if CFG_SDIO_INTR_ENHANCE + u4MailBox0 = prAdapter->prGlueInfo->rHifInfo.prSDIOCtrl->u4RcvMailbox0; + u4MailBox1 = prAdapter->prGlueInfo->rHifInfo.prSDIOCtrl->u4RcvMailbox1; +#else + halGetMailbox(prAdapter, 0, &u4MailBox0); + halGetMailbox(prAdapter, 1, &u4MailBox1); +#endif + + line = u4MailBox0 & 0x0000FFFF; + + u4MailBox0 = ((u4MailBox0 >> 16) & 0x0000FFFF); + + kalMemCopy(&aucAssertFile[0], &u4MailBox0, 2); + kalMemCopy(&aucAssertFile[2], &u4MailBox1, 4); + + aucAssertFile[6] = '\0'; + + LOG_FUNC("[%s][wifi][Firmware] Assert at \"%s\" #%u\n\n", + NIC_NAME, aucAssertFile, line); + +} + +void halPrintMailbox(IN struct ADAPTER *prAdapter) +{ + uint32_t u4MailBoxStatus0, u4MailBoxStatus1; + uint8_t fgResult; + + HAL_LP_OWN_RD(prAdapter, &fgResult); + if (fgResult != TRUE) + return; + + halGetMailbox(prAdapter, 0, &u4MailBoxStatus0); + halGetMailbox(prAdapter, 1, &u4MailBoxStatus1); + DBGFWLOG(INIT, ERROR, "MailBox Status = 0x%08X, 0x%08X\n", u4MailBoxStatus0, u4MailBoxStatus1); +} + +void halPrintIntStatus(IN struct ADAPTER *prAdapter) +{ +#if CFG_SDIO_INTR_ENHANCE + struct ENHANCE_MODE_DATA_STRUCT *prSDIOCtrl; + + prSDIOCtrl = prAdapter->prGlueInfo->rHifInfo.prSDIOCtrl; + ASSERT(prSDIOCtrl); + + DBGLOG_MEM32(REQ, WARN, prSDIOCtrl, sizeof(struct ENHANCE_MODE_DATA_STRUCT)); +#else + uint32_t u4IntStatus; + + HAL_MCR_RD(prAdapter, MCR_WHISR, u4IntStatus); + + DBGLOG(REQ, WARN, "INT status[0x%08x]\n", u4IntStatus); +#endif /* CFG_SDIO_INTR_ENHANCE */ +} + +void halDumpIntLog(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + struct SDIO_INT_LOG_T *prIntLog; + struct ENHANCE_MODE_DATA_STRUCT *prIntSts; + uint32_t u4Idx; + + for (u4Idx = 0; u4Idx < CFG_SDIO_INT_LOG_CNT; u4Idx++) { + prIntLog = &prHifInfo->arIntLog[u4Idx]; + prIntSts = (struct ENHANCE_MODE_DATA_STRUCT *)&prIntLog->aucIntSts[0]; + + DBGLOG(INTR, ERROR, "INT IDX[%u] STS[0x%08x] FG[0x%08x] Rx Pkt[%u] Sts0/1[%u:%u]\n", + prIntLog->u4Idx, prIntSts->u4WHISR, prIntLog->u4Flag, prIntLog->ucRxPktCnt, + prIntSts->rRxInfo.u.u2NumValidRx0Len, prIntSts->rRxInfo.u.u2NumValidRx1Len); + DBGLOG_MEM32(INTR, ERROR, &prIntLog->au2RxPktLen[0], sizeof(uint16_t) * HIF_RX_MAX_AGG_NUM); + DBGLOG_MEM32(INTR, ERROR, &prIntLog->au4RxPktInfo[0], sizeof(uint32_t) * HIF_RX_MAX_AGG_NUM); + DBGLOG_MEM32(INTR, ERROR, prIntSts, sizeof(struct ENHANCE_MODE_DATA_STRUCT)); + } + + DBGLOG(INTR, ERROR, "---------------------------------\n"); +} + +void halTagIntLog(IN struct ADAPTER *prAdapter, IN enum HIF_SDIO_INT_STS eTag) +{ + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + prHifInfo->arIntLog[prHifInfo->ucIntLogEntry].u4Flag |= BIT(eTag); +} + +void halRecIntLog(IN struct ADAPTER *prAdapter, IN struct ENHANCE_MODE_DATA_STRUCT *prSDIOCtrl) +{ + struct SDIO_INT_LOG_T *prIntLog; + uint8_t ucLogEntry; + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + prHifInfo->u4IntLogIdx++; + ucLogEntry = prHifInfo->u4IntLogIdx % CFG_SDIO_INT_LOG_CNT; + prIntLog = &prHifInfo->arIntLog[ucLogEntry]; + kalMemZero(prIntLog, sizeof(struct SDIO_INT_LOG_T)); + + prIntLog->u4Idx = prHifInfo->u4IntLogIdx; + prHifInfo->ucIntLogEntry = ucLogEntry; + kalMemCopy(&prIntLog->aucIntSts[0], prSDIOCtrl, sizeof(struct ENHANCE_MODE_DATA_STRUCT)); +} + +struct SDIO_INT_LOG_T *halGetIntLog(IN struct ADAPTER *prAdapter, IN uint32_t u4Idx) +{ + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + return &prHifInfo->arIntLog[u4Idx % CFG_SDIO_INT_LOG_CNT]; +} + +void halProcessAbnormalInterrupt(IN struct ADAPTER *prAdapter) +{ + uint32_t u4Data = 0; + uint8_t fgResult; + + HAL_LP_OWN_RD(prAdapter, &fgResult); + if (fgResult == TRUE) { + /* Need driver own */ + HAL_MCR_RD(prAdapter, MCR_WASR, &u4Data); + } + + halPollDbgCr(prAdapter, 5); + halPrintIntStatus(prAdapter); + + if (u4Data & (WASR_RX0_UNDER_FLOW | WASR_RX1_UNDER_FLOW)) { + DBGLOG(REQ, WARN, "Skip all SDIO Rx due to Rx underflow error!\n"); + prAdapter->prGlueInfo->rHifInfo.fgSkipRx = TRUE; + halDumpHifStatus(prAdapter, NULL, 0); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP); + } + + halDumpIntLog(prAdapter); +} + +void halProcessSoftwareInterrupt(IN struct ADAPTER *prAdapter) +{ + uint32_t u4IntrBits; + + ASSERT(prAdapter); + + u4IntrBits = prAdapter->u4IntStatus & BITS(8, 31); + + if ((u4IntrBits & WHISR_D2H_SW_ASSERT_INFO_INT) != 0) { + halPrintFirmwareAssertInfo(prAdapter); +#if CFG_CHIP_RESET_SUPPORT + glSendResetRequest(); +#endif + } + + if (u4IntrBits & WHISR_D2H_WKUP_BY_RX_PACKET) + DBGLOG(RX, INFO, "Wake up by Rx\n"); + + if (u4IntrBits & WHISR_D2H_SW_RD_MAILBOX_INT) + halPrintMailbox(prAdapter); + + if (u4IntrBits & SER_SDIO_N9_HOST_STOP_TX_OP) { + halPrintMailbox(prAdapter); + /* Stop HIF Tx operation */ + nicSerStopTx(prAdapter); + } + + if (u4IntrBits & SER_SDIO_N9_HOST_STOP_TX_RX_OP) { + halPrintMailbox(prAdapter); + /* Stop HIF Tx/Rx operation */ + nicSerStopTxRx(prAdapter); + } + + if ((u4IntrBits & ~WHISR_D2H_WKUP_BY_RX_PACKET) != 0) + DBGLOG(SW4, WARN, "u4IntrBits: 0x%08x\n", u4IntrBits); + +} /* end of halProcessSoftwareInterrupt() */ + +void halPutMailbox(IN struct ADAPTER *prAdapter, IN uint32_t u4MailboxNum, IN uint32_t u4Data) +{ + + switch (u4MailboxNum) { + case 0: + HAL_MCR_WR(prAdapter, MCR_H2DSM0R, u4Data); + break; + case 1: + HAL_MCR_WR(prAdapter, MCR_H2DSM1R, u4Data); + break; + + default: + ASSERT(0); + } + +} + +void halGetMailbox(IN struct ADAPTER *prAdapter, IN uint32_t u4MailboxNum, OUT uint32_t *pu4Data) +{ + switch (u4MailboxNum) { + case 0: + HAL_MCR_RD(prAdapter, MCR_D2HRM0R, pu4Data); + break; + case 1: + HAL_MCR_RD(prAdapter, MCR_D2HRM1R, pu4Data); + break; + + default: + ASSERT(0); + } +} + +u_int8_t halDeAggErrorCheck(struct ADAPTER *prAdapter, + struct SDIO_RX_COALESCING_BUF *prRxBuf, + uint8_t *pucPktAddr) +{ + struct mt66xx_chip_info *prChipInfo; + uint16_t u2PktLength = 0; + uint8_t *pucRxBufEnd; + struct RX_DESC_OPS_T *prRxDescOps; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + prRxDescOps = prChipInfo->prRxDescOps; + + pucRxBufEnd = (uint8_t *)prRxBuf->pvRxCoalescingBuf + prRxBuf->u4PktTotalLength; + + if (prRxDescOps->nic_rxd_get_rx_byte_count) + u2PktLength = + prRxDescOps->nic_rxd_get_rx_byte_count(pucPktAddr); + + /* Rx buffer boundary check */ + if ((pucPktAddr + ALIGN_4(u2PktLength + HIF_RX_HW_APPENDED_LEN)) >= pucRxBufEnd) + return TRUE; + + /* Rx packet min length check */ + if (u2PktLength <= prChipInfo->rxd_size) + return TRUE; + + /* Rx packet max length check */ + if (u2PktLength >= CFG_RX_MAX_PKT_SIZE) + return TRUE; + + return FALSE; +} + +void halDeAggRxPktWorker(struct work_struct *work) +{ + struct GLUE_INFO *prGlueInfo; + struct GL_HIF_INFO *prHifInfo; + struct ADAPTER *prAdapter; + struct SDIO_RX_COALESCING_BUF *prRxBuf; + uint32_t i; + struct QUE rTempFreeRfbList, rTempRxRfbList; + struct QUE *prTempFreeRfbList = &rTempFreeRfbList; + struct QUE *prTempRxRfbList = &rTempRxRfbList; + struct RX_CTRL *prRxCtrl; + struct SW_RFB *prSwRfb = (struct SW_RFB *) NULL; + uint8_t *pucSrcAddr; + uint16_t u2PktLength; + u_int8_t fgReschedule = FALSE; +#if CFG_TCP_IP_CHKSUM_OFFLOAD + uint32_t *pu4HwAppendDW; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + u_int8_t fgDeAggErr = FALSE; + struct SDIO_INT_LOG_T *prIntLog; + uint64_t u8Current = 0; + struct RX_DESC_OPS_T *prRxDescOps; + + KAL_SPIN_LOCK_DECLARATION(); + SDIO_TIME_INTERVAL_DEC(); + + if (g_u4HaltFlag) + return; + + prGlueInfo = ENTRY_OF(work, struct GLUE_INFO, rRxPktDeAggWork); + prHifInfo = &prGlueInfo->rHifInfo; + prAdapter = prGlueInfo->prAdapter; + prRxDescOps = prAdapter->chip_info->prRxDescOps; + ASSERT(prRxDescOps->nic_rxd_get_rx_byte_count); + ASSERT(prRxDescOps->nic_rxd_get_pkt_type); + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) + return; + + prRxCtrl = &prAdapter->rRxCtrl; + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + QUEUE_INITIALIZE(prTempFreeRfbList); + QUEUE_INITIALIZE(prTempRxRfbList); + + mutex_lock(&prHifInfo->rRxDeAggQueMutex); + QUEUE_REMOVE_HEAD(&prHifInfo->rRxDeAggQueue, prRxBuf, struct SDIO_RX_COALESCING_BUF *); + mutex_unlock(&prHifInfo->rRxDeAggQueMutex); + while (prRxBuf) { + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + if (prRxCtrl->rFreeSwRfbList.u4NumElem < prRxBuf->u4PktCount) { + fgReschedule = TRUE; + } else { + /* Get enough free SW_RFB to be Rx */ + for (i = 0; i < prRxBuf->u4PktCount; i++) { + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, struct SW_RFB *); + QUEUE_INSERT_TAIL(prTempFreeRfbList, &prSwRfb->rQueEntry); + } + fgReschedule = FALSE; + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + if (fgReschedule) { + mutex_lock(&prHifInfo->rRxDeAggQueMutex); + QUEUE_INSERT_HEAD(&prHifInfo->rRxDeAggQueue, (struct QUE_ENTRY *)prRxBuf); + mutex_unlock(&prHifInfo->rRxDeAggQueMutex); + + /* Reschedule this work */ + if ((prGlueInfo->ulFlag & GLUE_FLAG_HALT) == 0) + schedule_delayed_work(&prAdapter->prGlueInfo->rRxPktDeAggWork, 0); + + return; + } + + pucSrcAddr = prRxBuf->pvRxCoalescingBuf; + fgDeAggErr = FALSE; + + prIntLog = halGetIntLog(prAdapter, prRxBuf->u4IntLogIdx); + u8Current = sched_clock(); + + SDIO_REC_TIME_START(); + for (i = 0; i < prRxBuf->u4PktCount; i++) { + /* Rx de-aggregation check */ + if (halDeAggErrorCheck(prAdapter, prRxBuf, + pucSrcAddr)) { + fgDeAggErr = TRUE; + break; + } + + u2PktLength = prRxDescOps->nic_rxd_get_rx_byte_count( + pucSrcAddr); + + prIntLog->au2RxPktLen[i] = u2PktLength; + + QUEUE_REMOVE_HEAD(prTempFreeRfbList, prSwRfb, struct SW_RFB *); + kalMemCopy(prSwRfb->pucRecvBuff, pucSrcAddr, ALIGN_4(u2PktLength + HIF_RX_HW_APPENDED_LEN)); + + prSwRfb->ucPacketType = + prRxDescOps->nic_rxd_get_pkt_type(pucSrcAddr); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + pu4HwAppendDW = (uint32_t *) prSwRfb->prRxStatus; + pu4HwAppendDW += (ALIGN_4(u2PktLength) >> 2); + prSwRfb->u4TcpUdpIpCksStatus = *pu4HwAppendDW; + DBGLOG(RX, TRACE, "u4TcpUdpIpCksStatus[0x%02x]\n", prSwRfb->u4TcpUdpIpCksStatus); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + kalMemCopy(&prIntLog->au4RxPktInfo[i], pucSrcAddr + ALIGN_4(u2PktLength), sizeof(uint32_t)); + + GLUE_RX_SET_PKT_INT_TIME(prSwRfb->pvPacket, prAdapter->prGlueInfo->u8HifIntTime); + + GLUE_RX_SET_PKT_RX_TIME(prSwRfb->pvPacket, u8Current); + + QUEUE_INSERT_TAIL(prTempRxRfbList, &prSwRfb->rQueEntry); + + pucSrcAddr += ALIGN_4(u2PktLength + HIF_RX_HW_APPENDED_LEN); + } + SDIO_REC_TIME_END(); + SDIO_ADD_TIME_INTERVAL(prHifInfo->rStatCounter.u4RxDataCpTime); + + prIntLog->ucRxPktCnt = i; + + if (fgDeAggErr) { + /* Rx de-aggregation error */ + /* Dump current Rx buffer */ + DBGLOG(RX, ERROR, "Rx de-aggregation error!, INT sts: total len[%u] pkt cnt[%u]\n", + prRxBuf->u4PktTotalLength, prRxBuf->u4PktCount); + DBGLOG_MEM32(RX, ERROR, prRxBuf->pvRxCoalescingBuf, prRxBuf->u4PktTotalLength); + + halDumpIntLog(prAdapter); + + /* Free all de-aggregated SwRfb */ + QUEUE_CONCATENATE_QUEUES(prTempFreeRfbList, prTempRxRfbList); + } else { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + RX_ADD_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT, prTempRxRfbList->u4NumElem); + QUEUE_CONCATENATE_QUEUES(&prRxCtrl->rReceivedRfbList, prTempRxRfbList); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + /* Wake up Rx handling thread */ + set_bit(GLUE_FLAG_RX_BIT, &(prAdapter->prGlueInfo->ulFlag)); + wake_up_interruptible(&(prAdapter->prGlueInfo->waitq)); + } + + if (prTempFreeRfbList->u4NumElem) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_CONCATENATE_QUEUES(&prRxCtrl->rFreeSwRfbList, prTempFreeRfbList); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + } + + prRxBuf->u4PktCount = 0; + mutex_lock(&prHifInfo->rRxFreeBufQueMutex); + QUEUE_INSERT_TAIL(&prHifInfo->rRxFreeBufQueue, (struct QUE_ENTRY *)prRxBuf); + mutex_unlock(&prHifInfo->rRxFreeBufQueMutex); + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) + return; + + mutex_lock(&prHifInfo->rRxDeAggQueMutex); + QUEUE_REMOVE_HEAD(&prHifInfo->rRxDeAggQueue, prRxBuf, struct SDIO_RX_COALESCING_BUF *); + mutex_unlock(&prHifInfo->rRxDeAggQueMutex); + } +} + +void halDeAggRxPkt(struct ADAPTER *prAdapter, struct SDIO_RX_COALESCING_BUF *prRxBuf) +{ + struct GL_HIF_INFO *prHifInfo; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + /* Avoid to schedule DeAggWorker during uninit flow */ + if (prAdapter->prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + mutex_lock(&prHifInfo->rRxFreeBufQueMutex); + QUEUE_INSERT_TAIL(&prHifInfo->rRxFreeBufQueue, (struct QUE_ENTRY *)prRxBuf); + mutex_unlock(&prHifInfo->rRxFreeBufQueMutex); + + return; + } + + mutex_lock(&prHifInfo->rRxDeAggQueMutex); + QUEUE_INSERT_TAIL(&prHifInfo->rRxDeAggQueue, (struct QUE_ENTRY *)prRxBuf); + mutex_unlock(&prHifInfo->rRxDeAggQueMutex); + + schedule_delayed_work(&prAdapter->prGlueInfo->rRxPktDeAggWork, 0); +} + +void halRxTasklet(unsigned long data) +{ + +} + +void halTxCompleteTasklet(unsigned long data) +{ + +} + +/* Hif power off wifi */ +uint32_t halHifPowerOffWifi(IN struct ADAPTER *prAdapter) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + if (prAdapter->rAcpiState == ACPI_STATE_D0 && + !wlanIsChipNoAck(prAdapter) && !kalIsCardRemoved(prAdapter->prGlueInfo)) { + /* 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) { + uint32_t i; + /* 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 */ + rStatus = wlanCheckWifiFunc(prAdapter, FALSE); + } +#if !CFG_ENABLE_FULL_PM + /* 4. Set Onwership to F/W */ + nicpmSetFWOwn(prAdapter, FALSE); +#endif + +#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); + } + return rStatus; +} + +void halPollDbgCr(IN struct ADAPTER *prAdapter, IN uint32_t u4LoopCount) +{ + uint32_t au4Value[] = {MCR_WCIR, MCR_WHLPCR, MCR_D2HRM2R}; + uint32_t au4Value1[] = {MCR_WHIER, MCR_D2HRM0R, MCR_D2HRM1R}; + uint32_t u4Loop = 0; + uint32_t u4Data = 0; + uint8_t i = 0, fgResult; +#if MTK_WCN_HIF_SDIO + uint8_t *pucCCR = (uint8_t *)&au4Value[0]; + unsigned long cltCtx = prAdapter->prGlueInfo->rHifInfo.cltCtx; +#endif + + for (; i < sizeof(au4Value)/sizeof(uint32_t); i++) + HAL_MCR_RD(prAdapter, au4Value[i], &au4Value[i]); + DBGLOG(REQ, WARN, "MCR_WCIR:0x%x, MCR_WHLPCR:0x%x, MCR_D2HRM2R:0x%x\n", + au4Value[0], au4Value[1], au4Value[2]); + + /* Need driver own */ + HAL_LP_OWN_RD(prAdapter, &fgResult); + if (fgResult == TRUE) { + /* dump N9 programming counter */ + for (u4Loop = 0; u4Loop < u4LoopCount; u4Loop++) { + HAL_MCR_RD(prAdapter, MCR_SWPCDBGR, &u4Data); + DBGLOG(INIT, WARN, "SWPCDBGR 0x%08X\n", u4Data); + } + + /* dump others */ + for (i = 0; i < sizeof(au4Value1)/sizeof(uint32_t); i++) + HAL_MCR_RD(prAdapter, au4Value1[i], &au4Value1[i]); + + DBGLOG(REQ, WARN, "MCR_WHIER:0x%x, MCR_D2HRM0R:0x%x", + au4Value1[0], au4Value1[1]); + DBGLOG(REQ, WARN, "MCR_D2HRM1R:0x%x\n", + au4Value1[2]); + } + +#if MTK_WCN_HIF_SDIO + for (i = 0; i < 8; i++) + mtk_wcn_hif_sdio_f0_readb(cltCtx, 0xf8 + i, &pucCCR[i]); + DBGLOG(REQ, WARN, "CCCR %02x %02x %02x %02x %02x %02x %02x %02x\n", + pucCCR[0], pucCCR[1], pucCCR[2], pucCCR[3], pucCCR[4], pucCCR[5], pucCCR[6], pucCCR[7]); +#endif +} + +void halSerHifReset(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + /* Restore Tx resource */ + halRestoreTxResource(prAdapter); + + /* Clear interrupt status from Rx interrupt enhance mode */ + prHifInfo->fgIsPendingInt = FALSE; + kalMemZero(prHifInfo->prSDIOCtrl, sizeof(struct ENHANCE_MODE_DATA_STRUCT)); +} + +u_int8_t halIsPendingTxDone(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + uint32_t i; + u_int8_t fgIsPendingTxDone = FALSE; + + for (i = TC0_INDEX; i <= TC4_INDEX; i++) { + if (prHifInfo->au4PendingTxDoneCount[i]) { + fgIsPendingTxDone = TRUE; + break; + } + } + + if (fgIsPendingTxDone) + DBGLOG(NIC, ERROR, "Missing Tx done[%u:%u:%u:%u:%u]\n", + prHifInfo->au4PendingTxDoneCount[TC0_INDEX], + prHifInfo->au4PendingTxDoneCount[TC1_INDEX], + prHifInfo->au4PendingTxDoneCount[TC2_INDEX], + prHifInfo->au4PendingTxDoneCount[TC3_INDEX], + prHifInfo->au4PendingTxDoneCount[TC4_INDEX]); + + return fgIsPendingTxDone; +} + +void halPrintHifDbgInfo(IN struct ADAPTER *prAdapter) +{ + if (prAdapter->u4HifDbgFlag & DEG_HIF_ALL || + prAdapter->u4HifDbgFlag & DEG_HIF_DEFAULT_DUMP) { + halPrintMailbox(prAdapter); + halPollDbgCr(prAdapter, LP_DBGCR_POLL_ROUND); + } + prAdapter->u4HifDbgFlag = 0; +} + +u_int8_t halIsTxResourceControlEn(IN struct ADAPTER *prAdapter) +{ + return TRUE; +} + +void halTxResourceResetHwTQCounter(IN struct ADAPTER *prAdapter) +{ + uint32_t *pu4WHISR = NULL; + uint16_t au2TxCount[16]; + + pu4WHISR = (uint32_t *)kalMemAlloc(sizeof(uint32_t), PHY_MEM_TYPE); + if (!pu4WHISR) { + DBGLOG(INIT, ERROR, "Allocate pu4WHISR fail\n"); + return; + } + + HAL_READ_INTR_STATUS(prAdapter, sizeof(uint32_t), (uint8_t *)pu4WHISR); + if (HAL_IS_TX_DONE_INTR(*pu4WHISR)) + HAL_READ_TX_RELEASED_COUNT(prAdapter, au2TxCount); + + if (pu4WHISR) + kalMemFree(pu4WHISR, PHY_MEM_TYPE, sizeof(uint32_t)); +} + +uint32_t halGetHifTxPageSize(IN struct ADAPTER *prAdapter) +{ + if (!prAdapter->chip_info->is_support_cr4) { + if (prAdapter->fgIsNicTxReousrceValid) + return prAdapter->nicTxReousrce.u4DataResourceUnit; + else + return HIF_TX_PAGE_SIZE_STORED_FORWARD; + } + + /*cr4 mode*/ + return HIF_TX_PAGE_SIZE; +} +/*----------------------------------------------------------------------------*/ +/*! +* @brief Generic update Tx done counter +* +* @param prAdapter Pointer to the Adapter structure. +* @param au2TxDoneCnt Pointer to the final reference table +* @param au2TxRlsCnt Pointer to the Tx done counter result got fom interrupt +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ + +void halTxGetFreeResource(IN struct ADAPTER *prAdapter, IN uint16_t *au2TxDoneCnt, IN uint16_t *au2TxRlsCnt) +{ + uint8_t i; + struct BUS_INFO *prBusInfo = prAdapter->chip_info->bus_info; + + if (prBusInfo->halTxGetFreeResource) + return prBusInfo->halTxGetFreeResource(prAdapter, au2TxDoneCnt, au2TxRlsCnt); + + /* 6632, 7668 ways */ + for (i = HIF_TX_AC0_INDEX; i <= HIF_TX_AC23_INDEX; i++) + au2TxDoneCnt[i % WMM_AC_INDEX_NUM] += au2TxRlsCnt[i]; + au2TxDoneCnt[HIF_TX_CPU_INDEX] = au2TxRlsCnt[HIF_TX_CPU_INDEX]; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Update Tx done counter for mt7663 +* +* @param prAdapter Pointer to the Adapter structure. +* @param au2TxDoneCnt Pointer to the final reference table +* @param au2TxRlsCnt Pointer to the Tx done counter result got fom interrupt +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ + +void halTxGetFreeResource_v1(IN struct ADAPTER *prAdapter, IN uint16_t *au2TxDoneCnt, IN uint16_t *au2TxRlsCnt) +{ + uint8_t i; + + for (i = HIF_TXC_IDX_0; i < HIF_TXC_IDX_NUM; i++) + au2TxDoneCnt[i] = au2TxRlsCnt[i]; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Generic return free resource to TCs +* +* @param prAdapter Pointer to the Adapter structure. +* @param au2TxDoneCnt Pointer to the final reference table +* @param au2TxRlsCnt Pointer to the Tx done counter result got fom interrupt +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ + +void halTxReturnFreeResource(IN struct ADAPTER *prAdapter, IN uint16_t *au2TxDoneCnt) +{ + uint8_t i; + struct BUS_INFO *prBusInfo = prAdapter->chip_info->bus_info; + uint16_t u2ReturnCnt; + + KAL_SPIN_LOCK_DECLARATION(); + + + if (prBusInfo->halTxReturnFreeResource) + prBusInfo->halTxReturnFreeResource(prAdapter, au2TxDoneCnt); + else { + /* 6632, 7668 ways */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + for (i = TC0_INDEX; i < TC_NUM; i++) { + u2ReturnCnt = au2TxDoneCnt[nicTxGetTxQByTc(prAdapter, i)]; + nicTxReleaseResource_PSE(prAdapter, i, u2ReturnCnt, FALSE); + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[i] -= u2ReturnCnt; + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Return free resource to TCs for mt7663 +* +* @param prAdapter Pointer to the Adapter structure. +* @param au2TxDoneCnt Pointer to the final reference table +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void halTxReturnFreeResource_v1(IN struct ADAPTER *prAdapter, IN uint16_t *au2TxDoneCnt) +{ + uint8_t i; + uint16_t u2ReturnCnt; + + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + /* WMM 1 */ + for (i = HIF_TXC_IDX_0; i <= HIF_TXC_IDX_8; i++) { + uint8_t ucTc; + + u2ReturnCnt = au2TxDoneCnt[i]; + + if (i < HIF_TXC_IDX_5) { + ucTc = HIF_TXC_IDX_2_TC_IDX_PSE(i); + nicTxReleaseResource_PSE(prAdapter, ucTc, u2ReturnCnt, FALSE); + } else { + ucTc = HIF_TXC_IDX_2_TC_IDX_PLE(i); + nicTxReleaseResource_PLE(prAdapter, ucTc, u2ReturnCnt, FALSE); + } + + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[i] -= u2ReturnCnt; + } + + /* WMM 2,3 */ + /*TBD*/ + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Generic rollback resource to TCs +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ + +void halRestoreTxResource(IN struct ADAPTER *prAdapter) +{ + uint8_t i; + struct BUS_INFO *prBusInfo = prAdapter->chip_info->bus_info; + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + if (prBusInfo->halRestoreTxResource) + prBusInfo->halRestoreTxResource(prAdapter); + else { + /* 6632, 7668 ways */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + for (i = TC0_INDEX; i < TC_NUM; i++) { + nicTxReleaseResource_PSE(prAdapter, i, prHifInfo->au4PendingTxDoneCount[i], FALSE); + prHifInfo->au4PendingTxDoneCount[i] = 0; + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Rollback resource to TCs for mt7663 +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ + +void halRestoreTxResource_v1(IN struct ADAPTER *prAdapter) +{ + uint8_t i; + + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + /* WMM 1 */ + /* PSE pages: HIF_TXC_IDX_0- */ + for (i = HIF_TXC_IDX_0; i <= HIF_TXC_IDX_4; i++) { + nicTxReleaseResource_PSE(prAdapter, HIF_TXC_IDX_2_TC_IDX_PSE(i), + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[i], + FALSE); + + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[i] = 0; + } + + /* PLE pages */ + for (i = HIF_TXC_IDX_5; i <= HIF_TXC_IDX_8; i++) { + nicTxReleaseResource_PLE(prAdapter, HIF_TXC_IDX_2_TC_IDX_PLE(i), + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[i], + FALSE); + + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[i] = 0; + } + + /* WMM 2,3 */ + /*TBD*/ + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); +} + +void halUpdateTxDonePendingCount(IN struct ADAPTER *prAdapter, IN u_int8_t isIncr, IN uint8_t ucTc, IN uint32_t u4Len) +{ + uint8_t u2PageCnt; + struct BUS_INFO *prBusInfo = prAdapter->chip_info->bus_info; + + u2PageCnt = halTxGetPageCount(prAdapter, u4Len, FALSE); + + if (prBusInfo->halUpdateTxDonePendingCount) + prBusInfo->halUpdateTxDonePendingCount(prAdapter, isIncr, ucTc, u2PageCnt); + else { + /* 6632, 7668 ways */ + if (isIncr) + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[ucTc] += u2PageCnt; + else + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[ucTc] -= u2PageCnt; + } +} + +void halUpdateTxDonePendingCount_v1(IN struct ADAPTER *prAdapter, IN u_int8_t isIncr, IN uint8_t ucTc, IN uint16_t u2Cnt) +{ + uint8_t idx; + + /* Update PSE part */ + idx = TC_IDX_PSE_2_HIF_TXC_IDX(ucTc); + + if (idx >= HIF_TXC_IDX_NUM) + ASSERT(0); + + if (isIncr) + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[idx] += u2Cnt; + else + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[idx] -= u2Cnt; + + /* Update PLE part */ + if (!nicTxResourceIsPleCtrlNeeded(prAdapter, ucTc)) + return; + + idx = TC_IDX_PLE_2_HIF_TXC_IDX(ucTc); + + if (idx >= HIF_TXC_IDX_NUM) + ASSERT(0); + + if (isIncr) + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[idx] += NIX_TX_PLE_PAGE_CNT_PER_FRAME; + else + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[idx] -= NIX_TX_PLE_PAGE_CNT_PER_FRAME; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Check if HIF state is READY for upper layer cfg80211 +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (TRUE: ready, FALSE: not ready) +*/ +/*----------------------------------------------------------------------------*/ +bool halIsHifStateReady(IN struct ADAPTER *prAdapter, uint8_t *pucState) +{ + /* SDIO owner should implement this function */ + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Check if HIF state is during supend process +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (TRUE: suspend, reject the caller action. FALSE: not suspend) +*/ +/*----------------------------------------------------------------------------*/ +bool halIsHifStateSuspend(IN struct ADAPTER *prAdapter) +{ + /* SDIO owner should implement this function */ + + return FALSE; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/include/hif.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/include/hif.h new file mode 100644 index 0000000000000..8a95d92791f2b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/include/hif.h @@ -0,0 +1,403 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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 +*/ + + +#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 +******************************************************************************** +*/ +#if MTK_WCN_HIF_SDIO +#define HIF_SDIO_SUPPORT_GPIO_SLEEP_MODE 1 +#else +#define HIF_SDIO_SUPPORT_GPIO_SLEEP_MODE 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 +******************************************************************************** +*/ +#if defined(_HIF_SDIO) +#define HIF_NAME "SDIO" +#else +#error "No HIF defined!" +#endif + + +/* Enable driver timing profiling */ +#define CFG_SDIO_TIMING_PROFILING 0 + +#define CFG_SDIO_INT_LOG_CNT 8 + +#define SDIO_X86_WORKAROUND_WRITE_MCR 0x00C4 +#define HIF_NUM_OF_QM_RX_PKT_NUM 512 + +#define HIF_TX_INIT_CMD_PORT TX_RING_FWDL_IDX_3 + +#define HIF_IST_LOOP_COUNT 128 +#define HIF_IST_TX_THRESHOLD 32 /* Min msdu count to trigger Tx during INT polling state */ + +#define HIF_TX_MAX_AGG_LENGTH (511 * 512) /* 511 blocks x 512 */ + +#define HIF_RX_MAX_AGG_NUM 16 +/*!< Setting the maximum RX aggregation number 0: no limited (16) */ + +#define HIF_TX_BUFF_COUNT_TC0 8 +#define HIF_TX_BUFF_COUNT_TC1 167 +#define HIF_TX_BUFF_COUNT_TC2 8 +#define HIF_TX_BUFF_COUNT_TC3 8 +#define HIF_TX_BUFF_COUNT_TC4 7 +#define HIF_TX_BUFF_COUNT_TC5 0 + +#define HIF_TX_RESOURCE_CTRL 1 /* enable/disable TX resource control */ +#define HIF_TX_RESOURCE_CTRL_PLE 1 /* enable/disable TX resource control PLE */ + + +#define HIF_TX_PAGE_SIZE_IN_POWER_OF_2 11 +#define HIF_TX_PAGE_SIZE 2048 /* in unit of bytes */ +#define HIF_TX_PAGE_SIZE_STORED_FORWARD 128 /* in unit of bytes */ + +#define HIF_EXTRA_IO_BUFFER_SIZE \ + (sizeof(struct ENHANCE_MODE_DATA_STRUCT) + HIF_RX_COALESCING_BUF_COUNT * HIF_RX_COALESCING_BUFFER_SIZE) + +#define HIF_CR4_FWDL_SECTION_NUM 2 +#define HIF_IMG_DL_STATUS_PORT_IDX 0 + +#define HIF_RX_ENHANCE_MODE_PAD_LEN 4 + +#define HIF_TX_TERMINATOR_LEN 4 + +#if CFG_SDIO_TX_AGG +#define HIF_TX_COALESCING_BUFFER_SIZE (HIF_TX_MAX_AGG_LENGTH) +#else +#define HIF_TX_COALESCING_BUFFER_SIZE (CFG_TX_MAX_PKT_SIZE) +#endif + +#if CFG_SDIO_RX_AGG +#define HIF_RX_COALESCING_BUFFER_SIZE ((HIF_RX_MAX_AGG_NUM + 1) * CFG_RX_MAX_PKT_SIZE) +#else +#define HIF_RX_COALESCING_BUFFER_SIZE (CFG_RX_MAX_PKT_SIZE) +#endif + +#define HIF_RX_COALESCING_BUF_COUNT 16 + +/* WHISR device to host (D2H) */ +/* N9 Interrupt Host to stop tx/rx operation (at the moment, HIF tx/rx are stopted) */ +#define SER_SDIO_N9_HOST_STOP_TX_RX_OP BIT(8) +/* N9 Interrupt Host to stop tx operation (at the moment, HIF tx are stopted) */ +#define SER_SDIO_N9_HOST_STOP_TX_OP BIT(9) +/* N9 Interrupt Host all modules were reset done (to let host reinit HIF) */ +#define SER_SDIO_N9_HOST_RESET_DONE BIT(10) +/* N9 Interrupt Host System Error Recovery Done */ +#define SER_SDIO_N9_HOST_RECOVERY_DONE BIT(11) + +/* WSICR host to device (H2D) */ +/* Host ACK HIF tx/rx ring stop operatio */ +#define SER_SDIO_HOST_N9_STOP_TX_RX_OP_ACK BIT(19) +/* Host interrupt N9 HIF init done */ +#define SER_SDIO_HOST_N9_RESET_DONE_ACK BIT(20) +/* Host interrupt N9 System Error Recovery done */ +#define SER_SDIO_HOST_N9_RECOVERY_DONE_ACK BIT(21) +enum HIF_TX_COUNT_IDX_T { + HIF_TXC_IDX_0, + HIF_TXC_IDX_1, + HIF_TXC_IDX_2, + HIF_TXC_IDX_3, + HIF_TXC_IDX_4, + HIF_TXC_IDX_5, + HIF_TXC_IDX_6, + HIF_TXC_IDX_7, + HIF_TXC_IDX_8, + HIF_TXC_IDX_9, + HIF_TXC_IDX_10, + HIF_TXC_IDX_11, + HIF_TXC_IDX_12, + HIF_TXC_IDX_13, + HIF_TXC_IDX_14, + HIF_TXC_IDX_15, + HIF_TXC_IDX_NUM +}; + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +struct ENHANCE_MODE_DATA_STRUCT; /* declare SDIO_CTRL_T */ + +struct SDIO_STAT_COUNTER { + /* Tx data */ + uint32_t u4DataPortWriteCnt; + uint32_t u4DataPktWriteCnt; + uint32_t u4DataPortKickCnt; + + /* Tx command */ + uint32_t u4CmdPortWriteCnt; + uint32_t u4CmdPktWriteCnt; + + /* Tx done interrupt */ + uint32_t u4TxDoneCnt[HIF_TXC_IDX_NUM]; + uint32_t u4TxDoneIntCnt[HIF_TXC_IDX_NUM]; + uint32_t u4TxDoneIntTotCnt; + uint32_t u4TxDonePendingPktCnt; + + uint32_t u4IntReadCnt; + uint32_t u4IntCnt; + + /* Rx data/cmd*/ + uint32_t u4PortReadCnt[2]; + uint32_t u4PktReadCnt[2]; + + uint32_t u4RxBufUnderFlowCnt; + +#if CFG_SDIO_TIMING_PROFILING + uint32_t u4TxDataCpTime; + uint32_t u4TxDataFreeTime; + + uint32_t u4RxDataCpTime; + uint32_t u4PortReadTime; + + uint32_t u4TxDoneIntTime; + uint32_t u4IntReadTime; +#endif +}; + +struct SDIO_RX_COALESCING_BUF { + struct QUE_ENTRY rQueEntry; + void *pvRxCoalescingBuf; + uint32_t u4BufSize; + uint32_t u4PktCount; + uint32_t u4PktTotalLength; + + uint32_t u4IntLogIdx; +}; + +struct SDIO_INT_LOG_T { + uint32_t u4Idx; + uint8_t aucIntSts[128]; + uint32_t u4Flag; + uint16_t au2RxPktLen[HIF_RX_MAX_AGG_NUM]; + uint32_t au4RxPktInfo[HIF_RX_MAX_AGG_NUM]; + uint8_t ucRxPktCnt; +}; + +/* host interface's private data structure, which is attached to os glue +** layer info structure. + */ +struct GL_HIF_INFO { +#if MTK_WCN_HIF_SDIO + unsigned long cltCtx; + + const struct MTK_WCN_HIF_SDIO_FUNCINFO *prFuncInfo; +#else + struct sdio_func *func; +#endif + + struct ENHANCE_MODE_DATA_STRUCT *prSDIOCtrl; + + u_int8_t fgIntReadClear; + u_int8_t fgMbxReadClear; + struct QUE rFreeQueue; + u_int8_t fgIsPendingInt; + + uint32_t au4PendingTxDoneCount[HIF_TXC_IDX_NUM]; + + /* Statistic counter */ + struct SDIO_STAT_COUNTER rStatCounter; + + struct SDIO_RX_COALESCING_BUF rRxCoalesingBuf[HIF_RX_COALESCING_BUF_COUNT]; + + struct QUE rRxDeAggQueue; + struct QUE rRxFreeBufQueue; + + struct mutex rRxFreeBufQueMutex; + struct mutex rRxDeAggQueMutex; + + /* Error handling */ + u_int8_t fgSkipRx; + + struct SDIO_INT_LOG_T arIntLog[CFG_SDIO_INT_LOG_CNT]; + uint32_t u4IntLogIdx; + uint8_t ucIntLogEntry; + uint8_t fgForceFwOwn; +}; + +struct BUS_INFO { + void (*halTxGetFreeResource)(IN struct ADAPTER *prAdapter, IN uint16_t *au2TxDoneCnt, IN uint16_t *au2TxRlsCnt); + void (*halTxReturnFreeResource)(IN struct ADAPTER *prAdapter, IN uint16_t *au2TxDoneCnt); + void (*halRestoreTxResource)(IN struct ADAPTER *prAdapter); + void (*halUpdateTxDonePendingCount)(IN struct ADAPTER *prAdapter, + IN u_int8_t isIncr, IN uint8_t ucTc, IN uint16_t u2Cnt); +}; + +enum HIF_SDIO_INT_STS { + SDIO_INT_RX_ENHANCE = 0, + SDIO_INT_DRV_OWN, + SDIO_INT_WAKEUP_DSLP +}; + +/******************************************************************************* +* P U B 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_SDIO_TIMING_PROFILING +#define SDIO_TIME_INTERVAL_DEC() KAL_TIME_INTERVAL_DECLARATION() +#define SDIO_REC_TIME_START() KAL_REC_TIME_START() +#define SDIO_REC_TIME_END() KAL_REC_TIME_END() +#define SDIO_GET_TIME_INTERVAL() KAL_GET_TIME_INTERVAL() +#define SDIO_ADD_TIME_INTERVAL(_Interval) KAL_ADD_TIME_INTERVAL(_Interval) +#else +#define SDIO_TIME_INTERVAL_DEC() +#define SDIO_REC_TIME_START() +#define SDIO_REC_TIME_END() +#define SDIO_GET_TIME_INTERVAL() +#define SDIO_ADD_TIME_INTERVAL(_Interval) +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +uint32_t glRegisterBus(probe_card pfProbe, remove_card pfRemove); + +void glUnregisterBus(remove_card pfRemove); + +void glSetHifInfo(struct GLUE_INFO *prGlueInfo, unsigned long ulCookie); + +void glClearHifInfo(struct GLUE_INFO *prGlueInfo); + +u_int8_t glBusInit(void *pvData); + +void glBusRelease(void *pData); + +int32_t glBusSetIrq(void *pvData, void *pfnIsr, void *pvCookie); + +void glBusFreeIrq(void *pvData, void *pvCookie); + +void glSetPowerState(IN struct GLUE_INFO *prGlueInfo, IN uint32_t ePowerMode); + +void glGetDev(void *ctx, struct device **dev); + +void glGetHifDev(struct GL_HIF_INFO *prHif, struct device **dev); + +u_int8_t glWakeupSdio(struct GLUE_INFO *prGlueInfo); + +#if !CFG_SDIO_INTR_ENHANCE +void halRxSDIOReceiveRFBs(IN struct ADAPTER *prAdapter); + +uint32_t halRxReadBuffer(IN struct ADAPTER *prAdapter, IN OUT struct SW_RFB *prSwRfb); + +#else +void halRxSDIOEnhanceReceiveRFBs(IN struct ADAPTER *prAdapter); + +uint32_t halRxEnhanceReadBuffer(IN struct ADAPTER *prAdapter, IN uint32_t u4DataPort, + IN uint16_t u2RxLength, IN OUT struct SW_RFB *prSwRfb); + +void halProcessEnhanceInterruptStatus(IN struct ADAPTER *prAdapter); + +#endif /* CFG_SDIO_INTR_ENHANCE */ + +#if CFG_SDIO_RX_AGG +void halRxSDIOAggReceiveRFBs(IN struct ADAPTER *prAdapter); +#endif + +void halPutMailbox(IN struct ADAPTER *prAdapter, IN uint32_t u4MailboxNum, IN uint32_t u4Data); +void halGetMailbox(IN struct ADAPTER *prAdapter, IN uint32_t u4MailboxNum, OUT uint32_t *pu4Data); +void halDeAggRxPkt(struct ADAPTER *prAdapter, struct SDIO_RX_COALESCING_BUF *prRxBuf); +void halPrintMailbox(IN struct ADAPTER *prAdapter); +void halPollDbgCr(IN struct ADAPTER *prAdapter, IN uint32_t u4LoopCount); +void halTxGetFreeResource_v1(IN struct ADAPTER *prAdapter, IN uint16_t *au2TxDoneCnt, IN uint16_t *au2TxRlsCnt); + +u_int8_t halIsPendingTxDone(IN struct ADAPTER *prAdapter); +void halDumpIntLog(IN struct ADAPTER *prAdapter); +void halTagIntLog(IN struct ADAPTER *prAdapter, IN enum HIF_SDIO_INT_STS eTag); +void halRecIntLog(IN struct ADAPTER *prAdapter, IN struct ENHANCE_MODE_DATA_STRUCT *prSDIOCtrl); +struct SDIO_INT_LOG_T *halGetIntLog(IN struct ADAPTER *prAdapter, IN uint32_t u4Idx); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _HIF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/include/hif_sdio.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/include/hif_sdio.h new file mode 100644 index 0000000000000..9adba8b18dd7b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/include/hif_sdio.h @@ -0,0 +1,267 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/sdio/include/hif_sdio.h#2 +*/ + +/*! \file "hif_sdio.h" +* \brief +* +* +*/ + + +#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:turn off debug msg and assert, 1:turn 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 (8) + +#define HIF_DEFAULT_BLK_SIZE (256) +#define HIF_DEFAULT_VENDOR (0x037A) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/* sdio driver data mapping */ +struct MTK_WCN_SDIO_DRIVER_DATA_MAPPING { + uint16_t card_id; /* TPLMID_CARD: card ID */ + struct mt66xx_hif_driver_data *mt66xx_driver_data; +}; + + +/* Function info provided by client driver */ +struct MTK_WCN_HIF_SDIO_FUNCINFO; /* declare MTK_WCN_HIF_SDIO_FUNCINFO */ + +/* Client context provided by hif_sdio driver for the following function call */ + +/* Callback functions provided by client driver */ +typedef int32_t(*MTK_WCN_HIF_SDIO_PROBE)(unsigned long, const struct MTK_WCN_HIF_SDIO_FUNCINFO *prFuncInfo); +typedef int32_t(*MTK_WCN_HIF_SDIO_REMOVE)(unsigned long); +typedef int32_t(*MTK_WCN_HIF_SDIO_IRQ)(unsigned long); + +/* Function info provided by client driver */ +struct MTK_WCN_HIF_SDIO_FUNCINFO { + uint16_t manf_id; /* TPLMID_MANF: manufacturer ID */ + uint16_t card_id; /* TPLMID_CARD: card ID */ + uint16_t func_num; /* Function Number */ + uint16_t blk_sz; /* Function block size */ +}; + +/* Client info provided by client driver */ +struct MTK_WCN_HIF_SDIO_CLTINFO { + const struct MTK_WCN_HIF_SDIO_FUNCINFO *func_tbl; /* supported function info table */ + uint32_t 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 */ +}; + +/* function info provided by registed function */ +struct MTK_WCN_HIF_SDIO_REGISTINFO { + const struct MTK_WCN_HIF_SDIO_CLTINFO *sdio_cltinfo; /* client's MTK_WCN_HIF_SDIO_CLTINFO pointer */ + const struct MTK_WCN_HIF_SDIO_FUNCINFO *func_info; /* supported function info pointer */ +}; + +/* Card info provided by probed function */ +struct MTK_WCN_HIF_SDIO_PROBEINFO { + struct sdio_func *func; /* probed sdio function pointer */ + int8_t clt_idx; /* registered function table info element number (initial value is -1) */ + int interrupted; /* TRUE: interrupted, FALSE: not interrupted */ + void *private_data_p; /* clt's private data pointer */ +}; + +/* work queue info needed by worker */ +struct MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO { + struct work_struct probe_work; /* work queue structure */ + struct MTK_WCN_HIF_SDIO_REGISTINFO *registinfo_p; /* MTK_WCN_HIF_SDIO_REGISTINFO pointer of the client */ + int8_t probe_idx; /* probed function table info element number (initial value is -1) */ +}; + +/* error code returned by hif_sdio driver (use NEGATIVE number) */ +enum MTK_WCN_HIF_SDIO_ERR { + HIF_SDIO_ERR_SUCCESS = 0, + HIF_SDIO_ERR_FAIL, /* generic error */ + HIF_SDIO_ERR_INVALID_PARAM, + HIF_SDIO_ERR_DUPLICATED, + HIF_SDIO_ERR_UNSUP_MANF_ID, + HIF_SDIO_ERR_UNSUP_CARD_ID, + HIF_SDIO_ERR_INVALID_FUNC_NUM, + HIF_SDIO_ERR_INVALID_BLK_SZ, +}; + +/******************************************************************************* +* P U B 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) + +/*! + * \brief A debug print used to print debug messages while compiler flag HIF_SDIO_DEBUG on. + * + */ +#if HIF_SDIO_DEBUG +#define DPRINTK(fmt, args...) pr_debug("%s: " fmt, __func__, ## args) +#else +#define DPRINTK(fmt, args...) +#endif + +/*! + * \brief ASSERT function definition. + * + */ +#if HIF_SDIO_DEBUG +#define ASSERT(expr) \ + { \ + if (!(expr)) { \ + LOG_FUNC("assertion failed! %s[%d]: %s\n",\ + __func__, __LINE__, #expr); \ + WARN_ON(!(expr));\ + } \ + } +#else +#define 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_t mtk_wcn_hif_sdio_client_reg(const struct MTK_WCN_HIF_SDIO_CLTINFO *pinfo); + +extern int32_t mtk_wcn_hif_sdio_client_unreg(const struct MTK_WCN_HIF_SDIO_CLTINFO *pinfo); + +extern int32_t mtk_wcn_hif_sdio_readb(unsigned long ctx, uint32_t offset, uint8_t *pvb); + +extern int32_t mtk_wcn_hif_sdio_writeb(unsigned long ctx, uint32_t offset, uint8_t vb); + +extern int32_t mtk_wcn_hif_sdio_f0_readb(unsigned long ctx, uint32_t offset, uint8_t *pvb); + +extern int32_t mtk_wcn_hif_sdio_f0_writeb(unsigned long ctx, uint32_t offset, uint8_t vb); + +extern int32_t mtk_wcn_hif_sdio_readl(unsigned long ctx, uint32_t offset, uint32_t *pvl); + +extern int32_t mtk_wcn_hif_sdio_writel(unsigned long ctx, uint32_t offset, uint32_t vl); + +extern int32_t mtk_wcn_hif_sdio_read_buf(unsigned long ctx, uint32_t offset, uint32_t *pbuf, uint32_t len); + +extern int32_t mtk_wcn_hif_sdio_write_buf(unsigned long ctx, uint32_t offset, uint32_t *pbuf, uint32_t len); + +extern void mtk_wcn_hif_sdio_set_drvdata(unsigned long ctx, void *private_data_p); + +extern void *mtk_wcn_hif_sdio_get_drvdata(unsigned long ctx); + +extern void mtk_wcn_hif_sdio_get_dev(unsigned long ctx, struct device **dev); + +extern void mtk_wcn_hif_sdio_enable_irq(unsigned long ctx, int enable); + +#if KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE +extern int32_t mtk_wcn_stp_sdio_wake_up_ctrl(unsigned long ctx); +#else +extern int32_t mtk_wcn_hif_sdio_wake_up_ctrl(unsigned long ctx); +#endif + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _HIF_SDIO_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/include/mtk_porting.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/include/mtk_porting.h new file mode 100644 index 0000000000000..9be2f55d64c63 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/include/mtk_porting.h @@ -0,0 +1,89 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* porting layer */ +/* Android */ + +#ifndef _MTK_PORTING_H_ +#define _MTK_PORTING_H_ + +#include /* include stddef.h for NULL */ + +/* typedef void VOID, *PVOID; */ + +#ifndef MTK_WCN_BOOL_TRUE +#define MTK_WCN_BOOL_FALSE ((int) 0) +#define MTK_WCN_BOOL_TRUE ((int) 1) +#endif + + + +/* system APIs */ +/* mutex */ +typedef int(*MUTEX_CREATE) (const char *const name); +typedef int32_t(*MUTEX_DESTROY) (int mtx); +typedef int32_t(*MUTEX_LOCK) (int mtx); +typedef int32_t(*MUTEX_UNLOCK) (int mtx, unsigned long flags); +/* debug */ +typedef int32_t(*DBG_PRINT) (const char *str, ...); +typedef int32_t(*DBG_ASSERT) (int32_t expr, const char *file, int32_t line); +/* timer */ +typedef void (*MTK_WCN_TIMER_CB) (void); +typedef int(*TIMER_CREATE) (const char *const name); +typedef int32_t(*TIMER_DESTROY) (int tmr); +typedef int32_t(*TIMER_START) (int tmr, uint32_t timeout, MTK_WCN_TIMER_CB tmr_cb, void *param); +typedef int32_t(*TIMER_STOP) (int tmr); +/* kernel lib */ +typedef void *(*SYS_MEMCPY) (void *dest, const void *src, uint32_t n); +typedef void *(*SYS_MEMSET) (void *s, int32_t c, uint32_t n); +typedef int32_t(*SYS_SPRINTF) (char *str, const char *format, ...); + +#endif /* _MTK_PORTING_H_ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/include/test_driver_sdio_ops.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/include/test_driver_sdio_ops.h new file mode 100644 index 0000000000000..e396c46229657 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/include/test_driver_sdio_ops.h @@ -0,0 +1,48 @@ +/* + * linux/drivers/mmc/sdio_ops.c + * + * Copyright 2006-2007 Pierre Ossman + * + * 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. + */ + + +#ifndef __TEST_DRV_SDIO_OPS_H__ +#define __TEST_DRV_SDIO_OPS_H__ + +#include +#include +#include +#include +#include + + +int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr); +int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, + unsigned addr, u8 in, u8 *out); +int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, + unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz); + +int sdio_disable_wide(struct mmc_card *card); +int sdio_enable_4bit_bus(struct mmc_card *card); + + + +#include +#include +#define MMC_CMD_RETRIES 3 + +static inline void mmc_delay(unsigned int ms) +{ + if (ms < 1000 / HZ) { + cond_resched(); + mdelay(ms); + } else { + msleep(ms); + } +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/sdio.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/sdio.c new file mode 100644 index 0000000000000..a098ebe883077 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/sdio.c @@ -0,0 +1,1730 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** +*[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. +******************************************************************************/ + + +/******************************************************************************* +* C O M P I L E 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 "precomp.h" + +#if MTK_WCN_HIF_SDIO +#include "hif_sdio.h" +#else +#include +#include +#include +#include /* sdio_readl(), etc */ +#include +#endif + +#include +#ifndef CONFIG_X86 +#include +#endif + +#include "mt66xx_reg.h" + +#if (CFG_SDIO_1BIT_DATA_MODE == 1) +#include "test_driver_sdio_ops.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" + +#define HIF_SDIO_ACCESS_RETRY_LIMIT 250 +#define HIF_SDIO_INTERRUPT_RESPONSE_TIMEOUT (15000) + +#if MTK_WCN_HIF_SDIO + +/* + * function prototypes + * + */ + +static int32_t mtk_sdio_probe(unsigned long, const struct MTK_WCN_HIF_SDIO_FUNCINFO *); + +static int32_t mtk_sdio_remove(unsigned long); +static int32_t mtk_sdio_interrupt(unsigned long); + +/* + * sdio function info table + */ + +static struct MTK_WCN_HIF_SDIO_FUNCINFO funcInfo[] = { + {MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x6602, 0x1, 512)}, +}; + +static struct MTK_WCN_SDIO_DRIVER_DATA_MAPPING sdio_driver_data_mapping[] = { + {0x6602, &mt66xx_driver_data_mt6632}, +}; + +static struct MTK_WCN_HIF_SDIO_CLTINFO cltInfo = { + .func_tbl = funcInfo, + .func_tbl_size = sizeof(funcInfo) / sizeof(struct MTK_WCN_HIF_SDIO_FUNCINFO), + .hif_clt_probe = mtk_sdio_probe, + .hif_clt_remove = mtk_sdio_remove, + .hif_clt_irq = mtk_sdio_interrupt, +}; + +#else +/* + * function prototypes + * + */ +static int mtk_sdio_pm_suspend(struct device *pDev); +static int mtk_sdio_pm_resume(struct device *pDev); + +static const struct sdio_device_id mtk_sdio_ids[] = { +#ifdef MT6632 + { SDIO_DEVICE(0x037a, 0x6602), + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_mt6632},/* Not an SDIO standard class device */ +#endif /* MT6632 */ +#ifdef MT7668 + { SDIO_DEVICE(0x037a, 0x7608), + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_mt7668},/* Not an SDIO standard class device */ +#endif /* MT7668 */ +#ifdef MT7663 + { SDIO_DEVICE(0x037a, 0x7603), + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_mt7663}, +#endif /* MT7663 */ + { /* 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 +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static probe_card pfWlanProbe; +static remove_card pfWlanRemove; + +#if (MTK_WCN_HIF_SDIO == 0) +static const struct dev_pm_ops mtk_sdio_pm_ops = { + .suspend = mtk_sdio_pm_suspend, + .resume = mtk_sdio_pm_resume, +}; + +static struct sdio_driver mtk_sdio_driver = { + .name = "wlan", /* "MTK SDIO WLAN Driver" */ + .id_table = mtk_sdio_ids, + .probe = NULL, + .remove = NULL, + .drv = { + .owner = THIS_MODULE, + .pm = &mtk_sdio_pm_ops, + } +}; +#endif + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define dev_to_sdio_func(d) container_of(d, struct sdio_func, dev) + + +/******************************************************************************* +* 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 a SDIO interrupt callback function +* +* \param[in] func pointer to SDIO handle +* +* \return void +*/ +/*----------------------------------------------------------------------------*/ + +#if MTK_WCN_HIF_SDIO + +static int32_t mtk_sdio_interrupt(unsigned long cltCtx) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t 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; + } + + prGlueInfo->u8HifIntTime = sched_clock(); + + prGlueInfo->IsrCnt++; + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + /* printk(KERN_INFO DRV_NAME"GLUE_FLAG_HALT skip INT\n"); */ + ret = mtk_wcn_hif_sdio_writeb(cltCtx, MCR_WHLPCR, WHLPCR_INT_EN_CLR); + return ret; + } + + ret = mtk_wcn_hif_sdio_writeb(cltCtx, MCR_WHLPCR, WHLPCR_INT_EN_CLR); + + prGlueInfo->rHifInfo.fgIsPendingInt = FALSE; + + kalSetIntEvent(prGlueInfo); + prGlueInfo->IsrPassCnt++; + + return ret; +} + +#else +static void mtk_sdio_interrupt(struct sdio_func *func) +{ + struct GLUE_INFO *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->ulFlag & GLUE_FLAG_HALT) { + sdio_writeb(prGlueInfo->rHifInfo.func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, &ret); + /* printk(KERN_INFO DRV_NAME"GLUE_FLAG_HALT skip INT\n"); */ + return; + } + + sdio_writeb(prGlueInfo->rHifInfo.func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, &ret); + + prGlueInfo->rHifInfo.fgIsPendingInt = FALSE; + + kalSetIntEvent(prGlueInfo); +} +#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 struct MTK_WCN_HIF_SDIO_FUNCINFO *prFunc; + +static int32_t mtk_sdio_probe(unsigned long cltCtx, const struct MTK_WCN_HIF_SDIO_FUNCINFO *prFuncInfo) +{ + int32_t ret = HIF_SDIO_ERR_SUCCESS; + int32_t i = 0; + int32_t dd_table_len = sizeof(sdio_driver_data_mapping) / sizeof(struct MTK_WCN_SDIO_DRIVER_DATA_MAPPING); + struct mt66xx_hif_driver_data *sdio_driver_data = NULL; + + prFunc = prFuncInfo; + + for (i = 0; i < dd_table_len; i++) { + if (prFunc->card_id == sdio_driver_data_mapping[i].card_id) { + sdio_driver_data = sdio_driver_data_mapping[i].mt66xx_driver_data; + break; + } + } + + if (sdio_driver_data == NULL) { + DBGLOG(HAL, ERROR, "sdio probe error: %x driver data not found!\n", prFunc->card_id); + return HIF_SDIO_ERR_UNSUP_CARD_ID; + } + + if (pfWlanProbe((void *)&cltCtx, (void *) sdio_driver_data) != 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((void *) func, (void *) id->driver_data) != WLAN_STATUS_SUCCESS) { + /* printk(KERN_WARNING DRV_NAME"pfWlanProbe fail!call pfWlanRemove()\n"); */ + pfWlanRemove(); + ret = -1; + } + +out: + /* printk(KERN_INFO DRV_NAME"mtk_sdio_probe() done(%d)\n", ret); */ + return ret; +} +#endif + +#if MTK_WCN_HIF_SDIO +static int32_t mtk_sdio_remove(unsigned long cltCtx) +{ + int32_t 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"); */ + + 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_pm_suspend(struct device *pDev) +{ + int ret = 0, wait = 0; + int pm_caps, set_flag; + const char *func_id; + struct sdio_func *func; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint8_t drv_own_fail = FALSE; + + DBGLOG(HAL, STATE, "==>\n"); + + func = dev_to_sdio_func(pDev); + prGlueInfo = sdio_get_drvdata(func); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, STATE, "Wow:%d, WowEnable:%d, state:%d\n", + prAdapter->rWifiVar.ucWow, + prAdapter->rWowCtrl.fgWowEnable, + kalGetMediaStateIndicated(prGlueInfo, AIS_DEFAULT_INDEX)); + + /* 1) wifi cfg "Wow" is true + * 2) wow is enable + * 3) WIfI connected => execute WOW flow + */ + if (prAdapter->rWifiVar.ucWow && prAdapter->rWowCtrl.fgWowEnable && + (kalGetMediaStateIndicated(prGlueInfo, AIS_DEFAULT_INDEX) == + MEDIA_STATE_CONNECTED)) { + DBGLOG(HAL, STATE, "enter WOW flow\n"); + kalWowProcess(prGlueInfo, TRUE); + } + + prGlueInfo->rHifInfo.fgForceFwOwn = TRUE; + + /* Wait for + * 1. The other unfinished ownership handshakes + * 2. FW own back + */ + while (wait < 100) { + if ((prAdapter->u4PwrCtrlBlockCnt == 0) && + (prAdapter->fgIsFwOwn == TRUE) && + (drv_own_fail == FALSE)) { + DBGLOG(HAL, STATE, "************************\n"); + DBGLOG(HAL, STATE, "* Entered SDIO Suspend *\n"); + DBGLOG(HAL, STATE, "************************\n"); + DBGLOG(HAL, INFO, "wait = %d\n\n", wait); + break; + } + + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + /* Prevent that suspend without FW Own: + * Set Drv own has failed, and then Set FW Own is skipped + */ + if (prAdapter->fgIsFwOwn == FALSE) + drv_own_fail = FALSE; + else + drv_own_fail = TRUE; + /* For single core CPU, let hif_thread can be completed */ + kalMsleep(10); + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + + wait++; + } + + if (wait >= 100) { + DBGLOG(HAL, ERROR, "Set FW Own Timeout !!\n"); + return -EAGAIN; + } + + pm_caps = sdio_get_host_pm_caps(func); + func_id = sdio_func_id(func); + + /* Ask kernel keeping SDIO bus power-on */ + set_flag = MMC_PM_KEEP_POWER; + ret = sdio_set_host_pm_flags(func, set_flag); + if (ret) { + DBGLOG(HAL, ERROR, "set flag %d err %d\n", set_flag, ret); + DBGLOG(HAL, ERROR, + "%s: cannot remain alive(0x%X)\n", func_id, pm_caps); + } + + /* If wow enable, ask kernel accept SDIO IRQ in suspend mode */ + if (prAdapter->rWifiVar.ucWow && + prAdapter->rWowCtrl.fgWowEnable) { + set_flag = MMC_PM_WAKE_SDIO_IRQ; + ret = sdio_set_host_pm_flags(func, set_flag); + if (ret) { + DBGLOG(HAL, ERROR, "set flag %d err %d\n", set_flag, ret); + DBGLOG(HAL, ERROR, + "%s: cannot sdio wake-irq(0x%X)\n", func_id, pm_caps); + } + } + + DBGLOG(HAL, STATE, "<==\n"); + return 0; +} + +static int mtk_sdio_pm_resume(struct device *pDev) +{ + struct sdio_func *func; + struct GLUE_INFO *prGlueInfo = NULL; + + DBGLOG(HAL, STATE, "==>\n"); + + func = dev_to_sdio_func(pDev); + prGlueInfo = sdio_get_drvdata(func); + + DBGLOG(REQ, STATE, "Wow:%d, WowEnable:%d, state:%d\n", + prGlueInfo->prAdapter->rWifiVar.ucWow, + prGlueInfo->prAdapter->rWowCtrl.fgWowEnable, + kalGetMediaStateIndicated(prGlueInfo, AIS_DEFAULT_INDEX)); + + prGlueInfo->rHifInfo.fgForceFwOwn = FALSE; + + if (prGlueInfo->prAdapter->rWifiVar.ucWow && + prGlueInfo->prAdapter->rWowCtrl.fgWowEnable && + (kalGetMediaStateIndicated(prGlueInfo, AIS_DEFAULT_INDEX) == + MEDIA_STATE_CONNECTED)) { + DBGLOG(HAL, STATE, "leave WOW flow\n"); + kalWowProcess(prGlueInfo, FALSE); + } + + DBGLOG(HAL, STATE, "<==\n"); + return 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 mtk_sdio_pm_suspend(pDev); +} + +int mtk_sdio_resume(struct device *pDev) +{ + /* printk(KERN_INFO "mtk_sdio: mtk_sdio_resume dev(0x%p)\n", pDev); */ + + return mtk_sdio_pm_resume(pDev); +} +#if (CFG_SDIO_ASYNC_IRQ_AUTO_ENABLE == 1) +int mtk_sdio_async_irq_enable(struct sdio_func *func) +{ +#define SDIO_CCCR_IRQ_EXT 0x16 +#define SDIO_IRQ_EXT_SAI BIT(0) +#define SDIO_IRQ_EXT_EAI BIT(1) + unsigned char data = 0; + unsigned int quirks_bak; + int ret; + + /* Read CCCR 0x16 (interrupt extension)*/ + data = sdio_f0_readb(func, SDIO_CCCR_IRQ_EXT, &ret); + if (ret) { + DBGLOG(HAL, ERROR, "CCCR 0x%X read fail (%d).\n", SDIO_CCCR_IRQ_EXT, ret); + return FALSE; + } + /* Check CCCR capability status */ + if (!(data & SDIO_IRQ_EXT_SAI)) { + /* SAI = 0 */ + DBGLOG(HAL, ERROR, "No Async-IRQ capability.\n"); + return FALSE; + } else if (data & SDIO_IRQ_EXT_EAI) { + /* EAI = 1 */ + DBGLOG(INIT, INFO, "Async-IRQ enabled already.\n"); + return TRUE; + } + + /* Set EAI bit */ + data |= SDIO_IRQ_EXT_EAI; + + /* Enable capability to write CCCR */ + quirks_bak = func->card->quirks; + func->card->quirks |= MMC_QUIRK_LENIENT_FN0; + /* Write CCCR into card */ + sdio_f0_writeb(func, data, SDIO_CCCR_IRQ_EXT, &ret); + if (ret) { + DBGLOG(HAL, ERROR, "CCCR 0x%X write fail (%d).\n", SDIO_CCCR_IRQ_EXT, ret); + return FALSE; + } + func->card->quirks = quirks_bak; + + data = sdio_f0_readb(func, SDIO_CCCR_IRQ_EXT, &ret); + if (ret || !(data & SDIO_IRQ_EXT_EAI)) { + DBGLOG(HAL, ERROR, "CCCR 0x%X write fail (%d).\n", SDIO_CCCR_IRQ_EXT, ret); + return FALSE; + } + return TRUE; +} +#endif +#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 +*/ +/*----------------------------------------------------------------------------*/ +uint32_t 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 +} /* 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(struct GLUE_INFO *prGlueInfo, unsigned long ulCookie) +{ + struct GL_HIF_INFO *prHif = NULL; + uint8_t ucIdx; + + prHif = &prGlueInfo->rHifInfo; + + QUEUE_INITIALIZE(&prHif->rFreeQueue); + QUEUE_INITIALIZE(&prHif->rRxDeAggQueue); + QUEUE_INITIALIZE(&prHif->rRxFreeBufQueue); + +#if MTK_WCN_HIF_SDIO + /* prHif->prFuncInfo = ((MTK_WCN_HIF_SDIO_FUNCINFO *) u4Cookie); */ + prHif->prFuncInfo = prFunc; + prHif->cltCtx = *((unsigned long *) ulCookie); + mtk_wcn_hif_sdio_set_drvdata(prHif->cltCtx, prGlueInfo); + +#else + prHif->func = (struct sdio_func *)ulCookie; + + /* 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 + + /* Reset statistic counter */ + kalMemZero(&prHif->rStatCounter, sizeof(struct SDIO_STAT_COUNTER)); + + for (ucIdx = HIF_TXC_IDX_0; ucIdx < HIF_TXC_IDX_NUM; ucIdx++) + prHif->au4PendingTxDoneCount[ucIdx] = 0; + + mutex_init(&prHif->rRxFreeBufQueMutex); + mutex_init(&prHif->rRxDeAggQueMutex); + + prHif->fgSkipRx = FALSE; + prGlueInfo->u4InfType = MT_DEV_INF_SDIO; +} /* end of glSetHifInfo() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function clears hif related info. +* +* \param[in] prGlueInfo Pointer to glue info structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void glClearHifInfo(struct GLUE_INFO *prGlueInfo) +{ + /* P_GL_HIF_INFO_T prHif = NULL; */ + /* ASSERT(prGlueInfo); */ + /* prHif = &prGlueInfo->rHifInfo; */ +} /* 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) +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t glBusInit(void *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); + +#if (CFG_SDIO_1BIT_DATA_MODE == 1) + ret = sdio_disable_wide(func->card); + if (ret) + DBGLOG(HAL, ERROR, "glBusInit() Error at enabling SDIO 1-BIT data mode.\n"); + else + DBGLOG(HAL, INFO, "glBusInit() SDIO 1-BIT data mode is working.\n"); +#endif + +#if (CFG_SDIO_ASYNC_IRQ_AUTO_ENABLE == 1) + ret = mtk_sdio_async_irq_enable(func); + if (ret == FALSE) + DBGLOG(HAL, ERROR, "Async-IRQ auto-enable fail.\n"); + else + DBGLOG(INIT, INFO, "Async-IRQ is enabled.\n"); +#endif + + 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(void *pvData) +{ +} /* end of glBusRelease() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setup bus interrupt operation and interrupt handler for os. +* +* \param[in] pvData A pointer to struct net_device. +* \param[in] pfnIsr A pointer to interrupt handler function. +* \param[in] pvCookie Private data for pfnIsr function. +* +* \retval WLAN_STATUS_SUCCESS if success +* NEGATIVE_VALUE if fail +*/ +/*----------------------------------------------------------------------------*/ +int32_t glBusSetIrq(void *pvData, void *pfnIsr, void *pvCookie) +{ + int ret = 0; + + struct net_device *prNetDevice = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct GL_HIF_INFO *prHifInfo = NULL; + + ASSERT(pvData); + if (!pvData) + return -1; + + prNetDevice = (struct net_device *)pvData; + prGlueInfo = (struct GLUE_INFO *) pvCookie; + ASSERT(prGlueInfo); + if (!prGlueInfo) + return -1; + + prHifInfo = &prGlueInfo->rHifInfo; + +#if (MTK_WCN_HIF_SDIO == 0) + sdio_claim_host(prHifInfo->func); + ret = sdio_claim_irq(prHifInfo->func, mtk_sdio_interrupt); + sdio_release_host(prHifInfo->func); +#else + mtk_wcn_hif_sdio_enable_irq(prHifInfo->cltCtx, TRUE); +#endif + + prHifInfo->fgIsPendingInt = FALSE; + + prHifInfo->u4IntLogIdx = 0; + prHifInfo->ucIntLogEntry = 0; + + 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(void *pvData, void *pvCookie) +{ + struct net_device *prNetDevice = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct GL_HIF_INFO *prHifInfo = NULL; + + ASSERT(pvData); + if (!pvData) { + /* printk(KERN_INFO DRV_NAME"%s null pvData\n", __FUNCTION__); */ + return; + } + prNetDevice = (struct net_device *)pvData; + prGlueInfo = (struct GLUE_INFO *) pvCookie; + ASSERT(prGlueInfo); + if (!prGlueInfo) { + /* printk(KERN_INFO DRV_NAME"%s no glue info\n", __FUNCTION__); */ + return; + } + + prHifInfo = &prGlueInfo->rHifInfo; +#if (MTK_WCN_HIF_SDIO == 0) + sdio_claim_host(prHifInfo->func); + sdio_release_irq(prHifInfo->func); + sdio_release_host(prHifInfo->func); +#else + mtk_wcn_hif_sdio_enable_irq(prHifInfo->cltCtx, FALSE); +#endif +} /* end of glBusreeIrq() */ + +u_int8_t glIsReadClearReg(uint32_t u4Address) +{ + switch (u4Address) { + case MCR_WHISR: + case MCR_WASR: + case MCR_D2HRM0R: + case MCR_D2HRM1R: + case MCR_WTQCR0: + case MCR_WTQCR1: + case MCR_WTQCR2: + case MCR_WTQCR3: + case MCR_WTQCR4: + case MCR_WTQCR5: + case MCR_WTQCR6: + case MCR_WTQCR7: + return TRUE; + + default: + return FALSE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Read a 32-bit device register of SDIO host driver domian +* +* \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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevRegRead(IN struct GLUE_INFO *prGlueInfo, IN uint32_t u4Register, OUT uint32_t *pu4Value) +{ + int ret = 0; + uint8_t ucRetryCount = 0; + + ASSERT(prGlueInfo); + ASSERT(pu4Value); + + do { +#if MTK_WCN_HIF_SDIO + ret = mtk_wcn_hif_sdio_readl(prGlueInfo->rHifInfo.cltCtx, u4Register, (uint32_t *) pu4Value); +#else + sdio_claim_host(prGlueInfo->rHifInfo.func); + *pu4Value = sdio_readl(prGlueInfo->rHifInfo.func, u4Register, &ret); + sdio_release_host(prGlueInfo->rHifInfo.func); +#endif + + if (ret || ucRetryCount) { + /* DBGLOG(HAL, ERROR, + * ("sdio_readl() addr: 0x%08x value: 0x%08x status: %x retry: %u\n", + * u4Register, (unsigned int)*pu4Value, (unsigned int)ret, ucRetryCount)); + */ + + if (glIsReadClearReg(u4Register) && (ucRetryCount == 0)) { + /* Read Snapshot CR instead */ + u4Register = MCR_WSR; + } + } + + ucRetryCount++; + if (ucRetryCount > HIF_SDIO_ACCESS_RETRY_LIMIT) + break; + } while (ret); + + if (ret) { + kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, + HIF_SDIO_ERR_DESC_STR "sdio_readl() reports error: %x retry: %u", ret, ucRetryCount); + DBGLOG(HAL, ERROR, "sdio_readl() reports error: %x retry: %u\n", ret, ucRetryCount); + } + + return (ret) ? FALSE : TRUE; +} /* end of kalDevRegRead() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Read a 32-bit device register of chip firmware register domain +* +* \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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevRegRead_mac(IN struct GLUE_INFO *prGlueInfo, IN uint32_t u4Register, OUT uint32_t *pu4Value) +{ + uint32_t value; + uint32_t u4Time, u4Current; + uint8_t ucResult;/* For Unchecked return value*/ + + /* progrqm h2d mailbox0 as interested register address */ + ucResult = kalDevRegWrite(prGlueInfo, MCR_H2DSM0R, u4Register); + + /* set h2d interrupt to notify firmware. bit16 */ + ucResult = kalDevRegWrite(prGlueInfo, MCR_WSICR, + SDIO_MAILBOX_FUNC_READ_REG_IDX); + + /* polling interrupt status asserted. bit16 */ + + /* first, disable interrupt enable for SDIO_MAILBOX_FUNC_READ_REG_IDX */ + ucResult = kalDevRegRead(prGlueInfo, MCR_WHIER, &value); + ucResult = kalDevRegWrite(prGlueInfo, MCR_WHIER, + (value & ~SDIO_MAILBOX_FUNC_READ_REG_IDX)); + + u4Time = (uint32_t) kalGetTimeTick(); + + do { + /* check bit16 of WHISR assert for read register response */ + ucResult = kalDevRegRead(prGlueInfo, MCR_WHISR, &value); + + if (value & SDIO_MAILBOX_FUNC_READ_REG_IDX) { + /* read d2h mailbox0 for interested register address */ + ucResult = kalDevRegRead(prGlueInfo, + MCR_D2HRM0R, &value); + + if (value != u4Register) { + DBGLOG(HAL, ERROR, "ERROR! kalDevRegRead_mac():register address mis-match"); + DBGLOG(HAL, ERROR, "(u4Register = 0x%08x, reported register = 0x%08x)\n", + u4Register, value); + return FALSE; + } + + /* read d2h mailbox1 for the value of the register */ + ucResult = kalDevRegRead(prGlueInfo, + MCR_D2HRM1R, &value); + *pu4Value = value; + return TRUE; + } + + /* timeout exceeding check */ + u4Current = (uint32_t) kalGetTimeTick(); + + if (((u4Current > u4Time) && ((u4Current - u4Time) > HIF_SDIO_INTERRUPT_RESPONSE_TIMEOUT)) + || (u4Current < u4Time && ((u4Current + (0xFFFFFFFF - u4Time)) + > HIF_SDIO_INTERRUPT_RESPONSE_TIMEOUT))) { + DBGLOG(HAL, ERROR, "ERROR: kalDevRegRead_mac(): response timeout\n"); + return FALSE; + } + + /* Response packet is not ready */ + kalUdelay(50); + } while (1); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write a 32-bit device register of SDIO driver domian +* +* \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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevRegWrite(IN struct GLUE_INFO *prGlueInfo, IN uint32_t u4Register, IN uint32_t u4Value) +{ + int ret = 0; + uint8_t ucRetryCount = 0; + + ASSERT(prGlueInfo); + + do { +#if MTK_WCN_HIF_SDIO + ret = mtk_wcn_hif_sdio_writel(prGlueInfo->rHifInfo.cltCtx, u4Register, u4Value); +#else + sdio_claim_host(prGlueInfo->rHifInfo.func); + sdio_writel(prGlueInfo->rHifInfo.func, u4Value, u4Register, &ret); + sdio_release_host(prGlueInfo->rHifInfo.func); +#endif + + if (ret || ucRetryCount) { + /* DBGLOG(HAL, ERROR, + * ("sdio_writel() addr: 0x%x status: %x retry: %u\n", u4Register, + * ret, ucRetryCount)); + */ + } + + ucRetryCount++; + if (ucRetryCount > HIF_SDIO_ACCESS_RETRY_LIMIT) + break; + + } while (ret); + + if (ret) { + kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, + HIF_SDIO_ERR_DESC_STR "sdio_writel() reports error: %x retry: %u", ret, ucRetryCount); + DBGLOG(HAL, ERROR, "sdio_writel() reports error: %x retry: %u\n", ret, ucRetryCount); + } + + return (ret) ? FALSE : TRUE; +} /* end of kalDevRegWrite() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write a 32-bit device register of chip firmware register domain +* +* \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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevRegWrite_mac(IN struct GLUE_INFO *prGlueInfo, IN uint32_t u4Register, IN uint32_t u4Value) +{ + uint32_t value; + uint32_t u4Time, u4Current; + uint8_t ucResult; /* For Unchecked return value*/ + + /* progrqm h2d mailbox0 as interested register address */ + ucResult = kalDevRegWrite(prGlueInfo, MCR_H2DSM0R, u4Register); + + /* progrqm h2d mailbox1 as the value to write */ + ucResult = kalDevRegWrite(prGlueInfo, MCR_H2DSM1R, u4Value); + + /* set h2d interrupt to notify firmware bit17 */ + ucResult = kalDevRegWrite(prGlueInfo, MCR_WSICR, + SDIO_MAILBOX_FUNC_WRITE_REG_IDX); + + /* polling interrupt status asserted. bit17 */ + + /* first, disable interrupt enable for SDIO_MAILBOX_FUNC_WRITE_REG_IDX */ + ucResult = kalDevRegRead(prGlueInfo, MCR_WHIER, &value); + ucResult = kalDevRegWrite(prGlueInfo, MCR_WHIER, + (value & ~SDIO_MAILBOX_FUNC_WRITE_REG_IDX)); + + u4Time = (uint32_t) kalGetTimeTick(); + + do { + /* check bit17 of WHISR assert for response */ + ucResult = kalDevRegRead(prGlueInfo, MCR_WHISR, &value); + + if (value & SDIO_MAILBOX_FUNC_WRITE_REG_IDX) { + /* read d2h mailbox0 for interested register address */ + ucResult = kalDevRegRead(prGlueInfo, + MCR_D2HRM0R, &value); + + if (value != u4Register) { + DBGLOG(HAL, ERROR, "ERROR! kalDevRegWrite_mac():register address mis-match"); + DBGLOG(HAL, ERROR, "(u4Register = 0x%08x, reported register = 0x%08x)\n", + u4Register, value); + return FALSE; + } + return TRUE; + } + + /* timeout exceeding check */ + u4Current = (uint32_t) kalGetTimeTick(); + + if (((u4Current > u4Time) && ((u4Current - u4Time) > HIF_SDIO_INTERRUPT_RESPONSE_TIMEOUT)) + || (u4Current < u4Time && ((u4Current + (0xFFFFFFFF - u4Time)) + > HIF_SDIO_INTERRUPT_RESPONSE_TIMEOUT))) { + DBGLOG(HAL, ERROR, "ERROR: kalDevRegWrite_mac(): response timeout\n"); + return FALSE; + } + + /* Response packet is not ready */ + kalUdelay(50); + } while (1); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t +kalDevPortRead(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port, IN uint32_t u4Len, OUT uint8_t *pucBuf, IN uint32_t u4ValidOutBufSize) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + uint8_t *pucDst = NULL; + int count = u4Len; + 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, u4Len); */ +#endif + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + ASSERT(pucBuf); + pucDst = pucBuf; + + ASSERT(u4Len <= u4ValidOutBufSize); + +#if (MTK_WCN_HIF_SDIO == 0) + prSdioFunc = prHifInfo->func; + + ASSERT(prSdioFunc->cur_blksize > 0); + + 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); + } + + 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, (uint32_t *) pucDst, + ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz) * bNum); + } else { + ret = mtk_wcn_hif_sdio_read_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (uint32_t *) pucDst, count); + } +#endif + + if (ret) { + kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_readsb() reports error: %d", ret); + + DBGLOG(HAL, ERROR, "\n"); + DBGLOG(HAL, ERROR, "\nSDIO BUS ERROR: "); + DBGLOG(HAL, ERROR, "sdio_readsb() reports error: %d\n", ret); + DBGLOG(HAL, ERROR, "\n"); + } + + 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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t +kalDevPortWrite(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port, IN uint32_t u4Len, IN uint8_t *pucBuf, IN uint32_t u4ValidInBufSize) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + uint8_t *pucSrc = NULL; + int count = u4Len; + 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(u4Len <= u4ValidInBufSize); + +#if (MTK_WCN_HIF_SDIO == 0) + prSdioFunc = prHifInfo->func; + ASSERT(prSdioFunc->cur_blksize > 0); + + 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); + } + + 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, + (uint32_t *) pucSrc, ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz) * bNum); + } else { /* byte mode */ + ret = mtk_wcn_hif_sdio_write_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (uint32_t *) pucSrc, count); + } +#endif + + if (ret) { + kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, + HIF_SDIO_ERR_DESC_STR "sdio_writesb() reports error: %d", ret); + + DBGLOG(HAL, ERROR, "\n"); + DBGLOG(HAL, ERROR, "\nSDIO BUS ERROR: "); + DBGLOG(HAL, ERROR, "sdio_writesb() reports error: %d\n", ret); + DBGLOG(HAL, ERROR, "\n"); + } + + return (ret) ? FALSE : TRUE; +} /* end of kalDevPortWrite() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read interrupt status from hardware +* +* @param prAdapter pointer to the Adapter handler +* @param the interrupts +* +* @return N/A +* +*/ +/*----------------------------------------------------------------------------*/ +void kalDevReadIntStatus(IN struct ADAPTER *prAdapter, OUT uint32_t *pu4IntStatus) +{ +#if CFG_SDIO_INTR_ENHANCE + struct ENHANCE_MODE_DATA_STRUCT *prSDIOCtrl; + struct SDIO_STAT_COUNTER *prStatCounter; + u_int8_t fgPendingInt = FALSE; + + SDIO_TIME_INTERVAL_DEC(); + + DEBUGFUNC("nicSDIOReadIntStatus"); + + ASSERT(prAdapter); + ASSERT(pu4IntStatus); + + prSDIOCtrl = prAdapter->prGlueInfo->rHifInfo.prSDIOCtrl; + ASSERT(prSDIOCtrl); + + prStatCounter = &prAdapter->prGlueInfo->rHifInfo.rStatCounter; + + /* There are pending interrupt to be handled */ + if (prAdapter->prGlueInfo->rHifInfo.fgIsPendingInt) { + prAdapter->prGlueInfo->rHifInfo.fgIsPendingInt = FALSE; + fgPendingInt = TRUE; + } + else { + SDIO_REC_TIME_START(); + HAL_PORT_RD(prAdapter, MCR_WHISR, sizeof(struct ENHANCE_MODE_DATA_STRUCT), + (uint8_t *) prSDIOCtrl, sizeof(struct ENHANCE_MODE_DATA_STRUCT)); + SDIO_REC_TIME_END(); + SDIO_ADD_TIME_INTERVAL(prStatCounter->u4IntReadTime); + prStatCounter->u4IntReadCnt++; + } + + prStatCounter->u4IntCnt++; + + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + *pu4IntStatus = 0; + return; + } + + halProcessEnhanceInterruptStatus(prAdapter); + + if (prSDIOCtrl->u4WHISR) { + halRecIntLog(prAdapter, prSDIOCtrl); + if (fgPendingInt) + halTagIntLog(prAdapter, SDIO_INT_RX_ENHANCE); + } + + *pu4IntStatus = prSDIOCtrl->u4WHISR; +#else + HAL_MCR_RD(prAdapter, MCR_WHISR, pu4IntStatus); +#endif /* CFG_SDIO_INTR_ENHANCE */ + + if (*pu4IntStatus & ~(WHIER_DEFAULT | WHIER_FW_OWN_BACK_INT_EN)) { + DBGLOG(INTR, WARN, + "Un-handled HISR %lx, HISR = %lx (HIER:0x%lx)\n", + (*pu4IntStatus & ~WHIER_DEFAULT), *pu4IntStatus, + WHIER_DEFAULT); + *pu4IntStatus &= WHIER_DEFAULT; + } +} /* end of nicSDIOReadIntStatus() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevWriteWithSdioCmd52(IN struct GLUE_INFO *prGlueInfo, IN uint32_t u4Addr, IN uint8_t ucData) +{ + int ret = 0; + +#if (MTK_WCN_HIF_SDIO == 0) + sdio_claim_host(prGlueInfo->rHifInfo.func); + sdio_writeb(prGlueInfo->rHifInfo.func, ucData, u4Addr, &ret); + 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\n", ret); + } + + return (ret) ? FALSE : TRUE; + +} /* end of kalDevWriteWithSdioCmd52() */ + +void glSetPowerState(IN struct GLUE_INFO *prGlueInfo, IN uint32_t ePowerMode) +{ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write data to device +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] prMsduInfo msdu info +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevWriteData(IN struct GLUE_INFO *prGlueInfo, IN struct MSDU_INFO *prMsduInfo) +{ + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + struct TX_CTRL *prTxCtrl; + uint8_t *pucOutputBuf = (uint8_t *) NULL; + uint32_t u4PaddingLength; + struct sk_buff *skb; + uint8_t *pucBuf; + uint32_t u4Length; + uint8_t ucTC; + + SDIO_TIME_INTERVAL_DEC(); + + skb = (struct sk_buff *)prMsduInfo->prPacket; + pucBuf = skb->data; + u4Length = skb->len; + ucTC = prMsduInfo->ucTC; + + prTxCtrl = &prAdapter->rTxCtrl; + pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; + + if (prTxCtrl->u4WrIdx + ALIGN_4(u4Length) > prAdapter->u4CoalescingBufCachedSize) { + if ((prAdapter->u4CoalescingBufCachedSize - ALIGN_4(prTxCtrl->u4WrIdx)) >= HIF_TX_TERMINATOR_LEN) { + /* fill with single dword of zero as TX-aggregation termination */ + *(uint32_t *) (&((pucOutputBuf)[ALIGN_4(prTxCtrl->u4WrIdx)])) = 0; + } + + if (HAL_TEST_FLAG(prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { + if (kalDevPortWrite(prGlueInfo, MCR_WTDR1, prTxCtrl->u4WrIdx, + pucOutputBuf, prAdapter->u4CoalescingBufCachedSize) == FALSE) { + HAL_SET_FLAG(prAdapter, ADAPTER_FLAG_HW_ERR); + fgIsBusAccessFailed = TRUE; + } + prHifInfo->rStatCounter.u4DataPortWriteCnt++; + } + prTxCtrl->u4WrIdx = 0; + } + + SDIO_REC_TIME_START(); + memcpy(pucOutputBuf + prTxCtrl->u4WrIdx, pucBuf, u4Length); + SDIO_REC_TIME_END(); + SDIO_ADD_TIME_INTERVAL(prHifInfo->rStatCounter.u4TxDataCpTime); + + prTxCtrl->u4WrIdx += u4Length; + + u4PaddingLength = (ALIGN_4(u4Length) - u4Length); + if (u4PaddingLength) { + memset(pucOutputBuf + prTxCtrl->u4WrIdx, 0, u4PaddingLength); + prTxCtrl->u4WrIdx += u4PaddingLength; + } + + SDIO_REC_TIME_START(); + if (!prMsduInfo->pfTxDoneHandler) + kalFreeTxMsdu(prAdapter, prMsduInfo); + SDIO_REC_TIME_END(); + SDIO_ADD_TIME_INTERVAL(prHifInfo->rStatCounter.u4TxDataFreeTime); + + /* Update pending Tx done count */ + halUpdateTxDonePendingCount(prAdapter, TRUE, ucTC, u4Length); + + prHifInfo->rStatCounter.u4DataPktWriteCnt++; + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Kick Tx data to device +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevKickData(IN struct GLUE_INFO *prGlueInfo) +{ + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + struct TX_CTRL *prTxCtrl; + uint8_t *pucOutputBuf = (uint8_t *) NULL; + + prTxCtrl = &prAdapter->rTxCtrl; + pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; + + if (prTxCtrl->u4WrIdx == 0) + return FALSE; + + if ((prAdapter->u4CoalescingBufCachedSize - ALIGN_4(prTxCtrl->u4WrIdx)) >= HIF_TX_TERMINATOR_LEN) { + /* fill with single dword of zero as TX-aggregation termination */ + *(uint32_t *) (&((pucOutputBuf)[ALIGN_4(prTxCtrl->u4WrIdx)])) = 0; + } + + if (HAL_TEST_FLAG(prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { + if (kalDevPortWrite(prGlueInfo, MCR_WTDR1, prTxCtrl->u4WrIdx, + pucOutputBuf, prAdapter->u4CoalescingBufCachedSize) == FALSE) { + HAL_SET_FLAG(prAdapter, ADAPTER_FLAG_HW_ERR); + fgIsBusAccessFailed = TRUE; + } + prHifInfo->rStatCounter.u4DataPortWriteCnt++; + } + + prTxCtrl->u4WrIdx = 0; + + prHifInfo->rStatCounter.u4DataPortKickCnt++; + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write command to device +* +* \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 +*/ +/*----------------------------------------------------------------------------*/ +enum ENUM_CMD_TX_RESULT kalDevWriteCmd(IN struct GLUE_INFO *prGlueInfo, + IN struct CMD_INFO *prCmdInfo, IN uint8_t ucTC) +{ + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; +/* P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; */ + struct TX_CTRL *prTxCtrl; + uint8_t *pucOutputBuf = (uint8_t *) NULL; + uint16_t u2OverallBufferLength = 0; +/* WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; */ + + prTxCtrl = &prAdapter->rTxCtrl; + pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; + + if (TFCB_FRAME_PAD_TO_DW(prCmdInfo->u4TxdLen + prCmdInfo->u4TxpLen) > + prAdapter->u4CoalescingBufCachedSize) { + DBGLOG(HAL, ERROR, "Command TX buffer underflow!\n"); + return CMD_TX_RESULT_FAILED; + } + + if (prCmdInfo->u4TxdLen) { + memcpy((pucOutputBuf + u2OverallBufferLength), prCmdInfo->pucTxd, prCmdInfo->u4TxdLen); + u2OverallBufferLength += prCmdInfo->u4TxdLen; + } + + if (prCmdInfo->u4TxpLen) { + memcpy((pucOutputBuf + u2OverallBufferLength), prCmdInfo->pucTxp, prCmdInfo->u4TxpLen); + u2OverallBufferLength += prCmdInfo->u4TxpLen; + } + + memset(pucOutputBuf + u2OverallBufferLength, 0, + (TFCB_FRAME_PAD_TO_DW(u2OverallBufferLength) - u2OverallBufferLength)); + + if ((prAdapter->u4CoalescingBufCachedSize - ALIGN_4(u2OverallBufferLength)) >= HIF_TX_TERMINATOR_LEN) { + /* fill with single dword of zero as TX-aggregation termination */ + *(uint32_t *) (&((pucOutputBuf)[ALIGN_4(u2OverallBufferLength)])) = 0; + } + if (HAL_TEST_FLAG(prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { + if (kalDevPortWrite(prGlueInfo, MCR_WTDR1, TFCB_FRAME_PAD_TO_DW(u2OverallBufferLength), + pucOutputBuf, prAdapter->u4CoalescingBufCachedSize) == FALSE) { + HAL_SET_FLAG(prAdapter, ADAPTER_FLAG_HW_ERR); + fgIsBusAccessFailed = TRUE; + } + prGlueInfo->rHifInfo.rStatCounter.u4CmdPortWriteCnt++; + } + + /* Update pending Tx done count */ + halUpdateTxDonePendingCount(prAdapter, TRUE, ucTC, + (prCmdInfo->u4TxdLen + prCmdInfo->u4TxpLen)); + + prGlueInfo->rHifInfo.rStatCounter.u4CmdPktWriteCnt++; + return CMD_TX_RESULT_SUCCESS; +} + +void glGetDev(void *ctx, struct device **dev) +{ +#if MTK_WCN_HIF_SDIO + mtk_wcn_hif_sdio_get_dev(*((unsigned long *) ctx), dev); +#else + *dev = &((struct sdio_func *)ctx)->dev; +#endif +} + +void glGetHifDev(struct GL_HIF_INFO *prHif, struct device **dev) +{ +#if MTK_WCN_HIF_SDIO + mtk_wcn_hif_sdio_get_dev(prHif->cltCtx, dev); +#else + *dev = &(prHif->func->dev); +#endif +} + +u_int8_t glWakeupSdio(struct GLUE_INFO *prGlueInfo) +{ + u_int8_t fgSuccess = TRUE; + +#if (HIF_SDIO_SUPPORT_GPIO_SLEEP_MODE && MTK_WCN_HIF_SDIO) + #if KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE + if (mtk_wcn_stp_sdio_wake_up_ctrl(prGlueInfo->rHifInfo.cltCtx) != 0) + #else + if (mtk_wcn_hif_sdio_wake_up_ctrl(prGlueInfo->rHifInfo.cltCtx) != 0) + #endif + fgSuccess = FALSE; +#endif + + return fgSuccess; +} + +#if (CFG_CHIP_RESET_SUPPORT == 1) && (MTK_WCN_HIF_SDIO == 0) +void kalRemoveProbe(IN struct GLUE_INFO *prGlueInfo) +{ + struct mmc_host *host; + + ASSERT(prGlueInfo); + + host = prGlueInfo->rHifInfo.func->card->host; + host->rescan_entered = 0; + + /* clear trx fifo */ + DBGLOG(INIT, STATE, "[SER][L0] mmc_remove_host\n"); + mmc_remove_host(prGlueInfo->rHifInfo.func->card->host); + + DBGLOG(INIT, STATE, "[SER][L0] mmc_add_host\n"); + mmc_add_host(host); + +} +#endif + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/sdio_test_driver_core.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/sdio_test_driver_core.c new file mode 100644 index 0000000000000..996f4137b3f9f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/sdio_test_driver_core.c @@ -0,0 +1,448 @@ +#include "gl_os.h" + +#if (CFG_SDIO_1BIT_DATA_MODE == 1) +/* + * linux/drivers/mmc/core/core.c + * + * Copyright (C) 2003-2004 Russell King, All Rights Reserved. + * SD support Copyright (C) 2004 Ian Molton, All Rights Reserved. + * Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved. + * MMCv4 support Copyright (C) 2006 Philip Langdale, All Rights Reserved. + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +#include "test_driver_sdio_ops.h" + + +/* + * Internal function that does the actual ios call to the host driver, + * optionally printing some debug output. + */ +static inline void mmc_set_ios(struct mmc_host *host) +{ + struct mmc_ios *ios = &host->ios; + + pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u width %u timing %u\n", + mmc_hostname(host), ios->clock, ios->bus_mode, + ios->power_mode, ios->chip_select, ios->vdd, + ios->bus_width, ios->timing); + + host->ops->set_ios(host, ios); +} + +/* + * Control chip select pin on a host. + */ +void mmc_set_chip_select(struct mmc_host *host, int mode) +{ + host->ios.chip_select = mode; + mmc_set_ios(host); +} + +/* + * Sets the host clock to the highest possible frequency that + * is below "hz". + */ +void mmc_set_clock(struct mmc_host *host, unsigned int hz) +{ + WARN_ON(hz < host->f_min); + + if (hz > host->f_max) + hz = host->f_max; + + #if 1 + pr_debug("%s(): %dHz\n", __func__, hz); + #endif + + host->ios.clock = hz; + mmc_set_ios(host); +} + +/* + * Change the bus mode (open drain/push-pull) of a host. + */ +void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode) +{ + host->ios.bus_mode = mode; + mmc_set_ios(host); +} + +/* + * Change data bus width of a host. + */ +void mmc_set_bus_width(struct mmc_host *host, unsigned int width) +{ + host->ios.bus_width = width; + mmc_set_ios(host); +} + +/* + * Mask off any voltages we don't support and select + * the lowest voltage + */ +u32 mmc_select_voltage(struct mmc_host *host, u32 ocr) +{ + int bit; + + ocr &= host->ocr_avail; + + bit = ffs(ocr); + if (bit) { + bit -= 1; + + ocr &= 3 << bit; + + host->ios.vdd = bit; + mmc_set_ios(host); + } else { + pr_warn("%s: host doesn't support card's voltages\n", + mmc_hostname(host)); + ocr = 0; + } + + return ocr; +} + +/* + * Select timing parameters for host. + */ +void mmc_set_timing(struct mmc_host *host, unsigned int timing) +{ + host->ios.timing = timing; + mmc_set_ios(host); +} + + +static void mmc_power_off(struct mmc_host *host) +{ + host->ios.clock = 0; + host->ios.vdd = 0; + if (!mmc_host_is_spi(host)) { + host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; + host->ios.chip_select = MMC_CS_DONTCARE; + } + host->ios.power_mode = MMC_POWER_OFF; + host->ios.bus_width = MMC_BUS_WIDTH_1; + host->ios.timing = MMC_TIMING_LEGACY; + mmc_set_ios(host); +} + +/* + * Cleanup when the last reference to the bus operator is dropped. + */ +static void __mmc_release_bus(struct mmc_host *host) +{ + BUG_ON(!host); + BUG_ON(host->bus_refs); + BUG_ON(!host->bus_dead); + + host->bus_ops = NULL; +} + +/* + * Increase reference count of bus operator + */ +static inline void mmc_bus_get(struct mmc_host *host) +{ + unsigned long flags; + + spin_lock_irqsave(&host->lock, flags); + host->bus_refs++; + spin_unlock_irqrestore(&host->lock, flags); +} + +/* + * Decrease reference count of bus operator and free it if + * it is the last reference. + */ +static inline void mmc_bus_put(struct mmc_host *host) +{ + unsigned long flags; + + spin_lock_irqsave(&host->lock, flags); + host->bus_refs--; + if ((host->bus_refs == 0) && host->bus_ops) + __mmc_release_bus(host); + spin_unlock_irqrestore(&host->lock, flags); +} + +/* + * Assign a mmc bus handler to a host. Only one bus handler may control a + * host at any given time. + */ +void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops) +{ + unsigned long flags; + + BUG_ON(!host); + BUG_ON(!ops); + + WARN_ON(!host->claimed); + + spin_lock_irqsave(&host->lock, flags); + + BUG_ON(host->bus_ops); + BUG_ON(host->bus_refs); + + host->bus_ops = ops; + host->bus_refs = 1; + host->bus_dead = 0; + + spin_unlock_irqrestore(&host->lock, flags); +} + +/* + * Remove the current bus handler from a host. Assumes that there are + * no interesting cards left, so the bus is powered down. + */ +void mmc_detach_bus(struct mmc_host *host) +{ + unsigned long flags; + + BUG_ON(!host); + + WARN_ON(!host->claimed); + WARN_ON(!host->bus_ops); + + spin_lock_irqsave(&host->lock, flags); + + host->bus_dead = 1; + + spin_unlock_irqrestore(&host->lock, flags); + + mmc_power_off(host); + + mmc_bus_put(host); +} + +int mmc_app_set_bus_width(struct mmc_card *card, int width) +{ + int err; + struct mmc_command cmd; + + BUG_ON(!card); + BUG_ON(!card->host); + + memset(&cmd, 0, sizeof(struct mmc_command)); + + cmd.opcode = SD_APP_SET_BUS_WIDTH; + cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; + + switch (width) { + case MMC_BUS_WIDTH_1: + cmd.arg = SD_BUS_WIDTH_1; + break; + case MMC_BUS_WIDTH_4: + cmd.arg = SD_BUS_WIDTH_4; + break; + default: + return -EINVAL; + } + + err = mmc_wait_for_app_cmd(card->host, card, &cmd, MMC_CMD_RETRIES); + if (err) + return err; + + return 0; +} + +int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) +{ + struct mmc_command cmd; + int i, err = 0; + + BUG_ON(!host); + + memset(&cmd, 0, sizeof(struct mmc_command)); + + cmd.opcode = SD_APP_OP_COND; + if (mmc_host_is_spi(host)) + cmd.arg = ocr & (1 << 30); /* SPI only defines one bit */ + else + cmd.arg = ocr; + cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR; + + for (i = 100; i; i--) { + err = mmc_wait_for_app_cmd(host, NULL, &cmd, MMC_CMD_RETRIES); + if (err) + break; + + /* if we're just probing, do a single pass */ + if (ocr == 0) + break; + + /* otherwise wait until reset completes */ + if (mmc_host_is_spi(host)) { + if (!(cmd.resp[0] & R1_SPI_IDLE)) + break; + } else { + if (cmd.resp[0] & MMC_CARD_BUSY) + break; + } + + err = -ETIMEDOUT; + + mmc_delay(10); + } + + if (rocr && !mmc_host_is_spi(host)) + *rocr = cmd.resp[0]; + + return err; +} + +int mmc_send_if_cond(struct mmc_host *host, u32 ocr) +{ + struct mmc_command cmd; + int err; + static const u8 test_pattern = 0xAA; + u8 result_pattern; + + /* + * To support SD 2.0 cards, we must always invoke SD_SEND_IF_COND + * before SD_APP_OP_COND. This command will harmlessly fail for + * SD 1.0 cards. + */ + cmd.opcode = SD_SEND_IF_COND; + cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern; + cmd.flags = MMC_RSP_SPI_R7 | MMC_RSP_R7 | MMC_CMD_BCR; + + err = mmc_wait_for_cmd(host, &cmd, 0); + if (err) + return err; + + if (mmc_host_is_spi(host)) + result_pattern = cmd.resp[1] & 0xFF; + else + result_pattern = cmd.resp[0] & 0xFF; + + if (result_pattern != test_pattern) + return -EIO; + + return 0; +} + + + +static int sdio_enable_wide(struct mmc_card *card) +{ + int ret; + u8 ctrl; + + if (!(card->host->caps & MMC_CAP_4_BIT_DATA)) + return 0; + + + if (card->cccr.low_speed && !card->cccr.wide_bus) + return 0; + + + ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_IF, 0, &ctrl); + if (ret) + return ret; + + + if ((ctrl & SDIO_BUS_WIDTH_MASK) == SDIO_BUS_WIDTH_RESERVED) + pr_warn("%s: SDIO_CCCR_IF is invalid: 0x%02x\n", + mmc_hostname(card->host), ctrl); + + /* set as 4-bit bus width */ + ctrl &= ~SDIO_BUS_WIDTH_MASK; + ctrl |= SDIO_BUS_WIDTH_4BIT; + + ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_IF, ctrl, NULL); + if (ret) + return ret; + + return 1; +} + + + +/* + * Devices that remain active during a system suspend are + * put back into 1-bit mode. + */ +int sdio_disable_wide(struct mmc_card *card) +{ + int ret; + u8 ctrl; + + if (!(card->host->caps & MMC_CAP_4_BIT_DATA)) + return 0; + + + if (card->cccr.low_speed && !card->cccr.wide_bus) + return 0; + + + ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_IF, 0, &ctrl); + if (ret) + return ret; + + + if (!(ctrl & SDIO_BUS_WIDTH_4BIT)) + return 0; + + + ctrl &= ~SDIO_BUS_WIDTH_4BIT; + ctrl |= SDIO_BUS_ASYNC_INT; + + ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_IF, ctrl, NULL); + if (ret) + return ret; + + + mmc_set_bus_width(card->host, MMC_BUS_WIDTH_1); + + return 0; +} + + +int sdio_enable_4bit_bus(struct mmc_card *card) +{ + int err; + + if (card->type == MMC_TYPE_SDIO) + return sdio_enable_wide(card); + + + if ((card->host->caps & MMC_CAP_4_BIT_DATA) && + (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) { + + err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4); + if (err) + return err; + } else + return 0; + + + err = sdio_enable_wide(card); + if (err <= 0) + mmc_app_set_bus_width(card, MMC_BUS_WIDTH_1); + + return err; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/sdio_test_driver_ops.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/sdio_test_driver_ops.c new file mode 100644 index 0000000000000..82dfd14889c71 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/sdio_test_driver_ops.c @@ -0,0 +1,194 @@ + +#include "gl_os.h" + +#if (CFG_SDIO_1BIT_DATA_MODE == 1) +/* + * linux/drivers/mmc/sdio_ops.c + * + * Copyright 2006-2007 Pierre Ossman + * + * 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. + */ + +#include + +#if 0 +#include +#include +#include +#include +#include +#endif + +#include "test_driver_sdio_ops.h" + +int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) +{ + struct mmc_command cmd; + int i, err = 0; + + BUG_ON(!host); + + memset(&cmd, 0, sizeof(struct mmc_command)); + + cmd.opcode = SD_IO_SEND_OP_COND; + cmd.arg = ocr; + cmd.flags = MMC_RSP_SPI_R4 | MMC_RSP_R4 | MMC_CMD_BCR; + + for (i = 100; i; i--) { + err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); + if (err) + break; + + /* if we're just probing, do a single pass */ + if (ocr == 0) { + pr_warn("PROBE ONLY! RESP[0] = 0x%08x\n", cmd.resp[0]); + break; + } + + /* otherwise wait until reset completes */ + if (mmc_host_is_spi(host)) { + /* + * Both R1_SPI_IDLE and MMC_CARD_BUSY indicate + * an initialized card under SPI, but some cards + * (Marvell's) only behave when looking at this + * one. + */ + if (cmd.resp[1] & MMC_CARD_BUSY) + break; + } else { + if (cmd.resp[0] & MMC_CARD_BUSY) + break; + } + + err = -ETIMEDOUT; + + mmc_delay(10); + } + + if (rocr) + *rocr = cmd.resp[mmc_host_is_spi(host) ? 1 : 0]; + + return err; +} + +int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, + unsigned addr, u8 in, u8 *out) +{ + struct mmc_command cmd; + int err; + + BUG_ON(!card); + BUG_ON(fn > 7); + + /* sanity check */ + if (addr & ~0x1FFFF) + return -EINVAL; + + memset(&cmd, 0, sizeof(struct mmc_command)); + + cmd.opcode = SD_IO_RW_DIRECT; + cmd.arg = write ? 0x80000000 : 0x00000000; + cmd.arg |= fn << 28; + cmd.arg |= (write && out) ? 0x08000000 : 0x00000000; + cmd.arg |= addr << 9; + cmd.arg |= in; + cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC; + + err = mmc_wait_for_cmd(card->host, &cmd, 0); + if (err) + return err; + + if (mmc_host_is_spi(card->host)) { + /* host driver already reported errors */ + } else { + if (cmd.resp[0] & R5_ERROR) + return -EIO; + if (cmd.resp[0] & R5_FUNCTION_NUMBER) + return -EINVAL; + if (cmd.resp[0] & R5_OUT_OF_RANGE) + return -ERANGE; + } + + if (out) { + if (mmc_host_is_spi(card->host)) + *out = (cmd.resp[0] >> 8) & 0xFF; + else + *out = cmd.resp[0] & 0xFF; + } + + return 0; +} + +int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, + unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz) +{ + struct mmc_request mrq; + struct mmc_command cmd; + struct mmc_data data; + struct scatterlist sg; + + BUG_ON(!card); + BUG_ON(fn > 7); + BUG_ON(blocks == 1 && blksz > 512); + WARN_ON(blocks == 0); + WARN_ON(blksz == 0); + + /* sanity check */ + if (addr & ~0x1FFFF) + return -EINVAL; + + memset(&mrq, 0, sizeof(struct mmc_request)); + memset(&cmd, 0, sizeof(struct mmc_command)); + memset(&data, 0, sizeof(struct mmc_data)); + + mrq.cmd = &cmd; + mrq.data = &data; + + cmd.opcode = SD_IO_RW_EXTENDED; + cmd.arg = write ? 0x80000000 : 0x00000000; + cmd.arg |= fn << 28; + cmd.arg |= incr_addr ? 0x04000000 : 0x00000000; + cmd.arg |= addr << 9; + if (blocks == 1 && blksz <= 512) + cmd.arg |= (blksz == 512) ? 0 : blksz; /* byte mode */ + else + cmd.arg |= 0x08000000 | blocks; /* block mode */ + cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC; + + data.blksz = blksz; + data.blocks = blocks; + data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ; + data.sg = &sg; + data.sg_len = 1; + + sg_init_one(&sg, buf, blksz * blocks); + + mmc_set_data_timeout(&data, card); + + mmc_wait_for_req(card->host, &mrq); + + if (cmd.error) + return cmd.error; + if (data.error) + return data.error; + + if (mmc_host_is_spi(card->host)) { + /* host driver already reported errors */ + } else { + if (cmd.resp[0] & R5_ERROR) + return -EIO; + if (cmd.resp[0] & R5_FUNCTION_NUMBER) + return -EINVAL; + if (cmd.resp[0] & R5_OUT_OF_RANGE) + return -ERANGE; + } + + return 0; +} + +#endif + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/x86.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/x86.c new file mode 100644 index 0000000000000..7cbc34e29cdef --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/sdio/x86.c @@ -0,0 +1,62 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** +*[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. +******************************************************************************/ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/usb/hal_api.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/usb/hal_api.c new file mode 100644 index 0000000000000..e6279b8b2fe42 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/usb/hal_api.c @@ -0,0 +1,1945 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** +*[File] hif_api.c +*[Version] v1.0 +*[Revision Date] 2015-09-08 +*[Author] +*[Description] +* The program provides USB HIF APIs +*[Copyright] +* Copyright (C) 2015 MediaTek Incorporation. All Rights Reserved. +******************************************************************************/ + +/******************************************************************************* +* C O M P I L E 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 +#include + +#include +#ifndef CONFIG_X86 +#include +#endif + +#include "mt66xx_reg.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 const uint16_t arTcToUSBEP[USB_TC_NUM] = { + USB_DATA_BULK_OUT_EP4, + USB_DATA_BULK_OUT_EP5, + USB_DATA_BULK_OUT_EP6, + USB_DATA_BULK_OUT_EP7, + USB_DATA_BULK_OUT_EP8, + USB_DATA_BULK_OUT_EP9, + + /* Second HW queue */ +#if NIC_TX_ENABLE_SECOND_HW_QUEUE + USB_DATA_BULK_OUT_EP9, + USB_DATA_BULK_OUT_EP9, + USB_DATA_BULK_OUT_EP9, + USB_DATA_BULK_OUT_EP9, +#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 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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t halVerifyChipID(IN struct ADAPTER *prAdapter) +{ + uint32_t u4CIR = 0; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + + if (prAdapter->fgIsReadRevID) + return TRUE; + + prChipInfo = prAdapter->chip_info; + + HAL_MCR_RD(prAdapter, prChipInfo->top_hcr, &u4CIR); + DBGLOG(INIT, TRACE, "Chip ID: 0x%4x\n", u4CIR); + + if (u4CIR != prChipInfo->chip_id) + return FALSE; + + HAL_MCR_RD(prAdapter, prChipInfo->top_hvr, &u4CIR); + DBGLOG(INIT, TRACE, "Revision ID: 0x%4x\n", u4CIR); + + prAdapter->ucRevID = (uint8_t) (u4CIR & 0xF); + prAdapter->fgIsReadRevID = TRUE; + return TRUE; +} + +uint32_t +halRxWaitResponse(IN struct ADAPTER *prAdapter, IN uint8_t ucPortIdx, OUT uint8_t *pucRspBuffer, + IN uint32_t u4MaxRespBufferLen, OUT uint32_t *pu4Length) +{ + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + struct RX_CTRL *prRxCtrl; + u_int8_t ret = FALSE; + struct BUS_INFO *prBusInfo; + + DEBUGFUNC("halRxWaitResponse"); + + ASSERT(prAdapter); + ASSERT(pucRspBuffer); + + prRxCtrl = &prAdapter->rRxCtrl; + prBusInfo = prAdapter->chip_info->bus_info; + + if (prBusInfo->asicUsbEventEpDetected) + ucPortIdx = prBusInfo->asicUsbEventEpDetected(prAdapter); + else { + if (prHifInfo->fgEventEpDetected == FALSE) { + /* NOTE: This is temporary compatiable code with old/new CR4 FW to detect + * which EVENT endpoint that. + * CR4 FW is using. If the new EP4IN-using CR4 FW works without + * any issue for a while, + * this code block will be removed. + */ + if (prAdapter->fgIsCr4FwDownloaded) { + ucPortIdx = USB_DATA_EP_IN; + ret = kalDevPortRead(prAdapter->prGlueInfo, ucPortIdx, + ALIGN_4(u4MaxRespBufferLen) + LEN_USB_RX_PADDING_CSO, + prRxCtrl->pucRxCoalescingBufPtr, HIF_RX_COALESCING_BUFFER_SIZE); + + if (ret == TRUE) { + prHifInfo->eEventEpType = EVENT_EP_TYPE_DATA_EP; + } else { + ucPortIdx = USB_EVENT_EP_IN; + ret = kalDevPortRead(prAdapter->prGlueInfo, ucPortIdx, + ALIGN_4(u4MaxRespBufferLen) + LEN_USB_RX_PADDING_CSO, + prRxCtrl->pucRxCoalescingBufPtr, HIF_RX_COALESCING_BUFFER_SIZE); + } + prHifInfo->fgEventEpDetected = TRUE; + + kalMemCopy(pucRspBuffer, prRxCtrl->pucRxCoalescingBufPtr, u4MaxRespBufferLen); + *pu4Length = u4MaxRespBufferLen; + + if (ret == FALSE) + u4Status = WLAN_STATUS_FAILURE; + return u4Status; + } + + ucPortIdx = USB_EVENT_EP_IN; + } else { + if (prHifInfo->eEventEpType == EVENT_EP_TYPE_DATA_EP) + if (prAdapter->fgIsCr4FwDownloaded) + ucPortIdx = USB_DATA_EP_IN; + else + ucPortIdx = USB_EVENT_EP_IN; + else + ucPortIdx = USB_EVENT_EP_IN; + } + } + ret = kalDevPortRead(prAdapter->prGlueInfo, ucPortIdx, + ALIGN_4(u4MaxRespBufferLen) + LEN_USB_RX_PADDING_CSO, + prRxCtrl->pucRxCoalescingBufPtr, HIF_RX_COALESCING_BUFFER_SIZE); + + kalMemCopy(pucRspBuffer, prRxCtrl->pucRxCoalescingBufPtr, u4MaxRespBufferLen); + *pu4Length = u4MaxRespBufferLen; + + if (ret == FALSE) + u4Status = WLAN_STATUS_FAILURE; + + return u4Status; +} + +uint32_t halTxUSBSendCmd(IN struct GLUE_INFO *prGlueInfo, IN uint8_t ucTc, IN struct CMD_INFO *prCmdInfo) +{ + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + struct USB_REQ *prUsbReq; + struct BUF_CTRL *prBufCtrl; + uint16_t u2OverallBufferLength = 0; + unsigned long flags; + uint8_t ucQueIdx; + struct mt66xx_chip_info *prChipInfo; + int ret; + struct TX_DESC_OPS_T *prTxDescOps; + + if (!(prHifInfo->state == USB_STATE_LINK_UP || + prHifInfo->state == USB_STATE_PRE_RESUME || + prHifInfo->state == USB_STATE_PRE_SUSPEND_START || + prHifInfo->state == USB_STATE_READY)) + return WLAN_STATUS_FAILURE; + + prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxCmdFreeQ, &prHifInfo->rTxCmdQLock); + if (prUsbReq == NULL) + return WLAN_STATUS_RESOURCES; + + prBufCtrl = prUsbReq->prBufCtrl; + + if ((TFCB_FRAME_PAD_TO_DW(prCmdInfo->u4TxdLen + prCmdInfo->u4TxpLen) + LEN_USB_UDMA_TX_TERMINATOR) > + prBufCtrl->u4BufSize) { + DBGLOG(HAL, ERROR, "Command TX buffer underflow!\n"); + glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxCmdFreeQ, prUsbReq, + &prHifInfo->rTxCmdQLock, FALSE); + return WLAN_STATUS_RESOURCES; + } + + DBGLOG(HAL, INFO, "TX URB[0x%p]\n", prUsbReq->prUrb); + + prChipInfo = prGlueInfo->prAdapter->chip_info; + prTxDescOps = prChipInfo->prTxDescOps; + HAL_WRITE_HIF_TXD(prChipInfo, prBufCtrl->pucBuf, (prCmdInfo->u4TxdLen + prCmdInfo->u4TxpLen)); + u2OverallBufferLength += prChipInfo->u2HifTxdSize; + + if (prCmdInfo->u4TxdLen) { + memcpy((prBufCtrl->pucBuf + u2OverallBufferLength), prCmdInfo->pucTxd, prCmdInfo->u4TxdLen); + u2OverallBufferLength += prCmdInfo->u4TxdLen; + } + + if (prCmdInfo->u4TxpLen) { + memcpy((prBufCtrl->pucBuf + u2OverallBufferLength), prCmdInfo->pucTxp, prCmdInfo->u4TxpLen); + u2OverallBufferLength += prCmdInfo->u4TxpLen; + } + + if (prChipInfo->is_support_cr4 && prTxDescOps->nic_txd_queue_idx_op) { + void *prTxDesc = (void *)(prBufCtrl->pucBuf + + prChipInfo->u2HifTxdSize); + ucQueIdx = prTxDescOps->nic_txd_queue_idx_op( + prTxDesc, 0, FALSE); + /* For H2CDMA Tx CMD mapping + * Mapping port1 queue0~3 to queue28~31, + * and CR4 will unmask this. + */ + prTxDescOps->nic_txd_queue_idx_op( + prTxDesc, + (ucQueIdx | USB_TX_CMD_QUEUE_MASK), + TRUE); + } + + /* DBGLOG_MEM32(SW4, INFO, prBufCtrl->pucBuf, 32); */ + memset(prBufCtrl->pucBuf + u2OverallBufferLength, 0, + ((TFCB_FRAME_PAD_TO_DW(u2OverallBufferLength) - u2OverallBufferLength) + LEN_USB_UDMA_TX_TERMINATOR)); + prBufCtrl->u4WrIdx = TFCB_FRAME_PAD_TO_DW(u2OverallBufferLength) + LEN_USB_UDMA_TX_TERMINATOR; + + prUsbReq->prPriv = (void *) prCmdInfo; + usb_fill_bulk_urb(prUsbReq->prUrb, + prHifInfo->udev, + usb_sndbulkpipe(prHifInfo->udev, arTcToUSBEP[ucTc]), + (void *)prUsbReq->prBufCtrl->pucBuf, + prBufCtrl->u4WrIdx, halTxUSBSendCmdComplete, (void *)prUsbReq); + +#if CFG_USB_CONSISTENT_DMA + prUsbReq->prUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; +#endif + spin_lock_irqsave(&prHifInfo->rTxCmdQLock, flags); + ret = glUsbSubmitUrb(prHifInfo, prUsbReq->prUrb, SUBMIT_TYPE_TX_CMD); + if (ret) { + DBGLOG(HAL, ERROR, + "glUsbSubmitUrb() reports error (%d) [%s] (EP%d OUT)\n", + ret, __func__, arTcToUSBEP[ucTc]); + list_add_tail(&prUsbReq->list, &prHifInfo->rTxCmdFreeQ); + spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, flags); + return WLAN_STATUS_FAILURE; + } + list_add_tail(&prUsbReq->list, &prHifInfo->rTxCmdSendingQ); + spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, flags); + + if (wlanIsChipRstRecEnabled(prGlueInfo->prAdapter) + && wlanIsChipNoAck(prGlueInfo->prAdapter)) { + wlanChipRstPreAct(prGlueInfo->prAdapter); + DBGLOG(HAL, ERROR, "usb trigger whole reset\n"); + HAL_WIFI_FUNC_CHIP_RESET(prGlueInfo->prAdapter); + } + return u4Status; +} + +void halTxUSBSendCmdComplete(struct urb *urb) +{ + struct USB_REQ *prUsbReq = urb->context; + struct GL_HIF_INFO *prHifInfo = prUsbReq->prHifInfo; + struct GLUE_INFO *prGlueInfo = prHifInfo->prGlueInfo; + unsigned long flags; + +#if CFG_USB_TX_HANDLE_IN_HIF_THREAD + spin_lock_irqsave(&prHifInfo->rTxCmdQLock, flags); + list_del_init(&prUsbReq->list); + list_add_tail(&prUsbReq->list, &prHifInfo->rTxCmdCompleteQ); + spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, flags); + + kalSetIntEvent(prGlueInfo); +#else + spin_lock_irqsave(&prHifInfo->rTxCmdQLock, flags); + list_del_init(&prUsbReq->list); + spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, flags); + + halTxUSBProcessCmdComplete(prGlueInfo->prAdapter, prUsbReq); +#endif +} + +void halTxUSBProcessCmdComplete(IN struct ADAPTER *prAdapter, struct USB_REQ *prUsbReq) +{ + struct urb *urb = prUsbReq->prUrb; + uint32_t u4SentDataSize; + struct GL_HIF_INFO *prHifInfo = prUsbReq->prHifInfo; + + if (urb->status != 0) { + DBGLOG(TX, ERROR, "[%s] send CMD fail (status = %d)\n", __func__, urb->status); + /* TODO: handle error */ + } + + DBGLOG(HAL, INFO, "TX CMD DONE: URB[0x%p]\n", urb); + + glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxCmdFreeQ, prUsbReq, &prHifInfo->rTxCmdQLock, FALSE); + + u4SentDataSize = urb->actual_length - LEN_USB_UDMA_TX_TERMINATOR; + nicTxReleaseResource_PSE(prAdapter, TC4_INDEX, nicTxGetPageCount(prAdapter, u4SentDataSize, TRUE), TRUE); +} + +void halTxCancelSendingCmd(IN struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo) +{ + struct USB_REQ *prUsbReq, *prNext; + unsigned long flags; + struct urb *urb = NULL; + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + spin_lock_irqsave(&prHifInfo->rTxCmdQLock, flags); + list_for_each_entry_safe(prUsbReq, prNext, &prHifInfo->rTxCmdSendingQ, list) { + if (prUsbReq->prPriv == (void *) prCmdInfo) { + list_del_init(&prUsbReq->list); + urb = prUsbReq->prUrb; + break; + } + } + spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, flags); + + if (urb) { + prCmdInfo->pfHifTxCmdDoneCb = NULL; + usb_kill_urb(urb); + } +} + +void halTxCancelAllSending(IN struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo; + struct USB_REQ *prUsbReq, *prUsbReqNext; + struct GL_HIF_INFO *prHifInfo; +#if CFG_USB_TX_AGG + uint8_t ucTc; +#endif + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + prHifInfo = &prGlueInfo->rHifInfo; + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxCmdSendingQ, list) { + usb_kill_urb(prUsbReq->prUrb); + } + +#if CFG_USB_TX_AGG + for (ucTc = 0; ucTc < USB_TC_NUM; ++ucTc) + usb_kill_anchored_urbs(&prHifInfo->rTxDataAnchor[ucTc]); +#else + usb_kill_anchored_urbs(&prHifInfo->rTxDataAnchor); +#endif +} + +#if CFG_USB_TX_AGG +uint32_t halTxUSBSendAggData(IN struct GL_HIF_INFO *prHifInfo, IN uint8_t ucTc, IN struct USB_REQ *prUsbReq) +{ + struct GLUE_INFO *prGlueInfo = prHifInfo->prGlueInfo; + struct BUF_CTRL *prBufCtrl = prUsbReq->prBufCtrl; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + int ret; + + memset(prBufCtrl->pucBuf + prBufCtrl->u4WrIdx, 0, LEN_USB_UDMA_TX_TERMINATOR); + prBufCtrl->u4WrIdx += LEN_USB_UDMA_TX_TERMINATOR; + + if (!(prHifInfo->state == USB_STATE_LINK_UP || + prHifInfo->state == USB_STATE_READY)) { + /* No need to dequeue prUsbReq because LINK is not up */ + prBufCtrl->u4WrIdx = 0; + return WLAN_STATUS_FAILURE; + } + + list_del_init(&prUsbReq->list); + + usb_fill_bulk_urb(prUsbReq->prUrb, + prHifInfo->udev, + usb_sndbulkpipe(prHifInfo->udev, arTcToUSBEP[ucTc]), + (void *)prBufCtrl->pucBuf, prBufCtrl->u4WrIdx, halTxUSBSendDataComplete, (void *)prUsbReq); +#if CFG_USB_CONSISTENT_DMA + prUsbReq->prUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; +#endif + + usb_anchor_urb(prUsbReq->prUrb, &prHifInfo->rTxDataAnchor[ucTc]); + ret = glUsbSubmitUrb(prHifInfo, prUsbReq->prUrb, SUBMIT_TYPE_TX_DATA); + if (ret) { + DBGLOG(HAL, ERROR, + "glUsbSubmitUrb() reports error (%d) [%s] (EP%d OUT)\n", + ret, __func__, arTcToUSBEP[ucTc]); + halTxUSBProcessMsduDone(prGlueInfo, prUsbReq); + prBufCtrl->u4WrIdx = 0; + usb_unanchor_urb(prUsbReq->prUrb); + list_add_tail(&prUsbReq->list, &prHifInfo->rTxDataCompleteQ); +#if CFG_USB_TX_HANDLE_IN_HIF_THREAD + kalSetIntEvent(prGlueInfo); +#else + /*tasklet_hi_schedule(&prGlueInfo->rTxCompleteTask);*/ + tasklet_schedule(&prGlueInfo->rTxCompleteTask); +#endif + return WLAN_STATUS_FAILURE; + } + + return u4Status; +} +#endif + +uint32_t halTxUSBSendData(IN struct GLUE_INFO *prGlueInfo, IN struct MSDU_INFO *prMsduInfo) +{ + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + struct mt66xx_chip_info *prChipInfo; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + struct USB_REQ *prUsbReq; + struct BUF_CTRL *prBufCtrl; + uint32_t u4PaddingLength; + struct sk_buff *skb; + uint8_t ucTc; + uint8_t *pucBuf; + uint32_t u4Length; + uint32_t u4TotalLen; +#if CFG_USB_TX_AGG + unsigned long flags; +#else + int ret; +#endif + + prChipInfo = prGlueInfo->prAdapter->chip_info; + skb = (struct sk_buff *)prMsduInfo->prPacket; + pucBuf = skb->data; + u4Length = skb->len; + u4TotalLen = u4Length + prChipInfo->u2HifTxdSize; + ucTc = USB_TRANS_MSDU_TC(prMsduInfo); +#if (CFG_SUPPORT_DMASHDL_SYSDVT) + if (prMsduInfo->ucPktType == ENUM_PKT_ICMP) { + if (DMASHDL_DVT_QUEUE_MAPPING_TYPE1(prGlueInfo->prAdapter) + || DMASHDL_DVT_QUEUE_MAPPING_TYPE2(prGlueInfo->prAdapter)) { + /* send ping packets to each EP for DMASHDL DVT */ + ucTc = prMsduInfo->ucTarQueue % TC_NUM; + /* skip TC4, TC4=>EP8 is reserved for CMD */ + if (ucTc == TC4_INDEX) + ucTc = TC_NUM; + DMASHDL_DVT_INC_PING_PKT_CNT(prGlueInfo->prAdapter, + prMsduInfo->ucTarQueue); + } + } +#endif /* CFG_SUPPORT_DMASHDL_SYSDVT */ + +#if CFG_USB_TX_AGG + spin_lock_irqsave(&prHifInfo->rTxDataQLock, flags); + + if (list_empty(&prHifInfo->rTxDataFreeQ[ucTc])) { + if (glUsbBorrowFfaReq(prHifInfo, ucTc) == FALSE) { + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, flags); + DBGLOG(HAL, ERROR, "run out of rTxDataFreeQ #1!!\n"); + wlanProcessQueuedMsduInfo(prGlueInfo->prAdapter, prMsduInfo); + return WLAN_STATUS_RESOURCES; + } + } + prUsbReq = list_entry(prHifInfo->rTxDataFreeQ[ucTc].next, struct USB_REQ, list); + prBufCtrl = prUsbReq->prBufCtrl; + + if (prHifInfo->u4AggRsvSize[ucTc] < ALIGN_4(u4TotalLen)) + DBGLOG(HAL, ERROR, "u4AggRsvSize[%hhu] count FAIL (%u, %u)\n", + ucTc, prHifInfo->u4AggRsvSize[ucTc], u4TotalLen); + prHifInfo->u4AggRsvSize[ucTc] -= ALIGN_4(u4TotalLen); + + if (prBufCtrl->u4WrIdx + ALIGN_4(u4TotalLen) + LEN_USB_UDMA_TX_TERMINATOR > prBufCtrl->u4BufSize) { + halTxUSBSendAggData(prHifInfo, ucTc, prUsbReq); + + if (list_empty(&prHifInfo->rTxDataFreeQ[ucTc])) { + if (glUsbBorrowFfaReq(prHifInfo, ucTc) == FALSE) { + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, + flags); + DBGLOG(HAL, ERROR, "run out of rTxDataFreeQ #2!!\n"); + wlanProcessQueuedMsduInfo(prGlueInfo->prAdapter, prMsduInfo); + return WLAN_STATUS_FAILURE; + } + } + + prUsbReq = list_entry(prHifInfo->rTxDataFreeQ[ucTc].next, struct USB_REQ, list); + prBufCtrl = prUsbReq->prBufCtrl; + } + + HAL_WRITE_HIF_TXD(prChipInfo, prBufCtrl->pucBuf + prBufCtrl->u4WrIdx, u4Length); + prBufCtrl->u4WrIdx += prChipInfo->u2HifTxdSize; + memcpy(prBufCtrl->pucBuf + prBufCtrl->u4WrIdx, pucBuf, u4Length); + prBufCtrl->u4WrIdx += u4Length; + + u4PaddingLength = (ALIGN_4(u4TotalLen) - u4TotalLen); + if (u4PaddingLength) { + memset(prBufCtrl->pucBuf + prBufCtrl->u4WrIdx, 0, u4PaddingLength); + prBufCtrl->u4WrIdx += u4PaddingLength; + } + + if (!prMsduInfo->pfTxDoneHandler) + QUEUE_INSERT_TAIL(&prUsbReq->rSendingDataMsduInfoList, (struct QUE_ENTRY *) prMsduInfo); + + if (usb_anchor_empty(&prHifInfo->rTxDataAnchor[ucTc])) + halTxUSBSendAggData(prHifInfo, ucTc, prUsbReq); + + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, flags); +#else + prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxDataFreeQ, + &prHifInfo->rTxDataQLock); + if (prUsbReq == NULL) { + DBGLOG(HAL, ERROR, "run out of rTxDataFreeQ!!\n"); + wlanProcessQueuedMsduInfo(prGlueInfo->prAdapter, prMsduInfo); + return WLAN_STATUS_RESOURCES; + } + + prBufCtrl = prUsbReq->prBufCtrl; + prBufCtrl->u4WrIdx = 0; + + HAL_WRITE_HIF_TXD(prChipInfo, prBufCtrl->pucBuf, u4Length); + prBufCtrl->u4WrIdx += prChipInfo->u2HifTxdSize; + + memcpy(prBufCtrl->pucBuf + prChipInfo->u2HifTxdSize, pucBuf, u4Length); + prBufCtrl->u4WrIdx += u4Length; + + u4PaddingLength = (ALIGN_4(u4TotalLen) - u4TotalLen); + if (u4PaddingLength) { + memset(prBufCtrl->pucBuf + prBufCtrl->u4WrIdx, 0, u4PaddingLength); + prBufCtrl->u4WrIdx += u4PaddingLength; + } + + memset(prBufCtrl->pucBuf + prBufCtrl->u4WrIdx, 0, LEN_USB_UDMA_TX_TERMINATOR); + prBufCtrl->u4WrIdx += LEN_USB_UDMA_TX_TERMINATOR; + + if (!prMsduInfo->pfTxDoneHandler) + QUEUE_INSERT_TAIL(&prUsbReq->rSendingDataMsduInfoList, (struct QUE_ENTRY *) prMsduInfo); + + *((uint8_t *)&prUsbReq->prPriv) = ucTc; + usb_fill_bulk_urb(prUsbReq->prUrb, + prHifInfo->udev, + usb_sndbulkpipe(prHifInfo->udev, arTcToUSBEP[ucTc]), + (void *)prUsbReq->prBufCtrl->pucBuf, + prBufCtrl->u4WrIdx, halTxUSBSendDataComplete, (void *)prUsbReq); +#if CFG_USB_CONSISTENT_DMA + prUsbReq->prUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; +#endif + + usb_anchor_urb(prUsbReq->prUrb, &prHifInfo->rTxDataAnchor); + ret = glUsbSubmitUrb(prHifInfo, prUsbReq->prUrb, SUBMIT_TYPE_TX_DATA); + if (ret) { + DBGLOG(HAL, ERROR, + "glUsbSubmitUrb() reports error (%d) [%s] (EP%d OUT)\n", + ret, __func__, arTcToUSBEP[ucTc]); + halTxUSBProcessMsduDone(prHifInfo->prGlueInfo, prUsbReq); + prBufCtrl->u4WrIdx = 0; + usb_unanchor_urb(prUsbReq->prUrb); + glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxDataFreeQ, prUsbReq, + &prHifInfo->rTxDataQLock, FALSE); + return WLAN_STATUS_FAILURE; + } +#endif + + if (wlanIsChipRstRecEnabled(prGlueInfo->prAdapter) + && wlanIsChipNoAck(prGlueInfo->prAdapter)) { + wlanChipRstPreAct(prGlueInfo->prAdapter); + DBGLOG(HAL, ERROR, "usb trigger whole reset\n"); + HAL_WIFI_FUNC_CHIP_RESET(prGlueInfo->prAdapter); + } + return u4Status; +} + +uint32_t halTxUSBKickData(IN struct GLUE_INFO *prGlueInfo) +{ +#if CFG_USB_TX_AGG + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + struct USB_REQ *prUsbReq; + struct BUF_CTRL *prBufCtrl; + uint8_t ucTc; + unsigned long flags; + + spin_lock_irqsave(&prHifInfo->rTxDataQLock, flags); + + for (ucTc = TC0_INDEX; ucTc < USB_TC_NUM; ucTc++) { + if (list_empty(&prHifInfo->rTxDataFreeQ[ucTc])) + continue; + + prUsbReq = list_entry(prHifInfo->rTxDataFreeQ[ucTc].next, struct USB_REQ, list); + prBufCtrl = prUsbReq->prBufCtrl; + + if (prBufCtrl->u4WrIdx) + halTxUSBSendAggData(prHifInfo, ucTc, prUsbReq); + } + + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, flags); +#endif + + return WLAN_STATUS_SUCCESS; +} + +void halTxUSBSendDataComplete(struct urb *urb) +{ + struct USB_REQ *prUsbReq = urb->context; + struct GL_HIF_INFO *prHifInfo = prUsbReq->prHifInfo; + struct GLUE_INFO *prGlueInfo = prHifInfo->prGlueInfo; + + glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxDataCompleteQ, prUsbReq, &prHifInfo->rTxDataQLock, FALSE); + +#if CFG_USB_TX_HANDLE_IN_HIF_THREAD + kalSetIntEvent(prGlueInfo); +#else + /*tasklet_hi_schedule(&prGlueInfo->rTxCompleteTask);*/ + tasklet_schedule(&prGlueInfo->rTxCompleteTask); +#endif +} + +void halTxUSBProcessMsduDone(IN struct GLUE_INFO *prGlueInfo, struct USB_REQ *prUsbReq) +{ + uint8_t ucTc; + struct QUE rFreeQueue; + struct QUE *prFreeQueue; + struct urb *urb = prUsbReq->prUrb; + uint32_t u4SentDataSize; + + ucTc = *((uint8_t *)&prUsbReq->prPriv) & TC_MASK; + + prFreeQueue = &rFreeQueue; + QUEUE_INITIALIZE(prFreeQueue); + QUEUE_MOVE_ALL((prFreeQueue), (&(prUsbReq->rSendingDataMsduInfoList))); + if (g_pfTxDataDoneCb) + g_pfTxDataDoneCb(prGlueInfo, prFreeQueue); + + u4SentDataSize = urb->actual_length - LEN_USB_UDMA_TX_TERMINATOR; + nicTxReleaseResource_PSE(prGlueInfo->prAdapter, ucTc, + nicTxGetPageCount(prGlueInfo->prAdapter, u4SentDataSize, TRUE), TRUE); +} + +void halTxUSBProcessDataComplete(IN struct ADAPTER *prAdapter, struct USB_REQ *prUsbReq) +{ + uint8_t ucTc; + u_int8_t fgFfa; + struct urb *urb = prUsbReq->prUrb; + struct GL_HIF_INFO *prHifInfo = prUsbReq->prHifInfo; +#if CFG_USB_TX_AGG + struct BUF_CTRL *prBufCtrl = prUsbReq->prBufCtrl; +#endif + unsigned long flags; + + ucTc = *((uint8_t *)&prUsbReq->prPriv) & TC_MASK; + fgFfa = *((uint8_t *)&prUsbReq->prPriv) & FFA_MASK; + + if (urb->status != 0) { + DBGLOG(TX, ERROR, "[%s] send DATA fail (status = %d)\n", __func__, urb->status); + /* TODO: handle error */ + } + + halTxUSBProcessMsduDone(prAdapter->prGlueInfo, prUsbReq); + + spin_lock_irqsave(&prHifInfo->rTxDataQLock, flags); +#if CFG_USB_TX_AGG + prBufCtrl->u4WrIdx = 0; + + if ((fgFfa == FALSE) || list_empty(&prHifInfo->rTxDataFreeQ[ucTc])) + list_add_tail(&prUsbReq->list, &prHifInfo->rTxDataFreeQ[ucTc]); + else + list_add_tail(&prUsbReq->list, &prHifInfo->rTxDataFfaQ); + + if (usb_anchor_empty(&prHifInfo->rTxDataAnchor[ucTc])) { + prUsbReq = list_entry(prHifInfo->rTxDataFreeQ[ucTc].next, struct USB_REQ, list); + prBufCtrl = prUsbReq->prBufCtrl; + + if (prBufCtrl->u4WrIdx != 0) + halTxUSBSendAggData(prHifInfo, ucTc, prUsbReq); /* TODO */ + } +#else + list_add_tail(&prUsbReq->list, &prHifInfo->rTxDataFreeQ); +#endif + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, flags); + + if (!HAL_IS_TX_DIRECT(prAdapter)) { + if (kalGetTxPendingCmdCount(prAdapter->prGlueInfo) > 0 || wlanGetTxPendingFrameCount(prAdapter) > 0) + kalSetEvent(prAdapter->prGlueInfo); + kalSetTxEvent2Hif(prAdapter->prGlueInfo); + } +} + +uint32_t halRxUSBEnqueueRFB( + IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, + IN uint32_t u4Length, + IN uint32_t u4MinRfbCnt, + IN struct list_head *prCompleteQ) +{ + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct mt66xx_chip_info *prChipInfo; + struct RX_CTRL *prRxCtrl = &prAdapter->rRxCtrl; + struct SW_RFB *prSwRfb = (struct SW_RFB *) NULL; + void *prRxStatus; + uint32_t u4RemainCount; + uint16_t u2RxByteCount; + uint8_t *pucRxFrame; + uint32_t u4EnqCnt = 0; + struct BUS_INFO *prBusInfo; +#if CFG_TCP_IP_CHKSUM_OFFLOAD + uint32_t *pu4HwAppendDW; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + struct RX_DESC_OPS_T *prRxDescOps; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + prBusInfo = prChipInfo->bus_info; + prRxDescOps = prChipInfo->prRxDescOps; + ASSERT(prRxDescOps->nic_rxd_get_rx_byte_count); + ASSERT(prRxDescOps->nic_rxd_get_pkt_type); + + pucRxFrame = pucBuf; + u4RemainCount = u4Length; + while (u4RemainCount > 4) { + /* + * For different align support. + * Ex. We need to do 8byte align for 7915u. + */ + if (prBusInfo->asicUsbRxByteCount) + u2RxByteCount = prBusInfo->asicUsbRxByteCount(prAdapter, + prBusInfo, pucRxFrame); + else { + u2RxByteCount = + prRxDescOps->nic_rxd_get_rx_byte_count( + pucRxFrame); + u2RxByteCount = ALIGN_4(u2RxByteCount) + + LEN_USB_RX_PADDING_CSO; + } + + if (u2RxByteCount <= CFG_RX_MAX_PKT_SIZE) { + prSwRfb = NULL; + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + if (prRxCtrl->rFreeSwRfbList.u4NumElem > u4MinRfbCnt) + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, struct SW_RFB *); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + if (!prSwRfb) + return u4Length - u4RemainCount; + + kalMemCopy(prSwRfb->pucRecvBuff, pucRxFrame, u2RxByteCount); + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + prSwRfb->ucPacketType = + prRxDescOps->nic_rxd_get_pkt_type(prRxStatus); + /* DBGLOG(RX, TRACE, ("ucPacketType = %d\n", prSwRfb->ucPacketType)); */ +#if CFG_TCP_IP_CHKSUM_OFFLOAD + pu4HwAppendDW = (uint32_t *) prRxStatus; + pu4HwAppendDW += + (ALIGN_4(u2RxByteCount - LEN_USB_RX_PADDING_CSO) + >> 2); + prSwRfb->u4TcpUdpIpCksStatus = *pu4HwAppendDW; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + if (HAL_IS_RX_DIRECT(prAdapter)) { + switch (prSwRfb->ucPacketType) { + case RX_PKT_TYPE_RX_DATA: + spin_lock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_RX_DIRECT]); + if (HAL_MON_EN(prAdapter)) + nicRxProcessMonitorPacket( + prAdapter, prSwRfb); + else + nicRxProcessDataPacket( + prAdapter, prSwRfb); + spin_unlock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_RX_DIRECT]); + break; + default: + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_INSERT_TAIL(&prRxCtrl->rReceivedRfbList, &prSwRfb->rQueEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + u4EnqCnt++; + break; + } + } else { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_INSERT_TAIL(&prRxCtrl->rReceivedRfbList, &prSwRfb->rQueEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + u4EnqCnt++; + } + RX_INC_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT); + } else { + DBGLOG(RX, WARN, "Rx byte count:%u exceeds SW_RFB max length:%u\n!", + u2RxByteCount, CFG_RX_MAX_PKT_SIZE); + DBGLOG_MEM32(RX, WARN, pucRxFrame, + prChipInfo->rxd_size); + break; + } + + u4RemainCount -= u2RxByteCount; + pucRxFrame += u2RxByteCount; + } + + if (u4EnqCnt) { + set_bit(GLUE_FLAG_RX_BIT, &(prGlueInfo->ulFlag)); + wake_up_interruptible(&(prGlueInfo->waitq)); + } + + return u4Length; +} + +uint32_t halRxUSBReceiveEvent(IN struct ADAPTER *prAdapter, IN u_int8_t fgFillUrb) +{ + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + struct USB_REQ *prUsbReq; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + int ret; + + while (1) { + prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, &prHifInfo->rRxEventQLock); + if (prUsbReq == NULL) + return WLAN_STATUS_RESOURCES; + + usb_anchor_urb(prUsbReq->prUrb, &prHifInfo->rRxEventAnchor); + + prUsbReq->prBufCtrl->u4ReadSize = 0; + if (prHifInfo->eEventEpType == EVENT_EP_TYPE_INTR && fgFillUrb) { + usb_fill_int_urb(prUsbReq->prUrb, + prHifInfo->udev, + usb_rcvintpipe(prHifInfo->udev, + USB_EVENT_EP_IN), + (void *)prUsbReq->prBufCtrl->pucBuf, + prUsbReq->prBufCtrl->u4BufSize, + halRxUSBReceiveEventComplete, + (void *)prUsbReq, + 1); + } else if (prHifInfo->eEventEpType == EVENT_EP_TYPE_BULK) { + usb_fill_bulk_urb(prUsbReq->prUrb, + prHifInfo->udev, + usb_rcvbulkpipe(prHifInfo->udev, + USB_EVENT_EP_IN), + (void *)prUsbReq->prBufCtrl->pucBuf, + prUsbReq->prBufCtrl->u4BufSize, + halRxUSBReceiveEventComplete, + (void *)prUsbReq); + } + ret = glUsbSubmitUrb(prHifInfo, prUsbReq->prUrb, + SUBMIT_TYPE_RX_EVENT); + if (ret) { + DBGLOG(HAL, ERROR, + "glUsbSubmitUrb() reports error (%d) [%s] (EP%d IN)\n", + ret, __func__, (USB_EVENT_EP_IN & 0x0F)); + usb_unanchor_urb(prUsbReq->prUrb); + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, + &prHifInfo->rRxEventQLock, FALSE); + break; + } + } + + return u4Status; +} + +void halRxUSBReceiveEventComplete(struct urb *urb) +{ + struct USB_REQ *prUsbReq = urb->context; + struct GL_HIF_INFO *prHifInfo = prUsbReq->prHifInfo; + struct GLUE_INFO *prGlueInfo = prHifInfo->prGlueInfo; + + if (!(prHifInfo->state == USB_STATE_LINK_UP || + prHifInfo->state == USB_STATE_READY || + prHifInfo->state == USB_STATE_PRE_RESUME || + prHifInfo->state == USB_STATE_PRE_SUSPEND_START)) { + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); + return; + } + + /* Hif power off wifi, drop rx packets and continue polling RX packets until RX path empty */ + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); + halRxUSBReceiveEvent(prGlueInfo->prAdapter, FALSE); + return; + } + + if (urb->status == -ESHUTDOWN || urb->status == -ENOENT) { + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); + DBGLOG(RX, ERROR, "USB device shutdown skip Rx [%s]\n", __func__); + return; + } + +#if CFG_USB_RX_HANDLE_IN_HIF_THREAD + DBGLOG(RX, TRACE, "[%s] Rx URB[0x%p] Len[%u] Sts[%u]\n", __func__, urb, urb->actual_length, urb->status); + + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventCompleteQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); + + kalSetIntEvent(prGlueInfo); +#else + if (urb->status == 0) { + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventCompleteQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); + + /*tasklet_hi_schedule(&prGlueInfo->rRxTask);*/ + tasklet_schedule(&prGlueInfo->rRxTask); + } else { + DBGLOG(RX, ERROR, "[%s] receive EVENT fail (status = %d)\n", __func__, urb->status); + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); + + halRxUSBReceiveEvent(prGlueInfo->prAdapter, FALSE); + } +#endif +} + +uint32_t halRxUSBReceiveData(IN struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + struct USB_REQ *prUsbReq; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + int ret; + + while (1) { + prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, &prHifInfo->rRxDataQLock); + if (prUsbReq == NULL) + return WLAN_STATUS_RESOURCES; + + usb_anchor_urb(prUsbReq->prUrb, &prHifInfo->rRxDataAnchor); + + prUsbReq->prBufCtrl->u4ReadSize = 0; + usb_fill_bulk_urb(prUsbReq->prUrb, + prHifInfo->udev, + usb_rcvbulkpipe(prHifInfo->udev, USB_DATA_EP_IN), + (void *)prUsbReq->prBufCtrl->pucBuf, + prUsbReq->prBufCtrl->u4BufSize, halRxUSBReceiveDataComplete, (void *)prUsbReq); + ret = glUsbSubmitUrb(prHifInfo, prUsbReq->prUrb, + SUBMIT_TYPE_RX_DATA); + if (ret) { + DBGLOG(HAL, ERROR, + "glUsbSubmitUrb() reports error (%d) [%s] (EP%d IN)\n", + ret, __func__, (USB_EVENT_EP_IN & 0x0F)); + usb_unanchor_urb(prUsbReq->prUrb); + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE); + break; + } + } + + return u4Status; +} + +void halRxUSBReceiveDataComplete(struct urb *urb) +{ + struct USB_REQ *prUsbReq = urb->context; + struct GL_HIF_INFO *prHifInfo = prUsbReq->prHifInfo; + struct GLUE_INFO *prGlueInfo = prHifInfo->prGlueInfo; + + if (!(prHifInfo->state == USB_STATE_LINK_UP || + prHifInfo->state == USB_STATE_READY)) { + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE); + return; + } + + /* Hif power off wifi, drop rx packets and continue polling RX packets until RX path empty */ + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE); + halRxUSBReceiveData(prGlueInfo->prAdapter); + return; + } + + if (urb->status == -ESHUTDOWN || urb->status == -ENOENT) { + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE); + DBGLOG(RX, ERROR, "USB device shutdown skip Rx [%s]\n", __func__); + return; + } + +#if CFG_USB_RX_HANDLE_IN_HIF_THREAD + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataCompleteQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE); + + kalSetIntEvent(prGlueInfo); +#else + if (urb->status == 0) { + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataCompleteQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE); + + /*tasklet_hi_schedule(&prGlueInfo->rRxTask);*/ + tasklet_schedule(&prGlueInfo->rRxTask); + } else { + DBGLOG(RX, ERROR, "[%s] receive DATA fail (status = %d)\n", __func__, urb->status); + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE); + + halRxUSBReceiveData(prGlueInfo->prAdapter); + } +#endif +} + +void halRxUSBProcessEventDataComplete(IN struct ADAPTER *prAdapter, + struct list_head *prCompleteQ, struct list_head *prFreeQ, uint32_t u4MinRfbCnt) +{ + struct USB_REQ *prUsbReq; + struct urb *prUrb; + struct BUF_CTRL *prBufCtrl; + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + uint8_t *pucBufAddr; + uint32_t u4BufLen; + static u_int8_t s_fgOutOfSwRfb = FALSE; + static uint32_t s_u4OutOfSwRfbPrintLimit; + + /* lock with rRxDataQLock if processing queue is data queue */ + /* and vice versa */ + spinlock_t *prLock = + (prCompleteQ == &prHifInfo->rRxDataCompleteQ) ? + (&prHifInfo->rRxDataQLock) : + (&prHifInfo->rRxEventQLock); + + /* Process complete event/data */ + prUsbReq = glUsbDequeueReq(prHifInfo, prCompleteQ, prLock); + while (prUsbReq) { + prUrb = prUsbReq->prUrb; + prBufCtrl = prUsbReq->prBufCtrl; + + DBGLOG(RX, LOUD, "[%s] Rx URB[0x%p] Len[%u] Sts[%u]\n", __func__, + prUrb, prUrb->actual_length, prUrb->status); + + if (prUrb->status != 0) { + DBGLOG(RX, ERROR, "[%s] receive EVENT/DATA fail (status = %d)\n", __func__, prUrb->status); + + glUsbEnqueueReq(prHifInfo, prFreeQ, prUsbReq, prLock, + FALSE); + prUsbReq = glUsbDequeueReq(prHifInfo, prCompleteQ, + prLock); + continue; + } + + pucBufAddr = prBufCtrl->pucBuf + prBufCtrl->u4ReadSize; + u4BufLen = prUrb->actual_length - prBufCtrl->u4ReadSize; + + prBufCtrl->u4ReadSize += halRxUSBEnqueueRFB( + prAdapter, + pucBufAddr, + u4BufLen, + u4MinRfbCnt, + prCompleteQ); + + if (unlikely(prUrb->actual_length - prBufCtrl->u4ReadSize > 4)) { + if (s_fgOutOfSwRfb == FALSE) { + if ((long)jiffies - (long)s_u4OutOfSwRfbPrintLimit > 0) { + DBGLOG(RX, WARN, "Out of SwRfb!\n"); + s_u4OutOfSwRfbPrintLimit = jiffies + MSEC_TO_JIFFIES(SW_RFB_LOG_LIMIT_MS); + } + s_fgOutOfSwRfb = TRUE; + } + glUsbEnqueueReq(prHifInfo, prCompleteQ, prUsbReq, + prLock, TRUE); + + set_bit(GLUE_FLAG_RX_BIT, &prGlueInfo->ulFlag); + wake_up_interruptible(&prGlueInfo->waitq); + + schedule_delayed_work(&prGlueInfo->rRxPktDeAggWork, MSEC_TO_JIFFIES(SW_RFB_RECHECK_MS)); + break; + } + + if (unlikely(s_fgOutOfSwRfb == TRUE)) + s_fgOutOfSwRfb = FALSE; + + glUsbEnqueueReq(prHifInfo, prFreeQ, prUsbReq, prLock, FALSE); + prUsbReq = glUsbDequeueReq(prHifInfo, prCompleteQ, prLock); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief enable global interrupt +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void halEnableInterrupt(IN struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo; + struct GL_HIF_INFO *prHifInfo; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + prHifInfo = &prGlueInfo->rHifInfo; + + halRxUSBReceiveData(prAdapter); + if (prHifInfo->eEventEpType != EVENT_EP_TYPE_DATA_EP) + halRxUSBReceiveEvent(prAdapter, TRUE); + + glUdmaRxAggEnable(prGlueInfo, TRUE); +} /* end of halEnableInterrupt() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief disable global interrupt +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void halDisableInterrupt(IN struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo; + struct GL_HIF_INFO *prHifInfo; + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + prHifInfo = &prGlueInfo->rHifInfo; + + usb_kill_anchored_urbs(&prHifInfo->rRxDataAnchor); + usb_kill_anchored_urbs(&prHifInfo->rRxEventAnchor); + + glUdmaRxAggEnable(prGlueInfo, FALSE); + prAdapter->fgIsIntEnable = FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to process the POWER OFF procedure. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t halSetDriverOwn(IN struct ADAPTER *prAdapter) +{ + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to process the POWER ON procedure. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void halSetFWOwn(IN struct ADAPTER *prAdapter, IN u_int8_t fgEnableGlobalInt) +{ +} + +void halWakeUpWiFi(IN struct ADAPTER *prAdapter) +{ + u_int8_t fgResult; + uint8_t ucCount = 0; + + DBGLOG(INIT, INFO, "Power on Wi-Fi....\n"); + + HAL_WIFI_FUNC_READY_CHECK(prAdapter, WIFI_FUNC_INIT_DONE, &fgResult); + + while (!fgResult) { + HAL_WIFI_FUNC_POWER_ON(prAdapter); + kalMdelay(50); + HAL_WIFI_FUNC_READY_CHECK(prAdapter, WIFI_FUNC_INIT_DONE, &fgResult); + + ucCount++; + + if (ucCount >= 5) { + DBGLOG(INIT, WARN, "Power on failed!!!\n"); + break; + } + } + + prAdapter->fgIsFwOwn = FALSE; +} + +void halEnableFWDownload(IN struct ADAPTER *prAdapter, IN u_int8_t fgEnable) +{ +#if (CFG_UMAC_GENERATION >= 0x20) + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + + prChipInfo = prAdapter->chip_info; + if (prChipInfo->asicEnableFWDownload) { + prChipInfo->asicEnableFWDownload(prAdapter, fgEnable); + } else { + uint32_t u4Value = 0; + + HAL_MCR_RD(prAdapter, UDMA_TX_QSEL, &u4Value); + + if (fgEnable) + u4Value |= FW_DL_EN; + else + u4Value &= ~FW_DL_EN; + + HAL_MCR_WR(prAdapter, UDMA_TX_QSEL, u4Value); + } +#endif +} + +void halDevInit(IN struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo; + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + + glUdmaRxAggEnable(prGlueInfo, FALSE); + glUdmaTxRxEnable(prGlueInfo, TRUE); +} + +u_int8_t halTxIsDataBufEnough(IN struct ADAPTER *prAdapter, IN struct MSDU_INFO *prMsduInfo) +{ + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; +#if CFG_USB_TX_AGG + struct USB_REQ *prUsbReq; + struct BUF_CTRL *prBufCtrl; +#endif + uint8_t ucTc; + struct sk_buff *skb; + uint32_t u4Length; + struct mt66xx_chip_info *prChipInfo; + + unsigned long flags; + + prChipInfo = prAdapter->chip_info; + skb = (struct sk_buff *)prMsduInfo->prPacket; + u4Length = skb->len; + u4Length += prChipInfo->u2HifTxdSize; + ucTc = USB_TRANS_MSDU_TC(prMsduInfo); + + spin_lock_irqsave(&prHifInfo->rTxDataQLock, flags); + +#if CFG_USB_TX_AGG + if (list_empty(&prHifInfo->rTxDataFreeQ[ucTc])) { + if (glUsbBorrowFfaReq(prHifInfo, ucTc) == FALSE) { + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, flags); + return FALSE; + } + } + + prUsbReq = list_entry(prHifInfo->rTxDataFreeQ[ucTc].next, struct USB_REQ, list); + prBufCtrl = prUsbReq->prBufCtrl; + + if (prHifInfo->rTxDataFreeQ[ucTc].next->next == &prHifInfo->rTxDataFreeQ[ucTc]) { + /* length of rTxDataFreeQ equals 1 */ + if (prBufCtrl->u4WrIdx + ALIGN_4(u4Length) > + prBufCtrl->u4BufSize - prHifInfo->u4AggRsvSize[ucTc] - LEN_USB_UDMA_TX_TERMINATOR) { + /* Buffer is not enough */ + if (glUsbBorrowFfaReq(prHifInfo, ucTc) == FALSE) { + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, + flags); + return FALSE; + } + } + } + prHifInfo->u4AggRsvSize[ucTc] += ALIGN_4(u4Length); +#else + if (list_empty(&prHifInfo->rTxDataFreeQ)) { + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, flags); + + return FALSE; + } +#endif + + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, flags); + return TRUE; +} + +uint8_t halTxRingDataSelect(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + return 0; +} + +void halUpdateTxMaxQuota(IN struct ADAPTER *prAdapter) +{ +} + +void halProcessTxInterrupt(IN struct ADAPTER *prAdapter) +{ +#if CFG_USB_TX_HANDLE_IN_HIF_THREAD + struct USB_REQ *prUsbReq; + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + /* Process complete Tx cmd */ + prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxCmdCompleteQ, &prHifInfo->rTxCmdQLock); + while (prUsbReq) { + halTxUSBProcessCmdComplete(prAdapter, prUsbReq); + prUsbReq = glUsbDequeueReq(prHifInfo, + &prHifInfo->rTxCmdCompleteQ, + &prHifInfo->rTxCmdQLock); + } + + /* Process complete Tx data */ + prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxDataCompleteQ, + &prHifInfo->rTxDataQLock); + while (prUsbReq) { + halTxUSBProcessDataComplete(prAdapter, prUsbReq); + prUsbReq = glUsbDequeueReq(prHifInfo, + &prHifInfo->rTxDataCompleteQ, + &prHifInfo->rTxDataQLock); + } +#endif +} + +bool halHifSwInfoInit(IN struct ADAPTER *prAdapter) +{ + return true; +} + +void halRxProcessMsduReport(IN struct ADAPTER *prAdapter, IN OUT struct SW_RFB *prSwRfb) +{ + +} + +uint32_t halTxGetPageCount(IN struct ADAPTER *prAdapter, IN uint32_t u4FrameLength, IN u_int8_t fgIncludeDesc) +{ +#if CFG_USB_TX_AGG + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + uint32_t u4RequiredBufferSize; + uint32_t u4PageCount; + uint32_t u4TxHeadRoomSize = NIC_TX_DESC_AND_PADDING_LENGTH + prChipInfo->txd_append_size; + + /* Frame Buffer + * |<--Tx Descriptor-->|<--Tx descriptor padding-->| + * <--802.3/802.11 Header-->|<--Header padding-->|<--Payload-->| + */ + + if (fgIncludeDesc) + u4RequiredBufferSize = u4FrameLength; + else + u4RequiredBufferSize = u4TxHeadRoomSize + u4FrameLength; + + u4RequiredBufferSize = ALIGN_4(u4RequiredBufferSize); + + if (NIC_TX_PAGE_SIZE_IS_POWER_OF_2) + u4PageCount = (u4RequiredBufferSize + (NIC_TX_PAGE_SIZE - 1)) >> NIC_TX_PAGE_SIZE_IN_POWER_OF_2; + else + u4PageCount = (u4RequiredBufferSize + (NIC_TX_PAGE_SIZE - 1)) / NIC_TX_PAGE_SIZE; + + return u4PageCount; +#else + return 1; +#endif +} + +uint32_t halTxPollingResource(IN struct ADAPTER *prAdapter, IN uint8_t ucTC) +{ + return WLAN_STATUS_SUCCESS; +} + +void halSerHifReset(IN struct ADAPTER *prAdapter) +{ + uint32_t i; + + /** + * usb_reset_endpoint - Reset an endpoint's state. + * @dev: the device whose endpoint is to be reset + * @epaddr: the endpoint's address. Endpoint number for output, + * endpoint number + USB_DIR_IN for input + * + * Resets any host-side endpoint state such as the toggle bit, + * sequence number or current window. + * + * void usb_reset_endpoint(struct usb_device *dev, unsigned int epaddr); + */ + + /* SER new flow: just flush out ep out fifo, + * not to reset ep out endpoint + */ +#if 0 + /* reset ALL BULK OUT endpoints */ + for (i = USB_DATA_BULK_OUT_EP4; i <= USB_DATA_BULK_OUT_EP9; i++) + usb_reset_endpoint(prAdapter->prGlueInfo->rHifInfo.udev, i); +#endif + /* reset ALL BULK IN endpoints */ + for (i = USB_DATA_BULK_IN_EP4; i <= USB_DATA_BULK_IN_EP5; i++) + usb_reset_endpoint(prAdapter->prGlueInfo->rHifInfo.udev, + i | USB_DIR_IN); +} + +void halProcessRxInterrupt(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + /* Process complete data */ + halRxUSBProcessEventDataComplete(prAdapter, &prHifInfo->rRxDataCompleteQ, + &prHifInfo->rRxDataFreeQ, USB_RX_DATA_RFB_RSV_CNT); + halRxUSBReceiveData(prAdapter); + + if (prHifInfo->eEventEpType != EVENT_EP_TYPE_DATA_EP) { + /* Process complete event */ + halRxUSBProcessEventDataComplete(prAdapter, &prHifInfo->rRxEventCompleteQ, + &prHifInfo->rRxEventFreeQ, USB_RX_EVENT_RFB_RSV_CNT); + halRxUSBReceiveEvent(prAdapter, FALSE); + } +} + +uint32_t halDumpHifStatus(IN struct ADAPTER *prAdapter, IN uint8_t *pucBuf, IN uint32_t u4Max) +{ + uint32_t u4CpuIdx, u4DmaIdx, u4Int, u4GloCfg, u4Reg; + uint32_t u4Len = 0; + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + uint8_t pBuffer[512] = {0}; + + HAL_MCR_RD(prAdapter, 0x820b0118, &u4CpuIdx); + HAL_MCR_RD(prAdapter, 0x820b011c, &u4DmaIdx); + HAL_MCR_RD(prAdapter, 0x820b0220, &u4Int); + HAL_MCR_RD(prAdapter, 0x820b0204, &u4GloCfg); + + LOGBUF(pucBuf, u4Max, u4Len, "\n"); + LOGBUF(pucBuf, u4Max, u4Len, "PDMA1R1 CPU[%u] DMA[%u] INT[0x%08x] CFG[0x%08x]\n", u4CpuIdx, + u4DmaIdx, u4Int, u4GloCfg); + + HAL_MCR_RD(prAdapter, UDMA_WLCFG_0, &u4Reg); + + LOGBUF(pucBuf, u4Max, u4Len, "UDMA WLCFG[0x%08x]\n", u4Reg); + + LOGBUF(pucBuf, u4Max, u4Len, "\n"); + LOGBUF(pucBuf, u4Max, u4Len, "VenderID: %04x\n", + glGetUsbDeviceVendorId(prGlueInfo->rHifInfo.udev)); + LOGBUF(pucBuf, u4Max, u4Len, "ProductID: %04x\n", + glGetUsbDeviceProductId(prGlueInfo->rHifInfo.udev)); + + glGetUsbDeviceManufacturerName(prGlueInfo->rHifInfo.udev, pBuffer, + sizeof(pBuffer)); + LOGBUF(pucBuf, u4Max, u4Len, "Manufacturer: %s\n", + pBuffer); + + glGetUsbDeviceProductName(prGlueInfo->rHifInfo.udev, pBuffer, + sizeof(pBuffer)); + LOGBUF(pucBuf, u4Max, u4Len, "Product: %s\n", pBuffer); + + glGetUsbDeviceSerialNumber(prGlueInfo->rHifInfo.udev, pBuffer, + sizeof(pBuffer)); + LOGBUF(pucBuf, u4Max, u4Len, "SerialNumber: %s\n", + pBuffer); + + return u4Len; +} + +void halGetCompleteStatus(IN struct ADAPTER *prAdapter, OUT uint32_t *pu4IntStatus) +{ +#if CFG_USB_RX_HANDLE_IN_HIF_THREAD || CFG_USB_TX_HANDLE_IN_HIF_THREAD + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; +#endif + + *pu4IntStatus = 0; + +#if CFG_USB_RX_HANDLE_IN_HIF_THREAD + if (!list_empty(&prHifInfo->rRxDataCompleteQ) || !list_empty(&prHifInfo->rRxEventCompleteQ)) + *pu4IntStatus |= WHISR_RX0_DONE_INT; +#endif + +#if CFG_USB_TX_HANDLE_IN_HIF_THREAD + if (!list_empty(&prHifInfo->rTxDataCompleteQ) || !list_empty(&prHifInfo->rTxCmdCompleteQ)) + *pu4IntStatus |= WHISR_TX_DONE_INT; +#endif +} + +u_int8_t halIsPendingRx(IN struct ADAPTER *prAdapter) +{ +#if CFG_USB_RX_HANDLE_IN_HIF_THREAD + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + if (!list_empty(&prHifInfo->rRxDataCompleteQ) || !list_empty(&prHifInfo->rRxEventCompleteQ)) + return TRUE; + else + return FALSE; +#else + return FALSE; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Send HIF_CTRL command to inform FW stop send packet/event to host +* suspend = 1 +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (void) +*/ +/*----------------------------------------------------------------------------*/ +void halUSBPreSuspendCmd(IN struct ADAPTER *prAdapter) +{ + struct CMD_HIF_CTRL rCmdHifCtrl; + uint32_t rStatus; + + rCmdHifCtrl.ucHifType = ENUM_HIF_TYPE_USB; + rCmdHifCtrl.ucHifDirection = ENUM_HIF_TX; + rCmdHifCtrl.ucHifStop = 1; + rCmdHifCtrl.ucHifSuspend = 1; + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_HIF_CTRL, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct CMD_HIF_CTRL), /* u4SetQueryInfoLen */ + (uint8_t *)&rCmdHifCtrl, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Send HIF_CTRL command to inform FW allow send packet/event to host +* suspend = 0 +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (void) +*/ +/*----------------------------------------------------------------------------*/ +void halUSBPreResumeCmd(IN struct ADAPTER *prAdapter) +{ + struct CMD_HIF_CTRL rCmdHifCtrl; + uint32_t rStatus; + + rCmdHifCtrl.ucHifType = ENUM_HIF_TYPE_USB; + rCmdHifCtrl.ucHifDirection = ENUM_HIF_TX; + rCmdHifCtrl.ucHifStop = 0; + rCmdHifCtrl.ucHifSuspend = 0; + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_HIF_CTRL, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* nicEventHifCtrl */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct CMD_HIF_CTRL), + (uint8_t *)&rCmdHifCtrl, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); +} + +void halUSBPreSuspendDone(IN struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + unsigned long flags; + struct GL_HIF_INFO *prHifInfo; + + ASSERT(prAdapter); + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + spin_lock_irqsave(&prHifInfo->rStateLock, flags); + + if (prHifInfo->state == USB_STATE_LINK_UP + || prHifInfo->state == USB_STATE_PRE_SUSPEND_START) + prHifInfo->state = USB_STATE_PRE_SUSPEND_DONE; + else + DBGLOG(HAL, ERROR, "Previous USB state (%d)!\n", + prHifInfo->state); + + spin_unlock_irqrestore(&prHifInfo->rStateLock, flags); +} + +void halUSBPreSuspendTimeout(IN struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo) +{ + unsigned long flags; + struct GL_HIF_INFO *prHifInfo; + + ASSERT(prAdapter); + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + spin_lock_irqsave(&prHifInfo->rStateLock, flags); + + if (prHifInfo->state == USB_STATE_LINK_UP + || prHifInfo->state == USB_STATE_PRE_SUSPEND_START) + prHifInfo->state = USB_STATE_PRE_SUSPEND_FAIL; + else + DBGLOG(HAL, ERROR, "Previous USB state (%d)!\n", + prHifInfo->state); + + spin_unlock_irqrestore(&prHifInfo->rStateLock, flags); +} + +uint32_t halGetValidCoalescingBufSize(IN struct ADAPTER *prAdapter) +{ + uint32_t u4BufSize; + + if (HIF_TX_COALESCING_BUFFER_SIZE > HIF_RX_COALESCING_BUFFER_SIZE) + u4BufSize = HIF_TX_COALESCING_BUFFER_SIZE; + else + u4BufSize = HIF_RX_COALESCING_BUFFER_SIZE; + + return u4BufSize; +} + +uint32_t halAllocateIOBuffer(IN struct ADAPTER *prAdapter) +{ + return WLAN_STATUS_SUCCESS; +} + +uint32_t halReleaseIOBuffer(IN struct ADAPTER *prAdapter) +{ + return WLAN_STATUS_SUCCESS; +} + +void halProcessAbnormalInterrupt(IN struct ADAPTER *prAdapter) +{ + +} + +void halProcessSoftwareInterrupt(IN struct ADAPTER *prAdapter) +{ + +} + +void halDeAggRxPktWorker(struct work_struct *work) +{ + struct GLUE_INFO *prGlueInfo = ENTRY_OF(work, struct GLUE_INFO, rRxPktDeAggWork); + + /*tasklet_hi_schedule(&prGlueInfo->rRxTask);*/ + tasklet_schedule(&prGlueInfo->rRxTask); +} + +void halRxTasklet(unsigned long data) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)data; + + halProcessRxInterrupt(prGlueInfo->prAdapter); +} + +void halTxCompleteTasklet(unsigned long data) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)data; + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + struct USB_REQ *prUsbReq; + + /* Process complete Tx data */ + prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxDataCompleteQ, &prHifInfo->rTxDataQLock); + while (prUsbReq) { + halTxUSBProcessDataComplete(prGlueInfo->prAdapter, prUsbReq); + prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxDataCompleteQ, &prHifInfo->rTxDataQLock); + } +} + +/* Hif power off wifi */ +uint32_t halHifPowerOffWifi(IN struct ADAPTER *prAdapter) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + DBGLOG(INIT, INFO, "Power off Wi-Fi!\n"); + + /* Power off Wi-Fi */ + wlanSendNicPowerCtrlCmd(prAdapter, TRUE); + + rStatus = wlanCheckWifiFunc(prAdapter, FALSE); + + glUsbSetState(&prAdapter->prGlueInfo->rHifInfo, USB_STATE_WIFI_OFF); + + nicDisableInterrupt(prAdapter); + + wlanClearPendingInterrupt(prAdapter); + + halTxCancelAllSending(prAdapter); + + return rStatus; +} + +void halPrintHifDbgInfo(IN struct ADAPTER *prAdapter) +{ + +} + +u_int8_t halIsTxResourceControlEn(IN struct ADAPTER *prAdapter) +{ + return FALSE; +} + +void halTxResourceResetHwTQCounter(IN struct ADAPTER *prAdapter) +{ +} + +uint32_t halGetHifTxPageSize(IN struct ADAPTER *prAdapter) +{ + return HIF_TX_PAGE_SIZE; +} + +void halSerSyncTimerHandler(IN struct ADAPTER *prAdapter) +{ + static u_int8_t ucSerState = ERR_RECOV_STOP_IDLE; + uint32_t u4SerAction; + struct mt66xx_chip_info *prChipInfo; + + if (prAdapter->prGlueInfo->rHifInfo.state == USB_STATE_SUSPEND) + return; + + prChipInfo = prAdapter->chip_info; + + /* get MCU SER event */ + kalDevRegRead(prAdapter->prGlueInfo, prChipInfo->u4SerUsbMcuEventAddr, + &u4SerAction); + + if (u4SerAction) { + DBGLOG(NIC, INFO, "%s u4SerAction=0x%08X\n", __func__, + u4SerAction); + + /* clear MCU SER event */ + kalDevRegWrite(prAdapter->prGlueInfo, + prChipInfo->u4SerUsbMcuEventAddr, 0); + } + + switch (ucSerState) { + case ERR_RECOV_STOP_IDLE: + if (u4SerAction == ERROR_DETECT_STOP_PDMA) { + if (prChipInfo->asicDumpSerDummyCR) + prChipInfo->asicDumpSerDummyCR(prAdapter); + + DBGLOG(HAL, INFO, + "SER(E) Host stop HIF tx/rx operation\n"); + + /* change SER FSM to SER_STOP_HOST_TX_RX */ + nicSerStopTxRx(prAdapter); + /* stop TX BULK OUT URB */ + halTxCancelAllSending(prAdapter); + /* stop RX BULK IN URB */ + halDisableInterrupt(prAdapter); + + DBGLOG(HAL, INFO, + "SER(F) Host ACK HIF tx/rx stop operation done\n"); + + /* Send Host stops TX/RX done response to mcu */ + kalDevRegWrite(prAdapter->prGlueInfo, + prChipInfo->u4SerUsbHostAckAddr, + MCU_INT_PDMA0_STOP_DONE); + ucSerState = ERR_RECOV_STOP_PDMA0; + } else { + /* do nothing */ + } + break; + + case ERR_RECOV_STOP_PDMA0: + if (u4SerAction == ERROR_DETECT_RESET_DONE) { + DBGLOG(HAL, INFO, "SER(L) Host re-initialize WFDMA\n"); + DBGLOG(HAL, INFO, "SER(M) Host enable WFDMA\n"); + if (prChipInfo->asicUsbInit) + prChipInfo->asicUsbInit(prAdapter, prChipInfo); + + DBGLOG(HAL, INFO, + "SER(N) Host ACK WFDMA init done\n"); + /* Send Host stops TX/RX done response to mcu */ + kalDevRegWrite(prAdapter->prGlueInfo, + prChipInfo->u4SerUsbHostAckAddr, + MCU_INT_PDMA0_INIT_DONE); + + ucSerState = ERR_RECOV_RESET_PDMA0; + } else { + /* do nothing */ + } + break; + case ERR_RECOV_RESET_PDMA0: + if (u4SerAction == ERROR_DETECT_RECOVERY_DONE) { + DBGLOG(HAL, INFO, + "SER(Q) Host ACK MCU SER handle done\n"); + /* Send Host stops TX/RX done response to mcu */ + kalDevRegWrite(prAdapter->prGlueInfo, + prChipInfo->u4SerUsbHostAckAddr, + MCU_INT_PDMA0_RECOVERY_DONE); + ucSerState = ERR_RECOV_WAIT_MCU_NORMAL; + } else { + /* do nothing */ + } + break; + + case ERR_RECOV_WAIT_MCU_NORMAL: + if (u4SerAction == ERROR_DETECT_MCU_NORMAL_STATE) { + + /* update Beacon frame if operating in AP mode. */ + DBGLOG(HAL, INFO, "SER(T) Host re-initialize BCN\n"); + nicSerReInitBeaconFrame(prAdapter); + + DBGLOG(HAL, INFO, + "SER(U) Host reset TX/RX endpoint\n"); + + halSerHifReset(prAdapter); + halEnableInterrupt(prAdapter); + + /* resume TX/RX */ + nicSerStartTxRx(prAdapter); + ucSerState = ERR_RECOV_STOP_IDLE; + } else { + /* do nothing */ + } + break; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Check if HIF state is READY for upper layer cfg80211 +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (TRUE: ready, FALSE: not ready) +*/ +/*----------------------------------------------------------------------------*/ +bool halIsHifStateReady(IN struct ADAPTER *prAdapter, uint8_t *pucState) +{ + if (!prAdapter) + return FALSE; + + if (!prAdapter->prGlueInfo) + return FALSE; + + if (prAdapter->prGlueInfo->u4ReadyFlag == 0) + return FALSE; + + if (pucState) + *pucState = prAdapter->prGlueInfo->rHifInfo.state; + + if (prAdapter->prGlueInfo->rHifInfo.state != USB_STATE_READY) + return FALSE; + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Check if HIF state is LINK_UP or READY for USB TX/RX +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (TRUE: ready, FALSE: not ready) +*/ +/*----------------------------------------------------------------------------*/ +bool halIsHifStateLinkup(IN struct ADAPTER *prAdapter) +{ + if (!prAdapter) + return FALSE; + + if (!prAdapter->prGlueInfo) + return FALSE; + + if ((prAdapter->prGlueInfo->rHifInfo.state != USB_STATE_LINK_UP) && + (prAdapter->prGlueInfo->rHifInfo.state != USB_STATE_READY)) + return FALSE; + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Check if HIF state is during supend process +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (TRUE: suspend, reject the caller action. FALSE: not suspend) +*/ +/*----------------------------------------------------------------------------*/ +bool halIsHifStateSuspend(IN struct ADAPTER *prAdapter) +{ + enum usb_state state; + + if (!prAdapter) + return FALSE; + + if (!prAdapter->prGlueInfo) + return FALSE; + + state = prAdapter->prGlueInfo->rHifInfo.state; + + if (state == USB_STATE_SUSPEND) + return TRUE; + + return FALSE; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/usb/include/cust_usb_id.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/usb/include/cust_usb_id.h new file mode 100644 index 0000000000000..412b92096c9c0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/usb/include/cust_usb_id.h @@ -0,0 +1,116 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "cust_usb_id.h" + * \brief Define USB vid/pid table for customers + */ + + +#ifndef _CUST_USB_ID_H +#define _CUST_USB_ID_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 +******************************************************************************** +*/ + +/*! + * \brief Additional USB vid/pid tables for customers. + * Please add your vid/pid in table below as the example shows. + * + */ +#define CUST_USB_ID_TABLES \ +/* + * { USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x7618, 0xff, 0xff, 0xff), \ + * .driver_info = (kernel_ulong_t)&mt66xx_driver_data_mt7668},\ + * { USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x7658, 0xff, 0xff, 0xff), \ + * .driver_info = (kernel_ulong_t)&mt66xx_driver_data_mt7668},\ +*/ + +/******************************************************************************* +* 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 /* _CUST_USB_ID_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/usb/include/hif.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/usb/include/hif.h new file mode 100644 index 0000000000000..c3487b6b7e875 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/usb/include/hif.h @@ -0,0 +1,461 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \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 +*/ + + +#ifndef _HIF_H +#define _HIF_H + +#include "nic_cmd_event.h" +#include "wlan_typedef.h" + +enum ENUM_USB_END_POINT { + USB_DATA_BULK_OUT_EP4 = 4, + USB_DATA_BULK_OUT_EP5, + USB_DATA_BULK_OUT_EP6, + USB_DATA_BULK_OUT_EP7, + USB_DATA_BULK_OUT_EP8, + USB_DATA_BULK_OUT_EP9, + + USB_DATA_BULK_IN_EP4 = 4, + USB_DATA_BULK_IN_EP5, + +}; + +/******************************************************************************* +* C O M P I L E 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 +******************************************************************************** +*/ + +#if defined(_HIF_USB) +#define HIF_NAME "USB" +#else +#error "No HIF defined!" +#endif +#define HIF_CR4_FWDL_SECTION_NUM 2 +#define HIF_IMG_DL_STATUS_PORT_IDX 0 +#define HIF_IST_LOOP_COUNT (4) +#define HIF_IST_TX_THRESHOLD (1) /* Min msdu count to trigger Tx during INT polling state */ + +#define HIF_NUM_OF_QM_RX_PKT_NUM (512) + +#define HIF_TX_BUFF_COUNT_TC0 256 +#define HIF_TX_BUFF_COUNT_TC1 256 +#define HIF_TX_BUFF_COUNT_TC2 256 +#define HIF_TX_BUFF_COUNT_TC3 256 +#define HIF_TX_BUFF_COUNT_TC4 256 +#define HIF_TX_BUFF_COUNT_TC5 256 + +#define HIF_TX_RESOURCE_CTRL 0 /* enable/disable TX resource control */ +#define HIF_TX_RESOURCE_CTRL_PLE 0 /* enable/disable TX resource control PLE */ + + +#if CFG_USB_TX_AGG +#define HIF_TX_PAGE_SIZE_IN_POWER_OF_2 0 +#define HIF_TX_PAGE_SIZE 1 /* in unit of bytes */ +#else +#define HIF_TX_PAGE_SIZE_IN_POWER_OF_2 11 +#define HIF_TX_PAGE_SIZE 2048 /* in unit of bytes */ +#endif + +#define USB_EVENT_TYPE (EVENT_EP_TYPE_UNKONW) + +#define USB_CMD_EP_OUT (USB_DATA_BULK_OUT_EP8) +#define USB_EVENT_EP_IN (0x85) +#define USB_DATA_EP_IN (0x84) + +#define HIF_TX_INIT_CMD_PORT USB_CMD_EP_OUT + +#ifdef CFG_USB_REQ_TX_DATA_FFA_CNT +#define USB_REQ_TX_DATA_FFA_CNT (CFG_USB_REQ_TX_DATA_FFA_CNT) /* platform specific USB_REQ_TX_DATA_FFA_CNT */ +#else +#define USB_REQ_TX_DATA_FFA_CNT (10) +#endif + +#ifdef CFG_USB_REQ_TX_DATA_CNT +#define USB_REQ_TX_DATA_CNT (CFG_USB_REQ_TX_DATA_CNT) /* platform specific USB_REQ_TX_DATA_CNT */ +#else +#if CFG_USB_TX_AGG +#define USB_REQ_TX_DATA_CNT (2) /* must be >= 2 */ +#else +#define USB_REQ_TX_DATA_CNT (CFG_TX_MAX_PKT_NUM) +#endif +#endif + +#define USB_REQ_TX_CMD_CNT (CFG_TX_MAX_CMD_PKT_NUM) +#define USB_REQ_RX_EVENT_CNT (1) +#ifdef CFG_USB_REQ_RX_DATA_CNT +#define USB_REQ_RX_DATA_CNT (CFG_USB_REQ_RX_DATA_CNT) /* platform specific USB_REQ_RX_DATA_CNT */ +#else +#define USB_REQ_RX_DATA_CNT (2) +#endif + +#define USB_RX_AGGREGTAION_LIMIT (32) /* Unit: K-bytes */ +#define USB_RX_AGGREGTAION_TIMEOUT (100) /* Unit: us */ +#define USB_RX_AGGREGTAION_PKT_LIMIT (30) + +#define USB_TX_CMD_BUF_SIZE (1600) +#if CFG_USB_TX_AGG +#define USB_TX_DATA_BUFF_SIZE (32*1024) +#else +#define USB_TX_DATA_BUF_SIZE (NIC_TX_DESC_AND_PADDING_LENGTH + NIC_TX_DESC_HEADER_PADDING_LENGTH + \ + NIC_TX_MAX_SIZE_PER_FRAME + LEN_USB_UDMA_TX_TERMINATOR) +#endif +#define USB_RX_EVENT_BUF_SIZE (CFG_RX_MAX_PKT_SIZE + 3 + LEN_USB_RX_PADDING_CSO + 4) +#define USB_RX_DATA_BUF_SIZE (CFG_RX_MAX_PKT_SIZE + \ + min(USB_RX_AGGREGTAION_LIMIT * 1024, \ + (USB_RX_AGGREGTAION_PKT_LIMIT * \ + (CFG_RX_MAX_PKT_SIZE + 3 + LEN_USB_RX_PADDING_CSO) + 4))) + +#define LEN_USB_UDMA_TX_TERMINATOR (4) /*HW design spec */ +#define LEN_USB_RX_PADDING_CSO (4) /*HW design spec */ + +#define USB_RX_EVENT_RFB_RSV_CNT (0) +#define USB_RX_DATA_RFB_RSV_CNT (4) + +#define DEVICE_VENDOR_REQUEST_IN (0xc0) +#define DEVICE_VENDOR_REQUEST_IN_CONNAC2 (0xdF) +#define DEVICE_VENDOR_REQUEST_OUT (0x40) +#define DEVICE_VENDOR_REQUEST_OUT_CONNAC2 (0x5F) +#define VENDOR_TIMEOUT_MS (1000) +#define BULK_TIMEOUT_MS (1500) +#define INTERRUPT_TIMEOUT_MS (1000) +#define SW_RFB_RECHECK_MS (10) +#define SW_RFB_LOG_LIMIT_MS (5000) + +/* Vendor Request */ +#define VND_REQ_POWER_ON_WIFI (0x4) +#define VND_REQ_REG_READ (0x63) +#define VND_REQ_REG_WRITE (0x66) +#define VND_REQ_EP5_IN_INFO (0x67) +#define VND_REQ_FEATURE_SET (0x91) +#define FEATURE_SET_WVALUE_RESUME (0x5) +#define FEATURE_SET_WVALUE_SUSPEND (0x6) +#define VND_REQ_BUF_SIZE (16) + +#define USB_TX_CMD_QUEUE_MASK (BITS(2, 4)) /* For H2CDMA Tx CMD mapping */ + +#define USB_DBDC1_TC (TC_NUM)/* for DBDC1 */ +#define USB_TC_NUM (TC_NUM + 1)/* for DBDC1 */ +#define USB_TX_EPOUT_NUM (5) + +#define HIF_EXTRA_IO_BUFFER_SIZE (0) + +#define HIF_TX_COALESCING_BUFFER_SIZE (USB_TX_CMD_BUF_SIZE) +#define HIF_RX_COALESCING_BUFFER_SIZE (USB_RX_EVENT_BUF_SIZE) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/* host interface's private data structure, which is attached to os glue +** layer info structure. + */ + +enum usb_state { + USB_STATE_WIFI_OFF, /* Hif power off wifi */ + USB_STATE_LINK_DOWN, + USB_STATE_PRE_SUSPEND_START, + USB_STATE_PRE_SUSPEND_DONE, + USB_STATE_PRE_SUSPEND_FAIL, + USB_STATE_SUSPEND, + USB_STATE_PRE_RESUME, + USB_STATE_LINK_UP, + USB_STATE_READY +}; + +enum usb_submit_type { + SUBMIT_TYPE_TX_CMD, + SUBMIT_TYPE_TX_DATA, + SUBMIT_TYPE_RX_EVENT, + SUBMIT_TYPE_RX_DATA +}; + +enum EVENT_EP_TYPE { + EVENT_EP_TYPE_UNKONW, + EVENT_EP_TYPE_BULK, + EVENT_EP_TYPE_INTR, + EVENT_EP_TYPE_DATA_EP +}; + +enum ENUM_SUSPEND_VERSION { + SUSPEND_V1 = 1, + SUSPEND_V2 +}; + +struct BUF_CTRL { + uint8_t *pucBuf; + uint32_t u4BufSize; + uint32_t u4WrIdx; + uint32_t u4ReadSize; +}; + +struct GL_HIF_INFO { + struct usb_interface *intf; + struct usb_device *udev; + + struct GLUE_INFO *prGlueInfo; + enum usb_state state; + + spinlock_t rTxDataQLock; + spinlock_t rTxCmdQLock; + spinlock_t rRxEventQLock; + spinlock_t rRxDataQLock; + spinlock_t rStateLock; + + void *prTxCmdReqHead; + void *arTxDataFfaReqHead; + void *arTxDataReqHead[USB_TC_NUM]; + void *prRxEventReqHead; + void *prRxDataReqHead; + struct list_head rTxCmdFreeQ; + spinlock_t rTxCmdFreeQLock; + struct list_head rTxCmdSendingQ; + spinlock_t rTxCmdSendingQLock; + struct list_head rTxDataFfaQ; +#if CFG_USB_TX_AGG + uint32_t u4AggRsvSize[USB_TC_NUM]; + struct list_head rTxDataFreeQ[USB_TC_NUM]; + struct usb_anchor rTxDataAnchor[USB_TC_NUM]; +#else + struct list_head rTxDataFreeQ; + struct usb_anchor rTxDataAnchor; +#endif + /*spinlock_t rTxDataFreeQLock;*/ + struct list_head rRxEventFreeQ; + /*spinlock_t rRxEventFreeQLock;*/ + struct usb_anchor rRxEventAnchor; + struct list_head rRxDataFreeQ; + /*spinlock_t rRxDataFreeQLock;*/ + struct usb_anchor rRxDataAnchor; + struct list_head rRxEventCompleteQ; + /*spinlock_t rRxEventCompleteQLock;*/ + struct list_head rRxDataCompleteQ; + /*spinlock_t rRxDataCompleteQLock;*/ + struct list_head rTxCmdCompleteQ; + struct list_head rTxDataCompleteQ; + + struct BUF_CTRL rTxCmdBufCtrl[USB_REQ_TX_CMD_CNT]; + struct BUF_CTRL rTxDataFfaBufCtrl[USB_REQ_TX_DATA_FFA_CNT]; +#if CFG_USB_TX_AGG + struct BUF_CTRL rTxDataBufCtrl[USB_TC_NUM][USB_REQ_TX_DATA_CNT]; +#else + struct BUF_CTRL rTxDataBufCtrl[USB_REQ_TX_DATA_CNT]; +#endif + struct BUF_CTRL rRxEventBufCtrl[USB_REQ_RX_EVENT_CNT]; + struct BUF_CTRL rRxDataBufCtrl[USB_REQ_RX_DATA_CNT]; + + struct mutex vendor_req_sem; + void *vendor_req_buf; + u_int32_t vendor_req_buf_sz; + u_int8_t fgIntReadClear; + u_int8_t fgMbxReadClear; + u_int8_t fgEventEpDetected; + enum EVENT_EP_TYPE eEventEpType; +}; + +struct USB_REQ { + struct list_head list; + struct urb *prUrb; + struct BUF_CTRL *prBufCtrl; + struct GL_HIF_INFO *prHifInfo; + void *prPriv; + struct QUE rSendingDataMsduInfoList; +}; + +struct BUS_INFO { + const uint32_t u4UdmaWlCfg_0_Addr; + const uint32_t u4UdmaWlCfg_1_Addr; + const uint32_t u4UdmaTxQsel; + const uint32_t u4device_vender_request_in; + const uint32_t u4device_vender_request_out; + const uint32_t u4usb_tx_cmd_queue_mask; + uint32_t u4UdmaWlCfg_0; + uint32_t u4UdmaTxTimeout; /* UDMA Tx time out limit, unit: us */ + uint32_t u4SuspendVer; + u_int8_t (*asicUsbSuspend)( + IN struct ADAPTER *prAdapter, + IN struct GLUE_INFO *prGlueInfo); + u_int8_t (*asicUsbResume)( + IN struct ADAPTER *prAdapter, + IN struct GLUE_INFO *prGlueInfo); + uint8_t (*asicUsbEventEpDetected)(IN struct ADAPTER *prAdapter); + uint16_t (*asicUsbRxByteCount)(IN struct ADAPTER *prAdapter, + IN struct BUS_INFO *prBusInfo, + IN uint8_t *pRXD); + void (*DmaShdlInit)(IN struct ADAPTER *prAdapter); +}; + +/* USB_REQ_T prPriv field for TxData */ +#define FFA_MASK BIT(7) /* Indicate if this UsbReq is from FFA queue. */ +#define TC_MASK BITS(0, 6) /* Indicate which TC this UsbReq belongs to */ + +/******************************************************************************* +* P U B 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 USB_TRANS_MSDU_TC(_prMsduInfo) \ + ((_prMsduInfo)->ucWmmQueSet ? USB_DBDC1_TC : (_prMsduInfo)->ucTC) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +uint32_t glRegisterBus(probe_card pfProbe, remove_card pfRemove); + +void glUnregisterBus(remove_card pfRemove); + +void glSetHifInfo(struct GLUE_INFO *prGlueInfo, unsigned long ulCookie); + +void glClearHifInfo(struct GLUE_INFO *prGlueInfo); + +u_int8_t glBusInit(void *pvData); + +void glBusRelease(void *pData); + +int32_t glBusSetIrq(void *pvData, void *pfnIsr, void *pvCookie); + +void glBusFreeIrq(void *pvData, void *pvCookie); + +void glSetPowerState(IN struct GLUE_INFO *prGlueInfo, IN uint32_t ePowerMode); + +void glUdmaTxRxEnable(struct GLUE_INFO *prGlueInfo, u_int8_t enable); + +void glUdmaRxAggEnable(struct GLUE_INFO *prGlueInfo, u_int8_t enable); + +int32_t mtk_usb_vendor_request(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t uEndpointAddress, IN uint8_t RequestType, + IN uint8_t Request, IN uint16_t Value, IN uint16_t Index, + IN void *TransferBuffer, IN uint32_t TransferBufferLength); + +void glUsbEnqueueReq(struct GL_HIF_INFO *prHifInfo, struct list_head *prHead, struct USB_REQ *prUsbReq, + spinlock_t *prLock, u_int8_t fgHead); +struct USB_REQ *glUsbDequeueReq(struct GL_HIF_INFO *prHifInfo, struct list_head *prHead, spinlock_t *prLock); +u_int8_t glUsbBorrowFfaReq(struct GL_HIF_INFO *prHifInfo, uint8_t ucTc); + +void glUsbSetState(IN struct GL_HIF_INFO *prHifInfo, enum usb_state state); + +int glUsbSubmitUrb(IN struct GL_HIF_INFO *prHifInfo, struct urb *urb, + enum usb_submit_type type); + +uint32_t halTxUSBSendCmd(IN struct GLUE_INFO *prGlueInfo, IN uint8_t ucTc, IN struct CMD_INFO *prCmdInfo); +void halTxUSBSendCmdComplete(struct urb *urb); +void halTxUSBProcessCmdComplete(IN struct ADAPTER *prAdapter, struct USB_REQ *prUsbReq); + +uint32_t halTxUSBSendData(IN struct GLUE_INFO *prGlueInfo, IN struct MSDU_INFO *prMsduInfo); +uint32_t halTxUSBKickData(IN struct GLUE_INFO *prGlueInfo); +void halTxUSBSendDataComplete(struct urb *urb); +void halTxUSBProcessMsduDone(IN struct GLUE_INFO *prGlueInfo, struct USB_REQ *prUsbReq); +void halTxUSBProcessDataComplete(IN struct ADAPTER *prAdapter, struct USB_REQ *prUsbReq); + +uint32_t halRxUSBEnqueueRFB( + IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, + IN uint32_t u4Length, + IN uint32_t u4MinRfbCnt, + IN struct list_head *prCompleteQ); +uint32_t halRxUSBReceiveEvent(IN struct ADAPTER *prAdapter, IN u_int8_t fgFillUrb); +void halRxUSBReceiveEventComplete(struct urb *urb); +uint32_t halRxUSBReceiveData(IN struct ADAPTER *prAdapter); +void halRxUSBReceiveDataComplete(struct urb *urb); +void halRxUSBProcessEventDataComplete(IN struct ADAPTER *prAdapter, + struct list_head *prCompleteQ, struct list_head *prFreeQ, uint32_t u4MinRfbCnt); + +void halUSBPreSuspendCmd(IN struct ADAPTER *prAdapter); +void halUSBPreResumeCmd(IN struct ADAPTER *prAdapter); +void halUSBPreSuspendDone(IN struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); +void halUSBPreSuspendTimeout(IN struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo); + +void glGetDev(void *ctx, struct device **dev); +void glGetHifDev(struct GL_HIF_INFO *prHif, struct device **dev); + +void halGetCompleteStatus(IN struct ADAPTER *prAdapter, OUT uint32_t *pu4IntStatus); + +uint16_t glGetUsbDeviceVendorId(struct usb_device *dev); +uint16_t glGetUsbDeviceProductId(struct usb_device *dev); + +int32_t glGetUsbDeviceManufacturerName(struct usb_device *dev, uint8_t *buffer, uint32_t bufLen); +int32_t glGetUsbDeviceProductName(struct usb_device *dev, uint8_t *buffer, uint32_t bufLen); +int32_t glGetUsbDeviceSerialNumber(struct usb_device *dev, uint8_t *buffer, uint32_t bufLen); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _HIF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/usb/include/hif_usb.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/usb/include/hif_usb.h new file mode 100644 index 0000000000000..acb7ad32ad802 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/usb/include/hif_usb.h @@ -0,0 +1,131 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "hif_usb.h" + * \brief + */ + + +#ifndef _HIF_USB_H +#define _HIF_USB_H +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#define HIF_USB_DEBUG (0) /* 0:turn off debug msg and assert, 1:turn off debug msg and assert */ + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + +/*! + * \brief A debug print used to print debug messages while compiler flag HIF_SDIO_DEBUG on. + * + */ +#if HIF_USB_DEBUG +#define DPRINTK(fmt, args...) pr_debug("%s: " fmt, __func__, ## args) +#else +#define DPRINTK(fmt, args...) +#endif + +/*! + * \brief ASSERT function definition. + * + */ +#if HIF_USB_DEBUG +#define ASSERT(expr) \ + do { \ + if (!(expr)) { \ + pr_err("assertion failed! %s[%d]: %s\n", \ + __func__, __LINE__, #expr); \ + WARN_ON(!(expr)); \ + } \ + } while (0) +#else +#define 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 +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _HIF_USB_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/usb/usb.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/usb/usb.c new file mode 100644 index 0000000000000..7d97542c52602 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/hif/usb/usb.c @@ -0,0 +1,1658 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** +*[File] usb.c +*[Version] v1.0 +*[Revision Date] 2010-03-01 +*[Author] +*[Description] +* The program provides USB HIF driver +*[Copyright] +* Copyright (C) 2010 MediaTek Incorporation. All Rights Reserved. +******************************************************************************/ + + +/******************************************************************************* +* C O M P I L E 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 +#include + +#include +#ifndef CONFIG_X86 +#include +#endif + +#include "mt66xx_reg.h" +#include "cust_usb_id.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define HIF_USB_ERR_TITLE_STR "["CHIP_NAME"] USB Access Error!" +#define HIF_USB_ERR_DESC_STR "**USB Access Error**\n" + +#define HIF_USB_ACCESS_RETRY_LIMIT 1 + +#define MT_MAC_BASE 0x2 + +#define MTK_USB_PORT_MASK 0x0F +#define MTK_USB_BULK_IN_MIN_EP 4 +#define MTK_USB_BULK_IN_MAX_EP 5 +#define MTK_USB_BULK_OUT_MIN_EP 4 +#define MTK_USB_BULK_OUT_MAX_EP 9 + +static const struct usb_device_id mtk_usb_ids[] = { + /* {USB_DEVICE(0x0E8D,0x6632), .driver_info = MT_MAC_BASE}, */ +#ifdef MT6632 + { USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x6632, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&mt66xx_driver_data_mt6632}, + { USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x7666, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&mt66xx_driver_data_mt6632}, +#endif /* MT6632 */ +#ifdef MT7668 + { USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x7668, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&mt66xx_driver_data_mt7668}, +#endif /* MT7668 */ +#ifdef MT7663 + { USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x7663, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&mt66xx_driver_data_mt7663}, +#endif /* MT7663 */ +#ifdef MT7915 + { USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x7915, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&mt66xx_driver_data_mt7915}, +#endif /* MT7915 */ +#ifdef MT7961 + { USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x7961, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&mt66xx_driver_data_mt7961}, +#endif /* MT7961 */ + /* If customer usb id is presented, add to the table. */ + CUST_USB_ID_TABLES + { /* end: all zeroes */ }, +}; + +MODULE_DEVICE_TABLE(usb, mtk_usb_ids); + +/******************************************************************************* +* 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 probe_card pfWlanProbe; +static remove_card pfWlanRemove; + +static u_int8_t g_fgDriverProbed = FALSE; + +static struct usb_driver mtk_usb_driver = { + .name = "wlan", /* "MTK USB WLAN Driver" */ + .id_table = mtk_usb_ids, + .probe = NULL, + .disconnect = NULL, + .suspend = NULL, + .resume = NULL, + .reset_resume = NULL, + .supports_autosuspend = 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 +******************************************************************************** +*/ +static int mtk_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id); +static void mtk_usb_disconnect(struct usb_interface *intf); +static int mtk_usb_suspend(struct usb_interface *intf, pm_message_t message); +static int mtk_usb_resume(struct usb_interface *intf); +static int mtk_usb_reset_resume(struct usb_interface *intf); +static int mtk_usb_bulk_in_msg(struct GL_HIF_INFO *prHifInfo, uint32_t len, + uint8_t *buffer, int InEp); +static int mtk_usb_intr_in_msg(struct GL_HIF_INFO *prHifInfo, uint32_t len, + uint8_t *buffer, int InEp); +static int mtk_usb_bulk_out_msg(struct GL_HIF_INFO *prHifInfo, uint32_t len, + uint8_t *buffer, int OutEp); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a USB probe function +* +* \param[in] intf USB interface +* \param[in] id USB device id +* +* \return void +*/ +/*----------------------------------------------------------------------------*/ +static int mtk_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + int ret = 0; + struct usb_device *dev; + + DBGLOG(HAL, EVENT, "mtk_usb_probe()\n"); + + ASSERT(intf); + ASSERT(id); + + dev = interface_to_usbdev(intf); + dev = usb_get_dev(dev); + + /* Prevent un-expected usb operation */ + if (g_fgDriverProbed) { + DBGLOG(HAL, ERROR, "wlan_probe(): Device already probed!!\n"); + return -EBUSY; + } + + DBGLOG(HAL, EVENT, "wlan_probe()\n"); + if (pfWlanProbe((void *) intf, (void *) id->driver_info) != WLAN_STATUS_SUCCESS) { + /* printk(KERN_WARNING DRV_NAME"pfWlanProbe fail!call pfWlanRemove()\n"); */ + pfWlanRemove(); + DBGLOG(HAL, ERROR, "wlan_probe() failed\n"); + ret = -1; + } else { + g_fgDriverProbed = TRUE; + } + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a USB remove function +* +* \param[in] intf USB interface +* +* \return void +*/ +/*----------------------------------------------------------------------------*/ +static void mtk_usb_disconnect(struct usb_interface *intf) +{ + struct GLUE_INFO *prGlueInfo; + + DBGLOG(HAL, STATE, "mtk_usb_disconnect()\n"); + + ASSERT(intf); + prGlueInfo = (struct GLUE_INFO *)usb_get_intfdata(intf); + + glUsbSetState(&prGlueInfo->rHifInfo, USB_STATE_LINK_DOWN); + + if (g_fgDriverProbed) + pfWlanRemove(); + + usb_set_intfdata(intf, NULL); + usb_put_dev(interface_to_usbdev(intf)); + + g_fgDriverProbed = FALSE; + + DBGLOG(HAL, STATE, "mtk_usb_disconnect() done\n"); +} + +static int mtk_usb_resume(struct usb_interface *intf) +{ + int ret = 0; + struct GLUE_INFO *prGlueInfo = + (struct GLUE_INFO *)usb_get_intfdata(intf); + struct BUS_INFO *prBusInfo = NULL; + + DBGLOG(HAL, STATE, "mtk_usb_resume()\n"); + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + + if (prBusInfo->asicUsbResume) { + /* callback func registered for each chip */ + if (prBusInfo->asicUsbResume(prGlueInfo->prAdapter, prGlueInfo)) + ret = 0; + else + ret = -1; + } else { + /* Do general method if no callback func registered */ + /* NOTE: USB bus may not really do suspend and resume*/ + ret = usb_control_msg(prGlueInfo->rHifInfo.udev, + usb_sndctrlpipe(prGlueInfo->rHifInfo.udev, 0), + VND_REQ_FEATURE_SET, + prBusInfo->u4device_vender_request_out, + FEATURE_SET_WVALUE_RESUME, 0, NULL, 0, + VENDOR_TIMEOUT_MS); + if (ret) + DBGLOG(HAL, ERROR, + "VendorRequest FeatureSetResume ERROR: %x\n", + (unsigned int)ret); + + glUsbSetState(&prGlueInfo->rHifInfo, USB_STATE_PRE_RESUME); + /* To trigger CR4 path */ + wlanSendDummyCmd(prGlueInfo->prAdapter, FALSE); + + glUsbSetState(&prGlueInfo->rHifInfo, USB_STATE_LINK_UP); + halEnableInterrupt(prGlueInfo->prAdapter); + + if (prGlueInfo->prAdapter->rWifiVar.ucWow) { + DBGLOG(HAL, EVENT, "leave WOW flow\n"); + kalWowProcess(prGlueInfo, FALSE); + } + } + + /* Allow upper layers to call the device hard_start_xmit routine. */ + netif_tx_start_all_queues(prGlueInfo->prDevHandler); + + DBGLOG(HAL, STATE, "mtk_usb_resume() done ret=%d!\n", ret); + + /* TODO */ + return ret; +} + +static int mtk_usb_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)usb_get_intfdata(intf); + uint8_t count = 0; + struct BUS_INFO *prBusInfo = NULL; + int ret = 0; + + DBGLOG(HAL, STATE, "mtk_usb_suspend()\n"); + + /* Stop upper layers calling the device hard_start_xmit routine. */ + netif_tx_stop_all_queues(prGlueInfo->prDevHandler); + + /* change to non-READY state to block cfg80211 ops */ + glUsbSetState(&prGlueInfo->rHifInfo, USB_STATE_PRE_SUSPEND_START); + + wlanSuspendPmHandle(prGlueInfo); + + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + if (prBusInfo->asicUsbSuspend) { + if (prBusInfo->asicUsbSuspend(prGlueInfo->prAdapter, prGlueInfo)) + return 0; + else + return -1; + } + + halUSBPreSuspendCmd(prGlueInfo->prAdapter); + + while (prGlueInfo->rHifInfo.state != USB_STATE_PRE_SUSPEND_DONE) { + if (count > 25) { + DBGLOG(HAL, ERROR, "pre_suspend timeout\n"); + ret = -EFAULT; + break; + } + msleep(20); + count++; + } + + glUsbSetState(&prGlueInfo->rHifInfo, USB_STATE_SUSPEND); + halDisableInterrupt(prGlueInfo->prAdapter); + halTxCancelAllSending(prGlueInfo->prAdapter); + + DBGLOG(HAL, STATE, "mtk_usb_suspend() done!\n"); + + if (ret && PMSG_IS_AUTO(message)) + mtk_usb_resume(intf); + + return ret; +} + +static int mtk_usb_reset_resume(struct usb_interface *intf) +{ + DBGLOG(HAL, STATE, "mtk_usb_reset_resume()\n"); + + mtk_usb_resume(intf); + + DBGLOG(HAL, STATE, "mtk_usb_reset_resume done!()\n"); + + /* TODO */ + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief USB EP0 vendor request +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] uEndpointAddress +* \param[in] RequestType +* \param[in] Request +* \param[in] Value +* \param[in] Index +* \param[in] TransferBuffer +* \param[in] TransferBufferLength +* +* \retval 0 if success +* non-zero if fail, the return value of usb_control_msg() +*/ +/*----------------------------------------------------------------------------*/ +int32_t mtk_usb_vendor_request(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t uEndpointAddress, IN uint8_t RequestType, + IN uint8_t Request, IN uint16_t Value, IN uint16_t Index, + IN void *TransferBuffer, IN uint32_t TransferBufferLength) +{ + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + struct BUS_INFO *prBusInfo = NULL; + void *xfer_buf; + + /* refer to RTUSB_VendorRequest */ + int ret = 0; + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + + /* TODO: semaphore */ + + if (in_interrupt()) { + DBGLOG(REQ, ERROR, "BUG: mtk_usb_vendor_request is called from invalid context\n"); + return -EFAULT; + } + + if (unlikely(TransferBufferLength > prHifInfo->vendor_req_buf_sz)) { + DBGLOG(REQ, ERROR, "len %u exceeds limit %zu\n", + TransferBufferLength, + prHifInfo->vendor_req_buf_sz); + return -E2BIG; + } + + if (unlikely(TransferBuffer && !prHifInfo->vendor_req_buf)) { + DBGLOG(REQ, ERROR, "NULL vendor_req_buf\n"); + return -EFAULT; + } + + /* use heap instead of old stack memory */ + xfer_buf = (TransferBuffer) ? prHifInfo->vendor_req_buf : NULL; + + mutex_lock(&prHifInfo->vendor_req_sem); + + if (RequestType == prBusInfo->u4device_vender_request_out) { + if (xfer_buf) + memcpy(xfer_buf, TransferBuffer, TransferBufferLength); + ret = usb_control_msg(prHifInfo->udev, + usb_sndctrlpipe(prHifInfo->udev, + uEndpointAddress), + Request, RequestType, Value, Index, + xfer_buf, TransferBufferLength, + VENDOR_TIMEOUT_MS); + } else if (RequestType == prBusInfo->u4device_vender_request_in) { + ret = usb_control_msg(prHifInfo->udev, + usb_rcvctrlpipe(prHifInfo->udev, + uEndpointAddress), + Request, RequestType, Value, Index, + xfer_buf, TransferBufferLength, + VENDOR_TIMEOUT_MS); + if (xfer_buf && (ret > 0)) + memcpy(TransferBuffer, xfer_buf, TransferBufferLength); + } + mutex_unlock(&prHifInfo->vendor_req_sem); + + return (ret == TransferBufferLength) ? 0 : ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief USB Bulk IN msg +* +* \param[in] prHifInfo Pointer to the struct GL_HIF_INFO structure +* \param[in] len +* \param[in] buffer +* \param[in] InEp +* +* \retval +*/ +/*----------------------------------------------------------------------------*/ +static int mtk_usb_bulk_in_msg(IN struct GL_HIF_INFO *prHifInfo, IN uint32_t len, OUT uint8_t *buffer, int InEp) +{ + int ret = 0; + uint32_t count; + + if (in_interrupt()) { + DBGLOG(REQ, ERROR, "BUG: mtk_usb_bulk_in_msg is called from invalid context\n"); + return FALSE; + } + + mutex_lock(&prHifInfo->vendor_req_sem); + + /* do a blocking bulk read to get data from the device */ + ret = usb_bulk_msg(prHifInfo->udev, + usb_rcvbulkpipe(prHifInfo->udev, InEp), buffer, len, &count, BULK_TIMEOUT_MS); + + mutex_unlock(&prHifInfo->vendor_req_sem); + + if (ret >= 0) { +#if 0 /* maximize buff len for usb in */ + if (count != len) { + DBGLOG(HAL, WARN, "usb_bulk_msg(IN=%d) Warning. Data is not completed. (receive %d/%u)\n", + InEp, count, len); + } +#endif + return count; + } + + DBGLOG(HAL, ERROR, "usb_bulk_msg(IN=%d) Fail. Error code = %d.\n", InEp, ret); + return ret; +} + +static int mtk_usb_intr_in_msg(IN struct GL_HIF_INFO *prHifInfo, IN uint32_t len, OUT uint8_t *buffer, int InEp) +{ + int ret = 0; + uint32_t count; + + if (in_interrupt()) { + DBGLOG(REQ, ERROR, "BUG: mtk_usb_intr_in_msg is called from invalid context\n"); + return FALSE; + } + + mutex_lock(&prHifInfo->vendor_req_sem); + + /* do a blocking interrupt read to get data from the device */ + ret = usb_interrupt_msg(prHifInfo->udev, + usb_rcvintpipe(prHifInfo->udev, InEp), buffer, len, &count, INTERRUPT_TIMEOUT_MS); + + mutex_unlock(&prHifInfo->vendor_req_sem); + + if (ret >= 0) { +#if 0 /* maximize buff len for usb in */ + if (count != len) { + DBGLOG(HAL, WARN, "usb_interrupt_msg(IN=%d) Warning. Data is not completed. (receive %d/%u)\n", + InEp, count, len); + } +#endif + return count; + } + + DBGLOG(HAL, ERROR, "usb_interrupt_msg(IN=%d) Fail. Error code = %d.\n", InEp, ret); + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief USB Bulk OUT msg +* +* \param[in] prHifInfo Pointer to the struct GL_HIF_INFO structure +* \param[in] len +* \param[in] buffer +* \param[in] OutEp +* +* \retval +*/ +/*----------------------------------------------------------------------------*/ +static int mtk_usb_bulk_out_msg(IN struct GL_HIF_INFO *prHifInfo, IN uint32_t len, IN uint8_t *buffer, int OutEp) +{ + int ret = 0; + uint32_t count; + + if (in_interrupt()) { + DBGLOG(REQ, ERROR, "BUG: mtk_usb_bulk_out_msg is called from invalid context\n"); + return FALSE; + } + + mutex_lock(&prHifInfo->vendor_req_sem); + + /* do a blocking bulk read to get data from the device */ + ret = usb_bulk_msg(prHifInfo->udev, + usb_sndbulkpipe(prHifInfo->udev, OutEp), buffer, len, &count, BULK_TIMEOUT_MS); + + mutex_unlock(&prHifInfo->vendor_req_sem); + + if (ret >= 0) { +#if 0 + if (count != len) { + DBGLOG(HAL, ERROR, "usb_bulk_msg(OUT=%d) Warning. Data is not completed. (send %d/%u)\n", OutEp, + count, len); + } +#endif + return count; + } + + DBGLOG(HAL, ERROR, "usb_bulk_msg(OUT=%d) Fail. Error code = %d.\n", OutEp, ret); + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will register USB 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 USB bus +*/ +/*----------------------------------------------------------------------------*/ +uint32_t glRegisterBus(probe_card pfProbe, remove_card pfRemove) +{ + int ret = 0; + + ASSERT(pfProbe); + ASSERT(pfRemove); + + pfWlanProbe = pfProbe; + pfWlanRemove = pfRemove; + + mtk_usb_driver.probe = mtk_usb_probe; + mtk_usb_driver.disconnect = mtk_usb_disconnect; + mtk_usb_driver.suspend = mtk_usb_suspend; + mtk_usb_driver.resume = mtk_usb_resume; + mtk_usb_driver.reset_resume = mtk_usb_reset_resume; + mtk_usb_driver.supports_autosuspend = 1; + + ret = (usb_register(&mtk_usb_driver) == 0) ? WLAN_STATUS_SUCCESS : WLAN_STATUS_FAILURE; + + return ret; +} /* end of glRegisterBus() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will unregister USB bus to the os +* +* \param[in] pfRemove Function pointer to remove card +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void glUnregisterBus(remove_card pfRemove) +{ + if (g_fgDriverProbed) { + pfRemove(); + g_fgDriverProbed = FALSE; + } + usb_deregister(&mtk_usb_driver); +} /* end of glUnregisterBus() */ + +void glUdmaTxRxEnable(struct GLUE_INFO *prGlueInfo, u_int8_t enable) +{ + uint32_t u4Value = 0; + struct BUS_INFO *prBusInfo; + + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + kalDevRegRead(prGlueInfo, prBusInfo->u4UdmaWlCfg_0_Addr, &u4Value); + + /* enable UDMA TX & RX */ + if (enable) + u4Value |= prBusInfo->u4UdmaWlCfg_0; + else + u4Value &= ~prBusInfo->u4UdmaWlCfg_0; + + kalDevRegWrite(prGlueInfo, prBusInfo->u4UdmaWlCfg_0_Addr, u4Value); +} + +void glUdmaRxAggEnable(struct GLUE_INFO *prGlueInfo, u_int8_t enable) +{ + uint32_t u4Value = 0; + struct BUS_INFO *prBusInfo; + + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + if (enable) { + kalDevRegRead(prGlueInfo, prBusInfo->u4UdmaWlCfg_0_Addr, &u4Value); + /* enable UDMA TX & RX */ + u4Value &= ~(UDMA_WLCFG_0_RX_AGG_EN_MASK | + UDMA_WLCFG_0_RX_AGG_LMT_MASK | + UDMA_WLCFG_0_RX_AGG_TO_MASK); + u4Value |= UDMA_WLCFG_0_RX_AGG_EN(1) | + UDMA_WLCFG_0_RX_AGG_LMT(USB_RX_AGGREGTAION_LIMIT) | + UDMA_WLCFG_0_RX_AGG_TO(USB_RX_AGGREGTAION_TIMEOUT); + kalDevRegWrite(prGlueInfo, prBusInfo->u4UdmaWlCfg_0_Addr, u4Value); + + kalDevRegRead(prGlueInfo, prBusInfo->u4UdmaWlCfg_1_Addr, &u4Value); + u4Value &= ~UDMA_WLCFG_1_RX_AGG_PKT_LMT_MASK; + u4Value |= UDMA_WLCFG_1_RX_AGG_PKT_LMT(USB_RX_AGGREGTAION_PKT_LIMIT); + kalDevRegWrite(prGlueInfo, prBusInfo->u4UdmaWlCfg_1_Addr, u4Value); + } else { + kalDevRegRead(prGlueInfo, prBusInfo->u4UdmaWlCfg_0_Addr, &u4Value); + u4Value &= ~UDMA_WLCFG_0_RX_AGG_EN(1); + kalDevRegWrite(prGlueInfo, prBusInfo->u4UdmaWlCfg_0_Addr, u4Value); + } +} + +void *glUsbInitQ(struct GL_HIF_INFO *prHifInfo, struct list_head *prHead, uint32_t u4Cnt) +{ + uint32_t i; + struct USB_REQ *prUsbReqs, *prUsbReq; + + INIT_LIST_HEAD(prHead); + + prUsbReqs = kcalloc(u4Cnt, sizeof(struct USB_REQ), GFP_ATOMIC); + prUsbReq = prUsbReqs; + + for (i = 0; i < u4Cnt; ++i) { + prUsbReq->prHifInfo = prHifInfo; + prUsbReq->prUrb = usb_alloc_urb(0, GFP_ATOMIC); + + if (prUsbReq->prUrb == NULL) + DBGLOG(HAL, ERROR, "usb_alloc_urb() reports error\n"); + + prUsbReq->prBufCtrl = NULL; + + INIT_LIST_HEAD(&prUsbReq->list); + list_add_tail(&prUsbReq->list, prHead); + + prUsbReq++; + } + + return (void *) prUsbReqs; +} + +void glUsbUnInitQ(struct list_head *prHead) +{ + struct USB_REQ *prUsbReq, *prUsbReqNext; + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, prHead, list) { + usb_free_urb(prUsbReq->prUrb); + list_del_init(&prUsbReq->list); + } +} + +void glUsbEnqueueReq(struct GL_HIF_INFO *prHifInfo, struct list_head *prHead, struct USB_REQ *prUsbReq, spinlock_t *prLock, + u_int8_t fgHead) +{ + unsigned long flags; + + spin_lock_irqsave(prLock, flags); + if (fgHead) + list_add(&prUsbReq->list, prHead); + else + list_add_tail(&prUsbReq->list, prHead); + spin_unlock_irqrestore(prLock, flags); +} + +struct USB_REQ *glUsbDequeueReq(struct GL_HIF_INFO *prHifInfo, struct list_head *prHead, spinlock_t *prLock) +{ + struct USB_REQ *prUsbReq; + unsigned long flags; + + spin_lock_irqsave(prLock, flags); + if (list_empty(prHead)) { + spin_unlock_irqrestore(prLock, flags); + return NULL; + } + prUsbReq = list_entry(prHead->next, struct USB_REQ, list); + list_del_init(prHead->next); + spin_unlock_irqrestore(prLock, flags); + + return prUsbReq; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function borrow UsbReq from Tx data FFA queue to the spcified TC Tx data free queue +* +* \param[in] prHifInfo Pointer to the struct GL_HIF_INFO structure +* \param[in] ucTc Specify TC index +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t glUsbBorrowFfaReq(struct GL_HIF_INFO *prHifInfo, uint8_t ucTc) +{ + struct USB_REQ *prUsbReq; + + if (list_empty(&prHifInfo->rTxDataFfaQ)) + return FALSE; + prUsbReq = list_entry(prHifInfo->rTxDataFfaQ.next, struct USB_REQ, list); + list_del_init(prHifInfo->rTxDataFfaQ.next); + + *((uint8_t *)&prUsbReq->prPriv) = FFA_MASK | ucTc; + list_add_tail(&prUsbReq->list, &prHifInfo->rTxDataFreeQ[ucTc]); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function set USB state +* +* \param[in] prHifInfo Pointer to the struct GL_HIF_INFO structure +* \param[in] state Specify TC index +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +void glUsbSetState(struct GL_HIF_INFO *prHifInfo, enum usb_state state) +{ + unsigned long flags; + + spin_lock_irqsave(&prHifInfo->rStateLock, flags); + prHifInfo->state = state; + spin_unlock_irqrestore(&prHifInfo->rStateLock, flags); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a wrapper of submit urb to ensure driver can transmit +* WiFi packet when WiFi path of device is allowed. +* +* \param[in] prHifInfo Pointer to the struct GL_HIF_INFO structure +* \param[in] type Specify submit type +* +* \retval 0 Successful submissions. +* \retval negative Error number. +*/ +/*----------------------------------------------------------------------------*/ +int glUsbSubmitUrb(struct GL_HIF_INFO *prHifInfo, struct urb *urb, + enum usb_submit_type type) +{ + unsigned long flags; + uint32_t ret = 0; + + if (type == SUBMIT_TYPE_RX_EVENT || type == SUBMIT_TYPE_RX_DATA) + return usb_submit_urb(urb, GFP_ATOMIC); + + spin_lock_irqsave(&prHifInfo->rStateLock, flags); + if (type == SUBMIT_TYPE_TX_CMD) { + if (!(prHifInfo->state == USB_STATE_LINK_UP || + prHifInfo->state == USB_STATE_PRE_RESUME || + prHifInfo->state == USB_STATE_PRE_SUSPEND_START || + prHifInfo->state == USB_STATE_READY)) { + spin_unlock_irqrestore(&prHifInfo->rStateLock, flags); + DBGLOG(HAL, INFO, + "not allowed to transmit CMD packet. (%d)\n", + prHifInfo->state); + return -ESHUTDOWN; + } + } else if (type == SUBMIT_TYPE_TX_DATA) { + if (prHifInfo->state != USB_STATE_LINK_UP || + prHifInfo->state == USB_STATE_READY) { + spin_unlock_irqrestore(&prHifInfo->rStateLock, flags); + DBGLOG(HAL, INFO, + "not allowed to transmit DATA packet. (%d)\n", + prHifInfo->state); + return -ESHUTDOWN; + } + } + + if (nicSerIsTxStop(prHifInfo->prGlueInfo->prAdapter)) { + DBGLOG(HAL, ERROR, "[SER] BYPASS USB send packet\n"); + spin_unlock_irqrestore(&prHifInfo->rStateLock, flags); + return -EBUSY; + } + + ret = usb_submit_urb(urb, GFP_ATOMIC); + spin_unlock_irqrestore(&prHifInfo->rStateLock, flags); + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function stores hif related info, which is initialized before. +* +* \param[in] prGlueInfo Pointer to glue info structure +* \param[in] u4Cookie Pointer to uint32_t memory base variable for _HIF_HPI +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void glSetHifInfo(struct GLUE_INFO *prGlueInfo, unsigned long ulCookie) +{ + struct usb_host_interface *alts; + struct usb_host_endpoint *ep; + struct usb_endpoint_descriptor *ep_desc; + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + struct USB_REQ *prUsbReq, *prUsbReqNext; + uint32_t i; +#if CFG_USB_TX_AGG + uint8_t ucTc; +#endif + + prHifInfo->eEventEpType = USB_EVENT_TYPE; + prHifInfo->fgEventEpDetected = FALSE; + + prHifInfo->intf = (struct usb_interface *)ulCookie; + prHifInfo->udev = interface_to_usbdev(prHifInfo->intf); + + alts = prHifInfo->intf->cur_altsetting; + DBGLOG(HAL, STATE, "USB Device speed: %x [%u]\n", + prHifInfo->udev->speed, alts->endpoint[0].desc.wMaxPacketSize); + + if (prHifInfo->eEventEpType == EVENT_EP_TYPE_UNKONW) { + for (i = 0; i < alts->desc.bNumEndpoints; ++i) { + ep = &alts->endpoint[i]; + if (ep->desc.bEndpointAddress == USB_EVENT_EP_IN) { + ep_desc = &alts->endpoint[i].desc; + switch (ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + case USB_ENDPOINT_XFER_INT: + prHifInfo->eEventEpType = EVENT_EP_TYPE_INTR; + break; + case USB_ENDPOINT_XFER_BULK: + default: + prHifInfo->eEventEpType = EVENT_EP_TYPE_BULK; + break; + } + } + } + } + ASSERT(prHifInfo->eEventEpType != EVENT_EP_TYPE_UNKONW); + DBGLOG(HAL, INFO, "Event EP Type: %x\n", prHifInfo->eEventEpType); + + prHifInfo->prGlueInfo = prGlueInfo; + usb_set_intfdata(prHifInfo->intf, prGlueInfo); + + SET_NETDEV_DEV(prGlueInfo->prDevHandler, &prHifInfo->udev->dev); + + spin_lock_init(&prHifInfo->rTxCmdQLock); + spin_lock_init(&prHifInfo->rTxDataQLock); + spin_lock_init(&prHifInfo->rRxEventQLock); + spin_lock_init(&prHifInfo->rRxDataQLock); + spin_lock_init(&prHifInfo->rStateLock); + + mutex_init(&prHifInfo->vendor_req_sem); + prHifInfo->vendor_req_buf = kzalloc(VND_REQ_BUF_SIZE, GFP_KERNEL); + if (!prHifInfo->vendor_req_buf) { + DBGLOG(HAL, ERROR, "kzalloc vendor_req_buf %zu error\n", + VND_REQ_BUF_SIZE); + goto error; + } + prHifInfo->vendor_req_buf_sz = VND_REQ_BUF_SIZE; + +#if CFG_USB_TX_AGG + for (ucTc = 0; ucTc < USB_TC_NUM; ++ucTc) { + prHifInfo->u4AggRsvSize[ucTc] = 0; + init_usb_anchor(&prHifInfo->rTxDataAnchor[ucTc]); + } +#else + init_usb_anchor(&prHifInfo->rTxDataAnchor); +#endif + init_usb_anchor(&prHifInfo->rRxDataAnchor); + init_usb_anchor(&prHifInfo->rRxEventAnchor); + + /* TX CMD */ + prHifInfo->prTxCmdReqHead = glUsbInitQ(prHifInfo, &prHifInfo->rTxCmdFreeQ, USB_REQ_TX_CMD_CNT); + prUsbReq = list_entry(prHifInfo->rTxCmdFreeQ.next, struct USB_REQ, list); + i = 0; + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxCmdFreeQ, list) { + prUsbReq->prBufCtrl = &prHifInfo->rTxCmdBufCtrl[i]; +#if CFG_USB_CONSISTENT_DMA + prUsbReq->prBufCtrl->pucBuf = usb_alloc_coherent(prHifInfo->udev, USB_TX_CMD_BUF_SIZE, GFP_ATOMIC, + &prUsbReq->prUrb->transfer_dma); +#else + prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_TX_CMD_BUF_SIZE, GFP_ATOMIC); +#endif + if (prUsbReq->prBufCtrl->pucBuf == NULL) { + DBGLOG(HAL, ERROR, "kmalloc() reports error\n"); + goto error; + } + prUsbReq->prBufCtrl->u4BufSize = USB_TX_CMD_BUF_SIZE; + ++i; + } + + glUsbInitQ(prHifInfo, &prHifInfo->rTxCmdSendingQ, 0); + + /* TX Data FFA */ + prHifInfo->arTxDataFfaReqHead = glUsbInitQ(prHifInfo, + &prHifInfo->rTxDataFfaQ, USB_REQ_TX_DATA_FFA_CNT); + i = 0; + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxDataFfaQ, list) { + QUEUE_INITIALIZE(&prUsbReq->rSendingDataMsduInfoList); + *((uint8_t *)&prUsbReq->prPriv) = FFA_MASK; + prUsbReq->prBufCtrl = &prHifInfo->rTxDataFfaBufCtrl[i]; +#if CFG_USB_CONSISTENT_DMA + prUsbReq->prBufCtrl->pucBuf = + usb_alloc_coherent(prHifInfo->udev, USB_TX_DATA_BUFF_SIZE, GFP_ATOMIC, + &prUsbReq->prUrb->transfer_dma); +#else + prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_TX_DATA_BUFF_SIZE, GFP_ATOMIC); +#endif + if (prUsbReq->prBufCtrl->pucBuf == NULL) { + DBGLOG(HAL, ERROR, "kmalloc() reports error\n"); + goto error; + } + prUsbReq->prBufCtrl->u4BufSize = USB_TX_DATA_BUFF_SIZE; + prUsbReq->prBufCtrl->u4WrIdx = 0; + ++i; + } + + /* TX Data */ +#if CFG_USB_TX_AGG + for (ucTc = 0; ucTc < USB_TC_NUM; ++ucTc) { + /* Only for TC0 ~ TC3 and DBDC1_TC */ + if (ucTc >= TC4_INDEX && ucTc < USB_DBDC1_TC) + continue; + prHifInfo->arTxDataReqHead[ucTc] = glUsbInitQ(prHifInfo, + &prHifInfo->rTxDataFreeQ[ucTc], USB_REQ_TX_DATA_CNT); + i = 0; + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxDataFreeQ[ucTc], list) { + QUEUE_INITIALIZE(&prUsbReq->rSendingDataMsduInfoList); + /* TODO: every endpoint should has an unique and only TC */ + *((uint8_t *)&prUsbReq->prPriv) = ucTc; + prUsbReq->prBufCtrl = &prHifInfo->rTxDataBufCtrl[ucTc][i]; +#if CFG_USB_CONSISTENT_DMA + prUsbReq->prBufCtrl->pucBuf = + usb_alloc_coherent(prHifInfo->udev, USB_TX_DATA_BUFF_SIZE, GFP_ATOMIC, + &prUsbReq->prUrb->transfer_dma); +#else + prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_TX_DATA_BUFF_SIZE, GFP_ATOMIC); +#endif + if (prUsbReq->prBufCtrl->pucBuf == NULL) { + DBGLOG(HAL, ERROR, "kmalloc() reports error\n"); + goto error; + } + prUsbReq->prBufCtrl->u4BufSize = USB_TX_DATA_BUFF_SIZE; + prUsbReq->prBufCtrl->u4WrIdx = 0; + ++i; + } + + DBGLOG(INIT, INFO, "USB Tx URB INIT Tc[%u] cnt[%u] len[%u]\n", ucTc, i, + prHifInfo->rTxDataBufCtrl[ucTc][0].u4BufSize); + } +#else + glUsbInitQ(prHifInfo, &prHifInfo->rTxDataFreeQ, USB_REQ_TX_DATA_CNT); + prUsbReq = list_entry(prHifInfo->rTxDataFreeQ.next, struct USB_REQ, list); + i = 0; + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxDataFreeQ, list) { + QUEUE_INITIALIZE(&prUsbReq->rSendingDataMsduInfoList); + prUsbReq->prBufCtrl = &prHifInfo->rTxDataBufCtrl[i]; +#if CFG_USB_CONSISTENT_DMA + prUsbReq->prBufCtrl->pucBuf = + usb_alloc_coherent(prHifInfo->udev, USB_TX_DATA_BUF_SIZE, GFP_ATOMIC, + &prUsbReq->prUrb->transfer_dma); +#else + prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_TX_DATA_BUF_SIZE, GFP_ATOMIC); +#endif + if (prUsbReq->prBufCtrl->pucBuf == NULL) { + DBGLOG(HAL, ERROR, "kmalloc() reports error\n"); + goto error; + } + prUsbReq->prBufCtrl->u4BufSize = USB_TX_DATA_BUF_SIZE; + ++i; + } +#endif + + glUsbInitQ(prHifInfo, &prHifInfo->rTxCmdCompleteQ, 0); + glUsbInitQ(prHifInfo, &prHifInfo->rTxDataCompleteQ, 0); + + /* RX EVENT */ + prHifInfo->prRxEventReqHead = glUsbInitQ(prHifInfo, &prHifInfo->rRxEventFreeQ, USB_REQ_RX_EVENT_CNT); + i = 0; + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxEventFreeQ, list) { + prUsbReq->prBufCtrl = &prHifInfo->rRxEventBufCtrl[i]; + prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_RX_EVENT_BUF_SIZE, GFP_ATOMIC); + if (prUsbReq->prBufCtrl->pucBuf == NULL) { + DBGLOG(HAL, ERROR, "kmalloc() reports error\n"); + goto error; + } + prUsbReq->prBufCtrl->u4BufSize = USB_RX_EVENT_BUF_SIZE; + prUsbReq->prBufCtrl->u4ReadSize = 0; + ++i; + } + + /* RX Data */ + prHifInfo->prRxDataReqHead = glUsbInitQ(prHifInfo, &prHifInfo->rRxDataFreeQ, USB_REQ_RX_DATA_CNT); + i = 0; + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxDataFreeQ, list) { + prUsbReq->prBufCtrl = &prHifInfo->rRxDataBufCtrl[i]; + prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_RX_DATA_BUF_SIZE, GFP_ATOMIC); + if (prUsbReq->prBufCtrl->pucBuf == NULL) { + DBGLOG(HAL, ERROR, "kmalloc() reports error\n"); + goto error; + } + prUsbReq->prBufCtrl->u4BufSize = USB_RX_DATA_BUF_SIZE; + prUsbReq->prBufCtrl->u4ReadSize = 0; + ++i; + } + + glUsbInitQ(prHifInfo, &prHifInfo->rRxEventCompleteQ, 0); + glUsbInitQ(prHifInfo, &prHifInfo->rRxDataCompleteQ, 0); + + glUsbSetState(prHifInfo, USB_STATE_LINK_UP); + prGlueInfo->u4InfType = MT_DEV_INF_USB; + + return; + +error: + /* TODO */ + ; +} /* end of glSetHifInfo() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function clears hif related info. +* +* \param[in] prGlueInfo Pointer to glue info structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void glClearHifInfo(struct GLUE_INFO *prGlueInfo) +{ + /* struct GL_HIF_INFO *prHifInfo = NULL; */ + /* ASSERT(prGlueInfo); */ + /* prHifInfo = &prGlueInfo->rHifInfo; */ +#if CFG_USB_TX_AGG + uint8_t ucTc; +#endif + struct USB_REQ *prUsbReq, *prUsbReqNext; + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + +#if CFG_USB_TX_AGG + for (ucTc = 0; ucTc < USB_TC_NUM; ++ucTc) { + if (ucTc >= TC4_INDEX && ucTc < USB_DBDC1_TC) + continue; + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxDataFreeQ[ucTc], list) { +#if CFG_USB_CONSISTENT_DMA + usb_free_coherent(prHifInfo->udev, USB_TX_DATA_BUFF_SIZE, + prUsbReq->prBufCtrl->pucBuf, prUsbReq->prUrb->transfer_dma); +#else + kfree(prUsbReq->prBufCtrl->pucBuf); +#endif + usb_free_urb(prUsbReq->prUrb); + } + } +#else + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxDataFreeQ, list) { +#if CFG_USB_CONSISTENT_DMA + usb_free_coherent(prHifInfo->udev, USB_TX_DATA_BUFF_SIZE, + prUsbReq->prBufCtrl->pucBuf, prUsbReq->prUrb->transfer_dma); +#else + kfree(prUsbReq->prBufCtrl->pucBuf); +#endif + usb_free_urb(prUsbReq->prUrb); + } +#endif + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxDataFfaQ, list) { +#if CFG_USB_CONSISTENT_DMA + usb_free_coherent(prHifInfo->udev, USB_TX_DATA_BUFF_SIZE, + prUsbReq->prBufCtrl->pucBuf, prUsbReq->prUrb->transfer_dma); +#else + kfree(prUsbReq->prBufCtrl->pucBuf); +#endif + usb_free_urb(prUsbReq->prUrb); + } + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxCmdFreeQ, list) { +#if CFG_USB_CONSISTENT_DMA + usb_free_coherent(prHifInfo->udev, USB_TX_CMD_BUF_SIZE, + prUsbReq->prBufCtrl->pucBuf, prUsbReq->prUrb->transfer_dma); +#else + kfree(prUsbReq->prBufCtrl->pucBuf); +#endif + usb_free_urb(prUsbReq->prUrb); + } + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxCmdCompleteQ, list) { +#if CFG_USB_CONSISTENT_DMA + usb_free_coherent(prHifInfo->udev, USB_TX_CMD_BUF_SIZE, + prUsbReq->prBufCtrl->pucBuf, prUsbReq->prUrb->transfer_dma); +#else + kfree(prUsbReq->prBufCtrl->pucBuf); +#endif + usb_free_urb(prUsbReq->prUrb); + } + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxDataCompleteQ, list) { +#if CFG_USB_CONSISTENT_DMA + usb_free_coherent(prHifInfo->udev, USB_TX_CMD_BUF_SIZE, + prUsbReq->prBufCtrl->pucBuf, prUsbReq->prUrb->transfer_dma); +#else + kfree(prUsbReq->prBufCtrl->pucBuf); +#endif + usb_free_urb(prUsbReq->prUrb); + } + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxDataFreeQ, list) { + kfree(prUsbReq->prBufCtrl->pucBuf); + usb_free_urb(prUsbReq->prUrb); + } + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxEventFreeQ, list) { + kfree(prUsbReq->prBufCtrl->pucBuf); + usb_free_urb(prUsbReq->prUrb); + } + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxDataCompleteQ, list) { + kfree(prUsbReq->prBufCtrl->pucBuf); + usb_free_urb(prUsbReq->prUrb); + } + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxEventCompleteQ, list) { + kfree(prUsbReq->prBufCtrl->pucBuf); + usb_free_urb(prUsbReq->prUrb); + } + + kfree(prHifInfo->prTxCmdReqHead); + kfree(prHifInfo->arTxDataFfaReqHead); + for (ucTc = 0; ucTc < USB_TC_NUM; ++ucTc) + kfree(prHifInfo->arTxDataReqHead[ucTc]); + kfree(prHifInfo->prRxEventReqHead); + kfree(prHifInfo->prRxDataReqHead); + + mutex_destroy(&prHifInfo->vendor_req_sem); + kfree(prHifInfo->vendor_req_buf); + prHifInfo->vendor_req_buf = NULL; + prHifInfo->vendor_req_buf_sz = 0; +} /* 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 uint32_t type and +* stores a mapped base address. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t glBusInit(void *pvData) +{ + return TRUE; +} /* end of glBusInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus operation and release resources. +* +* \param[in] pvData A pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void glBusRelease(void *pvData) +{ +} /* end of glBusRelease() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setup bus interrupt operation and interrupt handler for os. +* +* \param[in] pvData A pointer to struct net_device. +* \param[in] pfnIsr A pointer to interrupt handler function. +* \param[in] pvCookie Private data for pfnIsr function. +* +* \retval WLAN_STATUS_SUCCESS if success +* NEGATIVE_VALUE if fail +*/ +/*----------------------------------------------------------------------------*/ +int32_t glBusSetIrq(void *pvData, void *pfnIsr, void *pvCookie) +{ + int ret = 0; + + struct net_device *prNetDevice = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct GL_HIF_INFO *prHifInfo = NULL; + + ASSERT(pvData); + if (!pvData) + return -1; + + prNetDevice = (struct net_device *)pvData; + prGlueInfo = (struct GLUE_INFO *) pvCookie; + ASSERT(prGlueInfo); + if (!prGlueInfo) + return -1; + + prHifInfo = &prGlueInfo->rHifInfo; + + 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(void *pvData, void *pvCookie) +{ + struct net_device *prNetDevice = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct GL_HIF_INFO *prHifInfo = NULL; + + ASSERT(pvData); + if (!pvData) { + /* printk(KERN_INFO DRV_NAME"%s null pvData\n", __FUNCTION__); */ + return; + } + prNetDevice = (struct net_device *)pvData; + prGlueInfo = (struct GLUE_INFO *) pvCookie; + ASSERT(prGlueInfo); + if (!prGlueInfo) { + /* printk(KERN_INFO DRV_NAME"%s no glue info\n", __FUNCTION__); */ + return; + } + + prHifInfo = &prGlueInfo->rHifInfo; +} /* end of glBusreeIrq() */ + +u_int8_t glIsReadClearReg(uint32_t u4Address) +{ + switch (u4Address) { + case MCR_WHISR: + case MCR_WASR: + case MCR_D2HRM0R: + case MCR_D2HRM1R: + case MCR_WTQCR0: + case MCR_WTQCR1: + case MCR_WTQCR2: + case MCR_WTQCR3: + case MCR_WTQCR4: + case MCR_WTQCR5: + case MCR_WTQCR6: + case MCR_WTQCR7: + return TRUE; + + default: + return FALSE; + } +} + +uint16_t glGetUsbDeviceVendorId(struct usb_device *dev) +{ + return dev->descriptor.idVendor; +} /* end of glGetUsbDeviceVendorId() */ + +uint16_t glGetUsbDeviceProductId(struct usb_device *dev) +{ + return dev->descriptor.idProduct; +} /* end of glGetUsbDeviceProductId() */ + +int32_t glGetUsbDeviceManufacturerName(struct usb_device *dev, uint8_t *buffer, uint32_t bufLen) +{ + return usb_string(dev, dev->descriptor.iManufacturer, buffer, bufLen); +} /* end of glGetUsbDeviceManufacturerName() */ + +int32_t glGetUsbDeviceProductName(struct usb_device *dev, uint8_t *buffer, uint32_t bufLen) +{ + return usb_string(dev, dev->descriptor.iProduct, buffer, bufLen); +} /* end of glGetUsbDeviceManufacturerName() */ + +int32_t glGetUsbDeviceSerialNumber(struct usb_device *dev, uint8_t *buffer, uint32_t bufLen) +{ + return usb_string(dev, dev->descriptor.iSerialNumber, buffer, bufLen); +} /* end of glGetUsbDeviceSerialNumber() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevRegRead(IN struct GLUE_INFO *prGlueInfo, IN uint32_t u4Register, OUT uint32_t *pu4Value) +{ + struct BUS_INFO *prBusInfo = NULL; + int ret = 0; + uint8_t ucRetryCount = 0; + + ASSERT(prGlueInfo); + ASSERT(pu4Value); + + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + *pu4Value = 0xFFFFFFFF; + + do { + ret = mtk_usb_vendor_request(prGlueInfo, + 0, + prBusInfo->u4device_vender_request_in, + VND_REQ_REG_READ, + (u4Register & 0xffff0000) >> 16, + (u4Register & 0x0000ffff), pu4Value, + sizeof(*pu4Value)); + + if (ret || ucRetryCount) + DBGLOG(HAL, ERROR, + "usb_control_msg() status: %d retry: %u\n", + ret, ucRetryCount); + + + ucRetryCount++; + if (ucRetryCount > HIF_USB_ACCESS_RETRY_LIMIT) + break; + } while (ret); + + if (ret) { + kalSendAeeWarning(HIF_USB_ERR_TITLE_STR, + HIF_USB_ERR_DESC_STR "USB() reports error: %x retry: %u", ret, ucRetryCount); + DBGLOG(HAL, ERROR, "usb_readl() reports error: %x retry: %u\n", ret, ucRetryCount); + } else { + DBGLOG(HAL, TRACE, "Get CR[0x%08x] value[0x%08x]\n", + u4Register, *pu4Value); + } + + 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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevRegWrite(IN struct GLUE_INFO *prGlueInfo, IN uint32_t u4Register, IN uint32_t u4Value) +{ + int ret = 0; + uint8_t ucRetryCount = 0; + struct BUS_INFO *prBusInfo = NULL; + + ASSERT(prGlueInfo); + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + do { + ret = mtk_usb_vendor_request(prGlueInfo, + 0, + prBusInfo->u4device_vender_request_out, + VND_REQ_REG_WRITE, + (u4Register & 0xffff0000) >> 16, + (u4Register & 0x0000ffff), + &u4Value, + sizeof(u4Value)); + + if (ret || ucRetryCount) + DBGLOG(HAL, ERROR, + "usb_control_msg() status: %d retry: %u\n", + ret, ucRetryCount); + + ucRetryCount++; + if (ucRetryCount > HIF_USB_ACCESS_RETRY_LIMIT) + break; + + } while (ret); + + if (ret) { + kalSendAeeWarning(HIF_USB_ERR_TITLE_STR, + HIF_USB_ERR_DESC_STR "usb_writel() reports error: %x retry: %u", ret, ucRetryCount); + DBGLOG(HAL, ERROR, "usb_writel() reports error: %x retry: %u\n", ret, ucRetryCount); + } else { + DBGLOG(HAL, INFO, "Set CR[0x%08x] value[0x%08x]\n", u4Register, u4Value); + } + + 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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t +kalDevPortRead(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port, IN uint32_t u4Len, OUT uint8_t *pucBuf, IN uint32_t u4ValidOutBufSize) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + uint8_t *pucDst = NULL; + /* int count = u4Len; */ + int ret = 0; + /* int bNum = 0; */ + +#if DBG + DBGLOG(HAL, INFO, "++kalDevPortRead++ buf:0x%p, port:0x%x, length:%d\n", pucBuf, u2Port, u4Len); +#endif + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + ASSERT(pucBuf); + pucDst = pucBuf; + + ASSERT(u4Len <= u4ValidOutBufSize); + + u2Port &= MTK_USB_PORT_MASK; + if (prGlueInfo->rHifInfo.eEventEpType == EVENT_EP_TYPE_INTR && + u2Port == (USB_EVENT_EP_IN & USB_ENDPOINT_NUMBER_MASK)) { + /* maximize buff len for usb in */ + ret = mtk_usb_intr_in_msg(&prGlueInfo->rHifInfo, u4ValidOutBufSize, pucDst, u2Port); + if (ret != u4Len) { + DBGLOG(HAL, WARN, "usb_interrupt_msg(IN=%d) Warning. Data is not completed. (receive %d/%u)\n", + u2Port, ret, u4Len); + } + ret = ret >= 0 ? 0 : ret; + } else if (u2Port >= MTK_USB_BULK_IN_MIN_EP && u2Port <= MTK_USB_BULK_IN_MAX_EP) { + /* maximize buff len for usb in */ + ret = mtk_usb_bulk_in_msg(&prGlueInfo->rHifInfo, u4ValidOutBufSize, pucDst, u2Port); + if (ret != u4Len) { + DBGLOG(HAL, WARN, "usb_bulk_msg(IN=%d) Warning. Data is not completed. (receive %d/%u)\n", + u2Port, ret, u4Len); + } + ret = ret >= 0 ? 0 : ret; + } else { + DBGLOG(HAL, ERROR, "kalDevPortRead reports error: invalid port %x\n", u2Port); + ret = -EINVAL; + } + + if (ret) { + kalSendAeeWarning(HIF_USB_ERR_TITLE_STR, HIF_USB_ERR_DESC_STR "usb_readsb() reports error: %x", ret); + DBGLOG(HAL, ERROR, "usb_readsb() reports error: %x\n", 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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t +kalDevPortWrite(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port, IN uint32_t u4Len, IN uint8_t *pucBuf, IN uint32_t u4ValidInBufSize) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + uint8_t *pucSrc = NULL; + /* int count = u4Len; */ + int ret = 0; + /* int bNum = 0; */ + +#if DBG + DBGLOG(HAL, INFO, "++kalDevPortWrite++ buf:0x%p, port:0x%x, length:%d\n", pucBuf, u2Port, u4Len); +#endif + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + ASSERT(pucBuf); + pucSrc = pucBuf; + + ASSERT((u4Len + LEN_USB_UDMA_TX_TERMINATOR) <= u4ValidInBufSize); + + kalMemZero(pucSrc + u4Len, LEN_USB_UDMA_TX_TERMINATOR); + u4Len += LEN_USB_UDMA_TX_TERMINATOR; + + u2Port &= MTK_USB_PORT_MASK; + if (u2Port >= MTK_USB_BULK_OUT_MIN_EP && u2Port <= MTK_USB_BULK_OUT_MAX_EP) { + ret = mtk_usb_bulk_out_msg(&prGlueInfo->rHifInfo, u4Len, pucSrc, u2Port/*8*/); + if (ret != u4Len) { + DBGLOG(HAL, WARN, "usb_bulk_msg(OUT=%d) Warning. Data is not completed. (receive %d/%u)\n", + u2Port, ret, u4Len); + } + ret = ret >= 0 ? 0 : ret; + } else { + DBGLOG(HAL, ERROR, "kalDevPortWrite reports error: invalid port %x\n", u2Port); + ret = -EINVAL; + } + + if (ret) { + kalSendAeeWarning(HIF_USB_ERR_TITLE_STR, HIF_USB_ERR_DESC_STR "usb_writesb() reports error: %x", ret); + DBGLOG(HAL, ERROR, "usb_writesb() reports error: %x\n", ret); + } + + return (ret) ? FALSE : TRUE; +} /* end of kalDevPortWrite() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set power state +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] ePowerMode +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void glSetPowerState(IN struct GLUE_INFO *prGlueInfo, IN uint32_t ePowerMode) +{ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write data to device +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] prMsduInfo msdu info +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevWriteData(IN struct GLUE_INFO *prGlueInfo, IN struct MSDU_INFO *prMsduInfo) +{ + halTxUSBSendData(prGlueInfo, prMsduInfo); + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Kick Tx data to device +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevKickData(IN struct GLUE_INFO *prGlueInfo) +{ +#if 0 + halTxUSBKickData(prGlueInfo); +#endif + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write command to device +* +* \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 +*/ +/*----------------------------------------------------------------------------*/ +enum ENUM_CMD_TX_RESULT kalDevWriteCmd(IN struct GLUE_INFO *prGlueInfo, + IN struct CMD_INFO *prCmdInfo, IN uint8_t ucTC) +{ + halTxUSBSendCmd(prGlueInfo, ucTC, prCmdInfo); + return CMD_TX_RESULT_SUCCESS; +} + +void glGetDev(void *ctx, struct device **dev) +{ + struct usb_interface *prUsbIntf = (struct usb_interface *) ctx; + struct usb_device *prUsbDev = interface_to_usbdev(prUsbIntf); + + *dev = &prUsbDev->dev; +} + +void glGetHifDev(struct GL_HIF_INFO *prHif, struct device **dev) +{ + *dev = &(prHif->udev->dev); +} + +#if CFG_CHIP_RESET_SUPPORT +void kalRemoveProbe(IN struct GLUE_INFO *prGlueInfo) +{ + DBGLOG(INIT, WARN, "[SER][L0] not support..\n"); +} +#endif + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_ate_agent.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_ate_agent.h new file mode 100644 index 0000000000000..afa0f148e2542 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_ate_agent.h @@ -0,0 +1,300 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/*! \file gl_ate_agent.h + * \brief This file includes private ioctl support. + */ + +#ifndef _GL_ATE_AGENT_H +#define _GL_ATE_AGENT_H +#if CFG_SUPPORT_QA_TOOL +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ + +extern uint32_t u4RxStatSeqNum; + +#if CFG_SUPPORT_TX_BF +extern union PFMU_PROFILE_TAG1 g_rPfmuTag1; +extern union PFMU_PROFILE_TAG2 g_rPfmuTag2; +extern union PFMU_DATA g_rPfmuData; +#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 + ******************************************************************************* + */ + +struct STA_REC_BF_UPD_ARGUMENT { + uint32_t u4WlanId; + uint32_t u4BssId; + uint32_t u4PfmuId; + uint32_t u4SuMu; + uint32_t u4eTxBfCap; + uint32_t u4NdpaRate; + uint32_t u4NdpRate; + uint32_t u4ReptPollRate; + uint32_t u4TxMode; + uint32_t u4Nc; + uint32_t u4Nr; + uint32_t u4Bw; + uint32_t u4SpeIdx; + uint32_t u4TotalMemReq; + uint32_t u4MemReq20M; + uint32_t au4MemRow[4]; + uint32_t au4MemCol[4]; +}; + +struct ATE_OPS_T { + int32_t (*setICapStart)(struct GLUE_INFO *prGlueInfo, + uint32_t fgTrigger, + uint32_t fgRingCapEn, + uint32_t u4Event, + uint32_t u4Node, + uint32_t u4Len, + uint32_t u4StopCycle, + uint32_t u4BW, + uint32_t u4MACTriggerEvent, + uint32_t u4SourceAddrLSB, + uint32_t u4SourceAddrMSB, + uint32_t u4Band); + int32_t (*getICapStatus)(struct GLUE_INFO *prGlueInfo); + int32_t (*getICapIQData)(struct GLUE_INFO *prGlueInfo, + uint8_t *pData, + uint32_t u4IQType, + uint32_t u4WFNum); + void (*getRbistDataDumpEvent)(struct ADAPTER *prAdapter, + uint8_t *pucEventBuf); + void (*icapRiseVcoreClockRate)(void); + void (*icapDownVcoreClockRate)(void); +}; + + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +int Set_ResetStatCounter_Proc(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATE(struct net_device *prNetDev, uint8_t *prInBuf); +int SetATEDa(struct net_device *prNetDev, uint8_t *prInBuf); +int SetATESa(struct net_device *prNetDev, uint8_t *prInBuf); +int SetATEChannel(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATETxPower0(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATETxGi(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATETxBw(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATETxMode(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATETxLength(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATETxCount(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATETxMcs(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATEIpg(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATETxVhtNss(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATETxPath(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATERxPath(struct net_device *prNetDev, + uint8_t *prInBuf); +#if CFG_SUPPORT_ANT_SWAP +int SetATEAntSwp(struct net_device *prNetDev, + uint8_t *prInBuf); +#endif + +#if CFG_SUPPORT_TX_BF +int Set_TxBfProfileTag_Help(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_InValid(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_PfmuIdx(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_BfType(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_DBW(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_SuMu(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_Mem(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_Matrix(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_SNR(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_SmartAnt(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_SeIdx(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_RmsdThrd(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_McsThrd(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_TimeOut(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_DesiredBW(struct net_device + *prNetDev, uint8_t *prInBuf); +int Set_TxBfProfileTag_DesiredNc(struct net_device + *prNetDev, uint8_t *prInBuf); +int Set_TxBfProfileTag_DesiredNr(struct net_device + *prNetDev, uint8_t *prInBuf); +int Set_TxBfProfileTagRead(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTagWrite(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_StaRecCmmUpdate(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_StaRecBfUpdate(struct net_device *prNetDev, + uint8_t *prInBuf); + +int Set_DevInfoUpdate(struct net_device *prNetDev, + uint8_t *prInBuf); + +int Set_BssInfoUpdate(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileDataRead(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileDataWrite(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_Trigger_Sounding_Proc(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_Stop_Sounding_Proc(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfTxApply(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfilePnRead(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfilePnWrite(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfManualAssoc(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfPfmuMemAlloc(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfPfmuMemRelease(struct net_device *prNetDev, + uint8_t *prInBuf); + +#if CFG_SUPPORT_MU_MIMO +int Set_MUGetInitMCS(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUCalInitMCS(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUCalLQ(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUGetLQ(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUSetSNROffset(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUSetZeroNss(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUSetSpeedUpLQ(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUSetMUTable(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUSetGroup(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUGetQD(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUSetEnable(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUSetGID_UP(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUTriggerTx(struct net_device *prNetDev, + uint8_t *prInBuf); +#endif + +#if CFG_SUPPORT_TX_BF_FPGA +int Set_TxBfProfileSwTagWrite(struct net_device *prNetDev, + uint8_t *prInBuf); +#endif +#endif + + +int WriteEfuse(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetTxTargetPower(struct net_device *prNetDev, + uint8_t *prInBuf); + +#if (CFG_SUPPORT_DFS_MASTER == 1) +int SetRddReport(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetByPassCac(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetRadarDetectMode(struct net_device *prNetDev, + uint8_t *prInBuf); +#endif + +int AteCmdSetHandle(struct net_device *prNetDev, + uint8_t *prInBuf, uint32_t u4InBufLen); + +#endif /*CFG_SUPPORT_QA_TOOL */ +#endif /* _GL_ATE_AGENT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_cfg80211.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_cfg80211.h new file mode 100644 index 0000000000000..9b428bb8dec07 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_cfg80211.h @@ -0,0 +1,779 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** 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. + */ + + +#ifndef _GL_CFG80211_H +#define _GL_CFG80211_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include +#include +#include +#include +#include + +#include "gl_os.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#ifdef CONFIG_NL80211_TESTMODE +#define NL80211_DRIVER_TESTMODE_VERSION 2 +#endif + +#if KERNEL_VERSION(4, 19, 0) > CFG80211_VERSION_CODE +#define NL80211_EXT_FEATURE_LOW_SPAN_SCAN 22 +#define NL80211_SCAN_FLAG_LOW_SPAN (1 << 8) +#endif + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +#ifdef CONFIG_NL80211_TESTMODE +#if CFG_SUPPORT_NFC_BEAM_PLUS + +struct NL80211_DRIVER_SET_NFC_PARAMS { + struct NL80211_DRIVER_TEST_MODE_PARAMS hdr; + uint32_t NFC_Enable; + +}; + +#endif + + + +struct NL80211_DRIVER_GET_STA_STATISTICS_PARAMS { + struct NL80211_DRIVER_TEST_MODE_PARAMS hdr; + uint32_t u4Version; + uint32_t u4Flag; + uint8_t aucMacAddr[MAC_ADDR_LEN]; +}; + +enum _ENUM_TESTMODE_LINK_DETECTION_ATTR { + NL80211_TESTMODE_LINK_INVALID = 0, + NL80211_TESTMODE_LINK_TX_FAIL_CNT, + NL80211_TESTMODE_LINK_TX_RETRY_CNT, + NL80211_TESTMODE_LINK_TX_MULTI_RETRY_CNT, + NL80211_TESTMODE_LINK_ACK_FAIL_CNT, + NL80211_TESTMODE_LINK_FCS_ERR_CNT, + NL80211_TESTMODE_LINK_TX_CNT, + NL80211_TESTMODE_LINK_RX_CNT, + NL80211_TESTMODE_LINK_RST_REASON, + NL80211_TESTMODE_LINK_RST_TIME, + NL80211_TESTMODE_LINK_ROAM_FAIL_TIMES, + NL80211_TESTMODE_LINK_ROAM_FAIL_TIME, + NL80211_TESTMODE_LINK_TX_DONE_DELAY_IS_ARP, + NL80211_TESTMODE_LINK_ARRIVE_DRV_TICK, + NL80211_TESTMODE_LINK_ENQUE_TICK, + NL80211_TESTMODE_LINK_DEQUE_TICK, + NL80211_TESTMODE_LINK_LEAVE_DRV_TICK, + NL80211_TESTMODE_LINK_CURR_TICK, + NL80211_TESTMODE_LINK_CURR_TIME, + + NL80211_TESTMODE_LINK_DETECT_NUM +}; + +enum ENUM_TESTMODE_STA_STATISTICS_ATTR { + NL80211_TESTMODE_STA_STATISTICS_INVALID = 0, + NL80211_TESTMODE_STA_STATISTICS_VERSION, + NL80211_TESTMODE_STA_STATISTICS_MAC, + NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE, + NL80211_TESTMODE_STA_STATISTICS_FLAG, + + NL80211_TESTMODE_STA_STATISTICS_PER, + NL80211_TESTMODE_STA_STATISTICS_RSSI, + NL80211_TESTMODE_STA_STATISTICS_PHY_MODE, + NL80211_TESTMODE_STA_STATISTICS_TX_RATE, + + NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT, + NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT, + + NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME, + NL80211_TESTMODE_STA_STATISTICS_MAX_PROCESS_TIME, + NL80211_TESTMODE_STA_STATISTICS_AVG_HIF_PROCESS_TIME, + NL80211_TESTMODE_STA_STATISTICS_MAX_HIF_PROCESS_TIME, + + NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT, + NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT, + NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME, + + NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY, + + /* + * how many packages TX during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_ENQUEUE, + + /* + * how many packages this TX during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_STA_ENQUEUE, + + /* + * how many packages dequeue during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_DEQUEUE, + + /* + * how many packages this sta dequeue during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_STA_DEQUEUE, + + /* + * how many TC[0-3] resource back from firmware during + * statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_RB_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_NO_TC_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_USED_TC_PGCT_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_WANTED_TC_PGCT_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_PASS_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_TASK_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_AB_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_SW_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_TX_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_RX_CNT, + + NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_NUM +}; +#endif +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +/* cfg80211 hooks */ +int +mtk_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, enum nl80211_iftype type, + u32 *flags, struct vif_params *params); + +int +mtk_cfg80211_add_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, bool pairwise, const u8 *mac_addr, + struct key_params *params); + +int +mtk_cfg80211_get_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, + bool pairwise, + const u8 *mac_addr, void *cookie, + void (*callback)(void *cookie, struct key_params *)); + +int +mtk_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_index, + bool pairwise, const u8 *mac_addr); + +int +mtk_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *ndev, + u8 key_index, bool unicast, bool multicast); + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *ndev, const u8 *mac, + struct station_info *sinfo); +#else +int mtk_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac, + struct station_info *sinfo); +#endif + +int +mtk_cfg80211_get_link_statistics(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac, + struct station_info *sinfo); + +int mtk_cfg80211_scan(struct wiphy *wiphy, + struct cfg80211_scan_request *request); + +void mtk_cfg80211_abort_scan(struct wiphy *wiphy, + struct wireless_dev *wdev); + +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_set_rekey_data(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_gtk_rekey_data *data); + +int mtk_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, struct ieee80211_channel *chan, + unsigned int duration, u64 *cookie); + +int mtk_cfg80211_cancel_remain_on_channel( + struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie); + +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie); +#else +int mtk_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *channel, bool offscan, + unsigned int wait, + const u8 *buf, size_t len, bool no_cck, + bool dont_wait_for_ack, u64 *cookie); +#endif + +void mtk_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, + IN struct wireless_dev *wdev, IN u16 frame_type, IN bool reg); + +int mtk_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct wireless_dev *wdev, u64 cookie); + +#ifdef CONFIG_NL80211_TESTMODE +int +mtk_cfg80211_testmode_get_sta_statistics(IN struct wiphy + *wiphy, + IN void *data, IN int len, IN struct GLUE_INFO *prGlueInfo); + +int mtk_cfg80211_testmode_get_scan_done(IN struct wiphy + *wiphy, IN void *data, IN int len, + IN struct GLUE_INFO *prGlueInfo); + +#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_testmode_cmd(struct wiphy *wiphy, + struct wireless_dev *wdev, + void *data, int len); +#else +int mtk_cfg80211_testmode_cmd(struct wiphy *wiphy, + struct wireless_dev *wdev, + void *data, int len); +#endif + +int mtk_cfg80211_testmode_sw_cmd(IN struct wiphy *wiphy, + IN struct wireless_dev *wdev, + IN void *data, IN int len); + +#if CFG_SUPPORT_PASSPOINT +int mtk_cfg80211_testmode_hs20_cmd(IN struct wiphy *wiphy, + IN struct wireless_dev *wdev, + IN void *data, IN int len); +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_WAPI +int mtk_cfg80211_testmode_set_key_ext(IN struct wiphy + *wiphy, + IN struct wireless_dev *wdev, + IN void *data, IN int len); +#endif +#if CFG_SUPPORT_NFC_BEAM_PLUS +int mtk_cfg80211_testmode_get_scan_done(IN struct wiphy *wiphy, + IN void *data, IN int len, IN struct GLUE_INFO *prGlueInfo); +#endif +#else +/* IGNORE KERNEL DEPENCY ERRORS */ +/* #error "Please ENABLE kernel config (CONFIG_NL80211_TESTMODE) to support + * Wi-Fi Direct" + */ +#endif + +#if CFG_SUPPORT_SCHED_SCAN +int +mtk_cfg80211_sched_scan_start(IN struct wiphy *wiphy, + IN struct net_device *ndev, + IN struct cfg80211_sched_scan_request *request); + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_sched_scan_stop(IN struct wiphy *wiphy, + IN struct net_device *ndev, + IN u64 reqid); +#else +int mtk_cfg80211_sched_scan_stop(IN struct wiphy *wiphy, + IN struct net_device *ndev); +#endif +#endif /* CFG_SUPPORT_SCHED_SCAN */ + +int mtk_cfg80211_assoc(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_assoc_request *req); + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int +mtk_cfg80211_change_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, struct station_parameters *params); + +int mtk_cfg80211_add_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, struct station_parameters *params); + +#if KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *ndev, + struct station_del_parameters *params); +#else +int mtk_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac); +#endif +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, + bool initiator, const u8 *buf, size_t len); +#else +int mtk_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, + const u8 *buf, size_t len); +#endif + +int mtk_cfg80211_tdls_oper(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, enum nl80211_tdls_operation oper); +#else +int +mtk_cfg80211_change_station(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac, + struct station_parameters *params); + +int mtk_cfg80211_add_station(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac, + struct station_parameters *params); + +int mtk_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac); + +int +mtk_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + u8 *peer, u8 action_code, + u8 dialog_token, u16 status_code, + const u8 *buf, size_t len); + +int mtk_cfg80211_tdls_oper(struct wiphy *wiphy, + struct net_device *dev, u8 *peer, + enum nl80211_tdls_operation oper); +#endif + +int32_t mtk_cfg80211_process_str_cmd(struct wiphy *wiphy, + struct wireless_dev *wdev, + uint8_t *cmd, int32_t len); + +int32_t mtk_cfg80211_process_str_cmd_reply( + IN struct wiphy *wiphy, IN char *data, IN int len); + +void mtk_reg_notify(IN struct wiphy *pWiphy, + IN struct regulatory_request *pRequest); +void cfg80211_regd_set_wiphy(IN struct wiphy *pWiphy); + +int mtk_cfg80211_suspend(struct wiphy *wiphy, + struct cfg80211_wowlan *wow); + +int mtk_cfg80211_resume(struct wiphy *wiphy); + +/* cfg80211 wrapper hooks */ +#if CFG_ENABLE_UNIFY_WIPHY +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +struct wireless_dev *mtk_cfg_add_iface(struct wiphy *wiphy, + const char *name, + unsigned char name_assign_type, + enum nl80211_iftype type, + struct vif_params *params); +#elif KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE +struct wireless_dev *mtk_cfg_add_iface(struct wiphy *wiphy, + const char *name, + unsigned char name_assign_type, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params); +#else +struct wireless_dev *mtk_cfg_add_iface(struct wiphy *wiphy, + const char *name, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params); +#endif +int mtk_cfg_del_iface(struct wiphy *wiphy, + struct wireless_dev *wdev); +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_change_iface(struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type, + struct vif_params *params); +#else +int mtk_cfg_change_iface(struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params); +#endif +int mtk_cfg_add_key(struct wiphy *wiphy, + struct net_device *ndev, u8 key_index, + bool pairwise, const u8 *mac_addr, + struct key_params *params); +int mtk_cfg_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_cfg_del_key(struct wiphy *wiphy, + struct net_device *ndev, u8 key_index, + bool pairwise, const u8 *mac_addr); +int mtk_cfg_set_default_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, bool unicast, bool multicast); + +int mtk_cfg_set_default_mgmt_key(struct wiphy *wiphy, + struct net_device *ndev, u8 key_index); + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_get_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, struct station_info *sinfo); +#else +int mtk_cfg_get_station(struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, struct station_info *sinfo); +#endif + +#if CFG_SUPPORT_TDLS +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_change_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, struct station_parameters *params); +#else +int mtk_cfg_change_station(struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, struct station_parameters *params); +#endif +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_add_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, struct station_parameters *params); +#else +int mtk_cfg_add_station(struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, struct station_parameters *params); +#endif +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_tdls_oper(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *peer, enum nl80211_tdls_operation oper); +#else +int mtk_cfg_tdls_oper(struct wiphy *wiphy, + struct net_device *ndev, + u8 *peer, enum nl80211_tdls_operation oper); +#endif +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_tdls_mgmt(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, + u32 peer_capability, bool initiator, const u8 *buf, + size_t len); +#elif KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_tdls_mgmt(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, + u32 peer_capability, const u8 *buf, size_t len); +#else +int mtk_cfg_tdls_mgmt(struct wiphy *wiphy, + struct net_device *ndev, + u8 *peer, u8 action_code, + u8 dialog_token, u16 status_code, + const u8 *buf, size_t len); +#endif +#endif /* CFG_SUPPORT_TDLS */ + +#if KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_del_station(struct wiphy *wiphy, + struct net_device *ndev, + struct station_del_parameters *params); +#elif KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_del_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac); +#else +int mtk_cfg_del_station(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac); +#endif +int mtk_cfg_scan(struct wiphy *wiphy, + struct cfg80211_scan_request *request); +#if KERNEL_VERSION(4, 5, 0) <= CFG80211_VERSION_CODE +void mtk_cfg_abort_scan(struct wiphy *wiphy, + struct wireless_dev *wdev); +#endif + +#if CFG_SUPPORT_SCHED_SCAN +int mtk_cfg_sched_scan_start(IN struct wiphy *wiphy, + IN struct net_device *ndev, + IN struct cfg80211_sched_scan_request *request); + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_sched_scan_stop(IN struct wiphy *wiphy, + IN struct net_device *ndev, + IN u64 reqid); +#else +int mtk_cfg_sched_scan_stop(IN struct wiphy *wiphy, + IN struct net_device *ndev); +#endif + +#endif /* CFG_SUPPORT_SCHED_SCAN */ + +int mtk_cfg_connect(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_connect_params *sme); +int mtk_cfg_disconnect(struct wiphy *wiphy, + struct net_device *ndev, + u16 reason_code); +int mtk_cfg_join_ibss(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_ibss_params *params); +int mtk_cfg_leave_ibss(struct wiphy *wiphy, + struct net_device *ndev); +int mtk_cfg_set_power_mgmt(struct wiphy *wiphy, + struct net_device *ndev, + bool enabled, int timeout); +int mtk_cfg_set_pmksa(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_pmksa *pmksa); +int mtk_cfg_del_pmksa(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_pmksa *pmksa); +int mtk_cfg_flush_pmksa(struct wiphy *wiphy, + struct net_device *ndev); +#if CONFIG_SUPPORT_GTK_REKEY +int mtk_cfg_set_rekey_data(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_gtk_rekey_data *data); +#endif /* CONFIG_SUPPORT_GTK_REKEY */ +int mtk_cfg_suspend(struct wiphy *wiphy, + struct cfg80211_wowlan *wow); +int mtk_cfg_resume(struct wiphy *wiphy); +int mtk_cfg_assoc(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_assoc_request *req); +int mtk_cfg_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, + unsigned int duration, + u64 *cookie); +int mtk_cfg_cancel_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, u64 cookie); +uint16_t cfg80211_get_non_wfa_vendor_ie( + struct GLUE_INFO *prGlueInfo, + uint8_t *ies, int32_t len, + uint8_t ucBssIndex); + +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, u64 *cookie); +#else +int mtk_cfg_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *channel, bool offscan, + unsigned int wait, + const u8 *buf, size_t len, bool no_cck, + bool dont_wait_for_ack, + u64 *cookie); +#endif +void mtk_cfg_mgmt_frame_register(struct wiphy *wiphy, + struct wireless_dev *wdev, + u16 frame_type, bool reg); + +#ifdef CONFIG_NL80211_TESTMODE +#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_testmode_cmd(struct wiphy *wiphy, + struct wireless_dev *wdev, + void *data, int len); +#else +int mtk_cfg_testmode_cmd(struct wiphy *wiphy, void *data, + int len); +#endif +#endif /* CONFIG_NL80211_TESTMODE */ + +#if (CFG_SUPPORT_DFS_MASTER == 1) +#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_start_radar_detection(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef, + unsigned int cac_time_ms); +#else +int mtk_cfg_start_radar_detection(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef); +#endif + + +#if KERNEL_VERSION(3, 13, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_channel_switch(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_csa_settings *params); +#endif +#endif + + +#if (CFG_ENABLE_WIFI_DIRECT_CFG_80211 != 0) +int mtk_cfg_change_bss(struct wiphy *wiphy, + struct net_device *dev, + struct bss_parameters *params); +int mtk_cfg_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie); +int mtk_cfg_deauth(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_deauth_request *req); +int mtk_cfg_disassoc(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_disassoc_request *req); +int mtk_cfg_start_ap(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ap_settings *settings); +int mtk_cfg_change_beacon(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_beacon_data *info); +int mtk_cfg_stop_ap(struct wiphy *wiphy, + struct net_device *dev); +int mtk_cfg_set_wiphy_params(struct wiphy *wiphy, + u32 changed); +int mtk_cfg_set_bitrate_mask(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, + const struct cfg80211_bitrate_mask *mask); +int mtk_cfg_set_txpower(struct wiphy *wiphy, + struct wireless_dev *wdev, + enum nl80211_tx_power_setting type, int mbm); +int mtk_cfg_get_txpower(struct wiphy *wiphy, + struct wireless_dev *wdev, + int *dbm); +#endif /* (CFG_ENABLE_WIFI_DIRECT_CFG_80211 != 0) */ + +#endif /* CFG_ENABLE_UNIFY_WIPHY */ + +int mtk_cfg80211_update_ft_ies(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_update_ft_ies_params *ftie); + +#if CFG_SUPPORT_WPA3 +int mtk_cfg80211_external_auth(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_external_auth_params *params); +#endif + +int mtk_IsP2PNetDevice(struct GLUE_INFO *prGlueInfo, + struct net_device *ndev); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _GL_CFG80211_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_hook_api.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_hook_api.h new file mode 100644 index 0000000000000..71ff629fc214e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_hook_api.h @@ -0,0 +1,353 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/*! \file gl_hook_api.h + * \brief This file includes private ioctl support. + */ + +#ifndef _GL_HOOK_API_H +#define _GL_HOOK_API_H +#if CFG_SUPPORT_QA_TOOL +/******************************************************************************* + * C O M P I L E 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 + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +int32_t MT_ATEStart(struct net_device *prNetDev, + uint8_t *prInBuf); +int32_t MT_ICAPStart(struct net_device *prNetDev, + uint8_t *prInBuf); +int32_t MT_ICAPCommand(struct net_device *prNetDev, + uint8_t *prInBuf); +int32_t MT_ATEStop(struct net_device *prNetDev, + uint8_t *prInBuf); +int32_t MT_ATEStartTX(struct net_device *prNetDev, + uint8_t *prInBuf); +int32_t MT_ATEStopTX(struct net_device *prNetDev, + uint8_t *prInBuf); +int32_t MT_ATEStartRX(struct net_device *prNetDev, + uint8_t *prInBuf); +int32_t MT_ATEStopRX(struct net_device *prNetDev, + uint8_t *prInBuf); +int32_t MT_ATESetChannel(struct net_device *prNetDev, + uint32_t u4SXIdx, uint32_t u4SetFreq); +int32_t MT_ATESetPreamble(struct net_device *prNetDev, + uint32_t u4Mode); +int32_t MT_ATESetSystemBW(struct net_device *prNetDev, + uint32_t u4BW); +int32_t MT_ATESetTxLength(struct net_device *prNetDev, + uint32_t u4TxLength); +int32_t MT_ATESetTxCount(struct net_device *prNetDev, + uint32_t u4TxCount); +int32_t MT_ATESetTxIPG(struct net_device *prNetDev, + uint32_t u4TxIPG); +int32_t MT_ATESetTxPath(struct net_device *prNetDev, + uint32_t u4Tx_path); +int32_t MT_ATESetRxPath(struct net_device *prNetDev, + uint32_t u4Rx_path); +int32_t MT_ATESetTxPower0(struct net_device *prNetDev, + uint32_t u4TxPower0); +int32_t MT_ATESetPerPacketBW(struct net_device *prNetDev, + uint32_t u4BW); +int32_t MT_ATEPrimarySetting(struct net_device *prNetDev, + uint32_t u4PrimaryCh); +int32_t MT_ATESetTxGi(struct net_device *prNetDev, + uint32_t u4SetTxGi); +int32_t MT_ATESetTxPayLoad(struct net_device *prNetDev, + uint32_t u4Gen_payload_rule, uint8_t ucPayload); +int32_t MT_ATESetTxSTBC(struct net_device *prNetDev, + uint32_t u4Stbc); +int32_t MT_ATESetTxPath(struct net_device *prNetDev, + uint32_t u4Tx_path); +int32_t MT_ATESetTxVhtNss(struct net_device *prNetDev, + uint32_t u4VhtNss); +int32_t MT_ATESetRate(struct net_device *prNetDev, + uint32_t u4Rate); +int32_t MT_ATESetEncodeMode(struct net_device *prNetDev, + uint32_t u4Ldpc); +int32_t MT_ATESetiBFEnable(struct net_device *prNetDev, + uint32_t u4iBF); +int32_t MT_ATESeteBFEnable(struct net_device *prNetDev, + uint32_t u4eBF); +int32_t MT_ATESetMACAddress(struct net_device *prNetDev, + uint32_t u4Type, uint8_t ucAddr[]); +int32_t MT_ATELogOnOff(struct net_device *prNetDev, + uint32_t u4Type, uint32_t u4On_off, uint32_t u4Size); +int32_t MT_ATEGetDumpRXV(struct net_device *prNetDev, + uint8_t *pData, int32_t *pCount); +int32_t MT_ATEResetTXRXCounter(struct net_device *prNetDev); +int32_t MT_ATESetDBDCBandIndex(struct net_device *prNetDev, + uint32_t u4BandIdx); +int32_t MT_ATESetBand(struct net_device *prNetDev, + int32_t i4Band); +int32_t MT_ATESetTxToneType(struct net_device *prNetDev, + int32_t i4ToneType); +int32_t MT_ATESetTxToneBW(struct net_device *prNetDev, + int32_t i4ToneFreq); +int32_t MT_ATESetTxToneDCOffset(struct net_device *prNetDev, + int32_t i4DcOffsetI, int32_t i4DcOffsetQ); +int32_t MT_ATESetDBDCTxTonePower(struct net_device *prNetDev, + int32_t i4AntIndex, int32_t i4RF_Power, int32_t i4Digi_Power); +int32_t MT_ATEDBDCTxTone(struct net_device *prNetDev, + int32_t i4Control); +int32_t MT_ATESetMacHeader(struct net_device *prNetDev, + uint32_t u2FrameCtrl, uint32_t u2DurationID, + uint32_t u4SeqCtrl); +int32_t MT_ATE_IRRSetADC(struct net_device *prNetDev, + uint32_t u4WFIdx, + uint32_t u4ChFreq, + uint32_t u4BW, uint32_t u4Sx, uint32_t u4Band, + uint32_t u4RunType, uint32_t u4FType); +int32_t MT_ATE_IRRSetRxGain(struct net_device *prNetDev, + uint32_t u4PgaLpfg, uint32_t u4Lna, uint32_t u4Band, + uint32_t u4WF_inx, uint32_t u4Rfdgc); +int32_t MT_ATE_IRRSetTTG(struct net_device *prNetDev, + uint32_t u4TTGPwrIdx, uint32_t u4ChFreq, + uint32_t u4FIToneFreq, uint32_t u4Band); +int32_t MT_ATE_IRRSetTrunOnTTG(struct net_device *prNetDev, uint32_t u4TTGOnOff, + uint32_t u4Band, uint32_t u4WF_inx); +int32_t MT_ATE_TMRSetting(struct net_device *prNetDev, uint32_t u4Setting, + uint32_t u4Version, uint32_t u4MPThres, uint32_t u4MPIter); +int32_t MT_ATERDDStart(struct net_device *prNetDev, + uint8_t *prInBuf); +int32_t MT_ATERDDStop(struct net_device *prNetDev, + uint8_t *prInBuf); +int32_t MT_ATEMPSSetSeqData(struct net_device *prNetDev, uint32_t u4TestNum, + uint32_t *pu4Phy, uint32_t u4Band); +int32_t MT_ATEMPSSetPayloadLength(struct net_device *prNetDev, + uint32_t u4TestNum, uint32_t *pu4Length, uint32_t u4Band); +int32_t MT_ATEMPSSetPacketCount(struct net_device *prNetDev, uint32_t u4TestNum, + uint32_t *pu4PktCnt, uint32_t u4Band); +int32_t MT_ATEMPSSetPowerGain(struct net_device *prNetDev, uint32_t u4TestNum, + uint32_t *pu4PwrGain, uint32_t u4Band); +int32_t MT_ATEMPSSetNss(struct net_device *prNetDev, + uint32_t u4TestNum, uint32_t *pu4Nss, uint32_t u4Band); +int32_t MT_ATEMPSSetPerpacketBW(struct net_device *prNetDev, uint32_t u4TestNum, + uint32_t *pu4PerPktBW, uint32_t u4Band); + + +int32_t MT_ATEWriteEfuse(struct net_device *prNetDev, + uint16_t u2Offset, uint16_t u2Content); +int32_t MT_ATESetTxTargetPower(struct net_device *prNetDev, + uint8_t ucTxTargetPower); + +#if CFG_SUPPORT_ANT_SWAP +int32_t MT_ATESetAntSwap(struct net_device *prNetDev, uint32_t u4Ant); +#endif + +#if (CFG_SUPPORT_DFS_MASTER == 1) +int32_t MT_ATESetRddReport(struct net_device *prNetDev, + uint8_t ucDbdcIdx); +int32_t MT_ATESetRadarDetectMode(struct net_device + *prNetDev, uint8_t ucRadarDetectMode); +#endif + + +#if CFG_SUPPORT_TX_BF +int32_t TxBfProfileTag_InValid(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + uint8_t ucInValid); +int32_t TxBfProfileTag_PfmuIdx(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + uint8_t ucProfileIdx); +int32_t TxBfProfileTag_TxBfType(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + uint8_t ucBFType); +int32_t TxBfProfileTag_DBW(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, uint8_t ucBW); +int32_t TxBfProfileTag_SuMu(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, uint8_t ucSuMu); +int32_t TxBfProfileTag_Mem(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + uint8_t *aucMemAddrColIdx, uint8_t *aucMemAddrRowIdx); +int32_t TxBfProfileTag_Matrix(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + uint8_t ucNrow, + uint8_t ucNcol, uint8_t ucNgroup, uint8_t ucLM, + uint8_t ucCodeBook, uint8_t ucHtcExist); +int32_t TxBfProfileTag_SNR(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + uint8_t ucSNR_STS0, uint8_t ucSNR_STS1, + uint8_t ucSNR_STS2, + uint8_t ucSNR_STS3); +int32_t TxBfProfileTag_SmtAnt(struct net_device *prNetDev, + union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t ucSmartAnt); +int32_t TxBfProfileTag_SeIdx(struct net_device *prNetDev, + union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t ucSeIdx); +int32_t TxBfProfileTag_RmsdThd(struct net_device *prNetDev, + union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t ucRmsdThrd); +int32_t TxBfProfileTag_McsThd(struct net_device *prNetDev, + union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t *pMCSThLSS, + uint8_t *pMCSThSSS); +int32_t TxBfProfileTag_TimeOut(struct net_device *prNetDev, + union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t ucTimeOut); +int32_t TxBfProfileTag_DesiredBW(struct net_device + *prNetDev, union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t ucDesiredBW); +int32_t TxBfProfileTag_DesiredNc(struct net_device + *prNetDev, union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t ucDesiredNc); +int32_t TxBfProfileTag_DesiredNr(struct net_device + *prNetDev, union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t ucDesiredNr); +int32_t TxBfProfileTagWrite(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t profileIdx); +int32_t TxBfProfileTagRead(struct net_device *prNetDev, + uint8_t PfmuIdx, uint8_t fgBFer); +int32_t TxBfProfileDataRead(struct net_device *prNetDev, + uint8_t profileIdx, uint8_t fgBFer, + uint8_t subcarrierIdxMsb, uint8_t subcarrierIdxLsb); +int32_t TxBfProfileDataWrite(struct net_device *prNetDev, + uint8_t profileIdx, + uint16_t subcarrierIdx, + uint16_t au2Phi[6], + uint8_t aucPsi[6], uint8_t aucDSnr[4] + ); +int32_t TxBfProfilePnRead(struct net_device *prNetDev, + uint8_t profileIdx); +int32_t TxBfProfilePnWrite(struct net_device *prNetDev, uint8_t ucProfileIdx, + uint16_t u2bw, uint16_t au2XSTS[12]); + +int32_t TxBfSounding(struct net_device *prNetDev, + uint8_t ucSuMu, /* 0/1/2/3 */ + uint8_t ucNumSta, /* 00~04 */ + uint8_t ucSndInterval, /* 00~FF */ + uint8_t ucWLan0, /* 00~7F */ + uint8_t ucWLan1, /* 00~7F */ + uint8_t ucWLan2, /* 00~7F */ + + uint8_t ucWLan3 /* 00~7F */ + ); +int32_t TxBfSoundingStop(struct net_device *prNetDev); +int32_t TxBfTxApply(struct net_device *prNetDev, + uint8_t ucWlanId, uint8_t fgETxBf, uint8_t fgITxBf, + uint8_t fgMuTxBf); + +int32_t TxBfManualAssoc(struct net_device *prNetDev, + uint8_t aucMac[MAC_ADDR_LEN], + uint8_t ucType, + uint8_t ucWtbl, + uint8_t ucOwnmac, + uint8_t ucPhyMode, + uint8_t ucBw, + uint8_t ucNss, uint8_t ucPfmuId, uint8_t ucMarate, + uint8_t ucSpeIdx, uint8_t ucRca2, uint8_t ucRv); + +int32_t TxBfPfmuMemAlloc(struct net_device *prNetDev, + uint8_t ucSuMuMode, uint8_t ucWlanIdx); + +int32_t TxBfPfmuMemRelease(struct net_device *prNetDev, + uint8_t ucWlanId); + +int32_t DevInfoUpdate(struct net_device *prNetDev, + uint8_t ucOwnMacIdx, uint8_t fgBand, + uint8_t aucMacAddr[MAC_ADDR_LEN]); + +int32_t BssInfoUpdate(struct net_device *prNetDev, + uint8_t u4OwnMacIdx, uint8_t u4BssIdx, + uint8_t u4BssId[MAC_ADDR_LEN]); + +int32_t StaRecCmmUpdate(struct net_device *prNetDev, + uint8_t ucWlanId, uint8_t ucBssId, uint8_t u4Aid, + uint8_t aucMacAddr[MAC_ADDR_LEN] + ); + +int32_t StaRecBfUpdate(struct net_device *prNetDev, + struct STA_REC_BF_UPD_ARGUMENT rStaRecBfUpdArg, + uint8_t aucMemRow[4], uint8_t aucMemCol[4] + ); + +#if CFG_SUPPORT_TX_BF_FPGA +int32_t TxBfPseudoTagUpdate(struct net_device *prNetDev, + uint8_t ucLm, uint8_t ucNr, + uint8_t ucNc, uint8_t ucBw, uint8_t ucCodeBook, + uint8_t ucGroup); +#endif + +#endif +#endif /*CFG_SUPPORT_QA_TOOL */ +#if (CONFIG_WLAN_SERVICE == 1) +uint32_t ServiceWlanOid(void *prNetDev, + uint32_t oidType, + void *param, + uint32_t paramLen, + uint32_t *u4BufLen, + void *rsp_data); +#endif /*#if (CONFIG_WLAN_SERVICE == 1)*/ + +#endif /* _GL_HOOK_API_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_kal.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_kal.h new file mode 100644 index 0000000000000..bba498b30014f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_kal.h @@ -0,0 +1,1846 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: /os/linux/include/gl_kal.h + */ + +/*! \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. + */ + +#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_wext_priv.h" +#include "link.h" +#include "nic/mac.h" +#include "nic/wlan_def.h" +#include "wlan_lib.h" +#include "wlan_oid.h" + +#if CFG_ENABLE_BT_OVER_WIFI +#include "nic/bow.h" +#endif + +#include "linux/kallsyms.h" +#include "linux/sched.h" +#if KERNEL_VERSION(4, 11, 0) <= CFG80211_VERSION_CODE +#include "linux/sched/types.h" +#endif + +#if CFG_SUPPORT_SCAN_CACHE_RESULT +#include "wireless/core.h" +#endif + +#if DBG +extern int allocatedMemSize; +#endif + +extern struct semaphore g_halt_sem; +extern int g_u4HaltFlag; +extern int g_u4WlanInitFlag; + +extern struct delayed_work sched_workq; + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +/* Define how many concurrent operation networks. */ +#define KAL_BSS_NUM 4 + +#if CFG_SUPPORT_DUAL_STA +#define KAL_AIS_NUM 2 +#else +#define KAL_AIS_NUM 1 +#endif + +#if CFG_DUAL_P2PLIKE_INTERFACE +#define KAL_P2P_NUM 2 +#else +#define KAL_P2P_NUM 1 +#endif + +#if CFG_SUPPORT_MULTITHREAD +#define GLUE_FLAG_MAIN_PROCESS \ + (GLUE_FLAG_HALT | GLUE_FLAG_SUB_MOD_MULTICAST | \ + GLUE_FLAG_TX_CMD_DONE | GLUE_FLAG_TXREQ | GLUE_FLAG_TIMEOUT | \ + GLUE_FLAG_FRAME_FILTER | GLUE_FLAG_OID | GLUE_FLAG_RX | \ + GLUE_FLAG_SER_TIMEOUT) + +#define GLUE_FLAG_HIF_PROCESS \ + (GLUE_FLAG_HALT | GLUE_FLAG_INT | GLUE_FLAG_HIF_TX | \ + GLUE_FLAG_HIF_TX_CMD | GLUE_FLAG_HIF_FW_OWN | \ + GLUE_FLAG_HIF_PRT_HIF_DBG_INFO | \ + GLUE_FLAG_UPDATE_WMM_QUOTA | \ + GLUE_FLAG_NOTIFY_MD_CRASH | \ + GLUE_FLAG_DRV_INT) + +#define GLUE_FLAG_RX_PROCESS (GLUE_FLAG_HALT | GLUE_FLAG_RX_TO_OS) +#else +/* All flags for single thread driver */ +#define GLUE_FLAG_TX_PROCESS 0xFFFFFFFF +#endif + +#if CFG_SUPPORT_SNIFFER +#define RADIOTAP_FIELD_TSFT BIT(0) +#define RADIOTAP_FIELD_FLAGS BIT(1) +#define RADIOTAP_FIELD_RATE BIT(2) +#define RADIOTAP_FIELD_CHANNEL BIT(3) +#define RADIOTAP_FIELD_ANT_SIGNAL BIT(5) +#define RADIOTAP_FIELD_ANT_NOISE BIT(6) +#define RADIOTAP_FIELD_ANT BIT(11) +#define RADIOTAP_FIELD_MCS BIT(19) +#define RADIOTAP_FIELD_AMPDU BIT(20) +#define RADIOTAP_FIELD_VHT BIT(21) +#define RADIOTAP_FIELD_VENDOR BIT(30) + +#define RADIOTAP_LEN_VHT 48 +#define RADIOTAP_FIELDS_VHT (RADIOTAP_FIELD_TSFT | \ + RADIOTAP_FIELD_FLAGS | \ + RADIOTAP_FIELD_RATE | \ + RADIOTAP_FIELD_CHANNEL | \ + RADIOTAP_FIELD_ANT_SIGNAL | \ + RADIOTAP_FIELD_ANT_NOISE | \ + RADIOTAP_FIELD_ANT | \ + RADIOTAP_FIELD_AMPDU | \ + RADIOTAP_FIELD_VHT | \ + RADIOTAP_FIELD_VENDOR) + +#define RADIOTAP_LEN_HT 36 +#define RADIOTAP_FIELDS_HT (RADIOTAP_FIELD_TSFT | \ + RADIOTAP_FIELD_FLAGS | \ + RADIOTAP_FIELD_RATE | \ + RADIOTAP_FIELD_CHANNEL | \ + RADIOTAP_FIELD_ANT_SIGNAL | \ + RADIOTAP_FIELD_ANT_NOISE | \ + RADIOTAP_FIELD_ANT | \ + RADIOTAP_FIELD_MCS | \ + RADIOTAP_FIELD_AMPDU | \ + RADIOTAP_FIELD_VENDOR) + +#define RADIOTAP_LEN_LEGACY 26 +#define RADIOTAP_FIELDS_LEGACY (RADIOTAP_FIELD_TSFT | \ + RADIOTAP_FIELD_FLAGS | \ + RADIOTAP_FIELD_RATE | \ + RADIOTAP_FIELD_CHANNEL | \ + RADIOTAP_FIELD_ANT_SIGNAL | \ + RADIOTAP_FIELD_ANT_NOISE | \ + RADIOTAP_FIELD_ANT | \ + RADIOTAP_FIELD_VENDOR) +#endif + +#define PERF_MON_INIT_BIT (0) +#define PERF_MON_DISABLE_BIT (1) +#define PERF_MON_STOP_BIT (2) +#define PERF_MON_RUNNING_BIT (3) + +#define PERF_MON_UPDATE_INTERVAL (1000) +#define PERF_MON_TP_MAX_THRESHOLD (10) + +#define PERF_MON_TP_CONDITION (125000) + +#if CFG_SUPPORT_DATA_STALL +#define REPORT_EVENT_INTERVAL 30 +#define EVENT_PER_HIGH_THRESHOLD 80 +#define EVENT_TX_LOW_RATE_THRESHOLD 20 +#define EVENT_RX_LOW_RATE_THRESHOLD 20 +#define TRAFFIC_RHRESHOLD 150 +#endif + +#define WIFI_LOG_MSG_MAX (512) +#define WIFI_LOG_MSG_BUFFER (WIFI_LOG_MSG_MAX * 2) + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +enum ENUM_SPIN_LOCK_CATEGORY_E { + SPIN_LOCK_FSM = 0, + +#if CFG_SUPPORT_MULTITHREAD + SPIN_LOCK_TX_PORT_QUE, + SPIN_LOCK_TX_CMD_QUE, + SPIN_LOCK_TX_CMD_DONE_QUE, + SPIN_LOCK_TC_RESOURCE, + SPIN_LOCK_RX_TO_OS_QUE, +#endif + + /* FIX ME */ + SPIN_LOCK_RX_QUE, + SPIN_LOCK_RX_FREE_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, + /* TX/RX Direct : BEGIN */ + SPIN_LOCK_TX_DIRECT, + SPIN_LOCK_RX_DIRECT, + SPIN_LOCK_RX_DIRECT_REORDER, + /* TX/RX Direct : END */ + SPIN_LOCK_IO_REQ, + SPIN_LOCK_INT, + SPIN_LOCK_UPDATE_WMM_QUOTA, + + 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_BSSLIST_FW, + SPIN_LOCK_BSSLIST_CFG, + SPIN_LOCK_NUM +}; + +enum ENUM_MUTEX_CATEGORY_E { + MUTEX_TX_CMD_CLEAR, + MUTEX_TX_DATA_DONE_QUE, + MUTEX_DEL_INF, + MUTEX_CHIP_RST, + MUTEX_SET_OWN, + MUTEX_BOOST_CPU, + MUTEX_NUM +}; + +/* event for assoc information update */ +struct EVENT_ASSOC_INFO { + uint8_t ucAssocReq; /* 1 for assoc req, 0 for assoc rsp */ + uint8_t ucReassoc; /* 0 for assoc, 1 for reassoc */ + uint16_t u2Length; + uint8_t *pucIe; +}; + +enum ENUM_KAL_NETWORK_TYPE_INDEX { + 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 ENUM_KAL_MEM_ALLOCATION_TYPE_E { + PHY_MEM_TYPE, /* physically continuous */ + VIR_MEM_TYPE, /* virtually continuous */ + MEM_TYPE_NUM +}; + +#ifdef CONFIG_ANDROID /* Defined in Android kernel source */ +#if (KERNEL_VERSION(4, 19, 0) <= CFG80211_VERSION_CODE) +#define KAL_WAKE_LOCK_T struct wakeup_source +#elif (KERNEL_VERSION(4, 9, 0) <= CFG80211_VERSION_CODE) +#define KAL_WAKE_LOCK_T struct wakeup_source +#else +#define KAL_WAKE_LOCK_T struct wake_lock +#endif +#else +#define KAL_WAKE_LOCK_T uint32_t +#endif + +#if CFG_SUPPORT_AGPS_ASSIST +enum ENUM_MTK_AGPS_ATTR { + MTK_ATTR_AGPS_INVALID, + MTK_ATTR_AGPS_CMD, + MTK_ATTR_AGPS_DATA, + MTK_ATTR_AGPS_IFINDEX, + MTK_ATTR_AGPS_IFNAME, + MTK_ATTR_AGPS_MAX +}; + +enum ENUM_AGPS_EVENT { + AGPS_EVENT_WLAN_ON, + AGPS_EVENT_WLAN_OFF, + AGPS_EVENT_WLAN_AP_LIST, +}; +u_int8_t kalIndicateAgpsNotify(struct ADAPTER *prAdapter, + uint8_t cmd, + uint8_t *data, uint16_t dataLen); +#endif /* CFG_SUPPORT_AGPS_ASSIST */ + +#if CFG_SUPPORT_SNIFFER +/* Vendor Namespace + * Bit Number 30 + * Required Alignment 2 bytes + */ +struct RADIOTAP_FIELD_VENDOR_ { + uint8_t aucOUI[3]; + uint8_t ucSubNamespace; + uint16_t u2DataLen; + uint8_t ucData; +} __KAL_ATTRIB_PACKED__; + +struct MONITOR_RADIOTAP { + /* radiotap header */ + uint8_t ucItVersion; /* set to 0 */ + uint8_t ucItPad; + uint16_t u2ItLen; /* entire length */ + uint32_t u4ItPresent; /* fields present */ + + /* TSFT + * Bit Number 0 + * Required Alignment 8 bytes + * Unit microseconds + */ + uint64_t u8MacTime; + + /* Flags + * Bit Number 1 + */ + uint8_t ucFlags; + + /* Rate + * Bit Number 2 + * Unit 500 Kbps + */ + uint8_t ucRate; + + /* Channel + * Bit Number 3 + * Required Alignment 2 bytes + */ + uint16_t u2ChFrequency; + uint16_t u2ChFlags; + + /* Antenna signal + * Bit Number 5 + * Unit dBm + */ + uint8_t ucAntennaSignal; + + /* Antenna noise + * Bit Number 6 + * Unit dBm + */ + uint8_t ucAntennaNoise; + + /* Antenna + * Bit Number 11 + * Unit antenna index + */ + uint8_t ucAntenna; + + /* MCS + * Bit Number 19 + * Required Alignment 1 byte + */ + uint8_t ucMcsKnown; + uint8_t ucMcsFlags; + uint8_t ucMcsMcs; + + /* A-MPDU status + * Bit Number 20 + * Required Alignment 4 bytes + */ + uint32_t u4AmpduRefNum; + uint16_t u2AmpduFlags; + uint8_t ucAmpduDelimiterCRC; + uint8_t ucAmpduReserved; + + /* VHT + * Bit Number 21 + * Required Alignment 2 bytes + */ + uint16_t u2VhtKnown; + uint8_t ucVhtFlags; + uint8_t ucVhtBandwidth; + uint8_t aucVhtMcsNss[4]; + uint8_t ucVhtCoding; + uint8_t ucVhtGroupId; + uint16_t u2VhtPartialAid; + + /* extension space */ + uint8_t aucReserve[12]; +} __KAL_ATTRIB_PACKED__; +#endif + +struct KAL_HALT_CTRL_T { + struct semaphore lock; + struct task_struct *owner; + u_int8_t fgHalt; + u_int8_t fgHeldByKalIoctl; + OS_SYSTIME u4HoldStart; +}; + +struct KAL_THREAD_SCHEDSTATS { + /* when marked: the profiling start time(ms), + * when unmarked: total duration(ms) + */ + unsigned long long time; + /* time spent in exec (sum_exec_runtime) */ + unsigned long long exec; + /* time spent in run-queue while not being scheduled (wait_sum) */ + unsigned long long runnable; + /* time spent waiting for I/O (iowait_sum) */ + unsigned long long iowait; +}; + +#if CFG_SUPPORT_DATA_STALL +enum ENUM_VENDOR_DRIVER_EVENT { + EVENT_TEST_MODE, + EVENT_ARP_NO_RESPONSE, + EVENT_PER_HIGH, + EVENT_TX_LOW_RATE, + EVENT_RX_LOW_RATE, + EVENT_SG_DISABLE, + EVENT_SG_1T1R, + EVENT_SG_2T2R, + EVENT_TX_DUP_OFF = 100, + EVENT_TX_DUP_ON = 101, + EVENT_TX_DUP_CERT_CHANGE = 102 +}; +#endif + +enum ENUM_CMD_TX_RESULT { + CMD_TX_RESULT_SUCCESS, + CMD_TX_RESULT_FAILED, + CMD_TX_RESULT_QUEUED, + CMD_TX_RESULT_NUM +}; + +/******************************************************************************* + * P U B 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 KAL_SET_BIT(bitOffset, value) set_bit(bitOffset, &value) +#define KAL_CLR_BIT(bitOffset, value) clear_bit(bitOffset, &value) +#define KAL_TEST_AND_CLEAR_BIT(bitOffset, value) \ + test_and_clear_bit(bitOffset, &value) +#define KAL_TEST_BIT(bitOffset, value) test_bit(bitOffset, &value) +#define SUSPEND_FLAG_FOR_WAKEUP_REASON (0) +#define SUSPEND_FLAG_CLEAR_WHEN_RESUME (1) + + +/*----------------------------------------------------------------------------*/ +/* Macros of getting current thread id */ +/*----------------------------------------------------------------------------*/ +#define KAL_GET_CURRENT_THREAD_ID() (current->pid) +#define KAL_GET_CURRENT_THREAD_NAME() (current->comm) + +/*----------------------------------------------------------------------------*/ +/* Macros of SPIN LOCK operations for using in Driver Layer */ +/*----------------------------------------------------------------------------*/ +#define KAL_SPIN_LOCK_DECLARATION() unsigned long __ulFlags + +#define KAL_ACQUIRE_SPIN_LOCK(_prAdapter, _rLockCategory) \ + kalAcquireSpinLock(((struct ADAPTER *)_prAdapter)->prGlueInfo, \ + _rLockCategory, &__ulFlags) + +#define KAL_RELEASE_SPIN_LOCK(_prAdapter, _rLockCategory) \ + kalReleaseSpinLock(((struct ADAPTER *)_prAdapter)->prGlueInfo, \ + _rLockCategory, __ulFlags) + +/*----------------------------------------------------------------------------*/ +/* Macros of MUTEX operations for using in Driver Layer */ +/*----------------------------------------------------------------------------*/ +#define KAL_ACQUIRE_MUTEX(_prAdapter, _rLockCategory) \ + kalAcquireMutex(((struct ADAPTER *)_prAdapter)->prGlueInfo, \ + _rLockCategory) + +#define KAL_RELEASE_MUTEX(_prAdapter, _rLockCategory) \ + kalReleaseMutex(((struct ADAPTER *)_prAdapter)->prGlueInfo, \ + _rLockCategory) + +/*----------------------------------------------------------------------------*/ +/* 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 for kernel related defines */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(3, 14, 0) > CFG80211_VERSION_CODE +#define IEEE80211_CHAN_PASSIVE_FLAG IEEE80211_CHAN_PASSIVE_SCAN +#define IEEE80211_CHAN_PASSIVE_STR "PASSIVE" +#else +#define IEEE80211_CHAN_PASSIVE_FLAG IEEE80211_CHAN_NO_IR +#define IEEE80211_CHAN_PASSIVE_STR "NO_IR" +#endif + +#if KERNEL_VERSION(4, 7, 0) <= CFG80211_VERSION_CODE +/** + * enum nl80211_band - Frequency band + * @NL80211_BAND_2GHZ: 2.4 GHz ISM band + * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz) + * @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 64.80 GHz) + * @NUM_NL80211_BANDS: number of bands, avoid using this in userspace + * since newer kernel versions may support more bands + */ +#define KAL_BAND_2GHZ NL80211_BAND_2GHZ +#define KAL_BAND_5GHZ NL80211_BAND_5GHZ +#define KAL_NUM_BANDS NUM_NL80211_BANDS +#else +#define KAL_BAND_2GHZ IEEE80211_BAND_2GHZ +#define KAL_BAND_5GHZ IEEE80211_BAND_5GHZ +#define KAL_NUM_BANDS IEEE80211_NUM_BANDS +#endif + +/** + * enum nl80211_reg_rule_flags - regulatory rule flags + * @NL80211_RRF_NO_OFDM: OFDM modulation not allowed + * @NL80211_RRF_AUTO_BW: maximum available bandwidth should be calculated + * base on contiguous rules and wider channels will be allowed to cross + * multiple contiguous/overlapping frequency ranges. + * @NL80211_RRF_DFS: DFS support is required to be used + */ +#define KAL_RRF_NO_OFDM NL80211_RRF_NO_OFDM +#define KAL_RRF_DFS NL80211_RRF_DFS +#if KERNEL_VERSION(3, 15, 0) > CFG80211_VERSION_CODE +#define KAL_RRF_AUTO_BW 0 +#else +#define KAL_RRF_AUTO_BW NL80211_RRF_AUTO_BW +#endif + +/** + * kalCfg80211ScanDone - abstraction of cfg80211_scan_done + * + * @request: the corresponding scan request (sanity checked by callers!) + * @aborted: set to true if the scan was aborted for any reason, + * userspace will be notified of that + * + * Since linux-4.8.y the 2nd parameter is changed from bool to + * struct cfg80211_scan_info, but we don't use all fields yet. + */ +#if KERNEL_VERSION(4, 8, 0) <= CFG80211_VERSION_CODE +static inline void kalCfg80211ScanDone(struct cfg80211_scan_request *request, + bool aborted) +{ + struct cfg80211_scan_info info = {.aborted = aborted }; + + cfg80211_scan_done(request, &info); +} +#else +static inline void kalCfg80211ScanDone(struct cfg80211_scan_request *request, + bool aborted) +{ + cfg80211_scan_done(request, aborted); +} +#endif + +/* Consider on some Android platform, using request_firmware_direct() + * may cause system failed to load firmware. So we still use + * request_firmware(). + */ +#define REQUEST_FIRMWARE(_fw, _name, _dev) \ + request_firmware(_fw, _name, _dev) + +/*----------------------------------------------------------------------------*/ +/* Macros of wake_lock operations for using in Driver Layer */ +/*----------------------------------------------------------------------------*/ +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) +/* CONFIG_ANDROID is defined in Android kernel source */ +#if (KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE) +#if (KERNEL_VERSION(4, 14, 149) <= LINUX_VERSION_CODE) +#define KAL_WAKE_LOCK_INIT(_prAdapter, _prWakeLock, _pcName) \ + _prWakeLock = wakeup_source_register(NULL, _pcName); + +#define KAL_WAKE_LOCK_DESTROY(_prAdapter, _prWakeLock) \ +{ \ + wakeup_source_unregister(_prWakeLock); \ + _prWakeLock = NULL; \ +} +#else +#define KAL_WAKE_LOCK_INIT(_prAdapter, _prWakeLock, _pcName) \ +{ \ + _prWakeLock = kalMemAlloc(sizeof(KAL_WAKE_LOCK_T), \ + VIR_MEM_TYPE); \ + if (!_prWakeLock) { \ + DBGLOG(HAL, ERROR, \ + "KAL_WAKE_LOCK_INIT init fail!\n"); \ + } \ + else { \ + wakeup_source_init(_prWakeLock, _pcName); \ + } \ +} + +#define KAL_WAKE_LOCK_DESTROY(_prAdapter, _prWakeLock) \ +{ \ + if (_prWakeLock) { \ + wakeup_source_trash(_prWakeLock); \ + _prWakeLock = NULL; \ + } \ +} +#endif +#define KAL_WAKE_LOCK(_prAdapter, _prWakeLock) \ +{ \ + if (_prWakeLock) { \ + __pm_stay_awake(_prWakeLock); \ + } \ +} + +#define KAL_WAKE_LOCK_TIMEOUT(_prAdapter, _prWakeLock, _u4Timeout) \ +{ \ + if (_prWakeLock) { \ + __pm_wakeup_event(_prWakeLock, JIFFIES_TO_MSEC(_u4Timeout)); \ + } \ +} + +#define KAL_WAKE_UNLOCK(_prAdapter, _prWakeLock) \ +{ \ + if (_prWakeLock) { \ + __pm_relax(_prWakeLock); \ + } \ +} + +#define KAL_WAKE_LOCK_ACTIVE(_prAdapter, _prWakeLock) \ + ((_prWakeLock) && ((_prWakeLock)->active)) + +#else +#define KAL_WAKE_LOCK_INIT(_prAdapter, _prWakeLock, _pcName) \ +{ \ + _prWakeLock = kalMemAlloc(sizeof(KAL_WAKE_LOCK_T), \ + VIR_MEM_TYPE); \ + if (!_prWakeLock) { \ + DBGLOG(HAL, ERROR, \ + "KAL_WAKE_LOCK_INIT init fail!\n"); \ + } \ + else { \ + wake_lock_init(_prWakeLock, WAKE_LOCK_SUSPEND, _pcName); \ + } \ +} + +#define KAL_WAKE_LOCK_DESTROY(_prAdapter, _prWakeLock) \ +{ \ + if (_prWakeLock) { \ + wake_lock_destroy(_prWakeLock); \ + } \ +} + +#define KAL_WAKE_LOCK(_prAdapter, _prWakeLock) \ +{ \ + if (_prWakeLock) { \ + wake_lock(_prWakeLock); \ + } \ +} + +#define KAL_WAKE_LOCK_TIMEOUT(_prAdapter, _prWakeLock, _u4Timeout) \ +{ \ + if (_prWakeLock) { \ + wake_lock_timeout(_prWakeLock, _u4Timeout); \ + } \ +} + +#define KAL_WAKE_UNLOCK(_prAdapter, _prWakeLock) \ +{ \ + if (_prWakeLock) { \ + wake_unlock(_prWakeLock); \ + } \ +} + +#define KAL_WAKE_LOCK_ACTIVE(_prAdapter, _prWakeLock) \ + ((_prWakeLock) && wake_lock_active(_prWakeLock)) +#endif + +#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) +#define KAL_WAKE_LOCK_ACTIVE(_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) { \ + if (in_interrupt()) \ + pvAddr = kmalloc(u4Size, GFP_ATOMIC); \ + else \ + pvAddr = kmalloc(u4Size, GFP_KERNEL); \ + } \ + else { \ + if (u4Size > PAGE_SIZE) \ + pvAddr = vmalloc(u4Size); \ + else \ + pvAddr = kmalloc(u4Size, GFP_KERNEL); \ + } \ + if (pvAddr) { \ + allocatedMemSize += u4Size; \ + DBGLOG(INIT, INFO, "0x%p(%ld) allocated (%s:%s)\n", \ + pvAddr, (uint32_t)u4Size, __FILE__, __func__); \ + } \ + pvAddr; \ +}) +#else +#define kalMemAlloc(u4Size, eMemType) ({ \ + void *pvAddr; \ + if (eMemType == PHY_MEM_TYPE) { \ + if (in_interrupt()) \ + pvAddr = kmalloc(u4Size, GFP_ATOMIC); \ + else \ + pvAddr = kmalloc(u4Size, GFP_KERNEL); \ + } \ + else { \ + if (u4Size > PAGE_SIZE) \ + pvAddr = vmalloc(u4Size); \ + else \ + pvAddr = kmalloc(u4Size, GFP_KERNEL); \ + } \ + if (!pvAddr) \ + ASSERT_NOMEM(); \ + pvAddr; \ +}) +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Free allocated cache memory + * + * \param[in] pvAddr Required memory size. + * \param[in] eMemType Memory allocation type + * \param[in] u4Size Allocated memory size. + * + * \return - + */ +/*----------------------------------------------------------------------------*/ +#if DBG +#define kalMemFree(pvAddr, eMemType, u4Size) \ +{ \ + if (pvAddr) { \ + allocatedMemSize -= u4Size; \ + DBGLOG(INIT, INFO, "0x%p(%ld) freed (%s:%s)\n", \ + pvAddr, (uint32_t)u4Size, __FILE__, __func__); \ + } \ + kvfree(pvAddr); \ +} +#else +#define kalMemFree(pvAddr, eMemType, u4Size) \ +{ \ + kvfree(pvAddr); \ +} +#endif + +#define kalUdelay(u4USec) udelay(u4USec) + +#define kalMdelay(u4MSec) mdelay(u4MSec) +#define kalMsleep(u4MSec) msleep(u4MSec) +#define kalUsleep_range(u4MinUSec, u4MaxUSec) \ + usleep_range(u4MinUSec, u4MaxUSec) + +/* 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) + +/* Move memory block with specific size */ +#define kalMemMove(pvDst, pvSrc, u4Size) \ + memmove(pvDst, pvSrc, u4Size) + +#if KERNEL_VERSION(4, 0, 0) <= LINUX_VERSION_CODE +#define strnicmp(s1, s2, n) strncasecmp(s1, s2, n) +#endif + +/* string operation */ +#define kalStrCpy(dest, src) strcpy(dest, src) +#define kalStrnCpy(dest, src, n) strncpy(dest, src, n) +#define kalStrCmp(ct, cs) strcmp(ct, cs) +#define kalStrnCmp(ct, cs, n) strncmp(ct, cs, n) +#define kalStrChr(s, c) strchr(s, c) +#define kalStrrChr(s, c) strrchr(s, c) +#define kalStrnChr(s, n, c) strnchr(s, n, c) +#define kalStrLen(s) strlen(s) +#define kalStrnLen(s, b) strnlen(s, b) +#define kalStrniCmp(ct, cs, n) strncasecmp(ct, cs, n) +/* #define kalStrtoul(cp, endp, base) simple_strtoul(cp, endp, base) */ +/* #define kalStrtol(cp, endp, base) simple_strtol(cp, endp, base) */ +#define kalkStrtou8(cp, base, resp) kstrtou8(cp, base, resp) +#define kalkStrtou16(cp, base, resp) kstrtou16(cp, base, resp) +#define kalkStrtou32(cp, base, resp) kstrtou32(cp, base, resp) +#define kalkStrtos32(cp, base, resp) kstrtos32(cp, base, resp) +#define kalSnprintf(buf, size, fmt, ...) \ + _kalSnprintf((char *)(buf), (size_t)(size), \ + (const char *)(fmt), ##__VA_ARGS__) +#define kalScnprintf(buf, size, fmt, ...) \ + scnprintf(buf, size, fmt, ##__VA_ARGS__) +#define kalSprintf(buf, fmt, ...) \ + _kalSprintf((char *)(buf), (const char *)(fmt), ##__VA_ARGS__) +/* remove for AOSP */ +/* #define kalSScanf(buf, fmt, ...) sscanf(buf, fmt, __VA_ARGS__) */ +#define kalStrStr(ct, cs) strstr(ct, cs) +#define kalStrSep(s, ct) strsep(s, ct) +#define kalStrCat(dest, src) strcat(dest, src) +#define kalIsXdigit(c) isxdigit(c) +#define kalStrtoint(_data, _base, _res) kstrtoint(_data, _base, _res) +#define kalStrtoul(_data, _base, _res) kstrtoul(_data, _base, _res) + +int8_t *strtok_r(int8_t *s, const int8_t *delim, int8_t **last); +#define kalStrtokR(_buf, _tok, _saved) \ + strtok_r((int8_t *)_buf, _tok, (int8_t **)_saved) + +int8_t atoi(uint8_t ch); +#define kalAtoi(_ch) atoi(_ch) + +/* defined for wince sdio driver only */ +#if defined(_HIF_SDIO) +#define kalDevSetPowerState(prGlueInfo, ePowerMode) \ + glSetPowerState(prGlueInfo, ePowerMode) +#else +#define kalDevSetPowerState(prGlueInfo, ePowerMode) +#endif + +#if CFG_MTK_ANDROID_WMT +#define _kalRequestFirmware request_firmware_direct +#else +#define _kalRequestFirmware request_firmware +#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) \ + ((uint8_t *)((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) \ + ((uint32_t)((struct sk_buff *)pvPacket)->end - \ + (uint32_t)((struct sk_buff *)pvPacket)->data) + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is used to copy the entire frame from skb to the + * destination address in the input parameter. + * + * \param[in] prGlueInfo Pointer of GLUE Data Structure + * \param[in] pvPacket Pointer of Packet Handle + * \param[in] pucDestBuffer Destination Address + * + * \return - + */ +/*----------------------------------------------------------------------------*/ +#define kalCopyFrame(prGlueInfo, pvPacket, pucDestBuffer) \ + do {struct sk_buff *skb = (struct sk_buff *)pvPacket; \ + memcpy(pucDestBuffer, skb->data, skb->len); } while (0) + +#define kalGetTimeTick() jiffies_to_msecs(jiffies) + +#define WLAN_TAG "[wlan]" +#define kalPrint kalPrintLog +#define kalPrintLimited kalPrintLogLimited + +#define kalBreakPoint() \ +do { \ + WARN_ON(1); \ + panic("Oops"); \ +} while (0) + +#if CFG_ENABLE_AEE_MSG +#define kalSendAeeException aee_kernel_exception +#define kalSendAeeWarning aee_kernel_warning +#define kalSendAeeReminding aee_kernel_reminding +#else +#define kalSendAeeException(_module, _desc, ...) +#define kalSendAeeWarning(_module, _desc, ...) +#define kalSendAeeReminding(_module, _desc, ...) +#endif + +#define PRINTF_ARG(...) __VA_ARGS__ +#define SPRINTF(buf, arg) {buf += sprintf((char *)(buf), PRINTF_ARG arg); } + +#define USEC_TO_SYSTIME(_usec) ((_usec) / USEC_PER_MSEC) +#define MSEC_TO_SYSTIME(_msec) (_msec) + +#define MSEC_TO_JIFFIES(_msec) msecs_to_jiffies(_msec) +#define JIFFIES_TO_MSEC(_jiffie) jiffies_to_msecs(_jiffie) + +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE +#define do_gettimeofday(_tv) kal_do_gettimeofday(_tv) +#define get_ds() KERNEL_DS +#define kal_access_ok(type, addr, size) access_ok(addr, size) +#else +#define kal_access_ok(type, addr, size) access_ok(type, addr, size) +#endif + +#define KAL_TIME_INTERVAL_DECLARATION() struct timeval __rTs, __rTe +#define KAL_REC_TIME_START() do_gettimeofday(&__rTs) +#define KAL_REC_TIME_END() do_gettimeofday(&__rTe) +#define KAL_GET_TIME_INTERVAL() \ + ((SEC_TO_USEC(__rTe.tv_sec) + __rTe.tv_usec) - \ + (SEC_TO_USEC(__rTs.tv_sec) + __rTs.tv_usec)) +#define KAL_ADD_TIME_INTERVAL(_Interval) \ + { \ + (_Interval) += KAL_GET_TIME_INTERVAL(); \ + } + +#if defined(_HIF_PCIE) +#define KAL_DMA_TO_DEVICE PCI_DMA_TODEVICE +#define KAL_DMA_FROM_DEVICE PCI_DMA_FROMDEVICE + +#define KAL_DMA_ALLOC_COHERENT(_dev, _size, _handle) \ + pci_alloc_consistent(_dev, _size, _handle) +#define KAL_DMA_FREE_COHERENT(_dev, _size, _addr, _handle) \ + pci_free_consistent(_dev, _size, _addr, _handle) +#define KAL_DMA_MAP_SINGLE(_dev, _ptr, _size, _dir) \ + pci_map_single(_dev, _ptr, _size, _dir) +#define KAL_DMA_UNMAP_SINGLE(_dev, _addr, _size, _dir) \ + pci_unmap_single(_dev, _addr, _size, _dir) +#define KAL_DMA_MAPPING_ERROR(_dev, _addr) \ + pci_dma_mapping_error(_dev, _addr) +#else +#define KAL_DMA_TO_DEVICE DMA_TO_DEVICE +#define KAL_DMA_FROM_DEVICE DMA_FROM_DEVICE + +#define KAL_DMA_ALLOC_COHERENT(_dev, _size, _handle) \ + dma_alloc_coherent(_dev, _size, _handle, GFP_DMA) +#define KAL_DMA_FREE_COHERENT(_dev, _size, _addr, _handle) \ + dma_free_coherent(_dev, _size, _addr, _handle) +#define KAL_DMA_MAP_SINGLE(_dev, _ptr, _size, _dir) \ + dma_map_single(_dev, _ptr, _size, _dir) +#define KAL_DMA_UNMAP_SINGLE(_dev, _addr, _size, _dir) \ + dma_unmap_single(_dev, _addr, _size, _dir) +#define KAL_DMA_MAPPING_ERROR(_dev, _addr) \ + dma_mapping_error(_dev, _addr) +#endif + +#if CFG_SUPPORT_DATA_STALL +#define KAL_REPORT_ERROR_EVENT kalIndicateDriverEvent +#endif + +#if CFG_SUPPORT_BIGDATA_PIP +#define KAL_REPORT_BIGDATA_PIP kalBigDataPip +#endif + +/*----------------------------------------------------------------------------*/ +/* Macros of show stack operations for using in Driver Layer */ +/*----------------------------------------------------------------------------*/ +#if CFG_MTK_ANDROID_WMT +#define kal_show_stack(_adapter, _task, _sp) \ + connectivity_export_show_stack(_task, _sp) +#else +#define kal_show_stack(_adapter, _task, _sp) +#endif + +/*----------------------------------------------------------------------------*/ +/* Macros of systrace operations for using in Driver Layer */ +/*----------------------------------------------------------------------------*/ +#if !CONFIG_WLAN_DRV_BUILD_IN + +#define kalTraceBegin(_fmt, ...) \ + tracing_mark_write("B|%d|" _fmt "\n", current->tgid, ##__VA_ARGS__) + +#define kalTraceEnd() \ + tracing_mark_write("E|%d\n", current->tgid) + +#define kalTraceInt(_value, _fmt, ...) \ + tracing_mark_write("C|%d|" _fmt "|%d\n", \ + current->tgid, ##__VA_ARGS__, _value) + +#define kalTraceCall() \ + { kalTraceBegin("%s", __func__); kalTraceEnd(); } + +#define kalTraceEvent(_fmt, ...) \ + { kalTraceBegin(_fmt, ##__VA_ARGS__); kalTraceEnd(); } + +#define __type_is_void(expr) __builtin_types_compatible_p(typeof(expr), void) +#define __expr_zero(expr) __builtin_choose_expr(__type_is_void(expr), 0, (expr)) + +#define TRACE(_expr, _fmt, ...) \ + __builtin_choose_expr(__type_is_void(_expr), \ + __TRACE_VOID(_expr, _fmt, ##__VA_ARGS__), \ + __TRACE(__expr_zero(_expr), _fmt, ##__VA_ARGS__)) + +#define __TRACE(_expr, _fmt, ...) \ + ({ \ + typeof(_expr) __ret; \ + kalTraceBegin(_fmt, ##__VA_ARGS__); \ + __ret = (_expr); \ + kalTraceEnd(); \ + __ret; \ + }) + +#define __TRACE_VOID(_expr, _fmt, ...) \ + ({ \ + kalTraceBegin(_fmt, ##__VA_ARGS__); \ + (void) (_expr); \ + kalTraceEnd(); \ + }) +#else + +#define kalTraceBegin(_fmt, ...) +#define kalTraceEnd() +#define kalTraceInt(_value, _fmt, ...) +#define kalTraceCall() +#define kalTraceEvent(_fmt, ...) +#define TRACE(_expr, _fmt, ...) _expr + +#endif +/******************************************************************************* + * 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 struct GLUE_INFO *prGlueInfo, + IN enum ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, + OUT unsigned long *plFlags); + +void kalReleaseSpinLock(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, + IN unsigned long ulFlags); + +void kalUpdateMACAddress(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucMacAddr); + +void kalAcquireMutex(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_MUTEX_CATEGORY_E rMutexCategory); + +void kalReleaseMutex(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_MUTEX_CATEGORY_E rMutexCategory); + +void kalPacketFree(IN struct GLUE_INFO *prGlueInfo, + IN void *pvPacket); + +void *kalPacketAlloc(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Size, + OUT uint8_t **ppucData); + +void *kalPacketAllocWithHeadroom(IN struct GLUE_INFO + *prGlueInfo, + IN uint32_t u4Size, OUT uint8_t **ppucData); + +void kalOsTimerInitialize(IN struct GLUE_INFO *prGlueInfo, + IN void *prTimerHandler); + +u_int8_t kalSetTimer(IN struct GLUE_INFO *prGlueInfo, + IN OS_SYSTIME rInterval); + +uint32_t +kalProcessRxPacket(IN struct GLUE_INFO *prGlueInfo, + IN void *pvPacket, + IN uint8_t *pucPacketStart, IN uint32_t u4PacketLen, + /* IN PBOOLEAN pfgIsRetain, */ + IN u_int8_t fgIsRetain, IN enum ENUM_CSUM_RESULT aeCSUM[]); + +uint32_t kalRxIndicatePkts(IN struct GLUE_INFO *prGlueInfo, + IN void *apvPkts[], + IN uint8_t ucPktNum); + +uint32_t kalRxIndicateOnePkt(IN struct GLUE_INFO + *prGlueInfo, IN void *pvPkt); + +void +kalIndicateStatusAndComplete(IN struct GLUE_INFO + *prGlueInfo, + IN uint32_t eStatus, IN void *pvBuf, + IN uint32_t u4BufLen, + IN uint8_t ucBssIndex); + +void +kalUpdateReAssocReqInfo(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucFrameBody, IN uint32_t u4FrameBodyLen, + IN u_int8_t fgReassocRequest, + IN uint8_t ucBssIndex); + +void kalUpdateReAssocRspInfo(IN struct GLUE_INFO + *prGlueInfo, + IN uint8_t *pucFrameBody, + IN uint32_t u4FrameBodyLen, + IN uint8_t ucBssIndex); + +#if CFG_TX_FRAGMENT +u_int8_t +kalQueryTxPacketHeader(IN struct GLUE_INFO *prGlueInfo, + IN void *pvPacket, OUT uint16_t *pu2EtherTypeLen, + OUT uint8_t *pucEthDestAddr); +#endif /* CFG_TX_FRAGMENT */ + +void kalSendCompleteAndAwakeQueue(IN struct GLUE_INFO + *prGlueInfo, + IN void *pvPacket); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +void kalQueryTxChksumOffloadParam(IN void *pvPacket, + OUT uint8_t *pucFlag); + +void kalUpdateRxCSUMOffloadParam(IN void *pvPacket, + IN enum ENUM_CSUM_RESULT eCSUM[]); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +u_int8_t kalRetrieveNetworkAddress(IN struct GLUE_INFO *prGlueInfo, + IN OUT uint8_t *prMacAddr); + +void +kalReadyOnChannel(IN struct GLUE_INFO *prGlueInfo, + IN uint64_t u8Cookie, + IN enum ENUM_BAND eBand, IN enum ENUM_CHNL_EXT eSco, + IN uint8_t ucChannelNum, IN uint32_t u4DurationMs, + IN uint8_t ucBssIndex); + +void +kalRemainOnChannelExpired(IN struct GLUE_INFO *prGlueInfo, + IN uint64_t u8Cookie, IN enum ENUM_BAND eBand, + IN enum ENUM_CHNL_EXT eSco, IN uint8_t ucChannelNum, + IN uint8_t ucBssIndex); + +#if CFG_SUPPORT_DFS +void +kalIndicateChannelSwitch(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_CHNL_EXT eSco, + IN uint8_t ucChannelNum); +#endif + +void +kalIndicateMgmtTxStatus(IN struct GLUE_INFO *prGlueInfo, + IN uint64_t u8Cookie, IN u_int8_t fgIsAck, + IN uint8_t *pucFrameBuf, IN uint32_t u4FrameLen, + IN uint8_t ucBssIndex); + +void kalIndicateRxMgmtFrame(IN struct GLUE_INFO *prGlueInfo, + IN struct SW_RFB *prSwRfb, + IN uint8_t ucBssIndex); + +#if CFG_SUPPORT_DATA_STALL +u_int8_t kalIndicateDriverEvent(struct ADAPTER *prAdapter, + uint32_t event, + uint16_t dataLen, + uint8_t ucBssIdx, + u_int8_t fgForceReport); +#endif + +#if CFG_SUPPORT_BIGDATA_PIP +int8_t kalBigDataPip(struct ADAPTER *prAdapter, + uint8_t *payload, + uint16_t dataLen); +#endif + +/*----------------------------------------------------------------------------*/ +/* Routines in interface - ehpi/sdio.c */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevRegRead(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Register, + OUT uint32_t *pu4Value); +u_int8_t kalDevRegRead_mac(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Register, OUT uint32_t *pu4Value); + +u_int8_t kalDevRegWrite(struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Register, + IN uint32_t u4Value); +u_int8_t kalDevRegWrite_mac(struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Register, IN uint32_t u4Value); + +u_int8_t +kalDevPortRead(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port, IN uint32_t u2Len, OUT uint8_t *pucBuf, + IN uint32_t u2ValidOutBufSize); + +u_int8_t +kalDevPortWrite(struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port, IN uint32_t u2Len, IN uint8_t *pucBuf, + IN uint32_t u2ValidInBufSize); + +u_int8_t kalDevWriteData(IN struct GLUE_INFO *prGlueInfo, + IN struct MSDU_INFO *prMsduInfo); +enum ENUM_CMD_TX_RESULT kalDevWriteCmd(IN struct GLUE_INFO *prGlueInfo, + IN struct CMD_INFO *prCmdInfo, IN uint8_t ucTC); +u_int8_t kalDevKickData(IN struct GLUE_INFO *prGlueInfo); +void kalDevReadIntStatus(IN struct ADAPTER *prAdapter, + OUT uint32_t *pu4IntStatus); + +u_int8_t kalDevWriteWithSdioCmd52(IN struct GLUE_INFO + *prGlueInfo, + IN uint32_t u4Addr, IN uint8_t ucData); + +#if CFG_SUPPORT_EXT_CONFIG +uint32_t kalReadExtCfg(IN struct GLUE_INFO *prGlueInfo); +#endif + +u_int8_t +kalQoSFrameClassifierAndPacketInfo(IN struct GLUE_INFO + *prGlueInfo, + IN void *prPacket, + OUT struct TX_PACKET_INFO *prTxPktInfo); + +u_int8_t kalGetEthDestAddr(IN struct GLUE_INFO *prGlueInfo, + IN void *prPacket, + OUT uint8_t *pucEthDestAddr); + +void +kalOidComplete(IN struct GLUE_INFO *prGlueInfo, + IN u_int8_t fgSetQuery, IN uint32_t u4SetQueryInfoLen, + IN uint32_t rOidStatus); + +uint32_t +kalIoctl(IN struct GLUE_INFO *prGlueInfo, + IN PFN_OID_HANDLER_FUNC pfnOidHandler, + IN void *pvInfoBuf, + IN uint32_t u4InfoBufLen, IN u_int8_t fgRead, + IN u_int8_t fgWaitResp, + IN u_int8_t fgCmd, OUT uint32_t *pu4QryInfoLen); + +uint32_t +kalIoctlByBssIdx(IN struct GLUE_INFO *prGlueInfo, + IN PFN_OID_HANDLER_FUNC pfnOidHandler, + IN void *pvInfoBuf, + IN uint32_t u4InfoBufLen, IN u_int8_t fgRead, + IN u_int8_t fgWaitResp, IN u_int8_t fgCmd, + OUT uint32_t *pu4QryInfoLen, + IN uint8_t ucBssIndex); + +void SET_IOCTL_BSSIDX( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +uint8_t GET_IOCTL_BSSIDX( + IN struct ADAPTER *prAdapter); + +void kalHandleAssocInfo(IN struct GLUE_INFO *prGlueInfo, + IN struct EVENT_ASSOC_INFO *prAssocInfo); + +#if CFG_ENABLE_FW_DOWNLOAD +void *kalFirmwareImageMapping(IN struct GLUE_INFO + *prGlueInfo, + OUT void **ppvMapFileBuf, + OUT uint32_t *pu4FileLength, + IN enum ENUM_IMG_DL_IDX_T eDlIdx); +void kalFirmwareImageUnmapping(IN struct GLUE_INFO + *prGlueInfo, + IN void *prFwHandle, IN void *pvMapFileBuf); +#endif + +#if CFG_CHIP_RESET_SUPPORT +void kalRemoveProbe(IN struct GLUE_INFO *prGlueInfo); +#endif +/*----------------------------------------------------------------------------*/ +/* Card Removal Check */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalIsCardRemoved(IN struct GLUE_INFO *prGlueInfo); + +/*----------------------------------------------------------------------------*/ +/* TX */ +/*----------------------------------------------------------------------------*/ +void kalFlushPendingTxPackets(IN struct GLUE_INFO + *prGlueInfo); + +/*----------------------------------------------------------------------------*/ +/* Media State Indication */ +/*----------------------------------------------------------------------------*/ +enum ENUM_PARAM_MEDIA_STATE kalGetMediaStateIndicated( + IN struct GLUE_INFO + *prGlueInfo, IN uint8_t ucBssIndex); + +void kalSetMediaStateIndicated(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_PARAM_MEDIA_STATE eParamMediaStateIndicate, + IN uint8_t ucBssIndex); + +/*----------------------------------------------------------------------------*/ +/* OID handling */ +/*----------------------------------------------------------------------------*/ +void kalOidCmdClearance(IN struct GLUE_INFO *prGlueInfo); + +void kalOidClearance(IN struct GLUE_INFO *prGlueInfo); + +void kalEnqueueCommand(IN struct GLUE_INFO *prGlueInfo, + IN struct QUE_ENTRY *prQueueEntry); + +#if CFG_ENABLE_BT_OVER_WIFI +/*----------------------------------------------------------------------------*/ +/* Bluetooth over Wi-Fi handling */ +/*----------------------------------------------------------------------------*/ +void kalIndicateBOWEvent(IN struct GLUE_INFO *prGlueInfo, + IN struct BT_OVER_WIFI_EVENT *prEvent); + +enum ENUM_BOW_DEVICE_STATE kalGetBowState( + IN struct GLUE_INFO *prGlueInfo, + IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN]); + +u_int8_t kalSetBowState(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_BOW_DEVICE_STATE eBowState, + uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN]); + +enum ENUM_BOW_DEVICE_STATE kalGetBowGlobalState( + IN struct GLUE_INFO + *prGlueInfo); + +uint32_t kalGetBowFreqInKHz(IN struct GLUE_INFO + *prGlueInfo); + +uint8_t kalGetBowRole(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN]); + +void kalSetBowRole(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRole, + IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN]); + +uint8_t kalGetBowAvailablePhysicalLinkCount( + IN struct GLUE_INFO *prGlueInfo); + +#if CFG_BOW_SEPARATE_DATA_PATH +/*----------------------------------------------------------------------------*/ +/* Bluetooth over Wi-Fi Net Device Init/Uninit */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalInitBowDevice(IN struct GLUE_INFO *prGlueInfo, + IN const char *prDevName); + +u_int8_t kalUninitBowDevice(IN struct GLUE_INFO + *prGlueInfo); +#endif /* CFG_BOW_SEPARATE_DATA_PATH */ +#endif /* CFG_ENABLE_BT_OVER_WIFI */ + +/*----------------------------------------------------------------------------*/ +/* Security Frame Clearance */ +/*----------------------------------------------------------------------------*/ +void kalClearSecurityFrames(IN struct GLUE_INFO + *prGlueInfo); + +void kalClearSecurityFramesByBssIdx(IN struct GLUE_INFO + *prGlueInfo, + IN uint8_t ucBssIndex); + +void kalSecurityFrameSendComplete(IN struct GLUE_INFO + *prGlueInfo, + IN void *pvPacket, IN uint32_t rStatus); + +/*----------------------------------------------------------------------------*/ +/* Management Frame Clearance */ +/*----------------------------------------------------------------------------*/ +void kalClearMgmtFrames(IN struct GLUE_INFO *prGlueInfo); + +void kalClearMgmtFramesByBssIdx(IN struct GLUE_INFO + *prGlueInfo, + IN uint8_t ucBssIndex); + +uint32_t kalGetTxPendingFrameCount(IN struct GLUE_INFO + *prGlueInfo); + +uint32_t kalGetTxPendingCmdCount(IN struct GLUE_INFO + *prGlueInfo); + +void kalClearCommandQueue(IN struct GLUE_INFO *prGlueInfo); + +u_int8_t kalSetTimer(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Interval); + +u_int8_t kalCancelTimer(IN struct GLUE_INFO *prGlueInfo); + +void kalScanDone(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucBssIndex, + IN uint32_t status); + +#if CFG_SUPPORT_SCAN_CACHE_RESULT +uint8_t kalUpdateBssTimestamp(IN struct GLUE_INFO *prGlueInfo); +#endif /* CFG_SUPPORT_SCAN_CACHE_RESULT */ + +uint32_t kalRandomNumber(void); + +#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE +void kalTimeoutHandler(struct timer_list *timer); +#else +void kalTimeoutHandler(unsigned long arg); +#endif + +void kalSetEvent(struct GLUE_INFO *pr); + +void kalSetSerTimeoutEvent(struct GLUE_INFO *pr); + +void kalSetIntEvent(struct GLUE_INFO *pr); + +void kalSetDrvIntEvent(struct GLUE_INFO *pr); + +void kalSetWmmUpdateEvent(struct GLUE_INFO *pr); + +void kalSetHifDbgEvent(struct GLUE_INFO *pr); + +#if CFG_SUPPORT_MULTITHREAD +void kalSetTxEvent2Hif(struct GLUE_INFO *pr); + +void kalSetTxEvent2Rx(struct GLUE_INFO *pr); + +void kalSetTxCmdEvent2Hif(struct GLUE_INFO *pr); + +void kalSetTxCmdDoneEvent(struct GLUE_INFO *pr); + +void kalSetRxProcessEvent(struct GLUE_INFO *pr); +#endif +/*----------------------------------------------------------------------------*/ +/* NVRAM/Registry Service */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalIsConfigurationExist(IN struct GLUE_INFO + *prGlueInfo); + +struct REG_INFO *kalGetConfiguration(IN struct GLUE_INFO + *prGlueInfo); + +u_int8_t kalCfgDataRead(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Offset, + IN ssize_t len, OUT uint16_t *pu2Data); + +u_int8_t kalCfgDataRead16(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Offset, + OUT uint16_t *pu2Data); + +u_int8_t kalCfgDataWrite16(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Offset, IN uint16_t u2Data); + +u_int8_t kalCfgDataWrite8(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Offset, IN uint8_t u2Data); + + +/*----------------------------------------------------------------------------*/ +/* RSSI Updating */ +/*----------------------------------------------------------------------------*/ +void +kalUpdateRSSI(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucBssIndex, + IN int8_t cRssi, + IN int8_t cLinkQuality); + +/*----------------------------------------------------------------------------*/ +/* I/O Buffer Pre-allocation */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalInitIOBuffer(u_int8_t is_pre_alloc); + +void kalUninitIOBuffer(void); + +void *kalAllocateIOBuffer(IN uint32_t u4AllocSize); + +void kalReleaseIOBuffer(IN void *pvAddr, + IN uint32_t u4Size); + +void +kalGetChannelList(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_BAND eSpecificBand, + IN uint8_t ucMaxChannelNum, IN uint8_t *pucNumOfChannel, + IN struct RF_CHANNEL_INFO *paucChannelList); + +u_int8_t kalIsAPmode(IN struct GLUE_INFO *prGlueInfo); + +#if CFG_SUPPORT_802_11W +/*----------------------------------------------------------------------------*/ +/* 802.11W */ +/*----------------------------------------------------------------------------*/ +uint32_t kalGetMfpSetting(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucBssIndex); +uint8_t kalGetRsnIeMfpCap(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucBssIndex); +#endif + +/*----------------------------------------------------------------------------*/ +/* file opetation */ +/*----------------------------------------------------------------------------*/ +uint32_t kalWriteToFile(const uint8_t *pucPath, + u_int8_t fgDoAppend, + uint8_t *pucData, uint32_t u4Size); + +uint32_t kalCheckPath(const uint8_t *pucPath); + +uint32_t kalTrunkPath(const uint8_t *pucPath); + +int32_t kalReadToFile(const uint8_t *pucPath, + uint8_t *pucData, + uint32_t u4Size, uint32_t *pu4ReadSize); + +int32_t kalRequestFirmware(const uint8_t *pucPath, + uint8_t *pucData, + uint32_t u4Size, uint32_t *pu4ReadSize, + struct device *dev); + + +/*----------------------------------------------------------------------------*/ +/* NL80211 */ +/*----------------------------------------------------------------------------*/ +void +kalIndicateBssInfo(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucFrameBuf, IN uint32_t u4BufLen, + IN uint8_t ucChannelNum, IN int32_t i4SignalStrength); + +/*----------------------------------------------------------------------------*/ +/* Net device */ +/*----------------------------------------------------------------------------*/ +uint32_t +kalHardStartXmit(struct sk_buff *prSkb, + IN struct net_device *prDev, + struct GLUE_INFO *prGlueInfo, uint8_t ucBssIndex); + +u_int8_t kalIsPairwiseEapolPacket(IN void *prPacket); + +u_int8_t +kalGetIPv4Address(IN struct net_device *prDev, + IN uint32_t u4MaxNumOfAddr, OUT uint8_t *pucIpv4Addrs, + OUT uint32_t *pu4NumOfIpv4Addr); + +#if IS_ENABLED(CONFIG_IPV6) +u_int8_t +kalGetIPv6Address(IN struct net_device *prDev, + IN uint32_t u4MaxNumOfAddr, OUT uint8_t *pucIpv6Addrs, + OUT uint32_t *pu4NumOfIpv6Addr); +#else +static inline u_int8_t +kalGetIPv6Address(IN struct net_device *prDev, + IN uint32_t u4MaxNumOfAddr, OUT uint8_t *pucIpv6Addrs, + OUT uint32_t *pu4NumOfIpv6Addr) { + /* Not support IPv6 */ + *pu4NumOfIpv6Addr = 0; + return 0; +} +#endif /* IS_ENABLED(CONFIG_IPV6) */ + +void kalSetNetAddressFromInterface(IN struct GLUE_INFO + *prGlueInfo, + IN struct net_device *prDev, + IN u_int8_t fgSet); + +uint32_t kalResetStats(IN struct net_device *prDev); + +void *kalGetStats(IN struct net_device *prDev); + +void kalResetPacket(IN struct GLUE_INFO *prGlueInfo, + IN void *prPacket); + +#if CFG_SUPPORT_QA_TOOL +struct file *kalFileOpen(const char *path, int flags, + int rights); + +void kalFileClose(struct file *file); + +uint32_t kalFileRead(struct file *file, + unsigned long long offset, + unsigned char *data, unsigned int size); +#endif + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN +/*----------------------------------------------------------------------------*/ +/* SDIO Read/Write Pattern Support */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalSetSdioTestPattern(IN struct GLUE_INFO + *prGlueInfo, + IN u_int8_t fgEn, IN u_int8_t fgRead); +#endif + +/*----------------------------------------------------------------------------*/ +/* PNO Support */ +/*----------------------------------------------------------------------------*/ +void kalSchedScanResults(IN struct GLUE_INFO *prGlueInfo); + +void kalSchedScanStopped(IN struct GLUE_INFO *prGlueInfo, + u_int8_t fgDriverTriggerd); + +void kalSetFwOwnEvent2Hif(struct GLUE_INFO *pr); +#if CFG_ASSERT_DUMP +/* Core Dump out put file */ +uint32_t kalOpenCorDumpFile(u_int8_t fgIsN9); +uint32_t kalWriteCorDumpFile(uint8_t *pucBuffer, + uint16_t u2Size, + u_int8_t fgIsN9); +uint32_t kalCloseCorDumpFile(u_int8_t fgIsN9); +#endif +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#if CFG_WOW_SUPPORT +void kalWowInit(IN struct GLUE_INFO *prGlueInfo); +void kalWowProcess(IN struct GLUE_INFO *prGlueInfo, + uint8_t enable); +#endif + +int main_thread(void *data); + +#if CFG_SUPPORT_MULTITHREAD +int hif_thread(void *data); +int rx_thread(void *data); +#endif +uint64_t kalGetBootTime(void); + +int kalMetInitProcfs(IN struct GLUE_INFO *prGlueInfo); +int kalMetRemoveProcfs(void); + +uint8_t kalGetEapolKeyType(void *prPacket); + +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG +u_int8_t kalIsWakeupByWlan(struct ADAPTER *prAdapter); +#endif + +int32_t kalHaltLock(uint32_t waitMs); +int32_t kalHaltTryLock(void); +void kalHaltUnlock(void); +void kalSetHalted(u_int8_t fgHalt); +u_int8_t kalIsHalted(void); + +void kalFreeTxMsduWorker(struct work_struct *work); +void kalFreeTxMsdu(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +int32_t kalPerMonInit(IN struct GLUE_INFO *prGlueInfo); +int32_t kalPerMonDisable(IN struct GLUE_INFO *prGlueInfo); +int32_t kalPerMonEnable(IN struct GLUE_INFO *prGlueInfo); +int32_t kalPerMonStart(IN struct GLUE_INFO *prGlueInfo); +int32_t kalPerMonStop(IN struct GLUE_INFO *prGlueInfo); +int32_t kalPerMonDestroy(IN struct GLUE_INFO *prGlueInfo); +void kalPerMonHandler(IN struct ADAPTER *prAdapter, + unsigned long ulParam); +uint32_t kalPerMonGetInfo(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, + IN uint32_t u4Max); +int32_t kalBoostCpu(IN struct ADAPTER *prAdapter, + IN uint32_t u4TarPerfLevel, + IN uint32_t u4BoostCpuTh); +int32_t kalCheckTputLoad(IN struct ADAPTER *prAdapter, + IN uint32_t u4CurrPerfLevel, + IN uint32_t u4TarPerfLevel, + IN int32_t i4Pending, + IN uint32_t u4Used); +uint32_t kalGetCpuBoostThreshold(void); +void kalSetRpsMap(IN struct GLUE_INFO *glue, IN unsigned long value); +extern int set_task_util_min_pct(pid_t pid, unsigned int min); + +#if CFG_MTK_ANDROID_EMI +void kalSetEmiMpuProtection(phys_addr_t emiPhyBase, bool enable); +void kalSetDrvEmiMpuProtection(phys_addr_t emiPhyBase, uint32_t offset, + uint32_t size); +#endif +int32_t kalSetCpuNumFreq(uint32_t u4CoreNum, + uint32_t u4Freq); +int32_t kalGetFwFlavor(uint8_t *flavor); +int32_t kalGetConnsysVerId(void); +int32_t kalPerMonSetForceEnableFlag(uint8_t uFlag); +int32_t kalFbNotifierReg(IN struct GLUE_INFO *prGlueInfo); +void kalFbNotifierUnReg(void); + +#if KERNEL_VERSION(3, 0, 0) <= LINUX_VERSION_CODE +/* since: 0b5c9db1b11d3175bb42b80663a9f072f801edf5 */ +static inline void kal_skb_reset_mac_len(struct sk_buff + *skb) +{ + skb_reset_mac_len(skb); +} +#else +static inline void kal_skb_reset_mac_len(struct sk_buff + *skb) +{ + skb->mac_len = skb->network_header - skb->mac_header; +} +#endif + +void kalInitDevWakeup(struct ADAPTER *prAdapter, struct device *prDev); + +u_int8_t kalIsValidMacAddr(const uint8_t *addr); + +u_int8_t kalScanParseRandomMac(const struct net_device *ndev, + const struct cfg80211_scan_request *request, uint8_t *pucRandomMac); + +u_int8_t kalSchedScanParseRandomMac(const struct net_device *ndev, + const struct cfg80211_sched_scan_request *request, + uint8_t *pucRandomMac, uint8_t *pucRandomMacMask); + +void kalScanReqLog(struct cfg80211_scan_request *request); +void kalScanResultLog(struct ADAPTER *prAdapter, struct ieee80211_mgmt *mgmt); +void kalScanLogCacheFlushBSS(struct ADAPTER *prAdapter, + const uint16_t logBufLen); +int kalMaskMemCmp(const void *cs, const void *ct, + const void *mask, size_t count); + +u_int8_t +kalChannelScoSwitch(IN enum nl80211_channel_type channel_type, + IN enum ENUM_CHNL_EXT *prChnlSco); + +u_int8_t +kalChannelFormatSwitch(IN struct cfg80211_chan_def *channel_def, + IN struct ieee80211_channel *channel, + IN struct RF_CHANNEL_INFO *prRfChnlInfo); + +#if CFG_SUPPORT_RX_GRO +uint32_t kal_is_skb_gro(struct ADAPTER *prAdapter, uint8_t ucBssIdx); +void kal_gro_flush(struct ADAPTER *prAdapter, struct net_device *prDev); +#endif + +void kalRemoveBss(struct GLUE_INFO *prGlueInfo, + uint8_t aucBSSID[], + uint8_t ucChannelNum, + enum ENUM_BAND eBand); + +#if CFG_SUPPORT_WPA3 +int kalExternalAuthRequest(IN struct ADAPTER *prAdapter, + IN uint8_t uBssIndex); +#endif + +int kalWlanUeventInit(void); +void kalWlanUeventDeinit(void); + +int _kalSnprintf(char *buf, size_t size, const char *fmt, ...); +int _kalSprintf(char *buf, const char *fmt, ...); + +/* systrace utilities */ +#if !CONFIG_WLAN_DRV_BUILD_IN +void tracing_mark_write(const char *fmt, ...); +#endif + +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE +void kal_do_gettimeofday(struct timeval *tv); +#endif + +uint32_t kalSetSuspendFlagToEMI(IN struct ADAPTER + *prAdapter, IN u_int8_t fgSuspend); + +extern uint32_t get_wifi_standalone_log_mode(void); +void kalPrintLog(const char *fmt, ...); +void kalPrintLogLimited(const char *fmt, ...); + +#endif /* _GL_KAL_H */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_os.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_os.h new file mode 100644 index 0000000000000..019ef1914b9db --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_os.h @@ -0,0 +1,1435 @@ + +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include + * /gl_os.h#4 + */ + +/*! \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. + */ + + +#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 */ + +/* 1: Enable use of SPIN LOCK Bottom Half for LINUX */ +/* 0: Disable - use SPIN LOCK IRQ SAVE instead */ +#define CFG_USE_SPIN_LOCK_BOTTOM_HALF 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_PADDING_SMALL_ETH_PACKET 0 + +#define CFG_TX_STOP_NETIF_QUEUE_THRESHOLD 256 /* packets */ + +#if (CFG_SUPPORT_CONNAC2X == 1) +#define CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD 1024 /* packets */ +#define CFG_TX_START_NETIF_PER_QUEUE_THRESHOLD 512 /* packets */ +#else +#define CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD 256 /* packets */ +#define CFG_TX_START_NETIF_PER_QUEUE_THRESHOLD 128 /* packets */ +#endif + + +#define CHIP_NAME "MT6632" + +#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) +#define GLUE_INFO_WSCIE_LENGTH (500) +/* for non-wfa vendor specific IE buffer */ +#define NON_WFA_VENDOR_IE_MAX_LEN (128) + + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include /* constant of kernel version */ + +#include /* bitops.h */ + +#include /* struct timer_list */ +#include /* jiffies */ +#include /* udelay and mdelay macro */ +#include +#include +#include + +#ifdef CONFIG_ANDROID +#if (KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE) +#include +#include +#else +#include +#endif +#endif + +#if KERNEL_VERSION(2, 6, 12) < LINUX_VERSION_CODE +#include /* IRQT_FALLING */ +#endif + +#include /* struct net_device, struct net_device_stats */ +#include /* for eth_type_trans() function */ +#include /* struct iw_statistics */ +#include +#include /* struct in_device */ + +#include /* struct iphdr */ + +#include /* for memcpy()/memset() function */ +#include /* for offsetof() macro */ + +#include /* The proc filesystem constants/structures */ + +#include /* for rtnl_lock() and rtnl_unlock() */ +#include /* kthread_should_stop(), kthread_run() */ +#include /* for copy_from_user() */ +#include /* for firmware download */ +#include + +#include /* for kfifo interface */ +#include /* for cdev interface */ + +#include /* for firmware download */ +#include + +#include + +#if defined(_HIF_USB) +#include +#include +#include +#endif + +#if defined(_HIF_PCIE) +#include +#endif + +#if defined(_HIF_SDIO) +#include +#include +#include +#endif + +#include + +#include /* readw and writew */ + +#if WIRELESS_EXT > 12 +#include +#endif + +#ifdef CFG_CFG80211_VERSION +#define CFG80211_VERSION_CODE CFG_CFG80211_VERSION +#else +#define CFG80211_VERSION_CODE LINUX_VERSION_CODE +#endif + +#include "version.h" +#include "config.h" + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#include +#include +#endif + +#include +#include +#include + +#if IS_ENABLED(CONFIG_IPV6) +#include +#include +#include +#endif + +#if CFG_SUPPORT_PASSPOINT +#include +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE +#include +#endif + +#ifdef UDP_SKT_WIFI +#if (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) +#include +#else +#include +#endif +#endif + +#include "gl_typedef.h" +#include "typedef.h" +#include "queue.h" +#include "gl_kal.h" +#include "gl_rst.h" +#include "hif.h" + +#if CFG_SUPPORT_TDLS +#include "tdls.h" +#endif + +#include "debug.h" + +#include "wlan_lib.h" +#include "wlan_oid.h" + +#if CFG_ENABLE_AEE_MSG +#ifdef CONFIG_ANDROID +#include +#else +#include +#endif +#endif + +#if CFG_MET_TAG_SUPPORT +#include +#endif +#include +#include + +#if (CONFIG_WLAN_SERVICE == 1) +#include "agent.h" +#endif + +extern u_int8_t fgIsBusAccessFailed; +extern const struct ieee80211_iface_combination + *p_mtk_iface_combinations_sta; +extern const int32_t mtk_iface_combinations_sta_num; +extern const struct ieee80211_iface_combination + *p_mtk_iface_combinations_p2p; +extern const int32_t mtk_iface_combinations_p2p_num; +extern uint8_t g_aucNvram[]; + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH +typedef void (*wifi_fwlog_event_func_cb)(int, int); +/* adaptor ko */ +extern int wifi_fwlog_onoff_status(void); +extern void wifi_fwlog_event_func_register(wifi_fwlog_event_func_cb pfFwlog); +#endif +#if CFG_MTK_ANDROID_WMT +extern void update_driver_loaded_status(uint8_t loaded); +#endif + +/******************************************************************************* + * 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_SER_TIMEOUT BIT(5) +#define GLUE_FLAG_SUB_MOD_MULTICAST BIT(7) +#define GLUE_FLAG_FRAME_FILTER BIT(8) +#define GLUE_FLAG_FRAME_FILTER_AIS BIT(9) + +#define GLUE_FLAG_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_SER_TIMEOUT_BIT (5) +#define GLUE_FLAG_SUB_MOD_MULTICAST_BIT (7) +#define GLUE_FLAG_FRAME_FILTER_BIT (8) +#define GLUE_FLAG_FRAME_FILTER_AIS_BIT (9) + +#if CFG_SUPPORT_MULTITHREAD +#define GLUE_FLAG_RX BIT(10) +#define GLUE_FLAG_TX_CMD_DONE BIT(11) +#define GLUE_FLAG_HIF_TX BIT(12) +#define GLUE_FLAG_HIF_TX_CMD BIT(13) +#define GLUE_FLAG_RX_TO_OS BIT(14) +#define GLUE_FLAG_HIF_FW_OWN BIT(15) +#define GLUE_FLAG_HIF_PRT_HIF_DBG_INFO BIT(16) +#define GLUE_FLAG_UPDATE_WMM_QUOTA BIT(17) +#define GLUE_FLAG_NOTIFY_MD_CRASH BIT(18) +#define GLUE_FLAG_DRV_INT BIT(19) + +#define GLUE_FLAG_RX_BIT (10) +#define GLUE_FLAG_TX_CMD_DONE_BIT (11) +#define GLUE_FLAG_HIF_TX_BIT (12) +#define GLUE_FLAG_HIF_TX_CMD_BIT (13) +#define GLUE_FLAG_RX_TO_OS_BIT (14) +#define GLUE_FLAG_HIF_FW_OWN_BIT (15) +#define GLUE_FLAG_HIF_PRT_HIF_DBG_INFO_BIT (16) +#define GLUE_FLAG_UPDATE_WMM_QUOTA_BIT (17) +#define GLUE_FLAG_NOTIFY_MD_CRASH_BIT (18) +#define GLUE_FLAG_DRV_INT_BIT (19) +#endif +#if (CFG_SUPPORT_CONNINFRA == 1) +#define GLUE_FLAG_RST_START BIT(18) +#define GLUE_FLAG_RST_START_BIT 18 +#define GLUE_FLAG_RST_END BIT(19) +#define GLUE_FLAG_RST_END_BIT 19 + +#endif +#define GLUE_BOW_KFIFO_DEPTH (1024) +/* #define GLUE_BOW_DEVICE_NAME "MT6620 802.11 AMP" */ +#define GLUE_BOW_DEVICE_NAME "ampc0" + +#define WAKE_LOCK_RX_TIMEOUT 300 /* ms */ +#define WAKE_LOCK_THREAD_WAKEUP_TIMEOUT 50 /* ms */ + +#define STR_HELPER(x) #x +#define STR(x) STR_HELPER(x) + +#define IW_AUTH_CIPHER_GCMP256 0x00000080 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +struct GLUE_INFO; + +struct GL_WPA_INFO { + uint32_t u4WpaVersion; + uint32_t u4KeyMgmt; + uint32_t u4CipherGroup; + uint32_t u4CipherPairwise; + uint32_t u4AuthAlg; + u_int8_t fgPrivacyInvoke; +#if CFG_SUPPORT_802_11W + uint32_t u4Mfp; + uint8_t ucRSNMfpCap; +#endif +}; + +#if CFG_SUPPORT_REPLAY_DETECTION +struct GL_REPLEY_PN_INFO { + uint8_t auPN[16]; + u_int8_t fgRekey; + u_int8_t fgFirstPkt; +}; +struct GL_DETECT_REPLAY_INFO { + uint8_t ucCurKeyId; + uint8_t ucKeyType; + struct GL_REPLEY_PN_INFO arReplayPNInfo[4]; +}; +#endif + +enum ENUM_NET_DEV_IDX { + NET_DEV_WLAN_IDX = 0, + NET_DEV_P2P_IDX, + NET_DEV_BOW_IDX, + NET_DEV_NUM +}; + +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 +}; + +#if CFG_ENABLE_WIFI_DIRECT +enum ENUM_NET_REG_STATE { + 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 +}; +#endif + +enum ENUM_PKT_FLAG { + ENUM_PKT_802_11, /* 802.11 or non-802.11 */ + ENUM_PKT_802_3, /* 802.3 or ethernetII */ + ENUM_PKT_1X, /* 1x frame or not */ + ENUM_PKT_PROTECTED_1X, /* protected 1x frame */ + ENUM_PKT_NON_PROTECTED_1X, /* Non protected 1x frame */ + ENUM_PKT_VLAN_EXIST, /* VLAN tag exist */ + ENUM_PKT_DHCP, /* DHCP frame */ + ENUM_PKT_ARP, /* ARP */ + ENUM_PKT_ICMP, /* ICMP */ + ENUM_PKT_TDLS, /* TDLS */ + ENUM_PKT_DNS, /* DNS */ + + ENUM_PKT_FLAG_NUM +}; + +enum ENUM_WLAN_DRV_BUF_TYPE_T { + ENUM_BUF_TYPE_NVRAM, + ENUM_BUF_TYPE_DRV_CFG, + ENUM_BUF_TYPE_FW_CFG, + ENUM_BUF_TYPE_NUM +}; + +enum ENUM_NVRAM_STATE { + NVRAM_STATE_INIT = 0, + NVRAM_STATE_READY, /*power on or update*/ + NVRAM_STATE_SEND_TO_FW, + NVRAM_STATE_NUM +}; + +/* WMM QOS user priority from 802.1D/802.11e */ +enum ENUM_WMM_UP { + WMM_UP_BE_INDEX = 0, + WMM_UP_BK_INDEX, + WMM_UP_RESV_INDEX, + WMM_UP_EE_INDEX, + WMM_UP_CL_INDEX, + WMM_UP_VI_INDEX, + WMM_UP_VO_INDEX, + WMM_UP_NC_INDEX, + WMM_UP_INDEX_NUM +}; + +struct GL_IO_REQ { + struct QUE_ENTRY rQueEntry; + /* wait_queue_head_t cmdwait_q; */ + u_int8_t fgRead; + u_int8_t fgWaitResp; + struct ADAPTER *prAdapter; + PFN_OID_HANDLER_FUNC pfnOidHandler; + void *pvInfoBuf; + uint32_t u4InfoBufLen; + uint32_t *pu4QryInfoLen; + uint32_t rStatus; + uint32_t u4Flag; + uint8_t ucBssIndex; +}; + +#if CFG_ENABLE_BT_OVER_WIFI +struct GL_BOW_INFO { + u_int8_t 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; + uint32_t u4FreqInKHz; /* frequency */ + + uint8_t aucRole[CFG_BOW_PHYSICAL_LINK_NUM]; /* 0: Responder, + * 1: Initiator + */ + enum ENUM_BOW_DEVICE_STATE + aeState[CFG_BOW_PHYSICAL_LINK_NUM]; + uint8_t arPeerAddr[CFG_BOW_PHYSICAL_LINK_NUM][PARAM_MAC_ADDR_LEN]; + + wait_queue_head_t outq; + +#if CFG_BOW_SEPARATE_DATA_PATH + /* Device handle */ + struct net_device *prDevHandler; + u_int8_t fgIsNetRegistered; +#endif + +}; +#endif + +#if CFG_SUPPORT_SCAN_CACHE_RESULT +struct GL_SCAN_CACHE_INFO { + struct GLUE_INFO *prGlueInfo; + + /* for cfg80211 scan done indication */ + struct cfg80211_scan_request *prRequest; + + /* total number of channels to scan */ + uint32_t n_channels; + + /* Scan period time */ + OS_SYSTIME u4LastScanTime; + + /* Bss index */ + uint8_t ucBssIndex; + + /* scan request flags */ + uint32_t u4Flags; +}; +#endif /* CFG_SUPPORT_SCAN_CACHE_RESULT */ + +#if CFG_SUPPORT_PERF_IND + struct GL_PERF_IND_INFO { + uint32_t u4CurTxBytes[BSSID_NUM]; /* Byte */ + uint32_t u4CurRxBytes[BSSID_NUM]; /* Byte */ + uint16_t u2CurRxRate[BSSID_NUM]; /* Unit 500 Kbps */ + uint8_t ucCurRxRCPI0[BSSID_NUM]; + uint8_t ucCurRxRCPI1[BSSID_NUM]; + uint8_t ucCurRxNss[BSSID_NUM]; + }; +#endif /* CFG_SUPPORT_SCAN_CACHE_RESULT */ + +struct FT_IES { + uint16_t u2MDID; + struct IE_MOBILITY_DOMAIN *prMDIE; + struct IE_FAST_TRANSITION *prFTIE; + struct IE_TIMEOUT_INTERVAL *prTIE; + struct RSN_INFO_ELEM *prRsnIE; + uint8_t *pucIEBuf; + uint32_t u4IeLength; +}; + +/* + * type definition of pointer to p2p structure + */ +struct GL_P2P_INFO; /* declare GL_P2P_INFO_T */ +struct GL_P2P_DEV_INFO; /* declare GL_P2P_DEV_INFO_T */ + +struct GLUE_INFO { + /* Device handle */ + struct net_device *prDevHandler; + + /* Device */ + struct device *prDev; + + /* Device Index(index of arWlanDevInfo[]) */ + int32_t i4DevIdx; + + /* Device statistics */ + /* struct net_device_stats rNetDevStats; */ + + /* Wireless statistics struct net_device */ + struct iw_statistics rIwStats[BSSID_NUM]; + + /* spinlock to sync power save mechanism */ + spinlock_t rSpinLock[SPIN_LOCK_NUM]; + + /* Mutex to protect interruptible section */ + struct mutex arMutex[MUTEX_NUM]; + + /* semaphore for ioctl */ + struct semaphore ioctl_sem; + + uint64_t u8Cookie; + + unsigned long ulFlag; /* GLUE_FLAG_XXX */ + uint32_t u4PendFlag; + /* UINT_32 u4TimeoutFlag; */ + uint32_t u4OidCompleteFlag; + uint32_t u4ReadyFlag; /* check if card is ready */ + + uint32_t u4OsMgmtFrameFilter; + + /* Number of pending frames, also used for debuging if any frame is + * missing during the process of unloading Driver. + * + * NOTE(Kevin): In Linux, we also use this variable as the threshold + * for manipulating the netif_stop(wake)_queue() func. + */ + int32_t ai4TxPendingFrameNumPerQueue[MAX_BSSID_NUM][CFG_MAX_TXQ_NUM]; + int32_t i4TxPendingFrameNum; + int32_t i4TxPendingSecurityFrameNum; + int32_t i4TxPendingCmdNum; + + /* Tx: for NetDev to BSS index mapping */ + struct NET_INTERFACE_INFO arNetInterfaceInfo[MAX_BSSID_NUM]; + + /* Rx: for BSS index to NetDev mapping */ + /* P_NET_INTERFACE_INFO_T aprBssIdxToNetInterfaceInfo[HW_BSSID_NUM]; */ + + /* current IO request for kalIoctl */ + struct GL_IO_REQ OidEntry; + + /* registry info */ + struct REG_INFO rRegInfo; + + /* firmware */ + struct firmware *prFw; + + /* Host interface related information */ + /* defined in related hif header file */ + struct GL_HIF_INFO rHifInfo; + + /*! \brief wext wpa related information */ + struct GL_WPA_INFO rWpaInfo[KAL_AIS_NUM]; +#if CFG_SUPPORT_REPLAY_DETECTION + struct GL_DETECT_REPLAY_INFO prDetRplyInfo[KAL_AIS_NUM]; +#endif + + /* Pointer to ADAPTER_T - main data structure of internal protocol + * stack + */ + struct ADAPTER *prAdapter; + +#if WLAN_INCLUDE_PROC + struct proc_dir_entry *pProcRoot; +#endif /* WLAN_INCLUDE_PROC */ + + /* Indicated media state */ + enum ENUM_PARAM_MEDIA_STATE + eParamMediaStateIndicated[KAL_AIS_NUM]; + + /* Device power state D0~D3 */ + enum 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_SUPPORT_MULTITHREAD + struct completion + rHifHaltComp; /* indicate hif_thread halt complete */ + struct completion + rRxHaltComp; /* indicate hif_thread halt complete */ + + uint32_t u4TxThreadPid; + uint32_t u4RxThreadPid; + uint32_t u4HifThreadPid; +#endif + +#if CFG_SUPPORT_NCHO + struct completion + rAisChGrntComp; /* indicate Ais channel grant complete */ +#endif + + uint32_t rPendStatus; + + struct QUE rTxQueue; + + /* OID related */ + struct QUE 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; + +#if CFG_SUPPORT_MULTITHREAD + wait_queue_head_t waitq_hif; + struct task_struct *hif_thread; + + wait_queue_head_t waitq_rx; + struct task_struct *rx_thread; + +#endif + struct tasklet_struct rRxTask; + struct tasklet_struct rTxCompleteTask; + + struct work_struct rTxMsduFreeWork; + struct delayed_work rRxPktDeAggWork; + + struct timer_list tickfn; + +#if CFG_SUPPORT_EXT_CONFIG + uint16_t au2ExtCfg[256]; /* NVRAM data buffer */ + uint32_t u4ExtCfgLength; /* 0 means data is NOT valid */ +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + struct GL_BOW_INFO rBowInfo; +#endif + +#if CFG_ENABLE_WIFI_DIRECT + struct GL_P2P_DEV_INFO *prP2PDevInfo; + struct GL_P2P_INFO *prP2PInfo[KAL_P2P_NUM]; +#if CFG_SUPPORT_P2P_RSSI_QUERY + /* Wireless statistics struct net_device */ + struct iw_statistics rP2pIwStats; +#endif +#endif + + /* NVRAM availability */ + u_int8_t fgNvramAvailable; + + u_int8_t fgMcrAccessAllowed; + + /* MAC Address Overridden by IOCTL */ + u_int8_t fgIsMacAddrOverride; + uint8_t rMacAddrOverride[PARAM_MAC_ADDR_LEN]; + + struct SET_TXPWR_CTRL rTxPwr; + + /* for cfg80211 scan done indication */ + struct cfg80211_scan_request *prScanRequest; + +#if CFG_SUPPORT_SCHED_SCAN + struct PARAM_SCHED_SCAN_REQUEST *prSchedScanRequest; +#else + /* for cfg80211 scheduled scan */ + struct cfg80211_sched_scan_request *prSchedScanRequest; +#endif + + /* to indicate registered or not */ + u_int8_t fgIsRegistered; + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN + u_int8_t fgEnSdioTestPattern; + u_int8_t fgSdioReadWriteMode; + u_int8_t fgIsSdioTestInitialized; + uint8_t aucSdioTestBuffer[256]; +#endif + + u_int8_t fgIsInSuspendMode; + +#if CFG_SUPPORT_PASSPOINT + u_int8_t fgIsDad; + uint8_t aucDADipv4[4]; + u_int8_t fgIs6Dad; + uint8_t aucDADipv6[16]; +#endif /* CFG_SUPPORT_PASSPOINT */ + + KAL_WAKE_LOCK_T *rIntrWakeLock; + KAL_WAKE_LOCK_T *rTimeoutWakeLock; + +#if CFG_MET_PACKET_TRACE_SUPPORT + u_int8_t fgMetProfilingEn; + uint16_t u2MetUdpPort; +#endif + +#if CFG_SUPPORT_SNIFFER + u_int8_t fgIsEnableMon; + struct net_device *prMonDevHandler; + struct work_struct monWork; +#endif + + int32_t i4RssiCache[BSSID_NUM]; + uint32_t u4LinkSpeedCache[BSSID_NUM]; + + + uint32_t u4InfType; + + uint32_t IsrCnt; + uint32_t IsrPassCnt; + uint32_t TaskIsrCnt; + + uint32_t IsrAbnormalCnt; + uint32_t IsrSoftWareCnt; + uint32_t IsrTxCnt; + uint32_t IsrRxCnt; + uint64_t u8HifIntTime; + + /* save partial scan channel information */ + /* PARTIAL_SCAN_INFO rScanChannelInfo; */ + uint8_t *pucScanChannel; + +#if CFG_SUPPORT_SCAN_CACHE_RESULT + struct GL_SCAN_CACHE_INFO scanCache; +#endif /* CFG_SUPPORT_SCAN_CACHE_RESULT */ +#if (CFG_SUPPORT_PERF_IND == 1) + struct GL_PERF_IND_INFO PerfIndCache; +#endif + + /* Full2Partial */ + OS_SYSTIME u4LastFullScanTime; + /* full scan or partial scan */ + uint8_t ucTrScanType; + /* UINT_8 aucChannelNum[FULL_SCAN_MAX_CHANNEL_NUM]; */ + /* PARTIAL_SCAN_INFO rFullScanApChannel; */ + uint8_t *pucFullScan2PartialChannel; + + uint32_t u4RoamFailCnt; + uint64_t u8RoamFailTime; + u_int8_t fgTxDoneDelayIsARP; + uint32_t u4ArriveDrvTick; + uint32_t u4EnQueTick; + uint32_t u4DeQueTick; + uint32_t u4LeaveDrvTick; + uint32_t u4CurrTick; + uint64_t u8CurrTime; + + /* FW Roaming */ + /* store the FW roaming enable state which FWK determines */ + /* if it's = 0, ignore the black/whitelists settings from FWK */ + uint32_t u4FWRoamingEnable; + + /*service for test mode*/ +#if (CONFIG_WLAN_SERVICE == 1) + struct service rService; +#endif +#if CFG_SUPPORT_SCAN_EXT_FLAG + uint32_t u4ScanExtFlag; +#endif +}; + +typedef irqreturn_t(*PFN_WLANISR) (int irq, void *dev_id, + struct pt_regs *regs); + +typedef void (*PFN_LINUX_TIMER_FUNC) (unsigned long); + +/* generic sub module init/exit handler + * now, we only have one sub module, p2p + */ +#if CFG_ENABLE_WIFI_DIRECT +typedef u_int8_t(*SUB_MODULE_INIT) (struct GLUE_INFO + *prGlueInfo); +typedef u_int8_t(*SUB_MODULE_EXIT) (struct GLUE_INFO + *prGlueInfo); + +struct SUB_MODULE_HANDLER { + SUB_MODULE_INIT subModInit; + SUB_MODULE_EXIT subModExit; + u_int8_t fgIsInited; +}; + +#endif + +#ifdef CONFIG_NL80211_TESTMODE + +enum TestModeCmdType { + TESTMODE_CMD_ID_SW_CMD = 1, + TESTMODE_CMD_ID_WAPI = 2, + TESTMODE_CMD_ID_HS20 = 3, + + /* Hotspot managerment testmode command */ + TESTMODE_CMD_ID_HS_CONFIG = 51, + + TESTMODE_CMD_ID_STR_CMD = 102, + + TESTMODE_CMD_ID_UPDATE_STA_PMKID = 1000, + NUM_OF_TESTMODE_CMD_ID +}; + +#if CFG_SUPPORT_PASSPOINT +enum Hs20CmdType { + HS20_CMD_ID_SET_BSSID_POOL = 0, + NUM_OF_HS20_CMD_ID +}; +#endif /* CFG_SUPPORT_PASSPOINT */ + +struct NL80211_DRIVER_TEST_MODE_PARAMS { + uint32_t index; + uint32_t buflen; +}; + +struct NL80211_DRIVER_STRING_CMD_PARAMS { + struct NL80211_DRIVER_TEST_MODE_PARAMS hdr; + uint32_t reply_buf_size; + uint32_t reply_len; + uint8_t *reply_buf; +}; + +/*SW CMD */ +struct NL80211_DRIVER_SW_CMD_PARAMS { + struct NL80211_DRIVER_TEST_MODE_PARAMS hdr; + uint8_t set; + uint32_t adr; + uint32_t data; +}; + +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 */ + /*!< ff:ff:ff:ff:ff:ff for broadcast/multicast + * (group) keys or unicast address for + * individual keys + */ + __u8 addr[MAC_ADDR_LEN]; + __u16 alg; /*!< IW_ENCODE_ALG_* */ + __u16 key_len; + __u8 key[32]; +}; + +/*SET KEY EXT */ +struct NL80211_DRIVER_SET_KEY_EXTS { + struct NL80211_DRIVER_TEST_MODE_PARAMS hdr; + uint8_t key_index; + uint8_t key_len; + struct iw_encode_exts ext; +}; + +#if CFG_SUPPORT_PASSPOINT + +struct param_hs20_set_bssid_pool { + uint8_t fgBssidPoolIsEnable; + uint8_t ucNumBssidPool; + uint8_t arBssidPool[8][ETH_ALEN]; +}; + +struct wpa_driver_hs20_data_s { + struct NL80211_DRIVER_TEST_MODE_PARAMS hdr; + enum Hs20CmdType CmdType; + struct param_hs20_set_bssid_pool hs20_set_bssid_pool; +}; + +#endif /* CFG_SUPPORT_PASSPOINT */ + +#endif + +struct NETDEV_PRIVATE_GLUE_INFO { + struct GLUE_INFO *prGlueInfo; + uint8_t ucBssIdx; +#if CFG_ENABLE_UNIFY_WIPHY + u_int8_t ucIsP2p; +#endif + u_int8_t ucMddpSupport; +#if CFG_SUPPORT_RX_GRO + struct napi_struct napi; + OS_SYSTIME tmGROFlushTimeout; + spinlock_t napi_spinlock; +#endif + struct net_device_stats stats; +}; + +struct PACKET_PRIVATE_DATA { + /* tx/rx both use cb */ + struct QUE_ENTRY rQueEntry; /* 16byte total:16 */ + + uint8_t ucBssIdx; /* 1byte */ + /* only rx use cb */ + u_int8_t fgIsIndependentPkt; /* 1byte */ + /* only tx use cb */ + uint8_t ucTid; /* 1byte */ + uint8_t ucHeaderLen; /* 1byte */ + uint8_t ucProfilingFlag; /* 1byte */ + uint8_t ucSeqNo; /* 1byte */ + uint16_t u2Flag; /* 2byte total:24 */ + + uint16_t u2IpId; /* 2byte */ + uint16_t u2FrameLen; /* 2byte */ + OS_SYSTIME rArrivalTime;/* 4byte total:32 */ + + uint64_t u8ArriveTime; /* 8byte total:40 */ +}; + +struct PACKET_PRIVATE_RX_DATA { + uint64_t u8IntTime; /* 8byte */ + uint64_t u8RxTime; /* 8byte */ +}; + +/******************************************************************************* + * P U B 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() unsigned long __ulFlags = 0 +#define GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, rLockCategory) \ + { \ + if (rLockCategory < SPIN_LOCK_NUM) \ + spin_lock_irqsave(\ + &(prGlueInfo)->rSpinLock[rLockCategory], __ulFlags); \ + } +#define GLUE_RELEASE_SPIN_LOCK(prGlueInfo, rLockCategory) \ + { \ + if (rLockCategory < SPIN_LOCK_NUM) \ + spin_unlock_irqrestore(\ + &(prGlueInfo->rSpinLock[rLockCategory]), __ulFlags); \ + } +#endif /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + +/*----------------------------------------------------------------------------*/ +/* Macros for accessing Reserved Fields of native packet */ +/*----------------------------------------------------------------------------*/ + +#define GLUE_GET_PKT_PRIVATE_DATA(_p) \ + ((struct PACKET_PRIVATE_DATA *)(&(((struct sk_buff *)(_p))->cb[0]))) + +#define GLUE_GET_PKT_QUEUE_ENTRY(_p) \ + (&(GLUE_GET_PKT_PRIVATE_DATA(_p)->rQueEntry)) + +#define GLUE_GET_PKT_DESCRIPTOR(_prQueueEntry) \ + ((void *) (((unsigned long)_prQueueEntry) \ + - offsetof(struct sk_buff, cb[0]))) + +#define GLUE_SET_PKT_TID(_p, _tid) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucTid = (uint8_t)(_tid)) + +#define GLUE_GET_PKT_TID(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucTid) + +#define GLUE_SET_PKT_FLAG(_p, _flag) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2Flag |= BIT(_flag)) + +#define GLUE_TEST_PKT_FLAG(_p, _flag) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2Flag & BIT(_flag)) + +#define GLUE_IS_PKT_FLAG_SET(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2Flag) + +#define GLUE_SET_PKT_BSS_IDX(_p, _ucBssIndex) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucBssIdx = (uint8_t)(_ucBssIndex)) + +#define GLUE_GET_PKT_BSS_IDX(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucBssIdx) + +#define GLUE_SET_PKT_HEADER_LEN(_p, _ucMacHeaderLen) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucHeaderLen = \ + (uint8_t)(_ucMacHeaderLen)) + +#define GLUE_GET_PKT_HEADER_LEN(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucHeaderLen) + +#define GLUE_SET_PKT_FRAME_LEN(_p, _u2PayloadLen) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2FrameLen = (uint16_t)(_u2PayloadLen)) + +#define GLUE_GET_PKT_FRAME_LEN(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2FrameLen) + +#define GLUE_SET_PKT_ARRIVAL_TIME(_p, _rSysTime) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->rArrivalTime = (OS_SYSTIME)(_rSysTime)) + +#define GLUE_GET_PKT_ARRIVAL_TIME(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->rArrivalTime) + +#define GLUE_SET_PKT_IP_ID(_p, _u2IpId) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2IpId = (uint16_t)(_u2IpId)) + +#define GLUE_GET_PKT_IP_ID(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2IpId) + +#define GLUE_SET_PKT_SEQ_NO(_p, _ucSeqNo) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucSeqNo = (uint8_t)(_ucSeqNo)) + +#define GLUE_GET_PKT_SEQ_NO(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucSeqNo) + +#define GLUE_SET_PKT_FLAG_PROF_MET(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucProfilingFlag |= BIT(0)) + +#define GLUE_GET_PKT_IS_PROF_MET(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucProfilingFlag & BIT(0)) + +#define GLUE_SET_PKT_XTIME(_p, _rSysTime) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u8ArriveTime = (uint64_t)(_rSysTime)) + +#define GLUE_GET_PKT_XTIME(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u8ArriveTime) + +#define GLUE_GET_INDEPENDENT_PKT(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->fgIsIndependentPkt) + +#define GLUE_SET_INDEPENDENT_PKT(_p, _fgIsIndePkt) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->fgIsIndependentPkt = _fgIsIndePkt) + +#define GLUE_GET_PKT_PRIVATE_RX_DATA(_p) \ + ((struct PACKET_PRIVATE_RX_DATA *)(&(((struct sk_buff *)(_p))->cb[24]))) + +#define GLUE_RX_SET_PKT_INT_TIME(_p, _rTime) \ + (GLUE_GET_PKT_PRIVATE_RX_DATA(_p)->u8IntTime = (uint64_t)(_rTime)) + +#define GLUE_RX_GET_PKT_INT_TIME(_p) \ + (GLUE_GET_PKT_PRIVATE_RX_DATA(_p)->u8IntTime) + +#define GLUE_RX_SET_PKT_RX_TIME(_p, _rTime) \ + (GLUE_GET_PKT_PRIVATE_RX_DATA(_p)->u8RxTime = (uint64_t)(_rTime)) + +#define GLUE_RX_GET_PKT_RX_TIME(_p) \ + (GLUE_GET_PKT_PRIVATE_RX_DATA(_p)->u8RxTime) + +#define GLUE_GET_PKT_ETHER_DEST_ADDR(_p) \ + ((uint8_t *)&(((struct sk_buff *)(_p))->data)) + +#define GLUE_COPY_PRIV_DATA(_pDst, _pSrc) \ + (kalMemCopy(GLUE_GET_PKT_PRIVATE_DATA(_pDst), \ + GLUE_GET_PKT_PRIVATE_DATA(_pSrc), sizeof(struct PACKET_PRIVATE_DATA))) + +/* Check validity of prDev, private data, and pointers */ +#define GLUE_CHK_DEV(prDev) \ + ((prDev && *((struct GLUE_INFO **) 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 GLUE_ADD_REF_CNT(_value, _refCount) \ + atomic_add(_value, (atomic_t *)&(_refCount)) +#define GLUE_SUB_REF_CNT(_value, _refCount) \ + atomic_sub(_value, (atomic_t *)&(_refCount)) +#define GLUE_GET_REF_CNT(_refCount) atomic_read((atomic_t *)&(_refCount)) + +#define DbgPrint(...) + +#define GLUE_LOOKUP_FUN(fun_name) kallsyms_lookup_name(fun_name) + + +#if CFG_MET_TAG_SUPPORT +#define GL_MET_TAG_START(_id, _name) met_tag_start(_id, _name) +#define GL_MET_TAG_END(_id, _name) met_tag_end(_id, _name) +#define GL_MET_TAG_ONESHOT(_id, _name, _value) \ + met_tag_oneshot(_id, _name, _value) +#define GL_MET_TAG_DISABLE(_id) met_tag_disable(_id) +#define GL_MET_TAG_ENABLE(_id) met_tag_enable(_id) +#define GL_MET_TAG_REC_ON() met_tag_record_on() +#define GL_MET_TAG_REC_OFF() met_tag_record_off() +#define GL_MET_TAG_INIT() met_tag_init() +#define GL_MET_TAG_UNINIT() met_tag_uninit() +#else +#define GL_MET_TAG_START(_id, _name) +#define GL_MET_TAG_END(_id, _name) +#define GL_MET_TAG_ONESHOT(_id, _name, _value) +#define GL_MET_TAG_DISABLE(_id) +#define GL_MET_TAG_ENABLE(_id) +#define GL_MET_TAG_REC_ON() +#define GL_MET_TAG_REC_OFF() +#define GL_MET_TAG_INIT() +#define GL_MET_TAG_UNINIT() +#endif + +#define MET_TAG_ID 0 + +/*----------------------------------------------------------------------------*/ +/* Macros of Data Type Check */ +/*----------------------------------------------------------------------------*/ +/* Kevin: we don't have to call following function to inspect the data + * structure. + * It will check automatically while at compile time. + */ +static __KAL_INLINE__ void glPacketDataTypeCheck(void) +{ + DATA_STRUCT_INSPECTING_ASSERT(sizeof(struct + PACKET_PRIVATE_DATA) <= sizeof(((struct sk_buff *) 0)->cb)); +} + +static bool is_critical_packet(struct net_device *dev, + struct sk_buff *skb, u16 orig_queue_index) +{ +#if CFG_CHANGE_CRITICAL_PACKET_PRIORITY + uint8_t *pucPkt; + uint16_t u2EtherType; + bool is_critical = false; + + if (!skb) + return false; + + pucPkt = skb->data; + u2EtherType = (pucPkt[ETH_TYPE_LEN_OFFSET] << 8) + | (pucPkt[ETH_TYPE_LEN_OFFSET + 1]); + + switch (u2EtherType) { + case ETH_P_ARP: + if (__netif_subqueue_stopped(dev, orig_queue_index)) + is_critical = true; + break; + case ETH_P_1X: + case ETH_P_PRE_1X: +#if CFG_SUPPORT_WAPI + case ETH_WPI_1X: +#endif + is_critical = true; + break; + default: + is_critical = false; + break; + } + return is_critical; +#else + return false; +#endif +} + +static inline u16 mtk_wlan_ndev_select_queue( + struct net_device *dev, + struct sk_buff *skb) +{ + static u16 ieee8021d_to_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; + u16 queue_index = 0; + + /* cfg80211_classify8021d returns 0~7 */ +#if KERNEL_VERSION(3, 14, 0) > CFG80211_VERSION_CODE + skb->priority = cfg80211_classify8021d(skb); +#else + skb->priority = cfg80211_classify8021d(skb, NULL); +#endif + queue_index = ieee8021d_to_queue[skb->priority]; + if (is_critical_packet(dev, skb, queue_index)) { + skb->priority = WMM_UP_VO_INDEX; + queue_index = ieee8021d_to_queue[skb->priority]; + } + + return queue_index; +} + +#if KERNEL_VERSION(2, 6, 34) > LINUX_VERSION_CODE +#define netdev_for_each_mc_addr(mclist, dev) \ + for (mclist = dev->mc_list; mclist; mclist = mclist->next) +#endif + +#if KERNEL_VERSION(2, 6, 34) > LINUX_VERSION_CODE +#define GET_ADDR(ha) (ha->da_addr) +#else +#define GET_ADDR(ha) (ha->addr) +#endif + +#if KERNEL_VERSION(2, 6, 35) <= LINUX_VERSION_CODE +#define LIST_FOR_EACH_IPV6_ADDR(_prIfa, _ip6_ptr) \ + list_for_each_entry(_prIfa, &((struct inet6_dev *) \ + _ip6_ptr)->addr_list, if_list) +#else +#define LIST_FOR_EACH_IPV6_ADDR(_prIfa, _ip6_ptr) \ + for (_prIfa = ((struct inet6_dev *) _ip6_ptr)->addr_list; _prIfa; \ + _prIfa = _prIfa->if_next) +#endif + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +#if WLAN_INCLUDE_PROC +int32_t procCreateFsEntry(struct GLUE_INFO *prGlueInfo); +int32_t procRemoveProcfs(void); + + +int32_t procInitFs(void); +int32_t procUninitProcFs(void); + + + +int32_t procInitProcfs(struct net_device *prDev, + char *pucDevName); +#endif /* WLAN_INCLUDE_PROC */ + +#if WLAN_INCLUDE_SYS +int32_t sysCreateFsEntry(struct GLUE_INFO *prGlueInfo); +int32_t sysRemoveSysfs(void); +int32_t sysInitFs(void); +int32_t sysUninitSysFs(void); +void sysMacAddrOverride(uint8_t *prMacAddr); +#endif /* WLAN_INCLUDE_SYS */ + +#if CFG_ENABLE_BT_OVER_WIFI +u_int8_t glRegisterAmpc(struct GLUE_INFO *prGlueInfo); + +u_int8_t glUnregisterAmpc(struct GLUE_INFO *prGlueInfo); +#endif + +#if CFG_ENABLE_WIFI_DIRECT +void p2pSetMulticastListWorkQueueWrapper(struct GLUE_INFO + *prGlueInfo); +#endif + +struct GLUE_INFO *wlanGetGlueInfo(void); +#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE +u16 wlanSelectQueue(struct net_device *dev, + struct sk_buff *skb, + struct net_device *sb_dev); +#elif KERNEL_VERSION(4, 19, 0) <= CFG80211_VERSION_CODE +u16 wlanSelectQueue(struct net_device *dev, + struct sk_buff *skb, + struct net_device *sb_dev, select_queue_fallback_t fallback); +#elif KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE +u16 wlanSelectQueue(struct net_device *dev, + struct sk_buff *skb, + void *accel_priv, select_queue_fallback_t fallback); +#elif KERNEL_VERSION(3, 13, 0) <= LINUX_VERSION_CODE +u16 wlanSelectQueue(struct net_device *dev, + struct sk_buff *skb, + void *accel_priv); +#else +u16 wlanSelectQueue(struct net_device *dev, + struct sk_buff *skb); +#endif + +void wlanDebugInit(void); + +uint32_t wlanSetDriverDbgLevel(IN uint32_t u4DbgIdx, + IN uint32_t u4DbgMask); + +uint32_t wlanGetDriverDbgLevel(IN uint32_t u4DbgIdx, + OUT uint32_t *pu4DbgMask); + +void wlanSetSuspendMode(struct GLUE_INFO *prGlueInfo, + u_int8_t fgEnable); + +void wlanGetConfig(struct ADAPTER *prAdapter); + +uint32_t wlanDownloadBufferBin(struct ADAPTER *prAdapter); + +uint32_t wlanConnacDownloadBufferBin(struct ADAPTER + *prAdapter); + +/******************************************************************************* + * E X T E R N A L F U N C T I O N S / V A R I A B L E + ******************************************************************************* + */ +extern struct net_device *gPrP2pDev[KAL_P2P_NUM]; +extern struct net_device *gPrDev; +extern struct wireless_dev *gprWdev[KAL_AIS_NUM]; +extern uint32_t g_u4DevIdx[KAL_P2P_NUM]; +extern enum ENUM_NVRAM_STATE g_NvramFsm; + + +#ifdef CFG_DRIVER_INF_NAME_CHANGE +extern char *gprifnameap; +extern char *gprifnamep2p; +extern char *gprifnamesta; +#endif /* CFG_DRIVER_INF_NAME_CHANGE */ + +void wlanRegisterInetAddrNotifier(void); +void wlanUnregisterInetAddrNotifier(void); +void wlanRegisterNetdevNotifier(void); +void wlanUnregisterNetdevNotifier(void); +#if CFG_MTK_ANDROID_WMT +typedef int (*set_p2p_mode) (struct net_device *netdev, + struct PARAM_CUSTOM_P2P_SET_STRUCT p2pmode); +extern void register_set_p2p_mode_handler( + set_p2p_mode handler); +#endif + +#if CFG_ENABLE_EARLY_SUSPEND +extern int glRegisterEarlySuspend(struct early_suspend + *prDesc, + early_suspend_callback wlanSuspend, + late_resume_callback wlanResume); + +extern int glUnregisterEarlySuspend(struct early_suspend + *prDesc); +#endif + +#if CFG_MET_PACKET_TRACE_SUPPORT +void kalMetTagPacket(IN struct GLUE_INFO *prGlueInfo, + IN void *prPacket, IN enum ENUM_TX_PROFILING_TAG eTag); + +void kalMetInit(IN struct GLUE_INFO *prGlueInfo); +#endif + +void wlanUpdateChannelTable(struct GLUE_INFO *prGlueInfo); + +#if CFG_SUPPORT_SAP_DFS_CHANNEL +void wlanUpdateDfsChannelTable(struct GLUE_INFO *prGlueInfo, + uint8_t ucRoleIdx, uint8_t ucChannel, uint8_t ucBandWidth, + enum ENUM_CHNL_EXT eBssSCO, uint32_t u4CenterFreq); +#endif + +#if (CFG_MTK_ANDROID_WMT || WLAN_INCLUDE_PROC) +int set_p2p_mode_handler(struct net_device *netdev, + struct PARAM_CUSTOM_P2P_SET_STRUCT p2pmode); +#endif + +#if CFG_ENABLE_UNIFY_WIPHY +const struct net_device_ops *wlanGetNdevOps(void); +#endif + +#if CFG_MTK_ANDROID_WMT +extern void connectivity_export_show_stack(struct task_struct *tsk, + unsigned long *sp); +#endif + +netdev_tx_t wlanHardStartXmit(struct sk_buff *prSkb, struct net_device *prDev); + +typedef uint8_t (*file_buf_handler) (void *ctx, + const char __user *buf, + uint16_t length); +extern void register_file_buf_handler(file_buf_handler handler, + void *ctx, + uint8_t ucType); + +/* extern from wifi wmt cdev wifi */ +extern uint32_t get_low_latency_mode(void); + +extern const uint8_t *kalFindIeMatchMask(uint8_t eid, + const uint8_t *ies, int len, + const uint8_t *match, + int match_len, int match_offset, + const uint8_t *match_mask); + + +void wlanNvramSetState(enum ENUM_NVRAM_STATE state); +enum ENUM_NVRAM_STATE wlanNvramGetState(void); + +#endif /* _GL_OS_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_p2p_ioctl.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_p2p_ioctl.h new file mode 100644 index 0000000000000..d9299e0f13796 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_p2p_ioctl.h @@ -0,0 +1,852 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 + */ + + +#ifndef _GL_P2P_IOCTL_H +#define _GL_P2P_IOCTL_H + +/****************************************************************************** + * C O M P I L E R F L A G S + ****************************************************************************** + */ + +/****************************************************************************** + * E X T E R N A L R E F E R E N C E S + ****************************************************************************** + */ +#include +#include +#include +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#include +#include +#endif + +#include "wlan_oid.h" + +/****************************************************************************** + * C O N S T A N T S + ****************************************************************************** + */ + +/* (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 + +#define CHN_DIRTY_WEIGHT_UPPERBOUND 4 + +/****************************************************************************** + * D A T A T Y P E S + ****************************************************************************** + */ +/*------------------------------------------------------------------------*/ +/* Wireless Extension: Private I/O Control */ +/*------------------------------------------------------------------------*/ +struct iw_p2p_cfg_device_type { + void __user *ssid; + uint8_t ssid_len; + uint8_t pri_device_type[8]; + uint8_t snd_device_type[8]; + void __user *device_name; + uint8_t device_name_len; + uint8_t intend; + uint8_t persistence; + uint8_t sec_mode; + uint8_t ch; + uint8_t ch_width; /* 0: 20 Mhz 1:20/40 Mhz auto */ + uint8_t max_scb; +}; + +struct iw_p2p_hostapd_param { + uint8_t cmd; + uint8_t rsv[3]; + uint8_t sta_addr[6]; + void __user *data; + uint16_t len; +}; + +struct iw_p2p_req_device_type { + uint8_t scan_type; /* 0: Full scan + Find + * 1: Full scan + * 2: Scan (Search +Listen) + * 3: Listen + * other : reserved + */ + uint8_t pri_device_type[8]; + void __user *probe_req_ie; + uint16_t probe_req_len; + void __user *probe_rsp_ie; + uint16_t probe_rsp_len; +}; + +struct iw_p2p_connect_device { + uint8_t sta_addr[6]; + /* 0: P2P Device, 1:GC, 2: GO */ + uint8_t p2pRole; + /* 0: Don't needed provision, 1: doing the wsc provision first */ + uint8_t needProvision; + /* 1: auth peer invitation request */ + uint8_t authPeer; + /* Request Peer Device used config method */ + uint8_t intend_config_method; +}; + +struct iw_p2p_password_ready { + uint8_t active_config_method; + void __user *probe_req_ie; + uint16_t probe_req_len; + void __user *probe_rsp_ie; + uint16_t probe_rsp_len; +}; + +struct iw_p2p_device_req { + uint8_t name[33]; + uint32_t name_len; + uint8_t device_addr[6]; + uint8_t device_type; + int32_t config_method; + int32_t active_config_method; +}; + +struct iw_p2p_transport_struct { + uint32_t u4CmdId; + uint32_t inBufferLength; + uint32_t outBufferLength; + uint8_t aucBuffer[16]; +}; + +/* For Invitation */ +struct iw_p2p_ioctl_invitation_struct { + uint8_t aucDeviceID[6]; + /* BSSID */ + uint8_t aucGroupID[6]; + uint8_t aucSsid[32]; + uint32_t u4SsidLen; + uint8_t ucReinvoke; +}; + +struct iw_p2p_ioctl_abort_invitation { + uint8_t dev_addr[6]; +}; + +struct iw_p2p_ioctl_invitation_indicate { + uint8_t dev_addr[6]; + uint8_t group_bssid[6]; + /* peer device supported config method */ + int32_t config_method; + /* for reinvoke */ + uint8_t dev_name[32]; + uint32_t name_len; + /* for re-invoke, target operating channel */ + uint8_t operating_channel; + /* invitation or re-invoke */ + uint8_t invitation_type; +}; + +struct iw_p2p_ioctl_invitation_status { + uint32_t status_code; +}; + +/* For Formation */ +struct iw_p2p_ioctl_start_formation { + /* bssid */ + uint8_t dev_addr[6]; + /* 0: P2P Device, 1:GC, 2: GO */ + uint8_t role; + /* 0: Don't needed provision, 1: doing the wsc provision first */ + uint8_t needProvision; + /* 1: auth peer invitation request */ + uint8_t auth; + /* Request Peer Device used config method */ + + uint8_t config_method; +}; + +/* SET_STRUCT / GET_STRUCT */ +enum ENUM_P2P_CMD_ID { + 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) */ +}; + +/* Service Discovery */ +struct iw_p2p_cmd_send_sd_response { + uint8_t rReceiverAddr[PARAM_MAC_ADDR_LEN]; + uint8_t fgNeedTxDoneIndication; + uint8_t ucSeqNum; + uint16_t u2PacketLength; + uint8_t aucPacketContent[0]; /*native 802.11 */ +}; + +struct iw_p2p_cmd_get_sd_request { + uint8_t rTransmitterAddr[PARAM_MAC_ADDR_LEN]; + uint16_t u2PacketLength; + uint8_t aucPacketContent[0]; /*native 802.11 */ +}; + +struct iw_p2p_cmd_send_service_discovery_request { + uint8_t rReceiverAddr[PARAM_MAC_ADDR_LEN]; + uint8_t fgNeedTxDoneIndication; + uint8_t ucSeqNum; + uint16_t u2PacketLength; + uint8_t aucPacketContent[0]; /*native 802.11 */ +}; + +struct iw_p2p_cmd_get_sd_response { + uint8_t rTransmitterAddr[PARAM_MAC_ADDR_LEN]; + uint16_t u2PacketLength; + uint8_t aucPacketContent[0]; /*native 802.11 */ +}; + +struct iw_p2p_cmd_terminate_sd_phase { + uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN]; +}; + +struct iw_p2p_version { + uint32_t u4Version; +}; + +/****************************************************************************** + * P U B L I C D A T A + ****************************************************************************** + */ +extern struct ieee80211_supported_band mtk_band_2ghz; +extern struct ieee80211_supported_band mtk_band_5ghz; + +extern const uint32_t mtk_cipher_suites[8]; + + +/****************************************************************************** + * 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 = KAL_BAND_2GHZ, \ + .center_freq = (_freq), \ + .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 (CFG_ENABLE_WIFI_DIRECT_CFG_80211 != 0) + +#if KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE +struct wireless_dev *mtk_p2p_cfg80211_add_iface(struct wiphy *wiphy, + const char *name, + unsigned char name_assign_type, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params); +#else +struct wireless_dev *mtk_p2p_cfg80211_add_iface(struct wiphy *wiphy, + const char *name, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params); +#endif + +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_del_iface(struct wiphy *wiphy, + struct wireless_dev *wdev); + +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_set_mgmt_key(struct wiphy *wiphy, + struct net_device *dev, + u8 key_index); + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, + struct station_info *sinfo); +#else +int mtk_p2p_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, + struct station_info *sinfo); +#endif +int mtk_p2p_cfg80211_scan(struct wiphy *wiphy, + struct cfg80211_scan_request *request); + +void mtk_p2p_cfg80211_abort_scan(struct wiphy *wiphy, + struct wireless_dev *wdev); + +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, + struct wireless_dev *wdev, + enum nl80211_tx_power_setting type, + int mbm); + +int mtk_p2p_cfg80211_get_txpower(struct wiphy *wiphy, + struct wireless_dev *wdev, + int *dbm); + +int mtk_p2p_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, + unsigned int duration, + u64 *cookie); + +int mtk_p2p_cfg80211_cancel_remain_on_channel( + struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie); + +int mtk_p2p_cfg80211_set_power_mgmt(struct wiphy *wiphy, + struct net_device *dev, + bool enabled, + int timeout); + +#if (CFG_SUPPORT_DFS_MASTER == 1) + +#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_start_radar_detection(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef, + unsigned int cac_time_ms); +#else +int mtk_p2p_cfg80211_start_radar_detection(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef); +#endif + + +#if KERNEL_VERSION(3, 13, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_channel_switch(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_csa_settings *params); +#endif +#endif + +int mtk_p2p_cfg80211_change_bss(struct wiphy *wiphy, + struct net_device *dev, + struct bss_parameters *params); + +int mtk_p2p_cfg80211_deauth(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_deauth_request *req); + +int mtk_p2p_cfg80211_disassoc(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_disassoc_request *req); + +int mtk_p2p_cfg80211_start_ap(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ap_settings *settings); + +int mtk_p2p_cfg80211_change_beacon(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_beacon_data *info); + +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie); +#else +int mtk_p2p_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, + bool offchan, + unsigned int wait, + const u8 *buf, + size_t len, + bool no_cck, + bool dont_wait_for_ack, + u64 *cookie); +#endif + +#if KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, + struct station_del_parameters *params); +#elif KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, + const u8 *mac); +#else +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, + u8 *mac); +#endif + +int mtk_p2p_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie); + +int mtk_p2p_cfg80211_stop_ap(struct wiphy *wiphy, + struct net_device *dev); + +int mtk_p2p_cfg80211_set_channel(struct wiphy *wiphy, + struct cfg80211_chan_def *chandef); + +void mtk_p2p_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, + struct wireless_dev *wdev, + IN u16 frame_type, + IN bool reg); + +int +mtk_p2p_cfg80211_set_bitrate_mask(IN struct wiphy *wiphy, + IN struct net_device *dev, + IN const u8 *peer, + IN const struct cfg80211_bitrate_mask *mask); + +#ifdef CONFIG_NL80211_TESTMODE +#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_testmode_cmd(struct wiphy *wiphy, + struct wireless_dev *wdev, + void *data, + int len); +#else +int mtk_p2p_cfg80211_testmode_cmd(struct wiphy *wiphy, + void *data, + int len); +#endif +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); + +int mtk_p2p_cfg80211_testmode_hotspot_config_cmd(IN struct wiphy *wiphy, + IN void *data, + IN int len); + +int mtk_p2p_cfg80211_testmode_update_sta_pmkid_cmd(IN struct wiphy *wiphy, + IN struct net_device *nDev, IN void *data, IN int len); + +#else +/* IGNORE KERNEL DEPENCY ERRORS*/ +/*#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 struct GLUE_INFO *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); + +#endif /* _GL_P2P_IOCTL_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_p2p_kal.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_p2p_kal.h new file mode 100644 index 0000000000000..b2123bf68602a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_p2p_kal.h @@ -0,0 +1,388 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + + +#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 + +u_int8_t kalP2pFuncGetChannelType(IN enum ENUM_CHNL_EXT rChnlSco, + OUT enum nl80211_channel_type *channel_type); + +/****************************************************************************** + * 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 struct GLUE_INFO *prGlueInfo, + IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN], + IN uint8_t ucSeqNum); + +void kalP2PIndicateSDResponse(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN], + IN uint8_t ucSeqNum); + +void kalP2PIndicateTXDone(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucSeqNum, IN uint8_t 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 struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucFrameBody, + IN uint32_t u4FrameBodyLen, + IN u_int8_t fgReassocRequest, + IN uint8_t ucBssIndex); + +/*UINT_32 kalP2PGetFreqInKHz(IN P_GLUE_INFO_T prGlueInfo);*/ + +int32_t mtk_Netdev_To_RoleIdx(struct GLUE_INFO *prGlueInfo, + struct net_device *ndev, + uint8_t *pucRoleIdx); + +uint8_t kalP2PGetRole(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIdx); + +#if 1 +void kalP2PSetRole(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRole, + IN uint8_t ucRoleIdx); + +#else +void +kalP2PSetRole(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucResult, + IN uint8_t *pucSSID, + IN uint8_t ucSSIDLen, + IN uint8_t ucRole); +#endif + +void kalP2PSetCipher(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Cipher, + IN uint8_t ucRoleIdx); + +u_int8_t kalP2PGetCipher(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIdx); + +u_int8_t kalP2PGetWepCipher(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIdx); + +u_int8_t kalP2PGetTkipCipher(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIdx); + +u_int8_t kalP2PGetCcmpCipher(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIdx); + +void kalP2PSetWscMode(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucWscMode); + +uint8_t kalP2PGetWscMode(IN struct GLUE_INFO *prGlueInfo); + +uint16_t kalP2PCalWSC_IELen(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucType, + IN uint8_t ucRoleIdx); + +void kalP2PGenWSC_IE(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucType, + IN uint8_t *pucBuffer, + IN uint8_t ucRoleIdx); + +void kalP2PUpdateWSC_IE(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucType, + IN uint8_t *pucBuffer, + IN uint16_t u2BufferLength, + IN uint8_t ucRoleIdx); + +uint16_t kalP2PCalP2P_IELen(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucIndex, + IN uint8_t ucRoleIdx); + +void kalP2PGenP2P_IE(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucIndex, + IN uint8_t *pucBuffer, + IN uint8_t ucRoleIdx); + +void kalP2PUpdateP2P_IE(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucIndex, + IN uint8_t *pucBuffer, + IN uint16_t u2BufferLength, + IN uint8_t ucRoleIdx); + +u_int8_t kalP2PIndicateFound(IN struct GLUE_INFO *prGlueInfo); + +void kalP2PIndicateConnReq(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucDevName, + IN int32_t u4NameLength, + IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN], + IN uint8_t ucDevType, /* 0: P2P Device / 1: GC / 2: GO */ + IN int32_t i4ConfigMethod, + IN int32_t i4ActiveConfigMethod); + +/*VOID kalP2PInvitationStatus(IN P_GLUE_INFO_T prGlueInfo, + * IN UINT_32 u4InvStatus); + */ + +void +kalP2PInvitationIndication(IN struct GLUE_INFO *prGlueInfo, + IN struct P2P_DEVICE_DESC *prP2pDevDesc, + IN uint8_t *pucSsid, + IN uint8_t ucSsidLen, + IN uint8_t ucOperatingChnl, + IN uint8_t ucInvitationType, + IN uint8_t *pucGroupBssid); + +struct net_device *kalP2PGetDevHdlr(struct GLUE_INFO *prGlueInfo); + +void +kalGetChnlList(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_BAND eSpecificBand, + IN uint8_t ucMaxChannelNum, + IN uint8_t *pucNumOfChannel, + IN struct RF_CHANNEL_INFO *paucChannelList); + +#if CFG_SUPPORT_ANTI_PIRACY +void kalP2PIndicateSecCheckRsp(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucRsp, + IN uint16_t u2RspLen); +#endif + +/****************************************************************************** + * F U N C T I O N S + ****************************************************************************** + */ + +void +kalP2PIndicateChannelReady(IN struct GLUE_INFO *prGlueInfo, + IN uint64_t u8SeqNum, + IN uint32_t u4ChannelNum, + IN enum ENUM_BAND eBand, + IN enum ENUM_CHNL_EXT eSco, + IN uint32_t u4Duration); + +void kalP2PIndicateScanDone(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex, + IN u_int8_t fgIsAbort); + +void +kalP2PIndicateBssInfo(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucFrameBuf, + IN uint32_t u4BufLen, + IN struct RF_CHANNEL_INFO *prChannelInfo, + IN int32_t i4SignalStrength); + +void +kalP2PIndicateRxMgmtFrame(IN struct GLUE_INFO *prGlueInfo, + IN struct SW_RFB *prSwRfb, + IN u_int8_t fgIsDevInterface, + IN uint8_t ucRoleIdx); + +void kalP2PIndicateMgmtTxStatus(IN struct GLUE_INFO *prGlueInfo, + IN struct MSDU_INFO *prMsduInfo, + IN u_int8_t fgIsAck); + +void +kalP2PIndicateChannelExpired(IN struct GLUE_INFO *prGlueInfo, + IN uint64_t u8SeqNum, + IN uint32_t u4ChannelNum, + IN enum ENUM_BAND eBand, + IN enum ENUM_CHNL_EXT eSco); + +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) +void +kalP2PGCIndicateConnectionStatus(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex, + IN struct P2P_CONNECTION_REQ_INFO *prP2pConnInfo, + IN uint8_t *pucRxIEBuf, + IN uint16_t u2RxIELen, + IN uint16_t u2StatusReason, + IN uint32_t eStatus); +#else +void +kalP2PGCIndicateConnectionStatus(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex, + IN struct P2P_CONNECTION_REQ_INFO *prP2pConnInfo, + IN uint8_t *pucRxIEBuf, + IN uint16_t u2RxIELen, + IN uint16_t u2StatusReason); + +#endif +void +kalP2PGOStationUpdate(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex, + IN struct STA_RECORD *prCliStaRec, + IN u_int8_t fgIsNew); + +#if (CFG_SUPPORT_DFS_MASTER == 1) +void +kalP2PRddDetectUpdate(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex); + +void +kalP2PCacFinishedUpdate(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex); +#endif + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + +u_int8_t kalP2PSetBlackList(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t rbssid[PARAM_MAC_ADDR_LEN], + IN u_int8_t fgIsblock, + IN uint8_t ucRoleIndex); + +u_int8_t kalP2PResetBlackList(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex); + +u_int8_t kalP2PCmpBlackList(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t rbssid[PARAM_MAC_ADDR_LEN], + IN uint8_t ucRoleIndex); + +void kalP2PSetMaxClients(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4MaxClient, + IN uint8_t ucRoleIndex); + +u_int8_t kalP2PMaxClients(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4NumClient, + IN uint8_t ucRoleIndex); + +#endif + +void kalP2pUnlinkBss(IN struct GLUE_INFO *prGlueInfo, IN uint8_t aucBSSID[]); + +void kalP2pIndicateQueuedMgmtFrame(IN struct GLUE_INFO *prGlueInfo, + IN struct P2P_QUEUED_ACTION_FRAME *prFrame); + +void kalP2pIndicateAcsResult(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex, + IN uint8_t ucPrimaryCh, + IN uint8_t ucSecondCh, + IN uint8_t ucSeg0Ch, + IN uint8_t ucSeg1Ch, + IN enum ENUM_MAX_BANDWIDTH_SETTING eChnlBw); + +void kalP2pNotifyStopApComplete(IN struct ADAPTER *prAdapter, + IN uint8_t ucRoleIndex); + +void kalP2pIndicateChnlSwitch(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo); + +#endif /* _GL_P2P_KAL_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_p2p_os.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_p2p_os.h new file mode 100644 index 0000000000000..cb8bab0279ff5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_p2p_os.h @@ -0,0 +1,387 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 + +#define VENDOR_SPECIFIC_IE_LENGTH 400 +/****************************************************************************** + * C O M P I L E R F L A G S + ****************************************************************************** + */ + +/****************************************************************************** + * E X T E R N A L R E F E R E N C E S + ****************************************************************************** + */ + +/****************************************************************************** + * E X T E R N A L V A R I A B L E + ****************************************************************************** + */ +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_WIFI_DIRECT_CFG_80211 +extern const struct net_device_ops p2p_netdev_ops; +#endif + +/****************************************************************************** + * C O N S T A N T S + ****************************************************************************** + */ + +/****************************************************************************** + * M A C R O S + ****************************************************************************** + */ + +/* For SET_STRUCT/GET_STRUCT */ +#define OID_SET_GET_STRUCT_LENGTH 4096 + +#define MAX_P2P_IE_SIZE 5 + +#define P2P_MAXIMUM_CLIENT_COUNT 16 +#define P2P_DEFAULT_CLIENT_COUNT 4 + +/****************************************************************************** + * D A T A T Y P E S + ****************************************************************************** + */ + +/****************************************************************************** + * P U B L I C D A T A + ****************************************************************************** + */ + +extern struct net_device *g_P2pPrDev; +extern struct wireless_dev *gprP2pWdev; +extern struct wireless_dev *gprP2pRoleWdev[KAL_P2P_NUM]; + +/****************************************************************************** + * 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 { + + /* P2P Device interface handle */ + /*only first p2p have this devhandler*/ + struct net_device *prDevHandler; + /*struct net_device *prRoleDevHandler;*//* TH3 multiple P2P */ + + struct net_device *aprRoleHandler; + + /* Todo : should move to the glueinfo or not*/ + /*UINT_8 ucRoleInterfaceNum;*//* TH3 multiple P2P */ + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + /* cfg80211 */ + struct wireless_dev *prWdev; + /*struct wireless_dev *prRoleWdev[KAL_P2P_NUM];*//* TH3 multiple P2P */ + + /*struct cfg80211_scan_request *prScanRequest;*//* TH3 multiple P2P */ + + /*UINT_64 u8Cookie;*//* TH3 multiple P2P */ + + /* Generation for station list update. */ + int32_t i4Generation; + + /*UINT_32 u4OsMgmtFrameFilter;*//* TH3 multiple P2P */ + +#endif + + /* Device statistics */ + /*struct net_device_stats rNetDevStats;*//* TH3 multiple P2P */ + + /* glue layer variables */ + /*move to glueinfo->adapter */ + /* BOOLEAN fgIsRegistered; */ + /*UINT_32 u4FreqInKHz;*//* TH3 multiple P2P */ /* frequency */ + /* 0: P2P Device, 1: Group Client, 2: Group Owner */ + uint8_t ucRole; + /*UINT_8 ucIntent;*//* TH3 multiple P2P */ /* range: 0-15 */ + /* 0: Search & Listen, 1: Scan without probe response */ + /*UINT_8 ucScanMode;*//* TH3 multiple P2P */ + + /*ENUM_PARAM_MEDIA_STATE_T eState;*//* TH3 multiple P2P */ + /*UINT_32 u4PacketFilter;*//* TH3 multiple P2P */ + /* TH3 multiple P2P */ + /*PARAM_MAC_ADDRESS aucMCAddrList[MAX_NUM_GROUP_ADDR];*/ + + /* connection-requested peer information *//* TH3 multiple P2P */ + /*UINT_8 aucConnReqDevName[32];*//* TH3 multiple P2P */ + /*INT_32 u4ConnReqNameLength;*//* TH3 multiple P2P */ + /*PARAM_MAC_ADDRESS rConnReqPeerAddr;*//* TH3 multiple P2P */ + /* For invitation group. */ + /*PARAM_MAC_ADDRESS rConnReqGroupAddr;*//* TH3 multiple P2P */ + /*UINT_8 ucConnReqDevType;*//* TH3 multiple P2P */ + /*INT_32 i4ConnReqConfigMethod;*//* TH3 multiple P2P */ + /*INT_32 i4ConnReqActiveConfigMethod;*//* TH3 multiple P2P */ + + uint32_t u4CipherPairwise; + /*UINT_8 ucWSCRunning;*//* TH3 multiple P2P */ + + /* 0: beacon, 1: probe req, 2:probe response, 3: assoc response */ + uint8_t aucWSCIE[4][VENDOR_SPECIFIC_IE_LENGTH]; + uint16_t u2WSCIELen[4]; + + uint8_t aucP2PIE[MAX_P2P_IE_SIZE][VENDOR_SPECIFIC_IE_LENGTH]; + uint16_t u2P2PIELen[MAX_P2P_IE_SIZE]; + +#if CFG_SUPPORT_WFD + /* 0 for beacon, 1 for probe req, 2 for probe response */ + uint8_t aucWFDIE[VENDOR_SPECIFIC_IE_LENGTH]; + uint16_t u2WFDIELen; + /* Save the other IE for probe resp */ +#endif +#if CFG_SUPPORT_CUSTOM_VENDOR_IE + uint8_t aucVenderIE[1024]; + uint16_t u2VenderIELen; +#endif + + /*UINT_8 ucOperatingChnl;*//* TH3 multiple P2P */ + /*UINT_8 ucInvitationType;*//* TH3 multiple P2P */ + + /*UINT_32 u4InvStatus;*//* TH3 multiple P2P */ + + /* For SET_STRUCT/GET_STRUCT */ + /*UINT_8 aucOidBuf[OID_SET_GET_STRUCT_LENGTH];*//* TH3 multiple P2P */ + +#if 1 /* CFG_SUPPORT_ANTI_PIRACY */ + /*UINT_8 aucSecCheck[256];*//* TH3 multiple P2P */ + /*UINT_8 aucSecCheckRsp[256];*//* TH3 multiple P2P */ +#endif + +#if (CFG_SUPPORT_DFS_MASTER == 1) + struct cfg80211_chan_def *chandef; + uint32_t cac_time_ms; +#endif + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + uint8_t aucblackMACList[P2P_MAXIMUM_CLIENT_COUNT][PARAM_MAC_ADDR_LEN]; + uint8_t ucMaxClients; +#endif + +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION + /*BOOLEAN fgEnableHotspotOptimization;*//* TH3 multiple P2P */ + /*UINT_32 u4PsLevel;*//* TH3 multiple P2P */ +#endif + + /* indicate caller thread for stop ap complete */ + struct completion rStopApComp; + + enum ENUM_CHNL_SWITCH_POLICY eChnlSwitchPolicy; +}; + +struct GL_P2P_DEV_INFO { +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + struct cfg80211_scan_request *prScanRequest; +#if 0 + struct cfg80211_scan_request rBackupScanRequest; +#endif + uint64_t u8Cookie; + uint32_t u4OsMgmtFrameFilter; +#endif + uint32_t u4PacketFilter; + uint8_t aucMCAddrList[MAX_NUM_GROUP_ADDR][PARAM_MAC_ADDR_LEN]; + uint8_t ucWSCRunning; +}; + +#ifdef CONFIG_NL80211_TESTMODE +struct NL80211_DRIVER_TEST_PRE_PARAMS { + uint16_t idx_mode; + uint16_t idx; + uint32_t value; +}; + +struct NL80211_DRIVER_TEST_PARAMS { + uint32_t index; + uint32_t buflen; +}; + +/* P2P Sigma*/ +struct NL80211_DRIVER_P2P_SIGMA_PARAMS { + struct NL80211_DRIVER_TEST_PARAMS hdr; + uint32_t idx; + uint32_t value; +}; + +/* Hotspot Client Management */ +struct NL80211_DRIVER_hotspot_block_PARAMS { + struct NL80211_DRIVER_TEST_PARAMS hdr; + uint8_t ucblocked; + uint8_t aucBssid[MAC_ADDR_LEN]; +}; + +/* Hotspot Management set config */ +struct NL80211_DRIVER_HOTSPOT_CONFIG_PARAMS { + struct NL80211_DRIVER_TEST_PARAMS hdr; + uint32_t idx; + uint32_t value; +}; + +#if CFG_SUPPORT_WFD +struct NL80211_DRIVER_WFD_PARAMS { + struct NL80211_DRIVER_TEST_PARAMS hdr; + uint32_t WfdCmdType; + uint8_t WfdEnable; + uint8_t WfdCoupleSinkStatus; + uint8_t WfdSessionAvailable; + uint8_t WfdSigmaMode; + uint16_t WfdDevInfo; + uint16_t WfdControlPort; + uint16_t WfdMaximumTp; + uint16_t WfdExtendCap; + uint8_t WfdCoupleSinkAddress[MAC_ADDR_LEN]; + uint8_t WfdAssociatedBssid[MAC_ADDR_LEN]; + uint8_t WfdVideoIp[4]; + uint8_t WfdAudioIp[4]; + uint16_t WfdVideoPort; + uint16_t WfdAudioPort; + uint32_t WfdFlag; + uint32_t WfdPolicy; + uint32_t WfdState; + /* Include Subelement ID, length */ + uint8_t WfdSessionInformationIE[24 * 8]; + uint16_t WfdSessionInformationIELen; + uint8_t aucReserved1[2]; + uint8_t aucWfdPrimarySinkMac[MAC_ADDR_LEN]; + uint8_t aucWfdSecondarySinkMac[MAC_ADDR_LEN]; + uint32_t WfdAdvanceFlag; + /* Group 1 64 bytes */ + uint8_t aucWfdLocalIp[4]; + uint16_t WfdLifetimeAc2; /* Unit is 2 TU */ + uint16_t WfdLifetimeAc3; /* Unit is 2 TU */ + uint16_t WfdCounterThreshold; /* Unit is ms */ + uint8_t aucReserved2[54]; + /* Group 3 64 bytes */ + uint8_t aucReserved3[64]; + /* Group 3 64 bytes */ + uint8_t aucReserved4[64]; +}; +#endif + +struct NL80211_DRIVER_UPDATE_STA_PMKID_PARAMS { + struct NL80211_DRIVER_TEST_PARAMS hdr; + uint8_t aucBssid[MAC_ADDR_LEN]; + uint8_t aucSta[MAC_ADDR_LEN]; + uint8_t aucPmkid[IW_PMKID_LEN]; + uint8_t ucAddRemove; /*1- ADD, 0- Remove*/ +}; +#endif + +/****************************************************************************** + * P U B L I C D A T A + ****************************************************************************** + */ + +/****************************************************************************** + * P R I V A T E D A T A + ****************************************************************************** + */ + +u_int8_t p2pRegisterToWlan(struct GLUE_INFO *prGlueInfo); + +u_int8_t p2pUnregisterToWlan(struct GLUE_INFO *prGlueInfo); + +u_int8_t p2pLaunch(struct GLUE_INFO *prGlueInfo); + +u_int8_t p2pRemove(struct GLUE_INFO *prGlueInfo); + +void p2pSetMode(IN uint8_t ucAPMode); + +u_int8_t glRegisterP2P(struct GLUE_INFO *prGlueInfo, + const char *prDevName, + const char *prDevName2, + uint8_t ucApMode); + +int glSetupP2P(struct GLUE_INFO *prGlueInfo, + struct wireless_dev *prP2pWdev, + struct net_device *prP2pDev, + uint8_t u4Idx, + u_int8_t fgIsApMode); + +u_int8_t glUnregisterP2P(struct GLUE_INFO *prGlueInfo, uint8_t ucIdx); + +u_int8_t p2pNetRegister(struct GLUE_INFO *prGlueInfo, + u_int8_t fgIsRtnlLockAcquired); + +u_int8_t p2pNetUnregister(struct GLUE_INFO *prGlueInfo, + u_int8_t fgIsRtnlLockAcquired); + + +u_int8_t p2PAllocInfo(IN struct GLUE_INFO *prGlueInfo, IN uint8_t ucIdex); +u_int8_t p2PFreeInfo(struct GLUE_INFO *prGlueInfo, uint8_t ucIdx); + +void p2pSetSuspendMode(struct GLUE_INFO *prGlueInfo, u_int8_t fgEnable); +u_int8_t glP2pCreateWirelessDevice(struct GLUE_INFO *prGlueInfo); +void glP2pDestroyWirelessDevice(void); +void p2pUpdateChannelTableByDomain(struct GLUE_INFO *prGlueInfo); +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_qa_agent.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_qa_agent.h new file mode 100644 index 0000000000000..3d9f7a99d47ee --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_qa_agent.h @@ -0,0 +1,438 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/*! \file gl_qa_agent.h + * \brief This file includes private ioctl support. + */ + +#ifndef _GL_QA_AGENT_H +#define _GL_QA_AGENT_H + +#if CFG_SUPPORT_QA_TOOL + +/******************************************************************************* + * C O M P I L E 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_MTK_ANDROID_EMI +extern phys_addr_t gConEmiPhyBase; +extern unsigned long long gConEmiSize; +#endif + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/* Trigger Event */ +#define CAP_FREE_RUN 0 + +/* Ring Mode */ +#define CAP_RING_MODE_ENABLE 1 +#define CAP_RING_MODE_DISABLE 0 + +/* Capture Bit Width */ +#define CAP_96BIT 0 +#define CAP_128BIT + +/* I/Q Type */ +#define CAP_I_TYPE 0 +#define CAP_Q_TYPE 1 +#define NUM_OF_CAP_TYPE 2 + +/* ACTION */ +#define ACTION_SWITCH_TO_RFTEST 0 /* to switch firmware mode between normal mode + * or rf test mode + */ +#define ACTION_IN_RFTEST 1 + +#define HQA_CMD_MAGIC_NO 0x18142880 +#define HQA_CHIP_ID_6632 0x6632 +#define HQA_CHIP_ID_7668 0x7668 + +/*soc3_0 EMI size= 320KB, 1 Sample Count (IQ) =4B (32bit) */ +#define MAX_ICAP_IQ_DATA_CNT (320 * 256) +#define ICAP_EVENT_DATA_SAMPLE 256 + + +#if CFG_SUPPORT_TX_BF +#define HQA_BF_STR_SIZE 512 +#endif + +#define HQA_RX_STATISTIC_NUM 66 + +#ifdef MAX_EEPROM_BUFFER_SIZE +#undef MAX_EEPROM_BUFFER_SIZE +#endif +#define MAX_EEPROM_BUFFER_SIZE 1200 + +#define HQA_DBDC_BAND_NUM 2 +#define HQA_ANT_NUM 4 +#define HQA_USER_NUM 16 + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ + +extern uint8_t uacEEPROMImage[MAX_EEPROM_BUFFER_SIZE]; + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +#if 0 +struct PARAM_RX_STAT { + uint32_t MacFCSErr; /* Y 0x820F_D014 */ + uint32_t MacMdrdy; /* Y 0x820F_D030 */ + uint32_t FCSErr_CCK; /* Y 0x8207_021C [15:00] */ + uint32_t FCSErr_OFDM; /* Y 0x8207_021C [31:16] */ + uint32_t CCK_PD; /* Y 0x8207_020C [15:00] */ + uint32_t OFDM_PD; /* Y 0x8207_020C [15:00] */ + uint32_t CCK_SIG_Err; /* Y 0x8207_0210 [31:16] */ + uint32_t CCK_SFD_Err; /* Y 0x8207_0210 [15:00] */ + uint32_t OFDM_SIG_Err; /* Y 0x8207_0214 [31:16] */ + uint32_t OFDM_TAG_Err; /* Y 0x8207_0214 [15:00] */ + uint32_t WB_RSSSI0; /* Y 0x8207_21A8 [23:16] */ + uint32_t IB_RSSSI0; /* Y 0x8207_21A8 [31:24] */ + uint32_t WB_RSSSI1; /* Y 0x8207_21A8 [07:00] */ + uint32_t IB_RSSSI1; /* Y 0x8207_21A8 [15:08] */ + uint32_t PhyMdrdyCCK; /* Y 0x8207_0220 [15:00] */ + uint32_t PhyMdrdyOFDM; /* Y 0x8207_0220 [31:16] */ + uint32_t DriverRxCount; /* Y FW Counter Band0 */ + uint32_t RCPI0; /* Y RXV4 [07:00] */ + uint32_t RCPI1; /* Y RXV4 [15:08] */ + uint32_t FreqOffsetFromRX; /* Y RXV5 MISC1[24:00] OFDM:[11:00] + * CCK:[10:00] + */ + uint32_t RSSI0; /* N */ + uint32_t RSSI1; /* N */ + uint32_t rx_fifo_full; /* N */ + uint32_t RxLenMismatch; /* N */ + uint32_t MacFCSErr_band1; /* Y 0x820F_D214 */ + uint32_t MacMdrdy_band1; /* Y 0x820F_D230 */ + /* Y RXV3 [23:16] (must set 0x8207066C[1:0] = 0x0 ~ 0x3) */ + uint32_t FAGC_IB_RSSSI[4]; + /* Y RXV3 [31:24] (must set 0x8207066C[1:0] = 0x0 ~ 0x3) */ + uint32_t FAGC_WB_RSSSI[4]; + /* Y 0x8207_21A8 [31:24] [15:08] 0x8207_29A8 [31:24] [15:08] */ + uint32_t Inst_IB_RSSSI[4]; + /* Y 0x8207_21A8 [23:16] [07:00] 0x8207_29A8 [23:16] [07:00] */ + uint32_t Inst_WB_RSSSI[4]; + uint32_t ACIHitLow; /* Y 0x8207_21B0 [18] */ + uint32_t ACIHitHigh; /* Y 0x8207_29B0 [18] */ + uint32_t DriverRxCount1; /* Y FW Counter Band1 */ + uint32_t RCPI2; /* Y RXV4 [23:16] */ + uint32_t RCPI3; /* Y RXV4 [31:24] */ + uint32_t RSSI2; /* N */ + uint32_t RSSI3; /* N */ + uint32_t SNR0; /* Y RXV5 (MISC1 >> 19) - 16 */ + uint32_t SNR1; /* N */ + uint32_t SNR2; /* N */ + uint32_t SNR3; /* N */ + uint32_t rx_fifo_full_band1; /* N */ + uint32_t RxLenMismatch_band1; /* N */ + uint32_t CCK_PD_band1; /* Y 0x8207_040C [15:00] */ + uint32_t OFDM_PD_band1; /* Y 0x8207_040C [31:16] */ + uint32_t CCK_SIG_Err_band1; /* Y 0x8207_0410 [31:16] */ + uint32_t CCK_SFD_Err_band1; /* Y 0x8207_0410 [15:00] */ + uint32_t OFDM_SIG_Err_band1; /* Y 0x8207_0414 [31:16] */ + uint32_t OFDM_TAG_Err_band1; /* Y 0x8207_0414 [15:00] */ + uint32_t PhyMdrdyCCK_band1; /* Y 0x8207_0420 [15:00] */ + uint32_t PhyMdrdyOFDM_band1; /* Y 0x8207_0420 [31:16] */ + uint32_t CCK_FCS_Err_band1; /* Y 0x8207_041C [15:00] */ + uint32_t OFDM_FCS_Err_band1; /* Y 0x8207_041C [31:16] */ + uint32_t MuPktCount; /* Y MT_ATEUpdateRxStatistic + * RXV1_2ND_CYCLE->GroupId + */ +}; +#else +struct PARAM_RX_STAT { + uint32_t MAC_FCS_Err; /* b0 */ + uint32_t MAC_Mdrdy; /* b0 */ + uint32_t FCSErr_CCK; + uint32_t FCSErr_OFDM; + uint32_t CCK_PD; + uint32_t OFDM_PD; + uint32_t CCK_SIG_Err; + uint32_t CCK_SFD_Err; + uint32_t OFDM_SIG_Err; + uint32_t OFDM_TAG_Err; + uint32_t WB_RSSI0; + uint32_t IB_RSSI0; + uint32_t WB_RSSI1; + uint32_t IB_RSSI1; + uint32_t PhyMdrdyCCK; + uint32_t PhyMdrdyOFDM; + uint32_t DriverRxCount; + uint32_t RCPI0; + uint32_t RCPI1; + uint32_t FreqOffsetFromRX; + uint32_t RSSI0; + uint32_t RSSI1; /* insert new member here */ + uint32_t OutOfResource; /* MT7615 begin here */ + uint32_t LengthMismatchCount_B0; + uint32_t MAC_FCS_Err1; /* b1 */ + uint32_t MAC_Mdrdy1; /* b1 */ + uint32_t FAGCRssiIBR0; + uint32_t FAGCRssiIBR1; + uint32_t FAGCRssiIBR2; + uint32_t FAGCRssiIBR3; + uint32_t FAGCRssiWBR0; + uint32_t FAGCRssiWBR1; + uint32_t FAGCRssiWBR2; + uint32_t FAGCRssiWBR3; + + uint32_t InstRssiIBR0; + uint32_t InstRssiIBR1; + uint32_t InstRssiIBR2; + uint32_t InstRssiIBR3; + uint32_t InstRssiWBR0; + uint32_t InstRssiWBR1; + uint32_t InstRssiWBR2; + uint32_t InstRssiWBR3; + uint32_t ACIHitLower; + uint32_t ACIHitUpper; + uint32_t DriverRxCount1; + uint32_t RCPI2; + uint32_t RCPI3; + uint32_t RSSI2; + uint32_t RSSI3; + uint32_t SNR0; + uint32_t SNR1; + uint32_t SNR2; + uint32_t SNR3; + uint32_t OutOfResource1; + uint32_t LengthMismatchCount_B1; + uint32_t CCK_PD_Band1; + uint32_t OFDM_PD_Band1; + uint32_t CCK_SIG_Err_Band1; + uint32_t CCK_SFD_Err_Band1; + uint32_t OFDM_SIG_Err_Band1; + uint32_t OFDM_TAG_Err_Band1; + uint32_t PHY_CCK_MDRDY_Band1; + uint32_t PHY_OFDM_MDRDY_Band1; + uint32_t CCK_FCS_Err_Band1; + uint32_t OFDM_FCS_Err_Band1; + uint32_t MRURxCount; + uint32_t SIGMCS; + uint32_t SINR; + uint32_t RXVRSSI; + uint32_t Reserved[184]; + uint32_t PHY_Mdrdy; + uint32_t Noise_Floor; + uint32_t AllLengthMismatchCount_B0; + uint32_t AllLengthMismatchCount_B1; + uint32_t AllMacMdrdy0; + uint32_t AllMacMdrdy1; + uint32_t AllFCSErr0; + uint32_t AllFCSErr1; + uint32_t RXOK0; + uint32_t RXOK1; + uint32_t PER0; + uint32_t PER1; +}; +extern struct PARAM_RX_STAT g_HqaRxStat; + +struct hqa_rx_stat_resp_field { + uint32_t type; + uint32_t version; + uint32_t item_mask; + uint32_t blk_cnt; + uint32_t blk_size; +}; + +struct hqa_rx_stat_band_format { + u_int32_t mac_rx_fcs_err_cnt; + u_int32_t mac_rx_mdrdy_cnt; + u_int32_t mac_rx_len_mismatch; + u_int32_t mac_rx_fcs_ok_cnt; + u_int32_t phy_rx_fcs_err_cnt_cck; + u_int32_t phy_rx_fcs_err_cnt_ofdm; + u_int32_t phy_rx_pd_cck; + u_int32_t phy_rx_pd_ofdm; + u_int32_t phy_rx_sig_err_cck; + u_int32_t phy_rx_sfd_err_cck; + u_int32_t phy_rx_sig_err_ofdm; + u_int32_t phy_rx_tag_err_ofdm; + u_int32_t phy_rx_mdrdy_cnt_cck; + u_int32_t phy_rx_mdrdy_cnt_ofdm; +}; + +struct hqa_rx_stat_path_format { + u_int32_t rcpi; + u_int32_t rssi; + u_int32_t fagc_ib_rssi; + u_int32_t fagc_wb_rssi; + u_int32_t inst_ib_rssi; + u_int32_t inst_wb_rssi; +}; + +struct hqa_rx_stat_user_format { + int32_t freq_offset_from_rx; + u_int32_t snr; + u_int32_t fcs_error_cnt; +}; + +struct hqa_rx_stat_comm_format { + u_int32_t rx_fifo_full; + u_int32_t aci_hit_low; + u_int32_t aci_hit_high; + u_int32_t mu_pkt_count; + u_int32_t sig_mcs; + u_int32_t sinr; + u_int32_t driver_rx_count; +}; + + +struct hqa_rx_stat_u { + union { + struct hqa_rx_stat_band_format rx_st_band; + struct hqa_rx_stat_path_format rx_st_path; + struct hqa_rx_stat_user_format rx_st_user; + struct hqa_rx_stat_comm_format rx_st_comm; + } u; +}; + +enum { + HQA_SERV_RX_STAT_TYPE_BAND = 0, + HQA_SERV_RX_STAT_TYPE_PATH, + HQA_SERV_RX_STAT_TYPE_USER, + HQA_SERV_RX_STAT_TYPE_COMM, + HQA_SERV_RX_STAT_TYPE_NUM +}; + +enum { + HQA_ANT_WF0 = 0, + HQA_ANT_WF1 = 1, + HQA_MAX_ANT_NUM +}; + +enum { + HQA_M_BAND_0 = 0, + HQA_M_BAND_1 = 1, + HQA_M_BAND_NUM +}; + +enum { + HQA_RX_STAT_BAND = 0, + HQA_RX_STAT_PATH, + HQA_RX_STAT_USER, + HQA_RX_STAT_COMM, + HQA_RX_STAT_NUM +}; +#endif + +struct HQA_CMD_FRAME { + uint32_t MagicNo; + uint16_t Type; + uint16_t Id; + uint16_t Length; + uint16_t Sequence; + uint8_t Data[2048]; +} __KAL_ATTRIB_PACKED__; + +typedef int32_t(*HQA_CMD_HANDLER) (struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame); + +struct HQA_CMD_TABLE { + HQA_CMD_HANDLER *CmdSet; + uint32_t CmdSetSize; + uint32_t CmdOffset; +}; + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +int HQA_CMDHandler(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame); + +int priv_qa_agent(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN char *pcExtra); + +int32_t mt6632SetICapStart(struct GLUE_INFO *prGlueInfo, + uint32_t u4Trigger, uint32_t u4RingCapEn, + uint32_t u4Event, uint32_t u4Node, uint32_t u4Len, + uint32_t u4StopCycle, + uint32_t u4BW, uint32_t u4MacTriggerEvent, + uint32_t u4SourceAddrLSB, + uint32_t u4SourceAddrMSB, uint32_t u4Band); +int32_t mt6632GetICapStatus(struct GLUE_INFO *prGlueInfo); + +int32_t connacSetICapStart(struct GLUE_INFO *prGlueInfo, + uint32_t u4Trigger, uint32_t u4RingCapEn, + uint32_t u4Event, uint32_t u4Node, uint32_t u4Len, + uint32_t u4StopCycle, + uint32_t u4BW, uint32_t u4MacTriggerEvent, + uint32_t u4SourceAddrLSB, + uint32_t u4SourceAddrMSB, uint32_t u4Band); +int32_t connacGetICapStatus(struct GLUE_INFO *prGlueInfo); + +int32_t commonGetICapIQData(struct GLUE_INFO *prGlueInfo, + uint8_t *pData, uint32_t u4IQType, uint32_t u4WFNum); +int32_t connacGetICapIQData(struct GLUE_INFO *prGlueInfo, + uint8_t *pData, uint32_t u4IQType, uint32_t u4WFNum); + + +#endif /*CFG_SUPPORT_QA_TOOL */ +#endif /* _GL_QA_AGENT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_rst.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_rst.h new file mode 100644 index 0000000000000..7cce675108fb9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_rst.h @@ -0,0 +1,313 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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" + +#if CFG_MTK_ANDROID_WMT && (CFG_SUPPORT_CONNINFRA == 0) +#include "wmt_exp.h" +#endif + +#if 0 +#include "mtk_porting.h" +#endif +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#if (MTK_WCN_HIF_SDIO == 1) || (MTK_WCN_HIF_AXI == 1) +#define CFG_WMT_RESET_API_SUPPORT 1 +#else +#define CFG_WMT_RESET_API_SUPPORT 0 +#endif + +#define RST_FLAG_CHIP_RESET 0 +#define RST_FLAG_DO_CORE_DUMP BIT(0) +#define RST_FLAG_PREVENT_POWER_OFF BIT(1) +#define RST_FLAG_DO_WHOLE_RESET BIT(2) + +#if CFG_CHIP_RESET_HANG +#define SER_L0_HANG_RST_NONE 0 +#define SER_L0_HANG_RST_TRGING 1 +#define SER_L0_HANG_RST_HAND_DISABLE 2 +#define SER_L0_HANG_RST_HANG 3 +#define SER_L0_HANG_RST_CMD_TRG 9 + +#define SER_L0_HANG_LOG_TIME_INTERVAL 3000 +#endif +#if (CFG_SUPPORT_CONNINFRA == 1) +#include "conninfra.h" +#define WIFI_TRIGGER_ASSERT_TIMEOUT 2000 +#define GLUE_FLAG_RST_PROCESS (GLUE_FLAG_HALT |\ + GLUE_FLAG_RST_START |\ + GLUE_FLAG_RST_END) +#define RST_FLAG_WHOLE_RESET (RST_FLAG_DO_CORE_DUMP | \ + RST_FLAG_PREVENT_POWER_OFF |\ + RST_FLAG_DO_WHOLE_RESET) +#define RST_FLAG_WF_RESET (RST_FLAG_DO_CORE_DUMP | RST_FLAG_PREVENT_POWER_OFF) +#endif +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +enum ENUM_RESET_STATUS { + RESET_FAIL, + RESET_SUCCESS +}; + +enum _ENUM_CHIP_RESET_REASON_TYPE_T { + RST_PROCESS_ABNORMAL_INT = 1, + RST_DRV_OWN_FAIL, + RST_FW_ASSERT, + RST_BT_TRIGGER, + RST_OID_TIMEOUT, + RST_CMD_TRIGGER, + RST_REASON_MAX +}; + +struct RESET_STRUCT { + struct GLUE_INFO *prGlueInfo; + struct work_struct rst_work; +#if CFG_WMT_RESET_API_SUPPORT + enum ENUM_RESET_STATUS rst_data; + struct work_struct rst_trigger_work; + uint32_t rst_trigger_flag; +#endif +}; + +#if CFG_WMT_RESET_API_SUPPORT +#if (CFG_SUPPORT_CONNINFRA == 1) +/* duplicated from wmt_exp.h for better driver isolation */ +enum ENUM_WMTDRV_TYPE { + 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 ENUM_WMTMSG_TYPE { + 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 ENUM_WMTRSTMSG_TYPE { + WMTRSTMSG_RESET_START = 0x0, /*whole chip reset (include other radio)*/ + WMTRSTMSG_RESET_END = 0x1, + WMTRSTMSG_RESET_END_FAIL = 0x2, + WMTRSTMSG_0P5RESET_START = 0x3, /*wfsys reset ( wifi only )*/ + WMTRSTMSG_RESET_MAX, + WMTRSTMSG_RESET_INVALID = 0xff +}; + +enum ENUM_WF_RST_SOURCE { + WF_RST_SOURCE_NONE = 0x0, + WF_RST_SOURCE_DRIVER = 0x1, + WF_RST_SOURCE_FW = 0x2, + WF_RST_SOURCE_MAX +}; +#endif +#endif + +/******************************************************************************* + * E X T E R N A L F U N C T I O N S + ******************************************************************************* + */ +#if CFG_CHIP_RESET_SUPPORT + +#if CFG_WMT_RESET_API_SUPPORT +extern int wifi_reset_start(void); +extern int wifi_reset_end(enum ENUM_RESET_STATUS); + +#if (CFG_SUPPORT_CONNINFRA == 1) +extern int hifAxiRemove(void); +extern void kalSetRstEvent(void); +extern void update_driver_reset_status(uint8_t fgIsResetting); +extern int32_t get_wifi_process_status(void); +extern int32_t get_wifi_powered_status(void); +#endif /* CFG_SUPPORT_CONNINFRA */ + +#endif /* CFG_WMT_RESET_API_SUPPORT */ +#endif /* CFG_CHIP_RESET_SUPPORT */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +#if CFG_CHIP_RESET_SUPPORT +extern u_int8_t fgIsResetting; +#if (CFG_SUPPORT_CONNINFRA == 1) +extern enum ENUM_WF_RST_SOURCE g_eWfRstSource; +#endif + +#if CFG_CHIP_RESET_HANG +extern u_int8_t fgIsResetHangState; +#endif + +#endif +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +#define GL_COREDUMP_TRIGGER(_prAdapter) \ +{ \ + wlanoidSerExtCmd(_prAdapter, SER_ACTION_RECOVER, \ + SER_SET_L0_RECOVER, 0); \ +} + +#if CFG_CHIP_RESET_SUPPORT +#if CFG_WMT_RESET_API_SUPPORT +#define GL_RESET_TRIGGER(_prAdapter, _u4Flags) \ + glResetTrigger(_prAdapter, (_u4Flags), \ + (const uint8_t *)__FILE__, __LINE__) +#else +#define GL_RESET_TRIGGER(_prAdapter, _u4Flags) \ +{ \ + if (glGetRstReason() == RST_OID_TIMEOUT || \ + glGetRstReason() == RST_FW_ASSERT || \ + glGetRstReason() == RST_CMD_TRIGGER || \ + glGetRstReason() == RST_BT_TRIGGER) { \ + glResetTrigger(_prAdapter, (_u4Flags), \ + (const uint8_t *)__FILE__, __LINE__); \ + } else { \ + GL_COREDUMP_TRIGGER(_prAdapter); \ + DBGLOG(INIT, ERROR, "Trigger coredump in %s line %u!\n", \ + __FILE__, __LINE__); \ + } \ +} +#endif +#else +#define GL_RESET_TRIGGER(_prAdapter, _u4Flags) \ + DBGLOG(INIT, INFO, "DO NOT support chip reset\n") +#endif + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +#if CFG_CHIP_RESET_SUPPORT +extern uint64_t u8ResetTime; +extern u_int8_t fgSimplifyResetFlow; +extern char *g_reason; +#else + +#endif +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +void glSetRstReason(enum _ENUM_CHIP_RESET_REASON_TYPE_T eReason); +int glGetRstReason(void); + +u_int8_t kalIsResetting(void); + +#if CFG_CHIP_RESET_SUPPORT +void glResetInit(struct GLUE_INFO *prGlueInfo); + +void glResetUninit(void); + +void glSendResetRequest(void); + +u_int8_t glResetTrigger(struct ADAPTER *prAdapter, + uint32_t u4RstFlag, const uint8_t *pucFile, + uint32_t u4Line); + +#if CFG_WMT_RESET_API_SUPPORT +int32_t glIsWmtCodeDump(void); +#endif +#if (CFG_SUPPORT_CONNINFRA == 1) + +int wlan_reset_thread_main(void *data); +int glRstwlanPreWholeChipReset(enum consys_drv_type type, char *reason); +int glRstwlanPostWholeChipReset(void); +u_int8_t kalIsWholeChipResetting(void); +void glSetRstReasonString(char *reason); + +#endif /*end of CFG_SUPPORT_CONNINFRA == 0*/ + +#else + +#endif +#endif /* _GL_RST_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_sec.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_sec.h new file mode 100644 index 0000000000000..e00aab1ff55e5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_sec.h @@ -0,0 +1,79 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include + * /gl_sec.h#1 + */ + +/*! \file p2p_fsm.h + * \brief Declaration of functions and finite state machine for P2P Module. + * + * Declaration of functions and finite state machine for P2P Module. + */ + +#ifndef _GL_SEC_H +#define _GL_SEC_H + +extern void handle_sec_msg_1(unsigned char *msg_in, int msg_in_len, + unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_2(unsigned char *msg_in, int msg_in_len, + unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_3(unsigned char *msg_in, int msg_in_len, + unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_4(unsigned char *msg_in, int msg_in_len, + unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_5(unsigned char *msg_in, int msg_in_len, + unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_final(unsigned char *msg_in, int msg_in_len, + unsigned char *msg_out, int *msg_out_len); + +#endif /* _GL_SEC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_typedef.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_typedef.h new file mode 100644 index 0000000000000..fb82f83bb26dd --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_typedef.h @@ -0,0 +1,322 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + * 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. + */ + + +#ifndef _GL_TYPEDEF_H +#define _GL_TYPEDEF_H + +#if CFG_ENABLE_EARLY_SUSPEND +#include +#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 ((u_int8_t) 0) +#define TRUE ((u_int8_t) 1) +#endif /* FALSE */ + +#ifndef NULL +#if defined(__cplusplus) +#define NULL 0 +#else +#define NULL ((void *) 0) +#endif +#endif + +#if CFG_ENABLE_EARLY_SUSPEND +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 */ + +/* Type definition for Boolean */ + +/* Type definition for signed integers */ + +/* Type definition for unsigned integers */ + + +#define OS_SYSTIME uint32_t + +/* Type definition of large integer (64bits) union to be comptaible with + * Windows definition, so we won't apply our own coding style to these data + * types. + * NOTE: LARGE_INTEGER must NOT be floating variable. + * : Check for big-endian compatibility. + */ +union LARGE_INTEGER { + struct { + uint32_t LowPart; + int32_t HighPart; + } u; + int64_t QuadPart; +}; + +union ULARGE_INTEGER { + struct { + uint32_t LowPart; + uint32_t HighPart; + } u; + uint64_t QuadPart; +}; + +typedef int32_t(*probe_card) (void *pvData, + void *pvDriverData); +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__ inline +#define __KAL_ATTRIB_PACKED__ __attribute__((__packed__)) +#define __KAL_ATTRIB_ALIGN_4__ __aligned(4) + +#ifndef BIT +#define BIT(n) ((uint32_t) 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) offsetof(_type, _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 *)((int8_t *)(_addrOfField) - \ + (int8_t *)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 */ + +#ifndef ALIGN_8 +#define ALIGN_8(_value) (((_value) + 7) & ~7u) +#endif /* ALIGN_4 */ + +/* This macro check the DW alignment of the input value. + * _value - value of address need to check + */ +#ifndef IS_ALIGN_4 +#define IS_ALIGN_4(_value) (((_value) & 0x3) ? FALSE : TRUE) +#endif /* IS_ALIGN_4 */ + +#ifndef IS_NOT_ALIGN_4 +#define IS_NOT_ALIGN_4(_value) (((_value) & 0x3) ? TRUE : FALSE) +#endif /* IS_NOT_ALIGN_4 */ + +/* This macro evaluate the input length in unit of Double Word(4 Bytes). + * _value - value in unit of Byte, output will round up to DW boundary. + */ +#ifndef BYTE_TO_DWORD +#define BYTE_TO_DWORD(_value) ((_value + 3) >> 2) +#endif /* BYTE_TO_DWORD */ + +/* This macro evaluate the input length in unit of Byte. + * _value - value in unit of DW, output is in unit of Byte. + */ +#ifndef DWORD_TO_BYTE +#define DWORD_TO_BYTE(_value) ((_value) << 2) +#endif /* DWORD_TO_BYTE */ + +#if 1 /* Little-Endian */ +#define CONST_NTOHS(_x) ntohs(_x) + +#define CONST_HTONS(_x) htons(_x) + +#define NTOHS(_x) ntohs(_x) + +#define HTONS(_x) htons(_x) + +#define NTOHL(_x) ntohl(_x) + +#define HTONL(_x) htonl(_x) + +#else /* Big-Endian */ + +#define CONST_NTOHS(_x) + +#define CONST_HTONS(_x) + +#define NTOHS(_x) + +#define HTONS(_x) + +#endif + +#define CPU_TO_LE16 cpu_to_le16 +#define CPU_TO_LE32 cpu_to_le32 +#define CPU_TO_LE64 cpu_to_le64 + +#define LE16_TO_CPU le16_to_cpu +#define LE32_TO_CPU le32_to_cpu +#define LE64_TO_CPU le64_to_cpu + +#define SWAP32(x) \ + ((uint32_t) (\ + (((uint32_t) (x) & (uint32_t) 0x000000ffUL) << 24) | \ + (((uint32_t) (x) & (uint32_t) 0x0000ff00UL) << 8) | \ + (((uint32_t) (x) & (uint32_t) 0x00ff0000UL) >> 8) | \ + (((uint32_t) (x) & (uint32_t) 0xff000000UL) >> 24))) + +/* Endian byte swapping codes */ +#ifdef __LITTLE_ENDIAN +#define LE48_TO_CPU(x) (x) +#define CPU_TO_LE48(x) (x) +#define cpu2le32(x) ((uint32_t)(x)) +#define le2cpu32(x) ((uint32_t)(x)) +#define cpu2be32(x) SWAP32((x)) +#define be2cpu32(x) SWAP32((x)) + +#else + + +#define SWAP48(x) \ + ((uint64_t)( \ + (uint64_t)(((UINT_64)(x) & (uint64_t) 0x0000000000ffULL) << 40) | \ + (uint64_t)(((UINT_64)(x) & (uint64_t) 0x00000000ff00ULL) << 24) | \ + (uint64_t)(((UINT_64)(x) & (uint64_t) 0x000000ff0000ULL) << 8) | \ + (uint64_t)(((UINT_64)(x) & (uint64_t) 0x0000ff000000ULL) >> 8) | \ + (uint64_t)(((UINT_64)(x) & (uint64_t) 0x00ff00000000ULL) >> 24) | \ + (uint64_t)(((UINT_64)(x) & (uint64_t) 0xff0000000000ULL) >> 40))) +#define LE48_TO_CPU(x) SWAP48(x) +#define CPU_TO_LE48(x) SWAP48(x) +#define cpu2le32(x) SWAP32((x)) +#define le2cpu32(x) SWAP32((x)) +#define cpu2be32(x) ((uint32_t)(x)) +#define be2cpu32(x) ((uint32_t)(x)) + + +#endif + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _GL_TYPEDEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_vendor.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_vendor.h new file mode 100644 index 0000000000000..6d5a850b0c4c4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_vendor.h @@ -0,0 +1,797 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + * Log: gl_vendor.h + * + * 10 14 2014 + * add vendor declaration + * + * + */ + +#ifndef _GL_VENDOR_H +#define _GL_VENDOR_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include +#include +#include +#include +#include +#include +#include +#include "wlan_lib.h" +#include "gl_wext.h" + + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define GOOGLE_OUI 0x001A11 +#define OUI_QCA 0x001374 +#if CFG_SUPPORT_DATA_STALL +#define OUI_MTK 0x000CE7 +#endif + +#define NL80211_VENDOR_SUBCMD_GET_PREFER_FREQ_LIST 103 +#define NL80211_VENDOR_SUBCMD_ACS 54 +#define NL80211_VENDOR_SUBCMD_GET_FEATURES 55 +#define QCA_NL80211_VENDOR_SUBCMD_ROAM 64 +#define QCA_NL80211_VENDOR_SUBCMD_SETBAND 105 + +#define WIFI_VENDOR_ATTR_FEATURE_FLAGS 7 + +enum NL80211_VENDOR_FEATURES { + VENDOR_FEATURE_KEY_MGMT_OFFLOAD = 0, + VENDOR_FEATURE_SUPPORT_HW_MODE_ANY = 1, + VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS = 2, + VENDOR_FEATURE_P2P_LISTEN_OFFLOAD = 3, + VENDOR_FEATURE_OCE_STA = 4, + VENDOR_FEATURE_OCE_AP = 5, + VENDOR_FEATURE_OCE_STA_CFON = 6, + NUM_VENDOR_FEATURES /* keep last */ +}; + +enum ANDROID_VENDOR_SUB_COMMAND { + /* Don't use 0 as a valid subcommand */ + ANDROID_NL80211_SUBCMD_UNSPECIFIED, + + /* Define all vendor startup commands between 0x0 and 0x0FFF */ + ANDROID_NL80211_SUBCMD_WIFI_RANGE_START = 0x0001, + ANDROID_NL80211_SUBCMD_WIFI_RANGE_END = 0x0FFF, + + /* Define all GScan related commands between 0x1000 and 0x10FF */ + ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START = 0x1000, + ANDROID_NL80211_SUBCMD_GSCAN_RANGE_END = 0x10FF, + + /* Define all RTT related commands between 0x1100 and 0x11FF */ + ANDROID_NL80211_SUBCMD_RTT_RANGE_START = 0x1100, + ANDROID_NL80211_SUBCMD_RTT_RANGE_END = 0x11FF, + + ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START = 0x1200, + ANDROID_NL80211_SUBCMD_LSTATS_RANGE_END = 0x12FF, + + /* Define all Logger related commands between 0x1400 and 0x14FF */ + ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START = 0x1400, + ANDROID_NL80211_SUBCMD_DEBUG_RANGE_END = 0x14FF, + + /* Define all wifi offload related commands between 0x1600 and 0x16FF */ + ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START = 0x1600, + ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_END = 0x16FF, + + /* This is reserved for future usage */ + +}; + +enum WIFI_SUB_COMMAND { + WIFI_SUBCMD_GET_CHANNEL_LIST = ANDROID_NL80211_SUBCMD_WIFI_RANGE_START, + + WIFI_SUBCMD_GET_FEATURE_SET, /* 0x0002 */ + WIFI_SUBCMD_GET_FEATURE_SET_MATRIX, /* 0x0003 */ + WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI, /* 0x0004 */ + WIFI_SUBCMD_NODFS_SET, /* 0x0005 */ + WIFI_SUBCMD_SET_COUNTRY_CODE, /* 0x0006 */ + WIFI_SUBCMD_SET_RSSI_MONITOR, /* 0x0007 */ + + /* Add more sub commands here */ + WIFI_SUBCMD_GET_ROAMING_CAPABILITIES, /* 0x0008 */ + WIFI_SUBCMD_SET_ROAMING = 0x0009, /* 0x0009 */ + WIFI_SUBCMD_CONFIG_ROAMING = 0x000a, /* 0x000a */ + WIFI_SUBCMD_ENABLE_ROAMING, /* 0x000b */ + WIFI_SUBCMD_SELECT_TX_POWER_SCENARIO, /* 0x000c */ +}; + +enum RTT_SUB_COMMAND { + RTT_SUBCMD_SET_CONFIG = ANDROID_NL80211_SUBCMD_RTT_RANGE_START, + RTT_SUBCMD_CANCEL_CONFIG, + RTT_SUBCMD_GETCAPABILITY, +}; + +enum LSTATS_SUB_COMMAND { + LSTATS_SUBCMD_GET_INFO = ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START, +}; + +/* moved from wifi_logger.cpp */ +enum DEBUG_SUB_COMMAND { + LOGGER_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START, + LOGGER_GET_VER, + LOGGER_DRIVER_MEM_DUMP, +}; + +enum WIFI_OFFLOAD_SUB_COMMAND { + WIFI_OFFLOAD_START_MKEEP_ALIVE = + ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START, + WIFI_OFFLOAD_STOP_MKEEP_ALIVE, +}; + +enum WIFI_VENDOR_EVENT { + GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS, + GSCAN_EVENT_HOTLIST_RESULTS_FOUND, + GSCAN_EVENT_SCAN_RESULTS_AVAILABLE, + GSCAN_EVENT_FULL_SCAN_RESULTS, + RTT_EVENT_COMPLETE, + GSCAN_EVENT_COMPLETE_SCAN, + GSCAN_EVENT_HOTLIST_RESULTS_LOST, + WIFI_EVENT_RSSI_MONITOR, + WIFI_EVENT_DRIVER_ERROR, + WIFI_EVENT_ACS, + WIFI_EVENT_GENERIC_RESPONSE, + WIFI_EVENT_BIGDATA_PIP + /* Always add at the end.*/ +}; + +enum WIFI_ATTRIBUTE { + WIFI_ATTRIBUTE_BAND = 1, + WIFI_ATTRIBUTE_NUM_CHANNELS, + WIFI_ATTRIBUTE_CHANNEL_LIST, + + WIFI_ATTRIBUTE_NUM_FEATURE_SET, + WIFI_ATTRIBUTE_FEATURE_SET, + WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, + WIFI_ATTRIBUTE_NODFS_VALUE, + WIFI_ATTRIBUTE_COUNTRY_CODE, + + WIFI_ATTRIBUTE_MAX_RSSI, + WIFI_ATTRIBUTE_MIN_RSSI, + WIFI_ATTRIBUTE_RSSI_MONITOR_START, + + WIFI_ATTRIBUTE_ROAMING_CAPABILITIES, + WIFI_ATTRIBUTE_ROAMING_BLACKLIST_NUM, + WIFI_ATTRIBUTE_ROAMING_BLACKLIST_BSSID, + WIFI_ATTRIBUTE_ROAMING_WHITELIST_NUM, + WIFI_ATTRIBUTE_ROAMING_WHITELIST_SSID, + WIFI_ATTRIBUTE_ROAMING_STATE, + WIFI_ATTRIBUTE_TX_POWER_SCENARIO, +}; + +/* moved from wifi_logger.cpp */ +enum LOGGER_ATTRIBUTE { + LOGGER_ATTRIBUTE_DRIVER_VER, + LOGGER_ATTRIBUTE_FW_VER +}; + +enum RTT_ATTRIBUTE { + RTT_ATTRIBUTE_CAPABILITIES = 1, + + RTT_ATTRIBUTE_TARGET_CNT = 10, + RTT_ATTRIBUTE_TARGET_INFO, + RTT_ATTRIBUTE_TARGET_MAC, + RTT_ATTRIBUTE_TARGET_TYPE, + RTT_ATTRIBUTE_TARGET_PEER, + RTT_ATTRIBUTE_TARGET_CHAN, + RTT_ATTRIBUTE_TARGET_PERIOD, + RTT_ATTRIBUTE_TARGET_NUM_BURST, + RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST, + RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM, + RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR, + RTT_ATTRIBUTE_TARGET_LCI, + RTT_ATTRIBUTE_TARGET_LCR, + RTT_ATTRIBUTE_TARGET_BURST_DURATION, + RTT_ATTRIBUTE_TARGET_PREAMBLE, + RTT_ATTRIBUTE_TARGET_BW, + RTT_ATTRIBUTE_RESULTS_COMPLETE = 30, + RTT_ATTRIBUTE_RESULTS_PER_TARGET, + RTT_ATTRIBUTE_RESULT_CNT, + RTT_ATTRIBUTE_RESULT +}; + +enum LSTATS_ATTRIBUTE { + LSTATS_ATTRIBUTE_STATS = 2, +}; + +enum WIFI_MKEEP_ALIVE_ATTRIBUTE { + MKEEP_ALIVE_ATTRIBUTE_ID = 1, + MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN, + MKEEP_ALIVE_ATTRIBUTE_IP_PKT, + MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR, + MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR, + MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC +}; + +/* QCA Vender CMD */ +enum QCA_SET_BAND { + QCA_SETBAND_AUTO, + QCA_SETBAND_5G, + QCA_SETBAND_2G, +}; + +enum QCA_ATTR_ROAM_SUBCMD { + QCA_ATTR_ROAM_SUBCMD_INVALID = 0, + QCA_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID = 6, + + /* keep last */ + QCA_ATTR_ROAM_SUBCMD_AFTER_LAST, + QCA_ATTR_ROAM_SUBCMD_MAX = + QCA_ATTR_ROAM_SUBCMD_AFTER_LAST - 1, +}; + +enum QCA_ATTR_ROAMING_PARAMS { + QCA_ATTR_ROAMING_PARAM_INVALID = 0, + + QCA_ATTR_ROAMING_SUBCMD = 1, + + /* Attribute for set_blacklist bssid params */ + QCA_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS = 18, + QCA_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID = 19, + QCA_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID = 20, + + /* keep last */ + QCA_ATTR_ROAMING_PARAM_AFTER_LAST, + QCA_ATTR_ROAMING_PARAM_MAX = + QCA_ATTR_ROAMING_PARAM_AFTER_LAST - 1, +}; + +enum WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST { + WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_INVALID, + WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_IFACE_TYPE, + WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_GET, + WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_LAST, + WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_MAX = + WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_LAST - 1 +}; + +enum WIFI_VENDOR_ATTR_ACS { + WIFI_VENDOR_ATTR_ACS_CHANNEL_INVALID = 0, + WIFI_VENDOR_ATTR_ACS_PRIMARY_CHANNEL, + WIFI_VENDOR_ATTR_ACS_SECONDARY_CHANNEL, + WIFI_VENDOR_ATTR_ACS_HW_MODE, + WIFI_VENDOR_ATTR_ACS_HT_ENABLED, + WIFI_VENDOR_ATTR_ACS_HT40_ENABLED, + WIFI_VENDOR_ATTR_ACS_VHT_ENABLED, + WIFI_VENDOR_ATTR_ACS_CHWIDTH, + WIFI_VENDOR_ATTR_ACS_CH_LIST, + WIFI_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL, + WIFI_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL, + WIFI_VENDOR_ATTR_ACS_FREQ_LIST, + WIFI_VENDOR_ATTR_ACS_AFTER_LAST, + WIFI_VENDOR_ATTR_ACS_MAX = + WIFI_VENDOR_ATTR_ACS_AFTER_LAST - 1 +}; + +#define MAX_FW_ROAMING_BLACKLIST_SIZE 16 +#define MAX_FW_ROAMING_WHITELIST_SIZE 8 + +#if CFG_SUPPORT_DATA_STALL +enum WIFI_DATA_STALL_ATTRIBUTE { + WIFI_ATTRIBUTE_ERROR_REASON = 0, +}; +#endif + +#if CFG_SUPPORT_BIGDATA_PIP +enum WIFI_BIGDATA_PIP_ATTRIBUTE { + WIFI_ATTRIBUTE_PIP_PAYLOAD = 0, +}; +#endif +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +#if CFG_SUPPORT_WAPI +extern uint8_t +keyStructBuf[1024]; /* add/remove key shared buffer */ +#else +extern uint8_t +keyStructBuf[100]; /* add/remove key shared buffer */ +#endif + +/******************************************************************************* + * MACROS + ******************************************************************************* + */ + +#if KERNEL_VERSION(3, 5, 0) <= LINUX_VERSION_CODE +/* + * #define NLA_PUT(skb, attrtype, attrlen, data) \ + * do { \ + * if (unlikely(nla_put(skb, attrtype, attrlen, data) < 0)) \ + * goto nla_put_failure; \ + * } while (0) + * + *#define NLA_PUT_TYPE(skb, type, attrtype, value) \ + * do { \ + * type __tmp = value; \ + * NLA_PUT(skb, attrtype, sizeof(type), &__tmp); \ + * } while (0) + */ +#define NLA_PUT(skb, attrtype, attrlen, data) \ + mtk_cfg80211_NLA_PUT(skb, attrtype, attrlen, data) + +#define NLA_PUT_TYPE(skb, type, attrtype, value) \ + mtk_cfg80211_nla_put_type(skb, type, attrtype, value) + +#define NLA_PUT_U8(skb, attrtype, value) \ + NLA_PUT_TYPE(skb, NLA_PUT_DATE_U8, attrtype, value) + +#define NLA_PUT_U16(skb, attrtype, value) \ + NLA_PUT_TYPE(skb, NLA_PUT_DATE_U16, attrtype, value) + +#define NLA_PUT_U32(skb, attrtype, value) \ + NLA_PUT_TYPE(skb, NLA_PUT_DATE_U32, attrtype, value) + +#define NLA_PUT_U64(skb, attrtype, value) \ + NLA_PUT_TYPE(skb, NLA_PUT_DATE_U64, attrtype, value) + +#endif + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +#define NLA_PARSE_NESTED(nlattr, maxtype, nla, policy) \ + nla_parse_nested(nlattr, maxtype, nla, policy, NULL) +#define NLA_PARSE(tb, maxtype, head, len, policy) \ + nla_parse(tb, maxtype, head, len, policy, NULL) +#else +#define NLA_PARSE_NESTED(nlattr, maxtype, nla, policy) \ + nla_parse_nested(nlattr, maxtype, nla, policy) +#define NLA_PARSE(tb, maxtype, head, len, policy) \ + nla_parse(tb, maxtype, head, len, policy) +#endif + +/******************************************************************************* + * P R I V A T E D A T A + * + ******************************************************************************* + */ +struct PARAM_WIFI_CHANGE_RESULT { + uint16_t flags; + uint16_t channel; + uint8_t bssid[6]; /* BSSID */ + int8_t rssi[8]; /* RSSI history in db */ +}; + +struct PARAM_AP_THRESHOLD { + uint8_t bssid[6]; /* AP BSSID */ + int32_t low; /* low threshold */ + int32_t high; /* high threshold */ + uint32_t channel; /* channel hint */ +}; + +/* channel operating width */ +enum WIFI_CHANNEL_WIDTH { + WIFI_CHAN_WIDTH_20 = 0, + WIFI_CHAN_WIDTH_40 = 1, + WIFI_CHAN_WIDTH_80 = 2, + WIFI_CHAN_WIDTH_160 = 3, + WIFI_CHAN_WIDTH_80P80 = 4, + WIFI_CHAN_WIDTH_5 = 5, + WIFI_CHAN_WIDTH_10 = 6, + WIFI_CHAN_WIDTH_INVALID = -1 +}; + +/* channel information */ +struct WIFI_CHANNEL_INFO { + enum WIFI_CHANNEL_WIDTH width; + uint32_t center_freq; + uint32_t center_freq0; + uint32_t center_freq1; +}; + +/* channel statistics */ +struct WIFI_CHANNEL_STAT { + struct WIFI_CHANNEL_INFO channel; + uint32_t on_time; + uint32_t cca_busy_time; +}; + +/* radio statistics */ +struct WIFI_RADIO_STAT { + uint32_t radio; + uint32_t on_time; + uint32_t tx_time; + uint32_t rx_time; + uint32_t on_time_scan; + uint32_t on_time_nbd; + uint32_t on_time_gscan; + uint32_t on_time_roam_scan; + uint32_t on_time_pno_scan; + uint32_t on_time_hs20; + uint32_t num_channels; + struct WIFI_CHANNEL_STAT channels[]; +}; + +/* wifi rate */ +struct WIFI_RATE { + uint32_t preamble: 3; + uint32_t nss: 2; + uint32_t bw: 3; + uint32_t rateMcsIdx: 8; + + uint32_t reserved: 16; + uint32_t bitrate; +}; + +/* per rate statistics */ +struct WIFI_RATE_STAT { + struct WIFI_RATE rate; + uint32_t tx_mpdu; + uint32_t rx_mpdu; + uint32_t mpdu_lost; + uint32_t retries; + uint32_t retries_short; + uint32_t retries_long; +}; + +/*wifi_interface_link_layer_info*/ +enum WIFI_CONNECTION_STATE { + WIFI_DISCONNECTED = 0, + WIFI_AUTHENTICATING = 1, + WIFI_ASSOCIATING = 2, + WIFI_ASSOCIATED = 3, + WIFI_EAPOL_STARTED = 4, + WIFI_EAPOL_COMPLETED = 5, +}; + +enum WIFI_ROAM_STATE { + WIFI_ROAMING_IDLE = 0, + WIFI_ROAMING_ACTIVE = 1, +}; + +enum WIFI_INTERFACE_MODE { + WIFI_INTERFACE_STA = 0, + WIFI_INTERFACE_SOFTAP = 1, + WIFI_INTERFACE_IBSS = 2, + WIFI_INTERFACE_P2P_CLIENT = 3, + WIFI_INTERFACE_P2P_GO = 4, + WIFI_INTERFACE_NAN = 5, + WIFI_INTERFACE_MESH = 6, + WIFI_INTERFACE_UNKNOWN = -1 +}; + +struct WIFI_INTERFACE_LINK_LAYER_INFO { + enum WIFI_INTERFACE_MODE mode; + u8 mac_addr[6]; + enum WIFI_CONNECTION_STATE state; + enum WIFI_ROAM_STATE roaming; + u32 capabilities; + u8 ssid[33]; + u8 bssid[6]; + u8 ap_country_str[3]; + u8 country_str[3]; +}; + +/* access categories */ +enum WIFI_TRAFFIC_AC { + WIFI_AC_VO = 0, + WIFI_AC_VI = 1, + WIFI_AC_BE = 2, + WIFI_AC_BK = 3, + WIFI_AC_MAX = 4, +}; + +/* wifi peer type */ +enum WIFI_PEER_TYPE { + WIFI_PEER_STA, + WIFI_PEER_AP, + WIFI_PEER_P2P_GO, + WIFI_PEER_P2P_CLIENT, + WIFI_PEER_NAN, + WIFI_PEER_TDLS, + WIFI_PEER_INVALID, +}; + +/* per peer statistics */ +struct WIFI_PEER_INFO { + enum WIFI_PEER_TYPE type; + uint8_t peer_mac_address[6]; + uint32_t capabilities; + uint32_t num_rate; + struct WIFI_RATE_STAT rate_stats[]; +}; + +/* per access category statistics */ +struct WIFI_WMM_AC_STAT_ { + enum WIFI_TRAFFIC_AC ac; + uint32_t tx_mpdu; + uint32_t rx_mpdu; + uint32_t tx_mcast; + + uint32_t rx_mcast; + uint32_t rx_ampdu; + uint32_t tx_ampdu; + uint32_t mpdu_lost; + uint32_t retries; + uint32_t retries_short; + uint32_t retries_long; + uint32_t contention_time_min; + uint32_t contention_time_max; + uint32_t contention_time_avg; + uint32_t contention_num_samples; +}; + +/* RTT Capabilities */ +struct PARAM_WIFI_RTT_CAPABILITIES { + /* if 1-sided rtt data collection is supported */ + uint8_t rtt_one_sided_supported; + /* if ftm rtt data collection is supported */ + uint8_t rtt_ftm_supported; + /* if initiator supports LCI request. Applies to 2-sided RTT */ + uint8_t lci_support; + /* if initiator supports LCR request. Applies to 2-sided RTT */ + uint8_t lcr_support; + /* bit mask indicates what preamble is supported by initiator */ + uint8_t preamble_support; + /* bit mask indicates what BW is supported by initiator */ + uint8_t bw_support; +}; + +/* interface statistics */ +struct WIFI_IFACE_STAT { + struct WIFI_INTERFACE_LINK_LAYER_INFO info; + uint32_t beacon_rx; + uint32_t mgmt_rx; + uint32_t mgmt_action_rx; + uint32_t mgmt_action_tx; + int32_t rssi_mgmt; + int32_t rssi_data; + int32_t rssi_ack; + struct WIFI_WMM_AC_STAT_ ac[WIFI_AC_MAX]; + uint32_t num_peers; + struct WIFI_PEER_INFO peer_info[]; +}; + +enum ENUM_NLA_PUT_DATE_TYPE { + NLA_PUT_DATE_U8 = 0, + NLA_PUT_DATE_U16, + NLA_PUT_DATE_U32, + NLA_PUT_DATE_U64, +}; + +/* RSSI Monitoring */ +struct PARAM_RSSI_MONITOR_T { + bool enable; /* 1=Start, 0=Stop*/ + int8_t max_rssi_value; + int8_t min_rssi_value; + uint8_t reserved[1]; + uint8_t reserved2[4]; /* reserved for MT6632 */ +}; + +struct PARAM_RSSI_MONITOR_EVENT { + uint8_t version; + int8_t rssi; + uint8_t BSSID[PARAM_MAC_ADDR_LEN]; +}; + +/* Packet Keep Alive */ +struct PARAM_PACKET_KEEPALIVE_T { + bool enable; /* 1=Start, 0=Stop*/ + uint8_t index; + int16_t u2IpPktLen; + uint8_t pIpPkt[256]; + uint8_t ucSrcMacAddr[PARAM_MAC_ADDR_LEN]; + uint8_t ucDstMacAddr[PARAM_MAC_ADDR_LEN]; + uint32_t u4PeriodMsec; + uint8_t reserved[8]; /* reserved for MT6632 */ +}; + +struct PARAM_BSS_MAC_OUI { + uint8_t ucBssIndex; + uint8_t ucMacOui[MAC_OUI_LEN]; +}; + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + + + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +int mtk_cfg80211_NLA_PUT(struct sk_buff *skb, int attrtype, + int attrlen, const void *data); + +int mtk_cfg80211_nla_put_type(struct sk_buff *skb, + enum ENUM_NLA_PUT_DATE_TYPE type, int attrtype, + const void *value); + +int mtk_cfg80211_vendor_get_capabilities(struct wiphy + *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_config(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_scan_config(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_significant_change( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_hotlist(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_enable_scan(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_enable_full_scan_results( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_get_scan_results(struct wiphy + *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_get_channel_list(struct wiphy + *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_country_code(struct wiphy + *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_get_rtt_capabilities( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_llstats_get_info(struct wiphy + *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_band(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_scan_mac_oui(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +#if CFG_SUPPORT_MBO +int mtk_cfg80211_vendor_set_roaming_param( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); +#endif + +int mtk_cfg80211_vendor_set_roaming_policy( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_get_roaming_capabilities( + struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); + +int mtk_cfg80211_vendor_config_roaming(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +int mtk_cfg80211_vendor_enable_roaming(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +int mtk_cfg80211_vendor_set_rssi_monitoring( + struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); + +int mtk_cfg80211_vendor_packet_keep_alive_start( + struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); + +int mtk_cfg80211_vendor_packet_keep_alive_stop( + struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); + +int mtk_cfg80211_vendor_get_version(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_event_generic_response( + struct wiphy *wiphy, struct wireless_dev *wdev, + uint32_t len, uint8_t *data); + +int mtk_cfg80211_vendor_get_supported_feature_set( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_event_rssi_beyond_range( + struct wiphy *wiphy, + struct wireless_dev *wdev, int rssi); + +int mtk_cfg80211_vendor_set_tx_power_scenario( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_get_preferred_freq_list(struct wiphy + *wiphy, struct wireless_dev *wdev, const void *data, + int data_len); + +int mtk_cfg80211_vendor_acs(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); + +int mtk_cfg80211_vendor_get_features(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); + +int mtk_cfg80211_vendor_driver_memory_dump(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +#endif /* _GL_VENDOR_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_wext.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_wext.h new file mode 100644 index 0000000000000..f11c272d716d4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_wext.h @@ -0,0 +1,390 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + * 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. + */ + + +#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 + ******************************************************************************* + */ +extern void wlanUpdateChannelTable(struct GLUE_INFO + *prGlueInfo); + +#if CFG_SUPPORT_WAPI +extern uint8_t +keyStructBuf[1024]; /* add/remove key shared buffer */ +#else +extern uint8_t +keyStructBuf[100]; /* add/remove key shared buffer */ +#endif + +/* for IE Searching */ +extern u_int8_t +wextSrchDesiredWPAIE(IN uint8_t *pucIEStart, + IN int32_t i4TotalIeLen, IN uint8_t ucDesiredElemId, + OUT uint8_t **ppucDesiredIE); + +#if CFG_SUPPORT_WPS +extern u_int8_t +wextSrchDesiredWPSIE(IN uint8_t *pucIEStart, + IN int32_t i4TotalIeLen, IN uint8_t ucDesiredElemId, + OUT uint8_t **ppucDesiredIE); +#endif + +/******************************************************************************* + * 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 + ******************************************************************************* + */ +struct PARAM_FIXED_IEs { + uint8_t aucTimestamp[8]; + uint16_t u2BeaconInterval; + uint16_t u2Capabilities; +}; + +struct PARAM_VARIABLE_IE { + uint8_t ucElementID; + uint8_t ucLength; + uint8_t aucData[1]; +}; + +#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, + /* used to check the valid filter bits */ + IEEE80211_FILTER_TYPE_ALL = 0xFF +}; + +#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 +#define IW_AUTH_ALG_FT 0x00000008 +#define IW_AUTH_ALG_SAE 0x00000010 + +/******************************************************************************* + * 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 struct GLUE_INFO *prGlueInfo, + IN unsigned int u4Cmd, IN unsigned char *pucData, + IN unsigned int u4DataLen, + IN uint8_t ucBssIndex); + +struct iw_statistics *wext_get_wireless_stats( + struct net_device *prDev); + + +u_int8_t +wextSrchDesiredWPAIE(IN uint8_t *pucIEStart, + IN int32_t i4TotalIeLen, IN uint8_t ucDesiredElemId, + OUT uint8_t **ppucDesiredIE); + +#if CFG_SUPPORT_WPS +u_int8_t +wextSrchDesiredWPSIE(IN uint8_t *pucIEStart, + IN int32_t i4TotalIeLen, IN uint8_t ucDesiredElemId, + OUT uint8_t **ppucDesiredIE); +#endif + +#if CFG_SUPPORT_PASSPOINT +u_int8_t wextSrchDesiredHS20IE(IN uint8_t *pucIEStart, + IN int32_t i4TotalIeLen, + OUT uint8_t **ppucDesiredIE); + +u_int8_t wextSrchDesiredAdvProtocolIE(IN uint8_t + *pucIEStart, IN int32_t i4TotalIeLen, + OUT uint8_t **ppucDesiredIE); + +u_int8_t wextSrchDesiredOsenIE(IN uint8_t *pucIEStart, + IN int32_t i4TotalIeLen, + OUT uint8_t **ppucDesiredIE); +#endif /* CFG_SUPPORT_PASSPOINT */ + +u_int8_t wextSrchDesiredWAPIIE(IN uint8_t *pucIEStart, + IN int32_t i4TotalIeLen, + OUT uint8_t **ppucDesiredIE); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* WIRELESS_EXT */ + +#endif /* _GL_WEXT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_wext_priv.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_wext_priv.h new file mode 100644 index 0000000000000..53b8bb94ee6d9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/include/gl_wext_priv.h @@ -0,0 +1,414 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + * 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. + */ + + +#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 IOCTL_SET_DRIVER (SIOCIWFIRSTPRIV + 14) +#define IOCTL_GET_DRIVER (SIOCIWFIRSTPRIV + 15) + +#if CFG_SUPPORT_QA_TOOL +#define IOCTL_QA_TOOL_DAEMON (SIOCIWFIRSTPRIV + 16) +#define IOCTL_IWPRIV_ATE (SIOCIWFIRSTPRIV + 17) +#endif + +#define IOC_AP_GET_STA_LIST (SIOCIWFIRSTPRIV+19) +#define IOC_AP_SET_MAC_FLTR (SIOCIWFIRSTPRIV+21) +#define IOC_AP_SET_CFG (SIOCIWFIRSTPRIV+23) +#define IOC_AP_STA_DISASSOC (SIOCIWFIRSTPRIV+25) +#define IOC_AP_SET_NSS (SIOCIWFIRSTPRIV+27) + +#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_NO_USED 25 + +#define PRIV_CMD_BAND_CONFIG 26 + +#define PRIV_CMD_DUMP_MEM 27 + +#define PRIV_CMD_P2P_MODE 28 + +#if CFG_SUPPORT_QA_TOOL +#define PRIV_QACMD_SET 29 +#endif + +#define PRIV_CMD_MET_PROFILING 33 + +#if CFG_WOW_SUPPORT +#define PRIV_CMD_SET_WOW_ENABLE 34 +#define PRIV_CMD_SET_WOW_PAR 35 +#endif + +#ifdef UT_TEST_MODE +#define PRIV_CMD_UT 36 +#endif /* UT_TEST_MODE */ + +#define PRIV_CMD_SET_SER 37 + +/* Get FW manifest version */ +#define PRIV_CMD_GET_FW_VERSION 38 + + +/* dynamic tx power control */ +#define PRIV_CMD_SET_PWR_CTRL 40 + +/* wifi type: 11g, 11n, ... */ +#define PRIV_CMD_GET_WIFI_TYPE 41 + +/* set ant swap control */ +#define PRIV_CMD_SET_ANT_SWAP_CTRL 50 + + +/* 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 +#define OID_CUSTOM_TEST_ICAP_MODE 0xFFA0C913 + +/* 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 + +#if CFG_SUPPORT_LOWLATENCY_MODE +#define OID_CUSTOM_LOWLATENCY_MODE 0xFFA0CC00 +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + +#define OID_IPC_WIFI_LOG_UI 0xFFA0CC01 +#define OID_IPC_WIFI_LOG_LEVEL 0xFFA0CC02 + +#if CFG_SUPPORT_ANT_SWAP +#define OID_CUSTOM_QUERY_ANT_SWAP_CAPABILITY 0xFFA0CD00 +#endif + +#if CFG_SUPPORT_NCHO +#define CMD_NCHO_COMP_TIMEOUT 1500 /* ms */ +#define CMD_NCHO_AF_DATA_LENGTH 1040 +#endif + +#ifdef UT_TEST_MODE +#define OID_UT 0xFFA0CD00 +#endif /* UT_TEST_MODE */ + +/* Define magic key of test mode (Don't change it for future compatibity) */ +#define PRIV_CMD_TEST_MAGIC_KEY 2011 +#define PRIV_CMD_TEST_MAGIC_KEY_ICAP 2013 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +/* NIC BBCR configuration entry structure */ +struct PRIV_CONFIG_ENTRY { + uint8_t ucOffset; + uint8_t ucValue; +}; + +typedef uint32_t(*PFN_OID_HANDLER_FUNC_REQ) ( + IN void *prAdapter, + IN OUT void *pvBuf, IN uint32_t u4BufLen, + OUT uint32_t *pu4OutInfoLen); + +enum ENUM_OID_METHOD { + ENUM_OID_GLUE_ONLY, + ENUM_OID_GLUE_EXTENSION, + ENUM_OID_DRIVER_CORE +}; + +/* OID set/query processing entry */ +struct WLAN_REQ_ENTRY { + uint32_t rOid; /* OID */ + uint8_t *pucOidName; /* OID name text */ + u_int8_t fgQryBufLenChecking; + u_int8_t fgSetBufLenChecking; + enum ENUM_OID_METHOD eOidMethod; + uint32_t u4InfoBufLen; + PFN_OID_HANDLER_FUNC_REQ pfOidQueryHandler; /* PFN_OID_HANDLER_FUNC */ + PFN_OID_HANDLER_FUNC_REQ pfOidSetHandler; /* PFN_OID_HANDLER_FUNC */ +}; + +struct NDIS_TRANSPORT_STRUCT { + uint32_t ndisOidCmd; + uint32_t inNdisOidlength; + uint32_t outNdisOidLength; + uint8_t ndisOidContent[16]; +}; + +enum AGG_RANGE_TYPE_T { + ENUM_AGG_RANGE_TYPE_TX = 0, + ENUM_AGG_RANGE_TYPE_TRX = 1, + ENUM_AGG_RANGE_TYPE_RX = 2 +}; + +/******************************************************************************* + * P U B 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_set_driver(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN OUT char *pcExtra); + +int +priv_set_ap(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); + +int priv_support_driver_cmd(IN struct net_device *prDev, + IN OUT struct ifreq *prReq, IN int i4Cmd); + +#ifdef CFG_ANDROID_AOSP_PRIV_CMD +int android_private_support_driver_cmd(IN struct net_device *prDev, +IN OUT struct ifreq *prReq, IN int i4Cmd); +#endif /* CFG_ANDROID_AOSP_PRIV_CMD */ + +int32_t priv_driver_cmds(IN struct net_device *prNetDev, + IN int8_t *pcCommand, IN int32_t i4TotalLen); + +int priv_driver_set_cfg(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen); + +#if CFG_SUPPORT_QA_TOOL +int +priv_ate_set(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN char *pcExtra); +#endif + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _GL_WEXT_PRIV_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/plat/mt6885/plat_priv.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/plat/mt6885/plat_priv.c new file mode 100644 index 0000000000000..82d880db7926c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/plat/mt6885/plat_priv.c @@ -0,0 +1,178 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#include +#include + +#include +#include + +#include "precomp.h" + +#ifdef CFG_MTK_ANDROID_EMI +#include +#include +#define REGION_WIFI 26 +#define WIFI_EMI_MEM_SIZE 0x140000 +#define WIFI_EMI_MEM_OFFSET 0x2B0000 +#define DOMAIN_AP 0 +#define DOMAIN_CONN 2 +#endif + + +#define MAX_CPU_FREQ (3 * 1024 * 1024) /* in kHZ */ +#define MAX_CLUSTER_NUM 3 +#define CPU_BIG_CORE (0xf0) +#define CPU_SMALL_CORE (0xff - CPU_BIG_CORE) + +#define CONNSYS_VERSION_ID 0x20010000 + +enum ENUM_CPU_BOOST_STATUS { + ENUM_CPU_BOOST_STATUS_INIT = 0, + ENUM_CPU_BOOST_STATUS_START, + ENUM_CPU_BOOST_STATUS_STOP, + ENUM_CPU_BOOST_STATUS_NUM +}; + +uint32_t kalGetCpuBoostThreshold(void) +{ + DBGLOG(SW4, TRACE, "enter kalGetCpuBoostThreshold\n"); + /* 5, stands for 250Mbps */ + return 5; +} + +int32_t kalCheckTputLoad(IN struct ADAPTER *prAdapter, + IN uint32_t u4CurrPerfLevel, + IN uint32_t u4TarPerfLevel, + IN int32_t i4Pending, + IN uint32_t u4Used) +{ + uint32_t pendingTh = + CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD * + prAdapter->rWifiVar.u4PerfMonPendingTh / 100; + uint32_t usedTh = (HIF_TX_MSDU_TOKEN_NUM / 2) * + prAdapter->rWifiVar.u4PerfMonUsedTh / 100; + return u4TarPerfLevel >= 3 && + u4TarPerfLevel < prAdapter->rWifiVar.u4BoostCpuTh && + i4Pending >= pendingTh && + u4Used >= usedTh ? + TRUE : FALSE; +} + +int32_t kalBoostCpu(IN struct ADAPTER *prAdapter, + IN uint32_t u4TarPerfLevel, + IN uint32_t u4BoostCpuTh) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ppm_limit_data freq_to_set[MAX_CLUSTER_NUM]; + int32_t i = 0, i4Freq = -1; + + static struct pm_qos_request wifi_qos_request; + static u_int8_t fgRequested = ENUM_CPU_BOOST_STATUS_INIT; + + uint32_t u4ClusterNum = topo_ctrl_get_nr_clusters(); + + prGlueInfo = (struct GLUE_INFO *)wiphy_priv(wlanGetWiphy()); + ASSERT(u4ClusterNum <= MAX_CLUSTER_NUM); + /* ACAO, we dont have to set core number */ + i4Freq = (u4TarPerfLevel >= u4BoostCpuTh) ? MAX_CPU_FREQ : -1; + for (i = 0; i < u4ClusterNum; i++) { + freq_to_set[i].min = i4Freq; + freq_to_set[i].max = i4Freq; + } + + if (fgRequested == ENUM_CPU_BOOST_STATUS_INIT) { + /* initially enable rps working at small cores */ + kalSetRpsMap(prGlueInfo, CPU_SMALL_CORE); + fgRequested = ENUM_CPU_BOOST_STATUS_STOP; + } + + if (u4TarPerfLevel >= u4BoostCpuTh) { + if (fgRequested == ENUM_CPU_BOOST_STATUS_STOP) { + pr_info("kalBoostCpu start (%d>=%d)\n", + u4TarPerfLevel, u4BoostCpuTh); + fgRequested = ENUM_CPU_BOOST_STATUS_START; + + set_task_util_min_pct(prGlueInfo->u4TxThreadPid, 100); + set_task_util_min_pct(prGlueInfo->u4RxThreadPid, 100); + set_task_util_min_pct(prGlueInfo->u4HifThreadPid, 100); + kalSetRpsMap(prGlueInfo, CPU_BIG_CORE); + update_userlimit_cpu_freq(CPU_KIR_WIFI, + u4ClusterNum, freq_to_set); + + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_BOOST_CPU); + pr_info("Max Dram Freq start\n"); + pm_qos_add_request(&wifi_qos_request, + PM_QOS_DDR_OPP, + DDR_OPP_0); + pm_qos_update_request(&wifi_qos_request, DDR_OPP_0); + KAL_RELEASE_MUTEX(prAdapter, MUTEX_BOOST_CPU); + } + } else { + if (fgRequested == ENUM_CPU_BOOST_STATUS_START) { + pr_info("kalBoostCpu stop (%d<%d)\n", + u4TarPerfLevel, u4BoostCpuTh); + fgRequested = ENUM_CPU_BOOST_STATUS_STOP; + + set_task_util_min_pct(prGlueInfo->u4TxThreadPid, 0); + set_task_util_min_pct(prGlueInfo->u4RxThreadPid, 0); + set_task_util_min_pct(prGlueInfo->u4HifThreadPid, 0); + kalSetRpsMap(prGlueInfo, CPU_SMALL_CORE); + update_userlimit_cpu_freq(CPU_KIR_WIFI, + u4ClusterNum, freq_to_set); + + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_BOOST_CPU); + pr_info("Max Dram Freq end\n"); + pm_qos_update_request(&wifi_qos_request, DDR_OPP_UNREQ); + pm_qos_remove_request(&wifi_qos_request); + KAL_RELEASE_MUTEX(prAdapter, MUTEX_BOOST_CPU); + } + } + kalTraceInt(fgRequested == ENUM_CPU_BOOST_STATUS_START, "kalBoostCpu"); + + return 0; +} + +#ifdef CFG_MTK_ANDROID_EMI +void kalSetEmiMpuProtection(phys_addr_t emiPhyBase, bool enable) +{ +} + +void kalSetDrvEmiMpuProtection(phys_addr_t emiPhyBase, uint32_t offset, + uint32_t size) +{ + struct emimpu_region_t region; + unsigned long long start = emiPhyBase + offset; + unsigned long long end = emiPhyBase + offset + size - 1; + int ret; + + DBGLOG(INIT, INFO, "emiPhyBase: 0x%p, offset: %d, size: %d\n", + emiPhyBase, offset, size); + + ret = mtk_emimpu_init_region(®ion, 18); + if (ret) { + DBGLOG(INIT, ERROR, "mtk_emimpu_init_region failed, ret: %d\n", + ret); + return; + } + mtk_emimpu_set_addr(®ion, start, end); + mtk_emimpu_set_apc(®ion, DOMAIN_AP, MTK_EMIMPU_NO_PROTECTION); + mtk_emimpu_set_apc(®ion, DOMAIN_CONN, MTK_EMIMPU_NO_PROTECTION); + mtk_emimpu_lock_region(®ion, MTK_EMIMPU_LOCK); + ret = mtk_emimpu_set_protection(®ion); + if (ret) + DBGLOG(INIT, ERROR, + "mtk_emimpu_set_protection failed, ret: %d\n", + ret); + mtk_emimpu_free_region(®ion); +} + +#endif + +int32_t kalGetConnsysVerId(void) +{ + return CONNSYS_VERSION_ID; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/plat/mt6893/plat_priv.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/plat/mt6893/plat_priv.c new file mode 100644 index 0000000000000..373a4ec5a7982 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/plat/mt6893/plat_priv.c @@ -0,0 +1,183 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#include +#include + +#include +#include + +#include "precomp.h" + +#ifdef CFG_MTK_ANDROID_EMI +#include +#define REGION_WIFI 26 +#define WIFI_EMI_MEM_SIZE 0x140000 +#define WIFI_EMI_MEM_OFFSET 0x2B0000 +#define DOMAIN_AP 0 +#define DOMAIN_CONN 2 +#endif + + +#define MAX_CPU_FREQ (3 * 1024 * 1024) /* in kHZ */ +#define MAX_CLUSTER_NUM 3 +#define CPU_BIG_CORE (0xf0) +#define CPU_SMALL_CORE (0xff - CPU_BIG_CORE) + +#define CONNSYS_VERSION_ID 0x20010101 + +enum ENUM_CPU_BOOST_STATUS { + ENUM_CPU_BOOST_STATUS_INIT = 0, + ENUM_CPU_BOOST_STATUS_START, + ENUM_CPU_BOOST_STATUS_STOP, + ENUM_CPU_BOOST_STATUS_NUM +}; + +uint32_t kalGetCpuBoostThreshold(void) +{ + DBGLOG(SW4, TRACE, "enter kalGetCpuBoostThreshold\n"); + /* 5, stands for 250Mbps */ + return 5; +} + +int32_t kalCheckTputLoad(IN struct ADAPTER *prAdapter, + IN uint32_t u4CurrPerfLevel, + IN uint32_t u4TarPerfLevel, + IN int32_t i4Pending, + IN uint32_t u4Used) +{ + uint32_t pendingTh = + CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD * + prAdapter->rWifiVar.u4PerfMonPendingTh / 100; + uint32_t usedTh = (HIF_TX_MSDU_TOKEN_NUM / 2) * + prAdapter->rWifiVar.u4PerfMonUsedTh / 100; + return u4TarPerfLevel >= 3 && + u4TarPerfLevel < prAdapter->rWifiVar.u4BoostCpuTh && + i4Pending >= pendingTh && + u4Used >= usedTh ? + TRUE : FALSE; +} + +int32_t kalBoostCpu(IN struct ADAPTER *prAdapter, + IN uint32_t u4TarPerfLevel, + IN uint32_t u4BoostCpuTh) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ppm_limit_data freq_to_set[MAX_CLUSTER_NUM]; + int32_t i = 0, i4Freq = -1; + + static struct pm_qos_request wifi_qos_request; + static u_int8_t fgRequested = ENUM_CPU_BOOST_STATUS_INIT; + + uint32_t u4ClusterNum = topo_ctrl_get_nr_clusters(); + + prGlueInfo = (struct GLUE_INFO *)wiphy_priv(wlanGetWiphy()); + ASSERT(u4ClusterNum <= MAX_CLUSTER_NUM); + /* ACAO, we dont have to set core number */ + i4Freq = (u4TarPerfLevel >= u4BoostCpuTh) ? MAX_CPU_FREQ : -1; + for (i = 0; i < u4ClusterNum; i++) { + freq_to_set[i].min = i4Freq; + freq_to_set[i].max = i4Freq; + } + + if (fgRequested == ENUM_CPU_BOOST_STATUS_INIT) { + /* initially enable rps working at small cores */ + kalSetRpsMap(prGlueInfo, CPU_SMALL_CORE); + fgRequested = ENUM_CPU_BOOST_STATUS_STOP; + } + + if (u4TarPerfLevel >= u4BoostCpuTh) { + if (fgRequested == ENUM_CPU_BOOST_STATUS_STOP) { + pr_info("kalBoostCpu start (%d>=%d)\n", + u4TarPerfLevel, u4BoostCpuTh); + fgRequested = ENUM_CPU_BOOST_STATUS_START; + + set_task_util_min_pct(prGlueInfo->u4TxThreadPid, 100); + set_task_util_min_pct(prGlueInfo->u4RxThreadPid, 100); + set_task_util_min_pct(prGlueInfo->u4HifThreadPid, 100); + kalSetRpsMap(prGlueInfo, CPU_BIG_CORE); + update_userlimit_cpu_freq(CPU_KIR_WIFI, + u4ClusterNum, freq_to_set); + + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_BOOST_CPU); + pr_info("Max Dram Freq start\n"); + pm_qos_add_request(&wifi_qos_request, + PM_QOS_DDR_OPP, + DDR_OPP_2); + pm_qos_update_request(&wifi_qos_request, DDR_OPP_2); + KAL_RELEASE_MUTEX(prAdapter, MUTEX_BOOST_CPU); + } + } else { + if (fgRequested == ENUM_CPU_BOOST_STATUS_START) { + pr_info("kalBoostCpu stop (%d<%d)\n", + u4TarPerfLevel, u4BoostCpuTh); + fgRequested = ENUM_CPU_BOOST_STATUS_STOP; + + set_task_util_min_pct(prGlueInfo->u4TxThreadPid, 0); + set_task_util_min_pct(prGlueInfo->u4RxThreadPid, 0); + set_task_util_min_pct(prGlueInfo->u4HifThreadPid, 0); + kalSetRpsMap(prGlueInfo, CPU_SMALL_CORE); + update_userlimit_cpu_freq(CPU_KIR_WIFI, + u4ClusterNum, freq_to_set); + + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_BOOST_CPU); + pr_info("Max Dram Freq end\n"); + pm_qos_update_request(&wifi_qos_request, DDR_OPP_UNREQ); + pm_qos_remove_request(&wifi_qos_request); + KAL_RELEASE_MUTEX(prAdapter, MUTEX_BOOST_CPU); + } + } + kalTraceInt(fgRequested == ENUM_CPU_BOOST_STATUS_START, "kalBoostCpu"); + + return 0; +} + +#ifdef CFG_MTK_ANDROID_EMI +void kalSetEmiMpuProtection(phys_addr_t emiPhyBase, bool enable) +{ +} + +void kalSetDrvEmiMpuProtection(phys_addr_t emiPhyBase, uint32_t offset, + uint32_t size) +{ + struct emimpu_region_t region; + unsigned long long start = emiPhyBase + offset; + unsigned long long end = emiPhyBase + offset + size - 1; + int ret; + + DBGLOG(INIT, INFO, "emiPhyBase: 0x%p, offset: %d, size: %d\n", + emiPhyBase, offset, size); + + ret = mtk_emimpu_init_region(®ion, 18); + if (ret) { + DBGLOG(INIT, ERROR, "mtk_emimpu_init_region failed, ret: %d\n", + ret); + return; + } + mtk_emimpu_set_addr(®ion, start, end); + mtk_emimpu_set_apc(®ion, DOMAIN_AP, MTK_EMIMPU_NO_PROTECTION); + mtk_emimpu_set_apc(®ion, DOMAIN_CONN, MTK_EMIMPU_NO_PROTECTION); + mtk_emimpu_lock_region(®ion, MTK_EMIMPU_LOCK); + ret = mtk_emimpu_set_protection(®ion); + if (ret) + DBGLOG(INIT, ERROR, + "mtk_emimpu_set_protection failed, ret: %d\n", + ret); + mtk_emimpu_free_region(®ion); +} + +#endif + +int32_t kalGetFwFlavor(uint8_t *flavor) +{ + *flavor = 'a'; + return 1; +} + +int32_t kalGetConnsysVerId(void) +{ + return CONNSYS_VERSION_ID; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/platform.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/platform.c new file mode 100644 index 0000000000000..76396a347ffb1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/linux/platform.c @@ -0,0 +1,679 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux + * /platform.c#3 + */ + +/*! \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 + * + */ + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include +#include +#include +#include +#include + +#include +#include "precomp.h" +#include "gl_os.h" + +#if CFG_ENABLE_EARLY_SUSPEND +#include +#endif + +/******************************************************************************* + * 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 + ******************************************************************************* + */ +static const uint8_t *apucDebugNetdevState[] = { + (uint8_t *) DISP_STRING("NETDEV_UNKNOWN"), + (uint8_t *) DISP_STRING("NETDEV_UP"), + (uint8_t *) DISP_STRING("NETDEV_DOWN"), + (uint8_t *) DISP_STRING("NETDEV_REBOOT"), + (uint8_t *) DISP_STRING("NETDEV_CHANGE"), + (uint8_t *) DISP_STRING("NETDEV_REGISTER"), + (uint8_t *) DISP_STRING("NETDEV_UNREGISTER"), + (uint8_t *) DISP_STRING("NETDEV_CHANGEMTU"), + (uint8_t *) DISP_STRING("NETDEV_CHANGEADDR"), + (uint8_t *) DISP_STRING("NETDEV_GOING_DOWN"), + (uint8_t *) DISP_STRING("NETDEV_CHANGENAME"), + (uint8_t *) DISP_STRING("NETDEV_FEAT_CHANGE"), + (uint8_t *) DISP_STRING("NETDEV_BONDING_FAILOVER"), + (uint8_t *) DISP_STRING("NETDEV_PRE_UP"), + (uint8_t *) DISP_STRING("NETDEV_PRE_TYPE_CHANGE"), + (uint8_t *) DISP_STRING("NETDEV_POST_TYPE_CHANGE"), + (uint8_t *) DISP_STRING("NETDEV_POST_INIT"), + (uint8_t *) DISP_STRING("NETDEV_UNREGISTER_FINAL"), + (uint8_t *) DISP_STRING("NETDEV_RELEASE"), + (uint8_t *) DISP_STRING("NETDEV_NOTIFY_PEERS"), + (uint8_t *) DISP_STRING("NETDEV_JOIN"), + (uint8_t *) DISP_STRING("NETDEV_CHANGEUPPER"), + (uint8_t *) DISP_STRING("NETDEV_RESEND_IGMP"), + (uint8_t *) DISP_STRING("NETDEV_PRECHANGEMTU"), + (uint8_t *) DISP_STRING("NETDEV_CHANGEINFODATA"), + (uint8_t *) DISP_STRING("NETDEV_BONDING_INFO"), + (uint8_t *) DISP_STRING("NETDEV_PRECHANGEUPPER"), + (uint8_t *) DISP_STRING("NETDEV_CHANGELOWERSTATE"), + (uint8_t *) DISP_STRING("NETDEV_UDP_TUNNEL_PUSH_INFO"), + (uint8_t *) DISP_STRING("NETDEV_UNKNOWN"), + (uint8_t *) DISP_STRING("NETDEV_CHANGE_TX_QUEUE_LEN"), +}; + +/******************************************************************************* + * M A 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 int wlan_netdev_notifier_call(struct notifier_block *nb, + unsigned long state, void *ndev); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#if 1 +static int netdev_event(struct notifier_block *nb, + unsigned long notification, void *ptr) +{ + struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; + struct net_device *prDev = ifa->ifa_dev->dev; + struct GLUE_INFO *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; + } +#if 0 /* CFG_SUPPORT_PASSPOINT */ + { + /* printk(KERN_INFO + * "[netdev_event] IPV4_DAD is unlock now!!\n"); + */ + prGlueInfo->fgIsDad = FALSE; + } +#endif /* CFG_SUPPORT_PASSPOINT */ + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + if (prGlueInfo == NULL) { + DBGLOG(REQ, INFO, "netdev_event: prGlueInfo is empty.\n"); + return NOTIFY_DONE; + } + + if (prGlueInfo->fgIsInSuspendMode == FALSE) { + /* DBGLOG(REQ, INFO, + * ("netdev_event: MEDIA_STATE_DISCONNECTED. (%d)\n", + * prGlueInfo->eParamMediaStateIndicated)); + */ + return NOTIFY_DONE; + } + + kalSetNetAddressFromInterface(prGlueInfo, prDev, TRUE); + + return NOTIFY_DONE; + +} +#endif +#if 0 /* CFG_SUPPORT_PASSPOINT */ +static int net6dev_event(struct notifier_block *nb, + unsigned long notification, void *ptr) +{ + struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr; + struct net_device *prDev = ifa->idev->dev; + struct GLUE_INFO *prGlueInfo = NULL; + + if (prDev == NULL) { + DBGLOG(REQ, INFO, "net6dev_event: device is empty.\n"); + return NOTIFY_DONE; + } + + if ((strncmp(prDev->name, "p2p", 3) != 0) + && (strncmp(prDev->name, "wlan", 4) != 0)) { + DBGLOG(REQ, INFO, "net6dev_event: xxx\n"); + return NOTIFY_DONE; + } + + if (strncmp(prDev->name, "p2p", 3) == 0) { + /* because we store the address of prGlueInfo in p2p's private + * date of net device + */ + /* *((P_GLUE_INFO_T *) netdev_priv( + * prGlueInfo->prP2PInfo[0]->prDevHandler)) = prGlueInfo; + */ + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + } else { /* wlan0 */ + prGlueInfo = (struct GLUE_INFO *) netdev_priv(prDev); + } + + if (prGlueInfo == NULL) { + DBGLOG(REQ, INFO, "netdev_event: prGlueInfo is empty.\n"); + return NOTIFY_DONE; + } + /* printk(KERN_INFO "[net6dev_event] IPV6_DAD is unlock now!!\n"); */ + prGlueInfo->fgIs6Dad = FALSE; + + return NOTIFY_DONE; +} +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if 1 /* unused */ +static struct notifier_block inetaddr_notifier = { + .notifier_call = netdev_event, +}; +#endif + +#if 0 /* CFG_SUPPORT_PASSPOINT */ +static struct notifier_block inet6addr_notifier = { + .notifier_call = net6dev_event, +}; +#endif /* CFG_SUPPORT_PASSPOINT */ + +void wlanRegisterInetAddrNotifier(void) +{ +#if CFG_ENABLE_NET_DEV_NOTIFY + + register_inetaddr_notifier(&inetaddr_notifier); +#if 0 /* CFG_SUPPORT_PASSPOINT */ + register_inet6addr_notifier(&inet6addr_notifier); +#endif /* CFG_SUPPORT_PASSPOINT */ + +#endif +} + +void wlanUnregisterInetAddrNotifier(void) +{ +#if CFG_ENABLE_NET_DEV_NOTIFY + + unregister_inetaddr_notifier(&inetaddr_notifier); +#if 0 /* CFG_SUPPORT_PASSPOINT */ + unregister_inetaddr_notifier(&inet6addr_notifier); +#endif /* CFG_SUPPORT_PASSPOINT */ + +#endif +} + +#if CFG_ENABLE_EARLY_SUSPEND +/*----------------------------------------------------------------------------*/ +/*! + * \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 (wlanSuspend != NULL) + prDesc->suspend = wlanSuspend; + else { + DBGLOG(REQ, INFO, + "glRegisterEarlySuspend wlanSuspend ERROR.\n"); + ret = -1; + } + + if (wlanResume != NULL) + prDesc->resume = wlanResume; + else { + DBGLOG(REQ, INFO, + "glRegisterEarlySuspend wlanResume ERROR.\n"); + ret = -1; + } + + register_early_suspend(prDesc); + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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; +} +#endif + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! + * \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; +#if KERNEL_VERSION(4, 4, 0) <= LINUX_VERSION_CODE + loff_t pos; + char __user *p; +#endif + + 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, "[nvram_read] : failed to open!!\n"); + set_fs(old_fs); + return -1; + } + + do { + if (fd->f_op == NULL) { + DBGLOG(INIT, INFO, "[nvram_read] : f_op is NULL!!\n"); + break; + } + + if (fd->f_pos != offset) { + if (fd->f_op->llseek) { + if (fd->f_op->llseek(fd, offset, 0) != offset) { + DBGLOG(INIT, INFO, + "[nvram_read] : failed to seek!!\n"); + break; + } + } else { + fd->f_pos = offset; + } + } + +#if KERNEL_VERSION(4, 4, 0) <= LINUX_VERSION_CODE + p = (__force char __user *)buf; + pos = (loff_t)offset; + + retLen = __vfs_read(fd, p, len, &pos); +#else + retLen = fd->f_op->read(fd, buf, len, &fd->f_pos); +#endif + if (retLen < 0) + DBGLOG(INIT, ERROR, + "[nvram_read] : read failed!! Error code: %d\n", + retLen); + } 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; +#if KERNEL_VERSION(4, 4, 0) <= LINUX_VERSION_CODE + loff_t pos; + char __user *p; +#endif + + 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, "[nvram_write] : failed to open!!\n"); + set_fs(old_fs); + return -1; + } + + do { + if (fd->f_op == NULL) { + DBGLOG(INIT, INFO, "[nvram_write] : f_op is NULL!!\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, + "[nvram_write] : failed to seek!!\n"); + break; + } + } else { + fd->f_pos = offset; + } + } + +#if KERNEL_VERSION(4, 4, 0) <= LINUX_VERSION_CODE + p = (__force char __user *)buf; + pos = (loff_t)offset; + + retLen = __vfs_write(fd, p, len, &pos); +#else + retLen = fd->f_op->write(fd, buf, len, &fd->f_pos); +#endif + if (retLen < 0) + DBGLOG(INIT, ERROR, + "[nvram_write] : write failed!! Error code: %d\n", + retLen); + } while (FALSE); + + filp_close(fd, NULL); + + set_fs(old_fs); + + return retLen; + +#else /* !CFG_SUPPORT_NVRAMS */ + + return -EIO; + +#endif +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief API for reading data on NVRAM with flexible length. + * + * \param[in] + * prGlueInfo + * u4Offset + * len + * \param[out] + * pu2Data + * \return + * TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalCfgDataRead(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Offset, + IN ssize_t len, OUT uint16_t *pu2Data) +{ + if (pu2Data == NULL) + return FALSE; + + if (u4Offset + len > MAX_CFG_FILE_WIFI_REC_SIZE) + return FALSE; + + kalMemCopy(pu2Data, &g_aucNvram[u4Offset], len); + return TRUE; +#if 0 + if (nvram_read(WIFI_NVRAM_FILE_NAME, + (char *)pu2Data, len, u4Offset) != len) { + return FALSE; + } else { + return TRUE; + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief API for reading data on NVRAM with 2 bytes fixed length. + * + * \param[in] + * prGlueInfo + * u4Offset + * \param[out] + * pu2Data + * \return + * TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalCfgDataRead16(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Offset, OUT uint16_t *pu2Data) +{ + if (pu2Data == NULL) + return FALSE; + + if (u4Offset + sizeof(unsigned short) > MAX_CFG_FILE_WIFI_REC_SIZE) + return FALSE; + + kalMemCopy(pu2Data, &g_aucNvram[u4Offset], + sizeof(unsigned short)); + return TRUE; +#if 0 + if (nvram_read(WIFI_NVRAM_FILE_NAME, + (char *)pu2Data, sizeof(unsigned short), + u4Offset) != sizeof(unsigned short)) { + return FALSE; + } else { + return TRUE; + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief API for writing data on NVRAM with 2 bytes fixed length. + * + * \param[in] + * prGlueInfo + * u4Offset + * u2Data + * \return + * TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalCfgDataWrite16(IN struct GLUE_INFO *prGlueInfo, + uint32_t u4Offset, uint16_t u2Data) +{ + if (u4Offset + sizeof(unsigned short) > MAX_CFG_FILE_WIFI_REC_SIZE) + return FALSE; + + kalMemCopy(&g_aucNvram[u4Offset], &u2Data, + sizeof(unsigned short)); + return TRUE; +#if 0 + if (nvram_write(WIFI_NVRAM_FILE_NAME, + (char *)&u2Data, sizeof(unsigned short), + u4Offset) != sizeof(unsigned short)) { + return FALSE; + } else { + return TRUE; + } +#endif +} +/*----------------------------------------------------------------------------*/ +/*! + * \brief API for writing data on NVRAM with 1 bytes fixed length. + * + * \param[in] + * prGlueInfo + * u4Offset + * u1Data + * \return + * TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ + +u_int8_t kalCfgDataWrite8(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Offset, IN uint8_t u1Data) +{ + if (u4Offset + sizeof(unsigned char) > MAX_CFG_FILE_WIFI_REC_SIZE) + return FALSE; + + kalMemCopy(&g_aucNvram[u4Offset], &u1Data, + sizeof(unsigned char)); + return TRUE; + +} + +static int wlan_netdev_notifier_call(struct notifier_block *nb, + unsigned long state, void *ndev) +{ +#if KERNEL_VERSION(3, 11, 0) <= CFG80211_VERSION_CODE + struct netdev_notifier_info *dev_notif_info = ndev; + struct net_device *dev = dev_notif_info != NULL ? + dev_notif_info->dev : NULL; +#else + struct net_device *dev = ndev; +#endif + + if (!dev) + return NOTIFY_DONE; + + if ((strncmp(dev->name, "wlan", 4) != 0) && + (strncmp(dev->name, "p2p", 3) != 0) && + (strncmp(dev->name, "ap", 2) != 0)) { + return NOTIFY_DONE; + } + + DBGLOG(REQ, TRACE, "%s's new state: %lu %s.\n", + dev->name, state, apucDebugNetdevState[state]); + + return NOTIFY_DONE; +} + +static struct notifier_block wlan_netdev_notifier = { + .notifier_call = wlan_netdev_notifier_call, +}; + +void wlanRegisterNetdevNotifier(void) +{ + register_netdevice_notifier(&wlan_netdev_notifier); +} + +void wlanUnregisterNetdevNotifier(void) +{ + unregister_netdevice_notifier(&wlan_netdev_notifier); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/gl_ate_agent.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/gl_ate_agent.c new file mode 100644 index 0000000000000..1457db39482f0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/gl_ate_agent.c @@ -0,0 +1,118 @@ +/**************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ***************************************************************************/ +/**************************************************************************** + *[File] gl_ate_agent.c + *[Version] v1.0 + *[Revision Date] 2019/01/01 + *[Author] + *[Description] + * DUT API implementation for test tool + *[Copyright] + * Copyright (C) 2010 MediaTek Incorporation. All Rights Reserved. + ****************************************************************************/ + + +/***************************************************************************** + * C O M P I L E 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 "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 + ***************************************************************************** + */ +/* export to other common part file */ +#if CFG_SUPPORT_TX_BF +union PFMU_PROFILE_TAG1 g_rPfmuTag1; +union PFMU_PROFILE_TAG2 g_rPfmuTag2; +union PFMU_DATA g_rPfmuData; +#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 + ***************************************************************************** + */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/gl_dependent.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/gl_dependent.c new file mode 100644 index 0000000000000..d2e73892d7322 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/gl_dependent.c @@ -0,0 +1,369 @@ +/**************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ***************************************************************************/ +/**************************************************************************** + *[File] gl_dependency.c + *[Version] v1.0 + *[Revision Date] 2019/01/01 + *[Author] + *[Description] + * The implementation for os-related API provided to common part. + * mainly Linux related code block in common part + *[Copyright] + * Copyright (C) 2010 MediaTek Incorporation. All Rights Reserved. + ****************************************************************************/ + + +/***************************************************************************** + * C O M P I L E 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 "precomp.h" + +#include "stdio.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 + ***************************************************************************** + */ +long KAL_NEED_IMPLEMENT(const char *f, const char *func, int line, ...) +{ + /* please refer to the implementation on other os. eg. Linux */ + DBGLOG(INIT, ERROR, "%s not supported here, %s@%d\n", + func, f, line); + return 0; +} + +int test(struct net_device *a) +{ + return 0; +} +/* + * for GCC to build under user space, please remove/keep it + * dependent to the OS + */ +int main(int argc, char *argv[]) +{ + wlanSetDriverDbgLevel(DBG_ALL_MODULE_IDX, + DBG_LOG_LEVEL_DEFAULT); + DBGLOG(INIT, ERROR, "test run\n"); + return 0; +} +#if 0 +int kal_dbg_print(const char *s, ...) +{ + printf((s), ...); + return 0; +} +#endif +int kal_hex_dump_to_buffer(const void *buf, size_t len, int rowsize, + int groupsize, char *linebuf, size_t linebuflen, bool ascii) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); + return 0; +} + +void kal_warn_on(uint8_t condition) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +void kal_do_gettimeofday(struct timeval *tv) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +void kal_get_monotonic_boottime(struct timespec *ts) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +int kal_mod_timer(struct timer_list *timer, unsigned long expires) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); + return 0; +} + +int kal_strtoint(const char *s, unsigned int base, int *res) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); + return 0; +} + +int kal_strtou8(const char *s, unsigned int base, uint8_t *res) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); + return 0; +} + +int kal_strtou16(const char *s, unsigned int base, uint16_t *res) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); + return 0; +} + +int kal_strtou32(const char *s, unsigned int base, uint32_t *res) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); + return 0; +} + +int kal_strtos32(const char *s, unsigned int base, int32_t *res) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); + return 0; +} + +int kal_strtoul(const char *s, unsigned int base, unsigned long *res) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); + return 0; +} + +int kal_scnprintf(char *buf, size_t size, const char *fmt, ...) +{ + va_list args; + int i = 0; + + va_start(args, fmt); + /* i = vscnprintf(buf, size, fmt, args); */ + va_end(args); + + return i; +} + +void *kal_kmalloc(size_t size, enum gfp_t type) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); + return NULL; +} + +void *kal_vmalloc(size_t size) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); + return NULL; +} + +void kal_kfree(void *addr) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +void kal_vfree(void *addr) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +void kal_spin_lock_bh(spinlock_t *lock) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +void kal_spin_unlock_bh(spinlock_t *lock) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +void kal_spin_lock_irqsave(spinlock_t *lock, unsigned long flags) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +void kal_spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +uint32_t kal_skb_queue_len(const struct sk_buff_head *list) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); + return list->qlen; +} + +void kal_skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +void *kal_skb_push(struct sk_buff *skb, unsigned int len) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); + return NULL; +} + +unsigned char *kal_skb_put(struct sk_buff *skb, unsigned int len) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); + return NULL; +} + +struct sk_buff *kal_skb_dequeue_tail(struct sk_buff_head *list) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); + return NULL; +} + +void kal_skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +void kal_skb_reset_tail_pointer(struct sk_buff *skb) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +void kal_skb_trim(struct sk_buff *skb, unsigned int len) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +struct sk_buff *kal_dev_alloc_skb(unsigned int length) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); + return NULL; +} + +void kal_kfree_skb(struct sk_buff *skb) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +int kal_test_and_clear_bit(unsigned long bit, unsigned long *p) +{ + unsigned int res; + unsigned long mask = 1UL << (bit & 31); + + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); + p += bit >> 5; + /* TODO: disable interrupt */ + res = *p; + *p = res & ~mask; + /* TODO: restore interrupt */ + + return (res & mask) != 0; +} + +void kal_clear_bit(unsigned long bit, unsigned long *p) +{ + unsigned long mask = 1UL << (bit & 31); + + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); + p += bit >> 5; + /* TODO: disable interrupt */ + *p &= ~mask; + /* TOD: restore interrupt */ +} + +void kal_set_bit(unsigned long nr, unsigned long *addr) +{ + unsigned long mask = BIT(nr % 32); + unsigned long *p = ((unsigned long *)addr) + (nr / 32); + + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); + /* TODO: disable interrupt */ + *p |= mask; + /* TODO: restore interrupt */ +} + +int kal_test_bit(unsigned long nr, unsigned long *addr) +{ + unsigned long mask = BIT(nr % 32); + unsigned long *p = ((unsigned long *)addr) + (nr / 32); + int res = 0; + + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); + /* TODO: disable interrupt */ + + res = mask & *p; + /* TODO: restore interrupt */ + + return res; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/gl_init.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/gl_init.c new file mode 100644 index 0000000000000..e5fe37d6b652e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/gl_init.c @@ -0,0 +1,125 @@ +/**************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ***************************************************************************/ +/**************************************************************************** + *[File] gl_init.c + *[Version] v1.0 + *[Revision Date] 2019/01/01 + *[Author] + *[Description] + * DUT initialization API implementation for os related logic. + *[Copyright] + * Copyright (C) 2010 MediaTek Incorporation. All Rights Reserved. + ****************************************************************************/ + + +/***************************************************************************** + * C O M P I L E R F L A G S + ***************************************************************************** + */ + +/***************************************************************************** + * E X T E R N A L R E F E R E N C E S + ***************************************************************************** + */ + +#include "precomp.h" + +#include "gl_os.h" + +/***************************************************************************** + * C O N S T A N T S + ***************************************************************************** + */ + +struct wireless_dev *gprWdev[KAL_AIS_NUM]; + +/***************************************************************************** + * 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 + ***************************************************************************** + */ +uint32_t wlanDownloadBufferBin(struct ADAPTER *prAdapter) +{ + return KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + + +uint32_t wlanConnacDownloadBufferBin(struct ADAPTER *prAdapter) +{ + return KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/gl_kal.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/gl_kal.c new file mode 100644 index 0000000000000..c0242b679c25a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/gl_kal.c @@ -0,0 +1,130 @@ +/**************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ***************************************************************************/ +/**************************************************************************** + *[File] gl_kal.c + *[Version] v1.0 + *[Revision Date] 2019/01/01 + *[Author] + *[Description] + * API implementation for os related logic. eg. threading, packet buf + *[Copyright] + * Copyright (C) 2010 MediaTek Incorporation. All Rights Reserved. + ****************************************************************************/ + + +/***************************************************************************** + * C O M P I L E 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 "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 + ***************************************************************************** + */ +/* + * debug level maintain in os-related part for(?) + * DBG_MODULE_NUM: include/debug.h + * ENUM_WIFI_LOG_MODULE_NUM: include/wlan_oid.h + * ENUM_WIFI_LOG_LEVEL_DEFAULT: include/wlan_oid.h + * + * access method in include/debug.h: + * extern uint8_t aucDebugModule[]; + * extern uint32_t au4LogLevel[]; + */ +uint8_t aucDebugModule[DBG_MODULE_NUM]; +uint32_t au4LogLevel[ENUM_WIFI_LOG_MODULE_NUM] = {ENUM_WIFI_LOG_LEVEL_DEFAULT}; +/***************************************************************************** + * P R I V A T E D A T A + ***************************************************************************** + */ + + +/***************************************************************************** + * M A C R O S + ***************************************************************************** + */ + +/***************************************************************************** + * F U N C T I O N D E C L A R A T I O N S + ***************************************************************************** + */ + + +/***************************************************************************** + * F U N C T I O N S + ***************************************************************************** + */ +#if CFG_CHIP_RESET_SUPPORT +void kalRemoveProbe(IN struct GLUE_INFO *prGlueInfo) +{ + DBGLOG(INIT, WARN, "[SER][L0] not support..\n"); +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/gl_qa_agent.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/gl_qa_agent.c new file mode 100644 index 0000000000000..54a56bb295b68 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/gl_qa_agent.c @@ -0,0 +1,156 @@ +/**************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ***************************************************************************/ +/**************************************************************************** + *[File] gl_qa_agent.c + *[Version] v1.0 + *[Revision Date] 2019/01/01 + *[Author] + *[Description] + * DUT API implementation for test tool + *[Copyright] + * Copyright (C) 2010 MediaTek Incorporation. All Rights Reserved. + ****************************************************************************/ + + +/***************************************************************************** + * C O M P I L E 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 "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 + ***************************************************************************** + */ +/* export to other common part file */ +struct PARAM_RX_STAT g_HqaRxStat; +uint32_t u4RxStatSeqNum; +/***************************************************************************** + * 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 + ***************************************************************************** + */ +int32_t connacSetICapStart(struct GLUE_INFO *prGlueInfo, + uint32_t u4Trigger, uint32_t u4RingCapEn, + uint32_t u4Event, uint32_t u4Node, uint32_t u4Len, + uint32_t u4StopCycle, + uint32_t u4BW, uint32_t u4MacTriggerEvent, + uint32_t u4SourceAddrLSB, + uint32_t u4SourceAddrMSB, uint32_t u4Band) +{ + return KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +int32_t connacGetICapStatus(struct GLUE_INFO *prGlueInfo) +{ + return KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +int32_t connacGetICapIQData(struct GLUE_INFO *prGlueInfo, + uint8_t *pData, uint32_t u4IQType, uint32_t u4WFNum) +{ + return KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +int32_t mt6632SetICapStart(struct GLUE_INFO *prGlueInfo, + uint32_t u4Trigger, uint32_t u4RingCapEn, + uint32_t u4Event, uint32_t u4Node, uint32_t u4Len, + uint32_t u4StopCycle, uint32_t u4BW, uint32_t u4MacTriggerEvent, + uint32_t u4SourceAddrLSB, uint32_t u4SourceAddrMSB, uint32_t u4Band) +{ + return KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +int32_t mt6632GetICapStatus(struct GLUE_INFO *prGlueInfo) +{ + return KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +int32_t commonGetICapIQData(struct GLUE_INFO *prGlueInfo, + uint8_t *pData, uint32_t u4IQType, uint32_t u4WFNum) +{ + return KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/hif/none/include/hif.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/hif/none/include/hif.h new file mode 100644 index 0000000000000..b415dd9799198 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/hif/none/include/hif.h @@ -0,0 +1,264 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \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 + */ + +#ifndef _HIF_H +#define _HIF_H + +#if defined(_HIF_NONE) +#define HIF_NAME "NONE" +#else +#error "No HIF defined!" +#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 + ******************************************************************************* + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +struct GL_HIF_INFO; + + +/* host interface's private data structure, which is attached to os glue + ** layer info structure. + */ +struct GL_HIF_INFO { +}; + +struct BUS_INFO { +}; + + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +/* Common data type */ +#define HIF_NUM_OF_QM_RX_PKT_NUM 512 + +/* chip dependent? used in wlanHarvardFormatDownload */ +#define HIF_CR4_FWDL_SECTION_NUM 2 +#define HIF_IMG_DL_STATUS_PORT_IDX 0 + +/* enable/disable TX resource control */ +#define HIF_TX_RESOURCE_CTRL 1 + +/* enable/disable TX resource control PLE */ +#define HIF_TX_RESOURCE_CTRL_PLE 0 + +#define HIF_IST_LOOP_COUNT 128 + +/* Min msdu count to trigger Tx during INT polling state */ +#define HIF_IST_TX_THRESHOLD 32 + +#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 +/******************************************************************************* + * 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 internal use */ +#define glRegisterBus(_pfProbe, _pfRemove) + +#define glUnregisterBus(_pfRemove) + +#define glSetHifInfo(_prGlueInfo, _ulCookie) + +#define glClearHifInfo(_prGlueInfo) + +#define glBusInit(_pvData) + +#define glBusRelease(_pData) + +#define glBusSetIrq(_pvData, _pfnIsr, _pvCookie) + +#define glBusFreeIrq(_pvData, _pvCookie) + +#define glSetPowerState(_prGlueInfo, _ePowerMode) + +#define glGetDev(_prCtx, _ppDev) + +#define glGetHifDev(_prHif, _ppDev) + +#define HAL_WAKE_UP_WIFI(_prAdapter) + +#define halWpdmaInitRing(_glueinfo, __fgResetHif) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +uint8_t halTxRingDataSelect(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +/* for nic/hal.h */ +/* + * kal_virt_write_tx_port: Write frame to data port + * @ad: structure for adapter private data + * @pid: port id to write data, eg.NIC_TX_INIT_CMD_PORT + * @len: data len to write + * @buf: data buf pointer + * @buf_size: maximum size for data buffer, buf_size >= len + * + * not: implementation for different HIF may refer to nic/hal.h + */ +void kal_virt_write_tx_port(struct ADAPTER *ad, + uint16_t pid, uint32_t len, uint8_t *buf, uint32_t buf_size); + +/* + * kal_virt_get_wifi_func_stat: check HW status when check ready fail + * @ad: structure for adapter private data + * @res: status for return + * + * not: implementation for different HIF may refer to nic/hal.h + */ +void kal_virt_get_wifi_func_stat(struct ADAPTER *ad, uint32_t *res); + +/* + * kal_virt_chk_wifi_func_off: check HW status for function OFF + * @ad: structure for adapter private data + * @ready_bits: asserted bit if function is off correctly + * @res: status for return + * + * not: implementation for different HIF may refer to nic/hal.h + */ +void kal_virt_chk_wifi_func_off(struct ADAPTER *ad, uint32_t ready_bits, + uint8_t *res); + +/* + * kal_virt_chk_wifi_func_off: check HW status for function ready + * @ad: structure for adapter private data + * @ready_bits: asserted bit if function is ready + * @res: status for return + * + * not: implementation for different HIF may refer to nic/hal.h + */ +void kal_virt_chk_wifi_func_ready(struct ADAPTER *ad, uint32_t ready_bits, + uint8_t *res); + +/* + * kal_virt_set_mailbox_readclear: set read clear on hw mailbox (?) + * @ad: structure for adapter private data + * @enable: enable read clear or not + * + * not: implementation for different HIF may refer to nic/hal.h + */ +void kal_virt_set_mailbox_readclear(struct ADAPTER *ad, bool enable); + +/* + * kal_virt_set_int_stat_readclear: set hardware interrupt read clear + * @ad: structure for adapter private data + * + * not: no disable command + * not: implementation for different HIF may refer to nic/hal.h + */ +void kal_virt_set_int_stat_readclear(struct ADAPTER *ad); + +/* + * kal_virt_init_hif: do device related initialization + * @ad: structure for adapter private data + * + * not: implementation for different HIF may refer to nic/hal.h + */ +void kal_virt_init_hif(struct ADAPTER *ad); + +/* + * kal_virt_enable_fwdl: enable firmware download + * @ad: structure for adapter private data + * + * not: implementation for different HIF may refer to nic/hal.h + */ +void kal_virt_enable_fwdl(struct ADAPTER *ad, bool enable); + +/* + * kal_virt_get_int_status: read interrupt status + * @ad: structure for adapter private data + * @status: return value for interrupt status + * + * not: implementation for different HIF may refer to nic/hal.h + */ +void kal_virt_get_int_status(struct ADAPTER *ad, uint32_t *status); +#endif /* _HIF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/hif/none/none.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/hif/none/none.c new file mode 100644 index 0000000000000..6349c996b7159 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/hif/none/none.c @@ -0,0 +1,333 @@ +/**************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ***************************************************************************/ +/**************************************************************************** + *[File] axi.c + *[Version] v1.0 + *[Revision Date] 2010-03-01 + *[Author] + *[Description] + * The program provides AXI HIF driver + *[Copyright] + * Copyright (C) 2010 MediaTek Incorporation. All Rights Reserved. + ****************************************************************************/ + + +/***************************************************************************** + * C O M P I L E 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 "precomp.h" + +#include "hif.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 + ***************************************************************************** + */ + +void kal_virt_write_tx_port(struct ADAPTER *ad, + uint16_t pid, uint32_t len, uint8_t *buf, uint32_t buf_size) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +void kal_virt_get_wifi_func_stat(struct ADAPTER *ad, uint32_t *res) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +void kal_virt_chk_wifi_func_off(struct ADAPTER *ad, uint32_t ready_bits, + uint8_t *res) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +void kal_virt_chk_wifi_func_ready(struct ADAPTER *ad, uint32_t ready_bits, + uint8_t *res) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +void kal_virt_set_mailbox_readclear(struct ADAPTER *ad, bool enable) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +void kal_virt_set_int_stat_readclear(struct ADAPTER *ad) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +void kal_virt_init_hif(struct ADAPTER *ad) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +void kal_virt_enable_fwdl(struct ADAPTER *ad, bool enable) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +void kal_virt_get_int_status(struct ADAPTER *ad, uint32_t *status) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); +} + +/* the following functions are defined in include/nic/hal.h + * need to be implemented directly in os/hif + */ +bool halHifSwInfoInit(IN struct ADAPTER *prAdapter) +{ + return KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +void halPrintHifDbgInfo(IN struct ADAPTER *prAdapter) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +uint32_t halHifPowerOffWifi(IN struct ADAPTER *prAdapter) +{ + return KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +void halTxResourceResetHwTQCounter(struct ADAPTER *prAdapter) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +uint32_t halDumpHifStatus(struct ADAPTER *prAdapter, + uint8_t *pucBuf, uint32_t u4Max) +{ + return KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +uint32_t halGetValidCoalescingBufSize(IN struct ADAPTER *prAdapter) +{ + return KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +uint32_t halAllocateIOBuffer(IN struct ADAPTER *prAdapter) +{ + return KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +uint32_t halReleaseIOBuffer(IN struct ADAPTER *prAdapter) +{ + return KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +void halDisableInterrupt(IN struct ADAPTER *prAdapter) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +void halEnableInterrupt(IN struct ADAPTER *prAdapter) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +u_int8_t halVerifyChipID(IN struct ADAPTER *prAdapter) +{ + return KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +void halProcessAbnormalInterrupt(IN struct ADAPTER *prAdapter) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +void halProcessSoftwareInterrupt(IN struct ADAPTER *prAdapter) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +void halProcessRxInterrupt(IN struct ADAPTER *prAdapter) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +void halProcessTxInterrupt(IN struct ADAPTER *prAdapter) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +void halSerHifReset(IN struct ADAPTER *prAdapter) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +u_int8_t halIsTxResourceControlEn(IN struct ADAPTER *prAdapter) +{ + return KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +uint32_t halTxPollingResource(IN struct ADAPTER *prAdapter, IN uint8_t ucTC) +{ + return KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +uint32_t halGetHifTxPageSize(IN struct ADAPTER *prAdapter) +{ + return KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +u_int8_t halTxIsDataBufEnough(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + return KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +uint32_t halTxGetPageCount(IN struct ADAPTER *prAdapter, + IN uint32_t u4FrameLength, IN u_int8_t fgIncludeDesc) +{ + return KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +void halTxCancelSendingCmd(struct ADAPTER *prAdapter, + struct CMD_INFO *prCmdInfo) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +void halRxProcessMsduReport(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +u_int8_t halIsPendingRx(IN struct ADAPTER *prAdapter) +{ + /* TODO: check pending Rx + * if previous Rx handling is break due to lack of SwRfb + */ + return KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +uint32_t +halRxWaitResponse(struct ADAPTER *prAdapter, uint8_t ucPortIdx, + uint8_t *pucRspBuffer, uint32_t u4MaxRespBufferLen, uint32_t *pu4Length) +{ + return KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +void halSetFWOwn(IN struct ADAPTER *prAdapter, IN u_int8_t fgEnableGlobalInt) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +u_int8_t halSetDriverOwn(IN struct ADAPTER *prAdapter) +{ + return KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +uint8_t halTxRingDataSelect(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Check if HIF state is during supend process +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (TRUE: suspend, reject the caller action. FALSE: not suspend) +*/ +/*----------------------------------------------------------------------------*/ +bool halIsHifStateSuspend(IN struct ADAPTER *prAdapter) +{ + /* HIF owner should implement this function */ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, prAdapter); + return FALSE; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_ate_agent.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_ate_agent.h new file mode 100644 index 0000000000000..81b2de9871547 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_ate_agent.h @@ -0,0 +1,288 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/*! \file gl_ate_agent.h + * \brief This file includes private ioctl support. + */ + +#ifndef _GL_ATE_AGENT_H +#define _GL_ATE_AGENT_H +#if CFG_SUPPORT_QA_TOOL +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ + +extern uint32_t u4RxStatSeqNum; + +#if CFG_SUPPORT_TX_BF +extern union PFMU_PROFILE_TAG1 g_rPfmuTag1; +extern union PFMU_PROFILE_TAG2 g_rPfmuTag2; +extern union PFMU_DATA g_rPfmuData; +#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 + ******************************************************************************* + */ + +struct STA_REC_BF_UPD_ARGUMENT { + uint32_t u4WlanId; + uint32_t u4BssId; + uint32_t u4PfmuId; + uint32_t u4SuMu; + uint32_t u4eTxBfCap; + uint32_t u4NdpaRate; + uint32_t u4NdpRate; + uint32_t u4ReptPollRate; + uint32_t u4TxMode; + uint32_t u4Nc; + uint32_t u4Nr; + uint32_t u4Bw; + uint32_t u4SpeIdx; + uint32_t u4TotalMemReq; + uint32_t u4MemReq20M; + uint32_t au4MemRow[4]; + uint32_t au4MemCol[4]; +}; + +struct ATE_OPS_T { + int32_t (*setICapStart)(struct GLUE_INFO *prGlueInfo, + uint32_t fgTrigger, + uint32_t fgRingCapEn, + uint32_t u4Event, + uint32_t u4Node, + uint32_t u4Len, + uint32_t u4StopCycle, + uint32_t u4BW, + uint32_t u4MACTriggerEvent, + uint32_t u4SourceAddrLSB, + uint32_t u4SourceAddrMSB, + uint32_t u4Band); + int32_t (*getICapStatus)(struct GLUE_INFO *prGlueInfo); + int32_t (*getICapIQData)(struct GLUE_INFO *prGlueInfo, + uint8_t *pData, + uint32_t u4IQType, + uint32_t u4WFNum); + void (*getRbistDataDumpEvent)(struct ADAPTER *prAdapter, + uint8_t *pucEventBuf); +}; + + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +int Set_ResetStatCounter_Proc(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATE(struct net_device *prNetDev, uint8_t *prInBuf); +int SetATEDa(struct net_device *prNetDev, uint8_t *prInBuf); +int SetATESa(struct net_device *prNetDev, uint8_t *prInBuf); +int SetATEChannel(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATETxPower0(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATETxGi(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATETxBw(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATETxMode(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATETxLength(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATETxCount(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATETxMcs(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATEIpg(struct net_device *prNetDev, + uint8_t *prInBuf); + +#if CFG_SUPPORT_TX_BF +int Set_TxBfProfileTag_Help(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_InValid(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_PfmuIdx(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_BfType(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_DBW(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_SuMu(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_Mem(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_Matrix(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_SNR(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_SmartAnt(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_SeIdx(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_RmsdThrd(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_McsThrd(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_TimeOut(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_DesiredBW(struct net_device + *prNetDev, uint8_t *prInBuf); +int Set_TxBfProfileTag_DesiredNc(struct net_device + *prNetDev, uint8_t *prInBuf); +int Set_TxBfProfileTag_DesiredNr(struct net_device + *prNetDev, uint8_t *prInBuf); +int Set_TxBfProfileTagRead(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTagWrite(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_StaRecCmmUpdate(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_StaRecBfUpdate(struct net_device *prNetDev, + uint8_t *prInBuf); + +int Set_DevInfoUpdate(struct net_device *prNetDev, + uint8_t *prInBuf); + +int Set_BssInfoUpdate(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileDataRead(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileDataWrite(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_Trigger_Sounding_Proc(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_Stop_Sounding_Proc(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfTxApply(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfilePnRead(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfilePnWrite(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfManualAssoc(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfPfmuMemAlloc(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfPfmuMemRelease(struct net_device *prNetDev, + uint8_t *prInBuf); + +#if CFG_SUPPORT_MU_MIMO +int Set_MUGetInitMCS(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUCalInitMCS(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUCalLQ(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUGetLQ(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUSetSNROffset(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUSetZeroNss(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUSetSpeedUpLQ(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUSetMUTable(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUSetGroup(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUGetQD(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUSetEnable(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUSetGID_UP(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUTriggerTx(struct net_device *prNetDev, + uint8_t *prInBuf); +#endif + +#if CFG_SUPPORT_TX_BF_FPGA +int Set_TxBfProfileSwTagWrite(struct net_device *prNetDev, + uint8_t *prInBuf); +#endif +#endif + + +int WriteEfuse(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetTxTargetPower(struct net_device *prNetDev, + uint8_t *prInBuf); + +#if (CFG_SUPPORT_DFS_MASTER == 1) +int SetRddReport(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetByPassCac(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetRadarDetectMode(struct net_device *prNetDev, + uint8_t *prInBuf); +#endif + +int AteCmdSetHandle(struct net_device *prNetDev, + uint8_t *prInBuf, uint32_t u4InBufLen); + +#endif /*CFG_SUPPORT_QA_TOOL */ +#endif /* _GL_ATE_AGENT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_cfg80211.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_cfg80211.h new file mode 100644 index 0000000000000..1175faf583cf4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_cfg80211.h @@ -0,0 +1,762 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** 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. + */ + + +#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 "gl_os.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#ifdef CONFIG_NL80211_TESTMODE +#define NL80211_DRIVER_TESTMODE_VERSION 2 +#endif + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +#ifdef CONFIG_NL80211_TESTMODE +#if CFG_SUPPORT_NFC_BEAM_PLUS + +struct NL80211_DRIVER_SET_NFC_PARAMS { + struct NL80211_DRIVER_TEST_MODE_PARAMS hdr; + uint32_t NFC_Enable; + +}; + +#endif + + + +struct NL80211_DRIVER_GET_STA_STATISTICS_PARAMS { + struct NL80211_DRIVER_TEST_MODE_PARAMS hdr; + uint32_t u4Version; + uint32_t u4Flag; + uint8_t aucMacAddr[MAC_ADDR_LEN]; +}; + +enum _ENUM_TESTMODE_LINK_DETECTION_ATTR { + NL80211_TESTMODE_LINK_INVALID = 0, + NL80211_TESTMODE_LINK_TX_FAIL_CNT, + NL80211_TESTMODE_LINK_TX_RETRY_CNT, + NL80211_TESTMODE_LINK_TX_MULTI_RETRY_CNT, + NL80211_TESTMODE_LINK_ACK_FAIL_CNT, + NL80211_TESTMODE_LINK_FCS_ERR_CNT, + NL80211_TESTMODE_LINK_TX_CNT, + NL80211_TESTMODE_LINK_RX_CNT, + NL80211_TESTMODE_LINK_RST_REASON, + NL80211_TESTMODE_LINK_RST_TIME, + NL80211_TESTMODE_LINK_ROAM_FAIL_TIMES, + NL80211_TESTMODE_LINK_ROAM_FAIL_TIME, + NL80211_TESTMODE_LINK_TX_DONE_DELAY_IS_ARP, + NL80211_TESTMODE_LINK_ARRIVE_DRV_TICK, + NL80211_TESTMODE_LINK_ENQUE_TICK, + NL80211_TESTMODE_LINK_DEQUE_TICK, + NL80211_TESTMODE_LINK_LEAVE_DRV_TICK, + NL80211_TESTMODE_LINK_CURR_TICK, + NL80211_TESTMODE_LINK_CURR_TIME, + + NL80211_TESTMODE_LINK_DETECT_NUM +}; + +enum ENUM_TESTMODE_STA_STATISTICS_ATTR { + NL80211_TESTMODE_STA_STATISTICS_INVALID = 0, + NL80211_TESTMODE_STA_STATISTICS_VERSION, + NL80211_TESTMODE_STA_STATISTICS_MAC, + NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE, + NL80211_TESTMODE_STA_STATISTICS_FLAG, + + NL80211_TESTMODE_STA_STATISTICS_PER, + NL80211_TESTMODE_STA_STATISTICS_RSSI, + NL80211_TESTMODE_STA_STATISTICS_PHY_MODE, + NL80211_TESTMODE_STA_STATISTICS_TX_RATE, + + NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT, + NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT, + + NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME, + NL80211_TESTMODE_STA_STATISTICS_MAX_PROCESS_TIME, + NL80211_TESTMODE_STA_STATISTICS_AVG_HIF_PROCESS_TIME, + NL80211_TESTMODE_STA_STATISTICS_MAX_HIF_PROCESS_TIME, + + NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT, + NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT, + NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME, + + NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY, + + /* + * how many packages TX during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_ENQUEUE, + + /* + * how many packages this TX during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_STA_ENQUEUE, + + /* + * how many packages dequeue during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_DEQUEUE, + + /* + * how many packages this sta dequeue during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_STA_DEQUEUE, + + /* + * how many TC[0-3] resource back from firmware during + * statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_RB_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_NO_TC_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_USED_TC_PGCT_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_WANTED_TC_PGCT_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_PASS_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_TASK_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_AB_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_SW_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_TX_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_RX_CNT, + + NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_NUM +}; +#endif +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +/* cfg80211 hooks */ +#if 0 +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); + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *ndev, const u8 *mac, + struct station_info *sinfo); +#else +int mtk_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac, + struct station_info *sinfo); +#endif + +int +mtk_cfg80211_get_link_statistics(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac, + struct station_info *sinfo); + +int mtk_cfg80211_scan(struct wiphy *wiphy, + struct cfg80211_scan_request *request); + +void mtk_cfg80211_abort_scan(struct wiphy *wiphy, + struct wireless_dev *wdev); + +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_set_rekey_data(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_gtk_rekey_data *data); + +int mtk_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, struct ieee80211_channel *chan, + unsigned int duration, u64 *cookie); + +int mtk_cfg80211_cancel_remain_on_channel( + struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie); +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie); +#else +int mtk_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *channel, bool offscan, + unsigned int wait, + const u8 *buf, size_t len, bool no_cck, + bool dont_wait_for_ack, u64 *cookie); +#endif + +void mtk_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, + IN struct wireless_dev *wdev, IN u16 frame_type, IN bool reg); + +int mtk_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct wireless_dev *wdev, u64 cookie); + +#ifdef CONFIG_NL80211_TESTMODE +int +mtk_cfg80211_testmode_get_sta_statistics(IN struct wiphy + *wiphy, + IN void *data, IN int len, IN struct GLUE_INFO *prGlueInfo); + +int mtk_cfg80211_testmode_get_scan_done(IN struct wiphy + *wiphy, IN void *data, IN int len, + IN struct GLUE_INFO *prGlueInfo); + +#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_testmode_cmd(struct wiphy *wiphy, + struct wireless_dev *wdev, + void *data, int len); +#else +int mtk_cfg80211_testmode_cmd(struct wiphy *wiphy, + void *data, int len); +#endif + +int mtk_cfg80211_testmode_sw_cmd(IN struct wiphy *wiphy, + IN void *data, IN int len); + +#if CFG_SUPPORT_PASSPOINT +int mtk_cfg80211_testmode_hs20_cmd(IN struct wiphy *wiphy, + IN void *data, IN int len); +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_WAPI +int mtk_cfg80211_testmode_set_key_ext(IN struct wiphy + *wiphy, IN void *data, IN int len); +#endif +#if CFG_SUPPORT_NFC_BEAM_PLUS +int mtk_cfg80211_testmode_get_scan_done(IN struct wiphy *wiphy, + IN void *data, IN int len, IN struct GLUE_INFO *prGlueInfo); +#endif +#else +/* IGNORE KERNEL DEPENCY ERRORS */ +/* #error "Please ENABLE kernel config (CONFIG_NL80211_TESTMODE) to support + * Wi-Fi Direct" + */ +#endif + +#if CFG_SUPPORT_SCHED_SCAN +int +mtk_cfg80211_sched_scan_start(IN struct wiphy *wiphy, + IN struct net_device *ndev, + IN struct cfg80211_sched_scan_request *request); + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_sched_scan_stop(IN struct wiphy *wiphy, + IN struct net_device *ndev, + IN u64 reqid); +#else +int mtk_cfg80211_sched_scan_stop(IN struct wiphy *wiphy, + IN struct net_device *ndev); +#endif +#endif /* CFG_SUPPORT_SCHED_SCAN */ + +int mtk_cfg80211_assoc(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_assoc_request *req); + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int +mtk_cfg80211_change_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, struct station_parameters *params); + +int mtk_cfg80211_add_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, struct station_parameters *params); + +#if KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *ndev, + struct station_del_parameters *params); +#else +int mtk_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac); +#endif +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, + bool initiator, const u8 *buf, size_t len); +#else +int mtk_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, + const u8 *buf, size_t len); +#endif + +int mtk_cfg80211_tdls_oper(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, enum nl80211_tdls_operation oper); +#else +int +mtk_cfg80211_change_station(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac, + struct station_parameters *params); + +int mtk_cfg80211_add_station(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac, + struct station_parameters *params); + +int mtk_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac); + +int +mtk_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + u8 *peer, u8 action_code, + u8 dialog_token, u16 status_code, + const u8 *buf, size_t len); + +int mtk_cfg80211_tdls_oper(struct wiphy *wiphy, + struct net_device *dev, u8 *peer, + enum nl80211_tdls_operation oper); +#endif + +int32_t mtk_cfg80211_process_str_cmd(struct GLUE_INFO + *prGlueInfo, uint8_t *cmd, int32_t len); + +void mtk_reg_notify(IN struct wiphy *pWiphy, + IN struct regulatory_request *pRequest); +void cfg80211_regd_set_wiphy(IN struct wiphy *pWiphy); + +int mtk_cfg80211_suspend(struct wiphy *wiphy, + struct cfg80211_wowlan *wow); + +int mtk_cfg80211_resume(struct wiphy *wiphy); + +/* cfg80211 wrapper hooks */ +#if CFG_ENABLE_UNIFY_WIPHY +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +struct wireless_dev *mtk_cfg_add_iface(struct wiphy *wiphy, + const char *name, + unsigned char name_assign_type, + enum nl80211_iftype type, + struct vif_params *params); +#elif KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE +struct wireless_dev *mtk_cfg_add_iface(struct wiphy *wiphy, + const char *name, + unsigned char name_assign_type, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params); +#else +struct wireless_dev *mtk_cfg_add_iface(struct wiphy *wiphy, + const char *name, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params); +#endif +int mtk_cfg_del_iface(struct wiphy *wiphy, + struct wireless_dev *wdev); +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_change_iface(struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type, + struct vif_params *params); +#else +int mtk_cfg_change_iface(struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params); +#endif +int mtk_cfg_add_key(struct wiphy *wiphy, + struct net_device *ndev, u8 key_index, + bool pairwise, const u8 *mac_addr, + struct key_params *params); +int mtk_cfg_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_cfg_del_key(struct wiphy *wiphy, + struct net_device *ndev, u8 key_index, + bool pairwise, const u8 *mac_addr); +int mtk_cfg_set_default_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, bool unicast, bool multicast); + +int mtk_cfg_set_default_mgmt_key(struct wiphy *wiphy, + struct net_device *ndev, u8 key_index); + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_get_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, struct station_info *sinfo); +#else +int mtk_cfg_get_station(struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, struct station_info *sinfo); +#endif + +#if CFG_SUPPORT_TDLS +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_change_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, struct station_parameters *params); +#else +int mtk_cfg_change_station(struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, struct station_parameters *params); +#endif +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_add_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, struct station_parameters *params); +#else +int mtk_cfg_add_station(struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, struct station_parameters *params); +#endif +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_tdls_oper(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *peer, enum nl80211_tdls_operation oper); +#else +int mtk_cfg_tdls_oper(struct wiphy *wiphy, + struct net_device *ndev, + u8 *peer, enum nl80211_tdls_operation oper); +#endif +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_tdls_mgmt(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, + u32 peer_capability, bool initiator, const u8 *buf, + size_t len); +#elif KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_tdls_mgmt(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, + u32 peer_capability, const u8 *buf, size_t len); +#else +int mtk_cfg_tdls_mgmt(struct wiphy *wiphy, + struct net_device *ndev, + u8 *peer, u8 action_code, + u8 dialog_token, u16 status_code, + const u8 *buf, size_t len); +#endif +#endif /* CFG_SUPPORT_TDLS */ + +#if KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_del_station(struct wiphy *wiphy, + struct net_device *ndev, + struct station_del_parameters *params); +#elif KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_del_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac); +#else +int mtk_cfg_del_station(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac); +#endif +int mtk_cfg_scan(struct wiphy *wiphy, + struct cfg80211_scan_request *request); +#if KERNEL_VERSION(4, 5, 0) <= CFG80211_VERSION_CODE +void mtk_cfg_abort_scan(struct wiphy *wiphy, + struct wireless_dev *wdev); +#endif + +#if CFG_SUPPORT_SCHED_SCAN +int mtk_cfg_sched_scan_start(IN struct wiphy *wiphy, + IN struct net_device *ndev, + IN struct cfg80211_sched_scan_request *request); + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_sched_scan_stop(IN struct wiphy *wiphy, + IN struct net_device *ndev, + IN u64 reqid); +#else +int mtk_cfg_sched_scan_stop(IN struct wiphy *wiphy, + IN struct net_device *ndev); +#endif + +#endif /* CFG_SUPPORT_SCHED_SCAN */ + +int mtk_cfg_connect(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_connect_params *sme); +int mtk_cfg_disconnect(struct wiphy *wiphy, + struct net_device *ndev, + u16 reason_code); +int mtk_cfg_join_ibss(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_ibss_params *params); +int mtk_cfg_leave_ibss(struct wiphy *wiphy, + struct net_device *ndev); +int mtk_cfg_set_power_mgmt(struct wiphy *wiphy, + struct net_device *ndev, + bool enabled, int timeout); +int mtk_cfg_set_pmksa(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_pmksa *pmksa); +int mtk_cfg_del_pmksa(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_pmksa *pmksa); +int mtk_cfg_flush_pmksa(struct wiphy *wiphy, + struct net_device *ndev); +#if CONFIG_SUPPORT_GTK_REKEY +int mtk_cfg_set_rekey_data(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_gtk_rekey_data *data); +#endif /* CONFIG_SUPPORT_GTK_REKEY */ +int mtk_cfg_suspend(struct wiphy *wiphy, + struct cfg80211_wowlan *wow); +int mtk_cfg_resume(struct wiphy *wiphy); +int mtk_cfg_assoc(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_assoc_request *req); +int mtk_cfg_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, + unsigned int duration, + u64 *cookie); +int mtk_cfg_cancel_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, u64 cookie); +uint16_t cfg80211_get_non_wfa_vendor_ie(struct GLUE_INFO + *prGlueInfo, uint8_t *ies, int32_t len); + +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, u64 *cookie); +#else +int mtk_cfg_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *channel, bool offscan, + unsigned int wait, + const u8 *buf, size_t len, bool no_cck, + bool dont_wait_for_ack, + u64 *cookie); +#endif +void mtk_cfg_mgmt_frame_register(struct wiphy *wiphy, + struct wireless_dev *wdev, + u16 frame_type, bool reg); + +#ifdef CONFIG_NL80211_TESTMODE +#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_testmode_cmd(struct wiphy *wiphy, + struct wireless_dev *wdev, + void *data, int len); +#else +int mtk_cfg_testmode_cmd(struct wiphy *wiphy, void *data, + int len); +#endif +#endif /* CONFIG_NL80211_TESTMODE */ + +#if (CFG_SUPPORT_DFS_MASTER == 1) +#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_start_radar_detection(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef, + unsigned int cac_time_ms); +#else +int mtk_cfg_start_radar_detection(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef); +#endif + + +#if KERNEL_VERSION(3, 13, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_channel_switch(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_csa_settings *params); +#endif +#endif + + +#if (CFG_ENABLE_WIFI_DIRECT_CFG_80211 != 0) +int mtk_cfg_change_bss(struct wiphy *wiphy, + struct net_device *dev, + struct bss_parameters *params); +int mtk_cfg_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie); +int mtk_cfg_deauth(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_deauth_request *req); +int mtk_cfg_disassoc(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_disassoc_request *req); +int mtk_cfg_start_ap(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ap_settings *settings); +int mtk_cfg_change_beacon(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_beacon_data *info); +int mtk_cfg_stop_ap(struct wiphy *wiphy, + struct net_device *dev); +int mtk_cfg_set_wiphy_params(struct wiphy *wiphy, + u32 changed); +int mtk_cfg_set_bitrate_mask(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, + const struct cfg80211_bitrate_mask *mask); +int mtk_cfg_set_txpower(struct wiphy *wiphy, + struct wireless_dev *wdev, + enum nl80211_tx_power_setting type, int mbm); +int mtk_cfg_get_txpower(struct wiphy *wiphy, + struct wireless_dev *wdev, + int *dbm); +#endif /* (CFG_ENABLE_WIFI_DIRECT_CFG_80211 != 0) */ + +#endif /* CFG_ENABLE_UNIFY_WIPHY */ + +int mtk_cfg80211_update_ft_ies(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_update_ft_ies_params *ftie); +#endif + +#ifdef CFG_REMIND_IMPLEMENT +#define mtk_cfg80211_find_ie_match_mask(_eid, _ies, _len, _match,\ + _match_len, _match_offset, _match_mask) \ + ((uint8_t *) KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__)) +#else +const uint8_t *mtk_cfg80211_find_ie_match_mask(uint8_t eid, + const uint8_t *ies, int len, + const uint8_t *match, + int match_len, int match_offset, + const uint8_t *match_mask); +#endif + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _GL_CFG80211_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_dependent.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_dependent.h new file mode 100644 index 0000000000000..6d66b1f00c3a3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_dependent.h @@ -0,0 +1,1100 @@ + +/***************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ***************************************************************************/ +/*! \file gl_dependency.h + * \brief List the os-dependent structure/API that need to implement + * to align with common part + * + * not to modify *.c while put current used linux-type strucutre/API here + * For porting to new OS, the API listed in this file needs to be + * implemented + */ + +#ifndef _GL_DEPENDENT_H +#define _GL_DEPENDENT_H + +#ifndef IS_ENABLED +#define IS_ENABLED(_val) defined(_val) +#endif +/* + * TODO: implement defined structure to let + * other OS aligned to linux style for common part logic workaround + */ +/* + * TODO: os-related?, CHN_DIRTY_WEIGHT_UPPERBOUND + * should we remove gl_*_ioctl.h in os/none? + * defined in os/linux/include/gl_p2p_ioctl.h + * used in + * 1) os/linux/gl_p2p_cfg80211.c + * 2) mgmt/cnm.c + * > is it related to ioctl?, or should it put in wlan_p2p.h + */ +#if 0 +#define CHN_DIRTY_WEIGHT_UPPERBOUND 4 +#endif + +/* some arch's have a small-data section that can be accessed register-relative + * but that can only take up to, say, 4-byte variables. jiffies being part of + * an 8-byte variable may not be correctly accessed unless we force the issue + * #define __jiffy_data __attribute__((section(".data"))) + * + * The 64-bit value is not atomic - you MUST NOT read it + * without sampling the sequence number in jiffies_lock. + + * extern u64 __jiffy_data jiffies_64; + * extern unsigned long volatile __jiffy_data jiffies; + * TODO: no idea how to implement jiffies here + */ +#ifndef HZ +#define HZ (1000) +#endif +#define jiffies (0) + +/* + * comment: cipher type should not related to os + * defined in os/linux/gl_wext.h, + * while it looks like also defined in linux/wireless.h + * are we trying to be an self-fulfilled driver then + * should not put it under os folder? or we should just include from linux + */ +/* 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 + +/* + * comment: + * 1) access GlueInfo member from core logic + * 2) IW_AUTH_WPA_VERSION_DISABLED is defined in os/linux/include/gl_wext.h + * > is the an os-dependent value/ protocol value. + * should implement depends on OS/ its WiFi + * needed by, + * mgmt/ais_fsm.c + * mgmt/assoc.c + */ +/* 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 + +#define IW_AUTH_ALG_FT 0x00000008 + +#define IW_PMKID_LEN 16 +/* + * this highly depends on kernel version + * why can't we just use kalGetTimeTick (?) + * needed by + * wmm.c + */ +#if 0 +struct timespec { + __kernel_time_t tv_sec; /* seconds */ + long tv_nsec; /* nanoseconds */ +}; +#endif + +/* + * defined in linux/time64.h + * in cnm_timer.h + * we do (?!), we may just add undef NSEC_PER_MSEC then define ours + * #undef MSEC_PER_SEC + * #define MSEC_PER_SEC 1000 + * #undef USEC_PER_MSEC + * #define USEC_PER_MSEC 1000 + * #undef USEC_PER_SEC + * #define USEC_PER_SEC 1000000 + */ +#define NSEC_PER_MSEC 1000000L + +/* + * needed by nic/nic_cmd_event.c + * defined in uapi/asm-generic/fcntl.h + */ +#define O_RDONLY 00000000 + +/* + * needed by que_mgt.c + * ETH_P_IP, include/linux/if_ether.h + */ +#define ETH_P_IP 0x0800 /* Internet Protocol packet */ + +/* + * needed by cmm_asic_connac.c + * Potential risk in this function + * #ifdef CONFIG_PHYS_ADDR_T_64BIT + * typedef u64 phys_addr_t; + * #else + * typedef u32 phys_addr_t; + * #endif + * while anyway the rDmaAddr is transfer to u8Addr still u64 + * , and filled into u4Ptr0 which is uint32_t (?) + */ +#define phys_addr_t uint32_t + +/* + * needed by nic_tx.h + * defined in linux/types.h + * #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT + * typedef u64 dma_addr_t; + * #else + * typedef u32 dma_addr_t; + * #endif + */ +#define dma_addr_t uint32_t + +/* needed by: + * common/debug.c + * source/include/linux/printk.h + */ +enum { + DUMP_PREFIX_NONE, + DUMP_PREFIX_ADDRESS, + DUMP_PREFIX_OFFSET +}; + +/* needed by + * common/wlan_lib.c + * include/mgmt/rsn.h + */ +#define LINUX_VERSION_CODE 199947 +#define CFG80211_VERSION_CODE LINUX_VERSION_CODE +#define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c)) + +/* needed by nic/nic_cmd_event.c */ +struct wireless_dev { + + struct wiphy *wiphy; + struct net_device *netdev; + +}; +/* needed by + * common/wlan_lib.c & wlan_lib.h + * mgmt/tdls.c + * mgmt/p2p_role_fsm.c + * nic/nic_cmd_event.c + */ +struct net_device { + /* + * access member of member of GlueInfo directly + * in mgmt/p2p_role_fsm.c + */ + unsigned char *dev_addr; + /* needed by nic/nic_cmd_event.c */ + struct wireless_dev *ieee80211_ptr; +}; + +struct device { +}; + +/* needed by + * common/debug.c + * mgmt/stats.c + * include/nic/nic_tx.h, nic/nic_tx.c + * cb for driver private for data packet + * dev needed by mgmt/tdls.c + * mgmt/tkip_mic.c, and do dev_alloc_skb + * nic/nic_rx.c + * nic/que_mgt.c + */ +struct sk_buff { + char cb[48]; + unsigned char *data; + unsigned int len; + struct net_device *dev; +}; + +/* + * needed by common/wlan_oid.c + * struct cfg80211_update_ft_ies_params - FT IE Information + * This structure provides information needed to update the fast transition IE + * + * @md: The Mobility Domain ID, 2 Octet value + * @ie: Fast Transition IEs + * @ie_len: Length of ft_ie in octets + */ +struct cfg80211_update_ft_ies_params { + u16 md; + const u8 *ie; + size_t ie_len; +}; + +/* + * needed by + * include/mgmt/rlm_domain.h + * mgmt/p2p_func.c + * + * enum nl80211_dfs_regions - regulatory DFS regions + * + * @NL80211_DFS_UNSET: Country has no DFS master region specified + * @NL80211_DFS_FCC: Country follows DFS master rules from FCC + * @NL80211_DFS_ETSI: Country follows DFS master rules from ETSI + * @NL80211_DFS_JP: Country follows DFS master rules from JP/MKK/Telec + */ +enum nl80211_dfs_regions { + NL80211_DFS_UNSET = 0, + NL80211_DFS_FCC = 1, + NL80211_DFS_ETSI = 2, + NL80211_DFS_JP = 3, +}; + +/* + * needed by mgmt/rlm_domain.c + * enum ieee80211_channel_flags - channel flags + * + * Channel flags set by the regulatory control code. + * + * @IEEE80211_CHAN_DISABLED: This channel is disabled. + * @IEEE80211_CHAN_NO_IR: do not initiate radiation, this includes + * sending probe requests or beaconing. + * @IEEE80211_CHAN_RADAR: Radar detection is required on this channel. + * @IEEE80211_CHAN_NO_HT40PLUS: extension channel above this channel + * is not permitted. + * @IEEE80211_CHAN_NO_HT40MINUS: extension channel below this channel + * is not permitted. + * @IEEE80211_CHAN_NO_OFDM: OFDM is not allowed on this channel. + * @IEEE80211_CHAN_NO_80MHZ: If the driver supports 80 MHz on the band, + * this flag indicates that an 80 MHz channel cannot use this + * channel as the control or any of the secondary channels. + * This may be due to the driver or due to regulatory bandwidth + * restrictions. + * @IEEE80211_CHAN_NO_160MHZ: If the driver supports 160 MHz on the band, + * this flag indicates that an 160 MHz channel cannot use this + * channel as the control or any of the secondary channels. + * This may be due to the driver or due to regulatory bandwidth + * restrictions. + * @IEEE80211_CHAN_INDOOR_ONLY: see %NL80211_FREQUENCY_ATTR_INDOOR_ONLY + * @IEEE80211_CHAN_GO_CONCURRENT: see %NL80211_FREQUENCY_ATTR_GO_CONCURRENT + * @IEEE80211_CHAN_NO_20MHZ: 20 MHz bandwidth is not permitted + * on this channel. + * @IEEE80211_CHAN_NO_10MHZ: 10 MHz bandwidth is not permitted + * on this channel. + * + */ +enum ieee80211_channel_flags { + IEEE80211_CHAN_DISABLED = 1<<0, + IEEE80211_CHAN_NO_IR = 1<<1, + /* hole at 1<<2 */ + IEEE80211_CHAN_RADAR = 1<<3, + IEEE80211_CHAN_NO_HT40PLUS = 1<<4, + IEEE80211_CHAN_NO_HT40MINUS = 1<<5, + IEEE80211_CHAN_NO_OFDM = 1<<6, + IEEE80211_CHAN_NO_80MHZ = 1<<7, + IEEE80211_CHAN_NO_160MHZ = 1<<8, + IEEE80211_CHAN_INDOOR_ONLY = 1<<9, + IEEE80211_CHAN_GO_CONCURRENT = 1<<10, + IEEE80211_CHAN_NO_20MHZ = 1<<11, + IEEE80211_CHAN_NO_10MHZ = 1<<12, +}; + +/* needed by mgmt/rlm_domain.c */ +#define IEEE80211_CHAN_NO_HT40 \ + (IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS) + +/* + * needed by + * mgmt/p2p_func.c + * + * enum nl80211_dfs_state - DFS states for channels + * + * Channel states used by the DFS code. + * + * @NL80211_DFS_USABLE: The channel can be used, but channel availability + * check (CAC) must be performed before using it for AP or IBSS. + * @NL80211_DFS_UNAVAILABLE: A radar has been detected on this channel, it + * is therefore marked as not available. + * @NL80211_DFS_AVAILABLE: The channel has been CAC checked and is available. + */ +enum nl80211_dfs_state { + NL80211_DFS_USABLE, + NL80211_DFS_UNAVAILABLE, + NL80211_DFS_AVAILABLE, +}; +/* + * needed by mgmt/rlm_domain.c + * needed by mgmt/p2p_func.c + * enum nl80211_band - Frequency band + * @NL80211_BAND_2GHZ: 2.4 GHz ISM band + * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz) + * @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 69.12 GHz) + * @NUM_NL80211_BANDS: number of bands, avoid using this in userspace + * since newer kernel versions may support more bands + */ +enum nl80211_band { + NL80211_BAND_2GHZ, + NL80211_BAND_5GHZ, + NL80211_BAND_60GHZ, + NUM_NL80211_BANDS, +}; + +/* + * enum nl80211_initiator - Indicates the initiator of a reg domain request + * @NL80211_REGDOM_SET_BY_CORE: Core queried CRDA for a dynamic world + * regulatory domain. + * @NL80211_REGDOM_SET_BY_USER: User asked the wireless core to set the + * regulatory domain. + * @NL80211_REGDOM_SET_BY_DRIVER: a wireless drivers has hinted to the + * wireless core it thinks its knows the regulatory domain we should be in. + * @NL80211_REGDOM_SET_BY_COUNTRY_IE: the wireless core has received an + * 802.11 country information element with regulatory information it + * thinks we should consider. cfg80211 only processes the country + * code from the IE, and relies on the regulatory domain information + * structure passed by userspace (CRDA) from our wireless-regdb. + * If a channel is enabled but the country code indicates it should + * be disabled we disable the channel and re-enable it upon disassociation. + */ +enum nl80211_reg_initiator { + L80211_REGDOM_SET_BY_CORE, + NL80211_REGDOM_SET_BY_USER, + NL80211_REGDOM_SET_BY_DRIVER, + NL80211_REGDOM_SET_BY_COUNTRY_IE, +}; +/* needed by + * mgmt/rlm_domain.c + * mgmt/cnm.c + * mgmt/p2p_func.c + */ +struct ieee80211_channel { + enum nl80211_band band; + u32 center_freq; + u16 hw_value; + u32 flags; + enum nl80211_dfs_state dfs_state; +}; + +/* + * needed by mgmt/cnm.c + * enum nl80211_chan_width - channel width definitions + * + * These values are used with the %NL80211_ATTR_CHANNEL_WIDTH + * attribute. + * + * @NL80211_CHAN_WIDTH_20_NOHT: 20 MHz, non-HT channel + * @NL80211_CHAN_WIDTH_20: 20 MHz HT channel + * @NL80211_CHAN_WIDTH_40: 40 MHz channel, the %NL80211_ATTR_CENTER_FREQ1 + * attribute must be provided as well + * @NL80211_CHAN_WIDTH_80: 80 MHz channel, the %NL80211_ATTR_CENTER_FREQ1 + * attribute must be provided as well + * @NL80211_CHAN_WIDTH_80P80: 80+80 MHz channel, the %NL80211_ATTR_CENTER_FREQ1 + * and %NL80211_ATTR_CENTER_FREQ2 attributes must be provided as well + * @NL80211_CHAN_WIDTH_160: 160 MHz channel, the %NL80211_ATTR_CENTER_FREQ1 + * attribute must be provided as well + * @NL80211_CHAN_WIDTH_5: 5 MHz OFDM channel + * @NL80211_CHAN_WIDTH_10: 10 MHz OFDM channel + */ +enum nl80211_chan_width { + NL80211_CHAN_WIDTH_20_NOHT, + NL80211_CHAN_WIDTH_20, + NL80211_CHAN_WIDTH_40, + NL80211_CHAN_WIDTH_80, + NL80211_CHAN_WIDTH_80P80, + NL80211_CHAN_WIDTH_160, + NL80211_CHAN_WIDTH_5, + NL80211_CHAN_WIDTH_10, +}; + +/* needed by mgmt/rlm_domain.c */ +struct ieee80211_supported_band { + struct ieee80211_channel *channels; + int n_channels; +}; + +/* + * too many os dependent in regular domain + * on/off fail + */ +#if CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1 +/* at leat 7 is needed for regdom_jp */ +#define MAX_NUMER_REG_RULES 7 + +struct ieee80211_power_rule { + u32 max_antenna_gain; + u32 max_eirp; +}; + +struct ieee80211_freq_range { + u32 start_freq_khz; + u32 end_freq_khz; + u32 max_bandwidth_khz; +}; + +struct ieee80211_reg_rule { + struct ieee80211_freq_range freq_range; + struct ieee80211_power_rule power_rule; + u32 flags; /* enum reg_flags */ + u32 dfs_cac_ms; +}; + +struct ieee80211_regdomain { + char alpha2[3]; + u32 n_reg_rules; + enum nl80211_dfs_regions dfs_region; + struct ieee80211_reg_rule reg_rules[MAX_NUMER_REG_RULES]; +}; + +#define MHZ_TO_KHZ(freq) ((freq) * 1000) +#define KHZ_TO_MHZ(freq) ((freq) / 1000) +#define DBI_TO_MBI(gain) ((gain) * 100) +#define MBI_TO_DBI(gain) ((gain) / 100) +#define DBM_TO_MBM(gain) ((gain) * 100) +#define MBM_TO_DBM(gain) ((gain) / 100) + +#define REG_RULE_EXT(start, end, bw, gain, eirp, dfs_cac, reg_flags) \ +{ \ + .freq_range.start_freq_khz = MHZ_TO_KHZ(start), \ + .freq_range.end_freq_khz = MHZ_TO_KHZ(end), \ + .freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw), \ + .power_rule.max_eirp = DBM_TO_MBM(eirp), \ + .flags = reg_flags, \ + .dfs_cac_ms = dfs_cac, \ +} + +#define REG_RULE(start, end, bw, gain, eirp, reg_flags) \ +{ \ + .freq_range.start_freq_khz = MHZ_TO_KHZ(start), \ + .freq_range.end_freq_khz = MHZ_TO_KHZ(end), \ + .freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw), \ + .power_rule.max_antenna_gain = DBI_TO_MBI(gain),\ + .power_rule.max_eirp = DBM_TO_MBM(eirp), \ + .flags = reg_flags, \ +} +#endif +/* needed by + * mgmt/rlm_domain.c + * nic/nic_cmd_event.c + */ +struct wiphy { + struct ieee80211_supported_band *bands[NUM_NL80211_BANDS]; +}; + +/* + * needed by include/mgmt/rlm_domain.h & mgmt/rlm_domain.c + * but parameter not used + */ +struct regulatory_request { + enum nl80211_reg_initiator initiator; +}; + +/* needed by mgmt/stats.c */ +struct rtc_time { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; +}; + +#define NSEC_PER_USEC 1000L + +/* + * needed by + * mgmt/tdls.c + * mgmt/saa_fsm.c, saaFsmSteps + * + * enum nl80211_tdls_operation - values for %NL80211_ATTR_TDLS_OPERATION + * @NL80211_TDLS_DISCOVERY_REQ: Send a TDLS discovery request + * @NL80211_TDLS_SETUP: Setup TDLS link + * @NL80211_TDLS_TEARDOWN: Teardown a TDLS link which is already established + * @NL80211_TDLS_ENABLE_LINK: Enable TDLS link + * @NL80211_TDLS_DISABLE_LINK: Disable TDLS link + */ +enum nl80211_tdls_operation { + NL80211_TDLS_DISCOVERY_REQ, + NL80211_TDLS_SETUP, + NL80211_TDLS_TEARDOWN, + NL80211_TDLS_ENABLE_LINK, + NL80211_TDLS_DISABLE_LINK, +}; + +/* + * needed by mgmt/tdls.c + */ +enum gfp_t { + GFP_KERNEL, + GFP_ATOMIC, + __GFP_HIGHMEM, + __GFP_HIGH +}; + +/* needed by include/nic/adapter.h + * for DIRECT_TX implementation in os folder + */ +struct timer_list { + /* TODO: from the comment in linux/timer.h. Its difficult to implement + * All fields that change during normal runtime grouped to the + * same cacheline + */ +}; + +/* needed by include/nic/adapter.h + * for DIRECT_TX implementation in os folder + */ +struct sk_buff_head { + /* These two members must be first. */ + /* struct sk_buff *next; */ + /* struct sk_buff *prev; */ + uint32_t qlen; +}; + +/* + * should be defined as lock in corresponding os + * access directly by + * nic/nic_tx.c + * nic/nic_rx.c + * nic/que_mgt.c + * + * reference: + * typedef struct spinlock { + * } spinlock_t; + */ +#define spinlock_t uint32_t + +/* + * needed by mgmt/auth.c + * struct cfg80211_ft_event - FT Information Elements + * @ies: FT IEs + * @ies_len: length of the FT IE in bytes + * @target_ap: target AP's MAC address + * @ric_ies: RIC IE + * @ric_ies_len: length of the RIC IE in bytes + */ +struct cfg80211_ft_event_params { + const u8 *ies; + size_t ies_len; + const u8 *target_ap; + const u8 *ric_ies; + size_t ric_ies_len; +}; + +/* + * needed by + * mgmt/cnm.c, which access struct GL_P2P_INFO directly + * mgmt/p2p_func.c, do cnmMemAlloc + * mgmt/p2p_role_fsm.c + * + * struct cfg80211_chan_def - channel definition + * @chan: the (control) channel + * @width: channel width + * @center_freq1: center frequency of first segment + * @center_freq2: center frequency of second segment + * (only with 80+80 MHz) + */ +struct cfg80211_chan_def { + struct ieee80211_channel *chan; + enum nl80211_chan_width width; + u32 center_freq1; + u32 center_freq2; +}; + +/* + * needed by + * mgmt/p2p_scan.c + */ +struct cfg80211_scan_request { +}; + +/* need by include/hal.h, halDeAggRxPktWorker + * comment: use os-related structure directly outside headers of gl layer + * while the implementation is in os/linux/hif* + * possible actions: + * 1) should we just move the function prototype to os gl layer? + */ +struct work_struct { + /* atomic_long_t data; */ + /* struct list_head entry; */ + /* work_func_t func; */ +}; + +/* needed by include/nic/mt66xx_reg.h + * struct mt66xx_chip_info + * comment: use with #if CFG_MTK_ANDROID_WMT + * implementation: extern void connectivity_export_show_stack + * which is outside our driver, but defined in chips/connac* + * should we move to glue layer ? other os can also show StakInfo + */ +struct task_struct { +}; +/* + * TODO: Functions need implementation + */ + +/**************************************************************************** + * TODO: Functions prototype, which could be realized as follows + * 1) inline function + * 2) os API with same functionality + * 3) implemented in gl_dependent.c + **************************************************************************** + */ +/* + * KAL_NEED_IMPLEMENT: wrapper to caution user to implement func when porting + * @file: from which file + * @func: called by which func + * @line: at which line + */ +long KAL_NEED_IMPLEMENT(const char *file, const char *func, int line, ...); + +/* + * kal_dbg_print: print debug message to screen + * + * needed by common/debug.c + * source/include/linux/printk.h + */ +int kal_dbg_print(const char *s, ...); +#define pr_info(fmt, ...) printf(fmt) + +/* + * kal_hex_dump_to_buffer: convert a blob of data to "hex ASCII" in memory + * @buf: data blob to dump + * @len: number of bytes in the @buf + * @rowsize: number of bytes to print per line; must be 16 or 32 + * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1) + * @linebuf: where to put the converted data + * @linebuflen: total size of @linebuf, including space for terminating NUL + * @ascii: include ASCII after the hex output + * + * needed by common/debug.c + * source/include/linux/printk.h + */ +int kal_hex_dump_to_buffer(const void *buf, size_t len, int rowsize, + int groupsize, char *linebuf, size_t linebuflen, + bool ascii); +#define hex_dump_to_buffer(_buf, _len, _rowsize, _groupsize, _linebuf, \ + _linebuflen, _ascii) \ + kal_hex_dump_to_buffer(_buf, _len, _rowsize, _groupsize, _linebuf, \ + _linebuflen, _ascii) + +/* + * purpose: + * polite version of BUG_ON() - WARN_ON() which doesn't + * kill the machine, replace panic() to dump_stack() + * needed by mgmt/rlm_domain.c + */ +void kal_warn_on(uint8_t condition); +#define WARN_ON(_condition) kal_warn_on(_condition) + +/* + * kal_do_gettimeofday - Returns the time of day in a timeval + * @tv: pointer to the timeval to be set + * needed by + * common/debug.c + * mgmt/stats.c + */ +void kal_do_gettimeofday(struct timeval *tv); +#define do_gettimeofday(_tv) kal_do_gettimeofday(_tv) + +/* + * needed by: mgmt/wmm.c + * anything on kalGetTimeTick (?) + * Timespec interfaces utilizing the ktime based ones + * ktime_to_timespec(ktime_get_boottime()); + */ +void kal_get_monotonic_boottime(struct timespec *ts); +#define get_monotonic_boottime(_ts) kal_get_monotonic_boottime(_ts) + +/* + * needed by nic_tx.c + * kal_mod_timer - modify a timer's timeout + * @timer: the timer to be modified + * @expires: new timeout in jiffies + * The function returns whether it has modified a pending timer or not. + * (ie. mod_timer() of an inactive timer returns 0, mod_timer() of an + * active timer returns 1.) + */ +int kal_mod_timer(struct timer_list *timer, unsigned long expires); +#define mod_timer(_timer, _expires) kal_mod_timer(_timer, _expires) + +/* + * kstrto* - convert a string to an * + * @s: The start of the string. The string must be null-terminated, and may also + * include a single newline before its terminating null. The first character + * may also be a plus sign or a minus sign. + * @base: The number base to use. The maximum supported base is 16. If base is + * given as 0, then the base of the string is automatically detected with the + * conventional semantics - If it begins with 0x the number will be parsed as a + * hexadecimal (case insensitive), if it otherwise begins with 0, it will be + * parsed as an octal number. Otherwise it will be parsed as a decimal. + * @res: Where to write the result of the conversion on success. + * + * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. + * Used as a replacement for the obsolete simple_strtoull. Return code must + * be checked. + */ +int kal_strtoint(const char *s, unsigned int base, int *res); +int kal_strtou8(const char *s, unsigned int base, uint8_t *res); +int kal_strtou16(const char *s, unsigned int base, uint16_t *res); +int kal_strtou32(const char *s, unsigned int base, uint32_t *res); +int kal_strtos32(const char *s, unsigned int base, int32_t *res); + +/* + * kstrtoul - convert a string to an unsigned long + * @s: The start of the string. The string must be null-terminated, and may also + * include a single newline before its terminating null. The first character + * may also be a plus sign, but not a minus sign. + * @base: The number base to use. The maximum supported base is 16. If base is + * given as 0, then the base of the string is automatically detected with the + * conventional semantics - If it begins with 0x the number will be parsed as a + * hexadecimal (case insensitive), if it otherwise begins with 0, it will be + * parsed as an octal number. Otherwise it will be parsed as a decimal. + * @res: Where to write the result of the conversion on success. + * + * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. + * Used as a replacement for the obsolete simple_strtoull. Return code must + * be checked. + */ +int kal_strtoul(const char *s, unsigned int base, unsigned long *res); + +/* + * scnprintf - Format a string and place it in a buffer + * @buf: The buffer to place the result into + * @size: The size of the buffer, including the trailing null space + * @fmt: The format string to use + * @...: Arguments for the format string + * + * The return value is the number of characters written into @buf not including + * the trailing '\0'. If @size is == 0 the function returns 0. + */ +int kal_scnprintf(char *buf, size_t size, const char *fmt, ...); + +void *kal_kmalloc(size_t size, enum gfp_t type); +void *kal_vmalloc(size_t size); + +void kal_kfree(void *addr); +void kal_vfree(void *addr); +/* + * kal_spin_lock_bh: lock in bottom half, os-dependent + * nic/nic_tx.c + * nic/nic_rx.c + * nic/que_mgt.c + */ +void kal_spin_lock_bh(spinlock_t *lock); +#define spin_lock_bh(_lock) kal_spin_lock_bh(_lock) + +/* + * kal_spin_unlock_bh: unlock in bottom half, os-dependent + * paired with kal_spin_lock_bh + * nic/nic_tx.c + * nic/nic_rx.c + * nic/que_mgt.c + */ +void kal_spin_unlock_bh(spinlock_t *lock); +#define spin_unlock_bh(_lock) kal_spin_unlock_bh(_lock) + +/* + * kal_spin_lock_irqsave: lock exclude irq, os-dependent + * nic/nic_tx.c + * nic/nic_rx.c + * nic/que_mgt.c + */ +void kal_spin_lock_irqsave(spinlock_t *lock, unsigned long flags); +#define spin_lock_irqsave(_lock, _flag) kal_spin_lock_irqsave(_lock, _flag) + +/* + * kal_spin_unlock_irqsave: unlock, os-dependent + * paired with kal_spin_lock_irqsave + * nic/nic_tx.c + * nic/nic_rx.c + * nic/que_mgt.c + */ +void kal_spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags); +#define spin_unlock_irqrestore(_lock, _flag) \ + kal_spin_unlock_irqrestore(_lock, _flag) +/* + * kal_skb_queue_len - get queue length + * @list_: list to measure + * Return the length of an &sk_buff queue. + * + * needed by nic_tx.c + */ +uint32_t kal_skb_queue_len(const struct sk_buff_head *list); +#define skb_queue_len(_list) kal_skb_queue_len(_list) + +/* kal_skb_queue_tail - queue a buffer at the list tail + * @list: list to use + * @newsk: buffer to queue + * Queue a buffer at the end of a list. This function takes no locks + * and you must therefore hold required locks before calling it. + * A buffer cannot be placed on two lists at the same time. + * + * needed by nic_tx.c, what's wrong with struct QUE? + */ +void kal_skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk); +#define skb_queue_tail(_list, _newsk) kal_skb_queue_tail(_list, _newsk) + +/* + * skb_put - add data to a buffer + * @skb: buffer to use + * @len: amount of data to add + * This function extends the used data area of the buffer. If this would + * exceed the total buffer size the kernel will panic. A pointer to the + * first byte of the extra data is returned. + * + * needed by nic_rx.c + */ +unsigned char *kal_skb_put(struct sk_buff *skb, unsigned int len); +#define skb_put(_skb, _len) kal_skb_put(_skb, _len) + +/* + * kal_skb_push - add data to the start of a buffer + * @skb: buffer to use + * @len: amount of data to add + * This function extends the used data area of the buffer at the buffer + * start. If this would exceed the total buffer headroom the kernel will + * panic. A pointer to the first byte of the extra data is returned. + * + * needed by nic_tx.c + */ +void *kal_skb_push(struct sk_buff *skb, unsigned int len); +#define skb_push(_skb, _len) kal_skb_push(_skb, _len) + +/* + * needed by nic_tx.c + * __skb_dequeue - remove from the head of the queue + * @list: list to dequeue from + * + * Remove the head of the list. This function does not take any locks + * so must be used with appropriate locks held only. The head item is + * returned or %NULL if the list is empty. + */ +struct sk_buff *kal_skb_dequeue_tail(struct sk_buff_head *list); +#define skb_dequeue(_list) kal_skb_dequeue_tail(_list) + +/* + * needed by nic_tx.c, what's wrong with struct QUE? + * __skb_queue_head - queue a buffer at the list head + * @list: list to use + * @newsk: buffer to queue + * + * Queue a buffer at the start of a list. This function takes no locks + * and you must therefore hold required locks before calling it. + * + * A buffer cannot be placed on two lists at the same time. + */ +void kal_skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk); +#define skb_queue_head(_list, _newsk) kal_skb_queue_head(_list, _newsk) + +/* + * needed by nic_rx.c + * make the tail pointer in skb point to beginning of data + */ +void kal_skb_reset_tail_pointer(struct sk_buff *skb); +#define skb_reset_tail_pointer(_skb) kal_skb_reset_tail_pointer(_skb) + +/* + * needed by nic_rx.c + * remove end from a buffer + * @len: len of skb after trim + */ +void kal_skb_trim(struct sk_buff *skb, unsigned int len); +#define skb_trim(_skb, _len) kal_skb_trim(_skb, _len) + +/* + * needed by mgmt/tkip_mic.c + * legacy helper around netdev_alloc_skb() + */ +struct sk_buff *kal_dev_alloc_skb(unsigned int length); +#define dev_alloc_skb(_length) kal_dev_alloc_skb(_length) + +/* needed by mgmt/tkip_mic.c */ +void kal_kfree_skb(struct sk_buff *skb); +#define kfree_skb(_skb) kal_kfree_skb(_skb) + +/**************************************************************************** + * TODO: Functions need implementation + **************************************************************************** + */ +/* needed by + * common/debug.c + * common/wlan_lib.c + * mgmt/stats.c + * ais_fsm.c + */ +#define kal_sched_clock() KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#define sched_clock() kal_sched_clock() + +/* looks like min/max not in C + * https://stackoverflow.com/questions/3437404/min-and-max-in-c + * needed by: + * common/debug.c + * mgmt/scan.c + */ +#define min(_a, _b) KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + + +/* needed by mgmt/stats.c */ +#define rtc_time_to_tm(_time, _tm) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +/* implemented: os/linux/gl_wext.c + * used: common/wlan_oid.c, wlanoidSetWapiAssocInfo + * why function called "search WPAIIE" has been implement under wext + * first used in wext_get_scan. Should it be part of wlan_oid? + */ +#if CFG_SUPPORT_WAPI +#define wextSrchDesiredWAPIIE(_pucIEStart, _i4TotalIeLen, \ + _ppucDesiredIE) KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#endif + +/* common/wlan_lib.c */ +#define netdev_priv(_ndev) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _ndev) + +/* + * needed by + * mgmt/rlm_domain.c + * nic/nic_cmd_event.c + */ +#define priv_to_wiphy(_priv) \ +((void *) KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _priv)) + + +/* needed by mgmt/rlm_domain.c + * implementation in linux is in gl_cfg80211.c + * while other operating system may also need to notify reg change + */ +#define mtk_reg_notify(_pWiphy, _pRequest) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +/* needed by mgmt/rlm_domain.c */ +#define regulatory_hint(_wiphy, _alpha2) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +/* needed by mgmt/tdls.c */ +#define cfg80211_tdls_oper_request(_dev, _peer, _oper, \ + _reason_code, _gfp) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +/* + * needed by + * mgmt/p2p_func.c + * + * cfg80211_ch_switch_notify - update wdev channel and notify userspace + * @dev: the device which switched channels + * @chandef: the new channel definition + * + * Caller must acquire wdev_lock, therefore must only be called from sleepable + * driver context! + */ +#define cfg80211_ch_switch_notify(_dev, _chandef) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +/* + * needed by mgmt/rlm.c + */ +#define get_random_bytes(_buf, _nbytes) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +/* + * needed by: nic/nic_cmd_event.c + * 0: no error !0: error + * defeined in include/linux/err.h + */ +#define IS_ERR(_ptr) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +/* + * os endian related, need to find corresponding API in OS + * eg. + * #if __BYTE_ORDER == __BIG_ENDIAN + * #define cpu_to_le16 bswap_16 + * #else + * #define cpu_to_le16 + * #endif + */ +#define cpu_to_le16(_val) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define cpu_to_le32(_val) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define cpu_to_le64(_val) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define le16_to_cpu(_val) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#define le32_to_cpu(_val) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#define le64_to_cpu(_val) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define div_u64(_val, _div) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +int kal_test_and_clear_bit(unsigned long bit, unsigned long *p); +#ifndef test_and_clear_bit +#define test_and_clear_bit(_offset, _val) \ + kal_test_and_clear_bit(_offset, _val) +#endif + +void kal_clear_bit(unsigned long bit, unsigned long *p); +#ifndef clear_bit +#define clear_bit(_offset, _val) kal_clear_bit(_offset, _val) +#endif + +/* + * kal_set_bit: set bit atomically + * @nr: bit to set + * @addr: addr to set bit + */ +void kal_set_bit(unsigned long bit, unsigned long *p); +#ifndef set_bit +#define set_bit(_offset, _val) kal_set_bit(_offset, _val) +#endif + +/* needed by mgmt/scan.c */ +int kal_test_bit(unsigned long bit, unsigned long *p); +#ifndef test_bit +#define test_bit(_offset, _val) kal_test_bit(_offset, _val) +#endif +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_kal.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_kal.h new file mode 100644 index 0000000000000..ef723081e851f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_kal.h @@ -0,0 +1,1978 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: /os/linux/include/gl_kal.h + */ + +/*! \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. + */ + +#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_os.h" +#include "gl_typedef.h" +#include "gl_wext_priv.h" +#include "link_drv.h" +#include "nic/mac.h" +#include "nic/wlan_def.h" +#include "wlan_lib.h" +#include "wlan_oid.h" + +#if CFG_ENABLE_BT_OVER_WIFI +#include "nic/bow.h" +#endif + +#if DBG +extern int allocatedMemSize; +#endif + +extern int g_u4HaltFlag; +extern int g_u4WlanInitFlag; + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +/* Define how many concurrent operation networks. */ +#define KAL_BSS_NUM 4 + +#define KAL_AIS_NUM 1 + +#if CFG_DUAL_P2PLIKE_INTERFACE +#define KAL_P2P_NUM 2 +#else +#define KAL_P2P_NUM 1 +#endif + +/* Threading */ +#if CFG_SUPPORT_MULTITHREAD +#define GLUE_FLAG_MAIN_PROCESS \ + (GLUE_FLAG_HALT | GLUE_FLAG_SUB_MOD_MULTICAST | \ + GLUE_FLAG_TX_CMD_DONE | GLUE_FLAG_TXREQ | GLUE_FLAG_TIMEOUT | \ + GLUE_FLAG_FRAME_FILTER | GLUE_FLAG_OID | GLUE_FLAG_RX) + +#define GLUE_FLAG_HIF_PROCESS \ + (GLUE_FLAG_HALT | GLUE_FLAG_INT | GLUE_FLAG_HIF_TX | \ + GLUE_FLAG_HIF_TX_CMD | GLUE_FLAG_HIF_FW_OWN | \ + GLUE_FLAG_HIF_PRT_HIF_DBG_INFO | \ + GLUE_FLAG_UPDATE_WMM_QUOTA) + +#define GLUE_FLAG_RX_PROCESS (GLUE_FLAG_HALT | GLUE_FLAG_RX_TO_OS) +#else +/* All flags for single thread driver */ +#define GLUE_FLAG_TX_PROCESS 0xFFFFFFFF +#endif + +#if CFG_SUPPORT_SNIFFER +#define RADIOTAP_FIELD_TSFT BIT(0) +#define RADIOTAP_FIELD_FLAGS BIT(1) +#define RADIOTAP_FIELD_RATE BIT(2) +#define RADIOTAP_FIELD_CHANNEL BIT(3) +#define RADIOTAP_FIELD_ANT_SIGNAL BIT(5) +#define RADIOTAP_FIELD_ANT_NOISE BIT(6) +#define RADIOTAP_FIELD_ANT BIT(11) +#define RADIOTAP_FIELD_MCS BIT(19) +#define RADIOTAP_FIELD_AMPDU BIT(20) +#define RADIOTAP_FIELD_VHT BIT(21) +#define RADIOTAP_FIELD_VENDOR BIT(30) + +#define RADIOTAP_LEN_VHT 48 +#define RADIOTAP_FIELDS_VHT (RADIOTAP_FIELD_TSFT | \ + RADIOTAP_FIELD_FLAGS | \ + RADIOTAP_FIELD_RATE | \ + RADIOTAP_FIELD_CHANNEL | \ + RADIOTAP_FIELD_ANT_SIGNAL | \ + RADIOTAP_FIELD_ANT_NOISE | \ + RADIOTAP_FIELD_ANT | \ + RADIOTAP_FIELD_AMPDU | \ + RADIOTAP_FIELD_VHT | \ + RADIOTAP_FIELD_VENDOR) + +#define RADIOTAP_LEN_HT 36 +#define RADIOTAP_FIELDS_HT (RADIOTAP_FIELD_TSFT | \ + RADIOTAP_FIELD_FLAGS | \ + RADIOTAP_FIELD_RATE | \ + RADIOTAP_FIELD_CHANNEL | \ + RADIOTAP_FIELD_ANT_SIGNAL | \ + RADIOTAP_FIELD_ANT_NOISE | \ + RADIOTAP_FIELD_ANT | \ + RADIOTAP_FIELD_MCS | \ + RADIOTAP_FIELD_AMPDU | \ + RADIOTAP_FIELD_VENDOR) + +#define RADIOTAP_LEN_LEGACY 26 +#define RADIOTAP_FIELDS_LEGACY (RADIOTAP_FIELD_TSFT | \ + RADIOTAP_FIELD_FLAGS | \ + RADIOTAP_FIELD_RATE | \ + RADIOTAP_FIELD_CHANNEL | \ + RADIOTAP_FIELD_ANT_SIGNAL | \ + RADIOTAP_FIELD_ANT_NOISE | \ + RADIOTAP_FIELD_ANT | \ + RADIOTAP_FIELD_VENDOR) +#endif + +/* performance monitor feature */ +#define PERF_MON_INIT_BIT (0) +#define PERF_MON_DISABLE_BIT (1) +#define PERF_MON_STOP_BIT (2) +#define PERF_MON_RUNNING_BIT (3) + +#define PERF_MON_UPDATE_INTERVAL (1000) +#define PERF_MON_TP_MAX_THRESHOLD (10) + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +/* Lock for process */ +enum ENUM_SPIN_LOCK_CATEGORY_E { + SPIN_LOCK_FSM = 0, + +#if CFG_SUPPORT_MULTITHREAD + SPIN_LOCK_TX_PORT_QUE, + SPIN_LOCK_TX_CMD_QUE, + SPIN_LOCK_TX_CMD_DONE_QUE, + SPIN_LOCK_TC_RESOURCE, + SPIN_LOCK_RX_TO_OS_QUE, +#endif + + /* FIX ME */ + SPIN_LOCK_RX_QUE, + SPIN_LOCK_RX_FREE_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, + /* TX/RX Direct : BEGIN */ + SPIN_LOCK_TX_DIRECT, + SPIN_LOCK_RX_DIRECT, + SPIN_LOCK_RX_DIRECT_REORDER, + /* TX/RX Direct : END */ + SPIN_LOCK_IO_REQ, + SPIN_LOCK_INT, + SPIN_LOCK_UPDATE_WMM_QUOTA, + + 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 ENUM_MUTEX_CATEGORY_E { + MUTEX_TX_CMD_CLEAR, + MUTEX_TX_DATA_DONE_QUE, + MUTEX_DEL_INF, + MUTEX_CHIP_RST, + MUTEX_SET_OWN, + MUTEX_BOOST_CPU, + MUTEX_NUM +}; + +/* event for assoc information update */ +struct EVENT_ASSOC_INFO { + uint8_t ucAssocReq; /* 1 for assoc req, 0 for assoc rsp */ + uint8_t ucReassoc; /* 0 for assoc, 1 for reassoc */ + uint16_t u2Length; + uint8_t *pucIe; +}; + +/* network type */ +enum ENUM_KAL_NETWORK_TYPE_INDEX { + 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 +}; + +/* malloc type */ +enum ENUM_KAL_MEM_ALLOCATION_TYPE_E { + PHY_MEM_TYPE, /* physically continuous */ + VIR_MEM_TYPE, /* virtually continuous */ + MEM_TYPE_NUM +}; + +/* suspend/resume related */ +#define KAL_WAKE_LOCK_T uint32_t + +/* TODO: unknown feature */ +#if CFG_SUPPORT_AGPS_ASSIST +enum ENUM_MTK_AGPS_ATTR { + MTK_ATTR_AGPS_INVALID, + MTK_ATTR_AGPS_CMD, + MTK_ATTR_AGPS_DATA, + MTK_ATTR_AGPS_IFINDEX, + MTK_ATTR_AGPS_IFNAME, + MTK_ATTR_AGPS_MAX +}; + +enum ENUM_AGPS_EVENT { + AGPS_EVENT_WLAN_ON, + AGPS_EVENT_WLAN_OFF, + AGPS_EVENT_WLAN_AP_LIST, +}; +u_int8_t kalIndicateAgpsNotify(struct ADAPTER *prAdapter, + uint8_t cmd, + uint8_t *data, uint16_t dataLen); +#endif /* CFG_SUPPORT_AGPS_ASSIST */ + +#if CFG_SUPPORT_SNIFFER +/* Vendor Namespace + * Bit Number 30 + * Required Alignment 2 bytes + */ +struct RADIOTAP_FIELD_VENDOR_ { + uint8_t aucOUI[3]; + uint8_t ucSubNamespace; + uint16_t u2DataLen; + uint8_t ucData; +} __KAL_ATTRIB_PACKED__; + +struct MONITOR_RADIOTAP { + /* radiotap header */ + uint8_t ucItVersion; /* set to 0 */ + uint8_t ucItPad; + uint16_t u2ItLen; /* entire length */ + uint32_t u4ItPresent; /* fields present */ + + /* TSFT + * Bit Number 0 + * Required Alignment 8 bytes + * Unit microseconds + */ + uint64_t u8MacTime; + + /* Flags + * Bit Number 1 + */ + uint8_t ucFlags; + + /* Rate + * Bit Number 2 + * Unit 500 Kbps + */ + uint8_t ucRate; + + /* Channel + * Bit Number 3 + * Required Alignment 2 bytes + */ + uint16_t u2ChFrequency; + uint16_t u2ChFlags; + + /* Antenna signal + * Bit Number 5 + * Unit dBm + */ + uint8_t ucAntennaSignal; + + /* Antenna noise + * Bit Number 6 + * Unit dBm + */ + uint8_t ucAntennaNoise; + + /* Antenna + * Bit Number 11 + * Unit antenna index + */ + uint8_t ucAntenna; + + /* MCS + * Bit Number 19 + * Required Alignment 1 byte + */ + uint8_t ucMcsKnown; + uint8_t ucMcsFlags; + uint8_t ucMcsMcs; + + /* A-MPDU status + * Bit Number 20 + * Required Alignment 4 bytes + */ + uint32_t u4AmpduRefNum; + uint16_t u2AmpduFlags; + uint8_t ucAmpduDelimiterCRC; + uint8_t ucAmpduReserved; + + /* VHT + * Bit Number 21 + * Required Alignment 2 bytes + */ + uint16_t u2VhtKnown; + uint8_t ucVhtFlags; + uint8_t ucVhtBandwidth; + uint8_t aucVhtMcsNss[4]; + uint8_t ucVhtCoding; + uint8_t ucVhtGroupId; + uint16_t u2VhtPartialAid; + + /* extension space */ + uint8_t aucReserve[12]; +} __KAL_ATTRIB_PACKED__; +#endif + +/* driver halt */ +struct KAL_HALT_CTRL_T { +/* TODO: os-related */ +#if 0 + struct semaphore lock; + struct task_struct *owner; +#endif + u_int8_t fgHalt; + u_int8_t fgHeldByKalIoctl; + OS_SYSTIME u4HoldStart; +}; + +struct KAL_THREAD_SCHEDSTATS { + /* when marked: the profiling start time(ms), + * when unmarked: total duration(ms) + */ + unsigned long long time; + /* time spent in exec (sum_exec_runtime) */ + unsigned long long exec; + /* time spent in run-queue while not being scheduled (wait_sum) */ + unsigned long long runnable; + /* time spent waiting for I/O (iowait_sum) */ + unsigned long long iowait; +}; + +enum ENUM_CMD_TX_RESULT { + CMD_TX_RESULT_SUCCESS, + CMD_TX_RESULT_FAILED, + CMD_TX_RESULT_QUEUED, + CMD_TX_RESULT_NUM +}; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +/* os-related: need implementation */ +#define KAL_SET_BIT(bitOffset, value) set_bit(bitOffset, &value) +#define KAL_CLR_BIT(bitOffset, value) clear_bit(bitOffset, &value) +#define KAL_TEST_AND_CLEAR_BIT(bitOffset, value) \ + test_and_clear_bit(bitOffset, &value) +#define KAL_TEST_BIT(bitOffset, value) test_bit(bitOffset, &value) +#define SUSPEND_FLAG_FOR_WAKEUP_REASON (0) +#define SUSPEND_FLAG_CLEAR_WHEN_RESUME (1) + + +/*----------------------------------------------------------------------------*/ +/* Macros of getting current thread id */ +/*----------------------------------------------------------------------------*/ +/* TODO: os-related: need implementation */ +#define KAL_GET_CURRENT_THREAD_ID() (0) +#define KAL_GET_CURRENT_THREAD_NAME() ("n/a") + +/*----------------------------------------------------------------------------*/ +/* Macros of SPIN LOCK operations for using in Driver Layer */ +/*----------------------------------------------------------------------------*/ +#define KAL_SPIN_LOCK_DECLARATION() unsigned long __ulFlags + +#define KAL_ACQUIRE_SPIN_LOCK(_prAdapter, _rLockCategory) \ + kalAcquireSpinLock(((struct ADAPTER *)_prAdapter)->prGlueInfo, \ + _rLockCategory, &__ulFlags) + +#define KAL_RELEASE_SPIN_LOCK(_prAdapter, _rLockCategory) \ + kalReleaseSpinLock(((struct ADAPTER *)_prAdapter)->prGlueInfo, \ + _rLockCategory, __ulFlags) + +/*----------------------------------------------------------------------------*/ +/* Macros of MUTEX operations for using in Driver Layer */ +/*----------------------------------------------------------------------------*/ +#define KAL_ACQUIRE_MUTEX(_prAdapter, _rLockCategory) \ + kalAcquireMutex(((struct ADAPTER *)_prAdapter)->prGlueInfo, \ + _rLockCategory) + +#define KAL_RELEASE_MUTEX(_prAdapter, _rLockCategory) \ + kalReleaseMutex(((struct ADAPTER *)_prAdapter)->prGlueInfo, \ + _rLockCategory) + +/*----------------------------------------------------------------------------*/ +/* 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 for kernel related defines */ +/*----------------------------------------------------------------------------*/ +/* TODO: os-related: need implementation */ +#define IEEE80211_CHAN_PASSIVE_FLAG (0) +#define IEEE80211_CHAN_PASSIVE_STR "PASSIVE" + +/** + * enum nl80211_band - Frequency band + * @NL80211_BAND_2GHZ: 2.4 GHz ISM band + * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz) + * @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 64.80 GHz) + * @NUM_NL80211_BANDS: number of bands, avoid using this in userspace + * since newer kernel versions may support more bands + */ +#define KAL_BAND_2GHZ (0) +#define KAL_BAND_5GHZ (1) +#define KAL_NUM_BANDS (2) + +/** + * enum nl80211_reg_rule_flags - regulatory rule flags + * @NL80211_RRF_NO_OFDM: OFDM modulation not allowed + * @NL80211_RRF_AUTO_BW: maximum available bandwidth should be calculated + * base on contiguous rules and wider channels will be allowed to cross + * multiple contiguous/overlapping frequency ranges. + * @NL80211_RRF_DFS: DFS support is required to be used + */ +#define KAL_RRF_NO_OFDM (0) +#define KAL_RRF_DFS (1) +#define KAL_RRF_AUTO_BW 0 + +/** + * kalCfg80211ScanDone - abstraction of cfg80211_scan_done + * + * @request: the corresponding scan request (sanity checked by callers!) + * @aborted: set to true if the scan was aborted for any reason, + * userspace will be notified of that + * + * Since linux-4.8.y the 2nd parameter is changed from bool to + * struct cfg80211_scan_info, but we don't use all fields yet. + */ +#define kalCfg80211ScanDone(_request, aborted) + +/* Consider on some Android platform, using request_firmware_direct() + * may cause system failed to load firmware. So we still use + * request_firmware(). + */ +#define REQUEST_FIRMWARE(_fw, _name, _dev) + +/*----------------------------------------------------------------------------*/ +/* Macros of wake_lock operations for using in Driver Layer */ +/*----------------------------------------------------------------------------*/ +#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) +#define KAL_WAKE_LOCK_ACTIVE(_prAdapter, _prWakeLock) + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Cache memory allocation + * + * \param[in] u4Size Required memory size. + * \param[in] eMemType Memory allocation type + * + * \return Pointer to allocated memory + * or NULL + */ +/*----------------------------------------------------------------------------*/ +#define kmalloc(_size, _type) kal_kmalloc(_size, _type) +#define vmalloc(_size) kal_vmalloc(_size) +#define in_interrupt() (FALSE) +#define kfree(_addr) kal_kfree(_addr) +#define vfree(_addr) kal_vfree(_addr) + +#if DBG +#define kalMemAlloc(u4Size, eMemType) ({ \ + void *pvAddr; \ + if (eMemType == PHY_MEM_TYPE) { \ + if (in_interrupt()) \ + pvAddr = kmalloc(u4Size, GFP_ATOMIC); \ + else \ + pvAddr = kmalloc(u4Size, GFP_KERNEL); \ + } \ + else { \ + pvAddr = vmalloc(u4Size); \ + } \ + if (pvAddr) { \ + allocatedMemSize += u4Size; \ + DBGLOG(INIT, INFO, "0x%p(%ld) allocated (%s:%s)\n", \ + pvAddr, (uint32_t)u4Size, __FILE__, __func__); \ + } \ + pvAddr; \ +}) +#else +#define kalMemAlloc(u4Size, eMemType) ({ \ + void *pvAddr; \ + if (eMemType == PHY_MEM_TYPE) { \ + if (in_interrupt()) \ + pvAddr = kmalloc(u4Size, GFP_ATOMIC); \ + else \ + pvAddr = kmalloc(u4Size, GFP_KERNEL); \ + } \ + else { \ + pvAddr = vmalloc(u4Size); \ + } \ + if (!pvAddr) \ + ASSERT_NOMEM(); \ + pvAddr; \ +}) +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Free allocated cache memory + * + * \param[in] pvAddr Required memory size. + * \param[in] eMemType Memory allocation type + * \param[in] u4Size Allocated memory size. + * + * \return - + */ +/*----------------------------------------------------------------------------*/ +#if DBG +#define kalMemFree(pvAddr, eMemType, u4Size) \ +{ \ + if (pvAddr) { \ + allocatedMemSize -= u4Size; \ + DBGLOG(INIT, INFO, "0x%p(%ld) freed (%s:%s)\n", \ + pvAddr, (uint32_t)u4Size, __FILE__, __func__); \ + } \ + if (eMemType == PHY_MEM_TYPE) { \ + kfree(pvAddr); \ + } \ + else { \ + vfree(pvAddr); \ + } \ +} +#else +#define kalMemFree(pvAddr, eMemType, u4Size) \ +{ \ + if (eMemType == PHY_MEM_TYPE) { \ + kfree(pvAddr); \ + } \ + else { \ + vfree(pvAddr); \ + } \ +} +#endif + +#define kalUdelay(u4USec) KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#define kalMdelay(u4MSec) KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#define kalMsleep(u4MSec) KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#define kalUsleep_range(u4MinUSec, u4MaxUSec) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +/* Copy memory from user space to kernel space */ +#define kalMemCopyFromUser(_pvTo, _pvFrom, _u4N) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +/* Copy memory from kernel space to user space */ +#define kalMemCopyToUser(_pvTo, _pvFrom, _u4N) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +/* 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) + +/* Move memory block with specific size */ +#define kalMemMove(pvDst, pvSrc, u4Size) \ + memmove(pvDst, pvSrc, u4Size) + +#define strnicmp(s1, s2, n) KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +/* string operation */ +#define kalStrCpy(dest, src) strcpy(dest, src) +#define kalStrnCpy(dest, src, n) strncpy(dest, src, n) +#define kalStrCmp(ct, cs) strcmp(ct, cs) +#define kalStrnCmp(ct, cs, n) strncmp(ct, cs, n) +#define kalStrChr(s, c) strchr(s, c) +#define kalStrrChr(s, c) strrchr(s, c) +#define kalStrnChr(s, n, c) strnchr(s, n, c) +#define kalStrLen(s) strlen(s) +#define kalStrnLen(s, b) strnlen(s, b) +#define kalStrniCmp(ct, cs, n) strncasecmp(ct, cs, n) +/* #define kalStrtoul(cp, endp, base) simple_strtoul(cp, endp, base) */ +/* #define kalStrtol(cp, endp, base) simple_strtol(cp, endp, base) */ +#define kalkStrtou8(cp, base, resp) kal_strtou8(cp, base, resp) +#define kalkStrtou16(cp, base, resp) kal_strtou16(cp, base, resp) +#define kalkStrtou32(cp, base, resp) kal_strtou32(cp, base, resp) +#define kalkStrtos32(cp, base, resp) kal_strtos32(cp, base, resp) +#define kalSnprintf(buf, size, fmt, ...) \ + snprintf(buf, size, fmt, ##__VA_ARGS__) +#define kalScnprintf(buf, size, fmt, ...) \ + kal_scnprintf(buf, size, fmt, ##__VA_ARGS__) +#define kalSprintf(buf, fmt, ...) sprintf(buf, fmt, __VA_ARGS__) +/* remove for AOSP */ +/* #define kalSScanf(buf, fmt, ...) sscanf(buf, fmt, __VA_ARGS__) */ +#define kalStrStr(ct, cs) strstr(ct, cs) +#define kalStrSep(s, ct) strsep(s, ct) +#define kalStrCat(dest, src) strcat(dest, src) +#define kalIsXdigit(c) isxdigit(c) +#define kalStrtoint(_data, _base, _res) kal_strtoint(_data, _base, _res) +#define kalStrtoul(_data, _base, _res) kal_strtoul(_data, _base, _res) +#define kalStrtokR(_buf, _tok, _saved) \ + strtok_r((char *)_buf, _tok, (char **)_saved) +/* implementation for no op API */ +int8_t kal_atoi(uint8_t ch); +#define kalAtoi(_ch) KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +/* 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) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +/*----------------------------------------------------------------------------*/ +/*! + * \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) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +/*----------------------------------------------------------------------------*/ +/*! + * \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) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define kalGetTimeTick() KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define WLAN_TAG "[wlan]" +#define kalPrint(_Fmt...) printf(WLAN_TAG _Fmt) +#define kalPrintLimited(_Fmt...) printf(WLAN_TAG _Fmt) + +#define kalBreakPoint() \ +do { \ + DBGLOG(INIT, ERROR, "WARN_ON()"); \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__); \ +} while (0) + +#if CFG_ENABLE_AEE_MSG +#else +#define kalSendAeeException(_module, _desc, ...) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#define kalSendAeeWarning(_module, _desc, ...) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#define kalSendAeeReminding(_module, _desc, ...) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#endif + +#define PRINTF_ARG(...) __VA_ARGS__ +#define SPRINTF(buf, arg) {buf += sprintf((char *)(buf), PRINTF_ARG arg); } + +#define USEC_TO_SYSTIME(_usec) ((_usec) / USEC_PER_MSEC) +#define MSEC_TO_SYSTIME(_msec) (_msec) + +#define MSEC_TO_JIFFIES(_msec) KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define KAL_TIME_INTERVAL_DECLARATION() uint32_t timeval __rTs, __rTe +#define KAL_REC_TIME_START() do_gettimeofday(&__rTs) +#define KAL_REC_TIME_END() do_gettimeofday(&__rTe) +#define KAL_GET_TIME_INTERVAL() \ + ((SEC_TO_USEC(__rTe.tv_sec) + __rTe.tv_usec) - \ + (SEC_TO_USEC(__rTs.tv_sec) + __rTs.tv_usec)) +#define KAL_ADD_TIME_INTERVAL(_Interval) \ + { \ + (_Interval) += KAL_GET_TIME_INTERVAL(); \ + } + +/* TODO: os-related HIF should we move to os/xxx/hif/include? */ +#if defined(_HIF_PCIE) +#define KAL_DMA_TO_DEVICE PCI_DMA_TODEVICE +#define KAL_DMA_FROM_DEVICE PCI_DMA_FROMDEVICE + +#define KAL_DMA_ALLOC_COHERENT(_dev, _size, _handle) \ +KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define KAL_DMA_FREE_COHERENT(_dev, _size, _addr, _handle) \ +KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define KAL_DMA_MAP_SINGLE(_dev, _ptr, _size, _dir) \ +KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define KAL_DMA_UNMAP_SINGLE(_dev, _addr, _size, _dir) \ +KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define KAL_DMA_MAPPING_ERROR(_dev, _addr) \ +KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#else +#define KAL_DMA_TO_DEVICE DMA_TO_DEVICE +#define KAL_DMA_FROM_DEVICE DMA_FROM_DEVICE + +#define KAL_DMA_ALLOC_COHERENT(_dev, _size, _handle) \ +KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define KAL_DMA_FREE_COHERENT(_dev, _size, _addr, _handle) \ +KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define KAL_DMA_MAP_SINGLE(_dev, _ptr, _size, _dir) \ +KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define KAL_DMA_UNMAP_SINGLE(_dev, _addr, _size, _dir) \ +KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define KAL_DMA_MAPPING_ERROR(_dev, _addr) \ +KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#endif + +#if defined(_HIF_AXI) +#define KAL_ARCH_SETUP_DMA_OPS(_dev, _base, _size, _iommu, _coherent) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#else +#define KAL_ARCH_SETUP_DMA_OPS(_dev, _base, _size, _iommu, _coherent) +#endif + +/*----------------------------------------------------------------------------*/ +/* Macros of show stack operations for using in Driver Layer */ +/*----------------------------------------------------------------------------*/ +#define kal_show_stack(_adapter, _task, _sp) + +/*----------------------------------------------------------------------------*/ +/* Macros of systrace operations for using in Driver Layer */ +/*----------------------------------------------------------------------------*/ +#define kalTraceBegin(_fmt, ...) +#define kalTraceEnd() +#define kalTraceInt(_value, _fmt, ...) +#define kalTraceCall() +#define kalTraceEvent(_fmt, ...) +#define TRACE(_expr, _fmt, ...) _expr + +/******************************************************************************* + * 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 */ +/*----------------------------------------------------------------------------*/ +#ifdef CFG_REMIND_IMPLEMENT +#define kalAcquireSpinLock(_pr, _rLockCate, _plFlags) \ +KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _pr, _rLockCate, _plFlags) + +#define kalReleaseSpinLock(_prGlueInfo, _rLockCategory, _ulFlags) \ +KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalUpdateMACAddress(_prGlueInfo, _pucMacAddr) \ +KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo, _pucMacAddr) + +#define kalAcquireMutex(_prGlueInfo, _rMutexCategory) \ +KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo, _rMutexCategory) + +#define kalReleaseMutex(_prGlueInfo, _rMutexCategory) \ +KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo, _rMutexCategory) + +#define kalPacketFree(_prGlueInfo, _pvPacket) \ +KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo, _pvPacket) + +#define kalPacketAlloc(_prGlueInfo, _u4Size, _ppucData) \ +((void *) KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo)) + +#define kalPacketAllocWithHeadroom(_prGlueInfo, _u4Size, _ppucData) \ +((void *) KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo)) +#else +void kalAcquireSpinLock(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, + OUT unsigned long *plFlags); + +void kalReleaseSpinLock(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, + IN unsigned long ulFlags); + +void kalUpdateMACAddress(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucMacAddr); + +void kalAcquireMutex(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_MUTEX_CATEGORY_E rMutexCategory); + +void kalReleaseMutex(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_MUTEX_CATEGORY_E rMutexCategory); + +void kalPacketFree(IN struct GLUE_INFO *prGlueInfo, + IN void *pvPacket); + +void *kalPacketAlloc(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Size, + OUT uint8_t **ppucData); + +void *kalPacketAllocWithHeadroom(IN struct GLUE_INFO + *prGlueInfo, + IN uint32_t u4Size, OUT uint8_t **ppucData); +#endif + +void kalOsTimerInitialize(IN struct GLUE_INFO *prGlueInfo, + IN void *prTimerHandler); + +u_int8_t kalSetTimer(IN struct GLUE_INFO *prGlueInfo, + IN OS_SYSTIME rInterval); + +#ifdef CFG_REMIND_IMPLEMENT +#define kalProcessRxPacket(_prGlueInfo, _pvPacket, _pucPacketStart, \ + _u4PacketLen, _fgIsRetain, _aeCSUM) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) +#else +uint32_t +kalProcessRxPacket(IN struct GLUE_INFO *prGlueInfo, + IN void *pvPacket, + IN uint8_t *pucPacketStart, IN uint32_t u4PacketLen, + /* IN PBOOLEAN pfgIsRetain, */ + IN u_int8_t fgIsRetain, IN enum ENUM_CSUM_RESULT aeCSUM[]); +#endif + +uint32_t kalRxIndicatePkts(IN struct GLUE_INFO *prGlueInfo, + IN void *apvPkts[], + IN uint8_t ucPktNum); + +#ifdef CFG_REMIND_IMPLEMENT +#define kalRxIndicateOnePkt(_prGlueInfo, _pvPkt) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define kalIndicateStatusAndComplete(_prGlInfo, _eStatus, _pvBuf, _u4BufLen, \ + _ucBssIndex) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define kalUpdateReAssocReqInfo(_prGlueInfo, _pucFrameBody, _u4FrameBodyLen, \ + _fgReassocRequest, _ucBssIndex) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define kalUpdateReAssocRspInfo(_prGlueInfo, _pucFrameBody, _u4FrameBodyLen, \ + _ucBssIndex) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#else +uint32_t kalRxIndicateOnePkt(IN struct GLUE_INFO + *prGlueInfo, IN void *pvPkt); + +void +kalIndicateStatusAndComplete(IN struct GLUE_INFO + *prGlueInfo, + IN uint32_t eStatus, IN void *pvBuf, + IN uint32_t u4BufLen, + IN uint8_t ucBssIndex); + +void +kalUpdateReAssocReqInfo(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucFrameBody, IN uint32_t u4FrameBodyLen, + IN u_int8_t fgReassocRequest, + IN uint8_t ucBssIndex); + +void kalUpdateReAssocRspInfo(IN struct GLUE_INFO + *prGlueInfo, + IN uint8_t *pucFrameBody, + IN uint32_t u4FrameBodyLen, + IN uint8_t ucBssIndex); +#endif + +#if CFG_TX_FRAGMENT +u_int8_t +kalQueryTxPacketHeader(IN struct GLUE_INFO *prGlueInfo, + IN void *pvPacket, OUT uint16_t *pu2EtherTypeLen, + OUT uint8_t *pucEthDestAddr); +#endif /* CFG_TX_FRAGMENT */ + +#ifdef CFG_REMIND_IMPLEMENT +#define kalSendCompleteAndAwakeQueue(_prGlueInfo, _pvPacket) \ +KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo, _pvPacket) +#else +void kalSendCompleteAndAwakeQueue(IN struct GLUE_INFO + *prGlueInfo, + IN void *pvPacket); +#endif + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +#ifdef CFG_REMIND_IMPLEMENT +#define kalQueryTxChksumOffloadParam(_pvPacket, _pucFlag) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#else +void kalQueryTxChksumOffloadParam(IN void *pvPacket, + OUT uint8_t *pucFlag); +#endif + +void kalUpdateRxCSUMOffloadParam(IN void *pvPacket, + IN enum ENUM_CSUM_RESULT eCSUM[]); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +#ifdef CFG_REMIND_IMPLEMENT +#define kalRetrieveNetworkAddress(_prGlueInfo, _prMacAddr) \ +KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo, _prMacAddr) + +#define kalReadyOnChannel(_prGlueInfo, _u8Cookie, _eBand, _eSco, \ + _ucChannelNum, _u4DurationMs, _ucBssIndex) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalRemainOnChannelExpired(_prGlueInfo, _u8Cookie, _eBand, \ + _eSco, _ucChannelNum, _ucBssIndex) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#if CFG_SUPPORT_DFS +#define kalIndicateChannelSwitch(_prGlueInfo, _eSco, _ucChannelNum) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) +#endif + + +#define kalIndicateMgmtTxStatus(_prGlueInfo, _u8Cookie, _fgIsAck, \ + _pucFrameBuf, _u4FrameLen, _ucBssIndex) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalIndicateRxMgmtFrame(_prGlueInfo, _prSwRfb, _ucBssIndex) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) +#else +u_int8_t kalRetrieveNetworkAddress(IN struct GLUE_INFO *prGlueInfo, + IN OUT uint8_t *prMacAddr); + +void +kalReadyOnChannel(IN struct GLUE_INFO *prGlueInfo, + IN uint64_t u8Cookie, + IN enum ENUM_BAND eBand, IN enum ENUM_CHNL_EXT eSco, + IN uint8_t ucChannelNum, IN uint32_t u4DurationMs, + IN uint8_t ucBssIndex); + +void +kalRemainOnChannelExpired(IN struct GLUE_INFO *prGlueInfo, + IN uint64_t u8Cookie, IN enum ENUM_BAND eBand, + IN enum ENUM_CHNL_EXT eSco, IN uint8_t ucChannelNum, + IN uint8_t ucBssIndex); + +#if CFG_SUPPORT_DFS +void +kalIndicateChannelSwitch(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_CHNL_EXT eSco, + IN uint8_t ucChannelNum); +#endif + +void +kalIndicateMgmtTxStatus(IN struct GLUE_INFO *prGlueInfo, + IN uint64_t u8Cookie, IN u_int8_t fgIsAck, + IN uint8_t *pucFrameBuf, IN uint32_t u4FrameLen, + IN uint8_t ucBssIndex); + +void kalIndicateRxMgmtFrame(IN struct GLUE_INFO *prGlueInfo, + IN struct SW_RFB *prSwRfb, + IN uint8_t ucBssIndex); +#endif +/*----------------------------------------------------------------------------*/ +/* Routines in interface - ehpi/sdio.c */ +/*----------------------------------------------------------------------------*/ +#ifdef CFG_REMIND_IMPLEMENT +#define kalDevRegRead(_prGlueInfo, _u4Register, _pu4Value) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) +#else +u_int8_t kalDevRegRead(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Register, + OUT uint32_t *pu4Value); +#endif +u_int8_t kalDevRegRead_mac(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Register, OUT uint32_t *pu4Value); + +#ifdef CFG_REMIND_IMPLEMENT +#define kalDevRegWrite(_prGlueInfo, _u4Register, _u4Value) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) +#else +u_int8_t kalDevRegWrite(struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Register, + IN uint32_t u4Value); +#endif +u_int8_t kalDevRegWrite_mac(struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Register, IN uint32_t u4Value); + +u_int8_t +kalDevPortRead(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port, IN uint32_t u2Len, OUT uint8_t *pucBuf, + IN uint32_t u2ValidOutBufSize); + +u_int8_t +kalDevPortWrite(struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port, IN uint32_t u2Len, IN uint8_t *pucBuf, + IN uint32_t u2ValidInBufSize); + +#ifdef CFG_REMIND_IMPLEMENT +#define kalDevWriteData(_prGlueInfo, _prMsduInfo) \ +KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalDevWriteCmd(_prGlueInfo, _prCmdInfo, _ucTC) \ +KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalDevKickData(_prGlueInfo) \ +KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) +#else +u_int8_t kalDevWriteData(IN struct GLUE_INFO *prGlueInfo, + IN struct MSDU_INFO *prMsduInfo); +enum ENUM_CMD_TX_RESULT kalDevWriteCmd(IN struct GLUE_INFO *prGlueInfo, + IN struct CMD_INFO *prCmdInfo, IN uint8_t ucTC); +u_int8_t kalDevKickData(IN struct GLUE_INFO *prGlueInfo); +#endif +void kalDevReadIntStatus(IN struct ADAPTER *prAdapter, + OUT uint32_t *pu4IntStatus); + +u_int8_t kalDevWriteWithSdioCmd52(IN struct GLUE_INFO + *prGlueInfo, + IN uint32_t u4Addr, IN uint8_t ucData); + +#if CFG_SUPPORT_EXT_CONFIG +uint32_t kalReadExtCfg(IN struct GLUE_INFO *prGlueInfo); +#endif + +#ifdef CFG_REMIND_IMPLEMENT +#define kalQoSFrameClassifierAndPacketInfo(_pr, _prPacket, _prTxPktInfo) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _pr) + +#define kalGetEthDestAddr(_prGlueInfo, _prPacket, _pucEthDestAddr) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalOidComplete(_prGlueInfo, _fgSetQuery, _u4SetQueryInfoLen, \ + _rOidStatus) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalIoctl(_pr, _pfnOidHandler, _pvInfoBuf, _u4InfoBufLen, \ + _fgRead, _fgWaitResp, _fgCmd, _pu4QryInfoLen) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _pr, \ + _pfnOidHandler, _pvInfoBuf, _u4InfoBufLen, \ + _fgRead, _fgWaitResp, _fgCmd, _pu4QryInfoLen) + +#define kalIoctlByBssIdx(_pr, _pfnOidHandler, _pvInfoBuf, _u4InfoBufLen, \ + _fgRead, _fgWaitResp, _fgCmd, _pu4QryInfoLen, _ucBssIndex) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _pr, \ + _pfnOidHandler, _pvInfoBuf, _u4InfoBufLen, \ + _fgRead, _fgWaitResp, _fgCmd, _pu4QryInfoLen, _ucBssIndex) + +#define SET_IOCTL_BSSIDX(_pr, _ucBssIndex) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _pr, \ + _ucBssIndex) + +#define GET_IOCTL_BSSIDX(_pr) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _pr) + +#else +u_int8_t +kalQoSFrameClassifierAndPacketInfo(IN struct GLUE_INFO + *prGlueInfo, + IN void *prPacket, + OUT struct TX_PACKET_INFO *prTxPktInfo); + +u_int8_t kalGetEthDestAddr(IN struct GLUE_INFO *prGlueInfo, + IN void *prPacket, + OUT uint8_t *pucEthDestAddr); + +void +kalOidComplete(IN struct GLUE_INFO *prGlueInfo, + IN u_int8_t fgSetQuery, IN uint32_t u4SetQueryInfoLen, + IN uint32_t rOidStatus); + +uint32_t +kalIoctl(IN struct GLUE_INFO *prGlueInfo, + IN PFN_OID_HANDLER_FUNC pfnOidHandler, + IN void *pvInfoBuf, + IN uint32_t u4InfoBufLen, IN u_int8_t fgRead, + IN u_int8_t fgWaitResp, + IN u_int8_t fgCmd, OUT uint32_t *pu4QryInfoLen); + +uint32_t +kalIoctlByBssIdx(IN struct GLUE_INFO *prGlueInfo, + IN PFN_OID_HANDLER_FUNC pfnOidHandler, + IN void *pvInfoBuf, + IN uint32_t u4InfoBufLen, IN u_int8_t fgRead, + IN u_int8_t fgWaitResp, IN u_int8_t fgCmd, + OUT uint32_t *pu4QryInfoLen, + IN uint8_t ucBssIndex); + +void SET_IOCTL_BSSIDX( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +uint8_t GET_IOCTL_BSSIDX( + IN struct ADAPTER *prAdapter); + +#endif + +void kalHandleAssocInfo(IN struct GLUE_INFO *prGlueInfo, + IN struct EVENT_ASSOC_INFO *prAssocInfo); + +#if CFG_ENABLE_FW_DOWNLOAD +#ifdef CFG_REMIND_IMPLEMENT +#define kalFirmwareImageMapping(_prGlueInfo, _ppvMapFileBuf, \ + _pu4FileLength, _eDlIdx) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalFirmwareImageUnmapping(_prGlueInfo, _prFwHandle, _pvMapFileBuf) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) +#else +void *kalFirmwareImageMapping(IN struct GLUE_INFO + *prGlueInfo, + OUT void **ppvMapFileBuf, + OUT uint32_t *pu4FileLength, + IN enum ENUM_IMG_DL_IDX_T eDlIdx); +void kalFirmwareImageUnmapping(IN struct GLUE_INFO + *prGlueInfo, + IN void *prFwHandle, IN void *pvMapFileBuf); +#endif +#endif + +/*----------------------------------------------------------------------------*/ +/* Card Removal Check */ +/*----------------------------------------------------------------------------*/ +#ifdef CFG_REMIND_IMPLEMENT +#define kalIsCardRemoved(_prGlueInfo) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) +#else +u_int8_t kalIsCardRemoved(IN struct GLUE_INFO *prGlueInfo); +#endif +/*----------------------------------------------------------------------------*/ +/* TX */ +/*----------------------------------------------------------------------------*/ +#ifdef CFG_REMIND_IMPLEMENT +#define kalFlushPendingTxPackets(_prGlueInfo) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) +#else +void kalFlushPendingTxPackets(IN struct GLUE_INFO + *prGlueInfo); +#endif + +/*----------------------------------------------------------------------------*/ +/* Media State Indication */ +/*----------------------------------------------------------------------------*/ +#ifdef CFG_REMIND_IMPLEMENT +#define kalGetMediaStateIndicated(_prGlueInfo, _ucBssIndex) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalSetMediaStateIndicated(_prGlueInfo, _eParamMediaStateIndicate, \ + _ucBssIndex) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) +#else +enum ENUM_PARAM_MEDIA_STATE kalGetMediaStateIndicated( + IN struct GLUE_INFO + *prGlueInfo, + IN uint8_t ucBssIndex); + +void kalSetMediaStateIndicated(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_PARAM_MEDIA_STATE eParamMediaStateIndicate, + IN uint8_t ucBssIndex); +#endif + +/*----------------------------------------------------------------------------*/ +/* OID handling */ +/*----------------------------------------------------------------------------*/ +#ifdef CFG_REMIND_IMPLEMENT +#define kalOidCmdClearance(_prGlueInfo) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalOidClearance(_prGlueInfo) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalEnqueueCommand(_prGlueInfo, _prQueueEntry) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) +#else +void kalOidCmdClearance(IN struct GLUE_INFO *prGlueInfo); + +void kalOidClearance(IN struct GLUE_INFO *prGlueInfo); + +void kalEnqueueCommand(IN struct GLUE_INFO *prGlueInfo, + IN struct QUE_ENTRY *prQueueEntry); +#endif + +#if CFG_ENABLE_BT_OVER_WIFI +/*----------------------------------------------------------------------------*/ +/* Bluetooth over Wi-Fi handling */ +/*----------------------------------------------------------------------------*/ +void kalIndicateBOWEvent(IN struct GLUE_INFO *prGlueInfo, + IN struct BT_OVER_WIFI_EVENT *prEvent); + +enum ENUM_BOW_DEVICE_STATE kalGetBowState( + IN struct GLUE_INFO *prGlueInfo, + IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN]); + +u_int8_t kalSetBowState(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_BOW_DEVICE_STATE eBowState, + uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN]); + +enum ENUM_BOW_DEVICE_STATE kalGetBowGlobalState( + IN struct GLUE_INFO + *prGlueInfo); + +uint32_t kalGetBowFreqInKHz(IN struct GLUE_INFO + *prGlueInfo); + +uint8_t kalGetBowRole(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN]); + +void kalSetBowRole(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRole, + IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN]); + +uint8_t kalGetBowAvailablePhysicalLinkCount( + IN struct GLUE_INFO *prGlueInfo); + +#if CFG_BOW_SEPARATE_DATA_PATH +/*----------------------------------------------------------------------------*/ +/* Bluetooth over Wi-Fi Net Device Init/Uninit */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalInitBowDevice(IN struct GLUE_INFO *prGlueInfo, + IN const char *prDevName); + +u_int8_t kalUninitBowDevice(IN struct GLUE_INFO + *prGlueInfo); +#endif /* CFG_BOW_SEPARATE_DATA_PATH */ +#endif /* CFG_ENABLE_BT_OVER_WIFI */ + +/*----------------------------------------------------------------------------*/ +/* Security Frame Clearance */ +/*----------------------------------------------------------------------------*/ +#ifdef CFG_REMIND_IMPLEMENT +#define kalClearSecurityFrames(_prGlueInfo) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalClearSecurityFramesByBssIdx(_prGlueInfo, _ucBssIndex) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalSecurityFrameSendComplete(_prGlueInfo, _pvPacket, _rStatus) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) +#else +void kalClearSecurityFrames(IN struct GLUE_INFO + *prGlueInfo); + +void kalClearSecurityFramesByBssIdx(IN struct GLUE_INFO + *prGlueInfo, + IN uint8_t ucBssIndex); + +void kalSecurityFrameSendComplete(IN struct GLUE_INFO + *prGlueInfo, + IN void *pvPacket, IN uint32_t rStatus); +#endif +/*----------------------------------------------------------------------------*/ +/* Management Frame Clearance */ +/*----------------------------------------------------------------------------*/ +#ifdef CFG_REMIND_IMPLEMENT +#define kalClearMgmtFrames(_prGlueInfo) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalClearMgmtFramesByBssIdx(_prGlueInfo, _ucBssIndex) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalGetTxPendingFrameCount(_prGlueInfo) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalGetTxPendingCmdCount(_prGlueInfo) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalClearCommandQueue(_prGlueInfo) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalSetTimer(_prGlueInfo, _u4Interval) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) +#else +void kalClearMgmtFrames(IN struct GLUE_INFO *prGlueInfo); + +void kalClearMgmtFramesByBssIdx(IN struct GLUE_INFO + *prGlueInfo, + IN uint8_t ucBssIndex); + +uint32_t kalGetTxPendingFrameCount(IN struct GLUE_INFO + *prGlueInfo); + +uint32_t kalGetTxPendingCmdCount(IN struct GLUE_INFO + *prGlueInfo); + +void kalClearCommandQueue(IN struct GLUE_INFO *prGlueInfo); + +u_int8_t kalSetTimer(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Interval); +#endif + +u_int8_t kalCancelTimer(IN struct GLUE_INFO *prGlueInfo); + +#ifdef CFG_REMIND_IMPLEMENT +#define kalScanDone(_prGlueInfo, _eNetTypeIdx, _status) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) +#else +void kalScanDone(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_KAL_NETWORK_TYPE_INDEX eNetTypeIdx, + IN uint32_t status); +#endif + +#if CFG_SUPPORT_SCAN_CACHE_RESULT +uint8_t kalUpdateBssTimestamp(IN struct GLUE_INFO *prGlueInfo); +#endif /* CFG_SUPPORT_SCAN_CACHE_RESULT */ + +void kalTimeoutHandler(unsigned long arg); + +#ifdef CFG_REMIND_IMPLEMENT +#define kalRandomNumber() KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define kalSetEvent(_pr) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _pr) + +#define kalSetIntEvent(_pr) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _pr) + +#define kalSetWmmUpdateEvent(_pr) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _pr) + +#define kalSetHifDbgEvent(_pr) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _pr) +#else +uint32_t kalRandomNumber(void); + +void kalSetEvent(struct GLUE_INFO *pr); + +void kalSetIntEvent(struct GLUE_INFO *pr); + +void kalSetWmmUpdateEvent(struct GLUE_INFO *pr); + +void kalSetHifDbgEvent(struct GLUE_INFO *pr); +#endif + +#if CFG_SUPPORT_MULTITHREAD +#ifdef CFG_REMIND_IMPLEMENT +#define kalSetTxEvent2Hif(_pr) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _pr) + +#define kalSetTxEvent2Rx(_pr) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _pr) + +#define kalSetTxCmdEvent2Hif(_pr) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _pr) +#define kalSetTxCmdDoneEvent(_pr) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _pr) + +#define kalSetRxProcessEvent(_pr) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _pr) +#else +void kalSetTxEvent2Hif(struct GLUE_INFO *pr); + +void kalSetTxEvent2Rx(struct GLUE_INFO *pr); + +void kalSetTxCmdEvent2Hif(struct GLUE_INFO *pr); + +void kalSetTxCmdDoneEvent(struct GLUE_INFO *pr); + +void kalSetRxProcessEvent(struct GLUE_INFO *pr); +#endif +#endif +/*----------------------------------------------------------------------------*/ +/* NVRAM/Registry Service */ +/*----------------------------------------------------------------------------*/ +#ifdef CFG_REMIND_IMPLEMENT +#define kalIsConfigurationExist(_prGlueInfo) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalGetConfiguration(_prGlueInfo) \ +((struct REG_INFO *)KAL_NEED_IMPLEMENT(__FILE__, __func__, \ + __LINE__, _prGlueInfo)) + +#define kalCfgDataRead16(_prGlueInfo, _u4Offset, _pu2Data) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalCfgDataWrite16(_prGlueInfo, _u4Offset, _u2Data) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) +#else +u_int8_t kalIsConfigurationExist(IN struct GLUE_INFO + *prGlueInfo); + +struct REG_INFO *kalGetConfiguration(IN struct GLUE_INFO + *prGlueInfo); + +u_int8_t kalCfgDataRead(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Offset, + IN ssize_t len, OUT uint16_t *pu2Data); + +u_int8_t kalCfgDataRead16(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Offset, + OUT uint16_t *pu2Data); + +u_int8_t kalCfgDataWrite16(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Offset, IN uint16_t u2Data); +#endif +/*----------------------------------------------------------------------------*/ +/* WSC Connection */ +/*----------------------------------------------------------------------------*/ +#ifdef CFG_REMIND_IMPLEMENT +#define kalWSCGetActiveState(_prGlueInfo) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) +#else +u_int8_t kalWSCGetActiveState(IN struct GLUE_INFO + *prGlueInfo); +#endif + +/*----------------------------------------------------------------------------*/ +/* RSSI Updating */ +/*----------------------------------------------------------------------------*/ +#ifdef CFG_REMIND_IMPLEMENT +#define kalUpdateRSSI(_prGlueInfo, _ucBssIndex, _cRssi, _cLinkQuality) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) +#else +void +kalUpdateRSSI(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucBssIndex, + IN int8_t cRssi, + IN int8_t cLinkQuality); +#endif + +/*----------------------------------------------------------------------------*/ +/* I/O Buffer Pre-allocation */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalInitIOBuffer(u_int8_t is_pre_alloc); + +void kalUninitIOBuffer(void); + +#ifdef CFG_REMIND_IMPLEMENT +#define kalAllocateIOBuffer(_u4AllocSize) \ +((uint8_t *) KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__)) + +#define kalReleaseIOBuffer(_pvAddr, _u4Size) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#else +void *kalAllocateIOBuffer(IN uint32_t u4AllocSize); + +void kalReleaseIOBuffer(IN void *pvAddr, + IN uint32_t u4Size); +#endif + +void +kalGetChannelList(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_BAND eSpecificBand, + IN uint8_t ucMaxChannelNum, IN uint8_t *pucNumOfChannel, + IN struct RF_CHANNEL_INFO *paucChannelList); + +u_int8_t kalIsAPmode(IN struct GLUE_INFO *prGlueInfo); + +#if CFG_SUPPORT_802_11W +/*----------------------------------------------------------------------------*/ +/* 802.11W */ +/*----------------------------------------------------------------------------*/ +#ifdef CFG_REMIND_IMPLEMENT +#define kalGetMfpSetting(_prGlueInfo, _ucBssIndex) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#define kalGetRsnIeMfpCap(_prGlueInfo, _ucBssIndex) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#else +uint32_t kalGetMfpSetting(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucBssIndex); +uint8_t kalGetRsnIeMfpCap(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucBssIndex); +#endif +#endif + +/*----------------------------------------------------------------------------*/ +/* file opetation */ +/*----------------------------------------------------------------------------*/ +#ifdef CFG_REMIND_IMPLEMENT +#define kalWriteToFile(_pucPath, _fgDoAppend, _pucData, _u4Size) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define kalCheckPath(_pucPath) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define kalTrunkPath(_pucPath) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define kalReadToFile(_pucPath, _pucData, _u4Size, _pu4ReadSize) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +/* used only under os folder */ +#define kalRequestFirmware(_pucPath, _pucData, _u4Size, _pu4ReadSize, _dev) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#else +uint32_t kalWriteToFile(const uint8_t *pucPath, + u_int8_t fgDoAppend, + uint8_t *pucData, uint32_t u4Size); + +uint32_t kalCheckPath(const uint8_t *pucPath); + +uint32_t kalTrunkPath(const uint8_t *pucPath); + +int32_t kalReadToFile(const uint8_t *pucPath, + uint8_t *pucData, + uint32_t u4Size, uint32_t *pu4ReadSize); + +/* used only under os folder */ +int32_t kalRequestFirmware(const uint8_t *pucPath, + uint8_t *pucData, + uint32_t u4Size, uint32_t *pu4ReadSize, + void *dev); +#endif +/*----------------------------------------------------------------------------*/ +/* NL80211 */ +/*----------------------------------------------------------------------------*/ +#ifdef CFG_REMIND_IMPLEMENT +#define kalIndicateBssInfo(_prGlueInfo, _pucFrameBuf, _u4BufLen, \ + _ucChannelNum, _i4SignalStrength) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) +#else +void +kalIndicateBssInfo(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucFrameBuf, IN uint32_t u4BufLen, + IN uint8_t ucChannelNum, IN int32_t i4SignalStrength); +#endif +/*----------------------------------------------------------------------------*/ +/* Net device */ +/*----------------------------------------------------------------------------*/ +#ifdef CFG_REMIND_IMPLEMENT +#define kalHardStartXmit(_prSkb, _prDev, _prGlueInfo, _ucBssIndex) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define kalIsPairwiseEapolPacket(_prPacket) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define kalGetIPv4Address(_prDev, _u4MaxNumOfAddr, _pucIpv4Addrs, \ + _pu4NumOfIpv4Addr) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#if IS_ENABLED(CONFIG_IPV6) +#define kalGetIPv6Address(_prDev, _u4MaxNumOfAddr, _pucIpv6Addrs, \ + _pu4NumOfIpv6Addr) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#endif /* IS_ENABLED(CONFIG_IPV6) */ + +#define kalSetNetAddressFromInterface(_prGlueInfo, _prDev, _fgSet) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define kalResetStats(_prDev) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define kalGetStats(_prDev) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#else +uint32_t +kalHardStartXmit(struct sk_buff *prSkb, + IN struct net_device *prDev, + struct GLUE_INFO *prGlueInfo, uint8_t ucBssIndex); + +u_int8_t kalIsPairwiseEapolPacket(IN void *prPacket); + +u_int8_t +kalGetIPv4Address(IN struct net_device *prDev, + IN uint32_t u4MaxNumOfAddr, OUT uint8_t *pucIpv4Addrs, + OUT uint32_t *pu4NumOfIpv4Addr); + +#if IS_ENABLED(CONFIG_IPV6) +u_int8_t +kalGetIPv6Address(IN struct net_device *prDev, + IN uint32_t u4MaxNumOfAddr, OUT uint8_t *pucIpv6Addrs, + OUT uint32_t *pu4NumOfIpv6Addr); +#else +static inline u_int8_t +kalGetIPv6Address(IN struct net_device *prDev, + IN uint32_t u4MaxNumOfAddr, OUT uint8_t *pucIpv6Addrs, + OUT uint32_t *pu4NumOfIpv6Addr) { + /* Not support IPv6 */ + *pu4NumOfIpv6Addr = 0; + return 0; +} +#endif /* IS_ENABLED(CONFIG_IPV6) */ + +void kalSetNetAddressFromInterface(IN struct GLUE_INFO + *prGlueInfo, + IN struct net_device *prDev, + IN u_int8_t fgSet); + +uint32_t kalResetStats(IN struct net_device *prDev); + +void *kalGetStats(IN struct net_device *prDev); +#endif + +void kalResetPacket(IN struct GLUE_INFO *prGlueInfo, + IN void *prPacket); + +#if CFG_SUPPORT_QA_TOOL +#ifdef CFG_REMIND_IMPLEMENT +#define kalFileOpen(_path, _flags, _rights) \ +((void *) KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__)) + +#define kalFileClose(_file) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define kalFileRead(_file, _offset, _data, _size) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#else +struct file *kalFileOpen(const char *path, int flags, + int rights); + +void kalFileClose(struct file *file); + +uint32_t kalFileRead(struct file *file, + unsigned long long offset, + unsigned char *data, unsigned int size); +#endif +#endif + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN +/*----------------------------------------------------------------------------*/ +/* SDIO Read/Write Pattern Support */ +/*----------------------------------------------------------------------------*/ +#ifdef CFG_REMIND_IMPLEMENT +#define kalSetSdioTestPattern(_prGlueInfo, _fgEn, _fgRead) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) +#else +u_int8_t kalSetSdioTestPattern(IN struct GLUE_INFO + *prGlueInfo, + IN u_int8_t fgEn, IN u_int8_t fgRead); +#endif +#endif + +/*----------------------------------------------------------------------------*/ +/* PNO Support */ +/*----------------------------------------------------------------------------*/ +#ifdef CFG_REMIND_IMPLEMENT +#define kalSchedScanResults(_prGlueInfo) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalSchedScanStopped(_prGlueInfo, _fgDriverTriggerd) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalSetFwOwnEvent2Hif(_pr) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _pr) +#else +void kalSchedScanResults(IN struct GLUE_INFO *prGlueInfo); + +void kalSchedScanStopped(IN struct GLUE_INFO *prGlueInfo, + u_int8_t fgDriverTriggerd); + +void kalSetFwOwnEvent2Hif(struct GLUE_INFO *pr); +#endif + +#if CFG_ASSERT_DUMP +#ifdef CFG_REMIND_IMPLEMENT +#define kalOpenCorDumpFile(_fgIsN9) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#define kalWriteCorDumpFile(_pucBuffer, _u2Size, _fgIsN9) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#define kalCloseCorDumpFile(_fgIsN9) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#else +/* Core Dump out put file */ +uint32_t kalOpenCorDumpFile(u_int8_t fgIsN9); +uint32_t kalWriteCorDumpFile(uint8_t *pucBuffer, + uint16_t u2Size, + u_int8_t fgIsN9); +uint32_t kalCloseCorDumpFile(u_int8_t fgIsN9); +#endif +#endif +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#if CFG_WOW_SUPPORT +#ifdef CFG_REMIND_IMPLEMENT +#define kalWowInit(_glueinfo) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#define kalWowProcess(_glueinfo, _enable) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#else +void kalWowInit(IN struct GLUE_INFO *prGlueInfo); +void kalWowProcess(IN struct GLUE_INFO *prGlueInfo, + uint8_t enable); +#endif +#endif + +int main_thread(void *data); + +#if CFG_SUPPORT_MULTITHREAD +int hif_thread(void *data); +int rx_thread(void *data); +#endif + +#ifdef CFG_REMIND_IMPLEMENT +#define kalGetBootTime() KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#else +uint64_t kalGetBootTime(void); +#endif + +int kalMetInitProcfs(IN struct GLUE_INFO *prGlueInfo); +int kalMetRemoveProcfs(void); + +uint8_t kalGetEapolKeyType(void *prPacket); + +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG +#ifdef CFG_REMIND_IMPLEMENT +#define kalIsWakeupByWlan(_prAdapter) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#else +u_int8_t kalIsWakeupByWlan(struct ADAPTER *prAdapter); +#endif +#endif + +int32_t kalHaltLock(uint32_t waitMs); +int32_t kalHaltTryLock(void); +void kalHaltUnlock(void); +void kalSetHalted(u_int8_t fgHalt); +u_int8_t kalIsHalted(void); + +#ifdef CFG_REMIND_IMPLEMENT +#define kalFreeTxMsduWorker(_work) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#else +void kalFreeTxMsduWorker(struct work_struct *work); +#endif +void kalFreeTxMsdu(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +int32_t kalPerMonInit(IN struct GLUE_INFO *prGlueInfo); +int32_t kalPerMonDisable(IN struct GLUE_INFO *prGlueInfo); +int32_t kalPerMonEnable(IN struct GLUE_INFO *prGlueInfo); +#ifdef CFG_REMIND_IMPLEMENT +#define kalPerMonStart(_prGlueInfo) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) +#else +int32_t kalPerMonStart(IN struct GLUE_INFO *prGlueInfo); +#endif +int32_t kalPerMonStop(IN struct GLUE_INFO *prGlueInfo); +int32_t kalPerMonDestroy(IN struct GLUE_INFO *prGlueInfo); +void kalPerMonHandler(IN struct ADAPTER *prAdapter, + unsigned long ulParam); +uint32_t kalPerMonGetInfo(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, + IN uint32_t u4Max); +int32_t kalBoostCpu(IN struct ADAPTER *prAdapter, + IN uint32_t u4TarPerfLevel, + IN uint32_t u4BoostCpuTh); +int32_t kalCheckTputLoad(IN struct ADAPTER *prAdapter, + IN uint32_t u4CurrPerfLevel, + IN uint32_t u4TarPerfLevel, + IN int32_t i4Pending, + IN uint32_t u4Used); +void kalSetRpsMap(IN struct GLUE_INFO *glue, IN unsigned long value); +#if CFG_MTK_ANDROID_EMI +void kalSetEmiMpuProtection(phys_addr_t emiPhyBase, uint32_t offset, + uint32_t size, bool enable); +void kalSetDrvEmiMpuProtection(phys_addr_t emiPhyBase, uint32_t offset, + uint32_t size); +#endif +int32_t kalSetCpuNumFreq(uint32_t u4CoreNum, + uint32_t u4Freq); +int32_t kalPerMonSetForceEnableFlag(uint8_t uFlag); +int32_t kalFbNotifierReg(IN struct GLUE_INFO *prGlueInfo); +void kalFbNotifierUnReg(void); + +#ifdef CFG_REMIND_IMPLEMENT +#define kalInitDevWakeup(_prAdapter, _prDev) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#else +void kalInitDevWakeup(struct ADAPTER *prAdapter, struct device *prDev); +#endif + +#ifdef CFG_REMIND_IMPLEMENT +#define kalIsValidMacAddr(_addr) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define kalScanParseRandomMac(_prdev, prRrequest, _pucRandomMac) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define kalSchedScanParseRandomMac(_prdev, prRrequest, _pucRandomMac \ + , _pucRandomMacMask) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define kalScanReqLog(prRrequest) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#define kalScanResultLog(_prAdapter, _prMgmt) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#else +u_int8_t kalIsValidMacAddr(const uint8_t *addr); + +u_int8_t kalScanParseRandomMac(const struct net_device *ndev, + const struct cfg80211_scan_request *request, uint8_t *pucRandomMac); + +u_int8_t kalSchedScanParseRandomMac(const struct net_device *ndev, + const struct cfg80211_sched_scan_request *request, + uint8_t *pucRandomMac, uint8_t *pucRandomMacMask); + +void kalScanReqLog(struct cfg80211_scan_request *request); +void kalScanResultLog(struct ADAPTER *prAdapter, struct ieee80211_mgmt *mgmt); +#endif +void kalScanLogCacheFlushBSS(struct ADAPTER *prAdapter, + const uint16_t logBufLen); + +#ifdef CFG_REMIND_IMPLEMENT +#define kalMaskMemCmp(_cs, _ct, _mask, _count) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define kalChannelScoSwitch(_channel_type, _prChnlSco) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define kalChannelFormatSwitch(_prChannel_def, _prChannel \ + , _prRfChnlInfo) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define kalRemoveBss(_prGlueInfo, \ + _aucBSSID, _ucChannelNum, \ + _eBand) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define kalIsResetting(_void) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#else +int kalMaskMemCmp(const void *cs, const void *ct, + const void *mask, size_t count); + +u_int8_t +kalChannelScoSwitch(IN enum nl80211_channel_type channel_type, + IN enum ENUM_CHNL_EXT *prChnlSco); + +u_int8_t +kalChannelFormatSwitch(IN struct cfg80211_chan_def *channel_def, + IN struct ieee80211_channel *channel, + IN struct RF_CHANNEL_INFO *prRfChnlInfo); + +void kalRemoveBss(struct GLUE_INFO *prGlueInfo, + uint8_t aucBSSID[], + uint8_t ucChannelNum, + enum ENUM_BAND eBand); + +u_int8_t kalIsResetting(void); +#endif + +#if CFG_CHIP_RESET_SUPPORT +void kalRemoveProbe(IN struct GLUE_INFO *prGlueInfo); +#endif + +#endif /* _GL_KAL_H */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_os.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_os.h new file mode 100644 index 0000000000000..a972898d65090 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_os.h @@ -0,0 +1,1277 @@ + +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/*! \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. + * For porting to new OS, the API listed in this file needs to be + * implemented + */ + + +#ifndef _GL_OS_H +#define _GL_OS_H + +/* Standard C, for implementation on differenct OS + * the following include files needs to be refined + */ +/* types */ +#include +#include "sys/types.h" + +/* bool type */ +#include + +/* memory operation */ +#include + +/* networking */ +#include + +/* offsetof series */ +#include + +/* sprintf series */ +#include + +/* error code */ +#include +#include + +/* va_* series */ +#include + +/* for INT_MAX for some reason include fail not checked */ +#if 0 +/* when there is platform specific toolchain + * there should be this file + * eg. gcc-arm-none-eabi/arm-none-eabi/include/limits.h + */ +#include +#else +/* Minimum and maximum values a `signed int' can hold. */ +# define INT_MIN (-INT_MAX - 1) +# define INT_MAX 2147483647 +#endif +/* cannot find the necessary include header */ +typedef uint64_t u64; +typedef uint32_t u32; +typedef uint16_t u16; +typedef uint8_t u8; + +/* driver internal */ +#include "version.h" +#include "config.h" +#include "gl_dependent.h" + +#include "gl_typedef.h" +#include "typedef.h" +#include "queue.h" +#include "gl_kal.h" +#include "gl_rst.h" +#include "hif.h" + +#if CFG_SUPPORT_TDLS +#include "tdls.h" +#endif + +#include "debug.h" + +#include "wlan_oid.h" + +/* + * comment: declared in wlan_lib.c + * and almost all of the glue layer includes #include "precomp.h" + * should we just but it in wlan_lib.h + */ +extern u_int8_t fgIsBusAccessFailed; + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ +#ifndef __weak +#define __weak __attribute__((weak)) +#endif +/*------------------------------------------------------------------------------ + * Flags for 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 */ + +/* 1: Enable use of SPIN LOCK Bottom Half for LINUX */ +/* 0: Disable - use SPIN LOCK IRQ SAVE instead */ +#define CFG_USE_SPIN_LOCK_BOTTOM_HALF 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_PADDING_SMALL_ETH_PACKET 0 + +#define CFG_TX_STOP_NETIF_QUEUE_THRESHOLD 256 /* packets */ + +#define CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD 256 /* packets */ +#define CFG_TX_START_NETIF_PER_QUEUE_THRESHOLD 128 /* packets */ + +#define CHIP_NAME "MT6632" + +#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) +#define GLUE_INFO_WSCIE_LENGTH (500) +/* for non-wfa vendor specific IE buffer */ +#define NON_WFA_VENDOR_IE_MAX_LEN (128) + + +/******************************************************************************* + * 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 + ******************************************************************************* + */ +/* driver events for threading */ +#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_MULTICAST BIT(7) +#define GLUE_FLAG_FRAME_FILTER BIT(8) +#define GLUE_FLAG_FRAME_FILTER_AIS BIT(9) + +#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_MULTICAST_BIT (7) +#define GLUE_FLAG_FRAME_FILTER_BIT (8) +#define GLUE_FLAG_FRAME_FILTER_AIS_BIT (9) + +#if CFG_SUPPORT_MULTITHREAD +#define GLUE_FLAG_RX BIT(10) +#define GLUE_FLAG_TX_CMD_DONE BIT(11) +#define GLUE_FLAG_HIF_TX BIT(12) +#define GLUE_FLAG_HIF_TX_CMD BIT(13) +#define GLUE_FLAG_RX_TO_OS BIT(14) +#define GLUE_FLAG_HIF_FW_OWN BIT(15) +#define GLUE_FLAG_HIF_PRT_HIF_DBG_INFO BIT(16) +#define GLUE_FLAG_UPDATE_WMM_QUOTA BIT(17) + +#define GLUE_FLAG_RX_BIT (10) +#define GLUE_FLAG_TX_CMD_DONE_BIT (11) +#define GLUE_FLAG_HIF_TX_BIT (12) +#define GLUE_FLAG_HIF_TX_CMD_BIT (13) +#define GLUE_FLAG_RX_TO_OS_BIT (14) +#define GLUE_FLAG_HIF_FW_OWN_BIT (15) +#define GLUE_FLAG_HIF_PRT_HIF_DBG_INFO_BIT (16) +#define GLUE_FLAG_UPDATE_WMM_QUOTA_BIT (17) +#endif + +#if CFG_ENABLE_BT_OVER_WIFI +#define GLUE_BOW_KFIFO_DEPTH (1024) +/* #define GLUE_BOW_DEVICE_NAME "MT6620 802.11 AMP" */ +#define GLUE_BOW_DEVICE_NAME "ampc0" +#endif + +/* wake lock for suspend/resume */ +#define WAKE_LOCK_RX_TIMEOUT 300 /* ms */ +#define WAKE_LOCK_THREAD_WAKEUP_TIMEOUT 50 /* ms */ + +#define STR_HELPER(x) #x +#define STR(x) STR_HELPER(x) + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +struct GLUE_INFO; + +struct GL_WPA_INFO { + uint32_t u4WpaVersion; + uint32_t u4KeyMgmt; + uint32_t u4CipherGroup; + uint32_t u4CipherPairwise; + uint32_t u4AuthAlg; + u_int8_t fgPrivacyInvoke; +#if CFG_SUPPORT_802_11W + uint32_t u4Mfp; + uint8_t ucRSNMfpCap; +#endif +}; + +#if CFG_SUPPORT_REPLAY_DETECTION +struct GL_REPLEY_PN_INFO { + uint8_t auPN[16]; + u_int8_t fgRekey; + u_int8_t fgFirstPkt; +}; +struct GL_DETECT_REPLAY_INFO { + uint8_t ucCurKeyId; + uint8_t ucKeyType; + struct GL_REPLEY_PN_INFO arReplayPNInfo[4]; +}; +#endif + +enum ENUM_NET_DEV_IDX { + NET_DEV_WLAN_IDX = 0, + NET_DEV_P2P_IDX, + NET_DEV_BOW_IDX, + NET_DEV_NUM +}; + +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 +}; + +#if CFG_ENABLE_WIFI_DIRECT +enum ENUM_NET_REG_STATE { + 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 +}; +#endif + +enum ENUM_PKT_FLAG { + ENUM_PKT_802_11, /* 802.11 or non-802.11 */ + ENUM_PKT_802_3, /* 802.3 or ethernetII */ + ENUM_PKT_1X, /* 1x frame or not */ + ENUM_PKT_PROTECTED_1X, /* protected 1x frame */ + ENUM_PKT_NON_PROTECTED_1X, /* Non protected 1x frame */ + ENUM_PKT_VLAN_EXIST, /* VLAN tag exist */ + ENUM_PKT_DHCP, /* DHCP frame */ + ENUM_PKT_ARP, /* ARP */ + ENUM_PKT_ICMP, /* ICMP */ + ENUM_PKT_TDLS, /* TDLS */ + ENUM_PKT_DNS, /* DNS */ + + ENUM_PKT_FLAG_NUM +}; + +struct GL_IO_REQ { + struct QUE_ENTRY rQueEntry; + /* wait_queue_head_t cmdwait_q; */ + u_int8_t fgRead; + u_int8_t fgWaitResp; + struct ADAPTER *prAdapter; + PFN_OID_HANDLER_FUNC pfnOidHandler; + void *pvInfoBuf; + uint32_t u4InfoBufLen; + uint32_t *pu4QryInfoLen; + uint32_t rStatus; + uint32_t u4Flag; +}; + +#if CFG_ENABLE_BT_OVER_WIFI +struct GL_BOW_INFO { +/* TODO: os-related */ +#if 0 + u_int8_t fgIsRegistered; + dev_t u4DeviceNumber; /* dynamic device number */ + struct kfifo rKfifo; /* for buffering indicated events */ + spinlock_t rSpinLock; /* spin lock for kfifo */ + struct cdev cdev; + uint32_t u4FreqInKHz; /* frequency */ + + uint8_t aucRole[CFG_BOW_PHYSICAL_LINK_NUM]; /* 0: Responder, + * 1: Initiator + */ + enum ENUM_BOW_DEVICE_STATE + aeState[CFG_BOW_PHYSICAL_LINK_NUM]; + uint8_t arPeerAddr[CFG_BOW_PHYSICAL_LINK_NUM][PARAM_MAC_ADDR_LEN]; + + wait_queue_head_t outq; + +#if CFG_BOW_SEPARATE_DATA_PATH + /* Device handle */ + struct net_device *prDevHandler; + u_int8_t fgIsNetRegistered; +#endif +#endif +}; +#endif + +#if CFG_SUPPORT_SCAN_CACHE_RESULT +struct GL_SCAN_CACHE_INFO { + struct GLUE_INFO *prGlueInfo; +/* TODO: os-related? */ + /* total number of channels to scan */ + uint32_t n_channels; + + /* Scan period time */ + OS_SYSTIME u4LastScanTime; +/* TODO: os-related */ +#if 0 + /* for cfg80211 scan done indication */ + struct cfg80211_scan_request *prRequest; +#endif +}; +#endif /* CFG_SUPPORT_SCAN_CACHE_RESULT */ + +struct FT_IES { + uint16_t u2MDID; + struct IE_MOBILITY_DOMAIN *prMDIE; + struct IE_FAST_TRANSITION *prFTIE; + struct IE_TIMEOUT_INTERVAL *prTIE; + struct RSN_INFO_ELEM *prRsnIE; + uint8_t *pucIEBuf; + uint32_t u4IeLength; +}; + +/* + * type definition of pointer to p2p structure + */ +struct GL_P2P_INFO; /* declare GL_P2P_INFO_T */ +struct GL_P2P_DEV_INFO; /* declare GL_P2P_DEV_INFO_T */ + +struct GLUE_INFO { + /* Pointer to ADAPTER_T - main data structure of internal protocol + * stack + */ + struct ADAPTER *prAdapter; + + /* OID related */ + struct QUE rCmdQueue; + + spinlock_t rSpinLock[SPIN_LOCK_NUM]; + + /* 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. + */ + int32_t ai4TxPendingFrameNumPerQueue[MAX_BSSID_NUM][CFG_MAX_TXQ_NUM]; + int32_t i4TxPendingFrameNum; + int32_t i4TxPendingSecurityFrameNum; + int32_t i4TxPendingCmdNum; + + /*! \brief wext wpa related information */ + struct GL_WPA_INFO rWpaInfo[KAL_AIS_NUM]; +#if CFG_SUPPORT_REPLAY_DETECTION + struct GL_DETECT_REPLAY_INFO prDetRplyInfo[KAL_AIS_NUM]; +#endif + + uint32_t u4RoamFailCnt; + uint64_t u8RoamFailTime; + + /* 11R */ + struct FT_IES rFtIeForTx; + struct cfg80211_ft_event_params rFtEventParam; + + uint32_t IsrAbnormalCnt; + uint32_t IsrSoftWareCnt; + + /* Indicated media state */ + enum ENUM_PARAM_MEDIA_STATE eParamMediaStateIndicated; + + /* NVRAM availability */ + u_int8_t fgNvramAvailable; + + struct SET_TXPWR_CTRL rTxPwr; + + uint32_t IsrCnt; + uint32_t IsrPassCnt; + uint32_t TaskIsrCnt; + + uint32_t IsrTxCnt; + uint32_t IsrRxCnt; + + /* Tx: for NetDev to BSS index mapping */ + struct NET_INTERFACE_INFO arNetInterfaceInfo[MAX_BSSID_NUM]; + + u_int8_t fgTxDoneDelayIsARP; + + uint32_t u4ArriveDrvTick; + uint32_t u4EnQueTick; + uint32_t u4DeQueTick; + uint32_t u4LeaveDrvTick; + uint32_t u4CurrTick; + uint64_t u8CurrTime; + + /* + * Buffer to hold non-wfa vendor specific IEs set + * from wpa_supplicant. This is used in sending + * Association Request in AIS mode. + */ + uint16_t non_wfa_vendor_ie_len; + uint8_t non_wfa_vendor_ie_buf[NON_WFA_VENDOR_IE_MAX_LEN]; + +#if CFG_ENABLE_WIFI_DIRECT + struct GL_P2P_DEV_INFO *prP2PDevInfo; + struct GL_P2P_INFO *prP2PInfo[KAL_P2P_NUM]; +#endif + +#if CFG_SUPPORT_SNIFFER + u_int8_t fgIsEnableMon; +#endif + + u_int8_t fgIsInSuspendMode; + + /* registry info */ + struct REG_INFO rRegInfo; + + /* + * needed by + * common/cmm_asic_connac.c + */ + uint32_t u4InfType; + + /* + * needed by + * mgmt/tdls.c + */ + /* Device handle */ + struct net_device *prDevHandler; + + /* Device */ + struct device *prDev; + /* not necessary for built */ + /* TODO: os-related */ + uint32_t u4ReadyFlag; /* check if card is ready */ +#if 0 + + /* Device */ + struct device *prDev; + + /* Device Index(index of arWlanDevInfo[]) */ + int32_t 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]; + + /* Mutex to protect interruptible section */ + struct mutex arMutex[MUTEX_NUM]; + + /* semaphore for ioctl */ + struct semaphore ioctl_sem; + + uint64_t u8Cookie; + + unsigned long ulFlag; /* GLUE_FLAG_XXX */ + uint32_t u4PendFlag; + /* UINT_32 u4TimeoutFlag; */ + uint32_t u4OidCompleteFlag; + uint32_t u4ReadyFlag; /* check if card is ready */ + + uint32_t u4OsMgmtFrameFilter; + + /* Number of pending frames, also used for debuging if any frame is + * missing during the process of unloading Driver. + * + * NOTE(Kevin): In Linux, we also use this variable as the threshold + * for manipulating the netif_stop(wake)_queue() func. + */ + int32_t ai4TxPendingFrameNumPerQueue[MAX_BSSID_NUM][CFG_MAX_TXQ_NUM]; + int32_t i4TxPendingFrameNum; + int32_t i4TxPendingSecurityFrameNum; + int32_t i4TxPendingCmdNum; + + /* Tx: for NetDev to BSS index mapping */ + struct NET_INTERFACE_INFO arNetInterfaceInfo[MAX_BSSID_NUM]; + + /* Rx: for BSS index to NetDev mapping */ + /* P_NET_INTERFACE_INFO_T aprBssIdxToNetInterfaceInfo[HW_BSSID_NUM]; */ + + /* current IO request for kalIoctl */ + struct GL_IO_REQ OidEntry; + + /* registry info */ + struct REG_INFO rRegInfo; + + /* firmware */ + struct firmware *prFw; + + /* Host interface related information */ + /* defined in related hif header file */ + struct GL_HIF_INFO rHifInfo; + + /*! \brief wext wpa related information */ + struct GL_WPA_INFO rWpaInfo; +#if CFG_SUPPORT_REPLAY_DETECTION + struct GL_DETECT_REPLAY_INFO prDetRplyInfo; +#endif + + /* Pointer to ADAPTER_T - main data structure of internal protocol + * stack + */ + struct ADAPTER *prAdapter; + +#if WLAN_INCLUDE_PROC + struct proc_dir_entry *pProcRoot; +#endif /* WLAN_INCLUDE_PROC */ + + /* Indicated media state */ + enum ENUM_PARAM_MEDIA_STATE eParamMediaStateIndicated; + + /* Device power state D0~D3 */ + enum 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_SUPPORT_MULTITHREAD + struct completion + rHifHaltComp; /* indicate hif_thread halt complete */ + struct completion + rRxHaltComp; /* indicate hif_thread halt complete */ + + uint32_t u4TxThreadPid; + uint32_t u4RxThreadPid; + uint32_t u4HifThreadPid; +#endif + +#if CFG_SUPPORT_NCHO + struct completion + rAisChGrntComp; /* indicate Ais channel grant complete */ +#endif + + uint32_t rPendStatus; + + struct QUE rTxQueue; + + /* OID related */ + struct QUE 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; + +#if CFG_SUPPORT_MULTITHREAD + wait_queue_head_t waitq_hif; + struct task_struct *hif_thread; + + wait_queue_head_t waitq_rx; + struct task_struct *rx_thread; + +#endif + struct tasklet_struct rRxTask; + struct tasklet_struct rTxCompleteTask; + + struct work_struct rTxMsduFreeWork; + struct delayed_work rRxPktDeAggWork; + + struct timer_list tickfn; + +#if CFG_SUPPORT_EXT_CONFIG + uint16_t au2ExtCfg[256]; /* NVRAM data buffer */ + uint32_t u4ExtCfgLength; /* 0 means data is NOT valid */ +#endif + +#if 1 /* CFG_SUPPORT_WAPI */ + /* Should be large than the PARAM_WAPI_ASSOC_INFO_T */ + uint8_t aucWapiAssocInfoIEs[42]; + uint16_t u2WapiAssocInfoIESz; +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + struct GL_BOW_INFO rBowInfo; +#endif + +#if CFG_ENABLE_WIFI_DIRECT + struct GL_P2P_DEV_INFO *prP2PDevInfo; + struct GL_P2P_INFO *prP2PInfo[KAL_P2P_NUM]; +#if CFG_SUPPORT_P2P_RSSI_QUERY + /* Wireless statistics struct net_device */ + struct iw_statistics rP2pIwStats; +#endif +#endif + u_int8_t fgWpsActive; + uint8_t aucWSCIE[GLUE_INFO_WSCIE_LENGTH]; /*for probe req */ + uint16_t u2WSCIELen; + uint8_t aucWSCAssocInfoIE[200]; /*for Assoc req */ + uint16_t u2WSCAssocInfoIELen; + + /* NVRAM availability */ + u_int8_t fgNvramAvailable; + + u_int8_t fgMcrAccessAllowed; + + /* MAC Address Overridden by IOCTL */ + u_int8_t fgIsMacAddrOverride; + uint8_t rMacAddrOverride[PARAM_MAC_ADDR_LEN]; + + struct SET_TXPWR_CTRL rTxPwr; + + /* for cfg80211 scan done indication */ + struct cfg80211_scan_request *prScanRequest; + + /* for cfg80211 scheduled scan */ + struct cfg80211_sched_scan_request *prSchedScanRequest; + + /* to indicate registered or not */ + u_int8_t fgIsRegistered; + + /* for cfg80211 connected indication */ + uint32_t u4RspIeLength; + uint8_t aucRspIe[CFG_CFG80211_IE_BUF_LEN]; + + uint32_t u4ReqIeLength; + uint8_t aucReqIe[CFG_CFG80211_IE_BUF_LEN]; + + /* + * Buffer to hold non-wfa vendor specific IEs set + * from wpa_supplicant. This is used in sending + * Association Request in AIS mode. + */ + uint16_t non_wfa_vendor_ie_len; + uint8_t non_wfa_vendor_ie_buf[NON_WFA_VENDOR_IE_MAX_LEN]; + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN + u_int8_t fgEnSdioTestPattern; + u_int8_t fgSdioReadWriteMode; + u_int8_t fgIsSdioTestInitialized; + uint8_t aucSdioTestBuffer[256]; +#endif + + u_int8_t fgIsInSuspendMode; + +#if CFG_SUPPORT_PASSPOINT + uint8_t aucHS20AssocInfoIE[200]; /*for Assoc req */ + uint16_t u2HS20AssocInfoIELen; + uint8_t ucHotspotConfig; + u_int8_t fgConnectHS20AP; + + u_int8_t fgIsDad; + uint8_t aucDADipv4[4]; + u_int8_t fgIs6Dad; + uint8_t aucDADipv6[16]; +#endif /* CFG_SUPPORT_PASSPOINT */ + + KAL_WAKE_LOCK_T rIntrWakeLock; + KAL_WAKE_LOCK_T rTimeoutWakeLock; + +#if CFG_MET_PACKET_TRACE_SUPPORT + u_int8_t fgMetProfilingEn; + uint16_t u2MetUdpPort; +#endif + +#if CFG_SUPPORT_SNIFFER + u_int8_t fgIsEnableMon; + struct net_device *prMonDevHandler; + struct work_struct monWork; +#endif + + int32_t i4RssiCache; + uint32_t u4LinkSpeedCache; + + + uint32_t u4InfType; + + uint32_t IsrCnt; + uint32_t IsrPassCnt; + uint32_t TaskIsrCnt; + + uint32_t IsrAbnormalCnt; + uint32_t IsrSoftWareCnt; + uint32_t IsrTxCnt; + uint32_t IsrRxCnt; + uint64_t u8HifIntTime; + + /* save partial scan channel information */ + /* PARTIAL_SCAN_INFO rScanChannelInfo; */ + uint8_t *pucScanChannel; + +#if CFG_SUPPORT_SCAN_CACHE_RESULT + struct GL_SCAN_CACHE_INFO scanCache; +#endif /* CFG_SUPPORT_SCAN_CACHE_RESULT */ + + /* Full2Partial */ + OS_SYSTIME u4LastFullScanTime; + /* full scan or partial scan */ + uint8_t ucTrScanType; + /* UINT_8 aucChannelNum[FULL_SCAN_MAX_CHANNEL_NUM]; */ + /* PARTIAL_SCAN_INFO rFullScanApChannel; */ + uint8_t *pucFullScan2PartialChannel; + + uint32_t u4RoamFailCnt; + uint64_t u8RoamFailTime; + u_int8_t fgTxDoneDelayIsARP; + uint32_t u4ArriveDrvTick; + uint32_t u4EnQueTick; + uint32_t u4DeQueTick; + uint32_t u4LeaveDrvTick; + uint32_t u4CurrTick; + uint64_t u8CurrTime; + + /* FW Roaming */ + /* store the FW roaming enable state which FWK determines */ + /* if it's = 0, ignore the black/whitelists settings from FWK */ + uint32_t u4FWRoamingEnable; + + /* 11R */ + struct FT_IES rFtIeForTx; + struct cfg80211_ft_event_params rFtEventParam; +#endif +}; + +#if 0 /* irq & time in Linux */ +typedef irqreturn_t(*PFN_WLANISR) (int irq, void *dev_id, + struct pt_regs *regs); + +typedef void (*PFN_LINUX_TIMER_FUNC) (unsigned long); +#endif + +/* generic sub module init/exit handler + * now, we only have one sub module, p2p + */ +#if CFG_ENABLE_WIFI_DIRECT +typedef u_int8_t(*SUB_MODULE_INIT) (struct GLUE_INFO + *prGlueInfo); +typedef u_int8_t(*SUB_MODULE_EXIT) (struct GLUE_INFO + *prGlueInfo); + +struct SUB_MODULE_HANDLER { + SUB_MODULE_INIT subModInit; + SUB_MODULE_EXIT subModExit; + u_int8_t fgIsInited; +}; + +#endif + +#ifdef CONFIG_NL80211_TESTMODE + +enum TestModeCmdType { + TESTMODE_CMD_ID_SW_CMD = 1, + TESTMODE_CMD_ID_WAPI = 2, + TESTMODE_CMD_ID_HS20 = 3, + + /* Hotspot managerment testmode command */ + TESTMODE_CMD_ID_HS_CONFIG = 51, + + TESTMODE_CMD_ID_STR_CMD = 102, + NUM_OF_TESTMODE_CMD_ID +}; + +#if CFG_SUPPORT_PASSPOINT +enum Hs20CmdType { + HS20_CMD_ID_SET_BSSID_POOL = 0, + NUM_OF_HS20_CMD_ID +}; +#endif /* CFG_SUPPORT_PASSPOINT */ + +struct NL80211_DRIVER_TEST_MODE_PARAMS { + uint32_t index; + uint32_t buflen; +}; + +struct NL80211_DRIVER_STRING_CMD_PARAMS { + struct NL80211_DRIVER_TEST_MODE_PARAMS hdr; + uint32_t reply_buf_size; + uint32_t reply_len; + uint8_t *reply_buf; +}; + +/*SW CMD */ +struct NL80211_DRIVER_SW_CMD_PARAMS { + struct NL80211_DRIVER_TEST_MODE_PARAMS hdr; + uint8_t set; + uint32_t adr; + uint32_t data; +}; + +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 */ + /*!< ff:ff:ff:ff:ff:ff for broadcast/multicast + * (group) keys or unicast address for + * individual keys + */ + __u8 addr[MAC_ADDR_LEN]; + __u16 alg; /*!< IW_ENCODE_ALG_* */ + __u16 key_len; + __u8 key[32]; +}; + +/*SET KEY EXT */ +struct NL80211_DRIVER_SET_KEY_EXTS { + struct NL80211_DRIVER_TEST_MODE_PARAMS hdr; + uint8_t key_index; + uint8_t key_len; + struct iw_encode_exts ext; +}; + +#if CFG_SUPPORT_PASSPOINT + +struct param_hs20_set_bssid_pool { + uint8_t fgBssidPoolIsEnable; + uint8_t ucNumBssidPool; + uint8_t arBssidPool[8][ETH_ALEN]; +}; + +struct wpa_driver_hs20_data_s { + struct NL80211_DRIVER_TEST_MODE_PARAMS hdr; + enum Hs20CmdType CmdType; + struct param_hs20_set_bssid_pool hs20_set_bssid_pool; +}; + +#endif /* CFG_SUPPORT_PASSPOINT */ + +#endif + +struct NETDEV_PRIVATE_GLUE_INFO { + struct GLUE_INFO *prGlueInfo; + uint8_t ucBssIdx; +#if CFG_ENABLE_UNIFY_WIPHY + u_int8_t ucIsP2p; +#endif +}; + +struct PACKET_PRIVATE_DATA { + /* tx/rx both use cb */ + struct QUE_ENTRY rQueEntry; /* 16byte total:16 */ + + uint8_t ucBssIdx; /* 1byte */ + /* only rx use cb */ + u_int8_t fgIsIndependentPkt; /* 1byte */ + /* only tx use cb */ + uint8_t ucTid; /* 1byte */ + uint8_t ucHeaderLen; /* 1byte */ + uint8_t ucProfilingFlag; /* 1byte */ + uint8_t ucSeqNo; /* 1byte */ + uint16_t u2Flag; /* 2byte total:24 */ + + uint16_t u2IpId; /* 2byte */ + uint16_t u2FrameLen; /* 2byte */ + OS_SYSTIME rArrivalTime;/* 4byte total:32 */ + + uint64_t u8ArriveTime; /* 8byte total:40 */ +}; + +struct PACKET_PRIVATE_RX_DATA { + uint64_t u8IntTime; /* 8byte */ + uint64_t u8RxTime; /* 8byte */ +}; + +/******************************************************************************* + * P U B 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 */ +/*----------------------------------------------------------------------------*/ +/* TODO: we have to lock source another is in kalAcquireSpinLock */ +#define GLUE_SPIN_LOCK_DECLARATION() +#define GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, rLockCategory) +#define GLUE_RELEASE_SPIN_LOCK(prGlueInfo, rLockCategory) +/*----------------------------------------------------------------------------*/ +/* Macros for accessing Reserved Fields of native packet */ +/*----------------------------------------------------------------------------*/ +/* TODO: os-related, implementation may refer to os/linux */ +#define GLUE_GET_PKT_PRIVATE_DATA(_p) ((struct PACKET_PRIVATE_DATA *)0) + +#define GLUE_GET_PKT_QUEUE_ENTRY(_p) \ + (&(GLUE_GET_PKT_PRIVATE_DATA(_p)->rQueEntry)) + +/* TODO: os-related implementation */ +#define GLUE_GET_PKT_DESCRIPTOR(_prQueueEntry) ((struct PACKET_PRIVATE_DATA *)0) + +#define GLUE_SET_PKT_TID(_p, _tid) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucTid = (uint8_t)(_tid)) + +#define GLUE_GET_PKT_TID(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucTid) + +#define GLUE_SET_PKT_FLAG(_p, _flag) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2Flag |= BIT(_flag)) + +#define GLUE_TEST_PKT_FLAG(_p, _flag) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2Flag & BIT(_flag)) + +#define GLUE_IS_PKT_FLAG_SET(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2Flag) + +#define GLUE_SET_PKT_BSS_IDX(_p, _ucBssIndex) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucBssIdx = (uint8_t)(_ucBssIndex)) + +#define GLUE_GET_PKT_BSS_IDX(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucBssIdx) + +#define GLUE_SET_PKT_HEADER_LEN(_p, _ucMacHeaderLen) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucHeaderLen = \ + (uint8_t)(_ucMacHeaderLen)) + +#define GLUE_GET_PKT_HEADER_LEN(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucHeaderLen) + +#define GLUE_SET_PKT_FRAME_LEN(_p, _u2PayloadLen) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2FrameLen = (uint16_t)(_u2PayloadLen)) + +#define GLUE_GET_PKT_FRAME_LEN(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2FrameLen) + +#define GLUE_SET_PKT_ARRIVAL_TIME(_p, _rSysTime) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->rArrivalTime = (OS_SYSTIME)(_rSysTime)) + +#define GLUE_GET_PKT_ARRIVAL_TIME(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->rArrivalTime) + +#define GLUE_SET_PKT_IP_ID(_p, _u2IpId) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2IpId = (uint16_t)(_u2IpId)) + +#define GLUE_GET_PKT_IP_ID(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2IpId) + +#define GLUE_SET_PKT_SEQ_NO(_p, _ucSeqNo) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucSeqNo = (uint8_t)(_ucSeqNo)) + +#define GLUE_GET_PKT_SEQ_NO(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucSeqNo) + +#define GLUE_SET_PKT_FLAG_PROF_MET(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucProfilingFlag |= BIT(0)) + +#define GLUE_GET_PKT_IS_PROF_MET(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucProfilingFlag & BIT(0)) + +#define GLUE_SET_PKT_XTIME(_p, _rSysTime) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u8ArriveTime = (uint64_t)(_rSysTime)) + +#define GLUE_GET_PKT_XTIME(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u8ArriveTime) + +/* TODO: os-related implementation */ +#define GLUE_GET_PKT_PRIVATE_RX_DATA(_p) \ + ((struct PACKET_PRIVATE_RX_DATA *)(&(((struct sk_buff *)(_p))->cb[24]))) + +#define GLUE_RX_SET_PKT_INT_TIME(_p, _rTime) \ + (GLUE_GET_PKT_PRIVATE_RX_DATA(_p)->u8IntTime = (uint64_t)(_rTime)) + +#define GLUE_RX_GET_PKT_INT_TIME(_p) \ + (GLUE_GET_PKT_PRIVATE_RX_DATA(_p)->u8IntTime) + +#define GLUE_RX_SET_PKT_RX_TIME(_p, _rTime) \ + (GLUE_GET_PKT_PRIVATE_RX_DATA(_p)->u8RxTime = (uint64_t)(_rTime)) + +#define GLUE_RX_GET_PKT_RX_TIME(_p) \ + (GLUE_GET_PKT_PRIVATE_RX_DATA(_p)->u8RxTime) + +/* TODO: os-related implementation */ +#define GLUE_GET_PKT_ETHER_DEST_ADDR(_p) + +/* Check validity of prDev, private data, and pointers */ +/* TODO: os-related implementation */ +#define GLUE_CHK_DEV(prDev) + +#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) +/* TODO: os-related implementation */ +#define GLUE_INC_REF_CNT(_refCount) (_refCount++) +#define GLUE_DEC_REF_CNT(_refCount) (_refCount--) +#define GLUE_ADD_REF_CNT(_value, _refCount) \ + (_refCount += _value) +#define GLUE_SUB_REF_CNT(_value, _refCount) \ + (_refCount -= _value) +#define GLUE_GET_REF_CNT(_refCount) (_refCount) + +#define DbgPrint(...) + +#define GLUE_LOOKUP_FUN(fun_name) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + + +#if CFG_MET_TAG_SUPPORT +#define GL_MET_TAG_START(_id, _name) met_tag_start(_id, _name) +#define GL_MET_TAG_END(_id, _name) met_tag_end(_id, _name) +#define GL_MET_TAG_ONESHOT(_id, _name, _value) \ + met_tag_oneshot(_id, _name, _value) +#define GL_MET_TAG_DISABLE(_id) met_tag_disable(_id) +#define GL_MET_TAG_ENABLE(_id) met_tag_enable(_id) +#define GL_MET_TAG_REC_ON() met_tag_record_on() +#define GL_MET_TAG_REC_OFF() met_tag_record_off() +#define GL_MET_TAG_INIT() met_tag_init() +#define GL_MET_TAG_UNINIT() met_tag_uninit() +#else +#define GL_MET_TAG_START(_id, _name) +#define GL_MET_TAG_END(_id, _name) +#define GL_MET_TAG_ONESHOT(_id, _name, _value) +#define GL_MET_TAG_DISABLE(_id) +#define GL_MET_TAG_ENABLE(_id) +#define GL_MET_TAG_REC_ON() +#define GL_MET_TAG_REC_OFF() +#define GL_MET_TAG_INIT() +#define GL_MET_TAG_UNINIT() +#endif + +#define MET_TAG_ID 0 + +/*----------------------------------------------------------------------------*/ +/* Macros of Data Type Check */ +/*----------------------------------------------------------------------------*/ +/* Kevin: we don't have to call following function to inspect the data + * structure. + * It will check automatically while at compile time. + */ +/* TODO: os-related, API implementation, may refer to Linux */ +#define glPacketDataTypeCheck() + +#define mtk_wlan_ndev_select_queue(_prNetdev, _prSkb) + +#define netdev_for_each_mc_addr(mclist, dev) + +#define GET_ADDR(ha) + +#define LIST_FOR_EACH_IPV6_ADDR(_prIfa, _ip6_ptr) + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +#if WLAN_INCLUDE_PROC +int32_t procCreateFsEntry(struct GLUE_INFO *prGlueInfo); +int32_t procRemoveProcfs(void); + + +int32_t procInitFs(void); +int32_t procUninitProcFs(void); + + + +/* TODO: os-related, API implementation, may refer to Linux */ +#define procInitProcfs(_prDev, _pucDevName) +#endif /* WLAN_INCLUDE_PROC */ + +#if CFG_ENABLE_BT_OVER_WIFI +u_int8_t glRegisterAmpc(struct GLUE_INFO *prGlueInfo); + +u_int8_t glUnregisterAmpc(struct GLUE_INFO *prGlueInfo); +#endif + +#if CFG_ENABLE_WIFI_DIRECT +void p2pSetMulticastListWorkQueueWrapper(struct GLUE_INFO + *prGlueInfo); +#endif + +struct GLUE_INFO *wlanGetGlueInfo(void); + +#ifdef CFG_REMIND_IMPLEMENT +#define wlanSelectQueue(_dev, _skb) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#define wlanDebugInit() \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#else +u16 wlanSelectQueue(struct net_device *dev, + struct sk_buff *skb); + +void wlanDebugInit(void); +#endif + +uint32_t wlanSetDriverDbgLevel(IN uint32_t u4DbgIdx, + IN uint32_t u4DbgMask); + +uint32_t wlanGetDriverDbgLevel(IN uint32_t u4DbgIdx, + OUT uint32_t *pu4DbgMask); + +void wlanSetSuspendMode(struct GLUE_INFO *prGlueInfo, + u_int8_t fgEnable); + +#ifdef CFG_REMIND_IMPLEMENT +#define wlanGetConfig(_prAdapter) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#else +void wlanGetConfig(struct ADAPTER *prAdapter); +#endif + +uint32_t wlanDownloadBufferBin(struct ADAPTER *prAdapter); + +uint32_t wlanConnacDownloadBufferBin(struct ADAPTER + *prAdapter); + +/******************************************************************************* + * E X T E R N A L F U N C T I O N S / V A R I A B L E + ******************************************************************************* + */ +extern struct net_device *gPrP2pDev[KAL_P2P_NUM]; +extern struct net_device *gPrDev; +extern struct wireless_dev *gprWdev[KAL_AIS_NUM]; +extern uint32_t g_u4DevIdx[KAL_P2P_NUM]; +extern enum ENUM_NVRAM_STATE g_NvramFsm; + +#ifdef CFG_DRIVER_INF_NAME_CHANGE +extern char *gprifnameap; +extern char *gprifnamep2p; +extern char *gprifnamesta; +#endif /* CFG_DRIVER_INF_NAME_CHANGE */ + +extern void wlanRegisterNotifier(void); +extern void wlanUnregisterNotifier(void); +#if CFG_MTK_ANDROID_WMT +typedef int (*set_p2p_mode) (struct net_device *netdev, + struct PARAM_CUSTOM_P2P_SET_STRUCT p2pmode); +extern void register_set_p2p_mode_handler( + set_p2p_mode handler); +#endif + +#if CFG_ENABLE_EARLY_SUSPEND +extern int glRegisterEarlySuspend(struct early_suspend + *prDesc, + early_suspend_callback wlanSuspend, + late_resume_callback wlanResume); + +extern int glUnregisterEarlySuspend(struct early_suspend + *prDesc); +#endif + +#if CFG_MET_PACKET_TRACE_SUPPORT +#ifdef CFG_REMIND_IMPLEMENT +#define kalMetTagPacket(_prGlueInfo, _prPacket, _eTag) \ +KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#else +void kalMetTagPacket(IN struct GLUE_INFO *prGlueInfo, + IN void *prPacket, IN enum ENUM_TX_PROFILING_TAG eTag); +#endif + +void kalMetInit(IN struct GLUE_INFO *prGlueInfo); +#endif + +#ifdef CFG_REMIND_IMPLEMENT +#define wlanUpdateChannelTable(_prGlueInfo) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#else +void wlanUpdateChannelTable(struct GLUE_INFO *prGlueInfo); +#endif + +#if CFG_SUPPORT_SAP_DFS_CHANNEL +#ifdef CFG_REMIND_IMPLEMENT +#define wlanUpdateDfsChannelTable(_prGlueInfo, \ + _ucRoleIdx, _ucChannel, _ucBandWidth, \ + _eBssSCO, _u4CenterFreq) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#else +void wlanUpdateDfsChannelTable(struct GLUE_INFO *prGlueInfo, + uint8_t ucRoleIdx, uint8_t ucChannel, uint8_t ucBandWidth, + enum ENUM_CHNL_EXT eBssSCO, uint32_t u4CenterFreq); +#endif +#endif + +#if (CFG_MTK_ANDROID_WMT || WLAN_INCLUDE_PROC) +int set_p2p_mode_handler(struct net_device *netdev, + struct PARAM_CUSTOM_P2P_SET_STRUCT p2pmode); +#endif + +#if CFG_ENABLE_UNIFY_WIPHY +const struct net_device_ops *wlanGetNdevOps(void); +#endif + +#if CFG_MTK_ANDROID_WMT +extern void connectivity_flush_dcache_area(void *addr, size_t len); +extern void connectivity_arch_setup_dma_ops( + struct device *dev, u64 dma_base, + u64 size, struct iommu_ops *iommu, + bool coherent); +#endif + +#define wlanHardStartXmit(_prSkb, _prDev) + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(arr) \ + (sizeof(arr) / sizeof(((typeof(arr)){})[0])) +#endif +#endif /* _GL_OS_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_p2p_ioctl.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_p2p_ioctl.h new file mode 100644 index 0000000000000..31f5cbc3199e4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_p2p_ioctl.h @@ -0,0 +1,857 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * os/none/include/gl_p2p_ioctl.h#9 + */ + +/*! \file gl_p2p_ioctl.h + * \brief This file is for custom ioctls for Wi-Fi Direct only + */ + + +#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 "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 + +#define CHN_DIRTY_WEIGHT_UPPERBOUND 4 + +/****************************************************************************** + * D A T A T Y P E S + ****************************************************************************** + */ +/*------------------------------------------------------------------------*/ +/* Wireless Extension: Private I/O Control */ +/*------------------------------------------------------------------------*/ + +#if 0 +struct iw_p2p_cfg_device_type { + void __user *ssid; + uint8_t ssid_len; + uint8_t pri_device_type[8]; + uint8_t snd_device_type[8]; + void __user *device_name; + uint8_t device_name_len; + uint8_t intend; + uint8_t persistence; + uint8_t sec_mode; + uint8_t ch; + uint8_t ch_width; /* 0: 20 Mhz 1:20/40 Mhz auto */ + uint8_t max_scb; +}; + +struct iw_p2p_hostapd_param { + uint8_t cmd; + uint8_t rsv[3]; + uint8_t sta_addr[6]; + void __user *data; + uint16_t len; +}; + +struct iw_p2p_req_device_type { + uint8_t scan_type; /* 0: Full scan + Find + * 1: Full scan + * 2: Scan (Search +Listen) + * 3: Listen + * other : reserved + */ + uint8_t pri_device_type[8]; + void __user *probe_req_ie; + uint16_t probe_req_len; + void __user *probe_rsp_ie; + uint16_t probe_rsp_len; +}; + +struct iw_p2p_connect_device { + uint8_t sta_addr[6]; + /* 0: P2P Device, 1:GC, 2: GO */ + uint8_t p2pRole; + /* 0: Don't needed provision, 1: doing the wsc provision first */ + uint8_t needProvision; + /* 1: auth peer invitation request */ + uint8_t authPeer; + /* Request Peer Device used config method */ + uint8_t intend_config_method; +}; + +struct iw_p2p_password_ready { + uint8_t active_config_method; + void __user *probe_req_ie; + uint16_t probe_req_len; + void __user *probe_rsp_ie; + uint16_t probe_rsp_len; +}; + +struct iw_p2p_device_req { + uint8_t name[33]; + uint32_t name_len; + uint8_t device_addr[6]; + uint8_t device_type; + int32_t config_method; + int32_t active_config_method; +}; + +struct iw_p2p_transport_struct { + uint32_t u4CmdId; + uint32_t inBufferLength; + uint32_t outBufferLength; + uint8_t aucBuffer[16]; +}; + +/* For Invitation */ +struct iw_p2p_ioctl_invitation_struct { + uint8_t aucDeviceID[6]; + /* BSSID */ + uint8_t aucGroupID[6]; + uint8_t aucSsid[32]; + uint32_t u4SsidLen; + uint8_t ucReinvoke; +}; + +struct iw_p2p_ioctl_abort_invitation { + uint8_t dev_addr[6]; +}; + +struct iw_p2p_ioctl_invitation_indicate { + uint8_t dev_addr[6]; + uint8_t group_bssid[6]; + /* peer device supported config method */ + int32_t config_method; + /* for reinvoke */ + uint8_t dev_name[32]; + uint32_t name_len; + /* for re-invoke, target operating channel */ + uint8_t operating_channel; + /* invitation or re-invoke */ + uint8_t invitation_type; +}; + +struct iw_p2p_ioctl_invitation_status { + uint32_t status_code; +}; + +/* For Formation */ +struct iw_p2p_ioctl_start_formation { + /* bssid */ + uint8_t dev_addr[6]; + /* 0: P2P Device, 1:GC, 2: GO */ + uint8_t role; + /* 0: Don't needed provision, 1: doing the wsc provision first */ + uint8_t needProvision; + /* 1: auth peer invitation request */ + uint8_t auth; + /* Request Peer Device used config method */ + + uint8_t config_method; +}; +#endif +/* SET_STRUCT / GET_STRUCT */ +enum ENUM_P2P_CMD_ID { + 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) */ + /* CFG_SUPPORT_ANTI_PIRACY */ + P2P_CMD_ID_SEC_CHECK, /* 0x05(Set) */ + 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) */ +}; + +#if 0 /* not used though ... */ +/* Service Discovery */ +struct iw_p2p_cmd_send_sd_response { + uint8_t rReceiverAddr[PARAM_MAC_ADDR_LEN]; + uint8_t fgNeedTxDoneIndication; + uint8_t ucSeqNum; + uint16_t u2PacketLength; + uint8_t aucPacketContent[0]; /*native 802.11 */ +}; + +struct iw_p2p_cmd_get_sd_request { + uint8_t rTransmitterAddr[PARAM_MAC_ADDR_LEN]; + uint16_t u2PacketLength; + uint8_t aucPacketContent[0]; /*native 802.11 */ +}; + +struct iw_p2p_cmd_send_service_discovery_request { + uint8_t rReceiverAddr[PARAM_MAC_ADDR_LEN]; + uint8_t fgNeedTxDoneIndication; + uint8_t ucSeqNum; + uint16_t u2PacketLength; + uint8_t aucPacketContent[0]; /*native 802.11 */ +}; + +struct iw_p2p_cmd_get_sd_response { + uint8_t rTransmitterAddr[PARAM_MAC_ADDR_LEN]; + uint16_t u2PacketLength; + uint8_t aucPacketContent[0]; /*native 802.11 */ +}; + +struct iw_p2p_cmd_terminate_sd_phase { + uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN]; +}; + +struct iw_p2p_version { + uint32_t u4Version; +}; +#endif + +/****************************************************************************** + * P U B L I C D A T A + ****************************************************************************** + */ +extern struct ieee80211_supported_band mtk_band_2ghz; +extern struct ieee80211_supported_band mtk_band_5ghz; + +extern const uint32_t mtk_cipher_suites[6]; + + +/****************************************************************************** + * 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 = KAL_BAND_2GHZ, \ + .center_freq = (_freq), \ + .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 (CFG_ENABLE_WIFI_DIRECT_CFG_80211 != 0) +/* + * TODO: function is os-related, while may depend on the purpose of function + * to implement on other os + */ +#if 0 +#if KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE +struct wireless_dev *mtk_p2p_cfg80211_add_iface(struct wiphy *wiphy, + const char *name, + unsigned char name_assign_type, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params); +#else +struct wireless_dev *mtk_p2p_cfg80211_add_iface(struct wiphy *wiphy, + const char *name, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params); +#endif + +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_del_iface(struct wiphy *wiphy, + struct wireless_dev *wdev); + +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_set_mgmt_key(struct wiphy *wiphy, + struct net_device *dev, + u8 key_index); + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, + struct station_info *sinfo); +#else +int mtk_p2p_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, + struct station_info *sinfo); +#endif +int mtk_p2p_cfg80211_scan(struct wiphy *wiphy, + struct cfg80211_scan_request *request); + +void mtk_p2p_cfg80211_abort_scan(struct wiphy *wiphy, + struct wireless_dev *wdev); + +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, + struct wireless_dev *wdev, + enum nl80211_tx_power_setting type, + int mbm); + +int mtk_p2p_cfg80211_get_txpower(struct wiphy *wiphy, + struct wireless_dev *wdev, + int *dbm); + +int mtk_p2p_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, + unsigned int duration, + u64 *cookie); + +int mtk_p2p_cfg80211_cancel_remain_on_channel( + struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie); + +int mtk_p2p_cfg80211_set_power_mgmt(struct wiphy *wiphy, + struct net_device *dev, + bool enabled, + int timeout); + +#if (CFG_SUPPORT_DFS_MASTER == 1) + +#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_start_radar_detection(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef, + unsigned int cac_time_ms); +#else +int mtk_p2p_cfg80211_start_radar_detection(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef); +#endif + + +#if KERNEL_VERSION(3, 13, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_channel_switch(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_csa_settings *params); +#endif +#endif + +int mtk_p2p_cfg80211_change_bss(struct wiphy *wiphy, + struct net_device *dev, + struct bss_parameters *params); + +int mtk_p2p_cfg80211_deauth(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_deauth_request *req); + +int mtk_p2p_cfg80211_disassoc(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_disassoc_request *req); + +int mtk_p2p_cfg80211_start_ap(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ap_settings *settings); + +int mtk_p2p_cfg80211_change_beacon(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_beacon_data *info); + +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie); +#else +int mtk_p2p_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, + bool offchan, + unsigned int wait, + const u8 *buf, + size_t len, + bool no_cck, + bool dont_wait_for_ack, + u64 *cookie); +#endif + +#if KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, + struct station_del_parameters *params); +#elif KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, + const u8 *mac); +#else +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, + u8 *mac); +#endif + +int mtk_p2p_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie); + +int mtk_p2p_cfg80211_stop_ap(struct wiphy *wiphy, + struct net_device *dev); + +int mtk_p2p_cfg80211_set_channel(struct wiphy *wiphy, + struct cfg80211_chan_def *chandef); + +void mtk_p2p_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, + struct wireless_dev *wdev, + IN u16 frame_type, + IN bool reg); + +int +mtk_p2p_cfg80211_set_bitrate_mask(IN struct wiphy *wiphy, + IN struct net_device *dev, + IN const u8 *peer, + IN const struct cfg80211_bitrate_mask *mask); + +#ifdef CONFIG_NL80211_TESTMODE +#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_testmode_cmd(struct wiphy *wiphy, + struct wireless_dev *wdev, + void *data, + int len); +#else +int mtk_p2p_cfg80211_testmode_cmd(struct wiphy *wiphy, + void *data, + int len); +#endif +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); + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +int mtk_p2p_cfg80211_testmode_get_best_channel(IN struct wiphy *wiphy, + IN void *data, + IN int len); +#endif + +int mtk_p2p_cfg80211_testmode_hotspot_config_cmd(IN struct wiphy *wiphy, + IN void *data, + IN int len); + +#else +/* IGNORE KERNEL DEPENCY ERRORS*/ +/*#error "Please ENABLE kernel config (CONFIG_NL80211_TESTMODE) + * to support Wi-Fi Direct" + */ +#endif +#endif +#endif + +/* I/O control handlers */ +/* + * TODO: function is os-related, while may depend on the purpose of function + * to implement on other os + */ +#if 0 +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 struct GLUE_INFO *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); +#endif +#endif /* _GL_P2P_IOCTL_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_p2p_kal.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_p2p_kal.h new file mode 100644 index 0000000000000..b81772d2b198d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_p2p_kal.h @@ -0,0 +1,479 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + + +#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" +/* for some structure in p2p_ioctl.h */ +#include "gl_p2p_ioctl.h" +#include "nic/p2p.h" + +#if DBG +extern int allocatedMemSize; +#endif + + +#define kalP2pFuncGetChannelType(_rChnlSco, _prChannelType) + +/****************************************************************************** + * 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 struct GLUE_INFO *prGlueInfo, + IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN], + IN uint8_t ucSeqNum); + +void kalP2PIndicateSDResponse(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN], + IN uint8_t ucSeqNum); + +void kalP2PIndicateTXDone(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucSeqNum, IN uint8_t 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); + */ + +/*UINT_32 kalP2PGetFreqInKHz(IN P_GLUE_INFO_T prGlueInfo);*/ + +int32_t mtk_Netdev_To_RoleIdx(struct GLUE_INFO *prGlueInfo, + struct net_device *ndev, + uint8_t *pucRoleIdx); + +#ifdef CFG_REMIND_IMPLEMENT +#define kalP2PUpdateAssocInfo(_prGlueInfo, _pucFrameBody, _u4FrameBodyLen, \ + _fgReassocRequest, _ucBssIndex) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalP2PGetRole(_prGlueInfo, _ucRoleIdx) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalP2PSetRole(_prGlueInfo, _ucRole, _ucRoleIdx) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalP2PSetCipher(_prGlueInfo, _u4Cipher, _ucRoleIdx) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalP2PGetCipher(_prGlueInfo, _ucRoleIdx) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalP2PGetWepCipher(_prGlueInfo, _ucRoleIdx) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalP2PGetTkipCipher(_prGlueInfo, _ucRoleIdx) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalP2PGetCcmpCipher(_prGlueInfo, _ucRoleIdx) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) +#else +void +kalP2PUpdateAssocInfo(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucFrameBody, + IN uint32_t u4FrameBodyLen, + IN u_int8_t fgReassocRequest, + IN uint8_t ucBssIndex); + +uint8_t kalP2PGetRole(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIdx); + +void kalP2PSetRole(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRole, + IN uint8_t ucRoleIdx); + +void kalP2PSetCipher(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Cipher, + IN uint8_t ucRoleIdx); + +u_int8_t kalP2PGetCipher(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIdx); + +u_int8_t kalP2PGetWepCipher(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIdx); + +u_int8_t kalP2PGetTkipCipher(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIdx); + +u_int8_t kalP2PGetCcmpCipher(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIdx); +#endif + +void kalP2PSetWscMode(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucWscMode); + +uint8_t kalP2PGetWscMode(IN struct GLUE_INFO *prGlueInfo); + +#ifdef CFG_REMIND_IMPLEMENT +#define kalP2PCalWSC_IELen(_prGlueInfo, _ucType, _ucRoleIdx) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalP2PGenWSC_IE(_prGlueInfo, _ucType, _pucBuffer, _ucRoleIdx) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalP2PUpdateWSC_IE(_prGlueInfo, _ucType, _pucBuffer, \ + _u2BufferLength, _ucRoleIdx) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalP2PCalP2P_IELen(_prGlueInfo, _ucIndex, _ucRoleIdx) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalP2PGenP2P_IE(_prGlueInfo, _ucIndex, _pucBuffer, _ucRoleIdx) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalP2PUpdateP2P_IE(_prGlueInfo, _ucIndex, _pucBuffer, \ + _u2BufferLength, _ucRoleIdx) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) +#else +uint16_t kalP2PCalWSC_IELen(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucType, + IN uint8_t ucRoleIdx); + +void kalP2PGenWSC_IE(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucType, + IN uint8_t *pucBuffer, + IN uint8_t ucRoleIdx); + +void kalP2PUpdateWSC_IE(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucType, + IN uint8_t *pucBuffer, + IN uint16_t u2BufferLength, + IN uint8_t ucRoleIdx); + +uint16_t kalP2PCalP2P_IELen(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucIndex, + IN uint8_t ucRoleIdx); + +void kalP2PGenP2P_IE(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucIndex, + IN uint8_t *pucBuffer, + IN uint8_t ucRoleIdx); + +void kalP2PUpdateP2P_IE(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucIndex, + IN uint8_t *pucBuffer, + IN uint16_t u2BufferLength, + IN uint8_t ucRoleIdx); +#endif + +u_int8_t kalP2PIndicateFound(IN struct GLUE_INFO *prGlueInfo); + +void kalP2PIndicateConnReq(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucDevName, + IN int32_t u4NameLength, + IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN], + IN uint8_t ucDevType, /* 0: P2P Device / 1: GC / 2: GO */ + IN int32_t i4ConfigMethod, + IN int32_t i4ActiveConfigMethod); + +/*VOID kalP2PInvitationStatus(IN P_GLUE_INFO_T prGlueInfo, + * IN UINT_32 u4InvStatus); + */ + +void +kalP2PInvitationIndication(IN struct GLUE_INFO *prGlueInfo, + IN struct P2P_DEVICE_DESC *prP2pDevDesc, + IN uint8_t *pucSsid, + IN uint8_t ucSsidLen, + IN uint8_t ucOperatingChnl, + IN uint8_t ucInvitationType, + IN uint8_t *pucGroupBssid); + +struct net_device *kalP2PGetDevHdlr(struct GLUE_INFO *prGlueInfo); + +void +kalGetChnlList(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_BAND eSpecificBand, + IN uint8_t ucMaxChannelNum, + IN uint8_t *pucNumOfChannel, + IN struct RF_CHANNEL_INFO *paucChannelList); + +#if CFG_SUPPORT_ANTI_PIRACY +void kalP2PIndicateSecCheckRsp(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucRsp, + IN uint16_t u2RspLen); +#endif + +/****************************************************************************** + * F U N C T I O N S + ****************************************************************************** + */ + +#ifdef CFG_REMIND_IMPLEMENT +#define kalP2PIndicateChannelReady(_prGlueInfo, _u8SeqNum, _u4ChannelNum, \ + _eBand, _eSco, _u4Duration) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalP2PIndicateScanDone(_prGlueInfo, _ucRoleIndex, _fgIsAbort) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalP2PIndicateBssInfo(_prGlueInfo, _pucFrameBuf, _u4BufLen, \ + _prChannelInfo, _i4SignalStrength) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalP2PIndicateRxMgmtFrame(_prGlueInfo, _prSwRfb, \ + _fgIsDevInterface, _ucRoleIdx) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalP2PIndicateMgmtTxStatus(_prGlueInfo, _prMsduInfo, _fgIsAck) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalP2PIndicateChannelExpired(_prGlueInfo, _u8SeqNum, \ + _u4ChannelNum, _eBand, _eSco) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalP2PGCIndicateConnectionStatus(_prGlueInfo, _ucRoleIndex, \ + _prP2pConnInfo, _pucRxIEBuf, _u2RxIELen, _u2StatusReason) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalP2PGOStationUpdate(_pr, _ucRoleIndex, _prCliStaRec, _fgIsNew) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _pr) +#else +void +kalP2PIndicateChannelReady(IN struct GLUE_INFO *prGlueInfo, + IN uint64_t u8SeqNum, + IN uint32_t u4ChannelNum, + IN enum ENUM_BAND eBand, + IN enum ENUM_CHNL_EXT eSco, + IN uint32_t u4Duration); + +void kalP2PIndicateScanDone(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex, + IN u_int8_t fgIsAbort); + +void +kalP2PIndicateBssInfo(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucFrameBuf, + IN uint32_t u4BufLen, + IN struct RF_CHANNEL_INFO *prChannelInfo, + IN int32_t i4SignalStrength); + +void +kalP2PIndicateRxMgmtFrame(IN struct GLUE_INFO *prGlueInfo, + IN struct SW_RFB *prSwRfb, + IN u_int8_t fgIsDevInterface, + IN uint8_t ucRoleIdx); + +void kalP2PIndicateMgmtTxStatus(IN struct GLUE_INFO *prGlueInfo, + IN struct MSDU_INFO *prMsduInfo, + IN u_int8_t fgIsAck); + +void +kalP2PIndicateChannelExpired(IN struct GLUE_INFO *prGlueInfo, + IN uint64_t u8SeqNum, + IN uint32_t u4ChannelNum, + IN enum ENUM_BAND eBand, + IN enum ENUM_CHNL_EXT eSco); + +void +kalP2PGCIndicateConnectionStatus(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex, + IN struct P2P_CONNECTION_REQ_INFO *prP2pConnInfo, + IN uint8_t *pucRxIEBuf, + IN uint16_t u2RxIELen, + IN uint16_t u2StatusReason); + +void +kalP2PGOStationUpdate(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex, + IN struct STA_RECORD *prCliStaRec, + IN u_int8_t fgIsNew); +#endif + +#if (CFG_SUPPORT_DFS_MASTER == 1) +#ifdef CFG_REMIND_IMPLEMENT +#define kalP2PRddDetectUpdate(_prGlueInfo, _ucRoleIndex) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalP2PCacFinishedUpdate(_prGlueInfo, _ucRoleIndex) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) +#else +void +kalP2PRddDetectUpdate(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex); + +void +kalP2PCacFinishedUpdate(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex); +#endif +#endif + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + +u_int8_t kalP2PSetBlackList(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t rbssid[PARAM_MAC_ADDR_LEN], + IN u_int8_t fgIsblock, + IN uint8_t ucRoleIndex); + +u_int8_t kalP2PResetBlackList(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex); + +void kalP2PSetMaxClients(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4MaxClient, + IN uint8_t ucRoleIndex); + +#ifdef CFG_REMIND_IMPLEMENT +#define kalP2PCmpBlackList(_prGlueInfo, _rbssid, _ucRoleIndex) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalP2PMaxClients(_prGlueInfo, _u4NumClient, _ucRoleIndex) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) +#else +u_int8_t kalP2PCmpBlackList(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t rbssid[PARAM_MAC_ADDR_LEN], + IN uint8_t ucRoleIndex); + +u_int8_t kalP2PMaxClients(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4NumClient, + IN uint8_t ucRoleIndex); +#endif +#endif + +#ifdef CFG_REMIND_IMPLEMENT +#define kalP2pUnlinkBss(_prGlueInfo, _aucBSSID) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalP2pIndicateQueuedMgmtFrame(_prGlueInfo, _prFrame) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalP2pIndicateAcsResult(_prGlueInfo, _ucRoleIndex, _ucPrimaryCh,\ + _ucSecondCh, _ucSeg0Ch, _ucSeg1Ch, _eChnlBw) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__, _prGlueInfo) + +#define kalP2pNotifyStopApComplete(_prAdapter, _ucRoleIndex) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define kalP2pIndicateChnlSwitch(_prAdapter, _prBssInfo) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#else +void kalP2pUnlinkBss(IN struct GLUE_INFO *prGlueInfo, IN uint8_t aucBSSID[]); + +void kalP2pIndicateQueuedMgmtFrame(IN struct GLUE_INFO *prGlueInfo, + IN struct P2P_QUEUED_ACTION_FRAME *prFrame); + +void kalP2pIndicateAcsResult(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex, + IN uint8_t ucPrimaryCh, + IN uint8_t ucSecondCh, + IN uint8_t ucSeg0Ch, + IN uint8_t ucSeg1Ch, + IN enum ENUM_MAX_BANDWIDTH_SETTING eChnlBw); + +void kalP2pNotifyStopApComplete(IN struct ADAPTER *prAdapter, + IN uint8_t ucRoleIndex); + +void kalP2pIndicateChnlSwitch(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo); +#endif +#endif /* _GL_P2P_KAL_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_p2p_os.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_p2p_os.h new file mode 100644 index 0000000000000..05842f3ede650 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_p2p_os.h @@ -0,0 +1,386 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 + ****************************************************************************** + */ + +/****************************************************************************** + * E X T E R N A L V A R I A B L E + ****************************************************************************** + */ +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_WIFI_DIRECT_CFG_80211 +extern const struct net_device_ops p2p_netdev_ops; +#endif + +/****************************************************************************** + * C O N S T A N T S + ****************************************************************************** + */ + +/****************************************************************************** + * M A C R O S + ****************************************************************************** + */ + +/* For SET_STRUCT/GET_STRUCT */ +#define OID_SET_GET_STRUCT_LENGTH 4096 + +#define MAX_P2P_IE_SIZE 5 + +#define P2P_MAXIMUM_CLIENT_COUNT 16 +#define P2P_DEFAULT_CLIENT_COUNT 4 + +/****************************************************************************** + * D A T A T Y P E S + ****************************************************************************** + */ + +/****************************************************************************** + * P U B L I C D A T A + ****************************************************************************** + */ + +extern struct net_device *g_P2pPrDev; +extern struct wireless_dev *gprP2pWdev; +extern struct wireless_dev *gprP2pRoleWdev[KAL_P2P_NUM]; + +/****************************************************************************** + * 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 { + + /* P2P Device interface handle */ + /*only first p2p have this devhandler*/ + struct net_device *prDevHandler; + /*struct net_device *prRoleDevHandler;*//* TH3 multiple P2P */ + + struct net_device *aprRoleHandler; + + /* Todo : should move to the glueinfo or not*/ + /*UINT_8 ucRoleInterfaceNum;*//* TH3 multiple P2P */ + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + /* cfg80211 */ + struct wireless_dev *prWdev; + /*struct wireless_dev *prRoleWdev[KAL_P2P_NUM];*//* TH3 multiple P2P */ + + /*struct cfg80211_scan_request *prScanRequest;*//* TH3 multiple P2P */ + + /*UINT_64 u8Cookie;*//* TH3 multiple P2P */ + + /* Generation for station list update. */ + int32_t i4Generation; + + /*UINT_32 u4OsMgmtFrameFilter;*//* TH3 multiple P2P */ + +#endif + + /* Device statistics */ + /*struct net_device_stats rNetDevStats;*//* TH3 multiple P2P */ + + /* glue layer variables */ + /*move to glueinfo->adapter */ + /* BOOLEAN fgIsRegistered; */ + /*UINT_32 u4FreqInKHz;*//* TH3 multiple P2P */ /* frequency */ + /* 0: P2P Device, 1: Group Client, 2: Group Owner */ + uint8_t ucRole; + /*UINT_8 ucIntent;*//* TH3 multiple P2P */ /* range: 0-15 */ + /* 0: Search & Listen, 1: Scan without probe response */ + /*UINT_8 ucScanMode;*//* TH3 multiple P2P */ + + /*ENUM_PARAM_MEDIA_STATE_T eState;*//* TH3 multiple P2P */ + /*UINT_32 u4PacketFilter;*//* TH3 multiple P2P */ + /* TH3 multiple P2P */ + /*PARAM_MAC_ADDRESS aucMCAddrList[MAX_NUM_GROUP_ADDR];*/ + + /* connection-requested peer information *//* TH3 multiple P2P */ + /*UINT_8 aucConnReqDevName[32];*//* TH3 multiple P2P */ + /*INT_32 u4ConnReqNameLength;*//* TH3 multiple P2P */ + /*PARAM_MAC_ADDRESS rConnReqPeerAddr;*//* TH3 multiple P2P */ + /* For invitation group. */ + /*PARAM_MAC_ADDRESS rConnReqGroupAddr;*//* TH3 multiple P2P */ + /*UINT_8 ucConnReqDevType;*//* TH3 multiple P2P */ + /*INT_32 i4ConnReqConfigMethod;*//* TH3 multiple P2P */ + /*INT_32 i4ConnReqActiveConfigMethod;*//* TH3 multiple P2P */ + + uint32_t u4CipherPairwise; + /*UINT_8 ucWSCRunning;*//* TH3 multiple P2P */ + + /* 0: beacon, 1: probe req, 2:probe response, 3: assoc response */ + uint8_t aucWSCIE[4][400]; + uint16_t u2WSCIELen[4]; + + uint8_t aucP2PIE[MAX_P2P_IE_SIZE][400]; + uint16_t u2P2PIELen[MAX_P2P_IE_SIZE]; + +#if CFG_SUPPORT_WFD + /* 0 for beacon, 1 for probe req, 2 for probe response */ + uint8_t aucWFDIE[400]; + uint16_t u2WFDIELen; + /* Save the other IE for probe resp */ +#if CFG_SUPPORT_CUSTOM_VENDOR_IE + uint8_t aucVenderIE[1024]; + uint16_t u2VenderIELen; +#endif +#endif + + /*UINT_8 ucOperatingChnl;*//* TH3 multiple P2P */ + /*UINT_8 ucInvitationType;*//* TH3 multiple P2P */ + + /*UINT_32 u4InvStatus;*//* TH3 multiple P2P */ + + /* For SET_STRUCT/GET_STRUCT */ + /*UINT_8 aucOidBuf[OID_SET_GET_STRUCT_LENGTH];*//* TH3 multiple P2P */ + +#if 1 /* CFG_SUPPORT_ANTI_PIRACY */ + /*UINT_8 aucSecCheck[256];*//* TH3 multiple P2P */ + /*UINT_8 aucSecCheckRsp[256];*//* TH3 multiple P2P */ +#endif + +#if (CFG_SUPPORT_DFS_MASTER == 1) + struct cfg80211_chan_def *chandef; + uint32_t cac_time_ms; +#endif + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + uint8_t aucblackMACList[P2P_MAXIMUM_CLIENT_COUNT][PARAM_MAC_ADDR_LEN]; + uint8_t ucMaxClients; +#endif + +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION + /*BOOLEAN fgEnableHotspotOptimization;*//* TH3 multiple P2P */ + /*UINT_32 u4PsLevel;*//* TH3 multiple P2P */ +#endif + + enum ENUM_CHNL_SWITCH_POLICY eChnlSwitchPolicy; +}; + +struct GL_P2P_DEV_INFO { +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + struct cfg80211_scan_request *prScanRequest; +#if 0 + struct cfg80211_scan_request rBackupScanRequest; +#endif + uint64_t u8Cookie; + uint32_t u4OsMgmtFrameFilter; +#endif + uint32_t u4PacketFilter; + uint8_t aucMCAddrList[MAX_NUM_GROUP_ADDR][PARAM_MAC_ADDR_LEN]; + uint8_t ucWSCRunning; +}; + +#ifdef CONFIG_NL80211_TESTMODE +struct NL80211_DRIVER_TEST_PRE_PARAMS { + uint16_t idx_mode; + uint16_t idx; + uint32_t value; +}; + +struct NL80211_DRIVER_TEST_PARAMS { + uint32_t index; + uint32_t buflen; +}; + +/* P2P Sigma*/ +struct NL80211_DRIVER_P2P_SIGMA_PARAMS { + struct NL80211_DRIVER_TEST_PARAMS hdr; + uint32_t idx; + uint32_t value; +}; + +/* Hotspot Client Management */ +struct NL80211_DRIVER_hotspot_block_PARAMS { + struct NL80211_DRIVER_TEST_PARAMS hdr; + uint8_t ucblocked; + uint8_t aucBssid[MAC_ADDR_LEN]; +}; + +/* Hotspot Management set config */ +struct NL80211_DRIVER_HOTSPOT_CONFIG_PARAMS { + struct NL80211_DRIVER_TEST_PARAMS hdr; + uint32_t idx; + uint32_t value; +}; + +#if CFG_SUPPORT_WFD +struct NL80211_DRIVER_WFD_PARAMS { + struct NL80211_DRIVER_TEST_PARAMS hdr; + uint32_t WfdCmdType; + uint8_t WfdEnable; + uint8_t WfdCoupleSinkStatus; + uint8_t WfdSessionAvailable; + uint8_t WfdSigmaMode; + uint16_t WfdDevInfo; + uint16_t WfdControlPort; + uint16_t WfdMaximumTp; + uint16_t WfdExtendCap; + uint8_t WfdCoupleSinkAddress[MAC_ADDR_LEN]; + uint8_t WfdAssociatedBssid[MAC_ADDR_LEN]; + uint8_t WfdVideoIp[4]; + uint8_t WfdAudioIp[4]; + uint16_t WfdVideoPort; + uint16_t WfdAudioPort; + uint32_t WfdFlag; + uint32_t WfdPolicy; + uint32_t WfdState; + /* Include Subelement ID, length */ + uint8_t WfdSessionInformationIE[24 * 8]; + uint16_t WfdSessionInformationIELen; + uint8_t aucReserved1[2]; + uint8_t aucWfdPrimarySinkMac[MAC_ADDR_LEN]; + uint8_t aucWfdSecondarySinkMac[MAC_ADDR_LEN]; + uint32_t WfdAdvanceFlag; + /* Group 1 64 bytes */ + uint8_t aucWfdLocalIp[4]; + uint16_t WfdLifetimeAc2; /* Unit is 2 TU */ + uint16_t WfdLifetimeAc3; /* Unit is 2 TU */ + uint16_t WfdCounterThreshold; /* Unit is ms */ + uint8_t aucReserved2[54]; + /* Group 3 64 bytes */ + uint8_t aucReserved3[64]; + /* Group 3 64 bytes */ + uint8_t aucReserved4[64]; +}; +#endif +#endif + +/****************************************************************************** + * P U B L I C D A T A + ****************************************************************************** + */ + +/****************************************************************************** + * P R I V A T E D A T A + ****************************************************************************** + */ + +u_int8_t p2pRegisterToWlan(struct GLUE_INFO *prGlueInfo); + +u_int8_t p2pUnregisterToWlan(struct GLUE_INFO *prGlueInfo); + +#ifdef CFG_REMIND_IMPLEMENT +#define p2pLaunch(_prGlueInfo) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define p2pRemove(_prGlueInfo) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define p2pSetMode(_ucAPMode) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#else +u_int8_t p2pLaunch(struct GLUE_INFO *prGlueInfo); + +u_int8_t p2pRemove(struct GLUE_INFO *prGlueInfo); + +void p2pSetMode(IN uint8_t ucAPMode); +#endif + +u_int8_t glRegisterP2P(struct GLUE_INFO *prGlueInfo, + const char *prDevName, + const char *prDevName2, + uint8_t ucApMode); + +int glSetupP2P(struct GLUE_INFO *prGlueInfo, + struct wireless_dev *prP2pWdev, + struct net_device *prP2pDev, + uint8_t u4Idx, + u_int8_t fgIsApMode); + +u_int8_t glUnregisterP2P(struct GLUE_INFO *prGlueInfo, uint8_t ucIdx); + +u_int8_t p2pNetRegister(struct GLUE_INFO *prGlueInfo, + u_int8_t fgIsRtnlLockAcquired); + +u_int8_t p2pNetUnregister(struct GLUE_INFO *prGlueInfo, + u_int8_t fgIsRtnlLockAcquired); + + +u_int8_t p2PAllocInfo(IN struct GLUE_INFO *prGlueInfo, IN uint8_t ucIdex); +u_int8_t p2PFreeInfo(struct GLUE_INFO *prGlueInfo, uint8_t ucIdx); + +void p2pSetSuspendMode(struct GLUE_INFO *prGlueInfo, u_int8_t fgEnable); +u_int8_t glP2pCreateWirelessDevice(struct GLUE_INFO *prGlueInfo); +void glP2pDestroyWirelessDevice(void); +void p2pUpdateChannelTableByDomain(struct GLUE_INFO *prGlueInfo); +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_qa_agent.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_qa_agent.h new file mode 100644 index 0000000000000..c4f64e80b27a8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_qa_agent.h @@ -0,0 +1,349 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/*! \file gl_qa_agent.h + * \brief This file includes private ioctl support. + */ + +#ifndef _GL_QA_AGENT_H +#define _GL_QA_AGENT_H + +#if CFG_SUPPORT_QA_TOOL + +/******************************************************************************* + * C O M P I L E 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_MTK_ANDROID_EMI +extern phys_addr_t gConEmiPhyBase; +extern unsigned long long gConEmiSize; +#endif + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/* Trigger Event */ +#define CAP_FREE_RUN 0 + +/* Ring Mode */ +#define CAP_RING_MODE_ENABLE 1 +#define CAP_RING_MODE_DISABLE 0 + +/* Capture Bit Width */ +#define CAP_96BIT 0 +#define CAP_128BIT + +/* I/Q Type */ +#define CAP_I_TYPE 0 +#define CAP_Q_TYPE 1 +#define NUM_OF_CAP_TYPE 2 + +/* ACTION */ +#define ACTION_SWITCH_TO_RFTEST 0 /* to switch firmware mode between normal mode + * or rf test mode + */ +#define ACTION_IN_RFTEST 1 + +#define HQA_CMD_MAGIC_NO 0x18142880 +#define HQA_CHIP_ID_6632 0x6632 +#define HQA_CHIP_ID_7668 0x7668 + +/* (4096(Samples/Bank) * 6Banks * 3(IQSamples/Sample) * 32bits)/96bits */ +#define MAX_ICAP_IQ_DATA_CNT (4096 * 8) +#define ICAP_EVENT_DATA_SAMPLE 256 + + +#if CFG_SUPPORT_TX_BF +#define HQA_BF_STR_SIZE 512 +#endif + +#define HQA_RX_STATISTIC_NUM 66 + +#ifdef MAX_EEPROM_BUFFER_SIZE +#undef MAX_EEPROM_BUFFER_SIZE +#endif +#define MAX_EEPROM_BUFFER_SIZE 1200 + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ + +extern uint8_t uacEEPROMImage[MAX_EEPROM_BUFFER_SIZE]; + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +#if 0 +struct PARAM_RX_STAT { + uint32_t MacFCSErr; /* Y 0x820F_D014 */ + uint32_t MacMdrdy; /* Y 0x820F_D030 */ + uint32_t FCSErr_CCK; /* Y 0x8207_021C [15:00] */ + uint32_t FCSErr_OFDM; /* Y 0x8207_021C [31:16] */ + uint32_t CCK_PD; /* Y 0x8207_020C [15:00] */ + uint32_t OFDM_PD; /* Y 0x8207_020C [15:00] */ + uint32_t CCK_SIG_Err; /* Y 0x8207_0210 [31:16] */ + uint32_t CCK_SFD_Err; /* Y 0x8207_0210 [15:00] */ + uint32_t OFDM_SIG_Err; /* Y 0x8207_0214 [31:16] */ + uint32_t OFDM_TAG_Err; /* Y 0x8207_0214 [15:00] */ + uint32_t WB_RSSSI0; /* Y 0x8207_21A8 [23:16] */ + uint32_t IB_RSSSI0; /* Y 0x8207_21A8 [31:24] */ + uint32_t WB_RSSSI1; /* Y 0x8207_21A8 [07:00] */ + uint32_t IB_RSSSI1; /* Y 0x8207_21A8 [15:08] */ + uint32_t PhyMdrdyCCK; /* Y 0x8207_0220 [15:00] */ + uint32_t PhyMdrdyOFDM; /* Y 0x8207_0220 [31:16] */ + uint32_t DriverRxCount; /* Y FW Counter Band0 */ + uint32_t RCPI0; /* Y RXV4 [07:00] */ + uint32_t RCPI1; /* Y RXV4 [15:08] */ + uint32_t FreqOffsetFromRX; /* Y RXV5 MISC1[24:00] OFDM:[11:00] + * CCK:[10:00] + */ + uint32_t RSSI0; /* N */ + uint32_t RSSI1; /* N */ + uint32_t rx_fifo_full; /* N */ + uint32_t RxLenMismatch; /* N */ + uint32_t MacFCSErr_band1; /* Y 0x820F_D214 */ + uint32_t MacMdrdy_band1; /* Y 0x820F_D230 */ + /* Y RXV3 [23:16] (must set 0x8207066C[1:0] = 0x0 ~ 0x3) */ + uint32_t FAGC_IB_RSSSI[4]; + /* Y RXV3 [31:24] (must set 0x8207066C[1:0] = 0x0 ~ 0x3) */ + uint32_t FAGC_WB_RSSSI[4]; + /* Y 0x8207_21A8 [31:24] [15:08] 0x8207_29A8 [31:24] [15:08] */ + uint32_t Inst_IB_RSSSI[4]; + /* Y 0x8207_21A8 [23:16] [07:00] 0x8207_29A8 [23:16] [07:00] */ + uint32_t Inst_WB_RSSSI[4]; + uint32_t ACIHitLow; /* Y 0x8207_21B0 [18] */ + uint32_t ACIHitHigh; /* Y 0x8207_29B0 [18] */ + uint32_t DriverRxCount1; /* Y FW Counter Band1 */ + uint32_t RCPI2; /* Y RXV4 [23:16] */ + uint32_t RCPI3; /* Y RXV4 [31:24] */ + uint32_t RSSI2; /* N */ + uint32_t RSSI3; /* N */ + uint32_t SNR0; /* Y RXV5 (MISC1 >> 19) - 16 */ + uint32_t SNR1; /* N */ + uint32_t SNR2; /* N */ + uint32_t SNR3; /* N */ + uint32_t rx_fifo_full_band1; /* N */ + uint32_t RxLenMismatch_band1; /* N */ + uint32_t CCK_PD_band1; /* Y 0x8207_040C [15:00] */ + uint32_t OFDM_PD_band1; /* Y 0x8207_040C [31:16] */ + uint32_t CCK_SIG_Err_band1; /* Y 0x8207_0410 [31:16] */ + uint32_t CCK_SFD_Err_band1; /* Y 0x8207_0410 [15:00] */ + uint32_t OFDM_SIG_Err_band1; /* Y 0x8207_0414 [31:16] */ + uint32_t OFDM_TAG_Err_band1; /* Y 0x8207_0414 [15:00] */ + uint32_t PhyMdrdyCCK_band1; /* Y 0x8207_0420 [15:00] */ + uint32_t PhyMdrdyOFDM_band1; /* Y 0x8207_0420 [31:16] */ + uint32_t CCK_FCS_Err_band1; /* Y 0x8207_041C [15:00] */ + uint32_t OFDM_FCS_Err_band1; /* Y 0x8207_041C [31:16] */ + uint32_t MuPktCount; /* Y MT_ATEUpdateRxStatistic + * RXV1_2ND_CYCLE->GroupId + */ +}; +#else +struct PARAM_RX_STAT { + uint32_t MAC_FCS_Err; /* b0 */ + uint32_t MAC_Mdrdy; /* b0 */ + uint32_t FCSErr_CCK; + uint32_t FCSErr_OFDM; + uint32_t CCK_PD; + uint32_t OFDM_PD; + uint32_t CCK_SIG_Err; + uint32_t CCK_SFD_Err; + uint32_t OFDM_SIG_Err; + uint32_t OFDM_TAG_Err; + uint32_t WB_RSSI0; + uint32_t IB_RSSI0; + uint32_t WB_RSSI1; + uint32_t IB_RSSI1; + uint32_t PhyMdrdyCCK; + uint32_t PhyMdrdyOFDM; + uint32_t DriverRxCount; + uint32_t RCPI0; + uint32_t RCPI1; + uint32_t FreqOffsetFromRX; + uint32_t RSSI0; + uint32_t RSSI1; /* insert new member here */ + uint32_t OutOfResource; /* MT7615 begin here */ + uint32_t LengthMismatchCount_B0; + uint32_t MAC_FCS_Err1; /* b1 */ + uint32_t MAC_Mdrdy1; /* b1 */ + uint32_t FAGCRssiIBR0; + uint32_t FAGCRssiIBR1; + uint32_t FAGCRssiIBR2; + uint32_t FAGCRssiIBR3; + uint32_t FAGCRssiWBR0; + uint32_t FAGCRssiWBR1; + uint32_t FAGCRssiWBR2; + uint32_t FAGCRssiWBR3; + + uint32_t InstRssiIBR0; + uint32_t InstRssiIBR1; + uint32_t InstRssiIBR2; + uint32_t InstRssiIBR3; + uint32_t InstRssiWBR0; + uint32_t InstRssiWBR1; + uint32_t InstRssiWBR2; + uint32_t InstRssiWBR3; + uint32_t ACIHitLower; + uint32_t ACIHitUpper; + uint32_t DriverRxCount1; + uint32_t RCPI2; + uint32_t RCPI3; + uint32_t RSSI2; + uint32_t RSSI3; + uint32_t SNR0; + uint32_t SNR1; + uint32_t SNR2; + uint32_t SNR3; + uint32_t OutOfResource1; + uint32_t LengthMismatchCount_B1; + uint32_t CCK_PD_Band1; + uint32_t OFDM_PD_Band1; + uint32_t CCK_SIG_Err_Band1; + uint32_t CCK_SFD_Err_Band1; + uint32_t OFDM_SIG_Err_Band1; + uint32_t OFDM_TAG_Err_Band1; + uint32_t PHY_CCK_MDRDY_Band1; + uint32_t PHY_OFDM_MDRDY_Band1; + uint32_t CCK_FCS_Err_Band1; + uint32_t OFDM_FCS_Err_Band1; + uint32_t MRURxCount; + uint32_t SIGMCS; + uint32_t SINR; + uint32_t RXVRSSI; + uint32_t Reserved[184]; + uint32_t PHY_Mdrdy; + uint32_t Noise_Floor; + uint32_t AllLengthMismatchCount_B0; + uint32_t AllLengthMismatchCount_B1; + uint32_t AllMacMdrdy0; + uint32_t AllMacMdrdy1; + uint32_t AllFCSErr0; + uint32_t AllFCSErr1; + uint32_t RXOK0; + uint32_t RXOK1; + uint32_t PER0; + uint32_t PER1; +}; +extern struct PARAM_RX_STAT g_HqaRxStat; +#endif + +struct HQA_CMD_FRAME { + uint32_t MagicNo; + uint16_t Type; + uint16_t Id; + uint16_t Length; + uint16_t Sequence; + uint8_t Data[2048]; +} __KAL_ATTRIB_PACKED__; + +/* TODO: os-related, implement with correspoinding structure in OS */ +typedef int32_t(*HQA_CMD_HANDLER) (void *prNetDev, + IN void *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame); + +struct HQA_CMD_TABLE { + HQA_CMD_HANDLER *CmdSet; + uint32_t CmdSetSize; + uint32_t CmdOffset; +}; + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/* TODO: os-related, implement with correspoinding structure in OS + * just use linux as function declare prototype + */ +int HQA_CMDHandler(void *prNetDev, + void *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame); + +int priv_qa_agent(IN void *prNetDev, + IN void *prIwReqInfo, + IN void *prIwReqData, IN char *pcExtra); + +int32_t mt6632SetICapStart(struct GLUE_INFO *prGlueInfo, + uint32_t u4Trigger, uint32_t u4RingCapEn, + uint32_t u4Event, uint32_t u4Node, uint32_t u4Len, + uint32_t u4StopCycle, + uint32_t u4BW, uint32_t u4MacTriggerEvent, + uint32_t u4SourceAddrLSB, + uint32_t u4SourceAddrMSB, uint32_t u4Band); +int32_t mt6632GetICapStatus(struct GLUE_INFO *prGlueInfo); + +int32_t connacSetICapStart(struct GLUE_INFO *prGlueInfo, + uint32_t u4Trigger, uint32_t u4RingCapEn, + uint32_t u4Event, uint32_t u4Node, uint32_t u4Len, + uint32_t u4StopCycle, + uint32_t u4BW, uint32_t u4MacTriggerEvent, + uint32_t u4SourceAddrLSB, + uint32_t u4SourceAddrMSB, uint32_t u4Band); +int32_t connacGetICapStatus(struct GLUE_INFO *prGlueInfo); + +int32_t commonGetICapIQData(struct GLUE_INFO *prGlueInfo, + uint8_t *pData, uint32_t u4IQType, uint32_t u4WFNum); +int32_t connacGetICapIQData(struct GLUE_INFO *prGlueInfo, + uint8_t *pData, uint32_t u4IQType, uint32_t u4WFNum); + + +#endif /*CFG_SUPPORT_QA_TOOL */ +#endif /* _GL_QA_AGENT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_rst.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_rst.h new file mode 100644 index 0000000000000..ccf4fad18d9d9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_rst.h @@ -0,0 +1,218 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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" + +#if 0 +#include "mtk_porting.h" +#endif +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#if (MTK_WCN_HIF_SDIO == 1) || (MTK_WCN_HIF_AXI == 1) +#define CFG_WMT_RESET_API_SUPPORT 1 +#else +#define CFG_WMT_RESET_API_SUPPORT 0 +#endif + +#define RST_FLAG_CHIP_RESET 0 +#define RST_FLAG_DO_CORE_DUMP BIT(0) +#define RST_FLAG_PREVENT_POWER_OFF BIT(1) +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +enum ENUM_RESET_STATUS { + RESET_FAIL, + RESET_SUCCESS +}; + +/* TODO: os-related, implementation reference */ +#if 0 +struct RESET_STRUCT { + enum ENUM_RESET_STATUS rst_data; + struct work_struct rst_work; + struct work_struct rst_trigger_work; + uint32_t rst_trigger_flag; +}; +#endif + +#if (CFG_SUPPORT_CONNINFRA == 1) +enum ENUM_WMTMSG_TYPE { + 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 ENUM_WMTRSTMSG_TYPE { + WMTRSTMSG_RESET_START = 0x0, /*whole chip reset (include other radio)*/ + WMTRSTMSG_RESET_END = 0x1, + WMTRSTMSG_RESET_END_FAIL = 0x2, + WMTRSTMSG_0P5RESET_START = 0x3, /*wfsys reset ( wifi only )*/ + WMTRSTMSG_RESET_MAX, + WMTRSTMSG_RESET_INVALID = 0xff +}; + +enum ENUM_WF_RST_SOURCE { + WF_RST_SOURCE_NONE = 0x0, + WF_RST_SOURCE_DRIVER = 0x1, + WF_RST_SOURCE_FW = 0x2, + WF_RST_SOURCE_MAX +}; +#endif + +enum _ENUM_CHIP_RESET_REASON_TYPE_T { + RST_PROCESS_ABNORMAL_INT = 1, + RST_DRV_OWN_FAIL, + RST_FW_ASSERT, + RST_BT_TRIGGER, + RST_OID_TIMEOUT, + RST_CMD_TRIGGER, + RST_REASON_MAX +}; + +/******************************************************************************* + * E X T E R N A L F U N C T I O N S + ******************************************************************************* + */ + +#if CFG_CHIP_RESET_SUPPORT +extern int wifi_reset_start(void); +extern int wifi_reset_end(enum ENUM_RESET_STATUS); +#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 + ******************************************************************************* + */ +#if CFG_CHIP_RESET_SUPPORT +#define GL_RESET_TRIGGER(_prAdapter, _u4Flags) \ + glResetTrigger(_prAdapter, (_u4Flags), \ + (const uint8_t *)__FILE__, __LINE__) +#else +#define GL_RESET_TRIGGER(_prAdapter, _u4Flags) \ + DBGLOG(INIT, INFO, "DO NOT support chip reset\n") +#endif + +extern uint64_t u8ResetTime; +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +void glResetInit(void); + +void glResetUninit(void); + +void glSendResetRequest(void); + +int32_t glIsWmtCodeDump(void); + +#ifdef CFG_REMIND_IMPLEMENT +#define glSetRstReason(_eReason) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define glGetRstReason() \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) + +#define glResetTrigger(prAdapter, u4RstFlag, pucFile, u4Line) \ + KAL_NEED_IMPLEMENT(__FILE__, __func__, __LINE__) +#else +void glSetRstReason(enum _ENUM_CHIP_RESET_REASON_TYPE_T + eReason); + +int glSetRstReason(void); +u_int8_t glResetTrigger(struct ADAPTER *prAdapter, + uint32_t u4RstFlag, const uint8_t *pucFile, + uint32_t u4Line); +#endif + +#endif /* _GL_RST_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_typedef.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_typedef.h new file mode 100644 index 0000000000000..9b9ff2618fd50 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_typedef.h @@ -0,0 +1,310 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + * 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. + */ + + +#ifndef _GL_TYPEDEF_H +#define _GL_TYPEDEF_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +/* Define HZ of timer tick for function kalGetTimeTick() */ +#define KAL_HZ (1000) + +/* Miscellaneous Equates */ +#ifndef FALSE +#define FALSE ((u_int8_t) 0) +#define TRUE ((u_int8_t) 1) +#endif /* FALSE */ + +#ifndef NULL +#if defined(__cplusplus) +#define NULL 0 +#else +#define NULL ((void *) 0) +#endif +#endif + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +/* Type definition for void */ + +/* Type definition for Boolean */ + +/* Type definition for signed integers */ + +/* Type definition for unsigned integers */ + + +#define OS_SYSTIME uint32_t + +/* Type definition of large integer (64bits) union to be comptaible with + * Windows definition, so we won't apply our own coding style to these data + * types. + * NOTE: LARGE_INTEGER must NOT be floating variable. + * : Check for big-endian compatibility. + */ +union LARGE_INTEGER { + struct { + uint32_t LowPart; + int32_t HighPart; + } u; + int64_t QuadPart; +}; + +union ULARGE_INTEGER { + struct { + uint32_t LowPart; + uint32_t HighPart; + } u; + uint64_t QuadPart; +}; + +typedef int32_t(*probe_card) (void *pvData, + void *pvDriverData); +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__ inline +#define __KAL_ATTRIB_PACKED__ __attribute__((__packed__)) +#define __KAL_ATTRIB_ALIGN_4__ __aligned(4) + +#ifndef BIT +#define BIT(n) ((uint32_t) 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) ((unsigned long)&(((_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 *)((int8_t *)(_addrOfField) - \ + (int8_t *)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 */ + +#ifndef ALIGN_8 +#define ALIGN_8(_value) (((_value) + 7) & ~7u) +#endif /* ALIGN_4 */ + +/* This macro check the DW alignment of the input value. + * _value - value of address need to check + */ +#ifndef IS_ALIGN_4 +#define IS_ALIGN_4(_value) (((_value) & 0x3) ? FALSE : TRUE) +#endif /* IS_ALIGN_4 */ + +#ifndef IS_NOT_ALIGN_4 +#define IS_NOT_ALIGN_4(_value) (((_value) & 0x3) ? TRUE : FALSE) +#endif /* IS_NOT_ALIGN_4 */ + +/* This macro evaluate the input length in unit of Double Word(4 Bytes). + * _value - value in unit of Byte, output will round up to DW boundary. + */ +#ifndef BYTE_TO_DWORD +#define BYTE_TO_DWORD(_value) ((_value + 3) >> 2) +#endif /* BYTE_TO_DWORD */ + +/* This macro evaluate the input length in unit of Byte. + * _value - value in unit of DW, output is in unit of Byte. + */ +#ifndef DWORD_TO_BYTE +#define DWORD_TO_BYTE(_value) ((_value) << 2) +#endif /* DWORD_TO_BYTE */ + +#if 1 /* Little-Endian */ +#define CONST_NTOHS(_x) ntohs(_x) + +#define CONST_HTONS(_x) htons(_x) + +#define NTOHS(_x) ntohs(_x) + +#define HTONS(_x) htons(_x) + +#define NTOHL(_x) ntohl(_x) + +#define HTONL(_x) htonl(_x) + +#else /* Big-Endian */ + +#define CONST_NTOHS(_x) + +#define CONST_HTONS(_x) + +#define NTOHS(_x) + +#define HTONS(_x) + +#endif + +#define CPU_TO_LE16 cpu_to_le16 +#define CPU_TO_LE32 cpu_to_le32 +#define CPU_TO_LE64 cpu_to_le64 + +#define LE16_TO_CPU le16_to_cpu +#define LE32_TO_CPU le32_to_cpu +#define LE64_TO_CPU le64_to_cpu + +#define SWAP32(x) \ + ((uint32_t) (\ + (((uint32_t) (x) & (uint32_t) 0x000000ffUL) << 24) | \ + (((uint32_t) (x) & (uint32_t) 0x0000ff00UL) << 8) | \ + (((uint32_t) (x) & (uint32_t) 0x00ff0000UL) >> 8) | \ + (((uint32_t) (x) & (uint32_t) 0xff000000UL) >> 24))) + +/* Endian byte swapping codes */ +#ifdef __LITTLE_ENDIAN +#define LE48_TO_CPU(x) (x) +#define CPU_TO_LE48(x) (x) +#define cpu2le32(x) ((uint32_t)(x)) +#define le2cpu32(x) ((uint32_t)(x)) +#define cpu2be32(x) SWAP32((x)) +#define be2cpu32(x) SWAP32((x)) + +#else + + +#define SWAP48(x) \ + ((uint64_t)( \ + (uint64_t)(((UINT_64)(x) & (uint64_t) 0x0000000000ffULL) << 40) | \ + (uint64_t)(((UINT_64)(x) & (uint64_t) 0x00000000ff00ULL) << 24) | \ + (uint64_t)(((UINT_64)(x) & (uint64_t) 0x000000ff0000ULL) << 8) | \ + (uint64_t)(((UINT_64)(x) & (uint64_t) 0x0000ff000000ULL) >> 8) | \ + (uint64_t)(((UINT_64)(x) & (uint64_t) 0x00ff00000000ULL) >> 24) | \ + (uint64_t)(((UINT_64)(x) & (uint64_t) 0xff0000000000ULL) >> 40))) +#define LE48_TO_CPU(x) SWAP48(x) +#define CPU_TO_LE48(x) SWAP48(x) +#define cpu2le32(x) SWAP32((x)) +#define le2cpu32(x) SWAP32((x)) +#define cpu2be32(x) ((uint32_t)(x)) +#define be2cpu32(x) ((uint32_t)(x)) + + +#endif + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _GL_TYPEDEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_vendor.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_vendor.h new file mode 100644 index 0000000000000..35cf0b7497901 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_vendor.h @@ -0,0 +1,714 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + * Log: gl_vendor.h + * + * 10 14 2014 + * add vendor declaration + * some structure is needed by common part in this file + * 1) struct PARAM_PACKET_KEEPALIVE_T needed by nic_cmd_event.h + */ + +#ifndef _GL_VENDOR_H +#define _GL_VENDOR_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "wlan_lib.h" + + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define GOOGLE_OUI 0x001A11 +#define OUI_QCA 0x001374 + +#define NL80211_VENDOR_SUBCMD_GET_PREFER_FREQ_LIST 103 +#define QCA_NL80211_VENDOR_SUBCMD_ROAM 64 +#define QCA_NL80211_VENDOR_SUBCMD_SETBAND 105 + +enum ANDROID_VENDOR_SUB_COMMAND { + /* Don't use 0 as a valid subcommand */ + ANDROID_NL80211_SUBCMD_UNSPECIFIED, + + /* Define all vendor startup commands between 0x0 and 0x0FFF */ + ANDROID_NL80211_SUBCMD_WIFI_RANGE_START = 0x0001, + ANDROID_NL80211_SUBCMD_WIFI_RANGE_END = 0x0FFF, + + /* Define all GScan related commands between 0x1000 and 0x10FF */ + ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START = 0x1000, + ANDROID_NL80211_SUBCMD_GSCAN_RANGE_END = 0x10FF, + + /* Define all RTT related commands between 0x1100 and 0x11FF */ + ANDROID_NL80211_SUBCMD_RTT_RANGE_START = 0x1100, + ANDROID_NL80211_SUBCMD_RTT_RANGE_END = 0x11FF, + + ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START = 0x1200, + ANDROID_NL80211_SUBCMD_LSTATS_RANGE_END = 0x12FF, + + /* Define all Logger related commands between 0x1400 and 0x14FF */ + ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START = 0x1400, + ANDROID_NL80211_SUBCMD_DEBUG_RANGE_END = 0x14FF, + + /* Define all wifi offload related commands between 0x1600 and 0x16FF */ + ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START = 0x1600, + ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_END = 0x16FF, + + /* This is reserved for future usage */ + +}; + +enum WIFI_SUB_COMMAND { + WIFI_SUBCMD_GET_CHANNEL_LIST = ANDROID_NL80211_SUBCMD_WIFI_RANGE_START, + + WIFI_SUBCMD_GET_FEATURE_SET, /* 0x0002 */ + WIFI_SUBCMD_GET_FEATURE_SET_MATRIX, /* 0x0003 */ + WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI, /* 0x0004 */ + WIFI_SUBCMD_NODFS_SET, /* 0x0005 */ + WIFI_SUBCMD_SET_COUNTRY_CODE, /* 0x0006 */ + WIFI_SUBCMD_SET_RSSI_MONITOR, /* 0x0007 */ + + /* Add more sub commands here */ + WIFI_SUBCMD_GET_ROAMING_CAPABILITIES, /* 0x0008 */ + WIFI_SUBCMD_SET_ROAMING = 0x0009, /* 0x0009 */ + WIFI_SUBCMD_CONFIG_ROAMING = 0x000a, /* 0x000a */ + WIFI_SUBCMD_ENABLE_ROAMING /* 0x000b */ +}; + +enum RTT_SUB_COMMAND { + RTT_SUBCMD_SET_CONFIG = ANDROID_NL80211_SUBCMD_RTT_RANGE_START, + RTT_SUBCMD_CANCEL_CONFIG, + RTT_SUBCMD_GETCAPABILITY, +}; + +enum LSTATS_SUB_COMMAND { + LSTATS_SUBCMD_GET_INFO = ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START, +}; + +/* moved from wifi_logger.cpp */ +enum DEBUG_SUB_COMMAND { + LOGGER_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START, + LOGGER_GET_VER +}; + +enum WIFI_OFFLOAD_SUB_COMMAND { + WIFI_OFFLOAD_START_MKEEP_ALIVE = + ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START, + WIFI_OFFLOAD_STOP_MKEEP_ALIVE, +}; + +enum WIFI_VENDOR_EVENT { + GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS, + GSCAN_EVENT_HOTLIST_RESULTS_FOUND, + GSCAN_EVENT_SCAN_RESULTS_AVAILABLE, + GSCAN_EVENT_FULL_SCAN_RESULTS, + RTT_EVENT_COMPLETE, + GSCAN_EVENT_COMPLETE_SCAN, + GSCAN_EVENT_HOTLIST_RESULTS_LOST, + WIFI_EVENT_RSSI_MONITOR +}; + +enum WIFI_ATTRIBUTE { + WIFI_ATTRIBUTE_BAND = 1, + WIFI_ATTRIBUTE_NUM_CHANNELS, + WIFI_ATTRIBUTE_CHANNEL_LIST, + + WIFI_ATTRIBUTE_NUM_FEATURE_SET, + WIFI_ATTRIBUTE_FEATURE_SET, + WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, + WIFI_ATTRIBUTE_NODFS_VALUE, + WIFI_ATTRIBUTE_COUNTRY_CODE, + + WIFI_ATTRIBUTE_MAX_RSSI, + WIFI_ATTRIBUTE_MIN_RSSI, + WIFI_ATTRIBUTE_RSSI_MONITOR_START, + + WIFI_ATTRIBUTE_ROAMING_CAPABILITIES, + WIFI_ATTRIBUTE_ROAMING_BLACKLIST_NUM, + WIFI_ATTRIBUTE_ROAMING_BLACKLIST_BSSID, + WIFI_ATTRIBUTE_ROAMING_WHITELIST_NUM, + WIFI_ATTRIBUTE_ROAMING_WHITELIST_SSID, + WIFI_ATTRIBUTE_ROAMING_STATE +}; + +/* moved from wifi_logger.cpp */ +enum LOGGER_ATTRIBUTE { + LOGGER_ATTRIBUTE_DRIVER_VER, + LOGGER_ATTRIBUTE_FW_VER +}; + +enum RTT_ATTRIBUTE { + RTT_ATTRIBUTE_CAPABILITIES = 1, + + RTT_ATTRIBUTE_TARGET_CNT = 10, + RTT_ATTRIBUTE_TARGET_INFO, + RTT_ATTRIBUTE_TARGET_MAC, + RTT_ATTRIBUTE_TARGET_TYPE, + RTT_ATTRIBUTE_TARGET_PEER, + RTT_ATTRIBUTE_TARGET_CHAN, + RTT_ATTRIBUTE_TARGET_PERIOD, + RTT_ATTRIBUTE_TARGET_NUM_BURST, + RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST, + RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM, + RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR, + RTT_ATTRIBUTE_TARGET_LCI, + RTT_ATTRIBUTE_TARGET_LCR, + RTT_ATTRIBUTE_TARGET_BURST_DURATION, + RTT_ATTRIBUTE_TARGET_PREAMBLE, + RTT_ATTRIBUTE_TARGET_BW, + RTT_ATTRIBUTE_RESULTS_COMPLETE = 30, + RTT_ATTRIBUTE_RESULTS_PER_TARGET, + RTT_ATTRIBUTE_RESULT_CNT, + RTT_ATTRIBUTE_RESULT +}; + +enum LSTATS_ATTRIBUTE { + LSTATS_ATTRIBUTE_STATS = 2, +}; + +enum WIFI_MKEEP_ALIVE_ATTRIBUTE { + MKEEP_ALIVE_ATTRIBUTE_ID = 1, + MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN, + MKEEP_ALIVE_ATTRIBUTE_IP_PKT, + MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR, + MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR, + MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC +}; + +/* QCA Vender CMD */ +enum QCA_SET_BAND { + QCA_SETBAND_AUTO, + QCA_SETBAND_5G, + QCA_SETBAND_2G, +}; + +enum QCA_ATTR_ROAM_SUBCMD { + QCA_ATTR_ROAM_SUBCMD_INVALID = 0, + QCA_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID = 6, + + /* keep last */ + QCA_ATTR_ROAM_SUBCMD_AFTER_LAST, + QCA_ATTR_ROAM_SUBCMD_MAX = + QCA_ATTR_ROAM_SUBCMD_AFTER_LAST - 1, +}; + +enum QCA_ATTR_ROAMING_PARAMS { + QCA_ATTR_ROAMING_PARAM_INVALID = 0, + + QCA_ATTR_ROAMING_SUBCMD = 1, + + /* Attribute for set_blacklist bssid params */ + QCA_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS = 18, + QCA_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID = 19, + QCA_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID = 20, + + /* keep last */ + QCA_ATTR_ROAMING_PARAM_AFTER_LAST, + QCA_ATTR_ROAMING_PARAM_MAX = + QCA_ATTR_ROAMING_PARAM_AFTER_LAST - 1, +}; + +enum WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST { + WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_INVALID, + WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_IFACE_TYPE, + WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_GET, + WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_LAST, + WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_MAX = + WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_LAST - 1 +}; + +#define MAX_FW_ROAMING_BLACKLIST_SIZE 16 +#define MAX_FW_ROAMING_WHITELIST_SIZE 8 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +#if CFG_SUPPORT_WAPI +extern uint8_t +keyStructBuf[1024]; /* add/remove key shared buffer */ +#else +extern uint8_t +keyStructBuf[100]; /* add/remove key shared buffer */ +#endif + +/******************************************************************************* + * MACROS + ******************************************************************************* + */ +/* + * TODO: function is os-related, while may depend on the purpose of function + * to implement on other os + */ +#if 0 +#if KERNEL_VERSION(3, 5, 0) <= LINUX_VERSION_CODE +/* + * #define NLA_PUT(skb, attrtype, attrlen, data) \ + * do { \ + * if (unlikely(nla_put(skb, attrtype, attrlen, data) < 0)) \ + * goto nla_put_failure; \ + * } while (0) + * + *#define NLA_PUT_TYPE(skb, type, attrtype, value) \ + * do { \ + * type __tmp = value; \ + * NLA_PUT(skb, attrtype, sizeof(type), &__tmp); \ + * } while (0) + */ +#define NLA_PUT(skb, attrtype, attrlen, data) \ + mtk_cfg80211_NLA_PUT(skb, attrtype, attrlen, data) + +#define NLA_PUT_TYPE(skb, type, attrtype, value) \ + mtk_cfg80211_nla_put_type(skb, type, attrtype, value) + +#define NLA_PUT_U8(skb, attrtype, value) \ + NLA_PUT_TYPE(skb, NLA_PUT_DATE_U8, attrtype, value) + +#define NLA_PUT_U16(skb, attrtype, value) \ + NLA_PUT_TYPE(skb, NLA_PUT_DATE_U16, attrtype, value) + +#define NLA_PUT_U32(skb, attrtype, value) \ + NLA_PUT_TYPE(skb, NLA_PUT_DATE_U32, attrtype, value) + +#define NLA_PUT_U64(skb, attrtype, value) \ + NLA_PUT_TYPE(skb, NLA_PUT_DATE_U64, attrtype, value) + +#endif + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +#define NLA_PARSE_NESTED(nlattr, maxtype, nla, policy) \ + nla_parse_nested(nlattr, maxtype, nla, policy, NULL) +#define NLA_PARSE(tb, maxtype, head, len, policy) \ + nla_parse(tb, maxtype, head, len, policy, NULL) +#else +#define NLA_PARSE_NESTED(nlattr, maxtype, nla, policy) \ + nla_parse_nested(nlattr, maxtype, nla, policy) +#define NLA_PARSE(tb, maxtype, head, len, policy) \ + nla_parse(tb, maxtype, head, len, policy) +#endif +#endif +/******************************************************************************* + * P R I V A T E D A T A + * + ******************************************************************************* + */ +struct PARAM_WIFI_CHANGE_RESULT { + uint16_t flags; + uint16_t channel; + uint8_t bssid[6]; /* BSSID */ + int8_t rssi[8]; /* RSSI history in db */ +}; + +struct PARAM_AP_THRESHOLD { + uint8_t bssid[6]; /* AP BSSID */ + int32_t low; /* low threshold */ + int32_t high; /* high threshold */ + uint32_t channel; /* channel hint */ +}; + +/* channel operating width */ +enum WIFI_CHANNEL_WIDTH { + WIFI_CHAN_WIDTH_20 = 0, + WIFI_CHAN_WIDTH_40 = 1, + WIFI_CHAN_WIDTH_80 = 2, + WIFI_CHAN_WIDTH_160 = 3, + WIFI_CHAN_WIDTH_80P80 = 4, + WIFI_CHAN_WIDTH_5 = 5, + WIFI_CHAN_WIDTH_10 = 6, + WIFI_CHAN_WIDTH_INVALID = -1 +}; + +/* channel information */ +struct WIFI_CHANNEL_INFO { + enum WIFI_CHANNEL_WIDTH width; + uint32_t center_freq; + uint32_t center_freq0; + uint32_t center_freq1; +}; + +/* channel statistics */ +struct WIFI_CHANNEL_STAT { + struct WIFI_CHANNEL_INFO channel; + uint32_t on_time; + uint32_t cca_busy_time; +}; + +/* radio statistics */ +struct WIFI_RADIO_STAT { + uint32_t radio; + uint32_t on_time; + uint32_t tx_time; + uint32_t rx_time; + uint32_t on_time_scan; + uint32_t on_time_nbd; + uint32_t on_time_gscan; + uint32_t on_time_roam_scan; + uint32_t on_time_pno_scan; + uint32_t on_time_hs20; + uint32_t num_channels; + struct WIFI_CHANNEL_STAT channels[]; +}; + +/* wifi rate */ +struct WIFI_RATE { + uint32_t preamble: 3; + uint32_t nss: 2; + uint32_t bw: 3; + uint32_t rateMcsIdx: 8; + + uint32_t reserved: 16; + uint32_t bitrate; +}; + +/* per rate statistics */ +struct WIFI_RATE_STAT { + struct WIFI_RATE rate; + uint32_t tx_mpdu; + uint32_t rx_mpdu; + uint32_t mpdu_lost; + uint32_t retries; + uint32_t retries_short; + uint32_t retries_long; +}; + +/*wifi_interface_link_layer_info*/ +enum WIFI_CONNECTION_STATE { + WIFI_DISCONNECTED = 0, + WIFI_AUTHENTICATING = 1, + WIFI_ASSOCIATING = 2, + WIFI_ASSOCIATED = 3, + WIFI_EAPOL_STARTED = 4, + WIFI_EAPOL_COMPLETED = 5, +}; + +enum WIFI_ROAM_STATE { + WIFI_ROAMING_IDLE = 0, + WIFI_ROAMING_ACTIVE = 1, +}; + +enum WIFI_INTERFACE_MODE { + WIFI_INTERFACE_STA = 0, + WIFI_INTERFACE_SOFTAP = 1, + WIFI_INTERFACE_IBSS = 2, + WIFI_INTERFACE_P2P_CLIENT = 3, + WIFI_INTERFACE_P2P_GO = 4, + WIFI_INTERFACE_NAN = 5, + WIFI_INTERFACE_MESH = 6, + WIFI_INTERFACE_UNKNOWN = -1 +}; + +struct WIFI_INTERFACE_LINK_LAYER_INFO { + enum WIFI_INTERFACE_MODE mode; + u8 mac_addr[6]; + enum WIFI_CONNECTION_STATE state; + enum WIFI_ROAM_STATE roaming; + u32 capabilities; + u8 ssid[33]; + u8 bssid[6]; + u8 ap_country_str[3]; + u8 country_str[3]; +}; + +/* access categories */ +enum WIFI_TRAFFIC_AC { + WIFI_AC_VO = 0, + WIFI_AC_VI = 1, + WIFI_AC_BE = 2, + WIFI_AC_BK = 3, + WIFI_AC_MAX = 4, +}; + +/* wifi peer type */ +enum WIFI_PEER_TYPE { + WIFI_PEER_STA, + WIFI_PEER_AP, + WIFI_PEER_P2P_GO, + WIFI_PEER_P2P_CLIENT, + WIFI_PEER_NAN, + WIFI_PEER_TDLS, + WIFI_PEER_INVALID, +}; + +/* per peer statistics */ +struct WIFI_PEER_INFO { + enum WIFI_PEER_TYPE type; + uint8_t peer_mac_address[6]; + uint32_t capabilities; + uint32_t num_rate; + struct WIFI_RATE_STAT rate_stats[]; +}; + +/* per access category statistics */ +struct WIFI_WMM_AC_STAT_ { + enum WIFI_TRAFFIC_AC ac; + uint32_t tx_mpdu; + uint32_t rx_mpdu; + uint32_t tx_mcast; + + uint32_t rx_mcast; + uint32_t rx_ampdu; + uint32_t tx_ampdu; + uint32_t mpdu_lost; + uint32_t retries; + uint32_t retries_short; + uint32_t retries_long; + uint32_t contention_time_min; + uint32_t contention_time_max; + uint32_t contention_time_avg; + uint32_t contention_num_samples; +}; + +/* RTT Capabilities */ +struct PARAM_WIFI_RTT_CAPABILITIES { + /* if 1-sided rtt data collection is supported */ + uint8_t rtt_one_sided_supported; + /* if ftm rtt data collection is supported */ + uint8_t rtt_ftm_supported; + /* if initiator supports LCI request. Applies to 2-sided RTT */ + uint8_t lci_support; + /* if initiator supports LCR request. Applies to 2-sided RTT */ + uint8_t lcr_support; + /* bit mask indicates what preamble is supported by initiator */ + uint8_t preamble_support; + /* bit mask indicates what BW is supported by initiator */ + uint8_t bw_support; +}; + +/* interface statistics */ +struct WIFI_IFACE_STAT { + struct WIFI_INTERFACE_LINK_LAYER_INFO info; + uint32_t beacon_rx; + uint32_t mgmt_rx; + uint32_t mgmt_action_rx; + uint32_t mgmt_action_tx; + int32_t rssi_mgmt; + int32_t rssi_data; + int32_t rssi_ack; + struct WIFI_WMM_AC_STAT_ ac[WIFI_AC_MAX]; + uint32_t num_peers; + struct WIFI_PEER_INFO peer_info[]; +}; + +enum ENUM_NLA_PUT_DATE_TYPE { + NLA_PUT_DATE_U8 = 0, + NLA_PUT_DATE_U16, + NLA_PUT_DATE_U32, + NLA_PUT_DATE_U64, +}; + +/* RSSI Monitoring */ +struct PARAM_RSSI_MONITOR_T { + bool enable; /* 1=Start, 0=Stop*/ + int8_t max_rssi_value; + int8_t min_rssi_value; + uint8_t reserved[1]; + uint8_t reserved2[4]; /* reserved for MT6632 */ +}; + +struct PARAM_RSSI_MONITOR_EVENT { + uint8_t version; + int8_t rssi; + uint8_t BSSID[PARAM_MAC_ADDR_LEN]; +}; + +/* Packet Keep Alive */ +struct PARAM_PACKET_KEEPALIVE_T { + bool enable; /* 1=Start, 0=Stop*/ + uint8_t index; + int16_t u2IpPktLen; + uint8_t pIpPkt[256]; + uint8_t ucSrcMacAddr[PARAM_MAC_ADDR_LEN]; + uint8_t ucDstMacAddr[PARAM_MAC_ADDR_LEN]; + uint32_t u4PeriodMsec; + uint8_t reserved[8]; /* reserved for MT6632 */ +}; + +struct PARAM_BSS_MAC_OUI { + uint8_t ucBssIndex; + uint8_t ucMacOui[MAC_OUI_LEN]; +}; + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + + + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +/* + * TODO: function is os-related, while may depend on the purpose of function + * to implement on other os + */ +#if 0 +int mtk_cfg80211_NLA_PUT(struct sk_buff *skb, int attrtype, + int attrlen, const void *data); + +int mtk_cfg80211_nla_put_type(struct sk_buff *skb, + enum ENUM_NLA_PUT_DATE_TYPE type, int attrtype, + const void *value); + +int mtk_cfg80211_vendor_get_capabilities(struct wiphy + *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_config(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_scan_config(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_significant_change( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_hotlist(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_enable_scan(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_enable_full_scan_results( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_get_scan_results(struct wiphy + *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_get_channel_list(struct wiphy + *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_country_code(struct wiphy + *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_get_rtt_capabilities( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_llstats_get_info(struct wiphy + *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_band(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_scan_mac_oui(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_roaming_policy( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_get_roaming_capabilities( + struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); + +int mtk_cfg80211_vendor_config_roaming(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +int mtk_cfg80211_vendor_enable_roaming(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +int mtk_cfg80211_vendor_set_rssi_monitoring( + struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); + +int mtk_cfg80211_vendor_packet_keep_alive_start( + struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); + +int mtk_cfg80211_vendor_packet_keep_alive_stop( + struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); + +int mtk_cfg80211_vendor_get_version(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_event_rssi_beyond_range( + struct wiphy *wiphy, + struct wireless_dev *wdev, int rssi); + +int mtk_cfg80211_vendor_get_preferred_freq_list(struct wiphy + *wiphy, struct wireless_dev *wdev, const void *data, + int data_len); +#endif +#endif /* _GL_VENDOR_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_wext_priv.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_wext_priv.h new file mode 100644 index 0000000000000..698ea57c8a3ee --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/none/include/gl_wext_priv.h @@ -0,0 +1,402 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + * 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. + */ + + +#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) + */ +/* TODO: os-related */ +#if 0 +#define IOCTL_SET_INT (SIOCIWFIRSTPRIV + 0) +#define IOCTL_GET_INT (SIOCIWFIRSTPRIV + 1) + +#define IOCTL_SET_ADDRESS (SIOCIWFIRSTPRIV + 2) +#define IOCTL_GET_ADDRESS (SIOCIWFIRSTPRIV + 3) +#define IOCTL_SET_STR (SIOCIWFIRSTPRIV + 4) +#define IOCTL_GET_STR (SIOCIWFIRSTPRIV + 5) +#define IOCTL_SET_KEY (SIOCIWFIRSTPRIV + 6) +#define IOCTL_GET_KEY (SIOCIWFIRSTPRIV + 7) +#define IOCTL_SET_STRUCT (SIOCIWFIRSTPRIV + 8) +#define IOCTL_GET_STRUCT (SIOCIWFIRSTPRIV + 9) +#define IOCTL_SET_STRUCT_FOR_EM (SIOCIWFIRSTPRIV + 11) +#define IOCTL_SET_INTS (SIOCIWFIRSTPRIV + 12) +#define IOCTL_GET_INTS (SIOCIWFIRSTPRIV + 13) +#define IOCTL_SET_DRIVER (SIOCIWFIRSTPRIV + 14) +#define IOCTL_GET_DRIVER (SIOCIWFIRSTPRIV + 15) + +#if CFG_SUPPORT_QA_TOOL +#define IOCTL_QA_TOOL_DAEMON (SIOCIWFIRSTPRIV + 16) +#define IOCTL_IWPRIV_ATE (SIOCIWFIRSTPRIV + 17) +#endif + +#define IOC_AP_GET_STA_LIST (SIOCIWFIRSTPRIV+19) +#define IOC_AP_SET_MAC_FLTR (SIOCIWFIRSTPRIV+21) +#define IOC_AP_SET_CFG (SIOCIWFIRSTPRIV+23) +#define IOC_AP_STA_DISASSOC (SIOCIWFIRSTPRIV+25) + +#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 + +#define PRIV_SEC_CHECK_OID 21 + +#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 + +#if CFG_SUPPORT_QA_TOOL +#define PRIV_QACMD_SET 29 +#endif + +#define PRIV_CMD_MET_PROFILING 33 + +#if CFG_WOW_SUPPORT +#define PRIV_CMD_SET_WOW_ENABLE 34 +#define PRIV_CMD_SET_WOW_PAR 35 +#endif + +#ifdef UT_TEST_MODE +#define PRIV_CMD_UT 36 +#endif /* UT_TEST_MODE */ + +#define PRIV_CMD_SET_SER 37 + +/* 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 +#define OID_CUSTOM_TEST_ICAP_MODE 0xFFA0C913 + +/* 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 + +#if CFG_SUPPORT_LOWLATENCY_MODE +#define OID_CUSTOM_LOWLATENCY_MODE 0xFFA0CC00 +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + +#define OID_IPC_WIFI_LOG_UI 0xFFA0CC01 +#define OID_IPC_WIFI_LOG_LEVEL 0xFFA0CC02 +#endif + +#if CFG_SUPPORT_NCHO +#define CMD_NCHO_COMP_TIMEOUT 1500 /* ms */ +#define CMD_NCHO_AF_DATA_LENGTH 1040 +#endif + +#ifdef UT_TEST_MODE +#define OID_UT 0xFFA0CD00 +#endif /* UT_TEST_MODE */ + +/* Define magic key of test mode (Don't change it for future compatibity) */ +#define PRIV_CMD_TEST_MAGIC_KEY 2011 +#define PRIV_CMD_TEST_MAGIC_KEY_ICAP 2013 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +/* NIC BBCR configuration entry structure */ +struct PRIV_CONFIG_ENTRY { + uint8_t ucOffset; + uint8_t ucValue; +}; + +typedef uint32_t(*PFN_OID_HANDLER_FUNC_REQ) ( + IN void *prAdapter, + IN OUT void *pvBuf, IN uint32_t u4BufLen, + OUT uint32_t *pu4OutInfoLen); + +enum ENUM_OID_METHOD { + ENUM_OID_GLUE_ONLY, + ENUM_OID_GLUE_EXTENSION, + ENUM_OID_DRIVER_CORE +}; + +/* OID set/query processing entry */ +struct WLAN_REQ_ENTRY { + uint32_t rOid; /* OID */ + uint8_t *pucOidName; /* OID name text */ + u_int8_t fgQryBufLenChecking; + u_int8_t fgSetBufLenChecking; + enum ENUM_OID_METHOD eOidMethod; + uint32_t u4InfoBufLen; + PFN_OID_HANDLER_FUNC_REQ pfOidQueryHandler; /* PFN_OID_HANDLER_FUNC */ + PFN_OID_HANDLER_FUNC_REQ pfOidSetHandler; /* PFN_OID_HANDLER_FUNC */ +}; + +struct NDIS_TRANSPORT_STRUCT { + uint32_t ndisOidCmd; + uint32_t inNdisOidlength; + uint32_t outNdisOidLength; + uint8_t ndisOidContent[16]; +}; + +enum AGG_RANGE_TYPE_T { + ENUM_AGG_RANGE_TYPE_TX = 0, + ENUM_AGG_RANGE_TYPE_TRX = 1, + ENUM_AGG_RANGE_TYPE_RX = 2 +}; + +/******************************************************************************* + * P U B 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 + ******************************************************************************* + */ +#if 0 +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); + +#if CFG_SUPPORT_NCHO +uint8_t CmdString2HexParse(IN uint8_t *InStr, + OUT uint8_t **OutStr, OUT uint8_t *OutLen); +#endif + +int +priv_set_driver(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN OUT char *pcExtra); + +int +priv_set_ap(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); + +int priv_support_driver_cmd(IN struct net_device *prDev, + IN OUT struct ifreq *prReq, IN int i4Cmd); + +#ifdef CFG_ANDROID_AOSP_PRIV_CMD +int android_private_support_driver_cmd(IN struct net_device *prDev, +IN OUT struct ifreq *prReq, IN int i4Cmd); +#endif /* CFG_ANDROID_AOSP_PRIV_CMD */ + +int32_t priv_driver_cmds(IN struct net_device *prNetDev, + IN int8_t *pcCommand, IN int32_t i4TotalLen); + +int priv_driver_set_cfg(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen); + +#if CFG_SUPPORT_QA_TOOL +int +priv_ate_set(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN char *pcExtra); +#endif +#else +#endif +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _GL_WEXT_PRIV_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/version.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/version.h new file mode 100644 index 0000000000000..26273a1d93543 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/os/version.h @@ -0,0 +1,138 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/version.h#1 + */ + +/*! \file "version.h" + * \brief Driver's version definition + * + */ + + +#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 +#define NIC_NAME "MT6632" +#define NIC_DEVICE_ID "MT6632" +#define NIC_DEVICE_ID_LOW "mt6632" +#endif + +/* NIC driver information */ +#define NIC_VENDOR "MediaTek Inc." +#define NIC_VENDOR_OUI {0x00, 0x0C, 0xE7} + +#define NIC_PRODUCT_NAME "MediaTek Inc. Wireless LAN Adapter" +#define NIC_DRIVER_NAME "MediaTek Inc. Wireless LAN Adapter Driver" + +/* Define our driver version */ +#define NIC_DRIVER_MAJOR_VERSION 1 +#define NIC_DRIVER_MINOR_VERSION 0 +#define NIC_DRIVER_SERIAL_VERSION 1 +#define NIC_DRIVER_VERSION (NIC_DRIVER_MAJOR_VERSION, \ + NIC_DRIVER_MINOR_VERSION, \ + NIC_DRIVER_SERIAL_VERSION) +#define NIC_DRIVER_VERSION_STRING "1.0.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 */ From a49f49a84e046123587741878f577d1b275b9631 Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 22:11:26 +0800 Subject: [PATCH 23/32] Update Makefile --- drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/Makefile b/drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/Makefile index 99e1e9eb4d004..fba470b6a3a52 100644 --- a/drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/Makefile +++ b/drivers/misc/mediatek/connectivity/bt/mt66xx/legacy/Makefile @@ -51,7 +51,7 @@ endif ############################################################################### MODULE_NAME := bt_drv -obj-m += $(MODULE_NAME).o +obj-y += $(MODULE_NAME).o ccflags-y += -D CREATE_NODE_DYNAMIC=1 From 7ee1c71f2e79b49b90c5b9939d1b24513756cefc Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 22:13:49 +0800 Subject: [PATCH 24/32] Add files via upload --- .../wlan/core/gen4m/include/CFG_Wifi_File.h | 593 + .../gen4m/include/chips/cmm_asic_connac.h | 184 + .../gen4m/include/chips/cmm_asic_connac2x.h | 1209 ++ .../include/chips/coda/mt7915/wf_cr_sw_def.h | 119 + .../include/chips/coda/mt7915/wf_ple_top.h | 8757 +++++++++++++++ .../include/chips/coda/mt7915/wf_pse_top.h | 3353 ++++++ .../chips/coda/mt7915/wf_wfdma_host_dma0.h | 6185 +++++++++++ .../chips/coda/mt7915/wf_wfdma_host_dma1.h | 9727 +++++++++++++++++ .../include/chips/coda/mt7961/wf_cr_sw_def.h | 93 + .../chips/coda/mt7961/wf_hif_dmashdl_top.h | 2356 ++++ .../include/chips/coda/mt7961/wf_ple_top.h | 6731 ++++++++++++ .../include/chips/coda/mt7961/wf_pse_top.h | 3661 +++++++ .../chips/coda/mt7961/wf_wfdma_host_dma0.h | 8406 ++++++++++++++ .../chips/coda/soc3_0/conn_infra_cfg.h | 75 + .../chips/coda/soc3_0/wf_hif_dmashdl_top.h | 2361 ++++ .../include/chips/coda/soc3_0/wf_ple_top.h | 6739 ++++++++++++ .../include/chips/coda/soc3_0/wf_pse_top.h | 3719 +++++++ .../chips/coda/soc3_0/wf_wfdma_host_dma0.h | 5922 ++++++++++ .../chips/coda/soc3_0/wf_wfdma_host_dma1.h | 8328 ++++++++++++++ .../wlan/core/gen4m/include/chips/connac.h | 133 + .../wlan/core/gen4m/include/chips/connac2x2.h | 128 + .../wlan/core/gen4m/include/chips/dma_sch.h | 199 + .../wlan/core/gen4m/include/chips/fw_dl.h | 413 + .../gen4m/include/chips/hal_dmashdl_mt7961.h | 376 + .../gen4m/include/chips/hal_dmashdl_soc3_0.h | 233 + .../wlan/core/gen4m/include/chips/host_csr.h | 104 + .../wlan/core/gen4m/include/chips/mt6632.h | 118 + .../wlan/core/gen4m/include/chips/mt7663.h | 124 + .../wlan/core/gen4m/include/chips/mt7668.h | 120 + .../wlan/core/gen4m/include/chips/mt7915.h | 139 + .../wlan/core/gen4m/include/chips/mt7961.h | 141 + .../wlan/core/gen4m/include/chips/mt_dmac.h | 362 + .../wlan/core/gen4m/include/chips/pse.h | 279 + .../wlan/core/gen4m/include/chips/soc3_0.h | 395 + .../wlan/core/gen4m/include/chips/wf_ple.h | 233 + .../wlan/core/gen4m/include/config.h | 1490 +++ .../wlan/core/gen4m/include/debug.h | 655 ++ .../wlan/core/gen4m/include/dvt/dvt_common.h | 387 + .../wlan/core/gen4m/include/dvt/dvt_dmashdl.h | 258 + .../wlan/core/gen4m/include/hif_cmm.h | 139 + .../wlan/core/gen4m/include/link.h | 529 + .../wlan/core/gen4m/include/link_drv.h | 527 + .../wlan/core/gen4m/include/mtk_wifi_trace.h | 41 + .../wlan/core/gen4m/include/nic/adapter.h | 1927 ++++ .../wlan/core/gen4m/include/nic/bow.h | 266 + .../wlan/core/gen4m/include/nic/cmd_buf.h | 227 + .../core/gen4m/include/nic/connac_dmashdl.h | 458 + .../wlan/core/gen4m/include/nic/connac_reg.h | 269 + .../wlan/core/gen4m/include/nic/hal.h | 1231 +++ .../wlan/core/gen4m/include/nic/hif_rx.h | 156 + .../wlan/core/gen4m/include/nic/hif_tx.h | 169 + .../wlan/core/gen4m/include/nic/mac.h | 3684 +++++++ .../wlan/core/gen4m/include/nic/mt66xx_reg.h | 1437 +++ .../wlan/core/gen4m/include/nic/nic.h | 481 + .../core/gen4m/include/nic/nic_connac2x_rx.h | 375 + .../core/gen4m/include/nic/nic_connac2x_tx.h | 871 ++ .../wlan/core/gen4m/include/nic/nic_rate.h | 292 + .../wlan/core/gen4m/include/nic/nic_rx.h | 1393 +++ .../wlan/core/gen4m/include/nic/nic_rxd_v1.h | 110 + .../wlan/core/gen4m/include/nic/nic_rxd_v2.h | 112 + .../wlan/core/gen4m/include/nic/nic_tx.h | 2032 ++++ .../wlan/core/gen4m/include/nic/nic_txd_v1.h | 138 + .../wlan/core/gen4m/include/nic/nic_txd_v2.h | 136 + .../wlan/core/gen4m/include/nic/nic_umac.h | 140 + .../wlan/core/gen4m/include/nic/p2p.h | 409 + .../wlan/core/gen4m/include/nic/p2p_cmd_buf.h | 121 + .../wlan/core/gen4m/include/nic/p2p_mac.h | 438 + .../wlan/core/gen4m/include/nic/p2p_nic.h | 116 + .../gen4m/include/nic/p2p_nic_cmd_event.h | 122 + .../wlan/core/gen4m/include/nic/que_mgt.h | 1241 +++ .../wlan/core/gen4m/include/nic/wlan_def.h | 1199 ++ .../wlan/core/gen4m/include/nic_cmd_event.h | 3267 ++++++ .../core/gen4m/include/nic_ext_cmd_event.h | 215 + .../core/gen4m/include/nic_init_cmd_event.h | 326 + .../wlan/core/gen4m/include/p2p_precomp.h | 247 + .../wlan/core/gen4m/include/p2p_typedef.h | 246 + .../wlan/core/gen4m/include/precomp.h | 342 + .../wlan/core/gen4m/include/pwr_mgt.h | 156 + .../wlan/core/gen4m/include/queue.h | 241 + .../wlan/core/gen4m/include/rftest.h | 438 + .../wlan/core/gen4m/include/typedef.h | 204 + .../wlan/core/gen4m/include/wlan_bow.h | 302 + .../wlan/core/gen4m/include/wlan_he.h | 107 + .../wlan/core/gen4m/include/wlan_lib.h | 1851 ++++ .../wlan/core/gen4m/include/wlan_oid.h | 4182 +++++++ .../wlan/core/gen4m/include/wlan_p2p.h | 318 + .../core/gen4m/include/wsys_cmd_handler_fw.h | 2033 ++++ 87 files changed, 120066 insertions(+) create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/CFG_Wifi_File.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/cmm_asic_connac.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/cmm_asic_connac2x.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7915/wf_cr_sw_def.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7915/wf_ple_top.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7915/wf_pse_top.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7915/wf_wfdma_host_dma0.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7915/wf_wfdma_host_dma1.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7961/wf_cr_sw_def.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7961/wf_hif_dmashdl_top.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7961/wf_ple_top.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7961/wf_pse_top.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7961/wf_wfdma_host_dma0.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/soc3_0/conn_infra_cfg.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/soc3_0/wf_hif_dmashdl_top.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/soc3_0/wf_ple_top.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/soc3_0/wf_pse_top.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/soc3_0/wf_wfdma_host_dma0.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/soc3_0/wf_wfdma_host_dma1.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/connac.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/connac2x2.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/dma_sch.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/fw_dl.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/hal_dmashdl_mt7961.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/hal_dmashdl_soc3_0.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/host_csr.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/mt6632.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/mt7663.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/mt7668.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/mt7915.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/mt7961.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/mt_dmac.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/pse.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/soc3_0.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/wf_ple.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/config.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/debug.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/dvt/dvt_common.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/dvt/dvt_dmashdl.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/hif_cmm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/link.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/link_drv.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mtk_wifi_trace.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/adapter.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/bow.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/cmd_buf.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/connac_dmashdl.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/connac_reg.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/hal.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/hif_rx.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/hif_tx.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/mac.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/mt66xx_reg.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_connac2x_rx.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_connac2x_tx.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_rate.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_rx.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_rxd_v1.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_rxd_v2.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_tx.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_txd_v1.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_txd_v2.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_umac.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/p2p.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/p2p_cmd_buf.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/p2p_mac.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/p2p_nic.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/p2p_nic_cmd_event.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/que_mgt.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/wlan_def.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic_cmd_event.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic_ext_cmd_event.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic_init_cmd_event.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/p2p_precomp.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/p2p_typedef.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/precomp.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/pwr_mgt.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/queue.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/rftest.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/typedef.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/wlan_bow.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/wlan_he.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/wlan_lib.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/wlan_oid.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/wlan_p2p.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/wsys_cmd_handler_fw.h diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/CFG_Wifi_File.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/CFG_Wifi_File.h new file mode 100644 index 0000000000000..f435ce30e9c4b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/CFG_Wifi_File.h @@ -0,0 +1,593 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** 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. + */ + +#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 + ******************************************************************************* + */ +/* Connac define */ +struct WIFI_NVRAM_2G4_TX_POWER_T { + uint8_t uc2G4TxPwrCck1M; + uint8_t uc2G4TxPwrCck2M; + uint8_t uc2G4TxPwrCck5M; + uint8_t uc2G4TxPwrCck11M; + uint8_t uc2G4TxPwrOfdm6M; + uint8_t uc2G4TxPwrOfdm9M; + uint8_t uc2G4TxPwrOfdm12M; + uint8_t uc2G4TxPwrOfdm18M; + uint8_t uc2G4TxPwrOfdm24M; + uint8_t uc2G4TxPwrOfdm36M; + uint8_t uc2G4TxPwrOfdm48M; + uint8_t uc2G4TxPwrOfdm54M; + uint8_t uc2G4TxPwrHt20Mcs0; + uint8_t uc2G4TxPwrHt20Mcs1; + uint8_t uc2G4TxPwrHt20Mcs2; + uint8_t uc2G4TxPwrHt20Mcs3; + uint8_t uc2G4TxPwrHt20Mcs4; + uint8_t uc2G4TxPwrHt20Mcs5; + uint8_t uc2G4TxPwrHt20Mcs6; + uint8_t uc2G4TxPwrHt20Mcs7; + uint8_t uc2G4TxPwrHt40Mcs0; + uint8_t uc2G4TxPwrHt40Mcs1; + uint8_t uc2G4TxPwrHt40Mcs2; + uint8_t uc2G4TxPwrHt40Mcs3; + uint8_t uc2G4TxPwrHt40Mcs4; + uint8_t uc2G4TxPwrHt40Mcs5; + uint8_t uc2G4TxPwrHt40Mcs6; + uint8_t uc2G4TxPwrHt40Mcs7; + uint8_t uc2G4TxPwrHt40Mcs32; + uint8_t uc2G4TxPwrVht20Mcs0; + uint8_t uc2G4TxPwrVht20Mcs1; + uint8_t uc2G4TxPwrVht20Mcs2; + uint8_t uc2G4TxPwrVht20Mcs3; + uint8_t uc2G4TxPwrVht20Mcs4; + uint8_t uc2G4TxPwrVht20Mcs5; + uint8_t uc2G4TxPwrVht20Mcs6; + uint8_t uc2G4TxPwrVht20Mcs7; + uint8_t uc2G4TxPwrVht20Mcs8; + uint8_t uc2G4TxPwrVht20Mcs9; + uint8_t uc2G4TxPwrVht40Mcs0; + uint8_t uc2G4TxPwrVht40Mcs1; + uint8_t uc2G4TxPwrVht40Mcs2; + uint8_t uc2G4TxPwrVht40Mcs3; + uint8_t uc2G4TxPwrVht40Mcs4; + uint8_t uc2G4TxPwrVht40Mcs5; + uint8_t uc2G4TxPwrVht40Mcs6; + uint8_t uc2G4TxPwrVht40Mcs7; + uint8_t uc2G4TxPwrVht40Mcs8; + uint8_t uc2G4TxPwrVht40Mcs9; + uint8_t uc2G4TxPwrRU26Mcs0; + uint8_t uc2G4TxPwrRU26Mcs1; + uint8_t uc2G4TxPwrRU26Mcs2; + uint8_t uc2G4TxPwrRU26Mcs3; + uint8_t uc2G4TxPwrRU26Mcs4; + uint8_t uc2G4TxPwrRU26Mcs5; + uint8_t uc2G4TxPwrRU26Mcs6; + uint8_t uc2G4TxPwrRU26Mcs7; + uint8_t uc2G4TxPwrRU26Mcs8; + uint8_t uc2G4TxPwrRU26Mcs9; + uint8_t uc2G4TxPwrRU26Mcs10; + uint8_t uc2G4TxPwrRU26Mcs11; + + uint8_t uc2G4TxPwrRU52Mcs0; + uint8_t uc2G4TxPwrRU52Mcs1; + uint8_t uc2G4TxPwrRU52Mcs2; + uint8_t uc2G4TxPwrRU52Mcs3; + uint8_t uc2G4TxPwrRU52Mcs4; + uint8_t uc2G4TxPwrRU52Mcs5; + uint8_t uc2G4TxPwrRU52Mcs6; + uint8_t uc2G4TxPwrRU52Mcs7; + uint8_t uc2G4TxPwrRU52Mcs8; + uint8_t uc2G4TxPwrRU52Mcs9; + uint8_t uc2G4TxPwrRU52Mcs10; + uint8_t uc2G4TxPwrRU52Mcs11; + + uint8_t uc2G4TxPwrRU106Mcs0; + uint8_t uc2G4TxPwrRU106Mcs1; + uint8_t uc2G4TxPwrRU106Mcs2; + uint8_t uc2G4TxPwrRU106Mcs3; + uint8_t uc2G4TxPwrRU106Mcs4; + uint8_t uc2G4TxPwrRU106Mcs5; + uint8_t uc2G4TxPwrRU106Mcs6; + uint8_t uc2G4TxPwrRU106Mcs7; + uint8_t uc2G4TxPwrRU106Mcs8; + uint8_t uc2G4TxPwrRU106Mcs9; + uint8_t uc2G4TxPwrRU106Mcs10; + uint8_t uc2G4TxPwrRU106Mcs11; + + uint8_t uc2G4TxPwrRU242Mcs0; + uint8_t uc2G4TxPwrRU242Mcs1; + uint8_t uc2G4TxPwrRU242Mcs2; + uint8_t uc2G4TxPwrRU242Mcs3; + uint8_t uc2G4TxPwrRU242Mcs4; + uint8_t uc2G4TxPwrRU242Mcs5; + uint8_t uc2G4TxPwrRU242Mcs6; + uint8_t uc2G4TxPwrRU242Mcs7; + uint8_t uc2G4TxPwrRU242Mcs8; + uint8_t uc2G4TxPwrRU242Mcs9; + uint8_t uc2G4TxPwrRU242Mcs10; + uint8_t uc2G4TxPwrRU242Mcs11; + + uint8_t uc2G4TxPwrRU484Mcs0; + uint8_t uc2G4TxPwrRU484Mcs1; + uint8_t uc2G4TxPwrRU484Mcs2; + uint8_t uc2G4TxPwrRU484Mcs3; + uint8_t uc2G4TxPwrRU484Mcs4; + uint8_t uc2G4TxPwrRU484Mcs5; + uint8_t uc2G4TxPwrRU484Mcs6; + uint8_t uc2G4TxPwrRU484Mcs7; + uint8_t uc2G4TxPwrRU484Mcs8; + uint8_t uc2G4TxPwrRU484Mcs9; + uint8_t uc2G4TxPwrRU484Mcs10; + uint8_t uc2G4TxPwrRU484Mcs11; + + uint8_t uc2G4TxPwrLGBW40DuplucateMode; + +}; + +struct WIFI_NVRAM_5G_TX_POWER_T { + uint8_t uc5GTxPwrOfdm6M; + uint8_t uc5GTxPwrOfdm9M; + uint8_t uc5GTxPwrOfdm12M; + uint8_t uc5GTxPwrOfdm18M; + uint8_t uc5GTxPwrOfdm24M; + uint8_t uc5GTxPwrOfdm36M; + uint8_t uc5GTxPwrOfdm48M; + uint8_t uc5GTxPwrOfdm54M; + uint8_t uc5GTxPwrHt20Mcs0; + uint8_t uc5GTxPwrHt20Mcs1; + uint8_t uc5GTxPwrHt20Mcs2; + uint8_t uc5GTxPwrHt20Mcs3; + uint8_t uc5GTxPwrHt20Mcs4; + uint8_t uc5GTxPwrHt20Mcs5; + uint8_t uc5GTxPwrHt20Mcs6; + uint8_t uc5GTxPwrHt20Mcs7; + uint8_t uc5GTxPwrHt40Mcs0; + uint8_t uc5GTxPwrHt40Mcs1; + uint8_t uc5GTxPwrHt40Mcs2; + uint8_t uc5GTxPwrHt40Mcs3; + uint8_t uc5GTxPwrHt40Mcs4; + uint8_t uc5GTxPwrHt40Mcs5; + uint8_t uc5GTxPwrHt40Mcs6; + uint8_t uc5GTxPwrHt40Mcs7; + uint8_t uc5GTxPwrHt40Mcs32; + + uint8_t uc5GTxPwrVht20Mcs0; + uint8_t uc5GTxPwrVht20Mcs1; + uint8_t uc5GTxPwrVht20Mcs2; + uint8_t uc5GTxPwrVht20Mcs3; + uint8_t uc5GTxPwrVht20Mcs4; + uint8_t uc5GTxPwrVht20Mcs5; + uint8_t uc5GTxPwrVht20Mcs6; + uint8_t uc5GTxPwrVht20Mcs7; + uint8_t uc5GTxPwrVht20Mcs8; + uint8_t uc5GTxPwrVht20Mcs9; + uint8_t uc5GTxPwrVht40Mcs0; + uint8_t uc5GTxPwrVht40Mcs1; + uint8_t uc5GTxPwrVht40Mcs2; + uint8_t uc5GTxPwrVht40Mcs3; + uint8_t uc5GTxPwrVht40Mcs4; + uint8_t uc5GTxPwrVht40Mcs5; + uint8_t uc5GTxPwrVht40Mcs6; + uint8_t uc5GTxPwrVht40Mcs7; + uint8_t uc5GTxPwrVht40Mcs8; + uint8_t uc5GTxPwrVht40Mcs9; + uint8_t uc5GTxPwrVht80Mcs0; + uint8_t uc5GTxPwrVht80Mcs1; + uint8_t uc5GTxPwrVht80Mcs2; + uint8_t uc5GTxPwrVht80Mcs3; + uint8_t uc5GTxPwrVht80Mcs4; + uint8_t uc5GTxPwrVht80Mcs5; + uint8_t uc5GTxPwrVht80Mcs6; + uint8_t uc5GTxPwrVht80Mcs7; + uint8_t uc5GTxPwrVht80Mcs8; + uint8_t uc5GTxPwrVht80Mcs9; + uint8_t uc5GTxPwrVht160Mcs0; + uint8_t uc5GTxPwrVht160Mcs1; + uint8_t uc5GTxPwrVht160Mcs2; + uint8_t uc5GTxPwrVht160Mcs3; + uint8_t uc5GTxPwrVht160Mcs4; + uint8_t uc5GTxPwrVht160Mcs5; + uint8_t uc5GTxPwrVht160Mcs6; + uint8_t uc5GTxPwrVht160Mcs7; + uint8_t uc5GTxPwrVht160Mcs8; + uint8_t uc5GTxPwrVht160Mcs9; + + uint8_t uc5GTxPwrRU26Mcs0; + uint8_t uc5GTxPwrRU26Mcs1; + uint8_t uc5GTxPwrRU26Mcs2; + uint8_t uc5GTxPwrRU26Mcs3; + uint8_t uc5GTxPwrRU26Mcs4; + uint8_t uc5GTxPwrRU26Mcs5; + uint8_t uc5GTxPwrRU26Mcs6; + uint8_t uc5GTxPwrRU26Mcs7; + uint8_t uc5GTxPwrRU26Mcs8; + uint8_t uc5GTxPwrRU26Mcs9; + uint8_t uc5GTxPwrRU26Mcs10; + uint8_t uc5GTxPwrRU26Mcs11; + + uint8_t uc5GTxPwrRU52Mcs0; + uint8_t uc5GTxPwrRU52Mcs1; + uint8_t uc5GTxPwrRU52Mcs2; + uint8_t uc5GTxPwrRU52Mcs3; + uint8_t uc5GTxPwrRU52Mcs4; + uint8_t uc5GTxPwrRU52Mcs5; + uint8_t uc5GTxPwrRU52Mcs6; + uint8_t uc5GTxPwrRU52Mcs7; + uint8_t uc5GTxPwrRU52Mcs8; + uint8_t uc5GTxPwrRU52Mcs9; + uint8_t uc5GTxPwrRU52Mcs10; + uint8_t uc5GTxPwrRU52Mcs11; + + uint8_t uc5GTxPwrRU106Mcs0; + uint8_t uc5GTxPwrRU106Mcs1; + uint8_t uc5GTxPwrRU106Mcs2; + uint8_t uc5GTxPwrRU106Mcs3; + uint8_t uc5GTxPwrRU106Mcs4; + uint8_t uc5GTxPwrRU106Mcs5; + uint8_t uc5GTxPwrRU106Mcs6; + uint8_t uc5GTxPwrRU106Mcs7; + uint8_t uc5GTxPwrRU106Mcs8; + uint8_t uc5GTxPwrRU106Mcs9; + uint8_t uc5GTxPwrRU106Mcs10; + uint8_t uc5GTxPwrRU106Mcs11; + + uint8_t uc5GTxPwrRU242Mcs0; + uint8_t uc5GTxPwrRU242Mcs1; + uint8_t uc5GTxPwrRU242Mcs2; + uint8_t uc5GTxPwrRU242Mcs3; + uint8_t uc5GTxPwrRU242Mcs4; + uint8_t uc5GTxPwrRU242Mcs5; + uint8_t uc5GTxPwrRU242Mcs6; + uint8_t uc5GTxPwrRU242Mcs7; + uint8_t uc5GTxPwrRU242Mcs8; + uint8_t uc5GTxPwrRU242Mcs9; + uint8_t uc5GTxPwrRU242Mcs10; + uint8_t uc5GTxPwrRU242Mcs11; + + uint8_t uc5GTxPwrRU484Mcs0; + uint8_t uc5GTxPwrRU484Mcs1; + uint8_t uc5GTxPwrRU484Mcs2; + uint8_t uc5GTxPwrRU484Mcs3; + uint8_t uc5GTxPwrRU484Mcs4; + uint8_t uc5GTxPwrRU484Mcs5; + uint8_t uc5GTxPwrRU484Mcs6; + uint8_t uc5GTxPwrRU484Mcs7; + uint8_t uc5GTxPwrRU484Mcs8; + uint8_t uc5GTxPwrRU484Mcs9; + uint8_t uc5GTxPwrRU484Mcs10; + uint8_t uc5GTxPwrRU484Mcs11; + + uint8_t uc5GTxPwrRU996Mcs0; + uint8_t uc5GTxPwrRU996Mcs1; + uint8_t uc5GTxPwrRU996Mcs2; + uint8_t uc5GTxPwrRU996Mcs3; + uint8_t uc5GTxPwrRU996Mcs4; + uint8_t uc5GTxPwrRU996Mcs5; + uint8_t uc5GTxPwrRU996Mcs6; + uint8_t uc5GTxPwrRU996Mcs7; + uint8_t uc5GTxPwrRU996Mcs8; + uint8_t uc5GTxPwrRU996Mcs9; + uint8_t uc5GTxPwrRU996Mcs10; + uint8_t uc5GTxPwrRU996Mcs11; + + uint8_t uc5GTxPwrLGBW40DuplucateMode; + uint8_t uc5GTxPwrLGBW80DuplucateMode; + uint8_t uc5GTxPwrLGBW1600DuplucateMode; + uint8_t uc5GBw5MTxPwrDelta; + uint8_t uc5GBw10MTxPwrDelta; +}; + +/* end Connac TX Power define */ + +/* duplicated from nic_cmd_event.h to avoid header dependency */ +struct TX_PWR_PARAM { + int8_t cTxPwr2G4Cck; /* signed, in unit of 0.5dBm */ + int8_t cTxPwr2G4Dsss; /* signed, in unit of 0.5dBm */ + int8_t acReserved[2]; + + int8_t cTxPwr2G4OFDM_BPSK; + int8_t cTxPwr2G4OFDM_QPSK; + int8_t cTxPwr2G4OFDM_16QAM; + int8_t cTxPwr2G4OFDM_Reserved; + int8_t cTxPwr2G4OFDM_48Mbps; + int8_t cTxPwr2G4OFDM_54Mbps; + + int8_t cTxPwr2G4HT20_BPSK; + int8_t cTxPwr2G4HT20_QPSK; + int8_t cTxPwr2G4HT20_16QAM; + int8_t cTxPwr2G4HT20_MCS5; + int8_t cTxPwr2G4HT20_MCS6; + int8_t cTxPwr2G4HT20_MCS7; + + int8_t cTxPwr2G4HT40_BPSK; + int8_t cTxPwr2G4HT40_QPSK; + int8_t cTxPwr2G4HT40_16QAM; + int8_t cTxPwr2G4HT40_MCS5; + int8_t cTxPwr2G4HT40_MCS6; + int8_t cTxPwr2G4HT40_MCS7; + + int8_t cTxPwr5GOFDM_BPSK; + int8_t cTxPwr5GOFDM_QPSK; + int8_t cTxPwr5GOFDM_16QAM; + int8_t cTxPwr5GOFDM_Reserved; + int8_t cTxPwr5GOFDM_48Mbps; + int8_t cTxPwr5GOFDM_54Mbps; + + int8_t cTxPwr5GHT20_BPSK; + int8_t cTxPwr5GHT20_QPSK; + int8_t cTxPwr5GHT20_16QAM; + int8_t cTxPwr5GHT20_MCS5; + int8_t cTxPwr5GHT20_MCS6; + int8_t cTxPwr5GHT20_MCS7; + + int8_t cTxPwr5GHT40_BPSK; + int8_t cTxPwr5GHT40_QPSK; + int8_t cTxPwr5GHT40_16QAM; + int8_t cTxPwr5GHT40_MCS5; + int8_t cTxPwr5GHT40_MCS6; + int8_t cTxPwr5GHT40_MCS7; +}; + +struct TX_AC_PWR { + int8_t c11AcTxPwr_BPSK; + int8_t c11AcTxPwr_QPSK; + int8_t c11AcTxPwr_16QAM; + int8_t c11AcTxPwr_MCS5_MCS6; + int8_t c11AcTxPwr_MCS7; + int8_t c11AcTxPwr_MCS8; + int8_t c11AcTxPwr_MCS9; + int8_t c11AcTxPwrVht40_OFFSET; + int8_t c11AcTxPwrVht80_OFFSET; + int8_t c11AcTxPwrVht160_OFFSET; + int8_t acReverse[2]; +}; + +struct RSSI_PATH_COMPASATION { + int8_t c2GRssiCompensation; + int8_t c5GRssiCompensation; +}; + +struct PWR_5G_OFFSET { + int8_t cOffsetBand0; /* 4.915-4.980G */ + int8_t cOffsetBand1; /* 5.000-5.080G */ + int8_t cOffsetBand2; /* 5.160-5.180G */ + int8_t cOffsetBand3; /* 5.200-5.280G */ + int8_t cOffsetBand4; /* 5.300-5.340G */ + int8_t cOffsetBand5; /* 5.500-5.580G */ + int8_t cOffsetBand6; /* 5.600-5.680G */ + int8_t cOffsetBand7; /* 5.700-5.825G */ +}; + +struct PWR_PARAM { + uint32_t au4Data[28]; + uint32_t u4RefValue1; + uint32_t u4RefValue2; +}; + +struct AC_PWR_SETTING_STRUCT { + uint8_t c11AcTxPwr_BPSK; + uint8_t c11AcTxPwr_QPSK; + uint8_t c11AcTxPwr_16QAM; + uint8_t c11AcTxPwr_MCS5_MCS6; + uint8_t c11AcTxPwr_MCS7; + uint8_t c11AcTxPwr_MCS8; + uint8_t c11AcTxPwr_MCS9; + uint8_t c11AcTxPwr_Reserved; + uint8_t c11AcTxPwrVht40_OFFSET; + uint8_t c11AcTxPwrVht80_OFFSET; + uint8_t c11AcTxPwrVht160_OFFSET; +}; + +struct BANDEDGE_5G { + uint8_t uc5GBandEdgePwrUsed; + uint8_t c5GBandEdgeMaxPwrOFDM20; + uint8_t c5GBandEdgeMaxPwrOFDM40; + uint8_t c5GBandEdgeMaxPwrOFDM80; + +}; + +struct NEW_EFUSE_MAPPING2NVRAM { + uint8_t ucReverse1[8]; + uint16_t u2Signature; + struct BANDEDGE_5G r5GBandEdgePwr; + uint8_t ucReverse2[14]; + + /* 0x50 */ + uint8_t aucChOffset[3]; + uint8_t ucChannelOffsetVaild; + uint8_t acAllChannelOffset; + uint8_t aucChOffset3[11]; + + /* 0x60 */ + uint8_t auc5GChOffset[8]; + uint8_t uc5GChannelOffsetVaild; + uint8_t aucChOffset4[7]; + + /* 0x70 */ + struct AC_PWR_SETTING_STRUCT r11AcTxPwr; + uint8_t uc11AcTxPwrValid; + + uint8_t ucReverse4[20]; + + /* 0x90 */ + struct AC_PWR_SETTING_STRUCT r11AcTxPwr2G; + uint8_t uc11AcTxPwrValid2G; + + uint8_t ucReverse5[40]; +}; + +struct WIFI_NVRAM_CONTROL_T { + uint8_t ucControl; /*0: disable, 1: enable*/ + uint8_t ucTotalSizeLSB; + uint8_t ucTotalSizeMSB; +}; + + +struct WIFI_CFG_PARAM_STRUCT { + /* NVRAM offset[0] ~ offset[255] */ + uint16_t u2Part1OwnVersion; + uint16_t u2Part1PeerVersion; + uint8_t aucMacAddress[6]; + uint8_t aucCountryCode[2]; + uint8_t aucOldTxPwr0[185]; + + uint8_t ucSupport5GBand; + uint8_t aucOldTxPwr1[4]; + + uint8_t ucRegChannelListMap; + uint8_t ucRegChannelListIndex; + uint8_t aucRegSubbandInfo[36]; + uint8_t ucEnable5GBand; /* move from 256+ offset to here */ + uint8_t ucNeedCheckLDO; + uint8_t ucDefaultTestMode; + uint8_t ucSupportCoAnt; + uint8_t aucReserved0[12]; + /* NVRAM offset[256] ~ offset[255] */ + /* uint8_t aucReserved0[256 - 241]; */ + + uint8_t ucTypeID0; + uint8_t ucTypeLen0LSB; + uint8_t ucTypeLen0MSB; + struct WIFI_NVRAM_CONTROL_T rCtrl; + uint8_t ucTypeID1; + uint8_t ucTypeLen1LSB; + uint8_t ucTypeLen1MSB; + struct WIFI_NVRAM_2G4_TX_POWER_T r2G4Pwr; + uint8_t ucTypeID2; + uint8_t ucTypeLen2LSB; + uint8_t ucTypeLen2MSB; + struct WIFI_NVRAM_5G_TX_POWER_T r5GPwr; + uint8_t aucReserved1[1528]; +}; + +struct WIFI_NVRAM_TAG_FORMAT { + uint8_t u1NvramTypeID; + uint8_t u1NvramTypeLenLsb; + uint8_t u1NvramTypeLenMsb; +}; +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +#ifndef DATA_STRUCT_INSPECTING_ASSERT +#define DATA_STRUCT_INSPECTING_ASSERT(expr) \ + {switch (0) {case 0: case (expr): default:; } } +#endif + +#define MAX_CFG_FILE_WIFI_REC_SIZE (1024*8) + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#ifndef _lint +/* We don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + * We'll need this to guarantee the same member order in different structures + * to simply handling effort in some functions. + */ +static __KAL_INLINE__ void nvramOffsetCheck(void) +{ + DATA_STRUCT_INSPECTING_ASSERT( + OFFSET_OF(struct WIFI_CFG_PARAM_STRUCT, ucTypeID0) == 256); + DATA_STRUCT_INSPECTING_ASSERT( + sizeof(struct WIFI_CFG_PARAM_STRUCT) == 2048); +} +#endif + +#endif /* _CFG_WIFI_FILE_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/cmm_asic_connac.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/cmm_asic_connac.h new file mode 100644 index 0000000000000..8e037c8a68eeb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/cmm_asic_connac.h @@ -0,0 +1,184 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/ + * MT6620_WIFI_DRIVER_V2_3/include/chips/connac.h#1 + */ + +/*! \file connac.h + * \brief This file contains the info of CONNAC + */ + +#ifndef _CMM_ASIC_CONNAC_H +#define _CMM_ASIC_CONNAC_H + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define CONNAC_CHIP_IP_VERSION (0x10020300) +#define CONNAC_CHIP_IP_CONFIG (0x1) +#define USB_HIF_TXD_LEN 4 +#define NIC_TX_PSE_HEADER_LENGTH 4 + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +void asicCapInit(IN struct ADAPTER *prAdapter); +uint32_t asicGetFwDlInfo(struct ADAPTER *prAdapter, + char *pcBuf, int i4TotalLen); +void asicEnableFWDownload(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnable); +uint32_t asicGetChipID(struct ADAPTER *prAdapter); +void fillNicTxDescAppend(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + OUT uint8_t *prTxDescBuffer); +void fillNicTxDescAppendWithCR4(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + OUT uint8_t *prTxDescBuffer); +void fillTxDescAppendByHost(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN uint16_t u4MsduId, + IN phys_addr_t rDmaAddr, IN uint32_t u4Idx, IN u_int8_t fgIsLast, + OUT uint8_t *pucBuffer); +void fillTxDescAppendByHostV2(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN uint16_t u4MsduId, + IN phys_addr_t rDmaAddr, IN uint32_t u4Idx, IN u_int8_t fgIsLast, + OUT uint8_t *pucBuffer); +void fillTxDescAppendByCR4(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN uint16_t u4MsduId, + IN phys_addr_t rDmaAddr, IN uint32_t u4Idx, IN u_int8_t fgIsLast, + OUT uint8_t *pucBuffer); +void fillTxDescTxByteCount(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + void *prTxDesc); +void fillTxDescTxByteCountWithCR4(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + void *prTxDesc); + +#if defined(_HIF_PCIE) || defined(_HIF_AXI) +/* DMS Scheduler Init */ +void asicPcieDmaShdlInit(IN struct ADAPTER *prAdapter); +void asicPdmaLoopBackConfig(struct GLUE_INFO *prGlueInfo, u_int8_t fgEnable); +void asicPdmaIntMaskConfig(struct GLUE_INFO *prGlueInfo, u_int8_t fgEnable); +void asicPdmaConfig(struct GLUE_INFO *prGlueInfo, u_int8_t fgEnable, + bool fgResetHif); +uint32_t asicUpdatTxRingMaxQuota(IN struct ADAPTER *prAdapter, + IN uint16_t u2Port, IN uint32_t u4MaxQuota); +void asicEnableInterrupt(IN struct ADAPTER *prAdapter); +void asicDisableInterrupt(IN struct ADAPTER *prAdapter); +void asicLowPowerOwnRead(IN struct ADAPTER *prAdapter, OUT u_int8_t *pfgResult); +void asicLowPowerOwnSet(IN struct ADAPTER *prAdapter, OUT u_int8_t *pfgResult); +void asicLowPowerOwnClear(IN struct ADAPTER *prAdapter, + OUT u_int8_t *pfgResult); +void asicLowPowerOwnClearPCIe(IN struct ADAPTER *prAdapter, + OUT u_int8_t *pfgResult); +void asicWakeUpWiFi(IN struct ADAPTER *prAdapter); +bool asicIsValidRegAccess(IN struct ADAPTER *prAdapter, IN uint32_t u4Register); +void asicGetMailboxStatus(IN struct ADAPTER *prAdapter, OUT uint32_t *pu4Val); +void asicSetDummyReg(struct GLUE_INFO *prGlueInfo); +void asicCheckDummyReg(struct GLUE_INFO *prGlueInfo); +void asicPdmaTxRingExtCtrl( + struct GLUE_INFO *prGlueInfo, + struct RTMP_TX_RING *tx_ring, + uint32_t index); +void asicPdmaRxRingExtCtrl( + struct GLUE_INFO *prGlueInfo, + struct RTMP_RX_RING *rx_ring, + uint32_t index); +#endif /* _HIF_PCIE */ + +#if defined(_HIF_USB) +/* DMS Scheduler Init */ +void asicUsbDmaShdlInit(IN struct ADAPTER *prAdapter); +void asicUdmaTxTimeoutEnable(IN struct ADAPTER *prAdapter); +u_int8_t asicUsbSuspend(IN struct ADAPTER *prAdapter, + IN struct GLUE_INFO *prGlueInfo); +uint8_t asicUsbEventEpDetected(IN struct ADAPTER *prAdapter); +void asicUdmaRxFlush(IN struct ADAPTER *prAdapter, IN u_int8_t bEnable); +void asicPdmaHifReset(IN struct ADAPTER *prAdapter, IN u_int8_t bRelease); +void fillUsbHifTxDesc(IN uint8_t **pDest, IN uint16_t *pInfoBufLen); +#endif /* _HIF_USB */ +void asicFillInitCmdTxd( + struct ADAPTER *prAdapter, + struct WIFI_CMD_INFO *prCmdInfo, + uint16_t *pu2BufInfoLen, + u_int8_t *pucSeqNum, + void **pCmdBuf); +void asicFillCmdTxd( + struct ADAPTER *prAdapter, + struct WIFI_CMD_INFO *prCmdInfo, + u_int8_t *pucSeqNum, + void **pCmdBuf); +void asicInitTxdHook( + struct TX_DESC_OPS_T *prTxDescOps); +void asicInitRxdHook( + struct RX_DESC_OPS_T *prRxDescOps); +#if (CFG_SUPPORT_MSP == 1) +void asicRxProcessRxvforMSP( + IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prRetSwRfb); +#endif /* CFG_SUPPORT_MSP == 1 */ +uint8_t asicRxGetRcpiValueFromRxv( + IN uint8_t ucRcpiMode, + IN struct SW_RFB *prSwRfb); +#if (CFG_SUPPORT_PERF_IND == 1) +void asicRxPerfIndProcessRXV(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint8_t ucBssIndex); +#endif + +#if (CFG_CHIP_RESET_SUPPORT == 1) && (CFG_WMT_RESET_API_SUPPORT == 0) +u_int8_t conn1_rst_L0_notify_step2(void); +#endif +#endif /* _CMM_ASIC_CONNAC_H */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/cmm_asic_connac2x.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/cmm_asic_connac2x.h new file mode 100644 index 0000000000000..7ac1b3ac45d40 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/cmm_asic_connac2x.h @@ -0,0 +1,1209 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file cmm_asic_connac2x.h +* \brief This file contains the info of CONNAC2X +*/ + +#ifndef _CMM_ASIC_CONNAC2X_H +#define _CMM_ASIC_CONNAC2X_H + +#if (CFG_SUPPORT_CONNAC2X == 1) + +#define CONN_INFRA_REMAPPING_OFFSET 0x64000000 +#define CONNAC2X_WFDMA_DISP_MAX_CNT_MASK 0x000000FF +#define CONNAC2X_WFDMA_DISP_BASE_PTR_MASK 0xFFFF0000 + +#define CONNAC2X_MCU_WPDMA_0_BASE 0x54000000 +#define CONNAC2X_MCU_WPDMA_1_BASE 0x55000000 +#define CONNAC2X_HOST_WPDMA_0_BASE 0x7c024000 +#define CONNAC2X_HOST_WPDMA_1_BASE 0x7c025000 +#define CONNAC2X_HOST_DMASHDL 0x7c026000 + +#define CONNAC2X_WPDMA_GLO_CFG(__BASE) ((__BASE) + 0x0208) +#define CONNAC2X_WPDMA_GLO_CFG_EXT0(__BASE) ((__BASE) + 0x02B0) +#define CONNAC2X_TX_RING_EXT_CTRL_BASE(__BASE) ((__BASE) + 0x0600) +#define CONNAC2X_TX_RING_DISP_MAX_CNT 4 +#define CONNAC2X_RX_RING_DISP_MAX_CNT 4 + +#define CONNAC2X_RX_RING_CIDX(__BASE) ((__BASE) + 0x0508) +#define CONNAC2X_HOST_DMASHDL_SW_CONTROL(__BASE) ((__BASE) + 0x0004) + +/* OMIT_TX_INFO[28]*/ +#define CONNAC2X_WPDMA1_GLO_CFG_OMIT_TX_INFO 0x10000000 +/* OMIT_RX_INFO[27]*/ +#define CONNAC2X_WPDMA1_GLO_CFG_OMIT_RX_INFO 0x08000000 +/* OMIT_RX_INFO_PFET2[21]*/ +#define CONNAC2X_WPDMA1_GLO_CFG_OMIT_RX_INFO_PFET2 0x00200000 +/* FW_DWLD_Bypass_dmashdl[9] */ +#define CONNAC2X_WPDMA1_GLO_CFG_FW_DWLD_Bypass_dmashdl 0x00000200 +/* RX_DMA_BUSY[3] */ +#define CONNAC2X_WPDMA1_GLO_CFG_RX_DMA_BUSY 0x00000008 +/* RX_DMA_EN[2] */ +#define CONNAC2X_WPDMA1_GLO_CFG_RX_DMA_EN 0x00000004 +/* TX_DMA_BUSY[1] */ +#define CONNAC2X_WPDMA1_GLO_CFG_TX_DMA_BUSY 0x00000002 +/* TX_DMA_EN[0] */ +#define CONNAC2X_WPDMA1_GLO_CFG_TX_DMA_EN 0x00000001 +/* TX_DMASHDL_ENABLE[6] */ +#define CONNAC2X_WPDMA1_GLO_CFG_EXT0_TX_DMASHDL_EN 0x00000040 +/* DMASHDL_BYPASS[28] */ +#define CONNAC2X_HIF_DMASHDL_BYPASS_EN 0x10000000 + +#define CONNAC2X_NIC_TX_PSE_HEADER_LENGTH 8 +#define CONNAC2X_RX_INIT_EVENT_LENGTH 8 + +#define CONNAC2X_WFDMA_DUMMY_CR (CONNAC2X_MCU_WPDMA_0_BASE + 0x120) +#define CONNAC2X_WFDMA_NEED_REINIT_BIT BIT(1) + +#if defined(_HIF_PCIE) || defined(_HIF_AXI) +#define CONNAC2X_CONN_HIF_ON_ADDR_REMAP23 0x7010 +#define CONNAC2X_HOST_EXT_CONN_HIF_WRAP 0x7c027000 +#define CONNAC2X_MCU_INT_CONN_HIF_WRAP 0x57000000 +#define CONNAC2X_WFDMA_COUNT 2 + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define CONNAC2X_WPDMA_EXT_INT_STA(__BASE) ((__BASE) + 0x0010) +#define CONNAC2X_WPDMA_EXT_INT_MASK(__BASE) ((__BASE) + 0x0014) +#define CONNAC2X_WPDMA_HIF_RST(__BASE) ((__BASE) + 0x0100) +#define CONNAC2X_WPDMA_HOST2MCU_SW_INT_SET(__BASE) ((__BASE) + 0x0108) +#define CONNAC2X_WPDMA_MCU2HOST_SW_INT_STA(__BASE) ((__BASE) + 0x01F0) +#define CONNAC2X_WPDMA_MCU2HOST_SW_INT_MASK(__BASE) ((__BASE) + 0x01F4) +#define CONNAC2X_WPDMA_INT_STA(__BASE) ((__BASE) + 0x0200) +#define CONNAC2X_WPDMA_INT_MASK(__BASE) ((__BASE) + 0x0204) +#define CONNAC2X_WPDMA_RST_DTX_PTR(__BASE) ((__BASE) + 0x020C) +#define CONNAC2X_WPDMA_RST_DRX_PTR(__BASE) ((__BASE) + 0x0280) + + +#define CONNAC2X_TX_RING_BASE(__BASE) ((__BASE) + 0x0300) +#define CONNAC2X_TX_RING_PTR(__BASE) ((__BASE) + 0x0300) +#define CONNAC2X_TX_RING_CNT(__BASE) ((__BASE) + 0x0304) +#define CONNAC2X_TX_RING_CIDX(__BASE) ((__BASE) + 0x0308) +#define CONNAC2X_TX_RING_DIDX(__BASE) ((__BASE) + 0x030C) + +#define CONNAC2X_RX_RING_BASE(__BASE) ((__BASE) + 0x0500) +#define CONNAC2X_RX_RING_PTR(__BASE) ((__BASE) + 0x0500) +#define CONNAC2X_RX_RING_CNT(__BASE) ((__BASE) + 0x0504) +#define CONNAC2X_RX_RING_DIDX(__BASE) ((__BASE) + 0x050C) +#define CONNAC2X_RX_RING_EXT_CTRL_BASE(__BASE) ((__BASE) + 0x0680) + +#define CONNAC2X_WFDMA1_RX_RING_BASE(__BASE) ((__BASE) + 0x0500) +#define CONNAC2X_WFDMA1_RX_RING_PTR(__BASE) ((__BASE) + 0x0500) +#define CONNAC2X_WFDMA1_RX_RING_CNT(__BASE) ((__BASE) + 0x0504) +#define CONNAC2X_WFDMA1_RX_RING_CIDX(__BASE) ((__BASE) + 0x0508) +#define CONNAC2X_WFDMA1_RX_RING_DIDX(__BASE) ((__BASE) + 0x050C) +#define CONNAC2X_WFDMA1_RX_RING_EXT_CTRL_BASE(__BASE) ((__BASE) + 0x0680) + +#define CONNAC2X_FWDL_TX_RING_IDX 16 +#define CONNAC2X_CMD_TX_RING_IDX 17 /* Direct to WM */ +#define CONNAC2X_DATA0_TXD_IDX 18 /* Band_0 TXD to WA */ +#define CONNAC2X_DATA1_TXD_IDX 19 /* Band_1 TXD to WA */ +#define CONNAC2X_CMD_TX_WA_RING_IDX 20 /* WA relay to WM */ + + +/* WPDMA_INT_STA (0x50000000+0x200) */ +#define CONNAC2X_WFDMA_TX_DONE_INT17 BIT(27) +#define CONNAC2X_WFDMA_TX_DONE_INT16 BIT(26) +#define CONNAC2X_WFDMA_RX_DONE_INT5 BIT(23) +#define CONNAC2X_WFDMA_RX_DONE_INT4 BIT(22) +#define CONNAC2X_TX_COHERENT_INT BIT(21) +#define CONNAC2X_RX_COHERENT_INT BIT(20) +#define CONNAC2X_WFDMA_TX_DONE_INT6 BIT(10) +#define CONNAC2X_WFDMA_TX_DONE_INT5 BIT(9) +#define CONNAC2X_WFDMA_TX_DONE_INT4 BIT(8) +#define CONNAC2X_WFDMA_TX_DONE_INT3 BIT(7) +#define CONNAC2X_WFDMA_TX_DONE_INT2 BIT(6) +#define CONNAC2X_WFDMA_TX_DONE_INT1 BIT(5) +#define CONNAC2X_WFDMA_TX_DONE_INT0 BIT(4) +#define CONNAC2X_WFDMA_RX_DONE_INT3 BIT(3) +#define CONNAC2X_WFDMA_RX_DONE_INT2 BIT(2) +#define CONNAC2X_WFDMA_RX_DONE_INT1 BIT(1) +#define CONNAC2X_WFDMA_RX_DONE_INT0 BIT(0) + +/* EXT WPDMA_INT_STA (0x53000000+0x10) */ +#define CONNAC2X_EXT_WFDMA1_TX_DONE_INT19 BIT(31) +#define CONNAC2X_EXT_WFDMA1_TX_DONE_INT18 BIT(30) +#define CONNAC2X_EXT_WFDMA1_TX_DONE_INT17 BIT(27) +#define CONNAC2X_EXT_WFDMA1_TX_DONE_INT16 BIT(26) +#define CONNAC2X_EXT_WFDMA0_TX_COHERENT_INT BIT(23) +#define CONNAC2X_EXT_WFDMA0_RX_COHERENT_INT BIT(22) +#define CONNAC2X_EXT_WFDMA1_TX_COHERENT_INT BIT(21) +#define CONNAC2X_EXT_WFDMA1_RX_COHERENT_INT BIT(20) +#define CONNAC2X_EXT_WFDMA0_RX_DONE_INT3 BIT(19) +#define CONNAC2X_EXT_WFDMA0_RX_DONE_INT2 BIT(18) +#define CONNAC2X_EXT_WFDMA0_RX_DONE_INT1 BIT(17) +#define CONNAC2X_EXT_WFDMA0_RX_DONE_INT0 BIT(16) +#define CONNAC2X_EXT_WFDMA1_TX_DONE_INT20 BIT(15) +#define CONNAC2X_EXT_WFDMA1_TX_DONE_INT6 BIT(10) +#define CONNAC2X_EXT_WFDMA1_TX_DONE_INT5 BIT(9) +#define CONNAC2X_EXT_WFDMA1_TX_DONE_INT4 BIT(8) +#define CONNAC2X_EXT_WFDMA1_TX_DONE_INT3 BIT(7) +#define CONNAC2X_EXT_WFDMA1_TX_DONE_INT2 BIT(6) +#define CONNAC2X_EXT_WFDMA1_TX_DONE_INT1 BIT(5) +#define CONNAC2X_EXT_WFDMA1_TX_DONE_INT0 BIT(4) +#define CONNAC2X_EXT_WFDMA1_RX_DONE_INT2 BIT(2) +#define CONNAC2X_EXT_WFDMA1_RX_DONE_INT1 BIT(1) +#define CONNAC2X_EXT_WFDMA1_RX_DONE_INT0 BIT(0) + + +#define CONNAC2X_HOST_CSR_TOP_BASE (0x7c060000) +#define CONNAC2X_BN0_LPCTL_ADDR (CONNAC2X_HOST_CSR_TOP_BASE + 0x10) +#define CONNAC2X_BN0_IRQ_STAT_ADDR (CONNAC2X_HOST_CSR_TOP_BASE + 0x14) +#define CONNAC2X_BN0_IRQ_ENA_ADDR (CONNAC2X_HOST_CSR_TOP_BASE + 0x18) + +#endif /* _HIF_PCIE || _HIF_AXI */ + +#if defined(_HIF_USB) +#define CONNAC2X_UDMA_BASE 0x74000000 +#define CONNAC2X_UDMA_TX_QSEL (CONNAC2X_UDMA_BASE + 0x08) /* 0008 */ +#define CONNAC2X_UDMA_RESET (CONNAC2X_UDMA_BASE + 0x14) /* 0014 */ +#define CONNAC2X_UDMA_WLCFG_1 (CONNAC2X_UDMA_BASE + 0x0C) /* 000c */ +#define CONNAC2X_UDMA_WLCFG_0 (CONNAC2X_UDMA_BASE + 0x18) /* 0018 */ + +#define CONNAC2X_UDMA_WLCFG_0_WL_TX_BUSY_MASK (0x1 << 31) +#define CONNAC2X_UDMA_WLCFG_0_WL_TX_EN(p) (((p) & 0x1) << 23) +#define CONNAC2X_UDMA_WLCFG_0_WL_RX_EN(p) (((p) & 0x1) << 22) +#define CONNAC2X_UDMA_WLCFG_0_TICK_1US_EN_MASK (0x1 << 20) +#define CONNAC2X_UDMA_WLCFG_0_TICK_1US_EN(p) (((p) & 0x1) << 20) +#define CONNAC2X_UDMA_WLCFG_0_WL_RX_FLUSH_MASK (0x1 << 19) +#define CONNAC2X_UDMA_WLCFG_0_WL_RX_MPSZ_PAD0(p) (((p) & 0x1) << 18) +#define CONNAC2X_UDMA_WLCFG_0_WL_TX_TMOUT_FUNC_EN_MASK (0x1 << 16) +#define CONNAC2X_UDMA_WLCFG_1_WL_TX_TMOUT_LMT_MASK (0xFFFFF << 8) +#define CONNAC2X_UDMA_WLCFG_1_WL_TX_TMOUT_LMT(p) (((p) & 0xFFFFF) << 8) + +#define CONNAC2X_UDMA_TX_TIMEOUT_LIMIT (50000) + +#define CONNAC2X_WFDMA_HOST_CONFIG_ADDR 0x7c027030 +/* + * 0: command packet forward to TX ring 17 (WMCPU) + * 1: forward to TX ring 20 (WACPU) + */ +#define CONNAC2X_WFDMA_HOST_CONFIG_USB_CMDPKT_DST_MASK (0x1 << 7) +#define CONNAC2X_WFDMA_HOST_CONFIG_USB_CMDPKT_DST(p) (((p) & 0x1) << 7) +#define CONNAC2X_USB_CMDPKT2WM 0 +#define CONNAC2X_USB_CMDPKT2WA 1 + +#define CONNAC2X_WFDMA_HOST_CONFIG_USB_RXEVT_EP4_EN (0x1 << 6) + +#define CONNAC2X_LEN_USB_RX_PADDING_CSO (4) /*HW design spec */ +#endif /* _HIF_USB */ + +/*------------------------------------------------------------------------*/ +/* Rx descriptor field related information */ +/*------------------------------------------------------------------------*/ +/* DW 0 */ +#define CONNAC2X_RXD_RX_BYTE_COUNT_MASK BITS(0, 15) +#define CONNAC2X_RXD_RX_BYTE_COUNT_OFFSET 0 + +#define CONNAC2X_RXD_PKT_TYPE_MASK BITS(27, 31) +#define CONNAC2X_RXD_PKT_TYPE_OFFSET 27 + +#define HAL_CONNAC2X_RXD_GET_PKT_TYPE(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2DW0 &\ + CONNAC2X_RXD_PKT_TYPE_MASK) >> CONNAC2X_RXD_PKT_TYPE_OFFSET) + +/*------------------------------------------------------------------------------ + * MACRO for WTBL INFO GET + *------------------------------------------------------------------------------ + */ + +/* CONNAC2X */ +#define CONNAC2X_WIFI_LWTBL_BASE 0x820d4000 +#define CONNAC2X_WIFI_LWTBL_GROUP_MASK 0x00000007 /* GROUP[2..0] */ +#define CONNAC2X_WIFI_LWTBL_GROUP_SHFT 0 + +#define CONNAC2X_WIFI_UWTBL_BASE 0x820c4000 +#define CONNAC2X_WIFI_UWTBL_TARGET_MASK 0x80000000 /* TARGET[31] */ +#define CONNAC2X_WIFI_UWTBL_TARGET_SHFT 31 +#define CONNAC2X_WIFI_UWTBL_GROUP_MASK 0x0000000F /* GROUP[3..0] */ +#define CONNAC2X_WIFI_UWTBL_GROUP_SHFT 0 + + +/* UWTBL DW 5 */ +#define CONNAC2X_WTBL_KEY_LINK_DW_KEY_LOC0_MASK BITS(0, 10) +#define CONNAC2X_WTBL_KEY_LINK_DW_KEY_LOC0_OFFSET 0 + +#define CONNAC2X_WTBL_KEY_LINK_DW_KEY_LOC1_MASK BITS(16, 26) +#define CONNAC2X_WTBL_KEY_LINK_DW_KEY_LOC1_OFFSET 16 + + + +#define CONNAC2X_LWTBL_CONFIG(_pAd, _lmacWtblDUAddr, _wlanIdx) \ + HAL_MCR_WR(_pAd, _lmacWtblDUAddr, \ + ((_wlanIdx >> 7) & CONNAC2X_WIFI_LWTBL_GROUP_MASK) \ + << CONNAC2X_WIFI_LWTBL_GROUP_SHFT) + +#define CONNAC2X_LWTBL_IDX2BASE(_lmacWtblDUAddr, _wlanIdx, _DW) \ + ((_lmacWtblDUAddr & 0xFFFF0000) | 0x8000 | \ + ((_wlanIdx & 0x7F) << 8) | (_DW & 0x3F) << 2) + +#define CONNAC2X_UWTBL_CONFIG(_pAd, _umacWtblDUAddr, _wlanIdx) \ + HAL_MCR_WR(_pAd, _umacWtblDUAddr, \ + ((_wlanIdx >> 7) & CONNAC2X_WIFI_UWTBL_GROUP_MASK) \ + << CONNAC2X_WIFI_UWTBL_GROUP_SHFT) + +#define CONNAC2X_UWTBL_IDX2BASE(_umacWtblDUAddr, _wlanIdx, _DW) \ + ((_umacWtblDUAddr & 0XFFFFC000) | 0x2000 | \ + ((_wlanIdx & 0x7F) << 6) | (_DW & 0xF) << 2) + +#define CONNAC2X_KEYTBL_CONFIG(_pAd, _umacWtblDUAddr, _key_loc) \ + HAL_MCR_WR(_pAd, _umacWtblDUAddr, \ + (CONNAC2X_WIFI_UWTBL_TARGET_MASK | \ + (((_key_loc >> 7) & CONNAC2X_WIFI_UWTBL_GROUP_MASK) \ + << CONNAC2X_WIFI_UWTBL_GROUP_SHFT))) + +#define CONNAC2X_KEYTBL_IDX2BASE(_umacWtblDUAddr, _key_loc, _DW) \ + ((_umacWtblDUAddr & 0XFFFFC000) | 0x2000 | \ + ((_key_loc & 0x7F) << 6) | (_DW & 0xF) << 2) + +/*------------------------------------------------------------------------------ + * MACRO for CONNAC2X RXVECTOR Parsing + *------------------------------------------------------------------------------ + */ +/* P-RXVector, 1st Cycle */ +#define CONNAC2X_RX_VT_RX_RATE_MASK BITS(0, 6) +#define CONNAC2X_RX_VT_RX_RATE_OFFSET 0 +#define CONNAC2X_RX_VT_NSTS_MASK BITS(7, 9) +#define CONNAC2X_RX_VT_NSTS_OFFSET 7 +#define CONNAC2X_RX_VT_LDPC BIT(11) + +/* C-RXC Vector, 1st Cycle */ +#define CONNAC2X_RX_VT_STBC_MASK BITS(0, 1) +#define CONNAC2X_RX_VT_STBC_OFFSET 0 +#define CONNAC2X_RX_VT_RX_MODE_MASK BITS(4, 7) +#define CONNAC2X_RX_VT_RX_MODE_OFFSET 4 +#define CONNAC2X_RX_VT_FR_MODE_MASK BITS(8, 10) +#define CONNAC2X_RX_VT_FR_MODE_OFFSET 8 +#define CONNAC2X_RX_VT_SHORT_GI_MASK BITS(13, 14) +#define CONNAC2X_RX_VT_SHORT_GI_OFFSET 13 +#define CONNAC2X_RX_VT_GROUP_ID_MASK BITS(22, 27) +#define CONNAC2X_RX_VT_GROUP_ID_OFFSET 22 + +/* C-RXC Vector, 4th Cycle */ +#define CONNAC2X_RX_VT_RCPI0_MASK BITS(0, 7) +#define CONNAC2X_RX_VT_RCPI0_OFFSET 0 +#define CONNAC2X_RX_VT_RCPI1_MASK BITS(8, 15) +#define CONNAC2X_RX_VT_RCPI1_OFFSET 8 +#define CONNAC2X_RX_VT_RCPI2_MASK BITS(16, 23) +#define CONNAC2X_RX_VT_RCPI2_OFFSET 16 +#define CONNAC2X_RX_VT_RCPI3_MASK BITS(24, 31) +#define CONNAC2X_RX_VT_RCPI3_OFFSET 24 + +#define CONNAC2X_HAL_RX_VECTOR_GET_RX_VECTOR(_prHwRxVector, _ucIdx) \ + ((_prHwRxVector)->u4RxVector[_ucIdx]) + + +#if defined(_HIF_PCIE) || defined(_HIF_AXI) +#define HAL_IS_CONNAC2X_EXT_TX_DONE_INTR(u4IntrStatus, __u4IntrBits) \ + ((u4IntrStatus & (__u4IntrBits)) ? TRUE : FALSE) + +#define HAL_IS_CONNAC2X_EXT_RX_DONE_INTR(u4IntrStatus, __u4IntrBits) \ + ((u4IntrStatus & (__u4IntrBits)) ? TRUE : FALSE) +#endif /* defined(_HIF_PCIE) || defined(_HIF_AXI) */ + + +/*------------------------------------------------------------------------------ + * MACRO for CONNAC2X WTBL TX RATE + *------------------------------------------------------------------------------ + */ +#define CONNAC2X_HW_TX_RATE_TO_MODE(_x) (((_x) & (0xf << 6)) >> 6) +#define CONNAC2X_HW_TX_RATE_TO_NSS(_x) (((_x) & (0x7 << 10)) >> 10) +#define CONNAC2X_HW_TX_RATE_TO_STBC(_x) (((_x) & (0x1 << 13)) >> 13) + +/*------------------------------------------------------------------------------ + * MACRO for CONNAC2X TXV + *------------------------------------------------------------------------------ + */ +#define CONNAC2X_TXV_GET_TX_RATE(_x) ((_x)->u4TxV[2] & 0x7f) +#define CONNAC2X_TXV_GET_TX_LDPC(_x) (((_x)->u4TxV[2] & (0x1 << 7)) >> 7) +#define CONNAC2X_TXV_GET_TX_STBC(_x) (((_x)->u4TxV[0] & (0x3 << 6)) >> 6) +#define CONNAC2X_TXV_GET_TX_FRMODE(_x) (((_x)->u4TxV[0] & (0x7 << 8)) >> 8) +#define CONNAC2X_TXV_GET_TX_MODE(_x) (((_x)->u4TxV[0] & (0xf << 12)) >> 12) +#define CONNAC2X_TXV_GET_TX_NSTS(_x) (((_x)->u4TxV[2] & (0x7 << 8)) >> 8) +#define CONNAC2X_TXV_GET_TX_PWR(_x) (((_x)->u4TxV[0] & (0xff << 16)) >> 16) +#define CONNAC2X_TXV_GET_TX_SGI(_x) (((_x)->u4TxV[1] & (0x3 << 26)) >> 26) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +struct CONNAC2X_WIFI_CMD { + struct HW_MAC_CONNAC2X_TX_DESC rWifiCmdTxD; + + uint16_t u2Length; + uint16_t u2PqId; + + uint8_t ucCID; + uint8_t ucPktTypeID; /* Must be 0x20 (CMD Packet) */ + uint8_t ucSetQuery; + uint8_t ucSeqNum; + + /* padding fields, hw may auto modify this field */ + uint8_t ucD2B0Rev; + uint8_t ucExtenCID; /* Extend CID */ + uint8_t ucS2DIndex; /* Index for Src to Dst in CMD usage */ + uint8_t ucExtCmdOption; /* Extend CID option */ + + uint8_t ucCmdVersion; + uint8_t ucReserved2[3]; + uint32_t au4Reserved3[4]; /* padding fields */ + + uint8_t aucBuffer[0]; +}; + +union WTBL_LMAC_DW0 { + struct { + uint32_t addr_4:8; + uint32_t addr_5:8; + uint32_t muar_idx:6; + uint32_t rc_a1:1; + uint32_t kid:2; + uint32_t rc_id:1; + uint32_t fd:1; + uint32_t td:1; + uint32_t rv:1; + uint32_t rc_a2:1; + uint32_t wpi_flg:1; + uint32_t pad:1; + } field; + uint32_t word; +}; + +union WTBL_LMAC_DW1 { + struct { + uint32_t addr_0; + } field; + uint32_t word; +}; + +enum WTBL_LMAC_CIPHER_SUIT { + WTBL_CIPHER_NONE = 0, + WTBL_CIPHER_WEP_40 = 1, + WTBL_CIPHER_TKIP_MIC = 2, + WTBL_CIPHER_TKIP_NO_MIC = 3, + WTBL_CIPHER_CCMP_128_PMF = 4, + WTBL_CIPHER_WEP_104 = 5, + WTBL_CIPHER_BIP_CMAC_128 = 6, + WTBL_CIPHER_WEP_128 = 7, + WTBL_CIPHER_WPI_128 = 8, + WTBL_CIPHER_CCMP_128_CCX = 9, + WTBL_CIPHER_CCMP_256 = 10, + WTBL_CIPHER_GCMP_128 = 11, + WTBL_CIPHER_GCMP_256 = 12, + WTBL_CIPHER_GCMP_WPI_128 = 13, +}; + +union WTBL_LMAC_DW2 { + struct { + uint32_t aid12:12; + uint32_t gid_su:1; + uint32_t spp_en:1; + uint32_t wpi_even:1; + uint32_t aad_om:1; + uint32_t cipher_suit:5; + uint32_t cipher_suit_igtk:2; + uint32_t rsvd:1; + uint32_t sw:1; + uint32_t ul:1; + uint32_t tx_ps:1; + uint32_t qos:1; + uint32_t ht:1; + uint32_t vht:1; + uint32_t he:1; + uint32_t mesh:1; + } field; + uint32_t word; +}; + +union WTBL_LMAC_DW3 { + struct { + uint32_t wmm_q:2; + uint32_t rxd_dup_mode:2; + uint32_t vlan_2e_th:1; + uint32_t pad:3; + uint32_t pfmu_index:8; + uint32_t bf_rsvd:8; + uint32_t ribf:1; + uint32_t bf_rsvd2:4; + uint32_t tebf:1; + uint32_t tebf_vht:1; + uint32_t tebf_he:1; + } field; + + struct { + uint32_t wmm_q:2; + uint32_t rxd_dup_mode:2; + uint32_t vlan_2e_th:1; + uint32_t beam_chg:1; + uint32_t ba_mode:2; + uint32_t pfmu_index:8; + uint32_t ulpf_index:8; + uint32_t ribf:1; + uint32_t ulpf:1; + uint32_t ign_fbk:1; + uint32_t bf_rsvd2:2; + uint32_t tebf:1; + uint32_t tebf_vht:1; + uint32_t tebf_he:1; + } field_v2; + uint32_t word; +}; + +union WTBL_LMAC_DW4 { + struct { + uint32_t ant_id_sts0:3; + uint32_t ant_id_sts1:3; + uint32_t ant_id_sts2:3; + uint32_t ant_id_sts3:3; + uint32_t ant_id_sts4:3; + uint32_t ant_id_sts5:3; + uint32_t ant_id_sts6:3; + uint32_t ant_id_sts7:3; + uint32_t cascad:1; + uint32_t ldpc_ht:1; + uint32_t ldpc_vht:1; + uint32_t ldpc_he:1; + uint32_t dis_rhtr:1; + uint32_t all_ack:1; + uint32_t drop:1; + uint32_t ack_en:1; + } field; + uint32_t word; +}; + +union WTBL_LMAC_DW5 { + struct { + uint32_t af:3; + uint32_t af_he:2; + uint32_t rts:1; + uint32_t smps:1; + uint32_t dyn_bw:1; + uint32_t mmss:3; + uint32_t usr:1; + uint32_t sr_r:2; + uint32_t beam_chg:1; + uint32_t sr_abort:1; + uint32_t tx_power_offset:6; + uint32_t mpdu_size:2; + uint32_t pe:2; + uint32_t doppl:1; + uint32_t txop_ps_cap:1; + uint32_t du_i_psm:1; + uint32_t i_psm:1; + uint32_t psm:1; + uint32_t skip_tx:1; + } field; + + struct { + uint32_t af:3; + uint32_t af_he:2; + uint32_t rts:1; + uint32_t smps:1; + uint32_t dyn_bw:1; + uint32_t mmss:3; + uint32_t usr:1; + uint32_t sr_r:3; + uint32_t sr_abort:1; + uint32_t tx_power_offset:6; + uint32_t mpdu_size:2; + uint32_t pe:2; + uint32_t doppl:1; + uint32_t txop_ps_cap:1; + uint32_t du_i_psm:1; + uint32_t i_psm:1; + uint32_t psm:1; + uint32_t skip_tx:1; + } field_v2; + uint32_t word; +}; + +union WTBL_LMAC_DW6 { + struct { + uint32_t ba_win_size_tid0:4; + uint32_t ba_win_size_tid1:4; + uint32_t ba_win_size_tid2:4; + uint32_t ba_win_size_tid3:4; + uint32_t ba_win_size_tid4:4; + uint32_t ba_win_size_tid5:4; + uint32_t ba_win_size_tid6:4; + uint32_t ba_win_size_tid7:4; + } field; + uint32_t word; +}; + +union WTBL_LMAC_DW7 { + struct { + uint32_t cb_rn:3; + uint32_t dbnss_en:1; + uint32_t bafen:1; + uint32_t rdg_ba:1; + uint32_t r:1; + uint32_t spe_idx:5; + uint32_t g2:1; + uint32_t g4:1; + uint32_t g8:1; + uint32_t g16:1; + uint32_t g2_ltf:2; + uint32_t g4_ltf:2; + uint32_t g8_ltf:2; + uint32_t g16_ltf:2; + uint32_t g2_he:2; + uint32_t g4_he:2; + uint32_t g8_he:2; + uint32_t g16_he:2; + } field; + uint32_t word; +}; + +union WTBL_LMAC_DW8 { + struct { + uint32_t rts_fail_cnt_ac0:5; + uint32_t rts_fail_cnt_ac1:5; + uint32_t rts_fail_cnt_ac2:5; + uint32_t rts_fail_cnt_ac3:5; + uint32_t partial_aid:9; + uint32_t pad:2; + uint32_t chk_per:1; + } field; + uint32_t word; +}; + +union WTBL_LMAC_DW9 { + struct { + uint32_t rx_avg_mpdu_size:14; + uint32_t pad:4; + uint32_t pritx_dcm:1; + uint32_t pritx_er160:1; + uint32_t pritx_ersu:1; + uint32_t fcap:2; + uint32_t mpdu_fail_cnt:3; + uint32_t mpdu_ok_cnt:3; + uint32_t rate_idx:3; + } field; + + struct { + uint32_t rx_avg_mpdu_size:14; + uint32_t pad:2; + uint32_t pritx_sw_mode:1; + uint32_t pritx_plr:1; + uint32_t pritx_dcm:1; + uint32_t pritx_er160:1; + uint32_t pritx_ersu:1; + uint32_t fcap:2; + uint32_t mpdu_fail_cnt:3; + uint32_t mpdu_ok_cnt:3; + uint32_t rate_idx:3; + } field_v2; + uint32_t word; +}; + +union WTBL_LMAC_DW10 { + struct { + uint32_t rate1:14; + uint32_t pad:2; + uint32_t rate2:14; + uint32_t pad2:2; + } field; + uint32_t word; +}; + +union WTBL_LMAC_DW11 { + struct { + uint32_t rate3:14; + uint32_t pad:2; + uint32_t rate4:14; + uint32_t pad2:2; + } field; + uint32_t word; +}; + +union WTBL_LMAC_DW12 { + struct { + uint32_t rate5:14; + uint32_t pad:2; + uint32_t rate6:14; + uint32_t pad2:2; + } field; + uint32_t word; +}; + +union WTBL_LMAC_DW13 { + struct { + uint32_t rate7:14; + uint32_t pad:2; + uint32_t rate8:14; + uint32_t pad2:2; + } field; + uint32_t word; +}; + +union WTBL_LMAC_DW14 { + struct { + uint32_t rate_1_tx_cnt:16; + uint32_t rate_1_fail_cnt:16; + } field; + uint32_t word; +}; + +union WTBL_LMAC_DW15 { + struct { + uint32_t rate_2_ok_cnt:16; + uint32_t rate_3_ok_cnt:16; + } field; + uint32_t word; +}; + +union WTBL_LMAC_DW16 { + struct { + uint32_t current_bw_tx_cnt:16; + uint32_t current_bw_fail_cnt:16; + } field; + uint32_t word; +}; + +union WTBL_LMAC_DW17 { + struct { + uint32_t other_bw_tx_cnt:16; + uint32_t other_bw_fail_cnt:16; + } field; + uint32_t word; +}; + +union WTBL_LMAC_DW18 { + struct { + uint32_t rts_ok_cnt:16; + uint32_t rts_fail_cnt:16; + } field; + uint32_t word; +}; + +union WTBL_LMAC_DW19 { + struct { + uint32_t data_retry_cnt:16; + uint32_t mgnt_retry_cnt:16; + } field; + uint32_t word; +}; + +union WTBL_LMAC_DW20 { + uint32_t word; +}; + +union WTBL_LMAC_DW21 { + uint32_t word; +}; + +union WTBL_LMAC_DW22 { + uint32_t word; +}; + +union WTBL_LMAC_DW23 { + uint32_t word; +}; + +union WTBL_LMAC_DW24 { + uint32_t word; +}; + +union WTBL_LMAC_DW25 { + uint32_t word; +}; + +union WTBL_LMAC_DW26 { + uint32_t word; +}; + +union WTBL_LMAC_DW27 { + uint32_t word; +}; + +union WTBL_LMAC_DW28 { + struct { + uint32_t usr_rssi:9; + uint32_t usr_snr:6; + uint32_t pad:1; + uint32_t rapid_reaction_rate:11; + uint32_t pad2:3; + uint32_t ht_amsdu:1; + uint32_t amsdu_cros_lg:1; + } field; + + struct { + uint32_t om_info:12; + uint32_t rxd_dup_om_chg:1; + uint32_t pad:19; + } field_v2; + uint32_t word; +}; + +union WTBL_LMAC_DW29 { + struct { + uint32_t resp_rcpi_0:8; + uint32_t resp_rcpi_1:8; + uint32_t resp_rcpi_2:8; + uint32_t resp_rcpi_3:8; + } field; + + struct { + uint32_t usr_rssi:9; + uint32_t usr_snr:6; + uint32_t pad:1; + uint32_t rapid_reaction_rate:11; + uint32_t pad2:3; + uint32_t ht_amsdu:1; + uint32_t amsdu_cros_lg:1; + } field_2; + uint32_t word; +}; + +union WTBL_LMAC_DW30 { + struct { + uint32_t resp_rcpi_4:8; + uint32_t resp_rcpi_5:8; + uint32_t resp_rcpi_6:8; + uint32_t resp_rcpi_7:8; + } field; + + struct { + uint32_t resp_rcpi_0:8; + uint32_t resp_rcpi_1:8; + uint32_t resp_rcpi_2:8; + uint32_t resp_rcpi_3:8; + } field_v2; + uint32_t word; +}; + +union WTBL_LMAC_DW31 { + struct { + uint32_t snr_rx0:6; + uint32_t snr_rx1:6; + uint32_t snr_rx2:6; + uint32_t snr_rx3:6; + uint32_t pad:8; + } field; + uint32_t word; +}; + +union WTBL_LMAC_DW32 { + struct { + uint32_t snr_rx4:6; + uint32_t snr_rx5:6; + uint32_t snr_rx6:6; + uint32_t snr_rx7:6; + uint32_t pad:8; + } field; + uint32_t word; +}; + +struct wtbl_rx_stat { + union WTBL_LMAC_DW28 wtbl_d28; + union WTBL_LMAC_DW29 wtbl_d29; + union WTBL_LMAC_DW30 wtbl_d30; + union WTBL_LMAC_DW31 wtbl_d31; + union WTBL_LMAC_DW32 wtbl_d32; +}; + +struct wtbl_adm_ctrl { + union WTBL_LMAC_DW20 wtbl_d20; + union WTBL_LMAC_DW21 wtbl_d21; + union WTBL_LMAC_DW22 wtbl_d22; + union WTBL_LMAC_DW23 wtbl_d23; + union WTBL_LMAC_DW24 wtbl_d24; + union WTBL_LMAC_DW25 wtbl_d25; + union WTBL_LMAC_DW26 wtbl_d26; + union WTBL_LMAC_DW27 wtbl_d27; +}; + +struct wtbl_ppdu_cnt { + union WTBL_LMAC_DW19 wtbl_d19; +}; + +struct wtbl_auto_rate_cnt { + union WTBL_LMAC_DW14 wtbl_d14; + union WTBL_LMAC_DW15 wtbl_d15; + union WTBL_LMAC_DW16 wtbl_d16; + union WTBL_LMAC_DW17 wtbl_d17; + union WTBL_LMAC_DW18 wtbl_d18; +}; + +struct wtbl_auto_rate_tb { + union WTBL_LMAC_DW10 wtbl_d10; + union WTBL_LMAC_DW11 wtbl_d11; + union WTBL_LMAC_DW12 wtbl_d12; + union WTBL_LMAC_DW13 wtbl_d13; +}; + +struct wtbl_tx_rx_cap { + union WTBL_LMAC_DW2 wtbl_d2; + union WTBL_LMAC_DW3 wtbl_d3; + union WTBL_LMAC_DW4 wtbl_d4; + union WTBL_LMAC_DW5 wtbl_d5; + union WTBL_LMAC_DW6 wtbl_d6; + union WTBL_LMAC_DW7 wtbl_d7; + union WTBL_LMAC_DW8 wtbl_d8; + union WTBL_LMAC_DW9 wtbl_d9; +}; + +struct wtbl_basic_info { + union WTBL_LMAC_DW0 wtbl_d0; + union WTBL_LMAC_DW1 wtbl_d1; +}; + +struct fwtbl_lmac_struct { + struct wtbl_basic_info peer_basic_info; + struct wtbl_tx_rx_cap trx_cap; + struct wtbl_auto_rate_tb auto_rate_tb; + struct wtbl_auto_rate_cnt auto_rate_counters; + struct wtbl_ppdu_cnt ppdu_counters; + struct wtbl_adm_ctrl adm_ctrl; + struct wtbl_rx_stat rx_stat; +}; + +union WTBL_UMAC_DW0 { + struct { + uint32_t pn0; + } field; + uint32_t word; +}; + +union WTBL_UMAC_DW1 { + struct { + uint32_t pn1:16; + uint32_t com_sn:12; + uint32_t pad:4; + } field; + uint32_t word; +}; + +union WTBL_UMAC_DW2 { + struct { + uint32_t ac0_sn:12; + uint32_t ac1_sn:12; + uint32_t ac2_sn:8; + } field; + uint32_t word; +}; + +union WTBL_UMAC_DW3 { + struct { + uint32_t ac2_sn:4; + uint32_t ac3_sn:12; + uint32_t ac4_sn:12; + uint32_t ac5_sn:4; + } field; + uint32_t word; +}; + +union WTBL_UMAC_DW4 { + struct { + uint32_t ac5_sn:8; + uint32_t ac6_sn:12; + uint32_t ac7_sn:12; + } field; + uint32_t word; +}; + +union WTBL_UMAC_DW5 { + struct { + uint32_t key_loc0:11; + uint32_t pad:5; + uint32_t key_loc1:11; + uint32_t qos:1; + uint32_t ht:1; + uint32_t pad2:3; + } field; + uint32_t word; +}; + +union WTBL_UMAC_DW6 { + struct { + uint32_t hw_amsdu_cfg:10; + uint32_t pad:22; + } field; + uint32_t word; +}; + +union WTBL_UMAC_DW7 { + struct { + uint32_t pad:32; + } field; + uint32_t word; +}; + +struct wtbl_key_tb { + union WTBL_UMAC_DW7 wtbl_d7; +}; + +struct wtbl_keylink_amsdu { + union WTBL_UMAC_DW5 wtbl_d5; + union WTBL_UMAC_DW6 wtbl_d6; +}; + +struct wtbl_serial_num { + union WTBL_UMAC_DW0 wtbl_d0; + union WTBL_UMAC_DW1 wtbl_d1; + union WTBL_UMAC_DW2 wtbl_d2; + union WTBL_UMAC_DW3 wtbl_d3; + union WTBL_UMAC_DW4 wtbl_d4; +}; + +struct fwtbl_umac_struct { + struct wtbl_serial_num serial_no; + struct wtbl_keylink_amsdu klink_amsdu; + struct wtbl_key_tb key_tb; +}; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +void asicConnac2xCapInit( + struct ADAPTER *prAdapter); +void asicConnac2xFillInitCmdTxd( + struct ADAPTER *prAdapter, + struct WIFI_CMD_INFO *prCmdInfo, + uint16_t *pu2BufInfoLen, + uint8_t *pucSeqNum, + void **pCmdBuf); +void asicConnac2xFillCmdTxd( + struct ADAPTER *prAdapter, + struct WIFI_CMD_INFO *prCmdInfo, + uint8_t *pucSeqNum, + void **pCmdBuf); + +#if defined(_HIF_PCIE) || defined(_HIF_AXI) +uint32_t asicConnac2xWfdmaCfgAddrGet( + struct GLUE_INFO *prGlueInfo, + u_int8_t ucDmaIdx); +uint32_t asicConnac2xWfdmaIntRstDtxPtrAddrGet( + struct GLUE_INFO *prGlueInfo, + u_int8_t ucDmaIdx); +uint32_t asicConnac2xWfdmaIntRstDrxPtrAddrGet( + struct GLUE_INFO *prGlueInfo, + u_int8_t ucDmaIdx); +uint32_t asicConnac2xWfdmaHifRstAddrGet( + struct GLUE_INFO *prGlueInfo, + u_int8_t ucDmaIdx); +void asicConnac2xWpdmaConfig( + struct GLUE_INFO *prGlueInfo, + uint8_t enable, + bool fgResetHif); +uint8_t asicConnac2xWfdmaWaitIdle( + struct GLUE_INFO *prGlueInfo, + uint8_t index, + uint32_t round, + uint32_t wait_us); +void asicConnac2xWfdmaTxRingExtCtrl( + struct GLUE_INFO *prGlueInfo, + struct RTMP_TX_RING *tx_ring, + uint32_t index); +void asicConnac2xWfdmaRxRingExtCtrl( + struct GLUE_INFO *prGlueInfo, + struct RTMP_RX_RING *rx_ring, + uint32_t index); +void asicConnac2xWfdmaManualPrefetch( + struct GLUE_INFO *prGlueInfo); +void asicConnac2xEnablePlatformIRQ( + struct ADAPTER *prAdapter); +void asicConnac2xDisablePlatformIRQ( + struct ADAPTER *prAdapter); +void asicConnac2xEnableExtInterrupt( + struct ADAPTER *prAdapter); +void asicConnac2xDisableExtInterrupt( + struct ADAPTER *prAdapter); +void asicConnac2xProcessTxInterrupt( + struct ADAPTER *prAdapter); +void asicConnac2xLowPowerOwnRead( + struct ADAPTER *prAdapter, + uint8_t *pfgResult); +void asicConnac2xLowPowerOwnSet( + struct ADAPTER *prAdapter, + uint8_t *pfgResult); +void asicConnac2xLowPowerOwnClear( + struct ADAPTER *prAdapter, + uint8_t *pfgResult); +void asicConnac2xProcessSoftwareInterrupt( + struct ADAPTER *prAdapter); +void asicConnac2xSoftwareInterruptMcu( + struct ADAPTER *prAdapter, u_int32_t intrBitMask); +void asicConnac2xHifRst( + struct GLUE_INFO *prGlueInfo); +void asicConnac2xReadExtIntStatus( + struct ADAPTER *prAdapter, + uint32_t *pu4IntStatus); +void asicConnac2xProcessRxInterrupt( + struct ADAPTER *prAdapter); +#endif /* _HIF_PCIE */ + +#if defined(_HIF_USB) +void asicConnac2xWfdmaInitForUSB( + struct ADAPTER *prAdapter, + struct mt66xx_chip_info *prChipInfo); +uint8_t asicConnac2xUsbEventEpDetected( + struct ADAPTER *prAdapter); +void asicConnac2xEnableUsbCmdTxRing( + struct ADAPTER *prAdapter, + u_int8_t ucDstRing); +#if CFG_ENABLE_FW_DOWNLOAD +void asicConnac2xEnableUsbFWDL( + struct ADAPTER *prAdapter, + u_int8_t fgEnable); +#endif /* CFG_ENABLE_FW_DOWNLOAD */ +u_int8_t asicConnac2xUsbResume(IN struct ADAPTER *prAdapter, + IN struct GLUE_INFO *prGlueInfo); +void asicConnac2xUdmaRxFlush( + struct ADAPTER *prAdapter, + u_int8_t bEnable); +uint16_t asicConnac2xUsbRxByteCount( + struct ADAPTER *prAdapter, + struct BUS_INFO *prBusInfo, + uint8_t *pRXD); +#endif /* _HIF_USB */ + +void fillConnac2xTxDescTxByteCount( + struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + void *prTxDesc); +void fillConnac2xTxDescAppendWithWaCpu( + struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + uint8_t *prTxDescBuffer); +void fillConnac2xTxDescAppendByWaCpu( + struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + uint16_t u4MsduId, + dma_addr_t rDmaAddr, + uint32_t u4Idx, + u_int8_t fgIsLast, + uint8_t *pucBuffer); +void fillTxDescTxByteCountWithWaCpu( + struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + void *prTxDesc); +void asicConnac2xInitTxdHook( + struct TX_DESC_OPS_T *prTxDescOps); +void asicConnac2xInitRxdHook( + struct RX_DESC_OPS_T *prRxDescOps); +#if (CFG_SUPPORT_MSP == 1) +void asicConnac2xRxProcessRxvforMSP(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prRetSwRfb); +#endif /* CFG_SUPPORT_MSP == 1 */ +uint8_t asicConnac2xRxGetRcpiValueFromRxv( + IN uint8_t ucRcpiMode, + IN struct SW_RFB *prSwRfb); +#if (CFG_SUPPORT_PERF_IND == 1) +void asicConnac2xRxPerfIndProcessRXV(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint8_t ucBssIndex); +#endif +void asicConnac2xWfdmaReInit( + struct ADAPTER *prAdapter); +void asicConnac2xWfdmaDummyCrWrite( + struct ADAPTER *prAdapter); + +#if (CFG_CHIP_RESET_SUPPORT == 1) && (CFG_WMT_RESET_API_SUPPORT == 0) +u_int8_t conn2_rst_L0_notify_step2(void); +#endif + +/******************************************************************************* +* D E B U G F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +uint32_t asic_connac2x_show_raw_wtbl_info( + struct GLUE_INFO *prGlueInfo, + int8_t *pcCommand, + int32_t i4TotalLen, + int32_t i4Argc, + int32_t idx); + +uint32_t dump_key_table( + struct GLUE_INFO *prGlueInfo, + int8_t *pcCommand, + int32_t i4TotalLen, + int16_t key_loc0, + int16_t key_loc1); + +char *asic_connac2x_hw_rate_ofdm_str( + u_int16_t ofdm_idx); + +char *asic_connac2x_fwtbl_hw_rate_str( + uint8_t mode, + uint16_t rate_idx); + +uint32_t asic_connac2x_show_txd_info( + struct ADAPTER *prAdapter, + int8_t *pcCommand, + int32_t i4TotalLen, + int32_t i4Argc, + int32_t idx); +uint32_t asic_connac2x_show_umac_wtbl_info( + struct ADAPTER *prAdapter, + int8_t *pcCommand, + int32_t i4TotalLen, + int32_t i4Argc, + int32_t idx); +u_int32_t asic_connac2x_show_rx_rate_info( + struct ADAPTER *prAdapter, + char *pcCommand, + int32_t i4TotalLen, + uint8_t ucStaIdx); +u_int32_t asic_connac2x_show_rx_rssi_info( + struct ADAPTER *prAdapter, + char *pcCommand, + int32_t i4TotalLen, + uint8_t ucStaIdx); +#endif /* CFG_SUPPORT_CONNAC2X == 1 */ +#endif /* _CMM_ASIC_CONNAC2X_H */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7915/wf_cr_sw_def.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7915/wf_cr_sw_def.h new file mode 100644 index 0000000000000..135f260de081c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7915/wf_cr_sw_def.h @@ -0,0 +1,119 @@ +/* [File] : wf_cr_sw_def.h */ +/* [Copyright] : Copyright (C) 2018 Mediatek Incorportion. All rights reserved. +*/ + +/******************************************************************************* +* 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 _WF_CR_SW_DEF_H +#define _WF_CR_SW_DEF_H + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + + +/****************************************************************************** +* +* MCU_SYSRAM SW CR Definitions +* +****************************************************************************** +*/ +#define WF_SW_DEF_CR_BASE 0x0041F200 + +#define WF_SW_DEF_CR_WACPU_STAT_ADDR \ + (WF_SW_DEF_CR_BASE + 0x000) /* F200 */ +#define WF_SW_DEF_CR_WACPU_SLEEP_STAT_ADDR \ + (WF_SW_DEF_CR_BASE + 0x004) /* F204 */ +#define WF_SW_DEF_CR_WM2WA_ACTION_ADDR \ + (WF_SW_DEF_CR_BASE + 0x008) /* F208 */ +#define WF_SW_DEF_CR_WA2WM_ACTION_ADDR \ + (WF_SW_DEF_CR_BASE + 0x00C) /* F20C */ +#define WF_SW_DEF_CR_LP_DBG0_ADDR \ + (WF_SW_DEF_CR_BASE + 0x010) /* F210 */ +#define WF_SW_DEF_CR_LP_DBG1_ADDR \ + (WF_SW_DEF_CR_BASE + 0x014) /* F214 */ +#define WF_SW_DEF_CR_SER_STATUS_ADDR \ + (WF_SW_DEF_CR_BASE + 0x040) /* F240 */ +#define WF_SW_DEF_CR_PLE_STATUS_ADDR \ + (WF_SW_DEF_CR_BASE + 0x044) /* F244 */ +#define WF_SW_DEF_CR_PLE1_STATUS_ADDR \ + (WF_SW_DEF_CR_BASE + 0x048) /* F248 */ +#define WF_SW_DEF_CR_PLE_AMSDU_STATUS_ADDR \ + (WF_SW_DEF_CR_BASE + 0x04C) /* F24C */ +#define WF_SW_DEF_CR_PSE_STATUS_ADDR \ + (WF_SW_DEF_CR_BASE + 0x050) /* F250 */ +#define WF_SW_DEF_CR_PSE1_STATUS_ADDR \ + (WF_SW_DEF_CR_BASE + 0x054) /* F254 */ +#define WF_SW_DEF_CR_LAMC_WISR6_BN0_STATUS_ADDR \ + (WF_SW_DEF_CR_BASE + 0x058) /* F258 */ +#define WF_SW_DEF_CR_LAMC_WISR6_BN1_STATUS_ADDR \ + (WF_SW_DEF_CR_BASE + 0x05C) /* F25C */ +#define WF_SW_DEF_CR_LAMC_WISR7_BN0_STATUS_ADDR \ + (WF_SW_DEF_CR_BASE + 0x060) /* F260 */ +#define WF_SW_DEF_CR_LAMC_WISR7_BN1_STATUS_ADDR \ + (WF_SW_DEF_CR_BASE + 0x064) /* F264 */ +#define WF_SW_DEF_CR_USB_MCU_EVENT_ADD \ + (WF_SW_DEF_CR_BASE + 0x070) /* F270 */ +#define WF_SW_DEF_CR_USB_HOST_ACK_ADDR \ + (WF_SW_DEF_CR_BASE + 0x074) /* F274 */ + +/* +* ---WF_SW_DEF_CR_WACPU_SLEEP_STAT_ADDR (0x0041F200 + 0x004)--- +* SLEEP_STATUS[0] - (RW) 0: Awake, 1: sleep +* GATING_STATUS[1] - (RW) 0:Idle, 1: Gating +* RESERVED5[31..2] - (RO) Reserved bits +*/ +#define WF_SW_DEF_CR_WACPU_SLEEP_STAT_SLEEP_ADDR \ + WF_SW_DEF_CR_WACPU_SLEEP_STAT_ADDR +#define WF_SW_DEF_CR_WACPU_SLEEP_STAT_SLEEP_MASK 0x00000001 +#define WF_SW_DEF_CR_WACPU_SLEEP_STAT_SLEEP_SHFT 0 +#define WF_SW_DEF_CR_WACPU_SLEEP_STAT_GATING_ADDR \ + WF_SW_DEF_CR_WACPU_SLEEP_STAT_ADDR +#define WF_SW_DEF_CR_WACPU_SLEEP_STAT_GATING_MASK 0x00000002 +#define WF_SW_DEF_CR_WACPU_SLEEP_STAT_GATING_SHFT 1 + + +#endif /* _WF_CR_SW_DEF_H */ + + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7915/wf_ple_top.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7915/wf_ple_top.h new file mode 100644 index 0000000000000..9529400319ebf --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7915/wf_ple_top.h @@ -0,0 +1,8757 @@ +/* [File] : wf_ple_top.h */ +/* [Revision time] : Mon Mar 18 15:00:44 2019 */ +/* [Description] : This file is auto generated by CODA */ +/* [Copyright] : Copyright (C) 2019 Mediatek Incorportion. All rights */ +/* reserved. */ + +#ifndef __WF_PLE_TOP_REGS_H__ +#define __WF_PLE_TOP_REGS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ************************************************************************** */ +/* */ +/* WF_PLE_TOP CR Definitions */ +/* */ +/* ************************************************************************** */ + +#define WF_PLE_TOP_BASE 0x820C0000 + +#define WF_PLE_TOP_GC_ADDR (WF_PLE_TOP_BASE + 0x00) /* 0000 */ +#define WF_PLE_TOP_PBUF_CTRL_ADDR (WF_PLE_TOP_BASE + 0x14) /* 0014 */ +#define WF_PLE_TOP_TIMEOUT_CTRL_ADDR (WF_PLE_TOP_BASE + 0x1c) /* 001C */ +#define WF_PLE_TOP_INT_N9_EN_MASK_ADDR (WF_PLE_TOP_BASE + 0x20) /* 0020 */ +#define WF_PLE_TOP_INT_N9_STS_ADDR (WF_PLE_TOP_BASE + 0x24) /* 0024 */ +#define WF_PLE_TOP_INT_N9_ERR_STS_ADDR (WF_PLE_TOP_BASE + 0x28) /* 0028 */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_ADDR (WF_PLE_TOP_BASE + 0x2C) /* 002C */ +#define WF_PLE_TOP_HOST_REPORT0_ADDR (WF_PLE_TOP_BASE + 0x30) /* 0030 */ +#define WF_PLE_TOP_HOST_REPORT1_ADDR (WF_PLE_TOP_BASE + 0x34) /* 0034 */ +#define WF_PLE_TOP_HOST_REPORT2_ADDR (WF_PLE_TOP_BASE + 0x38) /* 0038 */ +#define WF_PLE_TOP_BLK_MODE_RATE_LMT_ADDR (WF_PLE_TOP_BASE + 0x3c) /* 003C */ +#define WF_PLE_TOP_C_GET_FID_0_ADDR (WF_PLE_TOP_BASE + 0x40) /* 0040 */ +#define WF_PLE_TOP_C_GET_FID_1_ADDR (WF_PLE_TOP_BASE + 0x44) /* 0044 */ +#define WF_PLE_TOP_RELEASE_CTRL_0_ADDR (WF_PLE_TOP_BASE + 0x50) /* 0050 */ +#define WF_PLE_TOP_RELEASE_CTRL_1_ADDR (WF_PLE_TOP_BASE + 0x54) /* 0054 */ +#define WF_PLE_TOP_RELEASE_CTRL_2_ADDR (WF_PLE_TOP_BASE + 0x58) /* 0058 */ +#define WF_PLE_TOP_RELEASE_CTRL_3_ADDR (WF_PLE_TOP_BASE + 0x5c) /* 005C */ +#define WF_PLE_TOP_C_EN_QUEUE_0_ADDR (WF_PLE_TOP_BASE + 0x60) /* 0060 */ +#define WF_PLE_TOP_C_EN_QUEUE_1_ADDR (WF_PLE_TOP_BASE + 0x64) /* 0064 */ +#define WF_PLE_TOP_C_EN_QUEUE_2_ADDR (WF_PLE_TOP_BASE + 0x68) /* 0068 */ +#define WF_PLE_TOP_C_DE_QUEUE_0_ADDR (WF_PLE_TOP_BASE + 0x80) /* 0080 */ +#define WF_PLE_TOP_C_DE_QUEUE_1_ADDR (WF_PLE_TOP_BASE + 0x84) /* 0084 */ +#define WF_PLE_TOP_C_DE_QUEUE_2_ADDR (WF_PLE_TOP_BASE + 0x88) /* 0088 */ +#define WF_PLE_TOP_C_DE_QUEUE_3_ADDR (WF_PLE_TOP_BASE + 0x8c) /* 008C */ +#define WF_PLE_TOP_C_DE_QUEUE_4_ADDR (WF_PLE_TOP_BASE + 0x90) /* 0090 */ +#define WF_PLE_TOP_ALLOCATE_0_ADDR (WF_PLE_TOP_BASE + 0xA0) /* 00A0 */ +#define WF_PLE_TOP_ALLOCATE_1_ADDR (WF_PLE_TOP_BASE + 0xA4) /* 00A4 */ +#define WF_PLE_TOP_ALLOCATE_2_ADDR (WF_PLE_TOP_BASE + 0xA8) /* 00A8 */ +#define WF_PLE_TOP_QUEUE_EMPTY_ADDR (WF_PLE_TOP_BASE + 0xB0) /* 00B0 */ +#define WF_PLE_TOP_FREEPG_START_END_ADDR (WF_PLE_TOP_BASE + 0xc0) /* 00C0 */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR (WF_PLE_TOP_BASE + 0xc4)/* 00C4 */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR (WF_PLE_TOP_BASE + 0xd8) /* 00D8 */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR (WF_PLE_TOP_BASE + 0xdc) /* 00DC */ +#define WF_PLE_TOP_TO_N9_INT_ADDR (WF_PLE_TOP_BASE + 0xf0) /* 00F0 */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR (WF_PLE_TOP_BASE + 0xf4)/* 00F4 */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR (WF_PLE_TOP_BASE + 0xf8) /* 00F8 */ +#define WF_PLE_TOP_FREEPG_CNT_ADDR (WF_PLE_TOP_BASE + 0x100) /* 0100 */ +#define WF_PLE_TOP_FREEPG_HEAD_TAIL_ADDR (WF_PLE_TOP_BASE + 0x104) /* 0104 */ +#define WF_PLE_TOP_PG_HIF_GROUP_ADDR (WF_PLE_TOP_BASE + 0x110) /* 0110 */ +#define WF_PLE_TOP_HIF_PG_INFO_ADDR (WF_PLE_TOP_BASE + 0x114) /* 0114 */ +#define WF_PLE_TOP_PG_HIF_WMTXD_GROUP_ADDR (WF_PLE_TOP_BASE + 0x118) /* 0118 \ + */ +#define WF_PLE_TOP_HIF_WMTXD_PG_INFO_ADDR (WF_PLE_TOP_BASE + 0x11C)/* 011C */ +#define WF_PLE_TOP_PG_HIF_TXCMD_GROUP_ADDR (WF_PLE_TOP_BASE + 0x120) /* 0120 \ + */ +#define WF_PLE_TOP_HIF_TXCMD_PG_INFO_ADDR (WF_PLE_TOP_BASE + 0x124)/* 0124 */ +#define WF_PLE_TOP_TWT_TX_CTRL0_ADDR (WF_PLE_TOP_BASE + 0x130) /* 0130 */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR (WF_PLE_TOP_BASE + 0x140) /* 0140 */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_1_ADDR (WF_PLE_TOP_BASE + 0x144) /* 0144 */ +#define WF_PLE_TOP_PG_CPU_GROUP_ADDR (WF_PLE_TOP_BASE + 0x150) /* 0150 */ +#define WF_PLE_TOP_CPU_PG_INFO_ADDR (WF_PLE_TOP_BASE + 0x154) /* 0154 */ +#define WF_PLE_TOP_PLE_LOG_0_ADDR (WF_PLE_TOP_BASE + 0x170) /* 0170 */ +#define WF_PLE_TOP_PLE_LOG_1_ADDR (WF_PLE_TOP_BASE + 0x174) /* 0174 */ +#define WF_PLE_TOP_PLE_LOG_2_ADDR (WF_PLE_TOP_BASE + 0x178) /* 0178 */ +#define WF_PLE_TOP_PLE_LOG_3_ADDR (WF_PLE_TOP_BASE + 0x17c) /* 017C */ +#define WF_PLE_TOP_WMMAC_PGCNT_0_ADDR (WF_PLE_TOP_BASE + 0x180) /* 0180 */ +#define WF_PLE_TOP_WMMAC_PGCNT_1_ADDR (WF_PLE_TOP_BASE + 0x184) /* 0184 */ +#define WF_PLE_TOP_WMMAC_PGCNT_2_ADDR (WF_PLE_TOP_BASE + 0x188) /* 0188 */ +#define WF_PLE_TOP_WMMAC_PGCNT_3_ADDR (WF_PLE_TOP_BASE + 0x18c) /* 018C */ +#define WF_PLE_TOP_WMMAC_PGCNT_4_ADDR (WF_PLE_TOP_BASE + 0x190) /* 0190 */ +#define WF_PLE_TOP_WMMAC_PGCNT_5_ADDR (WF_PLE_TOP_BASE + 0x194) /* 0194 */ +#define WF_PLE_TOP_WMMAC_PGCNT_6_ADDR (WF_PLE_TOP_BASE + 0x198) /* 0198 */ +#define WF_PLE_TOP_WMMAC_PGCNT_7_ADDR (WF_PLE_TOP_BASE + 0x19c) /* 019C */ +#define WF_PLE_TOP_RL_BUF_CTRL_0_ADDR (WF_PLE_TOP_BASE + 0x1A0) /* 01A0 */ +#define WF_PLE_TOP_RL_BUF_CTRL_1_ADDR (WF_PLE_TOP_BASE + 0x1A4) /* 01A4 */ +#define WF_PLE_TOP_FL_QUE_CTRL_0_ADDR (WF_PLE_TOP_BASE + 0x1B0) /* 01B0 */ +#define WF_PLE_TOP_FL_QUE_CTRL_1_ADDR (WF_PLE_TOP_BASE + 0x1B4) /* 01B4 */ +#define WF_PLE_TOP_FL_QUE_CTRL_2_ADDR (WF_PLE_TOP_BASE + 0x1B8) /* 01B8 */ +#define WF_PLE_TOP_FL_QUE_CTRL_3_ADDR (WF_PLE_TOP_BASE + 0x1BC) /* 01BC */ +#define WF_PLE_TOP_PL_QUE_CTRL_0_ADDR (WF_PLE_TOP_BASE + 0x1C0) /* 01C0 */ +#define WF_PLE_TOP_PLE_DELAY_TX_CTRL_ADDR (WF_PLE_TOP_BASE + 0x1d0)/* 01D0 */ +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_ADDR \ +(WF_PLE_TOP_BASE + 0x1d4) /* 01D4 */ +#define WF_PLE_TOP_MACTX_LENGTH_LIMIT_ADDR (WF_PLE_TOP_BASE + 0x1ec) /* 01EC \ + */ +#define WF_PLE_TOP_HIF_ENQ_PKT_NUM_ADDR (WF_PLE_TOP_BASE + 0x1f0) /* 01F0 */ +#define WF_PLE_TOP_CPU_ENQ_PKT_NUM_ADDR (WF_PLE_TOP_BASE + 0x1f4) /* 01F4 */ +#define WF_PLE_TOP_RLS_MSDU_PKT_NUM_ADDR (WF_PLE_TOP_BASE + 0x1f8) /* 01F8 */ +#define WF_PLE_TOP_HOST_REPORT_NUM_ADDR (WF_PLE_TOP_BASE + 0x1fc) /* 01FC */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR (WF_PLE_TOP_BASE + 0x220) /* 0220 */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_ADDR (WF_PLE_TOP_BASE + 0x224) /* 0224 */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR \ +(WF_PLE_TOP_BASE + 0x228) /* 0228 */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR \ +(WF_PLE_TOP_BASE + 0x22c) /* 022C */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR (WF_PLE_TOP_BASE + 0x230) /* 0230 */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR (WF_PLE_TOP_BASE + 0x234) /* 0234 */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR (WF_PLE_TOP_BASE + 0x238) /* 0238\ + */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR \ +(WF_PLE_TOP_BASE + 0x23c) /* 023C */ +#define WF_PLE_TOP_UMAC_DBG_CTRL_ADDR (WF_PLE_TOP_BASE + 0x240) /* 0240 */ +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_ADDR (WF_PLE_TOP_BASE + 0x244)/* 0244\ + */ +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_ADDR (WF_PLE_TOP_BASE + 0x248)/* 0248\ + */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_ADDR (WF_PLE_TOP_BASE + 0x24C) /* 024C */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR (WF_PLE_TOP_BASE + 0x250) /* 0250 */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_ADDR (WF_PLE_TOP_BASE + 0x258)/* 0258\ + */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR (WF_PLE_TOP_BASE + 0x25C) /* 025C */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL9_ADDR (WF_PLE_TOP_BASE + 0x260)/* 0260\ + */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL10_ADDR (WF_PLE_TOP_BASE + 0x264) /* 0264\ + */ +#define WF_PLE_TOP_FUNC_ACT_CNT_0_ADDR (WF_PLE_TOP_BASE + 0x280) /* 0280 */ +#define WF_PLE_TOP_FUNC_ACT_CNT_1_ADDR (WF_PLE_TOP_BASE + 0x284) /* 0284 */ +#define WF_PLE_TOP_PORT_SER_CTRL_ADDR (WF_PLE_TOP_BASE + 0x2A0) /* 02A0 */ +#define WF_PLE_TOP_MACTX_SER_CTRL_ADDR (WF_PLE_TOP_BASE + 0x2A4) /* 02A4 */ +#define WF_PLE_TOP_DRR_SER_CTRL_ADDR (WF_PLE_TOP_BASE + 0x2A8) /* 02A8 */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL5_ADDR (WF_PLE_TOP_BASE + 0x2c0)/* 02C0\ + */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL6_ADDR (WF_PLE_TOP_BASE + 0x2c4)/* 02C4\ + */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL7_ADDR (WF_PLE_TOP_BASE + 0x2c8)/* 02C8\ + */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL8_ADDR (WF_PLE_TOP_BASE + 0x2cc)/* 02CC\ + */ +#define WF_PLE_TOP_SRAM_MBIST_BACKGROUND_ADDR \ +(WF_PLE_TOP_BASE + 0x2d0) /* 02D0 */ +#define WF_PLE_TOP_SRAM_MBIST_BSEL_ADDR (WF_PLE_TOP_BASE + 0x2d4) /* 02D4 */ +#define WF_PLE_TOP_SRAM_MBIST_DONE_ADDR (WF_PLE_TOP_BASE + 0x2d8) /* 02D8 */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR (WF_PLE_TOP_BASE + 0x2dc) /* 02DC */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR (WF_PLE_TOP_BASE + 0x2e0) /* 02E0 */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL1_ADDR (WF_PLE_TOP_BASE + 0x2e4) /* 02E4 \ + */ +#define WF_PLE_TOP_BSS_DBDC_CTRL_ADDR (WF_PLE_TOP_BASE + 0x2ec) /* 02EC */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL2_ADDR (WF_PLE_TOP_BASE + 0x2f0) /* 02F0 \ + */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL3_ADDR (WF_PLE_TOP_BASE + 0x2f4) /* 02F4 \ + */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL4_ADDR (WF_PLE_TOP_BASE + 0x2f8) /* 02F8 \ + */ +#define WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_ADDR (WF_PLE_TOP_BASE + 0x2fc) /* 02FC \ + */ +#define WF_PLE_TOP_PREDL_CTRL_ADDR (WF_PLE_TOP_BASE + 0x300) /* 0300 */ +#define WF_PLE_TOP_PREDL_CTRL1_ADDR (WF_PLE_TOP_BASE + 0x304) /* 0304 */ +#define WF_PLE_TOP_PREDL_BN0_LEN0_ADDR (WF_PLE_TOP_BASE + 0x330) /* 0330 */ +#define WF_PLE_TOP_PREDL_BN0_LEN1_ADDR (WF_PLE_TOP_BASE + 0x334) /* 0334 */ +#define WF_PLE_TOP_PREDL_BN1_LEN0_ADDR (WF_PLE_TOP_BASE + 0x338) /* 0338 */ +#define WF_PLE_TOP_PREDL_BN1_LEN1_ADDR (WF_PLE_TOP_BASE + 0x33c) /* 033C */ +#define WF_PLE_TOP_DRR_TABLE_WDATA0_ADDR (WF_PLE_TOP_BASE + 0x340) /* 0340 */ +#define WF_PLE_TOP_DRR_TABLE_WDATA1_ADDR (WF_PLE_TOP_BASE + 0x344) /* 0344 */ +#define WF_PLE_TOP_DRR_TABLE_WDATA2_ADDR (WF_PLE_TOP_BASE + 0x348) /* 0348 */ +#define WF_PLE_TOP_DRR_TABLE_WDATA3_ADDR (WF_PLE_TOP_BASE + 0x34c) /* 034C */ +#define WF_PLE_TOP_DRR_TABLE_RDATA0_ADDR (WF_PLE_TOP_BASE + 0x350) /* 0350 */ +#define WF_PLE_TOP_DRR_TABLE_RDATA1_ADDR (WF_PLE_TOP_BASE + 0x354) /* 0354 */ +#define WF_PLE_TOP_DRR_TABLE_RDATA2_ADDR (WF_PLE_TOP_BASE + 0x358) /* 0358 */ +#define WF_PLE_TOP_DRR_TABLE_RDATA3_ADDR (WF_PLE_TOP_BASE + 0x35c) /* 035C */ +#define WF_PLE_TOP_ERLY_TRM_CTRL0_ADDR (WF_PLE_TOP_BASE + 0x360) /* 0360 */ +#define WF_PLE_TOP_ERLY_TRM_CTRL1_ADDR (WF_PLE_TOP_BASE + 0x364) /* 0364 */ +#define WF_PLE_TOP_VOW_CONTROL_ADDR (WF_PLE_TOP_BASE + 0x370) /* 0370 */ +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_ADDR (WF_PLE_TOP_BASE + 0x374) /* 0374 */ +#define WF_PLE_TOP_CHECK_BW_TIME_TOKEN__ADDR \ +(WF_PLE_TOP_BASE + 0x378) /* 0378 */ +#define WF_PLE_TOP_CHECK_BW_LENGTH_TOKEN__ADDR \ +(WF_PLE_TOP_BASE + 0x37c) /* 037C */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_ADDR \ +(WF_PLE_TOP_BASE + 0x380) /* 0380 */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_ADDR \ +(WF_PLE_TOP_BASE + 0x384) /* 0384 */ +#define WF_PLE_TOP_DRR_TABLE_CTRL_ADDR (WF_PLE_TOP_BASE + 0x388) /* 0388 */ +#define WF_PLE_TOP_VOW_CTRL1_ADDR (WF_PLE_TOP_BASE + 0x38C) /* 038C */ +#define WF_PLE_TOP_DRR_CHNL_EMPTY_ADDR (WF_PLE_TOP_BASE + 0x390) /* 0390 */ +#define WF_PLE_TOP_DRR_SPL_CTRL_ADDR (WF_PLE_TOP_BASE + 0x394) /* 0394 */ +#define WF_PLE_TOP_DRR_SPL_CTRL_1_ADDR (WF_PLE_TOP_BASE + 0x398) /* 0398 */ +#define WF_PLE_TOP_VOW_DBG_SEL_ADDR (WF_PLE_TOP_BASE + 0x3A0) /* 03A0 */ +#define WF_PLE_TOP_AIRTIME_DBG_INFO0_ADDR (WF_PLE_TOP_BASE + 0x3A4) /* 03A4 */ +#define WF_PLE_TOP_AIRTIME_DBG_INFO1_ADDR (WF_PLE_TOP_BASE + 0x3A8) /* 03A8 */ +#define WF_PLE_TOP_BW_DBG_INFO_ADDR (WF_PLE_TOP_BASE + 0x3AC) /* 03AC */ +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING0_ADDR \ +(WF_PLE_TOP_BASE + 0x3B0) /* 03B0 */ +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING1_ADDR \ +(WF_PLE_TOP_BASE + 0x3B4) /* 03B4 */ +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING2_ADDR \ +(WF_PLE_TOP_BASE + 0x3B8) /* 03B8 */ +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING3_ADDR \ +(WF_PLE_TOP_BASE + 0x3bc) /* 03BC */ +#define WF_PLE_TOP_DRR_SW_CTRL_ADDR (WF_PLE_TOP_BASE + 0x3C8) /* 03C8 */ +#define WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_ADDR (WF_PLE_TOP_BASE + 0x3CC) /* 03CC\ + */ +#define WF_PLE_TOP_STATION_PAUSE0_ADDR (WF_PLE_TOP_BASE + 0x400) /* 0400 */ +#define WF_PLE_TOP_STATION_PAUSE1_ADDR (WF_PLE_TOP_BASE + 0x404) /* 0404 */ +#define WF_PLE_TOP_STATION_PAUSE2_ADDR (WF_PLE_TOP_BASE + 0x408) /* 0408 */ +#define WF_PLE_TOP_STATION_PAUSE3_ADDR (WF_PLE_TOP_BASE + 0x40c) /* 040C */ +#define WF_PLE_TOP_STATION_PAUSE4_ADDR (WF_PLE_TOP_BASE + 0x410) /* 0410 */ +#define WF_PLE_TOP_STATION_PAUSE5_ADDR (WF_PLE_TOP_BASE + 0x414) /* 0414 */ +#define WF_PLE_TOP_STATION_PAUSE6_ADDR (WF_PLE_TOP_BASE + 0x418) /* 0418 */ +#define WF_PLE_TOP_STATION_PAUSE7_ADDR (WF_PLE_TOP_BASE + 0x41c) /* 041C */ +#define WF_PLE_TOP_STATION_PAUSE8_ADDR (WF_PLE_TOP_BASE + 0x420) /* 0420 */ +#define WF_PLE_TOP_DIS_STA_MAP0_ADDR (WF_PLE_TOP_BASE + 0x440) /* 0440 */ +#define WF_PLE_TOP_DIS_STA_MAP1_ADDR (WF_PLE_TOP_BASE + 0x444) /* 0444 */ +#define WF_PLE_TOP_DIS_STA_MAP2_ADDR (WF_PLE_TOP_BASE + 0x448) /* 0448 */ +#define WF_PLE_TOP_DIS_STA_MAP3_ADDR (WF_PLE_TOP_BASE + 0x44c) /* 044C */ +#define WF_PLE_TOP_DIS_STA_MAP4_ADDR (WF_PLE_TOP_BASE + 0x450) /* 0450 */ +#define WF_PLE_TOP_DIS_STA_MAP5_ADDR (WF_PLE_TOP_BASE + 0x454) /* 0454 */ +#define WF_PLE_TOP_DIS_STA_MAP6_ADDR (WF_PLE_TOP_BASE + 0x458) /* 0458 */ +#define WF_PLE_TOP_DIS_STA_MAP7_ADDR (WF_PLE_TOP_BASE + 0x45c) /* 045C */ +#define WF_PLE_TOP_DIS_STA_MAP8_ADDR (WF_PLE_TOP_BASE + 0x460) /* 0460 */ +#define WF_PLE_TOP_STATION_REDIR0_ADDR (WF_PLE_TOP_BASE + 0x480) /* 0480 */ +#define WF_PLE_TOP_STATION_REDIR1_ADDR (WF_PLE_TOP_BASE + 0x484) /* 0484 */ +#define WF_PLE_TOP_STATION_REDIR2_ADDR (WF_PLE_TOP_BASE + 0x488) /* 0488 */ +#define WF_PLE_TOP_STATION_REDIR3_ADDR (WF_PLE_TOP_BASE + 0x48c) /* 048C */ +#define WF_PLE_TOP_STATION_REDIR4_ADDR (WF_PLE_TOP_BASE + 0x490) /* 0490 */ +#define WF_PLE_TOP_STATION_REDIR5_ADDR (WF_PLE_TOP_BASE + 0x494) /* 0494 */ +#define WF_PLE_TOP_STATION_REDIR6_ADDR (WF_PLE_TOP_BASE + 0x498) /* 0498 */ +#define WF_PLE_TOP_STATION_REDIR7_ADDR (WF_PLE_TOP_BASE + 0x49c) /* 049C */ +#define WF_PLE_TOP_STATION_REDIR8_ADDR (WF_PLE_TOP_BASE + 0x4a0) /* 04A0 */ +#define WF_PLE_TOP_TWT_STA_MAP0_ADDR (WF_PLE_TOP_BASE + 0x4c0) /* 04C0 */ +#define WF_PLE_TOP_TWT_STA_MAP1_ADDR (WF_PLE_TOP_BASE + 0x4c4) /* 04C4 */ +#define WF_PLE_TOP_TWT_STA_MAP2_ADDR (WF_PLE_TOP_BASE + 0x4c8) /* 04C8 */ +#define WF_PLE_TOP_TWT_STA_MAP3_ADDR (WF_PLE_TOP_BASE + 0x4cc) /* 04CC */ +#define WF_PLE_TOP_TWT_STA_MAP4_ADDR (WF_PLE_TOP_BASE + 0x4d0) /* 04D0 */ +#define WF_PLE_TOP_TWT_STA_MAP5_ADDR (WF_PLE_TOP_BASE + 0x4d4) /* 04D4 */ +#define WF_PLE_TOP_TWT_STA_MAP6_ADDR (WF_PLE_TOP_BASE + 0x4d8) /* 04D8 */ +#define WF_PLE_TOP_TWT_STA_MAP7_ADDR (WF_PLE_TOP_BASE + 0x4dc) /* 04DC */ +#define WF_PLE_TOP_TWT_STA_MAP8_ADDR (WF_PLE_TOP_BASE + 0x4e0) /* 04E0 */ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY0_ADDR (WF_PLE_TOP_BASE + 0x500) /* 0500 */ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY1_ADDR (WF_PLE_TOP_BASE + 0x504) /* 0504 */ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY2_ADDR (WF_PLE_TOP_BASE + 0x508) /* 0508 */ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY3_ADDR (WF_PLE_TOP_BASE + 0x50c) /* 050C */ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY4_ADDR (WF_PLE_TOP_BASE + 0x510) /* 0510 */ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY5_ADDR (WF_PLE_TOP_BASE + 0x514) /* 0514 */ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY6_ADDR (WF_PLE_TOP_BASE + 0x518) /* 0518 */ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY7_ADDR (WF_PLE_TOP_BASE + 0x51c) /* 051C */ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY8_ADDR (WF_PLE_TOP_BASE + 0x520) /* 0520 */ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY0_ADDR (WF_PLE_TOP_BASE + 0x540) /* 0540 */ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY1_ADDR (WF_PLE_TOP_BASE + 0x544) /* 0544 */ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY2_ADDR (WF_PLE_TOP_BASE + 0x548) /* 0548 */ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY3_ADDR (WF_PLE_TOP_BASE + 0x54c) /* 054C */ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY4_ADDR (WF_PLE_TOP_BASE + 0x550) /* 0550 */ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY5_ADDR (WF_PLE_TOP_BASE + 0x554) /* 0554 */ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY6_ADDR (WF_PLE_TOP_BASE + 0x558) /* 0558 */ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY7_ADDR (WF_PLE_TOP_BASE + 0x55c) /* 055C */ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY8_ADDR (WF_PLE_TOP_BASE + 0x560) /* 0560 */ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY0_ADDR (WF_PLE_TOP_BASE + 0x580) /* 0580 */ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY1_ADDR (WF_PLE_TOP_BASE + 0x584) /* 0584 */ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY2_ADDR (WF_PLE_TOP_BASE + 0x588) /* 0588 */ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY3_ADDR (WF_PLE_TOP_BASE + 0x58c) /* 058C */ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY4_ADDR (WF_PLE_TOP_BASE + 0x590) /* 0590 */ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY5_ADDR (WF_PLE_TOP_BASE + 0x594) /* 0594 */ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY6_ADDR (WF_PLE_TOP_BASE + 0x598) /* 0598 */ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY7_ADDR (WF_PLE_TOP_BASE + 0x59c) /* 059C */ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY8_ADDR (WF_PLE_TOP_BASE + 0x5a0) /* 05A0 */ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY0_ADDR (WF_PLE_TOP_BASE + 0x5c0) /* 05C0 */ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY1_ADDR (WF_PLE_TOP_BASE + 0x5c4) /* 05C4 */ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY2_ADDR (WF_PLE_TOP_BASE + 0x5c8) /* 05C8 */ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY3_ADDR (WF_PLE_TOP_BASE + 0x5cc) /* 05CC */ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY4_ADDR (WF_PLE_TOP_BASE + 0x5d0) /* 05D0 */ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY5_ADDR (WF_PLE_TOP_BASE + 0x5d4) /* 05D4 */ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY6_ADDR (WF_PLE_TOP_BASE + 0x5d8) /* 05D8 */ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY7_ADDR (WF_PLE_TOP_BASE + 0x5dc) /* 05DC */ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY8_ADDR (WF_PLE_TOP_BASE + 0x5e0) /* 05E0 */ +#define WF_PLE_TOP_DRR_TABLE_WDATA4_ADDR (WF_PLE_TOP_BASE + 0x680) /* 0680 */ +#define WF_PLE_TOP_DRR_TABLE_WDATA5_ADDR (WF_PLE_TOP_BASE + 0x684) /* 0684 */ +#define WF_PLE_TOP_DRR_TABLE_WDATA6_ADDR (WF_PLE_TOP_BASE + 0x688) /* 0688 */ +#define WF_PLE_TOP_DRR_TABLE_WDATA7_ADDR (WF_PLE_TOP_BASE + 0x68c) /* 068C */ +#define WF_PLE_TOP_DRR_TABLE_RDATA4_ADDR (WF_PLE_TOP_BASE + 0x690) /* 0690 */ +#define WF_PLE_TOP_DRR_TABLE_RDATA5_ADDR (WF_PLE_TOP_BASE + 0x694) /* 0694 */ +#define WF_PLE_TOP_DRR_TABLE_RDATA6_ADDR (WF_PLE_TOP_BASE + 0x698) /* 0698 */ +#define WF_PLE_TOP_DRR_TABLE_RDATA7_ADDR (WF_PLE_TOP_BASE + 0x69c) /* 069C */ +#define WF_PLE_TOP_TWT_STA_TABLE0_ADDR (WF_PLE_TOP_BASE + 0x6a0) /* 06A0 */ +#define WF_PLE_TOP_TWT_STA_TABLE1_ADDR (WF_PLE_TOP_BASE + 0x6a4) /* 06A4 */ +#define WF_PLE_TOP_TWT_STA_TABLE2_ADDR (WF_PLE_TOP_BASE + 0x6a8) /* 06A8 */ +#define WF_PLE_TOP_TWT_STA_TABLE3_ADDR (WF_PLE_TOP_BASE + 0x6ac) /* 06AC */ +#define WF_PLE_TOP_TWT_SW_CTRL_ADDR (WF_PLE_TOP_BASE + 0x6b0) /* 06B0 */ +#define WF_PLE_TOP_TWT_DBG_ADDR (WF_PLE_TOP_BASE + 0x6b4) /* 06B4 */ +#define WF_PLE_TOP_TWT_HW_SRCHCMD_FULL_ADDR (WF_PLE_TOP_BASE + 0x6b8) /* 06B8\ + */ +#define WF_PLE_TOP_SPL_GEN_CTRL_ADDR (WF_PLE_TOP_BASE + 0x700) /* 0700 */ +#define WF_PLE_TOP_AMSDU_GC_ADDR (WF_PLE_TOP_BASE + 0x1000) /* 1000 */ +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_ADDR \ +(WF_PLE_TOP_BASE + 0x1004) /* 1004 */ +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_1_ADDR \ +(WF_PLE_TOP_BASE + 0x1008) /* 1008 */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_ADDR \ +(WF_PLE_TOP_BASE + 0x1028) /* 1028 */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_ADDR \ +(WF_PLE_TOP_BASE + 0x102C) /* 102C */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_ADDR (WF_PLE_TOP_BASE + 0x10d0) /* 10D0 */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_ADDR (WF_PLE_TOP_BASE + 0x10d4) /* 10D4 */ +#define WF_PLE_TOP_AMSDU_PACK_1_MSDU_CNT_ADDR \ +(WF_PLE_TOP_BASE + 0x10e0) /* 10E0 */ +#define WF_PLE_TOP_AMSDU_PACK_2_MSDU_CNT_ADDR \ +(WF_PLE_TOP_BASE + 0x10e4) /* 10E4 */ +#define WF_PLE_TOP_AMSDU_PACK_3_MSDU_CNT_ADDR \ +(WF_PLE_TOP_BASE + 0x10e8) /* 10E8 */ +#define WF_PLE_TOP_AMSDU_PACK_4_MSDU_CNT_ADDR \ +(WF_PLE_TOP_BASE + 0x10ec) /* 10EC */ +#define WF_PLE_TOP_AMSDU_PACK_5_MSDU_CNT_ADDR \ +(WF_PLE_TOP_BASE + 0x10f0) /* 10F0 */ +#define WF_PLE_TOP_AMSDU_PACK_6_MSDU_CNT_ADDR \ +(WF_PLE_TOP_BASE + 0x10f4) /* 10F4 */ +#define WF_PLE_TOP_AMSDU_PACK_7_MSDU_CNT_ADDR \ +(WF_PLE_TOP_BASE + 0x10f8) /* 10F8 */ +#define WF_PLE_TOP_AMSDU_PACK_8_MSDU_CNT_ADDR \ +(WF_PLE_TOP_BASE + 0x10fc) /* 10FC */ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY0_ADDR \ +(WF_PLE_TOP_BASE + 0x1100) /* 1100 */ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY1_ADDR \ +(WF_PLE_TOP_BASE + 0x1104) /* 1104 */ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY2_ADDR \ +(WF_PLE_TOP_BASE + 0x1108) /* 1108 */ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY3_ADDR \ +(WF_PLE_TOP_BASE + 0x110C) /* 110C */ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY4_ADDR \ +(WF_PLE_TOP_BASE + 0x1110) /* 1110 */ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY5_ADDR \ +(WF_PLE_TOP_BASE + 0x1114) /* 1114 */ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY6_ADDR \ +(WF_PLE_TOP_BASE + 0x1118) /* 1118 */ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY7_ADDR \ +(WF_PLE_TOP_BASE + 0x111c) /* 111C */ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY8_ADDR \ +(WF_PLE_TOP_BASE + 0x1120) /* 1120 */ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY0_ADDR \ +(WF_PLE_TOP_BASE + 0x1140) /* 1140 */ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY1_ADDR \ +(WF_PLE_TOP_BASE + 0x1144) /* 1144 */ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY2_ADDR \ +(WF_PLE_TOP_BASE + 0x1148) /* 1148 */ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY3_ADDR \ +(WF_PLE_TOP_BASE + 0x114C) /* 114C */ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY4_ADDR \ +(WF_PLE_TOP_BASE + 0x1150) /* 1150 */ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY5_ADDR \ +(WF_PLE_TOP_BASE + 0x1154) /* 1154 */ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY6_ADDR \ +(WF_PLE_TOP_BASE + 0x1158) /* 1158 */ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY7_ADDR \ +(WF_PLE_TOP_BASE + 0x115c) /* 115C */ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY8_ADDR \ +(WF_PLE_TOP_BASE + 0x1160) /* 1160 */ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY0_ADDR \ +(WF_PLE_TOP_BASE + 0x1180) /* 1180 */ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY1_ADDR \ +(WF_PLE_TOP_BASE + 0x1184) /* 1184 */ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY2_ADDR \ +(WF_PLE_TOP_BASE + 0x1188) /* 1188 */ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY3_ADDR \ +(WF_PLE_TOP_BASE + 0x118C) /* 118C */ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY4_ADDR \ +(WF_PLE_TOP_BASE + 0x1190) /* 1190 */ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY5_ADDR \ +(WF_PLE_TOP_BASE + 0x1194) /* 1194 */ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY6_ADDR \ +(WF_PLE_TOP_BASE + 0x1198) /* 1198 */ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY7_ADDR \ +(WF_PLE_TOP_BASE + 0x119c) /* 119C */ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY8_ADDR \ +(WF_PLE_TOP_BASE + 0x11a0) /* 11A0 */ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY0_ADDR \ +(WF_PLE_TOP_BASE + 0x11C0) /* 11C0 */ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY1_ADDR \ +(WF_PLE_TOP_BASE + 0x11C4) /* 11C4 */ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY2_ADDR \ +(WF_PLE_TOP_BASE + 0x11C8) /* 11C8 */ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY3_ADDR \ +(WF_PLE_TOP_BASE + 0x11CC) /* 11CC */ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY4_ADDR \ +(WF_PLE_TOP_BASE + 0x11D0) /* 11D0 */ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY5_ADDR \ +(WF_PLE_TOP_BASE + 0x11D4) /* 11D4 */ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY6_ADDR \ +(WF_PLE_TOP_BASE + 0x11d8) /* 11D8 */ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY7_ADDR \ +(WF_PLE_TOP_BASE + 0x11dc) /* 11DC */ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY8_ADDR \ +(WF_PLE_TOP_BASE + 0x11e0) /* 11E0 */ +#define WF_PLE_TOP_CFG_DBDC_CTRL0_ADDR (WF_PLE_TOP_BASE + 0x2008) /* 2008 */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR \ +(WF_PLE_TOP_BASE + 0x2480) /* 2480 */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_ADDR \ +(WF_PLE_TOP_BASE + 0x2484) /* 2484 */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_2_ADDR \ +(WF_PLE_TOP_BASE + 0x2488) /* 2488 */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_3_ADDR \ +(WF_PLE_TOP_BASE + 0x248c) /* 248C */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_4_ADDR \ +(WF_PLE_TOP_BASE + 0x2490) /* 2490 */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_ADDR \ +(WF_PLE_TOP_BASE + 0x2494) /* 2494 */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_6_ADDR \ +(WF_PLE_TOP_BASE + 0x2498) /* 2498 */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_ADDR \ +(WF_PLE_TOP_BASE + 0x25c0) /* 25C0 */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_ADDR \ +(WF_PLE_TOP_BASE + 0x25c4) /* 25C4 */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_2_ADDR \ +(WF_PLE_TOP_BASE + 0x25c8) /* 25C8 */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_3_ADDR \ +(WF_PLE_TOP_BASE + 0x25cc) /* 25CC */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR \ +(WF_PLE_TOP_BASE + 0x25e0) /* 25E0 */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_ADDR \ +(WF_PLE_TOP_BASE + 0x25e4) /* 25E4 */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_2_ADDR \ +(WF_PLE_TOP_BASE + 0x25e8) /* 25E8 */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_3_ADDR \ +(WF_PLE_TOP_BASE + 0x25ec) /* 25EC */ +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_ADDR (WF_PLE_TOP_BASE + 0x3004)/* 3004\ + */ +#define WF_PLE_TOP_SYSRAM_MBIST_DEBUG_ADDR (WF_PLE_TOP_BASE + 0x3008) /* 3008\ + */ +#define WF_PLE_TOP_SYSRAM_MBIST_MODE_ADDR (WF_PLE_TOP_BASE + 0x300C)/* 300C\ + */ +#define WF_PLE_TOP_SYSRAM_MBIST_HOLDB_ADDR (WF_PLE_TOP_BASE + 0x3010) /* 3010\ + */ +#define WF_PLE_TOP_SYSRAM_MBIST_DONE_ADDR (WF_PLE_TOP_BASE + 0x3014)/* 3014\ + */ +#define WF_PLE_TOP_SYSRAM_MBIST_FAIL_ADDR (WF_PLE_TOP_BASE + 0x3018)/* 3018\ + */ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_TEST_ADDR \ +(WF_PLE_TOP_BASE + 0x301C) /* 301C */ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_INV_ADDR \ +(WF_PLE_TOP_BASE + 0x3020) /* 3020 */ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_W_ADDR \ +(WF_PLE_TOP_BASE + 0x3024) /* 3024 */ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_R_ADDR \ +(WF_PLE_TOP_BASE + 0x3028) /* 3028 */ +#define WF_PLE_TOP_SYSRAM_AWT_HDEN_ADDR (WF_PLE_TOP_BASE + 0x302C) /* 302C */ +#define WF_PLE_TOP_SYSRAM_DBG_SEL_ADDR (WF_PLE_TOP_BASE + 0x3030)/* 3030 */ +#define WF_PLE_TOP_SYSRAM_DELSEL_ADDR (WF_PLE_TOP_BASE + 0x3070) /* 3070 */ +#define WF_PLE_TOP_SYSRAM_DELSEL_1_ADDR (WF_PLE_TOP_BASE + 0x3074) /* 3074 */ +#define WF_PLE_TOP_SYSRAM_DELSEL_2_ADDR (WF_PLE_TOP_BASE + 0x3078) /* 3078 */ +#define WF_PLE_TOP_SYSRAM_DELSEL_3_ADDR (WF_PLE_TOP_BASE + 0x307C) /* 307C */ +#define WF_PLE_TOP_SYSRAM_OUTRAN_ERR_FLAG_ADDR \ +(WF_PLE_TOP_BASE + 0x3080) /* 3080 */ + +/* +* ---GC (0x820C0000 + 0x00)--- +* ALL_RESET[0] - (RW) Resets PLE logic and register +* LOGIC_RESET[1] - (RW) Resets PLE logic circuit +* INIT_DONE[2] - (RO) PLE control SRAM initialization +indicator +* UMAC_CFG_LOGIC_RESET[3] - (RW) Resets PF/MDP/SEC/UWTBL logic circuit +* RESERVED4[15..4] - (RO) Reserved bits +* SRAM_MBIST_G1_RESET[16] - (RW) Reset control of group 1 SRAM MBIST +* SRAM_MBIST_G2_RESET[17] - (RW) Reset control of group 2 SRAM MBIST +* DIS_PLE_DYN_CKG[18] - (RW) Disable control of wf_ple_top dynamic +* clock gating function +* RESERVED19[31..19] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_GC_DIS_PLE_DYN_CKG_ADDR WF_PLE_TOP_GC_ADDR +#define WF_PLE_TOP_GC_DIS_PLE_DYN_CKG_MASK 0x00040000 /* DIS_PLE_DYN_CKG[18] \ + */ +#define WF_PLE_TOP_GC_DIS_PLE_DYN_CKG_SHFT 18 +#define WF_PLE_TOP_GC_SRAM_MBIST_G2_RESET_ADDR WF_PLE_TOP_GC_ADDR +#define WF_PLE_TOP_GC_SRAM_MBIST_G2_RESET_MASK \ +0x00020000 /* SRAM_MBIST_G2_RESET[17] */ +#define WF_PLE_TOP_GC_SRAM_MBIST_G2_RESET_SHFT 17 +#define WF_PLE_TOP_GC_SRAM_MBIST_G1_RESET_ADDR WF_PLE_TOP_GC_ADDR +#define WF_PLE_TOP_GC_SRAM_MBIST_G1_RESET_MASK \ +0x00010000 /* SRAM_MBIST_G1_RESET[16] */ +#define WF_PLE_TOP_GC_SRAM_MBIST_G1_RESET_SHFT 16 +#define WF_PLE_TOP_GC_UMAC_CFG_LOGIC_RESET_ADDR WF_PLE_TOP_GC_ADDR +#define WF_PLE_TOP_GC_UMAC_CFG_LOGIC_RESET_MASK \ +0x00000008 /* UMAC_CFG_LOGIC_RESET[3] */ +#define WF_PLE_TOP_GC_UMAC_CFG_LOGIC_RESET_SHFT 3 +#define WF_PLE_TOP_GC_INIT_DONE_ADDR WF_PLE_TOP_GC_ADDR +#define WF_PLE_TOP_GC_INIT_DONE_MASK 0x00000004 /* INIT_DONE[2] */ +#define WF_PLE_TOP_GC_INIT_DONE_SHFT 2 +#define WF_PLE_TOP_GC_LOGIC_RESET_ADDR WF_PLE_TOP_GC_ADDR +#define WF_PLE_TOP_GC_LOGIC_RESET_MASK 0x00000002 /* LOGIC_RESET[1] */ +#define WF_PLE_TOP_GC_LOGIC_RESET_SHFT 1 +#define WF_PLE_TOP_GC_ALL_RESET_ADDR WF_PLE_TOP_GC_ADDR +#define WF_PLE_TOP_GC_ALL_RESET_MASK 0x00000001 /* ALL_RESET[0] */ +#define WF_PLE_TOP_GC_ALL_RESET_SHFT 0 + +/* +* ---PBUF_CTRL (0x820C0000 + 0x14)--- +* TOTAL_PAGE_NUM[11..0] - (RW) Total page number +* Set the total page before release PLE logic +* reset, and must not be changed after release logic reset. +* RESERVED12[16..12] - (RO) Reserved bits +* PBUF_OFFSET[25..17] - (RW) Packet buffer offset +* Set up the buffer offset before releasing +* PLE logic reset; it should not be changed after logic reset is released. +* RESERVED26[30..26] - (RO) Reserved bits +* PAGE_SIZE_CFG[31] - (RW) Configures page size +* Set up the page size before releasing PLE +* logic reset; it should not be changed after logic reset is released. +*/ +#define WF_PLE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_ADDR WF_PLE_TOP_PBUF_CTRL_ADDR +#define WF_PLE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_MASK \ +0x80000000 /* PAGE_SIZE_CFG[31] */ +#define WF_PLE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_SHFT 31 +#define WF_PLE_TOP_PBUF_CTRL_PBUF_OFFSET_ADDR WF_PLE_TOP_PBUF_CTRL_ADDR +#define WF_PLE_TOP_PBUF_CTRL_PBUF_OFFSET_MASK \ +0x03FE0000 /* PBUF_OFFSET[25..17] */ +#define WF_PLE_TOP_PBUF_CTRL_PBUF_OFFSET_SHFT 17 +#define WF_PLE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_ADDR WF_PLE_TOP_PBUF_CTRL_ADDR +#define WF_PLE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_MASK \ +0x00000FFF /* TOTAL_PAGE_NUM[11..0] */ +#define WF_PLE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_SHFT 0 + +/* +* ---TIMEOUT_CTRL (0x820C0000 + 0x1c)--- +* RESERVED0[7..0] - (RO) Reserved bits +* HOST_REPORT_TO_CTRL[15..8] - (RW) HOST report timeout control register +* APB_WD_TO_CTRL[23..16] - (RW) APB pready watch dog timeout control +register +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TIMEOUT_CTRL_APB_WD_TO_CTRL_ADDR WF_PLE_TOP_TIMEOUT_CTRL_ADDR +#define WF_PLE_TOP_TIMEOUT_CTRL_APB_WD_TO_CTRL_MASK \ +0x00FF0000 /* APB_WD_TO_CTRL[23..16] */ +#define WF_PLE_TOP_TIMEOUT_CTRL_APB_WD_TO_CTRL_SHFT 16 +#define WF_PLE_TOP_TIMEOUT_CTRL_HOST_REPORT_TO_CTRL_ADDR \ +WF_PLE_TOP_TIMEOUT_CTRL_ADDR +#define WF_PLE_TOP_TIMEOUT_CTRL_HOST_REPORT_TO_CTRL_MASK \ +0x0000FF00 /* HOST_REPORT_TO_CTRL[15..8] */ +#define WF_PLE_TOP_TIMEOUT_CTRL_HOST_REPORT_TO_CTRL_SHFT 8 + +/* +* ---INT_N9_EN_MASK (0x820C0000 + 0x20)--- +* EN_CPU_Q0_NE[0] - (RW) Enable control of interrupt for CPU +* queue 0 not empty +* EN_CPU_Q1_NE[1] - (RW) Enable control of interrupt for CPU +* queue 1 not empty +* EN_CPU_Q2_NE[2] - (RW) Enable control of interrupt for CPU +* queue 2 not empty +* EN_CPU_Q3_NE[3] - (RW) Enable control of interrupt for CPU +* queue 3 not empty +* RESERVED4[15..4] - (RO) Reserved bits +* EN_TOGGLE_INT[16] - (RW) Enable control of interrupt for data +* toggle of N9 toggle register (0xf0) +* EN_SPL_CMD_FIFO_FULL_INT[17] - (RW) Enable control of interrupt for SPL CMD +* FIFO full +* EN_UMAC_SYSRAM_OUTRAN_ERROR_INT[18] - (RW) Enable control of interrupt for +* UMAC SYSRAM out range error +* RESERVED19[19] - (RO) Reserved bits +* EN_AC_NONEMPTY_INT[20] - (RW) Enable control of AC queue empty fail +interrupt +* EN_AC_EMPTY_INT[21] - (RW) Enable control of AC queue empty raise +interrupt +* EN_AC_ENQ_LMAC_INT[22] - (RW) Enable control of AC enqueue interrupt +* RESERVED23[23] - (RO) Reserved bits +* EN_DBDC0_NONEMPTY_INT[24] - (RW) Enable control of DBDC0 queue empty fail +interrupt +* EN_DBDC0_EMPTY_INT[25] - (RW) Enable control of DBDC0 queue empty +* raise interrupt +* EN_DBDC0_ENQ_LMAC_INT[26] - (RW) Enable control of DBDC0 enqueue +interrupt +* RESERVED27[27] - (RO) Reserved bits +* EN_DBDC1_NONEMPTY_INT[28] - (RW) Enable control of DBDC1 queue empty fail +interrupt +* EN_DBDC1_EMPTY_INT[29] - (RW) Enable control of DBDC1 queue empty +* raise interrupt +* EN_DBDC1_ENQ_LMAC_INT[30] - (RW) Enable control of DBDC1 enqueue +interrupt +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_ENQ_LMAC_INT_ADDR \ +WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_ENQ_LMAC_INT_MASK \ +0x40000000 /* EN_DBDC1_ENQ_LMAC_INT[30] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_ENQ_LMAC_INT_SHFT 30 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_EMPTY_INT_ADDR \ +WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_EMPTY_INT_MASK \ +0x20000000 /* EN_DBDC1_EMPTY_INT[29] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_EMPTY_INT_SHFT 29 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_NONEMPTY_INT_ADDR \ +WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_NONEMPTY_INT_MASK \ +0x10000000 /* EN_DBDC1_NONEMPTY_INT[28] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_NONEMPTY_INT_SHFT 28 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_ENQ_LMAC_INT_ADDR \ +WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_ENQ_LMAC_INT_MASK \ +0x04000000 /* EN_DBDC0_ENQ_LMAC_INT[26] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_ENQ_LMAC_INT_SHFT 26 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_EMPTY_INT_ADDR \ +WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_EMPTY_INT_MASK \ +0x02000000 /* EN_DBDC0_EMPTY_INT[25] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_EMPTY_INT_SHFT 25 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_NONEMPTY_INT_ADDR \ +WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_NONEMPTY_INT_MASK \ +0x01000000 /* EN_DBDC0_NONEMPTY_INT[24] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_NONEMPTY_INT_SHFT 24 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_ENQ_LMAC_INT_ADDR \ +WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_ENQ_LMAC_INT_MASK \ +0x00400000 /* EN_AC_ENQ_LMAC_INT[22] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_ENQ_LMAC_INT_SHFT 22 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_EMPTY_INT_ADDR \ +WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_EMPTY_INT_MASK \ +0x00200000 /* EN_AC_EMPTY_INT[21] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_EMPTY_INT_SHFT 21 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_NONEMPTY_INT_ADDR \ +WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_NONEMPTY_INT_MASK \ +0x00100000 /* EN_AC_NONEMPTY_INT[20] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_NONEMPTY_INT_SHFT 20 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_UMAC_SYSRAM_OUTRAN_ERROR_INT_ADDR \ +WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_UMAC_SYSRAM_OUTRAN_ERROR_INT_MASK \ +0x00040000 /* EN_UMAC_SYSRAM_OUTRAN_ERROR_INT[18] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_UMAC_SYSRAM_OUTRAN_ERROR_INT_SHFT 18 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_SPL_CMD_FIFO_FULL_INT_ADDR \ +WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_SPL_CMD_FIFO_FULL_INT_MASK \ +0x00020000 /* EN_SPL_CMD_FIFO_FULL_INT[17] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_SPL_CMD_FIFO_FULL_INT_SHFT 17 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_TOGGLE_INT_ADDR \ +WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_TOGGLE_INT_MASK \ +0x00010000 /* EN_TOGGLE_INT[16] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_TOGGLE_INT_SHFT 16 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q3_NE_ADDR \ +WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q3_NE_MASK \ +0x00000008 /* EN_CPU_Q3_NE[3] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q3_NE_SHFT 3 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q2_NE_ADDR \ +WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q2_NE_MASK \ +0x00000004 /* EN_CPU_Q2_NE[2] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q2_NE_SHFT 2 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q1_NE_ADDR \ +WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q1_NE_MASK \ +0x00000002 /* EN_CPU_Q1_NE[1] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q1_NE_SHFT 1 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q0_NE_ADDR \ +WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q0_NE_MASK \ +0x00000001 /* EN_CPU_Q0_NE[0] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q0_NE_SHFT 0 + +/* +* ---INT_N9_STS (0x820C0000 + 0x24)--- +* CPU_Q0_NE[0] - (W1C) CPU queue 0 not empty interrupt status +* CPU_Q1_NE[1] - (W1C) CPU queue 1 not empty interrupt status +* CPU_Q2_NE[2] - (W1C) CPU queue 2 not empty interrupt status +* CPU_Q3_NE[3] - (W1C) CPU queue 3 not empty interrupt status +* RESERVED4[12..4] - (RO) Reserved bits +* ERROR_INT[13] - (RO) Error condition interrupt status, define +* by 0x28 +* ERROR_INT_1[14] - (RO) Error condition interrupt status 1, +* define by 0xd8 +* AMSDU_ERROR_INT[15] - (RO) HW AMSDU Error condition interrupt +* status, define by 0x1028 +* DATA_TOGGLE[16] - (W1C) Interrupt status of data toggle of N9 +* toggle register (0xf0) +* SPL_CMD_FIFO_FULL[17] - (W1C) Interrupt status of SPL CMD FIFO full +* UMAC_SYSRAM_OUTRAN_ERROR_INT[18] - (W1C) Interrupt status of UMAC SYSRAM out +* range error +* RESERVED19[19] - (RO) Reserved bits +* AC_NONEMPTY_INT[20] - (W1C) AC queue empty fail interrupt status +* AC_EMPTY_INT[21] - (W1C) AC queue empty raise interrupt status +* AC_ENQ_LMAC_INT[22] - (W1C) AC enqueue interrupt status +* RESERVED23[23] - (RO) Reserved bits +* DBDC0_NONEMPTY_INT[24] - (W1C) DBDC0 queue empty fail interrupt status +* DBDC0_EMPTY_INT[25] - (W1C) DBDC0 queue empty raise interrupt +status +* DBDC0_ENQ_LMAC_INT[26] - (W1C) DBDC0 enqueue interrupt status +* RESERVED27[27] - (RO) Reserved bits +* DBDC1_NONEMPTY_INT[28] - (W1C) DBDC1 queue empty fail interrupt status +* DBDC1_EMPTY_INT[29] - (W1C) DBDC1 queue empty raise interrupt +status +* DBDC1_ENQ_LMAC_INT[30] - (W1C) DBDC1 enqueue interrupt status +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_INT_N9_STS_DBDC1_ENQ_LMAC_INT_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_DBDC1_ENQ_LMAC_INT_MASK \ +0x40000000 /* DBDC1_ENQ_LMAC_INT[30] */ +#define WF_PLE_TOP_INT_N9_STS_DBDC1_ENQ_LMAC_INT_SHFT 30 +#define WF_PLE_TOP_INT_N9_STS_DBDC1_EMPTY_INT_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_DBDC1_EMPTY_INT_MASK \ +0x20000000 /* DBDC1_EMPTY_INT[29] */ +#define WF_PLE_TOP_INT_N9_STS_DBDC1_EMPTY_INT_SHFT 29 +#define WF_PLE_TOP_INT_N9_STS_DBDC1_NONEMPTY_INT_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_DBDC1_NONEMPTY_INT_MASK \ +0x10000000 /* DBDC1_NONEMPTY_INT[28] */ +#define WF_PLE_TOP_INT_N9_STS_DBDC1_NONEMPTY_INT_SHFT 28 +#define WF_PLE_TOP_INT_N9_STS_DBDC0_ENQ_LMAC_INT_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_DBDC0_ENQ_LMAC_INT_MASK \ +0x04000000 /* DBDC0_ENQ_LMAC_INT[26] */ +#define WF_PLE_TOP_INT_N9_STS_DBDC0_ENQ_LMAC_INT_SHFT 26 +#define WF_PLE_TOP_INT_N9_STS_DBDC0_EMPTY_INT_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_DBDC0_EMPTY_INT_MASK \ +0x02000000 /* DBDC0_EMPTY_INT[25] */ +#define WF_PLE_TOP_INT_N9_STS_DBDC0_EMPTY_INT_SHFT 25 +#define WF_PLE_TOP_INT_N9_STS_DBDC0_NONEMPTY_INT_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_DBDC0_NONEMPTY_INT_MASK \ +0x01000000 /* DBDC0_NONEMPTY_INT[24] */ +#define WF_PLE_TOP_INT_N9_STS_DBDC0_NONEMPTY_INT_SHFT 24 +#define WF_PLE_TOP_INT_N9_STS_AC_ENQ_LMAC_INT_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_AC_ENQ_LMAC_INT_MASK \ +0x00400000 /* AC_ENQ_LMAC_INT[22] */ +#define WF_PLE_TOP_INT_N9_STS_AC_ENQ_LMAC_INT_SHFT 22 +#define WF_PLE_TOP_INT_N9_STS_AC_EMPTY_INT_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_AC_EMPTY_INT_MASK \ +0x00200000 /* AC_EMPTY_INT[21] */ +#define WF_PLE_TOP_INT_N9_STS_AC_EMPTY_INT_SHFT 21 +#define WF_PLE_TOP_INT_N9_STS_AC_NONEMPTY_INT_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_AC_NONEMPTY_INT_MASK \ +0x00100000 /* AC_NONEMPTY_INT[20] */ +#define WF_PLE_TOP_INT_N9_STS_AC_NONEMPTY_INT_SHFT 20 +#define WF_PLE_TOP_INT_N9_STS_UMAC_SYSRAM_OUTRAN_ERROR_INT_ADDR \ +WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_UMAC_SYSRAM_OUTRAN_ERROR_INT_MASK \ +0x00040000 /* UMAC_SYSRAM_OUTRAN_ERROR_INT[18] */ +#define WF_PLE_TOP_INT_N9_STS_UMAC_SYSRAM_OUTRAN_ERROR_INT_SHFT 18 +#define WF_PLE_TOP_INT_N9_STS_SPL_CMD_FIFO_FULL_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_SPL_CMD_FIFO_FULL_MASK \ +0x00020000 /* SPL_CMD_FIFO_FULL[17] */ +#define WF_PLE_TOP_INT_N9_STS_SPL_CMD_FIFO_FULL_SHFT 17 +#define WF_PLE_TOP_INT_N9_STS_DATA_TOGGLE_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_DATA_TOGGLE_MASK 0x00010000 /* DATA_TOGGLE[16] \ + */ +#define WF_PLE_TOP_INT_N9_STS_DATA_TOGGLE_SHFT 16 +#define WF_PLE_TOP_INT_N9_STS_AMSDU_ERROR_INT_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_AMSDU_ERROR_INT_MASK \ +0x00008000 /* AMSDU_ERROR_INT[15] */ +#define WF_PLE_TOP_INT_N9_STS_AMSDU_ERROR_INT_SHFT 15 +#define WF_PLE_TOP_INT_N9_STS_ERROR_INT_1_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_ERROR_INT_1_MASK 0x00004000 /* ERROR_INT_1[14] \ + */ +#define WF_PLE_TOP_INT_N9_STS_ERROR_INT_1_SHFT 14 +#define WF_PLE_TOP_INT_N9_STS_ERROR_INT_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_ERROR_INT_MASK 0x00002000 /* ERROR_INT[13] */ +#define WF_PLE_TOP_INT_N9_STS_ERROR_INT_SHFT 13 +#define WF_PLE_TOP_INT_N9_STS_CPU_Q3_NE_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_CPU_Q3_NE_MASK 0x00000008 /* CPU_Q3_NE[3] */ +#define WF_PLE_TOP_INT_N9_STS_CPU_Q3_NE_SHFT 3 +#define WF_PLE_TOP_INT_N9_STS_CPU_Q2_NE_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_CPU_Q2_NE_MASK 0x00000004 /* CPU_Q2_NE[2] */ +#define WF_PLE_TOP_INT_N9_STS_CPU_Q2_NE_SHFT 2 +#define WF_PLE_TOP_INT_N9_STS_CPU_Q1_NE_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_CPU_Q1_NE_MASK 0x00000002 /* CPU_Q1_NE[1] */ +#define WF_PLE_TOP_INT_N9_STS_CPU_Q1_NE_SHFT 1 +#define WF_PLE_TOP_INT_N9_STS_CPU_Q0_NE_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_CPU_Q0_NE_MASK 0x00000001 /* CPU_Q0_NE[0] */ +#define WF_PLE_TOP_INT_N9_STS_CPU_Q0_NE_SHFT 0 + +/* +* ---INT_N9_ERR_STS (0x820C0000 + 0x28)--- +* Q_CMD_ERR_P0[0] - (W1C) Queue command error interrupt status of +* port 0. Avoid unclear error flag, please clear flag when logic reset. +* Q_CMD_ERR_P1[1] - (W1C) Queue command error interrupt status of +* port 1. Avoid unclear error flag, please clear flag when logic reset. +* Q_CMD_ERR_P2[2] - (W1C) Queue command error interrupt status of +* port 2. Avoid unclear error flag, please clear flag when logic reset. +* PAGE_UDF_P0[3] - (W1C) Page underflow interrupt status of port +* 0. Avoid unclear error flag, please clear flag when logic reset. +* PAGE_UDF_P1[4] - (W1C) Page underflow interrupt status of port +* 1. Avoid unclear error flag, please clear flag when logic reset. +* PAGE_UDF_P2[5] - (W1C) Page underflow interrupt status of port +* 2. Avoid unclear error flag, please clear flag when logic reset. +* DOUBLE_RLS_ERR[6] - (W1C) Double release error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* MDP_D_OPER_ERR[7] - (W1C) MDP data operation error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* MDP_HANG_ERR[8] - (W1C) MDP FSM Hang error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* RESERVED9[9] - (RO) Reserved bits +* DATA_OPER_ERR_P0[10] - (W1C) Data operation error of port 0. Avoid +* unclear error flag, please clear flag when logic reset. +* DATA_OPER_ERR_P1[11] - (W1C) Data operation error of port 1. Avoid +* unclear error flag, please clear flag when logic reset. +* DATA_OPER_ERR_P2[12] - (W1C) Data operation error of port 2. Avoid +* unclear error flag, please clear flag when logic reset. +* FL_HANG_ERR[13] - (W1C) Frame link FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* PL_HANG_ERR[14] - (W1C) Page link FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* HIF_HANG_ERR[15] - (W1C) HIF port FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* CPU_HANG_ERR[16] - (W1C) CPU port FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* LMAC_HANG_ERR[17] - (W1C) LMAC port FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* FREE_HEAD_TAIL_ERR[18] - (W1C) Free head/tail error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* QSTRUCT_ERR[19] - (W1C) Queue struct data error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* BN0_MACTX_HANG_ERR[20] - (W1C) BN0 MACTX Ctrl FSM Hang error +* interrupt. Avoid unclear error flag, please clear flag when logic reset. +* BN1_MACTX_HANG_ERR[21] - (W1C) BN1 MACTX Ctrl FSM Hang error +* interrupt. Avoid unclear error flag, please clear flag when logic reset. +* BN0_TXCMD_HANG_ERR[22] - (W1C) BN0 TXCMD Ctrl FSM Hang error +* interrupt. Avoid unclear error flag, please clear flag when logic reset. +* BN1_TXCMD_HANG_ERR[23] - (W1C) BN1 TXCMD Ctrl FSM Hang error +* interrupt. Avoid unclear error flag, please clear flag when logic reset. +* DRR_SRCH_DBDC0_ERR[24] - (W1C) DRR DBDC0 sta serach error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* DRR_SRCH_DBDC1_ERR[25] - (W1C) DRR DBDC1 sta serach error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* DRR_FL_ERR[26] - (W1C) DRR forward link access error +* interrupt. Avoid unclear error flag, please clear flag when logic reset. +* DRR_BL_ERR[27] - (W1C) DRR backward link access error +* interrupt. Avoid unclear error flag, please clear flag when logic reset. +* DRR_RL_ERR[28] - (W1C) DRR relay link access error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* DRR_CHRG_STA_ERR[29] - (W1C) DRR charge wlanid error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* DRR_STA_WLANID_ERR[30] - (W1C) DRR wlanid error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* DRR_STA_WMMID_ERR[31] - (W1C) DRR wmmid error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +*/ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_STA_WMMID_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_STA_WMMID_ERR_MASK \ +0x80000000 /* DRR_STA_WMMID_ERR[31] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_STA_WMMID_ERR_SHFT 31 +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_STA_WLANID_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_STA_WLANID_ERR_MASK \ +0x40000000 /* DRR_STA_WLANID_ERR[30] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_STA_WLANID_ERR_SHFT 30 +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_CHRG_STA_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_CHRG_STA_ERR_MASK \ +0x20000000 /* DRR_CHRG_STA_ERR[29] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_CHRG_STA_ERR_SHFT 29 +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_RL_ERR_ADDR WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_RL_ERR_MASK \ +0x10000000 /* DRR_RL_ERR[28] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_RL_ERR_SHFT 28 +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_BL_ERR_ADDR WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_BL_ERR_MASK \ +0x08000000 /* DRR_BL_ERR[27] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_BL_ERR_SHFT 27 +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_FL_ERR_ADDR WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_FL_ERR_MASK \ +0x04000000 /* DRR_FL_ERR[26] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_FL_ERR_SHFT 26 +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_SRCH_DBDC1_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_SRCH_DBDC1_ERR_MASK \ +0x02000000 /* DRR_SRCH_DBDC1_ERR[25] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_SRCH_DBDC1_ERR_SHFT 25 +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_SRCH_DBDC0_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_SRCH_DBDC0_ERR_MASK \ +0x01000000 /* DRR_SRCH_DBDC0_ERR[24] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_SRCH_DBDC0_ERR_SHFT 24 +#define WF_PLE_TOP_INT_N9_ERR_STS_BN1_TXCMD_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_BN1_TXCMD_HANG_ERR_MASK \ +0x00800000 /* BN1_TXCMD_HANG_ERR[23] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_BN1_TXCMD_HANG_ERR_SHFT 23 +#define WF_PLE_TOP_INT_N9_ERR_STS_BN0_TXCMD_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_BN0_TXCMD_HANG_ERR_MASK \ +0x00400000 /* BN0_TXCMD_HANG_ERR[22] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_BN0_TXCMD_HANG_ERR_SHFT 22 +#define WF_PLE_TOP_INT_N9_ERR_STS_BN1_MACTX_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_BN1_MACTX_HANG_ERR_MASK \ +0x00200000 /* BN1_MACTX_HANG_ERR[21] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_BN1_MACTX_HANG_ERR_SHFT 21 +#define WF_PLE_TOP_INT_N9_ERR_STS_BN0_MACTX_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_BN0_MACTX_HANG_ERR_MASK \ +0x00100000 /* BN0_MACTX_HANG_ERR[20] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_BN0_MACTX_HANG_ERR_SHFT 20 +#define WF_PLE_TOP_INT_N9_ERR_STS_QSTRUCT_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_QSTRUCT_ERR_MASK \ +0x00080000 /* QSTRUCT_ERR[19] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_QSTRUCT_ERR_SHFT 19 +#define WF_PLE_TOP_INT_N9_ERR_STS_FREE_HEAD_TAIL_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_FREE_HEAD_TAIL_ERR_MASK \ +0x00040000 /* FREE_HEAD_TAIL_ERR[18] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_FREE_HEAD_TAIL_ERR_SHFT 18 +#define WF_PLE_TOP_INT_N9_ERR_STS_LMAC_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_LMAC_HANG_ERR_MASK \ +0x00020000 /* LMAC_HANG_ERR[17] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_LMAC_HANG_ERR_SHFT 17 +#define WF_PLE_TOP_INT_N9_ERR_STS_CPU_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_CPU_HANG_ERR_MASK \ +0x00010000 /* CPU_HANG_ERR[16] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_CPU_HANG_ERR_SHFT 16 +#define WF_PLE_TOP_INT_N9_ERR_STS_HIF_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_HIF_HANG_ERR_MASK \ +0x00008000 /* HIF_HANG_ERR[15] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_HIF_HANG_ERR_SHFT 15 +#define WF_PLE_TOP_INT_N9_ERR_STS_PL_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_PL_HANG_ERR_MASK \ +0x00004000 /* PL_HANG_ERR[14] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_PL_HANG_ERR_SHFT 14 +#define WF_PLE_TOP_INT_N9_ERR_STS_FL_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_FL_HANG_ERR_MASK \ +0x00002000 /* FL_HANG_ERR[13] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_FL_HANG_ERR_SHFT 13 +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P2_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P2_MASK \ +0x00001000 /* DATA_OPER_ERR_P2[12] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P2_SHFT 12 +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P1_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P1_MASK \ +0x00000800 /* DATA_OPER_ERR_P1[11] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P1_SHFT 11 +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P0_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P0_MASK \ +0x00000400 /* DATA_OPER_ERR_P0[10] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P0_SHFT 10 +#define WF_PLE_TOP_INT_N9_ERR_STS_MDP_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_MDP_HANG_ERR_MASK \ +0x00000100 /* MDP_HANG_ERR[8] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_MDP_HANG_ERR_SHFT 8 +#define WF_PLE_TOP_INT_N9_ERR_STS_MDP_D_OPER_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_MDP_D_OPER_ERR_MASK \ +0x00000080 /* MDP_D_OPER_ERR[7] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_MDP_D_OPER_ERR_SHFT 7 +#define WF_PLE_TOP_INT_N9_ERR_STS_DOUBLE_RLS_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DOUBLE_RLS_ERR_MASK \ +0x00000040 /* DOUBLE_RLS_ERR[6] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DOUBLE_RLS_ERR_SHFT 6 +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P2_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P2_MASK \ +0x00000020 /* PAGE_UDF_P2[5] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P2_SHFT 5 +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P1_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P1_MASK \ +0x00000010 /* PAGE_UDF_P1[4] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P1_SHFT 4 +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P0_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P0_MASK \ +0x00000008 /* PAGE_UDF_P0[3] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P0_SHFT 3 +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P2_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P2_MASK \ +0x00000004 /* Q_CMD_ERR_P2[2] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P2_SHFT 2 +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P1_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P1_MASK \ +0x00000002 /* Q_CMD_ERR_P1[1] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P1_SHFT 1 +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P0_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P0_MASK \ +0x00000001 /* Q_CMD_ERR_P0[0] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P0_SHFT 0 + +/* +* ---INT_N9_ERR_MASK (0x820C0000 + 0x2C)--- +* EN_Q_CMD_ERR_P0[0] - (RW) Enables queue command error interrupt +* status of port 0 +* EN_Q_CMD_ERR_P1[1] - (RW) Enables queue command error interrupt +* status of port 1 +* EN_Q_CMD_ERR_P2[2] - (RW) Enables queue command error interrupt +* status of port 2 +* EN_PAGE_UDF_P0[3] - (RW) Enables page underflow interrupt status +* of port 0 +* EN_PAGE_UDF_P1[4] - (RW) Enables page underflow interrupt status +* of port 1 +* EN_PAGE_UDF_P2[5] - (RW) Enables page underflow interrupt status +* of port 2 +* EN_DOUBLE_RLS_ERR[6] - (RW) Enable double release error interrupt. +* EN_MDP_D_OPER_ERR[7] - (RW) Enable MDP data operation error +interrupt. +* EN_MDP_HANG_ERR[8] - (RW) Enable MDP FSM hang error interrupt. +* RESERVED9[9] - (RO) Reserved bits +* EN_DATA_OPER_ERR_P0[10] - (RW) Enables data operation error of port 0 +* EN_DATA_OPER_ERR_P1[11] - (RW) Enables data operation error of port 1 +* EN_DATA_OPER_ERR_P2[12] - (RW) Enables data operation error of port 2 +* EN_FL_HANG_ERR[13] - (RW) Enables frame link FSM hang error +interrupt +* EN_PL_HANG_ERR[14] - (RW) Enables page link FSM hang error +interrupt +* EN_HIF_HANG_ERR[15] - (RW) Enables HIF port FSM hang error +interrupt +* EN_CPU_HANG_ERR[16] - (RW) Enables CPU port FSM hang error +interrupt +* EN_LMAC_HANG_ERR[17] - (RW) Enables LMAC port FSM hang error +interrupt +* EN_FREE_HEAD_TAIL_ERR[18] - (RW) Enable free head/tail error interrupt. +* EN_QSTRUCT_ERR[19] - (RW) Enable queue struct data error +interrupt. +* EN_BN0_MACTX_HANG_ERR[20] - (RW) Enable BN0 MACTX Ctrl FSM Hang error +interrupt. +* EN_BN1_MACTX_HANG_ERR[21] - (RW) Enable BN1 MACTX Ctrl FSM Hang error +interrupt. +* EN_BN0_TXCMD_HANG_ERR[22] - (RW) Enable BN0 TXCMD Ctrl FSM Hang error +interrupt. +* EN_BN1_TXCMD_HANG_ERR[23] - (RW) Enable BN1 TXCMD Ctrl FSM Hang error +interrupt. +* EN_DRR_SRCH_DBDC0_ERR[24] - (RW) Enable DRR DBDC0 sta search error +interrupt. +* EN_DRR_SRCH_DBDC1_ERR[25] - (RW) Enable DRR DBDC1 sta search error +interrupt. +* EN_DRR_FL_ERR[26] - (RW) Enable DRR forward link access error +interrupt. +* EN_DRR_BL_ERR[27] - (RW) Enable DRR backward link access error +interrupt. +* EN_DRR_RL_ERR[28] - (RW) Enable DRR relay link access error +interrupt. +* EN_DRR_CHRG_STA_ERR[29] - (RW) Enable DRR wlanid error when charge +interrupt. +* EN_DRR_STA_WLANID_ERR[30] - (RW) Enable DRR wlanid error when add/remove +* sta interrupt. +* EN_DRR_STA_WMMID_ERR[31] - (RW) Enable DRR wmmid error when add/remove +* sta interrupt. +*/ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_STA_WMMID_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_STA_WMMID_ERR_MASK \ +0x80000000 /* EN_DRR_STA_WMMID_ERR[31] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_STA_WMMID_ERR_SHFT 31 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_STA_WLANID_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_STA_WLANID_ERR_MASK \ +0x40000000 /* EN_DRR_STA_WLANID_ERR[30] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_STA_WLANID_ERR_SHFT 30 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_CHRG_STA_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_CHRG_STA_ERR_MASK \ +0x20000000 /* EN_DRR_CHRG_STA_ERR[29] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_CHRG_STA_ERR_SHFT 29 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_RL_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_RL_ERR_MASK \ +0x10000000 /* EN_DRR_RL_ERR[28] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_RL_ERR_SHFT 28 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_BL_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_BL_ERR_MASK \ +0x08000000 /* EN_DRR_BL_ERR[27] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_BL_ERR_SHFT 27 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_FL_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_FL_ERR_MASK \ +0x04000000 /* EN_DRR_FL_ERR[26] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_FL_ERR_SHFT 26 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_SRCH_DBDC1_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_SRCH_DBDC1_ERR_MASK \ +0x02000000 /* EN_DRR_SRCH_DBDC1_ERR[25] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_SRCH_DBDC1_ERR_SHFT 25 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_SRCH_DBDC0_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_SRCH_DBDC0_ERR_MASK \ +0x01000000 /* EN_DRR_SRCH_DBDC0_ERR[24] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_SRCH_DBDC0_ERR_SHFT 24 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN1_TXCMD_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN1_TXCMD_HANG_ERR_MASK \ +0x00800000 /* EN_BN1_TXCMD_HANG_ERR[23] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN1_TXCMD_HANG_ERR_SHFT 23 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN0_TXCMD_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN0_TXCMD_HANG_ERR_MASK \ +0x00400000 /* EN_BN0_TXCMD_HANG_ERR[22] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN0_TXCMD_HANG_ERR_SHFT 22 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN1_MACTX_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN1_MACTX_HANG_ERR_MASK \ +0x00200000 /* EN_BN1_MACTX_HANG_ERR[21] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN1_MACTX_HANG_ERR_SHFT 21 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN0_MACTX_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN0_MACTX_HANG_ERR_MASK \ +0x00100000 /* EN_BN0_MACTX_HANG_ERR[20] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN0_MACTX_HANG_ERR_SHFT 20 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_QSTRUCT_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_QSTRUCT_ERR_MASK \ +0x00080000 /* EN_QSTRUCT_ERR[19] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_QSTRUCT_ERR_SHFT 19 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_FREE_HEAD_TAIL_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_FREE_HEAD_TAIL_ERR_MASK \ +0x00040000 /* EN_FREE_HEAD_TAIL_ERR[18] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_FREE_HEAD_TAIL_ERR_SHFT 18 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_LMAC_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_LMAC_HANG_ERR_MASK \ +0x00020000 /* EN_LMAC_HANG_ERR[17] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_LMAC_HANG_ERR_SHFT 17 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_CPU_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_CPU_HANG_ERR_MASK \ +0x00010000 /* EN_CPU_HANG_ERR[16] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_CPU_HANG_ERR_SHFT 16 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_HIF_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_HIF_HANG_ERR_MASK \ +0x00008000 /* EN_HIF_HANG_ERR[15] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_HIF_HANG_ERR_SHFT 15 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PL_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PL_HANG_ERR_MASK \ +0x00004000 /* EN_PL_HANG_ERR[14] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PL_HANG_ERR_SHFT 14 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_FL_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_FL_HANG_ERR_MASK \ +0x00002000 /* EN_FL_HANG_ERR[13] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_FL_HANG_ERR_SHFT 13 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P2_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P2_MASK \ +0x00001000 /* EN_DATA_OPER_ERR_P2[12] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P2_SHFT 12 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P1_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P1_MASK \ +0x00000800 /* EN_DATA_OPER_ERR_P1[11] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P1_SHFT 11 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P0_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P0_MASK \ +0x00000400 /* EN_DATA_OPER_ERR_P0[10] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P0_SHFT 10 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_MDP_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_MDP_HANG_ERR_MASK \ +0x00000100 /* EN_MDP_HANG_ERR[8] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_MDP_HANG_ERR_SHFT 8 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_MDP_D_OPER_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_MDP_D_OPER_ERR_MASK \ +0x00000080 /* EN_MDP_D_OPER_ERR[7] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_MDP_D_OPER_ERR_SHFT 7 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DOUBLE_RLS_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DOUBLE_RLS_ERR_MASK \ +0x00000040 /* EN_DOUBLE_RLS_ERR[6] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DOUBLE_RLS_ERR_SHFT 6 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P2_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P2_MASK \ +0x00000020 /* EN_PAGE_UDF_P2[5] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P2_SHFT 5 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P1_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P1_MASK \ +0x00000010 /* EN_PAGE_UDF_P1[4] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P1_SHFT 4 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P0_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P0_MASK \ +0x00000008 /* EN_PAGE_UDF_P0[3] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P0_SHFT 3 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P2_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P2_MASK \ +0x00000004 /* EN_Q_CMD_ERR_P2[2] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P2_SHFT 2 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P1_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P1_MASK \ +0x00000002 /* EN_Q_CMD_ERR_P1[1] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P1_SHFT 1 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P0_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P0_MASK \ +0x00000001 /* EN_Q_CMD_ERR_P0[0] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P0_SHFT 0 + +/* +* ---HOST_REPORT0 (0x820C0000 + 0x30)--- +* RESERVED0[0] - (RO) Reserved bits +* DIS_HOST_RPT[1] - (RW) Disables host report function +* HOST_RPT_VER0_EN[2] - (RW) Enable control for host report roll back +* to Version 2(MT7915 E1 used). +* HOST_RPT_TX_LATENCY[3] - (RW) Enable host report TX latency +* WMCPU_MSDU_ID_NUM[5..4] - (RW) Configuration of WMCPU MSDU ID usage. +* RESERVED6[7..6] - (RO) Reserved bits +* HOST_RPT_PACK_TH[15..8] - (RW) The buffer threshold for packing host +* report. The buffer size less then the MSDU numbers of a MPDU, would let +MSDU_ID +lose. +* HOST_RPT_QID[22..16] - (RW) PSE Queue ID control for host report. +* HOST_RPT_PID[23] - (RW) PSE Port ID control for host report. +* WMCPU_RPT_QID[30..24] - (RW) PSE Queue ID control for WMCPU report. +* WMCPU_RPT_PID[31] - (RW) PSE Port ID control for WMCPU report. +*/ +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_RPT_PID_ADDR WF_PLE_TOP_HOST_REPORT0_ADDR +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_RPT_PID_MASK \ +0x80000000 /* WMCPU_RPT_PID[31] */ +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_RPT_PID_SHFT 31 +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_RPT_QID_ADDR WF_PLE_TOP_HOST_REPORT0_ADDR +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_RPT_QID_MASK \ +0x7F000000 /* WMCPU_RPT_QID[30..24] */ +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_RPT_QID_SHFT 24 +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_PID_ADDR WF_PLE_TOP_HOST_REPORT0_ADDR +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_PID_MASK \ +0x00800000 /* HOST_RPT_PID[23] */ +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_PID_SHFT 23 +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_QID_ADDR WF_PLE_TOP_HOST_REPORT0_ADDR +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_QID_MASK \ +0x007F0000 /* HOST_RPT_QID[22..16] */ +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_QID_SHFT 16 +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_PACK_TH_ADDR \ +WF_PLE_TOP_HOST_REPORT0_ADDR +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_PACK_TH_MASK \ +0x0000FF00 /* HOST_RPT_PACK_TH[15..8] */ +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_PACK_TH_SHFT 8 +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_MSDU_ID_NUM_ADDR \ +WF_PLE_TOP_HOST_REPORT0_ADDR +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_MSDU_ID_NUM_MASK \ +0x00000030 /* WMCPU_MSDU_ID_NUM[5..4] */ +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_MSDU_ID_NUM_SHFT 4 +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_TX_LATENCY_ADDR \ +WF_PLE_TOP_HOST_REPORT0_ADDR +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_TX_LATENCY_MASK \ +0x00000008 /* HOST_RPT_TX_LATENCY[3] */ +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_TX_LATENCY_SHFT 3 +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_VER0_EN_ADDR \ +WF_PLE_TOP_HOST_REPORT0_ADDR +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_VER0_EN_MASK \ +0x00000004 /* HOST_RPT_VER0_EN[2] */ +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_VER0_EN_SHFT 2 +#define WF_PLE_TOP_HOST_REPORT0_DIS_HOST_RPT_ADDR WF_PLE_TOP_HOST_REPORT0_ADDR +#define WF_PLE_TOP_HOST_REPORT0_DIS_HOST_RPT_MASK \ +0x00000002 /* DIS_HOST_RPT[1] */ +#define WF_PLE_TOP_HOST_REPORT0_DIS_HOST_RPT_SHFT 1 + +/* +* ---HOST_REPORT1 (0x820C0000 + 0x34)--- +* SPL_RPT_QID[6..0] - (RW) PSE Queue ID control for SPL report. +* SPL_RPT_PID[7] - (RW) PSE Port ID control for SPL report. +* MD_RPT_QID[14..8] - (RW) PSE Queue ID control for MD CPU host +report. +* MD_RPT_PID[15] - (RW) PSE Port ID control for MD CPU host +report. +* HOST_RPT_PG_SIZE[19..16] - (RW) Setting of host report used PSE page +size. +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_HOST_REPORT1_HOST_RPT_PG_SIZE_ADDR \ +WF_PLE_TOP_HOST_REPORT1_ADDR +#define WF_PLE_TOP_HOST_REPORT1_HOST_RPT_PG_SIZE_MASK \ +0x000F0000 /* HOST_RPT_PG_SIZE[19..16] */ +#define WF_PLE_TOP_HOST_REPORT1_HOST_RPT_PG_SIZE_SHFT 16 +#define WF_PLE_TOP_HOST_REPORT1_MD_RPT_PID_ADDR WF_PLE_TOP_HOST_REPORT1_ADDR +#define WF_PLE_TOP_HOST_REPORT1_MD_RPT_PID_MASK 0x00008000 /* MD_RPT_PID[15] \ + */ +#define WF_PLE_TOP_HOST_REPORT1_MD_RPT_PID_SHFT 15 +#define WF_PLE_TOP_HOST_REPORT1_MD_RPT_QID_ADDR WF_PLE_TOP_HOST_REPORT1_ADDR +#define WF_PLE_TOP_HOST_REPORT1_MD_RPT_QID_MASK \ +0x00007F00 /* MD_RPT_QID[14..8] */ +#define WF_PLE_TOP_HOST_REPORT1_MD_RPT_QID_SHFT 8 +#define WF_PLE_TOP_HOST_REPORT1_SPL_RPT_PID_ADDR WF_PLE_TOP_HOST_REPORT1_ADDR +#define WF_PLE_TOP_HOST_REPORT1_SPL_RPT_PID_MASK 0x00000080 /* SPL_RPT_PID[7]\ + */ +#define WF_PLE_TOP_HOST_REPORT1_SPL_RPT_PID_SHFT 7 +#define WF_PLE_TOP_HOST_REPORT1_SPL_RPT_QID_ADDR WF_PLE_TOP_HOST_REPORT1_ADDR +#define WF_PLE_TOP_HOST_REPORT1_SPL_RPT_QID_MASK \ +0x0000007F /* SPL_RPT_QID[6..0] */ +#define WF_PLE_TOP_HOST_REPORT1_SPL_RPT_QID_SHFT 0 + +/* +* ---HOST_REPORT2 (0x820C0000 + 0x38)--- +* BN1_HOST_RPT_QID[6..0] - (RW) PSE Queue ID control for BN1 Host +report. +* BN1_HOST_RPT_PID[7] - (RW) PSE Port ID control for BN1 Host report. +* BN1_MD_RPT_QID[14..8] - (RW) PSE Queue ID control for BN1 MD CPU host +report. +* BN1_MD_RPT_PID[15] - (RW) PSE Port ID control for BN1 MD CPU host +report. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_HOST_REPORT2_BN1_MD_RPT_PID_ADDR WF_PLE_TOP_HOST_REPORT2_ADDR +#define WF_PLE_TOP_HOST_REPORT2_BN1_MD_RPT_PID_MASK \ +0x00008000 /* BN1_MD_RPT_PID[15] */ +#define WF_PLE_TOP_HOST_REPORT2_BN1_MD_RPT_PID_SHFT 15 +#define WF_PLE_TOP_HOST_REPORT2_BN1_MD_RPT_QID_ADDR WF_PLE_TOP_HOST_REPORT2_ADDR +#define WF_PLE_TOP_HOST_REPORT2_BN1_MD_RPT_QID_MASK \ +0x00007F00 /* BN1_MD_RPT_QID[14..8] */ +#define WF_PLE_TOP_HOST_REPORT2_BN1_MD_RPT_QID_SHFT 8 +#define WF_PLE_TOP_HOST_REPORT2_BN1_HOST_RPT_PID_ADDR \ +WF_PLE_TOP_HOST_REPORT2_ADDR +#define WF_PLE_TOP_HOST_REPORT2_BN1_HOST_RPT_PID_MASK \ +0x00000080 /* BN1_HOST_RPT_PID[7] */ +#define WF_PLE_TOP_HOST_REPORT2_BN1_HOST_RPT_PID_SHFT 7 +#define WF_PLE_TOP_HOST_REPORT2_BN1_HOST_RPT_QID_ADDR \ +WF_PLE_TOP_HOST_REPORT2_ADDR +#define WF_PLE_TOP_HOST_REPORT2_BN1_HOST_RPT_QID_MASK \ +0x0000007F /* BN1_HOST_RPT_QID[6..0] */ +#define WF_PLE_TOP_HOST_REPORT2_BN1_HOST_RPT_QID_SHFT 0 + +/* +* ---BLK_MODE_RATE_LMT (0x820C0000 + 0x3c)--- +* BN0_MACTX_BLK_RATE_LMT[15..0] - (RW) TX Rate limitaion of CutThrough data +* block mode. The rate less then the limitation would turn on block mode. +* BN1_MACTX_BLK_RATE_LMT[31..16] - (RW) TX Rate limitaion of CutThrough data +* block mode. The rate less then the limitation would turn on block mode. +*/ +#define WF_PLE_TOP_BLK_MODE_RATE_LMT_BN1_MACTX_BLK_RATE_LMT_ADDR \ +WF_PLE_TOP_BLK_MODE_RATE_LMT_ADDR +#define WF_PLE_TOP_BLK_MODE_RATE_LMT_BN1_MACTX_BLK_RATE_LMT_MASK \ +0xFFFF0000 /* BN1_MACTX_BLK_RATE_LMT[31..16] */ +#define WF_PLE_TOP_BLK_MODE_RATE_LMT_BN1_MACTX_BLK_RATE_LMT_SHFT 16 +#define WF_PLE_TOP_BLK_MODE_RATE_LMT_BN0_MACTX_BLK_RATE_LMT_ADDR \ +WF_PLE_TOP_BLK_MODE_RATE_LMT_ADDR +#define WF_PLE_TOP_BLK_MODE_RATE_LMT_BN0_MACTX_BLK_RATE_LMT_MASK \ +0x0000FFFF /* BN0_MACTX_BLK_RATE_LMT[15..0] */ +#define WF_PLE_TOP_BLK_MODE_RATE_LMT_BN0_MACTX_BLK_RATE_LMT_SHFT 0 + +/* +* ---C_GET_FID_0 (0x820C0000 + 0x40)--- +* GET_SRC_WLANID[9..0] - (RW) Source WLAN ID for get frame ID. +* RESERVED10[11..10] - (RO) Reserved bits +* GET_SRC_TGID[12] - (RW) Source TX Group ID for get frame ID. +* RESERVED13[13] - (RO) Reserved bits +* GET_SRC_PID[15..14] - (RW) Source port ID for get frame ID. +* GET_FRAME_TYPE[19..16] - (RW) GET_SUB_TYPE +* RESERVED20[23..20] - (RO) Reserved bits +* GET_SRC_QID[30..24] - (RW) Source Queue ID for get frame ID. +* EXECUTE[31] - (A0) Executes command +*/ +#define WF_PLE_TOP_C_GET_FID_0_EXECUTE_ADDR WF_PLE_TOP_C_GET_FID_0_ADDR +#define WF_PLE_TOP_C_GET_FID_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_C_GET_FID_0_EXECUTE_SHFT 31 +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_QID_ADDR WF_PLE_TOP_C_GET_FID_0_ADDR +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_QID_MASK \ +0x7F000000 /* GET_SRC_QID[30..24] */ +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_QID_SHFT 24 +#define WF_PLE_TOP_C_GET_FID_0_GET_FRAME_TYPE_ADDR WF_PLE_TOP_C_GET_FID_0_ADDR +#define WF_PLE_TOP_C_GET_FID_0_GET_FRAME_TYPE_MASK \ +0x000F0000 /* GET_FRAME_TYPE[19..16] */ +#define WF_PLE_TOP_C_GET_FID_0_GET_FRAME_TYPE_SHFT 16 +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_PID_ADDR WF_PLE_TOP_C_GET_FID_0_ADDR +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_PID_MASK \ +0x0000C000 /* GET_SRC_PID[15..14] */ +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_PID_SHFT 14 +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_TGID_ADDR WF_PLE_TOP_C_GET_FID_0_ADDR +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_TGID_MASK \ +0x00001000 /* GET_SRC_TGID[12] */ +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_TGID_SHFT 12 +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_WLANID_ADDR WF_PLE_TOP_C_GET_FID_0_ADDR +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_WLANID_MASK \ +0x000003FF /* GET_SRC_WLANID[9..0] */ +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_WLANID_SHFT 0 + +/* +* ---C_GET_FID_1 (0x820C0000 + 0x44)--- +* GET_RETURN_FID[11..0] - (RO) Return frame ID +* RESERVED12[14..12] - (RO) Reserved bits +* END[15] - (RO) Return frame ID is end FID. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_C_GET_FID_1_END_ADDR WF_PLE_TOP_C_GET_FID_1_ADDR +#define WF_PLE_TOP_C_GET_FID_1_END_MASK 0x00008000 /* END[15] */ +#define WF_PLE_TOP_C_GET_FID_1_END_SHFT 15 +#define WF_PLE_TOP_C_GET_FID_1_GET_RETURN_FID_ADDR WF_PLE_TOP_C_GET_FID_1_ADDR +#define WF_PLE_TOP_C_GET_FID_1_GET_RETURN_FID_MASK \ +0x00000FFF /* GET_RETURN_FID[11..0] */ +#define WF_PLE_TOP_C_GET_FID_1_GET_RETURN_FID_SHFT 0 + +/* +* ---RELEASE_CTRL_0 (0x820C0000 + 0x50)--- +* NOR_RLS_QID[6..0] - (RW) Normal TX packet release DST QID +* RESERVED7[7] - (RO) Reserved bits +* NOR_RLS_PID[9..8] - (RW) Normal TX packet release DST PID +* RESERVED10[15..10] - (RO) Reserved bits +* DROP_RLS_QID[22..16] - (RW) Drop packet release DST QID +* RESERVED23[23] - (RO) Reserved bits +* DROP_RLS_PID[25..24] - (RW) Drop packet release DST PID +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_RELEASE_CTRL_0_DROP_RLS_PID_ADDR \ +WF_PLE_TOP_RELEASE_CTRL_0_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_0_DROP_RLS_PID_MASK \ +0x03000000 /* DROP_RLS_PID[25..24] */ +#define WF_PLE_TOP_RELEASE_CTRL_0_DROP_RLS_PID_SHFT 24 +#define WF_PLE_TOP_RELEASE_CTRL_0_DROP_RLS_QID_ADDR \ +WF_PLE_TOP_RELEASE_CTRL_0_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_0_DROP_RLS_QID_MASK \ +0x007F0000 /* DROP_RLS_QID[22..16] */ +#define WF_PLE_TOP_RELEASE_CTRL_0_DROP_RLS_QID_SHFT 16 +#define WF_PLE_TOP_RELEASE_CTRL_0_NOR_RLS_PID_ADDR \ +WF_PLE_TOP_RELEASE_CTRL_0_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_0_NOR_RLS_PID_MASK \ +0x00000300 /* NOR_RLS_PID[9..8] */ +#define WF_PLE_TOP_RELEASE_CTRL_0_NOR_RLS_PID_SHFT 8 +#define WF_PLE_TOP_RELEASE_CTRL_0_NOR_RLS_QID_ADDR \ +WF_PLE_TOP_RELEASE_CTRL_0_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_0_NOR_RLS_QID_MASK \ +0x0000007F /* NOR_RLS_QID[6..0] */ +#define WF_PLE_TOP_RELEASE_CTRL_0_NOR_RLS_QID_SHFT 0 + +/* +* ---RELEASE_CTRL_1 (0x820C0000 + 0x54)--- +* BCN0_RLS_QID[6..0] - (RW) Beacon 0 packet release DST QID +* RESERVED7[7] - (RO) Reserved bits +* BCN0_RLS_PID[9..8] - (RW) Beacon 0 packet release DST PID +* RESERVED10[15..10] - (RO) Reserved bits +* BCN1_RLS_QID[22..16] - (RW) Beacon 1 packet release DST QID +* RESERVED23[23] - (RO) Reserved bits +* BCN1_RLS_PID[25..24] - (RW) Beacon 1 packet release DST PID +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN1_RLS_PID_ADDR \ +WF_PLE_TOP_RELEASE_CTRL_1_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN1_RLS_PID_MASK \ +0x03000000 /* BCN1_RLS_PID[25..24] */ +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN1_RLS_PID_SHFT 24 +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN1_RLS_QID_ADDR \ +WF_PLE_TOP_RELEASE_CTRL_1_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN1_RLS_QID_MASK \ +0x007F0000 /* BCN1_RLS_QID[22..16] */ +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN1_RLS_QID_SHFT 16 +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN0_RLS_PID_ADDR \ +WF_PLE_TOP_RELEASE_CTRL_1_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN0_RLS_PID_MASK \ +0x00000300 /* BCN0_RLS_PID[9..8] */ +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN0_RLS_PID_SHFT 8 +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN0_RLS_QID_ADDR \ +WF_PLE_TOP_RELEASE_CTRL_1_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN0_RLS_QID_MASK \ +0x0000007F /* BCN0_RLS_QID[6..0] */ +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN0_RLS_QID_SHFT 0 + +/* +* ---RELEASE_CTRL_2 (0x820C0000 + 0x58)--- +* TXCMD0_RLS_QID[6..0] - (RW) TXCMD 0 packet release DST QID +* RESERVED7[7] - (RO) Reserved bits +* TXCMD0_RLS_PID[9..8] - (RW) TXCMD 0 packet release DST PID +* RESERVED10[15..10] - (RO) Reserved bits +* TXCMD1_RLS_QID[22..16] - (RW) TXCDM 1 packet release DST QID +* RESERVED23[23] - (RO) Reserved bits +* TXCMD1_RLS_PID[25..24] - (RW) TXCMD 1 packet release DST PID +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_RELEASE_CTRL_2_TXCMD1_RLS_PID_ADDR \ +WF_PLE_TOP_RELEASE_CTRL_2_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_2_TXCMD1_RLS_PID_MASK \ +0x03000000 /* TXCMD1_RLS_PID[25..24] */ +#define WF_PLE_TOP_RELEASE_CTRL_2_TXCMD1_RLS_PID_SHFT 24 +#define WF_PLE_TOP_RELEASE_CTRL_2_TXCMD1_RLS_QID_ADDR \ +WF_PLE_TOP_RELEASE_CTRL_2_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_2_TXCMD1_RLS_QID_MASK \ +0x007F0000 /* TXCMD1_RLS_QID[22..16] */ +#define WF_PLE_TOP_RELEASE_CTRL_2_TXCMD1_RLS_QID_SHFT 16 +#define WF_PLE_TOP_RELEASE_CTRL_2_TXCMD0_RLS_PID_ADDR \ +WF_PLE_TOP_RELEASE_CTRL_2_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_2_TXCMD0_RLS_PID_MASK \ +0x00000300 /* TXCMD0_RLS_PID[9..8] */ +#define WF_PLE_TOP_RELEASE_CTRL_2_TXCMD0_RLS_PID_SHFT 8 +#define WF_PLE_TOP_RELEASE_CTRL_2_TXCMD0_RLS_QID_ADDR \ +WF_PLE_TOP_RELEASE_CTRL_2_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_2_TXCMD0_RLS_QID_MASK \ +0x0000007F /* TXCMD0_RLS_QID[6..0] */ +#define WF_PLE_TOP_RELEASE_CTRL_2_TXCMD0_RLS_QID_SHFT 0 + +/* +* ---RELEASE_CTRL_3 (0x820C0000 + 0x5c)--- +* RLS_FREE_DONE_PG_SIZE[3..0] - (RW) Page size configuration of Free done +* event(host report). +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_RELEASE_CTRL_3_RLS_FREE_DONE_PG_SIZE_ADDR \ +WF_PLE_TOP_RELEASE_CTRL_3_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_3_RLS_FREE_DONE_PG_SIZE_MASK \ +0x0000000F /* RLS_FREE_DONE_PG_SIZE[3..0] */ +#define WF_PLE_TOP_RELEASE_CTRL_3_RLS_FREE_DONE_PG_SIZE_SHFT 0 + +/* +* ---C_EN_QUEUE_0 (0x820C0000 + 0x60)--- +* DST_WLANID[9..0] - (RW) Destination WLANID for enqueue +* RESERVED10[11..10] - (RO) Reserved bits +* DST_TGID[12] - (RW) Destination TX Group ID for enqueue +* RESERVED13[13] - (RO) Reserved bits +* DST_PID[15..14] - (RW) Destination port ID for enqueue +* SUB_TYPE[19..16] - (RW) Sub-type of enqueue command +* RESERVED20[22..20] - (RO) Reserved bits +* DELAY_ENQ[23] - (RW) Delay enqueue +* ENQ_DST_QID[30..24] - (RW) Destination queue ID for enqueue +* EXECUTE[31] - (A0) Executes command +*/ +#define WF_PLE_TOP_C_EN_QUEUE_0_EXECUTE_ADDR WF_PLE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_C_EN_QUEUE_0_EXECUTE_SHFT 31 +#define WF_PLE_TOP_C_EN_QUEUE_0_ENQ_DST_QID_ADDR WF_PLE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_0_ENQ_DST_QID_MASK \ +0x7F000000 /* ENQ_DST_QID[30..24] */ +#define WF_PLE_TOP_C_EN_QUEUE_0_ENQ_DST_QID_SHFT 24 +#define WF_PLE_TOP_C_EN_QUEUE_0_DELAY_ENQ_ADDR WF_PLE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_0_DELAY_ENQ_MASK 0x00800000 /* DELAY_ENQ[23] */ +#define WF_PLE_TOP_C_EN_QUEUE_0_DELAY_ENQ_SHFT 23 +#define WF_PLE_TOP_C_EN_QUEUE_0_SUB_TYPE_ADDR WF_PLE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_0_SUB_TYPE_MASK 0x000F0000 /* SUB_TYPE[19..16] \ + */ +#define WF_PLE_TOP_C_EN_QUEUE_0_SUB_TYPE_SHFT 16 +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_PID_ADDR WF_PLE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_PID_MASK 0x0000C000 /* DST_PID[15..14] */ +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_PID_SHFT 14 +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_TGID_ADDR WF_PLE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_TGID_MASK 0x00001000 /* DST_TGID[12] */ +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_TGID_SHFT 12 +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_WLANID_ADDR WF_PLE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_WLANID_MASK \ +0x000003FF /* DST_WLANID[9..0] */ +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_WLANID_SHFT 0 + +/* +* ---C_EN_QUEUE_1 (0x820C0000 + 0x64)--- +* CUR_LIST_FID_START[11..0] - (RW) Start frame ID of enqueue operation +* list, enqueue FID of enqueue operation +* RESERVED12[15..12] - (RO) Reserved bits +* CUR_LIST_FID_END[27..16] - (RW) End frame ID of enqueue operation list +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_END_ADDR \ +WF_PLE_TOP_C_EN_QUEUE_1_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_END_MASK \ +0x0FFF0000 /* CUR_LIST_FID_END[27..16] */ +#define WF_PLE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_END_SHFT 16 +#define WF_PLE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_START_ADDR \ +WF_PLE_TOP_C_EN_QUEUE_1_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_START_MASK \ +0x00000FFF /* CUR_LIST_FID_START[11..0] */ +#define WF_PLE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_START_SHFT 0 + +/* +* ---C_EN_QUEUE_2 (0x820C0000 + 0x68)--- +* TARGET_FID[11..0] - (RW) Target reference FID for enqueue +operation +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_C_EN_QUEUE_2_TARGET_FID_ADDR WF_PLE_TOP_C_EN_QUEUE_2_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_2_TARGET_FID_MASK \ +0x00000FFF /* TARGET_FID[11..0] */ +#define WF_PLE_TOP_C_EN_QUEUE_2_TARGET_FID_SHFT 0 + +/* +* ---C_DE_QUEUE_0 (0x820C0000 + 0x80)--- +* SRC_WLANID[9..0] - (RW) Source WLAN ID for dequeue command +* RESERVED10[11..10] - (RO) Reserved bits +* SRC_TGID[12] - (RW) Source TX Group ID for dequeue command +* RESERVED13[13] - (RO) Reserved bits +* SRC_PID[15..14] - (RW) Source port ID for dequeue command +* DEQ_SUB_TYPE[19..16] - (RW) Dequeue subtype of dequeue command +* ENQ_SUB_TYPE[22..20] - (RW) Enqueue subtype of enqueue command +* Only valid in Deq&Enq type. +* ENQ_VLD[23] - (RW) Deq&Enq command valid +* SRC_QID[30..24] - (RW) Source queue ID for dequeue command +* EXECUTE[31] - (A0) Executes dequeue command +*/ +#define WF_PLE_TOP_C_DE_QUEUE_0_EXECUTE_ADDR WF_PLE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_C_DE_QUEUE_0_EXECUTE_SHFT 31 +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_QID_ADDR WF_PLE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_QID_MASK 0x7F000000 /* SRC_QID[30..24] */ +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_QID_SHFT 24 +#define WF_PLE_TOP_C_DE_QUEUE_0_ENQ_VLD_ADDR WF_PLE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_0_ENQ_VLD_MASK 0x00800000 /* ENQ_VLD[23] */ +#define WF_PLE_TOP_C_DE_QUEUE_0_ENQ_VLD_SHFT 23 +#define WF_PLE_TOP_C_DE_QUEUE_0_ENQ_SUB_TYPE_ADDR WF_PLE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_0_ENQ_SUB_TYPE_MASK \ +0x00700000 /* ENQ_SUB_TYPE[22..20] */ +#define WF_PLE_TOP_C_DE_QUEUE_0_ENQ_SUB_TYPE_SHFT 20 +#define WF_PLE_TOP_C_DE_QUEUE_0_DEQ_SUB_TYPE_ADDR WF_PLE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_0_DEQ_SUB_TYPE_MASK \ +0x000F0000 /* DEQ_SUB_TYPE[19..16] */ +#define WF_PLE_TOP_C_DE_QUEUE_0_DEQ_SUB_TYPE_SHFT 16 +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_PID_ADDR WF_PLE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_PID_MASK 0x0000C000 /* SRC_PID[15..14] */ +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_PID_SHFT 14 +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_TGID_ADDR WF_PLE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_TGID_MASK 0x00001000 /* SRC_TGID[12] */ +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_TGID_SHFT 12 +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_WLANID_ADDR WF_PLE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_WLANID_MASK \ +0x000003FF /* SRC_WLANID[9..0] */ +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_WLANID_SHFT 0 + +/* +* ---C_DE_QUEUE_1 (0x820C0000 + 0x84)--- +* CUR_LIST_FID_START[11..0] - (RW) Start frame ID of dequeue operation +* list, enqueue start FID of enqueue operation +* Only valid in Deq&Enq type. +* RESERVED12[15..12] - (RO) Reserved bits +* CUR_LIST_FID_END[27..16] - (RW) End framd ID of dequeue operation list, +* enqueue end FID of enqueue operation +* Only valid in Deq&Enq type. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_END_ADDR \ +WF_PLE_TOP_C_DE_QUEUE_1_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_END_MASK \ +0x0FFF0000 /* CUR_LIST_FID_END[27..16] */ +#define WF_PLE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_END_SHFT 16 +#define WF_PLE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_START_ADDR \ +WF_PLE_TOP_C_DE_QUEUE_1_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_START_MASK \ +0x00000FFF /* CUR_LIST_FID_START[11..0] */ +#define WF_PLE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_START_SHFT 0 + +/* +* ---C_DE_QUEUE_2 (0x820C0000 + 0x88)--- +* DEQ_ENQ_DST_WLANID[9..0] - (RW) Destination WLAN ID for enqueue command +* Only valid in Deq&Enq type. +* RESERVED10[11..10] - (RO) Reserved bits +* DEQ_ENQ_DST_TGID[12] - (RW) Destination TX Group ID for enqueue +command +* Only valid in Deq&Enq type. +* RESERVED13[13] - (RO) Reserved bits +* DEQ_ENQ_DST_PID[15..14] - (RW) Destination port ID for enqueue command +* OInly valid in Deq&Enq type. +* RESERVED16[23..16] - (RO) Reserved bits +* DEQ_ENQ_DST_QID[30..24] - (RW) Destination queue ID for enqueue command +* Only valid in Deq&Enq type. +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_QID_ADDR \ +WF_PLE_TOP_C_DE_QUEUE_2_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_QID_MASK \ +0x7F000000 /* DEQ_ENQ_DST_QID[30..24] */ +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_QID_SHFT 24 +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_PID_ADDR \ +WF_PLE_TOP_C_DE_QUEUE_2_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_PID_MASK \ +0x0000C000 /* DEQ_ENQ_DST_PID[15..14] */ +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_PID_SHFT 14 +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_TGID_ADDR \ +WF_PLE_TOP_C_DE_QUEUE_2_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_TGID_MASK \ +0x00001000 /* DEQ_ENQ_DST_TGID[12] */ +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_TGID_SHFT 12 +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_WLANID_ADDR \ +WF_PLE_TOP_C_DE_QUEUE_2_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_WLANID_MASK \ +0x000003FF /* DEQ_ENQ_DST_WLANID[9..0] */ +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_WLANID_SHFT 0 + +/* +* ---C_DE_QUEUE_3 (0x820C0000 + 0x8c)--- +* DEQ_HEAD_FID[11..0] - (RO) Head FID got from dequeue command +* RESERVED12[14..12] - (RO) Reserved bits +* DEQ_EMPTY[15] - (RO) Queue empty after dequeue command is +executed +* DEQ_TAIL_FID[27..16] - (RO) Last FID got from dequeue command +* RESERVED28[30..28] - (RO) Reserved bits +* BUSY[31] - (RO) Dequeue execute busy +*/ +#define WF_PLE_TOP_C_DE_QUEUE_3_BUSY_ADDR WF_PLE_TOP_C_DE_QUEUE_3_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_3_BUSY_MASK 0x80000000 /* BUSY[31] */ +#define WF_PLE_TOP_C_DE_QUEUE_3_BUSY_SHFT 31 +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_TAIL_FID_ADDR WF_PLE_TOP_C_DE_QUEUE_3_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_TAIL_FID_MASK \ +0x0FFF0000 /* DEQ_TAIL_FID[27..16] */ +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_TAIL_FID_SHFT 16 +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_EMPTY_ADDR WF_PLE_TOP_C_DE_QUEUE_3_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_EMPTY_MASK 0x00008000 /* DEQ_EMPTY[15] */ +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_EMPTY_SHFT 15 +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_HEAD_FID_ADDR WF_PLE_TOP_C_DE_QUEUE_3_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_HEAD_FID_MASK \ +0x00000FFF /* DEQ_HEAD_FID[11..0] */ +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_HEAD_FID_SHFT 0 + +/* +* ---C_DE_QUEUE_4 (0x820C0000 + 0x90)--- +* DEQ_ENQ_REF_FID[11..0] - (RW) Reference frame ID for enqueue command +* Only valid in Deq&Enq type. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_C_DE_QUEUE_4_DEQ_ENQ_REF_FID_ADDR \ +WF_PLE_TOP_C_DE_QUEUE_4_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_4_DEQ_ENQ_REF_FID_MASK \ +0x00000FFF /* DEQ_ENQ_REF_FID[11..0] */ +#define WF_PLE_TOP_C_DE_QUEUE_4_DEQ_ENQ_REF_FID_SHFT 0 + +/* +* ---ALLOCATE_0 (0x820C0000 + 0xA0)--- +* ALLOCATE_FRAME_LENGTH[13..0] - (RW) Allocate frame length +* Unit: DW (4 bytes) +* RESERVED14[15..14] - (RO) Reserved bits +* ALLOCATE_QID[20..16] - (RW) QID used for allocate buffer +* RESERVED21[30..21] - (RO) Reserved bits +* EXECUTE[31] - (A0) Executes allocate buffer command +*/ +#define WF_PLE_TOP_ALLOCATE_0_EXECUTE_ADDR WF_PLE_TOP_ALLOCATE_0_ADDR +#define WF_PLE_TOP_ALLOCATE_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_ALLOCATE_0_EXECUTE_SHFT 31 +#define WF_PLE_TOP_ALLOCATE_0_ALLOCATE_QID_ADDR WF_PLE_TOP_ALLOCATE_0_ADDR +#define WF_PLE_TOP_ALLOCATE_0_ALLOCATE_QID_MASK \ +0x001F0000 /* ALLOCATE_QID[20..16] */ +#define WF_PLE_TOP_ALLOCATE_0_ALLOCATE_QID_SHFT 16 +#define WF_PLE_TOP_ALLOCATE_0_ALLOCATE_FRAME_LENGTH_ADDR \ +WF_PLE_TOP_ALLOCATE_0_ADDR +#define WF_PLE_TOP_ALLOCATE_0_ALLOCATE_FRAME_LENGTH_MASK \ +0x00003FFF /* ALLOCATE_FRAME_LENGTH[13..0] */ +#define WF_PLE_TOP_ALLOCATE_0_ALLOCATE_FRAME_LENGTH_SHFT 0 + +/* +* ---ALLOCATE_1 (0x820C0000 + 0xA4)--- +* ALLOCATE_FID[11..0] - (RO) Return frame ID for allocate buffer +command +* RESERVED12[30..12] - (RO) Reserved bits +* EXECUTE[31] - (RO) Execute status of allocate buffer +command +*/ +#define WF_PLE_TOP_ALLOCATE_1_EXECUTE_ADDR WF_PLE_TOP_ALLOCATE_1_ADDR +#define WF_PLE_TOP_ALLOCATE_1_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_ALLOCATE_1_EXECUTE_SHFT 31 +#define WF_PLE_TOP_ALLOCATE_1_ALLOCATE_FID_ADDR WF_PLE_TOP_ALLOCATE_1_ADDR +#define WF_PLE_TOP_ALLOCATE_1_ALLOCATE_FID_MASK \ +0x00000FFF /* ALLOCATE_FID[11..0] */ +#define WF_PLE_TOP_ALLOCATE_1_ALLOCATE_FID_SHFT 0 + +/* +* ---ALLOCATE_2 (0x820C0000 + 0xA8)--- +* CPU_TXBYTE_COUNT[15..0] - (RW) TX data byte count +* This value should be the same as the first +* two bytes of TXD in PLE. +* CPU_MSDU_ID0_bit15_8[23..16] - (RW) MSDU_ID0 Bit15-Bit8 +* This value should be the same as the +* DW8[15:8] of TXD in PLE. +* CPU_PKT_FT[25..24] - (RW) TXD's PKT_FT +* This value should be the same as the +* DW0[24:23] of TXD in PLE. +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_ALLOCATE_2_CPU_PKT_FT_ADDR WF_PLE_TOP_ALLOCATE_2_ADDR +#define WF_PLE_TOP_ALLOCATE_2_CPU_PKT_FT_MASK \ +0x03000000 /* CPU_PKT_FT[25..24] */ +#define WF_PLE_TOP_ALLOCATE_2_CPU_PKT_FT_SHFT 24 +#define WF_PLE_TOP_ALLOCATE_2_CPU_MSDU_ID0_bit15_8_ADDR \ +WF_PLE_TOP_ALLOCATE_2_ADDR +#define WF_PLE_TOP_ALLOCATE_2_CPU_MSDU_ID0_bit15_8_MASK \ +0x00FF0000 /* CPU_MSDU_ID0_bit15_8[23..16] */ +#define WF_PLE_TOP_ALLOCATE_2_CPU_MSDU_ID0_bit15_8_SHFT 16 +#define WF_PLE_TOP_ALLOCATE_2_CPU_TXBYTE_COUNT_ADDR WF_PLE_TOP_ALLOCATE_2_ADDR +#define WF_PLE_TOP_ALLOCATE_2_CPU_TXBYTE_COUNT_MASK \ +0x0000FFFF /* CPU_TXBYTE_COUNT[15..0] */ +#define WF_PLE_TOP_ALLOCATE_2_CPU_TXBYTE_COUNT_SHFT 0 + +/* +* ---QUEUE_EMPTY (0x820C0000 + 0xB0)--- +* CPU_Q0_EMPTY[0] - (RO) CPU queue 0 empty status +* CPU_Q1_EMPTY[1] - (RO) CPU queue 1 empty status +* CPU_Q2_EMPTY[2] - (RO) CPU queue 2 empty status +* CPU_Q3_EMPTY[3] - (RO) CPU queue 3 empty status +* RESERVED4[7..4] - (RO) Reserved bits +* ALTX_0_EMPTY[8] - (RO) ALTX queue 0 empty status +* BMC_0_EMPTY[9] - (RO) BMC queue 0 empty status +* BCN_0_EMPTY[10] - (RO) BCN queue 0 empty status +* PSMP_0_EMPTY[11] - (RO) PSMP queue 0 empty status +* ALTX_1_EMPTY[12] - (RO) ALTX queue 1 empty status +* BMC_1_EMPTY[13] - (RO) BMC queue 1 empty status +* BCN_1_EMPTY[14] - (RO) BCN queue 1 empty status +* PSMP_1_EMPTY[15] - (RO) PSMP queue 1 empty status +* NAF_EMPTY[16] - (RO) NAF queue empty status +* NBCN_EMPTY[17] - (RO) NBCN queue empty status +* RESERVED18[19..18] - (RO) Reserved bits +* FIX_FID_EMPTY[20] - (RO) FIX_FID queue empty status +* RESERVED21[23..21] - (RO) Reserved bits +* ALL_AC_EMPTY[24] - (RO) All AC queue empty status +* RESERVED25[29..25] - (RO) Reserved bits +* RLS2_Q_EMTPY[30] - (RO) Release 2 queue empty status +* RLS_Q_EMTPY[31] - (RO) Release queue empty status +*/ +#define WF_PLE_TOP_QUEUE_EMPTY_RLS_Q_EMTPY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_RLS_Q_EMTPY_MASK 0x80000000 /* RLS_Q_EMTPY[31]\ + */ +#define WF_PLE_TOP_QUEUE_EMPTY_RLS_Q_EMTPY_SHFT 31 +#define WF_PLE_TOP_QUEUE_EMPTY_RLS2_Q_EMTPY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_RLS2_Q_EMTPY_MASK \ +0x40000000 /* RLS2_Q_EMTPY[30] */ +#define WF_PLE_TOP_QUEUE_EMPTY_RLS2_Q_EMTPY_SHFT 30 +#define WF_PLE_TOP_QUEUE_EMPTY_ALL_AC_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_ALL_AC_EMPTY_MASK \ +0x01000000 /* ALL_AC_EMPTY[24] */ +#define WF_PLE_TOP_QUEUE_EMPTY_ALL_AC_EMPTY_SHFT 24 +#define WF_PLE_TOP_QUEUE_EMPTY_FIX_FID_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_FIX_FID_EMPTY_MASK \ +0x00100000 /* FIX_FID_EMPTY[20] */ +#define WF_PLE_TOP_QUEUE_EMPTY_FIX_FID_EMPTY_SHFT 20 +#define WF_PLE_TOP_QUEUE_EMPTY_NBCN_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_NBCN_EMPTY_MASK 0x00020000 /* NBCN_EMPTY[17] */ +#define WF_PLE_TOP_QUEUE_EMPTY_NBCN_EMPTY_SHFT 17 +#define WF_PLE_TOP_QUEUE_EMPTY_NAF_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_NAF_EMPTY_MASK 0x00010000 /* NAF_EMPTY[16] */ +#define WF_PLE_TOP_QUEUE_EMPTY_NAF_EMPTY_SHFT 16 +#define WF_PLE_TOP_QUEUE_EMPTY_PSMP_1_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_PSMP_1_EMPTY_MASK \ +0x00008000 /* PSMP_1_EMPTY[15] */ +#define WF_PLE_TOP_QUEUE_EMPTY_PSMP_1_EMPTY_SHFT 15 +#define WF_PLE_TOP_QUEUE_EMPTY_BCN_1_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_BCN_1_EMPTY_MASK 0x00004000 /* BCN_1_EMPTY[14]\ + */ +#define WF_PLE_TOP_QUEUE_EMPTY_BCN_1_EMPTY_SHFT 14 +#define WF_PLE_TOP_QUEUE_EMPTY_BMC_1_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_BMC_1_EMPTY_MASK 0x00002000 /* BMC_1_EMPTY[13]\ + */ +#define WF_PLE_TOP_QUEUE_EMPTY_BMC_1_EMPTY_SHFT 13 +#define WF_PLE_TOP_QUEUE_EMPTY_ALTX_1_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_ALTX_1_EMPTY_MASK \ +0x00001000 /* ALTX_1_EMPTY[12] */ +#define WF_PLE_TOP_QUEUE_EMPTY_ALTX_1_EMPTY_SHFT 12 +#define WF_PLE_TOP_QUEUE_EMPTY_PSMP_0_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_PSMP_0_EMPTY_MASK \ +0x00000800 /* PSMP_0_EMPTY[11] */ +#define WF_PLE_TOP_QUEUE_EMPTY_PSMP_0_EMPTY_SHFT 11 +#define WF_PLE_TOP_QUEUE_EMPTY_BCN_0_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_BCN_0_EMPTY_MASK 0x00000400 /* BCN_0_EMPTY[10]\ + */ +#define WF_PLE_TOP_QUEUE_EMPTY_BCN_0_EMPTY_SHFT 10 +#define WF_PLE_TOP_QUEUE_EMPTY_BMC_0_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_BMC_0_EMPTY_MASK 0x00000200 /* BMC_0_EMPTY[9] \ + */ +#define WF_PLE_TOP_QUEUE_EMPTY_BMC_0_EMPTY_SHFT 9 +#define WF_PLE_TOP_QUEUE_EMPTY_ALTX_0_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_ALTX_0_EMPTY_MASK \ +0x00000100 /* ALTX_0_EMPTY[8] */ +#define WF_PLE_TOP_QUEUE_EMPTY_ALTX_0_EMPTY_SHFT 8 +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q3_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q3_EMPTY_MASK \ +0x00000008 /* CPU_Q3_EMPTY[3] */ +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q3_EMPTY_SHFT 3 +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q2_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q2_EMPTY_MASK \ +0x00000004 /* CPU_Q2_EMPTY[2] */ +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q2_EMPTY_SHFT 2 +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q1_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q1_EMPTY_MASK \ +0x00000002 /* CPU_Q1_EMPTY[1] */ +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q1_EMPTY_SHFT 1 +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q0_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q0_EMPTY_MASK \ +0x00000001 /* CPU_Q0_EMPTY[0] */ +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q0_EMPTY_SHFT 0 + +/* +* ---FREEPG_START_END (0x820C0000 + 0xc0)--- +* FREEPG_START[11..0] - (RW) Start page for free page list +* Set start page before release PLE logic +* reset, and must not be changed after release logic reset. +* RESERVED12[15..12] - (RO) Reserved bits +* FREEPG_END[27..16] - (RW) End page for free page list +* Set end page before release PLE logic +* reset, and must not be changed after release logic reset. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FREEPG_START_END_FREEPG_END_ADDR \ +WF_PLE_TOP_FREEPG_START_END_ADDR +#define WF_PLE_TOP_FREEPG_START_END_FREEPG_END_MASK \ +0x0FFF0000 /* FREEPG_END[27..16] */ +#define WF_PLE_TOP_FREEPG_START_END_FREEPG_END_SHFT 16 +#define WF_PLE_TOP_FREEPG_START_END_FREEPG_START_ADDR \ +WF_PLE_TOP_FREEPG_START_END_ADDR +#define WF_PLE_TOP_FREEPG_START_END_FREEPG_START_MASK \ +0x00000FFF /* FREEPG_START[11..0] */ +#define WF_PLE_TOP_FREEPG_START_END_FREEPG_START_SHFT 0 + +/* +* ---PLE_MODULE_CKG_DIS (0x820C0000 + 0xc4)--- +* DIS_FL_DYN_CKG[0] - (RW) Disable control of PLE frame link module +* dynamic clock gating function +* DIS_PL_DYN_CKG[1] - (RW) Disable control of PLE page link module +* dynamic clock gating function +* DIS_CPU_PORT_DYN_CKG[2] - (RW) Disable control of PLE CPU port module +* dynamic clock gating function +* DIS_HIF_PORT_DYN_CKG[3] - (RW) Disable control of PLE HIF port module +* dynamic clock gating function +* DIS_WF_PORT_DYN_CKG[4] - (RW) Disable control of PLE LMAC module +* dynamic clock gating function +* DIS_RLS_DYN_CKG[5] - (RW) Disable control of PLE release module +* dynamic clock gating function +* DIS_RL_DYN_CKG[6] - (RW) Disable control of PLE relay information +* module dynamic clock gating function +* DIS_MACTX_DYN_CKG[7] - (RW) Disable control of PLE MACTX module +* dynamic clock gating function +* DIS_PSEPORT_DYN_CKG[8] - (RW) Disable control of PLE PSE port module +* dynamic clock gating function +* DIS_CSR_DYN_CKG[9] - (RW) Disable control of PLE CR module dynamic +* clock gating function +* DIS_CPU_WRAP_DYN_CKG[10] - (RW) Disable control of PLE CPU_WRAP module +* dynamic clock gating function +* DIS_DBG_DYN_CKG[11] - (RW) Disable control of PLE debug module +* dynamic clock gating function +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_DBG_DYN_CKG_ADDR \ +WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_DBG_DYN_CKG_MASK \ +0x00000800 /* DIS_DBG_DYN_CKG[11] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_DBG_DYN_CKG_SHFT 11 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CPU_WRAP_DYN_CKG_ADDR \ +WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CPU_WRAP_DYN_CKG_MASK \ +0x00000400 /* DIS_CPU_WRAP_DYN_CKG[10] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CPU_WRAP_DYN_CKG_SHFT 10 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CSR_DYN_CKG_ADDR \ +WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CSR_DYN_CKG_MASK \ +0x00000200 /* DIS_CSR_DYN_CKG[9] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CSR_DYN_CKG_SHFT 9 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_PSEPORT_DYN_CKG_ADDR \ +WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_PSEPORT_DYN_CKG_MASK \ +0x00000100 /* DIS_PSEPORT_DYN_CKG[8] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_PSEPORT_DYN_CKG_SHFT 8 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_MACTX_DYN_CKG_ADDR \ +WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_MACTX_DYN_CKG_MASK \ +0x00000080 /* DIS_MACTX_DYN_CKG[7] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_MACTX_DYN_CKG_SHFT 7 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_RL_DYN_CKG_ADDR \ +WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_RL_DYN_CKG_MASK \ +0x00000040 /* DIS_RL_DYN_CKG[6] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_RL_DYN_CKG_SHFT 6 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_RLS_DYN_CKG_ADDR \ +WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_RLS_DYN_CKG_MASK \ +0x00000020 /* DIS_RLS_DYN_CKG[5] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_RLS_DYN_CKG_SHFT 5 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_WF_PORT_DYN_CKG_ADDR \ +WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_WF_PORT_DYN_CKG_MASK \ +0x00000010 /* DIS_WF_PORT_DYN_CKG[4] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_WF_PORT_DYN_CKG_SHFT 4 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_HIF_PORT_DYN_CKG_ADDR \ +WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_HIF_PORT_DYN_CKG_MASK \ +0x00000008 /* DIS_HIF_PORT_DYN_CKG[3] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_HIF_PORT_DYN_CKG_SHFT 3 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CPU_PORT_DYN_CKG_ADDR \ +WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CPU_PORT_DYN_CKG_MASK \ +0x00000004 /* DIS_CPU_PORT_DYN_CKG[2] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CPU_PORT_DYN_CKG_SHFT 2 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_PL_DYN_CKG_ADDR \ +WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_PL_DYN_CKG_MASK \ +0x00000002 /* DIS_PL_DYN_CKG[1] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_PL_DYN_CKG_SHFT 1 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_FL_DYN_CKG_ADDR \ +WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_FL_DYN_CKG_MASK \ +0x00000001 /* DIS_FL_DYN_CKG[0] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_FL_DYN_CKG_SHFT 0 + +/* +* ---INT_N9_ERR_STS_1 (0x820C0000 + 0xd8)--- +* BN0_MDP_TDP_HANG_ERR[0] - (W1C) BN0 MDP TDP FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* MDP_RDP_HANG_ERR[1] - (W1C) MDP RDP FSM hang error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* BN0_MDP_TIOC_HANG_ERR[2] - (W1C) BN0 MDP TIOC FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* BN0_MDP_RIOC_HANG_ERR[3] - (W1C) BN0 MDP RIOC FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* PF_HANG_ERR[4] - (W1C) PF FSM hang error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* SEC0_HANG_ERR[5] - (W1C) SEC 0 FSM hang error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* SEC1_HANG_ERR[6] - (W1C) SEC 1 FSM hang error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* BN1_MDP_TDP_HANG_ERR[7] - (W1C) BN1 MDP TDP FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* BN1_MDP_TIOC_HANG_ERR[8] - (W1C) BN1 MDP TIOC FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* BN1_MDP_RIOC_HANG_ERR[9] - (W1C) BN1 MDP RIOC FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* RESERVED10[11..10] - (RO) Reserved bits +* BN0_RPEDL_ARB_HANG_ERR[12] - (W1C) BN0 PREDL ARB hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* BN0_PREDL_TXCMD_HANG_ERR[13] - (W1C) BN0 PREDL TXCDM FSM hang error +* interrupt. Avoid unclear error flag, please clear flag when logic reset. +* BN1_RPEDL_ARB_HANG_ERR[14] - (W1C) BN1 PREDL ARB hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* BN1_PREDL_TXCMD_HANG_ERR[15] - (W1C) BN1 PREDL TXCDM FSM hang error +* interrupt. Avoid unclear error flag, please clear flag when logic reset. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_PREDL_TXCMD_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_PREDL_TXCMD_HANG_ERR_MASK \ +0x00008000 /* BN1_PREDL_TXCMD_HANG_ERR[15] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_PREDL_TXCMD_HANG_ERR_SHFT 15 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_RPEDL_ARB_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_RPEDL_ARB_HANG_ERR_MASK \ +0x00004000 /* BN1_RPEDL_ARB_HANG_ERR[14] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_RPEDL_ARB_HANG_ERR_SHFT 14 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_PREDL_TXCMD_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_PREDL_TXCMD_HANG_ERR_MASK \ +0x00002000 /* BN0_PREDL_TXCMD_HANG_ERR[13] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_PREDL_TXCMD_HANG_ERR_SHFT 13 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_RPEDL_ARB_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_RPEDL_ARB_HANG_ERR_MASK \ +0x00001000 /* BN0_RPEDL_ARB_HANG_ERR[12] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_RPEDL_ARB_HANG_ERR_SHFT 12 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_RIOC_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_RIOC_HANG_ERR_MASK \ +0x00000200 /* BN1_MDP_RIOC_HANG_ERR[9] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_RIOC_HANG_ERR_SHFT 9 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_TIOC_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_TIOC_HANG_ERR_MASK \ +0x00000100 /* BN1_MDP_TIOC_HANG_ERR[8] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_TIOC_HANG_ERR_SHFT 8 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_TDP_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_TDP_HANG_ERR_MASK \ +0x00000080 /* BN1_MDP_TDP_HANG_ERR[7] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_TDP_HANG_ERR_SHFT 7 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_SEC1_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_SEC1_HANG_ERR_MASK \ +0x00000040 /* SEC1_HANG_ERR[6] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_SEC1_HANG_ERR_SHFT 6 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_SEC0_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_SEC0_HANG_ERR_MASK \ +0x00000020 /* SEC0_HANG_ERR[5] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_SEC0_HANG_ERR_SHFT 5 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_PF_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_PF_HANG_ERR_MASK \ +0x00000010 /* PF_HANG_ERR[4] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_PF_HANG_ERR_SHFT 4 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_RIOC_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_RIOC_HANG_ERR_MASK \ +0x00000008 /* BN0_MDP_RIOC_HANG_ERR[3] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_RIOC_HANG_ERR_SHFT 3 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_TIOC_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_TIOC_HANG_ERR_MASK \ +0x00000004 /* BN0_MDP_TIOC_HANG_ERR[2] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_TIOC_HANG_ERR_SHFT 2 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_MDP_RDP_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_MDP_RDP_HANG_ERR_MASK \ +0x00000002 /* MDP_RDP_HANG_ERR[1] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_MDP_RDP_HANG_ERR_SHFT 1 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_TDP_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_TDP_HANG_ERR_MASK \ +0x00000001 /* BN0_MDP_TDP_HANG_ERR[0] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_TDP_HANG_ERR_SHFT 0 + +/* +* ---INT_N9_ERR_MASK_1 (0x820C0000 + 0xdc)--- +* EN_BN0_MDP_TDP_HANG_ERR[0] - (RW) Enables Band0 MDP TDP FSM hang error +interrupt +* EN_MDP_RDP_HANG_ERR[1] - (RW) Enables MDP RDP FSM hang error interrupt +* EN_BN0_MDP_TIOC_HANG_ERR[2] - (RW) Enables Band0 MDP TIOC FSM hang error +interrupt +* EN_BN0_MDP_RIOC_HANG_ERR[3] - (RW) Enables Band0 MDP RIOC FSM hang error +interrupt +* EN_PF_HANG_ERR[4] - (RW) Enables PF FSM hang error interrupt +* EN_SEC0_HANG_ERR[5] - (RW) Enables SEC 0 FSM hang error interrupt +* EN_SEC1_HANG_ERR[6] - (RW) Enables SEC 1 FSM hang error interrupt +* EN_BN1_MDP_TDP_HANG_ERR[7] - (RW) Enables Band1 MDP TDP FSM hang error +interrupt +* EN_BN1_MDP_TIOC_HANG_ERR[8] - (RW) Enables Band1 MDP TIOC FSM hang error +interrupt +* EN_BN1_MDP_RIOC_HANG_ERR[9] - (RW) Enables Band1 MDP RIOC FSM hang error +interrupt +* RESERVED10[11..10] - (RO) Reserved bits +* EN_BN0_PREDL_ARB_HANG_ERR[12] - (RW) Enables Band0 PREDL ARB FSM hang error +interrupt +* EN_BN0_PREDL_TXCMD_HANG_ERR[13] - (RW) Enables Band0 PREDL TXCMD parser FSM +* hang error interrupt +* EN_BN1_PREDL_ARB_HANG_ERR[14] - (RW) Enables Band1 PREDL ARB FSM hang error +interrupt +* EN_BN1_PREDL_TXCMD_HANG_ERR[15] - (RW) Enables Band1 PREDL TXCMD parser FSM +* hang error interrupt +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_PREDL_TXCMD_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_PREDL_TXCMD_HANG_ERR_MASK \ +0x00008000 /* EN_BN1_PREDL_TXCMD_HANG_ERR[15] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_PREDL_TXCMD_HANG_ERR_SHFT 15 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_PREDL_ARB_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_PREDL_ARB_HANG_ERR_MASK \ +0x00004000 /* EN_BN1_PREDL_ARB_HANG_ERR[14] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_PREDL_ARB_HANG_ERR_SHFT 14 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_PREDL_TXCMD_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_PREDL_TXCMD_HANG_ERR_MASK \ +0x00002000 /* EN_BN0_PREDL_TXCMD_HANG_ERR[13] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_PREDL_TXCMD_HANG_ERR_SHFT 13 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_PREDL_ARB_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_PREDL_ARB_HANG_ERR_MASK \ +0x00001000 /* EN_BN0_PREDL_ARB_HANG_ERR[12] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_PREDL_ARB_HANG_ERR_SHFT 12 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_RIOC_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_RIOC_HANG_ERR_MASK \ +0x00000200 /* EN_BN1_MDP_RIOC_HANG_ERR[9] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_RIOC_HANG_ERR_SHFT 9 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_TIOC_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_TIOC_HANG_ERR_MASK \ +0x00000100 /* EN_BN1_MDP_TIOC_HANG_ERR[8] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_TIOC_HANG_ERR_SHFT 8 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_TDP_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_TDP_HANG_ERR_MASK \ +0x00000080 /* EN_BN1_MDP_TDP_HANG_ERR[7] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_TDP_HANG_ERR_SHFT 7 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_SEC1_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_SEC1_HANG_ERR_MASK \ +0x00000040 /* EN_SEC1_HANG_ERR[6] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_SEC1_HANG_ERR_SHFT 6 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_SEC0_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_SEC0_HANG_ERR_MASK \ +0x00000020 /* EN_SEC0_HANG_ERR[5] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_SEC0_HANG_ERR_SHFT 5 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_PF_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_PF_HANG_ERR_MASK \ +0x00000010 /* EN_PF_HANG_ERR[4] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_PF_HANG_ERR_SHFT 4 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_RIOC_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_RIOC_HANG_ERR_MASK \ +0x00000008 /* EN_BN0_MDP_RIOC_HANG_ERR[3] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_RIOC_HANG_ERR_SHFT 3 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_TIOC_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_TIOC_HANG_ERR_MASK \ +0x00000004 /* EN_BN0_MDP_TIOC_HANG_ERR[2] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_TIOC_HANG_ERR_SHFT 2 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_MDP_RDP_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_MDP_RDP_HANG_ERR_MASK \ +0x00000002 /* EN_MDP_RDP_HANG_ERR[1] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_MDP_RDP_HANG_ERR_SHFT 1 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_TDP_HANG_ERR_ADDR \ +WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_TDP_HANG_ERR_MASK \ +0x00000001 /* EN_BN0_MDP_TDP_HANG_ERR[0] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_TDP_HANG_ERR_SHFT 0 + +/* +* ---TO_N9_INT (0x820C0000 + 0xf0)--- +* CR4_CMD[30..0] - (RW) Command for N9 +* TOGGLE[31] - (RW) When this bit is toggled, HW will send +* interrupt to N9. +*/ +#define WF_PLE_TOP_TO_N9_INT_TOGGLE_ADDR WF_PLE_TOP_TO_N9_INT_ADDR +#define WF_PLE_TOP_TO_N9_INT_TOGGLE_MASK 0x80000000 /* TOGGLE[31] */ +#define WF_PLE_TOP_TO_N9_INT_TOGGLE_SHFT 31 +#define WF_PLE_TOP_TO_N9_INT_CR4_CMD_ADDR WF_PLE_TOP_TO_N9_INT_ADDR +#define WF_PLE_TOP_TO_N9_INT_CR4_CMD_MASK 0x7FFFFFFF /* CR4_CMD[30..0] */ +#define WF_PLE_TOP_TO_N9_INT_CR4_CMD_SHFT 0 + +/* +* ---N9_BSS_PS_INT_MASK (0x820C0000 + 0xf4)--- +* EN_BSSID0_NONEMPTY_INT[0] - (RW) Enable control of BSSID0 queue empty +fall +* EN_BSSID1_NONEMPTY_INT[1] - (RW) Enable control of BSSID1 queue empty +fall +* EN_BSSID2_NONEMPTY_INT[2] - (RW) Enable control of BSSID2 queue empty +fall +* EN_BSSID3_NONEMPTY_INT[3] - (RW) Enable control of BSSID3 queue empty +fall +* RESERVED4[7..4] - (RO) Reserved bits +* EN_BSSID0_EMPTY_INT[8] - (RW) Enable control of BSSID0 queue empty +raise +* EN_BSSID1_EMPTY_INT[9] - (RW) Enable control of BSSID1 queue empty +raise +* EN_BSSID2_EMPTY_INT[10] - (RW) Enable control of BSSID2 queue empty +raise +* EN_BSSID3_EMPTY_INT[11] - (RW) Enable control of BSSID3 queue empty +raise +* RESERVED12[15..12] - (RO) Reserved bits +* EN_BSSID0_ENQ_LMAC_INT[16] - (RW) Enable control of BSSID0 enqueue +interrupt +* EN_BSSID1_ENQ_LMAC_INT[17] - (RW) Enable control of BSSID1 enqueue +interrupt +* EN_BSSID2_ENQ_LMAC_INT[18] - (RW) Enable control of BSSID2 enqueue +interrupt +* EN_BSSID3_ENQ_LMAC_INT[19] - (RW) Enable control of BSSID3 enqueue +interrupt +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_ENQ_LMAC_INT_ADDR \ +WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_ENQ_LMAC_INT_MASK \ +0x00080000 /* EN_BSSID3_ENQ_LMAC_INT[19] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_ENQ_LMAC_INT_SHFT 19 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_ENQ_LMAC_INT_ADDR \ +WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_ENQ_LMAC_INT_MASK \ +0x00040000 /* EN_BSSID2_ENQ_LMAC_INT[18] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_ENQ_LMAC_INT_SHFT 18 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_ENQ_LMAC_INT_ADDR \ +WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_ENQ_LMAC_INT_MASK \ +0x00020000 /* EN_BSSID1_ENQ_LMAC_INT[17] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_ENQ_LMAC_INT_SHFT 17 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_ENQ_LMAC_INT_ADDR \ +WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_ENQ_LMAC_INT_MASK \ +0x00010000 /* EN_BSSID0_ENQ_LMAC_INT[16] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_ENQ_LMAC_INT_SHFT 16 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_EMPTY_INT_ADDR \ +WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_EMPTY_INT_MASK \ +0x00000800 /* EN_BSSID3_EMPTY_INT[11] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_EMPTY_INT_SHFT 11 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_EMPTY_INT_ADDR \ +WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_EMPTY_INT_MASK \ +0x00000400 /* EN_BSSID2_EMPTY_INT[10] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_EMPTY_INT_SHFT 10 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_EMPTY_INT_ADDR \ +WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_EMPTY_INT_MASK \ +0x00000200 /* EN_BSSID1_EMPTY_INT[9] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_EMPTY_INT_SHFT 9 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_EMPTY_INT_ADDR \ +WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_EMPTY_INT_MASK \ +0x00000100 /* EN_BSSID0_EMPTY_INT[8] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_EMPTY_INT_SHFT 8 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_NONEMPTY_INT_ADDR \ +WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_NONEMPTY_INT_MASK \ +0x00000008 /* EN_BSSID3_NONEMPTY_INT[3] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_NONEMPTY_INT_SHFT 3 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_NONEMPTY_INT_ADDR \ +WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_NONEMPTY_INT_MASK \ +0x00000004 /* EN_BSSID2_NONEMPTY_INT[2] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_NONEMPTY_INT_SHFT 2 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_NONEMPTY_INT_ADDR \ +WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_NONEMPTY_INT_MASK \ +0x00000002 /* EN_BSSID1_NONEMPTY_INT[1] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_NONEMPTY_INT_SHFT 1 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_NONEMPTY_INT_ADDR \ +WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_NONEMPTY_INT_MASK \ +0x00000001 /* EN_BSSID0_NONEMPTY_INT[0] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_NONEMPTY_INT_SHFT 0 + +/* +* ---N9_BSS_PS_INT_STS (0x820C0000 + 0xf8)--- +* BSSID0_NONEMPTY_INT[0] - (W1C) BSSID0 queue empty fall interrupt +status +* BSSID1_NONEMPTY_INT[1] - (W1C) BSSID1 queue empty fall interrupt +status +* BSSID2_NONEMPTY_INT[2] - (W1C) BSSID2 queue empty fall interrupt +status +* BSSID3_NONEMPTY_INT[3] - (W1C) BSSID3 queue empty fall interrupt +status +* RESERVED4[7..4] - (RO) Reserved bits +* BSSID0_EMPTY_INT[8] - (W1C) BSSID0 queue empty raise interrupt +status +* BSSID1_EMPTY_INT[9] - (W1C) BSSID1 queue empty raise interrupt +status +* BSSID2_EMPTY_INT[10] - (W1C) BSSID2 queue empty raise interrupt +status +* BSSID3_EMPTY_INT[11] - (W1C) BSSID3 queue empty raise interrupt +status +* RESERVED12[15..12] - (RO) Reserved bits +* BSSID0_ENQ_LMAC_INT[16] - (W1C) BSSID0 enqueue interrupt status +* BSSID1_ENQ_LMAC_INT[17] - (W1C) BSSID1 enqueue interrupt status +* BSSID2_ENQ_LMAC_INT[18] - (W1C) BSSID2 enqueue interrupt status +* BSSID3_ENQ_LMAC_INT[19] - (W1C) BSSID3 enqueue interrupt status +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_ENQ_LMAC_INT_ADDR \ +WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_ENQ_LMAC_INT_MASK \ +0x00080000 /* BSSID3_ENQ_LMAC_INT[19] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_ENQ_LMAC_INT_SHFT 19 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_ENQ_LMAC_INT_ADDR \ +WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_ENQ_LMAC_INT_MASK \ +0x00040000 /* BSSID2_ENQ_LMAC_INT[18] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_ENQ_LMAC_INT_SHFT 18 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_ENQ_LMAC_INT_ADDR \ +WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_ENQ_LMAC_INT_MASK \ +0x00020000 /* BSSID1_ENQ_LMAC_INT[17] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_ENQ_LMAC_INT_SHFT 17 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_ENQ_LMAC_INT_ADDR \ +WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_ENQ_LMAC_INT_MASK \ +0x00010000 /* BSSID0_ENQ_LMAC_INT[16] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_ENQ_LMAC_INT_SHFT 16 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_EMPTY_INT_ADDR \ +WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_EMPTY_INT_MASK \ +0x00000800 /* BSSID3_EMPTY_INT[11] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_EMPTY_INT_SHFT 11 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_EMPTY_INT_ADDR \ +WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_EMPTY_INT_MASK \ +0x00000400 /* BSSID2_EMPTY_INT[10] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_EMPTY_INT_SHFT 10 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_EMPTY_INT_ADDR \ +WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_EMPTY_INT_MASK \ +0x00000200 /* BSSID1_EMPTY_INT[9] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_EMPTY_INT_SHFT 9 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_EMPTY_INT_ADDR \ +WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_EMPTY_INT_MASK \ +0x00000100 /* BSSID0_EMPTY_INT[8] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_EMPTY_INT_SHFT 8 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_NONEMPTY_INT_ADDR \ +WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_NONEMPTY_INT_MASK \ +0x00000008 /* BSSID3_NONEMPTY_INT[3] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_NONEMPTY_INT_SHFT 3 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_NONEMPTY_INT_ADDR \ +WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_NONEMPTY_INT_MASK \ +0x00000004 /* BSSID2_NONEMPTY_INT[2] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_NONEMPTY_INT_SHFT 2 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_NONEMPTY_INT_ADDR \ +WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_NONEMPTY_INT_MASK \ +0x00000002 /* BSSID1_NONEMPTY_INT[1] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_NONEMPTY_INT_SHFT 1 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_NONEMPTY_INT_ADDR \ +WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_NONEMPTY_INT_MASK \ +0x00000001 /* BSSID0_NONEMPTY_INT[0] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_NONEMPTY_INT_SHFT 0 + +/* +* ---FREEPG_CNT (0x820C0000 + 0x100)--- +* FREEPG_CNT[11..0] - (RO) Total page number of free +* RESERVED12[15..12] - (RO) Reserved bits +* FFA_CNT[27..16] - (RO) Free page numbers of free for all +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FREEPG_CNT_FFA_CNT_ADDR WF_PLE_TOP_FREEPG_CNT_ADDR +#define WF_PLE_TOP_FREEPG_CNT_FFA_CNT_MASK 0x0FFF0000 /* FFA_CNT[27..16] */ +#define WF_PLE_TOP_FREEPG_CNT_FFA_CNT_SHFT 16 +#define WF_PLE_TOP_FREEPG_CNT_FREEPG_CNT_ADDR WF_PLE_TOP_FREEPG_CNT_ADDR +#define WF_PLE_TOP_FREEPG_CNT_FREEPG_CNT_MASK 0x00000FFF /* FREEPG_CNT[11..0]\ + */ +#define WF_PLE_TOP_FREEPG_CNT_FREEPG_CNT_SHFT 0 + +/* +* ---FREEPG_HEAD_TAIL (0x820C0000 + 0x104)--- +* FREEPG_HEAD[11..0] - (RO) Head page of free page list +* RESERVED12[15..12] - (RO) Reserved bits +* FREEPG_TAIL[27..16] - (RO) Tail page of free page list +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_ADDR \ +WF_PLE_TOP_FREEPG_HEAD_TAIL_ADDR +#define WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_MASK \ +0x0FFF0000 /* FREEPG_TAIL[27..16] */ +#define WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_SHFT 16 +#define WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_ADDR \ +WF_PLE_TOP_FREEPG_HEAD_TAIL_ADDR +#define WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_MASK \ +0x00000FFF /* FREEPG_HEAD[11..0] */ +#define WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_SHFT 0 + +/* +* ---PG_HIF_GROUP (0x820C0000 + 0x110)--- +* HIF_MIN_QUOTA[11..0] - (RW) Min. quota of HIF group +* Set the quota before release PLE logic +* reset ,and must not be changed after release logic reset. +* RESERVED12[15..12] - (RO) Reserved bits +* HIF_MAX_QUOTA[27..16] - (RW) Max. quota of HIF group +* Set up the quota before releasing PLE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PG_HIF_GROUP_HIF_MAX_QUOTA_ADDR WF_PLE_TOP_PG_HIF_GROUP_ADDR +#define WF_PLE_TOP_PG_HIF_GROUP_HIF_MAX_QUOTA_MASK \ +0x0FFF0000 /* HIF_MAX_QUOTA[27..16] */ +#define WF_PLE_TOP_PG_HIF_GROUP_HIF_MAX_QUOTA_SHFT 16 +#define WF_PLE_TOP_PG_HIF_GROUP_HIF_MIN_QUOTA_ADDR WF_PLE_TOP_PG_HIF_GROUP_ADDR +#define WF_PLE_TOP_PG_HIF_GROUP_HIF_MIN_QUOTA_MASK \ +0x00000FFF /* HIF_MIN_QUOTA[11..0] */ +#define WF_PLE_TOP_PG_HIF_GROUP_HIF_MIN_QUOTA_SHFT 0 + +/* +* ---HIF_PG_INFO (0x820C0000 + 0x114)--- +* HIF_RSV_CNT[11..0] - (RO) Reserved pages of HIF group +* RESERVED12[15..12] - (RO) Reserved bits +* HIF_SRC_CNT[27..16] - (RO) Used pages of HIF group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_HIF_PG_INFO_HIF_SRC_CNT_ADDR WF_PLE_TOP_HIF_PG_INFO_ADDR +#define WF_PLE_TOP_HIF_PG_INFO_HIF_SRC_CNT_MASK \ +0x0FFF0000 /* HIF_SRC_CNT[27..16] */ +#define WF_PLE_TOP_HIF_PG_INFO_HIF_SRC_CNT_SHFT 16 +#define WF_PLE_TOP_HIF_PG_INFO_HIF_RSV_CNT_ADDR WF_PLE_TOP_HIF_PG_INFO_ADDR +#define WF_PLE_TOP_HIF_PG_INFO_HIF_RSV_CNT_MASK \ +0x00000FFF /* HIF_RSV_CNT[11..0] */ +#define WF_PLE_TOP_HIF_PG_INFO_HIF_RSV_CNT_SHFT 0 + +/* +* ---PG_HIF_WMTXD_GROUP (0x820C0000 + 0x118)--- +* HIF_WMTXD_MIN_QUOTA[11..0] - (RW) Min. quota of HIF WMCPU TXD group +* Set the quota before release PLE logic +* reset ,and must not be changed after release logic reset. +* RESERVED12[15..12] - (RO) Reserved bits +* HIF_WMTXD_MAX_QUOTA[27..16] - (RW) Max. quota of HIF WMCPU TXD group +* Set up the quota before releasing PLE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PG_HIF_WMTXD_GROUP_HIF_WMTXD_MAX_QUOTA_ADDR \ +WF_PLE_TOP_PG_HIF_WMTXD_GROUP_ADDR +#define WF_PLE_TOP_PG_HIF_WMTXD_GROUP_HIF_WMTXD_MAX_QUOTA_MASK \ +0x0FFF0000 /* HIF_WMTXD_MAX_QUOTA[27..16] */ +#define WF_PLE_TOP_PG_HIF_WMTXD_GROUP_HIF_WMTXD_MAX_QUOTA_SHFT 16 +#define WF_PLE_TOP_PG_HIF_WMTXD_GROUP_HIF_WMTXD_MIN_QUOTA_ADDR \ +WF_PLE_TOP_PG_HIF_WMTXD_GROUP_ADDR +#define WF_PLE_TOP_PG_HIF_WMTXD_GROUP_HIF_WMTXD_MIN_QUOTA_MASK \ +0x00000FFF /* HIF_WMTXD_MIN_QUOTA[11..0] */ +#define WF_PLE_TOP_PG_HIF_WMTXD_GROUP_HIF_WMTXD_MIN_QUOTA_SHFT 0 + +/* +* ---HIF_WMTXD_PG_INFO (0x820C0000 + 0x11C)--- +* HIF_WMTXD_RSV_CNT[11..0] - (RO) Reserved pages of HIF WMCPU TXD group +* RESERVED12[15..12] - (RO) Reserved bits +* HIF_WMTXD_SRC_CNT[27..16] - (RO) Used pages of HIF WMCPU TXD group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_HIF_WMTXD_PG_INFO_HIF_WMTXD_SRC_CNT_ADDR \ +WF_PLE_TOP_HIF_WMTXD_PG_INFO_ADDR +#define WF_PLE_TOP_HIF_WMTXD_PG_INFO_HIF_WMTXD_SRC_CNT_MASK \ +0x0FFF0000 /* HIF_WMTXD_SRC_CNT[27..16] */ +#define WF_PLE_TOP_HIF_WMTXD_PG_INFO_HIF_WMTXD_SRC_CNT_SHFT 16 +#define WF_PLE_TOP_HIF_WMTXD_PG_INFO_HIF_WMTXD_RSV_CNT_ADDR \ +WF_PLE_TOP_HIF_WMTXD_PG_INFO_ADDR +#define WF_PLE_TOP_HIF_WMTXD_PG_INFO_HIF_WMTXD_RSV_CNT_MASK \ +0x00000FFF /* HIF_WMTXD_RSV_CNT[11..0] */ +#define WF_PLE_TOP_HIF_WMTXD_PG_INFO_HIF_WMTXD_RSV_CNT_SHFT 0 + +/* +* ---PG_HIF_TXCMD_GROUP (0x820C0000 + 0x120)--- +* HIF_TXCMD_MIN_QUOTA[11..0] - (RW) Min. quota of HIF TXCMD group +* Set the quota before release PLE logic +* reset ,and must not be changed after release logic reset. +* RESERVED12[15..12] - (RO) Reserved bits +* HIF_TXCMD_MAX_QUOTA[27..16] - (RW) Max. quota of HIF TXCMD group +* Set up the quota before releasing PLE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MAX_QUOTA_ADDR \ +WF_PLE_TOP_PG_HIF_TXCMD_GROUP_ADDR +#define WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MAX_QUOTA_MASK \ +0x0FFF0000 /* HIF_TXCMD_MAX_QUOTA[27..16] */ +#define WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MAX_QUOTA_SHFT 16 +#define WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MIN_QUOTA_ADDR \ +WF_PLE_TOP_PG_HIF_TXCMD_GROUP_ADDR +#define WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MIN_QUOTA_MASK \ +0x00000FFF /* HIF_TXCMD_MIN_QUOTA[11..0] */ +#define WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MIN_QUOTA_SHFT 0 + +/* +* ---HIF_TXCMD_PG_INFO (0x820C0000 + 0x124)--- +* HIF_TXCMD_RSV_CNT[11..0] - (RO) Reserved pages of HIF TXCMD group +* RESERVED12[15..12] - (RO) Reserved bits +* HIF_TXCMD_SRC_CNT[27..16] - (RO) Used pages of HIF TXCMD group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_SRC_CNT_ADDR \ +WF_PLE_TOP_HIF_TXCMD_PG_INFO_ADDR +#define WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_SRC_CNT_MASK \ +0x0FFF0000 /* HIF_TXCMD_SRC_CNT[27..16] */ +#define WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_SRC_CNT_SHFT 16 +#define WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_RSV_CNT_ADDR \ +WF_PLE_TOP_HIF_TXCMD_PG_INFO_ADDR +#define WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_RSV_CNT_MASK \ +0x00000FFF /* HIF_TXCMD_RSV_CNT[11..0] */ +#define WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_RSV_CNT_SHFT 0 + +/* +* ---TWT_TX_CTRL0 (0x820C0000 + 0x130)--- +* en_twt_stop_tx_ctrl_0[0] - (RW) Enable TWT non-active period TX control +function. +* en_twt_stop_tx_ctrl_1[1] - (RW) Enable TWT non-active period TX control +function. +* en_twt_stop_tx_ctrl_2[2] - (RW) Enable TWT non-active period TX control +function. +* en_twt_stop_tx_ctrl_3[3] - (RW) Enable TWT non-active period TX control +function. +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_3_ADDR \ +WF_PLE_TOP_TWT_TX_CTRL0_ADDR +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_3_MASK \ +0x00000008 /* en_twt_stop_tx_ctrl_3[3] */ +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_3_SHFT 3 +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_2_ADDR \ +WF_PLE_TOP_TWT_TX_CTRL0_ADDR +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_2_MASK \ +0x00000004 /* en_twt_stop_tx_ctrl_2[2] */ +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_2_SHFT 2 +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_1_ADDR \ +WF_PLE_TOP_TWT_TX_CTRL0_ADDR +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_1_MASK \ +0x00000002 /* en_twt_stop_tx_ctrl_1[1] */ +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_1_SHFT 1 +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_0_ADDR \ +WF_PLE_TOP_TWT_TX_CTRL0_ADDR +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_0_MASK \ +0x00000001 /* en_twt_stop_tx_ctrl_0[0] */ +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_0_SHFT 0 + +/* +* ---PLE_FUNC_CTRL_0 (0x820C0000 + 0x140)--- +* MACTX_REQ_DEASSERT[0] - (RW) Enable of DeAsser MACTX REQ.(Normal +* operation must be zero.) +* MACTX_ABORT_DEASSERT[1] - (RW) Enable of DeAsser MACTX ABORT.(Normal +* operation must be zero.) +* MPDU_DONE_CNT_IN_NO_TX_REQ[2] - (RW) MPDU done mode for LMAC no TX request +* MPDU_DONE_CNT_IN_NO_ADD[3] - (RW) MPDU done mode for LMAC no add +* ACK_LMAC_NO_FID_ADD[4] - (RW) MACTX ack mode for LMAC no add any fid +* for TX +* RESERVED5[5] - (RO) Reserved bits +* DIS_STA_RLS_TO_1F[6] - (RW) Release port setting of disable STA +function +* RESERVED7[7] - (RO) Reserved bits +* MACTX_REQ_ASSERT[8] - (RW) Enable of Asser MACTX REQ.(Normal +* operation must be zero.) +* MACTX_ABORT_ASSERT[9] - (RW) Enable of Asser MACTX ABORT.(Normal +* operation must be zero.) +* RESERVED10[21..10] - (RO) Reserved bits +* DIS_AUTORATE_TXP_REQ[22] - (RW) Disable auto rate TXP request function +* LATER_PKT_PRE_CUT_1US[23] - (RW) Pre cut 1us air time for later packet. +* TXP_REQ_CNTDOWN_TH[27..24] - (RW) Threshold of air time count down for TXP +request +* TXP_REQ_HSPEED_DL_NUM[29..28] - (RW) Packet number of high speed TXP request +* issue, by pre-cut more micro-second +* TXP_REQ_HSPEED_CUT_US[31..30] - (RW) Number of pre-cut micro-second for high +* speed packet +*/ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_HSPEED_CUT_US_ADDR \ +WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_HSPEED_CUT_US_MASK \ +0xC0000000 /* TXP_REQ_HSPEED_CUT_US[31..30] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_HSPEED_CUT_US_SHFT 30 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_HSPEED_DL_NUM_ADDR \ +WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_HSPEED_DL_NUM_MASK \ +0x30000000 /* TXP_REQ_HSPEED_DL_NUM[29..28] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_HSPEED_DL_NUM_SHFT 28 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_CNTDOWN_TH_ADDR \ +WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_CNTDOWN_TH_MASK \ +0x0F000000 /* TXP_REQ_CNTDOWN_TH[27..24] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_CNTDOWN_TH_SHFT 24 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_LATER_PKT_PRE_CUT_1US_ADDR \ +WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_LATER_PKT_PRE_CUT_1US_MASK \ +0x00800000 /* LATER_PKT_PRE_CUT_1US[23] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_LATER_PKT_PRE_CUT_1US_SHFT 23 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_DIS_AUTORATE_TXP_REQ_ADDR \ +WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_DIS_AUTORATE_TXP_REQ_MASK \ +0x00400000 /* DIS_AUTORATE_TXP_REQ[22] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_DIS_AUTORATE_TXP_REQ_SHFT 22 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_ABORT_ASSERT_ADDR \ +WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_ABORT_ASSERT_MASK \ +0x00000200 /* MACTX_ABORT_ASSERT[9] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_ABORT_ASSERT_SHFT 9 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_REQ_ASSERT_ADDR \ +WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_REQ_ASSERT_MASK \ +0x00000100 /* MACTX_REQ_ASSERT[8] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_REQ_ASSERT_SHFT 8 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_DIS_STA_RLS_TO_1F_ADDR \ +WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_DIS_STA_RLS_TO_1F_MASK \ +0x00000040 /* DIS_STA_RLS_TO_1F[6] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_DIS_STA_RLS_TO_1F_SHFT 6 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_ACK_LMAC_NO_FID_ADD_ADDR \ +WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_ACK_LMAC_NO_FID_ADD_MASK \ +0x00000010 /* ACK_LMAC_NO_FID_ADD[4] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_ACK_LMAC_NO_FID_ADD_SHFT 4 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MPDU_DONE_CNT_IN_NO_ADD_ADDR \ +WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MPDU_DONE_CNT_IN_NO_ADD_MASK \ +0x00000008 /* MPDU_DONE_CNT_IN_NO_ADD[3] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MPDU_DONE_CNT_IN_NO_ADD_SHFT 3 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MPDU_DONE_CNT_IN_NO_TX_REQ_ADDR \ +WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MPDU_DONE_CNT_IN_NO_TX_REQ_MASK \ +0x00000004 /* MPDU_DONE_CNT_IN_NO_TX_REQ[2] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MPDU_DONE_CNT_IN_NO_TX_REQ_SHFT 2 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_ABORT_DEASSERT_ADDR \ +WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_ABORT_DEASSERT_MASK \ +0x00000002 /* MACTX_ABORT_DEASSERT[1] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_ABORT_DEASSERT_SHFT 1 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_REQ_DEASSERT_ADDR \ +WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_REQ_DEASSERT_MASK \ +0x00000001 /* MACTX_REQ_DEASSERT[0] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_REQ_DEASSERT_SHFT 0 + +/* +* ---PLE_FUNC_CTRL_1 (0x820C0000 + 0x144)--- +* RESERVED0[21..0] - (RO) Reserved bits +* PREDL_REQ_NORMAL_PRI[22] - (RW) Pre-download TXP request priority +control +* RESERVED23[31..23] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PLE_FUNC_CTRL_1_PREDL_REQ_NORMAL_PRI_ADDR \ +WF_PLE_TOP_PLE_FUNC_CTRL_1_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_1_PREDL_REQ_NORMAL_PRI_MASK \ +0x00400000 /* PREDL_REQ_NORMAL_PRI[22] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_1_PREDL_REQ_NORMAL_PRI_SHFT 22 + +/* +* ---PG_CPU_GROUP (0x820C0000 + 0x150)--- +* CPU_MIN_QUOTA[11..0] - (RW) Min. quota of CPU group +* Set up the quota before releasing PLE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* CPU_MAX_QUOTA[27..16] - (RW) Max. quota of CPU group +* Set up the quota before releasing PLE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PG_CPU_GROUP_CPU_MAX_QUOTA_ADDR WF_PLE_TOP_PG_CPU_GROUP_ADDR +#define WF_PLE_TOP_PG_CPU_GROUP_CPU_MAX_QUOTA_MASK \ +0x0FFF0000 /* CPU_MAX_QUOTA[27..16] */ +#define WF_PLE_TOP_PG_CPU_GROUP_CPU_MAX_QUOTA_SHFT 16 +#define WF_PLE_TOP_PG_CPU_GROUP_CPU_MIN_QUOTA_ADDR WF_PLE_TOP_PG_CPU_GROUP_ADDR +#define WF_PLE_TOP_PG_CPU_GROUP_CPU_MIN_QUOTA_MASK \ +0x00000FFF /* CPU_MIN_QUOTA[11..0] */ +#define WF_PLE_TOP_PG_CPU_GROUP_CPU_MIN_QUOTA_SHFT 0 + +/* +* ---CPU_PG_INFO (0x820C0000 + 0x154)--- +* CPU_RSV_CNT[11..0] - (RO) Reserved pages of CPU group +* RESERVED12[15..12] - (RO) Reserved bits +* CPU_SRC_CNT[27..16] - (RO) Used pages of CPU group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CPU_PG_INFO_CPU_SRC_CNT_ADDR WF_PLE_TOP_CPU_PG_INFO_ADDR +#define WF_PLE_TOP_CPU_PG_INFO_CPU_SRC_CNT_MASK \ +0x0FFF0000 /* CPU_SRC_CNT[27..16] */ +#define WF_PLE_TOP_CPU_PG_INFO_CPU_SRC_CNT_SHFT 16 +#define WF_PLE_TOP_CPU_PG_INFO_CPU_RSV_CNT_ADDR WF_PLE_TOP_CPU_PG_INFO_ADDR +#define WF_PLE_TOP_CPU_PG_INFO_CPU_RSV_CNT_MASK \ +0x00000FFF /* CPU_RSV_CNT[11..0] */ +#define WF_PLE_TOP_CPU_PG_INFO_CPU_RSV_CNT_SHFT 0 + +/* +* ---PLE_LOG_0 (0x820C0000 + 0x170)--- +* PLE_LOG_0[31..0] - (RW) Log message for SW +*/ +#define WF_PLE_TOP_PLE_LOG_0_PLE_LOG_0_ADDR WF_PLE_TOP_PLE_LOG_0_ADDR +#define WF_PLE_TOP_PLE_LOG_0_PLE_LOG_0_MASK 0xFFFFFFFF /* PLE_LOG_0[31..0] */ +#define WF_PLE_TOP_PLE_LOG_0_PLE_LOG_0_SHFT 0 + +/* +* ---PLE_LOG_1 (0x820C0000 + 0x174)--- +* PLE_LOG_1[31..0] - (RW) Log message for SW +*/ +#define WF_PLE_TOP_PLE_LOG_1_PLE_LOG_1_ADDR WF_PLE_TOP_PLE_LOG_1_ADDR +#define WF_PLE_TOP_PLE_LOG_1_PLE_LOG_1_MASK 0xFFFFFFFF /* PLE_LOG_1[31..0] */ +#define WF_PLE_TOP_PLE_LOG_1_PLE_LOG_1_SHFT 0 + +/* +* ---PLE_LOG_2 (0x820C0000 + 0x178)--- +* PLE_LOG_2[31..0] - (RW) Log message for SW +*/ +#define WF_PLE_TOP_PLE_LOG_2_PLE_LOG_2_ADDR WF_PLE_TOP_PLE_LOG_2_ADDR +#define WF_PLE_TOP_PLE_LOG_2_PLE_LOG_2_MASK 0xFFFFFFFF /* PLE_LOG_2[31..0] */ +#define WF_PLE_TOP_PLE_LOG_2_PLE_LOG_2_SHFT 0 + +/* +* ---PLE_LOG_3 (0x820C0000 + 0x17c)--- +* PLE_LOG_3[31..0] - (RW) Log message for SW +*/ +#define WF_PLE_TOP_PLE_LOG_3_PLE_LOG_3_ADDR WF_PLE_TOP_PLE_LOG_3_ADDR +#define WF_PLE_TOP_PLE_LOG_3_PLE_LOG_3_MASK 0xFFFFFFFF /* PLE_LOG_3[31..0] */ +#define WF_PLE_TOP_PLE_LOG_3_PLE_LOG_3_SHFT 0 + +/* +* ---WMMAC_PGCNT_0 (0x820C0000 + 0x180)--- +* WMMAC_00_PGCNT[11..0] - (RO) WMMAC 00 used page count +* RESERVED12[15..12] - (RO) Reserved bits +* WMMAC_01_PGCNT[27..16] - (RO) WMMAC 01 used page count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_WMMAC_PGCNT_0_WMMAC_01_PGCNT_ADDR \ +WF_PLE_TOP_WMMAC_PGCNT_0_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_0_WMMAC_01_PGCNT_MASK \ +0x0FFF0000 /* WMMAC_01_PGCNT[27..16] */ +#define WF_PLE_TOP_WMMAC_PGCNT_0_WMMAC_01_PGCNT_SHFT 16 +#define WF_PLE_TOP_WMMAC_PGCNT_0_WMMAC_00_PGCNT_ADDR \ +WF_PLE_TOP_WMMAC_PGCNT_0_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_0_WMMAC_00_PGCNT_MASK \ +0x00000FFF /* WMMAC_00_PGCNT[11..0] */ +#define WF_PLE_TOP_WMMAC_PGCNT_0_WMMAC_00_PGCNT_SHFT 0 + +/* +* ---WMMAC_PGCNT_1 (0x820C0000 + 0x184)--- +* WMMAC_02_PGCNT[11..0] - (RO) WMMAC 02 used page count +* RESERVED12[15..12] - (RO) Reserved bits +* WMMAC_03_PGCNT[27..16] - (RO) WMMAC 03 used page count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_WMMAC_PGCNT_1_WMMAC_03_PGCNT_ADDR \ +WF_PLE_TOP_WMMAC_PGCNT_1_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_1_WMMAC_03_PGCNT_MASK \ +0x0FFF0000 /* WMMAC_03_PGCNT[27..16] */ +#define WF_PLE_TOP_WMMAC_PGCNT_1_WMMAC_03_PGCNT_SHFT 16 +#define WF_PLE_TOP_WMMAC_PGCNT_1_WMMAC_02_PGCNT_ADDR \ +WF_PLE_TOP_WMMAC_PGCNT_1_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_1_WMMAC_02_PGCNT_MASK \ +0x00000FFF /* WMMAC_02_PGCNT[11..0] */ +#define WF_PLE_TOP_WMMAC_PGCNT_1_WMMAC_02_PGCNT_SHFT 0 + +/* +* ---WMMAC_PGCNT_2 (0x820C0000 + 0x188)--- +* WMMAC_10_PGCNT[11..0] - (RO) WMMAC 10 used page count +* RESERVED12[15..12] - (RO) Reserved bits +* WMMAC_11_PGCNT[27..16] - (RO) WMMAC 11 used page count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_WMMAC_PGCNT_2_WMMAC_11_PGCNT_ADDR \ +WF_PLE_TOP_WMMAC_PGCNT_2_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_2_WMMAC_11_PGCNT_MASK \ +0x0FFF0000 /* WMMAC_11_PGCNT[27..16] */ +#define WF_PLE_TOP_WMMAC_PGCNT_2_WMMAC_11_PGCNT_SHFT 16 +#define WF_PLE_TOP_WMMAC_PGCNT_2_WMMAC_10_PGCNT_ADDR \ +WF_PLE_TOP_WMMAC_PGCNT_2_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_2_WMMAC_10_PGCNT_MASK \ +0x00000FFF /* WMMAC_10_PGCNT[11..0] */ +#define WF_PLE_TOP_WMMAC_PGCNT_2_WMMAC_10_PGCNT_SHFT 0 + +/* +* ---WMMAC_PGCNT_3 (0x820C0000 + 0x18c)--- +* WMMAC_12_PGCNT[11..0] - (RO) WMMAC 12 used page count +* RESERVED12[15..12] - (RO) Reserved bits +* WMMAC_13_PGCNT[27..16] - (RO) WMMAC 13 used page count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_WMMAC_PGCNT_3_WMMAC_13_PGCNT_ADDR \ +WF_PLE_TOP_WMMAC_PGCNT_3_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_3_WMMAC_13_PGCNT_MASK \ +0x0FFF0000 /* WMMAC_13_PGCNT[27..16] */ +#define WF_PLE_TOP_WMMAC_PGCNT_3_WMMAC_13_PGCNT_SHFT 16 +#define WF_PLE_TOP_WMMAC_PGCNT_3_WMMAC_12_PGCNT_ADDR \ +WF_PLE_TOP_WMMAC_PGCNT_3_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_3_WMMAC_12_PGCNT_MASK \ +0x00000FFF /* WMMAC_12_PGCNT[11..0] */ +#define WF_PLE_TOP_WMMAC_PGCNT_3_WMMAC_12_PGCNT_SHFT 0 + +/* +* ---WMMAC_PGCNT_4 (0x820C0000 + 0x190)--- +* WMMAC_20_PGCNT[11..0] - (RO) WMMAC 20 used page count +* RESERVED12[15..12] - (RO) Reserved bits +* WMMAC_21_PGCNT[27..16] - (RO) WMMAC 21 used page count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_WMMAC_PGCNT_4_WMMAC_21_PGCNT_ADDR \ +WF_PLE_TOP_WMMAC_PGCNT_4_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_4_WMMAC_21_PGCNT_MASK \ +0x0FFF0000 /* WMMAC_21_PGCNT[27..16] */ +#define WF_PLE_TOP_WMMAC_PGCNT_4_WMMAC_21_PGCNT_SHFT 16 +#define WF_PLE_TOP_WMMAC_PGCNT_4_WMMAC_20_PGCNT_ADDR \ +WF_PLE_TOP_WMMAC_PGCNT_4_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_4_WMMAC_20_PGCNT_MASK \ +0x00000FFF /* WMMAC_20_PGCNT[11..0] */ +#define WF_PLE_TOP_WMMAC_PGCNT_4_WMMAC_20_PGCNT_SHFT 0 + +/* +* ---WMMAC_PGCNT_5 (0x820C0000 + 0x194)--- +* WMMAC_22_PGCNT[11..0] - (RO) WMMAC 22 used page count +* RESERVED12[15..12] - (RO) Reserved bits +* WMMAC_23_PGCNT[27..16] - (RO) WMMAC 23 used page count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_WMMAC_PGCNT_5_WMMAC_23_PGCNT_ADDR \ +WF_PLE_TOP_WMMAC_PGCNT_5_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_5_WMMAC_23_PGCNT_MASK \ +0x0FFF0000 /* WMMAC_23_PGCNT[27..16] */ +#define WF_PLE_TOP_WMMAC_PGCNT_5_WMMAC_23_PGCNT_SHFT 16 +#define WF_PLE_TOP_WMMAC_PGCNT_5_WMMAC_22_PGCNT_ADDR \ +WF_PLE_TOP_WMMAC_PGCNT_5_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_5_WMMAC_22_PGCNT_MASK \ +0x00000FFF /* WMMAC_22_PGCNT[11..0] */ +#define WF_PLE_TOP_WMMAC_PGCNT_5_WMMAC_22_PGCNT_SHFT 0 + +/* +* ---WMMAC_PGCNT_6 (0x820C0000 + 0x198)--- +* WMMAC_30_PGCNT[11..0] - (RO) WMMAC 30 used page count +* RESERVED12[15..12] - (RO) Reserved bits +* WMMAC_31_PGCNT[27..16] - (RO) WMMAC 31 used page count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_WMMAC_PGCNT_6_WMMAC_31_PGCNT_ADDR \ +WF_PLE_TOP_WMMAC_PGCNT_6_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_6_WMMAC_31_PGCNT_MASK \ +0x0FFF0000 /* WMMAC_31_PGCNT[27..16] */ +#define WF_PLE_TOP_WMMAC_PGCNT_6_WMMAC_31_PGCNT_SHFT 16 +#define WF_PLE_TOP_WMMAC_PGCNT_6_WMMAC_30_PGCNT_ADDR \ +WF_PLE_TOP_WMMAC_PGCNT_6_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_6_WMMAC_30_PGCNT_MASK \ +0x00000FFF /* WMMAC_30_PGCNT[11..0] */ +#define WF_PLE_TOP_WMMAC_PGCNT_6_WMMAC_30_PGCNT_SHFT 0 + +/* +* ---WMMAC_PGCNT_7 (0x820C0000 + 0x19c)--- +* WMMAC_32_PGCNT[11..0] - (RO) WMMAC 32 used page count +* RESERVED12[15..12] - (RO) Reserved bits +* WMMAC_33_PGCNT[27..16] - (RO) WMMAC 33 used page count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_WMMAC_PGCNT_7_WMMAC_33_PGCNT_ADDR \ +WF_PLE_TOP_WMMAC_PGCNT_7_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_7_WMMAC_33_PGCNT_MASK \ +0x0FFF0000 /* WMMAC_33_PGCNT[27..16] */ +#define WF_PLE_TOP_WMMAC_PGCNT_7_WMMAC_33_PGCNT_SHFT 16 +#define WF_PLE_TOP_WMMAC_PGCNT_7_WMMAC_32_PGCNT_ADDR \ +WF_PLE_TOP_WMMAC_PGCNT_7_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_7_WMMAC_32_PGCNT_MASK \ +0x00000FFF /* WMMAC_32_PGCNT[11..0] */ +#define WF_PLE_TOP_WMMAC_PGCNT_7_WMMAC_32_PGCNT_SHFT 0 + +/* +* ---RL_BUF_CTRL_0 (0x820C0000 + 0x1A0)--- +* RELAY_BUF_ADDR[11..0] - (RW) Read address of relay buffer +* RESERVED12[30..12] - (RO) Reserved bits +* EXECUTE[31] - (A0) Executes relay buffer read command +*/ +#define WF_PLE_TOP_RL_BUF_CTRL_0_EXECUTE_ADDR WF_PLE_TOP_RL_BUF_CTRL_0_ADDR +#define WF_PLE_TOP_RL_BUF_CTRL_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_RL_BUF_CTRL_0_EXECUTE_SHFT 31 +#define WF_PLE_TOP_RL_BUF_CTRL_0_RELAY_BUF_ADDR_ADDR \ +WF_PLE_TOP_RL_BUF_CTRL_0_ADDR +#define WF_PLE_TOP_RL_BUF_CTRL_0_RELAY_BUF_ADDR_MASK \ +0x00000FFF /* RELAY_BUF_ADDR[11..0] */ +#define WF_PLE_TOP_RL_BUF_CTRL_0_RELAY_BUF_ADDR_SHFT 0 + +/* +* ---RL_BUF_CTRL_1 (0x820C0000 + 0x1A4)--- +* PAGE_NUM_0[0] - (RO) Page number[0] of packet +* PKT_LEN[11..1] - (RO) Length of the packet with head page +* being the relay buffer address +* Unit: 32 bytes +* PKT_TAIL_PAGE[23..12] - (RO) Tail page of the packet with head page +* being the relay buffer address +* RESV_GRP_ID[24] - (RO) Group ID of reserved page used by FID +* RESERVED25[25] - (RO) Reserved bits +* PAGE_NUM_1[27..26] - (RO) Page number[2:1] of packet +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_RL_BUF_CTRL_1_PAGE_NUM_1_ADDR WF_PLE_TOP_RL_BUF_CTRL_1_ADDR +#define WF_PLE_TOP_RL_BUF_CTRL_1_PAGE_NUM_1_MASK \ +0x0C000000 /* PAGE_NUM_1[27..26] */ +#define WF_PLE_TOP_RL_BUF_CTRL_1_PAGE_NUM_1_SHFT 26 +#define WF_PLE_TOP_RL_BUF_CTRL_1_RESV_GRP_ID_ADDR WF_PLE_TOP_RL_BUF_CTRL_1_ADDR +#define WF_PLE_TOP_RL_BUF_CTRL_1_RESV_GRP_ID_MASK \ +0x01000000 /* RESV_GRP_ID[24] */ +#define WF_PLE_TOP_RL_BUF_CTRL_1_RESV_GRP_ID_SHFT 24 +#define WF_PLE_TOP_RL_BUF_CTRL_1_PKT_TAIL_PAGE_ADDR \ +WF_PLE_TOP_RL_BUF_CTRL_1_ADDR +#define WF_PLE_TOP_RL_BUF_CTRL_1_PKT_TAIL_PAGE_MASK \ +0x00FFF000 /* PKT_TAIL_PAGE[23..12] */ +#define WF_PLE_TOP_RL_BUF_CTRL_1_PKT_TAIL_PAGE_SHFT 12 +#define WF_PLE_TOP_RL_BUF_CTRL_1_PKT_LEN_ADDR WF_PLE_TOP_RL_BUF_CTRL_1_ADDR +#define WF_PLE_TOP_RL_BUF_CTRL_1_PKT_LEN_MASK 0x00000FFE /* PKT_LEN[11..1] */ +#define WF_PLE_TOP_RL_BUF_CTRL_1_PKT_LEN_SHFT 1 +#define WF_PLE_TOP_RL_BUF_CTRL_1_PAGE_NUM_0_ADDR WF_PLE_TOP_RL_BUF_CTRL_1_ADDR +#define WF_PLE_TOP_RL_BUF_CTRL_1_PAGE_NUM_0_MASK 0x00000001 /* PAGE_NUM_0[0] \ + */ +#define WF_PLE_TOP_RL_BUF_CTRL_1_PAGE_NUM_0_SHFT 0 + +/* +* ---FL_QUE_CTRL_0 (0x820C0000 + 0x1B0)--- +* Q_BUF_WLANID[9..0] - (RW) Address of queue structure buffer +WLANID. +* Q_BUF_PID[11..10] - (RW) Address of queue structure buffer PID +* FL_BUFFER_ADDR[23..12] - (RW) Frame address of read previous +* frame/next frame +* Q_BUF_QID[30..24] - (RW) Address of queue structure buffer QID +* EXECUTE[31] - (A0) Executes frame link and queue structure +* buffer read command +*/ +#define WF_PLE_TOP_FL_QUE_CTRL_0_EXECUTE_ADDR WF_PLE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_FL_QUE_CTRL_0_EXECUTE_SHFT 31 +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_ADDR WF_PLE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_MASK \ +0x7F000000 /* Q_BUF_QID[30..24] */ +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_SHFT 24 +#define WF_PLE_TOP_FL_QUE_CTRL_0_FL_BUFFER_ADDR_ADDR \ +WF_PLE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_0_FL_BUFFER_ADDR_MASK \ +0x00FFF000 /* FL_BUFFER_ADDR[23..12] */ +#define WF_PLE_TOP_FL_QUE_CTRL_0_FL_BUFFER_ADDR_SHFT 12 +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_ADDR WF_PLE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_MASK \ +0x00000C00 /* Q_BUF_PID[11..10] */ +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_SHFT 10 +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_WLANID_ADDR WF_PLE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_WLANID_MASK \ +0x000003FF /* Q_BUF_WLANID[9..0] */ +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_WLANID_SHFT 0 + +/* +* ---FL_QUE_CTRL_1 (0x820C0000 + 0x1B4)--- +* NEXT_FID[11..0] - (RO) Next frame ID of FL_BUFFER_ADDR +* RESERVED12[15..12] - (RO) Reserved bits +* PREV_FID[27..16] - (RO) Previous frame ID of FL_BUFFER_ADDR +* RESERVED28[30..28] - (RO) Reserved bits +* Q_BUF_TGID[31] - (RW) Address of queue structure buffer TGID +*/ +#define WF_PLE_TOP_FL_QUE_CTRL_1_Q_BUF_TGID_ADDR WF_PLE_TOP_FL_QUE_CTRL_1_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_1_Q_BUF_TGID_MASK 0x80000000 /* Q_BUF_TGID[31]\ + */ +#define WF_PLE_TOP_FL_QUE_CTRL_1_Q_BUF_TGID_SHFT 31 +#define WF_PLE_TOP_FL_QUE_CTRL_1_PREV_FID_ADDR WF_PLE_TOP_FL_QUE_CTRL_1_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_1_PREV_FID_MASK 0x0FFF0000 /* PREV_FID[27..16]\ + */ +#define WF_PLE_TOP_FL_QUE_CTRL_1_PREV_FID_SHFT 16 +#define WF_PLE_TOP_FL_QUE_CTRL_1_NEXT_FID_ADDR WF_PLE_TOP_FL_QUE_CTRL_1_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_1_NEXT_FID_MASK 0x00000FFF /* NEXT_FID[11..0] \ + */ +#define WF_PLE_TOP_FL_QUE_CTRL_1_NEXT_FID_SHFT 0 + +/* +* ---FL_QUE_CTRL_2 (0x820C0000 + 0x1B8)--- +* QUEUE_HEAD_FID[11..0] - (RO) Head frame ID of the quest queue setting +* in 0x01b0[15:0] +* RESERVED12[15..12] - (RO) Reserved bits +* QUEUE_TAIL_FID[27..16] - (RO) Tail frame ID of the quest queue setting +* in 0x01b0[15:0] +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_ADDR \ +WF_PLE_TOP_FL_QUE_CTRL_2_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_MASK \ +0x0FFF0000 /* QUEUE_TAIL_FID[27..16] */ +#define WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_SHFT 16 +#define WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_ADDR \ +WF_PLE_TOP_FL_QUE_CTRL_2_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_MASK \ +0x00000FFF /* QUEUE_HEAD_FID[11..0] */ +#define WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_SHFT 0 + +/* +* ---FL_QUE_CTRL_3 (0x820C0000 + 0x1BC)--- +* QUEUE_PKT_NUM[11..0] - (RO) Total packet number of the queue +* setting in 0x1b0[15:0] +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_ADDR \ +WF_PLE_TOP_FL_QUE_CTRL_3_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_MASK \ +0x00000FFF /* QUEUE_PKT_NUM[11..0] */ +#define WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_SHFT 0 + +/* +* ---PL_QUE_CTRL_0 (0x820C0000 + 0x1C0)--- +* NEXT_PAGE[11..0] - (RO) Next page of PL_BUFFER_ADDR +* RESERVED12[15..12] - (RO) Reserved bits +* PL_BUFFER_ADDR[27..16] - (RW) Page address of read next page +* RESERVED28[30..28] - (RO) Reserved bits +* EXECUTE[31] - (A0) Executes page link buffer read command +*/ +#define WF_PLE_TOP_PL_QUE_CTRL_0_EXECUTE_ADDR WF_PLE_TOP_PL_QUE_CTRL_0_ADDR +#define WF_PLE_TOP_PL_QUE_CTRL_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_PL_QUE_CTRL_0_EXECUTE_SHFT 31 +#define WF_PLE_TOP_PL_QUE_CTRL_0_PL_BUFFER_ADDR_ADDR \ +WF_PLE_TOP_PL_QUE_CTRL_0_ADDR +#define WF_PLE_TOP_PL_QUE_CTRL_0_PL_BUFFER_ADDR_MASK \ +0x0FFF0000 /* PL_BUFFER_ADDR[27..16] */ +#define WF_PLE_TOP_PL_QUE_CTRL_0_PL_BUFFER_ADDR_SHFT 16 +#define WF_PLE_TOP_PL_QUE_CTRL_0_NEXT_PAGE_ADDR WF_PLE_TOP_PL_QUE_CTRL_0_ADDR +#define WF_PLE_TOP_PL_QUE_CTRL_0_NEXT_PAGE_MASK \ +0x00000FFF /* NEXT_PAGE[11..0] */ +#define WF_PLE_TOP_PL_QUE_CTRL_0_NEXT_PAGE_SHFT 0 + +/* +* ---PLE_DELAY_TX_CTRL (0x820C0000 + 0x1d0)--- +* DELAY_TX_PAGE_TH[11..0] - (RW) Delay TX function is used to delay TXD +* be LMAC used. If the total pages of TXD large than page threshold, the delay +TX +* would be released. LMAC would use TXD to TX. +* RESERVED12[15..12] - (RO) Reserved bits +* DELAY_TX_TIMEOUT_TH[23..16] - (RW) Delay TX function is used to delay TXD +* be LMAC used. IF no more enqueue event in the time out threshold, the delay TX +* would be released. LMAC can use TXD to TX. (unit is 32us). +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PLE_DELAY_TX_CTRL_DELAY_TX_TIMEOUT_TH_ADDR \ +WF_PLE_TOP_PLE_DELAY_TX_CTRL_ADDR +#define WF_PLE_TOP_PLE_DELAY_TX_CTRL_DELAY_TX_TIMEOUT_TH_MASK \ +0x00FF0000 /* DELAY_TX_TIMEOUT_TH[23..16] */ +#define WF_PLE_TOP_PLE_DELAY_TX_CTRL_DELAY_TX_TIMEOUT_TH_SHFT 16 +#define WF_PLE_TOP_PLE_DELAY_TX_CTRL_DELAY_TX_PAGE_TH_ADDR \ +WF_PLE_TOP_PLE_DELAY_TX_CTRL_ADDR +#define WF_PLE_TOP_PLE_DELAY_TX_CTRL_DELAY_TX_PAGE_TH_MASK \ +0x00000FFF /* DELAY_TX_PAGE_TH[11..0] */ +#define WF_PLE_TOP_PLE_DELAY_TX_CTRL_DELAY_TX_PAGE_TH_SHFT 0 + +/* +* ---PLE_STATION_REDIR_CTRL (0x820C0000 + 0x1d4)--- +* STA_REDIR_QID[4..0] - (RW) Destitaion queue for Redirection +function. +* RESERVED5[5] - (RO) Reserved bits +* STA_REDIR_PID[7..6] - (RW) Destitaion port for Redirection +function. +* STA_REDIR_PASUE_TXD[8] - (RW) Pause TXD download for avoid race +* condition, when station redirection function turn off. +* RESERVED9[31..9] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_PASUE_TXD_ADDR \ +WF_PLE_TOP_PLE_STATION_REDIR_CTRL_ADDR +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_PASUE_TXD_MASK \ +0x00000100 /* STA_REDIR_PASUE_TXD[8] */ +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_PASUE_TXD_SHFT 8 +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_PID_ADDR \ +WF_PLE_TOP_PLE_STATION_REDIR_CTRL_ADDR +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_PID_MASK \ +0x000000C0 /* STA_REDIR_PID[7..6] */ +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_PID_SHFT 6 +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_QID_ADDR \ +WF_PLE_TOP_PLE_STATION_REDIR_CTRL_ADDR +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_QID_MASK \ +0x0000001F /* STA_REDIR_QID[4..0] */ +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_QID_SHFT 0 + +/* +* ---MACTX_LENGTH_LIMIT (0x820C0000 + 0x1ec)--- +* MACTX_LENGTH_LIMIT_BAND0[15..0] - (RW) MACTX download length limit of band0 +* MACTX_LENGTH_LIMIT_BAND1[31..16] - (RW) MACTX download length limit of band1 +*/ +#define WF_PLE_TOP_MACTX_LENGTH_LIMIT_MACTX_LENGTH_LIMIT_BAND1_ADDR \ +WF_PLE_TOP_MACTX_LENGTH_LIMIT_ADDR +#define WF_PLE_TOP_MACTX_LENGTH_LIMIT_MACTX_LENGTH_LIMIT_BAND1_MASK \ +0xFFFF0000 /* MACTX_LENGTH_LIMIT_BAND1[31..16] */ +#define WF_PLE_TOP_MACTX_LENGTH_LIMIT_MACTX_LENGTH_LIMIT_BAND1_SHFT 16 +#define WF_PLE_TOP_MACTX_LENGTH_LIMIT_MACTX_LENGTH_LIMIT_BAND0_ADDR \ +WF_PLE_TOP_MACTX_LENGTH_LIMIT_ADDR +#define WF_PLE_TOP_MACTX_LENGTH_LIMIT_MACTX_LENGTH_LIMIT_BAND0_MASK \ +0x0000FFFF /* MACTX_LENGTH_LIMIT_BAND0[15..0] */ +#define WF_PLE_TOP_MACTX_LENGTH_LIMIT_MACTX_LENGTH_LIMIT_BAND0_SHFT 0 + +/* +* ---HIF_ENQ_PKT_NUM (0x820C0000 + 0x1f0)--- +* HIF_ENQ_CPU_PKT_NUM[15..0] - (RO) Packet number of HIF enqueue to CPU, +* just keep in 16bits. +* HIF_ENQ_LMAC_PKT_NUM[31..16] - (RO) Packet number of HIF enqueue to LMAC, +* just keep in 16 bits +*/ +#define WF_PLE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_LMAC_PKT_NUM_ADDR \ +WF_PLE_TOP_HIF_ENQ_PKT_NUM_ADDR +#define WF_PLE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_LMAC_PKT_NUM_MASK \ +0xFFFF0000 /* HIF_ENQ_LMAC_PKT_NUM[31..16] */ +#define WF_PLE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_LMAC_PKT_NUM_SHFT 16 +#define WF_PLE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_CPU_PKT_NUM_ADDR \ +WF_PLE_TOP_HIF_ENQ_PKT_NUM_ADDR +#define WF_PLE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_CPU_PKT_NUM_MASK \ +0x0000FFFF /* HIF_ENQ_CPU_PKT_NUM[15..0] */ +#define WF_PLE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_CPU_PKT_NUM_SHFT 0 + +/* +* ---CPU_ENQ_PKT_NUM (0x820C0000 + 0x1f4)--- +* CPU_ENQ_LMAC_PKT_NUM[15..0] - (RO) Packet number of CPU enqueue to LMAC, +* just keep in 16 bits. +* RESV[31..16] - (RO) Reserved +*/ +#define WF_PLE_TOP_CPU_ENQ_PKT_NUM_RESV_ADDR WF_PLE_TOP_CPU_ENQ_PKT_NUM_ADDR +#define WF_PLE_TOP_CPU_ENQ_PKT_NUM_RESV_MASK 0xFFFF0000 /* RESV[31..16] */ +#define WF_PLE_TOP_CPU_ENQ_PKT_NUM_RESV_SHFT 16 +#define WF_PLE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_LMAC_PKT_NUM_ADDR \ +WF_PLE_TOP_CPU_ENQ_PKT_NUM_ADDR +#define WF_PLE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_LMAC_PKT_NUM_MASK \ +0x0000FFFF /* CPU_ENQ_LMAC_PKT_NUM[15..0] */ +#define WF_PLE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_LMAC_PKT_NUM_SHFT 0 + +/* +* ---RLS_MSDU_PKT_NUM (0x820C0000 + 0x1f8)--- +* RSL_RPT_TXD_NUM[15..0] - (RO) TXD number of host report function +* RSL_MSDUID_NUM[31..16] - (RO) Release MSDU_ID number of host report +function +*/ +#define WF_PLE_TOP_RLS_MSDU_PKT_NUM_RSL_MSDUID_NUM_ADDR \ +WF_PLE_TOP_RLS_MSDU_PKT_NUM_ADDR +#define WF_PLE_TOP_RLS_MSDU_PKT_NUM_RSL_MSDUID_NUM_MASK \ +0xFFFF0000 /* RSL_MSDUID_NUM[31..16] */ +#define WF_PLE_TOP_RLS_MSDU_PKT_NUM_RSL_MSDUID_NUM_SHFT 16 +#define WF_PLE_TOP_RLS_MSDU_PKT_NUM_RSL_RPT_TXD_NUM_ADDR \ +WF_PLE_TOP_RLS_MSDU_PKT_NUM_ADDR +#define WF_PLE_TOP_RLS_MSDU_PKT_NUM_RSL_RPT_TXD_NUM_MASK \ +0x0000FFFF /* RSL_RPT_TXD_NUM[15..0] */ +#define WF_PLE_TOP_RLS_MSDU_PKT_NUM_RSL_RPT_TXD_NUM_SHFT 0 + +/* +* ---HOST_REPORT_NUM (0x820C0000 + 0x1fc)--- +* RSL_TXD_NUM[15..0] - (RO) All TXD number of release function, +* include the no host report(not CT) TXD packets. +* HOST_REPORT_NUM[31..16] - (RO) Host report number that be the PSE +* packets carry release MSDU_ID information +*/ +#define WF_PLE_TOP_HOST_REPORT_NUM_HOST_REPORT_NUM_ADDR \ +WF_PLE_TOP_HOST_REPORT_NUM_ADDR +#define WF_PLE_TOP_HOST_REPORT_NUM_HOST_REPORT_NUM_MASK \ +0xFFFF0000 /* HOST_REPORT_NUM[31..16] */ +#define WF_PLE_TOP_HOST_REPORT_NUM_HOST_REPORT_NUM_SHFT 16 +#define WF_PLE_TOP_HOST_REPORT_NUM_RSL_TXD_NUM_ADDR \ +WF_PLE_TOP_HOST_REPORT_NUM_ADDR +#define WF_PLE_TOP_HOST_REPORT_NUM_RSL_TXD_NUM_MASK \ +0x0000FFFF /* RSL_TXD_NUM[15..0] */ +#define WF_PLE_TOP_HOST_REPORT_NUM_RSL_TXD_NUM_SHFT 0 + +/* +* ---TXD_QUEUE_EMPTY (0x820C0000 + 0x220)--- +* AC00_EMPTY[0] - (RO) WMM0 AC0 queue empty status +* AC01_EMPTY[1] - (RO) WMM0 AC1 queue empty status +* AC02_EMPTY[2] - (RO) WMM0 AC2 queue empty status +* AC03_EMPTY[3] - (RO) WMM0 AC3 queue empty status +* AC10_EMPTY[4] - (RO) WMM1 AC0 queue empty status +* AC11_EMPTY[5] - (RO) WMM1 AC1 queue empty status +* AC12_EMPTY[6] - (RO) WMM1 AC2 queue empty status +* AC13_EMPTY[7] - (RO) WMM1 AC3 queue empty status +* AC20_EMPTY[8] - (RO) WMM2 AC0 queue empty status +* AC21_EMPTY[9] - (RO) WMM2 AC1 queue empty status +* AC22_EMPTY[10] - (RO) WMM2 AC2 queue empty status +* AC23_EMPTY[11] - (RO) WMM2 AC3 queue empty status +* AC30_EMPTY[12] - (RO) WMM3 AC0 queue empty status +* AC31_EMPTY[13] - (RO) WMM3 AC1 queue empty status +* AC32_EMPTY[14] - (RO) WMM3 AC2 queue empty status +* AC33_EMPTY[15] - (RO) WMM3 AC3 queue empty status +* ALTX_0_EMPTY[16] - (RO) ALTX queue 0 empty status +* BMC_0_EMPTY[17] - (RO) BMC queue 0 empty status +* BCN_0_EMPTY[18] - (RO) BCN queue 0 empty status +* PSMP_0_EMPTY[19] - (RO) PSMP queue 0 empty status +* ALTX_1_EMPTY[20] - (RO) ALTX queue 1 empty status +* BMC_1_EMPTY[21] - (RO) BMC queue 1 empty status +* BCN_1_EMPTY[22] - (RO) BCN queue 1 empty status +* PSMP_1_EMPTY[23] - (RO) PSMP queue 1 empty status +* NAF_EMPTY[24] - (RO) NAF queue empty status +* NBCN_EMPTY[25] - (RO) NBCN queue empty status +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_NBCN_EMPTY_ADDR \ +WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_NBCN_EMPTY_MASK \ +0x02000000 /* NBCN_EMPTY[25] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_NBCN_EMPTY_SHFT 25 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_NAF_EMPTY_ADDR \ +WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_NAF_EMPTY_MASK 0x01000000 /* NAF_EMPTY[24]\ + */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_NAF_EMPTY_SHFT 24 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_PSMP_1_EMPTY_ADDR \ +WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_PSMP_1_EMPTY_MASK \ +0x00800000 /* PSMP_1_EMPTY[23] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_PSMP_1_EMPTY_SHFT 23 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BCN_1_EMPTY_ADDR \ +WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BCN_1_EMPTY_MASK \ +0x00400000 /* BCN_1_EMPTY[22] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BCN_1_EMPTY_SHFT 22 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BMC_1_EMPTY_ADDR \ +WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BMC_1_EMPTY_MASK \ +0x00200000 /* BMC_1_EMPTY[21] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BMC_1_EMPTY_SHFT 21 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_ALTX_1_EMPTY_ADDR \ +WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_ALTX_1_EMPTY_MASK \ +0x00100000 /* ALTX_1_EMPTY[20] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_ALTX_1_EMPTY_SHFT 20 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_PSMP_0_EMPTY_ADDR \ +WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_PSMP_0_EMPTY_MASK \ +0x00080000 /* PSMP_0_EMPTY[19] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_PSMP_0_EMPTY_SHFT 19 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BCN_0_EMPTY_ADDR \ +WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BCN_0_EMPTY_MASK \ +0x00040000 /* BCN_0_EMPTY[18] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BCN_0_EMPTY_SHFT 18 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BMC_0_EMPTY_ADDR \ +WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BMC_0_EMPTY_MASK \ +0x00020000 /* BMC_0_EMPTY[17] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BMC_0_EMPTY_SHFT 17 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_ALTX_0_EMPTY_ADDR \ +WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_ALTX_0_EMPTY_MASK \ +0x00010000 /* ALTX_0_EMPTY[16] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_ALTX_0_EMPTY_SHFT 16 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC33_EMPTY_ADDR \ +WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC33_EMPTY_MASK \ +0x00008000 /* AC33_EMPTY[15] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC33_EMPTY_SHFT 15 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC32_EMPTY_ADDR \ +WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC32_EMPTY_MASK \ +0x00004000 /* AC32_EMPTY[14] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC32_EMPTY_SHFT 14 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC31_EMPTY_ADDR \ +WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC31_EMPTY_MASK \ +0x00002000 /* AC31_EMPTY[13] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC31_EMPTY_SHFT 13 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC30_EMPTY_ADDR \ +WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC30_EMPTY_MASK \ +0x00001000 /* AC30_EMPTY[12] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC30_EMPTY_SHFT 12 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC23_EMPTY_ADDR \ +WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC23_EMPTY_MASK \ +0x00000800 /* AC23_EMPTY[11] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC23_EMPTY_SHFT 11 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC22_EMPTY_ADDR \ +WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC22_EMPTY_MASK \ +0x00000400 /* AC22_EMPTY[10] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC22_EMPTY_SHFT 10 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC21_EMPTY_ADDR \ +WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC21_EMPTY_MASK \ +0x00000200 /* AC21_EMPTY[9] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC21_EMPTY_SHFT 9 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC20_EMPTY_ADDR \ +WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC20_EMPTY_MASK \ +0x00000100 /* AC20_EMPTY[8] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC20_EMPTY_SHFT 8 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC13_EMPTY_ADDR \ +WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC13_EMPTY_MASK \ +0x00000080 /* AC13_EMPTY[7] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC13_EMPTY_SHFT 7 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC12_EMPTY_ADDR \ +WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC12_EMPTY_MASK \ +0x00000040 /* AC12_EMPTY[6] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC12_EMPTY_SHFT 6 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC11_EMPTY_ADDR \ +WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC11_EMPTY_MASK \ +0x00000020 /* AC11_EMPTY[5] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC11_EMPTY_SHFT 5 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC10_EMPTY_ADDR \ +WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC10_EMPTY_MASK \ +0x00000010 /* AC10_EMPTY[4] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC10_EMPTY_SHFT 4 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC03_EMPTY_ADDR \ +WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC03_EMPTY_MASK \ +0x00000008 /* AC03_EMPTY[3] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC03_EMPTY_SHFT 3 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC02_EMPTY_ADDR \ +WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC02_EMPTY_MASK \ +0x00000004 /* AC02_EMPTY[2] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC02_EMPTY_SHFT 2 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC01_EMPTY_ADDR \ +WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC01_EMPTY_MASK \ +0x00000002 /* AC01_EMPTY[1] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC01_EMPTY_SHFT 1 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC00_EMPTY_ADDR \ +WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC00_EMPTY_MASK \ +0x00000001 /* AC00_EMPTY[0] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC00_EMPTY_SHFT 0 + +/* +* ---TXS_BUF_PAUSE (0x820C0000 + 0x224)--- +* EN_PAUSE_AC00_QUEUE[0] - (RW) Pause control of WMM0 AC0 queue. +* EN_PAUSE_AC01_QUEUE[1] - (RW) Pause control of WMM0 AC1 queue. +* EN_PAUSE_AC02_QUEUE[2] - (RW) Pause control of WMM0 AC2 queue. +* EN_PAUSE_AC03_QUEUE[3] - (RW) Pause control of WMM0 AC3 queue. +* EN_PAUSE_AC10_QUEUE[4] - (RW) Pause control of WMM1 AC0 queue. +* EN_PAUSE_AC11_QUEUE[5] - (RW) Pause control of WMM1 AC1 queue. +* EN_PAUSE_AC12_QUEUE[6] - (RW) Pause control of WMM1 AC2 queue. +* EN_PAUSE_AC13_QUEUE[7] - (RW) Pause control of WMM1 AC3 queue. +* EN_PAUSE_AC20_QUEUE[8] - (RW) Pause control of WMM2 AC0 queue. +* EN_PAUSE_AC21_QUEUE[9] - (RW) Pause control of WMM2 AC1 queue. +* EN_PAUSE_AC22_QUEUE[10] - (RW) Pause control of WMM2 AC2 queue. +* EN_PAUSE_AC23_QUEUE[11] - (RW) Pause control of WMM2 AC3 queue. +* EN_PAUSE_AC30_QUEUE[12] - (RW) Pause control of WMM3 AC0 queue. +* EN_PAUSE_AC31_QUEUE[13] - (RW) Pause control of WMM3 AC1 queue. +* EN_PAUSE_AC32_QUEUE[14] - (RW) Pause control of WMM3 AC2 queue. +* EN_PAUSE_AC33_QUEUE[15] - (RW) Pause control of WMM3 AC3 queue. +* EN_PAUSE_ALTX_0_QUEUE[16] - (RW) Pause control of ALTX queue 0. +* EN_PAUSE_BMC_0_QUEUE[17] - (RW) Pause control of BMC queue 0. +* EN_PAUSE_BCN_0_QUEUE[18] - (RW) Pause control of BCN queue 0. +* EN_PAUSE_PSMP_0_QUEUE[19] - (RW) Pause control of PSMP queue 0. +* EN_PAUSE_ALTX_1_QUEUE[20] - (RW) Pause control of ALTX queue 1. +* EN_PAUSE_BMC_1_QUEUE[21] - (RW) Pause control of BMC queue 1. +* EN_PAUSE_BCN_1_QUEUE[22] - (RW) Pause control of BCN queue 1. +* EN_PAUSE_PSMP_1_QUEUE[23] - (RW) Pause control of PSMP queue 1. +* EN_PAUSE_NAF_QUEUE[24] - (RW) Pause control of NAF queue. +* EN_PAUSE_NBCN_QUEUE[25] - (RW) Pause control of NBCN queue. +* RESERVED26[30..26] - (RO) Reserved bits +* PSE_TXS_BUF_VALID[31] - (RO) PSE TXS buffer status. +*/ +#define WF_PLE_TOP_TXS_BUF_PAUSE_PSE_TXS_BUF_VALID_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_PSE_TXS_BUF_VALID_MASK \ +0x80000000 /* PSE_TXS_BUF_VALID[31] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_PSE_TXS_BUF_VALID_SHFT 31 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_NBCN_QUEUE_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_NBCN_QUEUE_MASK \ +0x02000000 /* EN_PAUSE_NBCN_QUEUE[25] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_NBCN_QUEUE_SHFT 25 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_NAF_QUEUE_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_NAF_QUEUE_MASK \ +0x01000000 /* EN_PAUSE_NAF_QUEUE[24] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_NAF_QUEUE_SHFT 24 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_PSMP_1_QUEUE_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_PSMP_1_QUEUE_MASK \ +0x00800000 /* EN_PAUSE_PSMP_1_QUEUE[23] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_PSMP_1_QUEUE_SHFT 23 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BCN_1_QUEUE_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BCN_1_QUEUE_MASK \ +0x00400000 /* EN_PAUSE_BCN_1_QUEUE[22] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BCN_1_QUEUE_SHFT 22 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BMC_1_QUEUE_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BMC_1_QUEUE_MASK \ +0x00200000 /* EN_PAUSE_BMC_1_QUEUE[21] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BMC_1_QUEUE_SHFT 21 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_ALTX_1_QUEUE_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_ALTX_1_QUEUE_MASK \ +0x00100000 /* EN_PAUSE_ALTX_1_QUEUE[20] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_ALTX_1_QUEUE_SHFT 20 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_PSMP_0_QUEUE_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_PSMP_0_QUEUE_MASK \ +0x00080000 /* EN_PAUSE_PSMP_0_QUEUE[19] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_PSMP_0_QUEUE_SHFT 19 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BCN_0_QUEUE_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BCN_0_QUEUE_MASK \ +0x00040000 /* EN_PAUSE_BCN_0_QUEUE[18] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BCN_0_QUEUE_SHFT 18 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BMC_0_QUEUE_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BMC_0_QUEUE_MASK \ +0x00020000 /* EN_PAUSE_BMC_0_QUEUE[17] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BMC_0_QUEUE_SHFT 17 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_ALTX_0_QUEUE_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_ALTX_0_QUEUE_MASK \ +0x00010000 /* EN_PAUSE_ALTX_0_QUEUE[16] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_ALTX_0_QUEUE_SHFT 16 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC33_QUEUE_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC33_QUEUE_MASK \ +0x00008000 /* EN_PAUSE_AC33_QUEUE[15] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC33_QUEUE_SHFT 15 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC32_QUEUE_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC32_QUEUE_MASK \ +0x00004000 /* EN_PAUSE_AC32_QUEUE[14] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC32_QUEUE_SHFT 14 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC31_QUEUE_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC31_QUEUE_MASK \ +0x00002000 /* EN_PAUSE_AC31_QUEUE[13] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC31_QUEUE_SHFT 13 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC30_QUEUE_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC30_QUEUE_MASK \ +0x00001000 /* EN_PAUSE_AC30_QUEUE[12] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC30_QUEUE_SHFT 12 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC23_QUEUE_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC23_QUEUE_MASK \ +0x00000800 /* EN_PAUSE_AC23_QUEUE[11] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC23_QUEUE_SHFT 11 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC22_QUEUE_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC22_QUEUE_MASK \ +0x00000400 /* EN_PAUSE_AC22_QUEUE[10] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC22_QUEUE_SHFT 10 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC21_QUEUE_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC21_QUEUE_MASK \ +0x00000200 /* EN_PAUSE_AC21_QUEUE[9] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC21_QUEUE_SHFT 9 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC20_QUEUE_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC20_QUEUE_MASK \ +0x00000100 /* EN_PAUSE_AC20_QUEUE[8] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC20_QUEUE_SHFT 8 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC13_QUEUE_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC13_QUEUE_MASK \ +0x00000080 /* EN_PAUSE_AC13_QUEUE[7] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC13_QUEUE_SHFT 7 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC12_QUEUE_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC12_QUEUE_MASK \ +0x00000040 /* EN_PAUSE_AC12_QUEUE[6] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC12_QUEUE_SHFT 6 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC11_QUEUE_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC11_QUEUE_MASK \ +0x00000020 /* EN_PAUSE_AC11_QUEUE[5] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC11_QUEUE_SHFT 5 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC10_QUEUE_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC10_QUEUE_MASK \ +0x00000010 /* EN_PAUSE_AC10_QUEUE[4] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC10_QUEUE_SHFT 4 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC03_QUEUE_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC03_QUEUE_MASK \ +0x00000008 /* EN_PAUSE_AC03_QUEUE[3] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC03_QUEUE_SHFT 3 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC02_QUEUE_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC02_QUEUE_MASK \ +0x00000004 /* EN_PAUSE_AC02_QUEUE[2] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC02_QUEUE_SHFT 2 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC01_QUEUE_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC01_QUEUE_MASK \ +0x00000002 /* EN_PAUSE_AC01_QUEUE[1] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC01_QUEUE_SHFT 1 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC00_QUEUE_ADDR \ +WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC00_QUEUE_MASK \ +0x00000001 /* EN_PAUSE_AC00_QUEUE[0] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC00_QUEUE_SHFT 0 + +/* +* ---NATIVE_TXD_QUEUE_EMPTY (0x820C0000 + 0x228)--- +* AC00_EMPTY[0] - (RO) WMM0 AC0 queue empty status +* AC01_EMPTY[1] - (RO) WMM0 AC1 queue empty status +* AC02_EMPTY[2] - (RO) WMM0 AC2 queue empty status +* AC03_EMPTY[3] - (RO) WMM0 AC3 queue empty status +* AC10_EMPTY[4] - (RO) WMM1 AC0 queue empty status +* AC11_EMPTY[5] - (RO) WMM1 AC1 queue empty status +* AC12_EMPTY[6] - (RO) WMM1 AC2 queue empty status +* AC13_EMPTY[7] - (RO) WMM1 AC3 queue empty status +* AC20_EMPTY[8] - (RO) WMM2 AC0 queue empty status +* AC21_EMPTY[9] - (RO) WMM2 AC1 queue empty status +* AC22_EMPTY[10] - (RO) WMM2 AC2 queue empty status +* AC23_EMPTY[11] - (RO) WMM2 AC3 queue empty status +* AC30_EMPTY[12] - (RO) WMM3 AC0 queue empty status +* AC31_EMPTY[13] - (RO) WMM3 AC1 queue empty status +* AC32_EMPTY[14] - (RO) WMM3 AC2 queue empty status +* AC33_EMPTY[15] - (RO) WMM3 AC3 queue empty status +* ALTX_0_EMPTY[16] - (RO) ALTX queue 0 empty status +* BMC_0_EMPTY[17] - (RO) BMC queue 0 empty status +* BCN_0_EMPTY[18] - (RO) BCN queue 0 empty status +* PSMP_0_EMPTY[19] - (RO) PSMP queue 0 empty status +* ALTX_1_EMPTY[20] - (RO) ALTX queue 1 empty status +* BMC_1_EMPTY[21] - (RO) BMC queue 1 empty status +* BCN_1_EMPTY[22] - (RO) BCN queue 1 empty status +* PSMP_1_EMPTY[23] - (RO) PSMP queue 1 empty status +* NAF_EMPTY[24] - (RO) NAF queue empty status +* NBCN_EMPTY[25] - (RO) NBCN queue empty status +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_NBCN_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_NBCN_EMPTY_MASK \ +0x02000000 /* NBCN_EMPTY[25] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_NBCN_EMPTY_SHFT 25 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_NAF_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_NAF_EMPTY_MASK \ +0x01000000 /* NAF_EMPTY[24] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_NAF_EMPTY_SHFT 24 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_PSMP_1_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_PSMP_1_EMPTY_MASK \ +0x00800000 /* PSMP_1_EMPTY[23] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_PSMP_1_EMPTY_SHFT 23 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BCN_1_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BCN_1_EMPTY_MASK \ +0x00400000 /* BCN_1_EMPTY[22] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BCN_1_EMPTY_SHFT 22 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BMC_1_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BMC_1_EMPTY_MASK \ +0x00200000 /* BMC_1_EMPTY[21] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BMC_1_EMPTY_SHFT 21 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ALTX_1_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ALTX_1_EMPTY_MASK \ +0x00100000 /* ALTX_1_EMPTY[20] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ALTX_1_EMPTY_SHFT 20 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_PSMP_0_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_PSMP_0_EMPTY_MASK \ +0x00080000 /* PSMP_0_EMPTY[19] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_PSMP_0_EMPTY_SHFT 19 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BCN_0_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BCN_0_EMPTY_MASK \ +0x00040000 /* BCN_0_EMPTY[18] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BCN_0_EMPTY_SHFT 18 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BMC_0_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BMC_0_EMPTY_MASK \ +0x00020000 /* BMC_0_EMPTY[17] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BMC_0_EMPTY_SHFT 17 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ALTX_0_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ALTX_0_EMPTY_MASK \ +0x00010000 /* ALTX_0_EMPTY[16] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ALTX_0_EMPTY_SHFT 16 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC33_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC33_EMPTY_MASK \ +0x00008000 /* AC33_EMPTY[15] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC33_EMPTY_SHFT 15 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC32_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC32_EMPTY_MASK \ +0x00004000 /* AC32_EMPTY[14] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC32_EMPTY_SHFT 14 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC31_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC31_EMPTY_MASK \ +0x00002000 /* AC31_EMPTY[13] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC31_EMPTY_SHFT 13 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC30_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC30_EMPTY_MASK \ +0x00001000 /* AC30_EMPTY[12] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC30_EMPTY_SHFT 12 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC23_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC23_EMPTY_MASK \ +0x00000800 /* AC23_EMPTY[11] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC23_EMPTY_SHFT 11 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC22_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC22_EMPTY_MASK \ +0x00000400 /* AC22_EMPTY[10] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC22_EMPTY_SHFT 10 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC21_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC21_EMPTY_MASK \ +0x00000200 /* AC21_EMPTY[9] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC21_EMPTY_SHFT 9 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC20_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC20_EMPTY_MASK \ +0x00000100 /* AC20_EMPTY[8] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC20_EMPTY_SHFT 8 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC13_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC13_EMPTY_MASK \ +0x00000080 /* AC13_EMPTY[7] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC13_EMPTY_SHFT 7 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC12_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC12_EMPTY_MASK \ +0x00000040 /* AC12_EMPTY[6] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC12_EMPTY_SHFT 6 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC11_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC11_EMPTY_MASK \ +0x00000020 /* AC11_EMPTY[5] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC11_EMPTY_SHFT 5 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC10_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC10_EMPTY_MASK \ +0x00000010 /* AC10_EMPTY[4] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC10_EMPTY_SHFT 4 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC03_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC03_EMPTY_MASK \ +0x00000008 /* AC03_EMPTY[3] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC03_EMPTY_SHFT 3 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC02_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC02_EMPTY_MASK \ +0x00000004 /* AC02_EMPTY[2] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC02_EMPTY_SHFT 2 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC01_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC01_EMPTY_MASK \ +0x00000002 /* AC01_EMPTY[1] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC01_EMPTY_SHFT 1 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC00_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC00_EMPTY_MASK \ +0x00000001 /* AC00_EMPTY[0] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC00_EMPTY_SHFT 0 + +/* +* ---NATIVE_TXCMD_QUEUE_EMPTY (0x820C0000 + 0x22c)--- +* AC00_TXCMD_EMPTY[0] - (RO) WMM0 AC0 TXCMD queue empty status +* AC01_TXCMD_EMPTY[1] - (RO) WMM0 AC1 TXCMD queue empty status +* AC02_TXCMD_EMPTY[2] - (RO) WMM0 AC2 TXCMD queue empty status +* AC03_TXCMD_EMPTY[3] - (RO) WMM0 AC3 TXCMD queue empty status +* AC10_TXCMD_EMPTY[4] - (RO) WMM1 AC0 TXCMD queue empty status +* AC11_TXCMD_EMPTY[5] - (RO) WMM1 AC1 TXCMD queue empty status +* AC12_TXCMD_EMPTY[6] - (RO) WMM1 AC2 TXCMD queue empty status +* AC13_TXCMD_EMPTY[7] - (RO) WMM1 AC3 TXCMD queue empty status +* AC20_TXCMD_EMPTY[8] - (RO) WMM2 AC0 TXCMD queue empty status +* AC21_TXCMD_EMPTY[9] - (RO) WMM2 AC1 TXCMD queue empty status +* AC22_TXCMD_EMPTY[10] - (RO) WMM2 AC2 TXCMD queue empty status +* AC23_TXCMD_EMPTY[11] - (RO) WMM2 AC3 TXCMD queue empty status +* AC30_TXCMD_EMPTY[12] - (RO) WMM3 AC0 TXCMD queue empty status +* AC31_TXCMD_EMPTY[13] - (RO) WMM3 AC1 TXCMD queue empty status +* AC32_TXCMD_EMPTY[14] - (RO) WMM3 AC2 TXCMD queue empty status +* AC33_TXCMD_EMPTY[15] - (RO) WMM3 AC3 TXCMD queue empty status +* ALTXCMD_0_EMPTY[16] - (RO) ALTXCMD 0 queue empty status +* TF_0_EMPTY[17] - (RO) TF 0 queue empty status +* TWT_TSF_TF_0_EMPTY[18] - (RO) TWT TSF-TF 0 queue empty status +* TWT_DL_0_EMPTY[19] - (RO) TWT DL 0 queue empty status +* TWT_UL_0_EMPTY[20] - (RO) TWT UL 0 queue empty status +* ALTXCMD_1_EMPTY[21] - (RO) ALTXCMD 1 queue empty status +* TF_1_EMPTY[22] - (RO) TF 1 queue empty status +* TWT_TSF_TF_1_EMPTY[23] - (RO) TWT TSF-TF 1 queue empty status +* TWT_DL_1_EMPTY[24] - (RO) TWT DL 1 queue empty status +* TWT_UL_1_EMPTY[25] - (RO) TWT UL 1 queue empty status +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_TWT_UL_1_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_TWT_UL_1_EMPTY_MASK \ +0x02000000 /* TWT_UL_1_EMPTY[25] */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_TWT_UL_1_EMPTY_SHFT 25 +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_TWT_DL_1_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_TWT_DL_1_EMPTY_MASK \ +0x01000000 /* TWT_DL_1_EMPTY[24] */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_TWT_DL_1_EMPTY_SHFT 24 +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_TWT_TSF_TF_1_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_TWT_TSF_TF_1_EMPTY_MASK \ +0x00800000 /* TWT_TSF_TF_1_EMPTY[23] */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_TWT_TSF_TF_1_EMPTY_SHFT 23 +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_TF_1_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_TF_1_EMPTY_MASK \ +0x00400000 /* TF_1_EMPTY[22] */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_TF_1_EMPTY_SHFT 22 +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ALTXCMD_1_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ALTXCMD_1_EMPTY_MASK \ +0x00200000 /* ALTXCMD_1_EMPTY[21] */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ALTXCMD_1_EMPTY_SHFT 21 +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_TWT_UL_0_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_TWT_UL_0_EMPTY_MASK \ +0x00100000 /* TWT_UL_0_EMPTY[20] */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_TWT_UL_0_EMPTY_SHFT 20 +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_TWT_DL_0_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_TWT_DL_0_EMPTY_MASK \ +0x00080000 /* TWT_DL_0_EMPTY[19] */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_TWT_DL_0_EMPTY_SHFT 19 +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_TWT_TSF_TF_0_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_TWT_TSF_TF_0_EMPTY_MASK \ +0x00040000 /* TWT_TSF_TF_0_EMPTY[18] */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_TWT_TSF_TF_0_EMPTY_SHFT 18 +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_TF_0_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_TF_0_EMPTY_MASK \ +0x00020000 /* TF_0_EMPTY[17] */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_TF_0_EMPTY_SHFT 17 +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ALTXCMD_0_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ALTXCMD_0_EMPTY_MASK \ +0x00010000 /* ALTXCMD_0_EMPTY[16] */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ALTXCMD_0_EMPTY_SHFT 16 +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC33_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC33_TXCMD_EMPTY_MASK \ +0x00008000 /* AC33_TXCMD_EMPTY[15] */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC33_TXCMD_EMPTY_SHFT 15 +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC32_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC32_TXCMD_EMPTY_MASK \ +0x00004000 /* AC32_TXCMD_EMPTY[14] */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC32_TXCMD_EMPTY_SHFT 14 +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC31_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC31_TXCMD_EMPTY_MASK \ +0x00002000 /* AC31_TXCMD_EMPTY[13] */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC31_TXCMD_EMPTY_SHFT 13 +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC30_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC30_TXCMD_EMPTY_MASK \ +0x00001000 /* AC30_TXCMD_EMPTY[12] */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC30_TXCMD_EMPTY_SHFT 12 +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC23_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC23_TXCMD_EMPTY_MASK \ +0x00000800 /* AC23_TXCMD_EMPTY[11] */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC23_TXCMD_EMPTY_SHFT 11 +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC22_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC22_TXCMD_EMPTY_MASK \ +0x00000400 /* AC22_TXCMD_EMPTY[10] */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC22_TXCMD_EMPTY_SHFT 10 +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC21_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC21_TXCMD_EMPTY_MASK \ +0x00000200 /* AC21_TXCMD_EMPTY[9] */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC21_TXCMD_EMPTY_SHFT 9 +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC20_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC20_TXCMD_EMPTY_MASK \ +0x00000100 /* AC20_TXCMD_EMPTY[8] */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC20_TXCMD_EMPTY_SHFT 8 +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC13_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC13_TXCMD_EMPTY_MASK \ +0x00000080 /* AC13_TXCMD_EMPTY[7] */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC13_TXCMD_EMPTY_SHFT 7 +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC12_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC12_TXCMD_EMPTY_MASK \ +0x00000040 /* AC12_TXCMD_EMPTY[6] */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC12_TXCMD_EMPTY_SHFT 6 +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC11_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC11_TXCMD_EMPTY_MASK \ +0x00000020 /* AC11_TXCMD_EMPTY[5] */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC11_TXCMD_EMPTY_SHFT 5 +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC10_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC10_TXCMD_EMPTY_MASK \ +0x00000010 /* AC10_TXCMD_EMPTY[4] */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC10_TXCMD_EMPTY_SHFT 4 +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC03_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC03_TXCMD_EMPTY_MASK \ +0x00000008 /* AC03_TXCMD_EMPTY[3] */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC03_TXCMD_EMPTY_SHFT 3 +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC02_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC02_TXCMD_EMPTY_MASK \ +0x00000004 /* AC02_TXCMD_EMPTY[2] */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC02_TXCMD_EMPTY_SHFT 2 +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC01_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC01_TXCMD_EMPTY_MASK \ +0x00000002 /* AC01_TXCMD_EMPTY[1] */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC01_TXCMD_EMPTY_SHFT 1 +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC00_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC00_TXCMD_EMPTY_MASK \ +0x00000001 /* AC00_TXCMD_EMPTY[0] */ +#define WF_PLE_TOP_NATIVE_TXCMD_QUEUE_EMPTY_AC00_TXCMD_EMPTY_SHFT 0 + +/* +* ---TXCMD_QUEUE_EMPTY (0x820C0000 + 0x230)--- +* AC00_TXCMD_EMPTY[0] - (RO) WMM0 AC0 TXCMD queue empty status +* AC01_TXCMD_EMPTY[1] - (RO) WMM0 AC1 TXCMD queue empty status +* AC02_TXCMD_EMPTY[2] - (RO) WMM0 AC2 TXCMD queue empty status +* AC03_TXCMD_EMPTY[3] - (RO) WMM0 AC3 TXCMD queue empty status +* AC10_TXCMD_EMPTY[4] - (RO) WMM1 AC0 TXCMD queue empty status +* AC11_TXCMD_EMPTY[5] - (RO) WMM1 AC1 TXCMD queue empty status +* AC12_TXCMD_EMPTY[6] - (RO) WMM1 AC2 TXCMD queue empty status +* AC13_TXCMD_EMPTY[7] - (RO) WMM1 AC3 TXCMD queue empty status +* AC20_TXCMD_EMPTY[8] - (RO) WMM2 AC0 TXCMD queue empty status +* AC21_TXCMD_EMPTY[9] - (RO) WMM2 AC1 TXCMD queue empty status +* AC22_TXCMD_EMPTY[10] - (RO) WMM2 AC2 TXCMD queue empty status +* AC23_TXCMD_EMPTY[11] - (RO) WMM2 AC3 TXCMD queue empty status +* AC30_TXCMD_EMPTY[12] - (RO) WMM3 AC0 TXCMD queue empty status +* AC31_TXCMD_EMPTY[13] - (RO) WMM3 AC1 TXCMD queue empty status +* AC32_TXCMD_EMPTY[14] - (RO) WMM3 AC2 TXCMD queue empty status +* AC33_TXCMD_EMPTY[15] - (RO) WMM3 AC3 TXCMD queue empty status +* ALTXCMD_0_EMPTY[16] - (RO) ALTXCMD 0 queue empty status +* TF_0_EMPTY[17] - (RO) TF 0 queue empty status +* TWT_TSF_TF_0_EMPTY[18] - (RO) TWT TSF-TF 0 queue empty status +* TWT_DL_0_EMPTY[19] - (RO) TWT DL 0 queue empty status +* TWT_UL_0_EMPTY[20] - (RO) TWT UL 0 queue empty status +* ALTXCMD_1_EMPTY[21] - (RO) ALTXCMD 1 queue empty status +* TF_1_EMPTY[22] - (RO) TF 1 queue empty status +* TWT_TSF_TF_1_EMPTY[23] - (RO) TWT TSF-TF 1 queue empty status +* TWT_DL_1_EMPTY[24] - (RO) TWT DL 1 queue empty status +* TWT_UL_1_EMPTY[25] - (RO) TWT UL 1 queue empty status +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_TWT_UL_1_EMPTY_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_TWT_UL_1_EMPTY_MASK \ +0x02000000 /* TWT_UL_1_EMPTY[25] */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_TWT_UL_1_EMPTY_SHFT 25 +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_TWT_DL_1_EMPTY_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_TWT_DL_1_EMPTY_MASK \ +0x01000000 /* TWT_DL_1_EMPTY[24] */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_TWT_DL_1_EMPTY_SHFT 24 +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_TWT_TSF_TF_1_EMPTY_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_TWT_TSF_TF_1_EMPTY_MASK \ +0x00800000 /* TWT_TSF_TF_1_EMPTY[23] */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_TWT_TSF_TF_1_EMPTY_SHFT 23 +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_TF_1_EMPTY_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_TF_1_EMPTY_MASK \ +0x00400000 /* TF_1_EMPTY[22] */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_TF_1_EMPTY_SHFT 22 +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ALTXCMD_1_EMPTY_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ALTXCMD_1_EMPTY_MASK \ +0x00200000 /* ALTXCMD_1_EMPTY[21] */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ALTXCMD_1_EMPTY_SHFT 21 +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_TWT_UL_0_EMPTY_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_TWT_UL_0_EMPTY_MASK \ +0x00100000 /* TWT_UL_0_EMPTY[20] */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_TWT_UL_0_EMPTY_SHFT 20 +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_TWT_DL_0_EMPTY_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_TWT_DL_0_EMPTY_MASK \ +0x00080000 /* TWT_DL_0_EMPTY[19] */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_TWT_DL_0_EMPTY_SHFT 19 +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_TWT_TSF_TF_0_EMPTY_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_TWT_TSF_TF_0_EMPTY_MASK \ +0x00040000 /* TWT_TSF_TF_0_EMPTY[18] */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_TWT_TSF_TF_0_EMPTY_SHFT 18 +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_TF_0_EMPTY_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_TF_0_EMPTY_MASK \ +0x00020000 /* TF_0_EMPTY[17] */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_TF_0_EMPTY_SHFT 17 +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ALTXCMD_0_EMPTY_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ALTXCMD_0_EMPTY_MASK \ +0x00010000 /* ALTXCMD_0_EMPTY[16] */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ALTXCMD_0_EMPTY_SHFT 16 +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC33_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC33_TXCMD_EMPTY_MASK \ +0x00008000 /* AC33_TXCMD_EMPTY[15] */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC33_TXCMD_EMPTY_SHFT 15 +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC32_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC32_TXCMD_EMPTY_MASK \ +0x00004000 /* AC32_TXCMD_EMPTY[14] */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC32_TXCMD_EMPTY_SHFT 14 +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC31_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC31_TXCMD_EMPTY_MASK \ +0x00002000 /* AC31_TXCMD_EMPTY[13] */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC31_TXCMD_EMPTY_SHFT 13 +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC30_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC30_TXCMD_EMPTY_MASK \ +0x00001000 /* AC30_TXCMD_EMPTY[12] */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC30_TXCMD_EMPTY_SHFT 12 +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC23_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC23_TXCMD_EMPTY_MASK \ +0x00000800 /* AC23_TXCMD_EMPTY[11] */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC23_TXCMD_EMPTY_SHFT 11 +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC22_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC22_TXCMD_EMPTY_MASK \ +0x00000400 /* AC22_TXCMD_EMPTY[10] */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC22_TXCMD_EMPTY_SHFT 10 +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC21_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC21_TXCMD_EMPTY_MASK \ +0x00000200 /* AC21_TXCMD_EMPTY[9] */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC21_TXCMD_EMPTY_SHFT 9 +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC20_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC20_TXCMD_EMPTY_MASK \ +0x00000100 /* AC20_TXCMD_EMPTY[8] */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC20_TXCMD_EMPTY_SHFT 8 +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC13_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC13_TXCMD_EMPTY_MASK \ +0x00000080 /* AC13_TXCMD_EMPTY[7] */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC13_TXCMD_EMPTY_SHFT 7 +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC12_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC12_TXCMD_EMPTY_MASK \ +0x00000040 /* AC12_TXCMD_EMPTY[6] */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC12_TXCMD_EMPTY_SHFT 6 +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC11_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC11_TXCMD_EMPTY_MASK \ +0x00000020 /* AC11_TXCMD_EMPTY[5] */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC11_TXCMD_EMPTY_SHFT 5 +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC10_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC10_TXCMD_EMPTY_MASK \ +0x00000010 /* AC10_TXCMD_EMPTY[4] */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC10_TXCMD_EMPTY_SHFT 4 +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC03_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC03_TXCMD_EMPTY_MASK \ +0x00000008 /* AC03_TXCMD_EMPTY[3] */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC03_TXCMD_EMPTY_SHFT 3 +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC02_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC02_TXCMD_EMPTY_MASK \ +0x00000004 /* AC02_TXCMD_EMPTY[2] */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC02_TXCMD_EMPTY_SHFT 2 +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC01_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC01_TXCMD_EMPTY_MASK \ +0x00000002 /* AC01_TXCMD_EMPTY[1] */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC01_TXCMD_EMPTY_SHFT 1 +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC00_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC00_TXCMD_EMPTY_MASK \ +0x00000001 /* AC00_TXCMD_EMPTY[0] */ +#define WF_PLE_TOP_TXCMD_QUEUE_EMPTY_AC00_TXCMD_EMPTY_SHFT 0 + +/* +* ---TXCMD_QUEUE_PAUSE (0x820C0000 + 0x234)--- +* EN_PAUSE_AC00_QUEUE[0] - (RW) Pause control of WMM0 AC0 TXCMD queue. +* EN_PAUSE_AC01_QUEUE[1] - (RW) Pause control of WMM0 AC1 TXCMD queue. +* EN_PAUSE_AC02_QUEUE[2] - (RW) Pause control of WMM0 AC2 TXCMD queue. +* EN_PAUSE_AC03_QUEUE[3] - (RW) Pause control of WMM0 AC3 TXCMD queue. +* EN_PAUSE_AC10_QUEUE[4] - (RW) Pause control of WMM1 AC0 TXCMD queue. +* EN_PAUSE_AC11_QUEUE[5] - (RW) Pause control of WMM1 AC1 TXCMD queue. +* EN_PAUSE_AC12_QUEUE[6] - (RW) Pause control of WMM1 AC2 TXCMD queue. +* EN_PAUSE_AC13_QUEUE[7] - (RW) Pause control of WMM1 AC3 TXCMD queue. +* EN_PAUSE_AC20_QUEUE[8] - (RW) Pause control of WMM2 AC0 TXCMD queue. +* EN_PAUSE_AC21_QUEUE[9] - (RW) Pause control of WMM2 AC1 TXCMD queue. +* EN_PAUSE_AC22_QUEUE[10] - (RW) Pause control of WMM2 AC2 TXCMD queue. +* EN_PAUSE_AC23_QUEUE[11] - (RW) Pause control of WMM2 AC3 TXCMD queue. +* EN_PAUSE_AC30_QUEUE[12] - (RW) Pause control of WMM3 AC0 TXCMD queue. +* EN_PAUSE_AC31_QUEUE[13] - (RW) Pause control of WMM3 AC1 TXCMD queue. +* EN_PAUSE_AC32_QUEUE[14] - (RW) Pause control of WMM3 AC2 TXCMD queue. +* EN_PAUSE_AC33_QUEUE[15] - (RW) Pause control of WMM3 AC3 TXCMD queue. +* EN_PAUSE_ALTXCMD_0_QUEUE[16] - (RW) Pause control of ALTXCMD 0 queue. +* EN_PAUSE_TF_0_QUEUE[17] - (RW) Pause control of TF 0 TXCDM queue . +* EN_PAUSE_TWT_TSF_TF_0_QUEUE[18] - (RW) Pause control of TWT TSF TF 0 TXCMD +queue. +* EN_PAUSE_TWT_DL_0_QUEUE[19] - (RW) Pause control of TWT DL 0 TXCMD queue. +* EN_PAUSE_TWT_UL_0_QUEUE[20] - (RW) Pause control of TWT UL 0 TXCMD queue. +* EN_PAUSE_ALTXCMD_1_QUEUE[21] - (RW) Pause control of ALTXCMD 1 queue. +* EN_PAUSE_TF_1_QUEUE[22] - (RW) Pause control of TF 1 TXCDM queue . +* EN_PAUSE_TWT_TSF_TF_1_QUEUE[23] - (RW) Pause control of TWT TSF TF 1 TXCMD +queue. +* EN_PAUSE_TWT_DL_1_QUEUE[24] - (RW) Pause control of TWT DL 1 TXCMD queue. +* EN_PAUSE_TWT_UL_1_QUEUE[25] - (RW) Pause control of TWT UL 1 TXCMD queue. +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_TWT_UL_1_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_TWT_UL_1_QUEUE_MASK \ +0x02000000 /* EN_PAUSE_TWT_UL_1_QUEUE[25] */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_TWT_UL_1_QUEUE_SHFT 25 +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_TWT_DL_1_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_TWT_DL_1_QUEUE_MASK \ +0x01000000 /* EN_PAUSE_TWT_DL_1_QUEUE[24] */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_TWT_DL_1_QUEUE_SHFT 24 +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_TWT_TSF_TF_1_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_TWT_TSF_TF_1_QUEUE_MASK \ +0x00800000 /* EN_PAUSE_TWT_TSF_TF_1_QUEUE[23] */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_TWT_TSF_TF_1_QUEUE_SHFT 23 +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_TF_1_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_TF_1_QUEUE_MASK \ +0x00400000 /* EN_PAUSE_TF_1_QUEUE[22] */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_TF_1_QUEUE_SHFT 22 +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_ALTXCMD_1_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_ALTXCMD_1_QUEUE_MASK \ +0x00200000 /* EN_PAUSE_ALTXCMD_1_QUEUE[21] */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_ALTXCMD_1_QUEUE_SHFT 21 +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_TWT_UL_0_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_TWT_UL_0_QUEUE_MASK \ +0x00100000 /* EN_PAUSE_TWT_UL_0_QUEUE[20] */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_TWT_UL_0_QUEUE_SHFT 20 +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_TWT_DL_0_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_TWT_DL_0_QUEUE_MASK \ +0x00080000 /* EN_PAUSE_TWT_DL_0_QUEUE[19] */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_TWT_DL_0_QUEUE_SHFT 19 +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_TWT_TSF_TF_0_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_TWT_TSF_TF_0_QUEUE_MASK \ +0x00040000 /* EN_PAUSE_TWT_TSF_TF_0_QUEUE[18] */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_TWT_TSF_TF_0_QUEUE_SHFT 18 +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_TF_0_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_TF_0_QUEUE_MASK \ +0x00020000 /* EN_PAUSE_TF_0_QUEUE[17] */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_TF_0_QUEUE_SHFT 17 +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_ALTXCMD_0_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_ALTXCMD_0_QUEUE_MASK \ +0x00010000 /* EN_PAUSE_ALTXCMD_0_QUEUE[16] */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_ALTXCMD_0_QUEUE_SHFT 16 +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC33_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC33_QUEUE_MASK \ +0x00008000 /* EN_PAUSE_AC33_QUEUE[15] */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC33_QUEUE_SHFT 15 +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC32_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC32_QUEUE_MASK \ +0x00004000 /* EN_PAUSE_AC32_QUEUE[14] */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC32_QUEUE_SHFT 14 +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC31_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC31_QUEUE_MASK \ +0x00002000 /* EN_PAUSE_AC31_QUEUE[13] */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC31_QUEUE_SHFT 13 +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC30_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC30_QUEUE_MASK \ +0x00001000 /* EN_PAUSE_AC30_QUEUE[12] */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC30_QUEUE_SHFT 12 +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC23_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC23_QUEUE_MASK \ +0x00000800 /* EN_PAUSE_AC23_QUEUE[11] */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC23_QUEUE_SHFT 11 +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC22_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC22_QUEUE_MASK \ +0x00000400 /* EN_PAUSE_AC22_QUEUE[10] */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC22_QUEUE_SHFT 10 +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC21_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC21_QUEUE_MASK \ +0x00000200 /* EN_PAUSE_AC21_QUEUE[9] */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC21_QUEUE_SHFT 9 +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC20_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC20_QUEUE_MASK \ +0x00000100 /* EN_PAUSE_AC20_QUEUE[8] */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC20_QUEUE_SHFT 8 +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC13_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC13_QUEUE_MASK \ +0x00000080 /* EN_PAUSE_AC13_QUEUE[7] */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC13_QUEUE_SHFT 7 +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC12_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC12_QUEUE_MASK \ +0x00000040 /* EN_PAUSE_AC12_QUEUE[6] */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC12_QUEUE_SHFT 6 +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC11_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC11_QUEUE_MASK \ +0x00000020 /* EN_PAUSE_AC11_QUEUE[5] */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC11_QUEUE_SHFT 5 +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC10_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC10_QUEUE_MASK \ +0x00000010 /* EN_PAUSE_AC10_QUEUE[4] */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC10_QUEUE_SHFT 4 +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC03_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC03_QUEUE_MASK \ +0x00000008 /* EN_PAUSE_AC03_QUEUE[3] */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC03_QUEUE_SHFT 3 +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC02_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC02_QUEUE_MASK \ +0x00000004 /* EN_PAUSE_AC02_QUEUE[2] */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC02_QUEUE_SHFT 2 +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC01_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC01_QUEUE_MASK \ +0x00000002 /* EN_PAUSE_AC01_QUEUE[1] */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC01_QUEUE_SHFT 1 +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC00_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_QUEUE_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC00_QUEUE_MASK \ +0x00000001 /* EN_PAUSE_AC00_QUEUE[0] */ +#define WF_PLE_TOP_TXCMD_QUEUE_PAUSE_EN_PAUSE_AC00_QUEUE_SHFT 0 + +/* +* ---TXCMD_TXS_BUF_PAUSE (0x820C0000 + 0x238)--- +* EN_PAUSE_AC00_QUEUE[0] - (RW) Pause control of WMM0 AC0 TXCMD queue. +* EN_PAUSE_AC01_QUEUE[1] - (RW) Pause control of WMM0 AC1 TXCMD queue. +* EN_PAUSE_AC02_QUEUE[2] - (RW) Pause control of WMM0 AC2 TXCMD queue. +* EN_PAUSE_AC03_QUEUE[3] - (RW) Pause control of WMM0 AC3 TXCMD queue. +* EN_PAUSE_AC10_QUEUE[4] - (RW) Pause control of WMM1 AC0 TXCMD queue. +* EN_PAUSE_AC11_QUEUE[5] - (RW) Pause control of WMM1 AC1 TXCMD queue. +* EN_PAUSE_AC12_QUEUE[6] - (RW) Pause control of WMM1 AC2 TXCMD queue. +* EN_PAUSE_AC13_QUEUE[7] - (RW) Pause control of WMM1 AC3 TXCMD queue. +* EN_PAUSE_AC20_QUEUE[8] - (RW) Pause control of WMM2 AC0 TXCMD queue. +* EN_PAUSE_AC21_QUEUE[9] - (RW) Pause control of WMM2 AC1 TXCMD queue. +* EN_PAUSE_AC22_QUEUE[10] - (RW) Pause control of WMM2 AC2 TXCMD queue. +* EN_PAUSE_AC23_QUEUE[11] - (RW) Pause control of WMM2 AC3 TXCMD queue. +* EN_PAUSE_AC30_QUEUE[12] - (RW) Pause control of WMM3 AC0 TXCMD queue. +* EN_PAUSE_AC31_QUEUE[13] - (RW) Pause control of WMM3 AC1 TXCMD queue. +* EN_PAUSE_AC32_QUEUE[14] - (RW) Pause control of WMM3 AC2 TXCMD queue. +* EN_PAUSE_AC33_QUEUE[15] - (RW) Pause control of WMM3 AC3 TXCMD queue. +* EN_PAUSE_ALTXCMD_0_QUEUE[16] - (RW) Pause control of ALTXCMD 0 queue. +* EN_PAUSE_TF_0_QUEUE[17] - (RW) Pause control of TF 0 TXCDM queue . +* EN_PAUSE_TWT_TSF_TF_0_QUEUE[18] - (RW) Pause control of TWT TSF TF 0 TXCMD +queue. +* EN_PAUSE_TWT_DL_0_QUEUE[19] - (RW) Pause control of TWT DL 0 TXCMD queue. +* EN_PAUSE_TWT_UL_0_QUEUE[20] - (RW) Pause control of TWT UL 0 TXCMD queue. +* EN_PAUSE_ALTXCMD_1_QUEUE[21] - (RW) Pause control of ALTXCMD 1 queue. +* EN_PAUSE_TF_1_QUEUE[22] - (RW) Pause control of TF 1 TXCDM queue . +* EN_PAUSE_TWT_TSF_TF_1_QUEUE[23] - (RW) Pause control of TWT TSF TF 1 TXCMD +queue. +* EN_PAUSE_TWT_DL_1_QUEUE[24] - (RW) Pause control of TWT DL 1 TXCMD queue. +* EN_PAUSE_TWT_UL_1_QUEUE[25] - (RW) Pause control of TWT UL 1 TXCMD queue. +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_TWT_UL_1_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_TWT_UL_1_QUEUE_MASK \ +0x02000000 /* EN_PAUSE_TWT_UL_1_QUEUE[25] */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_TWT_UL_1_QUEUE_SHFT 25 +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_TWT_DL_1_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_TWT_DL_1_QUEUE_MASK \ +0x01000000 /* EN_PAUSE_TWT_DL_1_QUEUE[24] */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_TWT_DL_1_QUEUE_SHFT 24 +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_TWT_TSF_TF_1_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_TWT_TSF_TF_1_QUEUE_MASK \ +0x00800000 /* EN_PAUSE_TWT_TSF_TF_1_QUEUE[23] */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_TWT_TSF_TF_1_QUEUE_SHFT 23 +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_TF_1_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_TF_1_QUEUE_MASK \ +0x00400000 /* EN_PAUSE_TF_1_QUEUE[22] */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_TF_1_QUEUE_SHFT 22 +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_ALTXCMD_1_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_ALTXCMD_1_QUEUE_MASK \ +0x00200000 /* EN_PAUSE_ALTXCMD_1_QUEUE[21] */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_ALTXCMD_1_QUEUE_SHFT 21 +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_TWT_UL_0_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_TWT_UL_0_QUEUE_MASK \ +0x00100000 /* EN_PAUSE_TWT_UL_0_QUEUE[20] */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_TWT_UL_0_QUEUE_SHFT 20 +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_TWT_DL_0_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_TWT_DL_0_QUEUE_MASK \ +0x00080000 /* EN_PAUSE_TWT_DL_0_QUEUE[19] */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_TWT_DL_0_QUEUE_SHFT 19 +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_TWT_TSF_TF_0_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_TWT_TSF_TF_0_QUEUE_MASK \ +0x00040000 /* EN_PAUSE_TWT_TSF_TF_0_QUEUE[18] */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_TWT_TSF_TF_0_QUEUE_SHFT 18 +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_TF_0_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_TF_0_QUEUE_MASK \ +0x00020000 /* EN_PAUSE_TF_0_QUEUE[17] */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_TF_0_QUEUE_SHFT 17 +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_ALTXCMD_0_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_ALTXCMD_0_QUEUE_MASK \ +0x00010000 /* EN_PAUSE_ALTXCMD_0_QUEUE[16] */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_ALTXCMD_0_QUEUE_SHFT 16 +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC33_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC33_QUEUE_MASK \ +0x00008000 /* EN_PAUSE_AC33_QUEUE[15] */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC33_QUEUE_SHFT 15 +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC32_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC32_QUEUE_MASK \ +0x00004000 /* EN_PAUSE_AC32_QUEUE[14] */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC32_QUEUE_SHFT 14 +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC31_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC31_QUEUE_MASK \ +0x00002000 /* EN_PAUSE_AC31_QUEUE[13] */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC31_QUEUE_SHFT 13 +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC30_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC30_QUEUE_MASK \ +0x00001000 /* EN_PAUSE_AC30_QUEUE[12] */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC30_QUEUE_SHFT 12 +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC23_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC23_QUEUE_MASK \ +0x00000800 /* EN_PAUSE_AC23_QUEUE[11] */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC23_QUEUE_SHFT 11 +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC22_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC22_QUEUE_MASK \ +0x00000400 /* EN_PAUSE_AC22_QUEUE[10] */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC22_QUEUE_SHFT 10 +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC21_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC21_QUEUE_MASK \ +0x00000200 /* EN_PAUSE_AC21_QUEUE[9] */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC21_QUEUE_SHFT 9 +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC20_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC20_QUEUE_MASK \ +0x00000100 /* EN_PAUSE_AC20_QUEUE[8] */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC20_QUEUE_SHFT 8 +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC13_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC13_QUEUE_MASK \ +0x00000080 /* EN_PAUSE_AC13_QUEUE[7] */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC13_QUEUE_SHFT 7 +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC12_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC12_QUEUE_MASK \ +0x00000040 /* EN_PAUSE_AC12_QUEUE[6] */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC12_QUEUE_SHFT 6 +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC11_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC11_QUEUE_MASK \ +0x00000020 /* EN_PAUSE_AC11_QUEUE[5] */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC11_QUEUE_SHFT 5 +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC10_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC10_QUEUE_MASK \ +0x00000010 /* EN_PAUSE_AC10_QUEUE[4] */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC10_QUEUE_SHFT 4 +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC03_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC03_QUEUE_MASK \ +0x00000008 /* EN_PAUSE_AC03_QUEUE[3] */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC03_QUEUE_SHFT 3 +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC02_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC02_QUEUE_MASK \ +0x00000004 /* EN_PAUSE_AC02_QUEUE[2] */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC02_QUEUE_SHFT 2 +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC01_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC01_QUEUE_MASK \ +0x00000002 /* EN_PAUSE_AC01_QUEUE[1] */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC01_QUEUE_SHFT 1 +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC00_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC00_QUEUE_MASK \ +0x00000001 /* EN_PAUSE_AC00_QUEUE[0] */ +#define WF_PLE_TOP_TXCMD_TXS_BUF_PAUSE_EN_PAUSE_AC00_QUEUE_SHFT 0 + +/* +* ---TXCMD_TXCMD_BUF_PAUSE (0x820C0000 + 0x23c)--- +* EN_PAUSE_AC00_QUEUE[0] - (RW) Pause control of WMM0 AC0 TXCMD queue. +* EN_PAUSE_AC01_QUEUE[1] - (RW) Pause control of WMM0 AC1 TXCMD queue. +* EN_PAUSE_AC02_QUEUE[2] - (RW) Pause control of WMM0 AC2 TXCMD queue. +* EN_PAUSE_AC03_QUEUE[3] - (RW) Pause control of WMM0 AC3 TXCMD queue. +* EN_PAUSE_AC10_QUEUE[4] - (RW) Pause control of WMM1 AC0 TXCMD queue. +* EN_PAUSE_AC11_QUEUE[5] - (RW) Pause control of WMM1 AC1 TXCMD queue. +* EN_PAUSE_AC12_QUEUE[6] - (RW) Pause control of WMM1 AC2 TXCMD queue. +* EN_PAUSE_AC13_QUEUE[7] - (RW) Pause control of WMM1 AC3 TXCMD queue. +* EN_PAUSE_AC20_QUEUE[8] - (RW) Pause control of WMM2 AC0 TXCMD queue. +* EN_PAUSE_AC21_QUEUE[9] - (RW) Pause control of WMM2 AC1 TXCMD queue. +* EN_PAUSE_AC22_QUEUE[10] - (RW) Pause control of WMM2 AC2 TXCMD queue. +* EN_PAUSE_AC23_QUEUE[11] - (RW) Pause control of WMM2 AC3 TXCMD queue. +* EN_PAUSE_AC30_QUEUE[12] - (RW) Pause control of WMM3 AC0 TXCMD queue. +* EN_PAUSE_AC31_QUEUE[13] - (RW) Pause control of WMM3 AC1 TXCMD queue. +* EN_PAUSE_AC32_QUEUE[14] - (RW) Pause control of WMM3 AC2 TXCMD queue. +* EN_PAUSE_AC33_QUEUE[15] - (RW) Pause control of WMM3 AC3 TXCMD queue. +* EN_PAUSE_ALTXCMD_0_QUEUE[16] - (RW) Pause control of ALTXCMD 0 queue. +* EN_PAUSE_TF_0_QUEUE[17] - (RW) Pause control of TF 0 TXCDM queue . +* EN_PAUSE_TWT_TSF_TF_0_QUEUE[18] - (RW) Pause control of TWT TSF TF 0 TXCMD +queue. +* EN_PAUSE_TWT_DL_0_QUEUE[19] - (RW) Pause control of TWT DL 0 TXCMD queue. +* EN_PAUSE_TWT_UL_0_QUEUE[20] - (RW) Pause control of TWT UL 0 TXCMD queue. +* EN_PAUSE_ALTXCMD_1_QUEUE[21] - (RW) Pause control of ALTXCMD 1 queue. +* EN_PAUSE_TF_1_QUEUE[22] - (RW) Pause control of TF 1 TXCDM queue . +* EN_PAUSE_TWT_TSF_TF_1_QUEUE[23] - (RW) Pause control of TWT TSF TF 1 TXCMD +queue. +* EN_PAUSE_TWT_DL_1_QUEUE[24] - (RW) Pause control of TWT DL 1 TXCMD queue. +* EN_PAUSE_TWT_UL_1_QUEUE[25] - (RW) Pause control of TWT UL 1 TXCMD queue. +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_TWT_UL_1_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_TWT_UL_1_QUEUE_MASK \ +0x02000000 /* EN_PAUSE_TWT_UL_1_QUEUE[25] */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_TWT_UL_1_QUEUE_SHFT 25 +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_TWT_DL_1_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_TWT_DL_1_QUEUE_MASK \ +0x01000000 /* EN_PAUSE_TWT_DL_1_QUEUE[24] */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_TWT_DL_1_QUEUE_SHFT 24 +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_TWT_TSF_TF_1_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_TWT_TSF_TF_1_QUEUE_MASK \ +0x00800000 /* EN_PAUSE_TWT_TSF_TF_1_QUEUE[23] */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_TWT_TSF_TF_1_QUEUE_SHFT 23 +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_TF_1_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_TF_1_QUEUE_MASK \ +0x00400000 /* EN_PAUSE_TF_1_QUEUE[22] */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_TF_1_QUEUE_SHFT 22 +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_ALTXCMD_1_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_ALTXCMD_1_QUEUE_MASK \ +0x00200000 /* EN_PAUSE_ALTXCMD_1_QUEUE[21] */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_ALTXCMD_1_QUEUE_SHFT 21 +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_TWT_UL_0_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_TWT_UL_0_QUEUE_MASK \ +0x00100000 /* EN_PAUSE_TWT_UL_0_QUEUE[20] */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_TWT_UL_0_QUEUE_SHFT 20 +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_TWT_DL_0_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_TWT_DL_0_QUEUE_MASK \ +0x00080000 /* EN_PAUSE_TWT_DL_0_QUEUE[19] */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_TWT_DL_0_QUEUE_SHFT 19 +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_TWT_TSF_TF_0_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_TWT_TSF_TF_0_QUEUE_MASK \ +0x00040000 /* EN_PAUSE_TWT_TSF_TF_0_QUEUE[18] */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_TWT_TSF_TF_0_QUEUE_SHFT 18 +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_TF_0_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_TF_0_QUEUE_MASK \ +0x00020000 /* EN_PAUSE_TF_0_QUEUE[17] */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_TF_0_QUEUE_SHFT 17 +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_ALTXCMD_0_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_ALTXCMD_0_QUEUE_MASK \ +0x00010000 /* EN_PAUSE_ALTXCMD_0_QUEUE[16] */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_ALTXCMD_0_QUEUE_SHFT 16 +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC33_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC33_QUEUE_MASK \ +0x00008000 /* EN_PAUSE_AC33_QUEUE[15] */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC33_QUEUE_SHFT 15 +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC32_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC32_QUEUE_MASK \ +0x00004000 /* EN_PAUSE_AC32_QUEUE[14] */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC32_QUEUE_SHFT 14 +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC31_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC31_QUEUE_MASK \ +0x00002000 /* EN_PAUSE_AC31_QUEUE[13] */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC31_QUEUE_SHFT 13 +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC30_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC30_QUEUE_MASK \ +0x00001000 /* EN_PAUSE_AC30_QUEUE[12] */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC30_QUEUE_SHFT 12 +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC23_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC23_QUEUE_MASK \ +0x00000800 /* EN_PAUSE_AC23_QUEUE[11] */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC23_QUEUE_SHFT 11 +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC22_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC22_QUEUE_MASK \ +0x00000400 /* EN_PAUSE_AC22_QUEUE[10] */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC22_QUEUE_SHFT 10 +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC21_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC21_QUEUE_MASK \ +0x00000200 /* EN_PAUSE_AC21_QUEUE[9] */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC21_QUEUE_SHFT 9 +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC20_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC20_QUEUE_MASK \ +0x00000100 /* EN_PAUSE_AC20_QUEUE[8] */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC20_QUEUE_SHFT 8 +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC13_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC13_QUEUE_MASK \ +0x00000080 /* EN_PAUSE_AC13_QUEUE[7] */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC13_QUEUE_SHFT 7 +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC12_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC12_QUEUE_MASK \ +0x00000040 /* EN_PAUSE_AC12_QUEUE[6] */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC12_QUEUE_SHFT 6 +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC11_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC11_QUEUE_MASK \ +0x00000020 /* EN_PAUSE_AC11_QUEUE[5] */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC11_QUEUE_SHFT 5 +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC10_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC10_QUEUE_MASK \ +0x00000010 /* EN_PAUSE_AC10_QUEUE[4] */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC10_QUEUE_SHFT 4 +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC03_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC03_QUEUE_MASK \ +0x00000008 /* EN_PAUSE_AC03_QUEUE[3] */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC03_QUEUE_SHFT 3 +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC02_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC02_QUEUE_MASK \ +0x00000004 /* EN_PAUSE_AC02_QUEUE[2] */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC02_QUEUE_SHFT 2 +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC01_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC01_QUEUE_MASK \ +0x00000002 /* EN_PAUSE_AC01_QUEUE[1] */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC01_QUEUE_SHFT 1 +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC00_QUEUE_ADDR \ +WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC00_QUEUE_MASK \ +0x00000001 /* EN_PAUSE_AC00_QUEUE[0] */ +#define WF_PLE_TOP_TXCMD_TXCMD_BUF_PAUSE_EN_PAUSE_AC00_QUEUE_SHFT 0 + +/* +* ---UMAC_DBG_CTRL (0x820C0000 + 0x240)--- +* UMAC_DBG_FUNC_SEL[3..0] - (RW) Selects UMAC debug mode +* RESERVED4[7..4] - (RO) Reserved bits +* PLE_DBG_FLAG_A_NIB_EN[11..8] - (RW) Enable control of PLE debug flag A +nibble +* PLE_DBG_FLAG_B_NIB_EN[15..12] - (RW) Enable control of PLE debug flag B +nibble +* PSE_DBG_FLAG_A_NIB_EN[19..16] - (RW) Enable control of PSE debug flag A +nibble +* PSE_DBG_FLAG_B_NIB_EN[23..20] - (RW) Enable control of PSE debug flag B +nibble +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_UMAC_DBG_CTRL_PSE_DBG_FLAG_B_NIB_EN_ADDR \ +WF_PLE_TOP_UMAC_DBG_CTRL_ADDR +#define WF_PLE_TOP_UMAC_DBG_CTRL_PSE_DBG_FLAG_B_NIB_EN_MASK \ +0x00F00000 /* PSE_DBG_FLAG_B_NIB_EN[23..20] */ +#define WF_PLE_TOP_UMAC_DBG_CTRL_PSE_DBG_FLAG_B_NIB_EN_SHFT 20 +#define WF_PLE_TOP_UMAC_DBG_CTRL_PSE_DBG_FLAG_A_NIB_EN_ADDR \ +WF_PLE_TOP_UMAC_DBG_CTRL_ADDR +#define WF_PLE_TOP_UMAC_DBG_CTRL_PSE_DBG_FLAG_A_NIB_EN_MASK \ +0x000F0000 /* PSE_DBG_FLAG_A_NIB_EN[19..16] */ +#define WF_PLE_TOP_UMAC_DBG_CTRL_PSE_DBG_FLAG_A_NIB_EN_SHFT 16 +#define WF_PLE_TOP_UMAC_DBG_CTRL_PLE_DBG_FLAG_B_NIB_EN_ADDR \ +WF_PLE_TOP_UMAC_DBG_CTRL_ADDR +#define WF_PLE_TOP_UMAC_DBG_CTRL_PLE_DBG_FLAG_B_NIB_EN_MASK \ +0x0000F000 /* PLE_DBG_FLAG_B_NIB_EN[15..12] */ +#define WF_PLE_TOP_UMAC_DBG_CTRL_PLE_DBG_FLAG_B_NIB_EN_SHFT 12 +#define WF_PLE_TOP_UMAC_DBG_CTRL_PLE_DBG_FLAG_A_NIB_EN_ADDR \ +WF_PLE_TOP_UMAC_DBG_CTRL_ADDR +#define WF_PLE_TOP_UMAC_DBG_CTRL_PLE_DBG_FLAG_A_NIB_EN_MASK \ +0x00000F00 /* PLE_DBG_FLAG_A_NIB_EN[11..8] */ +#define WF_PLE_TOP_UMAC_DBG_CTRL_PLE_DBG_FLAG_A_NIB_EN_SHFT 8 +#define WF_PLE_TOP_UMAC_DBG_CTRL_UMAC_DBG_FUNC_SEL_ADDR \ +WF_PLE_TOP_UMAC_DBG_CTRL_ADDR +#define WF_PLE_TOP_UMAC_DBG_CTRL_UMAC_DBG_FUNC_SEL_MASK \ +0x0000000F /* UMAC_DBG_FUNC_SEL[3..0] */ +#define WF_PLE_TOP_UMAC_DBG_CTRL_UMAC_DBG_FUNC_SEL_SHFT 0 + +/* +* ---PLE_DBG_A_BYTE_SEL (0x820C0000 + 0x244)--- +* PLE_DBG_FLAG_A_BYTE0_SEL[7..0] - (RW) Debug flag selection of PLE debug A +* byte 0 +* PLE_DBG_FLAG_A_BYTE1_SEL[15..8] - (RW) Debug flag selection of PLE debug A +* byte 1 +* PLE_DBG_FLAG_A_BYTE2_SEL[23..16] - (RW) Debug flag selection of PLE debug A +* byte 2 +* PLE_DBG_FLAG_A_BYTE3_SEL[31..24] - (RW) Debug flag selection of PLE debug A +* byte 3 +*/ +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE3_SEL_ADDR \ +WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_ADDR +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE3_SEL_MASK \ +0xFF000000 /* PLE_DBG_FLAG_A_BYTE3_SEL[31..24] */ +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE3_SEL_SHFT 24 +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE2_SEL_ADDR \ +WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_ADDR +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE2_SEL_MASK \ +0x00FF0000 /* PLE_DBG_FLAG_A_BYTE2_SEL[23..16] */ +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE2_SEL_SHFT 16 +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE1_SEL_ADDR \ +WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_ADDR +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE1_SEL_MASK \ +0x0000FF00 /* PLE_DBG_FLAG_A_BYTE1_SEL[15..8] */ +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE1_SEL_SHFT 8 +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE0_SEL_ADDR \ +WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_ADDR +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE0_SEL_MASK \ +0x000000FF /* PLE_DBG_FLAG_A_BYTE0_SEL[7..0] */ +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE0_SEL_SHFT 0 + +/* +* ---PLE_DBG_B_BYTE_SEL (0x820C0000 + 0x248)--- +* PLE_DBG_FLAG_B_BYTE0_SEL[7..0] - (RW) Debug flag selection of PLE debug B +* byte 0 +* PLE_DBG_FLAG_B_BYTE1_SEL[15..8] - (RW) Debug flag selection of PLE debug B +* byte 1 +* PLE_DBG_FLAG_B_BYTE2_SEL[23..16] - (RW) Debug flag selection of PLE debug B +* byte 2 +* PLE_DBG_FLAG_B_BYTE3_SEL[31..24] - (RW) Debug flag selection of PLE debug B +* byte 3 +*/ +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE3_SEL_ADDR \ +WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_ADDR +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE3_SEL_MASK \ +0xFF000000 /* PLE_DBG_FLAG_B_BYTE3_SEL[31..24] */ +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE3_SEL_SHFT 24 +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE2_SEL_ADDR \ +WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_ADDR +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE2_SEL_MASK \ +0x00FF0000 /* PLE_DBG_FLAG_B_BYTE2_SEL[23..16] */ +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE2_SEL_SHFT 16 +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE1_SEL_ADDR \ +WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_ADDR +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE1_SEL_MASK \ +0x0000FF00 /* PLE_DBG_FLAG_B_BYTE1_SEL[15..8] */ +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE1_SEL_SHFT 8 +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE0_SEL_ADDR \ +WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_ADDR +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE0_SEL_MASK \ +0x000000FF /* PLE_DBG_FLAG_B_BYTE0_SEL[7..0] */ +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE0_SEL_SHFT 0 + +/* +* ---FSM_IDLE_WD_CTRL (0x820C0000 + 0x24C)--- +* FL_IDLE_WD_TO_TH[7..0] - (RW) Watchdog timeout threshold for frame +* link FSM not returning to IDLE +* PL_IDLE_WD_TO_TH[15..8] - (RW) Watchdog timeout threshold for page link +* FSM not returning to IDLE +* PORT_IDLE_WD_TO_TH[23..16] - (RW) Watchdog timeout threshold for port oper +* FSM not returning to IDLE +* (Including HIF/CPU/LMAC port) +* MACTX_IDLE_WD_TO_TH[31..24] - (RW) Watchdog timeout threshold for MACTX FSM +* not returning to IDLE +*/ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_MACTX_IDLE_WD_TO_TH_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_CTRL_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_MACTX_IDLE_WD_TO_TH_MASK \ +0xFF000000 /* MACTX_IDLE_WD_TO_TH[31..24] */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_MACTX_IDLE_WD_TO_TH_SHFT 24 +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_PORT_IDLE_WD_TO_TH_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_CTRL_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_PORT_IDLE_WD_TO_TH_MASK \ +0x00FF0000 /* PORT_IDLE_WD_TO_TH[23..16] */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_PORT_IDLE_WD_TO_TH_SHFT 16 +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_PL_IDLE_WD_TO_TH_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_CTRL_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_PL_IDLE_WD_TO_TH_MASK \ +0x0000FF00 /* PL_IDLE_WD_TO_TH[15..8] */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_PL_IDLE_WD_TO_TH_SHFT 8 +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_FL_IDLE_WD_TO_TH_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_CTRL_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_FL_IDLE_WD_TO_TH_MASK \ +0x000000FF /* FL_IDLE_WD_TO_TH[7..0] */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_FL_IDLE_WD_TO_TH_SHFT 0 + +/* +* ---FSM_IDLE_WD_EN (0x820C0000 + 0x250)--- +* EN_FL_IDLE_WD_TO[0] - (RW) Enables watchdog for frame link FSM not +* returning to IDLE +* EN_PL_IDLE_WD_TO[1] - (RW) Enables watchdog for page link FSM not +* returning to IDLE +* EN_CPU_PORT_IDLE_WD_TO[2] - (RW) Enables watchdog for CPU port oper FSM +* not returning to IDLE +* EN_HIF_PORT_IDLE_WD_TO[3] - (RW) Enables watchdog for HIF port oper FSM +* not returning to IDLE +* EN_LMAC_PORT_IDLE_WD_TO[4] - (RW) Enables watchdog for LMAC port oper FSM +* not returning to IDLE +* EN_AMSDU_PORT_IDLE_WD_TO[5] - (RW) Enables watchdog for AMSDU port FSM not +* returning to IDLE +* EN_HW_AMSDU_IDLE_WD_TO[6] - (RW) Enables watchdog for HW AMSDU FSM not +* returning to IDLE +* RESERVED7[7] - (RO) Reserved bits +* EN_MACTX0_IDLE_WD_TO[8] - (RW) Enables watchdog for MACTX 0 FSM not +* returning to IDLE +* EN_MACTX2_IDLE_WD_TO[9] - (RW) Enables watchdog for MACTX 1 FSM not +* returning to IDLE +* EN_MACTX1_IDLE_WD_TO[10] - (RW) Enables watchdog for MACTX 2 FSM not +* returning to IDLE +* EN_MACTX3_IDLE_WD_TO[11] - (RW) Enables watchdog for MACTX 3 FSM not +* returning to IDLE +* EN_MDP_IDLE_WD_TO[12] - (RW) Enables watchdog for MDP port oper FSM +* not returning to IDLE +* EN_PREDL_ARB_IDLE_WD_TO[13] - (RW) Enables watchdog for Predl arbitrator +* FSM not returning to IDLE +* EN_PREDL_TXCMD_IDLE_WD_TO[14] - (RW) Enables watchdog for Predl TXCMD parser +* FSM not returning to IDLE +* RESERVED15[31..15] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PREDL_TXCMD_IDLE_WD_TO_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PREDL_TXCMD_IDLE_WD_TO_MASK \ +0x00004000 /* EN_PREDL_TXCMD_IDLE_WD_TO[14] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PREDL_TXCMD_IDLE_WD_TO_SHFT 14 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PREDL_ARB_IDLE_WD_TO_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PREDL_ARB_IDLE_WD_TO_MASK \ +0x00002000 /* EN_PREDL_ARB_IDLE_WD_TO[13] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PREDL_ARB_IDLE_WD_TO_SHFT 13 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MDP_IDLE_WD_TO_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MDP_IDLE_WD_TO_MASK \ +0x00001000 /* EN_MDP_IDLE_WD_TO[12] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MDP_IDLE_WD_TO_SHFT 12 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX3_IDLE_WD_TO_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX3_IDLE_WD_TO_MASK \ +0x00000800 /* EN_MACTX3_IDLE_WD_TO[11] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX3_IDLE_WD_TO_SHFT 11 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX1_IDLE_WD_TO_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX1_IDLE_WD_TO_MASK \ +0x00000400 /* EN_MACTX1_IDLE_WD_TO[10] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX1_IDLE_WD_TO_SHFT 10 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX2_IDLE_WD_TO_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX2_IDLE_WD_TO_MASK \ +0x00000200 /* EN_MACTX2_IDLE_WD_TO[9] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX2_IDLE_WD_TO_SHFT 9 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX0_IDLE_WD_TO_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX0_IDLE_WD_TO_MASK \ +0x00000100 /* EN_MACTX0_IDLE_WD_TO[8] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX0_IDLE_WD_TO_SHFT 8 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_HW_AMSDU_IDLE_WD_TO_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_HW_AMSDU_IDLE_WD_TO_MASK \ +0x00000040 /* EN_HW_AMSDU_IDLE_WD_TO[6] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_HW_AMSDU_IDLE_WD_TO_SHFT 6 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_AMSDU_PORT_IDLE_WD_TO_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_AMSDU_PORT_IDLE_WD_TO_MASK \ +0x00000020 /* EN_AMSDU_PORT_IDLE_WD_TO[5] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_AMSDU_PORT_IDLE_WD_TO_SHFT 5 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_LMAC_PORT_IDLE_WD_TO_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_LMAC_PORT_IDLE_WD_TO_MASK \ +0x00000010 /* EN_LMAC_PORT_IDLE_WD_TO[4] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_LMAC_PORT_IDLE_WD_TO_SHFT 4 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_HIF_PORT_IDLE_WD_TO_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_HIF_PORT_IDLE_WD_TO_MASK \ +0x00000008 /* EN_HIF_PORT_IDLE_WD_TO[3] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_HIF_PORT_IDLE_WD_TO_SHFT 3 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_CPU_PORT_IDLE_WD_TO_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_CPU_PORT_IDLE_WD_TO_MASK \ +0x00000004 /* EN_CPU_PORT_IDLE_WD_TO[2] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_CPU_PORT_IDLE_WD_TO_SHFT 2 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PL_IDLE_WD_TO_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PL_IDLE_WD_TO_MASK \ +0x00000002 /* EN_PL_IDLE_WD_TO[1] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PL_IDLE_WD_TO_SHFT 1 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_FL_IDLE_WD_TO_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_FL_IDLE_WD_TO_MASK \ +0x00000001 /* EN_FL_IDLE_WD_TO[0] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_FL_IDLE_WD_TO_SHFT 0 + +/* +* ---FSM_IDLE_WD_CTRL_1 (0x820C0000 + 0x258)--- +* MDP_IDLE_WD_TO_TH[7..0] - (RW) Watchdog timeout threshold for MDP FSM +* not returning to IDLE +* (Including MDP TDP/RDP/TIOC/RIOC) +* PF_IDLE_WD_TO_TH[15..8] - (RW) Watchdog timeout threshold for PF FSM +* not returning to IDLE +* SEC_IDLE_WD_TO_TH[23..16] - (RW) Watchdog timeout threshold for SEC FSM +* not returning to IDLE +* (Including SEC0/SEC1) +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_SEC_IDLE_WD_TO_TH_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_SEC_IDLE_WD_TO_TH_MASK \ +0x00FF0000 /* SEC_IDLE_WD_TO_TH[23..16] */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_SEC_IDLE_WD_TO_TH_SHFT 16 +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_PF_IDLE_WD_TO_TH_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_PF_IDLE_WD_TO_TH_MASK \ +0x0000FF00 /* PF_IDLE_WD_TO_TH[15..8] */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_PF_IDLE_WD_TO_TH_SHFT 8 +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_MDP_IDLE_WD_TO_TH_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_MDP_IDLE_WD_TO_TH_MASK \ +0x000000FF /* MDP_IDLE_WD_TO_TH[7..0] */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_MDP_IDLE_WD_TO_TH_SHFT 0 + +/* +* ---FSM_IDLE_WD_EN_1 (0x820C0000 + 0x25C)--- +* EN_BN0_MDP_TDP_IDLE_WD_TO[0] - (RW) Enables watchdog for Band0 MDP TDP FSM +* not returning to IDLE +* EN_MDP_RDP_IDLE_WD_TO[1] - (RW) Enables watchdog for MDP RDP FSM not +* returning to IDLE +* EN_BN0_MDP_TIOC_IDLE_WD_TO[2] - (RW) Enables watchdog for Band0 MDP TIOC FSM +* not returning to IDLE +* EN_BN0_MDP_RIOC_IDLE_WD_TO[3] - (RW) Enables watchdog for Band0 MDP RIOC FSM +* not returning to IDLE +* EN_PF_IDLE_WD_TO[4] - (RW) Enables watchdog for PF FSM not +* returning to IDLE +* EN_SEC0_IDLE_WD_TO[5] - (RW) Enables watchdog for SEC0 FSM not +* returning to IDLE +* EN_SEC1_IDLE_WD_TO[6] - (RW) Enables watchdog for SEC1 FSM not +* returning to IDLE +* EN_BN1_MDP_TDP_IDLE_WD_TO[7] - (RW) Enables watchdog for Band1 MDP TDP FSM +* not returning to IDLE +* EN_BN1_MDP_TIOC_IDLE_WD_TO[8] - (RW) Enables watchdog for Band1 MDP TIOC FSM +* not returning to IDLE +* EN_BN1_MDP_RIOC_IDLE_WD_TO[9] - (RW) Enables watchdog for Band1 MDP RIOC FSM +* not returning to IDLE +* RESERVED10[31..10] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_RIOC_IDLE_WD_TO_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_RIOC_IDLE_WD_TO_MASK \ +0x00000200 /* EN_BN1_MDP_RIOC_IDLE_WD_TO[9] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_RIOC_IDLE_WD_TO_SHFT 9 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_TIOC_IDLE_WD_TO_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_TIOC_IDLE_WD_TO_MASK \ +0x00000100 /* EN_BN1_MDP_TIOC_IDLE_WD_TO[8] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_TIOC_IDLE_WD_TO_SHFT 8 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_TDP_IDLE_WD_TO_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_TDP_IDLE_WD_TO_MASK \ +0x00000080 /* EN_BN1_MDP_TDP_IDLE_WD_TO[7] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_TDP_IDLE_WD_TO_SHFT 7 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_SEC1_IDLE_WD_TO_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_SEC1_IDLE_WD_TO_MASK \ +0x00000040 /* EN_SEC1_IDLE_WD_TO[6] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_SEC1_IDLE_WD_TO_SHFT 6 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_SEC0_IDLE_WD_TO_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_SEC0_IDLE_WD_TO_MASK \ +0x00000020 /* EN_SEC0_IDLE_WD_TO[5] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_SEC0_IDLE_WD_TO_SHFT 5 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_PF_IDLE_WD_TO_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_PF_IDLE_WD_TO_MASK \ +0x00000010 /* EN_PF_IDLE_WD_TO[4] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_PF_IDLE_WD_TO_SHFT 4 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_RIOC_IDLE_WD_TO_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_RIOC_IDLE_WD_TO_MASK \ +0x00000008 /* EN_BN0_MDP_RIOC_IDLE_WD_TO[3] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_RIOC_IDLE_WD_TO_SHFT 3 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_TIOC_IDLE_WD_TO_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_TIOC_IDLE_WD_TO_MASK \ +0x00000004 /* EN_BN0_MDP_TIOC_IDLE_WD_TO[2] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_TIOC_IDLE_WD_TO_SHFT 2 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_MDP_RDP_IDLE_WD_TO_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_MDP_RDP_IDLE_WD_TO_MASK \ +0x00000002 /* EN_MDP_RDP_IDLE_WD_TO[1] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_MDP_RDP_IDLE_WD_TO_SHFT 1 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_TDP_IDLE_WD_TO_ADDR \ +WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_TDP_IDLE_WD_TO_MASK \ +0x00000001 /* EN_BN0_MDP_TDP_IDLE_WD_TO[0] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_TDP_IDLE_WD_TO_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL9 (0x820C0000 + 0x260)--- +* SRAM9_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM9 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL9_SRAM9_MBIST_DELSEL_ADDR \ +WF_PLE_TOP_SRAM_MBIST_DELSEL9_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL9_SRAM9_MBIST_DELSEL_MASK \ +0xFFFFFFFF /* SRAM9_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL9_SRAM9_MBIST_DELSEL_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL10 (0x820C0000 + 0x264)--- +* SRAM10_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM10 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL10_SRAM10_MBIST_DELSEL_ADDR \ +WF_PLE_TOP_SRAM_MBIST_DELSEL10_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL10_SRAM10_MBIST_DELSEL_MASK \ +0xFFFFFFFF /* SRAM10_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL10_SRAM10_MBIST_DELSEL_SHFT 0 + +/* +* ---FUNC_ACT_CNT_0 (0x820C0000 + 0x280)--- +* RESERVED0[15..0] - (RO) Reserved bits +* SPL_GEN_NUM[31..16] - (RO) Counter of SPL report generation. +*/ +#define WF_PLE_TOP_FUNC_ACT_CNT_0_SPL_GEN_NUM_ADDR \ +WF_PLE_TOP_FUNC_ACT_CNT_0_ADDR +#define WF_PLE_TOP_FUNC_ACT_CNT_0_SPL_GEN_NUM_MASK \ +0xFFFF0000 /* SPL_GEN_NUM[31..16] */ +#define WF_PLE_TOP_FUNC_ACT_CNT_0_SPL_GEN_NUM_SHFT 16 + +/* +* ---FUNC_ACT_CNT_1 (0x820C0000 + 0x284)--- +* MACTX0_ACT_CNT[3..0] - (RO) Counter of MACTX0 TX active. +* MACTX0_NOR_END_CNT[7..4] - (RO) Counter of MACTX0 TX normal end. +* MACTX0_ABORT_CNT[11..8] - (RO) Counter of MACTX0 TX abort. +* RESERVED12[15..12] - (RO) Reserved bits +* TXCMD0_ADD_FID_CNT[19..16] - (RO) Counter of TXCMD0 TX add FID. +* TXCMD0_NOR_END_CNT[23..20] - (RO) Counter of TXCMD0 TX normal end. +* TXCMD0_ABORT_CNT[27..24] - (RO) Counter of TXCMD0 TX abort. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_ABORT_CNT_ADDR \ +WF_PLE_TOP_FUNC_ACT_CNT_1_ADDR +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_ABORT_CNT_MASK \ +0x0F000000 /* TXCMD0_ABORT_CNT[27..24] */ +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_ABORT_CNT_SHFT 24 +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_NOR_END_CNT_ADDR \ +WF_PLE_TOP_FUNC_ACT_CNT_1_ADDR +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_NOR_END_CNT_MASK \ +0x00F00000 /* TXCMD0_NOR_END_CNT[23..20] */ +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_NOR_END_CNT_SHFT 20 +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_ADD_FID_CNT_ADDR \ +WF_PLE_TOP_FUNC_ACT_CNT_1_ADDR +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_ADD_FID_CNT_MASK \ +0x000F0000 /* TXCMD0_ADD_FID_CNT[19..16] */ +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_ADD_FID_CNT_SHFT 16 +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_ABORT_CNT_ADDR \ +WF_PLE_TOP_FUNC_ACT_CNT_1_ADDR +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_ABORT_CNT_MASK \ +0x00000F00 /* MACTX0_ABORT_CNT[11..8] */ +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_ABORT_CNT_SHFT 8 +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_NOR_END_CNT_ADDR \ +WF_PLE_TOP_FUNC_ACT_CNT_1_ADDR +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_NOR_END_CNT_MASK \ +0x000000F0 /* MACTX0_NOR_END_CNT[7..4] */ +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_NOR_END_CNT_SHFT 4 +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_ACT_CNT_ADDR \ +WF_PLE_TOP_FUNC_ACT_CNT_1_ADDR +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_ACT_CNT_MASK \ +0x0000000F /* MACTX0_ACT_CNT[3..0] */ +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_ACT_CNT_SHFT 0 + +/* +* ---PORT_SER_CTRL (0x820C0000 + 0x2A0)--- +* EN_HIF_PORT_ALLOC_BLOCKING[0] - (RW) Enable HIF/AMSDU port allocate +* operation blocking. +* EN_CPU_PORT_ALLOC_BLOCKING[1] - (RW) Enable CPU port allocate operation +blocking. +* EN_WF_PORT_ALLOC_BLOCKING[2] - (RW) Enable LMAC port allocate operation +blocking. +* RESERVED3[7..3] - (RO) Reserved bits +* EN_HIF_PORT_D_OPR_BLOCKING[8] - (RW) Enable HIF/AMSDU/MDP/PREDL port data +* operation blocking. +* EN_CPU_PORT_D_OPR_BLOCKING[9] - (RW) Enable CPU port data operation +blocking. +* EN_WF_PORT_D_OPR_BLOCKING[10] - (RW) Enable LMAC port data operation +blocking. +* RESERVED11[15..11] - (RO) Reserved bits +* EN_HIF_PORT_Q_OPR_BLOCKING[16] - (RW) Enable HIF/AMSDU port queue operation +blocking. +* EN_CPU_PORT_Q_OPR_BLOCKING[17] - (RW) Enable CPU port queue operation +blocking. +* EN_WF_PORT_Q_OPR_BLOCKING[18] - (RW) Enable LMAC port queue operation +blocking. +* RESERVED19[31..19] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_Q_OPR_BLOCKING_ADDR \ +WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_Q_OPR_BLOCKING_MASK \ +0x00040000 /* EN_WF_PORT_Q_OPR_BLOCKING[18] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_Q_OPR_BLOCKING_SHFT 18 +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_Q_OPR_BLOCKING_ADDR \ +WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_Q_OPR_BLOCKING_MASK \ +0x00020000 /* EN_CPU_PORT_Q_OPR_BLOCKING[17] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_Q_OPR_BLOCKING_SHFT 17 +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_Q_OPR_BLOCKING_ADDR \ +WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_Q_OPR_BLOCKING_MASK \ +0x00010000 /* EN_HIF_PORT_Q_OPR_BLOCKING[16] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_Q_OPR_BLOCKING_SHFT 16 +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_D_OPR_BLOCKING_ADDR \ +WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_D_OPR_BLOCKING_MASK \ +0x00000400 /* EN_WF_PORT_D_OPR_BLOCKING[10] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_D_OPR_BLOCKING_SHFT 10 +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_D_OPR_BLOCKING_ADDR \ +WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_D_OPR_BLOCKING_MASK \ +0x00000200 /* EN_CPU_PORT_D_OPR_BLOCKING[9] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_D_OPR_BLOCKING_SHFT 9 +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_D_OPR_BLOCKING_ADDR \ +WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_D_OPR_BLOCKING_MASK \ +0x00000100 /* EN_HIF_PORT_D_OPR_BLOCKING[8] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_D_OPR_BLOCKING_SHFT 8 +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_ALLOC_BLOCKING_ADDR \ +WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_ALLOC_BLOCKING_MASK \ +0x00000004 /* EN_WF_PORT_ALLOC_BLOCKING[2] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_ALLOC_BLOCKING_SHFT 2 +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_ALLOC_BLOCKING_ADDR \ +WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_ALLOC_BLOCKING_MASK \ +0x00000002 /* EN_CPU_PORT_ALLOC_BLOCKING[1] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_ALLOC_BLOCKING_SHFT 1 +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_ALLOC_BLOCKING_ADDR \ +WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_ALLOC_BLOCKING_MASK \ +0x00000001 /* EN_HIF_PORT_ALLOC_BLOCKING[0] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_ALLOC_BLOCKING_SHFT 0 + +/* +* ---MACTX_SER_CTRL (0x820C0000 + 0x2A4)--- +* EN_MACTX_G0_BLOCKING[0] - (RW) Enable MACTX group 0 operation +blocking. +* RESERVED1[7..1] - (RO) Reserved bits +* EN_MACTX_G1_BLOCKING[8] - (RW) Enable MACTX group 1 operation +blocking. +* RESERVED9[15..9] - (RO) Reserved bits +* EN_MACTX_G2_BLOCKING[16] - (RW) Enable MACTX group 2 operation blocking. +* RESERVED17[23..17] - (RO) Reserved bits +* EN_MACTX_G3_BLOCKING[24] - (RW) Enable MACTX group 3 operation blocking. +* RESERVED25[31..25] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G3_BLOCKING_ADDR \ +WF_PLE_TOP_MACTX_SER_CTRL_ADDR +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G3_BLOCKING_MASK \ +0x01000000 /* EN_MACTX_G3_BLOCKING[24] */ +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G3_BLOCKING_SHFT 24 +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G2_BLOCKING_ADDR \ +WF_PLE_TOP_MACTX_SER_CTRL_ADDR +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G2_BLOCKING_MASK \ +0x00010000 /* EN_MACTX_G2_BLOCKING[16] */ +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G2_BLOCKING_SHFT 16 +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G1_BLOCKING_ADDR \ +WF_PLE_TOP_MACTX_SER_CTRL_ADDR +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G1_BLOCKING_MASK \ +0x00000100 /* EN_MACTX_G1_BLOCKING[8] */ +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G1_BLOCKING_SHFT 8 +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G0_BLOCKING_ADDR \ +WF_PLE_TOP_MACTX_SER_CTRL_ADDR +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G0_BLOCKING_MASK \ +0x00000001 /* EN_MACTX_G0_BLOCKING[0] */ +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G0_BLOCKING_SHFT 0 + +/* +* ---DRR_SER_CTRL (0x820C0000 + 0x2A8)--- +* EN_DRR_CHARGE_BLOCKING[0] - (RW) Enable DRR charge operation blocking. +* RESERVED1[3..1] - (RO) Reserved bits +* EN_DRR_SRCH_0_BLOCKING[4] - (RW) Enable DRR search 0 operation blocking. +* EN_DRR_SRCH_1_BLOCKING[5] - (RW) Enable DRR search 1 operation blocking. +* RESERVED6[7..6] - (RO) Reserved bits +* EN_DRR_RDG_0_BLOCKING[8] - (RW) Enable DRR RDG 0 operation blocking. +* EN_DRR_RDG_1_BLOCKING[9] - (RW) Enable DRR RDG 1 operation blocking. +* RESERVED10[31..10] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_RDG_1_BLOCKING_ADDR \ +WF_PLE_TOP_DRR_SER_CTRL_ADDR +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_RDG_1_BLOCKING_MASK \ +0x00000200 /* EN_DRR_RDG_1_BLOCKING[9] */ +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_RDG_1_BLOCKING_SHFT 9 +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_RDG_0_BLOCKING_ADDR \ +WF_PLE_TOP_DRR_SER_CTRL_ADDR +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_RDG_0_BLOCKING_MASK \ +0x00000100 /* EN_DRR_RDG_0_BLOCKING[8] */ +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_RDG_0_BLOCKING_SHFT 8 +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_SRCH_1_BLOCKING_ADDR \ +WF_PLE_TOP_DRR_SER_CTRL_ADDR +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_SRCH_1_BLOCKING_MASK \ +0x00000020 /* EN_DRR_SRCH_1_BLOCKING[5] */ +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_SRCH_1_BLOCKING_SHFT 5 +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_SRCH_0_BLOCKING_ADDR \ +WF_PLE_TOP_DRR_SER_CTRL_ADDR +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_SRCH_0_BLOCKING_MASK \ +0x00000010 /* EN_DRR_SRCH_0_BLOCKING[4] */ +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_SRCH_0_BLOCKING_SHFT 4 +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_CHARGE_BLOCKING_ADDR \ +WF_PLE_TOP_DRR_SER_CTRL_ADDR +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_CHARGE_BLOCKING_MASK \ +0x00000001 /* EN_DRR_CHARGE_BLOCKING[0] */ +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_CHARGE_BLOCKING_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL5 (0x820C0000 + 0x2c0)--- +* SRAM5_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM5 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL5_SRAM5_MBIST_DELSEL_ADDR \ +WF_PLE_TOP_SRAM_MBIST_DELSEL5_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL5_SRAM5_MBIST_DELSEL_MASK \ +0xFFFFFFFF /* SRAM5_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL5_SRAM5_MBIST_DELSEL_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL6 (0x820C0000 + 0x2c4)--- +* SRAM6_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM6 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL6_SRAM6_MBIST_DELSEL_ADDR \ +WF_PLE_TOP_SRAM_MBIST_DELSEL6_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL6_SRAM6_MBIST_DELSEL_MASK \ +0xFFFFFFFF /* SRAM6_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL6_SRAM6_MBIST_DELSEL_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL7 (0x820C0000 + 0x2c8)--- +* SRAM7_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM7 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL7_SRAM7_MBIST_DELSEL_ADDR \ +WF_PLE_TOP_SRAM_MBIST_DELSEL7_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL7_SRAM7_MBIST_DELSEL_MASK \ +0xFFFFFFFF /* SRAM7_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL7_SRAM7_MBIST_DELSEL_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL8 (0x820C0000 + 0x2cc)--- +* SRAM8_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM8 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL8_SRAM8_MBIST_DELSEL_ADDR \ +WF_PLE_TOP_SRAM_MBIST_DELSEL8_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL8_SRAM8_MBIST_DELSEL_MASK \ +0xFFFFFFFF /* SRAM8_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL8_SRAM8_MBIST_DELSEL_SHFT 0 + +/* +* ---SRAM_MBIST_BACKGROUND (0x820C0000 + 0x2d0)--- +* MBIST_BACKGROUND[15..0] - (RW) bsel setting for PLE SRAM MBIST circuit +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SRAM_MBIST_BACKGROUND_MBIST_BACKGROUND_ADDR \ +WF_PLE_TOP_SRAM_MBIST_BACKGROUND_ADDR +#define WF_PLE_TOP_SRAM_MBIST_BACKGROUND_MBIST_BACKGROUND_MASK \ +0x0000FFFF /* MBIST_BACKGROUND[15..0] */ +#define WF_PLE_TOP_SRAM_MBIST_BACKGROUND_MBIST_BACKGROUND_SHFT 0 + +/* +* ---SRAM_MBIST_BSEL (0x820C0000 + 0x2d4)--- +* MBIST_BSEL[15..0] - (RW) The bsel setting for PLE SRAM MBIST +circuit. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SRAM_MBIST_BSEL_MBIST_BSEL_ADDR \ +WF_PLE_TOP_SRAM_MBIST_BSEL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_BSEL_MBIST_BSEL_MASK \ +0x0000FFFF /* MBIST_BSEL[15..0] */ +#define WF_PLE_TOP_SRAM_MBIST_BSEL_MBIST_BSEL_SHFT 0 + +/* +* ---SRAM_MBIST_DONE (0x820C0000 + 0x2d8)--- +* G1_MBIST_DONE[0] - (RO) Working status of PLE G1 SRAM MBIST +circuit +* G2_MBIST_DONE[1] - (RO) Working status of PLE G2 SRAM MBIST +circuit +* RESERVED2[31..2] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SRAM_MBIST_DONE_G2_MBIST_DONE_ADDR \ +WF_PLE_TOP_SRAM_MBIST_DONE_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DONE_G2_MBIST_DONE_MASK \ +0x00000002 /* G2_MBIST_DONE[1] */ +#define WF_PLE_TOP_SRAM_MBIST_DONE_G2_MBIST_DONE_SHFT 1 +#define WF_PLE_TOP_SRAM_MBIST_DONE_G1_MBIST_DONE_ADDR \ +WF_PLE_TOP_SRAM_MBIST_DONE_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DONE_G1_MBIST_DONE_MASK \ +0x00000001 /* G1_MBIST_DONE[0] */ +#define WF_PLE_TOP_SRAM_MBIST_DONE_G1_MBIST_DONE_SHFT 0 + +/* +* ---SRAM_MBIST_FAIL (0x820C0000 + 0x2dc)--- +* G1_SRAM0_MBIST_FAIL[0] - (RO) MBIST check result of group 1 SRAM0 +* G1_SRAM1_MBIST_FAIL[1] - (RO) MBIST check result of group 1 SRAM1 +* G1_SRAM2_MBIST_FAIL[2] - (RO) MBIST check result of group 1 SRAM2 +* G1_SRAM3_MBIST_FAIL[3] - (RO) MBIST check result of group 1 SRAM3 +* G2_SRAM0_MBIST_FAIL[4] - (RO) MBIST check result of group 2 SRAM0 +* G2_SRAM1_MBIST_FAIL[5] - (RO) MBIST check result of group 2 SRAM1 +* G2_SRAM2_MBIST_FAIL[6] - (RO) MBIST check result of group 2 SRAM2 +* G2_SRAM3_MBIST_FAIL[7] - (RO) MBIST check result of group 2 SRAM3 +* G2_SRAM4_MBIST_FAIL[8] - (RO) MBIST check result of group 2 SRAM4 +* G2_SRAM5_MBIST_FAIL[9] - (RO) MBIST check result of group 2 SRAM5 +* RESERVED10[31..10] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM5_MBIST_FAIL_ADDR \ +WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM5_MBIST_FAIL_MASK \ +0x00000200 /* G2_SRAM5_MBIST_FAIL[9] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM5_MBIST_FAIL_SHFT 9 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM4_MBIST_FAIL_ADDR \ +WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM4_MBIST_FAIL_MASK \ +0x00000100 /* G2_SRAM4_MBIST_FAIL[8] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM4_MBIST_FAIL_SHFT 8 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM3_MBIST_FAIL_ADDR \ +WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM3_MBIST_FAIL_MASK \ +0x00000080 /* G2_SRAM3_MBIST_FAIL[7] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM3_MBIST_FAIL_SHFT 7 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM2_MBIST_FAIL_ADDR \ +WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM2_MBIST_FAIL_MASK \ +0x00000040 /* G2_SRAM2_MBIST_FAIL[6] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM2_MBIST_FAIL_SHFT 6 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM1_MBIST_FAIL_ADDR \ +WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM1_MBIST_FAIL_MASK \ +0x00000020 /* G2_SRAM1_MBIST_FAIL[5] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM1_MBIST_FAIL_SHFT 5 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM0_MBIST_FAIL_ADDR \ +WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM0_MBIST_FAIL_MASK \ +0x00000010 /* G2_SRAM0_MBIST_FAIL[4] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM0_MBIST_FAIL_SHFT 4 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM3_MBIST_FAIL_ADDR \ +WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM3_MBIST_FAIL_MASK \ +0x00000008 /* G1_SRAM3_MBIST_FAIL[3] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM3_MBIST_FAIL_SHFT 3 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM2_MBIST_FAIL_ADDR \ +WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM2_MBIST_FAIL_MASK \ +0x00000004 /* G1_SRAM2_MBIST_FAIL[2] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM2_MBIST_FAIL_SHFT 2 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM1_MBIST_FAIL_ADDR \ +WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM1_MBIST_FAIL_MASK \ +0x00000002 /* G1_SRAM1_MBIST_FAIL[1] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM1_MBIST_FAIL_SHFT 1 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM0_MBIST_FAIL_ADDR \ +WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM0_MBIST_FAIL_MASK \ +0x00000001 /* G1_SRAM0_MBIST_FAIL[0] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM0_MBIST_FAIL_SHFT 0 + +/* +* ---SRAM_MBIST_CTRL (0x820C0000 + 0x2e0)--- +* G1_MBIST_MODE[0] - (RW) Control register for mbist_mode of group +* 1 MBIST +* G2_MBIST_MODE[1] - (RW) Control register for mbist_mode of group +* 2 MBIST +* RESERVED2[3..2] - (RO) Reserved bits +* G1_MBIST_HOLDB[4] - (RW) Control register for mbist_holdb of +* group 1 MBIST +* G2_MBIST_HOLDB[5] - (RW) Control register for mbist_holdb of +* group 2 MBIST +* RESERVED6[7..6] - (RO) Reserved bits +* G1_MBIST_DEBUG[8] - (RW) Control register for mbist_debug of +* group 1 MBIST +* G2_MBIST_DEBUG[9] - (RW) Control register for mbist_debug of +* group 2 MBIST +* G1_MBIST_USE_DEFAULT_DELSEL[10] - (RW) Control register for default DELSEL +* value of group 1 memory +* G2_MBIST_USE_DEFAULT_DELSEL[11] - (RW) Control register for default DELSEL +* value of group 2 memory +* MBIST_DIAG_SEL[16..12] - (RW) Selection register for +mbist_diag_scan_out +* RESERVED17[19..17] - (RO) Reserved bits +* UMAC_MBIST_DIAG_SEL[20] - (RW) Selection register for UMAC +* mbist_diag_scan_out (PLE or PSE) +* RESERVED21[23..21] - (RO) Reserved bits +* G1_MBIST_SLEEP_TEST[24] - (RW) Control register for sleep_test of group +* 1 MBIST +* G1_MBIST_SLEEP_INV[25] - (RW) Control register for sleep_inv of group +* 1 MBIST +* G1_MBIST_SLEEP_W[26] - (RW) Control register for sleep_w of group 1 +MBIST +* G1_MBIST_SLEEP_R[27] - (RW) Control register for sleep_r of group 1 +MBIST +* G2_MBIST_SLEEP_TEST[28] - (RW) Control register for sleep_test of group +* 2 MBIST +* G2_MBIST_SLEEP_INV[29] - (RW) Control register for sleep_inv of group +* 2 MBIST +* G2_MBIST_SLEEP_W[30] - (RW) Control register for sleep_w of group 2 +MBIST +* G2_MBIST_SLEEP_R[31] - (RW) Control register for sleep_r of group 2 +MBIST +*/ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_R_ADDR \ +WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_R_MASK \ +0x80000000 /* G2_MBIST_SLEEP_R[31] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_R_SHFT 31 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_W_ADDR \ +WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_W_MASK \ +0x40000000 /* G2_MBIST_SLEEP_W[30] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_W_SHFT 30 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_INV_ADDR \ +WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_INV_MASK \ +0x20000000 /* G2_MBIST_SLEEP_INV[29] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_INV_SHFT 29 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_TEST_ADDR \ +WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_TEST_MASK \ +0x10000000 /* G2_MBIST_SLEEP_TEST[28] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_TEST_SHFT 28 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_R_ADDR \ +WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_R_MASK \ +0x08000000 /* G1_MBIST_SLEEP_R[27] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_R_SHFT 27 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_W_ADDR \ +WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_W_MASK \ +0x04000000 /* G1_MBIST_SLEEP_W[26] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_W_SHFT 26 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_INV_ADDR \ +WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_INV_MASK \ +0x02000000 /* G1_MBIST_SLEEP_INV[25] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_INV_SHFT 25 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_TEST_ADDR \ +WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_TEST_MASK \ +0x01000000 /* G1_MBIST_SLEEP_TEST[24] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_TEST_SHFT 24 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_UMAC_MBIST_DIAG_SEL_ADDR \ +WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_UMAC_MBIST_DIAG_SEL_MASK \ +0x00100000 /* UMAC_MBIST_DIAG_SEL[20] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_UMAC_MBIST_DIAG_SEL_SHFT 20 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_MBIST_DIAG_SEL_ADDR \ +WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_MBIST_DIAG_SEL_MASK \ +0x0001F000 /* MBIST_DIAG_SEL[16..12] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_MBIST_DIAG_SEL_SHFT 12 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_USE_DEFAULT_DELSEL_ADDR \ +WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_USE_DEFAULT_DELSEL_MASK \ +0x00000800 /* G2_MBIST_USE_DEFAULT_DELSEL[11] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_USE_DEFAULT_DELSEL_SHFT 11 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_USE_DEFAULT_DELSEL_ADDR \ +WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_USE_DEFAULT_DELSEL_MASK \ +0x00000400 /* G1_MBIST_USE_DEFAULT_DELSEL[10] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_USE_DEFAULT_DELSEL_SHFT 10 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_DEBUG_ADDR \ +WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_DEBUG_MASK \ +0x00000200 /* G2_MBIST_DEBUG[9] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_DEBUG_SHFT 9 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_DEBUG_ADDR \ +WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_DEBUG_MASK \ +0x00000100 /* G1_MBIST_DEBUG[8] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_DEBUG_SHFT 8 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_HOLDB_ADDR \ +WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_HOLDB_MASK \ +0x00000020 /* G2_MBIST_HOLDB[5] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_HOLDB_SHFT 5 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_HOLDB_ADDR \ +WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_HOLDB_MASK \ +0x00000010 /* G1_MBIST_HOLDB[4] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_HOLDB_SHFT 4 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_MODE_ADDR \ +WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_MODE_MASK \ +0x00000002 /* G2_MBIST_MODE[1] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_MODE_SHFT 1 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_MODE_ADDR \ +WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_MODE_MASK \ +0x00000001 /* G1_MBIST_MODE[0] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_MODE_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL1 (0x820C0000 + 0x2e4)--- +* SRAM1_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM1 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL1_SRAM1_MBIST_DELSEL_ADDR \ +WF_PLE_TOP_SRAM_MBIST_DELSEL1_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL1_SRAM1_MBIST_DELSEL_MASK \ +0xFFFFFFFF /* SRAM1_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL1_SRAM1_MBIST_DELSEL_SHFT 0 + +/* +* ---BSS_DBDC_CTRL (0x820C0000 + 0x2ec)--- +* BSS_BAND_SEL[15..0] - (RW) Select band of each BSS +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_BSS_DBDC_CTRL_BSS_BAND_SEL_ADDR WF_PLE_TOP_BSS_DBDC_CTRL_ADDR +#define WF_PLE_TOP_BSS_DBDC_CTRL_BSS_BAND_SEL_MASK \ +0x0000FFFF /* BSS_BAND_SEL[15..0] */ +#define WF_PLE_TOP_BSS_DBDC_CTRL_BSS_BAND_SEL_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL2 (0x820C0000 + 0x2f0)--- +* SRAM2_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM2 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL2_SRAM2_MBIST_DELSEL_ADDR \ +WF_PLE_TOP_SRAM_MBIST_DELSEL2_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL2_SRAM2_MBIST_DELSEL_MASK \ +0xFFFFFFFF /* SRAM2_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL2_SRAM2_MBIST_DELSEL_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL3 (0x820C0000 + 0x2f4)--- +* SRAM3_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM3 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL3_SRAM3_MBIST_DELSEL_ADDR \ +WF_PLE_TOP_SRAM_MBIST_DELSEL3_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL3_SRAM3_MBIST_DELSEL_MASK \ +0xFFFFFFFF /* SRAM3_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL3_SRAM3_MBIST_DELSEL_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL4 (0x820C0000 + 0x2f8)--- +* SRAM4_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM4 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL4_SRAM4_MBIST_DELSEL_ADDR \ +WF_PLE_TOP_SRAM_MBIST_DELSEL4_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL4_SRAM4_MBIST_DELSEL_MASK \ +0xFFFFFFFF /* SRAM4_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL4_SRAM4_MBIST_DELSEL_SHFT 0 + +/* +* ---SRAM_AWT_HDEN_CTRL (0x820C0000 + 0x2fc)--- +* SRAM_AWT_CTRL[13..0] - (RW) AWT setting of SRAMS +* RESERVED14[15..14] - (RO) Reserved bits +* SRAM_HDEN_CTRL[29..16] - (RW) HDEN setting of SRAMS +* RESERVED30[31..30] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_SRAM_HDEN_CTRL_ADDR \ +WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_SRAM_HDEN_CTRL_MASK \ +0x3FFF0000 /* SRAM_HDEN_CTRL[29..16] */ +#define WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_SRAM_HDEN_CTRL_SHFT 16 +#define WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_SRAM_AWT_CTRL_ADDR \ +WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_SRAM_AWT_CTRL_MASK \ +0x00003FFF /* SRAM_AWT_CTRL[13..0] */ +#define WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_SRAM_AWT_CTRL_SHFT 0 + +/* +* ---PREDL_CTRL (0x820C0000 + 0x300)--- +* EN_PREDL[0] - (RW) Enable control of pre-download function +* RESERVED1[15..1] - (RO) Reserved bits +* BN0_PREDL_CLEAN_QID[22..16] - (RW) QID for clean BN0 PREDL buffer command. +* BN0_PREDL_CLEAN_EXECUTE[23] - (A0) Executes clean BN0 PREDL buffer command. +* BN1_PREDL_CLEAN_QID[30..24] - (RW) QID for clean BN1 PREDL buffer command. +* BN1_PREDL_CLEAN_EXECUTE[31] - (A0) Executes clean BN1 PREDL buffer command. +*/ +#define WF_PLE_TOP_PREDL_CTRL_BN1_PREDL_CLEAN_EXECUTE_ADDR \ +WF_PLE_TOP_PREDL_CTRL_ADDR +#define WF_PLE_TOP_PREDL_CTRL_BN1_PREDL_CLEAN_EXECUTE_MASK \ +0x80000000 /* BN1_PREDL_CLEAN_EXECUTE[31] */ +#define WF_PLE_TOP_PREDL_CTRL_BN1_PREDL_CLEAN_EXECUTE_SHFT 31 +#define WF_PLE_TOP_PREDL_CTRL_BN1_PREDL_CLEAN_QID_ADDR \ +WF_PLE_TOP_PREDL_CTRL_ADDR +#define WF_PLE_TOP_PREDL_CTRL_BN1_PREDL_CLEAN_QID_MASK \ +0x7F000000 /* BN1_PREDL_CLEAN_QID[30..24] */ +#define WF_PLE_TOP_PREDL_CTRL_BN1_PREDL_CLEAN_QID_SHFT 24 +#define WF_PLE_TOP_PREDL_CTRL_BN0_PREDL_CLEAN_EXECUTE_ADDR \ +WF_PLE_TOP_PREDL_CTRL_ADDR +#define WF_PLE_TOP_PREDL_CTRL_BN0_PREDL_CLEAN_EXECUTE_MASK \ +0x00800000 /* BN0_PREDL_CLEAN_EXECUTE[23] */ +#define WF_PLE_TOP_PREDL_CTRL_BN0_PREDL_CLEAN_EXECUTE_SHFT 23 +#define WF_PLE_TOP_PREDL_CTRL_BN0_PREDL_CLEAN_QID_ADDR \ +WF_PLE_TOP_PREDL_CTRL_ADDR +#define WF_PLE_TOP_PREDL_CTRL_BN0_PREDL_CLEAN_QID_MASK \ +0x007F0000 /* BN0_PREDL_CLEAN_QID[22..16] */ +#define WF_PLE_TOP_PREDL_CTRL_BN0_PREDL_CLEAN_QID_SHFT 16 +#define WF_PLE_TOP_PREDL_CTRL_EN_PREDL_ADDR WF_PLE_TOP_PREDL_CTRL_ADDR +#define WF_PLE_TOP_PREDL_CTRL_EN_PREDL_MASK 0x00000001 /* EN_PREDL[0] */ +#define WF_PLE_TOP_PREDL_CTRL_EN_PREDL_SHFT 0 + +/* +* ---PREDL_CTRL1 (0x820C0000 + 0x304)--- +* PREDL_WMMAC_ENABLE[25..0] - (RW) Enable control of pre-download function +* per queue control. +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PREDL_CTRL1_PREDL_WMMAC_ENABLE_ADDR \ +WF_PLE_TOP_PREDL_CTRL1_ADDR +#define WF_PLE_TOP_PREDL_CTRL1_PREDL_WMMAC_ENABLE_MASK \ +0x03FFFFFF /* PREDL_WMMAC_ENABLE[25..0] */ +#define WF_PLE_TOP_PREDL_CTRL1_PREDL_WMMAC_ENABLE_SHFT 0 + +/* +* ---PREDL_BN0_LEN0 (0x820C0000 + 0x330)--- +* BUF_SIZE[15..0] - (RW) Pre-Download Per TXCMD buffer size +limit. +* BUF_SIZE_OF_TXOP[31..16] - (RW) Pre-Download Per TXCMD buffer size limit +* under TXOP. +*/ +#define WF_PLE_TOP_PREDL_BN0_LEN0_BUF_SIZE_OF_TXOP_ADDR \ +WF_PLE_TOP_PREDL_BN0_LEN0_ADDR +#define WF_PLE_TOP_PREDL_BN0_LEN0_BUF_SIZE_OF_TXOP_MASK \ +0xFFFF0000 /* BUF_SIZE_OF_TXOP[31..16] */ +#define WF_PLE_TOP_PREDL_BN0_LEN0_BUF_SIZE_OF_TXOP_SHFT 16 +#define WF_PLE_TOP_PREDL_BN0_LEN0_BUF_SIZE_ADDR WF_PLE_TOP_PREDL_BN0_LEN0_ADDR +#define WF_PLE_TOP_PREDL_BN0_LEN0_BUF_SIZE_MASK 0x0000FFFF /* BUF_SIZE[15..0]\ + */ +#define WF_PLE_TOP_PREDL_BN0_LEN0_BUF_SIZE_SHFT 0 + +/* +* ---PREDL_BN0_LEN1 (0x820C0000 + 0x334)--- +* STA_NUM[5..0] - (RW) Pre-Download Per TXCMD station number +limit. +* RESERVED6[7..6] - (RO) Reserved bits +* PKT_LIMIT[13..8] - (RW) Pre-Download Per TXCMD packet number +limit. +* RESERVED14[15..14] - (RO) Reserved bits +* TOTAL_BUF_SIZE[31..16] - (RW) Pre-Download total buffer size limit. +*/ +#define WF_PLE_TOP_PREDL_BN0_LEN1_TOTAL_BUF_SIZE_ADDR \ +WF_PLE_TOP_PREDL_BN0_LEN1_ADDR +#define WF_PLE_TOP_PREDL_BN0_LEN1_TOTAL_BUF_SIZE_MASK \ +0xFFFF0000 /* TOTAL_BUF_SIZE[31..16] */ +#define WF_PLE_TOP_PREDL_BN0_LEN1_TOTAL_BUF_SIZE_SHFT 16 +#define WF_PLE_TOP_PREDL_BN0_LEN1_PKT_LIMIT_ADDR WF_PLE_TOP_PREDL_BN0_LEN1_ADDR +#define WF_PLE_TOP_PREDL_BN0_LEN1_PKT_LIMIT_MASK \ +0x00003F00 /* PKT_LIMIT[13..8] */ +#define WF_PLE_TOP_PREDL_BN0_LEN1_PKT_LIMIT_SHFT 8 +#define WF_PLE_TOP_PREDL_BN0_LEN1_STA_NUM_ADDR WF_PLE_TOP_PREDL_BN0_LEN1_ADDR +#define WF_PLE_TOP_PREDL_BN0_LEN1_STA_NUM_MASK 0x0000003F /* STA_NUM[5..0] */ +#define WF_PLE_TOP_PREDL_BN0_LEN1_STA_NUM_SHFT 0 + +/* +* ---PREDL_BN1_LEN0 (0x820C0000 + 0x338)--- +* BUF_SIZE[15..0] - (RW) Pre-Download Per TXCMD buffer size +limit. +* BUF_SIZE_OF_TXOP[31..16] - (RW) Pre-Download Per TXCMD buffer size limit +* under TXOP. +*/ +#define WF_PLE_TOP_PREDL_BN1_LEN0_BUF_SIZE_OF_TXOP_ADDR \ +WF_PLE_TOP_PREDL_BN1_LEN0_ADDR +#define WF_PLE_TOP_PREDL_BN1_LEN0_BUF_SIZE_OF_TXOP_MASK \ +0xFFFF0000 /* BUF_SIZE_OF_TXOP[31..16] */ +#define WF_PLE_TOP_PREDL_BN1_LEN0_BUF_SIZE_OF_TXOP_SHFT 16 +#define WF_PLE_TOP_PREDL_BN1_LEN0_BUF_SIZE_ADDR WF_PLE_TOP_PREDL_BN1_LEN0_ADDR +#define WF_PLE_TOP_PREDL_BN1_LEN0_BUF_SIZE_MASK 0x0000FFFF /* BUF_SIZE[15..0]\ + */ +#define WF_PLE_TOP_PREDL_BN1_LEN0_BUF_SIZE_SHFT 0 + +/* +* ---PREDL_BN1_LEN1 (0x820C0000 + 0x33c)--- +* STA_NUM[5..0] - (RW) Pre-Download Per TXCMD station number +limit. +* RESERVED6[7..6] - (RO) Reserved bits +* PKT_LIMIT[13..8] - (RW) Pre-Download Per TXCMD packet number +limit. +* RESERVED14[15..14] - (RO) Reserved bits +* TOTAL_BUF_SIZE[31..16] - (RW) Pre-Download total buffer size limit. +*/ +#define WF_PLE_TOP_PREDL_BN1_LEN1_TOTAL_BUF_SIZE_ADDR \ +WF_PLE_TOP_PREDL_BN1_LEN1_ADDR +#define WF_PLE_TOP_PREDL_BN1_LEN1_TOTAL_BUF_SIZE_MASK \ +0xFFFF0000 /* TOTAL_BUF_SIZE[31..16] */ +#define WF_PLE_TOP_PREDL_BN1_LEN1_TOTAL_BUF_SIZE_SHFT 16 +#define WF_PLE_TOP_PREDL_BN1_LEN1_PKT_LIMIT_ADDR WF_PLE_TOP_PREDL_BN1_LEN1_ADDR +#define WF_PLE_TOP_PREDL_BN1_LEN1_PKT_LIMIT_MASK \ +0x00003F00 /* PKT_LIMIT[13..8] */ +#define WF_PLE_TOP_PREDL_BN1_LEN1_PKT_LIMIT_SHFT 8 +#define WF_PLE_TOP_PREDL_BN1_LEN1_STA_NUM_ADDR WF_PLE_TOP_PREDL_BN1_LEN1_ADDR +#define WF_PLE_TOP_PREDL_BN1_LEN1_STA_NUM_MASK 0x0000003F /* STA_NUM[5..0] */ +#define WF_PLE_TOP_PREDL_BN1_LEN1_STA_NUM_SHFT 0 + +/* +* ---DRR_TABLE_WDATA0 (0x820C0000 + 0x340)--- +* DRR_TABLE_WDATA[31..0] - (RW) DRRwdata[31:0] for reading/writing DRR +table +* Mode 0x2?: DRR station mode +* WData[15:0]: Sta setting +* WData[127:16]: Reserved +* Mode 0x4?: BSS mode +* See SRAM layout. +* Mode 0x8?: Charge mode +* WData [15:0]: Charge length (unit: +byte) +* WData [31:16]: Charge time 9 unit +1.024us +* WData[127:32]: Reserved +*/ +#define WF_PLE_TOP_DRR_TABLE_WDATA0_DRR_TABLE_WDATA_ADDR \ +WF_PLE_TOP_DRR_TABLE_WDATA0_ADDR +#define WF_PLE_TOP_DRR_TABLE_WDATA0_DRR_TABLE_WDATA_MASK \ +0xFFFFFFFF /* DRR_TABLE_WDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_WDATA0_DRR_TABLE_WDATA_SHFT 0 + +/* +* ---DRR_TABLE_WDATA1 (0x820C0000 + 0x344)--- +* DRR_TABLE_WDATA[31..0] - (RW) DRR wdata[63:32] for reading/writing DRR +table +*/ +#define WF_PLE_TOP_DRR_TABLE_WDATA1_DRR_TABLE_WDATA_ADDR \ +WF_PLE_TOP_DRR_TABLE_WDATA1_ADDR +#define WF_PLE_TOP_DRR_TABLE_WDATA1_DRR_TABLE_WDATA_MASK \ +0xFFFFFFFF /* DRR_TABLE_WDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_WDATA1_DRR_TABLE_WDATA_SHFT 0 + +/* +* ---DRR_TABLE_WDATA2 (0x820C0000 + 0x348)--- +* DRR_TABLE_WDATA[31..0] - (RW) DRR wdata[95:64] for reading/writing DRR +table +*/ +#define WF_PLE_TOP_DRR_TABLE_WDATA2_DRR_TABLE_WDATA_ADDR \ +WF_PLE_TOP_DRR_TABLE_WDATA2_ADDR +#define WF_PLE_TOP_DRR_TABLE_WDATA2_DRR_TABLE_WDATA_MASK \ +0xFFFFFFFF /* DRR_TABLE_WDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_WDATA2_DRR_TABLE_WDATA_SHFT 0 + +/* +* ---DRR_TABLE_WDATA3 (0x820C0000 + 0x34c)--- +* DRR_TABLE_WDATA[31..0] - (RW) DRR wdata[127:96] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_WDATA3_DRR_TABLE_WDATA_ADDR \ +WF_PLE_TOP_DRR_TABLE_WDATA3_ADDR +#define WF_PLE_TOP_DRR_TABLE_WDATA3_DRR_TABLE_WDATA_MASK \ +0xFFFFFFFF /* DRR_TABLE_WDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_WDATA3_DRR_TABLE_WDATA_SHFT 0 + +/* +* ---DRR_TABLE_RDATA0 (0x820C0000 + 0x350)--- +* DRR_TABLE_RDATA[31..0] - (RW) DRR rdata[31:0] for reading/writing DRR +table +*/ +#define WF_PLE_TOP_DRR_TABLE_RDATA0_DRR_TABLE_RDATA_ADDR \ +WF_PLE_TOP_DRR_TABLE_RDATA0_ADDR +#define WF_PLE_TOP_DRR_TABLE_RDATA0_DRR_TABLE_RDATA_MASK \ +0xFFFFFFFF /* DRR_TABLE_RDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_RDATA0_DRR_TABLE_RDATA_SHFT 0 + +/* +* ---DRR_TABLE_RDATA1 (0x820C0000 + 0x354)--- +* DRR_TABLE_RDATA[31..0] - (RW) DRR rdata[63:32] for reading/writing DRR +table +*/ +#define WF_PLE_TOP_DRR_TABLE_RDATA1_DRR_TABLE_RDATA_ADDR \ +WF_PLE_TOP_DRR_TABLE_RDATA1_ADDR +#define WF_PLE_TOP_DRR_TABLE_RDATA1_DRR_TABLE_RDATA_MASK \ +0xFFFFFFFF /* DRR_TABLE_RDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_RDATA1_DRR_TABLE_RDATA_SHFT 0 + +/* +* ---DRR_TABLE_RDATA2 (0x820C0000 + 0x358)--- +* DRR_TABLE_RDATA[31..0] - (RW) DRR rdata[95:64] for reading/writing DRR +table +*/ +#define WF_PLE_TOP_DRR_TABLE_RDATA2_DRR_TABLE_RDATA_ADDR \ +WF_PLE_TOP_DRR_TABLE_RDATA2_ADDR +#define WF_PLE_TOP_DRR_TABLE_RDATA2_DRR_TABLE_RDATA_MASK \ +0xFFFFFFFF /* DRR_TABLE_RDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_RDATA2_DRR_TABLE_RDATA_SHFT 0 + +/* +* ---DRR_TABLE_RDATA3 (0x820C0000 + 0x35c)--- +* DRR_TABLE_RDATA[31..0] - (RW) DRR rdata[127:96] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_RDATA3_DRR_TABLE_RDATA_ADDR \ +WF_PLE_TOP_DRR_TABLE_RDATA3_ADDR +#define WF_PLE_TOP_DRR_TABLE_RDATA3_DRR_TABLE_RDATA_MASK \ +0xFFFFFFFF /* DRR_TABLE_RDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_RDATA3_DRR_TABLE_RDATA_SHFT 0 + +/* +* ---ERLY_TRM_CTRL0 (0x820C0000 + 0x360)--- +* ERLY_TRM_EN[0] - (RW) Enable control of early terminate +function +* RESERVED1[7..1] - (RO) Reserved bits +* ERLY_TRM_MPDU_TH_0[15..8] - (RW) MPDU number Threshold for TX Bit Rate <= +97.5Mbps +* ERLY_TRM_MPDU_TH_1[23..16] - (RW) MPDU number Threshold for 97.5Mbps < TX +* Bit Rate <= 195Mbps +* ERLY_TRM_MPDU_TH_2[31..24] - (RW) MPDU number Threshold for TX Bit Rate <= +97.5Mbps +*/ +#define WF_PLE_TOP_ERLY_TRM_CTRL0_ERLY_TRM_MPDU_TH_2_ADDR \ +WF_PLE_TOP_ERLY_TRM_CTRL0_ADDR +#define WF_PLE_TOP_ERLY_TRM_CTRL0_ERLY_TRM_MPDU_TH_2_MASK \ +0xFF000000 /* ERLY_TRM_MPDU_TH_2[31..24] */ +#define WF_PLE_TOP_ERLY_TRM_CTRL0_ERLY_TRM_MPDU_TH_2_SHFT 24 +#define WF_PLE_TOP_ERLY_TRM_CTRL0_ERLY_TRM_MPDU_TH_1_ADDR \ +WF_PLE_TOP_ERLY_TRM_CTRL0_ADDR +#define WF_PLE_TOP_ERLY_TRM_CTRL0_ERLY_TRM_MPDU_TH_1_MASK \ +0x00FF0000 /* ERLY_TRM_MPDU_TH_1[23..16] */ +#define WF_PLE_TOP_ERLY_TRM_CTRL0_ERLY_TRM_MPDU_TH_1_SHFT 16 +#define WF_PLE_TOP_ERLY_TRM_CTRL0_ERLY_TRM_MPDU_TH_0_ADDR \ +WF_PLE_TOP_ERLY_TRM_CTRL0_ADDR +#define WF_PLE_TOP_ERLY_TRM_CTRL0_ERLY_TRM_MPDU_TH_0_MASK \ +0x0000FF00 /* ERLY_TRM_MPDU_TH_0[15..8] */ +#define WF_PLE_TOP_ERLY_TRM_CTRL0_ERLY_TRM_MPDU_TH_0_SHFT 8 +#define WF_PLE_TOP_ERLY_TRM_CTRL0_ERLY_TRM_EN_ADDR \ +WF_PLE_TOP_ERLY_TRM_CTRL0_ADDR +#define WF_PLE_TOP_ERLY_TRM_CTRL0_ERLY_TRM_EN_MASK \ +0x00000001 /* ERLY_TRM_EN[0] */ +#define WF_PLE_TOP_ERLY_TRM_CTRL0_ERLY_TRM_EN_SHFT 0 + +/* +* ---ERLY_TRM_CTRL1 (0x820C0000 + 0x364)--- +* ERLY_TRM_MPDU_TH_3[7..0] - (RW) MPDU number Threshold for 325Mbps < TX +* Bit Rate <= 433Mbps +* ERLY_TRM_MPDU_TH_4[15..8] - (RW) MPDU number Threshold for 433Mbps < TX +* Bit Rate <= 866.7Mbps +* ERLY_TRM_MPDU_TH_5[23..16] - (RW) MPDU number Threshold for 866.7Mbps < TX +* Bit Rate <= 1300Mbps +* ERLY_TRM_MPDU_TH_6[31..24] - (RW) MPDU number Threshold for TX Bit Rate <= +97.5Mbps +*/ +#define WF_PLE_TOP_ERLY_TRM_CTRL1_ERLY_TRM_MPDU_TH_6_ADDR \ +WF_PLE_TOP_ERLY_TRM_CTRL1_ADDR +#define WF_PLE_TOP_ERLY_TRM_CTRL1_ERLY_TRM_MPDU_TH_6_MASK \ +0xFF000000 /* ERLY_TRM_MPDU_TH_6[31..24] */ +#define WF_PLE_TOP_ERLY_TRM_CTRL1_ERLY_TRM_MPDU_TH_6_SHFT 24 +#define WF_PLE_TOP_ERLY_TRM_CTRL1_ERLY_TRM_MPDU_TH_5_ADDR \ +WF_PLE_TOP_ERLY_TRM_CTRL1_ADDR +#define WF_PLE_TOP_ERLY_TRM_CTRL1_ERLY_TRM_MPDU_TH_5_MASK \ +0x00FF0000 /* ERLY_TRM_MPDU_TH_5[23..16] */ +#define WF_PLE_TOP_ERLY_TRM_CTRL1_ERLY_TRM_MPDU_TH_5_SHFT 16 +#define WF_PLE_TOP_ERLY_TRM_CTRL1_ERLY_TRM_MPDU_TH_4_ADDR \ +WF_PLE_TOP_ERLY_TRM_CTRL1_ADDR +#define WF_PLE_TOP_ERLY_TRM_CTRL1_ERLY_TRM_MPDU_TH_4_MASK \ +0x0000FF00 /* ERLY_TRM_MPDU_TH_4[15..8] */ +#define WF_PLE_TOP_ERLY_TRM_CTRL1_ERLY_TRM_MPDU_TH_4_SHFT 8 +#define WF_PLE_TOP_ERLY_TRM_CTRL1_ERLY_TRM_MPDU_TH_3_ADDR \ +WF_PLE_TOP_ERLY_TRM_CTRL1_ADDR +#define WF_PLE_TOP_ERLY_TRM_CTRL1_ERLY_TRM_MPDU_TH_3_MASK \ +0x000000FF /* ERLY_TRM_MPDU_TH_3[7..0] */ +#define WF_PLE_TOP_ERLY_TRM_CTRL1_ERLY_TRM_MPDU_TH_3_SHFT 0 + +/* +* ---VOW_CONTROL (0x820C0000 + 0x370)--- +* PER_BSS_BW_CONTROL_ENABLE[15..0] - (RW) BW control of BSSID +* REFILL_PERIOD[18..16] - (RW) Period of token refill function +* RESERVED19[19] - (RO) Reserved bits +* DBDC1_SEARCH_RULE[20] - (RW) Priority for HW search if internal +* collision occurs +* DBDC0_SEARCH_RULE[21] - (RW) Priority for HW search if internal +* collision occcurs +* RESERVED22[25..22] - (RO) Reserved bits +* DRR_LOGIC_RESET[26] - (RW) DRR logic reset control +* DIS_WTBL_PS_IGNORE[27] - (RW) Disable control of the function that STA +* with WTBL PS ignore in TXQ busy +* ENABLE_TXOP_NO_CHANGE_BSS_GROUP[28] - (RW) HW cannot change BW group In TXOP +burst. +* ENABLE_AIRTIME_FAIRNESS[29] - (RW) When airtime function is disabled, HW +* will change station without checking station qouta. +* ENABLE_TOKEN_REFILL[30] - (RW) Enable control of token refill function +* ENABLE_BW_CONTROL[31] - (RW) HW will check if there are tokens in BW +* bucket before TX. +*/ +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_BW_CONTROL_ADDR \ +WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_BW_CONTROL_MASK \ +0x80000000 /* ENABLE_BW_CONTROL[31] */ +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_BW_CONTROL_SHFT 31 +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_TOKEN_REFILL_ADDR \ +WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_TOKEN_REFILL_MASK \ +0x40000000 /* ENABLE_TOKEN_REFILL[30] */ +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_TOKEN_REFILL_SHFT 30 +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_AIRTIME_FAIRNESS_ADDR \ +WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_AIRTIME_FAIRNESS_MASK \ +0x20000000 /* ENABLE_AIRTIME_FAIRNESS[29] */ +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_AIRTIME_FAIRNESS_SHFT 29 +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_TXOP_NO_CHANGE_BSS_GROUP_ADDR \ +WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_TXOP_NO_CHANGE_BSS_GROUP_MASK \ +0x10000000 /* ENABLE_TXOP_NO_CHANGE_BSS_GROUP[28] */ +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_TXOP_NO_CHANGE_BSS_GROUP_SHFT 28 +#define WF_PLE_TOP_VOW_CONTROL_DIS_WTBL_PS_IGNORE_ADDR \ +WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_DIS_WTBL_PS_IGNORE_MASK \ +0x08000000 /* DIS_WTBL_PS_IGNORE[27] */ +#define WF_PLE_TOP_VOW_CONTROL_DIS_WTBL_PS_IGNORE_SHFT 27 +#define WF_PLE_TOP_VOW_CONTROL_DRR_LOGIC_RESET_ADDR WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_DRR_LOGIC_RESET_MASK \ +0x04000000 /* DRR_LOGIC_RESET[26] */ +#define WF_PLE_TOP_VOW_CONTROL_DRR_LOGIC_RESET_SHFT 26 +#define WF_PLE_TOP_VOW_CONTROL_DBDC0_SEARCH_RULE_ADDR \ +WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_DBDC0_SEARCH_RULE_MASK \ +0x00200000 /* DBDC0_SEARCH_RULE[21] */ +#define WF_PLE_TOP_VOW_CONTROL_DBDC0_SEARCH_RULE_SHFT 21 +#define WF_PLE_TOP_VOW_CONTROL_DBDC1_SEARCH_RULE_ADDR \ +WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_DBDC1_SEARCH_RULE_MASK \ +0x00100000 /* DBDC1_SEARCH_RULE[20] */ +#define WF_PLE_TOP_VOW_CONTROL_DBDC1_SEARCH_RULE_SHFT 20 +#define WF_PLE_TOP_VOW_CONTROL_REFILL_PERIOD_ADDR WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_REFILL_PERIOD_MASK \ +0x00070000 /* REFILL_PERIOD[18..16] */ +#define WF_PLE_TOP_VOW_CONTROL_REFILL_PERIOD_SHFT 16 +#define WF_PLE_TOP_VOW_CONTROL_PER_BSS_BW_CONTROL_ENABLE_ADDR \ +WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_PER_BSS_BW_CONTROL_ENABLE_MASK \ +0x0000FFFF /* PER_BSS_BW_CONTROL_ENABLE[15..0] */ +#define WF_PLE_TOP_VOW_CONTROL_PER_BSS_BW_CONTROL_ENABLE_SHFT 0 + +/* +* ---AIRTIME_DRR_SIZE (0x820C0000 + 0x374)--- +* AIRTIME_DEFICIT_BOUNDARY[7..0] - (RW) Limits airtime DRR's maximum deficit +* Unit: 256us +* RESERVED2[15..8] - (RW) xxx +* BW_DEFICIT_BOUNDARY[23..16] - (RW) Limits BW DRR's maximum deficit +* Unit: 256us +* DRR_TXCNT_SIZE[31..24] - (RW) Tx count mode charge time setting +* Unit: 256us +*/ +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_DRR_TXCNT_SIZE_ADDR \ +WF_PLE_TOP_AIRTIME_DRR_SIZE_ADDR +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_DRR_TXCNT_SIZE_MASK \ +0xFF000000 /* DRR_TXCNT_SIZE[31..24] */ +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_DRR_TXCNT_SIZE_SHFT 24 +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_BW_DEFICIT_BOUNDARY_ADDR \ +WF_PLE_TOP_AIRTIME_DRR_SIZE_ADDR +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_BW_DEFICIT_BOUNDARY_MASK \ +0x00FF0000 /* BW_DEFICIT_BOUNDARY[23..16] */ +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_BW_DEFICIT_BOUNDARY_SHFT 16 +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_RESERVED2_ADDR \ +WF_PLE_TOP_AIRTIME_DRR_SIZE_ADDR +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_RESERVED2_MASK \ +0x0000FF00 /* RESERVED2[15..8] */ +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_RESERVED2_SHFT 8 +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_AIRTIME_DEFICIT_BOUNDARY_ADDR \ +WF_PLE_TOP_AIRTIME_DRR_SIZE_ADDR +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_AIRTIME_DEFICIT_BOUNDARY_MASK \ +0x000000FF /* AIRTIME_DEFICIT_BOUNDARY[7..0] */ +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_AIRTIME_DEFICIT_BOUNDARY_SHFT 0 + +/* +* ---CHECK_BW_TIME_TOKEN_ (0x820C0000 + 0x378)--- +* DISABLE_BW_TIME_CHECK[15..0] - (RW) HW will ignore time token status. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CHECK_BW_TIME_TOKEN__DISABLE_BW_TIME_CHECK_ADDR \ +WF_PLE_TOP_CHECK_BW_TIME_TOKEN__ADDR +#define WF_PLE_TOP_CHECK_BW_TIME_TOKEN__DISABLE_BW_TIME_CHECK_MASK \ +0x0000FFFF /* DISABLE_BW_TIME_CHECK[15..0] */ +#define WF_PLE_TOP_CHECK_BW_TIME_TOKEN__DISABLE_BW_TIME_CHECK_SHFT 0 + +/* +* ---CHECK_BW_LENGTH_TOKEN_ (0x820C0000 + 0x37c)--- +* DISABLE_BW_LENGTH_CHECK[15..0] - (RW) HW will ignore time token status. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CHECK_BW_LENGTH_TOKEN__DISABLE_BW_LENGTH_CHECK_ADDR \ +WF_PLE_TOP_CHECK_BW_LENGTH_TOKEN__ADDR +#define WF_PLE_TOP_CHECK_BW_LENGTH_TOKEN__DISABLE_BW_LENGTH_CHECK_MASK \ +0x0000FFFF /* DISABLE_BW_LENGTH_CHECK[15..0] */ +#define WF_PLE_TOP_CHECK_BW_LENGTH_TOKEN__DISABLE_BW_LENGTH_CHECK_SHFT 0 + +/* +* ---AIRTIME_QUANTUM_SETTING0 (0x820C0000 + 0x380)--- +* AIRTIME_QUANTUM0[7..0] - (RW) Airtime quantum 0 +* AIRTIME_QUANTUM1[15..8] - (RW) Airtime quantum 1 +* AIRTIME_QUANTUM2[23..16] - (RW) Airtime quantum 2 +* AIRTIME_QUANTUM3[31..24] - (RW) Airtime quantum 3 +*/ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM3_ADDR \ +WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_ADDR +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM3_MASK \ +0xFF000000 /* AIRTIME_QUANTUM3[31..24] */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM3_SHFT 24 +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM2_ADDR \ +WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_ADDR +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM2_MASK \ +0x00FF0000 /* AIRTIME_QUANTUM2[23..16] */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM2_SHFT 16 +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM1_ADDR \ +WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_ADDR +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM1_MASK \ +0x0000FF00 /* AIRTIME_QUANTUM1[15..8] */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM1_SHFT 8 +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM0_ADDR \ +WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_ADDR +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM0_MASK \ +0x000000FF /* AIRTIME_QUANTUM0[7..0] */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM0_SHFT 0 + +/* +* ---AIRTIME_QUANTUM_SETTING1 (0x820C0000 + 0x384)--- +* AIRTIME_QUANTUM4[7..0] - (RW) Airtime quantum 4 +* AIRTIME_QUANTUM5[15..8] - (RW) Airtime quantum 5 +* AIRTIME_QUANTUM6[23..16] - (RW) Airtime quantum 6 +* AIRTIME_QUANTUM7[31..24] - (RW) Airtime quantum 7 +*/ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM7_ADDR \ +WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_ADDR +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM7_MASK \ +0xFF000000 /* AIRTIME_QUANTUM7[31..24] */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM7_SHFT 24 +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM6_ADDR \ +WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_ADDR +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM6_MASK \ +0x00FF0000 /* AIRTIME_QUANTUM6[23..16] */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM6_SHFT 16 +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM5_ADDR \ +WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_ADDR +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM5_MASK \ +0x0000FF00 /* AIRTIME_QUANTUM5[15..8] */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM5_SHFT 8 +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM4_ADDR \ +WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_ADDR +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM4_MASK \ +0x000000FF /* AIRTIME_QUANTUM4[7..0] */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM4_SHFT 0 + +/* +* ---DRR_TABLE_CTRL (0x820C0000 + 0x388)--- +* INDEX[11..0] - (RW) Operation index +* Mode 0x00: DRR STA link, STA relay +* Bit[1:0]: qid +* Bit[10:2]: Station ID +//-- +* Mode 0x20: addr[6:0] mean station ID +* Mode 0x21: addr[6:0] mean station ID +* Mode 0x22: SRAM idx (debug mode) +* Mode 0x23: SRAM idx (debug mode) +* 0~35: STA bitmap +* 36~51: STA setting +//-- +* Mode 0x40: addr[3:0] = bssid, +* Mode 0x41: addr[3:0] = bssid, +* Mode 0x42: addr[3:0] = bssid, +* Mode 0x43: addr[3:0] = bssid, +* Mode 0x44: SRAM idx (debug mode) +* Mode 0x45: SRAM idx (debug mode) +* 0~15: BSS bitmap +* 16~31: BSS setting +* 32~47: Token status +//-- +* Mode 0x81~0x83: addr[3:0] = BSS group ID +* Bit[0]: Charge bw_token +* Bit[1]: Charge bw DRR +* Mode 0x84: addr[7:0] = station ID, +* addr[11:8]= qid +* Bit[2]: Charge airtime DRR +* Bit[3]: Charge is ADD mode +* WRITE_MASK[15..12] - (RW) DRR table will not be updated if mask +* write bits are enabled. +* MODE[23..16] - (RW) Operation mode for DRR table +* WRITE_MASK_2[27..24] - (RW) DRR table will not be updated if mask +* write bits are enabled. +* RESERVED28[30..28] - (RO) Reserved bits +* EXECUTE[31] - (RW) Excutes SW command to read/write DRR +table +*/ +#define WF_PLE_TOP_DRR_TABLE_CTRL_EXECUTE_ADDR WF_PLE_TOP_DRR_TABLE_CTRL_ADDR +#define WF_PLE_TOP_DRR_TABLE_CTRL_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_DRR_TABLE_CTRL_EXECUTE_SHFT 31 +#define WF_PLE_TOP_DRR_TABLE_CTRL_WRITE_MASK_2_ADDR \ +WF_PLE_TOP_DRR_TABLE_CTRL_ADDR +#define WF_PLE_TOP_DRR_TABLE_CTRL_WRITE_MASK_2_MASK \ +0x0F000000 /* WRITE_MASK_2[27..24] */ +#define WF_PLE_TOP_DRR_TABLE_CTRL_WRITE_MASK_2_SHFT 24 +#define WF_PLE_TOP_DRR_TABLE_CTRL_MODE_ADDR WF_PLE_TOP_DRR_TABLE_CTRL_ADDR +#define WF_PLE_TOP_DRR_TABLE_CTRL_MODE_MASK 0x00FF0000 /* MODE[23..16] */ +#define WF_PLE_TOP_DRR_TABLE_CTRL_MODE_SHFT 16 +#define WF_PLE_TOP_DRR_TABLE_CTRL_WRITE_MASK_ADDR WF_PLE_TOP_DRR_TABLE_CTRL_ADDR +#define WF_PLE_TOP_DRR_TABLE_CTRL_WRITE_MASK_MASK \ +0x0000F000 /* WRITE_MASK[15..12] */ +#define WF_PLE_TOP_DRR_TABLE_CTRL_WRITE_MASK_SHFT 12 +#define WF_PLE_TOP_DRR_TABLE_CTRL_INDEX_ADDR WF_PLE_TOP_DRR_TABLE_CTRL_ADDR +#define WF_PLE_TOP_DRR_TABLE_CTRL_INDEX_MASK 0x00000FFF /* INDEX[11..0] */ +#define WF_PLE_TOP_DRR_TABLE_CTRL_INDEX_SHFT 0 + +/* +* ---VOW_CTRL1 (0x820C0000 + 0x38C)--- +* RESERVED0[0] - (RO) Reserved bits +* EN_BSSID_CHECK[1] - (RW) Enable control of check BSSID's trap +* state in search station +* EN_LOCK_STA[2] - (RW) Lock mode for RTS retry same sta until +* RTS drop +* EN_KEEP_QTM[3] - (RW) Not reset remain Tx time when sta has +* new packet +* EN_TXCNT_MODE[4] - (RW) Tx count weighted round robin control +* EN_TXED_MODE[5] - (RW) Txed bitmap control +* EN_RXSCH_MODE[6] - (RW) Rx scheduling with rx earlyend bitmap +control +* EN_BWRF_SRCH[7] - (RW) Bandwidth refill search control +* DIS_BSSID0_TRAP_IGNORE[8] - (RW) Disable control of the function that STA +* with BSSID0 trap ignore in TXQ busy +* DIS_BSSID1_TRAP_IGNORE[9] - (RW) Disable control of the function that STA +* with BSSID1 trap ignore in TXQ busy +* DIS_BSSID2_TRAP_IGNORE[10] - (RW) Disable control of the function that STA +* with BSSID2 trap ignore in TXQ busy +* DIS_BSSID3_TRAP_IGNORE[11] - (RW) Disable control of the function that STA +* with BSSID3 trap ignore in TXQ busy +* DIS_KEEP_TRGT_BSS[12] - (RW) Disable control of keeping BSS as target +* station when SPL search +* SPL_SW_BSR_STALINK[13] - (RW) SW add/remove uplink station control +* SPL_RUNN_EN[14] - (RW) Over run 1 station search control +* RESERVED15[31..15] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_VOW_CTRL1_SPL_RUNN_EN_ADDR WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_SPL_RUNN_EN_MASK 0x00004000 /* SPL_RUNN_EN[14] */ +#define WF_PLE_TOP_VOW_CTRL1_SPL_RUNN_EN_SHFT 14 +#define WF_PLE_TOP_VOW_CTRL1_SPL_SW_BSR_STALINK_ADDR WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_SPL_SW_BSR_STALINK_MASK \ +0x00002000 /* SPL_SW_BSR_STALINK[13] */ +#define WF_PLE_TOP_VOW_CTRL1_SPL_SW_BSR_STALINK_SHFT 13 +#define WF_PLE_TOP_VOW_CTRL1_DIS_KEEP_TRGT_BSS_ADDR WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_DIS_KEEP_TRGT_BSS_MASK \ +0x00001000 /* DIS_KEEP_TRGT_BSS[12] */ +#define WF_PLE_TOP_VOW_CTRL1_DIS_KEEP_TRGT_BSS_SHFT 12 +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID3_TRAP_IGNORE_ADDR \ +WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID3_TRAP_IGNORE_MASK \ +0x00000800 /* DIS_BSSID3_TRAP_IGNORE[11] */ +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID3_TRAP_IGNORE_SHFT 11 +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID2_TRAP_IGNORE_ADDR \ +WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID2_TRAP_IGNORE_MASK \ +0x00000400 /* DIS_BSSID2_TRAP_IGNORE[10] */ +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID2_TRAP_IGNORE_SHFT 10 +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID1_TRAP_IGNORE_ADDR \ +WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID1_TRAP_IGNORE_MASK \ +0x00000200 /* DIS_BSSID1_TRAP_IGNORE[9] */ +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID1_TRAP_IGNORE_SHFT 9 +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID0_TRAP_IGNORE_ADDR \ +WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID0_TRAP_IGNORE_MASK \ +0x00000100 /* DIS_BSSID0_TRAP_IGNORE[8] */ +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID0_TRAP_IGNORE_SHFT 8 +#define WF_PLE_TOP_VOW_CTRL1_EN_BWRF_SRCH_ADDR WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_EN_BWRF_SRCH_MASK 0x00000080 /* EN_BWRF_SRCH[7] \ + */ +#define WF_PLE_TOP_VOW_CTRL1_EN_BWRF_SRCH_SHFT 7 +#define WF_PLE_TOP_VOW_CTRL1_EN_RXSCH_MODE_ADDR WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_EN_RXSCH_MODE_MASK \ +0x00000040 /* EN_RXSCH_MODE[6] */ +#define WF_PLE_TOP_VOW_CTRL1_EN_RXSCH_MODE_SHFT 6 +#define WF_PLE_TOP_VOW_CTRL1_EN_TXED_MODE_ADDR WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_EN_TXED_MODE_MASK 0x00000020 /* EN_TXED_MODE[5] \ + */ +#define WF_PLE_TOP_VOW_CTRL1_EN_TXED_MODE_SHFT 5 +#define WF_PLE_TOP_VOW_CTRL1_EN_TXCNT_MODE_ADDR WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_EN_TXCNT_MODE_MASK \ +0x00000010 /* EN_TXCNT_MODE[4] */ +#define WF_PLE_TOP_VOW_CTRL1_EN_TXCNT_MODE_SHFT 4 +#define WF_PLE_TOP_VOW_CTRL1_EN_KEEP_QTM_ADDR WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_EN_KEEP_QTM_MASK 0x00000008 /* EN_KEEP_QTM[3] */ +#define WF_PLE_TOP_VOW_CTRL1_EN_KEEP_QTM_SHFT 3 +#define WF_PLE_TOP_VOW_CTRL1_EN_LOCK_STA_ADDR WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_EN_LOCK_STA_MASK 0x00000004 /* EN_LOCK_STA[2] */ +#define WF_PLE_TOP_VOW_CTRL1_EN_LOCK_STA_SHFT 2 +#define WF_PLE_TOP_VOW_CTRL1_EN_BSSID_CHECK_ADDR WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_EN_BSSID_CHECK_MASK \ +0x00000002 /* EN_BSSID_CHECK[1] */ +#define WF_PLE_TOP_VOW_CTRL1_EN_BSSID_CHECK_SHFT 1 + +/* +* ---DRR_CHNL_EMPTY (0x820C0000 + 0x390)--- +* WMM_STA_DL_EMPTY[15..0] - (RO) Indicate emptiness of 16 DL station link +* WMM_STA_UL_EMPTY[31..16] - (RO) Indicate emptiness of 16 UL station link +*/ +#define WF_PLE_TOP_DRR_CHNL_EMPTY_WMM_STA_UL_EMPTY_ADDR \ +WF_PLE_TOP_DRR_CHNL_EMPTY_ADDR +#define WF_PLE_TOP_DRR_CHNL_EMPTY_WMM_STA_UL_EMPTY_MASK \ +0xFFFF0000 /* WMM_STA_UL_EMPTY[31..16] */ +#define WF_PLE_TOP_DRR_CHNL_EMPTY_WMM_STA_UL_EMPTY_SHFT 16 +#define WF_PLE_TOP_DRR_CHNL_EMPTY_WMM_STA_DL_EMPTY_ADDR \ +WF_PLE_TOP_DRR_CHNL_EMPTY_ADDR +#define WF_PLE_TOP_DRR_CHNL_EMPTY_WMM_STA_DL_EMPTY_MASK \ +0x0000FFFF /* WMM_STA_DL_EMPTY[15..0] */ +#define WF_PLE_TOP_DRR_CHNL_EMPTY_WMM_STA_DL_EMPTY_SHFT 0 + +/* +* ---DRR_SPL_CTRL (0x820C0000 + 0x394)--- +* SPL_EM2NEM_SRCH_DL_EN[15..0] - (RW) DL empty-to-nonempty search event +* trigger control +* SUBRND_TIMES[19..16] - (RW) Subround times setting to trigger round +end +* EN_SBTG_RNDEND[20] - (RW) Enable control of round ends by subround +times +* EN_QLEN_TH[21] - (RW) Enable control of queue length +* constraint to select station +* EN_ARB_CUT_IN[22] - (RW) Enable control of SPL search interrupt +* in TXD/TXCMD concurrent mode +* EN_SPL_MERGE[23] - (RW) Enable SPL merge mode with DL and UL +* station list +* SPL_STA_NUM[31..24] - (RW) SPL station number. Must equal to or +* larger than 1 +*/ +#define WF_PLE_TOP_DRR_SPL_CTRL_SPL_STA_NUM_ADDR WF_PLE_TOP_DRR_SPL_CTRL_ADDR +#define WF_PLE_TOP_DRR_SPL_CTRL_SPL_STA_NUM_MASK \ +0xFF000000 /* SPL_STA_NUM[31..24] */ +#define WF_PLE_TOP_DRR_SPL_CTRL_SPL_STA_NUM_SHFT 24 +#define WF_PLE_TOP_DRR_SPL_CTRL_EN_SPL_MERGE_ADDR WF_PLE_TOP_DRR_SPL_CTRL_ADDR +#define WF_PLE_TOP_DRR_SPL_CTRL_EN_SPL_MERGE_MASK \ +0x00800000 /* EN_SPL_MERGE[23] */ +#define WF_PLE_TOP_DRR_SPL_CTRL_EN_SPL_MERGE_SHFT 23 +#define WF_PLE_TOP_DRR_SPL_CTRL_EN_ARB_CUT_IN_ADDR WF_PLE_TOP_DRR_SPL_CTRL_ADDR +#define WF_PLE_TOP_DRR_SPL_CTRL_EN_ARB_CUT_IN_MASK \ +0x00400000 /* EN_ARB_CUT_IN[22] */ +#define WF_PLE_TOP_DRR_SPL_CTRL_EN_ARB_CUT_IN_SHFT 22 +#define WF_PLE_TOP_DRR_SPL_CTRL_EN_QLEN_TH_ADDR WF_PLE_TOP_DRR_SPL_CTRL_ADDR +#define WF_PLE_TOP_DRR_SPL_CTRL_EN_QLEN_TH_MASK 0x00200000 /* EN_QLEN_TH[21] \ + */ +#define WF_PLE_TOP_DRR_SPL_CTRL_EN_QLEN_TH_SHFT 21 +#define WF_PLE_TOP_DRR_SPL_CTRL_EN_SBTG_RNDEND_ADDR WF_PLE_TOP_DRR_SPL_CTRL_ADDR +#define WF_PLE_TOP_DRR_SPL_CTRL_EN_SBTG_RNDEND_MASK \ +0x00100000 /* EN_SBTG_RNDEND[20] */ +#define WF_PLE_TOP_DRR_SPL_CTRL_EN_SBTG_RNDEND_SHFT 20 +#define WF_PLE_TOP_DRR_SPL_CTRL_SUBRND_TIMES_ADDR WF_PLE_TOP_DRR_SPL_CTRL_ADDR +#define WF_PLE_TOP_DRR_SPL_CTRL_SUBRND_TIMES_MASK \ +0x000F0000 /* SUBRND_TIMES[19..16] */ +#define WF_PLE_TOP_DRR_SPL_CTRL_SUBRND_TIMES_SHFT 16 +#define WF_PLE_TOP_DRR_SPL_CTRL_SPL_EM2NEM_SRCH_DL_EN_ADDR \ +WF_PLE_TOP_DRR_SPL_CTRL_ADDR +#define WF_PLE_TOP_DRR_SPL_CTRL_SPL_EM2NEM_SRCH_DL_EN_MASK \ +0x0000FFFF /* SPL_EM2NEM_SRCH_DL_EN[15..0] */ +#define WF_PLE_TOP_DRR_SPL_CTRL_SPL_EM2NEM_SRCH_DL_EN_SHFT 0 + +/* +* ---DRR_SPL_CTRL_1 (0x820C0000 + 0x398)--- +* SPL_EM2NEM_SRCH_UL_EN[15..0] - (RW) UL empty-to-nonempty search event +* trigger control +* EN_BWRF_FILTER[16] - (RW) BW refill mode SPL with NE=1 STA_CNT=0 +* filter enable control +* EN_BWCHRG_ORIG[17] - (RW) BW charge original scheme enable control +* RESERVED18[19..18] - (RO) Reserved bits +* EN_PS_CHG_SPL_GEN[20] - (RW) PS change SPL generation control. +* EN_PS_CHG_CHK_AC_EMPTY[21] - (RW) Enable control of STA AC queue empty +* check for PS change SPL generation. +* EN_PS_CHG_CHK_TXCMD_EMPTY[22] - (RW) Enable control of TXCMD queue empty +* check for PS change SPL generation. +* EN_PS_CHG_SPL_MERGE[23] - (RW) Enable PS change SPL merge mode with DL +* and UL station list. +* EN_PS_CHG_SPL_KEEP_PAUSE[24] - (RW) Enable control for PLE Station pause in +* PS change SPL generation. +* RESERVED25[31..25] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_PS_CHG_SPL_KEEP_PAUSE_ADDR \ +WF_PLE_TOP_DRR_SPL_CTRL_1_ADDR +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_PS_CHG_SPL_KEEP_PAUSE_MASK \ +0x01000000 /* EN_PS_CHG_SPL_KEEP_PAUSE[24] */ +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_PS_CHG_SPL_KEEP_PAUSE_SHFT 24 +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_PS_CHG_SPL_MERGE_ADDR \ +WF_PLE_TOP_DRR_SPL_CTRL_1_ADDR +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_PS_CHG_SPL_MERGE_MASK \ +0x00800000 /* EN_PS_CHG_SPL_MERGE[23] */ +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_PS_CHG_SPL_MERGE_SHFT 23 +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_PS_CHG_CHK_TXCMD_EMPTY_ADDR \ +WF_PLE_TOP_DRR_SPL_CTRL_1_ADDR +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_PS_CHG_CHK_TXCMD_EMPTY_MASK \ +0x00400000 /* EN_PS_CHG_CHK_TXCMD_EMPTY[22] */ +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_PS_CHG_CHK_TXCMD_EMPTY_SHFT 22 +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_PS_CHG_CHK_AC_EMPTY_ADDR \ +WF_PLE_TOP_DRR_SPL_CTRL_1_ADDR +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_PS_CHG_CHK_AC_EMPTY_MASK \ +0x00200000 /* EN_PS_CHG_CHK_AC_EMPTY[21] */ +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_PS_CHG_CHK_AC_EMPTY_SHFT 21 +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_PS_CHG_SPL_GEN_ADDR \ +WF_PLE_TOP_DRR_SPL_CTRL_1_ADDR +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_PS_CHG_SPL_GEN_MASK \ +0x00100000 /* EN_PS_CHG_SPL_GEN[20] */ +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_PS_CHG_SPL_GEN_SHFT 20 +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_BWCHRG_ORIG_ADDR \ +WF_PLE_TOP_DRR_SPL_CTRL_1_ADDR +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_BWCHRG_ORIG_MASK \ +0x00020000 /* EN_BWCHRG_ORIG[17] */ +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_BWCHRG_ORIG_SHFT 17 +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_BWRF_FILTER_ADDR \ +WF_PLE_TOP_DRR_SPL_CTRL_1_ADDR +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_BWRF_FILTER_MASK \ +0x00010000 /* EN_BWRF_FILTER[16] */ +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_BWRF_FILTER_SHFT 16 +#define WF_PLE_TOP_DRR_SPL_CTRL_1_SPL_EM2NEM_SRCH_UL_EN_ADDR \ +WF_PLE_TOP_DRR_SPL_CTRL_1_ADDR +#define WF_PLE_TOP_DRR_SPL_CTRL_1_SPL_EM2NEM_SRCH_UL_EN_MASK \ +0x0000FFFF /* SPL_EM2NEM_SRCH_UL_EN[15..0] */ +#define WF_PLE_TOP_DRR_SPL_CTRL_1_SPL_EM2NEM_SRCH_UL_EN_SHFT 0 + +/* +* ---VOW_DBG_SEL (0x820C0000 + 0x3A0)--- +* AIRTIME_DEBUG_SEL[15..0] - (RW) Selects airtime debug +* BW_DEBUG_SEL[31..16] - (RW) Selects BW control debug +*/ +#define WF_PLE_TOP_VOW_DBG_SEL_BW_DEBUG_SEL_ADDR WF_PLE_TOP_VOW_DBG_SEL_ADDR +#define WF_PLE_TOP_VOW_DBG_SEL_BW_DEBUG_SEL_MASK \ +0xFFFF0000 /* BW_DEBUG_SEL[31..16] */ +#define WF_PLE_TOP_VOW_DBG_SEL_BW_DEBUG_SEL_SHFT 16 +#define WF_PLE_TOP_VOW_DBG_SEL_AIRTIME_DEBUG_SEL_ADDR \ +WF_PLE_TOP_VOW_DBG_SEL_ADDR +#define WF_PLE_TOP_VOW_DBG_SEL_AIRTIME_DEBUG_SEL_MASK \ +0x0000FFFF /* AIRTIME_DEBUG_SEL[15..0] */ +#define WF_PLE_TOP_VOW_DBG_SEL_AIRTIME_DEBUG_SEL_SHFT 0 + +/* +* ---AIRTIME_DBG_INFO0 (0x820C0000 + 0x3A4)--- +* AIRTIME_DBG_INFO0[31..0] - (RO) Station link head/tail +*/ +#define WF_PLE_TOP_AIRTIME_DBG_INFO0_AIRTIME_DBG_INFO0_ADDR \ +WF_PLE_TOP_AIRTIME_DBG_INFO0_ADDR +#define WF_PLE_TOP_AIRTIME_DBG_INFO0_AIRTIME_DBG_INFO0_MASK \ +0xFFFFFFFF /* AIRTIME_DBG_INFO0[31..0] */ +#define WF_PLE_TOP_AIRTIME_DBG_INFO0_AIRTIME_DBG_INFO0_SHFT 0 + +/* +* ---AIRTIME_DBG_INFO1 (0x820C0000 + 0x3A8)--- +* AIRTIME_DBG_INFO1[31..0] - (RO) Station link head/tail +*/ +#define WF_PLE_TOP_AIRTIME_DBG_INFO1_AIRTIME_DBG_INFO1_ADDR \ +WF_PLE_TOP_AIRTIME_DBG_INFO1_ADDR +#define WF_PLE_TOP_AIRTIME_DBG_INFO1_AIRTIME_DBG_INFO1_MASK \ +0xFFFFFFFF /* AIRTIME_DBG_INFO1[31..0] */ +#define WF_PLE_TOP_AIRTIME_DBG_INFO1_AIRTIME_DBG_INFO1_SHFT 0 + +/* +* ---BW_DBG_INFO (0x820C0000 + 0x3AC)--- +* BW_DBG_INFO1[31..0] - (RO) BSS link head/tail +*/ +#define WF_PLE_TOP_BW_DBG_INFO_BW_DBG_INFO1_ADDR WF_PLE_TOP_BW_DBG_INFO_ADDR +#define WF_PLE_TOP_BW_DBG_INFO_BW_DBG_INFO1_MASK \ +0xFFFFFFFF /* BW_DBG_INFO1[31..0] */ +#define WF_PLE_TOP_BW_DBG_INFO_BW_DBG_INFO1_SHFT 0 + +/* +* ---BW_GROUP_QUANTUM_SETTING0 (0x820C0000 + 0x3B0)--- +* BW_GROUP0_QUANTUM[7..0] - (RW) BW_GROUP0 quantum(BW control only) +* BW_GROUP1_QUANTUM[15..8] - (RW) BW_GROUP1 quantum(BW control only) +* BW_GROUP2_QUANTUM[23..16] - (RW) BW_GROUP2 quantum(BW control only) +* BW_GROUP3_QUANTUM[31..24] - (RW) BW_GROUP3 quantum(BW control only) +*/ +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING0_BW_GROUP3_QUANTUM_ADDR \ +WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING0_ADDR +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING0_BW_GROUP3_QUANTUM_MASK \ +0xFF000000 /* BW_GROUP3_QUANTUM[31..24] */ +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING0_BW_GROUP3_QUANTUM_SHFT 24 +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING0_BW_GROUP2_QUANTUM_ADDR \ +WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING0_ADDR +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING0_BW_GROUP2_QUANTUM_MASK \ +0x00FF0000 /* BW_GROUP2_QUANTUM[23..16] */ +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING0_BW_GROUP2_QUANTUM_SHFT 16 +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING0_BW_GROUP1_QUANTUM_ADDR \ +WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING0_ADDR +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING0_BW_GROUP1_QUANTUM_MASK \ +0x0000FF00 /* BW_GROUP1_QUANTUM[15..8] */ +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING0_BW_GROUP1_QUANTUM_SHFT 8 +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING0_BW_GROUP0_QUANTUM_ADDR \ +WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING0_ADDR +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING0_BW_GROUP0_QUANTUM_MASK \ +0x000000FF /* BW_GROUP0_QUANTUM[7..0] */ +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING0_BW_GROUP0_QUANTUM_SHFT 0 + +/* +* ---BW_GROUP_QUANTUM_SETTING1 (0x820C0000 + 0x3B4)--- +* BW_GROUP4_QUANTUM[7..0] - (RW) BW_GROUP4 quantum(BW control only) +* BW_GROUP5_QUANTUM[15..8] - (RW) BW_GROUP5 quantum(BW control only) +* BW_GROUP6_QUANTUM[23..16] - (RW) BW_GROUP6 quantum(BW control only) +* BW_GROUP7_QUANTUM[31..24] - (RW) BW_GROUP7 quantum(BW control only) +*/ +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING1_BW_GROUP7_QUANTUM_ADDR \ +WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING1_ADDR +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING1_BW_GROUP7_QUANTUM_MASK \ +0xFF000000 /* BW_GROUP7_QUANTUM[31..24] */ +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING1_BW_GROUP7_QUANTUM_SHFT 24 +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING1_BW_GROUP6_QUANTUM_ADDR \ +WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING1_ADDR +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING1_BW_GROUP6_QUANTUM_MASK \ +0x00FF0000 /* BW_GROUP6_QUANTUM[23..16] */ +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING1_BW_GROUP6_QUANTUM_SHFT 16 +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING1_BW_GROUP5_QUANTUM_ADDR \ +WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING1_ADDR +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING1_BW_GROUP5_QUANTUM_MASK \ +0x0000FF00 /* BW_GROUP5_QUANTUM[15..8] */ +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING1_BW_GROUP5_QUANTUM_SHFT 8 +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING1_BW_GROUP4_QUANTUM_ADDR \ +WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING1_ADDR +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING1_BW_GROUP4_QUANTUM_MASK \ +0x000000FF /* BW_GROUP4_QUANTUM[7..0] */ +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING1_BW_GROUP4_QUANTUM_SHFT 0 + +/* +* ---BW_GROUP_QUANTUM_SETTING2 (0x820C0000 + 0x3B8)--- +* BW_GROUP8_QUANTUM[7..0] - (RW) BW_GROUP8 quantum(BW control only) +* BW_GROUP9_QUANTUM[15..8] - (RW) BW_GROUP9 quantum(BW control only) +* BW_GROUP10_QUANTUM[23..16] - (RW) BW_GROUP10 quantum(BW control only) +* BW_GROUP11_QUANTUM[31..24] - (RW) BW_GROUP11 quantum(BW control only) +*/ +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING2_BW_GROUP11_QUANTUM_ADDR \ +WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING2_ADDR +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING2_BW_GROUP11_QUANTUM_MASK \ +0xFF000000 /* BW_GROUP11_QUANTUM[31..24] */ +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING2_BW_GROUP11_QUANTUM_SHFT 24 +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING2_BW_GROUP10_QUANTUM_ADDR \ +WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING2_ADDR +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING2_BW_GROUP10_QUANTUM_MASK \ +0x00FF0000 /* BW_GROUP10_QUANTUM[23..16] */ +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING2_BW_GROUP10_QUANTUM_SHFT 16 +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING2_BW_GROUP9_QUANTUM_ADDR \ +WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING2_ADDR +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING2_BW_GROUP9_QUANTUM_MASK \ +0x0000FF00 /* BW_GROUP9_QUANTUM[15..8] */ +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING2_BW_GROUP9_QUANTUM_SHFT 8 +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING2_BW_GROUP8_QUANTUM_ADDR \ +WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING2_ADDR +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING2_BW_GROUP8_QUANTUM_MASK \ +0x000000FF /* BW_GROUP8_QUANTUM[7..0] */ +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING2_BW_GROUP8_QUANTUM_SHFT 0 + +/* +* ---BW_GROUP_QUANTUM_SETTING3 (0x820C0000 + 0x3bc)--- +* BW_GROUP12_QUANTUM[7..0] - (RW) BW_GROUP12 quantum(BW control only) +* BW_GROUP13_QUANTUM[15..8] - (RW) BW_GROUP13 quantum(BW control only) +* BW_GROUP14_QUANTUM[23..16] - (RW) BW_GROUP14 quantum(BW control only) +* BW_GROUP15_QUANTUM[31..24] - (RW) BW_GROUP15 quantum(BW control only) +*/ +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING3_BW_GROUP15_QUANTUM_ADDR \ +WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING3_ADDR +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING3_BW_GROUP15_QUANTUM_MASK \ +0xFF000000 /* BW_GROUP15_QUANTUM[31..24] */ +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING3_BW_GROUP15_QUANTUM_SHFT 24 +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING3_BW_GROUP14_QUANTUM_ADDR \ +WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING3_ADDR +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING3_BW_GROUP14_QUANTUM_MASK \ +0x00FF0000 /* BW_GROUP14_QUANTUM[23..16] */ +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING3_BW_GROUP14_QUANTUM_SHFT 16 +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING3_BW_GROUP13_QUANTUM_ADDR \ +WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING3_ADDR +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING3_BW_GROUP13_QUANTUM_MASK \ +0x0000FF00 /* BW_GROUP13_QUANTUM[15..8] */ +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING3_BW_GROUP13_QUANTUM_SHFT 8 +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING3_BW_GROUP12_QUANTUM_ADDR \ +WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING3_ADDR +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING3_BW_GROUP12_QUANTUM_MASK \ +0x000000FF /* BW_GROUP12_QUANTUM[7..0] */ +#define WF_PLE_TOP_BW_GROUP_QUANTUM_SETTING3_BW_GROUP12_QUANTUM_SHFT 0 + +/* +* ---DRR_SW_CTRL (0x820C0000 + 0x3C8)--- +* INDEX[15..0] - (RW) Operation index +* Mode 0x00: Bit[15:12]: QID, Bit[9:0]: wlan +ID +* Mode 0x01: Bit[15:12]: QID, Bit[9:0]: wlan +ID +* Mode 0x10: Bit[3:0]: QID +* Mode 0x11: Bit[3:0]: QID +* MODE[23..16] - (RW) IO software command mode +* RESERVED24[29..24] - (RO) Reserved bits +* SRCH_CMD_DROP[30] - (W1C) IO search command drop flag due to +* command FIFO full +* EXECUTE[31] - (RW) Executes SW command to trigger search +* event and add/remove station +*/ +#define WF_PLE_TOP_DRR_SW_CTRL_EXECUTE_ADDR WF_PLE_TOP_DRR_SW_CTRL_ADDR +#define WF_PLE_TOP_DRR_SW_CTRL_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_DRR_SW_CTRL_EXECUTE_SHFT 31 +#define WF_PLE_TOP_DRR_SW_CTRL_SRCH_CMD_DROP_ADDR WF_PLE_TOP_DRR_SW_CTRL_ADDR +#define WF_PLE_TOP_DRR_SW_CTRL_SRCH_CMD_DROP_MASK \ +0x40000000 /* SRCH_CMD_DROP[30] */ +#define WF_PLE_TOP_DRR_SW_CTRL_SRCH_CMD_DROP_SHFT 30 +#define WF_PLE_TOP_DRR_SW_CTRL_MODE_ADDR WF_PLE_TOP_DRR_SW_CTRL_ADDR +#define WF_PLE_TOP_DRR_SW_CTRL_MODE_MASK 0x00FF0000 /* MODE[23..16] */ +#define WF_PLE_TOP_DRR_SW_CTRL_MODE_SHFT 16 +#define WF_PLE_TOP_DRR_SW_CTRL_INDEX_ADDR WF_PLE_TOP_DRR_SW_CTRL_ADDR +#define WF_PLE_TOP_DRR_SW_CTRL_INDEX_MASK 0x0000FFFF /* INDEX[15..0] */ +#define WF_PLE_TOP_DRR_SW_CTRL_INDEX_SHFT 0 + +/* +* ---DRR_HW_SRCHCMD_FULL (0x820C0000 + 0x3CC)--- +* CMD_FULL_CHNL_DL[15..0] - (RW) Hardware search command full flag of 16 +* backoff channel of downlink +* CMD_FULL_CHNL_UL[31..16] - (RW) Hardware search command full flag of 16 +* backoff channel of uplink +*/ +#define WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_CMD_FULL_CHNL_UL_ADDR \ +WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_ADDR +#define WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_CMD_FULL_CHNL_UL_MASK \ +0xFFFF0000 /* CMD_FULL_CHNL_UL[31..16] */ +#define WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_CMD_FULL_CHNL_UL_SHFT 16 +#define WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_CMD_FULL_CHNL_DL_ADDR \ +WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_ADDR +#define WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_CMD_FULL_CHNL_DL_MASK \ +0x0000FFFF /* CMD_FULL_CHNL_DL[15..0] */ +#define WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_CMD_FULL_CHNL_DL_SHFT 0 + +/* +* ---STATION_PAUSE0 (0x820C0000 + 0x400)--- +* STATION_PAUSE_0[31..0] - (RW) SW can stop station TX by this setting +* for STA0~STA31. +*/ +#define WF_PLE_TOP_STATION_PAUSE0_STATION_PAUSE_0_ADDR \ +WF_PLE_TOP_STATION_PAUSE0_ADDR +#define WF_PLE_TOP_STATION_PAUSE0_STATION_PAUSE_0_MASK \ +0xFFFFFFFF /* STATION_PAUSE_0[31..0] */ +#define WF_PLE_TOP_STATION_PAUSE0_STATION_PAUSE_0_SHFT 0 + +/* +* ---STATION_PAUSE1 (0x820C0000 + 0x404)--- +* STATION_PAUSE_1[31..0] - (RW) SW can stop station TX by this setting +* for STA32~STA63. +*/ +#define WF_PLE_TOP_STATION_PAUSE1_STATION_PAUSE_1_ADDR \ +WF_PLE_TOP_STATION_PAUSE1_ADDR +#define WF_PLE_TOP_STATION_PAUSE1_STATION_PAUSE_1_MASK \ +0xFFFFFFFF /* STATION_PAUSE_1[31..0] */ +#define WF_PLE_TOP_STATION_PAUSE1_STATION_PAUSE_1_SHFT 0 + +/* +* ---STATION_PAUSE2 (0x820C0000 + 0x408)--- +* STATION_PAUSE_2[31..0] - (RW) SW can stop station TX by this setting +* for STA64~STA95. +*/ +#define WF_PLE_TOP_STATION_PAUSE2_STATION_PAUSE_2_ADDR \ +WF_PLE_TOP_STATION_PAUSE2_ADDR +#define WF_PLE_TOP_STATION_PAUSE2_STATION_PAUSE_2_MASK \ +0xFFFFFFFF /* STATION_PAUSE_2[31..0] */ +#define WF_PLE_TOP_STATION_PAUSE2_STATION_PAUSE_2_SHFT 0 + +/* +* ---STATION_PAUSE3 (0x820C0000 + 0x40c)--- +* STATION_PAUSE_3[31..0] - (RW) SW can stop station TX by this setting +* for STA96~STA127. +*/ +#define WF_PLE_TOP_STATION_PAUSE3_STATION_PAUSE_3_ADDR \ +WF_PLE_TOP_STATION_PAUSE3_ADDR +#define WF_PLE_TOP_STATION_PAUSE3_STATION_PAUSE_3_MASK \ +0xFFFFFFFF /* STATION_PAUSE_3[31..0] */ +#define WF_PLE_TOP_STATION_PAUSE3_STATION_PAUSE_3_SHFT 0 + +/* +* ---STATION_PAUSE4 (0x820C0000 + 0x410)--- +* STATION_PAUSE_4_0[7..0] - (RW) SW can stop station TX by this setting +* for STA128~STA135. +* STATION_PAUSE_4_1[15..8] - (RW) SW can stop station TX by this setting +* for STA136~STA143. +* STATION_PAUSE_4_2[31..16] - (RW) SW can stop station TX by this setting +* for STA144~STA159. +*/ +#define WF_PLE_TOP_STATION_PAUSE4_STATION_PAUSE_4_2_ADDR \ +WF_PLE_TOP_STATION_PAUSE4_ADDR +#define WF_PLE_TOP_STATION_PAUSE4_STATION_PAUSE_4_2_MASK \ +0xFFFF0000 /* STATION_PAUSE_4_2[31..16] */ +#define WF_PLE_TOP_STATION_PAUSE4_STATION_PAUSE_4_2_SHFT 16 +#define WF_PLE_TOP_STATION_PAUSE4_STATION_PAUSE_4_1_ADDR \ +WF_PLE_TOP_STATION_PAUSE4_ADDR +#define WF_PLE_TOP_STATION_PAUSE4_STATION_PAUSE_4_1_MASK \ +0x0000FF00 /* STATION_PAUSE_4_1[15..8] */ +#define WF_PLE_TOP_STATION_PAUSE4_STATION_PAUSE_4_1_SHFT 8 +#define WF_PLE_TOP_STATION_PAUSE4_STATION_PAUSE_4_0_ADDR \ +WF_PLE_TOP_STATION_PAUSE4_ADDR +#define WF_PLE_TOP_STATION_PAUSE4_STATION_PAUSE_4_0_MASK \ +0x000000FF /* STATION_PAUSE_4_0[7..0] */ +#define WF_PLE_TOP_STATION_PAUSE4_STATION_PAUSE_4_0_SHFT 0 + +/* +* ---STATION_PAUSE5 (0x820C0000 + 0x414)--- +* STATION_PAUSE_5[31..0] - (RW) SW can stop station TX by this setting +* for STA160~STA191. +*/ +#define WF_PLE_TOP_STATION_PAUSE5_STATION_PAUSE_5_ADDR \ +WF_PLE_TOP_STATION_PAUSE5_ADDR +#define WF_PLE_TOP_STATION_PAUSE5_STATION_PAUSE_5_MASK \ +0xFFFFFFFF /* STATION_PAUSE_5[31..0] */ +#define WF_PLE_TOP_STATION_PAUSE5_STATION_PAUSE_5_SHFT 0 + +/* +* ---STATION_PAUSE6 (0x820C0000 + 0x418)--- +* STATION_PAUSE_6[31..0] - (RW) SW can stop station TX by this setting +* for STA192~STA223. +*/ +#define WF_PLE_TOP_STATION_PAUSE6_STATION_PAUSE_6_ADDR \ +WF_PLE_TOP_STATION_PAUSE6_ADDR +#define WF_PLE_TOP_STATION_PAUSE6_STATION_PAUSE_6_MASK \ +0xFFFFFFFF /* STATION_PAUSE_6[31..0] */ +#define WF_PLE_TOP_STATION_PAUSE6_STATION_PAUSE_6_SHFT 0 + +/* +* ---STATION_PAUSE7 (0x820C0000 + 0x41c)--- +* STATION_PAUSE_7[31..0] - (RW) SW can stop station TX by this setting +* for STA224~STA255. +*/ +#define WF_PLE_TOP_STATION_PAUSE7_STATION_PAUSE_7_ADDR \ +WF_PLE_TOP_STATION_PAUSE7_ADDR +#define WF_PLE_TOP_STATION_PAUSE7_STATION_PAUSE_7_MASK \ +0xFFFFFFFF /* STATION_PAUSE_7[31..0] */ +#define WF_PLE_TOP_STATION_PAUSE7_STATION_PAUSE_7_SHFT 0 + +/* +* ---STATION_PAUSE8 (0x820C0000 + 0x420)--- +* STATION_PAUSE_8[31..0] - (RW) SW can stop station TX by this setting +* for STA256~STA287. +*/ +#define WF_PLE_TOP_STATION_PAUSE8_STATION_PAUSE_8_ADDR \ +WF_PLE_TOP_STATION_PAUSE8_ADDR +#define WF_PLE_TOP_STATION_PAUSE8_STATION_PAUSE_8_MASK \ +0xFFFFFFFF /* STATION_PAUSE_8[31..0] */ +#define WF_PLE_TOP_STATION_PAUSE8_STATION_PAUSE_8_SHFT 0 + +/* +* ---DIS_STA_MAP0 (0x820C0000 + 0x440)--- +* DIS_STA_MAP_0[31..0] - (RW) Disable map for STA 0~31 TX +*/ +#define WF_PLE_TOP_DIS_STA_MAP0_DIS_STA_MAP_0_ADDR WF_PLE_TOP_DIS_STA_MAP0_ADDR +#define WF_PLE_TOP_DIS_STA_MAP0_DIS_STA_MAP_0_MASK \ +0xFFFFFFFF /* DIS_STA_MAP_0[31..0] */ +#define WF_PLE_TOP_DIS_STA_MAP0_DIS_STA_MAP_0_SHFT 0 + +/* +* ---DIS_STA_MAP1 (0x820C0000 + 0x444)--- +* DIS_STA_MAP_1[31..0] - (RW) Disable map for STA 32~63 TX +*/ +#define WF_PLE_TOP_DIS_STA_MAP1_DIS_STA_MAP_1_ADDR WF_PLE_TOP_DIS_STA_MAP1_ADDR +#define WF_PLE_TOP_DIS_STA_MAP1_DIS_STA_MAP_1_MASK \ +0xFFFFFFFF /* DIS_STA_MAP_1[31..0] */ +#define WF_PLE_TOP_DIS_STA_MAP1_DIS_STA_MAP_1_SHFT 0 + +/* +* ---DIS_STA_MAP2 (0x820C0000 + 0x448)--- +* DIS_STA_MAP_2[31..0] - (RW) Disable map for STA 64~95 TX +*/ +#define WF_PLE_TOP_DIS_STA_MAP2_DIS_STA_MAP_2_ADDR WF_PLE_TOP_DIS_STA_MAP2_ADDR +#define WF_PLE_TOP_DIS_STA_MAP2_DIS_STA_MAP_2_MASK \ +0xFFFFFFFF /* DIS_STA_MAP_2[31..0] */ +#define WF_PLE_TOP_DIS_STA_MAP2_DIS_STA_MAP_2_SHFT 0 + +/* +* ---DIS_STA_MAP3 (0x820C0000 + 0x44c)--- +* DIS_STA_MAP_3[31..0] - (RW) Disable map for STA 96~127 TX +*/ +#define WF_PLE_TOP_DIS_STA_MAP3_DIS_STA_MAP_3_ADDR WF_PLE_TOP_DIS_STA_MAP3_ADDR +#define WF_PLE_TOP_DIS_STA_MAP3_DIS_STA_MAP_3_MASK \ +0xFFFFFFFF /* DIS_STA_MAP_3[31..0] */ +#define WF_PLE_TOP_DIS_STA_MAP3_DIS_STA_MAP_3_SHFT 0 + +/* +* ---DIS_STA_MAP4 (0x820C0000 + 0x450)--- +* DIS_STA_MAP_4_0[7..0] - (RW) Disable map for STA 128~135 TX +* DIS_STA_MAP_4_1[15..8] - (RW) Disable map for STA 136~143 TX +* DIS_STA_MAP_4_2[31..16] - (RW) Disable map for STA 144~159 TX +*/ +#define WF_PLE_TOP_DIS_STA_MAP4_DIS_STA_MAP_4_2_ADDR \ +WF_PLE_TOP_DIS_STA_MAP4_ADDR +#define WF_PLE_TOP_DIS_STA_MAP4_DIS_STA_MAP_4_2_MASK \ +0xFFFF0000 /* DIS_STA_MAP_4_2[31..16] */ +#define WF_PLE_TOP_DIS_STA_MAP4_DIS_STA_MAP_4_2_SHFT 16 +#define WF_PLE_TOP_DIS_STA_MAP4_DIS_STA_MAP_4_1_ADDR \ +WF_PLE_TOP_DIS_STA_MAP4_ADDR +#define WF_PLE_TOP_DIS_STA_MAP4_DIS_STA_MAP_4_1_MASK \ +0x0000FF00 /* DIS_STA_MAP_4_1[15..8] */ +#define WF_PLE_TOP_DIS_STA_MAP4_DIS_STA_MAP_4_1_SHFT 8 +#define WF_PLE_TOP_DIS_STA_MAP4_DIS_STA_MAP_4_0_ADDR \ +WF_PLE_TOP_DIS_STA_MAP4_ADDR +#define WF_PLE_TOP_DIS_STA_MAP4_DIS_STA_MAP_4_0_MASK \ +0x000000FF /* DIS_STA_MAP_4_0[7..0] */ +#define WF_PLE_TOP_DIS_STA_MAP4_DIS_STA_MAP_4_0_SHFT 0 + +/* +* ---DIS_STA_MAP5 (0x820C0000 + 0x454)--- +* DIS_STA_MAP_5[31..0] - (RW) Disable map for STA 160~191 TX +*/ +#define WF_PLE_TOP_DIS_STA_MAP5_DIS_STA_MAP_5_ADDR WF_PLE_TOP_DIS_STA_MAP5_ADDR +#define WF_PLE_TOP_DIS_STA_MAP5_DIS_STA_MAP_5_MASK \ +0xFFFFFFFF /* DIS_STA_MAP_5[31..0] */ +#define WF_PLE_TOP_DIS_STA_MAP5_DIS_STA_MAP_5_SHFT 0 + +/* +* ---DIS_STA_MAP6 (0x820C0000 + 0x458)--- +* DIS_STA_MAP_6[31..0] - (RW) Disable map for STA 192~223 TX +*/ +#define WF_PLE_TOP_DIS_STA_MAP6_DIS_STA_MAP_6_ADDR WF_PLE_TOP_DIS_STA_MAP6_ADDR +#define WF_PLE_TOP_DIS_STA_MAP6_DIS_STA_MAP_6_MASK \ +0xFFFFFFFF /* DIS_STA_MAP_6[31..0] */ +#define WF_PLE_TOP_DIS_STA_MAP6_DIS_STA_MAP_6_SHFT 0 + +/* +* ---DIS_STA_MAP7 (0x820C0000 + 0x45c)--- +* DIS_STA_MAP_7[31..0] - (RW) Disable map for STA 224~255 TX +*/ +#define WF_PLE_TOP_DIS_STA_MAP7_DIS_STA_MAP_7_ADDR WF_PLE_TOP_DIS_STA_MAP7_ADDR +#define WF_PLE_TOP_DIS_STA_MAP7_DIS_STA_MAP_7_MASK \ +0xFFFFFFFF /* DIS_STA_MAP_7[31..0] */ +#define WF_PLE_TOP_DIS_STA_MAP7_DIS_STA_MAP_7_SHFT 0 + +/* +* ---DIS_STA_MAP8 (0x820C0000 + 0x460)--- +* DIS_STA_MAP_8[31..0] - (RW) Disable map for STA 256~287 TX +*/ +#define WF_PLE_TOP_DIS_STA_MAP8_DIS_STA_MAP_8_ADDR WF_PLE_TOP_DIS_STA_MAP8_ADDR +#define WF_PLE_TOP_DIS_STA_MAP8_DIS_STA_MAP_8_MASK \ +0xFFFFFFFF /* DIS_STA_MAP_8[31..0] */ +#define WF_PLE_TOP_DIS_STA_MAP8_DIS_STA_MAP_8_SHFT 0 + +/* +* ---STATION_REDIR0 (0x820C0000 + 0x480)--- +* STATION_REDIR_0[31..0] - (RW) SW can redirection to designed +* port/queue by this setting for STA0~STA31. +*/ +#define WF_PLE_TOP_STATION_REDIR0_STATION_REDIR_0_ADDR \ +WF_PLE_TOP_STATION_REDIR0_ADDR +#define WF_PLE_TOP_STATION_REDIR0_STATION_REDIR_0_MASK \ +0xFFFFFFFF /* STATION_REDIR_0[31..0] */ +#define WF_PLE_TOP_STATION_REDIR0_STATION_REDIR_0_SHFT 0 + +/* +* ---STATION_REDIR1 (0x820C0000 + 0x484)--- +* STATION_REDIR_1[31..0] - (RW) SW can redirection to designed +* port/queue by this setting for STA32~STA63. +*/ +#define WF_PLE_TOP_STATION_REDIR1_STATION_REDIR_1_ADDR \ +WF_PLE_TOP_STATION_REDIR1_ADDR +#define WF_PLE_TOP_STATION_REDIR1_STATION_REDIR_1_MASK \ +0xFFFFFFFF /* STATION_REDIR_1[31..0] */ +#define WF_PLE_TOP_STATION_REDIR1_STATION_REDIR_1_SHFT 0 + +/* +* ---STATION_REDIR2 (0x820C0000 + 0x488)--- +* STATION_REDIR_2[31..0] - (RW) SW can redirection to designed +* port/queue by this setting for STA64~STA95. +*/ +#define WF_PLE_TOP_STATION_REDIR2_STATION_REDIR_2_ADDR \ +WF_PLE_TOP_STATION_REDIR2_ADDR +#define WF_PLE_TOP_STATION_REDIR2_STATION_REDIR_2_MASK \ +0xFFFFFFFF /* STATION_REDIR_2[31..0] */ +#define WF_PLE_TOP_STATION_REDIR2_STATION_REDIR_2_SHFT 0 + +/* +* ---STATION_REDIR3 (0x820C0000 + 0x48c)--- +* STATION_REDIR_3[31..0] - (RW) SW can redirection to designed +* port/queue by this setting for STA96~STA127. +*/ +#define WF_PLE_TOP_STATION_REDIR3_STATION_REDIR_3_ADDR \ +WF_PLE_TOP_STATION_REDIR3_ADDR +#define WF_PLE_TOP_STATION_REDIR3_STATION_REDIR_3_MASK \ +0xFFFFFFFF /* STATION_REDIR_3[31..0] */ +#define WF_PLE_TOP_STATION_REDIR3_STATION_REDIR_3_SHFT 0 + +/* +* ---STATION_REDIR4 (0x820C0000 + 0x490)--- +* STATION_REDIR_4_0[7..0] - (RW) SW can redirection to designed +* port/queue by this setting for STA128~STA135. +* STATION_REDIR_4_1[15..8] - (RW) SW can redirection to designed +* port/queue by this setting for STA136~STA143. +* STATION_REDIR_4_2[31..16] - (RW) SW can redirection to designed +* port/queue by this setting for STA144~STA159. +*/ +#define WF_PLE_TOP_STATION_REDIR4_STATION_REDIR_4_2_ADDR \ +WF_PLE_TOP_STATION_REDIR4_ADDR +#define WF_PLE_TOP_STATION_REDIR4_STATION_REDIR_4_2_MASK \ +0xFFFF0000 /* STATION_REDIR_4_2[31..16] */ +#define WF_PLE_TOP_STATION_REDIR4_STATION_REDIR_4_2_SHFT 16 +#define WF_PLE_TOP_STATION_REDIR4_STATION_REDIR_4_1_ADDR \ +WF_PLE_TOP_STATION_REDIR4_ADDR +#define WF_PLE_TOP_STATION_REDIR4_STATION_REDIR_4_1_MASK \ +0x0000FF00 /* STATION_REDIR_4_1[15..8] */ +#define WF_PLE_TOP_STATION_REDIR4_STATION_REDIR_4_1_SHFT 8 +#define WF_PLE_TOP_STATION_REDIR4_STATION_REDIR_4_0_ADDR \ +WF_PLE_TOP_STATION_REDIR4_ADDR +#define WF_PLE_TOP_STATION_REDIR4_STATION_REDIR_4_0_MASK \ +0x000000FF /* STATION_REDIR_4_0[7..0] */ +#define WF_PLE_TOP_STATION_REDIR4_STATION_REDIR_4_0_SHFT 0 + +/* +* ---STATION_REDIR5 (0x820C0000 + 0x494)--- +* STATION_REDIR_5[31..0] - (RW) SW can redirection to designed +* port/queue by this setting STA160~STA191. +*/ +#define WF_PLE_TOP_STATION_REDIR5_STATION_REDIR_5_ADDR \ +WF_PLE_TOP_STATION_REDIR5_ADDR +#define WF_PLE_TOP_STATION_REDIR5_STATION_REDIR_5_MASK \ +0xFFFFFFFF /* STATION_REDIR_5[31..0] */ +#define WF_PLE_TOP_STATION_REDIR5_STATION_REDIR_5_SHFT 0 + +/* +* ---STATION_REDIR6 (0x820C0000 + 0x498)--- +* STATION_REDIR_6[31..0] - (RW) SW can redirection to designed +* port/queue by this setting STA192~STA223. +*/ +#define WF_PLE_TOP_STATION_REDIR6_STATION_REDIR_6_ADDR \ +WF_PLE_TOP_STATION_REDIR6_ADDR +#define WF_PLE_TOP_STATION_REDIR6_STATION_REDIR_6_MASK \ +0xFFFFFFFF /* STATION_REDIR_6[31..0] */ +#define WF_PLE_TOP_STATION_REDIR6_STATION_REDIR_6_SHFT 0 + +/* +* ---STATION_REDIR7 (0x820C0000 + 0x49c)--- +* STATION_REDIR_7[31..0] - (RW) SW can redirection to designed +* port/queue by this setting STA224~STA255. +*/ +#define WF_PLE_TOP_STATION_REDIR7_STATION_REDIR_7_ADDR \ +WF_PLE_TOP_STATION_REDIR7_ADDR +#define WF_PLE_TOP_STATION_REDIR7_STATION_REDIR_7_MASK \ +0xFFFFFFFF /* STATION_REDIR_7[31..0] */ +#define WF_PLE_TOP_STATION_REDIR7_STATION_REDIR_7_SHFT 0 + +/* +* ---STATION_REDIR8 (0x820C0000 + 0x4a0)--- +* STATION_REDIR8[31..0] - (RW) SW can redirection to designed +* port/queue by this setting STA256~STA287. +*/ +#define WF_PLE_TOP_STATION_REDIR8_STATION_REDIR8_ADDR \ +WF_PLE_TOP_STATION_REDIR8_ADDR +#define WF_PLE_TOP_STATION_REDIR8_STATION_REDIR8_MASK \ +0xFFFFFFFF /* STATION_REDIR8[31..0] */ +#define WF_PLE_TOP_STATION_REDIR8_STATION_REDIR8_SHFT 0 + +/* +* ---TWT_STA_MAP0 (0x820C0000 + 0x4c0)--- +* TWT_STA_MAP_0[31..0] - (RW) TWT map for STA 0~31 TX +*/ +#define WF_PLE_TOP_TWT_STA_MAP0_TWT_STA_MAP_0_ADDR WF_PLE_TOP_TWT_STA_MAP0_ADDR +#define WF_PLE_TOP_TWT_STA_MAP0_TWT_STA_MAP_0_MASK \ +0xFFFFFFFF /* TWT_STA_MAP_0[31..0] */ +#define WF_PLE_TOP_TWT_STA_MAP0_TWT_STA_MAP_0_SHFT 0 + +/* +* ---TWT_STA_MAP1 (0x820C0000 + 0x4c4)--- +* TWT_STA_MAP_1[31..0] - (RW) TWT map for STA 32~63 TX +*/ +#define WF_PLE_TOP_TWT_STA_MAP1_TWT_STA_MAP_1_ADDR WF_PLE_TOP_TWT_STA_MAP1_ADDR +#define WF_PLE_TOP_TWT_STA_MAP1_TWT_STA_MAP_1_MASK \ +0xFFFFFFFF /* TWT_STA_MAP_1[31..0] */ +#define WF_PLE_TOP_TWT_STA_MAP1_TWT_STA_MAP_1_SHFT 0 + +/* +* ---TWT_STA_MAP2 (0x820C0000 + 0x4c8)--- +* TWT_STA_MAP_2[31..0] - (RW) TWT map for STA 64~95 TX +*/ +#define WF_PLE_TOP_TWT_STA_MAP2_TWT_STA_MAP_2_ADDR WF_PLE_TOP_TWT_STA_MAP2_ADDR +#define WF_PLE_TOP_TWT_STA_MAP2_TWT_STA_MAP_2_MASK \ +0xFFFFFFFF /* TWT_STA_MAP_2[31..0] */ +#define WF_PLE_TOP_TWT_STA_MAP2_TWT_STA_MAP_2_SHFT 0 + +/* +* ---TWT_STA_MAP3 (0x820C0000 + 0x4cc)--- +* TWT_STA_MAP_3[31..0] - (RW) TWT map for STA 96~127 TX +*/ +#define WF_PLE_TOP_TWT_STA_MAP3_TWT_STA_MAP_3_ADDR WF_PLE_TOP_TWT_STA_MAP3_ADDR +#define WF_PLE_TOP_TWT_STA_MAP3_TWT_STA_MAP_3_MASK \ +0xFFFFFFFF /* TWT_STA_MAP_3[31..0] */ +#define WF_PLE_TOP_TWT_STA_MAP3_TWT_STA_MAP_3_SHFT 0 + +/* +* ---TWT_STA_MAP4 (0x820C0000 + 0x4d0)--- +* TWT_STA_MAP_4_0[7..0] - (RW) TWT map for STA 128~135 TX +* TWT_STA_MAP_4_1[15..8] - (RW) TWT map for STA 136~143 TX +* TWT_STA_MAP_4_2[31..16] - (RW) TWT map for STA 144~159 TX +*/ +#define WF_PLE_TOP_TWT_STA_MAP4_TWT_STA_MAP_4_2_ADDR \ +WF_PLE_TOP_TWT_STA_MAP4_ADDR +#define WF_PLE_TOP_TWT_STA_MAP4_TWT_STA_MAP_4_2_MASK \ +0xFFFF0000 /* TWT_STA_MAP_4_2[31..16] */ +#define WF_PLE_TOP_TWT_STA_MAP4_TWT_STA_MAP_4_2_SHFT 16 +#define WF_PLE_TOP_TWT_STA_MAP4_TWT_STA_MAP_4_1_ADDR \ +WF_PLE_TOP_TWT_STA_MAP4_ADDR +#define WF_PLE_TOP_TWT_STA_MAP4_TWT_STA_MAP_4_1_MASK \ +0x0000FF00 /* TWT_STA_MAP_4_1[15..8] */ +#define WF_PLE_TOP_TWT_STA_MAP4_TWT_STA_MAP_4_1_SHFT 8 +#define WF_PLE_TOP_TWT_STA_MAP4_TWT_STA_MAP_4_0_ADDR \ +WF_PLE_TOP_TWT_STA_MAP4_ADDR +#define WF_PLE_TOP_TWT_STA_MAP4_TWT_STA_MAP_4_0_MASK \ +0x000000FF /* TWT_STA_MAP_4_0[7..0] */ +#define WF_PLE_TOP_TWT_STA_MAP4_TWT_STA_MAP_4_0_SHFT 0 + +/* +* ---TWT_STA_MAP5 (0x820C0000 + 0x4d4)--- +* TWT_STA_MAP_5[31..0] - (RW) TWT map for STA 160~191 TX +*/ +#define WF_PLE_TOP_TWT_STA_MAP5_TWT_STA_MAP_5_ADDR WF_PLE_TOP_TWT_STA_MAP5_ADDR +#define WF_PLE_TOP_TWT_STA_MAP5_TWT_STA_MAP_5_MASK \ +0xFFFFFFFF /* TWT_STA_MAP_5[31..0] */ +#define WF_PLE_TOP_TWT_STA_MAP5_TWT_STA_MAP_5_SHFT 0 + +/* +* ---TWT_STA_MAP6 (0x820C0000 + 0x4d8)--- +* TWT_STA_MAP_6[31..0] - (RW) TWT map for STA 192~223 TX +*/ +#define WF_PLE_TOP_TWT_STA_MAP6_TWT_STA_MAP_6_ADDR WF_PLE_TOP_TWT_STA_MAP6_ADDR +#define WF_PLE_TOP_TWT_STA_MAP6_TWT_STA_MAP_6_MASK \ +0xFFFFFFFF /* TWT_STA_MAP_6[31..0] */ +#define WF_PLE_TOP_TWT_STA_MAP6_TWT_STA_MAP_6_SHFT 0 + +/* +* ---TWT_STA_MAP7 (0x820C0000 + 0x4dc)--- +* TWT_STA_MAP_7[31..0] - (RW) TWT map for STA 224~255 TX +*/ +#define WF_PLE_TOP_TWT_STA_MAP7_TWT_STA_MAP_7_ADDR WF_PLE_TOP_TWT_STA_MAP7_ADDR +#define WF_PLE_TOP_TWT_STA_MAP7_TWT_STA_MAP_7_MASK \ +0xFFFFFFFF /* TWT_STA_MAP_7[31..0] */ +#define WF_PLE_TOP_TWT_STA_MAP7_TWT_STA_MAP_7_SHFT 0 + +/* +* ---TWT_STA_MAP8 (0x820C0000 + 0x4e0)--- +* TWT_STA_MAP_8[31..0] - (RW) TWT map for STA 256~287 TX +*/ +#define WF_PLE_TOP_TWT_STA_MAP8_TWT_STA_MAP_8_ADDR WF_PLE_TOP_TWT_STA_MAP8_ADDR +#define WF_PLE_TOP_TWT_STA_MAP8_TWT_STA_MAP_8_MASK \ +0xFFFFFFFF /* TWT_STA_MAP_8[31..0] */ +#define WF_PLE_TOP_TWT_STA_MAP8_TWT_STA_MAP_8_SHFT 0 + +/* +* ---AC0_QUEUE_EMPTY0 (0x820C0000 + 0x500)--- +* AC0_QUEUE_EMPTY_0[31..0] - (RO) Empty flag for STA 0~31 AC0 queue +*/ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY0_AC0_QUEUE_EMPTY_0_ADDR \ +WF_PLE_TOP_AC0_QUEUE_EMPTY0_ADDR +#define WF_PLE_TOP_AC0_QUEUE_EMPTY0_AC0_QUEUE_EMPTY_0_MASK \ +0xFFFFFFFF /* AC0_QUEUE_EMPTY_0[31..0] */ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY0_AC0_QUEUE_EMPTY_0_SHFT 0 + +/* +* ---AC0_QUEUE_EMPTY1 (0x820C0000 + 0x504)--- +* AC0_QUEUE_EMPTY_1[31..0] - (RO) Empty flag for STA 32~63 AC0 queue +*/ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY1_AC0_QUEUE_EMPTY_1_ADDR \ +WF_PLE_TOP_AC0_QUEUE_EMPTY1_ADDR +#define WF_PLE_TOP_AC0_QUEUE_EMPTY1_AC0_QUEUE_EMPTY_1_MASK \ +0xFFFFFFFF /* AC0_QUEUE_EMPTY_1[31..0] */ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY1_AC0_QUEUE_EMPTY_1_SHFT 0 + +/* +* ---AC0_QUEUE_EMPTY2 (0x820C0000 + 0x508)--- +* AC0_QUEUE_EMPTY_2[31..0] - (RO) Empty flag for STA 64~95 AC0 queue +*/ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY2_AC0_QUEUE_EMPTY_2_ADDR \ +WF_PLE_TOP_AC0_QUEUE_EMPTY2_ADDR +#define WF_PLE_TOP_AC0_QUEUE_EMPTY2_AC0_QUEUE_EMPTY_2_MASK \ +0xFFFFFFFF /* AC0_QUEUE_EMPTY_2[31..0] */ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY2_AC0_QUEUE_EMPTY_2_SHFT 0 + +/* +* ---AC0_QUEUE_EMPTY3 (0x820C0000 + 0x50c)--- +* AC0_QUEUE_EMPTY_3[31..0] - (RO) Empty flag for STA 96~127 AC0 queue +*/ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY3_AC0_QUEUE_EMPTY_3_ADDR \ +WF_PLE_TOP_AC0_QUEUE_EMPTY3_ADDR +#define WF_PLE_TOP_AC0_QUEUE_EMPTY3_AC0_QUEUE_EMPTY_3_MASK \ +0xFFFFFFFF /* AC0_QUEUE_EMPTY_3[31..0] */ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY3_AC0_QUEUE_EMPTY_3_SHFT 0 + +/* +* ---AC0_QUEUE_EMPTY4 (0x820C0000 + 0x510)--- +* AC0_QUEUE_EMPTY_4_0[7..0] - (RO) Empty flag for STA 128~135 AC0 queue +* AC0_QUEUE_EMPTY_4_1[15..8] - (RO) Empty flag for STA 136~143 AC0 queue +* AC0_QUEUE_EMPTY_4_2[31..16] - (RO) Empty flag for STA 144~159 AC0 queue +*/ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY4_AC0_QUEUE_EMPTY_4_2_ADDR \ +WF_PLE_TOP_AC0_QUEUE_EMPTY4_ADDR +#define WF_PLE_TOP_AC0_QUEUE_EMPTY4_AC0_QUEUE_EMPTY_4_2_MASK \ +0xFFFF0000 /* AC0_QUEUE_EMPTY_4_2[31..16] */ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY4_AC0_QUEUE_EMPTY_4_2_SHFT 16 +#define WF_PLE_TOP_AC0_QUEUE_EMPTY4_AC0_QUEUE_EMPTY_4_1_ADDR \ +WF_PLE_TOP_AC0_QUEUE_EMPTY4_ADDR +#define WF_PLE_TOP_AC0_QUEUE_EMPTY4_AC0_QUEUE_EMPTY_4_1_MASK \ +0x0000FF00 /* AC0_QUEUE_EMPTY_4_1[15..8] */ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY4_AC0_QUEUE_EMPTY_4_1_SHFT 8 +#define WF_PLE_TOP_AC0_QUEUE_EMPTY4_AC0_QUEUE_EMPTY_4_0_ADDR \ +WF_PLE_TOP_AC0_QUEUE_EMPTY4_ADDR +#define WF_PLE_TOP_AC0_QUEUE_EMPTY4_AC0_QUEUE_EMPTY_4_0_MASK \ +0x000000FF /* AC0_QUEUE_EMPTY_4_0[7..0] */ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY4_AC0_QUEUE_EMPTY_4_0_SHFT 0 + +/* +* ---AC0_QUEUE_EMPTY5 (0x820C0000 + 0x514)--- +* AC0_QUEUE_EMPTY_5[31..0] - (RO) Empty flag for STA 160~191 AC0 queue +*/ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY5_AC0_QUEUE_EMPTY_5_ADDR \ +WF_PLE_TOP_AC0_QUEUE_EMPTY5_ADDR +#define WF_PLE_TOP_AC0_QUEUE_EMPTY5_AC0_QUEUE_EMPTY_5_MASK \ +0xFFFFFFFF /* AC0_QUEUE_EMPTY_5[31..0] */ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY5_AC0_QUEUE_EMPTY_5_SHFT 0 + +/* +* ---AC0_QUEUE_EMPTY6 (0x820C0000 + 0x518)--- +* AC0_QUEUE_EMPTY_6[31..0] - (RO) Empty flag for STA 192~223 AC0 queue +*/ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY6_AC0_QUEUE_EMPTY_6_ADDR \ +WF_PLE_TOP_AC0_QUEUE_EMPTY6_ADDR +#define WF_PLE_TOP_AC0_QUEUE_EMPTY6_AC0_QUEUE_EMPTY_6_MASK \ +0xFFFFFFFF /* AC0_QUEUE_EMPTY_6[31..0] */ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY6_AC0_QUEUE_EMPTY_6_SHFT 0 + +/* +* ---AC0_QUEUE_EMPTY7 (0x820C0000 + 0x51c)--- +* AC0_QUEUE_EMPTY_7[31..0] - (RO) Empty flag for STA 224~255 AC0 queue +*/ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY7_AC0_QUEUE_EMPTY_7_ADDR \ +WF_PLE_TOP_AC0_QUEUE_EMPTY7_ADDR +#define WF_PLE_TOP_AC0_QUEUE_EMPTY7_AC0_QUEUE_EMPTY_7_MASK \ +0xFFFFFFFF /* AC0_QUEUE_EMPTY_7[31..0] */ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY7_AC0_QUEUE_EMPTY_7_SHFT 0 + +/* +* ---AC0_QUEUE_EMPTY8 (0x820C0000 + 0x520)--- +* AC0_QUEUE_EMPTY_8[31..0] - (RO) Empty flag for STA 256~287 AC0 queue +*/ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY8_AC0_QUEUE_EMPTY_8_ADDR \ +WF_PLE_TOP_AC0_QUEUE_EMPTY8_ADDR +#define WF_PLE_TOP_AC0_QUEUE_EMPTY8_AC0_QUEUE_EMPTY_8_MASK \ +0xFFFFFFFF /* AC0_QUEUE_EMPTY_8[31..0] */ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY8_AC0_QUEUE_EMPTY_8_SHFT 0 + +/* +* ---AC1_QUEUE_EMPTY0 (0x820C0000 + 0x540)--- +* AC1_QUEUE_EMPTY_0[31..0] - (RO) Empty flag for STA 0~31 AC1 queue +*/ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY0_AC1_QUEUE_EMPTY_0_ADDR \ +WF_PLE_TOP_AC1_QUEUE_EMPTY0_ADDR +#define WF_PLE_TOP_AC1_QUEUE_EMPTY0_AC1_QUEUE_EMPTY_0_MASK \ +0xFFFFFFFF /* AC1_QUEUE_EMPTY_0[31..0] */ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY0_AC1_QUEUE_EMPTY_0_SHFT 0 + +/* +* ---AC1_QUEUE_EMPTY1 (0x820C0000 + 0x544)--- +* AC1_QUEUE_EMPTY_1[31..0] - (RO) Empty flag for STA 32~63 AC1 queue +*/ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY1_AC1_QUEUE_EMPTY_1_ADDR \ +WF_PLE_TOP_AC1_QUEUE_EMPTY1_ADDR +#define WF_PLE_TOP_AC1_QUEUE_EMPTY1_AC1_QUEUE_EMPTY_1_MASK \ +0xFFFFFFFF /* AC1_QUEUE_EMPTY_1[31..0] */ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY1_AC1_QUEUE_EMPTY_1_SHFT 0 + +/* +* ---AC1_QUEUE_EMPTY2 (0x820C0000 + 0x548)--- +* AC1_QUEUE_EMPTY_2[31..0] - (RO) Empty flag for STA 64~95 AC1 queue +*/ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY2_AC1_QUEUE_EMPTY_2_ADDR \ +WF_PLE_TOP_AC1_QUEUE_EMPTY2_ADDR +#define WF_PLE_TOP_AC1_QUEUE_EMPTY2_AC1_QUEUE_EMPTY_2_MASK \ +0xFFFFFFFF /* AC1_QUEUE_EMPTY_2[31..0] */ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY2_AC1_QUEUE_EMPTY_2_SHFT 0 + +/* +* ---AC1_QUEUE_EMPTY3 (0x820C0000 + 0x54c)--- +* AC1_QUEUE_EMPTY_3[31..0] - (RO) Empty flag for STA 96~127 AC1 queue +*/ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY3_AC1_QUEUE_EMPTY_3_ADDR \ +WF_PLE_TOP_AC1_QUEUE_EMPTY3_ADDR +#define WF_PLE_TOP_AC1_QUEUE_EMPTY3_AC1_QUEUE_EMPTY_3_MASK \ +0xFFFFFFFF /* AC1_QUEUE_EMPTY_3[31..0] */ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY3_AC1_QUEUE_EMPTY_3_SHFT 0 + +/* +* ---AC1_QUEUE_EMPTY4 (0x820C0000 + 0x550)--- +* AC1_QUEUE_EMPTY_4_0[7..0] - (RO) Empty flag for STA 128~135 AC1 queue +* AC1_QUEUE_EMPTY_4_1[15..8] - (RO) Empty flag for STA 136~143 AC1 queue +* AC1_QUEUE_EMPTY_4_2[31..16] - (RO) Empty flag for STA 144~159 AC1 queue +*/ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY4_AC1_QUEUE_EMPTY_4_2_ADDR \ +WF_PLE_TOP_AC1_QUEUE_EMPTY4_ADDR +#define WF_PLE_TOP_AC1_QUEUE_EMPTY4_AC1_QUEUE_EMPTY_4_2_MASK \ +0xFFFF0000 /* AC1_QUEUE_EMPTY_4_2[31..16] */ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY4_AC1_QUEUE_EMPTY_4_2_SHFT 16 +#define WF_PLE_TOP_AC1_QUEUE_EMPTY4_AC1_QUEUE_EMPTY_4_1_ADDR \ +WF_PLE_TOP_AC1_QUEUE_EMPTY4_ADDR +#define WF_PLE_TOP_AC1_QUEUE_EMPTY4_AC1_QUEUE_EMPTY_4_1_MASK \ +0x0000FF00 /* AC1_QUEUE_EMPTY_4_1[15..8] */ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY4_AC1_QUEUE_EMPTY_4_1_SHFT 8 +#define WF_PLE_TOP_AC1_QUEUE_EMPTY4_AC1_QUEUE_EMPTY_4_0_ADDR \ +WF_PLE_TOP_AC1_QUEUE_EMPTY4_ADDR +#define WF_PLE_TOP_AC1_QUEUE_EMPTY4_AC1_QUEUE_EMPTY_4_0_MASK \ +0x000000FF /* AC1_QUEUE_EMPTY_4_0[7..0] */ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY4_AC1_QUEUE_EMPTY_4_0_SHFT 0 + +/* +* ---AC1_QUEUE_EMPTY5 (0x820C0000 + 0x554)--- +* AC1_QUEUE_EMPTY_5[31..0] - (RO) Empty flag for STA 160~191 AC1 queue +*/ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY5_AC1_QUEUE_EMPTY_5_ADDR \ +WF_PLE_TOP_AC1_QUEUE_EMPTY5_ADDR +#define WF_PLE_TOP_AC1_QUEUE_EMPTY5_AC1_QUEUE_EMPTY_5_MASK \ +0xFFFFFFFF /* AC1_QUEUE_EMPTY_5[31..0] */ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY5_AC1_QUEUE_EMPTY_5_SHFT 0 + +/* +* ---AC1_QUEUE_EMPTY6 (0x820C0000 + 0x558)--- +* AC1_QUEUE_EMPTY_6[31..0] - (RO) Empty flag for STA 192~223 AC1 queue +*/ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY6_AC1_QUEUE_EMPTY_6_ADDR \ +WF_PLE_TOP_AC1_QUEUE_EMPTY6_ADDR +#define WF_PLE_TOP_AC1_QUEUE_EMPTY6_AC1_QUEUE_EMPTY_6_MASK \ +0xFFFFFFFF /* AC1_QUEUE_EMPTY_6[31..0] */ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY6_AC1_QUEUE_EMPTY_6_SHFT 0 + +/* +* ---AC1_QUEUE_EMPTY7 (0x820C0000 + 0x55c)--- +* AC1_QUEUE_EMPTY_7[31..0] - (RO) Empty flag for STA 224~255 AC1 queue +*/ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY7_AC1_QUEUE_EMPTY_7_ADDR \ +WF_PLE_TOP_AC1_QUEUE_EMPTY7_ADDR +#define WF_PLE_TOP_AC1_QUEUE_EMPTY7_AC1_QUEUE_EMPTY_7_MASK \ +0xFFFFFFFF /* AC1_QUEUE_EMPTY_7[31..0] */ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY7_AC1_QUEUE_EMPTY_7_SHFT 0 + +/* +* ---AC1_QUEUE_EMPTY8 (0x820C0000 + 0x560)--- +* AC1_QUEUE_EMPTY_8[31..0] - (RO) Empty flag for STA 256~287 AC1 queue +*/ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY8_AC1_QUEUE_EMPTY_8_ADDR \ +WF_PLE_TOP_AC1_QUEUE_EMPTY8_ADDR +#define WF_PLE_TOP_AC1_QUEUE_EMPTY8_AC1_QUEUE_EMPTY_8_MASK \ +0xFFFFFFFF /* AC1_QUEUE_EMPTY_8[31..0] */ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY8_AC1_QUEUE_EMPTY_8_SHFT 0 + +/* +* ---AC2_QUEUE_EMPTY0 (0x820C0000 + 0x580)--- +* AC2_QUEUE_EMPTY_0[31..0] - (RO) Empty flag for STA 0~31 AC2 queue +*/ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY0_AC2_QUEUE_EMPTY_0_ADDR \ +WF_PLE_TOP_AC2_QUEUE_EMPTY0_ADDR +#define WF_PLE_TOP_AC2_QUEUE_EMPTY0_AC2_QUEUE_EMPTY_0_MASK \ +0xFFFFFFFF /* AC2_QUEUE_EMPTY_0[31..0] */ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY0_AC2_QUEUE_EMPTY_0_SHFT 0 + +/* +* ---AC2_QUEUE_EMPTY1 (0x820C0000 + 0x584)--- +* AC2_QUEUE_EMPTY_1[31..0] - (RO) Empty flag for STA 32~63 AC2 queue +*/ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY1_AC2_QUEUE_EMPTY_1_ADDR \ +WF_PLE_TOP_AC2_QUEUE_EMPTY1_ADDR +#define WF_PLE_TOP_AC2_QUEUE_EMPTY1_AC2_QUEUE_EMPTY_1_MASK \ +0xFFFFFFFF /* AC2_QUEUE_EMPTY_1[31..0] */ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY1_AC2_QUEUE_EMPTY_1_SHFT 0 + +/* +* ---AC2_QUEUE_EMPTY2 (0x820C0000 + 0x588)--- +* AC2_QUEUE_EMPTY_2[31..0] - (RO) Empty flag for STA 64~95 AC2 queue +*/ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY2_AC2_QUEUE_EMPTY_2_ADDR \ +WF_PLE_TOP_AC2_QUEUE_EMPTY2_ADDR +#define WF_PLE_TOP_AC2_QUEUE_EMPTY2_AC2_QUEUE_EMPTY_2_MASK \ +0xFFFFFFFF /* AC2_QUEUE_EMPTY_2[31..0] */ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY2_AC2_QUEUE_EMPTY_2_SHFT 0 + +/* +* ---AC2_QUEUE_EMPTY3 (0x820C0000 + 0x58c)--- +* AC2_QUEUE_EMPTY_3[31..0] - (RO) Empty flag for STA 96~127 AC2 queue +*/ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY3_AC2_QUEUE_EMPTY_3_ADDR \ +WF_PLE_TOP_AC2_QUEUE_EMPTY3_ADDR +#define WF_PLE_TOP_AC2_QUEUE_EMPTY3_AC2_QUEUE_EMPTY_3_MASK \ +0xFFFFFFFF /* AC2_QUEUE_EMPTY_3[31..0] */ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY3_AC2_QUEUE_EMPTY_3_SHFT 0 + +/* +* ---AC2_QUEUE_EMPTY4 (0x820C0000 + 0x590)--- +* AC2_QUEUE_EMPTY_4_0[7..0] - (RO) Empty flag for STA 128~135 AC2 queue +* AC2_QUEUE_EMPTY_4_1[15..8] - (RO) Empty flag for STA 136~143 AC2 queue +* AC2_QUEUE_EMPTY_4_2[31..16] - (RO) Empty flag for STA 144~159 AC2 queue +*/ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY4_AC2_QUEUE_EMPTY_4_2_ADDR \ +WF_PLE_TOP_AC2_QUEUE_EMPTY4_ADDR +#define WF_PLE_TOP_AC2_QUEUE_EMPTY4_AC2_QUEUE_EMPTY_4_2_MASK \ +0xFFFF0000 /* AC2_QUEUE_EMPTY_4_2[31..16] */ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY4_AC2_QUEUE_EMPTY_4_2_SHFT 16 +#define WF_PLE_TOP_AC2_QUEUE_EMPTY4_AC2_QUEUE_EMPTY_4_1_ADDR \ +WF_PLE_TOP_AC2_QUEUE_EMPTY4_ADDR +#define WF_PLE_TOP_AC2_QUEUE_EMPTY4_AC2_QUEUE_EMPTY_4_1_MASK \ +0x0000FF00 /* AC2_QUEUE_EMPTY_4_1[15..8] */ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY4_AC2_QUEUE_EMPTY_4_1_SHFT 8 +#define WF_PLE_TOP_AC2_QUEUE_EMPTY4_AC2_QUEUE_EMPTY_4_0_ADDR \ +WF_PLE_TOP_AC2_QUEUE_EMPTY4_ADDR +#define WF_PLE_TOP_AC2_QUEUE_EMPTY4_AC2_QUEUE_EMPTY_4_0_MASK \ +0x000000FF /* AC2_QUEUE_EMPTY_4_0[7..0] */ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY4_AC2_QUEUE_EMPTY_4_0_SHFT 0 + +/* +* ---AC2_QUEUE_EMPTY5 (0x820C0000 + 0x594)--- +* AC2_QUEUE_EMPTY_5[31..0] - (RO) Empty flag for STA 160~191 AC2 queue +*/ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY5_AC2_QUEUE_EMPTY_5_ADDR \ +WF_PLE_TOP_AC2_QUEUE_EMPTY5_ADDR +#define WF_PLE_TOP_AC2_QUEUE_EMPTY5_AC2_QUEUE_EMPTY_5_MASK \ +0xFFFFFFFF /* AC2_QUEUE_EMPTY_5[31..0] */ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY5_AC2_QUEUE_EMPTY_5_SHFT 0 + +/* +* ---AC2_QUEUE_EMPTY6 (0x820C0000 + 0x598)--- +* AC2_QUEUE_EMPTY_6[31..0] - (RO) Empty flag for STA 192~223 AC2 queue +*/ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY6_AC2_QUEUE_EMPTY_6_ADDR \ +WF_PLE_TOP_AC2_QUEUE_EMPTY6_ADDR +#define WF_PLE_TOP_AC2_QUEUE_EMPTY6_AC2_QUEUE_EMPTY_6_MASK \ +0xFFFFFFFF /* AC2_QUEUE_EMPTY_6[31..0] */ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY6_AC2_QUEUE_EMPTY_6_SHFT 0 + +/* +* ---AC2_QUEUE_EMPTY7 (0x820C0000 + 0x59c)--- +* AC2_QUEUE_EMPTY_7[31..0] - (RO) Empty flag for STA 224~255 AC2 queue +*/ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY7_AC2_QUEUE_EMPTY_7_ADDR \ +WF_PLE_TOP_AC2_QUEUE_EMPTY7_ADDR +#define WF_PLE_TOP_AC2_QUEUE_EMPTY7_AC2_QUEUE_EMPTY_7_MASK \ +0xFFFFFFFF /* AC2_QUEUE_EMPTY_7[31..0] */ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY7_AC2_QUEUE_EMPTY_7_SHFT 0 + +/* +* ---AC2_QUEUE_EMPTY8 (0x820C0000 + 0x5a0)--- +* AC2_QUEUE_EMPTY_8[31..0] - (RO) Empty flag for STA 256~287 AC2 queue +*/ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY8_AC2_QUEUE_EMPTY_8_ADDR \ +WF_PLE_TOP_AC2_QUEUE_EMPTY8_ADDR +#define WF_PLE_TOP_AC2_QUEUE_EMPTY8_AC2_QUEUE_EMPTY_8_MASK \ +0xFFFFFFFF /* AC2_QUEUE_EMPTY_8[31..0] */ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY8_AC2_QUEUE_EMPTY_8_SHFT 0 + +/* +* ---AC3_QUEUE_EMPTY0 (0x820C0000 + 0x5c0)--- +* AC3_QUEUE_EMPTY_0[31..0] - (RO) Empty flag for STA 0~31 AC3 queue +*/ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY0_AC3_QUEUE_EMPTY_0_ADDR \ +WF_PLE_TOP_AC3_QUEUE_EMPTY0_ADDR +#define WF_PLE_TOP_AC3_QUEUE_EMPTY0_AC3_QUEUE_EMPTY_0_MASK \ +0xFFFFFFFF /* AC3_QUEUE_EMPTY_0[31..0] */ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY0_AC3_QUEUE_EMPTY_0_SHFT 0 + +/* +* ---AC3_QUEUE_EMPTY1 (0x820C0000 + 0x5c4)--- +* AC3_QUEUE_EMPTY_1[31..0] - (RO) Empty flag for STA 32~63 AC3 queue +*/ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY1_AC3_QUEUE_EMPTY_1_ADDR \ +WF_PLE_TOP_AC3_QUEUE_EMPTY1_ADDR +#define WF_PLE_TOP_AC3_QUEUE_EMPTY1_AC3_QUEUE_EMPTY_1_MASK \ +0xFFFFFFFF /* AC3_QUEUE_EMPTY_1[31..0] */ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY1_AC3_QUEUE_EMPTY_1_SHFT 0 + +/* +* ---AC3_QUEUE_EMPTY2 (0x820C0000 + 0x5c8)--- +* AC3_QUEUE_EMPTY_2[31..0] - (RO) Empty flag for STA 64~95 AC3 queue +*/ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY2_AC3_QUEUE_EMPTY_2_ADDR \ +WF_PLE_TOP_AC3_QUEUE_EMPTY2_ADDR +#define WF_PLE_TOP_AC3_QUEUE_EMPTY2_AC3_QUEUE_EMPTY_2_MASK \ +0xFFFFFFFF /* AC3_QUEUE_EMPTY_2[31..0] */ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY2_AC3_QUEUE_EMPTY_2_SHFT 0 + +/* +* ---AC3_QUEUE_EMPTY3 (0x820C0000 + 0x5cc)--- +* AC3_QUEUE_EMPTY_3[31..0] - (RO) Empty flag for STA 96~127 AC3 queue +*/ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY3_AC3_QUEUE_EMPTY_3_ADDR \ +WF_PLE_TOP_AC3_QUEUE_EMPTY3_ADDR +#define WF_PLE_TOP_AC3_QUEUE_EMPTY3_AC3_QUEUE_EMPTY_3_MASK \ +0xFFFFFFFF /* AC3_QUEUE_EMPTY_3[31..0] */ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY3_AC3_QUEUE_EMPTY_3_SHFT 0 + +/* +* ---AC3_QUEUE_EMPTY4 (0x820C0000 + 0x5d0)--- +* AC3_QUEUE_EMPTY_4_0[7..0] - (RO) Empty flag for STA 128~135 AC3 queue +* AC3_QUEUE_EMPTY_4_1[15..8] - (RO) Empty flag for STA 136~143 AC3 queue +* AC3_QUEUE_EMPTY_4_2[31..16] - (RO) Empty flag for STA 144~159 AC3 queue +*/ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY4_AC3_QUEUE_EMPTY_4_2_ADDR \ +WF_PLE_TOP_AC3_QUEUE_EMPTY4_ADDR +#define WF_PLE_TOP_AC3_QUEUE_EMPTY4_AC3_QUEUE_EMPTY_4_2_MASK \ +0xFFFF0000 /* AC3_QUEUE_EMPTY_4_2[31..16] */ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY4_AC3_QUEUE_EMPTY_4_2_SHFT 16 +#define WF_PLE_TOP_AC3_QUEUE_EMPTY4_AC3_QUEUE_EMPTY_4_1_ADDR \ +WF_PLE_TOP_AC3_QUEUE_EMPTY4_ADDR +#define WF_PLE_TOP_AC3_QUEUE_EMPTY4_AC3_QUEUE_EMPTY_4_1_MASK \ +0x0000FF00 /* AC3_QUEUE_EMPTY_4_1[15..8] */ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY4_AC3_QUEUE_EMPTY_4_1_SHFT 8 +#define WF_PLE_TOP_AC3_QUEUE_EMPTY4_AC3_QUEUE_EMPTY_4_0_ADDR \ +WF_PLE_TOP_AC3_QUEUE_EMPTY4_ADDR +#define WF_PLE_TOP_AC3_QUEUE_EMPTY4_AC3_QUEUE_EMPTY_4_0_MASK \ +0x000000FF /* AC3_QUEUE_EMPTY_4_0[7..0] */ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY4_AC3_QUEUE_EMPTY_4_0_SHFT 0 + +/* +* ---AC3_QUEUE_EMPTY5 (0x820C0000 + 0x5d4)--- +* AC3_QUEUE_EMPTY_5[31..0] - (RO) Empty flag for STA 160~191 AC3 queue +*/ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY5_AC3_QUEUE_EMPTY_5_ADDR \ +WF_PLE_TOP_AC3_QUEUE_EMPTY5_ADDR +#define WF_PLE_TOP_AC3_QUEUE_EMPTY5_AC3_QUEUE_EMPTY_5_MASK \ +0xFFFFFFFF /* AC3_QUEUE_EMPTY_5[31..0] */ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY5_AC3_QUEUE_EMPTY_5_SHFT 0 + +/* +* ---AC3_QUEUE_EMPTY6 (0x820C0000 + 0x5d8)--- +* AC3_QUEUE_EMPTY_6[31..0] - (RO) Empty flag for STA 192~223 AC3 queue +*/ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY6_AC3_QUEUE_EMPTY_6_ADDR \ +WF_PLE_TOP_AC3_QUEUE_EMPTY6_ADDR +#define WF_PLE_TOP_AC3_QUEUE_EMPTY6_AC3_QUEUE_EMPTY_6_MASK \ +0xFFFFFFFF /* AC3_QUEUE_EMPTY_6[31..0] */ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY6_AC3_QUEUE_EMPTY_6_SHFT 0 + +/* +* ---AC3_QUEUE_EMPTY7 (0x820C0000 + 0x5dc)--- +* AC3_QUEUE_EMPTY_7[31..0] - (RO) Empty flag for STA 224~255 AC3 queue +*/ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY7_AC3_QUEUE_EMPTY_7_ADDR \ +WF_PLE_TOP_AC3_QUEUE_EMPTY7_ADDR +#define WF_PLE_TOP_AC3_QUEUE_EMPTY7_AC3_QUEUE_EMPTY_7_MASK \ +0xFFFFFFFF /* AC3_QUEUE_EMPTY_7[31..0] */ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY7_AC3_QUEUE_EMPTY_7_SHFT 0 + +/* +* ---AC3_QUEUE_EMPTY8 (0x820C0000 + 0x5e0)--- +* AC3_QUEUE_EMPTY_8[31..0] - (RO) Empty flag for STA 256~287 AC3 queue +*/ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY8_AC3_QUEUE_EMPTY_8_ADDR \ +WF_PLE_TOP_AC3_QUEUE_EMPTY8_ADDR +#define WF_PLE_TOP_AC3_QUEUE_EMPTY8_AC3_QUEUE_EMPTY_8_MASK \ +0xFFFFFFFF /* AC3_QUEUE_EMPTY_8[31..0] */ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY8_AC3_QUEUE_EMPTY_8_SHFT 0 + +/* +* ---DRR_TABLE_WDATA4 (0x820C0000 + 0x680)--- +* DRR_TABLE_WDATA[31..0] - (RW) DRRwdata[159:128] for reading/writing +* DRR table +* Mode 0x4?: BSS mode +* See SRAM layout. +*/ +#define WF_PLE_TOP_DRR_TABLE_WDATA4_DRR_TABLE_WDATA_ADDR \ +WF_PLE_TOP_DRR_TABLE_WDATA4_ADDR +#define WF_PLE_TOP_DRR_TABLE_WDATA4_DRR_TABLE_WDATA_MASK \ +0xFFFFFFFF /* DRR_TABLE_WDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_WDATA4_DRR_TABLE_WDATA_SHFT 0 + +/* +* ---DRR_TABLE_WDATA5 (0x820C0000 + 0x684)--- +* DRR_TABLE_WDATA[31..0] - (RW) DRR wdata[191:160] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_WDATA5_DRR_TABLE_WDATA_ADDR \ +WF_PLE_TOP_DRR_TABLE_WDATA5_ADDR +#define WF_PLE_TOP_DRR_TABLE_WDATA5_DRR_TABLE_WDATA_MASK \ +0xFFFFFFFF /* DRR_TABLE_WDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_WDATA5_DRR_TABLE_WDATA_SHFT 0 + +/* +* ---DRR_TABLE_WDATA6 (0x820C0000 + 0x688)--- +* DRR_TABLE_WDATA[31..0] - (RW) DRR wdata[223:192] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_WDATA6_DRR_TABLE_WDATA_ADDR \ +WF_PLE_TOP_DRR_TABLE_WDATA6_ADDR +#define WF_PLE_TOP_DRR_TABLE_WDATA6_DRR_TABLE_WDATA_MASK \ +0xFFFFFFFF /* DRR_TABLE_WDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_WDATA6_DRR_TABLE_WDATA_SHFT 0 + +/* +* ---DRR_TABLE_WDATA7 (0x820C0000 + 0x68c)--- +* DRR_TABLE_WDATA[31..0] - (RW) DRR wdata[255:224] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_WDATA7_DRR_TABLE_WDATA_ADDR \ +WF_PLE_TOP_DRR_TABLE_WDATA7_ADDR +#define WF_PLE_TOP_DRR_TABLE_WDATA7_DRR_TABLE_WDATA_MASK \ +0xFFFFFFFF /* DRR_TABLE_WDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_WDATA7_DRR_TABLE_WDATA_SHFT 0 + +/* +* ---DRR_TABLE_RDATA4 (0x820C0000 + 0x690)--- +* DRR_TABLE_RDATA[31..0] - (RW) DRR rdata[159:128] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_RDATA4_DRR_TABLE_RDATA_ADDR \ +WF_PLE_TOP_DRR_TABLE_RDATA4_ADDR +#define WF_PLE_TOP_DRR_TABLE_RDATA4_DRR_TABLE_RDATA_MASK \ +0xFFFFFFFF /* DRR_TABLE_RDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_RDATA4_DRR_TABLE_RDATA_SHFT 0 + +/* +* ---DRR_TABLE_RDATA5 (0x820C0000 + 0x694)--- +* DRR_TABLE_RDATA[31..0] - (RW) DRR rdata[191:160] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_RDATA5_DRR_TABLE_RDATA_ADDR \ +WF_PLE_TOP_DRR_TABLE_RDATA5_ADDR +#define WF_PLE_TOP_DRR_TABLE_RDATA5_DRR_TABLE_RDATA_MASK \ +0xFFFFFFFF /* DRR_TABLE_RDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_RDATA5_DRR_TABLE_RDATA_SHFT 0 + +/* +* ---DRR_TABLE_RDATA6 (0x820C0000 + 0x698)--- +* DRR_TABLE_RDATA[31..0] - (RW) DRR rdata[223:192] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_RDATA6_DRR_TABLE_RDATA_ADDR \ +WF_PLE_TOP_DRR_TABLE_RDATA6_ADDR +#define WF_PLE_TOP_DRR_TABLE_RDATA6_DRR_TABLE_RDATA_MASK \ +0xFFFFFFFF /* DRR_TABLE_RDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_RDATA6_DRR_TABLE_RDATA_SHFT 0 + +/* +* ---DRR_TABLE_RDATA7 (0x820C0000 + 0x69c)--- +* DRR_TABLE_RDATA[31..0] - (RW) DRR rdata[255:224] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_RDATA7_DRR_TABLE_RDATA_ADDR \ +WF_PLE_TOP_DRR_TABLE_RDATA7_ADDR +#define WF_PLE_TOP_DRR_TABLE_RDATA7_DRR_TABLE_RDATA_MASK \ +0xFFFFFFFF /* DRR_TABLE_RDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_RDATA7_DRR_TABLE_RDATA_SHFT 0 + +/* +* ---TWT_STA_TABLE0 (0x820C0000 + 0x6a0)--- +* TWT_STA_0[9..0] - (RW) TWT station 0 WLAN ID +* RESERVED10[15..10] - (RO) Reserved bits +* TWT_STA_1[25..16] - (RW) TWT station 1 WLAN ID +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TWT_STA_TABLE0_TWT_STA_1_ADDR WF_PLE_TOP_TWT_STA_TABLE0_ADDR +#define WF_PLE_TOP_TWT_STA_TABLE0_TWT_STA_1_MASK \ +0x03FF0000 /* TWT_STA_1[25..16] */ +#define WF_PLE_TOP_TWT_STA_TABLE0_TWT_STA_1_SHFT 16 +#define WF_PLE_TOP_TWT_STA_TABLE0_TWT_STA_0_ADDR WF_PLE_TOP_TWT_STA_TABLE0_ADDR +#define WF_PLE_TOP_TWT_STA_TABLE0_TWT_STA_0_MASK \ +0x000003FF /* TWT_STA_0[9..0] */ +#define WF_PLE_TOP_TWT_STA_TABLE0_TWT_STA_0_SHFT 0 + +/* +* ---TWT_STA_TABLE1 (0x820C0000 + 0x6a4)--- +* TWT_STA_2[9..0] - (RW) TWT station 2 WLAN ID +* RESERVED10[15..10] - (RO) Reserved bits +* TWT_STA_3[25..16] - (RW) TWT station 3 WLAN ID +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TWT_STA_TABLE1_TWT_STA_3_ADDR WF_PLE_TOP_TWT_STA_TABLE1_ADDR +#define WF_PLE_TOP_TWT_STA_TABLE1_TWT_STA_3_MASK \ +0x03FF0000 /* TWT_STA_3[25..16] */ +#define WF_PLE_TOP_TWT_STA_TABLE1_TWT_STA_3_SHFT 16 +#define WF_PLE_TOP_TWT_STA_TABLE1_TWT_STA_2_ADDR WF_PLE_TOP_TWT_STA_TABLE1_ADDR +#define WF_PLE_TOP_TWT_STA_TABLE1_TWT_STA_2_MASK \ +0x000003FF /* TWT_STA_2[9..0] */ +#define WF_PLE_TOP_TWT_STA_TABLE1_TWT_STA_2_SHFT 0 + +/* +* ---TWT_STA_TABLE2 (0x820C0000 + 0x6a8)--- +* TWT_STA_4[9..0] - (RW) TWT station 4 WLAN ID +* RESERVED10[15..10] - (RO) Reserved bits +* TWT_STA_5[25..16] - (RW) TWT station 5 WLAN ID +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TWT_STA_TABLE2_TWT_STA_5_ADDR WF_PLE_TOP_TWT_STA_TABLE2_ADDR +#define WF_PLE_TOP_TWT_STA_TABLE2_TWT_STA_5_MASK \ +0x03FF0000 /* TWT_STA_5[25..16] */ +#define WF_PLE_TOP_TWT_STA_TABLE2_TWT_STA_5_SHFT 16 +#define WF_PLE_TOP_TWT_STA_TABLE2_TWT_STA_4_ADDR WF_PLE_TOP_TWT_STA_TABLE2_ADDR +#define WF_PLE_TOP_TWT_STA_TABLE2_TWT_STA_4_MASK \ +0x000003FF /* TWT_STA_4[9..0] */ +#define WF_PLE_TOP_TWT_STA_TABLE2_TWT_STA_4_SHFT 0 + +/* +* ---TWT_STA_TABLE3 (0x820C0000 + 0x6ac)--- +* TWT_STA_6[9..0] - (RW) TWT station 6 WLAN ID +* RESERVED10[15..10] - (RO) Reserved bits +* TWT_STA_7[25..16] - (RW) TWT station 7 WLAN ID +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TWT_STA_TABLE3_TWT_STA_7_ADDR WF_PLE_TOP_TWT_STA_TABLE3_ADDR +#define WF_PLE_TOP_TWT_STA_TABLE3_TWT_STA_7_MASK \ +0x03FF0000 /* TWT_STA_7[25..16] */ +#define WF_PLE_TOP_TWT_STA_TABLE3_TWT_STA_7_SHFT 16 +#define WF_PLE_TOP_TWT_STA_TABLE3_TWT_STA_6_ADDR WF_PLE_TOP_TWT_STA_TABLE3_ADDR +#define WF_PLE_TOP_TWT_STA_TABLE3_TWT_STA_6_MASK \ +0x000003FF /* TWT_STA_6[9..0] */ +#define WF_PLE_TOP_TWT_STA_TABLE3_TWT_STA_6_SHFT 0 + +/* +* ---TWT_SW_CTRL (0x820C0000 + 0x6b0)--- +* INDEX[15..0] - (RW) Operation index +* Mode 0x00/0x01/0x08/0x09: Bit[3:0]: station +number +* Mode 0x10/0x11: Bit[3:0]: table index +* MODE[23..16] - (RW) IO software command mode +* RESERVED24[29..24] - (RO) Reserved bits +* SRCH_CMD_DROP[30] - (W1C) IO search command drop flag due to +* command FIFO full +* EXECUTE[31] - (RW) Executes SW command to trigger TWT +* search event and add/remove TWT station +*/ +#define WF_PLE_TOP_TWT_SW_CTRL_EXECUTE_ADDR WF_PLE_TOP_TWT_SW_CTRL_ADDR +#define WF_PLE_TOP_TWT_SW_CTRL_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_TWT_SW_CTRL_EXECUTE_SHFT 31 +#define WF_PLE_TOP_TWT_SW_CTRL_SRCH_CMD_DROP_ADDR WF_PLE_TOP_TWT_SW_CTRL_ADDR +#define WF_PLE_TOP_TWT_SW_CTRL_SRCH_CMD_DROP_MASK \ +0x40000000 /* SRCH_CMD_DROP[30] */ +#define WF_PLE_TOP_TWT_SW_CTRL_SRCH_CMD_DROP_SHFT 30 +#define WF_PLE_TOP_TWT_SW_CTRL_MODE_ADDR WF_PLE_TOP_TWT_SW_CTRL_ADDR +#define WF_PLE_TOP_TWT_SW_CTRL_MODE_MASK 0x00FF0000 /* MODE[23..16] */ +#define WF_PLE_TOP_TWT_SW_CTRL_MODE_SHFT 16 +#define WF_PLE_TOP_TWT_SW_CTRL_INDEX_ADDR WF_PLE_TOP_TWT_SW_CTRL_ADDR +#define WF_PLE_TOP_TWT_SW_CTRL_INDEX_MASK 0x0000FFFF /* INDEX[15..0] */ +#define WF_PLE_TOP_TWT_SW_CTRL_INDEX_SHFT 0 + +/* +* ---TWT_DBG (0x820C0000 + 0x6b4)--- +* TABLE_IDX_SEL[2..0] - (RW) Station index selection +* UL_TABLE_SEL[3] - (RW) Downlink/uplink station table selection +* RESERVED4[15..4] - (RO) Reserved bits +* TABLE_WLAN_ID[25..16] - (RO) Station WLAN ID in station table +* RESERVED26[27..26] - (RO) Reserved bits +* STA_CNT[31..28] - (RO) Valid station count in station table +*/ +#define WF_PLE_TOP_TWT_DBG_STA_CNT_ADDR WF_PLE_TOP_TWT_DBG_ADDR +#define WF_PLE_TOP_TWT_DBG_STA_CNT_MASK 0xF0000000 /* STA_CNT[31..28] */ +#define WF_PLE_TOP_TWT_DBG_STA_CNT_SHFT 28 +#define WF_PLE_TOP_TWT_DBG_TABLE_WLAN_ID_ADDR WF_PLE_TOP_TWT_DBG_ADDR +#define WF_PLE_TOP_TWT_DBG_TABLE_WLAN_ID_MASK \ +0x03FF0000 /* TABLE_WLAN_ID[25..16] */ +#define WF_PLE_TOP_TWT_DBG_TABLE_WLAN_ID_SHFT 16 +#define WF_PLE_TOP_TWT_DBG_UL_TABLE_SEL_ADDR WF_PLE_TOP_TWT_DBG_ADDR +#define WF_PLE_TOP_TWT_DBG_UL_TABLE_SEL_MASK 0x00000008 /* UL_TABLE_SEL[3] */ +#define WF_PLE_TOP_TWT_DBG_UL_TABLE_SEL_SHFT 3 +#define WF_PLE_TOP_TWT_DBG_TABLE_IDX_SEL_ADDR WF_PLE_TOP_TWT_DBG_ADDR +#define WF_PLE_TOP_TWT_DBG_TABLE_IDX_SEL_MASK \ +0x00000007 /* TABLE_IDX_SEL[2..0] */ +#define WF_PLE_TOP_TWT_DBG_TABLE_IDX_SEL_SHFT 0 + +/* +* ---TWT_HW_SRCHCMD_FULL (0x820C0000 + 0x6b8)--- +* TWT_SRCH_DL_FULL[0] - (RW) TWT hardware downlink search command +* full flag +* TWT_SRCH_UL_FULL[1] - (RW) TWT hardware uplink search command full +flag +* RESERVED2[31..2] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TWT_HW_SRCHCMD_FULL_TWT_SRCH_UL_FULL_ADDR \ +WF_PLE_TOP_TWT_HW_SRCHCMD_FULL_ADDR +#define WF_PLE_TOP_TWT_HW_SRCHCMD_FULL_TWT_SRCH_UL_FULL_MASK \ +0x00000002 /* TWT_SRCH_UL_FULL[1] */ +#define WF_PLE_TOP_TWT_HW_SRCHCMD_FULL_TWT_SRCH_UL_FULL_SHFT 1 +#define WF_PLE_TOP_TWT_HW_SRCHCMD_FULL_TWT_SRCH_DL_FULL_ADDR \ +WF_PLE_TOP_TWT_HW_SRCHCMD_FULL_ADDR +#define WF_PLE_TOP_TWT_HW_SRCHCMD_FULL_TWT_SRCH_DL_FULL_MASK \ +0x00000001 /* TWT_SRCH_DL_FULL[0] */ +#define WF_PLE_TOP_TWT_HW_SRCHCMD_FULL_TWT_SRCH_DL_FULL_SHFT 0 + +/* +* ---SPL_GEN_CTRL (0x820C0000 + 0x700)--- +* EN_PLE_SPL[0] - (RW) Enable control of PLE generate SPL +* report function. +* RESERVED1[7..1] - (RO) Reserved bits +* RPT_TWT_IN_AC_SPL[8] - (RW) Enable control of TWT station in WMMAC +* SPL report. +* RESERVED9[31..9] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SPL_GEN_CTRL_RPT_TWT_IN_AC_SPL_ADDR \ +WF_PLE_TOP_SPL_GEN_CTRL_ADDR +#define WF_PLE_TOP_SPL_GEN_CTRL_RPT_TWT_IN_AC_SPL_MASK \ +0x00000100 /* RPT_TWT_IN_AC_SPL[8] */ +#define WF_PLE_TOP_SPL_GEN_CTRL_RPT_TWT_IN_AC_SPL_SHFT 8 +#define WF_PLE_TOP_SPL_GEN_CTRL_EN_PLE_SPL_ADDR WF_PLE_TOP_SPL_GEN_CTRL_ADDR +#define WF_PLE_TOP_SPL_GEN_CTRL_EN_PLE_SPL_MASK 0x00000001 /* EN_PLE_SPL[0] */ +#define WF_PLE_TOP_SPL_GEN_CTRL_EN_PLE_SPL_SHFT 0 + +/* +* ---AMSDU_GC (0x820C0000 + 0x1000)--- +* EN_HW_AMSDU[0] - (RW) Enable control of HW AMSDU function. +* RESERVED1[7..1] - (RO) Reserved bits +* DIS_AMSDU_Q_EMPTY_FLUSH[8] - (RW) Disable control of HW AMSDU queue empty +* trigger packet flush function. +* DIS_LMAC_TX_NO_FULL_FLUSH[9] - (RW) Disable control of LMAC TX no get full +* packet trigger packet flush function. +* DIS_SFD_KEEP_SAME_PAGE[10] - (RW) Disable control of keep same page number +* of StoreForward packet function. +* RESERVED11[31..11] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_GC_DIS_SFD_KEEP_SAME_PAGE_ADDR WF_PLE_TOP_AMSDU_GC_ADDR +#define WF_PLE_TOP_AMSDU_GC_DIS_SFD_KEEP_SAME_PAGE_MASK \ +0x00000400 /* DIS_SFD_KEEP_SAME_PAGE[10] */ +#define WF_PLE_TOP_AMSDU_GC_DIS_SFD_KEEP_SAME_PAGE_SHFT 10 +#define WF_PLE_TOP_AMSDU_GC_DIS_LMAC_TX_NO_FULL_FLUSH_ADDR \ +WF_PLE_TOP_AMSDU_GC_ADDR +#define WF_PLE_TOP_AMSDU_GC_DIS_LMAC_TX_NO_FULL_FLUSH_MASK \ +0x00000200 /* DIS_LMAC_TX_NO_FULL_FLUSH[9] */ +#define WF_PLE_TOP_AMSDU_GC_DIS_LMAC_TX_NO_FULL_FLUSH_SHFT 9 +#define WF_PLE_TOP_AMSDU_GC_DIS_AMSDU_Q_EMPTY_FLUSH_ADDR \ +WF_PLE_TOP_AMSDU_GC_ADDR +#define WF_PLE_TOP_AMSDU_GC_DIS_AMSDU_Q_EMPTY_FLUSH_MASK \ +0x00000100 /* DIS_AMSDU_Q_EMPTY_FLUSH[8] */ +#define WF_PLE_TOP_AMSDU_GC_DIS_AMSDU_Q_EMPTY_FLUSH_SHFT 8 +#define WF_PLE_TOP_AMSDU_GC_EN_HW_AMSDU_ADDR WF_PLE_TOP_AMSDU_GC_ADDR +#define WF_PLE_TOP_AMSDU_GC_EN_HW_AMSDU_MASK 0x00000001 /* EN_HW_AMSDU[0] */ +#define WF_PLE_TOP_AMSDU_GC_EN_HW_AMSDU_SHFT 0 + +/* +* ---AMSDU_TXD_COMP_MAP_0 (0x820C0000 + 0x1004)--- +* TXDIN_TRIGGER_TH[11..0] - (RW) The TXD merge trigger threshold. +* RESERVED12[15..12] - (RO) Reserved bits +* TXD_COMPARE_NEED_MAP[31..16] - (RW) The compare bitmap for merging TXD. +*/ +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_TXD_COMPARE_NEED_MAP_ADDR \ +WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_ADDR +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_TXD_COMPARE_NEED_MAP_MASK \ +0xFFFF0000 /* TXD_COMPARE_NEED_MAP[31..16] */ +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_TXD_COMPARE_NEED_MAP_SHFT 16 +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_TXDIN_TRIGGER_TH_ADDR \ +WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_ADDR +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_TXDIN_TRIGGER_TH_MASK \ +0x00000FFF /* TXDIN_TRIGGER_TH[11..0] */ +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_TXDIN_TRIGGER_TH_SHFT 0 + +/* +* ---AMSDU_TXD_COMP_MAP_1 (0x820C0000 + 0x1008)--- +* TXD_COMPARE_NEED_MAP[31..0] - (RW) The compare bitmap for merging TXD. +*/ +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_1_TXD_COMPARE_NEED_MAP_ADDR \ +WF_PLE_TOP_AMSDU_TXD_COMP_MAP_1_ADDR +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_1_TXD_COMPARE_NEED_MAP_MASK \ +0xFFFFFFFF /* TXD_COMPARE_NEED_MAP[31..0] */ +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_1_TXD_COMPARE_NEED_MAP_SHFT 0 + +/* +* ---AMSDU_INT_N9_ERR_STS (0x820C0000 + 0x1028)--- +* AMSDU_Q_CMD_ERR[0] - (W1C) Queue command error interrupt status of +* port AMSDU. Avoid unclear error flag, please clear flag when logic reset. +* RESERVED1[3..1] - (RO) Reserved bits +* AMSDU_PAGE_UDF[4] - (W1C) Page underflow interrupt status of port +* AMSDU. Avoid unclear error flag, please clear flag when logic reset. +* RESERVED5[11..5] - (RO) Reserved bits +* AMSDU_DATA_OPER_ERR[12] - (W1C) Data operation error of port AMSDU. +* Avoid unclear error flag, please clear flag when logic reset. +* RESERVED13[15..13] - (RO) Reserved bits +* AMSDU_PORT_HANG_ERR[16] - (W1C) AMSDU port FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* AMSDU_CTRL_HANG_ERR[17] - (W1C) AMSDU FSM hang error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* RESERVED18[31..18] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_CTRL_HANG_ERR_ADDR \ +WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_CTRL_HANG_ERR_MASK \ +0x00020000 /* AMSDU_CTRL_HANG_ERR[17] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_CTRL_HANG_ERR_SHFT 17 +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_PORT_HANG_ERR_ADDR \ +WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_PORT_HANG_ERR_MASK \ +0x00010000 /* AMSDU_PORT_HANG_ERR[16] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_PORT_HANG_ERR_SHFT 16 +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_DATA_OPER_ERR_ADDR \ +WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_DATA_OPER_ERR_MASK \ +0x00001000 /* AMSDU_DATA_OPER_ERR[12] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_DATA_OPER_ERR_SHFT 12 +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_PAGE_UDF_ADDR \ +WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_PAGE_UDF_MASK \ +0x00000010 /* AMSDU_PAGE_UDF[4] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_PAGE_UDF_SHFT 4 +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_Q_CMD_ERR_ADDR \ +WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_Q_CMD_ERR_MASK \ +0x00000001 /* AMSDU_Q_CMD_ERR[0] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_Q_CMD_ERR_SHFT 0 + +/* +* ---AMSDU_INT_N9_ERR_MASK (0x820C0000 + 0x102C)--- +* EN_AMSDU_Q_CMD_ERR[0] - (RW) Enables queue command error interrupt +* status of port AMSDU +* RESERVED1[3..1] - (RO) Reserved bits +* EN_AMSDU_PAGE_UDF[4] - (RW) Enables page underflow interrupt status +* of port AMSDU +* RESERVED5[11..5] - (RO) Reserved bits +* EN_AMSDU_DATA_OPER_ERR[12] - (RW) Enables data operation error of port +AMSDU +* RESERVED13[15..13] - (RO) Reserved bits +* EN_AMSDU_PORT_HANG_ERR[16] - (RW) Enables AMSDU port FSM hang error +interrupt +* EN_AMSDU_CTRL_HANG_ERR[17] - (RW) Enables AMSDU CTRL FSM hang error +interrupt +* RESERVED18[31..18] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_CTRL_HANG_ERR_ADDR \ +WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_CTRL_HANG_ERR_MASK \ +0x00020000 /* EN_AMSDU_CTRL_HANG_ERR[17] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_CTRL_HANG_ERR_SHFT 17 +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_PORT_HANG_ERR_ADDR \ +WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_PORT_HANG_ERR_MASK \ +0x00010000 /* EN_AMSDU_PORT_HANG_ERR[16] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_PORT_HANG_ERR_SHFT 16 +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_DATA_OPER_ERR_ADDR \ +WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_DATA_OPER_ERR_MASK \ +0x00001000 /* EN_AMSDU_DATA_OPER_ERR[12] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_DATA_OPER_ERR_SHFT 12 +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_PAGE_UDF_ADDR \ +WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_PAGE_UDF_MASK \ +0x00000010 /* EN_AMSDU_PAGE_UDF[4] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_PAGE_UDF_SHFT 4 +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_Q_CMD_ERR_ADDR \ +WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_Q_CMD_ERR_MASK \ +0x00000001 /* EN_AMSDU_Q_CMD_ERR[0] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_Q_CMD_ERR_SHFT 0 + +/* +* ---AMSDU_PEEK_CR_00 (0x820C0000 + 0x10d0)--- +* AMSDU_DOP_CS[3..0] - (RO) AMSDU Data operation current state. +* RESERVED4[7..4] - (RO) Reserved bits +* AMSDU_CS[12..8] - (RO) AMSDU Merge Engine current state. +* RESERVED13[15..13] - (RO) Reserved bits +* AMSDU_Q_EMPTY_CS[17..16] - (RO) AMSDU Queue Empty Search Engine current +state. +* RESERVED18[23..18] - (RO) Reserved bits +* AMSDU_ARB_CS[26..24] - (RO) AMSDU Request Arbitration Current state. +* RESERVED27[31..27] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_ARB_CS_ADDR \ +WF_PLE_TOP_AMSDU_PEEK_CR_00_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_ARB_CS_MASK \ +0x07000000 /* AMSDU_ARB_CS[26..24] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_ARB_CS_SHFT 24 +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_Q_EMPTY_CS_ADDR \ +WF_PLE_TOP_AMSDU_PEEK_CR_00_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_Q_EMPTY_CS_MASK \ +0x00030000 /* AMSDU_Q_EMPTY_CS[17..16] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_Q_EMPTY_CS_SHFT 16 +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_CS_ADDR \ +WF_PLE_TOP_AMSDU_PEEK_CR_00_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_CS_MASK \ +0x00001F00 /* AMSDU_CS[12..8] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_CS_SHFT 8 +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_DOP_CS_ADDR \ +WF_PLE_TOP_AMSDU_PEEK_CR_00_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_DOP_CS_MASK \ +0x0000000F /* AMSDU_DOP_CS[3..0] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_DOP_CS_SHFT 0 + +/* +* ---AMSDU_PEEK_CR_01 (0x820C0000 + 0x10d4)--- +* AMSDU_DOP_PBUF_CS[2..0] - (RO) PLE AMSDU port - Data operation PBUF +* current state. +* RESERVED3[3] - (RO) Reserved bits +* AMSDU_DOP_CACHE_CS[5..4] - (RO) PLE AMSDU port - Data operation CACHE +* current state. +* RESERVED6[7..6] - (RO) Reserved bits +* AMSDU_QOP_Q_OPER_CS[11..8] - (RO) PLE AMSDU port - Queue operation current +state. +* AMSDU_QOP_RL_OCP_CS[13..12] - (RO) PLE AMSDU port - Queue operation RL +* current state. +* RESERVED14[15..14] - (RO) Reserved bits +* AMSDU_QOP_PL_OCP_CS[17..16] - (RO) PLE AMSDU port - Queue operation PL +* current state. +* RESERVED18[19..18] - (RO) Reserved bits +* AMSDU_QOP_ALLOCATE_CS[22..20] - (RO) PLE AMSDU port - Queue operation +* allocate current state. +* RESERVED23[31..23] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_ALLOCATE_CS_ADDR \ +WF_PLE_TOP_AMSDU_PEEK_CR_01_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_ALLOCATE_CS_MASK \ +0x00700000 /* AMSDU_QOP_ALLOCATE_CS[22..20] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_ALLOCATE_CS_SHFT 20 +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_PL_OCP_CS_ADDR \ +WF_PLE_TOP_AMSDU_PEEK_CR_01_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_PL_OCP_CS_MASK \ +0x00030000 /* AMSDU_QOP_PL_OCP_CS[17..16] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_PL_OCP_CS_SHFT 16 +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_RL_OCP_CS_ADDR \ +WF_PLE_TOP_AMSDU_PEEK_CR_01_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_RL_OCP_CS_MASK \ +0x00003000 /* AMSDU_QOP_RL_OCP_CS[13..12] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_RL_OCP_CS_SHFT 12 +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_Q_OPER_CS_ADDR \ +WF_PLE_TOP_AMSDU_PEEK_CR_01_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_Q_OPER_CS_MASK \ +0x00000F00 /* AMSDU_QOP_Q_OPER_CS[11..8] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_Q_OPER_CS_SHFT 8 +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_DOP_CACHE_CS_ADDR \ +WF_PLE_TOP_AMSDU_PEEK_CR_01_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_DOP_CACHE_CS_MASK \ +0x00000030 /* AMSDU_DOP_CACHE_CS[5..4] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_DOP_CACHE_CS_SHFT 4 +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_DOP_PBUF_CS_ADDR \ +WF_PLE_TOP_AMSDU_PEEK_CR_01_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_DOP_PBUF_CS_MASK \ +0x00000007 /* AMSDU_DOP_PBUF_CS[2..0] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_DOP_PBUF_CS_SHFT 0 + +/* +* ---AMSDU_PACK_1_MSDU_CNT (0x820C0000 + 0x10e0)--- +* pack_1_msdu_cnt[15..0] - (RC) AMSDU pack count of 1 MSDU in TXD. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PACK_1_MSDU_CNT_pack_1_msdu_cnt_ADDR \ +WF_PLE_TOP_AMSDU_PACK_1_MSDU_CNT_ADDR +#define WF_PLE_TOP_AMSDU_PACK_1_MSDU_CNT_pack_1_msdu_cnt_MASK \ +0x0000FFFF /* pack_1_msdu_cnt[15..0] */ +#define WF_PLE_TOP_AMSDU_PACK_1_MSDU_CNT_pack_1_msdu_cnt_SHFT 0 + +/* +* ---AMSDU_PACK_2_MSDU_CNT (0x820C0000 + 0x10e4)--- +* pack_2_msdu_cnt[15..0] - (RC) AMSDU pack count of 2 MSDU in TXD. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PACK_2_MSDU_CNT_pack_2_msdu_cnt_ADDR \ +WF_PLE_TOP_AMSDU_PACK_2_MSDU_CNT_ADDR +#define WF_PLE_TOP_AMSDU_PACK_2_MSDU_CNT_pack_2_msdu_cnt_MASK \ +0x0000FFFF /* pack_2_msdu_cnt[15..0] */ +#define WF_PLE_TOP_AMSDU_PACK_2_MSDU_CNT_pack_2_msdu_cnt_SHFT 0 + +/* +* ---AMSDU_PACK_3_MSDU_CNT (0x820C0000 + 0x10e8)--- +* pack_3_msdu_cnt[15..0] - (RC) AMSDU pack count of 3 MSDU in TXD. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PACK_3_MSDU_CNT_pack_3_msdu_cnt_ADDR \ +WF_PLE_TOP_AMSDU_PACK_3_MSDU_CNT_ADDR +#define WF_PLE_TOP_AMSDU_PACK_3_MSDU_CNT_pack_3_msdu_cnt_MASK \ +0x0000FFFF /* pack_3_msdu_cnt[15..0] */ +#define WF_PLE_TOP_AMSDU_PACK_3_MSDU_CNT_pack_3_msdu_cnt_SHFT 0 + +/* +* ---AMSDU_PACK_4_MSDU_CNT (0x820C0000 + 0x10ec)--- +* pack_4_msdu_cnt[15..0] - (RC) AMSDU pack count of 4 MSDU in TXD. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PACK_4_MSDU_CNT_pack_4_msdu_cnt_ADDR \ +WF_PLE_TOP_AMSDU_PACK_4_MSDU_CNT_ADDR +#define WF_PLE_TOP_AMSDU_PACK_4_MSDU_CNT_pack_4_msdu_cnt_MASK \ +0x0000FFFF /* pack_4_msdu_cnt[15..0] */ +#define WF_PLE_TOP_AMSDU_PACK_4_MSDU_CNT_pack_4_msdu_cnt_SHFT 0 + +/* +* ---AMSDU_PACK_5_MSDU_CNT (0x820C0000 + 0x10f0)--- +* pack_5_msdu_cnt[15..0] - (RC) AMSDU pack count of 5 MSDU in TXD. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PACK_5_MSDU_CNT_pack_5_msdu_cnt_ADDR \ +WF_PLE_TOP_AMSDU_PACK_5_MSDU_CNT_ADDR +#define WF_PLE_TOP_AMSDU_PACK_5_MSDU_CNT_pack_5_msdu_cnt_MASK \ +0x0000FFFF /* pack_5_msdu_cnt[15..0] */ +#define WF_PLE_TOP_AMSDU_PACK_5_MSDU_CNT_pack_5_msdu_cnt_SHFT 0 + +/* +* ---AMSDU_PACK_6_MSDU_CNT (0x820C0000 + 0x10f4)--- +* pack_6_msdu_cnt[15..0] - (RC) AMSDU pack count of 4 MSDU in TXD. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PACK_6_MSDU_CNT_pack_6_msdu_cnt_ADDR \ +WF_PLE_TOP_AMSDU_PACK_6_MSDU_CNT_ADDR +#define WF_PLE_TOP_AMSDU_PACK_6_MSDU_CNT_pack_6_msdu_cnt_MASK \ +0x0000FFFF /* pack_6_msdu_cnt[15..0] */ +#define WF_PLE_TOP_AMSDU_PACK_6_MSDU_CNT_pack_6_msdu_cnt_SHFT 0 + +/* +* ---AMSDU_PACK_7_MSDU_CNT (0x820C0000 + 0x10f8)--- +* pack_7_msdu_cnt[15..0] - (RC) AMSDU pack count of 7 MSDU in TXD. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PACK_7_MSDU_CNT_pack_7_msdu_cnt_ADDR \ +WF_PLE_TOP_AMSDU_PACK_7_MSDU_CNT_ADDR +#define WF_PLE_TOP_AMSDU_PACK_7_MSDU_CNT_pack_7_msdu_cnt_MASK \ +0x0000FFFF /* pack_7_msdu_cnt[15..0] */ +#define WF_PLE_TOP_AMSDU_PACK_7_MSDU_CNT_pack_7_msdu_cnt_SHFT 0 + +/* +* ---AMSDU_PACK_8_MSDU_CNT (0x820C0000 + 0x10fc)--- +* pack_8_msdu_cnt[15..0] - (RC) AMSDU pack count of 8 MSDU in TXD. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PACK_8_MSDU_CNT_pack_8_msdu_cnt_ADDR \ +WF_PLE_TOP_AMSDU_PACK_8_MSDU_CNT_ADDR +#define WF_PLE_TOP_AMSDU_PACK_8_MSDU_CNT_pack_8_msdu_cnt_MASK \ +0x0000FFFF /* pack_8_msdu_cnt[15..0] */ +#define WF_PLE_TOP_AMSDU_PACK_8_MSDU_CNT_pack_8_msdu_cnt_SHFT 0 + +/* +* ---AMSDU_AC0_QUEUE_EMPTY0 (0x820C0000 + 0x1100)--- +* AMSDU_QUEUE_EMPTY_FLAG_31_0[31..0] - (RO) AC0 queue empty flag for +* station31~station0 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_ADDR \ +WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY0_ADDR +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_MASK \ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_31_0[31..0] */ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_SHFT 0 + +/* +* ---AMSDU_AC0_QUEUE_EMPTY1 (0x820C0000 + 0x1104)--- +* AMSDU_QUEUE_EMPTY_FLAG_63_32[31..0] - (RO) AC0 queue empty flag for +* station63~station32 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY1_AMSDU_QUEUE_EMPTY_FLAG_63_32_ADDR \ +WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY1_ADDR +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY1_AMSDU_QUEUE_EMPTY_FLAG_63_32_MASK \ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_63_32[31..0] */ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY1_AMSDU_QUEUE_EMPTY_FLAG_63_32_SHFT 0 + +/* +* ---AMSDU_AC0_QUEUE_EMPTY2 (0x820C0000 + 0x1108)--- +* AMSDU_QUEUE_EMPTY_FLAG_95_64[31..0] - (RO) AC0 queue empty flag for +* station95~station64 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY2_AMSDU_QUEUE_EMPTY_FLAG_95_64_ADDR \ +WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY2_ADDR +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY2_AMSDU_QUEUE_EMPTY_FLAG_95_64_MASK \ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_95_64[31..0] */ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY2_AMSDU_QUEUE_EMPTY_FLAG_95_64_SHFT 0 + +/* +* ---AMSDU_AC0_QUEUE_EMPTY3 (0x820C0000 + 0x110C)--- +* AMSDU_QUEUE_EMPTY_FLAG_127_96[31..0] - (RO) AC0 queue empty flag for +* station127~station96 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY3_AMSDU_QUEUE_EMPTY_FLAG_127_96_ADDR \ +WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY3_ADDR +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY3_AMSDU_QUEUE_EMPTY_FLAG_127_96_MASK \ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_127_96[31..0] */ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY3_AMSDU_QUEUE_EMPTY_FLAG_127_96_SHFT 0 + +/* +* ---AMSDU_AC0_QUEUE_EMPTY4 (0x820C0000 + 0x1110)--- +* AMSDU_QUEUE_EMPTY_FLAG_135_128[7..0] - (RO) AC0 queue empty flag for +* station135~station128 in HW AMSDU engine. +* AMSDU_QUEUE_EMPTY_FLAG_143_136[15..8] - (RO) AC0 queue empty flag for +* station143~station136 in HW AMSDU engine. +* AMSDU_QUEUE_EMPTY_FLAG_159_144[31..16] - (RO) AC0 queue empty flag for +* station159~station144 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_159_144_ADDR\ +WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY4_ADDR +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_159_144_MASK\ +0xFFFF0000 /* AMSDU_QUEUE_EMPTY_FLAG_159_144[31..16] */ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_159_144_SHFT 16 +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_143_136_ADDR\ +WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY4_ADDR +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_143_136_MASK\ +0x0000FF00 /* AMSDU_QUEUE_EMPTY_FLAG_143_136[15..8] */ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_143_136_SHFT 8 +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_135_128_ADDR\ +WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY4_ADDR +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_135_128_MASK\ +0x000000FF /* AMSDU_QUEUE_EMPTY_FLAG_135_128[7..0] */ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_135_128_SHFT 0 + +/* +* ---AMSDU_AC0_QUEUE_EMPTY5 (0x820C0000 + 0x1114)--- +* AMSDU_QUEUE_EMPTY_FLAG_191_160[31..0] - (RO) AC0 queue empty flag for +* station191~station160 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY5_AMSDU_QUEUE_EMPTY_FLAG_191_160_ADDR\ +WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY5_ADDR +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY5_AMSDU_QUEUE_EMPTY_FLAG_191_160_MASK\ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_191_160[31..0] */ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY5_AMSDU_QUEUE_EMPTY_FLAG_191_160_SHFT 0 + +/* +* ---AMSDU_AC0_QUEUE_EMPTY6 (0x820C0000 + 0x1118)--- +* AMSDU_QUEUE_EMPTY_FLAG_223_192[31..0] - (RO) AC0 queue empty flag for +* station223~station192 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY6_AMSDU_QUEUE_EMPTY_FLAG_223_192_ADDR\ +WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY6_ADDR +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY6_AMSDU_QUEUE_EMPTY_FLAG_223_192_MASK\ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_223_192[31..0] */ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY6_AMSDU_QUEUE_EMPTY_FLAG_223_192_SHFT 0 + +/* +* ---AMSDU_AC0_QUEUE_EMPTY7 (0x820C0000 + 0x111c)--- +* AMSDU_QUEUE_EMPTY_FLAG_255_224[31..0] - (RO) AC0 queue empty flag for +* station255~station224 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY7_AMSDU_QUEUE_EMPTY_FLAG_255_224_ADDR\ +WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY7_ADDR +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY7_AMSDU_QUEUE_EMPTY_FLAG_255_224_MASK\ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_255_224[31..0] */ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY7_AMSDU_QUEUE_EMPTY_FLAG_255_224_SHFT 0 + +/* +* ---AMSDU_AC0_QUEUE_EMPTY8 (0x820C0000 + 0x1120)--- +* AMSDU_QUEUE_EMPTY_FLAG_287_256[31..0] - (RO) AC0 queue empty flag for +* station287~station256 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY8_AMSDU_QUEUE_EMPTY_FLAG_287_256_ADDR\ +WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY8_ADDR +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY8_AMSDU_QUEUE_EMPTY_FLAG_287_256_MASK\ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_287_256[31..0] */ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY8_AMSDU_QUEUE_EMPTY_FLAG_287_256_SHFT 0 + +/* +* ---AMSDU_AC1_QUEUE_EMPTY0 (0x820C0000 + 0x1140)--- +* AMSDU_QUEUE_EMPTY_FLAG_31_0[31..0] - (RO) AC1 queue empty flag for +* station31~station0 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_ADDR \ +WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY0_ADDR +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_MASK \ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_31_0[31..0] */ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_SHFT 0 + +/* +* ---AMSDU_AC1_QUEUE_EMPTY1 (0x820C0000 + 0x1144)--- +* AMSDU_QUEUE_EMPTY_FLAG_63_32[31..0] - (RO) AC1 queue empty flag for +* station63~station32 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY1_AMSDU_QUEUE_EMPTY_FLAG_63_32_ADDR \ +WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY1_ADDR +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY1_AMSDU_QUEUE_EMPTY_FLAG_63_32_MASK \ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_63_32[31..0] */ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY1_AMSDU_QUEUE_EMPTY_FLAG_63_32_SHFT 0 + +/* +* ---AMSDU_AC1_QUEUE_EMPTY2 (0x820C0000 + 0x1148)--- +* AMSDU_QUEUE_EMPTY_FLAG_95_64[31..0] - (RO) AC1 queue empty flag for +* station95~station64 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY2_AMSDU_QUEUE_EMPTY_FLAG_95_64_ADDR \ +WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY2_ADDR +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY2_AMSDU_QUEUE_EMPTY_FLAG_95_64_MASK \ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_95_64[31..0] */ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY2_AMSDU_QUEUE_EMPTY_FLAG_95_64_SHFT 0 + +/* +* ---AMSDU_AC1_QUEUE_EMPTY3 (0x820C0000 + 0x114C)--- +* AMSDU_QUEUE_EMPTY_FLAG_127_96[31..0] - (RO) AC1 queue empty flag for +* station127~station96 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY3_AMSDU_QUEUE_EMPTY_FLAG_127_96_ADDR \ +WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY3_ADDR +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY3_AMSDU_QUEUE_EMPTY_FLAG_127_96_MASK \ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_127_96[31..0] */ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY3_AMSDU_QUEUE_EMPTY_FLAG_127_96_SHFT 0 + +/* +* ---AMSDU_AC1_QUEUE_EMPTY4 (0x820C0000 + 0x1150)--- +* AMSDU_QUEUE_EMPTY_FLAG_135_128[7..0] - (RO) AC1 queue empty flag for +* station135~station128 in HW AMSDU engine. +* AMSDU_QUEUE_EMPTY_FLAG_143_136[15..8] - (RO) AC1 queue empty flag for +* station143~station136 in HW AMSDU engine. +* AMSDU_QUEUE_EMPTY_FLAG_159_144[31..16] - (RO) AC1 queue empty flag for +* station159~station144 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_159_144_ADDR\ +WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY4_ADDR +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_159_144_MASK\ +0xFFFF0000 /* AMSDU_QUEUE_EMPTY_FLAG_159_144[31..16] */ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_159_144_SHFT 16 +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_143_136_ADDR\ +WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY4_ADDR +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_143_136_MASK\ +0x0000FF00 /* AMSDU_QUEUE_EMPTY_FLAG_143_136[15..8] */ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_143_136_SHFT 8 +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_135_128_ADDR\ +WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY4_ADDR +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_135_128_MASK\ +0x000000FF /* AMSDU_QUEUE_EMPTY_FLAG_135_128[7..0] */ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_135_128_SHFT 0 + +/* +* ---AMSDU_AC1_QUEUE_EMPTY5 (0x820C0000 + 0x1154)--- +* AMSDU_QUEUE_EMPTY_FLAG_191_160[31..0] - (RO) AC1 queue empty flag for +* station191~station160 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY5_AMSDU_QUEUE_EMPTY_FLAG_191_160_ADDR\ +WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY5_ADDR +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY5_AMSDU_QUEUE_EMPTY_FLAG_191_160_MASK\ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_191_160[31..0] */ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY5_AMSDU_QUEUE_EMPTY_FLAG_191_160_SHFT 0 + +/* +* ---AMSDU_AC1_QUEUE_EMPTY6 (0x820C0000 + 0x1158)--- +* AMSDU_QUEUE_EMPTY_FLAG_223_192[31..0] - (RO) AC1 queue empty flag for +* station223~station192 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY6_AMSDU_QUEUE_EMPTY_FLAG_223_192_ADDR\ +WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY6_ADDR +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY6_AMSDU_QUEUE_EMPTY_FLAG_223_192_MASK\ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_223_192[31..0] */ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY6_AMSDU_QUEUE_EMPTY_FLAG_223_192_SHFT 0 + +/* +* ---AMSDU_AC1_QUEUE_EMPTY7 (0x820C0000 + 0x115c)--- +* AMSDU_QUEUE_EMPTY_FLAG_255_224[31..0] - (RO) AC1 queue empty flag for +* station255~station224 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY7_AMSDU_QUEUE_EMPTY_FLAG_255_224_ADDR\ +WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY7_ADDR +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY7_AMSDU_QUEUE_EMPTY_FLAG_255_224_MASK\ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_255_224[31..0] */ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY7_AMSDU_QUEUE_EMPTY_FLAG_255_224_SHFT 0 + +/* +* ---AMSDU_AC1_QUEUE_EMPTY8 (0x820C0000 + 0x1160)--- +* AMSDU_QUEUE_EMPTY_FLAG_287_256[31..0] - (RO) AC1 queue empty flag for +* station287~station256 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY8_AMSDU_QUEUE_EMPTY_FLAG_287_256_ADDR\ +WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY8_ADDR +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY8_AMSDU_QUEUE_EMPTY_FLAG_287_256_MASK\ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_287_256[31..0] */ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY8_AMSDU_QUEUE_EMPTY_FLAG_287_256_SHFT 0 + +/* +* ---AMSDU_AC2_QUEUE_EMPTY0 (0x820C0000 + 0x1180)--- +* AMSDU_QUEUE_EMPTY_FLAG_31_0[31..0] - (RO) AC2 queue empty flag for +* station31~station0 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_ADDR \ +WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY0_ADDR +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_MASK \ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_31_0[31..0] */ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_SHFT 0 + +/* +* ---AMSDU_AC2_QUEUE_EMPTY1 (0x820C0000 + 0x1184)--- +* AMSDU_QUEUE_EMPTY_FLAG_63_32[31..0] - (RO) AC2 queue empty flag for +* station63~station32 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY1_AMSDU_QUEUE_EMPTY_FLAG_63_32_ADDR \ +WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY1_ADDR +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY1_AMSDU_QUEUE_EMPTY_FLAG_63_32_MASK \ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_63_32[31..0] */ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY1_AMSDU_QUEUE_EMPTY_FLAG_63_32_SHFT 0 + +/* +* ---AMSDU_AC2_QUEUE_EMPTY2 (0x820C0000 + 0x1188)--- +* AMSDU_QUEUE_EMPTY_FLAG_95_64[31..0] - (RO) AC2 queue empty flag for +* station95~station64 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY2_AMSDU_QUEUE_EMPTY_FLAG_95_64_ADDR \ +WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY2_ADDR +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY2_AMSDU_QUEUE_EMPTY_FLAG_95_64_MASK \ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_95_64[31..0] */ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY2_AMSDU_QUEUE_EMPTY_FLAG_95_64_SHFT 0 + +/* +* ---AMSDU_AC2_QUEUE_EMPTY3 (0x820C0000 + 0x118C)--- +* AMSDU_QUEUE_EMPTY_FLAG_127_96[31..0] - (RO) AC2 queue empty flag for +* station127~station96 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY3_AMSDU_QUEUE_EMPTY_FLAG_127_96_ADDR \ +WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY3_ADDR +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY3_AMSDU_QUEUE_EMPTY_FLAG_127_96_MASK \ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_127_96[31..0] */ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY3_AMSDU_QUEUE_EMPTY_FLAG_127_96_SHFT 0 + +/* +* ---AMSDU_AC2_QUEUE_EMPTY4 (0x820C0000 + 0x1190)--- +* AMSDU_QUEUE_EMPTY_FLAG_135_128[7..0] - (RO) AC2 queue empty flag for +* station135~station128 in HW AMSDU engine. +* AMSDU_QUEUE_EMPTY_FLAG_143_136[15..8] - (RO) AC2 queue empty flag for +* station143~station136 in HW AMSDU engine. +* AMSDU_QUEUE_EMPTY_FLAG_159_144[31..16] - (RO) AC2 queue empty flag for +* station159~station144 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_159_144_ADDR\ +WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY4_ADDR +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_159_144_MASK\ +0xFFFF0000 /* AMSDU_QUEUE_EMPTY_FLAG_159_144[31..16] */ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_159_144_SHFT 16 +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_143_136_ADDR\ +WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY4_ADDR +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_143_136_MASK\ +0x0000FF00 /* AMSDU_QUEUE_EMPTY_FLAG_143_136[15..8] */ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_143_136_SHFT 8 +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_135_128_ADDR\ +WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY4_ADDR +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_135_128_MASK\ +0x000000FF /* AMSDU_QUEUE_EMPTY_FLAG_135_128[7..0] */ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_135_128_SHFT 0 + +/* +* ---AMSDU_AC2_QUEUE_EMPTY5 (0x820C0000 + 0x1194)--- +* AMSDU_QUEUE_EMPTY_FLAG_191_160[31..0] - (RO) AC2 queue empty flag for +* station191~station160 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY5_AMSDU_QUEUE_EMPTY_FLAG_191_160_ADDR\ +WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY5_ADDR +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY5_AMSDU_QUEUE_EMPTY_FLAG_191_160_MASK\ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_191_160[31..0] */ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY5_AMSDU_QUEUE_EMPTY_FLAG_191_160_SHFT 0 + +/* +* ---AMSDU_AC2_QUEUE_EMPTY6 (0x820C0000 + 0x1198)--- +* AMSDU_QUEUE_EMPTY_FLAG_223_192[31..0] - (RO) AC2 queue empty flag for +* station223~station192 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY6_AMSDU_QUEUE_EMPTY_FLAG_223_192_ADDR\ +WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY6_ADDR +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY6_AMSDU_QUEUE_EMPTY_FLAG_223_192_MASK\ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_223_192[31..0] */ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY6_AMSDU_QUEUE_EMPTY_FLAG_223_192_SHFT 0 + +/* +* ---AMSDU_AC2_QUEUE_EMPTY7 (0x820C0000 + 0x119c)--- +* AMSDU_QUEUE_EMPTY_FLAG_255_224[31..0] - (RO) AC2 queue empty flag for +* station255~station224 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY7_AMSDU_QUEUE_EMPTY_FLAG_255_224_ADDR\ +WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY7_ADDR +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY7_AMSDU_QUEUE_EMPTY_FLAG_255_224_MASK\ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_255_224[31..0] */ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY7_AMSDU_QUEUE_EMPTY_FLAG_255_224_SHFT 0 + +/* +* ---AMSDU_AC2_QUEUE_EMPTY8 (0x820C0000 + 0x11a0)--- +* AMSDU_QUEUE_EMPTY_FLAG_287_256[31..0] - (RO) AC2 queue empty flag for +* station287~station256 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY8_AMSDU_QUEUE_EMPTY_FLAG_287_256_ADDR\ +WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY8_ADDR +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY8_AMSDU_QUEUE_EMPTY_FLAG_287_256_MASK\ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_287_256[31..0] */ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY8_AMSDU_QUEUE_EMPTY_FLAG_287_256_SHFT 0 + +/* +* ---AMSDU_AC3_QUEUE_EMPTY0 (0x820C0000 + 0x11C0)--- +* AMSDU_QUEUE_EMPTY_FLAG_31_0[31..0] - (RO) AC3 queue empty flag for +* station31~station0 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_ADDR \ +WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY0_ADDR +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_MASK \ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_31_0[31..0] */ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_SHFT 0 + +/* +* ---AMSDU_AC3_QUEUE_EMPTY1 (0x820C0000 + 0x11C4)--- +* AMSDU_QUEUE_EMPTY_FLAG_63_32[31..0] - (RO) AC3 queue empty flag for +* station63~station32 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY1_AMSDU_QUEUE_EMPTY_FLAG_63_32_ADDR \ +WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY1_ADDR +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY1_AMSDU_QUEUE_EMPTY_FLAG_63_32_MASK \ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_63_32[31..0] */ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY1_AMSDU_QUEUE_EMPTY_FLAG_63_32_SHFT 0 + +/* +* ---AMSDU_AC3_QUEUE_EMPTY2 (0x820C0000 + 0x11C8)--- +* AMSDU_QUEUE_EMPTY_FLAG_95_64[31..0] - (RO) AC3 queue empty flag for +* station95~station64 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY2_AMSDU_QUEUE_EMPTY_FLAG_95_64_ADDR \ +WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY2_ADDR +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY2_AMSDU_QUEUE_EMPTY_FLAG_95_64_MASK \ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_95_64[31..0] */ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY2_AMSDU_QUEUE_EMPTY_FLAG_95_64_SHFT 0 + +/* +* ---AMSDU_AC3_QUEUE_EMPTY3 (0x820C0000 + 0x11CC)--- +* AMSDU_QUEUE_EMPTY_FLAG_127_96[31..0] - (RO) AC3 queue empty flag for +* station127~station96 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY3_AMSDU_QUEUE_EMPTY_FLAG_127_96_ADDR \ +WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY3_ADDR +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY3_AMSDU_QUEUE_EMPTY_FLAG_127_96_MASK \ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_127_96[31..0] */ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY3_AMSDU_QUEUE_EMPTY_FLAG_127_96_SHFT 0 + +/* +* ---AMSDU_AC3_QUEUE_EMPTY4 (0x820C0000 + 0x11D0)--- +* AMSDU_QUEUE_EMPTY_FLAG_135_128[7..0] - (RO) AC3 queue empty flag for +* station135~station128 in HW AMSDU engine. +* AMSDU_QUEUE_EMPTY_FLAG_143_136[15..8] - (RO) AC3 queue empty flag for +* station143~station136 in HW AMSDU engine. +* AMSDU_QUEUE_EMPTY_FLAG_159_144[31..16] - (RO) AC3 queue empty flag for +* station159~station144 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_159_144_ADDR\ +WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY4_ADDR +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_159_144_MASK\ +0xFFFF0000 /* AMSDU_QUEUE_EMPTY_FLAG_159_144[31..16] */ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_159_144_SHFT 16 +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_143_136_ADDR\ +WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY4_ADDR +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_143_136_MASK\ +0x0000FF00 /* AMSDU_QUEUE_EMPTY_FLAG_143_136[15..8] */ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_143_136_SHFT 8 +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_135_128_ADDR\ +WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY4_ADDR +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_135_128_MASK\ +0x000000FF /* AMSDU_QUEUE_EMPTY_FLAG_135_128[7..0] */ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY4_AMSDU_QUEUE_EMPTY_FLAG_135_128_SHFT 0 + +/* +* ---AMSDU_AC3_QUEUE_EMPTY5 (0x820C0000 + 0x11D4)--- +* AMSDU_QUEUE_EMPTY_FLAG_191_160[31..0] - (RO) AC3 queue empty flag for +* station191~station160 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY5_AMSDU_QUEUE_EMPTY_FLAG_191_160_ADDR\ +WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY5_ADDR +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY5_AMSDU_QUEUE_EMPTY_FLAG_191_160_MASK\ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_191_160[31..0] */ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY5_AMSDU_QUEUE_EMPTY_FLAG_191_160_SHFT 0 + +/* +* ---AMSDU_AC3_QUEUE_EMPTY6 (0x820C0000 + 0x11d8)--- +* AMSDU_QUEUE_EMPTY_FLAG_223_192[31..0] - (RO) AC3 queue empty flag for +* station223~station192 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY6_AMSDU_QUEUE_EMPTY_FLAG_223_192_ADDR\ +WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY6_ADDR +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY6_AMSDU_QUEUE_EMPTY_FLAG_223_192_MASK\ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_223_192[31..0] */ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY6_AMSDU_QUEUE_EMPTY_FLAG_223_192_SHFT 0 + +/* +* ---AMSDU_AC3_QUEUE_EMPTY7 (0x820C0000 + 0x11dc)--- +* AMSDU_QUEUE_EMPTY_FLAG_255_224[31..0] - (RO) AC3 queue empty flag for +* station255~station224 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY7_AMSDU_QUEUE_EMPTY_FLAG_255_224_ADDR\ +WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY7_ADDR +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY7_AMSDU_QUEUE_EMPTY_FLAG_255_224_MASK\ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_255_224[31..0] */ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY7_AMSDU_QUEUE_EMPTY_FLAG_255_224_SHFT 0 + +/* +* ---AMSDU_AC3_QUEUE_EMPTY8 (0x820C0000 + 0x11e0)--- +* AMSDU_QUEUE_EMPTY_FLAG_287_256[31..0] - (RO) AC3 queue empty flag for +* station287~station256 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY8_AMSDU_QUEUE_EMPTY_FLAG_287_256_ADDR\ +WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY8_ADDR +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY8_AMSDU_QUEUE_EMPTY_FLAG_287_256_MASK\ +0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_287_256[31..0] */ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY8_AMSDU_QUEUE_EMPTY_FLAG_287_256_SHFT 0 + +/* +* ---CFG_DBDC_CTRL0 (0x820C0000 + 0x2008)--- +* RESERVED0[7..0] - (RO) Reserved bits +* WMM_0TO3_BAND_SEL[11..8] - (RW) Selects WMM0~WMM3 band +* RESERVED12[15..12] - (RO) Reserved bits +* NAN_BAND_SEL[16] - (RW) Selects NAN band +* FUNCQ_BAND_SEL[17] - (RW) Selects Functional Queue band +* TGID 0 & TGID1 always selec to different +band +* RESERVED18[30..18] - (RO) Reserved bits +* DBDC_EN[31] - (RW) Enables DBDC +*/ +#define WF_PLE_TOP_CFG_DBDC_CTRL0_DBDC_EN_ADDR WF_PLE_TOP_CFG_DBDC_CTRL0_ADDR +#define WF_PLE_TOP_CFG_DBDC_CTRL0_DBDC_EN_MASK 0x80000000 /* DBDC_EN[31] */ +#define WF_PLE_TOP_CFG_DBDC_CTRL0_DBDC_EN_SHFT 31 +#define WF_PLE_TOP_CFG_DBDC_CTRL0_FUNCQ_BAND_SEL_ADDR \ +WF_PLE_TOP_CFG_DBDC_CTRL0_ADDR +#define WF_PLE_TOP_CFG_DBDC_CTRL0_FUNCQ_BAND_SEL_MASK \ +0x00020000 /* FUNCQ_BAND_SEL[17] */ +#define WF_PLE_TOP_CFG_DBDC_CTRL0_FUNCQ_BAND_SEL_SHFT 17 +#define WF_PLE_TOP_CFG_DBDC_CTRL0_NAN_BAND_SEL_ADDR \ +WF_PLE_TOP_CFG_DBDC_CTRL0_ADDR +#define WF_PLE_TOP_CFG_DBDC_CTRL0_NAN_BAND_SEL_MASK \ +0x00010000 /* NAN_BAND_SEL[16] */ +#define WF_PLE_TOP_CFG_DBDC_CTRL0_NAN_BAND_SEL_SHFT 16 +#define WF_PLE_TOP_CFG_DBDC_CTRL0_WMM_0TO3_BAND_SEL_ADDR \ +WF_PLE_TOP_CFG_DBDC_CTRL0_ADDR +#define WF_PLE_TOP_CFG_DBDC_CTRL0_WMM_0TO3_BAND_SEL_MASK \ +0x00000F00 /* WMM_0TO3_BAND_SEL[11..8] */ +#define WF_PLE_TOP_CFG_DBDC_CTRL0_WMM_0TO3_BAND_SEL_SHFT 8 + +/* +* ---CFG_UWTBL_MBIST_CTRL_0 (0x820C0000 + 0x2480)--- +* UWTBL_MBIST_MODE[0] - (RW) Control register for mbist_mode of UWTBL +MBIST +* UWTBL_MBIST_HOLDB[1] - (RW) Control register for mbist_holdb of +* UWTBL MBIST +* UWTBL_MBIST_DEBUG[2] - (RW) Control register for mbist_debug of +* UWTBL MBIST +* UWTBL_MBIST_USE_DEFAULT_DELSEL[3] - (RW) Control register for default DELSEL +* value of UWTBL memory +* UWTBL_MBIST_SLEEP_TEST[4] - (RW) Control register for sleep_test of UWTBL +MBIST +* UWTBL_MBIST_SLEEP_INV[5] - (RW) Control register for sleep_inv of UWTBL +MBIST +* UWTBL_MBIST_SLEEP_W[6] - (RW) Control register for sleep_w of UWTBL +MBIST +* UWTBL_MBIST_SLEEP_R[7] - (RW) Control register for sleep_r of UWTBL +MBIST +* UWTBL_MBIST_DONE[8] - (RO) Working status of UWTBL SRAM MBIST +circuit +* RESERVED9[15..9] - (RO) Reserved bits +* UWTBL_MBIST_FAIL[21..16] - (RO) MBIST check result of UWTBL SRAM +* RESERVED22[31..22] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_FAIL_ADDR \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_FAIL_MASK \ +0x003F0000 /* UWTBL_MBIST_FAIL[21..16] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_FAIL_SHFT 16 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_DONE_ADDR \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_DONE_MASK \ +0x00000100 /* UWTBL_MBIST_DONE[8] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_DONE_SHFT 8 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_R_ADDR \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_R_MASK \ +0x00000080 /* UWTBL_MBIST_SLEEP_R[7] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_R_SHFT 7 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_W_ADDR \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_W_MASK \ +0x00000040 /* UWTBL_MBIST_SLEEP_W[6] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_W_SHFT 6 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_INV_ADDR \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_INV_MASK \ +0x00000020 /* UWTBL_MBIST_SLEEP_INV[5] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_INV_SHFT 5 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_TEST_ADDR \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_TEST_MASK \ +0x00000010 /* UWTBL_MBIST_SLEEP_TEST[4] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_TEST_SHFT 4 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_USE_DEFAULT_DELSEL_ADDR\ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_USE_DEFAULT_DELSEL_MASK\ +0x00000008 /* UWTBL_MBIST_USE_DEFAULT_DELSEL[3] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_USE_DEFAULT_DELSEL_SHFT 3 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_DEBUG_ADDR \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_DEBUG_MASK \ +0x00000004 /* UWTBL_MBIST_DEBUG[2] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_DEBUG_SHFT 2 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_HOLDB_ADDR \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_HOLDB_MASK \ +0x00000002 /* UWTBL_MBIST_HOLDB[1] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_HOLDB_SHFT 1 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_MODE_ADDR \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_MODE_MASK \ +0x00000001 /* UWTBL_MBIST_MODE[0] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_MODE_SHFT 0 + +/* +* ---CFG_UWTBL_MBIST_CTRL_1 (0x820C0000 + 0x2484)--- +* UWTBL_MBIST_HDEN[5..0] - (RW) Control register for mbist UWTBL HDEN +* RESERVED6[15..6] - (RO) Reserved bits +* UWTBL_MBIST_AWT[21..16] - (RW) Control register for mbist UWTBL AWT +* RESERVED22[31..22] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_UWTBL_MBIST_AWT_ADDR \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_UWTBL_MBIST_AWT_MASK \ +0x003F0000 /* UWTBL_MBIST_AWT[21..16] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_UWTBL_MBIST_AWT_SHFT 16 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_UWTBL_MBIST_HDEN_ADDR \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_UWTBL_MBIST_HDEN_MASK \ +0x0000003F /* UWTBL_MBIST_HDEN[5..0] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_UWTBL_MBIST_HDEN_SHFT 0 + +/* +* ---CFG_UWTBL_MBIST_CTRL_2 (0x820C0000 + 0x2488)--- +* UWTBL_BACKGROUND[15..0] - (RW) The MBIST background control register +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_2_UWTBL_BACKGROUND_ADDR \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_2_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_2_UWTBL_BACKGROUND_MASK \ +0x0000FFFF /* UWTBL_BACKGROUND[15..0] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_2_UWTBL_BACKGROUND_SHFT 0 + +/* +* ---CFG_UWTBL_MBIST_CTRL_3 (0x820C0000 + 0x248c)--- +* UWTBL_DELSEL_0[31..0] - (RW) UWTBL DELSEL 0 +*/ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_3_UWTBL_DELSEL_0_ADDR \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_3_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_3_UWTBL_DELSEL_0_MASK \ +0xFFFFFFFF /* UWTBL_DELSEL_0[31..0] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_3_UWTBL_DELSEL_0_SHFT 0 + +/* +* ---CFG_UWTBL_MBIST_CTRL_4 (0x820C0000 + 0x2490)--- +* UWTBL_DELSEL_1[31..0] - (RW) UWTBL DELSEL 1 +*/ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_4_UWTBL_DELSEL_1_ADDR \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_4_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_4_UWTBL_DELSEL_1_MASK \ +0xFFFFFFFF /* UWTBL_DELSEL_1[31..0] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_4_UWTBL_DELSEL_1_SHFT 0 + +/* +* ---CFG_UWTBL_MBIST_CTRL_5 (0x820C0000 + 0x2494)--- +* UWTBL_FUSE[6..0] - (RW) UWTBL FUSE +* RESERVED7[7] - (RO) Reserved bits +* UWTBL_PRE_FUSE[14..8] - (RO) UWTBL MBIST Pre Fuse +* RESERVED15[15] - (RO) Reserved bits +* UWTBL_MBIST_REPAIR_OK[21..16] - (RO) MBIST Repair OK +* RESERVED22[23..22] - (RO) Reserved bits +* UWTBL_MBIST_REPAIR_FAIL[29..24] - (RO) MBIST Repair Fail +* RESERVED30[31..30] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_MBIST_REPAIR_FAIL_ADDR \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_MBIST_REPAIR_FAIL_MASK \ +0x3F000000 /* UWTBL_MBIST_REPAIR_FAIL[29..24] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_MBIST_REPAIR_FAIL_SHFT 24 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_MBIST_REPAIR_OK_ADDR \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_MBIST_REPAIR_OK_MASK \ +0x003F0000 /* UWTBL_MBIST_REPAIR_OK[21..16] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_MBIST_REPAIR_OK_SHFT 16 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_PRE_FUSE_ADDR \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_PRE_FUSE_MASK \ +0x00007F00 /* UWTBL_PRE_FUSE[14..8] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_PRE_FUSE_SHFT 8 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_FUSE_ADDR \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_FUSE_MASK \ +0x0000007F /* UWTBL_FUSE[6..0] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_FUSE_SHFT 0 + +/* +* ---CFG_UWTBL_MBIST_CTRL_6 (0x820C0000 + 0x2498)--- +* UWTBL_DELSEL_2[31..0] - (RW) UWTBL DELSEL 2 +*/ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_6_UWTBL_DELSEL_2_ADDR \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_6_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_6_UWTBL_DELSEL_2_MASK \ +0xFFFFFFFF /* UWTBL_DELSEL_2[31..0] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_6_UWTBL_DELSEL_2_SHFT 0 + +/* +* ---CFG_SEC_MBIST_CTRL_0 (0x820C0000 + 0x25c0)--- +* SEC_MBIST_MODE[0] - (RW) Control register for mbist_mode of SEC +MBIST +* SEC_MBIST_HOLDB[1] - (RW) Control register for mbist_holdb of SEC +MBIST +* SEC_MBIST_DEBUG[2] - (RW) Control register for mbist_debug of SEC +MBIST +* SEC_MBIST_USE_DEFAULT_DELSEL[3] - (RW) Control register for default DELSEL +* value of SEC memory +* RESERVED4[7..4] - (RO) Reserved bits +* SEC_MBIST_DONE[8] - (RO) Working status of SEC SRAM MBIST circuit +* RESERVED9[15..9] - (RO) Reserved bits +* SEC_MBIST_FAIL[17..16] - (RO) MBIST check result of SEC SRAM +* RESERVED18[31..18] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_FAIL_ADDR \ +WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_FAIL_MASK \ +0x00030000 /* SEC_MBIST_FAIL[17..16] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_FAIL_SHFT 16 +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_DONE_ADDR \ +WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_DONE_MASK \ +0x00000100 /* SEC_MBIST_DONE[8] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_DONE_SHFT 8 +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_USE_DEFAULT_DELSEL_ADDR \ +WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_USE_DEFAULT_DELSEL_MASK \ +0x00000008 /* SEC_MBIST_USE_DEFAULT_DELSEL[3] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_USE_DEFAULT_DELSEL_SHFT 3 +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_DEBUG_ADDR \ +WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_DEBUG_MASK \ +0x00000004 /* SEC_MBIST_DEBUG[2] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_DEBUG_SHFT 2 +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_HOLDB_ADDR \ +WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_HOLDB_MASK \ +0x00000002 /* SEC_MBIST_HOLDB[1] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_HOLDB_SHFT 1 +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_MODE_ADDR \ +WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_MODE_MASK \ +0x00000001 /* SEC_MBIST_MODE[0] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_MODE_SHFT 0 + +/* +* ---CFG_SEC_MBIST_CTRL_1 (0x820C0000 + 0x25c4)--- +* SEC_MBIST_HDEN[0] - (RW) Control register for mbist SEC HDEN +* RESERVED1[15..1] - (RO) Reserved bits +* SEC_MBIST_AWT[16] - (RW) Control register for mbist SEC AWT +* RESERVED17[31..17] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_SEC_MBIST_AWT_ADDR \ +WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_SEC_MBIST_AWT_MASK \ +0x00010000 /* SEC_MBIST_AWT[16] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_SEC_MBIST_AWT_SHFT 16 +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_SEC_MBIST_HDEN_ADDR \ +WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_SEC_MBIST_HDEN_MASK \ +0x00000001 /* SEC_MBIST_HDEN[0] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_SEC_MBIST_HDEN_SHFT 0 + +/* +* ---CFG_SEC_MBIST_CTRL_2 (0x820C0000 + 0x25c8)--- +* SEC_BACKGROUND[15..0] - (RW) The MBIST background control register +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_2_SEC_BACKGROUND_ADDR \ +WF_PLE_TOP_CFG_SEC_MBIST_CTRL_2_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_2_SEC_BACKGROUND_MASK \ +0x0000FFFF /* SEC_BACKGROUND[15..0] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_2_SEC_BACKGROUND_SHFT 0 + +/* +* ---CFG_SEC_MBIST_CTRL_3 (0x820C0000 + 0x25cc)--- +* SEC_DELSEL_0[31..0] - (RW) SEC DELSEL 0 +*/ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_3_SEC_DELSEL_0_ADDR \ +WF_PLE_TOP_CFG_SEC_MBIST_CTRL_3_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_3_SEC_DELSEL_0_MASK \ +0xFFFFFFFF /* SEC_DELSEL_0[31..0] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_3_SEC_DELSEL_0_SHFT 0 + +/* +* ---CFG_PF_MBIST_CTRL_0 (0x820C0000 + 0x25e0)--- +* PF_MBIST_MODE[0] - (RW) Control register for mbist_mode of PF +MBIST +* PF_MBIST_HOLDB[1] - (RW) Control register for mbist_holdb of PF +MBIST +* PF_MBIST_DEBUG[2] - (RW) Control register for mbist_debug of PF +MBIST +* PF_MBIST_USE_DEFAULT_DELSEL[3] - (RW) Control register for default DELSEL +* value of PF memory +* PF_MBIST_SLEEP_TEST[4] - (RW) Control register for sleep_test of PF +MBIST +* PF_MBIST_SLEEP_INV[5] - (RW) Control register for sleep_inv of PF +MBIST +* PF_MBIST_SLEEP_W[6] - (RW) Control register for sleep_w of PF MBIST +* PF_MBIST_SLEEP_R[7] - (RW) Control register for sleep_r of PF MBIST +* PF_MBIST_DONE[8] - (RO) Working status of PF SRAM MBIST circuit +* RESERVED9[11..9] - (RO) Reserved bits +* PF_MBIST_FAIL[31..12] - (RO) MBIST check result of PF SRAM +*/ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_FAIL_ADDR \ +WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_FAIL_MASK \ +0xFFFFF000 /* PF_MBIST_FAIL[31..12] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_FAIL_SHFT 12 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_DONE_ADDR \ +WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_DONE_MASK \ +0x00000100 /* PF_MBIST_DONE[8] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_DONE_SHFT 8 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_R_ADDR \ +WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_R_MASK \ +0x00000080 /* PF_MBIST_SLEEP_R[7] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_R_SHFT 7 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_W_ADDR \ +WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_W_MASK \ +0x00000040 /* PF_MBIST_SLEEP_W[6] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_W_SHFT 6 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_INV_ADDR \ +WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_INV_MASK \ +0x00000020 /* PF_MBIST_SLEEP_INV[5] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_INV_SHFT 5 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_TEST_ADDR \ +WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_TEST_MASK \ +0x00000010 /* PF_MBIST_SLEEP_TEST[4] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_TEST_SHFT 4 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_USE_DEFAULT_DELSEL_ADDR \ +WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_USE_DEFAULT_DELSEL_MASK \ +0x00000008 /* PF_MBIST_USE_DEFAULT_DELSEL[3] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_USE_DEFAULT_DELSEL_SHFT 3 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_DEBUG_ADDR \ +WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_DEBUG_MASK \ +0x00000004 /* PF_MBIST_DEBUG[2] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_DEBUG_SHFT 2 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_HOLDB_ADDR \ +WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_HOLDB_MASK \ +0x00000002 /* PF_MBIST_HOLDB[1] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_HOLDB_SHFT 1 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_MODE_ADDR \ +WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_MODE_MASK \ +0x00000001 /* PF_MBIST_MODE[0] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_MODE_SHFT 0 + +/* +* ---CFG_PF_MBIST_CTRL_1 (0x820C0000 + 0x25e4)--- +* PF_MBIST_HDEN[9..0] - (RW) Control register for mbist PF HDEN +* RESERVED10[11..10] - (RO) Reserved bits +* PF_MBIST_AWT[31..12] - (RW) Control register for mbist PF AWT +*/ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_PF_MBIST_AWT_ADDR \ +WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_PF_MBIST_AWT_MASK \ +0xFFFFF000 /* PF_MBIST_AWT[31..12] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_PF_MBIST_AWT_SHFT 12 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_PF_MBIST_HDEN_ADDR \ +WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_PF_MBIST_HDEN_MASK \ +0x000003FF /* PF_MBIST_HDEN[9..0] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_PF_MBIST_HDEN_SHFT 0 + +/* +* ---CFG_PF_MBIST_CTRL_2 (0x820C0000 + 0x25e8)--- +* PF_BACKGROUND[15..0] - (RW) The MBIST background control register +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_2_PF_BACKGROUND_ADDR \ +WF_PLE_TOP_CFG_PF_MBIST_CTRL_2_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_2_PF_BACKGROUND_MASK \ +0x0000FFFF /* PF_BACKGROUND[15..0] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_2_PF_BACKGROUND_SHFT 0 + +/* +* ---CFG_PF_MBIST_CTRL_3 (0x820C0000 + 0x25ec)--- +* PF_DELSEL_0[31..0] - (RW) PF DELSEL 0 +*/ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_3_PF_DELSEL_0_ADDR \ +WF_PLE_TOP_CFG_PF_MBIST_CTRL_3_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_3_PF_DELSEL_0_MASK \ +0xFFFFFFFF /* PF_DELSEL_0[31..0] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_3_PF_DELSEL_0_SHFT 0 + +/* +* ---SYSRAM_MBIST_CTRL (0x820C0000 + 0x3004)--- +* MBIST_SW_RESET[0] - (RW) MBIST Software reset +* RESERVED1[7..1] - (RO) Reserved bits +* MBIST_BSEL[15..8] - (RW) Controls BSEL of SRAM MBIST circuit. +* MBIST_BACKGROUND[31..16] - (RW) The MBIST background control register +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_BACKGROUND_ADDR \ +WF_PLE_TOP_SYSRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_BACKGROUND_MASK \ +0xFFFF0000 /* MBIST_BACKGROUND[31..16] */ +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_BACKGROUND_SHFT 16 +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_BSEL_ADDR \ +WF_PLE_TOP_SYSRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_BSEL_MASK \ +0x0000FF00 /* MBIST_BSEL[15..8] */ +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_BSEL_SHFT 8 +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_SW_RESET_ADDR \ +WF_PLE_TOP_SYSRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_SW_RESET_MASK \ +0x00000001 /* MBIST_SW_RESET[0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_SW_RESET_SHFT 0 + +/* +* ---SYSRAM_MBIST_DEBUG (0x820C0000 + 0x3008)--- +* SYSRAM_MBIST_DEBUG[15..0] - (RW) Control register for mbist_debug of +* SYSRAM MBIST +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_DEBUG_SYSRAM_MBIST_DEBUG_ADDR \ +WF_PLE_TOP_SYSRAM_MBIST_DEBUG_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_DEBUG_SYSRAM_MBIST_DEBUG_MASK \ +0x0000FFFF /* SYSRAM_MBIST_DEBUG[15..0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_DEBUG_SYSRAM_MBIST_DEBUG_SHFT 0 + +/* +* ---SYSRAM_MBIST_MODE (0x820C0000 + 0x300C)--- +* SYSRAM_MBIST_MODE[15..0] - (RW) Control register for mbist_holdb of +* SYSRAM MBIST +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_MODE_SYSRAM_MBIST_MODE_ADDR \ +WF_PLE_TOP_SYSRAM_MBIST_MODE_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_MODE_SYSRAM_MBIST_MODE_MASK \ +0x0000FFFF /* SYSRAM_MBIST_MODE[15..0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_MODE_SYSRAM_MBIST_MODE_SHFT 0 + +/* +* ---SYSRAM_MBIST_HOLDB (0x820C0000 + 0x3010)--- +* SYSRAM_MBIST_HOLDB[15..0] - (RW) Control register for mbist_holdb of +* sysram MBIST +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_HOLDB_SYSRAM_MBIST_HOLDB_ADDR \ +WF_PLE_TOP_SYSRAM_MBIST_HOLDB_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_HOLDB_SYSRAM_MBIST_HOLDB_MASK \ +0x0000FFFF /* SYSRAM_MBIST_HOLDB[15..0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_HOLDB_SYSRAM_MBIST_HOLDB_SHFT 0 + +/* +* ---SYSRAM_MBIST_DONE (0x820C0000 + 0x3014)--- +* SYSRAM_MBIST_DONE[15..0] - (RO) Working status of SYSRAM MBIST 3 circuit +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_DONE_SYSRAM_MBIST_DONE_ADDR \ +WF_PLE_TOP_SYSRAM_MBIST_DONE_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_DONE_SYSRAM_MBIST_DONE_MASK \ +0x0000FFFF /* SYSRAM_MBIST_DONE[15..0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_DONE_SYSRAM_MBIST_DONE_SHFT 0 + +/* +* ---SYSRAM_MBIST_FAIL (0x820C0000 + 0x3018)--- +* SYSRAM_MBIST_FAIL[31..0] - (RO) MBIST check result of SYSRAM cell 3 +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_FAIL_SYSRAM_MBIST_FAIL_ADDR \ +WF_PLE_TOP_SYSRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_FAIL_SYSRAM_MBIST_FAIL_MASK \ +0xFFFFFFFF /* SYSRAM_MBIST_FAIL[31..0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_FAIL_SYSRAM_MBIST_FAIL_SHFT 0 + +/* +* ---SYSRAM_MBIST_SLEEP_TEST (0x820C0000 + 0x301C)--- +* SYSRAM_MBIST_SLEEP_TEST[15..0] - (RW) Control register for sleep_test of +* group 3 MBIST +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_TEST_SYSRAM_MBIST_SLEEP_TEST_ADDR \ +WF_PLE_TOP_SYSRAM_MBIST_SLEEP_TEST_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_TEST_SYSRAM_MBIST_SLEEP_TEST_MASK \ +0x0000FFFF /* SYSRAM_MBIST_SLEEP_TEST[15..0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_TEST_SYSRAM_MBIST_SLEEP_TEST_SHFT 0 + +/* +* ---SYSRAM_MBIST_SLEEP_INV (0x820C0000 + 0x3020)--- +* SYSRAM_MBIST_SLEEP_INV[15..0] - (RW) Control register for sleep_inv of group +* 3 MBIST +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_INV_SYSRAM_MBIST_SLEEP_INV_ADDR \ +WF_PLE_TOP_SYSRAM_MBIST_SLEEP_INV_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_INV_SYSRAM_MBIST_SLEEP_INV_MASK \ +0x0000FFFF /* SYSRAM_MBIST_SLEEP_INV[15..0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_INV_SYSRAM_MBIST_SLEEP_INV_SHFT 0 + +/* +* ---SYSRAM_MBIST_SLEEP_W (0x820C0000 + 0x3024)--- +* SYSRAM_MBIST_SLEEP_WRITE[15..0] - (RW) Control register for sleep_w of group +* 3 MBIST +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_W_SYSRAM_MBIST_SLEEP_WRITE_ADDR \ +WF_PLE_TOP_SYSRAM_MBIST_SLEEP_W_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_W_SYSRAM_MBIST_SLEEP_WRITE_MASK \ +0x0000FFFF /* SYSRAM_MBIST_SLEEP_WRITE[15..0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_W_SYSRAM_MBIST_SLEEP_WRITE_SHFT 0 + +/* +* ---SYSRAM_MBIST_SLEEP_R (0x820C0000 + 0x3028)--- +* SYSRAM_MBIST_SLEEP_READ[15..0] - (RW) Control register for sleep_r of group +* 3 MBIST +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_R_SYSRAM_MBIST_SLEEP_READ_ADDR \ +WF_PLE_TOP_SYSRAM_MBIST_SLEEP_R_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_R_SYSRAM_MBIST_SLEEP_READ_MASK \ +0x0000FFFF /* SYSRAM_MBIST_SLEEP_READ[15..0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_R_SYSRAM_MBIST_SLEEP_READ_SHFT 0 + +/* +* ---SYSRAM_AWT_HDEN (0x820C0000 + 0x302C)--- +* SYSRAM_MBIST_AWT[15..0] - (RW) Control register for mbist SYSRAM 3 AWT +* SYSRAM_MBIST_HDEN[31..16] - (RW) Control register for mbist SYSRAM 3 HDEN +*/ +#define WF_PLE_TOP_SYSRAM_AWT_HDEN_SYSRAM_MBIST_HDEN_ADDR \ +WF_PLE_TOP_SYSRAM_AWT_HDEN_ADDR +#define WF_PLE_TOP_SYSRAM_AWT_HDEN_SYSRAM_MBIST_HDEN_MASK \ +0xFFFF0000 /* SYSRAM_MBIST_HDEN[31..16] */ +#define WF_PLE_TOP_SYSRAM_AWT_HDEN_SYSRAM_MBIST_HDEN_SHFT 16 +#define WF_PLE_TOP_SYSRAM_AWT_HDEN_SYSRAM_MBIST_AWT_ADDR \ +WF_PLE_TOP_SYSRAM_AWT_HDEN_ADDR +#define WF_PLE_TOP_SYSRAM_AWT_HDEN_SYSRAM_MBIST_AWT_MASK \ +0x0000FFFF /* SYSRAM_MBIST_AWT[15..0] */ +#define WF_PLE_TOP_SYSRAM_AWT_HDEN_SYSRAM_MBIST_AWT_SHFT 0 + +/* +* ---SYSRAM_DBG_SEL (0x820C0000 + 0x3030)--- +* SYSRAM_DEBUG_SELECT_0[7..0] - (RW) Selects SYSRAM control debug 0 +* SYSRAM_DEBUG_SELECT_1[15..8] - (RW) Selects SYSRAM control debug 1 +* SYSRAM_DEBUG_SELECT_2[23..16] - (RW) Selects SYSRAM control debug 2 +* SYSRAM_DEBUG_SELECT_3[31..24] - (RW) Selects SYSRAM control debug 3 +*/ +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_3_ADDR \ +WF_PLE_TOP_SYSRAM_DBG_SEL_ADDR +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_3_MASK \ +0xFF000000 /* SYSRAM_DEBUG_SELECT_3[31..24] */ +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_3_SHFT 24 +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_2_ADDR \ +WF_PLE_TOP_SYSRAM_DBG_SEL_ADDR +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_2_MASK \ +0x00FF0000 /* SYSRAM_DEBUG_SELECT_2[23..16] */ +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_2_SHFT 16 +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_1_ADDR \ +WF_PLE_TOP_SYSRAM_DBG_SEL_ADDR +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_1_MASK \ +0x0000FF00 /* SYSRAM_DEBUG_SELECT_1[15..8] */ +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_1_SHFT 8 +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_0_ADDR \ +WF_PLE_TOP_SYSRAM_DBG_SEL_ADDR +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_0_MASK \ +0x000000FF /* SYSRAM_DEBUG_SELECT_0[7..0] */ +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_0_SHFT 0 + +/* +* ---SYSRAM_DELSEL (0x820C0000 + 0x3070)--- +* TYPE0_SYSRAM_DELSEL[31..0] - (RW) Type0 SYSRAM DELSEL bits +*/ +#define WF_PLE_TOP_SYSRAM_DELSEL_TYPE0_SYSRAM_DELSEL_ADDR \ +WF_PLE_TOP_SYSRAM_DELSEL_ADDR +#define WF_PLE_TOP_SYSRAM_DELSEL_TYPE0_SYSRAM_DELSEL_MASK \ +0xFFFFFFFF /* TYPE0_SYSRAM_DELSEL[31..0] */ +#define WF_PLE_TOP_SYSRAM_DELSEL_TYPE0_SYSRAM_DELSEL_SHFT 0 + +/* +* ---SYSRAM_DELSEL_1 (0x820C0000 + 0x3074)--- +* TYPE1_SYSRAM_DELSEL[31..0] - (RW) Type1 SYSRAM DELSEL bits +*/ +#define WF_PLE_TOP_SYSRAM_DELSEL_1_TYPE1_SYSRAM_DELSEL_ADDR \ +WF_PLE_TOP_SYSRAM_DELSEL_1_ADDR +#define WF_PLE_TOP_SYSRAM_DELSEL_1_TYPE1_SYSRAM_DELSEL_MASK \ +0xFFFFFFFF /* TYPE1_SYSRAM_DELSEL[31..0] */ +#define WF_PLE_TOP_SYSRAM_DELSEL_1_TYPE1_SYSRAM_DELSEL_SHFT 0 + +/* +* ---SYSRAM_DELSEL_2 (0x820C0000 + 0x3078)--- +* TYPE2_SYSRAM_DELSEL[31..0] - (RW) Type2 SYSRAM DELSEL bits +*/ +#define WF_PLE_TOP_SYSRAM_DELSEL_2_TYPE2_SYSRAM_DELSEL_ADDR \ +WF_PLE_TOP_SYSRAM_DELSEL_2_ADDR +#define WF_PLE_TOP_SYSRAM_DELSEL_2_TYPE2_SYSRAM_DELSEL_MASK \ +0xFFFFFFFF /* TYPE2_SYSRAM_DELSEL[31..0] */ +#define WF_PLE_TOP_SYSRAM_DELSEL_2_TYPE2_SYSRAM_DELSEL_SHFT 0 + +/* +* ---SYSRAM_DELSEL_3 (0x820C0000 + 0x307C)--- +* TYPE3_SYSRAM_DELSEL[31..0] - (RW) Type3 SYSRAM DELSEL bits +*/ +#define WF_PLE_TOP_SYSRAM_DELSEL_3_TYPE3_SYSRAM_DELSEL_ADDR \ +WF_PLE_TOP_SYSRAM_DELSEL_3_ADDR +#define WF_PLE_TOP_SYSRAM_DELSEL_3_TYPE3_SYSRAM_DELSEL_MASK \ +0xFFFFFFFF /* TYPE3_SYSRAM_DELSEL[31..0] */ +#define WF_PLE_TOP_SYSRAM_DELSEL_3_TYPE3_SYSRAM_DELSEL_SHFT 0 + +/* +* ---SYSRAM_OUTRAN_ERR_FLAG (0x820C0000 + 0x3080)--- +* SYSRAM_OUTRAN_ERR_FLAG[31..0] - (RO) Type3 SYSRAM DELSEL bits +*/ +#define WF_PLE_TOP_SYSRAM_OUTRAN_ERR_FLAG_SYSRAM_OUTRAN_ERR_FLAG_ADDR \ +WF_PLE_TOP_SYSRAM_OUTRAN_ERR_FLAG_ADDR +#define WF_PLE_TOP_SYSRAM_OUTRAN_ERR_FLAG_SYSRAM_OUTRAN_ERR_FLAG_MASK \ +0xFFFFFFFF /* SYSRAM_OUTRAN_ERR_FLAG[31..0] */ +#define WF_PLE_TOP_SYSRAM_OUTRAN_ERR_FLAG_SYSRAM_OUTRAN_ERR_FLAG_SHFT 0 + +#ifdef __cplusplus +} +#endif + +#endif /* __WF_PLE_TOP_REGS_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7915/wf_pse_top.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7915/wf_pse_top.h new file mode 100644 index 0000000000000..668ee6364e84e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7915/wf_pse_top.h @@ -0,0 +1,3353 @@ +/* [File] : wf_pse_top.h */ +/* [Revision time] : Mon Mar 18 14:59:41 2019 */ +/* [Description] : This file is auto generated by CODA */ +/* [Copyright] : Copyright (C) 2019 Mediatek Incorportion. All rights */ +/* reserved. */ + +#ifndef __WF_PSE_TOP_REGS_H__ +#define __WF_PSE_TOP_REGS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ************************************************************************** */ +/* */ +/* WF_PSE_TOP CR Definitions */ +/* */ +/* ************************************************************************** */ + +#define WF_PSE_TOP_BASE 0x820C8000 + +#define WF_PSE_TOP_GC_ADDR (WF_PSE_TOP_BASE + 0x00) /* 8000 */ +#define WF_PSE_TOP_PBUF_CTRL_ADDR (WF_PSE_TOP_BASE + 0x14) /* 8014 */ +#define WF_PSE_TOP_INT_N9_EN_MASK_ADDR (WF_PSE_TOP_BASE + 0x20) /* 8020 */ +#define WF_PSE_TOP_INT_N9_STS_ADDR (WF_PSE_TOP_BASE + 0x24) /* 8024 */ +#define WF_PSE_TOP_INT_N9_ERR_STS_ADDR (WF_PSE_TOP_BASE + 0x28) /* 8028 */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_ADDR (WF_PSE_TOP_BASE + 0x2C) /* 802C */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_ADDR (WF_PSE_TOP_BASE + 0x30) /* 8030 */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR (WF_PSE_TOP_BASE + 0x34) /* 8034 */ +#define WF_PSE_TOP_C_GET_FID_0_ADDR (WF_PSE_TOP_BASE + 0x40) /* 8040 */ +#define WF_PSE_TOP_C_GET_FID_1_ADDR (WF_PSE_TOP_BASE + 0x44) /* 8044 */ +#define WF_PSE_TOP_C_EN_QUEUE_0_ADDR (WF_PSE_TOP_BASE + 0x60) /* 8060 */ +#define WF_PSE_TOP_C_EN_QUEUE_1_ADDR (WF_PSE_TOP_BASE + 0x64) /* 8064 */ +#define WF_PSE_TOP_C_EN_QUEUE_2_ADDR (WF_PSE_TOP_BASE + 0x68) /* 8068 */ +#define WF_PSE_TOP_C_DE_QUEUE_0_ADDR (WF_PSE_TOP_BASE + 0x80) /* 8080 */ +#define WF_PSE_TOP_C_DE_QUEUE_1_ADDR (WF_PSE_TOP_BASE + 0x84) /* 8084 */ +#define WF_PSE_TOP_C_DE_QUEUE_2_ADDR (WF_PSE_TOP_BASE + 0x88) /* 8088 */ +#define WF_PSE_TOP_C_DE_QUEUE_3_ADDR (WF_PSE_TOP_BASE + 0x8c) /* 808C */ +#define WF_PSE_TOP_C_DE_QUEUE_4_ADDR (WF_PSE_TOP_BASE + 0x90) /* 8090 */ +#define WF_PSE_TOP_ALLOCATE_0_ADDR (WF_PSE_TOP_BASE + 0xA0) /* 80A0 */ +#define WF_PSE_TOP_ALLOCATE_1_ADDR (WF_PSE_TOP_BASE + 0xA4) /* 80A4 */ +#define WF_PSE_TOP_QUEUE_EMPTY_ADDR (WF_PSE_TOP_BASE + 0xB0) /* 80B0 */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR (WF_PSE_TOP_BASE + 0xB4) /* 80B4 */ +#define WF_PSE_TOP_FREEPG_START_END_ADDR (WF_PSE_TOP_BASE + 0xC0) /* 80C0 */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR (WF_PSE_TOP_BASE + 0xc4) /* 80C4 */ +#define WF_PSE_TOP_TO_N9_INT_ADDR (WF_PSE_TOP_BASE + 0xf0) /* 80F0 */ +#define WF_PSE_TOP_FREEPG_CNT_ADDR (WF_PSE_TOP_BASE + 0x100) /* 8100 */ +#define WF_PSE_TOP_FREEPG_HEAD_TAIL_ADDR (WF_PSE_TOP_BASE + 0x104) /* 8104 */ +#define WF_PSE_TOP_GROUP_REFILL_CTRL_ADDR (WF_PSE_TOP_BASE + 0x108) /* 8108 */ +#define WF_PSE_TOP_PG_HIF0_GROUP_ADDR (WF_PSE_TOP_BASE + 0x110) /* 8110 */ +#define WF_PSE_TOP_HIF0_PG_INFO_ADDR (WF_PSE_TOP_BASE + 0x114) /* 8114 */ +#define WF_PSE_TOP_PG_HIF1_GROUP_ADDR (WF_PSE_TOP_BASE + 0x118) /* 8118 */ +#define WF_PSE_TOP_HIF1_PG_INFO_ADDR (WF_PSE_TOP_BASE + 0x11C) /* 811C */ +#define WF_PSE_TOP_PG_CPU_GROUP_ADDR (WF_PSE_TOP_BASE + 0x150) /* 8150 */ +#define WF_PSE_TOP_CPU_PG_INFO_ADDR (WF_PSE_TOP_BASE + 0x154) /* 8154 */ +#define WF_PSE_TOP_PG_PLE_GROUP_ADDR (WF_PSE_TOP_BASE + 0x160) /* 8160 */ +#define WF_PSE_TOP_PLE_PG_INFO_ADDR (WF_PSE_TOP_BASE + 0x164) /* 8164 */ +#define WF_PSE_TOP_PG_PLE1_GROUP_ADDR (WF_PSE_TOP_BASE + 0x168) /* 8168 */ +#define WF_PSE_TOP_PLE1_PG_INFO_ADDR (WF_PSE_TOP_BASE + 0x16C) /* 816C */ +#define WF_PSE_TOP_PG_LMAC0_GROUP_ADDR (WF_PSE_TOP_BASE + 0x170) /* 8170 */ +#define WF_PSE_TOP_LMAC0_PG_INFO_ADDR (WF_PSE_TOP_BASE + 0x174) /* 8174 */ +#define WF_PSE_TOP_PG_LMAC1_GROUP_ADDR (WF_PSE_TOP_BASE + 0x178) /* 8178 */ +#define WF_PSE_TOP_LMAC1_PG_INFO_ADDR (WF_PSE_TOP_BASE + 0x17C) /* 817C */ +#define WF_PSE_TOP_PG_LMAC2_GROUP_ADDR (WF_PSE_TOP_BASE + 0x180) /* 8180 */ +#define WF_PSE_TOP_LMAC2_PG_INFO_ADDR (WF_PSE_TOP_BASE + 0x184) /* 8184 */ +#define WF_PSE_TOP_PG_LMAC3_GROUP_ADDR (WF_PSE_TOP_BASE + 0x188) /* 8188 */ +#define WF_PSE_TOP_LMAC3_PG_INFO_ADDR (WF_PSE_TOP_BASE + 0x18C) /* 818C */ +#define WF_PSE_TOP_PG_MDP_GROUP_ADDR (WF_PSE_TOP_BASE + 0x198) /* 8198 */ +#define WF_PSE_TOP_MDP_PG_INFO_ADDR (WF_PSE_TOP_BASE + 0x19C) /* 819C */ +#define WF_PSE_TOP_RL_BUF_CTRL_0_ADDR (WF_PSE_TOP_BASE + 0x1A0) /* 81A0 */ +#define WF_PSE_TOP_RL_BUF_CTRL_1_ADDR (WF_PSE_TOP_BASE + 0x1A4) /* 81A4 */ +#define WF_PSE_TOP_FL_QUE_CTRL_0_ADDR (WF_PSE_TOP_BASE + 0x1B0) /* 81B0 */ +#define WF_PSE_TOP_FL_QUE_CTRL_1_ADDR (WF_PSE_TOP_BASE + 0x1B4) /* 81B4 */ +#define WF_PSE_TOP_FL_QUE_CTRL_2_ADDR (WF_PSE_TOP_BASE + 0x1B8) /* 81B8 */ +#define WF_PSE_TOP_FL_QUE_CTRL_3_ADDR (WF_PSE_TOP_BASE + 0x1BC) /* 81BC */ +#define WF_PSE_TOP_PL_QUE_CTRL_0_ADDR (WF_PSE_TOP_BASE + 0x1C0) /* 81C0 */ +#define WF_PSE_TOP_PSE_LP_CTRL_ADDR (WF_PSE_TOP_BASE + 0x1D0) /* 81D0 */ +#define WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_ADDR (WF_PSE_TOP_BASE + 0x1E0)/* 81E0*/ +#define WF_PSE_TOP_PSE_CT_PRI_CTRL_ADDR (WF_PSE_TOP_BASE + 0x1EC) /* 81EC */ +#define WF_PSE_TOP_PLE_ENQ_PKT_NUM_ADDR (WF_PSE_TOP_BASE + 0x1F0) /* 81F0 */ +#define WF_PSE_TOP_CPU_ENQ_PKT_NUM_ADDR (WF_PSE_TOP_BASE + 0x1F4) /* 81F4 */ +#define WF_PSE_TOP_LMAC_ENQ_PKT_NUM_ADDR (WF_PSE_TOP_BASE + 0x1F8) /* 81F8 */ +#define WF_PSE_TOP_HIF_ENQ_PKT_NUM_ADDR (WF_PSE_TOP_BASE + 0x1FC) /* 81FC */ +#define WF_PSE_TOP_MDP_ENQ_PKT_NUM_ADDR (WF_PSE_TOP_BASE + 0x200) /* 8200 */ +#define WF_PSE_TOP_TIMEOUT_CTRL_ADDR (WF_PSE_TOP_BASE + 0x244) /* 8244 */ +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_ADDR (WF_PSE_TOP_BASE + 0x24C) /* 824C */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR (WF_PSE_TOP_BASE + 0x250) /* 8250 */ +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_ADDR (WF_PSE_TOP_BASE + 0x280)/* 8280*/ +#define WF_PSE_TOP_PSE_SER_CTRL_ADDR (WF_PSE_TOP_BASE + 0x2a0) /* 82A0 */ +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_ADDR (WF_PSE_TOP_BASE + 0x2b0) /* 82B0 */ +#define WF_PSE_TOP_PSE_MBIST_BSEL_ADDR (WF_PSE_TOP_BASE + 0x2b4) /* 82B4 */ +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_ADDR (WF_PSE_TOP_BASE + 0x2b8) /* 82B8\*/ +#define WF_PSE_TOP_SRAM_MBIST_BACKGROUND_ADDR \ +(WF_PSE_TOP_BASE + 0x2d0) /* 82D0 */ +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_ADDR (WF_PSE_TOP_BASE + 0x2d4)/* 82D4*/ +#define WF_PSE_TOP_SRAM_MBIST_DONE_ADDR (WF_PSE_TOP_BASE + 0x2d8) /* 82D8 */ +#define WF_PSE_TOP_SRAM_MBIST_FAIL_ADDR (WF_PSE_TOP_BASE + 0x2dc) /* 82DC */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR (WF_PSE_TOP_BASE + 0x2e0) /* 82E0 */ +#define WF_PSE_TOP_SRAM_MBIST_DELSEL_ADDR (WF_PSE_TOP_BASE + 0x2e4) /* 82E4 */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR (WF_PSE_TOP_BASE + 0x2e8)/* 82E8*/ +#define WF_PSE_TOP_SRAM_MBIST_DELSEL_1_ADDR (WF_PSE_TOP_BASE + 0x2f0) /* 82F0\ + */ +#define WF_PSE_TOP_PSE_SEEK_CR_00_ADDR (WF_PSE_TOP_BASE + 0x3d0) /* 83D0 */ +#define WF_PSE_TOP_PSE_SEEK_CR_01_ADDR (WF_PSE_TOP_BASE + 0x3d4) /* 83D4 */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_ADDR (WF_PSE_TOP_BASE + 0x3d8) /* 83D8 */ +#define WF_PSE_TOP_PSE_SEEK_CR_03_ADDR (WF_PSE_TOP_BASE + 0x3dc) /* 83DC */ +#define WF_PSE_TOP_PSE_SEEK_CR_04_ADDR (WF_PSE_TOP_BASE + 0x3e0) /* 83E0 */ +#define WF_PSE_TOP_PSE_SEEK_CR_05_ADDR (WF_PSE_TOP_BASE + 0x3e4) /* 83E4 */ +#define WF_PSE_TOP_PSE_SEEK_CR_06_ADDR (WF_PSE_TOP_BASE + 0x3e8) /* 83E8 */ +#define WF_PSE_TOP_PSE_SEEK_CR_07_ADDR (WF_PSE_TOP_BASE + 0x3ec) /* 83EC */ +#define WF_PSE_TOP_PSE_SEEK_CR_08_ADDR (WF_PSE_TOP_BASE + 0x3f0) /* 83F0 */ +#define WF_PSE_TOP_PSE_SEEK_CR_09_ADDR (WF_PSE_TOP_BASE + 0x3f4) /* 83F4 */ + +/* +* ---GC (0x820C8000 + 0x00)--- +* ALL_RESET[0] - (RW) Resets PSE logic and register +* LOGIC_RESET[1] - (RW) Resets PSE logic circuit +* INIT_DONE[2] - (RO) PSE control SRAM initialization +indicator +* RESERVED3[15..3] - (RO) Reserved bits +* SRAM_MBIST_RESET[16] - (RW) Reset control of SRAM MBIST (low active) +* RESERVED17[17] - (RO) Reserved bits +* DIS_PSE_DYN_CKG[18] - (RW) Disable control of wf_pse_top dynamic +* clock gating function +* RESERVED19[31..19] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_GC_DIS_PSE_DYN_CKG_ADDR WF_PSE_TOP_GC_ADDR +#define WF_PSE_TOP_GC_DIS_PSE_DYN_CKG_MASK 0x00040000 /* DIS_PSE_DYN_CKG[18] \ + */ +#define WF_PSE_TOP_GC_DIS_PSE_DYN_CKG_SHFT 18 +#define WF_PSE_TOP_GC_SRAM_MBIST_RESET_ADDR WF_PSE_TOP_GC_ADDR +#define WF_PSE_TOP_GC_SRAM_MBIST_RESET_MASK \ +0x00010000 /* SRAM_MBIST_RESET[16] */ +#define WF_PSE_TOP_GC_SRAM_MBIST_RESET_SHFT 16 +#define WF_PSE_TOP_GC_INIT_DONE_ADDR WF_PSE_TOP_GC_ADDR +#define WF_PSE_TOP_GC_INIT_DONE_MASK 0x00000004 /* INIT_DONE[2] */ +#define WF_PSE_TOP_GC_INIT_DONE_SHFT 2 +#define WF_PSE_TOP_GC_LOGIC_RESET_ADDR WF_PSE_TOP_GC_ADDR +#define WF_PSE_TOP_GC_LOGIC_RESET_MASK 0x00000002 /* LOGIC_RESET[1] */ +#define WF_PSE_TOP_GC_LOGIC_RESET_SHFT 1 +#define WF_PSE_TOP_GC_ALL_RESET_ADDR WF_PSE_TOP_GC_ADDR +#define WF_PSE_TOP_GC_ALL_RESET_MASK 0x00000001 /* ALL_RESET[0] */ +#define WF_PSE_TOP_GC_ALL_RESET_SHFT 0 + +/* +* ---PBUF_CTRL (0x820C8000 + 0x14)--- +* TOTAL_PAGE_NUM[11..0] - (RW) Total page numbers +* Set the total page before release PSE logic +* reset, and must not be changed after release logic reset. +* RESERVED12[16..12] - (RO) Reserved bits +* PBUF_OFFSET[25..17] - (RW) Packet buffer offset. +* Set the buffer offset before release PSE +* logic reset, and must not be changed after release logic reset. +* RESERVED26[30..26] - (RO) Reserved bits +* PAGE_SIZE_CFG[31] - (RW) Configures page size +* Set up the page size before releasing PSE +* logic reset; it should not be changed after logic reset is released. +*/ +#define WF_PSE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_ADDR WF_PSE_TOP_PBUF_CTRL_ADDR +#define WF_PSE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_MASK \ +0x80000000 /* PAGE_SIZE_CFG[31] */ +#define WF_PSE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_SHFT 31 +#define WF_PSE_TOP_PBUF_CTRL_PBUF_OFFSET_ADDR WF_PSE_TOP_PBUF_CTRL_ADDR +#define WF_PSE_TOP_PBUF_CTRL_PBUF_OFFSET_MASK \ +0x03FE0000 /* PBUF_OFFSET[25..17] */ +#define WF_PSE_TOP_PBUF_CTRL_PBUF_OFFSET_SHFT 17 +#define WF_PSE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_ADDR WF_PSE_TOP_PBUF_CTRL_ADDR +#define WF_PSE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_MASK \ +0x00000FFF /* TOTAL_PAGE_NUM[11..0] */ +#define WF_PSE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_SHFT 0 + +/* +* ---INT_N9_EN_MASK (0x820C8000 + 0x20)--- +* EN_CPU_Q0_NE[0] - (RW) CPU queue 0 not empty interrupt +* EN_CPU_Q1_NE[1] - (RW) CPU queue 1 not empty interrupt +* EN_CPU_Q2_NE[2] - (RW) CPU queue 2 not empty interrupt +* EN_CPU_Q3_NE[3] - (RW) CPU queue 3 not empty interrupt +* RESERVED4[11..4] - (RO) Reserved bits +* EN_LMAC_ENQ[12] - (RW) Enables LMAC enq interrupt +* EN_ERROR_INT[13] - (RW) Error condition interrupt status +* RESERVED14[15..14] - (RO) Reserved bits +* EN_TOGGLE_INT[16] - (RW) Data toggle of CR4 toggle register +(0xe0) +* EN_LMAC_EMPTY_FALL[17] - (RW) LMAC Buffer empty fall edge detect +* EN_LMAC_EMPTY_RAISE[18] - (RW) LMAC Buffer empty raise edge detect +* EN_HIF_Q0_NE[19] - (RW) HIF queue 0 not empty interrupt +* EN_HIF_Q1_NE[20] - (RW) HIF queue 1 not empty interrupt +* EN_HIF_Q2_NE[21] - (RW) HIF queue 2 not empty interrupt +* EN_HIF_Q3_NE[22] - (RW) HIF queue 3 not empty interrupt +* EN_HIF_Q4_NE[23] - (RW) HIF queue 4 not empty interrupt +* EN_HIF_Q5_NE[24] - (RW) HIF queue 5 not empty interrupt +* EN_HIF_Q6_NE[25] - (RW) HIF queue 6 not empty interrupt +* EN_HIF_Q7_NE[26] - (RW) HIF queue 7 not empty interrupt +* EN_HIF_Q8_NE[27] - (RW) HIF queue 8 not empty interrupt +* EN_HIF_Q9_NE[28] - (RW) HIF queue 9 not empty interrupt +* EN_HIF_Q10_NE[29] - (RW) HIF queue 10 not empty interrupt +* EN_HIF_Q11_NE[30] - (RW) HIF queue 11 not empty interrupt +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q11_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q11_NE_MASK \ +0x40000000 /* EN_HIF_Q11_NE[30] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q11_NE_SHFT 30 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q10_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q10_NE_MASK \ +0x20000000 /* EN_HIF_Q10_NE[29] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q10_NE_SHFT 29 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q9_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q9_NE_MASK \ +0x10000000 /* EN_HIF_Q9_NE[28] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q9_NE_SHFT 28 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q8_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q8_NE_MASK \ +0x08000000 /* EN_HIF_Q8_NE[27] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q8_NE_SHFT 27 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q7_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q7_NE_MASK \ +0x04000000 /* EN_HIF_Q7_NE[26] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q7_NE_SHFT 26 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q6_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q6_NE_MASK \ +0x02000000 /* EN_HIF_Q6_NE[25] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q6_NE_SHFT 25 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q5_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q5_NE_MASK \ +0x01000000 /* EN_HIF_Q5_NE[24] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q5_NE_SHFT 24 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q4_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q4_NE_MASK \ +0x00800000 /* EN_HIF_Q4_NE[23] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q4_NE_SHFT 23 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q3_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q3_NE_MASK \ +0x00400000 /* EN_HIF_Q3_NE[22] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q3_NE_SHFT 22 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q2_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q2_NE_MASK \ +0x00200000 /* EN_HIF_Q2_NE[21] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q2_NE_SHFT 21 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q1_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q1_NE_MASK \ +0x00100000 /* EN_HIF_Q1_NE[20] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q1_NE_SHFT 20 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q0_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q0_NE_MASK \ +0x00080000 /* EN_HIF_Q0_NE[19] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q0_NE_SHFT 19 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_EMPTY_RAISE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_EMPTY_RAISE_MASK \ +0x00040000 /* EN_LMAC_EMPTY_RAISE[18] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_EMPTY_RAISE_SHFT 18 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_EMPTY_FALL_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_EMPTY_FALL_MASK \ +0x00020000 /* EN_LMAC_EMPTY_FALL[17] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_EMPTY_FALL_SHFT 17 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_TOGGLE_INT_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_TOGGLE_INT_MASK \ +0x00010000 /* EN_TOGGLE_INT[16] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_TOGGLE_INT_SHFT 16 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_ERROR_INT_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_ERROR_INT_MASK \ +0x00002000 /* EN_ERROR_INT[13] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_ERROR_INT_SHFT 13 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_ENQ_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_ENQ_MASK \ +0x00001000 /* EN_LMAC_ENQ[12] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_ENQ_SHFT 12 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q3_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q3_NE_MASK \ +0x00000008 /* EN_CPU_Q3_NE[3] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q3_NE_SHFT 3 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q2_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q2_NE_MASK \ +0x00000004 /* EN_CPU_Q2_NE[2] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q2_NE_SHFT 2 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q1_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q1_NE_MASK \ +0x00000002 /* EN_CPU_Q1_NE[1] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q1_NE_SHFT 1 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q0_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q0_NE_MASK \ +0x00000001 /* EN_CPU_Q0_NE[0] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q0_NE_SHFT 0 + +/* +* ---INT_N9_STS (0x820C8000 + 0x24)--- +* CPU_Q0_NE[0] - (W1C) CPU queue 0 not empty interrupt status +* CPU_Q1_NE[1] - (W1C) CPU queue 1 not empty interrupt status +* CPU_Q2_NE[2] - (W1C) CPU queue 2 not empty interrupt status +* CPU_Q3_NE[3] - (W1C) CPU queue 3 not empty interrupt status +* RESERVED4[11..4] - (RO) Reserved bits +* LMAC_ENQ[12] - (W1C) LMAC enq interrupt status +* ERROR_INT[13] - (RO) Error condition interrupt status +* ERROR_1_INT[14] - (RO) Error condition interrupt status +* RESERVED15[15] - (RO) Reserved bits +* DATA_TOGGLE[16] - (W1C) Data toggle of CR4 toggle register +(0xe0) +* LMAC_EMPTY_FALL[17] - (W1C) LMAC Buffer empty fall edge detect +* LMAC_EMPTY_RAISE[18] - (W1C) LMAC Buffer empty raise edge detect +* HIF_Q0_NE[19] - (W1C) HIF queue 0 not empty interrupt status +* HIF_Q1_NE[20] - (W1C) HIF queue 1 not empty interrupt status +* HIF_Q2_NE[21] - (W1C) HIF queue 2 not empty interrupt status +* HIF_Q3_NE[22] - (W1C) HIF queue 3 not empty interrupt status +* HIF_Q4_NE[23] - (W1C) HIF queue 4 not empty interrupt status +* HIF_Q5_NE[24] - (W1C) HIF queue 5 not empty interrupt status +* HIF_Q6_NE[25] - (W1C) HIF queue 6 not empty interrupt status +* HIF_Q7_NE[26] - (W1C) HIF queue 7 not empty interrupt status +* HIF_Q8_NE[27] - (W1C) HIF queue 8 not empty interrupt status +* HIF_Q9_NE[28] - (W1C) HIF queue 9 not empty interrupt status +* HIF_Q10_NE[29] - (W1C) HIF queue 10 not empty interrupt status +* HIF_Q11_NE[30] - (W1C) HIF queue 11 not empty interrupt status +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q11_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q11_NE_MASK 0x40000000 /* HIF_Q11_NE[30] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q11_NE_SHFT 30 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q10_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q10_NE_MASK 0x20000000 /* HIF_Q10_NE[29] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q10_NE_SHFT 29 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q9_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q9_NE_MASK 0x10000000 /* HIF_Q9_NE[28] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q9_NE_SHFT 28 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q8_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q8_NE_MASK 0x08000000 /* HIF_Q8_NE[27] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q8_NE_SHFT 27 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q7_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q7_NE_MASK 0x04000000 /* HIF_Q7_NE[26] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q7_NE_SHFT 26 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q6_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q6_NE_MASK 0x02000000 /* HIF_Q6_NE[25] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q6_NE_SHFT 25 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q5_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q5_NE_MASK 0x01000000 /* HIF_Q5_NE[24] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q5_NE_SHFT 24 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q4_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q4_NE_MASK 0x00800000 /* HIF_Q4_NE[23] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q4_NE_SHFT 23 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q3_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q3_NE_MASK 0x00400000 /* HIF_Q3_NE[22] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q3_NE_SHFT 22 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q2_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q2_NE_MASK 0x00200000 /* HIF_Q2_NE[21] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q2_NE_SHFT 21 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q1_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q1_NE_MASK 0x00100000 /* HIF_Q1_NE[20] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q1_NE_SHFT 20 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q0_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q0_NE_MASK 0x00080000 /* HIF_Q0_NE[19] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q0_NE_SHFT 19 +#define WF_PSE_TOP_INT_N9_STS_LMAC_EMPTY_RAISE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_LMAC_EMPTY_RAISE_MASK \ +0x00040000 /* LMAC_EMPTY_RAISE[18] */ +#define WF_PSE_TOP_INT_N9_STS_LMAC_EMPTY_RAISE_SHFT 18 +#define WF_PSE_TOP_INT_N9_STS_LMAC_EMPTY_FALL_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_LMAC_EMPTY_FALL_MASK \ +0x00020000 /* LMAC_EMPTY_FALL[17] */ +#define WF_PSE_TOP_INT_N9_STS_LMAC_EMPTY_FALL_SHFT 17 +#define WF_PSE_TOP_INT_N9_STS_DATA_TOGGLE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_DATA_TOGGLE_MASK 0x00010000 /* DATA_TOGGLE[16]*/ +#define WF_PSE_TOP_INT_N9_STS_DATA_TOGGLE_SHFT 16 +#define WF_PSE_TOP_INT_N9_STS_ERROR_1_INT_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_ERROR_1_INT_MASK 0x00004000 /* ERROR_1_INT[14]*/ +#define WF_PSE_TOP_INT_N9_STS_ERROR_1_INT_SHFT 14 +#define WF_PSE_TOP_INT_N9_STS_ERROR_INT_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_ERROR_INT_MASK 0x00002000 /* ERROR_INT[13] */ +#define WF_PSE_TOP_INT_N9_STS_ERROR_INT_SHFT 13 +#define WF_PSE_TOP_INT_N9_STS_LMAC_ENQ_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_LMAC_ENQ_MASK 0x00001000 /* LMAC_ENQ[12] */ +#define WF_PSE_TOP_INT_N9_STS_LMAC_ENQ_SHFT 12 +#define WF_PSE_TOP_INT_N9_STS_CPU_Q3_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_CPU_Q3_NE_MASK 0x00000008 /* CPU_Q3_NE[3] */ +#define WF_PSE_TOP_INT_N9_STS_CPU_Q3_NE_SHFT 3 +#define WF_PSE_TOP_INT_N9_STS_CPU_Q2_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_CPU_Q2_NE_MASK 0x00000004 /* CPU_Q2_NE[2] */ +#define WF_PSE_TOP_INT_N9_STS_CPU_Q2_NE_SHFT 2 +#define WF_PSE_TOP_INT_N9_STS_CPU_Q1_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_CPU_Q1_NE_MASK 0x00000002 /* CPU_Q1_NE[1] */ +#define WF_PSE_TOP_INT_N9_STS_CPU_Q1_NE_SHFT 1 +#define WF_PSE_TOP_INT_N9_STS_CPU_Q0_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_CPU_Q0_NE_MASK 0x00000001 /* CPU_Q0_NE[0] */ +#define WF_PSE_TOP_INT_N9_STS_CPU_Q0_NE_SHFT 0 + +/* +* ---INT_N9_ERR_STS (0x820C8000 + 0x28)--- +* Q_CMD_ERR_P0[0] - (W1C) Queue command error interrupt status of +* port 0. Avoid unclear error flag, please clear flag when logic reset. +* Q_CMD_ERR_P1[1] - (W1C) Queue command error interrupt status of +* port 1. Avoid unclear error flag, please clear flag when logic reset. +* Q_CMD_ERR_P2[2] - (W1C) Queue command error interrupt status of +* port 2. Avoid unclear error flag, please clear flag when logic reset. +* Q_CMD_ERR_P3[3] - (W1C) Queue command error interrupt status of +* port 3. Avoid unclear error flag, please clear flag when logic reset. +* Q_CMD_ERR_P4[4] - (W1C) Queue command error interrupt status of +* port 4. Avoid unclear error flag, please clear flag when logic reset. +* Q_CMD_ERR_P5[5] - (W1C) Queue command error interrupt status of +* port 5. Avoid unclear error flag, please clear flag when logic reset. +* Q_CMD_ERR_P6[6] - (W1C) Queue command error interrupt status of +* port 6. Avoid unclear error flag, please clear flag when logic reset. +* RESERVED7[7] - (RO) Reserved bits +* PAGE_UDF_P0[8] - (W1C) Page underflow interrupt status of port +* 0. Avoid unclear error flag, please clear flag when logic reset. +* PAGE_UDF_P1[9] - (W1C) Page underflow interrupt status of port +* 1. Avoid unclear error flag, please clear flag when logic reset. +* PAGE_UDF_P2[10] - (W1C) Page underflow interrupt status of port +* 2. Avoid unclear error flag, please clear flag when logic reset. +* PAGE_UDF_P3[11] - (W1C) Page underflow interrupt status of port +* 3. Avoid unclear error flag, please clear flag when logic reset. +* PAGE_UDF_P4[12] - (W1C) Page underflow interrupt status of port +* 4. Avoid unclear error flag, please clear flag when logic reset. +* PAGE_UDF_P5[13] - (W1C) Page underflow interrupt status of port +* 5. Avoid unclear error flag, please clear flag when logic reset. +* PAGE_UDF_P6[14] - (W1C) Page underflow interrupt status of port +* 6. Avoid unclear error flag, please clear flag when logic reset. +* RESERVED15[15] - (RO) Reserved bits +* QUEUE_OPER_ERR_P0[16] - (W1C) Queue operation error of port 0. Avoid +* unclear error flag, please clear flag when logic reset. +* QUEUE_OPER_ERR_P1[17] - (W1C) Queue operation error of port 1. Avoid +* unclear error flag, please clear flag when logic reset. +* QUEUE_OPER_ERR_P2[18] - (W1C) Queue operation error of port 2. Avoid +* unclear error flag, please clear flag when logic reset. +* QUEUE_OPER_ERR_P3[19] - (W1C) Queue operation error of port 3. Avoid +* unclear error flag, please clear flag when logic reset. +* QUEUE_OPER_ERR_P4[20] - (W1C) Queue operation error of port 4. Avoid +* unclear error flag, please clear flag when logic reset. +* QUEUE_OPER_ERR_P5[21] - (W1C) Queue operation error of port 5. Avoid +* unclear error flag, please clear flag when logic reset. +* QUEUE_OPER_ERR_P6[22] - (W1C) Queue operation error of port 6. Avoid +* unclear error flag, please clear flag when logic reset. +* RESERVED23[23] - (RO) Reserved bits +* DATA_OPER_ERR_P0[24] - (W1C) Data operation error of port 0. Avoid +* unclear error flag, please clear flag when logic reset. +* DATA_OPER_ERR_P1[25] - (W1C) Data operation error of port 1. Avoid +* unclear error flag, please clear flag when logic reset. +* DATA_OPER_ERR_P2[26] - (W1C) Data operation error of port 2. Avoid +* unclear error flag, please clear flag when logic reset. +* DATA_OPER_ERR_P3[27] - (W1C) Data operation error of port 3. Avoid +* unclear error flag, please clear flag when logic reset. +* DATA_OPER_ERR_P4[28] - (W1C) Data operation error of port 4. Avoid +* unclear error flag, please clear flag when logic reset. +* DATA_OPER_ERR_P5[29] - (W1C) Data operation error of port 5. Avoid +* unclear error flag, please clear flag when logic reset. +* DATA_OPER_ERR_P6[30] - (W1C) Data operation error of port 6. Avoid +* unclear error flag, please clear flag when logic reset. +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P6_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P6_MASK \ +0x40000000 /* DATA_OPER_ERR_P6[30] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P6_SHFT 30 +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P5_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P5_MASK \ +0x20000000 /* DATA_OPER_ERR_P5[29] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P5_SHFT 29 +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P4_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P4_MASK \ +0x10000000 /* DATA_OPER_ERR_P4[28] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P4_SHFT 28 +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P3_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P3_MASK \ +0x08000000 /* DATA_OPER_ERR_P3[27] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P3_SHFT 27 +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P2_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P2_MASK \ +0x04000000 /* DATA_OPER_ERR_P2[26] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P2_SHFT 26 +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P1_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P1_MASK \ +0x02000000 /* DATA_OPER_ERR_P1[25] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P1_SHFT 25 +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P0_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P0_MASK \ +0x01000000 /* DATA_OPER_ERR_P0[24] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P0_SHFT 24 +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P6_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P6_MASK \ +0x00400000 /* QUEUE_OPER_ERR_P6[22] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P6_SHFT 22 +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P5_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P5_MASK \ +0x00200000 /* QUEUE_OPER_ERR_P5[21] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P5_SHFT 21 +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P4_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P4_MASK \ +0x00100000 /* QUEUE_OPER_ERR_P4[20] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P4_SHFT 20 +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P3_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P3_MASK \ +0x00080000 /* QUEUE_OPER_ERR_P3[19] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P3_SHFT 19 +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P2_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P2_MASK \ +0x00040000 /* QUEUE_OPER_ERR_P2[18] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P2_SHFT 18 +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P1_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P1_MASK \ +0x00020000 /* QUEUE_OPER_ERR_P1[17] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P1_SHFT 17 +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P0_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P0_MASK \ +0x00010000 /* QUEUE_OPER_ERR_P0[16] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P0_SHFT 16 +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P6_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P6_MASK \ +0x00004000 /* PAGE_UDF_P6[14] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P6_SHFT 14 +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P5_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P5_MASK \ +0x00002000 /* PAGE_UDF_P5[13] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P5_SHFT 13 +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P4_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P4_MASK \ +0x00001000 /* PAGE_UDF_P4[12] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P4_SHFT 12 +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P3_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P3_MASK \ +0x00000800 /* PAGE_UDF_P3[11] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P3_SHFT 11 +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P2_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P2_MASK \ +0x00000400 /* PAGE_UDF_P2[10] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P2_SHFT 10 +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P1_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P1_MASK \ +0x00000200 /* PAGE_UDF_P1[9] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P1_SHFT 9 +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P0_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P0_MASK \ +0x00000100 /* PAGE_UDF_P0[8] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P0_SHFT 8 +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P6_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P6_MASK \ +0x00000040 /* Q_CMD_ERR_P6[6] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P6_SHFT 6 +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P5_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P5_MASK \ +0x00000020 /* Q_CMD_ERR_P5[5] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P5_SHFT 5 +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P4_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P4_MASK \ +0x00000010 /* Q_CMD_ERR_P4[4] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P4_SHFT 4 +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P3_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P3_MASK \ +0x00000008 /* Q_CMD_ERR_P3[3] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P3_SHFT 3 +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P2_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P2_MASK \ +0x00000004 /* Q_CMD_ERR_P2[2] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P2_SHFT 2 +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P1_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P1_MASK \ +0x00000002 /* Q_CMD_ERR_P1[1] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P1_SHFT 1 +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P0_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P0_MASK \ +0x00000001 /* Q_CMD_ERR_P0[0] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P0_SHFT 0 + +/* +* ---INT_N9_ERR_MASK (0x820C8000 + 0x2C)--- +* EN_Q_CMD_ERR_P0[0] - (RW) Enable Queue command error interrupt +* status of port 0. Avoid unclear error flag, please clear flag when logic +reset. +* EN_Q_CMD_ERR_P1[1] - (RW) Enable Queue command error interrupt +* status of port 1. Avoid unclear error flag, please clear flag when logic +reset. +* EN_Q_CMD_ERR_P2[2] - (RW) Enable Queue command error interrupt +* status of port 2. Avoid unclear error flag, please clear flag when logic +reset. +* EN_Q_CMD_ERR_P3[3] - (RW) Enable Queue command error interrupt +* status of port 3. Avoid unclear error flag, please clear flag when logic +reset. +* EN_Q_CMD_ERR_P4[4] - (RW) Enable Queue command error interrupt +* status of port 4. Avoid unclear error flag, please clear flag when logic +reset. +* EN_Q_CMD_ERR_P5[5] - (RW) Enable Queue command error interrupt +* status of port 5. Avoid unclear error flag, please clear flag when logic +reset. +* EN_Q_CMD_ERR_P6[6] - (RW) Enable Queue command error interrupt +* status of port 6. Avoid unclear error flag, please clear flag when logic +reset. +* RESERVED7[7] - (RO) Reserved bits +* EN_PAGE_UDF_P0[8] - (RW) Enable Page underflow interrupt status +* of port 0. Avoid unclear error flag, please clear flag when logic reset. +* EN_PAGE_UDF_P1[9] - (RW) Enable Page underflow interrupt status +* of port 1. Avoid unclear error flag, please clear flag when logic reset. +* EN_PAGE_UDF_P2[10] - (RW) Enable Page underflow interrupt status +* of port 2. Avoid unclear error flag, please clear flag when logic reset. +* EN_PAGE_UDF_P3[11] - (RW) Enable Page underflow interrupt status +* of port 3. Avoid unclear error flag, please clear flag when logic reset. +* EN_PAGE_UDF_P4[12] - (RW) Enable Page underflow interrupt status +* of port 4. Avoid unclear error flag, please clear flag when logic reset. +* EN_PAGE_UDF_P5[13] - (RW) Enable Page underflow interrupt status +* of port 5. Avoid unclear error flag, please clear flag when logic reset. +* EN_PAGE_UDF_P6[14] - (RW) Enable Page underflow interrupt status +* of port 6. Avoid unclear error flag, please clear flag when logic reset. +* RESERVED15[15] - (RO) Reserved bits +* EN_QUEUE_OPER_ERR_P0[16] - (RW) Enable Queue operation error of port 0. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_QUEUE_OPER_ERR_P1[17] - (RW) Enable Queue operation error of port 1. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_QUEUE_OPER_ERR_P2[18] - (RW) Enable Queue operation error of port 2. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_QUEUE_OPER_ERR_P3[19] - (RW) Enable Queue operation error of port 3. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_QUEUE_OPER_ERR_P4[20] - (RW) Enable Queue operation error of port 4. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_QUEUE_OPER_ERR_P5[21] - (RW) Enable Queue operation error of port 5. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_QUEUE_OPER_ERR_P6[22] - (RW) Enable Queue operation error of port 6. +* Avoid unclear error flag, please clear flag when logic reset. +* RESERVED23[23] - (RO) Reserved bits +* EN_DATA_OPER_ERR_P0[24] - (RW) Enable Data operation error of port 0. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_DATA_OPER_ERR_P1[25] - (RW) Enable Data operation error of port 1. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_DATA_OPER_ERR_P2[26] - (RW) Enable Data operation error of port 2. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_DATA_OPER_ERR_P3[27] - (RW) Enable Data operation error of port 3. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_DATA_OPER_ERR_P4[28] - (RW) Enable Data operation error of port 4. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_DATA_OPER_ERR_P5[29] - (RW) Enable Data operation error of port 5. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_DATA_OPER_EN_ERR_P6[30] - (RW) Enable Data operation error of port 6. +* Avoid unclear error flag, please clear flag when logic reset. +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_EN_ERR_P6_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_EN_ERR_P6_MASK \ +0x40000000 /* EN_DATA_OPER_EN_ERR_P6[30] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_EN_ERR_P6_SHFT 30 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P5_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P5_MASK \ +0x20000000 /* EN_DATA_OPER_ERR_P5[29] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P5_SHFT 29 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P4_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P4_MASK \ +0x10000000 /* EN_DATA_OPER_ERR_P4[28] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P4_SHFT 28 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P3_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P3_MASK \ +0x08000000 /* EN_DATA_OPER_ERR_P3[27] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P3_SHFT 27 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P2_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P2_MASK \ +0x04000000 /* EN_DATA_OPER_ERR_P2[26] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P2_SHFT 26 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P1_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P1_MASK \ +0x02000000 /* EN_DATA_OPER_ERR_P1[25] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P1_SHFT 25 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P0_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P0_MASK \ +0x01000000 /* EN_DATA_OPER_ERR_P0[24] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P0_SHFT 24 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P6_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P6_MASK \ +0x00400000 /* EN_QUEUE_OPER_ERR_P6[22] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P6_SHFT 22 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P5_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P5_MASK \ +0x00200000 /* EN_QUEUE_OPER_ERR_P5[21] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P5_SHFT 21 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P4_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P4_MASK \ +0x00100000 /* EN_QUEUE_OPER_ERR_P4[20] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P4_SHFT 20 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P3_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P3_MASK \ +0x00080000 /* EN_QUEUE_OPER_ERR_P3[19] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P3_SHFT 19 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P2_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P2_MASK \ +0x00040000 /* EN_QUEUE_OPER_ERR_P2[18] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P2_SHFT 18 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P1_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P1_MASK \ +0x00020000 /* EN_QUEUE_OPER_ERR_P1[17] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P1_SHFT 17 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P0_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P0_MASK \ +0x00010000 /* EN_QUEUE_OPER_ERR_P0[16] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P0_SHFT 16 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P6_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P6_MASK \ +0x00004000 /* EN_PAGE_UDF_P6[14] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P6_SHFT 14 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P5_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P5_MASK \ +0x00002000 /* EN_PAGE_UDF_P5[13] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P5_SHFT 13 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P4_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P4_MASK \ +0x00001000 /* EN_PAGE_UDF_P4[12] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P4_SHFT 12 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P3_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P3_MASK \ +0x00000800 /* EN_PAGE_UDF_P3[11] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P3_SHFT 11 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P2_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P2_MASK \ +0x00000400 /* EN_PAGE_UDF_P2[10] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P2_SHFT 10 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P1_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P1_MASK \ +0x00000200 /* EN_PAGE_UDF_P1[9] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P1_SHFT 9 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P0_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P0_MASK \ +0x00000100 /* EN_PAGE_UDF_P0[8] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P0_SHFT 8 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P6_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P6_MASK \ +0x00000040 /* EN_Q_CMD_ERR_P6[6] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P6_SHFT 6 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P5_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P5_MASK \ +0x00000020 /* EN_Q_CMD_ERR_P5[5] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P5_SHFT 5 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P4_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P4_MASK \ +0x00000010 /* EN_Q_CMD_ERR_P4[4] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P4_SHFT 4 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P3_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P3_MASK \ +0x00000008 /* EN_Q_CMD_ERR_P3[3] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P3_SHFT 3 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P2_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P2_MASK \ +0x00000004 /* EN_Q_CMD_ERR_P2[2] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P2_SHFT 2 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P1_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P1_MASK \ +0x00000002 /* EN_Q_CMD_ERR_P1[1] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P1_SHFT 1 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P0_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P0_MASK \ +0x00000001 /* EN_Q_CMD_ERR_P0[0] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P0_SHFT 0 + +/* +* ---INT_N9_ERR1_STS (0x820C8000 + 0x30)--- +* WDT_ERR_P0[0] - (W1C) Port state watch dog timeout error +* interrupt status of port 0. Avoid unclear error flag, please clear flag when +* logic reset. +* WDT_ERR_P1[1] - (W1C) Port state watch dog timeout error +* interrupt status of port 1. Avoid unclear error flag, please clear flag when +* logic reset. +* WDT_ERR_P2[2] - (W1C) Port state watch dog timeout error +* interrupt status of port 2. Avoid unclear error flag, please clear flag when +* logic reset. +* WDT_ERR_P3[3] - (W1C) Port state watch dog timeout error +* interrupt status of port 3. Avoid unclear error flag, please clear flag when +* logic reset. +* WDT_ERR_P4[4] - (W1C) Port state watch dog timeout error +* interrupt status of port 4. Avoid unclear error flag, please clear flag when +* logic reset. +* WDT_ERR_P5[5] - (W1C) Port state watch dog timeout error +* interrupt status of port 5. Avoid unclear error flag, please clear flag when +* logic reset. +* WDT_ERR_P6[6] - (W1C) Port state watch dog timeout error +* interrupt status of port 6. Avoid unclear error flag, please clear flag when +* logic reset. +* RESERVED7[7] - (RO) Reserved bits +* FL_HANG_ERR[8] - (W1C) Frame link FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* PL_HANG_ERR[9] - (W1C) Page link FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* DOUBLE_RLS_ERR[10] - (W1C) Double release error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* FREE_HEAD_TAIL_ERR[11] - (W1C) Free head/tail error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* FL_QSTRUCT_ERR[12] - (W1C) Frame Link queue NULL error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* RESERVED13[31..13] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_INT_N9_ERR1_STS_FL_QSTRUCT_ERR_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_FL_QSTRUCT_ERR_MASK \ +0x00001000 /* FL_QSTRUCT_ERR[12] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_FL_QSTRUCT_ERR_SHFT 12 +#define WF_PSE_TOP_INT_N9_ERR1_STS_FREE_HEAD_TAIL_ERR_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_FREE_HEAD_TAIL_ERR_MASK \ +0x00000800 /* FREE_HEAD_TAIL_ERR[11] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_FREE_HEAD_TAIL_ERR_SHFT 11 +#define WF_PSE_TOP_INT_N9_ERR1_STS_DOUBLE_RLS_ERR_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_DOUBLE_RLS_ERR_MASK \ +0x00000400 /* DOUBLE_RLS_ERR[10] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_DOUBLE_RLS_ERR_SHFT 10 +#define WF_PSE_TOP_INT_N9_ERR1_STS_PL_HANG_ERR_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_PL_HANG_ERR_MASK \ +0x00000200 /* PL_HANG_ERR[9] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_PL_HANG_ERR_SHFT 9 +#define WF_PSE_TOP_INT_N9_ERR1_STS_FL_HANG_ERR_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_FL_HANG_ERR_MASK \ +0x00000100 /* FL_HANG_ERR[8] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_FL_HANG_ERR_SHFT 8 +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P6_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P6_MASK \ +0x00000040 /* WDT_ERR_P6[6] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P6_SHFT 6 +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P5_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P5_MASK \ +0x00000020 /* WDT_ERR_P5[5] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P5_SHFT 5 +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P4_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P4_MASK \ +0x00000010 /* WDT_ERR_P4[4] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P4_SHFT 4 +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P3_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P3_MASK \ +0x00000008 /* WDT_ERR_P3[3] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P3_SHFT 3 +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P2_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P2_MASK \ +0x00000004 /* WDT_ERR_P2[2] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P2_SHFT 2 +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P1_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P1_MASK \ +0x00000002 /* WDT_ERR_P1[1] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P1_SHFT 1 +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P0_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P0_MASK \ +0x00000001 /* WDT_ERR_P0[0] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P0_SHFT 0 + +/* +* ---INT_N9_ERR1_MASK (0x820C8000 + 0x34)--- +* EN_WDT_ERR_P0[0] - (RW) Enable Port state watch dog timeout +* error interrupt status of port 0. Avoid unclear error flag, please clear flag +* when logic reset. +* EN_WDT_ERR_P1[1] - (RW) Enable Port state watch dog timeout +* error interrupt status of port 1. Avoid unclear error flag, please clear flag +* when logic reset. +* EN_WDT_ERR_P2[2] - (RW) Enable Port state watch dog timeout +* error interrupt status of port 2. Avoid unclear error flag, please clear flag +* when logic reset. +* EN_WDT_ERR_P3[3] - (RW) Enable Port state watch dog timeout +* error interrupt status of port 3. Avoid unclear error flag, please clear flag +* when logic reset. +* EN_WDT_ERR_P4[4] - (RW) Enable Port state watch dog timeout +* error interrupt status of port 4. Avoid unclear error flag, please clear flag +* when logic reset. +* EN_WDT_ERR_P5[5] - (RW) Enable Port state watch dog timeout +* error interrupt status of port 5. Avoid unclear error flag, please clear flag +* when logic reset. +* EN_WDT_ERR_P6[6] - (RW) Enable Port state watch dog timeout +* error interrupt status of port 6. Avoid unclear error flag, please clear flag +* when logic reset. +* RESERVED7[7] - (RO) Reserved bits +* EN_FL_HANG_ERR[8] - (RW) Enable Frame link FSM hang error +* interrupt. Avoid unclear error flag, please clear flag when logic reset. +* PL_HANGEN__ERR[9] - (RW) Enable Page link FSM hang error +* interrupt. Avoid unclear error flag, please clear flag when logic reset. +* EN_DOUBLE_RLS_ERR[10] - (RW) Enable Double release error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_FREE_HEAD_TAIL_ERR[11] - (RW) Enable Free head/tail error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_FL_QSTRTUT_ERR[12] - (RW) Enable Frame Link queue NULL error +* interrupt. Avoid unclear error flag, please clear flag when logic reset. +* RESERVED13[31..13] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FL_QSTRTUT_ERR_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FL_QSTRTUT_ERR_MASK \ +0x00001000 /* EN_FL_QSTRTUT_ERR[12] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FL_QSTRTUT_ERR_SHFT 12 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FREE_HEAD_TAIL_ERR_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FREE_HEAD_TAIL_ERR_MASK \ +0x00000800 /* EN_FREE_HEAD_TAIL_ERR[11] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FREE_HEAD_TAIL_ERR_SHFT 11 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_DOUBLE_RLS_ERR_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_DOUBLE_RLS_ERR_MASK \ +0x00000400 /* EN_DOUBLE_RLS_ERR[10] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_DOUBLE_RLS_ERR_SHFT 10 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_PL_HANGEN__ERR_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_PL_HANGEN__ERR_MASK \ +0x00000200 /* PL_HANGEN__ERR[9] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_PL_HANGEN__ERR_SHFT 9 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FL_HANG_ERR_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FL_HANG_ERR_MASK \ +0x00000100 /* EN_FL_HANG_ERR[8] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FL_HANG_ERR_SHFT 8 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P6_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P6_MASK \ +0x00000040 /* EN_WDT_ERR_P6[6] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P6_SHFT 6 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P5_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P5_MASK \ +0x00000020 /* EN_WDT_ERR_P5[5] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P5_SHFT 5 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P4_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P4_MASK \ +0x00000010 /* EN_WDT_ERR_P4[4] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P4_SHFT 4 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P3_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P3_MASK \ +0x00000008 /* EN_WDT_ERR_P3[3] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P3_SHFT 3 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P2_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P2_MASK \ +0x00000004 /* EN_WDT_ERR_P2[2] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P2_SHFT 2 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P1_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P1_MASK \ +0x00000002 /* EN_WDT_ERR_P1[1] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P1_SHFT 1 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P0_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P0_MASK \ +0x00000001 /* EN_WDT_ERR_P0[0] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P0_SHFT 0 + +/* +* ---C_GET_FID_0 (0x820C8000 + 0x40)--- +* QUEUE_FRAME_ID[15..0] - (RW) Frame ID for get command +* At GET_FRAME_TYPE = 2'h0/2'h1: +* QUEUE_FRAME_ID[15:14] = PID +* 2'h0: HIF port +* 2'h1: CPU port +* 2'h2: LMAC port +* QUEUE_FRAME_ID[9:0] = WLANID +* At GET_FRAME_TYPE = 2'h2/2'h3: +* QUEUE_FRAME_ID[11:0] = reference FID +* GET_FRAME_TYPE[19..16] - (RW) GET_SUB_TYPE +* RESERVED20[23..20] - (RO) Reserved bits +* GET_FRAME_QID[30..24] - (RW) Queue ID vlaue +* EXECUTE[31] - (A0) Executes command +*/ +#define WF_PSE_TOP_C_GET_FID_0_EXECUTE_ADDR WF_PSE_TOP_C_GET_FID_0_ADDR +#define WF_PSE_TOP_C_GET_FID_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PSE_TOP_C_GET_FID_0_EXECUTE_SHFT 31 +#define WF_PSE_TOP_C_GET_FID_0_GET_FRAME_QID_ADDR WF_PSE_TOP_C_GET_FID_0_ADDR +#define WF_PSE_TOP_C_GET_FID_0_GET_FRAME_QID_MASK \ +0x7F000000 /* GET_FRAME_QID[30..24] */ +#define WF_PSE_TOP_C_GET_FID_0_GET_FRAME_QID_SHFT 24 +#define WF_PSE_TOP_C_GET_FID_0_GET_FRAME_TYPE_ADDR WF_PSE_TOP_C_GET_FID_0_ADDR +#define WF_PSE_TOP_C_GET_FID_0_GET_FRAME_TYPE_MASK \ +0x000F0000 /* GET_FRAME_TYPE[19..16] */ +#define WF_PSE_TOP_C_GET_FID_0_GET_FRAME_TYPE_SHFT 16 +#define WF_PSE_TOP_C_GET_FID_0_QUEUE_FRAME_ID_ADDR WF_PSE_TOP_C_GET_FID_0_ADDR +#define WF_PSE_TOP_C_GET_FID_0_QUEUE_FRAME_ID_MASK \ +0x0000FFFF /* QUEUE_FRAME_ID[15..0] */ +#define WF_PSE_TOP_C_GET_FID_0_QUEUE_FRAME_ID_SHFT 0 + +/* +* ---C_GET_FID_1 (0x820C8000 + 0x44)--- +* GET_RETURN_FID[11..0] - (RO) Return frame ID +* RESERVED12[14..12] - (RO) Reserved bits +* END[15] - (RO) Return frame ID is end FID +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_C_GET_FID_1_END_ADDR WF_PSE_TOP_C_GET_FID_1_ADDR +#define WF_PSE_TOP_C_GET_FID_1_END_MASK 0x00008000 /* END[15] */ +#define WF_PSE_TOP_C_GET_FID_1_END_SHFT 15 +#define WF_PSE_TOP_C_GET_FID_1_GET_RETURN_FID_ADDR WF_PSE_TOP_C_GET_FID_1_ADDR +#define WF_PSE_TOP_C_GET_FID_1_GET_RETURN_FID_MASK \ +0x00000FFF /* GET_RETURN_FID[11..0] */ +#define WF_PSE_TOP_C_GET_FID_1_GET_RETURN_FID_SHFT 0 + +/* +* ---C_EN_QUEUE_0 (0x820C8000 + 0x60)--- +* DST_WLANID[9..0] - (RW) Destination WLANID for enqueue +* RESERVED10[13..10] - (RO) Reserved bits +* DST_PID[15..14] - (RW) Destination port ID for enqueue +* SUB_TYPE[19..16] - (RW) Sub-type of enqueue command +* RESERVED20[22..20] - (RO) Reserved bits +* DELAY_ENQ[23] - (RW) Delays enqueue +* DST_QID[30..24] - (RW) Destination queue ID for enqueue +* EXECUTE[31] - (A0) Executes command +*/ +#define WF_PSE_TOP_C_EN_QUEUE_0_EXECUTE_ADDR WF_PSE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PSE_TOP_C_EN_QUEUE_0_EXECUTE_SHFT 31 +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_QID_ADDR WF_PSE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_QID_MASK 0x7F000000 /* DST_QID[30..24] */ +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_QID_SHFT 24 +#define WF_PSE_TOP_C_EN_QUEUE_0_DELAY_ENQ_ADDR WF_PSE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_0_DELAY_ENQ_MASK 0x00800000 /* DELAY_ENQ[23] */ +#define WF_PSE_TOP_C_EN_QUEUE_0_DELAY_ENQ_SHFT 23 +#define WF_PSE_TOP_C_EN_QUEUE_0_SUB_TYPE_ADDR WF_PSE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_0_SUB_TYPE_MASK 0x000F0000 /* SUB_TYPE[19..16] \ + */ +#define WF_PSE_TOP_C_EN_QUEUE_0_SUB_TYPE_SHFT 16 +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_PID_ADDR WF_PSE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_PID_MASK 0x0000C000 /* DST_PID[15..14] */ +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_PID_SHFT 14 +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_WLANID_ADDR WF_PSE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_WLANID_MASK \ +0x000003FF /* DST_WLANID[9..0] */ +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_WLANID_SHFT 0 + +/* +* ---C_EN_QUEUE_1 (0x820C8000 + 0x64)--- +* CUR_LIST_FID_START[11..0] - (RW) Start frame ID of enqueue operation +* list, enqueue FID of enqueue operation +* RESERVED12[15..12] - (RO) Reserved bits +* CUR_LIST_FID_END[27..16] - (RW) End frame ID of enqueue operation list +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_END_ADDR \ +WF_PSE_TOP_C_EN_QUEUE_1_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_END_MASK \ +0x0FFF0000 /* CUR_LIST_FID_END[27..16] */ +#define WF_PSE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_END_SHFT 16 +#define WF_PSE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_START_ADDR \ +WF_PSE_TOP_C_EN_QUEUE_1_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_START_MASK \ +0x00000FFF /* CUR_LIST_FID_START[11..0] */ +#define WF_PSE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_START_SHFT 0 + +/* +* ---C_EN_QUEUE_2 (0x820C8000 + 0x68)--- +* TARGET_FID[11..0] - (RW) Target reference FID for enqueue +operation +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_C_EN_QUEUE_2_TARGET_FID_ADDR WF_PSE_TOP_C_EN_QUEUE_2_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_2_TARGET_FID_MASK \ +0x00000FFF /* TARGET_FID[11..0] */ +#define WF_PSE_TOP_C_EN_QUEUE_2_TARGET_FID_SHFT 0 + +/* +* ---C_DE_QUEUE_0 (0x820C8000 + 0x80)--- +* SRC_WLANID[9..0] - (RW) Source WLAN ID for dequeue command +* RESERVED10[13..10] - (RO) Reserved bits +* SRC_PID[15..14] - (RW) Source port ID for dequeue command +* DEQ_SUB_TYPE[19..16] - (RW) Dequeue subtype of dequeue command +* ENQ_SUB_TYPE[22..20] - (RW) Enqueue subtype of enqueue command +* Only valid in Deq&Enq type. +* ENQ_VLD[23] - (RW) Deq&Enq command valid +* SRC_QID[30..24] - (RW) Source queue ID for dequeue command +* EXECUTE[31] - (A0) Executes dequeue command +*/ +#define WF_PSE_TOP_C_DE_QUEUE_0_EXECUTE_ADDR WF_PSE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PSE_TOP_C_DE_QUEUE_0_EXECUTE_SHFT 31 +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_QID_ADDR WF_PSE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_QID_MASK 0x7F000000 /* SRC_QID[30..24] */ +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_QID_SHFT 24 +#define WF_PSE_TOP_C_DE_QUEUE_0_ENQ_VLD_ADDR WF_PSE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_0_ENQ_VLD_MASK 0x00800000 /* ENQ_VLD[23] */ +#define WF_PSE_TOP_C_DE_QUEUE_0_ENQ_VLD_SHFT 23 +#define WF_PSE_TOP_C_DE_QUEUE_0_ENQ_SUB_TYPE_ADDR WF_PSE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_0_ENQ_SUB_TYPE_MASK \ +0x00700000 /* ENQ_SUB_TYPE[22..20] */ +#define WF_PSE_TOP_C_DE_QUEUE_0_ENQ_SUB_TYPE_SHFT 20 +#define WF_PSE_TOP_C_DE_QUEUE_0_DEQ_SUB_TYPE_ADDR WF_PSE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_0_DEQ_SUB_TYPE_MASK \ +0x000F0000 /* DEQ_SUB_TYPE[19..16] */ +#define WF_PSE_TOP_C_DE_QUEUE_0_DEQ_SUB_TYPE_SHFT 16 +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_PID_ADDR WF_PSE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_PID_MASK 0x0000C000 /* SRC_PID[15..14] */ +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_PID_SHFT 14 +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_WLANID_ADDR WF_PSE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_WLANID_MASK \ +0x000003FF /* SRC_WLANID[9..0] */ +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_WLANID_SHFT 0 + +/* +* ---C_DE_QUEUE_1 (0x820C8000 + 0x84)--- +* CUR_LIST_FID_START[11..0] - (RW) Start frame ID of dequeue operation +* list, enqueue start FID of enqueue operation +* Only valid in Deq&Enq type. +* RESERVED12[15..12] - (RO) Reserved bits +* CUR_LIST_FID_END[27..16] - (RW) End framd ID of dequeue operation list, +* enqueue end FID of enqueue operation +* Only valid in Deq&Enq type. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_END_ADDR \ +WF_PSE_TOP_C_DE_QUEUE_1_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_END_MASK \ +0x0FFF0000 /* CUR_LIST_FID_END[27..16] */ +#define WF_PSE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_END_SHFT 16 +#define WF_PSE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_START_ADDR \ +WF_PSE_TOP_C_DE_QUEUE_1_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_START_MASK \ +0x00000FFF /* CUR_LIST_FID_START[11..0] */ +#define WF_PSE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_START_SHFT 0 + +/* +* ---C_DE_QUEUE_2 (0x820C8000 + 0x88)--- +* DEQ_ENQ_DST_WLANID[9..0] - (RW) Destination WLAN ID for enqueue command +* Only valid in Deq&Enq type. +* RESERVED10[13..10] - (RO) Reserved bits +* DEQ_ENQ_DST_PID[15..14] - (RW) Destination port ID for dequeue command +* RESERVED16[23..16] - (RO) Reserved bits +* DEQ_ENQ_DST_QID[30..24] - (RW) Destination queue ID for enqueue command +* Only valid in Deq&Enq type. +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_QID_ADDR \ +WF_PSE_TOP_C_DE_QUEUE_2_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_QID_MASK \ +0x7F000000 /* DEQ_ENQ_DST_QID[30..24] */ +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_QID_SHFT 24 +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_PID_ADDR \ +WF_PSE_TOP_C_DE_QUEUE_2_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_PID_MASK \ +0x0000C000 /* DEQ_ENQ_DST_PID[15..14] */ +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_PID_SHFT 14 +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_WLANID_ADDR \ +WF_PSE_TOP_C_DE_QUEUE_2_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_WLANID_MASK \ +0x000003FF /* DEQ_ENQ_DST_WLANID[9..0] */ +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_WLANID_SHFT 0 + +/* +* ---C_DE_QUEUE_3 (0x820C8000 + 0x8c)--- +* DEQ_HEAD_FDI[11..0] - (RO) Head FID got from dequeue command +* RESERVED12[14..12] - (RO) Reserved bits +* DEQ_EMPTY[15] - (RO) Queue empty after dequeue command is +executed +* DEQ_TAIL_FID[27..16] - (RO) Last FID got from dequeue command +* RESERVED28[30..28] - (RO) Reserved bits +* BUSY[31] - (RO) Dequeue execute busy +*/ +#define WF_PSE_TOP_C_DE_QUEUE_3_BUSY_ADDR WF_PSE_TOP_C_DE_QUEUE_3_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_3_BUSY_MASK 0x80000000 /* BUSY[31] */ +#define WF_PSE_TOP_C_DE_QUEUE_3_BUSY_SHFT 31 +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_TAIL_FID_ADDR WF_PSE_TOP_C_DE_QUEUE_3_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_TAIL_FID_MASK \ +0x0FFF0000 /* DEQ_TAIL_FID[27..16] */ +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_TAIL_FID_SHFT 16 +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_EMPTY_ADDR WF_PSE_TOP_C_DE_QUEUE_3_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_EMPTY_MASK 0x00008000 /* DEQ_EMPTY[15] */ +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_EMPTY_SHFT 15 +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_HEAD_FDI_ADDR WF_PSE_TOP_C_DE_QUEUE_3_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_HEAD_FDI_MASK \ +0x00000FFF /* DEQ_HEAD_FDI[11..0] */ +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_HEAD_FDI_SHFT 0 + +/* +* ---C_DE_QUEUE_4 (0x820C8000 + 0x90)--- +* DEQ_ENQ_REF_FID[11..0] - (RW) Reference frame ID for enqueue command +* Only valid in Deq&Enq type. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_C_DE_QUEUE_4_DEQ_ENQ_REF_FID_ADDR \ +WF_PSE_TOP_C_DE_QUEUE_4_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_4_DEQ_ENQ_REF_FID_MASK \ +0x00000FFF /* DEQ_ENQ_REF_FID[11..0] */ +#define WF_PSE_TOP_C_DE_QUEUE_4_DEQ_ENQ_REF_FID_SHFT 0 + +/* +* ---ALLOCATE_0 (0x820C8000 + 0xA0)--- +* ALLOCATE_FRAME_LENGTH[13..0] - (RW) Allocate frame length +* Unit: DW (4 bytes) +* RESERVED14[15..14] - (RO) Reserved bits +* ALLOCATE_QID[20..16] - (RW) QID used for allocate buffer +* RESERVED21[30..21] - (RO) Reserved bits +* EXECUTE[31] - (A0) Executes allocate buffer command +*/ +#define WF_PSE_TOP_ALLOCATE_0_EXECUTE_ADDR WF_PSE_TOP_ALLOCATE_0_ADDR +#define WF_PSE_TOP_ALLOCATE_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PSE_TOP_ALLOCATE_0_EXECUTE_SHFT 31 +#define WF_PSE_TOP_ALLOCATE_0_ALLOCATE_QID_ADDR WF_PSE_TOP_ALLOCATE_0_ADDR +#define WF_PSE_TOP_ALLOCATE_0_ALLOCATE_QID_MASK \ +0x001F0000 /* ALLOCATE_QID[20..16] */ +#define WF_PSE_TOP_ALLOCATE_0_ALLOCATE_QID_SHFT 16 +#define WF_PSE_TOP_ALLOCATE_0_ALLOCATE_FRAME_LENGTH_ADDR \ +WF_PSE_TOP_ALLOCATE_0_ADDR +#define WF_PSE_TOP_ALLOCATE_0_ALLOCATE_FRAME_LENGTH_MASK \ +0x00003FFF /* ALLOCATE_FRAME_LENGTH[13..0] */ +#define WF_PSE_TOP_ALLOCATE_0_ALLOCATE_FRAME_LENGTH_SHFT 0 + +/* +* ---ALLOCATE_1 (0x820C8000 + 0xA4)--- +* ALLOCATE_FID[11..0] - (RO) Return frame ID for allocate buffer +command +* RESERVED12[30..12] - (RO) Reserved bits +* EXECUTE[31] - (RO) Execute status of allocate buffer +command +*/ +#define WF_PSE_TOP_ALLOCATE_1_EXECUTE_ADDR WF_PSE_TOP_ALLOCATE_1_ADDR +#define WF_PSE_TOP_ALLOCATE_1_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PSE_TOP_ALLOCATE_1_EXECUTE_SHFT 31 +#define WF_PSE_TOP_ALLOCATE_1_ALLOCATE_FID_ADDR WF_PSE_TOP_ALLOCATE_1_ADDR +#define WF_PSE_TOP_ALLOCATE_1_ALLOCATE_FID_MASK \ +0x00000FFF /* ALLOCATE_FID[11..0] */ +#define WF_PSE_TOP_ALLOCATE_1_ALLOCATE_FID_SHFT 0 + +/* +* ---QUEUE_EMPTY (0x820C8000 + 0xB0)--- +* CPU_Q0_EMPTY[0] - (RO) CPU queue 0 empty status +* CPU_Q1_EMPTY[1] - (RO) CPU queue 1 empty status +* CPU_Q2_EMPTY[2] - (RO) CPU queue 2 empty status +* CPU_Q3_EMPTY[3] - (RO) CPU queue 3 empty status +* HIF_8_EMPTY[4] - (RO) HIF queue 8 empty status +* HIF_9_EMPTY[5] - (RO) HIF queue 9 empty status +* HIF_10_EMPTY[6] - (RO) HIF queue 10 empty status +* HIF_11_EMPTY[7] - (RO) HIF queue 11 empty status +* HIF_0_EMPTY[8] - (RO) HIF queue 0 empty status +* HIF_1_EMPTY[9] - (RO) HIF queue 1 empty status +* HIF_2_EMPTY[10] - (RO) HIF queue 2 empty status +* HIF_3_EMPTY[11] - (RO) HIF queue 3 empty status +* HIF_4_EMPTY[12] - (RO) HIF queue 4 empty status +* HIF_5_EMPTY[13] - (RO) HIF queue 5 empty status +* HIF_6_EMPTY[14] - (RO) HIF queue 6 empty status +* HIF_7_EMPTY[15] - (RO) HIF queue 7 empty status +* LMAC_TX_QUEUE_EMPTY[16] - (RO) LMAC TX queue empty status +* MDP_TX_QUEUE_EMPTY[17] - (RO) MDP TX queue empty status +* MDP_RX_QUEUE_EMPTY[18] - (RO) MDP RX queue empty status +* SEC_TX_QUEUE_EMPTY[19] - (RO) SEC TX queue empty status +* SEC_RX_QUEUE_EMPTY[20] - (RO) SEC RX queue empty status +* SFD_PARK_QUEUE_EMPTY[21] - (RO) SFD PARK queue empty status +* MDP_TXIOC_QUEUE_EMPTY[22] - (RO) MDP TXIOC queue empty status +* MDP_RXIOC_QUEUE_EMPTY[23] - (RO) MDP RXIOC queue empty status +* MDP_TX1_QUEUE_EMPTY[24] - (RO) MDP TX queue empty status for Band 1 +* SEC_TX1_QUEUE_EMPTY[25] - (RO) SEC TX queue empty status for Band 1 +* MDP_TXIOC1_QUEUE_EMPTY[26] - (RO) MDP TXIOC queue empty status for Band 1 +* MDP_RXIOC1_QUEUE_EMPTY[27] - (RO) MDP RXIOC queue empty status for Band 1 +* RESERVED28[30..28] - (RO) Reserved bits +* RLS_Q_EMTPY[31] - (RO) Release queue empty status +*/ +#define WF_PSE_TOP_QUEUE_EMPTY_RLS_Q_EMTPY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_RLS_Q_EMTPY_MASK 0x80000000 /* RLS_Q_EMTPY[31]\ + */ +#define WF_PSE_TOP_QUEUE_EMPTY_RLS_Q_EMTPY_SHFT 31 +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC1_QUEUE_EMPTY_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC1_QUEUE_EMPTY_MASK \ +0x08000000 /* MDP_RXIOC1_QUEUE_EMPTY[27] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC1_QUEUE_EMPTY_SHFT 27 +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC1_QUEUE_EMPTY_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC1_QUEUE_EMPTY_MASK \ +0x04000000 /* MDP_TXIOC1_QUEUE_EMPTY[26] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC1_QUEUE_EMPTY_SHFT 26 +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_TX1_QUEUE_EMPTY_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_TX1_QUEUE_EMPTY_MASK \ +0x02000000 /* SEC_TX1_QUEUE_EMPTY[25] */ +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_TX1_QUEUE_EMPTY_SHFT 25 +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TX1_QUEUE_EMPTY_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TX1_QUEUE_EMPTY_MASK \ +0x01000000 /* MDP_TX1_QUEUE_EMPTY[24] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TX1_QUEUE_EMPTY_SHFT 24 +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC_QUEUE_EMPTY_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC_QUEUE_EMPTY_MASK \ +0x00800000 /* MDP_RXIOC_QUEUE_EMPTY[23] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC_QUEUE_EMPTY_SHFT 23 +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC_QUEUE_EMPTY_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC_QUEUE_EMPTY_MASK \ +0x00400000 /* MDP_TXIOC_QUEUE_EMPTY[22] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC_QUEUE_EMPTY_SHFT 22 +#define WF_PSE_TOP_QUEUE_EMPTY_SFD_PARK_QUEUE_EMPTY_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_SFD_PARK_QUEUE_EMPTY_MASK \ +0x00200000 /* SFD_PARK_QUEUE_EMPTY[21] */ +#define WF_PSE_TOP_QUEUE_EMPTY_SFD_PARK_QUEUE_EMPTY_SHFT 21 +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_RX_QUEUE_EMPTY_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_RX_QUEUE_EMPTY_MASK \ +0x00100000 /* SEC_RX_QUEUE_EMPTY[20] */ +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_RX_QUEUE_EMPTY_SHFT 20 +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_TX_QUEUE_EMPTY_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_TX_QUEUE_EMPTY_MASK \ +0x00080000 /* SEC_TX_QUEUE_EMPTY[19] */ +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_TX_QUEUE_EMPTY_SHFT 19 +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RX_QUEUE_EMPTY_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RX_QUEUE_EMPTY_MASK \ +0x00040000 /* MDP_RX_QUEUE_EMPTY[18] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RX_QUEUE_EMPTY_SHFT 18 +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TX_QUEUE_EMPTY_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TX_QUEUE_EMPTY_MASK \ +0x00020000 /* MDP_TX_QUEUE_EMPTY[17] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TX_QUEUE_EMPTY_SHFT 17 +#define WF_PSE_TOP_QUEUE_EMPTY_LMAC_TX_QUEUE_EMPTY_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_LMAC_TX_QUEUE_EMPTY_MASK \ +0x00010000 /* LMAC_TX_QUEUE_EMPTY[16] */ +#define WF_PSE_TOP_QUEUE_EMPTY_LMAC_TX_QUEUE_EMPTY_SHFT 16 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_7_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_7_EMPTY_MASK 0x00008000 /* HIF_7_EMPTY[15]*/ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_7_EMPTY_SHFT 15 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_6_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_6_EMPTY_MASK 0x00004000 /* HIF_6_EMPTY[14]*/ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_6_EMPTY_SHFT 14 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_5_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_5_EMPTY_MASK 0x00002000 /* HIF_5_EMPTY[13]*/ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_5_EMPTY_SHFT 13 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_4_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_4_EMPTY_MASK 0x00001000 /* HIF_4_EMPTY[12]*/ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_4_EMPTY_SHFT 12 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_3_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_3_EMPTY_MASK 0x00000800 /* HIF_3_EMPTY[11]*/ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_3_EMPTY_SHFT 11 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_2_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_2_EMPTY_MASK 0x00000400 /* HIF_2_EMPTY[10]*/ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_2_EMPTY_SHFT 10 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_1_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_1_EMPTY_MASK 0x00000200 /* HIF_1_EMPTY[9]*/ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_1_EMPTY_SHFT 9 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_0_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_0_EMPTY_MASK 0x00000100 /* HIF_0_EMPTY[8]*/ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_0_EMPTY_SHFT 8 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_11_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_11_EMPTY_MASK \ +0x00000080 /* HIF_11_EMPTY[7] */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_11_EMPTY_SHFT 7 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_10_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_10_EMPTY_MASK \ +0x00000040 /* HIF_10_EMPTY[6] */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_10_EMPTY_SHFT 6 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_9_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_9_EMPTY_MASK 0x00000020 /* HIF_9_EMPTY[5] \ + */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_9_EMPTY_SHFT 5 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_8_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_8_EMPTY_MASK 0x00000010 /* HIF_8_EMPTY[4] \ + */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_8_EMPTY_SHFT 4 +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q3_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q3_EMPTY_MASK \ +0x00000008 /* CPU_Q3_EMPTY[3] */ +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q3_EMPTY_SHFT 3 +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q2_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q2_EMPTY_MASK \ +0x00000004 /* CPU_Q2_EMPTY[2] */ +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q2_EMPTY_SHFT 2 +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q1_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q1_EMPTY_MASK \ +0x00000002 /* CPU_Q1_EMPTY[1] */ +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q1_EMPTY_SHFT 1 +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q0_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q0_EMPTY_MASK \ +0x00000001 /* CPU_Q0_EMPTY[0] */ +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q0_EMPTY_SHFT 0 + +/* +* ---QUEUE_EMPTY_MASK (0x820C8000 + 0xB4)--- +* RESERVED0[7..0] - (RO) Reserved bits +* HIF_0_EMPTY_MASK[8] - (RW) Mask control of HIF queue 0 empty status +* HIF_1_EMPTY_MASK[9] - (RW) Mask control of HIF queue 1 empty status +* HIF_2_EMPTY_MASK[10] - (RW) Mask control of HIF queue 2 empty status +* HIF_3_EMPTY_MASK[11] - (RW) Mask control of HIF queue 3 empty status +* HIF_4_EMPTY_MASK[12] - (RW) Mask control of HIF queue 4 empty status +* HIF_5_EMPTY_MASK[13] - (RW) Mask control of HIF queue 5 empty status +* HIF_6_EMPTY_MASK[14] - (RW) Mask control of HIF queue 6 empty status +* HIF_7_EMPTY_MASK[15] - (RW) Mask control of HIF queue 7 empty status +* HIF_8_EMPTY_MASK[16] - (RW) Mask control of HIF queue 8 empty status +* HIF_9_EMPTY_MASK[17] - (RW) Mask control of HIF queue 9 empty status +* HIF_10_EMPTY_MASK[18] - (RW) Mask control of HIF queue 10 empty +status +* HIF_11_EMPTY_MASK[19] - (RW) Mask control of HIF queue 11 empty +status +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_11_EMPTY_MASK_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_11_EMPTY_MASK_MASK \ +0x00080000 /* HIF_11_EMPTY_MASK[19] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_11_EMPTY_MASK_SHFT 19 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_10_EMPTY_MASK_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_10_EMPTY_MASK_MASK \ +0x00040000 /* HIF_10_EMPTY_MASK[18] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_10_EMPTY_MASK_SHFT 18 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_9_EMPTY_MASK_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_9_EMPTY_MASK_MASK \ +0x00020000 /* HIF_9_EMPTY_MASK[17] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_9_EMPTY_MASK_SHFT 17 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_8_EMPTY_MASK_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_8_EMPTY_MASK_MASK \ +0x00010000 /* HIF_8_EMPTY_MASK[16] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_8_EMPTY_MASK_SHFT 16 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_7_EMPTY_MASK_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_7_EMPTY_MASK_MASK \ +0x00008000 /* HIF_7_EMPTY_MASK[15] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_7_EMPTY_MASK_SHFT 15 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_6_EMPTY_MASK_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_6_EMPTY_MASK_MASK \ +0x00004000 /* HIF_6_EMPTY_MASK[14] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_6_EMPTY_MASK_SHFT 14 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_5_EMPTY_MASK_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_5_EMPTY_MASK_MASK \ +0x00002000 /* HIF_5_EMPTY_MASK[13] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_5_EMPTY_MASK_SHFT 13 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_4_EMPTY_MASK_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_4_EMPTY_MASK_MASK \ +0x00001000 /* HIF_4_EMPTY_MASK[12] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_4_EMPTY_MASK_SHFT 12 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_3_EMPTY_MASK_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_3_EMPTY_MASK_MASK \ +0x00000800 /* HIF_3_EMPTY_MASK[11] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_3_EMPTY_MASK_SHFT 11 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_2_EMPTY_MASK_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_2_EMPTY_MASK_MASK \ +0x00000400 /* HIF_2_EMPTY_MASK[10] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_2_EMPTY_MASK_SHFT 10 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_1_EMPTY_MASK_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_1_EMPTY_MASK_MASK \ +0x00000200 /* HIF_1_EMPTY_MASK[9] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_1_EMPTY_MASK_SHFT 9 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_0_EMPTY_MASK_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_0_EMPTY_MASK_MASK \ +0x00000100 /* HIF_0_EMPTY_MASK[8] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_0_EMPTY_MASK_SHFT 8 + +/* +* ---FREEPG_START_END (0x820C8000 + 0xC0)--- +* FREEPG_START[11..0] - (RW) Start page setting of free pages +* RESERVED12[15..12] - (RO) Reserved bits +* FREEPG_END[27..16] - (RW) End page setting of free page +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_FREEPG_START_END_FREEPG_END_ADDR \ +WF_PSE_TOP_FREEPG_START_END_ADDR +#define WF_PSE_TOP_FREEPG_START_END_FREEPG_END_MASK \ +0x0FFF0000 /* FREEPG_END[27..16] */ +#define WF_PSE_TOP_FREEPG_START_END_FREEPG_END_SHFT 16 +#define WF_PSE_TOP_FREEPG_START_END_FREEPG_START_ADDR \ +WF_PSE_TOP_FREEPG_START_END_ADDR +#define WF_PSE_TOP_FREEPG_START_END_FREEPG_START_MASK \ +0x00000FFF /* FREEPG_START[11..0] */ +#define WF_PSE_TOP_FREEPG_START_END_FREEPG_START_SHFT 0 + +/* +* ---PSE_MODULE_CKG_DIS (0x820C8000 + 0xc4)--- +* DIS_FL_DYN_CKG[0] - (RW) Disable control of PSE frame link module +* dynamic clock gating function +* DIS_PL_DYN_CKG[1] - (RW) Disable control of PSE page link module +* dynamic clock gating function +* DIS_CPU_PORT_DYN_CKG[2] - (RW) Disable control of PSE CPU port module +* dynamic clock gating function +* DIS_HIF_PORT_DYN_CKG[3] - (RW) Disable control of PSE HIF port module +* dynamic clock gating function +* DIS_WF_PLE_PORT_DYN_CKG[4] - (RW) Disable control of PSE LMAC and PLE port +* module dynamic clock gating function +* DIS_RLS_DYN_CKG[5] - (RW) Disable control of PSE release module +* dynamic clock gating function +* DIS_RL_DYN_CKG[6] - (RW) Disable control of PSE relay information +* module dynamic clock gating function +* RESERVED7[8..7] - (RO) Reserved bits +* DIS_CSR_DYN_CKG[9] - (RW) Disable control of PSE CR module dynamic +* clock gating function +* DIS_CPU_WRAP_DYN_CKG[10] - (RW) Disable control of PSE CPU_WRAP module +* dynamic clock gating function +* DIS_DBG_DYN_CKG[11] - (RW) Disable control of PSE debug module +* dynamic clock gating function +* DIS_MDP_DYN_CKG[12] - (RW) Disable control of PSE MDP module +* dynamic clock gating function +* DIS_SEC_DYN_CKG[13] - (RW) Disable control of PSE SEC module +* dynamic clock gating function +* RESERVED14[31..14] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_SEC_DYN_CKG_ADDR \ +WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_SEC_DYN_CKG_MASK \ +0x00002000 /* DIS_SEC_DYN_CKG[13] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_SEC_DYN_CKG_SHFT 13 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_MDP_DYN_CKG_ADDR \ +WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_MDP_DYN_CKG_MASK \ +0x00001000 /* DIS_MDP_DYN_CKG[12] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_MDP_DYN_CKG_SHFT 12 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_DBG_DYN_CKG_ADDR \ +WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_DBG_DYN_CKG_MASK \ +0x00000800 /* DIS_DBG_DYN_CKG[11] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_DBG_DYN_CKG_SHFT 11 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CPU_WRAP_DYN_CKG_ADDR \ +WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CPU_WRAP_DYN_CKG_MASK \ +0x00000400 /* DIS_CPU_WRAP_DYN_CKG[10] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CPU_WRAP_DYN_CKG_SHFT 10 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CSR_DYN_CKG_ADDR \ +WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CSR_DYN_CKG_MASK \ +0x00000200 /* DIS_CSR_DYN_CKG[9] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CSR_DYN_CKG_SHFT 9 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_RL_DYN_CKG_ADDR \ +WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_RL_DYN_CKG_MASK \ +0x00000040 /* DIS_RL_DYN_CKG[6] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_RL_DYN_CKG_SHFT 6 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_RLS_DYN_CKG_ADDR \ +WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_RLS_DYN_CKG_MASK \ +0x00000020 /* DIS_RLS_DYN_CKG[5] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_RLS_DYN_CKG_SHFT 5 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_WF_PLE_PORT_DYN_CKG_ADDR \ +WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_WF_PLE_PORT_DYN_CKG_MASK \ +0x00000010 /* DIS_WF_PLE_PORT_DYN_CKG[4] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_WF_PLE_PORT_DYN_CKG_SHFT 4 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_HIF_PORT_DYN_CKG_ADDR \ +WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_HIF_PORT_DYN_CKG_MASK \ +0x00000008 /* DIS_HIF_PORT_DYN_CKG[3] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_HIF_PORT_DYN_CKG_SHFT 3 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CPU_PORT_DYN_CKG_ADDR \ +WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CPU_PORT_DYN_CKG_MASK \ +0x00000004 /* DIS_CPU_PORT_DYN_CKG[2] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CPU_PORT_DYN_CKG_SHFT 2 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_PL_DYN_CKG_ADDR \ +WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_PL_DYN_CKG_MASK \ +0x00000002 /* DIS_PL_DYN_CKG[1] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_PL_DYN_CKG_SHFT 1 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_FL_DYN_CKG_ADDR \ +WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_FL_DYN_CKG_MASK \ +0x00000001 /* DIS_FL_DYN_CKG[0] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_FL_DYN_CKG_SHFT 0 + +/* +* ---TO_N9_INT (0x820C8000 + 0xf0)--- +* CR4_CMD[30..0] - (RW) Command for N9 +* TOGGLE[31] - (RW) When this bit is toggled, HW will send +* interrupt to N9. +*/ +#define WF_PSE_TOP_TO_N9_INT_TOGGLE_ADDR WF_PSE_TOP_TO_N9_INT_ADDR +#define WF_PSE_TOP_TO_N9_INT_TOGGLE_MASK 0x80000000 /* TOGGLE[31] */ +#define WF_PSE_TOP_TO_N9_INT_TOGGLE_SHFT 31 +#define WF_PSE_TOP_TO_N9_INT_CR4_CMD_ADDR WF_PSE_TOP_TO_N9_INT_ADDR +#define WF_PSE_TOP_TO_N9_INT_CR4_CMD_MASK 0x7FFFFFFF /* CR4_CMD[30..0] */ +#define WF_PSE_TOP_TO_N9_INT_CR4_CMD_SHFT 0 + +/* +* ---FREEPG_CNT (0x820C8000 + 0x100)--- +* FREEPG_CNT[11..0] - (RO) Total page number of free +* RESERVED12[15..12] - (RO) Reserved bits +* FFA_CNT[27..16] - (RO) Free page numbers of free for all +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_FREEPG_CNT_FFA_CNT_ADDR WF_PSE_TOP_FREEPG_CNT_ADDR +#define WF_PSE_TOP_FREEPG_CNT_FFA_CNT_MASK 0x0FFF0000 /* FFA_CNT[27..16] */ +#define WF_PSE_TOP_FREEPG_CNT_FFA_CNT_SHFT 16 +#define WF_PSE_TOP_FREEPG_CNT_FREEPG_CNT_ADDR WF_PSE_TOP_FREEPG_CNT_ADDR +#define WF_PSE_TOP_FREEPG_CNT_FREEPG_CNT_MASK 0x00000FFF /* FREEPG_CNT[11..0]\ + */ +#define WF_PSE_TOP_FREEPG_CNT_FREEPG_CNT_SHFT 0 + +/* +* ---FREEPG_HEAD_TAIL (0x820C8000 + 0x104)--- +* FREEPG_HEAD[11..0] - (RO) Head page of free page list +* RESERVED12[15..12] - (RO) Reserved bits +* FREEPG_TAIL[27..16] - (RO) Tail page of free page list +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_ADDR \ +WF_PSE_TOP_FREEPG_HEAD_TAIL_ADDR +#define WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_MASK \ +0x0FFF0000 /* FREEPG_TAIL[27..16] */ +#define WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_SHFT 16 +#define WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_ADDR \ +WF_PSE_TOP_FREEPG_HEAD_TAIL_ADDR +#define WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_MASK \ +0x00000FFF /* FREEPG_HEAD[11..0] */ +#define WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_SHFT 0 + +/* +* ---GROUP_REFILL_CTRL (0x820C8000 + 0x108)--- +* GROUP_REFILL_PRI[8..0] - (RW) group refill priority control +* RESERVED9[15..9] - (RO) Reserved bits +* DIS_GROUP_REFILL[24..16] - (RW) group quota refill enable control +* RESERVED25[31..25] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_GROUP_REFILL_CTRL_DIS_GROUP_REFILL_ADDR \ +WF_PSE_TOP_GROUP_REFILL_CTRL_ADDR +#define WF_PSE_TOP_GROUP_REFILL_CTRL_DIS_GROUP_REFILL_MASK \ +0x01FF0000 /* DIS_GROUP_REFILL[24..16] */ +#define WF_PSE_TOP_GROUP_REFILL_CTRL_DIS_GROUP_REFILL_SHFT 16 +#define WF_PSE_TOP_GROUP_REFILL_CTRL_GROUP_REFILL_PRI_ADDR \ +WF_PSE_TOP_GROUP_REFILL_CTRL_ADDR +#define WF_PSE_TOP_GROUP_REFILL_CTRL_GROUP_REFILL_PRI_MASK \ +0x000001FF /* GROUP_REFILL_PRI[8..0] */ +#define WF_PSE_TOP_GROUP_REFILL_CTRL_GROUP_REFILL_PRI_SHFT 0 + +/* +* ---PG_HIF0_GROUP (0x820C8000 + 0x110)--- +* HIF0_MIN_QUOTA[11..0] - (RW) Min. quota of HIF 0 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* HIF0_MAX_QUOTA[27..16] - (RW) Max. quota of HIF 0 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MAX_QUOTA_ADDR \ +WF_PSE_TOP_PG_HIF0_GROUP_ADDR +#define WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MAX_QUOTA_MASK \ +0x0FFF0000 /* HIF0_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MIN_QUOTA_ADDR \ +WF_PSE_TOP_PG_HIF0_GROUP_ADDR +#define WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MIN_QUOTA_MASK \ +0x00000FFF /* HIF0_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MIN_QUOTA_SHFT 0 + +/* +* ---HIF0_PG_INFO (0x820C8000 + 0x114)--- +* HIF0_RSV_CNT[11..0] - (RO) Reserved pages of HIF 0 group +* RESERVED12[15..12] - (RO) Reserved bits +* HIF0_SRC_CNT[27..16] - (RO) Used pages of HIF 0 group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_HIF0_PG_INFO_HIF0_SRC_CNT_ADDR WF_PSE_TOP_HIF0_PG_INFO_ADDR +#define WF_PSE_TOP_HIF0_PG_INFO_HIF0_SRC_CNT_MASK \ +0x0FFF0000 /* HIF0_SRC_CNT[27..16] */ +#define WF_PSE_TOP_HIF0_PG_INFO_HIF0_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_HIF0_PG_INFO_HIF0_RSV_CNT_ADDR WF_PSE_TOP_HIF0_PG_INFO_ADDR +#define WF_PSE_TOP_HIF0_PG_INFO_HIF0_RSV_CNT_MASK \ +0x00000FFF /* HIF0_RSV_CNT[11..0] */ +#define WF_PSE_TOP_HIF0_PG_INFO_HIF0_RSV_CNT_SHFT 0 + +/* +* ---PG_HIF1_GROUP (0x820C8000 + 0x118)--- +* HIF1_MIN_QUOTA[11..0] - (RW) Min. quota of HIF 1 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* HIF1_MAX_QUOTA[27..16] - (RW) Max. quota of HIF 1 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_HIF1_GROUP_HIF1_MAX_QUOTA_ADDR \ +WF_PSE_TOP_PG_HIF1_GROUP_ADDR +#define WF_PSE_TOP_PG_HIF1_GROUP_HIF1_MAX_QUOTA_MASK \ +0x0FFF0000 /* HIF1_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_HIF1_GROUP_HIF1_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_HIF1_GROUP_HIF1_MIN_QUOTA_ADDR \ +WF_PSE_TOP_PG_HIF1_GROUP_ADDR +#define WF_PSE_TOP_PG_HIF1_GROUP_HIF1_MIN_QUOTA_MASK \ +0x00000FFF /* HIF1_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_HIF1_GROUP_HIF1_MIN_QUOTA_SHFT 0 + +/* +* ---HIF1_PG_INFO (0x820C8000 + 0x11C)--- +* HIF1_RSV_CNT[11..0] - (RO) Reserved pages of HIF 1 group +* RESERVED12[15..12] - (RO) Reserved bits +* HIF1_SRC_CNT[27..16] - (RO) Used pages of HIF 1 group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_HIF1_PG_INFO_HIF1_SRC_CNT_ADDR WF_PSE_TOP_HIF1_PG_INFO_ADDR +#define WF_PSE_TOP_HIF1_PG_INFO_HIF1_SRC_CNT_MASK \ +0x0FFF0000 /* HIF1_SRC_CNT[27..16] */ +#define WF_PSE_TOP_HIF1_PG_INFO_HIF1_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_HIF1_PG_INFO_HIF1_RSV_CNT_ADDR WF_PSE_TOP_HIF1_PG_INFO_ADDR +#define WF_PSE_TOP_HIF1_PG_INFO_HIF1_RSV_CNT_MASK \ +0x00000FFF /* HIF1_RSV_CNT[11..0] */ +#define WF_PSE_TOP_HIF1_PG_INFO_HIF1_RSV_CNT_SHFT 0 + +/* +* ---PG_CPU_GROUP (0x820C8000 + 0x150)--- +* CPU_MIN_QUOTA[11..0] - (RW) Min. quota of CPU group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* CPU_MAX_QUOTA[27..16] - (RW) Max. quota of CPU group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_CPU_GROUP_CPU_MAX_QUOTA_ADDR WF_PSE_TOP_PG_CPU_GROUP_ADDR +#define WF_PSE_TOP_PG_CPU_GROUP_CPU_MAX_QUOTA_MASK \ +0x0FFF0000 /* CPU_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_CPU_GROUP_CPU_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_CPU_GROUP_CPU_MIN_QUOTA_ADDR WF_PSE_TOP_PG_CPU_GROUP_ADDR +#define WF_PSE_TOP_PG_CPU_GROUP_CPU_MIN_QUOTA_MASK \ +0x00000FFF /* CPU_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_CPU_GROUP_CPU_MIN_QUOTA_SHFT 0 + +/* +* ---CPU_PG_INFO (0x820C8000 + 0x154)--- +* CPU_RSV_CNT[11..0] - (RO) Reserved pages of CPU group +* RESERVED12[15..12] - (RO) Reserved bits +* CPU_SRC_CNT[27..16] - (RO) Used pages of CPU group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_CPU_PG_INFO_CPU_SRC_CNT_ADDR WF_PSE_TOP_CPU_PG_INFO_ADDR +#define WF_PSE_TOP_CPU_PG_INFO_CPU_SRC_CNT_MASK \ +0x0FFF0000 /* CPU_SRC_CNT[27..16] */ +#define WF_PSE_TOP_CPU_PG_INFO_CPU_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_CPU_PG_INFO_CPU_RSV_CNT_ADDR WF_PSE_TOP_CPU_PG_INFO_ADDR +#define WF_PSE_TOP_CPU_PG_INFO_CPU_RSV_CNT_MASK \ +0x00000FFF /* CPU_RSV_CNT[11..0] */ +#define WF_PSE_TOP_CPU_PG_INFO_CPU_RSV_CNT_SHFT 0 + +/* +* ---PG_PLE_GROUP (0x820C8000 + 0x160)--- +* PLE_MIN_QUOTA[11..0] - (RW) Min. quota of PLE group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* PLE_MAX_QUOTA[27..16] - (RW) Max. quota of PLE group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_PLE_GROUP_PLE_MAX_QUOTA_ADDR WF_PSE_TOP_PG_PLE_GROUP_ADDR +#define WF_PSE_TOP_PG_PLE_GROUP_PLE_MAX_QUOTA_MASK \ +0x0FFF0000 /* PLE_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_PLE_GROUP_PLE_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_PLE_GROUP_PLE_MIN_QUOTA_ADDR WF_PSE_TOP_PG_PLE_GROUP_ADDR +#define WF_PSE_TOP_PG_PLE_GROUP_PLE_MIN_QUOTA_MASK \ +0x00000FFF /* PLE_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_PLE_GROUP_PLE_MIN_QUOTA_SHFT 0 + +/* +* ---PLE_PG_INFO (0x820C8000 + 0x164)--- +* PLE_RSV_CNT[11..0] - (RO) Reserved pages of PLE group +* RESERVED12[15..12] - (RO) Reserved bits +* PLE_SRC_CNT[27..16] - (RO) Used pages of PLE group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PLE_PG_INFO_PLE_SRC_CNT_ADDR WF_PSE_TOP_PLE_PG_INFO_ADDR +#define WF_PSE_TOP_PLE_PG_INFO_PLE_SRC_CNT_MASK \ +0x0FFF0000 /* PLE_SRC_CNT[27..16] */ +#define WF_PSE_TOP_PLE_PG_INFO_PLE_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_PLE_PG_INFO_PLE_RSV_CNT_ADDR WF_PSE_TOP_PLE_PG_INFO_ADDR +#define WF_PSE_TOP_PLE_PG_INFO_PLE_RSV_CNT_MASK \ +0x00000FFF /* PLE_RSV_CNT[11..0] */ +#define WF_PSE_TOP_PLE_PG_INFO_PLE_RSV_CNT_SHFT 0 + +/* +* ---PG_PLE1_GROUP (0x820C8000 + 0x168)--- +* PLE_MIN_QUOTA[11..0] - (RW) Min. quota of PLE group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* PLE_MAX_QUOTA[27..16] - (RW) Max. quota of PLE group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_PLE1_GROUP_PLE_MAX_QUOTA_ADDR \ +WF_PSE_TOP_PG_PLE1_GROUP_ADDR +#define WF_PSE_TOP_PG_PLE1_GROUP_PLE_MAX_QUOTA_MASK \ +0x0FFF0000 /* PLE_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_PLE1_GROUP_PLE_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_PLE1_GROUP_PLE_MIN_QUOTA_ADDR \ +WF_PSE_TOP_PG_PLE1_GROUP_ADDR +#define WF_PSE_TOP_PG_PLE1_GROUP_PLE_MIN_QUOTA_MASK \ +0x00000FFF /* PLE_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_PLE1_GROUP_PLE_MIN_QUOTA_SHFT 0 + +/* +* ---PLE1_PG_INFO (0x820C8000 + 0x16C)--- +* PLE_RSV_CNT[11..0] - (RO) Reserved pages of PLE group +* RESERVED12[15..12] - (RO) Reserved bits +* PLE_SRC_CNT[27..16] - (RO) Used pages of PLE group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PLE1_PG_INFO_PLE_SRC_CNT_ADDR WF_PSE_TOP_PLE1_PG_INFO_ADDR +#define WF_PSE_TOP_PLE1_PG_INFO_PLE_SRC_CNT_MASK \ +0x0FFF0000 /* PLE_SRC_CNT[27..16] */ +#define WF_PSE_TOP_PLE1_PG_INFO_PLE_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_PLE1_PG_INFO_PLE_RSV_CNT_ADDR WF_PSE_TOP_PLE1_PG_INFO_ADDR +#define WF_PSE_TOP_PLE1_PG_INFO_PLE_RSV_CNT_MASK \ +0x00000FFF /* PLE_RSV_CNT[11..0] */ +#define WF_PSE_TOP_PLE1_PG_INFO_PLE_RSV_CNT_SHFT 0 + +/* +* ---PG_LMAC0_GROUP (0x820C8000 + 0x170)--- +* LMAC0_MIN_QUOTA[11..0] - (RW) Min. quota of LMAC 0 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* LMAC0_MAX_QUOTA[27..16] - (RW) Max. quota of LMAC 0 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_LMAC0_GROUP_LMAC0_MAX_QUOTA_ADDR \ +WF_PSE_TOP_PG_LMAC0_GROUP_ADDR +#define WF_PSE_TOP_PG_LMAC0_GROUP_LMAC0_MAX_QUOTA_MASK \ +0x0FFF0000 /* LMAC0_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_LMAC0_GROUP_LMAC0_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_LMAC0_GROUP_LMAC0_MIN_QUOTA_ADDR \ +WF_PSE_TOP_PG_LMAC0_GROUP_ADDR +#define WF_PSE_TOP_PG_LMAC0_GROUP_LMAC0_MIN_QUOTA_MASK \ +0x00000FFF /* LMAC0_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_LMAC0_GROUP_LMAC0_MIN_QUOTA_SHFT 0 + +/* +* ---LMAC0_PG_INFO (0x820C8000 + 0x174)--- +* LMAC0_RSV_CNT[11..0] - (RO) Reserved pages of LMAC 0 group +* RESERVED12[15..12] - (RO) Reserved bits +* LMAC0_SRC_CNT[27..16] - (RO) Used pages of LMAC 0 group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_LMAC0_PG_INFO_LMAC0_SRC_CNT_ADDR \ +WF_PSE_TOP_LMAC0_PG_INFO_ADDR +#define WF_PSE_TOP_LMAC0_PG_INFO_LMAC0_SRC_CNT_MASK \ +0x0FFF0000 /* LMAC0_SRC_CNT[27..16] */ +#define WF_PSE_TOP_LMAC0_PG_INFO_LMAC0_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_LMAC0_PG_INFO_LMAC0_RSV_CNT_ADDR \ +WF_PSE_TOP_LMAC0_PG_INFO_ADDR +#define WF_PSE_TOP_LMAC0_PG_INFO_LMAC0_RSV_CNT_MASK \ +0x00000FFF /* LMAC0_RSV_CNT[11..0] */ +#define WF_PSE_TOP_LMAC0_PG_INFO_LMAC0_RSV_CNT_SHFT 0 + +/* +* ---PG_LMAC1_GROUP (0x820C8000 + 0x178)--- +* LMAC1_MIN_QUOTA[11..0] - (RW) Min. quota of LMAC 1 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* LMAC1_MAX_QUOTA[27..16] - (RW) Max. quota of LMAC 1 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_LMAC1_GROUP_LMAC1_MAX_QUOTA_ADDR \ +WF_PSE_TOP_PG_LMAC1_GROUP_ADDR +#define WF_PSE_TOP_PG_LMAC1_GROUP_LMAC1_MAX_QUOTA_MASK \ +0x0FFF0000 /* LMAC1_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_LMAC1_GROUP_LMAC1_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_LMAC1_GROUP_LMAC1_MIN_QUOTA_ADDR \ +WF_PSE_TOP_PG_LMAC1_GROUP_ADDR +#define WF_PSE_TOP_PG_LMAC1_GROUP_LMAC1_MIN_QUOTA_MASK \ +0x00000FFF /* LMAC1_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_LMAC1_GROUP_LMAC1_MIN_QUOTA_SHFT 0 + +/* +* ---LMAC1_PG_INFO (0x820C8000 + 0x17C)--- +* LMAC1_RSV_CNT[11..0] - (RO) Reserved pages of LMAC 1 group +* RESERVED12[15..12] - (RO) Reserved bits +* LMAC1_SRC_CNT[27..16] - (RO) Used pages of LMAC 1 group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_LMAC1_PG_INFO_LMAC1_SRC_CNT_ADDR \ +WF_PSE_TOP_LMAC1_PG_INFO_ADDR +#define WF_PSE_TOP_LMAC1_PG_INFO_LMAC1_SRC_CNT_MASK \ +0x0FFF0000 /* LMAC1_SRC_CNT[27..16] */ +#define WF_PSE_TOP_LMAC1_PG_INFO_LMAC1_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_LMAC1_PG_INFO_LMAC1_RSV_CNT_ADDR \ +WF_PSE_TOP_LMAC1_PG_INFO_ADDR +#define WF_PSE_TOP_LMAC1_PG_INFO_LMAC1_RSV_CNT_MASK \ +0x00000FFF /* LMAC1_RSV_CNT[11..0] */ +#define WF_PSE_TOP_LMAC1_PG_INFO_LMAC1_RSV_CNT_SHFT 0 + +/* +* ---PG_LMAC2_GROUP (0x820C8000 + 0x180)--- +* LMAC2_MIN_QUOTA[11..0] - (RW) Min. quota of LMAC 2 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* LMAC2_MAX_QUOTA[27..16] - (RW) Max. quota of LMAC 2 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_LMAC2_GROUP_LMAC2_MAX_QUOTA_ADDR \ +WF_PSE_TOP_PG_LMAC2_GROUP_ADDR +#define WF_PSE_TOP_PG_LMAC2_GROUP_LMAC2_MAX_QUOTA_MASK \ +0x0FFF0000 /* LMAC2_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_LMAC2_GROUP_LMAC2_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_LMAC2_GROUP_LMAC2_MIN_QUOTA_ADDR \ +WF_PSE_TOP_PG_LMAC2_GROUP_ADDR +#define WF_PSE_TOP_PG_LMAC2_GROUP_LMAC2_MIN_QUOTA_MASK \ +0x00000FFF /* LMAC2_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_LMAC2_GROUP_LMAC2_MIN_QUOTA_SHFT 0 + +/* +* ---LMAC2_PG_INFO (0x820C8000 + 0x184)--- +* LMAC2_RSV_CNT[11..0] - (RO) Reserved pages of LMAC 2 group +* RESERVED12[15..12] - (RO) Reserved bits +* LMAC2_SRC_CNT[27..16] - (RO) Used pages of LMAC 2 group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_LMAC2_PG_INFO_LMAC2_SRC_CNT_ADDR \ +WF_PSE_TOP_LMAC2_PG_INFO_ADDR +#define WF_PSE_TOP_LMAC2_PG_INFO_LMAC2_SRC_CNT_MASK \ +0x0FFF0000 /* LMAC2_SRC_CNT[27..16] */ +#define WF_PSE_TOP_LMAC2_PG_INFO_LMAC2_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_LMAC2_PG_INFO_LMAC2_RSV_CNT_ADDR \ +WF_PSE_TOP_LMAC2_PG_INFO_ADDR +#define WF_PSE_TOP_LMAC2_PG_INFO_LMAC2_RSV_CNT_MASK \ +0x00000FFF /* LMAC2_RSV_CNT[11..0] */ +#define WF_PSE_TOP_LMAC2_PG_INFO_LMAC2_RSV_CNT_SHFT 0 + +/* +* ---PG_LMAC3_GROUP (0x820C8000 + 0x188)--- +* LMAC3_MIN_QUOTA[11..0] - (RW) Min. quota of LMAC 3 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* LMAC3_MAX_QUOTA[27..16] - (RW) Max. quota of LMAC 3 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_LMAC3_GROUP_LMAC3_MAX_QUOTA_ADDR \ +WF_PSE_TOP_PG_LMAC3_GROUP_ADDR +#define WF_PSE_TOP_PG_LMAC3_GROUP_LMAC3_MAX_QUOTA_MASK \ +0x0FFF0000 /* LMAC3_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_LMAC3_GROUP_LMAC3_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_LMAC3_GROUP_LMAC3_MIN_QUOTA_ADDR \ +WF_PSE_TOP_PG_LMAC3_GROUP_ADDR +#define WF_PSE_TOP_PG_LMAC3_GROUP_LMAC3_MIN_QUOTA_MASK \ +0x00000FFF /* LMAC3_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_LMAC3_GROUP_LMAC3_MIN_QUOTA_SHFT 0 + +/* +* ---LMAC3_PG_INFO (0x820C8000 + 0x18C)--- +* LMAC3_RSV_CNT[11..0] - (RO) Reserved pages of LMAC 3 group +* RESERVED12[15..12] - (RO) Reserved bits +* LMAC3_SRC_CNT[27..16] - (RO) Used pages of LMAC 3 group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_LMAC3_PG_INFO_LMAC3_SRC_CNT_ADDR \ +WF_PSE_TOP_LMAC3_PG_INFO_ADDR +#define WF_PSE_TOP_LMAC3_PG_INFO_LMAC3_SRC_CNT_MASK \ +0x0FFF0000 /* LMAC3_SRC_CNT[27..16] */ +#define WF_PSE_TOP_LMAC3_PG_INFO_LMAC3_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_LMAC3_PG_INFO_LMAC3_RSV_CNT_ADDR \ +WF_PSE_TOP_LMAC3_PG_INFO_ADDR +#define WF_PSE_TOP_LMAC3_PG_INFO_LMAC3_RSV_CNT_MASK \ +0x00000FFF /* LMAC3_RSV_CNT[11..0] */ +#define WF_PSE_TOP_LMAC3_PG_INFO_LMAC3_RSV_CNT_SHFT 0 + +/* +* ---PG_MDP_GROUP (0x820C8000 + 0x198)--- +* MDP_MIN_QUOTA[11..0] - (RW) Min. quota of MDP group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* MDP_MAX_QUOTA[27..16] - (RW) Max. quota of MDP group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_MDP_GROUP_MDP_MAX_QUOTA_ADDR WF_PSE_TOP_PG_MDP_GROUP_ADDR +#define WF_PSE_TOP_PG_MDP_GROUP_MDP_MAX_QUOTA_MASK \ +0x0FFF0000 /* MDP_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_MDP_GROUP_MDP_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_MDP_GROUP_MDP_MIN_QUOTA_ADDR WF_PSE_TOP_PG_MDP_GROUP_ADDR +#define WF_PSE_TOP_PG_MDP_GROUP_MDP_MIN_QUOTA_MASK \ +0x00000FFF /* MDP_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_MDP_GROUP_MDP_MIN_QUOTA_SHFT 0 + +/* +* ---MDP_PG_INFO (0x820C8000 + 0x19C)--- +* MDP_RSV_CNT[11..0] - (RO) Reserved pages of MDP group +* RESERVED12[15..12] - (RO) Reserved bits +* MDP_SRC_CNT[27..16] - (RO) Used pages of MDP group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_MDP_PG_INFO_MDP_SRC_CNT_ADDR WF_PSE_TOP_MDP_PG_INFO_ADDR +#define WF_PSE_TOP_MDP_PG_INFO_MDP_SRC_CNT_MASK \ +0x0FFF0000 /* MDP_SRC_CNT[27..16] */ +#define WF_PSE_TOP_MDP_PG_INFO_MDP_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_MDP_PG_INFO_MDP_RSV_CNT_ADDR WF_PSE_TOP_MDP_PG_INFO_ADDR +#define WF_PSE_TOP_MDP_PG_INFO_MDP_RSV_CNT_MASK \ +0x00000FFF /* MDP_RSV_CNT[11..0] */ +#define WF_PSE_TOP_MDP_PG_INFO_MDP_RSV_CNT_SHFT 0 + +/* +* ---RL_BUF_CTRL_0 (0x820C8000 + 0x1A0)--- +* RELAY_BUF_ADDR[11..0] - (RW) Read address of relay buffer +* RESERVED12[30..12] - (RO) Reserved bits +* EXECUTE[31] - (A0) Executes relay buffer read command +*/ +#define WF_PSE_TOP_RL_BUF_CTRL_0_EXECUTE_ADDR WF_PSE_TOP_RL_BUF_CTRL_0_ADDR +#define WF_PSE_TOP_RL_BUF_CTRL_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PSE_TOP_RL_BUF_CTRL_0_EXECUTE_SHFT 31 +#define WF_PSE_TOP_RL_BUF_CTRL_0_RELAY_BUF_ADDR_ADDR \ +WF_PSE_TOP_RL_BUF_CTRL_0_ADDR +#define WF_PSE_TOP_RL_BUF_CTRL_0_RELAY_BUF_ADDR_MASK \ +0x00000FFF /* RELAY_BUF_ADDR[11..0] */ +#define WF_PSE_TOP_RL_BUF_CTRL_0_RELAY_BUF_ADDR_SHFT 0 + +/* +* ---RL_BUF_CTRL_1 (0x820C8000 + 0x1A4)--- +* PAGE_NUM[8..0] - (RO) Page number of packet +* RESERVED9[13..9] - (RO) Reserved bits +* PKT_TAIL_PAGE[25..14] - (RO) Tail page of the packet with head page +* being the relay buffer address +* RESERVED26[26] - (RO) Reserved bits +* RESV_GRP_ID[30..27] - (RO) Group ID of reserved page used by FID +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_RL_BUF_CTRL_1_RESV_GRP_ID_ADDR WF_PSE_TOP_RL_BUF_CTRL_1_ADDR +#define WF_PSE_TOP_RL_BUF_CTRL_1_RESV_GRP_ID_MASK \ +0x78000000 /* RESV_GRP_ID[30..27] */ +#define WF_PSE_TOP_RL_BUF_CTRL_1_RESV_GRP_ID_SHFT 27 +#define WF_PSE_TOP_RL_BUF_CTRL_1_PKT_TAIL_PAGE_ADDR \ +WF_PSE_TOP_RL_BUF_CTRL_1_ADDR +#define WF_PSE_TOP_RL_BUF_CTRL_1_PKT_TAIL_PAGE_MASK \ +0x03FFC000 /* PKT_TAIL_PAGE[25..14] */ +#define WF_PSE_TOP_RL_BUF_CTRL_1_PKT_TAIL_PAGE_SHFT 14 +#define WF_PSE_TOP_RL_BUF_CTRL_1_PAGE_NUM_ADDR WF_PSE_TOP_RL_BUF_CTRL_1_ADDR +#define WF_PSE_TOP_RL_BUF_CTRL_1_PAGE_NUM_MASK 0x000001FF /* PAGE_NUM[8..0] */ +#define WF_PSE_TOP_RL_BUF_CTRL_1_PAGE_NUM_SHFT 0 + +/* +* ---FL_QUE_CTRL_0 (0x820C8000 + 0x1B0)--- +* Q_BUF_WLANID[9..0] - (RW) Address of queue structure buffer +WLANID. +* Q_BUF_PID[11..10] - (RW) Address of queue structure buffer PID +* FL_BUFFER_ADDR[23..12] - (RW) Frame address of read previous +* frame/next frame +* Q_BUF_QID[30..24] - (RW) Address of queue structure buffer QID +* EXECUTE[31] - (A0) Executes frame link and queue structure +* buffer read command +*/ +#define WF_PSE_TOP_FL_QUE_CTRL_0_EXECUTE_ADDR WF_PSE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PSE_TOP_FL_QUE_CTRL_0_EXECUTE_SHFT 31 +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_ADDR WF_PSE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_MASK \ +0x7F000000 /* Q_BUF_QID[30..24] */ +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_SHFT 24 +#define WF_PSE_TOP_FL_QUE_CTRL_0_FL_BUFFER_ADDR_ADDR \ +WF_PSE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_0_FL_BUFFER_ADDR_MASK \ +0x00FFF000 /* FL_BUFFER_ADDR[23..12] */ +#define WF_PSE_TOP_FL_QUE_CTRL_0_FL_BUFFER_ADDR_SHFT 12 +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_ADDR WF_PSE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_MASK \ +0x00000C00 /* Q_BUF_PID[11..10] */ +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_SHFT 10 +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_WLANID_ADDR WF_PSE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_WLANID_MASK \ +0x000003FF /* Q_BUF_WLANID[9..0] */ +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_WLANID_SHFT 0 + +/* +* ---FL_QUE_CTRL_1 (0x820C8000 + 0x1B4)--- +* NEXT_FID[11..0] - (RO) Next frame ID of FL_BUFFER_ADDR +* RESERVED12[15..12] - (RO) Reserved bits +* PREV_FID[27..16] - (RO) Previous frame ID of FL_BUFFER_ADDR +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_FL_QUE_CTRL_1_PREV_FID_ADDR WF_PSE_TOP_FL_QUE_CTRL_1_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_1_PREV_FID_MASK 0x0FFF0000 /* PREV_FID[27..16]\ + */ +#define WF_PSE_TOP_FL_QUE_CTRL_1_PREV_FID_SHFT 16 +#define WF_PSE_TOP_FL_QUE_CTRL_1_NEXT_FID_ADDR WF_PSE_TOP_FL_QUE_CTRL_1_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_1_NEXT_FID_MASK 0x00000FFF /* NEXT_FID[11..0] \ + */ +#define WF_PSE_TOP_FL_QUE_CTRL_1_NEXT_FID_SHFT 0 + +/* +* ---FL_QUE_CTRL_2 (0x820C8000 + 0x1B8)--- +* QUEUE_HEAD_FID[11..0] - (RO) Head frame ID of quest queue setting in +0x01b0[15:0] +* RESERVED12[15..12] - (RO) Reserved bits +* QUEUE_TAIL_FID[27..16] - (RO) Tail frame ID of quest queue setting in +0x01b0[15:0] +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_ADDR \ +WF_PSE_TOP_FL_QUE_CTRL_2_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_MASK \ +0x0FFF0000 /* QUEUE_TAIL_FID[27..16] */ +#define WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_SHFT 16 +#define WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_ADDR \ +WF_PSE_TOP_FL_QUE_CTRL_2_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_MASK \ +0x00000FFF /* QUEUE_HEAD_FID[11..0] */ +#define WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_SHFT 0 + +/* +* ---FL_QUE_CTRL_3 (0x820C8000 + 0x1BC)--- +* QUEUE_PKT_NUM[11..0] - (RO) Total packet number of queue setting in +0x1b0[15:0] +* QUEUE_PAGE_NUM[23..12] - (RO) Total page number of queue setting in +0x1b0[15:0] +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_FL_QUE_CTRL_3_QUEUE_PAGE_NUM_ADDR \ +WF_PSE_TOP_FL_QUE_CTRL_3_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_3_QUEUE_PAGE_NUM_MASK \ +0x00FFF000 /* QUEUE_PAGE_NUM[23..12] */ +#define WF_PSE_TOP_FL_QUE_CTRL_3_QUEUE_PAGE_NUM_SHFT 12 +#define WF_PSE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_ADDR \ +WF_PSE_TOP_FL_QUE_CTRL_3_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_MASK \ +0x00000FFF /* QUEUE_PKT_NUM[11..0] */ +#define WF_PSE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_SHFT 0 + +/* +* ---PL_QUE_CTRL_0 (0x820C8000 + 0x1C0)--- +* NEXT_PAGE[11..0] - (RO) Next page of the PL_BUFFER_ADDR +* RESERVED12[15..12] - (RO) Reserved bits +* PL_BUFFER_ADDR[27..16] - (RW) Page address of read next page +* RESERVED28[30..28] - (RO) Reserved bits +* EXECUTE[31] - (A0) Executes page link buffer read command +*/ +#define WF_PSE_TOP_PL_QUE_CTRL_0_EXECUTE_ADDR WF_PSE_TOP_PL_QUE_CTRL_0_ADDR +#define WF_PSE_TOP_PL_QUE_CTRL_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PSE_TOP_PL_QUE_CTRL_0_EXECUTE_SHFT 31 +#define WF_PSE_TOP_PL_QUE_CTRL_0_PL_BUFFER_ADDR_ADDR \ +WF_PSE_TOP_PL_QUE_CTRL_0_ADDR +#define WF_PSE_TOP_PL_QUE_CTRL_0_PL_BUFFER_ADDR_MASK \ +0x0FFF0000 /* PL_BUFFER_ADDR[27..16] */ +#define WF_PSE_TOP_PL_QUE_CTRL_0_PL_BUFFER_ADDR_SHFT 16 +#define WF_PSE_TOP_PL_QUE_CTRL_0_NEXT_PAGE_ADDR WF_PSE_TOP_PL_QUE_CTRL_0_ADDR +#define WF_PSE_TOP_PL_QUE_CTRL_0_NEXT_PAGE_MASK \ +0x00000FFF /* NEXT_PAGE[11..0] */ +#define WF_PSE_TOP_PL_QUE_CTRL_0_NEXT_PAGE_SHFT 0 + +/* +* ---PSE_LP_CTRL (0x820C8000 + 0x1D0)--- +* RESERVED0[6..0] - (RO) Reserved bits +* PSE_LP_WAKEUP[7] - (RW) PSE Low Power Wakeup control +* PSE2HIF_PSSS_EN[8] - (RW) PSE Access HIF port control +* MCU_COALEASCE[9] - (RW) Coalease CPU ENQ and ENQ_DLY for HIF +port +* RESERVED10[31..10] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_LP_CTRL_MCU_COALEASCE_ADDR WF_PSE_TOP_PSE_LP_CTRL_ADDR +#define WF_PSE_TOP_PSE_LP_CTRL_MCU_COALEASCE_MASK \ +0x00000200 /* MCU_COALEASCE[9] */ +#define WF_PSE_TOP_PSE_LP_CTRL_MCU_COALEASCE_SHFT 9 +#define WF_PSE_TOP_PSE_LP_CTRL_PSE2HIF_PSSS_EN_ADDR WF_PSE_TOP_PSE_LP_CTRL_ADDR +#define WF_PSE_TOP_PSE_LP_CTRL_PSE2HIF_PSSS_EN_MASK \ +0x00000100 /* PSE2HIF_PSSS_EN[8] */ +#define WF_PSE_TOP_PSE_LP_CTRL_PSE2HIF_PSSS_EN_SHFT 8 +#define WF_PSE_TOP_PSE_LP_CTRL_PSE_LP_WAKEUP_ADDR WF_PSE_TOP_PSE_LP_CTRL_ADDR +#define WF_PSE_TOP_PSE_LP_CTRL_PSE_LP_WAKEUP_MASK \ +0x00000080 /* PSE_LP_WAKEUP[7] */ +#define WF_PSE_TOP_PSE_LP_CTRL_PSE_LP_WAKEUP_SHFT 7 + +/* +* ---PSE_WFDMA_BUF_CTRL (0x820C8000 + 0x1E0)--- +* WFDMA_TXS_BUF_VLD_TH[7..0] - (RW) TXS valid reserved page count threshold +* WFDMA_TXCMD_BUF_VLD_TH[15..8] - (RW) TXCMD valid reserved page count +threshold +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_WFDMA_TXCMD_BUF_VLD_TH_ADDR \ +WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_ADDR +#define WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_WFDMA_TXCMD_BUF_VLD_TH_MASK \ +0x0000FF00 /* WFDMA_TXCMD_BUF_VLD_TH[15..8] */ +#define WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_WFDMA_TXCMD_BUF_VLD_TH_SHFT 8 +#define WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_WFDMA_TXS_BUF_VLD_TH_ADDR \ +WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_ADDR +#define WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_WFDMA_TXS_BUF_VLD_TH_MASK \ +0x000000FF /* WFDMA_TXS_BUF_VLD_TH[7..0] */ +#define WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_WFDMA_TXS_BUF_VLD_TH_SHFT 0 + +/* +* ---PSE_CT_PRI_CTRL (0x820C8000 + 0x1EC)--- +* PSE_CT_PRI_LOW_LV[11..0] - (RW) Low trigger level of Group0 qouta +* RESERVED12[15..12] - (RO) Reserved bits +* PSE_CT_PRI_HI_LV[27..16] - (RW) High trigger level of Group0 qouta +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_CT_PRI_CTRL_PSE_CT_PRI_HI_LV_ADDR \ +WF_PSE_TOP_PSE_CT_PRI_CTRL_ADDR +#define WF_PSE_TOP_PSE_CT_PRI_CTRL_PSE_CT_PRI_HI_LV_MASK \ +0x0FFF0000 /* PSE_CT_PRI_HI_LV[27..16] */ +#define WF_PSE_TOP_PSE_CT_PRI_CTRL_PSE_CT_PRI_HI_LV_SHFT 16 +#define WF_PSE_TOP_PSE_CT_PRI_CTRL_PSE_CT_PRI_LOW_LV_ADDR \ +WF_PSE_TOP_PSE_CT_PRI_CTRL_ADDR +#define WF_PSE_TOP_PSE_CT_PRI_CTRL_PSE_CT_PRI_LOW_LV_MASK \ +0x00000FFF /* PSE_CT_PRI_LOW_LV[11..0] */ +#define WF_PSE_TOP_PSE_CT_PRI_CTRL_PSE_CT_PRI_LOW_LV_SHFT 0 + +/* +* ---PLE_ENQ_PKT_NUM (0x820C8000 + 0x1F0)--- +* PLE_ENQ_HIF_Q_PKT_NUM[15..0] - (RO) The packets numbers of PLE port enqueue +* to HIF queue. +* PLE_ENQ_HIF_Q_SEL[19..16] - (RW) Select HIF queue which is PLE port +* enqueue to. +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PLE_ENQ_PKT_NUM_PLE_ENQ_HIF_Q_SEL_ADDR \ +WF_PSE_TOP_PLE_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_PLE_ENQ_PKT_NUM_PLE_ENQ_HIF_Q_SEL_MASK \ +0x000F0000 /* PLE_ENQ_HIF_Q_SEL[19..16] */ +#define WF_PSE_TOP_PLE_ENQ_PKT_NUM_PLE_ENQ_HIF_Q_SEL_SHFT 16 +#define WF_PSE_TOP_PLE_ENQ_PKT_NUM_PLE_ENQ_HIF_Q_PKT_NUM_ADDR \ +WF_PSE_TOP_PLE_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_PLE_ENQ_PKT_NUM_PLE_ENQ_HIF_Q_PKT_NUM_MASK \ +0x0000FFFF /* PLE_ENQ_HIF_Q_PKT_NUM[15..0] */ +#define WF_PSE_TOP_PLE_ENQ_PKT_NUM_PLE_ENQ_HIF_Q_PKT_NUM_SHFT 0 + +/* +* ---CPU_ENQ_PKT_NUM (0x820C8000 + 0x1F4)--- +* CPU_ENQ_HIF_Q_PKT_NUM[15..0] - (RO) The packets numbers of CPU port enqueue +* to HIF queue. +* CPU_ENQ_HIF_Q_SEL[19..16] - (RW) Select HIF queue which is CPU port +* enqueue to. +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_HIF_Q_SEL_ADDR \ +WF_PSE_TOP_CPU_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_HIF_Q_SEL_MASK \ +0x000F0000 /* CPU_ENQ_HIF_Q_SEL[19..16] */ +#define WF_PSE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_HIF_Q_SEL_SHFT 16 +#define WF_PSE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_HIF_Q_PKT_NUM_ADDR \ +WF_PSE_TOP_CPU_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_HIF_Q_PKT_NUM_MASK \ +0x0000FFFF /* CPU_ENQ_HIF_Q_PKT_NUM[15..0] */ +#define WF_PSE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_HIF_Q_PKT_NUM_SHFT 0 + +/* +* ---LMAC_ENQ_PKT_NUM (0x820C8000 + 0x1F8)--- +* LMAC_ENQ_HIF_Q_PKT_NUM[15..0] - (RO) The packets numbers of LMAC port +* enqueue to HIF queue. +* LMAC_ENQ_HIF_Q_SEL[19..16] - (RW) Select HIF queue which is LMAC port +* enqueue to. +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_LMAC_ENQ_PKT_NUM_LMAC_ENQ_HIF_Q_SEL_ADDR \ +WF_PSE_TOP_LMAC_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_LMAC_ENQ_PKT_NUM_LMAC_ENQ_HIF_Q_SEL_MASK \ +0x000F0000 /* LMAC_ENQ_HIF_Q_SEL[19..16] */ +#define WF_PSE_TOP_LMAC_ENQ_PKT_NUM_LMAC_ENQ_HIF_Q_SEL_SHFT 16 +#define WF_PSE_TOP_LMAC_ENQ_PKT_NUM_LMAC_ENQ_HIF_Q_PKT_NUM_ADDR \ +WF_PSE_TOP_LMAC_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_LMAC_ENQ_PKT_NUM_LMAC_ENQ_HIF_Q_PKT_NUM_MASK \ +0x0000FFFF /* LMAC_ENQ_HIF_Q_PKT_NUM[15..0] */ +#define WF_PSE_TOP_LMAC_ENQ_PKT_NUM_LMAC_ENQ_HIF_Q_PKT_NUM_SHFT 0 + +/* +* ---HIF_ENQ_PKT_NUM (0x820C8000 + 0x1FC)--- +* HIF_ENQ_MDP[15..0] - (RO) The packets numbers of HIF port enqueue +* to MDP TX queue. +* HIF_ENQ_CPU[31..16] - (RO) The packets numbers of HIF port enqueue +* to CPU queue +*/ +#define WF_PSE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_CPU_ADDR \ +WF_PSE_TOP_HIF_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_CPU_MASK \ +0xFFFF0000 /* HIF_ENQ_CPU[31..16] */ +#define WF_PSE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_CPU_SHFT 16 +#define WF_PSE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_MDP_ADDR \ +WF_PSE_TOP_HIF_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_MDP_MASK \ +0x0000FFFF /* HIF_ENQ_MDP[15..0] */ +#define WF_PSE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_MDP_SHFT 0 + +/* +* ---MDP_ENQ_PKT_NUM (0x820C8000 + 0x200)--- +* MDP_ENQ_HIF_Q_PKT_NUM[15..0] - (RO) The packets numbers of MDP port enqueue +* to HIF queue. +* MDP_ENQ_HIF_Q_SEL[31..16] - (RW) Select HIF queue which is MDP port +* enqueue to. +*/ +#define WF_PSE_TOP_MDP_ENQ_PKT_NUM_MDP_ENQ_HIF_Q_SEL_ADDR \ +WF_PSE_TOP_MDP_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_MDP_ENQ_PKT_NUM_MDP_ENQ_HIF_Q_SEL_MASK \ +0xFFFF0000 /* MDP_ENQ_HIF_Q_SEL[31..16] */ +#define WF_PSE_TOP_MDP_ENQ_PKT_NUM_MDP_ENQ_HIF_Q_SEL_SHFT 16 +#define WF_PSE_TOP_MDP_ENQ_PKT_NUM_MDP_ENQ_HIF_Q_PKT_NUM_ADDR \ +WF_PSE_TOP_MDP_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_MDP_ENQ_PKT_NUM_MDP_ENQ_HIF_Q_PKT_NUM_MASK \ +0x0000FFFF /* MDP_ENQ_HIF_Q_PKT_NUM[15..0] */ +#define WF_PSE_TOP_MDP_ENQ_PKT_NUM_MDP_ENQ_HIF_Q_PKT_NUM_SHFT 0 + +/* +* ---TIMEOUT_CTRL (0x820C8000 + 0x244)--- +* FL_WD_TO_CTRL[7..0] - (RW) FL watch dog timeput +* RESERVED8[15..8] - (RO) Reserved bits +* APB_WD_TO_CTRL[23..16] - (RW) APB pready watch dog timeout control +register. +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_TIMEOUT_CTRL_APB_WD_TO_CTRL_ADDR WF_PSE_TOP_TIMEOUT_CTRL_ADDR +#define WF_PSE_TOP_TIMEOUT_CTRL_APB_WD_TO_CTRL_MASK \ +0x00FF0000 /* APB_WD_TO_CTRL[23..16] */ +#define WF_PSE_TOP_TIMEOUT_CTRL_APB_WD_TO_CTRL_SHFT 16 +#define WF_PSE_TOP_TIMEOUT_CTRL_FL_WD_TO_CTRL_ADDR WF_PSE_TOP_TIMEOUT_CTRL_ADDR +#define WF_PSE_TOP_TIMEOUT_CTRL_FL_WD_TO_CTRL_MASK \ +0x000000FF /* FL_WD_TO_CTRL[7..0] */ +#define WF_PSE_TOP_TIMEOUT_CTRL_FL_WD_TO_CTRL_SHFT 0 + +/* +* ---FSM_IDLE_WD_CTRL (0x820C8000 + 0x24C)--- +* FL_IDLE_WD_TO_TH[7..0] - (RW) Watchdog timeout threshold for frame +* link FSM not returning to IDLE +* PL_IDLE_WD_TO_TH[15..8] - (RW) Watchdog timeout threshold for page link +* FSM not returning to IDLE +* PORT_IDLE_WD_TO_TH[23..16] - (RW) Watchdog timeout threshold for page link +* Port Link not returning to IDLE +* (Including HIF/CPU/LMAC port) +* MACTX_IDLE_WD_TO_TH[31..24] - (RW) Watchdog timeout threshold for port oper +* MACTX not returning to IDLE +*/ +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_MACTX_IDLE_WD_TO_TH_ADDR \ +WF_PSE_TOP_FSM_IDLE_WD_CTRL_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_MACTX_IDLE_WD_TO_TH_MASK \ +0xFF000000 /* MACTX_IDLE_WD_TO_TH[31..24] */ +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_MACTX_IDLE_WD_TO_TH_SHFT 24 +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_PORT_IDLE_WD_TO_TH_ADDR \ +WF_PSE_TOP_FSM_IDLE_WD_CTRL_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_PORT_IDLE_WD_TO_TH_MASK \ +0x00FF0000 /* PORT_IDLE_WD_TO_TH[23..16] */ +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_PORT_IDLE_WD_TO_TH_SHFT 16 +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_PL_IDLE_WD_TO_TH_ADDR \ +WF_PSE_TOP_FSM_IDLE_WD_CTRL_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_PL_IDLE_WD_TO_TH_MASK \ +0x0000FF00 /* PL_IDLE_WD_TO_TH[15..8] */ +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_PL_IDLE_WD_TO_TH_SHFT 8 +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_FL_IDLE_WD_TO_TH_ADDR \ +WF_PSE_TOP_FSM_IDLE_WD_CTRL_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_FL_IDLE_WD_TO_TH_MASK \ +0x000000FF /* FL_IDLE_WD_TO_TH[7..0] */ +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_FL_IDLE_WD_TO_TH_SHFT 0 + +/* +* ---FSM_IDLE_WD_EN (0x820C8000 + 0x250)--- +* EN_HIF_PORT_IDLE_WD_TO[0] - (RW) Enables watchdog for HIF port oper FSM +* not returning to IDLE +* EN_CPU_PORT_IDLE_WD_TO[1] - (RW) Enables watchdog for CPU port oper FSM +* not returning to IDLE +* EN_LMAC_PORT_IDLE_WD_TO[2] - (RW) Enables watchdog for LMAC port oper FSM +* not returning to IDLE +* EN_MDP_IDLE_WD_TO[3] - (RW) Enables watchdog for MDP port oper FSM +* not returning to IDLE +* EN_SEC_IDLE_WD_TO[4] - (RW) Enables watchdog for SEC port oper FSM +* not returning to IDLE +* EN_PLE_IDLE_WD_TO[5] - (RW) Enables watchdog for PLE port oper FSM +* not returning to IDLE +* EN_AMSDU_IDLE_WD_TO[6] - (RW) Enables watchdog for AMSDU port oper FSM +* not returning to IDLE +* RESERVED7[7] - (RO) Reserved bits +* EN_FL_IDLE_WD_TO[8] - (RW) Enables watchdog for frame link FSM not +* returning to IDLE +* EN_PL_IDLE_WD_TO[9] - (RW) Enables watchdog for page link FSM not +* returning to IDLE +* RESERVED10[31..10] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_PL_IDLE_WD_TO_ADDR \ +WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_PL_IDLE_WD_TO_MASK \ +0x00000200 /* EN_PL_IDLE_WD_TO[9] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_PL_IDLE_WD_TO_SHFT 9 +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_FL_IDLE_WD_TO_ADDR \ +WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_FL_IDLE_WD_TO_MASK \ +0x00000100 /* EN_FL_IDLE_WD_TO[8] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_FL_IDLE_WD_TO_SHFT 8 +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_AMSDU_IDLE_WD_TO_ADDR \ +WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_AMSDU_IDLE_WD_TO_MASK \ +0x00000040 /* EN_AMSDU_IDLE_WD_TO[6] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_AMSDU_IDLE_WD_TO_SHFT 6 +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_PLE_IDLE_WD_TO_ADDR \ +WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_PLE_IDLE_WD_TO_MASK \ +0x00000020 /* EN_PLE_IDLE_WD_TO[5] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_PLE_IDLE_WD_TO_SHFT 5 +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_SEC_IDLE_WD_TO_ADDR \ +WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_SEC_IDLE_WD_TO_MASK \ +0x00000010 /* EN_SEC_IDLE_WD_TO[4] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_SEC_IDLE_WD_TO_SHFT 4 +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_MDP_IDLE_WD_TO_ADDR \ +WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_MDP_IDLE_WD_TO_MASK \ +0x00000008 /* EN_MDP_IDLE_WD_TO[3] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_MDP_IDLE_WD_TO_SHFT 3 +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_LMAC_PORT_IDLE_WD_TO_ADDR \ +WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_LMAC_PORT_IDLE_WD_TO_MASK \ +0x00000004 /* EN_LMAC_PORT_IDLE_WD_TO[2] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_LMAC_PORT_IDLE_WD_TO_SHFT 2 +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_CPU_PORT_IDLE_WD_TO_ADDR \ +WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_CPU_PORT_IDLE_WD_TO_MASK \ +0x00000002 /* EN_CPU_PORT_IDLE_WD_TO[1] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_CPU_PORT_IDLE_WD_TO_SHFT 1 +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_HIF_PORT_IDLE_WD_TO_ADDR \ +WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_HIF_PORT_IDLE_WD_TO_MASK \ +0x00000001 /* EN_HIF_PORT_IDLE_WD_TO[0] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_HIF_PORT_IDLE_WD_TO_SHFT 0 + +/* +* ---PSE_INTER_ERR_FLAG (0x820C8000 + 0x280)--- +* DEQ_EMPTY_QUEUE[0] - (RO) DEQueue Empty Error Flag +* APB_WD_TO[1] - (RO) APB Write Data Timeout Error Flag +* FL_CTRL_WD_TO[2] - (RO) FL Write Data Timeout Error Flag +* RESERVED3[31..3] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_FL_CTRL_WD_TO_ADDR \ +WF_PSE_TOP_PSE_INTER_ERR_FLAG_ADDR +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_FL_CTRL_WD_TO_MASK \ +0x00000004 /* FL_CTRL_WD_TO[2] */ +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_FL_CTRL_WD_TO_SHFT 2 +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_APB_WD_TO_ADDR \ +WF_PSE_TOP_PSE_INTER_ERR_FLAG_ADDR +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_APB_WD_TO_MASK \ +0x00000002 /* APB_WD_TO[1] */ +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_APB_WD_TO_SHFT 1 +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_DEQ_EMPTY_QUEUE_ADDR \ +WF_PSE_TOP_PSE_INTER_ERR_FLAG_ADDR +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_DEQ_EMPTY_QUEUE_MASK \ +0x00000001 /* DEQ_EMPTY_QUEUE[0] */ +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_DEQ_EMPTY_QUEUE_SHFT 0 + +/* +* ---PSE_SER_CTRL (0x820C8000 + 0x2a0)--- +* HIF_SER_PAUSE_ALLOCATE[0] - (RW) System Error Recover function for Pause +* HIFBuffer Allocation +* CPU_SER_PAUSE_ALLOCATE[1] - (RW) System Error Recover function for Pause +* CPU Buffer Allocation +* WF_SER_PAUSE_ALLOCATE[2] - (RW) System Error Recover function for Pause +* WF Buffer Allocation +* MDP_SER_PAUSE_ALLOCATE[3] - (RW) System Error Recover function for Pause +* MDP Buffer Allocation +* SEC_SER_PAUSE_ALLOCATE[4] - (RW) System Error Recover function for Pause +* SEC Buffer Allocation +* PLE_SER_PAUSE_ALLOCATE[5] - (RW) System Error Recover function for Pause +* PLE Buffer Allocation +* RESERVED6[7..6] - (RO) Reserved bits +* HIF_SER_PAUSE_DATA[8] - (RW) System Error Recover function for Pause +* HIF DATA opeartion. +* CPU_SER_PAUSE_DATA[9] - (RW) System Error Recover function for Pause +* CPU DATA opeartion. +* WF_SER_PAUSE_DATA[10] - (RW) System Error Recover function for Pause +* WF DATA opeartion. +* MDP_SER_PAUSE_DATA[11] - (RW) System Error Recover function for Pause +* MDP DATA opeartion. +* SEC_SER_PAUSE_DATA[12] - (RW) System Error Recover function for Pause +* SEC DATA opeartion. +* PLE_SER_PAUSE_DATA[13] - (RW) System Error Recover function for Pause +* PLE DATA opeartion. +* RESERVED14[15..14] - (RO) Reserved bits +* HIF_SER_PAUSE_QUEUE[16] - (RW) System Error Recover function for Pause +* HIF Queue opeartion. +* CPU_SER_PAUSE_QUEUE[17] - (RW) System Error Recover function for Pause +* CPU Queue opeartion. +* WF_SER_PAUSE_QUEUE[18] - (RW) System Error Recover function for Pause +* WF Queue opeartion. +* MDP_SER_PAUSE_QUEUE[19] - (RW) System Error Recover function for Pause +* MDP Queue opeartion. +* SEC_SER_PAUSE_QUEUE[20] - (RW) System Error Recover function for Pause +* SEC Queue opeartion. +* PLE_SER_PAUSE_QUEUE[21] - (RW) System Error Recover function for Pause +* PLE Queue opeartion. +* RESERVED22[31..22] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_QUEUE_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_QUEUE_MASK \ +0x00200000 /* PLE_SER_PAUSE_QUEUE[21] */ +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_QUEUE_SHFT 21 +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_QUEUE_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_QUEUE_MASK \ +0x00100000 /* SEC_SER_PAUSE_QUEUE[20] */ +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_QUEUE_SHFT 20 +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_QUEUE_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_QUEUE_MASK \ +0x00080000 /* MDP_SER_PAUSE_QUEUE[19] */ +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_QUEUE_SHFT 19 +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_QUEUE_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_QUEUE_MASK \ +0x00040000 /* WF_SER_PAUSE_QUEUE[18] */ +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_QUEUE_SHFT 18 +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_QUEUE_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_QUEUE_MASK \ +0x00020000 /* CPU_SER_PAUSE_QUEUE[17] */ +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_QUEUE_SHFT 17 +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_QUEUE_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_QUEUE_MASK \ +0x00010000 /* HIF_SER_PAUSE_QUEUE[16] */ +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_QUEUE_SHFT 16 +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_DATA_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_DATA_MASK \ +0x00002000 /* PLE_SER_PAUSE_DATA[13] */ +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_DATA_SHFT 13 +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_DATA_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_DATA_MASK \ +0x00001000 /* SEC_SER_PAUSE_DATA[12] */ +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_DATA_SHFT 12 +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_DATA_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_DATA_MASK \ +0x00000800 /* MDP_SER_PAUSE_DATA[11] */ +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_DATA_SHFT 11 +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_DATA_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_DATA_MASK \ +0x00000400 /* WF_SER_PAUSE_DATA[10] */ +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_DATA_SHFT 10 +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_DATA_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_DATA_MASK \ +0x00000200 /* CPU_SER_PAUSE_DATA[9] */ +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_DATA_SHFT 9 +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_DATA_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_DATA_MASK \ +0x00000100 /* HIF_SER_PAUSE_DATA[8] */ +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_DATA_SHFT 8 +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_ALLOCATE_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_ALLOCATE_MASK \ +0x00000020 /* PLE_SER_PAUSE_ALLOCATE[5] */ +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_ALLOCATE_SHFT 5 +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_ALLOCATE_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_ALLOCATE_MASK \ +0x00000010 /* SEC_SER_PAUSE_ALLOCATE[4] */ +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_ALLOCATE_SHFT 4 +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_ALLOCATE_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_ALLOCATE_MASK \ +0x00000008 /* MDP_SER_PAUSE_ALLOCATE[3] */ +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_ALLOCATE_SHFT 3 +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_ALLOCATE_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_ALLOCATE_MASK \ +0x00000004 /* WF_SER_PAUSE_ALLOCATE[2] */ +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_ALLOCATE_SHFT 2 +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_ALLOCATE_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_ALLOCATE_MASK \ +0x00000002 /* CPU_SER_PAUSE_ALLOCATE[1] */ +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_ALLOCATE_SHFT 1 +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_ALLOCATE_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_ALLOCATE_MASK \ +0x00000001 /* HIF_SER_PAUSE_ALLOCATE[0] */ +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_ALLOCATE_SHFT 0 + +/* +* ---PSE_MBIST_RP_FUSE (0x820C8000 + 0x2b0)--- +* WF_PSE_MBIST_RP_FAIL[3..0] - (RO) MBIST Repair FAIL report +* RESERVED4[7..4] - (RO) Reserved bits +* WF_PSE_MBIST_RP_OK[11..8] - (RO) MBIST Repair OK report +* RESERVED12[14..12] - (RO) Reserved bits +* REG_FUSE_SEL[15] - (RW) MBIST FUSE setting +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_REG_FUSE_SEL_ADDR \ +WF_PSE_TOP_PSE_MBIST_RP_FUSE_ADDR +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_REG_FUSE_SEL_MASK \ +0x00008000 /* REG_FUSE_SEL[15] */ +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_REG_FUSE_SEL_SHFT 15 +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_WF_PSE_MBIST_RP_OK_ADDR \ +WF_PSE_TOP_PSE_MBIST_RP_FUSE_ADDR +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_WF_PSE_MBIST_RP_OK_MASK \ +0x00000F00 /* WF_PSE_MBIST_RP_OK[11..8] */ +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_WF_PSE_MBIST_RP_OK_SHFT 8 +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_WF_PSE_MBIST_RP_FAIL_ADDR \ +WF_PSE_TOP_PSE_MBIST_RP_FUSE_ADDR +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_WF_PSE_MBIST_RP_FAIL_MASK \ +0x0000000F /* WF_PSE_MBIST_RP_FAIL[3..0] */ +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_WF_PSE_MBIST_RP_FAIL_SHFT 0 + +/* +* ---PSE_MBIST_BSEL (0x820C8000 + 0x2b4)--- +* WF_PSE_MBIST_BSEL[15..0] - (RW) Memory MBIST BSEL control +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_MBIST_BSEL_WF_PSE_MBIST_BSEL_ADDR \ +WF_PSE_TOP_PSE_MBIST_BSEL_ADDR +#define WF_PSE_TOP_PSE_MBIST_BSEL_WF_PSE_MBIST_BSEL_MASK \ +0x0000FFFF /* WF_PSE_MBIST_BSEL[15..0] */ +#define WF_PSE_TOP_PSE_MBIST_BSEL_WF_PSE_MBIST_BSEL_SHFT 0 + +/* +* ---PSE_MBIST_RP_FUSE_1 (0x820C8000 + 0x2b8)--- +* WF_UMAC_TOP_MBIST_PREFUSE_0[15..0] - (RW) MBIST PRE-FUSE setting +* WF_UMAC_TOP_MBIST_PREFUSE_D_0[31..16] - (RO) MBIST PRE-FUSE result +*/ +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_WF_UMAC_TOP_MBIST_PREFUSE_D_0_ADDR \ +WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_ADDR +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_WF_UMAC_TOP_MBIST_PREFUSE_D_0_MASK \ +0xFFFF0000 /* WF_UMAC_TOP_MBIST_PREFUSE_D_0[31..16] */ +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_WF_UMAC_TOP_MBIST_PREFUSE_D_0_SHFT 16 +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_WF_UMAC_TOP_MBIST_PREFUSE_0_ADDR \ +WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_ADDR +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_WF_UMAC_TOP_MBIST_PREFUSE_0_MASK \ +0x0000FFFF /* WF_UMAC_TOP_MBIST_PREFUSE_0[15..0] */ +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_WF_UMAC_TOP_MBIST_PREFUSE_0_SHFT 0 + +/* +* ---SRAM_MBIST_BACKGROUND (0x820C8000 + 0x2d0)--- +* MBIST_BACKGROUND[15..0] - (RW) Background setting for PSE SRAM MBIST +circuit +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_SRAM_MBIST_BACKGROUND_MBIST_BACKGROUND_ADDR \ +WF_PSE_TOP_SRAM_MBIST_BACKGROUND_ADDR +#define WF_PSE_TOP_SRAM_MBIST_BACKGROUND_MBIST_BACKGROUND_MASK \ +0x0000FFFF /* MBIST_BACKGROUND[15..0] */ +#define WF_PSE_TOP_SRAM_MBIST_BACKGROUND_MBIST_BACKGROUND_SHFT 0 + +/* +* ---PSE_MISC_FUNC_CTRL (0x820C8000 + 0x2d4)--- +* RESERVED0[7..0] - (RO) Reserved bits +* PSE_QUEUE_ACK_MODE[8] - (RW) Queue ACK mode control +* RESERVED9[29..9] - (RO) Reserved bits +* DIS_BYPASS_INVALID_FID[30] - (RW) Bypass invalid FID control +* DIS_BLOCK_MODE[31] - (RW) Block Mode Control +*/ +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_DIS_BLOCK_MODE_ADDR \ +WF_PSE_TOP_PSE_MISC_FUNC_CTRL_ADDR +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_DIS_BLOCK_MODE_MASK \ +0x80000000 /* DIS_BLOCK_MODE[31] */ +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_DIS_BLOCK_MODE_SHFT 31 +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_DIS_BYPASS_INVALID_FID_ADDR \ +WF_PSE_TOP_PSE_MISC_FUNC_CTRL_ADDR +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_DIS_BYPASS_INVALID_FID_MASK \ +0x40000000 /* DIS_BYPASS_INVALID_FID[30] */ +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_DIS_BYPASS_INVALID_FID_SHFT 30 +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_PSE_QUEUE_ACK_MODE_ADDR \ +WF_PSE_TOP_PSE_MISC_FUNC_CTRL_ADDR +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_PSE_QUEUE_ACK_MODE_MASK \ +0x00000100 /* PSE_QUEUE_ACK_MODE[8] */ +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_PSE_QUEUE_ACK_MODE_SHFT 8 + +/* +* ---SRAM_MBIST_DONE (0x820C8000 + 0x2d8)--- +* MBIST_DONE[0] - (RO) Working status of PSE SRAM MBIST circuit +* RESERVED1[31..1] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_SRAM_MBIST_DONE_MBIST_DONE_ADDR \ +WF_PSE_TOP_SRAM_MBIST_DONE_ADDR +#define WF_PSE_TOP_SRAM_MBIST_DONE_MBIST_DONE_MASK \ +0x00000001 /* MBIST_DONE[0] */ +#define WF_PSE_TOP_SRAM_MBIST_DONE_MBIST_DONE_SHFT 0 + +/* +* ---SRAM_MBIST_FAIL (0x820C8000 + 0x2dc)--- +* FORDLINK_SRAM_MBIST_FAIL[0] - (RO) MBIST check result of forward link SRAM +* BACKLINK_SRAM_MBIST_FAIL[1] - (RO) MBIST check result of backward link SRAM +* PAGELINK_SRAM_MBIST_FAIL[2] - (RO) MBIST check result of PAGELINK SRAM +* RLINFO_SRAM_MBIST_FAIL[3] - (RO) MBIST check result of RLINFO SRAM +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_SRAM_MBIST_FAIL_RLINFO_SRAM_MBIST_FAIL_ADDR \ +WF_PSE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_FAIL_RLINFO_SRAM_MBIST_FAIL_MASK \ +0x00000008 /* RLINFO_SRAM_MBIST_FAIL[3] */ +#define WF_PSE_TOP_SRAM_MBIST_FAIL_RLINFO_SRAM_MBIST_FAIL_SHFT 3 +#define WF_PSE_TOP_SRAM_MBIST_FAIL_PAGELINK_SRAM_MBIST_FAIL_ADDR \ +WF_PSE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_FAIL_PAGELINK_SRAM_MBIST_FAIL_MASK \ +0x00000004 /* PAGELINK_SRAM_MBIST_FAIL[2] */ +#define WF_PSE_TOP_SRAM_MBIST_FAIL_PAGELINK_SRAM_MBIST_FAIL_SHFT 2 +#define WF_PSE_TOP_SRAM_MBIST_FAIL_BACKLINK_SRAM_MBIST_FAIL_ADDR \ +WF_PSE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_FAIL_BACKLINK_SRAM_MBIST_FAIL_MASK \ +0x00000002 /* BACKLINK_SRAM_MBIST_FAIL[1] */ +#define WF_PSE_TOP_SRAM_MBIST_FAIL_BACKLINK_SRAM_MBIST_FAIL_SHFT 1 +#define WF_PSE_TOP_SRAM_MBIST_FAIL_FORDLINK_SRAM_MBIST_FAIL_ADDR \ +WF_PSE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_FAIL_FORDLINK_SRAM_MBIST_FAIL_MASK \ +0x00000001 /* FORDLINK_SRAM_MBIST_FAIL[0] */ +#define WF_PSE_TOP_SRAM_MBIST_FAIL_FORDLINK_SRAM_MBIST_FAIL_SHFT 0 + +/* +* ---SRAM_MBIST_CTRL (0x820C8000 + 0x2e0)--- +* MBIST_MODE[0] - (RW) Control register for mbist_mode of MBIST +* RESERVED1[3..1] - (RO) Reserved bits +* MBIST_HOLDB[4] - (RW) Control register for mbist_holdb of +MBIST +* RESERVED5[7..5] - (RO) Reserved bits +* MBIST_DEBUG[8] - (RW) Control register for mbist_debug of +MBIST +* MBIST_RPRST_B[9] - (RW) MBIST Repair function Enable +* MBIST_USE_DEFAULT_DELSEL[10] - (RW) MBIST delay select control +* RESERVED11[15..11] - (RO) Reserved bits +* MBIST_DIAG_SEL[19..16] - (RW) Selection register for +mbist_diag_scan_out +* RESERVED20[23..20] - (RO) Reserved bits +* MBIST_SLEEP_TEST[24] - (RW) Control register for sleep_test of MBIST +* MBIST_SLEEP_INV[25] - (RW) Control register for sleep_inv of MBIST +* MBIST_SLEEP_W[26] - (RW) Control register for sleep_w of MBIST +* MBIST_SLEEP_R[27] - (RW) Control register for sleep_r of MBIST +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_R_ADDR \ +WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_R_MASK \ +0x08000000 /* MBIST_SLEEP_R[27] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_R_SHFT 27 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_W_ADDR \ +WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_W_MASK \ +0x04000000 /* MBIST_SLEEP_W[26] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_W_SHFT 26 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_INV_ADDR \ +WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_INV_MASK \ +0x02000000 /* MBIST_SLEEP_INV[25] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_INV_SHFT 25 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_TEST_ADDR \ +WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_TEST_MASK \ +0x01000000 /* MBIST_SLEEP_TEST[24] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_TEST_SHFT 24 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_DIAG_SEL_ADDR \ +WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_DIAG_SEL_MASK \ +0x000F0000 /* MBIST_DIAG_SEL[19..16] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_DIAG_SEL_SHFT 16 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_USE_DEFAULT_DELSEL_ADDR \ +WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_USE_DEFAULT_DELSEL_MASK \ +0x00000400 /* MBIST_USE_DEFAULT_DELSEL[10] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_USE_DEFAULT_DELSEL_SHFT 10 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_RPRST_B_ADDR \ +WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_RPRST_B_MASK \ +0x00000200 /* MBIST_RPRST_B[9] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_RPRST_B_SHFT 9 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_DEBUG_ADDR \ +WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_DEBUG_MASK \ +0x00000100 /* MBIST_DEBUG[8] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_DEBUG_SHFT 8 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_HOLDB_ADDR \ +WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_HOLDB_MASK \ +0x00000010 /* MBIST_HOLDB[4] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_HOLDB_SHFT 4 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_MODE_ADDR \ +WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_MODE_MASK \ +0x00000001 /* MBIST_MODE[0] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_MODE_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL (0x820C8000 + 0x2e4)--- +* MBIST_DELSEL0_2[31..0] - (RW) Control register of delsel for PL SRAM +*/ +#define WF_PSE_TOP_SRAM_MBIST_DELSEL_MBIST_DELSEL0_2_ADDR \ +WF_PSE_TOP_SRAM_MBIST_DELSEL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_DELSEL_MBIST_DELSEL0_2_MASK \ +0xFFFFFFFF /* MBIST_DELSEL0_2[31..0] */ +#define WF_PSE_TOP_SRAM_MBIST_DELSEL_MBIST_DELSEL0_2_SHFT 0 + +/* +* ---SRAM_AWT_HDEN_CTRL (0x820C8000 + 0x2e8)--- +* FL_TBL_AWT1[0] - (RW) Memory AWT Control for FL_TBL1 +* FL_TBL_AWT2[1] - (RW) Memory AWT Control for FL_TBL2 +* PL_TBL_AWT[2] - (RW) Memory AWT Control for PL +* RLINFO_MEM_AWT[3] - (RW) Memory AWT Control for RL +* RESERVED4[15..4] - (RO) Reserved bits +* FL_TBL_HDEN1[16] - (RW) Memory HDEN Control for FL_TBL1 +* FL_TBL_HDEN2[17] - (RW) Memory HDEN Control for FL_TBL2 +* PL_TBL_HDEN[18] - (RW) Memory HDEN Control for PL +* RLINFO_MEM_HDEN[19] - (RW) Memory HDEN Control for RL +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_RLINFO_MEM_HDEN_ADDR \ +WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_RLINFO_MEM_HDEN_MASK \ +0x00080000 /* RLINFO_MEM_HDEN[19] */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_RLINFO_MEM_HDEN_SHFT 19 +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_PL_TBL_HDEN_ADDR \ +WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_PL_TBL_HDEN_MASK \ +0x00040000 /* PL_TBL_HDEN[18] */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_PL_TBL_HDEN_SHFT 18 +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_HDEN2_ADDR \ +WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_HDEN2_MASK \ +0x00020000 /* FL_TBL_HDEN2[17] */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_HDEN2_SHFT 17 +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_HDEN1_ADDR \ +WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_HDEN1_MASK \ +0x00010000 /* FL_TBL_HDEN1[16] */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_HDEN1_SHFT 16 +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_RLINFO_MEM_AWT_ADDR \ +WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_RLINFO_MEM_AWT_MASK \ +0x00000008 /* RLINFO_MEM_AWT[3] */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_RLINFO_MEM_AWT_SHFT 3 +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_PL_TBL_AWT_ADDR \ +WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_PL_TBL_AWT_MASK \ +0x00000004 /* PL_TBL_AWT[2] */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_PL_TBL_AWT_SHFT 2 +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_AWT2_ADDR \ +WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_AWT2_MASK \ +0x00000002 /* FL_TBL_AWT2[1] */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_AWT2_SHFT 1 +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_AWT1_ADDR \ +WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_AWT1_MASK \ +0x00000001 /* FL_TBL_AWT1[0] */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_AWT1_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL_1 (0x820C8000 + 0x2f0)--- +* MBIST_DELSEL3[31..0] - (RW) Control register of delsel for RLINFO +SRAM +*/ +#define WF_PSE_TOP_SRAM_MBIST_DELSEL_1_MBIST_DELSEL3_ADDR \ +WF_PSE_TOP_SRAM_MBIST_DELSEL_1_ADDR +#define WF_PSE_TOP_SRAM_MBIST_DELSEL_1_MBIST_DELSEL3_MASK \ +0xFFFFFFFF /* MBIST_DELSEL3[31..0] */ +#define WF_PSE_TOP_SRAM_MBIST_DELSEL_1_MBIST_DELSEL3_SHFT 0 + +/* +* ---PSE_SEEK_CR_00 (0x820C8000 + 0x3d0)--- +* PSE_FL_ARB_CS[2..0] - (RO) PSE debug state for FL_ARB_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_FL_CS[7..4] - (RO) PSE debug state for FL_CS +* PSE_ENQ_FL_CS[11..8] - (RO) PSE debug state for ENQ_FL_CS +* PSE_DEQ_FL_CS[15..12] - (RO) PSE debug state for DEQ_FL_CS +* PSE_ACC_LST_CS[18..16] - (RO) PSE debug state for ACC_LST_CS +* RESERVED19[31..19] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_ACC_LST_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_00_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_ACC_LST_CS_MASK \ +0x00070000 /* PSE_ACC_LST_CS[18..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_ACC_LST_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_DEQ_FL_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_00_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_DEQ_FL_CS_MASK \ +0x0000F000 /* PSE_DEQ_FL_CS[15..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_DEQ_FL_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_ENQ_FL_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_00_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_ENQ_FL_CS_MASK \ +0x00000F00 /* PSE_ENQ_FL_CS[11..8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_ENQ_FL_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_FL_CS_ADDR WF_PSE_TOP_PSE_SEEK_CR_00_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_FL_CS_MASK \ +0x000000F0 /* PSE_FL_CS[7..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_FL_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_FL_ARB_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_00_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_FL_ARB_CS_MASK \ +0x00000007 /* PSE_FL_ARB_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_FL_ARB_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_01 (0x820C8000 + 0x3d4)--- +* PSE_PL_ARB_CS[2..0] - (RO) PSE debug state for PL_ARB_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_PL_INIT_CS[5..4] - (RO) PSE debug state for PL_INIT_CS +* RESERVED6[7..6] - (RO) Reserved bits +* PSE_PL_GNEXT_CS[8] - (RO) PSE debug state for PL_GNEXT_CS +* RESERVED9[11..9] - (RO) Reserved bits +* PSE_PL_GBUF_CS[14..12] - (RO) PSE debug state for PL_GBUF_CS +* RESERVED15[15] - (RO) Reserved bits +* PSE_PL_RLS_CS[17..16] - (RO) PSE debug state for PL_RLS_CS +* RESERVED18[19..18] - (RO) Reserved bits +* PSE_PL_REFILL_CS[22..20] - (RO) PSE debug state for PL_REFILL_CS +* RESERVED23[23] - (RO) Reserved bits +* PSE_RLS_CS[25..24] - (RO) PSE debug state for RLS_CS +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_RLS_CS_ADDR WF_PSE_TOP_PSE_SEEK_CR_01_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_RLS_CS_MASK \ +0x03000000 /* PSE_RLS_CS[25..24] */ +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_RLS_CS_SHFT 24 +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_REFILL_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_01_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_REFILL_CS_MASK \ +0x00700000 /* PSE_PL_REFILL_CS[22..20] */ +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_REFILL_CS_SHFT 20 +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_RLS_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_01_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_RLS_CS_MASK \ +0x00030000 /* PSE_PL_RLS_CS[17..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_RLS_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_GBUF_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_01_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_GBUF_CS_MASK \ +0x00007000 /* PSE_PL_GBUF_CS[14..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_GBUF_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_GNEXT_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_01_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_GNEXT_CS_MASK \ +0x00000100 /* PSE_PL_GNEXT_CS[8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_GNEXT_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_INIT_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_01_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_INIT_CS_MASK \ +0x00000030 /* PSE_PL_INIT_CS[5..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_INIT_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_ARB_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_01_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_ARB_CS_MASK \ +0x00000007 /* PSE_PL_ARB_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_ARB_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_02 (0x820C8000 + 0x3d8)--- +* PSE_HIF_DOP_PBUF_CS[2..0] - (RO) PSE debug state for HIF_DOP_PBUF_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_HIF_DOP_CACHE_CS[5..4] - (RO) PSE debug state for HIF_DOP_CACHE_CS +* RESERVED6[7..6] - (RO) Reserved bits +* PSE_HIF_QOP_Q_OPER_CS[11..8] - (RO) PSE debug state for HIF_QOP_Q_OPER_CS +* PSE_HIF_QOP_RL_OCP_CS[13..12] - (RO) PSE debug state for HIF_QOP_RL_OCP_CS +* RESERVED14[15..14] - (RO) Reserved bits +* PSE_HIF_QOP_PL_OCP_CS[17..16] - (RO) PSE debug state for HIF_QOP_PL_OCP_CS +* RESERVED18[19..18] - (RO) Reserved bits +* PSE_HIF_QOP_ALLOCATE_CS[22..20] - (RO) PSE debug state for +HIF_QOP_ALLOCATE_CS +* RESERVED23[23] - (RO) Reserved bits +* PSE_HIF_RX_DOP_PBUF_CS[26..24] - (RO) PSE debug state for HIF_RX_DOP_PBUF_CS +* RESERVED27[27] - (RO) Reserved bits +* PSE_HIF_RX_DOP_CACHE_CS[29..28] - (RO) PSE debug state for +HIF_RX_DOP_CACHE_CS +* RESERVED30[31..30] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_RX_DOP_CACHE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_02_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_RX_DOP_CACHE_CS_MASK \ +0x30000000 /* PSE_HIF_RX_DOP_CACHE_CS[29..28] */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_RX_DOP_CACHE_CS_SHFT 28 +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_RX_DOP_PBUF_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_02_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_RX_DOP_PBUF_CS_MASK \ +0x07000000 /* PSE_HIF_RX_DOP_PBUF_CS[26..24] */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_RX_DOP_PBUF_CS_SHFT 24 +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_ALLOCATE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_02_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_ALLOCATE_CS_MASK \ +0x00700000 /* PSE_HIF_QOP_ALLOCATE_CS[22..20] */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_ALLOCATE_CS_SHFT 20 +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_PL_OCP_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_02_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_PL_OCP_CS_MASK \ +0x00030000 /* PSE_HIF_QOP_PL_OCP_CS[17..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_PL_OCP_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_RL_OCP_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_02_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_RL_OCP_CS_MASK \ +0x00003000 /* PSE_HIF_QOP_RL_OCP_CS[13..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_RL_OCP_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_Q_OPER_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_02_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_Q_OPER_CS_MASK \ +0x00000F00 /* PSE_HIF_QOP_Q_OPER_CS[11..8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_Q_OPER_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_DOP_CACHE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_02_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_DOP_CACHE_CS_MASK \ +0x00000030 /* PSE_HIF_DOP_CACHE_CS[5..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_DOP_CACHE_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_DOP_PBUF_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_02_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_DOP_PBUF_CS_MASK \ +0x00000007 /* PSE_HIF_DOP_PBUF_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_DOP_PBUF_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_03 (0x820C8000 + 0x3dc)--- +* PSE_CPU_DOP_PBUF_CS[2..0] - (RO) PSE debug state for CPU_DOP_PBUF_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_CPU_DOP_CACHE_CS[5..4] - (RO) PSE debug state for CPU_DOP_CACHE_CS +* RESERVED6[7..6] - (RO) Reserved bits +* PSE_CPU_QOP_Q_OPER_CS[11..8] - (RO) PSE debug state for CPU_QOP_Q_OPER_CS +* PSE_CPU_QOP_RL_OCP_CS[13..12] - (RO) PSE debug state for CPU_QOP_RL_OCP_CS +* RESERVED14[15..14] - (RO) Reserved bits +* PSE_CPU_QOP_PL_OCP_CS[17..16] - (RO) PSE debug state for CPU_QOP_PL_OCP_CS +* RESERVED18[19..18] - (RO) Reserved bits +* PSE_CPU_QOP_ALLOCATE_CS[22..20] - (RO) PSE debug state for +CPU_QOP_ALLOCATE_CS +* RESERVED23[31..23] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_ALLOCATE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_03_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_ALLOCATE_CS_MASK \ +0x00700000 /* PSE_CPU_QOP_ALLOCATE_CS[22..20] */ +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_ALLOCATE_CS_SHFT 20 +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_PL_OCP_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_03_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_PL_OCP_CS_MASK \ +0x00030000 /* PSE_CPU_QOP_PL_OCP_CS[17..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_PL_OCP_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_RL_OCP_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_03_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_RL_OCP_CS_MASK \ +0x00003000 /* PSE_CPU_QOP_RL_OCP_CS[13..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_RL_OCP_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_Q_OPER_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_03_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_Q_OPER_CS_MASK \ +0x00000F00 /* PSE_CPU_QOP_Q_OPER_CS[11..8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_Q_OPER_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_DOP_CACHE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_03_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_DOP_CACHE_CS_MASK \ +0x00000030 /* PSE_CPU_DOP_CACHE_CS[5..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_DOP_CACHE_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_DOP_PBUF_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_03_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_DOP_PBUF_CS_MASK \ +0x00000007 /* PSE_CPU_DOP_PBUF_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_DOP_PBUF_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_04 (0x820C8000 + 0x3e0)--- +* PSE_WF_DOP_PBUF_CS[2..0] - (RO) PSE debug state for WF_DOP_PBUF_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_WF_DOP_CACHE_CS[5..4] - (RO) PSE debug state for WF_DOP_CACHE_CS +* RESERVED6[7..6] - (RO) Reserved bits +* PSE_WF_QOP_Q_OPER_CS[11..8] - (RO) PSE debug state for WF_QOP_Q_OPER_CS +* PSE_WF_QOP_RL_OCP_CS[13..12] - (RO) PSE debug state for WF_QOP_RL_OCP_CS +* RESERVED14[15..14] - (RO) Reserved bits +* PSE_WF_QOP_PL_OCP_CS[17..16] - (RO) PSE debug state for WF_QOP_PL_OCP_CS +* RESERVED18[19..18] - (RO) Reserved bits +* PSE_WF_QOP_ALLOCATE_CS[22..20] - (RO) PSE debug state for WF_QOP_ALLOCATE_CS +* RESERVED23[31..23] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_ALLOCATE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_04_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_ALLOCATE_CS_MASK \ +0x00700000 /* PSE_WF_QOP_ALLOCATE_CS[22..20] */ +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_ALLOCATE_CS_SHFT 20 +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_PL_OCP_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_04_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_PL_OCP_CS_MASK \ +0x00030000 /* PSE_WF_QOP_PL_OCP_CS[17..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_PL_OCP_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_RL_OCP_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_04_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_RL_OCP_CS_MASK \ +0x00003000 /* PSE_WF_QOP_RL_OCP_CS[13..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_RL_OCP_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_Q_OPER_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_04_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_Q_OPER_CS_MASK \ +0x00000F00 /* PSE_WF_QOP_Q_OPER_CS[11..8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_Q_OPER_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_DOP_CACHE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_04_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_DOP_CACHE_CS_MASK \ +0x00000030 /* PSE_WF_DOP_CACHE_CS[5..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_DOP_CACHE_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_DOP_PBUF_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_04_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_DOP_PBUF_CS_MASK \ +0x00000007 /* PSE_WF_DOP_PBUF_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_DOP_PBUF_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_05 (0x820C8000 + 0x3e4)--- +* PSE_MDP_DOP_PBUF_CS[2..0] - (RO) PSE debug state for MDP_DOP_PBUF_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_MDP_DOP_CACHE_CS[5..4] - (RO) PSE debug state for MDP_DOP_CACHE_CS +* RESERVED6[7..6] - (RO) Reserved bits +* PSE_MDP_QOP_Q_OPER_CS[11..8] - (RO) PSE debug state for MDP_QOP_Q_OPER_CS +* PSE_MDP_QOP_RL_OCP_CS[13..12] - (RO) PSE debug state for MDP_QOP_RL_OCP_CS +* RESERVED14[15..14] - (RO) Reserved bits +* PSE_MDP_QOP_PL_OCP_CS[17..16] - (RO) PSE debug state for MDP_QOP_PL_OCP_CS +* RESERVED18[19..18] - (RO) Reserved bits +* PSE_MDP_QOP_ALLOCATE_CS[22..20] - (RO) PSE debug state for +MDP_QOP_ALLOCATE_CS +* RESERVED23[31..23] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_ALLOCATE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_05_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_ALLOCATE_CS_MASK \ +0x00700000 /* PSE_MDP_QOP_ALLOCATE_CS[22..20] */ +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_ALLOCATE_CS_SHFT 20 +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_PL_OCP_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_05_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_PL_OCP_CS_MASK \ +0x00030000 /* PSE_MDP_QOP_PL_OCP_CS[17..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_PL_OCP_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_RL_OCP_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_05_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_RL_OCP_CS_MASK \ +0x00003000 /* PSE_MDP_QOP_RL_OCP_CS[13..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_RL_OCP_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_Q_OPER_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_05_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_Q_OPER_CS_MASK \ +0x00000F00 /* PSE_MDP_QOP_Q_OPER_CS[11..8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_Q_OPER_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_DOP_CACHE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_05_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_DOP_CACHE_CS_MASK \ +0x00000030 /* PSE_MDP_DOP_CACHE_CS[5..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_DOP_CACHE_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_DOP_PBUF_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_05_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_DOP_PBUF_CS_MASK \ +0x00000007 /* PSE_MDP_DOP_PBUF_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_DOP_PBUF_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_06 (0x820C8000 + 0x3e8)--- +* PSE_SEC_DOP_PBUF_CS[2..0] - (RO) PSE debug state for SEC_DOP_PBUF_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_SEC_DOP_CACHE_CS[5..4] - (RO) PSE debug state for SEC_DOP_CACHE_CS +* RESERVED6[7..6] - (RO) Reserved bits +* PSE_SEC_QOP_Q_OPER_CS[11..8] - (RO) PSE debug state for SEC_QOP_Q_OPER_CS +* PSE_SEC_QOP_RL_OCP_CS[13..12] - (RO) PSE debug state for SEC_QOP_RL_OCP_CS +* RESERVED14[15..14] - (RO) Reserved bits +* PSE_SEC_QOP_PL_OCP_CS[17..16] - (RO) PSE debug state for SEC_QOP_PL_OCP_CS +* RESERVED18[19..18] - (RO) Reserved bits +* PSE_SEC_QOP_ALLOCATE_CS[22..20] - (RO) PSE debug state for +SEC_QOP_ALLOCATE_CS +* RESERVED23[31..23] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_ALLOCATE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_06_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_ALLOCATE_CS_MASK \ +0x00700000 /* PSE_SEC_QOP_ALLOCATE_CS[22..20] */ +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_ALLOCATE_CS_SHFT 20 +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_PL_OCP_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_06_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_PL_OCP_CS_MASK \ +0x00030000 /* PSE_SEC_QOP_PL_OCP_CS[17..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_PL_OCP_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_RL_OCP_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_06_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_RL_OCP_CS_MASK \ +0x00003000 /* PSE_SEC_QOP_RL_OCP_CS[13..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_RL_OCP_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_Q_OPER_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_06_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_Q_OPER_CS_MASK \ +0x00000F00 /* PSE_SEC_QOP_Q_OPER_CS[11..8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_Q_OPER_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_DOP_CACHE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_06_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_DOP_CACHE_CS_MASK \ +0x00000030 /* PSE_SEC_DOP_CACHE_CS[5..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_DOP_CACHE_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_DOP_PBUF_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_06_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_DOP_PBUF_CS_MASK \ +0x00000007 /* PSE_SEC_DOP_PBUF_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_DOP_PBUF_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_07 (0x820C8000 + 0x3ec)--- +* PSE_PLE_DOP_PBUF_CS[2..0] - (RO) PSE debug state for PLE_DOP_PBUF_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_PLE_DOP_CACHE_CS[5..4] - (RO) PSE debug state for PLE_DOP_CACHE_CS +* RESERVED6[7..6] - (RO) Reserved bits +* PSE_PLE_QOP_Q_OPER_CS[11..8] - (RO) PSE debug state for PLE_QOP_Q_OPER_CS +* PSE_PLE_QOP_RL_OCP_CS[13..12] - (RO) PSE debug state for PLE_QOP_RL_OCP_CS +* RESERVED14[15..14] - (RO) Reserved bits +* PSE_PLE_QOP_PL_OCP_CS[17..16] - (RO) PSE debug state for PLE_QOP_PL_OCP_CS +* RESERVED18[19..18] - (RO) Reserved bits +* PSE_PLE_QOP_ALLOCATE_CS[22..20] - (RO) PSE debug state for +PLE_QOP_ALLOCATE_CS +* RESERVED23[31..23] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_ALLOCATE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_07_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_ALLOCATE_CS_MASK \ +0x00700000 /* PSE_PLE_QOP_ALLOCATE_CS[22..20] */ +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_ALLOCATE_CS_SHFT 20 +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_PL_OCP_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_07_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_PL_OCP_CS_MASK \ +0x00030000 /* PSE_PLE_QOP_PL_OCP_CS[17..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_PL_OCP_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_RL_OCP_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_07_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_RL_OCP_CS_MASK \ +0x00003000 /* PSE_PLE_QOP_RL_OCP_CS[13..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_RL_OCP_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_Q_OPER_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_07_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_Q_OPER_CS_MASK \ +0x00000F00 /* PSE_PLE_QOP_Q_OPER_CS[11..8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_Q_OPER_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_DOP_CACHE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_07_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_DOP_CACHE_CS_MASK \ +0x00000030 /* PSE_PLE_DOP_CACHE_CS[5..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_DOP_CACHE_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_DOP_PBUF_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_07_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_DOP_PBUF_CS_MASK \ +0x00000007 /* PSE_PLE_DOP_PBUF_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_DOP_PBUF_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_08 (0x820C8000 + 0x3f0)--- +* PSE_AMSDU_DOP_PBUF_CS[2..0] - (RO) PSE debug state for AMSDU_DOP_PBUF_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_AMSDU_DOP_CACHE_CS[5..4] - (RO) PSE debug state for AMSDU_DOP_CACHE_CS +* RESERVED6[7..6] - (RO) Reserved bits +* CPU_Q_OP_CS[11..8] - (RO) PSE debug state for CPI_Q_OP_CS +* ARB_REQ_CS[14..12] - (RO) PSE debug state for ARB_REQ_CS +* RESERVED15[15] - (RO) Reserved bits +* APB_REQ_CS[18..16] - (RO) PSE debug state for APB_REQ_CS +* RESERVED19[31..19] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_08_APB_REQ_CS_ADDR WF_PSE_TOP_PSE_SEEK_CR_08_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_08_APB_REQ_CS_MASK \ +0x00070000 /* APB_REQ_CS[18..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_08_APB_REQ_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_08_ARB_REQ_CS_ADDR WF_PSE_TOP_PSE_SEEK_CR_08_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_08_ARB_REQ_CS_MASK \ +0x00007000 /* ARB_REQ_CS[14..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_08_ARB_REQ_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_08_CPU_Q_OP_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_08_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_08_CPU_Q_OP_CS_MASK \ +0x00000F00 /* CPU_Q_OP_CS[11..8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_08_CPU_Q_OP_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_08_PSE_AMSDU_DOP_CACHE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_08_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_08_PSE_AMSDU_DOP_CACHE_CS_MASK \ +0x00000030 /* PSE_AMSDU_DOP_CACHE_CS[5..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_08_PSE_AMSDU_DOP_CACHE_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_08_PSE_AMSDU_DOP_PBUF_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_08_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_08_PSE_AMSDU_DOP_PBUF_CS_MASK \ +0x00000007 /* PSE_AMSDU_DOP_PBUF_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_08_PSE_AMSDU_DOP_PBUF_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_09 (0x820C8000 + 0x3f4)--- +* RESERVED0[15..0] - (RO) Reserved bits +* DOUBLE_RLS_FID[27..16] - (RO) PSE double RLS FID PAGE +* RESERVED28[30..28] - (RO) Reserved bits +* DOUBLE_RLS_ERROR[31] - (RO) PSE double RLS error flag +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_09_DOUBLE_RLS_ERROR_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_09_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_09_DOUBLE_RLS_ERROR_MASK \ +0x80000000 /* DOUBLE_RLS_ERROR[31] */ +#define WF_PSE_TOP_PSE_SEEK_CR_09_DOUBLE_RLS_ERROR_SHFT 31 +#define WF_PSE_TOP_PSE_SEEK_CR_09_DOUBLE_RLS_FID_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_09_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_09_DOUBLE_RLS_FID_MASK \ +0x0FFF0000 /* DOUBLE_RLS_FID[27..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_09_DOUBLE_RLS_FID_SHFT 16 + +#ifdef __cplusplus +} +#endif + +#endif /* __WF_PSE_TOP_REGS_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7915/wf_wfdma_host_dma0.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7915/wf_wfdma_host_dma0.h new file mode 100644 index 0000000000000..1643cb4825ee4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7915/wf_wfdma_host_dma0.h @@ -0,0 +1,6185 @@ +/* [File] : wf_wfdma_host_dma0.h */ +/* [Revision time] : Tue Jun 5 14:35:00 2018 */ +/* [Description] : This file is auto generated by CODA */ +/* [Copyright] : Copyright (C) 2018 Mediatek Incorportion. All rights reserved. +*/ + +#ifndef __WF_WFDMA_HOST_DMA0_REGS_H__ +#define __WF_WFDMA_HOST_DMA0_REGS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* ************************************************************************** */ +/* */ +/* WF_WFDMA_HOST_DMA0 CR Definitions */ +/* */ +/* ************************************************************************** */ + +#define WF_WFDMA_HOST_DMA0_BASE 0x7C024000 + +#define WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0XA0) /* 40A0 */ +#define WF_WFDMA_HOST_DMA0_HOST_IF_RX_DONE_STS_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0XA4) /* 40A4 */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_RST_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x100) /* 4100 */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x104) /* 4104 */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0X108) /* 4108 */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x10C) /* 410C */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0X110) /* 4110 */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0X114) /* 4114 */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DUMMY_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x120) /* 4120 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x124) /* 4124 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_PROBE_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x128) /* 4128 */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x12C) /* 412C */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_PROBE_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x130) /* 4130 */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DMASHDL_DBG_PROBE_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x134) /* 4134 */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x138) /* 4138 */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x13c) /* 413C */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x140) /* 4140 */ +#define WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x1E8) /* 41E8 */ +#define WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x1EC) /* 41EC */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x1F0) /* 41F0 */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x1F4) /* 41F4 */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x1F8) /* 41F8 */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x1FC) /* 41FC */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x200) /* 4200 */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0X204) /* 4204 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x208) /* 4208 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x20C) /* 420C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_TX_Q_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x224) /* 4224 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x230) /* 4230 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x234) /* 4234 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x240) /* 4240 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x260) /* 4260 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x264) /* 4264 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x268) /* 4268 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x26C) /* 426C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x280) /* 4280 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x284) /* 4284 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x288) /* 4288 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x298) /* 4298 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2A0) /* 42A0 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2A4) /* 42A4 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2A8) /* 42A8 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2AC) /* 42AC */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2B0) /* 42B0 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2B4) /* 42B4 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2B8) /* 42B8 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2BC) /* 42BC */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2C0) /* 42C0 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2C4) /* 42C4 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2C8) /* 42C8 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2CC) /* 42CC */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2D0) /* 42D0 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2D4) /* 42D4 */ +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2E0) /* 42E0 */ +#define WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2E4) /* 42E4 */ +#define WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2E8) /* 42E8 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2F0) /* 42F0 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x300) /* 4300 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x304) /* 4304 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x308) /* 4308 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x30c) /* 430C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x310) /* 4310 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x314) /* 4314 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x318) /* 4318 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x31c) /* 431C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x320) /* 4320 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x324) /* 4324 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x328) /* 4328 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x32c) /* 432C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x330) /* 4330 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x334) /* 4334 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x338) /* 4338 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x33c) /* 433C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x500) /* 4500 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x504) /* 4504 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x508) /* 4508 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x50c) /* 450C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x510) /* 4510 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x514) /* 4514 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x518) /* 4518 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x51c) /* 451C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x520) /* 4520 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x524) /* 4524 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x528) /* 4528 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x52C) /* 452C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x530) /* 4530 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x534) /* 4534 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x538) /* 4538 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x53C) /* 453C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x600) /* 4600 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x604) /* 4604 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x608) /* 4608 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x60C) /* 460C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x680) /* 4680 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x684) /* 4684 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x688) /* 4688 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x68C) /* 468C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x900) /* 4900 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x904) /* 4904 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x910) /* 4910 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x914) /* 4914 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x918) /* 4918 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA3_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x91C) /* 491C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x920) /* 4920 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x924) /* 4924 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x928) /* 4928 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA3_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x92C) /* 492C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x930) /* 4930 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x934) /* 4934 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x938) /* 4938 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT3_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x93C) /* 493C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT4_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x940) /* 4940 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT5_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x944) /* 4944 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x980) /* 4980 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x984) /* 4984 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x988) /* 4988 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x98C) /* 498C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA4_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x990) /* 4990 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xA00) /* 4A00 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xA04) /* 4A04 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xA08) /* 4A08 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xA10) /* 4A10 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xA14) /* 4A14 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xA18) /* 4A18 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xA20) /* 4A20 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xA24) /* 4A24 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xA28) /* 4A28 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xA30) /* 4A30 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xA34) /* 4A34 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xA38) /* 4A38 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC00) /* 4C00 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC04) /* 4C04 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC08) /* 4C08 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC10) /* 4C10 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC14) /* 4C14 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC18) /* 4C18 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC20) /* 4C20 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC24) /* 4C24 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC28) /* 4C28 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC30) /* 4C30 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC34) /* 4C34 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC38) /* 4C38 */ + + + + +/* +* ---HOST_IF_TX_DONE_STS (0x7C024000 + 0XA0)--- +* fifo_dfet_txdone_dat0_done_sts[0] - (W1C) USB DAT0 FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint buffer +* fifo_dfet_txdone_dat1_done_sts[1] - (W1C) USB DAT1 FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint buffer +* fifo_dfet_txdone_dat2_done_sts[2] - (W1C) USB DAT2 FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint buffer +* fifo_dfet_txdone_dat3_done_sts[3] - (W1C) USB DAT3 FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint buffer +* fifo_dfet_txdone_dat4_done_sts[4] - (W1C) USB DAT4 FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint buffer +* fifo_dfet_txdone_cmd_done_sts[5] - (W1C) USB CMD FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint buffer +* fifo_dfet_txdone_fwdl_done_sts[6] - (W1C) USB Firmware download FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint buffer +* SDIO Mode (All SDIO Tx packet goto firmware download FIFO) +* 0 : no tx done +* 1 : pdma start to fetch data from SDIO buffer +* RESERVED7[31..7] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_fwdl_done_sts_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_fwdl_done_sts_MASK \ + 0x00000040 /* fifo_dfet_txdone_fwdl_done_sts[6] */ +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_fwdl_done_sts_SHFT \ + 6 +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_cmd_done_sts_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_cmd_done_sts_MASK \ + 0x00000020 /* fifo_dfet_txdone_cmd_done_sts[5] */ +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_cmd_done_sts_SHFT \ + 5 +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat4_done_sts_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat4_done_sts_MASK \ + 0x00000010 /* fifo_dfet_txdone_dat4_done_sts[4] */ +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat4_done_sts_SHFT \ + 4 +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat3_done_sts_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat3_done_sts_MASK \ + 0x00000008 /* fifo_dfet_txdone_dat3_done_sts[3] */ +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat3_done_sts_SHFT \ + 3 +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat2_done_sts_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat2_done_sts_MASK \ + 0x00000004 /* fifo_dfet_txdone_dat2_done_sts[2] */ +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat2_done_sts_SHFT \ + 2 +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat1_done_sts_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat1_done_sts_MASK \ + 0x00000002 /* fifo_dfet_txdone_dat1_done_sts[1] */ +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat1_done_sts_SHFT \ + 1 +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat0_done_sts_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat0_done_sts_MASK \ + 0x00000001 /* fifo_dfet_txdone_dat0_done_sts[0] */ +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat0_done_sts_SHFT \ + 0 + +/* +* ---HOST_IF_RX_DONE_STS (0x7C024000 + 0XA4)--- +* rx0_packet_done_sts[0] - (W1C) USB/SDIO Rx0 packet done status +* 0 : no rx packet done +* 1 : rx packet send to host interface +* rx1_packet_done_sts[1] - (W1C) USB/SDIO Rx1 packet done status +* 0 : no rx packet done +* 1 : rx packet send to host interface +* Note : All SDIO Packet send to SIDO RX0 port +* RESERVED2[31..2] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_HOST_IF_RX_DONE_STS_rx1_packet_done_sts_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_IF_RX_DONE_STS_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_IF_RX_DONE_STS_rx1_packet_done_sts_MASK \ + 0x00000002 /* rx1_packet_done_sts[1] */ +#define WF_WFDMA_HOST_DMA0_HOST_IF_RX_DONE_STS_rx1_packet_done_sts_SHFT 1 +#define WF_WFDMA_HOST_DMA0_HOST_IF_RX_DONE_STS_rx0_packet_done_sts_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_IF_RX_DONE_STS_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_IF_RX_DONE_STS_rx0_packet_done_sts_MASK \ + 0x00000001 /* rx0_packet_done_sts[0] */ +#define WF_WFDMA_HOST_DMA0_HOST_IF_RX_DONE_STS_rx0_packet_done_sts_SHFT 0 + +/* +* ---CONN_HIF_RST (0x7C024000 + 0x100)--- +* RESERVED0[3..0] - (RO) Reserved bits +* conn_hif_logic_rst_n[4] - (RW) This conn_hif_logic_rst_n would reset wpdma +* logic partial control register, include Tx/Rx ring control. +* Also, conn_hif_logic_rst_n would reset wifi data path, include tx fifo, rx +* fifo, r2x_bridge, axi_mux and other other asynchronous bridge. +* (Note : conn_hif_logic_rst_n would not reset hif_dmashdl logic) +* dmashdl_all_rst_n[5] - (RW) This dmashdl_all_rst_n would reset +* hif_dmashdl_top, include logic and control register. +* RESERVED6[31..6] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_RST_dmashdl_all_rst_n_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_RST_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_RST_dmashdl_all_rst_n_MASK \ + 0x00000020 /* dmashdl_all_rst_n[5] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_RST_dmashdl_all_rst_n_SHFT 5 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_RST_conn_hif_logic_rst_n_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_RST_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_RST_conn_hif_logic_rst_n_MASK \ + 0x00000010 /* conn_hif_logic_rst_n[4] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_RST_conn_hif_logic_rst_n_SHFT 4 + +/* +* ---CONN_HIF_TOP_MISC (0x7C024000 + 0x104)--- +* ahb_mux_2to1_ultra[1..0] - (RW) conn _hif ahb mux ultra +* ahb_mux_2to1_qos_en[2] - (RW) conn_hif ahb mux qos enable +* RESERVED3[4..3] - (RO) Reserved bits +* axi_cg_in_ck_bypass[5] - (RW) axi frequency bridge bus in clock gating bypass +* 0 : enable clock gating function +* 1 : bypass clock gating function +* axi_cg_out_ck_bypass[6] - (RW) axi frequency bridge bus out clock gating +bypass +* 0 : enable clock gating function +* 1 : bypass clock gating function +* RESERVED7[15..7] - (RO) Reserved bits +* pdma_rxring1_immint_en[16] - (RW) PDMA RX Ring 1 Immediate Interrupt Enable +* RESERVED17[31..17] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_pdma_rxring1_immint_en_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_pdma_rxring1_immint_en_MASK \ + 0x00010000 /* pdma_rxring1_immint_en[16] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_pdma_rxring1_immint_en_SHFT 16 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_axi_cg_out_ck_bypass_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_axi_cg_out_ck_bypass_MASK \ + 0x00000040 /* axi_cg_out_ck_bypass[6] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_axi_cg_out_ck_bypass_SHFT 6 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_axi_cg_in_ck_bypass_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_axi_cg_in_ck_bypass_MASK \ + 0x00000020 /* axi_cg_in_ck_bypass[5] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_axi_cg_in_ck_bypass_SHFT 5 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_ahb_mux_2to1_qos_en_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_ahb_mux_2to1_qos_en_MASK \ + 0x00000004 /* ahb_mux_2to1_qos_en[2] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_ahb_mux_2to1_qos_en_SHFT 2 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_ahb_mux_2to1_ultra_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_ahb_mux_2to1_ultra_MASK \ + 0x00000003 /* ahb_mux_2to1_ultra[1..0] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_ahb_mux_2to1_ultra_SHFT 0 + +/* +* ---HOST2MCU_SW_INT_SET (0x7C024000 + 0X108)--- +* host2mcu_sw_int_0_set[0] - (WO) Driver set this bit to generate MCU interrupt +* and 0x5000_0110[0] will be set to 1. +* host2mcu_sw_int_1_set[1] - (WO) Driver set this bit to generate MCU interrupt +* and 0x5000_0110[1] will be set to 1. +* host2mcu_sw_int_2_set[2] - (WO) Driver set this bit to generate MCU interrupt +* and 0x5000_0110[2] will be set to 1. +* host2mcu_sw_int_3_set[3] - (WO) Driver set [0x0_4108] bit[3] to generate MCU +* interrupt and 0x5000_0110[3] will be set to 1. +* host2mcu_sw_int_4_set[4] - (WO) Driver set [0x0_4108] bit[4] to generate MCU +* interrupt and 0x5000_0110[4] will be set to 1. +* host2mcu_sw_int_5_set[5] - (WO) Driver set [0x0_4108] bit[5] to generate MCU +* interrupt and 0x5000_0110[5] will be set to 1. +* host2mcu_sw_int_6_set[6] - (WO) Driver set [0x0_4108] bit[6] to generate MCU +* interrupt and 0x5000_0110[6] will be set to 1. +* host2mcu_sw_int_7_set[7] - (WO) Driver set [0x0_4108] bit[7] to generate MCU +* interrupt and 0x5000_0110[7] will be set to 1. +* RESERVED8[31..8] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_7_set_ADDR \ + WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_7_set_MASK \ + 0x00000080 /* host2mcu_sw_int_7_set[7] */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_7_set_SHFT 7 +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_6_set_ADDR \ + WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_6_set_MASK \ + 0x00000040 /* host2mcu_sw_int_6_set[6] */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_6_set_SHFT 6 +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_5_set_ADDR \ + WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_5_set_MASK \ + 0x00000020 /* host2mcu_sw_int_5_set[5] */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_5_set_SHFT 5 +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_4_set_ADDR \ + WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_4_set_MASK \ + 0x00000010 /* host2mcu_sw_int_4_set[4] */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_4_set_SHFT 4 +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_3_set_ADDR \ + WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_3_set_MASK \ + 0x00000008 /* host2mcu_sw_int_3_set[3] */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_3_set_SHFT 3 +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_2_set_ADDR \ + WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_2_set_MASK \ + 0x00000004 /* host2mcu_sw_int_2_set[2] */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_2_set_SHFT 2 +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_1_set_ADDR \ + WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_1_set_MASK \ + 0x00000002 /* host2mcu_sw_int_1_set[1] */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_1_set_SHFT 1 +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_0_set_ADDR \ + WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_0_set_MASK \ + 0x00000001 /* host2mcu_sw_int_0_set[0] */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_0_set_SHFT 0 + +/* +* ---MCU2HOST_SW_INT_SET (0x7C024000 + 0x10C)--- +* mcu2host_sw_int_set_0[0] - (WO) Internal CPU writes this register will trigger +* MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[0] to check interrupt status +* mcu2host_sw_int_set_1[1] - (WO) Internal CPU writes this register will trigger +* MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[1] to check interrupt status +* mcu2host_sw_int_set_2[2] - (WO) Internal CPU writes this register will trigger +* MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[2] to check interrupt status +* mcu2host_sw_int_set_3[3] - (WO) Internal CPU writes this register will trigger +* MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[3] to check interrupt status +* mcu2host_sw_int_set_4[4] - (WO) Internal CPU writes this register will trigger +* MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[4] to check interrupt status +* mcu2host_sw_int_set_5[5] - (WO) Internal CPU writes this register will trigger +* MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[5] to check interrupt status +* mcu2host_sw_int_set_6[6] - (WO) Internal CPU writes this register will trigger +* MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[6] to check interrupt status +* mcu2host_sw_int_set_7[7] - (WO) Internal CPU writes this register will trigger +* MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[7] to check interrupt status +* mcu2host_sw_int_set_8[8] - (WO) Internal CPU writes this register will trigger +* MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[0] to check interrupt status +* mcu2host_sw_int_set_9[9] - (WO) Internal CPU writes this register will trigger +* MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[1] to check interrupt status +* mcu2host_sw_int_set_10[10] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[2] to check interrupt status +* mcu2host_sw_int_set_11[11] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[3] to check interrupt status +* mcu2host_sw_int_set_12[12] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[4] to check interrupt status +* mcu2host_sw_int_set_13[13] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[5] to check interrupt status +* mcu2host_sw_int_set_14[14] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[6] to check interrupt status +* mcu2host_sw_int_set_15[15] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[7] to check interrupt status +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_15_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_15_MASK \ + 0x00008000 /* mcu2host_sw_int_set_15[15] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_15_SHFT 15 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_14_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_14_MASK \ + 0x00004000 /* mcu2host_sw_int_set_14[14] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_14_SHFT 14 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_13_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_13_MASK \ + 0x00002000 /* mcu2host_sw_int_set_13[13] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_13_SHFT 13 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_12_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_12_MASK \ + 0x00001000 /* mcu2host_sw_int_set_12[12] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_12_SHFT 12 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_11_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_11_MASK \ + 0x00000800 /* mcu2host_sw_int_set_11[11] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_11_SHFT 11 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_10_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_10_MASK \ + 0x00000400 /* mcu2host_sw_int_set_10[10] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_10_SHFT 10 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_9_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_9_MASK \ + 0x00000200 /* mcu2host_sw_int_set_9[9] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_9_SHFT 9 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_8_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_8_MASK \ + 0x00000100 /* mcu2host_sw_int_set_8[8] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_8_SHFT 8 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_7_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_7_MASK \ + 0x00000080 /* mcu2host_sw_int_set_7[7] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_7_SHFT 7 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_6_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_6_MASK \ + 0x00000040 /* mcu2host_sw_int_set_6[6] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_6_SHFT 6 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_5_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_5_MASK \ + 0x00000020 /* mcu2host_sw_int_set_5[5] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_5_SHFT 5 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_4_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_4_MASK \ + 0x00000010 /* mcu2host_sw_int_set_4[4] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_4_SHFT 4 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_3_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_3_MASK \ + 0x00000008 /* mcu2host_sw_int_set_3[3] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_2_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_2_MASK \ + 0x00000004 /* mcu2host_sw_int_set_2[2] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_1_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_1_MASK \ + 0x00000002 /* mcu2host_sw_int_set_1[1] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_0_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_0_MASK \ + 0x00000001 /* mcu2host_sw_int_set_0[0] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_0_SHFT 0 + +/* +* ---MCU_INT_STA (0x7C024000 + 0X110)--- +* host2mcu_sw_int_sts[7..0] - (W1C) MCU interrupt status, write 1 to clear the +interrupt +* wpdma_tx_timeout_int_sts[8] - (W1C) WPDMA TX dma timeout interrupt stauts, +* write 1 to clear the interrupt +* wpdma_rx_timeout_int_sts[9] - (W1C) WPDMA RX dma timeout interrupt stauts, +* write 1 to clear the interrupt +* wifi_txfifo0_wr_ovf_int_sts[10] - (W1C) conn_hif txfifo erorr detec +* interruptt. It indicate tx-fifo memory write overflow. +* wifi_txfifo1_wr_ovf_int_sts[11] - (W1C) conn_hif txfifo erorr detec +* interruptt. It indicate tx-fifo memory write overflow. +* wifi_rxfifo_wr_ovf_int_sts[12] - (W1C) conn_hif rxfifo erorr detect interrupt. +* It indicate rx-fifo memory write overflow. +* wpdma_tx_dmad_mem_range_err_mcu_int_sts[13] - (W1C) WPDMA tx dma descriptor +* memory range error detection mcu interrupt status +* When user setup WPDMA_TX_DMAD_RNG (not equal to zero), design would check +* tx_dmad address. If address range not correct, it would alarm memory range +* error interrupt +* wpdma_rx_dmad_mem_range_err_mcu_int_sts[14] - (W1C) WPDMA rx dma descriptor +* memory range error detection mcu interrupt status +* When user setup WPDMA_RX_DMAD_RNG (not equal to zero), design would check +* rx_dmad address. If address range not correct, it would alarm memory range +* error interrupt +* wpdma_tx_payload_mem_range_err_mcu_int_sts[15] - (W1C) WPDMA tx payload memory +* range error detection mcu interrupt status +* When user setup WPDMA_TX_PLD_RNG (not equal to zero), design would check +* tx_dma payload address. If address range not correct, it would alarm memory +* range error interrupt +* wpdma_rx_payload_mem_range_err_mcu_int_sts[16] - (W1C) WPDMA rx payload memory +* range error detection mcu interrupt status +* When user setup WPDMA_RX_PLD_RNG (not equal to zero), design would check +* rx_dma payload address. If address range not correct, it would alarm memory +* range error interrupt +* RESERVED17[31..17] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_payload_mem_range_err_mcu_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_payload_mem_range_err_mcu_int_sts_MASK \ + 0x00010000 /* wpdma_rx_payload_mem_range_err_mcu_int_sts[16] */ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_payload_mem_range_err_mcu_int_sts_SHFT \ + 16 +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_payload_mem_range_err_mcu_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_payload_mem_range_err_mcu_int_sts_MASK \ + 0x00008000 /* wpdma_tx_payload_mem_range_err_mcu_int_sts[15] */ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_payload_mem_range_err_mcu_int_sts_SHFT \ + 15 +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_dmad_mem_range_err_mcu_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_dmad_mem_range_err_mcu_int_sts_MASK \ + 0x00004000 /* wpdma_rx_dmad_mem_range_err_mcu_int_sts[14] */ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_dmad_mem_range_err_mcu_int_sts_SHFT \ + 14 +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_dmad_mem_range_err_mcu_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_dmad_mem_range_err_mcu_int_sts_MASK \ + 0x00002000 /* wpdma_tx_dmad_mem_range_err_mcu_int_sts[13] */ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_dmad_mem_range_err_mcu_int_sts_SHFT \ + 13 +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_rxfifo_wr_ovf_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_rxfifo_wr_ovf_int_sts_MASK \ + 0x00001000 /* wifi_rxfifo_wr_ovf_int_sts[12] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_rxfifo_wr_ovf_int_sts_SHFT 12 +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_txfifo1_wr_ovf_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_txfifo1_wr_ovf_int_sts_MASK \ + 0x00000800 /* wifi_txfifo1_wr_ovf_int_sts[11] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_txfifo1_wr_ovf_int_sts_SHFT 11 +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_txfifo0_wr_ovf_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_txfifo0_wr_ovf_int_sts_MASK \ + 0x00000400 /* wifi_txfifo0_wr_ovf_int_sts[10] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_txfifo0_wr_ovf_int_sts_SHFT 10 +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_timeout_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_timeout_int_sts_MASK \ + 0x00000200 /* wpdma_rx_timeout_int_sts[9] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_timeout_int_sts_SHFT 9 +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_timeout_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_timeout_int_sts_MASK \ + 0x00000100 /* wpdma_tx_timeout_int_sts[8] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_timeout_int_sts_SHFT 8 +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_host2mcu_sw_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_host2mcu_sw_int_sts_MASK \ + 0x000000FF /* host2mcu_sw_int_sts[7..0] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_host2mcu_sw_int_sts_SHFT 0 + +/* +* ---MCU_INT_ENA (0x7C024000 + 0X114)--- +* host2mcu_sw_int_ena[7..0] - (RW) host2mcu interrupt enable +* wpdma_tx_dma_timeout_int_ena[8] - (RW) WPDMA TX error detection interrupt +enable +* wpdma_rx_dma_timeout_int_ena[9] - (RW) WPDMA RX error detection interrupt +enable +* wifi_txfifo0_wr_ovf_int_ena[10] - (RW) conn_hif txfifo erorr detect interrupt +enable. +* wifi_txfifo1_wr_ovf_int_ena[11] - (RW) conn_hif txfifo erorr detect interrupt +enable. +* wifi_rxfifo_wr_ovf_int_ena[12] - (RW) conn_hif rxfifo erorr detect interrupt +enable. +* wpdma_tx_dmad_mem_range_err_mcu_int_ena[13] - (RW) WPDMA tx dma descriptor +* memory range error detection interrupt enable +* wpdma_rx_dmad_mem_range_err_mcu_int_ena[14] - (RW) WPDMA rx dma descriptor +* memory range error detection interrupt enable +* wpdma_tx_payload_mem_range_err_mcu_int_ena[15] - (RW) WPDMA tx payload memory +* range error detection interrupt enable +* wpdma_rx_payload_mem_range_err_mcu_int_ena[16] - (RW) WPDMA rx payload memory +* range error detection interrupt enable +* RESERVED17[31..17] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_payload_mem_range_err_mcu_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_payload_mem_range_err_mcu_int_ena_MASK \ + 0x00010000 /* wpdma_rx_payload_mem_range_err_mcu_int_ena[16] */ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_payload_mem_range_err_mcu_int_ena_SHFT \ + 16 +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_payload_mem_range_err_mcu_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_payload_mem_range_err_mcu_int_ena_MASK \ + 0x00008000 /* wpdma_tx_payload_mem_range_err_mcu_int_ena[15] */ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_payload_mem_range_err_mcu_int_ena_SHFT \ + 15 +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_dmad_mem_range_err_mcu_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_dmad_mem_range_err_mcu_int_ena_MASK \ + 0x00004000 /* wpdma_rx_dmad_mem_range_err_mcu_int_ena[14] */ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_dmad_mem_range_err_mcu_int_ena_SHFT \ + 14 +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_dmad_mem_range_err_mcu_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_dmad_mem_range_err_mcu_int_ena_MASK \ + 0x00002000 /* wpdma_tx_dmad_mem_range_err_mcu_int_ena[13] */ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_dmad_mem_range_err_mcu_int_ena_SHFT \ + 13 +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_rxfifo_wr_ovf_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_rxfifo_wr_ovf_int_ena_MASK \ + 0x00001000 /* wifi_rxfifo_wr_ovf_int_ena[12] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_rxfifo_wr_ovf_int_ena_SHFT 12 +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_txfifo1_wr_ovf_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_txfifo1_wr_ovf_int_ena_MASK \ + 0x00000800 /* wifi_txfifo1_wr_ovf_int_ena[11] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_txfifo1_wr_ovf_int_ena_SHFT 11 +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_txfifo0_wr_ovf_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_txfifo0_wr_ovf_int_ena_MASK \ + 0x00000400 /* wifi_txfifo0_wr_ovf_int_ena[10] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_txfifo0_wr_ovf_int_ena_SHFT 10 +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_dma_timeout_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_dma_timeout_int_ena_MASK \ + 0x00000200 /* wpdma_rx_dma_timeout_int_ena[9] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_dma_timeout_int_ena_SHFT 9 +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_dma_timeout_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_dma_timeout_int_ena_MASK \ + 0x00000100 /* wpdma_tx_dma_timeout_int_ena[8] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_dma_timeout_int_ena_SHFT 8 +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_host2mcu_sw_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_host2mcu_sw_int_ena_MASK \ + 0x000000FF /* host2mcu_sw_int_ena[7..0] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_host2mcu_sw_int_ena_SHFT 0 + +/* +* ---CONN_HIF_DUMMY (0x7C024000 + 0x120)--- +* CONN_HIF_DUMMY[31..0] - (RW) Reserved CR, SE will use it for pcie calibration! +*/ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DUMMY_CONN_HIF_DUMMY_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_DUMMY_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DUMMY_CONN_HIF_DUMMY_MASK \ + 0xFFFFFFFF /* CONN_HIF_DUMMY[31..0] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DUMMY_CONN_HIF_DUMMY_SHFT 0 + +/* +* ---WPDMA_DBG_IDX (0x7C024000 + 0x124)--- +* PDMA_DBG_IDX[7..0] - (RW) PDMA debug index +* PDMA_DBG_Enable[8] - (RW) PDMA Debug Enable +* 0: PDMA_DBG_port would has no function +* 1 : PDMA DBG_IDX select PDMA debug flag index +* RESERVED9[31..9] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_PDMA_DBG_Enable_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_PDMA_DBG_Enable_MASK \ + 0x00000100 /* PDMA_DBG_Enable[8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_PDMA_DBG_Enable_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_PDMA_DBG_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_PDMA_DBG_IDX_MASK \ + 0x000000FF /* PDMA_DBG_IDX[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_PDMA_DBG_IDX_SHFT 0 + +/* +* ---WPDMA_DBG_PROBE (0x7C024000 + 0x128)--- +* PDMA_DBG_PROBE[31..0] - (RO) PDMA Debug probe read +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_PROBE_PDMA_DBG_PROBE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_DBG_PROBE_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_PROBE_PDMA_DBG_PROBE_MASK \ + 0xFFFFFFFF /* PDMA_DBG_PROBE[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_PROBE_PDMA_DBG_PROBE_SHFT 0 + +/* +* ---CONN_HIF_DBG_IDX (0x7C024000 + 0x12C)--- +* conn_hif_dbg_byt0_sel[2..0] - (RW) conn_hif_dbg_byt0_sel : Select +* conn_hif_dbg[7:0] from "pdma_dbg"/"hif_dmashdl_top" +* conn_hif_dbg_byt1_sel[5..3] - (RW) conn_hif_dbg_byt1_sel : Select +* conn_hif_dbg[15:8] from "pdma_dbg"/"hif_dmashdl_top" +* conn_hif_dbg_byt2_sel[8..6] - (RW) conn_hif_dbg_byt2_sel : Select +* conn_hif_dbg[23:16] from "pdma_dbg"/"hif_dmashdl_top" +* conn_hif_dbg_byt3_sel[11..9] - (RW) conn_hif_dbg_byt3_sel : Select +* conn_hif_dbg[31:24] from "pdma_dbg"/"hif_dmashdl_top" +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt3_sel_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt3_sel_MASK \ + 0x00000E00 /* conn_hif_dbg_byt3_sel[11..9] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt3_sel_SHFT 9 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt2_sel_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt2_sel_MASK \ + 0x000001C0 /* conn_hif_dbg_byt2_sel[8..6] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt2_sel_SHFT 6 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt1_sel_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt1_sel_MASK \ + 0x00000038 /* conn_hif_dbg_byt1_sel[5..3] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt1_sel_SHFT 3 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt0_sel_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt0_sel_MASK \ + 0x00000007 /* conn_hif_dbg_byt0_sel[2..0] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt0_sel_SHFT 0 + +/* +* ---CONN_HIF_DBG_PROBE (0x7C024000 + 0x130)--- +* conn_hif_dbg_probe[31..0] - (RO) conn_hif_dbg_probe read +*/ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_PROBE_conn_hif_dbg_probe_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_PROBE_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_PROBE_conn_hif_dbg_probe_MASK \ + 0xFFFFFFFF /* conn_hif_dbg_probe[31..0] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_PROBE_conn_hif_dbg_probe_SHFT 0 + +/* +* ---CONN_HIF_DMASHDL_DBG_PROBE (0x7C024000 + 0x134)--- +* DMASHDL_DBG_PROBE[15..0] - (RO) conn_hif_dmashdl_dbg_probe read +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DMASHDL_DBG_PROBE_DMASHDL_DBG_PROBE_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_DMASHDL_DBG_PROBE_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DMASHDL_DBG_PROBE_DMASHDL_DBG_PROBE_MASK \ + 0x0000FFFF /* DMASHDL_DBG_PROBE[15..0] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DMASHDL_DBG_PROBE_DMASHDL_DBG_PROBE_SHFT 0 + +/* +* ---CONN_HIF_BUSY_STATUS (0x7C024000 + 0x138)--- +* conn_hif_txfifo0_busy[0] - (RO) conn_hif txfifo0 busy status +* 0 : txfifo empty +* 1 : txfifo non empty +* conn_hif_txfifo1_busy[1] - (RO) conn_hif txfifo1 busy status +* 0 : txfifo empty +* 1 : txfifo non empty +* conn_hif_rxfifo_busy[2] - (RO) conn_hif rxfifo busy status +* 0 : rxfifo empty +* 1 : rxfifo non empty +* RESERVED[30..3] - (RO) Reserved CR +* conn_hif_busy[31] - (RO) Over all conn_hif busy status, it was busy summation +* of bit[6] ~ bit[0] status +*/ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_busy_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_busy_MASK \ + 0x80000000 /* conn_hif_busy[31] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_busy_SHFT 31 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_rxfifo_busy_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_rxfifo_busy_MASK \ + 0x00000004 /* conn_hif_rxfifo_busy[2] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_rxfifo_busy_SHFT 2 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_txfifo1_busy_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_txfifo1_busy_MASK \ + 0x00000002 /* conn_hif_txfifo1_busy[1] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_txfifo1_busy_SHFT 1 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_txfifo0_busy_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_txfifo0_busy_MASK \ + 0x00000001 /* conn_hif_txfifo0_busy[0] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_txfifo0_busy_SHFT 0 + +/* +* ---CONN_HIF_BUSY_ENA (0x7C024000 + 0x13c)--- +* conn_hif_txfifo0_busy_enable[0] - (RW) busy enable control +* 0: ignore busy status +* 1: conn_hif_busy would tack care busy status +* conn_hif_txfifo1_busy_enable[1] - (RW) busy enable control +* 0: ignore busy status +* 1: conn_hif_busy would tack care busy status +* conn_hif_rxfifo_busy_enable[2] - (RW) busy enable control +* 0: ignore busy status +* 1: conn_hif_busy would tack care busy status +* axi_mx4to1_w_busy_enable[3] - (RW) busy enable control +* 0: ignore busy status +* 1: conn_hif_busy would tack care busy status +* axi_mx4to1_r_busy_enable[4] - (RW) busy enable control +* 0: ignore busy status +* 1: conn_hif_busy would tack care busy status +* RESERVED[31..5] - (RW) Reserved CR +*/ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_axi_mx4to1_r_busy_enable_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_axi_mx4to1_r_busy_enable_MASK \ + 0x00000010 /* axi_mx4to1_r_busy_enable[4] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_axi_mx4to1_r_busy_enable_SHFT 4 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_axi_mx4to1_w_busy_enable_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_axi_mx4to1_w_busy_enable_MASK \ + 0x00000008 /* axi_mx4to1_w_busy_enable[3] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_axi_mx4to1_w_busy_enable_SHFT 3 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_rxfifo_busy_enable_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_rxfifo_busy_enable_MASK \ + 0x00000004 /* conn_hif_rxfifo_busy_enable[2] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_rxfifo_busy_enable_SHFT 2 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_txfifo1_busy_enable_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_txfifo1_busy_enable_MASK \ + 0x00000002 /* conn_hif_txfifo1_busy_enable[1] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_txfifo1_busy_enable_SHFT 1 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_txfifo0_busy_enable_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_txfifo0_busy_enable_MASK \ + 0x00000001 /* conn_hif_txfifo0_busy_enable[0] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_txfifo0_busy_enable_SHFT 0 + +/* +* ---CONN_HIF_FIFO_TEST_MOD (0x7C024000 + 0x140)--- +* csr_wfdma_loopback_en[0] - (RW) conn_hif fifo loopback enable +* NOTICE : when loopback, OMIT_TX_INFO and OMIT_RX_INFO sould be both set to +1'b1 +* csr_wfdma_loopback_qsel[2..1] - (RW) No USE for (conn_hif fifo loopback packet +* go into Rx-ring number) +* RESERVED3[31..3] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_qsel_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_qsel_MASK \ + 0x00000006 /* csr_wfdma_loopback_qsel[2..1] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_qsel_SHFT 1 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_en_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_en_MASK \ + 0x00000001 /* csr_wfdma_loopback_en[0] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_en_SHFT 0 + +/* +* ---WPDMA2HOST_ERR_INT_STA (0x7C024000 + 0x1E8)--- +* wpdma_tx_timeout_int_sts[0] - (W1C) WPDMA TX error detection interrupt stauts, +* write 1 to clear the interrupt +* wpdma_rx_timeout_int_sts[1] - (W1C) WPDMA RX error detection interrupt stauts, +* write 1 to clear the interrupt +* wpdma_tx_dmad_mem_range_err_int_sts[2] - (W1C) WPDMA tx dma descriptor memory +* range error detection interrupt status +* When user setup WPDMA_TX_DMAD_RNG (not equal to zero), design would check +* tx_dmad address. If address range not correct, it would alarm memory range +* error interrupt +* wpdma_rx_dmad_mem_range_err_int_sts[3] - (W1C) WPDMA rx dma descriptor memory +* range error detection interrupt status +* When user setup WPDMA_RX_DMAD_RNG (not equal to zero), design would check +* rx_dmad address. If address range not correct, it would alarm memory range +* error interrupt +* wpdma_tx_payload_mem_range_err_int_sts[4] - (W1C) WPDMA tx payload memory +* range error detection interrupt status +* When user setup WPDMA_TX_PLD_RNG (not equal to zero), design would check +* tx_dma payload address. If address range not correct, it would alarm memory +* range error interrupt +* wpdma_rx_payload_mem_range_err_int_sts[5] - (W1C) WPDMA rx payload memory +* range error detection interrupt status +* When user setup WPDMA_RX_PLD_RNG (not equal to zero), design would check +* rx_dma payload address. If address range not correct, it would alarm memory +* range error interrupt +* wpdma_axi_bresp_error_int_sts[6] - (W1C) WPDMA AXI master bresp error +* detection interrupt status, check WPDMA_AXI_MST_DBG1 for error information +* wpdma_axi_rresp_error_int_sts[7] - (W1C) WPDMA AXI master rresp error +* detection interrupt status, check WPDMA_AXI_MST_DBG0 for error information +* m0_wr_axi_err_det_int_sts[8] - (W1C) WPDMA AXI write master for RX payload +* error detection interrupt status +* m1_wr_axi_err_det_int_sts[9] - (W1C) WPDMA AXI write master for RX DMAD error +* detection interrupt status +* m2_wr_axi_err_det_int_sts[10] - (W1C) WPDMA AXI write master for TX DMAD error +* detection interrupt status +* m0_rd_axi_err_det_int_sts[11] - (W1C) WPDMA AXI read master for DBDC0 TX +* payload error detection interrupt status +* m1_rd_axi_err_det_int_sts[12] - (W1C) WPDMA AXI read master for RX DMAD error +* detection interrupt status +* m2_rd_axi_err_det_int_sts[13] - (W1C) WPDMA AXI read master for TX DMAD error +* detection interrupt status +* m3_rd_axi_err_det_int_sts[14] - (W1C) WPDMA AXI read master for DBDC1 TX +* payload error detection interrupt status +* pf_sram_size_underflow_int_sts[15] - (RO) Prefetch sram overflow error +* interrupt status. This reflect configured prefetch sram is not enough for all +* TX and RX prefetch ring. Prefetch sram size should be greater than (DMAD size +* total of each RING's MAX_CNT) +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_pf_sram_size_underflow_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_pf_sram_size_underflow_int_sts_MASK \ + 0x00008000 /* pf_sram_size_underflow_int_sts[15] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_pf_sram_size_underflow_int_sts_SHFT \ + 15 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_m3_rd_axi_err_det_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_m3_rd_axi_err_det_int_sts_MASK \ + 0x00004000 /* m3_rd_axi_err_det_int_sts[14] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_m3_rd_axi_err_det_int_sts_SHFT \ + 14 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_m2_rd_axi_err_det_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_m2_rd_axi_err_det_int_sts_MASK \ + 0x00002000 /* m2_rd_axi_err_det_int_sts[13] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_m2_rd_axi_err_det_int_sts_SHFT \ + 13 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_m1_rd_axi_err_det_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_m1_rd_axi_err_det_int_sts_MASK \ + 0x00001000 /* m1_rd_axi_err_det_int_sts[12] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_m1_rd_axi_err_det_int_sts_SHFT \ + 12 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_m0_rd_axi_err_det_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_m0_rd_axi_err_det_int_sts_MASK \ + 0x00000800 /* m0_rd_axi_err_det_int_sts[11] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_m0_rd_axi_err_det_int_sts_SHFT \ + 11 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_m2_wr_axi_err_det_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_m2_wr_axi_err_det_int_sts_MASK \ + 0x00000400 /* m2_wr_axi_err_det_int_sts[10] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_m2_wr_axi_err_det_int_sts_SHFT \ + 10 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_m1_wr_axi_err_det_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_m1_wr_axi_err_det_int_sts_MASK \ + 0x00000200 /* m1_wr_axi_err_det_int_sts[9] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_m1_wr_axi_err_det_int_sts_SHFT \ + 9 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_m0_wr_axi_err_det_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_m0_wr_axi_err_det_int_sts_MASK \ + 0x00000100 /* m0_wr_axi_err_det_int_sts[8] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_m0_wr_axi_err_det_int_sts_SHFT \ + 8 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_axi_rresp_error_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_axi_rresp_error_int_sts_MASK \ + 0x00000080 /* wpdma_axi_rresp_error_int_sts[7] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_axi_rresp_error_int_sts_SHFT \ + 7 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_axi_bresp_error_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_axi_bresp_error_int_sts_MASK \ + 0x00000040 /* wpdma_axi_bresp_error_int_sts[6] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_axi_bresp_error_int_sts_SHFT \ + 6 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_rx_payload_mem_range_err_int_st\ +s_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_rx_payload_mem_range_err_int_st\ +s_MASK \ +0x00000020 /* wpdma_rx_payload_mem_range_err_int_sts[5] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_rx_payload_mem_range_err_int_st\ +s_SHFT \ +5 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_tx_payload_mem_range_err_int_st\ +s_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_tx_payload_mem_range_err_int_st\ +s_MASK \ +0x00000010 /* wpdma_tx_payload_mem_range_err_int_sts[4] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_tx_payload_mem_range_err_int_st\ +s_SHFT \ +4 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_rx_dmad_mem_range_err_int_sts_A\ +DDR \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_rx_dmad_mem_range_err_int_sts_M\ +ASK \ +0x00000008 /* wpdma_rx_dmad_mem_range_err_int_sts[3] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_rx_dmad_mem_range_err_int_sts_S\ +HFT \ +3 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_tx_dmad_mem_range_err_int_sts_A\ +DDR \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_tx_dmad_mem_range_err_int_sts_M\ +ASK \ +0x00000004 /* wpdma_tx_dmad_mem_range_err_int_sts[2] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_tx_dmad_mem_range_err_int_sts_S\ +HFT \ +2 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_rx_timeout_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_rx_timeout_int_sts_MASK \ + 0x00000002 /* wpdma_rx_timeout_int_sts[1] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_rx_timeout_int_sts_SHFT \ + 1 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_tx_timeout_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_tx_timeout_int_sts_MASK \ + 0x00000001 /* wpdma_tx_timeout_int_sts[0] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_tx_timeout_int_sts_SHFT \ + 0 + +/* +* ---WPDMA2HOST_ERR_INT_ENA (0x7C024000 + 0x1EC)--- +* wpdma_rx_timeout_int_ena[0] - (RW) WPDMA TX error detection interrupt enable +* wpdma_tx_timeout_int_ena[1] - (RW) WPDMA RX error detection interrupt enable +* wpdma_tx_dmad_mem_range_err_int_ena[2] - (RW) WPDMA tx dma descriptor memory +* range error detection interrupt enable +* wpdma_rx_dmad_mem_range_err_int_ena[3] - (RW) WPDMA rx dma descriptor memory +* range error detection interrupt enable +* wpdma_tx_payload_mem_range_err_int_ena[4] - (RW) WPDMA tx payload memory range +* error detection interrupt enable +* wpdma_rx_payload_mem_range_err_int_ena[5] - (RW) WPDMA rx payload memory range +* error detection interrupt enable +* wpdma_axi_bresp_error_int_ena[6] - (RW) WPDMA AXI master bresp error detection +* interrupt enable +* wpdma_axi_rresp_error_int_ena[7] - (RW) WPDMA AXI master rresp error detection +* interrupt enable +* m0_wr_axi_err_det_int_ena[8] - (RW) WPDMA AXI write master for RX payload +* error detection interrupt enable +* m1_wr_axi_err_det_int_ena[9] - (RW) WPDMA AXI write master for RX DMAD error +* detection interrupt enable +* m2_wr_axi_err_det_int_ena[10] - (RW) WPDMA AXI write master for TX DMAD error +* detection interrupt enable +* m0_rd_axi_err_det_int_ena[11] - (RW) WPDMA AXI read master for DBDC0 TX +* payload error detection interrupt enable +* m1_rd_axi_err_det_int_ena[12] - (RW) WPDMA AXI read master for RX DMAD error +* detection interrupt enable +* m2_rd_axi_err_det_int_ena[13] - (RW) WPDMA AXI read master for TX DMAD error +* detection interrupt enable +* m3_rd_axi_err_det_int_ena[14] - (RW) WPDMA AXI read master for DBDC1 TX +* payload error detection interrupt enable +* pf_sram_size_underflow_int_ena[15] - (RW) Prefetch sram overflow error +* interrupt enable +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_pf_sram_size_underflow_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_pf_sram_size_underflow_int_ena_MASK \ + 0x00008000 /* pf_sram_size_underflow_int_ena[15] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_pf_sram_size_underflow_int_ena_SHFT \ + 15 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_m3_rd_axi_err_det_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_m3_rd_axi_err_det_int_ena_MASK \ + 0x00004000 /* m3_rd_axi_err_det_int_ena[14] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_m3_rd_axi_err_det_int_ena_SHFT \ + 14 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_m2_rd_axi_err_det_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_m2_rd_axi_err_det_int_ena_MASK \ + 0x00002000 /* m2_rd_axi_err_det_int_ena[13] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_m2_rd_axi_err_det_int_ena_SHFT \ + 13 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_m1_rd_axi_err_det_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_m1_rd_axi_err_det_int_ena_MASK \ + 0x00001000 /* m1_rd_axi_err_det_int_ena[12] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_m1_rd_axi_err_det_int_ena_SHFT \ + 12 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_m0_rd_axi_err_det_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_m0_rd_axi_err_det_int_ena_MASK \ + 0x00000800 /* m0_rd_axi_err_det_int_ena[11] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_m0_rd_axi_err_det_int_ena_SHFT \ + 11 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_m2_wr_axi_err_det_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_m2_wr_axi_err_det_int_ena_MASK \ + 0x00000400 /* m2_wr_axi_err_det_int_ena[10] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_m2_wr_axi_err_det_int_ena_SHFT \ + 10 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_m1_wr_axi_err_det_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_m1_wr_axi_err_det_int_ena_MASK \ + 0x00000200 /* m1_wr_axi_err_det_int_ena[9] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_m1_wr_axi_err_det_int_ena_SHFT \ + 9 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_m0_wr_axi_err_det_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_m0_wr_axi_err_det_int_ena_MASK \ + 0x00000100 /* m0_wr_axi_err_det_int_ena[8] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_m0_wr_axi_err_det_int_ena_SHFT \ + 8 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_axi_rresp_error_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_axi_rresp_error_int_ena_MASK \ + 0x00000080 /* wpdma_axi_rresp_error_int_ena[7] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_axi_rresp_error_int_ena_SHFT \ + 7 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_axi_bresp_error_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_axi_bresp_error_int_ena_MASK \ + 0x00000040 /* wpdma_axi_bresp_error_int_ena[6] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_axi_bresp_error_int_ena_SHFT \ + 6 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_payload_mem_range_err_int_en\ +a_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_payload_mem_range_err_int_en\ +a_MASK \ +0x00000020 /* wpdma_rx_payload_mem_range_err_int_ena[5] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_payload_mem_range_err_int_en\ +a_SHFT \ +5 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_payload_mem_range_err_int_en\ +a_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_payload_mem_range_err_int_en\ +a_MASK \ +0x00000010 /* wpdma_tx_payload_mem_range_err_int_ena[4] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_payload_mem_range_err_int_en\ +a_SHFT \ +4 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_dmad_mem_range_err_int_ena_A\ +DDR \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_dmad_mem_range_err_int_ena_M\ +ASK \ +0x00000008 /* wpdma_rx_dmad_mem_range_err_int_ena[3] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_dmad_mem_range_err_int_ena_S\ +HFT \ +3 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_dmad_mem_range_err_int_ena_A\ +DDR \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_dmad_mem_range_err_int_ena_M\ +ASK \ +0x00000004 /* wpdma_tx_dmad_mem_range_err_int_ena[2] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_dmad_mem_range_err_int_ena_S\ +HFT \ +2 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_timeout_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_timeout_int_ena_MASK \ + 0x00000002 /* wpdma_tx_timeout_int_ena[1] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_timeout_int_ena_SHFT \ + 1 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_timeout_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_timeout_int_ena_MASK \ + 0x00000001 /* wpdma_rx_timeout_int_ena[0] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_timeout_int_ena_SHFT \ + 0 + +/* +* ---MCU2HOST_SW_INT_STA (0x7C024000 + 0x1F0)--- +* mcu2host_sw_int_0[0] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_1[1] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_2[2] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_3[3] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_4[4] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_5[5] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_6[6] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_7[7] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_8[8] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_9[9] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_10[10] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_11[11] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_12[12] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_13[13] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_14[14] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_15[15] - (W1C) mcu2host interrupt status +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_15_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_15_MASK \ + 0x00008000 /* mcu2host_sw_int_15[15] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_15_SHFT 15 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_14_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_14_MASK \ + 0x00004000 /* mcu2host_sw_int_14[14] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_14_SHFT 14 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_13_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_13_MASK \ + 0x00002000 /* mcu2host_sw_int_13[13] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_13_SHFT 13 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_12_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_12_MASK \ + 0x00001000 /* mcu2host_sw_int_12[12] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_12_SHFT 12 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_11_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_11_MASK \ + 0x00000800 /* mcu2host_sw_int_11[11] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_11_SHFT 11 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_10_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_10_MASK \ + 0x00000400 /* mcu2host_sw_int_10[10] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_10_SHFT 10 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_9_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_9_MASK \ + 0x00000200 /* mcu2host_sw_int_9[9] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_9_SHFT 9 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_8_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_8_MASK \ + 0x00000100 /* mcu2host_sw_int_8[8] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_8_SHFT 8 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_7_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_7_MASK \ + 0x00000080 /* mcu2host_sw_int_7[7] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_7_SHFT 7 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_6_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_6_MASK \ + 0x00000040 /* mcu2host_sw_int_6[6] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_6_SHFT 6 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_5_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_5_MASK \ + 0x00000020 /* mcu2host_sw_int_5[5] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_5_SHFT 5 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_4_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_4_MASK \ + 0x00000010 /* mcu2host_sw_int_4[4] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_4_SHFT 4 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_3_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_3_MASK \ + 0x00000008 /* mcu2host_sw_int_3[3] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_2_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_2_MASK \ + 0x00000004 /* mcu2host_sw_int_2[2] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_1_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_1_MASK \ + 0x00000002 /* mcu2host_sw_int_1[1] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_0_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_0_MASK \ + 0x00000001 /* mcu2host_sw_int_0[0] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_0_SHFT 0 + +/* +* ---MCU2HOST_SW_INT_ENA (0x7C024000 + 0x1F4)--- +* mcu2host_int_ena_0[0] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_1[1] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_2[2] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_3[3] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_4[4] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_5[5] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_6[6] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_7[7] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_8[8] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_9[9] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_10[10] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_11[11] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_12[12] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_13[13] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_14[14] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_15[15] - (RW) MCU2HOST software interrupt interrupt enable +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_15_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_15_MASK \ + 0x00008000 /* mcu2host_int_ena_15[15] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_15_SHFT 15 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_14_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_14_MASK \ + 0x00004000 /* mcu2host_int_ena_14[14] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_14_SHFT 14 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_13_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_13_MASK \ + 0x00002000 /* mcu2host_int_ena_13[13] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_13_SHFT 13 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_12_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_12_MASK \ + 0x00001000 /* mcu2host_int_ena_12[12] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_12_SHFT 12 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_11_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_11_MASK \ + 0x00000800 /* mcu2host_int_ena_11[11] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_11_SHFT 11 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_10_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_10_MASK \ + 0x00000400 /* mcu2host_int_ena_10[10] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_10_SHFT 10 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_9_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_9_MASK \ + 0x00000200 /* mcu2host_int_ena_9[9] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_9_SHFT 9 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_8_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_8_MASK \ + 0x00000100 /* mcu2host_int_ena_8[8] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_8_SHFT 8 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_7_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_7_MASK \ + 0x00000080 /* mcu2host_int_ena_7[7] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_7_SHFT 7 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_6_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_6_MASK \ + 0x00000040 /* mcu2host_int_ena_6[6] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_6_SHFT 6 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_5_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_5_MASK \ + 0x00000020 /* mcu2host_int_ena_5[5] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_5_SHFT 5 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_4_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_4_MASK \ + 0x00000010 /* mcu2host_int_ena_4[4] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_4_SHFT 4 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_3_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_3_MASK \ + 0x00000008 /* mcu2host_int_ena_3[3] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_2_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_2_MASK \ + 0x00000004 /* mcu2host_int_ena_2[2] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_1_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_1_MASK \ + 0x00000002 /* mcu2host_int_ena_1[1] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_0_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_0_MASK \ + 0x00000001 /* mcu2host_int_ena_0[0] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_0_SHFT 0 + +/* +* ---SUBSYS2HOST_INT_STA (0x7C024000 + 0x1F8)--- +* mac_int_sts_0[0] - (RO) MAC interrupt 0: TBTT interrupt(Check +* wf_int_wakeup_top/hwisr0 [0x820Fc03c]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_1[1] - (RO) MAC interrupt 1: Pre-TBTT interrupt(Check +* wf_int_wakeup_top/hwisr1 [0x820Fc044]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_2[2] - (RO) MAC interrupt 2: TX status interrupt(Check +* wf_int_wakeup_top/hwisr2 [0x820Fc04c]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_3[3] - (RO) MAC interrupt 3: Auto wakeup interrupt (Check +* wf_int_wakeup_top/hwisr3 [0x820Fc054]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_4[4] - (RO) MAC interrupt 4: GP timer interrupt (Check +* wf_int_wakeup_top/hwisr4 [0x820Fc05c]) +* 0 : no interrupt +* 1 : interrupt assert +* RESERVED5[7..5] - (RO) Reserved bits +* conn_hif_on_host_int_sts[8] - (RO) CONN_HIF_ON interrupt enable +* 0 : no conn_hif_on_host_int interrupt +* 1 : conn_hif_on_host_int interrupt assert. User should check conn_hif_on +* (host_csr) interrupt status and clear interrupt. +* conn2ap_sw_irq_sts[9] - (RO) MCUSYS conn2ap_sw_irq status (Check +* conn_mcu_config/EMI_CTL [0x80000150] bit[4:0]) +* 0 : no conn2ap_sw_irq interrupt. +* 1 : conn2ap_sw_irq interrupt assert. User should check mcusys_n9 interrupt +* status and clear interrupt. (conn_mcu_config/EMI_CTL [0x80000150] bit[4:0] != +0) +* RESERVED10[31..10] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_conn2ap_sw_irq_sts_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_conn2ap_sw_irq_sts_MASK \ + 0x00000200 /* conn2ap_sw_irq_sts[9] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_conn2ap_sw_irq_sts_SHFT 9 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_conn_hif_on_host_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_conn_hif_on_host_int_sts_MASK \ + 0x00000100 /* conn_hif_on_host_int_sts[8] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_conn_hif_on_host_int_sts_SHFT 8 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_4_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_4_MASK \ + 0x00000010 /* mac_int_sts_4[4] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_4_SHFT 4 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_3_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_3_MASK \ + 0x00000008 /* mac_int_sts_3[3] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_2_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_2_MASK \ + 0x00000004 /* mac_int_sts_2[2] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_1_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_1_MASK \ + 0x00000002 /* mac_int_sts_1[1] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_0_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_0_MASK \ + 0x00000001 /* mac_int_sts_0[0] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_0_SHFT 0 + +/* +* ---SUBSYS2HOST_INT_ENA (0x7C024000 + 0x1FC)--- +* mac_int_ena_0[0] - (RW) MAC interrupt enable +* mac_int_ena_1[1] - (RW) MAC interrupt enable +* mac_int_ena_2[2] - (RW) MAC interrupt enable +* mac_int_ena_3[3] - (RW) MAC interrupt enable +* mac_int_ena_4[4] - (RW) MAC interrupt enable +* RESERVED5[7..5] - (RO) Reserved bits +* conn_hif_on_host_int_ena[8] - (RW) CONN_HIF_ON interrupt enable +* conn2ap_sw_irq_ena[9] - (RW) MCUSYS conn2ap_sw_irq enable +* RESERVED10[31..10] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_conn2ap_sw_irq_ena_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_conn2ap_sw_irq_ena_MASK \ + 0x00000200 /* conn2ap_sw_irq_ena[9] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_conn2ap_sw_irq_ena_SHFT 9 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_conn_hif_on_host_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_conn_hif_on_host_int_ena_MASK \ + 0x00000100 /* conn_hif_on_host_int_ena[8] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_conn_hif_on_host_int_ena_SHFT 8 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_4_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_4_MASK \ + 0x00000010 /* mac_int_ena_4[4] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_4_SHFT 4 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_3_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_3_MASK \ + 0x00000008 /* mac_int_ena_3[3] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_2_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_2_MASK \ + 0x00000004 /* mac_int_ena_2[2] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_1_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_1_MASK \ + 0x00000002 /* mac_int_ena_1[1] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_0_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_0_MASK \ + 0x00000001 /* mac_int_ena_0[0] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_0_SHFT 0 + +/* +* ---HOST_INT_STA (0x7C024000 + 0x200)--- +* rx_done_int_sts_0[0] - (W1C) RX Queue#0 packet receive interrupt +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* rx_done_int_sts_1[1] - (W1C) RX Queue#1 packet receive interrupt +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* rx_done_int_sts_2[2] - (W1C) RX Queue#2 packet receive interrupt +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* rx_done_int_sts_3[3] - (W1C) RX Queue#3 packet receive interrupt +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* tx_done_int_sts_0[4] - (W1C) TX Queue#0 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_1[5] - (W1C) TX Queue#1 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_2[6] - (W1C) TX Queue#2 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_3[7] - (W1C) TX Queue#3 packet transmit interrupt +* Write 1 to clear the interrupt +* RESERVED8[19..8] - (RO) Reserved bits +* rx_coherent_int_sts[20] - (W1C) RX_DMA finds data coherent event when checking +* ddone bit +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* tx_coherent_int_sts[21] - (W1C) TX_DMA finds data coherent event when checking +* ddone bit +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* RESERVED[23..22] - (RO) reserved, originally used for delayed interrupt of +* legacy TX/RX done +* wpdma2host_err_int_sts[24] - (RO) wpdma interrupt overall status +* User should should check WPDMA_ERR_INT_STA for each wpdma error interrupt +status +* Host could read [0x0_41E8] to check indivisual wpdma2host_error interrupt +status +* RESERVED25[27..25] - (RO) Reserved bits +* subsys_int_sts[28] - (RO) subsys interrupt overall status +* User should should check SUBSYS2HOST_INT_STA for each interrupt status +* Host could read [0x0_41F8] to check indivisual subsys hw interrupt status +* mcu2host_sw_int_sts[29] - (RO) subsys interrupt overall status +* User should should check SUBSYS2HOST_INT_STA for each interrupt status +* Host could read [0x0_41F8] to check indivisual subsys hw interrupt status +* RESERVED30[31..30] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_mcu2host_sw_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_mcu2host_sw_int_sts_MASK \ + 0x20000000 /* mcu2host_sw_int_sts[29] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_mcu2host_sw_int_sts_SHFT 29 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_subsys_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_subsys_int_sts_MASK \ + 0x10000000 /* subsys_int_sts[28] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_subsys_int_sts_SHFT 28 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_wpdma2host_err_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_wpdma2host_err_int_sts_MASK \ + 0x01000000 /* wpdma2host_err_int_sts[24] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_wpdma2host_err_int_sts_SHFT 24 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_coherent_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_coherent_int_sts_MASK \ + 0x00200000 /* tx_coherent_int_sts[21] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_coherent_int_sts_SHFT 21 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_coherent_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_coherent_int_sts_MASK \ + 0x00100000 /* rx_coherent_int_sts[20] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_coherent_int_sts_SHFT 20 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_3_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_3_MASK \ + 0x00000080 /* tx_done_int_sts_3[7] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_3_SHFT 7 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_2_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_2_MASK \ + 0x00000040 /* tx_done_int_sts_2[6] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_2_SHFT 6 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_1_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_1_MASK \ + 0x00000020 /* tx_done_int_sts_1[5] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_1_SHFT 5 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_0_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_0_MASK \ + 0x00000010 /* tx_done_int_sts_0[4] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_0_SHFT 4 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_3_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_3_MASK \ + 0x00000008 /* rx_done_int_sts_3[3] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_2_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_2_MASK \ + 0x00000004 /* rx_done_int_sts_2[2] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_1_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_1_MASK \ + 0x00000002 /* rx_done_int_sts_1[1] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_0_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_0_MASK \ + 0x00000001 /* rx_done_int_sts_0[0] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_0_SHFT 0 + +/* +* ---HOST_INT_ENA (0x7C024000 + 0X204)--- +* HOST_RX_DONE_INT_ENA0[0] - (RW) RX Queue#0 packet receive interrupt +* HOST_RX_DONE_INT_ENA1[1] - (RW) RX Queue#1 packet receive interrupt +* HOST_RX_DONE_INT_ENA2[2] - (RW) RX Queue#2 packet receive interrupt +* HOST_RX_DONE_INT_ENA3[3] - (RW) RX Queue#3 packet receive interrupt +* HOST_TX_DONE_INT_ENA0[4] - (RW) TX Queue#0 packet transmit interrupt +* HOST_TX_DONE_INT_ENA1[5] - (RW) TX Queue#1 packet transmit interrupt +* HOST_TX_DONE_INT_ENA2[6] - (RW) TX Queue#2 packet transmit interrupt +* HOST_TX_DONE_INT_ENA3[7] - (RW) TX Queue#3 packet transmit interrupt +* RESERVED8[19..8] - (RO) Reserved bits +* HOST_RX_COHERENT_EN[20] - (RW) Enable for RX_DMA data coherent interrupt +* HOST_TX_COHERENT_EN[21] - (RW) Enable for TX_DMA data coherent interrupt +* RESERVED[23..22] - (RO) reserved, originally used for delayed interrupt of +* legacy TX/RX done +* wpdma2host_err_int_ena[24] - (RW) Enable bit of wpdma2host_err_int +* RESERVED25[27..25] - (RO) Reserved bits +* subsys_int_ena[28] - (RW) Enable bit of subsys_int +* mcu2host_sw_int_ena[29] - (RW) Enable bit of mcu2host_sw_int +* RESERVED30[31..30] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_mcu2host_sw_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_mcu2host_sw_int_ena_MASK \ + 0x20000000 /* mcu2host_sw_int_ena[29] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_mcu2host_sw_int_ena_SHFT 29 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_subsys_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_subsys_int_ena_MASK \ + 0x10000000 /* subsys_int_ena[28] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_subsys_int_ena_SHFT 28 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_wpdma2host_err_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_wpdma2host_err_int_ena_MASK \ + 0x01000000 /* wpdma2host_err_int_ena[24] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_wpdma2host_err_int_ena_SHFT 24 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_COHERENT_EN_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_COHERENT_EN_MASK \ + 0x00200000 /* HOST_TX_COHERENT_EN[21] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_COHERENT_EN_SHFT 21 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_COHERENT_EN_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_COHERENT_EN_MASK \ + 0x00100000 /* HOST_RX_COHERENT_EN[20] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_COHERENT_EN_SHFT 20 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA3_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA3_MASK \ + 0x00000080 /* HOST_TX_DONE_INT_ENA3[7] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA3_SHFT 7 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA2_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA2_MASK \ + 0x00000040 /* HOST_TX_DONE_INT_ENA2[6] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA2_SHFT 6 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA1_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA1_MASK \ + 0x00000020 /* HOST_TX_DONE_INT_ENA1[5] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA1_SHFT 5 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA0_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA0_MASK \ + 0x00000010 /* HOST_TX_DONE_INT_ENA0[4] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA0_SHFT 4 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA3_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA3_MASK \ + 0x00000008 /* HOST_RX_DONE_INT_ENA3[3] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA2_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA2_MASK \ + 0x00000004 /* HOST_RX_DONE_INT_ENA2[2] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA1_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA1_MASK \ + 0x00000002 /* HOST_RX_DONE_INT_ENA1[1] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA0_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA0_MASK \ + 0x00000001 /* HOST_RX_DONE_INT_ENA0[0] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA0_SHFT 0 + +/* +* ---WPDMA_GLO_CFG (0x7C024000 + 0x208)--- +* TX_DMA_EN[0] - (RW) TX_DMA Enable +* 1: Enable TX_DMA, MUST wait until all prefetch rings' +* MAX_CNT(WPDMA_T(R)X_RING*_EXT_CTRL) of DMA including neighbor DMA have been +* configured successfully +* 0: Disable TX_DMA +* TX_DMA_BUSY[1] - (RO) TX_DMA Busy indicator +* 1: TX_DMA is busy +* 0: TX_DMA is not busy +* RX_DMA_EN[2] - (RW) RX_DMA Enable +* 1: Enable RX_DMA, MUST wait until all prefetch rings' +* MAX_CNT(WPDMA_T(R)X_RING*_EXT_CTRL) of DMA including neighbor DMA have been +* configured successfully +* 0: Disable RX_DMA +* RX_DMA_BUSY[3] - (RO) RX_DMA Busy indicator +* 1: RX_DMA is busy +* 0: RX_DMA is not busy +* PDMA_BT_SIZE[5..4] - (RW) Define the burst size of WPDMA +* 2'h0 : 4 DWORD (16bytes) +* 2'h1 : 8 DWORD (32 bytes) +* 2'h2 : 16 DWORD (64 bytes) +* 2'h3 : 32 DWORD (128 bytes) +* TX_WB_DDONE[6] - (RW) 1'b1 : TX engine will wait to assert IRQ util whole TX +* dmad has been fully written into AXI bus which represents HOST memory, 1'b0 : +* TX engine will assert IRQ once TX dmad write-back request have been ACKed +* BIG_ENDIAN[7] - (RW) The endian mode selection. DMA applies the endian rule to +* convert payload and TX/RX information. DMA won't apply endian rule to register +* or descriptor. +* 1: big endian. +* 0: little endian. +* DMAD_32B_EN[8] - (RW) DMA Descriptor 32-byte Enable +* 0: The size of descriptors is set to 16-byte +* 1: The size of descriptors is set to 32-byte +* FW_DWLD_Bypass_dmashdl[9] - (RW) No USE for (APSOC/PCIE) +* For firmware download packet, driver shold using tx-ring16 to download packet +* and set this bit to bypass dmashdl resource control. +* After firmware download finish, driver should clear this bit. +* After all, tx-ring16 could be used for normal data operation. +(USB) +* For USB test_mode, user could set this bit to bypass dmashdl with all endpoint +* CSR_WFDMA_DUMMY_REG[10] - (RW) dummy CR for use if ECO needed +* CSR_AXI_BUFRDY_BYP[11] - (RW) to disable read data fifo available checking +* before issuing next AXI read request +* FIFO_LITTLE_ENDIAN[12] - (RW) Determines the endianness of the FIFO side +* 0: Big-endian +* 1: Little-endian +* CSR_RX_WB_DDONE[13] - (RW) 1'b1 : RX engine will wait to assert IRQ util whole +* RX dmad has been fully written into AXI bus which represents HOST memory, 1'b0 +* : RX engine will assert IRQ once RX dmad write-back request have been ACKed +* CSR_PP_HIF_TXP_ACTIVE_EN[14] - (RW) 1'b1 : enable legacy pp_hif_txp_active +* function to lock tx engine for favor TXP transmit requested directly from PP, +* other pdma TX rings request will be masked until pp_hif_txp_active is +deasserted +* 1'b0 : disable legacy pp_hif_txp_active function, use latest TX source QoS +* design to change throttler settings to favor TXP transmit! +* CSR_DISP_BASE_PTR_CHAIN_EN[15] - (RW) Enable prefet sram ring address +* arrangement by hardware chain structure(DMA#N TX ring group -> DMA#N RX ring +* group -> DMA#M TX ring group -> DMA#M RX ring group and son on). If not +* enabled, firmware need to program DISP_BASE_PTR of WPDMA_T(R)X_RING*_EXT_CTRL +instead!! +* CSR_LBK_RX_Q_SEL[17..16] - (RW) loopback data from TXFIFO will be direct to +* this RX ring when CSR_LBK_RX_Q_SEL_EN in loopback mode, valid bit-width is +* equal to RX_RING_WIDTH which can be calculated from WPDMA_INFO 0x284[15:8] +RX_RING_NUMBER +* RESERVED18[19..18] - (RO) Reserved bits +* CSR_LBK_RX_Q_SEL_EN[20] - (RW) Force configured CSR_LBK_RX_Q_SEL to receive +* loopback data from TXFIFO +* RESERVED21[23..21] - (RO) Reserved bits +* CSR_SW_RST[24] - (RO) SW reset all designs (To be tested for SER in the +future) +* FORCE_TX_EOF[25] - (RW) Force to send an eof after PDMA being reset (for +Packet_Processor) +* 0: Disabled +* 1: Enabled +* PDMA_ADDR_EXT_EN[26] - (RW) No Fnction for now!! For PDMA Address 32bits +* extension. When this design option was enable. PDMA would change Tx/Rx +* descriptor format for address extension. +* 0 : PDMA 32bits address +* 1 : PDMA Tx descirptor DW3 (TXINFO) would used to extend address +* PDMA Rx descirpt DW2 (Reserved) would used to extend address. +* OMIT_RX_INFO[27] - (RW) For loopback mode, set to 1'b1. +* For normal wifi data operation. User should not set this option and should +* keep 1'b0 because UMAC will always add extra QW for checksum after received +* packet's laster QW +* VERY IMPORTANT : for cpu_dma0/1 where CR resides in 0x5100_0xxx, OMIT_RX_INFO +* MUST be set to 1'b1 +* Omit rx_info of all RX packets +* 0: All the PX packets should end with a rx_info +* 1: All the PX packets should NOT end with a rx_info but an eof +* OMIT_TX_INFO[28] - (RW) For loopback mode, set to 1'b1. +* For normal wifi data operation. User should set this option to +* Omit tx_info of all TX packets because UMAC design not support TXINFO +* 0: The tx_info in DMAD will be sent at the beginning +* 1: The tx_info in DMAD will NOT be sent at the beginning +* BYTE_SWAP[29] - (RW) Byte Swapping for TX/RX DMAD +* 0: Not to swap (Endian of DMAD unchanged) +* 1: Swap (Endian of DMAD reversed) +* CLK_GATE_DIS[30] - (RW) PDMA Clock Gated Function Disable +* 0: normal function +* 1: disable clock gated function +* RX_2B_OFFSET[31] - (RW) RX PBF 2-byte Offset +* 1: Skip the first two bytes of the RX PBF +* 0: Not to skip the first two bytes of the RX PBF +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_2B_OFFSET_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_2B_OFFSET_MASK \ + 0x80000000 /* RX_2B_OFFSET[31] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_2B_OFFSET_SHFT 31 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CLK_GATE_DIS_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CLK_GATE_DIS_MASK \ + 0x40000000 /* CLK_GATE_DIS[30] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CLK_GATE_DIS_SHFT 30 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_BYTE_SWAP_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_BYTE_SWAP_MASK \ + 0x20000000 /* BYTE_SWAP[29] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_BYTE_SWAP_SHFT 29 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_OMIT_TX_INFO_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_OMIT_TX_INFO_MASK \ + 0x10000000 /* OMIT_TX_INFO[28] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_OMIT_TX_INFO_SHFT 28 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_OMIT_RX_INFO_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_OMIT_RX_INFO_MASK \ + 0x08000000 /* OMIT_RX_INFO[27] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_OMIT_RX_INFO_SHFT 27 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_PDMA_ADDR_EXT_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_PDMA_ADDR_EXT_EN_MASK \ + 0x04000000 /* PDMA_ADDR_EXT_EN[26] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_PDMA_ADDR_EXT_EN_SHFT 26 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FORCE_TX_EOF_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FORCE_TX_EOF_MASK \ + 0x02000000 /* FORCE_TX_EOF[25] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FORCE_TX_EOF_SHFT 25 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_SW_RST_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_SW_RST_MASK \ + 0x01000000 /* CSR_SW_RST[24] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_SW_RST_SHFT 24 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_EN_MASK \ + 0x00100000 /* CSR_LBK_RX_Q_SEL_EN[20] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_EN_SHFT 20 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_MASK \ + 0x00030000 /* CSR_LBK_RX_Q_SEL[17..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN_MASK \ + 0x00008000 /* CSR_DISP_BASE_PTR_CHAIN_EN[15] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN_SHFT 15 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_PP_HIF_TXP_ACTIVE_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_PP_HIF_TXP_ACTIVE_EN_MASK \ + 0x00004000 /* CSR_PP_HIF_TXP_ACTIVE_EN[14] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_PP_HIF_TXP_ACTIVE_EN_SHFT 14 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_RX_WB_DDONE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_RX_WB_DDONE_MASK \ + 0x00002000 /* CSR_RX_WB_DDONE[13] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_RX_WB_DDONE_SHFT 13 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN_MASK \ + 0x00001000 /* FIFO_LITTLE_ENDIAN[12] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN_SHFT 12 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_AXI_BUFRDY_BYP_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_AXI_BUFRDY_BYP_MASK \ + 0x00000800 /* CSR_AXI_BUFRDY_BYP[11] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_AXI_BUFRDY_BYP_SHFT 11 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_WFDMA_DUMMY_REG_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_WFDMA_DUMMY_REG_MASK \ + 0x00000400 /* CSR_WFDMA_DUMMY_REG[10] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_WFDMA_DUMMY_REG_SHFT 10 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FW_DWLD_Bypass_dmashdl_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FW_DWLD_Bypass_dmashdl_MASK \ + 0x00000200 /* FW_DWLD_Bypass_dmashdl[9] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FW_DWLD_Bypass_dmashdl_SHFT 9 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_DMAD_32B_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_DMAD_32B_EN_MASK \ + 0x00000100 /* DMAD_32B_EN[8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_DMAD_32B_EN_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_BIG_ENDIAN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_BIG_ENDIAN_MASK \ + 0x00000080 /* BIG_ENDIAN[7] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_BIG_ENDIAN_SHFT 7 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_WB_DDONE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_WB_DDONE_MASK \ + 0x00000040 /* TX_WB_DDONE[6] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_WB_DDONE_SHFT 6 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_PDMA_BT_SIZE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_PDMA_BT_SIZE_MASK \ + 0x00000030 /* PDMA_BT_SIZE[5..4] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_PDMA_BT_SIZE_SHFT 4 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_BUSY_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_BUSY_MASK \ + 0x00000008 /* RX_DMA_BUSY[3] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_BUSY_SHFT 3 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_EN_MASK \ + 0x00000004 /* RX_DMA_EN[2] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_EN_SHFT 2 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_BUSY_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_BUSY_MASK \ + 0x00000002 /* TX_DMA_BUSY[1] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_BUSY_SHFT 1 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_EN_MASK \ + 0x00000001 /* TX_DMA_EN[0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_EN_SHFT 0 + +/* +* ---WPDMA_RST_DTX_PTR (0x7C024000 + 0x20C)--- +* RST_DTX_IDX0[0] - (WO) Write 1 to reset to TX_DMATX_IDX0 to 0 +* RST_DTX_IDX1[1] - (WO) Write 1 to reset to TX_DMATX_IDX1 to 0 +* RST_DTX_IDX2[2] - (WO) Write 1 to reset to TX_DMATX_IDX2 to 0 +* RST_DTX_IDX3[3] - (WO) Write 1 to reset to TX_DMATX_IDX3 to 0 +* RESERVED[31..4] - (WO) Reserved +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX3_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX3_MASK \ + 0x00000008 /* RST_DTX_IDX3[3] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX2_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX2_MASK \ + 0x00000004 /* RST_DTX_IDX2[2] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX1_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX1_MASK \ + 0x00000002 /* RST_DTX_IDX1[1] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX0_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX0_MASK \ + 0x00000001 /* RST_DTX_IDX0[0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX0_SHFT 0 + +/* +* ---WPDMA_PAUSE_TX_Q (0x7C024000 + 0x224)--- +* TX_Q_PAUSE[3..0] - (RW) Pause signal for each TX ring (16 bits for 16 rings) +* Set 0: Normal function; Set 1: The corresponding TX ring is paused +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_TX_Q_TX_Q_PAUSE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_TX_Q_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_TX_Q_TX_Q_PAUSE_MASK \ + 0x0000000F /* TX_Q_PAUSE[3..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_TX_Q_TX_Q_PAUSE_SHFT 0 + +/* +* ---WPDMA_TIMEOUT_CFG (0x7C024000 + 0x230)--- +* WPDMA_TX_TIMEOUT_TH[7..0] - (RW) xxx +* WPDMA_TX_TIMEOUT_TICK[14..8] - (RW) xxx +* WPDMA_TX_TIMEOUT_ENA[15] - (RW) xxx +* WPDMA_RX_TIMEOUT_TH[23..16] - (RW) xxx +* WPDMA_RX_TIMEOUT_TICK[30..24] - (RW) xxx +* WPDMA_RX_TIMEOUT_ENA[31] - (RW) xxx +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_ENA_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_ENA_MASK \ + 0x80000000 /* WPDMA_RX_TIMEOUT_ENA[31] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_ENA_SHFT 31 +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TICK_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TICK_MASK \ + 0x7F000000 /* WPDMA_RX_TIMEOUT_TICK[30..24] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TICK_SHFT 24 +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TH_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TH_MASK \ + 0x00FF0000 /* WPDMA_RX_TIMEOUT_TH[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TH_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_ENA_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_ENA_MASK \ + 0x00008000 /* WPDMA_TX_TIMEOUT_ENA[15] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_ENA_SHFT 15 +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TICK_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TICK_MASK \ + 0x00007F00 /* WPDMA_TX_TIMEOUT_TICK[14..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TICK_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TH_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TH_MASK \ + 0x000000FF /* WPDMA_TX_TIMEOUT_TH[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TH_SHFT 0 + +/* +* ---WPDMA_MISC_CFG (0x7C024000 + 0x234)--- +* WPDMA_TX_TIMEOUT_SEL[0] - (RW) xxx +* WPDMA_RX_TIMEOUT_SEL[1] - (RW) xxx +* WPDMA_RX_FREE_Q_TH[5..2] - (RW) When loopback, this will be used to generate +* correct tx_pause to avlid deadlock which caused from situration that tx_dma +* will start reading tx packet from memory without considering lack of RX dmad +* in prefetch sram and needing to read RX dmad from memory which tx dma is +* reading tx packet too and rready is deasserted due to txfifo full !! +* RX dmad in prefetch sram should be greater than RX_FREE_Q_TH for rx_dma to +* start writing received packet into memory!! +* RESERVED6[31..6] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_RX_FREE_Q_TH_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_RX_FREE_Q_TH_MASK \ + 0x0000003C /* WPDMA_RX_FREE_Q_TH[5..2] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_RX_FREE_Q_TH_SHFT 2 +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_RX_TIMEOUT_SEL_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_RX_TIMEOUT_SEL_MASK \ + 0x00000002 /* WPDMA_RX_TIMEOUT_SEL[1] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_RX_TIMEOUT_SEL_SHFT 1 +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_TX_TIMEOUT_SEL_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_TX_TIMEOUT_SEL_MASK \ + 0x00000001 /* WPDMA_TX_TIMEOUT_SEL[0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_TX_TIMEOUT_SEL_SHFT 0 + +/* +* ---WPDMA_TX_WRR_ARB_GBF0 (0x7C024000 + 0x240)--- +* WRR_REQ0_ARB_GBF[2..0] - (RW) WRR REQ#0 priority level, mapped to lumpped +* request from TX ring0~ring15 for host TXD +* WRR_REQ1_ARB_GBF[5..3] - (RW) WRR REQ#1 priority level, mapped to request from +* TX ring16 when dual tx fifo for host event packet +* WRR_REQ2_ARB_GBF[8..6] - (RW) WRR REQ#2 priority level, mapped to request from +* TX ring17 when dual tx fifo for host event packet +* WRR_REQ3_ARB_GBF[11..9] - (RW) WRR REQ#3 priority level, mapped to request +* from TX ring18 when dual tx fifo for host event packet +* WRR_REQ4_ARB_GBF[14..12] - (RW) WRR REQ#4 priority level, mapped to request +* from TX ring19 when dual tx fifo for host event packet +* RESERVED[31..15] - (RW) Reserved +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ4_ARB_GBF_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ4_ARB_GBF_MASK \ + 0x00007000 /* WRR_REQ4_ARB_GBF[14..12] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ4_ARB_GBF_SHFT 12 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ3_ARB_GBF_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ3_ARB_GBF_MASK \ + 0x00000E00 /* WRR_REQ3_ARB_GBF[11..9] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ3_ARB_GBF_SHFT 9 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ2_ARB_GBF_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ2_ARB_GBF_MASK \ + 0x000001C0 /* WRR_REQ2_ARB_GBF[8..6] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ2_ARB_GBF_SHFT 6 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ1_ARB_GBF_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ1_ARB_GBF_MASK \ + 0x00000038 /* WRR_REQ1_ARB_GBF[5..3] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ1_ARB_GBF_SHFT 3 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ0_ARB_GBF_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ0_ARB_GBF_MASK \ + 0x00000007 /* WRR_REQ0_ARB_GBF[2..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ0_ARB_GBF_SHFT 0 + +/* +* ---WPDMA_PAUSE_RX_Q_TH10 (0x7C024000 + 0x260)--- +* RX_DMAD_TH0[11..0] - (RW) RX Ring0 DMAD threshold to pause PP sending packet +* to RX FIFO +* pause_rx_q = (available RX DMAD counts) < +* RESERVED12[15..12] - (RO) Reserved bits +* RX_DMAD_TH1[27..16] - (RW) RX Ring1 DMAD threshold to pause PP sending packet +* to RX FIFO +* pause_rx_q = (available RX DMAD counts) < +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH1_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH1_MASK \ + 0x0FFF0000 /* RX_DMAD_TH1[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH1_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH0_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH0_MASK \ + 0x00000FFF /* RX_DMAD_TH0[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH0_SHFT 0 + +/* +* ---WPDMA_PAUSE_RX_Q_TH32 (0x7C024000 + 0x264)--- +* RX_DMAD_TH2[11..0] - (RW) RX Ring2 DMAD threshold to pause PP sending packet +* to RX FIFO +* pause_rx_q = (available RX DMAD counts) < +* RESERVED12[15..12] - (RO) Reserved bits +* RX_DMAD_TH3[27..16] - (RW) RX Ring3 DMAD threshold to pause PP sending packet +* to RX FIFO +* pause_rx_q = (available RX DMAD counts) < +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH3_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH3_MASK \ + 0x0FFF0000 /* RX_DMAD_TH3[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH3_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH2_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH2_MASK \ + 0x00000FFF /* RX_DMAD_TH2[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH2_SHFT 0 + +/* +* ---WPDMA_PAUSE_RX_Q_TH54 (0x7C024000 + 0x268)--- +* RX_DMAD_TH4[11..0] - (RW) RX Ring4 DMAD threshold to pause PP sending packet +* to RX FIFO +* pause_rx_q = (available RX DMAD counts) < +* RESERVED12[15..12] - (RO) Reserved bits +* RX_DMAD_TH5[27..16] - (RW) RX Ring5 DMAD threshold to pause PP sending packet +* to RX FIFO +* pause_rx_q = (available RX DMAD counts) < +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH5_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH5_MASK \ + 0x0FFF0000 /* RX_DMAD_TH5[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH5_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH4_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH4_MASK \ + 0x00000FFF /* RX_DMAD_TH4[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH4_SHFT 0 + +/* +* ---WPDMA_PAUSE_RX_Q_TH76 (0x7C024000 + 0x26C)--- +* RX_DMAD_TH6[11..0] - (RW) RX Ring6 DMAD threshold to pause PP sending packet +* to RX FIFO +* pause_rx_q = (available RX DMAD counts) < +* RESERVED12[15..12] - (RO) Reserved bits +* RX_DMAD_TH7[27..16] - (RW) RX Ring7 DMAD threshold to pause PP sending packet +* to RX FIFO +* pause_rx_q = (available RX DMAD counts) < +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH7_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH7_MASK \ + 0x0FFF0000 /* RX_DMAD_TH7[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH7_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH6_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH6_MASK \ + 0x00000FFF /* RX_DMAD_TH6[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH6_SHFT 0 + +/* +* ---WPDMA_RST_DRX_PTR (0x7C024000 + 0x280)--- +* RST_DRX_IDX0[0] - (WO) Write 1 to reset to RX_DMARX_IDX0 to 0 +* RST_DRX_IDX1[1] - (WO) Write 1 to reset to RX_DMARX_IDX1 to 0 +* RST_DRX_IDX2[2] - (WO) Write 1 to reset to RX_DMARX_IDX2 to 0 +* RST_DRX_IDX3[3] - (WO) Write 1 to reset to RX_DMARX_IDX3 to 0 +* RESERVED[31..4] - (WO) Reserved +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX3_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX3_MASK \ + 0x00000008 /* RST_DRX_IDX3[3] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX2_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX2_MASK \ + 0x00000004 /* RST_DRX_IDX2[2] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX1_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX1_MASK \ + 0x00000002 /* RST_DRX_IDX1[1] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX0_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX0_MASK \ + 0x00000001 /* RST_DRX_IDX0[0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX0_SHFT 0 + +/* +* ---WPDMA_INFO (0x7C024000 + 0x284)--- +* TX_RING_NUMBER[7..0] - (RO) TX_RING_NUMBER +* RX_RING_NUMBER[15..8] - (RO) RX_RING_NUMBER +* BASE_PTR_WIDTH[23..16] - (RO) {2'h0, 6'd32-'BASE_PTR_WIDTH[5:0]} +* INDEX_WIDTH[27..24] - (RO) RING_INDEX_WIDTH +* PDMA_PREFETCH_SRAM_SIZE[30..28] - (RO) PDMA prefetch sram size{3'h0 : 128 +* byte, 3'h1 : 256 byte, 3'h2 : 512 byte, 3'h3 : 1KB, 3'h4 : 2KB, 3'h5 : 4KB, +* 3'h6 : 8KB, 3'h7 : reserved}, be noticed that prefetch sram is shared outside +* with other DMAs, please check all DMAs' total prefetch ring number and max_cnt +* for each prefetch ring to make sure that total size of all configured prefetch +* dmad of all DMAs' prefetch ring should be less than PDMA_PREFETCH_SRAM_SIZE +* WFDMA_PDA_EXIST[31] - (RO) Only cpu_dma1 will support pda functions for +* firmware download and wfdma_pda_top resides in between cpu_dma0 and cpu_dma1! +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_WFDMA_PDA_EXIST_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_WFDMA_PDA_EXIST_MASK \ + 0x80000000 /* WFDMA_PDA_EXIST[31] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_WFDMA_PDA_EXIST_SHFT 31 +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_PDMA_PREFETCH_SRAM_SIZE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_PDMA_PREFETCH_SRAM_SIZE_MASK \ + 0x70000000 /* PDMA_PREFETCH_SRAM_SIZE[30..28] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_PDMA_PREFETCH_SRAM_SIZE_SHFT 28 +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_INDEX_WIDTH_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_INDEX_WIDTH_MASK \ + 0x0F000000 /* INDEX_WIDTH[27..24] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_INDEX_WIDTH_SHFT 24 +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_BASE_PTR_WIDTH_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_BASE_PTR_WIDTH_MASK \ + 0x00FF0000 /* BASE_PTR_WIDTH[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_BASE_PTR_WIDTH_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_RX_RING_NUMBER_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_RX_RING_NUMBER_MASK \ + 0x0000FF00 /* RX_RING_NUMBER[15..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_RX_RING_NUMBER_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_TX_RING_NUMBER_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_TX_RING_NUMBER_MASK \ + 0x000000FF /* TX_RING_NUMBER[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_TX_RING_NUMBER_SHFT 0 + +/* +* ---WPDMA_INFO_EXT (0x7C024000 + 0x288)--- +* TX_EVENT_RING_NUMBER[7..0] - (RO) When TX_EVENT_RING_NUMBER equal 8'h0, it +* means that this DMA doesn't support dual TX fifo, thus in default it only +* support TX_RING_NUMBER of TX rings !! +* But when TX_EVENT_RING_NUMBER NOT equal 8'h0, this dma is configured as dual +* TX fifo and TX_RING[16+TX_EVENT_RING_NUM-1:16] are for getting HOST EVENT +* packet from HOST to WX_CPU!! +* TX_DMAD_RING_NUMBER[15..8] - (RO) When TX_EVENT_RING_NUMBER not equal to 8'h0, +* it means that this DMA support dual TX fifo and TX +* ring[TX_DMAD_RING_NUMBER-1:0] are for getting TXD from HOST to UMAC!! +* RESERVED[30..16] - (RO) Reserved +* TX_DMASHDL_EXIST[31] - (RO) TX_DMASHDL_EXIST +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_DMASHDL_EXIST_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_DMASHDL_EXIST_MASK \ + 0x80000000 /* TX_DMASHDL_EXIST[31] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_DMASHDL_EXIST_SHFT 31 +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_DMAD_RING_NUMBER_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_DMAD_RING_NUMBER_MASK \ + 0x0000FF00 /* TX_DMAD_RING_NUMBER[15..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_DMAD_RING_NUMBER_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_EVENT_RING_NUMBER_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_EVENT_RING_NUMBER_MASK \ + 0x000000FF /* TX_EVENT_RING_NUMBER[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_EVENT_RING_NUMBER_SHFT 0 + +/* +* ---WPDMA_INT_RX_PRI_SEL (0x7C024000 + 0x298)--- +* WPDMA_INT_RX_RING0_PRI_SEL[0] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_RX_RING1_PRI_SEL[1] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_RX_RING2_PRI_SEL[2] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* RESERVED3[31..3] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING2_PRI_SEL_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING2_PRI_SEL_MASK \ + 0x00000004 /* WPDMA_INT_RX_RING2_PRI_SEL[2] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING2_PRI_SEL_SHFT \ + 2 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING1_PRI_SEL_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING1_PRI_SEL_MASK \ + 0x00000002 /* WPDMA_INT_RX_RING1_PRI_SEL[1] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING1_PRI_SEL_SHFT \ + 1 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING0_PRI_SEL_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING0_PRI_SEL_MASK \ + 0x00000001 /* WPDMA_INT_RX_RING0_PRI_SEL[0] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING0_PRI_SEL_SHFT \ + 0 + +/* +* ---WPDMA_TX_DBG0 (0x7C024000 + 0x2A0)--- +* WPDMA_TX_DBG0[31..0] - (RO) xxx +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG0_WPDMA_TX_DBG0_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG0_WPDMA_TX_DBG0_MASK \ + 0xFFFFFFFF /* WPDMA_TX_DBG0[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG0_WPDMA_TX_DBG0_SHFT 0 + +/* +* ---WPDMA_TX_DBG1 (0x7C024000 + 0x2A4)--- +* WPDMA_TX_DBG1[31..0] - (RO) xxx +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG1_WPDMA_TX_DBG1_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG1_WPDMA_TX_DBG1_MASK \ + 0xFFFFFFFF /* WPDMA_TX_DBG1[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG1_WPDMA_TX_DBG1_SHFT 0 + +/* +* ---WPDMA_RX_DBG0 (0x7C024000 + 0x2A8)--- +* WPDMA_RX_DBG0[31..0] - (RO) xxx +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG0_WPDMA_RX_DBG0_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG0_WPDMA_RX_DBG0_MASK \ + 0xFFFFFFFF /* WPDMA_RX_DBG0[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG0_WPDMA_RX_DBG0_SHFT 0 + +/* +* ---WPDMA_RX_DBG1 (0x7C024000 + 0x2AC)--- +* WPDMA_RX_DBG1[31..0] - (RO) xxx +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG1_WPDMA_RX_DBG1_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG1_WPDMA_RX_DBG1_MASK \ + 0xFFFFFFFF /* WPDMA_RX_DBG1[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG1_WPDMA_RX_DBG1_SHFT 0 + +/* +* ---WPDMA_GLO_CFG_EXT0 (0x7C024000 + 0x2B0)--- +* CSR_MAX_PREFETCH_CNT[1..0] - (RW) Max. dmad count per prefet request, 2'b00 : +* 1 entry, 2'b01 : 2 entries, 2'b10 : 4 entries, 2'b11 : 8 entries, Note : 1 +* entry(dmad size) is 16 bytes = 4 DWs = 2 QWs +* CSR_MEM_BST_SIZE[3..2] - (RW) Max. burst size per sram request. 00 : 16-byte, +* 01 : 32-byte, 10 : 64-byte, 11 : 128-byte +* CSR_MEM_ARB_LOCK_EN[4] - (RW) 1'b1 : Lock round-robin sram access arbiter +* until whole long burst request from dma FSM finish, 1'b0 : no lock sram +* arbiter, grant will be change per request due to round-robin +* CSR_RX_DMA_WBQ_EN[5] - (RW) 1'b1 : RX dmad will be posted-write and deal with +* next received packet immediately, 1'b0 : RX dmad will be written back +* immediately after received packet has been sent to host memory +* CSR_TX_DMASHDL_ENABLE[6] - (RW) 1'b1 : request DMASHDL before TX to select +* next TX ring, 1'b0 : disable DMASHDL and use round-robin arbiter to select +* next TX ring +* CSR_BRESP_ERROR_BYPASS_EN[7] - (RW) 1'b1 : Bypass AXI error bresp as a normal +* response. 1'b0 : Will not assert bready to error bresp(00 : OKAY, 01 : EXOKAY, +* 10 : SLVERR, 11 : DECERR) +* CSR_AXI_SLEEP_MODE[9..8] - (RW) 2'b00 : no sleep, normal TX/RX, 2b1* : sleep +* after AXI request, 2'b11 : force assertion of wvalid, rready and bready to +* finish all committed data phases, then sleep immediately +* RESERVED10[14..10] - (RO) Reserved bits +* CSR_Q_STATUS_IDX_BKRS_EN[15] - (RW) backup/restore enable bit for +* q_status(payload, prefetch and dispatch) index +* CSR_AXI_BST_SIZE[17..16] - (RW) AXI busrt length, 00 : 128-byte, 01 : 64-byte, +* 10 : 32-byte, 11 : 16-byte +* CSR_RX_DMAD_WB_MIRROR_EN[18] - (RW) Set to 1'b1 to split RX DMAD write-back +* into two AXI request which carries ddone bit (DW1[31], DW1[15]) for each iif +* external AXI dispatcher exist and need to do push-write behavior to make sure +* all datas from two PCIE have arrived HOST memory +* CSR_AXI_FAKE[19] - (RW) If set to 1'b1, all requests from DMA engine will not +* be sent to AXI INFRA, this try to fix AXI bus hang issue temporarily! +* CSR_DMAD_PREFETCH_THRESHOLD[21..20] - (RW) trigger dmad prefetch when +* available dmad cnt >= {1(2'b00), 2(2'b01), 4(2'b10), 8(2'b11)} +* CSR_BID_CHECK_BYPASS_EN[22] - (RW) If set to 1'b0, axi master will check +* matching between awid and bid before assert bready, if set to 1'b1, it will +* bypass this checking and assert bready for each bvalid even though bid doesn't +* match any awid ever issued! +* CSR_RX_INFO_WB_EN[23] - (RW) If set to 1'b0, only DW0 and DW1 will be written +* back into memory after received RX packet process finished, this will save bus +* bandwidth a little because DW2 and DW3 are useless for FW +* CSR_AXI_OUTSTANDING_NUM[27..24] - (RW) decide max. outstanding AXI requests, +* common for AXI read or write! +* CSR_AXI_ARUSER_LOCK_EN[28] - (RW) on/off customized lock ctrl design thru AXI +* aruser signal, this will influence TX QoS ctrl +* CSR_AXI_AWUSER_LOCK_EN[29] - (RW) on/off customized lock ctrl design thru AXI +* awuser signal when RX dmad write-back have to be separately written into +* memory due to external dispatcher exists! +* CSR_AXI_LOCK_EN[30] - (RW) Global lock enable to on/off AXI spec. lock(axlock) +* behavior and also will on/off customized lock ctrl design thru AXI awuser +signal +* CSR_AXI_CLKGATE_BYP[31] - (RW) To bypass functional CG enable which incduced +* from coding style for DC inserted CG cell in all AXI read/write master design +module +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_CLKGATE_BYP_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_CLKGATE_BYP_MASK \ + 0x80000000 /* CSR_AXI_CLKGATE_BYP[31] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_CLKGATE_BYP_SHFT 31 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_LOCK_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_LOCK_EN_MASK \ + 0x40000000 /* CSR_AXI_LOCK_EN[30] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_LOCK_EN_SHFT 30 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_AWUSER_LOCK_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_AWUSER_LOCK_EN_MASK \ + 0x20000000 /* CSR_AXI_AWUSER_LOCK_EN[29] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_AWUSER_LOCK_EN_SHFT 29 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_ARUSER_LOCK_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_ARUSER_LOCK_EN_MASK \ + 0x10000000 /* CSR_AXI_ARUSER_LOCK_EN[28] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_ARUSER_LOCK_EN_SHFT 28 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_OUTSTANDING_NUM_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_OUTSTANDING_NUM_MASK \ + 0x0F000000 /* CSR_AXI_OUTSTANDING_NUM[27..24] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_OUTSTANDING_NUM_SHFT 24 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_RX_INFO_WB_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_RX_INFO_WB_EN_MASK \ + 0x00800000 /* CSR_RX_INFO_WB_EN[23] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_RX_INFO_WB_EN_SHFT 23 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_BID_CHECK_BYPASS_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_BID_CHECK_BYPASS_EN_MASK \ + 0x00400000 /* CSR_BID_CHECK_BYPASS_EN[22] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_BID_CHECK_BYPASS_EN_SHFT 22 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_DMAD_PREFETCH_THRESHOLD_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_DMAD_PREFETCH_THRESHOLD_MASK \ + 0x00300000 /* CSR_DMAD_PREFETCH_THRESHOLD[21..20] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_DMAD_PREFETCH_THRESHOLD_SHFT \ + 20 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_FAKE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_FAKE_MASK \ + 0x00080000 /* CSR_AXI_FAKE[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_FAKE_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_RX_DMAD_WB_MIRROR_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_RX_DMAD_WB_MIRROR_EN_MASK \ + 0x00040000 /* CSR_RX_DMAD_WB_MIRROR_EN[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_RX_DMAD_WB_MIRROR_EN_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_BST_SIZE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_BST_SIZE_MASK \ + 0x00030000 /* CSR_AXI_BST_SIZE[17..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_BST_SIZE_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_Q_STATUS_IDX_BKRS_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_Q_STATUS_IDX_BKRS_EN_MASK \ + 0x00008000 /* CSR_Q_STATUS_IDX_BKRS_EN[15] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_Q_STATUS_IDX_BKRS_EN_SHFT 15 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_SLEEP_MODE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_SLEEP_MODE_MASK \ + 0x00000300 /* CSR_AXI_SLEEP_MODE[9..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_SLEEP_MODE_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_BRESP_ERROR_BYPASS_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_BRESP_ERROR_BYPASS_EN_MASK \ + 0x00000080 /* CSR_BRESP_ERROR_BYPASS_EN[7] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_BRESP_ERROR_BYPASS_EN_SHFT 7 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_TX_DMASHDL_ENABLE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_TX_DMASHDL_ENABLE_MASK \ + 0x00000040 /* CSR_TX_DMASHDL_ENABLE[6] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_TX_DMASHDL_ENABLE_SHFT 6 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_RX_DMA_WBQ_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_RX_DMA_WBQ_EN_MASK \ + 0x00000020 /* CSR_RX_DMA_WBQ_EN[5] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_RX_DMA_WBQ_EN_SHFT 5 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MEM_ARB_LOCK_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MEM_ARB_LOCK_EN_MASK \ + 0x00000010 /* CSR_MEM_ARB_LOCK_EN[4] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MEM_ARB_LOCK_EN_SHFT 4 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MEM_BST_SIZE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MEM_BST_SIZE_MASK \ + 0x0000000C /* CSR_MEM_BST_SIZE[3..2] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MEM_BST_SIZE_SHFT 2 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MAX_PREFETCH_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MAX_PREFETCH_CNT_MASK \ + 0x00000003 /* CSR_MAX_PREFETCH_CNT[1..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MAX_PREFETCH_CNT_SHFT 0 + +/* +* ---WPDMA_GLO_CFG_EXT1 (0x7C024000 + 0x2B4)--- +* CSR_TXFIFO0_RDY_THRESHOLD[7..0] - (RW) xxx +* CSR_TXFIFO1_RDY_THRESHOLD[15..8] - (RW) xxx +* CSR_TX_DISP_ARB_SCHEDULED_ACCESS_TIMER[23..16] - (RW) timer setting for +* SCHEDULED_ACCESS_TIME_ARB of csr_tx_disp_arb_mode +* CSR_TX_DISP_ARB_MODE[25..24] - (RW) 00 : FAIR_ARB, 01 : FIX_ARB, 10 : +* UNBALANCED_ARB, 11 : SCHEDULED_ACCESS_TIME_ARB +* CSR_FWDL_FLOW_CTRL_BYASS_EN[26] - (RW) To disable firmware download TX flow +* control of TX dma(host_dma1) when firmare download of RX dma(mcu_dma1) is in +* firmware download polling mode!! Remember to set to 1'b0 when firmware +* download ring is set back to normal ring usage which should be in flow control +* for correct behavior!! +* CSR_FWDL_FLOW_CTRL_BYASS_LS_QSEL_EN[27] - (RW) select firmware download TX +* ring(LSB/MSB ring) to bypass TX flow control when firmare download RX +* ring(LSB/MSB ring) of RX dma(mcu_dma1) is in firmware download polling mode!! +* RESERVED[31..28] - (RW) reserved +*/ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_LS_QSEL_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_LS_QSEL_EN_MASK \ + 0x08000000 /* CSR_FWDL_FLOW_CTRL_BYASS_LS_QSEL_EN[27] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_LS_QSEL_EN_SHFT \ + 27 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_EN_MASK \ + 0x04000000 /* CSR_FWDL_FLOW_CTRL_BYASS_EN[26] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_EN_SHFT \ + 26 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_MODE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_MODE_MASK \ + 0x03000000 /* CSR_TX_DISP_ARB_MODE[25..24] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_MODE_SHFT 24 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_SCHEDULED_ACCESS_TIMER_AD\ +DR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_SCHEDULED_ACCESS_TIMER_MA\ +SK \ +0x00FF0000 /* CSR_TX_DISP_ARB_SCHEDULED_ACCESS_TIMER[23..16] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_SCHEDULED_ACCESS_TIMER_SH\ +FT \ +16 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO1_RDY_THRESHOLD_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO1_RDY_THRESHOLD_MASK \ + 0x0000FF00 /* CSR_TXFIFO1_RDY_THRESHOLD[15..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO1_RDY_THRESHOLD_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO0_RDY_THRESHOLD_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO0_RDY_THRESHOLD_MASK \ + 0x000000FF /* CSR_TXFIFO0_RDY_THRESHOLD[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO0_RDY_THRESHOLD_SHFT 0 + +/* +* ---WPDMA_AXI_MST_DBG0 (0x7C024000 + 0x2B8)--- +* M0_AXI_RRESP_ERROR_RRESP[1..0] - (W1C) tx_pfet AXI rresp +* RESERVED2[3..2] - (RO) Reserved bits +* M0_AXI_RRESP_ERROR_RID[7..4] - (W1C) tx_pfet AXI rid +* M1_AXI_RRESP_ERROR_RRESP[9..8] - (W1C) pf_dfet_rx AXI rresp +* RESERVED10[11..10] - (RO) Reserved bits +* M1_AXI_RRESP_ERROR_RID[15..12] - (W1C) pf_dfet_rx AXI rid +* M2_AXI_RRESP_ERROR_RRESP[17..16] - (W1C) pf_dfet_tx AXI rresp +* RESERVED18[19..18] - (RO) Reserved bits +* M2_AXI_RRESP_ERROR_RID[23..20] - (W1C) pf_dfet_tx AXI rid +* M0_AXI_RRESP_ERROR[24] - (W1C) tx_pfet_tx AXI rresp_error +* M1_AXI_RRESP_ERROR[25] - (W1C) pf_dfet_rx AXI rresp_error +* M2_AXI_RRESP_ERROR[26] - (W1C) pf_dfet_tx AXI rresp_error +* RESERVED27[31..27] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M2_AXI_RRESP_ERROR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M2_AXI_RRESP_ERROR_MASK \ + 0x04000000 /* M2_AXI_RRESP_ERROR[26] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M2_AXI_RRESP_ERROR_SHFT 26 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M1_AXI_RRESP_ERROR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M1_AXI_RRESP_ERROR_MASK \ + 0x02000000 /* M1_AXI_RRESP_ERROR[25] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M1_AXI_RRESP_ERROR_SHFT 25 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M0_AXI_RRESP_ERROR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M0_AXI_RRESP_ERROR_MASK \ + 0x01000000 /* M0_AXI_RRESP_ERROR[24] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M0_AXI_RRESP_ERROR_SHFT 24 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M2_AXI_RRESP_ERROR_RID_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M2_AXI_RRESP_ERROR_RID_MASK \ + 0x00F00000 /* M2_AXI_RRESP_ERROR_RID[23..20] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M2_AXI_RRESP_ERROR_RID_SHFT 20 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M2_AXI_RRESP_ERROR_RRESP_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M2_AXI_RRESP_ERROR_RRESP_MASK \ + 0x00030000 /* M2_AXI_RRESP_ERROR_RRESP[17..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M2_AXI_RRESP_ERROR_RRESP_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M1_AXI_RRESP_ERROR_RID_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M1_AXI_RRESP_ERROR_RID_MASK \ + 0x0000F000 /* M1_AXI_RRESP_ERROR_RID[15..12] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M1_AXI_RRESP_ERROR_RID_SHFT 12 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M1_AXI_RRESP_ERROR_RRESP_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M1_AXI_RRESP_ERROR_RRESP_MASK \ + 0x00000300 /* M1_AXI_RRESP_ERROR_RRESP[9..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M1_AXI_RRESP_ERROR_RRESP_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M0_AXI_RRESP_ERROR_RID_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M0_AXI_RRESP_ERROR_RID_MASK \ + 0x000000F0 /* M0_AXI_RRESP_ERROR_RID[7..4] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M0_AXI_RRESP_ERROR_RID_SHFT 4 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M0_AXI_RRESP_ERROR_RRESP_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M0_AXI_RRESP_ERROR_RRESP_MASK \ + 0x00000003 /* M0_AXI_RRESP_ERROR_RRESP[1..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG0_M0_AXI_RRESP_ERROR_RRESP_SHFT 0 + +/* +* ---WPDMA_AXI_MST_DBG1 (0x7C024000 + 0x2BC)--- +* M0_AXI_BRESP_ERROR_BRESP[1..0] - (W1C) rx_pfet AXI bresp +* RESERVED2[3..2] - (RO) Reserved bits +* M0_AXI_BRESP_ERROR_RID[7..4] - (W1C) rx_pfet AXI bid +* M1_AXI_BRESP_ERROR_BRESP[9..8] - (W1C) wb_dfet_rx AXI bresp +* RESERVED10[11..10] - (RO) Reserved bits +* M1_AXI_BRESP_ERROR_RID[15..12] - (W1C) wb_dfet_rx AXI bid +* M2_AXI_BRESP_ERROR_BRESP[17..16] - (W1C) wb_dfet_tx AXI bresp +* RESERVED18[19..18] - (RO) Reserved bits +* M2_AXI_BRESP_ERROR_RID[23..20] - (W1C) wb_dfet_tx AXI bid +* M0_AXI_BRESP_ERROR[24] - (W1C) tx_pfet_tx AXI bresp_error +* M1_AXI_BRESP_ERROR[25] - (W1C) pf_dfet_rx AXI bresp_error +* M2_AXI_BRESP_ERROR[26] - (W1C) pf_dfet_tx AXI bresp_error +* RESERVED27[31..27] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M2_AXI_BRESP_ERROR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M2_AXI_BRESP_ERROR_MASK \ + 0x04000000 /* M2_AXI_BRESP_ERROR[26] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M2_AXI_BRESP_ERROR_SHFT 26 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M1_AXI_BRESP_ERROR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M1_AXI_BRESP_ERROR_MASK \ + 0x02000000 /* M1_AXI_BRESP_ERROR[25] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M1_AXI_BRESP_ERROR_SHFT 25 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M0_AXI_BRESP_ERROR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M0_AXI_BRESP_ERROR_MASK \ + 0x01000000 /* M0_AXI_BRESP_ERROR[24] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M0_AXI_BRESP_ERROR_SHFT 24 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M2_AXI_BRESP_ERROR_RID_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M2_AXI_BRESP_ERROR_RID_MASK \ + 0x00F00000 /* M2_AXI_BRESP_ERROR_RID[23..20] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M2_AXI_BRESP_ERROR_RID_SHFT 20 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M2_AXI_BRESP_ERROR_BRESP_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M2_AXI_BRESP_ERROR_BRESP_MASK \ + 0x00030000 /* M2_AXI_BRESP_ERROR_BRESP[17..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M2_AXI_BRESP_ERROR_BRESP_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M1_AXI_BRESP_ERROR_RID_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M1_AXI_BRESP_ERROR_RID_MASK \ + 0x0000F000 /* M1_AXI_BRESP_ERROR_RID[15..12] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M1_AXI_BRESP_ERROR_RID_SHFT 12 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M1_AXI_BRESP_ERROR_BRESP_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M1_AXI_BRESP_ERROR_BRESP_MASK \ + 0x00000300 /* M1_AXI_BRESP_ERROR_BRESP[9..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M1_AXI_BRESP_ERROR_BRESP_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M0_AXI_BRESP_ERROR_RID_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M0_AXI_BRESP_ERROR_RID_MASK \ + 0x000000F0 /* M0_AXI_BRESP_ERROR_RID[7..4] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M0_AXI_BRESP_ERROR_RID_SHFT 4 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M0_AXI_BRESP_ERROR_BRESP_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M0_AXI_BRESP_ERROR_BRESP_MASK \ + 0x00000003 /* M0_AXI_BRESP_ERROR_BRESP[1..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_DBG1_M0_AXI_BRESP_ERROR_BRESP_SHFT 0 + +/* +* ---WPDMA_TX_QOS_LMT_CFG0 (0x7C024000 + 0x2C0)--- +* CSR_TX_PLD_0_AXI_LIMITER_REQ[2..0] - (RW) QoS CR, Limiter Enable for packet +* traffice of type TX_PLD_0 +* CSR_TX_PLD_0_AXI_LIMITER_EN_REQ[3] - (RW) QoS CR, Limiter Enable for packet +* traffice of type TX_PLD_0 +* CSR_TX_PLD_0_AXI_LIMITER_PKT[6..4] - (RW) QoS CR, Limiter Enable for packet +* traffice of type TX_PLD_0 +* CSR_TX_PLD_0_AXI_LIMITER_EN_PKT[7] - (RW) QoS CR, Limiter Enable for packet +* traffice of type TX_PLD_0 +* CSR_TX_PLD_1_PLD_AXI_LIMITER_REQ[10..8] - (RW) QoS CR, Limiter Enable for +* request traffice of type TX_PLD_1_PLD +* CSR_TX_PLD_1_PLD_AXI_LIMITER_EN_REQ[11] - (RW) QoS CR, Limiter Enable for +* request traffice of type TX_PLD_1_PLD +* CSR_TX_PLD_1_PLD_AXI_LIMITER_PKT[14..12] - (RW) QoS CR, Limiter Enable for +* request traffice of type TX_PLD_1_PLD +* CSR_TX_PLD_1_PLD_AXI_LIMITER_EN_PKT[15] - (RW) QoS CR, Limiter Enable for +* request traffice of type TX_PLD_1_PLD +* CSR_RX_PLD_AXI_LIMITER_REQ[18..16] - (RW) QoS CR, Limiter Enable for request +* traffice of type RX_PLD +* CSR_RX_PLD_AXI_LIMITER_EN_REQ[19] - (RW) QoS CR, Limiter Enable for request +* traffice of type RX_PLD +* CSR_RX_PLD_AXI_LIMITER_PKT[22..20] - (RW) QoS CR, Limiter Enable for request +* traffice of type RX_PLD +* CSR_RX_PLD_AXI_LIMITER_EN_PKT[23] - (RW) QoS CR, Limiter Enable for request +* traffice of type RX_PLD +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_EN_PKT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_EN_PKT_MASK \ + 0x00800000 /* CSR_RX_PLD_AXI_LIMITER_EN_PKT[23] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_EN_PKT_SHFT \ + 23 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_PKT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_PKT_MASK \ + 0x00700000 /* CSR_RX_PLD_AXI_LIMITER_PKT[22..20] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_PKT_SHFT \ + 20 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_EN_REQ_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_EN_REQ_MASK \ + 0x00080000 /* CSR_RX_PLD_AXI_LIMITER_EN_REQ[19] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_EN_REQ_SHFT \ + 19 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_REQ_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_REQ_MASK \ + 0x00070000 /* CSR_RX_PLD_AXI_LIMITER_REQ[18..16] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_REQ_SHFT \ + 16 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_1_PLD_AXI_LIMITER_EN_PKT_AD\ +DR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_1_PLD_AXI_LIMITER_EN_PKT_MA\ +SK \ +0x00008000 /* CSR_TX_PLD_1_PLD_AXI_LIMITER_EN_PKT[15] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_1_PLD_AXI_LIMITER_EN_PKT_SH\ +FT \ +15 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_1_PLD_AXI_LIMITER_PKT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_1_PLD_AXI_LIMITER_PKT_MASK \ + 0x00007000 /* CSR_TX_PLD_1_PLD_AXI_LIMITER_PKT[14..12] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_1_PLD_AXI_LIMITER_PKT_SHFT \ + 12 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_1_PLD_AXI_LIMITER_EN_REQ_AD\ +DR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_1_PLD_AXI_LIMITER_EN_REQ_MA\ +SK \ +0x00000800 /* CSR_TX_PLD_1_PLD_AXI_LIMITER_EN_REQ[11] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_1_PLD_AXI_LIMITER_EN_REQ_SH\ +FT \ +11 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_1_PLD_AXI_LIMITER_REQ_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_1_PLD_AXI_LIMITER_REQ_MASK \ + 0x00000700 /* CSR_TX_PLD_1_PLD_AXI_LIMITER_REQ[10..8] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_1_PLD_AXI_LIMITER_REQ_SHFT \ + 8 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_0_AXI_LIMITER_EN_PKT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_0_AXI_LIMITER_EN_PKT_MASK \ + 0x00000080 /* CSR_TX_PLD_0_AXI_LIMITER_EN_PKT[7] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_0_AXI_LIMITER_EN_PKT_SHFT \ + 7 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_0_AXI_LIMITER_PKT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_0_AXI_LIMITER_PKT_MASK \ + 0x00000070 /* CSR_TX_PLD_0_AXI_LIMITER_PKT[6..4] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_0_AXI_LIMITER_PKT_SHFT \ + 4 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_0_AXI_LIMITER_EN_REQ_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_0_AXI_LIMITER_EN_REQ_MASK \ + 0x00000008 /* CSR_TX_PLD_0_AXI_LIMITER_EN_REQ[3] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_0_AXI_LIMITER_EN_REQ_SHFT \ + 3 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_0_AXI_LIMITER_REQ_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_0_AXI_LIMITER_REQ_MASK \ + 0x00000007 /* CSR_TX_PLD_0_AXI_LIMITER_REQ[2..0] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_0_AXI_LIMITER_REQ_SHFT \ + 0 + +/* +* ---WPDMA_TX_QOS_LMT_CFG1 (0x7C024000 + 0x2C4)--- +* CSR_AUX_TX_PLD_0_AXI_LIMITER_REQ[2..0] - (RW) QoS CR, Limiter value selected +* by PP dynamically +* RESERVED3[3] - (RO) Reserved bits +* CSR_AUX_TX_PLD_0_AXI_LIMITER_PKT[6..4] - (RW) QoS CR, Limiter value selected +* by PP dynamically +* RESERVED7[7] - (RO) Reserved bits +* CSR_AUX_TX_PLD_1_AXI_LIMITER_REQ[10..8] - (RW) QoS CR, Limiter value selected +* by PP dynamically +* RESERVED11[11] - (RO) Reserved bits +* CSR_AUX_TX_PLD_1_AXI_LIMITER_PKT[14..12] - (RW) QoS CR, Limiter value selected +* by PP dynamically +* RESERVED15[15] - (RO) Reserved bits +* CSR_AUX_RX_PLD_AXI_LIMITER_REQ[18..16] - (RW) QoS CR, Limiter value selected +* by PP dynamically +* RESERVED19[19] - (RO) Reserved bits +* CSR_AUX_RX_PLD_AXI_LIMITER_PKT[22..20] - (RW) QoS CR, Limiter value selected +* by PP dynamically +* RESERVED23[31..23] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_RX_PLD_AXI_LIMITER_PKT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_RX_PLD_AXI_LIMITER_PKT_MASK \ + 0x00700000 /* CSR_AUX_RX_PLD_AXI_LIMITER_PKT[22..20] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_RX_PLD_AXI_LIMITER_PKT_SHFT \ + 20 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_RX_PLD_AXI_LIMITER_REQ_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_RX_PLD_AXI_LIMITER_REQ_MASK \ + 0x00070000 /* CSR_AUX_RX_PLD_AXI_LIMITER_REQ[18..16] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_RX_PLD_AXI_LIMITER_REQ_SHFT \ + 16 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_1_AXI_LIMITER_PKT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_1_AXI_LIMITER_PKT_MASK \ + 0x00007000 /* CSR_AUX_TX_PLD_1_AXI_LIMITER_PKT[14..12] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_1_AXI_LIMITER_PKT_SHFT \ + 12 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_1_AXI_LIMITER_REQ_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_1_AXI_LIMITER_REQ_MASK \ + 0x00000700 /* CSR_AUX_TX_PLD_1_AXI_LIMITER_REQ[10..8] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_1_AXI_LIMITER_REQ_SHFT \ + 8 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_0_AXI_LIMITER_PKT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_0_AXI_LIMITER_PKT_MASK \ + 0x00000070 /* CSR_AUX_TX_PLD_0_AXI_LIMITER_PKT[6..4] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_0_AXI_LIMITER_PKT_SHFT \ + 4 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_0_AXI_LIMITER_REQ_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_0_AXI_LIMITER_REQ_MASK \ + 0x00000007 /* CSR_AUX_TX_PLD_0_AXI_LIMITER_REQ[2..0] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_0_AXI_LIMITER_REQ_SHFT \ + 0 + +/* +* ---WPDMA_TX_QOS_LMT_CFG2 (0x7C024000 + 0x2C8)--- +* CSR_RX_RD_DMAD_AXI_LIMITER_REQ[2..0] - (RW) QoS CR, Limiter Value for packet +* traffice of type RX_RD_DMAD +* CSR_RX_RD_DMAD_AXI_LIMITER_EN_REQ[3] - (RW) QoS CR, Limiter Enable for request +* traffice of type RX_RD_DMAD +* CSR_RX_RD_DMAD_AXI_LIMITER_PKT[6..4] - (RW) QoS CR, Limiter Value for packet +* traffice of type RX_RD_DMAD +* CSR_RX_RD_DMAD_AXI_LIMITER_EN_PKT[7] - (RW) QoS CR, Limiter Enable for packet +* traffice of type RX_RD_DMAD +* CSR_RX_WR_DMAD_AXI_LIMITER_REQ[10..8] - (RW) QoS CR, Limiter Value for packet +* traffice of type RX_WR_DMAD +* CSR_RX_WR_DMAD_AXI_LIMITER_EN_REQ[11] - (RW) QoS CR, Limiter Enable for +* request traffice of type RX_WR_DMAD +* CSR_RX_WR_DMAD_AXI_LIMITER_PKT[14..12] - (RW) QoS CR, Limiter Value for packet +* traffice of type RX_WR_DMAD +* CSR_RX_WR_DMAD_AXI_LIMITER_EN_PKT[15] - (RW) QoS CR, Limiter Enable for packet +* traffice of type RX_WR_DMAD +* CSR_TX_RD_DMAD_AXI_LIMITER_REQ[18..16] - (RW) QoS CR, Limiter Value for packet +* traffice of type TX_RD_DMAD +* CSR_TX_RD_DMAD_AXI_LIMITER_EN_REQ[19] - (RW) QoS CR, Limiter Enable for +* request traffice of type TX_RD_DMAD +* CSR_TX_RD_DMAD_AXI_LIMITER_PKT[22..20] - (RW) QoS CR, Limiter Value for packet +* traffice of type TX_RD_DMAD +* CSR_TX_RD_DMAD_AXI_LIMITER_EN_PKT[23] - (RW) QoS CR, Limiter Enable for packet +* traffice of type TX_RD_DMAD +* CSR_TX_WR_DMAD_AXI_LIMITER_REQ[26..24] - (RW) QoS CR, Limiter Value for packet +* traffice of type TX_WR_DMAD +* CSR_TX_WR_DMAD_AXI_LIMITER_EN_REQ[27] - (RW) QoS CR, Limiter Enable for +* request traffice of type TX_WR_DMAD +* CSR_TX_WR_DMAD_AXI_LIMITER_PKT[30..28] - (RW) QoS CR, Limiter Value for packet +* traffice of type TX_WR_DMAD +* CSR_TX_WR_DMAD_AXI_LIMITER_EN_PKT[31] - (RW) QoS CR, Limiter Enable for packet +* traffice of type TX_WR_DMAD +*/ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_EN_PKT_ADDR\ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_EN_PKT_MASK\ +0x80000000 /* CSR_TX_WR_DMAD_AXI_LIMITER_EN_PKT[31] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_EN_PKT_SHFT\ +31 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_PKT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_PKT_MASK \ + 0x70000000 /* CSR_TX_WR_DMAD_AXI_LIMITER_PKT[30..28] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_PKT_SHFT \ + 28 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_EN_REQ_ADDR\ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_EN_REQ_MASK\ +0x08000000 /* CSR_TX_WR_DMAD_AXI_LIMITER_EN_REQ[27] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_EN_REQ_SHFT\ +27 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_REQ_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_REQ_MASK \ + 0x07000000 /* CSR_TX_WR_DMAD_AXI_LIMITER_REQ[26..24] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_REQ_SHFT \ + 24 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_EN_PKT_ADDR\ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_EN_PKT_MASK\ +0x00800000 /* CSR_TX_RD_DMAD_AXI_LIMITER_EN_PKT[23] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_EN_PKT_SHFT\ +23 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_PKT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_PKT_MASK \ + 0x00700000 /* CSR_TX_RD_DMAD_AXI_LIMITER_PKT[22..20] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_PKT_SHFT \ + 20 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_EN_REQ_ADDR\ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_EN_REQ_MASK\ +0x00080000 /* CSR_TX_RD_DMAD_AXI_LIMITER_EN_REQ[19] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_EN_REQ_SHFT\ +19 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_REQ_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_REQ_MASK \ + 0x00070000 /* CSR_TX_RD_DMAD_AXI_LIMITER_REQ[18..16] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_REQ_SHFT \ + 16 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_EN_PKT_ADDR\ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_EN_PKT_MASK\ +0x00008000 /* CSR_RX_WR_DMAD_AXI_LIMITER_EN_PKT[15] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_EN_PKT_SHFT\ +15 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_PKT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_PKT_MASK \ + 0x00007000 /* CSR_RX_WR_DMAD_AXI_LIMITER_PKT[14..12] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_PKT_SHFT \ + 12 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_EN_REQ_ADDR\ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_EN_REQ_MASK\ +0x00000800 /* CSR_RX_WR_DMAD_AXI_LIMITER_EN_REQ[11] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_EN_REQ_SHFT\ +11 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_REQ_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_REQ_MASK \ + 0x00000700 /* CSR_RX_WR_DMAD_AXI_LIMITER_REQ[10..8] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_REQ_SHFT \ + 8 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_EN_PKT_ADDR\ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_EN_PKT_MASK\ +0x00000080 /* CSR_RX_RD_DMAD_AXI_LIMITER_EN_PKT[7] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_EN_PKT_SHFT\ +7 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_PKT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_PKT_MASK \ + 0x00000070 /* CSR_RX_RD_DMAD_AXI_LIMITER_PKT[6..4] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_PKT_SHFT \ + 4 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_EN_REQ_ADDR\ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_EN_REQ_MASK\ +0x00000008 /* CSR_RX_RD_DMAD_AXI_LIMITER_EN_REQ[3] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_EN_REQ_SHFT\ +3 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_REQ_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_REQ_MASK \ + 0x00000007 /* CSR_RX_RD_DMAD_AXI_LIMITER_REQ[2..0] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_REQ_SHFT \ + 0 + +/* +* ---WPDMA_TX_QOS_LMT_CFG3 (0x7C024000 + 0x2CC)--- +* CSR_AUX_RX_RD_DMAD_AXI_LIMITER_REQ[2..0] - (RW) QoS CR, Limiter value selected +* by PP dynamically +* RESERVED3[3] - (RO) Reserved bits +* CSR_AUX_RX_RD_DMAD_AXI_LIMITER_PKT[6..4] - (RW) QoS CR, Limiter value selected +* by PP dynamically +* RESERVED7[7] - (RO) Reserved bits +* CSR_AUX_RX_WR_DMAD_AXI_LIMITER_REQ[10..8] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED11[11] - (RO) Reserved bits +* CSR_AUX_RX_WR_DMAD_AXI_LIMITER_PKT[14..12] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED15[15] - (RO) Reserved bits +* CSR_AUX_TX_RD_DMAD_AXI_LIMITER_REQ[18..16] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED19[19] - (RO) Reserved bits +* CSR_AUX_TX_RD_DMAD_AXI_LIMITER_PKT[22..20] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED23[23] - (RO) Reserved bits +* CSR_AUX_TX_WR_DMAD_AXI_LIMITER_REQ[26..24] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED27[27] - (RO) Reserved bits +* CSR_AUX_TX_WR_DMAD_AXI_LIMITER_PKT[30..28] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED31[31] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_WR_DMAD_AXI_LIMITER_PKT_ADD\ +R \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_WR_DMAD_AXI_LIMITER_PKT_MAS\ +K \ +0x70000000 /* CSR_AUX_TX_WR_DMAD_AXI_LIMITER_PKT[30..28] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_WR_DMAD_AXI_LIMITER_PKT_SHF\ +T \ +28 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_WR_DMAD_AXI_LIMITER_REQ_ADD\ +R \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_WR_DMAD_AXI_LIMITER_REQ_MAS\ +K \ +0x07000000 /* CSR_AUX_TX_WR_DMAD_AXI_LIMITER_REQ[26..24] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_WR_DMAD_AXI_LIMITER_REQ_SHF\ +T \ +24 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_RD_DMAD_AXI_LIMITER_PKT_ADD\ +R \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_RD_DMAD_AXI_LIMITER_PKT_MAS\ +K \ +0x00700000 /* CSR_AUX_TX_RD_DMAD_AXI_LIMITER_PKT[22..20] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_RD_DMAD_AXI_LIMITER_PKT_SHF\ +T \ +20 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_RD_DMAD_AXI_LIMITER_REQ_ADD\ +R \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_RD_DMAD_AXI_LIMITER_REQ_MAS\ +K \ +0x00070000 /* CSR_AUX_TX_RD_DMAD_AXI_LIMITER_REQ[18..16] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_RD_DMAD_AXI_LIMITER_REQ_SHF\ +T \ +16 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_WR_DMAD_AXI_LIMITER_PKT_ADD\ +R \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_WR_DMAD_AXI_LIMITER_PKT_MAS\ +K \ +0x00007000 /* CSR_AUX_RX_WR_DMAD_AXI_LIMITER_PKT[14..12] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_WR_DMAD_AXI_LIMITER_PKT_SHF\ +T \ +12 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_WR_DMAD_AXI_LIMITER_REQ_ADD\ +R \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_WR_DMAD_AXI_LIMITER_REQ_MAS\ +K \ +0x00000700 /* CSR_AUX_RX_WR_DMAD_AXI_LIMITER_REQ[10..8] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_WR_DMAD_AXI_LIMITER_REQ_SHF\ +T \ +8 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_RD_DMAD_AXI_LIMITER_PKT_ADD\ +R \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_RD_DMAD_AXI_LIMITER_PKT_MAS\ +K \ +0x00000070 /* CSR_AUX_RX_RD_DMAD_AXI_LIMITER_PKT[6..4] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_RD_DMAD_AXI_LIMITER_PKT_SHF\ +T \ +4 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_RD_DMAD_AXI_LIMITER_REQ_ADD\ +R \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_RD_DMAD_AXI_LIMITER_REQ_MAS\ +K \ +0x00000007 /* CSR_AUX_RX_RD_DMAD_AXI_LIMITER_REQ[2..0] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_RD_DMAD_AXI_LIMITER_REQ_SHF\ +T \ +0 + +/* +* ---WPDMA_TX_QOS_QTM_CFG0 (0x7C024000 + 0x2D0)--- +* CSR_TXP0_FFA_QTM[3..0] - (RW) CSR_TXP0_FFA_QTM +* CSR_TXP0_RSVD_QTM[7..4] - (RW) CSR_TXP0_RSVD_QTM +* CSR_TXP1_FFA_QTM[11..8] - (RW) CSR_TXP1_FFA_QTM +* CSR_TXP1_RSVD_QTM[15..12] - (RW) CSR_TXP1_RSVD_QTM +* RESERVED16[23..16] - (RO) Reserved bits +* CSR_FFA_TOTAL_QTM[27..24] - (RW) CSR_FFA_TOTAL_QTM +* CSR_QOS_QTM_MODE[29..28] - (RW) 2'b01 : csr_rsvd_qtm_mode_only, 2'b10 : +* csr_ffa_qtm_mode_only, others : rsvd+ffa mode +* RESERVED30[31..30] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_QOS_QTM_MODE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_QOS_QTM_MODE_MASK \ + 0x30000000 /* CSR_QOS_QTM_MODE[29..28] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_QOS_QTM_MODE_SHFT 28 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_FFA_TOTAL_QTM_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_FFA_TOTAL_QTM_MASK \ + 0x0F000000 /* CSR_FFA_TOTAL_QTM[27..24] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_FFA_TOTAL_QTM_SHFT 24 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP1_RSVD_QTM_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP1_RSVD_QTM_MASK \ + 0x0000F000 /* CSR_TXP1_RSVD_QTM[15..12] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP1_RSVD_QTM_SHFT 12 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP1_FFA_QTM_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP1_FFA_QTM_MASK \ + 0x00000F00 /* CSR_TXP1_FFA_QTM[11..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP1_FFA_QTM_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP0_RSVD_QTM_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP0_RSVD_QTM_MASK \ + 0x000000F0 /* CSR_TXP0_RSVD_QTM[7..4] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP0_RSVD_QTM_SHFT 4 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP0_FFA_QTM_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP0_FFA_QTM_MASK \ + 0x0000000F /* CSR_TXP0_FFA_QTM[3..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP0_FFA_QTM_SHFT 0 + +/* +* ---WPDMA_TX_QOS_QTM_CFG1 (0x7C024000 + 0x2D4)--- +* CSR_DMAD_FFA_QTM[3..0] - (RW) CSR_DMAD_FFA_QTM +* CSR_DMAD_RSVD_QTM[7..4] - (RW) CSR_DMAD_RSVD_QTM +* CSR_TXD_FFA_QTM[11..8] - (RW) CSR_TXD_FFA_QTM +* CSR_TXD_RSVD_QTM[15..12] - (RW) CSR_TXD_RSVD_QTM +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_TXD_RSVD_QTM_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_TXD_RSVD_QTM_MASK \ + 0x0000F000 /* CSR_TXD_RSVD_QTM[15..12] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_TXD_RSVD_QTM_SHFT 12 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_TXD_FFA_QTM_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_TXD_FFA_QTM_MASK \ + 0x00000F00 /* CSR_TXD_FFA_QTM[11..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_TXD_FFA_QTM_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_DMAD_RSVD_QTM_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_DMAD_RSVD_QTM_MASK \ + 0x000000F0 /* CSR_DMAD_RSVD_QTM[7..4] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_DMAD_RSVD_QTM_SHFT 4 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_DMAD_FFA_QTM_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_DMAD_FFA_QTM_MASK \ + 0x0000000F /* CSR_DMAD_FFA_QTM[3..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_DMAD_FFA_QTM_SHFT 0 + +/* +* ---HOST_PRI_INT_STA (0x7C024000 + 0x2E0)--- +* host_pri_int_sts_0[0] - (W1C) rx_done_int[0], configuration interrupt please +* refer to 0x2E0 WPDMA_PRI_DLY_INT_CFG0[15:0] +* host_pri_int_sts_1[1] - (W1C) rx_done_int[1], configuration interrupt please +* refer to 0x2E0 WPDMA_PRI_DLY_INT_CFG0[31:16] +* RESERVED2[31..2] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_1_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_1_MASK \ + 0x00000002 /* host_pri_int_sts_1[1] */ +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_0_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_0_MASK \ + 0x00000001 /* host_pri_int_sts_0[0] */ +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_0_SHFT 0 + +/* +* ---HOST_PER_INT_ENA_STA (0x7C024000 + 0x2E4)--- +* wpdma_per_int_sts[3..0] - (W1C) status bit for rx ring periodic delayed +* interrupt to tracking ring is full or not, start delayed interrupt timer when +* RX ring is not full from falling edge of full flag and reset when ring full +* flag is asserted +* RESERVED4[15..4] - (RO) Reserved bits +* wpdma_per_int_ena[19..16] - (RW) enable bit for rx ring periodic delayed +* interrupt to tracking ring is full or not, start delayed interrupt timer when +* RX ring is not full from falling edge of full flag and reset when ring full +* flag is asserted +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_wpdma_per_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_wpdma_per_int_ena_MASK \ + 0x000F0000 /* wpdma_per_int_ena[19..16] */ +#define WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_wpdma_per_int_ena_SHFT 16 +#define WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_wpdma_per_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_wpdma_per_int_sts_MASK \ + 0x0000000F /* wpdma_per_int_sts[3..0] */ +#define WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_wpdma_per_int_sts_SHFT 0 + +/* +* ---HOST_PER_DLY_INT_CFG (0x7C024000 + 0x2E8)--- +* wpdma_per_max_ptime[7..0] - (RW) Specified Max pending time for the internal +* RX ring full flag falling edge. When the pending time equal or greater +* PER_MAX_PTIME x 20us or the # of pended TX_DONE_INT equal or greater than +* TX_MAX_PINT (see above), an Final TX_DLY_INT is generated +* Set to 0 will disable pending interrupt time check +* wpdma_per_dly_int_en[11..8] - (RW) RX periodic Delayed Interrupt Enable +* 1: Enable RX periodic delayed interrupt mechanism +* 0: Disable RX periodic delayed interrupt mechanism +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_wpdma_per_dly_int_en_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_wpdma_per_dly_int_en_MASK \ + 0x00000F00 /* wpdma_per_dly_int_en[11..8] */ +#define WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_wpdma_per_dly_int_en_SHFT 8 +#define WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_wpdma_per_max_ptime_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_wpdma_per_max_ptime_MASK \ + 0x000000FF /* wpdma_per_max_ptime[7..0] */ +#define WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_wpdma_per_max_ptime_SHFT 0 + +/* +* ---WPDMA_PRI_DLY_INT_CFG0 (0x7C024000 + 0x2F0)--- +* PRI0_MAX_PTIME[7..0] - (RW) Specified Max pending time for the internal +* PRI0_DONE_INT. When the pending time equal or greater PRI0_MAX_PTIME x 20us or +* the # of pended PRI0_DONE_INT equal or greater than PRI0_MAX_PINT (see above), +* an Final PRI0_DLY_INT is generated +* Set to 0 will disable pending interrupt time check +* PRI0_MAX_PINT[14..8] - (RW) Specified Max # of pended interrupts. +* When the # of pended interrupts equal or greater than the value specified here +* or interrupt pending time reach the limit (See below), a Final PRI0_DLY_INT is +generated. +* Set to 0 will disable pending interrupt count check +* PRI0_DLY_INT_EN[15] - (RW) Priority Delayed Interrupt Enable +* 1: Enable Priority delayed interrupt mechanism +* 0: Disable Priority delayed interrupt mechanism +* In AXE host_dma0, these PRI1_* settings are for rx_ring[1]_int, and PRI0_* +* settings are for rx_ring[0]_int +* In AXE host_dma1, these PRI1_* settings are for rx_ring[0]_int, and PRI0_* +* settings are for Ored-tx_ring[14:0]_int +* In AXE mcu_dma0 and mcu_dma1, there are no priority interrupt thus no this +* 0x2E0 CR!! +* PRI1_MAX_PTIME[23..16] - (RW) Specified Max pending time for the internal +* PRI1_DONE_INT. When the pending time equal or greater PRI1_MAX_PTIME x 20us or +* the # of pended PRI1_DONE_INT equal or greater than PRI1_MAX_PINT (see above), +* an Final PRI1_DLY_INT is generated +* Set to 0 will disable pending interrupt time check +* PRI1_MAX_PINT[30..24] - (RW) Specified Max # of pended interrupts. +* When the # of pended interrupts equal or greater than the value specified here +* or interrupt pending time reach the limit (See below), a Final PRI1_DLY_INT is +generated. +* Set to 0 will disable pending interrupt count check +* PRI1_DLY_INT_EN[31] - (RW) Priority Delayed Interrupt Enable +* 1: Enable Priority delayed interrupt mechanism +* 0: Disable Priority delayed interrupt mechanism +* In AXE host_dma0, these PRI1_* settings are for rx_ring[1]_int, and PRI0_* +* settings are for rx_ring[0]_int +* In AXE host_dma1, these PRI1_* settings are for rx_ring[0]_int, and PRI0_* +* settings are for Ored-tx_ring[14:0]_int +* In AXE mcu_dma0 and mcu_dma1, there are no priority interrupt thus no this +* 0x2E0 CR!! +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_DLY_INT_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_DLY_INT_EN_MASK \ + 0x80000000 /* PRI1_DLY_INT_EN[31] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_DLY_INT_EN_SHFT 31 +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PINT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PINT_MASK \ + 0x7F000000 /* PRI1_MAX_PINT[30..24] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PINT_SHFT 24 +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PTIME_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PTIME_MASK \ + 0x00FF0000 /* PRI1_MAX_PTIME[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PTIME_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_DLY_INT_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_DLY_INT_EN_MASK \ + 0x00008000 /* PRI0_DLY_INT_EN[15] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_DLY_INT_EN_SHFT 15 +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PINT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PINT_MASK \ + 0x00007F00 /* PRI0_MAX_PINT[14..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PINT_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PTIME_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PTIME_MASK \ + 0x000000FF /* PRI0_MAX_PTIME[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PTIME_SHFT 0 + +/* +* ---WPDMA_TX_RING0_CTRL0 (0x7C024000 + 0x300)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring0 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING0_CTRL1 (0x7C024000 + 0x304)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring0. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring0 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING0_CTRL2 (0x7C024000 + 0x308)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING0_CTRL3 (0x7C024000 + 0x30c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING1_CTRL0 (0x7C024000 + 0x310)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring1 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING1_CTRL1 (0x7C024000 + 0x314)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring1. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring1 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING1_CTRL2 (0x7C024000 + 0x318)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING1_CTRL3 (0x7C024000 + 0x31c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING2_CTRL0 (0x7C024000 + 0x320)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring2 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING2_CTRL1 (0x7C024000 + 0x324)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring2. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring2 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING2_CTRL2 (0x7C024000 + 0x328)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING2_CTRL3 (0x7C024000 + 0x32c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING3_CTRL0 (0x7C024000 + 0x330)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring3 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING3_CTRL1 (0x7C024000 + 0x334)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring3. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring3 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING3_CTRL2 (0x7C024000 + 0x338)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING3_CTRL3 (0x7C024000 + 0x33c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING0_CTRL0 (0x7C024000 + 0x500)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #0 (GE ports). It +* should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING0_CTRL1 (0x7C024000 + 0x504)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD Ring #0. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring0 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING0_CTRL2 (0x7C024000 + 0x508)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to allocate to RXD Ring +#0. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING0_CTRL3 (0x7C024000 + 0x50c)--- +* DMA_IDX[11..0] - (RW) In normal operation, user dma_index would udated by +* hardware when moving rx packet done. User should not write dma_index. +* Point to the next RXD DMA wants to use in FDS Ring#0. It should be a 8-DWORD +* aligned address. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING1_CTRL0 (0x7C024000 + 0x510)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #1 (GE ports). It +* should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING1_CTRL1 (0x7C024000 + 0x514)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD Ring #1. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring1 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING1_CTRL2 (0x7C024000 + 0x518)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to allocate to RXD Ring +#1. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING1_CTRL3 (0x7C024000 + 0x51c)--- +* DMA_IDX[11..0] - (RW) In normal operation, user dma_index would udated by +* hardware when moving rx packet done. User should not write dma_index. +* Point to the next RXD DMA wants to use in FDS Ring#1. It should be a 8-DWORD +* aligned address. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING2_CTRL0 (0x7C024000 + 0x520)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #2 (GE ports). It +* should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING2_CTRL1 (0x7C024000 + 0x524)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD Ring #2. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring2 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING2_CTRL2 (0x7C024000 + 0x528)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to allocate to RXD Ring +#2. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING2_CTRL3 (0x7C024000 + 0x52C)--- +* DMA_IDX[11..0] - (RW) In normal operation, user dma_index would udated by +* hardware when moving rx packet done. User should not write dma_index. +* Point to the next RXD DMA wants to use in FDS Ring#2. It should be a 8-DWORD +* aligned address. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING3_CTRL0 (0x7C024000 + 0x530)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #3 (GE ports). It +* should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING3_CTRL1 (0x7C024000 + 0x534)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD Ring #3. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring3 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING3_CTRL2 (0x7C024000 + 0x538)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to allocate to RXD Ring +#3. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING3_CTRL3 (0x7C024000 + 0x53C)--- +* DMA_IDX[11..0] - (RW) In normal operation, user dma_index would udated by +* hardware when moving rx packet done. User should not write dma_index. +* Point to the next RXD DMA wants to use in FDS Ring#3. It should be a 8-DWORD +* aligned address. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING0_EXT_CTRL (0x7C024000 + 0x600)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #0 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING1_EXT_CTRL (0x7C024000 + 0x604)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #1 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING2_EXT_CTRL (0x7C024000 + 0x608)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #2 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING3_EXT_CTRL (0x7C024000 + 0x60C)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #3 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING0_EXT_CTRL (0x7C024000 + 0x680)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #0 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING1_EXT_CTRL (0x7C024000 + 0x684)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #1 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING2_EXT_CTRL (0x7C024000 + 0x688)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #2 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING3_EXT_CTRL (0x7C024000 + 0x68C)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #3 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_PERF_CFG (0x7C024000 + 0x900)--- +* AXI_MTR_PERF_SEL_W_CH[2..0] - (RW) csr_axi_mtr_perf_sel_w_ch +* AXI_MTR_BW_W_RST[3] - (RW) csr_axi_mtr_bw_w_rst +* AXI_MTR_LAT_W_RST[4] - (RW) csr_axi_mtr_lat_w_rst +* RESERVED5[7..5] - (RO) Reserved bits +* AXI_MTR_PERF_SEL_R_CH[10..8] - (RW) csr_axi_mtr_perf_sel_r_ch +* AXI_MTR_BW_R_RST[11] - (RW) csr_axi_mtr_bw_r_rst +* AXI_MTR_LAT_R_RST[12] - (RW) csr_axi_mtr_lat_r_rst +* RESERVED13[30..13] - (RO) Reserved bits +* AXI_MTR_ENABLE[31] - (RW) csr_axi_mtr_enable +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_ENABLE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_ENABLE_MASK \ + 0x80000000 /* AXI_MTR_ENABLE[31] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_ENABLE_SHFT 31 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_LAT_R_RST_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_LAT_R_RST_MASK \ + 0x00001000 /* AXI_MTR_LAT_R_RST[12] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_LAT_R_RST_SHFT 12 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_BW_R_RST_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_BW_R_RST_MASK \ + 0x00000800 /* AXI_MTR_BW_R_RST[11] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_BW_R_RST_SHFT 11 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_PERF_SEL_R_CH_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_PERF_SEL_R_CH_MASK \ + 0x00000700 /* AXI_MTR_PERF_SEL_R_CH[10..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_PERF_SEL_R_CH_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_LAT_W_RST_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_LAT_W_RST_MASK \ + 0x00000010 /* AXI_MTR_LAT_W_RST[4] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_LAT_W_RST_SHFT 4 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_BW_W_RST_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_BW_W_RST_MASK \ + 0x00000008 /* AXI_MTR_BW_W_RST[3] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_BW_W_RST_SHFT 3 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_PERF_SEL_W_CH_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_PERF_SEL_W_CH_MASK \ + 0x00000007 /* AXI_MTR_PERF_SEL_W_CH[2..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_PERF_SEL_W_CH_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_DBG_CFG (0x7C024000 + 0x904)--- +* AXI_MST_DBG_CH_SEL[2..0] - (RW) csr_axi_mst_dbg_ch_sel[2:0] +* RESERVED3[7..3] - (RO) Reserved bits +* MASTER0_AXI_AW_CH_COUNTER_SET[8] - (RW) master0 axi_aw_ch_counter_set +* MASTER0_AXI_W_CH_COUNTER_SET[9] - (RW) master0 axi_w_ch_counter_set +* MASTER0_AXI_B_CH_COUNTER_SET[10] - (RW) master0 axi_b_ch_counter_set +* MASTER0_AXI_AR_CH_COUNTER_SET[11] - (RW) master0 axi_ar_ch_counter_set +* MASTER0_AXI_R_CH_COUNTER_SET[12] - (RW) master0 axi_r_ch_counter_set +* MASTER1_AXI_AW_CH_COUNTER_SET[13] - (RW) master1 axi_aw_ch_counter_set +* MASTER1_AXI_W_CH_COUNTER_SET[14] - (RW) master1 axi_w_ch_counter_set +* MASTER1_AXI_B_CH_COUNTER_SET[15] - (RW) master1 axi_b_ch_counter_set +* MASTER1_AXI_AR_CH_COUNTER_SET[16] - (RW) master1 axi_ar_ch_counter_set +* MASTER1_AXI_R_CH_COUNTER_SET[17] - (RW) master1 axi_r_ch_counter_set +* MASTER2_AXI_AW_CH_COUNTER_SET[18] - (RW) master2 axi_aw_ch_counter_set +* MASTER2_AXI_W_CH_COUNTER_SET[19] - (RW) master2 axi_w_ch_counter_set +* MASTER2_AXI_B_CH_COUNTER_SET[20] - (RW) master2 axi_b_ch_counter_set +* MASTER2_AXI_AR_CH_COUNTER_SET[21] - (RW) master2 axi_ar_ch_counter_set +* MASTER2_AXI_R_CH_COUNTER_SET[22] - (RW) master2 axi_r_ch_counter_set +* RESERVED23[31..23] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_R_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_R_CH_COUNTER_SET_MASK \ + 0x00400000 /* MASTER2_AXI_R_CH_COUNTER_SET[22] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_R_CH_COUNTER_SET_SHFT \ + 22 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_AR_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_AR_CH_COUNTER_SET_MASK \ + 0x00200000 /* MASTER2_AXI_AR_CH_COUNTER_SET[21] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_AR_CH_COUNTER_SET_SHFT \ + 21 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_B_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_B_CH_COUNTER_SET_MASK \ + 0x00100000 /* MASTER2_AXI_B_CH_COUNTER_SET[20] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_B_CH_COUNTER_SET_SHFT \ + 20 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_W_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_W_CH_COUNTER_SET_MASK \ + 0x00080000 /* MASTER2_AXI_W_CH_COUNTER_SET[19] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_W_CH_COUNTER_SET_SHFT \ + 19 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_AW_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_AW_CH_COUNTER_SET_MASK \ + 0x00040000 /* MASTER2_AXI_AW_CH_COUNTER_SET[18] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_AW_CH_COUNTER_SET_SHFT \ + 18 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_R_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_R_CH_COUNTER_SET_MASK \ + 0x00020000 /* MASTER1_AXI_R_CH_COUNTER_SET[17] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_R_CH_COUNTER_SET_SHFT \ + 17 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_AR_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_AR_CH_COUNTER_SET_MASK \ + 0x00010000 /* MASTER1_AXI_AR_CH_COUNTER_SET[16] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_AR_CH_COUNTER_SET_SHFT \ + 16 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_B_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_B_CH_COUNTER_SET_MASK \ + 0x00008000 /* MASTER1_AXI_B_CH_COUNTER_SET[15] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_B_CH_COUNTER_SET_SHFT \ + 15 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_W_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_W_CH_COUNTER_SET_MASK \ + 0x00004000 /* MASTER1_AXI_W_CH_COUNTER_SET[14] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_W_CH_COUNTER_SET_SHFT \ + 14 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_AW_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_AW_CH_COUNTER_SET_MASK \ + 0x00002000 /* MASTER1_AXI_AW_CH_COUNTER_SET[13] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_AW_CH_COUNTER_SET_SHFT \ + 13 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_R_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_R_CH_COUNTER_SET_MASK \ + 0x00001000 /* MASTER0_AXI_R_CH_COUNTER_SET[12] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_R_CH_COUNTER_SET_SHFT \ + 12 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_AR_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_AR_CH_COUNTER_SET_MASK \ + 0x00000800 /* MASTER0_AXI_AR_CH_COUNTER_SET[11] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_AR_CH_COUNTER_SET_SHFT \ + 11 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_B_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_B_CH_COUNTER_SET_MASK \ + 0x00000400 /* MASTER0_AXI_B_CH_COUNTER_SET[10] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_B_CH_COUNTER_SET_SHFT \ + 10 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_W_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_W_CH_COUNTER_SET_MASK \ + 0x00000200 /* MASTER0_AXI_W_CH_COUNTER_SET[9] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_W_CH_COUNTER_SET_SHFT \ + 9 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_AW_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_AW_CH_COUNTER_SET_MASK \ + 0x00000100 /* MASTER0_AXI_AW_CH_COUNTER_SET[8] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_AW_CH_COUNTER_SET_SHFT \ + 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_AXI_MST_DBG_CH_SEL_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_AXI_MST_DBG_CH_SEL_MASK \ + 0x00000007 /* AXI_MST_DBG_CH_SEL[2..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_CFG_AXI_MST_DBG_CH_SEL_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_PERF_W_STA0 (0x7C024000 + 0x910)--- +* WR_REQ_AVG_LAT[9..0] - (RO) req_avg_lat[9:0](long-term average) +* WR_REQ_PEAK_LAT[19..10] - (RO) req_peak_lat[9:0] +* WR_REQ_LAT[29..20] - (RO) req_lat[9:0](shot-term average) +* RESERVED[31..30] - (RO) tied constant +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA0_WR_REQ_LAT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA0_WR_REQ_LAT_MASK \ + 0x3FF00000 /* WR_REQ_LAT[29..20] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA0_WR_REQ_LAT_SHFT 20 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA0_WR_REQ_PEAK_LAT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA0_WR_REQ_PEAK_LAT_MASK \ + 0x000FFC00 /* WR_REQ_PEAK_LAT[19..10] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA0_WR_REQ_PEAK_LAT_SHFT 10 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA0_WR_REQ_AVG_LAT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA0_WR_REQ_AVG_LAT_MASK \ + 0x000003FF /* WR_REQ_AVG_LAT[9..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA0_WR_REQ_AVG_LAT_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_PERF_W_STA1 (0x7C024000 + 0x914)--- +* WR_ACK_AVG_LAT[9..0] - (RO) ack_avg_lat[9:0](long-term average) +* WR_ACK_PEAK_LAT[19..10] - (RO) ack_peak_lat[9:0] +* WR_ACK_LAT[29..20] - (RO) ack_lat[9:0](shot-term average) +* RESERVED[31..30] - (RO) tied constant +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA1_WR_ACK_LAT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA1_WR_ACK_LAT_MASK \ + 0x3FF00000 /* WR_ACK_LAT[29..20] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA1_WR_ACK_LAT_SHFT 20 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA1_WR_ACK_PEAK_LAT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA1_WR_ACK_PEAK_LAT_MASK \ + 0x000FFC00 /* WR_ACK_PEAK_LAT[19..10] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA1_WR_ACK_PEAK_LAT_SHFT 10 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA1_WR_ACK_AVG_LAT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA1_WR_ACK_AVG_LAT_MASK \ + 0x000003FF /* WR_ACK_AVG_LAT[9..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA1_WR_ACK_AVG_LAT_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_PERF_W_STA2 (0x7C024000 + 0x918)--- +* WR_BW[9..0] - (RO) bw[9:0](long-term average) +* WR_PEAK_BW[19..10] - (RO) peak_bw[9:0] +* WR_AVG_BW[29..20] - (RO) avg_bw[9:0](shot-term average) +* RESERVED[31..30] - (RO) tied constant +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA2_WR_AVG_BW_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA2_WR_AVG_BW_MASK \ + 0x3FF00000 /* WR_AVG_BW[29..20] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA2_WR_AVG_BW_SHFT 20 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA2_WR_PEAK_BW_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA2_WR_PEAK_BW_MASK \ + 0x000FFC00 /* WR_PEAK_BW[19..10] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA2_WR_PEAK_BW_SHFT 10 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA2_WR_BW_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA2_WR_BW_MASK \ + 0x000003FF /* WR_BW[9..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA2_WR_BW_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_PERF_W_STA3 (0x7C024000 + 0x91C)--- +* WR_LAT[9..0] - (RO) lat[9:0](long-term average) +* WR_PEAK_LAT[19..10] - (RO) peak_lat[9:0] +* WR_AVG_LAT[29..20] - (RO) avg_lat[9:0](shot-term average) +* RESERVED[31..30] - (RO) tied constant +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA3_WR_AVG_LAT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA3_WR_AVG_LAT_MASK \ + 0x3FF00000 /* WR_AVG_LAT[29..20] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA3_WR_AVG_LAT_SHFT 20 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA3_WR_PEAK_LAT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA3_WR_PEAK_LAT_MASK \ + 0x000FFC00 /* WR_PEAK_LAT[19..10] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA3_WR_PEAK_LAT_SHFT 10 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA3_WR_LAT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA3_WR_LAT_MASK \ + 0x000003FF /* WR_LAT[9..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_W_STA3_WR_LAT_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_PERF_R_STA0 (0x7C024000 + 0x920)--- +* RD_REQ_AVG_LAT[9..0] - (RO) req_avg_lat[9:0](long-term average) +* RD_REQ_PEAK_LAT[19..10] - (RO) req_peak_lat[9:0] +* RD_REQ_LAT[29..20] - (RO) req_lat[9:0](shot-term average) +* RESERVED[31..30] - (RO) tied constant +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA0_RD_REQ_LAT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA0_RD_REQ_LAT_MASK \ + 0x3FF00000 /* RD_REQ_LAT[29..20] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA0_RD_REQ_LAT_SHFT 20 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA0_RD_REQ_PEAK_LAT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA0_RD_REQ_PEAK_LAT_MASK \ + 0x000FFC00 /* RD_REQ_PEAK_LAT[19..10] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA0_RD_REQ_PEAK_LAT_SHFT 10 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA0_RD_REQ_AVG_LAT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA0_RD_REQ_AVG_LAT_MASK \ + 0x000003FF /* RD_REQ_AVG_LAT[9..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA0_RD_REQ_AVG_LAT_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_PERF_R_STA1 (0x7C024000 + 0x924)--- +* RD_ACK_AVG_LAT[9..0] - (RO) ack_avg_lat[9:0](long-term average) +* RD_ACK_PEAK_LAT[19..10] - (RO) ack_peak_lat[9:0] +* RD_ACK_LAT[29..20] - (RO) ack_lat[9:0](shot-term average) +* RESERVED[31..30] - (RO) tied constant +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA1_RD_ACK_LAT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA1_RD_ACK_LAT_MASK \ + 0x3FF00000 /* RD_ACK_LAT[29..20] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA1_RD_ACK_LAT_SHFT 20 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA1_RD_ACK_PEAK_LAT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA1_RD_ACK_PEAK_LAT_MASK \ + 0x000FFC00 /* RD_ACK_PEAK_LAT[19..10] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA1_RD_ACK_PEAK_LAT_SHFT 10 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA1_RD_ACK_AVG_LAT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA1_RD_ACK_AVG_LAT_MASK \ + 0x000003FF /* RD_ACK_AVG_LAT[9..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA1_RD_ACK_AVG_LAT_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_PERF_R_STA2 (0x7C024000 + 0x928)--- +* RD_BW[9..0] - (RO) bw[9:0](long-term average) +* RD_PEAK_BW[19..10] - (RO) peak_bw[9:0] +* RD_AVG_BW[29..20] - (RO) avg_bw[9:0](shot-term average) +* RESERVED[31..30] - (RO) tied constant +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA2_RD_AVG_BW_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA2_RD_AVG_BW_MASK \ + 0x3FF00000 /* RD_AVG_BW[29..20] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA2_RD_AVG_BW_SHFT 20 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA2_RD_PEAK_BW_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA2_RD_PEAK_BW_MASK \ + 0x000FFC00 /* RD_PEAK_BW[19..10] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA2_RD_PEAK_BW_SHFT 10 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA2_RD_BW_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA2_RD_BW_MASK \ + 0x000003FF /* RD_BW[9..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA2_RD_BW_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_PERF_R_STA3 (0x7C024000 + 0x92C)--- +* RD_LAT[9..0] - (RO) lat[9:0](long-term average) +* RD_PEAK_LAT[19..10] - (RO) peak_lat[9:0] +* RD_AVG_LAT[29..20] - (RO) avg_lat[9:0](shot-term average) +* RESERVED[31..30] - (RO) tied constant +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA3_RD_AVG_LAT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA3_RD_AVG_LAT_MASK \ + 0x3FF00000 /* RD_AVG_LAT[29..20] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA3_RD_AVG_LAT_SHFT 20 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA3_RD_PEAK_LAT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA3_RD_PEAK_LAT_MASK \ + 0x000FFC00 /* RD_PEAK_LAT[19..10] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA3_RD_PEAK_LAT_SHFT 10 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA3_RD_LAT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA3_RD_LAT_MASK \ + 0x000003FF /* RD_LAT[9..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_PERF_R_STA3_RD_LAT_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_DBG_OUT0 (0x7C024000 + 0x930)--- +* AXI_AW_CH_COUNTER[7..0] - (RO) axi_aw_ch_counter[7:0] +* AXI_W_CH_COUNTER[15..8] - (RO) axi_w_ch_counter[7:0] +* AXI_B_CH_COUNTER[23..16] - (RO) axi_b_ch_counter[7:0] +* AXI_AR_CH_COUNTER[31..24] - (RO) axi_ar_ch_counter[7:0] +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT0_AXI_AR_CH_COUNTER_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT0_AXI_AR_CH_COUNTER_MASK \ + 0xFF000000 /* AXI_AR_CH_COUNTER[31..24] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT0_AXI_AR_CH_COUNTER_SHFT 24 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT0_AXI_B_CH_COUNTER_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT0_AXI_B_CH_COUNTER_MASK \ + 0x00FF0000 /* AXI_B_CH_COUNTER[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT0_AXI_B_CH_COUNTER_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT0_AXI_W_CH_COUNTER_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT0_AXI_W_CH_COUNTER_MASK \ + 0x0000FF00 /* AXI_W_CH_COUNTER[15..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT0_AXI_W_CH_COUNTER_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT0_AXI_AW_CH_COUNTER_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT0_AXI_AW_CH_COUNTER_MASK \ + 0x000000FF /* AXI_AW_CH_COUNTER[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT0_AXI_AW_CH_COUNTER_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_DBG_OUT1 (0x7C024000 + 0x934)--- +* AXI_R_CH_COUNTER[7..0] - (RO) axi_r_ch_counter[7:0] +* AW_CURRENT_LEN[15..8] - (RO) aw_current_len[8:0] +* AR_CURRENT_LEN[23..16] - (RO) ar_current_len[8:0] +* RESERVED[31..24] - (RO) tied constant +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT1_AR_CURRENT_LEN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT1_AR_CURRENT_LEN_MASK \ + 0x00FF0000 /* AR_CURRENT_LEN[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT1_AR_CURRENT_LEN_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT1_AW_CURRENT_LEN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT1_AW_CURRENT_LEN_MASK \ + 0x0000FF00 /* AW_CURRENT_LEN[15..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT1_AW_CURRENT_LEN_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT1_AXI_R_CH_COUNTER_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT1_AXI_R_CH_COUNTER_MASK \ + 0x000000FF /* AXI_R_CH_COUNTER[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT1_AXI_R_CH_COUNTER_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_DBG_OUT2 (0x7C024000 + 0x938)--- +* AWVALID[0] - (RO) awvalid +* AWREADY[1] - (RO) awready +* WVALID[2] - (RO) wvalid +* WREADY[3] - (RO) wready +* BVALID[4] - (RO) bvalid +* BREADY[5] - (RO) bready +* ARVALID[6] - (RO) arvalid +* ARREADY[7] - (RO) arready +* RVALID[8] - (RO) rvalid +* RREADY[9] - (RO) rready +* RESERVED10[31..10] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_RREADY_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_RREADY_MASK \ + 0x00000200 /* RREADY[9] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_RREADY_SHFT 9 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_RVALID_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_RVALID_MASK \ + 0x00000100 /* RVALID[8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_RVALID_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_ARREADY_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_ARREADY_MASK \ + 0x00000080 /* ARREADY[7] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_ARREADY_SHFT 7 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_ARVALID_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_ARVALID_MASK \ + 0x00000040 /* ARVALID[6] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_ARVALID_SHFT 6 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_BREADY_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_BREADY_MASK \ + 0x00000020 /* BREADY[5] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_BREADY_SHFT 5 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_BVALID_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_BVALID_MASK \ + 0x00000010 /* BVALID[4] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_BVALID_SHFT 4 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_WREADY_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_WREADY_MASK \ + 0x00000008 /* WREADY[3] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_WREADY_SHFT 3 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_WVALID_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_WVALID_MASK \ + 0x00000004 /* WVALID[2] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_WVALID_SHFT 2 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_AWREADY_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_AWREADY_MASK \ + 0x00000002 /* AWREADY[1] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_AWREADY_SHFT 1 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_AWVALID_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_AWVALID_MASK \ + 0x00000001 /* AWVALID[0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT2_AWVALID_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_DBG_OUT3 (0x7C024000 + 0x93C)--- +* AR_CURRENT_ADDRESS[31..0] - (RO) ar_current_address[31:0] +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT3_AR_CURRENT_ADDRESS_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT3_AR_CURRENT_ADDRESS_MASK \ + 0xFFFFFFFF /* AR_CURRENT_ADDRESS[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT3_AR_CURRENT_ADDRESS_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_DBG_OUT4 (0x7C024000 + 0x940)--- +* AW_CURRENT_ADDRESS[31..0] - (RO) aw_current_address[31:0] +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT4_AW_CURRENT_ADDRESS_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT4_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT4_AW_CURRENT_ADDRESS_MASK \ + 0xFFFFFFFF /* AW_CURRENT_ADDRESS[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT4_AW_CURRENT_ADDRESS_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_DBG_OUT5 (0x7C024000 + 0x944)--- +* AR_CURRENT_ADDRESS_EXT[3..0] - (RO) ar_current_address[35:32] +* RESERVED4[15..4] - (RO) Reserved bits +* AW_CURRENT_ADDRESS_EXT[19..16] - (RO) aw_current_address[35:32] +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT5_AW_CURRENT_ADDRESS_EXT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT5_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT5_AW_CURRENT_ADDRESS_EXT_MASK \ + 0x000F0000 /* AW_CURRENT_ADDRESS_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT5_AW_CURRENT_ADDRESS_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT5_AR_CURRENT_ADDRESS_EXT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT5_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT5_AR_CURRENT_ADDRESS_EXT_MASK \ + 0x0000000F /* AR_CURRENT_ADDRESS_EXT[3..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MTR_DBG_OUT5_AR_CURRENT_ADDRESS_EXT_SHFT 0 + +/* +* ---WPDMA_AXI_MST_SLEEP_STA0 (0x7C024000 + 0x980)--- +* tx_pfet_cmd_state_idle[0] - (RO) cmd_state_idle +* tx_pfet_ar_cs_idle[1] - (RO) ar_cs_idle +* tx_pfet_axi_dp_cs_idle[2] - (RO) axi_dp_cs_idle +* tx_pfet_ar_cs_sleep[3] - (RO) ar_cs_sleep +* tx_pfet_buf_empty_axi_outstanding[4] - (RO) buf_empty(axi_outstanding) +* tx_pfet_data_fifo_empty[5] - (RO) data_fifo_empty +* RESERVED6[7..6] - (RO) Reserved bits +* tx_pfet_dma_req_fifo_empty[8] - (RO) dma_req_fifo_empty +* tx_pfet_axi_req_fifo_empty[9] - (RO) axi_req_fifo_empty +* tx_pfet_axi_pkt_fifo_empty[10] - (RO) axi_pkt_fifo_empty +* RESERVED11[11] - (RO) Reserved bits +* tx_pfet_axi_outstanding_req[15..12] - (RO) current pipelined +* axi_outstanding_req number +* pf_dfet_rx_cmd_state_idle[16] - (RO) cmd_state_idle +* pf_dfet_rx_ar_cs_idle[17] - (RO) ar_cs_idle +* pf_dfet_rx_axi_dp_cs_idle[18] - (RO) axi_dp_cs_idle +* pf_dfet_rx_ar_cs_sleep[19] - (RO) ar_cs_sleep +* pf_dfet_rx_buf_empty_axi_outstanding[20] - (RO) buf_empty(axi_outstanding) +* RESERVED21[23..21] - (RO) Reserved bits +* pf_dfet_rx_dma_req_fifo_empty[24] - (RO) dma_req_fifo_empty +* pf_dfet_rx_axi_req_fifo_empty[25] - (RO) axi_req_fifo_empty +* pf_dfet_rx_axi_pkt_fifo_empty[26] - (RO) axi_pkt_fifo_empty +* RESERVED27[27] - (RO) Reserved bits +* pf_dfet_rx_axi_outstanding_req[31..28] - (RO) current pipelined +* axi_outstanding_req number +*/ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_axi_outstanding_req_ADDR\ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_axi_outstanding_req_MASK\ +0xF0000000 /* pf_dfet_rx_axi_outstanding_req[31..28] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_axi_outstanding_req_SHFT\ +28 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_axi_pkt_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_axi_pkt_fifo_empty_MASK \ + 0x04000000 /* pf_dfet_rx_axi_pkt_fifo_empty[26] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_axi_pkt_fifo_empty_SHFT \ + 26 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_axi_req_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_axi_req_fifo_empty_MASK \ + 0x02000000 /* pf_dfet_rx_axi_req_fifo_empty[25] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_axi_req_fifo_empty_SHFT \ + 25 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_dma_req_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_dma_req_fifo_empty_MASK \ + 0x01000000 /* pf_dfet_rx_dma_req_fifo_empty[24] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_dma_req_fifo_empty_SHFT \ + 24 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_buf_empty_axi_outstandin\ +g_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_buf_empty_axi_outstandin\ +g_MASK \ +0x00100000 /* pf_dfet_rx_buf_empty_axi_outstanding[20] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_buf_empty_axi_outstandin\ +g_SHFT \ +20 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_ar_cs_sleep_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_ar_cs_sleep_MASK \ + 0x00080000 /* pf_dfet_rx_ar_cs_sleep[19] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_ar_cs_sleep_SHFT \ + 19 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_axi_dp_cs_idle_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_axi_dp_cs_idle_MASK \ + 0x00040000 /* pf_dfet_rx_axi_dp_cs_idle[18] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_axi_dp_cs_idle_SHFT \ + 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_ar_cs_idle_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_ar_cs_idle_MASK \ + 0x00020000 /* pf_dfet_rx_ar_cs_idle[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_ar_cs_idle_SHFT \ + 17 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_cmd_state_idle_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_cmd_state_idle_MASK \ + 0x00010000 /* pf_dfet_rx_cmd_state_idle[16] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_cmd_state_idle_SHFT \ + 16 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_axi_outstanding_req_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_axi_outstanding_req_MASK \ + 0x0000F000 /* tx_pfet_axi_outstanding_req[15..12] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_axi_outstanding_req_SHFT \ + 12 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_axi_pkt_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_axi_pkt_fifo_empty_MASK \ + 0x00000400 /* tx_pfet_axi_pkt_fifo_empty[10] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_axi_pkt_fifo_empty_SHFT \ + 10 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_axi_req_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_axi_req_fifo_empty_MASK \ + 0x00000200 /* tx_pfet_axi_req_fifo_empty[9] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_axi_req_fifo_empty_SHFT \ + 9 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_dma_req_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_dma_req_fifo_empty_MASK \ + 0x00000100 /* tx_pfet_dma_req_fifo_empty[8] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_dma_req_fifo_empty_SHFT \ + 8 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_data_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_data_fifo_empty_MASK \ + 0x00000020 /* tx_pfet_data_fifo_empty[5] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_data_fifo_empty_SHFT \ + 5 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_buf_empty_axi_outstanding_A\ +DDR \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_buf_empty_axi_outstanding_M\ +ASK \ +0x00000010 /* tx_pfet_buf_empty_axi_outstanding[4] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_buf_empty_axi_outstanding_S\ +HFT \ +4 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_ar_cs_sleep_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_ar_cs_sleep_MASK \ + 0x00000008 /* tx_pfet_ar_cs_sleep[3] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_ar_cs_sleep_SHFT 3 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_axi_dp_cs_idle_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_axi_dp_cs_idle_MASK \ + 0x00000004 /* tx_pfet_axi_dp_cs_idle[2] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_axi_dp_cs_idle_SHFT \ + 2 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_ar_cs_idle_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_ar_cs_idle_MASK \ + 0x00000002 /* tx_pfet_ar_cs_idle[1] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_ar_cs_idle_SHFT 1 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_cmd_state_idle_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_cmd_state_idle_MASK \ + 0x00000001 /* tx_pfet_cmd_state_idle[0] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_cmd_state_idle_SHFT \ + 0 + +/* +* ---WPDMA_AXI_MST_SLEEP_STA1 (0x7C024000 + 0x984)--- +* pf_dfet_tx_cmd_state_idle[0] - (RO) cmd_state_idle +* pf_dfet_tx_ar_cs_idle[1] - (RO) ar_cs_idle +* pf_dfet_tx_axi_dp_cs_idle[2] - (RO) axi_dp_cs_idle +* pf_dfet_tx_ar_cs_sleep[3] - (RO) ar_cs_sleep +* pf_dfet_tx_buf_empty_axi_outstanding[4] - (RO) buf_empty(axi_outstanding) +* RESERVED5[7..5] - (RO) Reserved bits +* pf_dfet_tx_dma_req_fifo_empty[8] - (RO) dma_req_fifo_empty +* pf_dfet_tx_axi_req_fifo_empty[9] - (RO) axi_req_fifo_empty +* pf_dfet_tx_axi_pkt_fifo_empty[10] - (RO) axi_pkt_fifo_empty +* RESERVED11[11] - (RO) Reserved bits +* pf_dfet_tx_axi_outstanding_req[15..12] - (RO) current pipelined +* axi_outstanding_req number +* tx_pfet_cmd_state_idle[16] - (RO) cmd_state_idle +* tx_pfet_ar_cs_idle[17] - (RO) ar_cs_idle +* tx_pfet_axi_dp_cs_idle[18] - (RO) axi_dp_cs_idle +* tx_pfet_ar_cs_sleep[19] - (RO) ar_cs_sleep +* tx_pfet_buf_empty_axi_outstanding[20] - (RO) buf_empty(axi_outstanding) +* tx_pfet_data_fifo_empty[21] - (RO) data_fifo_empty +* RESERVED22[23..22] - (RO) Reserved bits +* tx_pfet_dma_req_fifo_empty[24] - (RO) dma_req_fifo_empty +* tx_pfet_axi_req_fifo_empty[25] - (RO) axi_req_fifo_empty +* tx_pfet_axi_pkt_fifo_empty[26] - (RO) axi_pkt_fifo_empty +* RESERVED27[27] - (RO) Reserved bits +* tx_pfet_axi_outstanding_req[31..28] - (RO) current pipelined +* axi_outstanding_req number +*/ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_axi_outstanding_req_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_axi_outstanding_req_MASK \ + 0xF0000000 /* tx_pfet_axi_outstanding_req[31..28] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_axi_outstanding_req_SHFT \ + 28 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_axi_pkt_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_axi_pkt_fifo_empty_MASK \ + 0x04000000 /* tx_pfet_axi_pkt_fifo_empty[26] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_axi_pkt_fifo_empty_SHFT \ + 26 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_axi_req_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_axi_req_fifo_empty_MASK \ + 0x02000000 /* tx_pfet_axi_req_fifo_empty[25] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_axi_req_fifo_empty_SHFT \ + 25 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_dma_req_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_dma_req_fifo_empty_MASK \ + 0x01000000 /* tx_pfet_dma_req_fifo_empty[24] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_dma_req_fifo_empty_SHFT \ + 24 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_data_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_data_fifo_empty_MASK \ + 0x00200000 /* tx_pfet_data_fifo_empty[21] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_data_fifo_empty_SHFT \ + 21 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_buf_empty_axi_outstanding_A\ +DDR \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_buf_empty_axi_outstanding_M\ +ASK \ +0x00100000 /* tx_pfet_buf_empty_axi_outstanding[20] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_buf_empty_axi_outstanding_S\ +HFT \ +20 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_ar_cs_sleep_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_ar_cs_sleep_MASK \ + 0x00080000 /* tx_pfet_ar_cs_sleep[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_ar_cs_sleep_SHFT 19 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_axi_dp_cs_idle_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_axi_dp_cs_idle_MASK \ + 0x00040000 /* tx_pfet_axi_dp_cs_idle[18] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_axi_dp_cs_idle_SHFT \ + 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_ar_cs_idle_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_ar_cs_idle_MASK \ + 0x00020000 /* tx_pfet_ar_cs_idle[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_ar_cs_idle_SHFT 17 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_cmd_state_idle_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_cmd_state_idle_MASK \ + 0x00010000 /* tx_pfet_cmd_state_idle[16] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_tx_pfet_cmd_state_idle_SHFT \ + 16 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_axi_outstanding_req_ADDR\ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_axi_outstanding_req_MASK\ +0x0000F000 /* pf_dfet_tx_axi_outstanding_req[15..12] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_axi_outstanding_req_SHFT\ +12 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_axi_pkt_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_axi_pkt_fifo_empty_MASK \ + 0x00000400 /* pf_dfet_tx_axi_pkt_fifo_empty[10] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_axi_pkt_fifo_empty_SHFT \ + 10 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_axi_req_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_axi_req_fifo_empty_MASK \ + 0x00000200 /* pf_dfet_tx_axi_req_fifo_empty[9] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_axi_req_fifo_empty_SHFT \ + 9 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_dma_req_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_dma_req_fifo_empty_MASK \ + 0x00000100 /* pf_dfet_tx_dma_req_fifo_empty[8] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_dma_req_fifo_empty_SHFT \ + 8 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_buf_empty_axi_outstandin\ +g_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_buf_empty_axi_outstandin\ +g_MASK \ +0x00000010 /* pf_dfet_tx_buf_empty_axi_outstanding[4] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_buf_empty_axi_outstandin\ +g_SHFT \ +4 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_ar_cs_sleep_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_ar_cs_sleep_MASK \ + 0x00000008 /* pf_dfet_tx_ar_cs_sleep[3] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_ar_cs_sleep_SHFT \ + 3 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_axi_dp_cs_idle_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_axi_dp_cs_idle_MASK \ + 0x00000004 /* pf_dfet_tx_axi_dp_cs_idle[2] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_axi_dp_cs_idle_SHFT \ + 2 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_ar_cs_idle_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_ar_cs_idle_MASK \ + 0x00000002 /* pf_dfet_tx_ar_cs_idle[1] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_ar_cs_idle_SHFT 1 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_cmd_state_idle_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_cmd_state_idle_MASK \ + 0x00000001 /* pf_dfet_tx_cmd_state_idle[0] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_cmd_state_idle_SHFT \ + 0 + +/* +* ---WPDMA_AXI_MST_SLEEP_STA2 (0x7C024000 + 0x988)--- +* rx_pfet_cmd_state_idle[0] - (RO) cmd_state_idle +* rx_pfet_aw_cs_idle[1] - (RO) aw_cs_idle +* rx_pfet_axi_dp_cs_idle[2] - (RO) axi_dp_cs_idle +* rx_pfet_aw_cs_sleep[3] - (RO) aw_cs_sleep +* rx_pfet_buf_empty_axi_outstanding[4] - (RO) buf_empty(axi_outstanding) +* rx_pfet_data_fifo_empty[5] - (RO) data_fifo_empty +* rx_pfet_rx_axi_bid_fifo_empty[6] - (RO) axi_bid_fifo_empty +* RESERVED7[7] - (RO) Reserved bits +* rx_pfet_dma_req_fifo_empty[8] - (RO) dma_req_fifo_empty +* rx_pfet_axi_req_fifo_empty[9] - (RO) axi_req_fifo_empty +* rx_pfet_axi_pkt_fifo_empty[10] - (RO) axi_pkt_fifo_empty +* RESERVED11[11] - (RO) Reserved bits +* rx_pfet_axi_outstanding_req[15..12] - (RO) current pipelined +* axi_outstanding_req number +* wb_dfet_rx_cmd_state_idle[16] - (RO) cmd_state_idle +* wb_dfet_rx_aw_cs_idle[17] - (RO) aw_cs_idle +* wb_dfet_rx_axi_dp_cs_idle[18] - (RO) axi_dp_cs_idle +* wb_dfet_rx_aw_cs_sleep[19] - (RO) aw_cs_sleep +* wb_dfet_rx_buf_empty_axi_outstanding[20] - (RO) buf_empty(axi_outstanding) +* wb_dfet_rx_axi_data_fifo_empty[21] - (RO) axi_data_fifo_empty +* wb_dfet_rx_axi_bid_fifo_empty[22] - (RO) axi_bid_fifo_empty +* RESERVED23[23] - (RO) Reserved bits +* wb_dfet_rx_dma_req_fifo_empty[24] - (RO) dma_req_fifo_empty +* wb_dfet_rx_axi_req_fifo_empty[25] - (RO) axi_req_fifo_empty +* wb_dfet_rx_axi_pkt_fifo_empty[26] - (RO) axi_pkt_fifo_empty +* RESERVED27[27] - (RO) Reserved bits +* wb_dfet_rx_axi_outstanding_req[31..28] - (RO) current pipelined +* axi_outstanding_req number +*/ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_outstanding_req_ADDR\ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_outstanding_req_MASK\ +0xF0000000 /* wb_dfet_rx_axi_outstanding_req[31..28] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_outstanding_req_SHFT\ +28 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_pkt_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_pkt_fifo_empty_MASK \ + 0x04000000 /* wb_dfet_rx_axi_pkt_fifo_empty[26] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_pkt_fifo_empty_SHFT \ + 26 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_req_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_req_fifo_empty_MASK \ + 0x02000000 /* wb_dfet_rx_axi_req_fifo_empty[25] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_req_fifo_empty_SHFT \ + 25 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_dma_req_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_dma_req_fifo_empty_MASK \ + 0x01000000 /* wb_dfet_rx_dma_req_fifo_empty[24] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_dma_req_fifo_empty_SHFT \ + 24 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_bid_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_bid_fifo_empty_MASK \ + 0x00400000 /* wb_dfet_rx_axi_bid_fifo_empty[22] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_bid_fifo_empty_SHFT \ + 22 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_data_fifo_empty_ADDR\ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_data_fifo_empty_MASK\ +0x00200000 /* wb_dfet_rx_axi_data_fifo_empty[21] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_data_fifo_empty_SHFT\ +21 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_buf_empty_axi_outstandin\ +g_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_buf_empty_axi_outstandin\ +g_MASK \ +0x00100000 /* wb_dfet_rx_buf_empty_axi_outstanding[20] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_buf_empty_axi_outstandin\ +g_SHFT \ +20 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_aw_cs_sleep_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_aw_cs_sleep_MASK \ + 0x00080000 /* wb_dfet_rx_aw_cs_sleep[19] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_aw_cs_sleep_SHFT \ + 19 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_dp_cs_idle_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_dp_cs_idle_MASK \ + 0x00040000 /* wb_dfet_rx_axi_dp_cs_idle[18] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_dp_cs_idle_SHFT \ + 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_aw_cs_idle_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_aw_cs_idle_MASK \ + 0x00020000 /* wb_dfet_rx_aw_cs_idle[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_aw_cs_idle_SHFT \ + 17 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_cmd_state_idle_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_cmd_state_idle_MASK \ + 0x00010000 /* wb_dfet_rx_cmd_state_idle[16] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_cmd_state_idle_SHFT \ + 16 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_axi_outstanding_req_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_axi_outstanding_req_MASK \ + 0x0000F000 /* rx_pfet_axi_outstanding_req[15..12] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_axi_outstanding_req_SHFT \ + 12 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_axi_pkt_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_axi_pkt_fifo_empty_MASK \ + 0x00000400 /* rx_pfet_axi_pkt_fifo_empty[10] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_axi_pkt_fifo_empty_SHFT \ + 10 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_axi_req_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_axi_req_fifo_empty_MASK \ + 0x00000200 /* rx_pfet_axi_req_fifo_empty[9] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_axi_req_fifo_empty_SHFT \ + 9 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_dma_req_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_dma_req_fifo_empty_MASK \ + 0x00000100 /* rx_pfet_dma_req_fifo_empty[8] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_dma_req_fifo_empty_SHFT \ + 8 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_rx_axi_bid_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_rx_axi_bid_fifo_empty_MASK \ + 0x00000040 /* rx_pfet_rx_axi_bid_fifo_empty[6] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_rx_axi_bid_fifo_empty_SHFT \ + 6 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_data_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_data_fifo_empty_MASK \ + 0x00000020 /* rx_pfet_data_fifo_empty[5] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_data_fifo_empty_SHFT \ + 5 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_buf_empty_axi_outstanding_A\ +DDR \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_buf_empty_axi_outstanding_M\ +ASK \ +0x00000010 /* rx_pfet_buf_empty_axi_outstanding[4] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_buf_empty_axi_outstanding_S\ +HFT \ +4 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_aw_cs_sleep_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_aw_cs_sleep_MASK \ + 0x00000008 /* rx_pfet_aw_cs_sleep[3] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_aw_cs_sleep_SHFT 3 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_axi_dp_cs_idle_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_axi_dp_cs_idle_MASK \ + 0x00000004 /* rx_pfet_axi_dp_cs_idle[2] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_axi_dp_cs_idle_SHFT \ + 2 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_aw_cs_idle_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_aw_cs_idle_MASK \ + 0x00000002 /* rx_pfet_aw_cs_idle[1] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_aw_cs_idle_SHFT 1 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_cmd_state_idle_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_cmd_state_idle_MASK \ + 0x00000001 /* rx_pfet_cmd_state_idle[0] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_cmd_state_idle_SHFT \ + 0 + +/* +* ---WPDMA_AXI_MST_SLEEP_STA3 (0x7C024000 + 0x98C)--- +* wb_dfet_tx_cmd_state_idle[0] - (RO) cmd_state_idle +* wb_dfet_tx_aw_cs_idle[1] - (RO) aw_cs_idle +* wb_dfet_tx_axi_dp_cs_idle[2] - (RO) axi_dp_cs_idle +* wb_dfet_tx_aw_cs_sleep[3] - (RO) aw_cs_sleep +* wb_dfet_tx_buf_empty_axi_outstanding[4] - (RO) buf_empty(axi_outstanding) +* wb_dfet_tx_axi_data_fifo_empty[5] - (RO) axi_data_fifo_empty +* wb_dfet_rx_axi_bid_fifo_empty[6] - (RO) axi_bid_fifo_empty +* RESERVED7[7] - (RO) Reserved bits +* wb_dfet_tx_dma_req_fifo_empty[8] - (RO) dma_req_fifo_empty +* wb_dfet_tx_axi_req_fifo_empty[9] - (RO) axi_req_fifo_empty +* wb_dfet_tx_axi_pkt_fifo_empty[10] - (RO) axi_pkt_fifo_empty +* RESERVED11[11] - (RO) Reserved bits +* wb_dfet_tx_axi_outstanding_req[15..12] - (RO) current pipelined +* axi_outstanding_req number +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_outstanding_req_ADDR\ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_outstanding_req_MASK\ +0x0000F000 /* wb_dfet_tx_axi_outstanding_req[15..12] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_outstanding_req_SHFT\ +12 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_pkt_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_pkt_fifo_empty_MASK \ + 0x00000400 /* wb_dfet_tx_axi_pkt_fifo_empty[10] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_pkt_fifo_empty_SHFT \ + 10 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_req_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_req_fifo_empty_MASK \ + 0x00000200 /* wb_dfet_tx_axi_req_fifo_empty[9] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_req_fifo_empty_SHFT \ + 9 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_dma_req_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_dma_req_fifo_empty_MASK \ + 0x00000100 /* wb_dfet_tx_dma_req_fifo_empty[8] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_dma_req_fifo_empty_SHFT \ + 8 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_rx_axi_bid_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_rx_axi_bid_fifo_empty_MASK \ + 0x00000040 /* wb_dfet_rx_axi_bid_fifo_empty[6] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_rx_axi_bid_fifo_empty_SHFT \ + 6 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_data_fifo_empty_ADDR\ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_data_fifo_empty_MASK\ +0x00000020 /* wb_dfet_tx_axi_data_fifo_empty[5] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_data_fifo_empty_SHFT\ +5 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_buf_empty_axi_outstandin\ +g_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_buf_empty_axi_outstandin\ +g_MASK \ +0x00000010 /* wb_dfet_tx_buf_empty_axi_outstanding[4] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_buf_empty_axi_outstandin\ +g_SHFT \ +4 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_aw_cs_sleep_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_aw_cs_sleep_MASK \ + 0x00000008 /* wb_dfet_tx_aw_cs_sleep[3] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_aw_cs_sleep_SHFT \ + 3 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_dp_cs_idle_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_dp_cs_idle_MASK \ + 0x00000004 /* wb_dfet_tx_axi_dp_cs_idle[2] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_dp_cs_idle_SHFT \ + 2 +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_aw_cs_idle_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_aw_cs_idle_MASK \ + 0x00000002 /* wb_dfet_tx_aw_cs_idle[1] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_aw_cs_idle_SHFT 1 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_cmd_state_idle_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_cmd_state_idle_MASK \ + 0x00000001 /* wb_dfet_tx_cmd_state_idle[0] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_cmd_state_idle_SHFT \ + 0 + +/* +* ---WPDMA_AXI_MST_SLEEP_STA4 (0x7C024000 + 0x990)--- +* RESERVED0[0] - (RO) Reserved bits +* rx_pfet_pld_rx_pfet_sleep_rdy[1] - (RO) pld_rx_pfet_sleep_rdy +* RESERVED2[30..2] - (RO) Reserved bits +* tx_pfet_pld_tx_pfet_sleep_rdy[31] - (RO) pld_tx_pfet_sleep_rdy +*/ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA4_tx_pfet_pld_tx_pfet_sleep_rdy_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA4_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA4_tx_pfet_pld_tx_pfet_sleep_rdy_MASK \ + 0x80000000 /* tx_pfet_pld_tx_pfet_sleep_rdy[31] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA4_tx_pfet_pld_tx_pfet_sleep_rdy_SHFT \ + 31 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA4_rx_pfet_pld_rx_pfet_sleep_rdy_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA4_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA4_rx_pfet_pld_rx_pfet_sleep_rdy_MASK \ + 0x00000002 /* rx_pfet_pld_rx_pfet_sleep_rdy[1] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_AXI_MST_SLEEP_STA4_rx_pfet_pld_rx_pfet_sleep_rdy_SHFT \ + 1 + +/* +* ---WPDMA_TX_RING0_BKRS_CTRL0 (0x7C024000 + 0xA00)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING0_BKRS_CTRL1 (0x7C024000 + 0xA04)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING0_BKRS_CTRL2 (0x7C024000 + 0xA08)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING1_BKRS_CTRL0 (0x7C024000 + 0xA10)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING1_BKRS_CTRL1 (0x7C024000 + 0xA14)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING1_BKRS_CTRL2 (0x7C024000 + 0xA18)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING2_BKRS_CTRL0 (0x7C024000 + 0xA20)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING2_BKRS_CTRL1 (0x7C024000 + 0xA24)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING2_BKRS_CTRL2 (0x7C024000 + 0xA28)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING3_BKRS_CTRL0 (0x7C024000 + 0xA30)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING3_BKRS_CTRL1 (0x7C024000 + 0xA34)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING3_BKRS_CTRL2 (0x7C024000 + 0xA38)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING0_BKRS_CTRL0 (0x7C024000 + 0xC00)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING0_BKRS_CTRL1 (0x7C024000 + 0xC04)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING0_BKRS_CTRL2 (0x7C024000 + 0xC08)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING1_BKRS_CTRL0 (0x7C024000 + 0xC10)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING1_BKRS_CTRL1 (0x7C024000 + 0xC14)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING1_BKRS_CTRL2 (0x7C024000 + 0xC18)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING2_BKRS_CTRL0 (0x7C024000 + 0xC20)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING2_BKRS_CTRL1 (0x7C024000 + 0xC24)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING2_BKRS_CTRL2 (0x7C024000 + 0xC28)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING3_BKRS_CTRL0 (0x7C024000 + 0xC30)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING3_BKRS_CTRL1 (0x7C024000 + 0xC34)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING3_BKRS_CTRL2 (0x7C024000 + 0xC38)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +#ifdef __cplusplus +} +#endif + +#endif /* __WF_WFDMA_HOST_DMA0_REGS_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7915/wf_wfdma_host_dma1.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7915/wf_wfdma_host_dma1.h new file mode 100644 index 0000000000000..cfe344697eabe --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7915/wf_wfdma_host_dma1.h @@ -0,0 +1,9727 @@ +/* [File] : wf_wfdma_host_dma1.h */ +/* [Revision time] : Tue Jun 5 14:32:37 2018 */ +/* [Description] : This file is auto generated by CODA */ +/* [Copyright] : Copyright (C) 2018 Mediatek Incorportion. All rights reserved. +*/ + +#ifndef __WF_WFDMA_HOST_DMA1_REGS_H__ +#define __WF_WFDMA_HOST_DMA1_REGS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* ************************************************************************** */ +/* */ +/* WF_WFDMA_HOST_DMA1 CR Definitions */ +/* */ +/* ************************************************************************** */ + +#define WF_WFDMA_HOST_DMA1_BASE 0x7C025000 + + +#define WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0XA0) /* 50A0 */ +#define WF_WFDMA_HOST_DMA1_HOST_IF_RX_DONE_STS_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0XA4) /* 50A4 */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_RST_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x100) /* 5100 */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x104) /* 5104 */ +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0X108) /* 5108 */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x10C) /* 510C */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0X110) /* 5110 */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0X114) /* 5114 */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_EXT_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x118) /* 5118 */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_EXT_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0X11C) /* 511C */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DUMMY_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x120) /* 5120 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_DBG_IDX_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x124) /* 5124 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_DBG_PROBE_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x128) /* 5128 */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x12C) /* 512C */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_PROBE_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x130) /* 5130 */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DMASHDL_DBG_PROBE_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x134) /* 5134 */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x138) /* 5138 */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x13c) /* 513C */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_FIFO_TEST_MOD_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x140) /* 5140 */ +#define WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x1E8) /* 51E8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x1EC) /* 51EC */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x1F0) /* 51F0 */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x1F4) /* 51F4 */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x1F8) /* 51F8 */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x1FC) /* 51FC */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x200) /* 5200 */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0X204) /* 5204 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x208) /* 5208 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x20C) /* 520C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_TX_Q_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x224) /* 5224 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x230) /* 5230 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_MISC_CFG_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x234) /* 5234 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x240) /* 5240 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH10_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x260) /* 5260 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH32_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x264) /* 5264 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH54_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x268) /* 5268 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH76_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x26C) /* 526C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x280) /* 5280 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x284) /* 5284 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_EXT_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x288) /* 5288 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x298) /* 5298 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x29C) /* 529C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_DBG0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2A0) /* 52A0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_DBG1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2A4) /* 52A4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_DBG0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2A8) /* 52A8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_DBG1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2AC) /* 52AC */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2B0) /* 52B0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2B4) /* 52B4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2B8) /* 52B8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2BC) /* 52BC */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2C0) /* 52C0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2C4) /* 52C4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2C8) /* 52C8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2CC) /* 52CC */ +#define WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2E0) /* 52E0 */ +#define WF_WFDMA_HOST_DMA1_HOST_PER_INT_ENA_STA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2E4) /* 52E4 */ +#define WF_WFDMA_HOST_DMA1_HOST_PER_DLY_INT_CFG_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2E8) /* 52E8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2F0) /* 52F0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x300) /* 5300 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x304) /* 5304 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x308) /* 5308 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x30c) /* 530C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x310) /* 5310 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x314) /* 5314 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x318) /* 5318 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x31c) /* 531C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x320) /* 5320 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x324) /* 5324 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x328) /* 5328 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x32c) /* 532C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x330) /* 5330 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x334) /* 5334 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x338) /* 5338 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x33c) /* 533C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x340) /* 5340 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x344) /* 5344 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x348) /* 5348 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x34c) /* 534C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x350) /* 5350 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x354) /* 5354 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x358) /* 5358 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x35c) /* 535C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x360) /* 5360 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x364) /* 5364 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x368) /* 5368 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x36c) /* 536C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x370) /* 5370 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x374) /* 5374 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x378) /* 5378 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x37c) /* 537C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x380) /* 5380 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x384) /* 5384 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x388) /* 5388 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x38c) /* 538C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x390) /* 5390 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x394) /* 5394 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x398) /* 5398 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x39c) /* 539C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3a0) /* 53A0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3a4) /* 53A4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3a8) /* 53A8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3ac) /* 53AC */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3b0) /* 53B0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3b4) /* 53B4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3b8) /* 53B8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3bc) /* 53BC */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3c0) /* 53C0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3c4) /* 53C4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3c8) /* 53C8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3cc) /* 53CC */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3d0) /* 53D0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3d4) /* 53D4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3d8) /* 53D8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3dc) /* 53DC */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3e0) /* 53E0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3e4) /* 53E4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3e8) /* 53E8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3ec) /* 53EC */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3f0) /* 53F0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3f4) /* 53F4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3f8) /* 53F8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3fc) /* 53FC */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x400) /* 5400 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x404) /* 5404 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x408) /* 5408 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x40c) /* 540C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x410) /* 5410 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x414) /* 5414 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x418) /* 5418 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x41c) /* 541C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x420) /* 5420 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x424) /* 5424 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x428) /* 5428 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x42c) /* 542C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x430) /* 5430 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x434) /* 5434 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x438) /* 5438 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x43c) /* 543C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x440) /* 5440 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x444) /* 5444 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x448) /* 5448 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x44c) /* 544C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x450) /* 5450 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x454) /* 5454 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x458) /* 5458 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x45c) /* 545C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x460) /* 5460 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x464) /* 5464 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x468) /* 5468 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x46c) /* 546C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x470) /* 5470 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x474) /* 5474 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x478) /* 5478 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x47c) /* 547C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x500) /* 5500 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x504) /* 5504 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x508) /* 5508 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x50c) /* 550C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x510) /* 5510 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x514) /* 5514 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x518) /* 5518 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x51c) /* 551C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x520) /* 5520 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x524) /* 5524 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x528) /* 5528 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x52C) /* 552C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x530) /* 5530 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x534) /* 5534 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x538) /* 5538 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x53C) /* 553C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x600) /* 5600 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x604) /* 5604 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x608) /* 5608 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x60C) /* 560C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x610) /* 5610 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x614) /* 5614 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x618) /* 5618 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x61C) /* 561C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x620) /* 5620 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x624) /* 5624 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x628) /* 5628 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x62C) /* 562C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x630) /* 5630 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x634) /* 5634 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x638) /* 5638 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x63C) /* 563C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x640) /* 5640 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x644) /* 5644 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x648) /* 5648 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x64C) /* 564C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x650) /* 5650 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x654) /* 5654 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x658) /* 5658 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x65C) /* 565C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x680) /* 5680 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x684) /* 5684 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x688) /* 5688 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x68C) /* 568C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x900) /* 5900 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x904) /* 5904 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x910) /* 5910 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x914) /* 5914 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x918) /* 5918 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x91C) /* 591C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x920) /* 5920 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x924) /* 5924 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x928) /* 5928 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x92C) /* 592C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x930) /* 5930 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x934) /* 5934 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x938) /* 5938 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x93C) /* 593C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT4_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x940) /* 5940 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT5_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x944) /* 5944 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x980) /* 5980 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x984) /* 5984 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x988) /* 5988 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x98C) /* 598C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA4_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x990) /* 5990 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA00) /* 5A00 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA04) /* 5A04 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA08) /* 5A08 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA10) /* 5A10 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA14) /* 5A14 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA18) /* 5A18 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA20) /* 5A20 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA24) /* 5A24 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA28) /* 5A28 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA30) /* 5A30 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA34) /* 5A34 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA38) /* 5A38 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA40) /* 5A40 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA44) /* 5A44 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA48) /* 5A48 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA50) /* 5A50 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA54) /* 5A54 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA58) /* 5A58 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA60) /* 5A60 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA64) /* 5A64 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA68) /* 5A68 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA70) /* 5A70 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA74) /* 5A74 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA78) /* 5A78 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA80) /* 5A80 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA84) /* 5A84 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA88) /* 5A88 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA90) /* 5A90 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA94) /* 5A94 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA98) /* 5A98 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAA0) /* 5AA0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAA4) /* 5AA4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAA8) /* 5AA8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAB0) /* 5AB0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAB4) /* 5AB4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAB8) /* 5AB8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAC0) /* 5AC0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAC4) /* 5AC4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAC8) /* 5AC8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAD0) /* 5AD0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAD4) /* 5AD4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAD8) /* 5AD8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAE0) /* 5AE0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAE4) /* 5AE4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAE8) /* 5AE8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAF0) /* 5AF0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAF4) /* 5AF4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAF8) /* 5AF8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB00) /* 5B00 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB04) /* 5B04 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB08) /* 5B08 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB10) /* 5B10 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB14) /* 5B14 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB18) /* 5B18 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB20) /* 5B20 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB24) /* 5B24 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB28) /* 5B28 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB30) /* 5B30 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB34) /* 5B34 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB38) /* 5B38 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB40) /* 5B40 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB44) /* 5B44 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB48) /* 5B48 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB50) /* 5B50 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB54) /* 5B54 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB58) /* 5B58 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB60) /* 5B60 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB64) /* 5B64 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB68) /* 5B68 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB70) /* 5B70 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB74) /* 5B74 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB78) /* 5B78 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xC00) /* 5C00 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xC04) /* 5C04 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xC08) /* 5C08 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xC10) /* 5C10 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xC14) /* 5C14 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xC18) /* 5C18 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xC20) /* 5C20 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xC24) /* 5C24 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xC28) /* 5C28 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xC30) /* 5C30 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xC34) /* 5C34 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xC38) /* 5C38 */ + + + + +/* +* ---HOST_IF_TX_DONE_STS (0x7C025000 + 0XA0)--- +* fifo_dfet_txdone_dat0_done_sts[0] - (W1C) USB DAT0 FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint buffer +* fifo_dfet_txdone_dat1_done_sts[1] - (W1C) USB DAT1 FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint buffer +* fifo_dfet_txdone_dat2_done_sts[2] - (W1C) USB DAT2 FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint buffer +* fifo_dfet_txdone_dat3_done_sts[3] - (W1C) USB DAT3 FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint buffer +* fifo_dfet_txdone_dat4_done_sts[4] - (W1C) USB DAT4 FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint buffer +* fifo_dfet_txdone_cmd_done_sts[5] - (W1C) USB CMD FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint buffer +* fifo_dfet_txdone_fwdl_done_sts[6] - (W1C) USB Firmware download FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint buffer +* SDIO Mode (All SDIO Tx packet goto firmware download FIFO) +* 0 : no tx done +* 1 : pdma start to fetch data from SDIO buffer +* RESERVED7[31..7] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_fwdl_done_sts_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_fwdl_done_sts_MASK \ + 0x00000040 /* fifo_dfet_txdone_fwdl_done_sts[6] */ +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_fwdl_done_sts_SHFT \ + 6 +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_cmd_done_sts_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_cmd_done_sts_MASK \ + 0x00000020 /* fifo_dfet_txdone_cmd_done_sts[5] */ +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_cmd_done_sts_SHFT \ + 5 +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat4_done_sts_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat4_done_sts_MASK \ + 0x00000010 /* fifo_dfet_txdone_dat4_done_sts[4] */ +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat4_done_sts_SHFT \ + 4 +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat3_done_sts_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat3_done_sts_MASK \ + 0x00000008 /* fifo_dfet_txdone_dat3_done_sts[3] */ +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat3_done_sts_SHFT \ + 3 +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat2_done_sts_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat2_done_sts_MASK \ + 0x00000004 /* fifo_dfet_txdone_dat2_done_sts[2] */ +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat2_done_sts_SHFT \ + 2 +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat1_done_sts_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat1_done_sts_MASK \ + 0x00000002 /* fifo_dfet_txdone_dat1_done_sts[1] */ +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat1_done_sts_SHFT \ + 1 +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat0_done_sts_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat0_done_sts_MASK \ + 0x00000001 /* fifo_dfet_txdone_dat0_done_sts[0] */ +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat0_done_sts_SHFT \ + 0 + +/* +* ---HOST_IF_RX_DONE_STS (0x7C025000 + 0XA4)--- +* rx0_packet_done_sts[0] - (W1C) USB/SDIO Rx0 packet done status +* 0 : no rx packet done +* 1 : rx packet send to host interface +* rx1_packet_done_sts[1] - (W1C) USB/SDIO Rx1 packet done status +* 0 : no rx packet done +* 1 : rx packet send to host interface +* Note : All SDIO Packet send to SIDO RX0 port +* RESERVED2[31..2] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_HOST_IF_RX_DONE_STS_rx1_packet_done_sts_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_IF_RX_DONE_STS_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_IF_RX_DONE_STS_rx1_packet_done_sts_MASK \ + 0x00000002 /* rx1_packet_done_sts[1] */ +#define WF_WFDMA_HOST_DMA1_HOST_IF_RX_DONE_STS_rx1_packet_done_sts_SHFT 1 +#define WF_WFDMA_HOST_DMA1_HOST_IF_RX_DONE_STS_rx0_packet_done_sts_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_IF_RX_DONE_STS_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_IF_RX_DONE_STS_rx0_packet_done_sts_MASK \ + 0x00000001 /* rx0_packet_done_sts[0] */ +#define WF_WFDMA_HOST_DMA1_HOST_IF_RX_DONE_STS_rx0_packet_done_sts_SHFT 0 + +/* +* ---CONN_HIF_RST (0x7C025000 + 0x100)--- +* RESERVED0[3..0] - (RO) Reserved bits +* conn_hif_logic_rst_n[4] - (RW) This conn_hif_logic_rst_n would reset wpdma +* logic partial control register, include Tx/Rx ring control. +* Also, conn_hif_logic_rst_n would reset wifi data path, include tx fifo, rx +* fifo, r2x_bridge, axi_mux and other other asynchronous bridge. +* (Note : conn_hif_logic_rst_n would not reset hif_dmashdl logic) +* dmashdl_all_rst_n[5] - (RW) This dmashdl_all_rst_n would reset +* hif_dmashdl_top, include logic and control register. +* RESERVED6[31..6] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_RST_dmashdl_all_rst_n_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_RST_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_RST_dmashdl_all_rst_n_MASK \ + 0x00000020 /* dmashdl_all_rst_n[5] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_RST_dmashdl_all_rst_n_SHFT 5 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_RST_conn_hif_logic_rst_n_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_RST_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_RST_conn_hif_logic_rst_n_MASK \ + 0x00000010 /* conn_hif_logic_rst_n[4] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_RST_conn_hif_logic_rst_n_SHFT 4 + +/* +* ---CONN_HIF_TOP_MISC (0x7C025000 + 0x104)--- +* ahb_mux_2to1_ultra[1..0] - (RW) conn _hif ahb mux ultra +* ahb_mux_2to1_qos_en[2] - (RW) conn_hif ahb mux qos enable +* RESERVED3[4..3] - (RO) Reserved bits +* axi_cg_in_ck_bypass[5] - (RW) axi frequency bridge bus in clock gating bypass +* 0 : enable clock gating function +* 1 : bypass clock gating function +* axi_cg_out_ck_bypass[6] - (RW) axi frequency bridge bus out clock gating +bypass +* 0 : enable clock gating function +* 1 : bypass clock gating function +* RESERVED7[15..7] - (RO) Reserved bits +* pdma_rxring1_immint_en[16] - (RW) PDMA RX Ring 1 Immediate Interrupt Enable +* RESERVED17[31..17] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_pdma_rxring1_immint_en_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_pdma_rxring1_immint_en_MASK \ + 0x00010000 /* pdma_rxring1_immint_en[16] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_pdma_rxring1_immint_en_SHFT 16 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_axi_cg_out_ck_bypass_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_axi_cg_out_ck_bypass_MASK \ + 0x00000040 /* axi_cg_out_ck_bypass[6] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_axi_cg_out_ck_bypass_SHFT 6 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_axi_cg_in_ck_bypass_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_axi_cg_in_ck_bypass_MASK \ + 0x00000020 /* axi_cg_in_ck_bypass[5] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_axi_cg_in_ck_bypass_SHFT 5 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_ahb_mux_2to1_qos_en_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_ahb_mux_2to1_qos_en_MASK \ + 0x00000004 /* ahb_mux_2to1_qos_en[2] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_ahb_mux_2to1_qos_en_SHFT 2 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_ahb_mux_2to1_ultra_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_ahb_mux_2to1_ultra_MASK \ + 0x00000003 /* ahb_mux_2to1_ultra[1..0] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_ahb_mux_2to1_ultra_SHFT 0 + +/* +* ---HOST2MCU_SW_INT_SET (0x7C025000 + 0X108)--- +* host2mcu_sw_int_0_set[0] - (WO) Driver set this bit to generate MCU interrupt +* and 0x5000_0110[0] will be set to 1. +* host2mcu_sw_int_1_set[1] - (WO) Driver set this bit to generate MCU interrupt +* and 0x5000_0110[1] will be set to 1. +* host2mcu_sw_int_2_set[2] - (WO) Driver set this bit to generate MCU interrupt +* and 0x5000_0110[2] will be set to 1. +* host2mcu_sw_int_3_set[3] - (WO) Driver set [0x0_4108] bit[3] to generate MCU +* interrupt and 0x5000_0110[3] will be set to 1. +* host2mcu_sw_int_4_set[4] - (WO) Driver set [0x0_4108] bit[4] to generate MCU +* interrupt and 0x5000_0110[4] will be set to 1. +* host2mcu_sw_int_5_set[5] - (WO) Driver set [0x0_4108] bit[5] to generate MCU +* interrupt and 0x5000_0110[5] will be set to 1. +* host2mcu_sw_int_6_set[6] - (WO) Driver set [0x0_4108] bit[6] to generate MCU +* interrupt and 0x5000_0110[6] will be set to 1. +* host2mcu_sw_int_7_set[7] - (WO) Driver set [0x0_4108] bit[7] to generate MCU +* interrupt and 0x5000_0110[7] will be set to 1. +* RESERVED8[31..8] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_7_set_ADDR \ + WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_7_set_MASK \ + 0x00000080 /* host2mcu_sw_int_7_set[7] */ +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_7_set_SHFT 7 +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_6_set_ADDR \ + WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_6_set_MASK \ + 0x00000040 /* host2mcu_sw_int_6_set[6] */ +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_6_set_SHFT 6 +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_5_set_ADDR \ + WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_5_set_MASK \ + 0x00000020 /* host2mcu_sw_int_5_set[5] */ +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_5_set_SHFT 5 +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_4_set_ADDR \ + WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_4_set_MASK \ + 0x00000010 /* host2mcu_sw_int_4_set[4] */ +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_4_set_SHFT 4 +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_3_set_ADDR \ + WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_3_set_MASK \ + 0x00000008 /* host2mcu_sw_int_3_set[3] */ +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_3_set_SHFT 3 +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_2_set_ADDR \ + WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_2_set_MASK \ + 0x00000004 /* host2mcu_sw_int_2_set[2] */ +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_2_set_SHFT 2 +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_1_set_ADDR \ + WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_1_set_MASK \ + 0x00000002 /* host2mcu_sw_int_1_set[1] */ +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_1_set_SHFT 1 +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_0_set_ADDR \ + WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_0_set_MASK \ + 0x00000001 /* host2mcu_sw_int_0_set[0] */ +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_0_set_SHFT 0 + +/* +* ---MCU2HOST_SW_INT_SET (0x7C025000 + 0x10C)--- +* mcu2host_sw_int_set_0[0] - (WO) Internal CPU writes this register will trigger +* MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[0] to check interrupt status +* mcu2host_sw_int_set_1[1] - (WO) Internal CPU writes this register will trigger +* MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[1] to check interrupt status +* mcu2host_sw_int_set_2[2] - (WO) Internal CPU writes this register will trigger +* MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[2] to check interrupt status +* mcu2host_sw_int_set_3[3] - (WO) Internal CPU writes this register will trigger +* MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[3] to check interrupt status +* mcu2host_sw_int_set_4[4] - (WO) Internal CPU writes this register will trigger +* MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[4] to check interrupt status +* mcu2host_sw_int_set_5[5] - (WO) Internal CPU writes this register will trigger +* MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[5] to check interrupt status +* mcu2host_sw_int_set_6[6] - (WO) Internal CPU writes this register will trigger +* MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[6] to check interrupt status +* mcu2host_sw_int_set_7[7] - (WO) Internal CPU writes this register will trigger +* MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[7] to check interrupt status +* mcu2host_sw_int_set_8[8] - (WO) Internal CPU writes this register will trigger +* MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[0] to check interrupt status +* mcu2host_sw_int_set_9[9] - (WO) Internal CPU writes this register will trigger +* MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[1] to check interrupt status +* mcu2host_sw_int_set_10[10] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[2] to check interrupt status +* mcu2host_sw_int_set_11[11] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[3] to check interrupt status +* mcu2host_sw_int_set_12[12] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[4] to check interrupt status +* mcu2host_sw_int_set_13[13] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[5] to check interrupt status +* mcu2host_sw_int_set_14[14] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[6] to check interrupt status +* mcu2host_sw_int_set_15[15] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[7] to check interrupt status +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_15_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_15_MASK \ + 0x00008000 /* mcu2host_sw_int_set_15[15] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_15_SHFT 15 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_14_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_14_MASK \ + 0x00004000 /* mcu2host_sw_int_set_14[14] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_14_SHFT 14 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_13_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_13_MASK \ + 0x00002000 /* mcu2host_sw_int_set_13[13] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_13_SHFT 13 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_12_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_12_MASK \ + 0x00001000 /* mcu2host_sw_int_set_12[12] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_12_SHFT 12 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_11_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_11_MASK \ + 0x00000800 /* mcu2host_sw_int_set_11[11] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_11_SHFT 11 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_10_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_10_MASK \ + 0x00000400 /* mcu2host_sw_int_set_10[10] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_10_SHFT 10 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_9_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_9_MASK \ + 0x00000200 /* mcu2host_sw_int_set_9[9] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_9_SHFT 9 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_8_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_8_MASK \ + 0x00000100 /* mcu2host_sw_int_set_8[8] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_8_SHFT 8 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_7_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_7_MASK \ + 0x00000080 /* mcu2host_sw_int_set_7[7] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_7_SHFT 7 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_6_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_6_MASK \ + 0x00000040 /* mcu2host_sw_int_set_6[6] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_6_SHFT 6 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_5_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_5_MASK \ + 0x00000020 /* mcu2host_sw_int_set_5[5] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_5_SHFT 5 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_4_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_4_MASK \ + 0x00000010 /* mcu2host_sw_int_set_4[4] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_4_SHFT 4 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_3_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_3_MASK \ + 0x00000008 /* mcu2host_sw_int_set_3[3] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_3_SHFT 3 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_2_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_2_MASK \ + 0x00000004 /* mcu2host_sw_int_set_2[2] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_2_SHFT 2 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_1_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_1_MASK \ + 0x00000002 /* mcu2host_sw_int_set_1[1] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_1_SHFT 1 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_0_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_0_MASK \ + 0x00000001 /* mcu2host_sw_int_set_0[0] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_0_SHFT 0 + +/* +* ---MCU_INT_STA (0x7C025000 + 0X110)--- +* host2mcu_sw_int_sts[7..0] - (W1C) MCU interrupt status, write 1 to clear the +interrupt +* wpdma_tx_timeout_int_sts[8] - (W1C) WPDMA TX dma timeout interrupt stauts, +* write 1 to clear the interrupt +* wpdma_rx_timeout_int_sts[9] - (W1C) WPDMA RX dma timeout interrupt stauts, +* write 1 to clear the interrupt +* wifi_txfifo0_wr_ovf_int_sts[10] - (W1C) conn_hif txfifo erorr detec +* interruptt. It indicate tx-fifo memory write overflow. +* wifi_txfifo1_wr_ovf_int_sts[11] - (W1C) conn_hif txfifo erorr detec +* interruptt. It indicate tx-fifo memory write overflow. +* wifi_rxfifo_wr_ovf_int_sts[12] - (W1C) conn_hif rxfifo erorr detect interrupt. +* It indicate rx-fifo memory write overflow. +* wpdma_tx_dmad_mem_range_err_mcu_int_sts[13] - (W1C) WPDMA tx dma descriptor +* memory range error detection mcu interrupt status +* When user setup WPDMA_TX_DMAD_RNG (not equal to zero), design would check +* tx_dmad address. If address range not correct, it would alarm memory range +* error interrupt +* wpdma_rx_dmad_mem_range_err_mcu_int_sts[14] - (W1C) WPDMA rx dma descriptor +* memory range error detection mcu interrupt status +* When user setup WPDMA_RX_DMAD_RNG (not equal to zero), design would check +* rx_dmad address. If address range not correct, it would alarm memory range +* error interrupt +* wpdma_tx_payload_mem_range_err_mcu_int_sts[15] - (W1C) WPDMA tx payload memory +* range error detection mcu interrupt status +* When user setup WPDMA_TX_PLD_RNG (not equal to zero), design would check +* tx_dma payload address. If address range not correct, it would alarm memory +* range error interrupt +* wpdma_rx_payload_mem_range_err_mcu_int_sts[16] - (W1C) WPDMA rx payload memory +* range error detection mcu interrupt status +* When user setup WPDMA_RX_PLD_RNG (not equal to zero), design would check +* rx_dma payload address. If address range not correct, it would alarm memory +* range error interrupt +* RESERVED17[31..17] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_rx_payload_mem_range_err_mcu_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_rx_payload_mem_range_err_mcu_int_sts_MASK \ + 0x00010000 /* wpdma_rx_payload_mem_range_err_mcu_int_sts[16] */ +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_rx_payload_mem_range_err_mcu_int_sts_SHFT \ + 16 +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_tx_payload_mem_range_err_mcu_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_tx_payload_mem_range_err_mcu_int_sts_MASK \ + 0x00008000 /* wpdma_tx_payload_mem_range_err_mcu_int_sts[15] */ +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_tx_payload_mem_range_err_mcu_int_sts_SHFT \ + 15 +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_rx_dmad_mem_range_err_mcu_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_rx_dmad_mem_range_err_mcu_int_sts_MASK \ + 0x00004000 /* wpdma_rx_dmad_mem_range_err_mcu_int_sts[14] */ +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_rx_dmad_mem_range_err_mcu_int_sts_SHFT \ + 14 +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_tx_dmad_mem_range_err_mcu_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_tx_dmad_mem_range_err_mcu_int_sts_MASK \ + 0x00002000 /* wpdma_tx_dmad_mem_range_err_mcu_int_sts[13] */ +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_tx_dmad_mem_range_err_mcu_int_sts_SHFT \ + 13 +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wifi_rxfifo_wr_ovf_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wifi_rxfifo_wr_ovf_int_sts_MASK \ + 0x00001000 /* wifi_rxfifo_wr_ovf_int_sts[12] */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wifi_rxfifo_wr_ovf_int_sts_SHFT 12 +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wifi_txfifo1_wr_ovf_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wifi_txfifo1_wr_ovf_int_sts_MASK \ + 0x00000800 /* wifi_txfifo1_wr_ovf_int_sts[11] */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wifi_txfifo1_wr_ovf_int_sts_SHFT 11 +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wifi_txfifo0_wr_ovf_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wifi_txfifo0_wr_ovf_int_sts_MASK \ + 0x00000400 /* wifi_txfifo0_wr_ovf_int_sts[10] */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wifi_txfifo0_wr_ovf_int_sts_SHFT 10 +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_rx_timeout_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_rx_timeout_int_sts_MASK \ + 0x00000200 /* wpdma_rx_timeout_int_sts[9] */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_rx_timeout_int_sts_SHFT 9 +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_tx_timeout_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_tx_timeout_int_sts_MASK \ + 0x00000100 /* wpdma_tx_timeout_int_sts[8] */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_tx_timeout_int_sts_SHFT 8 +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_host2mcu_sw_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_host2mcu_sw_int_sts_MASK \ + 0x000000FF /* host2mcu_sw_int_sts[7..0] */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_host2mcu_sw_int_sts_SHFT 0 + +/* +* ---MCU_INT_ENA (0x7C025000 + 0X114)--- +* host2mcu_sw_int_ena[7..0] - (RW) host2mcu interrupt enable +* wpdma_tx_dma_timeout_int_ena[8] - (RW) WPDMA TX error detection interrupt +enable +* wpdma_rx_dma_timeout_int_ena[9] - (RW) WPDMA RX error detection interrupt +enable +* wifi_txfifo0_wr_ovf_int_ena[10] - (RW) conn_hif txfifo erorr detect interrupt +enable. +* wifi_txfifo1_wr_ovf_int_ena[11] - (RW) conn_hif txfifo erorr detect interrupt +enable. +* wifi_rxfifo_wr_ovf_int_ena[12] - (RW) conn_hif rxfifo erorr detect interrupt +enable. +* wpdma_tx_dmad_mem_range_err_mcu_int_ena[13] - (RW) WPDMA tx dma descriptor +* memory range error detection interrupt enable +* wpdma_rx_dmad_mem_range_err_mcu_int_ena[14] - (RW) WPDMA rx dma descriptor +* memory range error detection interrupt enable +* wpdma_tx_payload_mem_range_err_mcu_int_ena[15] - (RW) WPDMA tx payload memory +* range error detection interrupt enable +* wpdma_rx_payload_mem_range_err_mcu_int_ena[16] - (RW) WPDMA rx payload memory +* range error detection interrupt enable +* RESERVED17[31..17] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_rx_payload_mem_range_err_mcu_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_rx_payload_mem_range_err_mcu_int_ena_MASK \ + 0x00010000 /* wpdma_rx_payload_mem_range_err_mcu_int_ena[16] */ +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_rx_payload_mem_range_err_mcu_int_ena_SHFT \ + 16 +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_tx_payload_mem_range_err_mcu_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_tx_payload_mem_range_err_mcu_int_ena_MASK \ + 0x00008000 /* wpdma_tx_payload_mem_range_err_mcu_int_ena[15] */ +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_tx_payload_mem_range_err_mcu_int_ena_SHFT \ + 15 +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_rx_dmad_mem_range_err_mcu_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_rx_dmad_mem_range_err_mcu_int_ena_MASK \ + 0x00004000 /* wpdma_rx_dmad_mem_range_err_mcu_int_ena[14] */ +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_rx_dmad_mem_range_err_mcu_int_ena_SHFT \ + 14 +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_tx_dmad_mem_range_err_mcu_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_tx_dmad_mem_range_err_mcu_int_ena_MASK \ + 0x00002000 /* wpdma_tx_dmad_mem_range_err_mcu_int_ena[13] */ +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_tx_dmad_mem_range_err_mcu_int_ena_SHFT \ + 13 +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wifi_rxfifo_wr_ovf_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wifi_rxfifo_wr_ovf_int_ena_MASK \ + 0x00001000 /* wifi_rxfifo_wr_ovf_int_ena[12] */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wifi_rxfifo_wr_ovf_int_ena_SHFT 12 +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wifi_txfifo1_wr_ovf_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wifi_txfifo1_wr_ovf_int_ena_MASK \ + 0x00000800 /* wifi_txfifo1_wr_ovf_int_ena[11] */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wifi_txfifo1_wr_ovf_int_ena_SHFT 11 +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wifi_txfifo0_wr_ovf_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wifi_txfifo0_wr_ovf_int_ena_MASK \ + 0x00000400 /* wifi_txfifo0_wr_ovf_int_ena[10] */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wifi_txfifo0_wr_ovf_int_ena_SHFT 10 +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_rx_dma_timeout_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_rx_dma_timeout_int_ena_MASK \ + 0x00000200 /* wpdma_rx_dma_timeout_int_ena[9] */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_rx_dma_timeout_int_ena_SHFT 9 +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_tx_dma_timeout_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_tx_dma_timeout_int_ena_MASK \ + 0x00000100 /* wpdma_tx_dma_timeout_int_ena[8] */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_tx_dma_timeout_int_ena_SHFT 8 +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_host2mcu_sw_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_host2mcu_sw_int_ena_MASK \ + 0x000000FF /* host2mcu_sw_int_ena[7..0] */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_host2mcu_sw_int_ena_SHFT 0 + +/* +* ---HOST_INT_STA_EXT (0x7C025000 + 0x118)--- +* RESERVED0[4..0] - (RO) Reserved bits +* tx_done_int_sts_21[5] - (W1C) TX Queue#21 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_22[6] - (W1C) TX Queue#22 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_23[7] - (W1C) TX Queue#23 packet transmit interrupt +* Write 1 to clear the interrupt +* RESERVED8[31..8] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_EXT_tx_done_int_sts_23_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_EXT_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_EXT_tx_done_int_sts_23_MASK \ + 0x00000080 /* tx_done_int_sts_23[7] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_EXT_tx_done_int_sts_23_SHFT 7 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_EXT_tx_done_int_sts_22_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_EXT_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_EXT_tx_done_int_sts_22_MASK \ + 0x00000040 /* tx_done_int_sts_22[6] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_EXT_tx_done_int_sts_22_SHFT 6 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_EXT_tx_done_int_sts_21_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_EXT_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_EXT_tx_done_int_sts_21_MASK \ + 0x00000020 /* tx_done_int_sts_21[5] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_EXT_tx_done_int_sts_21_SHFT 5 + +/* +* ---HOST_INT_ENA_EXT (0x7C025000 + 0X11C)--- +* RESERVED0[4..0] - (RO) Reserved bits +* HOST_TX_DONE_INT_ENA21[5] - (RW) TX Queue#21 packet transmit interrupt +* HOST_TX_DONE_INT_ENA22[6] - (RW) TX Queue#22 packet transmit interrupt +* HOST_TX_DONE_INT_ENA23[7] - (RW) TX Queue#23 packet transmit interrupt +* RESERVED8[31..8] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_EXT_HOST_TX_DONE_INT_ENA23_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_EXT_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_EXT_HOST_TX_DONE_INT_ENA23_MASK \ + 0x00000080 /* HOST_TX_DONE_INT_ENA23[7] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_EXT_HOST_TX_DONE_INT_ENA23_SHFT 7 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_EXT_HOST_TX_DONE_INT_ENA22_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_EXT_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_EXT_HOST_TX_DONE_INT_ENA22_MASK \ + 0x00000040 /* HOST_TX_DONE_INT_ENA22[6] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_EXT_HOST_TX_DONE_INT_ENA22_SHFT 6 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_EXT_HOST_TX_DONE_INT_ENA21_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_EXT_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_EXT_HOST_TX_DONE_INT_ENA21_MASK \ + 0x00000020 /* HOST_TX_DONE_INT_ENA21[5] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_EXT_HOST_TX_DONE_INT_ENA21_SHFT 5 + +/* +* ---CONN_HIF_DUMMY (0x7C025000 + 0x120)--- +* CONN_HIF_DUMMY[31..0] - (RW) Reserved CR, SE will use it for pcie calibration! +*/ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DUMMY_CONN_HIF_DUMMY_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_DUMMY_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DUMMY_CONN_HIF_DUMMY_MASK \ + 0xFFFFFFFF /* CONN_HIF_DUMMY[31..0] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DUMMY_CONN_HIF_DUMMY_SHFT 0 + +/* +* ---WPDMA_DBG_IDX (0x7C025000 + 0x124)--- +* PDMA_DBG_IDX[7..0] - (RW) PDMA debug index +* PDMA_DBG_Enable[8] - (RW) PDMA Debug Enable +* 0: PDMA_DBG_port would has no function +* 1 : PDMA DBG_IDX select PDMA debug flag index +* RESERVED9[31..9] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_DBG_IDX_PDMA_DBG_Enable_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_DBG_IDX_PDMA_DBG_Enable_MASK \ + 0x00000100 /* PDMA_DBG_Enable[8] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_DBG_IDX_PDMA_DBG_Enable_SHFT 8 +#define WF_WFDMA_HOST_DMA1_WPDMA_DBG_IDX_PDMA_DBG_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_DBG_IDX_PDMA_DBG_IDX_MASK \ + 0x000000FF /* PDMA_DBG_IDX[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_DBG_IDX_PDMA_DBG_IDX_SHFT 0 + +/* +* ---WPDMA_DBG_PROBE (0x7C025000 + 0x128)--- +* PDMA_DBG_PROBE[31..0] - (RO) PDMA Debug probe read +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_DBG_PROBE_PDMA_DBG_PROBE_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_DBG_PROBE_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_DBG_PROBE_PDMA_DBG_PROBE_MASK \ + 0xFFFFFFFF /* PDMA_DBG_PROBE[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_DBG_PROBE_PDMA_DBG_PROBE_SHFT 0 + +/* +* ---CONN_HIF_DBG_IDX (0x7C025000 + 0x12C)--- +* conn_hif_dbg_byt0_sel[2..0] - (RW) conn_hif_dbg_byt0_sel : Select +* conn_hif_dbg[7:0] from "pdma_dbg"/"hif_dmashdl_top" +* conn_hif_dbg_byt1_sel[5..3] - (RW) conn_hif_dbg_byt1_sel : Select +* conn_hif_dbg[15:8] from "pdma_dbg"/"hif_dmashdl_top" +* conn_hif_dbg_byt2_sel[8..6] - (RW) conn_hif_dbg_byt2_sel : Select +* conn_hif_dbg[23:16] from "pdma_dbg"/"hif_dmashdl_top" +* conn_hif_dbg_byt3_sel[11..9] - (RW) conn_hif_dbg_byt3_sel : Select +* conn_hif_dbg[31:24] from "pdma_dbg"/"hif_dmashdl_top" +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_conn_hif_dbg_byt3_sel_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_conn_hif_dbg_byt3_sel_MASK \ + 0x00000E00 /* conn_hif_dbg_byt3_sel[11..9] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_conn_hif_dbg_byt3_sel_SHFT 9 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_conn_hif_dbg_byt2_sel_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_conn_hif_dbg_byt2_sel_MASK \ + 0x000001C0 /* conn_hif_dbg_byt2_sel[8..6] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_conn_hif_dbg_byt2_sel_SHFT 6 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_conn_hif_dbg_byt1_sel_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_conn_hif_dbg_byt1_sel_MASK \ + 0x00000038 /* conn_hif_dbg_byt1_sel[5..3] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_conn_hif_dbg_byt1_sel_SHFT 3 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_conn_hif_dbg_byt0_sel_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_conn_hif_dbg_byt0_sel_MASK \ + 0x00000007 /* conn_hif_dbg_byt0_sel[2..0] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_conn_hif_dbg_byt0_sel_SHFT 0 + +/* +* ---CONN_HIF_DBG_PROBE (0x7C025000 + 0x130)--- +* conn_hif_dbg_probe[31..0] - (RO) conn_hif_dbg_probe read +*/ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_PROBE_conn_hif_dbg_probe_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_PROBE_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_PROBE_conn_hif_dbg_probe_MASK \ + 0xFFFFFFFF /* conn_hif_dbg_probe[31..0] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_PROBE_conn_hif_dbg_probe_SHFT 0 + +/* +* ---CONN_HIF_DMASHDL_DBG_PROBE (0x7C025000 + 0x134)--- +* DMASHDL_DBG_PROBE[15..0] - (RO) conn_hif_dmashdl_dbg_probe read +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DMASHDL_DBG_PROBE_DMASHDL_DBG_PROBE_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_DMASHDL_DBG_PROBE_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DMASHDL_DBG_PROBE_DMASHDL_DBG_PROBE_MASK \ + 0x0000FFFF /* DMASHDL_DBG_PROBE[15..0] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DMASHDL_DBG_PROBE_DMASHDL_DBG_PROBE_SHFT 0 + +/* +* ---CONN_HIF_BUSY_STATUS (0x7C025000 + 0x138)--- +* conn_hif_txfifo0_busy[0] - (RO) conn_hif txfifo0 busy status +* 0 : txfifo empty +* 1 : txfifo non empty +* conn_hif_txfifo1_busy[1] - (RO) conn_hif txfifo1 busy status +* 0 : txfifo empty +* 1 : txfifo non empty +* conn_hif_rxfifo_busy[2] - (RO) conn_hif rxfifo busy status +* 0 : rxfifo empty +* 1 : rxfifo non empty +* RESERVED[30..3] - (RO) Reserved CR +* conn_hif_busy[31] - (RO) Over all conn_hif busy status, it was busy summation +* of bit[6] ~ bit[0] status +*/ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_conn_hif_busy_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_conn_hif_busy_MASK \ + 0x80000000 /* conn_hif_busy[31] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_conn_hif_busy_SHFT 31 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_conn_hif_rxfifo_busy_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_conn_hif_rxfifo_busy_MASK \ + 0x00000004 /* conn_hif_rxfifo_busy[2] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_conn_hif_rxfifo_busy_SHFT 2 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_conn_hif_txfifo1_busy_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_conn_hif_txfifo1_busy_MASK \ + 0x00000002 /* conn_hif_txfifo1_busy[1] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_conn_hif_txfifo1_busy_SHFT 1 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_conn_hif_txfifo0_busy_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_conn_hif_txfifo0_busy_MASK \ + 0x00000001 /* conn_hif_txfifo0_busy[0] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_conn_hif_txfifo0_busy_SHFT 0 + +/* +* ---CONN_HIF_BUSY_ENA (0x7C025000 + 0x13c)--- +* conn_hif_txfifo0_busy_enable[0] - (RW) busy enable control +* 0: ignore busy status +* 1: conn_hif_busy would tack care busy status +* conn_hif_txfifo1_busy_enable[1] - (RW) busy enable control +* 0: ignore busy status +* 1: conn_hif_busy would tack care busy status +* conn_hif_rxfifo_busy_enable[2] - (RW) busy enable control +* 0: ignore busy status +* 1: conn_hif_busy would tack care busy status +* axi_mx4to1_w_busy_enable[3] - (RW) busy enable control +* 0: ignore busy status +* 1: conn_hif_busy would tack care busy status +* axi_mx4to1_r_busy_enable[4] - (RW) busy enable control +* 0: ignore busy status +* 1: conn_hif_busy would tack care busy status +* RESERVED[31..5] - (RW) Reserved CR +*/ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_axi_mx4to1_r_busy_enable_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_axi_mx4to1_r_busy_enable_MASK \ + 0x00000010 /* axi_mx4to1_r_busy_enable[4] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_axi_mx4to1_r_busy_enable_SHFT 4 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_axi_mx4to1_w_busy_enable_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_axi_mx4to1_w_busy_enable_MASK \ + 0x00000008 /* axi_mx4to1_w_busy_enable[3] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_axi_mx4to1_w_busy_enable_SHFT 3 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_conn_hif_rxfifo_busy_enable_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_conn_hif_rxfifo_busy_enable_MASK \ + 0x00000004 /* conn_hif_rxfifo_busy_enable[2] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_conn_hif_rxfifo_busy_enable_SHFT 2 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_conn_hif_txfifo1_busy_enable_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_conn_hif_txfifo1_busy_enable_MASK \ + 0x00000002 /* conn_hif_txfifo1_busy_enable[1] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_conn_hif_txfifo1_busy_enable_SHFT 1 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_conn_hif_txfifo0_busy_enable_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_conn_hif_txfifo0_busy_enable_MASK \ + 0x00000001 /* conn_hif_txfifo0_busy_enable[0] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_conn_hif_txfifo0_busy_enable_SHFT 0 + +/* +* ---CONN_HIF_FIFO_TEST_MOD (0x7C025000 + 0x140)--- +* csr_wfdma_loopback_en[0] - (RW) conn_hif fifo loopback enable +* NOTICE : when loopback, OMIT_TX_INFO and OMIT_RX_INFO sould be both set to +1'b1 +* csr_wfdma_loopback_qsel[2..1] - (RW) No USE for (conn_hif fifo loopback packet +* go into Rx-ring number) +* RESERVED3[31..3] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_qsel_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_FIFO_TEST_MOD_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_qsel_MASK \ + 0x00000006 /* csr_wfdma_loopback_qsel[2..1] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_qsel_SHFT 1 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_en_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_FIFO_TEST_MOD_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_en_MASK \ + 0x00000001 /* csr_wfdma_loopback_en[0] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_en_SHFT 0 + +/* +* ---WPDMA2HOST_ERR_INT_STA (0x7C025000 + 0x1E8)--- +* wpdma_tx_timeout_int_sts[0] - (W1C) WPDMA TX error detection interrupt stauts, +* write 1 to clear the interrupt +* wpdma_rx_timeout_int_sts[1] - (W1C) WPDMA RX error detection interrupt stauts, +* write 1 to clear the interrupt +* wpdma_tx_dmad_mem_range_err_int_sts[2] - (W1C) WPDMA tx dma descriptor memory +* range error detection interrupt status +* When user setup WPDMA_TX_DMAD_RNG (not equal to zero), design would check +* tx_dmad address. If address range not correct, it would alarm memory range +* error interrupt +* wpdma_rx_dmad_mem_range_err_int_sts[3] - (W1C) WPDMA rx dma descriptor memory +* range error detection interrupt status +* When user setup WPDMA_RX_DMAD_RNG (not equal to zero), design would check +* rx_dmad address. If address range not correct, it would alarm memory range +* error interrupt +* wpdma_tx_payload_mem_range_err_int_sts[4] - (W1C) WPDMA tx payload memory +* range error detection interrupt status +* When user setup WPDMA_TX_PLD_RNG (not equal to zero), design would check +* tx_dma payload address. If address range not correct, it would alarm memory +* range error interrupt +* wpdma_rx_payload_mem_range_err_int_sts[5] - (W1C) WPDMA rx payload memory +* range error detection interrupt status +* When user setup WPDMA_RX_PLD_RNG (not equal to zero), design would check +* rx_dma payload address. If address range not correct, it would alarm memory +* range error interrupt +* wpdma_axi_bresp_error_int_sts[6] - (W1C) WPDMA AXI master bresp error +* detection interrupt status, check WPDMA_AXI_MST_DBG1 for error information +* wpdma_axi_rresp_error_int_sts[7] - (W1C) WPDMA AXI master rresp error +* detection interrupt status, check WPDMA_AXI_MST_DBG0 for error information +* m0_wr_axi_err_det_int_sts[8] - (W1C) WPDMA AXI write master for RX payload +* error detection interrupt status +* m1_wr_axi_err_det_int_sts[9] - (W1C) WPDMA AXI write master for RX DMAD error +* detection interrupt status +* m2_wr_axi_err_det_int_sts[10] - (W1C) WPDMA AXI write master for TX DMAD error +* detection interrupt status +* m0_rd_axi_err_det_int_sts[11] - (W1C) WPDMA AXI read master for TX payload +* error detection interrupt status +* m1_rd_axi_err_det_int_sts[12] - (W1C) WPDMA AXI read master for RX DMAD error +* detection interrupt status +* m2_rd_axi_err_det_int_sts[13] - (W1C) WPDMA AXI read master for TX DMAD error +* detection interrupt status +* RESERVED14[14] - (RO) Reserved bits +* pf_sram_size_underflow_int_sts[15] - (RO) Prefetch sram overflow error +* interrupt status. This reflect configured prefetch sram is not enough for all +* TX and RX prefetch ring. Prefetch sram size should be greater than (DMAD size +* total of each RING's MAX_CNT) +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_pf_sram_size_underflow_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_pf_sram_size_underflow_int_sts_MASK \ + 0x00008000 /* pf_sram_size_underflow_int_sts[15] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_pf_sram_size_underflow_int_sts_SHFT \ + 15 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_m2_rd_axi_err_det_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_m2_rd_axi_err_det_int_sts_MASK \ + 0x00002000 /* m2_rd_axi_err_det_int_sts[13] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_m2_rd_axi_err_det_int_sts_SHFT \ + 13 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_m1_rd_axi_err_det_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_m1_rd_axi_err_det_int_sts_MASK \ + 0x00001000 /* m1_rd_axi_err_det_int_sts[12] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_m1_rd_axi_err_det_int_sts_SHFT \ + 12 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_m0_rd_axi_err_det_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_m0_rd_axi_err_det_int_sts_MASK \ + 0x00000800 /* m0_rd_axi_err_det_int_sts[11] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_m0_rd_axi_err_det_int_sts_SHFT \ + 11 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_m2_wr_axi_err_det_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_m2_wr_axi_err_det_int_sts_MASK \ + 0x00000400 /* m2_wr_axi_err_det_int_sts[10] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_m2_wr_axi_err_det_int_sts_SHFT \ + 10 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_m1_wr_axi_err_det_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_m1_wr_axi_err_det_int_sts_MASK \ + 0x00000200 /* m1_wr_axi_err_det_int_sts[9] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_m1_wr_axi_err_det_int_sts_SHFT \ + 9 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_m0_wr_axi_err_det_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_m0_wr_axi_err_det_int_sts_MASK \ + 0x00000100 /* m0_wr_axi_err_det_int_sts[8] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_m0_wr_axi_err_det_int_sts_SHFT \ + 8 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_axi_rresp_error_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_axi_rresp_error_int_sts_MASK \ + 0x00000080 /* wpdma_axi_rresp_error_int_sts[7] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_axi_rresp_error_int_sts_SHFT \ + 7 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_axi_bresp_error_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_axi_bresp_error_int_sts_MASK \ + 0x00000040 /* wpdma_axi_bresp_error_int_sts[6] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_axi_bresp_error_int_sts_SHFT \ + 6 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_rx_payload_mem_range_err_int_st\ +s_ADDR \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_rx_payload_mem_range_err_int_st\ +s_MASK \ +0x00000020 /* wpdma_rx_payload_mem_range_err_int_sts[5] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_rx_payload_mem_range_err_int_st\ +s_SHFT \ +5 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_tx_payload_mem_range_err_int_st\ +s_ADDR \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_tx_payload_mem_range_err_int_st\ +s_MASK \ +0x00000010 /* wpdma_tx_payload_mem_range_err_int_sts[4] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_tx_payload_mem_range_err_int_st\ +s_SHFT \ +4 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_rx_dmad_mem_range_err_int_sts_A\ +DDR \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_rx_dmad_mem_range_err_int_sts_M\ +ASK \ +0x00000008 /* wpdma_rx_dmad_mem_range_err_int_sts[3] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_rx_dmad_mem_range_err_int_sts_S\ +HFT \ +3 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_tx_dmad_mem_range_err_int_sts_A\ +DDR \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_tx_dmad_mem_range_err_int_sts_M\ +ASK \ +0x00000004 /* wpdma_tx_dmad_mem_range_err_int_sts[2] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_tx_dmad_mem_range_err_int_sts_S\ +HFT \ +2 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_rx_timeout_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_rx_timeout_int_sts_MASK \ + 0x00000002 /* wpdma_rx_timeout_int_sts[1] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_rx_timeout_int_sts_SHFT \ + 1 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_tx_timeout_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_tx_timeout_int_sts_MASK \ + 0x00000001 /* wpdma_tx_timeout_int_sts[0] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_tx_timeout_int_sts_SHFT \ + 0 + +/* +* ---WPDMA2HOST_ERR_INT_ENA (0x7C025000 + 0x1EC)--- +* wpdma_rx_timeout_int_ena[0] - (RW) WPDMA TX error detection interrupt enable +* wpdma_tx_timeout_int_ena[1] - (RW) WPDMA RX error detection interrupt enable +* wpdma_tx_dmad_mem_range_err_int_ena[2] - (RW) WPDMA tx dma descriptor memory +* range error detection interrupt enable +* wpdma_rx_dmad_mem_range_err_int_ena[3] - (RW) WPDMA rx dma descriptor memory +* range error detection interrupt enable +* wpdma_tx_payload_mem_range_err_int_ena[4] - (RW) WPDMA tx payload memory range +* error detection interrupt enable +* wpdma_rx_payload_mem_range_err_int_ena[5] - (RW) WPDMA rx payload memory range +* error detection interrupt enable +* wpdma_axi_bresp_error_int_ena[6] - (RW) WPDMA AXI master bresp error detection +* interrupt enable +* wpdma_axi_rresp_error_int_ena[7] - (RW) WPDMA AXI master rresp error detection +* interrupt enable +* m0_wr_axi_err_det_int_ena[8] - (RW) WPDMA AXI write master for RX payload +* error detection interrupt enable +* m1_wr_axi_err_det_int_ena[9] - (RW) WPDMA AXI write master for RX DMAD error +* detection interrupt enable +* m2_wr_axi_err_det_int_ena[10] - (RW) WPDMA AXI write master for TX DMAD error +* detection interrupt enable +* m0_rd_axi_err_det_int_ena[11] - (RW) WPDMA AXI read master for TX payload +* error detection interrupt enable +* m1_rd_axi_err_det_int_ena[12] - (RW) WPDMA AXI read master for RX DMAD error +* detection interrupt enable +* m2_rd_axi_err_det_int_ena[13] - (RW) WPDMA AXI read master for TX DMAD error +* detection interrupt enable +* RESERVED14[14] - (RO) Reserved bits +* pf_sram_size_underflow_int_ena[15] - (RW) Prefetch sram overflow error +* interrupt enable +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_pf_sram_size_underflow_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_pf_sram_size_underflow_int_ena_MASK \ + 0x00008000 /* pf_sram_size_underflow_int_ena[15] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_pf_sram_size_underflow_int_ena_SHFT \ + 15 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_m2_rd_axi_err_det_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_m2_rd_axi_err_det_int_ena_MASK \ + 0x00002000 /* m2_rd_axi_err_det_int_ena[13] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_m2_rd_axi_err_det_int_ena_SHFT \ + 13 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_m1_rd_axi_err_det_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_m1_rd_axi_err_det_int_ena_MASK \ + 0x00001000 /* m1_rd_axi_err_det_int_ena[12] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_m1_rd_axi_err_det_int_ena_SHFT \ + 12 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_m0_rd_axi_err_det_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_m0_rd_axi_err_det_int_ena_MASK \ + 0x00000800 /* m0_rd_axi_err_det_int_ena[11] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_m0_rd_axi_err_det_int_ena_SHFT \ + 11 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_m2_wr_axi_err_det_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_m2_wr_axi_err_det_int_ena_MASK \ + 0x00000400 /* m2_wr_axi_err_det_int_ena[10] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_m2_wr_axi_err_det_int_ena_SHFT \ + 10 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_m1_wr_axi_err_det_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_m1_wr_axi_err_det_int_ena_MASK \ + 0x00000200 /* m1_wr_axi_err_det_int_ena[9] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_m1_wr_axi_err_det_int_ena_SHFT \ + 9 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_m0_wr_axi_err_det_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_m0_wr_axi_err_det_int_ena_MASK \ + 0x00000100 /* m0_wr_axi_err_det_int_ena[8] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_m0_wr_axi_err_det_int_ena_SHFT \ + 8 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_axi_rresp_error_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_axi_rresp_error_int_ena_MASK \ + 0x00000080 /* wpdma_axi_rresp_error_int_ena[7] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_axi_rresp_error_int_ena_SHFT \ + 7 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_axi_bresp_error_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_axi_bresp_error_int_ena_MASK \ + 0x00000040 /* wpdma_axi_bresp_error_int_ena[6] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_axi_bresp_error_int_ena_SHFT \ + 6 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_payload_mem_range_err_int_en\ +a_ADDR \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_payload_mem_range_err_int_en\ +a_MASK \ +0x00000020 /* wpdma_rx_payload_mem_range_err_int_ena[5] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_payload_mem_range_err_int_en\ +a_SHFT \ +5 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_payload_mem_range_err_int_en\ +a_ADDR \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_payload_mem_range_err_int_en\ +a_MASK \ +0x00000010 /* wpdma_tx_payload_mem_range_err_int_ena[4] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_payload_mem_range_err_int_en\ +a_SHFT \ +4 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_dmad_mem_range_err_int_ena_A\ +DDR \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_dmad_mem_range_err_int_ena_M\ +ASK \ +0x00000008 /* wpdma_rx_dmad_mem_range_err_int_ena[3] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_dmad_mem_range_err_int_ena_S\ +HFT \ +3 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_dmad_mem_range_err_int_ena_A\ +DDR \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_dmad_mem_range_err_int_ena_M\ +ASK \ +0x00000004 /* wpdma_tx_dmad_mem_range_err_int_ena[2] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_dmad_mem_range_err_int_ena_S\ +HFT \ +2 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_timeout_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_timeout_int_ena_MASK \ + 0x00000002 /* wpdma_tx_timeout_int_ena[1] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_timeout_int_ena_SHFT \ + 1 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_timeout_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_timeout_int_ena_MASK \ + 0x00000001 /* wpdma_rx_timeout_int_ena[0] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_timeout_int_ena_SHFT \ + 0 + +/* +* ---MCU2HOST_SW_INT_STA (0x7C025000 + 0x1F0)--- +* mcu2host_sw_int_0[0] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_1[1] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_2[2] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_3[3] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_4[4] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_5[5] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_6[6] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_7[7] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_8[8] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_9[9] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_10[10] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_11[11] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_12[12] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_13[13] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_14[14] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_15[15] - (W1C) mcu2host interrupt status +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_15_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_15_MASK \ + 0x00008000 /* mcu2host_sw_int_15[15] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_15_SHFT 15 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_14_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_14_MASK \ + 0x00004000 /* mcu2host_sw_int_14[14] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_14_SHFT 14 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_13_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_13_MASK \ + 0x00002000 /* mcu2host_sw_int_13[13] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_13_SHFT 13 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_12_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_12_MASK \ + 0x00001000 /* mcu2host_sw_int_12[12] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_12_SHFT 12 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_11_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_11_MASK \ + 0x00000800 /* mcu2host_sw_int_11[11] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_11_SHFT 11 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_10_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_10_MASK \ + 0x00000400 /* mcu2host_sw_int_10[10] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_10_SHFT 10 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_9_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_9_MASK \ + 0x00000200 /* mcu2host_sw_int_9[9] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_9_SHFT 9 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_8_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_8_MASK \ + 0x00000100 /* mcu2host_sw_int_8[8] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_8_SHFT 8 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_7_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_7_MASK \ + 0x00000080 /* mcu2host_sw_int_7[7] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_7_SHFT 7 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_6_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_6_MASK \ + 0x00000040 /* mcu2host_sw_int_6[6] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_6_SHFT 6 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_5_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_5_MASK \ + 0x00000020 /* mcu2host_sw_int_5[5] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_5_SHFT 5 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_4_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_4_MASK \ + 0x00000010 /* mcu2host_sw_int_4[4] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_4_SHFT 4 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_3_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_3_MASK \ + 0x00000008 /* mcu2host_sw_int_3[3] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_3_SHFT 3 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_2_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_2_MASK \ + 0x00000004 /* mcu2host_sw_int_2[2] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_2_SHFT 2 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_1_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_1_MASK \ + 0x00000002 /* mcu2host_sw_int_1[1] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_1_SHFT 1 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_0_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_0_MASK \ + 0x00000001 /* mcu2host_sw_int_0[0] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_0_SHFT 0 + +/* +* ---MCU2HOST_SW_INT_ENA (0x7C025000 + 0x1F4)--- +* mcu2host_int_ena_0[0] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_1[1] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_2[2] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_3[3] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_4[4] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_5[5] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_6[6] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_7[7] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_8[8] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_9[9] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_10[10] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_11[11] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_12[12] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_13[13] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_14[14] - (RW) MCU2HOST software interrupt interrupt enable +* mcu2host_int_ena_15[15] - (RW) MCU2HOST software interrupt interrupt enable +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_15_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_15_MASK \ + 0x00008000 /* mcu2host_int_ena_15[15] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_15_SHFT 15 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_14_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_14_MASK \ + 0x00004000 /* mcu2host_int_ena_14[14] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_14_SHFT 14 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_13_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_13_MASK \ + 0x00002000 /* mcu2host_int_ena_13[13] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_13_SHFT 13 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_12_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_12_MASK \ + 0x00001000 /* mcu2host_int_ena_12[12] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_12_SHFT 12 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_11_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_11_MASK \ + 0x00000800 /* mcu2host_int_ena_11[11] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_11_SHFT 11 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_10_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_10_MASK \ + 0x00000400 /* mcu2host_int_ena_10[10] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_10_SHFT 10 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_9_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_9_MASK \ + 0x00000200 /* mcu2host_int_ena_9[9] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_9_SHFT 9 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_8_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_8_MASK \ + 0x00000100 /* mcu2host_int_ena_8[8] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_8_SHFT 8 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_7_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_7_MASK \ + 0x00000080 /* mcu2host_int_ena_7[7] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_7_SHFT 7 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_6_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_6_MASK \ + 0x00000040 /* mcu2host_int_ena_6[6] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_6_SHFT 6 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_5_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_5_MASK \ + 0x00000020 /* mcu2host_int_ena_5[5] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_5_SHFT 5 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_4_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_4_MASK \ + 0x00000010 /* mcu2host_int_ena_4[4] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_4_SHFT 4 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_3_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_3_MASK \ + 0x00000008 /* mcu2host_int_ena_3[3] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_3_SHFT 3 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_2_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_2_MASK \ + 0x00000004 /* mcu2host_int_ena_2[2] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_2_SHFT 2 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_1_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_1_MASK \ + 0x00000002 /* mcu2host_int_ena_1[1] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_1_SHFT 1 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_0_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_0_MASK \ + 0x00000001 /* mcu2host_int_ena_0[0] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_0_SHFT 0 + +/* +* ---SUBSYS2HOST_INT_STA (0x7C025000 + 0x1F8)--- +* mac_int_sts_0[0] - (RO) MAC interrupt 0: TBTT interrupt(Check +* wf_int_wakeup_top/hwisr0 [0x820Fc03c]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_1[1] - (RO) MAC interrupt 1: Pre-TBTT interrupt(Check +* wf_int_wakeup_top/hwisr1 [0x820Fc044]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_2[2] - (RO) MAC interrupt 2: TX status interrupt(Check +* wf_int_wakeup_top/hwisr2 [0x820Fc04c]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_3[3] - (RO) MAC interrupt 3: Auto wakeup interrupt (Check +* wf_int_wakeup_top/hwisr3 [0x820Fc054]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_4[4] - (RO) MAC interrupt 4: GP timer interrupt (Check +* wf_int_wakeup_top/hwisr4 [0x820Fc05c]) +* 0 : no interrupt +* 1 : interrupt assert +* RESERVED5[7..5] - (RO) Reserved bits +* conn_hif_on_host_int_sts[8] - (RO) CONN_HIF_ON interrupt enable +* 0 : no conn_hif_on_host_int interrupt +* 1 : conn_hif_on_host_int interrupt assert. User should check conn_hif_on +* (host_csr) interrupt status and clear interrupt. +* conn2ap_sw_irq_sts[9] - (RO) MCUSYS conn2ap_sw_irq status (Check +* conn_mcu_config/EMI_CTL [0x80000150] bit[4:0]) +* 0 : no conn2ap_sw_irq interrupt. +* 1 : conn2ap_sw_irq interrupt assert. User should check mcusys_n9 interrupt +* status and clear interrupt. (conn_mcu_config/EMI_CTL [0x80000150] bit[4:0] != +0) +* RESERVED10[31..10] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_conn2ap_sw_irq_sts_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_conn2ap_sw_irq_sts_MASK \ + 0x00000200 /* conn2ap_sw_irq_sts[9] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_conn2ap_sw_irq_sts_SHFT 9 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_conn_hif_on_host_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_conn_hif_on_host_int_sts_MASK \ + 0x00000100 /* conn_hif_on_host_int_sts[8] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_conn_hif_on_host_int_sts_SHFT 8 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_4_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_4_MASK \ + 0x00000010 /* mac_int_sts_4[4] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_4_SHFT 4 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_3_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_3_MASK \ + 0x00000008 /* mac_int_sts_3[3] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_3_SHFT 3 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_2_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_2_MASK \ + 0x00000004 /* mac_int_sts_2[2] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_2_SHFT 2 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_1_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_1_MASK \ + 0x00000002 /* mac_int_sts_1[1] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_1_SHFT 1 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_0_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_0_MASK \ + 0x00000001 /* mac_int_sts_0[0] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_0_SHFT 0 + +/* +* ---SUBSYS2HOST_INT_ENA (0x7C025000 + 0x1FC)--- +* mac_int_ena_0[0] - (RW) MAC interrupt enable +* mac_int_ena_1[1] - (RW) MAC interrupt enable +* mac_int_ena_2[2] - (RW) MAC interrupt enable +* mac_int_ena_3[3] - (RW) MAC interrupt enable +* mac_int_ena_4[4] - (RW) MAC interrupt enable +* RESERVED5[7..5] - (RO) Reserved bits +* conn_hif_on_host_int_ena[8] - (RW) CONN_HIF_ON interrupt enable +* conn2ap_sw_irq_ena[9] - (RW) MCUSYS conn2ap_sw_irq enable +* RESERVED10[31..10] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_conn2ap_sw_irq_ena_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_conn2ap_sw_irq_ena_MASK \ + 0x00000200 /* conn2ap_sw_irq_ena[9] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_conn2ap_sw_irq_ena_SHFT 9 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_conn_hif_on_host_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_conn_hif_on_host_int_ena_MASK \ + 0x00000100 /* conn_hif_on_host_int_ena[8] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_conn_hif_on_host_int_ena_SHFT 8 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_4_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_4_MASK \ + 0x00000010 /* mac_int_ena_4[4] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_4_SHFT 4 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_3_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_3_MASK \ + 0x00000008 /* mac_int_ena_3[3] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_3_SHFT 3 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_2_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_2_MASK \ + 0x00000004 /* mac_int_ena_2[2] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_2_SHFT 2 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_1_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_1_MASK \ + 0x00000002 /* mac_int_ena_1[1] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_1_SHFT 1 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_0_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_0_MASK \ + 0x00000001 /* mac_int_ena_0[0] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_0_SHFT 0 + +/* +* ---HOST_INT_STA (0x7C025000 + 0x200)--- +* rx_done_int_sts_0[0] - (W1C) RX Queue#0 packet receive interrupt +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* rx_done_int_sts_1[1] - (W1C) RX Queue#1 packet receive interrupt +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* rx_done_int_sts_2[2] - (W1C) RX Queue#2 packet receive interrupt +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* rx_done_int_sts_3[3] - (W1C) RX Queue#3 packet receive interrupt +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* tx_done_int_sts_0[4] - (W1C) TX Queue#0 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_1[5] - (W1C) TX Queue#1 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_2[6] - (W1C) TX Queue#2 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_3[7] - (W1C) TX Queue#3 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_4[8] - (W1C) TX Queue#4 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_5[9] - (W1C) TX Queue#5 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_6[10] - (W1C) TX Queue#6 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_7[11] - (W1C) TX Queue#7 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_8[12] - (W1C) TX Queue#8 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_9[13] - (W1C) TX Queue#9 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_10[14] - (W1C) TX Queue#10 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_11[15] - (W1C) TX Queue#11 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_12[16] - (W1C) TX Queue#12 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_13[17] - (W1C) TX Queue#13 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_14[18] - (W1C) TX Queue#14 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_15[19] - (W1C) TX Queue#15 packet transmit interrupt +* Write 1 to clear the interrupt +* rx_coherent_int_sts[20] - (W1C) RX_DMA finds data coherent event when checking +* ddone bit +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* tx_coherent_int_sts[21] - (W1C) TX_DMA finds data coherent event when checking +* ddone bit +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* RESERVED[23..22] - (RO) reserved, originally used for delayed interrupt of +* legacy TX/RX done +* wpdma2host_err_int_sts[24] - (RO) wpdma interrupt overall status +* User should should check WPDMA_ERR_INT_STA for each wpdma error interrupt +status +* Host could read [0x0_41E8] to check indivisual wpdma2host_error interrupt +status +* tx_done_int_sts_20[25] - (W1C) TX Queue#20 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_16[26] - (W1C) TX Queue#16 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_17[27] - (W1C) TX Queue#17 packet transmit interrupt +* Write 1 to clear the interrupt +* subsys_int_sts[28] - (RO) subsys interrupt overall status +* User should should check SUBSYS2HOST_INT_STA for each interrupt status +* Host could read [0x0_41F8] to check indivisual subsys hw interrupt status +* mcu2host_sw_int_sts[29] - (RO) subsys interrupt overall status +* User should should check SUBSYS2HOST_INT_STA for each interrupt status +* Host could read [0x0_41F8] to check indivisual subsys hw interrupt status +* tx_done_int_sts_18[30] - (W1C) TX Queue#18 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_19[31] - (W1C) TX Queue#19 packet transmit interrupt +* Write 1 to clear the interrupt +*/ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_19_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_19_MASK \ + 0x80000000 /* tx_done_int_sts_19[31] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_19_SHFT 31 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_18_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_18_MASK \ + 0x40000000 /* tx_done_int_sts_18[30] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_18_SHFT 30 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_mcu2host_sw_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_mcu2host_sw_int_sts_MASK \ + 0x20000000 /* mcu2host_sw_int_sts[29] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_mcu2host_sw_int_sts_SHFT 29 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_subsys_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_subsys_int_sts_MASK \ + 0x10000000 /* subsys_int_sts[28] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_subsys_int_sts_SHFT 28 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_17_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_17_MASK \ + 0x08000000 /* tx_done_int_sts_17[27] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_17_SHFT 27 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_16_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_16_MASK \ + 0x04000000 /* tx_done_int_sts_16[26] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_16_SHFT 26 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_20_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_20_MASK \ + 0x02000000 /* tx_done_int_sts_20[25] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_20_SHFT 25 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_wpdma2host_err_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_wpdma2host_err_int_sts_MASK \ + 0x01000000 /* wpdma2host_err_int_sts[24] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_wpdma2host_err_int_sts_SHFT 24 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_coherent_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_coherent_int_sts_MASK \ + 0x00200000 /* tx_coherent_int_sts[21] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_coherent_int_sts_SHFT 21 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_coherent_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_coherent_int_sts_MASK \ + 0x00100000 /* rx_coherent_int_sts[20] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_coherent_int_sts_SHFT 20 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_15_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_15_MASK \ + 0x00080000 /* tx_done_int_sts_15[19] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_15_SHFT 19 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_14_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_14_MASK \ + 0x00040000 /* tx_done_int_sts_14[18] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_14_SHFT 18 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_13_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_13_MASK \ + 0x00020000 /* tx_done_int_sts_13[17] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_13_SHFT 17 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_12_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_12_MASK \ + 0x00010000 /* tx_done_int_sts_12[16] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_12_SHFT 16 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_11_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_11_MASK \ + 0x00008000 /* tx_done_int_sts_11[15] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_11_SHFT 15 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_10_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_10_MASK \ + 0x00004000 /* tx_done_int_sts_10[14] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_10_SHFT 14 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_9_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_9_MASK \ + 0x00002000 /* tx_done_int_sts_9[13] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_9_SHFT 13 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_8_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_8_MASK \ + 0x00001000 /* tx_done_int_sts_8[12] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_8_SHFT 12 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_7_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_7_MASK \ + 0x00000800 /* tx_done_int_sts_7[11] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_7_SHFT 11 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_6_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_6_MASK \ + 0x00000400 /* tx_done_int_sts_6[10] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_6_SHFT 10 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_5_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_5_MASK \ + 0x00000200 /* tx_done_int_sts_5[9] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_5_SHFT 9 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_4_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_4_MASK \ + 0x00000100 /* tx_done_int_sts_4[8] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_4_SHFT 8 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_3_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_3_MASK \ + 0x00000080 /* tx_done_int_sts_3[7] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_3_SHFT 7 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_2_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_2_MASK \ + 0x00000040 /* tx_done_int_sts_2[6] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_2_SHFT 6 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_1_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_1_MASK \ + 0x00000020 /* tx_done_int_sts_1[5] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_1_SHFT 5 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_0_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_0_MASK \ + 0x00000010 /* tx_done_int_sts_0[4] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_0_SHFT 4 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_done_int_sts_3_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_done_int_sts_3_MASK \ + 0x00000008 /* rx_done_int_sts_3[3] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_done_int_sts_3_SHFT 3 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_done_int_sts_2_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_done_int_sts_2_MASK \ + 0x00000004 /* rx_done_int_sts_2[2] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_done_int_sts_2_SHFT 2 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_done_int_sts_1_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_done_int_sts_1_MASK \ + 0x00000002 /* rx_done_int_sts_1[1] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_done_int_sts_1_SHFT 1 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_done_int_sts_0_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_done_int_sts_0_MASK \ + 0x00000001 /* rx_done_int_sts_0[0] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_done_int_sts_0_SHFT 0 + +/* +* ---HOST_INT_ENA (0x7C025000 + 0X204)--- +* HOST_RX_DONE_INT_ENA0[0] - (RW) RX Queue#0 packet receive interrupt +* HOST_RX_DONE_INT_ENA1[1] - (RW) RX Queue#1 packet receive interrupt +* HOST_RX_DONE_INT_ENA2[2] - (RW) RX Queue#2 packet receive interrupt +* HOST_RX_DONE_INT_ENA3[3] - (RW) RX Queue#3 packet receive interrupt +* HOST_TX_DONE_INT_ENA0[4] - (RW) TX Queue#0 packet transmit interrupt +* HOST_TX_DONE_INT_ENA1[5] - (RW) TX Queue#1 packet transmit interrupt +* HOST_TX_DONE_INT_ENA2[6] - (RW) TX Queue#2 packet transmit interrupt +* HOST_TX_DONE_INT_ENA3[7] - (RW) TX Queue#3 packet transmit interrupt +* HOST_TX_DONE_INT_ENA4[8] - (RW) TX Queue#4 packet transmit interrupt +* HOST_TX_DONE_INT_ENA5[9] - (RW) TX Queue#5 packet transmit interrupt +* HOST_TX_DONE_INT_ENA6[10] - (RW) TX Queue#6 packet transmit interrupt +* HOST_TX_DONE_INT_ENA7[11] - (RW) TX Queue#7 packet transmit interrupt +* HOST_TX_DONE_INT_ENA8[12] - (RW) TX Queue#8 packet transmit interrupt +* HOST_TX_DONE_INT_ENA9[13] - (RW) TX Queue#9 packet transmit interrupt +* HOST_TX_DONE_INT_ENA10[14] - (RW) TX Queue#10 packet transmit interrupt +* HOST_TX_DONE_INT_ENA11[15] - (RW) TX Queue#11 packet transmit interrupt +* HOST_TX_DONE_INT_ENA12[16] - (RW) TX Queue#12 packet transmit interrupt +* HOST_TX_DONE_INT_ENA13[17] - (RW) TX Queue#13 packet transmit interrupt +* HOST_TX_DONE_INT_ENA14[18] - (RW) TX Queue#14 packet transmit interrupt +* HOST_TX_DONE_INT_ENA15[19] - (RW) TX Queue#15 packet transmit interrupt +* HOST_RX_COHERENT_EN[20] - (RW) Enable for RX_DMA data coherent interrupt +* HOST_TX_COHERENT_EN[21] - (RW) Enable for TX_DMA data coherent interrupt +* RESERVED[23..22] - (RO) reserved, originally used for delayed interrupt of +* legacy TX/RX done +* wpdma2host_err_int_ena[24] - (RW) Enable bit of wpdma2host_err_int +* HOST_TX_DONE_INT_ENA20[25] - (RW) TX Queue#20 packet transmit interrupt +* HOST_TX_DONE_INT_ENA16[26] - (RW) TX Queue#16 packet transmit interrupt +* HOST_TX_DONE_INT_ENA17[27] - (RW) TX Queue#17 packet transmit interrupt +* subsys_int_ena[28] - (RW) Enable bit of subsys_int +* mcu2host_sw_int_ena[29] - (RW) Enable bit of mcu2host_sw_int +* HOST_TX_DONE_INT_ENA18[30] - (RW) TX Queue#18 packet transmit interrupt +* HOST_TX_DONE_INT_ENA19[31] - (RW) TX Queue#19 packet transmit interrupt +*/ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA19_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA19_MASK \ + 0x80000000 /* HOST_TX_DONE_INT_ENA19[31] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA19_SHFT 31 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA18_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA18_MASK \ + 0x40000000 /* HOST_TX_DONE_INT_ENA18[30] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA18_SHFT 30 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_mcu2host_sw_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_mcu2host_sw_int_ena_MASK \ + 0x20000000 /* mcu2host_sw_int_ena[29] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_mcu2host_sw_int_ena_SHFT 29 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_subsys_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_subsys_int_ena_MASK \ + 0x10000000 /* subsys_int_ena[28] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_subsys_int_ena_SHFT 28 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA17_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA17_MASK \ + 0x08000000 /* HOST_TX_DONE_INT_ENA17[27] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA17_SHFT 27 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA16_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA16_MASK \ + 0x04000000 /* HOST_TX_DONE_INT_ENA16[26] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA16_SHFT 26 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA20_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA20_MASK \ + 0x02000000 /* HOST_TX_DONE_INT_ENA20[25] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA20_SHFT 25 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_wpdma2host_err_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_wpdma2host_err_int_ena_MASK \ + 0x01000000 /* wpdma2host_err_int_ena[24] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_wpdma2host_err_int_ena_SHFT 24 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_COHERENT_EN_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_COHERENT_EN_MASK \ + 0x00200000 /* HOST_TX_COHERENT_EN[21] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_COHERENT_EN_SHFT 21 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_COHERENT_EN_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_COHERENT_EN_MASK \ + 0x00100000 /* HOST_RX_COHERENT_EN[20] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_COHERENT_EN_SHFT 20 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA15_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA15_MASK \ + 0x00080000 /* HOST_TX_DONE_INT_ENA15[19] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA15_SHFT 19 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA14_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA14_MASK \ + 0x00040000 /* HOST_TX_DONE_INT_ENA14[18] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA14_SHFT 18 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA13_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA13_MASK \ + 0x00020000 /* HOST_TX_DONE_INT_ENA13[17] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA13_SHFT 17 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA12_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA12_MASK \ + 0x00010000 /* HOST_TX_DONE_INT_ENA12[16] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA12_SHFT 16 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA11_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA11_MASK \ + 0x00008000 /* HOST_TX_DONE_INT_ENA11[15] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA11_SHFT 15 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA10_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA10_MASK \ + 0x00004000 /* HOST_TX_DONE_INT_ENA10[14] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA10_SHFT 14 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA9_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA9_MASK \ + 0x00002000 /* HOST_TX_DONE_INT_ENA9[13] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA9_SHFT 13 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA8_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA8_MASK \ + 0x00001000 /* HOST_TX_DONE_INT_ENA8[12] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA8_SHFT 12 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA7_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA7_MASK \ + 0x00000800 /* HOST_TX_DONE_INT_ENA7[11] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA7_SHFT 11 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA6_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA6_MASK \ + 0x00000400 /* HOST_TX_DONE_INT_ENA6[10] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA6_SHFT 10 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA5_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA5_MASK \ + 0x00000200 /* HOST_TX_DONE_INT_ENA5[9] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA5_SHFT 9 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA4_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA4_MASK \ + 0x00000100 /* HOST_TX_DONE_INT_ENA4[8] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA4_SHFT 8 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA3_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA3_MASK \ + 0x00000080 /* HOST_TX_DONE_INT_ENA3[7] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA3_SHFT 7 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA2_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA2_MASK \ + 0x00000040 /* HOST_TX_DONE_INT_ENA2[6] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA2_SHFT 6 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA1_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA1_MASK \ + 0x00000020 /* HOST_TX_DONE_INT_ENA1[5] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA1_SHFT 5 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA0_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA0_MASK \ + 0x00000010 /* HOST_TX_DONE_INT_ENA0[4] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA0_SHFT 4 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_DONE_INT_ENA3_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_DONE_INT_ENA3_MASK \ + 0x00000008 /* HOST_RX_DONE_INT_ENA3[3] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_DONE_INT_ENA3_SHFT 3 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_DONE_INT_ENA2_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_DONE_INT_ENA2_MASK \ + 0x00000004 /* HOST_RX_DONE_INT_ENA2[2] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_DONE_INT_ENA2_SHFT 2 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_DONE_INT_ENA1_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_DONE_INT_ENA1_MASK \ + 0x00000002 /* HOST_RX_DONE_INT_ENA1[1] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_DONE_INT_ENA1_SHFT 1 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_DONE_INT_ENA0_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_DONE_INT_ENA0_MASK \ + 0x00000001 /* HOST_RX_DONE_INT_ENA0[0] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_DONE_INT_ENA0_SHFT 0 + +/* +* ---WPDMA_GLO_CFG (0x7C025000 + 0x208)--- +* TX_DMA_EN[0] - (RW) TX_DMA Enable +* 1: Enable TX_DMA, MUST wait until all prefetch rings' +* MAX_CNT(WPDMA_T(R)X_RING*_EXT_CTRL) of DMA including neighbor DMA have been +* configured successfully +* 0: Disable TX_DMA +* TX_DMA_BUSY[1] - (RO) TX_DMA Busy indicator +* 1: TX_DMA is busy +* 0: TX_DMA is not busy +* RX_DMA_EN[2] - (RW) RX_DMA Enable +* 1: Enable RX_DMA, MUST wait until all prefetch rings' +* MAX_CNT(WPDMA_T(R)X_RING*_EXT_CTRL) of DMA including neighbor DMA have been +* configured successfully +* 0: Disable RX_DMA +* RX_DMA_BUSY[3] - (RO) RX_DMA Busy indicator +* 1: RX_DMA is busy +* 0: RX_DMA is not busy +* PDMA_BT_SIZE[5..4] - (RW) Define the burst size of WPDMA +* 2'h0 : 4 DWORD (16bytes) +* 2'h1 : 8 DWORD (32 bytes) +* 2'h2 : 16 DWORD (64 bytes) +* 2'h3 : 32 DWORD (128 bytes) +* TX_WB_DDONE[6] - (RW) 1'b1 : TX engine will wait to assert IRQ util whole TX +* dmad has been fully written into AXI bus which represents HOST memory, 1'b0 : +* TX engine will assert IRQ once TX dmad write-back request have been ACKed +* BIG_ENDIAN[7] - (RW) The endian mode selection. DMA applies the endian rule to +* convert payload and TX/RX information. DMA won't apply endian rule to register +* or descriptor. +* 1: big endian. +* 0: little endian. +* DMAD_32B_EN[8] - (RW) DMA Descriptor 32-byte Enable +* 0: The size of descriptors is set to 16-byte +* 1: The size of descriptors is set to 32-byte +* FW_DWLD_Bypass_dmashdl[9] - (RW) No USE for (APSOC/PCIE) +* For firmware download packet, driver shold using tx-ring16 to download packet +* and set this bit to bypass dmashdl resource control. +* After firmware download finish, driver should clear this bit. +* After all, tx-ring16 could be used for normal data operation. +(USB) +* For USB test_mode, user could set this bit to bypass dmashdl with all endpoint +* CSR_WFDMA_DUMMY_REG[10] - (RW) dummy CR for use if ECO needed +* CSR_AXI_BUFRDY_BYP[11] - (RW) to disable read data fifo available checking +* before issuing next AXI read request +* FIFO_LITTLE_ENDIAN[12] - (RW) Determines the endianness of the FIFO side +* 0: Big-endian +* 1: Little-endian +* CSR_RX_WB_DDONE[13] - (RW) 1'b1 : RX engine will wait to assert IRQ util whole +* RX dmad has been fully written into AXI bus which represents HOST memory, 1'b0 +* : RX engine will assert IRQ once RX dmad write-back request have been ACKed +* CSR_PP_HIF_TXP_ACTIVE_EN[14] - (RW) 1'b1 : enable legacy pp_hif_txp_active +* function to lock tx engine for favor TXP transmit requested directly from PP, +* other pdma TX rings request will be masked until pp_hif_txp_active is +deasserted +* 1'b0 : disable legacy pp_hif_txp_active function, use latest TX source QoS +* design to change throttler settings to favor TXP transmit! +* CSR_DISP_BASE_PTR_CHAIN_EN[15] - (RW) Enable prefet sram ring address +* arrangement by hardware chain structure(DMA#N TX ring group -> DMA#N RX ring +* group -> DMA#M TX ring group -> DMA#M RX ring group and son on). If not +* enabled, firmware need to program DISP_BASE_PTR of WPDMA_T(R)X_RING*_EXT_CTRL +instead!! +* CSR_LBK_RX_Q_SEL[17..16] - (RW) loopback data from TXFIFO will be direct to +* this RX ring when CSR_LBK_RX_Q_SEL_EN in loopback mode, valid bit-width is +* equal to RX_RING_WIDTH which can be calculated from WPDMA_INFO 0x284[15:8] +RX_RING_NUMBER +* RESERVED18[19..18] - (RO) Reserved bits +* CSR_LBK_RX_Q_SEL_EN[20] - (RW) Force configured CSR_LBK_RX_Q_SEL to receive +* loopback data from TXFIFO +* RESERVED21[23..21] - (RO) Reserved bits +* CSR_SW_RST[24] - (RO) SW reset all designs (To be tested for SER in the +future) +* FORCE_TX_EOF[25] - (RW) Force to send an eof after PDMA being reset (for +Packet_Processor) +* 0: Disabled +* 1: Enabled +* PDMA_ADDR_EXT_EN[26] - (RW) No Fnction for now!! For PDMA Address 32bits +* extension. When this design option was enable. PDMA would change Tx/Rx +* descriptor format for address extension. +* 0 : PDMA 32bits address +* 1 : PDMA Tx descirptor DW3 (TXINFO) would used to extend address +* PDMA Rx descirpt DW2 (Reserved) would used to extend address. +* OMIT_RX_INFO[27] - (RW) For loopback mode, set to 1'b1. +* For normal wifi data operation. User should not set this option and should +* keep 1'b0 because UMAC will always add extra QW for checksum after received +* packet's laster QW +* VERY IMPORTANT : for cpu_dma0/1 where CR resides in 0x5100_0xxx, OMIT_RX_INFO +* MUST be set to 1'b1 +* Omit rx_info of all RX packets +* 0: All the PX packets should end with a rx_info +* 1: All the PX packets should NOT end with a rx_info but an eof +* OMIT_TX_INFO[28] - (RW) For loopback mode, set to 1'b1. +* For normal wifi data operation. User should set this option to +* Omit tx_info of all TX packets because UMAC design not support TXINFO +* 0: The tx_info in DMAD will be sent at the beginning +* 1: The tx_info in DMAD will NOT be sent at the beginning +* BYTE_SWAP[29] - (RW) Byte Swapping for TX/RX DMAD +* 0: Not to swap (Endian of DMAD unchanged) +* 1: Swap (Endian of DMAD reversed) +* CLK_GATE_DIS[30] - (RW) PDMA Clock Gated Function Disable +* 0: normal function +* 1: disable clock gated function +* RX_2B_OFFSET[31] - (RW) RX PBF 2-byte Offset +* 1: Skip the first two bytes of the RX PBF +* 0: Not to skip the first two bytes of the RX PBF +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_RX_2B_OFFSET_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_RX_2B_OFFSET_MASK \ + 0x80000000 /* RX_2B_OFFSET[31] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_RX_2B_OFFSET_SHFT 31 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CLK_GATE_DIS_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CLK_GATE_DIS_MASK \ + 0x40000000 /* CLK_GATE_DIS[30] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CLK_GATE_DIS_SHFT 30 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_BYTE_SWAP_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_BYTE_SWAP_MASK \ + 0x20000000 /* BYTE_SWAP[29] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_BYTE_SWAP_SHFT 29 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_OMIT_TX_INFO_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_OMIT_TX_INFO_MASK \ + 0x10000000 /* OMIT_TX_INFO[28] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_OMIT_TX_INFO_SHFT 28 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_OMIT_RX_INFO_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_OMIT_RX_INFO_MASK \ + 0x08000000 /* OMIT_RX_INFO[27] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_OMIT_RX_INFO_SHFT 27 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_PDMA_ADDR_EXT_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_PDMA_ADDR_EXT_EN_MASK \ + 0x04000000 /* PDMA_ADDR_EXT_EN[26] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_PDMA_ADDR_EXT_EN_SHFT 26 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_FORCE_TX_EOF_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_FORCE_TX_EOF_MASK \ + 0x02000000 /* FORCE_TX_EOF[25] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_FORCE_TX_EOF_SHFT 25 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_SW_RST_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_SW_RST_MASK \ + 0x01000000 /* CSR_SW_RST[24] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_SW_RST_SHFT 24 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_EN_MASK \ + 0x00100000 /* CSR_LBK_RX_Q_SEL_EN[20] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_EN_SHFT 20 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_MASK \ + 0x00030000 /* CSR_LBK_RX_Q_SEL[17..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN_MASK \ + 0x00008000 /* CSR_DISP_BASE_PTR_CHAIN_EN[15] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN_SHFT 15 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_PP_HIF_TXP_ACTIVE_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_PP_HIF_TXP_ACTIVE_EN_MASK \ + 0x00004000 /* CSR_PP_HIF_TXP_ACTIVE_EN[14] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_PP_HIF_TXP_ACTIVE_EN_SHFT 14 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_RX_WB_DDONE_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_RX_WB_DDONE_MASK \ + 0x00002000 /* CSR_RX_WB_DDONE[13] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_RX_WB_DDONE_SHFT 13 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN_MASK \ + 0x00001000 /* FIFO_LITTLE_ENDIAN[12] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN_SHFT 12 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_AXI_BUFRDY_BYP_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_AXI_BUFRDY_BYP_MASK \ + 0x00000800 /* CSR_AXI_BUFRDY_BYP[11] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_AXI_BUFRDY_BYP_SHFT 11 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_WFDMA_DUMMY_REG_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_WFDMA_DUMMY_REG_MASK \ + 0x00000400 /* CSR_WFDMA_DUMMY_REG[10] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_WFDMA_DUMMY_REG_SHFT 10 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_FW_DWLD_Bypass_dmashdl_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_FW_DWLD_Bypass_dmashdl_MASK \ + 0x00000200 /* FW_DWLD_Bypass_dmashdl[9] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_FW_DWLD_Bypass_dmashdl_SHFT 9 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_DMAD_32B_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_DMAD_32B_EN_MASK \ + 0x00000100 /* DMAD_32B_EN[8] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_DMAD_32B_EN_SHFT 8 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_BIG_ENDIAN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_BIG_ENDIAN_MASK \ + 0x00000080 /* BIG_ENDIAN[7] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_BIG_ENDIAN_SHFT 7 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_TX_WB_DDONE_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_TX_WB_DDONE_MASK \ + 0x00000040 /* TX_WB_DDONE[6] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_TX_WB_DDONE_SHFT 6 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_PDMA_BT_SIZE_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_PDMA_BT_SIZE_MASK \ + 0x00000030 /* PDMA_BT_SIZE[5..4] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_PDMA_BT_SIZE_SHFT 4 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_RX_DMA_BUSY_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_RX_DMA_BUSY_MASK \ + 0x00000008 /* RX_DMA_BUSY[3] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_RX_DMA_BUSY_SHFT 3 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_RX_DMA_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_RX_DMA_EN_MASK \ + 0x00000004 /* RX_DMA_EN[2] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_RX_DMA_EN_SHFT 2 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_TX_DMA_BUSY_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_TX_DMA_BUSY_MASK \ + 0x00000002 /* TX_DMA_BUSY[1] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_TX_DMA_BUSY_SHFT 1 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_TX_DMA_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_TX_DMA_EN_MASK \ + 0x00000001 /* TX_DMA_EN[0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_TX_DMA_EN_SHFT 0 + +/* +* ---WPDMA_RST_DTX_PTR (0x7C025000 + 0x20C)--- +* RST_DTX_IDX0[0] - (WO) Write 1 to reset to TX_DMATX_IDX0 to 0 +* RST_DTX_IDX1[1] - (WO) Write 1 to reset to TX_DMATX_IDX1 to 0 +* RST_DTX_IDX2[2] - (WO) Write 1 to reset to TX_DMATX_IDX2 to 0 +* RST_DTX_IDX3[3] - (WO) Write 1 to reset to TX_DMATX_IDX3 to 0 +* RST_DTX_IDX4[4] - (WO) Write 1 to reset to TX_DMATX_IDX4 to 0 +* RST_DTX_IDX5[5] - (WO) Write 1 to reset to TX_DMATX_IDX5 to 0 +* RST_DTX_IDX6[6] - (WO) Write 1 to reset to TX_DMATX_IDX6 to 0 +* RST_DTX_IDX7[7] - (WO) Write 1 to reset to TX_DMATX_IDX7 to 0 +* RST_DTX_IDX8[8] - (WO) Write 1 to reset to TX_DMATX_IDX8 to 0 +* RST_DTX_IDX9[9] - (WO) Write 1 to reset to TX_DMATX_IDX9 to 0 +* RST_DTX_IDX10[10] - (WO) Write 1 to reset to TX_DMATX_IDX10 to 0 +* RST_DTX_IDX11[11] - (WO) Write 1 to reset to TX_DMATX_IDX11 to 0 +* RST_DTX_IDX12[12] - (WO) Write 1 to reset to TX_DMATX_IDX12 to 0 +* RST_DTX_IDX13[13] - (WO) Write 1 to reset to TX_DMATX_IDX13 to 0 +* RST_DTX_IDX14[14] - (WO) Write 1 to reset to TX_DMATX_IDX14 to 0 +* RST_DTX_IDX15[15] - (WO) Write 1 to reset to TX_DMATX_IDX15 to 0 +* RST_DTX_IDX16[16] - (WO) Write 1 to reset to TX_DMATX_IDX16 to 0 +* RST_DTX_IDX17[17] - (WO) Write 1 to reset to TX_DMATX_IDX17 to 0 +* RST_DTX_IDX18[18] - (WO) Write 1 to reset to TX_DMATX_IDX18 to 0 +* RST_DTX_IDX19[19] - (WO) Write 1 to reset to TX_DMATX_IDX19 to 0 +* RESERVED[31..20] - (WO) Reserved +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX19_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX19_MASK \ + 0x00080000 /* RST_DTX_IDX19[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX19_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX18_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX18_MASK \ + 0x00040000 /* RST_DTX_IDX18[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX18_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX17_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX17_MASK \ + 0x00020000 /* RST_DTX_IDX17[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX17_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX16_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX16_MASK \ + 0x00010000 /* RST_DTX_IDX16[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX16_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX15_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX15_MASK \ + 0x00008000 /* RST_DTX_IDX15[15] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX15_SHFT 15 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX14_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX14_MASK \ + 0x00004000 /* RST_DTX_IDX14[14] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX14_SHFT 14 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX13_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX13_MASK \ + 0x00002000 /* RST_DTX_IDX13[13] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX13_SHFT 13 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX12_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX12_MASK \ + 0x00001000 /* RST_DTX_IDX12[12] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX12_SHFT 12 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX11_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX11_MASK \ + 0x00000800 /* RST_DTX_IDX11[11] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX11_SHFT 11 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX10_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX10_MASK \ + 0x00000400 /* RST_DTX_IDX10[10] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX10_SHFT 10 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX9_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX9_MASK \ + 0x00000200 /* RST_DTX_IDX9[9] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX9_SHFT 9 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX8_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX8_MASK \ + 0x00000100 /* RST_DTX_IDX8[8] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX8_SHFT 8 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX7_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX7_MASK \ + 0x00000080 /* RST_DTX_IDX7[7] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX7_SHFT 7 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX6_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX6_MASK \ + 0x00000040 /* RST_DTX_IDX6[6] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX6_SHFT 6 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX5_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX5_MASK \ + 0x00000020 /* RST_DTX_IDX5[5] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX5_SHFT 5 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX4_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX4_MASK \ + 0x00000010 /* RST_DTX_IDX4[4] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX4_SHFT 4 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX3_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX3_MASK \ + 0x00000008 /* RST_DTX_IDX3[3] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX3_SHFT 3 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX2_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX2_MASK \ + 0x00000004 /* RST_DTX_IDX2[2] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX2_SHFT 2 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX1_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX1_MASK \ + 0x00000002 /* RST_DTX_IDX1[1] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX1_SHFT 1 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX0_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX0_MASK \ + 0x00000001 /* RST_DTX_IDX0[0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX0_SHFT 0 + +/* +* ---WPDMA_PAUSE_TX_Q (0x7C025000 + 0x224)--- +* TX_Q_PAUSE[31..0] - (RW) Pause signal for each TX ring (16 bits for 16 rings) +* Set 0: Normal function; Set 1: The corresponding TX ring is paused +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_TX_Q_TX_Q_PAUSE_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_TX_Q_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_TX_Q_TX_Q_PAUSE_MASK \ + 0xFFFFFFFF /* TX_Q_PAUSE[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_TX_Q_TX_Q_PAUSE_SHFT 0 + +/* +* ---WPDMA_TIMEOUT_CFG (0x7C025000 + 0x230)--- +* WPDMA_TX_TIMEOUT_TH[7..0] - (RW) xxx +* WPDMA_TX_TIMEOUT_TICK[14..8] - (RW) xxx +* WPDMA_TX_TIMEOUT_ENA[15] - (RW) xxx +* WPDMA_RX_TIMEOUT_TH[23..16] - (RW) xxx +* WPDMA_RX_TIMEOUT_TICK[30..24] - (RW) xxx +* WPDMA_RX_TIMEOUT_ENA[31] - (RW) xxx +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_ENA_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_ENA_MASK \ + 0x80000000 /* WPDMA_RX_TIMEOUT_ENA[31] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_ENA_SHFT 31 +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TICK_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TICK_MASK \ + 0x7F000000 /* WPDMA_RX_TIMEOUT_TICK[30..24] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TICK_SHFT 24 +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TH_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TH_MASK \ + 0x00FF0000 /* WPDMA_RX_TIMEOUT_TH[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TH_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_ENA_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_ENA_MASK \ + 0x00008000 /* WPDMA_TX_TIMEOUT_ENA[15] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_ENA_SHFT 15 +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TICK_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TICK_MASK \ + 0x00007F00 /* WPDMA_TX_TIMEOUT_TICK[14..8] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TICK_SHFT 8 +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TH_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TH_MASK \ + 0x000000FF /* WPDMA_TX_TIMEOUT_TH[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TH_SHFT 0 + +/* +* ---WPDMA_MISC_CFG (0x7C025000 + 0x234)--- +* WPDMA_TX_TIMEOUT_SEL[0] - (RW) xxx +* WPDMA_RX_TIMEOUT_SEL[1] - (RW) xxx +* WPDMA_RX_FREE_Q_TH[5..2] - (RW) When loopback, this will be used to generate +* correct tx_pause to avlid deadlock which caused from situration that tx_dma +* will start reading tx packet from memory without considering lack of RX dmad +* in prefetch sram and needing to read RX dmad from memory which tx dma is +* reading tx packet too and rready is deasserted due to txfifo full !! +* RX dmad in prefetch sram should be greater than RX_FREE_Q_TH for rx_dma to +* start writing received packet into memory!! +* RESERVED6[31..6] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_MISC_CFG_WPDMA_RX_FREE_Q_TH_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_MISC_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_MISC_CFG_WPDMA_RX_FREE_Q_TH_MASK \ + 0x0000003C /* WPDMA_RX_FREE_Q_TH[5..2] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_MISC_CFG_WPDMA_RX_FREE_Q_TH_SHFT 2 +#define WF_WFDMA_HOST_DMA1_WPDMA_MISC_CFG_WPDMA_RX_TIMEOUT_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_MISC_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_MISC_CFG_WPDMA_RX_TIMEOUT_SEL_MASK \ + 0x00000002 /* WPDMA_RX_TIMEOUT_SEL[1] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_MISC_CFG_WPDMA_RX_TIMEOUT_SEL_SHFT 1 +#define WF_WFDMA_HOST_DMA1_WPDMA_MISC_CFG_WPDMA_TX_TIMEOUT_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_MISC_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_MISC_CFG_WPDMA_TX_TIMEOUT_SEL_MASK \ + 0x00000001 /* WPDMA_TX_TIMEOUT_SEL[0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_MISC_CFG_WPDMA_TX_TIMEOUT_SEL_SHFT 0 + +/* +* ---WPDMA_TX_WRR_ARB_GBF0 (0x7C025000 + 0x240)--- +* WRR_REQ0_ARB_GBF[2..0] - (RW) WRR REQ#0 priority level, mapped to lumpped +* request from TX ring0~ring15 for host TXD +* WRR_REQ1_ARB_GBF[5..3] - (RW) WRR REQ#1 priority level, mapped to request from +* TX ring16 when dual tx fifo for host event packet +* WRR_REQ2_ARB_GBF[8..6] - (RW) WRR REQ#2 priority level, mapped to request from +* TX ring17 when dual tx fifo for host event packet +* WRR_REQ3_ARB_GBF[11..9] - (RW) WRR REQ#3 priority level, mapped to request +* from TX ring18 when dual tx fifo for host event packet +* WRR_REQ4_ARB_GBF[14..12] - (RW) WRR REQ#4 priority level, mapped to request +* from TX ring19 when dual tx fifo for host event packet +* RESERVED[31..15] - (RW) Reserved +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ4_ARB_GBF_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ4_ARB_GBF_MASK \ + 0x00007000 /* WRR_REQ4_ARB_GBF[14..12] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ4_ARB_GBF_SHFT 12 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ3_ARB_GBF_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ3_ARB_GBF_MASK \ + 0x00000E00 /* WRR_REQ3_ARB_GBF[11..9] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ3_ARB_GBF_SHFT 9 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ2_ARB_GBF_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ2_ARB_GBF_MASK \ + 0x000001C0 /* WRR_REQ2_ARB_GBF[8..6] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ2_ARB_GBF_SHFT 6 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ1_ARB_GBF_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ1_ARB_GBF_MASK \ + 0x00000038 /* WRR_REQ1_ARB_GBF[5..3] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ1_ARB_GBF_SHFT 3 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ0_ARB_GBF_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ0_ARB_GBF_MASK \ + 0x00000007 /* WRR_REQ0_ARB_GBF[2..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ0_ARB_GBF_SHFT 0 + +/* +* ---WPDMA_PAUSE_RX_Q_TH10 (0x7C025000 + 0x260)--- +* RX_DMAD_TH0[11..0] - (RW) RX Ring0 DMAD threshold to pause PP sending packet +* to RX FIFO +* pause_rx_q = (available RX DMAD counts) < +* RESERVED12[15..12] - (RO) Reserved bits +* RX_DMAD_TH1[27..16] - (RW) RX Ring1 DMAD threshold to pause PP sending packet +* to RX FIFO +* pause_rx_q = (available RX DMAD counts) < +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH1_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH10_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH1_MASK \ + 0x0FFF0000 /* RX_DMAD_TH1[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH1_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH0_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH10_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH0_MASK \ + 0x00000FFF /* RX_DMAD_TH0[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH0_SHFT 0 + +/* +* ---WPDMA_PAUSE_RX_Q_TH32 (0x7C025000 + 0x264)--- +* RX_DMAD_TH2[11..0] - (RW) RX Ring2 DMAD threshold to pause PP sending packet +* to RX FIFO +* pause_rx_q = (available RX DMAD counts) < +* RESERVED12[15..12] - (RO) Reserved bits +* RX_DMAD_TH3[27..16] - (RW) RX Ring3 DMAD threshold to pause PP sending packet +* to RX FIFO +* pause_rx_q = (available RX DMAD counts) < +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH3_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH32_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH3_MASK \ + 0x0FFF0000 /* RX_DMAD_TH3[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH3_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH2_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH32_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH2_MASK \ + 0x00000FFF /* RX_DMAD_TH2[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH2_SHFT 0 + +/* +* ---WPDMA_PAUSE_RX_Q_TH54 (0x7C025000 + 0x268)--- +* RX_DMAD_TH4[11..0] - (RW) RX Ring4 DMAD threshold to pause PP sending packet +* to RX FIFO +* pause_rx_q = (available RX DMAD counts) < +* RESERVED12[15..12] - (RO) Reserved bits +* RX_DMAD_TH5[27..16] - (RW) RX Ring5 DMAD threshold to pause PP sending packet +* to RX FIFO +* pause_rx_q = (available RX DMAD counts) < +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH5_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH54_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH5_MASK \ + 0x0FFF0000 /* RX_DMAD_TH5[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH5_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH4_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH54_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH4_MASK \ + 0x00000FFF /* RX_DMAD_TH4[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH4_SHFT 0 + +/* +* ---WPDMA_PAUSE_RX_Q_TH76 (0x7C025000 + 0x26C)--- +* RX_DMAD_TH6[11..0] - (RW) RX Ring6 DMAD threshold to pause PP sending packet +* to RX FIFO +* pause_rx_q = (available RX DMAD counts) < +* RESERVED12[15..12] - (RO) Reserved bits +* RX_DMAD_TH7[27..16] - (RW) RX Ring7 DMAD threshold to pause PP sending packet +* to RX FIFO +* pause_rx_q = (available RX DMAD counts) < +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH7_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH76_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH7_MASK \ + 0x0FFF0000 /* RX_DMAD_TH7[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH7_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH6_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH76_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH6_MASK \ + 0x00000FFF /* RX_DMAD_TH6[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH6_SHFT 0 + +/* +* ---WPDMA_RST_DRX_PTR (0x7C025000 + 0x280)--- +* RST_DRX_IDX0[0] - (WO) Write 1 to reset to RX_DMARX_IDX0 to 0 +* RST_DRX_IDX1[1] - (WO) Write 1 to reset to RX_DMARX_IDX1 to 0 +* RST_DRX_IDX2[2] - (WO) Write 1 to reset to RX_DMARX_IDX2 to 0 +* RST_DRX_IDX3[3] - (WO) Write 1 to reset to RX_DMARX_IDX3 to 0 +* RESERVED[31..4] - (WO) Reserved +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_RST_DRX_IDX3_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_RST_DRX_IDX3_MASK \ + 0x00000008 /* RST_DRX_IDX3[3] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_RST_DRX_IDX3_SHFT 3 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_RST_DRX_IDX2_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_RST_DRX_IDX2_MASK \ + 0x00000004 /* RST_DRX_IDX2[2] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_RST_DRX_IDX2_SHFT 2 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_RST_DRX_IDX1_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_RST_DRX_IDX1_MASK \ + 0x00000002 /* RST_DRX_IDX1[1] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_RST_DRX_IDX1_SHFT 1 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_RST_DRX_IDX0_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_RST_DRX_IDX0_MASK \ + 0x00000001 /* RST_DRX_IDX0[0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_RST_DRX_IDX0_SHFT 0 + +/* +* ---WPDMA_INFO (0x7C025000 + 0x284)--- +* TX_RING_NUMBER[7..0] - (RO) TX_RING_NUMBER +* RX_RING_NUMBER[15..8] - (RO) RX_RING_NUMBER +* BASE_PTR_WIDTH[23..16] - (RO) {2'h0, 6'd32-'BASE_PTR_WIDTH[5:0]} +* INDEX_WIDTH[27..24] - (RO) RING_INDEX_WIDTH +* PDMA_PREFETCH_SRAM_SIZE[30..28] - (RO) PDMA prefetch sram size{3'h0 : 128 +* byte, 3'h1 : 256 byte, 3'h2 : 512 byte, 3'h3 : 1KB, 3'h4 : 2KB, 3'h5 : 4KB, +* 3'h6 : 8KB, 3'h7 : reserved}, be noticed that prefetch sram is shared outside +* with other DMAs, please check all DMAs' total prefetch ring number and max_cnt +* for each prefetch ring to make sure that total size of all configured prefetch +* dmad of all DMAs' prefetch ring should be less than PDMA_PREFETCH_SRAM_SIZE +* WFDMA_PDA_EXIST[31] - (RO) Only cpu_dma1 will support pda functions for +* firmware download and wfdma_pda_top resides in between cpu_dma0 and cpu_dma1! +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_WFDMA_PDA_EXIST_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_WFDMA_PDA_EXIST_MASK \ + 0x80000000 /* WFDMA_PDA_EXIST[31] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_WFDMA_PDA_EXIST_SHFT 31 +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_PDMA_PREFETCH_SRAM_SIZE_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_PDMA_PREFETCH_SRAM_SIZE_MASK \ + 0x70000000 /* PDMA_PREFETCH_SRAM_SIZE[30..28] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_PDMA_PREFETCH_SRAM_SIZE_SHFT 28 +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_INDEX_WIDTH_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_INDEX_WIDTH_MASK \ + 0x0F000000 /* INDEX_WIDTH[27..24] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_INDEX_WIDTH_SHFT 24 +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_BASE_PTR_WIDTH_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_BASE_PTR_WIDTH_MASK \ + 0x00FF0000 /* BASE_PTR_WIDTH[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_BASE_PTR_WIDTH_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_RX_RING_NUMBER_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_RX_RING_NUMBER_MASK \ + 0x0000FF00 /* RX_RING_NUMBER[15..8] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_RX_RING_NUMBER_SHFT 8 +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_TX_RING_NUMBER_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_TX_RING_NUMBER_MASK \ + 0x000000FF /* TX_RING_NUMBER[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_TX_RING_NUMBER_SHFT 0 + +/* +* ---WPDMA_INFO_EXT (0x7C025000 + 0x288)--- +* TX_EVENT_RING_NUMBER[7..0] - (RO) When TX_EVENT_RING_NUMBER equal 8'h0, it +* means that this DMA doesn't support dual TX fifo, thus in default it only +* support TX_RING_NUMBER of TX rings !! +* But when TX_EVENT_RING_NUMBER NOT equal 8'h0, this dma is configured as dual +* TX fifo and TX_RING[16+TX_EVENT_RING_NUM-1:16] are for getting HOST EVENT +* packet from HOST to WX_CPU!! +* TX_DMAD_RING_NUMBER[15..8] - (RO) When TX_EVENT_RING_NUMBER not equal to 8'h0, +* it means that this DMA support dual TX fifo and TX +* ring[TX_DMAD_RING_NUMBER-1:0] are for getting TXD from HOST to UMAC!! +* RESERVED[30..16] - (RO) Reserved +* TX_DMASHDL_EXIST[31] - (RO) TX_DMASHDL_EXIST +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_EXT_TX_DMASHDL_EXIST_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INFO_EXT_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_EXT_TX_DMASHDL_EXIST_MASK \ + 0x80000000 /* TX_DMASHDL_EXIST[31] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_EXT_TX_DMASHDL_EXIST_SHFT 31 +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_EXT_TX_DMAD_RING_NUMBER_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INFO_EXT_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_EXT_TX_DMAD_RING_NUMBER_MASK \ + 0x0000FF00 /* TX_DMAD_RING_NUMBER[15..8] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_EXT_TX_DMAD_RING_NUMBER_SHFT 8 +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_EXT_TX_EVENT_RING_NUMBER_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INFO_EXT_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_EXT_TX_EVENT_RING_NUMBER_MASK \ + 0x000000FF /* TX_EVENT_RING_NUMBER[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_EXT_TX_EVENT_RING_NUMBER_SHFT 0 + +/* +* ---WPDMA_INT_RX_PRI_SEL (0x7C025000 + 0x298)--- +* WPDMA_INT_RX_RING0_PRI_SEL[0] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_RX_RING1_PRI_SEL[1] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* RESERVED2[2] - (RO) Reserved bits +* WPDMA_INT_RX_RING3_PRI_SEL[3] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING3_PRI_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING3_PRI_SEL_MASK \ + 0x00000008 /* WPDMA_INT_RX_RING3_PRI_SEL[3] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING3_PRI_SEL_SHFT \ + 3 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING1_PRI_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING1_PRI_SEL_MASK \ + 0x00000002 /* WPDMA_INT_RX_RING1_PRI_SEL[1] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING1_PRI_SEL_SHFT \ + 1 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING0_PRI_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING0_PRI_SEL_MASK \ + 0x00000001 /* WPDMA_INT_RX_RING0_PRI_SEL[0] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING0_PRI_SEL_SHFT \ + 0 + +/* +* ---WPDMA_INT_TX_PRI_SEL (0x7C025000 + 0x29C)--- +* WPDMA_INT_TX_RING0_PRI_SEL[0] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING1_PRI_SEL[1] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING2_PRI_SEL[2] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING3_PRI_SEL[3] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING4_PRI_SEL[4] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING5_PRI_SEL[5] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING6_PRI_SEL[6] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING7_PRI_SEL[7] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING8_PRI_SEL[8] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING9_PRI_SEL[9] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING10_PRI_SEL[10] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING11_PRI_SEL[11] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING12_PRI_SEL[12] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING13_PRI_SEL[13] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING14_PRI_SEL[14] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* RESERVED15[15] - (RO) Reserved bits +* WPDMA_INT_TX_RING16_PRI_SEL[16] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING17_PRI_SEL[17] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* RESERVED18[31..18] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING17_PRI_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING17_PRI_SEL_MASK \ + 0x00020000 /* WPDMA_INT_TX_RING17_PRI_SEL[17] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING17_PRI_SEL_SHFT \ + 17 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING16_PRI_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING16_PRI_SEL_MASK \ + 0x00010000 /* WPDMA_INT_TX_RING16_PRI_SEL[16] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING16_PRI_SEL_SHFT \ + 16 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING14_PRI_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING14_PRI_SEL_MASK \ + 0x00004000 /* WPDMA_INT_TX_RING14_PRI_SEL[14] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING14_PRI_SEL_SHFT \ + 14 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING13_PRI_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING13_PRI_SEL_MASK \ + 0x00002000 /* WPDMA_INT_TX_RING13_PRI_SEL[13] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING13_PRI_SEL_SHFT \ + 13 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING12_PRI_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING12_PRI_SEL_MASK \ + 0x00001000 /* WPDMA_INT_TX_RING12_PRI_SEL[12] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING12_PRI_SEL_SHFT \ + 12 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING11_PRI_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING11_PRI_SEL_MASK \ + 0x00000800 /* WPDMA_INT_TX_RING11_PRI_SEL[11] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING11_PRI_SEL_SHFT \ + 11 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING10_PRI_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING10_PRI_SEL_MASK \ + 0x00000400 /* WPDMA_INT_TX_RING10_PRI_SEL[10] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING10_PRI_SEL_SHFT \ + 10 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING9_PRI_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING9_PRI_SEL_MASK \ + 0x00000200 /* WPDMA_INT_TX_RING9_PRI_SEL[9] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING9_PRI_SEL_SHFT \ + 9 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING8_PRI_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING8_PRI_SEL_MASK \ + 0x00000100 /* WPDMA_INT_TX_RING8_PRI_SEL[8] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING8_PRI_SEL_SHFT \ + 8 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING7_PRI_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING7_PRI_SEL_MASK \ + 0x00000080 /* WPDMA_INT_TX_RING7_PRI_SEL[7] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING7_PRI_SEL_SHFT \ + 7 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING6_PRI_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING6_PRI_SEL_MASK \ + 0x00000040 /* WPDMA_INT_TX_RING6_PRI_SEL[6] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING6_PRI_SEL_SHFT \ + 6 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING5_PRI_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING5_PRI_SEL_MASK \ + 0x00000020 /* WPDMA_INT_TX_RING5_PRI_SEL[5] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING5_PRI_SEL_SHFT \ + 5 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING4_PRI_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING4_PRI_SEL_MASK \ + 0x00000010 /* WPDMA_INT_TX_RING4_PRI_SEL[4] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING4_PRI_SEL_SHFT \ + 4 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING3_PRI_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING3_PRI_SEL_MASK \ + 0x00000008 /* WPDMA_INT_TX_RING3_PRI_SEL[3] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING3_PRI_SEL_SHFT \ + 3 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING2_PRI_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING2_PRI_SEL_MASK \ + 0x00000004 /* WPDMA_INT_TX_RING2_PRI_SEL[2] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING2_PRI_SEL_SHFT \ + 2 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING1_PRI_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING1_PRI_SEL_MASK \ + 0x00000002 /* WPDMA_INT_TX_RING1_PRI_SEL[1] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING1_PRI_SEL_SHFT \ + 1 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING0_PRI_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING0_PRI_SEL_MASK \ + 0x00000001 /* WPDMA_INT_TX_RING0_PRI_SEL[0] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING0_PRI_SEL_SHFT \ + 0 + +/* +* ---WPDMA_TX_DBG0 (0x7C025000 + 0x2A0)--- +* WPDMA_TX_DBG0[31..0] - (RO) xxx +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_DBG0_WPDMA_TX_DBG0_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_DBG0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_DBG0_WPDMA_TX_DBG0_MASK \ + 0xFFFFFFFF /* WPDMA_TX_DBG0[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_DBG0_WPDMA_TX_DBG0_SHFT 0 + +/* +* ---WPDMA_TX_DBG1 (0x7C025000 + 0x2A4)--- +* WPDMA_TX_DBG1[31..0] - (RO) xxx +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_DBG1_WPDMA_TX_DBG1_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_DBG1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_DBG1_WPDMA_TX_DBG1_MASK \ + 0xFFFFFFFF /* WPDMA_TX_DBG1[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_DBG1_WPDMA_TX_DBG1_SHFT 0 + +/* +* ---WPDMA_RX_DBG0 (0x7C025000 + 0x2A8)--- +* WPDMA_RX_DBG0[31..0] - (RO) xxx +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_DBG0_WPDMA_RX_DBG0_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_DBG0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_DBG0_WPDMA_RX_DBG0_MASK \ + 0xFFFFFFFF /* WPDMA_RX_DBG0[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_DBG0_WPDMA_RX_DBG0_SHFT 0 + +/* +* ---WPDMA_RX_DBG1 (0x7C025000 + 0x2AC)--- +* WPDMA_RX_DBG1[31..0] - (RO) xxx +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_DBG1_WPDMA_RX_DBG1_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_DBG1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_DBG1_WPDMA_RX_DBG1_MASK \ + 0xFFFFFFFF /* WPDMA_RX_DBG1[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_DBG1_WPDMA_RX_DBG1_SHFT 0 + +/* +* ---WPDMA_GLO_CFG_EXT0 (0x7C025000 + 0x2B0)--- +* CSR_MAX_PREFETCH_CNT[1..0] - (RW) Max. dmad count per prefet request, 2'b00 : +* 1 entry, 2'b01 : 2 entries, 2'b10 : 4 entries, 2'b11 : 8 entries, Note : 1 +* entry(dmad size) is 16 bytes = 4 DWs = 2 QWs +* CSR_MEM_BST_SIZE[3..2] - (RW) Max. burst size per sram request. 00 : 16-byte, +* 01 : 32-byte, 10 : 64-byte, 11 : 128-byte +* CSR_MEM_ARB_LOCK_EN[4] - (RW) 1'b1 : Lock round-robin sram access arbiter +* until whole long burst request from dma FSM finish, 1'b0 : no lock sram +* arbiter, grant will be change per request due to round-robin +* CSR_RX_DMA_WBQ_EN[5] - (RW) 1'b1 : RX dmad will be posted-write and deal with +* next received packet immediately, 1'b0 : RX dmad will be written back +* immediately after received packet has been sent to host memory +* CSR_TX_DMASHDL_ENABLE[6] - (RW) 1'b1 : request DMASHDL before TX to select +* next TX ring, 1'b0 : disable DMASHDL and use round-robin arbiter to select +* next TX ring +* CSR_BRESP_ERROR_BYPASS_EN[7] - (RW) 1'b1 : Bypass AXI error bresp as a normal +* response. 1'b0 : Will not assert bready to error bresp(00 : OKAY, 01 : EXOKAY, +* 10 : SLVERR, 11 : DECERR) +* CSR_AXI_SLEEP_MODE[9..8] - (RW) 2'b00 : no sleep, normal TX/RX, 2b1* : sleep +* after AXI request, 2'b11 : force assertion of wvalid, rready and bready to +* finish all committed data phases, then sleep immediately +* RESERVED10[14..10] - (RO) Reserved bits +* CSR_Q_STATUS_IDX_BKRS_EN[15] - (RW) backup/restore enable bit for +* q_status(payload, prefetch and dispatch) index +* CSR_AXI_BST_SIZE[17..16] - (RW) AXI busrt length, 00 : 128-byte, 01 : 64-byte, +* 10 : 32-byte, 11 : 16-byte +* CSR_RX_DMAD_WB_MIRROR_EN[18] - (RW) Set to 1'b1 to split RX DMAD write-back +* into two AXI request which carries ddone bit (DW1[31], DW1[15]) for each iif +* external AXI dispatcher exist and need to do push-write behavior to make sure +* all datas from two PCIE have arrived HOST memory +* CSR_AXI_FAKE[19] - (RW) If set to 1'b1, all requests from DMA engine will not +* be sent to AXI INFRA, this try to fix AXI bus hang issue temporarily! +* CSR_DMAD_PREFETCH_THRESHOLD[21..20] - (RW) trigger dmad prefetch when +* available dmad cnt >= {1(2'b00), 2(2'b01), 4(2'b10), 8(2'b11)} +* CSR_BID_CHECK_BYPASS_EN[22] - (RW) If set to 1'b0, axi master will check +* matching between awid and bid before assert bready, if set to 1'b1, it will +* bypass this checking and assert bready for each bvalid even though bid doesn't +* match any awid ever issued! +* CSR_RX_INFO_WB_EN[23] - (RW) If set to 1'b0, only DW0 and DW1 will be written +* back into memory after received RX packet process finished, this will save bus +* bandwidth a little because DW2 and DW3 are useless for FW +* CSR_AXI_OUTSTANDING_NUM[27..24] - (RW) decide max. outstanding AXI requests, +* common for AXI read or write! +* CSR_AXI_ARUSER_LOCK_EN[28] - (RW) on/off customized lock ctrl design thru AXI +* aruser signal, this will influence TX QoS ctrl +* CSR_AXI_AWUSER_LOCK_EN[29] - (RW) on/off customized lock ctrl design thru AXI +* awuser signal when RX dmad write-back have to be separately written into +* memory due to external dispatcher exists! +* CSR_AXI_LOCK_EN[30] - (RW) Global lock enable to on/off AXI spec. lock(axlock) +* behavior and also will on/off customized lock ctrl design thru AXI awuser +signal +* CSR_AXI_CLKGATE_BYP[31] - (RW) To bypass functional CG enable which incduced +* from coding style for DC inserted CG cell in all AXI read/write master design +module +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_CLKGATE_BYP_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_CLKGATE_BYP_MASK \ + 0x80000000 /* CSR_AXI_CLKGATE_BYP[31] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_CLKGATE_BYP_SHFT 31 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_LOCK_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_LOCK_EN_MASK \ + 0x40000000 /* CSR_AXI_LOCK_EN[30] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_LOCK_EN_SHFT 30 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_AWUSER_LOCK_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_AWUSER_LOCK_EN_MASK \ + 0x20000000 /* CSR_AXI_AWUSER_LOCK_EN[29] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_AWUSER_LOCK_EN_SHFT 29 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_ARUSER_LOCK_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_ARUSER_LOCK_EN_MASK \ + 0x10000000 /* CSR_AXI_ARUSER_LOCK_EN[28] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_ARUSER_LOCK_EN_SHFT 28 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_OUTSTANDING_NUM_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_OUTSTANDING_NUM_MASK \ + 0x0F000000 /* CSR_AXI_OUTSTANDING_NUM[27..24] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_OUTSTANDING_NUM_SHFT 24 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_RX_INFO_WB_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_RX_INFO_WB_EN_MASK \ + 0x00800000 /* CSR_RX_INFO_WB_EN[23] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_RX_INFO_WB_EN_SHFT 23 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_BID_CHECK_BYPASS_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_BID_CHECK_BYPASS_EN_MASK \ + 0x00400000 /* CSR_BID_CHECK_BYPASS_EN[22] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_BID_CHECK_BYPASS_EN_SHFT 22 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_DMAD_PREFETCH_THRESHOLD_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_DMAD_PREFETCH_THRESHOLD_MASK \ + 0x00300000 /* CSR_DMAD_PREFETCH_THRESHOLD[21..20] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_DMAD_PREFETCH_THRESHOLD_SHFT \ + 20 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_FAKE_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_FAKE_MASK \ + 0x00080000 /* CSR_AXI_FAKE[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_FAKE_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_RX_DMAD_WB_MIRROR_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_RX_DMAD_WB_MIRROR_EN_MASK \ + 0x00040000 /* CSR_RX_DMAD_WB_MIRROR_EN[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_RX_DMAD_WB_MIRROR_EN_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_BST_SIZE_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_BST_SIZE_MASK \ + 0x00030000 /* CSR_AXI_BST_SIZE[17..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_BST_SIZE_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_Q_STATUS_IDX_BKRS_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_Q_STATUS_IDX_BKRS_EN_MASK \ + 0x00008000 /* CSR_Q_STATUS_IDX_BKRS_EN[15] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_Q_STATUS_IDX_BKRS_EN_SHFT 15 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_SLEEP_MODE_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_SLEEP_MODE_MASK \ + 0x00000300 /* CSR_AXI_SLEEP_MODE[9..8] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_SLEEP_MODE_SHFT 8 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_BRESP_ERROR_BYPASS_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_BRESP_ERROR_BYPASS_EN_MASK \ + 0x00000080 /* CSR_BRESP_ERROR_BYPASS_EN[7] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_BRESP_ERROR_BYPASS_EN_SHFT 7 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_TX_DMASHDL_ENABLE_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_TX_DMASHDL_ENABLE_MASK \ + 0x00000040 /* CSR_TX_DMASHDL_ENABLE[6] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_TX_DMASHDL_ENABLE_SHFT 6 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_RX_DMA_WBQ_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_RX_DMA_WBQ_EN_MASK \ + 0x00000020 /* CSR_RX_DMA_WBQ_EN[5] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_RX_DMA_WBQ_EN_SHFT 5 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_MEM_ARB_LOCK_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_MEM_ARB_LOCK_EN_MASK \ + 0x00000010 /* CSR_MEM_ARB_LOCK_EN[4] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_MEM_ARB_LOCK_EN_SHFT 4 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_MEM_BST_SIZE_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_MEM_BST_SIZE_MASK \ + 0x0000000C /* CSR_MEM_BST_SIZE[3..2] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_MEM_BST_SIZE_SHFT 2 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_MAX_PREFETCH_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_MAX_PREFETCH_CNT_MASK \ + 0x00000003 /* CSR_MAX_PREFETCH_CNT[1..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_MAX_PREFETCH_CNT_SHFT 0 + +/* +* ---WPDMA_GLO_CFG_EXT1 (0x7C025000 + 0x2B4)--- +* CSR_TXFIFO0_RDY_THRESHOLD[7..0] - (RW) xxx +* CSR_TXFIFO1_RDY_THRESHOLD[15..8] - (RW) xxx +* CSR_TX_DISP_ARB_SCHEDULED_ACCESS_TIMER[23..16] - (RW) timer setting for +* SCHEDULED_ACCESS_TIME_ARB of csr_tx_disp_arb_mode +* CSR_TX_DISP_ARB_MODE[25..24] - (RW) 00 : FAIR_ARB, 01 : FIX_ARB, 10 : +* UNBALANCED_ARB, 11 : SCHEDULED_ACCESS_TIME_ARB +* CSR_FWDL_FLOW_CTRL_BYASS_EN[26] - (RW) To disable firmware download TX flow +* control of TX dma(host_dma1) when firmare download of RX dma(mcu_dma1) is in +* firmware download polling mode!! Remember to set to 1'b0 when firmware +* download ring is set back to normal ring usage which should be in flow control +* for correct behavior!! +* CSR_FWDL_FLOW_CTRL_BYASS_LS_QSEL_EN[27] - (RW) select firmware download TX +* ring(LSB/MSB ring) to bypass TX flow control when firmare download RX +* ring(LSB/MSB ring) of RX dma(mcu_dma1) is in firmware download polling mode!! +* RESERVED[31..28] - (RW) reserved +*/ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_LS_QSEL_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_LS_QSEL_EN_MASK \ + 0x08000000 /* CSR_FWDL_FLOW_CTRL_BYASS_LS_QSEL_EN[27] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_LS_QSEL_EN_SHFT \ + 27 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_EN_MASK \ + 0x04000000 /* CSR_FWDL_FLOW_CTRL_BYASS_EN[26] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_EN_SHFT \ + 26 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_MODE_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_MODE_MASK \ + 0x03000000 /* CSR_TX_DISP_ARB_MODE[25..24] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_MODE_SHFT 24 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_SCHEDULED_ACCESS_TIMER_AD\ +DR \ +WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_SCHEDULED_ACCESS_TIMER_MA\ +SK \ +0x00FF0000 /* CSR_TX_DISP_ARB_SCHEDULED_ACCESS_TIMER[23..16] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_SCHEDULED_ACCESS_TIMER_SH\ +FT \ +16 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO1_RDY_THRESHOLD_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO1_RDY_THRESHOLD_MASK \ + 0x0000FF00 /* CSR_TXFIFO1_RDY_THRESHOLD[15..8] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO1_RDY_THRESHOLD_SHFT 8 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO0_RDY_THRESHOLD_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO0_RDY_THRESHOLD_MASK \ + 0x000000FF /* CSR_TXFIFO0_RDY_THRESHOLD[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO0_RDY_THRESHOLD_SHFT 0 + +/* +* ---WPDMA_AXI_MST_DBG0 (0x7C025000 + 0x2B8)--- +* M0_AXI_RRESP_ERROR_RRESP[1..0] - (W1C) tx_pfet AXI rresp +* RESERVED2[3..2] - (RO) Reserved bits +* M0_AXI_RRESP_ERROR_RID[7..4] - (W1C) tx_pfet AXI rid +* M1_AXI_RRESP_ERROR_RRESP[9..8] - (W1C) pf_dfet_rx AXI rresp +* RESERVED10[11..10] - (RO) Reserved bits +* M1_AXI_RRESP_ERROR_RID[15..12] - (W1C) pf_dfet_rx AXI rid +* M2_AXI_RRESP_ERROR_RRESP[17..16] - (W1C) pf_dfet_tx AXI rresp +* RESERVED18[19..18] - (RO) Reserved bits +* M2_AXI_RRESP_ERROR_RID[23..20] - (W1C) pf_dfet_tx AXI rid +* M0_AXI_RRESP_ERROR[24] - (W1C) tx_pfet_tx AXI rresp_error +* M1_AXI_RRESP_ERROR[25] - (W1C) pf_dfet_rx AXI rresp_error +* M2_AXI_RRESP_ERROR[26] - (W1C) pf_dfet_tx AXI rresp_error +* RESERVED27[31..27] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M2_AXI_RRESP_ERROR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M2_AXI_RRESP_ERROR_MASK \ + 0x04000000 /* M2_AXI_RRESP_ERROR[26] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M2_AXI_RRESP_ERROR_SHFT 26 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M1_AXI_RRESP_ERROR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M1_AXI_RRESP_ERROR_MASK \ + 0x02000000 /* M1_AXI_RRESP_ERROR[25] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M1_AXI_RRESP_ERROR_SHFT 25 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M0_AXI_RRESP_ERROR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M0_AXI_RRESP_ERROR_MASK \ + 0x01000000 /* M0_AXI_RRESP_ERROR[24] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M0_AXI_RRESP_ERROR_SHFT 24 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M2_AXI_RRESP_ERROR_RID_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M2_AXI_RRESP_ERROR_RID_MASK \ + 0x00F00000 /* M2_AXI_RRESP_ERROR_RID[23..20] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M2_AXI_RRESP_ERROR_RID_SHFT 20 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M2_AXI_RRESP_ERROR_RRESP_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M2_AXI_RRESP_ERROR_RRESP_MASK \ + 0x00030000 /* M2_AXI_RRESP_ERROR_RRESP[17..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M2_AXI_RRESP_ERROR_RRESP_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M1_AXI_RRESP_ERROR_RID_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M1_AXI_RRESP_ERROR_RID_MASK \ + 0x0000F000 /* M1_AXI_RRESP_ERROR_RID[15..12] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M1_AXI_RRESP_ERROR_RID_SHFT 12 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M1_AXI_RRESP_ERROR_RRESP_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M1_AXI_RRESP_ERROR_RRESP_MASK \ + 0x00000300 /* M1_AXI_RRESP_ERROR_RRESP[9..8] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M1_AXI_RRESP_ERROR_RRESP_SHFT 8 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M0_AXI_RRESP_ERROR_RID_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M0_AXI_RRESP_ERROR_RID_MASK \ + 0x000000F0 /* M0_AXI_RRESP_ERROR_RID[7..4] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M0_AXI_RRESP_ERROR_RID_SHFT 4 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M0_AXI_RRESP_ERROR_RRESP_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M0_AXI_RRESP_ERROR_RRESP_MASK \ + 0x00000003 /* M0_AXI_RRESP_ERROR_RRESP[1..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG0_M0_AXI_RRESP_ERROR_RRESP_SHFT 0 + +/* +* ---WPDMA_AXI_MST_DBG1 (0x7C025000 + 0x2BC)--- +* M0_AXI_BRESP_ERROR_BRESP[1..0] - (W1C) rx_pfet AXI bresp +* RESERVED2[3..2] - (RO) Reserved bits +* M0_AXI_BRESP_ERROR_RID[7..4] - (W1C) rx_pfet AXI bid +* M1_AXI_BRESP_ERROR_BRESP[9..8] - (W1C) wb_dfet_rx AXI bresp +* RESERVED10[11..10] - (RO) Reserved bits +* M1_AXI_BRESP_ERROR_RID[15..12] - (W1C) wb_dfet_rx AXI bid +* M2_AXI_BRESP_ERROR_BRESP[17..16] - (W1C) wb_dfet_tx AXI bresp +* RESERVED18[19..18] - (RO) Reserved bits +* M2_AXI_BRESP_ERROR_RID[23..20] - (W1C) wb_dfet_tx AXI bid +* M0_AXI_BRESP_ERROR[24] - (W1C) tx_pfet_tx AXI bresp_error +* M1_AXI_BRESP_ERROR[25] - (W1C) pf_dfet_rx AXI bresp_error +* M2_AXI_BRESP_ERROR[26] - (W1C) pf_dfet_tx AXI bresp_error +* RESERVED27[31..27] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M2_AXI_BRESP_ERROR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M2_AXI_BRESP_ERROR_MASK \ + 0x04000000 /* M2_AXI_BRESP_ERROR[26] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M2_AXI_BRESP_ERROR_SHFT 26 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M1_AXI_BRESP_ERROR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M1_AXI_BRESP_ERROR_MASK \ + 0x02000000 /* M1_AXI_BRESP_ERROR[25] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M1_AXI_BRESP_ERROR_SHFT 25 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M0_AXI_BRESP_ERROR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M0_AXI_BRESP_ERROR_MASK \ + 0x01000000 /* M0_AXI_BRESP_ERROR[24] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M0_AXI_BRESP_ERROR_SHFT 24 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M2_AXI_BRESP_ERROR_RID_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M2_AXI_BRESP_ERROR_RID_MASK \ + 0x00F00000 /* M2_AXI_BRESP_ERROR_RID[23..20] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M2_AXI_BRESP_ERROR_RID_SHFT 20 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M2_AXI_BRESP_ERROR_BRESP_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M2_AXI_BRESP_ERROR_BRESP_MASK \ + 0x00030000 /* M2_AXI_BRESP_ERROR_BRESP[17..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M2_AXI_BRESP_ERROR_BRESP_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M1_AXI_BRESP_ERROR_RID_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M1_AXI_BRESP_ERROR_RID_MASK \ + 0x0000F000 /* M1_AXI_BRESP_ERROR_RID[15..12] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M1_AXI_BRESP_ERROR_RID_SHFT 12 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M1_AXI_BRESP_ERROR_BRESP_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M1_AXI_BRESP_ERROR_BRESP_MASK \ + 0x00000300 /* M1_AXI_BRESP_ERROR_BRESP[9..8] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M1_AXI_BRESP_ERROR_BRESP_SHFT 8 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M0_AXI_BRESP_ERROR_RID_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M0_AXI_BRESP_ERROR_RID_MASK \ + 0x000000F0 /* M0_AXI_BRESP_ERROR_RID[7..4] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M0_AXI_BRESP_ERROR_RID_SHFT 4 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M0_AXI_BRESP_ERROR_BRESP_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M0_AXI_BRESP_ERROR_BRESP_MASK \ + 0x00000003 /* M0_AXI_BRESP_ERROR_BRESP[1..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_DBG1_M0_AXI_BRESP_ERROR_BRESP_SHFT 0 + +/* +* ---WPDMA_TX_QOS_LMT_CFG0 (0x7C025000 + 0x2C0)--- +* CSR_TX_PLD_AXI_LIMITER_REQ[2..0] - (RW) QoS CR, Limiter Enable for packet +* traffice of type TX_PLD +* CSR_TX_PLD_AXI_LIMITER_EN_REQ[3] - (RW) QoS CR, Limiter Enable for packet +* traffice of type TX_PLD +* CSR_TX_PLD_AXI_LIMITER_PKT[6..4] - (RW) QoS CR, Limiter Enable for packet +* traffice of type TX_PLD +* CSR_TX_PLD_AXI_LIMITER_EN_PKT[7] - (RW) QoS CR, Limiter Enable for packet +* traffice of type TX_PLD +* CSR_RX_PLD_AXI_LIMITER_REQ[10..8] - (RW) QoS CR, Limiter Enable for request +* traffice of type RX_PLD +* CSR_RX_PLD_AXI_LIMITER_EN_REQ[11] - (RW) QoS CR, Limiter Enable for request +* traffice of type RX_PLD +* CSR_RX_PLD_AXI_LIMITER_PKT[14..12] - (RW) QoS CR, Limiter Enable for request +* traffice of type RX_PLD +* CSR_RX_PLD_AXI_LIMITER_EN_PKT[15] - (RW) QoS CR, Limiter Enable for request +* traffice of type RX_PLD +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_EN_PKT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_EN_PKT_MASK \ + 0x00008000 /* CSR_RX_PLD_AXI_LIMITER_EN_PKT[15] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_EN_PKT_SHFT \ + 15 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_PKT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_PKT_MASK \ + 0x00007000 /* CSR_RX_PLD_AXI_LIMITER_PKT[14..12] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_PKT_SHFT \ + 12 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_EN_REQ_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_EN_REQ_MASK \ + 0x00000800 /* CSR_RX_PLD_AXI_LIMITER_EN_REQ[11] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_EN_REQ_SHFT \ + 11 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_REQ_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_REQ_MASK \ + 0x00000700 /* CSR_RX_PLD_AXI_LIMITER_REQ[10..8] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_REQ_SHFT \ + 8 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_AXI_LIMITER_EN_PKT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_AXI_LIMITER_EN_PKT_MASK \ + 0x00000080 /* CSR_TX_PLD_AXI_LIMITER_EN_PKT[7] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_AXI_LIMITER_EN_PKT_SHFT \ + 7 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_AXI_LIMITER_PKT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_AXI_LIMITER_PKT_MASK \ + 0x00000070 /* CSR_TX_PLD_AXI_LIMITER_PKT[6..4] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_AXI_LIMITER_PKT_SHFT \ + 4 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_AXI_LIMITER_EN_REQ_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_AXI_LIMITER_EN_REQ_MASK \ + 0x00000008 /* CSR_TX_PLD_AXI_LIMITER_EN_REQ[3] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_AXI_LIMITER_EN_REQ_SHFT \ + 3 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_AXI_LIMITER_REQ_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_AXI_LIMITER_REQ_MASK \ + 0x00000007 /* CSR_TX_PLD_AXI_LIMITER_REQ[2..0] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_AXI_LIMITER_REQ_SHFT \ + 0 + +/* +* ---WPDMA_TX_QOS_LMT_CFG1 (0x7C025000 + 0x2C4)--- +* CSR_AUX_TX_PLD_AXI_LIMITER_REQ[2..0] - (RW) QoS CR, Limiter value selected by +* PP dynamically +* RESERVED3[3] - (RO) Reserved bits +* CSR_AUX_TX_PLD_AXI_LIMITER_PKT[6..4] - (RW) QoS CR, Limiter value selected by +* PP dynamically +* RESERVED7[7] - (RO) Reserved bits +* CSR_AUX_RX_PLD_AXI_LIMITER_REQ[10..8] - (RW) QoS CR, Limiter value selected by +* PP dynamically +* RESERVED11[11] - (RO) Reserved bits +* CSR_AUX_RX_PLD_AXI_LIMITER_PKT[14..12] - (RW) QoS CR, Limiter value selected +* by PP dynamically +* RESERVED15[31..15] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_RX_PLD_AXI_LIMITER_PKT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_RX_PLD_AXI_LIMITER_PKT_MASK \ + 0x00007000 /* CSR_AUX_RX_PLD_AXI_LIMITER_PKT[14..12] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_RX_PLD_AXI_LIMITER_PKT_SHFT \ + 12 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_RX_PLD_AXI_LIMITER_REQ_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_RX_PLD_AXI_LIMITER_REQ_MASK \ + 0x00000700 /* CSR_AUX_RX_PLD_AXI_LIMITER_REQ[10..8] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_RX_PLD_AXI_LIMITER_REQ_SHFT \ + 8 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_AXI_LIMITER_PKT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_AXI_LIMITER_PKT_MASK \ + 0x00000070 /* CSR_AUX_TX_PLD_AXI_LIMITER_PKT[6..4] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_AXI_LIMITER_PKT_SHFT \ + 4 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_AXI_LIMITER_REQ_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_AXI_LIMITER_REQ_MASK \ + 0x00000007 /* CSR_AUX_TX_PLD_AXI_LIMITER_REQ[2..0] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_AXI_LIMITER_REQ_SHFT \ + 0 + +/* +* ---WPDMA_TX_QOS_LMT_CFG2 (0x7C025000 + 0x2C8)--- +* CSR_RX_RD_DMAD_AXI_LIMITER_REQ[2..0] - (RW) QoS CR, Limiter Value for packet +* traffice of type RX_RD_DMAD +* CSR_RX_RD_DMAD_AXI_LIMITER_EN_REQ[3] - (RW) QoS CR, Limiter Enable for request +* traffice of type RX_RD_DMAD +* CSR_RX_RD_DMAD_AXI_LIMITER_PKT[6..4] - (RW) QoS CR, Limiter Value for packet +* traffice of type RX_RD_DMAD +* CSR_RX_RD_DMAD_AXI_LIMITER_EN_PKT[7] - (RW) QoS CR, Limiter Enable for packet +* traffice of type RX_RD_DMAD +* CSR_RX_WR_DMAD_AXI_LIMITER_REQ[10..8] - (RW) QoS CR, Limiter Value for packet +* traffice of type RX_WR_DMAD +* CSR_RX_WR_DMAD_AXI_LIMITER_EN_REQ[11] - (RW) QoS CR, Limiter Enable for +* request traffice of type RX_WR_DMAD +* CSR_RX_WR_DMAD_AXI_LIMITER_PKT[14..12] - (RW) QoS CR, Limiter Value for packet +* traffice of type RX_WR_DMAD +* CSR_RX_WR_DMAD_AXI_LIMITER_EN_PKT[15] - (RW) QoS CR, Limiter Enable for packet +* traffice of type RX_WR_DMAD +* CSR_TX_RD_DMAD_AXI_LIMITER_REQ[18..16] - (RW) QoS CR, Limiter Value for packet +* traffice of type TX_RD_DMAD +* CSR_TX_RD_DMAD_AXI_LIMITER_EN_REQ[19] - (RW) QoS CR, Limiter Enable for +* request traffice of type TX_RD_DMAD +* CSR_TX_RD_DMAD_AXI_LIMITER_PKT[22..20] - (RW) QoS CR, Limiter Value for packet +* traffice of type TX_RD_DMAD +* CSR_TX_RD_DMAD_AXI_LIMITER_EN_PKT[23] - (RW) QoS CR, Limiter Enable for packet +* traffice of type TX_RD_DMAD +* CSR_TX_WR_DMAD_AXI_LIMITER_REQ[26..24] - (RW) QoS CR, Limiter Value for packet +* traffice of type TX_WR_DMAD +* CSR_TX_WR_DMAD_AXI_LIMITER_EN_REQ[27] - (RW) QoS CR, Limiter Enable for +* request traffice of type TX_WR_DMAD +* CSR_TX_WR_DMAD_AXI_LIMITER_PKT[30..28] - (RW) QoS CR, Limiter Value for packet +* traffice of type TX_WR_DMAD +* CSR_TX_WR_DMAD_AXI_LIMITER_EN_PKT[31] - (RW) QoS CR, Limiter Enable for packet +* traffice of type TX_WR_DMAD +*/ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_EN_PKT_ADDR\ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_EN_PKT_MASK\ +0x80000000 /* CSR_TX_WR_DMAD_AXI_LIMITER_EN_PKT[31] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_EN_PKT_SHFT\ +31 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_PKT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_PKT_MASK \ + 0x70000000 /* CSR_TX_WR_DMAD_AXI_LIMITER_PKT[30..28] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_PKT_SHFT \ + 28 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_EN_REQ_ADDR\ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_EN_REQ_MASK\ +0x08000000 /* CSR_TX_WR_DMAD_AXI_LIMITER_EN_REQ[27] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_EN_REQ_SHFT\ +27 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_REQ_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_REQ_MASK \ + 0x07000000 /* CSR_TX_WR_DMAD_AXI_LIMITER_REQ[26..24] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_REQ_SHFT \ + 24 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_EN_PKT_ADDR\ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_EN_PKT_MASK\ +0x00800000 /* CSR_TX_RD_DMAD_AXI_LIMITER_EN_PKT[23] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_EN_PKT_SHFT\ +23 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_PKT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_PKT_MASK \ + 0x00700000 /* CSR_TX_RD_DMAD_AXI_LIMITER_PKT[22..20] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_PKT_SHFT \ + 20 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_EN_REQ_ADDR\ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_EN_REQ_MASK\ +0x00080000 /* CSR_TX_RD_DMAD_AXI_LIMITER_EN_REQ[19] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_EN_REQ_SHFT\ +19 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_REQ_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_REQ_MASK \ + 0x00070000 /* CSR_TX_RD_DMAD_AXI_LIMITER_REQ[18..16] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_REQ_SHFT \ + 16 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_EN_PKT_ADDR\ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_EN_PKT_MASK\ +0x00008000 /* CSR_RX_WR_DMAD_AXI_LIMITER_EN_PKT[15] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_EN_PKT_SHFT\ +15 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_PKT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_PKT_MASK \ + 0x00007000 /* CSR_RX_WR_DMAD_AXI_LIMITER_PKT[14..12] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_PKT_SHFT \ + 12 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_EN_REQ_ADDR\ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_EN_REQ_MASK\ +0x00000800 /* CSR_RX_WR_DMAD_AXI_LIMITER_EN_REQ[11] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_EN_REQ_SHFT\ +11 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_REQ_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_REQ_MASK \ + 0x00000700 /* CSR_RX_WR_DMAD_AXI_LIMITER_REQ[10..8] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_REQ_SHFT \ + 8 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_EN_PKT_ADDR\ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_EN_PKT_MASK\ +0x00000080 /* CSR_RX_RD_DMAD_AXI_LIMITER_EN_PKT[7] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_EN_PKT_SHFT\ +7 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_PKT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_PKT_MASK \ + 0x00000070 /* CSR_RX_RD_DMAD_AXI_LIMITER_PKT[6..4] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_PKT_SHFT \ + 4 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_EN_REQ_ADDR\ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_EN_REQ_MASK\ +0x00000008 /* CSR_RX_RD_DMAD_AXI_LIMITER_EN_REQ[3] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_EN_REQ_SHFT\ +3 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_REQ_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_REQ_MASK \ + 0x00000007 /* CSR_RX_RD_DMAD_AXI_LIMITER_REQ[2..0] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_REQ_SHFT \ + 0 + +/* +* ---WPDMA_TX_QOS_LMT_CFG3 (0x7C025000 + 0x2CC)--- +* CSR_AUX_RX_RD_DMAD_AXI_LIMITER_REQ[2..0] - (RW) QoS CR, Limiter value selected +* by PP dynamically +* RESERVED3[3] - (RO) Reserved bits +* CSR_AUX_RX_RD_DMAD_AXI_LIMITER_PKT[6..4] - (RW) QoS CR, Limiter value selected +* by PP dynamically +* RESERVED7[7] - (RO) Reserved bits +* CSR_AUX_RX_WR_DMAD_AXI_LIMITER_REQ[10..8] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED11[11] - (RO) Reserved bits +* CSR_AUX_RX_WR_DMAD_AXI_LIMITER_PKT[14..12] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED15[15] - (RO) Reserved bits +* CSR_AUX_TX_RD_DMAD_AXI_LIMITER_REQ[18..16] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED19[19] - (RO) Reserved bits +* CSR_AUX_TX_RD_DMAD_AXI_LIMITER_PKT[22..20] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED23[23] - (RO) Reserved bits +* CSR_AUX_TX_WR_DMAD_AXI_LIMITER_REQ[26..24] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED27[27] - (RO) Reserved bits +* CSR_AUX_TX_WR_DMAD_AXI_LIMITER_PKT[30..28] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED31[31] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_WR_DMAD_AXI_LIMITER_PKT_ADD\ +R \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_WR_DMAD_AXI_LIMITER_PKT_MAS\ +K \ +0x70000000 /* CSR_AUX_TX_WR_DMAD_AXI_LIMITER_PKT[30..28] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_WR_DMAD_AXI_LIMITER_PKT_SHF\ +T \ +28 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_WR_DMAD_AXI_LIMITER_REQ_ADD\ +R \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_WR_DMAD_AXI_LIMITER_REQ_MAS\ +K \ +0x07000000 /* CSR_AUX_TX_WR_DMAD_AXI_LIMITER_REQ[26..24] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_WR_DMAD_AXI_LIMITER_REQ_SHF\ +T \ +24 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_RD_DMAD_AXI_LIMITER_PKT_ADD\ +R \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_RD_DMAD_AXI_LIMITER_PKT_MAS\ +K \ +0x00700000 /* CSR_AUX_TX_RD_DMAD_AXI_LIMITER_PKT[22..20] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_RD_DMAD_AXI_LIMITER_PKT_SHF\ +T \ +20 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_RD_DMAD_AXI_LIMITER_REQ_ADD\ +R \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_RD_DMAD_AXI_LIMITER_REQ_MAS\ +K \ +0x00070000 /* CSR_AUX_TX_RD_DMAD_AXI_LIMITER_REQ[18..16] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_RD_DMAD_AXI_LIMITER_REQ_SHF\ +T \ +16 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_WR_DMAD_AXI_LIMITER_PKT_ADD\ +R \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_WR_DMAD_AXI_LIMITER_PKT_MAS\ +K \ +0x00007000 /* CSR_AUX_RX_WR_DMAD_AXI_LIMITER_PKT[14..12] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_WR_DMAD_AXI_LIMITER_PKT_SHF\ +T \ +12 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_WR_DMAD_AXI_LIMITER_REQ_ADD\ +R \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_WR_DMAD_AXI_LIMITER_REQ_MAS\ +K \ +0x00000700 /* CSR_AUX_RX_WR_DMAD_AXI_LIMITER_REQ[10..8] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_WR_DMAD_AXI_LIMITER_REQ_SHF\ +T \ +8 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_RD_DMAD_AXI_LIMITER_PKT_ADD\ +R \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_RD_DMAD_AXI_LIMITER_PKT_MAS\ +K \ +0x00000070 /* CSR_AUX_RX_RD_DMAD_AXI_LIMITER_PKT[6..4] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_RD_DMAD_AXI_LIMITER_PKT_SHF\ +T \ +4 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_RD_DMAD_AXI_LIMITER_REQ_ADD\ +R \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_RD_DMAD_AXI_LIMITER_REQ_MAS\ +K \ +0x00000007 /* CSR_AUX_RX_RD_DMAD_AXI_LIMITER_REQ[2..0] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_RD_DMAD_AXI_LIMITER_REQ_SHF\ +T \ +0 + +/* +* ---HOST_PRI_INT_STA (0x7C025000 + 0x2E0)--- +* host_pri_int_sts_0[0] - (W1C) rx_done_int[0], configuration interrupt please +* refer to 0x2E0 WPDMA_PRI_DLY_INT_CFG0[15:0] +* host_pri_int_sts_1[1] - (W1C) rx_done_int[1], configuration interrupt please +* refer to 0x2E0 WPDMA_PRI_DLY_INT_CFG0[31:16] +* RESERVED2[31..2] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_host_pri_int_sts_1_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_host_pri_int_sts_1_MASK \ + 0x00000002 /* host_pri_int_sts_1[1] */ +#define WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_host_pri_int_sts_1_SHFT 1 +#define WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_host_pri_int_sts_0_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_host_pri_int_sts_0_MASK \ + 0x00000001 /* host_pri_int_sts_0[0] */ +#define WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_host_pri_int_sts_0_SHFT 0 + +/* +* ---HOST_PER_INT_ENA_STA (0x7C025000 + 0x2E4)--- +* wpdma_per_int_sts[3..0] - (W1C) status bit for rx ring periodic delayed +* interrupt to tracking ring is full or not, start delayed interrupt timer when +* RX ring is not full from falling edge of full flag and reset when ring full +* flag is asserted +* RESERVED4[15..4] - (RO) Reserved bits +* wpdma_per_int_ena[19..16] - (RW) enable bit for rx ring periodic delayed +* interrupt to tracking ring is full or not, start delayed interrupt timer when +* RX ring is not full from falling edge of full flag and reset when ring full +* flag is asserted +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_HOST_PER_INT_ENA_STA_wpdma_per_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_PER_INT_ENA_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_PER_INT_ENA_STA_wpdma_per_int_ena_MASK \ + 0x000F0000 /* wpdma_per_int_ena[19..16] */ +#define WF_WFDMA_HOST_DMA1_HOST_PER_INT_ENA_STA_wpdma_per_int_ena_SHFT 16 +#define WF_WFDMA_HOST_DMA1_HOST_PER_INT_ENA_STA_wpdma_per_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_PER_INT_ENA_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_PER_INT_ENA_STA_wpdma_per_int_sts_MASK \ + 0x0000000F /* wpdma_per_int_sts[3..0] */ +#define WF_WFDMA_HOST_DMA1_HOST_PER_INT_ENA_STA_wpdma_per_int_sts_SHFT 0 + +/* +* ---HOST_PER_DLY_INT_CFG (0x7C025000 + 0x2E8)--- +* wpdma_per_max_ptime[7..0] - (RW) Specified Max pending time for the internal +* RX ring full flag falling edge. When the pending time equal or greater +* PER_MAX_PTIME x 20us or the # of pended TX_DONE_INT equal or greater than +* TX_MAX_PINT (see above), an Final TX_DLY_INT is generated +* Set to 0 will disable pending interrupt time check +* wpdma_per_dly_int_en[11..8] - (RW) RX periodic Delayed Interrupt Enable +* 1: Enable RX periodic delayed interrupt mechanism +* 0: Disable RX periodic delayed interrupt mechanism +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_HOST_PER_DLY_INT_CFG_wpdma_per_dly_int_en_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_PER_DLY_INT_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_PER_DLY_INT_CFG_wpdma_per_dly_int_en_MASK \ + 0x00000F00 /* wpdma_per_dly_int_en[11..8] */ +#define WF_WFDMA_HOST_DMA1_HOST_PER_DLY_INT_CFG_wpdma_per_dly_int_en_SHFT 8 +#define WF_WFDMA_HOST_DMA1_HOST_PER_DLY_INT_CFG_wpdma_per_max_ptime_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_PER_DLY_INT_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_PER_DLY_INT_CFG_wpdma_per_max_ptime_MASK \ + 0x000000FF /* wpdma_per_max_ptime[7..0] */ +#define WF_WFDMA_HOST_DMA1_HOST_PER_DLY_INT_CFG_wpdma_per_max_ptime_SHFT 0 + +/* +* ---WPDMA_PRI_DLY_INT_CFG0 (0x7C025000 + 0x2F0)--- +* PRI0_MAX_PTIME[7..0] - (RW) Specified Max pending time for the internal +* PRI0_DONE_INT. When the pending time equal or greater PRI0_MAX_PTIME x 20us or +* the # of pended PRI0_DONE_INT equal or greater than PRI0_MAX_PINT (see above), +* an Final PRI0_DLY_INT is generated +* Set to 0 will disable pending interrupt time check +* PRI0_MAX_PINT[14..8] - (RW) Specified Max # of pended interrupts. +* When the # of pended interrupts equal or greater than the value specified here +* or interrupt pending time reach the limit (See below), a Final PRI0_DLY_INT is +generated. +* Set to 0 will disable pending interrupt count check +* PRI0_DLY_INT_EN[15] - (RW) Priority Delayed Interrupt Enable +* 1: Enable Priority delayed interrupt mechanism +* 0: Disable Priority delayed interrupt mechanism +* In AXE host_dma0, these PRI1_* settings are for rx_ring[1]_int, and PRI0_* +* settings are for rx_ring[0]_int +* In AXE host_dma1, these PRI1_* settings are for rx_ring[0]_int, and PRI0_* +* settings are for Ored-tx_ring[14:0]_int +* In AXE mcu_dma0 and mcu_dma1, there are no priority interrupt thus no this +* 0x2E0 CR!! +* PRI1_MAX_PTIME[23..16] - (RW) Specified Max pending time for the internal +* PRI1_DONE_INT. When the pending time equal or greater PRI1_MAX_PTIME x 20us or +* the # of pended PRI1_DONE_INT equal or greater than PRI1_MAX_PINT (see above), +* an Final PRI1_DLY_INT is generated +* Set to 0 will disable pending interrupt time check +* PRI1_MAX_PINT[30..24] - (RW) Specified Max # of pended interrupts. +* When the # of pended interrupts equal or greater than the value specified here +* or interrupt pending time reach the limit (See below), a Final PRI1_DLY_INT is +generated. +* Set to 0 will disable pending interrupt count check +* PRI1_DLY_INT_EN[31] - (RW) Priority Delayed Interrupt Enable +* 1: Enable Priority delayed interrupt mechanism +* 0: Disable Priority delayed interrupt mechanism +* In AXE host_dma0, these PRI1_* settings are for rx_ring[1]_int, and PRI0_* +* settings are for rx_ring[0]_int +* In AXE host_dma1, these PRI1_* settings are for rx_ring[0]_int, and PRI0_* +* settings are for Ored-tx_ring[14:0]_int +* In AXE mcu_dma0 and mcu_dma1, there are no priority interrupt thus no this +* 0x2E0 CR!! +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI1_DLY_INT_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI1_DLY_INT_EN_MASK \ + 0x80000000 /* PRI1_DLY_INT_EN[31] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI1_DLY_INT_EN_SHFT 31 +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PINT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PINT_MASK \ + 0x7F000000 /* PRI1_MAX_PINT[30..24] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PINT_SHFT 24 +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PTIME_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PTIME_MASK \ + 0x00FF0000 /* PRI1_MAX_PTIME[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PTIME_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI0_DLY_INT_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI0_DLY_INT_EN_MASK \ + 0x00008000 /* PRI0_DLY_INT_EN[15] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI0_DLY_INT_EN_SHFT 15 +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PINT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PINT_MASK \ + 0x00007F00 /* PRI0_MAX_PINT[14..8] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PINT_SHFT 8 +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PTIME_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PTIME_MASK \ + 0x000000FF /* PRI0_MAX_PTIME[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PTIME_SHFT 0 + +/* +* ---WPDMA_TX_RING0_CTRL0 (0x7C025000 + 0x300)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring0 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING0_CTRL1 (0x7C025000 + 0x304)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring0. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring0 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING0_CTRL2 (0x7C025000 + 0x308)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING0_CTRL3 (0x7C025000 + 0x30c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING1_CTRL0 (0x7C025000 + 0x310)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring1 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING1_CTRL1 (0x7C025000 + 0x314)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring1. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring1 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING1_CTRL2 (0x7C025000 + 0x318)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING1_CTRL3 (0x7C025000 + 0x31c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING2_CTRL0 (0x7C025000 + 0x320)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring2 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING2_CTRL1 (0x7C025000 + 0x324)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring2. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring2 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING2_CTRL2 (0x7C025000 + 0x328)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING2_CTRL3 (0x7C025000 + 0x32c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING3_CTRL0 (0x7C025000 + 0x330)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring3 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING3_CTRL1 (0x7C025000 + 0x334)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring3. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring3 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING3_CTRL2 (0x7C025000 + 0x338)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING3_CTRL3 (0x7C025000 + 0x33c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING4_CTRL0 (0x7C025000 + 0x340)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring4 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING4_CTRL1 (0x7C025000 + 0x344)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring4. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring4 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING4_CTRL2 (0x7C025000 + 0x348)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING4_CTRL3 (0x7C025000 + 0x34c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING5_CTRL0 (0x7C025000 + 0x350)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring5 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING5_CTRL1 (0x7C025000 + 0x354)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring5. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring5 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING5_CTRL2 (0x7C025000 + 0x358)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING5_CTRL3 (0x7C025000 + 0x35c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING6_CTRL0 (0x7C025000 + 0x360)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring6 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING6_CTRL1 (0x7C025000 + 0x364)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring6. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring6 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING6_CTRL2 (0x7C025000 + 0x368)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING6_CTRL3 (0x7C025000 + 0x36c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING7_CTRL0 (0x7C025000 + 0x370)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring7 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING7_CTRL1 (0x7C025000 + 0x374)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring7. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring7 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING7_CTRL2 (0x7C025000 + 0x378)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING7_CTRL3 (0x7C025000 + 0x37c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING8_CTRL0 (0x7C025000 + 0x380)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring8 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING8_CTRL1 (0x7C025000 + 0x384)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring8. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring8 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING8_CTRL2 (0x7C025000 + 0x388)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING8_CTRL3 (0x7C025000 + 0x38c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING9_CTRL0 (0x7C025000 + 0x390)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring9 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING9_CTRL1 (0x7C025000 + 0x394)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring9. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring9 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING9_CTRL2 (0x7C025000 + 0x398)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING9_CTRL3 (0x7C025000 + 0x39c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING10_CTRL0 (0x7C025000 + 0x3a0)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring10 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING10_CTRL1 (0x7C025000 + 0x3a4)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring10. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring10 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING10_CTRL2 (0x7C025000 + 0x3a8)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING10_CTRL3 (0x7C025000 + 0x3ac)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING11_CTRL0 (0x7C025000 + 0x3b0)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring11 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING11_CTRL1 (0x7C025000 + 0x3b4)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring11. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring11 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING11_CTRL2 (0x7C025000 + 0x3b8)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING11_CTRL3 (0x7C025000 + 0x3bc)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING12_CTRL0 (0x7C025000 + 0x3c0)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring12 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING12_CTRL1 (0x7C025000 + 0x3c4)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring12. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring12 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING12_CTRL2 (0x7C025000 + 0x3c8)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING12_CTRL3 (0x7C025000 + 0x3cc)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING13_CTRL0 (0x7C025000 + 0x3d0)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring13 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING13_CTRL1 (0x7C025000 + 0x3d4)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring13. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring13 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING13_CTRL2 (0x7C025000 + 0x3d8)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING13_CTRL3 (0x7C025000 + 0x3dc)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING14_CTRL0 (0x7C025000 + 0x3e0)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring14 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING14_CTRL1 (0x7C025000 + 0x3e4)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring14. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring14 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING14_CTRL2 (0x7C025000 + 0x3e8)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING14_CTRL3 (0x7C025000 + 0x3ec)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING15_CTRL0 (0x7C025000 + 0x3f0)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring15 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING15_CTRL1 (0x7C025000 + 0x3f4)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring15. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring15 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING15_CTRL2 (0x7C025000 + 0x3f8)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING15_CTRL3 (0x7C025000 + 0x3fc)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING16_CTRL0 (0x7C025000 + 0x400)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_RING16 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING16_CTRL1 (0x7C025000 + 0x404)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_RING16. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring16 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING16_CTRL2 (0x7C025000 + 0x408)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING16_CTRL3 (0x7C025000 + 0x40c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING17_CTRL0 (0x7C025000 + 0x410)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring17 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING17_CTRL1 (0x7C025000 + 0x414)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring17. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring17 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING17_CTRL2 (0x7C025000 + 0x418)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING17_CTRL3 (0x7C025000 + 0x41c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING18_CTRL0 (0x7C025000 + 0x420)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring18 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING18_CTRL1 (0x7C025000 + 0x424)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring18. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring18 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING18_CTRL2 (0x7C025000 + 0x428)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING18_CTRL3 (0x7C025000 + 0x42c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING19_CTRL0 (0x7C025000 + 0x430)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring19 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING19_CTRL1 (0x7C025000 + 0x434)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring19. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring19 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING19_CTRL2 (0x7C025000 + 0x438)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING19_CTRL3 (0x7C025000 + 0x43c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING20_CTRL0 (0x7C025000 + 0x440)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring20 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING20_CTRL1 (0x7C025000 + 0x444)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring0. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring20 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING20_CTRL2 (0x7C025000 + 0x448)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING20_CTRL3 (0x7C025000 + 0x44c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING21_CTRL0 (0x7C025000 + 0x450)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring21 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING21_CTRL1 (0x7C025000 + 0x454)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring1. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring21 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING21_CTRL2 (0x7C025000 + 0x458)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING21_CTRL3 (0x7C025000 + 0x45c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING22_CTRL0 (0x7C025000 + 0x460)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring22 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING22_CTRL1 (0x7C025000 + 0x464)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring2. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring22 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING22_CTRL2 (0x7C025000 + 0x468)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING22_CTRL3 (0x7C025000 + 0x46c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING23_CTRL0 (0x7C025000 + 0x470)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring23 (8-DWORD aligned +address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING23_CTRL1 (0x7C025000 + 0x474)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in TXD_Ring3. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of TX_Ring23 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING23_CTRL2 (0x7C025000 + 0x478)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING23_CTRL3 (0x7C025000 + 0x47c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING0_CTRL0 (0x7C025000 + 0x500)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #0 (GE ports). It +* should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING0_CTRL1 (0x7C025000 + 0x504)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD Ring #0. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of RX_Ring0 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING0_CTRL2 (0x7C025000 + 0x508)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to allocate to RXD Ring +#0. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING0_CTRL3 (0x7C025000 + 0x50c)--- +* DMA_IDX[11..0] - (RW) In normal operation, user dma_index would udated by +* hardware when moving rx packet done. User should not write dma_index. +* Point to the next RXD DMA wants to use in FDS Ring#0. It should be a 8-DWORD +* aligned address. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING1_CTRL0 (0x7C025000 + 0x510)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #1 (GE ports). It +* should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING1_CTRL1 (0x7C025000 + 0x514)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD Ring #1. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of RX_Ring1 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING1_CTRL2 (0x7C025000 + 0x518)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to allocate to RXD Ring +#1. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING1_CTRL3 (0x7C025000 + 0x51c)--- +* DMA_IDX[11..0] - (RW) In normal operation, user dma_index would udated by +* hardware when moving rx packet done. User should not write dma_index. +* Point to the next RXD DMA wants to use in FDS Ring#1. It should be a 8-DWORD +* aligned address. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING2_CTRL0 (0x7C025000 + 0x520)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #2 (GE ports). It +* should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING2_CTRL1 (0x7C025000 + 0x524)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD Ring #2. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of RX_Ring2 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING2_CTRL2 (0x7C025000 + 0x528)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to allocate to RXD Ring +#2. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING2_CTRL3 (0x7C025000 + 0x52C)--- +* DMA_IDX[11..0] - (RW) In normal operation, user dma_index would udated by +* hardware when moving rx packet done. User should not write dma_index. +* Point to the next RXD DMA wants to use in FDS Ring#2. It should be a 8-DWORD +* aligned address. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING3_CTRL0 (0x7C025000 + 0x530)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #3 (GE ports). It +* should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING3_CTRL1 (0x7C025000 + 0x534)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD Ring #3. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of RX_Ring3 +* (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING3_CTRL2 (0x7C025000 + 0x538)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to allocate to RXD Ring +#3. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING3_CTRL3 (0x7C025000 + 0x53C)--- +* DMA_IDX[11..0] - (RW) In normal operation, user dma_index would udated by +* hardware when moving rx packet done. User should not write dma_index. +* Point to the next RXD DMA wants to use in FDS Ring#3. It should be a 8-DWORD +* aligned address. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING0_EXT_CTRL (0x7C025000 + 0x600)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #0 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING1_EXT_CTRL (0x7C025000 + 0x604)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #1 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING2_EXT_CTRL (0x7C025000 + 0x608)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #2 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING3_EXT_CTRL (0x7C025000 + 0x60C)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #3 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING4_EXT_CTRL (0x7C025000 + 0x610)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #4 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING5_EXT_CTRL (0x7C025000 + 0x614)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #5 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING6_EXT_CTRL (0x7C025000 + 0x618)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #6 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING7_EXT_CTRL (0x7C025000 + 0x61C)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #7 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING8_EXT_CTRL (0x7C025000 + 0x620)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #8 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING9_EXT_CTRL (0x7C025000 + 0x624)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #9 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING10_EXT_CTRL (0x7C025000 + 0x628)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #10 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING11_EXT_CTRL (0x7C025000 + 0x62C)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #11 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING12_EXT_CTRL (0x7C025000 + 0x630)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #12 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING13_EXT_CTRL (0x7C025000 + 0x634)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #13 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING14_EXT_CTRL (0x7C025000 + 0x638)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #14 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING15_EXT_CTRL (0x7C025000 + 0x63C)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #15 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING16_EXT_CTRL (0x7C025000 + 0x640)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #16 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING17_EXT_CTRL (0x7C025000 + 0x644)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #17 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING18_EXT_CTRL (0x7C025000 + 0x648)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #18 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING19_EXT_CTRL (0x7C025000 + 0x64C)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #19 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING20_EXT_CTRL (0x7C025000 + 0x650)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #20 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING21_EXT_CTRL (0x7C025000 + 0x654)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #21 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING22_EXT_CTRL (0x7C025000 + 0x658)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #22 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING23_EXT_CTRL (0x7C025000 + 0x65C)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #23 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING0_EXT_CTRL (0x7C025000 + 0x680)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #0 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING1_EXT_CTRL (0x7C025000 + 0x684)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #1 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING2_EXT_CTRL (0x7C025000 + 0x688)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #2 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING3_EXT_CTRL (0x7C025000 + 0x68C)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #3 Extension, to configure prefetch +* settings, like base_ptr means each prefetch ring's base address in internal +* prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_PERF_CFG (0x7C025000 + 0x900)--- +* AXI_MTR_PERF_SEL_W_CH[2..0] - (RW) csr_axi_mtr_perf_sel_w_ch +* AXI_MTR_BW_W_RST[3] - (RW) csr_axi_mtr_bw_w_rst +* AXI_MTR_LAT_W_RST[4] - (RW) csr_axi_mtr_lat_w_rst +* RESERVED5[7..5] - (RO) Reserved bits +* AXI_MTR_PERF_SEL_R_CH[10..8] - (RW) csr_axi_mtr_perf_sel_r_ch +* AXI_MTR_BW_R_RST[11] - (RW) csr_axi_mtr_bw_r_rst +* AXI_MTR_LAT_R_RST[12] - (RW) csr_axi_mtr_lat_r_rst +* RESERVED13[30..13] - (RO) Reserved bits +* AXI_MTR_ENABLE[31] - (RW) csr_axi_mtr_enable +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_ENABLE_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_ENABLE_MASK \ + 0x80000000 /* AXI_MTR_ENABLE[31] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_ENABLE_SHFT 31 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_LAT_R_RST_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_LAT_R_RST_MASK \ + 0x00001000 /* AXI_MTR_LAT_R_RST[12] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_LAT_R_RST_SHFT 12 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_BW_R_RST_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_BW_R_RST_MASK \ + 0x00000800 /* AXI_MTR_BW_R_RST[11] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_BW_R_RST_SHFT 11 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_PERF_SEL_R_CH_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_PERF_SEL_R_CH_MASK \ + 0x00000700 /* AXI_MTR_PERF_SEL_R_CH[10..8] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_PERF_SEL_R_CH_SHFT 8 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_LAT_W_RST_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_LAT_W_RST_MASK \ + 0x00000010 /* AXI_MTR_LAT_W_RST[4] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_LAT_W_RST_SHFT 4 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_BW_W_RST_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_BW_W_RST_MASK \ + 0x00000008 /* AXI_MTR_BW_W_RST[3] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_BW_W_RST_SHFT 3 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_PERF_SEL_W_CH_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_PERF_SEL_W_CH_MASK \ + 0x00000007 /* AXI_MTR_PERF_SEL_W_CH[2..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_CFG_AXI_MTR_PERF_SEL_W_CH_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_DBG_CFG (0x7C025000 + 0x904)--- +* AXI_MST_DBG_CH_SEL[2..0] - (RW) csr_axi_mst_dbg_ch_sel[2:0] +* RESERVED3[7..3] - (RO) Reserved bits +* MASTER0_AXI_AW_CH_COUNTER_SET[8] - (RW) master0 axi_aw_ch_counter_set +* MASTER0_AXI_W_CH_COUNTER_SET[9] - (RW) master0 axi_w_ch_counter_set +* MASTER0_AXI_B_CH_COUNTER_SET[10] - (RW) master0 axi_b_ch_counter_set +* MASTER0_AXI_AR_CH_COUNTER_SET[11] - (RW) master0 axi_ar_ch_counter_set +* MASTER0_AXI_R_CH_COUNTER_SET[12] - (RW) master0 axi_r_ch_counter_set +* MASTER1_AXI_AW_CH_COUNTER_SET[13] - (RW) master1 axi_aw_ch_counter_set +* MASTER1_AXI_W_CH_COUNTER_SET[14] - (RW) master1 axi_w_ch_counter_set +* MASTER1_AXI_B_CH_COUNTER_SET[15] - (RW) master1 axi_b_ch_counter_set +* MASTER1_AXI_AR_CH_COUNTER_SET[16] - (RW) master1 axi_ar_ch_counter_set +* MASTER1_AXI_R_CH_COUNTER_SET[17] - (RW) master1 axi_r_ch_counter_set +* MASTER2_AXI_AW_CH_COUNTER_SET[18] - (RW) master2 axi_aw_ch_counter_set +* MASTER2_AXI_W_CH_COUNTER_SET[19] - (RW) master2 axi_w_ch_counter_set +* MASTER2_AXI_B_CH_COUNTER_SET[20] - (RW) master2 axi_b_ch_counter_set +* MASTER2_AXI_AR_CH_COUNTER_SET[21] - (RW) master2 axi_ar_ch_counter_set +* MASTER2_AXI_R_CH_COUNTER_SET[22] - (RW) master2 axi_r_ch_counter_set +* MASTER3_AXI_AW_CH_COUNTER_SET[23] - (RW) master3 axi_aw_ch_counter_set +* MASTER3_AXI_W_CH_COUNTER_SET[24] - (RW) master3 axi_w_ch_counter_set +* MASTER3_AXI_B_CH_COUNTER_SET[25] - (RW) master3 axi_b_ch_counter_set +* MASTER3_AXI_AR_CH_COUNTER_SET[26] - (RW) master3 axi_ar_ch_counter_set +* MASTER3_AXI_R_CH_COUNTER_SET[27] - (RW) master3 axi_r_ch_counter_set +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER3_AXI_R_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER3_AXI_R_CH_COUNTER_SET_MASK \ + 0x08000000 /* MASTER3_AXI_R_CH_COUNTER_SET[27] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER3_AXI_R_CH_COUNTER_SET_SHFT \ + 27 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER3_AXI_AR_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER3_AXI_AR_CH_COUNTER_SET_MASK \ + 0x04000000 /* MASTER3_AXI_AR_CH_COUNTER_SET[26] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER3_AXI_AR_CH_COUNTER_SET_SHFT \ + 26 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER3_AXI_B_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER3_AXI_B_CH_COUNTER_SET_MASK \ + 0x02000000 /* MASTER3_AXI_B_CH_COUNTER_SET[25] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER3_AXI_B_CH_COUNTER_SET_SHFT \ + 25 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER3_AXI_W_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER3_AXI_W_CH_COUNTER_SET_MASK \ + 0x01000000 /* MASTER3_AXI_W_CH_COUNTER_SET[24] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER3_AXI_W_CH_COUNTER_SET_SHFT \ + 24 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER3_AXI_AW_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER3_AXI_AW_CH_COUNTER_SET_MASK \ + 0x00800000 /* MASTER3_AXI_AW_CH_COUNTER_SET[23] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER3_AXI_AW_CH_COUNTER_SET_SHFT \ + 23 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_R_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_R_CH_COUNTER_SET_MASK \ + 0x00400000 /* MASTER2_AXI_R_CH_COUNTER_SET[22] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_R_CH_COUNTER_SET_SHFT \ + 22 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_AR_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_AR_CH_COUNTER_SET_MASK \ + 0x00200000 /* MASTER2_AXI_AR_CH_COUNTER_SET[21] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_AR_CH_COUNTER_SET_SHFT \ + 21 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_B_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_B_CH_COUNTER_SET_MASK \ + 0x00100000 /* MASTER2_AXI_B_CH_COUNTER_SET[20] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_B_CH_COUNTER_SET_SHFT \ + 20 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_W_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_W_CH_COUNTER_SET_MASK \ + 0x00080000 /* MASTER2_AXI_W_CH_COUNTER_SET[19] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_W_CH_COUNTER_SET_SHFT \ + 19 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_AW_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_AW_CH_COUNTER_SET_MASK \ + 0x00040000 /* MASTER2_AXI_AW_CH_COUNTER_SET[18] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER2_AXI_AW_CH_COUNTER_SET_SHFT \ + 18 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_R_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_R_CH_COUNTER_SET_MASK \ + 0x00020000 /* MASTER1_AXI_R_CH_COUNTER_SET[17] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_R_CH_COUNTER_SET_SHFT \ + 17 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_AR_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_AR_CH_COUNTER_SET_MASK \ + 0x00010000 /* MASTER1_AXI_AR_CH_COUNTER_SET[16] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_AR_CH_COUNTER_SET_SHFT \ + 16 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_B_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_B_CH_COUNTER_SET_MASK \ + 0x00008000 /* MASTER1_AXI_B_CH_COUNTER_SET[15] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_B_CH_COUNTER_SET_SHFT \ + 15 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_W_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_W_CH_COUNTER_SET_MASK \ + 0x00004000 /* MASTER1_AXI_W_CH_COUNTER_SET[14] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_W_CH_COUNTER_SET_SHFT \ + 14 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_AW_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_AW_CH_COUNTER_SET_MASK \ + 0x00002000 /* MASTER1_AXI_AW_CH_COUNTER_SET[13] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER1_AXI_AW_CH_COUNTER_SET_SHFT \ + 13 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_R_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_R_CH_COUNTER_SET_MASK \ + 0x00001000 /* MASTER0_AXI_R_CH_COUNTER_SET[12] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_R_CH_COUNTER_SET_SHFT \ + 12 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_AR_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_AR_CH_COUNTER_SET_MASK \ + 0x00000800 /* MASTER0_AXI_AR_CH_COUNTER_SET[11] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_AR_CH_COUNTER_SET_SHFT \ + 11 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_B_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_B_CH_COUNTER_SET_MASK \ + 0x00000400 /* MASTER0_AXI_B_CH_COUNTER_SET[10] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_B_CH_COUNTER_SET_SHFT \ + 10 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_W_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_W_CH_COUNTER_SET_MASK \ + 0x00000200 /* MASTER0_AXI_W_CH_COUNTER_SET[9] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_W_CH_COUNTER_SET_SHFT \ + 9 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_AW_CH_COUNTER_SET_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_AW_CH_COUNTER_SET_MASK \ + 0x00000100 /* MASTER0_AXI_AW_CH_COUNTER_SET[8] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_MASTER0_AXI_AW_CH_COUNTER_SET_SHFT \ + 8 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_AXI_MST_DBG_CH_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_AXI_MST_DBG_CH_SEL_MASK \ + 0x00000007 /* AXI_MST_DBG_CH_SEL[2..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_CFG_AXI_MST_DBG_CH_SEL_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_PERF_W_STA0 (0x7C025000 + 0x910)--- +* WR_REQ_AVG_LAT[9..0] - (RO) req_avg_lat[9:0](long-term average) +* WR_REQ_PEAK_LAT[19..10] - (RO) req_peak_lat[9:0] +* WR_REQ_LAT[29..20] - (RO) req_lat[9:0](shot-term average) +* RESERVED[31..30] - (RO) tied constant +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA0_WR_REQ_LAT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA0_WR_REQ_LAT_MASK \ + 0x3FF00000 /* WR_REQ_LAT[29..20] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA0_WR_REQ_LAT_SHFT 20 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA0_WR_REQ_PEAK_LAT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA0_WR_REQ_PEAK_LAT_MASK \ + 0x000FFC00 /* WR_REQ_PEAK_LAT[19..10] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA0_WR_REQ_PEAK_LAT_SHFT 10 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA0_WR_REQ_AVG_LAT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA0_WR_REQ_AVG_LAT_MASK \ + 0x000003FF /* WR_REQ_AVG_LAT[9..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA0_WR_REQ_AVG_LAT_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_PERF_W_STA1 (0x7C025000 + 0x914)--- +* WR_ACK_AVG_LAT[9..0] - (RO) ack_avg_lat[9:0](long-term average) +* WR_ACK_PEAK_LAT[19..10] - (RO) ack_peak_lat[9:0] +* WR_ACK_LAT[29..20] - (RO) ack_lat[9:0](shot-term average) +* RESERVED[31..30] - (RO) tied constant +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA1_WR_ACK_LAT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA1_WR_ACK_LAT_MASK \ + 0x3FF00000 /* WR_ACK_LAT[29..20] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA1_WR_ACK_LAT_SHFT 20 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA1_WR_ACK_PEAK_LAT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA1_WR_ACK_PEAK_LAT_MASK \ + 0x000FFC00 /* WR_ACK_PEAK_LAT[19..10] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA1_WR_ACK_PEAK_LAT_SHFT 10 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA1_WR_ACK_AVG_LAT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA1_WR_ACK_AVG_LAT_MASK \ + 0x000003FF /* WR_ACK_AVG_LAT[9..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA1_WR_ACK_AVG_LAT_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_PERF_W_STA2 (0x7C025000 + 0x918)--- +* WR_BW[9..0] - (RO) bw[9:0](long-term average) +* WR_PEAK_BW[19..10] - (RO) peak_bw[9:0] +* WR_AVG_BW[29..20] - (RO) avg_bw[9:0](shot-term average) +* RESERVED[31..30] - (RO) tied constant +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA2_WR_AVG_BW_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA2_WR_AVG_BW_MASK \ + 0x3FF00000 /* WR_AVG_BW[29..20] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA2_WR_AVG_BW_SHFT 20 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA2_WR_PEAK_BW_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA2_WR_PEAK_BW_MASK \ + 0x000FFC00 /* WR_PEAK_BW[19..10] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA2_WR_PEAK_BW_SHFT 10 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA2_WR_BW_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA2_WR_BW_MASK \ + 0x000003FF /* WR_BW[9..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA2_WR_BW_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_PERF_W_STA3 (0x7C025000 + 0x91C)--- +* WR_LAT[9..0] - (RO) lat[9:0](long-term average) +* WR_PEAK_LAT[19..10] - (RO) peak_lat[9:0] +* WR_AVG_LAT[29..20] - (RO) avg_lat[9:0](shot-term average) +* RESERVED[31..30] - (RO) tied constant +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA3_WR_AVG_LAT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA3_WR_AVG_LAT_MASK \ + 0x3FF00000 /* WR_AVG_LAT[29..20] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA3_WR_AVG_LAT_SHFT 20 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA3_WR_PEAK_LAT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA3_WR_PEAK_LAT_MASK \ + 0x000FFC00 /* WR_PEAK_LAT[19..10] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA3_WR_PEAK_LAT_SHFT 10 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA3_WR_LAT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA3_WR_LAT_MASK \ + 0x000003FF /* WR_LAT[9..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_W_STA3_WR_LAT_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_PERF_R_STA0 (0x7C025000 + 0x920)--- +* RD_REQ_AVG_LAT[9..0] - (RO) req_avg_lat[9:0](long-term average) +* RD_REQ_PEAK_LAT[19..10] - (RO) req_peak_lat[9:0] +* RD_REQ_LAT[29..20] - (RO) req_lat[9:0](shot-term average) +* RESERVED[31..30] - (RO) tied constant +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA0_RD_REQ_LAT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA0_RD_REQ_LAT_MASK \ + 0x3FF00000 /* RD_REQ_LAT[29..20] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA0_RD_REQ_LAT_SHFT 20 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA0_RD_REQ_PEAK_LAT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA0_RD_REQ_PEAK_LAT_MASK \ + 0x000FFC00 /* RD_REQ_PEAK_LAT[19..10] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA0_RD_REQ_PEAK_LAT_SHFT 10 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA0_RD_REQ_AVG_LAT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA0_RD_REQ_AVG_LAT_MASK \ + 0x000003FF /* RD_REQ_AVG_LAT[9..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA0_RD_REQ_AVG_LAT_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_PERF_R_STA1 (0x7C025000 + 0x924)--- +* RD_ACK_AVG_LAT[9..0] - (RO) ack_avg_lat[9:0](long-term average) +* RD_ACK_PEAK_LAT[19..10] - (RO) ack_peak_lat[9:0] +* RD_ACK_LAT[29..20] - (RO) ack_lat[9:0](shot-term average) +* RESERVED[31..30] - (RO) tied constant +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA1_RD_ACK_LAT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA1_RD_ACK_LAT_MASK \ + 0x3FF00000 /* RD_ACK_LAT[29..20] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA1_RD_ACK_LAT_SHFT 20 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA1_RD_ACK_PEAK_LAT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA1_RD_ACK_PEAK_LAT_MASK \ + 0x000FFC00 /* RD_ACK_PEAK_LAT[19..10] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA1_RD_ACK_PEAK_LAT_SHFT 10 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA1_RD_ACK_AVG_LAT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA1_RD_ACK_AVG_LAT_MASK \ + 0x000003FF /* RD_ACK_AVG_LAT[9..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA1_RD_ACK_AVG_LAT_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_PERF_R_STA2 (0x7C025000 + 0x928)--- +* RD_BW[9..0] - (RO) bw[9:0](long-term average) +* RD_PEAK_BW[19..10] - (RO) peak_bw[9:0] +* RD_AVG_BW[29..20] - (RO) avg_bw[9:0](shot-term average) +* RESERVED[31..30] - (RO) tied constant +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA2_RD_AVG_BW_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA2_RD_AVG_BW_MASK \ + 0x3FF00000 /* RD_AVG_BW[29..20] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA2_RD_AVG_BW_SHFT 20 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA2_RD_PEAK_BW_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA2_RD_PEAK_BW_MASK \ + 0x000FFC00 /* RD_PEAK_BW[19..10] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA2_RD_PEAK_BW_SHFT 10 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA2_RD_BW_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA2_RD_BW_MASK \ + 0x000003FF /* RD_BW[9..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA2_RD_BW_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_PERF_R_STA3 (0x7C025000 + 0x92C)--- +* RD_LAT[9..0] - (RO) lat[9:0](long-term average) +* RD_PEAK_LAT[19..10] - (RO) peak_lat[9:0] +* RD_AVG_LAT[29..20] - (RO) avg_lat[9:0](shot-term average) +* RESERVED[31..30] - (RO) tied constant +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA3_RD_AVG_LAT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA3_RD_AVG_LAT_MASK \ + 0x3FF00000 /* RD_AVG_LAT[29..20] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA3_RD_AVG_LAT_SHFT 20 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA3_RD_PEAK_LAT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA3_RD_PEAK_LAT_MASK \ + 0x000FFC00 /* RD_PEAK_LAT[19..10] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA3_RD_PEAK_LAT_SHFT 10 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA3_RD_LAT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA3_RD_LAT_MASK \ + 0x000003FF /* RD_LAT[9..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_PERF_R_STA3_RD_LAT_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_DBG_OUT0 (0x7C025000 + 0x930)--- +* AXI_AW_CH_COUNTER[7..0] - (RO) axi_aw_ch_counter[7:0] +* AXI_W_CH_COUNTER[15..8] - (RO) axi_w_ch_counter[7:0] +* AXI_B_CH_COUNTER[23..16] - (RO) axi_b_ch_counter[7:0] +* AXI_AR_CH_COUNTER[31..24] - (RO) axi_ar_ch_counter[7:0] +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT0_AXI_AR_CH_COUNTER_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT0_AXI_AR_CH_COUNTER_MASK \ + 0xFF000000 /* AXI_AR_CH_COUNTER[31..24] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT0_AXI_AR_CH_COUNTER_SHFT 24 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT0_AXI_B_CH_COUNTER_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT0_AXI_B_CH_COUNTER_MASK \ + 0x00FF0000 /* AXI_B_CH_COUNTER[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT0_AXI_B_CH_COUNTER_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT0_AXI_W_CH_COUNTER_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT0_AXI_W_CH_COUNTER_MASK \ + 0x0000FF00 /* AXI_W_CH_COUNTER[15..8] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT0_AXI_W_CH_COUNTER_SHFT 8 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT0_AXI_AW_CH_COUNTER_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT0_AXI_AW_CH_COUNTER_MASK \ + 0x000000FF /* AXI_AW_CH_COUNTER[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT0_AXI_AW_CH_COUNTER_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_DBG_OUT1 (0x7C025000 + 0x934)--- +* AXI_R_CH_COUNTER[7..0] - (RO) axi_r_ch_counter[7:0] +* AW_CURRENT_LEN[15..8] - (RO) aw_current_len[8:0] +* AR_CURRENT_LEN[23..16] - (RO) ar_current_len[8:0] +* RESERVED[31..24] - (RO) tied constant +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT1_AR_CURRENT_LEN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT1_AR_CURRENT_LEN_MASK \ + 0x00FF0000 /* AR_CURRENT_LEN[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT1_AR_CURRENT_LEN_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT1_AW_CURRENT_LEN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT1_AW_CURRENT_LEN_MASK \ + 0x0000FF00 /* AW_CURRENT_LEN[15..8] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT1_AW_CURRENT_LEN_SHFT 8 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT1_AXI_R_CH_COUNTER_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT1_AXI_R_CH_COUNTER_MASK \ + 0x000000FF /* AXI_R_CH_COUNTER[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT1_AXI_R_CH_COUNTER_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_DBG_OUT2 (0x7C025000 + 0x938)--- +* AWVALID[0] - (RO) awvalid +* AWREADY[1] - (RO) awready +* WVALID[2] - (RO) wvalid +* WREADY[3] - (RO) wready +* BVALID[4] - (RO) bvalid +* BREADY[5] - (RO) bready +* ARVALID[6] - (RO) arvalid +* ARREADY[7] - (RO) arready +* RVALID[8] - (RO) rvalid +* RREADY[9] - (RO) rready +* RESERVED10[31..10] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_RREADY_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_RREADY_MASK \ + 0x00000200 /* RREADY[9] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_RREADY_SHFT 9 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_RVALID_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_RVALID_MASK \ + 0x00000100 /* RVALID[8] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_RVALID_SHFT 8 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_ARREADY_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_ARREADY_MASK \ + 0x00000080 /* ARREADY[7] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_ARREADY_SHFT 7 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_ARVALID_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_ARVALID_MASK \ + 0x00000040 /* ARVALID[6] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_ARVALID_SHFT 6 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_BREADY_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_BREADY_MASK \ + 0x00000020 /* BREADY[5] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_BREADY_SHFT 5 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_BVALID_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_BVALID_MASK \ + 0x00000010 /* BVALID[4] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_BVALID_SHFT 4 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_WREADY_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_WREADY_MASK \ + 0x00000008 /* WREADY[3] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_WREADY_SHFT 3 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_WVALID_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_WVALID_MASK \ + 0x00000004 /* WVALID[2] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_WVALID_SHFT 2 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_AWREADY_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_AWREADY_MASK \ + 0x00000002 /* AWREADY[1] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_AWREADY_SHFT 1 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_AWVALID_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_AWVALID_MASK \ + 0x00000001 /* AWVALID[0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT2_AWVALID_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_DBG_OUT3 (0x7C025000 + 0x93C)--- +* AR_CURRENT_ADDRESS[31..0] - (RO) ar_current_address[31:0] +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT3_AR_CURRENT_ADDRESS_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT3_AR_CURRENT_ADDRESS_MASK \ + 0xFFFFFFFF /* AR_CURRENT_ADDRESS[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT3_AR_CURRENT_ADDRESS_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_DBG_OUT4 (0x7C025000 + 0x940)--- +* AW_CURRENT_ADDRESS[31..0] - (RO) aw_current_address[31:0] +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT4_AW_CURRENT_ADDRESS_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT4_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT4_AW_CURRENT_ADDRESS_MASK \ + 0xFFFFFFFF /* AW_CURRENT_ADDRESS[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT4_AW_CURRENT_ADDRESS_SHFT 0 + +/* +* ---WPDMA_AXI_MTR_DBG_OUT5 (0x7C025000 + 0x944)--- +* AR_CURRENT_ADDRESS_EXT[3..0] - (RO) ar_current_address[35:32] +* RESERVED4[15..4] - (RO) Reserved bits +* AW_CURRENT_ADDRESS_EXT[19..16] - (RO) aw_current_address[35:32] +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT5_AW_CURRENT_ADDRESS_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT5_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT5_AW_CURRENT_ADDRESS_EXT_MASK \ + 0x000F0000 /* AW_CURRENT_ADDRESS_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT5_AW_CURRENT_ADDRESS_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT5_AR_CURRENT_ADDRESS_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT5_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT5_AR_CURRENT_ADDRESS_EXT_MASK \ + 0x0000000F /* AR_CURRENT_ADDRESS_EXT[3..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MTR_DBG_OUT5_AR_CURRENT_ADDRESS_EXT_SHFT 0 + +/* +* ---WPDMA_AXI_MST_SLEEP_STA0 (0x7C025000 + 0x980)--- +* tx_pfet_cmd_state_idle[0] - (RO) cmd_state_idle +* tx_pfet_ar_cs_idle[1] - (RO) ar_cs_idle +* tx_pfet_axi_dp_cs_idle[2] - (RO) axi_dp_cs_idle +* tx_pfet_ar_cs_sleep[3] - (RO) ar_cs_sleep +* tx_pfet_buf_empty_axi_outstanding[4] - (RO) buf_empty(axi_outstanding) +* tx_pfet_data_fifo_empty[5] - (RO) data_fifo_empty +* RESERVED6[7..6] - (RO) Reserved bits +* tx_pfet_dma_req_fifo_empty[8] - (RO) dma_req_fifo_empty +* tx_pfet_axi_req_fifo_empty[9] - (RO) axi_req_fifo_empty +* tx_pfet_axi_pkt_fifo_empty[10] - (RO) axi_pkt_fifo_empty +* RESERVED11[11] - (RO) Reserved bits +* tx_pfet_axi_outstanding_req[15..12] - (RO) current pipelined +* axi_outstanding_req number +* pf_dfet_rx_cmd_state_idle[16] - (RO) cmd_state_idle +* pf_dfet_rx_ar_cs_idle[17] - (RO) ar_cs_idle +* pf_dfet_rx_axi_dp_cs_idle[18] - (RO) axi_dp_cs_idle +* pf_dfet_rx_ar_cs_sleep[19] - (RO) ar_cs_sleep +* pf_dfet_rx_buf_empty_axi_outstanding[20] - (RO) buf_empty(axi_outstanding) +* RESERVED21[23..21] - (RO) Reserved bits +* pf_dfet_rx_dma_req_fifo_empty[24] - (RO) dma_req_fifo_empty +* pf_dfet_rx_axi_req_fifo_empty[25] - (RO) axi_req_fifo_empty +* pf_dfet_rx_axi_pkt_fifo_empty[26] - (RO) axi_pkt_fifo_empty +* RESERVED27[27] - (RO) Reserved bits +* pf_dfet_rx_axi_outstanding_req[31..28] - (RO) current pipelined +* axi_outstanding_req number +*/ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_axi_outstanding_req_ADDR\ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_axi_outstanding_req_MASK\ +0xF0000000 /* pf_dfet_rx_axi_outstanding_req[31..28] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_axi_outstanding_req_SHFT\ +28 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_axi_pkt_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_axi_pkt_fifo_empty_MASK \ + 0x04000000 /* pf_dfet_rx_axi_pkt_fifo_empty[26] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_axi_pkt_fifo_empty_SHFT \ + 26 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_axi_req_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_axi_req_fifo_empty_MASK \ + 0x02000000 /* pf_dfet_rx_axi_req_fifo_empty[25] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_axi_req_fifo_empty_SHFT \ + 25 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_dma_req_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_dma_req_fifo_empty_MASK \ + 0x01000000 /* pf_dfet_rx_dma_req_fifo_empty[24] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_dma_req_fifo_empty_SHFT \ + 24 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_buf_empty_axi_outstandin\ +g_ADDR \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_buf_empty_axi_outstandin\ +g_MASK \ +0x00100000 /* pf_dfet_rx_buf_empty_axi_outstanding[20] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_buf_empty_axi_outstandin\ +g_SHFT \ +20 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_ar_cs_sleep_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_ar_cs_sleep_MASK \ + 0x00080000 /* pf_dfet_rx_ar_cs_sleep[19] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_ar_cs_sleep_SHFT \ + 19 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_axi_dp_cs_idle_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_axi_dp_cs_idle_MASK \ + 0x00040000 /* pf_dfet_rx_axi_dp_cs_idle[18] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_axi_dp_cs_idle_SHFT \ + 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_ar_cs_idle_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_ar_cs_idle_MASK \ + 0x00020000 /* pf_dfet_rx_ar_cs_idle[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_ar_cs_idle_SHFT \ + 17 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_cmd_state_idle_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_cmd_state_idle_MASK \ + 0x00010000 /* pf_dfet_rx_cmd_state_idle[16] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_pf_dfet_rx_cmd_state_idle_SHFT \ + 16 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_axi_outstanding_req_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_axi_outstanding_req_MASK \ + 0x0000F000 /* tx_pfet_axi_outstanding_req[15..12] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_axi_outstanding_req_SHFT \ + 12 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_axi_pkt_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_axi_pkt_fifo_empty_MASK \ + 0x00000400 /* tx_pfet_axi_pkt_fifo_empty[10] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_axi_pkt_fifo_empty_SHFT \ + 10 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_axi_req_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_axi_req_fifo_empty_MASK \ + 0x00000200 /* tx_pfet_axi_req_fifo_empty[9] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_axi_req_fifo_empty_SHFT \ + 9 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_dma_req_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_dma_req_fifo_empty_MASK \ + 0x00000100 /* tx_pfet_dma_req_fifo_empty[8] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_dma_req_fifo_empty_SHFT \ + 8 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_data_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_data_fifo_empty_MASK \ + 0x00000020 /* tx_pfet_data_fifo_empty[5] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_data_fifo_empty_SHFT \ + 5 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_buf_empty_axi_outstanding_A\ +DDR \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_buf_empty_axi_outstanding_M\ +ASK \ +0x00000010 /* tx_pfet_buf_empty_axi_outstanding[4] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_buf_empty_axi_outstanding_S\ +HFT \ +4 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_ar_cs_sleep_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_ar_cs_sleep_MASK \ + 0x00000008 /* tx_pfet_ar_cs_sleep[3] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_ar_cs_sleep_SHFT 3 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_axi_dp_cs_idle_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_axi_dp_cs_idle_MASK \ + 0x00000004 /* tx_pfet_axi_dp_cs_idle[2] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_axi_dp_cs_idle_SHFT \ + 2 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_ar_cs_idle_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_ar_cs_idle_MASK \ + 0x00000002 /* tx_pfet_ar_cs_idle[1] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_ar_cs_idle_SHFT 1 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_cmd_state_idle_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_cmd_state_idle_MASK \ + 0x00000001 /* tx_pfet_cmd_state_idle[0] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA0_tx_pfet_cmd_state_idle_SHFT \ + 0 + +/* +* ---WPDMA_AXI_MST_SLEEP_STA1 (0x7C025000 + 0x984)--- +* pf_dfet_tx_cmd_state_idle[0] - (RO) cmd_state_idle +* pf_dfet_tx_ar_cs_idle[1] - (RO) ar_cs_idle +* pf_dfet_tx_axi_dp_cs_idle[2] - (RO) axi_dp_cs_idle +* pf_dfet_tx_ar_cs_sleep[3] - (RO) ar_cs_sleep +* pf_dfet_tx_buf_empty_axi_outstanding[4] - (RO) buf_empty(axi_outstanding) +* RESERVED5[7..5] - (RO) Reserved bits +* pf_dfet_tx_dma_req_fifo_empty[8] - (RO) dma_req_fifo_empty +* pf_dfet_tx_axi_req_fifo_empty[9] - (RO) axi_req_fifo_empty +* pf_dfet_tx_axi_pkt_fifo_empty[10] - (RO) axi_pkt_fifo_empty +* RESERVED11[11] - (RO) Reserved bits +* pf_dfet_tx_axi_outstanding_req[15..12] - (RO) current pipelined +* axi_outstanding_req number +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_axi_outstanding_req_ADDR\ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_axi_outstanding_req_MASK\ +0x0000F000 /* pf_dfet_tx_axi_outstanding_req[15..12] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_axi_outstanding_req_SHFT\ +12 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_axi_pkt_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_axi_pkt_fifo_empty_MASK \ + 0x00000400 /* pf_dfet_tx_axi_pkt_fifo_empty[10] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_axi_pkt_fifo_empty_SHFT \ + 10 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_axi_req_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_axi_req_fifo_empty_MASK \ + 0x00000200 /* pf_dfet_tx_axi_req_fifo_empty[9] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_axi_req_fifo_empty_SHFT \ + 9 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_dma_req_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_dma_req_fifo_empty_MASK \ + 0x00000100 /* pf_dfet_tx_dma_req_fifo_empty[8] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_dma_req_fifo_empty_SHFT \ + 8 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_buf_empty_axi_outstandin\ +g_ADDR \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_buf_empty_axi_outstandin\ +g_MASK \ +0x00000010 /* pf_dfet_tx_buf_empty_axi_outstanding[4] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_buf_empty_axi_outstandin\ +g_SHFT \ +4 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_ar_cs_sleep_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_ar_cs_sleep_MASK \ + 0x00000008 /* pf_dfet_tx_ar_cs_sleep[3] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_ar_cs_sleep_SHFT \ + 3 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_axi_dp_cs_idle_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_axi_dp_cs_idle_MASK \ + 0x00000004 /* pf_dfet_tx_axi_dp_cs_idle[2] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_axi_dp_cs_idle_SHFT \ + 2 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_ar_cs_idle_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_ar_cs_idle_MASK \ + 0x00000002 /* pf_dfet_tx_ar_cs_idle[1] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_ar_cs_idle_SHFT 1 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_cmd_state_idle_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_cmd_state_idle_MASK \ + 0x00000001 /* pf_dfet_tx_cmd_state_idle[0] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA1_pf_dfet_tx_cmd_state_idle_SHFT \ + 0 + +/* +* ---WPDMA_AXI_MST_SLEEP_STA2 (0x7C025000 + 0x988)--- +* rx_pfet_cmd_state_idle[0] - (RO) cmd_state_idle +* rx_pfet_aw_cs_idle[1] - (RO) aw_cs_idle +* rx_pfet_axi_dp_cs_idle[2] - (RO) axi_dp_cs_idle +* rx_pfet_aw_cs_sleep[3] - (RO) aw_cs_sleep +* rx_pfet_buf_empty_axi_outstanding[4] - (RO) buf_empty(axi_outstanding) +* rx_pfet_data_fifo_empty[5] - (RO) data_fifo_empty +* rx_pfet_rx_axi_bid_fifo_empty[6] - (RO) axi_bid_fifo_empty +* RESERVED7[7] - (RO) Reserved bits +* rx_pfet_dma_req_fifo_empty[8] - (RO) dma_req_fifo_empty +* rx_pfet_axi_req_fifo_empty[9] - (RO) axi_req_fifo_empty +* rx_pfet_axi_pkt_fifo_empty[10] - (RO) axi_pkt_fifo_empty +* RESERVED11[11] - (RO) Reserved bits +* rx_pfet_axi_outstanding_req[15..12] - (RO) current pipelined +* axi_outstanding_req number +* wb_dfet_rx_cmd_state_idle[16] - (RO) cmd_state_idle +* wb_dfet_rx_aw_cs_idle[17] - (RO) aw_cs_idle +* wb_dfet_rx_axi_dp_cs_idle[18] - (RO) axi_dp_cs_idle +* wb_dfet_rx_aw_cs_sleep[19] - (RO) aw_cs_sleep +* wb_dfet_rx_buf_empty_axi_outstanding[20] - (RO) buf_empty(axi_outstanding) +* wb_dfet_rx_axi_data_fifo_empty[21] - (RO) axi_data_fifo_empty +* wb_dfet_rx_axi_bid_fifo_empty[22] - (RO) axi_bid_fifo_empty +* RESERVED23[23] - (RO) Reserved bits +* wb_dfet_rx_dma_req_fifo_empty[24] - (RO) dma_req_fifo_empty +* wb_dfet_rx_axi_req_fifo_empty[25] - (RO) axi_req_fifo_empty +* wb_dfet_rx_axi_pkt_fifo_empty[26] - (RO) axi_pkt_fifo_empty +* RESERVED27[27] - (RO) Reserved bits +* wb_dfet_rx_axi_outstanding_req[31..28] - (RO) current pipelined +* axi_outstanding_req number +*/ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_outstanding_req_ADDR\ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_outstanding_req_MASK\ +0xF0000000 /* wb_dfet_rx_axi_outstanding_req[31..28] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_outstanding_req_SHFT\ +28 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_pkt_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_pkt_fifo_empty_MASK \ + 0x04000000 /* wb_dfet_rx_axi_pkt_fifo_empty[26] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_pkt_fifo_empty_SHFT \ + 26 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_req_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_req_fifo_empty_MASK \ + 0x02000000 /* wb_dfet_rx_axi_req_fifo_empty[25] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_req_fifo_empty_SHFT \ + 25 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_dma_req_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_dma_req_fifo_empty_MASK \ + 0x01000000 /* wb_dfet_rx_dma_req_fifo_empty[24] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_dma_req_fifo_empty_SHFT \ + 24 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_bid_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_bid_fifo_empty_MASK \ + 0x00400000 /* wb_dfet_rx_axi_bid_fifo_empty[22] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_bid_fifo_empty_SHFT \ + 22 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_data_fifo_empty_ADDR\ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_data_fifo_empty_MASK\ +0x00200000 /* wb_dfet_rx_axi_data_fifo_empty[21] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_data_fifo_empty_SHFT\ +21 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_buf_empty_axi_outstandin\ +g_ADDR \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_buf_empty_axi_outstandin\ +g_MASK \ +0x00100000 /* wb_dfet_rx_buf_empty_axi_outstanding[20] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_buf_empty_axi_outstandin\ +g_SHFT \ +20 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_aw_cs_sleep_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_aw_cs_sleep_MASK \ + 0x00080000 /* wb_dfet_rx_aw_cs_sleep[19] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_aw_cs_sleep_SHFT \ + 19 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_dp_cs_idle_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_dp_cs_idle_MASK \ + 0x00040000 /* wb_dfet_rx_axi_dp_cs_idle[18] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_axi_dp_cs_idle_SHFT \ + 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_aw_cs_idle_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_aw_cs_idle_MASK \ + 0x00020000 /* wb_dfet_rx_aw_cs_idle[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_aw_cs_idle_SHFT \ + 17 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_cmd_state_idle_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_cmd_state_idle_MASK \ + 0x00010000 /* wb_dfet_rx_cmd_state_idle[16] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_wb_dfet_rx_cmd_state_idle_SHFT \ + 16 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_axi_outstanding_req_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_axi_outstanding_req_MASK \ + 0x0000F000 /* rx_pfet_axi_outstanding_req[15..12] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_axi_outstanding_req_SHFT \ + 12 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_axi_pkt_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_axi_pkt_fifo_empty_MASK \ + 0x00000400 /* rx_pfet_axi_pkt_fifo_empty[10] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_axi_pkt_fifo_empty_SHFT \ + 10 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_axi_req_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_axi_req_fifo_empty_MASK \ + 0x00000200 /* rx_pfet_axi_req_fifo_empty[9] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_axi_req_fifo_empty_SHFT \ + 9 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_dma_req_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_dma_req_fifo_empty_MASK \ + 0x00000100 /* rx_pfet_dma_req_fifo_empty[8] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_dma_req_fifo_empty_SHFT \ + 8 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_rx_axi_bid_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_rx_axi_bid_fifo_empty_MASK \ + 0x00000040 /* rx_pfet_rx_axi_bid_fifo_empty[6] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_rx_axi_bid_fifo_empty_SHFT \ + 6 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_data_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_data_fifo_empty_MASK \ + 0x00000020 /* rx_pfet_data_fifo_empty[5] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_data_fifo_empty_SHFT \ + 5 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_buf_empty_axi_outstanding_A\ +DDR \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_buf_empty_axi_outstanding_M\ +ASK \ +0x00000010 /* rx_pfet_buf_empty_axi_outstanding[4] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_buf_empty_axi_outstanding_S\ +HFT \ +4 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_aw_cs_sleep_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_aw_cs_sleep_MASK \ + 0x00000008 /* rx_pfet_aw_cs_sleep[3] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_aw_cs_sleep_SHFT 3 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_axi_dp_cs_idle_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_axi_dp_cs_idle_MASK \ + 0x00000004 /* rx_pfet_axi_dp_cs_idle[2] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_axi_dp_cs_idle_SHFT \ + 2 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_aw_cs_idle_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_aw_cs_idle_MASK \ + 0x00000002 /* rx_pfet_aw_cs_idle[1] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_aw_cs_idle_SHFT 1 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_cmd_state_idle_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_cmd_state_idle_MASK \ + 0x00000001 /* rx_pfet_cmd_state_idle[0] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA2_rx_pfet_cmd_state_idle_SHFT \ + 0 + +/* +* ---WPDMA_AXI_MST_SLEEP_STA3 (0x7C025000 + 0x98C)--- +* wb_dfet_tx_cmd_state_idle[0] - (RO) cmd_state_idle +* wb_dfet_tx_aw_cs_idle[1] - (RO) aw_cs_idle +* wb_dfet_tx_axi_dp_cs_idle[2] - (RO) axi_dp_cs_idle +* wb_dfet_tx_aw_cs_sleep[3] - (RO) aw_cs_sleep +* wb_dfet_tx_buf_empty_axi_outstanding[4] - (RO) buf_empty(axi_outstanding) +* wb_dfet_tx_axi_data_fifo_empty[5] - (RO) axi_data_fifo_empty +* wb_dfet_rx_axi_bid_fifo_empty[6] - (RO) axi_bid_fifo_empty +* RESERVED7[7] - (RO) Reserved bits +* wb_dfet_tx_dma_req_fifo_empty[8] - (RO) dma_req_fifo_empty +* wb_dfet_tx_axi_req_fifo_empty[9] - (RO) axi_req_fifo_empty +* wb_dfet_tx_axi_pkt_fifo_empty[10] - (RO) axi_pkt_fifo_empty +* RESERVED11[11] - (RO) Reserved bits +* wb_dfet_tx_axi_outstanding_req[15..12] - (RO) current pipelined +* axi_outstanding_req number +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_outstanding_req_ADDR\ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_outstanding_req_MASK\ +0x0000F000 /* wb_dfet_tx_axi_outstanding_req[15..12] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_outstanding_req_SHFT\ +12 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_pkt_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_pkt_fifo_empty_MASK \ + 0x00000400 /* wb_dfet_tx_axi_pkt_fifo_empty[10] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_pkt_fifo_empty_SHFT \ + 10 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_req_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_req_fifo_empty_MASK \ + 0x00000200 /* wb_dfet_tx_axi_req_fifo_empty[9] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_req_fifo_empty_SHFT \ + 9 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_dma_req_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_dma_req_fifo_empty_MASK \ + 0x00000100 /* wb_dfet_tx_dma_req_fifo_empty[8] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_dma_req_fifo_empty_SHFT \ + 8 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_rx_axi_bid_fifo_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_rx_axi_bid_fifo_empty_MASK \ + 0x00000040 /* wb_dfet_rx_axi_bid_fifo_empty[6] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_rx_axi_bid_fifo_empty_SHFT \ + 6 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_data_fifo_empty_ADDR\ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_data_fifo_empty_MASK\ +0x00000020 /* wb_dfet_tx_axi_data_fifo_empty[5] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_data_fifo_empty_SHFT\ +5 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_buf_empty_axi_outstandin\ +g_ADDR \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_buf_empty_axi_outstandin\ +g_MASK \ +0x00000010 /* wb_dfet_tx_buf_empty_axi_outstanding[4] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_buf_empty_axi_outstandin\ +g_SHFT \ +4 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_aw_cs_sleep_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_aw_cs_sleep_MASK \ + 0x00000008 /* wb_dfet_tx_aw_cs_sleep[3] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_aw_cs_sleep_SHFT \ + 3 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_dp_cs_idle_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_dp_cs_idle_MASK \ + 0x00000004 /* wb_dfet_tx_axi_dp_cs_idle[2] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_axi_dp_cs_idle_SHFT \ + 2 +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_aw_cs_idle_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_aw_cs_idle_MASK \ + 0x00000002 /* wb_dfet_tx_aw_cs_idle[1] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_aw_cs_idle_SHFT 1 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_cmd_state_idle_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_cmd_state_idle_MASK \ + 0x00000001 /* wb_dfet_tx_cmd_state_idle[0] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA3_wb_dfet_tx_cmd_state_idle_SHFT \ + 0 + +/* +* ---WPDMA_AXI_MST_SLEEP_STA4 (0x7C025000 + 0x990)--- +* RESERVED0[0] - (RO) Reserved bits +* rx_pfet_pld_rx_pfet_sleep_rdy[1] - (RO) pld_rx_pfet_sleep_rdy +* RESERVED2[30..2] - (RO) Reserved bits +* tx_pfet_pld_tx_pfet_sleep_rdy[31] - (RO) pld_tx_pfet_sleep_rdy +*/ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA4_tx_pfet_pld_tx_pfet_sleep_rdy_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA4_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA4_tx_pfet_pld_tx_pfet_sleep_rdy_MASK \ + 0x80000000 /* tx_pfet_pld_tx_pfet_sleep_rdy[31] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA4_tx_pfet_pld_tx_pfet_sleep_rdy_SHFT \ + 31 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA4_rx_pfet_pld_rx_pfet_sleep_rdy_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA4_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA4_rx_pfet_pld_rx_pfet_sleep_rdy_MASK \ + 0x00000002 /* rx_pfet_pld_rx_pfet_sleep_rdy[1] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_AXI_MST_SLEEP_STA4_rx_pfet_pld_rx_pfet_sleep_rdy_SHFT \ + 1 + +/* +* ---WPDMA_TX_RING0_BKRS_CTRL0 (0x7C025000 + 0xA00)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING0_BKRS_CTRL1 (0x7C025000 + 0xA04)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING0_BKRS_CTRL2 (0x7C025000 + 0xA08)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING1_BKRS_CTRL0 (0x7C025000 + 0xA10)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING1_BKRS_CTRL1 (0x7C025000 + 0xA14)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING1_BKRS_CTRL2 (0x7C025000 + 0xA18)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING2_BKRS_CTRL0 (0x7C025000 + 0xA20)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING2_BKRS_CTRL1 (0x7C025000 + 0xA24)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING2_BKRS_CTRL2 (0x7C025000 + 0xA28)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING3_BKRS_CTRL0 (0x7C025000 + 0xA30)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING3_BKRS_CTRL1 (0x7C025000 + 0xA34)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING3_BKRS_CTRL2 (0x7C025000 + 0xA38)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING4_BKRS_CTRL0 (0x7C025000 + 0xA40)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING4_BKRS_CTRL1 (0x7C025000 + 0xA44)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING4_BKRS_CTRL2 (0x7C025000 + 0xA48)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING5_BKRS_CTRL0 (0x7C025000 + 0xA50)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING5_BKRS_CTRL1 (0x7C025000 + 0xA54)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING5_BKRS_CTRL2 (0x7C025000 + 0xA58)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING6_BKRS_CTRL0 (0x7C025000 + 0xA60)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING6_BKRS_CTRL1 (0x7C025000 + 0xA64)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING6_BKRS_CTRL2 (0x7C025000 + 0xA68)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING7_BKRS_CTRL0 (0x7C025000 + 0xA70)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING7_BKRS_CTRL1 (0x7C025000 + 0xA74)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING7_BKRS_CTRL2 (0x7C025000 + 0xA78)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING8_BKRS_CTRL0 (0x7C025000 + 0xA80)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING8_BKRS_CTRL1 (0x7C025000 + 0xA84)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING8_BKRS_CTRL2 (0x7C025000 + 0xA88)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING9_BKRS_CTRL0 (0x7C025000 + 0xA90)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING9_BKRS_CTRL1 (0x7C025000 + 0xA94)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING9_BKRS_CTRL2 (0x7C025000 + 0xA98)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING10_BKRS_CTRL0 (0x7C025000 + 0xAA0)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING10_BKRS_CTRL1 (0x7C025000 + 0xAA4)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING10_BKRS_CTRL2 (0x7C025000 + 0xAA8)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING11_BKRS_CTRL0 (0x7C025000 + 0xAB0)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING11_BKRS_CTRL1 (0x7C025000 + 0xAB4)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING11_BKRS_CTRL2 (0x7C025000 + 0xAB8)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING12_BKRS_CTRL0 (0x7C025000 + 0xAC0)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING12_BKRS_CTRL1 (0x7C025000 + 0xAC4)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING12_BKRS_CTRL2 (0x7C025000 + 0xAC8)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING13_BKRS_CTRL0 (0x7C025000 + 0xAD0)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING13_BKRS_CTRL1 (0x7C025000 + 0xAD4)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING13_BKRS_CTRL2 (0x7C025000 + 0xAD8)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING14_BKRS_CTRL0 (0x7C025000 + 0xAE0)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING14_BKRS_CTRL1 (0x7C025000 + 0xAE4)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING14_BKRS_CTRL2 (0x7C025000 + 0xAE8)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING15_BKRS_CTRL0 (0x7C025000 + 0xAF0)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING15_BKRS_CTRL1 (0x7C025000 + 0xAF4)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING15_BKRS_CTRL2 (0x7C025000 + 0xAF8)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING176_BKRS_CTRL0 (0x7C025000 + 0xB00)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING176_BKRS_CTRL1 (0x7C025000 + 0xB04)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING176_BKRS_CTRL2 (0x7C025000 + 0xB08)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING176_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING17_BKRS_CTRL0 (0x7C025000 + 0xB10)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING17_BKRS_CTRL1 (0x7C025000 + 0xB14)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING17_BKRS_CTRL2 (0x7C025000 + 0xB18)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING18_BKRS_CTRL0 (0x7C025000 + 0xB20)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING18_BKRS_CTRL1 (0x7C025000 + 0xB24)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING18_BKRS_CTRL2 (0x7C025000 + 0xB28)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING19_BKRS_CTRL0 (0x7C025000 + 0xB30)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING19_BKRS_CTRL1 (0x7C025000 + 0xB34)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING19_BKRS_CTRL2 (0x7C025000 + 0xB38)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING20_BKRS_CTRL0 (0x7C025000 + 0xB40)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING20_BKRS_CTRL1 (0x7C025000 + 0xB44)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING20_BKRS_CTRL2 (0x7C025000 + 0xB48)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING20_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING21_BKRS_CTRL0 (0x7C025000 + 0xB50)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING21_BKRS_CTRL1 (0x7C025000 + 0xB54)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING21_BKRS_CTRL2 (0x7C025000 + 0xB58)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING21_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING22_BKRS_CTRL0 (0x7C025000 + 0xB60)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING22_BKRS_CTRL1 (0x7C025000 + 0xB64)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING22_BKRS_CTRL2 (0x7C025000 + 0xB68)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING22_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING23_BKRS_CTRL0 (0x7C025000 + 0xB70)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING23_BKRS_CTRL1 (0x7C025000 + 0xB74)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING23_BKRS_CTRL2 (0x7C025000 + 0xB78)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING23_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING0_BKRS_CTRL0 (0x7C025000 + 0xC00)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING0_BKRS_CTRL1 (0x7C025000 + 0xC04)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING0_BKRS_CTRL2 (0x7C025000 + 0xC08)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING1_BKRS_CTRL0 (0x7C025000 + 0xC10)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING1_BKRS_CTRL1 (0x7C025000 + 0xC14)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING1_BKRS_CTRL2 (0x7C025000 + 0xC18)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING2_BKRS_CTRL0 (0x7C025000 + 0xC20)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING2_BKRS_CTRL1 (0x7C025000 + 0xC24)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING2_BKRS_CTRL2 (0x7C025000 + 0xC28)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING3_BKRS_CTRL0 (0x7C025000 + 0xC30)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING3_BKRS_CTRL1 (0x7C025000 + 0xC34)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING3_BKRS_CTRL2 (0x7C025000 + 0xC38)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +#ifdef __cplusplus +} +#endif + +#endif /* __WF_WFDMA_HOST_DMA1_REGS_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7961/wf_cr_sw_def.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7961/wf_cr_sw_def.h new file mode 100644 index 0000000000000..8523ee383292e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7961/wf_cr_sw_def.h @@ -0,0 +1,93 @@ +/* [File] : wf_cr_sw_def.h */ +/* [Copyright] : Copyright (C) 2018 Mediatek Incorportion. All rights reserved. +*/ + +/******************************************************************************* +* 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 _WF_CR_SW_DEF_H +#define _WF_CR_SW_DEF_H + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + + +/****************************************************************************** +* +* MCU_SYSRAM SW CR Definitions +* +****************************************************************************** +*/ +#define WF_SW_DEF_CR_BASE 0x00400E00 + +#define WF_SW_DEF_CR_SER_STATUS_ADDR \ + (WF_SW_DEF_CR_BASE + 0x000) /* E00 */ +#define WF_SW_DEF_CR_PLE_STATUS_ADDR \ + (WF_SW_DEF_CR_BASE + 0x004) /* E04 */ +#define WF_SW_DEF_CR_PLE1_STATUS_ADDR \ + (WF_SW_DEF_CR_BASE + 0x008) /* E08 */ +#define WF_SW_DEF_CR_PLE_AMSDU_STATUS_ADDR \ + (WF_SW_DEF_CR_BASE + 0x00C) /* E0C */ +#define WF_SW_DEF_CR_PSE_STATUS_ADDR \ + (WF_SW_DEF_CR_BASE + 0x010) /* E10 */ +#define WF_SW_DEF_CR_PSE1_STATUS_ADDR \ + (WF_SW_DEF_CR_BASE + 0x014) /* E14 */ +#define WF_SW_DEF_CR_LAMC_WISR6_BN0_STATUS_ADDR \ + (WF_SW_DEF_CR_BASE + 0x018) /* E18 */ +#define WF_SW_DEF_CR_LAMC_WISR6_BN1_STATUS_ADDR \ + (WF_SW_DEF_CR_BASE + 0x01C) /* E1C */ +#define WF_SW_DEF_CR_LAMC_WISR7_BN0_STATUS_ADDR \ + (WF_SW_DEF_CR_BASE + 0x020) /* E20 */ +#define WF_SW_DEF_CR_LAMC_WISR7_BN1_STATUS_ADDR \ + (WF_SW_DEF_CR_BASE + 0x024) /* E24 */ +#define WF_SW_DEF_CR_USB_MCU_EVENT_ADD \ + (WF_SW_DEF_CR_BASE + 0x028) /* E28 */ +#define WF_SW_DEF_CR_USB_HOST_ACK_ADDR \ + (WF_SW_DEF_CR_BASE + 0x02C) /* E2C */ +#define WF_SW_DEF_CR_ICAP_SPECTRUM_MODE_ADDR \ + (WF_SW_DEF_CR_BASE + 0x030) /* E30 */ + +#endif /* _WF_CR_SW_DEF_H */ + + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7961/wf_hif_dmashdl_top.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7961/wf_hif_dmashdl_top.h new file mode 100644 index 0000000000000..5dfea109fb3c4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7961/wf_hif_dmashdl_top.h @@ -0,0 +1,2356 @@ +/* [File] : wf_hif_dmashdl_top.h */ +/* [Revision time] : Mon Apr 29 11:37:41 2019 */ +/* [Description] : This file is auto generated by CODA */ +/* [Copyright] : Copyright (C) 2019 Mediatek Incorportion. All rights */ +/* reserved. */ + +#ifndef __WF_HIF_DMASHDL_TOP_REGS_H__ +#define __WF_HIF_DMASHDL_TOP_REGS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ************************************************************************** */ +/* */ +/* WF_HIF_DMASHDL_TOP CR Definitions */ +/* */ +/* ************************************************************************** */ + +#define WF_HIF_DMASHDL_TOP_BASE 0x7C026000 + +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x00) /* 6000 */ +#define WF_HIF_DMASHDL_TOP_SW_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x04) /* 6004 */ +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x08) /* 6008 */ +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x0C) /* 600C */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x10) /* 6010 */ +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x14) /* 6014 */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x18) /* 6018 */ +#define WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x1c) /* 601C */ +#define WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x20) /* 6020 */ +#define WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x24) /* 6024 */ +#define WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x28) /* 6028 */ +#define WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x2C) /* 602C */ +#define WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x30) /* 6030 */ +#define WF_HIF_DMASHDL_TOP_GROUP5_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x34) /* 6034 */ +#define WF_HIF_DMASHDL_TOP_GROUP6_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x38) /* 6038 */ +#define WF_HIF_DMASHDL_TOP_GROUP7_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x3C) /* 603C */ +#define WF_HIF_DMASHDL_TOP_GROUP8_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x40) /* 6040 */ +#define WF_HIF_DMASHDL_TOP_GROUP9_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x44) /* 6044 */ +#define WF_HIF_DMASHDL_TOP_GROUP10_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x48) /* 6048 */ +#define WF_HIF_DMASHDL_TOP_GROUP11_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x4C) /* 604C */ +#define WF_HIF_DMASHDL_TOP_GROUP12_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x50) /* 6050 */ +#define WF_HIF_DMASHDL_TOP_GROUP13_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x54) /* 6054 */ +#define WF_HIF_DMASHDL_TOP_GROUP14_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x58) /* 6058 */ +#define WF_HIF_DMASHDL_TOP_GROUP15_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x5C) /* 605C */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x60) /* 6060 */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x64) /* 6064 */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x68) /* 6068 */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x6c) /* 606C */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x70) /* 6070 */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x74) /* 6074 */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x78) /* 6078 */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x7C) /* 607C */ +#define WF_HIF_DMASHDL_TOP_SLOT_PERIOD_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x80) /* 6080 */ +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT00_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0xC0) /* 60C0 */ +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT01_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0xC4) /* 60C4 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0xC8) /* 60C8 */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0xCC) /* 60CC */ +#define WF_HIF_DMASHDL_TOP_TX_PACKET_SIZE_PAGE_MAP_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0xD0) /* 60D0 */ +#define WF_HIF_DMASHDL_TOP_HIF_ASK_LONG_CHECK_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0xD4) /* 60D4 */ +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0xD8) /* 60D8 */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0xDC) /* 60DC */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x100) /* 6100 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD0_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x110) /* 6110 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x140) /* 6140 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP1_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x144) /* 6144 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP2_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x148) /* 6148 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP3_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x14c) /* 614C */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP4_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x150) /* 6150 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP5_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x154) /* 6154 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP6_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x158) /* 6158 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP7_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x15C) /* 615C */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP8_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x160) /* 6160 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP9_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x164) /* 6164 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP10_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x168) /* 6168 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP11_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x16c) /* 616C */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP12_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x170) /* 6170 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP13_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x174) /* 6174 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP14_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x178) /* 6178 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP15_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x17C) /* 617C */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x180) /* 6180 */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x184) /* 6184 */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x188) /* 6188 */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x18c) /* 618C */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x190) /* 6190 */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x194) /* 6194 */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x198) /* 6198 */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x19c) /* 619C */ + +/* +* ---WACPU_REFILL (0x7C026000 + 0x00)--- +* WACPU_RETURN_PAGE_CNT[11..0] - (RW) WACPU refill page count +* RESERVED12[15..12] - (RO) Reserved bits +* WACPU_RETRUN_QID[20..16] - (RW) WACPU refill queue ID +* RESERVED21[23..21] - (RO) Reserved bits +* WACPU_RETRUN_MODE[25..24] - (RW) WACPU refill mode selection +* 2'b00 : Return mode +* 2'b01 : Add reservation mode(initial quota +setting) +* 2'b10 : Substrate source mode +* 2'b11 : Add source mode +* RESERVED26[30..26] - (RO) Reserved bits +* WACPU_EXCUTE[31] - (WO) Excute this CR action +*/ +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_EXCUTE_ADDR \ + WF_HIF_DMASHDL_TOP_WACPU_REFILL_ADDR +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_EXCUTE_MASK \ + 0x80000000 /* WACPU_EXCUTE[31] */ +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_EXCUTE_SHFT 31 +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETRUN_MODE_ADDR \ + WF_HIF_DMASHDL_TOP_WACPU_REFILL_ADDR +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETRUN_MODE_MASK \ + 0x03000000 /* WACPU_RETRUN_MODE[25..24] */ +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETRUN_MODE_SHFT 24 +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETRUN_QID_ADDR \ + WF_HIF_DMASHDL_TOP_WACPU_REFILL_ADDR +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETRUN_QID_MASK \ + 0x001F0000 /* WACPU_RETRUN_QID[20..16] */ +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETRUN_QID_SHFT 16 +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETURN_PAGE_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_WACPU_REFILL_ADDR +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETURN_PAGE_CNT_MASK \ + 0x00000FFF /* WACPU_RETURN_PAGE_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETURN_PAGE_CNT_SHFT 0 + +/* +* ---SW_CONTROL (0x7C026000 + 0x04)--- +* SW_LOG_RESET[0] - (RW) SW reset logic function action +* RESERVED1[27..1] - (RO) Reserved bits +* DMASHDL_BYPASS[28] - (RW) DMASHDL host ask and quota control +* function bypass +* RESERVED29[31..29] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_SW_CONTROL_DMASHDL_BYPASS_ADDR \ + WF_HIF_DMASHDL_TOP_SW_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_SW_CONTROL_DMASHDL_BYPASS_MASK \ + 0x10000000 /* DMASHDL_BYPASS[28] */ +#define WF_HIF_DMASHDL_TOP_SW_CONTROL_DMASHDL_BYPASS_SHFT 28 +#define WF_HIF_DMASHDL_TOP_SW_CONTROL_SW_LOG_RESET_ADDR \ + WF_HIF_DMASHDL_TOP_SW_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_SW_CONTROL_SW_LOG_RESET_MASK \ + 0x00000001 /* SW_LOG_RESET[0] */ +#define WF_HIF_DMASHDL_TOP_SW_CONTROL_SW_LOG_RESET_SHFT 0 + +/* +* ---OPTIONAL_CONTROL (0x7C026000 + 0x08)--- +* CR_HIF_GUP_ACT_MAP[15..0] - (RW) Group active mapping to joint the hif +* ask round robin setting in hif_ack_cnt_th period. +* Bit 0: group 0 joint active setting (1: +* joint, 0: disjoint) +* Bit 1: group 1 joint active setting (1: +* joint, 0: disjoint) +* Bit 2: group 2 joint active setting (1: +* joint, 0: disjoint) +* Bit 3: group 3 joint active setting (1: +* joint, 0: disjoint) +* Bit 4: group 4 joint active setting (1: +* joint, 0: disjoint) +* Bit 5: group 5 joint active setting (1: +* joint, 0: disjoint) +* Bit 6: group 6 joint active setting (1: +* joint, 0: disjoint) +* Bit 7: group 7 joint active setting (1: +* joint, 0: disjoint) +* Bit 8: group 8 joint active setting (1: +* joint, 0: disjoint) +* Bit 9: group 9 joint active setting (1: +* joint, 0: disjoint) +...... +* Bit 15: group 15 joint active setting (1: +* joint, 0: disjoint) +* CR_HIF_ACK_CNT_TH[23..16] - (RW) Host ask success count threshold setting +* to reset initial for round robin period +* RESERVED24[27..24] - (RO) Reserved bits +* CR_HIF_ASK_RR_ENA[28] - (RW) HIF ask round robin like arbiter enable +* CR_HIF_ASK_MIN_RR_ENA[29] - (RW) Source count below minimum quota check +* enable by round robin like arbitration +* CR_PSEBF_BL_TH2_NOBMIN_RASIGN_ENA[30] - (RW) Assignment when all TXD groups +* great or equal minimum quota +* CR_PSEBF_BL_TH2_CHK_DISABLE[31] - (RW) Disable PSE buffer Threshold 2 check +* and assignment +*/ +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_PSEBF_BL_TH2_CHK_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_PSEBF_BL_TH2_CHK_DISABLE_MASK \ + 0x80000000 /* CR_PSEBF_BL_TH2_CHK_DISABLE[31] */ +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_PSEBF_BL_TH2_CHK_DISABLE_SHFT 31 +#define \ +WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_PSEBF_BL_TH2_NOBMIN_RASIGN_ENA_ADDR \ + \ + WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_ADDR +#define \ +WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_PSEBF_BL_TH2_NOBMIN_RASIGN_ENA_MASK \ + \ + 0x40000000 /* CR_PSEBF_BL_TH2_NOBMIN_RASIGN_ENA[30] */ +#define \ +WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_PSEBF_BL_TH2_NOBMIN_RASIGN_ENA_SHFT \ + \ + 30 +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_ASK_MIN_RR_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_ASK_MIN_RR_ENA_MASK \ + 0x20000000 /* CR_HIF_ASK_MIN_RR_ENA[29] */ +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_ASK_MIN_RR_ENA_SHFT 29 +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_ASK_RR_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_ASK_RR_ENA_MASK \ + 0x10000000 /* CR_HIF_ASK_RR_ENA[28] */ +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_ASK_RR_ENA_SHFT 28 +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_ACK_CNT_TH_ADDR \ + WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_ACK_CNT_TH_MASK \ + 0x00FF0000 /* CR_HIF_ACK_CNT_TH[23..16] */ +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_ACK_CNT_TH_SHFT 16 +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_GUP_ACT_MAP_ADDR \ + WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_GUP_ACT_MAP_MASK \ + 0x0000FFFF /* CR_HIF_GUP_ACT_MAP[15..0] */ +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_GUP_ACT_MAP_SHFT 0 + +/* +* ---PAGE_SETTING (0x7C026000 + 0x0C)--- +* PSE_ADD_BSIZE[9..0] - (RW) PSE(command) packet size add extra byte +count +* RESERVED10[11..10] - (RO) Reserved bits +* PP_OFFSET_ADD_ENA[12] - (RW) PSE(command) packet size add offset +* enable from packet processor +* RESERVED13[15..13] - (RO) Reserved bits +* GROUP_SEQUENCE_ORDER_TYPE[16] - (RW) User program group sequence type +control +* SLOT_TYPE_ARBITER_CONTROL[17] - (RW) Slot type arbiter control +* DUMMY_00[18] - (RW) Dummy_00 bit +* DUMMY_01[19] - (RW) Dummy_01 bit +* SRC_CNT_PRI_EN[20] - (RW) Source count below min quota first +* priority check enable +* QUP_ACL_SLOT_CG_EN[21] - (RW) Group ack then slot ID change function +enable +* RESERVED22[31..22] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_QUP_ACL_SLOT_CG_EN_ADDR \ + WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_QUP_ACL_SLOT_CG_EN_MASK \ + 0x00200000 /* QUP_ACL_SLOT_CG_EN[21] */ +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_QUP_ACL_SLOT_CG_EN_SHFT 21 +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_SRC_CNT_PRI_EN_ADDR \ + WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_SRC_CNT_PRI_EN_MASK \ + 0x00100000 /* SRC_CNT_PRI_EN[20] */ +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_SRC_CNT_PRI_EN_SHFT 20 +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_DUMMY_01_ADDR \ + WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_DUMMY_01_MASK \ + 0x00080000 /* DUMMY_01[19] */ +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_DUMMY_01_SHFT 19 +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_DUMMY_00_ADDR \ + WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_DUMMY_00_MASK \ + 0x00040000 /* DUMMY_00[18] */ +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_DUMMY_00_SHFT 18 +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_SLOT_TYPE_ARBITER_CONTROL_ADDR \ + WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_SLOT_TYPE_ARBITER_CONTROL_MASK \ + 0x00020000 /* SLOT_TYPE_ARBITER_CONTROL[17] */ +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_SLOT_TYPE_ARBITER_CONTROL_SHFT 17 +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_GROUP_SEQUENCE_ORDER_TYPE_ADDR \ + WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_GROUP_SEQUENCE_ORDER_TYPE_MASK \ + 0x00010000 /* GROUP_SEQUENCE_ORDER_TYPE[16] */ +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_GROUP_SEQUENCE_ORDER_TYPE_SHFT 16 +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_PP_OFFSET_ADD_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_PP_OFFSET_ADD_ENA_MASK \ + 0x00001000 /* PP_OFFSET_ADD_ENA[12] */ +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_PP_OFFSET_ADD_ENA_SHFT 12 +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_PSE_ADD_BSIZE_ADDR \ + WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_PSE_ADD_BSIZE_MASK \ + 0x000003FF /* PSE_ADD_BSIZE[9..0] */ +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_PSE_ADD_BSIZE_SHFT 0 + +/* +* ---REFILL_CONTROL (0x7C026000 + 0x10)--- +* GROUP0_REFILL_PRIORITY[0] - (RW) Group0 refill priority +* GROUP1_REFILL_PRIORITY[1] - (RW) Group1 refill priority +* GROUP2_REFILL_PRIORITY[2] - (RW) Group2 refill priority +* GROUP3_REFILL_PRIORITY[3] - (RW) Group3 refill priority +* GROUP4_REFILL_PRIORITY[4] - (RW) Group4 refill priority +* GROUP5_REFILL_PRIORITY[5] - (RW) Group5 refill priority +* GROUP6_REFILL_PRIORITY[6] - (RW) Group6 refill priority +* GROUP7_REFILL_PRIORITY[7] - (RW) Group7 refill priority +* GROUP8_REFILL_PRIORITY[8] - (RW) Group8 refill priority +* GROUP9_REFILL_PRIORITY[9] - (RW) Group9 refill priority +* GROUP10_REFILL_PRIORITY[10] - (RW) Group10 refill priority +* GROUP11_REFILL_PRIORITY[11] - (RW) Group11 refill priority +* GROUP12_REFILL_PRIORITY[12] - (RW) Group12 refill priority +* GROUP13_REFILL_PRIORITY[13] - (RW) Group13 refill priority +* GROUP14_REFILL_PRIORITY[14] - (RW) Group14 refill priority +* GROUP15_REFILL_PRIORITY[15] - (RW) Group15 refill priority +* GROUP0_REFILL_DISABLE[16] - (RW) Group0 refill control +* GROUP1_REFILL_DISABLE[17] - (RW) Group1 refill control +* GROUP2_REFILL_DISABLE[18] - (RW) Group2 refill control +* GROUP3_REFILL_DISABLE[19] - (RW) Group3 refill control +* GROUP4_REFILL_DISABLE[20] - (RW) Group4 refill control +* GROUP5_REFILL_DISABLE[21] - (RW) Group5 refill control +* GROUP6_REFILL_DISABLE[22] - (RW) Group6 refill control +* GROUP7_REFILL_DISABLE[23] - (RW) Group7 refill control +* GROUP8_REFILL_DISABLE[24] - (RW) Group8 refill control +* GROUP9_REFILL_DISABLE[25] - (RW) Group9 refill control +* GROUP10_REFILL_DISABLE[26] - (RW) Group10 refill control +* GROUP11_REFILL_DISABLE[27] - (RW) Group11 refill control +* GROUP12_REFILL_DISABLE[28] - (RW) Group12 refill control +* GROUP13_REFILL_DISABLE[29] - (RW) Group13 refill control +* GROUP14_REFILL_DISABLE[30] - (RW) Group14 refill control +* GROUP15_REFILL_DISABLE[31] - (RW) Group15 refill control +*/ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP15_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP15_REFILL_DISABLE_MASK \ + 0x80000000 /* GROUP15_REFILL_DISABLE[31] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP15_REFILL_DISABLE_SHFT 31 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP14_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP14_REFILL_DISABLE_MASK \ + 0x40000000 /* GROUP14_REFILL_DISABLE[30] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP14_REFILL_DISABLE_SHFT 30 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP13_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP13_REFILL_DISABLE_MASK \ + 0x20000000 /* GROUP13_REFILL_DISABLE[29] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP13_REFILL_DISABLE_SHFT 29 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP12_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP12_REFILL_DISABLE_MASK \ + 0x10000000 /* GROUP12_REFILL_DISABLE[28] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP12_REFILL_DISABLE_SHFT 28 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP11_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP11_REFILL_DISABLE_MASK \ + 0x08000000 /* GROUP11_REFILL_DISABLE[27] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP11_REFILL_DISABLE_SHFT 27 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP10_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP10_REFILL_DISABLE_MASK \ + 0x04000000 /* GROUP10_REFILL_DISABLE[26] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP10_REFILL_DISABLE_SHFT 26 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP9_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP9_REFILL_DISABLE_MASK \ + 0x02000000 /* GROUP9_REFILL_DISABLE[25] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP9_REFILL_DISABLE_SHFT 25 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP8_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP8_REFILL_DISABLE_MASK \ + 0x01000000 /* GROUP8_REFILL_DISABLE[24] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP8_REFILL_DISABLE_SHFT 24 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP7_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP7_REFILL_DISABLE_MASK \ + 0x00800000 /* GROUP7_REFILL_DISABLE[23] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP7_REFILL_DISABLE_SHFT 23 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP6_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP6_REFILL_DISABLE_MASK \ + 0x00400000 /* GROUP6_REFILL_DISABLE[22] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP6_REFILL_DISABLE_SHFT 22 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP5_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP5_REFILL_DISABLE_MASK \ + 0x00200000 /* GROUP5_REFILL_DISABLE[21] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP5_REFILL_DISABLE_SHFT 21 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP4_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP4_REFILL_DISABLE_MASK \ + 0x00100000 /* GROUP4_REFILL_DISABLE[20] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP4_REFILL_DISABLE_SHFT 20 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP3_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP3_REFILL_DISABLE_MASK \ + 0x00080000 /* GROUP3_REFILL_DISABLE[19] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP3_REFILL_DISABLE_SHFT 19 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP2_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP2_REFILL_DISABLE_MASK \ + 0x00040000 /* GROUP2_REFILL_DISABLE[18] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP2_REFILL_DISABLE_SHFT 18 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP1_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP1_REFILL_DISABLE_MASK \ + 0x00020000 /* GROUP1_REFILL_DISABLE[17] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP1_REFILL_DISABLE_SHFT 17 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP0_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP0_REFILL_DISABLE_MASK \ + 0x00010000 /* GROUP0_REFILL_DISABLE[16] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP0_REFILL_DISABLE_SHFT 16 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP15_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP15_REFILL_PRIORITY_MASK \ + 0x00008000 /* GROUP15_REFILL_PRIORITY[15] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP15_REFILL_PRIORITY_SHFT 15 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP14_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP14_REFILL_PRIORITY_MASK \ + 0x00004000 /* GROUP14_REFILL_PRIORITY[14] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP14_REFILL_PRIORITY_SHFT 14 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP13_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP13_REFILL_PRIORITY_MASK \ + 0x00002000 /* GROUP13_REFILL_PRIORITY[13] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP13_REFILL_PRIORITY_SHFT 13 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP12_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP12_REFILL_PRIORITY_MASK \ + 0x00001000 /* GROUP12_REFILL_PRIORITY[12] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP12_REFILL_PRIORITY_SHFT 12 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP11_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP11_REFILL_PRIORITY_MASK \ + 0x00000800 /* GROUP11_REFILL_PRIORITY[11] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP11_REFILL_PRIORITY_SHFT 11 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP10_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP10_REFILL_PRIORITY_MASK \ + 0x00000400 /* GROUP10_REFILL_PRIORITY[10] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP10_REFILL_PRIORITY_SHFT 10 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP9_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP9_REFILL_PRIORITY_MASK \ + 0x00000200 /* GROUP9_REFILL_PRIORITY[9] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP9_REFILL_PRIORITY_SHFT 9 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP8_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP8_REFILL_PRIORITY_MASK \ + 0x00000100 /* GROUP8_REFILL_PRIORITY[8] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP8_REFILL_PRIORITY_SHFT 8 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP7_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP7_REFILL_PRIORITY_MASK \ + 0x00000080 /* GROUP7_REFILL_PRIORITY[7] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP7_REFILL_PRIORITY_SHFT 7 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP6_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP6_REFILL_PRIORITY_MASK \ + 0x00000040 /* GROUP6_REFILL_PRIORITY[6] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP6_REFILL_PRIORITY_SHFT 6 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP5_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP5_REFILL_PRIORITY_MASK \ + 0x00000020 /* GROUP5_REFILL_PRIORITY[5] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP5_REFILL_PRIORITY_SHFT 5 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP4_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP4_REFILL_PRIORITY_MASK \ + 0x00000010 /* GROUP4_REFILL_PRIORITY[4] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP4_REFILL_PRIORITY_SHFT 4 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP3_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP3_REFILL_PRIORITY_MASK \ + 0x00000008 /* GROUP3_REFILL_PRIORITY[3] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP3_REFILL_PRIORITY_SHFT 3 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP2_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP2_REFILL_PRIORITY_MASK \ + 0x00000004 /* GROUP2_REFILL_PRIORITY[2] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP2_REFILL_PRIORITY_SHFT 2 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP1_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP1_REFILL_PRIORITY_MASK \ + 0x00000002 /* GROUP1_REFILL_PRIORITY[1] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP1_REFILL_PRIORITY_SHFT 1 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP0_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP0_REFILL_PRIORITY_MASK \ + 0x00000001 /* GROUP0_REFILL_PRIORITY[0] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP0_REFILL_PRIORITY_SHFT 0 + +/* +* ---PKT_IN_CNT_CTRL (0x7C026000 + 0x14)--- +* CNT1_RET_CNT_ENA[0] - (RW) Counter1 PLE/PSE return count enable +* CNT1_PKTIN_RET_CNT_ENA[1] - (RW) Counter1 pktin return count enable +* CNT1_PKTIN_CNT_ENA[2] - (RW) Counter1 pktin(ask) substrate count +enable +* CNT0_RET_CNT_ENA[3] - (RW) Counter0 PLE/PSE return count enable +* CNT0_PKTIN_RET_CNT_ENA[4] - (RW) Counter0 pktin return count enable +* CNT0_PKTIN_CNT_ENA[5] - (RW) Counter0 pktin(ask) substrate count +enable +* RESERVED6[31..6] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT0_PKTIN_CNT_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT0_PKTIN_CNT_ENA_MASK \ + 0x00000020 /* CNT0_PKTIN_CNT_ENA[5] */ +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT0_PKTIN_CNT_ENA_SHFT 5 +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT0_PKTIN_RET_CNT_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT0_PKTIN_RET_CNT_ENA_MASK \ + 0x00000010 /* CNT0_PKTIN_RET_CNT_ENA[4] */ +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT0_PKTIN_RET_CNT_ENA_SHFT 4 +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT0_RET_CNT_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT0_RET_CNT_ENA_MASK \ + 0x00000008 /* CNT0_RET_CNT_ENA[3] */ +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT0_RET_CNT_ENA_SHFT 3 +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT1_PKTIN_CNT_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT1_PKTIN_CNT_ENA_MASK \ + 0x00000004 /* CNT1_PKTIN_CNT_ENA[2] */ +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT1_PKTIN_CNT_ENA_SHFT 2 +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT1_PKTIN_RET_CNT_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT1_PKTIN_RET_CNT_ENA_MASK \ + 0x00000002 /* CNT1_PKTIN_RET_CNT_ENA[1] */ +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT1_PKTIN_RET_CNT_ENA_SHFT 1 +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT1_RET_CNT_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT1_RET_CNT_ENA_MASK \ + 0x00000001 /* CNT1_RET_CNT_ENA[0] */ +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT1_RET_CNT_ENA_SHFT 0 + +/* +* ---CONTROL_SIGNAL (0x7C026000 + 0x18)--- +* CR_WACPU_MODE_EN[0] - (RW) Enable to WACPU mode for store forward +* packet to DLM +* RESERVED1[3..1] - (RO) Reserved bits +* WACPU_CMD_RET_PAGE_CNT[7..4] - (RW) WACPU mode, each packet in the CMD +* return the page count +* WACPU_TXD_RET_PAGE_CNT[11..8] - (RW) WACPU mode, each packet in the TXD +* return the page count +* WACPU_CMD_ASK_MAX_PAGE_CNT[15..12] - (RW) WACPU mode, CMD ask to require the +* maximum page count +* CR_HIF_ASK_SUB_ENA[16] - (RW) Enable packet in substration action from +* HIF ask period +* CR_PLE_SUB_ENA[17] - (RW) Enable packet in substration action from +PLE +* RESERVED18[19..18] - (RO) Reserved bits +* WACPU_TXD_ASK_MAX_PAGE_CNT[23..20] - (RW) WACPU mode, TXD ask to require the +* maximum page count +* WACPU_SUB_SRC_REFILL_ENA[24] - (RW) Enable terminate refill period when +* WACPU substrate source count to do refill action. +* WACPU_ADD_SRC_REFILL_ENA[25] - (RW) Enable terminate refill period when +* WACPU add source count to do refill action. +* WACPU_ADD_RES_REFILL_ENA[26] - (RW) Enable terminate refill period when +* WACPU add reserve count to do refill action. +* WACPU_RET_REFILL_ENA[27] - (RW) Enable terminate refill period when +* WACPU release packet to do refill action. +* RESERVED28[28] - (RO) Reserved bits +* CR_PLE_ADD_INT_REFILL_ENA[29] - (RW) Enable terminate refill period when PLE +* release packet to do addition. +* CR_PDMA_ADD_INT_REFILL_ENA[30] - (RW) Enable terminate refill period when +* packet in to do addition. +* CR_PKTIN_INT_REFILL_ENA[31] - (RW) Enable terminate refill period when +* packet in to do substration. +*/ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_PKTIN_INT_REFILL_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_PKTIN_INT_REFILL_ENA_MASK \ + 0x80000000 /* CR_PKTIN_INT_REFILL_ENA[31] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_PKTIN_INT_REFILL_ENA_SHFT 31 +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_PDMA_ADD_INT_REFILL_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_PDMA_ADD_INT_REFILL_ENA_MASK \ + 0x40000000 /* CR_PDMA_ADD_INT_REFILL_ENA[30] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_PDMA_ADD_INT_REFILL_ENA_SHFT 30 +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_PLE_ADD_INT_REFILL_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_PLE_ADD_INT_REFILL_ENA_MASK \ + 0x20000000 /* CR_PLE_ADD_INT_REFILL_ENA[29] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_PLE_ADD_INT_REFILL_ENA_SHFT 29 +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_RET_REFILL_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_RET_REFILL_ENA_MASK \ + 0x08000000 /* WACPU_RET_REFILL_ENA[27] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_RET_REFILL_ENA_SHFT 27 +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_ADD_RES_REFILL_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_ADD_RES_REFILL_ENA_MASK \ + 0x04000000 /* WACPU_ADD_RES_REFILL_ENA[26] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_ADD_RES_REFILL_ENA_SHFT 26 +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_ADD_SRC_REFILL_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_ADD_SRC_REFILL_ENA_MASK \ + 0x02000000 /* WACPU_ADD_SRC_REFILL_ENA[25] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_ADD_SRC_REFILL_ENA_SHFT 25 +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_SUB_SRC_REFILL_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_SUB_SRC_REFILL_ENA_MASK \ + 0x01000000 /* WACPU_SUB_SRC_REFILL_ENA[24] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_SUB_SRC_REFILL_ENA_SHFT 24 +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_TXD_ASK_MAX_PAGE_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_TXD_ASK_MAX_PAGE_CNT_MASK \ + 0x00F00000 /* WACPU_TXD_ASK_MAX_PAGE_CNT[23..20] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_TXD_ASK_MAX_PAGE_CNT_SHFT 20 +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_PLE_SUB_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_PLE_SUB_ENA_MASK \ + 0x00020000 /* CR_PLE_SUB_ENA[17] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_PLE_SUB_ENA_SHFT 17 +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_HIF_ASK_SUB_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_HIF_ASK_SUB_ENA_MASK \ + 0x00010000 /* CR_HIF_ASK_SUB_ENA[16] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_HIF_ASK_SUB_ENA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_CMD_ASK_MAX_PAGE_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_CMD_ASK_MAX_PAGE_CNT_MASK \ + 0x0000F000 /* WACPU_CMD_ASK_MAX_PAGE_CNT[15..12] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_CMD_ASK_MAX_PAGE_CNT_SHFT 12 +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_TXD_RET_PAGE_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_TXD_RET_PAGE_CNT_MASK \ + 0x00000F00 /* WACPU_TXD_RET_PAGE_CNT[11..8] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_TXD_RET_PAGE_CNT_SHFT 8 +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_CMD_RET_PAGE_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_CMD_RET_PAGE_CNT_MASK \ + 0x000000F0 /* WACPU_CMD_RET_PAGE_CNT[7..4] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_CMD_RET_PAGE_CNT_SHFT 4 +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_WACPU_MODE_EN_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_WACPU_MODE_EN_MASK \ + 0x00000001 /* CR_WACPU_MODE_EN[0] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_WACPU_MODE_EN_SHFT 0 + +/* +* ---PACKET_MAX_SIZE (0x7C026000 + 0x1c)--- +* PLE_PACKET_MAX_SIZE[11..0] - (RW) PLE packet maximum page size (group 0 ~ +11) +* RESERVED12[15..12] - (RO) Reserved bits +* PSE_PACKET_MAX_SIZE[27..16] - (RW) PSE packet maximum page size (group 15) +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PSE_PACKET_MAX_SIZE_ADDR \ + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR +#define WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PSE_PACKET_MAX_SIZE_MASK \ + 0x0FFF0000 /* PSE_PACKET_MAX_SIZE[27..16] */ +#define WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PSE_PACKET_MAX_SIZE_SHFT 16 +#define WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PLE_PACKET_MAX_SIZE_ADDR \ + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR +#define WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PLE_PACKET_MAX_SIZE_MASK \ + 0x00000FFF /* PLE_PACKET_MAX_SIZE[11..0] */ +#define WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PLE_PACKET_MAX_SIZE_SHFT 0 + +/* +* ---GROUP0_CONTROL (0x7C026000 + 0x20)--- +* GROUP0_MIN_QUOTA[11..0] - (RW) Group0 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP0_MAX_QUOTA[27..16] - (RW) Group0 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_GROUP0_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_GROUP0_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP0_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_GROUP0_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_GROUP0_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_GROUP0_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP0_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_GROUP0_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP1_CONTROL (0x7C026000 + 0x24)--- +* GROUP1_MIN_QUOTA[11..0] - (RW) Group1 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP1_MAX_QUOTA[27..16] - (RW) Group1 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_GROUP1_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_GROUP1_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP1_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_GROUP1_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_GROUP1_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_GROUP1_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP1_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_GROUP1_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP2_CONTROL (0x7C026000 + 0x28)--- +* GROUP2_MIN_QUOTA[11..0] - (RW) Group2 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP2_MAX_QUOTA[27..16] - (RW) Group2 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_GROUP2_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_GROUP2_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP2_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_GROUP2_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_GROUP2_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_GROUP2_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP2_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_GROUP2_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP3_CONTROL (0x7C026000 + 0x2C)--- +* GROUP3_MIN_QUOTA[11..0] - (RW) Group3 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP3_MAX_QUOTA[27..16] - (RW) Group3 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_GROUP3_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_GROUP3_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP3_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_GROUP3_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_GROUP3_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_GROUP3_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP3_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_GROUP3_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP4_CONTROL (0x7C026000 + 0x30)--- +* GROUP4_MIN_QUOTA[11..0] - (RW) Group4 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP4_MAX_QUOTA[27..16] - (RW) Group4 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_GROUP4_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_GROUP4_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP4_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_GROUP4_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_GROUP4_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_GROUP4_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP4_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_GROUP4_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP5_CONTROL (0x7C026000 + 0x34)--- +* GROUP5_MIN_QUOTA[11..0] - (RW) Group5 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP5_MAX_QUOTA[27..16] - (RW) Group5 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP5_CONTROL_GROUP5_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP5_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP5_CONTROL_GROUP5_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP5_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP5_CONTROL_GROUP5_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP5_CONTROL_GROUP5_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP5_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP5_CONTROL_GROUP5_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP5_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP5_CONTROL_GROUP5_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP6_CONTROL (0x7C026000 + 0x38)--- +* GROUP6_MIN_QUOTA[11..0] - (RW) Group6 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP6_MAX_QUOTA[27..16] - (RW) Group6 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP6_CONTROL_GROUP6_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP6_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP6_CONTROL_GROUP6_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP6_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP6_CONTROL_GROUP6_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP6_CONTROL_GROUP6_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP6_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP6_CONTROL_GROUP6_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP6_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP6_CONTROL_GROUP6_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP7_CONTROL (0x7C026000 + 0x3C)--- +* GROUP7_MIN_QUOTA[11..0] - (RW) Group7 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP7_MAX_QUOTA[27..16] - (RW) Group7 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP7_CONTROL_GROUP7_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP7_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP7_CONTROL_GROUP7_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP7_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP7_CONTROL_GROUP7_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP7_CONTROL_GROUP7_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP7_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP7_CONTROL_GROUP7_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP7_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP7_CONTROL_GROUP7_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP8_CONTROL (0x7C026000 + 0x40)--- +* GROUP8_MIN_QUOTA[11..0] - (RW) Group8 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP8_MAX_QUOTA[27..16] - (RW) Group8 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP8_CONTROL_GROUP8_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP8_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP8_CONTROL_GROUP8_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP8_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP8_CONTROL_GROUP8_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP8_CONTROL_GROUP8_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP8_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP8_CONTROL_GROUP8_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP8_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP8_CONTROL_GROUP8_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP9_CONTROL (0x7C026000 + 0x44)--- +* GROUP9_MIN_QUOTA[11..0] - (RW) Group9 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP9_MAX_QUOTA[27..16] - (RW) Group9 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP9_CONTROL_GROUP9_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP9_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP9_CONTROL_GROUP9_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP9_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP9_CONTROL_GROUP9_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP9_CONTROL_GROUP9_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP9_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP9_CONTROL_GROUP9_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP9_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP9_CONTROL_GROUP9_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP10_CONTROL (0x7C026000 + 0x48)--- +* GROUP10_MIN_QUOTA[11..0] - (RW) Group10 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP10_MAX_QUOTA[27..16] - (RW) Group10 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP10_CONTROL_GROUP10_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP10_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP10_CONTROL_GROUP10_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP10_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP10_CONTROL_GROUP10_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP10_CONTROL_GROUP10_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP10_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP10_CONTROL_GROUP10_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP10_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP10_CONTROL_GROUP10_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP11_CONTROL (0x7C026000 + 0x4C)--- +* GROUP11_MIN_QUOTA[11..0] - (RW) Group11 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP11_MAX_QUOTA[27..16] - (RW) Group11 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP11_CONTROL_GROUP11_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP11_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP11_CONTROL_GROUP11_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP11_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP11_CONTROL_GROUP11_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP11_CONTROL_GROUP11_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP11_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP11_CONTROL_GROUP11_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP11_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP11_CONTROL_GROUP11_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP12_CONTROL (0x7C026000 + 0x50)--- +* GROUP12_MIN_QUOTA[11..0] - (RW) Group12 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP12_MAX_QUOTA[27..16] - (RW) Group12 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP12_CONTROL_GROUP12_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP12_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP12_CONTROL_GROUP12_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP12_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP12_CONTROL_GROUP12_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP12_CONTROL_GROUP12_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP12_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP12_CONTROL_GROUP12_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP12_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP12_CONTROL_GROUP12_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP13_CONTROL (0x7C026000 + 0x54)--- +* GROUP13_MIN_QUOTA[11..0] - (RW) Group13 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP13_MAX_QUOTA[27..16] - (RW) Group13 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP13_CONTROL_GROUP13_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP13_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP13_CONTROL_GROUP13_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP13_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP13_CONTROL_GROUP13_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP13_CONTROL_GROUP13_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP13_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP13_CONTROL_GROUP13_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP13_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP13_CONTROL_GROUP13_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP14_CONTROL (0x7C026000 + 0x58)--- +* GROUP14_MIN_QUOTA[11..0] - (RW) Group14 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP14_MAX_QUOTA[27..16] - (RW) Group14 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP14_CONTROL_GROUP14_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP14_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP14_CONTROL_GROUP14_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP14_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP14_CONTROL_GROUP14_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP14_CONTROL_GROUP14_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP14_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP14_CONTROL_GROUP14_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP14_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP14_CONTROL_GROUP14_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP15_CONTROL (0x7C026000 + 0x5C)--- +* GROUP15_MIN_QUOTA[11..0] - (RW) Group15 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP15_MAX_QUOTA[27..16] - (RW) Group15 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP15_CONTROL_GROUP15_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP15_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP15_CONTROL_GROUP15_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP15_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP15_CONTROL_GROUP15_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP15_CONTROL_GROUP15_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP15_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP15_CONTROL_GROUP15_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP15_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP15_CONTROL_GROUP15_MIN_QUOTA_SHFT 0 + +/* +* ---QUEUE_MAPPING0 (0x7C026000 + 0x60)--- +* QUEUE0_MAPPING[3..0] - (RW) Queue 0 use which group ID +* QUEUE1_MAPPING[7..4] - (RW) Queue 1 use which group ID +* QUEUE2_MAPPING[11..8] - (RW) Queue 2 use which group ID +* QUEUE3_MAPPING[15..12] - (RW) Queue 3 use which group ID +* QUEUE4_MAPPING[19..16] - (RW) Queue 4 use which group ID +* QUEUE5_MAPPING[23..20] - (RW) Queue 5 use which group ID +* QUEUE6_MAPPING[27..24] - (RW) Queue 6 use which group ID +* QUEUE7_MAPPING[31..28] - (RW) Queue 7 use which group ID +*/ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE7_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE7_MAPPING_MASK \ + 0xF0000000 /* QUEUE7_MAPPING[31..28] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE7_MAPPING_SHFT 28 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE6_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE6_MAPPING_MASK \ + 0x0F000000 /* QUEUE6_MAPPING[27..24] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE6_MAPPING_SHFT 24 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE5_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE5_MAPPING_MASK \ + 0x00F00000 /* QUEUE5_MAPPING[23..20] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE5_MAPPING_SHFT 20 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE4_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE4_MAPPING_MASK \ + 0x000F0000 /* QUEUE4_MAPPING[19..16] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE4_MAPPING_SHFT 16 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE3_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE3_MAPPING_MASK \ + 0x0000F000 /* QUEUE3_MAPPING[15..12] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE3_MAPPING_SHFT 12 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE2_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE2_MAPPING_MASK \ + 0x00000F00 /* QUEUE2_MAPPING[11..8] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE2_MAPPING_SHFT 8 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE1_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE1_MAPPING_MASK \ + 0x000000F0 /* QUEUE1_MAPPING[7..4] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE1_MAPPING_SHFT 4 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE0_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE0_MAPPING_MASK \ + 0x0000000F /* QUEUE0_MAPPING[3..0] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE0_MAPPING_SHFT 0 + +/* +* ---QUEUE_MAPPING1 (0x7C026000 + 0x64)--- +* QUEUE8_MAPPING[3..0] - (RW) Queue 8 use which group ID +* QUEUE9_MAPPING[7..4] - (RW) Queue 9 use which group ID +* QUEUE10_MAPPING[11..8] - (RW) Queue 10 use which group ID +* QUEUE11_MAPPING[15..12] - (RW) Queue 11 use which group ID +* QUEUE12_MAPPING[19..16] - (RW) Queue 12 use which group ID +* QUEUE13_MAPPING[23..20] - (RW) Queue 13 use which group ID +* QUEUE14_MAPPING[27..24] - (RW) Queue 14 use which group ID +* QUEUE15_MAPPING[31..28] - (RW) Queue 15 use which group ID +*/ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE15_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE15_MAPPING_MASK \ + 0xF0000000 /* QUEUE15_MAPPING[31..28] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE15_MAPPING_SHFT 28 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE14_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE14_MAPPING_MASK \ + 0x0F000000 /* QUEUE14_MAPPING[27..24] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE14_MAPPING_SHFT 24 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE13_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE13_MAPPING_MASK \ + 0x00F00000 /* QUEUE13_MAPPING[23..20] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE13_MAPPING_SHFT 20 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE12_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE12_MAPPING_MASK \ + 0x000F0000 /* QUEUE12_MAPPING[19..16] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE12_MAPPING_SHFT 16 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE11_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE11_MAPPING_MASK \ + 0x0000F000 /* QUEUE11_MAPPING[15..12] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE11_MAPPING_SHFT 12 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE10_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE10_MAPPING_MASK \ + 0x00000F00 /* QUEUE10_MAPPING[11..8] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE10_MAPPING_SHFT 8 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE9_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE9_MAPPING_MASK \ + 0x000000F0 /* QUEUE9_MAPPING[7..4] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE9_MAPPING_SHFT 4 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE8_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE8_MAPPING_MASK \ + 0x0000000F /* QUEUE8_MAPPING[3..0] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE8_MAPPING_SHFT 0 + +/* +* ---QUEUE_MAPPING2 (0x7C026000 + 0x68)--- +* QUEUE16_MAPPING[3..0] - (RW) Queue 16 use which group ID +* QUEUE17_MAPPING[7..4] - (RW) Queue 17 use which group ID +* QUEUE18_MAPPING[11..8] - (RW) Queue 18 use which group ID +* QUEUE19_MAPPING[15..12] - (RW) Queue 19 use which group ID +* QUEUE20_MAPPING[19..16] - (RW) Queue 20 use which group ID +* QUEUE21_MAPPING[23..20] - (RW) Queue 21 use which group ID +* QUEUE22_MAPPING[27..24] - (RW) Queue 22 use which group ID +* QUEUE23_MAPPING[31..28] - (RW) Queue 23 use which group ID +*/ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE23_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE23_MAPPING_MASK \ + 0xF0000000 /* QUEUE23_MAPPING[31..28] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE23_MAPPING_SHFT 28 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE22_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE22_MAPPING_MASK \ + 0x0F000000 /* QUEUE22_MAPPING[27..24] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE22_MAPPING_SHFT 24 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE21_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE21_MAPPING_MASK \ + 0x00F00000 /* QUEUE21_MAPPING[23..20] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE21_MAPPING_SHFT 20 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE20_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE20_MAPPING_MASK \ + 0x000F0000 /* QUEUE20_MAPPING[19..16] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE20_MAPPING_SHFT 16 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE19_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE19_MAPPING_MASK \ + 0x0000F000 /* QUEUE19_MAPPING[15..12] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE19_MAPPING_SHFT 12 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE18_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE18_MAPPING_MASK \ + 0x00000F00 /* QUEUE18_MAPPING[11..8] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE18_MAPPING_SHFT 8 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE17_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE17_MAPPING_MASK \ + 0x000000F0 /* QUEUE17_MAPPING[7..4] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE17_MAPPING_SHFT 4 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE16_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE16_MAPPING_MASK \ + 0x0000000F /* QUEUE16_MAPPING[3..0] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE16_MAPPING_SHFT 0 + +/* +* ---QUEUE_MAPPING3 (0x7C026000 + 0x6c)--- +* QUEUE24_MAPPING[3..0] - (RW) Queue 24 use which group ID +* QUEUE25_MAPPING[7..4] - (RW) Queue 25 use which group ID +* QUEUE26_MAPPING[11..8] - (RW) Queue 26 use which group ID +* QUEUE27_MAPPING[15..12] - (RW) Queue 27 use which group ID +* QUEUE28_MAPPING[19..16] - (RW) Queue 28 use which group ID +* QUEUE29_MAPPING[23..20] - (RW) Queue 29 use which group ID +* QUEUE30_MAPPING[27..24] - (RW) Queue 30 use which group ID +* QUEUE31_MAPPING[31..28] - (RW) Queue 31 use which group ID +*/ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE31_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE31_MAPPING_MASK \ + 0xF0000000 /* QUEUE31_MAPPING[31..28] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE31_MAPPING_SHFT 28 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE30_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE30_MAPPING_MASK \ + 0x0F000000 /* QUEUE30_MAPPING[27..24] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE30_MAPPING_SHFT 24 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE29_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE29_MAPPING_MASK \ + 0x00F00000 /* QUEUE29_MAPPING[23..20] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE29_MAPPING_SHFT 20 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE28_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE28_MAPPING_MASK \ + 0x000F0000 /* QUEUE28_MAPPING[19..16] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE28_MAPPING_SHFT 16 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE27_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE27_MAPPING_MASK \ + 0x0000F000 /* QUEUE27_MAPPING[15..12] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE27_MAPPING_SHFT 12 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE26_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE26_MAPPING_MASK \ + 0x00000F00 /* QUEUE26_MAPPING[11..8] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE26_MAPPING_SHFT 8 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE25_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE25_MAPPING_MASK \ + 0x000000F0 /* QUEUE25_MAPPING[7..4] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE25_MAPPING_SHFT 4 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE24_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE24_MAPPING_MASK \ + 0x0000000F /* QUEUE24_MAPPING[3..0] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE24_MAPPING_SHFT 0 + +/* +* ---HIF_SCHEDULER_SETTING0 (0x7C026000 + 0x70)--- +* PRIORITY0_GROUP[3..0] - (RW) Which group is priority 0, this group is +* highest priority +* PRIORITY1_GROUP[7..4] - (RW) Which group is priority 1 +* PRIORITY2_GROUP[11..8] - (RW) Which group is priority 2 +* PRIORITY3_GROUP[15..12] - (RW) Which group is priority 3 +* PRIORITY4_GROUP[19..16] - (RW) Which group is priority 4 +* PRIORITY5_GROUP[23..20] - (RW) Which group is priority 5 +* PRIORITY6_GROUP[27..24] - (RW) Which group is priority 6 +* PRIORITY7_GROUP[31..28] - (RW) Which group is priority 7 +*/ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY7_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY7_GROUP_MASK \ + 0xF0000000 /* PRIORITY7_GROUP[31..28] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY7_GROUP_SHFT 28 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY6_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY6_GROUP_MASK \ + 0x0F000000 /* PRIORITY6_GROUP[27..24] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY6_GROUP_SHFT 24 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY5_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY5_GROUP_MASK \ + 0x00F00000 /* PRIORITY5_GROUP[23..20] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY5_GROUP_SHFT 20 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY4_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY4_GROUP_MASK \ + 0x000F0000 /* PRIORITY4_GROUP[19..16] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY4_GROUP_SHFT 16 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY3_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY3_GROUP_MASK \ + 0x0000F000 /* PRIORITY3_GROUP[15..12] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY3_GROUP_SHFT 12 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY2_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY2_GROUP_MASK \ + 0x00000F00 /* PRIORITY2_GROUP[11..8] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY2_GROUP_SHFT 8 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY1_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY1_GROUP_MASK \ + 0x000000F0 /* PRIORITY1_GROUP[7..4] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY1_GROUP_SHFT 4 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY0_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY0_GROUP_MASK \ + 0x0000000F /* PRIORITY0_GROUP[3..0] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY0_GROUP_SHFT 0 + +/* +* ---HIF_SCHEDULER_SETTING1 (0x7C026000 + 0x74)--- +* PRIORITY8_GROUP[3..0] - (RW) Which group is priority 8 +* PRIORITY9_GROUP[7..4] - (RW) Which group is priority 9 +* PRIORITY10_GROUP[11..8] - (RW) Which group is priority 10 +* PRIORITY11_GROUP[15..12] - (RW) Which group is priority 11 +* PRIORITY12_GROUP[19..16] - (RW) Which group is priority 12 +* PRIORITY13_GROUP[23..20] - (RW) Which group is priority 13 +* PRIORITY14_GROUP[27..24] - (RW) Which group is priority 14 +* PRIORITY15_GROUP[31..28] - (RW) Which group is priority 15, this group +* is last priority +*/ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY15_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY15_GROUP_MASK \ + 0xF0000000 /* PRIORITY15_GROUP[31..28] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY15_GROUP_SHFT 28 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY14_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY14_GROUP_MASK \ + 0x0F000000 /* PRIORITY14_GROUP[27..24] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY14_GROUP_SHFT 24 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY13_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY13_GROUP_MASK \ + 0x00F00000 /* PRIORITY13_GROUP[23..20] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY13_GROUP_SHFT 20 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY12_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY12_GROUP_MASK \ + 0x000F0000 /* PRIORITY12_GROUP[19..16] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY12_GROUP_SHFT 16 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY11_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY11_GROUP_MASK \ + 0x0000F000 /* PRIORITY11_GROUP[15..12] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY11_GROUP_SHFT 12 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY10_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY10_GROUP_MASK \ + 0x00000F00 /* PRIORITY10_GROUP[11..8] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY10_GROUP_SHFT 8 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY9_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY9_GROUP_MASK \ + 0x000000F0 /* PRIORITY9_GROUP[7..4] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY9_GROUP_SHFT 4 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY8_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY8_GROUP_MASK \ + 0x0000000F /* PRIORITY8_GROUP[3..0] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY8_GROUP_SHFT 0 + +/* +* ---SLOT_SETTING0 (0x7C026000 + 0x78)--- +* SLOT_0_SETTING[3..0] - (RW) Slot0 priority setting +* SLOT_1_SETTING[7..4] - (RW) Slot1 priority setting +* SLOT_2_SETTING[11..8] - (RW) Slot2 priority setting +* SLOT_3_SETTING[15..12] - (RW) Slot3 priority setting +* SLOT_4_SETTING[19..16] - (RW) Slot4 priority setting +* SLOT_5_SETTING[23..20] - (RW) Slot5 priority setting +* SLOT_6_SETTING[27..24] - (RW) Slot6 priority setting +* SLOT_7_SETTING[31..28] - (RW) Slot7 priority setting(which group ID) +*/ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_7_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_7_SETTING_MASK \ + 0xF0000000 /* SLOT_7_SETTING[31..28] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_7_SETTING_SHFT 28 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_6_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_6_SETTING_MASK \ + 0x0F000000 /* SLOT_6_SETTING[27..24] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_6_SETTING_SHFT 24 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_5_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_5_SETTING_MASK \ + 0x00F00000 /* SLOT_5_SETTING[23..20] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_5_SETTING_SHFT 20 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_4_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_4_SETTING_MASK \ + 0x000F0000 /* SLOT_4_SETTING[19..16] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_4_SETTING_SHFT 16 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_3_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_3_SETTING_MASK \ + 0x0000F000 /* SLOT_3_SETTING[15..12] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_3_SETTING_SHFT 12 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_2_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_2_SETTING_MASK \ + 0x00000F00 /* SLOT_2_SETTING[11..8] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_2_SETTING_SHFT 8 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_1_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_1_SETTING_MASK \ + 0x000000F0 /* SLOT_1_SETTING[7..4] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_1_SETTING_SHFT 4 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_0_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_0_SETTING_MASK \ + 0x0000000F /* SLOT_0_SETTING[3..0] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_0_SETTING_SHFT 0 + +/* +* ---SLOT_SETTING1 (0x7C026000 + 0x7C)--- +* SLOT_8_SETTING[3..0] - (RW) Slot8 priority setting +* SLOT_9_SETTING[7..4] - (RW) Slot9 priority setting +* SLOT_10_SETTING[11..8] - (RW) Slot10 priority setting +* SLOT_11_SETTING[15..12] - (RW) Slo11 priority setting +* SLOT_12_SETTING[19..16] - (RW) Slot12 priority setting +* SLOT_13_SETTING[23..20] - (RW) Slot13 priority setting +* SLOT_14_SETTING[27..24] - (RW) Slot14 priority setting +* SLOT_15_SETTING[31..28] - (RW) Slot15 priority setting(which group ID) +*/ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_15_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_15_SETTING_MASK \ + 0xF0000000 /* SLOT_15_SETTING[31..28] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_15_SETTING_SHFT 28 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_14_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_14_SETTING_MASK \ + 0x0F000000 /* SLOT_14_SETTING[27..24] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_14_SETTING_SHFT 24 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_13_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_13_SETTING_MASK \ + 0x00F00000 /* SLOT_13_SETTING[23..20] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_13_SETTING_SHFT 20 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_12_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_12_SETTING_MASK \ + 0x000F0000 /* SLOT_12_SETTING[19..16] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_12_SETTING_SHFT 16 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_11_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_11_SETTING_MASK \ + 0x0000F000 /* SLOT_11_SETTING[15..12] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_11_SETTING_SHFT 12 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_10_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_10_SETTING_MASK \ + 0x00000F00 /* SLOT_10_SETTING[11..8] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_10_SETTING_SHFT 8 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_9_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_9_SETTING_MASK \ + 0x000000F0 /* SLOT_9_SETTING[7..4] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_9_SETTING_SHFT 4 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_8_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_8_SETTING_MASK \ + 0x0000000F /* SLOT_8_SETTING[3..0] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_8_SETTING_SHFT 0 + +/* +* ---SLOT_PERIOD (0x7C026000 + 0x80)--- +* SLOT_PERIOD[15..0] - (RW) Slot Period (clock periods) +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_SLOT_PERIOD_SLOT_PERIOD_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_PERIOD_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_PERIOD_SLOT_PERIOD_MASK \ + 0x0000FFFF /* SLOT_PERIOD[15..0] */ +#define WF_HIF_DMASHDL_TOP_SLOT_PERIOD_SLOT_PERIOD_SHFT 0 + +/* +* ---DEBUG_PORT00 (0x7C026000 + 0xC0)--- +* DEBUG_N0_SEL[0] - (RW) Debug port n0 enable +* DEBUG_N1_SEL[1] - (RW) Debug port n1 enable +* DEBUG_N2_SEL[2] - (RW) Debug port n2 enable +* DEBUG_N3_SEL[3] - (RW) Debug port n3 enable +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT00_DEBUG_N3_SEL_ADDR \ + WF_HIF_DMASHDL_TOP_DEBUG_PORT00_ADDR +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT00_DEBUG_N3_SEL_MASK \ + 0x00000008 /* DEBUG_N3_SEL[3] */ +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT00_DEBUG_N3_SEL_SHFT 3 +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT00_DEBUG_N2_SEL_ADDR \ + WF_HIF_DMASHDL_TOP_DEBUG_PORT00_ADDR +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT00_DEBUG_N2_SEL_MASK \ + 0x00000004 /* DEBUG_N2_SEL[2] */ +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT00_DEBUG_N2_SEL_SHFT 2 +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT00_DEBUG_N1_SEL_ADDR \ + WF_HIF_DMASHDL_TOP_DEBUG_PORT00_ADDR +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT00_DEBUG_N1_SEL_MASK \ + 0x00000002 /* DEBUG_N1_SEL[1] */ +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT00_DEBUG_N1_SEL_SHFT 1 +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT00_DEBUG_N0_SEL_ADDR \ + WF_HIF_DMASHDL_TOP_DEBUG_PORT00_ADDR +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT00_DEBUG_N0_SEL_MASK \ + 0x00000001 /* DEBUG_N0_SEL[0] */ +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT00_DEBUG_N0_SEL_SHFT 0 + +/* +* ---DEBUG_PORT01 (0x7C026000 + 0xC4)--- +* DEBUG_FLAG_N0_SEL[7..0] - (RW) Debug port n0 select +* DEBUG_FLAG_N1_SEL[15..8] - (RW) Debug port n1 select +* DEBUG_FLAG_N2_SEL[23..16] - (RW) Debug port n2 select +* DEBUG_FLAG_N3_SEL[31..24] - (RW) Debug port n3 select +*/ +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT01_DEBUG_FLAG_N3_SEL_ADDR \ + WF_HIF_DMASHDL_TOP_DEBUG_PORT01_ADDR +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT01_DEBUG_FLAG_N3_SEL_MASK \ + 0xFF000000 /* DEBUG_FLAG_N3_SEL[31..24] */ +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT01_DEBUG_FLAG_N3_SEL_SHFT 24 +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT01_DEBUG_FLAG_N2_SEL_ADDR \ + WF_HIF_DMASHDL_TOP_DEBUG_PORT01_ADDR +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT01_DEBUG_FLAG_N2_SEL_MASK \ + 0x00FF0000 /* DEBUG_FLAG_N2_SEL[23..16] */ +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT01_DEBUG_FLAG_N2_SEL_SHFT 16 +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT01_DEBUG_FLAG_N1_SEL_ADDR \ + WF_HIF_DMASHDL_TOP_DEBUG_PORT01_ADDR +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT01_DEBUG_FLAG_N1_SEL_MASK \ + 0x0000FF00 /* DEBUG_FLAG_N1_SEL[15..8] */ +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT01_DEBUG_FLAG_N1_SEL_SHFT 8 +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT01_DEBUG_FLAG_N0_SEL_ADDR \ + WF_HIF_DMASHDL_TOP_DEBUG_PORT01_ADDR +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT01_DEBUG_FLAG_N0_SEL_MASK \ + 0x000000FF /* DEBUG_FLAG_N0_SEL[7..0] */ +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT01_DEBUG_FLAG_N0_SEL_SHFT 0 + +/* +* ---STATUS_RD02 (0x7C026000 + 0xC8)--- +* REFILL_CS[3..0] - (RO) Refill state machine for current state +* REFILL_NS[7..4] - (RO) Refill state machine for next state +* DMASHDL_CS[10..8] - (RO) DMASHDL state machine for current state +* RESERVED11[11] - (RO) Reserved bits +* DMASHDL_NS[14..12] - (RO) DMASHDL state machine for next state +* RESERVED15[15] - (RO) Reserved bits +* HIF_DMASHDL_DEBUG_PORT[31..16] - (RO) DMASHDL debug port signals +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_HIF_DMASHDL_DEBUG_PORT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD02_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_HIF_DMASHDL_DEBUG_PORT_MASK \ + 0xFFFF0000 /* HIF_DMASHDL_DEBUG_PORT[31..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_HIF_DMASHDL_DEBUG_PORT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_DMASHDL_NS_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD02_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_DMASHDL_NS_MASK \ + 0x00007000 /* DMASHDL_NS[14..12] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_DMASHDL_NS_SHFT 12 +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_DMASHDL_CS_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD02_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_DMASHDL_CS_MASK \ + 0x00000700 /* DMASHDL_CS[10..8] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_DMASHDL_CS_SHFT 8 +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_REFILL_NS_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD02_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_REFILL_NS_MASK \ + 0x000000F0 /* REFILL_NS[7..4] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_REFILL_NS_SHFT 4 +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_REFILL_CS_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD02_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_REFILL_CS_MASK \ + 0x0000000F /* REFILL_CS[3..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_REFILL_CS_SHFT 0 + +/* +* ---COUNTER_UDF_CLR (0x7C026000 + 0xCC)--- +* FREEPG_CNT_UDF_CLR[0] - (RW) Clear freepage count underflow flag +* FFA_CNT_UDF_CLR[1] - (RW) Clear FFA count underflow flag +* SRC_SUB_CUR_UDF_CLR[2] - (RW) Clear PLE return stage source count +* underflow flag +* REFILL_MAX1_UDF_CLR[3] - (RW) Clear pktin return stage source count +* underflow flag +* REFILL_MAX0_UDF_CLR[4] - (RW) Clear RSV add SRC count greater than +* maximum quota +* RSV_SUB_CURR_UDF_CLR[5] - (RW) Clear reservation count underflow flag +* PLE_TXD_GT_MAX_SIZE_FLAG_CLR[6] - (RW) Clear PLE TXD size greater than max +* PLE TXD size flag +* PSE_SIZE_GT_MAX_SIZE_FLAG_CLR[7] - (RW) Clear PSE packet size greater than +* max packet size flag +* HIF_ASK_LONG_FLAG_CLR[8] - (RW) Clear the HIF ask after long time period +* to grant flag +* PSE_RSV_UDF_CLR[9] - (RW) Clear the HIF ask to let reservation +* count underflow flag +* PSE_SRC_PSERET_UDF_CLR[10] - (RW) Clear the PSE source count PSE module +* return underflow flag +* PSE_SRC_PKTRET_UDF_CLR[11] - (RW) Clear the PSE source count packet in +* return underflow flag +* RESERVED12[15..12] - (RO) Reserved bits +* HIF_ASK_PKTIN_CNT_CLR[16] - (RW) Clear the ask counters and pktin return +* counters for all groups +* RESERVED17[31..17] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_HIF_ASK_PKTIN_CNT_CLR_ADDR \ + WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_HIF_ASK_PKTIN_CNT_CLR_MASK \ + 0x00010000 /* HIF_ASK_PKTIN_CNT_CLR[16] */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_HIF_ASK_PKTIN_CNT_CLR_SHFT 16 +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PSE_SRC_PKTRET_UDF_CLR_ADDR \ + WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PSE_SRC_PKTRET_UDF_CLR_MASK \ + 0x00000800 /* PSE_SRC_PKTRET_UDF_CLR[11] */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PSE_SRC_PKTRET_UDF_CLR_SHFT 11 +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PSE_SRC_PSERET_UDF_CLR_ADDR \ + WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PSE_SRC_PSERET_UDF_CLR_MASK \ + 0x00000400 /* PSE_SRC_PSERET_UDF_CLR[10] */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PSE_SRC_PSERET_UDF_CLR_SHFT 10 +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PSE_RSV_UDF_CLR_ADDR \ + WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PSE_RSV_UDF_CLR_MASK \ + 0x00000200 /* PSE_RSV_UDF_CLR[9] */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PSE_RSV_UDF_CLR_SHFT 9 +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_HIF_ASK_LONG_FLAG_CLR_ADDR \ + WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_HIF_ASK_LONG_FLAG_CLR_MASK \ + 0x00000100 /* HIF_ASK_LONG_FLAG_CLR[8] */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_HIF_ASK_LONG_FLAG_CLR_SHFT 8 +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PSE_SIZE_GT_MAX_SIZE_FLAG_CLR_ADDR \ + WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PSE_SIZE_GT_MAX_SIZE_FLAG_CLR_MASK \ + 0x00000080 /* PSE_SIZE_GT_MAX_SIZE_FLAG_CLR[7] */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PSE_SIZE_GT_MAX_SIZE_FLAG_CLR_SHFT 7 +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PLE_TXD_GT_MAX_SIZE_FLAG_CLR_ADDR \ + WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PLE_TXD_GT_MAX_SIZE_FLAG_CLR_MASK \ + 0x00000040 /* PLE_TXD_GT_MAX_SIZE_FLAG_CLR[6] */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PLE_TXD_GT_MAX_SIZE_FLAG_CLR_SHFT 6 +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_RSV_SUB_CURR_UDF_CLR_ADDR \ + WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_RSV_SUB_CURR_UDF_CLR_MASK \ + 0x00000020 /* RSV_SUB_CURR_UDF_CLR[5] */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_RSV_SUB_CURR_UDF_CLR_SHFT 5 +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_REFILL_MAX0_UDF_CLR_ADDR \ + WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_REFILL_MAX0_UDF_CLR_MASK \ + 0x00000010 /* REFILL_MAX0_UDF_CLR[4] */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_REFILL_MAX0_UDF_CLR_SHFT 4 +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_REFILL_MAX1_UDF_CLR_ADDR \ + WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_REFILL_MAX1_UDF_CLR_MASK \ + 0x00000008 /* REFILL_MAX1_UDF_CLR[3] */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_REFILL_MAX1_UDF_CLR_SHFT 3 +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_SRC_SUB_CUR_UDF_CLR_ADDR \ + WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_SRC_SUB_CUR_UDF_CLR_MASK \ + 0x00000004 /* SRC_SUB_CUR_UDF_CLR[2] */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_SRC_SUB_CUR_UDF_CLR_SHFT 2 +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_FFA_CNT_UDF_CLR_ADDR \ + WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_FFA_CNT_UDF_CLR_MASK \ + 0x00000002 /* FFA_CNT_UDF_CLR[1] */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_FFA_CNT_UDF_CLR_SHFT 1 +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_FREEPG_CNT_UDF_CLR_ADDR \ + WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_FREEPG_CNT_UDF_CLR_MASK \ + 0x00000001 /* FREEPG_CNT_UDF_CLR[0] */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_FREEPG_CNT_UDF_CLR_SHFT 0 + +/* +* ---TX_PACKET_SIZE_PAGE_MAP (0x7C026000 + 0xD0)--- +* PACKET_SIZE_PAGE_MAP[7..0] - (RW) PSE Packet size page map +* 8'bxxxx_xxx1 : 32 bytes +* 8'bxxxx_xx10 : 64 bytes +* 8'bxxxx_x100 : 128 bytes +* 8'bxxxx_1000 : 256 bytes +* 8'bxxx1_0000 : 512 bytes +* 8'bxx10_0000 : 1024 bytes +* 8'bx100_0000 : 2048 bytes +* 8'b1000_0000 : 4096 bytes +* CR_PSE_LEN_MAP_SEL[8] - (RW) Enable pse packet length page mapping by +* CR Packet size page map or not +* RESERVED9[31..9] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_TX_PACKET_SIZE_PAGE_MAP_CR_PSE_LEN_MAP_SEL_ADDR \ + WF_HIF_DMASHDL_TOP_TX_PACKET_SIZE_PAGE_MAP_ADDR +#define WF_HIF_DMASHDL_TOP_TX_PACKET_SIZE_PAGE_MAP_CR_PSE_LEN_MAP_SEL_MASK \ + 0x00000100 /* CR_PSE_LEN_MAP_SEL[8] */ +#define WF_HIF_DMASHDL_TOP_TX_PACKET_SIZE_PAGE_MAP_CR_PSE_LEN_MAP_SEL_SHFT 8 +#define WF_HIF_DMASHDL_TOP_TX_PACKET_SIZE_PAGE_MAP_PACKET_SIZE_PAGE_MAP_ADDR \ + WF_HIF_DMASHDL_TOP_TX_PACKET_SIZE_PAGE_MAP_ADDR +#define WF_HIF_DMASHDL_TOP_TX_PACKET_SIZE_PAGE_MAP_PACKET_SIZE_PAGE_MAP_MASK \ + 0x000000FF /* PACKET_SIZE_PAGE_MAP[7..0] */ +#define WF_HIF_DMASHDL_TOP_TX_PACKET_SIZE_PAGE_MAP_PACKET_SIZE_PAGE_MAP_SHFT 0 + +/* +* ---HIF_ASK_LONG_CHECK (0x7C026000 + 0xD4)--- +* HIF_ASK_TICK_CNT[15..0] - (RO) HIF request ask wait period count. +* HIF_ASK_LONG_CNT_TH[31..16] - (RW) HIF request ask wait period threshold. +* (unit = 32us, wf_aon_32us_tick) +*/ +#define WF_HIF_DMASHDL_TOP_HIF_ASK_LONG_CHECK_HIF_ASK_LONG_CNT_TH_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_ASK_LONG_CHECK_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_ASK_LONG_CHECK_HIF_ASK_LONG_CNT_TH_MASK \ + 0xFFFF0000 /* HIF_ASK_LONG_CNT_TH[31..16] */ +#define WF_HIF_DMASHDL_TOP_HIF_ASK_LONG_CHECK_HIF_ASK_LONG_CNT_TH_SHFT 16 +#define WF_HIF_DMASHDL_TOP_HIF_ASK_LONG_CHECK_HIF_ASK_TICK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_ASK_LONG_CHECK_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_ASK_LONG_CHECK_HIF_ASK_TICK_CNT_MASK \ + 0x0000FFFF /* HIF_ASK_TICK_CNT[15..0] */ +#define WF_HIF_DMASHDL_TOP_HIF_ASK_LONG_CHECK_HIF_ASK_TICK_CNT_SHFT 0 + +/* +* ---CPU_QUOTA_SET (0x7C026000 + 0xD8)--- +* RETURN_PAGE_CNT[11..0] - (RW) CPU refill page count +* RESERVED12[15..12] - (RO) Reserved bits +* CPU_RETRUN_GID[19..16] - (RW) CPU refill group's ID +* RESERVED20[23..20] - (RO) Reserved bits +* CPU_RETRUN_MODE[25..24] - (RW) CPU refill mode selection +* 2'b00 : Substrate source mode +* 2'b01 : Return mode +* 2'b10 : Add source mode +* 2'b11 : Substrate reservation mode +* RESERVED26[30..26] - (RO) Reserved bits +* EXCUTE[31] - (WO) Excute this CR action +*/ +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_EXCUTE_ADDR \ + WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_ADDR +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_EXCUTE_MASK 0x80000000 /* EXCUTE[31] */ +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_EXCUTE_SHFT 31 +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_CPU_RETRUN_MODE_ADDR \ + WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_ADDR +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_CPU_RETRUN_MODE_MASK \ + 0x03000000 /* CPU_RETRUN_MODE[25..24] */ +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_CPU_RETRUN_MODE_SHFT 24 +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_CPU_RETRUN_GID_ADDR \ + WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_ADDR +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_CPU_RETRUN_GID_MASK \ + 0x000F0000 /* CPU_RETRUN_GID[19..16] */ +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_CPU_RETRUN_GID_SHFT 16 +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_RETURN_PAGE_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_ADDR +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_RETURN_PAGE_CNT_MASK \ + 0x00000FFF /* RETURN_PAGE_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_RETURN_PAGE_CNT_SHFT 0 + +/* +* ---ERROR_FLAG_CTRL (0x7C026000 + 0xDC)--- +* CNT_UDF_INT_DMASK[15..0] - (RW) Underflow flag interrupt disable mask +control: +* bit[11] : pse_src_pktret_udf_flag +* bit[10] : pse_src_pseret_udf_flag +* bit[9] : pse_rsv_udf_flag +* bit[8] : hif_ask_long_flag_flag +* bit[7] : pse_size_gt_max_size_flag +* bit[6] : ple_txd_gt_max_size_flag +* bit[5] : rsv_sub_curr_udf_flag +* bit[4] : refill_max0_udf_flag +* bit[3] : refill_max1_udf_flag +* bit[2] : src_sub_cur_udf_flag +* bit[1] : ffa_cnt_udf_flag +* bit[0] : freepg_cnt_udf_flag +* FREEPG_CNT_UDF_FLAG[16] - (RO) Freepage count underflow flag +* FFA_CNT_UDF_FLAG[17] - (RO) FFA count underflow flag +* SRC_SUB_CUR_UDF_FLAG[18] - (RO) PLE return stage source count underflow +flag +* REFILL_MAX1_UDF_FLAG[19] - (RO) Pktin return stage source count +* underflow flag +* REFILL_MAX0_UDF_FLAG[20] - (RO) RSV add SRC count greater than maximum +quota +* RSV_SUB_CURR_UDF_FLAG[21] - (RO) Reservation count underflow flag +* PLE_TXD_GT_MAX_SIZE_FLAG[22] - (RO) PLE txd size greater than max PLE txd +* size flag +* PSE_SIZE_GT_MAX_SIZE_FLAG[23] - (RO) PSE packet size greater than max packet +* size flag +* HIF_ASK_LONG_FLAG[24] - (RO) The HIF ask after long time period to +* grant flag +* PSE_RSV_UDF_FLAG[25] - (RO) The HIF ask to let reservation count +* underflow flag +* PSE_SRC_PSERET_UDF_FLAG[26] - (RO) The PSE source count PSE module return +* underflow flag +* PSE_SRC_PKTRET_UDF_FLAG[27] - (RO) The PSE source count packet in return +* underflow flag +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PSE_SRC_PKTRET_UDF_FLAG_ADDR \ + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PSE_SRC_PKTRET_UDF_FLAG_MASK \ + 0x08000000 /* PSE_SRC_PKTRET_UDF_FLAG[27] */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PSE_SRC_PKTRET_UDF_FLAG_SHFT 27 +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PSE_SRC_PSERET_UDF_FLAG_ADDR \ + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PSE_SRC_PSERET_UDF_FLAG_MASK \ + 0x04000000 /* PSE_SRC_PSERET_UDF_FLAG[26] */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PSE_SRC_PSERET_UDF_FLAG_SHFT 26 +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PSE_RSV_UDF_FLAG_ADDR \ + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PSE_RSV_UDF_FLAG_MASK \ + 0x02000000 /* PSE_RSV_UDF_FLAG[25] */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PSE_RSV_UDF_FLAG_SHFT 25 +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_HIF_ASK_LONG_FLAG_ADDR \ + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_HIF_ASK_LONG_FLAG_MASK \ + 0x01000000 /* HIF_ASK_LONG_FLAG[24] */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_HIF_ASK_LONG_FLAG_SHFT 24 +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PSE_SIZE_GT_MAX_SIZE_FLAG_ADDR \ + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PSE_SIZE_GT_MAX_SIZE_FLAG_MASK \ + 0x00800000 /* PSE_SIZE_GT_MAX_SIZE_FLAG[23] */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PSE_SIZE_GT_MAX_SIZE_FLAG_SHFT 23 +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PLE_TXD_GT_MAX_SIZE_FLAG_ADDR \ + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PLE_TXD_GT_MAX_SIZE_FLAG_MASK \ + 0x00400000 /* PLE_TXD_GT_MAX_SIZE_FLAG[22] */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PLE_TXD_GT_MAX_SIZE_FLAG_SHFT 22 +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_RSV_SUB_CURR_UDF_FLAG_ADDR \ + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_RSV_SUB_CURR_UDF_FLAG_MASK \ + 0x00200000 /* RSV_SUB_CURR_UDF_FLAG[21] */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_RSV_SUB_CURR_UDF_FLAG_SHFT 21 +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_REFILL_MAX0_UDF_FLAG_ADDR \ + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_REFILL_MAX0_UDF_FLAG_MASK \ + 0x00100000 /* REFILL_MAX0_UDF_FLAG[20] */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_REFILL_MAX0_UDF_FLAG_SHFT 20 +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_REFILL_MAX1_UDF_FLAG_ADDR \ + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_REFILL_MAX1_UDF_FLAG_MASK \ + 0x00080000 /* REFILL_MAX1_UDF_FLAG[19] */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_REFILL_MAX1_UDF_FLAG_SHFT 19 +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_SRC_SUB_CUR_UDF_FLAG_ADDR \ + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_SRC_SUB_CUR_UDF_FLAG_MASK \ + 0x00040000 /* SRC_SUB_CUR_UDF_FLAG[18] */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_SRC_SUB_CUR_UDF_FLAG_SHFT 18 +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_FFA_CNT_UDF_FLAG_ADDR \ + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_FFA_CNT_UDF_FLAG_MASK \ + 0x00020000 /* FFA_CNT_UDF_FLAG[17] */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_FFA_CNT_UDF_FLAG_SHFT 17 +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_FREEPG_CNT_UDF_FLAG_ADDR \ + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_FREEPG_CNT_UDF_FLAG_MASK \ + 0x00010000 /* FREEPG_CNT_UDF_FLAG[16] */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_FREEPG_CNT_UDF_FLAG_SHFT 16 +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_CNT_UDF_INT_DMASK_ADDR \ + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_CNT_UDF_INT_DMASK_MASK \ + 0x0000FFFF /* CNT_UDF_INT_DMASK[15..0] */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_CNT_UDF_INT_DMASK_SHFT 0 + +/* +* ---STATUS_RD (0x7C026000 + 0x100)--- +* FFA_CNT[11..0] - (RO) Free for all (FFA) count +* RESERVED12[15..12] - (RO) Reserved bits +* FREE_PAGE_CNT[27..16] - (RO) Free page count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_FREE_PAGE_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_FREE_PAGE_CNT_MASK \ + 0x0FFF0000 /* FREE_PAGE_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_FREE_PAGE_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_FFA_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_FFA_CNT_MASK \ + 0x00000FFF /* FFA_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_FFA_CNT_SHFT 0 + +/* +* ---STATUS_RD0 (0x7C026000 + 0x110)--- +* PLE_TXD_QID_MAX2_NZERO_CNT[3..0] - (RO) Number of TXD QID[6:5] not equal +* zero counter from PLE return. +* HOST_TXD_QID_MAX2_NZERO_CNT[7..4] - (RO) Number of TXD QID[6:5] not equal +* zero counter from host send. +* CURR_TXD_CTXD_FLAG[8] - (RO) Current TXD is cascade TXD format or not +* RESERVED9[31..9] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD0_CURR_TXD_CTXD_FLAG_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD0_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD0_CURR_TXD_CTXD_FLAG_MASK \ + 0x00000100 /* CURR_TXD_CTXD_FLAG[8] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD0_CURR_TXD_CTXD_FLAG_SHFT 8 +#define WF_HIF_DMASHDL_TOP_STATUS_RD0_HOST_TXD_QID_MAX2_NZERO_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD0_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD0_HOST_TXD_QID_MAX2_NZERO_CNT_MASK \ + 0x000000F0 /* HOST_TXD_QID_MAX2_NZERO_CNT[7..4] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD0_HOST_TXD_QID_MAX2_NZERO_CNT_SHFT 4 +#define WF_HIF_DMASHDL_TOP_STATUS_RD0_PLE_TXD_QID_MAX2_NZERO_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD0_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD0_PLE_TXD_QID_MAX2_NZERO_CNT_MASK \ + 0x0000000F /* PLE_TXD_QID_MAX2_NZERO_CNT[3..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD0_PLE_TXD_QID_MAX2_NZERO_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP0 (0x7C026000 + 0x140)--- +* G0_SRC_CNT[11..0] - (RO) Group0 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G0_RSV_CNT[27..16] - (RO) Group0 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_RSV_CNT_MASK \ + 0x0FFF0000 /* G0_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_SRC_CNT_MASK \ + 0x00000FFF /* G0_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP1 (0x7C026000 + 0x144)--- +* G1_SRC_CNT[11..0] - (RO) Group1 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G1_RSV_CNT[27..16] - (RO) Group1 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP1_G1_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP1_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP1_G1_RSV_CNT_MASK \ + 0x0FFF0000 /* G1_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP1_G1_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP1_G1_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP1_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP1_G1_SRC_CNT_MASK \ + 0x00000FFF /* G1_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP1_G1_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP2 (0x7C026000 + 0x148)--- +* G2_SRC_CNT[11..0] - (RO) Group2 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G2_RSV_CNT[27..16] - (RO) Group2 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP2_G2_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP2_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP2_G2_RSV_CNT_MASK \ + 0x0FFF0000 /* G2_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP2_G2_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP2_G2_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP2_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP2_G2_SRC_CNT_MASK \ + 0x00000FFF /* G2_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP2_G2_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP3 (0x7C026000 + 0x14c)--- +* G3_SRC_CNT[11..0] - (RO) Group3 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G3_RSV_CNT[27..16] - (RO) Group3 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP3_G3_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP3_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP3_G3_RSV_CNT_MASK \ + 0x0FFF0000 /* G3_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP3_G3_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP3_G3_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP3_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP3_G3_SRC_CNT_MASK \ + 0x00000FFF /* G3_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP3_G3_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP4 (0x7C026000 + 0x150)--- +* G4_SRC_CNT[11..0] - (RO) Group4 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G4_RSV_CNT[27..16] - (RO) Group4 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP4_G4_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP4_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP4_G4_RSV_CNT_MASK \ + 0x0FFF0000 /* G4_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP4_G4_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP4_G4_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP4_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP4_G4_SRC_CNT_MASK \ + 0x00000FFF /* G4_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP4_G4_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP5 (0x7C026000 + 0x154)--- +* G5_SRC_CNT[11..0] - (RO) Group5 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G5_RSV_CNT[27..16] - (RO) Group5 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP5_G5_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP5_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP5_G5_RSV_CNT_MASK \ + 0x0FFF0000 /* G5_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP5_G5_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP5_G5_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP5_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP5_G5_SRC_CNT_MASK \ + 0x00000FFF /* G5_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP5_G5_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP6 (0x7C026000 + 0x158)--- +* G6_SRC_CNT[11..0] - (RO) Group6 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G6_RSV_CNT[27..16] - (RO) Group6 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP6_G6_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP6_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP6_G6_RSV_CNT_MASK \ + 0x0FFF0000 /* G6_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP6_G6_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP6_G6_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP6_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP6_G6_SRC_CNT_MASK \ + 0x00000FFF /* G6_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP6_G6_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP7 (0x7C026000 + 0x15C)--- +* G7_SRC_CNT[11..0] - (RO) Group7 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G7_RSV_CNT[27..16] - (RO) Group7 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP7_G7_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP7_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP7_G7_RSV_CNT_MASK \ + 0x0FFF0000 /* G7_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP7_G7_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP7_G7_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP7_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP7_G7_SRC_CNT_MASK \ + 0x00000FFF /* G7_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP7_G7_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP8 (0x7C026000 + 0x160)--- +* G8_SRC_CNT[11..0] - (RO) Group8 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G8_RSV_CNT[27..16] - (RO) Group8 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP8_G8_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP8_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP8_G8_RSV_CNT_MASK \ + 0x0FFF0000 /* G8_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP8_G8_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP8_G8_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP8_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP8_G8_SRC_CNT_MASK \ + 0x00000FFF /* G8_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP8_G8_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP9 (0x7C026000 + 0x164)--- +* G9_SRC_CNT[11..0] - (RO) Group9 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G9_RSV_CNT[27..16] - (RO) Group9 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP9_G9_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP9_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP9_G9_RSV_CNT_MASK \ + 0x0FFF0000 /* G9_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP9_G9_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP9_G9_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP9_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP9_G9_SRC_CNT_MASK \ + 0x00000FFF /* G9_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP9_G9_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP10 (0x7C026000 + 0x168)--- +* G10_SRC_CNT[11..0] - (RO) Group10 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G10_RSV_CNT[27..16] - (RO) Group10 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP10_G10_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP10_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP10_G10_RSV_CNT_MASK \ + 0x0FFF0000 /* G10_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP10_G10_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP10_G10_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP10_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP10_G10_SRC_CNT_MASK \ + 0x00000FFF /* G10_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP10_G10_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP11 (0x7C026000 + 0x16c)--- +* G11_SRC_CNT[11..0] - (RO) Group11 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G11_RSV_CNT[27..16] - (RO) Group11 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP11_G11_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP11_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP11_G11_RSV_CNT_MASK \ + 0x0FFF0000 /* G11_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP11_G11_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP11_G11_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP11_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP11_G11_SRC_CNT_MASK \ + 0x00000FFF /* G11_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP11_G11_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP12 (0x7C026000 + 0x170)--- +* G12_SRC_CNT[11..0] - (RO) Group12 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G12_RSV_CNT[27..16] - (RO) Group12 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP12_G12_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP12_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP12_G12_RSV_CNT_MASK \ + 0x0FFF0000 /* G12_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP12_G12_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP12_G12_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP12_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP12_G12_SRC_CNT_MASK \ + 0x00000FFF /* G12_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP12_G12_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP13 (0x7C026000 + 0x174)--- +* G13_SRC_CNT[11..0] - (RO) Group13 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G13_RSV_CNT[27..16] - (RO) Group13 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP13_G13_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP13_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP13_G13_RSV_CNT_MASK \ + 0x0FFF0000 /* G13_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP13_G13_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP13_G13_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP13_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP13_G13_SRC_CNT_MASK \ + 0x00000FFF /* G13_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP13_G13_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP14 (0x7C026000 + 0x178)--- +* G14_SRC_CNT[11..0] - (RO) Group14 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G14_RSV_CNT[27..16] - (RO) Group14 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP14_G14_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP14_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP14_G14_RSV_CNT_MASK \ + 0x0FFF0000 /* G14_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP14_G14_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP14_G14_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP14_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP14_G14_SRC_CNT_MASK \ + 0x00000FFF /* G14_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP14_G14_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP15 (0x7C026000 + 0x17C)--- +* G15_SRC_CNT[11..0] - (RO) Group15 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G15_RSV_CNT[27..16] - (RO) Group15 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP15_G15_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP15_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP15_G15_RSV_CNT_MASK \ + 0x0FFF0000 /* G15_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP15_G15_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP15_G15_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP15_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP15_G15_SRC_CNT_MASK \ + 0x00000FFF /* G15_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP15_G15_SRC_CNT_SHFT 0 + +/* +* ---RD_GROUP_PKT_CNT0 (0x7C026000 + 0x180)--- +* GP0_ASK_CNT[7..0] - (RO) Group0 ask count +* GP0_PKTIN_CNT[15..8] - (RO) Group0 packet in count +* GP1_ASK_CNT[23..16] - (RO) Group1 ask count +* GP1_PKTIN_CNT[31..24] - (RO) Group1 packet in count +*/ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_GP1_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_GP1_PKTIN_CNT_MASK \ + 0xFF000000 /* GP1_PKTIN_CNT[31..24] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_GP1_PKTIN_CNT_SHFT 24 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_GP1_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_GP1_ASK_CNT_MASK \ + 0x00FF0000 /* GP1_ASK_CNT[23..16] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_GP1_ASK_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_GP0_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_GP0_PKTIN_CNT_MASK \ + 0x0000FF00 /* GP0_PKTIN_CNT[15..8] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_GP0_PKTIN_CNT_SHFT 8 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_GP0_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_GP0_ASK_CNT_MASK \ + 0x000000FF /* GP0_ASK_CNT[7..0] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_GP0_ASK_CNT_SHFT 0 + +/* +* ---RD_GROUP_PKT_CNT1 (0x7C026000 + 0x184)--- +* GP2_ASK_CNT[7..0] - (RO) Group2 ask count +* GP2_PKTIN_CNT[15..8] - (RO) Group2 packet in count +* GP3_ASK_CNT[23..16] - (RO) Group3 ask count +* GP3_PKTIN_CNT[31..24] - (RO) Group3 packet in count +*/ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_GP3_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_GP3_PKTIN_CNT_MASK \ + 0xFF000000 /* GP3_PKTIN_CNT[31..24] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_GP3_PKTIN_CNT_SHFT 24 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_GP3_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_GP3_ASK_CNT_MASK \ + 0x00FF0000 /* GP3_ASK_CNT[23..16] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_GP3_ASK_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_GP2_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_GP2_PKTIN_CNT_MASK \ + 0x0000FF00 /* GP2_PKTIN_CNT[15..8] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_GP2_PKTIN_CNT_SHFT 8 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_GP2_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_GP2_ASK_CNT_MASK \ + 0x000000FF /* GP2_ASK_CNT[7..0] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_GP2_ASK_CNT_SHFT 0 + +/* +* ---RD_GROUP_PKT_CNT2 (0x7C026000 + 0x188)--- +* GP4_ASK_CNT[7..0] - (RO) Group4 ask count +* GP4_PKTIN_CNT[15..8] - (RO) Group4 packet in count +* GP5_ASK_CNT[23..16] - (RO) Group5 ask count +* GP5_PKTIN_CNT[31..24] - (RO) Group5 packet in count +*/ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_GP5_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_GP5_PKTIN_CNT_MASK \ + 0xFF000000 /* GP5_PKTIN_CNT[31..24] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_GP5_PKTIN_CNT_SHFT 24 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_GP5_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_GP5_ASK_CNT_MASK \ + 0x00FF0000 /* GP5_ASK_CNT[23..16] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_GP5_ASK_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_GP4_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_GP4_PKTIN_CNT_MASK \ + 0x0000FF00 /* GP4_PKTIN_CNT[15..8] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_GP4_PKTIN_CNT_SHFT 8 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_GP4_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_GP4_ASK_CNT_MASK \ + 0x000000FF /* GP4_ASK_CNT[7..0] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_GP4_ASK_CNT_SHFT 0 + +/* +* ---RD_GROUP_PKT_CNT3 (0x7C026000 + 0x18c)--- +* GP6_ASK_CNT[7..0] - (RO) Group6 ask count +* GP6_PKTIN_CNT[15..8] - (RO) Group6 packet in count +* GP7_ASK_CNT[23..16] - (RO) Group7 ask count +* GP7_PKTIN_CNT[31..24] - (RO) Group7 packet in count +*/ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_GP7_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_GP7_PKTIN_CNT_MASK \ + 0xFF000000 /* GP7_PKTIN_CNT[31..24] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_GP7_PKTIN_CNT_SHFT 24 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_GP7_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_GP7_ASK_CNT_MASK \ + 0x00FF0000 /* GP7_ASK_CNT[23..16] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_GP7_ASK_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_GP6_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_GP6_PKTIN_CNT_MASK \ + 0x0000FF00 /* GP6_PKTIN_CNT[15..8] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_GP6_PKTIN_CNT_SHFT 8 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_GP6_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_GP6_ASK_CNT_MASK \ + 0x000000FF /* GP6_ASK_CNT[7..0] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_GP6_ASK_CNT_SHFT 0 + +/* +* ---RD_GROUP_PKT_CNT4 (0x7C026000 + 0x190)--- +* GP8_ASK_CNT[7..0] - (RO) Group8 ask count +* GP8_PKTIN_CNT[15..8] - (RO) Group8 packet in count +* GP9_ASK_CNT[23..16] - (RO) Group9 ask count +* GP9_PKTIN_CNT[31..24] - (RO) Group9 packet in count +*/ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_GP9_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_GP9_PKTIN_CNT_MASK \ + 0xFF000000 /* GP9_PKTIN_CNT[31..24] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_GP9_PKTIN_CNT_SHFT 24 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_GP9_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_GP9_ASK_CNT_MASK \ + 0x00FF0000 /* GP9_ASK_CNT[23..16] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_GP9_ASK_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_GP8_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_GP8_PKTIN_CNT_MASK \ + 0x0000FF00 /* GP8_PKTIN_CNT[15..8] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_GP8_PKTIN_CNT_SHFT 8 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_GP8_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_GP8_ASK_CNT_MASK \ + 0x000000FF /* GP8_ASK_CNT[7..0] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_GP8_ASK_CNT_SHFT 0 + +/* +* ---RD_GROUP_PKT_CNT5 (0x7C026000 + 0x194)--- +* GP10_ASK_CNT[7..0] - (RO) Group10 ask count +* GP10_PKTIN_CNT[15..8] - (RO) Group10 packet in count +* GP11_ASK_CNT[23..16] - (RO) Group11 ask count +* GP11_PKTIN_CNT[31..24] - (RO) Group11 packet in count +*/ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_GP11_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_GP11_PKTIN_CNT_MASK \ + 0xFF000000 /* GP11_PKTIN_CNT[31..24] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_GP11_PKTIN_CNT_SHFT 24 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_GP11_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_GP11_ASK_CNT_MASK \ + 0x00FF0000 /* GP11_ASK_CNT[23..16] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_GP11_ASK_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_GP10_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_GP10_PKTIN_CNT_MASK \ + 0x0000FF00 /* GP10_PKTIN_CNT[15..8] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_GP10_PKTIN_CNT_SHFT 8 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_GP10_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_GP10_ASK_CNT_MASK \ + 0x000000FF /* GP10_ASK_CNT[7..0] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_GP10_ASK_CNT_SHFT 0 + +/* +* ---RD_GROUP_PKT_CNT6 (0x7C026000 + 0x198)--- +* GP12_ASK_CNT[7..0] - (RO) Group12 ask count +* GP12_PKTIN_CNT[15..8] - (RO) Group12 packet in count +* GP13_ASK_CNT[23..16] - (RO) Group13 ask count +* GP13_PKTIN_CNT[31..24] - (RO) Group13 packet in count +*/ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_GP13_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_GP13_PKTIN_CNT_MASK \ + 0xFF000000 /* GP13_PKTIN_CNT[31..24] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_GP13_PKTIN_CNT_SHFT 24 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_GP13_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_GP13_ASK_CNT_MASK \ + 0x00FF0000 /* GP13_ASK_CNT[23..16] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_GP13_ASK_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_GP12_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_GP12_PKTIN_CNT_MASK \ + 0x0000FF00 /* GP12_PKTIN_CNT[15..8] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_GP12_PKTIN_CNT_SHFT 8 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_GP12_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_GP12_ASK_CNT_MASK \ + 0x000000FF /* GP12_ASK_CNT[7..0] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_GP12_ASK_CNT_SHFT 0 + +/* +* ---RD_GROUP_PKT_CNT7 (0x7C026000 + 0x19c)--- +* GP14_ASK_CNT[7..0] - (RO) Group14 ask count +* GP14_PKTIN_CNT[15..8] - (RO) Group14 packet in count +* GP15_ASK_CNT[23..16] - (RO) Group15 ask count +* GP15_PKTIN_CNT[31..24] - (RO) Group15 packet in count +*/ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_GP15_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_GP15_PKTIN_CNT_MASK \ + 0xFF000000 /* GP15_PKTIN_CNT[31..24] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_GP15_PKTIN_CNT_SHFT 24 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_GP15_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_GP15_ASK_CNT_MASK \ + 0x00FF0000 /* GP15_ASK_CNT[23..16] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_GP15_ASK_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_GP14_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_GP14_PKTIN_CNT_MASK \ + 0x0000FF00 /* GP14_PKTIN_CNT[15..8] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_GP14_PKTIN_CNT_SHFT 8 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_GP14_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_GP14_ASK_CNT_MASK \ + 0x000000FF /* GP14_ASK_CNT[7..0] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_GP14_ASK_CNT_SHFT 0 + +#ifdef __cplusplus +} +#endif + +#endif /* __WF_HIF_DMASHDL_TOP_REGS_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7961/wf_ple_top.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7961/wf_ple_top.h new file mode 100644 index 0000000000000..0e957b86cef91 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7961/wf_ple_top.h @@ -0,0 +1,6731 @@ +/* [File] : wf_ple_top.h */ +/* [Revision time] : Fri May 31 13:36:43 2019 */ +/* [Description] : This file is auto generated by CODA */ +/* [Copyright] : Copyright (C) 2019 Mediatek Incorportion. All rights */ +/* reserved. */ + +#ifndef __WF_PLE_TOP_REGS_H__ +#define __WF_PLE_TOP_REGS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ************************************************************************** */ +/* */ +/* WF_PLE_TOP CR Definitions */ +/* */ +/* ************************************************************************** */ + +#define WF_PLE_TOP_BASE 0x820C0000 + +#define WF_PLE_TOP_GC_ADDR \ + (WF_PLE_TOP_BASE + 0x00) /* 0000 */ +#define WF_PLE_TOP_PBUF_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x04) /* 0004 */ +#define WF_PLE_TOP_FREEPG_START_END_ADDR \ + (WF_PLE_TOP_BASE + 0x08) /* 0008 */ +#define WF_PLE_TOP_PG_HIF_GROUP_ADDR \ + (WF_PLE_TOP_BASE + 0x0c) /* 000C */ +#define WF_PLE_TOP_PG_HIF_WMTXD_GROUP_ADDR \ + (WF_PLE_TOP_BASE + 0x10) /* 0010 */ +#define WF_PLE_TOP_PG_HIF_TXCMD_GROUP_ADDR \ + (WF_PLE_TOP_BASE + 0x14) /* 0014 */ +#define WF_PLE_TOP_PG_CPU_GROUP_ADDR \ + (WF_PLE_TOP_BASE + 0x18) /* 0018 */ +#define WF_PLE_TOP_VOW_CONTROL_ADDR \ + (WF_PLE_TOP_BASE + 0x1c) /* 001C */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL1_ADDR \ + (WF_PLE_TOP_BASE + 0x20) /* 0020 */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL2_ADDR \ + (WF_PLE_TOP_BASE + 0x24) /* 0024 */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL3_ADDR \ + (WF_PLE_TOP_BASE + 0x28) /* 0028 */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL4_ADDR \ + (WF_PLE_TOP_BASE + 0x2c) /* 002C */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL5_ADDR \ + (WF_PLE_TOP_BASE + 0x30) /* 0030 */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL6_ADDR \ + (WF_PLE_TOP_BASE + 0x34) /* 0034 */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL7_ADDR \ + (WF_PLE_TOP_BASE + 0x38) /* 0038 */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL8_ADDR \ + (WF_PLE_TOP_BASE + 0x3c) /* 003C */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL9_ADDR \ + (WF_PLE_TOP_BASE + 0x40) /* 0040 */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL10_ADDR \ + (WF_PLE_TOP_BASE + 0x44) /* 0044 */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x48) /* 0048 */ +#define WF_PLE_TOP_INT_N9_EN_MASK_ADDR \ + (WF_PLE_TOP_BASE + 0x80) /* 0080 */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_ADDR \ + (WF_PLE_TOP_BASE + 0x84) /* 0084 */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR \ + (WF_PLE_TOP_BASE + 0x88) /* 0088 */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR \ + (WF_PLE_TOP_BASE + 0x8c) /* 008C */ +#define WF_PLE_TOP_HOST_REPORT0_ADDR \ + (WF_PLE_TOP_BASE + 0x90) /* 0090 */ +#define WF_PLE_TOP_HOST_REPORT1_ADDR \ + (WF_PLE_TOP_BASE + 0x94) /* 0094 */ +#define WF_PLE_TOP_HOST_REPORT2_ADDR \ + (WF_PLE_TOP_BASE + 0x98) /* 0098 */ +#define WF_PLE_TOP_RELEASE_CTRL_0_ADDR \ + (WF_PLE_TOP_BASE + 0x9c) /* 009C */ +#define WF_PLE_TOP_RELEASE_CTRL_1_ADDR \ + (WF_PLE_TOP_BASE + 0xA0) /* 00A0 */ +#define WF_PLE_TOP_RELEASE_CTRL_3_ADDR \ + (WF_PLE_TOP_BASE + 0xa8) /* 00A8 */ +#define WF_PLE_TOP_BLK_MODE_RATE_LMT_ADDR \ + (WF_PLE_TOP_BASE + 0xac) /* 00AC */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR \ + (WF_PLE_TOP_BASE + 0xb0) /* 00B0 */ +#define WF_PLE_TOP_PLE_DELAY_TX_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0xb4) /* 00B4 */ +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0xb8) /* 00B8 */ +#define WF_PLE_TOP_MACTX_LENGTH_LIMIT_ADDR \ + (WF_PLE_TOP_BASE + 0xBC) /* 00BC */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_ADDR \ + (WF_PLE_TOP_BASE + 0xc0) /* 00C0 */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0xd0) /* 00D0 */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR \ + (WF_PLE_TOP_BASE + 0xd4) /* 00D4 */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_ADDR \ + (WF_PLE_TOP_BASE + 0xd8) /* 00D8 */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR \ + (WF_PLE_TOP_BASE + 0xdc) /* 00DC */ +#define WF_PLE_TOP_ERLY_TRM_CTRL0_ADDR \ + (WF_PLE_TOP_BASE + 0xf8) /* 00F8 */ +#define WF_PLE_TOP_ERLY_TRM_CTRL1_ADDR \ + (WF_PLE_TOP_BASE + 0xfc) /* 00FC */ +#define WF_PLE_TOP_STATION_PAUSE0_ADDR \ + (WF_PLE_TOP_BASE + 0x100) /* 0100 */ +#define WF_PLE_TOP_STATION_PAUSE1_ADDR \ + (WF_PLE_TOP_BASE + 0x104) /* 0104 */ +#define WF_PLE_TOP_DIS_STA_MAP0_ADDR \ + (WF_PLE_TOP_BASE + 0x140) /* 0140 */ +#define WF_PLE_TOP_DIS_STA_MAP1_ADDR \ + (WF_PLE_TOP_BASE + 0x144) /* 0144 */ +#define WF_PLE_TOP_STATION_REDIR0_ADDR \ + (WF_PLE_TOP_BASE + 0x180) /* 0180 */ +#define WF_PLE_TOP_STATION_REDIR1_ADDR \ + (WF_PLE_TOP_BASE + 0x184) /* 0184 */ +#define WF_PLE_TOP_TWT_STA_MAP0_ADDR \ + (WF_PLE_TOP_BASE + 0x1C0) /* 01C0 */ +#define WF_PLE_TOP_TWT_STA_MAP1_ADDR \ + (WF_PLE_TOP_BASE + 0x1C4) /* 01C4 */ +#define WF_PLE_TOP_TWT_TX_CTRL0_ADDR \ + (WF_PLE_TOP_BASE + 0x200) /* 0200 */ +#define WF_PLE_TOP_DRR_SPL_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x204) /* 0204 */ +#define WF_PLE_TOP_BSS_DBDC_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x208) /* 0208 */ +#define WF_PLE_TOP_VOW_CTRL1_ADDR \ + (WF_PLE_TOP_BASE + 0x20c) /* 020C */ +#define WF_PLE_TOP_TWT_STA_TABLE0_ADDR \ + (WF_PLE_TOP_BASE + 0x210) /* 0210 */ +#define WF_PLE_TOP_TWT_STA_TABLE1_ADDR \ + (WF_PLE_TOP_BASE + 0x214) /* 0214 */ +#define WF_PLE_TOP_TWT_STA_TABLE2_ADDR \ + (WF_PLE_TOP_BASE + 0x218) /* 0218 */ +#define WF_PLE_TOP_TWT_STA_TABLE3_ADDR \ + (WF_PLE_TOP_BASE + 0x21c) /* 021C */ +#define WF_PLE_TOP_TWT_SW_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x220) /* 0220 */ +#define WF_PLE_TOP_TWT_HW_SRCHCMD_FULL_ADDR \ + (WF_PLE_TOP_BASE + 0x224) /* 0224 */ +#define WF_PLE_TOP_DRR_SW_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x228) /* 0228 */ +#define WF_PLE_TOP_DRR_SPL_CTRL_1_ADDR \ + (WF_PLE_TOP_BASE + 0x22c) /* 022C */ +#define WF_PLE_TOP_TWT_STA_FIX_AC_ADDR \ + (WF_PLE_TOP_BASE + 0x234) /* 0234 */ +#define WF_PLE_TOP_EN_UMAC_L1_DCM_ADDR \ + (WF_PLE_TOP_BASE + 0x238) /* 0238 */ +#define WF_PLE_TOP_PCIE_POWER_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x23c) /* 023C */ +#define WF_PLE_TOP_TIMEOUT_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x280) /* 0280 */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR \ + (WF_PLE_TOP_BASE + 0x284) /* 0284 */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_1_ADDR \ + (WF_PLE_TOP_BASE + 0x288) /* 0288 */ +#define WF_PLE_TOP_PORT_SER_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x290) /* 0290 */ +#define WF_PLE_TOP_MACTX_SER_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x294) /* 0294 */ +#define WF_PLE_TOP_DRR_SER_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x298) /* 0298 */ +#define WF_PLE_TOP_INT_N9_STS_ADDR \ + (WF_PLE_TOP_BASE + 0x300) /* 0300 */ +#define WF_PLE_TOP_INT_N9_ERR_STS_ADDR \ + (WF_PLE_TOP_BASE + 0x304) /* 0304 */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR \ + (WF_PLE_TOP_BASE + 0x308) /* 0308 */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR \ + (WF_PLE_TOP_BASE + 0x30c) /* 030C */ +#define WF_PLE_TOP_C_GET_FID_0_ADDR \ + (WF_PLE_TOP_BASE + 0x310) /* 0310 */ +#define WF_PLE_TOP_C_GET_FID_1_ADDR \ + (WF_PLE_TOP_BASE + 0x314) /* 0314 */ +#define WF_PLE_TOP_TO_N9_INT_ADDR \ + (WF_PLE_TOP_BASE + 0x318) /* 0318 */ +#define WF_PLE_TOP_C_EN_QUEUE_0_ADDR \ + (WF_PLE_TOP_BASE + 0x320) /* 0320 */ +#define WF_PLE_TOP_C_EN_QUEUE_1_ADDR \ + (WF_PLE_TOP_BASE + 0x324) /* 0324 */ +#define WF_PLE_TOP_C_EN_QUEUE_2_ADDR \ + (WF_PLE_TOP_BASE + 0x328) /* 0328 */ +#define WF_PLE_TOP_C_DE_QUEUE_0_ADDR \ + (WF_PLE_TOP_BASE + 0x330) /* 0330 */ +#define WF_PLE_TOP_C_DE_QUEUE_1_ADDR \ + (WF_PLE_TOP_BASE + 0x334) /* 0334 */ +#define WF_PLE_TOP_C_DE_QUEUE_2_ADDR \ + (WF_PLE_TOP_BASE + 0x338) /* 0338 */ +#define WF_PLE_TOP_C_DE_QUEUE_3_ADDR \ + (WF_PLE_TOP_BASE + 0x33c) /* 033C */ +#define WF_PLE_TOP_C_DE_QUEUE_4_ADDR \ + (WF_PLE_TOP_BASE + 0x340) /* 0340 */ +#define WF_PLE_TOP_ALLOCATE_0_ADDR \ + (WF_PLE_TOP_BASE + 0x350) /* 0350 */ +#define WF_PLE_TOP_ALLOCATE_1_ADDR \ + (WF_PLE_TOP_BASE + 0x354) /* 0354 */ +#define WF_PLE_TOP_ALLOCATE_2_ADDR \ + (WF_PLE_TOP_BASE + 0x358) /* 0358 */ +#define WF_PLE_TOP_QUEUE_EMPTY_ADDR \ + (WF_PLE_TOP_BASE + 0x360) /* 0360 */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR \ + (WF_PLE_TOP_BASE + 0x364) /* 0364 */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR \ + (WF_PLE_TOP_BASE + 0x368) /* 0368 */ +#define WF_PLE_TOP_DRR_CHNL_EMPTY_ADDR \ + (WF_PLE_TOP_BASE + 0x374) /* 0374 */ +#define WF_PLE_TOP_FREEPG_CNT_ADDR \ + (WF_PLE_TOP_BASE + 0x380) /* 0380 */ +#define WF_PLE_TOP_FREEPG_HEAD_TAIL_ADDR \ + (WF_PLE_TOP_BASE + 0x384) /* 0384 */ +#define WF_PLE_TOP_HIF_PG_INFO_ADDR \ + (WF_PLE_TOP_BASE + 0x388) /* 0388 */ +#define WF_PLE_TOP_HIF_WMTXD_PG_INFO_ADDR \ + (WF_PLE_TOP_BASE + 0x38c) /* 038C */ +#define WF_PLE_TOP_HIF_TXCMD_PG_INFO_ADDR \ + (WF_PLE_TOP_BASE + 0x390) /* 0390 */ +#define WF_PLE_TOP_CPU_PG_INFO_ADDR \ + (WF_PLE_TOP_BASE + 0x394) /* 0394 */ +#define WF_PLE_TOP_PLE_LOG_0_ADDR \ + (WF_PLE_TOP_BASE + 0x3a0) /* 03A0 */ +#define WF_PLE_TOP_PLE_LOG_1_ADDR \ + (WF_PLE_TOP_BASE + 0x3a4) /* 03A4 */ +#define WF_PLE_TOP_PLE_LOG_2_ADDR \ + (WF_PLE_TOP_BASE + 0x3a8) /* 03A8 */ +#define WF_PLE_TOP_PLE_LOG_3_ADDR \ + (WF_PLE_TOP_BASE + 0x3ac) /* 03AC */ +#define WF_PLE_TOP_WMMAC_PGCNT_0_ADDR \ + (WF_PLE_TOP_BASE + 0x3b0) /* 03B0 */ +#define WF_PLE_TOP_WMMAC_PGCNT_1_ADDR \ + (WF_PLE_TOP_BASE + 0x3b4) /* 03B4 */ +#define WF_PLE_TOP_WMMAC_PGCNT_2_ADDR \ + (WF_PLE_TOP_BASE + 0x3b8) /* 03B8 */ +#define WF_PLE_TOP_WMMAC_PGCNT_3_ADDR \ + (WF_PLE_TOP_BASE + 0x3bc) /* 03BC */ +#define WF_PLE_TOP_WMMAC_PGCNT_4_ADDR \ + (WF_PLE_TOP_BASE + 0x3c0) /* 03C0 */ +#define WF_PLE_TOP_WMMAC_PGCNT_5_ADDR \ + (WF_PLE_TOP_BASE + 0x3c4) /* 03C4 */ +#define WF_PLE_TOP_WMMAC_PGCNT_6_ADDR \ + (WF_PLE_TOP_BASE + 0x3c8) /* 03C8 */ +#define WF_PLE_TOP_WMMAC_PGCNT_7_ADDR \ + (WF_PLE_TOP_BASE + 0x3cc) /* 03CC */ +#define WF_PLE_TOP_RL_BUF_CTRL_0_ADDR \ + (WF_PLE_TOP_BASE + 0x3d0) /* 03D0 */ +#define WF_PLE_TOP_RL_BUF_CTRL_1_ADDR \ + (WF_PLE_TOP_BASE + 0x3d4) /* 03D4 */ +#define WF_PLE_TOP_FL_QUE_CTRL_0_ADDR \ + (WF_PLE_TOP_BASE + 0x3e0) /* 03E0 */ +#define WF_PLE_TOP_FL_QUE_CTRL_1_ADDR \ + (WF_PLE_TOP_BASE + 0x3e4) /* 03E4 */ +#define WF_PLE_TOP_FL_QUE_CTRL_2_ADDR \ + (WF_PLE_TOP_BASE + 0x3e8) /* 03E8 */ +#define WF_PLE_TOP_FL_QUE_CTRL_3_ADDR \ + (WF_PLE_TOP_BASE + 0x3ec) /* 03EC */ +#define WF_PLE_TOP_PL_QUE_CTRL_0_ADDR \ + (WF_PLE_TOP_BASE + 0x3f0) /* 03F0 */ +#define WF_PLE_TOP_HIF_ENQ_PKT_NUM_ADDR \ + (WF_PLE_TOP_BASE + 0x400) /* 0400 */ +#define WF_PLE_TOP_CPU_ENQ_PKT_NUM_ADDR \ + (WF_PLE_TOP_BASE + 0x404) /* 0404 */ +#define WF_PLE_TOP_RLS_MSDU_PKT_NUM_ADDR \ + (WF_PLE_TOP_BASE + 0x408) /* 0408 */ +#define WF_PLE_TOP_HOST_REPORT_NUM_ADDR \ + (WF_PLE_TOP_BASE + 0x40c) /* 040C */ +#define WF_PLE_TOP_UMAC_DBG_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x410) /* 0410 */ +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_ADDR \ + (WF_PLE_TOP_BASE + 0x414) /* 0414 */ +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_ADDR \ + (WF_PLE_TOP_BASE + 0x418) /* 0418 */ +#define WF_PLE_TOP_FUNC_ACT_CNT_1_ADDR \ + (WF_PLE_TOP_BASE + 0x424) /* 0424 */ +#define WF_PLE_TOP_SRAM_MBIST_BACKGROUND_ADDR \ + (WF_PLE_TOP_BASE + 0x430) /* 0430 */ +#define WF_PLE_TOP_SRAM_MBIST_BSEL_ADDR \ + (WF_PLE_TOP_BASE + 0x434) /* 0434 */ +#define WF_PLE_TOP_SRAM_MBIST_DONE_ADDR \ + (WF_PLE_TOP_BASE + 0x438) /* 0438 */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR \ + (WF_PLE_TOP_BASE + 0x43c) /* 043C */ +#define WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x440) /* 0440 */ +#define WF_PLE_TOP_DRR_TABLE_WDATA0_ADDR \ + (WF_PLE_TOP_BASE + 0x450) /* 0450 */ +#define WF_PLE_TOP_DRR_TABLE_WDATA1_ADDR \ + (WF_PLE_TOP_BASE + 0x454) /* 0454 */ +#define WF_PLE_TOP_DRR_TABLE_WDATA2_ADDR \ + (WF_PLE_TOP_BASE + 0x458) /* 0458 */ +#define WF_PLE_TOP_DRR_TABLE_WDATA3_ADDR \ + (WF_PLE_TOP_BASE + 0x45c) /* 045C */ +#define WF_PLE_TOP_DRR_TABLE_WDATA4_ADDR \ + (WF_PLE_TOP_BASE + 0x460) /* 0460 */ +#define WF_PLE_TOP_DRR_TABLE_WDATA5_ADDR \ + (WF_PLE_TOP_BASE + 0x464) /* 0464 */ +#define WF_PLE_TOP_DRR_TABLE_WDATA6_ADDR \ + (WF_PLE_TOP_BASE + 0x468) /* 0468 */ +#define WF_PLE_TOP_DRR_TABLE_WDATA7_ADDR \ + (WF_PLE_TOP_BASE + 0x46c) /* 046C */ +#define WF_PLE_TOP_DRR_TABLE_RDATA0_ADDR \ + (WF_PLE_TOP_BASE + 0x470) /* 0470 */ +#define WF_PLE_TOP_DRR_TABLE_RDATA1_ADDR \ + (WF_PLE_TOP_BASE + 0x474) /* 0474 */ +#define WF_PLE_TOP_DRR_TABLE_RDATA2_ADDR \ + (WF_PLE_TOP_BASE + 0x478) /* 0478 */ +#define WF_PLE_TOP_DRR_TABLE_RDATA3_ADDR \ + (WF_PLE_TOP_BASE + 0x47c) /* 047C */ +#define WF_PLE_TOP_DRR_TABLE_RDATA4_ADDR \ + (WF_PLE_TOP_BASE + 0x480) /* 0480 */ +#define WF_PLE_TOP_DRR_TABLE_RDATA5_ADDR \ + (WF_PLE_TOP_BASE + 0x484) /* 0484 */ +#define WF_PLE_TOP_DRR_TABLE_RDATA6_ADDR \ + (WF_PLE_TOP_BASE + 0x488) /* 0488 */ +#define WF_PLE_TOP_DRR_TABLE_RDATA7_ADDR \ + (WF_PLE_TOP_BASE + 0x48c) /* 048C */ +#define WF_PLE_TOP_DRR_TABLE_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x490) /* 0490 */ +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_ADDR \ + (WF_PLE_TOP_BASE + 0x494) /* 0494 */ +#define WF_PLE_TOP_CHECK_BW_TIME_TOKEN__ADDR \ + (WF_PLE_TOP_BASE + 0x498) /* 0498 */ +#define WF_PLE_TOP_CHECK_BW_LENGTH_TOKEN__ADDR \ + (WF_PLE_TOP_BASE + 0x49c) /* 049C */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_ADDR \ + (WF_PLE_TOP_BASE + 0x4a0) /* 04A0 */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_ADDR \ + (WF_PLE_TOP_BASE + 0x4a4)/* 04A4 */ +#define WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_ADDR \ + (WF_PLE_TOP_BASE + 0x4c0) /* 04C0 */ +#define WF_PLE_TOP_TWT_DBG_ADDR \ + (WF_PLE_TOP_BASE + 0x4d0) /* 04D0 */ +#define WF_PLE_TOP_VOW_DBG_SEL_ADDR \ + (WF_PLE_TOP_BASE + 0x4d4) /* 04D4 */ +#define WF_PLE_TOP_AIRTIME_DBG_INFO0_ADDR \ + (WF_PLE_TOP_BASE + 0x4d8) /* 04D8 */ +#define WF_PLE_TOP_AIRTIME_DBG_INFO1_ADDR \ + (WF_PLE_TOP_BASE + 0x4dc) /* 04DC */ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY0_ADDR \ + (WF_PLE_TOP_BASE + 0x500) /* 0500 */ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY1_ADDR \ + (WF_PLE_TOP_BASE + 0x504) /* 0504 */ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY0_ADDR \ + (WF_PLE_TOP_BASE + 0x540) /* 0540 */ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY1_ADDR \ + (WF_PLE_TOP_BASE + 0x544) /* 0544 */ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY0_ADDR \ + (WF_PLE_TOP_BASE + 0x580) /* 0580 */ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY1_ADDR \ + (WF_PLE_TOP_BASE + 0x584) /* 0584 */ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY0_ADDR \ + (WF_PLE_TOP_BASE + 0x5c0) /* 05C0 */ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY1_ADDR \ + (WF_PLE_TOP_BASE + 0x5c4) /* 05C4 */ +#define WF_PLE_TOP_PEEK_CR_00_ADDR \ + (WF_PLE_TOP_BASE + 0x600) /* 0600 */ +#define WF_PLE_TOP_PEEK_CR_01_ADDR \ + (WF_PLE_TOP_BASE + 0x604) /* 0604 */ +#define WF_PLE_TOP_PEEK_CR_02_ADDR \ + (WF_PLE_TOP_BASE + 0x608) /* 0608 */ +#define WF_PLE_TOP_PEEK_CR_03_ADDR \ + (WF_PLE_TOP_BASE + 0x60C) /* 060C */ +#define WF_PLE_TOP_PEEK_CR_04_ADDR \ + (WF_PLE_TOP_BASE + 0x610) /* 0610 */ +#define WF_PLE_TOP_PEEK_CR_05_ADDR \ + (WF_PLE_TOP_BASE + 0x614) /* 0614 */ +#define WF_PLE_TOP_PEEK_CR_06_ADDR \ + (WF_PLE_TOP_BASE + 0x618) /* 0618 */ +#define WF_PLE_TOP_PEEK_CR_07_ADDR \ + (WF_PLE_TOP_BASE + 0x61c) /* 061C */ +#define WF_PLE_TOP_PEEK_CR_08_ADDR \ + (WF_PLE_TOP_BASE + 0x620) /* 0620 */ +#define WF_PLE_TOP_PEEK_CR_09_ADDR \ + (WF_PLE_TOP_BASE + 0x624) /* 0624 */ +#define WF_PLE_TOP_PEEK_CR_10_ADDR \ + (WF_PLE_TOP_BASE + 0x628) /* 0628 */ +#define WF_PLE_TOP_PEEK_CR_11_ADDR \ + (WF_PLE_TOP_BASE + 0x62c) /* 062C */ +#define WF_PLE_TOP_AMSDU_GC_ADDR \ + (WF_PLE_TOP_BASE + 0x1000) /* 1000 */ +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_ADDR \ + (WF_PLE_TOP_BASE + 0x1004) /* 1004 */ +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_1_ADDR \ + (WF_PLE_TOP_BASE + 0x1008) /* 1008 */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_ADDR \ + (WF_PLE_TOP_BASE + 0x100c) /* 100C */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_ADDR \ + (WF_PLE_TOP_BASE + 0x1010) /* 1010 */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_ADDR \ + (WF_PLE_TOP_BASE + 0x10d0) /* 10D0 */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_ADDR \ + (WF_PLE_TOP_BASE + 0x10d4) /* 10D4 */ +#define WF_PLE_TOP_AMSDU_PACK_1_MSDU_CNT_ADDR \ + (WF_PLE_TOP_BASE + 0x10e0) /* 10E0 */ +#define WF_PLE_TOP_AMSDU_PACK_2_MSDU_CNT_ADDR \ + (WF_PLE_TOP_BASE + 0x10e4) /* 10E4 */ +#define WF_PLE_TOP_AMSDU_PACK_3_MSDU_CNT_ADDR \ + (WF_PLE_TOP_BASE + 0x10e8) /* 10E8 */ +#define WF_PLE_TOP_AMSDU_PACK_4_MSDU_CNT_ADDR \ + (WF_PLE_TOP_BASE + 0x10ec) /* 10EC */ +#define WF_PLE_TOP_AMSDU_PACK_5_MSDU_CNT_ADDR \ + (WF_PLE_TOP_BASE + 0x10f0) /* 10F0 */ +#define WF_PLE_TOP_AMSDU_PACK_6_MSDU_CNT_ADDR \ + (WF_PLE_TOP_BASE + 0x10f4) /* 10F4 */ +#define WF_PLE_TOP_AMSDU_PACK_7_MSDU_CNT_ADDR \ + (WF_PLE_TOP_BASE + 0x10f8) /* 10F8 */ +#define WF_PLE_TOP_AMSDU_PACK_8_MSDU_CNT_ADDR \ + (WF_PLE_TOP_BASE + 0x10fc) /* 10FC */ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY0_ADDR \ + (WF_PLE_TOP_BASE + 0x1100) /* 1100 */ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY1_ADDR \ + (WF_PLE_TOP_BASE + 0x1104) /* 1104 */ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY0_ADDR \ + (WF_PLE_TOP_BASE + 0x1140) /* 1140 */ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY1_ADDR \ + (WF_PLE_TOP_BASE + 0x1144) /* 1144 */ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY0_ADDR \ + (WF_PLE_TOP_BASE + 0x1180) /* 1180 */ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY1_ADDR \ + (WF_PLE_TOP_BASE + 0x1184) /* 1184 */ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY0_ADDR \ + (WF_PLE_TOP_BASE + 0x11C0) /* 11C0 */ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY1_ADDR \ + (WF_PLE_TOP_BASE + 0x11C4) /* 11C4 */ +#define WF_PLE_TOP_CFG_DBDC_CTRL0_ADDR (WF_PLE_TOP_BASE + 0x2008) /* 2008 */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR \ + (WF_PLE_TOP_BASE + 0x2480) /* 2480 */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_ADDR \ + (WF_PLE_TOP_BASE + 0x2484) /* 2484 */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_2_ADDR \ + (WF_PLE_TOP_BASE + 0x2488) /* 2488 */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_3_ADDR \ + (WF_PLE_TOP_BASE + 0x248c) /* 248C */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_4_ADDR \ + (WF_PLE_TOP_BASE + 0x2490) /* 2490 */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_ADDR \ + (WF_PLE_TOP_BASE + 0x2494) /* 2494 */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_6_ADDR \ + (WF_PLE_TOP_BASE + 0x2498) /* 2498 */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_ADDR \ + (WF_PLE_TOP_BASE + 0x25c0) /* 25C0 */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_ADDR \ + (WF_PLE_TOP_BASE + 0x25c4) /* 25C4 */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_2_ADDR \ + (WF_PLE_TOP_BASE + 0x25c8) /* 25C8 */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_3_ADDR \ + (WF_PLE_TOP_BASE + 0x25cc) /* 25CC */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR \ + (WF_PLE_TOP_BASE + 0x25e0) /* 25E0 */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_ADDR \ + (WF_PLE_TOP_BASE + 0x25e4) /* 25E4 */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_2_ADDR \ + (WF_PLE_TOP_BASE + 0x25e8) /* 25E8 */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_3_ADDR \ + (WF_PLE_TOP_BASE + 0x25ec) /* 25EC */ +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x3004) /* 3004 */ +#define WF_PLE_TOP_SYSRAM_MBIST_DEBUG_ADDR \ + (WF_PLE_TOP_BASE + 0x3008) /* 3008 */ +#define WF_PLE_TOP_SYSRAM_MBIST_MODE_ADDR \ + (WF_PLE_TOP_BASE + 0x300C) /* 300C */ +#define WF_PLE_TOP_SYSRAM_MBIST_HOLDB_ADDR \ + (WF_PLE_TOP_BASE + 0x3010) /* 3010 */ +#define WF_PLE_TOP_SYSRAM_MBIST_DONE_ADDR \ + (WF_PLE_TOP_BASE + 0x3014) /* 3014 */ +#define WF_PLE_TOP_SYSRAM_MBIST_FAIL_ADDR \ + (WF_PLE_TOP_BASE + 0x3018) /* 3018 */ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_TEST_ADDR \ + (WF_PLE_TOP_BASE + 0x301C) /* 301C */ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_INV_ADDR \ + (WF_PLE_TOP_BASE + 0x3020) /* 3020 */ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_W_ADDR \ + (WF_PLE_TOP_BASE + 0x3024) /* 3024 */ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_R_ADDR \ + (WF_PLE_TOP_BASE + 0x3028) /* 3028 */ +#define WF_PLE_TOP_SYSRAM_AWT_HDEN_ADDR \ + (WF_PLE_TOP_BASE + 0x302C) /* 302C */ +#define WF_PLE_TOP_SYSRAM_DBG_SEL_ADDR \ + (WF_PLE_TOP_BASE + 0x3030) /* 3030 */ +#define WF_PLE_TOP_SYSRAM_DELSEL_ADDR \ + (WF_PLE_TOP_BASE + 0x3070) /* 3070 */ +#define WF_PLE_TOP_SYSRAM_DELSEL_1_ADDR \ + (WF_PLE_TOP_BASE + 0x3074) /* 3074 */ +#define WF_PLE_TOP_SYSRAM_DELSEL_2_ADDR \ + (WF_PLE_TOP_BASE + 0x3078) /* 3078 */ +#define WF_PLE_TOP_SYSRAM_DELSEL_3_ADDR \ + (WF_PLE_TOP_BASE + 0x307C) /* 307C */ +#define WF_PLE_TOP_SYSRAM_OUTRAN_ERR_FLAG_ADDR \ + (WF_PLE_TOP_BASE + 0x3080) /* 3080 */ + +/* +* ---GC (0x820C0000 + 0x00)--- +* ALL_RESET[0] - (RW) Resets PLE logic and register +* LOGIC_RESET[1] - (RW) Resets PLE logic circuit +* INIT_DONE[2] - (RO) PLE control SRAM initialization +indicator +* UMAC_CFG_LOGIC_RESET[3] - (RW) Resets PF/MDP/SEC/UWTBL logic circuit +* RESERVED4[15..4] - (RO) Reserved bits +* SRAM_MBIST_G1_RESET[16] - (RW) Reset control of group 1 SRAM MBIST +* SRAM_MBIST_G2_RESET[17] - (RW) Reset control of group 2 SRAM MBIST +* DIS_PLE_DYN_CKG[18] - (RW) Disable control of wf_ple_top dynamic +* clock gating function +* RESERVED19[31..19] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_GC_DIS_PLE_DYN_CKG_ADDR WF_PLE_TOP_GC_ADDR +#define WF_PLE_TOP_GC_DIS_PLE_DYN_CKG_MASK 0x00040000 /* DIS_PLE_DYN_CKG[18] */ +#define WF_PLE_TOP_GC_DIS_PLE_DYN_CKG_SHFT 18 +#define WF_PLE_TOP_GC_SRAM_MBIST_G2_RESET_ADDR WF_PLE_TOP_GC_ADDR +#define WF_PLE_TOP_GC_SRAM_MBIST_G2_RESET_MASK \ + 0x00020000 /* SRAM_MBIST_G2_RESET[17] */ +#define WF_PLE_TOP_GC_SRAM_MBIST_G2_RESET_SHFT 17 +#define WF_PLE_TOP_GC_SRAM_MBIST_G1_RESET_ADDR WF_PLE_TOP_GC_ADDR +#define WF_PLE_TOP_GC_SRAM_MBIST_G1_RESET_MASK \ + 0x00010000 /* SRAM_MBIST_G1_RESET[16] */ +#define WF_PLE_TOP_GC_SRAM_MBIST_G1_RESET_SHFT 16 +#define WF_PLE_TOP_GC_UMAC_CFG_LOGIC_RESET_ADDR WF_PLE_TOP_GC_ADDR +#define WF_PLE_TOP_GC_UMAC_CFG_LOGIC_RESET_MASK \ + 0x00000008 /* UMAC_CFG_LOGIC_RESET[3] */ +#define WF_PLE_TOP_GC_UMAC_CFG_LOGIC_RESET_SHFT 3 +#define WF_PLE_TOP_GC_INIT_DONE_ADDR WF_PLE_TOP_GC_ADDR +#define WF_PLE_TOP_GC_INIT_DONE_MASK 0x00000004 /* INIT_DONE[2] */ +#define WF_PLE_TOP_GC_INIT_DONE_SHFT 2 +#define WF_PLE_TOP_GC_LOGIC_RESET_ADDR WF_PLE_TOP_GC_ADDR +#define WF_PLE_TOP_GC_LOGIC_RESET_MASK 0x00000002 /* LOGIC_RESET[1] */ +#define WF_PLE_TOP_GC_LOGIC_RESET_SHFT 1 +#define WF_PLE_TOP_GC_ALL_RESET_ADDR WF_PLE_TOP_GC_ADDR +#define WF_PLE_TOP_GC_ALL_RESET_MASK 0x00000001 /* ALL_RESET[0] */ +#define WF_PLE_TOP_GC_ALL_RESET_SHFT 0 + +/* +* ---PBUF_CTRL (0x820C0000 + 0x04)--- +* TOTAL_PAGE_NUM[11..0] - (RW) Total page number +* Set the total page before release PLE logic +* reset, and must not be changed after release logic reset. +* RESERVED12[16..12] - (RO) Reserved bits +* PBUF_OFFSET[25..17] - (RW) Packet buffer offset +* Set up the buffer offset before releasing +* PLE logic reset; it should not be changed after logic reset is released. +* RESERVED26[30..26] - (RO) Reserved bits +* PAGE_SIZE_CFG[31] - (RW) Configures page size +* Set up the page size before releasing PLE +* logic reset; it should not be changed after logic reset is released. +*/ +#define WF_PLE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_ADDR WF_PLE_TOP_PBUF_CTRL_ADDR +#define WF_PLE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_MASK \ + 0x80000000 /* PAGE_SIZE_CFG[31] */ +#define WF_PLE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_SHFT 31 +#define WF_PLE_TOP_PBUF_CTRL_PBUF_OFFSET_ADDR WF_PLE_TOP_PBUF_CTRL_ADDR +#define WF_PLE_TOP_PBUF_CTRL_PBUF_OFFSET_MASK \ + 0x03FE0000 /* PBUF_OFFSET[25..17] */ +#define WF_PLE_TOP_PBUF_CTRL_PBUF_OFFSET_SHFT 17 +#define WF_PLE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_ADDR WF_PLE_TOP_PBUF_CTRL_ADDR +#define WF_PLE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_MASK \ + 0x00000FFF /* TOTAL_PAGE_NUM[11..0] */ +#define WF_PLE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_SHFT 0 + +/* +* ---FREEPG_START_END (0x820C0000 + 0x08)--- +* FREEPG_START[11..0] - (RW) Start page for free page list +* Set start page before release PLE logic +* reset, and must not be changed after release logic reset. +* RESERVED12[15..12] - (RO) Reserved bits +* FREEPG_END[27..16] - (RW) End page for free page list +* Set end page before release PLE logic +* reset, and must not be changed after release logic reset. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FREEPG_START_END_FREEPG_END_ADDR \ + WF_PLE_TOP_FREEPG_START_END_ADDR +#define WF_PLE_TOP_FREEPG_START_END_FREEPG_END_MASK \ + 0x0FFF0000 /* FREEPG_END[27..16] */ +#define WF_PLE_TOP_FREEPG_START_END_FREEPG_END_SHFT 16 +#define WF_PLE_TOP_FREEPG_START_END_FREEPG_START_ADDR \ + WF_PLE_TOP_FREEPG_START_END_ADDR +#define WF_PLE_TOP_FREEPG_START_END_FREEPG_START_MASK \ + 0x00000FFF /* FREEPG_START[11..0] */ +#define WF_PLE_TOP_FREEPG_START_END_FREEPG_START_SHFT 0 + +/* +* ---PG_HIF_GROUP (0x820C0000 + 0x0c)--- +* HIF_MIN_QUOTA[11..0] - (RW) Min. quota of HIF group +* Set the quota before release PLE logic +* reset ,and must not be changed after release logic reset. +* RESERVED12[15..12] - (RO) Reserved bits +* HIF_MAX_QUOTA[27..16] - (RW) Max. quota of HIF group +* Set up the quota before releasing PLE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PG_HIF_GROUP_HIF_MAX_QUOTA_ADDR WF_PLE_TOP_PG_HIF_GROUP_ADDR +#define WF_PLE_TOP_PG_HIF_GROUP_HIF_MAX_QUOTA_MASK \ + 0x0FFF0000 /* HIF_MAX_QUOTA[27..16] */ +#define WF_PLE_TOP_PG_HIF_GROUP_HIF_MAX_QUOTA_SHFT 16 +#define WF_PLE_TOP_PG_HIF_GROUP_HIF_MIN_QUOTA_ADDR WF_PLE_TOP_PG_HIF_GROUP_ADDR +#define WF_PLE_TOP_PG_HIF_GROUP_HIF_MIN_QUOTA_MASK \ + 0x00000FFF /* HIF_MIN_QUOTA[11..0] */ +#define WF_PLE_TOP_PG_HIF_GROUP_HIF_MIN_QUOTA_SHFT 0 + +/* +* ---PG_HIF_WMTXD_GROUP (0x820C0000 + 0x10)--- +* HIF_WMTXD_MIN_QUOTA[11..0] - (RW) Min. quota of HIF WMCPU TXD group +* Set the quota before release PLE logic +* reset ,and must not be changed after release logic reset. +* RESERVED12[15..12] - (RO) Reserved bits +* HIF_WMTXD_MAX_QUOTA[27..16] - (RW) Max. quota of HIF WMCPU TXD group +* Set up the quota before releasing PLE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PG_HIF_WMTXD_GROUP_HIF_WMTXD_MAX_QUOTA_ADDR \ + WF_PLE_TOP_PG_HIF_WMTXD_GROUP_ADDR +#define WF_PLE_TOP_PG_HIF_WMTXD_GROUP_HIF_WMTXD_MAX_QUOTA_MASK \ + 0x0FFF0000 /* HIF_WMTXD_MAX_QUOTA[27..16] */ +#define WF_PLE_TOP_PG_HIF_WMTXD_GROUP_HIF_WMTXD_MAX_QUOTA_SHFT 16 +#define WF_PLE_TOP_PG_HIF_WMTXD_GROUP_HIF_WMTXD_MIN_QUOTA_ADDR \ + WF_PLE_TOP_PG_HIF_WMTXD_GROUP_ADDR +#define WF_PLE_TOP_PG_HIF_WMTXD_GROUP_HIF_WMTXD_MIN_QUOTA_MASK \ + 0x00000FFF /* HIF_WMTXD_MIN_QUOTA[11..0] */ +#define WF_PLE_TOP_PG_HIF_WMTXD_GROUP_HIF_WMTXD_MIN_QUOTA_SHFT 0 + +/* +* ---PG_HIF_TXCMD_GROUP (0x820C0000 + 0x14)--- +* HIF_TXCMD_MIN_QUOTA[11..0] - (RW) Min. quota of HIF TXCMD group +* Set the quota before release PLE logic +* reset ,and must not be changed after release logic reset. +* RESERVED12[15..12] - (RO) Reserved bits +* HIF_TXCMD_MAX_QUOTA[27..16] - (RW) Max. quota of HIF TXCMD group +* Set up the quota before releasing PLE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MAX_QUOTA_ADDR \ + WF_PLE_TOP_PG_HIF_TXCMD_GROUP_ADDR +#define WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MAX_QUOTA_MASK \ + 0x0FFF0000 /* HIF_TXCMD_MAX_QUOTA[27..16] */ +#define WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MAX_QUOTA_SHFT 16 +#define WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MIN_QUOTA_ADDR \ + WF_PLE_TOP_PG_HIF_TXCMD_GROUP_ADDR +#define WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MIN_QUOTA_MASK \ + 0x00000FFF /* HIF_TXCMD_MIN_QUOTA[11..0] */ +#define WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MIN_QUOTA_SHFT 0 + +/* +* ---PG_CPU_GROUP (0x820C0000 + 0x18)--- +* CPU_MIN_QUOTA[11..0] - (RW) Min. quota of CPU group +* Set up the quota before releasing PLE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* CPU_MAX_QUOTA[27..16] - (RW) Max. quota of CPU group +* Set up the quota before releasing PLE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PG_CPU_GROUP_CPU_MAX_QUOTA_ADDR WF_PLE_TOP_PG_CPU_GROUP_ADDR +#define WF_PLE_TOP_PG_CPU_GROUP_CPU_MAX_QUOTA_MASK \ + 0x0FFF0000 /* CPU_MAX_QUOTA[27..16] */ +#define WF_PLE_TOP_PG_CPU_GROUP_CPU_MAX_QUOTA_SHFT 16 +#define WF_PLE_TOP_PG_CPU_GROUP_CPU_MIN_QUOTA_ADDR WF_PLE_TOP_PG_CPU_GROUP_ADDR +#define WF_PLE_TOP_PG_CPU_GROUP_CPU_MIN_QUOTA_MASK \ + 0x00000FFF /* CPU_MIN_QUOTA[11..0] */ +#define WF_PLE_TOP_PG_CPU_GROUP_CPU_MIN_QUOTA_SHFT 0 + +/* +* ---VOW_CONTROL (0x820C0000 + 0x1c)--- +* PER_BSS_BW_CONTROL_ENABLE[15..0] - (RW) BW control of BSSID +* REFILL_PERIOD[18..16] - (RW) Period of token refill function +* RESERVED19[19] - (RO) Reserved bits +* DBDC1_SEARCH_RULE[20] - (RW) Priority for HW search if internal +* collision occurs +* DBDC0_SEARCH_RULE[21] - (RW) Priority for HW search if internal +* collision occcurs +* RESERVED22[25..22] - (RO) Reserved bits +* DRR_LOGIC_RESET[26] - (RW) DRR logic reset control +* DIS_WTBL_PS_IGNORE[27] - (RW) Disable control of the function that STA +* with WTBL PS ignore in TXQ busy +* ENABLE_TXOP_NO_CHANGE_BSS_GROUP[28] - (RW) HW cannot change BW group In TXOP +burst. +* ENABLE_AIRTIME_FAIRNESS[29] - (RW) When airtime function is disabled, HW +* will change station without checking station qouta. +* ENABLE_TOKEN_REFILL[30] - (RW) Enable control of token refill function +* ENABLE_BW_CONTROL[31] - (RW) HW will check if there are tokens in BW +* bucket before TX. +*/ +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_BW_CONTROL_ADDR \ + WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_BW_CONTROL_MASK \ + 0x80000000 /* ENABLE_BW_CONTROL[31] */ +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_BW_CONTROL_SHFT 31 +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_TOKEN_REFILL_ADDR \ + WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_TOKEN_REFILL_MASK \ + 0x40000000 /* ENABLE_TOKEN_REFILL[30] */ +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_TOKEN_REFILL_SHFT 30 +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_AIRTIME_FAIRNESS_ADDR \ + WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_AIRTIME_FAIRNESS_MASK \ + 0x20000000 /* ENABLE_AIRTIME_FAIRNESS[29] */ +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_AIRTIME_FAIRNESS_SHFT 29 +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_TXOP_NO_CHANGE_BSS_GROUP_ADDR \ + WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_TXOP_NO_CHANGE_BSS_GROUP_MASK \ + 0x10000000 /* ENABLE_TXOP_NO_CHANGE_BSS_GROUP[28] */ +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_TXOP_NO_CHANGE_BSS_GROUP_SHFT 28 +#define WF_PLE_TOP_VOW_CONTROL_DIS_WTBL_PS_IGNORE_ADDR \ + WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_DIS_WTBL_PS_IGNORE_MASK \ + 0x08000000 /* DIS_WTBL_PS_IGNORE[27] */ +#define WF_PLE_TOP_VOW_CONTROL_DIS_WTBL_PS_IGNORE_SHFT 27 +#define WF_PLE_TOP_VOW_CONTROL_DRR_LOGIC_RESET_ADDR WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_DRR_LOGIC_RESET_MASK \ + 0x04000000 /* DRR_LOGIC_RESET[26] */ +#define WF_PLE_TOP_VOW_CONTROL_DRR_LOGIC_RESET_SHFT 26 +#define WF_PLE_TOP_VOW_CONTROL_DBDC0_SEARCH_RULE_ADDR \ + WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_DBDC0_SEARCH_RULE_MASK \ + 0x00200000 /* DBDC0_SEARCH_RULE[21] */ +#define WF_PLE_TOP_VOW_CONTROL_DBDC0_SEARCH_RULE_SHFT 21 +#define WF_PLE_TOP_VOW_CONTROL_DBDC1_SEARCH_RULE_ADDR \ + WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_DBDC1_SEARCH_RULE_MASK \ + 0x00100000 /* DBDC1_SEARCH_RULE[20] */ +#define WF_PLE_TOP_VOW_CONTROL_DBDC1_SEARCH_RULE_SHFT 20 +#define WF_PLE_TOP_VOW_CONTROL_REFILL_PERIOD_ADDR WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_REFILL_PERIOD_MASK \ + 0x00070000 /* REFILL_PERIOD[18..16] */ +#define WF_PLE_TOP_VOW_CONTROL_REFILL_PERIOD_SHFT 16 +#define WF_PLE_TOP_VOW_CONTROL_PER_BSS_BW_CONTROL_ENABLE_ADDR \ + WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_PER_BSS_BW_CONTROL_ENABLE_MASK \ + 0x0000FFFF /* PER_BSS_BW_CONTROL_ENABLE[15..0] */ +#define WF_PLE_TOP_VOW_CONTROL_PER_BSS_BW_CONTROL_ENABLE_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL1 (0x820C0000 + 0x20)--- +* SRAM1_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM1 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL1_SRAM1_MBIST_DELSEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_DELSEL1_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL1_SRAM1_MBIST_DELSEL_MASK \ + 0xFFFFFFFF /* SRAM1_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL1_SRAM1_MBIST_DELSEL_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL2 (0x820C0000 + 0x24)--- +* SRAM2_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM2 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL2_SRAM2_MBIST_DELSEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_DELSEL2_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL2_SRAM2_MBIST_DELSEL_MASK \ + 0xFFFFFFFF /* SRAM2_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL2_SRAM2_MBIST_DELSEL_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL3 (0x820C0000 + 0x28)--- +* SRAM3_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM3 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL3_SRAM3_MBIST_DELSEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_DELSEL3_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL3_SRAM3_MBIST_DELSEL_MASK \ + 0xFFFFFFFF /* SRAM3_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL3_SRAM3_MBIST_DELSEL_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL4 (0x820C0000 + 0x2c)--- +* SRAM4_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM4 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL4_SRAM4_MBIST_DELSEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_DELSEL4_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL4_SRAM4_MBIST_DELSEL_MASK \ + 0xFFFFFFFF /* SRAM4_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL4_SRAM4_MBIST_DELSEL_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL5 (0x820C0000 + 0x30)--- +* SRAM5_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM5 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL5_SRAM5_MBIST_DELSEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_DELSEL5_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL5_SRAM5_MBIST_DELSEL_MASK \ + 0xFFFFFFFF /* SRAM5_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL5_SRAM5_MBIST_DELSEL_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL6 (0x820C0000 + 0x34)--- +* SRAM6_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM6 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL6_SRAM6_MBIST_DELSEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_DELSEL6_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL6_SRAM6_MBIST_DELSEL_MASK \ + 0xFFFFFFFF /* SRAM6_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL6_SRAM6_MBIST_DELSEL_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL7 (0x820C0000 + 0x38)--- +* SRAM7_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM7 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL7_SRAM7_MBIST_DELSEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_DELSEL7_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL7_SRAM7_MBIST_DELSEL_MASK \ + 0xFFFFFFFF /* SRAM7_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL7_SRAM7_MBIST_DELSEL_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL8 (0x820C0000 + 0x3c)--- +* SRAM8_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM8 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL8_SRAM8_MBIST_DELSEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_DELSEL8_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL8_SRAM8_MBIST_DELSEL_MASK \ + 0xFFFFFFFF /* SRAM8_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL8_SRAM8_MBIST_DELSEL_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL9 (0x820C0000 + 0x40)--- +* SRAM9_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM9 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL9_SRAM9_MBIST_DELSEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_DELSEL9_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL9_SRAM9_MBIST_DELSEL_MASK \ + 0xFFFFFFFF /* SRAM9_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL9_SRAM9_MBIST_DELSEL_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL10 (0x820C0000 + 0x44)--- +* SRAM10_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM10 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL10_SRAM10_MBIST_DELSEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_DELSEL10_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL10_SRAM10_MBIST_DELSEL_MASK \ + 0xFFFFFFFF /* SRAM10_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL10_SRAM10_MBIST_DELSEL_SHFT 0 + +/* +* ---SRAM_MBIST_CTRL (0x820C0000 + 0x48)--- +* G1_MBIST_MODE[0] - (RW) Control register for mbist_mode of group +* 1 MBIST +* G2_MBIST_MODE[1] - (RW) Control register for mbist_mode of group +* 2 MBIST +* RESERVED2[3..2] - (RO) Reserved bits +* G1_MBIST_HOLDB[4] - (RW) Control register for mbist_holdb of +* group 1 MBIST +* G2_MBIST_HOLDB[5] - (RW) Control register for mbist_holdb of +* group 2 MBIST +* RESERVED6[7..6] - (RO) Reserved bits +* G1_MBIST_DEBUG[8] - (RW) Control register for mbist_debug of +* group 1 MBIST +* G2_MBIST_DEBUG[9] - (RW) Control register for mbist_debug of +* group 2 MBIST +* G1_MBIST_USE_DEFAULT_DELSEL[10] - (RW) Control register for default DELSEL +* value of group 1 memory +* G2_MBIST_USE_DEFAULT_DELSEL[11] - (RW) Control register for default DELSEL +* value of group 2 memory +* MBIST_DIAG_SEL[16..12] - (RW) Selection register for +mbist_diag_scan_out +* RESERVED17[19..17] - (RO) Reserved bits +* UMAC_MBIST_DIAG_SEL[20] - (RW) Selection register for UMAC +* mbist_diag_scan_out (PLE or PSE) +* RESERVED21[23..21] - (RO) Reserved bits +* G1_MBIST_SLEEP_TEST[24] - (RW) Control register for sleep_test of group +* 1 MBIST +* G1_MBIST_SLEEP_INV[25] - (RW) Control register for sleep_inv of group +* 1 MBIST +* G1_MBIST_SLEEP_W[26] - (RW) Control register for sleep_w of group 1 +MBIST +* G1_MBIST_SLEEP_R[27] - (RW) Control register for sleep_r of group 1 +MBIST +* G2_MBIST_SLEEP_TEST[28] - (RW) Control register for sleep_test of group +* 2 MBIST +* G2_MBIST_SLEEP_INV[29] - (RW) Control register for sleep_inv of group +* 2 MBIST +* G2_MBIST_SLEEP_W[30] - (RW) Control register for sleep_w of group 2 +MBIST +* G2_MBIST_SLEEP_R[31] - (RW) Control register for sleep_r of group 2 +MBIST +*/ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_R_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_R_MASK \ + 0x80000000 /* G2_MBIST_SLEEP_R[31] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_R_SHFT 31 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_W_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_W_MASK \ + 0x40000000 /* G2_MBIST_SLEEP_W[30] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_W_SHFT 30 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_INV_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_INV_MASK \ + 0x20000000 /* G2_MBIST_SLEEP_INV[29] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_INV_SHFT 29 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_TEST_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_TEST_MASK \ + 0x10000000 /* G2_MBIST_SLEEP_TEST[28] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_TEST_SHFT 28 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_R_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_R_MASK \ + 0x08000000 /* G1_MBIST_SLEEP_R[27] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_R_SHFT 27 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_W_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_W_MASK \ + 0x04000000 /* G1_MBIST_SLEEP_W[26] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_W_SHFT 26 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_INV_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_INV_MASK \ + 0x02000000 /* G1_MBIST_SLEEP_INV[25] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_INV_SHFT 25 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_TEST_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_TEST_MASK \ + 0x01000000 /* G1_MBIST_SLEEP_TEST[24] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_TEST_SHFT 24 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_UMAC_MBIST_DIAG_SEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_UMAC_MBIST_DIAG_SEL_MASK \ + 0x00100000 /* UMAC_MBIST_DIAG_SEL[20] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_UMAC_MBIST_DIAG_SEL_SHFT 20 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_MBIST_DIAG_SEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_MBIST_DIAG_SEL_MASK \ + 0x0001F000 /* MBIST_DIAG_SEL[16..12] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_MBIST_DIAG_SEL_SHFT 12 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_USE_DEFAULT_DELSEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_USE_DEFAULT_DELSEL_MASK \ + 0x00000800 /* G2_MBIST_USE_DEFAULT_DELSEL[11] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_USE_DEFAULT_DELSEL_SHFT 11 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_USE_DEFAULT_DELSEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_USE_DEFAULT_DELSEL_MASK \ + 0x00000400 /* G1_MBIST_USE_DEFAULT_DELSEL[10] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_USE_DEFAULT_DELSEL_SHFT 10 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_DEBUG_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_DEBUG_MASK \ + 0x00000200 /* G2_MBIST_DEBUG[9] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_DEBUG_SHFT 9 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_DEBUG_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_DEBUG_MASK \ + 0x00000100 /* G1_MBIST_DEBUG[8] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_DEBUG_SHFT 8 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_HOLDB_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_HOLDB_MASK \ + 0x00000020 /* G2_MBIST_HOLDB[5] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_HOLDB_SHFT 5 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_HOLDB_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_HOLDB_MASK \ + 0x00000010 /* G1_MBIST_HOLDB[4] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_HOLDB_SHFT 4 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_MODE_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_MODE_MASK \ + 0x00000002 /* G2_MBIST_MODE[1] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_MODE_SHFT 1 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_MODE_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_MODE_MASK \ + 0x00000001 /* G1_MBIST_MODE[0] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_MODE_SHFT 0 + +/* +* ---INT_N9_EN_MASK (0x820C0000 + 0x80)--- +* EN_CPU_Q0_NE[0] - (RW) Enable control of interrupt for CPU +* queue 0 not empty +* EN_CPU_Q1_NE[1] - (RW) Enable control of interrupt for CPU +* queue 1 not empty +* EN_CPU_Q2_NE[2] - (RW) Enable control of interrupt for CPU +* queue 2 not empty +* EN_CPU_Q3_NE[3] - (RW) Enable control of interrupt for CPU +* queue 3 not empty +* RESERVED4[15..4] - (RO) Reserved bits +* EN_TOGGLE_INT[16] - (RW) Enable control of interrupt for data +* toggle of N9 toggle register (0xf0) +* RESERVED17[17] - (RO) Reserved bits +* EN_UMAC_SYSRAM_OUTRAN_ERROR_INT[18] - (RW) Enable control of interrupt for +* UMAC SYSRAM out range error +* RESERVED19[19] - (RO) Reserved bits +* EN_AC_NONEMPTY_INT[20] - (RW) Enable control of AC queue empty fail +interrupt +* EN_AC_EMPTY_INT[21] - (RW) Enable control of AC queue empty raise +interrupt +* EN_AC_ENQ_LMAC_INT[22] - (RW) Enable control of AC enqueue interrupt +* RESERVED23[23] - (RO) Reserved bits +* EN_DBDC0_NONEMPTY_INT[24] - (RW) Enable control of DBDC0 queue empty fail +interrupt +* EN_DBDC0_EMPTY_INT[25] - (RW) Enable control of DBDC0 queue empty +* raise interrupt +* EN_DBDC0_ENQ_LMAC_INT[26] - (RW) Enable control of DBDC0 enqueue +interrupt +* RESERVED27[27] - (RO) Reserved bits +* EN_DBDC1_NONEMPTY_INT[28] - (RW) Enable control of DBDC1 queue empty fail +interrupt +* EN_DBDC1_EMPTY_INT[29] - (RW) Enable control of DBDC1 queue empty +* raise interrupt +* EN_DBDC1_ENQ_LMAC_INT[30] - (RW) Enable control of DBDC1 enqueue +interrupt +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_ENQ_LMAC_INT_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_ENQ_LMAC_INT_MASK \ + 0x40000000 /* EN_DBDC1_ENQ_LMAC_INT[30] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_ENQ_LMAC_INT_SHFT 30 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_EMPTY_INT_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_EMPTY_INT_MASK \ + 0x20000000 /* EN_DBDC1_EMPTY_INT[29] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_EMPTY_INT_SHFT 29 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_NONEMPTY_INT_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_NONEMPTY_INT_MASK \ + 0x10000000 /* EN_DBDC1_NONEMPTY_INT[28] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_NONEMPTY_INT_SHFT 28 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_ENQ_LMAC_INT_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_ENQ_LMAC_INT_MASK \ + 0x04000000 /* EN_DBDC0_ENQ_LMAC_INT[26] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_ENQ_LMAC_INT_SHFT 26 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_EMPTY_INT_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_EMPTY_INT_MASK \ + 0x02000000 /* EN_DBDC0_EMPTY_INT[25] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_EMPTY_INT_SHFT 25 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_NONEMPTY_INT_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_NONEMPTY_INT_MASK \ + 0x01000000 /* EN_DBDC0_NONEMPTY_INT[24] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_NONEMPTY_INT_SHFT 24 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_ENQ_LMAC_INT_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_ENQ_LMAC_INT_MASK \ + 0x00400000 /* EN_AC_ENQ_LMAC_INT[22] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_ENQ_LMAC_INT_SHFT 22 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_EMPTY_INT_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_EMPTY_INT_MASK \ + 0x00200000 /* EN_AC_EMPTY_INT[21] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_EMPTY_INT_SHFT 21 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_NONEMPTY_INT_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_NONEMPTY_INT_MASK \ + 0x00100000 /* EN_AC_NONEMPTY_INT[20] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_NONEMPTY_INT_SHFT 20 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_UMAC_SYSRAM_OUTRAN_ERROR_INT_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_UMAC_SYSRAM_OUTRAN_ERROR_INT_MASK \ + 0x00040000 /* EN_UMAC_SYSRAM_OUTRAN_ERROR_INT[18] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_UMAC_SYSRAM_OUTRAN_ERROR_INT_SHFT 18 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_TOGGLE_INT_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_TOGGLE_INT_MASK \ + 0x00010000 /* EN_TOGGLE_INT[16] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_TOGGLE_INT_SHFT 16 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q3_NE_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q3_NE_MASK \ + 0x00000008 /* EN_CPU_Q3_NE[3] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q3_NE_SHFT 3 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q2_NE_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q2_NE_MASK \ + 0x00000004 /* EN_CPU_Q2_NE[2] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q2_NE_SHFT 2 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q1_NE_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q1_NE_MASK \ + 0x00000002 /* EN_CPU_Q1_NE[1] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q1_NE_SHFT 1 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q0_NE_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q0_NE_MASK \ + 0x00000001 /* EN_CPU_Q0_NE[0] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q0_NE_SHFT 0 + +/* +* ---INT_N9_ERR_MASK (0x820C0000 + 0x84)--- +* EN_Q_CMD_ERR_P0[0] - (RW) Enables queue command error interrupt +* status of port 0 +* EN_Q_CMD_ERR_P1[1] - (RW) Enables queue command error interrupt +* status of port 1 +* EN_Q_CMD_ERR_P2[2] - (RW) Enables queue command error interrupt +* status of port 2 +* EN_PAGE_UDF_P0[3] - (RW) Enables page underflow interrupt status +* of port 0 +* EN_PAGE_UDF_P1[4] - (RW) Enables page underflow interrupt status +* of port 1 +* EN_PAGE_UDF_P2[5] - (RW) Enables page underflow interrupt status +* of port 2 +* EN_DOUBLE_RLS_ERR[6] - (RW) Enable double release error interrupt. +* EN_MDP_D_OPER_ERR[7] - (RW) Enable MDP data operation error +interrupt. +* EN_MDP_HANG_ERR[8] - (RW) Enable MDP FSM hang error interrupt. +* RESERVED9[9] - (RO) Reserved bits +* EN_DATA_OPER_ERR_P0[10] - (RW) Enables data operation error of port 0 +* EN_DATA_OPER_ERR_P1[11] - (RW) Enables data operation error of port 1 +* EN_DATA_OPER_ERR_P2[12] - (RW) Enables data operation error of port 2 +* EN_FL_HANG_ERR[13] - (RW) Enables frame link FSM hang error +interrupt +* EN_PL_HANG_ERR[14] - (RW) Enables page link FSM hang error +interrupt +* EN_HIF_HANG_ERR[15] - (RW) Enables HIF port FSM hang error +interrupt +* EN_CPU_HANG_ERR[16] - (RW) Enables CPU port FSM hang error +interrupt +* EN_LMAC_HANG_ERR[17] - (RW) Enables LMAC port FSM hang error +interrupt +* EN_FREE_HEAD_TAIL_ERR[18] - (RW) Enable free head/tail error interrupt. +* EN_QSTRUCT_ERR[19] - (RW) Enable queue struct data error +interrupt. +* EN_BN0_MACTX_HANG_ERR[20] - (RW) Enable BN0 MACTX Ctrl FSM Hang error +interrupt. +* EN_BN1_MACTX_HANG_ERR[21] - (RW) Enable BN1 MACTX Ctrl FSM Hang error +interrupt. +* EN_BN0_TXCMD_HANG_ERR[22] - (RW) Enable BN0 TXCMD Ctrl FSM Hang error +interrupt. +* EN_BN1_TXCMD_HANG_ERR[23] - (RW) Enable BN1 TXCMD Ctrl FSM Hang error +interrupt. +* EN_DRR_SRCH_DBDC0_ERR[24] - (RW) Enable DRR DBDC0 sta search error +interrupt. +* EN_DRR_SRCH_DBDC1_ERR[25] - (RW) Enable DRR DBDC1 sta search error +interrupt. +* EN_DRR_FL_ERR[26] - (RW) Enable DRR forward link access error +interrupt. +* EN_DRR_BL_ERR[27] - (RW) Enable DRR backward link access error +interrupt. +* EN_DRR_RL_ERR[28] - (RW) Enable DRR relay link access error +interrupt. +* EN_DRR_CHRG_STA_ERR[29] - (RW) Enable DRR wlanid error when charge +interrupt. +* EN_DRR_STA_WLANID_ERR[30] - (RW) Enable DRR wlanid error when add/remove +* sta interrupt. +* EN_DRR_STA_WMMID_ERR[31] - (RW) Enable DRR wmmid error when add/remove +* sta interrupt. +*/ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_STA_WMMID_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_STA_WMMID_ERR_MASK \ + 0x80000000 /* EN_DRR_STA_WMMID_ERR[31] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_STA_WMMID_ERR_SHFT 31 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_STA_WLANID_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_STA_WLANID_ERR_MASK \ + 0x40000000 /* EN_DRR_STA_WLANID_ERR[30] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_STA_WLANID_ERR_SHFT 30 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_CHRG_STA_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_CHRG_STA_ERR_MASK \ + 0x20000000 /* EN_DRR_CHRG_STA_ERR[29] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_CHRG_STA_ERR_SHFT 29 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_RL_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_RL_ERR_MASK \ + 0x10000000 /* EN_DRR_RL_ERR[28] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_RL_ERR_SHFT 28 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_BL_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_BL_ERR_MASK \ + 0x08000000 /* EN_DRR_BL_ERR[27] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_BL_ERR_SHFT 27 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_FL_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_FL_ERR_MASK \ + 0x04000000 /* EN_DRR_FL_ERR[26] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_FL_ERR_SHFT 26 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_SRCH_DBDC1_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_SRCH_DBDC1_ERR_MASK \ + 0x02000000 /* EN_DRR_SRCH_DBDC1_ERR[25] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_SRCH_DBDC1_ERR_SHFT 25 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_SRCH_DBDC0_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_SRCH_DBDC0_ERR_MASK \ + 0x01000000 /* EN_DRR_SRCH_DBDC0_ERR[24] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_SRCH_DBDC0_ERR_SHFT 24 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN1_TXCMD_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN1_TXCMD_HANG_ERR_MASK \ + 0x00800000 /* EN_BN1_TXCMD_HANG_ERR[23] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN1_TXCMD_HANG_ERR_SHFT 23 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN0_TXCMD_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN0_TXCMD_HANG_ERR_MASK \ + 0x00400000 /* EN_BN0_TXCMD_HANG_ERR[22] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN0_TXCMD_HANG_ERR_SHFT 22 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN1_MACTX_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN1_MACTX_HANG_ERR_MASK \ + 0x00200000 /* EN_BN1_MACTX_HANG_ERR[21] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN1_MACTX_HANG_ERR_SHFT 21 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN0_MACTX_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN0_MACTX_HANG_ERR_MASK \ + 0x00100000 /* EN_BN0_MACTX_HANG_ERR[20] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN0_MACTX_HANG_ERR_SHFT 20 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_QSTRUCT_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_QSTRUCT_ERR_MASK \ + 0x00080000 /* EN_QSTRUCT_ERR[19] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_QSTRUCT_ERR_SHFT 19 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_FREE_HEAD_TAIL_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_FREE_HEAD_TAIL_ERR_MASK \ + 0x00040000 /* EN_FREE_HEAD_TAIL_ERR[18] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_FREE_HEAD_TAIL_ERR_SHFT 18 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_LMAC_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_LMAC_HANG_ERR_MASK \ + 0x00020000 /* EN_LMAC_HANG_ERR[17] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_LMAC_HANG_ERR_SHFT 17 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_CPU_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_CPU_HANG_ERR_MASK \ + 0x00010000 /* EN_CPU_HANG_ERR[16] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_CPU_HANG_ERR_SHFT 16 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_HIF_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_HIF_HANG_ERR_MASK \ + 0x00008000 /* EN_HIF_HANG_ERR[15] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_HIF_HANG_ERR_SHFT 15 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PL_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PL_HANG_ERR_MASK \ + 0x00004000 /* EN_PL_HANG_ERR[14] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PL_HANG_ERR_SHFT 14 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_FL_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_FL_HANG_ERR_MASK \ + 0x00002000 /* EN_FL_HANG_ERR[13] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_FL_HANG_ERR_SHFT 13 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P2_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P2_MASK \ + 0x00001000 /* EN_DATA_OPER_ERR_P2[12] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P2_SHFT 12 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P1_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P1_MASK \ + 0x00000800 /* EN_DATA_OPER_ERR_P1[11] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P1_SHFT 11 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P0_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P0_MASK \ + 0x00000400 /* EN_DATA_OPER_ERR_P0[10] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P0_SHFT 10 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_MDP_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_MDP_HANG_ERR_MASK \ + 0x00000100 /* EN_MDP_HANG_ERR[8] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_MDP_HANG_ERR_SHFT 8 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_MDP_D_OPER_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_MDP_D_OPER_ERR_MASK \ + 0x00000080 /* EN_MDP_D_OPER_ERR[7] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_MDP_D_OPER_ERR_SHFT 7 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DOUBLE_RLS_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DOUBLE_RLS_ERR_MASK \ + 0x00000040 /* EN_DOUBLE_RLS_ERR[6] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DOUBLE_RLS_ERR_SHFT 6 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P2_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P2_MASK \ + 0x00000020 /* EN_PAGE_UDF_P2[5] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P2_SHFT 5 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P1_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P1_MASK \ + 0x00000010 /* EN_PAGE_UDF_P1[4] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P1_SHFT 4 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P0_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P0_MASK \ + 0x00000008 /* EN_PAGE_UDF_P0[3] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P0_SHFT 3 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P2_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P2_MASK \ + 0x00000004 /* EN_Q_CMD_ERR_P2[2] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P2_SHFT 2 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P1_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P1_MASK \ + 0x00000002 /* EN_Q_CMD_ERR_P1[1] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P1_SHFT 1 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P0_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P0_MASK \ + 0x00000001 /* EN_Q_CMD_ERR_P0[0] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P0_SHFT 0 + +/* +* ---INT_N9_ERR_MASK_1 (0x820C0000 + 0x88)--- +* EN_BN0_MDP_TDP_HANG_ERR[0] - (RW) Enables Band0 MDP TDP FSM hang error +interrupt +* EN_MDP_RDP_HANG_ERR[1] - (RW) Enables MDP RDP FSM hang error interrupt +* EN_BN0_MDP_TIOC_HANG_ERR[2] - (RW) Enables Band0 MDP TIOC FSM hang error +interrupt +* EN_BN0_MDP_RIOC_HANG_ERR[3] - (RW) Enables Band0 MDP RIOC FSM hang error +interrupt +* EN_PF_HANG_ERR[4] - (RW) Enables PF FSM hang error interrupt +* EN_SEC0_HANG_ERR[5] - (RW) Enables SEC 0 FSM hang error interrupt +* EN_SEC1_HANG_ERR[6] - (RW) Enables SEC 1 FSM hang error interrupt +* EN_BN1_MDP_TDP_HANG_ERR[7] - (RW) Enables Band1 MDP TDP FSM hang error +interrupt +* EN_BN1_MDP_TIOC_HANG_ERR[8] - (RW) Enables Band1 MDP TIOC FSM hang error +interrupt +* EN_BN1_MDP_RIOC_HANG_ERR[9] - (RW) Enables Band1 MDP RIOC FSM hang error +interrupt +* RESERVED10[11..10] - (RO) Reserved bits +* EN_BN0_PREDL_ARB_HANG_ERR[12] - (RW) Enables Band0 PREDL ARB FSM hang error +interrupt +* EN_BN0_PREDL_TXCMD_HANG_ERR[13] - (RW) Enables Band0 PREDL TXCMD parser FSM +* hang error interrupt +* EN_BN1_PREDL_ARB_HANG_ERR[14] - (RW) Enables Band1 PREDL ARB FSM hang error +interrupt +* EN_BN1_PREDL_TXCMD_HANG_ERR[15] - (RW) Enables Band1 PREDL TXCMD parser FSM +* hang error interrupt +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_PREDL_TXCMD_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_PREDL_TXCMD_HANG_ERR_MASK \ + 0x00008000 /* EN_BN1_PREDL_TXCMD_HANG_ERR[15] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_PREDL_TXCMD_HANG_ERR_SHFT 15 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_PREDL_ARB_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_PREDL_ARB_HANG_ERR_MASK \ + 0x00004000 /* EN_BN1_PREDL_ARB_HANG_ERR[14] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_PREDL_ARB_HANG_ERR_SHFT 14 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_PREDL_TXCMD_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_PREDL_TXCMD_HANG_ERR_MASK \ + 0x00002000 /* EN_BN0_PREDL_TXCMD_HANG_ERR[13] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_PREDL_TXCMD_HANG_ERR_SHFT 13 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_PREDL_ARB_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_PREDL_ARB_HANG_ERR_MASK \ + 0x00001000 /* EN_BN0_PREDL_ARB_HANG_ERR[12] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_PREDL_ARB_HANG_ERR_SHFT 12 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_RIOC_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_RIOC_HANG_ERR_MASK \ + 0x00000200 /* EN_BN1_MDP_RIOC_HANG_ERR[9] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_RIOC_HANG_ERR_SHFT 9 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_TIOC_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_TIOC_HANG_ERR_MASK \ + 0x00000100 /* EN_BN1_MDP_TIOC_HANG_ERR[8] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_TIOC_HANG_ERR_SHFT 8 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_TDP_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_TDP_HANG_ERR_MASK \ + 0x00000080 /* EN_BN1_MDP_TDP_HANG_ERR[7] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_TDP_HANG_ERR_SHFT 7 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_SEC1_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_SEC1_HANG_ERR_MASK \ + 0x00000040 /* EN_SEC1_HANG_ERR[6] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_SEC1_HANG_ERR_SHFT 6 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_SEC0_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_SEC0_HANG_ERR_MASK \ + 0x00000020 /* EN_SEC0_HANG_ERR[5] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_SEC0_HANG_ERR_SHFT 5 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_PF_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_PF_HANG_ERR_MASK \ + 0x00000010 /* EN_PF_HANG_ERR[4] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_PF_HANG_ERR_SHFT 4 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_RIOC_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_RIOC_HANG_ERR_MASK \ + 0x00000008 /* EN_BN0_MDP_RIOC_HANG_ERR[3] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_RIOC_HANG_ERR_SHFT 3 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_TIOC_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_TIOC_HANG_ERR_MASK \ + 0x00000004 /* EN_BN0_MDP_TIOC_HANG_ERR[2] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_TIOC_HANG_ERR_SHFT 2 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_MDP_RDP_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_MDP_RDP_HANG_ERR_MASK \ + 0x00000002 /* EN_MDP_RDP_HANG_ERR[1] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_MDP_RDP_HANG_ERR_SHFT 1 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_TDP_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_TDP_HANG_ERR_MASK \ + 0x00000001 /* EN_BN0_MDP_TDP_HANG_ERR[0] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_TDP_HANG_ERR_SHFT 0 + +/* +* ---N9_BSS_PS_INT_MASK (0x820C0000 + 0x8c)--- +* EN_BSSID0_NONEMPTY_INT[0] - (RW) Enable control of BSSID0 queue empty +fall +* EN_BSSID1_NONEMPTY_INT[1] - (RW) Enable control of BSSID1 queue empty +fall +* EN_BSSID2_NONEMPTY_INT[2] - (RW) Enable control of BSSID2 queue empty +fall +* EN_BSSID3_NONEMPTY_INT[3] - (RW) Enable control of BSSID3 queue empty +fall +* RESERVED4[7..4] - (RO) Reserved bits +* EN_BSSID0_EMPTY_INT[8] - (RW) Enable control of BSSID0 queue empty +raise +* EN_BSSID1_EMPTY_INT[9] - (RW) Enable control of BSSID1 queue empty +raise +* EN_BSSID2_EMPTY_INT[10] - (RW) Enable control of BSSID2 queue empty +raise +* EN_BSSID3_EMPTY_INT[11] - (RW) Enable control of BSSID3 queue empty +raise +* RESERVED12[15..12] - (RO) Reserved bits +* EN_BSSID0_ENQ_LMAC_INT[16] - (RW) Enable control of BSSID0 enqueue +interrupt +* EN_BSSID1_ENQ_LMAC_INT[17] - (RW) Enable control of BSSID1 enqueue +interrupt +* EN_BSSID2_ENQ_LMAC_INT[18] - (RW) Enable control of BSSID2 enqueue +interrupt +* EN_BSSID3_ENQ_LMAC_INT[19] - (RW) Enable control of BSSID3 enqueue +interrupt +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_ENQ_LMAC_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_ENQ_LMAC_INT_MASK \ + 0x00080000 /* EN_BSSID3_ENQ_LMAC_INT[19] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_ENQ_LMAC_INT_SHFT 19 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_ENQ_LMAC_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_ENQ_LMAC_INT_MASK \ + 0x00040000 /* EN_BSSID2_ENQ_LMAC_INT[18] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_ENQ_LMAC_INT_SHFT 18 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_ENQ_LMAC_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_ENQ_LMAC_INT_MASK \ + 0x00020000 /* EN_BSSID1_ENQ_LMAC_INT[17] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_ENQ_LMAC_INT_SHFT 17 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_ENQ_LMAC_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_ENQ_LMAC_INT_MASK \ + 0x00010000 /* EN_BSSID0_ENQ_LMAC_INT[16] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_ENQ_LMAC_INT_SHFT 16 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_EMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_EMPTY_INT_MASK \ + 0x00000800 /* EN_BSSID3_EMPTY_INT[11] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_EMPTY_INT_SHFT 11 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_EMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_EMPTY_INT_MASK \ + 0x00000400 /* EN_BSSID2_EMPTY_INT[10] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_EMPTY_INT_SHFT 10 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_EMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_EMPTY_INT_MASK \ + 0x00000200 /* EN_BSSID1_EMPTY_INT[9] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_EMPTY_INT_SHFT 9 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_EMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_EMPTY_INT_MASK \ + 0x00000100 /* EN_BSSID0_EMPTY_INT[8] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_EMPTY_INT_SHFT 8 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_NONEMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_NONEMPTY_INT_MASK \ + 0x00000008 /* EN_BSSID3_NONEMPTY_INT[3] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_NONEMPTY_INT_SHFT 3 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_NONEMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_NONEMPTY_INT_MASK \ + 0x00000004 /* EN_BSSID2_NONEMPTY_INT[2] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_NONEMPTY_INT_SHFT 2 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_NONEMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_NONEMPTY_INT_MASK \ + 0x00000002 /* EN_BSSID1_NONEMPTY_INT[1] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_NONEMPTY_INT_SHFT 1 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_NONEMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_NONEMPTY_INT_MASK \ + 0x00000001 /* EN_BSSID0_NONEMPTY_INT[0] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_NONEMPTY_INT_SHFT 0 + +/* +* ---HOST_REPORT0 (0x820C0000 + 0x90)--- +* RESERVED0[0] - (RO) Reserved bits +* DIS_HOST_RPT[1] - (RW) Disables host report function +* HOST_RPT_VER0_EN[2] - (RW) Enable control for host report roll back +* to Version 2(MT7915 E1 used). +* HOST_RPT_TX_LATENCY[3] - (RW) Enable host report TX latency +* WMCPU_MSDU_ID_NUM[5..4] - (RW) Configuration of WMCPU MSDU ID usage. +* RESERVED6[7..6] - (RO) Reserved bits +* HOST_RPT_PACK_TH[15..8] - (RW) The buffer threshold for packing host +* report. The buffer size less then the MSDU numbers of a MPDU, would let +MSDU_ID +lose. +* HOST_RPT_QID[22..16] - (RW) PSE Queue ID control for host report. +* HOST_RPT_PID[23] - (RW) PSE Port ID control for host report. +* WMCPU_RPT_QID[30..24] - (RW) PSE Queue ID control for WMCPU report. +* WMCPU_RPT_PID[31] - (RW) PSE Port ID control for WMCPU report. +*/ +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_RPT_PID_ADDR WF_PLE_TOP_HOST_REPORT0_ADDR +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_RPT_PID_MASK \ + 0x80000000 /* WMCPU_RPT_PID[31] */ +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_RPT_PID_SHFT 31 +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_RPT_QID_ADDR WF_PLE_TOP_HOST_REPORT0_ADDR +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_RPT_QID_MASK \ + 0x7F000000 /* WMCPU_RPT_QID[30..24] */ +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_RPT_QID_SHFT 24 +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_PID_ADDR WF_PLE_TOP_HOST_REPORT0_ADDR +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_PID_MASK \ + 0x00800000 /* HOST_RPT_PID[23] */ +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_PID_SHFT 23 +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_QID_ADDR WF_PLE_TOP_HOST_REPORT0_ADDR +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_QID_MASK \ + 0x007F0000 /* HOST_RPT_QID[22..16] */ +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_QID_SHFT 16 +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_PACK_TH_ADDR \ + WF_PLE_TOP_HOST_REPORT0_ADDR +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_PACK_TH_MASK \ + 0x0000FF00 /* HOST_RPT_PACK_TH[15..8] */ +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_PACK_TH_SHFT 8 +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_MSDU_ID_NUM_ADDR \ + WF_PLE_TOP_HOST_REPORT0_ADDR +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_MSDU_ID_NUM_MASK \ + 0x00000030 /* WMCPU_MSDU_ID_NUM[5..4] */ +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_MSDU_ID_NUM_SHFT 4 +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_TX_LATENCY_ADDR \ + WF_PLE_TOP_HOST_REPORT0_ADDR +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_TX_LATENCY_MASK \ + 0x00000008 /* HOST_RPT_TX_LATENCY[3] */ +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_TX_LATENCY_SHFT 3 +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_VER0_EN_ADDR \ + WF_PLE_TOP_HOST_REPORT0_ADDR +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_VER0_EN_MASK \ + 0x00000004 /* HOST_RPT_VER0_EN[2] */ +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_VER0_EN_SHFT 2 +#define WF_PLE_TOP_HOST_REPORT0_DIS_HOST_RPT_ADDR WF_PLE_TOP_HOST_REPORT0_ADDR +#define WF_PLE_TOP_HOST_REPORT0_DIS_HOST_RPT_MASK \ + 0x00000002 /* DIS_HOST_RPT[1] */ +#define WF_PLE_TOP_HOST_REPORT0_DIS_HOST_RPT_SHFT 1 + +/* +* ---HOST_REPORT1 (0x820C0000 + 0x94)--- +* RESERVED0[7..0] - (RO) Reserved bits +* MD_RPT_QID[14..8] - (RW) PSE Queue ID control for MD CPU host +report. +* MD_RPT_PID[15] - (RW) PSE Port ID control for MD CPU host +report. +* HOST_RPT_PG_SIZE[19..16] - (RW) Setting of host report used PSE page +size. +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_HOST_REPORT1_HOST_RPT_PG_SIZE_ADDR \ + WF_PLE_TOP_HOST_REPORT1_ADDR +#define WF_PLE_TOP_HOST_REPORT1_HOST_RPT_PG_SIZE_MASK \ + 0x000F0000 /* HOST_RPT_PG_SIZE[19..16] */ +#define WF_PLE_TOP_HOST_REPORT1_HOST_RPT_PG_SIZE_SHFT 16 +#define WF_PLE_TOP_HOST_REPORT1_MD_RPT_PID_ADDR WF_PLE_TOP_HOST_REPORT1_ADDR +#define WF_PLE_TOP_HOST_REPORT1_MD_RPT_PID_MASK 0x00008000 /* MD_RPT_PID[15] */ +#define WF_PLE_TOP_HOST_REPORT1_MD_RPT_PID_SHFT 15 +#define WF_PLE_TOP_HOST_REPORT1_MD_RPT_QID_ADDR WF_PLE_TOP_HOST_REPORT1_ADDR +#define WF_PLE_TOP_HOST_REPORT1_MD_RPT_QID_MASK \ + 0x00007F00 /* MD_RPT_QID[14..8] */ +#define WF_PLE_TOP_HOST_REPORT1_MD_RPT_QID_SHFT 8 + +/* +* ---HOST_REPORT2 (0x820C0000 + 0x98)--- +* BN1_HOST_RPT_QID[6..0] - (RW) PSE Queue ID control for BN1 Host +report. +* BN1_HOST_RPT_PID[7] - (RW) PSE Port ID control for BN1 Host report. +* BN1_MD_RPT_QID[14..8] - (RW) PSE Queue ID control for BN1 MD CPU host +report. +* BN1_MD_RPT_PID[15] - (RW) PSE Port ID control for BN1 MD CPU host +report. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_HOST_REPORT2_BN1_MD_RPT_PID_ADDR WF_PLE_TOP_HOST_REPORT2_ADDR +#define WF_PLE_TOP_HOST_REPORT2_BN1_MD_RPT_PID_MASK \ + 0x00008000 /* BN1_MD_RPT_PID[15] */ +#define WF_PLE_TOP_HOST_REPORT2_BN1_MD_RPT_PID_SHFT 15 +#define WF_PLE_TOP_HOST_REPORT2_BN1_MD_RPT_QID_ADDR WF_PLE_TOP_HOST_REPORT2_ADDR +#define WF_PLE_TOP_HOST_REPORT2_BN1_MD_RPT_QID_MASK \ + 0x00007F00 /* BN1_MD_RPT_QID[14..8] */ +#define WF_PLE_TOP_HOST_REPORT2_BN1_MD_RPT_QID_SHFT 8 +#define WF_PLE_TOP_HOST_REPORT2_BN1_HOST_RPT_PID_ADDR \ + WF_PLE_TOP_HOST_REPORT2_ADDR +#define WF_PLE_TOP_HOST_REPORT2_BN1_HOST_RPT_PID_MASK \ + 0x00000080 /* BN1_HOST_RPT_PID[7] */ +#define WF_PLE_TOP_HOST_REPORT2_BN1_HOST_RPT_PID_SHFT 7 +#define WF_PLE_TOP_HOST_REPORT2_BN1_HOST_RPT_QID_ADDR \ + WF_PLE_TOP_HOST_REPORT2_ADDR +#define WF_PLE_TOP_HOST_REPORT2_BN1_HOST_RPT_QID_MASK \ + 0x0000007F /* BN1_HOST_RPT_QID[6..0] */ +#define WF_PLE_TOP_HOST_REPORT2_BN1_HOST_RPT_QID_SHFT 0 + +/* +* ---RELEASE_CTRL_0 (0x820C0000 + 0x9c)--- +* NOR_RLS_QID[6..0] - (RW) Normal TX packet release DST QID +* RESERVED7[7] - (RO) Reserved bits +* NOR_RLS_PID[9..8] - (RW) Normal TX packet release DST PID +* RESERVED10[15..10] - (RO) Reserved bits +* DROP_RLS_QID[22..16] - (RW) Drop packet release DST QID +* RESERVED23[23] - (RO) Reserved bits +* DROP_RLS_PID[25..24] - (RW) Drop packet release DST PID +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_RELEASE_CTRL_0_DROP_RLS_PID_ADDR \ + WF_PLE_TOP_RELEASE_CTRL_0_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_0_DROP_RLS_PID_MASK \ + 0x03000000 /* DROP_RLS_PID[25..24] */ +#define WF_PLE_TOP_RELEASE_CTRL_0_DROP_RLS_PID_SHFT 24 +#define WF_PLE_TOP_RELEASE_CTRL_0_DROP_RLS_QID_ADDR \ + WF_PLE_TOP_RELEASE_CTRL_0_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_0_DROP_RLS_QID_MASK \ + 0x007F0000 /* DROP_RLS_QID[22..16] */ +#define WF_PLE_TOP_RELEASE_CTRL_0_DROP_RLS_QID_SHFT 16 +#define WF_PLE_TOP_RELEASE_CTRL_0_NOR_RLS_PID_ADDR \ + WF_PLE_TOP_RELEASE_CTRL_0_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_0_NOR_RLS_PID_MASK \ + 0x00000300 /* NOR_RLS_PID[9..8] */ +#define WF_PLE_TOP_RELEASE_CTRL_0_NOR_RLS_PID_SHFT 8 +#define WF_PLE_TOP_RELEASE_CTRL_0_NOR_RLS_QID_ADDR \ + WF_PLE_TOP_RELEASE_CTRL_0_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_0_NOR_RLS_QID_MASK \ + 0x0000007F /* NOR_RLS_QID[6..0] */ +#define WF_PLE_TOP_RELEASE_CTRL_0_NOR_RLS_QID_SHFT 0 + +/* +* ---RELEASE_CTRL_1 (0x820C0000 + 0xA0)--- +* BCN0_RLS_QID[6..0] - (RW) Beacon 0 packet release DST QID +* RESERVED7[7] - (RO) Reserved bits +* BCN0_RLS_PID[9..8] - (RW) Beacon 0 packet release DST PID +* RESERVED10[15..10] - (RO) Reserved bits +* BCN1_RLS_QID[22..16] - (RW) Beacon 1 packet release DST QID +* RESERVED23[23] - (RO) Reserved bits +* BCN1_RLS_PID[25..24] - (RW) Beacon 1 packet release DST PID +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN1_RLS_PID_ADDR \ + WF_PLE_TOP_RELEASE_CTRL_1_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN1_RLS_PID_MASK \ + 0x03000000 /* BCN1_RLS_PID[25..24] */ +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN1_RLS_PID_SHFT 24 +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN1_RLS_QID_ADDR \ + WF_PLE_TOP_RELEASE_CTRL_1_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN1_RLS_QID_MASK \ + 0x007F0000 /* BCN1_RLS_QID[22..16] */ +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN1_RLS_QID_SHFT 16 +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN0_RLS_PID_ADDR \ + WF_PLE_TOP_RELEASE_CTRL_1_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN0_RLS_PID_MASK \ + 0x00000300 /* BCN0_RLS_PID[9..8] */ +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN0_RLS_PID_SHFT 8 +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN0_RLS_QID_ADDR \ + WF_PLE_TOP_RELEASE_CTRL_1_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN0_RLS_QID_MASK \ + 0x0000007F /* BCN0_RLS_QID[6..0] */ +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN0_RLS_QID_SHFT 0 + +/* +* ---RELEASE_CTRL_3 (0x820C0000 + 0xa8)--- +* RLS_FREE_DONE_PG_SIZE[3..0] - (RW) Page size configuration of Free done +* event(host report). +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_RELEASE_CTRL_3_RLS_FREE_DONE_PG_SIZE_ADDR \ + WF_PLE_TOP_RELEASE_CTRL_3_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_3_RLS_FREE_DONE_PG_SIZE_MASK \ + 0x0000000F /* RLS_FREE_DONE_PG_SIZE[3..0] */ +#define WF_PLE_TOP_RELEASE_CTRL_3_RLS_FREE_DONE_PG_SIZE_SHFT 0 + +/* +* ---BLK_MODE_RATE_LMT (0x820C0000 + 0xac)--- +* BN0_MACTX_BLK_RATE_LMT[15..0] - (RW) TX Rate limitaion of CutThrough data +* block mode. The rate less then the limitation would turn on block mode. +* BN1_MACTX_BLK_RATE_LMT[31..16] - (RW) TX Rate limitaion of CutThrough data +* block mode. The rate less then the limitation would turn on block mode. +*/ +#define WF_PLE_TOP_BLK_MODE_RATE_LMT_BN1_MACTX_BLK_RATE_LMT_ADDR \ + WF_PLE_TOP_BLK_MODE_RATE_LMT_ADDR +#define WF_PLE_TOP_BLK_MODE_RATE_LMT_BN1_MACTX_BLK_RATE_LMT_MASK \ + 0xFFFF0000 /* BN1_MACTX_BLK_RATE_LMT[31..16] */ +#define WF_PLE_TOP_BLK_MODE_RATE_LMT_BN1_MACTX_BLK_RATE_LMT_SHFT 16 +#define WF_PLE_TOP_BLK_MODE_RATE_LMT_BN0_MACTX_BLK_RATE_LMT_ADDR \ + WF_PLE_TOP_BLK_MODE_RATE_LMT_ADDR +#define WF_PLE_TOP_BLK_MODE_RATE_LMT_BN0_MACTX_BLK_RATE_LMT_MASK \ + 0x0000FFFF /* BN0_MACTX_BLK_RATE_LMT[15..0] */ +#define WF_PLE_TOP_BLK_MODE_RATE_LMT_BN0_MACTX_BLK_RATE_LMT_SHFT 0 + +/* +* ---PLE_MODULE_CKG_DIS (0x820C0000 + 0xb0)--- +* DIS_FL_DYN_CKG[0] - (RW) Disable control of PLE frame link module +* dynamic clock gating function +* DIS_PL_DYN_CKG[1] - (RW) Disable control of PLE page link module +* dynamic clock gating function +* DIS_CPU_PORT_DYN_CKG[2] - (RW) Disable control of PLE CPU port module +* dynamic clock gating function +* DIS_HIF_PORT_DYN_CKG[3] - (RW) Disable control of PLE HIF port module +* dynamic clock gating function +* DIS_WF_PORT_DYN_CKG[4] - (RW) Disable control of PLE LMAC module +* dynamic clock gating function +* DIS_RLS_DYN_CKG[5] - (RW) Disable control of PLE release module +* dynamic clock gating function +* DIS_RL_DYN_CKG[6] - (RW) Disable control of PLE relay information +* module dynamic clock gating function +* DIS_MACTX_DYN_CKG[7] - (RW) Disable control of PLE MACTX module +* dynamic clock gating function +* DIS_PSEPORT_DYN_CKG[8] - (RW) Disable control of PLE PSE port module +* dynamic clock gating function +* DIS_CSR_DYN_CKG[9] - (RW) Disable control of PLE CR module dynamic +* clock gating function +* DIS_CPU_WRAP_DYN_CKG[10] - (RW) Disable control of PLE CPU_WRAP module +* dynamic clock gating function +* DIS_DBG_DYN_CKG[11] - (RW) Disable control of PLE debug module +* dynamic clock gating function +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_DBG_DYN_CKG_ADDR \ + WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_DBG_DYN_CKG_MASK \ + 0x00000800 /* DIS_DBG_DYN_CKG[11] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_DBG_DYN_CKG_SHFT 11 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CPU_WRAP_DYN_CKG_ADDR \ + WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CPU_WRAP_DYN_CKG_MASK \ + 0x00000400 /* DIS_CPU_WRAP_DYN_CKG[10] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CPU_WRAP_DYN_CKG_SHFT 10 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CSR_DYN_CKG_ADDR \ + WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CSR_DYN_CKG_MASK \ + 0x00000200 /* DIS_CSR_DYN_CKG[9] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CSR_DYN_CKG_SHFT 9 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_PSEPORT_DYN_CKG_ADDR \ + WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_PSEPORT_DYN_CKG_MASK \ + 0x00000100 /* DIS_PSEPORT_DYN_CKG[8] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_PSEPORT_DYN_CKG_SHFT 8 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_MACTX_DYN_CKG_ADDR \ + WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_MACTX_DYN_CKG_MASK \ + 0x00000080 /* DIS_MACTX_DYN_CKG[7] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_MACTX_DYN_CKG_SHFT 7 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_RL_DYN_CKG_ADDR \ + WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_RL_DYN_CKG_MASK \ + 0x00000040 /* DIS_RL_DYN_CKG[6] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_RL_DYN_CKG_SHFT 6 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_RLS_DYN_CKG_ADDR \ + WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_RLS_DYN_CKG_MASK \ + 0x00000020 /* DIS_RLS_DYN_CKG[5] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_RLS_DYN_CKG_SHFT 5 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_WF_PORT_DYN_CKG_ADDR \ + WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_WF_PORT_DYN_CKG_MASK \ + 0x00000010 /* DIS_WF_PORT_DYN_CKG[4] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_WF_PORT_DYN_CKG_SHFT 4 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_HIF_PORT_DYN_CKG_ADDR \ + WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_HIF_PORT_DYN_CKG_MASK \ + 0x00000008 /* DIS_HIF_PORT_DYN_CKG[3] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_HIF_PORT_DYN_CKG_SHFT 3 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CPU_PORT_DYN_CKG_ADDR \ + WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CPU_PORT_DYN_CKG_MASK \ + 0x00000004 /* DIS_CPU_PORT_DYN_CKG[2] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CPU_PORT_DYN_CKG_SHFT 2 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_PL_DYN_CKG_ADDR \ + WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_PL_DYN_CKG_MASK \ + 0x00000002 /* DIS_PL_DYN_CKG[1] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_PL_DYN_CKG_SHFT 1 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_FL_DYN_CKG_ADDR \ + WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_FL_DYN_CKG_MASK \ + 0x00000001 /* DIS_FL_DYN_CKG[0] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_FL_DYN_CKG_SHFT 0 + +/* +* ---PLE_DELAY_TX_CTRL (0x820C0000 + 0xb4)--- +* DELAY_TX_PAGE_TH[11..0] - (RW) Delay TX function is used to delay TXD +* be LMAC used. If the total pages of TXD large than page threshold, the delay +TX +* would be released. LMAC would use TXD to TX. +* RESERVED12[15..12] - (RO) Reserved bits +* DELAY_TX_TIMEOUT_TH[23..16] - (RW) Delay TX function is used to delay TXD +* be LMAC used. IF no more enqueue event in the time out threshold, the delay TX +* would be released. LMAC can use TXD to TX. (unit is 32us). +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PLE_DELAY_TX_CTRL_DELAY_TX_TIMEOUT_TH_ADDR \ + WF_PLE_TOP_PLE_DELAY_TX_CTRL_ADDR +#define WF_PLE_TOP_PLE_DELAY_TX_CTRL_DELAY_TX_TIMEOUT_TH_MASK \ + 0x00FF0000 /* DELAY_TX_TIMEOUT_TH[23..16] */ +#define WF_PLE_TOP_PLE_DELAY_TX_CTRL_DELAY_TX_TIMEOUT_TH_SHFT 16 +#define WF_PLE_TOP_PLE_DELAY_TX_CTRL_DELAY_TX_PAGE_TH_ADDR \ + WF_PLE_TOP_PLE_DELAY_TX_CTRL_ADDR +#define WF_PLE_TOP_PLE_DELAY_TX_CTRL_DELAY_TX_PAGE_TH_MASK \ + 0x00000FFF /* DELAY_TX_PAGE_TH[11..0] */ +#define WF_PLE_TOP_PLE_DELAY_TX_CTRL_DELAY_TX_PAGE_TH_SHFT 0 + +/* +* ---PLE_STATION_REDIR_CTRL (0x820C0000 + 0xb8)--- +* STA_REDIR_QID[4..0] - (RW) Destitaion queue for Redirection +function. +* RESERVED5[5] - (RO) Reserved bits +* STA_REDIR_PID[7..6] - (RW) Destitaion port for Redirection +function. +* STA_REDIR_PASUE_TXD[8] - (RW) Pause TXD download for avoid race +* condition, when station redirection function turn off. +* RESERVED9[31..9] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_PASUE_TXD_ADDR \ + WF_PLE_TOP_PLE_STATION_REDIR_CTRL_ADDR +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_PASUE_TXD_MASK \ + 0x00000100 /* STA_REDIR_PASUE_TXD[8] */ +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_PASUE_TXD_SHFT 8 +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_PID_ADDR \ + WF_PLE_TOP_PLE_STATION_REDIR_CTRL_ADDR +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_PID_MASK \ + 0x000000C0 /* STA_REDIR_PID[7..6] */ +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_PID_SHFT 6 +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_QID_ADDR \ + WF_PLE_TOP_PLE_STATION_REDIR_CTRL_ADDR +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_QID_MASK \ + 0x0000001F /* STA_REDIR_QID[4..0] */ +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_QID_SHFT 0 + +/* +* ---MACTX_LENGTH_LIMIT (0x820C0000 + 0xBC)--- +* MACTX_LENGTH_LIMIT_BAND0[15..0] - (RW) MACTX download length limit of band0 +* MACTX_LENGTH_LIMIT_BAND1[31..16] - (RW) MACTX download length limit of band1 +*/ +#define WF_PLE_TOP_MACTX_LENGTH_LIMIT_MACTX_LENGTH_LIMIT_BAND1_ADDR \ + WF_PLE_TOP_MACTX_LENGTH_LIMIT_ADDR +#define WF_PLE_TOP_MACTX_LENGTH_LIMIT_MACTX_LENGTH_LIMIT_BAND1_MASK \ + 0xFFFF0000 /* MACTX_LENGTH_LIMIT_BAND1[31..16] */ +#define WF_PLE_TOP_MACTX_LENGTH_LIMIT_MACTX_LENGTH_LIMIT_BAND1_SHFT 16 +#define WF_PLE_TOP_MACTX_LENGTH_LIMIT_MACTX_LENGTH_LIMIT_BAND0_ADDR \ + WF_PLE_TOP_MACTX_LENGTH_LIMIT_ADDR +#define WF_PLE_TOP_MACTX_LENGTH_LIMIT_MACTX_LENGTH_LIMIT_BAND0_MASK \ + 0x0000FFFF /* MACTX_LENGTH_LIMIT_BAND0[15..0] */ +#define WF_PLE_TOP_MACTX_LENGTH_LIMIT_MACTX_LENGTH_LIMIT_BAND0_SHFT 0 + +/* +* ---TXS_BUF_PAUSE (0x820C0000 + 0xc0)--- +* EN_PAUSE_AC00_QUEUE[0] - (RW) Pause control of WMM0 AC0 queue. +* EN_PAUSE_AC01_QUEUE[1] - (RW) Pause control of WMM0 AC1 queue. +* EN_PAUSE_AC02_QUEUE[2] - (RW) Pause control of WMM0 AC2 queue. +* EN_PAUSE_AC03_QUEUE[3] - (RW) Pause control of WMM0 AC3 queue. +* EN_PAUSE_AC10_QUEUE[4] - (RW) Pause control of WMM1 AC0 queue. +* EN_PAUSE_AC11_QUEUE[5] - (RW) Pause control of WMM1 AC1 queue. +* EN_PAUSE_AC12_QUEUE[6] - (RW) Pause control of WMM1 AC2 queue. +* EN_PAUSE_AC13_QUEUE[7] - (RW) Pause control of WMM1 AC3 queue. +* EN_PAUSE_AC20_QUEUE[8] - (RW) Pause control of WMM2 AC0 queue. +* EN_PAUSE_AC21_QUEUE[9] - (RW) Pause control of WMM2 AC1 queue. +* EN_PAUSE_AC22_QUEUE[10] - (RW) Pause control of WMM2 AC2 queue. +* EN_PAUSE_AC23_QUEUE[11] - (RW) Pause control of WMM2 AC3 queue. +* EN_PAUSE_AC30_QUEUE[12] - (RW) Pause control of WMM3 AC0 queue. +* EN_PAUSE_AC31_QUEUE[13] - (RW) Pause control of WMM3 AC1 queue. +* EN_PAUSE_AC32_QUEUE[14] - (RW) Pause control of WMM3 AC2 queue. +* EN_PAUSE_AC33_QUEUE[15] - (RW) Pause control of WMM3 AC3 queue. +* EN_PAUSE_ALTX_0_QUEUE[16] - (RW) Pause control of ALTX queue 0. +* EN_PAUSE_BMC_0_QUEUE[17] - (RW) Pause control of BMC queue 0. +* EN_PAUSE_BCN_0_QUEUE[18] - (RW) Pause control of BCN queue 0. +* EN_PAUSE_PSMP_0_QUEUE[19] - (RW) Pause control of PSMP queue 0. +* EN_PAUSE_ALTX_1_QUEUE[20] - (RW) Pause control of ALTX queue 1. +* EN_PAUSE_BMC_1_QUEUE[21] - (RW) Pause control of BMC queue 1. +* EN_PAUSE_BCN_1_QUEUE[22] - (RW) Pause control of BCN queue 1. +* EN_PAUSE_PSMP_1_QUEUE[23] - (RW) Pause control of PSMP queue 1. +* EN_PAUSE_NAF_QUEUE[24] - (RW) Pause control of NAF queue. +* EN_PAUSE_NBCN_QUEUE[25] - (RW) Pause control of NBCN queue. +* RESERVED26[30..26] - (RO) Reserved bits +* PSE_TXS_BUF_VALID[31] - (RO) PSE TXS buffer status. +*/ +#define WF_PLE_TOP_TXS_BUF_PAUSE_PSE_TXS_BUF_VALID_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_PSE_TXS_BUF_VALID_MASK \ + 0x80000000 /* PSE_TXS_BUF_VALID[31] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_PSE_TXS_BUF_VALID_SHFT 31 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_NBCN_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_NBCN_QUEUE_MASK \ + 0x02000000 /* EN_PAUSE_NBCN_QUEUE[25] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_NBCN_QUEUE_SHFT 25 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_NAF_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_NAF_QUEUE_MASK \ + 0x01000000 /* EN_PAUSE_NAF_QUEUE[24] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_NAF_QUEUE_SHFT 24 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_PSMP_1_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_PSMP_1_QUEUE_MASK \ + 0x00800000 /* EN_PAUSE_PSMP_1_QUEUE[23] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_PSMP_1_QUEUE_SHFT 23 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BCN_1_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BCN_1_QUEUE_MASK \ + 0x00400000 /* EN_PAUSE_BCN_1_QUEUE[22] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BCN_1_QUEUE_SHFT 22 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BMC_1_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BMC_1_QUEUE_MASK \ + 0x00200000 /* EN_PAUSE_BMC_1_QUEUE[21] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BMC_1_QUEUE_SHFT 21 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_ALTX_1_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_ALTX_1_QUEUE_MASK \ + 0x00100000 /* EN_PAUSE_ALTX_1_QUEUE[20] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_ALTX_1_QUEUE_SHFT 20 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_PSMP_0_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_PSMP_0_QUEUE_MASK \ + 0x00080000 /* EN_PAUSE_PSMP_0_QUEUE[19] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_PSMP_0_QUEUE_SHFT 19 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BCN_0_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BCN_0_QUEUE_MASK \ + 0x00040000 /* EN_PAUSE_BCN_0_QUEUE[18] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BCN_0_QUEUE_SHFT 18 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BMC_0_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BMC_0_QUEUE_MASK \ + 0x00020000 /* EN_PAUSE_BMC_0_QUEUE[17] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BMC_0_QUEUE_SHFT 17 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_ALTX_0_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_ALTX_0_QUEUE_MASK \ + 0x00010000 /* EN_PAUSE_ALTX_0_QUEUE[16] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_ALTX_0_QUEUE_SHFT 16 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC33_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC33_QUEUE_MASK \ + 0x00008000 /* EN_PAUSE_AC33_QUEUE[15] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC33_QUEUE_SHFT 15 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC32_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC32_QUEUE_MASK \ + 0x00004000 /* EN_PAUSE_AC32_QUEUE[14] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC32_QUEUE_SHFT 14 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC31_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC31_QUEUE_MASK \ + 0x00002000 /* EN_PAUSE_AC31_QUEUE[13] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC31_QUEUE_SHFT 13 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC30_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC30_QUEUE_MASK \ + 0x00001000 /* EN_PAUSE_AC30_QUEUE[12] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC30_QUEUE_SHFT 12 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC23_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC23_QUEUE_MASK \ + 0x00000800 /* EN_PAUSE_AC23_QUEUE[11] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC23_QUEUE_SHFT 11 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC22_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC22_QUEUE_MASK \ + 0x00000400 /* EN_PAUSE_AC22_QUEUE[10] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC22_QUEUE_SHFT 10 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC21_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC21_QUEUE_MASK \ + 0x00000200 /* EN_PAUSE_AC21_QUEUE[9] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC21_QUEUE_SHFT 9 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC20_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC20_QUEUE_MASK \ + 0x00000100 /* EN_PAUSE_AC20_QUEUE[8] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC20_QUEUE_SHFT 8 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC13_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC13_QUEUE_MASK \ + 0x00000080 /* EN_PAUSE_AC13_QUEUE[7] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC13_QUEUE_SHFT 7 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC12_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC12_QUEUE_MASK \ + 0x00000040 /* EN_PAUSE_AC12_QUEUE[6] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC12_QUEUE_SHFT 6 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC11_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC11_QUEUE_MASK \ + 0x00000020 /* EN_PAUSE_AC11_QUEUE[5] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC11_QUEUE_SHFT 5 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC10_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC10_QUEUE_MASK \ + 0x00000010 /* EN_PAUSE_AC10_QUEUE[4] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC10_QUEUE_SHFT 4 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC03_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC03_QUEUE_MASK \ + 0x00000008 /* EN_PAUSE_AC03_QUEUE[3] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC03_QUEUE_SHFT 3 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC02_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC02_QUEUE_MASK \ + 0x00000004 /* EN_PAUSE_AC02_QUEUE[2] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC02_QUEUE_SHFT 2 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC01_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC01_QUEUE_MASK \ + 0x00000002 /* EN_PAUSE_AC01_QUEUE[1] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC01_QUEUE_SHFT 1 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC00_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC00_QUEUE_MASK \ + 0x00000001 /* EN_PAUSE_AC00_QUEUE[0] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC00_QUEUE_SHFT 0 + +/* +* ---FSM_IDLE_WD_CTRL (0x820C0000 + 0xd0)--- +* FL_IDLE_WD_TO_TH[7..0] - (RW) Watchdog timeout threshold for frame +* link FSM not returning to IDLE +* PL_IDLE_WD_TO_TH[15..8] - (RW) Watchdog timeout threshold for page link +* FSM not returning to IDLE +* PORT_IDLE_WD_TO_TH[23..16] - (RW) Watchdog timeout threshold for port oper +* FSM not returning to IDLE +* (Including HIF/CPU/LMAC port) +* MACTX_IDLE_WD_TO_TH[31..24] - (RW) Watchdog timeout threshold for MACTX FSM +* not returning to IDLE +*/ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_MACTX_IDLE_WD_TO_TH_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_CTRL_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_MACTX_IDLE_WD_TO_TH_MASK \ + 0xFF000000 /* MACTX_IDLE_WD_TO_TH[31..24] */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_MACTX_IDLE_WD_TO_TH_SHFT 24 +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_PORT_IDLE_WD_TO_TH_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_CTRL_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_PORT_IDLE_WD_TO_TH_MASK \ + 0x00FF0000 /* PORT_IDLE_WD_TO_TH[23..16] */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_PORT_IDLE_WD_TO_TH_SHFT 16 +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_PL_IDLE_WD_TO_TH_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_CTRL_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_PL_IDLE_WD_TO_TH_MASK \ + 0x0000FF00 /* PL_IDLE_WD_TO_TH[15..8] */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_PL_IDLE_WD_TO_TH_SHFT 8 +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_FL_IDLE_WD_TO_TH_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_CTRL_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_FL_IDLE_WD_TO_TH_MASK \ + 0x000000FF /* FL_IDLE_WD_TO_TH[7..0] */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_FL_IDLE_WD_TO_TH_SHFT 0 + +/* +* ---FSM_IDLE_WD_EN (0x820C0000 + 0xd4)--- +* EN_FL_IDLE_WD_TO[0] - (RW) Enables watchdog for frame link FSM not +* returning to IDLE +* EN_PL_IDLE_WD_TO[1] - (RW) Enables watchdog for page link FSM not +* returning to IDLE +* EN_CPU_PORT_IDLE_WD_TO[2] - (RW) Enables watchdog for CPU port oper FSM +* not returning to IDLE +* EN_HIF_PORT_IDLE_WD_TO[3] - (RW) Enables watchdog for HIF port oper FSM +* not returning to IDLE +* EN_LMAC_PORT_IDLE_WD_TO[4] - (RW) Enables watchdog for LMAC port oper FSM +* not returning to IDLE +* EN_AMSDU_PORT_IDLE_WD_TO[5] - (RW) Enables watchdog for AMSDU port FSM not +* returning to IDLE +* EN_HW_AMSDU_IDLE_WD_TO[6] - (RW) Enables watchdog for HW AMSDU FSM not +* returning to IDLE +* RESERVED7[7] - (RO) Reserved bits +* EN_MACTX0_IDLE_WD_TO[8] - (RW) Enables watchdog for MACTX 0 FSM not +* returning to IDLE +* EN_MACTX2_IDLE_WD_TO[9] - (RW) Enables watchdog for MACTX 1 FSM not +* returning to IDLE +* EN_MACTX1_IDLE_WD_TO[10] - (RW) Enables watchdog for MACTX 2 FSM not +* returning to IDLE +* EN_MACTX3_IDLE_WD_TO[11] - (RW) Enables watchdog for MACTX 3 FSM not +* returning to IDLE +* EN_MDP_IDLE_WD_TO[12] - (RW) Enables watchdog for MDP port oper FSM +* not returning to IDLE +* EN_PREDL_ARB_IDLE_WD_TO[13] - (RW) Enables watchdog for Predl arbitrator +* FSM not returning to IDLE +* EN_PREDL_TXCMD_IDLE_WD_TO[14] - (RW) Enables watchdog for Predl TXCMD parser +* FSM not returning to IDLE +* RESERVED15[31..15] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PREDL_TXCMD_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PREDL_TXCMD_IDLE_WD_TO_MASK \ + 0x00004000 /* EN_PREDL_TXCMD_IDLE_WD_TO[14] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PREDL_TXCMD_IDLE_WD_TO_SHFT 14 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PREDL_ARB_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PREDL_ARB_IDLE_WD_TO_MASK \ + 0x00002000 /* EN_PREDL_ARB_IDLE_WD_TO[13] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PREDL_ARB_IDLE_WD_TO_SHFT 13 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MDP_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MDP_IDLE_WD_TO_MASK \ + 0x00001000 /* EN_MDP_IDLE_WD_TO[12] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MDP_IDLE_WD_TO_SHFT 12 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX3_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX3_IDLE_WD_TO_MASK \ + 0x00000800 /* EN_MACTX3_IDLE_WD_TO[11] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX3_IDLE_WD_TO_SHFT 11 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX1_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX1_IDLE_WD_TO_MASK \ + 0x00000400 /* EN_MACTX1_IDLE_WD_TO[10] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX1_IDLE_WD_TO_SHFT 10 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX2_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX2_IDLE_WD_TO_MASK \ + 0x00000200 /* EN_MACTX2_IDLE_WD_TO[9] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX2_IDLE_WD_TO_SHFT 9 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX0_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX0_IDLE_WD_TO_MASK \ + 0x00000100 /* EN_MACTX0_IDLE_WD_TO[8] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX0_IDLE_WD_TO_SHFT 8 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_HW_AMSDU_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_HW_AMSDU_IDLE_WD_TO_MASK \ + 0x00000040 /* EN_HW_AMSDU_IDLE_WD_TO[6] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_HW_AMSDU_IDLE_WD_TO_SHFT 6 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_AMSDU_PORT_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_AMSDU_PORT_IDLE_WD_TO_MASK \ + 0x00000020 /* EN_AMSDU_PORT_IDLE_WD_TO[5] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_AMSDU_PORT_IDLE_WD_TO_SHFT 5 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_LMAC_PORT_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_LMAC_PORT_IDLE_WD_TO_MASK \ + 0x00000010 /* EN_LMAC_PORT_IDLE_WD_TO[4] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_LMAC_PORT_IDLE_WD_TO_SHFT 4 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_HIF_PORT_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_HIF_PORT_IDLE_WD_TO_MASK \ + 0x00000008 /* EN_HIF_PORT_IDLE_WD_TO[3] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_HIF_PORT_IDLE_WD_TO_SHFT 3 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_CPU_PORT_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_CPU_PORT_IDLE_WD_TO_MASK \ + 0x00000004 /* EN_CPU_PORT_IDLE_WD_TO[2] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_CPU_PORT_IDLE_WD_TO_SHFT 2 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PL_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PL_IDLE_WD_TO_MASK \ + 0x00000002 /* EN_PL_IDLE_WD_TO[1] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PL_IDLE_WD_TO_SHFT 1 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_FL_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_FL_IDLE_WD_TO_MASK \ + 0x00000001 /* EN_FL_IDLE_WD_TO[0] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_FL_IDLE_WD_TO_SHFT 0 + +/* +* ---FSM_IDLE_WD_CTRL_1 (0x820C0000 + 0xd8)--- +* MDP_IDLE_WD_TO_TH[7..0] - (RW) Watchdog timeout threshold for MDP FSM +* not returning to IDLE +* (Including MDP TDP/RDP/TIOC/RIOC) +* PF_IDLE_WD_TO_TH[15..8] - (RW) Watchdog timeout threshold for PF FSM +* not returning to IDLE +* SEC_IDLE_WD_TO_TH[23..16] - (RW) Watchdog timeout threshold for SEC FSM +* not returning to IDLE +* (Including SEC0/SEC1) +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_SEC_IDLE_WD_TO_TH_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_SEC_IDLE_WD_TO_TH_MASK \ + 0x00FF0000 /* SEC_IDLE_WD_TO_TH[23..16] */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_SEC_IDLE_WD_TO_TH_SHFT 16 +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_PF_IDLE_WD_TO_TH_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_PF_IDLE_WD_TO_TH_MASK \ + 0x0000FF00 /* PF_IDLE_WD_TO_TH[15..8] */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_PF_IDLE_WD_TO_TH_SHFT 8 +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_MDP_IDLE_WD_TO_TH_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_MDP_IDLE_WD_TO_TH_MASK \ + 0x000000FF /* MDP_IDLE_WD_TO_TH[7..0] */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_MDP_IDLE_WD_TO_TH_SHFT 0 + +/* +* ---FSM_IDLE_WD_EN_1 (0x820C0000 + 0xdc)--- +* EN_BN0_MDP_TDP_IDLE_WD_TO[0] - (RW) Enables watchdog for Band0 MDP TDP FSM +* not returning to IDLE +* EN_MDP_RDP_IDLE_WD_TO[1] - (RW) Enables watchdog for MDP RDP FSM not +* returning to IDLE +* EN_BN0_MDP_TIOC_IDLE_WD_TO[2] - (RW) Enables watchdog for Band0 MDP TIOC FSM +* not returning to IDLE +* EN_BN0_MDP_RIOC_IDLE_WD_TO[3] - (RW) Enables watchdog for Band0 MDP RIOC FSM +* not returning to IDLE +* EN_PF_IDLE_WD_TO[4] - (RW) Enables watchdog for PF FSM not +* returning to IDLE +* EN_SEC0_IDLE_WD_TO[5] - (RW) Enables watchdog for SEC0 FSM not +* returning to IDLE +* EN_SEC1_IDLE_WD_TO[6] - (RW) Enables watchdog for SEC1 FSM not +* returning to IDLE +* EN_BN1_MDP_TDP_IDLE_WD_TO[7] - (RW) Enables watchdog for Band1 MDP TDP FSM +* not returning to IDLE +* EN_BN1_MDP_TIOC_IDLE_WD_TO[8] - (RW) Enables watchdog for Band1 MDP TIOC FSM +* not returning to IDLE +* EN_BN1_MDP_RIOC_IDLE_WD_TO[9] - (RW) Enables watchdog for Band1 MDP RIOC FSM +* not returning to IDLE +* RESERVED10[31..10] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_RIOC_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_RIOC_IDLE_WD_TO_MASK \ + 0x00000200 /* EN_BN1_MDP_RIOC_IDLE_WD_TO[9] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_RIOC_IDLE_WD_TO_SHFT 9 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_TIOC_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_TIOC_IDLE_WD_TO_MASK \ + 0x00000100 /* EN_BN1_MDP_TIOC_IDLE_WD_TO[8] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_TIOC_IDLE_WD_TO_SHFT 8 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_TDP_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_TDP_IDLE_WD_TO_MASK \ + 0x00000080 /* EN_BN1_MDP_TDP_IDLE_WD_TO[7] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_TDP_IDLE_WD_TO_SHFT 7 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_SEC1_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_SEC1_IDLE_WD_TO_MASK \ + 0x00000040 /* EN_SEC1_IDLE_WD_TO[6] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_SEC1_IDLE_WD_TO_SHFT 6 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_SEC0_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_SEC0_IDLE_WD_TO_MASK \ + 0x00000020 /* EN_SEC0_IDLE_WD_TO[5] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_SEC0_IDLE_WD_TO_SHFT 5 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_PF_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_PF_IDLE_WD_TO_MASK \ + 0x00000010 /* EN_PF_IDLE_WD_TO[4] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_PF_IDLE_WD_TO_SHFT 4 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_RIOC_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_RIOC_IDLE_WD_TO_MASK \ + 0x00000008 /* EN_BN0_MDP_RIOC_IDLE_WD_TO[3] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_RIOC_IDLE_WD_TO_SHFT 3 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_TIOC_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_TIOC_IDLE_WD_TO_MASK \ + 0x00000004 /* EN_BN0_MDP_TIOC_IDLE_WD_TO[2] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_TIOC_IDLE_WD_TO_SHFT 2 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_MDP_RDP_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_MDP_RDP_IDLE_WD_TO_MASK \ + 0x00000002 /* EN_MDP_RDP_IDLE_WD_TO[1] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_MDP_RDP_IDLE_WD_TO_SHFT 1 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_TDP_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_TDP_IDLE_WD_TO_MASK \ + 0x00000001 /* EN_BN0_MDP_TDP_IDLE_WD_TO[0] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_TDP_IDLE_WD_TO_SHFT 0 + +/* +* ---ERLY_TRM_CTRL0 (0x820C0000 + 0xf8)--- +* ERLY_TRM_EN[0] - (RW) Enable control of early terminate +function +* RESERVED1[7..1] - (RO) Reserved bits +* ERLY_TRM_MPDU_TH_0[15..8] - (RW) MPDU number Threshold for TX Bit Rate <= +97.5Mbps +* ERLY_TRM_MPDU_TH_1[23..16] - (RW) MPDU number Threshold for 97.5Mbps < TX +* Bit Rate <= 195Mbps +* ERLY_TRM_MPDU_TH_2[31..24] - (RW) MPDU number Threshold for TX Bit Rate <= +97.5Mbps +*/ +#define WF_PLE_TOP_ERLY_TRM_CTRL0_ERLY_TRM_MPDU_TH_2_ADDR \ + WF_PLE_TOP_ERLY_TRM_CTRL0_ADDR +#define WF_PLE_TOP_ERLY_TRM_CTRL0_ERLY_TRM_MPDU_TH_2_MASK \ + 0xFF000000 /* ERLY_TRM_MPDU_TH_2[31..24] */ +#define WF_PLE_TOP_ERLY_TRM_CTRL0_ERLY_TRM_MPDU_TH_2_SHFT 24 +#define WF_PLE_TOP_ERLY_TRM_CTRL0_ERLY_TRM_MPDU_TH_1_ADDR \ + WF_PLE_TOP_ERLY_TRM_CTRL0_ADDR +#define WF_PLE_TOP_ERLY_TRM_CTRL0_ERLY_TRM_MPDU_TH_1_MASK \ + 0x00FF0000 /* ERLY_TRM_MPDU_TH_1[23..16] */ +#define WF_PLE_TOP_ERLY_TRM_CTRL0_ERLY_TRM_MPDU_TH_1_SHFT 16 +#define WF_PLE_TOP_ERLY_TRM_CTRL0_ERLY_TRM_MPDU_TH_0_ADDR \ + WF_PLE_TOP_ERLY_TRM_CTRL0_ADDR +#define WF_PLE_TOP_ERLY_TRM_CTRL0_ERLY_TRM_MPDU_TH_0_MASK \ + 0x0000FF00 /* ERLY_TRM_MPDU_TH_0[15..8] */ +#define WF_PLE_TOP_ERLY_TRM_CTRL0_ERLY_TRM_MPDU_TH_0_SHFT 8 +#define WF_PLE_TOP_ERLY_TRM_CTRL0_ERLY_TRM_EN_ADDR \ + WF_PLE_TOP_ERLY_TRM_CTRL0_ADDR +#define WF_PLE_TOP_ERLY_TRM_CTRL0_ERLY_TRM_EN_MASK \ + 0x00000001 /* ERLY_TRM_EN[0] */ +#define WF_PLE_TOP_ERLY_TRM_CTRL0_ERLY_TRM_EN_SHFT 0 + +/* +* ---ERLY_TRM_CTRL1 (0x820C0000 + 0xfc)--- +* ERLY_TRM_MPDU_TH_3[7..0] - (RW) MPDU number Threshold for 325Mbps < TX +* Bit Rate <= 433Mbps +* ERLY_TRM_MPDU_TH_4[15..8] - (RW) MPDU number Threshold for 433Mbps < TX +* Bit Rate <= 866.7Mbps +* ERLY_TRM_MPDU_TH_5[23..16] - (RW) MPDU number Threshold for 866.7Mbps < TX +* Bit Rate <= 1300Mbps +* ERLY_TRM_MPDU_TH_6[31..24] - (RW) MPDU number Threshold for TX Bit Rate <= +97.5Mbps +*/ +#define WF_PLE_TOP_ERLY_TRM_CTRL1_ERLY_TRM_MPDU_TH_6_ADDR \ + WF_PLE_TOP_ERLY_TRM_CTRL1_ADDR +#define WF_PLE_TOP_ERLY_TRM_CTRL1_ERLY_TRM_MPDU_TH_6_MASK \ + 0xFF000000 /* ERLY_TRM_MPDU_TH_6[31..24] */ +#define WF_PLE_TOP_ERLY_TRM_CTRL1_ERLY_TRM_MPDU_TH_6_SHFT 24 +#define WF_PLE_TOP_ERLY_TRM_CTRL1_ERLY_TRM_MPDU_TH_5_ADDR \ + WF_PLE_TOP_ERLY_TRM_CTRL1_ADDR +#define WF_PLE_TOP_ERLY_TRM_CTRL1_ERLY_TRM_MPDU_TH_5_MASK \ + 0x00FF0000 /* ERLY_TRM_MPDU_TH_5[23..16] */ +#define WF_PLE_TOP_ERLY_TRM_CTRL1_ERLY_TRM_MPDU_TH_5_SHFT 16 +#define WF_PLE_TOP_ERLY_TRM_CTRL1_ERLY_TRM_MPDU_TH_4_ADDR \ + WF_PLE_TOP_ERLY_TRM_CTRL1_ADDR +#define WF_PLE_TOP_ERLY_TRM_CTRL1_ERLY_TRM_MPDU_TH_4_MASK \ + 0x0000FF00 /* ERLY_TRM_MPDU_TH_4[15..8] */ +#define WF_PLE_TOP_ERLY_TRM_CTRL1_ERLY_TRM_MPDU_TH_4_SHFT 8 +#define WF_PLE_TOP_ERLY_TRM_CTRL1_ERLY_TRM_MPDU_TH_3_ADDR \ + WF_PLE_TOP_ERLY_TRM_CTRL1_ADDR +#define WF_PLE_TOP_ERLY_TRM_CTRL1_ERLY_TRM_MPDU_TH_3_MASK \ + 0x000000FF /* ERLY_TRM_MPDU_TH_3[7..0] */ +#define WF_PLE_TOP_ERLY_TRM_CTRL1_ERLY_TRM_MPDU_TH_3_SHFT 0 + +/* +* ---STATION_PAUSE0 (0x820C0000 + 0x100)--- +* STATION_PAUSE_0[31..0] - (RW) SW can stop station TX by this setting +* for STA0~STA31. +*/ +#define WF_PLE_TOP_STATION_PAUSE0_STATION_PAUSE_0_ADDR \ + WF_PLE_TOP_STATION_PAUSE0_ADDR +#define WF_PLE_TOP_STATION_PAUSE0_STATION_PAUSE_0_MASK \ + 0xFFFFFFFF /* STATION_PAUSE_0[31..0] */ +#define WF_PLE_TOP_STATION_PAUSE0_STATION_PAUSE_0_SHFT 0 + +/* +* ---STATION_PAUSE1 (0x820C0000 + 0x104)--- +* STATION_PAUSE_1[31..0] - (RW) SW can stop station TX by this setting +* for STA32~STA63. +*/ +#define WF_PLE_TOP_STATION_PAUSE1_STATION_PAUSE_1_ADDR \ + WF_PLE_TOP_STATION_PAUSE1_ADDR +#define WF_PLE_TOP_STATION_PAUSE1_STATION_PAUSE_1_MASK \ + 0xFFFFFFFF /* STATION_PAUSE_1[31..0] */ +#define WF_PLE_TOP_STATION_PAUSE1_STATION_PAUSE_1_SHFT 0 + +/* +* ---DIS_STA_MAP0 (0x820C0000 + 0x140)--- +* DIS_STA_MAP_0[31..0] - (RW) Disable map for STA 0~31 TX +*/ +#define WF_PLE_TOP_DIS_STA_MAP0_DIS_STA_MAP_0_ADDR WF_PLE_TOP_DIS_STA_MAP0_ADDR +#define WF_PLE_TOP_DIS_STA_MAP0_DIS_STA_MAP_0_MASK \ + 0xFFFFFFFF /* DIS_STA_MAP_0[31..0] */ +#define WF_PLE_TOP_DIS_STA_MAP0_DIS_STA_MAP_0_SHFT 0 + +/* +* ---DIS_STA_MAP1 (0x820C0000 + 0x144)--- +* DIS_STA_MAP_1[31..0] - (RW) Disable map for STA 32~63 TX +*/ +#define WF_PLE_TOP_DIS_STA_MAP1_DIS_STA_MAP_1_ADDR WF_PLE_TOP_DIS_STA_MAP1_ADDR +#define WF_PLE_TOP_DIS_STA_MAP1_DIS_STA_MAP_1_MASK \ + 0xFFFFFFFF /* DIS_STA_MAP_1[31..0] */ +#define WF_PLE_TOP_DIS_STA_MAP1_DIS_STA_MAP_1_SHFT 0 + +/* +* ---STATION_REDIR0 (0x820C0000 + 0x180)--- +* STATION_REDIR_0[31..0] - (RW) SW can redirection to designed +* port/queue by this setting for STA0~STA31. +*/ +#define WF_PLE_TOP_STATION_REDIR0_STATION_REDIR_0_ADDR \ + WF_PLE_TOP_STATION_REDIR0_ADDR +#define WF_PLE_TOP_STATION_REDIR0_STATION_REDIR_0_MASK \ + 0xFFFFFFFF /* STATION_REDIR_0[31..0] */ +#define WF_PLE_TOP_STATION_REDIR0_STATION_REDIR_0_SHFT 0 + +/* +* ---STATION_REDIR1 (0x820C0000 + 0x184)--- +* STATION_REDIR_1[31..0] - (RW) SW can redirection to designed +* port/queue by this setting for STA32~STA63. +*/ +#define WF_PLE_TOP_STATION_REDIR1_STATION_REDIR_1_ADDR \ + WF_PLE_TOP_STATION_REDIR1_ADDR +#define WF_PLE_TOP_STATION_REDIR1_STATION_REDIR_1_MASK \ + 0xFFFFFFFF /* STATION_REDIR_1[31..0] */ +#define WF_PLE_TOP_STATION_REDIR1_STATION_REDIR_1_SHFT 0 + +/* +* ---TWT_STA_MAP0 (0x820C0000 + 0x1C0)--- +* TWT_STA_MAP_0[31..0] - (RW) TWT map for STA 0~31 TX +*/ +#define WF_PLE_TOP_TWT_STA_MAP0_TWT_STA_MAP_0_ADDR WF_PLE_TOP_TWT_STA_MAP0_ADDR +#define WF_PLE_TOP_TWT_STA_MAP0_TWT_STA_MAP_0_MASK \ + 0xFFFFFFFF /* TWT_STA_MAP_0[31..0] */ +#define WF_PLE_TOP_TWT_STA_MAP0_TWT_STA_MAP_0_SHFT 0 + +/* +* ---TWT_STA_MAP1 (0x820C0000 + 0x1C4)--- +* TWT_STA_MAP_1[31..0] - (RW) TWT map for STA 32~63 TX +*/ +#define WF_PLE_TOP_TWT_STA_MAP1_TWT_STA_MAP_1_ADDR WF_PLE_TOP_TWT_STA_MAP1_ADDR +#define WF_PLE_TOP_TWT_STA_MAP1_TWT_STA_MAP_1_MASK \ + 0xFFFFFFFF /* TWT_STA_MAP_1[31..0] */ +#define WF_PLE_TOP_TWT_STA_MAP1_TWT_STA_MAP_1_SHFT 0 + +/* +* ---TWT_TX_CTRL0 (0x820C0000 + 0x200)--- +* en_twt_stop_tx_ctrl_0[0] - (RW) Enable TWT non-active period TX control +function. +* en_twt_stop_tx_ctrl_1[1] - (RW) Enable TWT non-active period TX control +function. +* en_twt_stop_tx_ctrl_2[2] - (RW) Enable TWT non-active period TX control +function. +* en_twt_stop_tx_ctrl_3[3] - (RW) Enable TWT non-active period TX control +function. +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_3_ADDR \ + WF_PLE_TOP_TWT_TX_CTRL0_ADDR +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_3_MASK \ + 0x00000008 /* en_twt_stop_tx_ctrl_3[3] */ +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_3_SHFT 3 +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_2_ADDR \ + WF_PLE_TOP_TWT_TX_CTRL0_ADDR +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_2_MASK \ + 0x00000004 /* en_twt_stop_tx_ctrl_2[2] */ +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_2_SHFT 2 +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_1_ADDR \ + WF_PLE_TOP_TWT_TX_CTRL0_ADDR +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_1_MASK \ + 0x00000002 /* en_twt_stop_tx_ctrl_1[1] */ +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_1_SHFT 1 +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_0_ADDR \ + WF_PLE_TOP_TWT_TX_CTRL0_ADDR +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_0_MASK \ + 0x00000001 /* en_twt_stop_tx_ctrl_0[0] */ +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_0_SHFT 0 + +/* +* ---DRR_SPL_CTRL (0x820C0000 + 0x204)--- +* RESERVED0[15..0] - (RO) Reserved bits +* SUBRND_TIMES[19..16] - (RW) Subround times setting to trigger round +end +* EN_SBTG_RNDEND[20] - (RW) Enable control of round ends by subround +times +* EN_QLEN_TH[21] - (RW) Enable control of queue length +* constraint to select station +* RESERVED22[31..22] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_DRR_SPL_CTRL_EN_QLEN_TH_ADDR WF_PLE_TOP_DRR_SPL_CTRL_ADDR +#define WF_PLE_TOP_DRR_SPL_CTRL_EN_QLEN_TH_MASK 0x00200000 /* EN_QLEN_TH[21] */ +#define WF_PLE_TOP_DRR_SPL_CTRL_EN_QLEN_TH_SHFT 21 +#define WF_PLE_TOP_DRR_SPL_CTRL_EN_SBTG_RNDEND_ADDR WF_PLE_TOP_DRR_SPL_CTRL_ADDR +#define WF_PLE_TOP_DRR_SPL_CTRL_EN_SBTG_RNDEND_MASK \ + 0x00100000 /* EN_SBTG_RNDEND[20] */ +#define WF_PLE_TOP_DRR_SPL_CTRL_EN_SBTG_RNDEND_SHFT 20 +#define WF_PLE_TOP_DRR_SPL_CTRL_SUBRND_TIMES_ADDR WF_PLE_TOP_DRR_SPL_CTRL_ADDR +#define WF_PLE_TOP_DRR_SPL_CTRL_SUBRND_TIMES_MASK \ + 0x000F0000 /* SUBRND_TIMES[19..16] */ +#define WF_PLE_TOP_DRR_SPL_CTRL_SUBRND_TIMES_SHFT 16 + +/* +* ---BSS_DBDC_CTRL (0x820C0000 + 0x208)--- +* BSS_BAND_SEL[15..0] - (RW) Select band of each BSS +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_BSS_DBDC_CTRL_BSS_BAND_SEL_ADDR WF_PLE_TOP_BSS_DBDC_CTRL_ADDR +#define WF_PLE_TOP_BSS_DBDC_CTRL_BSS_BAND_SEL_MASK \ + 0x0000FFFF /* BSS_BAND_SEL[15..0] */ +#define WF_PLE_TOP_BSS_DBDC_CTRL_BSS_BAND_SEL_SHFT 0 + +/* +* ---VOW_CTRL1 (0x820C0000 + 0x20c)--- +* RESERVED0[0] - (RO) Reserved bits +* EN_BSSID_CHECK[1] - (RW) Enable control of check BSSID's trap +* state in search station +* EN_LOCK_STA[2] - (RW) Lock mode for RTS retry same sta until +* RTS drop +* EN_KEEP_QTM[3] - (RW) Not reset remain Tx time when sta has +* new packet +* EN_TXCNT_MODE[4] - (RW) Tx count weighted round robin control +* EN_TXED_MODE[5] - (RW) Txed bitmap control +* EN_RXSCH_MODE[6] - (RW) Rx scheduling with rx earlyend bitmap +control +* EN_BWRF_SRCH[7] - (RW) Bandwidth refill search control +* DIS_BSSID0_TRAP_IGNORE[8] - (RW) Disable control of the function that STA +* with BSSID0 trap ignore in TXQ busy +* DIS_BSSID1_TRAP_IGNORE[9] - (RW) Disable control of the function that STA +* with BSSID1 trap ignore in TXQ busy +* DIS_BSSID2_TRAP_IGNORE[10] - (RW) Disable control of the function that STA +* with BSSID2 trap ignore in TXQ busy +* DIS_BSSID3_TRAP_IGNORE[11] - (RW) Disable control of the function that STA +* with BSSID3 trap ignore in TXQ busy +* DIS_KEEP_TRGT_BSS[12] - (RW) Disable control of keeping BSS as target +* station when SPL search +* RESERVED13[31..13] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_VOW_CTRL1_DIS_KEEP_TRGT_BSS_ADDR WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_DIS_KEEP_TRGT_BSS_MASK \ + 0x00001000 /* DIS_KEEP_TRGT_BSS[12] */ +#define WF_PLE_TOP_VOW_CTRL1_DIS_KEEP_TRGT_BSS_SHFT 12 +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID3_TRAP_IGNORE_ADDR \ + WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID3_TRAP_IGNORE_MASK \ + 0x00000800 /* DIS_BSSID3_TRAP_IGNORE[11] */ +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID3_TRAP_IGNORE_SHFT 11 +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID2_TRAP_IGNORE_ADDR \ + WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID2_TRAP_IGNORE_MASK \ + 0x00000400 /* DIS_BSSID2_TRAP_IGNORE[10] */ +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID2_TRAP_IGNORE_SHFT 10 +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID1_TRAP_IGNORE_ADDR \ + WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID1_TRAP_IGNORE_MASK \ + 0x00000200 /* DIS_BSSID1_TRAP_IGNORE[9] */ +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID1_TRAP_IGNORE_SHFT 9 +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID0_TRAP_IGNORE_ADDR \ + WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID0_TRAP_IGNORE_MASK \ + 0x00000100 /* DIS_BSSID0_TRAP_IGNORE[8] */ +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID0_TRAP_IGNORE_SHFT 8 +#define WF_PLE_TOP_VOW_CTRL1_EN_BWRF_SRCH_ADDR WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_EN_BWRF_SRCH_MASK 0x00000080 /* EN_BWRF_SRCH[7] */ +#define WF_PLE_TOP_VOW_CTRL1_EN_BWRF_SRCH_SHFT 7 +#define WF_PLE_TOP_VOW_CTRL1_EN_RXSCH_MODE_ADDR WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_EN_RXSCH_MODE_MASK \ + 0x00000040 /* EN_RXSCH_MODE[6] */ +#define WF_PLE_TOP_VOW_CTRL1_EN_RXSCH_MODE_SHFT 6 +#define WF_PLE_TOP_VOW_CTRL1_EN_TXED_MODE_ADDR WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_EN_TXED_MODE_MASK 0x00000020 /* EN_TXED_MODE[5] */ +#define WF_PLE_TOP_VOW_CTRL1_EN_TXED_MODE_SHFT 5 +#define WF_PLE_TOP_VOW_CTRL1_EN_TXCNT_MODE_ADDR WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_EN_TXCNT_MODE_MASK \ + 0x00000010 /* EN_TXCNT_MODE[4] */ +#define WF_PLE_TOP_VOW_CTRL1_EN_TXCNT_MODE_SHFT 4 +#define WF_PLE_TOP_VOW_CTRL1_EN_KEEP_QTM_ADDR WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_EN_KEEP_QTM_MASK 0x00000008 /* EN_KEEP_QTM[3] */ +#define WF_PLE_TOP_VOW_CTRL1_EN_KEEP_QTM_SHFT 3 +#define WF_PLE_TOP_VOW_CTRL1_EN_LOCK_STA_ADDR WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_EN_LOCK_STA_MASK 0x00000004 /* EN_LOCK_STA[2] */ +#define WF_PLE_TOP_VOW_CTRL1_EN_LOCK_STA_SHFT 2 +#define WF_PLE_TOP_VOW_CTRL1_EN_BSSID_CHECK_ADDR WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_EN_BSSID_CHECK_MASK \ + 0x00000002 /* EN_BSSID_CHECK[1] */ +#define WF_PLE_TOP_VOW_CTRL1_EN_BSSID_CHECK_SHFT 1 + +/* +* ---TWT_STA_TABLE0 (0x820C0000 + 0x210)--- +* TWT_STA_0[9..0] - (RW) TWT station 0 WLAN ID +* RESERVED10[31..10] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TWT_STA_TABLE0_TWT_STA_0_ADDR WF_PLE_TOP_TWT_STA_TABLE0_ADDR +#define WF_PLE_TOP_TWT_STA_TABLE0_TWT_STA_0_MASK \ + 0x000003FF /* TWT_STA_0[9..0] */ +#define WF_PLE_TOP_TWT_STA_TABLE0_TWT_STA_0_SHFT 0 + +/* +* ---TWT_STA_TABLE1 (0x820C0000 + 0x214)--- +* TWT_STA_2[9..0] - (RW) TWT station 2 WLAN ID +* RESERVED10[31..10] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TWT_STA_TABLE1_TWT_STA_2_ADDR WF_PLE_TOP_TWT_STA_TABLE1_ADDR +#define WF_PLE_TOP_TWT_STA_TABLE1_TWT_STA_2_MASK \ + 0x000003FF /* TWT_STA_2[9..0] */ +#define WF_PLE_TOP_TWT_STA_TABLE1_TWT_STA_2_SHFT 0 + +/* +* ---TWT_STA_TABLE2 (0x820C0000 + 0x218)--- +* TWT_STA_4[9..0] - (RW) TWT station 4 WLAN ID +* RESERVED10[31..10] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TWT_STA_TABLE2_TWT_STA_4_ADDR WF_PLE_TOP_TWT_STA_TABLE2_ADDR +#define WF_PLE_TOP_TWT_STA_TABLE2_TWT_STA_4_MASK \ + 0x000003FF /* TWT_STA_4[9..0] */ +#define WF_PLE_TOP_TWT_STA_TABLE2_TWT_STA_4_SHFT 0 + +/* +* ---TWT_STA_TABLE3 (0x820C0000 + 0x21c)--- +* TWT_STA_6[9..0] - (RW) TWT station 6 WLAN ID +* RESERVED10[31..10] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TWT_STA_TABLE3_TWT_STA_6_ADDR WF_PLE_TOP_TWT_STA_TABLE3_ADDR +#define WF_PLE_TOP_TWT_STA_TABLE3_TWT_STA_6_MASK \ + 0x000003FF /* TWT_STA_6[9..0] */ +#define WF_PLE_TOP_TWT_STA_TABLE3_TWT_STA_6_SHFT 0 + +/* +* ---TWT_SW_CTRL (0x820C0000 + 0x220)--- +* INDEX[15..0] - (RW) Operation index +* Mode 0x00/0x01/0x08/0x09: Bit[3:0]: station +number +* Mode 0x10/0x11: Bit[3:0]: table index +* MODE[23..16] - (RW) IO software command mode +* TWT_STA_FIX_AC_EN[24] - (RW) Enable TWT station fix AC function +* RESERVED25[29..25] - (RO) Reserved bits +* SRCH_CMD_DROP[30] - (W1C) IO search command drop flag due to +* command FIFO full +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TWT_SW_CTRL_SRCH_CMD_DROP_ADDR WF_PLE_TOP_TWT_SW_CTRL_ADDR +#define WF_PLE_TOP_TWT_SW_CTRL_SRCH_CMD_DROP_MASK \ + 0x40000000 /* SRCH_CMD_DROP[30] */ +#define WF_PLE_TOP_TWT_SW_CTRL_SRCH_CMD_DROP_SHFT 30 +#define WF_PLE_TOP_TWT_SW_CTRL_TWT_STA_FIX_AC_EN_ADDR \ + WF_PLE_TOP_TWT_SW_CTRL_ADDR +#define WF_PLE_TOP_TWT_SW_CTRL_TWT_STA_FIX_AC_EN_MASK \ + 0x01000000 /* TWT_STA_FIX_AC_EN[24] */ +#define WF_PLE_TOP_TWT_SW_CTRL_TWT_STA_FIX_AC_EN_SHFT 24 +#define WF_PLE_TOP_TWT_SW_CTRL_MODE_ADDR WF_PLE_TOP_TWT_SW_CTRL_ADDR +#define WF_PLE_TOP_TWT_SW_CTRL_MODE_MASK 0x00FF0000 /* MODE[23..16] */ +#define WF_PLE_TOP_TWT_SW_CTRL_MODE_SHFT 16 +#define WF_PLE_TOP_TWT_SW_CTRL_INDEX_ADDR WF_PLE_TOP_TWT_SW_CTRL_ADDR +#define WF_PLE_TOP_TWT_SW_CTRL_INDEX_MASK 0x0000FFFF /* INDEX[15..0] */ +#define WF_PLE_TOP_TWT_SW_CTRL_INDEX_SHFT 0 + +/* +* ---TWT_HW_SRCHCMD_FULL (0x820C0000 + 0x224)--- +* TWT_SRCH_DL_FULL[0] - (RW) TWT hardware downlink search command +* full flag +* RESERVED1[31..1] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TWT_HW_SRCHCMD_FULL_TWT_SRCH_DL_FULL_ADDR \ + WF_PLE_TOP_TWT_HW_SRCHCMD_FULL_ADDR +#define WF_PLE_TOP_TWT_HW_SRCHCMD_FULL_TWT_SRCH_DL_FULL_MASK \ + 0x00000001 /* TWT_SRCH_DL_FULL[0] */ +#define WF_PLE_TOP_TWT_HW_SRCHCMD_FULL_TWT_SRCH_DL_FULL_SHFT 0 + +/* +* ---DRR_SW_CTRL (0x820C0000 + 0x228)--- +* INDEX[15..0] - (RW) Operation index +* Mode 0x00: Bit[15:12]: QID, Bit[9:0]: wlan +ID +* Mode 0x01: Bit[15:12]: QID, Bit[9:0]: wlan +ID +* Mode 0x10: Bit[3:0]: QID +* Mode 0x11: Bit[3:0]: QID +* MODE[23..16] - (RW) IO software command mode +* RESERVED24[29..24] - (RO) Reserved bits +* SRCH_CMD_DROP[30] - (W1C) IO search command drop flag due to +* command FIFO full +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_DRR_SW_CTRL_SRCH_CMD_DROP_ADDR WF_PLE_TOP_DRR_SW_CTRL_ADDR +#define WF_PLE_TOP_DRR_SW_CTRL_SRCH_CMD_DROP_MASK \ + 0x40000000 /* SRCH_CMD_DROP[30] */ +#define WF_PLE_TOP_DRR_SW_CTRL_SRCH_CMD_DROP_SHFT 30 +#define WF_PLE_TOP_DRR_SW_CTRL_MODE_ADDR WF_PLE_TOP_DRR_SW_CTRL_ADDR +#define WF_PLE_TOP_DRR_SW_CTRL_MODE_MASK 0x00FF0000 /* MODE[23..16] */ +#define WF_PLE_TOP_DRR_SW_CTRL_MODE_SHFT 16 +#define WF_PLE_TOP_DRR_SW_CTRL_INDEX_ADDR WF_PLE_TOP_DRR_SW_CTRL_ADDR +#define WF_PLE_TOP_DRR_SW_CTRL_INDEX_MASK 0x0000FFFF /* INDEX[15..0] */ +#define WF_PLE_TOP_DRR_SW_CTRL_INDEX_SHFT 0 + +/* +* ---DRR_SPL_CTRL_1 (0x820C0000 + 0x22c)--- +* RESERVED0[16..0] - (RO) Reserved bits +* EN_BWCHRG_ORIG[17] - (RW) BW charge original scheme enable control +* RESERVED18[31..18] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_BWCHRG_ORIG_ADDR \ + WF_PLE_TOP_DRR_SPL_CTRL_1_ADDR +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_BWCHRG_ORIG_MASK \ + 0x00020000 /* EN_BWCHRG_ORIG[17] */ +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_BWCHRG_ORIG_SHFT 17 + +/* +* ---TWT_STA_FIX_AC (0x820C0000 + 0x234)--- +* DL_TWT_STA0_FIX_AC[1..0] - (RW) DL TWT station 0 fix AC setting +* DL_TWT_STA1_FIX_AC[3..2] - (RW) DL TWT station 1 fix AC setting +* DL_TWT_STA2_FIX_AC[5..4] - (RW) DL TWT station 2 fix AC setting +* DL_TWT_STA3_FIX_AC[7..6] - (RW) DL TWT station 3 fix AC setting +* DL_TWT_STA4_FIX_AC[9..8] - (RW) DL TWT station 4 fix AC setting +* DL_TWT_STA5_FIX_AC[11..10] - (RW) DL TWT station 5 fix AC setting +* DL_TWT_STA6_FIX_AC[13..12] - (RW) DL TWT station 6 fix AC setting +* DL_TWT_STA7_FIX_AC[15..14] - (RW) DL TWT station 7 fix AC setting +* UL_TWT_STA0_FIX_AC[17..16] - (RW) UL TWT station 0 fix AC setting +* UL_TWT_STA1_FIX_AC[19..18] - (RW) UL TWT station 1 fix AC setting +* UL_TWT_STA2_FIX_AC[21..20] - (RW) UL TWT station 2 fix AC setting +* UL_TWT_STA3_FIX_AC[23..22] - (RW) UL TWT station 3 fix AC setting +* UL_TWT_STA4_FIX_AC[25..24] - (RW) UL TWT station 4 fix AC setting +* UL_TWT_STA5_FIX_AC[27..26] - (RW) UL TWT station 5 fix AC setting +* UL_TWT_STA6_FIX_AC[29..28] - (RW) UL TWT station 6 fix AC setting +* RESERVED30[31..30] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TWT_STA_FIX_AC_UL_TWT_STA6_FIX_AC_ADDR \ + WF_PLE_TOP_TWT_STA_FIX_AC_ADDR +#define WF_PLE_TOP_TWT_STA_FIX_AC_UL_TWT_STA6_FIX_AC_MASK \ + 0x30000000 /* UL_TWT_STA6_FIX_AC[29..28] */ +#define WF_PLE_TOP_TWT_STA_FIX_AC_UL_TWT_STA6_FIX_AC_SHFT 28 +#define WF_PLE_TOP_TWT_STA_FIX_AC_UL_TWT_STA5_FIX_AC_ADDR \ + WF_PLE_TOP_TWT_STA_FIX_AC_ADDR +#define WF_PLE_TOP_TWT_STA_FIX_AC_UL_TWT_STA5_FIX_AC_MASK \ + 0x0C000000 /* UL_TWT_STA5_FIX_AC[27..26] */ +#define WF_PLE_TOP_TWT_STA_FIX_AC_UL_TWT_STA5_FIX_AC_SHFT 26 +#define WF_PLE_TOP_TWT_STA_FIX_AC_UL_TWT_STA4_FIX_AC_ADDR \ + WF_PLE_TOP_TWT_STA_FIX_AC_ADDR +#define WF_PLE_TOP_TWT_STA_FIX_AC_UL_TWT_STA4_FIX_AC_MASK \ + 0x03000000 /* UL_TWT_STA4_FIX_AC[25..24] */ +#define WF_PLE_TOP_TWT_STA_FIX_AC_UL_TWT_STA4_FIX_AC_SHFT 24 +#define WF_PLE_TOP_TWT_STA_FIX_AC_UL_TWT_STA3_FIX_AC_ADDR \ + WF_PLE_TOP_TWT_STA_FIX_AC_ADDR +#define WF_PLE_TOP_TWT_STA_FIX_AC_UL_TWT_STA3_FIX_AC_MASK \ + 0x00C00000 /* UL_TWT_STA3_FIX_AC[23..22] */ +#define WF_PLE_TOP_TWT_STA_FIX_AC_UL_TWT_STA3_FIX_AC_SHFT 22 +#define WF_PLE_TOP_TWT_STA_FIX_AC_UL_TWT_STA2_FIX_AC_ADDR \ + WF_PLE_TOP_TWT_STA_FIX_AC_ADDR +#define WF_PLE_TOP_TWT_STA_FIX_AC_UL_TWT_STA2_FIX_AC_MASK \ + 0x00300000 /* UL_TWT_STA2_FIX_AC[21..20] */ +#define WF_PLE_TOP_TWT_STA_FIX_AC_UL_TWT_STA2_FIX_AC_SHFT 20 +#define WF_PLE_TOP_TWT_STA_FIX_AC_UL_TWT_STA1_FIX_AC_ADDR \ + WF_PLE_TOP_TWT_STA_FIX_AC_ADDR +#define WF_PLE_TOP_TWT_STA_FIX_AC_UL_TWT_STA1_FIX_AC_MASK \ + 0x000C0000 /* UL_TWT_STA1_FIX_AC[19..18] */ +#define WF_PLE_TOP_TWT_STA_FIX_AC_UL_TWT_STA1_FIX_AC_SHFT 18 +#define WF_PLE_TOP_TWT_STA_FIX_AC_UL_TWT_STA0_FIX_AC_ADDR \ + WF_PLE_TOP_TWT_STA_FIX_AC_ADDR +#define WF_PLE_TOP_TWT_STA_FIX_AC_UL_TWT_STA0_FIX_AC_MASK \ + 0x00030000 /* UL_TWT_STA0_FIX_AC[17..16] */ +#define WF_PLE_TOP_TWT_STA_FIX_AC_UL_TWT_STA0_FIX_AC_SHFT 16 +#define WF_PLE_TOP_TWT_STA_FIX_AC_DL_TWT_STA7_FIX_AC_ADDR \ + WF_PLE_TOP_TWT_STA_FIX_AC_ADDR +#define WF_PLE_TOP_TWT_STA_FIX_AC_DL_TWT_STA7_FIX_AC_MASK \ + 0x0000C000 /* DL_TWT_STA7_FIX_AC[15..14] */ +#define WF_PLE_TOP_TWT_STA_FIX_AC_DL_TWT_STA7_FIX_AC_SHFT 14 +#define WF_PLE_TOP_TWT_STA_FIX_AC_DL_TWT_STA6_FIX_AC_ADDR \ + WF_PLE_TOP_TWT_STA_FIX_AC_ADDR +#define WF_PLE_TOP_TWT_STA_FIX_AC_DL_TWT_STA6_FIX_AC_MASK \ + 0x00003000 /* DL_TWT_STA6_FIX_AC[13..12] */ +#define WF_PLE_TOP_TWT_STA_FIX_AC_DL_TWT_STA6_FIX_AC_SHFT 12 +#define WF_PLE_TOP_TWT_STA_FIX_AC_DL_TWT_STA5_FIX_AC_ADDR \ + WF_PLE_TOP_TWT_STA_FIX_AC_ADDR +#define WF_PLE_TOP_TWT_STA_FIX_AC_DL_TWT_STA5_FIX_AC_MASK \ + 0x00000C00 /* DL_TWT_STA5_FIX_AC[11..10] */ +#define WF_PLE_TOP_TWT_STA_FIX_AC_DL_TWT_STA5_FIX_AC_SHFT 10 +#define WF_PLE_TOP_TWT_STA_FIX_AC_DL_TWT_STA4_FIX_AC_ADDR \ + WF_PLE_TOP_TWT_STA_FIX_AC_ADDR +#define WF_PLE_TOP_TWT_STA_FIX_AC_DL_TWT_STA4_FIX_AC_MASK \ + 0x00000300 /* DL_TWT_STA4_FIX_AC[9..8] */ +#define WF_PLE_TOP_TWT_STA_FIX_AC_DL_TWT_STA4_FIX_AC_SHFT 8 +#define WF_PLE_TOP_TWT_STA_FIX_AC_DL_TWT_STA3_FIX_AC_ADDR \ + WF_PLE_TOP_TWT_STA_FIX_AC_ADDR +#define WF_PLE_TOP_TWT_STA_FIX_AC_DL_TWT_STA3_FIX_AC_MASK \ + 0x000000C0 /* DL_TWT_STA3_FIX_AC[7..6] */ +#define WF_PLE_TOP_TWT_STA_FIX_AC_DL_TWT_STA3_FIX_AC_SHFT 6 +#define WF_PLE_TOP_TWT_STA_FIX_AC_DL_TWT_STA2_FIX_AC_ADDR \ + WF_PLE_TOP_TWT_STA_FIX_AC_ADDR +#define WF_PLE_TOP_TWT_STA_FIX_AC_DL_TWT_STA2_FIX_AC_MASK \ + 0x00000030 /* DL_TWT_STA2_FIX_AC[5..4] */ +#define WF_PLE_TOP_TWT_STA_FIX_AC_DL_TWT_STA2_FIX_AC_SHFT 4 +#define WF_PLE_TOP_TWT_STA_FIX_AC_DL_TWT_STA1_FIX_AC_ADDR \ + WF_PLE_TOP_TWT_STA_FIX_AC_ADDR +#define WF_PLE_TOP_TWT_STA_FIX_AC_DL_TWT_STA1_FIX_AC_MASK \ + 0x0000000C /* DL_TWT_STA1_FIX_AC[3..2] */ +#define WF_PLE_TOP_TWT_STA_FIX_AC_DL_TWT_STA1_FIX_AC_SHFT 2 +#define WF_PLE_TOP_TWT_STA_FIX_AC_DL_TWT_STA0_FIX_AC_ADDR \ + WF_PLE_TOP_TWT_STA_FIX_AC_ADDR +#define WF_PLE_TOP_TWT_STA_FIX_AC_DL_TWT_STA0_FIX_AC_MASK \ + 0x00000003 /* DL_TWT_STA0_FIX_AC[1..0] */ +#define WF_PLE_TOP_TWT_STA_FIX_AC_DL_TWT_STA0_FIX_AC_SHFT 0 + +/* +* ---EN_UMAC_L1_DCM (0x820C0000 + 0x238)--- +* UMAC_DCM_KEEP_HIGH_SPEED[0] - (RW) UMAC L1 DCM control +* RESERVED1[22..1] - (RO) Reserved bits +* DCM_IDLE_CNT_DOWN_UNIT[23] - (RW) UMAC L1 DCM idle count down time unit +select. +* DCM_IDLE_CNT_DOWN_VALUE[31..24] - (RW) UMAC L1 DCM idle count down value. +*/ +#define WF_PLE_TOP_EN_UMAC_L1_DCM_DCM_IDLE_CNT_DOWN_VALUE_ADDR \ + WF_PLE_TOP_EN_UMAC_L1_DCM_ADDR +#define WF_PLE_TOP_EN_UMAC_L1_DCM_DCM_IDLE_CNT_DOWN_VALUE_MASK \ + 0xFF000000 /* DCM_IDLE_CNT_DOWN_VALUE[31..24] */ +#define WF_PLE_TOP_EN_UMAC_L1_DCM_DCM_IDLE_CNT_DOWN_VALUE_SHFT 24 +#define WF_PLE_TOP_EN_UMAC_L1_DCM_DCM_IDLE_CNT_DOWN_UNIT_ADDR \ + WF_PLE_TOP_EN_UMAC_L1_DCM_ADDR +#define WF_PLE_TOP_EN_UMAC_L1_DCM_DCM_IDLE_CNT_DOWN_UNIT_MASK \ + 0x00800000 /* DCM_IDLE_CNT_DOWN_UNIT[23] */ +#define WF_PLE_TOP_EN_UMAC_L1_DCM_DCM_IDLE_CNT_DOWN_UNIT_SHFT 23 +#define WF_PLE_TOP_EN_UMAC_L1_DCM_UMAC_DCM_KEEP_HIGH_SPEED_ADDR \ + WF_PLE_TOP_EN_UMAC_L1_DCM_ADDR +#define WF_PLE_TOP_EN_UMAC_L1_DCM_UMAC_DCM_KEEP_HIGH_SPEED_MASK \ + 0x00000001 /* UMAC_DCM_KEEP_HIGH_SPEED[0] */ +#define WF_PLE_TOP_EN_UMAC_L1_DCM_UMAC_DCM_KEEP_HIGH_SPEED_SHFT 0 + +/* +* ---PCIE_POWER_CTRL (0x820C0000 + 0x23c)--- +* DIS_UMAC_PCIE_POWER_CTRL[11..0] - (RW) MAC PCIE power control. +* RESERVED12[30..12] - (RO) Reserved bits +* EN_UMAC_PCIE_POWER_CTRL_GLO[31] - (RW) MAC PCIE power global control. +*/ +#define WF_PLE_TOP_PCIE_POWER_CTRL_EN_UMAC_PCIE_POWER_CTRL_GLO_ADDR \ + WF_PLE_TOP_PCIE_POWER_CTRL_ADDR +#define WF_PLE_TOP_PCIE_POWER_CTRL_EN_UMAC_PCIE_POWER_CTRL_GLO_MASK \ + 0x80000000 /* EN_UMAC_PCIE_POWER_CTRL_GLO[31] */ +#define WF_PLE_TOP_PCIE_POWER_CTRL_EN_UMAC_PCIE_POWER_CTRL_GLO_SHFT 31 +#define WF_PLE_TOP_PCIE_POWER_CTRL_DIS_UMAC_PCIE_POWER_CTRL_ADDR \ + WF_PLE_TOP_PCIE_POWER_CTRL_ADDR +#define WF_PLE_TOP_PCIE_POWER_CTRL_DIS_UMAC_PCIE_POWER_CTRL_MASK \ + 0x00000FFF /* DIS_UMAC_PCIE_POWER_CTRL[11..0] */ +#define WF_PLE_TOP_PCIE_POWER_CTRL_DIS_UMAC_PCIE_POWER_CTRL_SHFT 0 + +/* +* ---TIMEOUT_CTRL (0x820C0000 + 0x280)--- +* RESERVED0[7..0] - (RO) Reserved bits +* HOST_REPORT_TO_CTRL[15..8] - (RW) HOST report timeout control register +* APB_WD_TO_CTRL[23..16] - (RW) APB pready watch dog timeout control +register +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TIMEOUT_CTRL_APB_WD_TO_CTRL_ADDR WF_PLE_TOP_TIMEOUT_CTRL_ADDR +#define WF_PLE_TOP_TIMEOUT_CTRL_APB_WD_TO_CTRL_MASK \ + 0x00FF0000 /* APB_WD_TO_CTRL[23..16] */ +#define WF_PLE_TOP_TIMEOUT_CTRL_APB_WD_TO_CTRL_SHFT 16 +#define WF_PLE_TOP_TIMEOUT_CTRL_HOST_REPORT_TO_CTRL_ADDR \ + WF_PLE_TOP_TIMEOUT_CTRL_ADDR +#define WF_PLE_TOP_TIMEOUT_CTRL_HOST_REPORT_TO_CTRL_MASK \ + 0x0000FF00 /* HOST_REPORT_TO_CTRL[15..8] */ +#define WF_PLE_TOP_TIMEOUT_CTRL_HOST_REPORT_TO_CTRL_SHFT 8 + +/* +* ---PLE_FUNC_CTRL_0 (0x820C0000 + 0x284)--- +* MACTX_REQ_DEASSERT[0] - (RW) Enable of DeAsser MACTX REQ.(Normal +* operation must be zero.) +* MACTX_ABORT_DEASSERT[1] - (RW) Enable of DeAsser MACTX ABORT.(Normal +* operation must be zero.) +* MPDU_DONE_CNT_IN_NO_TX_REQ[2] - (RW) MPDU done mode for LMAC no TX request +* MPDU_DONE_CNT_IN_NO_ADD[3] - (RW) MPDU done mode for LMAC no add +* ACK_LMAC_NO_FID_ADD[4] - (RW) MACTX ack mode for LMAC no add any fid +* for TX +* RESERVED5[5] - (RO) Reserved bits +* DIS_STA_RLS_TO_1F[6] - (RW) Release port setting of disable STA +function +* RESERVED7[7] - (RO) Reserved bits +* MACTX_REQ_ASSERT[8] - (RW) Enable of Asser MACTX REQ.(Normal +* operation must be zero.) +* MACTX_ABORT_ASSERT[9] - (RW) Enable of Asser MACTX ABORT.(Normal +* operation must be zero.) +* RESERVED10[21..10] - (RO) Reserved bits +* DIS_AUTORATE_TXP_REQ[22] - (RW) Disable auto rate TXP request function +* LATER_PKT_PRE_CUT_1US[23] - (RW) Pre cut 1us air time for later packet. +* TXP_REQ_CNTDOWN_TH[27..24] - (RW) Threshold of air time count down for TXP +request +* TXP_REQ_HSPEED_DL_NUM[29..28] - (RW) Packet number of high speed TXP request +* issue, by pre-cut more micro-second +* TXP_REQ_HSPEED_CUT_US[31..30] - (RW) Number of pre-cut micro-second for high +* speed packet +*/ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_HSPEED_CUT_US_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_HSPEED_CUT_US_MASK \ + 0xC0000000 /* TXP_REQ_HSPEED_CUT_US[31..30] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_HSPEED_CUT_US_SHFT 30 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_HSPEED_DL_NUM_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_HSPEED_DL_NUM_MASK \ + 0x30000000 /* TXP_REQ_HSPEED_DL_NUM[29..28] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_HSPEED_DL_NUM_SHFT 28 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_CNTDOWN_TH_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_CNTDOWN_TH_MASK \ + 0x0F000000 /* TXP_REQ_CNTDOWN_TH[27..24] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_CNTDOWN_TH_SHFT 24 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_LATER_PKT_PRE_CUT_1US_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_LATER_PKT_PRE_CUT_1US_MASK \ + 0x00800000 /* LATER_PKT_PRE_CUT_1US[23] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_LATER_PKT_PRE_CUT_1US_SHFT 23 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_DIS_AUTORATE_TXP_REQ_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_DIS_AUTORATE_TXP_REQ_MASK \ + 0x00400000 /* DIS_AUTORATE_TXP_REQ[22] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_DIS_AUTORATE_TXP_REQ_SHFT 22 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_ABORT_ASSERT_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_ABORT_ASSERT_MASK \ + 0x00000200 /* MACTX_ABORT_ASSERT[9] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_ABORT_ASSERT_SHFT 9 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_REQ_ASSERT_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_REQ_ASSERT_MASK \ + 0x00000100 /* MACTX_REQ_ASSERT[8] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_REQ_ASSERT_SHFT 8 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_DIS_STA_RLS_TO_1F_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_DIS_STA_RLS_TO_1F_MASK \ + 0x00000040 /* DIS_STA_RLS_TO_1F[6] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_DIS_STA_RLS_TO_1F_SHFT 6 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_ACK_LMAC_NO_FID_ADD_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_ACK_LMAC_NO_FID_ADD_MASK \ + 0x00000010 /* ACK_LMAC_NO_FID_ADD[4] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_ACK_LMAC_NO_FID_ADD_SHFT 4 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MPDU_DONE_CNT_IN_NO_ADD_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MPDU_DONE_CNT_IN_NO_ADD_MASK \ + 0x00000008 /* MPDU_DONE_CNT_IN_NO_ADD[3] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MPDU_DONE_CNT_IN_NO_ADD_SHFT 3 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MPDU_DONE_CNT_IN_NO_TX_REQ_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MPDU_DONE_CNT_IN_NO_TX_REQ_MASK \ + 0x00000004 /* MPDU_DONE_CNT_IN_NO_TX_REQ[2] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MPDU_DONE_CNT_IN_NO_TX_REQ_SHFT 2 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_ABORT_DEASSERT_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_ABORT_DEASSERT_MASK \ + 0x00000002 /* MACTX_ABORT_DEASSERT[1] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_ABORT_DEASSERT_SHFT 1 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_REQ_DEASSERT_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_REQ_DEASSERT_MASK \ + 0x00000001 /* MACTX_REQ_DEASSERT[0] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_REQ_DEASSERT_SHFT 0 + +/* +* ---PLE_FUNC_CTRL_1 (0x820C0000 + 0x288)--- +* RESERVED0[21..0] - (RO) Reserved bits +* PREDL_REQ_NORMAL_PRI[22] - (RW) Pre-download TXP request priority +control +* RESERVED23[31..23] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PLE_FUNC_CTRL_1_PREDL_REQ_NORMAL_PRI_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_1_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_1_PREDL_REQ_NORMAL_PRI_MASK \ + 0x00400000 /* PREDL_REQ_NORMAL_PRI[22] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_1_PREDL_REQ_NORMAL_PRI_SHFT 22 + +/* +* ---PORT_SER_CTRL (0x820C0000 + 0x290)--- +* EN_HIF_PORT_ALLOC_BLOCKING[0] - (RW) Enable HIF/AMSDU port allocate +* operation blocking. +* EN_CPU_PORT_ALLOC_BLOCKING[1] - (RW) Enable CPU port allocate operation +blocking. +* EN_WF_PORT_ALLOC_BLOCKING[2] - (RW) Enable LMAC port allocate operation +blocking. +* RESERVED3[7..3] - (RO) Reserved bits +* EN_HIF_PORT_D_OPR_BLOCKING[8] - (RW) Enable HIF/AMSDU/MDP/PREDL port data +* operation blocking. +* EN_CPU_PORT_D_OPR_BLOCKING[9] - (RW) Enable CPU port data operation +blocking. +* EN_WF_PORT_D_OPR_BLOCKING[10] - (RW) Enable LMAC port data operation +blocking. +* RESERVED11[15..11] - (RO) Reserved bits +* EN_HIF_PORT_Q_OPR_BLOCKING[16] - (RW) Enable HIF/AMSDU port queue operation +blocking. +* EN_CPU_PORT_Q_OPR_BLOCKING[17] - (RW) Enable CPU port queue operation +blocking. +* EN_WF_PORT_Q_OPR_BLOCKING[18] - (RW) Enable LMAC port queue operation +blocking. +* RESERVED19[31..19] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_Q_OPR_BLOCKING_ADDR \ + WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_Q_OPR_BLOCKING_MASK \ + 0x00040000 /* EN_WF_PORT_Q_OPR_BLOCKING[18] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_Q_OPR_BLOCKING_SHFT 18 +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_Q_OPR_BLOCKING_ADDR \ + WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_Q_OPR_BLOCKING_MASK \ + 0x00020000 /* EN_CPU_PORT_Q_OPR_BLOCKING[17] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_Q_OPR_BLOCKING_SHFT 17 +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_Q_OPR_BLOCKING_ADDR \ + WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_Q_OPR_BLOCKING_MASK \ + 0x00010000 /* EN_HIF_PORT_Q_OPR_BLOCKING[16] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_Q_OPR_BLOCKING_SHFT 16 +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_D_OPR_BLOCKING_ADDR \ + WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_D_OPR_BLOCKING_MASK \ + 0x00000400 /* EN_WF_PORT_D_OPR_BLOCKING[10] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_D_OPR_BLOCKING_SHFT 10 +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_D_OPR_BLOCKING_ADDR \ + WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_D_OPR_BLOCKING_MASK \ + 0x00000200 /* EN_CPU_PORT_D_OPR_BLOCKING[9] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_D_OPR_BLOCKING_SHFT 9 +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_D_OPR_BLOCKING_ADDR \ + WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_D_OPR_BLOCKING_MASK \ + 0x00000100 /* EN_HIF_PORT_D_OPR_BLOCKING[8] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_D_OPR_BLOCKING_SHFT 8 +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_ALLOC_BLOCKING_ADDR \ + WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_ALLOC_BLOCKING_MASK \ + 0x00000004 /* EN_WF_PORT_ALLOC_BLOCKING[2] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_ALLOC_BLOCKING_SHFT 2 +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_ALLOC_BLOCKING_ADDR \ + WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_ALLOC_BLOCKING_MASK \ + 0x00000002 /* EN_CPU_PORT_ALLOC_BLOCKING[1] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_ALLOC_BLOCKING_SHFT 1 +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_ALLOC_BLOCKING_ADDR \ + WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_ALLOC_BLOCKING_MASK \ + 0x00000001 /* EN_HIF_PORT_ALLOC_BLOCKING[0] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_ALLOC_BLOCKING_SHFT 0 + +/* +* ---MACTX_SER_CTRL (0x820C0000 + 0x294)--- +* EN_MACTX_G0_BLOCKING[0] - (RW) Enable MACTX group 0 operation +blocking. +* RESERVED1[7..1] - (RO) Reserved bits +* EN_MACTX_G1_BLOCKING[8] - (RW) Enable MACTX group 1 operation +blocking. +* RESERVED9[15..9] - (RO) Reserved bits +* EN_MACTX_G2_BLOCKING[16] - (RW) Enable MACTX group 2 operation blocking. +* RESERVED17[23..17] - (RO) Reserved bits +* EN_MACTX_G3_BLOCKING[24] - (RW) Enable MACTX group 3 operation blocking. +* RESERVED25[31..25] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G3_BLOCKING_ADDR \ + WF_PLE_TOP_MACTX_SER_CTRL_ADDR +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G3_BLOCKING_MASK \ + 0x01000000 /* EN_MACTX_G3_BLOCKING[24] */ +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G3_BLOCKING_SHFT 24 +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G2_BLOCKING_ADDR \ + WF_PLE_TOP_MACTX_SER_CTRL_ADDR +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G2_BLOCKING_MASK \ + 0x00010000 /* EN_MACTX_G2_BLOCKING[16] */ +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G2_BLOCKING_SHFT 16 +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G1_BLOCKING_ADDR \ + WF_PLE_TOP_MACTX_SER_CTRL_ADDR +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G1_BLOCKING_MASK \ + 0x00000100 /* EN_MACTX_G1_BLOCKING[8] */ +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G1_BLOCKING_SHFT 8 +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G0_BLOCKING_ADDR \ + WF_PLE_TOP_MACTX_SER_CTRL_ADDR +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G0_BLOCKING_MASK \ + 0x00000001 /* EN_MACTX_G0_BLOCKING[0] */ +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G0_BLOCKING_SHFT 0 + +/* +* ---DRR_SER_CTRL (0x820C0000 + 0x298)--- +* EN_DRR_CHARGE_BLOCKING[0] - (RW) Enable DRR charge operation blocking. +* RESERVED1[3..1] - (RO) Reserved bits +* EN_DRR_SRCH_0_BLOCKING[4] - (RW) Enable DRR search 0 operation blocking. +* EN_DRR_SRCH_1_BLOCKING[5] - (RW) Enable DRR search 1 operation blocking. +* RESERVED6[7..6] - (RO) Reserved bits +* EN_DRR_RDG_0_BLOCKING[8] - (RW) Enable DRR RDG 0 operation blocking. +* EN_DRR_RDG_1_BLOCKING[9] - (RW) Enable DRR RDG 1 operation blocking. +* RESERVED10[31..10] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_RDG_1_BLOCKING_ADDR \ + WF_PLE_TOP_DRR_SER_CTRL_ADDR +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_RDG_1_BLOCKING_MASK \ + 0x00000200 /* EN_DRR_RDG_1_BLOCKING[9] */ +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_RDG_1_BLOCKING_SHFT 9 +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_RDG_0_BLOCKING_ADDR \ + WF_PLE_TOP_DRR_SER_CTRL_ADDR +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_RDG_0_BLOCKING_MASK \ + 0x00000100 /* EN_DRR_RDG_0_BLOCKING[8] */ +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_RDG_0_BLOCKING_SHFT 8 +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_SRCH_1_BLOCKING_ADDR \ + WF_PLE_TOP_DRR_SER_CTRL_ADDR +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_SRCH_1_BLOCKING_MASK \ + 0x00000020 /* EN_DRR_SRCH_1_BLOCKING[5] */ +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_SRCH_1_BLOCKING_SHFT 5 +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_SRCH_0_BLOCKING_ADDR \ + WF_PLE_TOP_DRR_SER_CTRL_ADDR +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_SRCH_0_BLOCKING_MASK \ + 0x00000010 /* EN_DRR_SRCH_0_BLOCKING[4] */ +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_SRCH_0_BLOCKING_SHFT 4 +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_CHARGE_BLOCKING_ADDR \ + WF_PLE_TOP_DRR_SER_CTRL_ADDR +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_CHARGE_BLOCKING_MASK \ + 0x00000001 /* EN_DRR_CHARGE_BLOCKING[0] */ +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_CHARGE_BLOCKING_SHFT 0 + +/* +* ---INT_N9_STS (0x820C0000 + 0x300)--- +* CPU_Q0_NE[0] - (W1C) CPU queue 0 not empty interrupt status +* CPU_Q1_NE[1] - (W1C) CPU queue 1 not empty interrupt status +* CPU_Q2_NE[2] - (W1C) CPU queue 2 not empty interrupt status +* CPU_Q3_NE[3] - (W1C) CPU queue 3 not empty interrupt status +* RESERVED4[12..4] - (RO) Reserved bits +* ERROR_INT[13] - (RO) Error condition interrupt status, define +* by 0x28 +* ERROR_INT_1[14] - (RO) Error condition interrupt status 1, +* define by 0xd8 +* AMSDU_ERROR_INT[15] - (RO) HW AMSDU Error condition interrupt +* status, define by 0x1028 +* DATA_TOGGLE[16] - (W1C) Interrupt status of data toggle of N9 +* toggle register (0xf0) +* RESERVED17[17] - (RO) Reserved bits +* UMAC_SYSRAM_OUTRAN_ERROR_INT[18] - (W1C) Interrupt status of UMAC SYSRAM out +* range error +* RESERVED19[19] - (RO) Reserved bits +* AC_NONEMPTY_INT[20] - (W1C) AC queue empty fail interrupt status +* AC_EMPTY_INT[21] - (W1C) AC queue empty raise interrupt status +* AC_ENQ_LMAC_INT[22] - (W1C) AC enqueue interrupt status +* RESERVED23[23] - (RO) Reserved bits +* DBDC0_NONEMPTY_INT[24] - (W1C) DBDC0 queue empty fail interrupt status +* DBDC0_EMPTY_INT[25] - (W1C) DBDC0 queue empty raise interrupt +status +* DBDC0_ENQ_LMAC_INT[26] - (W1C) DBDC0 enqueue interrupt status +* RESERVED27[27] - (RO) Reserved bits +* DBDC1_NONEMPTY_INT[28] - (W1C) DBDC1 queue empty fail interrupt status +* DBDC1_EMPTY_INT[29] - (W1C) DBDC1 queue empty raise interrupt +status +* DBDC1_ENQ_LMAC_INT[30] - (W1C) DBDC1 enqueue interrupt status +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_INT_N9_STS_DBDC1_ENQ_LMAC_INT_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_DBDC1_ENQ_LMAC_INT_MASK \ + 0x40000000 /* DBDC1_ENQ_LMAC_INT[30] */ +#define WF_PLE_TOP_INT_N9_STS_DBDC1_ENQ_LMAC_INT_SHFT 30 +#define WF_PLE_TOP_INT_N9_STS_DBDC1_EMPTY_INT_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_DBDC1_EMPTY_INT_MASK \ + 0x20000000 /* DBDC1_EMPTY_INT[29] */ +#define WF_PLE_TOP_INT_N9_STS_DBDC1_EMPTY_INT_SHFT 29 +#define WF_PLE_TOP_INT_N9_STS_DBDC1_NONEMPTY_INT_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_DBDC1_NONEMPTY_INT_MASK \ + 0x10000000 /* DBDC1_NONEMPTY_INT[28] */ +#define WF_PLE_TOP_INT_N9_STS_DBDC1_NONEMPTY_INT_SHFT 28 +#define WF_PLE_TOP_INT_N9_STS_DBDC0_ENQ_LMAC_INT_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_DBDC0_ENQ_LMAC_INT_MASK \ + 0x04000000 /* DBDC0_ENQ_LMAC_INT[26] */ +#define WF_PLE_TOP_INT_N9_STS_DBDC0_ENQ_LMAC_INT_SHFT 26 +#define WF_PLE_TOP_INT_N9_STS_DBDC0_EMPTY_INT_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_DBDC0_EMPTY_INT_MASK \ + 0x02000000 /* DBDC0_EMPTY_INT[25] */ +#define WF_PLE_TOP_INT_N9_STS_DBDC0_EMPTY_INT_SHFT 25 +#define WF_PLE_TOP_INT_N9_STS_DBDC0_NONEMPTY_INT_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_DBDC0_NONEMPTY_INT_MASK \ + 0x01000000 /* DBDC0_NONEMPTY_INT[24] */ +#define WF_PLE_TOP_INT_N9_STS_DBDC0_NONEMPTY_INT_SHFT 24 +#define WF_PLE_TOP_INT_N9_STS_AC_ENQ_LMAC_INT_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_AC_ENQ_LMAC_INT_MASK \ + 0x00400000 /* AC_ENQ_LMAC_INT[22] */ +#define WF_PLE_TOP_INT_N9_STS_AC_ENQ_LMAC_INT_SHFT 22 +#define WF_PLE_TOP_INT_N9_STS_AC_EMPTY_INT_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_AC_EMPTY_INT_MASK \ + 0x00200000 /* AC_EMPTY_INT[21] */ +#define WF_PLE_TOP_INT_N9_STS_AC_EMPTY_INT_SHFT 21 +#define WF_PLE_TOP_INT_N9_STS_AC_NONEMPTY_INT_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_AC_NONEMPTY_INT_MASK \ + 0x00100000 /* AC_NONEMPTY_INT[20] */ +#define WF_PLE_TOP_INT_N9_STS_AC_NONEMPTY_INT_SHFT 20 +#define WF_PLE_TOP_INT_N9_STS_UMAC_SYSRAM_OUTRAN_ERROR_INT_ADDR \ + WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_UMAC_SYSRAM_OUTRAN_ERROR_INT_MASK \ + 0x00040000 /* UMAC_SYSRAM_OUTRAN_ERROR_INT[18] */ +#define WF_PLE_TOP_INT_N9_STS_UMAC_SYSRAM_OUTRAN_ERROR_INT_SHFT 18 +#define WF_PLE_TOP_INT_N9_STS_DATA_TOGGLE_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_DATA_TOGGLE_MASK 0x00010000 /* DATA_TOGGLE[16] */ +#define WF_PLE_TOP_INT_N9_STS_DATA_TOGGLE_SHFT 16 +#define WF_PLE_TOP_INT_N9_STS_AMSDU_ERROR_INT_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_AMSDU_ERROR_INT_MASK \ + 0x00008000 /* AMSDU_ERROR_INT[15] */ +#define WF_PLE_TOP_INT_N9_STS_AMSDU_ERROR_INT_SHFT 15 +#define WF_PLE_TOP_INT_N9_STS_ERROR_INT_1_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_ERROR_INT_1_MASK 0x00004000 /* ERROR_INT_1[14] */ +#define WF_PLE_TOP_INT_N9_STS_ERROR_INT_1_SHFT 14 +#define WF_PLE_TOP_INT_N9_STS_ERROR_INT_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_ERROR_INT_MASK 0x00002000 /* ERROR_INT[13] */ +#define WF_PLE_TOP_INT_N9_STS_ERROR_INT_SHFT 13 +#define WF_PLE_TOP_INT_N9_STS_CPU_Q3_NE_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_CPU_Q3_NE_MASK 0x00000008 /* CPU_Q3_NE[3] */ +#define WF_PLE_TOP_INT_N9_STS_CPU_Q3_NE_SHFT 3 +#define WF_PLE_TOP_INT_N9_STS_CPU_Q2_NE_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_CPU_Q2_NE_MASK 0x00000004 /* CPU_Q2_NE[2] */ +#define WF_PLE_TOP_INT_N9_STS_CPU_Q2_NE_SHFT 2 +#define WF_PLE_TOP_INT_N9_STS_CPU_Q1_NE_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_CPU_Q1_NE_MASK 0x00000002 /* CPU_Q1_NE[1] */ +#define WF_PLE_TOP_INT_N9_STS_CPU_Q1_NE_SHFT 1 +#define WF_PLE_TOP_INT_N9_STS_CPU_Q0_NE_ADDR WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_CPU_Q0_NE_MASK 0x00000001 /* CPU_Q0_NE[0] */ +#define WF_PLE_TOP_INT_N9_STS_CPU_Q0_NE_SHFT 0 + +/* +* ---INT_N9_ERR_STS (0x820C0000 + 0x304)--- +* Q_CMD_ERR_P0[0] - (W1C) Queue command error interrupt status of +* port 0. Avoid unclear error flag, please clear flag when logic reset. +* Q_CMD_ERR_P1[1] - (W1C) Queue command error interrupt status of +* port 1. Avoid unclear error flag, please clear flag when logic reset. +* Q_CMD_ERR_P2[2] - (W1C) Queue command error interrupt status of +* port 2. Avoid unclear error flag, please clear flag when logic reset. +* PAGE_UDF_P0[3] - (W1C) Page underflow interrupt status of port +* 0. Avoid unclear error flag, please clear flag when logic reset. +* PAGE_UDF_P1[4] - (W1C) Page underflow interrupt status of port +* 1. Avoid unclear error flag, please clear flag when logic reset. +* PAGE_UDF_P2[5] - (W1C) Page underflow interrupt status of port +* 2. Avoid unclear error flag, please clear flag when logic reset. +* DOUBLE_RLS_ERR[6] - (W1C) Double release error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* MDP_D_OPER_ERR[7] - (W1C) MDP data operation error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* MDP_HANG_ERR[8] - (W1C) MDP FSM Hang error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* RESERVED9[9] - (RO) Reserved bits +* DATA_OPER_ERR_P0[10] - (W1C) Data operation error of port 0. Avoid +* unclear error flag, please clear flag when logic reset. +* DATA_OPER_ERR_P1[11] - (W1C) Data operation error of port 1. Avoid +* unclear error flag, please clear flag when logic reset. +* DATA_OPER_ERR_P2[12] - (W1C) Data operation error of port 2. Avoid +* unclear error flag, please clear flag when logic reset. +* FL_HANG_ERR[13] - (W1C) Frame link FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* PL_HANG_ERR[14] - (W1C) Page link FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* HIF_HANG_ERR[15] - (W1C) HIF port FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* CPU_HANG_ERR[16] - (W1C) CPU port FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* LMAC_HANG_ERR[17] - (W1C) LMAC port FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* FREE_HEAD_TAIL_ERR[18] - (W1C) Free head/tail error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* QSTRUCT_ERR[19] - (W1C) Queue struct data error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* BN0_MACTX_HANG_ERR[20] - (W1C) BN0 MACTX Ctrl FSM Hang error +* interrupt. Avoid unclear error flag, please clear flag when logic reset. +* BN1_MACTX_HANG_ERR[21] - (W1C) BN1 MACTX Ctrl FSM Hang error +* interrupt. Avoid unclear error flag, please clear flag when logic reset. +* BN0_TXCMD_HANG_ERR[22] - (W1C) BN0 TXCMD Ctrl FSM Hang error +* interrupt. Avoid unclear error flag, please clear flag when logic reset. +* BN1_TXCMD_HANG_ERR[23] - (W1C) BN1 TXCMD Ctrl FSM Hang error +* interrupt. Avoid unclear error flag, please clear flag when logic reset. +* DRR_SRCH_DBDC0_ERR[24] - (W1C) DRR DBDC0 sta serach error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* DRR_SRCH_DBDC1_ERR[25] - (W1C) DRR DBDC1 sta serach error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* DRR_FL_ERR[26] - (W1C) DRR forward link access error +* interrupt. Avoid unclear error flag, please clear flag when logic reset. +* DRR_BL_ERR[27] - (W1C) DRR backward link access error +* interrupt. Avoid unclear error flag, please clear flag when logic reset. +* DRR_RL_ERR[28] - (W1C) DRR relay link access error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* DRR_CHRG_STA_ERR[29] - (W1C) DRR charge wlanid error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* DRR_STA_WLANID_ERR[30] - (W1C) DRR wlanid error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* DRR_STA_WMMID_ERR[31] - (W1C) DRR wmmid error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +*/ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_STA_WMMID_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_STA_WMMID_ERR_MASK \ + 0x80000000 /* DRR_STA_WMMID_ERR[31] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_STA_WMMID_ERR_SHFT 31 +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_STA_WLANID_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_STA_WLANID_ERR_MASK \ + 0x40000000 /* DRR_STA_WLANID_ERR[30] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_STA_WLANID_ERR_SHFT 30 +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_CHRG_STA_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_CHRG_STA_ERR_MASK \ + 0x20000000 /* DRR_CHRG_STA_ERR[29] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_CHRG_STA_ERR_SHFT 29 +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_RL_ERR_ADDR WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_RL_ERR_MASK \ + 0x10000000 /* DRR_RL_ERR[28] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_RL_ERR_SHFT 28 +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_BL_ERR_ADDR WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_BL_ERR_MASK \ + 0x08000000 /* DRR_BL_ERR[27] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_BL_ERR_SHFT 27 +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_FL_ERR_ADDR WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_FL_ERR_MASK \ + 0x04000000 /* DRR_FL_ERR[26] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_FL_ERR_SHFT 26 +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_SRCH_DBDC1_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_SRCH_DBDC1_ERR_MASK \ + 0x02000000 /* DRR_SRCH_DBDC1_ERR[25] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_SRCH_DBDC1_ERR_SHFT 25 +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_SRCH_DBDC0_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_SRCH_DBDC0_ERR_MASK \ + 0x01000000 /* DRR_SRCH_DBDC0_ERR[24] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_SRCH_DBDC0_ERR_SHFT 24 +#define WF_PLE_TOP_INT_N9_ERR_STS_BN1_TXCMD_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_BN1_TXCMD_HANG_ERR_MASK \ + 0x00800000 /* BN1_TXCMD_HANG_ERR[23] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_BN1_TXCMD_HANG_ERR_SHFT 23 +#define WF_PLE_TOP_INT_N9_ERR_STS_BN0_TXCMD_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_BN0_TXCMD_HANG_ERR_MASK \ + 0x00400000 /* BN0_TXCMD_HANG_ERR[22] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_BN0_TXCMD_HANG_ERR_SHFT 22 +#define WF_PLE_TOP_INT_N9_ERR_STS_BN1_MACTX_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_BN1_MACTX_HANG_ERR_MASK \ + 0x00200000 /* BN1_MACTX_HANG_ERR[21] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_BN1_MACTX_HANG_ERR_SHFT 21 +#define WF_PLE_TOP_INT_N9_ERR_STS_BN0_MACTX_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_BN0_MACTX_HANG_ERR_MASK \ + 0x00100000 /* BN0_MACTX_HANG_ERR[20] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_BN0_MACTX_HANG_ERR_SHFT 20 +#define WF_PLE_TOP_INT_N9_ERR_STS_QSTRUCT_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_QSTRUCT_ERR_MASK \ + 0x00080000 /* QSTRUCT_ERR[19] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_QSTRUCT_ERR_SHFT 19 +#define WF_PLE_TOP_INT_N9_ERR_STS_FREE_HEAD_TAIL_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_FREE_HEAD_TAIL_ERR_MASK \ + 0x00040000 /* FREE_HEAD_TAIL_ERR[18] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_FREE_HEAD_TAIL_ERR_SHFT 18 +#define WF_PLE_TOP_INT_N9_ERR_STS_LMAC_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_LMAC_HANG_ERR_MASK \ + 0x00020000 /* LMAC_HANG_ERR[17] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_LMAC_HANG_ERR_SHFT 17 +#define WF_PLE_TOP_INT_N9_ERR_STS_CPU_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_CPU_HANG_ERR_MASK \ + 0x00010000 /* CPU_HANG_ERR[16] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_CPU_HANG_ERR_SHFT 16 +#define WF_PLE_TOP_INT_N9_ERR_STS_HIF_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_HIF_HANG_ERR_MASK \ + 0x00008000 /* HIF_HANG_ERR[15] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_HIF_HANG_ERR_SHFT 15 +#define WF_PLE_TOP_INT_N9_ERR_STS_PL_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_PL_HANG_ERR_MASK \ + 0x00004000 /* PL_HANG_ERR[14] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_PL_HANG_ERR_SHFT 14 +#define WF_PLE_TOP_INT_N9_ERR_STS_FL_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_FL_HANG_ERR_MASK \ + 0x00002000 /* FL_HANG_ERR[13] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_FL_HANG_ERR_SHFT 13 +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P2_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P2_MASK \ + 0x00001000 /* DATA_OPER_ERR_P2[12] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P2_SHFT 12 +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P1_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P1_MASK \ + 0x00000800 /* DATA_OPER_ERR_P1[11] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P1_SHFT 11 +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P0_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P0_MASK \ + 0x00000400 /* DATA_OPER_ERR_P0[10] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P0_SHFT 10 +#define WF_PLE_TOP_INT_N9_ERR_STS_MDP_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_MDP_HANG_ERR_MASK \ + 0x00000100 /* MDP_HANG_ERR[8] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_MDP_HANG_ERR_SHFT 8 +#define WF_PLE_TOP_INT_N9_ERR_STS_MDP_D_OPER_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_MDP_D_OPER_ERR_MASK \ + 0x00000080 /* MDP_D_OPER_ERR[7] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_MDP_D_OPER_ERR_SHFT 7 +#define WF_PLE_TOP_INT_N9_ERR_STS_DOUBLE_RLS_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DOUBLE_RLS_ERR_MASK \ + 0x00000040 /* DOUBLE_RLS_ERR[6] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DOUBLE_RLS_ERR_SHFT 6 +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P2_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P2_MASK \ + 0x00000020 /* PAGE_UDF_P2[5] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P2_SHFT 5 +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P1_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P1_MASK \ + 0x00000010 /* PAGE_UDF_P1[4] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P1_SHFT 4 +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P0_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P0_MASK \ + 0x00000008 /* PAGE_UDF_P0[3] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P0_SHFT 3 +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P2_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P2_MASK \ + 0x00000004 /* Q_CMD_ERR_P2[2] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P2_SHFT 2 +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P1_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P1_MASK \ + 0x00000002 /* Q_CMD_ERR_P1[1] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P1_SHFT 1 +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P0_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P0_MASK \ + 0x00000001 /* Q_CMD_ERR_P0[0] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P0_SHFT 0 + +/* +* ---INT_N9_ERR_STS_1 (0x820C0000 + 0x308)--- +* BN0_MDP_TDP_HANG_ERR[0] - (W1C) BN0 MDP TDP FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* MDP_RDP_HANG_ERR[1] - (W1C) MDP RDP FSM hang error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* BN0_MDP_TIOC_HANG_ERR[2] - (W1C) BN0 MDP TIOC FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* BN0_MDP_RIOC_HANG_ERR[3] - (W1C) BN0 MDP RIOC FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* PF_HANG_ERR[4] - (W1C) PF FSM hang error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* SEC0_HANG_ERR[5] - (W1C) SEC 0 FSM hang error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* SEC1_HANG_ERR[6] - (W1C) SEC 1 FSM hang error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* BN1_MDP_TDP_HANG_ERR[7] - (W1C) BN1 MDP TDP FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* BN1_MDP_TIOC_HANG_ERR[8] - (W1C) BN1 MDP TIOC FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* BN1_MDP_RIOC_HANG_ERR[9] - (W1C) BN1 MDP RIOC FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* RESERVED10[11..10] - (RO) Reserved bits +* BN0_RPEDL_ARB_HANG_ERR[12] - (W1C) BN0 PREDL ARB hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* BN0_PREDL_TXCMD_HANG_ERR[13] - (W1C) BN0 PREDL TXCDM FSM hang error +* interrupt. Avoid unclear error flag, please clear flag when logic reset. +* BN1_RPEDL_ARB_HANG_ERR[14] - (W1C) BN1 PREDL ARB hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* BN1_PREDL_TXCMD_HANG_ERR[15] - (W1C) BN1 PREDL TXCDM FSM hang error +* interrupt. Avoid unclear error flag, please clear flag when logic reset. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_PREDL_TXCMD_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_PREDL_TXCMD_HANG_ERR_MASK \ + 0x00008000 /* BN1_PREDL_TXCMD_HANG_ERR[15] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_PREDL_TXCMD_HANG_ERR_SHFT 15 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_RPEDL_ARB_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_RPEDL_ARB_HANG_ERR_MASK \ + 0x00004000 /* BN1_RPEDL_ARB_HANG_ERR[14] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_RPEDL_ARB_HANG_ERR_SHFT 14 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_PREDL_TXCMD_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_PREDL_TXCMD_HANG_ERR_MASK \ + 0x00002000 /* BN0_PREDL_TXCMD_HANG_ERR[13] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_PREDL_TXCMD_HANG_ERR_SHFT 13 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_RPEDL_ARB_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_RPEDL_ARB_HANG_ERR_MASK \ + 0x00001000 /* BN0_RPEDL_ARB_HANG_ERR[12] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_RPEDL_ARB_HANG_ERR_SHFT 12 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_RIOC_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_RIOC_HANG_ERR_MASK \ + 0x00000200 /* BN1_MDP_RIOC_HANG_ERR[9] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_RIOC_HANG_ERR_SHFT 9 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_TIOC_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_TIOC_HANG_ERR_MASK \ + 0x00000100 /* BN1_MDP_TIOC_HANG_ERR[8] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_TIOC_HANG_ERR_SHFT 8 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_TDP_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_TDP_HANG_ERR_MASK \ + 0x00000080 /* BN1_MDP_TDP_HANG_ERR[7] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_TDP_HANG_ERR_SHFT 7 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_SEC1_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_SEC1_HANG_ERR_MASK \ + 0x00000040 /* SEC1_HANG_ERR[6] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_SEC1_HANG_ERR_SHFT 6 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_SEC0_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_SEC0_HANG_ERR_MASK \ + 0x00000020 /* SEC0_HANG_ERR[5] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_SEC0_HANG_ERR_SHFT 5 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_PF_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_PF_HANG_ERR_MASK \ + 0x00000010 /* PF_HANG_ERR[4] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_PF_HANG_ERR_SHFT 4 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_RIOC_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_RIOC_HANG_ERR_MASK \ + 0x00000008 /* BN0_MDP_RIOC_HANG_ERR[3] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_RIOC_HANG_ERR_SHFT 3 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_TIOC_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_TIOC_HANG_ERR_MASK \ + 0x00000004 /* BN0_MDP_TIOC_HANG_ERR[2] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_TIOC_HANG_ERR_SHFT 2 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_MDP_RDP_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_MDP_RDP_HANG_ERR_MASK \ + 0x00000002 /* MDP_RDP_HANG_ERR[1] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_MDP_RDP_HANG_ERR_SHFT 1 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_TDP_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_TDP_HANG_ERR_MASK \ + 0x00000001 /* BN0_MDP_TDP_HANG_ERR[0] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_TDP_HANG_ERR_SHFT 0 + +/* +* ---N9_BSS_PS_INT_STS (0x820C0000 + 0x30c)--- +* BSSID0_NONEMPTY_INT[0] - (W1C) BSSID0 queue empty fall interrupt +status +* BSSID1_NONEMPTY_INT[1] - (W1C) BSSID1 queue empty fall interrupt +status +* BSSID2_NONEMPTY_INT[2] - (W1C) BSSID2 queue empty fall interrupt +status +* BSSID3_NONEMPTY_INT[3] - (W1C) BSSID3 queue empty fall interrupt +status +* RESERVED4[7..4] - (RO) Reserved bits +* BSSID0_EMPTY_INT[8] - (W1C) BSSID0 queue empty raise interrupt +status +* BSSID1_EMPTY_INT[9] - (W1C) BSSID1 queue empty raise interrupt +status +* BSSID2_EMPTY_INT[10] - (W1C) BSSID2 queue empty raise interrupt +status +* BSSID3_EMPTY_INT[11] - (W1C) BSSID3 queue empty raise interrupt +status +* RESERVED12[15..12] - (RO) Reserved bits +* BSSID0_ENQ_LMAC_INT[16] - (W1C) BSSID0 enqueue interrupt status +* BSSID1_ENQ_LMAC_INT[17] - (W1C) BSSID1 enqueue interrupt status +* BSSID2_ENQ_LMAC_INT[18] - (W1C) BSSID2 enqueue interrupt status +* BSSID3_ENQ_LMAC_INT[19] - (W1C) BSSID3 enqueue interrupt status +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_ENQ_LMAC_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_ENQ_LMAC_INT_MASK \ + 0x00080000 /* BSSID3_ENQ_LMAC_INT[19] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_ENQ_LMAC_INT_SHFT 19 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_ENQ_LMAC_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_ENQ_LMAC_INT_MASK \ + 0x00040000 /* BSSID2_ENQ_LMAC_INT[18] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_ENQ_LMAC_INT_SHFT 18 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_ENQ_LMAC_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_ENQ_LMAC_INT_MASK \ + 0x00020000 /* BSSID1_ENQ_LMAC_INT[17] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_ENQ_LMAC_INT_SHFT 17 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_ENQ_LMAC_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_ENQ_LMAC_INT_MASK \ + 0x00010000 /* BSSID0_ENQ_LMAC_INT[16] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_ENQ_LMAC_INT_SHFT 16 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_EMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_EMPTY_INT_MASK \ + 0x00000800 /* BSSID3_EMPTY_INT[11] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_EMPTY_INT_SHFT 11 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_EMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_EMPTY_INT_MASK \ + 0x00000400 /* BSSID2_EMPTY_INT[10] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_EMPTY_INT_SHFT 10 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_EMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_EMPTY_INT_MASK \ + 0x00000200 /* BSSID1_EMPTY_INT[9] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_EMPTY_INT_SHFT 9 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_EMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_EMPTY_INT_MASK \ + 0x00000100 /* BSSID0_EMPTY_INT[8] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_EMPTY_INT_SHFT 8 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_NONEMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_NONEMPTY_INT_MASK \ + 0x00000008 /* BSSID3_NONEMPTY_INT[3] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_NONEMPTY_INT_SHFT 3 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_NONEMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_NONEMPTY_INT_MASK \ + 0x00000004 /* BSSID2_NONEMPTY_INT[2] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_NONEMPTY_INT_SHFT 2 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_NONEMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_NONEMPTY_INT_MASK \ + 0x00000002 /* BSSID1_NONEMPTY_INT[1] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_NONEMPTY_INT_SHFT 1 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_NONEMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_NONEMPTY_INT_MASK \ + 0x00000001 /* BSSID0_NONEMPTY_INT[0] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_NONEMPTY_INT_SHFT 0 + +/* +* ---C_GET_FID_0 (0x820C0000 + 0x310)--- +* GET_SRC_WLANID[9..0] - (RW) Source WLAN ID for get frame ID. +* RESERVED10[11..10] - (RO) Reserved bits +* GET_SRC_TGID[12] - (RW) Source TX Group ID for get frame ID. +* RESERVED13[13] - (RO) Reserved bits +* GET_SRC_PID[15..14] - (RW) Source port ID for get frame ID. +* GET_FRAME_TYPE[19..16] - (RW) GET_SUB_TYPE +* RESERVED20[23..20] - (RO) Reserved bits +* GET_SRC_QID[30..24] - (RW) Source Queue ID for get frame ID. +* EXECUTE[31] - (A0) Executes command +*/ +#define WF_PLE_TOP_C_GET_FID_0_EXECUTE_ADDR WF_PLE_TOP_C_GET_FID_0_ADDR +#define WF_PLE_TOP_C_GET_FID_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_C_GET_FID_0_EXECUTE_SHFT 31 +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_QID_ADDR WF_PLE_TOP_C_GET_FID_0_ADDR +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_QID_MASK \ + 0x7F000000 /* GET_SRC_QID[30..24] */ +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_QID_SHFT 24 +#define WF_PLE_TOP_C_GET_FID_0_GET_FRAME_TYPE_ADDR WF_PLE_TOP_C_GET_FID_0_ADDR +#define WF_PLE_TOP_C_GET_FID_0_GET_FRAME_TYPE_MASK \ + 0x000F0000 /* GET_FRAME_TYPE[19..16] */ +#define WF_PLE_TOP_C_GET_FID_0_GET_FRAME_TYPE_SHFT 16 +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_PID_ADDR WF_PLE_TOP_C_GET_FID_0_ADDR +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_PID_MASK \ + 0x0000C000 /* GET_SRC_PID[15..14] */ +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_PID_SHFT 14 +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_TGID_ADDR WF_PLE_TOP_C_GET_FID_0_ADDR +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_TGID_MASK \ + 0x00001000 /* GET_SRC_TGID[12] */ +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_TGID_SHFT 12 +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_WLANID_ADDR WF_PLE_TOP_C_GET_FID_0_ADDR +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_WLANID_MASK \ + 0x000003FF /* GET_SRC_WLANID[9..0] */ +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_WLANID_SHFT 0 + +/* +* ---C_GET_FID_1 (0x820C0000 + 0x314)--- +* GET_RETURN_FID[11..0] - (RO) Return frame ID +* RESERVED12[14..12] - (RO) Reserved bits +* END[15] - (RO) Return frame ID is end FID. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_C_GET_FID_1_END_ADDR WF_PLE_TOP_C_GET_FID_1_ADDR +#define WF_PLE_TOP_C_GET_FID_1_END_MASK 0x00008000 /* END[15] */ +#define WF_PLE_TOP_C_GET_FID_1_END_SHFT 15 +#define WF_PLE_TOP_C_GET_FID_1_GET_RETURN_FID_ADDR WF_PLE_TOP_C_GET_FID_1_ADDR +#define WF_PLE_TOP_C_GET_FID_1_GET_RETURN_FID_MASK \ + 0x00000FFF /* GET_RETURN_FID[11..0] */ +#define WF_PLE_TOP_C_GET_FID_1_GET_RETURN_FID_SHFT 0 + +/* +* ---TO_N9_INT (0x820C0000 + 0x318)--- +* CR4_CMD[30..0] - (RW) Command for N9 +* TOGGLE[31] - (RW) When this bit is toggled, HW will send +* interrupt to N9. +*/ +#define WF_PLE_TOP_TO_N9_INT_TOGGLE_ADDR WF_PLE_TOP_TO_N9_INT_ADDR +#define WF_PLE_TOP_TO_N9_INT_TOGGLE_MASK 0x80000000 /* TOGGLE[31] */ +#define WF_PLE_TOP_TO_N9_INT_TOGGLE_SHFT 31 +#define WF_PLE_TOP_TO_N9_INT_CR4_CMD_ADDR WF_PLE_TOP_TO_N9_INT_ADDR +#define WF_PLE_TOP_TO_N9_INT_CR4_CMD_MASK 0x7FFFFFFF /* CR4_CMD[30..0] */ +#define WF_PLE_TOP_TO_N9_INT_CR4_CMD_SHFT 0 + +/* +* ---C_EN_QUEUE_0 (0x820C0000 + 0x320)--- +* DST_WLANID[9..0] - (RW) Destination WLANID for enqueue +* RESERVED10[11..10] - (RO) Reserved bits +* DST_TGID[12] - (RW) Destination TX Group ID for enqueue +* RESERVED13[13] - (RO) Reserved bits +* DST_PID[15..14] - (RW) Destination port ID for enqueue +* SUB_TYPE[19..16] - (RW) Sub-type of enqueue command +* RESERVED20[22..20] - (RO) Reserved bits +* DELAY_ENQ[23] - (RW) Delay enqueue +* ENQ_DST_QID[30..24] - (RW) Destination queue ID for enqueue +* EXECUTE[31] - (A0) Executes command +*/ +#define WF_PLE_TOP_C_EN_QUEUE_0_EXECUTE_ADDR WF_PLE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_C_EN_QUEUE_0_EXECUTE_SHFT 31 +#define WF_PLE_TOP_C_EN_QUEUE_0_ENQ_DST_QID_ADDR WF_PLE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_0_ENQ_DST_QID_MASK \ + 0x7F000000 /* ENQ_DST_QID[30..24] */ +#define WF_PLE_TOP_C_EN_QUEUE_0_ENQ_DST_QID_SHFT 24 +#define WF_PLE_TOP_C_EN_QUEUE_0_DELAY_ENQ_ADDR WF_PLE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_0_DELAY_ENQ_MASK 0x00800000 /* DELAY_ENQ[23] */ +#define WF_PLE_TOP_C_EN_QUEUE_0_DELAY_ENQ_SHFT 23 +#define WF_PLE_TOP_C_EN_QUEUE_0_SUB_TYPE_ADDR WF_PLE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_0_SUB_TYPE_MASK 0x000F0000 /* SUB_TYPE[19..16] */ +#define WF_PLE_TOP_C_EN_QUEUE_0_SUB_TYPE_SHFT 16 +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_PID_ADDR WF_PLE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_PID_MASK 0x0000C000 /* DST_PID[15..14] */ +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_PID_SHFT 14 +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_TGID_ADDR WF_PLE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_TGID_MASK 0x00001000 /* DST_TGID[12] */ +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_TGID_SHFT 12 +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_WLANID_ADDR WF_PLE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_WLANID_MASK \ + 0x000003FF /* DST_WLANID[9..0] */ +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_WLANID_SHFT 0 + +/* +* ---C_EN_QUEUE_1 (0x820C0000 + 0x324)--- +* CUR_LIST_FID_START[11..0] - (RW) Start frame ID of enqueue operation +* list, enqueue FID of enqueue operation +* RESERVED12[15..12] - (RO) Reserved bits +* CUR_LIST_FID_END[27..16] - (RW) End frame ID of enqueue operation list +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_END_ADDR \ + WF_PLE_TOP_C_EN_QUEUE_1_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_END_MASK \ + 0x0FFF0000 /* CUR_LIST_FID_END[27..16] */ +#define WF_PLE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_END_SHFT 16 +#define WF_PLE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_START_ADDR \ + WF_PLE_TOP_C_EN_QUEUE_1_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_START_MASK \ + 0x00000FFF /* CUR_LIST_FID_START[11..0] */ +#define WF_PLE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_START_SHFT 0 + +/* +* ---C_EN_QUEUE_2 (0x820C0000 + 0x328)--- +* TARGET_FID[11..0] - (RW) Target reference FID for enqueue +operation +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_C_EN_QUEUE_2_TARGET_FID_ADDR WF_PLE_TOP_C_EN_QUEUE_2_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_2_TARGET_FID_MASK \ + 0x00000FFF /* TARGET_FID[11..0] */ +#define WF_PLE_TOP_C_EN_QUEUE_2_TARGET_FID_SHFT 0 + +/* +* ---C_DE_QUEUE_0 (0x820C0000 + 0x330)--- +* SRC_WLANID[9..0] - (RW) Source WLAN ID for dequeue command +* RESERVED10[11..10] - (RO) Reserved bits +* SRC_TGID[12] - (RW) Source TX Group ID for dequeue command +* RESERVED13[13] - (RO) Reserved bits +* SRC_PID[15..14] - (RW) Source port ID for dequeue command +* DEQ_SUB_TYPE[19..16] - (RW) Dequeue subtype of dequeue command +* ENQ_SUB_TYPE[22..20] - (RW) Enqueue subtype of enqueue command +* Only valid in Deq&Enq type. +* ENQ_VLD[23] - (RW) Deq&Enq command valid +* SRC_QID[30..24] - (RW) Source queue ID for dequeue command +* EXECUTE[31] - (A0) Executes dequeue command +*/ +#define WF_PLE_TOP_C_DE_QUEUE_0_EXECUTE_ADDR WF_PLE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_C_DE_QUEUE_0_EXECUTE_SHFT 31 +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_QID_ADDR WF_PLE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_QID_MASK 0x7F000000 /* SRC_QID[30..24] */ +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_QID_SHFT 24 +#define WF_PLE_TOP_C_DE_QUEUE_0_ENQ_VLD_ADDR WF_PLE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_0_ENQ_VLD_MASK 0x00800000 /* ENQ_VLD[23] */ +#define WF_PLE_TOP_C_DE_QUEUE_0_ENQ_VLD_SHFT 23 +#define WF_PLE_TOP_C_DE_QUEUE_0_ENQ_SUB_TYPE_ADDR WF_PLE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_0_ENQ_SUB_TYPE_MASK \ + 0x00700000 /* ENQ_SUB_TYPE[22..20] */ +#define WF_PLE_TOP_C_DE_QUEUE_0_ENQ_SUB_TYPE_SHFT 20 +#define WF_PLE_TOP_C_DE_QUEUE_0_DEQ_SUB_TYPE_ADDR WF_PLE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_0_DEQ_SUB_TYPE_MASK \ + 0x000F0000 /* DEQ_SUB_TYPE[19..16] */ +#define WF_PLE_TOP_C_DE_QUEUE_0_DEQ_SUB_TYPE_SHFT 16 +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_PID_ADDR WF_PLE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_PID_MASK 0x0000C000 /* SRC_PID[15..14] */ +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_PID_SHFT 14 +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_TGID_ADDR WF_PLE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_TGID_MASK 0x00001000 /* SRC_TGID[12] */ +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_TGID_SHFT 12 +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_WLANID_ADDR WF_PLE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_WLANID_MASK \ + 0x000003FF /* SRC_WLANID[9..0] */ +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_WLANID_SHFT 0 + +/* +* ---C_DE_QUEUE_1 (0x820C0000 + 0x334)--- +* CUR_LIST_FID_START[11..0] - (RW) Start frame ID of dequeue operation +* list, enqueue start FID of enqueue operation +* Only valid in Deq&Enq type. +* RESERVED12[15..12] - (RO) Reserved bits +* CUR_LIST_FID_END[27..16] - (RW) End framd ID of dequeue operation list, +* enqueue end FID of enqueue operation +* Only valid in Deq&Enq type. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_END_ADDR \ + WF_PLE_TOP_C_DE_QUEUE_1_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_END_MASK \ + 0x0FFF0000 /* CUR_LIST_FID_END[27..16] */ +#define WF_PLE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_END_SHFT 16 +#define WF_PLE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_START_ADDR \ + WF_PLE_TOP_C_DE_QUEUE_1_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_START_MASK \ + 0x00000FFF /* CUR_LIST_FID_START[11..0] */ +#define WF_PLE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_START_SHFT 0 + +/* +* ---C_DE_QUEUE_2 (0x820C0000 + 0x338)--- +* DEQ_ENQ_DST_WLANID[9..0] - (RW) Destination WLAN ID for enqueue command +* Only valid in Deq&Enq type. +* RESERVED10[11..10] - (RO) Reserved bits +* DEQ_ENQ_DST_TGID[12] - (RW) Destination TX Group ID for enqueue +command +* Only valid in Deq&Enq type. +* RESERVED13[13] - (RO) Reserved bits +* DEQ_ENQ_DST_PID[15..14] - (RW) Destination port ID for enqueue command +* OInly valid in Deq&Enq type. +* RESERVED16[23..16] - (RO) Reserved bits +* DEQ_ENQ_DST_QID[30..24] - (RW) Destination queue ID for enqueue command +* Only valid in Deq&Enq type. +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_QID_ADDR \ + WF_PLE_TOP_C_DE_QUEUE_2_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_QID_MASK \ + 0x7F000000 /* DEQ_ENQ_DST_QID[30..24] */ +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_QID_SHFT 24 +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_PID_ADDR \ + WF_PLE_TOP_C_DE_QUEUE_2_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_PID_MASK \ + 0x0000C000 /* DEQ_ENQ_DST_PID[15..14] */ +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_PID_SHFT 14 +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_TGID_ADDR \ + WF_PLE_TOP_C_DE_QUEUE_2_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_TGID_MASK \ + 0x00001000 /* DEQ_ENQ_DST_TGID[12] */ +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_TGID_SHFT 12 +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_WLANID_ADDR \ + WF_PLE_TOP_C_DE_QUEUE_2_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_WLANID_MASK \ + 0x000003FF /* DEQ_ENQ_DST_WLANID[9..0] */ +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_WLANID_SHFT 0 + +/* +* ---C_DE_QUEUE_3 (0x820C0000 + 0x33c)--- +* DEQ_HEAD_FID[11..0] - (RO) Head FID got from dequeue command +* RESERVED12[14..12] - (RO) Reserved bits +* DEQ_EMPTY[15] - (RO) Queue empty after dequeue command is +executed +* DEQ_TAIL_FID[27..16] - (RO) Last FID got from dequeue command +* RESERVED28[30..28] - (RO) Reserved bits +* BUSY[31] - (RO) Dequeue execute busy +*/ +#define WF_PLE_TOP_C_DE_QUEUE_3_BUSY_ADDR WF_PLE_TOP_C_DE_QUEUE_3_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_3_BUSY_MASK 0x80000000 /* BUSY[31] */ +#define WF_PLE_TOP_C_DE_QUEUE_3_BUSY_SHFT 31 +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_TAIL_FID_ADDR WF_PLE_TOP_C_DE_QUEUE_3_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_TAIL_FID_MASK \ + 0x0FFF0000 /* DEQ_TAIL_FID[27..16] */ +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_TAIL_FID_SHFT 16 +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_EMPTY_ADDR WF_PLE_TOP_C_DE_QUEUE_3_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_EMPTY_MASK 0x00008000 /* DEQ_EMPTY[15] */ +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_EMPTY_SHFT 15 +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_HEAD_FID_ADDR WF_PLE_TOP_C_DE_QUEUE_3_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_HEAD_FID_MASK \ + 0x00000FFF /* DEQ_HEAD_FID[11..0] */ +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_HEAD_FID_SHFT 0 + +/* +* ---C_DE_QUEUE_4 (0x820C0000 + 0x340)--- +* DEQ_ENQ_REF_FID[11..0] - (RW) Reference frame ID for enqueue command +* Only valid in Deq&Enq type. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_C_DE_QUEUE_4_DEQ_ENQ_REF_FID_ADDR \ + WF_PLE_TOP_C_DE_QUEUE_4_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_4_DEQ_ENQ_REF_FID_MASK \ + 0x00000FFF /* DEQ_ENQ_REF_FID[11..0] */ +#define WF_PLE_TOP_C_DE_QUEUE_4_DEQ_ENQ_REF_FID_SHFT 0 + +/* +* ---ALLOCATE_0 (0x820C0000 + 0x350)--- +* ALLOCATE_FRAME_LENGTH[13..0] - (RW) Allocate frame length +* Unit: DW (4 bytes) +* RESERVED14[15..14] - (RO) Reserved bits +* ALLOCATE_QID[20..16] - (RW) QID used for allocate buffer +* RESERVED21[30..21] - (RO) Reserved bits +* EXECUTE[31] - (A0) Executes allocate buffer command +*/ +#define WF_PLE_TOP_ALLOCATE_0_EXECUTE_ADDR WF_PLE_TOP_ALLOCATE_0_ADDR +#define WF_PLE_TOP_ALLOCATE_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_ALLOCATE_0_EXECUTE_SHFT 31 +#define WF_PLE_TOP_ALLOCATE_0_ALLOCATE_QID_ADDR WF_PLE_TOP_ALLOCATE_0_ADDR +#define WF_PLE_TOP_ALLOCATE_0_ALLOCATE_QID_MASK \ + 0x001F0000 /* ALLOCATE_QID[20..16] */ +#define WF_PLE_TOP_ALLOCATE_0_ALLOCATE_QID_SHFT 16 +#define WF_PLE_TOP_ALLOCATE_0_ALLOCATE_FRAME_LENGTH_ADDR \ + WF_PLE_TOP_ALLOCATE_0_ADDR +#define WF_PLE_TOP_ALLOCATE_0_ALLOCATE_FRAME_LENGTH_MASK \ + 0x00003FFF /* ALLOCATE_FRAME_LENGTH[13..0] */ +#define WF_PLE_TOP_ALLOCATE_0_ALLOCATE_FRAME_LENGTH_SHFT 0 + +/* +* ---ALLOCATE_1 (0x820C0000 + 0x354)--- +* ALLOCATE_FID[11..0] - (RO) Return frame ID for allocate buffer +command +* RESERVED12[30..12] - (RO) Reserved bits +* EXECUTE[31] - (RO) Execute status of allocate buffer +command +*/ +#define WF_PLE_TOP_ALLOCATE_1_EXECUTE_ADDR WF_PLE_TOP_ALLOCATE_1_ADDR +#define WF_PLE_TOP_ALLOCATE_1_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_ALLOCATE_1_EXECUTE_SHFT 31 +#define WF_PLE_TOP_ALLOCATE_1_ALLOCATE_FID_ADDR WF_PLE_TOP_ALLOCATE_1_ADDR +#define WF_PLE_TOP_ALLOCATE_1_ALLOCATE_FID_MASK \ + 0x00000FFF /* ALLOCATE_FID[11..0] */ +#define WF_PLE_TOP_ALLOCATE_1_ALLOCATE_FID_SHFT 0 + +/* +* ---ALLOCATE_2 (0x820C0000 + 0x358)--- +* CPU_TXBYTE_COUNT[15..0] - (RW) TX data byte count +* This value should be the same as the first +* two bytes of TXD in PLE. +* CPU_MSDU_ID0_bit15_8[23..16] - (RW) MSDU_ID0 Bit15-Bit8 +* This value should be the same as the +* DW8[15:8] of TXD in PLE. +* CPU_PKT_FT[25..24] - (RW) TXD's PKT_FT +* This value should be the same as the +* DW0[24:23] of TXD in PLE. +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_ALLOCATE_2_CPU_PKT_FT_ADDR WF_PLE_TOP_ALLOCATE_2_ADDR +#define WF_PLE_TOP_ALLOCATE_2_CPU_PKT_FT_MASK \ + 0x03000000 /* CPU_PKT_FT[25..24] */ +#define WF_PLE_TOP_ALLOCATE_2_CPU_PKT_FT_SHFT 24 +#define WF_PLE_TOP_ALLOCATE_2_CPU_MSDU_ID0_bit15_8_ADDR \ + WF_PLE_TOP_ALLOCATE_2_ADDR +#define WF_PLE_TOP_ALLOCATE_2_CPU_MSDU_ID0_bit15_8_MASK \ + 0x00FF0000 /* CPU_MSDU_ID0_bit15_8[23..16] */ +#define WF_PLE_TOP_ALLOCATE_2_CPU_MSDU_ID0_bit15_8_SHFT 16 +#define WF_PLE_TOP_ALLOCATE_2_CPU_TXBYTE_COUNT_ADDR WF_PLE_TOP_ALLOCATE_2_ADDR +#define WF_PLE_TOP_ALLOCATE_2_CPU_TXBYTE_COUNT_MASK \ + 0x0000FFFF /* CPU_TXBYTE_COUNT[15..0] */ +#define WF_PLE_TOP_ALLOCATE_2_CPU_TXBYTE_COUNT_SHFT 0 + +/* +* ---QUEUE_EMPTY (0x820C0000 + 0x360)--- +* CPU_Q0_EMPTY[0] - (RO) CPU queue 0 empty status +* CPU_Q1_EMPTY[1] - (RO) CPU queue 1 empty status +* CPU_Q2_EMPTY[2] - (RO) CPU queue 2 empty status +* CPU_Q3_EMPTY[3] - (RO) CPU queue 3 empty status +* RESERVED4[7..4] - (RO) Reserved bits +* ALTX_0_EMPTY[8] - (RO) ALTX queue 0 empty status +* BMC_0_EMPTY[9] - (RO) BMC queue 0 empty status +* BCN_0_EMPTY[10] - (RO) BCN queue 0 empty status +* PSMP_0_EMPTY[11] - (RO) PSMP queue 0 empty status +* ALTX_1_EMPTY[12] - (RO) ALTX queue 1 empty status +* BMC_1_EMPTY[13] - (RO) BMC queue 1 empty status +* BCN_1_EMPTY[14] - (RO) BCN queue 1 empty status +* PSMP_1_EMPTY[15] - (RO) PSMP queue 1 empty status +* NAF_EMPTY[16] - (RO) NAF queue empty status +* NBCN_EMPTY[17] - (RO) NBCN queue empty status +* RESERVED18[19..18] - (RO) Reserved bits +* FIX_FID_EMPTY[20] - (RO) FIX_FID queue empty status +* RESERVED21[23..21] - (RO) Reserved bits +* ALL_AC_EMPTY[24] - (RO) All AC queue empty status +* RESERVED25[29..25] - (RO) Reserved bits +* RLS2_Q_EMTPY[30] - (RO) Release 2 queue empty status +* RLS_Q_EMTPY[31] - (RO) Release queue empty status +*/ +#define WF_PLE_TOP_QUEUE_EMPTY_RLS_Q_EMTPY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_RLS_Q_EMTPY_MASK 0x80000000 /* RLS_Q_EMTPY[31] */ +#define WF_PLE_TOP_QUEUE_EMPTY_RLS_Q_EMTPY_SHFT 31 +#define WF_PLE_TOP_QUEUE_EMPTY_RLS2_Q_EMTPY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_RLS2_Q_EMTPY_MASK \ + 0x40000000 /* RLS2_Q_EMTPY[30] */ +#define WF_PLE_TOP_QUEUE_EMPTY_RLS2_Q_EMTPY_SHFT 30 +#define WF_PLE_TOP_QUEUE_EMPTY_ALL_AC_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_ALL_AC_EMPTY_MASK \ + 0x01000000 /* ALL_AC_EMPTY[24] */ +#define WF_PLE_TOP_QUEUE_EMPTY_ALL_AC_EMPTY_SHFT 24 +#define WF_PLE_TOP_QUEUE_EMPTY_FIX_FID_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_FIX_FID_EMPTY_MASK \ + 0x00100000 /* FIX_FID_EMPTY[20] */ +#define WF_PLE_TOP_QUEUE_EMPTY_FIX_FID_EMPTY_SHFT 20 +#define WF_PLE_TOP_QUEUE_EMPTY_NBCN_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_NBCN_EMPTY_MASK 0x00020000 /* NBCN_EMPTY[17] */ +#define WF_PLE_TOP_QUEUE_EMPTY_NBCN_EMPTY_SHFT 17 +#define WF_PLE_TOP_QUEUE_EMPTY_NAF_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_NAF_EMPTY_MASK 0x00010000 /* NAF_EMPTY[16] */ +#define WF_PLE_TOP_QUEUE_EMPTY_NAF_EMPTY_SHFT 16 +#define WF_PLE_TOP_QUEUE_EMPTY_PSMP_1_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_PSMP_1_EMPTY_MASK \ + 0x00008000 /* PSMP_1_EMPTY[15] */ +#define WF_PLE_TOP_QUEUE_EMPTY_PSMP_1_EMPTY_SHFT 15 +#define WF_PLE_TOP_QUEUE_EMPTY_BCN_1_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_BCN_1_EMPTY_MASK 0x00004000 /* BCN_1_EMPTY[14] */ +#define WF_PLE_TOP_QUEUE_EMPTY_BCN_1_EMPTY_SHFT 14 +#define WF_PLE_TOP_QUEUE_EMPTY_BMC_1_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_BMC_1_EMPTY_MASK 0x00002000 /* BMC_1_EMPTY[13] */ +#define WF_PLE_TOP_QUEUE_EMPTY_BMC_1_EMPTY_SHFT 13 +#define WF_PLE_TOP_QUEUE_EMPTY_ALTX_1_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_ALTX_1_EMPTY_MASK \ + 0x00001000 /* ALTX_1_EMPTY[12] */ +#define WF_PLE_TOP_QUEUE_EMPTY_ALTX_1_EMPTY_SHFT 12 +#define WF_PLE_TOP_QUEUE_EMPTY_PSMP_0_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_PSMP_0_EMPTY_MASK \ + 0x00000800 /* PSMP_0_EMPTY[11] */ +#define WF_PLE_TOP_QUEUE_EMPTY_PSMP_0_EMPTY_SHFT 11 +#define WF_PLE_TOP_QUEUE_EMPTY_BCN_0_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_BCN_0_EMPTY_MASK 0x00000400 /* BCN_0_EMPTY[10] */ +#define WF_PLE_TOP_QUEUE_EMPTY_BCN_0_EMPTY_SHFT 10 +#define WF_PLE_TOP_QUEUE_EMPTY_BMC_0_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_BMC_0_EMPTY_MASK 0x00000200 /* BMC_0_EMPTY[9] */ +#define WF_PLE_TOP_QUEUE_EMPTY_BMC_0_EMPTY_SHFT 9 +#define WF_PLE_TOP_QUEUE_EMPTY_ALTX_0_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_ALTX_0_EMPTY_MASK \ + 0x00000100 /* ALTX_0_EMPTY[8] */ +#define WF_PLE_TOP_QUEUE_EMPTY_ALTX_0_EMPTY_SHFT 8 +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q3_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q3_EMPTY_MASK \ + 0x00000008 /* CPU_Q3_EMPTY[3] */ +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q3_EMPTY_SHFT 3 +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q2_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q2_EMPTY_MASK \ + 0x00000004 /* CPU_Q2_EMPTY[2] */ +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q2_EMPTY_SHFT 2 +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q1_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q1_EMPTY_MASK \ + 0x00000002 /* CPU_Q1_EMPTY[1] */ +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q1_EMPTY_SHFT 1 +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q0_EMPTY_ADDR WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q0_EMPTY_MASK \ + 0x00000001 /* CPU_Q0_EMPTY[0] */ +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q0_EMPTY_SHFT 0 + +/* +* ---TXD_QUEUE_EMPTY (0x820C0000 + 0x364)--- +* AC00_EMPTY[0] - (RO) WMM0 AC0 queue empty status +* AC01_EMPTY[1] - (RO) WMM0 AC1 queue empty status +* AC02_EMPTY[2] - (RO) WMM0 AC2 queue empty status +* AC03_EMPTY[3] - (RO) WMM0 AC3 queue empty status +* AC10_EMPTY[4] - (RO) WMM1 AC0 queue empty status +* AC11_EMPTY[5] - (RO) WMM1 AC1 queue empty status +* AC12_EMPTY[6] - (RO) WMM1 AC2 queue empty status +* AC13_EMPTY[7] - (RO) WMM1 AC3 queue empty status +* AC20_EMPTY[8] - (RO) WMM2 AC0 queue empty status +* AC21_EMPTY[9] - (RO) WMM2 AC1 queue empty status +* AC22_EMPTY[10] - (RO) WMM2 AC2 queue empty status +* AC23_EMPTY[11] - (RO) WMM2 AC3 queue empty status +* AC30_EMPTY[12] - (RO) WMM3 AC0 queue empty status +* AC31_EMPTY[13] - (RO) WMM3 AC1 queue empty status +* AC32_EMPTY[14] - (RO) WMM3 AC2 queue empty status +* AC33_EMPTY[15] - (RO) WMM3 AC3 queue empty status +* ALTX_0_EMPTY[16] - (RO) ALTX queue 0 empty status +* BMC_0_EMPTY[17] - (RO) BMC queue 0 empty status +* BCN_0_EMPTY[18] - (RO) BCN queue 0 empty status +* PSMP_0_EMPTY[19] - (RO) PSMP queue 0 empty status +* ALTX_1_EMPTY[20] - (RO) ALTX queue 1 empty status +* BMC_1_EMPTY[21] - (RO) BMC queue 1 empty status +* BCN_1_EMPTY[22] - (RO) BCN queue 1 empty status +* PSMP_1_EMPTY[23] - (RO) PSMP queue 1 empty status +* NAF_EMPTY[24] - (RO) NAF queue empty status +* NBCN_EMPTY[25] - (RO) NBCN queue empty status +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_NBCN_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_NBCN_EMPTY_MASK \ + 0x02000000 /* NBCN_EMPTY[25] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_NBCN_EMPTY_SHFT 25 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_NAF_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_NAF_EMPTY_MASK 0x01000000 /* NAF_EMPTY[24] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_NAF_EMPTY_SHFT 24 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_PSMP_1_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_PSMP_1_EMPTY_MASK \ + 0x00800000 /* PSMP_1_EMPTY[23] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_PSMP_1_EMPTY_SHFT 23 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BCN_1_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BCN_1_EMPTY_MASK \ + 0x00400000 /* BCN_1_EMPTY[22] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BCN_1_EMPTY_SHFT 22 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BMC_1_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BMC_1_EMPTY_MASK \ + 0x00200000 /* BMC_1_EMPTY[21] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BMC_1_EMPTY_SHFT 21 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_ALTX_1_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_ALTX_1_EMPTY_MASK \ + 0x00100000 /* ALTX_1_EMPTY[20] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_ALTX_1_EMPTY_SHFT 20 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_PSMP_0_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_PSMP_0_EMPTY_MASK \ + 0x00080000 /* PSMP_0_EMPTY[19] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_PSMP_0_EMPTY_SHFT 19 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BCN_0_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BCN_0_EMPTY_MASK \ + 0x00040000 /* BCN_0_EMPTY[18] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BCN_0_EMPTY_SHFT 18 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BMC_0_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BMC_0_EMPTY_MASK \ + 0x00020000 /* BMC_0_EMPTY[17] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BMC_0_EMPTY_SHFT 17 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_ALTX_0_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_ALTX_0_EMPTY_MASK \ + 0x00010000 /* ALTX_0_EMPTY[16] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_ALTX_0_EMPTY_SHFT 16 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC33_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC33_EMPTY_MASK \ + 0x00008000 /* AC33_EMPTY[15] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC33_EMPTY_SHFT 15 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC32_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC32_EMPTY_MASK \ + 0x00004000 /* AC32_EMPTY[14] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC32_EMPTY_SHFT 14 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC31_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC31_EMPTY_MASK \ + 0x00002000 /* AC31_EMPTY[13] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC31_EMPTY_SHFT 13 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC30_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC30_EMPTY_MASK \ + 0x00001000 /* AC30_EMPTY[12] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC30_EMPTY_SHFT 12 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC23_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC23_EMPTY_MASK \ + 0x00000800 /* AC23_EMPTY[11] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC23_EMPTY_SHFT 11 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC22_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC22_EMPTY_MASK \ + 0x00000400 /* AC22_EMPTY[10] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC22_EMPTY_SHFT 10 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC21_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC21_EMPTY_MASK \ + 0x00000200 /* AC21_EMPTY[9] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC21_EMPTY_SHFT 9 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC20_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC20_EMPTY_MASK \ + 0x00000100 /* AC20_EMPTY[8] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC20_EMPTY_SHFT 8 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC13_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC13_EMPTY_MASK \ + 0x00000080 /* AC13_EMPTY[7] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC13_EMPTY_SHFT 7 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC12_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC12_EMPTY_MASK \ + 0x00000040 /* AC12_EMPTY[6] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC12_EMPTY_SHFT 6 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC11_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC11_EMPTY_MASK \ + 0x00000020 /* AC11_EMPTY[5] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC11_EMPTY_SHFT 5 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC10_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC10_EMPTY_MASK \ + 0x00000010 /* AC10_EMPTY[4] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC10_EMPTY_SHFT 4 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC03_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC03_EMPTY_MASK \ + 0x00000008 /* AC03_EMPTY[3] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC03_EMPTY_SHFT 3 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC02_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC02_EMPTY_MASK \ + 0x00000004 /* AC02_EMPTY[2] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC02_EMPTY_SHFT 2 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC01_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC01_EMPTY_MASK \ + 0x00000002 /* AC01_EMPTY[1] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC01_EMPTY_SHFT 1 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC00_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC00_EMPTY_MASK \ + 0x00000001 /* AC00_EMPTY[0] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC00_EMPTY_SHFT 0 + +/* +* ---NATIVE_TXD_QUEUE_EMPTY (0x820C0000 + 0x368)--- +* AC00_EMPTY[0] - (RO) WMM0 AC0 queue empty status +* AC01_EMPTY[1] - (RO) WMM0 AC1 queue empty status +* AC02_EMPTY[2] - (RO) WMM0 AC2 queue empty status +* AC03_EMPTY[3] - (RO) WMM0 AC3 queue empty status +* AC10_EMPTY[4] - (RO) WMM1 AC0 queue empty status +* AC11_EMPTY[5] - (RO) WMM1 AC1 queue empty status +* AC12_EMPTY[6] - (RO) WMM1 AC2 queue empty status +* AC13_EMPTY[7] - (RO) WMM1 AC3 queue empty status +* AC20_EMPTY[8] - (RO) WMM2 AC0 queue empty status +* AC21_EMPTY[9] - (RO) WMM2 AC1 queue empty status +* AC22_EMPTY[10] - (RO) WMM2 AC2 queue empty status +* AC23_EMPTY[11] - (RO) WMM2 AC3 queue empty status +* AC30_EMPTY[12] - (RO) WMM3 AC0 queue empty status +* AC31_EMPTY[13] - (RO) WMM3 AC1 queue empty status +* AC32_EMPTY[14] - (RO) WMM3 AC2 queue empty status +* AC33_EMPTY[15] - (RO) WMM3 AC3 queue empty status +* ALTX_0_EMPTY[16] - (RO) ALTX queue 0 empty status +* BMC_0_EMPTY[17] - (RO) BMC queue 0 empty status +* BCN_0_EMPTY[18] - (RO) BCN queue 0 empty status +* PSMP_0_EMPTY[19] - (RO) PSMP queue 0 empty status +* ALTX_1_EMPTY[20] - (RO) ALTX queue 1 empty status +* BMC_1_EMPTY[21] - (RO) BMC queue 1 empty status +* BCN_1_EMPTY[22] - (RO) BCN queue 1 empty status +* PSMP_1_EMPTY[23] - (RO) PSMP queue 1 empty status +* NAF_EMPTY[24] - (RO) NAF queue empty status +* NBCN_EMPTY[25] - (RO) NBCN queue empty status +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_NBCN_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_NBCN_EMPTY_MASK \ + 0x02000000 /* NBCN_EMPTY[25] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_NBCN_EMPTY_SHFT 25 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_NAF_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_NAF_EMPTY_MASK \ + 0x01000000 /* NAF_EMPTY[24] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_NAF_EMPTY_SHFT 24 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_PSMP_1_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_PSMP_1_EMPTY_MASK \ + 0x00800000 /* PSMP_1_EMPTY[23] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_PSMP_1_EMPTY_SHFT 23 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BCN_1_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BCN_1_EMPTY_MASK \ + 0x00400000 /* BCN_1_EMPTY[22] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BCN_1_EMPTY_SHFT 22 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BMC_1_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BMC_1_EMPTY_MASK \ + 0x00200000 /* BMC_1_EMPTY[21] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BMC_1_EMPTY_SHFT 21 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ALTX_1_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ALTX_1_EMPTY_MASK \ + 0x00100000 /* ALTX_1_EMPTY[20] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ALTX_1_EMPTY_SHFT 20 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_PSMP_0_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_PSMP_0_EMPTY_MASK \ + 0x00080000 /* PSMP_0_EMPTY[19] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_PSMP_0_EMPTY_SHFT 19 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BCN_0_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BCN_0_EMPTY_MASK \ + 0x00040000 /* BCN_0_EMPTY[18] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BCN_0_EMPTY_SHFT 18 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BMC_0_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BMC_0_EMPTY_MASK \ + 0x00020000 /* BMC_0_EMPTY[17] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BMC_0_EMPTY_SHFT 17 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ALTX_0_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ALTX_0_EMPTY_MASK \ + 0x00010000 /* ALTX_0_EMPTY[16] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ALTX_0_EMPTY_SHFT 16 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC33_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC33_EMPTY_MASK \ + 0x00008000 /* AC33_EMPTY[15] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC33_EMPTY_SHFT 15 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC32_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC32_EMPTY_MASK \ + 0x00004000 /* AC32_EMPTY[14] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC32_EMPTY_SHFT 14 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC31_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC31_EMPTY_MASK \ + 0x00002000 /* AC31_EMPTY[13] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC31_EMPTY_SHFT 13 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC30_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC30_EMPTY_MASK \ + 0x00001000 /* AC30_EMPTY[12] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC30_EMPTY_SHFT 12 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC23_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC23_EMPTY_MASK \ + 0x00000800 /* AC23_EMPTY[11] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC23_EMPTY_SHFT 11 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC22_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC22_EMPTY_MASK \ + 0x00000400 /* AC22_EMPTY[10] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC22_EMPTY_SHFT 10 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC21_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC21_EMPTY_MASK \ + 0x00000200 /* AC21_EMPTY[9] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC21_EMPTY_SHFT 9 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC20_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC20_EMPTY_MASK \ + 0x00000100 /* AC20_EMPTY[8] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC20_EMPTY_SHFT 8 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC13_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC13_EMPTY_MASK \ + 0x00000080 /* AC13_EMPTY[7] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC13_EMPTY_SHFT 7 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC12_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC12_EMPTY_MASK \ + 0x00000040 /* AC12_EMPTY[6] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC12_EMPTY_SHFT 6 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC11_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC11_EMPTY_MASK \ + 0x00000020 /* AC11_EMPTY[5] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC11_EMPTY_SHFT 5 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC10_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC10_EMPTY_MASK \ + 0x00000010 /* AC10_EMPTY[4] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC10_EMPTY_SHFT 4 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC03_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC03_EMPTY_MASK \ + 0x00000008 /* AC03_EMPTY[3] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC03_EMPTY_SHFT 3 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC02_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC02_EMPTY_MASK \ + 0x00000004 /* AC02_EMPTY[2] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC02_EMPTY_SHFT 2 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC01_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC01_EMPTY_MASK \ + 0x00000002 /* AC01_EMPTY[1] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC01_EMPTY_SHFT 1 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC00_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC00_EMPTY_MASK \ + 0x00000001 /* AC00_EMPTY[0] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC00_EMPTY_SHFT 0 + +/* +* ---DRR_CHNL_EMPTY (0x820C0000 + 0x374)--- +* WMM_STA_DL_EMPTY[15..0] - (RO) Indicate emptiness of 16 DL station link +* WMM_STA_UL_EMPTY[31..16] - (RO) Indicate emptiness of 16 UL station link +*/ +#define WF_PLE_TOP_DRR_CHNL_EMPTY_WMM_STA_UL_EMPTY_ADDR \ + WF_PLE_TOP_DRR_CHNL_EMPTY_ADDR +#define WF_PLE_TOP_DRR_CHNL_EMPTY_WMM_STA_UL_EMPTY_MASK \ + 0xFFFF0000 /* WMM_STA_UL_EMPTY[31..16] */ +#define WF_PLE_TOP_DRR_CHNL_EMPTY_WMM_STA_UL_EMPTY_SHFT 16 +#define WF_PLE_TOP_DRR_CHNL_EMPTY_WMM_STA_DL_EMPTY_ADDR \ + WF_PLE_TOP_DRR_CHNL_EMPTY_ADDR +#define WF_PLE_TOP_DRR_CHNL_EMPTY_WMM_STA_DL_EMPTY_MASK \ + 0x0000FFFF /* WMM_STA_DL_EMPTY[15..0] */ +#define WF_PLE_TOP_DRR_CHNL_EMPTY_WMM_STA_DL_EMPTY_SHFT 0 + +/* +* ---FREEPG_CNT (0x820C0000 + 0x380)--- +* FREEPG_CNT[11..0] - (RO) Total page number of free +* RESERVED12[15..12] - (RO) Reserved bits +* FFA_CNT[27..16] - (RO) Free page numbers of free for all +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FREEPG_CNT_FFA_CNT_ADDR WF_PLE_TOP_FREEPG_CNT_ADDR +#define WF_PLE_TOP_FREEPG_CNT_FFA_CNT_MASK 0x0FFF0000 /* FFA_CNT[27..16] */ +#define WF_PLE_TOP_FREEPG_CNT_FFA_CNT_SHFT 16 +#define WF_PLE_TOP_FREEPG_CNT_FREEPG_CNT_ADDR WF_PLE_TOP_FREEPG_CNT_ADDR +#define WF_PLE_TOP_FREEPG_CNT_FREEPG_CNT_MASK 0x00000FFF /* FREEPG_CNT[11..0] */ +#define WF_PLE_TOP_FREEPG_CNT_FREEPG_CNT_SHFT 0 + +/* +* ---FREEPG_HEAD_TAIL (0x820C0000 + 0x384)--- +* FREEPG_HEAD[11..0] - (RO) Head page of free page list +* RESERVED12[15..12] - (RO) Reserved bits +* FREEPG_TAIL[27..16] - (RO) Tail page of free page list +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_ADDR \ + WF_PLE_TOP_FREEPG_HEAD_TAIL_ADDR +#define WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_MASK \ + 0x0FFF0000 /* FREEPG_TAIL[27..16] */ +#define WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_SHFT 16 +#define WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_ADDR \ + WF_PLE_TOP_FREEPG_HEAD_TAIL_ADDR +#define WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_MASK \ + 0x00000FFF /* FREEPG_HEAD[11..0] */ +#define WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_SHFT 0 + +/* +* ---HIF_PG_INFO (0x820C0000 + 0x388)--- +* HIF_RSV_CNT[11..0] - (RO) Reserved pages of HIF group +* RESERVED12[15..12] - (RO) Reserved bits +* HIF_SRC_CNT[27..16] - (RO) Used pages of HIF group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_HIF_PG_INFO_HIF_SRC_CNT_ADDR WF_PLE_TOP_HIF_PG_INFO_ADDR +#define WF_PLE_TOP_HIF_PG_INFO_HIF_SRC_CNT_MASK \ + 0x0FFF0000 /* HIF_SRC_CNT[27..16] */ +#define WF_PLE_TOP_HIF_PG_INFO_HIF_SRC_CNT_SHFT 16 +#define WF_PLE_TOP_HIF_PG_INFO_HIF_RSV_CNT_ADDR WF_PLE_TOP_HIF_PG_INFO_ADDR +#define WF_PLE_TOP_HIF_PG_INFO_HIF_RSV_CNT_MASK \ + 0x00000FFF /* HIF_RSV_CNT[11..0] */ +#define WF_PLE_TOP_HIF_PG_INFO_HIF_RSV_CNT_SHFT 0 + +/* +* ---HIF_WMTXD_PG_INFO (0x820C0000 + 0x38c)--- +* HIF_WMTXD_RSV_CNT[11..0] - (RO) Reserved pages of HIF WMCPU TXD group +* RESERVED12[15..12] - (RO) Reserved bits +* HIF_WMTXD_SRC_CNT[27..16] - (RO) Used pages of HIF WMCPU TXD group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_HIF_WMTXD_PG_INFO_HIF_WMTXD_SRC_CNT_ADDR \ + WF_PLE_TOP_HIF_WMTXD_PG_INFO_ADDR +#define WF_PLE_TOP_HIF_WMTXD_PG_INFO_HIF_WMTXD_SRC_CNT_MASK \ + 0x0FFF0000 /* HIF_WMTXD_SRC_CNT[27..16] */ +#define WF_PLE_TOP_HIF_WMTXD_PG_INFO_HIF_WMTXD_SRC_CNT_SHFT 16 +#define WF_PLE_TOP_HIF_WMTXD_PG_INFO_HIF_WMTXD_RSV_CNT_ADDR \ + WF_PLE_TOP_HIF_WMTXD_PG_INFO_ADDR +#define WF_PLE_TOP_HIF_WMTXD_PG_INFO_HIF_WMTXD_RSV_CNT_MASK \ + 0x00000FFF /* HIF_WMTXD_RSV_CNT[11..0] */ +#define WF_PLE_TOP_HIF_WMTXD_PG_INFO_HIF_WMTXD_RSV_CNT_SHFT 0 + +/* +* ---HIF_TXCMD_PG_INFO (0x820C0000 + 0x390)--- +* HIF_TXCMD_RSV_CNT[11..0] - (RO) Reserved pages of HIF TXCMD group +* RESERVED12[15..12] - (RO) Reserved bits +* HIF_TXCMD_SRC_CNT[27..16] - (RO) Used pages of HIF TXCMD group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_SRC_CNT_ADDR \ + WF_PLE_TOP_HIF_TXCMD_PG_INFO_ADDR +#define WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_SRC_CNT_MASK \ + 0x0FFF0000 /* HIF_TXCMD_SRC_CNT[27..16] */ +#define WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_SRC_CNT_SHFT 16 +#define WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_RSV_CNT_ADDR \ + WF_PLE_TOP_HIF_TXCMD_PG_INFO_ADDR +#define WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_RSV_CNT_MASK \ + 0x00000FFF /* HIF_TXCMD_RSV_CNT[11..0] */ +#define WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_RSV_CNT_SHFT 0 + +/* +* ---CPU_PG_INFO (0x820C0000 + 0x394)--- +* CPU_RSV_CNT[11..0] - (RO) Reserved pages of CPU group +* RESERVED12[15..12] - (RO) Reserved bits +* CPU_SRC_CNT[27..16] - (RO) Used pages of CPU group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CPU_PG_INFO_CPU_SRC_CNT_ADDR WF_PLE_TOP_CPU_PG_INFO_ADDR +#define WF_PLE_TOP_CPU_PG_INFO_CPU_SRC_CNT_MASK \ + 0x0FFF0000 /* CPU_SRC_CNT[27..16] */ +#define WF_PLE_TOP_CPU_PG_INFO_CPU_SRC_CNT_SHFT 16 +#define WF_PLE_TOP_CPU_PG_INFO_CPU_RSV_CNT_ADDR WF_PLE_TOP_CPU_PG_INFO_ADDR +#define WF_PLE_TOP_CPU_PG_INFO_CPU_RSV_CNT_MASK \ + 0x00000FFF /* CPU_RSV_CNT[11..0] */ +#define WF_PLE_TOP_CPU_PG_INFO_CPU_RSV_CNT_SHFT 0 + +/* +* ---PLE_LOG_0 (0x820C0000 + 0x3a0)--- +* PLE_LOG_0[31..0] - (RW) Log message for SW +*/ +#define WF_PLE_TOP_PLE_LOG_0_PLE_LOG_0_ADDR WF_PLE_TOP_PLE_LOG_0_ADDR +#define WF_PLE_TOP_PLE_LOG_0_PLE_LOG_0_MASK 0xFFFFFFFF /* PLE_LOG_0[31..0] */ +#define WF_PLE_TOP_PLE_LOG_0_PLE_LOG_0_SHFT 0 + +/* +* ---PLE_LOG_1 (0x820C0000 + 0x3a4)--- +* PLE_LOG_1[31..0] - (RW) Log message for SW +*/ +#define WF_PLE_TOP_PLE_LOG_1_PLE_LOG_1_ADDR WF_PLE_TOP_PLE_LOG_1_ADDR +#define WF_PLE_TOP_PLE_LOG_1_PLE_LOG_1_MASK 0xFFFFFFFF /* PLE_LOG_1[31..0] */ +#define WF_PLE_TOP_PLE_LOG_1_PLE_LOG_1_SHFT 0 + +/* +* ---PLE_LOG_2 (0x820C0000 + 0x3a8)--- +* PLE_LOG_2[31..0] - (RW) Log message for SW +*/ +#define WF_PLE_TOP_PLE_LOG_2_PLE_LOG_2_ADDR WF_PLE_TOP_PLE_LOG_2_ADDR +#define WF_PLE_TOP_PLE_LOG_2_PLE_LOG_2_MASK 0xFFFFFFFF /* PLE_LOG_2[31..0] */ +#define WF_PLE_TOP_PLE_LOG_2_PLE_LOG_2_SHFT 0 + +/* +* ---PLE_LOG_3 (0x820C0000 + 0x3ac)--- +* PLE_LOG_3[31..0] - (RW) Log message for SW +*/ +#define WF_PLE_TOP_PLE_LOG_3_PLE_LOG_3_ADDR WF_PLE_TOP_PLE_LOG_3_ADDR +#define WF_PLE_TOP_PLE_LOG_3_PLE_LOG_3_MASK 0xFFFFFFFF /* PLE_LOG_3[31..0] */ +#define WF_PLE_TOP_PLE_LOG_3_PLE_LOG_3_SHFT 0 + +/* +* ---WMMAC_PGCNT_0 (0x820C0000 + 0x3b0)--- +* WMMAC_00_PGCNT[11..0] - (RO) WMMAC 00 used page count +* RESERVED12[15..12] - (RO) Reserved bits +* WMMAC_01_PGCNT[27..16] - (RO) WMMAC 01 used page count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_WMMAC_PGCNT_0_WMMAC_01_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_0_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_0_WMMAC_01_PGCNT_MASK \ + 0x0FFF0000 /* WMMAC_01_PGCNT[27..16] */ +#define WF_PLE_TOP_WMMAC_PGCNT_0_WMMAC_01_PGCNT_SHFT 16 +#define WF_PLE_TOP_WMMAC_PGCNT_0_WMMAC_00_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_0_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_0_WMMAC_00_PGCNT_MASK \ + 0x00000FFF /* WMMAC_00_PGCNT[11..0] */ +#define WF_PLE_TOP_WMMAC_PGCNT_0_WMMAC_00_PGCNT_SHFT 0 + +/* +* ---WMMAC_PGCNT_1 (0x820C0000 + 0x3b4)--- +* WMMAC_02_PGCNT[11..0] - (RO) WMMAC 02 used page count +* RESERVED12[15..12] - (RO) Reserved bits +* WMMAC_03_PGCNT[27..16] - (RO) WMMAC 03 used page count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_WMMAC_PGCNT_1_WMMAC_03_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_1_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_1_WMMAC_03_PGCNT_MASK \ + 0x0FFF0000 /* WMMAC_03_PGCNT[27..16] */ +#define WF_PLE_TOP_WMMAC_PGCNT_1_WMMAC_03_PGCNT_SHFT 16 +#define WF_PLE_TOP_WMMAC_PGCNT_1_WMMAC_02_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_1_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_1_WMMAC_02_PGCNT_MASK \ + 0x00000FFF /* WMMAC_02_PGCNT[11..0] */ +#define WF_PLE_TOP_WMMAC_PGCNT_1_WMMAC_02_PGCNT_SHFT 0 + +/* +* ---WMMAC_PGCNT_2 (0x820C0000 + 0x3b8)--- +* WMMAC_10_PGCNT[11..0] - (RO) WMMAC 10 used page count +* RESERVED12[15..12] - (RO) Reserved bits +* WMMAC_11_PGCNT[27..16] - (RO) WMMAC 11 used page count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_WMMAC_PGCNT_2_WMMAC_11_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_2_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_2_WMMAC_11_PGCNT_MASK \ + 0x0FFF0000 /* WMMAC_11_PGCNT[27..16] */ +#define WF_PLE_TOP_WMMAC_PGCNT_2_WMMAC_11_PGCNT_SHFT 16 +#define WF_PLE_TOP_WMMAC_PGCNT_2_WMMAC_10_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_2_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_2_WMMAC_10_PGCNT_MASK \ + 0x00000FFF /* WMMAC_10_PGCNT[11..0] */ +#define WF_PLE_TOP_WMMAC_PGCNT_2_WMMAC_10_PGCNT_SHFT 0 + +/* +* ---WMMAC_PGCNT_3 (0x820C0000 + 0x3bc)--- +* WMMAC_12_PGCNT[11..0] - (RO) WMMAC 12 used page count +* RESERVED12[15..12] - (RO) Reserved bits +* WMMAC_13_PGCNT[27..16] - (RO) WMMAC 13 used page count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_WMMAC_PGCNT_3_WMMAC_13_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_3_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_3_WMMAC_13_PGCNT_MASK \ + 0x0FFF0000 /* WMMAC_13_PGCNT[27..16] */ +#define WF_PLE_TOP_WMMAC_PGCNT_3_WMMAC_13_PGCNT_SHFT 16 +#define WF_PLE_TOP_WMMAC_PGCNT_3_WMMAC_12_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_3_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_3_WMMAC_12_PGCNT_MASK \ + 0x00000FFF /* WMMAC_12_PGCNT[11..0] */ +#define WF_PLE_TOP_WMMAC_PGCNT_3_WMMAC_12_PGCNT_SHFT 0 + +/* +* ---WMMAC_PGCNT_4 (0x820C0000 + 0x3c0)--- +* WMMAC_20_PGCNT[11..0] - (RO) WMMAC 20 used page count +* RESERVED12[15..12] - (RO) Reserved bits +* WMMAC_21_PGCNT[27..16] - (RO) WMMAC 21 used page count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_WMMAC_PGCNT_4_WMMAC_21_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_4_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_4_WMMAC_21_PGCNT_MASK \ + 0x0FFF0000 /* WMMAC_21_PGCNT[27..16] */ +#define WF_PLE_TOP_WMMAC_PGCNT_4_WMMAC_21_PGCNT_SHFT 16 +#define WF_PLE_TOP_WMMAC_PGCNT_4_WMMAC_20_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_4_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_4_WMMAC_20_PGCNT_MASK \ + 0x00000FFF /* WMMAC_20_PGCNT[11..0] */ +#define WF_PLE_TOP_WMMAC_PGCNT_4_WMMAC_20_PGCNT_SHFT 0 + +/* +* ---WMMAC_PGCNT_5 (0x820C0000 + 0x3c4)--- +* WMMAC_22_PGCNT[11..0] - (RO) WMMAC 22 used page count +* RESERVED12[15..12] - (RO) Reserved bits +* WMMAC_23_PGCNT[27..16] - (RO) WMMAC 23 used page count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_WMMAC_PGCNT_5_WMMAC_23_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_5_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_5_WMMAC_23_PGCNT_MASK \ + 0x0FFF0000 /* WMMAC_23_PGCNT[27..16] */ +#define WF_PLE_TOP_WMMAC_PGCNT_5_WMMAC_23_PGCNT_SHFT 16 +#define WF_PLE_TOP_WMMAC_PGCNT_5_WMMAC_22_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_5_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_5_WMMAC_22_PGCNT_MASK \ + 0x00000FFF /* WMMAC_22_PGCNT[11..0] */ +#define WF_PLE_TOP_WMMAC_PGCNT_5_WMMAC_22_PGCNT_SHFT 0 + +/* +* ---WMMAC_PGCNT_6 (0x820C0000 + 0x3c8)--- +* WMMAC_30_PGCNT[11..0] - (RO) WMMAC 30 used page count +* RESERVED12[15..12] - (RO) Reserved bits +* WMMAC_31_PGCNT[27..16] - (RO) WMMAC 31 used page count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_WMMAC_PGCNT_6_WMMAC_31_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_6_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_6_WMMAC_31_PGCNT_MASK \ + 0x0FFF0000 /* WMMAC_31_PGCNT[27..16] */ +#define WF_PLE_TOP_WMMAC_PGCNT_6_WMMAC_31_PGCNT_SHFT 16 +#define WF_PLE_TOP_WMMAC_PGCNT_6_WMMAC_30_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_6_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_6_WMMAC_30_PGCNT_MASK \ + 0x00000FFF /* WMMAC_30_PGCNT[11..0] */ +#define WF_PLE_TOP_WMMAC_PGCNT_6_WMMAC_30_PGCNT_SHFT 0 + +/* +* ---WMMAC_PGCNT_7 (0x820C0000 + 0x3cc)--- +* WMMAC_32_PGCNT[11..0] - (RO) WMMAC 32 used page count +* RESERVED12[15..12] - (RO) Reserved bits +* WMMAC_33_PGCNT[27..16] - (RO) WMMAC 33 used page count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_WMMAC_PGCNT_7_WMMAC_33_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_7_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_7_WMMAC_33_PGCNT_MASK \ + 0x0FFF0000 /* WMMAC_33_PGCNT[27..16] */ +#define WF_PLE_TOP_WMMAC_PGCNT_7_WMMAC_33_PGCNT_SHFT 16 +#define WF_PLE_TOP_WMMAC_PGCNT_7_WMMAC_32_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_7_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_7_WMMAC_32_PGCNT_MASK \ + 0x00000FFF /* WMMAC_32_PGCNT[11..0] */ +#define WF_PLE_TOP_WMMAC_PGCNT_7_WMMAC_32_PGCNT_SHFT 0 + +/* +* ---RL_BUF_CTRL_0 (0x820C0000 + 0x3d0)--- +* RELAY_BUF_ADDR[11..0] - (RW) Read address of relay buffer +* RESERVED12[30..12] - (RO) Reserved bits +* EXECUTE[31] - (A0) Executes relay buffer read command +*/ +#define WF_PLE_TOP_RL_BUF_CTRL_0_EXECUTE_ADDR WF_PLE_TOP_RL_BUF_CTRL_0_ADDR +#define WF_PLE_TOP_RL_BUF_CTRL_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_RL_BUF_CTRL_0_EXECUTE_SHFT 31 +#define WF_PLE_TOP_RL_BUF_CTRL_0_RELAY_BUF_ADDR_ADDR \ + WF_PLE_TOP_RL_BUF_CTRL_0_ADDR +#define WF_PLE_TOP_RL_BUF_CTRL_0_RELAY_BUF_ADDR_MASK \ + 0x00000FFF /* RELAY_BUF_ADDR[11..0] */ +#define WF_PLE_TOP_RL_BUF_CTRL_0_RELAY_BUF_ADDR_SHFT 0 + +/* +* ---RL_BUF_CTRL_1 (0x820C0000 + 0x3d4)--- +* PAGE_NUM_0[0] - (RO) Page number[0] of packet +* PKT_LEN[11..1] - (RO) Length of the packet with head page +* being the relay buffer address +* Unit: 32 bytes +* PKT_TAIL_PAGE[23..12] - (RO) Tail page of the packet with head page +* being the relay buffer address +* RESV_GRP_ID[24] - (RO) Group ID of reserved page used by FID +* RESERVED25[25] - (RO) Reserved bits +* PAGE_NUM_1[27..26] - (RO) Page number[2:1] of packet +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_RL_BUF_CTRL_1_PAGE_NUM_1_ADDR WF_PLE_TOP_RL_BUF_CTRL_1_ADDR +#define WF_PLE_TOP_RL_BUF_CTRL_1_PAGE_NUM_1_MASK \ + 0x0C000000 /* PAGE_NUM_1[27..26] */ +#define WF_PLE_TOP_RL_BUF_CTRL_1_PAGE_NUM_1_SHFT 26 +#define WF_PLE_TOP_RL_BUF_CTRL_1_RESV_GRP_ID_ADDR WF_PLE_TOP_RL_BUF_CTRL_1_ADDR +#define WF_PLE_TOP_RL_BUF_CTRL_1_RESV_GRP_ID_MASK \ + 0x01000000 /* RESV_GRP_ID[24] */ +#define WF_PLE_TOP_RL_BUF_CTRL_1_RESV_GRP_ID_SHFT 24 +#define WF_PLE_TOP_RL_BUF_CTRL_1_PKT_TAIL_PAGE_ADDR \ + WF_PLE_TOP_RL_BUF_CTRL_1_ADDR +#define WF_PLE_TOP_RL_BUF_CTRL_1_PKT_TAIL_PAGE_MASK \ + 0x00FFF000 /* PKT_TAIL_PAGE[23..12] */ +#define WF_PLE_TOP_RL_BUF_CTRL_1_PKT_TAIL_PAGE_SHFT 12 +#define WF_PLE_TOP_RL_BUF_CTRL_1_PKT_LEN_ADDR WF_PLE_TOP_RL_BUF_CTRL_1_ADDR +#define WF_PLE_TOP_RL_BUF_CTRL_1_PKT_LEN_MASK 0x00000FFE /* PKT_LEN[11..1] */ +#define WF_PLE_TOP_RL_BUF_CTRL_1_PKT_LEN_SHFT 1 +#define WF_PLE_TOP_RL_BUF_CTRL_1_PAGE_NUM_0_ADDR WF_PLE_TOP_RL_BUF_CTRL_1_ADDR +#define WF_PLE_TOP_RL_BUF_CTRL_1_PAGE_NUM_0_MASK 0x00000001 /* PAGE_NUM_0[0] */ +#define WF_PLE_TOP_RL_BUF_CTRL_1_PAGE_NUM_0_SHFT 0 + +/* +* ---FL_QUE_CTRL_0 (0x820C0000 + 0x3e0)--- +* Q_BUF_WLANID[9..0] - (RW) Address of queue structure buffer +WLANID. +* Q_BUF_PID[11..10] - (RW) Address of queue structure buffer PID +* FL_BUFFER_ADDR[23..12] - (RW) Frame address of read previous +* frame/next frame +* Q_BUF_QID[30..24] - (RW) Address of queue structure buffer QID +* EXECUTE[31] - (A0) Executes frame link and queue structure +* buffer read command +*/ +#define WF_PLE_TOP_FL_QUE_CTRL_0_EXECUTE_ADDR WF_PLE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_FL_QUE_CTRL_0_EXECUTE_SHFT 31 +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_ADDR WF_PLE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_MASK \ + 0x7F000000 /* Q_BUF_QID[30..24] */ +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_SHFT 24 +#define WF_PLE_TOP_FL_QUE_CTRL_0_FL_BUFFER_ADDR_ADDR \ + WF_PLE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_0_FL_BUFFER_ADDR_MASK \ + 0x00FFF000 /* FL_BUFFER_ADDR[23..12] */ +#define WF_PLE_TOP_FL_QUE_CTRL_0_FL_BUFFER_ADDR_SHFT 12 +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_ADDR WF_PLE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_MASK \ + 0x00000C00 /* Q_BUF_PID[11..10] */ +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_SHFT 10 +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_WLANID_ADDR WF_PLE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_WLANID_MASK \ + 0x000003FF /* Q_BUF_WLANID[9..0] */ +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_WLANID_SHFT 0 + +/* +* ---FL_QUE_CTRL_1 (0x820C0000 + 0x3e4)--- +* NEXT_FID[11..0] - (RO) Next frame ID of FL_BUFFER_ADDR +* RESERVED12[15..12] - (RO) Reserved bits +* PREV_FID[27..16] - (RO) Previous frame ID of FL_BUFFER_ADDR +* RESERVED28[30..28] - (RO) Reserved bits +* Q_BUF_TGID[31] - (RW) Address of queue structure buffer TGID +*/ +#define WF_PLE_TOP_FL_QUE_CTRL_1_Q_BUF_TGID_ADDR WF_PLE_TOP_FL_QUE_CTRL_1_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_1_Q_BUF_TGID_MASK 0x80000000 /* Q_BUF_TGID[31] */ +#define WF_PLE_TOP_FL_QUE_CTRL_1_Q_BUF_TGID_SHFT 31 +#define WF_PLE_TOP_FL_QUE_CTRL_1_PREV_FID_ADDR WF_PLE_TOP_FL_QUE_CTRL_1_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_1_PREV_FID_MASK 0x0FFF0000 /* PREV_FID[27..16] */ +#define WF_PLE_TOP_FL_QUE_CTRL_1_PREV_FID_SHFT 16 +#define WF_PLE_TOP_FL_QUE_CTRL_1_NEXT_FID_ADDR WF_PLE_TOP_FL_QUE_CTRL_1_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_1_NEXT_FID_MASK 0x00000FFF /* NEXT_FID[11..0] */ +#define WF_PLE_TOP_FL_QUE_CTRL_1_NEXT_FID_SHFT 0 + +/* +* ---FL_QUE_CTRL_2 (0x820C0000 + 0x3e8)--- +* QUEUE_HEAD_FID[11..0] - (RO) Head frame ID of the quest queue setting +* in 0x01b0[15:0] +* RESERVED12[15..12] - (RO) Reserved bits +* QUEUE_TAIL_FID[27..16] - (RO) Tail frame ID of the quest queue setting +* in 0x01b0[15:0] +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_ADDR \ + WF_PLE_TOP_FL_QUE_CTRL_2_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_MASK \ + 0x0FFF0000 /* QUEUE_TAIL_FID[27..16] */ +#define WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_SHFT 16 +#define WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_ADDR \ + WF_PLE_TOP_FL_QUE_CTRL_2_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_MASK \ + 0x00000FFF /* QUEUE_HEAD_FID[11..0] */ +#define WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_SHFT 0 + +/* +* ---FL_QUE_CTRL_3 (0x820C0000 + 0x3ec)--- +* QUEUE_PKT_NUM[11..0] - (RO) Total packet number of the queue +* setting in 0x1b0[15:0] +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_ADDR \ + WF_PLE_TOP_FL_QUE_CTRL_3_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_MASK \ + 0x00000FFF /* QUEUE_PKT_NUM[11..0] */ +#define WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_SHFT 0 + +/* +* ---PL_QUE_CTRL_0 (0x820C0000 + 0x3f0)--- +* NEXT_PAGE[11..0] - (RO) Next page of PL_BUFFER_ADDR +* RESERVED12[15..12] - (RO) Reserved bits +* PL_BUFFER_ADDR[27..16] - (RW) Page address of read next page +* RESERVED28[30..28] - (RO) Reserved bits +* EXECUTE[31] - (A0) Executes page link buffer read command +*/ +#define WF_PLE_TOP_PL_QUE_CTRL_0_EXECUTE_ADDR WF_PLE_TOP_PL_QUE_CTRL_0_ADDR +#define WF_PLE_TOP_PL_QUE_CTRL_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_PL_QUE_CTRL_0_EXECUTE_SHFT 31 +#define WF_PLE_TOP_PL_QUE_CTRL_0_PL_BUFFER_ADDR_ADDR \ + WF_PLE_TOP_PL_QUE_CTRL_0_ADDR +#define WF_PLE_TOP_PL_QUE_CTRL_0_PL_BUFFER_ADDR_MASK \ + 0x0FFF0000 /* PL_BUFFER_ADDR[27..16] */ +#define WF_PLE_TOP_PL_QUE_CTRL_0_PL_BUFFER_ADDR_SHFT 16 +#define WF_PLE_TOP_PL_QUE_CTRL_0_NEXT_PAGE_ADDR WF_PLE_TOP_PL_QUE_CTRL_0_ADDR +#define WF_PLE_TOP_PL_QUE_CTRL_0_NEXT_PAGE_MASK \ + 0x00000FFF /* NEXT_PAGE[11..0] */ +#define WF_PLE_TOP_PL_QUE_CTRL_0_NEXT_PAGE_SHFT 0 + +/* +* ---HIF_ENQ_PKT_NUM (0x820C0000 + 0x400)--- +* HIF_ENQ_CPU_PKT_NUM[15..0] - (RO) Packet number of HIF enqueue to CPU, +* just keep in 16bits. +* HIF_ENQ_LMAC_PKT_NUM[31..16] - (RO) Packet number of HIF enqueue to LMAC, +* just keep in 16 bits +*/ +#define WF_PLE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_LMAC_PKT_NUM_ADDR \ + WF_PLE_TOP_HIF_ENQ_PKT_NUM_ADDR +#define WF_PLE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_LMAC_PKT_NUM_MASK \ + 0xFFFF0000 /* HIF_ENQ_LMAC_PKT_NUM[31..16] */ +#define WF_PLE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_LMAC_PKT_NUM_SHFT 16 +#define WF_PLE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_CPU_PKT_NUM_ADDR \ + WF_PLE_TOP_HIF_ENQ_PKT_NUM_ADDR +#define WF_PLE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_CPU_PKT_NUM_MASK \ + 0x0000FFFF /* HIF_ENQ_CPU_PKT_NUM[15..0] */ +#define WF_PLE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_CPU_PKT_NUM_SHFT 0 + +/* +* ---CPU_ENQ_PKT_NUM (0x820C0000 + 0x404)--- +* CPU_ENQ_LMAC_PKT_NUM[15..0] - (RO) Packet number of CPU enqueue to LMAC, +* just keep in 16 bits. +* RESV[31..16] - (RO) Reserved +*/ +#define WF_PLE_TOP_CPU_ENQ_PKT_NUM_RESV_ADDR WF_PLE_TOP_CPU_ENQ_PKT_NUM_ADDR +#define WF_PLE_TOP_CPU_ENQ_PKT_NUM_RESV_MASK 0xFFFF0000 /* RESV[31..16] */ +#define WF_PLE_TOP_CPU_ENQ_PKT_NUM_RESV_SHFT 16 +#define WF_PLE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_LMAC_PKT_NUM_ADDR \ + WF_PLE_TOP_CPU_ENQ_PKT_NUM_ADDR +#define WF_PLE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_LMAC_PKT_NUM_MASK \ + 0x0000FFFF /* CPU_ENQ_LMAC_PKT_NUM[15..0] */ +#define WF_PLE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_LMAC_PKT_NUM_SHFT 0 + +/* +* ---RLS_MSDU_PKT_NUM (0x820C0000 + 0x408)--- +* RSL_RPT_TXD_NUM[15..0] - (RO) TXD number of host report function +* RSL_MSDUID_NUM[31..16] - (RO) Release MSDU_ID number of host report +function +*/ +#define WF_PLE_TOP_RLS_MSDU_PKT_NUM_RSL_MSDUID_NUM_ADDR \ + WF_PLE_TOP_RLS_MSDU_PKT_NUM_ADDR +#define WF_PLE_TOP_RLS_MSDU_PKT_NUM_RSL_MSDUID_NUM_MASK \ + 0xFFFF0000 /* RSL_MSDUID_NUM[31..16] */ +#define WF_PLE_TOP_RLS_MSDU_PKT_NUM_RSL_MSDUID_NUM_SHFT 16 +#define WF_PLE_TOP_RLS_MSDU_PKT_NUM_RSL_RPT_TXD_NUM_ADDR \ + WF_PLE_TOP_RLS_MSDU_PKT_NUM_ADDR +#define WF_PLE_TOP_RLS_MSDU_PKT_NUM_RSL_RPT_TXD_NUM_MASK \ + 0x0000FFFF /* RSL_RPT_TXD_NUM[15..0] */ +#define WF_PLE_TOP_RLS_MSDU_PKT_NUM_RSL_RPT_TXD_NUM_SHFT 0 + +/* +* ---HOST_REPORT_NUM (0x820C0000 + 0x40c)--- +* RSL_TXD_NUM[15..0] - (RO) All TXD number of release function, +* include the no host report(not CT) TXD packets. +* HOST_REPORT_NUM[31..16] - (RO) Host report number that be the PSE +* packets carry release MSDU_ID information +*/ +#define WF_PLE_TOP_HOST_REPORT_NUM_HOST_REPORT_NUM_ADDR \ + WF_PLE_TOP_HOST_REPORT_NUM_ADDR +#define WF_PLE_TOP_HOST_REPORT_NUM_HOST_REPORT_NUM_MASK \ + 0xFFFF0000 /* HOST_REPORT_NUM[31..16] */ +#define WF_PLE_TOP_HOST_REPORT_NUM_HOST_REPORT_NUM_SHFT 16 +#define WF_PLE_TOP_HOST_REPORT_NUM_RSL_TXD_NUM_ADDR \ + WF_PLE_TOP_HOST_REPORT_NUM_ADDR +#define WF_PLE_TOP_HOST_REPORT_NUM_RSL_TXD_NUM_MASK \ + 0x0000FFFF /* RSL_TXD_NUM[15..0] */ +#define WF_PLE_TOP_HOST_REPORT_NUM_RSL_TXD_NUM_SHFT 0 + +/* +* ---UMAC_DBG_CTRL (0x820C0000 + 0x410)--- +* UMAC_DBG_FUNC_SEL[3..0] - (RW) Selects UMAC debug mode +* RESERVED4[7..4] - (RO) Reserved bits +* PLE_DBG_FLAG_A_NIB_EN[11..8] - (RW) Enable control of PLE debug flag A +nibble +* PLE_DBG_FLAG_B_NIB_EN[15..12] - (RW) Enable control of PLE debug flag B +nibble +* PSE_DBG_FLAG_A_NIB_EN[19..16] - (RW) Enable control of PSE debug flag A +nibble +* PSE_DBG_FLAG_B_NIB_EN[23..20] - (RW) Enable control of PSE debug flag B +nibble +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_UMAC_DBG_CTRL_PSE_DBG_FLAG_B_NIB_EN_ADDR \ + WF_PLE_TOP_UMAC_DBG_CTRL_ADDR +#define WF_PLE_TOP_UMAC_DBG_CTRL_PSE_DBG_FLAG_B_NIB_EN_MASK \ + 0x00F00000 /* PSE_DBG_FLAG_B_NIB_EN[23..20] */ +#define WF_PLE_TOP_UMAC_DBG_CTRL_PSE_DBG_FLAG_B_NIB_EN_SHFT 20 +#define WF_PLE_TOP_UMAC_DBG_CTRL_PSE_DBG_FLAG_A_NIB_EN_ADDR \ + WF_PLE_TOP_UMAC_DBG_CTRL_ADDR +#define WF_PLE_TOP_UMAC_DBG_CTRL_PSE_DBG_FLAG_A_NIB_EN_MASK \ + 0x000F0000 /* PSE_DBG_FLAG_A_NIB_EN[19..16] */ +#define WF_PLE_TOP_UMAC_DBG_CTRL_PSE_DBG_FLAG_A_NIB_EN_SHFT 16 +#define WF_PLE_TOP_UMAC_DBG_CTRL_PLE_DBG_FLAG_B_NIB_EN_ADDR \ + WF_PLE_TOP_UMAC_DBG_CTRL_ADDR +#define WF_PLE_TOP_UMAC_DBG_CTRL_PLE_DBG_FLAG_B_NIB_EN_MASK \ + 0x0000F000 /* PLE_DBG_FLAG_B_NIB_EN[15..12] */ +#define WF_PLE_TOP_UMAC_DBG_CTRL_PLE_DBG_FLAG_B_NIB_EN_SHFT 12 +#define WF_PLE_TOP_UMAC_DBG_CTRL_PLE_DBG_FLAG_A_NIB_EN_ADDR \ + WF_PLE_TOP_UMAC_DBG_CTRL_ADDR +#define WF_PLE_TOP_UMAC_DBG_CTRL_PLE_DBG_FLAG_A_NIB_EN_MASK \ + 0x00000F00 /* PLE_DBG_FLAG_A_NIB_EN[11..8] */ +#define WF_PLE_TOP_UMAC_DBG_CTRL_PLE_DBG_FLAG_A_NIB_EN_SHFT 8 +#define WF_PLE_TOP_UMAC_DBG_CTRL_UMAC_DBG_FUNC_SEL_ADDR \ + WF_PLE_TOP_UMAC_DBG_CTRL_ADDR +#define WF_PLE_TOP_UMAC_DBG_CTRL_UMAC_DBG_FUNC_SEL_MASK \ + 0x0000000F /* UMAC_DBG_FUNC_SEL[3..0] */ +#define WF_PLE_TOP_UMAC_DBG_CTRL_UMAC_DBG_FUNC_SEL_SHFT 0 + +/* +* ---PLE_DBG_A_BYTE_SEL (0x820C0000 + 0x414)--- +* PLE_DBG_FLAG_A_BYTE0_SEL[7..0] - (RW) Debug flag selection of PLE debug A +* byte 0 +* PLE_DBG_FLAG_A_BYTE1_SEL[15..8] - (RW) Debug flag selection of PLE debug A +* byte 1 +* PLE_DBG_FLAG_A_BYTE2_SEL[23..16] - (RW) Debug flag selection of PLE debug A +* byte 2 +* PLE_DBG_FLAG_A_BYTE3_SEL[31..24] - (RW) Debug flag selection of PLE debug A +* byte 3 +*/ +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE3_SEL_ADDR \ + WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_ADDR +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE3_SEL_MASK \ + 0xFF000000 /* PLE_DBG_FLAG_A_BYTE3_SEL[31..24] */ +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE3_SEL_SHFT 24 +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE2_SEL_ADDR \ + WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_ADDR +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE2_SEL_MASK \ + 0x00FF0000 /* PLE_DBG_FLAG_A_BYTE2_SEL[23..16] */ +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE2_SEL_SHFT 16 +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE1_SEL_ADDR \ + WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_ADDR +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE1_SEL_MASK \ + 0x0000FF00 /* PLE_DBG_FLAG_A_BYTE1_SEL[15..8] */ +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE1_SEL_SHFT 8 +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE0_SEL_ADDR \ + WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_ADDR +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE0_SEL_MASK \ + 0x000000FF /* PLE_DBG_FLAG_A_BYTE0_SEL[7..0] */ +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE0_SEL_SHFT 0 + +/* +* ---PLE_DBG_B_BYTE_SEL (0x820C0000 + 0x418)--- +* PLE_DBG_FLAG_B_BYTE0_SEL[7..0] - (RW) Debug flag selection of PLE debug B +* byte 0 +* PLE_DBG_FLAG_B_BYTE1_SEL[15..8] - (RW) Debug flag selection of PLE debug B +* byte 1 +* PLE_DBG_FLAG_B_BYTE2_SEL[23..16] - (RW) Debug flag selection of PLE debug B +* byte 2 +* PLE_DBG_FLAG_B_BYTE3_SEL[31..24] - (RW) Debug flag selection of PLE debug B +* byte 3 +*/ +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE3_SEL_ADDR \ + WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_ADDR +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE3_SEL_MASK \ + 0xFF000000 /* PLE_DBG_FLAG_B_BYTE3_SEL[31..24] */ +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE3_SEL_SHFT 24 +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE2_SEL_ADDR \ + WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_ADDR +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE2_SEL_MASK \ + 0x00FF0000 /* PLE_DBG_FLAG_B_BYTE2_SEL[23..16] */ +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE2_SEL_SHFT 16 +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE1_SEL_ADDR \ + WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_ADDR +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE1_SEL_MASK \ + 0x0000FF00 /* PLE_DBG_FLAG_B_BYTE1_SEL[15..8] */ +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE1_SEL_SHFT 8 +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE0_SEL_ADDR \ + WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_ADDR +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE0_SEL_MASK \ + 0x000000FF /* PLE_DBG_FLAG_B_BYTE0_SEL[7..0] */ +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE0_SEL_SHFT 0 + +/* +* ---FUNC_ACT_CNT_1 (0x820C0000 + 0x424)--- +* MACTX0_ACT_CNT[3..0] - (RO) Counter of MACTX0 TX active. +* MACTX0_NOR_END_CNT[7..4] - (RO) Counter of MACTX0 TX normal end. +* MACTX0_ABORT_CNT[11..8] - (RO) Counter of MACTX0 TX abort. +* RESERVED12[15..12] - (RO) Reserved bits +* TXCMD0_ADD_FID_CNT[19..16] - (RO) Counter of TXCMD0 TX add FID. +* TXCMD0_NOR_END_CNT[23..20] - (RO) Counter of TXCMD0 TX normal end. +* TXCMD0_ABORT_CNT[27..24] - (RO) Counter of TXCMD0 TX abort. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_ABORT_CNT_ADDR \ + WF_PLE_TOP_FUNC_ACT_CNT_1_ADDR +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_ABORT_CNT_MASK \ + 0x0F000000 /* TXCMD0_ABORT_CNT[27..24] */ +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_ABORT_CNT_SHFT 24 +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_NOR_END_CNT_ADDR \ + WF_PLE_TOP_FUNC_ACT_CNT_1_ADDR +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_NOR_END_CNT_MASK \ + 0x00F00000 /* TXCMD0_NOR_END_CNT[23..20] */ +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_NOR_END_CNT_SHFT 20 +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_ADD_FID_CNT_ADDR \ + WF_PLE_TOP_FUNC_ACT_CNT_1_ADDR +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_ADD_FID_CNT_MASK \ + 0x000F0000 /* TXCMD0_ADD_FID_CNT[19..16] */ +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_ADD_FID_CNT_SHFT 16 +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_ABORT_CNT_ADDR \ + WF_PLE_TOP_FUNC_ACT_CNT_1_ADDR +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_ABORT_CNT_MASK \ + 0x00000F00 /* MACTX0_ABORT_CNT[11..8] */ +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_ABORT_CNT_SHFT 8 +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_NOR_END_CNT_ADDR \ + WF_PLE_TOP_FUNC_ACT_CNT_1_ADDR +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_NOR_END_CNT_MASK \ + 0x000000F0 /* MACTX0_NOR_END_CNT[7..4] */ +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_NOR_END_CNT_SHFT 4 +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_ACT_CNT_ADDR \ + WF_PLE_TOP_FUNC_ACT_CNT_1_ADDR +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_ACT_CNT_MASK \ + 0x0000000F /* MACTX0_ACT_CNT[3..0] */ +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_ACT_CNT_SHFT 0 + +/* +* ---SRAM_MBIST_BACKGROUND (0x820C0000 + 0x430)--- +* MBIST_BACKGROUND[15..0] - (RW) bsel setting for PLE SRAM MBIST circuit +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SRAM_MBIST_BACKGROUND_MBIST_BACKGROUND_ADDR \ + WF_PLE_TOP_SRAM_MBIST_BACKGROUND_ADDR +#define WF_PLE_TOP_SRAM_MBIST_BACKGROUND_MBIST_BACKGROUND_MASK \ + 0x0000FFFF /* MBIST_BACKGROUND[15..0] */ +#define WF_PLE_TOP_SRAM_MBIST_BACKGROUND_MBIST_BACKGROUND_SHFT 0 + +/* +* ---SRAM_MBIST_BSEL (0x820C0000 + 0x434)--- +* MBIST_BSEL[15..0] - (RW) The bsel setting for PLE SRAM MBIST +circuit. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SRAM_MBIST_BSEL_MBIST_BSEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_BSEL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_BSEL_MBIST_BSEL_MASK \ + 0x0000FFFF /* MBIST_BSEL[15..0] */ +#define WF_PLE_TOP_SRAM_MBIST_BSEL_MBIST_BSEL_SHFT 0 + +/* +* ---SRAM_MBIST_DONE (0x820C0000 + 0x438)--- +* G1_MBIST_DONE[0] - (RO) Working status of PLE G1 SRAM MBIST +circuit +* G2_MBIST_DONE[1] - (RO) Working status of PLE G2 SRAM MBIST +circuit +* RESERVED2[31..2] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SRAM_MBIST_DONE_G2_MBIST_DONE_ADDR \ + WF_PLE_TOP_SRAM_MBIST_DONE_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DONE_G2_MBIST_DONE_MASK \ + 0x00000002 /* G2_MBIST_DONE[1] */ +#define WF_PLE_TOP_SRAM_MBIST_DONE_G2_MBIST_DONE_SHFT 1 +#define WF_PLE_TOP_SRAM_MBIST_DONE_G1_MBIST_DONE_ADDR \ + WF_PLE_TOP_SRAM_MBIST_DONE_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DONE_G1_MBIST_DONE_MASK \ + 0x00000001 /* G1_MBIST_DONE[0] */ +#define WF_PLE_TOP_SRAM_MBIST_DONE_G1_MBIST_DONE_SHFT 0 + +/* +* ---SRAM_MBIST_FAIL (0x820C0000 + 0x43c)--- +* G1_SRAM0_MBIST_FAIL[0] - (RO) MBIST check result of group 1 SRAM0 +* G1_SRAM1_MBIST_FAIL[1] - (RO) MBIST check result of group 1 SRAM1 +* G1_SRAM2_MBIST_FAIL[2] - (RO) MBIST check result of group 1 SRAM2 +* G1_SRAM3_MBIST_FAIL[3] - (RO) MBIST check result of group 1 SRAM3 +* G2_SRAM0_MBIST_FAIL[4] - (RO) MBIST check result of group 2 SRAM0 +* G2_SRAM1_MBIST_FAIL[5] - (RO) MBIST check result of group 2 SRAM1 +* G2_SRAM2_MBIST_FAIL[6] - (RO) MBIST check result of group 2 SRAM2 +* G2_SRAM3_MBIST_FAIL[7] - (RO) MBIST check result of group 2 SRAM3 +* G2_SRAM4_MBIST_FAIL[8] - (RO) MBIST check result of group 2 SRAM4 +* G2_SRAM5_MBIST_FAIL[9] - (RO) MBIST check result of group 2 SRAM5 +* RESERVED10[31..10] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM5_MBIST_FAIL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM5_MBIST_FAIL_MASK \ + 0x00000200 /* G2_SRAM5_MBIST_FAIL[9] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM5_MBIST_FAIL_SHFT 9 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM4_MBIST_FAIL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM4_MBIST_FAIL_MASK \ + 0x00000100 /* G2_SRAM4_MBIST_FAIL[8] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM4_MBIST_FAIL_SHFT 8 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM3_MBIST_FAIL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM3_MBIST_FAIL_MASK \ + 0x00000080 /* G2_SRAM3_MBIST_FAIL[7] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM3_MBIST_FAIL_SHFT 7 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM2_MBIST_FAIL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM2_MBIST_FAIL_MASK \ + 0x00000040 /* G2_SRAM2_MBIST_FAIL[6] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM2_MBIST_FAIL_SHFT 6 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM1_MBIST_FAIL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM1_MBIST_FAIL_MASK \ + 0x00000020 /* G2_SRAM1_MBIST_FAIL[5] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM1_MBIST_FAIL_SHFT 5 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM0_MBIST_FAIL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM0_MBIST_FAIL_MASK \ + 0x00000010 /* G2_SRAM0_MBIST_FAIL[4] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM0_MBIST_FAIL_SHFT 4 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM3_MBIST_FAIL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM3_MBIST_FAIL_MASK \ + 0x00000008 /* G1_SRAM3_MBIST_FAIL[3] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM3_MBIST_FAIL_SHFT 3 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM2_MBIST_FAIL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM2_MBIST_FAIL_MASK \ + 0x00000004 /* G1_SRAM2_MBIST_FAIL[2] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM2_MBIST_FAIL_SHFT 2 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM1_MBIST_FAIL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM1_MBIST_FAIL_MASK \ + 0x00000002 /* G1_SRAM1_MBIST_FAIL[1] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM1_MBIST_FAIL_SHFT 1 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM0_MBIST_FAIL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM0_MBIST_FAIL_MASK \ + 0x00000001 /* G1_SRAM0_MBIST_FAIL[0] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM0_MBIST_FAIL_SHFT 0 + +/* +* ---SRAM_AWT_HDEN_CTRL (0x820C0000 + 0x440)--- +* SRAM_AWT_CTRL[13..0] - (RW) AWT setting of SRAMS +* RESERVED14[15..14] - (RO) Reserved bits +* SRAM_HDEN_CTRL[29..16] - (RW) HDEN setting of SRAMS +* RESERVED30[31..30] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_SRAM_HDEN_CTRL_ADDR \ + WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_SRAM_HDEN_CTRL_MASK \ + 0x3FFF0000 /* SRAM_HDEN_CTRL[29..16] */ +#define WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_SRAM_HDEN_CTRL_SHFT 16 +#define WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_SRAM_AWT_CTRL_ADDR \ + WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_SRAM_AWT_CTRL_MASK \ + 0x00003FFF /* SRAM_AWT_CTRL[13..0] */ +#define WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_SRAM_AWT_CTRL_SHFT 0 + +/* +* ---DRR_TABLE_WDATA0 (0x820C0000 + 0x450)--- +* DRR_TABLE_WDATA[31..0] - (RW) DRRwdata[31:0] for reading/writing DRR +table +* Mode 0x2?: DRR station mode +* WData[15:0]: Sta setting +* WData[127:16]: Reserved +* Mode 0x4?: BSS mode +* See SRAM layout. +* Mode 0x8?: Charge mode +* WData [15:0]: Charge length (unit: +byte) +* WData [31:16]: Charge time 9 unit +1.024us +* WData[127:32]: Reserved +*/ +#define WF_PLE_TOP_DRR_TABLE_WDATA0_DRR_TABLE_WDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_WDATA0_ADDR +#define WF_PLE_TOP_DRR_TABLE_WDATA0_DRR_TABLE_WDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_WDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_WDATA0_DRR_TABLE_WDATA_SHFT 0 + +/* +* ---DRR_TABLE_WDATA1 (0x820C0000 + 0x454)--- +* DRR_TABLE_WDATA[31..0] - (RW) DRR wdata[63:32] for reading/writing DRR +table +*/ +#define WF_PLE_TOP_DRR_TABLE_WDATA1_DRR_TABLE_WDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_WDATA1_ADDR +#define WF_PLE_TOP_DRR_TABLE_WDATA1_DRR_TABLE_WDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_WDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_WDATA1_DRR_TABLE_WDATA_SHFT 0 + +/* +* ---DRR_TABLE_WDATA2 (0x820C0000 + 0x458)--- +* DRR_TABLE_WDATA[31..0] - (RW) DRR wdata[95:64] for reading/writing DRR +table +*/ +#define WF_PLE_TOP_DRR_TABLE_WDATA2_DRR_TABLE_WDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_WDATA2_ADDR +#define WF_PLE_TOP_DRR_TABLE_WDATA2_DRR_TABLE_WDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_WDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_WDATA2_DRR_TABLE_WDATA_SHFT 0 + +/* +* ---DRR_TABLE_WDATA3 (0x820C0000 + 0x45c)--- +* DRR_TABLE_WDATA[31..0] - (RW) DRR wdata[127:96] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_WDATA3_DRR_TABLE_WDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_WDATA3_ADDR +#define WF_PLE_TOP_DRR_TABLE_WDATA3_DRR_TABLE_WDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_WDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_WDATA3_DRR_TABLE_WDATA_SHFT 0 + +/* +* ---DRR_TABLE_WDATA4 (0x820C0000 + 0x460)--- +* DRR_TABLE_WDATA[31..0] - (RW) DRRwdata[159:128] for reading/writing +* DRR table +* Mode 0x4?: BSS mode +* See SRAM layout. +*/ +#define WF_PLE_TOP_DRR_TABLE_WDATA4_DRR_TABLE_WDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_WDATA4_ADDR +#define WF_PLE_TOP_DRR_TABLE_WDATA4_DRR_TABLE_WDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_WDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_WDATA4_DRR_TABLE_WDATA_SHFT 0 + +/* +* ---DRR_TABLE_WDATA5 (0x820C0000 + 0x464)--- +* DRR_TABLE_WDATA[31..0] - (RW) DRR wdata[191:160] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_WDATA5_DRR_TABLE_WDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_WDATA5_ADDR +#define WF_PLE_TOP_DRR_TABLE_WDATA5_DRR_TABLE_WDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_WDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_WDATA5_DRR_TABLE_WDATA_SHFT 0 + +/* +* ---DRR_TABLE_WDATA6 (0x820C0000 + 0x468)--- +* DRR_TABLE_WDATA[31..0] - (RW) DRR wdata[223:192] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_WDATA6_DRR_TABLE_WDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_WDATA6_ADDR +#define WF_PLE_TOP_DRR_TABLE_WDATA6_DRR_TABLE_WDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_WDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_WDATA6_DRR_TABLE_WDATA_SHFT 0 + +/* +* ---DRR_TABLE_WDATA7 (0x820C0000 + 0x46c)--- +* DRR_TABLE_WDATA[31..0] - (RW) DRR wdata[255:224] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_WDATA7_DRR_TABLE_WDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_WDATA7_ADDR +#define WF_PLE_TOP_DRR_TABLE_WDATA7_DRR_TABLE_WDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_WDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_WDATA7_DRR_TABLE_WDATA_SHFT 0 + +/* +* ---DRR_TABLE_RDATA0 (0x820C0000 + 0x470)--- +* DRR_TABLE_RDATA[31..0] - (RW) DRR rdata[31:0] for reading/writing DRR +table +*/ +#define WF_PLE_TOP_DRR_TABLE_RDATA0_DRR_TABLE_RDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_RDATA0_ADDR +#define WF_PLE_TOP_DRR_TABLE_RDATA0_DRR_TABLE_RDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_RDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_RDATA0_DRR_TABLE_RDATA_SHFT 0 + +/* +* ---DRR_TABLE_RDATA1 (0x820C0000 + 0x474)--- +* DRR_TABLE_RDATA[31..0] - (RW) DRR rdata[63:32] for reading/writing DRR +table +*/ +#define WF_PLE_TOP_DRR_TABLE_RDATA1_DRR_TABLE_RDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_RDATA1_ADDR +#define WF_PLE_TOP_DRR_TABLE_RDATA1_DRR_TABLE_RDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_RDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_RDATA1_DRR_TABLE_RDATA_SHFT 0 + +/* +* ---DRR_TABLE_RDATA2 (0x820C0000 + 0x478)--- +* DRR_TABLE_RDATA[31..0] - (RW) DRR rdata[95:64] for reading/writing DRR +table +*/ +#define WF_PLE_TOP_DRR_TABLE_RDATA2_DRR_TABLE_RDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_RDATA2_ADDR +#define WF_PLE_TOP_DRR_TABLE_RDATA2_DRR_TABLE_RDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_RDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_RDATA2_DRR_TABLE_RDATA_SHFT 0 + +/* +* ---DRR_TABLE_RDATA3 (0x820C0000 + 0x47c)--- +* DRR_TABLE_RDATA[31..0] - (RW) DRR rdata[127:96] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_RDATA3_DRR_TABLE_RDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_RDATA3_ADDR +#define WF_PLE_TOP_DRR_TABLE_RDATA3_DRR_TABLE_RDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_RDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_RDATA3_DRR_TABLE_RDATA_SHFT 0 + +/* +* ---DRR_TABLE_RDATA4 (0x820C0000 + 0x480)--- +* DRR_TABLE_RDATA[31..0] - (RW) DRR rdata[159:128] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_RDATA4_DRR_TABLE_RDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_RDATA4_ADDR +#define WF_PLE_TOP_DRR_TABLE_RDATA4_DRR_TABLE_RDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_RDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_RDATA4_DRR_TABLE_RDATA_SHFT 0 + +/* +* ---DRR_TABLE_RDATA5 (0x820C0000 + 0x484)--- +* DRR_TABLE_RDATA[31..0] - (RW) DRR rdata[191:160] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_RDATA5_DRR_TABLE_RDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_RDATA5_ADDR +#define WF_PLE_TOP_DRR_TABLE_RDATA5_DRR_TABLE_RDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_RDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_RDATA5_DRR_TABLE_RDATA_SHFT 0 + +/* +* ---DRR_TABLE_RDATA6 (0x820C0000 + 0x488)--- +* DRR_TABLE_RDATA[31..0] - (RW) DRR rdata[223:192] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_RDATA6_DRR_TABLE_RDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_RDATA6_ADDR +#define WF_PLE_TOP_DRR_TABLE_RDATA6_DRR_TABLE_RDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_RDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_RDATA6_DRR_TABLE_RDATA_SHFT 0 + +/* +* ---DRR_TABLE_RDATA7 (0x820C0000 + 0x48c)--- +* DRR_TABLE_RDATA[31..0] - (RW) DRR rdata[255:224] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_RDATA7_DRR_TABLE_RDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_RDATA7_ADDR +#define WF_PLE_TOP_DRR_TABLE_RDATA7_DRR_TABLE_RDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_RDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_RDATA7_DRR_TABLE_RDATA_SHFT 0 + +/* +* ---DRR_TABLE_CTRL (0x820C0000 + 0x490)--- +* INDEX[11..0] - (RW) Operation index +* Mode 0x00: DRR STA link, STA relay +* Bit[1:0]: qid +* Bit[10:2]: Station ID +//-- +* Mode 0x20: addr[6:0] mean station ID +* Mode 0x21: addr[6:0] mean station ID +* Mode 0x22: SRAM idx (debug mode) +* Mode 0x23: SRAM idx (debug mode) +* 0~35: STA bitmap +* 36~51: STA setting +//-- +* Mode 0x40: addr[3:0] = bssid, +* Mode 0x41: addr[3:0] = bssid, +* Mode 0x42: addr[3:0] = bssid, +* Mode 0x43: addr[3:0] = bssid, +* Mode 0x44: SRAM idx (debug mode) +* Mode 0x45: SRAM idx (debug mode) +* 0~15: BSS bitmap +* 16~31: BSS setting +* 32~47: Token status +//-- +* Mode 0x81~0x83: addr[3:0] = BSS group ID +* Bit[0]: Charge bw_token +* Bit[1]: Charge bw DRR +* Mode 0x84: addr[7:0] = station ID, +* addr[11:8]= qid +* Bit[2]: Charge airtime DRR +* Bit[3]: Charge is ADD mode +* WRITE_MASK[15..12] - (RW) DRR table will not be updated if mask +* write bits are enabled. +* MODE[23..16] - (RW) Operation mode for DRR table +* WRITE_MASK_2[27..24] - (RW) DRR table will not be updated if mask +* write bits are enabled. +* RESERVED28[30..28] - (RO) Reserved bits +* EXECUTE[31] - (RW) Excutes SW command to read/write DRR +table +*/ +#define WF_PLE_TOP_DRR_TABLE_CTRL_EXECUTE_ADDR WF_PLE_TOP_DRR_TABLE_CTRL_ADDR +#define WF_PLE_TOP_DRR_TABLE_CTRL_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_DRR_TABLE_CTRL_EXECUTE_SHFT 31 +#define WF_PLE_TOP_DRR_TABLE_CTRL_WRITE_MASK_2_ADDR \ + WF_PLE_TOP_DRR_TABLE_CTRL_ADDR +#define WF_PLE_TOP_DRR_TABLE_CTRL_WRITE_MASK_2_MASK \ + 0x0F000000 /* WRITE_MASK_2[27..24] */ +#define WF_PLE_TOP_DRR_TABLE_CTRL_WRITE_MASK_2_SHFT 24 +#define WF_PLE_TOP_DRR_TABLE_CTRL_MODE_ADDR WF_PLE_TOP_DRR_TABLE_CTRL_ADDR +#define WF_PLE_TOP_DRR_TABLE_CTRL_MODE_MASK 0x00FF0000 /* MODE[23..16] */ +#define WF_PLE_TOP_DRR_TABLE_CTRL_MODE_SHFT 16 +#define WF_PLE_TOP_DRR_TABLE_CTRL_WRITE_MASK_ADDR WF_PLE_TOP_DRR_TABLE_CTRL_ADDR +#define WF_PLE_TOP_DRR_TABLE_CTRL_WRITE_MASK_MASK \ + 0x0000F000 /* WRITE_MASK[15..12] */ +#define WF_PLE_TOP_DRR_TABLE_CTRL_WRITE_MASK_SHFT 12 +#define WF_PLE_TOP_DRR_TABLE_CTRL_INDEX_ADDR WF_PLE_TOP_DRR_TABLE_CTRL_ADDR +#define WF_PLE_TOP_DRR_TABLE_CTRL_INDEX_MASK 0x00000FFF /* INDEX[11..0] */ +#define WF_PLE_TOP_DRR_TABLE_CTRL_INDEX_SHFT 0 + +/* +* ---AIRTIME_DRR_SIZE (0x820C0000 + 0x494)--- +* AIRTIME_DEFICIT_BOUNDARY[7..0] - (RW) Limits airtime DRR's maximum deficit +* Unit: 256us +* RESERVED2[15..8] - (RW) xxx +* BW_DEFICIT_BOUNDARY[23..16] - (RW) Limits BW DRR's maximum deficit +* Unit: 256us +* DRR_TXCNT_SIZE[31..24] - (RW) Tx count mode charge time setting +* Unit: 256us +*/ +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_DRR_TXCNT_SIZE_ADDR \ + WF_PLE_TOP_AIRTIME_DRR_SIZE_ADDR +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_DRR_TXCNT_SIZE_MASK \ + 0xFF000000 /* DRR_TXCNT_SIZE[31..24] */ +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_DRR_TXCNT_SIZE_SHFT 24 +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_BW_DEFICIT_BOUNDARY_ADDR \ + WF_PLE_TOP_AIRTIME_DRR_SIZE_ADDR +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_BW_DEFICIT_BOUNDARY_MASK \ + 0x00FF0000 /* BW_DEFICIT_BOUNDARY[23..16] */ +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_BW_DEFICIT_BOUNDARY_SHFT 16 +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_RESERVED2_ADDR \ + WF_PLE_TOP_AIRTIME_DRR_SIZE_ADDR +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_RESERVED2_MASK \ + 0x0000FF00 /* RESERVED2[15..8] */ +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_RESERVED2_SHFT 8 +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_AIRTIME_DEFICIT_BOUNDARY_ADDR \ + WF_PLE_TOP_AIRTIME_DRR_SIZE_ADDR +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_AIRTIME_DEFICIT_BOUNDARY_MASK \ + 0x000000FF /* AIRTIME_DEFICIT_BOUNDARY[7..0] */ +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_AIRTIME_DEFICIT_BOUNDARY_SHFT 0 + +/* +* ---CHECK_BW_TIME_TOKEN_ (0x820C0000 + 0x498)--- +* DISABLE_BW_TIME_CHECK[15..0] - (RW) HW will ignore time token status. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CHECK_BW_TIME_TOKEN__DISABLE_BW_TIME_CHECK_ADDR \ + WF_PLE_TOP_CHECK_BW_TIME_TOKEN__ADDR +#define WF_PLE_TOP_CHECK_BW_TIME_TOKEN__DISABLE_BW_TIME_CHECK_MASK \ + 0x0000FFFF /* DISABLE_BW_TIME_CHECK[15..0] */ +#define WF_PLE_TOP_CHECK_BW_TIME_TOKEN__DISABLE_BW_TIME_CHECK_SHFT 0 + +/* +* ---CHECK_BW_LENGTH_TOKEN_ (0x820C0000 + 0x49c)--- +* DISABLE_BW_LENGTH_CHECK[15..0] - (RW) HW will ignore time token status. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CHECK_BW_LENGTH_TOKEN__DISABLE_BW_LENGTH_CHECK_ADDR \ + WF_PLE_TOP_CHECK_BW_LENGTH_TOKEN__ADDR +#define WF_PLE_TOP_CHECK_BW_LENGTH_TOKEN__DISABLE_BW_LENGTH_CHECK_MASK \ + 0x0000FFFF /* DISABLE_BW_LENGTH_CHECK[15..0] */ +#define WF_PLE_TOP_CHECK_BW_LENGTH_TOKEN__DISABLE_BW_LENGTH_CHECK_SHFT 0 + +/* +* ---AIRTIME_QUANTUM_SETTING0 (0x820C0000 + 0x4a0)--- +* AIRTIME_QUANTUM0[7..0] - (RW) Airtime quantum 0 +* AIRTIME_QUANTUM1[15..8] - (RW) Airtime quantum 1 +* AIRTIME_QUANTUM2[23..16] - (RW) Airtime quantum 2 +* AIRTIME_QUANTUM3[31..24] - (RW) Airtime quantum 3 +*/ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM3_ADDR \ + WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_ADDR +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM3_MASK \ + 0xFF000000 /* AIRTIME_QUANTUM3[31..24] */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM3_SHFT 24 +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM2_ADDR \ + WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_ADDR +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM2_MASK \ + 0x00FF0000 /* AIRTIME_QUANTUM2[23..16] */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM2_SHFT 16 +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM1_ADDR \ + WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_ADDR +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM1_MASK \ + 0x0000FF00 /* AIRTIME_QUANTUM1[15..8] */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM1_SHFT 8 +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM0_ADDR \ + WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_ADDR +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM0_MASK \ + 0x000000FF /* AIRTIME_QUANTUM0[7..0] */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM0_SHFT 0 + +/* +* ---AIRTIME_QUANTUM_SETTING1 (0x820C0000 + 0x4a4)--- +* AIRTIME_QUANTUM4[7..0] - (RW) Airtime quantum 4 +* AIRTIME_QUANTUM5[15..8] - (RW) Airtime quantum 5 +* AIRTIME_QUANTUM6[23..16] - (RW) Airtime quantum 6 +* AIRTIME_QUANTUM7[31..24] - (RW) Airtime quantum 7 +*/ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM7_ADDR \ + WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_ADDR +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM7_MASK \ + 0xFF000000 /* AIRTIME_QUANTUM7[31..24] */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM7_SHFT 24 +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM6_ADDR \ + WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_ADDR +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM6_MASK \ + 0x00FF0000 /* AIRTIME_QUANTUM6[23..16] */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM6_SHFT 16 +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM5_ADDR \ + WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_ADDR +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM5_MASK \ + 0x0000FF00 /* AIRTIME_QUANTUM5[15..8] */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM5_SHFT 8 +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM4_ADDR \ + WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_ADDR +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM4_MASK \ + 0x000000FF /* AIRTIME_QUANTUM4[7..0] */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM4_SHFT 0 + +/* +* ---DRR_HW_SRCHCMD_FULL (0x820C0000 + 0x4c0)--- +* CMD_FULL_CHNL_DL[15..0] - (RW) Hardware search command full flag of 16 +* backoff channel of downlink +* CMD_FULL_CHNL_UL[31..16] - (RW) Hardware search command full flag of 16 +* backoff channel of uplink +*/ +#define WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_CMD_FULL_CHNL_UL_ADDR \ + WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_ADDR +#define WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_CMD_FULL_CHNL_UL_MASK \ + 0xFFFF0000 /* CMD_FULL_CHNL_UL[31..16] */ +#define WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_CMD_FULL_CHNL_UL_SHFT 16 +#define WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_CMD_FULL_CHNL_DL_ADDR \ + WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_ADDR +#define WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_CMD_FULL_CHNL_DL_MASK \ + 0x0000FFFF /* CMD_FULL_CHNL_DL[15..0] */ +#define WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_CMD_FULL_CHNL_DL_SHFT 0 + +/* +* ---TWT_DBG (0x820C0000 + 0x4d0)--- +* TABLE_IDX_SEL[2..0] - (RW) Station index selection +* UL_TABLE_SEL[3] - (RW) Downlink/uplink station table selection +* RESERVED4[15..4] - (RO) Reserved bits +* TABLE_WLAN_ID[25..16] - (RO) Station WLAN ID in station table +* RESERVED26[27..26] - (RO) Reserved bits +* STA_CNT[31..28] - (RO) Valid station count in station table +*/ +#define WF_PLE_TOP_TWT_DBG_STA_CNT_ADDR WF_PLE_TOP_TWT_DBG_ADDR +#define WF_PLE_TOP_TWT_DBG_STA_CNT_MASK 0xF0000000 /* STA_CNT[31..28] */ +#define WF_PLE_TOP_TWT_DBG_STA_CNT_SHFT 28 +#define WF_PLE_TOP_TWT_DBG_TABLE_WLAN_ID_ADDR WF_PLE_TOP_TWT_DBG_ADDR +#define WF_PLE_TOP_TWT_DBG_TABLE_WLAN_ID_MASK \ + 0x03FF0000 /* TABLE_WLAN_ID[25..16] */ +#define WF_PLE_TOP_TWT_DBG_TABLE_WLAN_ID_SHFT 16 +#define WF_PLE_TOP_TWT_DBG_UL_TABLE_SEL_ADDR WF_PLE_TOP_TWT_DBG_ADDR +#define WF_PLE_TOP_TWT_DBG_UL_TABLE_SEL_MASK 0x00000008 /* UL_TABLE_SEL[3] */ +#define WF_PLE_TOP_TWT_DBG_UL_TABLE_SEL_SHFT 3 +#define WF_PLE_TOP_TWT_DBG_TABLE_IDX_SEL_ADDR WF_PLE_TOP_TWT_DBG_ADDR +#define WF_PLE_TOP_TWT_DBG_TABLE_IDX_SEL_MASK \ + 0x00000007 /* TABLE_IDX_SEL[2..0] */ +#define WF_PLE_TOP_TWT_DBG_TABLE_IDX_SEL_SHFT 0 + +/* +* ---VOW_DBG_SEL (0x820C0000 + 0x4d4)--- +* AIRTIME_DEBUG_SEL[15..0] - (RW) Selects airtime debug +* BW_DEBUG_SEL[31..16] - (RW) Selects BW control debug +*/ +#define WF_PLE_TOP_VOW_DBG_SEL_BW_DEBUG_SEL_ADDR WF_PLE_TOP_VOW_DBG_SEL_ADDR +#define WF_PLE_TOP_VOW_DBG_SEL_BW_DEBUG_SEL_MASK \ + 0xFFFF0000 /* BW_DEBUG_SEL[31..16] */ +#define WF_PLE_TOP_VOW_DBG_SEL_BW_DEBUG_SEL_SHFT 16 +#define WF_PLE_TOP_VOW_DBG_SEL_AIRTIME_DEBUG_SEL_ADDR \ + WF_PLE_TOP_VOW_DBG_SEL_ADDR +#define WF_PLE_TOP_VOW_DBG_SEL_AIRTIME_DEBUG_SEL_MASK \ + 0x0000FFFF /* AIRTIME_DEBUG_SEL[15..0] */ +#define WF_PLE_TOP_VOW_DBG_SEL_AIRTIME_DEBUG_SEL_SHFT 0 + +/* +* ---AIRTIME_DBG_INFO0 (0x820C0000 + 0x4d8)--- +* AIRTIME_DBG_INFO0[31..0] - (RO) Station link head/tail +*/ +#define WF_PLE_TOP_AIRTIME_DBG_INFO0_AIRTIME_DBG_INFO0_ADDR \ + WF_PLE_TOP_AIRTIME_DBG_INFO0_ADDR +#define WF_PLE_TOP_AIRTIME_DBG_INFO0_AIRTIME_DBG_INFO0_MASK \ + 0xFFFFFFFF /* AIRTIME_DBG_INFO0[31..0] */ +#define WF_PLE_TOP_AIRTIME_DBG_INFO0_AIRTIME_DBG_INFO0_SHFT 0 + +/* +* ---AIRTIME_DBG_INFO1 (0x820C0000 + 0x4dc)--- +* AIRTIME_DBG_INFO1[31..0] - (RO) Station link head/tail +*/ +#define WF_PLE_TOP_AIRTIME_DBG_INFO1_AIRTIME_DBG_INFO1_ADDR \ + WF_PLE_TOP_AIRTIME_DBG_INFO1_ADDR +#define WF_PLE_TOP_AIRTIME_DBG_INFO1_AIRTIME_DBG_INFO1_MASK \ + 0xFFFFFFFF /* AIRTIME_DBG_INFO1[31..0] */ +#define WF_PLE_TOP_AIRTIME_DBG_INFO1_AIRTIME_DBG_INFO1_SHFT 0 + +/* +* ---AC0_QUEUE_EMPTY0 (0x820C0000 + 0x500)--- +* AC0_QUEUE_EMPTY_0[31..0] - (RO) Empty flag for STA 0~31 AC0 queue +*/ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY0_AC0_QUEUE_EMPTY_0_ADDR \ + WF_PLE_TOP_AC0_QUEUE_EMPTY0_ADDR +#define WF_PLE_TOP_AC0_QUEUE_EMPTY0_AC0_QUEUE_EMPTY_0_MASK \ + 0xFFFFFFFF /* AC0_QUEUE_EMPTY_0[31..0] */ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY0_AC0_QUEUE_EMPTY_0_SHFT 0 + +/* +* ---AC0_QUEUE_EMPTY1 (0x820C0000 + 0x504)--- +* AC0_QUEUE_EMPTY_1[31..0] - (RO) Empty flag for STA 32~63 AC0 queue +*/ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY1_AC0_QUEUE_EMPTY_1_ADDR \ + WF_PLE_TOP_AC0_QUEUE_EMPTY1_ADDR +#define WF_PLE_TOP_AC0_QUEUE_EMPTY1_AC0_QUEUE_EMPTY_1_MASK \ + 0xFFFFFFFF /* AC0_QUEUE_EMPTY_1[31..0] */ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY1_AC0_QUEUE_EMPTY_1_SHFT 0 + +/* +* ---AC1_QUEUE_EMPTY0 (0x820C0000 + 0x540)--- +* AC1_QUEUE_EMPTY_0[31..0] - (RO) Empty flag for STA 0~31 AC1 queue +*/ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY0_AC1_QUEUE_EMPTY_0_ADDR \ + WF_PLE_TOP_AC1_QUEUE_EMPTY0_ADDR +#define WF_PLE_TOP_AC1_QUEUE_EMPTY0_AC1_QUEUE_EMPTY_0_MASK \ + 0xFFFFFFFF /* AC1_QUEUE_EMPTY_0[31..0] */ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY0_AC1_QUEUE_EMPTY_0_SHFT 0 + +/* +* ---AC1_QUEUE_EMPTY1 (0x820C0000 + 0x544)--- +* AC1_QUEUE_EMPTY_1[31..0] - (RO) Empty flag for STA 32~63 AC1 queue +*/ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY1_AC1_QUEUE_EMPTY_1_ADDR \ + WF_PLE_TOP_AC1_QUEUE_EMPTY1_ADDR +#define WF_PLE_TOP_AC1_QUEUE_EMPTY1_AC1_QUEUE_EMPTY_1_MASK \ + 0xFFFFFFFF /* AC1_QUEUE_EMPTY_1[31..0] */ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY1_AC1_QUEUE_EMPTY_1_SHFT 0 + +/* +* ---AC2_QUEUE_EMPTY0 (0x820C0000 + 0x580)--- +* AC2_QUEUE_EMPTY_0[31..0] - (RO) Empty flag for STA 0~31 AC2 queue +*/ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY0_AC2_QUEUE_EMPTY_0_ADDR \ + WF_PLE_TOP_AC2_QUEUE_EMPTY0_ADDR +#define WF_PLE_TOP_AC2_QUEUE_EMPTY0_AC2_QUEUE_EMPTY_0_MASK \ + 0xFFFFFFFF /* AC2_QUEUE_EMPTY_0[31..0] */ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY0_AC2_QUEUE_EMPTY_0_SHFT 0 + +/* +* ---AC2_QUEUE_EMPTY1 (0x820C0000 + 0x584)--- +* AC2_QUEUE_EMPTY_1[31..0] - (RO) Empty flag for STA 32~63 AC2 queue +*/ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY1_AC2_QUEUE_EMPTY_1_ADDR \ + WF_PLE_TOP_AC2_QUEUE_EMPTY1_ADDR +#define WF_PLE_TOP_AC2_QUEUE_EMPTY1_AC2_QUEUE_EMPTY_1_MASK \ + 0xFFFFFFFF /* AC2_QUEUE_EMPTY_1[31..0] */ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY1_AC2_QUEUE_EMPTY_1_SHFT 0 + +/* +* ---AC3_QUEUE_EMPTY0 (0x820C0000 + 0x5c0)--- +* AC3_QUEUE_EMPTY_0[31..0] - (RO) Empty flag for STA 0~31 AC3 queue +*/ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY0_AC3_QUEUE_EMPTY_0_ADDR \ + WF_PLE_TOP_AC3_QUEUE_EMPTY0_ADDR +#define WF_PLE_TOP_AC3_QUEUE_EMPTY0_AC3_QUEUE_EMPTY_0_MASK \ + 0xFFFFFFFF /* AC3_QUEUE_EMPTY_0[31..0] */ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY0_AC3_QUEUE_EMPTY_0_SHFT 0 + +/* +* ---AC3_QUEUE_EMPTY1 (0x820C0000 + 0x5c4)--- +* AC3_QUEUE_EMPTY_1[31..0] - (RO) Empty flag for STA 32~63 AC3 queue +*/ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY1_AC3_QUEUE_EMPTY_1_ADDR \ + WF_PLE_TOP_AC3_QUEUE_EMPTY1_ADDR +#define WF_PLE_TOP_AC3_QUEUE_EMPTY1_AC3_QUEUE_EMPTY_1_MASK \ + 0xFFFFFFFF /* AC3_QUEUE_EMPTY_1[31..0] */ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY1_AC3_QUEUE_EMPTY_1_SHFT 0 + +/* +* ---PEEK_CR_00 (0x820C0000 + 0x600)--- +* PEEK_CR_00[31..0] - (RO) Empty flag for STA 480~511 AC3 queue +*/ +#define WF_PLE_TOP_PEEK_CR_00_PEEK_CR_00_ADDR WF_PLE_TOP_PEEK_CR_00_ADDR +#define WF_PLE_TOP_PEEK_CR_00_PEEK_CR_00_MASK 0xFFFFFFFF /* PEEK_CR_00[31..0] */ +#define WF_PLE_TOP_PEEK_CR_00_PEEK_CR_00_SHFT 0 + +/* +* ---PEEK_CR_01 (0x820C0000 + 0x604)--- +* PEEK_CR_01[31..0] - (RO) Empty flag for STA 480~511 AC3 queue +*/ +#define WF_PLE_TOP_PEEK_CR_01_PEEK_CR_01_ADDR WF_PLE_TOP_PEEK_CR_01_ADDR +#define WF_PLE_TOP_PEEK_CR_01_PEEK_CR_01_MASK 0xFFFFFFFF /* PEEK_CR_01[31..0] */ +#define WF_PLE_TOP_PEEK_CR_01_PEEK_CR_01_SHFT 0 + +/* +* ---PEEK_CR_02 (0x820C0000 + 0x608)--- +* PEEK_CR_02[31..0] - (RO) Empty flag for STA 480~511 AC3 queue +*/ +#define WF_PLE_TOP_PEEK_CR_02_PEEK_CR_02_ADDR WF_PLE_TOP_PEEK_CR_02_ADDR +#define WF_PLE_TOP_PEEK_CR_02_PEEK_CR_02_MASK 0xFFFFFFFF /* PEEK_CR_02[31..0] */ +#define WF_PLE_TOP_PEEK_CR_02_PEEK_CR_02_SHFT 0 + +/* +* ---PEEK_CR_03 (0x820C0000 + 0x60C)--- +* PEEK_CR_03[31..0] - (RO) Empty flag for STA 480~511 AC3 queue +*/ +#define WF_PLE_TOP_PEEK_CR_03_PEEK_CR_03_ADDR WF_PLE_TOP_PEEK_CR_03_ADDR +#define WF_PLE_TOP_PEEK_CR_03_PEEK_CR_03_MASK 0xFFFFFFFF /* PEEK_CR_03[31..0] */ +#define WF_PLE_TOP_PEEK_CR_03_PEEK_CR_03_SHFT 0 + +/* +* ---PEEK_CR_04 (0x820C0000 + 0x610)--- +* PEEK_CR_04[31..0] - (RO) Empty flag for STA 480~511 AC3 queue +*/ +#define WF_PLE_TOP_PEEK_CR_04_PEEK_CR_04_ADDR WF_PLE_TOP_PEEK_CR_04_ADDR +#define WF_PLE_TOP_PEEK_CR_04_PEEK_CR_04_MASK 0xFFFFFFFF /* PEEK_CR_04[31..0] */ +#define WF_PLE_TOP_PEEK_CR_04_PEEK_CR_04_SHFT 0 + +/* +* ---PEEK_CR_05 (0x820C0000 + 0x614)--- +* PEEK_CR_05[31..0] - (RO) Empty flag for STA 480~511 AC3 queue +*/ +#define WF_PLE_TOP_PEEK_CR_05_PEEK_CR_05_ADDR WF_PLE_TOP_PEEK_CR_05_ADDR +#define WF_PLE_TOP_PEEK_CR_05_PEEK_CR_05_MASK 0xFFFFFFFF /* PEEK_CR_05[31..0] */ +#define WF_PLE_TOP_PEEK_CR_05_PEEK_CR_05_SHFT 0 + +/* +* ---PEEK_CR_06 (0x820C0000 + 0x618)--- +* PEEK_CR_06[31..0] - (RO) Empty flag for STA 480~511 AC3 queue +*/ +#define WF_PLE_TOP_PEEK_CR_06_PEEK_CR_06_ADDR WF_PLE_TOP_PEEK_CR_06_ADDR +#define WF_PLE_TOP_PEEK_CR_06_PEEK_CR_06_MASK 0xFFFFFFFF /* PEEK_CR_06[31..0] */ +#define WF_PLE_TOP_PEEK_CR_06_PEEK_CR_06_SHFT 0 + +/* +* ---PEEK_CR_07 (0x820C0000 + 0x61c)--- +* PEEK_CR_07[31..0] - (RO) Empty flag for STA 480~511 AC3 queue +*/ +#define WF_PLE_TOP_PEEK_CR_07_PEEK_CR_07_ADDR WF_PLE_TOP_PEEK_CR_07_ADDR +#define WF_PLE_TOP_PEEK_CR_07_PEEK_CR_07_MASK 0xFFFFFFFF /* PEEK_CR_07[31..0] */ +#define WF_PLE_TOP_PEEK_CR_07_PEEK_CR_07_SHFT 0 + +/* +* ---PEEK_CR_08 (0x820C0000 + 0x620)--- +* PEEK_CR_08[31..0] - (RO) Empty flag for STA 480~511 AC3 queue +*/ +#define WF_PLE_TOP_PEEK_CR_08_PEEK_CR_08_ADDR WF_PLE_TOP_PEEK_CR_08_ADDR +#define WF_PLE_TOP_PEEK_CR_08_PEEK_CR_08_MASK 0xFFFFFFFF /* PEEK_CR_08[31..0] */ +#define WF_PLE_TOP_PEEK_CR_08_PEEK_CR_08_SHFT 0 + +/* +* ---PEEK_CR_09 (0x820C0000 + 0x624)--- +* PEEK_CR_09[31..0] - (RO) Empty flag for STA 480~511 AC3 queue +*/ +#define WF_PLE_TOP_PEEK_CR_09_PEEK_CR_09_ADDR WF_PLE_TOP_PEEK_CR_09_ADDR +#define WF_PLE_TOP_PEEK_CR_09_PEEK_CR_09_MASK 0xFFFFFFFF /* PEEK_CR_09[31..0] */ +#define WF_PLE_TOP_PEEK_CR_09_PEEK_CR_09_SHFT 0 + +/* +* ---PEEK_CR_10 (0x820C0000 + 0x628)--- +* PEEK_CR_10[31..0] - (RO) Empty flag for STA 480~511 AC3 queue +*/ +#define WF_PLE_TOP_PEEK_CR_10_PEEK_CR_10_ADDR WF_PLE_TOP_PEEK_CR_10_ADDR +#define WF_PLE_TOP_PEEK_CR_10_PEEK_CR_10_MASK 0xFFFFFFFF /* PEEK_CR_10[31..0] */ +#define WF_PLE_TOP_PEEK_CR_10_PEEK_CR_10_SHFT 0 + +/* +* ---PEEK_CR_11 (0x820C0000 + 0x62c)--- +* PEEK_CR_11[31..0] - (RO) Empty flag for STA 480~511 AC3 queue +*/ +#define WF_PLE_TOP_PEEK_CR_11_PEEK_CR_11_ADDR WF_PLE_TOP_PEEK_CR_11_ADDR +#define WF_PLE_TOP_PEEK_CR_11_PEEK_CR_11_MASK 0xFFFFFFFF /* PEEK_CR_11[31..0] */ +#define WF_PLE_TOP_PEEK_CR_11_PEEK_CR_11_SHFT 0 + +/* +* ---AMSDU_GC (0x820C0000 + 0x1000)--- +* EN_HW_AMSDU[0] - (RW) Enable control of HW AMSDU function. +* RESERVED1[7..1] - (RO) Reserved bits +* DIS_AMSDU_Q_EMPTY_FLUSH[8] - (RW) Disable control of HW AMSDU queue empty +* trigger packet flush function. +* DIS_LMAC_TX_NO_FULL_FLUSH[9] - (RW) Disable control of LMAC TX no get full +* packet trigger packet flush function. +* DIS_SFD_KEEP_SAME_PAGE[10] - (RW) Disable control of keep same page number +* of StoreForward packet function. +* RESERVED11[31..11] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_GC_DIS_SFD_KEEP_SAME_PAGE_ADDR WF_PLE_TOP_AMSDU_GC_ADDR +#define WF_PLE_TOP_AMSDU_GC_DIS_SFD_KEEP_SAME_PAGE_MASK \ + 0x00000400 /* DIS_SFD_KEEP_SAME_PAGE[10] */ +#define WF_PLE_TOP_AMSDU_GC_DIS_SFD_KEEP_SAME_PAGE_SHFT 10 +#define WF_PLE_TOP_AMSDU_GC_DIS_LMAC_TX_NO_FULL_FLUSH_ADDR \ + WF_PLE_TOP_AMSDU_GC_ADDR +#define WF_PLE_TOP_AMSDU_GC_DIS_LMAC_TX_NO_FULL_FLUSH_MASK \ + 0x00000200 /* DIS_LMAC_TX_NO_FULL_FLUSH[9] */ +#define WF_PLE_TOP_AMSDU_GC_DIS_LMAC_TX_NO_FULL_FLUSH_SHFT 9 +#define WF_PLE_TOP_AMSDU_GC_DIS_AMSDU_Q_EMPTY_FLUSH_ADDR \ + WF_PLE_TOP_AMSDU_GC_ADDR +#define WF_PLE_TOP_AMSDU_GC_DIS_AMSDU_Q_EMPTY_FLUSH_MASK \ + 0x00000100 /* DIS_AMSDU_Q_EMPTY_FLUSH[8] */ +#define WF_PLE_TOP_AMSDU_GC_DIS_AMSDU_Q_EMPTY_FLUSH_SHFT 8 +#define WF_PLE_TOP_AMSDU_GC_EN_HW_AMSDU_ADDR WF_PLE_TOP_AMSDU_GC_ADDR +#define WF_PLE_TOP_AMSDU_GC_EN_HW_AMSDU_MASK 0x00000001 /* EN_HW_AMSDU[0] */ +#define WF_PLE_TOP_AMSDU_GC_EN_HW_AMSDU_SHFT 0 + +/* +* ---AMSDU_TXD_COMP_MAP_0 (0x820C0000 + 0x1004)--- +* TXDIN_TRIGGER_TH[11..0] - (RW) The TXD merge trigger threshold. +* RESERVED12[15..12] - (RO) Reserved bits +* TXD_COMPARE_NEED_MAP[31..16] - (RW) The compare bitmap for merging TXD. +*/ +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_TXD_COMPARE_NEED_MAP_ADDR \ + WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_ADDR +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_TXD_COMPARE_NEED_MAP_MASK \ + 0xFFFF0000 /* TXD_COMPARE_NEED_MAP[31..16] */ +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_TXD_COMPARE_NEED_MAP_SHFT 16 +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_TXDIN_TRIGGER_TH_ADDR \ + WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_ADDR +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_TXDIN_TRIGGER_TH_MASK \ + 0x00000FFF /* TXDIN_TRIGGER_TH[11..0] */ +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_TXDIN_TRIGGER_TH_SHFT 0 + +/* +* ---AMSDU_TXD_COMP_MAP_1 (0x820C0000 + 0x1008)--- +* TXD_COMPARE_NEED_MAP[31..0] - (RW) The compare bitmap for merging TXD. +*/ +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_1_TXD_COMPARE_NEED_MAP_ADDR \ + WF_PLE_TOP_AMSDU_TXD_COMP_MAP_1_ADDR +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_1_TXD_COMPARE_NEED_MAP_MASK \ + 0xFFFFFFFF /* TXD_COMPARE_NEED_MAP[31..0] */ +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_1_TXD_COMPARE_NEED_MAP_SHFT 0 + +/* +* ---AMSDU_INT_N9_ERR_MASK (0x820C0000 + 0x100c)--- +* EN_AMSDU_Q_CMD_ERR[0] - (RW) Enables queue command error interrupt +* status of port AMSDU +* RESERVED1[3..1] - (RO) Reserved bits +* EN_AMSDU_PAGE_UDF[4] - (RW) Enables page underflow interrupt status +* of port AMSDU +* RESERVED5[11..5] - (RO) Reserved bits +* EN_AMSDU_DATA_OPER_ERR[12] - (RW) Enables data operation error of port +AMSDU +* RESERVED13[15..13] - (RO) Reserved bits +* EN_AMSDU_PORT_HANG_ERR[16] - (RW) Enables AMSDU port FSM hang error +interrupt +* EN_AMSDU_CTRL_HANG_ERR[17] - (RW) Enables AMSDU CTRL FSM hang error +interrupt +* RESERVED18[31..18] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_CTRL_HANG_ERR_ADDR \ + WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_CTRL_HANG_ERR_MASK \ + 0x00020000 /* EN_AMSDU_CTRL_HANG_ERR[17] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_CTRL_HANG_ERR_SHFT 17 +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_PORT_HANG_ERR_ADDR \ + WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_PORT_HANG_ERR_MASK \ + 0x00010000 /* EN_AMSDU_PORT_HANG_ERR[16] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_PORT_HANG_ERR_SHFT 16 +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_DATA_OPER_ERR_ADDR \ + WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_DATA_OPER_ERR_MASK \ + 0x00001000 /* EN_AMSDU_DATA_OPER_ERR[12] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_DATA_OPER_ERR_SHFT 12 +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_PAGE_UDF_ADDR \ + WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_PAGE_UDF_MASK \ + 0x00000010 /* EN_AMSDU_PAGE_UDF[4] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_PAGE_UDF_SHFT 4 +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_Q_CMD_ERR_ADDR \ + WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_Q_CMD_ERR_MASK \ + 0x00000001 /* EN_AMSDU_Q_CMD_ERR[0] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_Q_CMD_ERR_SHFT 0 + +/* +* ---AMSDU_INT_N9_ERR_STS (0x820C0000 + 0x1010)--- +* AMSDU_Q_CMD_ERR[0] - (W1C) Queue command error interrupt status of +* port AMSDU. Avoid unclear error flag, please clear flag when logic reset. +* RESERVED1[3..1] - (RO) Reserved bits +* AMSDU_PAGE_UDF[4] - (W1C) Page underflow interrupt status of port +* AMSDU. Avoid unclear error flag, please clear flag when logic reset. +* RESERVED5[11..5] - (RO) Reserved bits +* AMSDU_DATA_OPER_ERR[12] - (W1C) Data operation error of port AMSDU. +* Avoid unclear error flag, please clear flag when logic reset. +* RESERVED13[15..13] - (RO) Reserved bits +* AMSDU_PORT_HANG_ERR[16] - (W1C) AMSDU port FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* AMSDU_CTRL_HANG_ERR[17] - (W1C) AMSDU FSM hang error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* RESERVED18[31..18] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_CTRL_HANG_ERR_ADDR \ + WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_CTRL_HANG_ERR_MASK \ + 0x00020000 /* AMSDU_CTRL_HANG_ERR[17] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_CTRL_HANG_ERR_SHFT 17 +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_PORT_HANG_ERR_ADDR \ + WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_PORT_HANG_ERR_MASK \ + 0x00010000 /* AMSDU_PORT_HANG_ERR[16] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_PORT_HANG_ERR_SHFT 16 +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_DATA_OPER_ERR_ADDR \ + WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_DATA_OPER_ERR_MASK \ + 0x00001000 /* AMSDU_DATA_OPER_ERR[12] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_DATA_OPER_ERR_SHFT 12 +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_PAGE_UDF_ADDR \ + WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_PAGE_UDF_MASK \ + 0x00000010 /* AMSDU_PAGE_UDF[4] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_PAGE_UDF_SHFT 4 +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_Q_CMD_ERR_ADDR \ + WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_Q_CMD_ERR_MASK \ + 0x00000001 /* AMSDU_Q_CMD_ERR[0] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_Q_CMD_ERR_SHFT 0 + +/* +* ---AMSDU_PEEK_CR_00 (0x820C0000 + 0x10d0)--- +* AMSDU_DOP_CS[3..0] - (RO) AMSDU Data operation current state. +* RESERVED4[7..4] - (RO) Reserved bits +* AMSDU_CS[12..8] - (RO) AMSDU Merge Engine current state. +* RESERVED13[15..13] - (RO) Reserved bits +* AMSDU_Q_EMPTY_CS[17..16] - (RO) AMSDU Queue Empty Search Engine current +state. +* RESERVED18[23..18] - (RO) Reserved bits +* AMSDU_ARB_CS[26..24] - (RO) AMSDU Request Arbitration Current state. +* RESERVED27[31..27] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_ARB_CS_ADDR \ + WF_PLE_TOP_AMSDU_PEEK_CR_00_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_ARB_CS_MASK \ + 0x07000000 /* AMSDU_ARB_CS[26..24] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_ARB_CS_SHFT 24 +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_Q_EMPTY_CS_ADDR \ + WF_PLE_TOP_AMSDU_PEEK_CR_00_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_Q_EMPTY_CS_MASK \ + 0x00030000 /* AMSDU_Q_EMPTY_CS[17..16] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_Q_EMPTY_CS_SHFT 16 +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_CS_ADDR \ + WF_PLE_TOP_AMSDU_PEEK_CR_00_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_CS_MASK \ + 0x00001F00 /* AMSDU_CS[12..8] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_CS_SHFT 8 +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_DOP_CS_ADDR \ + WF_PLE_TOP_AMSDU_PEEK_CR_00_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_DOP_CS_MASK \ + 0x0000000F /* AMSDU_DOP_CS[3..0] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_DOP_CS_SHFT 0 + +/* +* ---AMSDU_PEEK_CR_01 (0x820C0000 + 0x10d4)--- +* AMSDU_DOP_PBUF_CS[2..0] - (RO) PLE AMSDU port - Data operation PBUF +* current state. +* RESERVED3[3] - (RO) Reserved bits +* AMSDU_DOP_CACHE_CS[5..4] - (RO) PLE AMSDU port - Data operation CACHE +* current state. +* RESERVED6[7..6] - (RO) Reserved bits +* AMSDU_QOP_Q_OPER_CS[11..8] - (RO) PLE AMSDU port - Queue operation current +state. +* AMSDU_QOP_RL_OCP_CS[13..12] - (RO) PLE AMSDU port - Queue operation RL +* current state. +* RESERVED14[15..14] - (RO) Reserved bits +* AMSDU_QOP_PL_OCP_CS[17..16] - (RO) PLE AMSDU port - Queue operation PL +* current state. +* RESERVED18[19..18] - (RO) Reserved bits +* AMSDU_QOP_ALLOCATE_CS[22..20] - (RO) PLE AMSDU port - Queue operation +* allocate current state. +* RESERVED23[31..23] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_ALLOCATE_CS_ADDR \ + WF_PLE_TOP_AMSDU_PEEK_CR_01_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_ALLOCATE_CS_MASK \ + 0x00700000 /* AMSDU_QOP_ALLOCATE_CS[22..20] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_ALLOCATE_CS_SHFT 20 +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_PL_OCP_CS_ADDR \ + WF_PLE_TOP_AMSDU_PEEK_CR_01_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_PL_OCP_CS_MASK \ + 0x00030000 /* AMSDU_QOP_PL_OCP_CS[17..16] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_PL_OCP_CS_SHFT 16 +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_RL_OCP_CS_ADDR \ + WF_PLE_TOP_AMSDU_PEEK_CR_01_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_RL_OCP_CS_MASK \ + 0x00003000 /* AMSDU_QOP_RL_OCP_CS[13..12] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_RL_OCP_CS_SHFT 12 +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_Q_OPER_CS_ADDR \ + WF_PLE_TOP_AMSDU_PEEK_CR_01_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_Q_OPER_CS_MASK \ + 0x00000F00 /* AMSDU_QOP_Q_OPER_CS[11..8] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_Q_OPER_CS_SHFT 8 +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_DOP_CACHE_CS_ADDR \ + WF_PLE_TOP_AMSDU_PEEK_CR_01_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_DOP_CACHE_CS_MASK \ + 0x00000030 /* AMSDU_DOP_CACHE_CS[5..4] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_DOP_CACHE_CS_SHFT 4 +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_DOP_PBUF_CS_ADDR \ + WF_PLE_TOP_AMSDU_PEEK_CR_01_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_DOP_PBUF_CS_MASK \ + 0x00000007 /* AMSDU_DOP_PBUF_CS[2..0] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_DOP_PBUF_CS_SHFT 0 + +/* +* ---AMSDU_PACK_1_MSDU_CNT (0x820C0000 + 0x10e0)--- +* pack_1_msdu_cnt[15..0] - (RC) AMSDU pack count of 1 MSDU in TXD. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PACK_1_MSDU_CNT_pack_1_msdu_cnt_ADDR \ + WF_PLE_TOP_AMSDU_PACK_1_MSDU_CNT_ADDR +#define WF_PLE_TOP_AMSDU_PACK_1_MSDU_CNT_pack_1_msdu_cnt_MASK \ + 0x0000FFFF /* pack_1_msdu_cnt[15..0] */ +#define WF_PLE_TOP_AMSDU_PACK_1_MSDU_CNT_pack_1_msdu_cnt_SHFT 0 + +/* +* ---AMSDU_PACK_2_MSDU_CNT (0x820C0000 + 0x10e4)--- +* pack_2_msdu_cnt[15..0] - (RC) AMSDU pack count of 2 MSDU in TXD. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PACK_2_MSDU_CNT_pack_2_msdu_cnt_ADDR \ + WF_PLE_TOP_AMSDU_PACK_2_MSDU_CNT_ADDR +#define WF_PLE_TOP_AMSDU_PACK_2_MSDU_CNT_pack_2_msdu_cnt_MASK \ + 0x0000FFFF /* pack_2_msdu_cnt[15..0] */ +#define WF_PLE_TOP_AMSDU_PACK_2_MSDU_CNT_pack_2_msdu_cnt_SHFT 0 + +/* +* ---AMSDU_PACK_3_MSDU_CNT (0x820C0000 + 0x10e8)--- +* pack_3_msdu_cnt[15..0] - (RC) AMSDU pack count of 3 MSDU in TXD. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PACK_3_MSDU_CNT_pack_3_msdu_cnt_ADDR \ + WF_PLE_TOP_AMSDU_PACK_3_MSDU_CNT_ADDR +#define WF_PLE_TOP_AMSDU_PACK_3_MSDU_CNT_pack_3_msdu_cnt_MASK \ + 0x0000FFFF /* pack_3_msdu_cnt[15..0] */ +#define WF_PLE_TOP_AMSDU_PACK_3_MSDU_CNT_pack_3_msdu_cnt_SHFT 0 + +/* +* ---AMSDU_PACK_4_MSDU_CNT (0x820C0000 + 0x10ec)--- +* pack_4_msdu_cnt[15..0] - (RC) AMSDU pack count of 4 MSDU in TXD. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PACK_4_MSDU_CNT_pack_4_msdu_cnt_ADDR \ + WF_PLE_TOP_AMSDU_PACK_4_MSDU_CNT_ADDR +#define WF_PLE_TOP_AMSDU_PACK_4_MSDU_CNT_pack_4_msdu_cnt_MASK \ + 0x0000FFFF /* pack_4_msdu_cnt[15..0] */ +#define WF_PLE_TOP_AMSDU_PACK_4_MSDU_CNT_pack_4_msdu_cnt_SHFT 0 + +/* +* ---AMSDU_PACK_5_MSDU_CNT (0x820C0000 + 0x10f0)--- +* pack_5_msdu_cnt[15..0] - (RC) AMSDU pack count of 5 MSDU in TXD. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PACK_5_MSDU_CNT_pack_5_msdu_cnt_ADDR \ + WF_PLE_TOP_AMSDU_PACK_5_MSDU_CNT_ADDR +#define WF_PLE_TOP_AMSDU_PACK_5_MSDU_CNT_pack_5_msdu_cnt_MASK \ + 0x0000FFFF /* pack_5_msdu_cnt[15..0] */ +#define WF_PLE_TOP_AMSDU_PACK_5_MSDU_CNT_pack_5_msdu_cnt_SHFT 0 + +/* +* ---AMSDU_PACK_6_MSDU_CNT (0x820C0000 + 0x10f4)--- +* pack_6_msdu_cnt[15..0] - (RC) AMSDU pack count of 4 MSDU in TXD. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PACK_6_MSDU_CNT_pack_6_msdu_cnt_ADDR \ + WF_PLE_TOP_AMSDU_PACK_6_MSDU_CNT_ADDR +#define WF_PLE_TOP_AMSDU_PACK_6_MSDU_CNT_pack_6_msdu_cnt_MASK \ + 0x0000FFFF /* pack_6_msdu_cnt[15..0] */ +#define WF_PLE_TOP_AMSDU_PACK_6_MSDU_CNT_pack_6_msdu_cnt_SHFT 0 + +/* +* ---AMSDU_PACK_7_MSDU_CNT (0x820C0000 + 0x10f8)--- +* pack_7_msdu_cnt[15..0] - (RC) AMSDU pack count of 7 MSDU in TXD. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PACK_7_MSDU_CNT_pack_7_msdu_cnt_ADDR \ + WF_PLE_TOP_AMSDU_PACK_7_MSDU_CNT_ADDR +#define WF_PLE_TOP_AMSDU_PACK_7_MSDU_CNT_pack_7_msdu_cnt_MASK \ + 0x0000FFFF /* pack_7_msdu_cnt[15..0] */ +#define WF_PLE_TOP_AMSDU_PACK_7_MSDU_CNT_pack_7_msdu_cnt_SHFT 0 + +/* +* ---AMSDU_PACK_8_MSDU_CNT (0x820C0000 + 0x10fc)--- +* pack_8_msdu_cnt[15..0] - (RC) AMSDU pack count of 8 MSDU in TXD. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PACK_8_MSDU_CNT_pack_8_msdu_cnt_ADDR \ + WF_PLE_TOP_AMSDU_PACK_8_MSDU_CNT_ADDR +#define WF_PLE_TOP_AMSDU_PACK_8_MSDU_CNT_pack_8_msdu_cnt_MASK \ + 0x0000FFFF /* pack_8_msdu_cnt[15..0] */ +#define WF_PLE_TOP_AMSDU_PACK_8_MSDU_CNT_pack_8_msdu_cnt_SHFT 0 + +/* +* ---AMSDU_AC0_QUEUE_EMPTY0 (0x820C0000 + 0x1100)--- +* AMSDU_QUEUE_EMPTY_FLAG_31_0[31..0] - (RO) AC0 queue empty flag for +* station31~station0 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_ADDR \ + WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY0_ADDR +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_MASK \ + 0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_31_0[31..0] */ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_SHFT 0 + +/* +* ---AMSDU_AC0_QUEUE_EMPTY1 (0x820C0000 + 0x1104)--- +* AMSDU_QUEUE_EMPTY_FLAG_63_32[31..0] - (RO) AC0 queue empty flag for +* station63~station32 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY1_AMSDU_QUEUE_EMPTY_FLAG_63_32_ADDR \ + WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY1_ADDR +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY1_AMSDU_QUEUE_EMPTY_FLAG_63_32_MASK \ + 0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_63_32[31..0] */ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY1_AMSDU_QUEUE_EMPTY_FLAG_63_32_SHFT 0 + +/* +* ---AMSDU_AC1_QUEUE_EMPTY0 (0x820C0000 + 0x1140)--- +* AMSDU_QUEUE_EMPTY_FLAG_31_0[31..0] - (RO) AC1 queue empty flag for +* station31~station0 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_ADDR \ + WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY0_ADDR +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_MASK \ + 0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_31_0[31..0] */ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_SHFT 0 + +/* +* ---AMSDU_AC1_QUEUE_EMPTY1 (0x820C0000 + 0x1144)--- +* AMSDU_QUEUE_EMPTY_FLAG_63_32[31..0] - (RO) AC1 queue empty flag for +* station63~station32 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY1_AMSDU_QUEUE_EMPTY_FLAG_63_32_ADDR \ + WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY1_ADDR +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY1_AMSDU_QUEUE_EMPTY_FLAG_63_32_MASK \ + 0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_63_32[31..0] */ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY1_AMSDU_QUEUE_EMPTY_FLAG_63_32_SHFT 0 + +/* +* ---AMSDU_AC2_QUEUE_EMPTY0 (0x820C0000 + 0x1180)--- +* AMSDU_QUEUE_EMPTY_FLAG_31_0[31..0] - (RO) AC2 queue empty flag for +* station31~station0 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_ADDR \ + WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY0_ADDR +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_MASK \ + 0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_31_0[31..0] */ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_SHFT 0 + +/* +* ---AMSDU_AC2_QUEUE_EMPTY1 (0x820C0000 + 0x1184)--- +* AMSDU_QUEUE_EMPTY_FLAG_63_32[31..0] - (RO) AC2 queue empty flag for +* station63~station32 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY1_AMSDU_QUEUE_EMPTY_FLAG_63_32_ADDR \ + WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY1_ADDR +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY1_AMSDU_QUEUE_EMPTY_FLAG_63_32_MASK \ + 0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_63_32[31..0] */ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY1_AMSDU_QUEUE_EMPTY_FLAG_63_32_SHFT 0 + +/* +* ---AMSDU_AC3_QUEUE_EMPTY0 (0x820C0000 + 0x11C0)--- +* AMSDU_QUEUE_EMPTY_FLAG_31_0[31..0] - (RO) AC3 queue empty flag for +* station31~station0 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_ADDR \ + WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY0_ADDR +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_MASK \ + 0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_31_0[31..0] */ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_SHFT 0 + +/* +* ---AMSDU_AC3_QUEUE_EMPTY1 (0x820C0000 + 0x11C4)--- +* AMSDU_QUEUE_EMPTY_FLAG_63_32[31..0] - (RO) AC3 queue empty flag for +* station63~station32 in HW AMSDU engine. +*/ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY1_AMSDU_QUEUE_EMPTY_FLAG_63_32_ADDR \ + WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY1_ADDR +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY1_AMSDU_QUEUE_EMPTY_FLAG_63_32_MASK \ + 0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_63_32[31..0] */ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY1_AMSDU_QUEUE_EMPTY_FLAG_63_32_SHFT 0 + +/* +* ---CFG_DBDC_CTRL0 (0x820C0000 + 0x2008)--- +* RESERVED0[7..0] - (RO) Reserved bits +* WMM_0TO3_BAND_SEL[11..8] - (RW) Selects WMM0~WMM3 band +* RESERVED12[15..12] - (RO) Reserved bits +* NAN_BAND_SEL[16] - (RW) Selects NAN band +* FUNCQ_BAND_SEL[17] - (RW) Selects Functional Queue band +* TGID 0 & TGID1 always selec to different +band +* RESERVED18[30..18] - (RO) Reserved bits +* DBDC_EN[31] - (RO) Enables DBDC +*/ +#define WF_PLE_TOP_CFG_DBDC_CTRL0_DBDC_EN_ADDR WF_PLE_TOP_CFG_DBDC_CTRL0_ADDR +#define WF_PLE_TOP_CFG_DBDC_CTRL0_DBDC_EN_MASK 0x80000000 /* DBDC_EN[31] */ +#define WF_PLE_TOP_CFG_DBDC_CTRL0_DBDC_EN_SHFT 31 +#define WF_PLE_TOP_CFG_DBDC_CTRL0_FUNCQ_BAND_SEL_ADDR \ + WF_PLE_TOP_CFG_DBDC_CTRL0_ADDR +#define WF_PLE_TOP_CFG_DBDC_CTRL0_FUNCQ_BAND_SEL_MASK \ + 0x00020000 /* FUNCQ_BAND_SEL[17] */ +#define WF_PLE_TOP_CFG_DBDC_CTRL0_FUNCQ_BAND_SEL_SHFT 17 +#define WF_PLE_TOP_CFG_DBDC_CTRL0_NAN_BAND_SEL_ADDR \ + WF_PLE_TOP_CFG_DBDC_CTRL0_ADDR +#define WF_PLE_TOP_CFG_DBDC_CTRL0_NAN_BAND_SEL_MASK \ + 0x00010000 /* NAN_BAND_SEL[16] */ +#define WF_PLE_TOP_CFG_DBDC_CTRL0_NAN_BAND_SEL_SHFT 16 +#define WF_PLE_TOP_CFG_DBDC_CTRL0_WMM_0TO3_BAND_SEL_ADDR \ + WF_PLE_TOP_CFG_DBDC_CTRL0_ADDR +#define WF_PLE_TOP_CFG_DBDC_CTRL0_WMM_0TO3_BAND_SEL_MASK \ + 0x00000F00 /* WMM_0TO3_BAND_SEL[11..8] */ +#define WF_PLE_TOP_CFG_DBDC_CTRL0_WMM_0TO3_BAND_SEL_SHFT 8 + +/* +* ---CFG_UWTBL_MBIST_CTRL_0 (0x820C0000 + 0x2480)--- +* UWTBL_MBIST_MODE[0] - (RW) Control register for mbist_mode of UWTBL +MBIST +* UWTBL_MBIST_HOLDB[1] - (RW) Control register for mbist_holdb of +* UWTBL MBIST +* UWTBL_MBIST_DEBUG[2] - (RW) Control register for mbist_debug of +* UWTBL MBIST +* UWTBL_MBIST_USE_DEFAULT_DELSEL[3] - (RW) Control register for default DELSEL +* value of UWTBL memory +* UWTBL_MBIST_SLEEP_TEST[4] - (RW) Control register for sleep_test of UWTBL +MBIST +* UWTBL_MBIST_SLEEP_INV[5] - (RW) Control register for sleep_inv of UWTBL +MBIST +* UWTBL_MBIST_SLEEP_W[6] - (RW) Control register for sleep_w of UWTBL +MBIST +* UWTBL_MBIST_SLEEP_R[7] - (RW) Control register for sleep_r of UWTBL +MBIST +* UWTBL_MBIST_DONE[8] - (RO) Working status of UWTBL SRAM MBIST +circuit +* RESERVED9[15..9] - (RO) Reserved bits +* UWTBL_MBIST_FAIL[21..16] - (RO) MBIST check result of UWTBL SRAM +* RESERVED22[31..22] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_FAIL_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_FAIL_MASK \ + 0x003F0000 /* UWTBL_MBIST_FAIL[21..16] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_FAIL_SHFT 16 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_DONE_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_DONE_MASK \ + 0x00000100 /* UWTBL_MBIST_DONE[8] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_DONE_SHFT 8 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_R_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_R_MASK \ + 0x00000080 /* UWTBL_MBIST_SLEEP_R[7] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_R_SHFT 7 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_W_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_W_MASK \ + 0x00000040 /* UWTBL_MBIST_SLEEP_W[6] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_W_SHFT 6 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_INV_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_INV_MASK \ + 0x00000020 /* UWTBL_MBIST_SLEEP_INV[5] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_INV_SHFT 5 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_TEST_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_TEST_MASK \ + 0x00000010 /* UWTBL_MBIST_SLEEP_TEST[4] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_TEST_SHFT 4 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_USE_DEFAULT_DELSEL_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_USE_DEFAULT_DELSEL_MASK \ + 0x00000008 /* UWTBL_MBIST_USE_DEFAULT_DELSEL[3] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_USE_DEFAULT_DELSEL_SHFT 3 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_DEBUG_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_DEBUG_MASK \ + 0x00000004 /* UWTBL_MBIST_DEBUG[2] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_DEBUG_SHFT 2 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_HOLDB_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_HOLDB_MASK \ + 0x00000002 /* UWTBL_MBIST_HOLDB[1] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_HOLDB_SHFT 1 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_MODE_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_MODE_MASK \ + 0x00000001 /* UWTBL_MBIST_MODE[0] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_MODE_SHFT 0 + +/* +* ---CFG_UWTBL_MBIST_CTRL_1 (0x820C0000 + 0x2484)--- +* UWTBL_MBIST_HDEN[5..0] - (RW) Control register for mbist UWTBL HDEN +* RESERVED6[15..6] - (RO) Reserved bits +* UWTBL_MBIST_AWT[21..16] - (RW) Control register for mbist UWTBL AWT +* RESERVED22[31..22] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_UWTBL_MBIST_AWT_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_UWTBL_MBIST_AWT_MASK \ + 0x003F0000 /* UWTBL_MBIST_AWT[21..16] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_UWTBL_MBIST_AWT_SHFT 16 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_UWTBL_MBIST_HDEN_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_UWTBL_MBIST_HDEN_MASK \ + 0x0000003F /* UWTBL_MBIST_HDEN[5..0] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_UWTBL_MBIST_HDEN_SHFT 0 + +/* +* ---CFG_UWTBL_MBIST_CTRL_2 (0x820C0000 + 0x2488)--- +* UWTBL_BACKGROUND[15..0] - (RW) The MBIST background control register +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_2_UWTBL_BACKGROUND_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_2_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_2_UWTBL_BACKGROUND_MASK \ + 0x0000FFFF /* UWTBL_BACKGROUND[15..0] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_2_UWTBL_BACKGROUND_SHFT 0 + +/* +* ---CFG_UWTBL_MBIST_CTRL_3 (0x820C0000 + 0x248c)--- +* UWTBL_DELSEL_0[31..0] - (RW) UWTBL DELSEL 0 +*/ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_3_UWTBL_DELSEL_0_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_3_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_3_UWTBL_DELSEL_0_MASK \ + 0xFFFFFFFF /* UWTBL_DELSEL_0[31..0] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_3_UWTBL_DELSEL_0_SHFT 0 + +/* +* ---CFG_UWTBL_MBIST_CTRL_4 (0x820C0000 + 0x2490)--- +* UWTBL_DELSEL_1[31..0] - (RW) UWTBL DELSEL 1 +*/ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_4_UWTBL_DELSEL_1_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_4_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_4_UWTBL_DELSEL_1_MASK \ + 0xFFFFFFFF /* UWTBL_DELSEL_1[31..0] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_4_UWTBL_DELSEL_1_SHFT 0 + +/* +* ---CFG_UWTBL_MBIST_CTRL_5 (0x820C0000 + 0x2494)--- +* UWTBL_FUSE[6..0] - (RW) UWTBL FUSE +* RESERVED7[7] - (RO) Reserved bits +* UWTBL_PRE_FUSE[14..8] - (RO) UWTBL MBIST Pre Fuse +* RESERVED15[15] - (RO) Reserved bits +* UWTBL_MBIST_REPAIR_OK[21..16] - (RO) MBIST Repair OK +* RESERVED22[23..22] - (RO) Reserved bits +* UWTBL_MBIST_REPAIR_FAIL[29..24] - (RO) MBIST Repair Fail +* RESERVED30[31..30] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_MBIST_REPAIR_FAIL_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_MBIST_REPAIR_FAIL_MASK \ + 0x3F000000 /* UWTBL_MBIST_REPAIR_FAIL[29..24] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_MBIST_REPAIR_FAIL_SHFT 24 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_MBIST_REPAIR_OK_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_MBIST_REPAIR_OK_MASK \ + 0x003F0000 /* UWTBL_MBIST_REPAIR_OK[21..16] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_MBIST_REPAIR_OK_SHFT 16 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_PRE_FUSE_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_PRE_FUSE_MASK \ + 0x00007F00 /* UWTBL_PRE_FUSE[14..8] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_PRE_FUSE_SHFT 8 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_FUSE_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_FUSE_MASK \ + 0x0000007F /* UWTBL_FUSE[6..0] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_FUSE_SHFT 0 + +/* +* ---CFG_UWTBL_MBIST_CTRL_6 (0x820C0000 + 0x2498)--- +* UWTBL_DELSEL_2[31..0] - (RW) UWTBL DELSEL 2 +*/ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_6_UWTBL_DELSEL_2_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_6_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_6_UWTBL_DELSEL_2_MASK \ + 0xFFFFFFFF /* UWTBL_DELSEL_2[31..0] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_6_UWTBL_DELSEL_2_SHFT 0 + +/* +* ---CFG_SEC_MBIST_CTRL_0 (0x820C0000 + 0x25c0)--- +* SEC_MBIST_MODE[0] - (RW) Control register for mbist_mode of SEC +MBIST +* SEC_MBIST_HOLDB[1] - (RW) Control register for mbist_holdb of SEC +MBIST +* SEC_MBIST_DEBUG[2] - (RW) Control register for mbist_debug of SEC +MBIST +* SEC_MBIST_USE_DEFAULT_DELSEL[3] - (RW) Control register for default DELSEL +* value of SEC memory +* RESERVED4[7..4] - (RO) Reserved bits +* SEC_MBIST_DONE[8] - (RO) Working status of SEC SRAM MBIST circuit +* RESERVED9[15..9] - (RO) Reserved bits +* SEC_MBIST_FAIL[17..16] - (RO) MBIST check result of SEC SRAM +* RESERVED18[31..18] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_FAIL_ADDR \ + WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_FAIL_MASK \ + 0x00030000 /* SEC_MBIST_FAIL[17..16] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_FAIL_SHFT 16 +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_DONE_ADDR \ + WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_DONE_MASK \ + 0x00000100 /* SEC_MBIST_DONE[8] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_DONE_SHFT 8 +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_USE_DEFAULT_DELSEL_ADDR \ + WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_USE_DEFAULT_DELSEL_MASK \ + 0x00000008 /* SEC_MBIST_USE_DEFAULT_DELSEL[3] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_USE_DEFAULT_DELSEL_SHFT 3 +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_DEBUG_ADDR \ + WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_DEBUG_MASK \ + 0x00000004 /* SEC_MBIST_DEBUG[2] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_DEBUG_SHFT 2 +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_HOLDB_ADDR \ + WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_HOLDB_MASK \ + 0x00000002 /* SEC_MBIST_HOLDB[1] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_HOLDB_SHFT 1 +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_MODE_ADDR \ + WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_MODE_MASK \ + 0x00000001 /* SEC_MBIST_MODE[0] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_MODE_SHFT 0 + +/* +* ---CFG_SEC_MBIST_CTRL_1 (0x820C0000 + 0x25c4)--- +* SEC_MBIST_HDEN[0] - (RW) Control register for mbist SEC HDEN +* RESERVED1[15..1] - (RO) Reserved bits +* SEC_MBIST_AWT[16] - (RW) Control register for mbist SEC AWT +* RESERVED17[31..17] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_SEC_MBIST_AWT_ADDR \ + WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_SEC_MBIST_AWT_MASK \ + 0x00010000 /* SEC_MBIST_AWT[16] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_SEC_MBIST_AWT_SHFT 16 +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_SEC_MBIST_HDEN_ADDR \ + WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_SEC_MBIST_HDEN_MASK \ + 0x00000001 /* SEC_MBIST_HDEN[0] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_SEC_MBIST_HDEN_SHFT 0 + +/* +* ---CFG_SEC_MBIST_CTRL_2 (0x820C0000 + 0x25c8)--- +* SEC_BACKGROUND[15..0] - (RW) The MBIST background control register +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_2_SEC_BACKGROUND_ADDR \ + WF_PLE_TOP_CFG_SEC_MBIST_CTRL_2_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_2_SEC_BACKGROUND_MASK \ + 0x0000FFFF /* SEC_BACKGROUND[15..0] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_2_SEC_BACKGROUND_SHFT 0 + +/* +* ---CFG_SEC_MBIST_CTRL_3 (0x820C0000 + 0x25cc)--- +* SEC_DELSEL_0[31..0] - (RW) SEC DELSEL 0 +*/ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_3_SEC_DELSEL_0_ADDR \ + WF_PLE_TOP_CFG_SEC_MBIST_CTRL_3_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_3_SEC_DELSEL_0_MASK \ + 0xFFFFFFFF /* SEC_DELSEL_0[31..0] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_3_SEC_DELSEL_0_SHFT 0 + +/* +* ---CFG_PF_MBIST_CTRL_0 (0x820C0000 + 0x25e0)--- +* PF_MBIST_MODE[0] - (RW) Control register for mbist_mode of PF +MBIST +* PF_MBIST_HOLDB[1] - (RW) Control register for mbist_holdb of PF +MBIST +* PF_MBIST_DEBUG[2] - (RW) Control register for mbist_debug of PF +MBIST +* PF_MBIST_USE_DEFAULT_DELSEL[3] - (RW) Control register for default DELSEL +* value of PF memory +* PF_MBIST_SLEEP_TEST[4] - (RW) Control register for sleep_test of PF +MBIST +* PF_MBIST_SLEEP_INV[5] - (RW) Control register for sleep_inv of PF +MBIST +* PF_MBIST_SLEEP_W[6] - (RW) Control register for sleep_w of PF MBIST +* PF_MBIST_SLEEP_R[7] - (RW) Control register for sleep_r of PF MBIST +* PF_MBIST_DONE[8] - (RO) Working status of PF SRAM MBIST circuit +* RESERVED9[11..9] - (RO) Reserved bits +* PF_MBIST_FAIL[31..12] - (RO) MBIST check result of PF SRAM +*/ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_FAIL_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_FAIL_MASK \ + 0xFFFFF000 /* PF_MBIST_FAIL[31..12] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_FAIL_SHFT 12 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_DONE_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_DONE_MASK \ + 0x00000100 /* PF_MBIST_DONE[8] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_DONE_SHFT 8 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_R_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_R_MASK \ + 0x00000080 /* PF_MBIST_SLEEP_R[7] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_R_SHFT 7 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_W_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_W_MASK \ + 0x00000040 /* PF_MBIST_SLEEP_W[6] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_W_SHFT 6 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_INV_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_INV_MASK \ + 0x00000020 /* PF_MBIST_SLEEP_INV[5] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_INV_SHFT 5 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_TEST_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_TEST_MASK \ + 0x00000010 /* PF_MBIST_SLEEP_TEST[4] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_TEST_SHFT 4 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_USE_DEFAULT_DELSEL_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_USE_DEFAULT_DELSEL_MASK \ + 0x00000008 /* PF_MBIST_USE_DEFAULT_DELSEL[3] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_USE_DEFAULT_DELSEL_SHFT 3 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_DEBUG_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_DEBUG_MASK \ + 0x00000004 /* PF_MBIST_DEBUG[2] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_DEBUG_SHFT 2 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_HOLDB_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_HOLDB_MASK \ + 0x00000002 /* PF_MBIST_HOLDB[1] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_HOLDB_SHFT 1 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_MODE_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_MODE_MASK \ + 0x00000001 /* PF_MBIST_MODE[0] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_MODE_SHFT 0 + +/* +* ---CFG_PF_MBIST_CTRL_1 (0x820C0000 + 0x25e4)--- +* PF_MBIST_HDEN[9..0] - (RW) Control register for mbist PF HDEN +* RESERVED10[11..10] - (RO) Reserved bits +* PF_MBIST_AWT[31..12] - (RW) Control register for mbist PF AWT +*/ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_PF_MBIST_AWT_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_PF_MBIST_AWT_MASK \ + 0xFFFFF000 /* PF_MBIST_AWT[31..12] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_PF_MBIST_AWT_SHFT 12 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_PF_MBIST_HDEN_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_PF_MBIST_HDEN_MASK \ + 0x000003FF /* PF_MBIST_HDEN[9..0] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_PF_MBIST_HDEN_SHFT 0 + +/* +* ---CFG_PF_MBIST_CTRL_2 (0x820C0000 + 0x25e8)--- +* PF_BACKGROUND[15..0] - (RW) The MBIST background control register +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_2_PF_BACKGROUND_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_2_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_2_PF_BACKGROUND_MASK \ + 0x0000FFFF /* PF_BACKGROUND[15..0] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_2_PF_BACKGROUND_SHFT 0 + +/* +* ---CFG_PF_MBIST_CTRL_3 (0x820C0000 + 0x25ec)--- +* PF_DELSEL_0[31..0] - (RW) PF DELSEL 0 +*/ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_3_PF_DELSEL_0_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_3_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_3_PF_DELSEL_0_MASK \ + 0xFFFFFFFF /* PF_DELSEL_0[31..0] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_3_PF_DELSEL_0_SHFT 0 + +/* +* ---SYSRAM_MBIST_CTRL (0x820C0000 + 0x3004)--- +* MBIST_SW_RESET[0] - (RW) MBIST Software reset +* RESERVED1[7..1] - (RO) Reserved bits +* MBIST_BSEL[15..8] - (RW) Controls BSEL of SRAM MBIST circuit. +* MBIST_BACKGROUND[31..16] - (RW) The MBIST background control register +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_BACKGROUND_ADDR \ + WF_PLE_TOP_SYSRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_BACKGROUND_MASK \ + 0xFFFF0000 /* MBIST_BACKGROUND[31..16] */ +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_BACKGROUND_SHFT 16 +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_BSEL_ADDR \ + WF_PLE_TOP_SYSRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_BSEL_MASK \ + 0x0000FF00 /* MBIST_BSEL[15..8] */ +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_BSEL_SHFT 8 +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_SW_RESET_ADDR \ + WF_PLE_TOP_SYSRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_SW_RESET_MASK \ + 0x00000001 /* MBIST_SW_RESET[0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_SW_RESET_SHFT 0 + +/* +* ---SYSRAM_MBIST_DEBUG (0x820C0000 + 0x3008)--- +* SYSRAM_MBIST_DEBUG[15..0] - (RW) Control register for mbist_debug of +* SYSRAM MBIST +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_DEBUG_SYSRAM_MBIST_DEBUG_ADDR \ + WF_PLE_TOP_SYSRAM_MBIST_DEBUG_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_DEBUG_SYSRAM_MBIST_DEBUG_MASK \ + 0x0000FFFF /* SYSRAM_MBIST_DEBUG[15..0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_DEBUG_SYSRAM_MBIST_DEBUG_SHFT 0 + +/* +* ---SYSRAM_MBIST_MODE (0x820C0000 + 0x300C)--- +* SYSRAM_MBIST_MODE[15..0] - (RW) Control register for mbist_holdb of +* SYSRAM MBIST +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_MODE_SYSRAM_MBIST_MODE_ADDR \ + WF_PLE_TOP_SYSRAM_MBIST_MODE_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_MODE_SYSRAM_MBIST_MODE_MASK \ + 0x0000FFFF /* SYSRAM_MBIST_MODE[15..0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_MODE_SYSRAM_MBIST_MODE_SHFT 0 + +/* +* ---SYSRAM_MBIST_HOLDB (0x820C0000 + 0x3010)--- +* SYSRAM_MBIST_HOLDB[15..0] - (RW) Control register for mbist_holdb of +* sysram MBIST +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_HOLDB_SYSRAM_MBIST_HOLDB_ADDR \ + WF_PLE_TOP_SYSRAM_MBIST_HOLDB_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_HOLDB_SYSRAM_MBIST_HOLDB_MASK \ + 0x0000FFFF /* SYSRAM_MBIST_HOLDB[15..0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_HOLDB_SYSRAM_MBIST_HOLDB_SHFT 0 + +/* +* ---SYSRAM_MBIST_DONE (0x820C0000 + 0x3014)--- +* SYSRAM_MBIST_DONE[15..0] - (RO) Working status of SYSRAM MBIST 3 circuit +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_DONE_SYSRAM_MBIST_DONE_ADDR \ + WF_PLE_TOP_SYSRAM_MBIST_DONE_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_DONE_SYSRAM_MBIST_DONE_MASK \ + 0x0000FFFF /* SYSRAM_MBIST_DONE[15..0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_DONE_SYSRAM_MBIST_DONE_SHFT 0 + +/* +* ---SYSRAM_MBIST_FAIL (0x820C0000 + 0x3018)--- +* SYSRAM_MBIST_FAIL[31..0] - (RO) MBIST check result of SYSRAM cell 3 +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_FAIL_SYSRAM_MBIST_FAIL_ADDR \ + WF_PLE_TOP_SYSRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_FAIL_SYSRAM_MBIST_FAIL_MASK \ + 0xFFFFFFFF /* SYSRAM_MBIST_FAIL[31..0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_FAIL_SYSRAM_MBIST_FAIL_SHFT 0 + +/* +* ---SYSRAM_MBIST_SLEEP_TEST (0x820C0000 + 0x301C)--- +* SYSRAM_MBIST_SLEEP_TEST[15..0] - (RW) Control register for sleep_test of +* group 3 MBIST +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_TEST_SYSRAM_MBIST_SLEEP_TEST_ADDR \ + WF_PLE_TOP_SYSRAM_MBIST_SLEEP_TEST_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_TEST_SYSRAM_MBIST_SLEEP_TEST_MASK \ + 0x0000FFFF /* SYSRAM_MBIST_SLEEP_TEST[15..0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_TEST_SYSRAM_MBIST_SLEEP_TEST_SHFT 0 + +/* +* ---SYSRAM_MBIST_SLEEP_INV (0x820C0000 + 0x3020)--- +* SYSRAM_MBIST_SLEEP_INV[15..0] - (RW) Control register for sleep_inv of group +* 3 MBIST +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_INV_SYSRAM_MBIST_SLEEP_INV_ADDR \ + WF_PLE_TOP_SYSRAM_MBIST_SLEEP_INV_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_INV_SYSRAM_MBIST_SLEEP_INV_MASK \ + 0x0000FFFF /* SYSRAM_MBIST_SLEEP_INV[15..0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_INV_SYSRAM_MBIST_SLEEP_INV_SHFT 0 + +/* +* ---SYSRAM_MBIST_SLEEP_W (0x820C0000 + 0x3024)--- +* SYSRAM_MBIST_SLEEP_WRITE[15..0] - (RW) Control register for sleep_w of group +* 3 MBIST +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_W_SYSRAM_MBIST_SLEEP_WRITE_ADDR \ + WF_PLE_TOP_SYSRAM_MBIST_SLEEP_W_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_W_SYSRAM_MBIST_SLEEP_WRITE_MASK \ + 0x0000FFFF /* SYSRAM_MBIST_SLEEP_WRITE[15..0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_W_SYSRAM_MBIST_SLEEP_WRITE_SHFT 0 + +/* +* ---SYSRAM_MBIST_SLEEP_R (0x820C0000 + 0x3028)--- +* SYSRAM_MBIST_SLEEP_READ[15..0] - (RW) Control register for sleep_r of group +* 3 MBIST +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_R_SYSRAM_MBIST_SLEEP_READ_ADDR \ + WF_PLE_TOP_SYSRAM_MBIST_SLEEP_R_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_R_SYSRAM_MBIST_SLEEP_READ_MASK \ + 0x0000FFFF /* SYSRAM_MBIST_SLEEP_READ[15..0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_R_SYSRAM_MBIST_SLEEP_READ_SHFT 0 + +/* +* ---SYSRAM_AWT_HDEN (0x820C0000 + 0x302C)--- +* SYSRAM_MBIST_AWT[15..0] - (RW) Control register for mbist SYSRAM 3 AWT +* SYSRAM_MBIST_HDEN[31..16] - (RW) Control register for mbist SYSRAM 3 HDEN +*/ +#define WF_PLE_TOP_SYSRAM_AWT_HDEN_SYSRAM_MBIST_HDEN_ADDR \ + WF_PLE_TOP_SYSRAM_AWT_HDEN_ADDR +#define WF_PLE_TOP_SYSRAM_AWT_HDEN_SYSRAM_MBIST_HDEN_MASK \ + 0xFFFF0000 /* SYSRAM_MBIST_HDEN[31..16] */ +#define WF_PLE_TOP_SYSRAM_AWT_HDEN_SYSRAM_MBIST_HDEN_SHFT 16 +#define WF_PLE_TOP_SYSRAM_AWT_HDEN_SYSRAM_MBIST_AWT_ADDR \ + WF_PLE_TOP_SYSRAM_AWT_HDEN_ADDR +#define WF_PLE_TOP_SYSRAM_AWT_HDEN_SYSRAM_MBIST_AWT_MASK \ + 0x0000FFFF /* SYSRAM_MBIST_AWT[15..0] */ +#define WF_PLE_TOP_SYSRAM_AWT_HDEN_SYSRAM_MBIST_AWT_SHFT 0 + +/* +* ---SYSRAM_DBG_SEL (0x820C0000 + 0x3030)--- +* SYSRAM_DEBUG_SELECT_0[7..0] - (RW) Selects SYSRAM control debug 0 +* SYSRAM_DEBUG_SELECT_1[15..8] - (RW) Selects SYSRAM control debug 1 +* SYSRAM_DEBUG_SELECT_2[23..16] - (RW) Selects SYSRAM control debug 2 +* SYSRAM_DEBUG_SELECT_3[31..24] - (RW) Selects SYSRAM control debug 3 +*/ +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_3_ADDR \ + WF_PLE_TOP_SYSRAM_DBG_SEL_ADDR +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_3_MASK \ + 0xFF000000 /* SYSRAM_DEBUG_SELECT_3[31..24] */ +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_3_SHFT 24 +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_2_ADDR \ + WF_PLE_TOP_SYSRAM_DBG_SEL_ADDR +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_2_MASK \ + 0x00FF0000 /* SYSRAM_DEBUG_SELECT_2[23..16] */ +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_2_SHFT 16 +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_1_ADDR \ + WF_PLE_TOP_SYSRAM_DBG_SEL_ADDR +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_1_MASK \ + 0x0000FF00 /* SYSRAM_DEBUG_SELECT_1[15..8] */ +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_1_SHFT 8 +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_0_ADDR \ + WF_PLE_TOP_SYSRAM_DBG_SEL_ADDR +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_0_MASK \ + 0x000000FF /* SYSRAM_DEBUG_SELECT_0[7..0] */ +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_0_SHFT 0 + +/* +* ---SYSRAM_DELSEL (0x820C0000 + 0x3070)--- +* TYPE0_SYSRAM_DELSEL[31..0] - (RW) Type0 SYSRAM DELSEL bits +*/ +#define WF_PLE_TOP_SYSRAM_DELSEL_TYPE0_SYSRAM_DELSEL_ADDR \ + WF_PLE_TOP_SYSRAM_DELSEL_ADDR +#define WF_PLE_TOP_SYSRAM_DELSEL_TYPE0_SYSRAM_DELSEL_MASK \ + 0xFFFFFFFF /* TYPE0_SYSRAM_DELSEL[31..0] */ +#define WF_PLE_TOP_SYSRAM_DELSEL_TYPE0_SYSRAM_DELSEL_SHFT 0 + +/* +* ---SYSRAM_DELSEL_1 (0x820C0000 + 0x3074)--- +* TYPE1_SYSRAM_DELSEL[31..0] - (RW) Type1 SYSRAM DELSEL bits +*/ +#define WF_PLE_TOP_SYSRAM_DELSEL_1_TYPE1_SYSRAM_DELSEL_ADDR \ + WF_PLE_TOP_SYSRAM_DELSEL_1_ADDR +#define WF_PLE_TOP_SYSRAM_DELSEL_1_TYPE1_SYSRAM_DELSEL_MASK \ + 0xFFFFFFFF /* TYPE1_SYSRAM_DELSEL[31..0] */ +#define WF_PLE_TOP_SYSRAM_DELSEL_1_TYPE1_SYSRAM_DELSEL_SHFT 0 + +/* +* ---SYSRAM_DELSEL_2 (0x820C0000 + 0x3078)--- +* TYPE2_SYSRAM_DELSEL[31..0] - (RW) Type2 SYSRAM DELSEL bits +*/ +#define WF_PLE_TOP_SYSRAM_DELSEL_2_TYPE2_SYSRAM_DELSEL_ADDR \ + WF_PLE_TOP_SYSRAM_DELSEL_2_ADDR +#define WF_PLE_TOP_SYSRAM_DELSEL_2_TYPE2_SYSRAM_DELSEL_MASK \ + 0xFFFFFFFF /* TYPE2_SYSRAM_DELSEL[31..0] */ +#define WF_PLE_TOP_SYSRAM_DELSEL_2_TYPE2_SYSRAM_DELSEL_SHFT 0 + +/* +* ---SYSRAM_DELSEL_3 (0x820C0000 + 0x307C)--- +* TYPE3_SYSRAM_DELSEL[31..0] - (RW) Type3 SYSRAM DELSEL bits +*/ +#define WF_PLE_TOP_SYSRAM_DELSEL_3_TYPE3_SYSRAM_DELSEL_ADDR \ + WF_PLE_TOP_SYSRAM_DELSEL_3_ADDR +#define WF_PLE_TOP_SYSRAM_DELSEL_3_TYPE3_SYSRAM_DELSEL_MASK \ + 0xFFFFFFFF /* TYPE3_SYSRAM_DELSEL[31..0] */ +#define WF_PLE_TOP_SYSRAM_DELSEL_3_TYPE3_SYSRAM_DELSEL_SHFT 0 + +/* +* ---SYSRAM_OUTRAN_ERR_FLAG (0x820C0000 + 0x3080)--- +* SYSRAM_OUTRAN_ERR_FLAG[31..0] - (RO) Type3 SYSRAM DELSEL bits +*/ +#define WF_PLE_TOP_SYSRAM_OUTRAN_ERR_FLAG_SYSRAM_OUTRAN_ERR_FLAG_ADDR \ + WF_PLE_TOP_SYSRAM_OUTRAN_ERR_FLAG_ADDR +#define WF_PLE_TOP_SYSRAM_OUTRAN_ERR_FLAG_SYSRAM_OUTRAN_ERR_FLAG_MASK \ + 0xFFFFFFFF /* SYSRAM_OUTRAN_ERR_FLAG[31..0] */ +#define WF_PLE_TOP_SYSRAM_OUTRAN_ERR_FLAG_SYSRAM_OUTRAN_ERR_FLAG_SHFT 0 + +#ifdef __cplusplus +} +#endif + +#endif /* __WF_PLE_TOP_REGS_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7961/wf_pse_top.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7961/wf_pse_top.h new file mode 100644 index 0000000000000..5199f127f81a3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7961/wf_pse_top.h @@ -0,0 +1,3661 @@ +/* [File] : wf_pse_top.h */ +/* [Revision time] : Fri May 31 13:36:45 2019 */ +/* [Description] : This file is auto generated by CODA */ +/* [Copyright] : Copyright (C) 2019 Mediatek Incorportion. All rights */ +/* reserved. */ + +#ifndef __WF_PSE_TOP_REGS_H__ +#define __WF_PSE_TOP_REGS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ************************************************************************** */ +/* */ +/* WF_PSE_TOP CR Definitions */ +/* */ +/* ************************************************************************** */ + +#define WF_PSE_TOP_BASE 0x820C8000 + +#define WF_PSE_TOP_GC_ADDR \ + (WF_PSE_TOP_BASE + 0x00) /* 8000 */ +#define WF_PSE_TOP_PBUF_CTRL_ADDR \ + (WF_PSE_TOP_BASE + 0x04) /* 8004 */ +#define WF_PSE_TOP_INT_N9_EN_MASK_ADDR \ + (WF_PSE_TOP_BASE + 0x08) /* 8008 */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_ADDR \ + (WF_PSE_TOP_BASE + 0x24) /* 8024 */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR \ + (WF_PSE_TOP_BASE + 0x28) /* 8028 */ +#define WF_PSE_TOP_INT_N9_STS_ADDR \ + (WF_PSE_TOP_BASE + 0x30) /* 8030 */ +#define WF_PSE_TOP_INT_N9_ERR_STS_ADDR \ + (WF_PSE_TOP_BASE + 0x34) /* 8034 */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_ADDR \ + (WF_PSE_TOP_BASE + 0x38) /* 8038 */ +#define WF_PSE_TOP_QUEUE_EMPTY_ADDR \ + (WF_PSE_TOP_BASE + 0xB0) /* 80B0 */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR \ + (WF_PSE_TOP_BASE + 0xB4) /* 80B4 */ +#define WF_PSE_TOP_PSE_LP_CTRL_ADDR \ + (WF_PSE_TOP_BASE + 0xB8) /* 80B8 */ +#define WF_PSE_TOP_TO_N9_INT_ADDR \ + (WF_PSE_TOP_BASE + 0xF0) /* 80F0 */ +#define WF_PSE_TOP_GROUP_REFILL_CTRL_ADDR \ + (WF_PSE_TOP_BASE + 0x108) /* 8108 */ +#define WF_PSE_TOP_FREEPG_START_END_ADDR \ + (WF_PSE_TOP_BASE + 0x10C) /* 810C */ +#define WF_PSE_TOP_PG_HIF0_GROUP_ADDR \ + (WF_PSE_TOP_BASE + 0x110) /* 8110 */ +#define WF_PSE_TOP_PG_HIF1_GROUP_ADDR \ + (WF_PSE_TOP_BASE + 0x114) /* 8114 */ +#define WF_PSE_TOP_PG_CPU_GROUP_ADDR \ + (WF_PSE_TOP_BASE + 0x118) /* 8118 */ +#define WF_PSE_TOP_PG_PLE_GROUP_ADDR \ + (WF_PSE_TOP_BASE + 0x11C) /* 811C */ +#define WF_PSE_TOP_PG_PLE1_GROUP_ADDR \ + (WF_PSE_TOP_BASE + 0x120) /* 8120 */ +#define WF_PSE_TOP_PG_LMAC0_GROUP_ADDR \ + (WF_PSE_TOP_BASE + 0x124) /* 8124 */ +#define WF_PSE_TOP_PG_LMAC1_GROUP_ADDR \ + (WF_PSE_TOP_BASE + 0x128) /* 8128 */ +#define WF_PSE_TOP_PG_LMAC2_GROUP_ADDR \ + (WF_PSE_TOP_BASE + 0x12C) /* 812C */ +#define WF_PSE_TOP_PG_LMAC3_GROUP_ADDR \ + (WF_PSE_TOP_BASE + 0x130) /* 8130 */ +#define WF_PSE_TOP_PG_MDP_GROUP_ADDR \ + (WF_PSE_TOP_BASE + 0x134) /* 8134 */ +#define WF_PSE_TOP_PG_MDP1_GROUP_ADDR \ + (WF_PSE_TOP_BASE + 0x138) /* 8138 */ +#define WF_PSE_TOP_PG_MDP2_GROUP_ADDR \ + (WF_PSE_TOP_BASE + 0x13C) /* 813C */ +#define WF_PSE_TOP_PG_HIF2_GROUP_ADDR \ + (WF_PSE_TOP_BASE + 0x140) /* 8140 */ +#define WF_PSE_TOP_HIF0_PG_INFO_ADDR \ + (WF_PSE_TOP_BASE + 0x150) /* 8150 */ +#define WF_PSE_TOP_HIF1_PG_INFO_ADDR \ + (WF_PSE_TOP_BASE + 0x154) /* 8154 */ +#define WF_PSE_TOP_CPU_PG_INFO_ADDR \ + (WF_PSE_TOP_BASE + 0x158) /* 8158 */ +#define WF_PSE_TOP_PLE_PG_INFO_ADDR \ + (WF_PSE_TOP_BASE + 0x15C) /* 815C */ +#define WF_PSE_TOP_PLE1_PG_INFO_ADDR \ + (WF_PSE_TOP_BASE + 0x160) /* 8160 */ +#define WF_PSE_TOP_LMAC0_PG_INFO_ADDR \ + (WF_PSE_TOP_BASE + 0x164) /* 8164 */ +#define WF_PSE_TOP_LMAC1_PG_INFO_ADDR \ + (WF_PSE_TOP_BASE + 0x168) /* 8168 */ +#define WF_PSE_TOP_LMAC2_PG_INFO_ADDR \ + (WF_PSE_TOP_BASE + 0x16C) /* 816C */ +#define WF_PSE_TOP_LMAC3_PG_INFO_ADDR \ + (WF_PSE_TOP_BASE + 0x170) /* 8170 */ +#define WF_PSE_TOP_MDP_PG_INFO_ADDR \ + (WF_PSE_TOP_BASE + 0x174) /* 8174 */ +#define WF_PSE_TOP_MDP1_PG_INFO_ADDR \ + (WF_PSE_TOP_BASE + 0x178) /* 8178 */ +#define WF_PSE_TOP_MDP2_PG_INFO_ADDR \ + (WF_PSE_TOP_BASE + 0x17C) /* 817C */ +#define WF_PSE_TOP_HIF2_PG_INFO_ADDR \ + (WF_PSE_TOP_BASE + 0x180) /* 8180 */ +#define WF_PSE_TOP_DTIM_CTRL_ADDR \ + (WF_PSE_TOP_BASE + 0x190) /* 8190 */ +#define WF_PSE_TOP_FREEPG_START_END_DTIM_ADDR \ + (WF_PSE_TOP_BASE + 0x194) /* 8194 */ +#define WF_PSE_TOP_PG_LMAC0_GROUP_DTIM_ADDR \ + (WF_PSE_TOP_BASE + 0x198) /* 8198 */ +#define WF_PSE_TOP_PG_LMAC1_GROUP_DTIM_ADDR \ + (WF_PSE_TOP_BASE + 0x19C) /* 819C */ +#define WF_PSE_TOP_PG_MDP_GROUP_DTIM_ADDR \ + (WF_PSE_TOP_BASE + 0x1A0) /* 81A0 */ +#define WF_PSE_TOP_FL_QUE_CTRL_0_ADDR \ + (WF_PSE_TOP_BASE + 0x1B0) /* 81B0 */ +#define WF_PSE_TOP_FL_QUE_CTRL_1_ADDR \ + (WF_PSE_TOP_BASE + 0x1B4) /* 81B4 */ +#define WF_PSE_TOP_FL_QUE_CTRL_2_ADDR \ + (WF_PSE_TOP_BASE + 0x1B8) /* 81B8 */ +#define WF_PSE_TOP_FL_QUE_CTRL_3_ADDR \ + (WF_PSE_TOP_BASE + 0x1BC) /* 81BC */ +#define WF_PSE_TOP_PL_QUE_CTRL_0_ADDR \ + (WF_PSE_TOP_BASE + 0x1C0) /* 81C0 */ +#define WF_PSE_TOP_PSE_CT_PRI_CTRL_ADDR \ + (WF_PSE_TOP_BASE + 0x1EC) /* 81EC */ +#define WF_PSE_TOP_PLE_ENQ_PKT_NUM_ADDR \ + (WF_PSE_TOP_BASE + 0x1F0) /* 81F0 */ +#define WF_PSE_TOP_CPU_ENQ_PKT_NUM_ADDR \ + (WF_PSE_TOP_BASE + 0x1F4) /* 81F4 */ +#define WF_PSE_TOP_LMAC_ENQ_PKT_NUM_ADDR \ + (WF_PSE_TOP_BASE + 0x1F8) /* 81F8 */ +#define WF_PSE_TOP_HIF_ENQ_PKT_NUM_ADDR \ + (WF_PSE_TOP_BASE + 0x1FC) /* 81FC */ +#define WF_PSE_TOP_MDP_ENQ_PKT_NUM_ADDR \ + (WF_PSE_TOP_BASE + 0x200) /* 8200 */ +#define WF_PSE_TOP_RL_BUF_CTRL_0_ADDR \ + (WF_PSE_TOP_BASE + 0x210) /* 8210 */ +#define WF_PSE_TOP_RL_BUF_CTRL_1_ADDR \ + (WF_PSE_TOP_BASE + 0x214) /* 8214 */ +#define WF_PSE_TOP_TIMEOUT_CTRL_ADDR \ + (WF_PSE_TOP_BASE + 0x244) /* 8244 */ +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_ADDR \ + (WF_PSE_TOP_BASE + 0x248) /* 8248 */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR \ + (WF_PSE_TOP_BASE + 0x24C) /* 824C */ +#define WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_ADDR \ + (WF_PSE_TOP_BASE + 0x250) /* 8250 */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR \ + (WF_PSE_TOP_BASE + 0x254) /* 8254 */ +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_ADDR \ + (WF_PSE_TOP_BASE + 0x258) /* 8258 */ +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_ADDR \ + (WF_PSE_TOP_BASE + 0x280) /* 8280 */ +#define WF_PSE_TOP_PSE_SER_CTRL_ADDR \ + (WF_PSE_TOP_BASE + 0x2A0) /* 82A0 */ +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_ADDR \ + (WF_PSE_TOP_BASE + 0x2B0) /* 82B0 */ +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_ADDR \ + (WF_PSE_TOP_BASE + 0x2B4) /* 82B4 */ +#define WF_PSE_TOP_PSE_MBIST_BSEL_ADDR \ + (WF_PSE_TOP_BASE + 0x2B8) /* 82B8 */ +#define WF_PSE_TOP_SRAM_MBIST_BACKGROUND_ADDR \ + (WF_PSE_TOP_BASE + 0x2C0) /* 82C0 */ +#define WF_PSE_TOP_SRAM_MBIST_DONE_ADDR \ + (WF_PSE_TOP_BASE + 0x2C4) /* 82C4 */ +#define WF_PSE_TOP_SRAM_MBIST_FAIL_ADDR \ + (WF_PSE_TOP_BASE + 0x2C8) /* 82C8 */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR \ + (WF_PSE_TOP_BASE + 0x2D0) /* 82D0 */ +#define WF_PSE_TOP_SRAM_MBIST_DELSEL_ADDR \ + (WF_PSE_TOP_BASE + 0x2D4) /* 82D4 */ +#define WF_PSE_TOP_SRAM_MBIST_DELSEL_1_ADDR \ + (WF_PSE_TOP_BASE + 0x2D8) /* 82D8 */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR \ + (WF_PSE_TOP_BASE + 0x2DC) /* 82DC */ +#define WF_PSE_TOP_C_GET_FID_0_ADDR \ + (WF_PSE_TOP_BASE + 0x310) /* 8310 */ +#define WF_PSE_TOP_C_GET_FID_1_ADDR \ + (WF_PSE_TOP_BASE + 0x314) /* 8314 */ +#define WF_PSE_TOP_C_EN_QUEUE_0_ADDR \ + (WF_PSE_TOP_BASE + 0x320) /* 8320 */ +#define WF_PSE_TOP_C_EN_QUEUE_1_ADDR \ + (WF_PSE_TOP_BASE + 0x324) /* 8324 */ +#define WF_PSE_TOP_C_EN_QUEUE_2_ADDR \ + (WF_PSE_TOP_BASE + 0x328) /* 8328 */ +#define WF_PSE_TOP_C_DE_QUEUE_0_ADDR \ + (WF_PSE_TOP_BASE + 0x330) /* 8330 */ +#define WF_PSE_TOP_C_DE_QUEUE_1_ADDR \ + (WF_PSE_TOP_BASE + 0x334) /* 8334 */ +#define WF_PSE_TOP_C_DE_QUEUE_2_ADDR \ + (WF_PSE_TOP_BASE + 0x338) /* 8338 */ +#define WF_PSE_TOP_C_DE_QUEUE_3_ADDR \ + (WF_PSE_TOP_BASE + 0x33C) /* 833C */ +#define WF_PSE_TOP_C_DE_QUEUE_4_ADDR \ + (WF_PSE_TOP_BASE + 0x340) /* 8340 */ +#define WF_PSE_TOP_ALLOCATE_0_ADDR \ + (WF_PSE_TOP_BASE + 0x350) /* 8350 */ +#define WF_PSE_TOP_ALLOCATE_1_ADDR \ + (WF_PSE_TOP_BASE + 0x354) /* 8354 */ +#define WF_PSE_TOP_FREEPG_CNT_ADDR \ + (WF_PSE_TOP_BASE + 0x380) /* 8380 */ +#define WF_PSE_TOP_FREEPG_HEAD_TAIL_ADDR \ + (WF_PSE_TOP_BASE + 0x384) /* 8384 */ +#define WF_PSE_TOP_PSE_SEEK_CR_00_ADDR \ + (WF_PSE_TOP_BASE + 0x3D0) /* 83D0 */ +#define WF_PSE_TOP_PSE_SEEK_CR_01_ADDR \ + (WF_PSE_TOP_BASE + 0x3D4) /* 83D4 */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_ADDR \ + (WF_PSE_TOP_BASE + 0x3D8) /* 83D8 */ +#define WF_PSE_TOP_PSE_SEEK_CR_03_ADDR \ + (WF_PSE_TOP_BASE + 0x3DC) /* 83DC */ +#define WF_PSE_TOP_PSE_SEEK_CR_04_ADDR \ + (WF_PSE_TOP_BASE + 0x3E0) /* 83E0 */ +#define WF_PSE_TOP_PSE_SEEK_CR_05_ADDR \ + (WF_PSE_TOP_BASE + 0x3E4) /* 83E4 */ +#define WF_PSE_TOP_PSE_SEEK_CR_06_ADDR \ + (WF_PSE_TOP_BASE + 0x3E8) /* 83E8 */ +#define WF_PSE_TOP_PSE_SEEK_CR_07_ADDR \ + (WF_PSE_TOP_BASE + 0x3EC) /* 83EC */ +#define WF_PSE_TOP_PSE_SEEK_CR_08_ADDR \ + (WF_PSE_TOP_BASE + 0x3F0) /* 83F0 */ +#define WF_PSE_TOP_PSE_SEEK_CR_09_ADDR \ + (WF_PSE_TOP_BASE + 0x3F4) /* 83F4 */ + +/* +* ---GC (0x820C8000 + 0x00)--- +* ALL_RESET[0] - (RW) Resets PSE logic and register +* LOGIC_RESET[1] - (RW) Resets PSE logic circuit +* INIT_DONE[2] - (RO) PSE control SRAM initialization +indicator +* RESERVED3[15..3] - (RO) Reserved bits +* SRAM_MBIST_RESET[16] - (RW) Reset control of SRAM MBIST (low active) +* RESERVED17[17] - (RO) Reserved bits +* DIS_PSE_DYN_CKG[18] - (RW) Disable control of wf_pse_top dynamic +* clock gating function +* RESERVED19[31..19] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_GC_DIS_PSE_DYN_CKG_ADDR WF_PSE_TOP_GC_ADDR +#define WF_PSE_TOP_GC_DIS_PSE_DYN_CKG_MASK 0x00040000 /* DIS_PSE_DYN_CKG[18] */ +#define WF_PSE_TOP_GC_DIS_PSE_DYN_CKG_SHFT 18 +#define WF_PSE_TOP_GC_SRAM_MBIST_RESET_ADDR WF_PSE_TOP_GC_ADDR +#define WF_PSE_TOP_GC_SRAM_MBIST_RESET_MASK \ + 0x00010000 /* SRAM_MBIST_RESET[16] */ +#define WF_PSE_TOP_GC_SRAM_MBIST_RESET_SHFT 16 +#define WF_PSE_TOP_GC_INIT_DONE_ADDR WF_PSE_TOP_GC_ADDR +#define WF_PSE_TOP_GC_INIT_DONE_MASK 0x00000004 /* INIT_DONE[2] */ +#define WF_PSE_TOP_GC_INIT_DONE_SHFT 2 +#define WF_PSE_TOP_GC_LOGIC_RESET_ADDR WF_PSE_TOP_GC_ADDR +#define WF_PSE_TOP_GC_LOGIC_RESET_MASK 0x00000002 /* LOGIC_RESET[1] */ +#define WF_PSE_TOP_GC_LOGIC_RESET_SHFT 1 +#define WF_PSE_TOP_GC_ALL_RESET_ADDR WF_PSE_TOP_GC_ADDR +#define WF_PSE_TOP_GC_ALL_RESET_MASK 0x00000001 /* ALL_RESET[0] */ +#define WF_PSE_TOP_GC_ALL_RESET_SHFT 0 + +/* +* ---PBUF_CTRL (0x820C8000 + 0x04)--- +* TOTAL_PAGE_NUM[11..0] - (RW) Total page numbers +* Set the total page before release PSE logic +* reset, and must not be changed after release logic reset. +* RESERVED12[16..12] - (RO) Reserved bits +* PBUF_OFFSET[25..17] - (RW) Packet buffer offset. +* Set the buffer offset before release PSE +* logic reset, and must not be changed after release logic reset. +* RESERVED26[30..26] - (RO) Reserved bits +* PAGE_SIZE_CFG[31] - (RW) Configures page size +* Set up the page size before releasing PSE +* logic reset; it should not be changed after logic reset is released. +*/ +#define WF_PSE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_ADDR WF_PSE_TOP_PBUF_CTRL_ADDR +#define WF_PSE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_MASK \ + 0x80000000 /* PAGE_SIZE_CFG[31] */ +#define WF_PSE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_SHFT 31 +#define WF_PSE_TOP_PBUF_CTRL_PBUF_OFFSET_ADDR WF_PSE_TOP_PBUF_CTRL_ADDR +#define WF_PSE_TOP_PBUF_CTRL_PBUF_OFFSET_MASK \ + 0x03FE0000 /* PBUF_OFFSET[25..17] */ +#define WF_PSE_TOP_PBUF_CTRL_PBUF_OFFSET_SHFT 17 +#define WF_PSE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_ADDR WF_PSE_TOP_PBUF_CTRL_ADDR +#define WF_PSE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_MASK \ +0x00000FFF /* TOTAL_PAGE_NUM[11..0] */ +#define WF_PSE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_SHFT 0 + +/* +* ---INT_N9_EN_MASK (0x820C8000 + 0x08)--- +* EN_CPU_Q0_NE[0] - (RW) CPU queue 0 not empty interrupt +* EN_CPU_Q1_NE[1] - (RW) CPU queue 1 not empty interrupt +* EN_CPU_Q2_NE[2] - (RW) CPU queue 2 not empty interrupt +* EN_CPU_Q3_NE[3] - (RW) CPU queue 3 not empty interrupt +* RESERVED4[11..4] - (RO) Reserved bits +* EN_LMAC_ENQ[12] - (RW) Enables LMAC enq interrupt +* EN_ERROR_INT[13] - (RW) Error condition interrupt status +* RESERVED14[15..14] - (RO) Reserved bits +* EN_TOGGLE_INT[16] - (RW) Data toggle of CR4 toggle register +(0xe0) +* EN_LMAC_EMPTY_FALL[17] - (RW) LMAC Buffer empty fall edge detect +* EN_LMAC_EMPTY_RAISE[18] - (RW) LMAC Buffer empty raise edge detect +* EN_HIF_Q0_NE[19] - (RW) HIF queue 0 not empty interrupt +* EN_HIF_Q1_NE[20] - (RW) HIF queue 1 not empty interrupt +* EN_HIF_Q2_NE[21] - (RW) HIF queue 2 not empty interrupt +* EN_HIF_Q3_NE[22] - (RW) HIF queue 3 not empty interrupt +* EN_HIF_Q4_NE[23] - (RW) HIF queue 4 not empty interrupt +* EN_HIF_Q5_NE[24] - (RW) HIF queue 5 not empty interrupt +* EN_HIF_Q6_NE[25] - (RW) HIF queue 6 not empty interrupt +* EN_HIF_Q7_NE[26] - (RW) HIF queue 7 not empty interrupt +* EN_HIF_Q8_NE[27] - (RW) HIF queue 8 not empty interrupt +* EN_HIF_Q9_NE[28] - (RW) HIF queue 9 not empty interrupt +* EN_HIF_Q10_NE[29] - (RW) HIF queue 10 not empty interrupt +* EN_HIF_Q11_NE[30] - (RW) HIF queue 11 not empty interrupt +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q11_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q11_NE_MASK \ +0x40000000 /* EN_HIF_Q11_NE[30] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q11_NE_SHFT 30 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q10_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q10_NE_MASK \ +0x20000000 /* EN_HIF_Q10_NE[29] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q10_NE_SHFT 29 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q9_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q9_NE_MASK \ +0x10000000 /* EN_HIF_Q9_NE[28] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q9_NE_SHFT 28 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q8_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q8_NE_MASK \ +0x08000000 /* EN_HIF_Q8_NE[27] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q8_NE_SHFT 27 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q7_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q7_NE_MASK \ +0x04000000 /* EN_HIF_Q7_NE[26] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q7_NE_SHFT 26 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q6_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q6_NE_MASK \ +0x02000000 /* EN_HIF_Q6_NE[25] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q6_NE_SHFT 25 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q5_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q5_NE_MASK \ +0x01000000 /* EN_HIF_Q5_NE[24] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q5_NE_SHFT 24 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q4_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q4_NE_MASK \ +0x00800000 /* EN_HIF_Q4_NE[23] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q4_NE_SHFT 23 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q3_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q3_NE_MASK \ +0x00400000 /* EN_HIF_Q3_NE[22] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q3_NE_SHFT 22 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q2_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q2_NE_MASK \ +0x00200000 /* EN_HIF_Q2_NE[21] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q2_NE_SHFT 21 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q1_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q1_NE_MASK \ +0x00100000 /* EN_HIF_Q1_NE[20] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q1_NE_SHFT 20 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q0_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q0_NE_MASK \ +0x00080000 /* EN_HIF_Q0_NE[19] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q0_NE_SHFT 19 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_EMPTY_RAISE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_EMPTY_RAISE_MASK \ +0x00040000 /* EN_LMAC_EMPTY_RAISE[18] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_EMPTY_RAISE_SHFT 18 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_EMPTY_FALL_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_EMPTY_FALL_MASK \ +0x00020000 /* EN_LMAC_EMPTY_FALL[17] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_EMPTY_FALL_SHFT 17 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_TOGGLE_INT_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_TOGGLE_INT_MASK \ +0x00010000 /* EN_TOGGLE_INT[16] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_TOGGLE_INT_SHFT 16 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_ERROR_INT_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_ERROR_INT_MASK \ +0x00002000 /* EN_ERROR_INT[13] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_ERROR_INT_SHFT 13 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_ENQ_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_ENQ_MASK \ + 0x00001000 /* EN_LMAC_ENQ[12] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_ENQ_SHFT 12 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q3_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q3_NE_MASK \ +0x00000008 /* EN_CPU_Q3_NE[3] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q3_NE_SHFT 3 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q2_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q2_NE_MASK \ +0x00000004 /* EN_CPU_Q2_NE[2] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q2_NE_SHFT 2 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q1_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q1_NE_MASK \ +0x00000002 /* EN_CPU_Q1_NE[1] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q1_NE_SHFT 1 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q0_NE_ADDR \ +WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q0_NE_MASK \ +0x00000001 /* EN_CPU_Q0_NE[0] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q0_NE_SHFT 0 + +/* +* ---INT_N9_ERR_MASK (0x820C8000 + 0x24)--- +* EN_Q_CMD_ERR_P0[0] - (RW) Enable Queue command error interrupt +* status of port 0. Avoid unclear error flag, please clear flag when logic +reset. +* EN_Q_CMD_ERR_P1[1] - (RW) Enable Queue command error interrupt +* status of port 1. Avoid unclear error flag, please clear flag when logic +reset. +* EN_Q_CMD_ERR_P2[2] - (RW) Enable Queue command error interrupt +* status of port 2. Avoid unclear error flag, please clear flag when logic +reset. +* EN_Q_CMD_ERR_P3[3] - (RW) Enable Queue command error interrupt +* status of port 3. Avoid unclear error flag, please clear flag when logic +reset. +* EN_Q_CMD_ERR_P4[4] - (RW) Enable Queue command error interrupt +* status of port 4. Avoid unclear error flag, please clear flag when logic +reset. +* EN_Q_CMD_ERR_P5[5] - (RW) Enable Queue command error interrupt +* status of port 5. Avoid unclear error flag, please clear flag when logic +reset. +* EN_Q_CMD_ERR_P6[6] - (RW) Enable Queue command error interrupt +* status of port 6. Avoid unclear error flag, please clear flag when logic +reset. +* RESERVED7[7] - (RO) Reserved bits +* EN_PAGE_UDF_P0[8] - (RW) Enable Page underflow interrupt status +* of port 0. Avoid unclear error flag, please clear flag when logic reset. +* EN_PAGE_UDF_P1[9] - (RW) Enable Page underflow interrupt status +* of port 1. Avoid unclear error flag, please clear flag when logic reset. +* EN_PAGE_UDF_P2[10] - (RW) Enable Page underflow interrupt status +* of port 2. Avoid unclear error flag, please clear flag when logic reset. +* EN_PAGE_UDF_P3[11] - (RW) Enable Page underflow interrupt status +* of port 3. Avoid unclear error flag, please clear flag when logic reset. +* EN_PAGE_UDF_P4[12] - (RW) Enable Page underflow interrupt status +* of port 4. Avoid unclear error flag, please clear flag when logic reset. +* EN_PAGE_UDF_P5[13] - (RW) Enable Page underflow interrupt status +* of port 5. Avoid unclear error flag, please clear flag when logic reset. +* EN_PAGE_UDF_P6[14] - (RW) Enable Page underflow interrupt status +* of port 6. Avoid unclear error flag, please clear flag when logic reset. +* RESERVED15[15] - (RO) Reserved bits +* EN_QUEUE_OPER_ERR_P0[16] - (RW) Enable Queue operation error of port 0. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_QUEUE_OPER_ERR_P1[17] - (RW) Enable Queue operation error of port 1. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_QUEUE_OPER_ERR_P2[18] - (RW) Enable Queue operation error of port 2. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_QUEUE_OPER_ERR_P3[19] - (RW) Enable Queue operation error of port 3. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_QUEUE_OPER_ERR_P4[20] - (RW) Enable Queue operation error of port 4. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_QUEUE_OPER_ERR_P5[21] - (RW) Enable Queue operation error of port 5. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_QUEUE_OPER_ERR_P6[22] - (RW) Enable Queue operation error of port 6. +* Avoid unclear error flag, please clear flag when logic reset. +* RESERVED23[23] - (RO) Reserved bits +* EN_DATA_OPER_ERR_P0[24] - (RW) Enable Data operation error of port 0. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_DATA_OPER_ERR_P1[25] - (RW) Enable Data operation error of port 1. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_DATA_OPER_ERR_P2[26] - (RW) Enable Data operation error of port 2. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_DATA_OPER_ERR_P3[27] - (RW) Enable Data operation error of port 3. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_DATA_OPER_ERR_P4[28] - (RW) Enable Data operation error of port 4. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_DATA_OPER_ERR_P5[29] - (RW) Enable Data operation error of port 5. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_DATA_OPER_EN_ERR_P6[30] - (RW) Enable Data operation error of port 6. +* Avoid unclear error flag, please clear flag when logic reset. +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_EN_ERR_P6_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_EN_ERR_P6_MASK \ +0x40000000 /* EN_DATA_OPER_EN_ERR_P6[30] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_EN_ERR_P6_SHFT 30 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P5_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P5_MASK \ +0x20000000 /* EN_DATA_OPER_ERR_P5[29] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P5_SHFT 29 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P4_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P4_MASK \ +0x10000000 /* EN_DATA_OPER_ERR_P4[28] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P4_SHFT 28 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P3_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P3_MASK \ +0x08000000 /* EN_DATA_OPER_ERR_P3[27] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P3_SHFT 27 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P2_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P2_MASK \ +0x04000000 /* EN_DATA_OPER_ERR_P2[26] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P2_SHFT 26 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P1_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P1_MASK \ +0x02000000 /* EN_DATA_OPER_ERR_P1[25] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P1_SHFT 25 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P0_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P0_MASK \ +0x01000000 /* EN_DATA_OPER_ERR_P0[24] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P0_SHFT 24 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P6_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P6_MASK \ +0x00400000 /* EN_QUEUE_OPER_ERR_P6[22] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P6_SHFT 22 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P5_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P5_MASK \ +0x00200000 /* EN_QUEUE_OPER_ERR_P5[21] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P5_SHFT 21 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P4_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P4_MASK \ +0x00100000 /* EN_QUEUE_OPER_ERR_P4[20] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P4_SHFT 20 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P3_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P3_MASK \ +0x00080000 /* EN_QUEUE_OPER_ERR_P3[19] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P3_SHFT 19 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P2_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P2_MASK \ +0x00040000 /* EN_QUEUE_OPER_ERR_P2[18] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P2_SHFT 18 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P1_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P1_MASK \ +0x00020000 /* EN_QUEUE_OPER_ERR_P1[17] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P1_SHFT 17 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P0_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P0_MASK \ +0x00010000 /* EN_QUEUE_OPER_ERR_P0[16] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P0_SHFT 16 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P6_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P6_MASK \ +0x00004000 /* EN_PAGE_UDF_P6[14] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P6_SHFT 14 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P5_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P5_MASK \ +0x00002000 /* EN_PAGE_UDF_P5[13] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P5_SHFT 13 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P4_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P4_MASK \ +0x00001000 /* EN_PAGE_UDF_P4[12] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P4_SHFT 12 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P3_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P3_MASK \ +0x00000800 /* EN_PAGE_UDF_P3[11] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P3_SHFT 11 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P2_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P2_MASK \ +0x00000400 /* EN_PAGE_UDF_P2[10] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P2_SHFT 10 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P1_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P1_MASK \ +0x00000200 /* EN_PAGE_UDF_P1[9] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P1_SHFT 9 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P0_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P0_MASK \ +0x00000100 /* EN_PAGE_UDF_P0[8] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P0_SHFT 8 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P6_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P6_MASK \ +0x00000040 /* EN_Q_CMD_ERR_P6[6] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P6_SHFT 6 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P5_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P5_MASK \ +0x00000020 /* EN_Q_CMD_ERR_P5[5] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P5_SHFT 5 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P4_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P4_MASK \ +0x00000010 /* EN_Q_CMD_ERR_P4[4] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P4_SHFT 4 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P3_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P3_MASK \ +0x00000008 /* EN_Q_CMD_ERR_P3[3] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P3_SHFT 3 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P2_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P2_MASK \ +0x00000004 /* EN_Q_CMD_ERR_P2[2] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P2_SHFT 2 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P1_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P1_MASK \ +0x00000002 /* EN_Q_CMD_ERR_P1[1] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P1_SHFT 1 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P0_ADDR \ +WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P0_MASK \ +0x00000001 /* EN_Q_CMD_ERR_P0[0] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P0_SHFT 0 + +/* +* ---INT_N9_ERR1_MASK (0x820C8000 + 0x28)--- +* EN_WDT_ERR_P0[0] - (RW) Enable Port state watch dog timeout +* error interrupt status of port 0. Avoid unclear error flag, please clear flag +* when logic reset. +* EN_WDT_ERR_P1[1] - (RW) Enable Port state watch dog timeout +* error interrupt status of port 1. Avoid unclear error flag, please clear flag +* when logic reset. +* EN_WDT_ERR_P2[2] - (RW) Enable Port state watch dog timeout +* error interrupt status of port 2. Avoid unclear error flag, please clear flag +* when logic reset. +* EN_WDT_ERR_P3[3] - (RW) Enable Port state watch dog timeout +* error interrupt status of port 3. Avoid unclear error flag, please clear flag +* when logic reset. +* EN_WDT_ERR_P4[4] - (RW) Enable Port state watch dog timeout +* error interrupt status of port 4. Avoid unclear error flag, please clear flag +* when logic reset. +* EN_WDT_ERR_P5[5] - (RW) Enable Port state watch dog timeout +* error interrupt status of port 5. Avoid unclear error flag, please clear flag +* when logic reset. +* EN_WDT_ERR_P6[6] - (RW) Enable Port state watch dog timeout +* error interrupt status of port 6. Avoid unclear error flag, please clear flag +* when logic reset. +* RESERVED7[7] - (RO) Reserved bits +* EN_FL_HANG_ERR[8] - (RW) Enable Frame link FSM hang error +* interrupt. Avoid unclear error flag, please clear flag when logic reset. +* PL_HANGEN__ERR[9] - (RW) Enable Page link FSM hang error +* interrupt. Avoid unclear error flag, please clear flag when logic reset. +* EN_DOUBLE_RLS_ERR[10] - (RW) Enable Double release error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_FREE_HEAD_TAIL_ERR[11] - (RW) Enable Free head/tail error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_FL_QSTRTUT_ERR[12] - (RW) Enable Frame Link queue NULL error +* interrupt. Avoid unclear error flag, please clear flag when logic reset. +* RESERVED13[31..13] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FL_QSTRTUT_ERR_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FL_QSTRTUT_ERR_MASK \ +0x00001000 /* EN_FL_QSTRTUT_ERR[12] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FL_QSTRTUT_ERR_SHFT 12 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FREE_HEAD_TAIL_ERR_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FREE_HEAD_TAIL_ERR_MASK \ +0x00000800 /* EN_FREE_HEAD_TAIL_ERR[11] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FREE_HEAD_TAIL_ERR_SHFT 11 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_DOUBLE_RLS_ERR_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_DOUBLE_RLS_ERR_MASK \ +0x00000400 /* EN_DOUBLE_RLS_ERR[10] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_DOUBLE_RLS_ERR_SHFT 10 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_PL_HANGEN__ERR_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_PL_HANGEN__ERR_MASK \ +0x00000200 /* PL_HANGEN__ERR[9] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_PL_HANGEN__ERR_SHFT 9 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FL_HANG_ERR_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FL_HANG_ERR_MASK \ +0x00000100 /* EN_FL_HANG_ERR[8] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FL_HANG_ERR_SHFT 8 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P6_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P6_MASK \ +0x00000040 /* EN_WDT_ERR_P6[6] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P6_SHFT 6 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P5_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P5_MASK \ +0x00000020 /* EN_WDT_ERR_P5[5] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P5_SHFT 5 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P4_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P4_MASK \ +0x00000010 /* EN_WDT_ERR_P4[4] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P4_SHFT 4 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P3_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P3_MASK \ +0x00000008 /* EN_WDT_ERR_P3[3] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P3_SHFT 3 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P2_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P2_MASK \ +0x00000004 /* EN_WDT_ERR_P2[2] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P2_SHFT 2 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P1_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P1_MASK \ +0x00000002 /* EN_WDT_ERR_P1[1] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P1_SHFT 1 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P0_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P0_MASK \ +0x00000001 /* EN_WDT_ERR_P0[0] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P0_SHFT 0 + +/* +* ---INT_N9_STS (0x820C8000 + 0x30)--- +* CPU_Q0_NE[0] - (W1C) CPU queue 0 not empty interrupt status +* CPU_Q1_NE[1] - (W1C) CPU queue 1 not empty interrupt status +* CPU_Q2_NE[2] - (W1C) CPU queue 2 not empty interrupt status +* CPU_Q3_NE[3] - (W1C) CPU queue 3 not empty interrupt status +* RESERVED4[11..4] - (RO) Reserved bits +* LMAC_ENQ[12] - (W1C) LMAC enq interrupt status +* ERROR_INT[13] - (RO) Error condition interrupt status +* ERROR_1_INT[14] - (RO) Error condition interrupt status +* RESERVED15[15] - (RO) Reserved bits +* DATA_TOGGLE[16] - (W1C) Data toggle of CR4 toggle register +(0xe0) +* LMAC_EMPTY_FALL[17] - (W1C) LMAC Buffer empty fall edge detect +* LMAC_EMPTY_RAISE[18] - (W1C) LMAC Buffer empty raise edge detect +* HIF_Q0_NE[19] - (W1C) HIF queue 0 not empty interrupt status +* HIF_Q1_NE[20] - (W1C) HIF queue 1 not empty interrupt status +* HIF_Q2_NE[21] - (W1C) HIF queue 2 not empty interrupt status +* HIF_Q3_NE[22] - (W1C) HIF queue 3 not empty interrupt status +* HIF_Q4_NE[23] - (W1C) HIF queue 4 not empty interrupt status +* HIF_Q5_NE[24] - (W1C) HIF queue 5 not empty interrupt status +* HIF_Q6_NE[25] - (W1C) HIF queue 6 not empty interrupt status +* HIF_Q7_NE[26] - (W1C) HIF queue 7 not empty interrupt status +* HIF_Q8_NE[27] - (W1C) HIF queue 8 not empty interrupt status +* HIF_Q9_NE[28] - (W1C) HIF queue 9 not empty interrupt status +* HIF_Q10_NE[29] - (W1C) HIF queue 10 not empty interrupt status +* HIF_Q11_NE[30] - (W1C) HIF queue 11 not empty interrupt status +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q11_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q11_NE_MASK 0x40000000 /* HIF_Q11_NE[30] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q11_NE_SHFT 30 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q10_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q10_NE_MASK 0x20000000 /* HIF_Q10_NE[29] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q10_NE_SHFT 29 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q9_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q9_NE_MASK 0x10000000 /* HIF_Q9_NE[28] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q9_NE_SHFT 28 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q8_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q8_NE_MASK 0x08000000 /* HIF_Q8_NE[27] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q8_NE_SHFT 27 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q7_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q7_NE_MASK 0x04000000 /* HIF_Q7_NE[26] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q7_NE_SHFT 26 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q6_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q6_NE_MASK 0x02000000 /* HIF_Q6_NE[25] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q6_NE_SHFT 25 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q5_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q5_NE_MASK 0x01000000 /* HIF_Q5_NE[24] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q5_NE_SHFT 24 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q4_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q4_NE_MASK 0x00800000 /* HIF_Q4_NE[23] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q4_NE_SHFT 23 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q3_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q3_NE_MASK 0x00400000 /* HIF_Q3_NE[22] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q3_NE_SHFT 22 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q2_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q2_NE_MASK 0x00200000 /* HIF_Q2_NE[21] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q2_NE_SHFT 21 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q1_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q1_NE_MASK 0x00100000 /* HIF_Q1_NE[20] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q1_NE_SHFT 20 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q0_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q0_NE_MASK 0x00080000 /* HIF_Q0_NE[19] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q0_NE_SHFT 19 +#define WF_PSE_TOP_INT_N9_STS_LMAC_EMPTY_RAISE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_LMAC_EMPTY_RAISE_MASK \ +0x00040000 /* LMAC_EMPTY_RAISE[18] */ +#define WF_PSE_TOP_INT_N9_STS_LMAC_EMPTY_RAISE_SHFT 18 +#define WF_PSE_TOP_INT_N9_STS_LMAC_EMPTY_FALL_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_LMAC_EMPTY_FALL_MASK \ +0x00020000 /* LMAC_EMPTY_FALL[17] */ +#define WF_PSE_TOP_INT_N9_STS_LMAC_EMPTY_FALL_SHFT 17 +#define WF_PSE_TOP_INT_N9_STS_DATA_TOGGLE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_DATA_TOGGLE_MASK 0x00010000 /* DATA_TOGGLE[16] */ +#define WF_PSE_TOP_INT_N9_STS_DATA_TOGGLE_SHFT 16 +#define WF_PSE_TOP_INT_N9_STS_ERROR_1_INT_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_ERROR_1_INT_MASK 0x00004000 /* ERROR_1_INT[14] */ +#define WF_PSE_TOP_INT_N9_STS_ERROR_1_INT_SHFT 14 +#define WF_PSE_TOP_INT_N9_STS_ERROR_INT_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_ERROR_INT_MASK 0x00002000 /* ERROR_INT[13] */ +#define WF_PSE_TOP_INT_N9_STS_ERROR_INT_SHFT 13 +#define WF_PSE_TOP_INT_N9_STS_LMAC_ENQ_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_LMAC_ENQ_MASK 0x00001000 /* LMAC_ENQ[12] */ +#define WF_PSE_TOP_INT_N9_STS_LMAC_ENQ_SHFT 12 +#define WF_PSE_TOP_INT_N9_STS_CPU_Q3_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_CPU_Q3_NE_MASK 0x00000008 /* CPU_Q3_NE[3] */ +#define WF_PSE_TOP_INT_N9_STS_CPU_Q3_NE_SHFT 3 +#define WF_PSE_TOP_INT_N9_STS_CPU_Q2_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_CPU_Q2_NE_MASK 0x00000004 /* CPU_Q2_NE[2] */ +#define WF_PSE_TOP_INT_N9_STS_CPU_Q2_NE_SHFT 2 +#define WF_PSE_TOP_INT_N9_STS_CPU_Q1_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_CPU_Q1_NE_MASK 0x00000002 /* CPU_Q1_NE[1] */ +#define WF_PSE_TOP_INT_N9_STS_CPU_Q1_NE_SHFT 1 +#define WF_PSE_TOP_INT_N9_STS_CPU_Q0_NE_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_CPU_Q0_NE_MASK 0x00000001 /* CPU_Q0_NE[0] */ +#define WF_PSE_TOP_INT_N9_STS_CPU_Q0_NE_SHFT 0 + +/* +* ---INT_N9_ERR_STS (0x820C8000 + 0x34)--- +* Q_CMD_ERR_P0[0] - (W1C) Queue command error interrupt status of +* port 0. Avoid unclear error flag, please clear flag when logic reset. +* Q_CMD_ERR_P1[1] - (W1C) Queue command error interrupt status of +* port 1. Avoid unclear error flag, please clear flag when logic reset. +* Q_CMD_ERR_P2[2] - (W1C) Queue command error interrupt status of +* port 2. Avoid unclear error flag, please clear flag when logic reset. +* Q_CMD_ERR_P3[3] - (W1C) Queue command error interrupt status of +* port 3. Avoid unclear error flag, please clear flag when logic reset. +* Q_CMD_ERR_P4[4] - (W1C) Queue command error interrupt status of +* port 4. Avoid unclear error flag, please clear flag when logic reset. +* Q_CMD_ERR_P5[5] - (W1C) Queue command error interrupt status of +* port 5. Avoid unclear error flag, please clear flag when logic reset. +* Q_CMD_ERR_P6[6] - (W1C) Queue command error interrupt status of +* port 6. Avoid unclear error flag, please clear flag when logic reset. +* RESERVED7[7] - (RO) Reserved bits +* PAGE_UDF_P0[8] - (W1C) Page underflow interrupt status of port +* 0. Avoid unclear error flag, please clear flag when logic reset. +* PAGE_UDF_P1[9] - (W1C) Page underflow interrupt status of port +* 1. Avoid unclear error flag, please clear flag when logic reset. +* PAGE_UDF_P2[10] - (W1C) Page underflow interrupt status of port +* 2. Avoid unclear error flag, please clear flag when logic reset. +* PAGE_UDF_P3[11] - (W1C) Page underflow interrupt status of port +* 3. Avoid unclear error flag, please clear flag when logic reset. +* PAGE_UDF_P4[12] - (W1C) Page underflow interrupt status of port +* 4. Avoid unclear error flag, please clear flag when logic reset. +* PAGE_UDF_P5[13] - (W1C) Page underflow interrupt status of port +* 5. Avoid unclear error flag, please clear flag when logic reset. +* PAGE_UDF_P6[14] - (W1C) Page underflow interrupt status of port +* 6. Avoid unclear error flag, please clear flag when logic reset. +* RESERVED15[15] - (RO) Reserved bits +* QUEUE_OPER_ERR_P0[16] - (W1C) Queue operation error of port 0. Avoid +* unclear error flag, please clear flag when logic reset. +* QUEUE_OPER_ERR_P1[17] - (W1C) Queue operation error of port 1. Avoid +* unclear error flag, please clear flag when logic reset. +* QUEUE_OPER_ERR_P2[18] - (W1C) Queue operation error of port 2. Avoid +* unclear error flag, please clear flag when logic reset. +* QUEUE_OPER_ERR_P3[19] - (W1C) Queue operation error of port 3. Avoid +* unclear error flag, please clear flag when logic reset. +* QUEUE_OPER_ERR_P4[20] - (W1C) Queue operation error of port 4. Avoid +* unclear error flag, please clear flag when logic reset. +* QUEUE_OPER_ERR_P5[21] - (W1C) Queue operation error of port 5. Avoid +* unclear error flag, please clear flag when logic reset. +* QUEUE_OPER_ERR_P6[22] - (W1C) Queue operation error of port 6. Avoid +* unclear error flag, please clear flag when logic reset. +* RESERVED23[23] - (RO) Reserved bits +* DATA_OPER_ERR_P0[24] - (W1C) Data operation error of port 0. Avoid +* unclear error flag, please clear flag when logic reset. +* DATA_OPER_ERR_P1[25] - (W1C) Data operation error of port 1. Avoid +* unclear error flag, please clear flag when logic reset. +* DATA_OPER_ERR_P2[26] - (W1C) Data operation error of port 2. Avoid +* unclear error flag, please clear flag when logic reset. +* DATA_OPER_ERR_P3[27] - (W1C) Data operation error of port 3. Avoid +* unclear error flag, please clear flag when logic reset. +* DATA_OPER_ERR_P4[28] - (W1C) Data operation error of port 4. Avoid +* unclear error flag, please clear flag when logic reset. +* DATA_OPER_ERR_P5[29] - (W1C) Data operation error of port 5. Avoid +* unclear error flag, please clear flag when logic reset. +* DATA_OPER_ERR_P6[30] - (W1C) Data operation error of port 6. Avoid +* unclear error flag, please clear flag when logic reset. +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P6_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P6_MASK \ +0x40000000 /* DATA_OPER_ERR_P6[30] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P6_SHFT 30 +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P5_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P5_MASK \ +0x20000000 /* DATA_OPER_ERR_P5[29] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P5_SHFT 29 +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P4_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P4_MASK \ +0x10000000 /* DATA_OPER_ERR_P4[28] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P4_SHFT 28 +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P3_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P3_MASK \ +0x08000000 /* DATA_OPER_ERR_P3[27] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P3_SHFT 27 +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P2_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P2_MASK \ +0x04000000 /* DATA_OPER_ERR_P2[26] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P2_SHFT 26 +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P1_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P1_MASK \ +0x02000000 /* DATA_OPER_ERR_P1[25] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P1_SHFT 25 +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P0_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P0_MASK \ +0x01000000 /* DATA_OPER_ERR_P0[24] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P0_SHFT 24 +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P6_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P6_MASK \ +0x00400000 /* QUEUE_OPER_ERR_P6[22] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P6_SHFT 22 +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P5_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P5_MASK \ +0x00200000 /* QUEUE_OPER_ERR_P5[21] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P5_SHFT 21 +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P4_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P4_MASK \ +0x00100000 /* QUEUE_OPER_ERR_P4[20] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P4_SHFT 20 +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P3_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P3_MASK \ +0x00080000 /* QUEUE_OPER_ERR_P3[19] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P3_SHFT 19 +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P2_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P2_MASK \ +0x00040000 /* QUEUE_OPER_ERR_P2[18] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P2_SHFT 18 +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P1_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P1_MASK \ +0x00020000 /* QUEUE_OPER_ERR_P1[17] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P1_SHFT 17 +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P0_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P0_MASK \ +0x00010000 /* QUEUE_OPER_ERR_P0[16] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P0_SHFT 16 +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P6_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P6_MASK \ + 0x00004000 /* PAGE_UDF_P6[14] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P6_SHFT 14 +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P5_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P5_MASK \ + 0x00002000 /* PAGE_UDF_P5[13] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P5_SHFT 13 +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P4_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P4_MASK \ + 0x00001000 /* PAGE_UDF_P4[12] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P4_SHFT 12 +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P3_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P3_MASK \ + 0x00000800 /* PAGE_UDF_P3[11] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P3_SHFT 11 +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P2_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P2_MASK \ + 0x00000400 /* PAGE_UDF_P2[10] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P2_SHFT 10 +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P1_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P1_MASK \ + 0x00000200 /* PAGE_UDF_P1[9] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P1_SHFT 9 +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P0_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P0_MASK \ + 0x00000100 /* PAGE_UDF_P0[8] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P0_SHFT 8 +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P6_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P6_MASK \ +0x00000040 /* Q_CMD_ERR_P6[6] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P6_SHFT 6 +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P5_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P5_MASK \ +0x00000020 /* Q_CMD_ERR_P5[5] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P5_SHFT 5 +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P4_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P4_MASK \ +0x00000010 /* Q_CMD_ERR_P4[4] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P4_SHFT 4 +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P3_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P3_MASK \ +0x00000008 /* Q_CMD_ERR_P3[3] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P3_SHFT 3 +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P2_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P2_MASK \ +0x00000004 /* Q_CMD_ERR_P2[2] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P2_SHFT 2 +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P1_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P1_MASK \ +0x00000002 /* Q_CMD_ERR_P1[1] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P1_SHFT 1 +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P0_ADDR \ +WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P0_MASK \ +0x00000001 /* Q_CMD_ERR_P0[0] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P0_SHFT 0 + +/* +* ---INT_N9_ERR1_STS (0x820C8000 + 0x38)--- +* WDT_ERR_P0[0] - (W1C) Port state watch dog timeout error +* interrupt status of port 0. Avoid unclear error flag, please clear flag when +* logic reset. +* WDT_ERR_P1[1] - (W1C) Port state watch dog timeout error +* interrupt status of port 1. Avoid unclear error flag, please clear flag when +* logic reset. +* WDT_ERR_P2[2] - (W1C) Port state watch dog timeout error +* interrupt status of port 2. Avoid unclear error flag, please clear flag when +* logic reset. +* WDT_ERR_P3[3] - (W1C) Port state watch dog timeout error +* interrupt status of port 3. Avoid unclear error flag, please clear flag when +* logic reset. +* WDT_ERR_P4[4] - (W1C) Port state watch dog timeout error +* interrupt status of port 4. Avoid unclear error flag, please clear flag when +* logic reset. +* WDT_ERR_P5[5] - (W1C) Port state watch dog timeout error +* interrupt status of port 5. Avoid unclear error flag, please clear flag when +* logic reset. +* WDT_ERR_P6[6] - (W1C) Port state watch dog timeout error +* interrupt status of port 6. Avoid unclear error flag, please clear flag when +* logic reset. +* RESERVED7[7] - (RO) Reserved bits +* FL_HANG_ERR[8] - (W1C) Frame link FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* PL_HANG_ERR[9] - (W1C) Page link FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* DOUBLE_RLS_ERR[10] - (W1C) Double release error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* FREE_HEAD_TAIL_ERR[11] - (W1C) Free head/tail error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* FL_QSTRUCT_ERR[12] - (W1C) Frame Link queue NULL error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* RESERVED13[31..13] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_INT_N9_ERR1_STS_FL_QSTRUCT_ERR_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_FL_QSTRUCT_ERR_MASK \ +0x00001000 /* FL_QSTRUCT_ERR[12] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_FL_QSTRUCT_ERR_SHFT 12 +#define WF_PSE_TOP_INT_N9_ERR1_STS_FREE_HEAD_TAIL_ERR_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_FREE_HEAD_TAIL_ERR_MASK \ +0x00000800 /* FREE_HEAD_TAIL_ERR[11] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_FREE_HEAD_TAIL_ERR_SHFT 11 +#define WF_PSE_TOP_INT_N9_ERR1_STS_DOUBLE_RLS_ERR_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_DOUBLE_RLS_ERR_MASK \ +0x00000400 /* DOUBLE_RLS_ERR[10] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_DOUBLE_RLS_ERR_SHFT 10 +#define WF_PSE_TOP_INT_N9_ERR1_STS_PL_HANG_ERR_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_PL_HANG_ERR_MASK \ + 0x00000200 /* PL_HANG_ERR[9] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_PL_HANG_ERR_SHFT 9 +#define WF_PSE_TOP_INT_N9_ERR1_STS_FL_HANG_ERR_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_FL_HANG_ERR_MASK \ + 0x00000100 /* FL_HANG_ERR[8] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_FL_HANG_ERR_SHFT 8 +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P6_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P6_MASK \ + 0x00000040 /* WDT_ERR_P6[6] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P6_SHFT 6 +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P5_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P5_MASK \ + 0x00000020 /* WDT_ERR_P5[5] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P5_SHFT 5 +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P4_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P4_MASK \ + 0x00000010 /* WDT_ERR_P4[4] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P4_SHFT 4 +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P3_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P3_MASK \ + 0x00000008 /* WDT_ERR_P3[3] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P3_SHFT 3 +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P2_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P2_MASK \ + 0x00000004 /* WDT_ERR_P2[2] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P2_SHFT 2 +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P1_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P1_MASK \ + 0x00000002 /* WDT_ERR_P1[1] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P1_SHFT 1 +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P0_ADDR \ +WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P0_MASK \ + 0x00000001 /* WDT_ERR_P0[0] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P0_SHFT 0 + +/* +* ---QUEUE_EMPTY (0x820C8000 + 0xB0)--- +* CPU_Q0_EMPTY[0] - (RO) CPU queue 0 empty status +* CPU_Q1_EMPTY[1] - (RO) CPU queue 1 empty status +* CPU_Q2_EMPTY[2] - (RO) CPU queue 2 empty status +* CPU_Q3_EMPTY[3] - (RO) CPU queue 3 empty status +* HIF_8_EMPTY[4] - (RO) HIF queue 8 empty status +* HIF_9_EMPTY[5] - (RO) HIF queue 9 empty status +* HIF_10_EMPTY[6] - (RO) HIF queue 10 empty status +* HIF_11_EMPTY[7] - (RO) HIF queue 11 empty status +* HIF_0_EMPTY[8] - (RO) HIF queue 0 empty status +* HIF_1_EMPTY[9] - (RO) HIF queue 1 empty status +* HIF_2_EMPTY[10] - (RO) HIF queue 2 empty status +* HIF_3_EMPTY[11] - (RO) HIF queue 3 empty status +* HIF_4_EMPTY[12] - (RO) HIF queue 4 empty status +* HIF_5_EMPTY[13] - (RO) HIF queue 5 empty status +* HIF_6_EMPTY[14] - (RO) HIF queue 6 empty status +* HIF_7_EMPTY[15] - (RO) HIF queue 7 empty status +* LMAC_TX_QUEUE_EMPTY[16] - (RO) LMAC TX queue empty status +* MDP_TX_QUEUE_EMPTY[17] - (RO) MDP TX queue empty status +* MDP_RX_QUEUE_EMPTY[18] - (RO) MDP RX queue empty status +* SEC_TX_QUEUE_EMPTY[19] - (RO) SEC TX queue empty status +* SEC_RX_QUEUE_EMPTY[20] - (RO) SEC RX queue empty status +* SFD_PARK_QUEUE_EMPTY[21] - (RO) SFD PARK queue empty status +* MDP_TXIOC_QUEUE_EMPTY[22] - (RO) MDP TXIOC queue empty status +* MDP_RXIOC_QUEUE_EMPTY[23] - (RO) MDP RXIOC queue empty status +* MDP_TX1_QUEUE_EMPTY[24] - (RO) MDP TX queue empty status for Band 1 +* SEC_TX1_QUEUE_EMPTY[25] - (RO) SEC TX queue empty status for Band 1 +* MDP_TXIOC1_QUEUE_EMPTY[26] - (RO) MDP TXIOC queue empty status for Band 1 +* MDP_RXIOC1_QUEUE_EMPTY[27] - (RO) MDP RXIOC queue empty status for Band 1 +* RESERVED28[30..28] - (RO) Reserved bits +* RLS_Q_EMTPY[31] - (RO) Release queue empty status +*/ +#define WF_PSE_TOP_QUEUE_EMPTY_RLS_Q_EMTPY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_RLS_Q_EMTPY_MASK 0x80000000 /* RLS_Q_EMTPY[31] */ +#define WF_PSE_TOP_QUEUE_EMPTY_RLS_Q_EMTPY_SHFT 31 +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC1_QUEUE_EMPTY_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC1_QUEUE_EMPTY_MASK \ +0x08000000 /* MDP_RXIOC1_QUEUE_EMPTY[27] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC1_QUEUE_EMPTY_SHFT 27 +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC1_QUEUE_EMPTY_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC1_QUEUE_EMPTY_MASK \ +0x04000000 /* MDP_TXIOC1_QUEUE_EMPTY[26] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC1_QUEUE_EMPTY_SHFT 26 +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_TX1_QUEUE_EMPTY_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_TX1_QUEUE_EMPTY_MASK \ +0x02000000 /* SEC_TX1_QUEUE_EMPTY[25] */ +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_TX1_QUEUE_EMPTY_SHFT 25 +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TX1_QUEUE_EMPTY_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TX1_QUEUE_EMPTY_MASK \ +0x01000000 /* MDP_TX1_QUEUE_EMPTY[24] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TX1_QUEUE_EMPTY_SHFT 24 +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC_QUEUE_EMPTY_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC_QUEUE_EMPTY_MASK \ +0x00800000 /* MDP_RXIOC_QUEUE_EMPTY[23] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC_QUEUE_EMPTY_SHFT 23 +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC_QUEUE_EMPTY_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC_QUEUE_EMPTY_MASK \ +0x00400000 /* MDP_TXIOC_QUEUE_EMPTY[22] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC_QUEUE_EMPTY_SHFT 22 +#define WF_PSE_TOP_QUEUE_EMPTY_SFD_PARK_QUEUE_EMPTY_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_SFD_PARK_QUEUE_EMPTY_MASK \ +0x00200000 /* SFD_PARK_QUEUE_EMPTY[21] */ +#define WF_PSE_TOP_QUEUE_EMPTY_SFD_PARK_QUEUE_EMPTY_SHFT 21 +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_RX_QUEUE_EMPTY_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_RX_QUEUE_EMPTY_MASK \ +0x00100000 /* SEC_RX_QUEUE_EMPTY[20] */ +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_RX_QUEUE_EMPTY_SHFT 20 +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_TX_QUEUE_EMPTY_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_TX_QUEUE_EMPTY_MASK \ +0x00080000 /* SEC_TX_QUEUE_EMPTY[19] */ +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_TX_QUEUE_EMPTY_SHFT 19 +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RX_QUEUE_EMPTY_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RX_QUEUE_EMPTY_MASK \ +0x00040000 /* MDP_RX_QUEUE_EMPTY[18] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RX_QUEUE_EMPTY_SHFT 18 +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TX_QUEUE_EMPTY_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TX_QUEUE_EMPTY_MASK \ +0x00020000 /* MDP_TX_QUEUE_EMPTY[17] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TX_QUEUE_EMPTY_SHFT 17 +#define WF_PSE_TOP_QUEUE_EMPTY_LMAC_TX_QUEUE_EMPTY_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_LMAC_TX_QUEUE_EMPTY_MASK \ +0x00010000 /* LMAC_TX_QUEUE_EMPTY[16] */ +#define WF_PSE_TOP_QUEUE_EMPTY_LMAC_TX_QUEUE_EMPTY_SHFT 16 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_7_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_7_EMPTY_MASK 0x00008000 /* HIF_7_EMPTY[15] */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_7_EMPTY_SHFT 15 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_6_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_6_EMPTY_MASK 0x00004000 /* HIF_6_EMPTY[14] */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_6_EMPTY_SHFT 14 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_5_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_5_EMPTY_MASK 0x00002000 /* HIF_5_EMPTY[13] */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_5_EMPTY_SHFT 13 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_4_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_4_EMPTY_MASK 0x00001000 /* HIF_4_EMPTY[12] */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_4_EMPTY_SHFT 12 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_3_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_3_EMPTY_MASK 0x00000800 /* HIF_3_EMPTY[11] */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_3_EMPTY_SHFT 11 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_2_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_2_EMPTY_MASK 0x00000400 /* HIF_2_EMPTY[10] */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_2_EMPTY_SHFT 10 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_1_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_1_EMPTY_MASK 0x00000200 /* HIF_1_EMPTY[9] */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_1_EMPTY_SHFT 9 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_0_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_0_EMPTY_MASK 0x00000100 /* HIF_0_EMPTY[8] */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_0_EMPTY_SHFT 8 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_11_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_11_EMPTY_MASK \ + 0x00000080 /* HIF_11_EMPTY[7] */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_11_EMPTY_SHFT 7 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_10_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_10_EMPTY_MASK \ + 0x00000040 /* HIF_10_EMPTY[6] */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_10_EMPTY_SHFT 6 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_9_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_9_EMPTY_MASK 0x00000020 /* HIF_9_EMPTY[5] */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_9_EMPTY_SHFT 5 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_8_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_8_EMPTY_MASK 0x00000010 /* HIF_8_EMPTY[4] */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_8_EMPTY_SHFT 4 +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q3_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q3_EMPTY_MASK \ + 0x00000008 /* CPU_Q3_EMPTY[3] */ +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q3_EMPTY_SHFT 3 +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q2_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q2_EMPTY_MASK \ + 0x00000004 /* CPU_Q2_EMPTY[2] */ +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q2_EMPTY_SHFT 2 +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q1_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q1_EMPTY_MASK \ + 0x00000002 /* CPU_Q1_EMPTY[1] */ +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q1_EMPTY_SHFT 1 +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q0_EMPTY_ADDR WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q0_EMPTY_MASK \ + 0x00000001 /* CPU_Q0_EMPTY[0] */ +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q0_EMPTY_SHFT 0 + +/* +* ---QUEUE_EMPTY_MASK (0x820C8000 + 0xB4)--- +* RESERVED0[7..0] - (RO) Reserved bits +* HIF_0_EMPTY_MASK[8] - (RW) Mask control of HIF queue 0 empty status +* HIF_1_EMPTY_MASK[9] - (RW) Mask control of HIF queue 1 empty status +* HIF_2_EMPTY_MASK[10] - (RW) Mask control of HIF queue 2 empty status +* HIF_3_EMPTY_MASK[11] - (RW) Mask control of HIF queue 3 empty status +* HIF_4_EMPTY_MASK[12] - (RW) Mask control of HIF queue 4 empty status +* HIF_5_EMPTY_MASK[13] - (RW) Mask control of HIF queue 5 empty status +* HIF_6_EMPTY_MASK[14] - (RW) Mask control of HIF queue 6 empty status +* HIF_7_EMPTY_MASK[15] - (RW) Mask control of HIF queue 7 empty status +* HIF_8_EMPTY_MASK[16] - (RW) Mask control of HIF queue 8 empty status +* HIF_9_EMPTY_MASK[17] - (RW) Mask control of HIF queue 9 empty status +* HIF_10_EMPTY_MASK[18] - (RW) Mask control of HIF queue 10 empty +status +* HIF_11_EMPTY_MASK[19] - (RW) Mask control of HIF queue 11 empty +status +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_11_EMPTY_MASK_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_11_EMPTY_MASK_MASK \ +0x00080000 /* HIF_11_EMPTY_MASK[19] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_11_EMPTY_MASK_SHFT 19 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_10_EMPTY_MASK_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_10_EMPTY_MASK_MASK \ +0x00040000 /* HIF_10_EMPTY_MASK[18] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_10_EMPTY_MASK_SHFT 18 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_9_EMPTY_MASK_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_9_EMPTY_MASK_MASK \ +0x00020000 /* HIF_9_EMPTY_MASK[17] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_9_EMPTY_MASK_SHFT 17 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_8_EMPTY_MASK_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_8_EMPTY_MASK_MASK \ +0x00010000 /* HIF_8_EMPTY_MASK[16] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_8_EMPTY_MASK_SHFT 16 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_7_EMPTY_MASK_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_7_EMPTY_MASK_MASK \ +0x00008000 /* HIF_7_EMPTY_MASK[15] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_7_EMPTY_MASK_SHFT 15 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_6_EMPTY_MASK_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_6_EMPTY_MASK_MASK \ +0x00004000 /* HIF_6_EMPTY_MASK[14] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_6_EMPTY_MASK_SHFT 14 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_5_EMPTY_MASK_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_5_EMPTY_MASK_MASK \ +0x00002000 /* HIF_5_EMPTY_MASK[13] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_5_EMPTY_MASK_SHFT 13 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_4_EMPTY_MASK_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_4_EMPTY_MASK_MASK \ +0x00001000 /* HIF_4_EMPTY_MASK[12] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_4_EMPTY_MASK_SHFT 12 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_3_EMPTY_MASK_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_3_EMPTY_MASK_MASK \ +0x00000800 /* HIF_3_EMPTY_MASK[11] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_3_EMPTY_MASK_SHFT 11 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_2_EMPTY_MASK_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_2_EMPTY_MASK_MASK \ +0x00000400 /* HIF_2_EMPTY_MASK[10] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_2_EMPTY_MASK_SHFT 10 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_1_EMPTY_MASK_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_1_EMPTY_MASK_MASK \ +0x00000200 /* HIF_1_EMPTY_MASK[9] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_1_EMPTY_MASK_SHFT 9 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_0_EMPTY_MASK_ADDR \ +WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_0_EMPTY_MASK_MASK \ +0x00000100 /* HIF_0_EMPTY_MASK[8] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_0_EMPTY_MASK_SHFT 8 + +/* +* ---PSE_LP_CTRL (0x820C8000 + 0xB8)--- +* RESERVED0[6..0] - (RO) Reserved bits +* PSE_LP_WAKEUP[7] - (RW) PSE Low Power Wakeup control +* PSE2HIF_PSSS_EN[8] - (RW) PSE Access HIF port control +* MCU_COALEASCE[9] - (RW) Coalease CPU ENQ and ENQ_DLY for HIF +port +* RESERVED10[31..10] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_LP_CTRL_MCU_COALEASCE_ADDR WF_PSE_TOP_PSE_LP_CTRL_ADDR +#define WF_PSE_TOP_PSE_LP_CTRL_MCU_COALEASCE_MASK \ + 0x00000200 /* MCU_COALEASCE[9] */ +#define WF_PSE_TOP_PSE_LP_CTRL_MCU_COALEASCE_SHFT 9 +#define WF_PSE_TOP_PSE_LP_CTRL_PSE2HIF_PSSS_EN_ADDR WF_PSE_TOP_PSE_LP_CTRL_ADDR +#define WF_PSE_TOP_PSE_LP_CTRL_PSE2HIF_PSSS_EN_MASK \ +0x00000100 /* PSE2HIF_PSSS_EN[8] */ +#define WF_PSE_TOP_PSE_LP_CTRL_PSE2HIF_PSSS_EN_SHFT 8 +#define WF_PSE_TOP_PSE_LP_CTRL_PSE_LP_WAKEUP_ADDR WF_PSE_TOP_PSE_LP_CTRL_ADDR +#define WF_PSE_TOP_PSE_LP_CTRL_PSE_LP_WAKEUP_MASK \ + 0x00000080 /* PSE_LP_WAKEUP[7] */ +#define WF_PSE_TOP_PSE_LP_CTRL_PSE_LP_WAKEUP_SHFT 7 + +/* +* ---TO_N9_INT (0x820C8000 + 0xF0)--- +* CR4_CMD[30..0] - (RW) Command for N9 +* TOGGLE[31] - (RW) When this bit is toggled, HW will send +* interrupt to N9. +*/ +#define WF_PSE_TOP_TO_N9_INT_TOGGLE_ADDR WF_PSE_TOP_TO_N9_INT_ADDR +#define WF_PSE_TOP_TO_N9_INT_TOGGLE_MASK 0x80000000 /* TOGGLE[31] */ +#define WF_PSE_TOP_TO_N9_INT_TOGGLE_SHFT 31 +#define WF_PSE_TOP_TO_N9_INT_CR4_CMD_ADDR WF_PSE_TOP_TO_N9_INT_ADDR +#define WF_PSE_TOP_TO_N9_INT_CR4_CMD_MASK 0x7FFFFFFF /* CR4_CMD[30..0] */ +#define WF_PSE_TOP_TO_N9_INT_CR4_CMD_SHFT 0 + +/* +* ---GROUP_REFILL_CTRL (0x820C8000 + 0x108)--- +* GROUP_REFILL_PRI[12..0] - (RW) group refill priority control +* RESERVED13[15..13] - (RO) Reserved bits +* DIS_GROUP_REFILL[28..16] - (RW) group quota refill enable control +* RESERVED29[31..29] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_GROUP_REFILL_CTRL_DIS_GROUP_REFILL_ADDR \ +WF_PSE_TOP_GROUP_REFILL_CTRL_ADDR +#define WF_PSE_TOP_GROUP_REFILL_CTRL_DIS_GROUP_REFILL_MASK \ +0x1FFF0000 /* DIS_GROUP_REFILL[28..16] */ +#define WF_PSE_TOP_GROUP_REFILL_CTRL_DIS_GROUP_REFILL_SHFT 16 +#define WF_PSE_TOP_GROUP_REFILL_CTRL_GROUP_REFILL_PRI_ADDR \ +WF_PSE_TOP_GROUP_REFILL_CTRL_ADDR +#define WF_PSE_TOP_GROUP_REFILL_CTRL_GROUP_REFILL_PRI_MASK \ +0x00001FFF /* GROUP_REFILL_PRI[12..0] */ +#define WF_PSE_TOP_GROUP_REFILL_CTRL_GROUP_REFILL_PRI_SHFT 0 + +/* +* ---FREEPG_START_END (0x820C8000 + 0x10C)--- +* FREEPG_START[11..0] - (RW) Start page setting of free pages +* RESERVED12[15..12] - (RO) Reserved bits +* FREEPG_END[27..16] - (RW) End page setting of free page +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_FREEPG_START_END_FREEPG_END_ADDR \ +WF_PSE_TOP_FREEPG_START_END_ADDR +#define WF_PSE_TOP_FREEPG_START_END_FREEPG_END_MASK \ +0x0FFF0000 /* FREEPG_END[27..16] */ +#define WF_PSE_TOP_FREEPG_START_END_FREEPG_END_SHFT 16 +#define WF_PSE_TOP_FREEPG_START_END_FREEPG_START_ADDR \ +WF_PSE_TOP_FREEPG_START_END_ADDR +#define WF_PSE_TOP_FREEPG_START_END_FREEPG_START_MASK \ +0x00000FFF /* FREEPG_START[11..0] */ +#define WF_PSE_TOP_FREEPG_START_END_FREEPG_START_SHFT 0 + +/* +* ---PG_HIF0_GROUP (0x820C8000 + 0x110)--- +* HIF0_MIN_QUOTA[11..0] - (RW) Min. quota of HIF 0 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* HIF0_MAX_QUOTA[27..16] - (RW) Max. quota of HIF 0 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MAX_QUOTA_ADDR \ +WF_PSE_TOP_PG_HIF0_GROUP_ADDR +#define WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MAX_QUOTA_MASK \ +0x0FFF0000 /* HIF0_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MIN_QUOTA_ADDR \ +WF_PSE_TOP_PG_HIF0_GROUP_ADDR +#define WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MIN_QUOTA_MASK \ +0x00000FFF /* HIF0_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MIN_QUOTA_SHFT 0 + +/* +* ---PG_HIF1_GROUP (0x820C8000 + 0x114)--- +* HIF1_MIN_QUOTA[11..0] - (RW) Min. quota of HIF 1 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* HIF1_MAX_QUOTA[27..16] - (RW) Max. quota of HIF 1 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_HIF1_GROUP_HIF1_MAX_QUOTA_ADDR \ +WF_PSE_TOP_PG_HIF1_GROUP_ADDR +#define WF_PSE_TOP_PG_HIF1_GROUP_HIF1_MAX_QUOTA_MASK \ +0x0FFF0000 /* HIF1_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_HIF1_GROUP_HIF1_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_HIF1_GROUP_HIF1_MIN_QUOTA_ADDR \ +WF_PSE_TOP_PG_HIF1_GROUP_ADDR +#define WF_PSE_TOP_PG_HIF1_GROUP_HIF1_MIN_QUOTA_MASK \ +0x00000FFF /* HIF1_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_HIF1_GROUP_HIF1_MIN_QUOTA_SHFT 0 + +/* +* ---PG_CPU_GROUP (0x820C8000 + 0x118)--- +* CPU_MIN_QUOTA[11..0] - (RW) Min. quota of CPU group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* CPU_MAX_QUOTA[27..16] - (RW) Max. quota of CPU group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_CPU_GROUP_CPU_MAX_QUOTA_ADDR WF_PSE_TOP_PG_CPU_GROUP_ADDR +#define WF_PSE_TOP_PG_CPU_GROUP_CPU_MAX_QUOTA_MASK \ +0x0FFF0000 /* CPU_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_CPU_GROUP_CPU_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_CPU_GROUP_CPU_MIN_QUOTA_ADDR WF_PSE_TOP_PG_CPU_GROUP_ADDR +#define WF_PSE_TOP_PG_CPU_GROUP_CPU_MIN_QUOTA_MASK \ +0x00000FFF /* CPU_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_CPU_GROUP_CPU_MIN_QUOTA_SHFT 0 + +/* +* ---PG_PLE_GROUP (0x820C8000 + 0x11C)--- +* PLE_MIN_QUOTA[11..0] - (RW) Min. quota of PLE group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* PLE_MAX_QUOTA[27..16] - (RW) Max. quota of PLE group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_PLE_GROUP_PLE_MAX_QUOTA_ADDR WF_PSE_TOP_PG_PLE_GROUP_ADDR +#define WF_PSE_TOP_PG_PLE_GROUP_PLE_MAX_QUOTA_MASK \ +0x0FFF0000 /* PLE_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_PLE_GROUP_PLE_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_PLE_GROUP_PLE_MIN_QUOTA_ADDR WF_PSE_TOP_PG_PLE_GROUP_ADDR +#define WF_PSE_TOP_PG_PLE_GROUP_PLE_MIN_QUOTA_MASK \ +0x00000FFF /* PLE_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_PLE_GROUP_PLE_MIN_QUOTA_SHFT 0 + +/* +* ---PG_PLE1_GROUP (0x820C8000 + 0x120)--- +* PLE_MIN_QUOTA[11..0] - (RW) Min. quota of PLE group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* PLE_MAX_QUOTA[27..16] - (RW) Max. quota of PLE group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_PLE1_GROUP_PLE_MAX_QUOTA_ADDR \ +WF_PSE_TOP_PG_PLE1_GROUP_ADDR +#define WF_PSE_TOP_PG_PLE1_GROUP_PLE_MAX_QUOTA_MASK \ +0x0FFF0000 /* PLE_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_PLE1_GROUP_PLE_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_PLE1_GROUP_PLE_MIN_QUOTA_ADDR \ +WF_PSE_TOP_PG_PLE1_GROUP_ADDR +#define WF_PSE_TOP_PG_PLE1_GROUP_PLE_MIN_QUOTA_MASK \ +0x00000FFF /* PLE_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_PLE1_GROUP_PLE_MIN_QUOTA_SHFT 0 + +/* +* ---PG_LMAC0_GROUP (0x820C8000 + 0x124)--- +* LMAC0_MIN_QUOTA[11..0] - (RW) Min. quota of LMAC 0 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* LMAC0_MAX_QUOTA[27..16] - (RW) Max. quota of LMAC 0 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_LMAC0_GROUP_LMAC0_MAX_QUOTA_ADDR \ +WF_PSE_TOP_PG_LMAC0_GROUP_ADDR +#define WF_PSE_TOP_PG_LMAC0_GROUP_LMAC0_MAX_QUOTA_MASK \ +0x0FFF0000 /* LMAC0_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_LMAC0_GROUP_LMAC0_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_LMAC0_GROUP_LMAC0_MIN_QUOTA_ADDR \ +WF_PSE_TOP_PG_LMAC0_GROUP_ADDR +#define WF_PSE_TOP_PG_LMAC0_GROUP_LMAC0_MIN_QUOTA_MASK \ +0x00000FFF /* LMAC0_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_LMAC0_GROUP_LMAC0_MIN_QUOTA_SHFT 0 + +/* +* ---PG_LMAC1_GROUP (0x820C8000 + 0x128)--- +* LMAC1_MIN_QUOTA[11..0] - (RW) Min. quota of LMAC 1 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* LMAC1_MAX_QUOTA[27..16] - (RW) Max. quota of LMAC 1 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_LMAC1_GROUP_LMAC1_MAX_QUOTA_ADDR \ +WF_PSE_TOP_PG_LMAC1_GROUP_ADDR +#define WF_PSE_TOP_PG_LMAC1_GROUP_LMAC1_MAX_QUOTA_MASK \ +0x0FFF0000 /* LMAC1_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_LMAC1_GROUP_LMAC1_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_LMAC1_GROUP_LMAC1_MIN_QUOTA_ADDR \ +WF_PSE_TOP_PG_LMAC1_GROUP_ADDR +#define WF_PSE_TOP_PG_LMAC1_GROUP_LMAC1_MIN_QUOTA_MASK \ +0x00000FFF /* LMAC1_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_LMAC1_GROUP_LMAC1_MIN_QUOTA_SHFT 0 + +/* +* ---PG_LMAC2_GROUP (0x820C8000 + 0x12C)--- +* LMAC2_MIN_QUOTA[11..0] - (RW) Min. quota of LMAC 2 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* LMAC2_MAX_QUOTA[27..16] - (RW) Max. quota of LMAC 2 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_LMAC2_GROUP_LMAC2_MAX_QUOTA_ADDR \ +WF_PSE_TOP_PG_LMAC2_GROUP_ADDR +#define WF_PSE_TOP_PG_LMAC2_GROUP_LMAC2_MAX_QUOTA_MASK \ +0x0FFF0000 /* LMAC2_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_LMAC2_GROUP_LMAC2_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_LMAC2_GROUP_LMAC2_MIN_QUOTA_ADDR \ +WF_PSE_TOP_PG_LMAC2_GROUP_ADDR +#define WF_PSE_TOP_PG_LMAC2_GROUP_LMAC2_MIN_QUOTA_MASK \ +0x00000FFF /* LMAC2_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_LMAC2_GROUP_LMAC2_MIN_QUOTA_SHFT 0 + +/* +* ---PG_LMAC3_GROUP (0x820C8000 + 0x130)--- +* LMAC3_MIN_QUOTA[11..0] - (RW) Min. quota of LMAC 3 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* LMAC3_MAX_QUOTA[27..16] - (RW) Max. quota of LMAC 3 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_LMAC3_GROUP_LMAC3_MAX_QUOTA_ADDR \ +WF_PSE_TOP_PG_LMAC3_GROUP_ADDR +#define WF_PSE_TOP_PG_LMAC3_GROUP_LMAC3_MAX_QUOTA_MASK \ +0x0FFF0000 /* LMAC3_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_LMAC3_GROUP_LMAC3_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_LMAC3_GROUP_LMAC3_MIN_QUOTA_ADDR \ +WF_PSE_TOP_PG_LMAC3_GROUP_ADDR +#define WF_PSE_TOP_PG_LMAC3_GROUP_LMAC3_MIN_QUOTA_MASK \ +0x00000FFF /* LMAC3_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_LMAC3_GROUP_LMAC3_MIN_QUOTA_SHFT 0 + +/* +* ---PG_MDP_GROUP (0x820C8000 + 0x134)--- +* MDP_MIN_QUOTA[11..0] - (RW) Min. quota of MDP group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* MDP_MAX_QUOTA[27..16] - (RW) Max. quota of MDP group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_MDP_GROUP_MDP_MAX_QUOTA_ADDR WF_PSE_TOP_PG_MDP_GROUP_ADDR +#define WF_PSE_TOP_PG_MDP_GROUP_MDP_MAX_QUOTA_MASK \ +0x0FFF0000 /* MDP_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_MDP_GROUP_MDP_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_MDP_GROUP_MDP_MIN_QUOTA_ADDR WF_PSE_TOP_PG_MDP_GROUP_ADDR +#define WF_PSE_TOP_PG_MDP_GROUP_MDP_MIN_QUOTA_MASK \ +0x00000FFF /* MDP_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_MDP_GROUP_MDP_MIN_QUOTA_SHFT 0 + +/* +* ---PG_MDP1_GROUP (0x820C8000 + 0x138)--- +* MDP1_MIN_QUOTA[11..0] - (RW) Min. quota of MDP1 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* MDP1_MAX_QUOTA[27..16] - (RW) Max. quota of MDP1 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_MDP1_GROUP_MDP1_MAX_QUOTA_ADDR \ +WF_PSE_TOP_PG_MDP1_GROUP_ADDR +#define WF_PSE_TOP_PG_MDP1_GROUP_MDP1_MAX_QUOTA_MASK \ +0x0FFF0000 /* MDP1_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_MDP1_GROUP_MDP1_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_MDP1_GROUP_MDP1_MIN_QUOTA_ADDR \ +WF_PSE_TOP_PG_MDP1_GROUP_ADDR +#define WF_PSE_TOP_PG_MDP1_GROUP_MDP1_MIN_QUOTA_MASK \ +0x00000FFF /* MDP1_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_MDP1_GROUP_MDP1_MIN_QUOTA_SHFT 0 + +/* +* ---PG_MDP2_GROUP (0x820C8000 + 0x13C)--- +* MDP2_MIN_QUOTA[11..0] - (RW) Min. quota of MDP2 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* MDP2_MAX_QUOTA[27..16] - (RW) Max. quota of MDP2 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_MDP2_GROUP_MDP2_MAX_QUOTA_ADDR \ +WF_PSE_TOP_PG_MDP2_GROUP_ADDR +#define WF_PSE_TOP_PG_MDP2_GROUP_MDP2_MAX_QUOTA_MASK \ +0x0FFF0000 /* MDP2_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_MDP2_GROUP_MDP2_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_MDP2_GROUP_MDP2_MIN_QUOTA_ADDR \ +WF_PSE_TOP_PG_MDP2_GROUP_ADDR +#define WF_PSE_TOP_PG_MDP2_GROUP_MDP2_MIN_QUOTA_MASK \ +0x00000FFF /* MDP2_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_MDP2_GROUP_MDP2_MIN_QUOTA_SHFT 0 + +/* +* ---PG_HIF2_GROUP (0x820C8000 + 0x140)--- +* HIF2_MIN_QUOTA[11..0] - (RW) Min. quota of HIF 2 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* HIF2_MAX_QUOTA[27..16] - (RW) Max. quota of HIF 2 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_HIF2_GROUP_HIF2_MAX_QUOTA_ADDR \ +WF_PSE_TOP_PG_HIF2_GROUP_ADDR +#define WF_PSE_TOP_PG_HIF2_GROUP_HIF2_MAX_QUOTA_MASK \ +0x0FFF0000 /* HIF2_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_HIF2_GROUP_HIF2_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_HIF2_GROUP_HIF2_MIN_QUOTA_ADDR \ +WF_PSE_TOP_PG_HIF2_GROUP_ADDR +#define WF_PSE_TOP_PG_HIF2_GROUP_HIF2_MIN_QUOTA_MASK \ +0x00000FFF /* HIF2_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_HIF2_GROUP_HIF2_MIN_QUOTA_SHFT 0 + +/* +* ---HIF0_PG_INFO (0x820C8000 + 0x150)--- +* HIF0_RSV_CNT[11..0] - (RO) Reserved pages of HIF 0 group +* RESERVED12[15..12] - (RO) Reserved bits +* HIF0_SRC_CNT[27..16] - (RO) Used pages of HIF 0 group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_HIF0_PG_INFO_HIF0_SRC_CNT_ADDR WF_PSE_TOP_HIF0_PG_INFO_ADDR +#define WF_PSE_TOP_HIF0_PG_INFO_HIF0_SRC_CNT_MASK \ +0x0FFF0000 /* HIF0_SRC_CNT[27..16] */ +#define WF_PSE_TOP_HIF0_PG_INFO_HIF0_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_HIF0_PG_INFO_HIF0_RSV_CNT_ADDR WF_PSE_TOP_HIF0_PG_INFO_ADDR +#define WF_PSE_TOP_HIF0_PG_INFO_HIF0_RSV_CNT_MASK \ +0x00000FFF /* HIF0_RSV_CNT[11..0] */ +#define WF_PSE_TOP_HIF0_PG_INFO_HIF0_RSV_CNT_SHFT 0 + +/* +* ---HIF1_PG_INFO (0x820C8000 + 0x154)--- +* HIF1_RSV_CNT[11..0] - (RO) Reserved pages of HIF 1 group +* RESERVED12[15..12] - (RO) Reserved bits +* HIF1_SRC_CNT[27..16] - (RO) Used pages of HIF 1 group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_HIF1_PG_INFO_HIF1_SRC_CNT_ADDR WF_PSE_TOP_HIF1_PG_INFO_ADDR +#define WF_PSE_TOP_HIF1_PG_INFO_HIF1_SRC_CNT_MASK \ +0x0FFF0000 /* HIF1_SRC_CNT[27..16] */ +#define WF_PSE_TOP_HIF1_PG_INFO_HIF1_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_HIF1_PG_INFO_HIF1_RSV_CNT_ADDR WF_PSE_TOP_HIF1_PG_INFO_ADDR +#define WF_PSE_TOP_HIF1_PG_INFO_HIF1_RSV_CNT_MASK \ +0x00000FFF /* HIF1_RSV_CNT[11..0] */ +#define WF_PSE_TOP_HIF1_PG_INFO_HIF1_RSV_CNT_SHFT 0 + +/* +* ---CPU_PG_INFO (0x820C8000 + 0x158)--- +* CPU_RSV_CNT[11..0] - (RO) Reserved pages of CPU group +* RESERVED12[15..12] - (RO) Reserved bits +* CPU_SRC_CNT[27..16] - (RO) Used pages of CPU group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_CPU_PG_INFO_CPU_SRC_CNT_ADDR WF_PSE_TOP_CPU_PG_INFO_ADDR +#define WF_PSE_TOP_CPU_PG_INFO_CPU_SRC_CNT_MASK \ +0x0FFF0000 /* CPU_SRC_CNT[27..16] */ +#define WF_PSE_TOP_CPU_PG_INFO_CPU_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_CPU_PG_INFO_CPU_RSV_CNT_ADDR WF_PSE_TOP_CPU_PG_INFO_ADDR +#define WF_PSE_TOP_CPU_PG_INFO_CPU_RSV_CNT_MASK \ + 0x00000FFF /* CPU_RSV_CNT[11..0] */ +#define WF_PSE_TOP_CPU_PG_INFO_CPU_RSV_CNT_SHFT 0 + +/* +* ---PLE_PG_INFO (0x820C8000 + 0x15C)--- +* PLE_RSV_CNT[11..0] - (RO) Reserved pages of PLE group +* RESERVED12[15..12] - (RO) Reserved bits +* PLE_SRC_CNT[27..16] - (RO) Used pages of PLE group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PLE_PG_INFO_PLE_SRC_CNT_ADDR WF_PSE_TOP_PLE_PG_INFO_ADDR +#define WF_PSE_TOP_PLE_PG_INFO_PLE_SRC_CNT_MASK \ +0x0FFF0000 /* PLE_SRC_CNT[27..16] */ +#define WF_PSE_TOP_PLE_PG_INFO_PLE_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_PLE_PG_INFO_PLE_RSV_CNT_ADDR WF_PSE_TOP_PLE_PG_INFO_ADDR +#define WF_PSE_TOP_PLE_PG_INFO_PLE_RSV_CNT_MASK \ + 0x00000FFF /* PLE_RSV_CNT[11..0] */ +#define WF_PSE_TOP_PLE_PG_INFO_PLE_RSV_CNT_SHFT 0 + +/* +* ---PLE1_PG_INFO (0x820C8000 + 0x160)--- +* PLE_RSV_CNT[11..0] - (RO) Reserved pages of PLE group +* RESERVED12[15..12] - (RO) Reserved bits +* PLE_SRC_CNT[27..16] - (RO) Used pages of PLE group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PLE1_PG_INFO_PLE_SRC_CNT_ADDR WF_PSE_TOP_PLE1_PG_INFO_ADDR +#define WF_PSE_TOP_PLE1_PG_INFO_PLE_SRC_CNT_MASK \ +0x0FFF0000 /* PLE_SRC_CNT[27..16] */ +#define WF_PSE_TOP_PLE1_PG_INFO_PLE_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_PLE1_PG_INFO_PLE_RSV_CNT_ADDR WF_PSE_TOP_PLE1_PG_INFO_ADDR +#define WF_PSE_TOP_PLE1_PG_INFO_PLE_RSV_CNT_MASK \ +0x00000FFF /* PLE_RSV_CNT[11..0] */ +#define WF_PSE_TOP_PLE1_PG_INFO_PLE_RSV_CNT_SHFT 0 + +/* +* ---LMAC0_PG_INFO (0x820C8000 + 0x164)--- +* LMAC0_RSV_CNT[11..0] - (RO) Reserved pages of LMAC 0 group +* RESERVED12[15..12] - (RO) Reserved bits +* LMAC0_SRC_CNT[27..16] - (RO) Used pages of LMAC 0 group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_LMAC0_PG_INFO_LMAC0_SRC_CNT_ADDR \ +WF_PSE_TOP_LMAC0_PG_INFO_ADDR +#define WF_PSE_TOP_LMAC0_PG_INFO_LMAC0_SRC_CNT_MASK \ +0x0FFF0000 /* LMAC0_SRC_CNT[27..16] */ +#define WF_PSE_TOP_LMAC0_PG_INFO_LMAC0_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_LMAC0_PG_INFO_LMAC0_RSV_CNT_ADDR \ +WF_PSE_TOP_LMAC0_PG_INFO_ADDR +#define WF_PSE_TOP_LMAC0_PG_INFO_LMAC0_RSV_CNT_MASK \ +0x00000FFF /* LMAC0_RSV_CNT[11..0] */ +#define WF_PSE_TOP_LMAC0_PG_INFO_LMAC0_RSV_CNT_SHFT 0 + +/* +* ---LMAC1_PG_INFO (0x820C8000 + 0x168)--- +* LMAC1_RSV_CNT[11..0] - (RO) Reserved pages of LMAC 1 group +* RESERVED12[15..12] - (RO) Reserved bits +* LMAC1_SRC_CNT[27..16] - (RO) Used pages of LMAC 1 group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_LMAC1_PG_INFO_LMAC1_SRC_CNT_ADDR \ +WF_PSE_TOP_LMAC1_PG_INFO_ADDR +#define WF_PSE_TOP_LMAC1_PG_INFO_LMAC1_SRC_CNT_MASK \ +0x0FFF0000 /* LMAC1_SRC_CNT[27..16] */ +#define WF_PSE_TOP_LMAC1_PG_INFO_LMAC1_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_LMAC1_PG_INFO_LMAC1_RSV_CNT_ADDR \ +WF_PSE_TOP_LMAC1_PG_INFO_ADDR +#define WF_PSE_TOP_LMAC1_PG_INFO_LMAC1_RSV_CNT_MASK \ +0x00000FFF /* LMAC1_RSV_CNT[11..0] */ +#define WF_PSE_TOP_LMAC1_PG_INFO_LMAC1_RSV_CNT_SHFT 0 + +/* +* ---LMAC2_PG_INFO (0x820C8000 + 0x16C)--- +* LMAC2_RSV_CNT[11..0] - (RO) Reserved pages of LMAC 2 group +* RESERVED12[15..12] - (RO) Reserved bits +* LMAC2_SRC_CNT[27..16] - (RO) Used pages of LMAC 2 group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_LMAC2_PG_INFO_LMAC2_SRC_CNT_ADDR \ +WF_PSE_TOP_LMAC2_PG_INFO_ADDR +#define WF_PSE_TOP_LMAC2_PG_INFO_LMAC2_SRC_CNT_MASK \ +0x0FFF0000 /* LMAC2_SRC_CNT[27..16] */ +#define WF_PSE_TOP_LMAC2_PG_INFO_LMAC2_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_LMAC2_PG_INFO_LMAC2_RSV_CNT_ADDR \ +WF_PSE_TOP_LMAC2_PG_INFO_ADDR +#define WF_PSE_TOP_LMAC2_PG_INFO_LMAC2_RSV_CNT_MASK \ +0x00000FFF /* LMAC2_RSV_CNT[11..0] */ +#define WF_PSE_TOP_LMAC2_PG_INFO_LMAC2_RSV_CNT_SHFT 0 + +/* +* ---LMAC3_PG_INFO (0x820C8000 + 0x170)--- +* LMAC3_RSV_CNT[11..0] - (RO) Reserved pages of LMAC 3 group +* RESERVED12[15..12] - (RO) Reserved bits +* LMAC3_SRC_CNT[27..16] - (RO) Used pages of LMAC 3 group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_LMAC3_PG_INFO_LMAC3_SRC_CNT_ADDR \ +WF_PSE_TOP_LMAC3_PG_INFO_ADDR +#define WF_PSE_TOP_LMAC3_PG_INFO_LMAC3_SRC_CNT_MASK \ +0x0FFF0000 /* LMAC3_SRC_CNT[27..16] */ +#define WF_PSE_TOP_LMAC3_PG_INFO_LMAC3_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_LMAC3_PG_INFO_LMAC3_RSV_CNT_ADDR \ +WF_PSE_TOP_LMAC3_PG_INFO_ADDR +#define WF_PSE_TOP_LMAC3_PG_INFO_LMAC3_RSV_CNT_MASK \ +0x00000FFF /* LMAC3_RSV_CNT[11..0] */ +#define WF_PSE_TOP_LMAC3_PG_INFO_LMAC3_RSV_CNT_SHFT 0 + +/* +* ---MDP_PG_INFO (0x820C8000 + 0x174)--- +* MDP_RSV_CNT[11..0] - (RO) Reserved pages of MDP group +* RESERVED12[15..12] - (RO) Reserved bits +* MDP_SRC_CNT[27..16] - (RO) Used pages of MDP group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_MDP_PG_INFO_MDP_SRC_CNT_ADDR WF_PSE_TOP_MDP_PG_INFO_ADDR +#define WF_PSE_TOP_MDP_PG_INFO_MDP_SRC_CNT_MASK \ +0x0FFF0000 /* MDP_SRC_CNT[27..16] */ +#define WF_PSE_TOP_MDP_PG_INFO_MDP_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_MDP_PG_INFO_MDP_RSV_CNT_ADDR WF_PSE_TOP_MDP_PG_INFO_ADDR +#define WF_PSE_TOP_MDP_PG_INFO_MDP_RSV_CNT_MASK \ + 0x00000FFF /* MDP_RSV_CNT[11..0] */ +#define WF_PSE_TOP_MDP_PG_INFO_MDP_RSV_CNT_SHFT 0 + +/* +* ---MDP1_PG_INFO (0x820C8000 + 0x178)--- +* MDP1_RSV_CNT[11..0] - (RO) Reserved pages of MDP 1 group +* RESERVED12[15..12] - (RO) Reserved bits +* MDP1_SRC_CNT[27..16] - (RO) Used pages of MDP 1 group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_MDP1_PG_INFO_MDP1_SRC_CNT_ADDR WF_PSE_TOP_MDP1_PG_INFO_ADDR +#define WF_PSE_TOP_MDP1_PG_INFO_MDP1_SRC_CNT_MASK \ +0x0FFF0000 /* MDP1_SRC_CNT[27..16] */ +#define WF_PSE_TOP_MDP1_PG_INFO_MDP1_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_MDP1_PG_INFO_MDP1_RSV_CNT_ADDR WF_PSE_TOP_MDP1_PG_INFO_ADDR +#define WF_PSE_TOP_MDP1_PG_INFO_MDP1_RSV_CNT_MASK \ +0x00000FFF /* MDP1_RSV_CNT[11..0] */ +#define WF_PSE_TOP_MDP1_PG_INFO_MDP1_RSV_CNT_SHFT 0 + +/* +* ---MDP2_PG_INFO (0x820C8000 + 0x17C)--- +* MDP2_RSV_CNT[11..0] - (RO) Reserved pages of MDP 2 group +* RESERVED12[15..12] - (RO) Reserved bits +* MDP2_SRC_CNT[27..16] - (RO) Used pages of MDP 2 group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_MDP2_PG_INFO_MDP2_SRC_CNT_ADDR WF_PSE_TOP_MDP2_PG_INFO_ADDR +#define WF_PSE_TOP_MDP2_PG_INFO_MDP2_SRC_CNT_MASK \ +0x0FFF0000 /* MDP2_SRC_CNT[27..16] */ +#define WF_PSE_TOP_MDP2_PG_INFO_MDP2_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_MDP2_PG_INFO_MDP2_RSV_CNT_ADDR WF_PSE_TOP_MDP2_PG_INFO_ADDR +#define WF_PSE_TOP_MDP2_PG_INFO_MDP2_RSV_CNT_MASK \ +0x00000FFF /* MDP2_RSV_CNT[11..0] */ +#define WF_PSE_TOP_MDP2_PG_INFO_MDP2_RSV_CNT_SHFT 0 + +/* +* ---HIF2_PG_INFO (0x820C8000 + 0x180)--- +* HIF2_RSV_CNT[11..0] - (RO) Reserved pages of HIF 2 group +* RESERVED12[15..12] - (RO) Reserved bits +* HIF2_SRC_CNT[27..16] - (RO) Used pages of HIF 2 group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_HIF2_PG_INFO_HIF2_SRC_CNT_ADDR WF_PSE_TOP_HIF2_PG_INFO_ADDR +#define WF_PSE_TOP_HIF2_PG_INFO_HIF2_SRC_CNT_MASK \ +0x0FFF0000 /* HIF2_SRC_CNT[27..16] */ +#define WF_PSE_TOP_HIF2_PG_INFO_HIF2_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_HIF2_PG_INFO_HIF2_RSV_CNT_ADDR WF_PSE_TOP_HIF2_PG_INFO_ADDR +#define WF_PSE_TOP_HIF2_PG_INFO_HIF2_RSV_CNT_MASK \ +0x00000FFF /* HIF2_RSV_CNT[11..0] */ +#define WF_PSE_TOP_HIF2_PG_INFO_HIF2_RSV_CNT_SHFT 0 + +/* +* ---DTIM_CTRL (0x820C8000 + 0x190)--- +* DTIM_MODE[0] - (RW) DTIM mode +* RESERVED1[31..1] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_DTIM_CTRL_DTIM_MODE_ADDR WF_PSE_TOP_DTIM_CTRL_ADDR +#define WF_PSE_TOP_DTIM_CTRL_DTIM_MODE_MASK 0x00000001 /* DTIM_MODE[0] */ +#define WF_PSE_TOP_DTIM_CTRL_DTIM_MODE_SHFT 0 + +/* +* ---FREEPG_START_END_DTIM (0x820C8000 + 0x194)--- +* FREEPG_START_DTIM[11..0] - (RW) Start page setting of DTIM free pages +* RESERVED12[15..12] - (RO) Reserved bits +* FREEPG_END_DTIM[27..16] - (RW) End page setting of DTIM free page +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_FREEPG_START_END_DTIM_FREEPG_END_DTIM_ADDR \ +WF_PSE_TOP_FREEPG_START_END_DTIM_ADDR +#define WF_PSE_TOP_FREEPG_START_END_DTIM_FREEPG_END_DTIM_MASK \ +0x0FFF0000 /* FREEPG_END_DTIM[27..16] */ +#define WF_PSE_TOP_FREEPG_START_END_DTIM_FREEPG_END_DTIM_SHFT 16 +#define WF_PSE_TOP_FREEPG_START_END_DTIM_FREEPG_START_DTIM_ADDR \ +WF_PSE_TOP_FREEPG_START_END_DTIM_ADDR +#define WF_PSE_TOP_FREEPG_START_END_DTIM_FREEPG_START_DTIM_MASK \ +0x00000FFF /* FREEPG_START_DTIM[11..0] */ +#define WF_PSE_TOP_FREEPG_START_END_DTIM_FREEPG_START_DTIM_SHFT 0 + +/* +* ---PG_LMAC0_GROUP_DTIM (0x820C8000 + 0x198)--- +* LMAC0_MIN_QUOTA_DTIM[11..0] - (RW) Min. quota of LMAC 0 group in DTIM +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* LMAC0_MAX_QUOTA_DTIM[27..16] - (RW) Max. quota of LMAC 0 group in DTIM +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_LMAC0_GROUP_DTIM_LMAC0_MAX_QUOTA_DTIM_ADDR \ +WF_PSE_TOP_PG_LMAC0_GROUP_DTIM_ADDR +#define WF_PSE_TOP_PG_LMAC0_GROUP_DTIM_LMAC0_MAX_QUOTA_DTIM_MASK \ +0x0FFF0000 /* LMAC0_MAX_QUOTA_DTIM[27..16] */ +#define WF_PSE_TOP_PG_LMAC0_GROUP_DTIM_LMAC0_MAX_QUOTA_DTIM_SHFT 16 +#define WF_PSE_TOP_PG_LMAC0_GROUP_DTIM_LMAC0_MIN_QUOTA_DTIM_ADDR \ +WF_PSE_TOP_PG_LMAC0_GROUP_DTIM_ADDR +#define WF_PSE_TOP_PG_LMAC0_GROUP_DTIM_LMAC0_MIN_QUOTA_DTIM_MASK \ +0x00000FFF /* LMAC0_MIN_QUOTA_DTIM[11..0] */ +#define WF_PSE_TOP_PG_LMAC0_GROUP_DTIM_LMAC0_MIN_QUOTA_DTIM_SHFT 0 + +/* +* ---PG_LMAC1_GROUP_DTIM (0x820C8000 + 0x19C)--- +* LMAC1_MIN_QUOTA_DTIM[11..0] - (RW) Min. quota of LMAC 1 group in DTIM +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* LMAC1_MAX_QUOTA_DTIM[27..16] - (RW) Max. quota of LMAC 1 group in DTIM +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_LMAC1_GROUP_DTIM_LMAC1_MAX_QUOTA_DTIM_ADDR \ +WF_PSE_TOP_PG_LMAC1_GROUP_DTIM_ADDR +#define WF_PSE_TOP_PG_LMAC1_GROUP_DTIM_LMAC1_MAX_QUOTA_DTIM_MASK \ +0x0FFF0000 /* LMAC1_MAX_QUOTA_DTIM[27..16] */ +#define WF_PSE_TOP_PG_LMAC1_GROUP_DTIM_LMAC1_MAX_QUOTA_DTIM_SHFT 16 +#define WF_PSE_TOP_PG_LMAC1_GROUP_DTIM_LMAC1_MIN_QUOTA_DTIM_ADDR \ +WF_PSE_TOP_PG_LMAC1_GROUP_DTIM_ADDR +#define WF_PSE_TOP_PG_LMAC1_GROUP_DTIM_LMAC1_MIN_QUOTA_DTIM_MASK \ +0x00000FFF /* LMAC1_MIN_QUOTA_DTIM[11..0] */ +#define WF_PSE_TOP_PG_LMAC1_GROUP_DTIM_LMAC1_MIN_QUOTA_DTIM_SHFT 0 + +/* +* ---PG_MDP_GROUP_DTIM (0x820C8000 + 0x1A0)--- +* MDP_MIN_QUOTA_DTIM[11..0] - (RW) Min. quota of MDP group in DTIM +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* MDP_MAX_QUOTA_DTIM[27..16] - (RW) Max. quota of MDP group in DTIM +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_MDP_GROUP_DTIM_MDP_MAX_QUOTA_DTIM_ADDR \ +WF_PSE_TOP_PG_MDP_GROUP_DTIM_ADDR +#define WF_PSE_TOP_PG_MDP_GROUP_DTIM_MDP_MAX_QUOTA_DTIM_MASK \ +0x0FFF0000 /* MDP_MAX_QUOTA_DTIM[27..16] */ +#define WF_PSE_TOP_PG_MDP_GROUP_DTIM_MDP_MAX_QUOTA_DTIM_SHFT 16 +#define WF_PSE_TOP_PG_MDP_GROUP_DTIM_MDP_MIN_QUOTA_DTIM_ADDR \ +WF_PSE_TOP_PG_MDP_GROUP_DTIM_ADDR +#define WF_PSE_TOP_PG_MDP_GROUP_DTIM_MDP_MIN_QUOTA_DTIM_MASK \ +0x00000FFF /* MDP_MIN_QUOTA_DTIM[11..0] */ +#define WF_PSE_TOP_PG_MDP_GROUP_DTIM_MDP_MIN_QUOTA_DTIM_SHFT 0 + +/* +* ---FL_QUE_CTRL_0 (0x820C8000 + 0x1B0)--- +* Q_BUF_WLANID[9..0] - (RW) Address of queue structure buffer +WLANID. +* Q_BUF_PID[11..10] - (RW) Address of queue structure buffer PID +* FL_BUFFER_ADDR[23..12] - (RW) Frame address of read previous +* frame/next frame +* Q_BUF_QID[30..24] - (RW) Address of queue structure buffer QID +* EXECUTE[31] - (A0) Executes frame link and queue structure +* buffer read command +*/ +#define WF_PSE_TOP_FL_QUE_CTRL_0_EXECUTE_ADDR WF_PSE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PSE_TOP_FL_QUE_CTRL_0_EXECUTE_SHFT 31 +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_ADDR WF_PSE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_MASK \ + 0x7F000000 /* Q_BUF_QID[30..24] */ +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_SHFT 24 +#define WF_PSE_TOP_FL_QUE_CTRL_0_FL_BUFFER_ADDR_ADDR \ +WF_PSE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_0_FL_BUFFER_ADDR_MASK \ +0x00FFF000 /* FL_BUFFER_ADDR[23..12] */ +#define WF_PSE_TOP_FL_QUE_CTRL_0_FL_BUFFER_ADDR_SHFT 12 +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_ADDR WF_PSE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_MASK \ + 0x00000C00 /* Q_BUF_PID[11..10] */ +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_SHFT 10 +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_WLANID_ADDR WF_PSE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_WLANID_MASK \ +0x000003FF /* Q_BUF_WLANID[9..0] */ +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_WLANID_SHFT 0 + +/* +* ---FL_QUE_CTRL_1 (0x820C8000 + 0x1B4)--- +* NEXT_FID[11..0] - (RO) Next frame ID of FL_BUFFER_ADDR +* RESERVED12[15..12] - (RO) Reserved bits +* PREV_FID[27..16] - (RO) Previous frame ID of FL_BUFFER_ADDR +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_FL_QUE_CTRL_1_PREV_FID_ADDR WF_PSE_TOP_FL_QUE_CTRL_1_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_1_PREV_FID_MASK 0x0FFF0000 /* PREV_FID[27..16] */ +#define WF_PSE_TOP_FL_QUE_CTRL_1_PREV_FID_SHFT 16 +#define WF_PSE_TOP_FL_QUE_CTRL_1_NEXT_FID_ADDR WF_PSE_TOP_FL_QUE_CTRL_1_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_1_NEXT_FID_MASK 0x00000FFF /* NEXT_FID[11..0] */ +#define WF_PSE_TOP_FL_QUE_CTRL_1_NEXT_FID_SHFT 0 + +/* +* ---FL_QUE_CTRL_2 (0x820C8000 + 0x1B8)--- +* QUEUE_HEAD_FID[11..0] - (RO) Head frame ID of quest queue setting in +0x01b0[15:0] +* RESERVED12[15..12] - (RO) Reserved bits +* QUEUE_TAIL_FID[27..16] - (RO) Tail frame ID of quest queue setting in +0x01b0[15:0] +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_ADDR \ +WF_PSE_TOP_FL_QUE_CTRL_2_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_MASK \ +0x0FFF0000 /* QUEUE_TAIL_FID[27..16] */ +#define WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_SHFT 16 +#define WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_ADDR \ +WF_PSE_TOP_FL_QUE_CTRL_2_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_MASK \ +0x00000FFF /* QUEUE_HEAD_FID[11..0] */ +#define WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_SHFT 0 + +/* +* ---FL_QUE_CTRL_3 (0x820C8000 + 0x1BC)--- +* QUEUE_PKT_NUM[11..0] - (RO) Total packet number of queue setting in +0x1b0[15:0] +* QUEUE_PAGE_NUM[23..12] - (RO) Total page number of queue setting in +0x1b0[15:0] +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_FL_QUE_CTRL_3_QUEUE_PAGE_NUM_ADDR \ +WF_PSE_TOP_FL_QUE_CTRL_3_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_3_QUEUE_PAGE_NUM_MASK \ +0x00FFF000 /* QUEUE_PAGE_NUM[23..12] */ +#define WF_PSE_TOP_FL_QUE_CTRL_3_QUEUE_PAGE_NUM_SHFT 12 +#define WF_PSE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_ADDR \ +WF_PSE_TOP_FL_QUE_CTRL_3_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_MASK \ +0x00000FFF /* QUEUE_PKT_NUM[11..0] */ +#define WF_PSE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_SHFT 0 + +/* +* ---PL_QUE_CTRL_0 (0x820C8000 + 0x1C0)--- +* NEXT_PAGE[11..0] - (RO) Next page of the PL_BUFFER_ADDR +* RESERVED12[15..12] - (RO) Reserved bits +* PL_BUFFER_ADDR[27..16] - (RW) Page address of read next page +* RESERVED28[30..28] - (RO) Reserved bits +* EXECUTE[31] - (A0) Executes page link buffer read command +*/ +#define WF_PSE_TOP_PL_QUE_CTRL_0_EXECUTE_ADDR WF_PSE_TOP_PL_QUE_CTRL_0_ADDR +#define WF_PSE_TOP_PL_QUE_CTRL_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PSE_TOP_PL_QUE_CTRL_0_EXECUTE_SHFT 31 +#define WF_PSE_TOP_PL_QUE_CTRL_0_PL_BUFFER_ADDR_ADDR \ +WF_PSE_TOP_PL_QUE_CTRL_0_ADDR +#define WF_PSE_TOP_PL_QUE_CTRL_0_PL_BUFFER_ADDR_MASK \ +0x0FFF0000 /* PL_BUFFER_ADDR[27..16] */ +#define WF_PSE_TOP_PL_QUE_CTRL_0_PL_BUFFER_ADDR_SHFT 16 +#define WF_PSE_TOP_PL_QUE_CTRL_0_NEXT_PAGE_ADDR WF_PSE_TOP_PL_QUE_CTRL_0_ADDR +#define WF_PSE_TOP_PL_QUE_CTRL_0_NEXT_PAGE_MASK \ + 0x00000FFF /* NEXT_PAGE[11..0] */ +#define WF_PSE_TOP_PL_QUE_CTRL_0_NEXT_PAGE_SHFT 0 + +/* +* ---PSE_CT_PRI_CTRL (0x820C8000 + 0x1EC)--- +* PSE_CT_PRI_LOW_LV[11..0] - (RW) Low trigger level of Group0 qouta +* RESERVED12[15..12] - (RO) Reserved bits +* PSE_CT_PRI_HI_LV[27..16] - (RW) High trigger level of Group0 qouta +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_CT_PRI_CTRL_PSE_CT_PRI_HI_LV_ADDR \ +WF_PSE_TOP_PSE_CT_PRI_CTRL_ADDR +#define WF_PSE_TOP_PSE_CT_PRI_CTRL_PSE_CT_PRI_HI_LV_MASK \ +0x0FFF0000 /* PSE_CT_PRI_HI_LV[27..16] */ +#define WF_PSE_TOP_PSE_CT_PRI_CTRL_PSE_CT_PRI_HI_LV_SHFT 16 +#define WF_PSE_TOP_PSE_CT_PRI_CTRL_PSE_CT_PRI_LOW_LV_ADDR \ +WF_PSE_TOP_PSE_CT_PRI_CTRL_ADDR +#define WF_PSE_TOP_PSE_CT_PRI_CTRL_PSE_CT_PRI_LOW_LV_MASK \ +0x00000FFF /* PSE_CT_PRI_LOW_LV[11..0] */ +#define WF_PSE_TOP_PSE_CT_PRI_CTRL_PSE_CT_PRI_LOW_LV_SHFT 0 + +/* +* ---PLE_ENQ_PKT_NUM (0x820C8000 + 0x1F0)--- +* PLE_ENQ_HIF_Q_PKT_NUM[15..0] - (RO) The packets numbers of PLE port enqueue +* to HIF queue. +* PLE_ENQ_HIF_Q_SEL[19..16] - (RW) Select HIF queue which is PLE port +* enqueue to. +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PLE_ENQ_PKT_NUM_PLE_ENQ_HIF_Q_SEL_ADDR \ +WF_PSE_TOP_PLE_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_PLE_ENQ_PKT_NUM_PLE_ENQ_HIF_Q_SEL_MASK \ +0x000F0000 /* PLE_ENQ_HIF_Q_SEL[19..16] */ +#define WF_PSE_TOP_PLE_ENQ_PKT_NUM_PLE_ENQ_HIF_Q_SEL_SHFT 16 +#define WF_PSE_TOP_PLE_ENQ_PKT_NUM_PLE_ENQ_HIF_Q_PKT_NUM_ADDR \ +WF_PSE_TOP_PLE_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_PLE_ENQ_PKT_NUM_PLE_ENQ_HIF_Q_PKT_NUM_MASK \ +0x0000FFFF /* PLE_ENQ_HIF_Q_PKT_NUM[15..0] */ +#define WF_PSE_TOP_PLE_ENQ_PKT_NUM_PLE_ENQ_HIF_Q_PKT_NUM_SHFT 0 + +/* +* ---CPU_ENQ_PKT_NUM (0x820C8000 + 0x1F4)--- +* CPU_ENQ_HIF_Q_PKT_NUM[15..0] - (RO) The packets numbers of CPU port enqueue +* to HIF queue. +* CPU_ENQ_HIF_Q_SEL[19..16] - (RW) Select HIF queue which is CPU port +* enqueue to. +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_HIF_Q_SEL_ADDR \ +WF_PSE_TOP_CPU_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_HIF_Q_SEL_MASK \ +0x000F0000 /* CPU_ENQ_HIF_Q_SEL[19..16] */ +#define WF_PSE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_HIF_Q_SEL_SHFT 16 +#define WF_PSE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_HIF_Q_PKT_NUM_ADDR \ +WF_PSE_TOP_CPU_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_HIF_Q_PKT_NUM_MASK \ +0x0000FFFF /* CPU_ENQ_HIF_Q_PKT_NUM[15..0] */ +#define WF_PSE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_HIF_Q_PKT_NUM_SHFT 0 + +/* +* ---LMAC_ENQ_PKT_NUM (0x820C8000 + 0x1F8)--- +* LMAC_ENQ_HIF_Q_PKT_NUM[15..0] - (RO) The packets numbers of LMAC port +* enqueue to HIF queue. +* LMAC_ENQ_HIF_Q_SEL[19..16] - (RW) Select HIF queue which is LMAC port +* enqueue to. +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_LMAC_ENQ_PKT_NUM_LMAC_ENQ_HIF_Q_SEL_ADDR \ +WF_PSE_TOP_LMAC_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_LMAC_ENQ_PKT_NUM_LMAC_ENQ_HIF_Q_SEL_MASK \ +0x000F0000 /* LMAC_ENQ_HIF_Q_SEL[19..16] */ +#define WF_PSE_TOP_LMAC_ENQ_PKT_NUM_LMAC_ENQ_HIF_Q_SEL_SHFT 16 +#define WF_PSE_TOP_LMAC_ENQ_PKT_NUM_LMAC_ENQ_HIF_Q_PKT_NUM_ADDR \ +WF_PSE_TOP_LMAC_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_LMAC_ENQ_PKT_NUM_LMAC_ENQ_HIF_Q_PKT_NUM_MASK \ +0x0000FFFF /* LMAC_ENQ_HIF_Q_PKT_NUM[15..0] */ +#define WF_PSE_TOP_LMAC_ENQ_PKT_NUM_LMAC_ENQ_HIF_Q_PKT_NUM_SHFT 0 + +/* +* ---HIF_ENQ_PKT_NUM (0x820C8000 + 0x1FC)--- +* HIF_ENQ_MDP[15..0] - (RO) The packets numbers of HIF port enqueue +* to MDP TX queue. +* HIF_ENQ_CPU[31..16] - (RO) The packets numbers of HIF port enqueue +* to CPU queue +*/ +#define WF_PSE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_CPU_ADDR \ +WF_PSE_TOP_HIF_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_CPU_MASK \ +0xFFFF0000 /* HIF_ENQ_CPU[31..16] */ +#define WF_PSE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_CPU_SHFT 16 +#define WF_PSE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_MDP_ADDR \ +WF_PSE_TOP_HIF_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_MDP_MASK \ +0x0000FFFF /* HIF_ENQ_MDP[15..0] */ +#define WF_PSE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_MDP_SHFT 0 + +/* +* ---MDP_ENQ_PKT_NUM (0x820C8000 + 0x200)--- +* MDP_ENQ_HIF_Q_PKT_NUM[15..0] - (RO) The packets numbers of MDP port enqueue +* to HIF queue. +* MDP_ENQ_HIF_Q_SEL[31..16] - (RW) Select HIF queue which is MDP port +* enqueue to. +*/ +#define WF_PSE_TOP_MDP_ENQ_PKT_NUM_MDP_ENQ_HIF_Q_SEL_ADDR \ +WF_PSE_TOP_MDP_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_MDP_ENQ_PKT_NUM_MDP_ENQ_HIF_Q_SEL_MASK \ +0xFFFF0000 /* MDP_ENQ_HIF_Q_SEL[31..16] */ +#define WF_PSE_TOP_MDP_ENQ_PKT_NUM_MDP_ENQ_HIF_Q_SEL_SHFT 16 +#define WF_PSE_TOP_MDP_ENQ_PKT_NUM_MDP_ENQ_HIF_Q_PKT_NUM_ADDR \ +WF_PSE_TOP_MDP_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_MDP_ENQ_PKT_NUM_MDP_ENQ_HIF_Q_PKT_NUM_MASK \ +0x0000FFFF /* MDP_ENQ_HIF_Q_PKT_NUM[15..0] */ +#define WF_PSE_TOP_MDP_ENQ_PKT_NUM_MDP_ENQ_HIF_Q_PKT_NUM_SHFT 0 + +/* +* ---RL_BUF_CTRL_0 (0x820C8000 + 0x210)--- +* RELAY_BUF_ADDR[11..0] - (RW) Read address of relay buffer +* RESERVED12[30..12] - (RO) Reserved bits +* EXECUTE[31] - (A0) Executes relay buffer read command +*/ +#define WF_PSE_TOP_RL_BUF_CTRL_0_EXECUTE_ADDR WF_PSE_TOP_RL_BUF_CTRL_0_ADDR +#define WF_PSE_TOP_RL_BUF_CTRL_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PSE_TOP_RL_BUF_CTRL_0_EXECUTE_SHFT 31 +#define WF_PSE_TOP_RL_BUF_CTRL_0_RELAY_BUF_ADDR_ADDR \ +WF_PSE_TOP_RL_BUF_CTRL_0_ADDR +#define WF_PSE_TOP_RL_BUF_CTRL_0_RELAY_BUF_ADDR_MASK \ +0x00000FFF /* RELAY_BUF_ADDR[11..0] */ +#define WF_PSE_TOP_RL_BUF_CTRL_0_RELAY_BUF_ADDR_SHFT 0 + +/* +* ---RL_BUF_CTRL_1 (0x820C8000 + 0x214)--- +* PAGE_NUM[8..0] - (RO) Page number of packet +* RESERVED9[13..9] - (RO) Reserved bits +* PKT_TAIL_PAGE[25..14] - (RO) Tail page of the packet with head page +* being the relay buffer address +* RESERVED26[26] - (RO) Reserved bits +* RESV_GRP_ID[30..27] - (RO) Group ID of reserved page used by FID +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_RL_BUF_CTRL_1_RESV_GRP_ID_ADDR WF_PSE_TOP_RL_BUF_CTRL_1_ADDR +#define WF_PSE_TOP_RL_BUF_CTRL_1_RESV_GRP_ID_MASK \ +0x78000000 /* RESV_GRP_ID[30..27] */ +#define WF_PSE_TOP_RL_BUF_CTRL_1_RESV_GRP_ID_SHFT 27 +#define WF_PSE_TOP_RL_BUF_CTRL_1_PKT_TAIL_PAGE_ADDR \ +WF_PSE_TOP_RL_BUF_CTRL_1_ADDR +#define WF_PSE_TOP_RL_BUF_CTRL_1_PKT_TAIL_PAGE_MASK \ +0x03FFC000 /* PKT_TAIL_PAGE[25..14] */ +#define WF_PSE_TOP_RL_BUF_CTRL_1_PKT_TAIL_PAGE_SHFT 14 +#define WF_PSE_TOP_RL_BUF_CTRL_1_PAGE_NUM_ADDR WF_PSE_TOP_RL_BUF_CTRL_1_ADDR +#define WF_PSE_TOP_RL_BUF_CTRL_1_PAGE_NUM_MASK 0x000001FF /* PAGE_NUM[8..0] */ +#define WF_PSE_TOP_RL_BUF_CTRL_1_PAGE_NUM_SHFT 0 + +/* +* ---TIMEOUT_CTRL (0x820C8000 + 0x244)--- +* FL_WD_TO_CTRL[7..0] - (RW) FL watch dog timeput +* RESERVED8[15..8] - (RO) Reserved bits +* APB_WD_TO_CTRL[23..16] - (RW) APB pready watch dog timeout control +register. +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_TIMEOUT_CTRL_APB_WD_TO_CTRL_ADDR WF_PSE_TOP_TIMEOUT_CTRL_ADDR +#define WF_PSE_TOP_TIMEOUT_CTRL_APB_WD_TO_CTRL_MASK \ +0x00FF0000 /* APB_WD_TO_CTRL[23..16] */ +#define WF_PSE_TOP_TIMEOUT_CTRL_APB_WD_TO_CTRL_SHFT 16 +#define WF_PSE_TOP_TIMEOUT_CTRL_FL_WD_TO_CTRL_ADDR WF_PSE_TOP_TIMEOUT_CTRL_ADDR +#define WF_PSE_TOP_TIMEOUT_CTRL_FL_WD_TO_CTRL_MASK \ +0x000000FF /* FL_WD_TO_CTRL[7..0] */ +#define WF_PSE_TOP_TIMEOUT_CTRL_FL_WD_TO_CTRL_SHFT 0 + +/* +* ---FSM_IDLE_WD_CTRL (0x820C8000 + 0x248)--- +* FL_IDLE_WD_TO_TH[7..0] - (RW) Watchdog timeout threshold for frame +* link FSM not returning to IDLE +* PL_IDLE_WD_TO_TH[15..8] - (RW) Watchdog timeout threshold for page link +* FSM not returning to IDLE +* PORT_IDLE_WD_TO_TH[23..16] - (RW) Watchdog timeout threshold for page link +* Port Link not returning to IDLE +* (Including HIF/CPU/LMAC port) +* MACTX_IDLE_WD_TO_TH[31..24] - (RW) Watchdog timeout threshold for port oper +* MACTX not returning to IDLE +*/ +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_MACTX_IDLE_WD_TO_TH_ADDR \ +WF_PSE_TOP_FSM_IDLE_WD_CTRL_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_MACTX_IDLE_WD_TO_TH_MASK \ +0xFF000000 /* MACTX_IDLE_WD_TO_TH[31..24] */ +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_MACTX_IDLE_WD_TO_TH_SHFT 24 +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_PORT_IDLE_WD_TO_TH_ADDR \ +WF_PSE_TOP_FSM_IDLE_WD_CTRL_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_PORT_IDLE_WD_TO_TH_MASK \ +0x00FF0000 /* PORT_IDLE_WD_TO_TH[23..16] */ +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_PORT_IDLE_WD_TO_TH_SHFT 16 +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_PL_IDLE_WD_TO_TH_ADDR \ +WF_PSE_TOP_FSM_IDLE_WD_CTRL_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_PL_IDLE_WD_TO_TH_MASK \ +0x0000FF00 /* PL_IDLE_WD_TO_TH[15..8] */ +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_PL_IDLE_WD_TO_TH_SHFT 8 +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_FL_IDLE_WD_TO_TH_ADDR \ +WF_PSE_TOP_FSM_IDLE_WD_CTRL_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_FL_IDLE_WD_TO_TH_MASK \ +0x000000FF /* FL_IDLE_WD_TO_TH[7..0] */ +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_FL_IDLE_WD_TO_TH_SHFT 0 + +/* +* ---FSM_IDLE_WD_EN (0x820C8000 + 0x24C)--- +* EN_HIF_PORT_IDLE_WD_TO[0] - (RW) Enables watchdog for HIF port oper FSM +* not returning to IDLE +* EN_CPU_PORT_IDLE_WD_TO[1] - (RW) Enables watchdog for CPU port oper FSM +* not returning to IDLE +* EN_LMAC_PORT_IDLE_WD_TO[2] - (RW) Enables watchdog for LMAC port oper FSM +* not returning to IDLE +* EN_MDP_IDLE_WD_TO[3] - (RW) Enables watchdog for MDP port oper FSM +* not returning to IDLE +* EN_SEC_IDLE_WD_TO[4] - (RW) Enables watchdog for SEC port oper FSM +* not returning to IDLE +* EN_PLE_IDLE_WD_TO[5] - (RW) Enables watchdog for PLE port oper FSM +* not returning to IDLE +* EN_AMSDU_IDLE_WD_TO[6] - (RW) Enables watchdog for AMSDU port oper FSM +* not returning to IDLE +* RESERVED7[7] - (RO) Reserved bits +* EN_FL_IDLE_WD_TO[8] - (RW) Enables watchdog for frame link FSM not +* returning to IDLE +* EN_PL_IDLE_WD_TO[9] - (RW) Enables watchdog for page link FSM not +* returning to IDLE +* RESERVED10[31..10] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_PL_IDLE_WD_TO_ADDR \ +WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_PL_IDLE_WD_TO_MASK \ +0x00000200 /* EN_PL_IDLE_WD_TO[9] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_PL_IDLE_WD_TO_SHFT 9 +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_FL_IDLE_WD_TO_ADDR \ +WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_FL_IDLE_WD_TO_MASK \ +0x00000100 /* EN_FL_IDLE_WD_TO[8] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_FL_IDLE_WD_TO_SHFT 8 +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_AMSDU_IDLE_WD_TO_ADDR \ +WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_AMSDU_IDLE_WD_TO_MASK \ +0x00000040 /* EN_AMSDU_IDLE_WD_TO[6] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_AMSDU_IDLE_WD_TO_SHFT 6 +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_PLE_IDLE_WD_TO_ADDR \ +WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_PLE_IDLE_WD_TO_MASK \ +0x00000020 /* EN_PLE_IDLE_WD_TO[5] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_PLE_IDLE_WD_TO_SHFT 5 +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_SEC_IDLE_WD_TO_ADDR \ +WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_SEC_IDLE_WD_TO_MASK \ +0x00000010 /* EN_SEC_IDLE_WD_TO[4] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_SEC_IDLE_WD_TO_SHFT 4 +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_MDP_IDLE_WD_TO_ADDR \ +WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_MDP_IDLE_WD_TO_MASK \ +0x00000008 /* EN_MDP_IDLE_WD_TO[3] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_MDP_IDLE_WD_TO_SHFT 3 +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_LMAC_PORT_IDLE_WD_TO_ADDR \ +WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_LMAC_PORT_IDLE_WD_TO_MASK \ +0x00000004 /* EN_LMAC_PORT_IDLE_WD_TO[2] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_LMAC_PORT_IDLE_WD_TO_SHFT 2 +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_CPU_PORT_IDLE_WD_TO_ADDR \ +WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_CPU_PORT_IDLE_WD_TO_MASK \ +0x00000002 /* EN_CPU_PORT_IDLE_WD_TO[1] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_CPU_PORT_IDLE_WD_TO_SHFT 1 +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_HIF_PORT_IDLE_WD_TO_ADDR \ +WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_HIF_PORT_IDLE_WD_TO_MASK \ +0x00000001 /* EN_HIF_PORT_IDLE_WD_TO[0] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_HIF_PORT_IDLE_WD_TO_SHFT 0 + +/* +* ---PSE_WFDMA_BUF_CTRL (0x820C8000 + 0x250)--- +* WFDMA_TXS_BUF_VLD_TH[7..0] - (RW) TXS valid reserved page count threshold +* WFDMA_TXCMD_BUF_VLD_TH[15..8] - (RW) TXCMD valid reserved page count +threshold +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_WFDMA_TXCMD_BUF_VLD_TH_ADDR \ +WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_ADDR +#define WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_WFDMA_TXCMD_BUF_VLD_TH_MASK \ +0x0000FF00 /* WFDMA_TXCMD_BUF_VLD_TH[15..8] */ +#define WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_WFDMA_TXCMD_BUF_VLD_TH_SHFT 8 +#define WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_WFDMA_TXS_BUF_VLD_TH_ADDR \ +WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_ADDR +#define WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_WFDMA_TXS_BUF_VLD_TH_MASK \ +0x000000FF /* WFDMA_TXS_BUF_VLD_TH[7..0] */ +#define WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_WFDMA_TXS_BUF_VLD_TH_SHFT 0 + +/* +* ---PSE_MODULE_CKG_DIS (0x820C8000 + 0x254)--- +* DIS_FL_DYN_CKG[0] - (RW) Disable control of PSE frame link module +* dynamic clock gating function +* DIS_PL_DYN_CKG[1] - (RW) Disable control of PSE page link module +* dynamic clock gating function +* DIS_CPU_PORT_DYN_CKG[2] - (RW) Disable control of PSE CPU port module +* dynamic clock gating function +* DIS_HIF_PORT_DYN_CKG[3] - (RW) Disable control of PSE HIF port module +* dynamic clock gating function +* DIS_WF_PLE_PORT_DYN_CKG[4] - (RW) Disable control of PSE LMAC and PLE port +* module dynamic clock gating function +* DIS_RLS_DYN_CKG[5] - (RW) Disable control of PSE release module +* dynamic clock gating function +* DIS_RL_DYN_CKG[6] - (RW) Disable control of PSE relay information +* module dynamic clock gating function +* RESERVED7[8..7] - (RO) Reserved bits +* DIS_CSR_DYN_CKG[9] - (RW) Disable control of PSE CR module dynamic +* clock gating function +* DIS_CPU_WRAP_DYN_CKG[10] - (RW) Disable control of PSE CPU_WRAP module +* dynamic clock gating function +* DIS_DBG_DYN_CKG[11] - (RW) Disable control of PSE debug module +* dynamic clock gating function +* DIS_MDP_DYN_CKG[12] - (RW) Disable control of PSE MDP module +* dynamic clock gating function +* DIS_SEC_DYN_CKG[13] - (RW) Disable control of PSE SEC module +* dynamic clock gating function +* RESERVED14[31..14] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_SEC_DYN_CKG_ADDR \ +WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_SEC_DYN_CKG_MASK \ +0x00002000 /* DIS_SEC_DYN_CKG[13] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_SEC_DYN_CKG_SHFT 13 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_MDP_DYN_CKG_ADDR \ +WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_MDP_DYN_CKG_MASK \ +0x00001000 /* DIS_MDP_DYN_CKG[12] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_MDP_DYN_CKG_SHFT 12 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_DBG_DYN_CKG_ADDR \ +WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_DBG_DYN_CKG_MASK \ +0x00000800 /* DIS_DBG_DYN_CKG[11] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_DBG_DYN_CKG_SHFT 11 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CPU_WRAP_DYN_CKG_ADDR \ +WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CPU_WRAP_DYN_CKG_MASK \ +0x00000400 /* DIS_CPU_WRAP_DYN_CKG[10] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CPU_WRAP_DYN_CKG_SHFT 10 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CSR_DYN_CKG_ADDR \ +WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CSR_DYN_CKG_MASK \ +0x00000200 /* DIS_CSR_DYN_CKG[9] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CSR_DYN_CKG_SHFT 9 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_RL_DYN_CKG_ADDR \ +WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_RL_DYN_CKG_MASK \ +0x00000040 /* DIS_RL_DYN_CKG[6] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_RL_DYN_CKG_SHFT 6 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_RLS_DYN_CKG_ADDR \ +WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_RLS_DYN_CKG_MASK \ +0x00000020 /* DIS_RLS_DYN_CKG[5] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_RLS_DYN_CKG_SHFT 5 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_WF_PLE_PORT_DYN_CKG_ADDR \ +WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_WF_PLE_PORT_DYN_CKG_MASK \ +0x00000010 /* DIS_WF_PLE_PORT_DYN_CKG[4] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_WF_PLE_PORT_DYN_CKG_SHFT 4 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_HIF_PORT_DYN_CKG_ADDR \ +WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_HIF_PORT_DYN_CKG_MASK \ +0x00000008 /* DIS_HIF_PORT_DYN_CKG[3] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_HIF_PORT_DYN_CKG_SHFT 3 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CPU_PORT_DYN_CKG_ADDR \ +WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CPU_PORT_DYN_CKG_MASK \ +0x00000004 /* DIS_CPU_PORT_DYN_CKG[2] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CPU_PORT_DYN_CKG_SHFT 2 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_PL_DYN_CKG_ADDR \ +WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_PL_DYN_CKG_MASK \ +0x00000002 /* DIS_PL_DYN_CKG[1] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_PL_DYN_CKG_SHFT 1 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_FL_DYN_CKG_ADDR \ +WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_FL_DYN_CKG_MASK \ +0x00000001 /* DIS_FL_DYN_CKG[0] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_FL_DYN_CKG_SHFT 0 + +/* +* ---PSE_MISC_FUNC_CTRL (0x820C8000 + 0x258)--- +* RESERVED0[7..0] - (RO) Reserved bits +* PSE_QUEUE_ACK_MODE[8] - (RW) Queue ACK mode control +* RESERVED9[29..9] - (RO) Reserved bits +* DIS_BYPASS_INVALID_FID[30] - (RW) Bypass invalid FID control +* DIS_BLOCK_MODE[31] - (RW) Block Mode Control +*/ +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_DIS_BLOCK_MODE_ADDR \ +WF_PSE_TOP_PSE_MISC_FUNC_CTRL_ADDR +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_DIS_BLOCK_MODE_MASK \ +0x80000000 /* DIS_BLOCK_MODE[31] */ +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_DIS_BLOCK_MODE_SHFT 31 +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_DIS_BYPASS_INVALID_FID_ADDR \ +WF_PSE_TOP_PSE_MISC_FUNC_CTRL_ADDR +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_DIS_BYPASS_INVALID_FID_MASK \ +0x40000000 /* DIS_BYPASS_INVALID_FID[30] */ +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_DIS_BYPASS_INVALID_FID_SHFT 30 +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_PSE_QUEUE_ACK_MODE_ADDR \ +WF_PSE_TOP_PSE_MISC_FUNC_CTRL_ADDR +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_PSE_QUEUE_ACK_MODE_MASK \ +0x00000100 /* PSE_QUEUE_ACK_MODE[8] */ +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_PSE_QUEUE_ACK_MODE_SHFT 8 + +/* +* ---PSE_INTER_ERR_FLAG (0x820C8000 + 0x280)--- +* DEQ_EMPTY_QUEUE[0] - (RO) DEQueue Empty Error Flag +* APB_WD_TO[1] - (RO) APB Write Data Timeout Error Flag +* FL_CTRL_WD_TO[2] - (RO) FL Write Data Timeout Error Flag +* RESERVED3[31..3] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_FL_CTRL_WD_TO_ADDR \ +WF_PSE_TOP_PSE_INTER_ERR_FLAG_ADDR +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_FL_CTRL_WD_TO_MASK \ +0x00000004 /* FL_CTRL_WD_TO[2] */ +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_FL_CTRL_WD_TO_SHFT 2 +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_APB_WD_TO_ADDR \ +WF_PSE_TOP_PSE_INTER_ERR_FLAG_ADDR +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_APB_WD_TO_MASK \ + 0x00000002 /* APB_WD_TO[1] */ +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_APB_WD_TO_SHFT 1 +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_DEQ_EMPTY_QUEUE_ADDR \ +WF_PSE_TOP_PSE_INTER_ERR_FLAG_ADDR +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_DEQ_EMPTY_QUEUE_MASK \ +0x00000001 /* DEQ_EMPTY_QUEUE[0] */ +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_DEQ_EMPTY_QUEUE_SHFT 0 + +/* +* ---PSE_SER_CTRL (0x820C8000 + 0x2A0)--- +* HIF_SER_PAUSE_ALLOCATE[0] - (RW) System Error Recover function for Pause +* HIFBuffer Allocation +* CPU_SER_PAUSE_ALLOCATE[1] - (RW) System Error Recover function for Pause +* CPU Buffer Allocation +* WF_SER_PAUSE_ALLOCATE[2] - (RW) System Error Recover function for Pause +* WF Buffer Allocation +* MDP_SER_PAUSE_ALLOCATE[3] - (RW) System Error Recover function for Pause +* MDP Buffer Allocation +* SEC_SER_PAUSE_ALLOCATE[4] - (RW) System Error Recover function for Pause +* SEC Buffer Allocation +* PLE_SER_PAUSE_ALLOCATE[5] - (RW) System Error Recover function for Pause +* PLE Buffer Allocation +* RESERVED6[7..6] - (RO) Reserved bits +* HIF_SER_PAUSE_DATA[8] - (RW) System Error Recover function for Pause +* HIF DATA opeartion. +* CPU_SER_PAUSE_DATA[9] - (RW) System Error Recover function for Pause +* CPU DATA opeartion. +* WF_SER_PAUSE_DATA[10] - (RW) System Error Recover function for Pause +* WF DATA opeartion. +* MDP_SER_PAUSE_DATA[11] - (RW) System Error Recover function for Pause +* MDP DATA opeartion. +* SEC_SER_PAUSE_DATA[12] - (RW) System Error Recover function for Pause +* SEC DATA opeartion. +* PLE_SER_PAUSE_DATA[13] - (RW) System Error Recover function for Pause +* PLE DATA opeartion. +* RESERVED14[15..14] - (RO) Reserved bits +* HIF_SER_PAUSE_QUEUE[16] - (RW) System Error Recover function for Pause +* HIF Queue opeartion. +* CPU_SER_PAUSE_QUEUE[17] - (RW) System Error Recover function for Pause +* CPU Queue opeartion. +* WF_SER_PAUSE_QUEUE[18] - (RW) System Error Recover function for Pause +* WF Queue opeartion. +* MDP_SER_PAUSE_QUEUE[19] - (RW) System Error Recover function for Pause +* MDP Queue opeartion. +* SEC_SER_PAUSE_QUEUE[20] - (RW) System Error Recover function for Pause +* SEC Queue opeartion. +* PLE_SER_PAUSE_QUEUE[21] - (RW) System Error Recover function for Pause +* PLE Queue opeartion. +* RESERVED22[31..22] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_QUEUE_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_QUEUE_MASK \ +0x00200000 /* PLE_SER_PAUSE_QUEUE[21] */ +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_QUEUE_SHFT 21 +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_QUEUE_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_QUEUE_MASK \ +0x00100000 /* SEC_SER_PAUSE_QUEUE[20] */ +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_QUEUE_SHFT 20 +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_QUEUE_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_QUEUE_MASK \ +0x00080000 /* MDP_SER_PAUSE_QUEUE[19] */ +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_QUEUE_SHFT 19 +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_QUEUE_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_QUEUE_MASK \ +0x00040000 /* WF_SER_PAUSE_QUEUE[18] */ +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_QUEUE_SHFT 18 +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_QUEUE_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_QUEUE_MASK \ +0x00020000 /* CPU_SER_PAUSE_QUEUE[17] */ +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_QUEUE_SHFT 17 +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_QUEUE_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_QUEUE_MASK \ +0x00010000 /* HIF_SER_PAUSE_QUEUE[16] */ +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_QUEUE_SHFT 16 +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_DATA_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_DATA_MASK \ +0x00002000 /* PLE_SER_PAUSE_DATA[13] */ +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_DATA_SHFT 13 +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_DATA_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_DATA_MASK \ +0x00001000 /* SEC_SER_PAUSE_DATA[12] */ +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_DATA_SHFT 12 +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_DATA_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_DATA_MASK \ +0x00000800 /* MDP_SER_PAUSE_DATA[11] */ +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_DATA_SHFT 11 +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_DATA_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_DATA_MASK \ +0x00000400 /* WF_SER_PAUSE_DATA[10] */ +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_DATA_SHFT 10 +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_DATA_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_DATA_MASK \ +0x00000200 /* CPU_SER_PAUSE_DATA[9] */ +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_DATA_SHFT 9 +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_DATA_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_DATA_MASK \ +0x00000100 /* HIF_SER_PAUSE_DATA[8] */ +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_DATA_SHFT 8 +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_ALLOCATE_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_ALLOCATE_MASK \ +0x00000020 /* PLE_SER_PAUSE_ALLOCATE[5] */ +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_ALLOCATE_SHFT 5 +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_ALLOCATE_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_ALLOCATE_MASK \ +0x00000010 /* SEC_SER_PAUSE_ALLOCATE[4] */ +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_ALLOCATE_SHFT 4 +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_ALLOCATE_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_ALLOCATE_MASK \ +0x00000008 /* MDP_SER_PAUSE_ALLOCATE[3] */ +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_ALLOCATE_SHFT 3 +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_ALLOCATE_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_ALLOCATE_MASK \ +0x00000004 /* WF_SER_PAUSE_ALLOCATE[2] */ +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_ALLOCATE_SHFT 2 +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_ALLOCATE_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_ALLOCATE_MASK \ +0x00000002 /* CPU_SER_PAUSE_ALLOCATE[1] */ +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_ALLOCATE_SHFT 1 +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_ALLOCATE_ADDR \ +WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_ALLOCATE_MASK \ +0x00000001 /* HIF_SER_PAUSE_ALLOCATE[0] */ +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_ALLOCATE_SHFT 0 + +/* +* ---PSE_MBIST_RP_FUSE (0x820C8000 + 0x2B0)--- +* WF_PSE_MBIST_RP_FAIL[3..0] - (RO) MBIST Repair FAIL report +* RESERVED4[7..4] - (RO) Reserved bits +* WF_PSE_MBIST_RP_OK[11..8] - (RO) MBIST Repair OK report +* RESERVED12[14..12] - (RO) Reserved bits +* REG_FUSE_SEL[15] - (RW) MBIST FUSE setting +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_REG_FUSE_SEL_ADDR \ +WF_PSE_TOP_PSE_MBIST_RP_FUSE_ADDR +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_REG_FUSE_SEL_MASK \ +0x00008000 /* REG_FUSE_SEL[15] */ +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_REG_FUSE_SEL_SHFT 15 +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_WF_PSE_MBIST_RP_OK_ADDR \ +WF_PSE_TOP_PSE_MBIST_RP_FUSE_ADDR +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_WF_PSE_MBIST_RP_OK_MASK \ +0x00000F00 /* WF_PSE_MBIST_RP_OK[11..8] */ +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_WF_PSE_MBIST_RP_OK_SHFT 8 +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_WF_PSE_MBIST_RP_FAIL_ADDR \ +WF_PSE_TOP_PSE_MBIST_RP_FUSE_ADDR +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_WF_PSE_MBIST_RP_FAIL_MASK \ +0x0000000F /* WF_PSE_MBIST_RP_FAIL[3..0] */ +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_WF_PSE_MBIST_RP_FAIL_SHFT 0 + +/* +* ---PSE_MBIST_RP_FUSE_1 (0x820C8000 + 0x2B4)--- +* WF_UMAC_TOP_MBIST_PREFUSE_0[15..0] - (RW) MBIST PRE-FUSE setting +* WF_UMAC_TOP_MBIST_PREFUSE_D_0[31..16] - (RO) MBIST PRE-FUSE result +*/ +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_WF_UMAC_TOP_MBIST_PREFUSE_D_0_ADDR \ +WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_ADDR +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_WF_UMAC_TOP_MBIST_PREFUSE_D_0_MASK \ +0xFFFF0000 /* WF_UMAC_TOP_MBIST_PREFUSE_D_0[31..16] */ +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_WF_UMAC_TOP_MBIST_PREFUSE_D_0_SHFT 16 +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_WF_UMAC_TOP_MBIST_PREFUSE_0_ADDR \ +WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_ADDR +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_WF_UMAC_TOP_MBIST_PREFUSE_0_MASK \ +0x0000FFFF /* WF_UMAC_TOP_MBIST_PREFUSE_0[15..0] */ +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_WF_UMAC_TOP_MBIST_PREFUSE_0_SHFT 0 + +/* +* ---PSE_MBIST_BSEL (0x820C8000 + 0x2B8)--- +* WF_PSE_MBIST_BSEL[15..0] - (RW) Memory MBIST BSEL control +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_MBIST_BSEL_WF_PSE_MBIST_BSEL_ADDR \ +WF_PSE_TOP_PSE_MBIST_BSEL_ADDR +#define WF_PSE_TOP_PSE_MBIST_BSEL_WF_PSE_MBIST_BSEL_MASK \ +0x0000FFFF /* WF_PSE_MBIST_BSEL[15..0] */ +#define WF_PSE_TOP_PSE_MBIST_BSEL_WF_PSE_MBIST_BSEL_SHFT 0 + +/* +* ---SRAM_MBIST_BACKGROUND (0x820C8000 + 0x2C0)--- +* MBIST_BACKGROUND[15..0] - (RW) Background setting for PSE SRAM MBIST +circuit +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_SRAM_MBIST_BACKGROUND_MBIST_BACKGROUND_ADDR \ +WF_PSE_TOP_SRAM_MBIST_BACKGROUND_ADDR +#define WF_PSE_TOP_SRAM_MBIST_BACKGROUND_MBIST_BACKGROUND_MASK \ +0x0000FFFF /* MBIST_BACKGROUND[15..0] */ +#define WF_PSE_TOP_SRAM_MBIST_BACKGROUND_MBIST_BACKGROUND_SHFT 0 + +/* +* ---SRAM_MBIST_DONE (0x820C8000 + 0x2C4)--- +* MBIST_DONE[0] - (RO) Working status of PSE SRAM MBIST circuit +* RESERVED1[31..1] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_SRAM_MBIST_DONE_MBIST_DONE_ADDR \ +WF_PSE_TOP_SRAM_MBIST_DONE_ADDR +#define WF_PSE_TOP_SRAM_MBIST_DONE_MBIST_DONE_MASK \ + 0x00000001 /* MBIST_DONE[0] */ +#define WF_PSE_TOP_SRAM_MBIST_DONE_MBIST_DONE_SHFT 0 + +/* +* ---SRAM_MBIST_FAIL (0x820C8000 + 0x2C8)--- +* FORDLINK_SRAM_MBIST_FAIL[0] - (RO) MBIST check result of forward link SRAM +* BACKLINK_SRAM_MBIST_FAIL[1] - (RO) MBIST check result of backward link SRAM +* PAGELINK_SRAM_MBIST_FAIL[2] - (RO) MBIST check result of PAGELINK SRAM +* RLINFO_SRAM_MBIST_FAIL[3] - (RO) MBIST check result of RLINFO SRAM +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_SRAM_MBIST_FAIL_RLINFO_SRAM_MBIST_FAIL_ADDR \ +WF_PSE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_FAIL_RLINFO_SRAM_MBIST_FAIL_MASK \ +0x00000008 /* RLINFO_SRAM_MBIST_FAIL[3] */ +#define WF_PSE_TOP_SRAM_MBIST_FAIL_RLINFO_SRAM_MBIST_FAIL_SHFT 3 +#define WF_PSE_TOP_SRAM_MBIST_FAIL_PAGELINK_SRAM_MBIST_FAIL_ADDR \ +WF_PSE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_FAIL_PAGELINK_SRAM_MBIST_FAIL_MASK \ +0x00000004 /* PAGELINK_SRAM_MBIST_FAIL[2] */ +#define WF_PSE_TOP_SRAM_MBIST_FAIL_PAGELINK_SRAM_MBIST_FAIL_SHFT 2 +#define WF_PSE_TOP_SRAM_MBIST_FAIL_BACKLINK_SRAM_MBIST_FAIL_ADDR \ +WF_PSE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_FAIL_BACKLINK_SRAM_MBIST_FAIL_MASK \ +0x00000002 /* BACKLINK_SRAM_MBIST_FAIL[1] */ +#define WF_PSE_TOP_SRAM_MBIST_FAIL_BACKLINK_SRAM_MBIST_FAIL_SHFT 1 +#define WF_PSE_TOP_SRAM_MBIST_FAIL_FORDLINK_SRAM_MBIST_FAIL_ADDR \ +WF_PSE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_FAIL_FORDLINK_SRAM_MBIST_FAIL_MASK \ +0x00000001 /* FORDLINK_SRAM_MBIST_FAIL[0] */ +#define WF_PSE_TOP_SRAM_MBIST_FAIL_FORDLINK_SRAM_MBIST_FAIL_SHFT 0 + +/* +* ---SRAM_MBIST_CTRL (0x820C8000 + 0x2D0)--- +* MBIST_MODE[0] - (RW) Control register for mbist_mode of MBIST +* RESERVED1[3..1] - (RO) Reserved bits +* MBIST_HOLDB[4] - (RW) Control register for mbist_holdb of +MBIST +* RESERVED5[7..5] - (RO) Reserved bits +* MBIST_DEBUG[8] - (RW) Control register for mbist_debug of +MBIST +* MBIST_RPRST_B[9] - (RW) MBIST Repair function Enable +* MBIST_USE_DEFAULT_DELSEL[10] - (RW) MBIST delay select control +* RESERVED11[15..11] - (RO) Reserved bits +* MBIST_DIAG_SEL[19..16] - (RW) Selection register for +mbist_diag_scan_out +* RESERVED20[23..20] - (RO) Reserved bits +* MBIST_SLEEP_TEST[24] - (RW) Control register for sleep_test of MBIST +* MBIST_SLEEP_INV[25] - (RW) Control register for sleep_inv of MBIST +* MBIST_SLEEP_W[26] - (RW) Control register for sleep_w of MBIST +* MBIST_SLEEP_R[27] - (RW) Control register for sleep_r of MBIST +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_R_ADDR \ +WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_R_MASK \ +0x08000000 /* MBIST_SLEEP_R[27] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_R_SHFT 27 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_W_ADDR \ +WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_W_MASK \ +0x04000000 /* MBIST_SLEEP_W[26] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_W_SHFT 26 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_INV_ADDR \ +WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_INV_MASK \ +0x02000000 /* MBIST_SLEEP_INV[25] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_INV_SHFT 25 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_TEST_ADDR \ +WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_TEST_MASK \ +0x01000000 /* MBIST_SLEEP_TEST[24] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_TEST_SHFT 24 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_DIAG_SEL_ADDR \ +WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_DIAG_SEL_MASK \ +0x000F0000 /* MBIST_DIAG_SEL[19..16] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_DIAG_SEL_SHFT 16 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_USE_DEFAULT_DELSEL_ADDR \ +WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_USE_DEFAULT_DELSEL_MASK \ +0x00000400 /* MBIST_USE_DEFAULT_DELSEL[10] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_USE_DEFAULT_DELSEL_SHFT 10 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_RPRST_B_ADDR \ +WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_RPRST_B_MASK \ +0x00000200 /* MBIST_RPRST_B[9] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_RPRST_B_SHFT 9 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_DEBUG_ADDR \ +WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_DEBUG_MASK \ + 0x00000100 /* MBIST_DEBUG[8] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_DEBUG_SHFT 8 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_HOLDB_ADDR \ +WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_HOLDB_MASK \ + 0x00000010 /* MBIST_HOLDB[4] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_HOLDB_SHFT 4 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_MODE_ADDR \ +WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_MODE_MASK \ + 0x00000001 /* MBIST_MODE[0] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_MODE_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL (0x820C8000 + 0x2D4)--- +* MBIST_DELSEL0_2[31..0] - (RW) Control register of delsel for PL SRAM +*/ +#define WF_PSE_TOP_SRAM_MBIST_DELSEL_MBIST_DELSEL0_2_ADDR \ +WF_PSE_TOP_SRAM_MBIST_DELSEL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_DELSEL_MBIST_DELSEL0_2_MASK \ +0xFFFFFFFF /* MBIST_DELSEL0_2[31..0] */ +#define WF_PSE_TOP_SRAM_MBIST_DELSEL_MBIST_DELSEL0_2_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL_1 (0x820C8000 + 0x2D8)--- +* MBIST_DELSEL3[31..0] - (RW) Control register of delsel for RLINFO +SRAM +*/ +#define WF_PSE_TOP_SRAM_MBIST_DELSEL_1_MBIST_DELSEL3_ADDR \ +WF_PSE_TOP_SRAM_MBIST_DELSEL_1_ADDR +#define WF_PSE_TOP_SRAM_MBIST_DELSEL_1_MBIST_DELSEL3_MASK \ +0xFFFFFFFF /* MBIST_DELSEL3[31..0] */ +#define WF_PSE_TOP_SRAM_MBIST_DELSEL_1_MBIST_DELSEL3_SHFT 0 + +/* +* ---SRAM_AWT_HDEN_CTRL (0x820C8000 + 0x2DC)--- +* FL_TBL_AWT1[0] - (RW) Memory AWT Control for FL_TBL1 +* FL_TBL_AWT2[1] - (RW) Memory AWT Control for FL_TBL2 +* PL_TBL_AWT[2] - (RW) Memory AWT Control for PL +* RLINFO_MEM_AWT[3] - (RW) Memory AWT Control for RL +* RESERVED4[15..4] - (RO) Reserved bits +* FL_TBL_HDEN1[16] - (RW) Memory HDEN Control for FL_TBL1 +* FL_TBL_HDEN2[17] - (RW) Memory HDEN Control for FL_TBL2 +* PL_TBL_HDEN[18] - (RW) Memory HDEN Control for PL +* RLINFO_MEM_HDEN[19] - (RW) Memory HDEN Control for RL +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_RLINFO_MEM_HDEN_ADDR \ +WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_RLINFO_MEM_HDEN_MASK \ +0x00080000 /* RLINFO_MEM_HDEN[19] */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_RLINFO_MEM_HDEN_SHFT 19 +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_PL_TBL_HDEN_ADDR \ +WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_PL_TBL_HDEN_MASK \ +0x00040000 /* PL_TBL_HDEN[18] */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_PL_TBL_HDEN_SHFT 18 +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_HDEN2_ADDR \ +WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_HDEN2_MASK \ +0x00020000 /* FL_TBL_HDEN2[17] */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_HDEN2_SHFT 17 +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_HDEN1_ADDR \ +WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_HDEN1_MASK \ +0x00010000 /* FL_TBL_HDEN1[16] */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_HDEN1_SHFT 16 +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_RLINFO_MEM_AWT_ADDR \ +WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_RLINFO_MEM_AWT_MASK \ +0x00000008 /* RLINFO_MEM_AWT[3] */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_RLINFO_MEM_AWT_SHFT 3 +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_PL_TBL_AWT_ADDR \ +WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_PL_TBL_AWT_MASK \ +0x00000004 /* PL_TBL_AWT[2] */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_PL_TBL_AWT_SHFT 2 +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_AWT2_ADDR \ +WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_AWT2_MASK \ +0x00000002 /* FL_TBL_AWT2[1] */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_AWT2_SHFT 1 +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_AWT1_ADDR \ +WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_AWT1_MASK \ +0x00000001 /* FL_TBL_AWT1[0] */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_AWT1_SHFT 0 + +/* +* ---C_GET_FID_0 (0x820C8000 + 0x310)--- +* QUEUE_FRAME_ID[15..0] - (RW) Frame ID for get command +* At GET_FRAME_TYPE = 2'h0/2'h1: +* QUEUE_FRAME_ID[15:14] = PID +* 2'h0: HIF port +* 2'h1: CPU port +* 2'h2: LMAC port +* QUEUE_FRAME_ID[9:0] = WLANID +* At GET_FRAME_TYPE = 2'h2/2'h3: +* QUEUE_FRAME_ID[11:0] = reference FID +* GET_FRAME_TYPE[19..16] - (RW) GET_SUB_TYPE +* RESERVED20[23..20] - (RO) Reserved bits +* GET_FRAME_QID[30..24] - (RW) Queue ID vlaue +* EXECUTE[31] - (A0) Executes command +*/ +#define WF_PSE_TOP_C_GET_FID_0_EXECUTE_ADDR WF_PSE_TOP_C_GET_FID_0_ADDR +#define WF_PSE_TOP_C_GET_FID_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PSE_TOP_C_GET_FID_0_EXECUTE_SHFT 31 +#define WF_PSE_TOP_C_GET_FID_0_GET_FRAME_QID_ADDR WF_PSE_TOP_C_GET_FID_0_ADDR +#define WF_PSE_TOP_C_GET_FID_0_GET_FRAME_QID_MASK \ +0x7F000000 /* GET_FRAME_QID[30..24] */ +#define WF_PSE_TOP_C_GET_FID_0_GET_FRAME_QID_SHFT 24 +#define WF_PSE_TOP_C_GET_FID_0_GET_FRAME_TYPE_ADDR WF_PSE_TOP_C_GET_FID_0_ADDR +#define WF_PSE_TOP_C_GET_FID_0_GET_FRAME_TYPE_MASK \ +0x000F0000 /* GET_FRAME_TYPE[19..16] */ +#define WF_PSE_TOP_C_GET_FID_0_GET_FRAME_TYPE_SHFT 16 +#define WF_PSE_TOP_C_GET_FID_0_QUEUE_FRAME_ID_ADDR WF_PSE_TOP_C_GET_FID_0_ADDR +#define WF_PSE_TOP_C_GET_FID_0_QUEUE_FRAME_ID_MASK \ +0x0000FFFF /* QUEUE_FRAME_ID[15..0] */ +#define WF_PSE_TOP_C_GET_FID_0_QUEUE_FRAME_ID_SHFT 0 + +/* +* ---C_GET_FID_1 (0x820C8000 + 0x314)--- +* GET_RETURN_FID[11..0] - (RO) Return frame ID +* RESERVED12[14..12] - (RO) Reserved bits +* END[15] - (RO) Return frame ID is end FID +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_C_GET_FID_1_END_ADDR WF_PSE_TOP_C_GET_FID_1_ADDR +#define WF_PSE_TOP_C_GET_FID_1_END_MASK 0x00008000 /* END[15] */ +#define WF_PSE_TOP_C_GET_FID_1_END_SHFT 15 +#define WF_PSE_TOP_C_GET_FID_1_GET_RETURN_FID_ADDR WF_PSE_TOP_C_GET_FID_1_ADDR +#define WF_PSE_TOP_C_GET_FID_1_GET_RETURN_FID_MASK \ +0x00000FFF /* GET_RETURN_FID[11..0] */ +#define WF_PSE_TOP_C_GET_FID_1_GET_RETURN_FID_SHFT 0 + +/* +* ---C_EN_QUEUE_0 (0x820C8000 + 0x320)--- +* DST_WLANID[9..0] - (RW) Destination WLANID for enqueue +* RESERVED10[13..10] - (RO) Reserved bits +* DST_PID[15..14] - (RW) Destination port ID for enqueue +* SUB_TYPE[19..16] - (RW) Sub-type of enqueue command +* RESERVED20[22..20] - (RO) Reserved bits +* DELAY_ENQ[23] - (RW) Delays enqueue +* DST_QID[30..24] - (RW) Destination queue ID for enqueue +* EXECUTE[31] - (A0) Executes command +*/ +#define WF_PSE_TOP_C_EN_QUEUE_0_EXECUTE_ADDR WF_PSE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PSE_TOP_C_EN_QUEUE_0_EXECUTE_SHFT 31 +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_QID_ADDR WF_PSE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_QID_MASK 0x7F000000 /* DST_QID[30..24] */ +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_QID_SHFT 24 +#define WF_PSE_TOP_C_EN_QUEUE_0_DELAY_ENQ_ADDR WF_PSE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_0_DELAY_ENQ_MASK 0x00800000 /* DELAY_ENQ[23] */ +#define WF_PSE_TOP_C_EN_QUEUE_0_DELAY_ENQ_SHFT 23 +#define WF_PSE_TOP_C_EN_QUEUE_0_SUB_TYPE_ADDR WF_PSE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_0_SUB_TYPE_MASK 0x000F0000 /* SUB_TYPE[19..16] */ +#define WF_PSE_TOP_C_EN_QUEUE_0_SUB_TYPE_SHFT 16 +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_PID_ADDR WF_PSE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_PID_MASK 0x0000C000 /* DST_PID[15..14] */ +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_PID_SHFT 14 +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_WLANID_ADDR WF_PSE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_WLANID_MASK \ + 0x000003FF /* DST_WLANID[9..0] */ +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_WLANID_SHFT 0 + +/* +* ---C_EN_QUEUE_1 (0x820C8000 + 0x324)--- +* CUR_LIST_FID_START[11..0] - (RW) Start frame ID of enqueue operation +* list, enqueue FID of enqueue operation +* RESERVED12[15..12] - (RO) Reserved bits +* CUR_LIST_FID_END[27..16] - (RW) End frame ID of enqueue operation list +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_END_ADDR \ +WF_PSE_TOP_C_EN_QUEUE_1_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_END_MASK \ +0x0FFF0000 /* CUR_LIST_FID_END[27..16] */ +#define WF_PSE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_END_SHFT 16 +#define WF_PSE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_START_ADDR \ +WF_PSE_TOP_C_EN_QUEUE_1_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_START_MASK \ +0x00000FFF /* CUR_LIST_FID_START[11..0] */ +#define WF_PSE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_START_SHFT 0 + +/* +* ---C_EN_QUEUE_2 (0x820C8000 + 0x328)--- +* TARGET_FID[11..0] - (RW) Target reference FID for enqueue +operation +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_C_EN_QUEUE_2_TARGET_FID_ADDR WF_PSE_TOP_C_EN_QUEUE_2_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_2_TARGET_FID_MASK \ + 0x00000FFF /* TARGET_FID[11..0] */ +#define WF_PSE_TOP_C_EN_QUEUE_2_TARGET_FID_SHFT 0 + +/* +* ---C_DE_QUEUE_0 (0x820C8000 + 0x330)--- +* SRC_WLANID[9..0] - (RW) Source WLAN ID for dequeue command +* RESERVED10[13..10] - (RO) Reserved bits +* SRC_PID[15..14] - (RW) Source port ID for dequeue command +* DEQ_SUB_TYPE[19..16] - (RW) Dequeue subtype of dequeue command +* ENQ_SUB_TYPE[22..20] - (RW) Enqueue subtype of enqueue command +* Only valid in Deq&Enq type. +* ENQ_VLD[23] - (RW) Deq&Enq command valid +* SRC_QID[30..24] - (RW) Source queue ID for dequeue command +* EXECUTE[31] - (A0) Executes dequeue command +*/ +#define WF_PSE_TOP_C_DE_QUEUE_0_EXECUTE_ADDR WF_PSE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PSE_TOP_C_DE_QUEUE_0_EXECUTE_SHFT 31 +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_QID_ADDR WF_PSE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_QID_MASK 0x7F000000 /* SRC_QID[30..24] */ +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_QID_SHFT 24 +#define WF_PSE_TOP_C_DE_QUEUE_0_ENQ_VLD_ADDR WF_PSE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_0_ENQ_VLD_MASK 0x00800000 /* ENQ_VLD[23] */ +#define WF_PSE_TOP_C_DE_QUEUE_0_ENQ_VLD_SHFT 23 +#define WF_PSE_TOP_C_DE_QUEUE_0_ENQ_SUB_TYPE_ADDR WF_PSE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_0_ENQ_SUB_TYPE_MASK \ +0x00700000 /* ENQ_SUB_TYPE[22..20] */ +#define WF_PSE_TOP_C_DE_QUEUE_0_ENQ_SUB_TYPE_SHFT 20 +#define WF_PSE_TOP_C_DE_QUEUE_0_DEQ_SUB_TYPE_ADDR WF_PSE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_0_DEQ_SUB_TYPE_MASK \ +0x000F0000 /* DEQ_SUB_TYPE[19..16] */ +#define WF_PSE_TOP_C_DE_QUEUE_0_DEQ_SUB_TYPE_SHFT 16 +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_PID_ADDR WF_PSE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_PID_MASK 0x0000C000 /* SRC_PID[15..14] */ +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_PID_SHFT 14 +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_WLANID_ADDR WF_PSE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_WLANID_MASK \ + 0x000003FF /* SRC_WLANID[9..0] */ +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_WLANID_SHFT 0 + +/* +* ---C_DE_QUEUE_1 (0x820C8000 + 0x334)--- +* CUR_LIST_FID_START[11..0] - (RW) Start frame ID of dequeue operation +* list, enqueue start FID of enqueue operation +* Only valid in Deq&Enq type. +* RESERVED12[15..12] - (RO) Reserved bits +* CUR_LIST_FID_END[27..16] - (RW) End framd ID of dequeue operation list, +* enqueue end FID of enqueue operation +* Only valid in Deq&Enq type. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_END_ADDR \ +WF_PSE_TOP_C_DE_QUEUE_1_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_END_MASK \ +0x0FFF0000 /* CUR_LIST_FID_END[27..16] */ +#define WF_PSE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_END_SHFT 16 +#define WF_PSE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_START_ADDR \ +WF_PSE_TOP_C_DE_QUEUE_1_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_START_MASK \ +0x00000FFF /* CUR_LIST_FID_START[11..0] */ +#define WF_PSE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_START_SHFT 0 + +/* +* ---C_DE_QUEUE_2 (0x820C8000 + 0x338)--- +* DEQ_ENQ_DST_WLANID[9..0] - (RW) Destination WLAN ID for enqueue command +* Only valid in Deq&Enq type. +* RESERVED10[13..10] - (RO) Reserved bits +* DEQ_ENQ_DST_PID[15..14] - (RW) Destination port ID for dequeue command +* RESERVED16[23..16] - (RO) Reserved bits +* DEQ_ENQ_DST_QID[30..24] - (RW) Destination queue ID for enqueue command +* Only valid in Deq&Enq type. +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_QID_ADDR \ +WF_PSE_TOP_C_DE_QUEUE_2_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_QID_MASK \ +0x7F000000 /* DEQ_ENQ_DST_QID[30..24] */ +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_QID_SHFT 24 +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_PID_ADDR \ +WF_PSE_TOP_C_DE_QUEUE_2_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_PID_MASK \ +0x0000C000 /* DEQ_ENQ_DST_PID[15..14] */ +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_PID_SHFT 14 +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_WLANID_ADDR \ +WF_PSE_TOP_C_DE_QUEUE_2_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_WLANID_MASK \ +0x000003FF /* DEQ_ENQ_DST_WLANID[9..0] */ +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_WLANID_SHFT 0 + +/* +* ---C_DE_QUEUE_3 (0x820C8000 + 0x33C)--- +* DEQ_HEAD_FDI[11..0] - (RO) Head FID got from dequeue command +* RESERVED12[14..12] - (RO) Reserved bits +* DEQ_EMPTY[15] - (RO) Queue empty after dequeue command is +executed +* DEQ_TAIL_FID[27..16] - (RO) Last FID got from dequeue command +* RESERVED28[30..28] - (RO) Reserved bits +* BUSY[31] - (RO) Dequeue execute busy +*/ +#define WF_PSE_TOP_C_DE_QUEUE_3_BUSY_ADDR WF_PSE_TOP_C_DE_QUEUE_3_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_3_BUSY_MASK 0x80000000 /* BUSY[31] */ +#define WF_PSE_TOP_C_DE_QUEUE_3_BUSY_SHFT 31 +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_TAIL_FID_ADDR WF_PSE_TOP_C_DE_QUEUE_3_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_TAIL_FID_MASK \ +0x0FFF0000 /* DEQ_TAIL_FID[27..16] */ +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_TAIL_FID_SHFT 16 +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_EMPTY_ADDR WF_PSE_TOP_C_DE_QUEUE_3_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_EMPTY_MASK 0x00008000 /* DEQ_EMPTY[15] */ +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_EMPTY_SHFT 15 +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_HEAD_FDI_ADDR WF_PSE_TOP_C_DE_QUEUE_3_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_HEAD_FDI_MASK \ +0x00000FFF /* DEQ_HEAD_FDI[11..0] */ +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_HEAD_FDI_SHFT 0 + +/* +* ---C_DE_QUEUE_4 (0x820C8000 + 0x340)--- +* DEQ_ENQ_REF_FID[11..0] - (RW) Reference frame ID for enqueue command +* Only valid in Deq&Enq type. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_C_DE_QUEUE_4_DEQ_ENQ_REF_FID_ADDR \ +WF_PSE_TOP_C_DE_QUEUE_4_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_4_DEQ_ENQ_REF_FID_MASK \ +0x00000FFF /* DEQ_ENQ_REF_FID[11..0] */ +#define WF_PSE_TOP_C_DE_QUEUE_4_DEQ_ENQ_REF_FID_SHFT 0 + +/* +* ---ALLOCATE_0 (0x820C8000 + 0x350)--- +* ALLOCATE_FRAME_LENGTH[13..0] - (RW) Allocate frame length +* Unit: DW (4 bytes) +* RESERVED14[15..14] - (RO) Reserved bits +* ALLOCATE_QID[20..16] - (RW) QID used for allocate buffer +* RESERVED21[30..21] - (RO) Reserved bits +* EXECUTE[31] - (A0) Executes allocate buffer command +*/ +#define WF_PSE_TOP_ALLOCATE_0_EXECUTE_ADDR WF_PSE_TOP_ALLOCATE_0_ADDR +#define WF_PSE_TOP_ALLOCATE_0_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PSE_TOP_ALLOCATE_0_EXECUTE_SHFT 31 +#define WF_PSE_TOP_ALLOCATE_0_ALLOCATE_QID_ADDR WF_PSE_TOP_ALLOCATE_0_ADDR +#define WF_PSE_TOP_ALLOCATE_0_ALLOCATE_QID_MASK \ +0x001F0000 /* ALLOCATE_QID[20..16] */ +#define WF_PSE_TOP_ALLOCATE_0_ALLOCATE_QID_SHFT 16 +#define WF_PSE_TOP_ALLOCATE_0_ALLOCATE_FRAME_LENGTH_ADDR \ +WF_PSE_TOP_ALLOCATE_0_ADDR +#define WF_PSE_TOP_ALLOCATE_0_ALLOCATE_FRAME_LENGTH_MASK \ +0x00003FFF /* ALLOCATE_FRAME_LENGTH[13..0] */ +#define WF_PSE_TOP_ALLOCATE_0_ALLOCATE_FRAME_LENGTH_SHFT 0 + +/* +* ---ALLOCATE_1 (0x820C8000 + 0x354)--- +* ALLOCATE_FID[11..0] - (RO) Return frame ID for allocate buffer +command +* RESERVED12[30..12] - (RO) Reserved bits +* EXECUTE[31] - (RO) Execute status of allocate buffer +command +*/ +#define WF_PSE_TOP_ALLOCATE_1_EXECUTE_ADDR WF_PSE_TOP_ALLOCATE_1_ADDR +#define WF_PSE_TOP_ALLOCATE_1_EXECUTE_MASK 0x80000000 /* EXECUTE[31] */ +#define WF_PSE_TOP_ALLOCATE_1_EXECUTE_SHFT 31 +#define WF_PSE_TOP_ALLOCATE_1_ALLOCATE_FID_ADDR WF_PSE_TOP_ALLOCATE_1_ADDR +#define WF_PSE_TOP_ALLOCATE_1_ALLOCATE_FID_MASK \ +0x00000FFF /* ALLOCATE_FID[11..0] */ +#define WF_PSE_TOP_ALLOCATE_1_ALLOCATE_FID_SHFT 0 + +/* +* ---FREEPG_CNT (0x820C8000 + 0x380)--- +* FREEPG_CNT[11..0] - (RO) Total page number of free +* RESERVED12[15..12] - (RO) Reserved bits +* FFA_CNT[27..16] - (RO) Free page numbers of free for all +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_FREEPG_CNT_FFA_CNT_ADDR WF_PSE_TOP_FREEPG_CNT_ADDR +#define WF_PSE_TOP_FREEPG_CNT_FFA_CNT_MASK 0x0FFF0000 /* FFA_CNT[27..16] */ +#define WF_PSE_TOP_FREEPG_CNT_FFA_CNT_SHFT 16 +#define WF_PSE_TOP_FREEPG_CNT_FREEPG_CNT_ADDR WF_PSE_TOP_FREEPG_CNT_ADDR +#define WF_PSE_TOP_FREEPG_CNT_FREEPG_CNT_MASK 0x00000FFF /* FREEPG_CNT[11..0] */ +#define WF_PSE_TOP_FREEPG_CNT_FREEPG_CNT_SHFT 0 + +/* +* ---FREEPG_HEAD_TAIL (0x820C8000 + 0x384)--- +* FREEPG_HEAD[11..0] - (RO) Head page of free page list +* RESERVED12[15..12] - (RO) Reserved bits +* FREEPG_TAIL[27..16] - (RO) Tail page of free page list +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_ADDR \ +WF_PSE_TOP_FREEPG_HEAD_TAIL_ADDR +#define WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_MASK \ +0x0FFF0000 /* FREEPG_TAIL[27..16] */ +#define WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_SHFT 16 +#define WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_ADDR \ +WF_PSE_TOP_FREEPG_HEAD_TAIL_ADDR +#define WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_MASK \ +0x00000FFF /* FREEPG_HEAD[11..0] */ +#define WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_SHFT 0 + +/* +* ---PSE_SEEK_CR_00 (0x820C8000 + 0x3D0)--- +* PSE_FL_ARB_CS[2..0] - (RO) PSE debug state for FL_ARB_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_FL_CS[7..4] - (RO) PSE debug state for FL_CS +* PSE_ENQ_FL_CS[11..8] - (RO) PSE debug state for ENQ_FL_CS +* PSE_DEQ_FL_CS[15..12] - (RO) PSE debug state for DEQ_FL_CS +* PSE_ACC_LST_CS[18..16] - (RO) PSE debug state for ACC_LST_CS +* RESERVED19[31..19] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_ACC_LST_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_00_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_ACC_LST_CS_MASK \ +0x00070000 /* PSE_ACC_LST_CS[18..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_ACC_LST_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_DEQ_FL_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_00_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_DEQ_FL_CS_MASK \ +0x0000F000 /* PSE_DEQ_FL_CS[15..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_DEQ_FL_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_ENQ_FL_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_00_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_ENQ_FL_CS_MASK \ +0x00000F00 /* PSE_ENQ_FL_CS[11..8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_ENQ_FL_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_FL_CS_ADDR WF_PSE_TOP_PSE_SEEK_CR_00_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_FL_CS_MASK \ + 0x000000F0 /* PSE_FL_CS[7..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_FL_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_FL_ARB_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_00_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_FL_ARB_CS_MASK \ +0x00000007 /* PSE_FL_ARB_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_FL_ARB_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_01 (0x820C8000 + 0x3D4)--- +* PSE_PL_ARB_CS[2..0] - (RO) PSE debug state for PL_ARB_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_PL_INIT_CS[5..4] - (RO) PSE debug state for PL_INIT_CS +* RESERVED6[7..6] - (RO) Reserved bits +* PSE_PL_GNEXT_CS[8] - (RO) PSE debug state for PL_GNEXT_CS +* RESERVED9[11..9] - (RO) Reserved bits +* PSE_PL_GBUF_CS[14..12] - (RO) PSE debug state for PL_GBUF_CS +* RESERVED15[15] - (RO) Reserved bits +* PSE_PL_RLS_CS[17..16] - (RO) PSE debug state for PL_RLS_CS +* RESERVED18[19..18] - (RO) Reserved bits +* PSE_PL_REFILL_CS[22..20] - (RO) PSE debug state for PL_REFILL_CS +* RESERVED23[23] - (RO) Reserved bits +* PSE_RLS_CS[25..24] - (RO) PSE debug state for RLS_CS +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_RLS_CS_ADDR WF_PSE_TOP_PSE_SEEK_CR_01_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_RLS_CS_MASK \ +0x03000000 /* PSE_RLS_CS[25..24] */ +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_RLS_CS_SHFT 24 +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_REFILL_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_01_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_REFILL_CS_MASK \ +0x00700000 /* PSE_PL_REFILL_CS[22..20] */ +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_REFILL_CS_SHFT 20 +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_RLS_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_01_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_RLS_CS_MASK \ +0x00030000 /* PSE_PL_RLS_CS[17..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_RLS_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_GBUF_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_01_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_GBUF_CS_MASK \ +0x00007000 /* PSE_PL_GBUF_CS[14..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_GBUF_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_GNEXT_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_01_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_GNEXT_CS_MASK \ +0x00000100 /* PSE_PL_GNEXT_CS[8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_GNEXT_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_INIT_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_01_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_INIT_CS_MASK \ +0x00000030 /* PSE_PL_INIT_CS[5..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_INIT_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_ARB_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_01_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_ARB_CS_MASK \ +0x00000007 /* PSE_PL_ARB_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_ARB_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_02 (0x820C8000 + 0x3D8)--- +* PSE_HIF_DOP_PBUF_CS[2..0] - (RO) PSE debug state for HIF_DOP_PBUF_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_HIF_DOP_CACHE_CS[5..4] - (RO) PSE debug state for HIF_DOP_CACHE_CS +* RESERVED6[7..6] - (RO) Reserved bits +* PSE_HIF_QOP_Q_OPER_CS[11..8] - (RO) PSE debug state for HIF_QOP_Q_OPER_CS +* PSE_HIF_QOP_RL_OCP_CS[13..12] - (RO) PSE debug state for HIF_QOP_RL_OCP_CS +* RESERVED14[15..14] - (RO) Reserved bits +* PSE_HIF_QOP_PL_OCP_CS[17..16] - (RO) PSE debug state for HIF_QOP_PL_OCP_CS +* RESERVED18[19..18] - (RO) Reserved bits +* PSE_HIF_QOP_ALLOCATE_CS[22..20] - (RO) PSE debug state for +HIF_QOP_ALLOCATE_CS +* RESERVED23[23] - (RO) Reserved bits +* PSE_HIF_RX_DOP_PBUF_CS[26..24] - (RO) PSE debug state for HIF_RX_DOP_PBUF_CS +* RESERVED27[27] - (RO) Reserved bits +* PSE_HIF_RX_DOP_CACHE_CS[29..28] - (RO) PSE debug state for +HIF_RX_DOP_CACHE_CS +* RESERVED30[31..30] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_RX_DOP_CACHE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_02_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_RX_DOP_CACHE_CS_MASK \ +0x30000000 /* PSE_HIF_RX_DOP_CACHE_CS[29..28] */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_RX_DOP_CACHE_CS_SHFT 28 +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_RX_DOP_PBUF_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_02_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_RX_DOP_PBUF_CS_MASK \ +0x07000000 /* PSE_HIF_RX_DOP_PBUF_CS[26..24] */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_RX_DOP_PBUF_CS_SHFT 24 +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_ALLOCATE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_02_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_ALLOCATE_CS_MASK \ +0x00700000 /* PSE_HIF_QOP_ALLOCATE_CS[22..20] */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_ALLOCATE_CS_SHFT 20 +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_PL_OCP_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_02_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_PL_OCP_CS_MASK \ +0x00030000 /* PSE_HIF_QOP_PL_OCP_CS[17..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_PL_OCP_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_RL_OCP_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_02_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_RL_OCP_CS_MASK \ +0x00003000 /* PSE_HIF_QOP_RL_OCP_CS[13..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_RL_OCP_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_Q_OPER_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_02_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_Q_OPER_CS_MASK \ +0x00000F00 /* PSE_HIF_QOP_Q_OPER_CS[11..8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_Q_OPER_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_DOP_CACHE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_02_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_DOP_CACHE_CS_MASK \ +0x00000030 /* PSE_HIF_DOP_CACHE_CS[5..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_DOP_CACHE_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_DOP_PBUF_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_02_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_DOP_PBUF_CS_MASK \ +0x00000007 /* PSE_HIF_DOP_PBUF_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_DOP_PBUF_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_03 (0x820C8000 + 0x3DC)--- +* PSE_CPU_DOP_PBUF_CS[2..0] - (RO) PSE debug state for CPU_DOP_PBUF_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_CPU_DOP_CACHE_CS[5..4] - (RO) PSE debug state for CPU_DOP_CACHE_CS +* RESERVED6[7..6] - (RO) Reserved bits +* PSE_CPU_QOP_Q_OPER_CS[11..8] - (RO) PSE debug state for CPU_QOP_Q_OPER_CS +* PSE_CPU_QOP_RL_OCP_CS[13..12] - (RO) PSE debug state for CPU_QOP_RL_OCP_CS +* RESERVED14[15..14] - (RO) Reserved bits +* PSE_CPU_QOP_PL_OCP_CS[17..16] - (RO) PSE debug state for CPU_QOP_PL_OCP_CS +* RESERVED18[19..18] - (RO) Reserved bits +* PSE_CPU_QOP_ALLOCATE_CS[22..20] - (RO) PSE debug state for +CPU_QOP_ALLOCATE_CS +* RESERVED23[31..23] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_ALLOCATE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_03_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_ALLOCATE_CS_MASK \ +0x00700000 /* PSE_CPU_QOP_ALLOCATE_CS[22..20] */ +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_ALLOCATE_CS_SHFT 20 +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_PL_OCP_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_03_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_PL_OCP_CS_MASK \ +0x00030000 /* PSE_CPU_QOP_PL_OCP_CS[17..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_PL_OCP_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_RL_OCP_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_03_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_RL_OCP_CS_MASK \ +0x00003000 /* PSE_CPU_QOP_RL_OCP_CS[13..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_RL_OCP_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_Q_OPER_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_03_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_Q_OPER_CS_MASK \ +0x00000F00 /* PSE_CPU_QOP_Q_OPER_CS[11..8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_Q_OPER_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_DOP_CACHE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_03_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_DOP_CACHE_CS_MASK \ +0x00000030 /* PSE_CPU_DOP_CACHE_CS[5..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_DOP_CACHE_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_DOP_PBUF_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_03_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_DOP_PBUF_CS_MASK \ +0x00000007 /* PSE_CPU_DOP_PBUF_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_DOP_PBUF_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_04 (0x820C8000 + 0x3E0)--- +* PSE_WF_DOP_PBUF_CS[2..0] - (RO) PSE debug state for WF_DOP_PBUF_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_WF_DOP_CACHE_CS[5..4] - (RO) PSE debug state for WF_DOP_CACHE_CS +* RESERVED6[7..6] - (RO) Reserved bits +* PSE_WF_QOP_Q_OPER_CS[11..8] - (RO) PSE debug state for WF_QOP_Q_OPER_CS +* PSE_WF_QOP_RL_OCP_CS[13..12] - (RO) PSE debug state for WF_QOP_RL_OCP_CS +* RESERVED14[15..14] - (RO) Reserved bits +* PSE_WF_QOP_PL_OCP_CS[17..16] - (RO) PSE debug state for WF_QOP_PL_OCP_CS +* RESERVED18[19..18] - (RO) Reserved bits +* PSE_WF_QOP_ALLOCATE_CS[22..20] - (RO) PSE debug state for WF_QOP_ALLOCATE_CS +* RESERVED23[31..23] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_ALLOCATE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_04_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_ALLOCATE_CS_MASK \ +0x00700000 /* PSE_WF_QOP_ALLOCATE_CS[22..20] */ +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_ALLOCATE_CS_SHFT 20 +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_PL_OCP_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_04_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_PL_OCP_CS_MASK \ +0x00030000 /* PSE_WF_QOP_PL_OCP_CS[17..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_PL_OCP_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_RL_OCP_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_04_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_RL_OCP_CS_MASK \ +0x00003000 /* PSE_WF_QOP_RL_OCP_CS[13..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_RL_OCP_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_Q_OPER_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_04_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_Q_OPER_CS_MASK \ +0x00000F00 /* PSE_WF_QOP_Q_OPER_CS[11..8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_Q_OPER_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_DOP_CACHE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_04_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_DOP_CACHE_CS_MASK \ +0x00000030 /* PSE_WF_DOP_CACHE_CS[5..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_DOP_CACHE_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_DOP_PBUF_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_04_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_DOP_PBUF_CS_MASK \ +0x00000007 /* PSE_WF_DOP_PBUF_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_DOP_PBUF_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_05 (0x820C8000 + 0x3E4)--- +* PSE_MDP_DOP_PBUF_CS[2..0] - (RO) PSE debug state for MDP_DOP_PBUF_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_MDP_DOP_CACHE_CS[5..4] - (RO) PSE debug state for MDP_DOP_CACHE_CS +* RESERVED6[7..6] - (RO) Reserved bits +* PSE_MDP_QOP_Q_OPER_CS[11..8] - (RO) PSE debug state for MDP_QOP_Q_OPER_CS +* PSE_MDP_QOP_RL_OCP_CS[13..12] - (RO) PSE debug state for MDP_QOP_RL_OCP_CS +* RESERVED14[15..14] - (RO) Reserved bits +* PSE_MDP_QOP_PL_OCP_CS[17..16] - (RO) PSE debug state for MDP_QOP_PL_OCP_CS +* RESERVED18[19..18] - (RO) Reserved bits +* PSE_MDP_QOP_ALLOCATE_CS[22..20] - (RO) PSE debug state for +MDP_QOP_ALLOCATE_CS +* RESERVED23[31..23] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_ALLOCATE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_05_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_ALLOCATE_CS_MASK \ +0x00700000 /* PSE_MDP_QOP_ALLOCATE_CS[22..20] */ +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_ALLOCATE_CS_SHFT 20 +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_PL_OCP_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_05_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_PL_OCP_CS_MASK \ +0x00030000 /* PSE_MDP_QOP_PL_OCP_CS[17..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_PL_OCP_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_RL_OCP_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_05_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_RL_OCP_CS_MASK \ +0x00003000 /* PSE_MDP_QOP_RL_OCP_CS[13..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_RL_OCP_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_Q_OPER_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_05_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_Q_OPER_CS_MASK \ +0x00000F00 /* PSE_MDP_QOP_Q_OPER_CS[11..8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_Q_OPER_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_DOP_CACHE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_05_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_DOP_CACHE_CS_MASK \ +0x00000030 /* PSE_MDP_DOP_CACHE_CS[5..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_DOP_CACHE_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_DOP_PBUF_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_05_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_DOP_PBUF_CS_MASK \ +0x00000007 /* PSE_MDP_DOP_PBUF_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_DOP_PBUF_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_06 (0x820C8000 + 0x3E8)--- +* PSE_SEC_DOP_PBUF_CS[2..0] - (RO) PSE debug state for SEC_DOP_PBUF_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_SEC_DOP_CACHE_CS[5..4] - (RO) PSE debug state for SEC_DOP_CACHE_CS +* RESERVED6[7..6] - (RO) Reserved bits +* PSE_SEC_QOP_Q_OPER_CS[11..8] - (RO) PSE debug state for SEC_QOP_Q_OPER_CS +* PSE_SEC_QOP_RL_OCP_CS[13..12] - (RO) PSE debug state for SEC_QOP_RL_OCP_CS +* RESERVED14[15..14] - (RO) Reserved bits +* PSE_SEC_QOP_PL_OCP_CS[17..16] - (RO) PSE debug state for SEC_QOP_PL_OCP_CS +* RESERVED18[19..18] - (RO) Reserved bits +* PSE_SEC_QOP_ALLOCATE_CS[22..20] - (RO) PSE debug state for +SEC_QOP_ALLOCATE_CS +* RESERVED23[31..23] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_ALLOCATE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_06_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_ALLOCATE_CS_MASK \ +0x00700000 /* PSE_SEC_QOP_ALLOCATE_CS[22..20] */ +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_ALLOCATE_CS_SHFT 20 +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_PL_OCP_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_06_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_PL_OCP_CS_MASK \ +0x00030000 /* PSE_SEC_QOP_PL_OCP_CS[17..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_PL_OCP_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_RL_OCP_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_06_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_RL_OCP_CS_MASK \ +0x00003000 /* PSE_SEC_QOP_RL_OCP_CS[13..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_RL_OCP_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_Q_OPER_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_06_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_Q_OPER_CS_MASK \ +0x00000F00 /* PSE_SEC_QOP_Q_OPER_CS[11..8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_Q_OPER_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_DOP_CACHE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_06_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_DOP_CACHE_CS_MASK \ +0x00000030 /* PSE_SEC_DOP_CACHE_CS[5..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_DOP_CACHE_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_DOP_PBUF_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_06_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_DOP_PBUF_CS_MASK \ +0x00000007 /* PSE_SEC_DOP_PBUF_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_DOP_PBUF_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_07 (0x820C8000 + 0x3EC)--- +* PSE_PLE_DOP_PBUF_CS[2..0] - (RO) PSE debug state for PLE_DOP_PBUF_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_PLE_DOP_CACHE_CS[5..4] - (RO) PSE debug state for PLE_DOP_CACHE_CS +* RESERVED6[7..6] - (RO) Reserved bits +* PSE_PLE_QOP_Q_OPER_CS[11..8] - (RO) PSE debug state for PLE_QOP_Q_OPER_CS +* PSE_PLE_QOP_RL_OCP_CS[13..12] - (RO) PSE debug state for PLE_QOP_RL_OCP_CS +* RESERVED14[15..14] - (RO) Reserved bits +* PSE_PLE_QOP_PL_OCP_CS[17..16] - (RO) PSE debug state for PLE_QOP_PL_OCP_CS +* RESERVED18[19..18] - (RO) Reserved bits +* PSE_PLE_QOP_ALLOCATE_CS[22..20] - (RO) PSE debug state for +PLE_QOP_ALLOCATE_CS +* RESERVED23[31..23] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_ALLOCATE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_07_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_ALLOCATE_CS_MASK \ +0x00700000 /* PSE_PLE_QOP_ALLOCATE_CS[22..20] */ +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_ALLOCATE_CS_SHFT 20 +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_PL_OCP_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_07_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_PL_OCP_CS_MASK \ +0x00030000 /* PSE_PLE_QOP_PL_OCP_CS[17..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_PL_OCP_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_RL_OCP_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_07_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_RL_OCP_CS_MASK \ +0x00003000 /* PSE_PLE_QOP_RL_OCP_CS[13..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_RL_OCP_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_Q_OPER_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_07_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_Q_OPER_CS_MASK \ +0x00000F00 /* PSE_PLE_QOP_Q_OPER_CS[11..8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_Q_OPER_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_DOP_CACHE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_07_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_DOP_CACHE_CS_MASK \ +0x00000030 /* PSE_PLE_DOP_CACHE_CS[5..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_DOP_CACHE_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_DOP_PBUF_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_07_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_DOP_PBUF_CS_MASK \ +0x00000007 /* PSE_PLE_DOP_PBUF_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_DOP_PBUF_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_08 (0x820C8000 + 0x3F0)--- +* PSE_AMSDU_DOP_PBUF_CS[2..0] - (RO) PSE debug state for AMSDU_DOP_PBUF_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_AMSDU_DOP_CACHE_CS[5..4] - (RO) PSE debug state for AMSDU_DOP_CACHE_CS +* RESERVED6[7..6] - (RO) Reserved bits +* CPU_Q_OP_CS[11..8] - (RO) PSE debug state for CPI_Q_OP_CS +* ARB_REQ_CS[14..12] - (RO) PSE debug state for ARB_REQ_CS +* RESERVED15[15] - (RO) Reserved bits +* APB_REQ_CS[18..16] - (RO) PSE debug state for APB_REQ_CS +* RESERVED19[31..19] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_08_APB_REQ_CS_ADDR WF_PSE_TOP_PSE_SEEK_CR_08_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_08_APB_REQ_CS_MASK \ +0x00070000 /* APB_REQ_CS[18..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_08_APB_REQ_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_08_ARB_REQ_CS_ADDR WF_PSE_TOP_PSE_SEEK_CR_08_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_08_ARB_REQ_CS_MASK \ +0x00007000 /* ARB_REQ_CS[14..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_08_ARB_REQ_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_08_CPU_Q_OP_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_08_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_08_CPU_Q_OP_CS_MASK \ +0x00000F00 /* CPU_Q_OP_CS[11..8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_08_CPU_Q_OP_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_08_PSE_AMSDU_DOP_CACHE_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_08_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_08_PSE_AMSDU_DOP_CACHE_CS_MASK \ +0x00000030 /* PSE_AMSDU_DOP_CACHE_CS[5..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_08_PSE_AMSDU_DOP_CACHE_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_08_PSE_AMSDU_DOP_PBUF_CS_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_08_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_08_PSE_AMSDU_DOP_PBUF_CS_MASK \ +0x00000007 /* PSE_AMSDU_DOP_PBUF_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_08_PSE_AMSDU_DOP_PBUF_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_09 (0x820C8000 + 0x3F4)--- +* RESERVED0[15..0] - (RO) Reserved bits +* DOUBLE_RLS_FID[27..16] - (RO) PSE double RLS FID PAGE +* RESERVED28[30..28] - (RO) Reserved bits +* DOUBLE_RLS_ERROR[31] - (RO) PSE double RLS error flag +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_09_DOUBLE_RLS_ERROR_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_09_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_09_DOUBLE_RLS_ERROR_MASK \ +0x80000000 /* DOUBLE_RLS_ERROR[31] */ +#define WF_PSE_TOP_PSE_SEEK_CR_09_DOUBLE_RLS_ERROR_SHFT 31 +#define WF_PSE_TOP_PSE_SEEK_CR_09_DOUBLE_RLS_FID_ADDR \ +WF_PSE_TOP_PSE_SEEK_CR_09_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_09_DOUBLE_RLS_FID_MASK \ +0x0FFF0000 /* DOUBLE_RLS_FID[27..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_09_DOUBLE_RLS_FID_SHFT 16 + +#ifdef __cplusplus +} +#endif + +#endif /* __WF_PSE_TOP_REGS_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7961/wf_wfdma_host_dma0.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7961/wf_wfdma_host_dma0.h new file mode 100644 index 0000000000000..115ead34a821a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/mt7961/wf_wfdma_host_dma0.h @@ -0,0 +1,8406 @@ +/* [File] : wf_wfdma_host_dma0.h */ +/* [Revision time] : Thu May 30 10:53:24 2019 */ +/* [Description] : This file is auto generated by CODA */ +/* [Copyright] : Copyright (C) 2019 Mediatek Incorportion. All rights */ +/* reserved. */ + +#ifndef __WF_WFDMA_HOST_DMA0_REGS_H__ +#define __WF_WFDMA_HOST_DMA0_REGS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ************************************************************************** */ +/* */ +/* WF_WFDMA_HOST_DMA0 CR Definitions */ +/* */ +/* ************************************************************************** */ + +#define WF_WFDMA_HOST_DMA0_BASE 0x7C024000 + +#define WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0XA0) /* 40A0 */ +#define WF_WFDMA_HOST_DMA0_HOST_IF_RX_DONE_STS_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0XA4) /* 40A4 */ +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_START_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x0B0) /* 40B0 */ +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_START_EXT_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x0B4) /* 40B4 */ +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_END_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x0B8) /* 40B8 */ +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_END_EXT_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x0BC) /* 40BC */ +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_START_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x0C0) /* 40C0 */ +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_START_EXT_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x0C4) /* 40C4 */ +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_END_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x0C8) /* 40C8 */ +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_END_EXT_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x0CC) /* 40CC */ +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_START_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x0D0) /* 40D0 */ +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_START_EXT_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x0D4) /* 40D4 */ +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_END_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x0D8) /* 40D8 */ +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_END_EXT_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x0DC) /* 40DC */ +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_START_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x0E0) /* 40E0 */ +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_START_EXT_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x0E4) /* 40E4 */ +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_END_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x0E8) /* 40E8 */ +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_END_EXT_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x0EC) /* 40EC */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_RST_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x100) /* 4100 */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0X108) /* 4108 */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x10C) /* 410C */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0X110) /* 4110 */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0X114) /* 4114 */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DUMMY_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x120) /* 4120 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x124) /* 4124 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_PROBE_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x128) /* 4128 */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x12C) /* 412C */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_PROBE_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x130) /* 4130 */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DMASHDL_DBG_PROBE_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x134) /* 4134 */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x138) /* 4138 */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x13c) /* 413C */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x140) /* 4140 */ +#define WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x1E8) /* 41E8 */ +#define WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x1EC) /* 41EC */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x1F0) /* 41F0 */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x1F4) /* 41F4 */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x1F8) /* 41F8 */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x1FC) /* 41FC */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x200) /* 4200 */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0X204) /* 4204 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x208) /* 4208 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x20C) /* 420C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_TX_Q_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x224) /* 4224 */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0X228) /* 4228 */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0X22C) /* 422C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x230) /* 4230 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x234) /* 4234 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x240) /* 4240 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x260) /* 4260 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x264) /* 4264 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x268) /* 4268 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x26C) /* 426C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x280) /* 4280 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x284) /* 4284 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x288) /* 4288 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x298) /* 4298 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x29C) /* 429C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x2A0) /* 42A0 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x2A4) /* 42A4 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x2A8) /* 42A8 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x2AC) /* 42AC */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x2B0) /* 42B0 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x2B4) /* 42B4 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x2B8) /* 42B8 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x2D0) /* 42D0 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x2D4) /* 42D4 */ +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x2E0) /* 42E0 */ +#define WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x2E4) /* 42E4 */ +#define WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x2E8) /* 42E8 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x2F0) /* 42F0 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x300) /* 4300 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x304) /* 4304 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x308) /* 4308 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x30c) /* 430C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x310) /* 4310 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x314) /* 4314 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x318) /* 4318 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x31c) /* 431C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x320) /* 4320 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x324) /* 4324 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x328) /* 4328 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x32c) /* 432C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x330) /* 4330 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x334) /* 4334 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x338) /* 4338 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x33c) /* 433C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x340) /* 4340 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x344) /* 4344 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x348) /* 4348 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x34c) /* 434C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x350) /* 4350 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x354) /* 4354 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x358) /* 4358 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x35c) /* 435C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x360) /* 4360 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x364) /* 4364 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x368) /* 4368 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x36c) /* 436C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x370) /* 4370 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x374) /* 4374 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x378) /* 4378 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x37c) /* 437C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x380) /* 4380 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x384) /* 4384 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x388) /* 4388 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x38c) /* 438C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x390) /* 4390 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x394) /* 4394 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x398) /* 4398 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x39c) /* 439C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x3a0) /* 43A0 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x3a4) /* 43A4 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x3a8) /* 43A8 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x3ac) /* 43AC */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x3b0) /* 43B0 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x3b4) /* 43B4 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x3b8) /* 43B8 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x3bc) /* 43BC */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x3c0) /* 43C0 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x3c4) /* 43C4 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x3c8) /* 43C8 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x3cc) /* 43CC */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x3d0) /* 43D0 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x3d4) /* 43D4 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x3d8) /* 43D8 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x3dc) /* 43DC */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x3e0) /* 43E0 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x3e4) /* 43E4 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x3e8) /* 43E8 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x3ec) /* 43EC */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x3f0) /* 43F0 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x3f4) /* 43F4 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x3f8) /* 43F8 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x3fc) /* 43FC */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x400) /* 4400 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x404) /* 4404 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x408) /* 4408 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x40c) /* 440C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x410) /* 4410 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x414) /* 4414 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x418) /* 4418 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x41c) /* 441C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x420) /* 4420 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x424) /* 4424 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x428) /* 4428 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x42c) /* 442C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x500) /* 4500 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x504) /* 4504 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x508) /* 4508 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x50c) /* 450C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x510) /* 4510 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x514) /* 4514 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x518) /* 4518 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x51c) /* 451C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x520) /* 4520 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x524) /* 4524 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x528) /* 4528 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x52C) /* 452C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x530) /* 4530 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x534) /* 4534 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x538) /* 4538 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x53C) /* 453C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x540) /* 4540 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x544) /* 4544 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x548) /* 4548 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x54c) /* 454C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x550) /* 4550 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x554) /* 4554 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x558) /* 4558 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x55c) /* 455C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x560) /* 4560 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x564) /* 4564 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x568) /* 4568 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x56C) /* 456C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x570) /* 4570 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x574) /* 4574 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x578) /* 4578 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL3_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x57C) /* 457C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x600) /* 4600 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x604) /* 4604 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x608) /* 4608 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x60C) /* 460C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x610) /* 4610 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x614) /* 4614 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x618) /* 4618 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x61C) /* 461C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x620) /* 4620 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x624) /* 4624 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x628) /* 4628 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x62C) /* 462C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x630) /* 4630 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x634) /* 4634 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x638) /* 4638 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x63C) /* 463C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x640) /* 4640 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x644) /* 4644 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x648) /* 4648 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x680) /* 4680 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x684) /* 4684 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x688) /* 4688 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x68C) /* 468C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x690) /* 4690 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x694) /* 4694 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x698) /* 4698 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_EXT_CTRL_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0x69C) /* 469C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA00) /* 4A00 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA04) /* 4A04 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA08) /* 4A08 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA10) /* 4A10 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA14) /* 4A14 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA18) /* 4A18 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA20) /* 4A20 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA24) /* 4A24 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA28) /* 4A28 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA30) /* 4A30 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA34) /* 4A34 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA38) /* 4A38 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA40) /* 4A40 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA44) /* 4A44 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA48) /* 4A48 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA50) /* 4A50 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA54) /* 4A54 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA58) /* 4A58 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA60) /* 4A60 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA64) /* 4A64 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA68) /* 4A68 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA70) /* 4A70 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA74) /* 4A74 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA78) /* 4A78 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA80) /* 4A80 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA84) /* 4A84 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA88) /* 4A88 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA90) /* 4A90 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA94) /* 4A94 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xA98) /* 4A98 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xAA0) /* 4AA0 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xAA4) /* 4AA4 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xAA8) /* 4AA8 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xAB0) /* 4AB0 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xAB4) /* 4AB4 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xAB8) /* 4AB8 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xAC0) /* 4AC0 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xAC4) /* 4AC4 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xAC8) /* 4AC8 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xAD0) /* 4AD0 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xAD4) /* 4AD4 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xAD8) /* 4AD8 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xAE0) /* 4AE0 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xAE4) /* 4AE4 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xAE8) /* 4AE8 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xAF0) /* 4AF0 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xAF4) /* 4AF4 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xAF8) /* 4AF8 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xB00) /* 4B00 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xB04) /* 4B04 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xB08) /* 4B08 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xB10) /* 4B10 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xB14) /* 4B14 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xB18) /* 4B18 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xB20) /* 4B20 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xB24) /* 4B24 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xB28) /* 4B28 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC00) /* 4C00 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC04) /* 4C04 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC08) /* 4C08 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC10) /* 4C10 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC14) /* 4C14 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC18) /* 4C18 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC20) /* 4C20 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC24) /* 4C24 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC28) /* 4C28 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC30) /* 4C30 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC34) /* 4C34 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC38) /* 4C38 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC40) /* 4C40 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC44) /* 4C44 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC48) /* 4C48 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC50) /* 4C50 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC54) /* 4C54 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC58) /* 4C58 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC60) /* 4C60 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC64) /* 4C64 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC68) /* 4C68 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC70) /* 4C70 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC74) /* 4C74 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC78) /* 4C78 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL0_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC80) /* 4C80 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL1_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC84) /* 4C84 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL2_ADDR \ +(WF_WFDMA_HOST_DMA0_BASE + 0xC88) /* 4C88 */ + +/* +* ---HOST_IF_TX_DONE_STS (0x18024000 + 0XA0)--- +* fifo_dfet_txdone_dat0_done_sts[0] - (W1C) USB DAT0 FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint +buffer +* fifo_dfet_txdone_dat1_done_sts[1] - (W1C) USB DAT1 FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint +buffer +* fifo_dfet_txdone_dat2_done_sts[2] - (W1C) USB DAT2 FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint +buffer +* fifo_dfet_txdone_dat3_done_sts[3] - (W1C) USB DAT3 FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint +buffer +* fifo_dfet_txdone_dat4_done_sts[4] - (W1C) USB DAT4 FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint +buffer +* fifo_dfet_txdone_cmd_done_sts[5] - (W1C) USB CMD FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint +buffer +* fifo_dfet_txdone_fwdl_done_sts[6] - (W1C) USB Firmware download FIFO Tx +status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint +buffer +* SDIO Mode (All SDIO Tx packet goto firmware +* download FIFO) +* 0 : no tx done +* 1 : pdma start to fetch data from SDIO +buffer +* RESERVED7[31..7] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_fwdl_done_sts_ADDR \ + \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_fwdl_done_sts_MASK \ + \ +0x00000040 /* fifo_dfet_txdone_fwdl_done_sts[6] */ +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_fwdl_done_sts_SHFT \ + \ +6 +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_cmd_done_sts_ADDR \ + \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_cmd_done_sts_MASK \ + \ +0x00000020 /* fifo_dfet_txdone_cmd_done_sts[5] */ +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_cmd_done_sts_SHFT \ + \ +5 +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat4_done_sts_ADDR \ + \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat4_done_sts_MASK \ + \ +0x00000010 /* fifo_dfet_txdone_dat4_done_sts[4] */ +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat4_done_sts_SHFT \ + \ +4 +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat3_done_sts_ADDR \ + \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat3_done_sts_MASK \ + \ +0x00000008 /* fifo_dfet_txdone_dat3_done_sts[3] */ +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat3_done_sts_SHFT \ + \ +3 +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat2_done_sts_ADDR \ + \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat2_done_sts_MASK \ + \ +0x00000004 /* fifo_dfet_txdone_dat2_done_sts[2] */ +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat2_done_sts_SHFT \ + \ +2 +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat1_done_sts_ADDR \ + \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat1_done_sts_MASK \ + \ +0x00000002 /* fifo_dfet_txdone_dat1_done_sts[1] */ +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat1_done_sts_SHFT \ + \ +1 +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat0_done_sts_ADDR \ + \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat0_done_sts_MASK \ + \ +0x00000001 /* fifo_dfet_txdone_dat0_done_sts[0] */ +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat0_done_sts_SHFT \ + \ +0 + +/* +* ---HOST_IF_RX_DONE_STS (0x18024000 + 0XA4)--- +* RESERVED0[0] - (RO) Reserved bits +* rx1_packet_done_sts[1] - (W1C) USB/SDIO Rx1 packet done status +* 0 : no rx packet done +* 1 : rx packet send to host interface +* Note : All SDIO Packet send to SIDO RX0 +port +* RESERVED2[31..2] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_HOST_IF_RX_DONE_STS_rx1_packet_done_sts_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_IF_RX_DONE_STS_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_IF_RX_DONE_STS_rx1_packet_done_sts_MASK \ +0x00000002 /* rx1_packet_done_sts[1] */ +#define WF_WFDMA_HOST_DMA0_HOST_IF_RX_DONE_STS_rx1_packet_done_sts_SHFT 1 + +/* +* ---TX_DMAD_RNG_START (0x18024000 + 0x0B0)--- +* tx_dmad_rng_start[31..0] - (RW) TX DMAD address range start [31:0] +*/ +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_START_tx_dmad_rng_start_ADDR \ +WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_START_ADDR +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_START_tx_dmad_rng_start_MASK \ +0xFFFFFFFF /* tx_dmad_rng_start[31..0] */ +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_START_tx_dmad_rng_start_SHFT 0 + +/* +* ---TX_DMAD_RNG_START_EXT (0x18024000 + 0x0B4)--- +* tx_dmad_rng_start_ext[3..0] - (RW) TX DMAD address range start [35:32] +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_START_EXT_tx_dmad_rng_start_ext_ADDR \ +WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_START_EXT_ADDR +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_START_EXT_tx_dmad_rng_start_ext_MASK \ +0x0000000F /* tx_dmad_rng_start_ext[3..0] */ +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_START_EXT_tx_dmad_rng_start_ext_SHFT 0 + +/* +* ---TX_DMAD_RNG_END (0x18024000 + 0x0B8)--- +* tx_dmad_rng_end[31..0] - (RW) TX DMAD address range end [31:0] +*/ +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_END_tx_dmad_rng_end_ADDR \ +WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_END_ADDR +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_END_tx_dmad_rng_end_MASK \ +0xFFFFFFFF /* tx_dmad_rng_end[31..0] */ +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_END_tx_dmad_rng_end_SHFT 0 + +/* +* ---TX_DMAD_RNG_END_EXT (0x18024000 + 0x0BC)--- +* tx_dmad_rng_end_ext[3..0] - (RW) TX DMAD address range end [35:32] +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_END_EXT_tx_dmad_rng_end_ext_ADDR \ +WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_END_EXT_ADDR +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_END_EXT_tx_dmad_rng_end_ext_MASK \ +0x0000000F /* tx_dmad_rng_end_ext[3..0] */ +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_END_EXT_tx_dmad_rng_end_ext_SHFT 0 + +/* +* ---RX_DMAD_RNG_START (0x18024000 + 0x0C0)--- +* rx_dmad_rng_start[31..0] - (RW) RX DMAD address range start [31:0] +*/ +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_START_rx_dmad_rng_start_ADDR \ +WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_START_ADDR +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_START_rx_dmad_rng_start_MASK \ +0xFFFFFFFF /* rx_dmad_rng_start[31..0] */ +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_START_rx_dmad_rng_start_SHFT 0 + +/* +* ---RX_DMAD_RNG_START_EXT (0x18024000 + 0x0C4)--- +* rx_dmad_rng_start_ext[3..0] - (RW) RX DMAD address range start [35:32] +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_START_EXT_rx_dmad_rng_start_ext_ADDR \ +WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_START_EXT_ADDR +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_START_EXT_rx_dmad_rng_start_ext_MASK \ +0x0000000F /* rx_dmad_rng_start_ext[3..0] */ +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_START_EXT_rx_dmad_rng_start_ext_SHFT 0 + +/* +* ---RX_DMAD_RNG_END (0x18024000 + 0x0C8)--- +* rx_dmad_rng_end[31..0] - (RW) RX DMAD address range end [31:0] +*/ +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_END_rx_dmad_rng_end_ADDR \ +WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_END_ADDR +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_END_rx_dmad_rng_end_MASK \ +0xFFFFFFFF /* rx_dmad_rng_end[31..0] */ +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_END_rx_dmad_rng_end_SHFT 0 + +/* +* ---RX_DMAD_RNG_END_EXT (0x18024000 + 0x0CC)--- +* rx_dmad_rng_end_ext[3..0] - (RW) RX DMAD address range end [35:32] +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_END_EXT_rx_dmad_rng_end_ext_ADDR \ +WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_END_EXT_ADDR +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_END_EXT_rx_dmad_rng_end_ext_MASK \ +0x0000000F /* rx_dmad_rng_end_ext[3..0] */ +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_END_EXT_rx_dmad_rng_end_ext_SHFT 0 + +/* +* ---TX_PLD_RNG_START (0x18024000 + 0x0D0)--- +* tx_pld_rng_start[31..0] - (RW) TX PLD address range start [31:0] +*/ +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_START_tx_pld_rng_start_ADDR \ +WF_WFDMA_HOST_DMA0_TX_PLD_RNG_START_ADDR +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_START_tx_pld_rng_start_MASK \ +0xFFFFFFFF /* tx_pld_rng_start[31..0] */ +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_START_tx_pld_rng_start_SHFT 0 + +/* +* ---TX_PLD_RNG_START_EXT (0x18024000 + 0x0D4)--- +* tx_pld_rng_start_ext[3..0] - (RW) TX PLD address range start [35:32] +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_START_EXT_tx_pld_rng_start_ext_ADDR \ +WF_WFDMA_HOST_DMA0_TX_PLD_RNG_START_EXT_ADDR +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_START_EXT_tx_pld_rng_start_ext_MASK \ +0x0000000F /* tx_pld_rng_start_ext[3..0] */ +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_START_EXT_tx_pld_rng_start_ext_SHFT 0 + +/* +* ---TX_PLD_RNG_END (0x18024000 + 0x0D8)--- +* tx_pld_rng_end[31..0] - (RW) TX PLD address range end [31:0] +*/ +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_END_tx_pld_rng_end_ADDR \ +WF_WFDMA_HOST_DMA0_TX_PLD_RNG_END_ADDR +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_END_tx_pld_rng_end_MASK \ +0xFFFFFFFF /* tx_pld_rng_end[31..0] */ +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_END_tx_pld_rng_end_SHFT 0 + +/* +* ---TX_PLD_RNG_END_EXT (0x18024000 + 0x0DC)--- +* tx_pld_rng_end_ext[3..0] - (RW) TX PLD address range end [35:32] +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_END_EXT_tx_pld_rng_end_ext_ADDR \ +WF_WFDMA_HOST_DMA0_TX_PLD_RNG_END_EXT_ADDR +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_END_EXT_tx_pld_rng_end_ext_MASK \ +0x0000000F /* tx_pld_rng_end_ext[3..0] */ +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_END_EXT_tx_pld_rng_end_ext_SHFT 0 + +/* +* ---RX_PLD_RNG_START (0x18024000 + 0x0E0)--- +* rx_pld_rng_start[31..0] - (RW) RX PLD address range start [31:0] +*/ +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_START_rx_pld_rng_start_ADDR \ +WF_WFDMA_HOST_DMA0_RX_PLD_RNG_START_ADDR +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_START_rx_pld_rng_start_MASK \ +0xFFFFFFFF /* rx_pld_rng_start[31..0] */ +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_START_rx_pld_rng_start_SHFT 0 + +/* +* ---RX_PLD_RNG_START_EXT (0x18024000 + 0x0E4)--- +* rx_pld_rng_start_ext[3..0] - (RW) RX PLD address range start [35:32] +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_START_EXT_rx_pld_rng_start_ext_ADDR \ +WF_WFDMA_HOST_DMA0_RX_PLD_RNG_START_EXT_ADDR +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_START_EXT_rx_pld_rng_start_ext_MASK \ +0x0000000F /* rx_pld_rng_start_ext[3..0] */ +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_START_EXT_rx_pld_rng_start_ext_SHFT 0 + +/* +* ---RX_PLD_RNG_END (0x18024000 + 0x0E8)--- +* rx_pld_rng_end[31..0] - (RW) RX PLD address range end [31:0] +*/ +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_END_rx_pld_rng_end_ADDR \ +WF_WFDMA_HOST_DMA0_RX_PLD_RNG_END_ADDR +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_END_rx_pld_rng_end_MASK \ +0xFFFFFFFF /* rx_pld_rng_end[31..0] */ +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_END_rx_pld_rng_end_SHFT 0 + +/* +* ---RX_PLD_RNG_END_EXT (0x18024000 + 0x0EC)--- +* rx_pld_rng_end_ext[3..0] - (RW) RX PLD address range end [35:32] +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_END_EXT_rx_pld_rng_end_ext_ADDR \ +WF_WFDMA_HOST_DMA0_RX_PLD_RNG_END_EXT_ADDR +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_END_EXT_rx_pld_rng_end_ext_MASK \ +0x0000000F /* rx_pld_rng_end_ext[3..0] */ +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_END_EXT_rx_pld_rng_end_ext_SHFT 0 + +/* +* ---CONN_HIF_RST (0x18024000 + 0x100)--- +* RESERVED0[3..0] - (RO) Reserved bits +* conn_hif_logic_rst_n[4] - (RW) This conn_hif_logic_rst_n would reset +* wpdma logic partial control register, include Tx/Rx ring control. +* Also, conn_hif_logic_rst_n would reset wifi +* data path, include tx fifo, rx fifo, r2x_bridge, axi_mux and other other +* asynchronous bridge. +* (Note : conn_hif_logic_rst_n would not +* reset hif_dmashdl logic) +* dmashdl_all_rst_n[5] - (RW) This dmashdl_all_rst_n would reset +* hif_dmashdl_top, include logic and control register. +* RESERVED6[31..6] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_RST_dmashdl_all_rst_n_ADDR \ +WF_WFDMA_HOST_DMA0_CONN_HIF_RST_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_RST_dmashdl_all_rst_n_MASK \ +0x00000020 /* dmashdl_all_rst_n[5] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_RST_dmashdl_all_rst_n_SHFT 5 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_RST_conn_hif_logic_rst_n_ADDR \ +WF_WFDMA_HOST_DMA0_CONN_HIF_RST_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_RST_conn_hif_logic_rst_n_MASK \ +0x00000010 /* conn_hif_logic_rst_n[4] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_RST_conn_hif_logic_rst_n_SHFT 4 + +/* +* ---HOST2MCU_SW_INT_SET (0x18024000 + 0X108)--- +* host2mcu_sw_int_0_set[0] - (WO) Driver set this bit to generate MCU +* interrupt and 0x5000_0110[0] will be set to 1. +* host2mcu_sw_int_1_set[1] - (WO) Driver set this bit to generate MCU +* interrupt and 0x5000_0110[1] will be set to 1. +* host2mcu_sw_int_2_set[2] - (WO) Driver set this bit to generate MCU +* interrupt and 0x5000_0110[2] will be set to 1. +* host2mcu_sw_int_3_set[3] - (WO) Driver set [0x0_4108] bit[3] to generate +* MCU interrupt and 0x5000_0110[3] will be set to 1. +* host2mcu_sw_int_4_set[4] - (WO) Driver set [0x0_4108] bit[4] to generate +* MCU interrupt and 0x5000_0110[4] will be set to 1. +* host2mcu_sw_int_5_set[5] - (WO) Driver set [0x0_4108] bit[5] to generate +* MCU interrupt and 0x5000_0110[5] will be set to 1. +* host2mcu_sw_int_6_set[6] - (WO) Driver set [0x0_4108] bit[6] to generate +* MCU interrupt and 0x5000_0110[6] will be set to 1. +* host2mcu_sw_int_7_set[7] - (WO) Driver set [0x0_4108] bit[7] to generate +* MCU interrupt and 0x5000_0110[7] will be set to 1. +* RESERVED8[31..8] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_7_set_ADDR \ +WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_7_set_MASK \ +0x00000080 /* host2mcu_sw_int_7_set[7] */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_7_set_SHFT 7 +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_6_set_ADDR \ +WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_6_set_MASK \ +0x00000040 /* host2mcu_sw_int_6_set[6] */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_6_set_SHFT 6 +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_5_set_ADDR \ +WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_5_set_MASK \ +0x00000020 /* host2mcu_sw_int_5_set[5] */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_5_set_SHFT 5 +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_4_set_ADDR \ +WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_4_set_MASK \ +0x00000010 /* host2mcu_sw_int_4_set[4] */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_4_set_SHFT 4 +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_3_set_ADDR \ +WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_3_set_MASK \ +0x00000008 /* host2mcu_sw_int_3_set[3] */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_3_set_SHFT 3 +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_2_set_ADDR \ +WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_2_set_MASK \ +0x00000004 /* host2mcu_sw_int_2_set[2] */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_2_set_SHFT 2 +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_1_set_ADDR \ +WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_1_set_MASK \ +0x00000002 /* host2mcu_sw_int_1_set[1] */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_1_set_SHFT 1 +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_0_set_ADDR \ +WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_0_set_MASK \ +0x00000001 /* host2mcu_sw_int_0_set[0] */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_0_set_SHFT 0 + +/* +* ---MCU2HOST_SW_INT_SET (0x18024000 + 0x10C)--- +* mcu2host_sw_int_set_0[0] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[0] to check +* interrupt status +* mcu2host_sw_int_set_1[1] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[1] to check +* interrupt status +* mcu2host_sw_int_set_2[2] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[2] to check +* interrupt status +* mcu2host_sw_int_set_3[3] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[3] to check +* interrupt status +* mcu2host_sw_int_set_4[4] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[4] to check +* interrupt status +* mcu2host_sw_int_set_5[5] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[5] to check +* interrupt status +* mcu2host_sw_int_set_6[6] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[6] to check +* interrupt status +* mcu2host_sw_int_set_7[7] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[7] to check +* interrupt status +* mcu2host_sw_int_set_8[8] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[0] to check +* interrupt status +* mcu2host_sw_int_set_9[9] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[1] to check +* interrupt status +* mcu2host_sw_int_set_10[10] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[2] to check +* interrupt status +* mcu2host_sw_int_set_11[11] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[3] to check +* interrupt status +* mcu2host_sw_int_set_12[12] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[4] to check +* interrupt status +* mcu2host_sw_int_set_13[13] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[5] to check +* interrupt status +* mcu2host_sw_int_set_14[14] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[6] to check +* interrupt status +* mcu2host_sw_int_set_15[15] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[7] to check +* interrupt status +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_15_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_15_MASK \ +0x00008000 /* mcu2host_sw_int_set_15[15] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_15_SHFT 15 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_14_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_14_MASK \ +0x00004000 /* mcu2host_sw_int_set_14[14] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_14_SHFT 14 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_13_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_13_MASK \ +0x00002000 /* mcu2host_sw_int_set_13[13] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_13_SHFT 13 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_12_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_12_MASK \ +0x00001000 /* mcu2host_sw_int_set_12[12] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_12_SHFT 12 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_11_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_11_MASK \ +0x00000800 /* mcu2host_sw_int_set_11[11] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_11_SHFT 11 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_10_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_10_MASK \ +0x00000400 /* mcu2host_sw_int_set_10[10] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_10_SHFT 10 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_9_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_9_MASK \ +0x00000200 /* mcu2host_sw_int_set_9[9] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_9_SHFT 9 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_8_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_8_MASK \ +0x00000100 /* mcu2host_sw_int_set_8[8] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_8_SHFT 8 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_7_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_7_MASK \ +0x00000080 /* mcu2host_sw_int_set_7[7] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_7_SHFT 7 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_6_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_6_MASK \ +0x00000040 /* mcu2host_sw_int_set_6[6] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_6_SHFT 6 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_5_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_5_MASK \ +0x00000020 /* mcu2host_sw_int_set_5[5] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_5_SHFT 5 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_4_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_4_MASK \ +0x00000010 /* mcu2host_sw_int_set_4[4] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_4_SHFT 4 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_3_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_3_MASK \ +0x00000008 /* mcu2host_sw_int_set_3[3] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_2_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_2_MASK \ +0x00000004 /* mcu2host_sw_int_set_2[2] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_1_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_1_MASK \ +0x00000002 /* mcu2host_sw_int_set_1[1] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_0_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_0_MASK \ +0x00000001 /* mcu2host_sw_int_set_0[0] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_0_SHFT 0 + +/* +* ---MCU_INT_STA (0x18024000 + 0X110)--- +* host2mcu_sw_int_sts[7..0] - (W1C) MCU interrupt status, write 1 to clear +* the interrupt +* wpdma_tx_timeout_int_sts[8] - (W1C) WPDMA TX dma timeout interrupt stauts, +* write 1 to clear the interrupt +* wpdma_rx_timeout_int_sts[9] - (W1C) WPDMA RX dma timeout interrupt stauts, +* write 1 to clear the interrupt +* wifi_txfifo0_wr_ovf_int_sts[10] - (W1C) conn_hif txfifo erorr detec +* interruptt. It indicate tx-fifo memory write overflow. +* wifi_txfifo1_wr_ovf_int_sts[11] - (W1C) conn_hif txfifo erorr detec +* interruptt. It indicate tx-fifo memory write overflow. +* wifi_rxfifo_wr_ovf_int_sts[12] - (W1C) conn_hif rxfifo erorr detect +* interrupt. It indicate rx-fifo memory write overflow. +* wpdma_tx_dmad_mem_range_err_mcu_int_sts[13] - (W1C) WPDMA tx dma descriptor +* memory range error detection mcu interrupt status +* When user setup WPDMA_TX_DMAD_RNG (not +* equal to zero), design would check tx_dmad address. If address range not +* correct, it would alarm memory range error interrupt +* wpdma_rx_dmad_mem_range_err_mcu_int_sts[14] - (W1C) WPDMA rx dma descriptor +* memory range error detection mcu interrupt status +* When user setup WPDMA_RX_DMAD_RNG (not +* equal to zero), design would check rx_dmad address. If address range not +* correct, it would alarm memory range error interrupt +* wpdma_tx_payload_mem_range_err_mcu_int_sts[15] - (W1C) WPDMA tx payload +* memory range error detection mcu interrupt status +* When user setup WPDMA_TX_PLD_RNG (not equal +* to zero), design would check tx_dma payload address. If address range not +* correct, it would alarm memory range error interrupt +* wpdma_rx_payload_mem_range_err_mcu_int_sts[16] - (W1C) WPDMA rx payload +* memory range error detection mcu interrupt status +* When user setup WPDMA_RX_PLD_RNG (not equal +* to zero), design would check rx_dma payload address. If address range not +* correct, it would alarm memory range error interrupt +* RESERVED17[31..17] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_payload_mem_range_err_mcu_int_sts_ADDR \ + \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_payload_mem_range_err_mcu_int_sts_MASK \ + \ +0x00010000 /* wpdma_rx_payload_mem_range_err_mcu_int_sts[16] */ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_payload_mem_range_err_mcu_int_sts_SHFT \ + \ +16 +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_payload_mem_range_err_mcu_int_sts_ADDR \ + \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_payload_mem_range_err_mcu_int_sts_MASK \ + \ +0x00008000 /* wpdma_tx_payload_mem_range_err_mcu_int_sts[15] */ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_payload_mem_range_err_mcu_int_sts_SHFT \ + \ +15 +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_dmad_mem_range_err_mcu_int_sts_ADDR \ + \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_dmad_mem_range_err_mcu_int_sts_MASK \ + \ +0x00004000 /* wpdma_rx_dmad_mem_range_err_mcu_int_sts[14] */ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_dmad_mem_range_err_mcu_int_sts_SHFT \ + \ +14 +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_dmad_mem_range_err_mcu_int_sts_ADDR \ + \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_dmad_mem_range_err_mcu_int_sts_MASK \ + \ +0x00002000 /* wpdma_tx_dmad_mem_range_err_mcu_int_sts[13] */ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_dmad_mem_range_err_mcu_int_sts_SHFT \ + \ +13 +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_rxfifo_wr_ovf_int_sts_ADDR \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_rxfifo_wr_ovf_int_sts_MASK \ +0x00001000 /* wifi_rxfifo_wr_ovf_int_sts[12] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_rxfifo_wr_ovf_int_sts_SHFT 12 +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_txfifo1_wr_ovf_int_sts_ADDR \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_txfifo1_wr_ovf_int_sts_MASK \ +0x00000800 /* wifi_txfifo1_wr_ovf_int_sts[11] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_txfifo1_wr_ovf_int_sts_SHFT 11 +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_txfifo0_wr_ovf_int_sts_ADDR \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_txfifo0_wr_ovf_int_sts_MASK \ +0x00000400 /* wifi_txfifo0_wr_ovf_int_sts[10] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_txfifo0_wr_ovf_int_sts_SHFT 10 +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_timeout_int_sts_ADDR \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_timeout_int_sts_MASK \ +0x00000200 /* wpdma_rx_timeout_int_sts[9] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_timeout_int_sts_SHFT 9 +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_timeout_int_sts_ADDR \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_timeout_int_sts_MASK \ +0x00000100 /* wpdma_tx_timeout_int_sts[8] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_timeout_int_sts_SHFT 8 +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_host2mcu_sw_int_sts_ADDR \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_host2mcu_sw_int_sts_MASK \ +0x000000FF /* host2mcu_sw_int_sts[7..0] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_host2mcu_sw_int_sts_SHFT 0 + +/* +* ---MCU_INT_ENA (0x18024000 + 0X114)--- +* host2mcu_sw_int_ena[7..0] - (RW) host2mcu interrupt enable +* wpdma_tx_dma_timeout_int_ena[8] - (RW) WPDMA TX error detection interrupt +enable +* wpdma_rx_dma_timeout_int_ena[9] - (RW) WPDMA RX error detection interrupt +enable +* wifi_txfifo0_wr_ovf_int_ena[10] - (RW) conn_hif txfifo erorr detect +* interrupt enable. +* wifi_txfifo1_wr_ovf_int_ena[11] - (RW) conn_hif txfifo erorr detect +* interrupt enable. +* wifi_rxfifo_wr_ovf_int_ena[12] - (RW) conn_hif rxfifo erorr detect interrupt +enable. +* wpdma_tx_dmad_mem_range_err_mcu_int_ena[13] - (RW) WPDMA tx dma descriptor +* memory range error detection interrupt enable +* wpdma_rx_dmad_mem_range_err_mcu_int_ena[14] - (RW) WPDMA rx dma descriptor +* memory range error detection interrupt enable +* wpdma_tx_payload_mem_range_err_mcu_int_ena[15] - (RW) WPDMA tx payload +* memory range error detection interrupt enable +* wpdma_rx_payload_mem_range_err_mcu_int_ena[16] - (RW) WPDMA rx payload +* memory range error detection interrupt enable +* RESERVED17[31..17] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_payload_mem_range_err_mcu_int_ena_ADDR \ + \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_payload_mem_range_err_mcu_int_ena_MASK \ + \ +0x00010000 /* wpdma_rx_payload_mem_range_err_mcu_int_ena[16] */ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_payload_mem_range_err_mcu_int_ena_SHFT \ + \ +16 +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_payload_mem_range_err_mcu_int_ena_ADDR \ + \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_payload_mem_range_err_mcu_int_ena_MASK \ + \ +0x00008000 /* wpdma_tx_payload_mem_range_err_mcu_int_ena[15] */ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_payload_mem_range_err_mcu_int_ena_SHFT \ + \ +15 +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_dmad_mem_range_err_mcu_int_ena_ADDR \ + \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_dmad_mem_range_err_mcu_int_ena_MASK \ + \ +0x00004000 /* wpdma_rx_dmad_mem_range_err_mcu_int_ena[14] */ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_dmad_mem_range_err_mcu_int_ena_SHFT \ + \ +14 +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_dmad_mem_range_err_mcu_int_ena_ADDR \ + \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_dmad_mem_range_err_mcu_int_ena_MASK \ + \ +0x00002000 /* wpdma_tx_dmad_mem_range_err_mcu_int_ena[13] */ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_dmad_mem_range_err_mcu_int_ena_SHFT \ + \ +13 +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_rxfifo_wr_ovf_int_ena_ADDR \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_rxfifo_wr_ovf_int_ena_MASK \ +0x00001000 /* wifi_rxfifo_wr_ovf_int_ena[12] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_rxfifo_wr_ovf_int_ena_SHFT 12 +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_txfifo1_wr_ovf_int_ena_ADDR \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_txfifo1_wr_ovf_int_ena_MASK \ +0x00000800 /* wifi_txfifo1_wr_ovf_int_ena[11] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_txfifo1_wr_ovf_int_ena_SHFT 11 +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_txfifo0_wr_ovf_int_ena_ADDR \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_txfifo0_wr_ovf_int_ena_MASK \ +0x00000400 /* wifi_txfifo0_wr_ovf_int_ena[10] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_txfifo0_wr_ovf_int_ena_SHFT 10 +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_dma_timeout_int_ena_ADDR \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_dma_timeout_int_ena_MASK \ +0x00000200 /* wpdma_rx_dma_timeout_int_ena[9] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_dma_timeout_int_ena_SHFT 9 +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_dma_timeout_int_ena_ADDR \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_dma_timeout_int_ena_MASK \ +0x00000100 /* wpdma_tx_dma_timeout_int_ena[8] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_dma_timeout_int_ena_SHFT 8 +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_host2mcu_sw_int_ena_ADDR \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_host2mcu_sw_int_ena_MASK \ +0x000000FF /* host2mcu_sw_int_ena[7..0] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_host2mcu_sw_int_ena_SHFT 0 + +/* +* ---CONN_HIF_DUMMY (0x18024000 + 0x120)--- +* CONN_HIF_DUMMY[31..0] - (RW) Reserved CR, SE will use it for pcie +calibration! +*/ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DUMMY_CONN_HIF_DUMMY_ADDR \ +WF_WFDMA_HOST_DMA0_CONN_HIF_DUMMY_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DUMMY_CONN_HIF_DUMMY_MASK \ +0xFFFFFFFF /* CONN_HIF_DUMMY[31..0] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DUMMY_CONN_HIF_DUMMY_SHFT 0 + +/* +* ---WPDMA_DBG_IDX (0x18024000 + 0x124)--- +* PDMA_DBG_IDX[7..0] - (RW) PDMA debug index +* PDMA_DBG_Enable[8] - (RW) PDMA Debug Enable +* 0: PDMA_DBG_port would has no function +* 1 : PDMA DBG_IDX select PDMA debug flag +index +* RESERVED9[31..9] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_PDMA_DBG_Enable_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_PDMA_DBG_Enable_MASK \ +0x00000100 /* PDMA_DBG_Enable[8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_PDMA_DBG_Enable_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_PDMA_DBG_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_PDMA_DBG_IDX_MASK \ +0x000000FF /* PDMA_DBG_IDX[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_PDMA_DBG_IDX_SHFT 0 + +/* +* ---WPDMA_DBG_PROBE (0x18024000 + 0x128)--- +* PDMA_DBG_PROBE[31..0] - (RO) PDMA Debug probe read +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_PROBE_PDMA_DBG_PROBE_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_DBG_PROBE_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_PROBE_PDMA_DBG_PROBE_MASK \ +0xFFFFFFFF /* PDMA_DBG_PROBE[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_PROBE_PDMA_DBG_PROBE_SHFT 0 + +/* +* ---CONN_HIF_DBG_IDX (0x18024000 + 0x12C)--- +* conn_hif_dbg_byt0_sel[2..0] - (RW) conn_hif_dbg_byt0_sel : Select +* conn_hif_dbg[7:0] from "pdma_dbg"/"hif_dmashdl_top" +* conn_hif_dbg_byt1_sel[5..3] - (RW) conn_hif_dbg_byt1_sel : Select +* conn_hif_dbg[15:8] from "pdma_dbg"/"hif_dmashdl_top" +* conn_hif_dbg_byt2_sel[8..6] - (RW) conn_hif_dbg_byt2_sel : Select +* conn_hif_dbg[23:16] from "pdma_dbg"/"hif_dmashdl_top" +* conn_hif_dbg_byt3_sel[11..9] - (RW) conn_hif_dbg_byt3_sel : Select +* conn_hif_dbg[31:24] from "pdma_dbg"/"hif_dmashdl_top" +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt3_sel_ADDR \ +WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt3_sel_MASK \ +0x00000E00 /* conn_hif_dbg_byt3_sel[11..9] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt3_sel_SHFT 9 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt2_sel_ADDR \ +WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt2_sel_MASK \ +0x000001C0 /* conn_hif_dbg_byt2_sel[8..6] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt2_sel_SHFT 6 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt1_sel_ADDR \ +WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt1_sel_MASK \ +0x00000038 /* conn_hif_dbg_byt1_sel[5..3] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt1_sel_SHFT 3 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt0_sel_ADDR \ +WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt0_sel_MASK \ +0x00000007 /* conn_hif_dbg_byt0_sel[2..0] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt0_sel_SHFT 0 + +/* +* ---CONN_HIF_DBG_PROBE (0x18024000 + 0x130)--- +* conn_hif_dbg_probe[31..0] - (RO) conn_hif_dbg_probe read +*/ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_PROBE_conn_hif_dbg_probe_ADDR \ +WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_PROBE_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_PROBE_conn_hif_dbg_probe_MASK \ +0xFFFFFFFF /* conn_hif_dbg_probe[31..0] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_PROBE_conn_hif_dbg_probe_SHFT 0 + +/* +* ---CONN_HIF_DMASHDL_DBG_PROBE (0x18024000 + 0x134)--- +* DMASHDL_DBG_PROBE[15..0] - (RO) conn_hif_dmashdl_dbg_probe read +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DMASHDL_DBG_PROBE_DMASHDL_DBG_PROBE_ADDR \ +WF_WFDMA_HOST_DMA0_CONN_HIF_DMASHDL_DBG_PROBE_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DMASHDL_DBG_PROBE_DMASHDL_DBG_PROBE_MASK \ +0x0000FFFF /* DMASHDL_DBG_PROBE[15..0] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DMASHDL_DBG_PROBE_DMASHDL_DBG_PROBE_SHFT 0 + +/* +* ---CONN_HIF_BUSY_STATUS (0x18024000 + 0x138)--- +* conn_hif_txfifo0_busy[0] - (RO) conn_hif txfifo0 busy status +* 0 : txfifo empty +* 1 : txfifo non empty +* conn_hif_txfifo1_busy[1] - (RO) conn_hif txfifo1 busy status +* 0 : txfifo empty +* 1 : txfifo non empty +* conn_hif_rxfifo_busy[2] - (RO) conn_hif rxfifo busy status +* 0 : rxfifo empty +* 1 : rxfifo non empty +* RESERVED[30..3] - (RO) Reserved CR +* conn_hif_busy[31] - (RO) Over all conn_hif busy status, it was +* busy summation of bit[6] ~ bit[0] status +*/ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_busy_ADDR \ +WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_busy_MASK \ +0x80000000 /* conn_hif_busy[31] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_busy_SHFT 31 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_rxfifo_busy_ADDR \ +WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_rxfifo_busy_MASK \ +0x00000004 /* conn_hif_rxfifo_busy[2] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_rxfifo_busy_SHFT 2 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_txfifo1_busy_ADDR \ +WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_txfifo1_busy_MASK \ +0x00000002 /* conn_hif_txfifo1_busy[1] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_txfifo1_busy_SHFT 1 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_txfifo0_busy_ADDR \ +WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_txfifo0_busy_MASK \ +0x00000001 /* conn_hif_txfifo0_busy[0] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_txfifo0_busy_SHFT 0 + +/* +* ---CONN_HIF_BUSY_ENA (0x18024000 + 0x13c)--- +* conn_hif_txfifo0_busy_enable[0] - (RW) busy enable control +* 0: ignore busy status +* 1: conn_hif_busy would tack care busy +status +* conn_hif_txfifo1_busy_enable[1] - (RW) busy enable control +* 0: ignore busy status +* 1: conn_hif_busy would tack care busy +status +* conn_hif_rxfifo_busy_enable[2] - (RW) busy enable control +* 0: ignore busy status +* 1: conn_hif_busy would tack care busy +status +* RESERVED3[4..3] - (RO) Reserved bits +* RESERVED[31..5] - (RW) Reserved CR +*/ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_rxfifo_busy_enable_ADDR\ +WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_rxfifo_busy_enable_MASK\ +0x00000004 /* conn_hif_rxfifo_busy_enable[2] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_rxfifo_busy_enable_SHFT 2 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_txfifo1_busy_enable_ADDR \ +WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_txfifo1_busy_enable_MASK \ +0x00000002 /* conn_hif_txfifo1_busy_enable[1] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_txfifo1_busy_enable_SHFT 1 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_txfifo0_busy_enable_ADDR \ +WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_txfifo0_busy_enable_MASK \ +0x00000001 /* conn_hif_txfifo0_busy_enable[0] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_txfifo0_busy_enable_SHFT 0 + +/* +* ---CONN_HIF_FIFO_TEST_MOD (0x18024000 + 0x140)--- +* csr_wfdma_loopback_en[0] - (RW) conn_hif fifo loopback enable +* NOTICE : when loopback, OMIT_TX_INFO and +* OMIT_RX_INFO sould be both set to 1'b1 +* csr_wfdma_loopback_qsel[2..1] - (RW) No USE for (conn_hif fifo loopback +* packet go into Rx-ring number) +* RESERVED3[31..3] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_qsel_ADDR \ +WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_qsel_MASK \ +0x00000006 /* csr_wfdma_loopback_qsel[2..1] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_qsel_SHFT 1 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_en_ADDR \ +WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_en_MASK \ +0x00000001 /* csr_wfdma_loopback_en[0] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_en_SHFT 0 + +/* +* ---WPDMA2HOST_ERR_INT_STA (0x18024000 + 0x1E8)--- +* wpdma_tx_timeout_int_sts[0] - (W1C) WPDMA TX error detection interrupt +* stauts, write 1 to clear the interrupt +* wpdma_rx_timeout_int_sts[1] - (W1C) WPDMA RX error detection interrupt +* stauts, write 1 to clear the interrupt +* RESERVED2[31..2] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_rx_timeout_int_sts_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_rx_timeout_int_sts_MASK \ + \ +0x00000002 /* wpdma_rx_timeout_int_sts[1] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_rx_timeout_int_sts_SHFT \ + \ +1 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_tx_timeout_int_sts_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_tx_timeout_int_sts_MASK \ + \ +0x00000001 /* wpdma_tx_timeout_int_sts[0] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_tx_timeout_int_sts_SHFT \ + \ +0 + +/* +* ---WPDMA2HOST_ERR_INT_ENA (0x18024000 + 0x1EC)--- +* wpdma_rx_timeout_int_ena[0] - (RW) WPDMA TX error detection interrupt +enable +* wpdma_tx_timeout_int_ena[1] - (RW) WPDMA RX error detection interrupt +enable +* RESERVED2[31..2] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_timeout_int_ena_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_timeout_int_ena_MASK \ + \ +0x00000002 /* wpdma_tx_timeout_int_ena[1] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_timeout_int_ena_SHFT \ + \ +1 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_timeout_int_ena_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_timeout_int_ena_MASK \ + \ +0x00000001 /* wpdma_rx_timeout_int_ena[0] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_timeout_int_ena_SHFT \ + \ +0 + +/* +* ---MCU2HOST_SW_INT_STA (0x18024000 + 0x1F0)--- +* mcu2host_sw_int_0[0] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_1[1] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_2[2] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_3[3] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_4[4] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_5[5] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_6[6] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_7[7] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_8[8] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_9[9] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_10[10] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_11[11] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_12[12] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_13[13] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_14[14] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_15[15] - (W1C) mcu2host interrupt status +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_15_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_15_MASK \ +0x00008000 /* mcu2host_sw_int_15[15] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_15_SHFT 15 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_14_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_14_MASK \ +0x00004000 /* mcu2host_sw_int_14[14] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_14_SHFT 14 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_13_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_13_MASK \ +0x00002000 /* mcu2host_sw_int_13[13] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_13_SHFT 13 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_12_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_12_MASK \ +0x00001000 /* mcu2host_sw_int_12[12] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_12_SHFT 12 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_11_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_11_MASK \ +0x00000800 /* mcu2host_sw_int_11[11] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_11_SHFT 11 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_10_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_10_MASK \ +0x00000400 /* mcu2host_sw_int_10[10] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_10_SHFT 10 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_9_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_9_MASK \ +0x00000200 /* mcu2host_sw_int_9[9] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_9_SHFT 9 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_8_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_8_MASK \ +0x00000100 /* mcu2host_sw_int_8[8] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_8_SHFT 8 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_7_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_7_MASK \ +0x00000080 /* mcu2host_sw_int_7[7] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_7_SHFT 7 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_6_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_6_MASK \ +0x00000040 /* mcu2host_sw_int_6[6] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_6_SHFT 6 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_5_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_5_MASK \ +0x00000020 /* mcu2host_sw_int_5[5] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_5_SHFT 5 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_4_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_4_MASK \ +0x00000010 /* mcu2host_sw_int_4[4] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_4_SHFT 4 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_3_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_3_MASK \ +0x00000008 /* mcu2host_sw_int_3[3] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_2_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_2_MASK \ +0x00000004 /* mcu2host_sw_int_2[2] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_1_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_1_MASK \ +0x00000002 /* mcu2host_sw_int_1[1] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_0_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_0_MASK \ +0x00000001 /* mcu2host_sw_int_0[0] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_0_SHFT 0 + +/* +* ---MCU2HOST_SW_INT_ENA (0x18024000 + 0x1F4)--- +* mcu2host_int_ena_0[0] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_1[1] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_2[2] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_3[3] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_4[4] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_5[5] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_6[6] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_7[7] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_8[8] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_9[9] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_10[10] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_11[11] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_12[12] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_13[13] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_14[14] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_15[15] - (RW) MCU2HOST software interrupt interrupt +enable +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_15_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_15_MASK \ +0x00008000 /* mcu2host_int_ena_15[15] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_15_SHFT 15 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_14_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_14_MASK \ +0x00004000 /* mcu2host_int_ena_14[14] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_14_SHFT 14 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_13_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_13_MASK \ +0x00002000 /* mcu2host_int_ena_13[13] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_13_SHFT 13 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_12_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_12_MASK \ +0x00001000 /* mcu2host_int_ena_12[12] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_12_SHFT 12 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_11_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_11_MASK \ +0x00000800 /* mcu2host_int_ena_11[11] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_11_SHFT 11 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_10_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_10_MASK \ +0x00000400 /* mcu2host_int_ena_10[10] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_10_SHFT 10 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_9_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_9_MASK \ +0x00000200 /* mcu2host_int_ena_9[9] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_9_SHFT 9 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_8_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_8_MASK \ +0x00000100 /* mcu2host_int_ena_8[8] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_8_SHFT 8 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_7_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_7_MASK \ +0x00000080 /* mcu2host_int_ena_7[7] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_7_SHFT 7 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_6_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_6_MASK \ +0x00000040 /* mcu2host_int_ena_6[6] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_6_SHFT 6 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_5_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_5_MASK \ +0x00000020 /* mcu2host_int_ena_5[5] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_5_SHFT 5 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_4_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_4_MASK \ +0x00000010 /* mcu2host_int_ena_4[4] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_4_SHFT 4 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_3_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_3_MASK \ +0x00000008 /* mcu2host_int_ena_3[3] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_2_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_2_MASK \ +0x00000004 /* mcu2host_int_ena_2[2] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_1_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_1_MASK \ +0x00000002 /* mcu2host_int_ena_1[1] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_0_ADDR \ +WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_0_MASK \ +0x00000001 /* mcu2host_int_ena_0[0] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_0_SHFT 0 + +/* +* ---SUBSYS2HOST_INT_STA (0x18024000 + 0x1F8)--- +* mac_int_sts_0[0] - (RO) MAC interrupt 0: Band0 TBTT +* interrupt(Check wf_int_wakeup_top/hwisr0 [0x820Fc03c]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_1[1] - (RO) MAC interrupt 1: Band0 Pre-TBTT +* interrupt(Check wf_int_wakeup_top/hwisr1 [0x820Fc044]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_2[2] - (RO) MAC interrupt 2: Band0 TX status +* interrupt(Check wf_int_wakeup_top/hwisr2 [0x820Fc04c]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_3[3] - (RO) MAC interrupt 3: Band0 Auto wakeup +* interrupt (Check wf_int_wakeup_top/hwisr3 [0x820Fc054]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_4[4] - (RO) MAC interrupt 4: Band0 GP timer +* interrupt (Check wf_int_wakeup_top/hwisr4 [0x820Fc05c]) +* 0 : no interrupt +* 1 : interrupt assert +* RESERVED5[7..5] - (RO) Reserved bits +* conn_hif_on_host_int_sts[8] - (RO) CONN_HIF_ON interrupt enable +* 0 : no conn_hif_on_host_int interrupt +* 1 : conn_hif_on_host_int interrupt assert. +* User should check conn_hif_on (host_csr) interrupt status and clear interrupt. +* conn2ap_sw_irq_sts[9] - (RO) MCUSYS conn2ap_sw_irq status (Check +* conn_mcu_config/EMI_CTL [0x80000150] bit[4:0]) +* 0 : no conn2ap_sw_irq interrupt. +* 1 : conn2ap_sw_irq interrupt assert. User +* should check mcusys_n9 interrupt status and clear interrupt. +* (conn_mcu_config/EMI_CTL [0x80000150] bit[4:0] != 0) +* dmashdl_int_sts[10] - (RO) DMASHDL error interrupt +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_5[11] - (RO) MAC interrupt 5: Band1 TBTT +* interrupt(Check wf_int_wakeup_top/hwisr0 [0x820Fc03c]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_6[12] - (RO) MAC interrupt 6: Band1 Pre-TBTT +* interrupt(Check wf_int_wakeup_top/hwisr1 [0x820Fc044]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_7[13] - (RO) MAC interrupt 7: Band1 TX status +* interrupt(Check wf_int_wakeup_top/hwisr2 [0x820Fc04c]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_8[14] - (RO) MAC interrupt 8: Band1 Auto wakeup +* interrupt (Check wf_int_wakeup_top/hwisr3 [0x820Fc054]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_9[15] - (RO) MAC interrupt 9: Band1 GP timer +* interrupt (Check wf_int_wakeup_top/hwisr4 [0x820Fc05c]) +* 0 : no interrupt +* 1 : interrupt assert +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_9_ADDR \ +WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_9_MASK \ +0x00008000 /* mac_int_sts_9[15] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_9_SHFT 15 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_8_ADDR \ +WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_8_MASK \ +0x00004000 /* mac_int_sts_8[14] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_8_SHFT 14 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_7_ADDR \ +WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_7_MASK \ +0x00002000 /* mac_int_sts_7[13] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_7_SHFT 13 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_6_ADDR \ +WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_6_MASK \ +0x00001000 /* mac_int_sts_6[12] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_6_SHFT 12 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_5_ADDR \ +WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_5_MASK \ +0x00000800 /* mac_int_sts_5[11] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_5_SHFT 11 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_dmashdl_int_sts_ADDR \ +WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_dmashdl_int_sts_MASK \ +0x00000400 /* dmashdl_int_sts[10] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_dmashdl_int_sts_SHFT 10 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_conn2ap_sw_irq_sts_ADDR \ +WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_conn2ap_sw_irq_sts_MASK \ +0x00000200 /* conn2ap_sw_irq_sts[9] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_conn2ap_sw_irq_sts_SHFT 9 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_conn_hif_on_host_int_sts_ADDR \ +WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_conn_hif_on_host_int_sts_MASK \ +0x00000100 /* conn_hif_on_host_int_sts[8] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_conn_hif_on_host_int_sts_SHFT 8 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_4_ADDR \ +WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_4_MASK \ +0x00000010 /* mac_int_sts_4[4] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_4_SHFT 4 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_3_ADDR \ +WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_3_MASK \ +0x00000008 /* mac_int_sts_3[3] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_2_ADDR \ +WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_2_MASK \ +0x00000004 /* mac_int_sts_2[2] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_1_ADDR \ +WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_1_MASK \ +0x00000002 /* mac_int_sts_1[1] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_0_ADDR \ +WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_0_MASK \ +0x00000001 /* mac_int_sts_0[0] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_0_SHFT 0 + +/* +* ---SUBSYS2HOST_INT_ENA (0x18024000 + 0x1FC)--- +* mac_int_ena_0[0] - (RW) MAC interrupt enable +* mac_int_ena_1[1] - (RW) MAC interrupt enable +* mac_int_ena_2[2] - (RW) MAC interrupt enable +* mac_int_ena_3[3] - (RW) MAC interrupt enable +* mac_int_ena_4[4] - (RW) MAC interrupt enable +* RESERVED5[7..5] - (RO) Reserved bits +* conn_hif_on_host_int_ena[8] - (RW) CONN_HIF_ON interrupt enable +* conn2ap_sw_irq_ena[9] - (RW) MCUSYS conn2ap_sw_irq enable +* dmashdl_int_ena[10] - (RW) DMASHDL interrupt enable +* mac_int_ena_5[11] - (RW) MAC interrupt enable +* mac_int_ena_6[12] - (RW) MAC interrupt enable +* mac_int_ena_7[13] - (RW) MAC interrupt enable +* mac_int_ena_8[14] - (RW) MAC interrupt enable +* mac_int_ena_9[15] - (RW) MAC interrupt enable +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_9_ADDR \ +WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_9_MASK \ +0x00008000 /* mac_int_ena_9[15] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_9_SHFT 15 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_8_ADDR \ +WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_8_MASK \ +0x00004000 /* mac_int_ena_8[14] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_8_SHFT 14 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_7_ADDR \ +WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_7_MASK \ +0x00002000 /* mac_int_ena_7[13] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_7_SHFT 13 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_6_ADDR \ +WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_6_MASK \ +0x00001000 /* mac_int_ena_6[12] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_6_SHFT 12 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_5_ADDR \ +WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_5_MASK \ +0x00000800 /* mac_int_ena_5[11] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_5_SHFT 11 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_dmashdl_int_ena_ADDR \ +WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_dmashdl_int_ena_MASK \ +0x00000400 /* dmashdl_int_ena[10] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_dmashdl_int_ena_SHFT 10 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_conn2ap_sw_irq_ena_ADDR \ +WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_conn2ap_sw_irq_ena_MASK \ +0x00000200 /* conn2ap_sw_irq_ena[9] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_conn2ap_sw_irq_ena_SHFT 9 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_conn_hif_on_host_int_ena_ADDR \ +WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_conn_hif_on_host_int_ena_MASK \ +0x00000100 /* conn_hif_on_host_int_ena[8] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_conn_hif_on_host_int_ena_SHFT 8 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_4_ADDR \ +WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_4_MASK \ +0x00000010 /* mac_int_ena_4[4] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_4_SHFT 4 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_3_ADDR \ +WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_3_MASK \ +0x00000008 /* mac_int_ena_3[3] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_2_ADDR \ +WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_2_MASK \ +0x00000004 /* mac_int_ena_2[2] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_1_ADDR \ +WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_1_MASK \ +0x00000002 /* mac_int_ena_1[1] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_0_ADDR \ +WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_0_MASK \ +0x00000001 /* mac_int_ena_0[0] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_0_SHFT 0 + +/* +* ---HOST_INT_STA (0x18024000 + 0x200)--- +* rx_done_int_sts_0[0] - (W1C) RX Queue#0 packet receive interrupt +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* rx_done_int_sts_1[1] - (W1C) RX Queue#1 packet receive interrupt +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* rx_done_int_sts_2[2] - (W1C) RX Queue#2 packet receive interrupt +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* rx_done_int_sts_3[3] - (W1C) RX Queue#3 packet receive interrupt +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* tx_done_int_sts_0[4] - (W1C) TX Queue#0 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_1[5] - (W1C) TX Queue#1 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_2[6] - (W1C) TX Queue#2 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_3[7] - (W1C) TX Queue#3 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_4[8] - (W1C) TX Queue#4 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_5[9] - (W1C) TX Queue#5 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_6[10] - (W1C) TX Queue#6 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_7[11] - (W1C) TX Queue#7 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_8[12] - (W1C) TX Queue#8 packet transmit +* interruptWrite 1 to clear the interrupt +* tx_done_int_sts_9[13] - (W1C) TX Queue#9 packet transmit +* interruptWrite 1 to clear the interrupt +* tx_done_int_sts_10[14] - (W1C) TX Queue#10 packet transmit +* interruptWrite 1 to clear the interrupt +* tx_done_int_sts_11[15] - (W1C) TX Queue#11 packet transmit +* interruptWrite 1 to clear the interrupt +* tx_done_int_sts_12[16] - (W1C) TX Queue#12 packet transmit +* interruptWrite 1 to clear the interrupt +* tx_done_int_sts_13[17] - (W1C) TX Queue#13 packet transmit +* interruptWrite 1 to clear the interrupt +* tx_done_int_sts_14[18] - (W1C) TX Queue#14 packet transmit +* interruptWrite 1 to clear the interrupt +* RESERVED19[19] - (RO) Reserved bits +* rx_coherent_int_sts[20] - (W1C) RX_DMA finds data coherent event when +* checking ddone bit +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* tx_coherent_int_sts[21] - (W1C) TX_DMA finds data coherent event when +* checking ddone bit +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* rx_done_int_sts_4[22] - (W1C) RX Queue#4 packet receive interrupt +* Write 1 to clear the interrupt Read to get the raw interrupt status +* rx_done_int_sts_5[23] - (W1C) RX Queue#5 packet receive interrupt +* Write 1 to clear the interrupt Read to get the raw interrupt status +* wpdma2host_err_int_sts[24] - (RO) wpdma interrupt overall status +* User should should check WPDMA_ERR_INT_STA +* for each wpdma error interrupt status +* Host could read [0x0_41E8] to check +* indivisual wpdma2host_error interrupt status +* RESERVED25[25] - (RO) Reserved bits +* tx_done_int_sts_16[26] - (W1C) TX Queue#16 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_17[27] - (W1C) TX Queue#17 packet transmit interrupt +* Write 1 to clear the interrupt +* subsys_int_sts[28] - (RO) subsys interrupt overall status +* User should should check +* SUBSYS2HOST_INT_STA for each interrupt status +* Host could read [0x0_41F8] to check +* indivisual subsys hw interrupt status +* mcu2host_sw_int_sts[29] - (RO) subsys interrupt overall status +* User should should check +* SUBSYS2HOST_INT_STA for each interrupt status +* Host could read [0x0_41F8] to check +* indivisual subsys hw interrupt status +* tx_done_int_sts_18[30] - (W1C) TX Queue#18 packet transmit interrupt +* Write 1 to clear the interrupt +* RESERVED[31] - (RO) reserved +*/ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_18_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_18_MASK \ +0x40000000 /* tx_done_int_sts_18[30] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_18_SHFT 30 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_mcu2host_sw_int_sts_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_mcu2host_sw_int_sts_MASK \ +0x20000000 /* mcu2host_sw_int_sts[29] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_mcu2host_sw_int_sts_SHFT 29 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_subsys_int_sts_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_subsys_int_sts_MASK \ +0x10000000 /* subsys_int_sts[28] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_subsys_int_sts_SHFT 28 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_17_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_17_MASK \ +0x08000000 /* tx_done_int_sts_17[27] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_17_SHFT 27 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_16_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_16_MASK \ +0x04000000 /* tx_done_int_sts_16[26] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_16_SHFT 26 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_wpdma2host_err_int_sts_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_wpdma2host_err_int_sts_MASK \ +0x01000000 /* wpdma2host_err_int_sts[24] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_wpdma2host_err_int_sts_SHFT 24 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_5_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_5_MASK \ +0x00800000 /* rx_done_int_sts_5[23] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_5_SHFT 23 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_4_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_4_MASK \ +0x00400000 /* rx_done_int_sts_4[22] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_4_SHFT 22 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_coherent_int_sts_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_coherent_int_sts_MASK \ +0x00200000 /* tx_coherent_int_sts[21] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_coherent_int_sts_SHFT 21 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_coherent_int_sts_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_coherent_int_sts_MASK \ +0x00100000 /* rx_coherent_int_sts[20] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_coherent_int_sts_SHFT 20 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_14_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_14_MASK \ +0x00040000 /* tx_done_int_sts_14[18] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_14_SHFT 18 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_13_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_13_MASK \ +0x00020000 /* tx_done_int_sts_13[17] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_13_SHFT 17 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_12_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_12_MASK \ +0x00010000 /* tx_done_int_sts_12[16] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_12_SHFT 16 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_11_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_11_MASK \ +0x00008000 /* tx_done_int_sts_11[15] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_11_SHFT 15 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_10_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_10_MASK \ +0x00004000 /* tx_done_int_sts_10[14] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_10_SHFT 14 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_9_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_9_MASK \ +0x00002000 /* tx_done_int_sts_9[13] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_9_SHFT 13 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_8_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_8_MASK \ +0x00001000 /* tx_done_int_sts_8[12] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_8_SHFT 12 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_7_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_7_MASK \ +0x00000800 /* tx_done_int_sts_7[11] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_7_SHFT 11 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_6_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_6_MASK \ +0x00000400 /* tx_done_int_sts_6[10] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_6_SHFT 10 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_5_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_5_MASK \ +0x00000200 /* tx_done_int_sts_5[9] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_5_SHFT 9 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_4_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_4_MASK \ +0x00000100 /* tx_done_int_sts_4[8] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_4_SHFT 8 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_3_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_3_MASK \ +0x00000080 /* tx_done_int_sts_3[7] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_3_SHFT 7 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_2_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_2_MASK \ +0x00000040 /* tx_done_int_sts_2[6] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_2_SHFT 6 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_1_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_1_MASK \ +0x00000020 /* tx_done_int_sts_1[5] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_1_SHFT 5 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_0_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_0_MASK \ +0x00000010 /* tx_done_int_sts_0[4] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_0_SHFT 4 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_3_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_3_MASK \ +0x00000008 /* rx_done_int_sts_3[3] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_2_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_2_MASK \ +0x00000004 /* rx_done_int_sts_2[2] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_1_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_1_MASK \ +0x00000002 /* rx_done_int_sts_1[1] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_0_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_0_MASK \ +0x00000001 /* rx_done_int_sts_0[0] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_0_SHFT 0 + +/* +* ---HOST_INT_ENA (0x18024000 + 0X204)--- +* HOST_RX_DONE_INT_ENA0[0] - (RW) RX Queue#0 packet receive interrupt +* HOST_RX_DONE_INT_ENA1[1] - (RW) RX Queue#1 packet receive interrupt +* HOST_RX_DONE_INT_ENA2[2] - (RW) RX Queue#2 packet receive interrupt +* HOST_RX_DONE_INT_ENA3[3] - (RW) RX Queue#3 packet receive interrupt +* HOST_TX_DONE_INT_ENA0[4] - (RW) TX Queue#0 packet transmit interrupt +* HOST_TX_DONE_INT_ENA1[5] - (RW) TX Queue#1 packet transmit interrupt +* HOST_TX_DONE_INT_ENA2[6] - (RW) TX Queue#2 packet transmit interrupt +* HOST_TX_DONE_INT_ENA3[7] - (RW) TX Queue#3 packet transmit interrupt +* HOST_TX_DONE_INT_ENA4[8] - (RW) TX Queue#4 packet transmit interrupt +* HOST_TX_DONE_INT_ENA5[9] - (RW) TX Queue#5 packet transmit interrupt +* HOST_TX_DONE_INT_ENA6[10] - (RW) TX Queue#6 packet transmit interrupt +* HOST_TX_DONE_INT_ENA7[11] - (RW) TX Queue#7 packet transmit interrupt +* HOST_TX_DONE_INT_ENA8[12] - (RW) TX Queue#8 packet transmit interrupt +* HOST_TX_DONE_INT_ENA9[13] - (RW) TX Queue#9 packet transmit interrupt +* HOST_TX_DONE_INT_ENA10[14] - (RW) TX Queue#10 packet transmit interrupt +* HOST_TX_DONE_INT_ENA11[15] - (RW) TX Queue#11 packet transmit interrupt +* HOST_TX_DONE_INT_ENA12[16] - (RW) TX Queue#12 packet transmit interrupt +* HOST_TX_DONE_INT_ENA13[17] - (RW) TX Queue#13 packet transmit interrupt +* HOST_TX_DONE_INT_ENA14[18] - (RW) TX Queue#14 packet transmit interrupt +* RESERVED19[19] - (RO) Reserved bits +* HOST_RX_COHERENT_EN[20] - (RW) Enable for RX_DMA data coherent +interrupt +* HOST_TX_COHERENT_EN[21] - (RW) Enable for TX_DMA data coherent +interrupt +* HOST_RX_DONE_INT_ENA4[22] - (RW) RX Queue#4 packet receive interrupt +* HOST_RX_DONE_INT_ENA5[23] - (RW) RX Queue#5 packet receive interrupt +* wpdma2host_err_int_ena[24] - (RW) Enable bit of wpdma2host_err_int +* RESERVED[25] - (RO) reserved +* HOST_TX_DONE_INT_ENA16[26] - (RW) TX Queue#16 packet transmit interrupt +* HOST_TX_DONE_INT_ENA17[27] - (RW) TX Queue#17 packet transmit interrupt +* subsys_int_ena[28] - (RW) Enable bit of subsys_int +* mcu2host_sw_int_ena[29] - (RW) Enable bit of mcu2host_sw_int +* HOST_TX_DONE_INT_ENA18[30] - (RW) TX Queue#18 packet transmit interrupt +* RESERVED[31] - (RO) reserved +*/ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA18_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA18_MASK \ +0x40000000 /* HOST_TX_DONE_INT_ENA18[30] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA18_SHFT 30 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_mcu2host_sw_int_ena_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_mcu2host_sw_int_ena_MASK \ +0x20000000 /* mcu2host_sw_int_ena[29] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_mcu2host_sw_int_ena_SHFT 29 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_subsys_int_ena_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_subsys_int_ena_MASK \ +0x10000000 /* subsys_int_ena[28] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_subsys_int_ena_SHFT 28 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA17_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA17_MASK \ +0x08000000 /* HOST_TX_DONE_INT_ENA17[27] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA17_SHFT 27 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA16_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA16_MASK \ +0x04000000 /* HOST_TX_DONE_INT_ENA16[26] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA16_SHFT 26 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_wpdma2host_err_int_ena_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_wpdma2host_err_int_ena_MASK \ +0x01000000 /* wpdma2host_err_int_ena[24] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_wpdma2host_err_int_ena_SHFT 24 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA5_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA5_MASK \ +0x00800000 /* HOST_RX_DONE_INT_ENA5[23] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA5_SHFT 23 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA4_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA4_MASK \ +0x00400000 /* HOST_RX_DONE_INT_ENA4[22] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA4_SHFT 22 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_COHERENT_EN_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_COHERENT_EN_MASK \ +0x00200000 /* HOST_TX_COHERENT_EN[21] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_COHERENT_EN_SHFT 21 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_COHERENT_EN_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_COHERENT_EN_MASK \ +0x00100000 /* HOST_RX_COHERENT_EN[20] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_COHERENT_EN_SHFT 20 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA14_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA14_MASK \ +0x00040000 /* HOST_TX_DONE_INT_ENA14[18] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA14_SHFT 18 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA13_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA13_MASK \ +0x00020000 /* HOST_TX_DONE_INT_ENA13[17] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA13_SHFT 17 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA12_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA12_MASK \ +0x00010000 /* HOST_TX_DONE_INT_ENA12[16] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA12_SHFT 16 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA11_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA11_MASK \ +0x00008000 /* HOST_TX_DONE_INT_ENA11[15] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA11_SHFT 15 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA10_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA10_MASK \ +0x00004000 /* HOST_TX_DONE_INT_ENA10[14] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA10_SHFT 14 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA9_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA9_MASK \ +0x00002000 /* HOST_TX_DONE_INT_ENA9[13] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA9_SHFT 13 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA8_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA8_MASK \ +0x00001000 /* HOST_TX_DONE_INT_ENA8[12] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA8_SHFT 12 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA7_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA7_MASK \ +0x00000800 /* HOST_TX_DONE_INT_ENA7[11] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA7_SHFT 11 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA6_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA6_MASK \ +0x00000400 /* HOST_TX_DONE_INT_ENA6[10] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA6_SHFT 10 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA5_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA5_MASK \ +0x00000200 /* HOST_TX_DONE_INT_ENA5[9] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA5_SHFT 9 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA4_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA4_MASK \ +0x00000100 /* HOST_TX_DONE_INT_ENA4[8] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA4_SHFT 8 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA3_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA3_MASK \ +0x00000080 /* HOST_TX_DONE_INT_ENA3[7] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA3_SHFT 7 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA2_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA2_MASK \ +0x00000040 /* HOST_TX_DONE_INT_ENA2[6] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA2_SHFT 6 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA1_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA1_MASK \ +0x00000020 /* HOST_TX_DONE_INT_ENA1[5] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA1_SHFT 5 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA0_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA0_MASK \ +0x00000010 /* HOST_TX_DONE_INT_ENA0[4] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA0_SHFT 4 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA3_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA3_MASK \ +0x00000008 /* HOST_RX_DONE_INT_ENA3[3] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA2_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA2_MASK \ +0x00000004 /* HOST_RX_DONE_INT_ENA2[2] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA1_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA1_MASK \ +0x00000002 /* HOST_RX_DONE_INT_ENA1[1] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA0_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA0_MASK \ +0x00000001 /* HOST_RX_DONE_INT_ENA0[0] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA0_SHFT 0 + +/* +* ---WPDMA_GLO_CFG (0x18024000 + 0x208)--- +* TX_DMA_EN[0] - (RW)TX_DMA Enable +* 1: Enable TX_DMA, MUST wait until all +* prefetch rings' MAX_CNT(WPDMA_T(R)X_RING*_EXT_CTRL)of DMA including neighbor +* DMA have been configured successfully +* 0: Disable TX_DMA +* TX_DMA_BUSY[1] - (RO)TX_DMA Busy indicator +* 1: TX_DMA is busy +* 0: TX_DMA is not busy +* RX_DMA_EN[2] - (RW)RX_DMA Enable +* 1: Enable RX_DMA, MUST wait until all +* prefetch rings' MAX_CNT(WPDMA_T(R)X_RING*_EXT_CTRL)of DMA including neighbor +* DMA have been configured successfully +* 0: Disable RX_DMA +* RX_DMA_BUSY[3] - (RO)RX_DMA Busy indicator +* 1: RX_DMA is busy +* 0: RX_DMA is not busy +* PDMA_BT_SIZE[5..4] - (RW)Define the burst size of WPDMA +* 2'h0 : 4 DWORD (16bytes) +* 2'h1 : 8 DWORD (32 bytes) +* 2'h2 : 16 DWORD (64 bytes) +* 2'h3 : 32 DWORD (128 bytes) +* TX_WB_DDONE[6] - (RW)1'b1 : TX engine will wait to assert IRQ +* util whole TX dmad has been fully written into AXI bus which represents HOST +* memory, 1'b0 : TX engine will assert IRQ once TX dmad write-back request have +* been ACKed +* BIG_ENDIAN[7] - (RW)The endian mode selection. DMA applies +* the endian rule to convert payload and TX/RX information. DMA won't apply +* endian rule to register or descriptor. +* 1: big endian. +* 0: little endian. +* DMAD_32B_EN[8] - (RW)DMA Descriptor 32-byte Enable +* 0: The size of descriptors is set to 16-byte +* 1: The size of descriptors is set to 32-byte +* FW_DWLD_Bypass_dmashdl[9] - (RW)No USE for (APSOC/PCIE)For firmware +* download packet, driver shold +* using tx-ring16 to download packet and set this bit to bypass dmashdl resource +* control. +* After firmware download finish, driver +* should clear this bit. +* After all, tx-ring16 could be used for +* normal data operation. For USB test_mode, user could set this bit +* to bypass dmashdl with all endpoint +* CSR_WFDMA_DUMMY_REG[10] - (RW)dummy CR for use if ECO needed +* CSR_AXI_BUFRDY_BYP[11] - (RW)to disable read data fifo available +* checking before issuing next AXI read request +* FIFO_LITTLE_ENDIAN[12] - (RW)Determines the endianness of the FIFO +* side +* 0: Big-endian +* 1: Little-endian +* CSR_RX_WB_DDONE[13] - (RW)1'b1 : RX engine will wait to assert IRQ +* util whole RX dmad has been fully written into AXI bus which represents HOST +* memory, 1'b0 : RX engine will assert IRQ once RX dmad write-back request have +* been ACKed +* CSR_PP_HIF_TXP_ACTIVE_EN[14] - (RW)1'b1 : enable legacy pp_hif_txp_active +* function to lock tx engine for favor TXP transmit requested directly from PP, +* other pdma TX rings request will be masked until pp_hif_txp_active is +* deasserted +* 1'b0 : disable legacy pp_hif_txp_active +* function, use latest TX source QoS design to change throttler settings to +* favor TXP transmit +* CSR_DISP_BASE_PTR_CHAIN_EN[15] - (RW)Enable prefet sram ring address +* arrangement by hardware chain structure(DMA#N TX ring group -> DMA#N RX ring +* group -> DMA#M TX ring group -> DMA#M RX ring group and son on). If not +* enabled, firmware need to program DISP_BASE_PTR of WPDMA_T(R)X_RING*_EXT_CTRL +* instead +* CSR_LBK_RX_Q_SEL[19..16] - (RW)loopback data from TXFIFO will be direct +* to this RX ring when CSR_LBK_RX_Q_SEL_EN in loopback mode, valid bit-width is +* equal to RX_RING_WIDTH which can be calculated from WPDMA_INFO 0x284[15:8] +* RX_RING_NUMBER +* CSR_LBK_RX_Q_SEL_EN[20] - (RW)Force configured CSR_LBK_RX_Q_SEL to +* receive loopback data from TXFIFO +* OMIT_RX_INFO_PFET2[21] - (RW)For loopback mode, set to 1'b1. +* For normal wifi data operation. User should +* not set this option and should keep 1'b0 because UMAC will always add extra QW +* for checksum after received packet's laster QW +* VERY IMPORTANT : for cpu_dma0/1 where CR +* resides in 0x5100_0xxx, OMIT_RX_INFO MUST be set to 1'b1 +* Omit rx_info of all RX packets +* 0: All the PX packets should end with a rx_info +* 1: All the PX packets should NOT end with a +* rx_info but an eof +* RESERVED22[23..22] - (RO)Reserved bits +* CSR_SW_RST[24] - (RO)SW reset all designs - To be tested for +* SER in the future. +* FORCE_TX_EOF[25] - (RW)Force to send an eof after PDMA being +* reset (for Packet_Processor) +* 0: Disabled +* 1: Enabled +* PDMA_ADDR_EXT_EN[26] - (RW)No Fnction for now!! For PDMA Address +* 32bits extension. When this design option was enable. PDMA would change Tx/Rx +* descriptor format for address extension. +* 0 : PDMA 32bits address +* 1 : PDMA Tx descirptor DW3 (TXINFO)would +* used to extend address +* PDMA Rx descirpt DW2 (Reserved)would used +* to extend address. +* OMIT_RX_INFO[27] - (RW)For loopback mode, set to 1'b1. +* For normal wifi data operation. User should +* not set this option and should keep 1'b0 because UMAC will always add extra QW +* for checksum after received packet's laster QW +* VERY IMPORTANT : for cpu_dma0/1 where CR +* resides in 0x5100_0xxx, OMIT_RX_INFO MUST be set to 1'b1 +* Omit rx_info of all RX packets +* 0: All the PX packets should end with a +* rx_info +* 1: All the PX packets should NOT end with a +* rx_info but an eof +* OMIT_TX_INFO[28] - (RW)For loopback mode, set to 1'b1. +* For normal wifi data operation. User should +* set this option to +* Omit tx_info of all TX packets because UMAC +* design not support TXINFO +* 0: The tx_info in DMAD will be sent at the +* beginning +* 1: The tx_info in DMAD will NOT be sent at +* the beginning +* BYTE_SWAP[29] - (RW)Byte Swapping for TX/RX DMAD +* 0: Not to swap (Endian of DMAD unchanged) +* 1: Swap (Endian of DMAD reversed) +* CLK_GATE_DIS[30] - (RW)PDMA Clock Gated Function Disable +* 0: normal function +* 1: disable clock gated function +* RX_2B_OFFSET[31] - (RW)RX PBF 2-byte Offset +* 1: Skip the first two bytes of the RX PBF +* 0: Not to skip the first two bytes of the +* RX PBF +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_2B_OFFSET_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_2B_OFFSET_MASK \ +0x80000000 /* RX_2B_OFFSET[31] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_2B_OFFSET_SHFT 31 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CLK_GATE_DIS_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CLK_GATE_DIS_MASK \ +0x40000000 /* CLK_GATE_DIS[30] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CLK_GATE_DIS_SHFT 30 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_BYTE_SWAP_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_BYTE_SWAP_MASK \ +0x20000000 /* BYTE_SWAP[29] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_BYTE_SWAP_SHFT 29 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_OMIT_TX_INFO_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_OMIT_TX_INFO_MASK \ +0x10000000 /* OMIT_TX_INFO[28] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_OMIT_TX_INFO_SHFT 28 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_OMIT_RX_INFO_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_OMIT_RX_INFO_MASK \ +0x08000000 /* OMIT_RX_INFO[27] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_OMIT_RX_INFO_SHFT 27 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_PDMA_ADDR_EXT_EN_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_PDMA_ADDR_EXT_EN_MASK \ +0x04000000 /* PDMA_ADDR_EXT_EN[26] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_PDMA_ADDR_EXT_EN_SHFT 26 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FORCE_TX_EOF_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FORCE_TX_EOF_MASK \ +0x02000000 /* FORCE_TX_EOF[25] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FORCE_TX_EOF_SHFT 25 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_SW_RST_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_SW_RST_MASK \ +0x01000000 /* CSR_SW_RST[24] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_SW_RST_SHFT 24 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_OMIT_RX_INFO_PFET2_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_OMIT_RX_INFO_PFET2_MASK \ +0x00200000 /* OMIT_RX_INFO_PFET2[21] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_OMIT_RX_INFO_PFET2_SHFT 21 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_EN_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_EN_MASK \ +0x00100000 /* CSR_LBK_RX_Q_SEL_EN[20] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_EN_SHFT 20 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_MASK \ +0x000F0000 /* CSR_LBK_RX_Q_SEL[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN_MASK \ +0x00008000 /* CSR_DISP_BASE_PTR_CHAIN_EN[15] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN_SHFT 15 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_PP_HIF_TXP_ACTIVE_EN_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_PP_HIF_TXP_ACTIVE_EN_MASK \ +0x00004000 /* CSR_PP_HIF_TXP_ACTIVE_EN[14] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_PP_HIF_TXP_ACTIVE_EN_SHFT 14 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_RX_WB_DDONE_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_RX_WB_DDONE_MASK \ +0x00002000 /* CSR_RX_WB_DDONE[13] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_RX_WB_DDONE_SHFT 13 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN_MASK \ +0x00001000 /* FIFO_LITTLE_ENDIAN[12] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN_SHFT 12 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_AXI_BUFRDY_BYP_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_AXI_BUFRDY_BYP_MASK \ +0x00000800 /* CSR_AXI_BUFRDY_BYP[11] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_AXI_BUFRDY_BYP_SHFT 11 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_WFDMA_DUMMY_REG_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_WFDMA_DUMMY_REG_MASK \ +0x00000400 /* CSR_WFDMA_DUMMY_REG[10] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_WFDMA_DUMMY_REG_SHFT 10 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FW_DWLD_Bypass_dmashdl_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FW_DWLD_Bypass_dmashdl_MASK \ +0x00000200 /* FW_DWLD_Bypass_dmashdl[9] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FW_DWLD_Bypass_dmashdl_SHFT 9 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_DMAD_32B_EN_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_DMAD_32B_EN_MASK \ +0x00000100 /* DMAD_32B_EN[8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_DMAD_32B_EN_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_BIG_ENDIAN_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_BIG_ENDIAN_MASK \ +0x00000080 /* BIG_ENDIAN[7] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_BIG_ENDIAN_SHFT 7 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_WB_DDONE_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_WB_DDONE_MASK \ +0x00000040 /* TX_WB_DDONE[6] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_WB_DDONE_SHFT 6 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_PDMA_BT_SIZE_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_PDMA_BT_SIZE_MASK \ +0x00000030 /* PDMA_BT_SIZE[5..4] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_PDMA_BT_SIZE_SHFT 4 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_BUSY_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_BUSY_MASK \ +0x00000008 /* RX_DMA_BUSY[3] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_BUSY_SHFT 3 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_EN_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_EN_MASK \ +0x00000004 /* RX_DMA_EN[2] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_EN_SHFT 2 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_BUSY_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_BUSY_MASK \ +0x00000002 /* TX_DMA_BUSY[1] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_BUSY_SHFT 1 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_EN_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_EN_MASK \ +0x00000001 /* TX_DMA_EN[0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_EN_SHFT 0 + +/* +* ---WPDMA_RST_DTX_PTR (0x18024000 + 0x20C)--- +* RST_DTX_IDX0[0] - (WO) Write 1 to reset to TX_DMATX_IDX0 to 0 +* RST_DTX_IDX1[1] - (WO) Write 1 to reset to TX_DMATX_IDX1 to 0 +* RST_DTX_IDX2[2] - (WO) Write 1 to reset to TX_DMATX_IDX2 to 0 +* RST_DTX_IDX3[3] - (WO) Write 1 to reset to TX_DMATX_IDX3 to 0 +* RST_DTX_IDX4[4] - (WO) Write 1 to reset to TX_DMATX_IDX4 to 0 +* RST_DTX_IDX5[5] - (WO) Write 1 to reset to TX_DMATX_IDX5 to 0 +* RST_DTX_IDX6[6] - (WO) Write 1 to reset to TX_DMATX_IDX6 to 0 +* RST_DTX_IDX7[7] - (WO) Write 1 to reset to TX_DMATX_IDX7 to 0 +* RST_DTX_IDX8[8] - (WO) Write 1 to reset to TX_DMATX_IDX8 to 0 +* RST_DTX_IDX9[9] - (WO) Write 1 to reset to TX_DMATX_IDX9 to 0 +* RST_DTX_IDX10[10] - (WO) Write 1 to reset to TX_DMATX_IDX10 to 0 +* RST_DTX_IDX11[11] - (WO) Write 1 to reset to TX_DMATX_IDX11 to 0 +* RST_DTX_IDX12[12] - (WO) Write 1 to reset to TX_DMATX_IDX12 to 0 +* RST_DTX_IDX13[13] - (WO) Write 1 to reset to TX_DMATX_IDX13 to 0 +* RST_DTX_IDX14[14] - (WO) Write 1 to reset to TX_DMATX_IDX14 to 0 +* RST_DTX_IDX15[15] - (WO) Write 1 to reset to TX_DMATX_IDX15 to 0 +* RST_DTX_IDX16[16] - (WO) Write 1 to reset to TX_DMATX_IDX16 to 0 +* RST_DTX_IDX17[17] - (WO) Write 1 to reset to TX_DMATX_IDX17 to 0 +* RST_DTX_IDX18[18] - (WO) Write 1 to reset to TX_DMATX_IDX18 to 0 +* RST_DTX_IDX19[19] - (WO) Write 1 to reset to TX_DMATX_IDX19 to 0 +* RST_DTX_IDX20[20] - (WO) Write 1 to reset to TX_DMATX_IDX20 to 0 +* RESERVED21[31..21] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX20_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX20_MASK \ +0x00100000 /* RST_DTX_IDX20[20] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX20_SHFT 20 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX19_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX19_MASK \ +0x00080000 /* RST_DTX_IDX19[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX19_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX18_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX18_MASK \ +0x00040000 /* RST_DTX_IDX18[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX18_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX17_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX17_MASK \ +0x00020000 /* RST_DTX_IDX17[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX17_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX16_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX16_MASK \ +0x00010000 /* RST_DTX_IDX16[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX16_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX15_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX15_MASK \ +0x00008000 /* RST_DTX_IDX15[15] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX15_SHFT 15 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX14_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX14_MASK \ +0x00004000 /* RST_DTX_IDX14[14] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX14_SHFT 14 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX13_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX13_MASK \ +0x00002000 /* RST_DTX_IDX13[13] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX13_SHFT 13 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX12_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX12_MASK \ +0x00001000 /* RST_DTX_IDX12[12] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX12_SHFT 12 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX11_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX11_MASK \ +0x00000800 /* RST_DTX_IDX11[11] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX11_SHFT 11 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX10_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX10_MASK \ +0x00000400 /* RST_DTX_IDX10[10] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX10_SHFT 10 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX9_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX9_MASK \ +0x00000200 /* RST_DTX_IDX9[9] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX9_SHFT 9 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX8_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX8_MASK \ +0x00000100 /* RST_DTX_IDX8[8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX8_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX7_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX7_MASK \ +0x00000080 /* RST_DTX_IDX7[7] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX7_SHFT 7 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX6_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX6_MASK \ +0x00000040 /* RST_DTX_IDX6[6] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX6_SHFT 6 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX5_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX5_MASK \ +0x00000020 /* RST_DTX_IDX5[5] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX5_SHFT 5 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX4_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX4_MASK \ +0x00000010 /* RST_DTX_IDX4[4] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX4_SHFT 4 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX3_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX3_MASK \ +0x00000008 /* RST_DTX_IDX3[3] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX2_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX2_MASK \ +0x00000004 /* RST_DTX_IDX2[2] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX1_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX1_MASK \ +0x00000002 /* RST_DTX_IDX1[1] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX0_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX0_MASK \ +0x00000001 /* RST_DTX_IDX0[0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX0_SHFT 0 + +/* +* ---WPDMA_PAUSE_TX_Q (0x18024000 + 0x224)--- +* TX_Q_PAUSE[31..0] - (RW) Pause signal for each TX ring (16 bits +* for 16 rings) +* Set 0: Normal function; Set 1: The +* corresponding TX ring is paused +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_TX_Q_TX_Q_PAUSE_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_TX_Q_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_TX_Q_TX_Q_PAUSE_MASK \ +0xFFFFFFFF /* TX_Q_PAUSE[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_TX_Q_TX_Q_PAUSE_SHFT 0 + +/* +* ---HOST_INT_ENA_SET (0x18024000 + 0X228)--- +* HOST_RX_DONE_INT_ENA0[0] - (W1S) RX Queue#0 packet receive interrupt +* HOST_RX_DONE_INT_ENA1[1] - (W1S) RX Queue#1 packet receive interrupt +* HOST_RX_DONE_INT_ENA2[2] - (W1S) RX Queue#2 packet receive interrupt +* HOST_RX_DONE_INT_ENA3[3] - (W1S) RX Queue#3 packet receive interrupt +* HOST_TX_DONE_INT_ENA0[4] - (W1S) TX Queue#0 packet transmit interrupt +* HOST_TX_DONE_INT_ENA1[5] - (W1S) TX Queue#1 packet transmit interrupt +* HOST_TX_DONE_INT_ENA2[6] - (W1S) TX Queue#2 packet transmit interrupt +* HOST_TX_DONE_INT_ENA3[7] - (W1S) TX Queue#3 packet transmit interrupt +* HOST_TX_DONE_INT_ENA4[8] - (W1S) TX Queue#4 packet transmit interrupt +* HOST_TX_DONE_INT_ENA5[9] - (W1S) TX Queue#5 packet transmit interrupt +* HOST_TX_DONE_INT_ENA6[10] - (W1S) TX Queue#6 packet transmit interrupt +* HOST_TX_DONE_INT_ENA7[11] - (W1S) TX Queue#7 packet transmit interrupt +* HOST_TX_DONE_INT_ENA8[12] - (W1S) TX Queue#8 packet transmit interrupt +* HOST_TX_DONE_INT_ENA9[13] - (W1S) TX Queue#9 packet transmit interrupt +* HOST_TX_DONE_INT_ENA10[14] - (W1S) TX Queue#10 packet transmit interrupt +* HOST_TX_DONE_INT_ENA11[15] - (W1S) TX Queue#11 packet transmit interrupt +* HOST_TX_DONE_INT_ENA12[16] - (W1S) TX Queue#12 packet transmit interrupt +* HOST_TX_DONE_INT_ENA13[17] - (W1S) TX Queue#13 packet transmit interrupt +* HOST_TX_DONE_INT_ENA14[18] - (W1S) TX Queue#14 packet transmit interrupt +* RESERVED19[19] - (RO) Reserved bits +* HOST_RX_COHERENT_EN[20] - (W1S) Enable for RX_DMA data coherent +interrupt +* HOST_TX_COHERENT_EN[21] - (W1S) Enable for TX_DMA data coherent +interrupt +* HOST_RX_DONE_INT_ENA4[22] - (W1S) RX Queue#4 packet receive interrupt +* HOST_RX_DONE_INT_ENA5[23] - (W1S) RX Queue#5 packet receive interrupt +* wpdma2host_err_int_ena[24] - (W1S) Enable bit of wpdma2host_err_int +* RESERVED25[25] - (RO) Reserved bits +* HOST_TX_DONE_INT_ENA16[26] - (W1S) TX Queue#16 packet transmit interrupt +* HOST_TX_DONE_INT_ENA17[27] - (W1S) TX Queue#17 packet transmit interrupt +* subsys_int_ena[28] - (W1S) Enable bit of subsys_int +* mcu2host_sw_int_ena[29] - (W1S) Enable bit of mcu2host_sw_int +* HOST_TX_DONE_INT_ENA18[30] - (W1S) TX Queue#18 packet transmit interrupt +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA18_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA18_MASK \ +0x40000000 /* HOST_TX_DONE_INT_ENA18[30] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA18_SHFT 30 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_mcu2host_sw_int_ena_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_mcu2host_sw_int_ena_MASK \ +0x20000000 /* mcu2host_sw_int_ena[29] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_mcu2host_sw_int_ena_SHFT 29 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_subsys_int_ena_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_subsys_int_ena_MASK \ +0x10000000 /* subsys_int_ena[28] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_subsys_int_ena_SHFT 28 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA17_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA17_MASK \ +0x08000000 /* HOST_TX_DONE_INT_ENA17[27] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA17_SHFT 27 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA16_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA16_MASK \ +0x04000000 /* HOST_TX_DONE_INT_ENA16[26] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA16_SHFT 26 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_wpdma2host_err_int_ena_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_wpdma2host_err_int_ena_MASK \ +0x01000000 /* wpdma2host_err_int_ena[24] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_wpdma2host_err_int_ena_SHFT 24 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA5_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA5_MASK \ +0x00800000 /* HOST_RX_DONE_INT_ENA5[23] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA5_SHFT 23 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA4_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA4_MASK \ +0x00400000 /* HOST_RX_DONE_INT_ENA4[22] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA4_SHFT 22 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_COHERENT_EN_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_COHERENT_EN_MASK \ +0x00200000 /* HOST_TX_COHERENT_EN[21] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_COHERENT_EN_SHFT 21 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_COHERENT_EN_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_COHERENT_EN_MASK \ +0x00100000 /* HOST_RX_COHERENT_EN[20] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_COHERENT_EN_SHFT 20 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA14_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA14_MASK \ +0x00040000 /* HOST_TX_DONE_INT_ENA14[18] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA14_SHFT 18 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA13_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA13_MASK \ +0x00020000 /* HOST_TX_DONE_INT_ENA13[17] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA13_SHFT 17 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA12_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA12_MASK \ +0x00010000 /* HOST_TX_DONE_INT_ENA12[16] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA12_SHFT 16 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA11_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA11_MASK \ +0x00008000 /* HOST_TX_DONE_INT_ENA11[15] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA11_SHFT 15 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA10_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA10_MASK \ +0x00004000 /* HOST_TX_DONE_INT_ENA10[14] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA10_SHFT 14 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA9_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA9_MASK \ +0x00002000 /* HOST_TX_DONE_INT_ENA9[13] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA9_SHFT 13 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA8_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA8_MASK \ +0x00001000 /* HOST_TX_DONE_INT_ENA8[12] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA8_SHFT 12 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA7_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA7_MASK \ +0x00000800 /* HOST_TX_DONE_INT_ENA7[11] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA7_SHFT 11 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA6_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA6_MASK \ +0x00000400 /* HOST_TX_DONE_INT_ENA6[10] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA6_SHFT 10 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA5_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA5_MASK \ +0x00000200 /* HOST_TX_DONE_INT_ENA5[9] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA5_SHFT 9 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA4_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA4_MASK \ +0x00000100 /* HOST_TX_DONE_INT_ENA4[8] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA4_SHFT 8 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA3_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA3_MASK \ +0x00000080 /* HOST_TX_DONE_INT_ENA3[7] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA3_SHFT 7 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA2_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA2_MASK \ +0x00000040 /* HOST_TX_DONE_INT_ENA2[6] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA2_SHFT 6 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA1_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA1_MASK \ +0x00000020 /* HOST_TX_DONE_INT_ENA1[5] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA1_SHFT 5 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA0_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA0_MASK \ +0x00000010 /* HOST_TX_DONE_INT_ENA0[4] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA0_SHFT 4 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA3_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA3_MASK \ +0x00000008 /* HOST_RX_DONE_INT_ENA3[3] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA2_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA2_MASK \ +0x00000004 /* HOST_RX_DONE_INT_ENA2[2] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA1_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA1_MASK \ +0x00000002 /* HOST_RX_DONE_INT_ENA1[1] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA0_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA0_MASK \ +0x00000001 /* HOST_RX_DONE_INT_ENA0[0] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA0_SHFT 0 + +/* +* ---HOST_INT_ENA_CLR (0x18024000 + 0X22C)--- +* HOST_RX_DONE_INT_ENA0[0] - (W1C) RX Queue#0 packet receive interrupt +* HOST_RX_DONE_INT_ENA1[1] - (W1C) RX Queue#1 packet receive interrupt +* HOST_RX_DONE_INT_ENA2[2] - (W1C) RX Queue#2 packet receive interrupt +* HOST_RX_DONE_INT_ENA3[3] - (W1C) RX Queue#3 packet receive interrupt +* HOST_TX_DONE_INT_ENA0[4] - (W1C) TX Queue#0 packet transmit interrupt +* HOST_TX_DONE_INT_ENA1[5] - (W1C) TX Queue#1 packet transmit interrupt +* HOST_TX_DONE_INT_ENA2[6] - (W1C) TX Queue#2 packet transmit interrupt +* HOST_TX_DONE_INT_ENA3[7] - (W1C) TX Queue#3 packet transmit interrupt +* HOST_TX_DONE_INT_ENA4[8] - (W1C) TX Queue#4 packet transmit interrupt +* HOST_TX_DONE_INT_ENA5[9] - (W1C) TX Queue#5 packet transmit interrupt +* HOST_TX_DONE_INT_ENA6[10] - (W1C) TX Queue#6 packet transmit interrupt +* HOST_TX_DONE_INT_ENA7[11] - (W1C) TX Queue#7 packet transmit interrupt +* HOST_TX_DONE_INT_ENA8[12] - (W1C) TX Queue#8 packet transmit interrupt +* HOST_TX_DONE_INT_ENA9[13] - (W1C) TX Queue#9 packet transmit interrupt +* HOST_TX_DONE_INT_ENA10[14] - (W1C) TX Queue#10 packet transmit interrupt +* HOST_TX_DONE_INT_ENA11[15] - (W1C) TX Queue#11 packet transmit interrupt +* HOST_TX_DONE_INT_ENA12[16] - (W1C) TX Queue#12 packet transmit interrupt +* HOST_TX_DONE_INT_ENA13[17] - (W1C) TX Queue#13 packet transmit interrupt +* HOST_TX_DONE_INT_ENA14[18] - (W1C) TX Queue#14 packet transmit interrupt +* RESERVED19[19] - (RO) Reserved bits +* HOST_RX_COHERENT_EN[20] - (W1C) Enable for RX_DMA data coherent +interrupt +* HOST_TX_COHERENT_EN[21] - (W1C) Enable for TX_DMA data coherent +interrupt +* HOST_RX_DONE_INT_ENA4[22] - (W1C) RX Queue#4 packet receive interrupt +* HOST_RX_DONE_INT_ENA5[23] - (W1C) RX Queue#5 packet receive interrupt +* wpdma2host_err_int_ena[24] - (W1C) Enable bit of wpdma2host_err_int +* RESERVED25[25] - (RO) Reserved bits +* HOST_TX_DONE_INT_ENA16[26] - (W1C) TX Queue#16 packet transmit interrupt +* HOST_TX_DONE_INT_ENA17[27] - (W1C) TX Queue#17 packet transmit interrupt +* subsys_int_ena[28] - (W1C) Enable bit of subsys_int +* mcu2host_sw_int_ena[29] - (W1C) Enable bit of mcu2host_sw_int +* HOST_TX_DONE_INT_ENA18[30] - (W1C) TX Queue#18 packet transmit interrupt +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA18_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA18_MASK \ +0x40000000 /* HOST_TX_DONE_INT_ENA18[30] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA18_SHFT 30 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_mcu2host_sw_int_ena_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_mcu2host_sw_int_ena_MASK \ +0x20000000 /* mcu2host_sw_int_ena[29] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_mcu2host_sw_int_ena_SHFT 29 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_subsys_int_ena_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_subsys_int_ena_MASK \ +0x10000000 /* subsys_int_ena[28] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_subsys_int_ena_SHFT 28 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA17_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA17_MASK \ +0x08000000 /* HOST_TX_DONE_INT_ENA17[27] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA17_SHFT 27 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA16_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA16_MASK \ +0x04000000 /* HOST_TX_DONE_INT_ENA16[26] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA16_SHFT 26 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_wpdma2host_err_int_ena_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_wpdma2host_err_int_ena_MASK \ +0x01000000 /* wpdma2host_err_int_ena[24] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_wpdma2host_err_int_ena_SHFT 24 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA5_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA5_MASK \ +0x00800000 /* HOST_RX_DONE_INT_ENA5[23] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA5_SHFT 23 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA4_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA4_MASK \ +0x00400000 /* HOST_RX_DONE_INT_ENA4[22] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA4_SHFT 22 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_COHERENT_EN_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_COHERENT_EN_MASK \ +0x00200000 /* HOST_TX_COHERENT_EN[21] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_COHERENT_EN_SHFT 21 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_COHERENT_EN_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_COHERENT_EN_MASK \ +0x00100000 /* HOST_RX_COHERENT_EN[20] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_COHERENT_EN_SHFT 20 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA14_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA14_MASK \ +0x00040000 /* HOST_TX_DONE_INT_ENA14[18] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA14_SHFT 18 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA13_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA13_MASK \ +0x00020000 /* HOST_TX_DONE_INT_ENA13[17] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA13_SHFT 17 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA12_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA12_MASK \ +0x00010000 /* HOST_TX_DONE_INT_ENA12[16] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA12_SHFT 16 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA11_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA11_MASK \ +0x00008000 /* HOST_TX_DONE_INT_ENA11[15] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA11_SHFT 15 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA10_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA10_MASK \ +0x00004000 /* HOST_TX_DONE_INT_ENA10[14] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA10_SHFT 14 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA9_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA9_MASK \ +0x00002000 /* HOST_TX_DONE_INT_ENA9[13] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA9_SHFT 13 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA8_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA8_MASK \ +0x00001000 /* HOST_TX_DONE_INT_ENA8[12] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA8_SHFT 12 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA7_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA7_MASK \ +0x00000800 /* HOST_TX_DONE_INT_ENA7[11] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA7_SHFT 11 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA6_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA6_MASK \ +0x00000400 /* HOST_TX_DONE_INT_ENA6[10] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA6_SHFT 10 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA5_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA5_MASK \ +0x00000200 /* HOST_TX_DONE_INT_ENA5[9] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA5_SHFT 9 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA4_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA4_MASK \ +0x00000100 /* HOST_TX_DONE_INT_ENA4[8] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA4_SHFT 8 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA3_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA3_MASK \ +0x00000080 /* HOST_TX_DONE_INT_ENA3[7] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA3_SHFT 7 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA2_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA2_MASK \ +0x00000040 /* HOST_TX_DONE_INT_ENA2[6] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA2_SHFT 6 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA1_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA1_MASK \ +0x00000020 /* HOST_TX_DONE_INT_ENA1[5] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA1_SHFT 5 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA0_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA0_MASK \ +0x00000010 /* HOST_TX_DONE_INT_ENA0[4] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA0_SHFT 4 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA3_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA3_MASK \ +0x00000008 /* HOST_RX_DONE_INT_ENA3[3] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA2_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA2_MASK \ +0x00000004 /* HOST_RX_DONE_INT_ENA2[2] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA1_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA1_MASK \ +0x00000002 /* HOST_RX_DONE_INT_ENA1[1] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA0_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA0_MASK \ +0x00000001 /* HOST_RX_DONE_INT_ENA0[0] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA0_SHFT 0 + +/* +* ---WPDMA_TIMEOUT_CFG (0x18024000 + 0x230)--- +* WPDMA_TX_TIMEOUT_TH[7..0] - (RW) xxx +* WPDMA_TX_TIMEOUT_TICK[14..8] - (RW) xxx +* WPDMA_TX_TIMEOUT_ENA[15] - (RW) xxx +* WPDMA_RX_TIMEOUT_TH[23..16] - (RW) xxx +* WPDMA_RX_TIMEOUT_TICK[30..24] - (RW) xxx +* WPDMA_RX_TIMEOUT_ENA[31] - (RW) xxx +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_ENA_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_ENA_MASK \ +0x80000000 /* WPDMA_RX_TIMEOUT_ENA[31] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_ENA_SHFT 31 +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TICK_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TICK_MASK \ +0x7F000000 /* WPDMA_RX_TIMEOUT_TICK[30..24] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TICK_SHFT 24 +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TH_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TH_MASK \ +0x00FF0000 /* WPDMA_RX_TIMEOUT_TH[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TH_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_ENA_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_ENA_MASK \ +0x00008000 /* WPDMA_TX_TIMEOUT_ENA[15] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_ENA_SHFT 15 +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TICK_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TICK_MASK \ +0x00007F00 /* WPDMA_TX_TIMEOUT_TICK[14..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TICK_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TH_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TH_MASK \ +0x000000FF /* WPDMA_TX_TIMEOUT_TH[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TH_SHFT 0 + +/* +* ---WPDMA_MISC_CFG (0x18024000 + 0x234)--- +* WPDMA_TX_TIMEOUT_SEL[0] - (RW) xxx +* WPDMA_RX_TIMEOUT_SEL[1] - (RW) xxx +* WPDMA_RX_FREE_Q_TH[5..2] - (RW) When loopback, this will be used to +* generate correct tx_pause to avlid deadlock which caused from situration that +* tx_dma will start reading tx packet from memory without considering lack of RX +* dmad in prefetch sram and needing to read RX dmad from memory which tx dma is +* reading tx packet too and rready is deasserted due to txfifo full !! +* RX dmad in prefetch sram should be greater +* than RX_FREE_Q_TH for rx_dma to start writing received packet into memory!! +* RESERVED6[31..6] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_RX_FREE_Q_TH_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_RX_FREE_Q_TH_MASK \ +0x0000003C /* WPDMA_RX_FREE_Q_TH[5..2] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_RX_FREE_Q_TH_SHFT 2 +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_RX_TIMEOUT_SEL_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_RX_TIMEOUT_SEL_MASK \ +0x00000002 /* WPDMA_RX_TIMEOUT_SEL[1] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_RX_TIMEOUT_SEL_SHFT 1 +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_TX_TIMEOUT_SEL_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_TX_TIMEOUT_SEL_MASK \ +0x00000001 /* WPDMA_TX_TIMEOUT_SEL[0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_TX_TIMEOUT_SEL_SHFT 0 + +/* +* ---WPDMA_TX_WRR_ARB_GBF0 (0x18024000 + 0x240)--- +* WRR_REQ0_ARB_GBF[2..0] - (RW) WRR REQ#0 priority level, mapped to +* lumpped request from TX ring0~ring15 for host TXD +* WRR_REQ1_ARB_GBF[5..3] - (RW) WRR REQ#1 priority level, mapped to +* request from TX ring16 when dual tx fifo for host event packet +* WRR_REQ2_ARB_GBF[8..6] - (RW) WRR REQ#2 priority level, mapped to +* request from TX ring17 when dual tx fifo for host event packet +* WRR_REQ3_ARB_GBF[11..9] - (RW) WRR REQ#3 priority level, mapped to +* request from TX ring18 when dual tx fifo for host event packet +* WRR_REQ4_ARB_GBF[14..12] - (RW) WRR REQ#4 priority level, mapped to +* request from TX ring19 when dual tx fifo for host event packet +* RESERVED[31..15] - (RW) Reserved +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ4_ARB_GBF_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ4_ARB_GBF_MASK \ +0x00007000 /* WRR_REQ4_ARB_GBF[14..12] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ4_ARB_GBF_SHFT 12 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ3_ARB_GBF_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ3_ARB_GBF_MASK \ +0x00000E00 /* WRR_REQ3_ARB_GBF[11..9] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ3_ARB_GBF_SHFT 9 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ2_ARB_GBF_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ2_ARB_GBF_MASK \ +0x000001C0 /* WRR_REQ2_ARB_GBF[8..6] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ2_ARB_GBF_SHFT 6 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ1_ARB_GBF_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ1_ARB_GBF_MASK \ +0x00000038 /* WRR_REQ1_ARB_GBF[5..3] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ1_ARB_GBF_SHFT 3 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ0_ARB_GBF_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ0_ARB_GBF_MASK \ +0x00000007 /* WRR_REQ0_ARB_GBF[2..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ0_ARB_GBF_SHFT 0 + +/* +* ---WPDMA_PAUSE_RX_Q_TH10 (0x18024000 + 0x260)--- +* RX_DMAD_TH0[11..0] - (RW) RX Ring0 DMAD threshold to pause PP +* sending packet to RX FIFO +* pause_rx_q = (available RX DMAD counts) < + +* RESERVED12[15..12] - (RO) Reserved bits +* RX_DMAD_TH1[27..16] - (RW) RX Ring1 DMAD threshold to pause PP +* sending packet to RX FIFO +* pause_rx_q = (available RX DMAD counts) < + +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH1_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH1_MASK \ +0x0FFF0000 /* RX_DMAD_TH1[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH1_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH0_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH0_MASK \ +0x00000FFF /* RX_DMAD_TH0[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH0_SHFT 0 + +/* +* ---WPDMA_PAUSE_RX_Q_TH32 (0x18024000 + 0x264)--- +* RX_DMAD_TH2[11..0] - (RW) RX Ring2 DMAD threshold to pause PP +* sending packet to RX FIFO +* pause_rx_q = (available RX DMAD counts) < + +* RESERVED12[15..12] - (RO) Reserved bits +* RX_DMAD_TH3[27..16] - (RW) RX Ring3 DMAD threshold to pause PP +* sending packet to RX FIFO +* pause_rx_q = (available RX DMAD counts) < + +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH3_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH3_MASK \ +0x0FFF0000 /* RX_DMAD_TH3[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH3_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH2_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH2_MASK \ +0x00000FFF /* RX_DMAD_TH2[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH2_SHFT 0 + +/* +* ---WPDMA_PAUSE_RX_Q_TH54 (0x18024000 + 0x268)--- +* RX_DMAD_TH4[11..0] - (RW) RX Ring4 DMAD threshold to pause PP +* sending packet to RX FIFO +* pause_rx_q = (available RX DMAD counts) < + +* RESERVED12[15..12] - (RO) Reserved bits +* RX_DMAD_TH5[27..16] - (RW) RX Ring5 DMAD threshold to pause PP +* sending packet to RX FIFO +* pause_rx_q = (available RX DMAD counts) < + +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH5_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH5_MASK \ +0x0FFF0000 /* RX_DMAD_TH5[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH5_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH4_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH4_MASK \ +0x00000FFF /* RX_DMAD_TH4[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH4_SHFT 0 + +/* +* ---WPDMA_PAUSE_RX_Q_TH76 (0x18024000 + 0x26C)--- +* RX_DMAD_TH6[11..0] - (RW) RX Ring6 DMAD threshold to pause PP +* sending packet to RX FIFO +* pause_rx_q = (available RX DMAD counts) < + +* RESERVED12[15..12] - (RO) Reserved bits +* RX_DMAD_TH7[27..16] - (RW) RX Ring7 DMAD threshold to pause PP +* sending packet to RX FIFO +* pause_rx_q = (available RX DMAD counts) < + +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH7_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH7_MASK \ +0x0FFF0000 /* RX_DMAD_TH7[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH7_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH6_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH6_MASK \ +0x00000FFF /* RX_DMAD_TH6[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH6_SHFT 0 + +/* +* ---WPDMA_RST_DRX_PTR (0x18024000 + 0x280)--- +* RST_DRX_IDX0[0] - (WO) Write 1 to reset to RX_DMARX_IDX0 to 0 +* RST_DRX_IDX1[1] - (WO) Write 1 to reset to RX_DMARX_IDX1 to 0 +* RST_DRX_IDX2[2] - (WO) Write 1 to reset to RX_DMARX_IDX2 to 0 +* RST_DRX_IDX3[3] - (WO) Write 1 to reset to RX_DMARX_IDX3 to 0 +* RESERVED[31..4] - (WO) Reserved +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX3_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX3_MASK \ +0x00000008 /* RST_DRX_IDX3[3] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX2_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX2_MASK \ +0x00000004 /* RST_DRX_IDX2[2] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX1_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX1_MASK \ +0x00000002 /* RST_DRX_IDX1[1] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX0_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX0_MASK \ +0x00000001 /* RST_DRX_IDX0[0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX0_SHFT 0 + +/* +* ---WPDMA_INFO (0x18024000 + 0x284)--- +* TX_RING_NUMBER[7..0] - (RO) TX_RING_NUMBER +* RX_RING_NUMBER[15..8] - (RO) RX_RING_NUMBER +* BASE_PTR_WIDTH[23..16] - (RO) {2'h0, 6'd32-'BASE_PTR_WIDTH[5:0]} +* INDEX_WIDTH[27..24] - (RO) RING_INDEX_WIDTH +* PDMA_PREFETCH_SRAM_SIZE[30..28] - (RO) PDMA prefetch sram size{3'h0 : 128 +* byte, 3'h1 : 256 byte, 3'h2 : 512 byte, 3'h3 : 1KB, 3'h4 : 2KB, 3'h5 : 4KB, +* 3'h6 : 8KB, 3'h7 : reserved}, be noticed that prefetch sram is shared outside +* with other DMAs, please check all DMAs' total prefetch ring number and max_cnt +* for each prefetch ring to make sure that total size of all configured prefetch +* dmad of all DMAs' prefetch ring should be less than PDMA_PREFETCH_SRAM_SIZE +* WFDMA_PDA_EXIST[31] - (RO) Only cpu_dma1 will support pda functions +* for firmware download and wfdma_pda_top resides in between cpu_dma0 and +cpu_dma1! +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_WFDMA_PDA_EXIST_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_WFDMA_PDA_EXIST_MASK \ +0x80000000 /* WFDMA_PDA_EXIST[31] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_WFDMA_PDA_EXIST_SHFT 31 +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_PDMA_PREFETCH_SRAM_SIZE_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_PDMA_PREFETCH_SRAM_SIZE_MASK \ +0x70000000 /* PDMA_PREFETCH_SRAM_SIZE[30..28] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_PDMA_PREFETCH_SRAM_SIZE_SHFT 28 +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_INDEX_WIDTH_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_INDEX_WIDTH_MASK \ +0x0F000000 /* INDEX_WIDTH[27..24] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_INDEX_WIDTH_SHFT 24 +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_BASE_PTR_WIDTH_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_BASE_PTR_WIDTH_MASK \ +0x00FF0000 /* BASE_PTR_WIDTH[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_BASE_PTR_WIDTH_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_RX_RING_NUMBER_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_RX_RING_NUMBER_MASK \ +0x0000FF00 /* RX_RING_NUMBER[15..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_RX_RING_NUMBER_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_TX_RING_NUMBER_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_TX_RING_NUMBER_MASK \ +0x000000FF /* TX_RING_NUMBER[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_TX_RING_NUMBER_SHFT 0 + +/* +* ---WPDMA_INFO_EXT (0x18024000 + 0x288)--- +* TX_EVENT_RING_NUMBER[7..0] - (RO) When TX_EVENT_RING_NUMBER equal 8'h0, it +* means that this DMA doesn't support dual TX fifo, thus in default it only +* support TX_RING_NUMBER of TX rings !! +* But when TX_EVENT_RING_NUMBER NOT equal +* 8'h0, this dma is configured as dual TX fifo and +* TX_RING[16+TX_EVENT_RING_NUM-1:16] are for getting HOST EVENT packet from HOST +* to WX_CPU!! +* TX_DMAD_RING_NUMBER[15..8] - (RO) When TX_EVENT_RING_NUMBER not equal to +* 8'h0, it means that this DMA support dual TX fifo and TX +* ring[TX_DMAD_RING_NUMBER-1:0] are for getting TXD from HOST to UMAC!! +* RESERVED[30..16] - (RO) Reserved +* TX_DMASHDL_EXIST[31] - (RO) TX_DMASHDL_EXIST +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_DMASHDL_EXIST_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_DMASHDL_EXIST_MASK \ +0x80000000 /* TX_DMASHDL_EXIST[31] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_DMASHDL_EXIST_SHFT 31 +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_DMAD_RING_NUMBER_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_DMAD_RING_NUMBER_MASK \ +0x0000FF00 /* TX_DMAD_RING_NUMBER[15..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_DMAD_RING_NUMBER_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_EVENT_RING_NUMBER_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_EVENT_RING_NUMBER_MASK \ +0x000000FF /* TX_EVENT_RING_NUMBER[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_EVENT_RING_NUMBER_SHFT 0 + +/* +* ---WPDMA_INT_RX_PRI_SEL (0x18024000 + 0x298)--- +* WPDMA_INT_RX_RING0_PRI_SEL[0] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_RX_RING1_PRI_SEL[1] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_RX_RING2_PRI_SEL[2] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_RX_RING3_PRI_SEL[3] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_RX_RING4_PRI_SEL[4] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_RX_RING5_PRI_SEL[5] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* RESERVED6[31..6] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING5_PRI_SEL_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING5_PRI_SEL_MASK \ + \ +0x00000020 /* WPDMA_INT_RX_RING5_PRI_SEL[5] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING5_PRI_SEL_SHFT \ + \ +5 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING4_PRI_SEL_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING4_PRI_SEL_MASK \ + \ +0x00000010 /* WPDMA_INT_RX_RING4_PRI_SEL[4] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING4_PRI_SEL_SHFT \ + \ +4 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING3_PRI_SEL_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING3_PRI_SEL_MASK \ + \ +0x00000008 /* WPDMA_INT_RX_RING3_PRI_SEL[3] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING3_PRI_SEL_SHFT \ + \ +3 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING2_PRI_SEL_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING2_PRI_SEL_MASK \ + \ +0x00000004 /* WPDMA_INT_RX_RING2_PRI_SEL[2] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING2_PRI_SEL_SHFT \ + \ +2 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING1_PRI_SEL_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING1_PRI_SEL_MASK \ + \ +0x00000002 /* WPDMA_INT_RX_RING1_PRI_SEL[1] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING1_PRI_SEL_SHFT \ + \ +1 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING0_PRI_SEL_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING0_PRI_SEL_MASK \ + \ +0x00000001 /* WPDMA_INT_RX_RING0_PRI_SEL[0] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING0_PRI_SEL_SHFT \ + \ +0 + +/* +* ---WPDMA_INT_TX_PRI_SEL (0x18024000 + 0x29C)--- +* WPDMA_INT_TX_RING0_PRI_SEL[0] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING1_PRI_SEL[1] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING2_PRI_SEL[2] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING3_PRI_SEL[3] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING4_PRI_SEL[4] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING5_PRI_SEL[5] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING6_PRI_SEL[6] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING7_PRI_SEL[7] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING8_PRI_SEL[8] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING9_PRI_SEL[9] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING10_PRI_SEL[10] - (RW) write 1 to enable corresponding ring +* to be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING11_PRI_SEL[11] - (RW) write 1 to enable corresponding ring +* to be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING12_PRI_SEL[12] - (RW) write 1 to enable corresponding ring +* to be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING13_PRI_SEL[13] - (RW) write 1 to enable corresponding ring +* to be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING14_PRI_SEL[14] - (RW) write 1 to enable corresponding ring +* to be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* RESERVED15[15] - (RO) Reserved bits +* WPDMA_INT_TX_RING16_PRI_SEL[16] - (RW) write 1 to enable corresponding ring +* to be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING17_PRI_SEL[17] - (RW) write 1 to enable corresponding ring +* to be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING18_PRI_SEL[18] - (RW) write 1 to enable corresponding ring +* to be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* RESERVED[19] - (RO) Reserved +* RESERVED[20] - (RO) Reserved +* RESERVED21[31..21] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING18_PRI_SEL_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING18_PRI_SEL_MASK \ + \ +0x00040000 /* WPDMA_INT_TX_RING18_PRI_SEL[18] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING18_PRI_SEL_SHFT \ + \ +18 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING17_PRI_SEL_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING17_PRI_SEL_MASK \ + \ +0x00020000 /* WPDMA_INT_TX_RING17_PRI_SEL[17] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING17_PRI_SEL_SHFT \ + \ +17 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING16_PRI_SEL_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING16_PRI_SEL_MASK \ + \ +0x00010000 /* WPDMA_INT_TX_RING16_PRI_SEL[16] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING16_PRI_SEL_SHFT \ + \ +16 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING14_PRI_SEL_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING14_PRI_SEL_MASK \ + \ +0x00004000 /* WPDMA_INT_TX_RING14_PRI_SEL[14] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING14_PRI_SEL_SHFT \ + \ +14 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING13_PRI_SEL_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING13_PRI_SEL_MASK \ + \ +0x00002000 /* WPDMA_INT_TX_RING13_PRI_SEL[13] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING13_PRI_SEL_SHFT \ + \ +13 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING12_PRI_SEL_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING12_PRI_SEL_MASK \ + \ +0x00001000 /* WPDMA_INT_TX_RING12_PRI_SEL[12] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING12_PRI_SEL_SHFT \ + \ +12 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING11_PRI_SEL_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING11_PRI_SEL_MASK \ + \ +0x00000800 /* WPDMA_INT_TX_RING11_PRI_SEL[11] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING11_PRI_SEL_SHFT \ + \ +11 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING10_PRI_SEL_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING10_PRI_SEL_MASK \ + \ +0x00000400 /* WPDMA_INT_TX_RING10_PRI_SEL[10] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING10_PRI_SEL_SHFT \ + \ +10 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING9_PRI_SEL_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING9_PRI_SEL_MASK \ + \ +0x00000200 /* WPDMA_INT_TX_RING9_PRI_SEL[9] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING9_PRI_SEL_SHFT \ + \ +9 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING8_PRI_SEL_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING8_PRI_SEL_MASK \ + \ +0x00000100 /* WPDMA_INT_TX_RING8_PRI_SEL[8] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING8_PRI_SEL_SHFT \ + \ +8 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING7_PRI_SEL_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING7_PRI_SEL_MASK \ + \ +0x00000080 /* WPDMA_INT_TX_RING7_PRI_SEL[7] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING7_PRI_SEL_SHFT \ + \ +7 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING6_PRI_SEL_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING6_PRI_SEL_MASK \ + \ +0x00000040 /* WPDMA_INT_TX_RING6_PRI_SEL[6] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING6_PRI_SEL_SHFT \ + \ +6 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING5_PRI_SEL_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING5_PRI_SEL_MASK \ + \ +0x00000020 /* WPDMA_INT_TX_RING5_PRI_SEL[5] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING5_PRI_SEL_SHFT \ + \ +5 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING4_PRI_SEL_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING4_PRI_SEL_MASK \ + \ +0x00000010 /* WPDMA_INT_TX_RING4_PRI_SEL[4] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING4_PRI_SEL_SHFT \ + \ +4 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING3_PRI_SEL_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING3_PRI_SEL_MASK \ + \ +0x00000008 /* WPDMA_INT_TX_RING3_PRI_SEL[3] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING3_PRI_SEL_SHFT \ + \ +3 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING2_PRI_SEL_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING2_PRI_SEL_MASK \ + \ +0x00000004 /* WPDMA_INT_TX_RING2_PRI_SEL[2] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING2_PRI_SEL_SHFT \ + \ +2 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING1_PRI_SEL_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING1_PRI_SEL_MASK \ + \ +0x00000002 /* WPDMA_INT_TX_RING1_PRI_SEL[1] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING1_PRI_SEL_SHFT \ + \ +1 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING0_PRI_SEL_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING0_PRI_SEL_MASK \ + \ +0x00000001 /* WPDMA_INT_TX_RING0_PRI_SEL[0] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING0_PRI_SEL_SHFT \ + \ +0 + +/* +* ---WPDMA_TX_DBG0 (0x18024000 + 0x2A0)--- +* WPDMA_TX_DBG0[31..0] - (RO) xxx +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG0_WPDMA_TX_DBG0_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG0_WPDMA_TX_DBG0_MASK \ +0xFFFFFFFF /* WPDMA_TX_DBG0[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG0_WPDMA_TX_DBG0_SHFT 0 + +/* +* ---WPDMA_TX_DBG1 (0x18024000 + 0x2A4)--- +* WPDMA_TX_DBG1[31..0] - (RO) xxx +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG1_WPDMA_TX_DBG1_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG1_WPDMA_TX_DBG1_MASK \ +0xFFFFFFFF /* WPDMA_TX_DBG1[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG1_WPDMA_TX_DBG1_SHFT 0 + +/* +* ---WPDMA_RX_DBG0 (0x18024000 + 0x2A8)--- +* WPDMA_RX_DBG0[31..0] - (RO) xxx +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG0_WPDMA_RX_DBG0_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG0_WPDMA_RX_DBG0_MASK \ +0xFFFFFFFF /* WPDMA_RX_DBG0[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG0_WPDMA_RX_DBG0_SHFT 0 + +/* +* ---WPDMA_RX_DBG1 (0x18024000 + 0x2AC)--- +* WPDMA_RX_DBG1[31..0] - (RO) xxx +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG1_WPDMA_RX_DBG1_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG1_WPDMA_RX_DBG1_MASK \ +0xFFFFFFFF /* WPDMA_RX_DBG1[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG1_WPDMA_RX_DBG1_SHFT 0 + +/* +* ---WPDMA_GLO_CFG_EXT0 (0x18024000 + 0x2B0)--- +* CSR_MAX_PREFETCH_CNT[1..0] - (RW) Max. dmad count per prefet request, +* 2'b00 : 1 entry, 2'b01 : 2 entries, 2'b10 : 4 entries, 2'b11 : 8 entries, Note +* : 1 entry(dmad size) is 16 bytes = 4 DWs = 2 QWs +* CSR_MEM_BST_SIZE[3..2] - (RW) Max. burst size per sram request. 00 : +* 16-byte, 01 : 32-byte, 10 : 64-byte, 11 : 128-byte +* CSR_MEM_ARB_LOCK_EN[4] - (RW) 1'b1 : Lock round-robin sram access +* arbiter until whole long burst request from dma FSM finish, 1'b0 : no lock +* sram +* arbiter, grant will be change per request due to round-robin +* CSR_RX_DMA_WBQ_EN[5] - (RW) 1'b1 : RX dmad will be posted-write and +* deal with next received packet immediately, 1'b0 : RX dmad will be written +* back +* immediately after received packet has been sent to host memory +* CSR_TX_DMASHDL_ENABLE[6] - (RW) 1'b1 : request DMASHDL before TX to +* select next TX ring, 1'b0 : disable DMASHDL and use round-robin arbiter to +* select next TX ring +* CSR_BRESP_ERROR_BYPASS_EN[7] - (RW) 1'b1 : Bypass AXI error bresp as a +* normal response. 1'b0 : Will not assert bready to error bresp(00 : OKAY, 01 : +* EXOKAY, 10 : SLVERR, 11 : DECERR) +* CSR_AXI_SLEEP_MODE[9..8] - (RW) 2'b00 : no sleep, normal TX/RX, 2b1* : +* sleep after AXI request, 2'b11 : force assertion of wvalid, rready and bready +* to finish all committed data phases, then sleep immediately +* RESERVED10[14..10] - (RO) Reserved bits +* CSR_Q_STATUS_IDX_BKRS_EN[15] - (RW) backup/restore enable bit for +* q_status(payload, prefetch and dispatch) index +* CSR_AXI_BST_SIZE[17..16] - (RW) AXI busrt length, 00 : 128-byte, 01 : +* 64-byte, 10 : 32-byte, 11 : 16-byte +* RESERVED18[18] - (RO) Reserved bits +* CSR_AXI_FAKE[19] - (RW) If set to 1'b1, all requests from DMA +* engine will not be sent to AXI INFRA, this try to fix AXI bus hang issue +* temporarily! +* CSR_DMAD_PREFETCH_THRESHOLD[21..20] - (RW) trigger dmad prefetch when +* available dmad cnt >= {1(2'b00), 2(2'b01), 4(2'b10), 8(2'b11)} +* CSR_BID_CHECK_BYPASS_EN[22] - (RW) If set to 1'b0, axi master will check +* matching between awid and bid before assert bready, if set to 1'b1, it will +* bypass this checking and assert bready for each bvalid even though bid doesn't +* match any awid ever issued! +* CSR_RX_INFO_WB_EN[23] - (RW) If set to 1'b0, only DW0 and DW1 will be +* written back into memory after received RX packet process finished, this will +* save bus bandwidth a little because DW2 and DW3 are useless for FW +* CSR_AXI_OUTSTANDING_NUM[27..24] - (RW) decide max. outstanding AXI requests, +* common for AXI read or write! +* CSR_AXI_ARUSER_LOCK_EN[28] - (RW) on/off customized lock ctrl design thru +* AXI aruser signal, this will influence TX QoS ctrl +* CSR_AXI_AWUSER_LOCK_EN[29] - (RW) on/off customized lock ctrl design thru +* AXI awuser signal when RX dmad write-back have to be separately written into +* memory due to external dispatcher exists! +* CSR_AXI_LOCK_EN[30] - (RW) Global lock enable to on/off AXI spec. +* lock(axlock) behavior and also will on/off customized lock ctrl design thru +* AXI awuser signal +* CSR_AXI_CLKGATE_BYP[31] - (RW) To bypass functional CG enable which +* incduced from coding style for DC inserted CG cell in all AXI read/write +* master +* design module +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_CLKGATE_BYP_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_CLKGATE_BYP_MASK \ +0x80000000 /* CSR_AXI_CLKGATE_BYP[31] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_CLKGATE_BYP_SHFT 31 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_LOCK_EN_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_LOCK_EN_MASK \ +0x40000000 /* CSR_AXI_LOCK_EN[30] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_LOCK_EN_SHFT 30 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_AWUSER_LOCK_EN_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_AWUSER_LOCK_EN_MASK \ +0x20000000 /* CSR_AXI_AWUSER_LOCK_EN[29] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_AWUSER_LOCK_EN_SHFT 29 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_ARUSER_LOCK_EN_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_ARUSER_LOCK_EN_MASK \ +0x10000000 /* CSR_AXI_ARUSER_LOCK_EN[28] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_ARUSER_LOCK_EN_SHFT 28 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_OUTSTANDING_NUM_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_OUTSTANDING_NUM_MASK \ +0x0F000000 /* CSR_AXI_OUTSTANDING_NUM[27..24] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_OUTSTANDING_NUM_SHFT 24 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_RX_INFO_WB_EN_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_RX_INFO_WB_EN_MASK \ +0x00800000 /* CSR_RX_INFO_WB_EN[23] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_RX_INFO_WB_EN_SHFT 23 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_BID_CHECK_BYPASS_EN_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_BID_CHECK_BYPASS_EN_MASK \ +0x00400000 /* CSR_BID_CHECK_BYPASS_EN[22] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_BID_CHECK_BYPASS_EN_SHFT 22 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_DMAD_PREFETCH_THRESHOLD_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_DMAD_PREFETCH_THRESHOLD_MASK \ +0x00300000 /* CSR_DMAD_PREFETCH_THRESHOLD[21..20] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_DMAD_PREFETCH_THRESHOLD_SHFT \ +20 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_FAKE_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_FAKE_MASK \ +0x00080000 /* CSR_AXI_FAKE[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_FAKE_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_BST_SIZE_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_BST_SIZE_MASK \ +0x00030000 /* CSR_AXI_BST_SIZE[17..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_BST_SIZE_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_Q_STATUS_IDX_BKRS_EN_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_Q_STATUS_IDX_BKRS_EN_MASK \ +0x00008000 /* CSR_Q_STATUS_IDX_BKRS_EN[15] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_Q_STATUS_IDX_BKRS_EN_SHFT 15 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_SLEEP_MODE_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_SLEEP_MODE_MASK \ +0x00000300 /* CSR_AXI_SLEEP_MODE[9..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_SLEEP_MODE_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_BRESP_ERROR_BYPASS_EN_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_BRESP_ERROR_BYPASS_EN_MASK \ +0x00000080 /* CSR_BRESP_ERROR_BYPASS_EN[7] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_BRESP_ERROR_BYPASS_EN_SHFT 7 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_TX_DMASHDL_ENABLE_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_TX_DMASHDL_ENABLE_MASK \ +0x00000040 /* CSR_TX_DMASHDL_ENABLE[6] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_TX_DMASHDL_ENABLE_SHFT 6 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_RX_DMA_WBQ_EN_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_RX_DMA_WBQ_EN_MASK \ +0x00000020 /* CSR_RX_DMA_WBQ_EN[5] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_RX_DMA_WBQ_EN_SHFT 5 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MEM_ARB_LOCK_EN_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MEM_ARB_LOCK_EN_MASK \ +0x00000010 /* CSR_MEM_ARB_LOCK_EN[4] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MEM_ARB_LOCK_EN_SHFT 4 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MEM_BST_SIZE_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MEM_BST_SIZE_MASK \ +0x0000000C /* CSR_MEM_BST_SIZE[3..2] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MEM_BST_SIZE_SHFT 2 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MAX_PREFETCH_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MAX_PREFETCH_CNT_MASK \ +0x00000003 /* CSR_MAX_PREFETCH_CNT[1..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MAX_PREFETCH_CNT_SHFT 0 + +/* +* ---WPDMA_GLO_CFG_EXT1 (0x18024000 + 0x2B4)--- +* CSR_TXFIFO0_RDY_THRESHOLD[7..0] - (RW) xxx +* CSR_TXFIFO1_RDY_THRESHOLD[15..8] - (RW) xxx +* CSR_TX_DISP_ARB_SCHEDULED_ACCESS_TIMER[23..16] - (RW) timer setting for +* SCHEDULED_ACCESS_TIME_ARB of csr_tx_disp_arb_mode +* CSR_TX_DISP_ARB_MODE[25..24] - (RW) 00 : FAIR_ARB, 01 : FIX_ARB, 10 : +* UNBALANCED_ARB, 11 : SCHEDULED_ACCESS_TIME_ARB +* CSR_FWDL_FLOW_CTRL_BYASS_EN[26] - (RW) To disable firmware download TX flow +* control of TX dma(host_dma1) when firmare download of RX dma(mcu_dma1) is in +* firmware download polling mode!! Remember to set to 1'b0 when firmware +download +* ring is set back to normal ring usage which should be in flow control for +* correct behavior!! +* CSR_FWDL_FLOW_CTRL_BYASS_LS_QSEL_EN[27] - (RW) select firmware download TX +* ring(LSB/MSB ring) to bypass TX flow control when firmare download RX +* ring(LSB/MSB ring) of RX dma(mcu_dma1) is in firmware download polling mode!! +* RESERVED28[30..28] - (RO) Reserved bits +* CSR_PF_WRAP_CALC_MODE[31] - (RW) 1'b0 : prefetch SRAM wrapping boundary +* is decided by bext ring base address 1'b1 : prefetch SRAM wrapping boundary +* is decided by prefetch max_cnt +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_PF_WRAP_CALC_MODE_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_PF_WRAP_CALC_MODE_MASK \ +0x80000000 /* CSR_PF_WRAP_CALC_MODE[31] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_PF_WRAP_CALC_MODE_SHFT 31 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_LS_QSEL_EN_ADDR \ + \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_LS_QSEL_EN_MASK \ + \ +0x08000000 /* CSR_FWDL_FLOW_CTRL_BYASS_LS_QSEL_EN[27] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_LS_QSEL_EN_SHFT \ + \ +27 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_EN_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_EN_MASK \ +0x04000000 /* CSR_FWDL_FLOW_CTRL_BYASS_EN[26] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_EN_SHFT \ +26 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_MODE_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_MODE_MASK \ +0x03000000 /* CSR_TX_DISP_ARB_MODE[25..24] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_MODE_SHFT 24 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_SCHEDULED_ACCESS_TIMER_AD\ +DR \ +\ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_SCHEDULED_ACCESS_TIMER_MA\ +SK \ +\ +0x00FF0000 /* CSR_TX_DISP_ARB_SCHEDULED_ACCESS_TIMER[23..16] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_SCHEDULED_ACCESS_TIMER_SH\ +FT \ +\ +16 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO1_RDY_THRESHOLD_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO1_RDY_THRESHOLD_MASK \ +0x0000FF00 /* CSR_TXFIFO1_RDY_THRESHOLD[15..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO1_RDY_THRESHOLD_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO0_RDY_THRESHOLD_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO0_RDY_THRESHOLD_MASK \ +0x000000FF /* CSR_TXFIFO0_RDY_THRESHOLD[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO0_RDY_THRESHOLD_SHFT 0 + +/* +* ---WPDMA_GLO_CFG_EXT2 (0x18024000 + 0x2B8)--- +* RESERVED0[15..0] - (RO) Reserved bits +* CSR_TX_DROP_MODE[17..16] - (RW) 2'h0 : No TX drop , 2'h1 : Ignore DMAD +* fetch and UDMA APB , 2'h2 : Flush TX dispatch queue +* RESERVED18[31..18] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT2_CSR_TX_DROP_MODE_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT2_CSR_TX_DROP_MODE_MASK \ +0x00030000 /* CSR_TX_DROP_MODE[17..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT2_CSR_TX_DROP_MODE_SHFT 16 + +/* +* ---WPDMA_TX_QOS_QTM_CFG0 (0x18024000 + 0x2D0)--- +* CSR_TXP0_FFA_QTM[3..0] - (RW) CSR_TXP0_FFA_QTM +* CSR_TXP0_RSVD_QTM[7..4] - (RW) CSR_TXP0_RSVD_QTM +* CSR_TXP1_FFA_QTM[11..8] - (RW) CSR_TXP1_FFA_QTM +* CSR_TXP1_RSVD_QTM[15..12] - (RW) CSR_TXP1_RSVD_QTM +* RESERVED16[23..16] - (RO) Reserved bits +* CSR_FFA_TOTAL_QTM[27..24] - (RW) CSR_FFA_TOTAL_QTM +* CSR_QOS_QTM_MODE[29..28] - (RW) 2'b01 : csr_rsvd_qtm_mode_only, 2'b10 : +* csr_ffa_qtm_mode_only, others : rsvd+ffa mode +* RESERVED30[31..30] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_QOS_QTM_MODE_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_QOS_QTM_MODE_MASK \ +0x30000000 /* CSR_QOS_QTM_MODE[29..28] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_QOS_QTM_MODE_SHFT 28 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_FFA_TOTAL_QTM_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_FFA_TOTAL_QTM_MASK \ +0x0F000000 /* CSR_FFA_TOTAL_QTM[27..24] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_FFA_TOTAL_QTM_SHFT 24 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP1_RSVD_QTM_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP1_RSVD_QTM_MASK \ +0x0000F000 /* CSR_TXP1_RSVD_QTM[15..12] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP1_RSVD_QTM_SHFT 12 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP1_FFA_QTM_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP1_FFA_QTM_MASK \ +0x00000F00 /* CSR_TXP1_FFA_QTM[11..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP1_FFA_QTM_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP0_RSVD_QTM_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP0_RSVD_QTM_MASK \ +0x000000F0 /* CSR_TXP0_RSVD_QTM[7..4] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP0_RSVD_QTM_SHFT 4 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP0_FFA_QTM_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP0_FFA_QTM_MASK \ +0x0000000F /* CSR_TXP0_FFA_QTM[3..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP0_FFA_QTM_SHFT 0 + +/* +* ---WPDMA_TX_QOS_QTM_CFG1 (0x18024000 + 0x2D4)--- +* CSR_DMAD_FFA_QTM[3..0] - (RW) CSR_DMAD_FFA_QTM +* CSR_DMAD_RSVD_QTM[7..4] - (RW) CSR_DMAD_RSVD_QTM +* CSR_TXD_FFA_QTM[11..8] - (RW) CSR_TXD_FFA_QTM +* CSR_TXD_RSVD_QTM[15..12] - (RW) CSR_TXD_RSVD_QTM +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_TXD_RSVD_QTM_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_TXD_RSVD_QTM_MASK \ +0x0000F000 /* CSR_TXD_RSVD_QTM[15..12] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_TXD_RSVD_QTM_SHFT 12 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_TXD_FFA_QTM_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_TXD_FFA_QTM_MASK \ +0x00000F00 /* CSR_TXD_FFA_QTM[11..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_TXD_FFA_QTM_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_DMAD_RSVD_QTM_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_DMAD_RSVD_QTM_MASK \ +0x000000F0 /* CSR_DMAD_RSVD_QTM[7..4] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_DMAD_RSVD_QTM_SHFT 4 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_DMAD_FFA_QTM_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_DMAD_FFA_QTM_MASK \ +0x0000000F /* CSR_DMAD_FFA_QTM[3..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_DMAD_FFA_QTM_SHFT 0 + +/* +* ---HOST_PRI_INT_STA (0x18024000 + 0x2E0)--- +* host_pri_int_sts_0[0] - (W1C) tx_done_int[18], W1C to clear delay +interrupt +* host_pri_int_sts_1[1] - (W1C) tx_done_int[19], W1C to clear delay +interrupt +* host_pri_int_sts_2[2] - (W1C) rx_done_int[0], W1C to clear delay +interrupt +* host_pri_int_sts_3[3] - (W1C) rx_done_int[1], W1C to clear delay +interrupt +* host_pri_int_sts_4[4] - (W1C) rx_done_int[2], W1C to clear delay +interrupt +* RESERVED5[31..5] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_4_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_4_MASK \ +0x00000010 /* host_pri_int_sts_4[4] */ +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_4_SHFT 4 +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_3_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_3_MASK \ +0x00000008 /* host_pri_int_sts_3[3] */ +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_2_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_2_MASK \ +0x00000004 /* host_pri_int_sts_2[2] */ +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_1_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_1_MASK \ +0x00000002 /* host_pri_int_sts_1[1] */ +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_0_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_0_MASK \ +0x00000001 /* host_pri_int_sts_0[0] */ +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_0_SHFT 0 + +/* +* ---HOST_PER_INT_ENA_STA (0x18024000 + 0x2E4)--- +* wpdma_per_int_sts[3..0] - (W1C) status bit for rx ring periodic delayed +* interrupt to tracking ring is full or not, start delayed interrupt timer when +* RX ring is not full from falling edge of full flag and reset when ring full +* flag is asserted +* RESERVED4[15..4] - (RO) Reserved bits +* wpdma_per_int_ena[19..16] - (RW) enable bit for rx ring periodic delayed +* interrupt to tracking ring is full or not, start delayed interrupt timer when +* RX ring is not full from falling edge of full flag and reset when ring full +* flag is asserted +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_wpdma_per_int_ena_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_wpdma_per_int_ena_MASK \ +0x000F0000 /* wpdma_per_int_ena[19..16] */ +#define WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_wpdma_per_int_ena_SHFT 16 +#define WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_wpdma_per_int_sts_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_wpdma_per_int_sts_MASK \ +0x0000000F /* wpdma_per_int_sts[3..0] */ +#define WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_wpdma_per_int_sts_SHFT 0 + +/* +* ---HOST_PER_DLY_INT_CFG (0x18024000 + 0x2E8)--- +* wpdma_per_max_ptime[7..0] - (RW) Specified Max pending time for the +* internal RX ring full flag falling edge. When the pending time equal or +greater +* PER_MAX_PTIME x 20us or the # of pended TX_DONE_INT equal or greater than +* TX_MAX_PINT (see above), an Final TX_DLY_INT is generated +* Set to 0 will disable pending interrupt +* time check +* wpdma_per_dly_int_en[11..8] - (RW) RX periodic Delayed Interrupt Enable +* 1: Enable RX periodic delayed interrupt +mechanism +* 0: Disable RX periodic delayed interrupt +mechanism +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_wpdma_per_dly_int_en_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_wpdma_per_dly_int_en_MASK \ +0x00000F00 /* wpdma_per_dly_int_en[11..8] */ +#define WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_wpdma_per_dly_int_en_SHFT 8 +#define WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_wpdma_per_max_ptime_ADDR \ +WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_wpdma_per_max_ptime_MASK \ +0x000000FF /* wpdma_per_max_ptime[7..0] */ +#define WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_wpdma_per_max_ptime_SHFT 0 + +/* +* ---WPDMA_PRI_DLY_INT_CFG0 (0x18024000 + 0x2F0)--- +* PRI0_MAX_PTIME[7..0] - (RW) Specified Max pending time for the +* internal PRI0_DONE_INT. When the pending time equal or greater PRI0_MAX_PTIME +x +* 20us or the # of pended PRI0_DONE_INT equal or greater than PRI0_MAX_PINT (see +* above), an Final PRI0_DLY_INT is generated +* Set to 0 will disable pending interrupt +* time check +* PRI0_MAX_PINT[14..8] - (RW) Specified Max # of pended interrupts. +* When the # of pended interrupts equal or +* greater than the value specified here or interrupt pending time reach the +limit +* (See below), a Final PRI0_DLY_INT is generated. +* Set to 0 will disable pending interrupt +* count check +* PRI0_DLY_INT_EN[15] - (RW) Priority Delayed Interrupt Enable +* 1: Enable Priority delayed interrupt +mechanism +* 0: Disable Priority delayed interrupt +mechanism +* In AXE host_dma0, these PRI1_* settings are +* for rx_ring[1]_int, and PRI0_* settings are for rx_ring[0]_int +* In AXE host_dma1, these PRI1_* settings are +* for rx_ring[0]_int, and PRI0_* settings are for Ored-tx_ring[14:0]_int +* In AXE mcu_dma0 and mcu_dma1, there are no +* priority interrupt thus no this 0x2E0 CR!! +* PRI1_MAX_PTIME[23..16] - (RW) Specified Max pending time for the +* internal PRI1_DONE_INT. When the pending time equal or greater PRI1_MAX_PTIME +x +* 20us or the # of pended PRI1_DONE_INT equal or greater than PRI1_MAX_PINT (see +* above), an Final PRI1_DLY_INT is generated +* Set to 0 will disable pending interrupt +* time check +* PRI1_MAX_PINT[30..24] - (RW) Specified Max # of pended interrupts. +* When the # of pended interrupts equal or +* greater than the value specified here or interrupt pending time reach the +limit +* (See below), a Final PRI1_DLY_INT is generated. +* Set to 0 will disable pending interrupt +* count check +* PRI1_DLY_INT_EN[31] - (RW) Priority Delayed Interrupt Enable +* 1: Enable Priority delayed interrupt +mechanism +* 0: Disable Priority delayed interrupt +mechanism +* In AXE host_dma0, these PRI1_* settings are +* for rx_ring[1]_int, and PRI0_* settings are for rx_ring[0]_int +* In AXE host_dma1, these PRI1_* settings are +* for rx_ring[0]_int, and PRI0_* settings are for Ored-tx_ring[14:0]_int +* In AXE mcu_dma0 and mcu_dma1, there are no +* priority interrupt thus no this 0x2E0 CR!! +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_DLY_INT_EN_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_DLY_INT_EN_MASK \ +0x80000000 /* PRI1_DLY_INT_EN[31] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_DLY_INT_EN_SHFT 31 +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PINT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PINT_MASK \ +0x7F000000 /* PRI1_MAX_PINT[30..24] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PINT_SHFT 24 +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PTIME_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PTIME_MASK \ +0x00FF0000 /* PRI1_MAX_PTIME[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PTIME_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_DLY_INT_EN_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_DLY_INT_EN_MASK \ +0x00008000 /* PRI0_DLY_INT_EN[15] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_DLY_INT_EN_SHFT 15 +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PINT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PINT_MASK \ +0x00007F00 /* PRI0_MAX_PINT[14..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PINT_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PTIME_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PTIME_MASK \ +0x000000FF /* PRI0_MAX_PTIME[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PTIME_SHFT 0 + +/* +* ---WPDMA_TX_RING0_CTRL0 (0x18024000 + 0x300)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring0 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING0_CTRL1 (0x18024000 + 0x304)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring0. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring0 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING0_CTRL2 (0x18024000 + 0x308)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING0_CTRL3 (0x18024000 + 0x30c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING1_CTRL0 (0x18024000 + 0x310)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring1 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING1_CTRL1 (0x18024000 + 0x314)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring1. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring1 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING1_CTRL2 (0x18024000 + 0x318)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING1_CTRL3 (0x18024000 + 0x31c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING2_CTRL0 (0x18024000 + 0x320)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring2 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING2_CTRL1 (0x18024000 + 0x324)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring2. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring2 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING2_CTRL2 (0x18024000 + 0x328)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING2_CTRL3 (0x18024000 + 0x32c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING3_CTRL0 (0x18024000 + 0x330)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring3 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING3_CTRL1 (0x18024000 + 0x334)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring3. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring3 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING3_CTRL2 (0x18024000 + 0x338)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING3_CTRL3 (0x18024000 + 0x33c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING4_CTRL0 (0x18024000 + 0x340)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring4 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING4_CTRL1 (0x18024000 + 0x344)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring4. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring4 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING4_CTRL2 (0x18024000 + 0x348)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING4_CTRL3 (0x18024000 + 0x34c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING5_CTRL0 (0x18024000 + 0x350)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring5 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING5_CTRL1 (0x18024000 + 0x354)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring5. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring5 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING5_CTRL2 (0x18024000 + 0x358)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING5_CTRL3 (0x18024000 + 0x35c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING6_CTRL0 (0x18024000 + 0x360)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring6 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING6_CTRL1 (0x18024000 + 0x364)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring6. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring6 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING6_CTRL2 (0x18024000 + 0x368)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING6_CTRL3 (0x18024000 + 0x36c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING7_CTRL0 (0x18024000 + 0x370)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring7 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING7_CTRL1 (0x18024000 + 0x374)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring7. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring7 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING7_CTRL2 (0x18024000 + 0x378)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING7_CTRL3 (0x18024000 + 0x37c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING8_CTRL0 (0x18024000 + 0x380)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring0 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING8_CTRL1 (0x18024000 + 0x384)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring0. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring0 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING8_CTRL2 (0x18024000 + 0x388)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING8_CTRL3 (0x18024000 + 0x38c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING9_CTRL0 (0x18024000 + 0x390)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring1 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING9_CTRL1 (0x18024000 + 0x394)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring1. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring1 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING9_CTRL2 (0x18024000 + 0x398)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING9_CTRL3 (0x18024000 + 0x39c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING10_CTRL0 (0x18024000 + 0x3a0)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring2 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING10_CTRL1 (0x18024000 + 0x3a4)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring2. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring2 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING10_CTRL2 (0x18024000 + 0x3a8)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING10_CTRL3 (0x18024000 + 0x3ac)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING11_CTRL0 (0x18024000 + 0x3b0)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring3 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING11_CTRL1 (0x18024000 + 0x3b4)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring3. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring3 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING11_CTRL2 (0x18024000 + 0x3b8)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING11_CTRL3 (0x18024000 + 0x3bc)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING12_CTRL0 (0x18024000 + 0x3c0)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring4 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING12_CTRL1 (0x18024000 + 0x3c4)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring4. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring4 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING12_CTRL2 (0x18024000 + 0x3c8)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING12_CTRL3 (0x18024000 + 0x3cc)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING13_CTRL0 (0x18024000 + 0x3d0)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring5 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING13_CTRL1 (0x18024000 + 0x3d4)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring5. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring5 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING13_CTRL2 (0x18024000 + 0x3d8)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING13_CTRL3 (0x18024000 + 0x3dc)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING14_CTRL0 (0x18024000 + 0x3e0)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring6 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING14_CTRL1 (0x18024000 + 0x3e4)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring6. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring6 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING14_CTRL2 (0x18024000 + 0x3e8)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING14_CTRL3 (0x18024000 + 0x3ec)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING15_CTRL0 (0x18024000 + 0x3f0)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring7 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING15_CTRL1 (0x18024000 + 0x3f4)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring7. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring7 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING15_CTRL2 (0x18024000 + 0x3f8)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING15_CTRL3 (0x18024000 + 0x3fc)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING16_CTRL0 (0x18024000 + 0x400)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_RING16 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING16_CTRL1 (0x18024000 + 0x404)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_RING16. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring16 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING16_CTRL2 (0x18024000 + 0x408)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING16_CTRL3 (0x18024000 + 0x40c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING17_CTRL0 (0x18024000 + 0x410)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring17 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING17_CTRL1 (0x18024000 + 0x414)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring17. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring17 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING17_CTRL2 (0x18024000 + 0x418)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING17_CTRL3 (0x18024000 + 0x41c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING18_CTRL0 (0x18024000 + 0x420)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring18 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING18_CTRL1 (0x18024000 + 0x424)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring18. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring18 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING18_CTRL2 (0x18024000 + 0x428)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING18_CTRL3 (0x18024000 + 0x42c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING0_CTRL0 (0x18024000 + 0x500)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #0 +* (GE ports). It should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING0_CTRL1 (0x18024000 + 0x504)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD +* Ring #0. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* RX_Ring0 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING0_CTRL2 (0x18024000 + 0x508)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to +* allocate to RXD Ring #0. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING0_CTRL3 (0x18024000 + 0x50c)--- +* DMA_IDX[11..0] - (RW) Point to the next RXD PDMA engine wants +* to use for RXD Ring #0. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING1_CTRL0 (0x18024000 + 0x510)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #1 +* (GE ports). It should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING1_CTRL1 (0x18024000 + 0x514)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD +* Ring #1. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* RX_Ring1 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING1_CTRL2 (0x18024000 + 0x518)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to +* allocate to RXD Ring #1. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING1_CTRL3 (0x18024000 + 0x51c)--- +* DMA_IDX[11..0] - (RW) Point to the next RXD PDMA engine wants +* to use for RXD Ring #1. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING2_CTRL0 (0x18024000 + 0x520)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #2 +* (GE ports). It should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING2_CTRL1 (0x18024000 + 0x524)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD +* Ring #2. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* RX_Ring2 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING2_CTRL2 (0x18024000 + 0x528)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to +* allocate to RXD Ring #2. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING2_CTRL3 (0x18024000 + 0x52C)--- +* DMA_IDX[11..0] - (RW) Point to the next RXD PDMA engine wants +* to use for RXD Ring #2. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING3_CTRL0 (0x18024000 + 0x530)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #3 +* (GE ports). It should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING3_CTRL1 (0x18024000 + 0x534)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD +* Ring #3. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* RX_Ring3 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING3_CTRL2 (0x18024000 + 0x538)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to +* allocate to RXD Ring #3. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING3_CTRL3 (0x18024000 + 0x53C)--- +* DMA_IDX[11..0] - (RW) Point to the next RXD PDMA engine wants +* to use for RXD Ring #3. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING4_CTRL0 (0x18024000 + 0x540)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #4 +* (GE ports). It should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING4_CTRL1 (0x18024000 + 0x544)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD +* Ring #4. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* RX_Ring4 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING4_CTRL2 (0x18024000 + 0x548)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to +* allocate to RXD Ring #4. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING4_CTRL3 (0x18024000 + 0x54c)--- +* DMA_IDX[11..0] - (RW) Point to the next RXD PDMA engine wants +* to use for RXD Ring #4. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING5_CTRL0 (0x18024000 + 0x550)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #5 +* (GE ports). It should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING5_CTRL1 (0x18024000 + 0x554)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD +* Ring #5. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* RX_Ring5 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING5_CTRL2 (0x18024000 + 0x558)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to +* allocate to RXD Ring #5. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING5_CTRL3 (0x18024000 + 0x55c)--- +* DMA_IDX[11..0] - (RW) Point to the next RXD PDMA engine wants +* to use for RXD Ring #5. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING6_CTRL0 (0x18024000 + 0x560)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #6 +* (GE ports). It should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING6_CTRL1 (0x18024000 + 0x564)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD +* Ring #6. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* RX_Ring6 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING6_CTRL2 (0x18024000 + 0x568)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to +* allocate to RXD Ring #6. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING6_CTRL3 (0x18024000 + 0x56C)--- +* DMA_IDX[11..0] - (RW) Point to the next RXD PDMA engine wants +* to use for RXD Ring #6. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING7_CTRL0 (0x18024000 + 0x570)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #7 +* (GE ports). It should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL0_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL0_BASE_PTR_MASK \ +0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING7_CTRL1 (0x18024000 + 0x574)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD +* Ring #7. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* RX_Ring7 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL1_BASE_PTR_EXT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL1_BASE_PTR_EXT_MASK \ +0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL1_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL1_MAX_CNT_MASK \ +0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING7_CTRL2 (0x18024000 + 0x578)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to +* allocate to RXD Ring #7. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL2_CPU_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL2_CPU_IDX_MASK \ +0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING7_CTRL3 (0x18024000 + 0x57C)--- +* DMA_IDX[11..0] - (RW) Point to the next RXD PDMA engine wants +* to use for RXD Ring #7. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL3_DMA_IDX_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL3_DMA_IDX_MASK \ +0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING0_EXT_CTRL (0x18024000 + 0x600)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #0 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING1_EXT_CTRL (0x18024000 + 0x604)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #1 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING2_EXT_CTRL (0x18024000 + 0x608)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #2 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING3_EXT_CTRL (0x18024000 + 0x60C)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #3 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING4_EXT_CTRL (0x18024000 + 0x610)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #4 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING5_EXT_CTRL (0x18024000 + 0x614)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #5 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING6_EXT_CTRL (0x18024000 + 0x618)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #6 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING7_EXT_CTRL (0x18024000 + 0x61C)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #7 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING8_EXT_CTRL (0x18024000 + 0x620)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #0 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING9_EXT_CTRL (0x18024000 + 0x624)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #1 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING10_EXT_CTRL (0x18024000 + 0x628)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #2 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING11_EXT_CTRL (0x18024000 + 0x62C)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #3 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING12_EXT_CTRL (0x18024000 + 0x630)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #4 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING13_EXT_CTRL (0x18024000 + 0x634)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #5 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING14_EXT_CTRL (0x18024000 + 0x638)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #6 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING15_EXT_CTRL (0x18024000 + 0x63C)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #7 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING16_EXT_CTRL (0x18024000 + 0x640)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #16 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING17_EXT_CTRL (0x18024000 + 0x644)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #17 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING18_EXT_CTRL (0x18024000 + 0x648)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #18 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING0_EXT_CTRL (0x18024000 + 0x680)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #0 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING1_EXT_CTRL (0x18024000 + 0x684)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #1 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING2_EXT_CTRL (0x18024000 + 0x688)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #2 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING3_EXT_CTRL (0x18024000 + 0x68C)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #3 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING4_EXT_CTRL (0x18024000 + 0x690)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #4 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING5_EXT_CTRL (0x18024000 + 0x694)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #5 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING6_EXT_CTRL (0x18024000 + 0x698)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #6 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING7_EXT_CTRL (0x18024000 + 0x69C)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #7 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_EXT_CTRL_DISP_BASE_PTR_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_EXT_CTRL_DISP_BASE_PTR_MASK \ +0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_EXT_CTRL_DISP_MAX_CNT_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_EXT_CTRL_DISP_MAX_CNT_MASK \ +0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING0_BKRS_CTRL0 (0x18024000 + 0xA00)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING0_BKRS_CTRL1 (0x18024000 + 0xA04)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING0_BKRS_CTRL2 (0x18024000 + 0xA08)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING1_BKRS_CTRL0 (0x18024000 + 0xA10)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING1_BKRS_CTRL1 (0x18024000 + 0xA14)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING1_BKRS_CTRL2 (0x18024000 + 0xA18)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING2_BKRS_CTRL0 (0x18024000 + 0xA20)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING2_BKRS_CTRL1 (0x18024000 + 0xA24)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING2_BKRS_CTRL2 (0x18024000 + 0xA28)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING3_BKRS_CTRL0 (0x18024000 + 0xA30)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING3_BKRS_CTRL1 (0x18024000 + 0xA34)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING3_BKRS_CTRL2 (0x18024000 + 0xA38)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING4_BKRS_CTRL0 (0x18024000 + 0xA40)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING4_BKRS_CTRL1 (0x18024000 + 0xA44)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING4_BKRS_CTRL2 (0x18024000 + 0xA48)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING5_BKRS_CTRL0 (0x18024000 + 0xA50)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING5_BKRS_CTRL1 (0x18024000 + 0xA54)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING5_BKRS_CTRL2 (0x18024000 + 0xA58)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING6_BKRS_CTRL0 (0x18024000 + 0xA60)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING6_BKRS_CTRL1 (0x18024000 + 0xA64)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING6_BKRS_CTRL2 (0x18024000 + 0xA68)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING7_BKRS_CTRL0 (0x18024000 + 0xA70)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING7_BKRS_CTRL1 (0x18024000 + 0xA74)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING7_BKRS_CTRL2 (0x18024000 + 0xA78)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING7_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING8_BKRS_CTRL0 (0x18024000 + 0xA80)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING8_BKRS_CTRL1 (0x18024000 + 0xA84)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING8_BKRS_CTRL2 (0x18024000 + 0xA88)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING8_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING9_BKRS_CTRL0 (0x18024000 + 0xA90)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING9_BKRS_CTRL1 (0x18024000 + 0xA94)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING9_BKRS_CTRL2 (0x18024000 + 0xA98)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING9_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING10_BKRS_CTRL0 (0x18024000 + 0xAA0)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING10_BKRS_CTRL1 (0x18024000 + 0xAA4)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING10_BKRS_CTRL2 (0x18024000 + 0xAA8)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING10_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING11_BKRS_CTRL0 (0x18024000 + 0xAB0)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING11_BKRS_CTRL1 (0x18024000 + 0xAB4)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING11_BKRS_CTRL2 (0x18024000 + 0xAB8)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING11_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING12_BKRS_CTRL0 (0x18024000 + 0xAC0)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING12_BKRS_CTRL1 (0x18024000 + 0xAC4)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING12_BKRS_CTRL2 (0x18024000 + 0xAC8)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING12_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING13_BKRS_CTRL0 (0x18024000 + 0xAD0)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING13_BKRS_CTRL1 (0x18024000 + 0xAD4)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING13_BKRS_CTRL2 (0x18024000 + 0xAD8)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING13_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING14_BKRS_CTRL0 (0x18024000 + 0xAE0)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING14_BKRS_CTRL1 (0x18024000 + 0xAE4)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING14_BKRS_CTRL2 (0x18024000 + 0xAE8)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING14_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING15_BKRS_CTRL0 (0x18024000 + 0xAF0)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING15_BKRS_CTRL1 (0x18024000 + 0xAF4)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING15_BKRS_CTRL2 (0x18024000 + 0xAF8)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING15_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING16_BKRS_CTRL0 (0x18024000 + 0xB00)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING16_BKRS_CTRL1 (0x18024000 + 0xB04)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING16_BKRS_CTRL2 (0x18024000 + 0xB08)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING17_BKRS_CTRL0 (0x18024000 + 0xB10)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING17_BKRS_CTRL1 (0x18024000 + 0xB14)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING17_BKRS_CTRL2 (0x18024000 + 0xB18)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING18_BKRS_CTRL0 (0x18024000 + 0xB20)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING18_BKRS_CTRL1 (0x18024000 + 0xB24)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING18_BKRS_CTRL2 (0x18024000 + 0xB28)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING0_BKRS_CTRL0 (0x18024000 + 0xC00)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING0_BKRS_CTRL1 (0x18024000 + 0xC04)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING0_BKRS_CTRL2 (0x18024000 + 0xC08)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING1_BKRS_CTRL0 (0x18024000 + 0xC10)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING1_BKRS_CTRL1 (0x18024000 + 0xC14)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING1_BKRS_CTRL2 (0x18024000 + 0xC18)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING2_BKRS_CTRL0 (0x18024000 + 0xC20)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING2_BKRS_CTRL1 (0x18024000 + 0xC24)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING2_BKRS_CTRL2 (0x18024000 + 0xC28)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING3_BKRS_CTRL0 (0x18024000 + 0xC30)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING3_BKRS_CTRL1 (0x18024000 + 0xC34)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING3_BKRS_CTRL2 (0x18024000 + 0xC38)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING4_BKRS_CTRL0 (0x18024000 + 0xC40)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING4_BKRS_CTRL1 (0x18024000 + 0xC44)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING4_BKRS_CTRL2 (0x18024000 + 0xC48)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING5_BKRS_CTRL0 (0x18024000 + 0xC50)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING5_BKRS_CTRL1 (0x18024000 + 0xC54)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING5_BKRS_CTRL2 (0x18024000 + 0xC58)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING6_BKRS_CTRL0 (0x18024000 + 0xC60)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING6_BKRS_CTRL1 (0x18024000 + 0xC64)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING6_BKRS_CTRL2 (0x18024000 + 0xC68)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING7_BKRS_CTRL0 (0x18024000 + 0xC70)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING7_BKRS_CTRL1 (0x18024000 + 0xC74)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING7_BKRS_CTRL2 (0x18024000 + 0xC78)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING8_BKRS_CTRL0 (0x18024000 + 0xC80)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL0_pf_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL0_pf_didx_idx_MASK \ +0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL0_pld_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL0_pld_didx_idx_MASK \ +0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING8_BKRS_CTRL1 (0x18024000 + 0xC84)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL1_disp_didx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL1_disp_didx_idx_MASK \ +0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL1_disp_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL1_disp_cidx_idx_MASK \ +0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING8_BKRS_CTRL2 (0x18024000 + 0xC88)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL2_disp_ring_vld_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL2_disp_ring_vld_MASK \ +0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL2_pf_dq_ring_empty_MASK \ +0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL2_pf_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL2_pf_ring_empty_MASK \ +0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL2_pld_ring_empty_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL2_pld_ring_empty_MASK \ +0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL2_pld_cidx_idx_ADDR \ +WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL2_pld_cidx_idx_MASK \ +0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +#ifdef __cplusplus +} +#endif + +#endif /* __WF_WFDMA_HOST_DMA0_REGS_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/soc3_0/conn_infra_cfg.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/soc3_0/conn_infra_cfg.h new file mode 100644 index 0000000000000..897b727cc6f03 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/soc3_0/conn_infra_cfg.h @@ -0,0 +1,75 @@ +/* +*[File] : conn_infra_cfg.h +*[Revision time] : Tue Apr 16 15:11:54 2019 +*[Description] : This file is auto generated by CODA +*[Copyright] : Copyright (C) 2019 Mediatek Incorportion. +* All rights reserved. +*/ + +#ifndef __CONN_INFRA_CFG_REGS_H__ +#define __CONN_INFRA_CFG_REGS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +/**************************************************************************** +* +* CONN_INFRA_CFG CR Definitions +* +***************************************************************************** +*/ +#define CONN_INFRA_CFG_BASE 0x7C001000 +#define CONN_INFRA_CFG_AP2WF_BUS_ADDR 0x7C500000 +#define CONN_INFRA_CFG_PCIE2AP_REMAP_2_ADDR_DE_HARDCODE 0x18501844 + +#define CONN_INFRA_CFG_CONN_HW_VER_ADDR \ + (CONN_INFRA_CFG_BASE + 0x0000) /* 1000 */ +#define CONN_INFRA_CFG_CONN_CFG_ID_ADDR \ + (CONN_INFRA_CFG_BASE + 0x0004) /* 1004 */ +#define CONN_INFRA_CFG_CONN_FPGA_DUMMY0_ADDR \ + (CONN_INFRA_CFG_BASE + 0x0010) /* 1010 */ +#define CONN_INFRA_CFG_CONN_FPGA_DUMMY1_ADDR \ + (CONN_INFRA_CFG_BASE + 0x0014) /* 1014 */ +#define CONN_INFRA_CFG_EASY_SECURITY_WF_IRQ_CLR_ADDR \ + (CONN_INFRA_CFG_BASE + 0x00E0) /* 10E0 */ +#define CONN_INFRA_CFG_EASY_SECURITY_BGF_IRQ_CLR_ADDR \ + (CONN_INFRA_CFG_BASE + 0x00E4) /* 10E4 */ +#define CONN_INFRA_CFG_LIGHT_SECURITY_CTRL_ADDR \ + (CONN_INFRA_CFG_BASE + 0x00F0) /* 10F0 */ +#define CONN_INFRA_CFG_BUS_DEAD_CR_ADDRESS_ADDR \ + (CONN_INFRA_CFG_BASE + 0x00FC) /* 10FC */ +#define CONN_INFRA_CFG_AP2BGF_REMAP_0_ADDR \ + (CONN_INFRA_CFG_BASE + 0x0100) /* 1100 */ +#define CONN_INFRA_CFG_AP2BGF_REMAP_1_ADDR \ + (CONN_INFRA_CFG_BASE + 0x0104) /* 1104 */ +#define CONN_INFRA_CFG_AP2BGF_REMAP_2_ADDR \ + (CONN_INFRA_CFG_BASE + 0x0108) /* 1108 */ +#define CONN_INFRA_CFG_AP2BGF_REMAP_SEG_0_ADDR \ + (CONN_INFRA_CFG_BASE + 0x010C) /* 110C */ +#define CONN_INFRA_CFG_AP2BGF_REMAP_SEG_1_ADDR \ + (CONN_INFRA_CFG_BASE + 0x0110) /* 1110 */ +#define CONN_INFRA_CFG_SUBSYS2AP_REMAP_0_ADDR \ + (CONN_INFRA_CFG_BASE + 0x0114) /* 1114 */ +#define CONN_INFRA_CFG_AP2BGF_REMAP_3_ADDR \ + (CONN_INFRA_CFG_BASE + 0x0118) /* 1118 */ +#define CONN_INFRA_CFG_AP2WF_REMAP_0_ADDR \ + (CONN_INFRA_CFG_BASE + 0x011C) /* 111C */ + +/********************************************** +* Only define referenced CRs +*********************************************** +*/ + +#define CONN_INFRA_CFG_AP2WF_REMAP_1_ADDR \ + (CONN_INFRA_CFG_BASE + 0x0120) /* 1120 */ + +#define CONN_INFRA_CFG_PCIE2AP_REMAP_2_ADDR \ + (CONN_INFRA_CFG_BASE + 0x0198) /* 1198 */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CONN_INFRA_CFG_REGS_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/soc3_0/wf_hif_dmashdl_top.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/soc3_0/wf_hif_dmashdl_top.h new file mode 100644 index 0000000000000..87c492dd20a62 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/soc3_0/wf_hif_dmashdl_top.h @@ -0,0 +1,2361 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +/* [File] : wf_hif_dmashdl_top.h */ +/* [Revision time] : Tue Aug 6 17:14:15 2019 */ +/* [Description] : This file is auto generated by CODA */ +/* [Copyright] : Copyright (C) 2019 Mediatek Incorportion. All rights */ +/* reserved. */ + +#ifndef __WF_HIF_DMASHDL_TOP_REGS_H__ +#define __WF_HIF_DMASHDL_TOP_REGS_H__ + + +#ifdef __cplusplus +extern "C" { +#endif + +/* ************************************************************************** */ +/* */ +/* WF_HIF_DMASHDL_TOP CR Definitions */ +/* */ +/* ************************************************************************** */ + +#define WF_HIF_DMASHDL_TOP_BASE 0x7C026000 + +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x00) /* 6000 */ +#define WF_HIF_DMASHDL_TOP_SW_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x04) /* 6004 */ +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x08) /* 6008 */ +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x0C) /* 600C */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x10) /* 6010 */ +#define WF_HIF_DMASHDL_TOP_TX_PACKET_SIZE_PAGE_MAP_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x14) /* 6014 */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x18) /* 6018 */ +#define WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x1c) /* 601C */ +#define WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x20) /* 6020 */ +#define WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x24) /* 6024 */ +#define WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x28) /* 6028 */ +#define WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x2C) /* 602C */ +#define WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x30) /* 6030 */ +#define WF_HIF_DMASHDL_TOP_GROUP5_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x34) /* 6034 */ +#define WF_HIF_DMASHDL_TOP_GROUP6_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x38) /* 6038 */ +#define WF_HIF_DMASHDL_TOP_GROUP7_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x3C) /* 603C */ +#define WF_HIF_DMASHDL_TOP_GROUP8_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x40) /* 6040 */ +#define WF_HIF_DMASHDL_TOP_GROUP9_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x44) /* 6044 */ +#define WF_HIF_DMASHDL_TOP_GROUP10_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x48) /* 6048 */ +#define WF_HIF_DMASHDL_TOP_GROUP11_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x4C) /* 604C */ +#define WF_HIF_DMASHDL_TOP_GROUP12_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x50) /* 6050 */ +#define WF_HIF_DMASHDL_TOP_GROUP13_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x54) /* 6054 */ +#define WF_HIF_DMASHDL_TOP_GROUP14_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x58) /* 6058 */ +#define WF_HIF_DMASHDL_TOP_GROUP15_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x5C) /* 605C */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD0_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x70) /* 6070 */ +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT00_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x80) /* 6080 */ +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT01_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x84) /* 6084 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x88) /* 6088 */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x8C) /* 608C */ +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x90) /* 6090 */ +#define WF_HIF_DMASHDL_TOP_HIF_ASK_LONG_CHECK_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x94) /* 6094 */ +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x98) /* 6098 */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x9c) /* 609C */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0xB0) /* 60B0 */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0xB4) /* 60B4 */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0xC4) /* 60C4 */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0xC8) /* 60C8 */ +#define WF_HIF_DMASHDL_TOP_SLOT_PERIOD_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0xCC) /* 60CC */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0xd0) /* 60D0 */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0xd4) /* 60D4 */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0xd8) /* 60D8 */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0xdc) /* 60DC */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x100) /* 6100 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x140) /* 6140 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP1_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x144) /* 6144 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP2_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x148) /* 6148 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP3_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x14c) /* 614C */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP4_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x150) /* 6150 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP5_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x154) /* 6154 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP6_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x158) /* 6158 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP7_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x15C) /* 615C */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP8_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x160) /* 6160 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP9_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x164) /* 6164 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP10_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x168) /* 6168 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP11_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x16c) /* 616C */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP12_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x170) /* 6170 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP13_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x174) /* 6174 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP14_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x178) /* 6178 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP15_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x17C) /* 617C */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x180) /* 6180 */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x184) /* 6184 */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x188) /* 6188 */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x18c) /* 618C */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x190) /* 6190 */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x194) /* 6194 */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x198) /* 6198 */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x19c) /* 619C */ + +/* +* ---WACPU_REFILL (0x7C026000 + 0x00)--- +* WACPU_RETURN_PAGE_CNT[11..0] - (RW) WACPU refill page count +* RESERVED12[15..12] - (RO) Reserved bits +* WACPU_RETRUN_QID[20..16] - (RW) WACPU refill queue ID +* RESERVED21[23..21] - (RO) Reserved bits +* WACPU_RETRUN_MODE[25..24] - (RW) WACPU refill mode selection +* 2'b00 : Return mode +* 2'b01 : Add reservation mode(initial quota +setting) +* 2'b10 : Substrate source mode +* 2'b11 : Add source mode +* RESERVED26[30..26] - (RO) Reserved bits +* WACPU_EXCUTE[31] - (WO) Excute this CR action +*/ +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_EXCUTE_ADDR \ + WF_HIF_DMASHDL_TOP_WACPU_REFILL_ADDR +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_EXCUTE_MASK \ + 0x80000000 /* WACPU_EXCUTE[31] */ +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_EXCUTE_SHFT 31 +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETRUN_MODE_ADDR \ + WF_HIF_DMASHDL_TOP_WACPU_REFILL_ADDR +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETRUN_MODE_MASK \ + 0x03000000 /* WACPU_RETRUN_MODE[25..24] */ +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETRUN_MODE_SHFT 24 +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETRUN_QID_ADDR \ + WF_HIF_DMASHDL_TOP_WACPU_REFILL_ADDR +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETRUN_QID_MASK \ + 0x001F0000 /* WACPU_RETRUN_QID[20..16] */ +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETRUN_QID_SHFT 16 +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETURN_PAGE_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_WACPU_REFILL_ADDR +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETURN_PAGE_CNT_MASK \ + 0x00000FFF /* WACPU_RETURN_PAGE_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETURN_PAGE_CNT_SHFT 0 + +/* +* ---SW_CONTROL (0x7C026000 + 0x04)--- +* SW_LOG_RESET[0] - (RW) SW reset logic function action +* RESERVED1[27..1] - (RO) Reserved bits +* DMASHDL_BYPASS[28] - (RW) DMASHDL host ask and quota control +* function bypass +* RESERVED29[31..29] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_SW_CONTROL_DMASHDL_BYPASS_ADDR \ + WF_HIF_DMASHDL_TOP_SW_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_SW_CONTROL_DMASHDL_BYPASS_MASK \ + 0x10000000 /* DMASHDL_BYPASS[28] */ +#define WF_HIF_DMASHDL_TOP_SW_CONTROL_DMASHDL_BYPASS_SHFT 28 +#define WF_HIF_DMASHDL_TOP_SW_CONTROL_SW_LOG_RESET_ADDR \ + WF_HIF_DMASHDL_TOP_SW_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_SW_CONTROL_SW_LOG_RESET_MASK \ + 0x00000001 /* SW_LOG_RESET[0] */ +#define WF_HIF_DMASHDL_TOP_SW_CONTROL_SW_LOG_RESET_SHFT 0 + +/* +* ---OPTIONAL_CONTROL (0x7C026000 + 0x08)--- +* CR_HIF_GUP_ACT_MAP[15..0] - (RW) Group active mapping to joint the hif +* ask round robin setting in hif_ack_cnt_th period. +* Bit 0: group 0 joint active setting (1: +* joint, 0: disjoint) +* Bit 1: group 1 joint active setting (1: +* joint, 0: disjoint) +* Bit 2: group 2 joint active setting (1: +* joint, 0: disjoint) +* Bit 3: group 3 joint active setting (1: +* joint, 0: disjoint) +* Bit 4: group 4 joint active setting (1: +* joint, 0: disjoint) +* Bit 5: group 5 joint active setting (1: +* joint, 0: disjoint) +* Bit 6: group 6 joint active setting (1: +* joint, 0: disjoint) +* Bit 7: group 7 joint active setting (1: +* joint, 0: disjoint) +* Bit 8: group 8 joint active setting (1: +* joint, 0: disjoint) +* Bit 9: group 9 joint active setting (1: +* joint, 0: disjoint) +...... +* Bit 15: group 15 joint active setting (1: +* joint, 0: disjoint) +* CR_HIF_ACK_CNT_TH[23..16] - (RW) Host ask success count threshold setting +* to reset initial for round robin period +* RESERVED24[27..24] - (RO) Reserved bits +* CR_HIF_ASK_RR_ENA[28] - (RW) HIF ask round robin like arbiter enable +* CR_HIF_ASK_MIN_RR_ENA[29] - (RW) Source count below minimum quota check +* enable by round robin like arbitration +* CR_PSEBF_BL_TH2_NOBMIN_RASIGN_ENA[30] - (RW) Assignment when all TXD groups +* great or equal minimum quota +* CR_PSEBF_BL_TH2_CHK_DISABLE[31] - (RW) Disable PSE buffer Threshold 2 check +* and assignment +*/ +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_PSEBF_BL_TH2_CHK_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_PSEBF_BL_TH2_CHK_DISABLE_MASK \ + 0x80000000 /* CR_PSEBF_BL_TH2_CHK_DISABLE[31] */ +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_PSEBF_BL_TH2_CHK_DISABLE_SHFT 31 +#define \ +WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_PSEBF_BL_TH2_NOBMIN_RASIGN_ENA_ADDR \ + \ + WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_ADDR +#define \ +WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_PSEBF_BL_TH2_NOBMIN_RASIGN_ENA_MASK \ + \ + 0x40000000 /* CR_PSEBF_BL_TH2_NOBMIN_RASIGN_ENA[30] */ +#define \ +WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_PSEBF_BL_TH2_NOBMIN_RASIGN_ENA_SHFT \ + \ + 30 +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_ASK_MIN_RR_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_ASK_MIN_RR_ENA_MASK \ + 0x20000000 /* CR_HIF_ASK_MIN_RR_ENA[29] */ +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_ASK_MIN_RR_ENA_SHFT 29 +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_ASK_RR_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_ASK_RR_ENA_MASK \ + 0x10000000 /* CR_HIF_ASK_RR_ENA[28] */ +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_ASK_RR_ENA_SHFT 28 +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_ACK_CNT_TH_ADDR \ + WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_ACK_CNT_TH_MASK \ + 0x00FF0000 /* CR_HIF_ACK_CNT_TH[23..16] */ +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_ACK_CNT_TH_SHFT 16 +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_GUP_ACT_MAP_ADDR \ + WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_GUP_ACT_MAP_MASK \ + 0x0000FFFF /* CR_HIF_GUP_ACT_MAP[15..0] */ +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_GUP_ACT_MAP_SHFT 0 + +/* +* ---PAGE_SETTING (0x7C026000 + 0x0C)--- +* PSE_ADD_BSIZE[9..0] - (RW) PSE(command) packet size add extra byte +count +* RESERVED10[11..10] - (RO) Reserved bits +* PP_OFFSET_ADD_ENA[12] - (RW) PSE(command) packet size add offset +* enable from packet processor +* RESERVED13[15..13] - (RO) Reserved bits +* GROUP_SEQUENCE_ORDER_TYPE[16] - (RW) User program group sequence type +control +* SLOT_TYPE_ARBITER_CONTROL[17] - (RW) Slot type arbiter control +* DUMMY_00[18] - (RW) Dummy_00 bit +* DUMMY_01[19] - (RW) Dummy_01 bit +* SRC_CNT_PRI_EN[20] - (RW) Source count below min quota first +* priority check enable +* QUP_ACL_SLOT_CG_EN[21] - (RW) Group ack then slot ID change function +enable +* RESERVED22[31..22] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_QUP_ACL_SLOT_CG_EN_ADDR \ + WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_QUP_ACL_SLOT_CG_EN_MASK \ + 0x00200000 /* QUP_ACL_SLOT_CG_EN[21] */ +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_QUP_ACL_SLOT_CG_EN_SHFT 21 +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_SRC_CNT_PRI_EN_ADDR \ + WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_SRC_CNT_PRI_EN_MASK \ + 0x00100000 /* SRC_CNT_PRI_EN[20] */ +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_SRC_CNT_PRI_EN_SHFT 20 +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_DUMMY_01_ADDR \ + WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_DUMMY_01_MASK \ + 0x00080000 /* DUMMY_01[19] */ +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_DUMMY_01_SHFT 19 +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_DUMMY_00_ADDR \ + WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_DUMMY_00_MASK \ + 0x00040000 /* DUMMY_00[18] */ +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_DUMMY_00_SHFT 18 +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_SLOT_TYPE_ARBITER_CONTROL_ADDR \ + WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_SLOT_TYPE_ARBITER_CONTROL_MASK \ + 0x00020000 /* SLOT_TYPE_ARBITER_CONTROL[17] */ +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_SLOT_TYPE_ARBITER_CONTROL_SHFT 17 +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_GROUP_SEQUENCE_ORDER_TYPE_ADDR \ + WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_GROUP_SEQUENCE_ORDER_TYPE_MASK \ + 0x00010000 /* GROUP_SEQUENCE_ORDER_TYPE[16] */ +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_GROUP_SEQUENCE_ORDER_TYPE_SHFT 16 +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_PP_OFFSET_ADD_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_PP_OFFSET_ADD_ENA_MASK \ + 0x00001000 /* PP_OFFSET_ADD_ENA[12] */ +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_PP_OFFSET_ADD_ENA_SHFT 12 +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_PSE_ADD_BSIZE_ADDR \ + WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_PSE_ADD_BSIZE_MASK \ + 0x000003FF /* PSE_ADD_BSIZE[9..0] */ +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_PSE_ADD_BSIZE_SHFT 0 + +/* +* ---REFILL_CONTROL (0x7C026000 + 0x10)--- +* GROUP0_REFILL_PRIORITY[0] - (RW) Group0 refill priority +* GROUP1_REFILL_PRIORITY[1] - (RW) Group1 refill priority +* GROUP2_REFILL_PRIORITY[2] - (RW) Group2 refill priority +* GROUP3_REFILL_PRIORITY[3] - (RW) Group3 refill priority +* GROUP4_REFILL_PRIORITY[4] - (RW) Group4 refill priority +* GROUP5_REFILL_PRIORITY[5] - (RW) Group5 refill priority +* GROUP6_REFILL_PRIORITY[6] - (RW) Group6 refill priority +* GROUP7_REFILL_PRIORITY[7] - (RW) Group7 refill priority +* GROUP8_REFILL_PRIORITY[8] - (RW) Group8 refill priority +* GROUP9_REFILL_PRIORITY[9] - (RW) Group9 refill priority +* GROUP10_REFILL_PRIORITY[10] - (RW) Group10 refill priority +* GROUP11_REFILL_PRIORITY[11] - (RW) Group11 refill priority +* GROUP12_REFILL_PRIORITY[12] - (RW) Group12 refill priority +* GROUP13_REFILL_PRIORITY[13] - (RW) Group13 refill priority +* GROUP14_REFILL_PRIORITY[14] - (RW) Group14 refill priority +* GROUP15_REFILL_PRIORITY[15] - (RW) Group15 refill priority +* GROUP0_REFILL_DISABLE[16] - (RW) Group0 refill control +* GROUP1_REFILL_DISABLE[17] - (RW) Group1 refill control +* GROUP2_REFILL_DISABLE[18] - (RW) Group2 refill control +* GROUP3_REFILL_DISABLE[19] - (RW) Group3 refill control +* GROUP4_REFILL_DISABLE[20] - (RW) Group4 refill control +* GROUP5_REFILL_DISABLE[21] - (RW) Group5 refill control +* GROUP6_REFILL_DISABLE[22] - (RW) Group6 refill control +* GROUP7_REFILL_DISABLE[23] - (RW) Group7 refill control +* GROUP8_REFILL_DISABLE[24] - (RW) Group8 refill control +* GROUP9_REFILL_DISABLE[25] - (RW) Group9 refill control +* GROUP10_REFILL_DISABLE[26] - (RW) Group10 refill control +* GROUP11_REFILL_DISABLE[27] - (RW) Group11 refill control +* GROUP12_REFILL_DISABLE[28] - (RW) Group12 refill control +* GROUP13_REFILL_DISABLE[29] - (RW) Group13 refill control +* GROUP14_REFILL_DISABLE[30] - (RW) Group14 refill control +* GROUP15_REFILL_DISABLE[31] - (RW) Group15 refill control +*/ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP15_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP15_REFILL_DISABLE_MASK \ + 0x80000000 /* GROUP15_REFILL_DISABLE[31] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP15_REFILL_DISABLE_SHFT 31 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP14_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP14_REFILL_DISABLE_MASK \ + 0x40000000 /* GROUP14_REFILL_DISABLE[30] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP14_REFILL_DISABLE_SHFT 30 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP13_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP13_REFILL_DISABLE_MASK \ + 0x20000000 /* GROUP13_REFILL_DISABLE[29] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP13_REFILL_DISABLE_SHFT 29 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP12_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP12_REFILL_DISABLE_MASK \ + 0x10000000 /* GROUP12_REFILL_DISABLE[28] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP12_REFILL_DISABLE_SHFT 28 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP11_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP11_REFILL_DISABLE_MASK \ + 0x08000000 /* GROUP11_REFILL_DISABLE[27] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP11_REFILL_DISABLE_SHFT 27 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP10_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP10_REFILL_DISABLE_MASK \ + 0x04000000 /* GROUP10_REFILL_DISABLE[26] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP10_REFILL_DISABLE_SHFT 26 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP9_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP9_REFILL_DISABLE_MASK \ + 0x02000000 /* GROUP9_REFILL_DISABLE[25] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP9_REFILL_DISABLE_SHFT 25 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP8_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP8_REFILL_DISABLE_MASK \ + 0x01000000 /* GROUP8_REFILL_DISABLE[24] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP8_REFILL_DISABLE_SHFT 24 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP7_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP7_REFILL_DISABLE_MASK \ + 0x00800000 /* GROUP7_REFILL_DISABLE[23] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP7_REFILL_DISABLE_SHFT 23 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP6_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP6_REFILL_DISABLE_MASK \ + 0x00400000 /* GROUP6_REFILL_DISABLE[22] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP6_REFILL_DISABLE_SHFT 22 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP5_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP5_REFILL_DISABLE_MASK \ + 0x00200000 /* GROUP5_REFILL_DISABLE[21] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP5_REFILL_DISABLE_SHFT 21 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP4_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP4_REFILL_DISABLE_MASK \ + 0x00100000 /* GROUP4_REFILL_DISABLE[20] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP4_REFILL_DISABLE_SHFT 20 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP3_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP3_REFILL_DISABLE_MASK \ + 0x00080000 /* GROUP3_REFILL_DISABLE[19] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP3_REFILL_DISABLE_SHFT 19 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP2_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP2_REFILL_DISABLE_MASK \ + 0x00040000 /* GROUP2_REFILL_DISABLE[18] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP2_REFILL_DISABLE_SHFT 18 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP1_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP1_REFILL_DISABLE_MASK \ + 0x00020000 /* GROUP1_REFILL_DISABLE[17] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP1_REFILL_DISABLE_SHFT 17 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP0_REFILL_DISABLE_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP0_REFILL_DISABLE_MASK \ + 0x00010000 /* GROUP0_REFILL_DISABLE[16] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP0_REFILL_DISABLE_SHFT 16 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP15_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP15_REFILL_PRIORITY_MASK \ + 0x00008000 /* GROUP15_REFILL_PRIORITY[15] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP15_REFILL_PRIORITY_SHFT 15 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP14_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP14_REFILL_PRIORITY_MASK \ + 0x00004000 /* GROUP14_REFILL_PRIORITY[14] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP14_REFILL_PRIORITY_SHFT 14 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP13_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP13_REFILL_PRIORITY_MASK \ + 0x00002000 /* GROUP13_REFILL_PRIORITY[13] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP13_REFILL_PRIORITY_SHFT 13 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP12_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP12_REFILL_PRIORITY_MASK \ + 0x00001000 /* GROUP12_REFILL_PRIORITY[12] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP12_REFILL_PRIORITY_SHFT 12 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP11_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP11_REFILL_PRIORITY_MASK \ + 0x00000800 /* GROUP11_REFILL_PRIORITY[11] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP11_REFILL_PRIORITY_SHFT 11 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP10_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP10_REFILL_PRIORITY_MASK \ + 0x00000400 /* GROUP10_REFILL_PRIORITY[10] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP10_REFILL_PRIORITY_SHFT 10 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP9_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP9_REFILL_PRIORITY_MASK \ + 0x00000200 /* GROUP9_REFILL_PRIORITY[9] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP9_REFILL_PRIORITY_SHFT 9 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP8_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP8_REFILL_PRIORITY_MASK \ + 0x00000100 /* GROUP8_REFILL_PRIORITY[8] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP8_REFILL_PRIORITY_SHFT 8 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP7_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP7_REFILL_PRIORITY_MASK \ + 0x00000080 /* GROUP7_REFILL_PRIORITY[7] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP7_REFILL_PRIORITY_SHFT 7 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP6_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP6_REFILL_PRIORITY_MASK \ + 0x00000040 /* GROUP6_REFILL_PRIORITY[6] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP6_REFILL_PRIORITY_SHFT 6 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP5_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP5_REFILL_PRIORITY_MASK \ + 0x00000020 /* GROUP5_REFILL_PRIORITY[5] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP5_REFILL_PRIORITY_SHFT 5 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP4_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP4_REFILL_PRIORITY_MASK \ + 0x00000010 /* GROUP4_REFILL_PRIORITY[4] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP4_REFILL_PRIORITY_SHFT 4 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP3_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP3_REFILL_PRIORITY_MASK \ + 0x00000008 /* GROUP3_REFILL_PRIORITY[3] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP3_REFILL_PRIORITY_SHFT 3 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP2_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP2_REFILL_PRIORITY_MASK \ + 0x00000004 /* GROUP2_REFILL_PRIORITY[2] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP2_REFILL_PRIORITY_SHFT 2 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP1_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP1_REFILL_PRIORITY_MASK \ + 0x00000002 /* GROUP1_REFILL_PRIORITY[1] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP1_REFILL_PRIORITY_SHFT 1 +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP0_REFILL_PRIORITY_ADDR \ + WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP0_REFILL_PRIORITY_MASK \ + 0x00000001 /* GROUP0_REFILL_PRIORITY[0] */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP0_REFILL_PRIORITY_SHFT 0 + +/* +* ---TX_PACKET_SIZE_PAGE_MAP (0x7C026000 + 0x14)--- +* PACKET_SIZE_PAGE_MAP[7..0] - (RW) PSE Packet size page map +* 8'bxxxx_xxx1 : 32 bytes +* 8'bxxxx_xx10 : 64 bytes +* 8'bxxxx_x100 : 128 bytes +* 8'bxxxx_1000 : 256 bytes +* 8'bxxx1_0000 : 512 bytes +* 8'bxx10_0000 : 1024 bytes +* 8'bx100_0000 : 2048 bytes +* 8'b1000_0000 : 4096 bytes +* CR_PSE_LEN_MAP_SEL[8] - (RW) Enable pse packet length page mapping by +* CR Packet size page map or not +* RESERVED9[31..9] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_TX_PACKET_SIZE_PAGE_MAP_CR_PSE_LEN_MAP_SEL_ADDR \ + WF_HIF_DMASHDL_TOP_TX_PACKET_SIZE_PAGE_MAP_ADDR +#define WF_HIF_DMASHDL_TOP_TX_PACKET_SIZE_PAGE_MAP_CR_PSE_LEN_MAP_SEL_MASK \ + 0x00000100 /* CR_PSE_LEN_MAP_SEL[8] */ +#define WF_HIF_DMASHDL_TOP_TX_PACKET_SIZE_PAGE_MAP_CR_PSE_LEN_MAP_SEL_SHFT 8 +#define WF_HIF_DMASHDL_TOP_TX_PACKET_SIZE_PAGE_MAP_PACKET_SIZE_PAGE_MAP_ADDR \ + WF_HIF_DMASHDL_TOP_TX_PACKET_SIZE_PAGE_MAP_ADDR +#define WF_HIF_DMASHDL_TOP_TX_PACKET_SIZE_PAGE_MAP_PACKET_SIZE_PAGE_MAP_MASK \ + 0x000000FF /* PACKET_SIZE_PAGE_MAP[7..0] */ +#define WF_HIF_DMASHDL_TOP_TX_PACKET_SIZE_PAGE_MAP_PACKET_SIZE_PAGE_MAP_SHFT 0 + +/* +* ---CONTROL_SIGNAL (0x7C026000 + 0x18)--- +* CR_WACPU_MODE_EN[0] - (RW) Enable to WACPU mode for store forward +* packet to DLM +* RESERVED1[3..1] - (RO) Reserved bits +* WACPU_CMD_RET_PAGE_CNT[7..4] - (RW) WACPU mode, each packet in the CMD +* return the page count +* WACPU_TXD_RET_PAGE_CNT[11..8] - (RW) WACPU mode, each packet in the TXD +* return the page count +* WACPU_CMD_ASK_MAX_PAGE_CNT[15..12] - (RW) WACPU mode, CMD ask to require the +* maximum page count +* CR_HIF_ASK_SUB_ENA[16] - (RW) Enable packet in substration action from +* HIF ask period +* CR_PLE_SUB_ENA[17] - (RW) Enable packet in substration action from +PLE +* RESERVED18[19..18] - (RO) Reserved bits +* WACPU_TXD_ASK_MAX_PAGE_CNT[23..20] - (RW) WACPU mode, TXD ask to require the +* maximum page count +* WACPU_SUB_SRC_REFILL_ENA[24] - (RW) Enable terminate refill period when +* WACPU substrate source count to do refill action. +* WACPU_ADD_SRC_REFILL_ENA[25] - (RW) Enable terminate refill period when +* WACPU add source count to do refill action. +* WACPU_ADD_RES_REFILL_ENA[26] - (RW) Enable terminate refill period when +* WACPU add reserve count to do refill action. +* WACPU_RET_REFILL_ENA[27] - (RW) Enable terminate refill period when +* WACPU release packet to do refill action. +* RESERVED28[28] - (RO) Reserved bits +* CR_PLE_ADD_INT_REFILL_ENA[29] - (RW) Enable terminate refill period when PLE +* release packet to do addition. +* CR_PDMA_ADD_INT_REFILL_ENA[30] - (RW) Enable terminate refill period when +* packet in to do addition. +* CR_PKTIN_INT_REFILL_ENA[31] - (RW) Enable terminate refill period when +* packet in to do substration. +*/ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_PKTIN_INT_REFILL_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_PKTIN_INT_REFILL_ENA_MASK \ + 0x80000000 /* CR_PKTIN_INT_REFILL_ENA[31] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_PKTIN_INT_REFILL_ENA_SHFT 31 +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_PDMA_ADD_INT_REFILL_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_PDMA_ADD_INT_REFILL_ENA_MASK \ + 0x40000000 /* CR_PDMA_ADD_INT_REFILL_ENA[30] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_PDMA_ADD_INT_REFILL_ENA_SHFT 30 +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_PLE_ADD_INT_REFILL_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_PLE_ADD_INT_REFILL_ENA_MASK \ + 0x20000000 /* CR_PLE_ADD_INT_REFILL_ENA[29] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_PLE_ADD_INT_REFILL_ENA_SHFT 29 +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_RET_REFILL_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_RET_REFILL_ENA_MASK \ + 0x08000000 /* WACPU_RET_REFILL_ENA[27] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_RET_REFILL_ENA_SHFT 27 +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_ADD_RES_REFILL_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_ADD_RES_REFILL_ENA_MASK \ + 0x04000000 /* WACPU_ADD_RES_REFILL_ENA[26] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_ADD_RES_REFILL_ENA_SHFT 26 +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_ADD_SRC_REFILL_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_ADD_SRC_REFILL_ENA_MASK \ + 0x02000000 /* WACPU_ADD_SRC_REFILL_ENA[25] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_ADD_SRC_REFILL_ENA_SHFT 25 +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_SUB_SRC_REFILL_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_SUB_SRC_REFILL_ENA_MASK \ + 0x01000000 /* WACPU_SUB_SRC_REFILL_ENA[24] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_SUB_SRC_REFILL_ENA_SHFT 24 +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_TXD_ASK_MAX_PAGE_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_TXD_ASK_MAX_PAGE_CNT_MASK \ + 0x00F00000 /* WACPU_TXD_ASK_MAX_PAGE_CNT[23..20] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_TXD_ASK_MAX_PAGE_CNT_SHFT 20 +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_PLE_SUB_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_PLE_SUB_ENA_MASK \ + 0x00020000 /* CR_PLE_SUB_ENA[17] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_PLE_SUB_ENA_SHFT 17 +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_HIF_ASK_SUB_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_HIF_ASK_SUB_ENA_MASK \ + 0x00010000 /* CR_HIF_ASK_SUB_ENA[16] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_HIF_ASK_SUB_ENA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_CMD_ASK_MAX_PAGE_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_CMD_ASK_MAX_PAGE_CNT_MASK \ + 0x0000F000 /* WACPU_CMD_ASK_MAX_PAGE_CNT[15..12] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_CMD_ASK_MAX_PAGE_CNT_SHFT 12 +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_TXD_RET_PAGE_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_TXD_RET_PAGE_CNT_MASK \ + 0x00000F00 /* WACPU_TXD_RET_PAGE_CNT[11..8] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_TXD_RET_PAGE_CNT_SHFT 8 +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_CMD_RET_PAGE_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_CMD_RET_PAGE_CNT_MASK \ + 0x000000F0 /* WACPU_CMD_RET_PAGE_CNT[7..4] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_WACPU_CMD_RET_PAGE_CNT_SHFT 4 +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_WACPU_MODE_EN_ADDR \ + WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_WACPU_MODE_EN_MASK \ + 0x00000001 /* CR_WACPU_MODE_EN[0] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_WACPU_MODE_EN_SHFT 0 + +/* +* ---PACKET_MAX_SIZE (0x7C026000 + 0x1c)--- +* PLE_PACKET_MAX_SIZE[11..0] - (RW) PLE packet maximum page size (group 0 ~ +11) +* RESERVED12[15..12] - (RO) Reserved bits +* PSE_PACKET_MAX_SIZE[27..16] - (RW) PSE packet maximum page size (group 15) +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PSE_PACKET_MAX_SIZE_ADDR \ + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR +#define WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PSE_PACKET_MAX_SIZE_MASK \ + 0x0FFF0000 /* PSE_PACKET_MAX_SIZE[27..16] */ +#define WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PSE_PACKET_MAX_SIZE_SHFT 16 +#define WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PLE_PACKET_MAX_SIZE_ADDR \ + WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR +#define WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PLE_PACKET_MAX_SIZE_MASK \ + 0x00000FFF /* PLE_PACKET_MAX_SIZE[11..0] */ +#define WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_PLE_PACKET_MAX_SIZE_SHFT 0 + +/* +* ---GROUP0_CONTROL (0x7C026000 + 0x20)--- +* GROUP0_MIN_QUOTA[11..0] - (RW) Group0 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP0_MAX_QUOTA[27..16] - (RW) Group0 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_GROUP0_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_GROUP0_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP0_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_GROUP0_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_GROUP0_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_GROUP0_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP0_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_GROUP0_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP1_CONTROL (0x7C026000 + 0x24)--- +* GROUP1_MIN_QUOTA[11..0] - (RW) Group1 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP1_MAX_QUOTA[27..16] - (RW) Group1 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_GROUP1_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_GROUP1_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP1_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_GROUP1_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_GROUP1_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_GROUP1_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP1_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_GROUP1_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP2_CONTROL (0x7C026000 + 0x28)--- +* GROUP2_MIN_QUOTA[11..0] - (RW) Group2 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP2_MAX_QUOTA[27..16] - (RW) Group2 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_GROUP2_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_GROUP2_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP2_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_GROUP2_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_GROUP2_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_GROUP2_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP2_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_GROUP2_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP3_CONTROL (0x7C026000 + 0x2C)--- +* GROUP3_MIN_QUOTA[11..0] - (RW) Group3 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP3_MAX_QUOTA[27..16] - (RW) Group3 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_GROUP3_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_GROUP3_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP3_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_GROUP3_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_GROUP3_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_GROUP3_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP3_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_GROUP3_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP4_CONTROL (0x7C026000 + 0x30)--- +* GROUP4_MIN_QUOTA[11..0] - (RW) Group4 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP4_MAX_QUOTA[27..16] - (RW) Group4 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_GROUP4_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_GROUP4_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP4_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_GROUP4_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_GROUP4_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_GROUP4_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP4_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_GROUP4_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP5_CONTROL (0x7C026000 + 0x34)--- +* GROUP5_MIN_QUOTA[11..0] - (RW) Group5 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP5_MAX_QUOTA[27..16] - (RW) Group5 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP5_CONTROL_GROUP5_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP5_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP5_CONTROL_GROUP5_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP5_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP5_CONTROL_GROUP5_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP5_CONTROL_GROUP5_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP5_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP5_CONTROL_GROUP5_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP5_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP5_CONTROL_GROUP5_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP6_CONTROL (0x7C026000 + 0x38)--- +* GROUP6_MIN_QUOTA[11..0] - (RW) Group6 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP6_MAX_QUOTA[27..16] - (RW) Group6 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP6_CONTROL_GROUP6_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP6_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP6_CONTROL_GROUP6_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP6_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP6_CONTROL_GROUP6_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP6_CONTROL_GROUP6_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP6_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP6_CONTROL_GROUP6_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP6_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP6_CONTROL_GROUP6_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP7_CONTROL (0x7C026000 + 0x3C)--- +* GROUP7_MIN_QUOTA[11..0] - (RW) Group7 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP7_MAX_QUOTA[27..16] - (RW) Group7 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP7_CONTROL_GROUP7_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP7_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP7_CONTROL_GROUP7_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP7_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP7_CONTROL_GROUP7_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP7_CONTROL_GROUP7_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP7_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP7_CONTROL_GROUP7_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP7_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP7_CONTROL_GROUP7_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP8_CONTROL (0x7C026000 + 0x40)--- +* GROUP8_MIN_QUOTA[11..0] - (RW) Group8 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP8_MAX_QUOTA[27..16] - (RW) Group8 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP8_CONTROL_GROUP8_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP8_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP8_CONTROL_GROUP8_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP8_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP8_CONTROL_GROUP8_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP8_CONTROL_GROUP8_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP8_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP8_CONTROL_GROUP8_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP8_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP8_CONTROL_GROUP8_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP9_CONTROL (0x7C026000 + 0x44)--- +* GROUP9_MIN_QUOTA[11..0] - (RW) Group9 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP9_MAX_QUOTA[27..16] - (RW) Group9 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP9_CONTROL_GROUP9_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP9_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP9_CONTROL_GROUP9_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP9_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP9_CONTROL_GROUP9_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP9_CONTROL_GROUP9_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP9_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP9_CONTROL_GROUP9_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP9_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP9_CONTROL_GROUP9_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP10_CONTROL (0x7C026000 + 0x48)--- +* GROUP10_MIN_QUOTA[11..0] - (RW) Group10 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP10_MAX_QUOTA[27..16] - (RW) Group10 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP10_CONTROL_GROUP10_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP10_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP10_CONTROL_GROUP10_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP10_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP10_CONTROL_GROUP10_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP10_CONTROL_GROUP10_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP10_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP10_CONTROL_GROUP10_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP10_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP10_CONTROL_GROUP10_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP11_CONTROL (0x7C026000 + 0x4C)--- +* GROUP11_MIN_QUOTA[11..0] - (RW) Group11 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP11_MAX_QUOTA[27..16] - (RW) Group11 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP11_CONTROL_GROUP11_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP11_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP11_CONTROL_GROUP11_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP11_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP11_CONTROL_GROUP11_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP11_CONTROL_GROUP11_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP11_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP11_CONTROL_GROUP11_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP11_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP11_CONTROL_GROUP11_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP12_CONTROL (0x7C026000 + 0x50)--- +* GROUP12_MIN_QUOTA[11..0] - (RW) Group12 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP12_MAX_QUOTA[27..16] - (RW) Group12 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP12_CONTROL_GROUP12_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP12_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP12_CONTROL_GROUP12_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP12_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP12_CONTROL_GROUP12_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP12_CONTROL_GROUP12_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP12_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP12_CONTROL_GROUP12_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP12_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP12_CONTROL_GROUP12_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP13_CONTROL (0x7C026000 + 0x54)--- +* GROUP13_MIN_QUOTA[11..0] - (RW) Group13 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP13_MAX_QUOTA[27..16] - (RW) Group13 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP13_CONTROL_GROUP13_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP13_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP13_CONTROL_GROUP13_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP13_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP13_CONTROL_GROUP13_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP13_CONTROL_GROUP13_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP13_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP13_CONTROL_GROUP13_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP13_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP13_CONTROL_GROUP13_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP14_CONTROL (0x7C026000 + 0x58)--- +* GROUP14_MIN_QUOTA[11..0] - (RW) Group14 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP14_MAX_QUOTA[27..16] - (RW) Group14 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP14_CONTROL_GROUP14_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP14_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP14_CONTROL_GROUP14_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP14_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP14_CONTROL_GROUP14_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP14_CONTROL_GROUP14_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP14_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP14_CONTROL_GROUP14_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP14_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP14_CONTROL_GROUP14_MIN_QUOTA_SHFT 0 + +/* +* ---GROUP15_CONTROL (0x7C026000 + 0x5C)--- +* GROUP15_MIN_QUOTA[11..0] - (RW) Group15 Minimum Quota +* RESERVED12[15..12] - (RO) Reserved bits +* GROUP15_MAX_QUOTA[27..16] - (RW) Group15 Maximum Quota +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_GROUP15_CONTROL_GROUP15_MAX_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP15_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP15_CONTROL_GROUP15_MAX_QUOTA_MASK \ + 0x0FFF0000 /* GROUP15_MAX_QUOTA[27..16] */ +#define WF_HIF_DMASHDL_TOP_GROUP15_CONTROL_GROUP15_MAX_QUOTA_SHFT 16 +#define WF_HIF_DMASHDL_TOP_GROUP15_CONTROL_GROUP15_MIN_QUOTA_ADDR \ + WF_HIF_DMASHDL_TOP_GROUP15_CONTROL_ADDR +#define WF_HIF_DMASHDL_TOP_GROUP15_CONTROL_GROUP15_MIN_QUOTA_MASK \ + 0x00000FFF /* GROUP15_MIN_QUOTA[11..0] */ +#define WF_HIF_DMASHDL_TOP_GROUP15_CONTROL_GROUP15_MIN_QUOTA_SHFT 0 + +/* +* ---STATUS_RD0 (0x7C026000 + 0x70)--- +* PLE_TXD_QID_MAX2_NZERO_CNT[3..0] - (RO) Number of TXD QID[6:5] not equal +* zero counter from PLE return. +* HOST_TXD_QID_MAX2_NZERO_CNT[7..4] - (RO) Number of TXD QID[6:5] not equal +* zero counter from host send. +* CURR_TXD_CTXD_FLAG[8] - (RO) Current TXD is cascade TXD format or not +* RESERVED9[31..9] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD0_CURR_TXD_CTXD_FLAG_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD0_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD0_CURR_TXD_CTXD_FLAG_MASK \ + 0x00000100 /* CURR_TXD_CTXD_FLAG[8] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD0_CURR_TXD_CTXD_FLAG_SHFT 8 +#define WF_HIF_DMASHDL_TOP_STATUS_RD0_HOST_TXD_QID_MAX2_NZERO_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD0_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD0_HOST_TXD_QID_MAX2_NZERO_CNT_MASK \ + 0x000000F0 /* HOST_TXD_QID_MAX2_NZERO_CNT[7..4] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD0_HOST_TXD_QID_MAX2_NZERO_CNT_SHFT 4 +#define WF_HIF_DMASHDL_TOP_STATUS_RD0_PLE_TXD_QID_MAX2_NZERO_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD0_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD0_PLE_TXD_QID_MAX2_NZERO_CNT_MASK \ + 0x0000000F /* PLE_TXD_QID_MAX2_NZERO_CNT[3..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD0_PLE_TXD_QID_MAX2_NZERO_CNT_SHFT 0 + +/* +* ---DEBUG_PORT00 (0x7C026000 + 0x80)--- +* DEBUG_N0_SEL[0] - (RW) Debug port n0 enable +* DEBUG_N1_SEL[1] - (RW) Debug port n1 enable +* DEBUG_N2_SEL[2] - (RW) Debug port n2 enable +* DEBUG_N3_SEL[3] - (RW) Debug port n3 enable +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT00_DEBUG_N3_SEL_ADDR \ + WF_HIF_DMASHDL_TOP_DEBUG_PORT00_ADDR +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT00_DEBUG_N3_SEL_MASK \ + 0x00000008 /* DEBUG_N3_SEL[3] */ +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT00_DEBUG_N3_SEL_SHFT 3 +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT00_DEBUG_N2_SEL_ADDR \ + WF_HIF_DMASHDL_TOP_DEBUG_PORT00_ADDR +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT00_DEBUG_N2_SEL_MASK \ + 0x00000004 /* DEBUG_N2_SEL[2] */ +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT00_DEBUG_N2_SEL_SHFT 2 +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT00_DEBUG_N1_SEL_ADDR \ + WF_HIF_DMASHDL_TOP_DEBUG_PORT00_ADDR +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT00_DEBUG_N1_SEL_MASK \ + 0x00000002 /* DEBUG_N1_SEL[1] */ +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT00_DEBUG_N1_SEL_SHFT 1 +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT00_DEBUG_N0_SEL_ADDR \ + WF_HIF_DMASHDL_TOP_DEBUG_PORT00_ADDR +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT00_DEBUG_N0_SEL_MASK \ + 0x00000001 /* DEBUG_N0_SEL[0] */ +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT00_DEBUG_N0_SEL_SHFT 0 + +/* +* ---DEBUG_PORT01 (0x7C026000 + 0x84)--- +* DEBUG_FLAG_N0_SEL[7..0] - (RW) Debug port n0 select +* DEBUG_FLAG_N1_SEL[15..8] - (RW) Debug port n1 select +* DEBUG_FLAG_N2_SEL[23..16] - (RW) Debug port n2 select +* DEBUG_FLAG_N3_SEL[31..24] - (RW) Debug port n3 select +*/ +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT01_DEBUG_FLAG_N3_SEL_ADDR \ + WF_HIF_DMASHDL_TOP_DEBUG_PORT01_ADDR +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT01_DEBUG_FLAG_N3_SEL_MASK \ + 0xFF000000 /* DEBUG_FLAG_N3_SEL[31..24] */ +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT01_DEBUG_FLAG_N3_SEL_SHFT 24 +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT01_DEBUG_FLAG_N2_SEL_ADDR \ + WF_HIF_DMASHDL_TOP_DEBUG_PORT01_ADDR +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT01_DEBUG_FLAG_N2_SEL_MASK \ + 0x00FF0000 /* DEBUG_FLAG_N2_SEL[23..16] */ +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT01_DEBUG_FLAG_N2_SEL_SHFT 16 +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT01_DEBUG_FLAG_N1_SEL_ADDR \ + WF_HIF_DMASHDL_TOP_DEBUG_PORT01_ADDR +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT01_DEBUG_FLAG_N1_SEL_MASK \ + 0x0000FF00 /* DEBUG_FLAG_N1_SEL[15..8] */ +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT01_DEBUG_FLAG_N1_SEL_SHFT 8 +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT01_DEBUG_FLAG_N0_SEL_ADDR \ + WF_HIF_DMASHDL_TOP_DEBUG_PORT01_ADDR +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT01_DEBUG_FLAG_N0_SEL_MASK \ + 0x000000FF /* DEBUG_FLAG_N0_SEL[7..0] */ +#define WF_HIF_DMASHDL_TOP_DEBUG_PORT01_DEBUG_FLAG_N0_SEL_SHFT 0 + +/* +* ---STATUS_RD02 (0x7C026000 + 0x88)--- +* REFILL_CS[3..0] - (RO) Refill state machine for current state +* REFILL_NS[7..4] - (RO) Refill state machine for next state +* DMASHDL_CS[10..8] - (RO) DMASHDL state machine for current state +* RESERVED11[11] - (RO) Reserved bits +* DMASHDL_NS[14..12] - (RO) DMASHDL state machine for next state +* RESERVED15[15] - (RO) Reserved bits +* HIF_DMASHDL_DEBUG_PORT[31..16] - (RO) DMASHDL debug port signals +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_HIF_DMASHDL_DEBUG_PORT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD02_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_HIF_DMASHDL_DEBUG_PORT_MASK \ + 0xFFFF0000 /* HIF_DMASHDL_DEBUG_PORT[31..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_HIF_DMASHDL_DEBUG_PORT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_DMASHDL_NS_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD02_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_DMASHDL_NS_MASK \ + 0x00007000 /* DMASHDL_NS[14..12] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_DMASHDL_NS_SHFT 12 +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_DMASHDL_CS_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD02_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_DMASHDL_CS_MASK \ + 0x00000700 /* DMASHDL_CS[10..8] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_DMASHDL_CS_SHFT 8 +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_REFILL_NS_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD02_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_REFILL_NS_MASK \ + 0x000000F0 /* REFILL_NS[7..4] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_REFILL_NS_SHFT 4 +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_REFILL_CS_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD02_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_REFILL_CS_MASK \ + 0x0000000F /* REFILL_CS[3..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD02_REFILL_CS_SHFT 0 + +/* +* ---COUNTER_UDF_CLR (0x7C026000 + 0x8C)--- +* FREEPG_CNT_UDF_CLR[0] - (RW) Clear freepage count underflow flag +* FFA_CNT_UDF_CLR[1] - (RW) Clear FFA count underflow flag +* SRC_SUB_CUR_UDF_CLR[2] - (RW) Clear PLE return stage source count +* underflow flag +* REFILL_MAX1_UDF_CLR[3] - (RW) Clear pktin return stage source count +* underflow flag +* REFILL_MAX0_UDF_CLR[4] - (RW) Clear RSV add SRC count greater than +* maximum quota +* RSV_SUB_CURR_UDF_CLR[5] - (RW) Clear reservation count underflow flag +* PLE_TXD_GT_MAX_SIZE_FLAG_CLR[6] - (RW) Clear PLE TXD size greater than max +* PLE TXD size flag +* PSE_SIZE_GT_MAX_SIZE_FLAG_CLR[7] - (RW) Clear PSE packet size greater than +* max packet size flag +* HIF_ASK_LONG_FLAG_CLR[8] - (RW) Clear the HIF ask after long time period +* to grant flag +* PSE_RSV_UDF_CLR[9] - (RW) Clear the HIF ask to let reservation +* count underflow flag +* PSE_SRC_PSERET_UDF_CLR[10] - (RW) Clear the PSE source count PSE module +* return underflow flag +* PSE_SRC_PKTRET_UDF_CLR[11] - (RW) Clear the PSE source count packet in +* return underflow flag +* RESERVED12[15..12] - (RO) Reserved bits +* HIF_ASK_PKTIN_CNT_CLR[16] - (RW) Clear the ask counters and pktin return +* counters for all groups +* RESERVED17[31..17] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_HIF_ASK_PKTIN_CNT_CLR_ADDR \ + WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_HIF_ASK_PKTIN_CNT_CLR_MASK \ + 0x00010000 /* HIF_ASK_PKTIN_CNT_CLR[16] */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_HIF_ASK_PKTIN_CNT_CLR_SHFT 16 +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PSE_SRC_PKTRET_UDF_CLR_ADDR \ + WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PSE_SRC_PKTRET_UDF_CLR_MASK \ + 0x00000800 /* PSE_SRC_PKTRET_UDF_CLR[11] */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PSE_SRC_PKTRET_UDF_CLR_SHFT 11 +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PSE_SRC_PSERET_UDF_CLR_ADDR \ + WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PSE_SRC_PSERET_UDF_CLR_MASK \ + 0x00000400 /* PSE_SRC_PSERET_UDF_CLR[10] */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PSE_SRC_PSERET_UDF_CLR_SHFT 10 +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PSE_RSV_UDF_CLR_ADDR \ + WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PSE_RSV_UDF_CLR_MASK \ + 0x00000200 /* PSE_RSV_UDF_CLR[9] */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PSE_RSV_UDF_CLR_SHFT 9 +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_HIF_ASK_LONG_FLAG_CLR_ADDR \ + WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_HIF_ASK_LONG_FLAG_CLR_MASK \ + 0x00000100 /* HIF_ASK_LONG_FLAG_CLR[8] */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_HIF_ASK_LONG_FLAG_CLR_SHFT 8 +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PSE_SIZE_GT_MAX_SIZE_FLAG_CLR_ADDR \ + WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PSE_SIZE_GT_MAX_SIZE_FLAG_CLR_MASK \ + 0x00000080 /* PSE_SIZE_GT_MAX_SIZE_FLAG_CLR[7] */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PSE_SIZE_GT_MAX_SIZE_FLAG_CLR_SHFT 7 +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PLE_TXD_GT_MAX_SIZE_FLAG_CLR_ADDR \ + WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PLE_TXD_GT_MAX_SIZE_FLAG_CLR_MASK \ + 0x00000040 /* PLE_TXD_GT_MAX_SIZE_FLAG_CLR[6] */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_PLE_TXD_GT_MAX_SIZE_FLAG_CLR_SHFT 6 +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_RSV_SUB_CURR_UDF_CLR_ADDR \ + WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_RSV_SUB_CURR_UDF_CLR_MASK \ + 0x00000020 /* RSV_SUB_CURR_UDF_CLR[5] */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_RSV_SUB_CURR_UDF_CLR_SHFT 5 +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_REFILL_MAX0_UDF_CLR_ADDR \ + WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_REFILL_MAX0_UDF_CLR_MASK \ + 0x00000010 /* REFILL_MAX0_UDF_CLR[4] */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_REFILL_MAX0_UDF_CLR_SHFT 4 +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_REFILL_MAX1_UDF_CLR_ADDR \ + WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_REFILL_MAX1_UDF_CLR_MASK \ + 0x00000008 /* REFILL_MAX1_UDF_CLR[3] */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_REFILL_MAX1_UDF_CLR_SHFT 3 +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_SRC_SUB_CUR_UDF_CLR_ADDR \ + WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_SRC_SUB_CUR_UDF_CLR_MASK \ + 0x00000004 /* SRC_SUB_CUR_UDF_CLR[2] */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_SRC_SUB_CUR_UDF_CLR_SHFT 2 +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_FFA_CNT_UDF_CLR_ADDR \ + WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_FFA_CNT_UDF_CLR_MASK \ + 0x00000002 /* FFA_CNT_UDF_CLR[1] */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_FFA_CNT_UDF_CLR_SHFT 1 +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_FREEPG_CNT_UDF_CLR_ADDR \ + WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_ADDR +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_FREEPG_CNT_UDF_CLR_MASK \ + 0x00000001 /* FREEPG_CNT_UDF_CLR[0] */ +#define WF_HIF_DMASHDL_TOP_COUNTER_UDF_CLR_FREEPG_CNT_UDF_CLR_SHFT 0 + +/* +* ---PKT_IN_CNT_CTRL (0x7C026000 + 0x90)--- +* CNT1_RET_CNT_ENA[0] - (RW) Counter1 PLE/PSE return count enable +* CNT1_PKTIN_RET_CNT_ENA[1] - (RW) Counter1 pktin return count enable +* CNT1_PKTIN_CNT_ENA[2] - (RW) Counter1 pktin(ask) substrate count +enable +* CNT0_RET_CNT_ENA[3] - (RW) Counter0 PLE/PSE return count enable +* CNT0_PKTIN_RET_CNT_ENA[4] - (RW) Counter0 pktin return count enable +* CNT0_PKTIN_CNT_ENA[5] - (RW) Counter0 pktin(ask) substrate count +enable +* RESERVED6[31..6] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT0_PKTIN_CNT_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT0_PKTIN_CNT_ENA_MASK \ + 0x00000020 /* CNT0_PKTIN_CNT_ENA[5] */ +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT0_PKTIN_CNT_ENA_SHFT 5 +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT0_PKTIN_RET_CNT_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT0_PKTIN_RET_CNT_ENA_MASK \ + 0x00000010 /* CNT0_PKTIN_RET_CNT_ENA[4] */ +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT0_PKTIN_RET_CNT_ENA_SHFT 4 +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT0_RET_CNT_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT0_RET_CNT_ENA_MASK \ + 0x00000008 /* CNT0_RET_CNT_ENA[3] */ +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT0_RET_CNT_ENA_SHFT 3 +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT1_PKTIN_CNT_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT1_PKTIN_CNT_ENA_MASK \ + 0x00000004 /* CNT1_PKTIN_CNT_ENA[2] */ +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT1_PKTIN_CNT_ENA_SHFT 2 +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT1_PKTIN_RET_CNT_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT1_PKTIN_RET_CNT_ENA_MASK \ + 0x00000002 /* CNT1_PKTIN_RET_CNT_ENA[1] */ +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT1_PKTIN_RET_CNT_ENA_SHFT 1 +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT1_RET_CNT_ENA_ADDR \ + WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT1_RET_CNT_ENA_MASK \ + 0x00000001 /* CNT1_RET_CNT_ENA[0] */ +#define WF_HIF_DMASHDL_TOP_PKT_IN_CNT_CTRL_CNT1_RET_CNT_ENA_SHFT 0 + +/* +* ---HIF_ASK_LONG_CHECK (0x7C026000 + 0x94)--- +* HIF_ASK_TICK_CNT[15..0] - (RO) HIF request ask wait period count. +* HIF_ASK_LONG_CNT_TH[31..16] - (RW) HIF request ask wait period threshold. +* (unit = 32us, wf_aon_32us_tick) +*/ +#define WF_HIF_DMASHDL_TOP_HIF_ASK_LONG_CHECK_HIF_ASK_LONG_CNT_TH_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_ASK_LONG_CHECK_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_ASK_LONG_CHECK_HIF_ASK_LONG_CNT_TH_MASK \ + 0xFFFF0000 /* HIF_ASK_LONG_CNT_TH[31..16] */ +#define WF_HIF_DMASHDL_TOP_HIF_ASK_LONG_CHECK_HIF_ASK_LONG_CNT_TH_SHFT 16 +#define WF_HIF_DMASHDL_TOP_HIF_ASK_LONG_CHECK_HIF_ASK_TICK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_ASK_LONG_CHECK_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_ASK_LONG_CHECK_HIF_ASK_TICK_CNT_MASK \ + 0x0000FFFF /* HIF_ASK_TICK_CNT[15..0] */ +#define WF_HIF_DMASHDL_TOP_HIF_ASK_LONG_CHECK_HIF_ASK_TICK_CNT_SHFT 0 + +/* +* ---CPU_QUOTA_SET (0x7C026000 + 0x98)--- +* RETURN_PAGE_CNT[11..0] - (RW) CPU refill page count +* RESERVED12[15..12] - (RO) Reserved bits +* CPU_RETRUN_GID[19..16] - (RW) CPU refill group's ID +* RESERVED20[23..20] - (RO) Reserved bits +* CPU_RETRUN_MODE[25..24] - (RW) CPU refill mode selection +* 2'b00 : Substrate source mode +* 2'b01 : Return mode +* 2'b10 : Add source mode +* 2'b11 : Substrate reservation mode +* RESERVED26[30..26] - (RO) Reserved bits +* EXCUTE[31] - (WO) Excute this CR action +*/ +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_EXCUTE_ADDR \ + WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_ADDR +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_EXCUTE_MASK 0x80000000 /* EXCUTE[31] */ +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_EXCUTE_SHFT 31 +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_CPU_RETRUN_MODE_ADDR \ + WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_ADDR +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_CPU_RETRUN_MODE_MASK \ + 0x03000000 /* CPU_RETRUN_MODE[25..24] */ +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_CPU_RETRUN_MODE_SHFT 24 +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_CPU_RETRUN_GID_ADDR \ + WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_ADDR +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_CPU_RETRUN_GID_MASK \ + 0x000F0000 /* CPU_RETRUN_GID[19..16] */ +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_CPU_RETRUN_GID_SHFT 16 +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_RETURN_PAGE_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_ADDR +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_RETURN_PAGE_CNT_MASK \ + 0x00000FFF /* RETURN_PAGE_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_RETURN_PAGE_CNT_SHFT 0 + +/* +* ---ERROR_FLAG_CTRL (0x7C026000 + 0x9c)--- +* CNT_UDF_INT_DMASK[15..0] - (RW) Underflow flag interrupt disable mask +control: +* bit[11] : pse_src_pktret_udf_flag +* bit[10] : pse_src_pseret_udf_flag +* bit[9] : pse_rsv_udf_flag +* bit[8] : hif_ask_long_flag_flag +* bit[7] : pse_size_gt_max_size_flag +* bit[6] : ple_txd_gt_max_size_flag +* bit[5] : rsv_sub_curr_udf_flag +* bit[4] : refill_max0_udf_flag +* bit[3] : refill_max1_udf_flag +* bit[2] : src_sub_cur_udf_flag +* bit[1] : ffa_cnt_udf_flag +* bit[0] : freepg_cnt_udf_flag +* FREEPG_CNT_UDF_FLAG[16] - (RO) Freepage count underflow flag +* FFA_CNT_UDF_FLAG[17] - (RO) FFA count underflow flag +* SRC_SUB_CUR_UDF_FLAG[18] - (RO) PLE return stage source count underflow +flag +* REFILL_MAX1_UDF_FLAG[19] - (RO) Pktin return stage source count +* underflow flag +* REFILL_MAX0_UDF_FLAG[20] - (RO) RSV add SRC count greater than maximum +quota +* RSV_SUB_CURR_UDF_FLAG[21] - (RO) Reservation count underflow flag +* PLE_TXD_GT_MAX_SIZE_FLAG[22] - (RO) PLE txd size greater than max PLE txd +* size flag +* PSE_SIZE_GT_MAX_SIZE_FLAG[23] - (RO) PSE packet size greater than max packet +* size flag +* HIF_ASK_LONG_FLAG[24] - (RO) The HIF ask after long time period to +* grant flag +* PSE_RSV_UDF_FLAG[25] - (RO) The HIF ask to let reservation count +* underflow flag +* PSE_SRC_PSERET_UDF_FLAG[26] - (RO) The PSE source count PSE module return +* underflow flag +* PSE_SRC_PKTRET_UDF_FLAG[27] - (RO) The PSE source count packet in return +* underflow flag +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PSE_SRC_PKTRET_UDF_FLAG_ADDR \ + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PSE_SRC_PKTRET_UDF_FLAG_MASK \ + 0x08000000 /* PSE_SRC_PKTRET_UDF_FLAG[27] */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PSE_SRC_PKTRET_UDF_FLAG_SHFT 27 +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PSE_SRC_PSERET_UDF_FLAG_ADDR \ + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PSE_SRC_PSERET_UDF_FLAG_MASK \ + 0x04000000 /* PSE_SRC_PSERET_UDF_FLAG[26] */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PSE_SRC_PSERET_UDF_FLAG_SHFT 26 +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PSE_RSV_UDF_FLAG_ADDR \ + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PSE_RSV_UDF_FLAG_MASK \ + 0x02000000 /* PSE_RSV_UDF_FLAG[25] */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PSE_RSV_UDF_FLAG_SHFT 25 +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_HIF_ASK_LONG_FLAG_ADDR \ + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_HIF_ASK_LONG_FLAG_MASK \ + 0x01000000 /* HIF_ASK_LONG_FLAG[24] */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_HIF_ASK_LONG_FLAG_SHFT 24 +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PSE_SIZE_GT_MAX_SIZE_FLAG_ADDR \ + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PSE_SIZE_GT_MAX_SIZE_FLAG_MASK \ + 0x00800000 /* PSE_SIZE_GT_MAX_SIZE_FLAG[23] */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PSE_SIZE_GT_MAX_SIZE_FLAG_SHFT 23 +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PLE_TXD_GT_MAX_SIZE_FLAG_ADDR \ + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PLE_TXD_GT_MAX_SIZE_FLAG_MASK \ + 0x00400000 /* PLE_TXD_GT_MAX_SIZE_FLAG[22] */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_PLE_TXD_GT_MAX_SIZE_FLAG_SHFT 22 +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_RSV_SUB_CURR_UDF_FLAG_ADDR \ + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_RSV_SUB_CURR_UDF_FLAG_MASK \ + 0x00200000 /* RSV_SUB_CURR_UDF_FLAG[21] */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_RSV_SUB_CURR_UDF_FLAG_SHFT 21 +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_REFILL_MAX0_UDF_FLAG_ADDR \ + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_REFILL_MAX0_UDF_FLAG_MASK \ + 0x00100000 /* REFILL_MAX0_UDF_FLAG[20] */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_REFILL_MAX0_UDF_FLAG_SHFT 20 +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_REFILL_MAX1_UDF_FLAG_ADDR \ + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_REFILL_MAX1_UDF_FLAG_MASK \ + 0x00080000 /* REFILL_MAX1_UDF_FLAG[19] */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_REFILL_MAX1_UDF_FLAG_SHFT 19 +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_SRC_SUB_CUR_UDF_FLAG_ADDR \ + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_SRC_SUB_CUR_UDF_FLAG_MASK \ + 0x00040000 /* SRC_SUB_CUR_UDF_FLAG[18] */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_SRC_SUB_CUR_UDF_FLAG_SHFT 18 +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_FFA_CNT_UDF_FLAG_ADDR \ + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_FFA_CNT_UDF_FLAG_MASK \ + 0x00020000 /* FFA_CNT_UDF_FLAG[17] */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_FFA_CNT_UDF_FLAG_SHFT 17 +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_FREEPG_CNT_UDF_FLAG_ADDR \ + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_FREEPG_CNT_UDF_FLAG_MASK \ + 0x00010000 /* FREEPG_CNT_UDF_FLAG[16] */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_FREEPG_CNT_UDF_FLAG_SHFT 16 +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_CNT_UDF_INT_DMASK_ADDR \ + WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_ADDR +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_CNT_UDF_INT_DMASK_MASK \ + 0x0000FFFF /* CNT_UDF_INT_DMASK[15..0] */ +#define WF_HIF_DMASHDL_TOP_ERROR_FLAG_CTRL_CNT_UDF_INT_DMASK_SHFT 0 + +/* +* ---HIF_SCHEDULER_SETTING0 (0x7C026000 + 0xB0)--- +* PRIORITY0_GROUP[3..0] - (RW) Which group is priority 0, this group is +* highest priority +* PRIORITY1_GROUP[7..4] - (RW) Which group is priority 1 +* PRIORITY2_GROUP[11..8] - (RW) Which group is priority 2 +* PRIORITY3_GROUP[15..12] - (RW) Which group is priority 3 +* PRIORITY4_GROUP[19..16] - (RW) Which group is priority 4 +* PRIORITY5_GROUP[23..20] - (RW) Which group is priority 5 +* PRIORITY6_GROUP[27..24] - (RW) Which group is priority 6 +* PRIORITY7_GROUP[31..28] - (RW) Which group is priority 7 +*/ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY7_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY7_GROUP_MASK \ + 0xF0000000 /* PRIORITY7_GROUP[31..28] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY7_GROUP_SHFT 28 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY6_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY6_GROUP_MASK \ + 0x0F000000 /* PRIORITY6_GROUP[27..24] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY6_GROUP_SHFT 24 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY5_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY5_GROUP_MASK \ + 0x00F00000 /* PRIORITY5_GROUP[23..20] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY5_GROUP_SHFT 20 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY4_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY4_GROUP_MASK \ + 0x000F0000 /* PRIORITY4_GROUP[19..16] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY4_GROUP_SHFT 16 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY3_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY3_GROUP_MASK \ + 0x0000F000 /* PRIORITY3_GROUP[15..12] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY3_GROUP_SHFT 12 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY2_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY2_GROUP_MASK \ + 0x00000F00 /* PRIORITY2_GROUP[11..8] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY2_GROUP_SHFT 8 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY1_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY1_GROUP_MASK \ + 0x000000F0 /* PRIORITY1_GROUP[7..4] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY1_GROUP_SHFT 4 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY0_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY0_GROUP_MASK \ + 0x0000000F /* PRIORITY0_GROUP[3..0] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_PRIORITY0_GROUP_SHFT 0 + +/* +* ---HIF_SCHEDULER_SETTING1 (0x7C026000 + 0xB4)--- +* PRIORITY8_GROUP[3..0] - (RW) Which group is priority 8 +* PRIORITY9_GROUP[7..4] - (RW) Which group is priority 9 +* PRIORITY10_GROUP[11..8] - (RW) Which group is priority 10 +* PRIORITY11_GROUP[15..12] - (RW) Which group is priority 11 +* PRIORITY12_GROUP[19..16] - (RW) Which group is priority 12 +* PRIORITY13_GROUP[23..20] - (RW) Which group is priority 13 +* PRIORITY14_GROUP[27..24] - (RW) Which group is priority 14 +* PRIORITY15_GROUP[31..28] - (RW) Which group is priority 15, this group +* is last priority +*/ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY15_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY15_GROUP_MASK \ + 0xF0000000 /* PRIORITY15_GROUP[31..28] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY15_GROUP_SHFT 28 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY14_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY14_GROUP_MASK \ + 0x0F000000 /* PRIORITY14_GROUP[27..24] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY14_GROUP_SHFT 24 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY13_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY13_GROUP_MASK \ + 0x00F00000 /* PRIORITY13_GROUP[23..20] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY13_GROUP_SHFT 20 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY12_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY12_GROUP_MASK \ + 0x000F0000 /* PRIORITY12_GROUP[19..16] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY12_GROUP_SHFT 16 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY11_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY11_GROUP_MASK \ + 0x0000F000 /* PRIORITY11_GROUP[15..12] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY11_GROUP_SHFT 12 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY10_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY10_GROUP_MASK \ + 0x00000F00 /* PRIORITY10_GROUP[11..8] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY10_GROUP_SHFT 8 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY9_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY9_GROUP_MASK \ + 0x000000F0 /* PRIORITY9_GROUP[7..4] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY9_GROUP_SHFT 4 +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY8_GROUP_ADDR \ + WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY8_GROUP_MASK \ + 0x0000000F /* PRIORITY8_GROUP[3..0] */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_PRIORITY8_GROUP_SHFT 0 + +/* +* ---SLOT_SETTING0 (0x7C026000 + 0xC4)--- +* SLOT_0_SETTING[3..0] - (RW) Slot0 priority setting +* SLOT_1_SETTING[7..4] - (RW) Slot1 priority setting +* SLOT_2_SETTING[11..8] - (RW) Slot2 priority setting +* SLOT_3_SETTING[15..12] - (RW) Slot3 priority setting +* SLOT_4_SETTING[19..16] - (RW) Slot4 priority setting +* SLOT_5_SETTING[23..20] - (RW) Slot5 priority setting +* SLOT_6_SETTING[27..24] - (RW) Slot6 priority setting +* SLOT_7_SETTING[31..28] - (RW) Slot7 priority setting(which group ID) +*/ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_7_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_7_SETTING_MASK \ + 0xF0000000 /* SLOT_7_SETTING[31..28] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_7_SETTING_SHFT 28 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_6_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_6_SETTING_MASK \ + 0x0F000000 /* SLOT_6_SETTING[27..24] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_6_SETTING_SHFT 24 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_5_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_5_SETTING_MASK \ + 0x00F00000 /* SLOT_5_SETTING[23..20] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_5_SETTING_SHFT 20 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_4_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_4_SETTING_MASK \ + 0x000F0000 /* SLOT_4_SETTING[19..16] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_4_SETTING_SHFT 16 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_3_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_3_SETTING_MASK \ + 0x0000F000 /* SLOT_3_SETTING[15..12] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_3_SETTING_SHFT 12 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_2_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_2_SETTING_MASK \ + 0x00000F00 /* SLOT_2_SETTING[11..8] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_2_SETTING_SHFT 8 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_1_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_1_SETTING_MASK \ + 0x000000F0 /* SLOT_1_SETTING[7..4] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_1_SETTING_SHFT 4 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_0_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING0_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_0_SETTING_MASK \ + 0x0000000F /* SLOT_0_SETTING[3..0] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING0_SLOT_0_SETTING_SHFT 0 + +/* +* ---SLOT_SETTING1 (0x7C026000 + 0xC8)--- +* SLOT_8_SETTING[3..0] - (RW) Slot8 priority setting +* SLOT_9_SETTING[7..4] - (RW) Slot9 priority setting +* SLOT_10_SETTING[11..8] - (RW) Slot10 priority setting +* SLOT_11_SETTING[15..12] - (RW) Slo11 priority setting +* SLOT_12_SETTING[19..16] - (RW) Slot12 priority setting +* SLOT_13_SETTING[23..20] - (RW) Slot13 priority setting +* SLOT_14_SETTING[27..24] - (RW) Slot14 priority setting +* SLOT_15_SETTING[31..28] - (RW) Slot15 priority setting(which group ID) +*/ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_15_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_15_SETTING_MASK \ + 0xF0000000 /* SLOT_15_SETTING[31..28] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_15_SETTING_SHFT 28 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_14_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_14_SETTING_MASK \ + 0x0F000000 /* SLOT_14_SETTING[27..24] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_14_SETTING_SHFT 24 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_13_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_13_SETTING_MASK \ + 0x00F00000 /* SLOT_13_SETTING[23..20] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_13_SETTING_SHFT 20 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_12_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_12_SETTING_MASK \ + 0x000F0000 /* SLOT_12_SETTING[19..16] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_12_SETTING_SHFT 16 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_11_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_11_SETTING_MASK \ + 0x0000F000 /* SLOT_11_SETTING[15..12] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_11_SETTING_SHFT 12 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_10_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_10_SETTING_MASK \ + 0x00000F00 /* SLOT_10_SETTING[11..8] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_10_SETTING_SHFT 8 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_9_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_9_SETTING_MASK \ + 0x000000F0 /* SLOT_9_SETTING[7..4] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_9_SETTING_SHFT 4 +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_8_SETTING_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_SETTING1_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_8_SETTING_MASK \ + 0x0000000F /* SLOT_8_SETTING[3..0] */ +#define WF_HIF_DMASHDL_TOP_SLOT_SETTING1_SLOT_8_SETTING_SHFT 0 + +/* +* ---SLOT_PERIOD (0x7C026000 + 0xCC)--- +* SLOT_PERIOD[15..0] - (RW) Slot Period (clock periods) +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_SLOT_PERIOD_SLOT_PERIOD_ADDR \ + WF_HIF_DMASHDL_TOP_SLOT_PERIOD_ADDR +#define WF_HIF_DMASHDL_TOP_SLOT_PERIOD_SLOT_PERIOD_MASK \ + 0x0000FFFF /* SLOT_PERIOD[15..0] */ +#define WF_HIF_DMASHDL_TOP_SLOT_PERIOD_SLOT_PERIOD_SHFT 0 + +/* +* ---QUEUE_MAPPING0 (0x7C026000 + 0xd0)--- +* QUEUE0_MAPPING[3..0] - (RW) Queue 0 use which group ID +* QUEUE1_MAPPING[7..4] - (RW) Queue 1 use which group ID +* QUEUE2_MAPPING[11..8] - (RW) Queue 2 use which group ID +* QUEUE3_MAPPING[15..12] - (RW) Queue 3 use which group ID +* QUEUE4_MAPPING[19..16] - (RW) Queue 4 use which group ID +* QUEUE5_MAPPING[23..20] - (RW) Queue 5 use which group ID +* QUEUE6_MAPPING[27..24] - (RW) Queue 6 use which group ID +* QUEUE7_MAPPING[31..28] - (RW) Queue 7 use which group ID +*/ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE7_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE7_MAPPING_MASK \ + 0xF0000000 /* QUEUE7_MAPPING[31..28] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE7_MAPPING_SHFT 28 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE6_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE6_MAPPING_MASK \ + 0x0F000000 /* QUEUE6_MAPPING[27..24] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE6_MAPPING_SHFT 24 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE5_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE5_MAPPING_MASK \ + 0x00F00000 /* QUEUE5_MAPPING[23..20] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE5_MAPPING_SHFT 20 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE4_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE4_MAPPING_MASK \ + 0x000F0000 /* QUEUE4_MAPPING[19..16] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE4_MAPPING_SHFT 16 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE3_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE3_MAPPING_MASK \ + 0x0000F000 /* QUEUE3_MAPPING[15..12] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE3_MAPPING_SHFT 12 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE2_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE2_MAPPING_MASK \ + 0x00000F00 /* QUEUE2_MAPPING[11..8] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE2_MAPPING_SHFT 8 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE1_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE1_MAPPING_MASK \ + 0x000000F0 /* QUEUE1_MAPPING[7..4] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE1_MAPPING_SHFT 4 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE0_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE0_MAPPING_MASK \ + 0x0000000F /* QUEUE0_MAPPING[3..0] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE0_MAPPING_SHFT 0 + +/* +* ---QUEUE_MAPPING1 (0x7C026000 + 0xd4)--- +* QUEUE8_MAPPING[3..0] - (RW) Queue 8 use which group ID +* QUEUE9_MAPPING[7..4] - (RW) Queue 9 use which group ID +* QUEUE10_MAPPING[11..8] - (RW) Queue 10 use which group ID +* QUEUE11_MAPPING[15..12] - (RW) Queue 11 use which group ID +* QUEUE12_MAPPING[19..16] - (RW) Queue 12 use which group ID +* QUEUE13_MAPPING[23..20] - (RW) Queue 13 use which group ID +* QUEUE14_MAPPING[27..24] - (RW) Queue 14 use which group ID +* QUEUE15_MAPPING[31..28] - (RW) Queue 15 use which group ID +*/ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE15_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE15_MAPPING_MASK \ + 0xF0000000 /* QUEUE15_MAPPING[31..28] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE15_MAPPING_SHFT 28 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE14_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE14_MAPPING_MASK \ + 0x0F000000 /* QUEUE14_MAPPING[27..24] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE14_MAPPING_SHFT 24 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE13_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE13_MAPPING_MASK \ + 0x00F00000 /* QUEUE13_MAPPING[23..20] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE13_MAPPING_SHFT 20 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE12_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE12_MAPPING_MASK \ + 0x000F0000 /* QUEUE12_MAPPING[19..16] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE12_MAPPING_SHFT 16 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE11_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE11_MAPPING_MASK \ + 0x0000F000 /* QUEUE11_MAPPING[15..12] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE11_MAPPING_SHFT 12 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE10_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE10_MAPPING_MASK \ + 0x00000F00 /* QUEUE10_MAPPING[11..8] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE10_MAPPING_SHFT 8 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE9_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE9_MAPPING_MASK \ + 0x000000F0 /* QUEUE9_MAPPING[7..4] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE9_MAPPING_SHFT 4 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE8_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE8_MAPPING_MASK \ + 0x0000000F /* QUEUE8_MAPPING[3..0] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE8_MAPPING_SHFT 0 + +/* +* ---QUEUE_MAPPING2 (0x7C026000 + 0xd8)--- +* QUEUE16_MAPPING[3..0] - (RW) Queue 16 use which group ID +* QUEUE17_MAPPING[7..4] - (RW) Queue 17 use which group ID +* QUEUE18_MAPPING[11..8] - (RW) Queue 18 use which group ID +* QUEUE19_MAPPING[15..12] - (RW) Queue 19 use which group ID +* QUEUE20_MAPPING[19..16] - (RW) Queue 20 use which group ID +* QUEUE21_MAPPING[23..20] - (RW) Queue 21 use which group ID +* QUEUE22_MAPPING[27..24] - (RW) Queue 22 use which group ID +* QUEUE23_MAPPING[31..28] - (RW) Queue 23 use which group ID +*/ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE23_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE23_MAPPING_MASK \ + 0xF0000000 /* QUEUE23_MAPPING[31..28] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE23_MAPPING_SHFT 28 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE22_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE22_MAPPING_MASK \ + 0x0F000000 /* QUEUE22_MAPPING[27..24] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE22_MAPPING_SHFT 24 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE21_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE21_MAPPING_MASK \ + 0x00F00000 /* QUEUE21_MAPPING[23..20] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE21_MAPPING_SHFT 20 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE20_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE20_MAPPING_MASK \ + 0x000F0000 /* QUEUE20_MAPPING[19..16] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE20_MAPPING_SHFT 16 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE19_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE19_MAPPING_MASK \ + 0x0000F000 /* QUEUE19_MAPPING[15..12] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE19_MAPPING_SHFT 12 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE18_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE18_MAPPING_MASK \ + 0x00000F00 /* QUEUE18_MAPPING[11..8] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE18_MAPPING_SHFT 8 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE17_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE17_MAPPING_MASK \ + 0x000000F0 /* QUEUE17_MAPPING[7..4] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE17_MAPPING_SHFT 4 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE16_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE16_MAPPING_MASK \ + 0x0000000F /* QUEUE16_MAPPING[3..0] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE16_MAPPING_SHFT 0 + +/* +* ---QUEUE_MAPPING3 (0x7C026000 + 0xdc)--- +* QUEUE24_MAPPING[3..0] - (RW) Queue 24 use which group ID +* QUEUE25_MAPPING[7..4] - (RW) Queue 25 use which group ID +* QUEUE26_MAPPING[11..8] - (RW) Queue 26 use which group ID +* QUEUE27_MAPPING[15..12] - (RW) Queue 27 use which group ID +* QUEUE28_MAPPING[19..16] - (RW) Queue 28 use which group ID +* QUEUE29_MAPPING[23..20] - (RW) Queue 29 use which group ID +* QUEUE30_MAPPING[27..24] - (RW) Queue 30 use which group ID +* QUEUE31_MAPPING[31..28] - (RW) Queue 31 use which group ID +*/ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE31_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE31_MAPPING_MASK \ + 0xF0000000 /* QUEUE31_MAPPING[31..28] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE31_MAPPING_SHFT 28 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE30_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE30_MAPPING_MASK \ + 0x0F000000 /* QUEUE30_MAPPING[27..24] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE30_MAPPING_SHFT 24 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE29_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE29_MAPPING_MASK \ + 0x00F00000 /* QUEUE29_MAPPING[23..20] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE29_MAPPING_SHFT 20 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE28_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE28_MAPPING_MASK \ + 0x000F0000 /* QUEUE28_MAPPING[19..16] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE28_MAPPING_SHFT 16 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE27_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE27_MAPPING_MASK \ + 0x0000F000 /* QUEUE27_MAPPING[15..12] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE27_MAPPING_SHFT 12 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE26_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE26_MAPPING_MASK \ + 0x00000F00 /* QUEUE26_MAPPING[11..8] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE26_MAPPING_SHFT 8 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE25_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE25_MAPPING_MASK \ + 0x000000F0 /* QUEUE25_MAPPING[7..4] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE25_MAPPING_SHFT 4 +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE24_MAPPING_ADDR \ + WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE24_MAPPING_MASK \ + 0x0000000F /* QUEUE24_MAPPING[3..0] */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_QUEUE24_MAPPING_SHFT 0 + +/* +* ---STATUS_RD (0x7C026000 + 0x100)--- +* FFA_CNT[11..0] - (RO) Free for all (FFA) count +* RESERVED12[15..12] - (RO) Reserved bits +* FREE_PAGE_CNT[27..16] - (RO) Free page count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_FREE_PAGE_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_FREE_PAGE_CNT_MASK \ + 0x0FFF0000 /* FREE_PAGE_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_FREE_PAGE_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_FFA_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_FFA_CNT_MASK \ + 0x00000FFF /* FFA_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_FFA_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP0 (0x7C026000 + 0x140)--- +* G0_SRC_CNT[11..0] - (RO) Group0 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G0_RSV_CNT[27..16] - (RO) Group0 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_RSV_CNT_MASK \ + 0x0FFF0000 /* G0_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_SRC_CNT_MASK \ + 0x00000FFF /* G0_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP1 (0x7C026000 + 0x144)--- +* G1_SRC_CNT[11..0] - (RO) Group1 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G1_RSV_CNT[27..16] - (RO) Group1 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP1_G1_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP1_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP1_G1_RSV_CNT_MASK \ + 0x0FFF0000 /* G1_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP1_G1_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP1_G1_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP1_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP1_G1_SRC_CNT_MASK \ + 0x00000FFF /* G1_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP1_G1_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP2 (0x7C026000 + 0x148)--- +* G2_SRC_CNT[11..0] - (RO) Group2 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G2_RSV_CNT[27..16] - (RO) Group2 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP2_G2_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP2_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP2_G2_RSV_CNT_MASK \ + 0x0FFF0000 /* G2_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP2_G2_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP2_G2_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP2_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP2_G2_SRC_CNT_MASK \ + 0x00000FFF /* G2_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP2_G2_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP3 (0x7C026000 + 0x14c)--- +* G3_SRC_CNT[11..0] - (RO) Group3 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G3_RSV_CNT[27..16] - (RO) Group3 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP3_G3_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP3_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP3_G3_RSV_CNT_MASK \ + 0x0FFF0000 /* G3_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP3_G3_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP3_G3_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP3_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP3_G3_SRC_CNT_MASK \ + 0x00000FFF /* G3_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP3_G3_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP4 (0x7C026000 + 0x150)--- +* G4_SRC_CNT[11..0] - (RO) Group4 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G4_RSV_CNT[27..16] - (RO) Group4 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP4_G4_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP4_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP4_G4_RSV_CNT_MASK \ + 0x0FFF0000 /* G4_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP4_G4_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP4_G4_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP4_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP4_G4_SRC_CNT_MASK \ + 0x00000FFF /* G4_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP4_G4_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP5 (0x7C026000 + 0x154)--- +* G5_SRC_CNT[11..0] - (RO) Group5 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G5_RSV_CNT[27..16] - (RO) Group5 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP5_G5_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP5_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP5_G5_RSV_CNT_MASK \ + 0x0FFF0000 /* G5_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP5_G5_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP5_G5_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP5_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP5_G5_SRC_CNT_MASK \ + 0x00000FFF /* G5_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP5_G5_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP6 (0x7C026000 + 0x158)--- +* G6_SRC_CNT[11..0] - (RO) Group6 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G6_RSV_CNT[27..16] - (RO) Group6 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP6_G6_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP6_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP6_G6_RSV_CNT_MASK \ + 0x0FFF0000 /* G6_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP6_G6_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP6_G6_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP6_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP6_G6_SRC_CNT_MASK \ + 0x00000FFF /* G6_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP6_G6_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP7 (0x7C026000 + 0x15C)--- +* G7_SRC_CNT[11..0] - (RO) Group7 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G7_RSV_CNT[27..16] - (RO) Group7 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP7_G7_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP7_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP7_G7_RSV_CNT_MASK \ + 0x0FFF0000 /* G7_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP7_G7_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP7_G7_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP7_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP7_G7_SRC_CNT_MASK \ + 0x00000FFF /* G7_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP7_G7_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP8 (0x7C026000 + 0x160)--- +* G8_SRC_CNT[11..0] - (RO) Group8 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G8_RSV_CNT[27..16] - (RO) Group8 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP8_G8_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP8_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP8_G8_RSV_CNT_MASK \ + 0x0FFF0000 /* G8_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP8_G8_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP8_G8_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP8_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP8_G8_SRC_CNT_MASK \ + 0x00000FFF /* G8_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP8_G8_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP9 (0x7C026000 + 0x164)--- +* G9_SRC_CNT[11..0] - (RO) Group9 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G9_RSV_CNT[27..16] - (RO) Group9 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP9_G9_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP9_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP9_G9_RSV_CNT_MASK \ + 0x0FFF0000 /* G9_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP9_G9_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP9_G9_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP9_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP9_G9_SRC_CNT_MASK \ + 0x00000FFF /* G9_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP9_G9_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP10 (0x7C026000 + 0x168)--- +* G10_SRC_CNT[11..0] - (RO) Group10 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G10_RSV_CNT[27..16] - (RO) Group10 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP10_G10_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP10_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP10_G10_RSV_CNT_MASK \ + 0x0FFF0000 /* G10_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP10_G10_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP10_G10_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP10_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP10_G10_SRC_CNT_MASK \ + 0x00000FFF /* G10_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP10_G10_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP11 (0x7C026000 + 0x16c)--- +* G11_SRC_CNT[11..0] - (RO) Group11 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G11_RSV_CNT[27..16] - (RO) Group11 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP11_G11_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP11_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP11_G11_RSV_CNT_MASK \ + 0x0FFF0000 /* G11_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP11_G11_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP11_G11_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP11_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP11_G11_SRC_CNT_MASK \ + 0x00000FFF /* G11_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP11_G11_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP12 (0x7C026000 + 0x170)--- +* G12_SRC_CNT[11..0] - (RO) Group12 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G12_RSV_CNT[27..16] - (RO) Group12 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP12_G12_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP12_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP12_G12_RSV_CNT_MASK \ + 0x0FFF0000 /* G12_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP12_G12_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP12_G12_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP12_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP12_G12_SRC_CNT_MASK \ + 0x00000FFF /* G12_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP12_G12_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP13 (0x7C026000 + 0x174)--- +* G13_SRC_CNT[11..0] - (RO) Group13 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G13_RSV_CNT[27..16] - (RO) Group13 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP13_G13_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP13_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP13_G13_RSV_CNT_MASK \ + 0x0FFF0000 /* G13_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP13_G13_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP13_G13_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP13_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP13_G13_SRC_CNT_MASK \ + 0x00000FFF /* G13_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP13_G13_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP14 (0x7C026000 + 0x178)--- +* G14_SRC_CNT[11..0] - (RO) Group14 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G14_RSV_CNT[27..16] - (RO) Group14 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP14_G14_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP14_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP14_G14_RSV_CNT_MASK \ + 0x0FFF0000 /* G14_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP14_G14_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP14_G14_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP14_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP14_G14_SRC_CNT_MASK \ + 0x00000FFF /* G14_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP14_G14_SRC_CNT_SHFT 0 + +/* +* ---STATUS_RD_GP15 (0x7C026000 + 0x17C)--- +* G15_SRC_CNT[11..0] - (RO) Group15 source count +* RESERVED12[15..12] - (RO) Reserved bits +* G15_RSV_CNT[27..16] - (RO) Group15 reservation count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP15_G15_RSV_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP15_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP15_G15_RSV_CNT_MASK \ + 0x0FFF0000 /* G15_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP15_G15_RSV_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP15_G15_SRC_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_STATUS_RD_GP15_ADDR +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP15_G15_SRC_CNT_MASK \ + 0x00000FFF /* G15_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP15_G15_SRC_CNT_SHFT 0 + +/* +* ---RD_GROUP_PKT_CNT0 (0x7C026000 + 0x180)--- +* GP0_ASK_CNT[7..0] - (RO) Group0 ask count +* GP0_PKTIN_CNT[15..8] - (RO) Group0 packet in count +* GP1_ASK_CNT[23..16] - (RO) Group1 ask count +* GP1_PKTIN_CNT[31..24] - (RO) Group1 packet in count +*/ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_GP1_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_GP1_PKTIN_CNT_MASK \ + 0xFF000000 /* GP1_PKTIN_CNT[31..24] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_GP1_PKTIN_CNT_SHFT 24 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_GP1_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_GP1_ASK_CNT_MASK \ + 0x00FF0000 /* GP1_ASK_CNT[23..16] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_GP1_ASK_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_GP0_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_GP0_PKTIN_CNT_MASK \ + 0x0000FF00 /* GP0_PKTIN_CNT[15..8] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_GP0_PKTIN_CNT_SHFT 8 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_GP0_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_GP0_ASK_CNT_MASK \ + 0x000000FF /* GP0_ASK_CNT[7..0] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_GP0_ASK_CNT_SHFT 0 + +/* +* ---RD_GROUP_PKT_CNT1 (0x7C026000 + 0x184)--- +* GP2_ASK_CNT[7..0] - (RO) Group2 ask count +* GP2_PKTIN_CNT[15..8] - (RO) Group2 packet in count +* GP3_ASK_CNT[23..16] - (RO) Group3 ask count +* GP3_PKTIN_CNT[31..24] - (RO) Group3 packet in count +*/ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_GP3_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_GP3_PKTIN_CNT_MASK \ + 0xFF000000 /* GP3_PKTIN_CNT[31..24] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_GP3_PKTIN_CNT_SHFT 24 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_GP3_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_GP3_ASK_CNT_MASK \ + 0x00FF0000 /* GP3_ASK_CNT[23..16] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_GP3_ASK_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_GP2_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_GP2_PKTIN_CNT_MASK \ + 0x0000FF00 /* GP2_PKTIN_CNT[15..8] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_GP2_PKTIN_CNT_SHFT 8 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_GP2_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_GP2_ASK_CNT_MASK \ + 0x000000FF /* GP2_ASK_CNT[7..0] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT1_GP2_ASK_CNT_SHFT 0 + +/* +* ---RD_GROUP_PKT_CNT2 (0x7C026000 + 0x188)--- +* GP4_ASK_CNT[7..0] - (RO) Group4 ask count +* GP4_PKTIN_CNT[15..8] - (RO) Group4 packet in count +* GP5_ASK_CNT[23..16] - (RO) Group5 ask count +* GP5_PKTIN_CNT[31..24] - (RO) Group5 packet in count +*/ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_GP5_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_GP5_PKTIN_CNT_MASK \ + 0xFF000000 /* GP5_PKTIN_CNT[31..24] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_GP5_PKTIN_CNT_SHFT 24 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_GP5_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_GP5_ASK_CNT_MASK \ + 0x00FF0000 /* GP5_ASK_CNT[23..16] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_GP5_ASK_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_GP4_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_GP4_PKTIN_CNT_MASK \ + 0x0000FF00 /* GP4_PKTIN_CNT[15..8] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_GP4_PKTIN_CNT_SHFT 8 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_GP4_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_GP4_ASK_CNT_MASK \ + 0x000000FF /* GP4_ASK_CNT[7..0] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT2_GP4_ASK_CNT_SHFT 0 + +/* +* ---RD_GROUP_PKT_CNT3 (0x7C026000 + 0x18c)--- +* GP6_ASK_CNT[7..0] - (RO) Group6 ask count +* GP6_PKTIN_CNT[15..8] - (RO) Group6 packet in count +* GP7_ASK_CNT[23..16] - (RO) Group7 ask count +* GP7_PKTIN_CNT[31..24] - (RO) Group7 packet in count +*/ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_GP7_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_GP7_PKTIN_CNT_MASK \ + 0xFF000000 /* GP7_PKTIN_CNT[31..24] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_GP7_PKTIN_CNT_SHFT 24 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_GP7_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_GP7_ASK_CNT_MASK \ + 0x00FF0000 /* GP7_ASK_CNT[23..16] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_GP7_ASK_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_GP6_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_GP6_PKTIN_CNT_MASK \ + 0x0000FF00 /* GP6_PKTIN_CNT[15..8] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_GP6_PKTIN_CNT_SHFT 8 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_GP6_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_GP6_ASK_CNT_MASK \ + 0x000000FF /* GP6_ASK_CNT[7..0] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT3_GP6_ASK_CNT_SHFT 0 + +/* +* ---RD_GROUP_PKT_CNT4 (0x7C026000 + 0x190)--- +* GP8_ASK_CNT[7..0] - (RO) Group8 ask count +* GP8_PKTIN_CNT[15..8] - (RO) Group8 packet in count +* GP9_ASK_CNT[23..16] - (RO) Group9 ask count +* GP9_PKTIN_CNT[31..24] - (RO) Group9 packet in count +*/ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_GP9_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_GP9_PKTIN_CNT_MASK \ + 0xFF000000 /* GP9_PKTIN_CNT[31..24] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_GP9_PKTIN_CNT_SHFT 24 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_GP9_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_GP9_ASK_CNT_MASK \ + 0x00FF0000 /* GP9_ASK_CNT[23..16] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_GP9_ASK_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_GP8_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_GP8_PKTIN_CNT_MASK \ + 0x0000FF00 /* GP8_PKTIN_CNT[15..8] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_GP8_PKTIN_CNT_SHFT 8 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_GP8_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_GP8_ASK_CNT_MASK \ + 0x000000FF /* GP8_ASK_CNT[7..0] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT4_GP8_ASK_CNT_SHFT 0 + +/* +* ---RD_GROUP_PKT_CNT5 (0x7C026000 + 0x194)--- +* GP10_ASK_CNT[7..0] - (RO) Group10 ask count +* GP10_PKTIN_CNT[15..8] - (RO) Group10 packet in count +* GP11_ASK_CNT[23..16] - (RO) Group11 ask count +* GP11_PKTIN_CNT[31..24] - (RO) Group11 packet in count +*/ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_GP11_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_GP11_PKTIN_CNT_MASK \ + 0xFF000000 /* GP11_PKTIN_CNT[31..24] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_GP11_PKTIN_CNT_SHFT 24 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_GP11_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_GP11_ASK_CNT_MASK \ + 0x00FF0000 /* GP11_ASK_CNT[23..16] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_GP11_ASK_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_GP10_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_GP10_PKTIN_CNT_MASK \ + 0x0000FF00 /* GP10_PKTIN_CNT[15..8] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_GP10_PKTIN_CNT_SHFT 8 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_GP10_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_GP10_ASK_CNT_MASK \ + 0x000000FF /* GP10_ASK_CNT[7..0] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT5_GP10_ASK_CNT_SHFT 0 + +/* +* ---RD_GROUP_PKT_CNT6 (0x7C026000 + 0x198)--- +* GP12_ASK_CNT[7..0] - (RO) Group12 ask count +* GP12_PKTIN_CNT[15..8] - (RO) Group12 packet in count +* GP13_ASK_CNT[23..16] - (RO) Group13 ask count +* GP13_PKTIN_CNT[31..24] - (RO) Group13 packet in count +*/ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_GP13_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_GP13_PKTIN_CNT_MASK \ + 0xFF000000 /* GP13_PKTIN_CNT[31..24] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_GP13_PKTIN_CNT_SHFT 24 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_GP13_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_GP13_ASK_CNT_MASK \ + 0x00FF0000 /* GP13_ASK_CNT[23..16] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_GP13_ASK_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_GP12_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_GP12_PKTIN_CNT_MASK \ + 0x0000FF00 /* GP12_PKTIN_CNT[15..8] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_GP12_PKTIN_CNT_SHFT 8 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_GP12_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_GP12_ASK_CNT_MASK \ + 0x000000FF /* GP12_ASK_CNT[7..0] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT6_GP12_ASK_CNT_SHFT 0 + +/* +* ---RD_GROUP_PKT_CNT7 (0x7C026000 + 0x19c)--- +* GP14_ASK_CNT[7..0] - (RO) Group14 ask count +* GP14_PKTIN_CNT[15..8] - (RO) Group14 packet in count +* GP15_ASK_CNT[23..16] - (RO) Group15 ask count +* GP15_PKTIN_CNT[31..24] - (RO) Group15 packet in count +*/ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_GP15_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_GP15_PKTIN_CNT_MASK \ + 0xFF000000 /* GP15_PKTIN_CNT[31..24] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_GP15_PKTIN_CNT_SHFT 24 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_GP15_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_GP15_ASK_CNT_MASK \ + 0x00FF0000 /* GP15_ASK_CNT[23..16] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_GP15_ASK_CNT_SHFT 16 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_GP14_PKTIN_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_GP14_PKTIN_CNT_MASK \ + 0x0000FF00 /* GP14_PKTIN_CNT[15..8] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_GP14_PKTIN_CNT_SHFT 8 +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_GP14_ASK_CNT_ADDR \ + WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_ADDR +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_GP14_ASK_CNT_MASK \ + 0x000000FF /* GP14_ASK_CNT[7..0] */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_GP14_ASK_CNT_SHFT 0 + +#ifdef __cplusplus +} +#endif + +#endif /* __WF_HIF_DMASHDL_TOP_REGS_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/soc3_0/wf_ple_top.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/soc3_0/wf_ple_top.h new file mode 100644 index 0000000000000..ae6d51e5569e6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/soc3_0/wf_ple_top.h @@ -0,0 +1,6739 @@ +/* [File] : wf_ple_top.h */ +/* [Revision time] : Mon Apr 15 14:13:52 2019 */ +/* [Description] : This file is auto generated by CODA */ +/* [Copyright] : Copyright (C) 2019 Mediatek Incorportion. All rights +*/ +/* reserved. */ + +#ifndef __WF_PLE_TOP_REGS_H__ +#define __WF_PLE_TOP_REGS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* **************************************************************** */ +/* */ +/* WF_PLE_TOP CR Definitions */ +/* */ +/* **************************************************************** */ + +#define WF_PLE_TOP_BASE 0x820C0000 + +#define WF_PLE_TOP_GC_ADDR \ + (WF_PLE_TOP_BASE + 0x00) /* 0000 */ +#define WF_PLE_TOP_PBUF_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x14) /* 0014 */ +#define WF_PLE_TOP_TIMEOUT_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x1c) /* 001C */ +#define WF_PLE_TOP_INT_N9_EN_MASK_ADDR \ + (WF_PLE_TOP_BASE + 0x20) /* 0020 */ +#define WF_PLE_TOP_INT_N9_STS_ADDR \ + (WF_PLE_TOP_BASE + 0x24) /* 0024 */ +#define WF_PLE_TOP_INT_N9_ERR_STS_ADDR \ + (WF_PLE_TOP_BASE + 0x28) /* 0028 */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_ADDR \ + (WF_PLE_TOP_BASE + 0x2C) /* 002C */ +#define WF_PLE_TOP_HOST_REPORT0_ADDR \ + (WF_PLE_TOP_BASE + 0x30) /* 0030 */ +#define WF_PLE_TOP_HOST_REPORT1_ADDR \ + (WF_PLE_TOP_BASE + 0x34) /* 0034 */ +#define WF_PLE_TOP_HOST_REPORT2_ADDR \ + (WF_PLE_TOP_BASE + 0x38) /* 0038 */ +#define WF_PLE_TOP_BLK_MODE_RATE_LMT_ADDR \ + (WF_PLE_TOP_BASE + 0x3c) /* 003C */ +#define WF_PLE_TOP_C_GET_FID_0_ADDR \ + (WF_PLE_TOP_BASE + 0x40) /* 0040 */ +#define WF_PLE_TOP_C_GET_FID_1_ADDR \ + (WF_PLE_TOP_BASE + 0x44) /* 0044 */ +#define WF_PLE_TOP_RELEASE_CTRL_0_ADDR \ + (WF_PLE_TOP_BASE + 0x50) /* 0050 */ +#define WF_PLE_TOP_RELEASE_CTRL_1_ADDR \ + (WF_PLE_TOP_BASE + 0x54) /* 0054 */ +#define WF_PLE_TOP_RELEASE_CTRL_3_ADDR \ + (WF_PLE_TOP_BASE + 0x5c) /* 005C */ +#define WF_PLE_TOP_C_EN_QUEUE_0_ADDR \ + (WF_PLE_TOP_BASE + 0x60) /* 0060 */ +#define WF_PLE_TOP_C_EN_QUEUE_1_ADDR \ + (WF_PLE_TOP_BASE + 0x64) /* 0064 */ +#define WF_PLE_TOP_C_EN_QUEUE_2_ADDR \ + (WF_PLE_TOP_BASE + 0x68) /* 0068 */ +#define WF_PLE_TOP_C_DE_QUEUE_0_ADDR \ + (WF_PLE_TOP_BASE + 0x80) /* 0080 */ +#define WF_PLE_TOP_C_DE_QUEUE_1_ADDR \ + (WF_PLE_TOP_BASE + 0x84) /* 0084 */ +#define WF_PLE_TOP_C_DE_QUEUE_2_ADDR \ + (WF_PLE_TOP_BASE + 0x88) /* 0088 */ +#define WF_PLE_TOP_C_DE_QUEUE_3_ADDR \ + (WF_PLE_TOP_BASE + 0x8c) /* 008C */ +#define WF_PLE_TOP_C_DE_QUEUE_4_ADDR \ + (WF_PLE_TOP_BASE + 0x90) /* 0090 */ +#define WF_PLE_TOP_ALLOCATE_0_ADDR \ + (WF_PLE_TOP_BASE + 0xA0) /* 00A0 */ +#define WF_PLE_TOP_ALLOCATE_1_ADDR \ + (WF_PLE_TOP_BASE + 0xA4) /* 00A4 */ +#define WF_PLE_TOP_ALLOCATE_2_ADDR \ + (WF_PLE_TOP_BASE + 0xA8) /* 00A8 */ +#define WF_PLE_TOP_QUEUE_EMPTY_ADDR \ + (WF_PLE_TOP_BASE + 0xB0) /* 00B0 */ +#define WF_PLE_TOP_FREEPG_START_END_ADDR \ + (WF_PLE_TOP_BASE + 0xc0) /* 00C0 */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR \ + (WF_PLE_TOP_BASE + 0xc4) /* 00C4 */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR \ + (WF_PLE_TOP_BASE + 0xd8) /* 00D8 */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR \ + (WF_PLE_TOP_BASE + 0xdc) /* 00DC */ +#define WF_PLE_TOP_TO_N9_INT_ADDR \ + (WF_PLE_TOP_BASE + 0xf0) /* 00F0 */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR \ + (WF_PLE_TOP_BASE + 0xf4) /* 00F4 */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR \ + (WF_PLE_TOP_BASE + 0xf8) /* 00F8 */ +#define WF_PLE_TOP_FREEPG_CNT_ADDR \ + (WF_PLE_TOP_BASE + 0x100) /* 0100 */ +#define WF_PLE_TOP_FREEPG_HEAD_TAIL_ADDR \ + (WF_PLE_TOP_BASE + 0x104) /* 0104 */ +#define WF_PLE_TOP_PG_HIF_GROUP_ADDR \ + (WF_PLE_TOP_BASE + 0x110) /* 0110 */ +#define WF_PLE_TOP_HIF_PG_INFO_ADDR \ + (WF_PLE_TOP_BASE + 0x114) /* 0114 */ +#define WF_PLE_TOP_PG_HIF_WMTXD_GROUP_ADDR \ + (WF_PLE_TOP_BASE + 0x118) /* 0118 */ +#define WF_PLE_TOP_HIF_WMTXD_PG_INFO_ADDR \ + (WF_PLE_TOP_BASE + 0x11C) /* 011C */ +#define WF_PLE_TOP_PG_HIF_TXCMD_GROUP_ADDR \ + (WF_PLE_TOP_BASE + 0x120) /* 0120 */ +#define WF_PLE_TOP_HIF_TXCMD_PG_INFO_ADDR \ + (WF_PLE_TOP_BASE + 0x124) /* 0124 */ +#define WF_PLE_TOP_TWT_TX_CTRL0_ADDR \ + (WF_PLE_TOP_BASE + 0x130) /* 0130 */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR \ + (WF_PLE_TOP_BASE + 0x140) /* 0140 */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_1_ADDR \ + (WF_PLE_TOP_BASE + 0x144) /* 0144 */ +#define WF_PLE_TOP_PG_CPU_GROUP_ADDR \ + (WF_PLE_TOP_BASE + 0x150) /* 0150 */ +#define WF_PLE_TOP_CPU_PG_INFO_ADDR \ + (WF_PLE_TOP_BASE + 0x154) /* 0154 */ +#define WF_PLE_TOP_PLE_LOG_0_ADDR \ + (WF_PLE_TOP_BASE + 0x170) /* 0170 */ +#define WF_PLE_TOP_PLE_LOG_1_ADDR \ + (WF_PLE_TOP_BASE + 0x174) /* 0174 */ +#define WF_PLE_TOP_PLE_LOG_2_ADDR \ + (WF_PLE_TOP_BASE + 0x178) /* 0178 */ +#define WF_PLE_TOP_PLE_LOG_3_ADDR \ + (WF_PLE_TOP_BASE + 0x17c) /* 017C */ +#define WF_PLE_TOP_WMMAC_PGCNT_0_ADDR \ + (WF_PLE_TOP_BASE + 0x180) /* 0180 */ +#define WF_PLE_TOP_WMMAC_PGCNT_1_ADDR \ + (WF_PLE_TOP_BASE + 0x184) /* 0184 */ +#define WF_PLE_TOP_WMMAC_PGCNT_2_ADDR \ + (WF_PLE_TOP_BASE + 0x188) /* 0188 */ +#define WF_PLE_TOP_WMMAC_PGCNT_3_ADDR \ + (WF_PLE_TOP_BASE + 0x18c) /* 018C */ +#define WF_PLE_TOP_WMMAC_PGCNT_4_ADDR \ + (WF_PLE_TOP_BASE + 0x190) /* 0190 */ +#define WF_PLE_TOP_WMMAC_PGCNT_5_ADDR \ + (WF_PLE_TOP_BASE + 0x194) /* 0194 */ +#define WF_PLE_TOP_WMMAC_PGCNT_6_ADDR \ + (WF_PLE_TOP_BASE + 0x198) /* 0198 */ +#define WF_PLE_TOP_WMMAC_PGCNT_7_ADDR \ + (WF_PLE_TOP_BASE + 0x19c) /* 019C */ +#define WF_PLE_TOP_RL_BUF_CTRL_0_ADDR \ + (WF_PLE_TOP_BASE + 0x1A0) /* 01A0 */ +#define WF_PLE_TOP_RL_BUF_CTRL_1_ADDR \ + (WF_PLE_TOP_BASE + 0x1A4) /* 01A4 */ +#define WF_PLE_TOP_FL_QUE_CTRL_0_ADDR \ + (WF_PLE_TOP_BASE + 0x1B0) /* 01B0 */ +#define WF_PLE_TOP_FL_QUE_CTRL_1_ADDR \ + (WF_PLE_TOP_BASE + 0x1B4) /* 01B4 */ +#define WF_PLE_TOP_FL_QUE_CTRL_2_ADDR \ + (WF_PLE_TOP_BASE + 0x1B8) /* 01B8 */ +#define WF_PLE_TOP_FL_QUE_CTRL_3_ADDR \ + (WF_PLE_TOP_BASE + 0x1BC) /* 01BC */ +#define WF_PLE_TOP_PL_QUE_CTRL_0_ADDR \ + (WF_PLE_TOP_BASE + 0x1C0) /* 01C0 */ +#define WF_PLE_TOP_PLE_DELAY_TX_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x1d0) /* 01D0 */ +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x1d4) /* 01D4 */ +#define WF_PLE_TOP_MACTX_LENGTH_LIMIT_ADDR \ + (WF_PLE_TOP_BASE + 0x1ec) /* 01EC */ +#define WF_PLE_TOP_HIF_ENQ_PKT_NUM_ADDR \ + (WF_PLE_TOP_BASE + 0x1f0) /* 01F0 */ +#define WF_PLE_TOP_CPU_ENQ_PKT_NUM_ADDR \ + (WF_PLE_TOP_BASE + 0x1f4) /* 01F4 */ +#define WF_PLE_TOP_RLS_MSDU_PKT_NUM_ADDR \ + (WF_PLE_TOP_BASE + 0x1f8) /* 01F8 */ +#define WF_PLE_TOP_HOST_REPORT_NUM_ADDR \ + (WF_PLE_TOP_BASE + 0x1fc) /* 01FC */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR \ + (WF_PLE_TOP_BASE + 0x220) /* 0220 */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_ADDR \ + (WF_PLE_TOP_BASE + 0x224) /* 0224 */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR \ + (WF_PLE_TOP_BASE + 0x228) /* 0228 */ +#define WF_PLE_TOP_UMAC_DBG_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x240) /* 0240 */ +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_ADDR \ + (WF_PLE_TOP_BASE + 0x244) /* 0244 */ +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_ADDR \ + (WF_PLE_TOP_BASE + 0x248) /* 0248 */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x24C) /* 024C */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR \ + (WF_PLE_TOP_BASE + 0x250) /* 0250 */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_ADDR \ + (WF_PLE_TOP_BASE + 0x258) /* 0258 */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR \ + (WF_PLE_TOP_BASE + 0x25C) /* 025C */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL9_ADDR \ + (WF_PLE_TOP_BASE + 0x260) /* 0260 */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL10_ADDR \ + (WF_PLE_TOP_BASE + 0x264) /* 0264 */ +#define WF_PLE_TOP_FUNC_ACT_CNT_1_ADDR \ + (WF_PLE_TOP_BASE + 0x284) /* 0284 */ +#define WF_PLE_TOP_PORT_SER_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x2A0) /* 02A0 */ +#define WF_PLE_TOP_MACTX_SER_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x2A4) /* 02A4 */ +#define WF_PLE_TOP_DRR_SER_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x2A8) /* 02A8 */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL5_ADDR \ + (WF_PLE_TOP_BASE + 0x2c0) /* 02C0 */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL6_ADDR \ + (WF_PLE_TOP_BASE + 0x2c4) /* 02C4 */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL7_ADDR \ + (WF_PLE_TOP_BASE + 0x2c8) /* 02C8 */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL8_ADDR \ + (WF_PLE_TOP_BASE + 0x2cc) /* 02CC */ +#define WF_PLE_TOP_SRAM_MBIST_BACKGROUND_ADDR \ + (WF_PLE_TOP_BASE + 0x2d0) /* 02D0 */ +#define WF_PLE_TOP_SRAM_MBIST_BSEL_ADDR \ + (WF_PLE_TOP_BASE + 0x2d4) /* 02D4 */ +#define WF_PLE_TOP_SRAM_MBIST_DONE_ADDR \ + (WF_PLE_TOP_BASE + 0x2d8) /* 02D8 */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR \ + (WF_PLE_TOP_BASE + 0x2dc) /* 02DC */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x2e0) /* 02E0 */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL1_ADDR \ + (WF_PLE_TOP_BASE + 0x2e4) /* 02E4 */ +#define WF_PLE_TOP_BSS_DBDC_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x2ec) /* 02EC */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL2_ADDR \ + (WF_PLE_TOP_BASE + 0x2f0) /* 02F0 */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL3_ADDR \ + (WF_PLE_TOP_BASE + 0x2f4) /* 02F4 */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL4_ADDR \ + (WF_PLE_TOP_BASE + 0x2f8) /* 02F8 */ +#define WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x2fc) /* 02FC */ +#define WF_PLE_TOP_DRR_TABLE_WDATA0_ADDR \ + (WF_PLE_TOP_BASE + 0x340) /* 0340 */ +#define WF_PLE_TOP_DRR_TABLE_WDATA1_ADDR \ + (WF_PLE_TOP_BASE + 0x344) /* 0344 */ +#define WF_PLE_TOP_DRR_TABLE_WDATA2_ADDR \ + (WF_PLE_TOP_BASE + 0x348) /* 0348 */ +#define WF_PLE_TOP_DRR_TABLE_WDATA3_ADDR \ + (WF_PLE_TOP_BASE + 0x34c) /* 034C */ +#define WF_PLE_TOP_DRR_TABLE_RDATA0_ADDR \ + (WF_PLE_TOP_BASE + 0x350) /* 0350 */ +#define WF_PLE_TOP_DRR_TABLE_RDATA1_ADDR \ + (WF_PLE_TOP_BASE + 0x354) /* 0354 */ +#define WF_PLE_TOP_DRR_TABLE_RDATA2_ADDR \ + (WF_PLE_TOP_BASE + 0x358) /* 0358 */ +#define WF_PLE_TOP_DRR_TABLE_RDATA3_ADDR \ + (WF_PLE_TOP_BASE + 0x35c) /* 035C */ +#define WF_PLE_TOP_VOW_CONTROL_ADDR \ + (WF_PLE_TOP_BASE + 0x370) /* 0370 */ +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_ADDR \ + (WF_PLE_TOP_BASE + 0x374) /* 0374 */ +#define WF_PLE_TOP_CHECK_BW_TIME_TOKEN__ADDR \ + (WF_PLE_TOP_BASE + 0x378) /* 0378 */ +#define WF_PLE_TOP_CHECK_BW_LENGTH_TOKEN__ADDR \ + (WF_PLE_TOP_BASE + 0x37c) /* 037C */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_ADDR \ + (WF_PLE_TOP_BASE + 0x380) /* 0380 */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_ADDR \ + (WF_PLE_TOP_BASE + 0x384) /* 0384 */ +#define WF_PLE_TOP_DRR_TABLE_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x388) /* 0388 */ +#define WF_PLE_TOP_VOW_CTRL1_ADDR \ + (WF_PLE_TOP_BASE + 0x38C) /* 038C */ +#define WF_PLE_TOP_DRR_CHNL_EMPTY_ADDR \ + (WF_PLE_TOP_BASE + 0x390) /* 0390 */ +#define WF_PLE_TOP_DRR_SPL_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x394) /* 0394 */ +#define WF_PLE_TOP_DRR_SPL_CTRL_1_ADDR \ + (WF_PLE_TOP_BASE + 0x398) /* 0398 */ +#define WF_PLE_TOP_VOW_DBG_SEL_ADDR \ + (WF_PLE_TOP_BASE + 0x3A0) /* 03A0 */ +#define WF_PLE_TOP_AIRTIME_DBG_INFO0_ADDR \ + (WF_PLE_TOP_BASE + 0x3A4) /* 03A4 */ +#define WF_PLE_TOP_AIRTIME_DBG_INFO1_ADDR \ + (WF_PLE_TOP_BASE + 0x3A8) /* 03A8 */ +#define WF_PLE_TOP_DRR_SW_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x3C8) /* 03C8 */ +#define WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_ADDR \ + (WF_PLE_TOP_BASE + 0x3CC) /* 03CC */ +#define WF_PLE_TOP_STATION_PAUSE0_ADDR \ + (WF_PLE_TOP_BASE + 0x400) /* 0400 */ +#define WF_PLE_TOP_DIS_STA_MAP0_ADDR \ + (WF_PLE_TOP_BASE + 0x440) /* 0440 */ +#define WF_PLE_TOP_STATION_REDIR0_ADDR \ + (WF_PLE_TOP_BASE + 0x480) /* 0480 */ +#define WF_PLE_TOP_TWT_STA_MAP0_ADDR \ + (WF_PLE_TOP_BASE + 0x4c0) /* 04C0 */ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY0_ADDR \ + (WF_PLE_TOP_BASE + 0x500) /* 0500 */ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY0_ADDR \ + (WF_PLE_TOP_BASE + 0x540) /* 0540 */ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY0_ADDR \ + (WF_PLE_TOP_BASE + 0x580) /* 0580 */ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY0_ADDR \ + (WF_PLE_TOP_BASE + 0x5c0) /* 05C0 */ +#define WF_PLE_TOP_DRR_TABLE_WDATA4_ADDR \ + (WF_PLE_TOP_BASE + 0x680) /* 0680 */ +#define WF_PLE_TOP_DRR_TABLE_WDATA5_ADDR \ + (WF_PLE_TOP_BASE + 0x684) /* 0684 */ +#define WF_PLE_TOP_DRR_TABLE_WDATA6_ADDR \ + (WF_PLE_TOP_BASE + 0x688) /* 0688 */ +#define WF_PLE_TOP_DRR_TABLE_WDATA7_ADDR \ + (WF_PLE_TOP_BASE + 0x68c) /* 068C */ +#define WF_PLE_TOP_DRR_TABLE_RDATA4_ADDR \ + (WF_PLE_TOP_BASE + 0x690) /* 0690 */ +#define WF_PLE_TOP_DRR_TABLE_RDATA5_ADDR \ + (WF_PLE_TOP_BASE + 0x694) /* 0694 */ +#define WF_PLE_TOP_DRR_TABLE_RDATA6_ADDR \ + (WF_PLE_TOP_BASE + 0x698) /* 0698 */ +#define WF_PLE_TOP_DRR_TABLE_RDATA7_ADDR \ + (WF_PLE_TOP_BASE + 0x69c) /* 069C */ +#define WF_PLE_TOP_TWT_STA_TABLE0_ADDR \ + (WF_PLE_TOP_BASE + 0x6a0) /* 06A0 */ +#define WF_PLE_TOP_TWT_STA_TABLE1_ADDR \ + (WF_PLE_TOP_BASE + 0x6a4) /* 06A4 */ +#define WF_PLE_TOP_TWT_STA_TABLE2_ADDR \ + (WF_PLE_TOP_BASE + 0x6a8) /* 06A8 */ +#define WF_PLE_TOP_TWT_STA_TABLE3_ADDR \ + (WF_PLE_TOP_BASE + 0x6ac) /* 06AC */ +#define WF_PLE_TOP_TWT_SW_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x6b0) /* 06B0 */ +#define WF_PLE_TOP_TWT_DBG_ADDR (WF_PLE_TOP_BASE + 0x6b4) /* 06B4 */ +#define WF_PLE_TOP_TWT_HW_SRCHCMD_FULL_ADDR \ + (WF_PLE_TOP_BASE + 0x6b8) /* 06B8 */ +#define WF_PLE_TOP_AMSDU_GC_ADDR \ + (WF_PLE_TOP_BASE + 0x1000) /* 1000 */ +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_ADDR \ + (WF_PLE_TOP_BASE + 0x1004) /* 1004 */ +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_1_ADDR \ + (WF_PLE_TOP_BASE + 0x1008) /* 1008 */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_ADDR \ + (WF_PLE_TOP_BASE + 0x1028) /* 1028 */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_ADDR \ + (WF_PLE_TOP_BASE + 0x102C) /* 102C */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_ADDR \ + (WF_PLE_TOP_BASE + 0x10d0) /* 10D0 */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_ADDR \ + (WF_PLE_TOP_BASE + 0x10d4) /* 10D4 */ +#define WF_PLE_TOP_AMSDU_PACK_1_MSDU_CNT_ADDR \ + (WF_PLE_TOP_BASE + 0x10e0) /* 10E0 */ +#define WF_PLE_TOP_AMSDU_PACK_2_MSDU_CNT_ADDR \ + (WF_PLE_TOP_BASE + 0x10e4) /* 10E4 */ +#define WF_PLE_TOP_AMSDU_PACK_3_MSDU_CNT_ADDR \ + (WF_PLE_TOP_BASE + 0x10e8) /* 10E8 */ +#define WF_PLE_TOP_AMSDU_PACK_4_MSDU_CNT_ADDR \ + (WF_PLE_TOP_BASE + 0x10ec) /* 10EC */ +#define WF_PLE_TOP_AMSDU_PACK_5_MSDU_CNT_ADDR \ + (WF_PLE_TOP_BASE + 0x10f0) /* 10F0 */ +#define WF_PLE_TOP_AMSDU_PACK_6_MSDU_CNT_ADDR \ + (WF_PLE_TOP_BASE + 0x10f4) /* 10F4 */ +#define WF_PLE_TOP_AMSDU_PACK_7_MSDU_CNT_ADDR \ + (WF_PLE_TOP_BASE + 0x10f8) /* 10F8 */ +#define WF_PLE_TOP_AMSDU_PACK_8_MSDU_CNT_ADDR \ + (WF_PLE_TOP_BASE + 0x10fc) /* 10FC */ +#define WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY0_ADDR \ + (WF_PLE_TOP_BASE + 0x1100) /* 1100 */ +#define WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY0_ADDR \ + (WF_PLE_TOP_BASE + 0x1140) /* 1140 */ +#define WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY0_ADDR \ + (WF_PLE_TOP_BASE + 0x1180) /* 1180 */ +#define WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY0_ADDR \ + (WF_PLE_TOP_BASE + 0x11C0) /* 11C0 */ +#define WF_PLE_TOP_CFG_DBDC_CTRL0_ADDR \ + (WF_PLE_TOP_BASE + 0x2008) /* 2008 */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR \ + (WF_PLE_TOP_BASE + 0x2480) /* 2480 */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_ADDR \ + (WF_PLE_TOP_BASE + 0x2484) /* 2484 */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_2_ADDR \ + (WF_PLE_TOP_BASE + 0x2488) /* 2488 */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_3_ADDR \ + (WF_PLE_TOP_BASE + 0x248c) /* 248C */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_4_ADDR \ + (WF_PLE_TOP_BASE + 0x2490) /* 2490 */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_ADDR \ + (WF_PLE_TOP_BASE + 0x2494) /* 2494 */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_6_ADDR \ + (WF_PLE_TOP_BASE + 0x2498) /* 2498 */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_ADDR \ + (WF_PLE_TOP_BASE + 0x25c0) /* 25C0 */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_ADDR \ + (WF_PLE_TOP_BASE + 0x25c4) /* 25C4 */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_2_ADDR \ + (WF_PLE_TOP_BASE + 0x25c8) /* 25C8 */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_3_ADDR \ + (WF_PLE_TOP_BASE + 0x25cc) /* 25CC */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR \ + (WF_PLE_TOP_BASE + 0x25e0) /* 25E0 */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_ADDR \ + (WF_PLE_TOP_BASE + 0x25e4) /* 25E4 */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_2_ADDR \ + (WF_PLE_TOP_BASE + 0x25e8) /* 25E8 */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_3_ADDR \ + (WF_PLE_TOP_BASE + 0x25ec) /* 25EC */ +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_ADDR \ + (WF_PLE_TOP_BASE + 0x3004) /* 3004 */ +#define WF_PLE_TOP_SYSRAM_MBIST_DEBUG_ADDR \ + (WF_PLE_TOP_BASE + 0x3008) /* 3008 */ +#define WF_PLE_TOP_SYSRAM_MBIST_MODE_ADDR \ + (WF_PLE_TOP_BASE + 0x300C) /* 300C */ +#define WF_PLE_TOP_SYSRAM_MBIST_HOLDB_ADDR \ + (WF_PLE_TOP_BASE + 0x3010) /* 3010 */ +#define WF_PLE_TOP_SYSRAM_MBIST_DONE_ADDR \ + (WF_PLE_TOP_BASE + 0x3014) /* 3014 */ +#define WF_PLE_TOP_SYSRAM_MBIST_FAIL_ADDR \ + (WF_PLE_TOP_BASE + 0x3018) /* 3018 */ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_TEST_ADDR \ + (WF_PLE_TOP_BASE + 0x301C) /* 301C */ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_INV_ADDR \ + (WF_PLE_TOP_BASE + 0x3020) /* 3020 */ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_W_ADDR \ + (WF_PLE_TOP_BASE + 0x3024) /* 3024 */ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_R_ADDR \ + (WF_PLE_TOP_BASE + 0x3028) /* 3028 */ +#define WF_PLE_TOP_SYSRAM_AWT_HDEN_ADDR \ + (WF_PLE_TOP_BASE + 0x302C) /* 302C */ +#define WF_PLE_TOP_SYSRAM_DBG_SEL_ADDR \ + (WF_PLE_TOP_BASE + 0x3030) /* 3030 */ +#define WF_PLE_TOP_SYSRAM_DELSEL_ADDR \ + (WF_PLE_TOP_BASE + 0x3070) /* 3070 */ +#define WF_PLE_TOP_SYSRAM_DELSEL_1_ADDR \ + (WF_PLE_TOP_BASE + 0x3074) /* 3074 */ +#define WF_PLE_TOP_SYSRAM_DELSEL_2_ADDR \ + (WF_PLE_TOP_BASE + 0x3078) /* 3078 */ +#define WF_PLE_TOP_SYSRAM_DELSEL_3_ADDR \ + (WF_PLE_TOP_BASE + 0x307C) /* 307C */ +#define WF_PLE_TOP_SYSRAM_OUTRAN_ERR_FLAG_ADDR \ + (WF_PLE_TOP_BASE + 0x3080) /* 3080 */ + +/* +* ---GC (0x820C0000 + 0x00)--- +* ALL_RESET[0] - (RW) Resets PLE logic and register +* LOGIC_RESET[1] - (RW) Resets PLE logic circuit +* INIT_DONE[2] - (RO) PLE control SRAM initialization +indicator +* UMAC_CFG_LOGIC_RESET[3] - (RW) Resets PF/MDP/SEC/UWTBL logic circuit +* RESERVED4[15..4] - (RO) Reserved bits +* SRAM_MBIST_G1_RESET[16] - (RW) Reset control of group 1 SRAM MBIST +* SRAM_MBIST_G2_RESET[17] - (RW) Reset control of group 2 SRAM MBIST +* DIS_PLE_DYN_CKG[18] - (RW) Disable control of wf_ple_top dynamic +* clock gating function +* RESERVED19[31..19] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_GC_DIS_PLE_DYN_CKG_ADDR WF_PLE_TOP_GC_ADDR +#define WF_PLE_TOP_GC_DIS_PLE_DYN_CKG_MASK \ + 0x00040000 /* DIS_PLE_DYN_CKG[18] */ +#define WF_PLE_TOP_GC_DIS_PLE_DYN_CKG_SHFT 18 +#define WF_PLE_TOP_GC_SRAM_MBIST_G2_RESET_ADDR WF_PLE_TOP_GC_ADDR +#define WF_PLE_TOP_GC_SRAM_MBIST_G2_RESET_MASK \ + 0x00020000 /* SRAM_MBIST_G2_RESET[17] */ +#define WF_PLE_TOP_GC_SRAM_MBIST_G2_RESET_SHFT 17 +#define WF_PLE_TOP_GC_SRAM_MBIST_G1_RESET_ADDR WF_PLE_TOP_GC_ADDR +#define WF_PLE_TOP_GC_SRAM_MBIST_G1_RESET_MASK \ + 0x00010000 /* SRAM_MBIST_G1_RESET[16] */ +#define WF_PLE_TOP_GC_SRAM_MBIST_G1_RESET_SHFT 16 +#define WF_PLE_TOP_GC_UMAC_CFG_LOGIC_RESET_ADDR WF_PLE_TOP_GC_ADDR +#define WF_PLE_TOP_GC_UMAC_CFG_LOGIC_RESET_MASK \ + 0x00000008 /* UMAC_CFG_LOGIC_RESET[3] */ +#define WF_PLE_TOP_GC_UMAC_CFG_LOGIC_RESET_SHFT 3 +#define WF_PLE_TOP_GC_INIT_DONE_ADDR WF_PLE_TOP_GC_ADDR +#define WF_PLE_TOP_GC_INIT_DONE_MASK 0x00000004 /* INIT_DONE[2] */ +#define WF_PLE_TOP_GC_INIT_DONE_SHFT 2 +#define WF_PLE_TOP_GC_LOGIC_RESET_ADDR WF_PLE_TOP_GC_ADDR +#define WF_PLE_TOP_GC_LOGIC_RESET_MASK 0x00000002 /* LOGIC_RESET[1] */ +#define WF_PLE_TOP_GC_LOGIC_RESET_SHFT 1 +#define WF_PLE_TOP_GC_ALL_RESET_ADDR WF_PLE_TOP_GC_ADDR +#define WF_PLE_TOP_GC_ALL_RESET_MASK 0x00000001 /* ALL_RESET[0] */ +#define WF_PLE_TOP_GC_ALL_RESET_SHFT 0 + +/* +* ---PBUF_CTRL (0x820C0000 + 0x14)--- +* TOTAL_PAGE_NUM[11..0] - (RW) Total page number +* Set the total page before release PLE logic +* reset, and must not be changed after release logic reset. +* RESERVED12[16..12] - (RO) Reserved bits +* PBUF_OFFSET[25..17] - (RW) Packet buffer offset +* Set up the buffer offset before releasing +* PLE logic reset; it should not be changed after logic reset is +released. +* RESERVED26[30..26] - (RO) Reserved bits +* PAGE_SIZE_CFG[31] - (RW) Configures page size +* Set up the page size before releasing PLE +* logic reset; it should not be changed after logic reset is released. +*/ +#define WF_PLE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_ADDR \ + WF_PLE_TOP_PBUF_CTRL_ADDR +#define WF_PLE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_MASK \ + 0x80000000 /* PAGE_SIZE_CFG[31] */ +#define WF_PLE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_SHFT 31 +#define WF_PLE_TOP_PBUF_CTRL_PBUF_OFFSET_ADDR \ + WF_PLE_TOP_PBUF_CTRL_ADDR +#define WF_PLE_TOP_PBUF_CTRL_PBUF_OFFSET_MASK \ + 0x03FE0000 /* PBUF_OFFSET[25..17] */ +#define WF_PLE_TOP_PBUF_CTRL_PBUF_OFFSET_SHFT 17 +#define WF_PLE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_ADDR \ + WF_PLE_TOP_PBUF_CTRL_ADDR +#define WF_PLE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_MASK \ + 0x00000FFF /* TOTAL_PAGE_NUM[11..0] */ +#define WF_PLE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_SHFT 0 + +/* +* ---TIMEOUT_CTRL (0x820C0000 + 0x1c)--- +* RESERVED0[7..0] - (RO) Reserved bits +* HOST_REPORT_TO_CTRL[15..8] - (RW) HOST report timeout control +register +* APB_WD_TO_CTRL[23..16] - (RW) APB pready watch dog timeout control +register +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TIMEOUT_CTRL_APB_WD_TO_CTRL_ADDR \ + WF_PLE_TOP_TIMEOUT_CTRL_ADDR +#define WF_PLE_TOP_TIMEOUT_CTRL_APB_WD_TO_CTRL_MASK \ + 0x00FF0000 /* APB_WD_TO_CTRL[23..16] */ +#define WF_PLE_TOP_TIMEOUT_CTRL_APB_WD_TO_CTRL_SHFT 16 +#define WF_PLE_TOP_TIMEOUT_CTRL_HOST_REPORT_TO_CTRL_ADDR \ + WF_PLE_TOP_TIMEOUT_CTRL_ADDR +#define WF_PLE_TOP_TIMEOUT_CTRL_HOST_REPORT_TO_CTRL_MASK \ + 0x0000FF00 /* HOST_REPORT_TO_CTRL[15..8] */ +#define WF_PLE_TOP_TIMEOUT_CTRL_HOST_REPORT_TO_CTRL_SHFT 8 + +/* +* ---INT_N9_EN_MASK (0x820C0000 + 0x20)--- +* EN_CPU_Q0_NE[0] - (RW) Enable control of interrupt for CPU +* queue 0 not empty +* EN_CPU_Q1_NE[1] - (RW) Enable control of interrupt for CPU +* queue 1 not empty +* EN_CPU_Q2_NE[2] - (RW) Enable control of interrupt for CPU +* queue 2 not empty +* EN_CPU_Q3_NE[3] - (RW) Enable control of interrupt for CPU +* queue 3 not empty +* RESERVED4[15..4] - (RO) Reserved bits +* EN_TOGGLE_INT[16] - (RW) Enable control of interrupt for data +* toggle of N9 toggle register (0xf0) +* RESERVED17[17] - (RO) Reserved bits +* EN_UMAC_SYSRAM_OUTRAN_ERROR_INT[18] - (RW) Enable control of +* interrupt for +* UMAC SYSRAM out range error +* RESERVED19[19] - (RO) Reserved bits +* EN_AC_NONEMPTY_INT[20] - (RW) Enable control of AC queue empty fail +interrupt +* EN_AC_EMPTY_INT[21] - (RW) Enable control of AC queue empty raise +interrupt +* EN_AC_ENQ_LMAC_INT[22] - (RW) Enable control of AC enqueue interrupt +* RESERVED23[23] - (RO) Reserved bits +* EN_DBDC0_NONEMPTY_INT[24] - (RW) Enable control of DBDC0 queue empty +fail +interrupt +* EN_DBDC0_EMPTY_INT[25] - (RW) Enable control of DBDC0 queue empty +* raise interrupt +* EN_DBDC0_ENQ_LMAC_INT[26] - (RW) Enable control of DBDC0 enqueue +interrupt +* RESERVED27[27] - (RO) Reserved bits +* EN_DBDC1_NONEMPTY_INT[28] - (RW) Enable control of DBDC1 queue empty +fail +interrupt +* EN_DBDC1_EMPTY_INT[29] - (RW) Enable control of DBDC1 queue empty +* raise interrupt +* EN_DBDC1_ENQ_LMAC_INT[30] - (RW) Enable control of DBDC1 enqueue +interrupt +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_ENQ_LMAC_INT_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_ENQ_LMAC_INT_MASK \ + 0x40000000 /* EN_DBDC1_ENQ_LMAC_INT[30] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_ENQ_LMAC_INT_SHFT 30 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_EMPTY_INT_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_EMPTY_INT_MASK \ + 0x20000000 /* EN_DBDC1_EMPTY_INT[29] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_EMPTY_INT_SHFT 29 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_NONEMPTY_INT_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_NONEMPTY_INT_MASK \ + 0x10000000 /* EN_DBDC1_NONEMPTY_INT[28] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC1_NONEMPTY_INT_SHFT 28 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_ENQ_LMAC_INT_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_ENQ_LMAC_INT_MASK \ + 0x04000000 /* EN_DBDC0_ENQ_LMAC_INT[26] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_ENQ_LMAC_INT_SHFT 26 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_EMPTY_INT_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_EMPTY_INT_MASK \ + 0x02000000 /* EN_DBDC0_EMPTY_INT[25] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_EMPTY_INT_SHFT 25 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_NONEMPTY_INT_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_NONEMPTY_INT_MASK \ + 0x01000000 /* EN_DBDC0_NONEMPTY_INT[24] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_DBDC0_NONEMPTY_INT_SHFT 24 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_ENQ_LMAC_INT_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_ENQ_LMAC_INT_MASK \ + 0x00400000 /* EN_AC_ENQ_LMAC_INT[22] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_ENQ_LMAC_INT_SHFT 22 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_EMPTY_INT_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_EMPTY_INT_MASK \ + 0x00200000 /* EN_AC_EMPTY_INT[21] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_EMPTY_INT_SHFT 21 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_NONEMPTY_INT_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_NONEMPTY_INT_MASK \ + 0x00100000 /* EN_AC_NONEMPTY_INT[20] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_AC_NONEMPTY_INT_SHFT 20 +#define \ +WF_PLE_TOP_INT_N9_EN_MASK_EN_UMAC_SYSRAM_OUTRAN_ERROR_INT_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define \ +WF_PLE_TOP_INT_N9_EN_MASK_EN_UMAC_SYSRAM_OUTRAN_ERROR_INT_MASK \ + 0x00040000 /* EN_UMAC_SYSRAM_OUTRAN_ERROR_INT[18] */ +#define \ +WF_PLE_TOP_INT_N9_EN_MASK_EN_UMAC_SYSRAM_OUTRAN_ERROR_INT_SHFT \ + 18 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_TOGGLE_INT_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_TOGGLE_INT_MASK \ + 0x00010000 /* EN_TOGGLE_INT[16] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_TOGGLE_INT_SHFT 16 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q3_NE_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q3_NE_MASK \ + 0x00000008 /* EN_CPU_Q3_NE[3] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q3_NE_SHFT 3 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q2_NE_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q2_NE_MASK \ + 0x00000004 /* EN_CPU_Q2_NE[2] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q2_NE_SHFT 2 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q1_NE_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q1_NE_MASK \ + 0x00000002 /* EN_CPU_Q1_NE[1] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q1_NE_SHFT 1 +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q0_NE_ADDR \ + WF_PLE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q0_NE_MASK \ + 0x00000001 /* EN_CPU_Q0_NE[0] */ +#define WF_PLE_TOP_INT_N9_EN_MASK_EN_CPU_Q0_NE_SHFT 0 + +/* +* ---INT_N9_STS (0x820C0000 + 0x24)--- +* CPU_Q0_NE[0] - (W1C) CPU queue 0 not empty interrupt status +* CPU_Q1_NE[1] - (W1C) CPU queue 1 not empty interrupt status +* CPU_Q2_NE[2] - (W1C) CPU queue 2 not empty interrupt status +* CPU_Q3_NE[3] - (W1C) CPU queue 3 not empty interrupt status +* RESERVED4[12..4] - (RO) Reserved bits +* ERROR_INT[13] - (RO) Error condition interrupt status, define +* by 0x28 +* ERROR_INT_1[14] - (RO) Error condition interrupt status 1, +* define by 0xd8 +* AMSDU_ERROR_INT[15] - (RO) HW AMSDU Error condition interrupt +* status, define by 0x1028 +* DATA_TOGGLE[16] - (W1C) Interrupt status of data toggle of N9 +* toggle register (0xf0) +* RESERVED17[17] - (RO) Reserved bits +* UMAC_SYSRAM_OUTRAN_ERROR_INT[18] - (W1C) Interrupt status of UMAC +* SYSRAM out +* range error +* RESERVED19[19] - (RO) Reserved bits +* AC_NONEMPTY_INT[20] - (W1C) AC queue empty fail interrupt status +* AC_EMPTY_INT[21] - (W1C) AC queue empty raise interrupt status +* AC_ENQ_LMAC_INT[22] - (W1C) AC enqueue interrupt status +* RESERVED23[23] - (RO) Reserved bits +* DBDC0_NONEMPTY_INT[24] - (W1C) DBDC0 queue empty fail interrupt +status +* DBDC0_EMPTY_INT[25] - (W1C) DBDC0 queue empty raise interrupt +status +* DBDC0_ENQ_LMAC_INT[26] - (W1C) DBDC0 enqueue interrupt status +* RESERVED27[27] - (RO) Reserved bits +* DBDC1_NONEMPTY_INT[28] - (W1C) DBDC1 queue empty fail interrupt +status +* DBDC1_EMPTY_INT[29] - (W1C) DBDC1 queue empty raise interrupt +status +* DBDC1_ENQ_LMAC_INT[30] - (W1C) DBDC1 enqueue interrupt status +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_INT_N9_STS_DBDC1_ENQ_LMAC_INT_ADDR \ + WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_DBDC1_ENQ_LMAC_INT_MASK \ + 0x40000000 /* DBDC1_ENQ_LMAC_INT[30] */ +#define WF_PLE_TOP_INT_N9_STS_DBDC1_ENQ_LMAC_INT_SHFT 30 +#define WF_PLE_TOP_INT_N9_STS_DBDC1_EMPTY_INT_ADDR \ + WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_DBDC1_EMPTY_INT_MASK \ + 0x20000000 /* DBDC1_EMPTY_INT[29] */ +#define WF_PLE_TOP_INT_N9_STS_DBDC1_EMPTY_INT_SHFT 29 +#define WF_PLE_TOP_INT_N9_STS_DBDC1_NONEMPTY_INT_ADDR \ + WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_DBDC1_NONEMPTY_INT_MASK \ + 0x10000000 /* DBDC1_NONEMPTY_INT[28] */ +#define WF_PLE_TOP_INT_N9_STS_DBDC1_NONEMPTY_INT_SHFT 28 +#define WF_PLE_TOP_INT_N9_STS_DBDC0_ENQ_LMAC_INT_ADDR \ + WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_DBDC0_ENQ_LMAC_INT_MASK \ + 0x04000000 /* DBDC0_ENQ_LMAC_INT[26] */ +#define WF_PLE_TOP_INT_N9_STS_DBDC0_ENQ_LMAC_INT_SHFT 26 +#define WF_PLE_TOP_INT_N9_STS_DBDC0_EMPTY_INT_ADDR \ + WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_DBDC0_EMPTY_INT_MASK \ + 0x02000000 /* DBDC0_EMPTY_INT[25] */ +#define WF_PLE_TOP_INT_N9_STS_DBDC0_EMPTY_INT_SHFT 25 +#define WF_PLE_TOP_INT_N9_STS_DBDC0_NONEMPTY_INT_ADDR \ + WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_DBDC0_NONEMPTY_INT_MASK \ + 0x01000000 /* DBDC0_NONEMPTY_INT[24] */ +#define WF_PLE_TOP_INT_N9_STS_DBDC0_NONEMPTY_INT_SHFT 24 +#define WF_PLE_TOP_INT_N9_STS_AC_ENQ_LMAC_INT_ADDR \ + WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_AC_ENQ_LMAC_INT_MASK \ + 0x00400000 /* AC_ENQ_LMAC_INT[22] */ +#define WF_PLE_TOP_INT_N9_STS_AC_ENQ_LMAC_INT_SHFT 22 +#define WF_PLE_TOP_INT_N9_STS_AC_EMPTY_INT_ADDR \ + WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_AC_EMPTY_INT_MASK \ + 0x00200000 /* AC_EMPTY_INT[21] */ +#define WF_PLE_TOP_INT_N9_STS_AC_EMPTY_INT_SHFT 21 +#define WF_PLE_TOP_INT_N9_STS_AC_NONEMPTY_INT_ADDR \ + WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_AC_NONEMPTY_INT_MASK \ + 0x00100000 /* AC_NONEMPTY_INT[20] */ +#define WF_PLE_TOP_INT_N9_STS_AC_NONEMPTY_INT_SHFT 20 +#define WF_PLE_TOP_INT_N9_STS_UMAC_SYSRAM_OUTRAN_ERROR_INT_ADDR \ + WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_UMAC_SYSRAM_OUTRAN_ERROR_INT_MASK \ + 0x00040000 /* UMAC_SYSRAM_OUTRAN_ERROR_INT[18] */ +#define WF_PLE_TOP_INT_N9_STS_UMAC_SYSRAM_OUTRAN_ERROR_INT_SHFT 18 +#define WF_PLE_TOP_INT_N9_STS_DATA_TOGGLE_ADDR \ + WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_DATA_TOGGLE_MASK \ + 0x00010000 /* DATA_TOGGLE[16] */ +#define WF_PLE_TOP_INT_N9_STS_DATA_TOGGLE_SHFT 16 +#define WF_PLE_TOP_INT_N9_STS_AMSDU_ERROR_INT_ADDR \ + WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_AMSDU_ERROR_INT_MASK \ + 0x00008000 /* AMSDU_ERROR_INT[15] */ +#define WF_PLE_TOP_INT_N9_STS_AMSDU_ERROR_INT_SHFT 15 +#define WF_PLE_TOP_INT_N9_STS_ERROR_INT_1_ADDR \ + WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_ERROR_INT_1_MASK \ + 0x00004000 /* ERROR_INT_1[14] */ +#define WF_PLE_TOP_INT_N9_STS_ERROR_INT_1_SHFT 14 +#define WF_PLE_TOP_INT_N9_STS_ERROR_INT_ADDR \ + WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_ERROR_INT_MASK \ + 0x00002000 /* ERROR_INT[13] */ +#define WF_PLE_TOP_INT_N9_STS_ERROR_INT_SHFT 13 +#define WF_PLE_TOP_INT_N9_STS_CPU_Q3_NE_ADDR \ + WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_CPU_Q3_NE_MASK \ + 0x00000008 /* CPU_Q3_NE[3] */ +#define WF_PLE_TOP_INT_N9_STS_CPU_Q3_NE_SHFT 3 +#define WF_PLE_TOP_INT_N9_STS_CPU_Q2_NE_ADDR \ + WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_CPU_Q2_NE_MASK \ + 0x00000004 /* CPU_Q2_NE[2] */ +#define WF_PLE_TOP_INT_N9_STS_CPU_Q2_NE_SHFT 2 +#define WF_PLE_TOP_INT_N9_STS_CPU_Q1_NE_ADDR \ + WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_CPU_Q1_NE_MASK \ + 0x00000002 /* CPU_Q1_NE[1] */ +#define WF_PLE_TOP_INT_N9_STS_CPU_Q1_NE_SHFT 1 +#define WF_PLE_TOP_INT_N9_STS_CPU_Q0_NE_ADDR \ + WF_PLE_TOP_INT_N9_STS_ADDR +#define WF_PLE_TOP_INT_N9_STS_CPU_Q0_NE_MASK \ + 0x00000001 /* CPU_Q0_NE[0] */ +#define WF_PLE_TOP_INT_N9_STS_CPU_Q0_NE_SHFT 0 + +/* +* ---INT_N9_ERR_STS (0x820C0000 + 0x28)--- +* Q_CMD_ERR_P0[0] - (W1C) Queue command error interrupt status of +* port 0. Avoid unclear error flag, please clear flag when logic +reset. +* Q_CMD_ERR_P1[1] - (W1C) Queue command error interrupt status of +* port 1. Avoid unclear error flag, please clear flag when logic +reset. +* Q_CMD_ERR_P2[2] - (W1C) Queue command error interrupt status of +* port 2. Avoid unclear error flag, please clear flag when logic +reset. +* PAGE_UDF_P0[3] - (W1C) Page underflow interrupt status of port +* 0. Avoid unclear error flag, please clear flag when logic reset. +* PAGE_UDF_P1[4] - (W1C) Page underflow interrupt status of port +* 1. Avoid unclear error flag, please clear flag when logic reset. +* PAGE_UDF_P2[5] - (W1C) Page underflow interrupt status of port +* 2. Avoid unclear error flag, please clear flag when logic reset. +* DOUBLE_RLS_ERR[6] - (W1C) Double release error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* MDP_D_OPER_ERR[7] - (W1C) MDP data operation error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* MDP_HANG_ERR[8] - (W1C) MDP FSM Hang error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* RESERVED9[9] - (RO) Reserved bits +* DATA_OPER_ERR_P0[10] - (W1C) Data operation error of port 0. Avoid +* unclear error flag, please clear flag when logic reset. +* DATA_OPER_ERR_P1[11] - (W1C) Data operation error of port 1. Avoid +* unclear error flag, please clear flag when logic reset. +* DATA_OPER_ERR_P2[12] - (W1C) Data operation error of port 2. Avoid +* unclear error flag, please clear flag when logic reset. +* FL_HANG_ERR[13] - (W1C) Frame link FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* PL_HANG_ERR[14] - (W1C) Page link FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* HIF_HANG_ERR[15] - (W1C) HIF port FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* CPU_HANG_ERR[16] - (W1C) CPU port FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* LMAC_HANG_ERR[17] - (W1C) LMAC port FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* FREE_HEAD_TAIL_ERR[18] - (W1C) Free head/tail error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* QSTRUCT_ERR[19] - (W1C) Queue struct data error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* BN0_MACTX_HANG_ERR[20] - (W1C) BN0 MACTX Ctrl FSM Hang error +* interrupt. Avoid unclear error flag, please clear flag when logic +reset. +* BN1_MACTX_HANG_ERR[21] - (W1C) BN1 MACTX Ctrl FSM Hang error +* interrupt. Avoid unclear error flag, please clear flag when logic +reset. +* BN0_TXCMD_HANG_ERR[22] - (W1C) BN0 TXCMD Ctrl FSM Hang error +* interrupt. Avoid unclear error flag, please clear flag when logic +reset. +* BN1_TXCMD_HANG_ERR[23] - (W1C) BN1 TXCMD Ctrl FSM Hang error +* interrupt. Avoid unclear error flag, please clear flag when logic +reset. +* DRR_SRCH_DBDC0_ERR[24] - (W1C) DRR DBDC0 sta serach error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* DRR_SRCH_DBDC1_ERR[25] - (W1C) DRR DBDC1 sta serach error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* DRR_FL_ERR[26] - (W1C) DRR forward link access error +* interrupt. Avoid unclear error flag, please clear flag when logic +reset. +* DRR_BL_ERR[27] - (W1C) DRR backward link access error +* interrupt. Avoid unclear error flag, please clear flag when logic +reset. +* DRR_RL_ERR[28] - (W1C) DRR relay link access error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* DRR_CHRG_STA_ERR[29] - (W1C) DRR charge wlanid error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* DRR_STA_WLANID_ERR[30] - (W1C) DRR wlanid error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* DRR_STA_WMMID_ERR[31] - (W1C) DRR wmmid error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +*/ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_STA_WMMID_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_STA_WMMID_ERR_MASK \ + 0x80000000 /* DRR_STA_WMMID_ERR[31] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_STA_WMMID_ERR_SHFT 31 +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_STA_WLANID_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_STA_WLANID_ERR_MASK \ + 0x40000000 /* DRR_STA_WLANID_ERR[30] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_STA_WLANID_ERR_SHFT 30 +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_CHRG_STA_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_CHRG_STA_ERR_MASK \ + 0x20000000 /* DRR_CHRG_STA_ERR[29] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_CHRG_STA_ERR_SHFT 29 +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_RL_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_RL_ERR_MASK \ + 0x10000000 /* DRR_RL_ERR[28] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_RL_ERR_SHFT 28 +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_BL_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_BL_ERR_MASK \ + 0x08000000 /* DRR_BL_ERR[27] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_BL_ERR_SHFT 27 +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_FL_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_FL_ERR_MASK \ + 0x04000000 /* DRR_FL_ERR[26] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_FL_ERR_SHFT 26 +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_SRCH_DBDC1_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_SRCH_DBDC1_ERR_MASK \ + 0x02000000 /* DRR_SRCH_DBDC1_ERR[25] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_SRCH_DBDC1_ERR_SHFT 25 +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_SRCH_DBDC0_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_SRCH_DBDC0_ERR_MASK \ + 0x01000000 /* DRR_SRCH_DBDC0_ERR[24] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DRR_SRCH_DBDC0_ERR_SHFT 24 +#define WF_PLE_TOP_INT_N9_ERR_STS_BN1_TXCMD_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_BN1_TXCMD_HANG_ERR_MASK \ + 0x00800000 /* BN1_TXCMD_HANG_ERR[23] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_BN1_TXCMD_HANG_ERR_SHFT 23 +#define WF_PLE_TOP_INT_N9_ERR_STS_BN0_TXCMD_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_BN0_TXCMD_HANG_ERR_MASK \ + 0x00400000 /* BN0_TXCMD_HANG_ERR[22] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_BN0_TXCMD_HANG_ERR_SHFT 22 +#define WF_PLE_TOP_INT_N9_ERR_STS_BN1_MACTX_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_BN1_MACTX_HANG_ERR_MASK \ + 0x00200000 /* BN1_MACTX_HANG_ERR[21] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_BN1_MACTX_HANG_ERR_SHFT 21 +#define WF_PLE_TOP_INT_N9_ERR_STS_BN0_MACTX_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_BN0_MACTX_HANG_ERR_MASK \ + 0x00100000 /* BN0_MACTX_HANG_ERR[20] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_BN0_MACTX_HANG_ERR_SHFT 20 +#define WF_PLE_TOP_INT_N9_ERR_STS_QSTRUCT_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_QSTRUCT_ERR_MASK \ + 0x00080000 /* QSTRUCT_ERR[19] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_QSTRUCT_ERR_SHFT 19 +#define WF_PLE_TOP_INT_N9_ERR_STS_FREE_HEAD_TAIL_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_FREE_HEAD_TAIL_ERR_MASK \ + 0x00040000 /* FREE_HEAD_TAIL_ERR[18] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_FREE_HEAD_TAIL_ERR_SHFT 18 +#define WF_PLE_TOP_INT_N9_ERR_STS_LMAC_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_LMAC_HANG_ERR_MASK \ + 0x00020000 /* LMAC_HANG_ERR[17] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_LMAC_HANG_ERR_SHFT 17 +#define WF_PLE_TOP_INT_N9_ERR_STS_CPU_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_CPU_HANG_ERR_MASK \ + 0x00010000 /* CPU_HANG_ERR[16] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_CPU_HANG_ERR_SHFT 16 +#define WF_PLE_TOP_INT_N9_ERR_STS_HIF_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_HIF_HANG_ERR_MASK \ + 0x00008000 /* HIF_HANG_ERR[15] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_HIF_HANG_ERR_SHFT 15 +#define WF_PLE_TOP_INT_N9_ERR_STS_PL_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_PL_HANG_ERR_MASK \ + 0x00004000 /* PL_HANG_ERR[14] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_PL_HANG_ERR_SHFT 14 +#define WF_PLE_TOP_INT_N9_ERR_STS_FL_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_FL_HANG_ERR_MASK \ + 0x00002000 /* FL_HANG_ERR[13] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_FL_HANG_ERR_SHFT 13 +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P2_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P2_MASK \ + 0x00001000 /* DATA_OPER_ERR_P2[12] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P2_SHFT 12 +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P1_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P1_MASK \ + 0x00000800 /* DATA_OPER_ERR_P1[11] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P1_SHFT 11 +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P0_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P0_MASK \ + 0x00000400 /* DATA_OPER_ERR_P0[10] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P0_SHFT 10 +#define WF_PLE_TOP_INT_N9_ERR_STS_MDP_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_MDP_HANG_ERR_MASK \ + 0x00000100 /* MDP_HANG_ERR[8] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_MDP_HANG_ERR_SHFT 8 +#define WF_PLE_TOP_INT_N9_ERR_STS_MDP_D_OPER_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_MDP_D_OPER_ERR_MASK \ + 0x00000080 /* MDP_D_OPER_ERR[7] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_MDP_D_OPER_ERR_SHFT 7 +#define WF_PLE_TOP_INT_N9_ERR_STS_DOUBLE_RLS_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_DOUBLE_RLS_ERR_MASK \ + 0x00000040 /* DOUBLE_RLS_ERR[6] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_DOUBLE_RLS_ERR_SHFT 6 +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P2_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P2_MASK \ + 0x00000020 /* PAGE_UDF_P2[5] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P2_SHFT 5 +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P1_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P1_MASK \ + 0x00000010 /* PAGE_UDF_P1[4] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P1_SHFT 4 +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P0_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P0_MASK \ + 0x00000008 /* PAGE_UDF_P0[3] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_PAGE_UDF_P0_SHFT 3 +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P2_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P2_MASK \ + 0x00000004 /* Q_CMD_ERR_P2[2] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P2_SHFT 2 +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P1_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P1_MASK \ + 0x00000002 /* Q_CMD_ERR_P1[1] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P1_SHFT 1 +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P0_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P0_MASK \ + 0x00000001 /* Q_CMD_ERR_P0[0] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P0_SHFT 0 + +/* +* ---INT_N9_ERR_MASK (0x820C0000 + 0x2C)--- +* EN_Q_CMD_ERR_P0[0] - (RW) Enables queue command error interrupt +* status of port 0 +* EN_Q_CMD_ERR_P1[1] - (RW) Enables queue command error interrupt +* status of port 1 +* EN_Q_CMD_ERR_P2[2] - (RW) Enables queue command error interrupt +* status of port 2 +* EN_PAGE_UDF_P0[3] - (RW) Enables page underflow interrupt status +* of port 0 +* EN_PAGE_UDF_P1[4] - (RW) Enables page underflow interrupt status +* of port 1 +* EN_PAGE_UDF_P2[5] - (RW) Enables page underflow interrupt status +* of port 2 +* EN_DOUBLE_RLS_ERR[6] - (RW) Enable double release error interrupt. +* EN_MDP_D_OPER_ERR[7] - (RW) Enable MDP data operation error +interrupt. +* EN_MDP_HANG_ERR[8] - (RW) Enable MDP FSM hang error interrupt. +* RESERVED9[9] - (RO) Reserved bits +* EN_DATA_OPER_ERR_P0[10] - (RW) Enables data operation error of port +0 +* EN_DATA_OPER_ERR_P1[11] - (RW) Enables data operation error of port +1 +* EN_DATA_OPER_ERR_P2[12] - (RW) Enables data operation error of port +2 +* EN_FL_HANG_ERR[13] - (RW) Enables frame link FSM hang error +interrupt +* EN_PL_HANG_ERR[14] - (RW) Enables page link FSM hang error +interrupt +* EN_HIF_HANG_ERR[15] - (RW) Enables HIF port FSM hang error +interrupt +* EN_CPU_HANG_ERR[16] - (RW) Enables CPU port FSM hang error +interrupt +* EN_LMAC_HANG_ERR[17] - (RW) Enables LMAC port FSM hang error +interrupt +* EN_FREE_HEAD_TAIL_ERR[18] - (RW) Enable free head/tail error +interrupt. +* EN_QSTRUCT_ERR[19] - (RW) Enable queue struct data error +interrupt. +* EN_BN0_MACTX_HANG_ERR[20] - (RW) Enable BN0 MACTX Ctrl FSM Hang +error +interrupt. +* EN_BN1_MACTX_HANG_ERR[21] - (RW) Enable BN1 MACTX Ctrl FSM Hang +error +interrupt. +* EN_BN0_TXCMD_HANG_ERR[22] - (RW) Enable BN0 TXCMD Ctrl FSM Hang +error +interrupt. +* EN_BN1_TXCMD_HANG_ERR[23] - (RW) Enable BN1 TXCMD Ctrl FSM Hang +error +interrupt. +* EN_DRR_SRCH_DBDC0_ERR[24] - (RW) Enable DRR DBDC0 sta search error +interrupt. +* EN_DRR_SRCH_DBDC1_ERR[25] - (RW) Enable DRR DBDC1 sta search error +interrupt. +* EN_DRR_FL_ERR[26] - (RW) Enable DRR forward link access error +interrupt. +* EN_DRR_BL_ERR[27] - (RW) Enable DRR backward link access error +interrupt. +* EN_DRR_RL_ERR[28] - (RW) Enable DRR relay link access error +interrupt. +* EN_DRR_CHRG_STA_ERR[29] - (RW) Enable DRR wlanid error when charge +interrupt. +* EN_DRR_STA_WLANID_ERR[30] - (RW) Enable DRR wlanid error when +add/remove +* sta interrupt. +* EN_DRR_STA_WMMID_ERR[31] - (RW) Enable DRR wmmid error when +add/remove +* sta interrupt. +*/ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_STA_WMMID_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_STA_WMMID_ERR_MASK \ + 0x80000000 /* EN_DRR_STA_WMMID_ERR[31] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_STA_WMMID_ERR_SHFT 31 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_STA_WLANID_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_STA_WLANID_ERR_MASK \ + 0x40000000 /* EN_DRR_STA_WLANID_ERR[30] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_STA_WLANID_ERR_SHFT 30 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_CHRG_STA_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_CHRG_STA_ERR_MASK \ + 0x20000000 /* EN_DRR_CHRG_STA_ERR[29] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_CHRG_STA_ERR_SHFT 29 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_RL_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_RL_ERR_MASK \ + 0x10000000 /* EN_DRR_RL_ERR[28] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_RL_ERR_SHFT 28 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_BL_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_BL_ERR_MASK \ + 0x08000000 /* EN_DRR_BL_ERR[27] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_BL_ERR_SHFT 27 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_FL_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_FL_ERR_MASK \ + 0x04000000 /* EN_DRR_FL_ERR[26] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_FL_ERR_SHFT 26 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_SRCH_DBDC1_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_SRCH_DBDC1_ERR_MASK \ + 0x02000000 /* EN_DRR_SRCH_DBDC1_ERR[25] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_SRCH_DBDC1_ERR_SHFT 25 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_SRCH_DBDC0_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_SRCH_DBDC0_ERR_MASK \ + 0x01000000 /* EN_DRR_SRCH_DBDC0_ERR[24] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DRR_SRCH_DBDC0_ERR_SHFT 24 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN1_TXCMD_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN1_TXCMD_HANG_ERR_MASK \ + 0x00800000 /* EN_BN1_TXCMD_HANG_ERR[23] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN1_TXCMD_HANG_ERR_SHFT 23 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN0_TXCMD_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN0_TXCMD_HANG_ERR_MASK \ + 0x00400000 /* EN_BN0_TXCMD_HANG_ERR[22] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN0_TXCMD_HANG_ERR_SHFT 22 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN1_MACTX_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN1_MACTX_HANG_ERR_MASK \ + 0x00200000 /* EN_BN1_MACTX_HANG_ERR[21] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN1_MACTX_HANG_ERR_SHFT 21 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN0_MACTX_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN0_MACTX_HANG_ERR_MASK \ + 0x00100000 /* EN_BN0_MACTX_HANG_ERR[20] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_BN0_MACTX_HANG_ERR_SHFT 20 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_QSTRUCT_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_QSTRUCT_ERR_MASK \ + 0x00080000 /* EN_QSTRUCT_ERR[19] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_QSTRUCT_ERR_SHFT 19 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_FREE_HEAD_TAIL_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_FREE_HEAD_TAIL_ERR_MASK \ + 0x00040000 /* EN_FREE_HEAD_TAIL_ERR[18] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_FREE_HEAD_TAIL_ERR_SHFT 18 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_LMAC_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_LMAC_HANG_ERR_MASK \ + 0x00020000 /* EN_LMAC_HANG_ERR[17] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_LMAC_HANG_ERR_SHFT 17 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_CPU_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_CPU_HANG_ERR_MASK \ + 0x00010000 /* EN_CPU_HANG_ERR[16] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_CPU_HANG_ERR_SHFT 16 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_HIF_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_HIF_HANG_ERR_MASK \ + 0x00008000 /* EN_HIF_HANG_ERR[15] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_HIF_HANG_ERR_SHFT 15 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PL_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PL_HANG_ERR_MASK \ + 0x00004000 /* EN_PL_HANG_ERR[14] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PL_HANG_ERR_SHFT 14 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_FL_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_FL_HANG_ERR_MASK \ + 0x00002000 /* EN_FL_HANG_ERR[13] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_FL_HANG_ERR_SHFT 13 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P2_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P2_MASK \ + 0x00001000 /* EN_DATA_OPER_ERR_P2[12] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P2_SHFT 12 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P1_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P1_MASK \ + 0x00000800 /* EN_DATA_OPER_ERR_P1[11] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P1_SHFT 11 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P0_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P0_MASK \ + 0x00000400 /* EN_DATA_OPER_ERR_P0[10] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P0_SHFT 10 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_MDP_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_MDP_HANG_ERR_MASK \ + 0x00000100 /* EN_MDP_HANG_ERR[8] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_MDP_HANG_ERR_SHFT 8 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_MDP_D_OPER_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_MDP_D_OPER_ERR_MASK \ + 0x00000080 /* EN_MDP_D_OPER_ERR[7] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_MDP_D_OPER_ERR_SHFT 7 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DOUBLE_RLS_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DOUBLE_RLS_ERR_MASK \ + 0x00000040 /* EN_DOUBLE_RLS_ERR[6] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_DOUBLE_RLS_ERR_SHFT 6 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P2_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P2_MASK \ + 0x00000020 /* EN_PAGE_UDF_P2[5] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P2_SHFT 5 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P1_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P1_MASK \ + 0x00000010 /* EN_PAGE_UDF_P1[4] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P1_SHFT 4 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P0_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P0_MASK \ + 0x00000008 /* EN_PAGE_UDF_P0[3] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P0_SHFT 3 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P2_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P2_MASK \ + 0x00000004 /* EN_Q_CMD_ERR_P2[2] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P2_SHFT 2 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P1_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P1_MASK \ + 0x00000002 /* EN_Q_CMD_ERR_P1[1] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P1_SHFT 1 +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P0_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P0_MASK \ + 0x00000001 /* EN_Q_CMD_ERR_P0[0] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P0_SHFT 0 + +/* +* ---HOST_REPORT0 (0x820C0000 + 0x30)--- +* RESERVED0[0] - (RO) Reserved bits +* DIS_HOST_RPT[1] - (RW) Disables host report function +* HOST_RPT_VER0_EN[2] - (RW) Enable control for host report roll back +* to Version 0(MT7615 used). +* RESERVED3[3] - (RO) Reserved bits +* WMCPU_MSDU_ID_NUM[5..4] - (RW) Configuration of WMCPU MSDU ID usage. +* RESERVED6[7..6] - (RO) Reserved bits +* HOST_RPT_PACK_TH[15..8] - (RW) The buffer threshold for packing host +* report. The buffer size less then the MSDU numbers of a MPDU, would +* let MSDU_ID +lose. +* HOST_RPT_QID[22..16] - (RW) PSE Queue ID control for host report. +* HOST_RPT_PID[23] - (RW) PSE Port ID control for host report. +* WMCPU_RPT_QID[30..24] - (RW) PSE Queue ID control for WMCPU report. +* WMCPU_RPT_PID[31] - (RW) PSE Port ID control for WMCPU report. +*/ +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_RPT_PID_ADDR \ + WF_PLE_TOP_HOST_REPORT0_ADDR +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_RPT_PID_MASK \ + 0x80000000 /* WMCPU_RPT_PID[31] */ +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_RPT_PID_SHFT 31 +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_RPT_QID_ADDR \ + WF_PLE_TOP_HOST_REPORT0_ADDR +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_RPT_QID_MASK \ + 0x7F000000 /* WMCPU_RPT_QID[30..24] */ +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_RPT_QID_SHFT 24 +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_PID_ADDR \ + WF_PLE_TOP_HOST_REPORT0_ADDR +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_PID_MASK \ + 0x00800000 /* HOST_RPT_PID[23] */ +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_PID_SHFT 23 +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_QID_ADDR \ + WF_PLE_TOP_HOST_REPORT0_ADDR +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_QID_MASK \ + 0x007F0000 /* HOST_RPT_QID[22..16] */ +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_QID_SHFT 16 +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_PACK_TH_ADDR \ + WF_PLE_TOP_HOST_REPORT0_ADDR +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_PACK_TH_MASK \ + 0x0000FF00 /* HOST_RPT_PACK_TH[15..8] */ +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_PACK_TH_SHFT 8 +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_MSDU_ID_NUM_ADDR \ + WF_PLE_TOP_HOST_REPORT0_ADDR +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_MSDU_ID_NUM_MASK \ + 0x00000030 /* WMCPU_MSDU_ID_NUM[5..4] */ +#define WF_PLE_TOP_HOST_REPORT0_WMCPU_MSDU_ID_NUM_SHFT 4 +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_VER0_EN_ADDR \ + WF_PLE_TOP_HOST_REPORT0_ADDR +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_VER0_EN_MASK \ + 0x00000004 /* HOST_RPT_VER0_EN[2] */ +#define WF_PLE_TOP_HOST_REPORT0_HOST_RPT_VER0_EN_SHFT 2 +#define WF_PLE_TOP_HOST_REPORT0_DIS_HOST_RPT_ADDR \ + WF_PLE_TOP_HOST_REPORT0_ADDR +#define WF_PLE_TOP_HOST_REPORT0_DIS_HOST_RPT_MASK \ + 0x00000002 /* DIS_HOST_RPT[1] */ +#define WF_PLE_TOP_HOST_REPORT0_DIS_HOST_RPT_SHFT 1 + +/* +* ---HOST_REPORT1 (0x820C0000 + 0x34)--- +* RESERVED0[7..0] - (RO) Reserved bits +* MD_RPT_QID[14..8] - (RW) PSE Queue ID control for MD CPU host +report. +* MD_RPT_PID[15] - (RW) PSE Port ID control for MD CPU host +report. +* HOST_RPT_PG_SIZE[19..16] - (RW) Setting of host report used PSE page +size. +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_HOST_REPORT1_HOST_RPT_PG_SIZE_ADDR \ + WF_PLE_TOP_HOST_REPORT1_ADDR +#define WF_PLE_TOP_HOST_REPORT1_HOST_RPT_PG_SIZE_MASK \ + 0x000F0000 /* HOST_RPT_PG_SIZE[19..16] */ +#define WF_PLE_TOP_HOST_REPORT1_HOST_RPT_PG_SIZE_SHFT 16 +#define WF_PLE_TOP_HOST_REPORT1_MD_RPT_PID_ADDR \ + WF_PLE_TOP_HOST_REPORT1_ADDR +#define WF_PLE_TOP_HOST_REPORT1_MD_RPT_PID_MASK \ + 0x00008000 /* MD_RPT_PID[15] */ +#define WF_PLE_TOP_HOST_REPORT1_MD_RPT_PID_SHFT 15 +#define WF_PLE_TOP_HOST_REPORT1_MD_RPT_QID_ADDR \ + WF_PLE_TOP_HOST_REPORT1_ADDR +#define WF_PLE_TOP_HOST_REPORT1_MD_RPT_QID_MASK \ + 0x00007F00 /* MD_RPT_QID[14..8] */ +#define WF_PLE_TOP_HOST_REPORT1_MD_RPT_QID_SHFT 8 + +/* +* ---HOST_REPORT2 (0x820C0000 + 0x38)--- +* BN1_HOST_RPT_QID[6..0] - (RW) PSE Queue ID control for BN1 Host +report. +* BN1_HOST_RPT_PID[7] - (RW) PSE Port ID control for BN1 Host report. +* BN1_MD_RPT_QID[14..8] - (RW) PSE Queue ID control for BN1 MD CPU +host +report. +* BN1_MD_RPT_PID[15] - (RW) PSE Port ID control for BN1 MD CPU host +report. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_HOST_REPORT2_BN1_MD_RPT_PID_ADDR \ + WF_PLE_TOP_HOST_REPORT2_ADDR +#define WF_PLE_TOP_HOST_REPORT2_BN1_MD_RPT_PID_MASK \ + 0x00008000 /* BN1_MD_RPT_PID[15] */ +#define WF_PLE_TOP_HOST_REPORT2_BN1_MD_RPT_PID_SHFT 15 +#define WF_PLE_TOP_HOST_REPORT2_BN1_MD_RPT_QID_ADDR \ + WF_PLE_TOP_HOST_REPORT2_ADDR +#define WF_PLE_TOP_HOST_REPORT2_BN1_MD_RPT_QID_MASK \ + 0x00007F00 /* BN1_MD_RPT_QID[14..8] */ +#define WF_PLE_TOP_HOST_REPORT2_BN1_MD_RPT_QID_SHFT 8 +#define WF_PLE_TOP_HOST_REPORT2_BN1_HOST_RPT_PID_ADDR \ + WF_PLE_TOP_HOST_REPORT2_ADDR +#define WF_PLE_TOP_HOST_REPORT2_BN1_HOST_RPT_PID_MASK \ + 0x00000080 /* BN1_HOST_RPT_PID[7] */ +#define WF_PLE_TOP_HOST_REPORT2_BN1_HOST_RPT_PID_SHFT 7 +#define WF_PLE_TOP_HOST_REPORT2_BN1_HOST_RPT_QID_ADDR \ + WF_PLE_TOP_HOST_REPORT2_ADDR +#define WF_PLE_TOP_HOST_REPORT2_BN1_HOST_RPT_QID_MASK \ + 0x0000007F /* BN1_HOST_RPT_QID[6..0] */ +#define WF_PLE_TOP_HOST_REPORT2_BN1_HOST_RPT_QID_SHFT 0 + +/* +* ---BLK_MODE_RATE_LMT (0x820C0000 + 0x3c)--- +* BN0_MACTX_BLK_RATE_LMT[15..0] - (RW) TX Rate limitaion of CutThrough +data +* block mode. The rate less then the limitation would turn on block +mode. +* BN1_MACTX_BLK_RATE_LMT[31..16] - (RW) TX Rate limitaion of +* CutThrough data +* block mode. The rate less then the limitation would turn on block +mode. +*/ +#define WF_PLE_TOP_BLK_MODE_RATE_LMT_BN1_MACTX_BLK_RATE_LMT_ADDR \ + WF_PLE_TOP_BLK_MODE_RATE_LMT_ADDR +#define WF_PLE_TOP_BLK_MODE_RATE_LMT_BN1_MACTX_BLK_RATE_LMT_MASK \ + 0xFFFF0000 /* BN1_MACTX_BLK_RATE_LMT[31..16] */ +#define WF_PLE_TOP_BLK_MODE_RATE_LMT_BN1_MACTX_BLK_RATE_LMT_SHFT 16 +#define WF_PLE_TOP_BLK_MODE_RATE_LMT_BN0_MACTX_BLK_RATE_LMT_ADDR \ + WF_PLE_TOP_BLK_MODE_RATE_LMT_ADDR +#define WF_PLE_TOP_BLK_MODE_RATE_LMT_BN0_MACTX_BLK_RATE_LMT_MASK \ + 0x0000FFFF /* BN0_MACTX_BLK_RATE_LMT[15..0] */ +#define WF_PLE_TOP_BLK_MODE_RATE_LMT_BN0_MACTX_BLK_RATE_LMT_SHFT 0 + +/* +* ---C_GET_FID_0 (0x820C0000 + 0x40)--- +* GET_SRC_WLANID[9..0] - (RW) Source WLAN ID for get frame ID. +* RESERVED10[11..10] - (RO) Reserved bits +* GET_SRC_TGID[12] - (RW) Source TX Group ID for get frame ID. +* RESERVED13[13] - (RO) Reserved bits +* GET_SRC_PID[15..14] - (RW) Source port ID for get frame ID. +* GET_FRAME_TYPE[19..16] - (RW) GET_SUB_TYPE +* RESERVED20[23..20] - (RO) Reserved bits +* GET_SRC_QID[30..24] - (RW) Source Queue ID for get frame ID. +* EXECUTE[31] - (A0) Executes command +*/ +#define WF_PLE_TOP_C_GET_FID_0_EXECUTE_ADDR \ + WF_PLE_TOP_C_GET_FID_0_ADDR +#define WF_PLE_TOP_C_GET_FID_0_EXECUTE_MASK \ + 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_C_GET_FID_0_EXECUTE_SHFT 31 +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_QID_ADDR \ + WF_PLE_TOP_C_GET_FID_0_ADDR +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_QID_MASK \ + 0x7F000000 /* GET_SRC_QID[30..24] */ +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_QID_SHFT 24 +#define WF_PLE_TOP_C_GET_FID_0_GET_FRAME_TYPE_ADDR \ + WF_PLE_TOP_C_GET_FID_0_ADDR +#define WF_PLE_TOP_C_GET_FID_0_GET_FRAME_TYPE_MASK \ + 0x000F0000 /* GET_FRAME_TYPE[19..16] */ +#define WF_PLE_TOP_C_GET_FID_0_GET_FRAME_TYPE_SHFT 16 +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_PID_ADDR \ + WF_PLE_TOP_C_GET_FID_0_ADDR +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_PID_MASK \ + 0x0000C000 /* GET_SRC_PID[15..14] */ +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_PID_SHFT 14 +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_TGID_ADDR \ + WF_PLE_TOP_C_GET_FID_0_ADDR +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_TGID_MASK \ + 0x00001000 /* GET_SRC_TGID[12] */ +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_TGID_SHFT 12 +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_WLANID_ADDR \ + WF_PLE_TOP_C_GET_FID_0_ADDR +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_WLANID_MASK \ + 0x000003FF /* GET_SRC_WLANID[9..0] */ +#define WF_PLE_TOP_C_GET_FID_0_GET_SRC_WLANID_SHFT 0 + +/* +* ---C_GET_FID_1 (0x820C0000 + 0x44)--- +* GET_RETURN_FID[11..0] - (RO) Return frame ID +* RESERVED12[14..12] - (RO) Reserved bits +* END[15] - (RO) Return frame ID is end FID. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_C_GET_FID_1_END_ADDR WF_PLE_TOP_C_GET_FID_1_ADDR +#define WF_PLE_TOP_C_GET_FID_1_END_MASK 0x00008000 /* END[15] */ +#define WF_PLE_TOP_C_GET_FID_1_END_SHFT 15 +#define WF_PLE_TOP_C_GET_FID_1_GET_RETURN_FID_ADDR \ + WF_PLE_TOP_C_GET_FID_1_ADDR +#define WF_PLE_TOP_C_GET_FID_1_GET_RETURN_FID_MASK \ + 0x00000FFF /* GET_RETURN_FID[11..0] */ +#define WF_PLE_TOP_C_GET_FID_1_GET_RETURN_FID_SHFT 0 + +/* +* ---RELEASE_CTRL_0 (0x820C0000 + 0x50)--- +* NOR_RLS_QID[6..0] - (RW) Normal TX packet release DST QID +* RESERVED7[7] - (RO) Reserved bits +* NOR_RLS_PID[9..8] - (RW) Normal TX packet release DST PID +* RESERVED10[15..10] - (RO) Reserved bits +* DROP_RLS_QID[22..16] - (RW) Drop packet release DST QID +* RESERVED23[23] - (RO) Reserved bits +* DROP_RLS_PID[25..24] - (RW) Drop packet release DST PID +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_RELEASE_CTRL_0_DROP_RLS_PID_ADDR \ + WF_PLE_TOP_RELEASE_CTRL_0_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_0_DROP_RLS_PID_MASK \ + 0x03000000 /* DROP_RLS_PID[25..24] */ +#define WF_PLE_TOP_RELEASE_CTRL_0_DROP_RLS_PID_SHFT 24 +#define WF_PLE_TOP_RELEASE_CTRL_0_DROP_RLS_QID_ADDR \ + WF_PLE_TOP_RELEASE_CTRL_0_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_0_DROP_RLS_QID_MASK \ + 0x007F0000 /* DROP_RLS_QID[22..16] */ +#define WF_PLE_TOP_RELEASE_CTRL_0_DROP_RLS_QID_SHFT 16 +#define WF_PLE_TOP_RELEASE_CTRL_0_NOR_RLS_PID_ADDR \ + WF_PLE_TOP_RELEASE_CTRL_0_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_0_NOR_RLS_PID_MASK \ + 0x00000300 /* NOR_RLS_PID[9..8] */ +#define WF_PLE_TOP_RELEASE_CTRL_0_NOR_RLS_PID_SHFT 8 +#define WF_PLE_TOP_RELEASE_CTRL_0_NOR_RLS_QID_ADDR \ + WF_PLE_TOP_RELEASE_CTRL_0_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_0_NOR_RLS_QID_MASK \ + 0x0000007F /* NOR_RLS_QID[6..0] */ +#define WF_PLE_TOP_RELEASE_CTRL_0_NOR_RLS_QID_SHFT 0 + +/* +* ---RELEASE_CTRL_1 (0x820C0000 + 0x54)--- +* BCN0_RLS_QID[6..0] - (RW) Beacon 0 packet release DST QID +* RESERVED7[7] - (RO) Reserved bits +* BCN0_RLS_PID[9..8] - (RW) Beacon 0 packet release DST PID +* RESERVED10[15..10] - (RO) Reserved bits +* BCN1_RLS_QID[22..16] - (RW) Beacon 1 packet release DST QID +* RESERVED23[23] - (RO) Reserved bits +* BCN1_RLS_PID[25..24] - (RW) Beacon 1 packet release DST PID +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN1_RLS_PID_ADDR \ + WF_PLE_TOP_RELEASE_CTRL_1_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN1_RLS_PID_MASK \ + 0x03000000 /* BCN1_RLS_PID[25..24] */ +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN1_RLS_PID_SHFT 24 +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN1_RLS_QID_ADDR \ + WF_PLE_TOP_RELEASE_CTRL_1_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN1_RLS_QID_MASK \ + 0x007F0000 /* BCN1_RLS_QID[22..16] */ +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN1_RLS_QID_SHFT 16 +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN0_RLS_PID_ADDR \ + WF_PLE_TOP_RELEASE_CTRL_1_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN0_RLS_PID_MASK \ + 0x00000300 /* BCN0_RLS_PID[9..8] */ +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN0_RLS_PID_SHFT 8 +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN0_RLS_QID_ADDR \ + WF_PLE_TOP_RELEASE_CTRL_1_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN0_RLS_QID_MASK \ + 0x0000007F /* BCN0_RLS_QID[6..0] */ +#define WF_PLE_TOP_RELEASE_CTRL_1_BCN0_RLS_QID_SHFT 0 + +/* +* ---RELEASE_CTRL_3 (0x820C0000 + 0x5c)--- +* RLS_FREE_DONE_PG_SIZE[3..0] - (RW) Page size configuration of Free +done +* event(host report). +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_RELEASE_CTRL_3_RLS_FREE_DONE_PG_SIZE_ADDR \ + WF_PLE_TOP_RELEASE_CTRL_3_ADDR +#define WF_PLE_TOP_RELEASE_CTRL_3_RLS_FREE_DONE_PG_SIZE_MASK \ + 0x0000000F /* RLS_FREE_DONE_PG_SIZE[3..0] */ +#define WF_PLE_TOP_RELEASE_CTRL_3_RLS_FREE_DONE_PG_SIZE_SHFT 0 + +/* +* ---C_EN_QUEUE_0 (0x820C0000 + 0x60)--- +* DST_WLANID[9..0] - (RW) Destination WLANID for enqueue +* RESERVED10[11..10] - (RO) Reserved bits +* DST_TGID[12] - (RW) Destination TX Group ID for enqueue +* RESERVED13[13] - (RO) Reserved bits +* DST_PID[15..14] - (RW) Destination port ID for enqueue +* SUB_TYPE[19..16] - (RW) Sub-type of enqueue command +* RESERVED20[22..20] - (RO) Reserved bits +* DELAY_ENQ[23] - (RW) Delay enqueue +* ENQ_DST_QID[30..24] - (RW) Destination queue ID for enqueue +* EXECUTE[31] - (A0) Executes command +*/ +#define WF_PLE_TOP_C_EN_QUEUE_0_EXECUTE_ADDR \ + WF_PLE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_0_EXECUTE_MASK \ + 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_C_EN_QUEUE_0_EXECUTE_SHFT 31 +#define WF_PLE_TOP_C_EN_QUEUE_0_ENQ_DST_QID_ADDR \ + WF_PLE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_0_ENQ_DST_QID_MASK \ + 0x7F000000 /* ENQ_DST_QID[30..24] */ +#define WF_PLE_TOP_C_EN_QUEUE_0_ENQ_DST_QID_SHFT 24 +#define WF_PLE_TOP_C_EN_QUEUE_0_DELAY_ENQ_ADDR \ + WF_PLE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_0_DELAY_ENQ_MASK \ + 0x00800000 /* DELAY_ENQ[23] */ +#define WF_PLE_TOP_C_EN_QUEUE_0_DELAY_ENQ_SHFT 23 +#define WF_PLE_TOP_C_EN_QUEUE_0_SUB_TYPE_ADDR \ + WF_PLE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_0_SUB_TYPE_MASK \ + 0x000F0000 /* SUB_TYPE[19..16] */ +#define WF_PLE_TOP_C_EN_QUEUE_0_SUB_TYPE_SHFT 16 +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_PID_ADDR \ + WF_PLE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_PID_MASK \ + 0x0000C000 /* DST_PID[15..14] */ +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_PID_SHFT 14 +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_TGID_ADDR \ + WF_PLE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_TGID_MASK \ + 0x00001000 /* DST_TGID[12] */ +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_TGID_SHFT 12 +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_WLANID_ADDR \ + WF_PLE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_WLANID_MASK \ + 0x000003FF /* DST_WLANID[9..0] */ +#define WF_PLE_TOP_C_EN_QUEUE_0_DST_WLANID_SHFT 0 + +/* +* ---C_EN_QUEUE_1 (0x820C0000 + 0x64)--- +* CUR_LIST_FID_START[11..0] - (RW) Start frame ID of enqueue operation +* list, enqueue FID of enqueue operation +* RESERVED12[15..12] - (RO) Reserved bits +* CUR_LIST_FID_END[27..16] - (RW) End frame ID of enqueue operation +list +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_END_ADDR \ + WF_PLE_TOP_C_EN_QUEUE_1_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_END_MASK \ + 0x0FFF0000 /* CUR_LIST_FID_END[27..16] */ +#define WF_PLE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_END_SHFT 16 +#define WF_PLE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_START_ADDR \ + WF_PLE_TOP_C_EN_QUEUE_1_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_START_MASK \ + 0x00000FFF /* CUR_LIST_FID_START[11..0] */ +#define WF_PLE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_START_SHFT 0 + +/* +* ---C_EN_QUEUE_2 (0x820C0000 + 0x68)--- +* TARGET_FID[11..0] - (RW) Target reference FID for enqueue +operation +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_C_EN_QUEUE_2_TARGET_FID_ADDR \ + WF_PLE_TOP_C_EN_QUEUE_2_ADDR +#define WF_PLE_TOP_C_EN_QUEUE_2_TARGET_FID_MASK \ + 0x00000FFF /* TARGET_FID[11..0] */ +#define WF_PLE_TOP_C_EN_QUEUE_2_TARGET_FID_SHFT 0 + +/* +* ---C_DE_QUEUE_0 (0x820C0000 + 0x80)--- +* SRC_WLANID[9..0] - (RW) Source WLAN ID for dequeue command +* RESERVED10[11..10] - (RO) Reserved bits +* SRC_TGID[12] - (RW) Source TX Group ID for dequeue command +* RESERVED13[13] - (RO) Reserved bits +* SRC_PID[15..14] - (RW) Source port ID for dequeue command +* DEQ_SUB_TYPE[19..16] - (RW) Dequeue subtype of dequeue command +* ENQ_SUB_TYPE[22..20] - (RW) Enqueue subtype of enqueue command +* Only valid in Deq&Enq type. +* ENQ_VLD[23] - (RW) Deq&Enq command valid +* SRC_QID[30..24] - (RW) Source queue ID for dequeue command +* EXECUTE[31] - (A0) Executes dequeue command +*/ +#define WF_PLE_TOP_C_DE_QUEUE_0_EXECUTE_ADDR \ + WF_PLE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_0_EXECUTE_MASK \ + 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_C_DE_QUEUE_0_EXECUTE_SHFT 31 +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_QID_ADDR \ + WF_PLE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_QID_MASK \ + 0x7F000000 /* SRC_QID[30..24] */ +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_QID_SHFT 24 +#define WF_PLE_TOP_C_DE_QUEUE_0_ENQ_VLD_ADDR \ + WF_PLE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_0_ENQ_VLD_MASK \ + 0x00800000 /* ENQ_VLD[23] */ +#define WF_PLE_TOP_C_DE_QUEUE_0_ENQ_VLD_SHFT 23 +#define WF_PLE_TOP_C_DE_QUEUE_0_ENQ_SUB_TYPE_ADDR \ + WF_PLE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_0_ENQ_SUB_TYPE_MASK \ + 0x00700000 /* ENQ_SUB_TYPE[22..20] */ +#define WF_PLE_TOP_C_DE_QUEUE_0_ENQ_SUB_TYPE_SHFT 20 +#define WF_PLE_TOP_C_DE_QUEUE_0_DEQ_SUB_TYPE_ADDR \ + WF_PLE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_0_DEQ_SUB_TYPE_MASK \ + 0x000F0000 /* DEQ_SUB_TYPE[19..16] */ +#define WF_PLE_TOP_C_DE_QUEUE_0_DEQ_SUB_TYPE_SHFT 16 +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_PID_ADDR \ + WF_PLE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_PID_MASK \ + 0x0000C000 /* SRC_PID[15..14] */ +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_PID_SHFT 14 +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_TGID_ADDR \ + WF_PLE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_TGID_MASK \ + 0x00001000 /* SRC_TGID[12] */ +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_TGID_SHFT 12 +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_WLANID_ADDR \ + WF_PLE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_WLANID_MASK \ + 0x000003FF /* SRC_WLANID[9..0] */ +#define WF_PLE_TOP_C_DE_QUEUE_0_SRC_WLANID_SHFT 0 + +/* +* ---C_DE_QUEUE_1 (0x820C0000 + 0x84)--- +* CUR_LIST_FID_START[11..0] - (RW) Start frame ID of dequeue operation +* list, enqueue start FID of enqueue operation +* Only valid in Deq&Enq type. +* RESERVED12[15..12] - (RO) Reserved bits +* CUR_LIST_FID_END[27..16] - (RW) End framd ID of dequeue operation +list, +* enqueue end FID of enqueue operation +* Only valid in Deq&Enq type. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_END_ADDR \ + WF_PLE_TOP_C_DE_QUEUE_1_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_END_MASK \ + 0x0FFF0000 /* CUR_LIST_FID_END[27..16] */ +#define WF_PLE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_END_SHFT 16 +#define WF_PLE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_START_ADDR \ + WF_PLE_TOP_C_DE_QUEUE_1_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_START_MASK \ + 0x00000FFF /* CUR_LIST_FID_START[11..0] */ +#define WF_PLE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_START_SHFT 0 + +/* +* ---C_DE_QUEUE_2 (0x820C0000 + 0x88)--- +* DEQ_ENQ_DST_WLANID[9..0] - (RW) Destination WLAN ID for enqueue +command +* Only valid in Deq&Enq type. +* RESERVED10[11..10] - (RO) Reserved bits +* DEQ_ENQ_DST_TGID[12] - (RW) Destination TX Group ID for enqueue +command +* Only valid in Deq&Enq type. +* RESERVED13[13] - (RO) Reserved bits +* DEQ_ENQ_DST_PID[15..14] - (RW) Destination port ID for enqueue +command +* OInly valid in Deq&Enq type. +* RESERVED16[23..16] - (RO) Reserved bits +* DEQ_ENQ_DST_QID[30..24] - (RW) Destination queue ID for enqueue +command +* Only valid in Deq&Enq type. +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_QID_ADDR \ + WF_PLE_TOP_C_DE_QUEUE_2_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_QID_MASK \ + 0x7F000000 /* DEQ_ENQ_DST_QID[30..24] */ +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_QID_SHFT 24 +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_PID_ADDR \ + WF_PLE_TOP_C_DE_QUEUE_2_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_PID_MASK \ + 0x0000C000 /* DEQ_ENQ_DST_PID[15..14] */ +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_PID_SHFT 14 +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_TGID_ADDR \ + WF_PLE_TOP_C_DE_QUEUE_2_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_TGID_MASK \ + 0x00001000 /* DEQ_ENQ_DST_TGID[12] */ +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_TGID_SHFT 12 +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_WLANID_ADDR \ + WF_PLE_TOP_C_DE_QUEUE_2_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_WLANID_MASK \ + 0x000003FF /* DEQ_ENQ_DST_WLANID[9..0] */ +#define WF_PLE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_WLANID_SHFT 0 + +/* +* ---C_DE_QUEUE_3 (0x820C0000 + 0x8c)--- +* DEQ_HEAD_FID[11..0] - (RO) Head FID got from dequeue command +* RESERVED12[14..12] - (RO) Reserved bits +* DEQ_EMPTY[15] - (RO) Queue empty after dequeue command is +executed +* DEQ_TAIL_FID[27..16] - (RO) Last FID got from dequeue command +* RESERVED28[30..28] - (RO) Reserved bits +* BUSY[31] - (RO) Dequeue execute busy +*/ +#define WF_PLE_TOP_C_DE_QUEUE_3_BUSY_ADDR WF_PLE_TOP_C_DE_QUEUE_3_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_3_BUSY_MASK 0x80000000 /* BUSY[31] */ +#define WF_PLE_TOP_C_DE_QUEUE_3_BUSY_SHFT 31 +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_TAIL_FID_ADDR \ + WF_PLE_TOP_C_DE_QUEUE_3_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_TAIL_FID_MASK \ + 0x0FFF0000 /* DEQ_TAIL_FID[27..16] */ +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_TAIL_FID_SHFT 16 +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_EMPTY_ADDR \ + WF_PLE_TOP_C_DE_QUEUE_3_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_EMPTY_MASK \ + 0x00008000 /* DEQ_EMPTY[15] */ +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_EMPTY_SHFT 15 +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_HEAD_FID_ADDR \ + WF_PLE_TOP_C_DE_QUEUE_3_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_HEAD_FID_MASK \ + 0x00000FFF /* DEQ_HEAD_FID[11..0] */ +#define WF_PLE_TOP_C_DE_QUEUE_3_DEQ_HEAD_FID_SHFT 0 + +/* +* ---C_DE_QUEUE_4 (0x820C0000 + 0x90)--- +* DEQ_ENQ_REF_FID[11..0] - (RW) Reference frame ID for enqueue command +* Only valid in Deq&Enq type. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_C_DE_QUEUE_4_DEQ_ENQ_REF_FID_ADDR \ + WF_PLE_TOP_C_DE_QUEUE_4_ADDR +#define WF_PLE_TOP_C_DE_QUEUE_4_DEQ_ENQ_REF_FID_MASK \ + 0x00000FFF /* DEQ_ENQ_REF_FID[11..0] */ +#define WF_PLE_TOP_C_DE_QUEUE_4_DEQ_ENQ_REF_FID_SHFT 0 + +/* +* ---ALLOCATE_0 (0x820C0000 + 0xA0)--- +* ALLOCATE_FRAME_LENGTH[13..0] - (RW) Allocate frame length +* Unit: DW (4 bytes) +* RESERVED14[15..14] - (RO) Reserved bits +* ALLOCATE_QID[20..16] - (RW) QID used for allocate buffer +* RESERVED21[30..21] - (RO) Reserved bits +* EXECUTE[31] - (A0) Executes allocate buffer command +*/ +#define WF_PLE_TOP_ALLOCATE_0_EXECUTE_ADDR WF_PLE_TOP_ALLOCATE_0_ADDR +#define WF_PLE_TOP_ALLOCATE_0_EXECUTE_MASK \ + 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_ALLOCATE_0_EXECUTE_SHFT 31 +#define WF_PLE_TOP_ALLOCATE_0_ALLOCATE_QID_ADDR \ + WF_PLE_TOP_ALLOCATE_0_ADDR +#define WF_PLE_TOP_ALLOCATE_0_ALLOCATE_QID_MASK \ + 0x001F0000 /* ALLOCATE_QID[20..16] */ +#define WF_PLE_TOP_ALLOCATE_0_ALLOCATE_QID_SHFT 16 +#define WF_PLE_TOP_ALLOCATE_0_ALLOCATE_FRAME_LENGTH_ADDR \ + WF_PLE_TOP_ALLOCATE_0_ADDR +#define WF_PLE_TOP_ALLOCATE_0_ALLOCATE_FRAME_LENGTH_MASK \ + 0x00003FFF /* ALLOCATE_FRAME_LENGTH[13..0] */ +#define WF_PLE_TOP_ALLOCATE_0_ALLOCATE_FRAME_LENGTH_SHFT 0 + +/* +* ---ALLOCATE_1 (0x820C0000 + 0xA4)--- +* ALLOCATE_FID[11..0] - (RO) Return frame ID for allocate buffer +command +* RESERVED12[30..12] - (RO) Reserved bits +* EXECUTE[31] - (RO) Execute status of allocate buffer +command +*/ +#define WF_PLE_TOP_ALLOCATE_1_EXECUTE_ADDR WF_PLE_TOP_ALLOCATE_1_ADDR +#define WF_PLE_TOP_ALLOCATE_1_EXECUTE_MASK \ + 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_ALLOCATE_1_EXECUTE_SHFT 31 +#define WF_PLE_TOP_ALLOCATE_1_ALLOCATE_FID_ADDR \ + WF_PLE_TOP_ALLOCATE_1_ADDR +#define WF_PLE_TOP_ALLOCATE_1_ALLOCATE_FID_MASK \ + 0x00000FFF /* ALLOCATE_FID[11..0] */ +#define WF_PLE_TOP_ALLOCATE_1_ALLOCATE_FID_SHFT 0 + +/* +* ---ALLOCATE_2 (0x820C0000 + 0xA8)--- +* CPU_TXBYTE_COUNT[15..0] - (RW) TX data byte count +* This value should be the same as the first +* two bytes of TXD in PLE. +* CPU_MSDU_ID0_bit15_8[23..16] - (RW) MSDU_ID0 Bit15-Bit8 +* This value should be the same as the +* DW8[15:8] of TXD in PLE. +* CPU_PKT_FT[25..24] - (RW) TXD's PKT_FT +* This value should be the same as the +* DW0[24:23] of TXD in PLE. +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_ALLOCATE_2_CPU_PKT_FT_ADDR \ + WF_PLE_TOP_ALLOCATE_2_ADDR +#define WF_PLE_TOP_ALLOCATE_2_CPU_PKT_FT_MASK \ + 0x03000000 /* CPU_PKT_FT[25..24] */ +#define WF_PLE_TOP_ALLOCATE_2_CPU_PKT_FT_SHFT 24 +#define WF_PLE_TOP_ALLOCATE_2_CPU_MSDU_ID0_bit15_8_ADDR \ + WF_PLE_TOP_ALLOCATE_2_ADDR +#define WF_PLE_TOP_ALLOCATE_2_CPU_MSDU_ID0_bit15_8_MASK \ + 0x00FF0000 /* CPU_MSDU_ID0_bit15_8[23..16] */ +#define WF_PLE_TOP_ALLOCATE_2_CPU_MSDU_ID0_bit15_8_SHFT 16 +#define WF_PLE_TOP_ALLOCATE_2_CPU_TXBYTE_COUNT_ADDR \ + WF_PLE_TOP_ALLOCATE_2_ADDR +#define WF_PLE_TOP_ALLOCATE_2_CPU_TXBYTE_COUNT_MASK \ + 0x0000FFFF /* CPU_TXBYTE_COUNT[15..0] */ +#define WF_PLE_TOP_ALLOCATE_2_CPU_TXBYTE_COUNT_SHFT 0 + +/* +* ---QUEUE_EMPTY (0x820C0000 + 0xB0)--- +* CPU_Q0_EMPTY[0] - (RO) CPU queue 0 empty status +* CPU_Q1_EMPTY[1] - (RO) CPU queue 1 empty status +* CPU_Q2_EMPTY[2] - (RO) CPU queue 2 empty status +* CPU_Q3_EMPTY[3] - (RO) CPU queue 3 empty status +* RESERVED4[7..4] - (RO) Reserved bits +* ALTX_0_EMPTY[8] - (RO) ALTX queue 0 empty status +* BMC_0_EMPTY[9] - (RO) BMC queue 0 empty status +* BCN_0_EMPTY[10] - (RO) BCN queue 0 empty status +* PSMP_0_EMPTY[11] - (RO) PSMP queue 0 empty status +* ALTX_1_EMPTY[12] - (RO) ALTX queue 1 empty status +* BMC_1_EMPTY[13] - (RO) BMC queue 1 empty status +* BCN_1_EMPTY[14] - (RO) BCN queue 1 empty status +* PSMP_1_EMPTY[15] - (RO) PSMP queue 1 empty status +* NAF_EMPTY[16] - (RO) NAF queue empty status +* NBCN_EMPTY[17] - (RO) NBCN queue empty status +* RESERVED18[19..18] - (RO) Reserved bits +* FIX_FID_EMPTY[20] - (RO) FIX_FID queue empty status +* RESERVED21[23..21] - (RO) Reserved bits +* ALL_AC_EMPTY[24] - (RO) All AC queue empty status +* RESERVED25[29..25] - (RO) Reserved bits +* RLS2_Q_EMTPY[30] - (RO) Release 2 queue empty status +* RLS_Q_EMTPY[31] - (RO) Release queue empty status +*/ +#define WF_PLE_TOP_QUEUE_EMPTY_RLS_Q_EMTPY_ADDR \ + WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_RLS_Q_EMTPY_MASK \ + 0x80000000 /* RLS_Q_EMTPY[31] */ +#define WF_PLE_TOP_QUEUE_EMPTY_RLS_Q_EMTPY_SHFT 31 +#define WF_PLE_TOP_QUEUE_EMPTY_RLS2_Q_EMTPY_ADDR \ + WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_RLS2_Q_EMTPY_MASK \ + 0x40000000 /* RLS2_Q_EMTPY[30] */ +#define WF_PLE_TOP_QUEUE_EMPTY_RLS2_Q_EMTPY_SHFT 30 +#define WF_PLE_TOP_QUEUE_EMPTY_ALL_AC_EMPTY_ADDR \ + WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_ALL_AC_EMPTY_MASK \ + 0x01000000 /* ALL_AC_EMPTY[24] */ +#define WF_PLE_TOP_QUEUE_EMPTY_ALL_AC_EMPTY_SHFT 24 +#define WF_PLE_TOP_QUEUE_EMPTY_FIX_FID_EMPTY_ADDR \ + WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_FIX_FID_EMPTY_MASK \ + 0x00100000 /* FIX_FID_EMPTY[20] */ +#define WF_PLE_TOP_QUEUE_EMPTY_FIX_FID_EMPTY_SHFT 20 +#define WF_PLE_TOP_QUEUE_EMPTY_NBCN_EMPTY_ADDR \ + WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_NBCN_EMPTY_MASK \ + 0x00020000 /* NBCN_EMPTY[17] */ +#define WF_PLE_TOP_QUEUE_EMPTY_NBCN_EMPTY_SHFT 17 +#define WF_PLE_TOP_QUEUE_EMPTY_NAF_EMPTY_ADDR \ + WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_NAF_EMPTY_MASK \ + 0x00010000 /* NAF_EMPTY[16] */ +#define WF_PLE_TOP_QUEUE_EMPTY_NAF_EMPTY_SHFT 16 +#define WF_PLE_TOP_QUEUE_EMPTY_PSMP_1_EMPTY_ADDR \ + WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_PSMP_1_EMPTY_MASK \ + 0x00008000 /* PSMP_1_EMPTY[15] */ +#define WF_PLE_TOP_QUEUE_EMPTY_PSMP_1_EMPTY_SHFT 15 +#define WF_PLE_TOP_QUEUE_EMPTY_BCN_1_EMPTY_ADDR \ + WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_BCN_1_EMPTY_MASK \ + 0x00004000 /* BCN_1_EMPTY[14] */ +#define WF_PLE_TOP_QUEUE_EMPTY_BCN_1_EMPTY_SHFT 14 +#define WF_PLE_TOP_QUEUE_EMPTY_BMC_1_EMPTY_ADDR \ + WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_BMC_1_EMPTY_MASK \ + 0x00002000 /* BMC_1_EMPTY[13] */ +#define WF_PLE_TOP_QUEUE_EMPTY_BMC_1_EMPTY_SHFT 13 +#define WF_PLE_TOP_QUEUE_EMPTY_ALTX_1_EMPTY_ADDR \ + WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_ALTX_1_EMPTY_MASK \ + 0x00001000 /* ALTX_1_EMPTY[12] */ +#define WF_PLE_TOP_QUEUE_EMPTY_ALTX_1_EMPTY_SHFT 12 +#define WF_PLE_TOP_QUEUE_EMPTY_PSMP_0_EMPTY_ADDR \ + WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_PSMP_0_EMPTY_MASK \ + 0x00000800 /* PSMP_0_EMPTY[11] */ +#define WF_PLE_TOP_QUEUE_EMPTY_PSMP_0_EMPTY_SHFT 11 +#define WF_PLE_TOP_QUEUE_EMPTY_BCN_0_EMPTY_ADDR \ + WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_BCN_0_EMPTY_MASK \ + 0x00000400 /* BCN_0_EMPTY[10] */ +#define WF_PLE_TOP_QUEUE_EMPTY_BCN_0_EMPTY_SHFT 10 +#define WF_PLE_TOP_QUEUE_EMPTY_BMC_0_EMPTY_ADDR \ + WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_BMC_0_EMPTY_MASK \ + 0x00000200 /* BMC_0_EMPTY[9] */ +#define WF_PLE_TOP_QUEUE_EMPTY_BMC_0_EMPTY_SHFT 9 +#define WF_PLE_TOP_QUEUE_EMPTY_ALTX_0_EMPTY_ADDR \ + WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_ALTX_0_EMPTY_MASK \ + 0x00000100 /* ALTX_0_EMPTY[8] */ +#define WF_PLE_TOP_QUEUE_EMPTY_ALTX_0_EMPTY_SHFT 8 +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q3_EMPTY_ADDR \ + WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q3_EMPTY_MASK \ + 0x00000008 /* CPU_Q3_EMPTY[3] */ +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q3_EMPTY_SHFT 3 +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q2_EMPTY_ADDR \ + WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q2_EMPTY_MASK \ + 0x00000004 /* CPU_Q2_EMPTY[2] */ +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q2_EMPTY_SHFT 2 +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q1_EMPTY_ADDR \ + WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q1_EMPTY_MASK \ + 0x00000002 /* CPU_Q1_EMPTY[1] */ +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q1_EMPTY_SHFT 1 +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q0_EMPTY_ADDR \ + WF_PLE_TOP_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q0_EMPTY_MASK \ + 0x00000001 /* CPU_Q0_EMPTY[0] */ +#define WF_PLE_TOP_QUEUE_EMPTY_CPU_Q0_EMPTY_SHFT 0 + +/* +* ---FREEPG_START_END (0x820C0000 + 0xc0)--- +* FREEPG_START[11..0] - (RW) Start page for free page list +* Set start page before release PLE logic +* reset, and must not be changed after release logic reset. +* RESERVED12[15..12] - (RO) Reserved bits +* FREEPG_END[27..16] - (RW) End page for free page list +* Set end page before release PLE logic +* reset, and must not be changed after release logic reset. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FREEPG_START_END_FREEPG_END_ADDR \ + WF_PLE_TOP_FREEPG_START_END_ADDR +#define WF_PLE_TOP_FREEPG_START_END_FREEPG_END_MASK \ + 0x0FFF0000 /* FREEPG_END[27..16] */ +#define WF_PLE_TOP_FREEPG_START_END_FREEPG_END_SHFT 16 +#define WF_PLE_TOP_FREEPG_START_END_FREEPG_START_ADDR \ + WF_PLE_TOP_FREEPG_START_END_ADDR +#define WF_PLE_TOP_FREEPG_START_END_FREEPG_START_MASK \ + 0x00000FFF /* FREEPG_START[11..0] */ +#define WF_PLE_TOP_FREEPG_START_END_FREEPG_START_SHFT 0 + +/* +* ---PLE_MODULE_CKG_DIS (0x820C0000 + 0xc4)--- +* DIS_FL_DYN_CKG[0] - (RW) Disable control of PLE frame link module +* dynamic clock gating function +* DIS_PL_DYN_CKG[1] - (RW) Disable control of PLE page link module +* dynamic clock gating function +* DIS_CPU_PORT_DYN_CKG[2] - (RW) Disable control of PLE CPU port +module +* dynamic clock gating function +* DIS_HIF_PORT_DYN_CKG[3] - (RW) Disable control of PLE HIF port +module +* dynamic clock gating function +* DIS_WF_PORT_DYN_CKG[4] - (RW) Disable control of PLE LMAC module +* dynamic clock gating function +* DIS_RLS_DYN_CKG[5] - (RW) Disable control of PLE release module +* dynamic clock gating function +* DIS_RL_DYN_CKG[6] - (RW) Disable control of PLE relay information +* module dynamic clock gating function +* DIS_MACTX_DYN_CKG[7] - (RW) Disable control of PLE MACTX module +* dynamic clock gating function +* DIS_PSEPORT_DYN_CKG[8] - (RW) Disable control of PLE PSE port module +* dynamic clock gating function +* DIS_CSR_DYN_CKG[9] - (RW) Disable control of PLE CR module dynamic +* clock gating function +* DIS_CPU_WRAP_DYN_CKG[10] - (RW) Disable control of PLE CPU_WRAP +module +* dynamic clock gating function +* DIS_DBG_DYN_CKG[11] - (RW) Disable control of PLE debug module +* dynamic clock gating function +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_DBG_DYN_CKG_ADDR \ + WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_DBG_DYN_CKG_MASK \ + 0x00000800 /* DIS_DBG_DYN_CKG[11] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_DBG_DYN_CKG_SHFT 11 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CPU_WRAP_DYN_CKG_ADDR \ + WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CPU_WRAP_DYN_CKG_MASK \ + 0x00000400 /* DIS_CPU_WRAP_DYN_CKG[10] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CPU_WRAP_DYN_CKG_SHFT 10 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CSR_DYN_CKG_ADDR \ + WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CSR_DYN_CKG_MASK \ + 0x00000200 /* DIS_CSR_DYN_CKG[9] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CSR_DYN_CKG_SHFT 9 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_PSEPORT_DYN_CKG_ADDR \ + WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_PSEPORT_DYN_CKG_MASK \ + 0x00000100 /* DIS_PSEPORT_DYN_CKG[8] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_PSEPORT_DYN_CKG_SHFT 8 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_MACTX_DYN_CKG_ADDR \ + WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_MACTX_DYN_CKG_MASK \ + 0x00000080 /* DIS_MACTX_DYN_CKG[7] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_MACTX_DYN_CKG_SHFT 7 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_RL_DYN_CKG_ADDR \ + WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_RL_DYN_CKG_MASK \ + 0x00000040 /* DIS_RL_DYN_CKG[6] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_RL_DYN_CKG_SHFT 6 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_RLS_DYN_CKG_ADDR \ + WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_RLS_DYN_CKG_MASK \ + 0x00000020 /* DIS_RLS_DYN_CKG[5] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_RLS_DYN_CKG_SHFT 5 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_WF_PORT_DYN_CKG_ADDR \ + WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_WF_PORT_DYN_CKG_MASK \ + 0x00000010 /* DIS_WF_PORT_DYN_CKG[4] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_WF_PORT_DYN_CKG_SHFT 4 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_HIF_PORT_DYN_CKG_ADDR \ + WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_HIF_PORT_DYN_CKG_MASK \ + 0x00000008 /* DIS_HIF_PORT_DYN_CKG[3] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_HIF_PORT_DYN_CKG_SHFT 3 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CPU_PORT_DYN_CKG_ADDR \ + WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CPU_PORT_DYN_CKG_MASK \ + 0x00000004 /* DIS_CPU_PORT_DYN_CKG[2] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_CPU_PORT_DYN_CKG_SHFT 2 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_PL_DYN_CKG_ADDR \ + WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_PL_DYN_CKG_MASK \ + 0x00000002 /* DIS_PL_DYN_CKG[1] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_PL_DYN_CKG_SHFT 1 +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_FL_DYN_CKG_ADDR \ + WF_PLE_TOP_PLE_MODULE_CKG_DIS_ADDR +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_FL_DYN_CKG_MASK \ + 0x00000001 /* DIS_FL_DYN_CKG[0] */ +#define WF_PLE_TOP_PLE_MODULE_CKG_DIS_DIS_FL_DYN_CKG_SHFT 0 + +/* +* ---INT_N9_ERR_STS_1 (0x820C0000 + 0xd8)--- +* BN0_MDP_TDP_HANG_ERR[0] - (W1C) BN0 MDP TDP FSM hang error +interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* MDP_RDP_HANG_ERR[1] - (W1C) MDP RDP FSM hang error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* BN0_MDP_TIOC_HANG_ERR[2] - (W1C) BN0 MDP TIOC FSM hang error +interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* BN0_MDP_RIOC_HANG_ERR[3] - (W1C) BN0 MDP RIOC FSM hang error +interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* PF_HANG_ERR[4] - (W1C) PF FSM hang error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* SEC0_HANG_ERR[5] - (W1C) SEC 0 FSM hang error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* SEC1_HANG_ERR[6] - (W1C) SEC 1 FSM hang error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* BN1_MDP_TDP_HANG_ERR[7] - (W1C) BN1 MDP TDP FSM hang error +interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* BN1_MDP_TIOC_HANG_ERR[8] - (W1C) BN1 MDP TIOC FSM hang error +interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* BN1_MDP_RIOC_HANG_ERR[9] - (W1C) BN1 MDP RIOC FSM hang error +interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* RESERVED10[11..10] - (RO) Reserved bits +* BN0_RPEDL_ARB_HANG_ERR[12] - (W1C) BN0 PREDL ARB hang error +interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* BN0_PREDL_TXCMD_HANG_ERR[13] - (W1C) BN0 PREDL TXCDM FSM hang error +* interrupt. Avoid unclear error flag, please clear flag when logic +reset. +* BN1_RPEDL_ARB_HANG_ERR[14] - (W1C) BN1 PREDL ARB hang error +interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* BN1_PREDL_TXCMD_HANG_ERR[15] - (W1C) BN1 PREDL TXCDM FSM hang error +* interrupt. Avoid unclear error flag, please clear flag when logic +reset. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_PREDL_TXCMD_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_PREDL_TXCMD_HANG_ERR_MASK \ + 0x00008000 /* BN1_PREDL_TXCMD_HANG_ERR[15] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_PREDL_TXCMD_HANG_ERR_SHFT 15 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_RPEDL_ARB_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_RPEDL_ARB_HANG_ERR_MASK \ + 0x00004000 /* BN1_RPEDL_ARB_HANG_ERR[14] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_RPEDL_ARB_HANG_ERR_SHFT 14 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_PREDL_TXCMD_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_PREDL_TXCMD_HANG_ERR_MASK \ + 0x00002000 /* BN0_PREDL_TXCMD_HANG_ERR[13] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_PREDL_TXCMD_HANG_ERR_SHFT 13 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_RPEDL_ARB_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_RPEDL_ARB_HANG_ERR_MASK \ + 0x00001000 /* BN0_RPEDL_ARB_HANG_ERR[12] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_RPEDL_ARB_HANG_ERR_SHFT 12 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_RIOC_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_RIOC_HANG_ERR_MASK \ + 0x00000200 /* BN1_MDP_RIOC_HANG_ERR[9] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_RIOC_HANG_ERR_SHFT 9 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_TIOC_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_TIOC_HANG_ERR_MASK \ + 0x00000100 /* BN1_MDP_TIOC_HANG_ERR[8] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_TIOC_HANG_ERR_SHFT 8 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_TDP_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_TDP_HANG_ERR_MASK \ + 0x00000080 /* BN1_MDP_TDP_HANG_ERR[7] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN1_MDP_TDP_HANG_ERR_SHFT 7 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_SEC1_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_SEC1_HANG_ERR_MASK \ + 0x00000040 /* SEC1_HANG_ERR[6] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_SEC1_HANG_ERR_SHFT 6 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_SEC0_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_SEC0_HANG_ERR_MASK \ + 0x00000020 /* SEC0_HANG_ERR[5] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_SEC0_HANG_ERR_SHFT 5 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_PF_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_PF_HANG_ERR_MASK \ + 0x00000010 /* PF_HANG_ERR[4] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_PF_HANG_ERR_SHFT 4 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_RIOC_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_RIOC_HANG_ERR_MASK \ + 0x00000008 /* BN0_MDP_RIOC_HANG_ERR[3] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_RIOC_HANG_ERR_SHFT 3 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_TIOC_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_TIOC_HANG_ERR_MASK \ + 0x00000004 /* BN0_MDP_TIOC_HANG_ERR[2] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_TIOC_HANG_ERR_SHFT 2 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_MDP_RDP_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_MDP_RDP_HANG_ERR_MASK \ + 0x00000002 /* MDP_RDP_HANG_ERR[1] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_MDP_RDP_HANG_ERR_SHFT 1 +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_TDP_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_STS_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_TDP_HANG_ERR_MASK \ + 0x00000001 /* BN0_MDP_TDP_HANG_ERR[0] */ +#define WF_PLE_TOP_INT_N9_ERR_STS_1_BN0_MDP_TDP_HANG_ERR_SHFT 0 + +/* +* ---INT_N9_ERR_MASK_1 (0x820C0000 + 0xdc)--- +* EN_BN0_MDP_TDP_HANG_ERR[0] - (RW) Enables Band0 MDP TDP FSM hang +error +interrupt +* EN_MDP_RDP_HANG_ERR[1] - (RW) Enables MDP RDP FSM hang error +interrupt +* EN_BN0_MDP_TIOC_HANG_ERR[2] - (RW) Enables Band0 MDP TIOC FSM hang +error +interrupt +* EN_BN0_MDP_RIOC_HANG_ERR[3] - (RW) Enables Band0 MDP RIOC FSM hang +error +interrupt +* EN_PF_HANG_ERR[4] - (RW) Enables PF FSM hang error interrupt +* EN_SEC0_HANG_ERR[5] - (RW) Enables SEC 0 FSM hang error interrupt +* EN_SEC1_HANG_ERR[6] - (RW) Enables SEC 1 FSM hang error interrupt +* EN_BN1_MDP_TDP_HANG_ERR[7] - (RW) Enables Band1 MDP TDP FSM hang +error +interrupt +* EN_BN1_MDP_TIOC_HANG_ERR[8] - (RW) Enables Band1 MDP TIOC FSM hang +error +interrupt +* EN_BN1_MDP_RIOC_HANG_ERR[9] - (RW) Enables Band1 MDP RIOC FSM hang +error +interrupt +* RESERVED10[11..10] - (RO) Reserved bits +* EN_BN0_PREDL_ARB_HANG_ERR[12] - (RW) Enables Band0 PREDL ARB FSM +* hang error +interrupt +* EN_BN0_PREDL_TXCMD_HANG_ERR[13] - (RW) Enables Band0 PREDL TXCMD +* parser FSM +* hang error interrupt +* EN_BN1_PREDL_ARB_HANG_ERR[14] - (RW) Enables Band1 PREDL ARB FSM +* hang error +interrupt +* EN_BN1_PREDL_TXCMD_HANG_ERR[15] - (RW) Enables Band1 PREDL TXCMD +* parser FSM +* hang error interrupt +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define \ +WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_PREDL_TXCMD_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define \ +WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_PREDL_TXCMD_HANG_ERR_MASK \ + 0x00008000 /* EN_BN1_PREDL_TXCMD_HANG_ERR[15] */ +#define \ +WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_PREDL_TXCMD_HANG_ERR_SHFT \ + 15 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_PREDL_ARB_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_PREDL_ARB_HANG_ERR_MASK \ + 0x00004000 /* EN_BN1_PREDL_ARB_HANG_ERR[14] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_PREDL_ARB_HANG_ERR_SHFT 14 +#define \ +WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_PREDL_TXCMD_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define \ +WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_PREDL_TXCMD_HANG_ERR_MASK \ + 0x00002000 /* EN_BN0_PREDL_TXCMD_HANG_ERR[13] */ +#define \ +WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_PREDL_TXCMD_HANG_ERR_SHFT \ + 13 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_PREDL_ARB_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_PREDL_ARB_HANG_ERR_MASK \ + 0x00001000 /* EN_BN0_PREDL_ARB_HANG_ERR[12] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_PREDL_ARB_HANG_ERR_SHFT 12 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_RIOC_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_RIOC_HANG_ERR_MASK \ + 0x00000200 /* EN_BN1_MDP_RIOC_HANG_ERR[9] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_RIOC_HANG_ERR_SHFT 9 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_TIOC_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_TIOC_HANG_ERR_MASK \ + 0x00000100 /* EN_BN1_MDP_TIOC_HANG_ERR[8] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_TIOC_HANG_ERR_SHFT 8 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_TDP_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_TDP_HANG_ERR_MASK \ + 0x00000080 /* EN_BN1_MDP_TDP_HANG_ERR[7] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN1_MDP_TDP_HANG_ERR_SHFT 7 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_SEC1_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_SEC1_HANG_ERR_MASK \ + 0x00000040 /* EN_SEC1_HANG_ERR[6] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_SEC1_HANG_ERR_SHFT 6 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_SEC0_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_SEC0_HANG_ERR_MASK \ + 0x00000020 /* EN_SEC0_HANG_ERR[5] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_SEC0_HANG_ERR_SHFT 5 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_PF_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_PF_HANG_ERR_MASK \ + 0x00000010 /* EN_PF_HANG_ERR[4] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_PF_HANG_ERR_SHFT 4 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_RIOC_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_RIOC_HANG_ERR_MASK \ + 0x00000008 /* EN_BN0_MDP_RIOC_HANG_ERR[3] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_RIOC_HANG_ERR_SHFT 3 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_TIOC_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_TIOC_HANG_ERR_MASK \ + 0x00000004 /* EN_BN0_MDP_TIOC_HANG_ERR[2] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_TIOC_HANG_ERR_SHFT 2 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_MDP_RDP_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_MDP_RDP_HANG_ERR_MASK \ + 0x00000002 /* EN_MDP_RDP_HANG_ERR[1] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_MDP_RDP_HANG_ERR_SHFT 1 +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_TDP_HANG_ERR_ADDR \ + WF_PLE_TOP_INT_N9_ERR_MASK_1_ADDR +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_TDP_HANG_ERR_MASK \ + 0x00000001 /* EN_BN0_MDP_TDP_HANG_ERR[0] */ +#define WF_PLE_TOP_INT_N9_ERR_MASK_1_EN_BN0_MDP_TDP_HANG_ERR_SHFT 0 + +/* +* ---TO_N9_INT (0x820C0000 + 0xf0)--- +* CR4_CMD[30..0] - (RW) Command for N9 +* TOGGLE[31] - (RW) When this bit is toggled, HW will send +* interrupt to N9. +*/ +#define WF_PLE_TOP_TO_N9_INT_TOGGLE_ADDR WF_PLE_TOP_TO_N9_INT_ADDR +#define WF_PLE_TOP_TO_N9_INT_TOGGLE_MASK 0x80000000 /* TOGGLE[31] */ +#define WF_PLE_TOP_TO_N9_INT_TOGGLE_SHFT 31 +#define WF_PLE_TOP_TO_N9_INT_CR4_CMD_ADDR WF_PLE_TOP_TO_N9_INT_ADDR +#define WF_PLE_TOP_TO_N9_INT_CR4_CMD_MASK \ + 0x7FFFFFFF /* CR4_CMD[30..0] */ +#define WF_PLE_TOP_TO_N9_INT_CR4_CMD_SHFT 0 + +/* +* ---N9_BSS_PS_INT_MASK (0x820C0000 + 0xf4)--- +* EN_BSSID0_NONEMPTY_INT[0] - (RW) Enable control of BSSID0 queue +empty +fall +* EN_BSSID1_NONEMPTY_INT[1] - (RW) Enable control of BSSID1 queue +empty +fall +* EN_BSSID2_NONEMPTY_INT[2] - (RW) Enable control of BSSID2 queue +empty +fall +* EN_BSSID3_NONEMPTY_INT[3] - (RW) Enable control of BSSID3 queue +empty +fall +* RESERVED4[7..4] - (RO) Reserved bits +* EN_BSSID0_EMPTY_INT[8] - (RW) Enable control of BSSID0 queue empty +raise +* EN_BSSID1_EMPTY_INT[9] - (RW) Enable control of BSSID1 queue empty +raise +* EN_BSSID2_EMPTY_INT[10] - (RW) Enable control of BSSID2 queue empty +raise +* EN_BSSID3_EMPTY_INT[11] - (RW) Enable control of BSSID3 queue empty +raise +* RESERVED12[15..12] - (RO) Reserved bits +* EN_BSSID0_ENQ_LMAC_INT[16] - (RW) Enable control of BSSID0 enqueue +interrupt +* EN_BSSID1_ENQ_LMAC_INT[17] - (RW) Enable control of BSSID1 enqueue +interrupt +* EN_BSSID2_ENQ_LMAC_INT[18] - (RW) Enable control of BSSID2 enqueue +interrupt +* EN_BSSID3_ENQ_LMAC_INT[19] - (RW) Enable control of BSSID3 enqueue +interrupt +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_ENQ_LMAC_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_ENQ_LMAC_INT_MASK \ + 0x00080000 /* EN_BSSID3_ENQ_LMAC_INT[19] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_ENQ_LMAC_INT_SHFT 19 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_ENQ_LMAC_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_ENQ_LMAC_INT_MASK \ + 0x00040000 /* EN_BSSID2_ENQ_LMAC_INT[18] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_ENQ_LMAC_INT_SHFT 18 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_ENQ_LMAC_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_ENQ_LMAC_INT_MASK \ + 0x00020000 /* EN_BSSID1_ENQ_LMAC_INT[17] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_ENQ_LMAC_INT_SHFT 17 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_ENQ_LMAC_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_ENQ_LMAC_INT_MASK \ + 0x00010000 /* EN_BSSID0_ENQ_LMAC_INT[16] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_ENQ_LMAC_INT_SHFT 16 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_EMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_EMPTY_INT_MASK \ + 0x00000800 /* EN_BSSID3_EMPTY_INT[11] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_EMPTY_INT_SHFT 11 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_EMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_EMPTY_INT_MASK \ + 0x00000400 /* EN_BSSID2_EMPTY_INT[10] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_EMPTY_INT_SHFT 10 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_EMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_EMPTY_INT_MASK \ + 0x00000200 /* EN_BSSID1_EMPTY_INT[9] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_EMPTY_INT_SHFT 9 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_EMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_EMPTY_INT_MASK \ + 0x00000100 /* EN_BSSID0_EMPTY_INT[8] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_EMPTY_INT_SHFT 8 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_NONEMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_NONEMPTY_INT_MASK \ + 0x00000008 /* EN_BSSID3_NONEMPTY_INT[3] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID3_NONEMPTY_INT_SHFT 3 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_NONEMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_NONEMPTY_INT_MASK \ + 0x00000004 /* EN_BSSID2_NONEMPTY_INT[2] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID2_NONEMPTY_INT_SHFT 2 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_NONEMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_NONEMPTY_INT_MASK \ + 0x00000002 /* EN_BSSID1_NONEMPTY_INT[1] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID1_NONEMPTY_INT_SHFT 1 +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_NONEMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_MASK_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_NONEMPTY_INT_MASK \ + 0x00000001 /* EN_BSSID0_NONEMPTY_INT[0] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_MASK_EN_BSSID0_NONEMPTY_INT_SHFT 0 + +/* +* ---N9_BSS_PS_INT_STS (0x820C0000 + 0xf8)--- +* BSSID0_NONEMPTY_INT[0] - (W1C) BSSID0 queue empty fall interrupt +status +* BSSID1_NONEMPTY_INT[1] - (W1C) BSSID1 queue empty fall interrupt +status +* BSSID2_NONEMPTY_INT[2] - (W1C) BSSID2 queue empty fall interrupt +status +* BSSID3_NONEMPTY_INT[3] - (W1C) BSSID3 queue empty fall interrupt +status +* RESERVED4[7..4] - (RO) Reserved bits +* BSSID0_EMPTY_INT[8] - (W1C) BSSID0 queue empty raise interrupt +status +* BSSID1_EMPTY_INT[9] - (W1C) BSSID1 queue empty raise interrupt +status +* BSSID2_EMPTY_INT[10] - (W1C) BSSID2 queue empty raise interrupt +status +* BSSID3_EMPTY_INT[11] - (W1C) BSSID3 queue empty raise interrupt +status +* RESERVED12[15..12] - (RO) Reserved bits +* BSSID0_ENQ_LMAC_INT[16] - (W1C) BSSID0 enqueue interrupt status +* BSSID1_ENQ_LMAC_INT[17] - (W1C) BSSID1 enqueue interrupt status +* BSSID2_ENQ_LMAC_INT[18] - (W1C) BSSID2 enqueue interrupt status +* BSSID3_ENQ_LMAC_INT[19] - (W1C) BSSID3 enqueue interrupt status +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_ENQ_LMAC_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_ENQ_LMAC_INT_MASK \ + 0x00080000 /* BSSID3_ENQ_LMAC_INT[19] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_ENQ_LMAC_INT_SHFT 19 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_ENQ_LMAC_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_ENQ_LMAC_INT_MASK \ + 0x00040000 /* BSSID2_ENQ_LMAC_INT[18] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_ENQ_LMAC_INT_SHFT 18 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_ENQ_LMAC_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_ENQ_LMAC_INT_MASK \ + 0x00020000 /* BSSID1_ENQ_LMAC_INT[17] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_ENQ_LMAC_INT_SHFT 17 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_ENQ_LMAC_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_ENQ_LMAC_INT_MASK \ + 0x00010000 /* BSSID0_ENQ_LMAC_INT[16] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_ENQ_LMAC_INT_SHFT 16 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_EMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_EMPTY_INT_MASK \ + 0x00000800 /* BSSID3_EMPTY_INT[11] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_EMPTY_INT_SHFT 11 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_EMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_EMPTY_INT_MASK \ + 0x00000400 /* BSSID2_EMPTY_INT[10] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_EMPTY_INT_SHFT 10 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_EMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_EMPTY_INT_MASK \ + 0x00000200 /* BSSID1_EMPTY_INT[9] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_EMPTY_INT_SHFT 9 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_EMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_EMPTY_INT_MASK \ + 0x00000100 /* BSSID0_EMPTY_INT[8] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_EMPTY_INT_SHFT 8 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_NONEMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_NONEMPTY_INT_MASK \ + 0x00000008 /* BSSID3_NONEMPTY_INT[3] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID3_NONEMPTY_INT_SHFT 3 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_NONEMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_NONEMPTY_INT_MASK \ + 0x00000004 /* BSSID2_NONEMPTY_INT[2] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID2_NONEMPTY_INT_SHFT 2 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_NONEMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_NONEMPTY_INT_MASK \ + 0x00000002 /* BSSID1_NONEMPTY_INT[1] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID1_NONEMPTY_INT_SHFT 1 +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_NONEMPTY_INT_ADDR \ + WF_PLE_TOP_N9_BSS_PS_INT_STS_ADDR +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_NONEMPTY_INT_MASK \ + 0x00000001 /* BSSID0_NONEMPTY_INT[0] */ +#define WF_PLE_TOP_N9_BSS_PS_INT_STS_BSSID0_NONEMPTY_INT_SHFT 0 + +/* +* ---FREEPG_CNT (0x820C0000 + 0x100)--- +* FREEPG_CNT[11..0] - (RO) Total page number of free +* RESERVED12[15..12] - (RO) Reserved bits +* FFA_CNT[27..16] - (RO) Free page numbers of free for all +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FREEPG_CNT_FFA_CNT_ADDR WF_PLE_TOP_FREEPG_CNT_ADDR +#define WF_PLE_TOP_FREEPG_CNT_FFA_CNT_MASK \ + 0x0FFF0000 /* FFA_CNT[27..16] */ +#define WF_PLE_TOP_FREEPG_CNT_FFA_CNT_SHFT 16 +#define WF_PLE_TOP_FREEPG_CNT_FREEPG_CNT_ADDR \ + WF_PLE_TOP_FREEPG_CNT_ADDR +#define WF_PLE_TOP_FREEPG_CNT_FREEPG_CNT_MASK \ + 0x00000FFF /* FREEPG_CNT[11..0] */ +#define WF_PLE_TOP_FREEPG_CNT_FREEPG_CNT_SHFT 0 + +/* +* ---FREEPG_HEAD_TAIL (0x820C0000 + 0x104)--- +* FREEPG_HEAD[11..0] - (RO) Head page of free page list +* RESERVED12[15..12] - (RO) Reserved bits +* FREEPG_TAIL[27..16] - (RO) Tail page of free page list +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_ADDR \ + WF_PLE_TOP_FREEPG_HEAD_TAIL_ADDR +#define WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_MASK \ + 0x0FFF0000 /* FREEPG_TAIL[27..16] */ +#define WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_SHFT 16 +#define WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_ADDR \ + WF_PLE_TOP_FREEPG_HEAD_TAIL_ADDR +#define WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_MASK \ + 0x00000FFF /* FREEPG_HEAD[11..0] */ +#define WF_PLE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_SHFT 0 + +/* +* ---PG_HIF_GROUP (0x820C0000 + 0x110)--- +* HIF_MIN_QUOTA[11..0] - (RW) Min. quota of HIF group +* Set the quota before release PLE logic +* reset ,and must not be changed after release logic reset. +* RESERVED12[15..12] - (RO) Reserved bits +* HIF_MAX_QUOTA[27..16] - (RW) Max. quota of HIF group +* Set up the quota before releasing PLE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PG_HIF_GROUP_HIF_MAX_QUOTA_ADDR \ + WF_PLE_TOP_PG_HIF_GROUP_ADDR +#define WF_PLE_TOP_PG_HIF_GROUP_HIF_MAX_QUOTA_MASK \ + 0x0FFF0000 /* HIF_MAX_QUOTA[27..16] */ +#define WF_PLE_TOP_PG_HIF_GROUP_HIF_MAX_QUOTA_SHFT 16 +#define WF_PLE_TOP_PG_HIF_GROUP_HIF_MIN_QUOTA_ADDR \ + WF_PLE_TOP_PG_HIF_GROUP_ADDR +#define WF_PLE_TOP_PG_HIF_GROUP_HIF_MIN_QUOTA_MASK \ + 0x00000FFF /* HIF_MIN_QUOTA[11..0] */ +#define WF_PLE_TOP_PG_HIF_GROUP_HIF_MIN_QUOTA_SHFT 0 + +/* +* ---HIF_PG_INFO (0x820C0000 + 0x114)--- +* HIF_RSV_CNT[11..0] - (RO) Reserved pages of HIF group +* RESERVED12[15..12] - (RO) Reserved bits +* HIF_SRC_CNT[27..16] - (RO) Used pages of HIF group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_HIF_PG_INFO_HIF_SRC_CNT_ADDR \ + WF_PLE_TOP_HIF_PG_INFO_ADDR +#define WF_PLE_TOP_HIF_PG_INFO_HIF_SRC_CNT_MASK \ + 0x0FFF0000 /* HIF_SRC_CNT[27..16] */ +#define WF_PLE_TOP_HIF_PG_INFO_HIF_SRC_CNT_SHFT 16 +#define WF_PLE_TOP_HIF_PG_INFO_HIF_RSV_CNT_ADDR \ + WF_PLE_TOP_HIF_PG_INFO_ADDR +#define WF_PLE_TOP_HIF_PG_INFO_HIF_RSV_CNT_MASK \ + 0x00000FFF /* HIF_RSV_CNT[11..0] */ +#define WF_PLE_TOP_HIF_PG_INFO_HIF_RSV_CNT_SHFT 0 + +/* +* ---PG_HIF_WMTXD_GROUP (0x820C0000 + 0x118)--- +* HIF_WMTXD_MIN_QUOTA[11..0] - (RW) Min. quota of HIF WMCPU TXD group +* Set the quota before release PLE logic +* reset ,and must not be changed after release logic reset. +* RESERVED12[15..12] - (RO) Reserved bits +* HIF_WMTXD_MAX_QUOTA[27..16] - (RW) Max. quota of HIF WMCPU TXD group +* Set up the quota before releasing PLE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PG_HIF_WMTXD_GROUP_HIF_WMTXD_MAX_QUOTA_ADDR \ + WF_PLE_TOP_PG_HIF_WMTXD_GROUP_ADDR +#define WF_PLE_TOP_PG_HIF_WMTXD_GROUP_HIF_WMTXD_MAX_QUOTA_MASK \ + 0x0FFF0000 /* HIF_WMTXD_MAX_QUOTA[27..16] */ +#define WF_PLE_TOP_PG_HIF_WMTXD_GROUP_HIF_WMTXD_MAX_QUOTA_SHFT 16 +#define WF_PLE_TOP_PG_HIF_WMTXD_GROUP_HIF_WMTXD_MIN_QUOTA_ADDR \ + WF_PLE_TOP_PG_HIF_WMTXD_GROUP_ADDR +#define WF_PLE_TOP_PG_HIF_WMTXD_GROUP_HIF_WMTXD_MIN_QUOTA_MASK \ + 0x00000FFF /* HIF_WMTXD_MIN_QUOTA[11..0] */ +#define WF_PLE_TOP_PG_HIF_WMTXD_GROUP_HIF_WMTXD_MIN_QUOTA_SHFT 0 + +/* +* ---HIF_WMTXD_PG_INFO (0x820C0000 + 0x11C)--- +* HIF_WMTXD_RSV_CNT[11..0] - (RO) Reserved pages of HIF WMCPU TXD +group +* RESERVED12[15..12] - (RO) Reserved bits +* HIF_WMTXD_SRC_CNT[27..16] - (RO) Used pages of HIF WMCPU TXD group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_HIF_WMTXD_PG_INFO_HIF_WMTXD_SRC_CNT_ADDR \ + WF_PLE_TOP_HIF_WMTXD_PG_INFO_ADDR +#define WF_PLE_TOP_HIF_WMTXD_PG_INFO_HIF_WMTXD_SRC_CNT_MASK \ + 0x0FFF0000 /* HIF_WMTXD_SRC_CNT[27..16] */ +#define WF_PLE_TOP_HIF_WMTXD_PG_INFO_HIF_WMTXD_SRC_CNT_SHFT 16 +#define WF_PLE_TOP_HIF_WMTXD_PG_INFO_HIF_WMTXD_RSV_CNT_ADDR \ + WF_PLE_TOP_HIF_WMTXD_PG_INFO_ADDR +#define WF_PLE_TOP_HIF_WMTXD_PG_INFO_HIF_WMTXD_RSV_CNT_MASK \ + 0x00000FFF /* HIF_WMTXD_RSV_CNT[11..0] */ +#define WF_PLE_TOP_HIF_WMTXD_PG_INFO_HIF_WMTXD_RSV_CNT_SHFT 0 + +/* +* ---PG_HIF_TXCMD_GROUP (0x820C0000 + 0x120)--- +* HIF_TXCMD_MIN_QUOTA[11..0] - (RW) Min. quota of HIF TXCMD group +* Set the quota before release PLE logic +* reset ,and must not be changed after release logic reset. +* RESERVED12[15..12] - (RO) Reserved bits +* HIF_TXCMD_MAX_QUOTA[27..16] - (RW) Max. quota of HIF TXCMD group +* Set up the quota before releasing PLE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MAX_QUOTA_ADDR \ + WF_PLE_TOP_PG_HIF_TXCMD_GROUP_ADDR +#define WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MAX_QUOTA_MASK \ + 0x0FFF0000 /* HIF_TXCMD_MAX_QUOTA[27..16] */ +#define WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MAX_QUOTA_SHFT 16 +#define WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MIN_QUOTA_ADDR \ + WF_PLE_TOP_PG_HIF_TXCMD_GROUP_ADDR +#define WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MIN_QUOTA_MASK \ + 0x00000FFF /* HIF_TXCMD_MIN_QUOTA[11..0] */ +#define WF_PLE_TOP_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MIN_QUOTA_SHFT 0 + +/* +* ---HIF_TXCMD_PG_INFO (0x820C0000 + 0x124)--- +* HIF_TXCMD_RSV_CNT[11..0] - (RO) Reserved pages of HIF TXCMD group +* RESERVED12[15..12] - (RO) Reserved bits +* HIF_TXCMD_SRC_CNT[27..16] - (RO) Used pages of HIF TXCMD group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_SRC_CNT_ADDR \ + WF_PLE_TOP_HIF_TXCMD_PG_INFO_ADDR +#define WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_SRC_CNT_MASK \ + 0x0FFF0000 /* HIF_TXCMD_SRC_CNT[27..16] */ +#define WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_SRC_CNT_SHFT 16 +#define WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_RSV_CNT_ADDR \ + WF_PLE_TOP_HIF_TXCMD_PG_INFO_ADDR +#define WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_RSV_CNT_MASK \ + 0x00000FFF /* HIF_TXCMD_RSV_CNT[11..0] */ +#define WF_PLE_TOP_HIF_TXCMD_PG_INFO_HIF_TXCMD_RSV_CNT_SHFT 0 + +/* +* ---TWT_TX_CTRL0 (0x820C0000 + 0x130)--- +* en_twt_stop_tx_ctrl_0[0] - (RW) Enable TWT non-active period TX control +function. +* en_twt_stop_tx_ctrl_1[1] - (RW) Enable TWT non-active period TX control +function. +* en_twt_stop_tx_ctrl_2[2] - (RW) Enable TWT non-active period TX control +function. +* en_twt_stop_tx_ctrl_3[3] - (RW) Enable TWT non-active period TX control +function. +* RESERVED4[31..4] - (RO) Reserved bits +*/ + +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_3_ADDR \ + WF_PLE_TOP_TWT_TX_CTRL0_ADDR +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_3_MASK \ + 0x00000008 /* en_twt_stop_tx_ctrl_3[3] */ +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_3_SHFT 3 +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_2_ADDR \ + WF_PLE_TOP_TWT_TX_CTRL0_ADDR +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_2_MASK \ + 0x00000004 /* en_twt_stop_tx_ctrl_2[2] */ +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_2_SHFT 2 +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_1_ADDR \ + WF_PLE_TOP_TWT_TX_CTRL0_ADDR +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_1_MASK \ + 0x00000002 /* en_twt_stop_tx_ctrl_1[1] */ +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_1_SHFT 1 +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_0_ADDR \ + WF_PLE_TOP_TWT_TX_CTRL0_ADDR +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_0_MASK \ + 0x00000001 /* en_twt_stop_tx_ctrl_0[0] */ +#define WF_PLE_TOP_TWT_TX_CTRL0_en_twt_stop_tx_ctrl_0_SHFT 0 + +/* +* ---PLE_FUNC_CTRL_0 (0x820C0000 + 0x140)--- +* MACTX_REQ_DEASSERT[0] - (RW) Enable of DeAsser MACTX REQ.(Normal +* operation must be zero.) +* MACTX_ABORT_DEASSERT[1] - (RW) Enable of DeAsser MACTX ABORT.(Normal +* operation must be zero.) +* MPDU_DONE_CNT_IN_NO_TX_REQ[2] - (RW) MPDU done mode for LMAC no TX +request +* MPDU_DONE_CNT_IN_NO_ADD[3] - (RW) MPDU done mode for LMAC no add +* ACK_LMAC_NO_FID_ADD[4] - (RW) MACTX ack mode for LMAC no add any fid +* for TX +* RESERVED5[5] - (RO) Reserved bits +* DIS_STA_RLS_TO_1F[6] - (RW) Release port setting of disable STA +function +* RESERVED7[7] - (RO) Reserved bits +* MACTX_REQ_ASSERT[8] - (RW) Enable of Asser MACTX REQ.(Normal +* operation must be zero.) +* MACTX_ABORT_ASSERT[9] - (RW) Enable of Asser MACTX ABORT.(Normal +* operation must be zero.) +* RESERVED10[21..10] - (RO) Reserved bits +* DIS_AUTORATE_TXP_REQ[22] - (RW) Disable auto rate TXP request +function +* LATER_PKT_PRE_CUT_1US[23] - (RW) Pre cut 1us air time for later +packet. +* TXP_REQ_CNTDOWN_TH[27..24] - (RW) Threshold of air time count down +* for TXP +request +* TXP_REQ_HSPEED_DL_NUM[29..28] - (RW) Packet number of high speed TXP +request +* issue, by pre-cut more micro-second +* TXP_REQ_HSPEED_CUT_US[31..30] - (RW) Number of pre-cut micro-second +* for high +* speed packet +*/ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_HSPEED_CUT_US_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_HSPEED_CUT_US_MASK \ + 0xC0000000 /* TXP_REQ_HSPEED_CUT_US[31..30] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_HSPEED_CUT_US_SHFT 30 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_HSPEED_DL_NUM_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_HSPEED_DL_NUM_MASK \ + 0x30000000 /* TXP_REQ_HSPEED_DL_NUM[29..28] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_HSPEED_DL_NUM_SHFT 28 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_CNTDOWN_TH_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_CNTDOWN_TH_MASK \ + 0x0F000000 /* TXP_REQ_CNTDOWN_TH[27..24] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_TXP_REQ_CNTDOWN_TH_SHFT 24 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_LATER_PKT_PRE_CUT_1US_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_LATER_PKT_PRE_CUT_1US_MASK \ + 0x00800000 /* LATER_PKT_PRE_CUT_1US[23] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_LATER_PKT_PRE_CUT_1US_SHFT 23 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_DIS_AUTORATE_TXP_REQ_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_DIS_AUTORATE_TXP_REQ_MASK \ + 0x00400000 /* DIS_AUTORATE_TXP_REQ[22] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_DIS_AUTORATE_TXP_REQ_SHFT 22 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_ABORT_ASSERT_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_ABORT_ASSERT_MASK \ + 0x00000200 /* MACTX_ABORT_ASSERT[9] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_ABORT_ASSERT_SHFT 9 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_REQ_ASSERT_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_REQ_ASSERT_MASK \ + 0x00000100 /* MACTX_REQ_ASSERT[8] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_REQ_ASSERT_SHFT 8 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_DIS_STA_RLS_TO_1F_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_DIS_STA_RLS_TO_1F_MASK \ + 0x00000040 /* DIS_STA_RLS_TO_1F[6] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_DIS_STA_RLS_TO_1F_SHFT 6 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_ACK_LMAC_NO_FID_ADD_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_ACK_LMAC_NO_FID_ADD_MASK \ + 0x00000010 /* ACK_LMAC_NO_FID_ADD[4] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_ACK_LMAC_NO_FID_ADD_SHFT 4 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MPDU_DONE_CNT_IN_NO_ADD_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MPDU_DONE_CNT_IN_NO_ADD_MASK \ + 0x00000008 /* MPDU_DONE_CNT_IN_NO_ADD[3] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MPDU_DONE_CNT_IN_NO_ADD_SHFT 3 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MPDU_DONE_CNT_IN_NO_TX_REQ_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MPDU_DONE_CNT_IN_NO_TX_REQ_MASK \ + 0x00000004 /* MPDU_DONE_CNT_IN_NO_TX_REQ[2] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MPDU_DONE_CNT_IN_NO_TX_REQ_SHFT 2 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_ABORT_DEASSERT_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_ABORT_DEASSERT_MASK \ + 0x00000002 /* MACTX_ABORT_DEASSERT[1] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_ABORT_DEASSERT_SHFT 1 +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_REQ_DEASSERT_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_0_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_REQ_DEASSERT_MASK \ + 0x00000001 /* MACTX_REQ_DEASSERT[0] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_0_MACTX_REQ_DEASSERT_SHFT 0 + +/* +* ---PLE_FUNC_CTRL_1 (0x820C0000 + 0x144)--- +* RESERVED0[21..0] - (RO) Reserved bits +* PREDL_REQ_NORMAL_PRI[22] - (RW) Pre-download TXP request priority +control +* RESERVED23[31..23] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PLE_FUNC_CTRL_1_PREDL_REQ_NORMAL_PRI_ADDR \ + WF_PLE_TOP_PLE_FUNC_CTRL_1_ADDR +#define WF_PLE_TOP_PLE_FUNC_CTRL_1_PREDL_REQ_NORMAL_PRI_MASK \ + 0x00400000 /* PREDL_REQ_NORMAL_PRI[22] */ +#define WF_PLE_TOP_PLE_FUNC_CTRL_1_PREDL_REQ_NORMAL_PRI_SHFT 22 + +/* +* ---PG_CPU_GROUP (0x820C0000 + 0x150)--- +* CPU_MIN_QUOTA[11..0] - (RW) Min. quota of CPU group +* Set up the quota before releasing PLE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* CPU_MAX_QUOTA[27..16] - (RW) Max. quota of CPU group +* Set up the quota before releasing PLE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PG_CPU_GROUP_CPU_MAX_QUOTA_ADDR \ + WF_PLE_TOP_PG_CPU_GROUP_ADDR +#define WF_PLE_TOP_PG_CPU_GROUP_CPU_MAX_QUOTA_MASK \ + 0x0FFF0000 /* CPU_MAX_QUOTA[27..16] */ +#define WF_PLE_TOP_PG_CPU_GROUP_CPU_MAX_QUOTA_SHFT 16 +#define WF_PLE_TOP_PG_CPU_GROUP_CPU_MIN_QUOTA_ADDR \ + WF_PLE_TOP_PG_CPU_GROUP_ADDR +#define WF_PLE_TOP_PG_CPU_GROUP_CPU_MIN_QUOTA_MASK \ + 0x00000FFF /* CPU_MIN_QUOTA[11..0] */ +#define WF_PLE_TOP_PG_CPU_GROUP_CPU_MIN_QUOTA_SHFT 0 + +/* +* ---CPU_PG_INFO (0x820C0000 + 0x154)--- +* CPU_RSV_CNT[11..0] - (RO) Reserved pages of CPU group +* RESERVED12[15..12] - (RO) Reserved bits +* CPU_SRC_CNT[27..16] - (RO) Used pages of CPU group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CPU_PG_INFO_CPU_SRC_CNT_ADDR \ + WF_PLE_TOP_CPU_PG_INFO_ADDR +#define WF_PLE_TOP_CPU_PG_INFO_CPU_SRC_CNT_MASK \ + 0x0FFF0000 /* CPU_SRC_CNT[27..16] */ +#define WF_PLE_TOP_CPU_PG_INFO_CPU_SRC_CNT_SHFT 16 +#define WF_PLE_TOP_CPU_PG_INFO_CPU_RSV_CNT_ADDR \ + WF_PLE_TOP_CPU_PG_INFO_ADDR +#define WF_PLE_TOP_CPU_PG_INFO_CPU_RSV_CNT_MASK \ + 0x00000FFF /* CPU_RSV_CNT[11..0] */ +#define WF_PLE_TOP_CPU_PG_INFO_CPU_RSV_CNT_SHFT 0 + +/* +* ---PLE_LOG_0 (0x820C0000 + 0x170)--- +* PLE_LOG_0[31..0] - (RW) Log message for SW +*/ +#define WF_PLE_TOP_PLE_LOG_0_PLE_LOG_0_ADDR WF_PLE_TOP_PLE_LOG_0_ADDR +#define WF_PLE_TOP_PLE_LOG_0_PLE_LOG_0_MASK \ + 0xFFFFFFFF /* PLE_LOG_0[31..0] */ +#define WF_PLE_TOP_PLE_LOG_0_PLE_LOG_0_SHFT 0 + +/* +* ---PLE_LOG_1 (0x820C0000 + 0x174)--- +* PLE_LOG_1[31..0] - (RW) Log message for SW +*/ +#define WF_PLE_TOP_PLE_LOG_1_PLE_LOG_1_ADDR WF_PLE_TOP_PLE_LOG_1_ADDR +#define WF_PLE_TOP_PLE_LOG_1_PLE_LOG_1_MASK \ + 0xFFFFFFFF /* PLE_LOG_1[31..0] */ +#define WF_PLE_TOP_PLE_LOG_1_PLE_LOG_1_SHFT 0 + +/* +* ---PLE_LOG_2 (0x820C0000 + 0x178)--- +* PLE_LOG_2[31..0] - (RW) Log message for SW +*/ +#define WF_PLE_TOP_PLE_LOG_2_PLE_LOG_2_ADDR WF_PLE_TOP_PLE_LOG_2_ADDR +#define WF_PLE_TOP_PLE_LOG_2_PLE_LOG_2_MASK \ + 0xFFFFFFFF /* PLE_LOG_2[31..0] */ +#define WF_PLE_TOP_PLE_LOG_2_PLE_LOG_2_SHFT 0 + +/* +* ---PLE_LOG_3 (0x820C0000 + 0x17c)--- +* PLE_LOG_3[31..0] - (RW) Log message for SW +*/ +#define WF_PLE_TOP_PLE_LOG_3_PLE_LOG_3_ADDR WF_PLE_TOP_PLE_LOG_3_ADDR +#define WF_PLE_TOP_PLE_LOG_3_PLE_LOG_3_MASK \ + 0xFFFFFFFF /* PLE_LOG_3[31..0] */ +#define WF_PLE_TOP_PLE_LOG_3_PLE_LOG_3_SHFT 0 + +/* +* ---WMMAC_PGCNT_0 (0x820C0000 + 0x180)--- +* WMMAC_00_PGCNT[11..0] - (RO) WMMAC 00 used page count +* RESERVED12[15..12] - (RO) Reserved bits +* WMMAC_01_PGCNT[27..16] - (RO) WMMAC 01 used page count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_WMMAC_PGCNT_0_WMMAC_01_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_0_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_0_WMMAC_01_PGCNT_MASK \ + 0x0FFF0000 /* WMMAC_01_PGCNT[27..16] */ +#define WF_PLE_TOP_WMMAC_PGCNT_0_WMMAC_01_PGCNT_SHFT 16 +#define WF_PLE_TOP_WMMAC_PGCNT_0_WMMAC_00_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_0_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_0_WMMAC_00_PGCNT_MASK \ + 0x00000FFF /* WMMAC_00_PGCNT[11..0] */ +#define WF_PLE_TOP_WMMAC_PGCNT_0_WMMAC_00_PGCNT_SHFT 0 + +/* +* ---WMMAC_PGCNT_1 (0x820C0000 + 0x184)--- +* WMMAC_02_PGCNT[11..0] - (RO) WMMAC 02 used page count +* RESERVED12[15..12] - (RO) Reserved bits +* WMMAC_03_PGCNT[27..16] - (RO) WMMAC 03 used page count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_WMMAC_PGCNT_1_WMMAC_03_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_1_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_1_WMMAC_03_PGCNT_MASK \ + 0x0FFF0000 /* WMMAC_03_PGCNT[27..16] */ +#define WF_PLE_TOP_WMMAC_PGCNT_1_WMMAC_03_PGCNT_SHFT 16 +#define WF_PLE_TOP_WMMAC_PGCNT_1_WMMAC_02_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_1_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_1_WMMAC_02_PGCNT_MASK \ + 0x00000FFF /* WMMAC_02_PGCNT[11..0] */ +#define WF_PLE_TOP_WMMAC_PGCNT_1_WMMAC_02_PGCNT_SHFT 0 + +/* +* ---WMMAC_PGCNT_2 (0x820C0000 + 0x188)--- +* WMMAC_10_PGCNT[11..0] - (RO) WMMAC 10 used page count +* RESERVED12[15..12] - (RO) Reserved bits +* WMMAC_11_PGCNT[27..16] - (RO) WMMAC 11 used page count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_WMMAC_PGCNT_2_WMMAC_11_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_2_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_2_WMMAC_11_PGCNT_MASK \ + 0x0FFF0000 /* WMMAC_11_PGCNT[27..16] */ +#define WF_PLE_TOP_WMMAC_PGCNT_2_WMMAC_11_PGCNT_SHFT 16 +#define WF_PLE_TOP_WMMAC_PGCNT_2_WMMAC_10_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_2_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_2_WMMAC_10_PGCNT_MASK \ + 0x00000FFF /* WMMAC_10_PGCNT[11..0] */ +#define WF_PLE_TOP_WMMAC_PGCNT_2_WMMAC_10_PGCNT_SHFT 0 + +/* +* ---WMMAC_PGCNT_3 (0x820C0000 + 0x18c)--- +* WMMAC_12_PGCNT[11..0] - (RO) WMMAC 12 used page count +* RESERVED12[15..12] - (RO) Reserved bits +* WMMAC_13_PGCNT[27..16] - (RO) WMMAC 13 used page count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_WMMAC_PGCNT_3_WMMAC_13_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_3_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_3_WMMAC_13_PGCNT_MASK \ + 0x0FFF0000 /* WMMAC_13_PGCNT[27..16] */ +#define WF_PLE_TOP_WMMAC_PGCNT_3_WMMAC_13_PGCNT_SHFT 16 +#define WF_PLE_TOP_WMMAC_PGCNT_3_WMMAC_12_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_3_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_3_WMMAC_12_PGCNT_MASK \ + 0x00000FFF /* WMMAC_12_PGCNT[11..0] */ +#define WF_PLE_TOP_WMMAC_PGCNT_3_WMMAC_12_PGCNT_SHFT 0 + +/* +* ---WMMAC_PGCNT_4 (0x820C0000 + 0x190)--- +* WMMAC_20_PGCNT[11..0] - (RO) WMMAC 20 used page count +* RESERVED12[15..12] - (RO) Reserved bits +* WMMAC_21_PGCNT[27..16] - (RO) WMMAC 21 used page count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_WMMAC_PGCNT_4_WMMAC_21_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_4_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_4_WMMAC_21_PGCNT_MASK \ + 0x0FFF0000 /* WMMAC_21_PGCNT[27..16] */ +#define WF_PLE_TOP_WMMAC_PGCNT_4_WMMAC_21_PGCNT_SHFT 16 +#define WF_PLE_TOP_WMMAC_PGCNT_4_WMMAC_20_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_4_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_4_WMMAC_20_PGCNT_MASK \ + 0x00000FFF /* WMMAC_20_PGCNT[11..0] */ +#define WF_PLE_TOP_WMMAC_PGCNT_4_WMMAC_20_PGCNT_SHFT 0 + +/* +* ---WMMAC_PGCNT_5 (0x820C0000 + 0x194)--- +* WMMAC_22_PGCNT[11..0] - (RO) WMMAC 22 used page count +* RESERVED12[15..12] - (RO) Reserved bits +* WMMAC_23_PGCNT[27..16] - (RO) WMMAC 23 used page count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_WMMAC_PGCNT_5_WMMAC_23_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_5_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_5_WMMAC_23_PGCNT_MASK \ + 0x0FFF0000 /* WMMAC_23_PGCNT[27..16] */ +#define WF_PLE_TOP_WMMAC_PGCNT_5_WMMAC_23_PGCNT_SHFT 16 +#define WF_PLE_TOP_WMMAC_PGCNT_5_WMMAC_22_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_5_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_5_WMMAC_22_PGCNT_MASK \ + 0x00000FFF /* WMMAC_22_PGCNT[11..0] */ +#define WF_PLE_TOP_WMMAC_PGCNT_5_WMMAC_22_PGCNT_SHFT 0 + +/* +* ---WMMAC_PGCNT_6 (0x820C0000 + 0x198)--- +* WMMAC_30_PGCNT[11..0] - (RO) WMMAC 30 used page count +* RESERVED12[15..12] - (RO) Reserved bits +* WMMAC_31_PGCNT[27..16] - (RO) WMMAC 31 used page count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_WMMAC_PGCNT_6_WMMAC_31_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_6_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_6_WMMAC_31_PGCNT_MASK \ + 0x0FFF0000 /* WMMAC_31_PGCNT[27..16] */ +#define WF_PLE_TOP_WMMAC_PGCNT_6_WMMAC_31_PGCNT_SHFT 16 +#define WF_PLE_TOP_WMMAC_PGCNT_6_WMMAC_30_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_6_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_6_WMMAC_30_PGCNT_MASK \ + 0x00000FFF /* WMMAC_30_PGCNT[11..0] */ +#define WF_PLE_TOP_WMMAC_PGCNT_6_WMMAC_30_PGCNT_SHFT 0 + +/* +* ---WMMAC_PGCNT_7 (0x820C0000 + 0x19c)--- +* WMMAC_32_PGCNT[11..0] - (RO) WMMAC 32 used page count +* RESERVED12[15..12] - (RO) Reserved bits +* WMMAC_33_PGCNT[27..16] - (RO) WMMAC 33 used page count +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_WMMAC_PGCNT_7_WMMAC_33_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_7_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_7_WMMAC_33_PGCNT_MASK \ + 0x0FFF0000 /* WMMAC_33_PGCNT[27..16] */ +#define WF_PLE_TOP_WMMAC_PGCNT_7_WMMAC_33_PGCNT_SHFT 16 +#define WF_PLE_TOP_WMMAC_PGCNT_7_WMMAC_32_PGCNT_ADDR \ + WF_PLE_TOP_WMMAC_PGCNT_7_ADDR +#define WF_PLE_TOP_WMMAC_PGCNT_7_WMMAC_32_PGCNT_MASK \ + 0x00000FFF /* WMMAC_32_PGCNT[11..0] */ +#define WF_PLE_TOP_WMMAC_PGCNT_7_WMMAC_32_PGCNT_SHFT 0 + +/* +* ---RL_BUF_CTRL_0 (0x820C0000 + 0x1A0)--- +* RELAY_BUF_ADDR[11..0] - (RW) Read address of relay buffer +* RESERVED12[30..12] - (RO) Reserved bits +* EXECUTE[31] - (A0) Executes relay buffer read command +*/ +#define WF_PLE_TOP_RL_BUF_CTRL_0_EXECUTE_ADDR \ + WF_PLE_TOP_RL_BUF_CTRL_0_ADDR +#define WF_PLE_TOP_RL_BUF_CTRL_0_EXECUTE_MASK \ + 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_RL_BUF_CTRL_0_EXECUTE_SHFT 31 +#define WF_PLE_TOP_RL_BUF_CTRL_0_RELAY_BUF_ADDR_ADDR \ + WF_PLE_TOP_RL_BUF_CTRL_0_ADDR +#define WF_PLE_TOP_RL_BUF_CTRL_0_RELAY_BUF_ADDR_MASK \ + 0x00000FFF /* RELAY_BUF_ADDR[11..0] */ +#define WF_PLE_TOP_RL_BUF_CTRL_0_RELAY_BUF_ADDR_SHFT 0 + +/* +* ---RL_BUF_CTRL_1 (0x820C0000 + 0x1A4)--- +* PAGE_NUM_0[0] - (RO) Page number[0] of packet +* PKT_LEN[11..1] - (RO) Length of the packet with head page +* being the relay buffer address +* Unit: 32 bytes +* PKT_TAIL_PAGE[23..12] - (RO) Tail page of the packet with head page +* being the relay buffer address +* RESV_GRP_ID[24] - (RO) Group ID of reserved page used by FID +* RESERVED25[25] - (RO) Reserved bits +* PAGE_NUM_1[27..26] - (RO) Page number[2:1] of packet +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_RL_BUF_CTRL_1_PAGE_NUM_1_ADDR \ + WF_PLE_TOP_RL_BUF_CTRL_1_ADDR +#define WF_PLE_TOP_RL_BUF_CTRL_1_PAGE_NUM_1_MASK \ + 0x0C000000 /* PAGE_NUM_1[27..26] */ +#define WF_PLE_TOP_RL_BUF_CTRL_1_PAGE_NUM_1_SHFT 26 +#define WF_PLE_TOP_RL_BUF_CTRL_1_RESV_GRP_ID_ADDR \ + WF_PLE_TOP_RL_BUF_CTRL_1_ADDR +#define WF_PLE_TOP_RL_BUF_CTRL_1_RESV_GRP_ID_MASK \ + 0x01000000 /* RESV_GRP_ID[24] */ +#define WF_PLE_TOP_RL_BUF_CTRL_1_RESV_GRP_ID_SHFT 24 +#define WF_PLE_TOP_RL_BUF_CTRL_1_PKT_TAIL_PAGE_ADDR \ + WF_PLE_TOP_RL_BUF_CTRL_1_ADDR +#define WF_PLE_TOP_RL_BUF_CTRL_1_PKT_TAIL_PAGE_MASK \ + 0x00FFF000 /* PKT_TAIL_PAGE[23..12] */ +#define WF_PLE_TOP_RL_BUF_CTRL_1_PKT_TAIL_PAGE_SHFT 12 +#define WF_PLE_TOP_RL_BUF_CTRL_1_PKT_LEN_ADDR \ + WF_PLE_TOP_RL_BUF_CTRL_1_ADDR +#define WF_PLE_TOP_RL_BUF_CTRL_1_PKT_LEN_MASK \ + 0x00000FFE /* PKT_LEN[11..1] */ +#define WF_PLE_TOP_RL_BUF_CTRL_1_PKT_LEN_SHFT 1 +#define WF_PLE_TOP_RL_BUF_CTRL_1_PAGE_NUM_0_ADDR \ + WF_PLE_TOP_RL_BUF_CTRL_1_ADDR +#define WF_PLE_TOP_RL_BUF_CTRL_1_PAGE_NUM_0_MASK \ + 0x00000001 /* PAGE_NUM_0[0] */ +#define WF_PLE_TOP_RL_BUF_CTRL_1_PAGE_NUM_0_SHFT 0 + +/* +* ---FL_QUE_CTRL_0 (0x820C0000 + 0x1B0)--- +* Q_BUF_WLANID[9..0] - (RW) Address of queue structure buffer +WLANID. +* Q_BUF_PID[11..10] - (RW) Address of queue structure buffer PID +* FL_BUFFER_ADDR[23..12] - (RW) Frame address of read previous +* frame/next frame +* Q_BUF_QID[30..24] - (RW) Address of queue structure buffer QID +* EXECUTE[31] - (A0) Executes frame link and queue structure +* buffer read command +*/ +#define WF_PLE_TOP_FL_QUE_CTRL_0_EXECUTE_ADDR \ + WF_PLE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_0_EXECUTE_MASK \ + 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_FL_QUE_CTRL_0_EXECUTE_SHFT 31 +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_ADDR \ + WF_PLE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_MASK \ + 0x7F000000 /* Q_BUF_QID[30..24] */ +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_SHFT 24 +#define WF_PLE_TOP_FL_QUE_CTRL_0_FL_BUFFER_ADDR_ADDR \ + WF_PLE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_0_FL_BUFFER_ADDR_MASK \ + 0x00FFF000 /* FL_BUFFER_ADDR[23..12] */ +#define WF_PLE_TOP_FL_QUE_CTRL_0_FL_BUFFER_ADDR_SHFT 12 +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_ADDR \ + WF_PLE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_MASK \ + 0x00000C00 /* Q_BUF_PID[11..10] */ +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_SHFT 10 +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_WLANID_ADDR \ + WF_PLE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_WLANID_MASK \ + 0x000003FF /* Q_BUF_WLANID[9..0] */ +#define WF_PLE_TOP_FL_QUE_CTRL_0_Q_BUF_WLANID_SHFT 0 + +/* +* ---FL_QUE_CTRL_1 (0x820C0000 + 0x1B4)--- +* NEXT_FID[11..0] - (RO) Next frame ID of FL_BUFFER_ADDR +* RESERVED12[15..12] - (RO) Reserved bits +* PREV_FID[27..16] - (RO) Previous frame ID of FL_BUFFER_ADDR +* RESERVED28[30..28] - (RO) Reserved bits +* Q_BUF_TGID[31] - (RW) Address of queue structure buffer TGID +*/ +#define WF_PLE_TOP_FL_QUE_CTRL_1_Q_BUF_TGID_ADDR \ + WF_PLE_TOP_FL_QUE_CTRL_1_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_1_Q_BUF_TGID_MASK \ + 0x80000000 /* Q_BUF_TGID[31] */ +#define WF_PLE_TOP_FL_QUE_CTRL_1_Q_BUF_TGID_SHFT 31 +#define WF_PLE_TOP_FL_QUE_CTRL_1_PREV_FID_ADDR \ + WF_PLE_TOP_FL_QUE_CTRL_1_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_1_PREV_FID_MASK \ + 0x0FFF0000 /* PREV_FID[27..16] */ +#define WF_PLE_TOP_FL_QUE_CTRL_1_PREV_FID_SHFT 16 +#define WF_PLE_TOP_FL_QUE_CTRL_1_NEXT_FID_ADDR \ + WF_PLE_TOP_FL_QUE_CTRL_1_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_1_NEXT_FID_MASK \ + 0x00000FFF /* NEXT_FID[11..0] */ +#define WF_PLE_TOP_FL_QUE_CTRL_1_NEXT_FID_SHFT 0 + +/* +* ---FL_QUE_CTRL_2 (0x820C0000 + 0x1B8)--- +* QUEUE_HEAD_FID[11..0] - (RO) Head frame ID of the quest queue +setting +* in 0x01b0[15:0] +* RESERVED12[15..12] - (RO) Reserved bits +* QUEUE_TAIL_FID[27..16] - (RO) Tail frame ID of the quest queue +setting +* in 0x01b0[15:0] +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_ADDR \ + WF_PLE_TOP_FL_QUE_CTRL_2_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_MASK \ + 0x0FFF0000 /* QUEUE_TAIL_FID[27..16] */ +#define WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_SHFT 16 +#define WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_ADDR \ + WF_PLE_TOP_FL_QUE_CTRL_2_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_MASK \ + 0x00000FFF /* QUEUE_HEAD_FID[11..0] */ +#define WF_PLE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_SHFT 0 + +/* +* ---FL_QUE_CTRL_3 (0x820C0000 + 0x1BC)--- +* QUEUE_PKT_NUM[11..0] - (RO) Total packet number of the queue +* setting in 0x1b0[15:0] +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_ADDR \ + WF_PLE_TOP_FL_QUE_CTRL_3_ADDR +#define WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_MASK \ + 0x00000FFF /* QUEUE_PKT_NUM[11..0] */ +#define WF_PLE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_SHFT 0 + +/* +* ---PL_QUE_CTRL_0 (0x820C0000 + 0x1C0)--- +* NEXT_PAGE[11..0] - (RO) Next page of PL_BUFFER_ADDR +* RESERVED12[15..12] - (RO) Reserved bits +* PL_BUFFER_ADDR[27..16] - (RW) Page address of read next page +* RESERVED28[30..28] - (RO) Reserved bits +* EXECUTE[31] - (A0) Executes page link buffer read command +*/ +#define WF_PLE_TOP_PL_QUE_CTRL_0_EXECUTE_ADDR \ + WF_PLE_TOP_PL_QUE_CTRL_0_ADDR +#define WF_PLE_TOP_PL_QUE_CTRL_0_EXECUTE_MASK \ + 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_PL_QUE_CTRL_0_EXECUTE_SHFT 31 +#define WF_PLE_TOP_PL_QUE_CTRL_0_PL_BUFFER_ADDR_ADDR \ + WF_PLE_TOP_PL_QUE_CTRL_0_ADDR +#define WF_PLE_TOP_PL_QUE_CTRL_0_PL_BUFFER_ADDR_MASK \ + 0x0FFF0000 /* PL_BUFFER_ADDR[27..16] */ +#define WF_PLE_TOP_PL_QUE_CTRL_0_PL_BUFFER_ADDR_SHFT 16 +#define WF_PLE_TOP_PL_QUE_CTRL_0_NEXT_PAGE_ADDR \ + WF_PLE_TOP_PL_QUE_CTRL_0_ADDR +#define WF_PLE_TOP_PL_QUE_CTRL_0_NEXT_PAGE_MASK \ + 0x00000FFF /* NEXT_PAGE[11..0] */ +#define WF_PLE_TOP_PL_QUE_CTRL_0_NEXT_PAGE_SHFT 0 + +/* +* ---PLE_DELAY_TX_CTRL (0x820C0000 + 0x1d0)--- +* DELAY_TX_PAGE_TH[11..0] - (RW) Delay TX function is used to delay +TXD +* be LMAC used. If the total pages of TXD large than page threshold, +* the delay TX +* would be released. LMAC would use TXD to TX. +* RESERVED12[15..12] - (RO) Reserved bits +* DELAY_TX_TIMEOUT_TH[23..16] - (RW) Delay TX function is used to +* delay TXD +* be LMAC used. IF no more enqueue event in the time out threshold, +* the delay TX +* would be released. LMAC can use TXD to TX. (unit is 32us). +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PLE_DELAY_TX_CTRL_DELAY_TX_TIMEOUT_TH_ADDR \ + WF_PLE_TOP_PLE_DELAY_TX_CTRL_ADDR +#define WF_PLE_TOP_PLE_DELAY_TX_CTRL_DELAY_TX_TIMEOUT_TH_MASK \ + 0x00FF0000 /* DELAY_TX_TIMEOUT_TH[23..16] */ +#define WF_PLE_TOP_PLE_DELAY_TX_CTRL_DELAY_TX_TIMEOUT_TH_SHFT 16 +#define WF_PLE_TOP_PLE_DELAY_TX_CTRL_DELAY_TX_PAGE_TH_ADDR \ + WF_PLE_TOP_PLE_DELAY_TX_CTRL_ADDR +#define WF_PLE_TOP_PLE_DELAY_TX_CTRL_DELAY_TX_PAGE_TH_MASK \ + 0x00000FFF /* DELAY_TX_PAGE_TH[11..0] */ +#define WF_PLE_TOP_PLE_DELAY_TX_CTRL_DELAY_TX_PAGE_TH_SHFT 0 + +/* +* ---PLE_STATION_REDIR_CTRL (0x820C0000 + 0x1d4)--- +* STA_REDIR_QID[4..0] - (RW) Destitaion queue for Redirection +function. +* RESERVED5[5] - (RO) Reserved bits +* STA_REDIR_PID[7..6] - (RW) Destitaion port for Redirection +function. +* STA_REDIR_PASUE_TXD[8] - (RW) Pause TXD download for avoid race +* condition, when station redirection function turn off. +* RESERVED9[31..9] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_PASUE_TXD_ADDR \ + WF_PLE_TOP_PLE_STATION_REDIR_CTRL_ADDR +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_PASUE_TXD_MASK \ + 0x00000100 /* STA_REDIR_PASUE_TXD[8] */ +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_PASUE_TXD_SHFT 8 +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_PID_ADDR \ + WF_PLE_TOP_PLE_STATION_REDIR_CTRL_ADDR +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_PID_MASK \ + 0x000000C0 /* STA_REDIR_PID[7..6] */ +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_PID_SHFT 6 +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_QID_ADDR \ + WF_PLE_TOP_PLE_STATION_REDIR_CTRL_ADDR +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_QID_MASK \ + 0x0000001F /* STA_REDIR_QID[4..0] */ +#define WF_PLE_TOP_PLE_STATION_REDIR_CTRL_STA_REDIR_QID_SHFT 0 + +/* +* ---MACTX_LENGTH_LIMIT (0x820C0000 + 0x1ec)--- +* MACTX_LENGTH_LIMIT_BAND0[15..0] - (RW) MACTX download length limit +* of band0 +* MACTX_LENGTH_LIMIT_BAND1[31..16] - (RW) MACTX download length limit +* of band1 +*/ +#define WF_PLE_TOP_MACTX_LENGTH_LIMIT_MACTX_LENGTH_LIMIT_BAND1_ADDR \ + WF_PLE_TOP_MACTX_LENGTH_LIMIT_ADDR +#define WF_PLE_TOP_MACTX_LENGTH_LIMIT_MACTX_LENGTH_LIMIT_BAND1_MASK \ + 0xFFFF0000 /* MACTX_LENGTH_LIMIT_BAND1[31..16] */ +#define WF_PLE_TOP_MACTX_LENGTH_LIMIT_MACTX_LENGTH_LIMIT_BAND1_SHFT 16 +#define WF_PLE_TOP_MACTX_LENGTH_LIMIT_MACTX_LENGTH_LIMIT_BAND0_ADDR \ + WF_PLE_TOP_MACTX_LENGTH_LIMIT_ADDR +#define WF_PLE_TOP_MACTX_LENGTH_LIMIT_MACTX_LENGTH_LIMIT_BAND0_MASK \ + 0x0000FFFF /* MACTX_LENGTH_LIMIT_BAND0[15..0] */ +#define WF_PLE_TOP_MACTX_LENGTH_LIMIT_MACTX_LENGTH_LIMIT_BAND0_SHFT 0 + +/* +* ---HIF_ENQ_PKT_NUM (0x820C0000 + 0x1f0)--- +* HIF_ENQ_CPU_PKT_NUM[15..0] - (RO) Packet number of HIF enqueue to +CPU, +* just keep in 16bits. +* HIF_ENQ_LMAC_PKT_NUM[31..16] - (RO) Packet number of HIF enqueue to +LMAC, +* just keep in 16 bits +*/ +#define WF_PLE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_LMAC_PKT_NUM_ADDR \ + WF_PLE_TOP_HIF_ENQ_PKT_NUM_ADDR +#define WF_PLE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_LMAC_PKT_NUM_MASK \ + 0xFFFF0000 /* HIF_ENQ_LMAC_PKT_NUM[31..16] */ +#define WF_PLE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_LMAC_PKT_NUM_SHFT 16 +#define WF_PLE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_CPU_PKT_NUM_ADDR \ + WF_PLE_TOP_HIF_ENQ_PKT_NUM_ADDR +#define WF_PLE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_CPU_PKT_NUM_MASK \ + 0x0000FFFF /* HIF_ENQ_CPU_PKT_NUM[15..0] */ +#define WF_PLE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_CPU_PKT_NUM_SHFT 0 + +/* +* ---CPU_ENQ_PKT_NUM (0x820C0000 + 0x1f4)--- +* CPU_ENQ_LMAC_PKT_NUM[15..0] - (RO) Packet number of CPU enqueue to +LMAC, +* just keep in 16 bits. +* RESV[31..16] - (RO) Reserved +*/ +#define WF_PLE_TOP_CPU_ENQ_PKT_NUM_RESV_ADDR \ + WF_PLE_TOP_CPU_ENQ_PKT_NUM_ADDR +#define WF_PLE_TOP_CPU_ENQ_PKT_NUM_RESV_MASK \ + 0xFFFF0000 /* RESV[31..16] */ +#define WF_PLE_TOP_CPU_ENQ_PKT_NUM_RESV_SHFT 16 +#define WF_PLE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_LMAC_PKT_NUM_ADDR \ + WF_PLE_TOP_CPU_ENQ_PKT_NUM_ADDR +#define WF_PLE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_LMAC_PKT_NUM_MASK \ + 0x0000FFFF /* CPU_ENQ_LMAC_PKT_NUM[15..0] */ +#define WF_PLE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_LMAC_PKT_NUM_SHFT 0 + +/* +* ---RLS_MSDU_PKT_NUM (0x820C0000 + 0x1f8)--- +* RSL_RPT_TXD_NUM[15..0] - (RO) TXD number of host report function +* RSL_MSDUID_NUM[31..16] - (RO) Release MSDU_ID number of host report +function +*/ +#define WF_PLE_TOP_RLS_MSDU_PKT_NUM_RSL_MSDUID_NUM_ADDR \ + WF_PLE_TOP_RLS_MSDU_PKT_NUM_ADDR +#define WF_PLE_TOP_RLS_MSDU_PKT_NUM_RSL_MSDUID_NUM_MASK \ + 0xFFFF0000 /* RSL_MSDUID_NUM[31..16] */ +#define WF_PLE_TOP_RLS_MSDU_PKT_NUM_RSL_MSDUID_NUM_SHFT 16 +#define WF_PLE_TOP_RLS_MSDU_PKT_NUM_RSL_RPT_TXD_NUM_ADDR \ + WF_PLE_TOP_RLS_MSDU_PKT_NUM_ADDR +#define WF_PLE_TOP_RLS_MSDU_PKT_NUM_RSL_RPT_TXD_NUM_MASK \ + 0x0000FFFF /* RSL_RPT_TXD_NUM[15..0] */ +#define WF_PLE_TOP_RLS_MSDU_PKT_NUM_RSL_RPT_TXD_NUM_SHFT 0 + +/* +* ---HOST_REPORT_NUM (0x820C0000 + 0x1fc)--- +* RSL_TXD_NUM[15..0] - (RO) All TXD number of release function, +* include the no host report(not CT) TXD packets. +* HOST_REPORT_NUM[31..16] - (RO) Host report number that be the PSE +* packets carry release MSDU_ID information +*/ +#define WF_PLE_TOP_HOST_REPORT_NUM_HOST_REPORT_NUM_ADDR \ + WF_PLE_TOP_HOST_REPORT_NUM_ADDR +#define WF_PLE_TOP_HOST_REPORT_NUM_HOST_REPORT_NUM_MASK \ + 0xFFFF0000 /* HOST_REPORT_NUM[31..16] */ +#define WF_PLE_TOP_HOST_REPORT_NUM_HOST_REPORT_NUM_SHFT 16 +#define WF_PLE_TOP_HOST_REPORT_NUM_RSL_TXD_NUM_ADDR \ + WF_PLE_TOP_HOST_REPORT_NUM_ADDR +#define WF_PLE_TOP_HOST_REPORT_NUM_RSL_TXD_NUM_MASK \ + 0x0000FFFF /* RSL_TXD_NUM[15..0] */ +#define WF_PLE_TOP_HOST_REPORT_NUM_RSL_TXD_NUM_SHFT 0 + +/* +* ---TXD_QUEUE_EMPTY (0x820C0000 + 0x220)--- +* AC00_EMPTY[0] - (RO) WMM0 AC0 queue empty status +* AC01_EMPTY[1] - (RO) WMM0 AC1 queue empty status +* AC02_EMPTY[2] - (RO) WMM0 AC2 queue empty status +* AC03_EMPTY[3] - (RO) WMM0 AC3 queue empty status +* AC10_EMPTY[4] - (RO) WMM1 AC0 queue empty status +* AC11_EMPTY[5] - (RO) WMM1 AC1 queue empty status +* AC12_EMPTY[6] - (RO) WMM1 AC2 queue empty status +* AC13_EMPTY[7] - (RO) WMM1 AC3 queue empty status +* AC20_EMPTY[8] - (RO) WMM2 AC0 queue empty status +* AC21_EMPTY[9] - (RO) WMM2 AC1 queue empty status +* AC22_EMPTY[10] - (RO) WMM2 AC2 queue empty status +* AC23_EMPTY[11] - (RO) WMM2 AC3 queue empty status +* AC30_EMPTY[12] - (RO) WMM3 AC0 queue empty status +* AC31_EMPTY[13] - (RO) WMM3 AC1 queue empty status +* AC32_EMPTY[14] - (RO) WMM3 AC2 queue empty status +* AC33_EMPTY[15] - (RO) WMM3 AC3 queue empty status +* ALTX_0_EMPTY[16] - (RO) ALTX queue 0 empty status +* BMC_0_EMPTY[17] - (RO) BMC queue 0 empty status +* BCN_0_EMPTY[18] - (RO) BCN queue 0 empty status +* PSMP_0_EMPTY[19] - (RO) PSMP queue 0 empty status +* ALTX_1_EMPTY[20] - (RO) ALTX queue 1 empty status +* BMC_1_EMPTY[21] - (RO) BMC queue 1 empty status +* BCN_1_EMPTY[22] - (RO) BCN queue 1 empty status +* PSMP_1_EMPTY[23] - (RO) PSMP queue 1 empty status +* NAF_EMPTY[24] - (RO) NAF queue empty status +* NBCN_EMPTY[25] - (RO) NBCN queue empty status +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_NBCN_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_NBCN_EMPTY_MASK \ + 0x02000000 /* NBCN_EMPTY[25] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_NBCN_EMPTY_SHFT 25 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_NAF_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_NAF_EMPTY_MASK \ + 0x01000000 /* NAF_EMPTY[24] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_NAF_EMPTY_SHFT 24 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_PSMP_1_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_PSMP_1_EMPTY_MASK \ + 0x00800000 /* PSMP_1_EMPTY[23] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_PSMP_1_EMPTY_SHFT 23 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BCN_1_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BCN_1_EMPTY_MASK \ + 0x00400000 /* BCN_1_EMPTY[22] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BCN_1_EMPTY_SHFT 22 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BMC_1_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BMC_1_EMPTY_MASK \ + 0x00200000 /* BMC_1_EMPTY[21] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BMC_1_EMPTY_SHFT 21 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_ALTX_1_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_ALTX_1_EMPTY_MASK \ + 0x00100000 /* ALTX_1_EMPTY[20] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_ALTX_1_EMPTY_SHFT 20 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_PSMP_0_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_PSMP_0_EMPTY_MASK \ + 0x00080000 /* PSMP_0_EMPTY[19] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_PSMP_0_EMPTY_SHFT 19 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BCN_0_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BCN_0_EMPTY_MASK \ + 0x00040000 /* BCN_0_EMPTY[18] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BCN_0_EMPTY_SHFT 18 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BMC_0_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BMC_0_EMPTY_MASK \ + 0x00020000 /* BMC_0_EMPTY[17] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_BMC_0_EMPTY_SHFT 17 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_ALTX_0_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_ALTX_0_EMPTY_MASK \ + 0x00010000 /* ALTX_0_EMPTY[16] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_ALTX_0_EMPTY_SHFT 16 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC33_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC33_EMPTY_MASK \ + 0x00008000 /* AC33_EMPTY[15] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC33_EMPTY_SHFT 15 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC32_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC32_EMPTY_MASK \ + 0x00004000 /* AC32_EMPTY[14] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC32_EMPTY_SHFT 14 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC31_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC31_EMPTY_MASK \ + 0x00002000 /* AC31_EMPTY[13] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC31_EMPTY_SHFT 13 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC30_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC30_EMPTY_MASK \ + 0x00001000 /* AC30_EMPTY[12] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC30_EMPTY_SHFT 12 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC23_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC23_EMPTY_MASK \ + 0x00000800 /* AC23_EMPTY[11] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC23_EMPTY_SHFT 11 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC22_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC22_EMPTY_MASK \ + 0x00000400 /* AC22_EMPTY[10] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC22_EMPTY_SHFT 10 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC21_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC21_EMPTY_MASK \ + 0x00000200 /* AC21_EMPTY[9] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC21_EMPTY_SHFT 9 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC20_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC20_EMPTY_MASK \ + 0x00000100 /* AC20_EMPTY[8] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC20_EMPTY_SHFT 8 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC13_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC13_EMPTY_MASK \ + 0x00000080 /* AC13_EMPTY[7] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC13_EMPTY_SHFT 7 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC12_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC12_EMPTY_MASK \ + 0x00000040 /* AC12_EMPTY[6] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC12_EMPTY_SHFT 6 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC11_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC11_EMPTY_MASK \ + 0x00000020 /* AC11_EMPTY[5] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC11_EMPTY_SHFT 5 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC10_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC10_EMPTY_MASK \ + 0x00000010 /* AC10_EMPTY[4] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC10_EMPTY_SHFT 4 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC03_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC03_EMPTY_MASK \ + 0x00000008 /* AC03_EMPTY[3] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC03_EMPTY_SHFT 3 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC02_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC02_EMPTY_MASK \ + 0x00000004 /* AC02_EMPTY[2] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC02_EMPTY_SHFT 2 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC01_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC01_EMPTY_MASK \ + 0x00000002 /* AC01_EMPTY[1] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC01_EMPTY_SHFT 1 +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC00_EMPTY_ADDR \ + WF_PLE_TOP_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC00_EMPTY_MASK \ + 0x00000001 /* AC00_EMPTY[0] */ +#define WF_PLE_TOP_TXD_QUEUE_EMPTY_AC00_EMPTY_SHFT 0 + +/* +* ---TXS_BUF_PAUSE (0x820C0000 + 0x224)--- +* EN_PAUSE_AC00_QUEUE[0] - (RW) Pause control of WMM0 AC0 queue. +* EN_PAUSE_AC01_QUEUE[1] - (RW) Pause control of WMM0 AC1 queue. +* EN_PAUSE_AC02_QUEUE[2] - (RW) Pause control of WMM0 AC2 queue. +* EN_PAUSE_AC03_QUEUE[3] - (RW) Pause control of WMM0 AC3 queue. +* EN_PAUSE_AC10_QUEUE[4] - (RW) Pause control of WMM1 AC0 queue. +* EN_PAUSE_AC11_QUEUE[5] - (RW) Pause control of WMM1 AC1 queue. +* EN_PAUSE_AC12_QUEUE[6] - (RW) Pause control of WMM1 AC2 queue. +* EN_PAUSE_AC13_QUEUE[7] - (RW) Pause control of WMM1 AC3 queue. +* EN_PAUSE_AC20_QUEUE[8] - (RW) Pause control of WMM2 AC0 queue. +* EN_PAUSE_AC21_QUEUE[9] - (RW) Pause control of WMM2 AC1 queue. +* EN_PAUSE_AC22_QUEUE[10] - (RW) Pause control of WMM2 AC2 queue. +* EN_PAUSE_AC23_QUEUE[11] - (RW) Pause control of WMM2 AC3 queue. +* EN_PAUSE_AC30_QUEUE[12] - (RW) Pause control of WMM3 AC0 queue. +* EN_PAUSE_AC31_QUEUE[13] - (RW) Pause control of WMM3 AC1 queue. +* EN_PAUSE_AC32_QUEUE[14] - (RW) Pause control of WMM3 AC2 queue. +* EN_PAUSE_AC33_QUEUE[15] - (RW) Pause control of WMM3 AC3 queue. +* EN_PAUSE_ALTX_0_QUEUE[16] - (RW) Pause control of ALTX queue 0. +* EN_PAUSE_BMC_0_QUEUE[17] - (RW) Pause control of BMC queue 0. +* EN_PAUSE_BCN_0_QUEUE[18] - (RW) Pause control of BCN queue 0. +* EN_PAUSE_PSMP_0_QUEUE[19] - (RW) Pause control of PSMP queue 0. +* EN_PAUSE_ALTX_1_QUEUE[20] - (RW) Pause control of ALTX queue 1. +* EN_PAUSE_BMC_1_QUEUE[21] - (RW) Pause control of BMC queue 1. +* EN_PAUSE_BCN_1_QUEUE[22] - (RW) Pause control of BCN queue 1. +* EN_PAUSE_PSMP_1_QUEUE[23] - (RW) Pause control of PSMP queue 1. +* EN_PAUSE_NAF_QUEUE[24] - (RW) Pause control of NAF queue. +* EN_PAUSE_NBCN_QUEUE[25] - (RW) Pause control of NBCN queue. +* RESERVED26[30..26] - (RO) Reserved bits +* PSE_TXS_BUF_VALID[31] - (RO) PSE TXS buffer status. +*/ +#define WF_PLE_TOP_TXS_BUF_PAUSE_PSE_TXS_BUF_VALID_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_PSE_TXS_BUF_VALID_MASK \ + 0x80000000 /* PSE_TXS_BUF_VALID[31] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_PSE_TXS_BUF_VALID_SHFT 31 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_NBCN_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_NBCN_QUEUE_MASK \ + 0x02000000 /* EN_PAUSE_NBCN_QUEUE[25] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_NBCN_QUEUE_SHFT 25 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_NAF_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_NAF_QUEUE_MASK \ + 0x01000000 /* EN_PAUSE_NAF_QUEUE[24] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_NAF_QUEUE_SHFT 24 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_PSMP_1_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_PSMP_1_QUEUE_MASK \ + 0x00800000 /* EN_PAUSE_PSMP_1_QUEUE[23] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_PSMP_1_QUEUE_SHFT 23 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BCN_1_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BCN_1_QUEUE_MASK \ + 0x00400000 /* EN_PAUSE_BCN_1_QUEUE[22] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BCN_1_QUEUE_SHFT 22 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BMC_1_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BMC_1_QUEUE_MASK \ + 0x00200000 /* EN_PAUSE_BMC_1_QUEUE[21] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BMC_1_QUEUE_SHFT 21 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_ALTX_1_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_ALTX_1_QUEUE_MASK \ + 0x00100000 /* EN_PAUSE_ALTX_1_QUEUE[20] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_ALTX_1_QUEUE_SHFT 20 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_PSMP_0_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_PSMP_0_QUEUE_MASK \ + 0x00080000 /* EN_PAUSE_PSMP_0_QUEUE[19] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_PSMP_0_QUEUE_SHFT 19 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BCN_0_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BCN_0_QUEUE_MASK \ + 0x00040000 /* EN_PAUSE_BCN_0_QUEUE[18] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BCN_0_QUEUE_SHFT 18 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BMC_0_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BMC_0_QUEUE_MASK \ + 0x00020000 /* EN_PAUSE_BMC_0_QUEUE[17] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_BMC_0_QUEUE_SHFT 17 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_ALTX_0_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_ALTX_0_QUEUE_MASK \ + 0x00010000 /* EN_PAUSE_ALTX_0_QUEUE[16] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_ALTX_0_QUEUE_SHFT 16 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC33_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC33_QUEUE_MASK \ + 0x00008000 /* EN_PAUSE_AC33_QUEUE[15] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC33_QUEUE_SHFT 15 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC32_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC32_QUEUE_MASK \ + 0x00004000 /* EN_PAUSE_AC32_QUEUE[14] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC32_QUEUE_SHFT 14 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC31_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC31_QUEUE_MASK \ + 0x00002000 /* EN_PAUSE_AC31_QUEUE[13] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC31_QUEUE_SHFT 13 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC30_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC30_QUEUE_MASK \ + 0x00001000 /* EN_PAUSE_AC30_QUEUE[12] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC30_QUEUE_SHFT 12 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC23_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC23_QUEUE_MASK \ + 0x00000800 /* EN_PAUSE_AC23_QUEUE[11] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC23_QUEUE_SHFT 11 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC22_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC22_QUEUE_MASK \ + 0x00000400 /* EN_PAUSE_AC22_QUEUE[10] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC22_QUEUE_SHFT 10 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC21_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC21_QUEUE_MASK \ + 0x00000200 /* EN_PAUSE_AC21_QUEUE[9] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC21_QUEUE_SHFT 9 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC20_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC20_QUEUE_MASK \ + 0x00000100 /* EN_PAUSE_AC20_QUEUE[8] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC20_QUEUE_SHFT 8 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC13_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC13_QUEUE_MASK \ + 0x00000080 /* EN_PAUSE_AC13_QUEUE[7] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC13_QUEUE_SHFT 7 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC12_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC12_QUEUE_MASK \ + 0x00000040 /* EN_PAUSE_AC12_QUEUE[6] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC12_QUEUE_SHFT 6 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC11_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC11_QUEUE_MASK \ + 0x00000020 /* EN_PAUSE_AC11_QUEUE[5] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC11_QUEUE_SHFT 5 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC10_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC10_QUEUE_MASK \ + 0x00000010 /* EN_PAUSE_AC10_QUEUE[4] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC10_QUEUE_SHFT 4 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC03_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC03_QUEUE_MASK \ + 0x00000008 /* EN_PAUSE_AC03_QUEUE[3] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC03_QUEUE_SHFT 3 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC02_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC02_QUEUE_MASK \ + 0x00000004 /* EN_PAUSE_AC02_QUEUE[2] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC02_QUEUE_SHFT 2 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC01_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC01_QUEUE_MASK \ + 0x00000002 /* EN_PAUSE_AC01_QUEUE[1] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC01_QUEUE_SHFT 1 +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC00_QUEUE_ADDR \ + WF_PLE_TOP_TXS_BUF_PAUSE_ADDR +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC00_QUEUE_MASK \ + 0x00000001 /* EN_PAUSE_AC00_QUEUE[0] */ +#define WF_PLE_TOP_TXS_BUF_PAUSE_EN_PAUSE_AC00_QUEUE_SHFT 0 + +/* +* ---NATIVE_TXD_QUEUE_EMPTY (0x820C0000 + 0x228)--- +* AC00_EMPTY[0] - (RO) WMM0 AC0 queue empty status +* AC01_EMPTY[1] - (RO) WMM0 AC1 queue empty status +* AC02_EMPTY[2] - (RO) WMM0 AC2 queue empty status +* AC03_EMPTY[3] - (RO) WMM0 AC3 queue empty status +* AC10_EMPTY[4] - (RO) WMM1 AC0 queue empty status +* AC11_EMPTY[5] - (RO) WMM1 AC1 queue empty status +* AC12_EMPTY[6] - (RO) WMM1 AC2 queue empty status +* AC13_EMPTY[7] - (RO) WMM1 AC3 queue empty status +* AC20_EMPTY[8] - (RO) WMM2 AC0 queue empty status +* AC21_EMPTY[9] - (RO) WMM2 AC1 queue empty status +* AC22_EMPTY[10] - (RO) WMM2 AC2 queue empty status +* AC23_EMPTY[11] - (RO) WMM2 AC3 queue empty status +* AC30_EMPTY[12] - (RO) WMM3 AC0 queue empty status +* AC31_EMPTY[13] - (RO) WMM3 AC1 queue empty status +* AC32_EMPTY[14] - (RO) WMM3 AC2 queue empty status +* AC33_EMPTY[15] - (RO) WMM3 AC3 queue empty status +* ALTX_0_EMPTY[16] - (RO) ALTX queue 0 empty status +* BMC_0_EMPTY[17] - (RO) BMC queue 0 empty status +* BCN_0_EMPTY[18] - (RO) BCN queue 0 empty status +* PSMP_0_EMPTY[19] - (RO) PSMP queue 0 empty status +* ALTX_1_EMPTY[20] - (RO) ALTX queue 1 empty status +* BMC_1_EMPTY[21] - (RO) BMC queue 1 empty status +* BCN_1_EMPTY[22] - (RO) BCN queue 1 empty status +* PSMP_1_EMPTY[23] - (RO) PSMP queue 1 empty status +* NAF_EMPTY[24] - (RO) NAF queue empty status +* NBCN_EMPTY[25] - (RO) NBCN queue empty status +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_NBCN_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_NBCN_EMPTY_MASK \ + 0x02000000 /* NBCN_EMPTY[25] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_NBCN_EMPTY_SHFT 25 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_NAF_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_NAF_EMPTY_MASK \ + 0x01000000 /* NAF_EMPTY[24] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_NAF_EMPTY_SHFT 24 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_PSMP_1_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_PSMP_1_EMPTY_MASK \ + 0x00800000 /* PSMP_1_EMPTY[23] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_PSMP_1_EMPTY_SHFT 23 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BCN_1_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BCN_1_EMPTY_MASK \ + 0x00400000 /* BCN_1_EMPTY[22] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BCN_1_EMPTY_SHFT 22 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BMC_1_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BMC_1_EMPTY_MASK \ + 0x00200000 /* BMC_1_EMPTY[21] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BMC_1_EMPTY_SHFT 21 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ALTX_1_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ALTX_1_EMPTY_MASK \ + 0x00100000 /* ALTX_1_EMPTY[20] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ALTX_1_EMPTY_SHFT 20 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_PSMP_0_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_PSMP_0_EMPTY_MASK \ + 0x00080000 /* PSMP_0_EMPTY[19] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_PSMP_0_EMPTY_SHFT 19 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BCN_0_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BCN_0_EMPTY_MASK \ + 0x00040000 /* BCN_0_EMPTY[18] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BCN_0_EMPTY_SHFT 18 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BMC_0_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BMC_0_EMPTY_MASK \ + 0x00020000 /* BMC_0_EMPTY[17] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_BMC_0_EMPTY_SHFT 17 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ALTX_0_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ALTX_0_EMPTY_MASK \ + 0x00010000 /* ALTX_0_EMPTY[16] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ALTX_0_EMPTY_SHFT 16 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC33_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC33_EMPTY_MASK \ + 0x00008000 /* AC33_EMPTY[15] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC33_EMPTY_SHFT 15 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC32_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC32_EMPTY_MASK \ + 0x00004000 /* AC32_EMPTY[14] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC32_EMPTY_SHFT 14 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC31_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC31_EMPTY_MASK \ + 0x00002000 /* AC31_EMPTY[13] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC31_EMPTY_SHFT 13 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC30_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC30_EMPTY_MASK \ + 0x00001000 /* AC30_EMPTY[12] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC30_EMPTY_SHFT 12 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC23_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC23_EMPTY_MASK \ + 0x00000800 /* AC23_EMPTY[11] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC23_EMPTY_SHFT 11 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC22_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC22_EMPTY_MASK \ + 0x00000400 /* AC22_EMPTY[10] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC22_EMPTY_SHFT 10 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC21_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC21_EMPTY_MASK \ + 0x00000200 /* AC21_EMPTY[9] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC21_EMPTY_SHFT 9 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC20_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC20_EMPTY_MASK \ + 0x00000100 /* AC20_EMPTY[8] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC20_EMPTY_SHFT 8 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC13_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC13_EMPTY_MASK \ + 0x00000080 /* AC13_EMPTY[7] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC13_EMPTY_SHFT 7 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC12_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC12_EMPTY_MASK \ + 0x00000040 /* AC12_EMPTY[6] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC12_EMPTY_SHFT 6 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC11_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC11_EMPTY_MASK \ + 0x00000020 /* AC11_EMPTY[5] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC11_EMPTY_SHFT 5 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC10_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC10_EMPTY_MASK \ + 0x00000010 /* AC10_EMPTY[4] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC10_EMPTY_SHFT 4 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC03_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC03_EMPTY_MASK \ + 0x00000008 /* AC03_EMPTY[3] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC03_EMPTY_SHFT 3 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC02_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC02_EMPTY_MASK \ + 0x00000004 /* AC02_EMPTY[2] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC02_EMPTY_SHFT 2 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC01_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC01_EMPTY_MASK \ + 0x00000002 /* AC01_EMPTY[1] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC01_EMPTY_SHFT 1 +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC00_EMPTY_ADDR \ + WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_ADDR +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC00_EMPTY_MASK \ + 0x00000001 /* AC00_EMPTY[0] */ +#define WF_PLE_TOP_NATIVE_TXD_QUEUE_EMPTY_AC00_EMPTY_SHFT 0 + +/* +* ---UMAC_DBG_CTRL (0x820C0000 + 0x240)--- +* UMAC_DBG_FUNC_SEL[3..0] - (RW) Selects UMAC debug mode +* RESERVED4[7..4] - (RO) Reserved bits +* PLE_DBG_FLAG_A_NIB_EN[11..8] - (RW) Enable control of PLE debug flag +A +nibble +* PLE_DBG_FLAG_B_NIB_EN[15..12] - (RW) Enable control of PLE debug +* flag B +nibble +* PSE_DBG_FLAG_A_NIB_EN[19..16] - (RW) Enable control of PSE debug +* flag A +nibble +* PSE_DBG_FLAG_B_NIB_EN[23..20] - (RW) Enable control of PSE debug +* flag B +nibble +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_UMAC_DBG_CTRL_PSE_DBG_FLAG_B_NIB_EN_ADDR \ + WF_PLE_TOP_UMAC_DBG_CTRL_ADDR +#define WF_PLE_TOP_UMAC_DBG_CTRL_PSE_DBG_FLAG_B_NIB_EN_MASK \ + 0x00F00000 /* PSE_DBG_FLAG_B_NIB_EN[23..20] */ +#define WF_PLE_TOP_UMAC_DBG_CTRL_PSE_DBG_FLAG_B_NIB_EN_SHFT 20 +#define WF_PLE_TOP_UMAC_DBG_CTRL_PSE_DBG_FLAG_A_NIB_EN_ADDR \ + WF_PLE_TOP_UMAC_DBG_CTRL_ADDR +#define WF_PLE_TOP_UMAC_DBG_CTRL_PSE_DBG_FLAG_A_NIB_EN_MASK \ + 0x000F0000 /* PSE_DBG_FLAG_A_NIB_EN[19..16] */ +#define WF_PLE_TOP_UMAC_DBG_CTRL_PSE_DBG_FLAG_A_NIB_EN_SHFT 16 +#define WF_PLE_TOP_UMAC_DBG_CTRL_PLE_DBG_FLAG_B_NIB_EN_ADDR \ + WF_PLE_TOP_UMAC_DBG_CTRL_ADDR +#define WF_PLE_TOP_UMAC_DBG_CTRL_PLE_DBG_FLAG_B_NIB_EN_MASK \ + 0x0000F000 /* PLE_DBG_FLAG_B_NIB_EN[15..12] */ +#define WF_PLE_TOP_UMAC_DBG_CTRL_PLE_DBG_FLAG_B_NIB_EN_SHFT 12 +#define WF_PLE_TOP_UMAC_DBG_CTRL_PLE_DBG_FLAG_A_NIB_EN_ADDR \ + WF_PLE_TOP_UMAC_DBG_CTRL_ADDR +#define WF_PLE_TOP_UMAC_DBG_CTRL_PLE_DBG_FLAG_A_NIB_EN_MASK \ + 0x00000F00 /* PLE_DBG_FLAG_A_NIB_EN[11..8] */ +#define WF_PLE_TOP_UMAC_DBG_CTRL_PLE_DBG_FLAG_A_NIB_EN_SHFT 8 +#define WF_PLE_TOP_UMAC_DBG_CTRL_UMAC_DBG_FUNC_SEL_ADDR \ + WF_PLE_TOP_UMAC_DBG_CTRL_ADDR +#define WF_PLE_TOP_UMAC_DBG_CTRL_UMAC_DBG_FUNC_SEL_MASK \ + 0x0000000F /* UMAC_DBG_FUNC_SEL[3..0] */ +#define WF_PLE_TOP_UMAC_DBG_CTRL_UMAC_DBG_FUNC_SEL_SHFT 0 + +/* +* ---PLE_DBG_A_BYTE_SEL (0x820C0000 + 0x244)--- +* PLE_DBG_FLAG_A_BYTE0_SEL[7..0] - (RW) Debug flag selection of PLE +* debug A +* byte 0 +* PLE_DBG_FLAG_A_BYTE1_SEL[15..8] - (RW) Debug flag selection of PLE +* debug A +* byte 1 +* PLE_DBG_FLAG_A_BYTE2_SEL[23..16] - (RW) Debug flag selection of PLE +* debug A +* byte 2 +* PLE_DBG_FLAG_A_BYTE3_SEL[31..24] - (RW) Debug flag selection of PLE +* debug A +* byte 3 +*/ +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE3_SEL_ADDR \ + WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_ADDR +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE3_SEL_MASK \ + 0xFF000000 /* PLE_DBG_FLAG_A_BYTE3_SEL[31..24] */ +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE3_SEL_SHFT 24 +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE2_SEL_ADDR \ + WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_ADDR +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE2_SEL_MASK \ + 0x00FF0000 /* PLE_DBG_FLAG_A_BYTE2_SEL[23..16] */ +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE2_SEL_SHFT 16 +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE1_SEL_ADDR \ + WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_ADDR +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE1_SEL_MASK \ + 0x0000FF00 /* PLE_DBG_FLAG_A_BYTE1_SEL[15..8] */ +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE1_SEL_SHFT 8 +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE0_SEL_ADDR \ + WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_ADDR +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE0_SEL_MASK \ + 0x000000FF /* PLE_DBG_FLAG_A_BYTE0_SEL[7..0] */ +#define WF_PLE_TOP_PLE_DBG_A_BYTE_SEL_PLE_DBG_FLAG_A_BYTE0_SEL_SHFT 0 + +/* +* ---PLE_DBG_B_BYTE_SEL (0x820C0000 + 0x248)--- +* PLE_DBG_FLAG_B_BYTE0_SEL[7..0] - (RW) Debug flag selection of PLE +* debug B +* byte 0 +* PLE_DBG_FLAG_B_BYTE1_SEL[15..8] - (RW) Debug flag selection of PLE +* debug B +* byte 1 +* PLE_DBG_FLAG_B_BYTE2_SEL[23..16] - (RW) Debug flag selection of PLE +* debug B +* byte 2 +* PLE_DBG_FLAG_B_BYTE3_SEL[31..24] - (RW) Debug flag selection of PLE +* debug B +* byte 3 +*/ +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE3_SEL_ADDR \ + WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_ADDR +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE3_SEL_MASK \ + 0xFF000000 /* PLE_DBG_FLAG_B_BYTE3_SEL[31..24] */ +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE3_SEL_SHFT 24 +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE2_SEL_ADDR \ + WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_ADDR +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE2_SEL_MASK \ + 0x00FF0000 /* PLE_DBG_FLAG_B_BYTE2_SEL[23..16] */ +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE2_SEL_SHFT 16 +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE1_SEL_ADDR \ + WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_ADDR +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE1_SEL_MASK \ + 0x0000FF00 /* PLE_DBG_FLAG_B_BYTE1_SEL[15..8] */ +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE1_SEL_SHFT 8 +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE0_SEL_ADDR \ + WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_ADDR +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE0_SEL_MASK \ + 0x000000FF /* PLE_DBG_FLAG_B_BYTE0_SEL[7..0] */ +#define WF_PLE_TOP_PLE_DBG_B_BYTE_SEL_PLE_DBG_FLAG_B_BYTE0_SEL_SHFT 0 + +/* +* ---FSM_IDLE_WD_CTRL (0x820C0000 + 0x24C)--- +* FL_IDLE_WD_TO_TH[7..0] - (RW) Watchdog timeout threshold for frame +* link FSM not returning to IDLE +* PL_IDLE_WD_TO_TH[15..8] - (RW) Watchdog timeout threshold for page +link +* FSM not returning to IDLE +* PORT_IDLE_WD_TO_TH[23..16] - (RW) Watchdog timeout threshold for +* port oper +* FSM not returning to IDLE +* (Including HIF/CPU/LMAC port) +* MACTX_IDLE_WD_TO_TH[31..24] - (RW) Watchdog timeout threshold for +* MACTX FSM +* not returning to IDLE +*/ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_MACTX_IDLE_WD_TO_TH_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_CTRL_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_MACTX_IDLE_WD_TO_TH_MASK \ + 0xFF000000 /* MACTX_IDLE_WD_TO_TH[31..24] */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_MACTX_IDLE_WD_TO_TH_SHFT 24 +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_PORT_IDLE_WD_TO_TH_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_CTRL_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_PORT_IDLE_WD_TO_TH_MASK \ + 0x00FF0000 /* PORT_IDLE_WD_TO_TH[23..16] */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_PORT_IDLE_WD_TO_TH_SHFT 16 +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_PL_IDLE_WD_TO_TH_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_CTRL_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_PL_IDLE_WD_TO_TH_MASK \ + 0x0000FF00 /* PL_IDLE_WD_TO_TH[15..8] */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_PL_IDLE_WD_TO_TH_SHFT 8 +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_FL_IDLE_WD_TO_TH_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_CTRL_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_FL_IDLE_WD_TO_TH_MASK \ + 0x000000FF /* FL_IDLE_WD_TO_TH[7..0] */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_FL_IDLE_WD_TO_TH_SHFT 0 + +/* +* ---FSM_IDLE_WD_EN (0x820C0000 + 0x250)--- +* EN_FL_IDLE_WD_TO[0] - (RW) Enables watchdog for frame link FSM not +* returning to IDLE +* EN_PL_IDLE_WD_TO[1] - (RW) Enables watchdog for page link FSM not +* returning to IDLE +* EN_CPU_PORT_IDLE_WD_TO[2] - (RW) Enables watchdog for CPU port oper +FSM +* not returning to IDLE +* EN_HIF_PORT_IDLE_WD_TO[3] - (RW) Enables watchdog for HIF port oper +FSM +* not returning to IDLE +* EN_LMAC_PORT_IDLE_WD_TO[4] - (RW) Enables watchdog for LMAC port +* oper FSM +* not returning to IDLE +* EN_AMSDU_PORT_IDLE_WD_TO[5] - (RW) Enables watchdog for AMSDU port +* FSM not +* returning to IDLE +* EN_HW_AMSDU_IDLE_WD_TO[6] - (RW) Enables watchdog for HW AMSDU FSM +not +* returning to IDLE +* RESERVED7[7] - (RO) Reserved bits +* EN_MACTX0_IDLE_WD_TO[8] - (RW) Enables watchdog for MACTX 0 FSM not +* returning to IDLE +* EN_MACTX2_IDLE_WD_TO[9] - (RW) Enables watchdog for MACTX 1 FSM not +* returning to IDLE +* EN_MACTX1_IDLE_WD_TO[10] - (RW) Enables watchdog for MACTX 2 FSM not +* returning to IDLE +* EN_MACTX3_IDLE_WD_TO[11] - (RW) Enables watchdog for MACTX 3 FSM not +* returning to IDLE +* EN_MDP_IDLE_WD_TO[12] - (RW) Enables watchdog for MDP port oper FSM +* not returning to IDLE +* EN_PREDL_ARB_IDLE_WD_TO[13] - (RW) Enables watchdog for Predl +arbitrator +* FSM not returning to IDLE +* EN_PREDL_TXCMD_IDLE_WD_TO[14] - (RW) Enables watchdog for Predl +* TXCMD parser +* FSM not returning to IDLE +* RESERVED15[31..15] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PREDL_TXCMD_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PREDL_TXCMD_IDLE_WD_TO_MASK \ + 0x00004000 /* EN_PREDL_TXCMD_IDLE_WD_TO[14] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PREDL_TXCMD_IDLE_WD_TO_SHFT 14 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PREDL_ARB_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PREDL_ARB_IDLE_WD_TO_MASK \ + 0x00002000 /* EN_PREDL_ARB_IDLE_WD_TO[13] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PREDL_ARB_IDLE_WD_TO_SHFT 13 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MDP_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MDP_IDLE_WD_TO_MASK \ + 0x00001000 /* EN_MDP_IDLE_WD_TO[12] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MDP_IDLE_WD_TO_SHFT 12 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX3_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX3_IDLE_WD_TO_MASK \ + 0x00000800 /* EN_MACTX3_IDLE_WD_TO[11] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX3_IDLE_WD_TO_SHFT 11 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX1_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX1_IDLE_WD_TO_MASK \ + 0x00000400 /* EN_MACTX1_IDLE_WD_TO[10] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX1_IDLE_WD_TO_SHFT 10 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX2_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX2_IDLE_WD_TO_MASK \ + 0x00000200 /* EN_MACTX2_IDLE_WD_TO[9] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX2_IDLE_WD_TO_SHFT 9 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX0_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX0_IDLE_WD_TO_MASK \ + 0x00000100 /* EN_MACTX0_IDLE_WD_TO[8] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_MACTX0_IDLE_WD_TO_SHFT 8 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_HW_AMSDU_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_HW_AMSDU_IDLE_WD_TO_MASK \ + 0x00000040 /* EN_HW_AMSDU_IDLE_WD_TO[6] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_HW_AMSDU_IDLE_WD_TO_SHFT 6 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_AMSDU_PORT_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_AMSDU_PORT_IDLE_WD_TO_MASK \ + 0x00000020 /* EN_AMSDU_PORT_IDLE_WD_TO[5] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_AMSDU_PORT_IDLE_WD_TO_SHFT 5 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_LMAC_PORT_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_LMAC_PORT_IDLE_WD_TO_MASK \ + 0x00000010 /* EN_LMAC_PORT_IDLE_WD_TO[4] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_LMAC_PORT_IDLE_WD_TO_SHFT 4 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_HIF_PORT_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_HIF_PORT_IDLE_WD_TO_MASK \ + 0x00000008 /* EN_HIF_PORT_IDLE_WD_TO[3] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_HIF_PORT_IDLE_WD_TO_SHFT 3 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_CPU_PORT_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_CPU_PORT_IDLE_WD_TO_MASK \ + 0x00000004 /* EN_CPU_PORT_IDLE_WD_TO[2] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_CPU_PORT_IDLE_WD_TO_SHFT 2 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PL_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PL_IDLE_WD_TO_MASK \ + 0x00000002 /* EN_PL_IDLE_WD_TO[1] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_PL_IDLE_WD_TO_SHFT 1 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_FL_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_FL_IDLE_WD_TO_MASK \ + 0x00000001 /* EN_FL_IDLE_WD_TO[0] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_EN_FL_IDLE_WD_TO_SHFT 0 + +/* +* ---FSM_IDLE_WD_CTRL_1 (0x820C0000 + 0x258)--- +* MDP_IDLE_WD_TO_TH[7..0] - (RW) Watchdog timeout threshold for MDP +FSM +* not returning to IDLE +* (Including MDP TDP/RDP/TIOC/RIOC) +* PF_IDLE_WD_TO_TH[15..8] - (RW) Watchdog timeout threshold for PF FSM +* not returning to IDLE +* SEC_IDLE_WD_TO_TH[23..16] - (RW) Watchdog timeout threshold for SEC +FSM +* not returning to IDLE +* (Including SEC0/SEC1) +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_SEC_IDLE_WD_TO_TH_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_SEC_IDLE_WD_TO_TH_MASK \ + 0x00FF0000 /* SEC_IDLE_WD_TO_TH[23..16] */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_SEC_IDLE_WD_TO_TH_SHFT 16 +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_PF_IDLE_WD_TO_TH_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_PF_IDLE_WD_TO_TH_MASK \ + 0x0000FF00 /* PF_IDLE_WD_TO_TH[15..8] */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_PF_IDLE_WD_TO_TH_SHFT 8 +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_MDP_IDLE_WD_TO_TH_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_MDP_IDLE_WD_TO_TH_MASK \ + 0x000000FF /* MDP_IDLE_WD_TO_TH[7..0] */ +#define WF_PLE_TOP_FSM_IDLE_WD_CTRL_1_MDP_IDLE_WD_TO_TH_SHFT 0 + +/* +* ---FSM_IDLE_WD_EN_1 (0x820C0000 + 0x25C)--- +* EN_BN0_MDP_TDP_IDLE_WD_TO[0] - (RW) Enables watchdog for Band0 MDP +* TDP FSM +* not returning to IDLE +* EN_MDP_RDP_IDLE_WD_TO[1] - (RW) Enables watchdog for MDP RDP FSM not +* returning to IDLE +* EN_BN0_MDP_TIOC_IDLE_WD_TO[2] - (RW) Enables watchdog for Band0 MDP +* TIOC FSM +* not returning to IDLE +* EN_BN0_MDP_RIOC_IDLE_WD_TO[3] - (RW) Enables watchdog for Band0 MDP +* RIOC FSM +* not returning to IDLE +* EN_PF_IDLE_WD_TO[4] - (RW) Enables watchdog for PF FSM not +* returning to IDLE +* EN_SEC0_IDLE_WD_TO[5] - (RW) Enables watchdog for SEC0 FSM not +* returning to IDLE +* EN_SEC1_IDLE_WD_TO[6] - (RW) Enables watchdog for SEC1 FSM not +* returning to IDLE +* EN_BN1_MDP_TDP_IDLE_WD_TO[7] - (RW) Enables watchdog for Band1 MDP +* TDP FSM +* not returning to IDLE +* EN_BN1_MDP_TIOC_IDLE_WD_TO[8] - (RW) Enables watchdog for Band1 MDP +* TIOC FSM +* not returning to IDLE +* EN_BN1_MDP_RIOC_IDLE_WD_TO[9] - (RW) Enables watchdog for Band1 MDP +* RIOC FSM +* not returning to IDLE +* RESERVED10[31..10] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_RIOC_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_RIOC_IDLE_WD_TO_MASK \ + 0x00000200 /* EN_BN1_MDP_RIOC_IDLE_WD_TO[9] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_RIOC_IDLE_WD_TO_SHFT 9 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_TIOC_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_TIOC_IDLE_WD_TO_MASK \ + 0x00000100 /* EN_BN1_MDP_TIOC_IDLE_WD_TO[8] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_TIOC_IDLE_WD_TO_SHFT 8 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_TDP_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_TDP_IDLE_WD_TO_MASK \ + 0x00000080 /* EN_BN1_MDP_TDP_IDLE_WD_TO[7] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN1_MDP_TDP_IDLE_WD_TO_SHFT 7 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_SEC1_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_SEC1_IDLE_WD_TO_MASK \ + 0x00000040 /* EN_SEC1_IDLE_WD_TO[6] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_SEC1_IDLE_WD_TO_SHFT 6 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_SEC0_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_SEC0_IDLE_WD_TO_MASK \ + 0x00000020 /* EN_SEC0_IDLE_WD_TO[5] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_SEC0_IDLE_WD_TO_SHFT 5 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_PF_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_PF_IDLE_WD_TO_MASK \ + 0x00000010 /* EN_PF_IDLE_WD_TO[4] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_PF_IDLE_WD_TO_SHFT 4 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_RIOC_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_RIOC_IDLE_WD_TO_MASK \ + 0x00000008 /* EN_BN0_MDP_RIOC_IDLE_WD_TO[3] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_RIOC_IDLE_WD_TO_SHFT 3 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_TIOC_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_TIOC_IDLE_WD_TO_MASK \ + 0x00000004 /* EN_BN0_MDP_TIOC_IDLE_WD_TO[2] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_TIOC_IDLE_WD_TO_SHFT 2 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_MDP_RDP_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_MDP_RDP_IDLE_WD_TO_MASK \ + 0x00000002 /* EN_MDP_RDP_IDLE_WD_TO[1] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_MDP_RDP_IDLE_WD_TO_SHFT 1 +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_TDP_IDLE_WD_TO_ADDR \ + WF_PLE_TOP_FSM_IDLE_WD_EN_1_ADDR +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_TDP_IDLE_WD_TO_MASK \ + 0x00000001 /* EN_BN0_MDP_TDP_IDLE_WD_TO[0] */ +#define WF_PLE_TOP_FSM_IDLE_WD_EN_1_EN_BN0_MDP_TDP_IDLE_WD_TO_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL9 (0x820C0000 + 0x260)--- +* SRAM9_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM9 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL9_SRAM9_MBIST_DELSEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_DELSEL9_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL9_SRAM9_MBIST_DELSEL_MASK \ + 0xFFFFFFFF /* SRAM9_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL9_SRAM9_MBIST_DELSEL_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL10 (0x820C0000 + 0x264)--- +* SRAM10_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM10 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL10_SRAM10_MBIST_DELSEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_DELSEL10_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL10_SRAM10_MBIST_DELSEL_MASK \ + 0xFFFFFFFF /* SRAM10_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL10_SRAM10_MBIST_DELSEL_SHFT 0 + +/* +* ---FUNC_ACT_CNT_1 (0x820C0000 + 0x284)--- +* MACTX0_ACT_CNT[3..0] - (RO) Counter of MACTX0 TX active. +* MACTX0_NOR_END_CNT[7..4] - (RO) Counter of MACTX0 TX normal end. +* MACTX0_ABORT_CNT[11..8] - (RO) Counter of MACTX0 TX abort. +* RESERVED12[15..12] - (RO) Reserved bits +* TXCMD0_ADD_FID_CNT[19..16] - (RO) Counter of TXCMD0 TX add FID. +* TXCMD0_NOR_END_CNT[23..20] - (RO) Counter of TXCMD0 TX normal end. +* TXCMD0_ABORT_CNT[27..24] - (RO) Counter of TXCMD0 TX abort. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_ABORT_CNT_ADDR \ + WF_PLE_TOP_FUNC_ACT_CNT_1_ADDR +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_ABORT_CNT_MASK \ + 0x0F000000 /* TXCMD0_ABORT_CNT[27..24] */ +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_ABORT_CNT_SHFT 24 +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_NOR_END_CNT_ADDR \ + WF_PLE_TOP_FUNC_ACT_CNT_1_ADDR +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_NOR_END_CNT_MASK \ + 0x00F00000 /* TXCMD0_NOR_END_CNT[23..20] */ +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_NOR_END_CNT_SHFT 20 +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_ADD_FID_CNT_ADDR \ + WF_PLE_TOP_FUNC_ACT_CNT_1_ADDR +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_ADD_FID_CNT_MASK \ + 0x000F0000 /* TXCMD0_ADD_FID_CNT[19..16] */ +#define WF_PLE_TOP_FUNC_ACT_CNT_1_TXCMD0_ADD_FID_CNT_SHFT 16 +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_ABORT_CNT_ADDR \ + WF_PLE_TOP_FUNC_ACT_CNT_1_ADDR +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_ABORT_CNT_MASK \ + 0x00000F00 /* MACTX0_ABORT_CNT[11..8] */ +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_ABORT_CNT_SHFT 8 +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_NOR_END_CNT_ADDR \ + WF_PLE_TOP_FUNC_ACT_CNT_1_ADDR +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_NOR_END_CNT_MASK \ + 0x000000F0 /* MACTX0_NOR_END_CNT[7..4] */ +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_NOR_END_CNT_SHFT 4 +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_ACT_CNT_ADDR \ + WF_PLE_TOP_FUNC_ACT_CNT_1_ADDR +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_ACT_CNT_MASK \ + 0x0000000F /* MACTX0_ACT_CNT[3..0] */ +#define WF_PLE_TOP_FUNC_ACT_CNT_1_MACTX0_ACT_CNT_SHFT 0 + +/* +* ---PORT_SER_CTRL (0x820C0000 + 0x2A0)--- +* EN_HIF_PORT_ALLOC_BLOCKING[0] - (RW) Enable HIF/AMSDU port allocate +* operation blocking. +* EN_CPU_PORT_ALLOC_BLOCKING[1] - (RW) Enable CPU port allocate +operation +blocking. +* EN_WF_PORT_ALLOC_BLOCKING[2] - (RW) Enable LMAC port allocate +operation +blocking. +* RESERVED3[7..3] - (RO) Reserved bits +* EN_HIF_PORT_D_OPR_BLOCKING[8] - (RW) Enable HIF/AMSDU/MDP/PREDL port +data +* operation blocking. +* EN_CPU_PORT_D_OPR_BLOCKING[9] - (RW) Enable CPU port data operation +blocking. +* EN_WF_PORT_D_OPR_BLOCKING[10] - (RW) Enable LMAC port data operation +blocking. +* RESERVED11[15..11] - (RO) Reserved bits +* EN_HIF_PORT_Q_OPR_BLOCKING[16] - (RW) Enable HIF/AMSDU port queue +operation +blocking. +* EN_CPU_PORT_Q_OPR_BLOCKING[17] - (RW) Enable CPU port queue +operation +blocking. +* EN_WF_PORT_Q_OPR_BLOCKING[18] - (RW) Enable LMAC port queue +operation +blocking. +* RESERVED19[31..19] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_Q_OPR_BLOCKING_ADDR \ + WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_Q_OPR_BLOCKING_MASK \ + 0x00040000 /* EN_WF_PORT_Q_OPR_BLOCKING[18] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_Q_OPR_BLOCKING_SHFT 18 +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_Q_OPR_BLOCKING_ADDR \ + WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_Q_OPR_BLOCKING_MASK \ + 0x00020000 /* EN_CPU_PORT_Q_OPR_BLOCKING[17] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_Q_OPR_BLOCKING_SHFT 17 +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_Q_OPR_BLOCKING_ADDR \ + WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_Q_OPR_BLOCKING_MASK \ + 0x00010000 /* EN_HIF_PORT_Q_OPR_BLOCKING[16] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_Q_OPR_BLOCKING_SHFT 16 +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_D_OPR_BLOCKING_ADDR \ + WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_D_OPR_BLOCKING_MASK \ + 0x00000400 /* EN_WF_PORT_D_OPR_BLOCKING[10] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_D_OPR_BLOCKING_SHFT 10 +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_D_OPR_BLOCKING_ADDR \ + WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_D_OPR_BLOCKING_MASK \ + 0x00000200 /* EN_CPU_PORT_D_OPR_BLOCKING[9] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_D_OPR_BLOCKING_SHFT 9 +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_D_OPR_BLOCKING_ADDR \ + WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_D_OPR_BLOCKING_MASK \ + 0x00000100 /* EN_HIF_PORT_D_OPR_BLOCKING[8] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_D_OPR_BLOCKING_SHFT 8 +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_ALLOC_BLOCKING_ADDR \ + WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_ALLOC_BLOCKING_MASK \ + 0x00000004 /* EN_WF_PORT_ALLOC_BLOCKING[2] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_WF_PORT_ALLOC_BLOCKING_SHFT 2 +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_ALLOC_BLOCKING_ADDR \ + WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_ALLOC_BLOCKING_MASK \ + 0x00000002 /* EN_CPU_PORT_ALLOC_BLOCKING[1] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_CPU_PORT_ALLOC_BLOCKING_SHFT 1 +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_ALLOC_BLOCKING_ADDR \ + WF_PLE_TOP_PORT_SER_CTRL_ADDR +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_ALLOC_BLOCKING_MASK \ + 0x00000001 /* EN_HIF_PORT_ALLOC_BLOCKING[0] */ +#define WF_PLE_TOP_PORT_SER_CTRL_EN_HIF_PORT_ALLOC_BLOCKING_SHFT 0 + +/* +* ---MACTX_SER_CTRL (0x820C0000 + 0x2A4)--- +* EN_MACTX_G0_BLOCKING[0] - (RW) Enable MACTX group 0 operation +blocking. +* RESERVED1[7..1] - (RO) Reserved bits +* EN_MACTX_G1_BLOCKING[8] - (RW) Enable MACTX group 1 operation +blocking. +* RESERVED9[15..9] - (RO) Reserved bits +* EN_MACTX_G2_BLOCKING[16] - (RW) Enable MACTX group 2 operation +blocking. +* RESERVED17[23..17] - (RO) Reserved bits +* EN_MACTX_G3_BLOCKING[24] - (RW) Enable MACTX group 3 operation +blocking. +* RESERVED25[31..25] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G3_BLOCKING_ADDR \ + WF_PLE_TOP_MACTX_SER_CTRL_ADDR +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G3_BLOCKING_MASK \ + 0x01000000 /* EN_MACTX_G3_BLOCKING[24] */ +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G3_BLOCKING_SHFT 24 +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G2_BLOCKING_ADDR \ + WF_PLE_TOP_MACTX_SER_CTRL_ADDR +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G2_BLOCKING_MASK \ + 0x00010000 /* EN_MACTX_G2_BLOCKING[16] */ +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G2_BLOCKING_SHFT 16 +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G1_BLOCKING_ADDR \ + WF_PLE_TOP_MACTX_SER_CTRL_ADDR +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G1_BLOCKING_MASK \ + 0x00000100 /* EN_MACTX_G1_BLOCKING[8] */ +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G1_BLOCKING_SHFT 8 +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G0_BLOCKING_ADDR \ + WF_PLE_TOP_MACTX_SER_CTRL_ADDR +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G0_BLOCKING_MASK \ + 0x00000001 /* EN_MACTX_G0_BLOCKING[0] */ +#define WF_PLE_TOP_MACTX_SER_CTRL_EN_MACTX_G0_BLOCKING_SHFT 0 + +/* +* ---DRR_SER_CTRL (0x820C0000 + 0x2A8)--- +* EN_DRR_CHARGE_BLOCKING[0] - (RW) Enable DRR charge operation +blocking. +* RESERVED1[3..1] - (RO) Reserved bits +* EN_DRR_SRCH_0_BLOCKING[4] - (RW) Enable DRR search 0 operation +blocking. +* EN_DRR_SRCH_1_BLOCKING[5] - (RW) Enable DRR search 1 operation +blocking. +* RESERVED6[7..6] - (RO) Reserved bits +* EN_DRR_RDG_0_BLOCKING[8] - (RW) Enable DRR RDG 0 operation blocking. +* EN_DRR_RDG_1_BLOCKING[9] - (RW) Enable DRR RDG 1 operation blocking. +* RESERVED10[31..10] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_RDG_1_BLOCKING_ADDR \ + WF_PLE_TOP_DRR_SER_CTRL_ADDR +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_RDG_1_BLOCKING_MASK \ + 0x00000200 /* EN_DRR_RDG_1_BLOCKING[9] */ +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_RDG_1_BLOCKING_SHFT 9 +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_RDG_0_BLOCKING_ADDR \ + WF_PLE_TOP_DRR_SER_CTRL_ADDR +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_RDG_0_BLOCKING_MASK \ + 0x00000100 /* EN_DRR_RDG_0_BLOCKING[8] */ +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_RDG_0_BLOCKING_SHFT 8 +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_SRCH_1_BLOCKING_ADDR \ + WF_PLE_TOP_DRR_SER_CTRL_ADDR +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_SRCH_1_BLOCKING_MASK \ + 0x00000020 /* EN_DRR_SRCH_1_BLOCKING[5] */ +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_SRCH_1_BLOCKING_SHFT 5 +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_SRCH_0_BLOCKING_ADDR \ + WF_PLE_TOP_DRR_SER_CTRL_ADDR +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_SRCH_0_BLOCKING_MASK \ + 0x00000010 /* EN_DRR_SRCH_0_BLOCKING[4] */ +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_SRCH_0_BLOCKING_SHFT 4 +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_CHARGE_BLOCKING_ADDR \ + WF_PLE_TOP_DRR_SER_CTRL_ADDR +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_CHARGE_BLOCKING_MASK \ + 0x00000001 /* EN_DRR_CHARGE_BLOCKING[0] */ +#define WF_PLE_TOP_DRR_SER_CTRL_EN_DRR_CHARGE_BLOCKING_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL5 (0x820C0000 + 0x2c0)--- +* SRAM5_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM5 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL5_SRAM5_MBIST_DELSEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_DELSEL5_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL5_SRAM5_MBIST_DELSEL_MASK \ + 0xFFFFFFFF /* SRAM5_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL5_SRAM5_MBIST_DELSEL_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL6 (0x820C0000 + 0x2c4)--- +* SRAM6_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM6 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL6_SRAM6_MBIST_DELSEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_DELSEL6_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL6_SRAM6_MBIST_DELSEL_MASK \ + 0xFFFFFFFF /* SRAM6_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL6_SRAM6_MBIST_DELSEL_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL7 (0x820C0000 + 0x2c8)--- +* SRAM7_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM7 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL7_SRAM7_MBIST_DELSEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_DELSEL7_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL7_SRAM7_MBIST_DELSEL_MASK \ + 0xFFFFFFFF /* SRAM7_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL7_SRAM7_MBIST_DELSEL_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL8 (0x820C0000 + 0x2cc)--- +* SRAM8_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM8 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL8_SRAM8_MBIST_DELSEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_DELSEL8_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL8_SRAM8_MBIST_DELSEL_MASK \ + 0xFFFFFFFF /* SRAM8_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL8_SRAM8_MBIST_DELSEL_SHFT 0 + +/* +* ---SRAM_MBIST_BACKGROUND (0x820C0000 + 0x2d0)--- +* MBIST_BACKGROUND[15..0] - (RW) bsel setting for PLE SRAM MBIST +circuit +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SRAM_MBIST_BACKGROUND_MBIST_BACKGROUND_ADDR \ + WF_PLE_TOP_SRAM_MBIST_BACKGROUND_ADDR +#define WF_PLE_TOP_SRAM_MBIST_BACKGROUND_MBIST_BACKGROUND_MASK \ + 0x0000FFFF /* MBIST_BACKGROUND[15..0] */ +#define WF_PLE_TOP_SRAM_MBIST_BACKGROUND_MBIST_BACKGROUND_SHFT 0 + +/* +* ---SRAM_MBIST_BSEL (0x820C0000 + 0x2d4)--- +* MBIST_BSEL[15..0] - (RW) The bsel setting for PLE SRAM MBIST +circuit. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SRAM_MBIST_BSEL_MBIST_BSEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_BSEL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_BSEL_MBIST_BSEL_MASK \ + 0x0000FFFF /* MBIST_BSEL[15..0] */ +#define WF_PLE_TOP_SRAM_MBIST_BSEL_MBIST_BSEL_SHFT 0 + +/* +* ---SRAM_MBIST_DONE (0x820C0000 + 0x2d8)--- +* G1_MBIST_DONE[0] - (RO) Working status of PLE G1 SRAM MBIST +circuit +* G2_MBIST_DONE[1] - (RO) Working status of PLE G2 SRAM MBIST +circuit +* RESERVED2[31..2] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SRAM_MBIST_DONE_G2_MBIST_DONE_ADDR \ + WF_PLE_TOP_SRAM_MBIST_DONE_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DONE_G2_MBIST_DONE_MASK \ + 0x00000002 /* G2_MBIST_DONE[1] */ +#define WF_PLE_TOP_SRAM_MBIST_DONE_G2_MBIST_DONE_SHFT 1 +#define WF_PLE_TOP_SRAM_MBIST_DONE_G1_MBIST_DONE_ADDR \ + WF_PLE_TOP_SRAM_MBIST_DONE_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DONE_G1_MBIST_DONE_MASK \ + 0x00000001 /* G1_MBIST_DONE[0] */ +#define WF_PLE_TOP_SRAM_MBIST_DONE_G1_MBIST_DONE_SHFT 0 + +/* +* ---SRAM_MBIST_FAIL (0x820C0000 + 0x2dc)--- +* G1_SRAM0_MBIST_FAIL[0] - (RO) MBIST check result of group 1 SRAM0 +* G1_SRAM1_MBIST_FAIL[1] - (RO) MBIST check result of group 1 SRAM1 +* G1_SRAM2_MBIST_FAIL[2] - (RO) MBIST check result of group 1 SRAM2 +* G1_SRAM3_MBIST_FAIL[3] - (RO) MBIST check result of group 1 SRAM3 +* G2_SRAM0_MBIST_FAIL[4] - (RO) MBIST check result of group 2 SRAM0 +* G2_SRAM1_MBIST_FAIL[5] - (RO) MBIST check result of group 2 SRAM1 +* G2_SRAM2_MBIST_FAIL[6] - (RO) MBIST check result of group 2 SRAM2 +* G2_SRAM3_MBIST_FAIL[7] - (RO) MBIST check result of group 2 SRAM3 +* G2_SRAM4_MBIST_FAIL[8] - (RO) MBIST check result of group 2 SRAM4 +* G2_SRAM5_MBIST_FAIL[9] - (RO) MBIST check result of group 2 SRAM5 +* RESERVED10[31..10] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM5_MBIST_FAIL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM5_MBIST_FAIL_MASK \ + 0x00000200 /* G2_SRAM5_MBIST_FAIL[9] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM5_MBIST_FAIL_SHFT 9 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM4_MBIST_FAIL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM4_MBIST_FAIL_MASK \ + 0x00000100 /* G2_SRAM4_MBIST_FAIL[8] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM4_MBIST_FAIL_SHFT 8 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM3_MBIST_FAIL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM3_MBIST_FAIL_MASK \ + 0x00000080 /* G2_SRAM3_MBIST_FAIL[7] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM3_MBIST_FAIL_SHFT 7 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM2_MBIST_FAIL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM2_MBIST_FAIL_MASK \ + 0x00000040 /* G2_SRAM2_MBIST_FAIL[6] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM2_MBIST_FAIL_SHFT 6 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM1_MBIST_FAIL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM1_MBIST_FAIL_MASK \ + 0x00000020 /* G2_SRAM1_MBIST_FAIL[5] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM1_MBIST_FAIL_SHFT 5 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM0_MBIST_FAIL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM0_MBIST_FAIL_MASK \ + 0x00000010 /* G2_SRAM0_MBIST_FAIL[4] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G2_SRAM0_MBIST_FAIL_SHFT 4 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM3_MBIST_FAIL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM3_MBIST_FAIL_MASK \ + 0x00000008 /* G1_SRAM3_MBIST_FAIL[3] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM3_MBIST_FAIL_SHFT 3 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM2_MBIST_FAIL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM2_MBIST_FAIL_MASK \ + 0x00000004 /* G1_SRAM2_MBIST_FAIL[2] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM2_MBIST_FAIL_SHFT 2 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM1_MBIST_FAIL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM1_MBIST_FAIL_MASK \ + 0x00000002 /* G1_SRAM1_MBIST_FAIL[1] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM1_MBIST_FAIL_SHFT 1 +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM0_MBIST_FAIL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM0_MBIST_FAIL_MASK \ + 0x00000001 /* G1_SRAM0_MBIST_FAIL[0] */ +#define WF_PLE_TOP_SRAM_MBIST_FAIL_G1_SRAM0_MBIST_FAIL_SHFT 0 + +/* +* ---SRAM_MBIST_CTRL (0x820C0000 + 0x2e0)--- +* G1_MBIST_MODE[0] - (RW) Control register for mbist_mode of group +* 1 MBIST +* G2_MBIST_MODE[1] - (RW) Control register for mbist_mode of group +* 2 MBIST +* RESERVED2[3..2] - (RO) Reserved bits +* G1_MBIST_HOLDB[4] - (RW) Control register for mbist_holdb of +* group 1 MBIST +* G2_MBIST_HOLDB[5] - (RW) Control register for mbist_holdb of +* group 2 MBIST +* RESERVED6[7..6] - (RO) Reserved bits +* G1_MBIST_DEBUG[8] - (RW) Control register for mbist_debug of +* group 1 MBIST +* G2_MBIST_DEBUG[9] - (RW) Control register for mbist_debug of +* group 2 MBIST +* G1_MBIST_USE_DEFAULT_DELSEL[10] - (RW) Control register for default +DELSEL +* value of group 1 memory +* G2_MBIST_USE_DEFAULT_DELSEL[11] - (RW) Control register for default +DELSEL +* value of group 2 memory +* MBIST_DIAG_SEL[16..12] - (RW) Selection register for +mbist_diag_scan_out +* RESERVED17[19..17] - (RO) Reserved bits +* UMAC_MBIST_DIAG_SEL[20] - (RW) Selection register for UMAC +* mbist_diag_scan_out (PLE or PSE) +* RESERVED21[23..21] - (RO) Reserved bits +* G1_MBIST_SLEEP_TEST[24] - (RW) Control register for sleep_test of +group +* 1 MBIST +* G1_MBIST_SLEEP_INV[25] - (RW) Control register for sleep_inv of +group +* 1 MBIST +* G1_MBIST_SLEEP_W[26] - (RW) Control register for sleep_w of group 1 +MBIST +* G1_MBIST_SLEEP_R[27] - (RW) Control register for sleep_r of group 1 +MBIST +* G2_MBIST_SLEEP_TEST[28] - (RW) Control register for sleep_test of +group +* 2 MBIST +* G2_MBIST_SLEEP_INV[29] - (RW) Control register for sleep_inv of +group +* 2 MBIST +* G2_MBIST_SLEEP_W[30] - (RW) Control register for sleep_w of group 2 +MBIST +* G2_MBIST_SLEEP_R[31] - (RW) Control register for sleep_r of group 2 +MBIST +*/ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_R_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_R_MASK \ + 0x80000000 /* G2_MBIST_SLEEP_R[31] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_R_SHFT 31 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_W_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_W_MASK \ + 0x40000000 /* G2_MBIST_SLEEP_W[30] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_W_SHFT 30 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_INV_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_INV_MASK \ + 0x20000000 /* G2_MBIST_SLEEP_INV[29] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_INV_SHFT 29 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_TEST_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_TEST_MASK \ + 0x10000000 /* G2_MBIST_SLEEP_TEST[28] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_SLEEP_TEST_SHFT 28 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_R_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_R_MASK \ + 0x08000000 /* G1_MBIST_SLEEP_R[27] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_R_SHFT 27 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_W_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_W_MASK \ + 0x04000000 /* G1_MBIST_SLEEP_W[26] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_W_SHFT 26 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_INV_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_INV_MASK \ + 0x02000000 /* G1_MBIST_SLEEP_INV[25] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_INV_SHFT 25 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_TEST_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_TEST_MASK \ + 0x01000000 /* G1_MBIST_SLEEP_TEST[24] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_SLEEP_TEST_SHFT 24 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_UMAC_MBIST_DIAG_SEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_UMAC_MBIST_DIAG_SEL_MASK \ + 0x00100000 /* UMAC_MBIST_DIAG_SEL[20] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_UMAC_MBIST_DIAG_SEL_SHFT 20 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_MBIST_DIAG_SEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_MBIST_DIAG_SEL_MASK \ + 0x0001F000 /* MBIST_DIAG_SEL[16..12] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_MBIST_DIAG_SEL_SHFT 12 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_USE_DEFAULT_DELSEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_USE_DEFAULT_DELSEL_MASK \ + 0x00000800 /* G2_MBIST_USE_DEFAULT_DELSEL[11] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_USE_DEFAULT_DELSEL_SHFT 11 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_USE_DEFAULT_DELSEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_USE_DEFAULT_DELSEL_MASK \ + 0x00000400 /* G1_MBIST_USE_DEFAULT_DELSEL[10] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_USE_DEFAULT_DELSEL_SHFT 10 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_DEBUG_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_DEBUG_MASK \ + 0x00000200 /* G2_MBIST_DEBUG[9] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_DEBUG_SHFT 9 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_DEBUG_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_DEBUG_MASK \ + 0x00000100 /* G1_MBIST_DEBUG[8] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_DEBUG_SHFT 8 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_HOLDB_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_HOLDB_MASK \ + 0x00000020 /* G2_MBIST_HOLDB[5] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_HOLDB_SHFT 5 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_HOLDB_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_HOLDB_MASK \ + 0x00000010 /* G1_MBIST_HOLDB[4] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_HOLDB_SHFT 4 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_MODE_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_MODE_MASK \ + 0x00000002 /* G2_MBIST_MODE[1] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G2_MBIST_MODE_SHFT 1 +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_MODE_ADDR \ + WF_PLE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_MODE_MASK \ + 0x00000001 /* G1_MBIST_MODE[0] */ +#define WF_PLE_TOP_SRAM_MBIST_CTRL_G1_MBIST_MODE_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL1 (0x820C0000 + 0x2e4)--- +* SRAM1_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM1 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL1_SRAM1_MBIST_DELSEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_DELSEL1_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL1_SRAM1_MBIST_DELSEL_MASK \ + 0xFFFFFFFF /* SRAM1_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL1_SRAM1_MBIST_DELSEL_SHFT 0 + +/* +* ---BSS_DBDC_CTRL (0x820C0000 + 0x2ec)--- +* BSS_BAND_SEL[15..0] - (RW) Select band of each BSS +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_BSS_DBDC_CTRL_BSS_BAND_SEL_ADDR \ + WF_PLE_TOP_BSS_DBDC_CTRL_ADDR +#define WF_PLE_TOP_BSS_DBDC_CTRL_BSS_BAND_SEL_MASK \ + 0x0000FFFF /* BSS_BAND_SEL[15..0] */ +#define WF_PLE_TOP_BSS_DBDC_CTRL_BSS_BAND_SEL_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL2 (0x820C0000 + 0x2f0)--- +* SRAM2_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM2 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL2_SRAM2_MBIST_DELSEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_DELSEL2_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL2_SRAM2_MBIST_DELSEL_MASK \ + 0xFFFFFFFF /* SRAM2_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL2_SRAM2_MBIST_DELSEL_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL3 (0x820C0000 + 0x2f4)--- +* SRAM3_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM3 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL3_SRAM3_MBIST_DELSEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_DELSEL3_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL3_SRAM3_MBIST_DELSEL_MASK \ + 0xFFFFFFFF /* SRAM3_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL3_SRAM3_MBIST_DELSEL_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL4 (0x820C0000 + 0x2f8)--- +* SRAM4_MBIST_DELSEL[31..0] - (RW) MBIST delsel setting of SRAM4 +*/ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL4_SRAM4_MBIST_DELSEL_ADDR \ + WF_PLE_TOP_SRAM_MBIST_DELSEL4_ADDR +#define WF_PLE_TOP_SRAM_MBIST_DELSEL4_SRAM4_MBIST_DELSEL_MASK \ + 0xFFFFFFFF /* SRAM4_MBIST_DELSEL[31..0] */ +#define WF_PLE_TOP_SRAM_MBIST_DELSEL4_SRAM4_MBIST_DELSEL_SHFT 0 + +/* +* ---SRAM_AWT_HDEN_CTRL (0x820C0000 + 0x2fc)--- +* SRAM_AWT_CTRL[13..0] - (RW) AWT setting of SRAMS +* RESERVED14[15..14] - (RO) Reserved bits +* SRAM_HDEN_CTRL[29..16] - (RW) HDEN setting of SRAMS +* RESERVED30[31..30] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_SRAM_HDEN_CTRL_ADDR \ + WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_SRAM_HDEN_CTRL_MASK \ + 0x3FFF0000 /* SRAM_HDEN_CTRL[29..16] */ +#define WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_SRAM_HDEN_CTRL_SHFT 16 +#define WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_SRAM_AWT_CTRL_ADDR \ + WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_SRAM_AWT_CTRL_MASK \ + 0x00003FFF /* SRAM_AWT_CTRL[13..0] */ +#define WF_PLE_TOP_SRAM_AWT_HDEN_CTRL_SRAM_AWT_CTRL_SHFT 0 + +/* +* ---DRR_TABLE_WDATA0 (0x820C0000 + 0x340)--- +* DRR_TABLE_WDATA[31..0] - (RW) DRRwdata[31:0] for reading/writing DRR +table +* Mode 0x2?: DRR station mode +* WData[15:0]: Sta setting +* WData[127:16]: Reserved +* Mode 0x4?: BSS mode +* See SRAM layout. +* Mode 0x8?: Charge mode +* WData [15:0]: Charge length (unit: +byte) +* WData [31:16]: Charge time 9 unit +1.024us +* WData[127:32]: Reserved +*/ +#define WF_PLE_TOP_DRR_TABLE_WDATA0_DRR_TABLE_WDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_WDATA0_ADDR +#define WF_PLE_TOP_DRR_TABLE_WDATA0_DRR_TABLE_WDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_WDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_WDATA0_DRR_TABLE_WDATA_SHFT 0 + +/* +* ---DRR_TABLE_WDATA1 (0x820C0000 + 0x344)--- +* DRR_TABLE_WDATA[31..0] - (RW) DRR wdata[63:32] for reading/writing +DRR +table +*/ +#define WF_PLE_TOP_DRR_TABLE_WDATA1_DRR_TABLE_WDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_WDATA1_ADDR +#define WF_PLE_TOP_DRR_TABLE_WDATA1_DRR_TABLE_WDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_WDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_WDATA1_DRR_TABLE_WDATA_SHFT 0 + +/* +* ---DRR_TABLE_WDATA2 (0x820C0000 + 0x348)--- +* DRR_TABLE_WDATA[31..0] - (RW) DRR wdata[95:64] for reading/writing +DRR +table +*/ +#define WF_PLE_TOP_DRR_TABLE_WDATA2_DRR_TABLE_WDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_WDATA2_ADDR +#define WF_PLE_TOP_DRR_TABLE_WDATA2_DRR_TABLE_WDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_WDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_WDATA2_DRR_TABLE_WDATA_SHFT 0 + +/* +* ---DRR_TABLE_WDATA3 (0x820C0000 + 0x34c)--- +* DRR_TABLE_WDATA[31..0] - (RW) DRR wdata[127:96] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_WDATA3_DRR_TABLE_WDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_WDATA3_ADDR +#define WF_PLE_TOP_DRR_TABLE_WDATA3_DRR_TABLE_WDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_WDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_WDATA3_DRR_TABLE_WDATA_SHFT 0 + +/* +* ---DRR_TABLE_RDATA0 (0x820C0000 + 0x350)--- +* DRR_TABLE_RDATA[31..0] - (RW) DRR rdata[31:0] for reading/writing +DRR +table +*/ +#define WF_PLE_TOP_DRR_TABLE_RDATA0_DRR_TABLE_RDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_RDATA0_ADDR +#define WF_PLE_TOP_DRR_TABLE_RDATA0_DRR_TABLE_RDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_RDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_RDATA0_DRR_TABLE_RDATA_SHFT 0 + +/* +* ---DRR_TABLE_RDATA1 (0x820C0000 + 0x354)--- +* DRR_TABLE_RDATA[31..0] - (RW) DRR rdata[63:32] for reading/writing +DRR +table +*/ +#define WF_PLE_TOP_DRR_TABLE_RDATA1_DRR_TABLE_RDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_RDATA1_ADDR +#define WF_PLE_TOP_DRR_TABLE_RDATA1_DRR_TABLE_RDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_RDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_RDATA1_DRR_TABLE_RDATA_SHFT 0 + +/* +* ---DRR_TABLE_RDATA2 (0x820C0000 + 0x358)--- +* DRR_TABLE_RDATA[31..0] - (RW) DRR rdata[95:64] for reading/writing +DRR +table +*/ +#define WF_PLE_TOP_DRR_TABLE_RDATA2_DRR_TABLE_RDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_RDATA2_ADDR +#define WF_PLE_TOP_DRR_TABLE_RDATA2_DRR_TABLE_RDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_RDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_RDATA2_DRR_TABLE_RDATA_SHFT 0 + +/* +* ---DRR_TABLE_RDATA3 (0x820C0000 + 0x35c)--- +* DRR_TABLE_RDATA[31..0] - (RW) DRR rdata[127:96] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_RDATA3_DRR_TABLE_RDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_RDATA3_ADDR +#define WF_PLE_TOP_DRR_TABLE_RDATA3_DRR_TABLE_RDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_RDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_RDATA3_DRR_TABLE_RDATA_SHFT 0 + +/* +* ---VOW_CONTROL (0x820C0000 + 0x370)--- +* PER_BSS_BW_CONTROL_ENABLE[15..0] - (RW) BW control of BSSID +* REFILL_PERIOD[18..16] - (RW) Period of token refill function +* RESERVED19[19] - (RO) Reserved bits +* DBDC1_SEARCH_RULE[20] - (RW) Priority for HW search if internal +* collision occurs +* DBDC0_SEARCH_RULE[21] - (RW) Priority for HW search if internal +* collision occcurs +* RESERVED22[25..22] - (RO) Reserved bits +* DRR_LOGIC_RESET[26] - (RW) DRR logic reset control +* DIS_WTBL_PS_IGNORE[27] - (RW) Disable control of the function that +STA +* with WTBL PS ignore in TXQ busy +* ENABLE_TXOP_NO_CHANGE_BSS_GROUP[28] - (RW) HW cannot change BW group +* In TXOP +burst. +* ENABLE_AIRTIME_FAIRNESS[29] - (RW) When airtime function is +* disabled, HW +* will change station without checking station qouta. +* ENABLE_TOKEN_REFILL[30] - (RW) Enable control of token refill +function +* ENABLE_BW_CONTROL[31] - (RW) HW will check if there are tokens in BW +* bucket before TX. +*/ +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_BW_CONTROL_ADDR \ + WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_BW_CONTROL_MASK \ + 0x80000000 /* ENABLE_BW_CONTROL[31] */ +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_BW_CONTROL_SHFT 31 +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_TOKEN_REFILL_ADDR \ + WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_TOKEN_REFILL_MASK \ + 0x40000000 /* ENABLE_TOKEN_REFILL[30] */ +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_TOKEN_REFILL_SHFT 30 +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_AIRTIME_FAIRNESS_ADDR \ + WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_AIRTIME_FAIRNESS_MASK \ + 0x20000000 /* ENABLE_AIRTIME_FAIRNESS[29] */ +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_AIRTIME_FAIRNESS_SHFT 29 +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_TXOP_NO_CHANGE_BSS_GROUP_ADDR \ + WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_TXOP_NO_CHANGE_BSS_GROUP_MASK \ + 0x10000000 /* ENABLE_TXOP_NO_CHANGE_BSS_GROUP[28] */ +#define WF_PLE_TOP_VOW_CONTROL_ENABLE_TXOP_NO_CHANGE_BSS_GROUP_SHFT 28 +#define WF_PLE_TOP_VOW_CONTROL_DIS_WTBL_PS_IGNORE_ADDR \ + WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_DIS_WTBL_PS_IGNORE_MASK \ + 0x08000000 /* DIS_WTBL_PS_IGNORE[27] */ +#define WF_PLE_TOP_VOW_CONTROL_DIS_WTBL_PS_IGNORE_SHFT 27 +#define WF_PLE_TOP_VOW_CONTROL_DRR_LOGIC_RESET_ADDR \ + WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_DRR_LOGIC_RESET_MASK \ + 0x04000000 /* DRR_LOGIC_RESET[26] */ +#define WF_PLE_TOP_VOW_CONTROL_DRR_LOGIC_RESET_SHFT 26 +#define WF_PLE_TOP_VOW_CONTROL_DBDC0_SEARCH_RULE_ADDR \ + WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_DBDC0_SEARCH_RULE_MASK \ + 0x00200000 /* DBDC0_SEARCH_RULE[21] */ +#define WF_PLE_TOP_VOW_CONTROL_DBDC0_SEARCH_RULE_SHFT 21 +#define WF_PLE_TOP_VOW_CONTROL_DBDC1_SEARCH_RULE_ADDR \ + WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_DBDC1_SEARCH_RULE_MASK \ + 0x00100000 /* DBDC1_SEARCH_RULE[20] */ +#define WF_PLE_TOP_VOW_CONTROL_DBDC1_SEARCH_RULE_SHFT 20 +#define WF_PLE_TOP_VOW_CONTROL_REFILL_PERIOD_ADDR \ + WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_REFILL_PERIOD_MASK \ + 0x00070000 /* REFILL_PERIOD[18..16] */ +#define WF_PLE_TOP_VOW_CONTROL_REFILL_PERIOD_SHFT 16 +#define WF_PLE_TOP_VOW_CONTROL_PER_BSS_BW_CONTROL_ENABLE_ADDR \ + WF_PLE_TOP_VOW_CONTROL_ADDR +#define WF_PLE_TOP_VOW_CONTROL_PER_BSS_BW_CONTROL_ENABLE_MASK \ + 0x0000FFFF /* PER_BSS_BW_CONTROL_ENABLE[15..0] */ +#define WF_PLE_TOP_VOW_CONTROL_PER_BSS_BW_CONTROL_ENABLE_SHFT 0 + +/* +* ---AIRTIME_DRR_SIZE (0x820C0000 + 0x374)--- +* AIRTIME_DEFICIT_BOUNDARY[7..0] - (RW) Limits airtime DRR's maximum +deficit +* Unit: 256us +* RESERVED2[15..8] - (RW) xxx +* BW_DEFICIT_BOUNDARY[23..16] - (RW) Limits BW DRR's maximum deficit +* Unit: 256us +* DRR_TXCNT_SIZE[31..24] - (RW) Tx count mode charge time setting +* Unit: 256us +*/ +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_DRR_TXCNT_SIZE_ADDR \ + WF_PLE_TOP_AIRTIME_DRR_SIZE_ADDR +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_DRR_TXCNT_SIZE_MASK \ + 0xFF000000 /* DRR_TXCNT_SIZE[31..24] */ +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_DRR_TXCNT_SIZE_SHFT 24 +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_BW_DEFICIT_BOUNDARY_ADDR \ + WF_PLE_TOP_AIRTIME_DRR_SIZE_ADDR +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_BW_DEFICIT_BOUNDARY_MASK \ + 0x00FF0000 /* BW_DEFICIT_BOUNDARY[23..16] */ +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_BW_DEFICIT_BOUNDARY_SHFT 16 +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_RESERVED2_ADDR \ + WF_PLE_TOP_AIRTIME_DRR_SIZE_ADDR +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_RESERVED2_MASK \ + 0x0000FF00 /* RESERVED2[15..8] */ +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_RESERVED2_SHFT 8 +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_AIRTIME_DEFICIT_BOUNDARY_ADDR \ + WF_PLE_TOP_AIRTIME_DRR_SIZE_ADDR +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_AIRTIME_DEFICIT_BOUNDARY_MASK \ + 0x000000FF /* AIRTIME_DEFICIT_BOUNDARY[7..0] */ +#define WF_PLE_TOP_AIRTIME_DRR_SIZE_AIRTIME_DEFICIT_BOUNDARY_SHFT 0 + +/* +* ---CHECK_BW_TIME_TOKEN_ (0x820C0000 + 0x378)--- +* DISABLE_BW_TIME_CHECK[15..0] - (RW) HW will ignore time token +status. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CHECK_BW_TIME_TOKEN__DISABLE_BW_TIME_CHECK_ADDR \ + WF_PLE_TOP_CHECK_BW_TIME_TOKEN__ADDR +#define WF_PLE_TOP_CHECK_BW_TIME_TOKEN__DISABLE_BW_TIME_CHECK_MASK \ + 0x0000FFFF /* DISABLE_BW_TIME_CHECK[15..0] */ +#define WF_PLE_TOP_CHECK_BW_TIME_TOKEN__DISABLE_BW_TIME_CHECK_SHFT 0 + +/* +* ---CHECK_BW_LENGTH_TOKEN_ (0x820C0000 + 0x37c)--- +* DISABLE_BW_LENGTH_CHECK[15..0] - (RW) HW will ignore time token +status. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define \ +WF_PLE_TOP_CHECK_BW_LENGTH_TOKEN__DISABLE_BW_LENGTH_CHECK_ADDR \ + WF_PLE_TOP_CHECK_BW_LENGTH_TOKEN__ADDR +#define \ +WF_PLE_TOP_CHECK_BW_LENGTH_TOKEN__DISABLE_BW_LENGTH_CHECK_MASK \ + 0x0000FFFF /* DISABLE_BW_LENGTH_CHECK[15..0] */ +#define \ +WF_PLE_TOP_CHECK_BW_LENGTH_TOKEN__DISABLE_BW_LENGTH_CHECK_SHFT \ + 0 + +/* +* ---AIRTIME_QUANTUM_SETTING0 (0x820C0000 + 0x380)--- +* AIRTIME_QUANTUM0[7..0] - (RW) Airtime quantum 0 +* AIRTIME_QUANTUM1[15..8] - (RW) Airtime quantum 1 +* AIRTIME_QUANTUM2[23..16] - (RW) Airtime quantum 2 +* AIRTIME_QUANTUM3[31..24] - (RW) Airtime quantum 3 +*/ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM3_ADDR \ + WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_ADDR +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM3_MASK \ + 0xFF000000 /* AIRTIME_QUANTUM3[31..24] */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM3_SHFT 24 +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM2_ADDR \ + WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_ADDR +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM2_MASK \ + 0x00FF0000 /* AIRTIME_QUANTUM2[23..16] */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM2_SHFT 16 +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM1_ADDR \ + WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_ADDR +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM1_MASK \ + 0x0000FF00 /* AIRTIME_QUANTUM1[15..8] */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM1_SHFT 8 +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM0_ADDR \ + WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_ADDR +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM0_MASK \ + 0x000000FF /* AIRTIME_QUANTUM0[7..0] */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING0_AIRTIME_QUANTUM0_SHFT 0 + +/* +* ---AIRTIME_QUANTUM_SETTING1 (0x820C0000 + 0x384)--- +* AIRTIME_QUANTUM4[7..0] - (RW) Airtime quantum 4 +* AIRTIME_QUANTUM5[15..8] - (RW) Airtime quantum 5 +* AIRTIME_QUANTUM6[23..16] - (RW) Airtime quantum 6 +* AIRTIME_QUANTUM7[31..24] - (RW) Airtime quantum 7 +*/ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM7_ADDR \ + WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_ADDR +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM7_MASK \ + 0xFF000000 /* AIRTIME_QUANTUM7[31..24] */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM7_SHFT 24 +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM6_ADDR \ + WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_ADDR +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM6_MASK \ + 0x00FF0000 /* AIRTIME_QUANTUM6[23..16] */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM6_SHFT 16 +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM5_ADDR \ + WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_ADDR +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM5_MASK \ + 0x0000FF00 /* AIRTIME_QUANTUM5[15..8] */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM5_SHFT 8 +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM4_ADDR \ + WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_ADDR +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM4_MASK \ + 0x000000FF /* AIRTIME_QUANTUM4[7..0] */ +#define WF_PLE_TOP_AIRTIME_QUANTUM_SETTING1_AIRTIME_QUANTUM4_SHFT 0 + +/* +* ---DRR_TABLE_CTRL (0x820C0000 + 0x388)--- +* INDEX[11..0] - (RW) Operation index +* Mode 0x00: DRR STA link, STA relay +* Bit[1:0]: qid +* Bit[10:2]: Station ID +//-- +* Mode 0x20: addr[6:0] mean station ID +* Mode 0x21: addr[6:0] mean station ID +* Mode 0x22: SRAM idx (debug mode) +* Mode 0x23: SRAM idx (debug mode) +* 0~35: STA bitmap +* 36~51: STA setting +//-- +* Mode 0x40: addr[3:0] = bssid, +* Mode 0x41: addr[3:0] = bssid, +* Mode 0x42: addr[3:0] = bssid, +* Mode 0x43: addr[3:0] = bssid, +* Mode 0x44: SRAM idx (debug mode) +* Mode 0x45: SRAM idx (debug mode) +* 0~15: BSS bitmap +* 16~31: BSS setting +* 32~47: Token status +//-- +* Mode 0x81~0x83: addr[3:0] = BSS group ID +* Bit[0]: Charge bw_token +* Bit[1]: Charge bw DRR +* Mode 0x84: addr[7:0] = station ID, +* addr[11:8]= qid +* Bit[2]: Charge airtime DRR +* Bit[3]: Charge is ADD mode +* WRITE_MASK[15..12] - (RW) DRR table will not be updated if mask +* write bits are enabled. +* MODE[23..16] - (RW) Operation mode for DRR table +* WRITE_MASK_2[27..24] - (RW) DRR table will not be updated if mask +* write bits are enabled. +* RESERVED28[30..28] - (RO) Reserved bits +* EXECUTE[31] - (RW) Excutes SW command to read/write DRR +table +*/ +#define WF_PLE_TOP_DRR_TABLE_CTRL_EXECUTE_ADDR \ + WF_PLE_TOP_DRR_TABLE_CTRL_ADDR +#define WF_PLE_TOP_DRR_TABLE_CTRL_EXECUTE_MASK \ + 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_DRR_TABLE_CTRL_EXECUTE_SHFT 31 +#define WF_PLE_TOP_DRR_TABLE_CTRL_WRITE_MASK_2_ADDR \ + WF_PLE_TOP_DRR_TABLE_CTRL_ADDR +#define WF_PLE_TOP_DRR_TABLE_CTRL_WRITE_MASK_2_MASK \ + 0x0F000000 /* WRITE_MASK_2[27..24] */ +#define WF_PLE_TOP_DRR_TABLE_CTRL_WRITE_MASK_2_SHFT 24 +#define WF_PLE_TOP_DRR_TABLE_CTRL_MODE_ADDR \ + WF_PLE_TOP_DRR_TABLE_CTRL_ADDR +#define WF_PLE_TOP_DRR_TABLE_CTRL_MODE_MASK \ + 0x00FF0000 /* MODE[23..16] */ +#define WF_PLE_TOP_DRR_TABLE_CTRL_MODE_SHFT 16 +#define WF_PLE_TOP_DRR_TABLE_CTRL_WRITE_MASK_ADDR \ + WF_PLE_TOP_DRR_TABLE_CTRL_ADDR +#define WF_PLE_TOP_DRR_TABLE_CTRL_WRITE_MASK_MASK \ + 0x0000F000 /* WRITE_MASK[15..12] */ +#define WF_PLE_TOP_DRR_TABLE_CTRL_WRITE_MASK_SHFT 12 +#define WF_PLE_TOP_DRR_TABLE_CTRL_INDEX_ADDR \ + WF_PLE_TOP_DRR_TABLE_CTRL_ADDR +#define WF_PLE_TOP_DRR_TABLE_CTRL_INDEX_MASK \ + 0x00000FFF /* INDEX[11..0] */ +#define WF_PLE_TOP_DRR_TABLE_CTRL_INDEX_SHFT 0 + +/* +* ---VOW_CTRL1 (0x820C0000 + 0x38C)--- +* RESERVED0[0] - (RO) Reserved bits +* EN_BSSID_CHECK[1] - (RW) Enable control of check BSSID's trap +* state in search station +* EN_LOCK_STA[2] - (RW) Lock mode for RTS retry same sta until +* RTS drop +* EN_KEEP_QTM[3] - (RW) Not reset remain Tx time when sta has +* new packet +* EN_TXCNT_MODE[4] - (RW) Tx count weighted round robin control +* EN_TXED_MODE[5] - (RW) Txed bitmap control +* EN_RXSCH_MODE[6] - (RW) Rx scheduling with rx earlyend bitmap +control +* EN_BWRF_SRCH[7] - (RW) Bandwidth refill search control +* DIS_BSSID0_TRAP_IGNORE[8] - (RW) Disable control of the function +* that STA +* with BSSID0 trap ignore in TXQ busy +* DIS_BSSID1_TRAP_IGNORE[9] - (RW) Disable control of the function +* that STA +* with BSSID1 trap ignore in TXQ busy +* DIS_BSSID2_TRAP_IGNORE[10] - (RW) Disable control of the function +* that STA +* with BSSID2 trap ignore in TXQ busy +* DIS_BSSID3_TRAP_IGNORE[11] - (RW) Disable control of the function +* that STA +* with BSSID3 trap ignore in TXQ busy +* DIS_KEEP_TRGT_BSS[12] - (RW) Disable control of keeping BSS as +target +* station when SPL search +* RESERVED13[31..13] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_VOW_CTRL1_DIS_KEEP_TRGT_BSS_ADDR \ + WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_DIS_KEEP_TRGT_BSS_MASK \ + 0x00001000 /* DIS_KEEP_TRGT_BSS[12] */ +#define WF_PLE_TOP_VOW_CTRL1_DIS_KEEP_TRGT_BSS_SHFT 12 +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID3_TRAP_IGNORE_ADDR \ + WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID3_TRAP_IGNORE_MASK \ + 0x00000800 /* DIS_BSSID3_TRAP_IGNORE[11] */ +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID3_TRAP_IGNORE_SHFT 11 +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID2_TRAP_IGNORE_ADDR \ + WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID2_TRAP_IGNORE_MASK \ + 0x00000400 /* DIS_BSSID2_TRAP_IGNORE[10] */ +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID2_TRAP_IGNORE_SHFT 10 +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID1_TRAP_IGNORE_ADDR \ + WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID1_TRAP_IGNORE_MASK \ + 0x00000200 /* DIS_BSSID1_TRAP_IGNORE[9] */ +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID1_TRAP_IGNORE_SHFT 9 +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID0_TRAP_IGNORE_ADDR \ + WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID0_TRAP_IGNORE_MASK \ + 0x00000100 /* DIS_BSSID0_TRAP_IGNORE[8] */ +#define WF_PLE_TOP_VOW_CTRL1_DIS_BSSID0_TRAP_IGNORE_SHFT 8 +#define WF_PLE_TOP_VOW_CTRL1_EN_BWRF_SRCH_ADDR \ + WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_EN_BWRF_SRCH_MASK \ + 0x00000080 /* EN_BWRF_SRCH[7] */ +#define WF_PLE_TOP_VOW_CTRL1_EN_BWRF_SRCH_SHFT 7 +#define WF_PLE_TOP_VOW_CTRL1_EN_RXSCH_MODE_ADDR \ + WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_EN_RXSCH_MODE_MASK \ + 0x00000040 /* EN_RXSCH_MODE[6] */ +#define WF_PLE_TOP_VOW_CTRL1_EN_RXSCH_MODE_SHFT 6 +#define WF_PLE_TOP_VOW_CTRL1_EN_TXED_MODE_ADDR \ + WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_EN_TXED_MODE_MASK \ + 0x00000020 /* EN_TXED_MODE[5] */ +#define WF_PLE_TOP_VOW_CTRL1_EN_TXED_MODE_SHFT 5 +#define WF_PLE_TOP_VOW_CTRL1_EN_TXCNT_MODE_ADDR \ + WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_EN_TXCNT_MODE_MASK \ + 0x00000010 /* EN_TXCNT_MODE[4] */ +#define WF_PLE_TOP_VOW_CTRL1_EN_TXCNT_MODE_SHFT 4 +#define WF_PLE_TOP_VOW_CTRL1_EN_KEEP_QTM_ADDR \ + WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_EN_KEEP_QTM_MASK \ + 0x00000008 /* EN_KEEP_QTM[3] */ +#define WF_PLE_TOP_VOW_CTRL1_EN_KEEP_QTM_SHFT 3 +#define WF_PLE_TOP_VOW_CTRL1_EN_LOCK_STA_ADDR \ + WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_EN_LOCK_STA_MASK \ + 0x00000004 /* EN_LOCK_STA[2] */ +#define WF_PLE_TOP_VOW_CTRL1_EN_LOCK_STA_SHFT 2 +#define WF_PLE_TOP_VOW_CTRL1_EN_BSSID_CHECK_ADDR \ + WF_PLE_TOP_VOW_CTRL1_ADDR +#define WF_PLE_TOP_VOW_CTRL1_EN_BSSID_CHECK_MASK \ + 0x00000002 /* EN_BSSID_CHECK[1] */ +#define WF_PLE_TOP_VOW_CTRL1_EN_BSSID_CHECK_SHFT 1 + +/* +* ---DRR_CHNL_EMPTY (0x820C0000 + 0x390)--- +* WMM_STA_DL_EMPTY[15..0] - (RO) Indicate emptiness of 16 DL station +link +* WMM_STA_UL_EMPTY[31..16] - (RO) Indicate emptiness of 16 UL station +link +*/ +#define WF_PLE_TOP_DRR_CHNL_EMPTY_WMM_STA_UL_EMPTY_ADDR \ + WF_PLE_TOP_DRR_CHNL_EMPTY_ADDR +#define WF_PLE_TOP_DRR_CHNL_EMPTY_WMM_STA_UL_EMPTY_MASK \ + 0xFFFF0000 /* WMM_STA_UL_EMPTY[31..16] */ +#define WF_PLE_TOP_DRR_CHNL_EMPTY_WMM_STA_UL_EMPTY_SHFT 16 +#define WF_PLE_TOP_DRR_CHNL_EMPTY_WMM_STA_DL_EMPTY_ADDR \ + WF_PLE_TOP_DRR_CHNL_EMPTY_ADDR +#define WF_PLE_TOP_DRR_CHNL_EMPTY_WMM_STA_DL_EMPTY_MASK \ + 0x0000FFFF /* WMM_STA_DL_EMPTY[15..0] */ +#define WF_PLE_TOP_DRR_CHNL_EMPTY_WMM_STA_DL_EMPTY_SHFT 0 + +/* +* ---DRR_SPL_CTRL (0x820C0000 + 0x394)--- +* RESERVED0[15..0] - (RO) Reserved bits +* SUBRND_TIMES[19..16] - (RW) Subround times setting to trigger round +end +* EN_SBTG_RNDEND[20] - (RW) Enable control of round ends by subround +times +* EN_QLEN_TH[21] - (RW) Enable control of queue length +* constraint to select station +* RESERVED22[31..22] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_DRR_SPL_CTRL_EN_QLEN_TH_ADDR \ + WF_PLE_TOP_DRR_SPL_CTRL_ADDR +#define WF_PLE_TOP_DRR_SPL_CTRL_EN_QLEN_TH_MASK \ + 0x00200000 /* EN_QLEN_TH[21] */ +#define WF_PLE_TOP_DRR_SPL_CTRL_EN_QLEN_TH_SHFT 21 +#define WF_PLE_TOP_DRR_SPL_CTRL_EN_SBTG_RNDEND_ADDR \ + WF_PLE_TOP_DRR_SPL_CTRL_ADDR +#define WF_PLE_TOP_DRR_SPL_CTRL_EN_SBTG_RNDEND_MASK \ + 0x00100000 /* EN_SBTG_RNDEND[20] */ +#define WF_PLE_TOP_DRR_SPL_CTRL_EN_SBTG_RNDEND_SHFT 20 +#define WF_PLE_TOP_DRR_SPL_CTRL_SUBRND_TIMES_ADDR \ + WF_PLE_TOP_DRR_SPL_CTRL_ADDR +#define WF_PLE_TOP_DRR_SPL_CTRL_SUBRND_TIMES_MASK \ + 0x000F0000 /* SUBRND_TIMES[19..16] */ +#define WF_PLE_TOP_DRR_SPL_CTRL_SUBRND_TIMES_SHFT 16 + +/* +* ---DRR_SPL_CTRL_1 (0x820C0000 + 0x398)--- +* RESERVED0[15..0] - (RO) Reserved bits +* EN_BWRF_FILTER[16] - (RW) BW refill mode SPL with NE=1 STA_CNT=0 +* filter enable control +* RESERVED17[31..17] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_BWRF_FILTER_ADDR \ + WF_PLE_TOP_DRR_SPL_CTRL_1_ADDR +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_BWRF_FILTER_MASK \ + 0x00010000 /* EN_BWRF_FILTER[16] */ +#define WF_PLE_TOP_DRR_SPL_CTRL_1_EN_BWRF_FILTER_SHFT 16 + +/* +* ---VOW_DBG_SEL (0x820C0000 + 0x3A0)--- +* AIRTIME_DEBUG_SEL[15..0] - (RW) Selects airtime debug +* BW_DEBUG_SEL[31..16] - (RW) Selects BW control debug +*/ +#define WF_PLE_TOP_VOW_DBG_SEL_BW_DEBUG_SEL_ADDR \ + WF_PLE_TOP_VOW_DBG_SEL_ADDR +#define WF_PLE_TOP_VOW_DBG_SEL_BW_DEBUG_SEL_MASK \ + 0xFFFF0000 /* BW_DEBUG_SEL[31..16] */ +#define WF_PLE_TOP_VOW_DBG_SEL_BW_DEBUG_SEL_SHFT 16 +#define WF_PLE_TOP_VOW_DBG_SEL_AIRTIME_DEBUG_SEL_ADDR \ + WF_PLE_TOP_VOW_DBG_SEL_ADDR +#define WF_PLE_TOP_VOW_DBG_SEL_AIRTIME_DEBUG_SEL_MASK \ + 0x0000FFFF /* AIRTIME_DEBUG_SEL[15..0] */ +#define WF_PLE_TOP_VOW_DBG_SEL_AIRTIME_DEBUG_SEL_SHFT 0 + +/* +* ---AIRTIME_DBG_INFO0 (0x820C0000 + 0x3A4)--- +* AIRTIME_DBG_INFO0[31..0] - (RO) Station link head/tail +*/ +#define WF_PLE_TOP_AIRTIME_DBG_INFO0_AIRTIME_DBG_INFO0_ADDR \ + WF_PLE_TOP_AIRTIME_DBG_INFO0_ADDR +#define WF_PLE_TOP_AIRTIME_DBG_INFO0_AIRTIME_DBG_INFO0_MASK \ + 0xFFFFFFFF /* AIRTIME_DBG_INFO0[31..0] */ +#define WF_PLE_TOP_AIRTIME_DBG_INFO0_AIRTIME_DBG_INFO0_SHFT 0 + +/* +* ---AIRTIME_DBG_INFO1 (0x820C0000 + 0x3A8)--- +* AIRTIME_DBG_INFO1[31..0] - (RO) Station link head/tail +*/ +#define WF_PLE_TOP_AIRTIME_DBG_INFO1_AIRTIME_DBG_INFO1_ADDR \ + WF_PLE_TOP_AIRTIME_DBG_INFO1_ADDR +#define WF_PLE_TOP_AIRTIME_DBG_INFO1_AIRTIME_DBG_INFO1_MASK \ + 0xFFFFFFFF /* AIRTIME_DBG_INFO1[31..0] */ +#define WF_PLE_TOP_AIRTIME_DBG_INFO1_AIRTIME_DBG_INFO1_SHFT 0 + +/* +* ---DRR_SW_CTRL (0x820C0000 + 0x3C8)--- +* INDEX[15..0] - (RW) Operation index +* Mode 0x00: Bit[15:12]: QID, Bit[9:0]: wlan +ID +* Mode 0x01: Bit[15:12]: QID, Bit[9:0]: wlan +ID +* Mode 0x10: Bit[3:0]: QID +* Mode 0x11: Bit[3:0]: QID +* MODE[23..16] - (RW) IO software command mode +* RESERVED24[29..24] - (RO) Reserved bits +* SRCH_CMD_DROP[30] - (W1C) IO search command drop flag due to +* command FIFO full +* EXECUTE[31] - (RW) Executes SW command to trigger search +* event and add/remove station +*/ +#define WF_PLE_TOP_DRR_SW_CTRL_EXECUTE_ADDR \ + WF_PLE_TOP_DRR_SW_CTRL_ADDR +#define WF_PLE_TOP_DRR_SW_CTRL_EXECUTE_MASK \ + 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_DRR_SW_CTRL_EXECUTE_SHFT 31 +#define WF_PLE_TOP_DRR_SW_CTRL_SRCH_CMD_DROP_ADDR \ + WF_PLE_TOP_DRR_SW_CTRL_ADDR +#define WF_PLE_TOP_DRR_SW_CTRL_SRCH_CMD_DROP_MASK \ + 0x40000000 /* SRCH_CMD_DROP[30] */ +#define WF_PLE_TOP_DRR_SW_CTRL_SRCH_CMD_DROP_SHFT 30 +#define WF_PLE_TOP_DRR_SW_CTRL_MODE_ADDR WF_PLE_TOP_DRR_SW_CTRL_ADDR +#define WF_PLE_TOP_DRR_SW_CTRL_MODE_MASK 0x00FF0000 /* MODE[23..16] */ +#define WF_PLE_TOP_DRR_SW_CTRL_MODE_SHFT 16 +#define WF_PLE_TOP_DRR_SW_CTRL_INDEX_ADDR WF_PLE_TOP_DRR_SW_CTRL_ADDR +#define WF_PLE_TOP_DRR_SW_CTRL_INDEX_MASK \ + 0x0000FFFF /* INDEX[15..0] */ +#define WF_PLE_TOP_DRR_SW_CTRL_INDEX_SHFT 0 + +/* +* ---DRR_HW_SRCHCMD_FULL (0x820C0000 + 0x3CC)--- +* CMD_FULL_CHNL_DL[15..0] - (RW) Hardware search command full flag of +16 +* backoff channel of downlink +* CMD_FULL_CHNL_UL[31..16] - (RW) Hardware search command full flag of +16 +* backoff channel of uplink +*/ +#define WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_CMD_FULL_CHNL_UL_ADDR \ + WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_ADDR +#define WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_CMD_FULL_CHNL_UL_MASK \ + 0xFFFF0000 /* CMD_FULL_CHNL_UL[31..16] */ +#define WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_CMD_FULL_CHNL_UL_SHFT 16 +#define WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_CMD_FULL_CHNL_DL_ADDR \ + WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_ADDR +#define WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_CMD_FULL_CHNL_DL_MASK \ + 0x0000FFFF /* CMD_FULL_CHNL_DL[15..0] */ +#define WF_PLE_TOP_DRR_HW_SRCHCMD_FULL_CMD_FULL_CHNL_DL_SHFT 0 + +/* +* ---STATION_PAUSE0 (0x820C0000 + 0x400)--- +* STATION_PAUSE_0[31..0] - (RW) SW can stop station TX by this setting +* for STA0~STA31. +*/ +#define WF_PLE_TOP_STATION_PAUSE0_STATION_PAUSE_0_ADDR \ + WF_PLE_TOP_STATION_PAUSE0_ADDR +#define WF_PLE_TOP_STATION_PAUSE0_STATION_PAUSE_0_MASK \ + 0xFFFFFFFF /* STATION_PAUSE_0[31..0] */ +#define WF_PLE_TOP_STATION_PAUSE0_STATION_PAUSE_0_SHFT 0 + +/* +* ---DIS_STA_MAP0 (0x820C0000 + 0x440)--- +* DIS_STA_MAP_0[31..0] - (RW) Disable map for STA 0~31 TX +*/ +#define WF_PLE_TOP_DIS_STA_MAP0_DIS_STA_MAP_0_ADDR \ + WF_PLE_TOP_DIS_STA_MAP0_ADDR +#define WF_PLE_TOP_DIS_STA_MAP0_DIS_STA_MAP_0_MASK \ + 0xFFFFFFFF /* DIS_STA_MAP_0[31..0] */ +#define WF_PLE_TOP_DIS_STA_MAP0_DIS_STA_MAP_0_SHFT 0 + +/* +* ---STATION_REDIR0 (0x820C0000 + 0x480)--- +* STATION_REDIR_0[31..0] - (RW) SW can redirection to designed +* port/queue by this setting for STA0~STA31. +*/ +#define WF_PLE_TOP_STATION_REDIR0_STATION_REDIR_0_ADDR \ + WF_PLE_TOP_STATION_REDIR0_ADDR +#define WF_PLE_TOP_STATION_REDIR0_STATION_REDIR_0_MASK \ + 0xFFFFFFFF /* STATION_REDIR_0[31..0] */ +#define WF_PLE_TOP_STATION_REDIR0_STATION_REDIR_0_SHFT 0 + +/* +* ---TWT_STA_MAP0 (0x820C0000 + 0x4c0)--- +* TWT_STA_MAP_0[31..0] - (RW) TWT map for STA 0~31 TX +*/ +#define WF_PLE_TOP_TWT_STA_MAP0_TWT_STA_MAP_0_ADDR \ + WF_PLE_TOP_TWT_STA_MAP0_ADDR +#define WF_PLE_TOP_TWT_STA_MAP0_TWT_STA_MAP_0_MASK \ + 0xFFFFFFFF /* TWT_STA_MAP_0[31..0] */ +#define WF_PLE_TOP_TWT_STA_MAP0_TWT_STA_MAP_0_SHFT 0 + +/* +* ---AC0_QUEUE_EMPTY0 (0x820C0000 + 0x500)--- +* AC0_QUEUE_EMPTY_0[31..0] - (RO) Empty flag for STA 0~31 AC0 queue +*/ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY0_AC0_QUEUE_EMPTY_0_ADDR \ + WF_PLE_TOP_AC0_QUEUE_EMPTY0_ADDR +#define WF_PLE_TOP_AC0_QUEUE_EMPTY0_AC0_QUEUE_EMPTY_0_MASK \ + 0xFFFFFFFF /* AC0_QUEUE_EMPTY_0[31..0] */ +#define WF_PLE_TOP_AC0_QUEUE_EMPTY0_AC0_QUEUE_EMPTY_0_SHFT 0 + +/* +* ---AC1_QUEUE_EMPTY0 (0x820C0000 + 0x540)--- +* AC1_QUEUE_EMPTY_0[31..0] - (RO) Empty flag for STA 0~31 AC1 queue +*/ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY0_AC1_QUEUE_EMPTY_0_ADDR \ + WF_PLE_TOP_AC1_QUEUE_EMPTY0_ADDR +#define WF_PLE_TOP_AC1_QUEUE_EMPTY0_AC1_QUEUE_EMPTY_0_MASK \ + 0xFFFFFFFF /* AC1_QUEUE_EMPTY_0[31..0] */ +#define WF_PLE_TOP_AC1_QUEUE_EMPTY0_AC1_QUEUE_EMPTY_0_SHFT 0 + +/* +* ---AC2_QUEUE_EMPTY0 (0x820C0000 + 0x580)--- +* AC2_QUEUE_EMPTY_0[31..0] - (RO) Empty flag for STA 0~31 AC2 queue +*/ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY0_AC2_QUEUE_EMPTY_0_ADDR \ + WF_PLE_TOP_AC2_QUEUE_EMPTY0_ADDR +#define WF_PLE_TOP_AC2_QUEUE_EMPTY0_AC2_QUEUE_EMPTY_0_MASK \ + 0xFFFFFFFF /* AC2_QUEUE_EMPTY_0[31..0] */ +#define WF_PLE_TOP_AC2_QUEUE_EMPTY0_AC2_QUEUE_EMPTY_0_SHFT 0 + +/* +* ---AC3_QUEUE_EMPTY0 (0x820C0000 + 0x5c0)--- +* AC3_QUEUE_EMPTY_0[31..0] - (RO) Empty flag for STA 0~31 AC3 queue +*/ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY0_AC3_QUEUE_EMPTY_0_ADDR \ + WF_PLE_TOP_AC3_QUEUE_EMPTY0_ADDR +#define WF_PLE_TOP_AC3_QUEUE_EMPTY0_AC3_QUEUE_EMPTY_0_MASK \ + 0xFFFFFFFF /* AC3_QUEUE_EMPTY_0[31..0] */ +#define WF_PLE_TOP_AC3_QUEUE_EMPTY0_AC3_QUEUE_EMPTY_0_SHFT 0 + +/* +* ---DRR_TABLE_WDATA4 (0x820C0000 + 0x680)--- +* DRR_TABLE_WDATA[31..0] - (RW) DRRwdata[159:128] for reading/writing +* DRR table +* Mode 0x4?: BSS mode +* See SRAM layout. +*/ +#define WF_PLE_TOP_DRR_TABLE_WDATA4_DRR_TABLE_WDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_WDATA4_ADDR +#define WF_PLE_TOP_DRR_TABLE_WDATA4_DRR_TABLE_WDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_WDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_WDATA4_DRR_TABLE_WDATA_SHFT 0 + +/* +* ---DRR_TABLE_WDATA5 (0x820C0000 + 0x684)--- +* DRR_TABLE_WDATA[31..0] - (RW) DRR wdata[191:160] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_WDATA5_DRR_TABLE_WDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_WDATA5_ADDR +#define WF_PLE_TOP_DRR_TABLE_WDATA5_DRR_TABLE_WDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_WDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_WDATA5_DRR_TABLE_WDATA_SHFT 0 + +/* +* ---DRR_TABLE_WDATA6 (0x820C0000 + 0x688)--- +* DRR_TABLE_WDATA[31..0] - (RW) DRR wdata[223:192] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_WDATA6_DRR_TABLE_WDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_WDATA6_ADDR +#define WF_PLE_TOP_DRR_TABLE_WDATA6_DRR_TABLE_WDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_WDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_WDATA6_DRR_TABLE_WDATA_SHFT 0 + +/* +* ---DRR_TABLE_WDATA7 (0x820C0000 + 0x68c)--- +* DRR_TABLE_WDATA[31..0] - (RW) DRR wdata[255:224] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_WDATA7_DRR_TABLE_WDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_WDATA7_ADDR +#define WF_PLE_TOP_DRR_TABLE_WDATA7_DRR_TABLE_WDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_WDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_WDATA7_DRR_TABLE_WDATA_SHFT 0 + +/* +* ---DRR_TABLE_RDATA4 (0x820C0000 + 0x690)--- +* DRR_TABLE_RDATA[31..0] - (RW) DRR rdata[159:128] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_RDATA4_DRR_TABLE_RDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_RDATA4_ADDR +#define WF_PLE_TOP_DRR_TABLE_RDATA4_DRR_TABLE_RDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_RDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_RDATA4_DRR_TABLE_RDATA_SHFT 0 + +/* +* ---DRR_TABLE_RDATA5 (0x820C0000 + 0x694)--- +* DRR_TABLE_RDATA[31..0] - (RW) DRR rdata[191:160] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_RDATA5_DRR_TABLE_RDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_RDATA5_ADDR +#define WF_PLE_TOP_DRR_TABLE_RDATA5_DRR_TABLE_RDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_RDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_RDATA5_DRR_TABLE_RDATA_SHFT 0 + +/* +* ---DRR_TABLE_RDATA6 (0x820C0000 + 0x698)--- +* DRR_TABLE_RDATA[31..0] - (RW) DRR rdata[223:192] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_RDATA6_DRR_TABLE_RDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_RDATA6_ADDR +#define WF_PLE_TOP_DRR_TABLE_RDATA6_DRR_TABLE_RDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_RDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_RDATA6_DRR_TABLE_RDATA_SHFT 0 + +/* +* ---DRR_TABLE_RDATA7 (0x820C0000 + 0x69c)--- +* DRR_TABLE_RDATA[31..0] - (RW) DRR rdata[255:224] for reading/writing +* DRR table +*/ +#define WF_PLE_TOP_DRR_TABLE_RDATA7_DRR_TABLE_RDATA_ADDR \ + WF_PLE_TOP_DRR_TABLE_RDATA7_ADDR +#define WF_PLE_TOP_DRR_TABLE_RDATA7_DRR_TABLE_RDATA_MASK \ + 0xFFFFFFFF /* DRR_TABLE_RDATA[31..0] */ +#define WF_PLE_TOP_DRR_TABLE_RDATA7_DRR_TABLE_RDATA_SHFT 0 + +/* +* ---TWT_STA_TABLE0 (0x820C0000 + 0x6a0)--- +* TWT_STA_0[9..0] - (RW) TWT station 0 WLAN ID +* RESERVED10[15..10] - (RO) Reserved bits +* TWT_STA_1[25..16] - (RW) TWT station 1 WLAN ID +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TWT_STA_TABLE0_TWT_STA_1_ADDR \ + WF_PLE_TOP_TWT_STA_TABLE0_ADDR +#define WF_PLE_TOP_TWT_STA_TABLE0_TWT_STA_1_MASK \ + 0x03FF0000 /* TWT_STA_1[25..16] */ +#define WF_PLE_TOP_TWT_STA_TABLE0_TWT_STA_1_SHFT 16 +#define WF_PLE_TOP_TWT_STA_TABLE0_TWT_STA_0_ADDR \ + WF_PLE_TOP_TWT_STA_TABLE0_ADDR +#define WF_PLE_TOP_TWT_STA_TABLE0_TWT_STA_0_MASK \ + 0x000003FF /* TWT_STA_0[9..0] */ +#define WF_PLE_TOP_TWT_STA_TABLE0_TWT_STA_0_SHFT 0 + +/* +* ---TWT_STA_TABLE1 (0x820C0000 + 0x6a4)--- +* TWT_STA_2[9..0] - (RW) TWT station 2 WLAN ID +* RESERVED10[15..10] - (RO) Reserved bits +* TWT_STA_3[25..16] - (RW) TWT station 3 WLAN ID +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TWT_STA_TABLE1_TWT_STA_3_ADDR \ + WF_PLE_TOP_TWT_STA_TABLE1_ADDR +#define WF_PLE_TOP_TWT_STA_TABLE1_TWT_STA_3_MASK \ + 0x03FF0000 /* TWT_STA_3[25..16] */ +#define WF_PLE_TOP_TWT_STA_TABLE1_TWT_STA_3_SHFT 16 +#define WF_PLE_TOP_TWT_STA_TABLE1_TWT_STA_2_ADDR \ + WF_PLE_TOP_TWT_STA_TABLE1_ADDR +#define WF_PLE_TOP_TWT_STA_TABLE1_TWT_STA_2_MASK \ + 0x000003FF /* TWT_STA_2[9..0] */ +#define WF_PLE_TOP_TWT_STA_TABLE1_TWT_STA_2_SHFT 0 + +/* +* ---TWT_STA_TABLE2 (0x820C0000 + 0x6a8)--- +* TWT_STA_4[9..0] - (RW) TWT station 4 WLAN ID +* RESERVED10[15..10] - (RO) Reserved bits +* TWT_STA_5[25..16] - (RW) TWT station 5 WLAN ID +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TWT_STA_TABLE2_TWT_STA_5_ADDR \ + WF_PLE_TOP_TWT_STA_TABLE2_ADDR +#define WF_PLE_TOP_TWT_STA_TABLE2_TWT_STA_5_MASK \ + 0x03FF0000 /* TWT_STA_5[25..16] */ +#define WF_PLE_TOP_TWT_STA_TABLE2_TWT_STA_5_SHFT 16 +#define WF_PLE_TOP_TWT_STA_TABLE2_TWT_STA_4_ADDR \ + WF_PLE_TOP_TWT_STA_TABLE2_ADDR +#define WF_PLE_TOP_TWT_STA_TABLE2_TWT_STA_4_MASK \ + 0x000003FF /* TWT_STA_4[9..0] */ +#define WF_PLE_TOP_TWT_STA_TABLE2_TWT_STA_4_SHFT 0 + +/* +* ---TWT_STA_TABLE3 (0x820C0000 + 0x6ac)--- +* TWT_STA_6[9..0] - (RW) TWT station 6 WLAN ID +* RESERVED10[15..10] - (RO) Reserved bits +* TWT_STA_7[25..16] - (RW) TWT station 7 WLAN ID +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TWT_STA_TABLE3_TWT_STA_7_ADDR \ + WF_PLE_TOP_TWT_STA_TABLE3_ADDR +#define WF_PLE_TOP_TWT_STA_TABLE3_TWT_STA_7_MASK \ + 0x03FF0000 /* TWT_STA_7[25..16] */ +#define WF_PLE_TOP_TWT_STA_TABLE3_TWT_STA_7_SHFT 16 +#define WF_PLE_TOP_TWT_STA_TABLE3_TWT_STA_6_ADDR \ + WF_PLE_TOP_TWT_STA_TABLE3_ADDR +#define WF_PLE_TOP_TWT_STA_TABLE3_TWT_STA_6_MASK \ + 0x000003FF /* TWT_STA_6[9..0] */ +#define WF_PLE_TOP_TWT_STA_TABLE3_TWT_STA_6_SHFT 0 + +/* +* ---TWT_SW_CTRL (0x820C0000 + 0x6b0)--- +* INDEX[15..0] - (RW) Operation index +* Mode 0x00/0x01/0x08/0x09: Bit[3:0]: station +number +* Mode 0x10/0x11: Bit[3:0]: table index +* MODE[23..16] - (RW) IO software command mode +* RESERVED24[29..24] - (RO) Reserved bits +* SRCH_CMD_DROP[30] - (W1C) IO search command drop flag due to +* command FIFO full +* EXECUTE[31] - (RW) Executes SW command to trigger TWT +* search event and add/remove TWT station +*/ +#define WF_PLE_TOP_TWT_SW_CTRL_EXECUTE_ADDR \ + WF_PLE_TOP_TWT_SW_CTRL_ADDR +#define WF_PLE_TOP_TWT_SW_CTRL_EXECUTE_MASK \ + 0x80000000 /* EXECUTE[31] */ +#define WF_PLE_TOP_TWT_SW_CTRL_EXECUTE_SHFT 31 +#define WF_PLE_TOP_TWT_SW_CTRL_SRCH_CMD_DROP_ADDR \ + WF_PLE_TOP_TWT_SW_CTRL_ADDR +#define WF_PLE_TOP_TWT_SW_CTRL_SRCH_CMD_DROP_MASK \ + 0x40000000 /* SRCH_CMD_DROP[30] */ +#define WF_PLE_TOP_TWT_SW_CTRL_SRCH_CMD_DROP_SHFT 30 +#define WF_PLE_TOP_TWT_SW_CTRL_MODE_ADDR WF_PLE_TOP_TWT_SW_CTRL_ADDR +#define WF_PLE_TOP_TWT_SW_CTRL_MODE_MASK 0x00FF0000 /* MODE[23..16] */ +#define WF_PLE_TOP_TWT_SW_CTRL_MODE_SHFT 16 +#define WF_PLE_TOP_TWT_SW_CTRL_INDEX_ADDR WF_PLE_TOP_TWT_SW_CTRL_ADDR +#define WF_PLE_TOP_TWT_SW_CTRL_INDEX_MASK \ + 0x0000FFFF /* INDEX[15..0] */ +#define WF_PLE_TOP_TWT_SW_CTRL_INDEX_SHFT 0 + +/* +* ---TWT_DBG (0x820C0000 + 0x6b4)--- +* TABLE_IDX_SEL[2..0] - (RW) Station index selection +* UL_TABLE_SEL[3] - (RW) Downlink/uplink station table selection +* RESERVED4[15..4] - (RO) Reserved bits +* TABLE_WLAN_ID[25..16] - (RO) Station WLAN ID in station table +* RESERVED26[27..26] - (RO) Reserved bits +* STA_CNT[31..28] - (RO) Valid station count in station table +*/ +#define WF_PLE_TOP_TWT_DBG_STA_CNT_ADDR WF_PLE_TOP_TWT_DBG_ADDR +#define WF_PLE_TOP_TWT_DBG_STA_CNT_MASK \ + 0xF0000000 /* STA_CNT[31..28] */ +#define WF_PLE_TOP_TWT_DBG_STA_CNT_SHFT 28 +#define WF_PLE_TOP_TWT_DBG_TABLE_WLAN_ID_ADDR WF_PLE_TOP_TWT_DBG_ADDR +#define WF_PLE_TOP_TWT_DBG_TABLE_WLAN_ID_MASK \ + 0x03FF0000 /* TABLE_WLAN_ID[25..16] */ +#define WF_PLE_TOP_TWT_DBG_TABLE_WLAN_ID_SHFT 16 +#define WF_PLE_TOP_TWT_DBG_UL_TABLE_SEL_ADDR WF_PLE_TOP_TWT_DBG_ADDR +#define WF_PLE_TOP_TWT_DBG_UL_TABLE_SEL_MASK \ + 0x00000008 /* UL_TABLE_SEL[3] */ +#define WF_PLE_TOP_TWT_DBG_UL_TABLE_SEL_SHFT 3 +#define WF_PLE_TOP_TWT_DBG_TABLE_IDX_SEL_ADDR WF_PLE_TOP_TWT_DBG_ADDR +#define WF_PLE_TOP_TWT_DBG_TABLE_IDX_SEL_MASK \ + 0x00000007 /* TABLE_IDX_SEL[2..0] */ +#define WF_PLE_TOP_TWT_DBG_TABLE_IDX_SEL_SHFT 0 + +/* +* ---TWT_HW_SRCHCMD_FULL (0x820C0000 + 0x6b8)--- +* TWT_SRCH_DL_FULL[0] - (RW) TWT hardware downlink search command +* full flag +* TWT_SRCH_UL_FULL[1] - (RW) TWT hardware uplink search command full +flag +* RESERVED2[31..2] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_TWT_HW_SRCHCMD_FULL_TWT_SRCH_UL_FULL_ADDR \ + WF_PLE_TOP_TWT_HW_SRCHCMD_FULL_ADDR +#define WF_PLE_TOP_TWT_HW_SRCHCMD_FULL_TWT_SRCH_UL_FULL_MASK \ + 0x00000002 /* TWT_SRCH_UL_FULL[1] */ +#define WF_PLE_TOP_TWT_HW_SRCHCMD_FULL_TWT_SRCH_UL_FULL_SHFT 1 +#define WF_PLE_TOP_TWT_HW_SRCHCMD_FULL_TWT_SRCH_DL_FULL_ADDR \ + WF_PLE_TOP_TWT_HW_SRCHCMD_FULL_ADDR +#define WF_PLE_TOP_TWT_HW_SRCHCMD_FULL_TWT_SRCH_DL_FULL_MASK \ + 0x00000001 /* TWT_SRCH_DL_FULL[0] */ +#define WF_PLE_TOP_TWT_HW_SRCHCMD_FULL_TWT_SRCH_DL_FULL_SHFT 0 + +/* +* ---AMSDU_GC (0x820C0000 + 0x1000)--- +* EN_HW_AMSDU[0] - (RW) Enable control of HW AMSDU function. +* RESERVED1[7..1] - (RO) Reserved bits +* DIS_AMSDU_Q_EMPTY_FLUSH[8] - (RW) Disable control of HW AMSDU queue +empty +* trigger packet flush function. +* DIS_LMAC_TX_NO_FULL_FLUSH[9] - (RW) Disable control of LMAC TX no +* get full +* packet trigger packet flush function. +* DIS_SFD_KEEP_SAME_PAGE[10] - (RW) Disable control of keep same page +number +* of StoreForward packet function. +* RESERVED11[31..11] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_GC_DIS_SFD_KEEP_SAME_PAGE_ADDR \ + WF_PLE_TOP_AMSDU_GC_ADDR +#define WF_PLE_TOP_AMSDU_GC_DIS_SFD_KEEP_SAME_PAGE_MASK \ + 0x00000400 /* DIS_SFD_KEEP_SAME_PAGE[10] */ +#define WF_PLE_TOP_AMSDU_GC_DIS_SFD_KEEP_SAME_PAGE_SHFT 10 +#define WF_PLE_TOP_AMSDU_GC_DIS_LMAC_TX_NO_FULL_FLUSH_ADDR \ + WF_PLE_TOP_AMSDU_GC_ADDR +#define WF_PLE_TOP_AMSDU_GC_DIS_LMAC_TX_NO_FULL_FLUSH_MASK \ + 0x00000200 /* DIS_LMAC_TX_NO_FULL_FLUSH[9] */ +#define WF_PLE_TOP_AMSDU_GC_DIS_LMAC_TX_NO_FULL_FLUSH_SHFT 9 +#define WF_PLE_TOP_AMSDU_GC_DIS_AMSDU_Q_EMPTY_FLUSH_ADDR \ + WF_PLE_TOP_AMSDU_GC_ADDR +#define WF_PLE_TOP_AMSDU_GC_DIS_AMSDU_Q_EMPTY_FLUSH_MASK \ + 0x00000100 /* DIS_AMSDU_Q_EMPTY_FLUSH[8] */ +#define WF_PLE_TOP_AMSDU_GC_DIS_AMSDU_Q_EMPTY_FLUSH_SHFT 8 +#define WF_PLE_TOP_AMSDU_GC_EN_HW_AMSDU_ADDR WF_PLE_TOP_AMSDU_GC_ADDR +#define WF_PLE_TOP_AMSDU_GC_EN_HW_AMSDU_MASK \ + 0x00000001 /* EN_HW_AMSDU[0] */ +#define WF_PLE_TOP_AMSDU_GC_EN_HW_AMSDU_SHFT 0 + +/* +* ---AMSDU_TXD_COMP_MAP_0 (0x820C0000 + 0x1004)--- +* TXDIN_TRIGGER_TH[11..0] - (RW) The TXD merge trigger threshold. +* RESERVED12[15..12] - (RO) Reserved bits +* TXD_COMPARE_NEED_MAP[31..16] - (RW) The compare bitmap for merging +TXD. +*/ +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_TXD_COMPARE_NEED_MAP_ADDR \ + WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_ADDR +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_TXD_COMPARE_NEED_MAP_MASK \ + 0xFFFF0000 /* TXD_COMPARE_NEED_MAP[31..16] */ +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_TXD_COMPARE_NEED_MAP_SHFT 16 +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_TXDIN_TRIGGER_TH_ADDR \ + WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_ADDR +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_TXDIN_TRIGGER_TH_MASK \ + 0x00000FFF /* TXDIN_TRIGGER_TH[11..0] */ +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_0_TXDIN_TRIGGER_TH_SHFT 0 + +/* +* ---AMSDU_TXD_COMP_MAP_1 (0x820C0000 + 0x1008)--- +* TXD_COMPARE_NEED_MAP[31..0] - (RW) The compare bitmap for merging +TXD. +*/ +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_1_TXD_COMPARE_NEED_MAP_ADDR \ + WF_PLE_TOP_AMSDU_TXD_COMP_MAP_1_ADDR +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_1_TXD_COMPARE_NEED_MAP_MASK \ + 0xFFFFFFFF /* TXD_COMPARE_NEED_MAP[31..0] */ +#define WF_PLE_TOP_AMSDU_TXD_COMP_MAP_1_TXD_COMPARE_NEED_MAP_SHFT 0 + +/* +* ---AMSDU_INT_N9_ERR_STS (0x820C0000 + 0x1028)--- +* AMSDU_Q_CMD_ERR[0] - (W1C) Queue command error interrupt status of +* port AMSDU. Avoid unclear error flag, please clear flag when logic +reset. +* RESERVED1[3..1] - (RO) Reserved bits +* AMSDU_PAGE_UDF[4] - (W1C) Page underflow interrupt status of port +* AMSDU. Avoid unclear error flag, please clear flag when logic reset. +* RESERVED5[11..5] - (RO) Reserved bits +* AMSDU_DATA_OPER_ERR[12] - (W1C) Data operation error of port AMSDU. +* Avoid unclear error flag, please clear flag when logic reset. +* RESERVED13[15..13] - (RO) Reserved bits +* AMSDU_PORT_HANG_ERR[16] - (W1C) AMSDU port FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* AMSDU_CTRL_HANG_ERR[17] - (W1C) AMSDU FSM hang error interrupt. +Avoid +* unclear error flag, please clear flag when logic reset. +* RESERVED18[31..18] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_CTRL_HANG_ERR_ADDR \ + WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_CTRL_HANG_ERR_MASK \ + 0x00020000 /* AMSDU_CTRL_HANG_ERR[17] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_CTRL_HANG_ERR_SHFT 17 +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_PORT_HANG_ERR_ADDR \ + WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_PORT_HANG_ERR_MASK \ + 0x00010000 /* AMSDU_PORT_HANG_ERR[16] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_PORT_HANG_ERR_SHFT 16 +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_DATA_OPER_ERR_ADDR \ + WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_DATA_OPER_ERR_MASK \ + 0x00001000 /* AMSDU_DATA_OPER_ERR[12] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_DATA_OPER_ERR_SHFT 12 +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_PAGE_UDF_ADDR \ + WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_PAGE_UDF_MASK \ + 0x00000010 /* AMSDU_PAGE_UDF[4] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_PAGE_UDF_SHFT 4 +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_Q_CMD_ERR_ADDR \ + WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_Q_CMD_ERR_MASK \ + 0x00000001 /* AMSDU_Q_CMD_ERR[0] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_STS_AMSDU_Q_CMD_ERR_SHFT 0 + +/* +* ---AMSDU_INT_N9_ERR_MASK (0x820C0000 + 0x102C)--- +* EN_AMSDU_Q_CMD_ERR[0] - (RW) Enables queue command error interrupt +* status of port AMSDU +* RESERVED1[3..1] - (RO) Reserved bits +* EN_AMSDU_PAGE_UDF[4] - (RW) Enables page underflow interrupt status +* of port AMSDU +* RESERVED5[11..5] - (RO) Reserved bits +* EN_AMSDU_DATA_OPER_ERR[12] - (RW) Enables data operation error of +port +AMSDU +* RESERVED13[15..13] - (RO) Reserved bits +* EN_AMSDU_PORT_HANG_ERR[16] - (RW) Enables AMSDU port FSM hang error +interrupt +* EN_AMSDU_CTRL_HANG_ERR[17] - (RW) Enables AMSDU CTRL FSM hang error +interrupt +* RESERVED18[31..18] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_CTRL_HANG_ERR_ADDR \ + WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_CTRL_HANG_ERR_MASK \ + 0x00020000 /* EN_AMSDU_CTRL_HANG_ERR[17] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_CTRL_HANG_ERR_SHFT \ + 17 +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_PORT_HANG_ERR_ADDR \ + WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_PORT_HANG_ERR_MASK \ + 0x00010000 /* EN_AMSDU_PORT_HANG_ERR[16] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_PORT_HANG_ERR_SHFT \ + 16 +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_DATA_OPER_ERR_ADDR \ + WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_DATA_OPER_ERR_MASK \ + 0x00001000 /* EN_AMSDU_DATA_OPER_ERR[12] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_DATA_OPER_ERR_SHFT \ + 12 +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_PAGE_UDF_ADDR \ + WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_PAGE_UDF_MASK \ + 0x00000010 /* EN_AMSDU_PAGE_UDF[4] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_PAGE_UDF_SHFT 4 +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_Q_CMD_ERR_ADDR \ + WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_ADDR +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_Q_CMD_ERR_MASK \ + 0x00000001 /* EN_AMSDU_Q_CMD_ERR[0] */ +#define WF_PLE_TOP_AMSDU_INT_N9_ERR_MASK_EN_AMSDU_Q_CMD_ERR_SHFT 0 + +/* +* ---AMSDU_PEEK_CR_00 (0x820C0000 + 0x10d0)--- +* AMSDU_DOP_CS[3..0] - (RO) AMSDU Data operation current state. +* RESERVED4[7..4] - (RO) Reserved bits +* AMSDU_CS[12..8] - (RO) AMSDU Merge Engine current state. +* RESERVED13[15..13] - (RO) Reserved bits +* AMSDU_Q_EMPTY_CS[17..16] - (RO) AMSDU Queue Empty Search Engine +current +state. +* RESERVED18[23..18] - (RO) Reserved bits +* AMSDU_ARB_CS[26..24] - (RO) AMSDU Request Arbitration Current state. +* RESERVED27[31..27] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_ARB_CS_ADDR \ + WF_PLE_TOP_AMSDU_PEEK_CR_00_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_ARB_CS_MASK \ + 0x07000000 /* AMSDU_ARB_CS[26..24] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_ARB_CS_SHFT 24 +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_Q_EMPTY_CS_ADDR \ + WF_PLE_TOP_AMSDU_PEEK_CR_00_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_Q_EMPTY_CS_MASK \ + 0x00030000 /* AMSDU_Q_EMPTY_CS[17..16] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_Q_EMPTY_CS_SHFT 16 +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_CS_ADDR \ + WF_PLE_TOP_AMSDU_PEEK_CR_00_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_CS_MASK \ + 0x00001F00 /* AMSDU_CS[12..8] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_CS_SHFT 8 +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_DOP_CS_ADDR \ + WF_PLE_TOP_AMSDU_PEEK_CR_00_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_DOP_CS_MASK \ + 0x0000000F /* AMSDU_DOP_CS[3..0] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_00_AMSDU_DOP_CS_SHFT 0 + +/* +* ---AMSDU_PEEK_CR_01 (0x820C0000 + 0x10d4)--- +* AMSDU_DOP_PBUF_CS[2..0] - (RO) PLE AMSDU port - Data operation PBUF +* current state. +* RESERVED3[3] - (RO) Reserved bits +* AMSDU_DOP_CACHE_CS[5..4] - (RO) PLE AMSDU port - Data operation +CACHE +* current state. +* RESERVED6[7..6] - (RO) Reserved bits +* AMSDU_QOP_Q_OPER_CS[11..8] - (RO) PLE AMSDU port - Queue operation +current +state. +* AMSDU_QOP_RL_OCP_CS[13..12] - (RO) PLE AMSDU port - Queue operation +RL +* current state. +* RESERVED14[15..14] - (RO) Reserved bits +* AMSDU_QOP_PL_OCP_CS[17..16] - (RO) PLE AMSDU port - Queue operation +PL +* current state. +* RESERVED18[19..18] - (RO) Reserved bits +* AMSDU_QOP_ALLOCATE_CS[22..20] - (RO) PLE AMSDU port - Queue +operation +* allocate current state. +* RESERVED23[31..23] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_ALLOCATE_CS_ADDR \ + WF_PLE_TOP_AMSDU_PEEK_CR_01_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_ALLOCATE_CS_MASK \ + 0x00700000 /* AMSDU_QOP_ALLOCATE_CS[22..20] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_ALLOCATE_CS_SHFT 20 +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_PL_OCP_CS_ADDR \ + WF_PLE_TOP_AMSDU_PEEK_CR_01_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_PL_OCP_CS_MASK \ + 0x00030000 /* AMSDU_QOP_PL_OCP_CS[17..16] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_PL_OCP_CS_SHFT 16 +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_RL_OCP_CS_ADDR \ + WF_PLE_TOP_AMSDU_PEEK_CR_01_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_RL_OCP_CS_MASK \ + 0x00003000 /* AMSDU_QOP_RL_OCP_CS[13..12] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_RL_OCP_CS_SHFT 12 +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_Q_OPER_CS_ADDR \ + WF_PLE_TOP_AMSDU_PEEK_CR_01_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_Q_OPER_CS_MASK \ + 0x00000F00 /* AMSDU_QOP_Q_OPER_CS[11..8] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_QOP_Q_OPER_CS_SHFT 8 +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_DOP_CACHE_CS_ADDR \ + WF_PLE_TOP_AMSDU_PEEK_CR_01_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_DOP_CACHE_CS_MASK \ + 0x00000030 /* AMSDU_DOP_CACHE_CS[5..4] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_DOP_CACHE_CS_SHFT 4 +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_DOP_PBUF_CS_ADDR \ + WF_PLE_TOP_AMSDU_PEEK_CR_01_ADDR +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_DOP_PBUF_CS_MASK \ + 0x00000007 /* AMSDU_DOP_PBUF_CS[2..0] */ +#define WF_PLE_TOP_AMSDU_PEEK_CR_01_AMSDU_DOP_PBUF_CS_SHFT 0 + +/* +* ---AMSDU_PACK_1_MSDU_CNT (0x820C0000 + 0x10e0)--- +* pack_1_msdu_cnt[15..0] - (RC) AMSDU pack count of 1 MSDU in TXD. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PACK_1_MSDU_CNT_pack_1_msdu_cnt_ADDR \ + WF_PLE_TOP_AMSDU_PACK_1_MSDU_CNT_ADDR +#define WF_PLE_TOP_AMSDU_PACK_1_MSDU_CNT_pack_1_msdu_cnt_MASK \ + 0x0000FFFF /* pack_1_msdu_cnt[15..0] */ +#define WF_PLE_TOP_AMSDU_PACK_1_MSDU_CNT_pack_1_msdu_cnt_SHFT 0 + +/* +* ---AMSDU_PACK_2_MSDU_CNT (0x820C0000 + 0x10e4)--- +* pack_2_msdu_cnt[15..0] - (RC) AMSDU pack count of 2 MSDU in TXD. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PACK_2_MSDU_CNT_pack_2_msdu_cnt_ADDR \ + WF_PLE_TOP_AMSDU_PACK_2_MSDU_CNT_ADDR +#define WF_PLE_TOP_AMSDU_PACK_2_MSDU_CNT_pack_2_msdu_cnt_MASK \ + 0x0000FFFF /* pack_2_msdu_cnt[15..0] */ +#define WF_PLE_TOP_AMSDU_PACK_2_MSDU_CNT_pack_2_msdu_cnt_SHFT 0 + +/* +* ---AMSDU_PACK_3_MSDU_CNT (0x820C0000 + 0x10e8)--- +* pack_3_msdu_cnt[15..0] - (RC) AMSDU pack count of 3 MSDU in TXD. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PACK_3_MSDU_CNT_pack_3_msdu_cnt_ADDR \ + WF_PLE_TOP_AMSDU_PACK_3_MSDU_CNT_ADDR +#define WF_PLE_TOP_AMSDU_PACK_3_MSDU_CNT_pack_3_msdu_cnt_MASK \ + 0x0000FFFF /* pack_3_msdu_cnt[15..0] */ +#define WF_PLE_TOP_AMSDU_PACK_3_MSDU_CNT_pack_3_msdu_cnt_SHFT 0 + +/* +* ---AMSDU_PACK_4_MSDU_CNT (0x820C0000 + 0x10ec)--- +* pack_4_msdu_cnt[15..0] - (RC) AMSDU pack count of 4 MSDU in TXD. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PACK_4_MSDU_CNT_pack_4_msdu_cnt_ADDR \ + WF_PLE_TOP_AMSDU_PACK_4_MSDU_CNT_ADDR +#define WF_PLE_TOP_AMSDU_PACK_4_MSDU_CNT_pack_4_msdu_cnt_MASK \ + 0x0000FFFF /* pack_4_msdu_cnt[15..0] */ +#define WF_PLE_TOP_AMSDU_PACK_4_MSDU_CNT_pack_4_msdu_cnt_SHFT 0 + +/* +* ---AMSDU_PACK_5_MSDU_CNT (0x820C0000 + 0x10f0)--- +* pack_5_msdu_cnt[15..0] - (RC) AMSDU pack count of 5 MSDU in TXD. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PACK_5_MSDU_CNT_pack_5_msdu_cnt_ADDR \ + WF_PLE_TOP_AMSDU_PACK_5_MSDU_CNT_ADDR +#define WF_PLE_TOP_AMSDU_PACK_5_MSDU_CNT_pack_5_msdu_cnt_MASK \ + 0x0000FFFF /* pack_5_msdu_cnt[15..0] */ +#define WF_PLE_TOP_AMSDU_PACK_5_MSDU_CNT_pack_5_msdu_cnt_SHFT 0 + +/* +* ---AMSDU_PACK_6_MSDU_CNT (0x820C0000 + 0x10f4)--- +* pack_6_msdu_cnt[15..0] - (RC) AMSDU pack count of 4 MSDU in TXD. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PACK_6_MSDU_CNT_pack_6_msdu_cnt_ADDR \ + WF_PLE_TOP_AMSDU_PACK_6_MSDU_CNT_ADDR +#define WF_PLE_TOP_AMSDU_PACK_6_MSDU_CNT_pack_6_msdu_cnt_MASK \ + 0x0000FFFF /* pack_6_msdu_cnt[15..0] */ +#define WF_PLE_TOP_AMSDU_PACK_6_MSDU_CNT_pack_6_msdu_cnt_SHFT 0 + +/* +* ---AMSDU_PACK_7_MSDU_CNT (0x820C0000 + 0x10f8)--- +* pack_7_msdu_cnt[15..0] - (RC) AMSDU pack count of 7 MSDU in TXD. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PACK_7_MSDU_CNT_pack_7_msdu_cnt_ADDR \ + WF_PLE_TOP_AMSDU_PACK_7_MSDU_CNT_ADDR +#define WF_PLE_TOP_AMSDU_PACK_7_MSDU_CNT_pack_7_msdu_cnt_MASK \ + 0x0000FFFF /* pack_7_msdu_cnt[15..0] */ +#define WF_PLE_TOP_AMSDU_PACK_7_MSDU_CNT_pack_7_msdu_cnt_SHFT 0 + +/* +* ---AMSDU_PACK_8_MSDU_CNT (0x820C0000 + 0x10fc)--- +* pack_8_msdu_cnt[15..0] - (RC) AMSDU pack count of 8 MSDU in TXD. +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_AMSDU_PACK_8_MSDU_CNT_pack_8_msdu_cnt_ADDR \ + WF_PLE_TOP_AMSDU_PACK_8_MSDU_CNT_ADDR +#define WF_PLE_TOP_AMSDU_PACK_8_MSDU_CNT_pack_8_msdu_cnt_MASK \ + 0x0000FFFF /* pack_8_msdu_cnt[15..0] */ +#define WF_PLE_TOP_AMSDU_PACK_8_MSDU_CNT_pack_8_msdu_cnt_SHFT 0 + +/* +* ---AMSDU_AC0_QUEUE_EMPTY0 (0x820C0000 + 0x1100)--- +* AMSDU_QUEUE_EMPTY_FLAG_31_0[31..0] - (RO) AC0 queue empty flag for +* station31~station0 in HW AMSDU engine. +*/ +#define \ +WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_ADDR \ + WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY0_ADDR +#define \ +WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_MASK \ + 0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_31_0[31..0] */ +#define \ +WF_PLE_TOP_AMSDU_AC0_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_SHFT \ + 0 + +/* +* ---AMSDU_AC1_QUEUE_EMPTY0 (0x820C0000 + 0x1140)--- +* AMSDU_QUEUE_EMPTY_FLAG_31_0[31..0] - (RO) AC1 queue empty flag for +* station31~station0 in HW AMSDU engine. +*/ +#define \ +WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_ADDR \ + WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY0_ADDR +#define \ +WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_MASK \ + 0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_31_0[31..0] */ +#define \ +WF_PLE_TOP_AMSDU_AC1_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_SHFT \ + 0 + +/* +* ---AMSDU_AC2_QUEUE_EMPTY0 (0x820C0000 + 0x1180)--- +* AMSDU_QUEUE_EMPTY_FLAG_31_0[31..0] - (RO) AC2 queue empty flag for +* station31~station0 in HW AMSDU engine. +*/ +#define \ +WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_ADDR \ + WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY0_ADDR +#define \ +WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_MASK \ + 0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_31_0[31..0] */ +#define \ +WF_PLE_TOP_AMSDU_AC2_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_SHFT \ + 0 + +/* +* ---AMSDU_AC3_QUEUE_EMPTY0 (0x820C0000 + 0x11C0)--- +* AMSDU_QUEUE_EMPTY_FLAG_31_0[31..0] - (RO) AC3 queue empty flag for +* station31~station0 in HW AMSDU engine. +*/ +#define \ +WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_ADDR \ + WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY0_ADDR +#define \ +WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_MASK \ + 0xFFFFFFFF /* AMSDU_QUEUE_EMPTY_FLAG_31_0[31..0] */ +#define \ +WF_PLE_TOP_AMSDU_AC3_QUEUE_EMPTY0_AMSDU_QUEUE_EMPTY_FLAG_31_0_SHFT \ + 0 + +/* +* ---CFG_DBDC_CTRL0 (0x820C0000 + 0x2008)--- +* RESERVED0[7..0] - (RO) Reserved bits +* WMM_0TO3_BAND_SEL[11..8] - (RW) Selects WMM0~WMM3 band +* RESERVED12[15..12] - (RO) Reserved bits +* NAN_BAND_SEL[16] - (RW) Selects NAN band +* FUNCQ_BAND_SEL[17] - (RW) Selects Functional Queue band +* TGID 0 & TGID1 always selec to different +band +* RESERVED18[30..18] - (RO) Reserved bits +* DBDC_EN[31] - (RO) Enables DBDC +*/ +#define WF_PLE_TOP_CFG_DBDC_CTRL0_DBDC_EN_ADDR \ + WF_PLE_TOP_CFG_DBDC_CTRL0_ADDR +#define WF_PLE_TOP_CFG_DBDC_CTRL0_DBDC_EN_MASK \ + 0x80000000 /* DBDC_EN[31] */ +#define WF_PLE_TOP_CFG_DBDC_CTRL0_DBDC_EN_SHFT 31 +#define WF_PLE_TOP_CFG_DBDC_CTRL0_FUNCQ_BAND_SEL_ADDR \ + WF_PLE_TOP_CFG_DBDC_CTRL0_ADDR +#define WF_PLE_TOP_CFG_DBDC_CTRL0_FUNCQ_BAND_SEL_MASK \ + 0x00020000 /* FUNCQ_BAND_SEL[17] */ +#define WF_PLE_TOP_CFG_DBDC_CTRL0_FUNCQ_BAND_SEL_SHFT 17 +#define WF_PLE_TOP_CFG_DBDC_CTRL0_NAN_BAND_SEL_ADDR \ + WF_PLE_TOP_CFG_DBDC_CTRL0_ADDR +#define WF_PLE_TOP_CFG_DBDC_CTRL0_NAN_BAND_SEL_MASK \ + 0x00010000 /* NAN_BAND_SEL[16] */ +#define WF_PLE_TOP_CFG_DBDC_CTRL0_NAN_BAND_SEL_SHFT 16 +#define WF_PLE_TOP_CFG_DBDC_CTRL0_WMM_0TO3_BAND_SEL_ADDR \ + WF_PLE_TOP_CFG_DBDC_CTRL0_ADDR +#define WF_PLE_TOP_CFG_DBDC_CTRL0_WMM_0TO3_BAND_SEL_MASK \ + 0x00000F00 /* WMM_0TO3_BAND_SEL[11..8] */ +#define WF_PLE_TOP_CFG_DBDC_CTRL0_WMM_0TO3_BAND_SEL_SHFT 8 + +/* +* ---CFG_UWTBL_MBIST_CTRL_0 (0x820C0000 + 0x2480)--- +* UWTBL_MBIST_MODE[0] - (RW) Control register for mbist_mode of UWTBL +MBIST +* UWTBL_MBIST_HOLDB[1] - (RW) Control register for mbist_holdb of +* UWTBL MBIST +* UWTBL_MBIST_DEBUG[2] - (RW) Control register for mbist_debug of +* UWTBL MBIST +* UWTBL_MBIST_USE_DEFAULT_DELSEL[3] - (RW) Control register for +* default DELSEL +* value of UWTBL memory +* UWTBL_MBIST_SLEEP_TEST[4] - (RW) Control register for sleep_test of +UWTBL +MBIST +* UWTBL_MBIST_SLEEP_INV[5] - (RW) Control register for sleep_inv of +UWTBL +MBIST +* UWTBL_MBIST_SLEEP_W[6] - (RW) Control register for sleep_w of UWTBL +MBIST +* UWTBL_MBIST_SLEEP_R[7] - (RW) Control register for sleep_r of UWTBL +MBIST +* UWTBL_MBIST_DONE[8] - (RO) Working status of UWTBL SRAM MBIST +circuit +* RESERVED9[15..9] - (RO) Reserved bits +* UWTBL_MBIST_FAIL[21..16] - (RO) MBIST check result of UWTBL SRAM +* RESERVED22[31..22] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_FAIL_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_FAIL_MASK \ + 0x003F0000 /* UWTBL_MBIST_FAIL[21..16] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_FAIL_SHFT 16 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_DONE_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_DONE_MASK \ + 0x00000100 /* UWTBL_MBIST_DONE[8] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_DONE_SHFT 8 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_R_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_R_MASK \ + 0x00000080 /* UWTBL_MBIST_SLEEP_R[7] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_R_SHFT 7 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_W_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_W_MASK \ + 0x00000040 /* UWTBL_MBIST_SLEEP_W[6] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_W_SHFT 6 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_INV_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_INV_MASK \ + 0x00000020 /* UWTBL_MBIST_SLEEP_INV[5] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_INV_SHFT 5 +#define \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_TEST_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_TEST_MASK \ + 0x00000010 /* UWTBL_MBIST_SLEEP_TEST[4] */ +#define \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_SLEEP_TEST_SHFT \ + 4 +#define \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_USE_DEFAULT_DELSEL_ADDR\ +\ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_USE_DEFAULT_DELSEL_MASK\ +\ + 0x00000008 /* UWTBL_MBIST_USE_DEFAULT_DELSEL[3] */ +#define \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_USE_DEFAULT_DELSEL_SHFT\ +3 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_DEBUG_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_DEBUG_MASK \ + 0x00000004 /* UWTBL_MBIST_DEBUG[2] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_DEBUG_SHFT 2 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_HOLDB_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_HOLDB_MASK \ + 0x00000002 /* UWTBL_MBIST_HOLDB[1] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_HOLDB_SHFT 1 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_MODE_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_MODE_MASK \ + 0x00000001 /* UWTBL_MBIST_MODE[0] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_0_UWTBL_MBIST_MODE_SHFT 0 + +/* +* ---CFG_UWTBL_MBIST_CTRL_1 (0x820C0000 + 0x2484)--- +* UWTBL_MBIST_HDEN[5..0] - (RW) Control register for mbist UWTBL HDEN +* RESERVED6[15..6] - (RO) Reserved bits +* UWTBL_MBIST_AWT[21..16] - (RW) Control register for mbist UWTBL AWT +* RESERVED22[31..22] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_UWTBL_MBIST_AWT_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_UWTBL_MBIST_AWT_MASK \ + 0x003F0000 /* UWTBL_MBIST_AWT[21..16] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_UWTBL_MBIST_AWT_SHFT 16 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_UWTBL_MBIST_HDEN_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_UWTBL_MBIST_HDEN_MASK \ + 0x0000003F /* UWTBL_MBIST_HDEN[5..0] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_1_UWTBL_MBIST_HDEN_SHFT 0 + +/* +* ---CFG_UWTBL_MBIST_CTRL_2 (0x820C0000 + 0x2488)--- +* UWTBL_BACKGROUND[15..0] - (RW) The MBIST background control register +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_2_UWTBL_BACKGROUND_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_2_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_2_UWTBL_BACKGROUND_MASK \ + 0x0000FFFF /* UWTBL_BACKGROUND[15..0] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_2_UWTBL_BACKGROUND_SHFT 0 + +/* +* ---CFG_UWTBL_MBIST_CTRL_3 (0x820C0000 + 0x248c)--- +* UWTBL_DELSEL_0[31..0] - (RW) UWTBL DELSEL 0 +*/ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_3_UWTBL_DELSEL_0_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_3_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_3_UWTBL_DELSEL_0_MASK \ + 0xFFFFFFFF /* UWTBL_DELSEL_0[31..0] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_3_UWTBL_DELSEL_0_SHFT 0 + +/* +* ---CFG_UWTBL_MBIST_CTRL_4 (0x820C0000 + 0x2490)--- +* UWTBL_DELSEL_1[31..0] - (RW) UWTBL DELSEL 1 +*/ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_4_UWTBL_DELSEL_1_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_4_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_4_UWTBL_DELSEL_1_MASK \ + 0xFFFFFFFF /* UWTBL_DELSEL_1[31..0] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_4_UWTBL_DELSEL_1_SHFT 0 + +/* +* ---CFG_UWTBL_MBIST_CTRL_5 (0x820C0000 + 0x2494)--- +* UWTBL_FUSE[6..0] - (RW) UWTBL FUSE +* RESERVED7[7] - (RO) Reserved bits +* UWTBL_PRE_FUSE[14..8] - (RO) UWTBL MBIST Pre Fuse +* RESERVED15[15] - (RO) Reserved bits +* UWTBL_MBIST_REPAIR_OK[21..16] - (RO) MBIST Repair OK +* RESERVED22[23..22] - (RO) Reserved bits +* UWTBL_MBIST_REPAIR_FAIL[29..24] - (RO) MBIST Repair Fail +* RESERVED30[31..30] - (RO) Reserved bits +*/ +#define \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_MBIST_REPAIR_FAIL_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_ADDR +#define \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_MBIST_REPAIR_FAIL_MASK \ + 0x3F000000 /* UWTBL_MBIST_REPAIR_FAIL[29..24] */ +#define \ +WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_MBIST_REPAIR_FAIL_SHFT \ + 24 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_MBIST_REPAIR_OK_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_MBIST_REPAIR_OK_MASK \ + 0x003F0000 /* UWTBL_MBIST_REPAIR_OK[21..16] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_MBIST_REPAIR_OK_SHFT \ + 16 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_PRE_FUSE_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_PRE_FUSE_MASK \ + 0x00007F00 /* UWTBL_PRE_FUSE[14..8] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_PRE_FUSE_SHFT 8 +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_FUSE_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_FUSE_MASK \ + 0x0000007F /* UWTBL_FUSE[6..0] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_5_UWTBL_FUSE_SHFT 0 + +/* +* ---CFG_UWTBL_MBIST_CTRL_6 (0x820C0000 + 0x2498)--- +* UWTBL_DELSEL_2[31..0] - (RW) UWTBL DELSEL 2 +*/ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_6_UWTBL_DELSEL_2_ADDR \ + WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_6_ADDR +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_6_UWTBL_DELSEL_2_MASK \ + 0xFFFFFFFF /* UWTBL_DELSEL_2[31..0] */ +#define WF_PLE_TOP_CFG_UWTBL_MBIST_CTRL_6_UWTBL_DELSEL_2_SHFT 0 + +/* +* ---CFG_SEC_MBIST_CTRL_0 (0x820C0000 + 0x25c0)--- +* SEC_MBIST_MODE[0] - (RW) Control register for mbist_mode of SEC +MBIST +* SEC_MBIST_HOLDB[1] - (RW) Control register for mbist_holdb of SEC +MBIST +* SEC_MBIST_DEBUG[2] - (RW) Control register for mbist_debug of SEC +MBIST +* SEC_MBIST_USE_DEFAULT_DELSEL[3] - (RW) Control register for default +DELSEL +* value of SEC memory +* RESERVED4[7..4] - (RO) Reserved bits +* SEC_MBIST_DONE[8] - (RO) Working status of SEC SRAM MBIST circuit +* RESERVED9[15..9] - (RO) Reserved bits +* SEC_MBIST_FAIL[17..16] - (RO) MBIST check result of SEC SRAM +* RESERVED18[31..18] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_FAIL_ADDR \ + WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_FAIL_MASK \ + 0x00030000 /* SEC_MBIST_FAIL[17..16] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_FAIL_SHFT 16 +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_DONE_ADDR \ + WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_DONE_MASK \ + 0x00000100 /* SEC_MBIST_DONE[8] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_DONE_SHFT 8 +#define \ +WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_USE_DEFAULT_DELSEL_ADDR \ + WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_ADDR +#define \ +WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_USE_DEFAULT_DELSEL_MASK \ + 0x00000008 /* SEC_MBIST_USE_DEFAULT_DELSEL[3] */ +#define \ +WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_USE_DEFAULT_DELSEL_SHFT \ + 3 +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_DEBUG_ADDR \ + WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_DEBUG_MASK \ + 0x00000004 /* SEC_MBIST_DEBUG[2] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_DEBUG_SHFT 2 +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_HOLDB_ADDR \ + WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_HOLDB_MASK \ + 0x00000002 /* SEC_MBIST_HOLDB[1] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_HOLDB_SHFT 1 +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_MODE_ADDR \ + WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_MODE_MASK \ + 0x00000001 /* SEC_MBIST_MODE[0] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_0_SEC_MBIST_MODE_SHFT 0 + +/* +* ---CFG_SEC_MBIST_CTRL_1 (0x820C0000 + 0x25c4)--- +* SEC_MBIST_HDEN[0] - (RW) Control register for mbist SEC HDEN +* RESERVED1[15..1] - (RO) Reserved bits +* SEC_MBIST_AWT[16] - (RW) Control register for mbist SEC AWT +* RESERVED17[31..17] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_SEC_MBIST_AWT_ADDR \ + WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_SEC_MBIST_AWT_MASK \ + 0x00010000 /* SEC_MBIST_AWT[16] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_SEC_MBIST_AWT_SHFT 16 +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_SEC_MBIST_HDEN_ADDR \ + WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_SEC_MBIST_HDEN_MASK \ + 0x00000001 /* SEC_MBIST_HDEN[0] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_1_SEC_MBIST_HDEN_SHFT 0 + +/* +* ---CFG_SEC_MBIST_CTRL_2 (0x820C0000 + 0x25c8)--- +* SEC_BACKGROUND[15..0] - (RW) The MBIST background control register +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_2_SEC_BACKGROUND_ADDR \ + WF_PLE_TOP_CFG_SEC_MBIST_CTRL_2_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_2_SEC_BACKGROUND_MASK \ + 0x0000FFFF /* SEC_BACKGROUND[15..0] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_2_SEC_BACKGROUND_SHFT 0 + +/* +* ---CFG_SEC_MBIST_CTRL_3 (0x820C0000 + 0x25cc)--- +* SEC_DELSEL_0[31..0] - (RW) SEC DELSEL 0 +*/ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_3_SEC_DELSEL_0_ADDR \ + WF_PLE_TOP_CFG_SEC_MBIST_CTRL_3_ADDR +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_3_SEC_DELSEL_0_MASK \ + 0xFFFFFFFF /* SEC_DELSEL_0[31..0] */ +#define WF_PLE_TOP_CFG_SEC_MBIST_CTRL_3_SEC_DELSEL_0_SHFT 0 + +/* +* ---CFG_PF_MBIST_CTRL_0 (0x820C0000 + 0x25e0)--- +* PF_MBIST_MODE[0] - (RW) Control register for mbist_mode of PF +MBIST +* PF_MBIST_HOLDB[1] - (RW) Control register for mbist_holdb of PF +MBIST +* PF_MBIST_DEBUG[2] - (RW) Control register for mbist_debug of PF +MBIST +* PF_MBIST_USE_DEFAULT_DELSEL[3] - (RW) Control register for default +DELSEL +* value of PF memory +* PF_MBIST_SLEEP_TEST[4] - (RW) Control register for sleep_test of PF +MBIST +* PF_MBIST_SLEEP_INV[5] - (RW) Control register for sleep_inv of PF +MBIST +* PF_MBIST_SLEEP_W[6] - (RW) Control register for sleep_w of PF MBIST +* PF_MBIST_SLEEP_R[7] - (RW) Control register for sleep_r of PF MBIST +* PF_MBIST_DONE[8] - (RO) Working status of PF SRAM MBIST circuit +* RESERVED9[11..9] - (RO) Reserved bits +* PF_MBIST_FAIL[31..12] - (RO) MBIST check result of PF SRAM +*/ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_FAIL_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_FAIL_MASK \ + 0xFFFFF000 /* PF_MBIST_FAIL[31..12] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_FAIL_SHFT 12 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_DONE_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_DONE_MASK \ + 0x00000100 /* PF_MBIST_DONE[8] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_DONE_SHFT 8 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_R_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_R_MASK \ + 0x00000080 /* PF_MBIST_SLEEP_R[7] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_R_SHFT 7 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_W_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_W_MASK \ + 0x00000040 /* PF_MBIST_SLEEP_W[6] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_W_SHFT 6 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_INV_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_INV_MASK \ + 0x00000020 /* PF_MBIST_SLEEP_INV[5] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_INV_SHFT 5 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_TEST_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_TEST_MASK \ + 0x00000010 /* PF_MBIST_SLEEP_TEST[4] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_SLEEP_TEST_SHFT 4 +#define \ +WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_USE_DEFAULT_DELSEL_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define \ +WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_USE_DEFAULT_DELSEL_MASK \ + 0x00000008 /* PF_MBIST_USE_DEFAULT_DELSEL[3] */ +#define \ +WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_USE_DEFAULT_DELSEL_SHFT \ + 3 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_DEBUG_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_DEBUG_MASK \ + 0x00000004 /* PF_MBIST_DEBUG[2] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_DEBUG_SHFT 2 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_HOLDB_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_HOLDB_MASK \ + 0x00000002 /* PF_MBIST_HOLDB[1] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_HOLDB_SHFT 1 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_MODE_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_MODE_MASK \ + 0x00000001 /* PF_MBIST_MODE[0] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_0_PF_MBIST_MODE_SHFT 0 + +/* +* ---CFG_PF_MBIST_CTRL_1 (0x820C0000 + 0x25e4)--- +* PF_MBIST_HDEN[9..0] - (RW) Control register for mbist PF HDEN +* RESERVED10[11..10] - (RO) Reserved bits +* PF_MBIST_AWT[31..12] - (RW) Control register for mbist PF AWT +*/ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_PF_MBIST_AWT_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_PF_MBIST_AWT_MASK \ + 0xFFFFF000 /* PF_MBIST_AWT[31..12] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_PF_MBIST_AWT_SHFT 12 +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_PF_MBIST_HDEN_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_PF_MBIST_HDEN_MASK \ + 0x000003FF /* PF_MBIST_HDEN[9..0] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_1_PF_MBIST_HDEN_SHFT 0 + +/* +* ---CFG_PF_MBIST_CTRL_2 (0x820C0000 + 0x25e8)--- +* PF_BACKGROUND[15..0] - (RW) The MBIST background control register +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_2_PF_BACKGROUND_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_2_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_2_PF_BACKGROUND_MASK \ + 0x0000FFFF /* PF_BACKGROUND[15..0] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_2_PF_BACKGROUND_SHFT 0 + +/* +* ---CFG_PF_MBIST_CTRL_3 (0x820C0000 + 0x25ec)--- +* PF_DELSEL_0[31..0] - (RW) PF DELSEL 0 +*/ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_3_PF_DELSEL_0_ADDR \ + WF_PLE_TOP_CFG_PF_MBIST_CTRL_3_ADDR +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_3_PF_DELSEL_0_MASK \ + 0xFFFFFFFF /* PF_DELSEL_0[31..0] */ +#define WF_PLE_TOP_CFG_PF_MBIST_CTRL_3_PF_DELSEL_0_SHFT 0 + +/* +* ---SYSRAM_MBIST_CTRL (0x820C0000 + 0x3004)--- +* MBIST_SW_RESET[0] - (RW) MBIST Software reset +* RESERVED1[7..1] - (RO) Reserved bits +* MBIST_BSEL[15..8] - (RW) Controls BSEL of SRAM MBIST circuit. +* MBIST_BACKGROUND[31..16] - (RW) The MBIST background control +register +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_BACKGROUND_ADDR \ + WF_PLE_TOP_SYSRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_BACKGROUND_MASK \ + 0xFFFF0000 /* MBIST_BACKGROUND[31..16] */ +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_BACKGROUND_SHFT 16 +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_BSEL_ADDR \ + WF_PLE_TOP_SYSRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_BSEL_MASK \ + 0x0000FF00 /* MBIST_BSEL[15..8] */ +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_BSEL_SHFT 8 +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_SW_RESET_ADDR \ + WF_PLE_TOP_SYSRAM_MBIST_CTRL_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_SW_RESET_MASK \ + 0x00000001 /* MBIST_SW_RESET[0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_CTRL_MBIST_SW_RESET_SHFT 0 + +/* +* ---SYSRAM_MBIST_DEBUG (0x820C0000 + 0x3008)--- +* SYSRAM_MBIST_DEBUG[15..0] - (RW) Control register for mbist_debug of +* SYSRAM MBIST +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_DEBUG_SYSRAM_MBIST_DEBUG_ADDR \ + WF_PLE_TOP_SYSRAM_MBIST_DEBUG_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_DEBUG_SYSRAM_MBIST_DEBUG_MASK \ + 0x0000FFFF /* SYSRAM_MBIST_DEBUG[15..0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_DEBUG_SYSRAM_MBIST_DEBUG_SHFT 0 + +/* +* ---SYSRAM_MBIST_MODE (0x820C0000 + 0x300C)--- +* SYSRAM_MBIST_MODE[15..0] - (RW) Control register for mbist_holdb of +* SYSRAM MBIST +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_MODE_SYSRAM_MBIST_MODE_ADDR \ + WF_PLE_TOP_SYSRAM_MBIST_MODE_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_MODE_SYSRAM_MBIST_MODE_MASK \ + 0x0000FFFF /* SYSRAM_MBIST_MODE[15..0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_MODE_SYSRAM_MBIST_MODE_SHFT 0 + +/* +* ---SYSRAM_MBIST_HOLDB (0x820C0000 + 0x3010)--- +* SYSRAM_MBIST_HOLDB[15..0] - (RW) Control register for mbist_holdb of +* sysram MBIST +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_HOLDB_SYSRAM_MBIST_HOLDB_ADDR \ + WF_PLE_TOP_SYSRAM_MBIST_HOLDB_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_HOLDB_SYSRAM_MBIST_HOLDB_MASK \ + 0x0000FFFF /* SYSRAM_MBIST_HOLDB[15..0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_HOLDB_SYSRAM_MBIST_HOLDB_SHFT 0 + +/* +* ---SYSRAM_MBIST_DONE (0x820C0000 + 0x3014)--- +* SYSRAM_MBIST_DONE[15..0] - (RO) Working status of SYSRAM MBIST 3 +circuit +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_DONE_SYSRAM_MBIST_DONE_ADDR \ + WF_PLE_TOP_SYSRAM_MBIST_DONE_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_DONE_SYSRAM_MBIST_DONE_MASK \ + 0x0000FFFF /* SYSRAM_MBIST_DONE[15..0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_DONE_SYSRAM_MBIST_DONE_SHFT 0 + +/* +* ---SYSRAM_MBIST_FAIL (0x820C0000 + 0x3018)--- +* SYSRAM_MBIST_FAIL[31..0] - (RO) MBIST check result of SYSRAM cell 3 +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_FAIL_SYSRAM_MBIST_FAIL_ADDR \ + WF_PLE_TOP_SYSRAM_MBIST_FAIL_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_FAIL_SYSRAM_MBIST_FAIL_MASK \ + 0xFFFFFFFF /* SYSRAM_MBIST_FAIL[31..0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_FAIL_SYSRAM_MBIST_FAIL_SHFT 0 + +/* +* ---SYSRAM_MBIST_SLEEP_TEST (0x820C0000 + 0x301C)--- +* SYSRAM_MBIST_SLEEP_TEST[15..0] - (RW) Control register for +* sleep_test of +* group 3 MBIST +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define \ +WF_PLE_TOP_SYSRAM_MBIST_SLEEP_TEST_SYSRAM_MBIST_SLEEP_TEST_ADDR \ + WF_PLE_TOP_SYSRAM_MBIST_SLEEP_TEST_ADDR +#define \ +WF_PLE_TOP_SYSRAM_MBIST_SLEEP_TEST_SYSRAM_MBIST_SLEEP_TEST_MASK \ + 0x0000FFFF /* SYSRAM_MBIST_SLEEP_TEST[15..0] */ +#define \ +WF_PLE_TOP_SYSRAM_MBIST_SLEEP_TEST_SYSRAM_MBIST_SLEEP_TEST_SHFT \ + 0 + +/* +* ---SYSRAM_MBIST_SLEEP_INV (0x820C0000 + 0x3020)--- +* SYSRAM_MBIST_SLEEP_INV[15..0] - (RW) Control register for sleep_inv +* of group +* 3 MBIST +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define \ +WF_PLE_TOP_SYSRAM_MBIST_SLEEP_INV_SYSRAM_MBIST_SLEEP_INV_ADDR \ + WF_PLE_TOP_SYSRAM_MBIST_SLEEP_INV_ADDR +#define \ +WF_PLE_TOP_SYSRAM_MBIST_SLEEP_INV_SYSRAM_MBIST_SLEEP_INV_MASK \ + 0x0000FFFF /* SYSRAM_MBIST_SLEEP_INV[15..0] */ +#define \ +WF_PLE_TOP_SYSRAM_MBIST_SLEEP_INV_SYSRAM_MBIST_SLEEP_INV_SHFT \ + 0 + +/* +* ---SYSRAM_MBIST_SLEEP_W (0x820C0000 + 0x3024)--- +* SYSRAM_MBIST_SLEEP_WRITE[15..0] - (RW) Control register for sleep_w +* of group +* 3 MBIST +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define \ +WF_PLE_TOP_SYSRAM_MBIST_SLEEP_W_SYSRAM_MBIST_SLEEP_WRITE_ADDR \ + WF_PLE_TOP_SYSRAM_MBIST_SLEEP_W_ADDR +#define \ +WF_PLE_TOP_SYSRAM_MBIST_SLEEP_W_SYSRAM_MBIST_SLEEP_WRITE_MASK \ + 0x0000FFFF /* SYSRAM_MBIST_SLEEP_WRITE[15..0] */ +#define \ +WF_PLE_TOP_SYSRAM_MBIST_SLEEP_W_SYSRAM_MBIST_SLEEP_WRITE_SHFT \ + 0 + +/* +* ---SYSRAM_MBIST_SLEEP_R (0x820C0000 + 0x3028)--- +* SYSRAM_MBIST_SLEEP_READ[15..0] - (RW) Control register for sleep_r +* of group +* 3 MBIST +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_R_SYSRAM_MBIST_SLEEP_READ_ADDR \ + WF_PLE_TOP_SYSRAM_MBIST_SLEEP_R_ADDR +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_R_SYSRAM_MBIST_SLEEP_READ_MASK \ + 0x0000FFFF /* SYSRAM_MBIST_SLEEP_READ[15..0] */ +#define WF_PLE_TOP_SYSRAM_MBIST_SLEEP_R_SYSRAM_MBIST_SLEEP_READ_SHFT 0 + +/* +* ---SYSRAM_AWT_HDEN (0x820C0000 + 0x302C)--- +* SYSRAM_MBIST_AWT[15..0] - (RW) Control register for mbist SYSRAM 3 +AWT +* SYSRAM_MBIST_HDEN[31..16] - (RW) Control register for mbist SYSRAM 3 +HDEN +*/ +#define WF_PLE_TOP_SYSRAM_AWT_HDEN_SYSRAM_MBIST_HDEN_ADDR \ + WF_PLE_TOP_SYSRAM_AWT_HDEN_ADDR +#define WF_PLE_TOP_SYSRAM_AWT_HDEN_SYSRAM_MBIST_HDEN_MASK \ + 0xFFFF0000 /* SYSRAM_MBIST_HDEN[31..16] */ +#define WF_PLE_TOP_SYSRAM_AWT_HDEN_SYSRAM_MBIST_HDEN_SHFT 16 +#define WF_PLE_TOP_SYSRAM_AWT_HDEN_SYSRAM_MBIST_AWT_ADDR \ + WF_PLE_TOP_SYSRAM_AWT_HDEN_ADDR +#define WF_PLE_TOP_SYSRAM_AWT_HDEN_SYSRAM_MBIST_AWT_MASK \ + 0x0000FFFF /* SYSRAM_MBIST_AWT[15..0] */ +#define WF_PLE_TOP_SYSRAM_AWT_HDEN_SYSRAM_MBIST_AWT_SHFT 0 + +/* +* ---SYSRAM_DBG_SEL (0x820C0000 + 0x3030)--- +* SYSRAM_DEBUG_SELECT_0[7..0] - (RW) Selects SYSRAM control debug 0 +* SYSRAM_DEBUG_SELECT_1[15..8] - (RW) Selects SYSRAM control debug 1 +* SYSRAM_DEBUG_SELECT_2[23..16] - (RW) Selects SYSRAM control debug 2 +* SYSRAM_DEBUG_SELECT_3[31..24] - (RW) Selects SYSRAM control debug 3 +*/ +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_3_ADDR \ + WF_PLE_TOP_SYSRAM_DBG_SEL_ADDR +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_3_MASK \ + 0xFF000000 /* SYSRAM_DEBUG_SELECT_3[31..24] */ +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_3_SHFT 24 +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_2_ADDR \ + WF_PLE_TOP_SYSRAM_DBG_SEL_ADDR +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_2_MASK \ + 0x00FF0000 /* SYSRAM_DEBUG_SELECT_2[23..16] */ +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_2_SHFT 16 +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_1_ADDR \ + WF_PLE_TOP_SYSRAM_DBG_SEL_ADDR +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_1_MASK \ + 0x0000FF00 /* SYSRAM_DEBUG_SELECT_1[15..8] */ +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_1_SHFT 8 +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_0_ADDR \ + WF_PLE_TOP_SYSRAM_DBG_SEL_ADDR +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_0_MASK \ + 0x000000FF /* SYSRAM_DEBUG_SELECT_0[7..0] */ +#define WF_PLE_TOP_SYSRAM_DBG_SEL_SYSRAM_DEBUG_SELECT_0_SHFT 0 + +/* +* ---SYSRAM_DELSEL (0x820C0000 + 0x3070)--- +* TYPE0_SYSRAM_DELSEL[31..0] - (RW) Type0 SYSRAM DELSEL bits +*/ +#define WF_PLE_TOP_SYSRAM_DELSEL_TYPE0_SYSRAM_DELSEL_ADDR \ + WF_PLE_TOP_SYSRAM_DELSEL_ADDR +#define WF_PLE_TOP_SYSRAM_DELSEL_TYPE0_SYSRAM_DELSEL_MASK \ + 0xFFFFFFFF /* TYPE0_SYSRAM_DELSEL[31..0] */ +#define WF_PLE_TOP_SYSRAM_DELSEL_TYPE0_SYSRAM_DELSEL_SHFT 0 + +/* +* ---SYSRAM_DELSEL_1 (0x820C0000 + 0x3074)--- +* TYPE1_SYSRAM_DELSEL[31..0] - (RW) Type1 SYSRAM DELSEL bits +*/ +#define WF_PLE_TOP_SYSRAM_DELSEL_1_TYPE1_SYSRAM_DELSEL_ADDR \ + WF_PLE_TOP_SYSRAM_DELSEL_1_ADDR +#define WF_PLE_TOP_SYSRAM_DELSEL_1_TYPE1_SYSRAM_DELSEL_MASK \ + 0xFFFFFFFF /* TYPE1_SYSRAM_DELSEL[31..0] */ +#define WF_PLE_TOP_SYSRAM_DELSEL_1_TYPE1_SYSRAM_DELSEL_SHFT 0 + +/* +* ---SYSRAM_DELSEL_2 (0x820C0000 + 0x3078)--- +* TYPE2_SYSRAM_DELSEL[31..0] - (RW) Type2 SYSRAM DELSEL bits +*/ +#define WF_PLE_TOP_SYSRAM_DELSEL_2_TYPE2_SYSRAM_DELSEL_ADDR \ + WF_PLE_TOP_SYSRAM_DELSEL_2_ADDR +#define WF_PLE_TOP_SYSRAM_DELSEL_2_TYPE2_SYSRAM_DELSEL_MASK \ + 0xFFFFFFFF /* TYPE2_SYSRAM_DELSEL[31..0] */ +#define WF_PLE_TOP_SYSRAM_DELSEL_2_TYPE2_SYSRAM_DELSEL_SHFT 0 + +/* +* ---SYSRAM_DELSEL_3 (0x820C0000 + 0x307C)--- +* TYPE3_SYSRAM_DELSEL[31..0] - (RW) Type3 SYSRAM DELSEL bits +*/ +#define WF_PLE_TOP_SYSRAM_DELSEL_3_TYPE3_SYSRAM_DELSEL_ADDR \ + WF_PLE_TOP_SYSRAM_DELSEL_3_ADDR +#define WF_PLE_TOP_SYSRAM_DELSEL_3_TYPE3_SYSRAM_DELSEL_MASK \ + 0xFFFFFFFF /* TYPE3_SYSRAM_DELSEL[31..0] */ +#define WF_PLE_TOP_SYSRAM_DELSEL_3_TYPE3_SYSRAM_DELSEL_SHFT 0 + +/* +* ---SYSRAM_OUTRAN_ERR_FLAG (0x820C0000 + 0x3080)--- +* SYSRAM_OUTRAN_ERR_FLAG[31..0] - (RO) Type3 SYSRAM DELSEL bits +*/ +#define \ +WF_PLE_TOP_SYSRAM_OUTRAN_ERR_FLAG_SYSRAM_OUTRAN_ERR_FLAG_ADDR \ + WF_PLE_TOP_SYSRAM_OUTRAN_ERR_FLAG_ADDR +#define \ +WF_PLE_TOP_SYSRAM_OUTRAN_ERR_FLAG_SYSRAM_OUTRAN_ERR_FLAG_MASK \ + 0xFFFFFFFF /* SYSRAM_OUTRAN_ERR_FLAG[31..0] */ +#define \ +WF_PLE_TOP_SYSRAM_OUTRAN_ERR_FLAG_SYSRAM_OUTRAN_ERR_FLAG_SHFT \ + 0 + +#ifdef __cplusplus +} +#endif + +#endif /* __WF_PLE_TOP_REGS_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/soc3_0/wf_pse_top.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/soc3_0/wf_pse_top.h new file mode 100644 index 0000000000000..5820a942057b4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/soc3_0/wf_pse_top.h @@ -0,0 +1,3719 @@ +/* [File] : wf_pse_top.h */ +/* [Revision time] : Mon Apr 15 14:14:44 2019 */ +/* [Description] : This file is auto generated by CODA */ +/* [Copyright] : Copyright (C) 2019 Mediatek Incorportion. All rights +*/ +/* reserved. */ + +#ifndef __WF_PSE_TOP_REGS_H__ +#define __WF_PSE_TOP_REGS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* **************************************************************** */ +/* */ +/* WF_PSE_TOP CR Definitions */ +/* */ +/* **************************************************************** */ + +#define WF_PSE_TOP_BASE 0x820C8000 + +#define WF_PSE_TOP_GC_ADDR (WF_PSE_TOP_BASE + 0x00) /* 8000 */ +#define WF_PSE_TOP_PBUF_CTRL_ADDR (WF_PSE_TOP_BASE + 0x14) /* 8014 */ +#define WF_PSE_TOP_INT_N9_EN_MASK_ADDR \ + (WF_PSE_TOP_BASE + 0x20) /* 8020 */ +#define WF_PSE_TOP_INT_N9_STS_ADDR \ + (WF_PSE_TOP_BASE + 0x24) /* 8024 */ +#define WF_PSE_TOP_INT_N9_ERR_STS_ADDR \ + (WF_PSE_TOP_BASE + 0x28) /* 8028 */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_ADDR \ + (WF_PSE_TOP_BASE + 0x2C) /* 802C */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_ADDR \ + (WF_PSE_TOP_BASE + 0x30) /* 8030 */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR \ + (WF_PSE_TOP_BASE + 0x34) /* 8034 */ +#define WF_PSE_TOP_C_GET_FID_0_ADDR \ + (WF_PSE_TOP_BASE + 0x40) /* 8040 */ +#define WF_PSE_TOP_C_GET_FID_1_ADDR \ + (WF_PSE_TOP_BASE + 0x44) /* 8044 */ +#define WF_PSE_TOP_C_EN_QUEUE_0_ADDR \ + (WF_PSE_TOP_BASE + 0x60) /* 8060 */ +#define WF_PSE_TOP_C_EN_QUEUE_1_ADDR \ + (WF_PSE_TOP_BASE + 0x64) /* 8064 */ +#define WF_PSE_TOP_C_EN_QUEUE_2_ADDR \ + (WF_PSE_TOP_BASE + 0x68) /* 8068 */ +#define WF_PSE_TOP_C_DE_QUEUE_0_ADDR \ + (WF_PSE_TOP_BASE + 0x80) /* 8080 */ +#define WF_PSE_TOP_C_DE_QUEUE_1_ADDR \ + (WF_PSE_TOP_BASE + 0x84) /* 8084 */ +#define WF_PSE_TOP_C_DE_QUEUE_2_ADDR \ + (WF_PSE_TOP_BASE + 0x88) /* 8088 */ +#define WF_PSE_TOP_C_DE_QUEUE_3_ADDR \ + (WF_PSE_TOP_BASE + 0x8c) /* 808C */ +#define WF_PSE_TOP_C_DE_QUEUE_4_ADDR \ + (WF_PSE_TOP_BASE + 0x90) /* 8090 */ +#define WF_PSE_TOP_ALLOCATE_0_ADDR \ + (WF_PSE_TOP_BASE + 0xA0) /* 80A0 */ +#define WF_PSE_TOP_ALLOCATE_1_ADDR \ + (WF_PSE_TOP_BASE + 0xA4) /* 80A4 */ +#define WF_PSE_TOP_QUEUE_EMPTY_ADDR \ + (WF_PSE_TOP_BASE + 0xB0) /* 80B0 */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR \ + (WF_PSE_TOP_BASE + 0xB4) /* 80B4 */ +#define WF_PSE_TOP_FREEPG_START_END_ADDR \ + (WF_PSE_TOP_BASE + 0xC0) /* 80C0 */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR \ + (WF_PSE_TOP_BASE + 0xc4) /* 80C4 */ +#define WF_PSE_TOP_TO_N9_INT_ADDR (WF_PSE_TOP_BASE + 0xf0) /* 80F0 */ +#define WF_PSE_TOP_FREEPG_CNT_ADDR \ + (WF_PSE_TOP_BASE + 0x100) /* 8100 */ +#define WF_PSE_TOP_FREEPG_HEAD_TAIL_ADDR \ + (WF_PSE_TOP_BASE + 0x104) /* 8104 */ +#define WF_PSE_TOP_GROUP_REFILL_CTRL_ADDR \ + (WF_PSE_TOP_BASE + 0x108) /* 8108 */ +#define WF_PSE_TOP_PG_HIF0_GROUP_ADDR \ + (WF_PSE_TOP_BASE + 0x110) /* 8110 */ +#define WF_PSE_TOP_HIF0_PG_INFO_ADDR \ + (WF_PSE_TOP_BASE + 0x114) /* 8114 */ +#define WF_PSE_TOP_PG_HIF1_GROUP_ADDR \ + (WF_PSE_TOP_BASE + 0x118) /* 8118 */ +#define WF_PSE_TOP_HIF1_PG_INFO_ADDR \ + (WF_PSE_TOP_BASE + 0x11C) /* 811C */ +#define WF_PSE_TOP_PG_CPU_GROUP_ADDR \ + (WF_PSE_TOP_BASE + 0x150) /* 8150 */ +#define WF_PSE_TOP_CPU_PG_INFO_ADDR \ + (WF_PSE_TOP_BASE + 0x154) /* 8154 */ +#define WF_PSE_TOP_PG_PLE_GROUP_ADDR \ + (WF_PSE_TOP_BASE + 0x160) /* 8160 */ +#define WF_PSE_TOP_PLE_PG_INFO_ADDR \ + (WF_PSE_TOP_BASE + 0x164) /* 8164 */ +#define WF_PSE_TOP_PG_PLE1_GROUP_ADDR \ + (WF_PSE_TOP_BASE + 0x168) /* 8168 */ +#define WF_PSE_TOP_PLE1_PG_INFO_ADDR \ + (WF_PSE_TOP_BASE + 0x16C) /* 816C */ +#define WF_PSE_TOP_PG_LMAC0_GROUP_ADDR \ + (WF_PSE_TOP_BASE + 0x170) /* 8170 */ +#define WF_PSE_TOP_LMAC0_PG_INFO_ADDR \ + (WF_PSE_TOP_BASE + 0x174) /* 8174 */ +#define WF_PSE_TOP_PG_LMAC1_GROUP_ADDR \ + (WF_PSE_TOP_BASE + 0x178) /* 8178 */ +#define WF_PSE_TOP_LMAC1_PG_INFO_ADDR \ + (WF_PSE_TOP_BASE + 0x17C) /* 817C */ +#define WF_PSE_TOP_PG_LMAC2_GROUP_ADDR \ + (WF_PSE_TOP_BASE + 0x180) /* 8180 */ +#define WF_PSE_TOP_LMAC2_PG_INFO_ADDR \ + (WF_PSE_TOP_BASE + 0x184) /* 8184 */ +#define WF_PSE_TOP_PG_LMAC3_GROUP_ADDR \ + (WF_PSE_TOP_BASE + 0x188) /* 8188 */ +#define WF_PSE_TOP_LMAC3_PG_INFO_ADDR \ + (WF_PSE_TOP_BASE + 0x18C) /* 818C */ +#define WF_PSE_TOP_PG_MDP_GROUP_ADDR \ + (WF_PSE_TOP_BASE + 0x198) /* 8198 */ +#define WF_PSE_TOP_MDP_PG_INFO_ADDR \ + (WF_PSE_TOP_BASE + 0x19C) /* 819C */ +#define WF_PSE_TOP_RL_BUF_CTRL_0_ADDR \ + (WF_PSE_TOP_BASE + 0x1A0) /* 81A0 */ +#define WF_PSE_TOP_RL_BUF_CTRL_1_ADDR \ + (WF_PSE_TOP_BASE + 0x1A4) /* 81A4 */ +#define WF_PSE_TOP_FL_QUE_CTRL_0_ADDR \ + (WF_PSE_TOP_BASE + 0x1B0) /* 81B0 */ +#define WF_PSE_TOP_FL_QUE_CTRL_1_ADDR \ + (WF_PSE_TOP_BASE + 0x1B4) /* 81B4 */ +#define WF_PSE_TOP_FL_QUE_CTRL_2_ADDR \ + (WF_PSE_TOP_BASE + 0x1B8) /* 81B8 */ +#define WF_PSE_TOP_FL_QUE_CTRL_3_ADDR \ + (WF_PSE_TOP_BASE + 0x1BC) /* 81BC */ +#define WF_PSE_TOP_PL_QUE_CTRL_0_ADDR \ + (WF_PSE_TOP_BASE + 0x1C0) /* 81C0 */ +#define WF_PSE_TOP_PSE_LP_CTRL_ADDR \ + (WF_PSE_TOP_BASE + 0x1D0) /* 81D0 */ +#define WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_ADDR \ + (WF_PSE_TOP_BASE + 0x1E0) /* 81E0 */ +#define WF_PSE_TOP_PSE_CT_PRI_CTRL_ADDR \ + (WF_PSE_TOP_BASE + 0x1EC) /* 81EC */ +#define WF_PSE_TOP_PLE_ENQ_PKT_NUM_ADDR \ + (WF_PSE_TOP_BASE + 0x1F0) /* 81F0 */ +#define WF_PSE_TOP_CPU_ENQ_PKT_NUM_ADDR \ + (WF_PSE_TOP_BASE + 0x1F4) /* 81F4 */ +#define WF_PSE_TOP_LMAC_ENQ_PKT_NUM_ADDR \ + (WF_PSE_TOP_BASE + 0x1F8) /* 81F8 */ +#define WF_PSE_TOP_HIF_ENQ_PKT_NUM_ADDR \ + (WF_PSE_TOP_BASE + 0x1FC) /* 81FC */ +#define WF_PSE_TOP_MDP_ENQ_PKT_NUM_ADDR \ + (WF_PSE_TOP_BASE + 0x200) /* 8200 */ +#define WF_PSE_TOP_TIMEOUT_CTRL_ADDR \ + (WF_PSE_TOP_BASE + 0x244) /* 8244 */ +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_ADDR \ + (WF_PSE_TOP_BASE + 0x24C) /* 824C */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR \ + (WF_PSE_TOP_BASE + 0x250) /* 8250 */ +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_ADDR \ + (WF_PSE_TOP_BASE + 0x280) /* 8280 */ +#define WF_PSE_TOP_PSE_SER_CTRL_ADDR \ + (WF_PSE_TOP_BASE + 0x2a0) /* 82A0 */ +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_ADDR \ + (WF_PSE_TOP_BASE + 0x2b0) /* 82B0 */ +#define WF_PSE_TOP_PSE_MBIST_BSEL_ADDR \ + (WF_PSE_TOP_BASE + 0x2b4) /* 82B4 */ +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_ADDR \ + (WF_PSE_TOP_BASE + 0x2b8) /* 82B8 */ +#define WF_PSE_TOP_SRAM_MBIST_BACKGROUND_ADDR \ + (WF_PSE_TOP_BASE + 0x2d0) /* 82D0 */ +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_ADDR \ + (WF_PSE_TOP_BASE + 0x2d4) /* 82D4 */ +#define WF_PSE_TOP_SRAM_MBIST_DONE_ADDR \ + (WF_PSE_TOP_BASE + 0x2d8) /* 82D8 */ +#define WF_PSE_TOP_SRAM_MBIST_FAIL_ADDR \ + (WF_PSE_TOP_BASE + 0x2dc) /* 82DC */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR \ + (WF_PSE_TOP_BASE + 0x2e0) /* 82E0 */ +#define WF_PSE_TOP_SRAM_MBIST_DELSEL_ADDR \ + (WF_PSE_TOP_BASE + 0x2e4) /* 82E4 */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR \ + (WF_PSE_TOP_BASE + 0x2e8) /* 82E8 */ +#define WF_PSE_TOP_SRAM_MBIST_DELSEL_1_ADDR \ + (WF_PSE_TOP_BASE + 0x2f0) /* 82F0 */ +#define WF_PSE_TOP_PSE_SEEK_CR_00_ADDR \ + (WF_PSE_TOP_BASE + 0x3d0) /* 83D0 */ +#define WF_PSE_TOP_PSE_SEEK_CR_01_ADDR \ + (WF_PSE_TOP_BASE + 0x3d4) /* 83D4 */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_ADDR \ + (WF_PSE_TOP_BASE + 0x3d8) /* 83D8 */ +#define WF_PSE_TOP_PSE_SEEK_CR_03_ADDR \ + (WF_PSE_TOP_BASE + 0x3dc) /* 83DC */ +#define WF_PSE_TOP_PSE_SEEK_CR_04_ADDR \ + (WF_PSE_TOP_BASE + 0x3e0) /* 83E0 */ +#define WF_PSE_TOP_PSE_SEEK_CR_05_ADDR \ + (WF_PSE_TOP_BASE + 0x3e4) /* 83E4 */ +#define WF_PSE_TOP_PSE_SEEK_CR_06_ADDR \ + (WF_PSE_TOP_BASE + 0x3e8) /* 83E8 */ +#define WF_PSE_TOP_PSE_SEEK_CR_07_ADDR \ + (WF_PSE_TOP_BASE + 0x3ec) /* 83EC */ +#define WF_PSE_TOP_PSE_SEEK_CR_08_ADDR \ + (WF_PSE_TOP_BASE + 0x3f0) /* 83F0 */ +#define WF_PSE_TOP_PSE_SEEK_CR_09_ADDR \ + (WF_PSE_TOP_BASE + 0x3f4) /* 83F4 */ + +/* +* ---GC (0x820C8000 + 0x00)--- +* ALL_RESET[0] - (RW) Resets PSE logic and register +* LOGIC_RESET[1] - (RW) Resets PSE logic circuit +* INIT_DONE[2] - (RO) PSE control SRAM initialization +indicator +* RESERVED3[15..3] - (RO) Reserved bits +* SRAM_MBIST_RESET[16] - (RW) Reset control of SRAM MBIST (low active) +* RESERVED17[17] - (RO) Reserved bits +* DIS_PSE_DYN_CKG[18] - (RW) Disable control of wf_pse_top dynamic +* clock gating function +* RESERVED19[31..19] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_GC_DIS_PSE_DYN_CKG_ADDR WF_PSE_TOP_GC_ADDR +#define WF_PSE_TOP_GC_DIS_PSE_DYN_CKG_MASK \ + 0x00040000 /* DIS_PSE_DYN_CKG[18] */ +#define WF_PSE_TOP_GC_DIS_PSE_DYN_CKG_SHFT 18 +#define WF_PSE_TOP_GC_SRAM_MBIST_RESET_ADDR WF_PSE_TOP_GC_ADDR +#define WF_PSE_TOP_GC_SRAM_MBIST_RESET_MASK \ + 0x00010000 /* SRAM_MBIST_RESET[16] */ +#define WF_PSE_TOP_GC_SRAM_MBIST_RESET_SHFT 16 +#define WF_PSE_TOP_GC_INIT_DONE_ADDR WF_PSE_TOP_GC_ADDR +#define WF_PSE_TOP_GC_INIT_DONE_MASK 0x00000004 /* INIT_DONE[2] */ +#define WF_PSE_TOP_GC_INIT_DONE_SHFT 2 +#define WF_PSE_TOP_GC_LOGIC_RESET_ADDR WF_PSE_TOP_GC_ADDR +#define WF_PSE_TOP_GC_LOGIC_RESET_MASK 0x00000002 /* LOGIC_RESET[1] */ +#define WF_PSE_TOP_GC_LOGIC_RESET_SHFT 1 +#define WF_PSE_TOP_GC_ALL_RESET_ADDR WF_PSE_TOP_GC_ADDR +#define WF_PSE_TOP_GC_ALL_RESET_MASK 0x00000001 /* ALL_RESET[0] */ +#define WF_PSE_TOP_GC_ALL_RESET_SHFT 0 + +/* +* ---PBUF_CTRL (0x820C8000 + 0x14)--- +* TOTAL_PAGE_NUM[11..0] - (RW) Total page numbers +* Set the total page before release PSE logic +* reset, and must not be changed after release logic reset. +* RESERVED12[16..12] - (RO) Reserved bits +* PBUF_OFFSET[25..17] - (RW) Packet buffer offset. +* Set the buffer offset before release PSE +* logic reset, and must not be changed after release logic reset. +* RESERVED26[30..26] - (RO) Reserved bits +* PAGE_SIZE_CFG[31] - (RW) Configures page size +* Set up the page size before releasing PSE +* logic reset; it should not be changed after logic reset is released. +*/ +#define WF_PSE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_ADDR \ + WF_PSE_TOP_PBUF_CTRL_ADDR +#define WF_PSE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_MASK \ + 0x80000000 /* PAGE_SIZE_CFG[31] */ +#define WF_PSE_TOP_PBUF_CTRL_PAGE_SIZE_CFG_SHFT 31 +#define WF_PSE_TOP_PBUF_CTRL_PBUF_OFFSET_ADDR \ + WF_PSE_TOP_PBUF_CTRL_ADDR +#define WF_PSE_TOP_PBUF_CTRL_PBUF_OFFSET_MASK \ + 0x03FE0000 /* PBUF_OFFSET[25..17] */ +#define WF_PSE_TOP_PBUF_CTRL_PBUF_OFFSET_SHFT 17 +#define WF_PSE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_ADDR \ + WF_PSE_TOP_PBUF_CTRL_ADDR +#define WF_PSE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_MASK \ + 0x00000FFF /* TOTAL_PAGE_NUM[11..0] */ +#define WF_PSE_TOP_PBUF_CTRL_TOTAL_PAGE_NUM_SHFT 0 + +/* +* ---INT_N9_EN_MASK (0x820C8000 + 0x20)--- +* EN_CPU_Q0_NE[0] - (RW) CPU queue 0 not empty interrupt +* EN_CPU_Q1_NE[1] - (RW) CPU queue 1 not empty interrupt +* EN_CPU_Q2_NE[2] - (RW) CPU queue 2 not empty interrupt +* EN_CPU_Q3_NE[3] - (RW) CPU queue 3 not empty interrupt +* RESERVED4[11..4] - (RO) Reserved bits +* EN_LMAC_ENQ[12] - (RW) Enables LMAC enq interrupt +* EN_ERROR_INT[13] - (RW) Error condition interrupt status +* RESERVED14[15..14] - (RO) Reserved bits +* EN_TOGGLE_INT[16] - (RW) Data toggle of CR4 toggle register +(0xe0) +* EN_LMAC_EMPTY_FALL[17] - (RW) LMAC Buffer empty fall edge detect +* EN_LMAC_EMPTY_RAISE[18] - (RW) LMAC Buffer empty raise edge detect +* EN_HIF_Q0_NE[19] - (RW) HIF queue 0 not empty interrupt +* EN_HIF_Q1_NE[20] - (RW) HIF queue 1 not empty interrupt +* EN_HIF_Q2_NE[21] - (RW) HIF queue 2 not empty interrupt +* EN_HIF_Q3_NE[22] - (RW) HIF queue 3 not empty interrupt +* EN_HIF_Q4_NE[23] - (RW) HIF queue 4 not empty interrupt +* EN_HIF_Q5_NE[24] - (RW) HIF queue 5 not empty interrupt +* EN_HIF_Q6_NE[25] - (RW) HIF queue 6 not empty interrupt +* EN_HIF_Q7_NE[26] - (RW) HIF queue 7 not empty interrupt +* EN_HIF_Q8_NE[27] - (RW) HIF queue 8 not empty interrupt +* EN_HIF_Q9_NE[28] - (RW) HIF queue 9 not empty interrupt +* EN_HIF_Q10_NE[29] - (RW) HIF queue 10 not empty interrupt +* EN_HIF_Q11_NE[30] - (RW) HIF queue 11 not empty interrupt +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q11_NE_ADDR \ + WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q11_NE_MASK \ + 0x40000000 /* EN_HIF_Q11_NE[30] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q11_NE_SHFT 30 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q10_NE_ADDR \ + WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q10_NE_MASK \ + 0x20000000 /* EN_HIF_Q10_NE[29] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q10_NE_SHFT 29 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q9_NE_ADDR \ + WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q9_NE_MASK \ + 0x10000000 /* EN_HIF_Q9_NE[28] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q9_NE_SHFT 28 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q8_NE_ADDR \ + WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q8_NE_MASK \ + 0x08000000 /* EN_HIF_Q8_NE[27] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q8_NE_SHFT 27 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q7_NE_ADDR \ + WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q7_NE_MASK \ + 0x04000000 /* EN_HIF_Q7_NE[26] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q7_NE_SHFT 26 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q6_NE_ADDR \ + WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q6_NE_MASK \ + 0x02000000 /* EN_HIF_Q6_NE[25] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q6_NE_SHFT 25 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q5_NE_ADDR \ + WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q5_NE_MASK \ + 0x01000000 /* EN_HIF_Q5_NE[24] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q5_NE_SHFT 24 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q4_NE_ADDR \ + WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q4_NE_MASK \ + 0x00800000 /* EN_HIF_Q4_NE[23] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q4_NE_SHFT 23 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q3_NE_ADDR \ + WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q3_NE_MASK \ + 0x00400000 /* EN_HIF_Q3_NE[22] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q3_NE_SHFT 22 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q2_NE_ADDR \ + WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q2_NE_MASK \ + 0x00200000 /* EN_HIF_Q2_NE[21] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q2_NE_SHFT 21 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q1_NE_ADDR \ + WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q1_NE_MASK \ + 0x00100000 /* EN_HIF_Q1_NE[20] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q1_NE_SHFT 20 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q0_NE_ADDR \ + WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q0_NE_MASK \ + 0x00080000 /* EN_HIF_Q0_NE[19] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_HIF_Q0_NE_SHFT 19 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_EMPTY_RAISE_ADDR \ + WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_EMPTY_RAISE_MASK \ + 0x00040000 /* EN_LMAC_EMPTY_RAISE[18] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_EMPTY_RAISE_SHFT 18 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_EMPTY_FALL_ADDR \ + WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_EMPTY_FALL_MASK \ + 0x00020000 /* EN_LMAC_EMPTY_FALL[17] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_EMPTY_FALL_SHFT 17 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_TOGGLE_INT_ADDR \ + WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_TOGGLE_INT_MASK \ + 0x00010000 /* EN_TOGGLE_INT[16] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_TOGGLE_INT_SHFT 16 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_ERROR_INT_ADDR \ + WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_ERROR_INT_MASK \ + 0x00002000 /* EN_ERROR_INT[13] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_ERROR_INT_SHFT 13 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_ENQ_ADDR \ + WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_ENQ_MASK \ + 0x00001000 /* EN_LMAC_ENQ[12] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_LMAC_ENQ_SHFT 12 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q3_NE_ADDR \ + WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q3_NE_MASK \ + 0x00000008 /* EN_CPU_Q3_NE[3] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q3_NE_SHFT 3 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q2_NE_ADDR \ + WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q2_NE_MASK \ + 0x00000004 /* EN_CPU_Q2_NE[2] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q2_NE_SHFT 2 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q1_NE_ADDR \ + WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q1_NE_MASK \ + 0x00000002 /* EN_CPU_Q1_NE[1] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q1_NE_SHFT 1 +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q0_NE_ADDR \ + WF_PSE_TOP_INT_N9_EN_MASK_ADDR +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q0_NE_MASK \ + 0x00000001 /* EN_CPU_Q0_NE[0] */ +#define WF_PSE_TOP_INT_N9_EN_MASK_EN_CPU_Q0_NE_SHFT 0 + +/* +* ---INT_N9_STS (0x820C8000 + 0x24)--- +* CPU_Q0_NE[0] - (W1C) CPU queue 0 not empty interrupt status +* CPU_Q1_NE[1] - (W1C) CPU queue 1 not empty interrupt status +* CPU_Q2_NE[2] - (W1C) CPU queue 2 not empty interrupt status +* CPU_Q3_NE[3] - (W1C) CPU queue 3 not empty interrupt status +* RESERVED4[11..4] - (RO) Reserved bits +* LMAC_ENQ[12] - (W1C) LMAC enq interrupt status +* ERROR_INT[13] - (RO) Error condition interrupt status +* ERROR_1_INT[14] - (RO) Error condition interrupt status +* RESERVED15[15] - (RO) Reserved bits +* DATA_TOGGLE[16] - (W1C) Data toggle of CR4 toggle register +(0xe0) +* LMAC_EMPTY_FALL[17] - (W1C) LMAC Buffer empty fall edge detect +* LMAC_EMPTY_RAISE[18] - (W1C) LMAC Buffer empty raise edge detect +* HIF_Q0_NE[19] - (W1C) HIF queue 0 not empty interrupt status +* HIF_Q1_NE[20] - (W1C) HIF queue 1 not empty interrupt status +* HIF_Q2_NE[21] - (W1C) HIF queue 2 not empty interrupt status +* HIF_Q3_NE[22] - (W1C) HIF queue 3 not empty interrupt status +* HIF_Q4_NE[23] - (W1C) HIF queue 4 not empty interrupt status +* HIF_Q5_NE[24] - (W1C) HIF queue 5 not empty interrupt status +* HIF_Q6_NE[25] - (W1C) HIF queue 6 not empty interrupt status +* HIF_Q7_NE[26] - (W1C) HIF queue 7 not empty interrupt status +* HIF_Q8_NE[27] - (W1C) HIF queue 8 not empty interrupt status +* HIF_Q9_NE[28] - (W1C) HIF queue 9 not empty interrupt status +* HIF_Q10_NE[29] - (W1C) HIF queue 10 not empty interrupt status +* HIF_Q11_NE[30] - (W1C) HIF queue 11 not empty interrupt status +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q11_NE_ADDR \ + WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q11_NE_MASK \ + 0x40000000 /* HIF_Q11_NE[30] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q11_NE_SHFT 30 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q10_NE_ADDR \ + WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q10_NE_MASK \ + 0x20000000 /* HIF_Q10_NE[29] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q10_NE_SHFT 29 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q9_NE_ADDR \ + WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q9_NE_MASK \ + 0x10000000 /* HIF_Q9_NE[28] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q9_NE_SHFT 28 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q8_NE_ADDR \ + WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q8_NE_MASK \ + 0x08000000 /* HIF_Q8_NE[27] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q8_NE_SHFT 27 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q7_NE_ADDR \ + WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q7_NE_MASK \ + 0x04000000 /* HIF_Q7_NE[26] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q7_NE_SHFT 26 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q6_NE_ADDR \ + WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q6_NE_MASK \ + 0x02000000 /* HIF_Q6_NE[25] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q6_NE_SHFT 25 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q5_NE_ADDR \ + WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q5_NE_MASK \ + 0x01000000 /* HIF_Q5_NE[24] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q5_NE_SHFT 24 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q4_NE_ADDR \ + WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q4_NE_MASK \ + 0x00800000 /* HIF_Q4_NE[23] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q4_NE_SHFT 23 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q3_NE_ADDR \ + WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q3_NE_MASK \ + 0x00400000 /* HIF_Q3_NE[22] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q3_NE_SHFT 22 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q2_NE_ADDR \ + WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q2_NE_MASK \ + 0x00200000 /* HIF_Q2_NE[21] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q2_NE_SHFT 21 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q1_NE_ADDR \ + WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q1_NE_MASK \ + 0x00100000 /* HIF_Q1_NE[20] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q1_NE_SHFT 20 +#define WF_PSE_TOP_INT_N9_STS_HIF_Q0_NE_ADDR \ + WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_HIF_Q0_NE_MASK \ + 0x00080000 /* HIF_Q0_NE[19] */ +#define WF_PSE_TOP_INT_N9_STS_HIF_Q0_NE_SHFT 19 +#define WF_PSE_TOP_INT_N9_STS_LMAC_EMPTY_RAISE_ADDR \ + WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_LMAC_EMPTY_RAISE_MASK \ + 0x00040000 /* LMAC_EMPTY_RAISE[18] */ +#define WF_PSE_TOP_INT_N9_STS_LMAC_EMPTY_RAISE_SHFT 18 +#define WF_PSE_TOP_INT_N9_STS_LMAC_EMPTY_FALL_ADDR \ + WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_LMAC_EMPTY_FALL_MASK \ + 0x00020000 /* LMAC_EMPTY_FALL[17] */ +#define WF_PSE_TOP_INT_N9_STS_LMAC_EMPTY_FALL_SHFT 17 +#define WF_PSE_TOP_INT_N9_STS_DATA_TOGGLE_ADDR \ + WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_DATA_TOGGLE_MASK \ + 0x00010000 /* DATA_TOGGLE[16] */ +#define WF_PSE_TOP_INT_N9_STS_DATA_TOGGLE_SHFT 16 +#define WF_PSE_TOP_INT_N9_STS_ERROR_1_INT_ADDR \ + WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_ERROR_1_INT_MASK \ + 0x00004000 /* ERROR_1_INT[14] */ +#define WF_PSE_TOP_INT_N9_STS_ERROR_1_INT_SHFT 14 +#define WF_PSE_TOP_INT_N9_STS_ERROR_INT_ADDR \ + WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_ERROR_INT_MASK \ + 0x00002000 /* ERROR_INT[13] */ +#define WF_PSE_TOP_INT_N9_STS_ERROR_INT_SHFT 13 +#define WF_PSE_TOP_INT_N9_STS_LMAC_ENQ_ADDR WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_LMAC_ENQ_MASK \ + 0x00001000 /* LMAC_ENQ[12] */ +#define WF_PSE_TOP_INT_N9_STS_LMAC_ENQ_SHFT 12 +#define WF_PSE_TOP_INT_N9_STS_CPU_Q3_NE_ADDR \ + WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_CPU_Q3_NE_MASK \ + 0x00000008 /* CPU_Q3_NE[3] */ +#define WF_PSE_TOP_INT_N9_STS_CPU_Q3_NE_SHFT 3 +#define WF_PSE_TOP_INT_N9_STS_CPU_Q2_NE_ADDR \ + WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_CPU_Q2_NE_MASK \ + 0x00000004 /* CPU_Q2_NE[2] */ +#define WF_PSE_TOP_INT_N9_STS_CPU_Q2_NE_SHFT 2 +#define WF_PSE_TOP_INT_N9_STS_CPU_Q1_NE_ADDR \ + WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_CPU_Q1_NE_MASK \ + 0x00000002 /* CPU_Q1_NE[1] */ +#define WF_PSE_TOP_INT_N9_STS_CPU_Q1_NE_SHFT 1 +#define WF_PSE_TOP_INT_N9_STS_CPU_Q0_NE_ADDR \ + WF_PSE_TOP_INT_N9_STS_ADDR +#define WF_PSE_TOP_INT_N9_STS_CPU_Q0_NE_MASK \ + 0x00000001 /* CPU_Q0_NE[0] */ +#define WF_PSE_TOP_INT_N9_STS_CPU_Q0_NE_SHFT 0 + +/* +* ---INT_N9_ERR_STS (0x820C8000 + 0x28)--- +* Q_CMD_ERR_P0[0] - (W1C) Queue command error interrupt status of +* port 0. Avoid unclear error flag, please clear flag when logic +reset. +* Q_CMD_ERR_P1[1] - (W1C) Queue command error interrupt status of +* port 1. Avoid unclear error flag, please clear flag when logic +reset. +* Q_CMD_ERR_P2[2] - (W1C) Queue command error interrupt status of +* port 2. Avoid unclear error flag, please clear flag when logic +reset. +* Q_CMD_ERR_P3[3] - (W1C) Queue command error interrupt status of +* port 3. Avoid unclear error flag, please clear flag when logic +reset. +* Q_CMD_ERR_P4[4] - (W1C) Queue command error interrupt status of +* port 4. Avoid unclear error flag, please clear flag when logic +reset. +* Q_CMD_ERR_P5[5] - (W1C) Queue command error interrupt status of +* port 5. Avoid unclear error flag, please clear flag when logic +reset. +* Q_CMD_ERR_P6[6] - (W1C) Queue command error interrupt status of +* port 6. Avoid unclear error flag, please clear flag when logic +reset. +* RESERVED7[7] - (RO) Reserved bits +* PAGE_UDF_P0[8] - (W1C) Page underflow interrupt status of port +* 0. Avoid unclear error flag, please clear flag when logic reset. +* PAGE_UDF_P1[9] - (W1C) Page underflow interrupt status of port +* 1. Avoid unclear error flag, please clear flag when logic reset. +* PAGE_UDF_P2[10] - (W1C) Page underflow interrupt status of port +* 2. Avoid unclear error flag, please clear flag when logic reset. +* PAGE_UDF_P3[11] - (W1C) Page underflow interrupt status of port +* 3. Avoid unclear error flag, please clear flag when logic reset. +* PAGE_UDF_P4[12] - (W1C) Page underflow interrupt status of port +* 4. Avoid unclear error flag, please clear flag when logic reset. +* PAGE_UDF_P5[13] - (W1C) Page underflow interrupt status of port +* 5. Avoid unclear error flag, please clear flag when logic reset. +* PAGE_UDF_P6[14] - (W1C) Page underflow interrupt status of port +* 6. Avoid unclear error flag, please clear flag when logic reset. +* RESERVED15[15] - (RO) Reserved bits +* QUEUE_OPER_ERR_P0[16] - (W1C) Queue operation error of port 0. Avoid +* unclear error flag, please clear flag when logic reset. +* QUEUE_OPER_ERR_P1[17] - (W1C) Queue operation error of port 1. Avoid +* unclear error flag, please clear flag when logic reset. +* QUEUE_OPER_ERR_P2[18] - (W1C) Queue operation error of port 2. Avoid +* unclear error flag, please clear flag when logic reset. +* QUEUE_OPER_ERR_P3[19] - (W1C) Queue operation error of port 3. Avoid +* unclear error flag, please clear flag when logic reset. +* QUEUE_OPER_ERR_P4[20] - (W1C) Queue operation error of port 4. Avoid +* unclear error flag, please clear flag when logic reset. +* QUEUE_OPER_ERR_P5[21] - (W1C) Queue operation error of port 5. Avoid +* unclear error flag, please clear flag when logic reset. +* QUEUE_OPER_ERR_P6[22] - (W1C) Queue operation error of port 6. Avoid +* unclear error flag, please clear flag when logic reset. +* RESERVED23[23] - (RO) Reserved bits +* DATA_OPER_ERR_P0[24] - (W1C) Data operation error of port 0. Avoid +* unclear error flag, please clear flag when logic reset. +* DATA_OPER_ERR_P1[25] - (W1C) Data operation error of port 1. Avoid +* unclear error flag, please clear flag when logic reset. +* DATA_OPER_ERR_P2[26] - (W1C) Data operation error of port 2. Avoid +* unclear error flag, please clear flag when logic reset. +* DATA_OPER_ERR_P3[27] - (W1C) Data operation error of port 3. Avoid +* unclear error flag, please clear flag when logic reset. +* DATA_OPER_ERR_P4[28] - (W1C) Data operation error of port 4. Avoid +* unclear error flag, please clear flag when logic reset. +* DATA_OPER_ERR_P5[29] - (W1C) Data operation error of port 5. Avoid +* unclear error flag, please clear flag when logic reset. +* DATA_OPER_ERR_P6[30] - (W1C) Data operation error of port 6. Avoid +* unclear error flag, please clear flag when logic reset. +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P6_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P6_MASK \ + 0x40000000 /* DATA_OPER_ERR_P6[30] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P6_SHFT 30 +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P5_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P5_MASK \ + 0x20000000 /* DATA_OPER_ERR_P5[29] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P5_SHFT 29 +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P4_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P4_MASK \ + 0x10000000 /* DATA_OPER_ERR_P4[28] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P4_SHFT 28 +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P3_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P3_MASK \ + 0x08000000 /* DATA_OPER_ERR_P3[27] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P3_SHFT 27 +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P2_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P2_MASK \ + 0x04000000 /* DATA_OPER_ERR_P2[26] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P2_SHFT 26 +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P1_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P1_MASK \ + 0x02000000 /* DATA_OPER_ERR_P1[25] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P1_SHFT 25 +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P0_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P0_MASK \ + 0x01000000 /* DATA_OPER_ERR_P0[24] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_DATA_OPER_ERR_P0_SHFT 24 +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P6_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P6_MASK \ + 0x00400000 /* QUEUE_OPER_ERR_P6[22] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P6_SHFT 22 +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P5_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P5_MASK \ + 0x00200000 /* QUEUE_OPER_ERR_P5[21] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P5_SHFT 21 +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P4_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P4_MASK \ + 0x00100000 /* QUEUE_OPER_ERR_P4[20] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P4_SHFT 20 +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P3_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P3_MASK \ + 0x00080000 /* QUEUE_OPER_ERR_P3[19] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P3_SHFT 19 +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P2_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P2_MASK \ + 0x00040000 /* QUEUE_OPER_ERR_P2[18] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P2_SHFT 18 +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P1_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P1_MASK \ + 0x00020000 /* QUEUE_OPER_ERR_P1[17] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P1_SHFT 17 +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P0_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P0_MASK \ + 0x00010000 /* QUEUE_OPER_ERR_P0[16] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_QUEUE_OPER_ERR_P0_SHFT 16 +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P6_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P6_MASK \ + 0x00004000 /* PAGE_UDF_P6[14] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P6_SHFT 14 +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P5_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P5_MASK \ + 0x00002000 /* PAGE_UDF_P5[13] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P5_SHFT 13 +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P4_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P4_MASK \ + 0x00001000 /* PAGE_UDF_P4[12] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P4_SHFT 12 +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P3_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P3_MASK \ + 0x00000800 /* PAGE_UDF_P3[11] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P3_SHFT 11 +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P2_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P2_MASK \ + 0x00000400 /* PAGE_UDF_P2[10] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P2_SHFT 10 +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P1_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P1_MASK \ + 0x00000200 /* PAGE_UDF_P1[9] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P1_SHFT 9 +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P0_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P0_MASK \ + 0x00000100 /* PAGE_UDF_P0[8] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_PAGE_UDF_P0_SHFT 8 +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P6_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P6_MASK \ + 0x00000040 /* Q_CMD_ERR_P6[6] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P6_SHFT 6 +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P5_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P5_MASK \ + 0x00000020 /* Q_CMD_ERR_P5[5] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P5_SHFT 5 +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P4_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P4_MASK \ + 0x00000010 /* Q_CMD_ERR_P4[4] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P4_SHFT 4 +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P3_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P3_MASK \ + 0x00000008 /* Q_CMD_ERR_P3[3] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P3_SHFT 3 +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P2_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P2_MASK \ + 0x00000004 /* Q_CMD_ERR_P2[2] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P2_SHFT 2 +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P1_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P1_MASK \ + 0x00000002 /* Q_CMD_ERR_P1[1] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P1_SHFT 1 +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P0_ADDR \ + WF_PSE_TOP_INT_N9_ERR_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P0_MASK \ + 0x00000001 /* Q_CMD_ERR_P0[0] */ +#define WF_PSE_TOP_INT_N9_ERR_STS_Q_CMD_ERR_P0_SHFT 0 + +/* +* ---INT_N9_ERR_MASK (0x820C8000 + 0x2C)--- +* EN_Q_CMD_ERR_P0[0] - (RW) Enable Queue command error interrupt +* status of port 0. Avoid unclear error flag, please clear flag when +logic +reset. +* EN_Q_CMD_ERR_P1[1] - (RW) Enable Queue command error interrupt +* status of port 1. Avoid unclear error flag, please clear flag when +logic +reset. +* EN_Q_CMD_ERR_P2[2] - (RW) Enable Queue command error interrupt +* status of port 2. Avoid unclear error flag, please clear flag when +logic +reset. +* EN_Q_CMD_ERR_P3[3] - (RW) Enable Queue command error interrupt +* status of port 3. Avoid unclear error flag, please clear flag when +logic +reset. +* EN_Q_CMD_ERR_P4[4] - (RW) Enable Queue command error interrupt +* status of port 4. Avoid unclear error flag, please clear flag when +logic +reset. +* EN_Q_CMD_ERR_P5[5] - (RW) Enable Queue command error interrupt +* status of port 5. Avoid unclear error flag, please clear flag when +logic +reset. +* EN_Q_CMD_ERR_P6[6] - (RW) Enable Queue command error interrupt +* status of port 6. Avoid unclear error flag, please clear flag when +logic +reset. +* RESERVED7[7] - (RO) Reserved bits +* EN_PAGE_UDF_P0[8] - (RW) Enable Page underflow interrupt status +* of port 0. Avoid unclear error flag, please clear flag when logic +reset. +* EN_PAGE_UDF_P1[9] - (RW) Enable Page underflow interrupt status +* of port 1. Avoid unclear error flag, please clear flag when logic +reset. +* EN_PAGE_UDF_P2[10] - (RW) Enable Page underflow interrupt status +* of port 2. Avoid unclear error flag, please clear flag when logic +reset. +* EN_PAGE_UDF_P3[11] - (RW) Enable Page underflow interrupt status +* of port 3. Avoid unclear error flag, please clear flag when logic +reset. +* EN_PAGE_UDF_P4[12] - (RW) Enable Page underflow interrupt status +* of port 4. Avoid unclear error flag, please clear flag when logic +reset. +* EN_PAGE_UDF_P5[13] - (RW) Enable Page underflow interrupt status +* of port 5. Avoid unclear error flag, please clear flag when logic +reset. +* EN_PAGE_UDF_P6[14] - (RW) Enable Page underflow interrupt status +* of port 6. Avoid unclear error flag, please clear flag when logic +reset. +* RESERVED15[15] - (RO) Reserved bits +* EN_QUEUE_OPER_ERR_P0[16] - (RW) Enable Queue operation error of port +0. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_QUEUE_OPER_ERR_P1[17] - (RW) Enable Queue operation error of port +1. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_QUEUE_OPER_ERR_P2[18] - (RW) Enable Queue operation error of port +2. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_QUEUE_OPER_ERR_P3[19] - (RW) Enable Queue operation error of port +3. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_QUEUE_OPER_ERR_P4[20] - (RW) Enable Queue operation error of port +4. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_QUEUE_OPER_ERR_P5[21] - (RW) Enable Queue operation error of port +5. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_QUEUE_OPER_ERR_P6[22] - (RW) Enable Queue operation error of port +6. +* Avoid unclear error flag, please clear flag when logic reset. +* RESERVED23[23] - (RO) Reserved bits +* EN_DATA_OPER_ERR_P0[24] - (RW) Enable Data operation error of port +0. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_DATA_OPER_ERR_P1[25] - (RW) Enable Data operation error of port +1. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_DATA_OPER_ERR_P2[26] - (RW) Enable Data operation error of port +2. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_DATA_OPER_ERR_P3[27] - (RW) Enable Data operation error of port +3. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_DATA_OPER_ERR_P4[28] - (RW) Enable Data operation error of port +4. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_DATA_OPER_ERR_P5[29] - (RW) Enable Data operation error of port +5. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_DATA_OPER_EN_ERR_P6[30] - (RW) Enable Data operation error of +* port 6. +* Avoid unclear error flag, please clear flag when logic reset. +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_EN_ERR_P6_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_EN_ERR_P6_MASK \ + 0x40000000 /* EN_DATA_OPER_EN_ERR_P6[30] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_EN_ERR_P6_SHFT 30 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P5_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P5_MASK \ + 0x20000000 /* EN_DATA_OPER_ERR_P5[29] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P5_SHFT 29 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P4_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P4_MASK \ + 0x10000000 /* EN_DATA_OPER_ERR_P4[28] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P4_SHFT 28 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P3_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P3_MASK \ + 0x08000000 /* EN_DATA_OPER_ERR_P3[27] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P3_SHFT 27 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P2_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P2_MASK \ + 0x04000000 /* EN_DATA_OPER_ERR_P2[26] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P2_SHFT 26 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P1_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P1_MASK \ + 0x02000000 /* EN_DATA_OPER_ERR_P1[25] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P1_SHFT 25 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P0_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P0_MASK \ + 0x01000000 /* EN_DATA_OPER_ERR_P0[24] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_DATA_OPER_ERR_P0_SHFT 24 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P6_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P6_MASK \ + 0x00400000 /* EN_QUEUE_OPER_ERR_P6[22] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P6_SHFT 22 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P5_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P5_MASK \ + 0x00200000 /* EN_QUEUE_OPER_ERR_P5[21] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P5_SHFT 21 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P4_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P4_MASK \ + 0x00100000 /* EN_QUEUE_OPER_ERR_P4[20] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P4_SHFT 20 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P3_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P3_MASK \ + 0x00080000 /* EN_QUEUE_OPER_ERR_P3[19] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P3_SHFT 19 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P2_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P2_MASK \ + 0x00040000 /* EN_QUEUE_OPER_ERR_P2[18] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P2_SHFT 18 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P1_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P1_MASK \ + 0x00020000 /* EN_QUEUE_OPER_ERR_P1[17] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P1_SHFT 17 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P0_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P0_MASK \ + 0x00010000 /* EN_QUEUE_OPER_ERR_P0[16] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_QUEUE_OPER_ERR_P0_SHFT 16 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P6_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P6_MASK \ + 0x00004000 /* EN_PAGE_UDF_P6[14] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P6_SHFT 14 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P5_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P5_MASK \ + 0x00002000 /* EN_PAGE_UDF_P5[13] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P5_SHFT 13 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P4_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P4_MASK \ + 0x00001000 /* EN_PAGE_UDF_P4[12] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P4_SHFT 12 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P3_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P3_MASK \ + 0x00000800 /* EN_PAGE_UDF_P3[11] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P3_SHFT 11 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P2_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P2_MASK \ + 0x00000400 /* EN_PAGE_UDF_P2[10] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P2_SHFT 10 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P1_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P1_MASK \ + 0x00000200 /* EN_PAGE_UDF_P1[9] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P1_SHFT 9 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P0_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P0_MASK \ + 0x00000100 /* EN_PAGE_UDF_P0[8] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_PAGE_UDF_P0_SHFT 8 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P6_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P6_MASK \ + 0x00000040 /* EN_Q_CMD_ERR_P6[6] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P6_SHFT 6 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P5_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P5_MASK \ + 0x00000020 /* EN_Q_CMD_ERR_P5[5] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P5_SHFT 5 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P4_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P4_MASK \ + 0x00000010 /* EN_Q_CMD_ERR_P4[4] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P4_SHFT 4 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P3_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P3_MASK \ + 0x00000008 /* EN_Q_CMD_ERR_P3[3] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P3_SHFT 3 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P2_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P2_MASK \ + 0x00000004 /* EN_Q_CMD_ERR_P2[2] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P2_SHFT 2 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P1_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P1_MASK \ + 0x00000002 /* EN_Q_CMD_ERR_P1[1] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P1_SHFT 1 +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P0_ADDR \ + WF_PSE_TOP_INT_N9_ERR_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P0_MASK \ + 0x00000001 /* EN_Q_CMD_ERR_P0[0] */ +#define WF_PSE_TOP_INT_N9_ERR_MASK_EN_Q_CMD_ERR_P0_SHFT 0 + +/* +* ---INT_N9_ERR1_STS (0x820C8000 + 0x30)--- +* WDT_ERR_P0[0] - (W1C) Port state watch dog timeout error +* interrupt status of port 0. Avoid unclear error flag, please clear +* flag when +* logic reset. +* WDT_ERR_P1[1] - (W1C) Port state watch dog timeout error +* interrupt status of port 1. Avoid unclear error flag, please clear +* flag when +* logic reset. +* WDT_ERR_P2[2] - (W1C) Port state watch dog timeout error +* interrupt status of port 2. Avoid unclear error flag, please clear +* flag when +* logic reset. +* WDT_ERR_P3[3] - (W1C) Port state watch dog timeout error +* interrupt status of port 3. Avoid unclear error flag, please clear +* flag when +* logic reset. +* WDT_ERR_P4[4] - (W1C) Port state watch dog timeout error +* interrupt status of port 4. Avoid unclear error flag, please clear +* flag when +* logic reset. +* WDT_ERR_P5[5] - (W1C) Port state watch dog timeout error +* interrupt status of port 5. Avoid unclear error flag, please clear +* flag when +* logic reset. +* WDT_ERR_P6[6] - (W1C) Port state watch dog timeout error +* interrupt status of port 6. Avoid unclear error flag, please clear +* flag when +* logic reset. +* RESERVED7[7] - (RO) Reserved bits +* FL_HANG_ERR[8] - (W1C) Frame link FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* PL_HANG_ERR[9] - (W1C) Page link FSM hang error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* DOUBLE_RLS_ERR[10] - (W1C) Double release error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* FREE_HEAD_TAIL_ERR[11] - (W1C) Free head/tail error interrupt. Avoid +* unclear error flag, please clear flag when logic reset. +* FL_QSTRUCT_ERR[12] - (W1C) Frame Link queue NULL error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* RESERVED13[31..13] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_INT_N9_ERR1_STS_FL_QSTRUCT_ERR_ADDR \ + WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_FL_QSTRUCT_ERR_MASK \ + 0x00001000 /* FL_QSTRUCT_ERR[12] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_FL_QSTRUCT_ERR_SHFT 12 +#define WF_PSE_TOP_INT_N9_ERR1_STS_FREE_HEAD_TAIL_ERR_ADDR \ + WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_FREE_HEAD_TAIL_ERR_MASK \ + 0x00000800 /* FREE_HEAD_TAIL_ERR[11] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_FREE_HEAD_TAIL_ERR_SHFT 11 +#define WF_PSE_TOP_INT_N9_ERR1_STS_DOUBLE_RLS_ERR_ADDR \ + WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_DOUBLE_RLS_ERR_MASK \ + 0x00000400 /* DOUBLE_RLS_ERR[10] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_DOUBLE_RLS_ERR_SHFT 10 +#define WF_PSE_TOP_INT_N9_ERR1_STS_PL_HANG_ERR_ADDR \ + WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_PL_HANG_ERR_MASK \ + 0x00000200 /* PL_HANG_ERR[9] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_PL_HANG_ERR_SHFT 9 +#define WF_PSE_TOP_INT_N9_ERR1_STS_FL_HANG_ERR_ADDR \ + WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_FL_HANG_ERR_MASK \ + 0x00000100 /* FL_HANG_ERR[8] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_FL_HANG_ERR_SHFT 8 +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P6_ADDR \ + WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P6_MASK \ + 0x00000040 /* WDT_ERR_P6[6] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P6_SHFT 6 +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P5_ADDR \ + WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P5_MASK \ + 0x00000020 /* WDT_ERR_P5[5] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P5_SHFT 5 +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P4_ADDR \ + WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P4_MASK \ + 0x00000010 /* WDT_ERR_P4[4] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P4_SHFT 4 +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P3_ADDR \ + WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P3_MASK \ + 0x00000008 /* WDT_ERR_P3[3] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P3_SHFT 3 +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P2_ADDR \ + WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P2_MASK \ + 0x00000004 /* WDT_ERR_P2[2] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P2_SHFT 2 +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P1_ADDR \ + WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P1_MASK \ + 0x00000002 /* WDT_ERR_P1[1] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P1_SHFT 1 +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P0_ADDR \ + WF_PSE_TOP_INT_N9_ERR1_STS_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P0_MASK \ + 0x00000001 /* WDT_ERR_P0[0] */ +#define WF_PSE_TOP_INT_N9_ERR1_STS_WDT_ERR_P0_SHFT 0 + +/* +* ---INT_N9_ERR1_MASK (0x820C8000 + 0x34)--- +* EN_WDT_ERR_P0[0] - (RW) Enable Port state watch dog timeout +* error interrupt status of port 0. Avoid unclear error flag, please +* clear flag +* when logic reset. +* EN_WDT_ERR_P1[1] - (RW) Enable Port state watch dog timeout +* error interrupt status of port 1. Avoid unclear error flag, please +* clear flag +* when logic reset. +* EN_WDT_ERR_P2[2] - (RW) Enable Port state watch dog timeout +* error interrupt status of port 2. Avoid unclear error flag, please +* clear flag +* when logic reset. +* EN_WDT_ERR_P3[3] - (RW) Enable Port state watch dog timeout +* error interrupt status of port 3. Avoid unclear error flag, please +* clear flag +* when logic reset. +* EN_WDT_ERR_P4[4] - (RW) Enable Port state watch dog timeout +* error interrupt status of port 4. Avoid unclear error flag, please +* clear flag +* when logic reset. +* EN_WDT_ERR_P5[5] - (RW) Enable Port state watch dog timeout +* error interrupt status of port 5. Avoid unclear error flag, please +* clear flag +* when logic reset. +* EN_WDT_ERR_P6[6] - (RW) Enable Port state watch dog timeout +* error interrupt status of port 6. Avoid unclear error flag, please +* clear flag +* when logic reset. +* RESERVED7[7] - (RO) Reserved bits +* EN_FL_HANG_ERR[8] - (RW) Enable Frame link FSM hang error +* interrupt. Avoid unclear error flag, please clear flag when logic +reset. +* PL_HANGEN__ERR[9] - (RW) Enable Page link FSM hang error +* interrupt. Avoid unclear error flag, please clear flag when logic +reset. +* EN_DOUBLE_RLS_ERR[10] - (RW) Enable Double release error interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_FREE_HEAD_TAIL_ERR[11] - (RW) Enable Free head/tail error +interrupt. +* Avoid unclear error flag, please clear flag when logic reset. +* EN_FL_QSTRTUT_ERR[12] - (RW) Enable Frame Link queue NULL error +* interrupt. Avoid unclear error flag, please clear flag when logic +reset. +* RESERVED13[31..13] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FL_QSTRTUT_ERR_ADDR \ + WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FL_QSTRTUT_ERR_MASK \ + 0x00001000 /* EN_FL_QSTRTUT_ERR[12] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FL_QSTRTUT_ERR_SHFT 12 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FREE_HEAD_TAIL_ERR_ADDR \ + WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FREE_HEAD_TAIL_ERR_MASK \ + 0x00000800 /* EN_FREE_HEAD_TAIL_ERR[11] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FREE_HEAD_TAIL_ERR_SHFT 11 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_DOUBLE_RLS_ERR_ADDR \ + WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_DOUBLE_RLS_ERR_MASK \ + 0x00000400 /* EN_DOUBLE_RLS_ERR[10] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_DOUBLE_RLS_ERR_SHFT 10 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_PL_HANGEN__ERR_ADDR \ + WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_PL_HANGEN__ERR_MASK \ + 0x00000200 /* PL_HANGEN__ERR[9] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_PL_HANGEN__ERR_SHFT 9 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FL_HANG_ERR_ADDR \ + WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FL_HANG_ERR_MASK \ + 0x00000100 /* EN_FL_HANG_ERR[8] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_FL_HANG_ERR_SHFT 8 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P6_ADDR \ + WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P6_MASK \ + 0x00000040 /* EN_WDT_ERR_P6[6] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P6_SHFT 6 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P5_ADDR \ + WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P5_MASK \ + 0x00000020 /* EN_WDT_ERR_P5[5] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P5_SHFT 5 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P4_ADDR \ + WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P4_MASK \ + 0x00000010 /* EN_WDT_ERR_P4[4] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P4_SHFT 4 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P3_ADDR \ + WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P3_MASK \ + 0x00000008 /* EN_WDT_ERR_P3[3] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P3_SHFT 3 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P2_ADDR \ + WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P2_MASK \ + 0x00000004 /* EN_WDT_ERR_P2[2] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P2_SHFT 2 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P1_ADDR \ + WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P1_MASK \ + 0x00000002 /* EN_WDT_ERR_P1[1] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P1_SHFT 1 +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P0_ADDR \ + WF_PSE_TOP_INT_N9_ERR1_MASK_ADDR +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P0_MASK \ + 0x00000001 /* EN_WDT_ERR_P0[0] */ +#define WF_PSE_TOP_INT_N9_ERR1_MASK_EN_WDT_ERR_P0_SHFT 0 + +/* +* ---C_GET_FID_0 (0x820C8000 + 0x40)--- +* QUEUE_FRAME_ID[15..0] - (RW) Frame ID for get command +* At GET_FRAME_TYPE = 2'h0/2'h1: +* QUEUE_FRAME_ID[15:14] = PID +* 2'h0: HIF port +* 2'h1: CPU port +* 2'h2: LMAC port +* QUEUE_FRAME_ID[9:0] = WLANID +* At GET_FRAME_TYPE = 2'h2/2'h3: +* QUEUE_FRAME_ID[11:0] = reference FID +* GET_FRAME_TYPE[19..16] - (RW) GET_SUB_TYPE +* RESERVED20[23..20] - (RO) Reserved bits +* GET_FRAME_QID[30..24] - (RW) Queue ID vlaue +* EXECUTE[31] - (A0) Executes command +*/ +#define WF_PSE_TOP_C_GET_FID_0_EXECUTE_ADDR \ + WF_PSE_TOP_C_GET_FID_0_ADDR +#define WF_PSE_TOP_C_GET_FID_0_EXECUTE_MASK \ + 0x80000000 /* EXECUTE[31] */ +#define WF_PSE_TOP_C_GET_FID_0_EXECUTE_SHFT 31 +#define WF_PSE_TOP_C_GET_FID_0_GET_FRAME_QID_ADDR \ + WF_PSE_TOP_C_GET_FID_0_ADDR +#define WF_PSE_TOP_C_GET_FID_0_GET_FRAME_QID_MASK \ + 0x7F000000 /* GET_FRAME_QID[30..24] */ +#define WF_PSE_TOP_C_GET_FID_0_GET_FRAME_QID_SHFT 24 +#define WF_PSE_TOP_C_GET_FID_0_GET_FRAME_TYPE_ADDR \ + WF_PSE_TOP_C_GET_FID_0_ADDR +#define WF_PSE_TOP_C_GET_FID_0_GET_FRAME_TYPE_MASK \ + 0x000F0000 /* GET_FRAME_TYPE[19..16] */ +#define WF_PSE_TOP_C_GET_FID_0_GET_FRAME_TYPE_SHFT 16 +#define WF_PSE_TOP_C_GET_FID_0_QUEUE_FRAME_ID_ADDR \ + WF_PSE_TOP_C_GET_FID_0_ADDR +#define WF_PSE_TOP_C_GET_FID_0_QUEUE_FRAME_ID_MASK \ + 0x0000FFFF /* QUEUE_FRAME_ID[15..0] */ +#define WF_PSE_TOP_C_GET_FID_0_QUEUE_FRAME_ID_SHFT 0 + +/* +* ---C_GET_FID_1 (0x820C8000 + 0x44)--- +* GET_RETURN_FID[11..0] - (RO) Return frame ID +* RESERVED12[14..12] - (RO) Reserved bits +* END[15] - (RO) Return frame ID is end FID +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_C_GET_FID_1_END_ADDR WF_PSE_TOP_C_GET_FID_1_ADDR +#define WF_PSE_TOP_C_GET_FID_1_END_MASK 0x00008000 /* END[15] */ +#define WF_PSE_TOP_C_GET_FID_1_END_SHFT 15 +#define WF_PSE_TOP_C_GET_FID_1_GET_RETURN_FID_ADDR \ + WF_PSE_TOP_C_GET_FID_1_ADDR +#define WF_PSE_TOP_C_GET_FID_1_GET_RETURN_FID_MASK \ + 0x00000FFF /* GET_RETURN_FID[11..0] */ +#define WF_PSE_TOP_C_GET_FID_1_GET_RETURN_FID_SHFT 0 + +/* +* ---C_EN_QUEUE_0 (0x820C8000 + 0x60)--- +* DST_WLANID[9..0] - (RW) Destination WLANID for enqueue +* RESERVED10[13..10] - (RO) Reserved bits +* DST_PID[15..14] - (RW) Destination port ID for enqueue +* SUB_TYPE[19..16] - (RW) Sub-type of enqueue command +* RESERVED20[22..20] - (RO) Reserved bits +* DELAY_ENQ[23] - (RW) Delays enqueue +* DST_QID[30..24] - (RW) Destination queue ID for enqueue +* EXECUTE[31] - (A0) Executes command +*/ +#define WF_PSE_TOP_C_EN_QUEUE_0_EXECUTE_ADDR \ + WF_PSE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_0_EXECUTE_MASK \ + 0x80000000 /* EXECUTE[31] */ +#define WF_PSE_TOP_C_EN_QUEUE_0_EXECUTE_SHFT 31 +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_QID_ADDR \ + WF_PSE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_QID_MASK \ + 0x7F000000 /* DST_QID[30..24] */ +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_QID_SHFT 24 +#define WF_PSE_TOP_C_EN_QUEUE_0_DELAY_ENQ_ADDR \ + WF_PSE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_0_DELAY_ENQ_MASK \ + 0x00800000 /* DELAY_ENQ[23] */ +#define WF_PSE_TOP_C_EN_QUEUE_0_DELAY_ENQ_SHFT 23 +#define WF_PSE_TOP_C_EN_QUEUE_0_SUB_TYPE_ADDR \ + WF_PSE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_0_SUB_TYPE_MASK \ + 0x000F0000 /* SUB_TYPE[19..16] */ +#define WF_PSE_TOP_C_EN_QUEUE_0_SUB_TYPE_SHFT 16 +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_PID_ADDR \ + WF_PSE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_PID_MASK \ + 0x0000C000 /* DST_PID[15..14] */ +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_PID_SHFT 14 +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_WLANID_ADDR \ + WF_PSE_TOP_C_EN_QUEUE_0_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_WLANID_MASK \ + 0x000003FF /* DST_WLANID[9..0] */ +#define WF_PSE_TOP_C_EN_QUEUE_0_DST_WLANID_SHFT 0 + +/* +* ---C_EN_QUEUE_1 (0x820C8000 + 0x64)--- +* CUR_LIST_FID_START[11..0] - (RW) Start frame ID of enqueue operation +* list, enqueue FID of enqueue operation +* RESERVED12[15..12] - (RO) Reserved bits +* CUR_LIST_FID_END[27..16] - (RW) End frame ID of enqueue operation +list +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_END_ADDR \ + WF_PSE_TOP_C_EN_QUEUE_1_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_END_MASK \ + 0x0FFF0000 /* CUR_LIST_FID_END[27..16] */ +#define WF_PSE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_END_SHFT 16 +#define WF_PSE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_START_ADDR \ + WF_PSE_TOP_C_EN_QUEUE_1_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_START_MASK \ + 0x00000FFF /* CUR_LIST_FID_START[11..0] */ +#define WF_PSE_TOP_C_EN_QUEUE_1_CUR_LIST_FID_START_SHFT 0 + +/* +* ---C_EN_QUEUE_2 (0x820C8000 + 0x68)--- +* TARGET_FID[11..0] - (RW) Target reference FID for enqueue +operation +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_C_EN_QUEUE_2_TARGET_FID_ADDR \ + WF_PSE_TOP_C_EN_QUEUE_2_ADDR +#define WF_PSE_TOP_C_EN_QUEUE_2_TARGET_FID_MASK \ + 0x00000FFF /* TARGET_FID[11..0] */ +#define WF_PSE_TOP_C_EN_QUEUE_2_TARGET_FID_SHFT 0 + +/* +* ---C_DE_QUEUE_0 (0x820C8000 + 0x80)--- +* SRC_WLANID[9..0] - (RW) Source WLAN ID for dequeue command +* RESERVED10[13..10] - (RO) Reserved bits +* SRC_PID[15..14] - (RW) Source port ID for dequeue command +* DEQ_SUB_TYPE[19..16] - (RW) Dequeue subtype of dequeue command +* ENQ_SUB_TYPE[22..20] - (RW) Enqueue subtype of enqueue command +* Only valid in Deq&Enq type. +* ENQ_VLD[23] - (RW) Deq&Enq command valid +* SRC_QID[30..24] - (RW) Source queue ID for dequeue command +* EXECUTE[31] - (A0) Executes dequeue command +*/ +#define WF_PSE_TOP_C_DE_QUEUE_0_EXECUTE_ADDR \ + WF_PSE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_0_EXECUTE_MASK \ + 0x80000000 /* EXECUTE[31] */ +#define WF_PSE_TOP_C_DE_QUEUE_0_EXECUTE_SHFT 31 +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_QID_ADDR \ + WF_PSE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_QID_MASK \ + 0x7F000000 /* SRC_QID[30..24] */ +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_QID_SHFT 24 +#define WF_PSE_TOP_C_DE_QUEUE_0_ENQ_VLD_ADDR \ + WF_PSE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_0_ENQ_VLD_MASK \ + 0x00800000 /* ENQ_VLD[23] */ +#define WF_PSE_TOP_C_DE_QUEUE_0_ENQ_VLD_SHFT 23 +#define WF_PSE_TOP_C_DE_QUEUE_0_ENQ_SUB_TYPE_ADDR \ + WF_PSE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_0_ENQ_SUB_TYPE_MASK \ + 0x00700000 /* ENQ_SUB_TYPE[22..20] */ +#define WF_PSE_TOP_C_DE_QUEUE_0_ENQ_SUB_TYPE_SHFT 20 +#define WF_PSE_TOP_C_DE_QUEUE_0_DEQ_SUB_TYPE_ADDR \ + WF_PSE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_0_DEQ_SUB_TYPE_MASK \ + 0x000F0000 /* DEQ_SUB_TYPE[19..16] */ +#define WF_PSE_TOP_C_DE_QUEUE_0_DEQ_SUB_TYPE_SHFT 16 +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_PID_ADDR \ + WF_PSE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_PID_MASK \ + 0x0000C000 /* SRC_PID[15..14] */ +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_PID_SHFT 14 +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_WLANID_ADDR \ + WF_PSE_TOP_C_DE_QUEUE_0_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_WLANID_MASK \ + 0x000003FF /* SRC_WLANID[9..0] */ +#define WF_PSE_TOP_C_DE_QUEUE_0_SRC_WLANID_SHFT 0 + +/* +* ---C_DE_QUEUE_1 (0x820C8000 + 0x84)--- +* CUR_LIST_FID_START[11..0] - (RW) Start frame ID of dequeue operation +* list, enqueue start FID of enqueue operation +* Only valid in Deq&Enq type. +* RESERVED12[15..12] - (RO) Reserved bits +* CUR_LIST_FID_END[27..16] - (RW) End framd ID of dequeue operation +list, +* enqueue end FID of enqueue operation +* Only valid in Deq&Enq type. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_END_ADDR \ + WF_PSE_TOP_C_DE_QUEUE_1_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_END_MASK \ + 0x0FFF0000 /* CUR_LIST_FID_END[27..16] */ +#define WF_PSE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_END_SHFT 16 +#define WF_PSE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_START_ADDR \ + WF_PSE_TOP_C_DE_QUEUE_1_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_START_MASK \ + 0x00000FFF /* CUR_LIST_FID_START[11..0] */ +#define WF_PSE_TOP_C_DE_QUEUE_1_CUR_LIST_FID_START_SHFT 0 + +/* +* ---C_DE_QUEUE_2 (0x820C8000 + 0x88)--- +* DEQ_ENQ_DST_WLANID[9..0] - (RW) Destination WLAN ID for enqueue +command +* Only valid in Deq&Enq type. +* RESERVED10[13..10] - (RO) Reserved bits +* DEQ_ENQ_DST_PID[15..14] - (RW) Destination port ID for dequeue +command +* RESERVED16[23..16] - (RO) Reserved bits +* DEQ_ENQ_DST_QID[30..24] - (RW) Destination queue ID for enqueue +command +* Only valid in Deq&Enq type. +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_QID_ADDR \ + WF_PSE_TOP_C_DE_QUEUE_2_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_QID_MASK \ + 0x7F000000 /* DEQ_ENQ_DST_QID[30..24] */ +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_QID_SHFT 24 +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_PID_ADDR \ + WF_PSE_TOP_C_DE_QUEUE_2_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_PID_MASK \ + 0x0000C000 /* DEQ_ENQ_DST_PID[15..14] */ +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_PID_SHFT 14 +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_WLANID_ADDR \ + WF_PSE_TOP_C_DE_QUEUE_2_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_WLANID_MASK \ + 0x000003FF /* DEQ_ENQ_DST_WLANID[9..0] */ +#define WF_PSE_TOP_C_DE_QUEUE_2_DEQ_ENQ_DST_WLANID_SHFT 0 + +/* +* ---C_DE_QUEUE_3 (0x820C8000 + 0x8c)--- +* DEQ_HEAD_FDI[11..0] - (RO) Head FID got from dequeue command +* RESERVED12[14..12] - (RO) Reserved bits +* DEQ_EMPTY[15] - (RO) Queue empty after dequeue command is +executed +* DEQ_TAIL_FID[27..16] - (RO) Last FID got from dequeue command +* RESERVED28[30..28] - (RO) Reserved bits +* BUSY[31] - (RO) Dequeue execute busy +*/ +#define WF_PSE_TOP_C_DE_QUEUE_3_BUSY_ADDR WF_PSE_TOP_C_DE_QUEUE_3_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_3_BUSY_MASK 0x80000000 /* BUSY[31] */ +#define WF_PSE_TOP_C_DE_QUEUE_3_BUSY_SHFT 31 +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_TAIL_FID_ADDR \ + WF_PSE_TOP_C_DE_QUEUE_3_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_TAIL_FID_MASK \ + 0x0FFF0000 /* DEQ_TAIL_FID[27..16] */ +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_TAIL_FID_SHFT 16 +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_EMPTY_ADDR \ + WF_PSE_TOP_C_DE_QUEUE_3_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_EMPTY_MASK \ + 0x00008000 /* DEQ_EMPTY[15] */ +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_EMPTY_SHFT 15 +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_HEAD_FDI_ADDR \ + WF_PSE_TOP_C_DE_QUEUE_3_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_HEAD_FDI_MASK \ + 0x00000FFF /* DEQ_HEAD_FDI[11..0] */ +#define WF_PSE_TOP_C_DE_QUEUE_3_DEQ_HEAD_FDI_SHFT 0 + +/* +* ---C_DE_QUEUE_4 (0x820C8000 + 0x90)--- +* DEQ_ENQ_REF_FID[11..0] - (RW) Reference frame ID for enqueue command +* Only valid in Deq&Enq type. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_C_DE_QUEUE_4_DEQ_ENQ_REF_FID_ADDR \ + WF_PSE_TOP_C_DE_QUEUE_4_ADDR +#define WF_PSE_TOP_C_DE_QUEUE_4_DEQ_ENQ_REF_FID_MASK \ + 0x00000FFF /* DEQ_ENQ_REF_FID[11..0] */ +#define WF_PSE_TOP_C_DE_QUEUE_4_DEQ_ENQ_REF_FID_SHFT 0 + +/* +* ---ALLOCATE_0 (0x820C8000 + 0xA0)--- +* ALLOCATE_FRAME_LENGTH[13..0] - (RW) Allocate frame length +* Unit: DW (4 bytes) +* RESERVED14[15..14] - (RO) Reserved bits +* ALLOCATE_QID[20..16] - (RW) QID used for allocate buffer +* RESERVED21[30..21] - (RO) Reserved bits +* EXECUTE[31] - (A0) Executes allocate buffer command +*/ +#define WF_PSE_TOP_ALLOCATE_0_EXECUTE_ADDR WF_PSE_TOP_ALLOCATE_0_ADDR +#define WF_PSE_TOP_ALLOCATE_0_EXECUTE_MASK \ + 0x80000000 /* EXECUTE[31] */ +#define WF_PSE_TOP_ALLOCATE_0_EXECUTE_SHFT 31 +#define WF_PSE_TOP_ALLOCATE_0_ALLOCATE_QID_ADDR \ + WF_PSE_TOP_ALLOCATE_0_ADDR +#define WF_PSE_TOP_ALLOCATE_0_ALLOCATE_QID_MASK \ + 0x001F0000 /* ALLOCATE_QID[20..16] */ +#define WF_PSE_TOP_ALLOCATE_0_ALLOCATE_QID_SHFT 16 +#define WF_PSE_TOP_ALLOCATE_0_ALLOCATE_FRAME_LENGTH_ADDR \ + WF_PSE_TOP_ALLOCATE_0_ADDR +#define WF_PSE_TOP_ALLOCATE_0_ALLOCATE_FRAME_LENGTH_MASK \ + 0x00003FFF /* ALLOCATE_FRAME_LENGTH[13..0] */ +#define WF_PSE_TOP_ALLOCATE_0_ALLOCATE_FRAME_LENGTH_SHFT 0 + +/* +* ---ALLOCATE_1 (0x820C8000 + 0xA4)--- +* ALLOCATE_FID[11..0] - (RO) Return frame ID for allocate buffer +command +* RESERVED12[30..12] - (RO) Reserved bits +* EXECUTE[31] - (RO) Execute status of allocate buffer +command +*/ +#define WF_PSE_TOP_ALLOCATE_1_EXECUTE_ADDR WF_PSE_TOP_ALLOCATE_1_ADDR +#define WF_PSE_TOP_ALLOCATE_1_EXECUTE_MASK \ + 0x80000000 /* EXECUTE[31] */ +#define WF_PSE_TOP_ALLOCATE_1_EXECUTE_SHFT 31 +#define WF_PSE_TOP_ALLOCATE_1_ALLOCATE_FID_ADDR \ + WF_PSE_TOP_ALLOCATE_1_ADDR +#define WF_PSE_TOP_ALLOCATE_1_ALLOCATE_FID_MASK \ + 0x00000FFF /* ALLOCATE_FID[11..0] */ +#define WF_PSE_TOP_ALLOCATE_1_ALLOCATE_FID_SHFT 0 + +/* +* ---QUEUE_EMPTY (0x820C8000 + 0xB0)--- +* CPU_Q0_EMPTY[0] - (RO) CPU queue 0 empty status +* CPU_Q1_EMPTY[1] - (RO) CPU queue 1 empty status +* CPU_Q2_EMPTY[2] - (RO) CPU queue 2 empty status +* CPU_Q3_EMPTY[3] - (RO) CPU queue 3 empty status +* HIF_8_EMPTY[4] - (RO) HIF queue 8 empty status +* HIF_9_EMPTY[5] - (RO) HIF queue 9 empty status +* HIF_10_EMPTY[6] - (RO) HIF queue 10 empty status +* HIF_11_EMPTY[7] - (RO) HIF queue 11 empty status +* HIF_0_EMPTY[8] - (RO) HIF queue 0 empty status +* HIF_1_EMPTY[9] - (RO) HIF queue 1 empty status +* HIF_2_EMPTY[10] - (RO) HIF queue 2 empty status +* HIF_3_EMPTY[11] - (RO) HIF queue 3 empty status +* HIF_4_EMPTY[12] - (RO) HIF queue 4 empty status +* HIF_5_EMPTY[13] - (RO) HIF queue 5 empty status +* HIF_6_EMPTY[14] - (RO) HIF queue 6 empty status +* HIF_7_EMPTY[15] - (RO) HIF queue 7 empty status +* LMAC_TX_QUEUE_EMPTY[16] - (RO) LMAC TX queue empty status +* MDP_TX_QUEUE_EMPTY[17] - (RO) MDP TX queue empty status +* MDP_RX_QUEUE_EMPTY[18] - (RO) MDP RX queue empty status +* SEC_TX_QUEUE_EMPTY[19] - (RO) SEC TX queue empty status +* SEC_RX_QUEUE_EMPTY[20] - (RO) SEC RX queue empty status +* SFD_PARK_QUEUE_EMPTY[21] - (RO) SFD PARK queue empty status +* MDP_TXIOC_QUEUE_EMPTY[22] - (RO) MDP TXIOC queue empty status +* MDP_RXIOC_QUEUE_EMPTY[23] - (RO) MDP RXIOC queue empty status +* MDP_TX1_QUEUE_EMPTY[24] - (RO) MDP TX queue empty status for Band 1 +* SEC_TX1_QUEUE_EMPTY[25] - (RO) SEC TX queue empty status for Band 1 +* MDP_TXIOC1_QUEUE_EMPTY[26] - (RO) MDP TXIOC queue empty status for +* Band 1 +* MDP_RXIOC1_QUEUE_EMPTY[27] - (RO) MDP RXIOC queue empty status for +* Band 1 +* RESERVED28[30..28] - (RO) Reserved bits +* RLS_Q_EMTPY[31] - (RO) Release queue empty status +*/ +#define WF_PSE_TOP_QUEUE_EMPTY_RLS_Q_EMTPY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_RLS_Q_EMTPY_MASK \ + 0x80000000 /* RLS_Q_EMTPY[31] */ +#define WF_PSE_TOP_QUEUE_EMPTY_RLS_Q_EMTPY_SHFT 31 +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC1_QUEUE_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC1_QUEUE_EMPTY_MASK \ + 0x08000000 /* MDP_RXIOC1_QUEUE_EMPTY[27] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC1_QUEUE_EMPTY_SHFT 27 +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC1_QUEUE_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC1_QUEUE_EMPTY_MASK \ + 0x04000000 /* MDP_TXIOC1_QUEUE_EMPTY[26] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC1_QUEUE_EMPTY_SHFT 26 +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_TX1_QUEUE_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_TX1_QUEUE_EMPTY_MASK \ + 0x02000000 /* SEC_TX1_QUEUE_EMPTY[25] */ +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_TX1_QUEUE_EMPTY_SHFT 25 +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TX1_QUEUE_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TX1_QUEUE_EMPTY_MASK \ + 0x01000000 /* MDP_TX1_QUEUE_EMPTY[24] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TX1_QUEUE_EMPTY_SHFT 24 +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC_QUEUE_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC_QUEUE_EMPTY_MASK \ + 0x00800000 /* MDP_RXIOC_QUEUE_EMPTY[23] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RXIOC_QUEUE_EMPTY_SHFT 23 +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC_QUEUE_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC_QUEUE_EMPTY_MASK \ + 0x00400000 /* MDP_TXIOC_QUEUE_EMPTY[22] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TXIOC_QUEUE_EMPTY_SHFT 22 +#define WF_PSE_TOP_QUEUE_EMPTY_SFD_PARK_QUEUE_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_SFD_PARK_QUEUE_EMPTY_MASK \ + 0x00200000 /* SFD_PARK_QUEUE_EMPTY[21] */ +#define WF_PSE_TOP_QUEUE_EMPTY_SFD_PARK_QUEUE_EMPTY_SHFT 21 +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_RX_QUEUE_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_RX_QUEUE_EMPTY_MASK \ + 0x00100000 /* SEC_RX_QUEUE_EMPTY[20] */ +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_RX_QUEUE_EMPTY_SHFT 20 +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_TX_QUEUE_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_TX_QUEUE_EMPTY_MASK \ + 0x00080000 /* SEC_TX_QUEUE_EMPTY[19] */ +#define WF_PSE_TOP_QUEUE_EMPTY_SEC_TX_QUEUE_EMPTY_SHFT 19 +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RX_QUEUE_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RX_QUEUE_EMPTY_MASK \ + 0x00040000 /* MDP_RX_QUEUE_EMPTY[18] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_RX_QUEUE_EMPTY_SHFT 18 +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TX_QUEUE_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TX_QUEUE_EMPTY_MASK \ + 0x00020000 /* MDP_TX_QUEUE_EMPTY[17] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MDP_TX_QUEUE_EMPTY_SHFT 17 +#define WF_PSE_TOP_QUEUE_EMPTY_LMAC_TX_QUEUE_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_LMAC_TX_QUEUE_EMPTY_MASK \ + 0x00010000 /* LMAC_TX_QUEUE_EMPTY[16] */ +#define WF_PSE_TOP_QUEUE_EMPTY_LMAC_TX_QUEUE_EMPTY_SHFT 16 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_7_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_7_EMPTY_MASK \ + 0x00008000 /* HIF_7_EMPTY[15] */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_7_EMPTY_SHFT 15 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_6_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_6_EMPTY_MASK \ + 0x00004000 /* HIF_6_EMPTY[14] */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_6_EMPTY_SHFT 14 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_5_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_5_EMPTY_MASK \ + 0x00002000 /* HIF_5_EMPTY[13] */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_5_EMPTY_SHFT 13 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_4_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_4_EMPTY_MASK \ + 0x00001000 /* HIF_4_EMPTY[12] */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_4_EMPTY_SHFT 12 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_3_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_3_EMPTY_MASK \ + 0x00000800 /* HIF_3_EMPTY[11] */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_3_EMPTY_SHFT 11 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_2_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_2_EMPTY_MASK \ + 0x00000400 /* HIF_2_EMPTY[10] */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_2_EMPTY_SHFT 10 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_1_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_1_EMPTY_MASK \ + 0x00000200 /* HIF_1_EMPTY[9] */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_1_EMPTY_SHFT 9 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_0_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_0_EMPTY_MASK \ + 0x00000100 /* HIF_0_EMPTY[8] */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_0_EMPTY_SHFT 8 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_11_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_11_EMPTY_MASK \ + 0x00000080 /* HIF_11_EMPTY[7] */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_11_EMPTY_SHFT 7 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_10_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_10_EMPTY_MASK \ + 0x00000040 /* HIF_10_EMPTY[6] */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_10_EMPTY_SHFT 6 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_9_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_9_EMPTY_MASK \ + 0x00000020 /* HIF_9_EMPTY[5] */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_9_EMPTY_SHFT 5 +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_8_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_8_EMPTY_MASK \ + 0x00000010 /* HIF_8_EMPTY[4] */ +#define WF_PSE_TOP_QUEUE_EMPTY_HIF_8_EMPTY_SHFT 4 +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q3_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q3_EMPTY_MASK \ + 0x00000008 /* CPU_Q3_EMPTY[3] */ +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q3_EMPTY_SHFT 3 +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q2_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q2_EMPTY_MASK \ + 0x00000004 /* CPU_Q2_EMPTY[2] */ +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q2_EMPTY_SHFT 2 +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q1_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q1_EMPTY_MASK \ + 0x00000002 /* CPU_Q1_EMPTY[1] */ +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q1_EMPTY_SHFT 1 +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q0_EMPTY_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q0_EMPTY_MASK \ + 0x00000001 /* CPU_Q0_EMPTY[0] */ +#define WF_PSE_TOP_QUEUE_EMPTY_CPU_Q0_EMPTY_SHFT 0 + +/* +* ---QUEUE_EMPTY_MASK (0x820C8000 + 0xB4)--- +* RESERVED0[7..0] - (RO) Reserved bits +* HIF_0_EMPTY_MASK[8] - (RW) Mask control of HIF queue 0 empty status +* HIF_1_EMPTY_MASK[9] - (RW) Mask control of HIF queue 1 empty status +* HIF_2_EMPTY_MASK[10] - (RW) Mask control of HIF queue 2 empty status +* HIF_3_EMPTY_MASK[11] - (RW) Mask control of HIF queue 3 empty status +* HIF_4_EMPTY_MASK[12] - (RW) Mask control of HIF queue 4 empty status +* HIF_5_EMPTY_MASK[13] - (RW) Mask control of HIF queue 5 empty status +* HIF_6_EMPTY_MASK[14] - (RW) Mask control of HIF queue 6 empty status +* HIF_7_EMPTY_MASK[15] - (RW) Mask control of HIF queue 7 empty status +* HIF_8_EMPTY_MASK[16] - (RW) Mask control of HIF queue 8 empty status +* HIF_9_EMPTY_MASK[17] - (RW) Mask control of HIF queue 9 empty status +* HIF_10_EMPTY_MASK[18] - (RW) Mask control of HIF queue 10 empty +status +* HIF_11_EMPTY_MASK[19] - (RW) Mask control of HIF queue 11 empty +status +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_11_EMPTY_MASK_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_11_EMPTY_MASK_MASK \ + 0x00080000 /* HIF_11_EMPTY_MASK[19] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_11_EMPTY_MASK_SHFT 19 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_10_EMPTY_MASK_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_10_EMPTY_MASK_MASK \ + 0x00040000 /* HIF_10_EMPTY_MASK[18] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_10_EMPTY_MASK_SHFT 18 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_9_EMPTY_MASK_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_9_EMPTY_MASK_MASK \ + 0x00020000 /* HIF_9_EMPTY_MASK[17] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_9_EMPTY_MASK_SHFT 17 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_8_EMPTY_MASK_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_8_EMPTY_MASK_MASK \ + 0x00010000 /* HIF_8_EMPTY_MASK[16] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_8_EMPTY_MASK_SHFT 16 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_7_EMPTY_MASK_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_7_EMPTY_MASK_MASK \ + 0x00008000 /* HIF_7_EMPTY_MASK[15] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_7_EMPTY_MASK_SHFT 15 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_6_EMPTY_MASK_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_6_EMPTY_MASK_MASK \ + 0x00004000 /* HIF_6_EMPTY_MASK[14] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_6_EMPTY_MASK_SHFT 14 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_5_EMPTY_MASK_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_5_EMPTY_MASK_MASK \ + 0x00002000 /* HIF_5_EMPTY_MASK[13] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_5_EMPTY_MASK_SHFT 13 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_4_EMPTY_MASK_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_4_EMPTY_MASK_MASK \ + 0x00001000 /* HIF_4_EMPTY_MASK[12] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_4_EMPTY_MASK_SHFT 12 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_3_EMPTY_MASK_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_3_EMPTY_MASK_MASK \ + 0x00000800 /* HIF_3_EMPTY_MASK[11] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_3_EMPTY_MASK_SHFT 11 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_2_EMPTY_MASK_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_2_EMPTY_MASK_MASK \ + 0x00000400 /* HIF_2_EMPTY_MASK[10] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_2_EMPTY_MASK_SHFT 10 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_1_EMPTY_MASK_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_1_EMPTY_MASK_MASK \ + 0x00000200 /* HIF_1_EMPTY_MASK[9] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_1_EMPTY_MASK_SHFT 9 +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_0_EMPTY_MASK_ADDR \ + WF_PSE_TOP_QUEUE_EMPTY_MASK_ADDR +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_0_EMPTY_MASK_MASK \ + 0x00000100 /* HIF_0_EMPTY_MASK[8] */ +#define WF_PSE_TOP_QUEUE_EMPTY_MASK_HIF_0_EMPTY_MASK_SHFT 8 + +/* +* ---FREEPG_START_END (0x820C8000 + 0xC0)--- +* FREEPG_START[11..0] - (RW) Start page setting of free pages +* RESERVED12[15..12] - (RO) Reserved bits +* FREEPG_END[27..16] - (RW) End page setting of free page +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_FREEPG_START_END_FREEPG_END_ADDR \ + WF_PSE_TOP_FREEPG_START_END_ADDR +#define WF_PSE_TOP_FREEPG_START_END_FREEPG_END_MASK \ + 0x0FFF0000 /* FREEPG_END[27..16] */ +#define WF_PSE_TOP_FREEPG_START_END_FREEPG_END_SHFT 16 +#define WF_PSE_TOP_FREEPG_START_END_FREEPG_START_ADDR \ + WF_PSE_TOP_FREEPG_START_END_ADDR +#define WF_PSE_TOP_FREEPG_START_END_FREEPG_START_MASK \ + 0x00000FFF /* FREEPG_START[11..0] */ +#define WF_PSE_TOP_FREEPG_START_END_FREEPG_START_SHFT 0 + +/* +* ---PSE_MODULE_CKG_DIS (0x820C8000 + 0xc4)--- +* DIS_FL_DYN_CKG[0] - (RW) Disable control of PSE frame link module +* dynamic clock gating function +* DIS_PL_DYN_CKG[1] - (RW) Disable control of PSE page link module +* dynamic clock gating function +* DIS_CPU_PORT_DYN_CKG[2] - (RW) Disable control of PSE CPU port +module +* dynamic clock gating function +* DIS_HIF_PORT_DYN_CKG[3] - (RW) Disable control of PSE HIF port +module +* dynamic clock gating function +* DIS_WF_PLE_PORT_DYN_CKG[4] - (RW) Disable control of PSE LMAC and +* PLE port +* module dynamic clock gating function +* DIS_RLS_DYN_CKG[5] - (RW) Disable control of PSE release module +* dynamic clock gating function +* DIS_RL_DYN_CKG[6] - (RW) Disable control of PSE relay information +* module dynamic clock gating function +* RESERVED7[8..7] - (RO) Reserved bits +* DIS_CSR_DYN_CKG[9] - (RW) Disable control of PSE CR module dynamic +* clock gating function +* DIS_CPU_WRAP_DYN_CKG[10] - (RW) Disable control of PSE CPU_WRAP +module +* dynamic clock gating function +* DIS_DBG_DYN_CKG[11] - (RW) Disable control of PSE debug module +* dynamic clock gating function +* DIS_MDP_DYN_CKG[12] - (RW) Disable control of PSE MDP module +* dynamic clock gating function +* DIS_SEC_DYN_CKG[13] - (RW) Disable control of PSE SEC module +* dynamic clock gating function +* RESERVED14[31..14] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_SEC_DYN_CKG_ADDR \ + WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_SEC_DYN_CKG_MASK \ + 0x00002000 /* DIS_SEC_DYN_CKG[13] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_SEC_DYN_CKG_SHFT 13 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_MDP_DYN_CKG_ADDR \ + WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_MDP_DYN_CKG_MASK \ + 0x00001000 /* DIS_MDP_DYN_CKG[12] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_MDP_DYN_CKG_SHFT 12 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_DBG_DYN_CKG_ADDR \ + WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_DBG_DYN_CKG_MASK \ + 0x00000800 /* DIS_DBG_DYN_CKG[11] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_DBG_DYN_CKG_SHFT 11 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CPU_WRAP_DYN_CKG_ADDR \ + WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CPU_WRAP_DYN_CKG_MASK \ + 0x00000400 /* DIS_CPU_WRAP_DYN_CKG[10] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CPU_WRAP_DYN_CKG_SHFT 10 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CSR_DYN_CKG_ADDR \ + WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CSR_DYN_CKG_MASK \ + 0x00000200 /* DIS_CSR_DYN_CKG[9] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CSR_DYN_CKG_SHFT 9 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_RL_DYN_CKG_ADDR \ + WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_RL_DYN_CKG_MASK \ + 0x00000040 /* DIS_RL_DYN_CKG[6] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_RL_DYN_CKG_SHFT 6 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_RLS_DYN_CKG_ADDR \ + WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_RLS_DYN_CKG_MASK \ + 0x00000020 /* DIS_RLS_DYN_CKG[5] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_RLS_DYN_CKG_SHFT 5 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_WF_PLE_PORT_DYN_CKG_ADDR \ + WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_WF_PLE_PORT_DYN_CKG_MASK \ + 0x00000010 /* DIS_WF_PLE_PORT_DYN_CKG[4] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_WF_PLE_PORT_DYN_CKG_SHFT 4 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_HIF_PORT_DYN_CKG_ADDR \ + WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_HIF_PORT_DYN_CKG_MASK \ + 0x00000008 /* DIS_HIF_PORT_DYN_CKG[3] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_HIF_PORT_DYN_CKG_SHFT 3 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CPU_PORT_DYN_CKG_ADDR \ + WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CPU_PORT_DYN_CKG_MASK \ + 0x00000004 /* DIS_CPU_PORT_DYN_CKG[2] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_CPU_PORT_DYN_CKG_SHFT 2 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_PL_DYN_CKG_ADDR \ + WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_PL_DYN_CKG_MASK \ + 0x00000002 /* DIS_PL_DYN_CKG[1] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_PL_DYN_CKG_SHFT 1 +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_FL_DYN_CKG_ADDR \ + WF_PSE_TOP_PSE_MODULE_CKG_DIS_ADDR +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_FL_DYN_CKG_MASK \ + 0x00000001 /* DIS_FL_DYN_CKG[0] */ +#define WF_PSE_TOP_PSE_MODULE_CKG_DIS_DIS_FL_DYN_CKG_SHFT 0 + +/* +* ---TO_N9_INT (0x820C8000 + 0xf0)--- +* CR4_CMD[30..0] - (RW) Command for N9 +* TOGGLE[31] - (RW) When this bit is toggled, HW will send +* interrupt to N9. +*/ +#define WF_PSE_TOP_TO_N9_INT_TOGGLE_ADDR WF_PSE_TOP_TO_N9_INT_ADDR +#define WF_PSE_TOP_TO_N9_INT_TOGGLE_MASK 0x80000000 /* TOGGLE[31] */ +#define WF_PSE_TOP_TO_N9_INT_TOGGLE_SHFT 31 +#define WF_PSE_TOP_TO_N9_INT_CR4_CMD_ADDR WF_PSE_TOP_TO_N9_INT_ADDR +#define WF_PSE_TOP_TO_N9_INT_CR4_CMD_MASK \ + 0x7FFFFFFF /* CR4_CMD[30..0] */ +#define WF_PSE_TOP_TO_N9_INT_CR4_CMD_SHFT 0 + +/* +* ---FREEPG_CNT (0x820C8000 + 0x100)--- +* FREEPG_CNT[11..0] - (RO) Total page number of free +* RESERVED12[15..12] - (RO) Reserved bits +* FFA_CNT[27..16] - (RO) Free page numbers of free for all +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_FREEPG_CNT_FFA_CNT_ADDR WF_PSE_TOP_FREEPG_CNT_ADDR +#define WF_PSE_TOP_FREEPG_CNT_FFA_CNT_MASK \ + 0x0FFF0000 /* FFA_CNT[27..16] */ +#define WF_PSE_TOP_FREEPG_CNT_FFA_CNT_SHFT 16 +#define WF_PSE_TOP_FREEPG_CNT_FREEPG_CNT_ADDR \ + WF_PSE_TOP_FREEPG_CNT_ADDR +#define WF_PSE_TOP_FREEPG_CNT_FREEPG_CNT_MASK \ + 0x00000FFF /* FREEPG_CNT[11..0] */ +#define WF_PSE_TOP_FREEPG_CNT_FREEPG_CNT_SHFT 0 + +/* +* ---FREEPG_HEAD_TAIL (0x820C8000 + 0x104)--- +* FREEPG_HEAD[11..0] - (RO) Head page of free page list +* RESERVED12[15..12] - (RO) Reserved bits +* FREEPG_TAIL[27..16] - (RO) Tail page of free page list +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_ADDR \ + WF_PSE_TOP_FREEPG_HEAD_TAIL_ADDR +#define WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_MASK \ + 0x0FFF0000 /* FREEPG_TAIL[27..16] */ +#define WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_TAIL_SHFT 16 +#define WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_ADDR \ + WF_PSE_TOP_FREEPG_HEAD_TAIL_ADDR +#define WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_MASK \ + 0x00000FFF /* FREEPG_HEAD[11..0] */ +#define WF_PSE_TOP_FREEPG_HEAD_TAIL_FREEPG_HEAD_SHFT 0 + +/* +* ---GROUP_REFILL_CTRL (0x820C8000 + 0x108)--- +* GROUP_REFILL_PRI[8..0] - (RW) group refill priority control +* RESERVED9[15..9] - (RO) Reserved bits +* DIS_GROUP_REFILL[24..16] - (RW) group quota refill enable control +* RESERVED25[31..25] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_GROUP_REFILL_CTRL_DIS_GROUP_REFILL_ADDR \ + WF_PSE_TOP_GROUP_REFILL_CTRL_ADDR +#define WF_PSE_TOP_GROUP_REFILL_CTRL_DIS_GROUP_REFILL_MASK \ + 0x01FF0000 /* DIS_GROUP_REFILL[24..16] */ +#define WF_PSE_TOP_GROUP_REFILL_CTRL_DIS_GROUP_REFILL_SHFT 16 +#define WF_PSE_TOP_GROUP_REFILL_CTRL_GROUP_REFILL_PRI_ADDR \ + WF_PSE_TOP_GROUP_REFILL_CTRL_ADDR +#define WF_PSE_TOP_GROUP_REFILL_CTRL_GROUP_REFILL_PRI_MASK \ + 0x000001FF /* GROUP_REFILL_PRI[8..0] */ +#define WF_PSE_TOP_GROUP_REFILL_CTRL_GROUP_REFILL_PRI_SHFT 0 + +/* +* ---PG_HIF0_GROUP (0x820C8000 + 0x110)--- +* HIF0_MIN_QUOTA[11..0] - (RW) Min. quota of HIF 0 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* HIF0_MAX_QUOTA[27..16] - (RW) Max. quota of HIF 0 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MAX_QUOTA_ADDR \ + WF_PSE_TOP_PG_HIF0_GROUP_ADDR +#define WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MAX_QUOTA_MASK \ + 0x0FFF0000 /* HIF0_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MIN_QUOTA_ADDR \ + WF_PSE_TOP_PG_HIF0_GROUP_ADDR +#define WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MIN_QUOTA_MASK \ + 0x00000FFF /* HIF0_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_HIF0_GROUP_HIF0_MIN_QUOTA_SHFT 0 + +/* +* ---HIF0_PG_INFO (0x820C8000 + 0x114)--- +* HIF0_RSV_CNT[11..0] - (RO) Reserved pages of HIF 0 group +* RESERVED12[15..12] - (RO) Reserved bits +* HIF0_SRC_CNT[27..16] - (RO) Used pages of HIF 0 group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_HIF0_PG_INFO_HIF0_SRC_CNT_ADDR \ + WF_PSE_TOP_HIF0_PG_INFO_ADDR +#define WF_PSE_TOP_HIF0_PG_INFO_HIF0_SRC_CNT_MASK \ + 0x0FFF0000 /* HIF0_SRC_CNT[27..16] */ +#define WF_PSE_TOP_HIF0_PG_INFO_HIF0_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_HIF0_PG_INFO_HIF0_RSV_CNT_ADDR \ + WF_PSE_TOP_HIF0_PG_INFO_ADDR +#define WF_PSE_TOP_HIF0_PG_INFO_HIF0_RSV_CNT_MASK \ + 0x00000FFF /* HIF0_RSV_CNT[11..0] */ +#define WF_PSE_TOP_HIF0_PG_INFO_HIF0_RSV_CNT_SHFT 0 + +/* +* ---PG_HIF1_GROUP (0x820C8000 + 0x118)--- +* HIF1_MIN_QUOTA[11..0] - (RW) Min. quota of HIF 1 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* HIF1_MAX_QUOTA[27..16] - (RW) Max. quota of HIF 1 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_HIF1_GROUP_HIF1_MAX_QUOTA_ADDR \ + WF_PSE_TOP_PG_HIF1_GROUP_ADDR +#define WF_PSE_TOP_PG_HIF1_GROUP_HIF1_MAX_QUOTA_MASK \ + 0x0FFF0000 /* HIF1_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_HIF1_GROUP_HIF1_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_HIF1_GROUP_HIF1_MIN_QUOTA_ADDR \ + WF_PSE_TOP_PG_HIF1_GROUP_ADDR +#define WF_PSE_TOP_PG_HIF1_GROUP_HIF1_MIN_QUOTA_MASK \ + 0x00000FFF /* HIF1_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_HIF1_GROUP_HIF1_MIN_QUOTA_SHFT 0 + +/* +* ---HIF1_PG_INFO (0x820C8000 + 0x11C)--- +* HIF1_RSV_CNT[11..0] - (RO) Reserved pages of HIF 1 group +* RESERVED12[15..12] - (RO) Reserved bits +* HIF1_SRC_CNT[27..16] - (RO) Used pages of HIF 1 group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_HIF1_PG_INFO_HIF1_SRC_CNT_ADDR \ + WF_PSE_TOP_HIF1_PG_INFO_ADDR +#define WF_PSE_TOP_HIF1_PG_INFO_HIF1_SRC_CNT_MASK \ + 0x0FFF0000 /* HIF1_SRC_CNT[27..16] */ +#define WF_PSE_TOP_HIF1_PG_INFO_HIF1_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_HIF1_PG_INFO_HIF1_RSV_CNT_ADDR \ + WF_PSE_TOP_HIF1_PG_INFO_ADDR +#define WF_PSE_TOP_HIF1_PG_INFO_HIF1_RSV_CNT_MASK \ + 0x00000FFF /* HIF1_RSV_CNT[11..0] */ +#define WF_PSE_TOP_HIF1_PG_INFO_HIF1_RSV_CNT_SHFT 0 + +/* +* ---PG_CPU_GROUP (0x820C8000 + 0x150)--- +* CPU_MIN_QUOTA[11..0] - (RW) Min. quota of CPU group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* CPU_MAX_QUOTA[27..16] - (RW) Max. quota of CPU group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_CPU_GROUP_CPU_MAX_QUOTA_ADDR \ + WF_PSE_TOP_PG_CPU_GROUP_ADDR +#define WF_PSE_TOP_PG_CPU_GROUP_CPU_MAX_QUOTA_MASK \ + 0x0FFF0000 /* CPU_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_CPU_GROUP_CPU_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_CPU_GROUP_CPU_MIN_QUOTA_ADDR \ + WF_PSE_TOP_PG_CPU_GROUP_ADDR +#define WF_PSE_TOP_PG_CPU_GROUP_CPU_MIN_QUOTA_MASK \ + 0x00000FFF /* CPU_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_CPU_GROUP_CPU_MIN_QUOTA_SHFT 0 + +/* +* ---CPU_PG_INFO (0x820C8000 + 0x154)--- +* CPU_RSV_CNT[11..0] - (RO) Reserved pages of CPU group +* RESERVED12[15..12] - (RO) Reserved bits +* CPU_SRC_CNT[27..16] - (RO) Used pages of CPU group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_CPU_PG_INFO_CPU_SRC_CNT_ADDR \ + WF_PSE_TOP_CPU_PG_INFO_ADDR +#define WF_PSE_TOP_CPU_PG_INFO_CPU_SRC_CNT_MASK \ + 0x0FFF0000 /* CPU_SRC_CNT[27..16] */ +#define WF_PSE_TOP_CPU_PG_INFO_CPU_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_CPU_PG_INFO_CPU_RSV_CNT_ADDR \ + WF_PSE_TOP_CPU_PG_INFO_ADDR +#define WF_PSE_TOP_CPU_PG_INFO_CPU_RSV_CNT_MASK \ + 0x00000FFF /* CPU_RSV_CNT[11..0] */ +#define WF_PSE_TOP_CPU_PG_INFO_CPU_RSV_CNT_SHFT 0 + +/* +* ---PG_PLE_GROUP (0x820C8000 + 0x160)--- +* PLE_MIN_QUOTA[11..0] - (RW) Min. quota of PLE group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* PLE_MAX_QUOTA[27..16] - (RW) Max. quota of PLE group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_PLE_GROUP_PLE_MAX_QUOTA_ADDR \ + WF_PSE_TOP_PG_PLE_GROUP_ADDR +#define WF_PSE_TOP_PG_PLE_GROUP_PLE_MAX_QUOTA_MASK \ + 0x0FFF0000 /* PLE_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_PLE_GROUP_PLE_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_PLE_GROUP_PLE_MIN_QUOTA_ADDR \ + WF_PSE_TOP_PG_PLE_GROUP_ADDR +#define WF_PSE_TOP_PG_PLE_GROUP_PLE_MIN_QUOTA_MASK \ + 0x00000FFF /* PLE_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_PLE_GROUP_PLE_MIN_QUOTA_SHFT 0 + +/* +* ---PLE_PG_INFO (0x820C8000 + 0x164)--- +* PLE_RSV_CNT[11..0] - (RO) Reserved pages of PLE group +* RESERVED12[15..12] - (RO) Reserved bits +* PLE_SRC_CNT[27..16] - (RO) Used pages of PLE group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PLE_PG_INFO_PLE_SRC_CNT_ADDR \ + WF_PSE_TOP_PLE_PG_INFO_ADDR +#define WF_PSE_TOP_PLE_PG_INFO_PLE_SRC_CNT_MASK \ + 0x0FFF0000 /* PLE_SRC_CNT[27..16] */ +#define WF_PSE_TOP_PLE_PG_INFO_PLE_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_PLE_PG_INFO_PLE_RSV_CNT_ADDR \ + WF_PSE_TOP_PLE_PG_INFO_ADDR +#define WF_PSE_TOP_PLE_PG_INFO_PLE_RSV_CNT_MASK \ + 0x00000FFF /* PLE_RSV_CNT[11..0] */ +#define WF_PSE_TOP_PLE_PG_INFO_PLE_RSV_CNT_SHFT 0 + +/* +* ---PG_PLE1_GROUP (0x820C8000 + 0x168)--- +* PLE_MIN_QUOTA[11..0] - (RW) Min. quota of PLE group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* PLE_MAX_QUOTA[27..16] - (RW) Max. quota of PLE group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_PLE1_GROUP_PLE_MAX_QUOTA_ADDR \ + WF_PSE_TOP_PG_PLE1_GROUP_ADDR +#define WF_PSE_TOP_PG_PLE1_GROUP_PLE_MAX_QUOTA_MASK \ + 0x0FFF0000 /* PLE_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_PLE1_GROUP_PLE_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_PLE1_GROUP_PLE_MIN_QUOTA_ADDR \ + WF_PSE_TOP_PG_PLE1_GROUP_ADDR +#define WF_PSE_TOP_PG_PLE1_GROUP_PLE_MIN_QUOTA_MASK \ + 0x00000FFF /* PLE_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_PLE1_GROUP_PLE_MIN_QUOTA_SHFT 0 + +/* +* ---PLE1_PG_INFO (0x820C8000 + 0x16C)--- +* PLE_RSV_CNT[11..0] - (RO) Reserved pages of PLE group +* RESERVED12[15..12] - (RO) Reserved bits +* PLE_SRC_CNT[27..16] - (RO) Used pages of PLE group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PLE1_PG_INFO_PLE_SRC_CNT_ADDR \ + WF_PSE_TOP_PLE1_PG_INFO_ADDR +#define WF_PSE_TOP_PLE1_PG_INFO_PLE_SRC_CNT_MASK \ + 0x0FFF0000 /* PLE_SRC_CNT[27..16] */ +#define WF_PSE_TOP_PLE1_PG_INFO_PLE_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_PLE1_PG_INFO_PLE_RSV_CNT_ADDR \ + WF_PSE_TOP_PLE1_PG_INFO_ADDR +#define WF_PSE_TOP_PLE1_PG_INFO_PLE_RSV_CNT_MASK \ + 0x00000FFF /* PLE_RSV_CNT[11..0] */ +#define WF_PSE_TOP_PLE1_PG_INFO_PLE_RSV_CNT_SHFT 0 + +/* +* ---PG_LMAC0_GROUP (0x820C8000 + 0x170)--- +* LMAC0_MIN_QUOTA[11..0] - (RW) Min. quota of LMAC 0 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* LMAC0_MAX_QUOTA[27..16] - (RW) Max. quota of LMAC 0 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_LMAC0_GROUP_LMAC0_MAX_QUOTA_ADDR \ + WF_PSE_TOP_PG_LMAC0_GROUP_ADDR +#define WF_PSE_TOP_PG_LMAC0_GROUP_LMAC0_MAX_QUOTA_MASK \ + 0x0FFF0000 /* LMAC0_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_LMAC0_GROUP_LMAC0_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_LMAC0_GROUP_LMAC0_MIN_QUOTA_ADDR \ + WF_PSE_TOP_PG_LMAC0_GROUP_ADDR +#define WF_PSE_TOP_PG_LMAC0_GROUP_LMAC0_MIN_QUOTA_MASK \ + 0x00000FFF /* LMAC0_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_LMAC0_GROUP_LMAC0_MIN_QUOTA_SHFT 0 + +/* +* ---LMAC0_PG_INFO (0x820C8000 + 0x174)--- +* LMAC0_RSV_CNT[11..0] - (RO) Reserved pages of LMAC 0 group +* RESERVED12[15..12] - (RO) Reserved bits +* LMAC0_SRC_CNT[27..16] - (RO) Used pages of LMAC 0 group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_LMAC0_PG_INFO_LMAC0_SRC_CNT_ADDR \ + WF_PSE_TOP_LMAC0_PG_INFO_ADDR +#define WF_PSE_TOP_LMAC0_PG_INFO_LMAC0_SRC_CNT_MASK \ + 0x0FFF0000 /* LMAC0_SRC_CNT[27..16] */ +#define WF_PSE_TOP_LMAC0_PG_INFO_LMAC0_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_LMAC0_PG_INFO_LMAC0_RSV_CNT_ADDR \ + WF_PSE_TOP_LMAC0_PG_INFO_ADDR +#define WF_PSE_TOP_LMAC0_PG_INFO_LMAC0_RSV_CNT_MASK \ + 0x00000FFF /* LMAC0_RSV_CNT[11..0] */ +#define WF_PSE_TOP_LMAC0_PG_INFO_LMAC0_RSV_CNT_SHFT 0 + +/* +* ---PG_LMAC1_GROUP (0x820C8000 + 0x178)--- +* LMAC1_MIN_QUOTA[11..0] - (RW) Min. quota of LMAC 1 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* LMAC1_MAX_QUOTA[27..16] - (RW) Max. quota of LMAC 1 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_LMAC1_GROUP_LMAC1_MAX_QUOTA_ADDR \ + WF_PSE_TOP_PG_LMAC1_GROUP_ADDR +#define WF_PSE_TOP_PG_LMAC1_GROUP_LMAC1_MAX_QUOTA_MASK \ + 0x0FFF0000 /* LMAC1_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_LMAC1_GROUP_LMAC1_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_LMAC1_GROUP_LMAC1_MIN_QUOTA_ADDR \ + WF_PSE_TOP_PG_LMAC1_GROUP_ADDR +#define WF_PSE_TOP_PG_LMAC1_GROUP_LMAC1_MIN_QUOTA_MASK \ + 0x00000FFF /* LMAC1_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_LMAC1_GROUP_LMAC1_MIN_QUOTA_SHFT 0 + +/* +* ---LMAC1_PG_INFO (0x820C8000 + 0x17C)--- +* LMAC1_RSV_CNT[11..0] - (RO) Reserved pages of LMAC 1 group +* RESERVED12[15..12] - (RO) Reserved bits +* LMAC1_SRC_CNT[27..16] - (RO) Used pages of LMAC 1 group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_LMAC1_PG_INFO_LMAC1_SRC_CNT_ADDR \ + WF_PSE_TOP_LMAC1_PG_INFO_ADDR +#define WF_PSE_TOP_LMAC1_PG_INFO_LMAC1_SRC_CNT_MASK \ + 0x0FFF0000 /* LMAC1_SRC_CNT[27..16] */ +#define WF_PSE_TOP_LMAC1_PG_INFO_LMAC1_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_LMAC1_PG_INFO_LMAC1_RSV_CNT_ADDR \ + WF_PSE_TOP_LMAC1_PG_INFO_ADDR +#define WF_PSE_TOP_LMAC1_PG_INFO_LMAC1_RSV_CNT_MASK \ + 0x00000FFF /* LMAC1_RSV_CNT[11..0] */ +#define WF_PSE_TOP_LMAC1_PG_INFO_LMAC1_RSV_CNT_SHFT 0 + +/* +* ---PG_LMAC2_GROUP (0x820C8000 + 0x180)--- +* LMAC2_MIN_QUOTA[11..0] - (RW) Min. quota of LMAC 2 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* LMAC2_MAX_QUOTA[27..16] - (RW) Max. quota of LMAC 2 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_LMAC2_GROUP_LMAC2_MAX_QUOTA_ADDR \ + WF_PSE_TOP_PG_LMAC2_GROUP_ADDR +#define WF_PSE_TOP_PG_LMAC2_GROUP_LMAC2_MAX_QUOTA_MASK \ + 0x0FFF0000 /* LMAC2_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_LMAC2_GROUP_LMAC2_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_LMAC2_GROUP_LMAC2_MIN_QUOTA_ADDR \ + WF_PSE_TOP_PG_LMAC2_GROUP_ADDR +#define WF_PSE_TOP_PG_LMAC2_GROUP_LMAC2_MIN_QUOTA_MASK \ + 0x00000FFF /* LMAC2_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_LMAC2_GROUP_LMAC2_MIN_QUOTA_SHFT 0 + +/* +* ---LMAC2_PG_INFO (0x820C8000 + 0x184)--- +* LMAC2_RSV_CNT[11..0] - (RO) Reserved pages of LMAC 2 group +* RESERVED12[15..12] - (RO) Reserved bits +* LMAC2_SRC_CNT[27..16] - (RO) Used pages of LMAC 2 group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_LMAC2_PG_INFO_LMAC2_SRC_CNT_ADDR \ + WF_PSE_TOP_LMAC2_PG_INFO_ADDR +#define WF_PSE_TOP_LMAC2_PG_INFO_LMAC2_SRC_CNT_MASK \ + 0x0FFF0000 /* LMAC2_SRC_CNT[27..16] */ +#define WF_PSE_TOP_LMAC2_PG_INFO_LMAC2_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_LMAC2_PG_INFO_LMAC2_RSV_CNT_ADDR \ + WF_PSE_TOP_LMAC2_PG_INFO_ADDR +#define WF_PSE_TOP_LMAC2_PG_INFO_LMAC2_RSV_CNT_MASK \ + 0x00000FFF /* LMAC2_RSV_CNT[11..0] */ +#define WF_PSE_TOP_LMAC2_PG_INFO_LMAC2_RSV_CNT_SHFT 0 + +/* +* ---PG_LMAC3_GROUP (0x820C8000 + 0x188)--- +* LMAC3_MIN_QUOTA[11..0] - (RW) Min. quota of LMAC 3 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* LMAC3_MAX_QUOTA[27..16] - (RW) Max. quota of LMAC 3 group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_LMAC3_GROUP_LMAC3_MAX_QUOTA_ADDR \ + WF_PSE_TOP_PG_LMAC3_GROUP_ADDR +#define WF_PSE_TOP_PG_LMAC3_GROUP_LMAC3_MAX_QUOTA_MASK \ + 0x0FFF0000 /* LMAC3_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_LMAC3_GROUP_LMAC3_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_LMAC3_GROUP_LMAC3_MIN_QUOTA_ADDR \ + WF_PSE_TOP_PG_LMAC3_GROUP_ADDR +#define WF_PSE_TOP_PG_LMAC3_GROUP_LMAC3_MIN_QUOTA_MASK \ + 0x00000FFF /* LMAC3_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_LMAC3_GROUP_LMAC3_MIN_QUOTA_SHFT 0 + +/* +* ---LMAC3_PG_INFO (0x820C8000 + 0x18C)--- +* LMAC3_RSV_CNT[11..0] - (RO) Reserved pages of LMAC 3 group +* RESERVED12[15..12] - (RO) Reserved bits +* LMAC3_SRC_CNT[27..16] - (RO) Used pages of LMAC 3 group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_LMAC3_PG_INFO_LMAC3_SRC_CNT_ADDR \ + WF_PSE_TOP_LMAC3_PG_INFO_ADDR +#define WF_PSE_TOP_LMAC3_PG_INFO_LMAC3_SRC_CNT_MASK \ + 0x0FFF0000 /* LMAC3_SRC_CNT[27..16] */ +#define WF_PSE_TOP_LMAC3_PG_INFO_LMAC3_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_LMAC3_PG_INFO_LMAC3_RSV_CNT_ADDR \ + WF_PSE_TOP_LMAC3_PG_INFO_ADDR +#define WF_PSE_TOP_LMAC3_PG_INFO_LMAC3_RSV_CNT_MASK \ + 0x00000FFF /* LMAC3_RSV_CNT[11..0] */ +#define WF_PSE_TOP_LMAC3_PG_INFO_LMAC3_RSV_CNT_SHFT 0 + +/* +* ---PG_MDP_GROUP (0x820C8000 + 0x198)--- +* MDP_MIN_QUOTA[11..0] - (RW) Min. quota of MDP group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED12[15..12] - (RO) Reserved bits +* MDP_MAX_QUOTA[27..16] - (RW) Max. quota of MDP group +* Set up the quota before releasing PSE logic +* reset; it should not be changed after logic reset is released. +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PG_MDP_GROUP_MDP_MAX_QUOTA_ADDR \ + WF_PSE_TOP_PG_MDP_GROUP_ADDR +#define WF_PSE_TOP_PG_MDP_GROUP_MDP_MAX_QUOTA_MASK \ + 0x0FFF0000 /* MDP_MAX_QUOTA[27..16] */ +#define WF_PSE_TOP_PG_MDP_GROUP_MDP_MAX_QUOTA_SHFT 16 +#define WF_PSE_TOP_PG_MDP_GROUP_MDP_MIN_QUOTA_ADDR \ + WF_PSE_TOP_PG_MDP_GROUP_ADDR +#define WF_PSE_TOP_PG_MDP_GROUP_MDP_MIN_QUOTA_MASK \ + 0x00000FFF /* MDP_MIN_QUOTA[11..0] */ +#define WF_PSE_TOP_PG_MDP_GROUP_MDP_MIN_QUOTA_SHFT 0 + +/* +* ---MDP_PG_INFO (0x820C8000 + 0x19C)--- +* MDP_RSV_CNT[11..0] - (RO) Reserved pages of MDP group +* RESERVED12[15..12] - (RO) Reserved bits +* MDP_SRC_CNT[27..16] - (RO) Used pages of MDP group +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_MDP_PG_INFO_MDP_SRC_CNT_ADDR \ + WF_PSE_TOP_MDP_PG_INFO_ADDR +#define WF_PSE_TOP_MDP_PG_INFO_MDP_SRC_CNT_MASK \ + 0x0FFF0000 /* MDP_SRC_CNT[27..16] */ +#define WF_PSE_TOP_MDP_PG_INFO_MDP_SRC_CNT_SHFT 16 +#define WF_PSE_TOP_MDP_PG_INFO_MDP_RSV_CNT_ADDR \ + WF_PSE_TOP_MDP_PG_INFO_ADDR +#define WF_PSE_TOP_MDP_PG_INFO_MDP_RSV_CNT_MASK \ + 0x00000FFF /* MDP_RSV_CNT[11..0] */ +#define WF_PSE_TOP_MDP_PG_INFO_MDP_RSV_CNT_SHFT 0 + +/* +* ---RL_BUF_CTRL_0 (0x820C8000 + 0x1A0)--- +* RELAY_BUF_ADDR[11..0] - (RW) Read address of relay buffer +* RESERVED12[30..12] - (RO) Reserved bits +* EXECUTE[31] - (A0) Executes relay buffer read command +*/ +#define WF_PSE_TOP_RL_BUF_CTRL_0_EXECUTE_ADDR \ + WF_PSE_TOP_RL_BUF_CTRL_0_ADDR +#define WF_PSE_TOP_RL_BUF_CTRL_0_EXECUTE_MASK \ + 0x80000000 /* EXECUTE[31] */ +#define WF_PSE_TOP_RL_BUF_CTRL_0_EXECUTE_SHFT 31 +#define WF_PSE_TOP_RL_BUF_CTRL_0_RELAY_BUF_ADDR_ADDR \ + WF_PSE_TOP_RL_BUF_CTRL_0_ADDR +#define WF_PSE_TOP_RL_BUF_CTRL_0_RELAY_BUF_ADDR_MASK \ + 0x00000FFF /* RELAY_BUF_ADDR[11..0] */ +#define WF_PSE_TOP_RL_BUF_CTRL_0_RELAY_BUF_ADDR_SHFT 0 + +/* +* ---RL_BUF_CTRL_1 (0x820C8000 + 0x1A4)--- +* PAGE_NUM[8..0] - (RO) Page number of packet +* RESERVED9[13..9] - (RO) Reserved bits +* PKT_TAIL_PAGE[25..14] - (RO) Tail page of the packet with head page +* being the relay buffer address +* RESERVED26[26] - (RO) Reserved bits +* RESV_GRP_ID[30..27] - (RO) Group ID of reserved page used by FID +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_RL_BUF_CTRL_1_RESV_GRP_ID_ADDR \ + WF_PSE_TOP_RL_BUF_CTRL_1_ADDR +#define WF_PSE_TOP_RL_BUF_CTRL_1_RESV_GRP_ID_MASK \ + 0x78000000 /* RESV_GRP_ID[30..27] */ +#define WF_PSE_TOP_RL_BUF_CTRL_1_RESV_GRP_ID_SHFT 27 +#define WF_PSE_TOP_RL_BUF_CTRL_1_PKT_TAIL_PAGE_ADDR \ + WF_PSE_TOP_RL_BUF_CTRL_1_ADDR +#define WF_PSE_TOP_RL_BUF_CTRL_1_PKT_TAIL_PAGE_MASK \ + 0x03FFC000 /* PKT_TAIL_PAGE[25..14] */ +#define WF_PSE_TOP_RL_BUF_CTRL_1_PKT_TAIL_PAGE_SHFT 14 +#define WF_PSE_TOP_RL_BUF_CTRL_1_PAGE_NUM_ADDR \ + WF_PSE_TOP_RL_BUF_CTRL_1_ADDR +#define WF_PSE_TOP_RL_BUF_CTRL_1_PAGE_NUM_MASK \ + 0x000001FF /* PAGE_NUM[8..0] */ +#define WF_PSE_TOP_RL_BUF_CTRL_1_PAGE_NUM_SHFT 0 + +/* +* ---FL_QUE_CTRL_0 (0x820C8000 + 0x1B0)--- +* Q_BUF_WLANID[9..0] - (RW) Address of queue structure buffer +WLANID. +* Q_BUF_PID[11..10] - (RW) Address of queue structure buffer PID +* FL_BUFFER_ADDR[23..12] - (RW) Frame address of read previous +* frame/next frame +* Q_BUF_QID[30..24] - (RW) Address of queue structure buffer QID +* EXECUTE[31] - (A0) Executes frame link and queue structure +* buffer read command +*/ +#define WF_PSE_TOP_FL_QUE_CTRL_0_EXECUTE_ADDR \ + WF_PSE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_0_EXECUTE_MASK \ + 0x80000000 /* EXECUTE[31] */ +#define WF_PSE_TOP_FL_QUE_CTRL_0_EXECUTE_SHFT 31 +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_ADDR \ + WF_PSE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_MASK \ + 0x7F000000 /* Q_BUF_QID[30..24] */ +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_QID_SHFT 24 +#define WF_PSE_TOP_FL_QUE_CTRL_0_FL_BUFFER_ADDR_ADDR \ + WF_PSE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_0_FL_BUFFER_ADDR_MASK \ + 0x00FFF000 /* FL_BUFFER_ADDR[23..12] */ +#define WF_PSE_TOP_FL_QUE_CTRL_0_FL_BUFFER_ADDR_SHFT 12 +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_ADDR \ + WF_PSE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_MASK \ + 0x00000C00 /* Q_BUF_PID[11..10] */ +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_PID_SHFT 10 +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_WLANID_ADDR \ + WF_PSE_TOP_FL_QUE_CTRL_0_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_WLANID_MASK \ + 0x000003FF /* Q_BUF_WLANID[9..0] */ +#define WF_PSE_TOP_FL_QUE_CTRL_0_Q_BUF_WLANID_SHFT 0 + +/* +* ---FL_QUE_CTRL_1 (0x820C8000 + 0x1B4)--- +* NEXT_FID[11..0] - (RO) Next frame ID of FL_BUFFER_ADDR +* RESERVED12[15..12] - (RO) Reserved bits +* PREV_FID[27..16] - (RO) Previous frame ID of FL_BUFFER_ADDR +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_FL_QUE_CTRL_1_PREV_FID_ADDR \ + WF_PSE_TOP_FL_QUE_CTRL_1_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_1_PREV_FID_MASK \ + 0x0FFF0000 /* PREV_FID[27..16] */ +#define WF_PSE_TOP_FL_QUE_CTRL_1_PREV_FID_SHFT 16 +#define WF_PSE_TOP_FL_QUE_CTRL_1_NEXT_FID_ADDR \ + WF_PSE_TOP_FL_QUE_CTRL_1_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_1_NEXT_FID_MASK \ + 0x00000FFF /* NEXT_FID[11..0] */ +#define WF_PSE_TOP_FL_QUE_CTRL_1_NEXT_FID_SHFT 0 + +/* +* ---FL_QUE_CTRL_2 (0x820C8000 + 0x1B8)--- +* QUEUE_HEAD_FID[11..0] - (RO) Head frame ID of quest queue setting in +0x01b0[15:0] +* RESERVED12[15..12] - (RO) Reserved bits +* QUEUE_TAIL_FID[27..16] - (RO) Tail frame ID of quest queue setting +in +0x01b0[15:0] +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_ADDR \ + WF_PSE_TOP_FL_QUE_CTRL_2_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_MASK \ + 0x0FFF0000 /* QUEUE_TAIL_FID[27..16] */ +#define WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_TAIL_FID_SHFT 16 +#define WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_ADDR \ + WF_PSE_TOP_FL_QUE_CTRL_2_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_MASK \ + 0x00000FFF /* QUEUE_HEAD_FID[11..0] */ +#define WF_PSE_TOP_FL_QUE_CTRL_2_QUEUE_HEAD_FID_SHFT 0 + +/* +* ---FL_QUE_CTRL_3 (0x820C8000 + 0x1BC)--- +* QUEUE_PKT_NUM[11..0] - (RO) Total packet number of queue setting in +0x1b0[15:0] +* QUEUE_PAGE_NUM[23..12] - (RO) Total page number of queue setting in +0x1b0[15:0] +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_FL_QUE_CTRL_3_QUEUE_PAGE_NUM_ADDR \ + WF_PSE_TOP_FL_QUE_CTRL_3_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_3_QUEUE_PAGE_NUM_MASK \ + 0x00FFF000 /* QUEUE_PAGE_NUM[23..12] */ +#define WF_PSE_TOP_FL_QUE_CTRL_3_QUEUE_PAGE_NUM_SHFT 12 +#define WF_PSE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_ADDR \ + WF_PSE_TOP_FL_QUE_CTRL_3_ADDR +#define WF_PSE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_MASK \ + 0x00000FFF /* QUEUE_PKT_NUM[11..0] */ +#define WF_PSE_TOP_FL_QUE_CTRL_3_QUEUE_PKT_NUM_SHFT 0 + +/* +* ---PL_QUE_CTRL_0 (0x820C8000 + 0x1C0)--- +* NEXT_PAGE[11..0] - (RO) Next page of the PL_BUFFER_ADDR +* RESERVED12[15..12] - (RO) Reserved bits +* PL_BUFFER_ADDR[27..16] - (RW) Page address of read next page +* RESERVED28[30..28] - (RO) Reserved bits +* EXECUTE[31] - (A0) Executes page link buffer read command +*/ +#define WF_PSE_TOP_PL_QUE_CTRL_0_EXECUTE_ADDR \ + WF_PSE_TOP_PL_QUE_CTRL_0_ADDR +#define WF_PSE_TOP_PL_QUE_CTRL_0_EXECUTE_MASK \ + 0x80000000 /* EXECUTE[31] */ +#define WF_PSE_TOP_PL_QUE_CTRL_0_EXECUTE_SHFT 31 +#define WF_PSE_TOP_PL_QUE_CTRL_0_PL_BUFFER_ADDR_ADDR \ + WF_PSE_TOP_PL_QUE_CTRL_0_ADDR +#define WF_PSE_TOP_PL_QUE_CTRL_0_PL_BUFFER_ADDR_MASK \ + 0x0FFF0000 /* PL_BUFFER_ADDR[27..16] */ +#define WF_PSE_TOP_PL_QUE_CTRL_0_PL_BUFFER_ADDR_SHFT 16 +#define WF_PSE_TOP_PL_QUE_CTRL_0_NEXT_PAGE_ADDR \ + WF_PSE_TOP_PL_QUE_CTRL_0_ADDR +#define WF_PSE_TOP_PL_QUE_CTRL_0_NEXT_PAGE_MASK \ + 0x00000FFF /* NEXT_PAGE[11..0] */ +#define WF_PSE_TOP_PL_QUE_CTRL_0_NEXT_PAGE_SHFT 0 + +/* +* ---PSE_LP_CTRL (0x820C8000 + 0x1D0)--- +* RESERVED0[6..0] - (RO) Reserved bits +* PSE_LP_WAKEUP[7] - (RW) PSE Low Power Wakeup control +* PSE2HIF_PSSS_EN[8] - (RW) PSE Access HIF port control +* MCU_COALEASCE[9] - (RW) Coalease CPU ENQ and ENQ_DLY for HIF +port +* RESERVED10[31..10] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_LP_CTRL_MCU_COALEASCE_ADDR \ + WF_PSE_TOP_PSE_LP_CTRL_ADDR +#define WF_PSE_TOP_PSE_LP_CTRL_MCU_COALEASCE_MASK \ + 0x00000200 /* MCU_COALEASCE[9] */ +#define WF_PSE_TOP_PSE_LP_CTRL_MCU_COALEASCE_SHFT 9 +#define WF_PSE_TOP_PSE_LP_CTRL_PSE2HIF_PSSS_EN_ADDR \ + WF_PSE_TOP_PSE_LP_CTRL_ADDR +#define WF_PSE_TOP_PSE_LP_CTRL_PSE2HIF_PSSS_EN_MASK \ + 0x00000100 /* PSE2HIF_PSSS_EN[8] */ +#define WF_PSE_TOP_PSE_LP_CTRL_PSE2HIF_PSSS_EN_SHFT 8 +#define WF_PSE_TOP_PSE_LP_CTRL_PSE_LP_WAKEUP_ADDR \ + WF_PSE_TOP_PSE_LP_CTRL_ADDR +#define WF_PSE_TOP_PSE_LP_CTRL_PSE_LP_WAKEUP_MASK \ + 0x00000080 /* PSE_LP_WAKEUP[7] */ +#define WF_PSE_TOP_PSE_LP_CTRL_PSE_LP_WAKEUP_SHFT 7 + +/* +* ---PSE_WFDMA_BUF_CTRL (0x820C8000 + 0x1E0)--- +* WFDMA_TXS_BUF_VLD_TH[7..0] - (RW) TXS valid reserved page count +threshold +* WFDMA_TXCMD_BUF_VLD_TH[15..8] - (RW) TXCMD valid reserved page count +threshold +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_WFDMA_TXCMD_BUF_VLD_TH_ADDR \ + WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_ADDR +#define WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_WFDMA_TXCMD_BUF_VLD_TH_MASK \ + 0x0000FF00 /* WFDMA_TXCMD_BUF_VLD_TH[15..8] */ +#define WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_WFDMA_TXCMD_BUF_VLD_TH_SHFT 8 +#define WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_WFDMA_TXS_BUF_VLD_TH_ADDR \ + WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_ADDR +#define WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_WFDMA_TXS_BUF_VLD_TH_MASK \ + 0x000000FF /* WFDMA_TXS_BUF_VLD_TH[7..0] */ +#define WF_PSE_TOP_PSE_WFDMA_BUF_CTRL_WFDMA_TXS_BUF_VLD_TH_SHFT 0 + +/* +* ---PSE_CT_PRI_CTRL (0x820C8000 + 0x1EC)--- +* PSE_CT_PRI_LOW_LV[11..0] - (RW) Low trigger level of Group0 qouta +* RESERVED12[15..12] - (RO) Reserved bits +* PSE_CT_PRI_HI_LV[27..16] - (RW) High trigger level of Group0 qouta +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_CT_PRI_CTRL_PSE_CT_PRI_HI_LV_ADDR \ + WF_PSE_TOP_PSE_CT_PRI_CTRL_ADDR +#define WF_PSE_TOP_PSE_CT_PRI_CTRL_PSE_CT_PRI_HI_LV_MASK \ + 0x0FFF0000 /* PSE_CT_PRI_HI_LV[27..16] */ +#define WF_PSE_TOP_PSE_CT_PRI_CTRL_PSE_CT_PRI_HI_LV_SHFT 16 +#define WF_PSE_TOP_PSE_CT_PRI_CTRL_PSE_CT_PRI_LOW_LV_ADDR \ + WF_PSE_TOP_PSE_CT_PRI_CTRL_ADDR +#define WF_PSE_TOP_PSE_CT_PRI_CTRL_PSE_CT_PRI_LOW_LV_MASK \ + 0x00000FFF /* PSE_CT_PRI_LOW_LV[11..0] */ +#define WF_PSE_TOP_PSE_CT_PRI_CTRL_PSE_CT_PRI_LOW_LV_SHFT 0 + +/* +* ---PLE_ENQ_PKT_NUM (0x820C8000 + 0x1F0)--- +* PLE_ENQ_HIF_Q_PKT_NUM[15..0] - (RO) The packets numbers of PLE port +enqueue +* to HIF queue. +* PLE_ENQ_HIF_Q_SEL[19..16] - (RW) Select HIF queue which is PLE port +* enqueue to. +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PLE_ENQ_PKT_NUM_PLE_ENQ_HIF_Q_SEL_ADDR \ + WF_PSE_TOP_PLE_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_PLE_ENQ_PKT_NUM_PLE_ENQ_HIF_Q_SEL_MASK \ + 0x000F0000 /* PLE_ENQ_HIF_Q_SEL[19..16] */ +#define WF_PSE_TOP_PLE_ENQ_PKT_NUM_PLE_ENQ_HIF_Q_SEL_SHFT 16 +#define WF_PSE_TOP_PLE_ENQ_PKT_NUM_PLE_ENQ_HIF_Q_PKT_NUM_ADDR \ + WF_PSE_TOP_PLE_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_PLE_ENQ_PKT_NUM_PLE_ENQ_HIF_Q_PKT_NUM_MASK \ + 0x0000FFFF /* PLE_ENQ_HIF_Q_PKT_NUM[15..0] */ +#define WF_PSE_TOP_PLE_ENQ_PKT_NUM_PLE_ENQ_HIF_Q_PKT_NUM_SHFT 0 + +/* +* ---CPU_ENQ_PKT_NUM (0x820C8000 + 0x1F4)--- +* CPU_ENQ_HIF_Q_PKT_NUM[15..0] - (RO) The packets numbers of CPU port +enqueue +* to HIF queue. +* CPU_ENQ_HIF_Q_SEL[19..16] - (RW) Select HIF queue which is CPU port +* enqueue to. +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_HIF_Q_SEL_ADDR \ + WF_PSE_TOP_CPU_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_HIF_Q_SEL_MASK \ + 0x000F0000 /* CPU_ENQ_HIF_Q_SEL[19..16] */ +#define WF_PSE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_HIF_Q_SEL_SHFT 16 +#define WF_PSE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_HIF_Q_PKT_NUM_ADDR \ + WF_PSE_TOP_CPU_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_HIF_Q_PKT_NUM_MASK \ + 0x0000FFFF /* CPU_ENQ_HIF_Q_PKT_NUM[15..0] */ +#define WF_PSE_TOP_CPU_ENQ_PKT_NUM_CPU_ENQ_HIF_Q_PKT_NUM_SHFT 0 + +/* +* ---LMAC_ENQ_PKT_NUM (0x820C8000 + 0x1F8)--- +* LMAC_ENQ_HIF_Q_PKT_NUM[15..0] - (RO) The packets numbers of LMAC +port +* enqueue to HIF queue. +* LMAC_ENQ_HIF_Q_SEL[19..16] - (RW) Select HIF queue which is LMAC +port +* enqueue to. +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_LMAC_ENQ_PKT_NUM_LMAC_ENQ_HIF_Q_SEL_ADDR \ + WF_PSE_TOP_LMAC_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_LMAC_ENQ_PKT_NUM_LMAC_ENQ_HIF_Q_SEL_MASK \ + 0x000F0000 /* LMAC_ENQ_HIF_Q_SEL[19..16] */ +#define WF_PSE_TOP_LMAC_ENQ_PKT_NUM_LMAC_ENQ_HIF_Q_SEL_SHFT 16 +#define WF_PSE_TOP_LMAC_ENQ_PKT_NUM_LMAC_ENQ_HIF_Q_PKT_NUM_ADDR \ + WF_PSE_TOP_LMAC_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_LMAC_ENQ_PKT_NUM_LMAC_ENQ_HIF_Q_PKT_NUM_MASK \ + 0x0000FFFF /* LMAC_ENQ_HIF_Q_PKT_NUM[15..0] */ +#define WF_PSE_TOP_LMAC_ENQ_PKT_NUM_LMAC_ENQ_HIF_Q_PKT_NUM_SHFT 0 + +/* +* ---HIF_ENQ_PKT_NUM (0x820C8000 + 0x1FC)--- +* HIF_ENQ_MDP[15..0] - (RO) The packets numbers of HIF port enqueue +* to MDP TX queue. +* HIF_ENQ_CPU[31..16] - (RO) The packets numbers of HIF port enqueue +* to CPU queue +*/ +#define WF_PSE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_CPU_ADDR \ + WF_PSE_TOP_HIF_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_CPU_MASK \ + 0xFFFF0000 /* HIF_ENQ_CPU[31..16] */ +#define WF_PSE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_CPU_SHFT 16 +#define WF_PSE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_MDP_ADDR \ + WF_PSE_TOP_HIF_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_MDP_MASK \ + 0x0000FFFF /* HIF_ENQ_MDP[15..0] */ +#define WF_PSE_TOP_HIF_ENQ_PKT_NUM_HIF_ENQ_MDP_SHFT 0 + +/* +* ---MDP_ENQ_PKT_NUM (0x820C8000 + 0x200)--- +* MDP_ENQ_HIF_Q_PKT_NUM[15..0] - (RO) The packets numbers of MDP port +enqueue +* to HIF queue. +* MDP_ENQ_HIF_Q_SEL[31..16] - (RW) Select HIF queue which is MDP port +* enqueue to. +*/ +#define WF_PSE_TOP_MDP_ENQ_PKT_NUM_MDP_ENQ_HIF_Q_SEL_ADDR \ + WF_PSE_TOP_MDP_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_MDP_ENQ_PKT_NUM_MDP_ENQ_HIF_Q_SEL_MASK \ + 0xFFFF0000 /* MDP_ENQ_HIF_Q_SEL[31..16] */ +#define WF_PSE_TOP_MDP_ENQ_PKT_NUM_MDP_ENQ_HIF_Q_SEL_SHFT 16 +#define WF_PSE_TOP_MDP_ENQ_PKT_NUM_MDP_ENQ_HIF_Q_PKT_NUM_ADDR \ + WF_PSE_TOP_MDP_ENQ_PKT_NUM_ADDR +#define WF_PSE_TOP_MDP_ENQ_PKT_NUM_MDP_ENQ_HIF_Q_PKT_NUM_MASK \ + 0x0000FFFF /* MDP_ENQ_HIF_Q_PKT_NUM[15..0] */ +#define WF_PSE_TOP_MDP_ENQ_PKT_NUM_MDP_ENQ_HIF_Q_PKT_NUM_SHFT 0 + +/* +* ---TIMEOUT_CTRL (0x820C8000 + 0x244)--- +* FL_WD_TO_CTRL[7..0] - (RW) FL watch dog timeput +* RESERVED8[15..8] - (RO) Reserved bits +* APB_WD_TO_CTRL[23..16] - (RW) APB pready watch dog timeout control +register. +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_TIMEOUT_CTRL_APB_WD_TO_CTRL_ADDR \ + WF_PSE_TOP_TIMEOUT_CTRL_ADDR +#define WF_PSE_TOP_TIMEOUT_CTRL_APB_WD_TO_CTRL_MASK \ + 0x00FF0000 /* APB_WD_TO_CTRL[23..16] */ +#define WF_PSE_TOP_TIMEOUT_CTRL_APB_WD_TO_CTRL_SHFT 16 +#define WF_PSE_TOP_TIMEOUT_CTRL_FL_WD_TO_CTRL_ADDR \ + WF_PSE_TOP_TIMEOUT_CTRL_ADDR +#define WF_PSE_TOP_TIMEOUT_CTRL_FL_WD_TO_CTRL_MASK \ + 0x000000FF /* FL_WD_TO_CTRL[7..0] */ +#define WF_PSE_TOP_TIMEOUT_CTRL_FL_WD_TO_CTRL_SHFT 0 + +/* +* ---FSM_IDLE_WD_CTRL (0x820C8000 + 0x24C)--- +* FL_IDLE_WD_TO_TH[7..0] - (RW) Watchdog timeout threshold for frame +* link FSM not returning to IDLE +* PL_IDLE_WD_TO_TH[15..8] - (RW) Watchdog timeout threshold for page +link +* FSM not returning to IDLE +* PORT_IDLE_WD_TO_TH[23..16] - (RW) Watchdog timeout threshold for +* page link +* Port Link not returning to IDLE +* (Including HIF/CPU/LMAC port) +* MACTX_IDLE_WD_TO_TH[31..24] - (RW) Watchdog timeout threshold for +* port oper +* MACTX not returning to IDLE +*/ +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_MACTX_IDLE_WD_TO_TH_ADDR \ + WF_PSE_TOP_FSM_IDLE_WD_CTRL_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_MACTX_IDLE_WD_TO_TH_MASK \ + 0xFF000000 /* MACTX_IDLE_WD_TO_TH[31..24] */ +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_MACTX_IDLE_WD_TO_TH_SHFT 24 +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_PORT_IDLE_WD_TO_TH_ADDR \ + WF_PSE_TOP_FSM_IDLE_WD_CTRL_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_PORT_IDLE_WD_TO_TH_MASK \ + 0x00FF0000 /* PORT_IDLE_WD_TO_TH[23..16] */ +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_PORT_IDLE_WD_TO_TH_SHFT 16 +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_PL_IDLE_WD_TO_TH_ADDR \ + WF_PSE_TOP_FSM_IDLE_WD_CTRL_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_PL_IDLE_WD_TO_TH_MASK \ + 0x0000FF00 /* PL_IDLE_WD_TO_TH[15..8] */ +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_PL_IDLE_WD_TO_TH_SHFT 8 +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_FL_IDLE_WD_TO_TH_ADDR \ + WF_PSE_TOP_FSM_IDLE_WD_CTRL_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_FL_IDLE_WD_TO_TH_MASK \ + 0x000000FF /* FL_IDLE_WD_TO_TH[7..0] */ +#define WF_PSE_TOP_FSM_IDLE_WD_CTRL_FL_IDLE_WD_TO_TH_SHFT 0 + +/* +* ---FSM_IDLE_WD_EN (0x820C8000 + 0x250)--- +* EN_HIF_PORT_IDLE_WD_TO[0] - (RW) Enables watchdog for HIF port oper +FSM +* not returning to IDLE +* EN_CPU_PORT_IDLE_WD_TO[1] - (RW) Enables watchdog for CPU port oper +FSM +* not returning to IDLE +* EN_LMAC_PORT_IDLE_WD_TO[2] - (RW) Enables watchdog for LMAC port +* oper FSM +* not returning to IDLE +* EN_MDP_IDLE_WD_TO[3] - (RW) Enables watchdog for MDP port oper FSM +* not returning to IDLE +* EN_SEC_IDLE_WD_TO[4] - (RW) Enables watchdog for SEC port oper FSM +* not returning to IDLE +* EN_PLE_IDLE_WD_TO[5] - (RW) Enables watchdog for PLE port oper FSM +* not returning to IDLE +* EN_AMSDU_IDLE_WD_TO[6] - (RW) Enables watchdog for AMSDU port oper +FSM +* not returning to IDLE +* RESERVED7[7] - (RO) Reserved bits +* EN_FL_IDLE_WD_TO[8] - (RW) Enables watchdog for frame link FSM not +* returning to IDLE +* EN_PL_IDLE_WD_TO[9] - (RW) Enables watchdog for page link FSM not +* returning to IDLE +* RESERVED10[31..10] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_PL_IDLE_WD_TO_ADDR \ + WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_PL_IDLE_WD_TO_MASK \ + 0x00000200 /* EN_PL_IDLE_WD_TO[9] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_PL_IDLE_WD_TO_SHFT 9 +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_FL_IDLE_WD_TO_ADDR \ + WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_FL_IDLE_WD_TO_MASK \ + 0x00000100 /* EN_FL_IDLE_WD_TO[8] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_FL_IDLE_WD_TO_SHFT 8 +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_AMSDU_IDLE_WD_TO_ADDR \ + WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_AMSDU_IDLE_WD_TO_MASK \ + 0x00000040 /* EN_AMSDU_IDLE_WD_TO[6] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_AMSDU_IDLE_WD_TO_SHFT 6 +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_PLE_IDLE_WD_TO_ADDR \ + WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_PLE_IDLE_WD_TO_MASK \ + 0x00000020 /* EN_PLE_IDLE_WD_TO[5] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_PLE_IDLE_WD_TO_SHFT 5 +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_SEC_IDLE_WD_TO_ADDR \ + WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_SEC_IDLE_WD_TO_MASK \ + 0x00000010 /* EN_SEC_IDLE_WD_TO[4] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_SEC_IDLE_WD_TO_SHFT 4 +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_MDP_IDLE_WD_TO_ADDR \ + WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_MDP_IDLE_WD_TO_MASK \ + 0x00000008 /* EN_MDP_IDLE_WD_TO[3] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_MDP_IDLE_WD_TO_SHFT 3 +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_LMAC_PORT_IDLE_WD_TO_ADDR \ + WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_LMAC_PORT_IDLE_WD_TO_MASK \ + 0x00000004 /* EN_LMAC_PORT_IDLE_WD_TO[2] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_LMAC_PORT_IDLE_WD_TO_SHFT 2 +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_CPU_PORT_IDLE_WD_TO_ADDR \ + WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_CPU_PORT_IDLE_WD_TO_MASK \ + 0x00000002 /* EN_CPU_PORT_IDLE_WD_TO[1] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_CPU_PORT_IDLE_WD_TO_SHFT 1 +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_HIF_PORT_IDLE_WD_TO_ADDR \ + WF_PSE_TOP_FSM_IDLE_WD_EN_ADDR +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_HIF_PORT_IDLE_WD_TO_MASK \ + 0x00000001 /* EN_HIF_PORT_IDLE_WD_TO[0] */ +#define WF_PSE_TOP_FSM_IDLE_WD_EN_EN_HIF_PORT_IDLE_WD_TO_SHFT 0 + +/* +* ---PSE_INTER_ERR_FLAG (0x820C8000 + 0x280)--- +* DEQ_EMPTY_QUEUE[0] - (RO) DEQueue Empty Error Flag +* APB_WD_TO[1] - (RO) APB Write Data Timeout Error Flag +* FL_CTRL_WD_TO[2] - (RO) FL Write Data Timeout Error Flag +* RESERVED3[31..3] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_FL_CTRL_WD_TO_ADDR \ + WF_PSE_TOP_PSE_INTER_ERR_FLAG_ADDR +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_FL_CTRL_WD_TO_MASK \ + 0x00000004 /* FL_CTRL_WD_TO[2] */ +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_FL_CTRL_WD_TO_SHFT 2 +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_APB_WD_TO_ADDR \ + WF_PSE_TOP_PSE_INTER_ERR_FLAG_ADDR +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_APB_WD_TO_MASK \ + 0x00000002 /* APB_WD_TO[1] */ +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_APB_WD_TO_SHFT 1 +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_DEQ_EMPTY_QUEUE_ADDR \ + WF_PSE_TOP_PSE_INTER_ERR_FLAG_ADDR +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_DEQ_EMPTY_QUEUE_MASK \ + 0x00000001 /* DEQ_EMPTY_QUEUE[0] */ +#define WF_PSE_TOP_PSE_INTER_ERR_FLAG_DEQ_EMPTY_QUEUE_SHFT 0 + +/* +* ---PSE_SER_CTRL (0x820C8000 + 0x2a0)--- +* HIF_SER_PAUSE_ALLOCATE[0] - (RW) System Error Recover function for +Pause +* HIFBuffer Allocation +* CPU_SER_PAUSE_ALLOCATE[1] - (RW) System Error Recover function for +Pause +* CPU Buffer Allocation +* WF_SER_PAUSE_ALLOCATE[2] - (RW) System Error Recover function for +Pause +* WF Buffer Allocation +* MDP_SER_PAUSE_ALLOCATE[3] - (RW) System Error Recover function for +Pause +* MDP Buffer Allocation +* SEC_SER_PAUSE_ALLOCATE[4] - (RW) System Error Recover function for +Pause +* SEC Buffer Allocation +* PLE_SER_PAUSE_ALLOCATE[5] - (RW) System Error Recover function for +Pause +* PLE Buffer Allocation +* RESERVED6[7..6] - (RO) Reserved bits +* HIF_SER_PAUSE_DATA[8] - (RW) System Error Recover function for Pause +* HIF DATA opeartion. +* CPU_SER_PAUSE_DATA[9] - (RW) System Error Recover function for Pause +* CPU DATA opeartion. +* WF_SER_PAUSE_DATA[10] - (RW) System Error Recover function for Pause +* WF DATA opeartion. +* MDP_SER_PAUSE_DATA[11] - (RW) System Error Recover function for +Pause +* MDP DATA opeartion. +* SEC_SER_PAUSE_DATA[12] - (RW) System Error Recover function for +Pause +* SEC DATA opeartion. +* PLE_SER_PAUSE_DATA[13] - (RW) System Error Recover function for +Pause +* PLE DATA opeartion. +* RESERVED14[15..14] - (RO) Reserved bits +* HIF_SER_PAUSE_QUEUE[16] - (RW) System Error Recover function for +Pause +* HIF Queue opeartion. +* CPU_SER_PAUSE_QUEUE[17] - (RW) System Error Recover function for +Pause +* CPU Queue opeartion. +* WF_SER_PAUSE_QUEUE[18] - (RW) System Error Recover function for +Pause +* WF Queue opeartion. +* MDP_SER_PAUSE_QUEUE[19] - (RW) System Error Recover function for +Pause +* MDP Queue opeartion. +* SEC_SER_PAUSE_QUEUE[20] - (RW) System Error Recover function for +Pause +* SEC Queue opeartion. +* PLE_SER_PAUSE_QUEUE[21] - (RW) System Error Recover function for +Pause +* PLE Queue opeartion. +* RESERVED22[31..22] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_QUEUE_ADDR \ + WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_QUEUE_MASK \ + 0x00200000 /* PLE_SER_PAUSE_QUEUE[21] */ +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_QUEUE_SHFT 21 +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_QUEUE_ADDR \ + WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_QUEUE_MASK \ + 0x00100000 /* SEC_SER_PAUSE_QUEUE[20] */ +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_QUEUE_SHFT 20 +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_QUEUE_ADDR \ + WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_QUEUE_MASK \ + 0x00080000 /* MDP_SER_PAUSE_QUEUE[19] */ +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_QUEUE_SHFT 19 +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_QUEUE_ADDR \ + WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_QUEUE_MASK \ + 0x00040000 /* WF_SER_PAUSE_QUEUE[18] */ +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_QUEUE_SHFT 18 +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_QUEUE_ADDR \ + WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_QUEUE_MASK \ + 0x00020000 /* CPU_SER_PAUSE_QUEUE[17] */ +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_QUEUE_SHFT 17 +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_QUEUE_ADDR \ + WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_QUEUE_MASK \ + 0x00010000 /* HIF_SER_PAUSE_QUEUE[16] */ +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_QUEUE_SHFT 16 +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_DATA_ADDR \ + WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_DATA_MASK \ + 0x00002000 /* PLE_SER_PAUSE_DATA[13] */ +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_DATA_SHFT 13 +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_DATA_ADDR \ + WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_DATA_MASK \ + 0x00001000 /* SEC_SER_PAUSE_DATA[12] */ +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_DATA_SHFT 12 +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_DATA_ADDR \ + WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_DATA_MASK \ + 0x00000800 /* MDP_SER_PAUSE_DATA[11] */ +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_DATA_SHFT 11 +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_DATA_ADDR \ + WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_DATA_MASK \ + 0x00000400 /* WF_SER_PAUSE_DATA[10] */ +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_DATA_SHFT 10 +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_DATA_ADDR \ + WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_DATA_MASK \ + 0x00000200 /* CPU_SER_PAUSE_DATA[9] */ +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_DATA_SHFT 9 +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_DATA_ADDR \ + WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_DATA_MASK \ + 0x00000100 /* HIF_SER_PAUSE_DATA[8] */ +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_DATA_SHFT 8 +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_ALLOCATE_ADDR \ + WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_ALLOCATE_MASK \ + 0x00000020 /* PLE_SER_PAUSE_ALLOCATE[5] */ +#define WF_PSE_TOP_PSE_SER_CTRL_PLE_SER_PAUSE_ALLOCATE_SHFT 5 +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_ALLOCATE_ADDR \ + WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_ALLOCATE_MASK \ + 0x00000010 /* SEC_SER_PAUSE_ALLOCATE[4] */ +#define WF_PSE_TOP_PSE_SER_CTRL_SEC_SER_PAUSE_ALLOCATE_SHFT 4 +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_ALLOCATE_ADDR \ + WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_ALLOCATE_MASK \ + 0x00000008 /* MDP_SER_PAUSE_ALLOCATE[3] */ +#define WF_PSE_TOP_PSE_SER_CTRL_MDP_SER_PAUSE_ALLOCATE_SHFT 3 +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_ALLOCATE_ADDR \ + WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_ALLOCATE_MASK \ + 0x00000004 /* WF_SER_PAUSE_ALLOCATE[2] */ +#define WF_PSE_TOP_PSE_SER_CTRL_WF_SER_PAUSE_ALLOCATE_SHFT 2 +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_ALLOCATE_ADDR \ + WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_ALLOCATE_MASK \ + 0x00000002 /* CPU_SER_PAUSE_ALLOCATE[1] */ +#define WF_PSE_TOP_PSE_SER_CTRL_CPU_SER_PAUSE_ALLOCATE_SHFT 1 +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_ALLOCATE_ADDR \ + WF_PSE_TOP_PSE_SER_CTRL_ADDR +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_ALLOCATE_MASK \ + 0x00000001 /* HIF_SER_PAUSE_ALLOCATE[0] */ +#define WF_PSE_TOP_PSE_SER_CTRL_HIF_SER_PAUSE_ALLOCATE_SHFT 0 + +/* +* ---PSE_MBIST_RP_FUSE (0x820C8000 + 0x2b0)--- +* WF_PSE_MBIST_RP_FAIL[3..0] - (RO) MBIST Repair FAIL report +* RESERVED4[7..4] - (RO) Reserved bits +* WF_PSE_MBIST_RP_OK[11..8] - (RO) MBIST Repair OK report +* RESERVED12[14..12] - (RO) Reserved bits +* REG_FUSE_SEL[15] - (RW) MBIST FUSE setting +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_REG_FUSE_SEL_ADDR \ + WF_PSE_TOP_PSE_MBIST_RP_FUSE_ADDR +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_REG_FUSE_SEL_MASK \ + 0x00008000 /* REG_FUSE_SEL[15] */ +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_REG_FUSE_SEL_SHFT 15 +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_WF_PSE_MBIST_RP_OK_ADDR \ + WF_PSE_TOP_PSE_MBIST_RP_FUSE_ADDR +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_WF_PSE_MBIST_RP_OK_MASK \ + 0x00000F00 /* WF_PSE_MBIST_RP_OK[11..8] */ +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_WF_PSE_MBIST_RP_OK_SHFT 8 +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_WF_PSE_MBIST_RP_FAIL_ADDR \ + WF_PSE_TOP_PSE_MBIST_RP_FUSE_ADDR +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_WF_PSE_MBIST_RP_FAIL_MASK \ + 0x0000000F /* WF_PSE_MBIST_RP_FAIL[3..0] */ +#define WF_PSE_TOP_PSE_MBIST_RP_FUSE_WF_PSE_MBIST_RP_FAIL_SHFT 0 + +/* +* ---PSE_MBIST_BSEL (0x820C8000 + 0x2b4)--- +* WF_PSE_MBIST_BSEL[15..0] - (RW) Memory MBIST BSEL control +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_MBIST_BSEL_WF_PSE_MBIST_BSEL_ADDR \ + WF_PSE_TOP_PSE_MBIST_BSEL_ADDR +#define WF_PSE_TOP_PSE_MBIST_BSEL_WF_PSE_MBIST_BSEL_MASK \ + 0x0000FFFF /* WF_PSE_MBIST_BSEL[15..0] */ +#define WF_PSE_TOP_PSE_MBIST_BSEL_WF_PSE_MBIST_BSEL_SHFT 0 + +/* +* ---PSE_MBIST_RP_FUSE_1 (0x820C8000 + 0x2b8)--- +* WF_UMAC_TOP_MBIST_PREFUSE_0[15..0] - (RW) MBIST PRE-FUSE setting +* WF_UMAC_TOP_MBIST_PREFUSE_D_0[31..16] - (RO) MBIST PRE-FUSE result +*/ +#define \ +WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_WF_UMAC_TOP_MBIST_PREFUSE_D_0_ADDR \ + WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_ADDR +#define \ +WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_WF_UMAC_TOP_MBIST_PREFUSE_D_0_MASK \ + 0xFFFF0000 /* WF_UMAC_TOP_MBIST_PREFUSE_D_0[31..16] */ +#define \ +WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_WF_UMAC_TOP_MBIST_PREFUSE_D_0_SHFT \ + 16 +#define \ +WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_WF_UMAC_TOP_MBIST_PREFUSE_0_ADDR \ + WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_ADDR +#define \ +WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_WF_UMAC_TOP_MBIST_PREFUSE_0_MASK \ + 0x0000FFFF /* WF_UMAC_TOP_MBIST_PREFUSE_0[15..0] */ +#define \ +WF_PSE_TOP_PSE_MBIST_RP_FUSE_1_WF_UMAC_TOP_MBIST_PREFUSE_0_SHFT \ + 0 + +/* +* ---SRAM_MBIST_BACKGROUND (0x820C8000 + 0x2d0)--- +* MBIST_BACKGROUND[15..0] - (RW) Background setting for PSE SRAM MBIST +circuit +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_SRAM_MBIST_BACKGROUND_MBIST_BACKGROUND_ADDR \ + WF_PSE_TOP_SRAM_MBIST_BACKGROUND_ADDR +#define WF_PSE_TOP_SRAM_MBIST_BACKGROUND_MBIST_BACKGROUND_MASK \ + 0x0000FFFF /* MBIST_BACKGROUND[15..0] */ +#define WF_PSE_TOP_SRAM_MBIST_BACKGROUND_MBIST_BACKGROUND_SHFT 0 + +/* +* ---PSE_MISC_FUNC_CTRL (0x820C8000 + 0x2d4)--- +* RESERVED0[7..0] - (RO) Reserved bits +* PSE_QUEUE_ACK_MODE[8] - (RW) Queue ACK mode control +* RESERVED9[29..9] - (RO) Reserved bits +* DIS_BYPASS_INVALID_FID[30] - (RW) Bypass invalid FID control +* DIS_BLOCK_MODE[31] - (RW) Block Mode Control +*/ +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_DIS_BLOCK_MODE_ADDR \ + WF_PSE_TOP_PSE_MISC_FUNC_CTRL_ADDR +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_DIS_BLOCK_MODE_MASK \ + 0x80000000 /* DIS_BLOCK_MODE[31] */ +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_DIS_BLOCK_MODE_SHFT 31 +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_DIS_BYPASS_INVALID_FID_ADDR \ + WF_PSE_TOP_PSE_MISC_FUNC_CTRL_ADDR +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_DIS_BYPASS_INVALID_FID_MASK \ + 0x40000000 /* DIS_BYPASS_INVALID_FID[30] */ +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_DIS_BYPASS_INVALID_FID_SHFT 30 +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_PSE_QUEUE_ACK_MODE_ADDR \ + WF_PSE_TOP_PSE_MISC_FUNC_CTRL_ADDR +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_PSE_QUEUE_ACK_MODE_MASK \ + 0x00000100 /* PSE_QUEUE_ACK_MODE[8] */ +#define WF_PSE_TOP_PSE_MISC_FUNC_CTRL_PSE_QUEUE_ACK_MODE_SHFT 8 + +/* +* ---SRAM_MBIST_DONE (0x820C8000 + 0x2d8)--- +* MBIST_DONE[0] - (RO) Working status of PSE SRAM MBIST circuit +* RESERVED1[31..1] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_SRAM_MBIST_DONE_MBIST_DONE_ADDR \ + WF_PSE_TOP_SRAM_MBIST_DONE_ADDR +#define WF_PSE_TOP_SRAM_MBIST_DONE_MBIST_DONE_MASK \ + 0x00000001 /* MBIST_DONE[0] */ +#define WF_PSE_TOP_SRAM_MBIST_DONE_MBIST_DONE_SHFT 0 + +/* +* ---SRAM_MBIST_FAIL (0x820C8000 + 0x2dc)--- +* FORDLINK_SRAM_MBIST_FAIL[0] - (RO) MBIST check result of forward +* link SRAM +* BACKLINK_SRAM_MBIST_FAIL[1] - (RO) MBIST check result of backward +* link SRAM +* PAGELINK_SRAM_MBIST_FAIL[2] - (RO) MBIST check result of PAGELINK +SRAM +* RLINFO_SRAM_MBIST_FAIL[3] - (RO) MBIST check result of RLINFO SRAM +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_SRAM_MBIST_FAIL_RLINFO_SRAM_MBIST_FAIL_ADDR \ + WF_PSE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_FAIL_RLINFO_SRAM_MBIST_FAIL_MASK \ + 0x00000008 /* RLINFO_SRAM_MBIST_FAIL[3] */ +#define WF_PSE_TOP_SRAM_MBIST_FAIL_RLINFO_SRAM_MBIST_FAIL_SHFT 3 +#define WF_PSE_TOP_SRAM_MBIST_FAIL_PAGELINK_SRAM_MBIST_FAIL_ADDR \ + WF_PSE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_FAIL_PAGELINK_SRAM_MBIST_FAIL_MASK \ + 0x00000004 /* PAGELINK_SRAM_MBIST_FAIL[2] */ +#define WF_PSE_TOP_SRAM_MBIST_FAIL_PAGELINK_SRAM_MBIST_FAIL_SHFT 2 +#define WF_PSE_TOP_SRAM_MBIST_FAIL_BACKLINK_SRAM_MBIST_FAIL_ADDR \ + WF_PSE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_FAIL_BACKLINK_SRAM_MBIST_FAIL_MASK \ + 0x00000002 /* BACKLINK_SRAM_MBIST_FAIL[1] */ +#define WF_PSE_TOP_SRAM_MBIST_FAIL_BACKLINK_SRAM_MBIST_FAIL_SHFT 1 +#define WF_PSE_TOP_SRAM_MBIST_FAIL_FORDLINK_SRAM_MBIST_FAIL_ADDR \ + WF_PSE_TOP_SRAM_MBIST_FAIL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_FAIL_FORDLINK_SRAM_MBIST_FAIL_MASK \ + 0x00000001 /* FORDLINK_SRAM_MBIST_FAIL[0] */ +#define WF_PSE_TOP_SRAM_MBIST_FAIL_FORDLINK_SRAM_MBIST_FAIL_SHFT 0 + +/* +* ---SRAM_MBIST_CTRL (0x820C8000 + 0x2e0)--- +* MBIST_MODE[0] - (RW) Control register for mbist_mode of MBIST +* RESERVED1[3..1] - (RO) Reserved bits +* MBIST_HOLDB[4] - (RW) Control register for mbist_holdb of +MBIST +* RESERVED5[7..5] - (RO) Reserved bits +* MBIST_DEBUG[8] - (RW) Control register for mbist_debug of +MBIST +* MBIST_RPRST_B[9] - (RW) MBIST Repair function Enable +* MBIST_USE_DEFAULT_DELSEL[10] - (RW) MBIST delay select control +* RESERVED11[15..11] - (RO) Reserved bits +* MBIST_DIAG_SEL[19..16] - (RW) Selection register for +mbist_diag_scan_out +* RESERVED20[23..20] - (RO) Reserved bits +* MBIST_SLEEP_TEST[24] - (RW) Control register for sleep_test of MBIST +* MBIST_SLEEP_INV[25] - (RW) Control register for sleep_inv of MBIST +* MBIST_SLEEP_W[26] - (RW) Control register for sleep_w of MBIST +* MBIST_SLEEP_R[27] - (RW) Control register for sleep_r of MBIST +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_R_ADDR \ + WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_R_MASK \ + 0x08000000 /* MBIST_SLEEP_R[27] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_R_SHFT 27 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_W_ADDR \ + WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_W_MASK \ + 0x04000000 /* MBIST_SLEEP_W[26] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_W_SHFT 26 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_INV_ADDR \ + WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_INV_MASK \ + 0x02000000 /* MBIST_SLEEP_INV[25] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_INV_SHFT 25 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_TEST_ADDR \ + WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_TEST_MASK \ + 0x01000000 /* MBIST_SLEEP_TEST[24] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_SLEEP_TEST_SHFT 24 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_DIAG_SEL_ADDR \ + WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_DIAG_SEL_MASK \ + 0x000F0000 /* MBIST_DIAG_SEL[19..16] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_DIAG_SEL_SHFT 16 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_USE_DEFAULT_DELSEL_ADDR \ + WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_USE_DEFAULT_DELSEL_MASK \ + 0x00000400 /* MBIST_USE_DEFAULT_DELSEL[10] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_USE_DEFAULT_DELSEL_SHFT 10 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_RPRST_B_ADDR \ + WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_RPRST_B_MASK \ + 0x00000200 /* MBIST_RPRST_B[9] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_RPRST_B_SHFT 9 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_DEBUG_ADDR \ + WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_DEBUG_MASK \ + 0x00000100 /* MBIST_DEBUG[8] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_DEBUG_SHFT 8 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_HOLDB_ADDR \ + WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_HOLDB_MASK \ + 0x00000010 /* MBIST_HOLDB[4] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_HOLDB_SHFT 4 +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_MODE_ADDR \ + WF_PSE_TOP_SRAM_MBIST_CTRL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_MODE_MASK \ + 0x00000001 /* MBIST_MODE[0] */ +#define WF_PSE_TOP_SRAM_MBIST_CTRL_MBIST_MODE_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL (0x820C8000 + 0x2e4)--- +* MBIST_DELSEL0_2[31..0] - (RW) Control register of delsel for PL SRAM +*/ +#define WF_PSE_TOP_SRAM_MBIST_DELSEL_MBIST_DELSEL0_2_ADDR \ + WF_PSE_TOP_SRAM_MBIST_DELSEL_ADDR +#define WF_PSE_TOP_SRAM_MBIST_DELSEL_MBIST_DELSEL0_2_MASK \ + 0xFFFFFFFF /* MBIST_DELSEL0_2[31..0] */ +#define WF_PSE_TOP_SRAM_MBIST_DELSEL_MBIST_DELSEL0_2_SHFT 0 + +/* +* ---SRAM_AWT_HDEN_CTRL (0x820C8000 + 0x2e8)--- +* FL_TBL_AWT1[0] - (RW) Memory AWT Control for FL_TBL1 +* FL_TBL_AWT2[1] - (RW) Memory AWT Control for FL_TBL2 +* PL_TBL_AWT[2] - (RW) Memory AWT Control for PL +* RLINFO_MEM_AWT[3] - (RW) Memory AWT Control for RL +* RESERVED4[15..4] - (RO) Reserved bits +* FL_TBL_HDEN1[16] - (RW) Memory HDEN Control for FL_TBL1 +* FL_TBL_HDEN2[17] - (RW) Memory HDEN Control for FL_TBL2 +* PL_TBL_HDEN[18] - (RW) Memory HDEN Control for PL +* RLINFO_MEM_HDEN[19] - (RW) Memory HDEN Control for RL +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_RLINFO_MEM_HDEN_ADDR \ + WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_RLINFO_MEM_HDEN_MASK \ + 0x00080000 /* RLINFO_MEM_HDEN[19] */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_RLINFO_MEM_HDEN_SHFT 19 +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_PL_TBL_HDEN_ADDR \ + WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_PL_TBL_HDEN_MASK \ + 0x00040000 /* PL_TBL_HDEN[18] */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_PL_TBL_HDEN_SHFT 18 +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_HDEN2_ADDR \ + WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_HDEN2_MASK \ + 0x00020000 /* FL_TBL_HDEN2[17] */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_HDEN2_SHFT 17 +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_HDEN1_ADDR \ + WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_HDEN1_MASK \ + 0x00010000 /* FL_TBL_HDEN1[16] */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_HDEN1_SHFT 16 +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_RLINFO_MEM_AWT_ADDR \ + WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_RLINFO_MEM_AWT_MASK \ + 0x00000008 /* RLINFO_MEM_AWT[3] */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_RLINFO_MEM_AWT_SHFT 3 +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_PL_TBL_AWT_ADDR \ + WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_PL_TBL_AWT_MASK \ + 0x00000004 /* PL_TBL_AWT[2] */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_PL_TBL_AWT_SHFT 2 +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_AWT2_ADDR \ + WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_AWT2_MASK \ + 0x00000002 /* FL_TBL_AWT2[1] */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_AWT2_SHFT 1 +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_AWT1_ADDR \ + WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_ADDR +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_AWT1_MASK \ + 0x00000001 /* FL_TBL_AWT1[0] */ +#define WF_PSE_TOP_SRAM_AWT_HDEN_CTRL_FL_TBL_AWT1_SHFT 0 + +/* +* ---SRAM_MBIST_DELSEL_1 (0x820C8000 + 0x2f0)--- +* MBIST_DELSEL3[31..0] - (RW) Control register of delsel for RLINFO +SRAM +*/ +#define WF_PSE_TOP_SRAM_MBIST_DELSEL_1_MBIST_DELSEL3_ADDR \ + WF_PSE_TOP_SRAM_MBIST_DELSEL_1_ADDR +#define WF_PSE_TOP_SRAM_MBIST_DELSEL_1_MBIST_DELSEL3_MASK \ + 0xFFFFFFFF /* MBIST_DELSEL3[31..0] */ +#define WF_PSE_TOP_SRAM_MBIST_DELSEL_1_MBIST_DELSEL3_SHFT 0 + +/* +* ---PSE_SEEK_CR_00 (0x820C8000 + 0x3d0)--- +* PSE_FL_ARB_CS[2..0] - (RO) PSE debug state for FL_ARB_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_FL_CS[7..4] - (RO) PSE debug state for FL_CS +* PSE_ENQ_FL_CS[11..8] - (RO) PSE debug state for ENQ_FL_CS +* PSE_DEQ_FL_CS[15..12] - (RO) PSE debug state for DEQ_FL_CS +* PSE_ACC_LST_CS[18..16] - (RO) PSE debug state for ACC_LST_CS +* RESERVED19[31..19] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_ACC_LST_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_00_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_ACC_LST_CS_MASK \ + 0x00070000 /* PSE_ACC_LST_CS[18..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_ACC_LST_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_DEQ_FL_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_00_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_DEQ_FL_CS_MASK \ + 0x0000F000 /* PSE_DEQ_FL_CS[15..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_DEQ_FL_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_ENQ_FL_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_00_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_ENQ_FL_CS_MASK \ + 0x00000F00 /* PSE_ENQ_FL_CS[11..8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_ENQ_FL_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_FL_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_00_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_FL_CS_MASK \ + 0x000000F0 /* PSE_FL_CS[7..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_FL_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_FL_ARB_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_00_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_FL_ARB_CS_MASK \ + 0x00000007 /* PSE_FL_ARB_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_00_PSE_FL_ARB_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_01 (0x820C8000 + 0x3d4)--- +* PSE_PL_ARB_CS[2..0] - (RO) PSE debug state for PL_ARB_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_PL_INIT_CS[5..4] - (RO) PSE debug state for PL_INIT_CS +* RESERVED6[7..6] - (RO) Reserved bits +* PSE_PL_GNEXT_CS[8] - (RO) PSE debug state for PL_GNEXT_CS +* RESERVED9[11..9] - (RO) Reserved bits +* PSE_PL_GBUF_CS[14..12] - (RO) PSE debug state for PL_GBUF_CS +* RESERVED15[15] - (RO) Reserved bits +* PSE_PL_RLS_CS[17..16] - (RO) PSE debug state for PL_RLS_CS +* RESERVED18[19..18] - (RO) Reserved bits +* PSE_PL_REFILL_CS[22..20] - (RO) PSE debug state for PL_REFILL_CS +* RESERVED23[23] - (RO) Reserved bits +* PSE_RLS_CS[25..24] - (RO) PSE debug state for RLS_CS +* RESERVED26[31..26] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_RLS_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_01_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_RLS_CS_MASK \ + 0x03000000 /* PSE_RLS_CS[25..24] */ +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_RLS_CS_SHFT 24 +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_REFILL_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_01_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_REFILL_CS_MASK \ + 0x00700000 /* PSE_PL_REFILL_CS[22..20] */ +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_REFILL_CS_SHFT 20 +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_RLS_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_01_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_RLS_CS_MASK \ + 0x00030000 /* PSE_PL_RLS_CS[17..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_RLS_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_GBUF_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_01_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_GBUF_CS_MASK \ + 0x00007000 /* PSE_PL_GBUF_CS[14..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_GBUF_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_GNEXT_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_01_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_GNEXT_CS_MASK \ + 0x00000100 /* PSE_PL_GNEXT_CS[8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_GNEXT_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_INIT_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_01_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_INIT_CS_MASK \ + 0x00000030 /* PSE_PL_INIT_CS[5..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_INIT_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_ARB_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_01_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_ARB_CS_MASK \ + 0x00000007 /* PSE_PL_ARB_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_01_PSE_PL_ARB_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_02 (0x820C8000 + 0x3d8)--- +* PSE_HIF_DOP_PBUF_CS[2..0] - (RO) PSE debug state for HIF_DOP_PBUF_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_HIF_DOP_CACHE_CS[5..4] - (RO) PSE debug state for +HIF_DOP_CACHE_CS +* RESERVED6[7..6] - (RO) Reserved bits +* PSE_HIF_QOP_Q_OPER_CS[11..8] - (RO) PSE debug state for +HIF_QOP_Q_OPER_CS +* PSE_HIF_QOP_RL_OCP_CS[13..12] - (RO) PSE debug state for +HIF_QOP_RL_OCP_CS +* RESERVED14[15..14] - (RO) Reserved bits +* PSE_HIF_QOP_PL_OCP_CS[17..16] - (RO) PSE debug state for +HIF_QOP_PL_OCP_CS +* RESERVED18[19..18] - (RO) Reserved bits +* PSE_HIF_QOP_ALLOCATE_CS[22..20] - (RO) PSE debug state for +HIF_QOP_ALLOCATE_CS +* RESERVED23[23] - (RO) Reserved bits +* PSE_HIF_RX_DOP_PBUF_CS[26..24] - (RO) PSE debug state for +HIF_RX_DOP_PBUF_CS +* RESERVED27[27] - (RO) Reserved bits +* PSE_HIF_RX_DOP_CACHE_CS[29..28] - (RO) PSE debug state for +HIF_RX_DOP_CACHE_CS +* RESERVED30[31..30] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_RX_DOP_CACHE_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_02_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_RX_DOP_CACHE_CS_MASK \ + 0x30000000 /* PSE_HIF_RX_DOP_CACHE_CS[29..28] */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_RX_DOP_CACHE_CS_SHFT 28 +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_RX_DOP_PBUF_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_02_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_RX_DOP_PBUF_CS_MASK \ + 0x07000000 /* PSE_HIF_RX_DOP_PBUF_CS[26..24] */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_RX_DOP_PBUF_CS_SHFT 24 +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_ALLOCATE_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_02_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_ALLOCATE_CS_MASK \ + 0x00700000 /* PSE_HIF_QOP_ALLOCATE_CS[22..20] */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_ALLOCATE_CS_SHFT 20 +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_PL_OCP_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_02_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_PL_OCP_CS_MASK \ + 0x00030000 /* PSE_HIF_QOP_PL_OCP_CS[17..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_PL_OCP_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_RL_OCP_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_02_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_RL_OCP_CS_MASK \ + 0x00003000 /* PSE_HIF_QOP_RL_OCP_CS[13..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_RL_OCP_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_Q_OPER_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_02_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_Q_OPER_CS_MASK \ + 0x00000F00 /* PSE_HIF_QOP_Q_OPER_CS[11..8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_QOP_Q_OPER_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_DOP_CACHE_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_02_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_DOP_CACHE_CS_MASK \ + 0x00000030 /* PSE_HIF_DOP_CACHE_CS[5..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_DOP_CACHE_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_DOP_PBUF_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_02_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_DOP_PBUF_CS_MASK \ + 0x00000007 /* PSE_HIF_DOP_PBUF_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_02_PSE_HIF_DOP_PBUF_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_03 (0x820C8000 + 0x3dc)--- +* PSE_CPU_DOP_PBUF_CS[2..0] - (RO) PSE debug state for CPU_DOP_PBUF_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_CPU_DOP_CACHE_CS[5..4] - (RO) PSE debug state for +CPU_DOP_CACHE_CS +* RESERVED6[7..6] - (RO) Reserved bits +* PSE_CPU_QOP_Q_OPER_CS[11..8] - (RO) PSE debug state for +CPU_QOP_Q_OPER_CS +* PSE_CPU_QOP_RL_OCP_CS[13..12] - (RO) PSE debug state for +CPU_QOP_RL_OCP_CS +* RESERVED14[15..14] - (RO) Reserved bits +* PSE_CPU_QOP_PL_OCP_CS[17..16] - (RO) PSE debug state for +CPU_QOP_PL_OCP_CS +* RESERVED18[19..18] - (RO) Reserved bits +* PSE_CPU_QOP_ALLOCATE_CS[22..20] - (RO) PSE debug state for +CPU_QOP_ALLOCATE_CS +* RESERVED23[31..23] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_ALLOCATE_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_03_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_ALLOCATE_CS_MASK \ + 0x00700000 /* PSE_CPU_QOP_ALLOCATE_CS[22..20] */ +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_ALLOCATE_CS_SHFT 20 +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_PL_OCP_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_03_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_PL_OCP_CS_MASK \ + 0x00030000 /* PSE_CPU_QOP_PL_OCP_CS[17..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_PL_OCP_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_RL_OCP_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_03_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_RL_OCP_CS_MASK \ + 0x00003000 /* PSE_CPU_QOP_RL_OCP_CS[13..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_RL_OCP_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_Q_OPER_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_03_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_Q_OPER_CS_MASK \ + 0x00000F00 /* PSE_CPU_QOP_Q_OPER_CS[11..8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_QOP_Q_OPER_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_DOP_CACHE_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_03_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_DOP_CACHE_CS_MASK \ + 0x00000030 /* PSE_CPU_DOP_CACHE_CS[5..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_DOP_CACHE_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_DOP_PBUF_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_03_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_DOP_PBUF_CS_MASK \ + 0x00000007 /* PSE_CPU_DOP_PBUF_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_03_PSE_CPU_DOP_PBUF_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_04 (0x820C8000 + 0x3e0)--- +* PSE_WF_DOP_PBUF_CS[2..0] - (RO) PSE debug state for WF_DOP_PBUF_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_WF_DOP_CACHE_CS[5..4] - (RO) PSE debug state for WF_DOP_CACHE_CS +* RESERVED6[7..6] - (RO) Reserved bits +* PSE_WF_QOP_Q_OPER_CS[11..8] - (RO) PSE debug state for +WF_QOP_Q_OPER_CS +* PSE_WF_QOP_RL_OCP_CS[13..12] - (RO) PSE debug state for +WF_QOP_RL_OCP_CS +* RESERVED14[15..14] - (RO) Reserved bits +* PSE_WF_QOP_PL_OCP_CS[17..16] - (RO) PSE debug state for +WF_QOP_PL_OCP_CS +* RESERVED18[19..18] - (RO) Reserved bits +* PSE_WF_QOP_ALLOCATE_CS[22..20] - (RO) PSE debug state for +WF_QOP_ALLOCATE_CS +* RESERVED23[31..23] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_ALLOCATE_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_04_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_ALLOCATE_CS_MASK \ + 0x00700000 /* PSE_WF_QOP_ALLOCATE_CS[22..20] */ +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_ALLOCATE_CS_SHFT 20 +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_PL_OCP_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_04_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_PL_OCP_CS_MASK \ + 0x00030000 /* PSE_WF_QOP_PL_OCP_CS[17..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_PL_OCP_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_RL_OCP_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_04_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_RL_OCP_CS_MASK \ + 0x00003000 /* PSE_WF_QOP_RL_OCP_CS[13..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_RL_OCP_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_Q_OPER_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_04_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_Q_OPER_CS_MASK \ + 0x00000F00 /* PSE_WF_QOP_Q_OPER_CS[11..8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_QOP_Q_OPER_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_DOP_CACHE_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_04_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_DOP_CACHE_CS_MASK \ + 0x00000030 /* PSE_WF_DOP_CACHE_CS[5..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_DOP_CACHE_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_DOP_PBUF_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_04_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_DOP_PBUF_CS_MASK \ + 0x00000007 /* PSE_WF_DOP_PBUF_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_04_PSE_WF_DOP_PBUF_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_05 (0x820C8000 + 0x3e4)--- +* PSE_MDP_DOP_PBUF_CS[2..0] - (RO) PSE debug state for MDP_DOP_PBUF_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_MDP_DOP_CACHE_CS[5..4] - (RO) PSE debug state for +MDP_DOP_CACHE_CS +* RESERVED6[7..6] - (RO) Reserved bits +* PSE_MDP_QOP_Q_OPER_CS[11..8] - (RO) PSE debug state for +MDP_QOP_Q_OPER_CS +* PSE_MDP_QOP_RL_OCP_CS[13..12] - (RO) PSE debug state for +MDP_QOP_RL_OCP_CS +* RESERVED14[15..14] - (RO) Reserved bits +* PSE_MDP_QOP_PL_OCP_CS[17..16] - (RO) PSE debug state for +MDP_QOP_PL_OCP_CS +* RESERVED18[19..18] - (RO) Reserved bits +* PSE_MDP_QOP_ALLOCATE_CS[22..20] - (RO) PSE debug state for +MDP_QOP_ALLOCATE_CS +* RESERVED23[31..23] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_ALLOCATE_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_05_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_ALLOCATE_CS_MASK \ + 0x00700000 /* PSE_MDP_QOP_ALLOCATE_CS[22..20] */ +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_ALLOCATE_CS_SHFT 20 +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_PL_OCP_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_05_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_PL_OCP_CS_MASK \ + 0x00030000 /* PSE_MDP_QOP_PL_OCP_CS[17..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_PL_OCP_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_RL_OCP_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_05_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_RL_OCP_CS_MASK \ + 0x00003000 /* PSE_MDP_QOP_RL_OCP_CS[13..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_RL_OCP_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_Q_OPER_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_05_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_Q_OPER_CS_MASK \ + 0x00000F00 /* PSE_MDP_QOP_Q_OPER_CS[11..8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_QOP_Q_OPER_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_DOP_CACHE_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_05_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_DOP_CACHE_CS_MASK \ + 0x00000030 /* PSE_MDP_DOP_CACHE_CS[5..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_DOP_CACHE_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_DOP_PBUF_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_05_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_DOP_PBUF_CS_MASK \ + 0x00000007 /* PSE_MDP_DOP_PBUF_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_05_PSE_MDP_DOP_PBUF_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_06 (0x820C8000 + 0x3e8)--- +* PSE_SEC_DOP_PBUF_CS[2..0] - (RO) PSE debug state for SEC_DOP_PBUF_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_SEC_DOP_CACHE_CS[5..4] - (RO) PSE debug state for +SEC_DOP_CACHE_CS +* RESERVED6[7..6] - (RO) Reserved bits +* PSE_SEC_QOP_Q_OPER_CS[11..8] - (RO) PSE debug state for +SEC_QOP_Q_OPER_CS +* PSE_SEC_QOP_RL_OCP_CS[13..12] - (RO) PSE debug state for +SEC_QOP_RL_OCP_CS +* RESERVED14[15..14] - (RO) Reserved bits +* PSE_SEC_QOP_PL_OCP_CS[17..16] - (RO) PSE debug state for +SEC_QOP_PL_OCP_CS +* RESERVED18[19..18] - (RO) Reserved bits +* PSE_SEC_QOP_ALLOCATE_CS[22..20] - (RO) PSE debug state for +SEC_QOP_ALLOCATE_CS +* RESERVED23[31..23] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_ALLOCATE_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_06_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_ALLOCATE_CS_MASK \ + 0x00700000 /* PSE_SEC_QOP_ALLOCATE_CS[22..20] */ +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_ALLOCATE_CS_SHFT 20 +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_PL_OCP_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_06_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_PL_OCP_CS_MASK \ + 0x00030000 /* PSE_SEC_QOP_PL_OCP_CS[17..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_PL_OCP_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_RL_OCP_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_06_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_RL_OCP_CS_MASK \ + 0x00003000 /* PSE_SEC_QOP_RL_OCP_CS[13..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_RL_OCP_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_Q_OPER_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_06_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_Q_OPER_CS_MASK \ + 0x00000F00 /* PSE_SEC_QOP_Q_OPER_CS[11..8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_QOP_Q_OPER_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_DOP_CACHE_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_06_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_DOP_CACHE_CS_MASK \ + 0x00000030 /* PSE_SEC_DOP_CACHE_CS[5..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_DOP_CACHE_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_DOP_PBUF_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_06_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_DOP_PBUF_CS_MASK \ + 0x00000007 /* PSE_SEC_DOP_PBUF_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_06_PSE_SEC_DOP_PBUF_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_07 (0x820C8000 + 0x3ec)--- +* PSE_PLE_DOP_PBUF_CS[2..0] - (RO) PSE debug state for PLE_DOP_PBUF_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_PLE_DOP_CACHE_CS[5..4] - (RO) PSE debug state for +PLE_DOP_CACHE_CS +* RESERVED6[7..6] - (RO) Reserved bits +* PSE_PLE_QOP_Q_OPER_CS[11..8] - (RO) PSE debug state for +PLE_QOP_Q_OPER_CS +* PSE_PLE_QOP_RL_OCP_CS[13..12] - (RO) PSE debug state for +PLE_QOP_RL_OCP_CS +* RESERVED14[15..14] - (RO) Reserved bits +* PSE_PLE_QOP_PL_OCP_CS[17..16] - (RO) PSE debug state for +PLE_QOP_PL_OCP_CS +* RESERVED18[19..18] - (RO) Reserved bits +* PSE_PLE_QOP_ALLOCATE_CS[22..20] - (RO) PSE debug state for +PLE_QOP_ALLOCATE_CS +* RESERVED23[31..23] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_ALLOCATE_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_07_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_ALLOCATE_CS_MASK \ + 0x00700000 /* PSE_PLE_QOP_ALLOCATE_CS[22..20] */ +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_ALLOCATE_CS_SHFT 20 +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_PL_OCP_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_07_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_PL_OCP_CS_MASK \ + 0x00030000 /* PSE_PLE_QOP_PL_OCP_CS[17..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_PL_OCP_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_RL_OCP_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_07_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_RL_OCP_CS_MASK \ + 0x00003000 /* PSE_PLE_QOP_RL_OCP_CS[13..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_RL_OCP_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_Q_OPER_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_07_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_Q_OPER_CS_MASK \ + 0x00000F00 /* PSE_PLE_QOP_Q_OPER_CS[11..8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_QOP_Q_OPER_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_DOP_CACHE_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_07_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_DOP_CACHE_CS_MASK \ + 0x00000030 /* PSE_PLE_DOP_CACHE_CS[5..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_DOP_CACHE_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_DOP_PBUF_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_07_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_DOP_PBUF_CS_MASK \ + 0x00000007 /* PSE_PLE_DOP_PBUF_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_07_PSE_PLE_DOP_PBUF_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_08 (0x820C8000 + 0x3f0)--- +* PSE_AMSDU_DOP_PBUF_CS[2..0] - (RO) PSE debug state for +AMSDU_DOP_PBUF_CS +* RESERVED3[3] - (RO) Reserved bits +* PSE_AMSDU_DOP_CACHE_CS[5..4] - (RO) PSE debug state for +AMSDU_DOP_CACHE_CS +* RESERVED6[7..6] - (RO) Reserved bits +* CPU_Q_OP_CS[11..8] - (RO) PSE debug state for CPI_Q_OP_CS +* ARB_REQ_CS[14..12] - (RO) PSE debug state for ARB_REQ_CS +* RESERVED15[15] - (RO) Reserved bits +* APB_REQ_CS[18..16] - (RO) PSE debug state for APB_REQ_CS +* RESERVED19[31..19] - (RO) Reserved bits +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_08_APB_REQ_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_08_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_08_APB_REQ_CS_MASK \ + 0x00070000 /* APB_REQ_CS[18..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_08_APB_REQ_CS_SHFT 16 +#define WF_PSE_TOP_PSE_SEEK_CR_08_ARB_REQ_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_08_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_08_ARB_REQ_CS_MASK \ + 0x00007000 /* ARB_REQ_CS[14..12] */ +#define WF_PSE_TOP_PSE_SEEK_CR_08_ARB_REQ_CS_SHFT 12 +#define WF_PSE_TOP_PSE_SEEK_CR_08_CPU_Q_OP_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_08_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_08_CPU_Q_OP_CS_MASK \ + 0x00000F00 /* CPU_Q_OP_CS[11..8] */ +#define WF_PSE_TOP_PSE_SEEK_CR_08_CPU_Q_OP_CS_SHFT 8 +#define WF_PSE_TOP_PSE_SEEK_CR_08_PSE_AMSDU_DOP_CACHE_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_08_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_08_PSE_AMSDU_DOP_CACHE_CS_MASK \ + 0x00000030 /* PSE_AMSDU_DOP_CACHE_CS[5..4] */ +#define WF_PSE_TOP_PSE_SEEK_CR_08_PSE_AMSDU_DOP_CACHE_CS_SHFT 4 +#define WF_PSE_TOP_PSE_SEEK_CR_08_PSE_AMSDU_DOP_PBUF_CS_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_08_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_08_PSE_AMSDU_DOP_PBUF_CS_MASK \ + 0x00000007 /* PSE_AMSDU_DOP_PBUF_CS[2..0] */ +#define WF_PSE_TOP_PSE_SEEK_CR_08_PSE_AMSDU_DOP_PBUF_CS_SHFT 0 + +/* +* ---PSE_SEEK_CR_09 (0x820C8000 + 0x3f4)--- +* RESERVED0[15..0] - (RO) Reserved bits +* DOUBLE_RLS_FID[27..16] - (RO) PSE double RLS FID PAGE +* RESERVED28[30..28] - (RO) Reserved bits +* DOUBLE_RLS_ERROR[31] - (RO) PSE double RLS error flag +*/ +#define WF_PSE_TOP_PSE_SEEK_CR_09_DOUBLE_RLS_ERROR_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_09_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_09_DOUBLE_RLS_ERROR_MASK \ + 0x80000000 /* DOUBLE_RLS_ERROR[31] */ +#define WF_PSE_TOP_PSE_SEEK_CR_09_DOUBLE_RLS_ERROR_SHFT 31 +#define WF_PSE_TOP_PSE_SEEK_CR_09_DOUBLE_RLS_FID_ADDR \ + WF_PSE_TOP_PSE_SEEK_CR_09_ADDR +#define WF_PSE_TOP_PSE_SEEK_CR_09_DOUBLE_RLS_FID_MASK \ + 0x0FFF0000 /* DOUBLE_RLS_FID[27..16] */ +#define WF_PSE_TOP_PSE_SEEK_CR_09_DOUBLE_RLS_FID_SHFT 16 + +#ifdef __cplusplus +} +#endif + +#endif /* __WF_PSE_TOP_REGS_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/soc3_0/wf_wfdma_host_dma0.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/soc3_0/wf_wfdma_host_dma0.h new file mode 100644 index 0000000000000..fc54b7cea9241 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/soc3_0/wf_wfdma_host_dma0.h @@ -0,0 +1,5922 @@ +/* [File] : wf_wfdma_host_dma0.h */ +/* [Revision time] : Mon Apr 15 14:14:47 2019 */ +/* [Description] : This file is auto generated by CODA */ +/* [Copyright] : Copyright (C) 2019 Mediatek Incorportion. All rights */ +/* reserved. */ + +#ifndef __WF_WFDMA_HOST_DMA0_REGS_H__ +#define __WF_WFDMA_HOST_DMA0_REGS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ************************************************************************** */ +/* */ +/* WF_WFDMA_HOST_DMA0 CR Definitions */ +/* */ +/* ************************************************************************** */ + +#define WF_WFDMA_HOST_DMA0_BASE 0x7C024000 + +#define WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0XA0) /* 40A0 */ +#define WF_WFDMA_HOST_DMA0_HOST_IF_RX_DONE_STS_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0XA4) /* 40A4 */ +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_START_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x0B0) /* 40B0 */ +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_START_EXT_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x0B4) /* 40B4 */ +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_END_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x0B8) /* 40B8 */ +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_END_EXT_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x0BC) /* 40BC */ +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_START_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x0C0) /* 40C0 */ +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_START_EXT_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x0C4) /* 40C4 */ +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_END_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x0C8) /* 40C8 */ +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_END_EXT_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x0CC) /* 40CC */ +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_START_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x0D0) /* 40D0 */ +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_START_EXT_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x0D4) /* 40D4 */ +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_END_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x0D8) /* 40D8 */ +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_END_EXT_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x0DC) /* 40DC */ +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_START_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x0E0) /* 40E0 */ +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_START_EXT_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x0E4) /* 40E4 */ +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_END_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x0E8) /* 40E8 */ +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_END_EXT_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x0EC) /* 40EC */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_RST_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x100) /* 4100 */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x104) /* 4104 */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0X108) /* 4108 */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x10C) /* 410C */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0X110) /* 4110 */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0X114) /* 4114 */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DUMMY_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x120) /* 4120 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x124) /* 4124 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_PROBE_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x128) /* 4128 */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x12C) /* 412C */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_PROBE_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x130) /* 4130 */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DMASHDL_DBG_PROBE_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x134) /* 4134 */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x138) /* 4138 */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x13c) /* 413C */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x140) /* 4140 */ +#define WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x1E8) /* 41E8 */ +#define WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x1EC) /* 41EC */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x1F0) /* 41F0 */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x1F4) /* 41F4 */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x1F8) /* 41F8 */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x1FC) /* 41FC */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x200) /* 4200 */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0X204) /* 4204 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x208) /* 4208 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x20C) /* 420C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_TX_Q_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x224) /* 4224 */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0X228) /* 4228 */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0X22C) /* 422C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x230) /* 4230 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x234) /* 4234 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x240) /* 4240 */ +#define WF_WFDMA_HOST_DMA0_MD_INT_STA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x250) /* 4250 */ +#define WF_WFDMA_HOST_DMA0_MD_INT_ENA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x254) /* 4254 */ +#define WF_WFDMA_HOST_DMA0_MCU2MD_SW_INT_SET_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x258) /* 4258 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x260) /* 4260 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x264) /* 4264 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x268) /* 4268 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x26C) /* 426C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x280) /* 4280 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x284) /* 4284 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x288) /* 4288 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x298) /* 4298 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2A0) /* 42A0 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2A4) /* 42A4 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2A8) /* 42A8 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2AC) /* 42AC */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2B0) /* 42B0 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2B4) /* 42B4 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2C0) /* 42C0 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2C4) /* 42C4 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2C8) /* 42C8 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2CC) /* 42CC */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2D0) /* 42D0 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2D4) /* 42D4 */ +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2E0) /* 42E0 */ +#define WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2E4) /* 42E4 */ +#define WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2E8) /* 42E8 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x2F0) /* 42F0 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x300) /* 4300 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x304) /* 4304 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x308) /* 4308 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x30c) /* 430C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x310) /* 4310 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x314) /* 4314 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x318) /* 4318 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x31c) /* 431C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x320) /* 4320 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x324) /* 4324 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x328) /* 4328 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x32c) /* 432C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x330) /* 4330 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x334) /* 4334 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x338) /* 4338 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x33c) /* 433C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x500) /* 4500 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x504) /* 4504 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x508) /* 4508 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x50c) /* 450C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x510) /* 4510 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x514) /* 4514 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x518) /* 4518 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x51c) /* 451C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x520) /* 4520 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x524) /* 4524 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x528) /* 4528 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x52C) /* 452C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x530) /* 4530 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x534) /* 4534 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x538) /* 4538 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x53C) /* 453C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x540) /* 4540 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x544) /* 4544 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x548) /* 4548 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x54c) /* 454C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x550) /* 4550 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x554) /* 4554 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x558) /* 4558 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x55c) /* 455C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x560) /* 4560 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x564) /* 4564 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x568) /* 4568 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x56C) /* 456C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x570) /* 4570 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x574) /* 4574 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x578) /* 4578 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x57C) /* 457C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x600) /* 4600 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x604) /* 4604 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x608) /* 4608 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x60C) /* 460C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x680) /* 4680 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x684) /* 4684 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x688) /* 4688 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x68C) /* 468C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x690) /* 4690 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x694) /* 4694 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x698) /* 4698 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0x69C) /* 469C */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xA00) /* 4A00 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xA04) /* 4A04 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xA08) /* 4A08 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xA10) /* 4A10 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xA14) /* 4A14 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xA18) /* 4A18 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xA20) /* 4A20 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xA24) /* 4A24 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xA28) /* 4A28 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xA30) /* 4A30 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xA34) /* 4A34 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xA38) /* 4A38 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC00) /* 4C00 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC04) /* 4C04 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC08) /* 4C08 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC10) /* 4C10 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC14) /* 4C14 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC18) /* 4C18 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC20) /* 4C20 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC24) /* 4C24 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC28) /* 4C28 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC30) /* 4C30 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC34) /* 4C34 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC38) /* 4C38 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC40) /* 4C40 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC44) /* 4C44 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC48) /* 4C48 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC50) /* 4C50 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC54) /* 4C54 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC58) /* 4C58 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC60) /* 4C60 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC64) /* 4C64 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC68) /* 4C68 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC70) /* 4C70 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC74) /* 4C74 */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA0_BASE + 0xC78) /* 4C78 */ + +/* +* ---HOST_IF_TX_DONE_STS (0x18024000 + 0XA0)--- +* fifo_dfet_txdone_dat0_done_sts[0] - (W1C) USB DAT0 FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint +buffer +* fifo_dfet_txdone_dat1_done_sts[1] - (W1C) USB DAT1 FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint +buffer +* fifo_dfet_txdone_dat2_done_sts[2] - (W1C) USB DAT2 FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint +buffer +* fifo_dfet_txdone_dat3_done_sts[3] - (W1C) USB DAT3 FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint +buffer +* fifo_dfet_txdone_dat4_done_sts[4] - (W1C) USB DAT4 FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint +buffer +* fifo_dfet_txdone_cmd_done_sts[5] - (W1C) USB CMD FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint +buffer +* fifo_dfet_txdone_fwdl_done_sts[6] - (W1C) USB Firmware download FIFO Tx +status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint +buffer +* SDIO Mode (All SDIO Tx packet goto firmware +* download FIFO) +* 0 : no tx done +* 1 : pdma start to fetch data from SDIO +buffer +* RESERVED7[31..7] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_fwdl_done_sts_ADDR \ + \ + WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_fwdl_done_sts_MASK \ + \ + 0x00000040 /* fifo_dfet_txdone_fwdl_done_sts[6] */ +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_fwdl_done_sts_SHFT \ + \ + 6 +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_cmd_done_sts_ADDR \ + \ + WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_cmd_done_sts_MASK \ + \ + 0x00000020 /* fifo_dfet_txdone_cmd_done_sts[5] */ +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_cmd_done_sts_SHFT \ + \ + 5 +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat4_done_sts_ADDR \ + \ + WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat4_done_sts_MASK \ + \ + 0x00000010 /* fifo_dfet_txdone_dat4_done_sts[4] */ +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat4_done_sts_SHFT \ + \ + 4 +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat3_done_sts_ADDR \ + \ + WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat3_done_sts_MASK \ + \ + 0x00000008 /* fifo_dfet_txdone_dat3_done_sts[3] */ +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat3_done_sts_SHFT \ + \ + 3 +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat2_done_sts_ADDR \ + \ + WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat2_done_sts_MASK \ + \ + 0x00000004 /* fifo_dfet_txdone_dat2_done_sts[2] */ +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat2_done_sts_SHFT \ + \ + 2 +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat1_done_sts_ADDR \ + \ + WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat1_done_sts_MASK \ + \ + 0x00000002 /* fifo_dfet_txdone_dat1_done_sts[1] */ +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat1_done_sts_SHFT \ + \ + 1 +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat0_done_sts_ADDR \ + \ + WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat0_done_sts_MASK \ + \ + 0x00000001 /* fifo_dfet_txdone_dat0_done_sts[0] */ +#define \ +WF_WFDMA_HOST_DMA0_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat0_done_sts_SHFT \ + \ + 0 + +/* +* ---HOST_IF_RX_DONE_STS (0x18024000 + 0XA4)--- +* rx0_packet_done_sts[0] - (W1C) USB/SDIO Rx0 packet done status +* 0 : no rx packet done +* 1 : rx packet send to host interface +* rx1_packet_done_sts[1] - (W1C) USB/SDIO Rx1 packet done status +* 0 : no rx packet done +* 1 : rx packet send to host interface +* Note : All SDIO Packet send to SIDO RX0 +port +* RESERVED2[31..2] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_HOST_IF_RX_DONE_STS_rx1_packet_done_sts_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_IF_RX_DONE_STS_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_IF_RX_DONE_STS_rx1_packet_done_sts_MASK \ + 0x00000002 /* rx1_packet_done_sts[1] */ +#define WF_WFDMA_HOST_DMA0_HOST_IF_RX_DONE_STS_rx1_packet_done_sts_SHFT 1 +#define WF_WFDMA_HOST_DMA0_HOST_IF_RX_DONE_STS_rx0_packet_done_sts_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_IF_RX_DONE_STS_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_IF_RX_DONE_STS_rx0_packet_done_sts_MASK \ + 0x00000001 /* rx0_packet_done_sts[0] */ +#define WF_WFDMA_HOST_DMA0_HOST_IF_RX_DONE_STS_rx0_packet_done_sts_SHFT 0 + +/* +* ---TX_DMAD_RNG_START (0x18024000 + 0x0B0)--- +* tx_dmad_rng_start[31..0] - (RW) TX DMAD address range start [31:0] +*/ +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_START_tx_dmad_rng_start_ADDR \ + WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_START_ADDR +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_START_tx_dmad_rng_start_MASK \ + 0xFFFFFFFF /* tx_dmad_rng_start[31..0] */ +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_START_tx_dmad_rng_start_SHFT 0 + +/* +* ---TX_DMAD_RNG_START_EXT (0x18024000 + 0x0B4)--- +* tx_dmad_rng_start_ext[3..0] - (RW) TX DMAD address range start [35:32] +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_START_EXT_tx_dmad_rng_start_ext_ADDR \ + WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_START_EXT_ADDR +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_START_EXT_tx_dmad_rng_start_ext_MASK \ + 0x0000000F /* tx_dmad_rng_start_ext[3..0] */ +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_START_EXT_tx_dmad_rng_start_ext_SHFT 0 + +/* +* ---TX_DMAD_RNG_END (0x18024000 + 0x0B8)--- +* tx_dmad_rng_end[31..0] - (RW) TX DMAD address range end [31:0] +*/ +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_END_tx_dmad_rng_end_ADDR \ + WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_END_ADDR +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_END_tx_dmad_rng_end_MASK \ + 0xFFFFFFFF /* tx_dmad_rng_end[31..0] */ +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_END_tx_dmad_rng_end_SHFT 0 + +/* +* ---TX_DMAD_RNG_END_EXT (0x18024000 + 0x0BC)--- +* tx_dmad_rng_end_ext[3..0] - (RW) TX DMAD address range end [35:32] +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_END_EXT_tx_dmad_rng_end_ext_ADDR \ + WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_END_EXT_ADDR +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_END_EXT_tx_dmad_rng_end_ext_MASK \ + 0x0000000F /* tx_dmad_rng_end_ext[3..0] */ +#define WF_WFDMA_HOST_DMA0_TX_DMAD_RNG_END_EXT_tx_dmad_rng_end_ext_SHFT 0 + +/* +* ---RX_DMAD_RNG_START (0x18024000 + 0x0C0)--- +* rx_dmad_rng_start[31..0] - (RW) RX DMAD address range start [31:0] +*/ +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_START_rx_dmad_rng_start_ADDR \ + WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_START_ADDR +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_START_rx_dmad_rng_start_MASK \ + 0xFFFFFFFF /* rx_dmad_rng_start[31..0] */ +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_START_rx_dmad_rng_start_SHFT 0 + +/* +* ---RX_DMAD_RNG_START_EXT (0x18024000 + 0x0C4)--- +* rx_dmad_rng_start_ext[3..0] - (RW) RX DMAD address range start [35:32] +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_START_EXT_rx_dmad_rng_start_ext_ADDR \ + WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_START_EXT_ADDR +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_START_EXT_rx_dmad_rng_start_ext_MASK \ + 0x0000000F /* rx_dmad_rng_start_ext[3..0] */ +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_START_EXT_rx_dmad_rng_start_ext_SHFT 0 + +/* +* ---RX_DMAD_RNG_END (0x18024000 + 0x0C8)--- +* rx_dmad_rng_end[31..0] - (RW) RX DMAD address range end [31:0] +*/ +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_END_rx_dmad_rng_end_ADDR \ + WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_END_ADDR +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_END_rx_dmad_rng_end_MASK \ + 0xFFFFFFFF /* rx_dmad_rng_end[31..0] */ +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_END_rx_dmad_rng_end_SHFT 0 + +/* +* ---RX_DMAD_RNG_END_EXT (0x18024000 + 0x0CC)--- +* rx_dmad_rng_end_ext[3..0] - (RW) RX DMAD address range end [35:32] +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_END_EXT_rx_dmad_rng_end_ext_ADDR \ + WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_END_EXT_ADDR +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_END_EXT_rx_dmad_rng_end_ext_MASK \ + 0x0000000F /* rx_dmad_rng_end_ext[3..0] */ +#define WF_WFDMA_HOST_DMA0_RX_DMAD_RNG_END_EXT_rx_dmad_rng_end_ext_SHFT 0 + +/* +* ---TX_PLD_RNG_START (0x18024000 + 0x0D0)--- +* tx_pld_rng_start[31..0] - (RW) TX PLD address range start [31:0] +*/ +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_START_tx_pld_rng_start_ADDR \ + WF_WFDMA_HOST_DMA0_TX_PLD_RNG_START_ADDR +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_START_tx_pld_rng_start_MASK \ + 0xFFFFFFFF /* tx_pld_rng_start[31..0] */ +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_START_tx_pld_rng_start_SHFT 0 + +/* +* ---TX_PLD_RNG_START_EXT (0x18024000 + 0x0D4)--- +* tx_pld_rng_start_ext[3..0] - (RW) TX PLD address range start [35:32] +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_START_EXT_tx_pld_rng_start_ext_ADDR \ + WF_WFDMA_HOST_DMA0_TX_PLD_RNG_START_EXT_ADDR +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_START_EXT_tx_pld_rng_start_ext_MASK \ + 0x0000000F /* tx_pld_rng_start_ext[3..0] */ +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_START_EXT_tx_pld_rng_start_ext_SHFT 0 + +/* +* ---TX_PLD_RNG_END (0x18024000 + 0x0D8)--- +* tx_pld_rng_end[31..0] - (RW) TX PLD address range end [31:0] +*/ +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_END_tx_pld_rng_end_ADDR \ + WF_WFDMA_HOST_DMA0_TX_PLD_RNG_END_ADDR +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_END_tx_pld_rng_end_MASK \ + 0xFFFFFFFF /* tx_pld_rng_end[31..0] */ +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_END_tx_pld_rng_end_SHFT 0 + +/* +* ---TX_PLD_RNG_END_EXT (0x18024000 + 0x0DC)--- +* tx_pld_rng_end_ext[3..0] - (RW) TX PLD address range end [35:32] +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_END_EXT_tx_pld_rng_end_ext_ADDR \ + WF_WFDMA_HOST_DMA0_TX_PLD_RNG_END_EXT_ADDR +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_END_EXT_tx_pld_rng_end_ext_MASK \ + 0x0000000F /* tx_pld_rng_end_ext[3..0] */ +#define WF_WFDMA_HOST_DMA0_TX_PLD_RNG_END_EXT_tx_pld_rng_end_ext_SHFT 0 + +/* +* ---RX_PLD_RNG_START (0x18024000 + 0x0E0)--- +* rx_pld_rng_start[31..0] - (RW) RX PLD address range start [31:0] +*/ +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_START_rx_pld_rng_start_ADDR \ + WF_WFDMA_HOST_DMA0_RX_PLD_RNG_START_ADDR +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_START_rx_pld_rng_start_MASK \ + 0xFFFFFFFF /* rx_pld_rng_start[31..0] */ +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_START_rx_pld_rng_start_SHFT 0 + +/* +* ---RX_PLD_RNG_START_EXT (0x18024000 + 0x0E4)--- +* rx_pld_rng_start_ext[3..0] - (RW) RX PLD address range start [35:32] +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_START_EXT_rx_pld_rng_start_ext_ADDR \ + WF_WFDMA_HOST_DMA0_RX_PLD_RNG_START_EXT_ADDR +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_START_EXT_rx_pld_rng_start_ext_MASK \ + 0x0000000F /* rx_pld_rng_start_ext[3..0] */ +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_START_EXT_rx_pld_rng_start_ext_SHFT 0 + +/* +* ---RX_PLD_RNG_END (0x18024000 + 0x0E8)--- +* rx_pld_rng_end[31..0] - (RW) RX PLD address range end [31:0] +*/ +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_END_rx_pld_rng_end_ADDR \ + WF_WFDMA_HOST_DMA0_RX_PLD_RNG_END_ADDR +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_END_rx_pld_rng_end_MASK \ + 0xFFFFFFFF /* rx_pld_rng_end[31..0] */ +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_END_rx_pld_rng_end_SHFT 0 + +/* +* ---RX_PLD_RNG_END_EXT (0x18024000 + 0x0EC)--- +* rx_pld_rng_end_ext[3..0] - (RW) RX PLD address range end [35:32] +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_END_EXT_rx_pld_rng_end_ext_ADDR \ + WF_WFDMA_HOST_DMA0_RX_PLD_RNG_END_EXT_ADDR +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_END_EXT_rx_pld_rng_end_ext_MASK \ + 0x0000000F /* rx_pld_rng_end_ext[3..0] */ +#define WF_WFDMA_HOST_DMA0_RX_PLD_RNG_END_EXT_rx_pld_rng_end_ext_SHFT 0 + +/* +* ---CONN_HIF_RST (0x18024000 + 0x100)--- +* RESERVED0[3..0] - (RO) Reserved bits +* conn_hif_logic_rst_n[4] - (RW) This conn_hif_logic_rst_n would reset +* wpdma logic partial control register, include Tx/Rx ring control. +* Also, conn_hif_logic_rst_n would reset wifi +* data path, include tx fifo, rx fifo, r2x_bridge, axi_mux and other other +* asynchronous bridge. +* (Note : conn_hif_logic_rst_n would not +* reset hif_dmashdl logic) +* dmashdl_all_rst_n[5] - (RW) This dmashdl_all_rst_n would reset +* hif_dmashdl_top, include logic and control register. +* RESERVED6[31..6] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_RST_dmashdl_all_rst_n_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_RST_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_RST_dmashdl_all_rst_n_MASK \ + 0x00000020 /* dmashdl_all_rst_n[5] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_RST_dmashdl_all_rst_n_SHFT 5 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_RST_conn_hif_logic_rst_n_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_RST_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_RST_conn_hif_logic_rst_n_MASK \ + 0x00000010 /* conn_hif_logic_rst_n[4] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_RST_conn_hif_logic_rst_n_SHFT 4 + +/* +* ---CONN_HIF_TOP_MISC (0x18024000 + 0x104)--- +* ahb_mux_2to1_ultra[1..0] - (RW) conn _hif ahb mux ultra +* ahb_mux_2to1_qos_en[2] - (RW) conn_hif ahb mux qos enable +* RESERVED3[15..3] - (RO) Reserved bits +* pdma_rxring1_immint_en[16] - (RW) PDMA RX Ring 1 Immediate Interrupt +Enable +* RESERVED17[31..17] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_pdma_rxring1_immint_en_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_pdma_rxring1_immint_en_MASK \ + 0x00010000 /* pdma_rxring1_immint_en[16] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_pdma_rxring1_immint_en_SHFT 16 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_ahb_mux_2to1_qos_en_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_ahb_mux_2to1_qos_en_MASK \ + 0x00000004 /* ahb_mux_2to1_qos_en[2] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_ahb_mux_2to1_qos_en_SHFT 2 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_ahb_mux_2to1_ultra_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_ahb_mux_2to1_ultra_MASK \ + 0x00000003 /* ahb_mux_2to1_ultra[1..0] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_TOP_MISC_ahb_mux_2to1_ultra_SHFT 0 + +/* +* ---HOST2MCU_SW_INT_SET (0x18024000 + 0X108)--- +* host2mcu_sw_int_0_set[0] - (WO) Driver set this bit to generate MCU +* interrupt and 0x5000_0110[0] will be set to 1. +* host2mcu_sw_int_1_set[1] - (WO) Driver set this bit to generate MCU +* interrupt and 0x5000_0110[1] will be set to 1. +* host2mcu_sw_int_2_set[2] - (WO) Driver set this bit to generate MCU +* interrupt and 0x5000_0110[2] will be set to 1. +* host2mcu_sw_int_3_set[3] - (WO) Driver set [0x0_4108] bit[3] to generate +* MCU interrupt and 0x5000_0110[3] will be set to 1. +* host2mcu_sw_int_4_set[4] - (WO) Driver set [0x0_4108] bit[4] to generate +* MCU interrupt and 0x5000_0110[4] will be set to 1. +* host2mcu_sw_int_5_set[5] - (WO) Driver set [0x0_4108] bit[5] to generate +* MCU interrupt and 0x5000_0110[5] will be set to 1. +* host2mcu_sw_int_6_set[6] - (WO) Driver set [0x0_4108] bit[6] to generate +* MCU interrupt and 0x5000_0110[6] will be set to 1. +* host2mcu_sw_int_7_set[7] - (WO) Driver set [0x0_4108] bit[7] to generate +* MCU interrupt and 0x5000_0110[7] will be set to 1. +* RESERVED8[31..8] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_7_set_ADDR \ + WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_7_set_MASK \ + 0x00000080 /* host2mcu_sw_int_7_set[7] */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_7_set_SHFT 7 +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_6_set_ADDR \ + WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_6_set_MASK \ + 0x00000040 /* host2mcu_sw_int_6_set[6] */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_6_set_SHFT 6 +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_5_set_ADDR \ + WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_5_set_MASK \ + 0x00000020 /* host2mcu_sw_int_5_set[5] */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_5_set_SHFT 5 +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_4_set_ADDR \ + WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_4_set_MASK \ + 0x00000010 /* host2mcu_sw_int_4_set[4] */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_4_set_SHFT 4 +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_3_set_ADDR \ + WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_3_set_MASK \ + 0x00000008 /* host2mcu_sw_int_3_set[3] */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_3_set_SHFT 3 +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_2_set_ADDR \ + WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_2_set_MASK \ + 0x00000004 /* host2mcu_sw_int_2_set[2] */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_2_set_SHFT 2 +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_1_set_ADDR \ + WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_1_set_MASK \ + 0x00000002 /* host2mcu_sw_int_1_set[1] */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_1_set_SHFT 1 +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_0_set_ADDR \ + WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_0_set_MASK \ + 0x00000001 /* host2mcu_sw_int_0_set[0] */ +#define WF_WFDMA_HOST_DMA0_HOST2MCU_SW_INT_SET_host2mcu_sw_int_0_set_SHFT 0 + +/* +* ---MCU2HOST_SW_INT_SET (0x18024000 + 0x10C)--- +* mcu2host_sw_int_set_0[0] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[0] to check +* interrupt status +* mcu2host_sw_int_set_1[1] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[1] to check +* interrupt status +* mcu2host_sw_int_set_2[2] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[2] to check +* interrupt status +* mcu2host_sw_int_set_3[3] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[3] to check +* interrupt status +* mcu2host_sw_int_set_4[4] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[4] to check +* interrupt status +* mcu2host_sw_int_set_5[5] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[5] to check +* interrupt status +* mcu2host_sw_int_set_6[6] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[6] to check +* interrupt status +* mcu2host_sw_int_set_7[7] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[7] to check +* interrupt status +* mcu2host_sw_int_set_8[8] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[0] to check +* interrupt status +* mcu2host_sw_int_set_9[9] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[1] to check +* interrupt status +* mcu2host_sw_int_set_10[10] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[2] to check +* interrupt status +* mcu2host_sw_int_set_11[11] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[3] to check +* interrupt status +* mcu2host_sw_int_set_12[12] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[4] to check +* interrupt status +* mcu2host_sw_int_set_13[13] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[5] to check +* interrupt status +* mcu2host_sw_int_set_14[14] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[6] to check +* interrupt status +* mcu2host_sw_int_set_15[15] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[7] to check +* interrupt status +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_15_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_15_MASK \ + 0x00008000 /* mcu2host_sw_int_set_15[15] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_15_SHFT 15 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_14_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_14_MASK \ + 0x00004000 /* mcu2host_sw_int_set_14[14] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_14_SHFT 14 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_13_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_13_MASK \ + 0x00002000 /* mcu2host_sw_int_set_13[13] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_13_SHFT 13 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_12_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_12_MASK \ + 0x00001000 /* mcu2host_sw_int_set_12[12] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_12_SHFT 12 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_11_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_11_MASK \ + 0x00000800 /* mcu2host_sw_int_set_11[11] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_11_SHFT 11 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_10_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_10_MASK \ + 0x00000400 /* mcu2host_sw_int_set_10[10] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_10_SHFT 10 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_9_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_9_MASK \ + 0x00000200 /* mcu2host_sw_int_set_9[9] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_9_SHFT 9 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_8_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_8_MASK \ + 0x00000100 /* mcu2host_sw_int_set_8[8] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_8_SHFT 8 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_7_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_7_MASK \ + 0x00000080 /* mcu2host_sw_int_set_7[7] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_7_SHFT 7 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_6_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_6_MASK \ + 0x00000040 /* mcu2host_sw_int_set_6[6] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_6_SHFT 6 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_5_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_5_MASK \ + 0x00000020 /* mcu2host_sw_int_set_5[5] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_5_SHFT 5 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_4_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_4_MASK \ + 0x00000010 /* mcu2host_sw_int_set_4[4] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_4_SHFT 4 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_3_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_3_MASK \ + 0x00000008 /* mcu2host_sw_int_set_3[3] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_2_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_2_MASK \ + 0x00000004 /* mcu2host_sw_int_set_2[2] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_1_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_1_MASK \ + 0x00000002 /* mcu2host_sw_int_set_1[1] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_0_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_0_MASK \ + 0x00000001 /* mcu2host_sw_int_set_0[0] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_0_SHFT 0 + +/* +* ---MCU_INT_STA (0x18024000 + 0X110)--- +* host2mcu_sw_int_sts[7..0] - (W1C) MCU interrupt status, write 1 to clear +* the interrupt +* wpdma_tx_timeout_int_sts[8] - (W1C) WPDMA TX dma timeout interrupt stauts, +* write 1 to clear the interrupt +* wpdma_rx_timeout_int_sts[9] - (W1C) WPDMA RX dma timeout interrupt stauts, +* write 1 to clear the interrupt +* wifi_txfifo0_wr_ovf_int_sts[10] - (W1C) conn_hif txfifo erorr detec +* interruptt. It indicate tx-fifo memory write overflow. +* wifi_txfifo1_wr_ovf_int_sts[11] - (W1C) conn_hif txfifo erorr detec +* interruptt. It indicate tx-fifo memory write overflow. +* wifi_rxfifo_wr_ovf_int_sts[12] - (W1C) conn_hif rxfifo erorr detect +* interrupt. It indicate rx-fifo memory write overflow. +* wpdma_tx_dmad_mem_range_err_mcu_int_sts[13] - (W1C) WPDMA tx dma descriptor +* memory range error detection mcu interrupt status +* When user setup WPDMA_TX_DMAD_RNG (not +* equal to zero), design would check tx_dmad address. If address range not +* correct, it would alarm memory range error interrupt +* wpdma_rx_dmad_mem_range_err_mcu_int_sts[14] - (W1C) WPDMA rx dma descriptor +* memory range error detection mcu interrupt status +* When user setup WPDMA_RX_DMAD_RNG (not +* equal to zero), design would check rx_dmad address. If address range not +* correct, it would alarm memory range error interrupt +* wpdma_tx_payload_mem_range_err_mcu_int_sts[15] - (W1C) WPDMA tx payload +* memory range error detection mcu interrupt status +* When user setup WPDMA_TX_PLD_RNG (not equal +* to zero), design would check tx_dma payload address. If address range not +* correct, it would alarm memory range error interrupt +* wpdma_rx_payload_mem_range_err_mcu_int_sts[16] - (W1C) WPDMA rx payload +* memory range error detection mcu interrupt status +* When user setup WPDMA_RX_PLD_RNG (not equal +* to zero), design would check rx_dma payload address. If address range not +* correct, it would alarm memory range error interrupt +* RESERVED17[31..17] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_payload_mem_range_err_mcu_int_sts_ADDR \ + \ + WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_payload_mem_range_err_mcu_int_sts_MASK \ + \ + 0x00010000 /* wpdma_rx_payload_mem_range_err_mcu_int_sts[16] */ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_payload_mem_range_err_mcu_int_sts_SHFT \ + \ + 16 +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_payload_mem_range_err_mcu_int_sts_ADDR \ + \ + WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_payload_mem_range_err_mcu_int_sts_MASK \ + \ + 0x00008000 /* wpdma_tx_payload_mem_range_err_mcu_int_sts[15] */ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_payload_mem_range_err_mcu_int_sts_SHFT \ + \ + 15 +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_dmad_mem_range_err_mcu_int_sts_ADDR \ + \ + WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_dmad_mem_range_err_mcu_int_sts_MASK \ + \ + 0x00004000 /* wpdma_rx_dmad_mem_range_err_mcu_int_sts[14] */ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_dmad_mem_range_err_mcu_int_sts_SHFT \ + \ + 14 +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_dmad_mem_range_err_mcu_int_sts_ADDR \ + \ + WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_dmad_mem_range_err_mcu_int_sts_MASK \ + \ + 0x00002000 /* wpdma_tx_dmad_mem_range_err_mcu_int_sts[13] */ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_dmad_mem_range_err_mcu_int_sts_SHFT \ + \ + 13 +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_rxfifo_wr_ovf_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_rxfifo_wr_ovf_int_sts_MASK \ + 0x00001000 /* wifi_rxfifo_wr_ovf_int_sts[12] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_rxfifo_wr_ovf_int_sts_SHFT 12 +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_txfifo1_wr_ovf_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_txfifo1_wr_ovf_int_sts_MASK \ + 0x00000800 /* wifi_txfifo1_wr_ovf_int_sts[11] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_txfifo1_wr_ovf_int_sts_SHFT 11 +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_txfifo0_wr_ovf_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_txfifo0_wr_ovf_int_sts_MASK \ + 0x00000400 /* wifi_txfifo0_wr_ovf_int_sts[10] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wifi_txfifo0_wr_ovf_int_sts_SHFT 10 +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_timeout_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_timeout_int_sts_MASK \ + 0x00000200 /* wpdma_rx_timeout_int_sts[9] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_rx_timeout_int_sts_SHFT 9 +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_timeout_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_timeout_int_sts_MASK \ + 0x00000100 /* wpdma_tx_timeout_int_sts[8] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_wpdma_tx_timeout_int_sts_SHFT 8 +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_host2mcu_sw_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_host2mcu_sw_int_sts_MASK \ + 0x000000FF /* host2mcu_sw_int_sts[7..0] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_STA_host2mcu_sw_int_sts_SHFT 0 + +/* +* ---MCU_INT_ENA (0x18024000 + 0X114)--- +* host2mcu_sw_int_ena[7..0] - (RW) host2mcu interrupt enable +* wpdma_tx_dma_timeout_int_ena[8] - (RW) WPDMA TX error detection interrupt +enable +* wpdma_rx_dma_timeout_int_ena[9] - (RW) WPDMA RX error detection interrupt +enable +* wifi_txfifo0_wr_ovf_int_ena[10] - (RW) conn_hif txfifo erorr detect +* interrupt enable. +* wifi_txfifo1_wr_ovf_int_ena[11] - (RW) conn_hif txfifo erorr detect +* interrupt enable. +* wifi_rxfifo_wr_ovf_int_ena[12] - (RW) conn_hif rxfifo erorr detect interrupt +enable. +* wpdma_tx_dmad_mem_range_err_mcu_int_ena[13] - (RW) WPDMA tx dma descriptor +* memory range error detection interrupt enable +* wpdma_rx_dmad_mem_range_err_mcu_int_ena[14] - (RW) WPDMA rx dma descriptor +* memory range error detection interrupt enable +* wpdma_tx_payload_mem_range_err_mcu_int_ena[15] - (RW) WPDMA tx payload +* memory range error detection interrupt enable +* wpdma_rx_payload_mem_range_err_mcu_int_ena[16] - (RW) WPDMA rx payload +* memory range error detection interrupt enable +* RESERVED17[31..17] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_payload_mem_range_err_mcu_int_ena_ADDR \ + \ + WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_payload_mem_range_err_mcu_int_ena_MASK \ + \ + 0x00010000 /* wpdma_rx_payload_mem_range_err_mcu_int_ena[16] */ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_payload_mem_range_err_mcu_int_ena_SHFT \ + \ + 16 +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_payload_mem_range_err_mcu_int_ena_ADDR \ + \ + WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_payload_mem_range_err_mcu_int_ena_MASK \ + \ + 0x00008000 /* wpdma_tx_payload_mem_range_err_mcu_int_ena[15] */ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_payload_mem_range_err_mcu_int_ena_SHFT \ + \ + 15 +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_dmad_mem_range_err_mcu_int_ena_ADDR \ + \ + WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_dmad_mem_range_err_mcu_int_ena_MASK \ + \ + 0x00004000 /* wpdma_rx_dmad_mem_range_err_mcu_int_ena[14] */ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_dmad_mem_range_err_mcu_int_ena_SHFT \ + \ + 14 +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_dmad_mem_range_err_mcu_int_ena_ADDR \ + \ + WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_dmad_mem_range_err_mcu_int_ena_MASK \ + \ + 0x00002000 /* wpdma_tx_dmad_mem_range_err_mcu_int_ena[13] */ +#define \ +WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_dmad_mem_range_err_mcu_int_ena_SHFT \ + \ + 13 +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_rxfifo_wr_ovf_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_rxfifo_wr_ovf_int_ena_MASK \ + 0x00001000 /* wifi_rxfifo_wr_ovf_int_ena[12] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_rxfifo_wr_ovf_int_ena_SHFT 12 +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_txfifo1_wr_ovf_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_txfifo1_wr_ovf_int_ena_MASK \ + 0x00000800 /* wifi_txfifo1_wr_ovf_int_ena[11] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_txfifo1_wr_ovf_int_ena_SHFT 11 +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_txfifo0_wr_ovf_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_txfifo0_wr_ovf_int_ena_MASK \ + 0x00000400 /* wifi_txfifo0_wr_ovf_int_ena[10] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wifi_txfifo0_wr_ovf_int_ena_SHFT 10 +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_dma_timeout_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_dma_timeout_int_ena_MASK \ + 0x00000200 /* wpdma_rx_dma_timeout_int_ena[9] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_rx_dma_timeout_int_ena_SHFT 9 +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_dma_timeout_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_dma_timeout_int_ena_MASK \ + 0x00000100 /* wpdma_tx_dma_timeout_int_ena[8] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_wpdma_tx_dma_timeout_int_ena_SHFT 8 +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_host2mcu_sw_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_host2mcu_sw_int_ena_MASK \ + 0x000000FF /* host2mcu_sw_int_ena[7..0] */ +#define WF_WFDMA_HOST_DMA0_MCU_INT_ENA_host2mcu_sw_int_ena_SHFT 0 + +/* +* ---CONN_HIF_DUMMY (0x18024000 + 0x120)--- +* CONN_HIF_DUMMY[31..0] - (RW) Reserved CR, SE will use it for pcie +calibration! +*/ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DUMMY_CONN_HIF_DUMMY_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_DUMMY_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DUMMY_CONN_HIF_DUMMY_MASK \ + 0xFFFFFFFF /* CONN_HIF_DUMMY[31..0] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DUMMY_CONN_HIF_DUMMY_SHFT 0 + +/* +* ---WPDMA_DBG_IDX (0x18024000 + 0x124)--- +* PDMA_DBG_IDX[7..0] - (RW) PDMA debug index +* PDMA_DBG_Enable[8] - (RW) PDMA Debug Enable +* 0: PDMA_DBG_port would has no function +* 1 : PDMA DBG_IDX select PDMA debug flag +index +* RESERVED9[31..9] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_PDMA_DBG_Enable_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_PDMA_DBG_Enable_MASK \ + 0x00000100 /* PDMA_DBG_Enable[8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_PDMA_DBG_Enable_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_PDMA_DBG_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_PDMA_DBG_IDX_MASK \ + 0x000000FF /* PDMA_DBG_IDX[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_IDX_PDMA_DBG_IDX_SHFT 0 + +/* +* ---WPDMA_DBG_PROBE (0x18024000 + 0x128)--- +* PDMA_DBG_PROBE[31..0] - (RO) PDMA Debug probe read +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_PROBE_PDMA_DBG_PROBE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_DBG_PROBE_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_PROBE_PDMA_DBG_PROBE_MASK \ + 0xFFFFFFFF /* PDMA_DBG_PROBE[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_DBG_PROBE_PDMA_DBG_PROBE_SHFT 0 + +/* +* ---CONN_HIF_DBG_IDX (0x18024000 + 0x12C)--- +* conn_hif_dbg_byt0_sel[2..0] - (RW) conn_hif_dbg_byt0_sel : Select +* conn_hif_dbg[7:0] from "pdma_dbg"/"hif_dmashdl_top" +* conn_hif_dbg_byt1_sel[5..3] - (RW) conn_hif_dbg_byt1_sel : Select +* conn_hif_dbg[15:8] from "pdma_dbg"/"hif_dmashdl_top" +* conn_hif_dbg_byt2_sel[8..6] - (RW) conn_hif_dbg_byt2_sel : Select +* conn_hif_dbg[23:16] from "pdma_dbg"/"hif_dmashdl_top" +* conn_hif_dbg_byt3_sel[11..9] - (RW) conn_hif_dbg_byt3_sel : Select +* conn_hif_dbg[31:24] from "pdma_dbg"/"hif_dmashdl_top" +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt3_sel_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt3_sel_MASK \ + 0x00000E00 /* conn_hif_dbg_byt3_sel[11..9] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt3_sel_SHFT 9 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt2_sel_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt2_sel_MASK \ + 0x000001C0 /* conn_hif_dbg_byt2_sel[8..6] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt2_sel_SHFT 6 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt1_sel_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt1_sel_MASK \ + 0x00000038 /* conn_hif_dbg_byt1_sel[5..3] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt1_sel_SHFT 3 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt0_sel_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt0_sel_MASK \ + 0x00000007 /* conn_hif_dbg_byt0_sel[2..0] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_IDX_conn_hif_dbg_byt0_sel_SHFT 0 + +/* +* ---CONN_HIF_DBG_PROBE (0x18024000 + 0x130)--- +* conn_hif_dbg_probe[31..0] - (RO) conn_hif_dbg_probe read +*/ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_PROBE_conn_hif_dbg_probe_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_PROBE_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_PROBE_conn_hif_dbg_probe_MASK \ + 0xFFFFFFFF /* conn_hif_dbg_probe[31..0] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DBG_PROBE_conn_hif_dbg_probe_SHFT 0 + +/* +* ---CONN_HIF_DMASHDL_DBG_PROBE (0x18024000 + 0x134)--- +* DMASHDL_DBG_PROBE[15..0] - (RO) conn_hif_dmashdl_dbg_probe read +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DMASHDL_DBG_PROBE_DMASHDL_DBG_PROBE_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_DMASHDL_DBG_PROBE_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DMASHDL_DBG_PROBE_DMASHDL_DBG_PROBE_MASK \ + 0x0000FFFF /* DMASHDL_DBG_PROBE[15..0] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_DMASHDL_DBG_PROBE_DMASHDL_DBG_PROBE_SHFT 0 + +/* +* ---CONN_HIF_BUSY_STATUS (0x18024000 + 0x138)--- +* conn_hif_txfifo0_busy[0] - (RO) conn_hif txfifo0 busy status +* 0 : txfifo empty +* 1 : txfifo non empty +* conn_hif_txfifo1_busy[1] - (RO) conn_hif txfifo1 busy status +* 0 : txfifo empty +* 1 : txfifo non empty +* conn_hif_rxfifo_busy[2] - (RO) conn_hif rxfifo busy status +* 0 : rxfifo empty +* 1 : rxfifo non empty +* RESERVED[30..3] - (RO) Reserved CR +* conn_hif_busy[31] - (RO) Over all conn_hif busy status, it was +* busy summation of bit[6] ~ bit[0] status +*/ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_busy_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_busy_MASK \ + 0x80000000 /* conn_hif_busy[31] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_busy_SHFT 31 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_rxfifo_busy_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_rxfifo_busy_MASK \ + 0x00000004 /* conn_hif_rxfifo_busy[2] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_rxfifo_busy_SHFT 2 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_txfifo1_busy_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_txfifo1_busy_MASK \ + 0x00000002 /* conn_hif_txfifo1_busy[1] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_txfifo1_busy_SHFT 1 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_txfifo0_busy_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_txfifo0_busy_MASK \ + 0x00000001 /* conn_hif_txfifo0_busy[0] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_STATUS_conn_hif_txfifo0_busy_SHFT 0 + +/* +* ---CONN_HIF_BUSY_ENA (0x18024000 + 0x13c)--- +* conn_hif_txfifo0_busy_enable[0] - (RW) busy enable control +* 0: ignore busy status +* 1: conn_hif_busy would tack care busy +status +* conn_hif_txfifo1_busy_enable[1] - (RW) busy enable control +* 0: ignore busy status +* 1: conn_hif_busy would tack care busy +status +* conn_hif_rxfifo_busy_enable[2] - (RW) busy enable control +* 0: ignore busy status +* 1: conn_hif_busy would tack care busy +status +* RESERVED3[4..3] - (RO) Reserved bits +* RESERVED[31..5] - (RW) Reserved CR +*/ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_rxfifo_busy_enable_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_rxfifo_busy_enable_MASK \ + 0x00000004 /* conn_hif_rxfifo_busy_enable[2] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_rxfifo_busy_enable_SHFT 2 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_txfifo1_busy_enable_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_txfifo1_busy_enable_MASK \ + 0x00000002 /* conn_hif_txfifo1_busy_enable[1] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_txfifo1_busy_enable_SHFT 1 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_txfifo0_busy_enable_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_txfifo0_busy_enable_MASK \ + 0x00000001 /* conn_hif_txfifo0_busy_enable[0] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_BUSY_ENA_conn_hif_txfifo0_busy_enable_SHFT 0 + +/* +* ---CONN_HIF_FIFO_TEST_MOD (0x18024000 + 0x140)--- +* csr_wfdma_loopback_en[0] - (RW) conn_hif fifo loopback enable +* NOTICE : when loopback, OMIT_TX_INFO and +* OMIT_RX_INFO sould be both set to 1'b1 +* csr_wfdma_loopback_qsel[2..1] - (RW) No USE for (conn_hif fifo loopback +* packet go into Rx-ring number) +* RESERVED3[31..3] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_qsel_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_qsel_MASK \ + 0x00000006 /* csr_wfdma_loopback_qsel[2..1] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_qsel_SHFT 1 +#define WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_en_ADDR \ + WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_ADDR +#define WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_en_MASK \ + 0x00000001 /* csr_wfdma_loopback_en[0] */ +#define WF_WFDMA_HOST_DMA0_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_en_SHFT 0 + +/* +* ---WPDMA2HOST_ERR_INT_STA (0x18024000 + 0x1E8)--- +* wpdma_tx_timeout_int_sts[0] - (W1C) WPDMA TX error detection interrupt +* stauts, write 1 to clear the interrupt +* wpdma_rx_timeout_int_sts[1] - (W1C) WPDMA RX error detection interrupt +* stauts, write 1 to clear the interrupt +* RESERVED2[31..2] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_rx_timeout_int_sts_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_rx_timeout_int_sts_MASK \ + \ + 0x00000002 /* wpdma_rx_timeout_int_sts[1] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_rx_timeout_int_sts_SHFT \ + \ + 1 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_tx_timeout_int_sts_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_tx_timeout_int_sts_MASK \ + \ + 0x00000001 /* wpdma_tx_timeout_int_sts[0] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_STA_wpdma_tx_timeout_int_sts_SHFT \ + \ + 0 + +/* +* ---WPDMA2HOST_ERR_INT_ENA (0x18024000 + 0x1EC)--- +* wpdma_rx_timeout_int_ena[0] - (RW) WPDMA TX error detection interrupt +enable +* wpdma_tx_timeout_int_ena[1] - (RW) WPDMA RX error detection interrupt +enable +* RESERVED2[31..2] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_timeout_int_ena_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_timeout_int_ena_MASK \ + \ + 0x00000002 /* wpdma_tx_timeout_int_ena[1] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_timeout_int_ena_SHFT \ + \ + 1 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_timeout_int_ena_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_timeout_int_ena_MASK \ + \ + 0x00000001 /* wpdma_rx_timeout_int_ena[0] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_timeout_int_ena_SHFT \ + \ + 0 + +/* +* ---MCU2HOST_SW_INT_STA (0x18024000 + 0x1F0)--- +* mcu2host_sw_int_0[0] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_1[1] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_2[2] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_3[3] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_4[4] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_5[5] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_6[6] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_7[7] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_8[8] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_9[9] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_10[10] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_11[11] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_12[12] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_13[13] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_14[14] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_15[15] - (W1C) mcu2host interrupt status +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_15_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_15_MASK \ + 0x00008000 /* mcu2host_sw_int_15[15] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_15_SHFT 15 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_14_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_14_MASK \ + 0x00004000 /* mcu2host_sw_int_14[14] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_14_SHFT 14 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_13_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_13_MASK \ + 0x00002000 /* mcu2host_sw_int_13[13] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_13_SHFT 13 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_12_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_12_MASK \ + 0x00001000 /* mcu2host_sw_int_12[12] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_12_SHFT 12 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_11_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_11_MASK \ + 0x00000800 /* mcu2host_sw_int_11[11] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_11_SHFT 11 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_10_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_10_MASK \ + 0x00000400 /* mcu2host_sw_int_10[10] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_10_SHFT 10 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_9_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_9_MASK \ + 0x00000200 /* mcu2host_sw_int_9[9] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_9_SHFT 9 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_8_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_8_MASK \ + 0x00000100 /* mcu2host_sw_int_8[8] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_8_SHFT 8 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_7_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_7_MASK \ + 0x00000080 /* mcu2host_sw_int_7[7] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_7_SHFT 7 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_6_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_6_MASK \ + 0x00000040 /* mcu2host_sw_int_6[6] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_6_SHFT 6 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_5_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_5_MASK \ + 0x00000020 /* mcu2host_sw_int_5[5] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_5_SHFT 5 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_4_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_4_MASK \ + 0x00000010 /* mcu2host_sw_int_4[4] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_4_SHFT 4 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_3_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_3_MASK \ + 0x00000008 /* mcu2host_sw_int_3[3] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_2_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_2_MASK \ + 0x00000004 /* mcu2host_sw_int_2[2] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_1_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_1_MASK \ + 0x00000002 /* mcu2host_sw_int_1[1] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_0_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_0_MASK \ + 0x00000001 /* mcu2host_sw_int_0[0] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_STA_mcu2host_sw_int_0_SHFT 0 + +/* +* ---MCU2HOST_SW_INT_ENA (0x18024000 + 0x1F4)--- +* mcu2host_int_ena_0[0] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_1[1] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_2[2] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_3[3] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_4[4] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_5[5] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_6[6] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_7[7] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_8[8] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_9[9] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_10[10] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_11[11] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_12[12] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_13[13] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_14[14] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_15[15] - (RW) MCU2HOST software interrupt interrupt +enable +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_15_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_15_MASK \ + 0x00008000 /* mcu2host_int_ena_15[15] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_15_SHFT 15 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_14_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_14_MASK \ + 0x00004000 /* mcu2host_int_ena_14[14] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_14_SHFT 14 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_13_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_13_MASK \ + 0x00002000 /* mcu2host_int_ena_13[13] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_13_SHFT 13 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_12_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_12_MASK \ + 0x00001000 /* mcu2host_int_ena_12[12] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_12_SHFT 12 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_11_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_11_MASK \ + 0x00000800 /* mcu2host_int_ena_11[11] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_11_SHFT 11 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_10_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_10_MASK \ + 0x00000400 /* mcu2host_int_ena_10[10] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_10_SHFT 10 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_9_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_9_MASK \ + 0x00000200 /* mcu2host_int_ena_9[9] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_9_SHFT 9 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_8_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_8_MASK \ + 0x00000100 /* mcu2host_int_ena_8[8] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_8_SHFT 8 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_7_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_7_MASK \ + 0x00000080 /* mcu2host_int_ena_7[7] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_7_SHFT 7 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_6_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_6_MASK \ + 0x00000040 /* mcu2host_int_ena_6[6] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_6_SHFT 6 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_5_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_5_MASK \ + 0x00000020 /* mcu2host_int_ena_5[5] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_5_SHFT 5 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_4_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_4_MASK \ + 0x00000010 /* mcu2host_int_ena_4[4] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_4_SHFT 4 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_3_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_3_MASK \ + 0x00000008 /* mcu2host_int_ena_3[3] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_2_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_2_MASK \ + 0x00000004 /* mcu2host_int_ena_2[2] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_1_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_1_MASK \ + 0x00000002 /* mcu2host_int_ena_1[1] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_0_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_0_MASK \ + 0x00000001 /* mcu2host_int_ena_0[0] */ +#define WF_WFDMA_HOST_DMA0_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_0_SHFT 0 + +/* +* ---SUBSYS2HOST_INT_STA (0x18024000 + 0x1F8)--- +* mac_int_sts_0[0] - (RO) MAC interrupt 0: TBTT interrupt(Check +* wf_int_wakeup_top/hwisr0 [0x820Fc03c]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_1[1] - (RO) MAC interrupt 1: Pre-TBTT +* interrupt(Check wf_int_wakeup_top/hwisr1 [0x820Fc044]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_2[2] - (RO) MAC interrupt 2: TX status +* interrupt(Check wf_int_wakeup_top/hwisr2 [0x820Fc04c]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_3[3] - (RO) MAC interrupt 3: Auto wakeup interrupt +* (Check wf_int_wakeup_top/hwisr3 [0x820Fc054]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_4[4] - (RO) MAC interrupt 4: GP timer interrupt +* (Check wf_int_wakeup_top/hwisr4 [0x820Fc05c]) +* 0 : no interrupt +* 1 : interrupt assert +* RESERVED5[7..5] - (RO) Reserved bits +* conn_hif_on_host_int_sts[8] - (RO) CONN_HIF_ON interrupt enable +* 0 : no conn_hif_on_host_int interrupt +* 1 : conn_hif_on_host_int interrupt assert. +* User should check conn_hif_on (host_csr) interrupt status and clear interrupt. +* conn2ap_sw_irq_sts[9] - (RO) MCUSYS conn2ap_sw_irq status (Check +* conn_mcu_config/EMI_CTL [0x80000150] bit[4:0]) +* 0 : no conn2ap_sw_irq interrupt. +* 1 : conn2ap_sw_irq interrupt assert. User +* should check mcusys_n9 interrupt status and clear interrupt. +* (conn_mcu_config/EMI_CTL [0x80000150] bit[4:0] != 0) +* RESERVED10[31..10] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_conn2ap_sw_irq_sts_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_conn2ap_sw_irq_sts_MASK \ + 0x00000200 /* conn2ap_sw_irq_sts[9] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_conn2ap_sw_irq_sts_SHFT 9 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_conn_hif_on_host_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_conn_hif_on_host_int_sts_MASK \ + 0x00000100 /* conn_hif_on_host_int_sts[8] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_conn_hif_on_host_int_sts_SHFT 8 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_4_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_4_MASK \ + 0x00000010 /* mac_int_sts_4[4] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_4_SHFT 4 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_3_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_3_MASK \ + 0x00000008 /* mac_int_sts_3[3] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_2_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_2_MASK \ + 0x00000004 /* mac_int_sts_2[2] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_1_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_1_MASK \ + 0x00000002 /* mac_int_sts_1[1] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_0_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_0_MASK \ + 0x00000001 /* mac_int_sts_0[0] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_STA_mac_int_sts_0_SHFT 0 + +/* +* ---SUBSYS2HOST_INT_ENA (0x18024000 + 0x1FC)--- +* mac_int_ena_0[0] - (RW) MAC interrupt enable +* mac_int_ena_1[1] - (RW) MAC interrupt enable +* mac_int_ena_2[2] - (RW) MAC interrupt enable +* mac_int_ena_3[3] - (RW) MAC interrupt enable +* mac_int_ena_4[4] - (RW) MAC interrupt enable +* RESERVED5[7..5] - (RO) Reserved bits +* conn_hif_on_host_int_ena[8] - (RW) CONN_HIF_ON interrupt enable +* conn2ap_sw_irq_ena[9] - (RW) MCUSYS conn2ap_sw_irq enable +* dmashdl_int_ena[10] - (RW) DMASHDL interrupt enable +* mac_int_ena_5[11] - (RW) MAC interrupt enable +* mac_int_ena_6[12] - (RW) MAC interrupt enable +* mac_int_ena_7[13] - (RW) MAC interrupt enable +* mac_int_ena_8[14] - (RW) MAC interrupt enable +* mac_int_ena_9[15] - (RW) MAC interrupt enable +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_9_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_9_MASK \ + 0x00008000 /* mac_int_ena_9[15] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_9_SHFT 15 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_8_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_8_MASK \ + 0x00004000 /* mac_int_ena_8[14] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_8_SHFT 14 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_7_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_7_MASK \ + 0x00002000 /* mac_int_ena_7[13] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_7_SHFT 13 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_6_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_6_MASK \ + 0x00001000 /* mac_int_ena_6[12] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_6_SHFT 12 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_5_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_5_MASK \ + 0x00000800 /* mac_int_ena_5[11] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_5_SHFT 11 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_dmashdl_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_dmashdl_int_ena_MASK \ + 0x00000400 /* dmashdl_int_ena[10] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_dmashdl_int_ena_SHFT 10 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_conn2ap_sw_irq_ena_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_conn2ap_sw_irq_ena_MASK \ + 0x00000200 /* conn2ap_sw_irq_ena[9] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_conn2ap_sw_irq_ena_SHFT 9 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_conn_hif_on_host_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_conn_hif_on_host_int_ena_MASK \ + 0x00000100 /* conn_hif_on_host_int_ena[8] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_conn_hif_on_host_int_ena_SHFT 8 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_4_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_4_MASK \ + 0x00000010 /* mac_int_ena_4[4] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_4_SHFT 4 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_3_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_3_MASK \ + 0x00000008 /* mac_int_ena_3[3] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_2_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_2_MASK \ + 0x00000004 /* mac_int_ena_2[2] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_1_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_1_MASK \ + 0x00000002 /* mac_int_ena_1[1] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_0_ADDR \ + WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_0_MASK \ + 0x00000001 /* mac_int_ena_0[0] */ +#define WF_WFDMA_HOST_DMA0_SUBSYS2HOST_INT_ENA_mac_int_ena_0_SHFT 0 + +/* +* ---HOST_INT_STA (0x18024000 + 0x200)--- +* rx_done_int_sts_0[0] - (W1C) RX Queue#0 packet receive interrupt +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* rx_done_int_sts_1[1] - (W1C) RX Queue#1 packet receive interrupt +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* rx_done_int_sts_2[2] - (W1C) RX Queue#2 packet receive interrupt +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* rx_done_int_sts_3[3] - (W1C) RX Queue#3 packet receive interrupt +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* tx_done_int_sts_0[4] - (W1C) TX Queue#0 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_1[5] - (W1C) TX Queue#1 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_2[6] - (W1C) TX Queue#2 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_3[7] - (W1C) TX Queue#3 packet transmit interrupt +* Write 1 to clear the interrupt +* RESERVED8[18..8] - (RO) Reserved bits +* rx_done_int_sts_6[19] - (W1C) RX Queue#6 packet receive interrupt +* Write 1 to clear the interrupt Read to get the raw interrupt status +* rx_coherent_int_sts[20] - (W1C) RX_DMA finds data coherent event when +* checking ddone bit +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* tx_coherent_int_sts[21] - (W1C) TX_DMA finds data coherent event when +* checking ddone bit +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* rx_done_int_sts_4[22] - (W1C) RX Queue#4 packet receive interrupt +* Write 1 to clear the interrupt Read to get the raw interrupt status +* rx_done_int_sts_5[23] - (W1C) RX Queue#5 packet receive interrupt +* Write 1 to clear the interrupt Read to get the raw interrupt status +* wpdma2host_err_int_sts[24] - (RO) wpdma interrupt overall status +* User should should check WPDMA_ERR_INT_STA +* for each wpdma error interrupt status +* Host could read [0x0_41E8] to check +* indivisual wpdma2host_error interrupt status +* rx_done_int_sts_7[25] - (W1C) RX Queue#7 packet receive interrupt +* Write 1 to clear the interrupt Read to get the raw interrupt status +* RESERVED26[27..26] - (RO) Reserved bits +* subsys_int_sts[28] - (RO) subsys interrupt overall status +* User should should check +* SUBSYS2HOST_INT_STA for each interrupt status +* Host could read [0x0_41F8] to check +* indivisual subsys hw interrupt status +* mcu2host_sw_int_sts[29] - (RO) subsys interrupt overall status +* User should should check +* SUBSYS2HOST_INT_STA for each interrupt status +* Host could read [0x0_41F8] to check +* indivisual subsys hw interrupt status +* RESERVED30[31..30] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_mcu2host_sw_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_mcu2host_sw_int_sts_MASK \ + 0x20000000 /* mcu2host_sw_int_sts[29] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_mcu2host_sw_int_sts_SHFT 29 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_subsys_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_subsys_int_sts_MASK \ + 0x10000000 /* subsys_int_sts[28] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_subsys_int_sts_SHFT 28 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_7_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_7_MASK \ + 0x02000000 /* rx_done_int_sts_7[25] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_7_SHFT 25 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_wpdma2host_err_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_wpdma2host_err_int_sts_MASK \ + 0x01000000 /* wpdma2host_err_int_sts[24] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_wpdma2host_err_int_sts_SHFT 24 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_5_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_5_MASK \ + 0x00800000 /* rx_done_int_sts_5[23] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_5_SHFT 23 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_4_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_4_MASK \ + 0x00400000 /* rx_done_int_sts_4[22] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_4_SHFT 22 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_coherent_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_coherent_int_sts_MASK \ + 0x00200000 /* tx_coherent_int_sts[21] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_coherent_int_sts_SHFT 21 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_coherent_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_coherent_int_sts_MASK \ + 0x00100000 /* rx_coherent_int_sts[20] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_coherent_int_sts_SHFT 20 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_6_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_6_MASK \ + 0x00080000 /* rx_done_int_sts_6[19] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_6_SHFT 19 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_3_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_3_MASK \ + 0x00000080 /* tx_done_int_sts_3[7] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_3_SHFT 7 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_2_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_2_MASK \ + 0x00000040 /* tx_done_int_sts_2[6] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_2_SHFT 6 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_1_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_1_MASK \ + 0x00000020 /* tx_done_int_sts_1[5] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_1_SHFT 5 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_0_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_0_MASK \ + 0x00000010 /* tx_done_int_sts_0[4] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_tx_done_int_sts_0_SHFT 4 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_3_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_3_MASK \ + 0x00000008 /* rx_done_int_sts_3[3] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_2_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_2_MASK \ + 0x00000004 /* rx_done_int_sts_2[2] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_1_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_1_MASK \ + 0x00000002 /* rx_done_int_sts_1[1] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_0_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_0_MASK \ + 0x00000001 /* rx_done_int_sts_0[0] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_rx_done_int_sts_0_SHFT 0 + +/* +* ---HOST_INT_ENA (0x18024000 + 0X204)--- +* HOST_RX_DONE_INT_ENA0[0] - (RW) RX Queue#0 packet receive interrupt +* HOST_RX_DONE_INT_ENA1[1] - (RW) RX Queue#1 packet receive interrupt +* HOST_RX_DONE_INT_ENA2[2] - (RW) RX Queue#2 packet receive interrupt +* HOST_RX_DONE_INT_ENA3[3] - (RW) RX Queue#3 packet receive interrupt +* HOST_TX_DONE_INT_ENA0[4] - (RW) TX Queue#0 packet transmit interrupt +* HOST_TX_DONE_INT_ENA1[5] - (RW) TX Queue#1 packet transmit interrupt +* HOST_TX_DONE_INT_ENA2[6] - (RW) TX Queue#2 packet transmit interrupt +* HOST_TX_DONE_INT_ENA3[7] - (RW) TX Queue#3 packet transmit interrupt +* RESERVED8[18..8] - (RO) Reserved bits +* HOST_RX_DONE_INT_ENA6[19] - (RW) RX Queue#6 packet receive interrupt +* HOST_RX_COHERENT_EN[20] - (RW) Enable for RX_DMA data coherent +interrupt +* HOST_TX_COHERENT_EN[21] - (RW) Enable for TX_DMA data coherent +interrupt +* HOST_RX_DONE_INT_ENA4[22] - (RW) RX Queue#4 packet receive interrupt +* HOST_RX_DONE_INT_ENA5[23] - (RW) RX Queue#5 packet receive interrupt +* wpdma2host_err_int_ena[24] - (RW) Enable bit of wpdma2host_err_int +* HOST_RX_DONE_INT_ENA7[25] - (RW) RX Queue#7 packet receive interrupt +* RESERVED26[27..26] - (RO) Reserved bits +* subsys_int_ena[28] - (RW) Enable bit of subsys_int +* mcu2host_sw_int_ena[29] - (RW) Enable bit of mcu2host_sw_int +* RESERVED30[31..30] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_mcu2host_sw_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_mcu2host_sw_int_ena_MASK \ + 0x20000000 /* mcu2host_sw_int_ena[29] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_mcu2host_sw_int_ena_SHFT 29 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_subsys_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_subsys_int_ena_MASK \ + 0x10000000 /* subsys_int_ena[28] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_subsys_int_ena_SHFT 28 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA7_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA7_MASK \ + 0x02000000 /* HOST_RX_DONE_INT_ENA7[25] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA7_SHFT 25 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_wpdma2host_err_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_wpdma2host_err_int_ena_MASK \ + 0x01000000 /* wpdma2host_err_int_ena[24] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_wpdma2host_err_int_ena_SHFT 24 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA5_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA5_MASK \ + 0x00800000 /* HOST_RX_DONE_INT_ENA5[23] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA5_SHFT 23 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA4_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA4_MASK \ + 0x00400000 /* HOST_RX_DONE_INT_ENA4[22] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA4_SHFT 22 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_COHERENT_EN_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_COHERENT_EN_MASK \ + 0x00200000 /* HOST_TX_COHERENT_EN[21] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_COHERENT_EN_SHFT 21 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_COHERENT_EN_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_COHERENT_EN_MASK \ + 0x00100000 /* HOST_RX_COHERENT_EN[20] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_COHERENT_EN_SHFT 20 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA6_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA6_MASK \ + 0x00080000 /* HOST_RX_DONE_INT_ENA6[19] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA6_SHFT 19 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA3_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA3_MASK \ + 0x00000080 /* HOST_TX_DONE_INT_ENA3[7] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA3_SHFT 7 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA2_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA2_MASK \ + 0x00000040 /* HOST_TX_DONE_INT_ENA2[6] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA2_SHFT 6 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA1_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA1_MASK \ + 0x00000020 /* HOST_TX_DONE_INT_ENA1[5] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA1_SHFT 5 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA0_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA0_MASK \ + 0x00000010 /* HOST_TX_DONE_INT_ENA0[4] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_TX_DONE_INT_ENA0_SHFT 4 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA3_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA3_MASK \ + 0x00000008 /* HOST_RX_DONE_INT_ENA3[3] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA2_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA2_MASK \ + 0x00000004 /* HOST_RX_DONE_INT_ENA2[2] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA1_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA1_MASK \ + 0x00000002 /* HOST_RX_DONE_INT_ENA1[1] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA0_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA0_MASK \ + 0x00000001 /* HOST_RX_DONE_INT_ENA0[0] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_HOST_RX_DONE_INT_ENA0_SHFT 0 + +/* +* ---WPDMA_GLO_CFG (0x18024000 + 0x208)--- +* TX_DMA_EN[0] - (RW) TX_DMA Enable +* 1: Enable TX_DMA, MUST wait until all +* prefetch rings' MAX_CNT(WPDMA_T(R)X_RING*_EXT_CTRL) of DMA including neighbor +* DMA have been configured successfully +* 0: Disable TX_DMA +* TX_DMA_BUSY[1] - (RO) TX_DMA Busy indicator +* 1: TX_DMA is busy +* 0: TX_DMA is not busy +* RX_DMA_EN[2] - (RW) RX_DMA Enable +* 1: Enable RX_DMA, MUST wait until all +* prefetch rings' MAX_CNT(WPDMA_T(R)X_RING*_EXT_CTRL) of DMA including neighbor +* DMA have been configured successfully +* 0: Disable RX_DMA +* RX_DMA_BUSY[3] - (RO) RX_DMA Busy indicator +* 1: RX_DMA is busy +* 0: RX_DMA is not busy +* PDMA_BT_SIZE[5..4] - (RW) Define the burst size of WPDMA +* 2'h0 : 4 DWORD (16bytes) +* 2'h1 : 8 DWORD (32 bytes) +* 2'h2 : 16 DWORD (64 bytes) +* 2'h3 : 32 DWORD (128 bytes) +* TX_WB_DDONE[6] - (RW) 1'b1 : TX engine will wait to assert IRQ +* util whole TX dmad has been fully written into AXI bus which represents HOST +* memory, 1'b0 : TX engine will assert IRQ once TX dmad write-back request have +* been ACKed +* BIG_ENDIAN[7] - (RW) The endian mode selection. DMA applies +* the endian rule to convert payload and TX/RX information. DMA won't apply +* endian rule to register or descriptor. +* 1: big endian. +* 0: little endian. +* DMAD_32B_EN[8] - (RW) DMA Descriptor 32-byte Enable +* 0: The size of descriptors is set to 16-byte +* 1: The size of descriptors is set to 32-byte +* FW_DWLD_Bypass_dmashdl[9] - (RW) No USE for (APSOC/PCIE) +* For firmware download packet, driver shold using tx-ring16 to download packet +* and set this bit to bypass dmashdl resource control. +* After firmware download finish, driver should clear this bit. +* After all, tx-ring16 could be used for normal data operation. +(USB) +* For USB test_mode, user could set this bit to bypass dmashdl with all endpoint +* CSR_WFDMA_DUMMY_REG[10] - (RW) dummy CR for use if ECO needed +* CSR_AXI_BUFRDY_BYP[11] - (RW) to disable read data fifo available +* checking before issuing next AXI read request +* FIFO_LITTLE_ENDIAN[12] - (RW) Determines the endianness of the FIFO side +* 0: Big-endian +* 1: Little-endian +* CSR_RX_WB_DDONE[13] - (RW) 1'b1 : RX engine will wait to assert IRQ +* util whole RX dmad has been fully written into AXI bus which represents HOST +* memory, 1'b0 : RX engine will assert IRQ once RX dmad write-back request have +* been ACKed +* CSR_PP_HIF_TXP_ACTIVE_EN[14] - (RW) 1'b1 : enable legacy pp_hif_txp_active +* function to lock tx engine for favor TXP transmit requested directly from PP, +* other pdma TX rings request will be masked until pp_hif_txp_active is +deasserted +* 1'b0 : disable legacy pp_hif_txp_active function, use latest TX source QoS +* design to change throttler settings to favor TXP transmit! +* CSR_DISP_BASE_PTR_CHAIN_EN[15] - (RW) Enable prefet sram ring address +* arrangement by hardware chain structure(DMA#N TX ring group -> DMA#N RX ring +* group -> DMA#M TX ring group -> DMA#M RX ring group and son on). If not +* enabled, firmware need to program DISP_BASE_PTR of WPDMA_T(R)X_RING*_EXT_CTRL +instead!! +*CSR_LBK_RX_Q_SEL[18..16] - (RW) loopback data from TXFIFO will be direct to +* this RX ring when CSR_LBK_RX_Q_SEL_EN in loopback mode, valid bit-width is +* equal to RX_RING_WIDTH which can be calculated from WPDMA_INFO 0x284[15:8] +RX_RING_NUMBER +* RESERVED19[19] - (RO) Reserved bits +* CSR_LBK_RX_Q_SEL_EN[20] - (RW) Force configured CSR_LBK_RX_Q_SEL to +* receive loopback data from TXFIFO +* RESERVED21[23..21] - (RO) Reserved bits +* CSR_SW_RST[24] - (RO) SW reset all designs (To be tested for SER in the +future) +* FORCE_TX_EOF[25] - (RW) Force to send an eof after PDMA being reset (for +Packet_Processor) +* 0: Disabled +* 1: Enabled +* PDMA_ADDR_EXT_EN[26] - (RW) No Fnction for now!! For PDMA Address 32bits +* extension. When this design option was enable. PDMA would change Tx/Rx +* descriptor format for address extension. +* 0 : PDMA 32bits address +* 1 : PDMA Tx descirptor DW3 (TXINFO) would used to extend address +* PDMA Rx descirpt DW2 (Reserved) would used to extend address. +* OMIT_RX_INFO[27] - (RW) For loopback mode, set to 1'b1. +* For normal wifi data operation. User should not set this option and should +* keep 1'b0 because UMAC will always add extra QW for checksum after received +* packet's laster QW +* VERY IMPORTANT : for cpu_dma0/1 where CR +* resides in 0x5100_0xxx, OMIT_RX_INFO MUST be set to 1'b1 +* Omit rx_info of all RX packets +* 0: All the PX packets should end with a rx_info +* 1: All the PX packets should NOT end with a rx_info but an eof +* OMIT_TX_INFO[28] - (RW) For loopback mode, set to 1'b1. +* For normal wifi data operation. User should +* set this option to +* Omit tx_info of all TX packets because UMAC +* design not support TXINFO +* 0: The tx_info in DMAD will be sent at the beginning +* 1: The tx_info in DMAD will NOT be sent at the beginning +* BYTE_SWAP[29] - (RW) Byte Swapping for TX/RX DMAD +* 0: Not to swap (Endian of DMAD unchanged) +* 1: Swap (Endian of DMAD reversed) +* CLK_GATE_DIS[30] - (RW) PDMA Clock Gated Function Disable +* 0: normal function +* 1: disable clock gated function +* RX_2B_OFFSET[31] - (RW) RX PBF 2-byte Offset +* 1: Skip the first two bytes of the RX PBF +* 0: Not to skip the first two bytes of the +* RX PBF +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_2B_OFFSET_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_2B_OFFSET_MASK \ + 0x80000000 /* RX_2B_OFFSET[31] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_2B_OFFSET_SHFT 31 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CLK_GATE_DIS_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CLK_GATE_DIS_MASK \ + 0x40000000 /* CLK_GATE_DIS[30] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CLK_GATE_DIS_SHFT 30 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_BYTE_SWAP_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_BYTE_SWAP_MASK \ + 0x20000000 /* BYTE_SWAP[29] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_BYTE_SWAP_SHFT 29 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_OMIT_TX_INFO_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_OMIT_TX_INFO_MASK \ + 0x10000000 /* OMIT_TX_INFO[28] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_OMIT_TX_INFO_SHFT 28 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_OMIT_RX_INFO_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_OMIT_RX_INFO_MASK \ + 0x08000000 /* OMIT_RX_INFO[27] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_OMIT_RX_INFO_SHFT 27 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_PDMA_ADDR_EXT_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_PDMA_ADDR_EXT_EN_MASK \ + 0x04000000 /* PDMA_ADDR_EXT_EN[26] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_PDMA_ADDR_EXT_EN_SHFT 26 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FORCE_TX_EOF_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FORCE_TX_EOF_MASK \ + 0x02000000 /* FORCE_TX_EOF[25] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FORCE_TX_EOF_SHFT 25 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_SW_RST_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_SW_RST_MASK \ + 0x01000000 /* CSR_SW_RST[24] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_SW_RST_SHFT 24 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_EN_MASK \ + 0x00100000 /* CSR_LBK_RX_Q_SEL_EN[20] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_EN_SHFT 20 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_MASK \ + 0x00070000 /* CSR_LBK_RX_Q_SEL[18..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN_MASK \ + 0x00008000 /* CSR_DISP_BASE_PTR_CHAIN_EN[15] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN_SHFT 15 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_PP_HIF_TXP_ACTIVE_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_PP_HIF_TXP_ACTIVE_EN_MASK \ + 0x00004000 /* CSR_PP_HIF_TXP_ACTIVE_EN[14] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_PP_HIF_TXP_ACTIVE_EN_SHFT 14 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_RX_WB_DDONE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_RX_WB_DDONE_MASK \ + 0x00002000 /* CSR_RX_WB_DDONE[13] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_RX_WB_DDONE_SHFT 13 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN_MASK \ + 0x00001000 /* FIFO_LITTLE_ENDIAN[12] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN_SHFT 12 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_AXI_BUFRDY_BYP_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_AXI_BUFRDY_BYP_MASK \ + 0x00000800 /* CSR_AXI_BUFRDY_BYP[11] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_AXI_BUFRDY_BYP_SHFT 11 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_WFDMA_DUMMY_REG_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_WFDMA_DUMMY_REG_MASK \ + 0x00000400 /* CSR_WFDMA_DUMMY_REG[10] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_CSR_WFDMA_DUMMY_REG_SHFT 10 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FW_DWLD_Bypass_dmashdl_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FW_DWLD_Bypass_dmashdl_MASK \ + 0x00000200 /* FW_DWLD_Bypass_dmashdl[9] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_FW_DWLD_Bypass_dmashdl_SHFT 9 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_DMAD_32B_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_DMAD_32B_EN_MASK \ + 0x00000100 /* DMAD_32B_EN[8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_DMAD_32B_EN_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_BIG_ENDIAN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_BIG_ENDIAN_MASK \ + 0x00000080 /* BIG_ENDIAN[7] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_BIG_ENDIAN_SHFT 7 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_WB_DDONE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_WB_DDONE_MASK \ + 0x00000040 /* TX_WB_DDONE[6] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_WB_DDONE_SHFT 6 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_PDMA_BT_SIZE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_PDMA_BT_SIZE_MASK \ + 0x00000030 /* PDMA_BT_SIZE[5..4] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_PDMA_BT_SIZE_SHFT 4 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_BUSY_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_BUSY_MASK \ + 0x00000008 /* RX_DMA_BUSY[3] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_BUSY_SHFT 3 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_EN_MASK \ + 0x00000004 /* RX_DMA_EN[2] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_EN_SHFT 2 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_BUSY_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_BUSY_MASK \ + 0x00000002 /* TX_DMA_BUSY[1] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_BUSY_SHFT 1 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_EN_MASK \ + 0x00000001 /* TX_DMA_EN[0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_EN_SHFT 0 + +/* +* ---WPDMA_RST_DTX_PTR (0x18024000 + 0x20C)--- +* RST_DTX_IDX0[0] - (WO) Write 1 to reset to TX_DMATX_IDX0 to 0 +* RST_DTX_IDX1[1] - (WO) Write 1 to reset to TX_DMATX_IDX1 to 0 +* RST_DTX_IDX2[2] - (WO) Write 1 to reset to TX_DMATX_IDX2 to 0 +* RST_DTX_IDX3[3] - (WO) Write 1 to reset to TX_DMATX_IDX3 to 0 +* RESERVED[31..4] - (WO) Reserved +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX3_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX3_MASK \ + 0x00000008 /* RST_DTX_IDX3[3] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX2_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX2_MASK \ + 0x00000004 /* RST_DTX_IDX2[2] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX1_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX1_MASK \ + 0x00000002 /* RST_DTX_IDX1[1] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX0_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX0_MASK \ + 0x00000001 /* RST_DTX_IDX0[0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DTX_PTR_RST_DTX_IDX0_SHFT 0 + +/* +* ---WPDMA_PAUSE_TX_Q (0x18024000 + 0x224)--- +* TX_Q_PAUSE[3..0] - (RW) Pause signal for each TX ring (16 bits +* for 16 rings) +* Set 0: Normal function; Set 1: The +* corresponding TX ring is paused +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_TX_Q_TX_Q_PAUSE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_TX_Q_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_TX_Q_TX_Q_PAUSE_MASK \ + 0x0000000F /* TX_Q_PAUSE[3..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_TX_Q_TX_Q_PAUSE_SHFT 0 + +/* +* ---HOST_INT_ENA_SET (0x18024000 + 0X228)--- +* HOST_RX_DONE_INT_ENA0[0] - (W1S) RX Queue#0 packet receive interrupt +* HOST_RX_DONE_INT_ENA1[1] - (W1S) RX Queue#1 packet receive interrupt +* HOST_RX_DONE_INT_ENA2[2] - (W1S) RX Queue#2 packet receive interrupt +* HOST_RX_DONE_INT_ENA3[3] - (W1S) RX Queue#3 packet receive interrupt +* HOST_TX_DONE_INT_ENA0[4] - (W1S) TX Queue#0 packet transmit interrupt +* HOST_TX_DONE_INT_ENA1[5] - (W1S) TX Queue#1 packet transmit interrupt +* HOST_TX_DONE_INT_ENA2[6] - (W1S) TX Queue#2 packet transmit interrupt +* HOST_TX_DONE_INT_ENA3[7] - (W1S) TX Queue#3 packet transmit interrupt +* RESERVED8[18..8] - (RO) Reserved bits +* HOST_RX_DONE_INT_ENA6[19] - (W1S) RX Queue#6 packet receive interrupt +* HOST_RX_COHERENT_EN[20] - (W1S) Enable for RX_DMA data coherent +interrupt +* HOST_TX_COHERENT_EN[21] - (W1S) Enable for TX_DMA data coherent +interrupt +* HOST_RX_DONE_INT_ENA4[22] - (W1S) RX Queue#4 packet receive interrupt +* HOST_RX_DONE_INT_ENA5[23] - (W1S) RX Queue#5 packet receive interrupt +* wpdma2host_err_int_ena[24] - (W1S) Enable bit of wpdma2host_err_int +* HOST_RX_DONE_INT_ENA7[25] - (W1S) RX Queue#7 packet receive interrupt +* RESERVED26[27..26] - (RO) Reserved bits +* subsys_int_ena[28] - (W1S) Enable bit of subsys_int +* mcu2host_sw_int_ena[29] - (W1S) Enable bit of mcu2host_sw_int +* RESERVED30[31..30] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_mcu2host_sw_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_mcu2host_sw_int_ena_MASK \ + 0x20000000 /* mcu2host_sw_int_ena[29] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_mcu2host_sw_int_ena_SHFT 29 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_subsys_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_subsys_int_ena_MASK \ + 0x10000000 /* subsys_int_ena[28] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_subsys_int_ena_SHFT 28 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA7_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA7_MASK \ + 0x02000000 /* HOST_RX_DONE_INT_ENA7[25] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA7_SHFT 25 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_wpdma2host_err_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_wpdma2host_err_int_ena_MASK \ + 0x01000000 /* wpdma2host_err_int_ena[24] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_wpdma2host_err_int_ena_SHFT 24 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA5_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA5_MASK \ + 0x00800000 /* HOST_RX_DONE_INT_ENA5[23] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA5_SHFT 23 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA4_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA4_MASK \ + 0x00400000 /* HOST_RX_DONE_INT_ENA4[22] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA4_SHFT 22 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_COHERENT_EN_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_COHERENT_EN_MASK \ + 0x00200000 /* HOST_TX_COHERENT_EN[21] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_COHERENT_EN_SHFT 21 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_COHERENT_EN_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_COHERENT_EN_MASK \ + 0x00100000 /* HOST_RX_COHERENT_EN[20] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_COHERENT_EN_SHFT 20 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA6_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA6_MASK \ + 0x00080000 /* HOST_RX_DONE_INT_ENA6[19] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA6_SHFT 19 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA3_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA3_MASK \ + 0x00000080 /* HOST_TX_DONE_INT_ENA3[7] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA3_SHFT 7 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA2_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA2_MASK \ + 0x00000040 /* HOST_TX_DONE_INT_ENA2[6] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA2_SHFT 6 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA1_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA1_MASK \ + 0x00000020 /* HOST_TX_DONE_INT_ENA1[5] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA1_SHFT 5 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA0_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA0_MASK \ + 0x00000010 /* HOST_TX_DONE_INT_ENA0[4] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA0_SHFT 4 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA3_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA3_MASK \ + 0x00000008 /* HOST_RX_DONE_INT_ENA3[3] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA2_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA2_MASK \ + 0x00000004 /* HOST_RX_DONE_INT_ENA2[2] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA1_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA1_MASK \ + 0x00000002 /* HOST_RX_DONE_INT_ENA1[1] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA0_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA0_MASK \ + 0x00000001 /* HOST_RX_DONE_INT_ENA0[0] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA0_SHFT 0 + +/* +* ---HOST_INT_ENA_CLR (0x18024000 + 0X22C)--- +* HOST_RX_DONE_INT_ENA0[0] - (W1C) RX Queue#0 packet receive interrupt +* HOST_RX_DONE_INT_ENA1[1] - (W1C) RX Queue#1 packet receive interrupt +* HOST_RX_DONE_INT_ENA2[2] - (W1C) RX Queue#2 packet receive interrupt +* HOST_RX_DONE_INT_ENA3[3] - (W1C) RX Queue#3 packet receive interrupt +* HOST_TX_DONE_INT_ENA0[4] - (W1C) TX Queue#0 packet transmit interrupt +* HOST_TX_DONE_INT_ENA1[5] - (W1C) TX Queue#1 packet transmit interrupt +* HOST_TX_DONE_INT_ENA2[6] - (W1C) TX Queue#2 packet transmit interrupt +* HOST_TX_DONE_INT_ENA3[7] - (W1C) TX Queue#3 packet transmit interrupt +* RESERVED8[18..8] - (RO) Reserved bits +* HOST_RX_DONE_INT_ENA6[19] - (W1C) RX Queue#6 packet receive interrupt +* HOST_RX_COHERENT_EN[20] - (W1C) Enable for RX_DMA data coherent +interrupt +* HOST_TX_COHERENT_EN[21] - (W1C) Enable for TX_DMA data coherent +interrupt +* HOST_RX_DONE_INT_ENA4[22] - (W1C) RX Queue#4 packet receive interrupt +* HOST_RX_DONE_INT_ENA5[23] - (W1C) RX Queue#5 packet receive interrupt +* wpdma2host_err_int_ena[24] - (W1C) Enable bit of wpdma2host_err_int +* HOST_RX_DONE_INT_ENA7[25] - (W1C) RX Queue#7 packet receive interrupt +* RESERVED26[27..26] - (RO) Reserved bits +* subsys_int_ena[28] - (W1C) Enable bit of subsys_int +* mcu2host_sw_int_ena[29] - (W1C) Enable bit of mcu2host_sw_int +* RESERVED30[31..30] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_mcu2host_sw_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_mcu2host_sw_int_ena_MASK \ + 0x20000000 /* mcu2host_sw_int_ena[29] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_mcu2host_sw_int_ena_SHFT 29 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_subsys_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_subsys_int_ena_MASK \ + 0x10000000 /* subsys_int_ena[28] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_subsys_int_ena_SHFT 28 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA7_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA7_MASK \ + 0x02000000 /* HOST_RX_DONE_INT_ENA7[25] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA7_SHFT 25 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_wpdma2host_err_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_wpdma2host_err_int_ena_MASK \ + 0x01000000 /* wpdma2host_err_int_ena[24] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_wpdma2host_err_int_ena_SHFT 24 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA5_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA5_MASK \ + 0x00800000 /* HOST_RX_DONE_INT_ENA5[23] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA5_SHFT 23 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA4_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA4_MASK \ + 0x00400000 /* HOST_RX_DONE_INT_ENA4[22] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA4_SHFT 22 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_COHERENT_EN_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_COHERENT_EN_MASK \ + 0x00200000 /* HOST_TX_COHERENT_EN[21] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_COHERENT_EN_SHFT 21 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_COHERENT_EN_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_COHERENT_EN_MASK \ + 0x00100000 /* HOST_RX_COHERENT_EN[20] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_COHERENT_EN_SHFT 20 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA6_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA6_MASK \ + 0x00080000 /* HOST_RX_DONE_INT_ENA6[19] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA6_SHFT 19 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA3_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA3_MASK \ + 0x00000080 /* HOST_TX_DONE_INT_ENA3[7] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA3_SHFT 7 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA2_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA2_MASK \ + 0x00000040 /* HOST_TX_DONE_INT_ENA2[6] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA2_SHFT 6 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA1_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA1_MASK \ + 0x00000020 /* HOST_TX_DONE_INT_ENA1[5] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA1_SHFT 5 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA0_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA0_MASK \ + 0x00000010 /* HOST_TX_DONE_INT_ENA0[4] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA0_SHFT 4 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA3_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA3_MASK \ + 0x00000008 /* HOST_RX_DONE_INT_ENA3[3] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA2_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA2_MASK \ + 0x00000004 /* HOST_RX_DONE_INT_ENA2[2] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA1_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA1_MASK \ + 0x00000002 /* HOST_RX_DONE_INT_ENA1[1] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA0_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA0_MASK \ + 0x00000001 /* HOST_RX_DONE_INT_ENA0[0] */ +#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA0_SHFT 0 + +/* +* ---WPDMA_TIMEOUT_CFG (0x18024000 + 0x230)--- +* WPDMA_TX_TIMEOUT_TH[7..0] - (RW) xxx +* WPDMA_TX_TIMEOUT_TICK[14..8] - (RW) xxx +* WPDMA_TX_TIMEOUT_ENA[15] - (RW) xxx +* WPDMA_RX_TIMEOUT_TH[23..16] - (RW) xxx +* WPDMA_RX_TIMEOUT_TICK[30..24] - (RW) xxx +* WPDMA_RX_TIMEOUT_ENA[31] - (RW) xxx +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_ENA_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_ENA_MASK \ + 0x80000000 /* WPDMA_RX_TIMEOUT_ENA[31] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_ENA_SHFT 31 +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TICK_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TICK_MASK \ + 0x7F000000 /* WPDMA_RX_TIMEOUT_TICK[30..24] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TICK_SHFT 24 +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TH_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TH_MASK \ + 0x00FF0000 /* WPDMA_RX_TIMEOUT_TH[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TH_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_ENA_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_ENA_MASK \ + 0x00008000 /* WPDMA_TX_TIMEOUT_ENA[15] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_ENA_SHFT 15 +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TICK_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TICK_MASK \ + 0x00007F00 /* WPDMA_TX_TIMEOUT_TICK[14..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TICK_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TH_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TH_MASK \ + 0x000000FF /* WPDMA_TX_TIMEOUT_TH[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TH_SHFT 0 + +/* +* ---WPDMA_MISC_CFG (0x18024000 + 0x234)--- +* WPDMA_TX_TIMEOUT_SEL[0] - (RW) xxx +* WPDMA_RX_TIMEOUT_SEL[1] - (RW) xxx +* WPDMA_RX_FREE_Q_TH[5..2] - (RW) When loopback, this will be used to +* generate correct tx_pause to avlid deadlock which caused from situration that +* tx_dma will start reading tx packet from memory without considering lack of RX +* dmad in prefetch sram and needing to read RX dmad from memory which tx dma is +* reading tx packet too and rready is deasserted due to txfifo full !! +* RX dmad in prefetch sram should be greater +* than RX_FREE_Q_TH for rx_dma to start writing received packet into memory!! +* RESERVED6[31..6] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_RX_FREE_Q_TH_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_RX_FREE_Q_TH_MASK \ + 0x0000003C /* WPDMA_RX_FREE_Q_TH[5..2] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_RX_FREE_Q_TH_SHFT 2 +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_RX_TIMEOUT_SEL_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_RX_TIMEOUT_SEL_MASK \ + 0x00000002 /* WPDMA_RX_TIMEOUT_SEL[1] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_RX_TIMEOUT_SEL_SHFT 1 +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_TX_TIMEOUT_SEL_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_TX_TIMEOUT_SEL_MASK \ + 0x00000001 /* WPDMA_TX_TIMEOUT_SEL[0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_MISC_CFG_WPDMA_TX_TIMEOUT_SEL_SHFT 0 + +/* +* ---WPDMA_TX_WRR_ARB_GBF0 (0x18024000 + 0x240)--- +* WRR_REQ0_ARB_GBF[2..0] - (RW) WRR REQ#0 priority level, mapped to +* lumpped request from TX ring0~ring15 for host TXD +* WRR_REQ1_ARB_GBF[5..3] - (RW) WRR REQ#1 priority level, mapped to +* request from TX ring16 when dual tx fifo for host event packet +* WRR_REQ2_ARB_GBF[8..6] - (RW) WRR REQ#2 priority level, mapped to +* request from TX ring17 when dual tx fifo for host event packet +* WRR_REQ3_ARB_GBF[11..9] - (RW) WRR REQ#3 priority level, mapped to +* request from TX ring18 when dual tx fifo for host event packet +* WRR_REQ4_ARB_GBF[14..12] - (RW) WRR REQ#4 priority level, mapped to +* request from TX ring19 when dual tx fifo for host event packet +* RESERVED[31..15] - (RW) Reserved +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ4_ARB_GBF_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ4_ARB_GBF_MASK \ + 0x00007000 /* WRR_REQ4_ARB_GBF[14..12] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ4_ARB_GBF_SHFT 12 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ3_ARB_GBF_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ3_ARB_GBF_MASK \ + 0x00000E00 /* WRR_REQ3_ARB_GBF[11..9] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ3_ARB_GBF_SHFT 9 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ2_ARB_GBF_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ2_ARB_GBF_MASK \ + 0x000001C0 /* WRR_REQ2_ARB_GBF[8..6] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ2_ARB_GBF_SHFT 6 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ1_ARB_GBF_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ1_ARB_GBF_MASK \ + 0x00000038 /* WRR_REQ1_ARB_GBF[5..3] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ1_ARB_GBF_SHFT 3 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ0_ARB_GBF_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ0_ARB_GBF_MASK \ + 0x00000007 /* WRR_REQ0_ARB_GBF[2..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ0_ARB_GBF_SHFT 0 + +/* +* ---MD_INT_STA (0x18024000 + 0x250)--- +* MCU2MD_SW_INT_STS[15..0] - (W1C) MCU to MD S/W interrupt indicator +* CONN_HIF_ON_MD_INT_STS[16] - (RO) MD driver own interrupt indicator +* RESERVED17[31..17] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_MD_INT_STA_CONN_HIF_ON_MD_INT_STS_ADDR \ + WF_WFDMA_HOST_DMA0_MD_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MD_INT_STA_CONN_HIF_ON_MD_INT_STS_MASK \ + 0x00010000 /* CONN_HIF_ON_MD_INT_STS[16] */ +#define WF_WFDMA_HOST_DMA0_MD_INT_STA_CONN_HIF_ON_MD_INT_STS_SHFT 16 +#define WF_WFDMA_HOST_DMA0_MD_INT_STA_MCU2MD_SW_INT_STS_ADDR \ + WF_WFDMA_HOST_DMA0_MD_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_MD_INT_STA_MCU2MD_SW_INT_STS_MASK \ + 0x0000FFFF /* MCU2MD_SW_INT_STS[15..0] */ +#define WF_WFDMA_HOST_DMA0_MD_INT_STA_MCU2MD_SW_INT_STS_SHFT 0 + +/* +* ---MD_INT_ENA (0x18024000 + 0x254)--- +* MCU2MD_SW_INT_ENA[15..0] - (RW) MCU to MD S/W interrupt enable +* CONN_HIF_ON_MD_INT_ENA[16] - (RW) MD driver own interrupt enable +* RESERVED17[31..17] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_MD_INT_ENA_CONN_HIF_ON_MD_INT_ENA_ADDR \ + WF_WFDMA_HOST_DMA0_MD_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MD_INT_ENA_CONN_HIF_ON_MD_INT_ENA_MASK \ + 0x00010000 /* CONN_HIF_ON_MD_INT_ENA[16] */ +#define WF_WFDMA_HOST_DMA0_MD_INT_ENA_CONN_HIF_ON_MD_INT_ENA_SHFT 16 +#define WF_WFDMA_HOST_DMA0_MD_INT_ENA_MCU2MD_SW_INT_ENA_ADDR \ + WF_WFDMA_HOST_DMA0_MD_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA0_MD_INT_ENA_MCU2MD_SW_INT_ENA_MASK \ + 0x0000FFFF /* MCU2MD_SW_INT_ENA[15..0] */ +#define WF_WFDMA_HOST_DMA0_MD_INT_ENA_MCU2MD_SW_INT_ENA_SHFT 0 + +/* +* ---MCU2MD_SW_INT_SET (0x18024000 + 0x258)--- +* MCU2MD_SW_INT_SET[15..0] - (RO) MCU to MD S/W interrupt set +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_MCU2MD_SW_INT_SET_MCU2MD_SW_INT_SET_ADDR \ + WF_WFDMA_HOST_DMA0_MCU2MD_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA0_MCU2MD_SW_INT_SET_MCU2MD_SW_INT_SET_MASK \ + 0x0000FFFF /* MCU2MD_SW_INT_SET[15..0] */ +#define WF_WFDMA_HOST_DMA0_MCU2MD_SW_INT_SET_MCU2MD_SW_INT_SET_SHFT 0 + +/* +* ---WPDMA_PAUSE_RX_Q_TH10 (0x18024000 + 0x260)--- +* RX_DMAD_TH0[11..0] - (RW) RX Ring0 DMAD threshold to pause PP +* sending packet to RX FIFO +* pause_rx_q = (available RX DMAD counts) < + +* RESERVED12[15..12] - (RO) Reserved bits +* RX_DMAD_TH1[27..16] - (RW) RX Ring1 DMAD threshold to pause PP +* sending packet to RX FIFO +* pause_rx_q = (available RX DMAD counts) < + +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH1_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH1_MASK \ + 0x0FFF0000 /* RX_DMAD_TH1[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH1_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH0_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH0_MASK \ + 0x00000FFF /* RX_DMAD_TH0[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH0_SHFT 0 + +/* +* ---WPDMA_PAUSE_RX_Q_TH32 (0x18024000 + 0x264)--- +* RX_DMAD_TH2[11..0] - (RW) RX Ring2 DMAD threshold to pause PP +* sending packet to RX FIFO +* pause_rx_q = (available RX DMAD counts) < + +* RESERVED12[15..12] - (RO) Reserved bits +* RX_DMAD_TH3[27..16] - (RW) RX Ring3 DMAD threshold to pause PP +* sending packet to RX FIFO +* pause_rx_q = (available RX DMAD counts) < + +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH3_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH3_MASK \ + 0x0FFF0000 /* RX_DMAD_TH3[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH3_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH2_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH2_MASK \ + 0x00000FFF /* RX_DMAD_TH2[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH2_SHFT 0 + +/* +* ---WPDMA_PAUSE_RX_Q_TH54 (0x18024000 + 0x268)--- +* RX_DMAD_TH4[11..0] - (RW) RX Ring4 DMAD threshold to pause PP +* sending packet to RX FIFO +* pause_rx_q = (available RX DMAD counts) < + +* RESERVED12[15..12] - (RO) Reserved bits +* RX_DMAD_TH5[27..16] - (RW) RX Ring5 DMAD threshold to pause PP +* sending packet to RX FIFO +* pause_rx_q = (available RX DMAD counts) < + +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH5_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH5_MASK \ + 0x0FFF0000 /* RX_DMAD_TH5[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH5_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH4_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH4_MASK \ + 0x00000FFF /* RX_DMAD_TH4[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH4_SHFT 0 + +/* +* ---WPDMA_PAUSE_RX_Q_TH76 (0x18024000 + 0x26C)--- +* RX_DMAD_TH6[11..0] - (RW) RX Ring6 DMAD threshold to pause PP +* sending packet to RX FIFO +* pause_rx_q = (available RX DMAD counts) < + +* RESERVED12[15..12] - (RO) Reserved bits +* RX_DMAD_TH7[27..16] - (RW) RX Ring7 DMAD threshold to pause PP +* sending packet to RX FIFO +* pause_rx_q = (available RX DMAD counts) < + +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH7_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH7_MASK \ + 0x0FFF0000 /* RX_DMAD_TH7[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH7_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH6_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH6_MASK \ + 0x00000FFF /* RX_DMAD_TH6[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH6_SHFT 0 + +/* +* ---WPDMA_RST_DRX_PTR (0x18024000 + 0x280)--- +* RST_DRX_IDX0[0] - (WO) Write 1 to reset to RX_DMARX_IDX0 to 0 +* RST_DRX_IDX1[1] - (WO) Write 1 to reset to RX_DMARX_IDX1 to 0 +* RST_DRX_IDX2[2] - (WO) Write 1 to reset to RX_DMARX_IDX2 to 0 +* RST_DRX_IDX3[3] - (WO) Write 1 to reset to RX_DMARX_IDX3 to 0 +* RESERVED[31..4] - (WO) Reserved +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX3_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX3_MASK \ + 0x00000008 /* RST_DRX_IDX3[3] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX3_SHFT 3 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX2_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX2_MASK \ + 0x00000004 /* RST_DRX_IDX2[2] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX2_SHFT 2 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX1_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX1_MASK \ + 0x00000002 /* RST_DRX_IDX1[1] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX0_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX0_MASK \ + 0x00000001 /* RST_DRX_IDX0[0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RST_DRX_PTR_RST_DRX_IDX0_SHFT 0 + +/* +* ---WPDMA_INFO (0x18024000 + 0x284)--- +* TX_RING_NUMBER[7..0] - (RO) TX_RING_NUMBER +* RX_RING_NUMBER[15..8] - (RO) RX_RING_NUMBER +* BASE_PTR_WIDTH[23..16] - (RO) {2'h0, 6'd32-'BASE_PTR_WIDTH[5:0]} +* INDEX_WIDTH[27..24] - (RO) RING_INDEX_WIDTH +* PDMA_PREFETCH_SRAM_SIZE[30..28] - (RO) PDMA prefetch sram size{3'h0 : 128 +* byte, 3'h1 : 256 byte, 3'h2 : 512 byte, 3'h3 : 1KB, 3'h4 : 2KB, 3'h5 : 4KB, +* 3'h6 : 8KB, 3'h7 : reserved}, be noticed that prefetch sram is shared outside +* with other DMAs, please check all DMAs' total prefetch ring number and max_cnt +* for each prefetch ring to make sure that total size of all configured prefetch +* dmad of all DMAs' prefetch ring should be less than PDMA_PREFETCH_SRAM_SIZE +* WFDMA_PDA_EXIST[31] - (RO) Only cpu_dma1 will support pda functions +* for firmware download and wfdma_pda_top resides in between cpu_dma0 and +cpu_dma1! +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_WFDMA_PDA_EXIST_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_WFDMA_PDA_EXIST_MASK \ + 0x80000000 /* WFDMA_PDA_EXIST[31] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_WFDMA_PDA_EXIST_SHFT 31 +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_PDMA_PREFETCH_SRAM_SIZE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_PDMA_PREFETCH_SRAM_SIZE_MASK \ + 0x70000000 /* PDMA_PREFETCH_SRAM_SIZE[30..28] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_PDMA_PREFETCH_SRAM_SIZE_SHFT 28 +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_INDEX_WIDTH_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_INDEX_WIDTH_MASK \ + 0x0F000000 /* INDEX_WIDTH[27..24] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_INDEX_WIDTH_SHFT 24 +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_BASE_PTR_WIDTH_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_BASE_PTR_WIDTH_MASK \ + 0x00FF0000 /* BASE_PTR_WIDTH[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_BASE_PTR_WIDTH_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_RX_RING_NUMBER_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_RX_RING_NUMBER_MASK \ + 0x0000FF00 /* RX_RING_NUMBER[15..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_RX_RING_NUMBER_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_TX_RING_NUMBER_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_TX_RING_NUMBER_MASK \ + 0x000000FF /* TX_RING_NUMBER[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_TX_RING_NUMBER_SHFT 0 + +/* +* ---WPDMA_INFO_EXT (0x18024000 + 0x288)--- +* TX_EVENT_RING_NUMBER[7..0] - (RO) When TX_EVENT_RING_NUMBER equal 8'h0, it +* means that this DMA doesn't support dual TX fifo, thus in default it only +* support TX_RING_NUMBER of TX rings !! +* But when TX_EVENT_RING_NUMBER NOT equal +* 8'h0, this dma is configured as dual TX fifo and +* TX_RING[16+TX_EVENT_RING_NUM-1:16] are for getting HOST EVENT packet from HOST +* to WX_CPU!! +* TX_DMAD_RING_NUMBER[15..8] - (RO) When TX_EVENT_RING_NUMBER not equal to +* 8'h0, it means that this DMA support dual TX fifo and TX +* ring[TX_DMAD_RING_NUMBER-1:0] are for getting TXD from HOST to UMAC!! +* RESERVED[30..16] - (RO) Reserved +* TX_DMASHDL_EXIST[31] - (RO) TX_DMASHDL_EXIST +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_DMASHDL_EXIST_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_DMASHDL_EXIST_MASK \ + 0x80000000 /* TX_DMASHDL_EXIST[31] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_DMASHDL_EXIST_SHFT 31 +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_DMAD_RING_NUMBER_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_DMAD_RING_NUMBER_MASK \ + 0x0000FF00 /* TX_DMAD_RING_NUMBER[15..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_DMAD_RING_NUMBER_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_EVENT_RING_NUMBER_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_EVENT_RING_NUMBER_MASK \ + 0x000000FF /* TX_EVENT_RING_NUMBER[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_INFO_EXT_TX_EVENT_RING_NUMBER_SHFT 0 + +/* +* ---WPDMA_INT_RX_PRI_SEL (0x18024000 + 0x298)--- +* WPDMA_INT_RX_RING0_PRI_SEL[0] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_RX_RING1_PRI_SEL[1] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_RX_RING2_PRI_SEL[2] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_RX_RING3_PRI_SEL[3] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_RX_RING4_PRI_SEL[4] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_RX_RING5_PRI_SEL[5] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_RX_RING6_PRI_SEL[6] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_RX_RING7_PRI_SEL[7] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* RESERVED8[31..8] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING7_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING7_PRI_SEL_MASK \ + \ + 0x00000080 /* WPDMA_INT_RX_RING7_PRI_SEL[7] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING7_PRI_SEL_SHFT \ + \ + 7 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING6_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING6_PRI_SEL_MASK \ + \ + 0x00000040 /* WPDMA_INT_RX_RING6_PRI_SEL[6] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING6_PRI_SEL_SHFT \ + \ + 6 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING5_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING5_PRI_SEL_MASK \ + \ + 0x00000020 /* WPDMA_INT_RX_RING5_PRI_SEL[5] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING5_PRI_SEL_SHFT \ + \ + 5 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING4_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING4_PRI_SEL_MASK \ + \ + 0x00000010 /* WPDMA_INT_RX_RING4_PRI_SEL[4] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING4_PRI_SEL_SHFT \ + \ + 4 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING3_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING3_PRI_SEL_MASK \ + \ + 0x00000008 /* WPDMA_INT_RX_RING3_PRI_SEL[3] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING3_PRI_SEL_SHFT \ + \ + 3 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING2_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING2_PRI_SEL_MASK \ + \ + 0x00000004 /* WPDMA_INT_RX_RING2_PRI_SEL[2] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING2_PRI_SEL_SHFT \ + \ + 2 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING1_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING1_PRI_SEL_MASK \ + \ + 0x00000002 /* WPDMA_INT_RX_RING1_PRI_SEL[1] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING1_PRI_SEL_SHFT \ + \ + 1 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING0_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING0_PRI_SEL_MASK \ + \ + 0x00000001 /* WPDMA_INT_RX_RING0_PRI_SEL[0] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING0_PRI_SEL_SHFT \ + \ + 0 + +/* +* ---WPDMA_TX_DBG0 (0x18024000 + 0x2A0)--- +* WPDMA_TX_DBG0[31..0] - (RO) xxx +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG0_WPDMA_TX_DBG0_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG0_WPDMA_TX_DBG0_MASK \ + 0xFFFFFFFF /* WPDMA_TX_DBG0[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG0_WPDMA_TX_DBG0_SHFT 0 + +/* +* ---WPDMA_TX_DBG1 (0x18024000 + 0x2A4)--- +* WPDMA_TX_DBG1[31..0] - (RO) xxx +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG1_WPDMA_TX_DBG1_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG1_WPDMA_TX_DBG1_MASK \ + 0xFFFFFFFF /* WPDMA_TX_DBG1[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_DBG1_WPDMA_TX_DBG1_SHFT 0 + +/* +* ---WPDMA_RX_DBG0 (0x18024000 + 0x2A8)--- +* WPDMA_RX_DBG0[31..0] - (RO) xxx +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG0_WPDMA_RX_DBG0_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG0_WPDMA_RX_DBG0_MASK \ + 0xFFFFFFFF /* WPDMA_RX_DBG0[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG0_WPDMA_RX_DBG0_SHFT 0 + +/* +* ---WPDMA_RX_DBG1 (0x18024000 + 0x2AC)--- +* WPDMA_RX_DBG1[31..0] - (RO) xxx +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG1_WPDMA_RX_DBG1_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG1_WPDMA_RX_DBG1_MASK \ + 0xFFFFFFFF /* WPDMA_RX_DBG1[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_DBG1_WPDMA_RX_DBG1_SHFT 0 + +/* +* ---WPDMA_GLO_CFG_EXT0 (0x18024000 + 0x2B0)--- +* CSR_MAX_PREFETCH_CNT[1..0] - (RW) Max. dmad count per prefet request, +* 2'b00 : 1 entry, 2'b01 : 2 entries, 2'b10 : 4 entries, 2'b11 : 8 entries, Note +* : 1 entry(dmad size) is 16 bytes = 4 DWs = 2 QWs +* CSR_MEM_BST_SIZE[3..2] - (RW) Max. burst size per sram request. 00 : +* 16-byte, 01 : 32-byte, 10 : 64-byte, 11 : 128-byte +* CSR_MEM_ARB_LOCK_EN[4] - (RW) 1'b1 : Lock round-robin sram access +* arbiter until whole long burst request from dma FSM finish, 1'b0 : no lock +sram +* arbiter, grant will be change per request due to round-robin +* CSR_RX_DMA_WBQ_EN[5] - (RW) 1'b1 : RX dmad will be posted-write and +* deal with next received packet immediately, 1'b0 : RX dmad will be written +back +* immediately after received packet has been sent to host memory +* CSR_TX_DMASHDL_ENABLE[6] - (RW) 1'b1 : request DMASHDL before TX to +* select next TX ring, 1'b0 : disable DMASHDL and use round-robin arbiter to +* select next TX ring +* CSR_BRESP_ERROR_BYPASS_EN[7] - (RW) 1'b1 : Bypass AXI error bresp as a +* normal response. 1'b0 : Will not assert bready to error bresp(00 : OKAY, 01 : +* EXOKAY, 10 : SLVERR, 11 : DECERR) +* CSR_AXI_SLEEP_MODE[9..8] - (RW) 2'b00 : no sleep, normal TX/RX, 2b1* : +* sleep after AXI request, 2'b11 : force assertion of wvalid, rready and bready +* to finish all committed data phases, then sleep immediately +* RESERVED10[14..10] - (RO) Reserved bits +* CSR_Q_STATUS_IDX_BKRS_EN[15] - (RW) backup/restore enable bit for +* q_status(payload, prefetch and dispatch) index +* CSR_AXI_BST_SIZE[17..16] - (RW) AXI busrt length, 00 : 128-byte, 01 : +* 64-byte, 10 : 32-byte, 11 : 16-byte +* RESERVED18[18] - (RO) Reserved bits +* CSR_AXI_FAKE[19] - (RW) If set to 1'b1, all requests from DMA +* engine will not be sent to AXI INFRA, this try to fix AXI bus hang issue +temporarily! +* CSR_DMAD_PREFETCH_THRESHOLD[21..20] - (RW) trigger dmad prefetch when +* available dmad cnt >= {1(2'b00), 2(2'b01), 4(2'b10), 8(2'b11)} +* CSR_BID_CHECK_BYPASS_EN[22] - (RW) If set to 1'b0, axi master will check +* matching between awid and bid before assert bready, if set to 1'b1, it will +* bypass this checking and assert bready for each bvalid even though bid doesn't +* match any awid ever issued! +* CSR_RX_INFO_WB_EN[23] - (RW) If set to 1'b0, only DW0 and DW1 will be +* written back into memory after received RX packet process finished, this will +* save bus bandwidth a little because DW2 and DW3 are useless for FW +* CSR_AXI_OUTSTANDING_NUM[27..24] - (RW) decide max. outstanding AXI requests, +* common for AXI read or write! +* CSR_AXI_ARUSER_LOCK_EN[28] - (RW) on/off customized lock ctrl design thru +* AXI aruser signal, this will influence TX QoS ctrl +* CSR_AXI_AWUSER_LOCK_EN[29] - (RW) on/off customized lock ctrl design thru AXI +* awuser signal when RX dmad write-back have to be separately written into +* memory due to external dispatcher exists! +* CSR_AXI_LOCK_EN[30] - (RW) Global lock enable to on/off AXI spec. lock(axlock) +* behavior and also will on/off customized lock ctrl design thru AXI awuser +signal +* CSR_AXI_CLKGATE_BYP[31] - (RW) To bypass functional CG enable which +* incduced from coding style for DC inserted CG cell in all AXI read/write +master +* design module +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_CLKGATE_BYP_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_CLKGATE_BYP_MASK \ + 0x80000000 /* CSR_AXI_CLKGATE_BYP[31] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_CLKGATE_BYP_SHFT 31 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_LOCK_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_LOCK_EN_MASK \ + 0x40000000 /* CSR_AXI_LOCK_EN[30] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_LOCK_EN_SHFT 30 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_AWUSER_LOCK_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_AWUSER_LOCK_EN_MASK \ + 0x20000000 /* CSR_AXI_AWUSER_LOCK_EN[29] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_AWUSER_LOCK_EN_SHFT 29 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_ARUSER_LOCK_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_ARUSER_LOCK_EN_MASK \ + 0x10000000 /* CSR_AXI_ARUSER_LOCK_EN[28] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_ARUSER_LOCK_EN_SHFT 28 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_OUTSTANDING_NUM_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_OUTSTANDING_NUM_MASK \ + 0x0F000000 /* CSR_AXI_OUTSTANDING_NUM[27..24] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_OUTSTANDING_NUM_SHFT 24 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_RX_INFO_WB_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_RX_INFO_WB_EN_MASK \ + 0x00800000 /* CSR_RX_INFO_WB_EN[23] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_RX_INFO_WB_EN_SHFT 23 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_BID_CHECK_BYPASS_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_BID_CHECK_BYPASS_EN_MASK \ + 0x00400000 /* CSR_BID_CHECK_BYPASS_EN[22] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_BID_CHECK_BYPASS_EN_SHFT 22 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_DMAD_PREFETCH_THRESHOLD_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_DMAD_PREFETCH_THRESHOLD_MASK \ + 0x00300000 /* CSR_DMAD_PREFETCH_THRESHOLD[21..20] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_DMAD_PREFETCH_THRESHOLD_SHFT \ + 20 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_FAKE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_FAKE_MASK \ + 0x00080000 /* CSR_AXI_FAKE[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_FAKE_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_BST_SIZE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_BST_SIZE_MASK \ + 0x00030000 /* CSR_AXI_BST_SIZE[17..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_BST_SIZE_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_Q_STATUS_IDX_BKRS_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_Q_STATUS_IDX_BKRS_EN_MASK \ + 0x00008000 /* CSR_Q_STATUS_IDX_BKRS_EN[15] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_Q_STATUS_IDX_BKRS_EN_SHFT 15 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_SLEEP_MODE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_SLEEP_MODE_MASK \ + 0x00000300 /* CSR_AXI_SLEEP_MODE[9..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_AXI_SLEEP_MODE_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_BRESP_ERROR_BYPASS_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_BRESP_ERROR_BYPASS_EN_MASK \ + 0x00000080 /* CSR_BRESP_ERROR_BYPASS_EN[7] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_BRESP_ERROR_BYPASS_EN_SHFT 7 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_TX_DMASHDL_ENABLE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_TX_DMASHDL_ENABLE_MASK \ + 0x00000040 /* CSR_TX_DMASHDL_ENABLE[6] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_TX_DMASHDL_ENABLE_SHFT 6 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_RX_DMA_WBQ_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_RX_DMA_WBQ_EN_MASK \ + 0x00000020 /* CSR_RX_DMA_WBQ_EN[5] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_RX_DMA_WBQ_EN_SHFT 5 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MEM_ARB_LOCK_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MEM_ARB_LOCK_EN_MASK \ + 0x00000010 /* CSR_MEM_ARB_LOCK_EN[4] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MEM_ARB_LOCK_EN_SHFT 4 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MEM_BST_SIZE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MEM_BST_SIZE_MASK \ + 0x0000000C /* CSR_MEM_BST_SIZE[3..2] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MEM_BST_SIZE_SHFT 2 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MAX_PREFETCH_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MAX_PREFETCH_CNT_MASK \ + 0x00000003 /* CSR_MAX_PREFETCH_CNT[1..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT0_CSR_MAX_PREFETCH_CNT_SHFT 0 + +/* +* ---WPDMA_GLO_CFG_EXT1 (0x18024000 + 0x2B4)--- +* CSR_TXFIFO0_RDY_THRESHOLD[7..0] - (RW) xxx +* CSR_TXFIFO1_RDY_THRESHOLD[15..8] - (RW) xxx +* CSR_TX_DISP_ARB_SCHEDULED_ACCESS_TIMER[23..16] - (RW) timer setting for +* SCHEDULED_ACCESS_TIME_ARB of csr_tx_disp_arb_mode +* CSR_TX_DISP_ARB_MODE[25..24] - (RW) 00 : FAIR_ARB, 01 : FIX_ARB, 10 : +* UNBALANCED_ARB, 11 : SCHEDULED_ACCESS_TIME_ARB +* CSR_FWDL_FLOW_CTRL_BYASS_EN[26] - (RW) To disable firmware download TX flow +* control of TX dma(host_dma1) when firmare download of RX dma(mcu_dma1) is in +* firmware download polling mode!! Remember to set to 1'b0 when firmware +download +* ring is set back to normal ring usage which should be in flow control for +* correct behavior!! +* CSR_FWDL_FLOW_CTRL_BYASS_LS_QSEL_EN[27] - (RW) select firmware download TX +* ring(LSB/MSB ring) to bypass TX flow control when firmare download RX +* ring(LSB/MSB ring) of RX dma(mcu_dma1) is in firmware download polling mode!! +* RESERVED[31..28] - (RW) reserved +*/ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_LS_QSEL_EN_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_LS_QSEL_EN_MASK \ + \ + 0x08000000 /* CSR_FWDL_FLOW_CTRL_BYASS_LS_QSEL_EN[27] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_LS_QSEL_EN_SHFT \ + \ + 27 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_EN_MASK \ + 0x04000000 /* CSR_FWDL_FLOW_CTRL_BYASS_EN[26] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_EN_SHFT \ + 26 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_MODE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_MODE_MASK \ + 0x03000000 /* CSR_TX_DISP_ARB_MODE[25..24] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_MODE_SHFT 24 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_SCHEDULED_ACCESS_TIMER_AD\ +DR \ +\ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_SCHEDULED_ACCESS_TIMER_MA\ +SK \ +\ + 0x00FF0000 /* CSR_TX_DISP_ARB_SCHEDULED_ACCESS_TIMER[23..16] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_SCHEDULED_ACCESS_TIMER_SH\ +FT \ +\ + 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO1_RDY_THRESHOLD_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO1_RDY_THRESHOLD_MASK \ + 0x0000FF00 /* CSR_TXFIFO1_RDY_THRESHOLD[15..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO1_RDY_THRESHOLD_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO0_RDY_THRESHOLD_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO0_RDY_THRESHOLD_MASK \ + 0x000000FF /* CSR_TXFIFO0_RDY_THRESHOLD[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO0_RDY_THRESHOLD_SHFT 0 + +/* +* ---WPDMA_TX_QOS_LMT_CFG0 (0x18024000 + 0x2C0)--- +* CSR_TX_PLD_0_AXI_LIMITER_REQ[2..0] - (RW) QoS CR, Limiter Enable for packet +* traffice of type TX_PLD_0 +* CSR_TX_PLD_0_AXI_LIMITER_EN_REQ[3] - (RW) QoS CR, Limiter Enable for packet +* traffice of type TX_PLD_0 +* CSR_TX_PLD_0_AXI_LIMITER_PKT[6..4] - (RW) QoS CR, Limiter Enable for packet +* traffice of type TX_PLD_0 +* CSR_TX_PLD_0_AXI_LIMITER_EN_PKT[7] - (RW) QoS CR, Limiter Enable for packet +* traffice of type TX_PLD_0 +* CSR_TX_PLD_1_PLD_AXI_LIMITER_REQ[10..8] - (RW) QoS CR, Limiter Enable for +* request traffice of type TX_PLD_1_PLD +* CSR_TX_PLD_1_PLD_AXI_LIMITER_EN_REQ[11] - (RW) QoS CR, Limiter Enable for +* request traffice of type TX_PLD_1_PLD +* CSR_TX_PLD_1_PLD_AXI_LIMITER_PKT[14..12] - (RW) QoS CR, Limiter Enable for +* request traffice of type TX_PLD_1_PLD +* CSR_TX_PLD_1_PLD_AXI_LIMITER_EN_PKT[15] - (RW) QoS CR, Limiter Enable for +* request traffice of type TX_PLD_1_PLD +* CSR_RX_PLD_AXI_LIMITER_REQ[18..16] - (RW) QoS CR, Limiter Enable for request +* traffice of type RX_PLD +* CSR_RX_PLD_AXI_LIMITER_EN_REQ[19] - (RW) QoS CR, Limiter Enable for request +* traffice of type RX_PLD +* CSR_RX_PLD_AXI_LIMITER_PKT[22..20] - (RW) QoS CR, Limiter Enable for request +* traffice of type RX_PLD +* CSR_RX_PLD_AXI_LIMITER_EN_PKT[23] - (RW) QoS CR, Limiter Enable for request +* traffice of type RX_PLD +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_EN_PKT_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_EN_PKT_MASK \ + \ + 0x00800000 /* CSR_RX_PLD_AXI_LIMITER_EN_PKT[23] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_EN_PKT_SHFT \ + \ + 23 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_PKT_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_PKT_MASK \ + \ + 0x00700000 /* CSR_RX_PLD_AXI_LIMITER_PKT[22..20] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_PKT_SHFT \ + \ + 20 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_EN_REQ_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_EN_REQ_MASK \ + \ + 0x00080000 /* CSR_RX_PLD_AXI_LIMITER_EN_REQ[19] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_EN_REQ_SHFT \ + \ + 19 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_REQ_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_REQ_MASK \ + \ + 0x00070000 /* CSR_RX_PLD_AXI_LIMITER_REQ[18..16] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_REQ_SHFT \ + \ + 16 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_1_PLD_AXI_LIMITER_EN_PKT_AD\ +DR \ +\ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_1_PLD_AXI_LIMITER_EN_PKT_MA\ +SK \ +\ + 0x00008000 /* CSR_TX_PLD_1_PLD_AXI_LIMITER_EN_PKT[15] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_1_PLD_AXI_LIMITER_EN_PKT_SH\ +FT \ +\ + 15 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_1_PLD_AXI_LIMITER_PKT_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_1_PLD_AXI_LIMITER_PKT_MASK \ + \ + 0x00007000 /* CSR_TX_PLD_1_PLD_AXI_LIMITER_PKT[14..12] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_1_PLD_AXI_LIMITER_PKT_SHFT \ + \ + 12 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_1_PLD_AXI_LIMITER_EN_REQ_AD\ +DR \ +\ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_1_PLD_AXI_LIMITER_EN_REQ_MA\ +SK \ +\ + 0x00000800 /* CSR_TX_PLD_1_PLD_AXI_LIMITER_EN_REQ[11] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_1_PLD_AXI_LIMITER_EN_REQ_SH\ +FT \ +\ + 11 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_1_PLD_AXI_LIMITER_REQ_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_1_PLD_AXI_LIMITER_REQ_MASK \ + \ + 0x00000700 /* CSR_TX_PLD_1_PLD_AXI_LIMITER_REQ[10..8] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_1_PLD_AXI_LIMITER_REQ_SHFT \ + \ + 8 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_0_AXI_LIMITER_EN_PKT_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_0_AXI_LIMITER_EN_PKT_MASK \ + \ + 0x00000080 /* CSR_TX_PLD_0_AXI_LIMITER_EN_PKT[7] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_0_AXI_LIMITER_EN_PKT_SHFT \ + \ + 7 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_0_AXI_LIMITER_PKT_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_0_AXI_LIMITER_PKT_MASK \ + \ + 0x00000070 /* CSR_TX_PLD_0_AXI_LIMITER_PKT[6..4] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_0_AXI_LIMITER_PKT_SHFT \ + \ + 4 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_0_AXI_LIMITER_EN_REQ_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_0_AXI_LIMITER_EN_REQ_MASK \ + \ + 0x00000008 /* CSR_TX_PLD_0_AXI_LIMITER_EN_REQ[3] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_0_AXI_LIMITER_EN_REQ_SHFT \ + \ + 3 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_0_AXI_LIMITER_REQ_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_0_AXI_LIMITER_REQ_MASK \ + \ + 0x00000007 /* CSR_TX_PLD_0_AXI_LIMITER_REQ[2..0] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_0_AXI_LIMITER_REQ_SHFT \ + \ + 0 + +/* +* ---WPDMA_TX_QOS_LMT_CFG1 (0x18024000 + 0x2C4)--- +* CSR_AUX_TX_PLD_0_AXI_LIMITER_REQ[2..0] - (RW) QoS CR, Limiter value selected +* by PP dynamically +* RESERVED3[3] - (RO) Reserved bits +* CSR_AUX_TX_PLD_0_AXI_LIMITER_PKT[6..4] - (RW) QoS CR, Limiter value selected +* by PP dynamically +* RESERVED7[7] - (RO) Reserved bits +* CSR_AUX_TX_PLD_1_AXI_LIMITER_REQ[10..8] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED11[11] - (RO) Reserved bits +* CSR_AUX_TX_PLD_1_AXI_LIMITER_PKT[14..12] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED15[15] - (RO) Reserved bits +* CSR_AUX_RX_PLD_AXI_LIMITER_REQ[18..16] - (RW) QoS CR, Limiter value selected +* by PP dynamically +* RESERVED19[19] - (RO) Reserved bits +* CSR_AUX_RX_PLD_AXI_LIMITER_PKT[22..20] - (RW) QoS CR, Limiter value selected +* by PP dynamically +* RESERVED23[31..23] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_RX_PLD_AXI_LIMITER_PKT_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_RX_PLD_AXI_LIMITER_PKT_MASK \ + \ + 0x00700000 /* CSR_AUX_RX_PLD_AXI_LIMITER_PKT[22..20] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_RX_PLD_AXI_LIMITER_PKT_SHFT \ + \ + 20 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_RX_PLD_AXI_LIMITER_REQ_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_RX_PLD_AXI_LIMITER_REQ_MASK \ + \ + 0x00070000 /* CSR_AUX_RX_PLD_AXI_LIMITER_REQ[18..16] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_RX_PLD_AXI_LIMITER_REQ_SHFT \ + \ + 16 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_1_AXI_LIMITER_PKT_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_1_AXI_LIMITER_PKT_MASK \ + \ + 0x00007000 /* CSR_AUX_TX_PLD_1_AXI_LIMITER_PKT[14..12] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_1_AXI_LIMITER_PKT_SHFT \ + \ + 12 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_1_AXI_LIMITER_REQ_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_1_AXI_LIMITER_REQ_MASK \ + \ + 0x00000700 /* CSR_AUX_TX_PLD_1_AXI_LIMITER_REQ[10..8] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_1_AXI_LIMITER_REQ_SHFT \ + \ + 8 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_0_AXI_LIMITER_PKT_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_0_AXI_LIMITER_PKT_MASK \ + \ + 0x00000070 /* CSR_AUX_TX_PLD_0_AXI_LIMITER_PKT[6..4] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_0_AXI_LIMITER_PKT_SHFT \ + \ + 4 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_0_AXI_LIMITER_REQ_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_0_AXI_LIMITER_REQ_MASK \ + \ + 0x00000007 /* CSR_AUX_TX_PLD_0_AXI_LIMITER_REQ[2..0] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_0_AXI_LIMITER_REQ_SHFT \ + \ + 0 + +/* +* ---WPDMA_TX_QOS_LMT_CFG2 (0x18024000 + 0x2C8)--- +* CSR_RX_RD_DMAD_AXI_LIMITER_REQ[2..0] - (RW) QoS CR, Limiter Value for +* packet traffice of type RX_RD_DMAD +* CSR_RX_RD_DMAD_AXI_LIMITER_EN_REQ[3] - (RW) QoS CR, Limiter Enable for +* request traffice of type RX_RD_DMAD +* CSR_RX_RD_DMAD_AXI_LIMITER_PKT[6..4] - (RW) QoS CR, Limiter Value for +* packet traffice of type RX_RD_DMAD +* CSR_RX_RD_DMAD_AXI_LIMITER_EN_PKT[7] - (RW) QoS CR, Limiter Enable for +* packet traffice of type RX_RD_DMAD +* CSR_RX_WR_DMAD_AXI_LIMITER_REQ[10..8] - (RW) QoS CR, Limiter Value for +* packet traffice of type RX_WR_DMAD +* CSR_RX_WR_DMAD_AXI_LIMITER_EN_REQ[11] - (RW) QoS CR, Limiter Enable for +* request traffice of type RX_WR_DMAD +* CSR_RX_WR_DMAD_AXI_LIMITER_PKT[14..12] - (RW) QoS CR, Limiter Value for +* packet traffice of type RX_WR_DMAD +* CSR_RX_WR_DMAD_AXI_LIMITER_EN_PKT[15] - (RW) QoS CR, Limiter Enable for +* packet traffice of type RX_WR_DMAD +* CSR_TX_RD_DMAD_AXI_LIMITER_REQ[18..16] - (RW) QoS CR, Limiter Value for +* packet traffice of type TX_RD_DMAD +* CSR_TX_RD_DMAD_AXI_LIMITER_EN_REQ[19] - (RW) QoS CR, Limiter Enable for +* request traffice of type TX_RD_DMAD +* CSR_TX_RD_DMAD_AXI_LIMITER_PKT[22..20] - (RW) QoS CR, Limiter Value for +* packet traffice of type TX_RD_DMAD +* CSR_TX_RD_DMAD_AXI_LIMITER_EN_PKT[23] - (RW) QoS CR, Limiter Enable for +* packet traffice of type TX_RD_DMAD +* CSR_TX_WR_DMAD_AXI_LIMITER_REQ[26..24] - (RW) QoS CR, Limiter Value for +* packet traffice of type TX_WR_DMAD +* CSR_TX_WR_DMAD_AXI_LIMITER_EN_REQ[27] - (RW) QoS CR, Limiter Enable for +* request traffice of type TX_WR_DMAD +* CSR_TX_WR_DMAD_AXI_LIMITER_PKT[30..28] - (RW) QoS CR, Limiter Value for +* packet traffice of type TX_WR_DMAD +* CSR_TX_WR_DMAD_AXI_LIMITER_EN_PKT[31] - (RW) QoS CR, Limiter Enable for +* packet traffice of type TX_WR_DMAD +*/ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_EN_PKT_ADDR\ +\ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_EN_PKT_MASK\ +\ + 0x80000000 /* CSR_TX_WR_DMAD_AXI_LIMITER_EN_PKT[31] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_EN_PKT_SHFT\ +\ + 31 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_PKT_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_PKT_MASK \ + \ + 0x70000000 /* CSR_TX_WR_DMAD_AXI_LIMITER_PKT[30..28] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_PKT_SHFT \ + \ + 28 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_EN_REQ_ADDR\ +\ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_EN_REQ_MASK\ +\ + 0x08000000 /* CSR_TX_WR_DMAD_AXI_LIMITER_EN_REQ[27] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_EN_REQ_SHFT\ +\ + 27 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_REQ_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_REQ_MASK \ + \ + 0x07000000 /* CSR_TX_WR_DMAD_AXI_LIMITER_REQ[26..24] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_REQ_SHFT \ + \ + 24 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_EN_PKT_ADDR\ +\ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_EN_PKT_MASK\ +\ + 0x00800000 /* CSR_TX_RD_DMAD_AXI_LIMITER_EN_PKT[23] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_EN_PKT_SHFT\ +\ + 23 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_PKT_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_PKT_MASK \ + \ + 0x00700000 /* CSR_TX_RD_DMAD_AXI_LIMITER_PKT[22..20] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_PKT_SHFT \ + \ + 20 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_EN_REQ_ADDR\ +\ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_EN_REQ_MASK\ +\ + 0x00080000 /* CSR_TX_RD_DMAD_AXI_LIMITER_EN_REQ[19] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_EN_REQ_SHFT\ +\ + 19 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_REQ_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_REQ_MASK \ + \ + 0x00070000 /* CSR_TX_RD_DMAD_AXI_LIMITER_REQ[18..16] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_REQ_SHFT \ + \ + 16 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_EN_PKT_ADDR\ +\ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_EN_PKT_MASK\ +\ + 0x00008000 /* CSR_RX_WR_DMAD_AXI_LIMITER_EN_PKT[15] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_EN_PKT_SHFT\ +\ + 15 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_PKT_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_PKT_MASK \ + \ + 0x00007000 /* CSR_RX_WR_DMAD_AXI_LIMITER_PKT[14..12] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_PKT_SHFT \ + \ + 12 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_EN_REQ_ADDR\ +\ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_EN_REQ_MASK\ +\ + 0x00000800 /* CSR_RX_WR_DMAD_AXI_LIMITER_EN_REQ[11] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_EN_REQ_SHFT\ +\ + 11 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_REQ_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_REQ_MASK \ + \ + 0x00000700 /* CSR_RX_WR_DMAD_AXI_LIMITER_REQ[10..8] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_REQ_SHFT \ + \ + 8 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_EN_PKT_ADDR\ +\ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_EN_PKT_MASK\ +\ + 0x00000080 /* CSR_RX_RD_DMAD_AXI_LIMITER_EN_PKT[7] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_EN_PKT_SHFT\ +\ + 7 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_PKT_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_PKT_MASK \ + \ + 0x00000070 /* CSR_RX_RD_DMAD_AXI_LIMITER_PKT[6..4] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_PKT_SHFT \ + \ + 4 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_EN_REQ_ADDR\ +\ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_EN_REQ_MASK\ +\ + 0x00000008 /* CSR_RX_RD_DMAD_AXI_LIMITER_EN_REQ[3] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_EN_REQ_SHFT\ +\ + 3 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_REQ_ADDR \ + \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_REQ_MASK \ + \ + 0x00000007 /* CSR_RX_RD_DMAD_AXI_LIMITER_REQ[2..0] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_REQ_SHFT \ + \ + 0 + +/* +* ---WPDMA_TX_QOS_LMT_CFG3 (0x18024000 + 0x2CC)--- +* CSR_AUX_RX_RD_DMAD_AXI_LIMITER_REQ[2..0] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED3[3] - (RO) Reserved bits +* CSR_AUX_RX_RD_DMAD_AXI_LIMITER_PKT[6..4] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED7[7] - (RO) Reserved bits +* CSR_AUX_RX_WR_DMAD_AXI_LIMITER_REQ[10..8] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED11[11] - (RO) Reserved bits +* CSR_AUX_RX_WR_DMAD_AXI_LIMITER_PKT[14..12] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED15[15] - (RO) Reserved bits +* CSR_AUX_TX_RD_DMAD_AXI_LIMITER_REQ[18..16] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED19[19] - (RO) Reserved bits +* CSR_AUX_TX_RD_DMAD_AXI_LIMITER_PKT[22..20] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED23[23] - (RO) Reserved bits +* CSR_AUX_TX_WR_DMAD_AXI_LIMITER_REQ[26..24] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED27[27] - (RO) Reserved bits +* CSR_AUX_TX_WR_DMAD_AXI_LIMITER_PKT[30..28] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED31[31] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_WR_DMAD_AXI_LIMITER_PKT_ADD\ +R \ +\ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_WR_DMAD_AXI_LIMITER_PKT_MAS\ +K \ +\ + 0x70000000 /* CSR_AUX_TX_WR_DMAD_AXI_LIMITER_PKT[30..28] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_WR_DMAD_AXI_LIMITER_PKT_SHF\ +T \ +\ + 28 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_WR_DMAD_AXI_LIMITER_REQ_ADD\ +R \ +\ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_WR_DMAD_AXI_LIMITER_REQ_MAS\ +K \ +\ + 0x07000000 /* CSR_AUX_TX_WR_DMAD_AXI_LIMITER_REQ[26..24] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_WR_DMAD_AXI_LIMITER_REQ_SHF\ +T \ +\ + 24 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_RD_DMAD_AXI_LIMITER_PKT_ADD\ +R \ +\ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_RD_DMAD_AXI_LIMITER_PKT_MAS\ +K \ +\ + 0x00700000 /* CSR_AUX_TX_RD_DMAD_AXI_LIMITER_PKT[22..20] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_RD_DMAD_AXI_LIMITER_PKT_SHF\ +T \ +\ + 20 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_RD_DMAD_AXI_LIMITER_REQ_ADD\ +R \ +\ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_RD_DMAD_AXI_LIMITER_REQ_MAS\ +K \ +\ + 0x00070000 /* CSR_AUX_TX_RD_DMAD_AXI_LIMITER_REQ[18..16] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_RD_DMAD_AXI_LIMITER_REQ_SHF\ +T \ +\ + 16 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_WR_DMAD_AXI_LIMITER_PKT_ADD\ +R \ +\ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_WR_DMAD_AXI_LIMITER_PKT_MAS\ +K \ +\ + 0x00007000 /* CSR_AUX_RX_WR_DMAD_AXI_LIMITER_PKT[14..12] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_WR_DMAD_AXI_LIMITER_PKT_SHF\ +T \ +\ + 12 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_WR_DMAD_AXI_LIMITER_REQ_ADD\ +R \ +\ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_WR_DMAD_AXI_LIMITER_REQ_MAS\ +K \ +\ + 0x00000700 /* CSR_AUX_RX_WR_DMAD_AXI_LIMITER_REQ[10..8] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_WR_DMAD_AXI_LIMITER_REQ_SHF\ +T \ +\ + 8 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_RD_DMAD_AXI_LIMITER_PKT_ADD\ +R \ +\ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_RD_DMAD_AXI_LIMITER_PKT_MAS\ +K \ +\ + 0x00000070 /* CSR_AUX_RX_RD_DMAD_AXI_LIMITER_PKT[6..4] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_RD_DMAD_AXI_LIMITER_PKT_SHF\ +T \ +\ + 4 +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_RD_DMAD_AXI_LIMITER_REQ_ADD\ +R \ +\ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_RD_DMAD_AXI_LIMITER_REQ_MAS\ +K \ +\ + 0x00000007 /* CSR_AUX_RX_RD_DMAD_AXI_LIMITER_REQ[2..0] */ +#define \ +WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_RD_DMAD_AXI_LIMITER_REQ_SHF\ +T \ +\ + 0 + +/* +* ---WPDMA_TX_QOS_QTM_CFG0 (0x18024000 + 0x2D0)--- +* CSR_TXP0_FFA_QTM[3..0] - (RW) CSR_TXP0_FFA_QTM +* CSR_TXP0_RSVD_QTM[7..4] - (RW) CSR_TXP0_RSVD_QTM +* CSR_TXP1_FFA_QTM[11..8] - (RW) CSR_TXP1_FFA_QTM +* CSR_TXP1_RSVD_QTM[15..12] - (RW) CSR_TXP1_RSVD_QTM +* RESERVED16[23..16] - (RO) Reserved bits +* CSR_FFA_TOTAL_QTM[27..24] - (RW) CSR_FFA_TOTAL_QTM +* CSR_QOS_QTM_MODE[29..28] - (RW) 2'b01 : csr_rsvd_qtm_mode_only, 2'b10 : +* csr_ffa_qtm_mode_only, others : rsvd+ffa mode +* RESERVED30[31..30] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_QOS_QTM_MODE_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_QOS_QTM_MODE_MASK \ + 0x30000000 /* CSR_QOS_QTM_MODE[29..28] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_QOS_QTM_MODE_SHFT 28 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_FFA_TOTAL_QTM_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_FFA_TOTAL_QTM_MASK \ + 0x0F000000 /* CSR_FFA_TOTAL_QTM[27..24] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_FFA_TOTAL_QTM_SHFT 24 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP1_RSVD_QTM_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP1_RSVD_QTM_MASK \ + 0x0000F000 /* CSR_TXP1_RSVD_QTM[15..12] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP1_RSVD_QTM_SHFT 12 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP1_FFA_QTM_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP1_FFA_QTM_MASK \ + 0x00000F00 /* CSR_TXP1_FFA_QTM[11..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP1_FFA_QTM_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP0_RSVD_QTM_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP0_RSVD_QTM_MASK \ + 0x000000F0 /* CSR_TXP0_RSVD_QTM[7..4] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP0_RSVD_QTM_SHFT 4 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP0_FFA_QTM_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP0_FFA_QTM_MASK \ + 0x0000000F /* CSR_TXP0_FFA_QTM[3..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG0_CSR_TXP0_FFA_QTM_SHFT 0 + +/* +* ---WPDMA_TX_QOS_QTM_CFG1 (0x18024000 + 0x2D4)--- +* CSR_DMAD_FFA_QTM[3..0] - (RW) CSR_DMAD_FFA_QTM +* CSR_DMAD_RSVD_QTM[7..4] - (RW) CSR_DMAD_RSVD_QTM +* CSR_TXD_FFA_QTM[11..8] - (RW) CSR_TXD_FFA_QTM +* CSR_TXD_RSVD_QTM[15..12] - (RW) CSR_TXD_RSVD_QTM +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_TXD_RSVD_QTM_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_TXD_RSVD_QTM_MASK \ + 0x0000F000 /* CSR_TXD_RSVD_QTM[15..12] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_TXD_RSVD_QTM_SHFT 12 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_TXD_FFA_QTM_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_TXD_FFA_QTM_MASK \ + 0x00000F00 /* CSR_TXD_FFA_QTM[11..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_TXD_FFA_QTM_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_DMAD_RSVD_QTM_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_DMAD_RSVD_QTM_MASK \ + 0x000000F0 /* CSR_DMAD_RSVD_QTM[7..4] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_DMAD_RSVD_QTM_SHFT 4 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_DMAD_FFA_QTM_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_DMAD_FFA_QTM_MASK \ + 0x0000000F /* CSR_DMAD_FFA_QTM[3..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_QOS_QTM_CFG1_CSR_DMAD_FFA_QTM_SHFT 0 + +/* +* ---HOST_PRI_INT_STA (0x18024000 + 0x2E0)--- +* host_pri_int_sts_0[0] - (W1C) rx_done_int[0], W1C to clear delay +interrupt +* host_pri_int_sts_1[1] - (W1C) rx_done_int[1], W1C to clear delay +interrupt +* RESERVED2[31..2] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_1_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_1_MASK \ + 0x00000002 /* host_pri_int_sts_1[1] */ +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_1_SHFT 1 +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_0_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_0_MASK \ + 0x00000001 /* host_pri_int_sts_0[0] */ +#define WF_WFDMA_HOST_DMA0_HOST_PRI_INT_STA_host_pri_int_sts_0_SHFT 0 + +/* +* ---HOST_PER_INT_ENA_STA (0x18024000 + 0x2E4)--- +* wpdma_per_int_sts[3..0] - (W1C) status bit for rx ring periodic delayed +* interrupt to tracking ring is full or not, start delayed interrupt timer when +* RX ring is not full from falling edge of full flag and reset when ring full +* flag is asserted +* RESERVED4[15..4] - (RO) Reserved bits +* wpdma_per_int_ena[19..16] - (RW) enable bit for rx ring periodic delayed +* interrupt to tracking ring is full or not, start delayed interrupt timer when +* RX ring is not full from falling edge of full flag and reset when ring full +* flag is asserted +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_wpdma_per_int_ena_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_wpdma_per_int_ena_MASK \ + 0x000F0000 /* wpdma_per_int_ena[19..16] */ +#define WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_wpdma_per_int_ena_SHFT 16 +#define WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_wpdma_per_int_sts_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_wpdma_per_int_sts_MASK \ + 0x0000000F /* wpdma_per_int_sts[3..0] */ +#define WF_WFDMA_HOST_DMA0_HOST_PER_INT_ENA_STA_wpdma_per_int_sts_SHFT 0 + +/* +* ---HOST_PER_DLY_INT_CFG (0x18024000 + 0x2E8)--- +* wpdma_per_max_ptime[7..0] - (RW) Specified Max pending time for the +* internal RX ring full flag falling edge. When the pending time equal or +greater +* PER_MAX_PTIME x 20us or the # of pended TX_DONE_INT equal or greater than +* TX_MAX_PINT (see above), an Final TX_DLY_INT is generated +* Set to 0 will disable pending interrupt +* time check +* wpdma_per_dly_int_en[11..8] - (RW) RX periodic Delayed Interrupt Enable +* 1: Enable RX periodic delayed interrupt +mechanism +* 0: Disable RX periodic delayed interrupt +mechanism +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_wpdma_per_dly_int_en_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_wpdma_per_dly_int_en_MASK \ + 0x00000F00 /* wpdma_per_dly_int_en[11..8] */ +#define WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_wpdma_per_dly_int_en_SHFT 8 +#define WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_wpdma_per_max_ptime_ADDR \ + WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_ADDR +#define WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_wpdma_per_max_ptime_MASK \ + 0x000000FF /* wpdma_per_max_ptime[7..0] */ +#define WF_WFDMA_HOST_DMA0_HOST_PER_DLY_INT_CFG_wpdma_per_max_ptime_SHFT 0 + +/* +* ---WPDMA_PRI_DLY_INT_CFG0 (0x18024000 + 0x2F0)--- +* PRI0_MAX_PTIME[7..0] - (RW) Specified Max pending time for the +* internal PRI0_DONE_INT. When the pending time equal or greater PRI0_MAX_PTIME +x +* 20us or the # of pended PRI0_DONE_INT equal or greater than PRI0_MAX_PINT (see +* above), an Final PRI0_DLY_INT is generated +* Set to 0 will disable pending interrupt +* time check +* PRI0_MAX_PINT[14..8] - (RW) Specified Max # of pended interrupts. +* When the # of pended interrupts equal or +* greater than the value specified here or interrupt pending time reach the +limit +* (See below), a Final PRI0_DLY_INT is generated. +* Set to 0 will disable pending interrupt +* count check +* PRI0_DLY_INT_EN[15] - (RW) Priority Delayed Interrupt Enable +* 1: Enable Priority delayed interrupt +mechanism +* 0: Disable Priority delayed interrupt +mechanism +* In AXE host_dma0, these PRI1_* settings are +* for rx_ring[1]_int, and PRI0_* settings are for rx_ring[0]_int +* In AXE host_dma1, these PRI1_* settings are +* for rx_ring[0]_int, and PRI0_* settings are for Ored-tx_ring[14:0]_int +* In AXE mcu_dma0 and mcu_dma1, there are no +* priority interrupt thus no this 0x2E0 CR!! +* PRI1_MAX_PTIME[23..16] - (RW) Specified Max pending time for the +* internal PRI1_DONE_INT. When the pending time equal or greater PRI1_MAX_PTIME +x +* 20us or the # of pended PRI1_DONE_INT equal or greater than PRI1_MAX_PINT (see +* above), an Final PRI1_DLY_INT is generated +* Set to 0 will disable pending interrupt +* time check +* PRI1_MAX_PINT[30..24] - (RW) Specified Max # of pended interrupts. +* When the # of pended interrupts equal or +* greater than the value specified here or interrupt pending time reach the +limit +* (See below), a Final PRI1_DLY_INT is generated. +* Set to 0 will disable pending interrupt +* count check +* PRI1_DLY_INT_EN[31] - (RW) Priority Delayed Interrupt Enable +* 1: Enable Priority delayed interrupt +mechanism +* 0: Disable Priority delayed interrupt +mechanism +* In AXE host_dma0, these PRI1_* settings are +* for rx_ring[1]_int, and PRI0_* settings are for rx_ring[0]_int +* In AXE host_dma1, these PRI1_* settings are +* for rx_ring[0]_int, and PRI0_* settings are for Ored-tx_ring[14:0]_int +* In AXE mcu_dma0 and mcu_dma1, there are no +* priority interrupt thus no this 0x2E0 CR!! +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_DLY_INT_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_DLY_INT_EN_MASK \ + 0x80000000 /* PRI1_DLY_INT_EN[31] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_DLY_INT_EN_SHFT 31 +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PINT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PINT_MASK \ + 0x7F000000 /* PRI1_MAX_PINT[30..24] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PINT_SHFT 24 +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PTIME_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PTIME_MASK \ + 0x00FF0000 /* PRI1_MAX_PTIME[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PTIME_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_DLY_INT_EN_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_DLY_INT_EN_MASK \ + 0x00008000 /* PRI0_DLY_INT_EN[15] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_DLY_INT_EN_SHFT 15 +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PINT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PINT_MASK \ + 0x00007F00 /* PRI0_MAX_PINT[14..8] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PINT_SHFT 8 +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PTIME_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PTIME_MASK \ + 0x000000FF /* PRI0_MAX_PTIME[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PTIME_SHFT 0 + +/* +* ---WPDMA_TX_RING0_CTRL0 (0x18024000 + 0x300)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring0 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING0_CTRL1 (0x18024000 + 0x304)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring0. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring0 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING0_CTRL2 (0x18024000 + 0x308)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING0_CTRL3 (0x18024000 + 0x30c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING1_CTRL0 (0x18024000 + 0x310)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring1 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING1_CTRL1 (0x18024000 + 0x314)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring1. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring1 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING1_CTRL2 (0x18024000 + 0x318)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING1_CTRL3 (0x18024000 + 0x31c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING2_CTRL0 (0x18024000 + 0x320)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring2 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING2_CTRL1 (0x18024000 + 0x324)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring2. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring2 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING2_CTRL2 (0x18024000 + 0x328)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING2_CTRL3 (0x18024000 + 0x32c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING3_CTRL0 (0x18024000 + 0x330)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring3 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING3_CTRL1 (0x18024000 + 0x334)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring3. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring3 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING3_CTRL2 (0x18024000 + 0x338)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING3_CTRL3 (0x18024000 + 0x33c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING0_CTRL0 (0x18024000 + 0x500)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #0 +* (GE ports). It should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING0_CTRL1 (0x18024000 + 0x504)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD +* Ring #0. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring0 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING0_CTRL2 (0x18024000 + 0x508)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to +* allocate to RXD Ring #0. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING0_CTRL3 (0x18024000 + 0x50c)--- +* DMA_IDX[11..0] - (RW) In normal operation, user dma_index +* would udated by hardware when moving rx packet done. User should not write +dma_index. +* Point to the next RXD DMA wants to use in +* FDS Ring#0. It should be a 8-DWORD aligned address. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING1_CTRL0 (0x18024000 + 0x510)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #1 +* (GE ports). It should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING1_CTRL1 (0x18024000 + 0x514)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD +* Ring #1. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring1 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING1_CTRL2 (0x18024000 + 0x518)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to +* allocate to RXD Ring #1. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING1_CTRL3 (0x18024000 + 0x51c)--- +* DMA_IDX[11..0] - (RW) In normal operation, user dma_index +* would udated by hardware when moving rx packet done. User should not write +dma_index. +* Point to the next RXD DMA wants to use in +* FDS Ring#1. It should be a 8-DWORD aligned address. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING2_CTRL0 (0x18024000 + 0x520)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #2 +* (GE ports). It should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING2_CTRL1 (0x18024000 + 0x524)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD +* Ring #2. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring2 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING2_CTRL2 (0x18024000 + 0x528)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to +* allocate to RXD Ring #2. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING2_CTRL3 (0x18024000 + 0x52C)--- +* DMA_IDX[11..0] - (RW) In normal operation, user dma_index +* would udated by hardware when moving rx packet done. User should not write +dma_index. +* Point to the next RXD DMA wants to use in +* FDS Ring#2. It should be a 8-DWORD aligned address. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING3_CTRL0 (0x18024000 + 0x530)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #3 +* (GE ports). It should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING3_CTRL1 (0x18024000 + 0x534)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD +* Ring #3. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring3 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING3_CTRL2 (0x18024000 + 0x538)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to +* allocate to RXD Ring #3. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING3_CTRL3 (0x18024000 + 0x53C)--- +* DMA_IDX[11..0] - (RW) In normal operation, user dma_index +* would udated by hardware when moving rx packet done. User should not write +dma_index. +* Point to the next RXD DMA wants to use in +* FDS Ring#3. It should be a 8-DWORD aligned address. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING4_CTRL0 (0x18024000 + 0x540)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #0 +* (GE ports). It should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING4_CTRL1 (0x18024000 + 0x544)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD +* Ring #0. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring0 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING4_CTRL2 (0x18024000 + 0x548)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to +* allocate to RXD Ring #0. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING4_CTRL3 (0x18024000 + 0x54c)--- +* DMA_IDX[11..0] - (RW) In normal operation, user dma_index +* would udated by hardware when moving rx packet done. User should not write +dma_index. +* Point to the next RXD DMA wants to use in +* FDS Ring#0. It should be a 8-DWORD aligned address. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING5_CTRL0 (0x18024000 + 0x550)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #1 +* (GE ports). It should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING5_CTRL1 (0x18024000 + 0x554)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD +* Ring #1. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring1 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING5_CTRL2 (0x18024000 + 0x558)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to +* allocate to RXD Ring #1. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING5_CTRL3 (0x18024000 + 0x55c)--- +* DMA_IDX[11..0] - (RW) In normal operation, user dma_index +* would udated by hardware when moving rx packet done. User should not write +dma_index. +* Point to the next RXD DMA wants to use in +* FDS Ring#1. It should be a 8-DWORD aligned address. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING6_CTRL0 (0x18024000 + 0x560)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #2 +* (GE ports). It should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING6_CTRL1 (0x18024000 + 0x564)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD +* Ring #2. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring2 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING6_CTRL2 (0x18024000 + 0x568)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to +* allocate to RXD Ring #2. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING6_CTRL3 (0x18024000 + 0x56C)--- +* DMA_IDX[11..0] - (RW) In normal operation, user dma_index +* would udated by hardware when moving rx packet done. User should not write +dma_index. +* Point to the next RXD DMA wants to use in +* FDS Ring#2. It should be a 8-DWORD aligned address. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING7_CTRL0 (0x18024000 + 0x570)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #3 +* (GE ports). It should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING7_CTRL1 (0x18024000 + 0x574)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD +* Ring #3. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring3 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING7_CTRL2 (0x18024000 + 0x578)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to +* allocate to RXD Ring #3. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING7_CTRL3 (0x18024000 + 0x57C)--- +* DMA_IDX[11..0] - (RW) In normal operation, user dma_index +* would udated by hardware when moving rx packet done. User should not write +dma_index. +* Point to the next RXD DMA wants to use in +* FDS Ring#3. It should be a 8-DWORD aligned address. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING0_EXT_CTRL (0x18024000 + 0x600)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #0 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING1_EXT_CTRL (0x18024000 + 0x604)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #1 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING2_EXT_CTRL (0x18024000 + 0x608)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #2 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING3_EXT_CTRL (0x18024000 + 0x60C)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #3 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING0_EXT_CTRL (0x18024000 + 0x680)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #0 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING1_EXT_CTRL (0x18024000 + 0x684)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #1 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING2_EXT_CTRL (0x18024000 + 0x688)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #2 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING3_EXT_CTRL (0x18024000 + 0x68C)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #3 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING4_EXT_CTRL (0x18024000 + 0x690)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #0 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING5_EXT_CTRL (0x18024000 + 0x694)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #1 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING6_EXT_CTRL (0x18024000 + 0x698)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #2 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING7_EXT_CTRL (0x18024000 + 0x69C)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #3 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING0_BKRS_CTRL0 (0x18024000 + 0xA00)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING0_BKRS_CTRL1 (0x18024000 + 0xA04)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING0_BKRS_CTRL2 (0x18024000 + 0xA08)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING1_BKRS_CTRL0 (0x18024000 + 0xA10)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING1_BKRS_CTRL1 (0x18024000 + 0xA14)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING1_BKRS_CTRL2 (0x18024000 + 0xA18)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING2_BKRS_CTRL0 (0x18024000 + 0xA20)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING2_BKRS_CTRL1 (0x18024000 + 0xA24)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING2_BKRS_CTRL2 (0x18024000 + 0xA28)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING3_BKRS_CTRL0 (0x18024000 + 0xA30)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING3_BKRS_CTRL1 (0x18024000 + 0xA34)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING3_BKRS_CTRL2 (0x18024000 + 0xA38)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING0_BKRS_CTRL0 (0x18024000 + 0xC00)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING0_BKRS_CTRL1 (0x18024000 + 0xC04)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING0_BKRS_CTRL2 (0x18024000 + 0xC08)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING1_BKRS_CTRL0 (0x18024000 + 0xC10)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING1_BKRS_CTRL1 (0x18024000 + 0xC14)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING1_BKRS_CTRL2 (0x18024000 + 0xC18)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING2_BKRS_CTRL0 (0x18024000 + 0xC20)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING2_BKRS_CTRL1 (0x18024000 + 0xC24)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING2_BKRS_CTRL2 (0x18024000 + 0xC28)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING3_BKRS_CTRL0 (0x18024000 + 0xC30)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING3_BKRS_CTRL1 (0x18024000 + 0xC34)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING3_BKRS_CTRL2 (0x18024000 + 0xC38)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING4_BKRS_CTRL0 (0x18024000 + 0xC40)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING4_BKRS_CTRL1 (0x18024000 + 0xC44)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING4_BKRS_CTRL2 (0x18024000 + 0xC48)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING5_BKRS_CTRL0 (0x18024000 + 0xC50)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING5_BKRS_CTRL1 (0x18024000 + 0xC54)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING5_BKRS_CTRL2 (0x18024000 + 0xC58)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING6_BKRS_CTRL0 (0x18024000 + 0xC60)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING6_BKRS_CTRL1 (0x18024000 + 0xC64)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING6_BKRS_CTRL2 (0x18024000 + 0xC68)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING7_BKRS_CTRL0 (0x18024000 + 0xC70)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING7_BKRS_CTRL1 (0x18024000 + 0xC74)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING7_BKRS_CTRL2 (0x18024000 + 0xC78)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +#ifdef __cplusplus +} +#endif + +#endif /* __WF_WFDMA_HOST_DMA0_REGS_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/soc3_0/wf_wfdma_host_dma1.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/soc3_0/wf_wfdma_host_dma1.h new file mode 100644 index 0000000000000..38a666ca2d6fb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/coda/soc3_0/wf_wfdma_host_dma1.h @@ -0,0 +1,8328 @@ +/* [File] : wf_wfdma_host_dma1.h */ +/* [Revision time] : Mon Apr 15 14:14:46 2019 */ +/* [Description] : This file is auto generated by CODA */ +/* [Copyright] : Copyright (C) 2019 Mediatek Incorportion. All rights */ +/* reserved. */ + +#ifndef __WF_WFDMA_HOST_DMA1_REGS_H__ +#define __WF_WFDMA_HOST_DMA1_REGS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ************************************************************************** */ +/* */ +/* WF_WFDMA_HOST_DMA1 CR Definitions */ +/* */ +/* ************************************************************************** */ + +#define WF_WFDMA_HOST_DMA1_BASE 0x7C025000 + +#define WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0XA0) /* 50A0 */ +#define WF_WFDMA_HOST_DMA1_HOST_IF_RX_DONE_STS_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0XA4) /* 50A4 */ +#define WF_WFDMA_HOST_DMA1_TX_DMAD_RNG_START_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x0B0) /* 50B0 */ +#define WF_WFDMA_HOST_DMA1_TX_DMAD_RNG_START_EXT_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x0B4) /* 50B4 */ +#define WF_WFDMA_HOST_DMA1_TX_DMAD_RNG_END_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x0B8) /* 50B8 */ +#define WF_WFDMA_HOST_DMA1_TX_DMAD_RNG_END_EXT_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x0BC) /* 50BC */ +#define WF_WFDMA_HOST_DMA1_RX_DMAD_RNG_START_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x0C0) /* 50C0 */ +#define WF_WFDMA_HOST_DMA1_RX_DMAD_RNG_START_EXT_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x0C4) /* 50C4 */ +#define WF_WFDMA_HOST_DMA1_RX_DMAD_RNG_END_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x0C8) /* 50C8 */ +#define WF_WFDMA_HOST_DMA1_RX_DMAD_RNG_END_EXT_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x0CC) /* 50CC */ +#define WF_WFDMA_HOST_DMA1_TX_PLD_RNG_START_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x0D0) /* 50D0 */ +#define WF_WFDMA_HOST_DMA1_TX_PLD_RNG_START_EXT_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x0D4) /* 50D4 */ +#define WF_WFDMA_HOST_DMA1_TX_PLD_RNG_END_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x0D8) /* 50D8 */ +#define WF_WFDMA_HOST_DMA1_TX_PLD_RNG_END_EXT_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x0DC) /* 50DC */ +#define WF_WFDMA_HOST_DMA1_RX_PLD_RNG_START_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x0E0) /* 50E0 */ +#define WF_WFDMA_HOST_DMA1_RX_PLD_RNG_START_EXT_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x0E4) /* 50E4 */ +#define WF_WFDMA_HOST_DMA1_RX_PLD_RNG_END_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x0E8) /* 50E8 */ +#define WF_WFDMA_HOST_DMA1_RX_PLD_RNG_END_EXT_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x0EC) /* 50EC */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_RST_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x100) /* 5100 */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x104) /* 5104 */ +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0X108) /* 5108 */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x10C) /* 510C */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0X110) /* 5110 */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0X114) /* 5114 */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DUMMY_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x120) /* 5120 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_DBG_IDX_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x124) /* 5124 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_DBG_PROBE_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x128) /* 5128 */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x12C) /* 512C */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_PROBE_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x130) /* 5130 */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DMASHDL_DBG_PROBE_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x134) /* 5134 */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x138) /* 5138 */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x13c) /* 513C */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_FIFO_TEST_MOD_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x140) /* 5140 */ +#define WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x1E8) /* 51E8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x1EC) /* 51EC */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x1F0) /* 51F0 */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x1F4) /* 51F4 */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x1F8) /* 51F8 */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x1FC) /* 51FC */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x200) /* 5200 */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0X204) /* 5204 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x208) /* 5208 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x20C) /* 520C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_TX_Q_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x224) /* 5224 */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0X228) /* 5228 */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0X22C) /* 522C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x230) /* 5230 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_MISC_CFG_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x234) /* 5234 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x240) /* 5240 */ +#define WF_WFDMA_HOST_DMA1_MD_INT_STA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x250) /* 5250 */ +#define WF_WFDMA_HOST_DMA1_MD_INT_ENA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x254) /* 5254 */ +#define WF_WFDMA_HOST_DMA1_MCU2MD_SW_INT_SET_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x258) /* 5258 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH10_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x260) /* 5260 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH32_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x264) /* 5264 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH54_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x268) /* 5268 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH76_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x26C) /* 526C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x280) /* 5280 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x284) /* 5284 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_EXT_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x288) /* 5288 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x298) /* 5298 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x29C) /* 529C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_DBG0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2A0) /* 52A0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_DBG1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2A4) /* 52A4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_DBG0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2A8) /* 52A8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_DBG1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2AC) /* 52AC */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2B0) /* 52B0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2B4) /* 52B4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2C0) /* 52C0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2C4) /* 52C4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2C8) /* 52C8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2CC) /* 52CC */ +#define WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2E0) /* 52E0 */ +#define WF_WFDMA_HOST_DMA1_HOST_PER_INT_ENA_STA_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2E4) /* 52E4 */ +#define WF_WFDMA_HOST_DMA1_HOST_PER_DLY_INT_CFG_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2E8) /* 52E8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x2F0) /* 52F0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x300) /* 5300 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x304) /* 5304 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x308) /* 5308 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x30c) /* 530C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x310) /* 5310 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x314) /* 5314 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x318) /* 5318 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x31c) /* 531C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x320) /* 5320 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x324) /* 5324 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x328) /* 5328 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x32c) /* 532C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x330) /* 5330 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x334) /* 5334 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x338) /* 5338 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x33c) /* 533C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x340) /* 5340 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x344) /* 5344 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x348) /* 5348 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x34c) /* 534C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x350) /* 5350 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x354) /* 5354 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x358) /* 5358 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x35c) /* 535C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x360) /* 5360 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x364) /* 5364 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x368) /* 5368 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x36c) /* 536C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x370) /* 5370 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x374) /* 5374 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x378) /* 5378 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x37c) /* 537C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x380) /* 5380 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x384) /* 5384 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x388) /* 5388 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x38c) /* 538C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x390) /* 5390 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x394) /* 5394 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x398) /* 5398 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x39c) /* 539C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3a0) /* 53A0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3a4) /* 53A4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3a8) /* 53A8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3ac) /* 53AC */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3b0) /* 53B0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3b4) /* 53B4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3b8) /* 53B8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3bc) /* 53BC */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3c0) /* 53C0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3c4) /* 53C4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3c8) /* 53C8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3cc) /* 53CC */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3d0) /* 53D0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3d4) /* 53D4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3d8) /* 53D8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3dc) /* 53DC */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3e0) /* 53E0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3e4) /* 53E4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3e8) /* 53E8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3ec) /* 53EC */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3f0) /* 53F0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3f4) /* 53F4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3f8) /* 53F8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x3fc) /* 53FC */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x400) /* 5400 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x404) /* 5404 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x408) /* 5408 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x40c) /* 540C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x410) /* 5410 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x414) /* 5414 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x418) /* 5418 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x41c) /* 541C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x420) /* 5420 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x424) /* 5424 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x428) /* 5428 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x42c) /* 542C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x430) /* 5430 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x434) /* 5434 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x438) /* 5438 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x43c) /* 543C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x500) /* 5500 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x504) /* 5504 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x508) /* 5508 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x50c) /* 550C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x510) /* 5510 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x514) /* 5514 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x518) /* 5518 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x51c) /* 551C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x520) /* 5520 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x524) /* 5524 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x528) /* 5528 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x52C) /* 552C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x530) /* 5530 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x534) /* 5534 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x538) /* 5538 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL3_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x53C) /* 553C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x600) /* 5600 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x604) /* 5604 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x608) /* 5608 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x60C) /* 560C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x610) /* 5610 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x614) /* 5614 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x618) /* 5618 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x61C) /* 561C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x620) /* 5620 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x624) /* 5624 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x628) /* 5628 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x62C) /* 562C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x630) /* 5630 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x634) /* 5634 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x638) /* 5638 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x63C) /* 563C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x640) /* 5640 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x644) /* 5644 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x648) /* 5648 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x64C) /* 564C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x680) /* 5680 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x684) /* 5684 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x688) /* 5688 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_EXT_CTRL_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0x68C) /* 568C */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA00) /* 5A00 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA04) /* 5A04 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA08) /* 5A08 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA10) /* 5A10 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA14) /* 5A14 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA18) /* 5A18 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA20) /* 5A20 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA24) /* 5A24 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA28) /* 5A28 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA30) /* 5A30 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA34) /* 5A34 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA38) /* 5A38 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA40) /* 5A40 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA44) /* 5A44 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA48) /* 5A48 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA50) /* 5A50 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA54) /* 5A54 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA58) /* 5A58 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA60) /* 5A60 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA64) /* 5A64 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA68) /* 5A68 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA70) /* 5A70 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA74) /* 5A74 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA78) /* 5A78 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA80) /* 5A80 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA84) /* 5A84 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA88) /* 5A88 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA90) /* 5A90 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA94) /* 5A94 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xA98) /* 5A98 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAA0) /* 5AA0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAA4) /* 5AA4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAA8) /* 5AA8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAB0) /* 5AB0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAB4) /* 5AB4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAB8) /* 5AB8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAC0) /* 5AC0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAC4) /* 5AC4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAC8) /* 5AC8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAD0) /* 5AD0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAD4) /* 5AD4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAD8) /* 5AD8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAE0) /* 5AE0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAE4) /* 5AE4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAE8) /* 5AE8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAF0) /* 5AF0 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAF4) /* 5AF4 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xAF8) /* 5AF8 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB00) /* 5B00 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB04) /* 5B04 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB08) /* 5B08 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB10) /* 5B10 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB14) /* 5B14 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB18) /* 5B18 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB20) /* 5B20 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB24) /* 5B24 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB28) /* 5B28 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB30) /* 5B30 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB34) /* 5B34 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xB38) /* 5B38 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xC00) /* 5C00 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xC04) /* 5C04 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xC08) /* 5C08 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xC10) /* 5C10 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xC14) /* 5C14 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xC18) /* 5C18 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xC20) /* 5C20 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xC24) /* 5C24 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xC28) /* 5C28 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL0_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xC30) /* 5C30 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL1_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xC34) /* 5C34 */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_ADDR \ + (WF_WFDMA_HOST_DMA1_BASE + 0xC38) /* 5C38 */ + +/* +* ---HOST_IF_TX_DONE_STS (0x18025000 + 0XA0)--- +* fifo_dfet_txdone_dat0_done_sts[0] - (W1C) USB DAT0 FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint +buffer +* fifo_dfet_txdone_dat1_done_sts[1] - (W1C) USB DAT1 FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint +buffer +* fifo_dfet_txdone_dat2_done_sts[2] - (W1C) USB DAT2 FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint +buffer +* fifo_dfet_txdone_dat3_done_sts[3] - (W1C) USB DAT3 FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint +buffer +* fifo_dfet_txdone_dat4_done_sts[4] - (W1C) USB DAT4 FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint +buffer +* fifo_dfet_txdone_cmd_done_sts[5] - (W1C) USB CMD FIFO Tx status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint +buffer +* fifo_dfet_txdone_fwdl_done_sts[6] - (W1C) USB Firmware download FIFO Tx +status +* 0 : no tx done +* 1 : pdma fetch data from USB endpoint +buffer +* SDIO Mode (All SDIO Tx packet goto firmware +* download FIFO) +* 0 : no tx done +* 1 : pdma start to fetch data from SDIO +buffer +* RESERVED7[31..7] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_fwdl_done_sts_ADDR \ + \ + WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_fwdl_done_sts_MASK \ + \ + 0x00000040 /* fifo_dfet_txdone_fwdl_done_sts[6] */ +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_fwdl_done_sts_SHFT \ + \ + 6 +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_cmd_done_sts_ADDR \ + \ + WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_cmd_done_sts_MASK \ + \ + 0x00000020 /* fifo_dfet_txdone_cmd_done_sts[5] */ +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_cmd_done_sts_SHFT \ + \ + 5 +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat4_done_sts_ADDR \ + \ + WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat4_done_sts_MASK \ + \ + 0x00000010 /* fifo_dfet_txdone_dat4_done_sts[4] */ +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat4_done_sts_SHFT \ + \ + 4 +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat3_done_sts_ADDR \ + \ + WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat3_done_sts_MASK \ + \ + 0x00000008 /* fifo_dfet_txdone_dat3_done_sts[3] */ +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat3_done_sts_SHFT \ + \ + 3 +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat2_done_sts_ADDR \ + \ + WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat2_done_sts_MASK \ + \ + 0x00000004 /* fifo_dfet_txdone_dat2_done_sts[2] */ +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat2_done_sts_SHFT \ + \ + 2 +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat1_done_sts_ADDR \ + \ + WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat1_done_sts_MASK \ + \ + 0x00000002 /* fifo_dfet_txdone_dat1_done_sts[1] */ +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat1_done_sts_SHFT \ + \ + 1 +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat0_done_sts_ADDR \ + \ + WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_ADDR +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat0_done_sts_MASK \ + \ + 0x00000001 /* fifo_dfet_txdone_dat0_done_sts[0] */ +#define \ +WF_WFDMA_HOST_DMA1_HOST_IF_TX_DONE_STS_fifo_dfet_txdone_dat0_done_sts_SHFT \ + \ + 0 + +/* +* ---HOST_IF_RX_DONE_STS (0x18025000 + 0XA4)--- +* RESERVED0[0] - (RO) Reserved bits +* rx1_packet_done_sts[1] - (W1C) USB/SDIO Rx1 packet done status +* 0 : no rx packet done +* 1 : rx packet send to host interface +* Note : All SDIO Packet send to SIDO RX0 +port +* RESERVED2[31..2] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_HOST_IF_RX_DONE_STS_rx1_packet_done_sts_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_IF_RX_DONE_STS_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_IF_RX_DONE_STS_rx1_packet_done_sts_MASK \ + 0x00000002 /* rx1_packet_done_sts[1] */ +#define WF_WFDMA_HOST_DMA1_HOST_IF_RX_DONE_STS_rx1_packet_done_sts_SHFT 1 + +/* +* ---TX_DMAD_RNG_START (0x18025000 + 0x0B0)--- +* tx_dmad_rng_start[31..0] - (RW) TX DMAD address range start [31:0] +*/ +#define WF_WFDMA_HOST_DMA1_TX_DMAD_RNG_START_tx_dmad_rng_start_ADDR \ + WF_WFDMA_HOST_DMA1_TX_DMAD_RNG_START_ADDR +#define WF_WFDMA_HOST_DMA1_TX_DMAD_RNG_START_tx_dmad_rng_start_MASK \ + 0xFFFFFFFF /* tx_dmad_rng_start[31..0] */ +#define WF_WFDMA_HOST_DMA1_TX_DMAD_RNG_START_tx_dmad_rng_start_SHFT 0 + +/* +* ---TX_DMAD_RNG_START_EXT (0x18025000 + 0x0B4)--- +* tx_dmad_rng_start_ext[3..0] - (RW) TX DMAD address range start [35:32] +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_TX_DMAD_RNG_START_EXT_tx_dmad_rng_start_ext_ADDR \ + WF_WFDMA_HOST_DMA1_TX_DMAD_RNG_START_EXT_ADDR +#define WF_WFDMA_HOST_DMA1_TX_DMAD_RNG_START_EXT_tx_dmad_rng_start_ext_MASK \ + 0x0000000F /* tx_dmad_rng_start_ext[3..0] */ +#define WF_WFDMA_HOST_DMA1_TX_DMAD_RNG_START_EXT_tx_dmad_rng_start_ext_SHFT 0 + +/* +* ---TX_DMAD_RNG_END (0x18025000 + 0x0B8)--- +* tx_dmad_rng_end[31..0] - (RW) TX DMAD address range end [31:0] +*/ +#define WF_WFDMA_HOST_DMA1_TX_DMAD_RNG_END_tx_dmad_rng_end_ADDR \ + WF_WFDMA_HOST_DMA1_TX_DMAD_RNG_END_ADDR +#define WF_WFDMA_HOST_DMA1_TX_DMAD_RNG_END_tx_dmad_rng_end_MASK \ + 0xFFFFFFFF /* tx_dmad_rng_end[31..0] */ +#define WF_WFDMA_HOST_DMA1_TX_DMAD_RNG_END_tx_dmad_rng_end_SHFT 0 + +/* +* ---TX_DMAD_RNG_END_EXT (0x18025000 + 0x0BC)--- +* tx_dmad_rng_end_ext[3..0] - (RW) TX DMAD address range end [35:32] +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_TX_DMAD_RNG_END_EXT_tx_dmad_rng_end_ext_ADDR \ + WF_WFDMA_HOST_DMA1_TX_DMAD_RNG_END_EXT_ADDR +#define WF_WFDMA_HOST_DMA1_TX_DMAD_RNG_END_EXT_tx_dmad_rng_end_ext_MASK \ + 0x0000000F /* tx_dmad_rng_end_ext[3..0] */ +#define WF_WFDMA_HOST_DMA1_TX_DMAD_RNG_END_EXT_tx_dmad_rng_end_ext_SHFT 0 + +/* +* ---RX_DMAD_RNG_START (0x18025000 + 0x0C0)--- +* rx_dmad_rng_start[31..0] - (RW) RX DMAD address range start [31:0] +*/ +#define WF_WFDMA_HOST_DMA1_RX_DMAD_RNG_START_rx_dmad_rng_start_ADDR \ + WF_WFDMA_HOST_DMA1_RX_DMAD_RNG_START_ADDR +#define WF_WFDMA_HOST_DMA1_RX_DMAD_RNG_START_rx_dmad_rng_start_MASK \ + 0xFFFFFFFF /* rx_dmad_rng_start[31..0] */ +#define WF_WFDMA_HOST_DMA1_RX_DMAD_RNG_START_rx_dmad_rng_start_SHFT 0 + +/* +* ---RX_DMAD_RNG_START_EXT (0x18025000 + 0x0C4)--- +* rx_dmad_rng_start_ext[3..0] - (RW) RX DMAD address range start [35:32] +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_RX_DMAD_RNG_START_EXT_rx_dmad_rng_start_ext_ADDR \ + WF_WFDMA_HOST_DMA1_RX_DMAD_RNG_START_EXT_ADDR +#define WF_WFDMA_HOST_DMA1_RX_DMAD_RNG_START_EXT_rx_dmad_rng_start_ext_MASK \ + 0x0000000F /* rx_dmad_rng_start_ext[3..0] */ +#define WF_WFDMA_HOST_DMA1_RX_DMAD_RNG_START_EXT_rx_dmad_rng_start_ext_SHFT 0 + +/* +* ---RX_DMAD_RNG_END (0x18025000 + 0x0C8)--- +* rx_dmad_rng_end[31..0] - (RW) RX DMAD address range end [31:0] +*/ +#define WF_WFDMA_HOST_DMA1_RX_DMAD_RNG_END_rx_dmad_rng_end_ADDR \ + WF_WFDMA_HOST_DMA1_RX_DMAD_RNG_END_ADDR +#define WF_WFDMA_HOST_DMA1_RX_DMAD_RNG_END_rx_dmad_rng_end_MASK \ + 0xFFFFFFFF /* rx_dmad_rng_end[31..0] */ +#define WF_WFDMA_HOST_DMA1_RX_DMAD_RNG_END_rx_dmad_rng_end_SHFT 0 + +/* +* ---RX_DMAD_RNG_END_EXT (0x18025000 + 0x0CC)--- +* rx_dmad_rng_end_ext[3..0] - (RW) RX DMAD address range end [35:32] +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_RX_DMAD_RNG_END_EXT_rx_dmad_rng_end_ext_ADDR \ + WF_WFDMA_HOST_DMA1_RX_DMAD_RNG_END_EXT_ADDR +#define WF_WFDMA_HOST_DMA1_RX_DMAD_RNG_END_EXT_rx_dmad_rng_end_ext_MASK \ + 0x0000000F /* rx_dmad_rng_end_ext[3..0] */ +#define WF_WFDMA_HOST_DMA1_RX_DMAD_RNG_END_EXT_rx_dmad_rng_end_ext_SHFT 0 + +/* +* ---TX_PLD_RNG_START (0x18025000 + 0x0D0)--- +* tx_pld_rng_start[31..0] - (RW) TX PLD address range start [31:0] +*/ +#define WF_WFDMA_HOST_DMA1_TX_PLD_RNG_START_tx_pld_rng_start_ADDR \ + WF_WFDMA_HOST_DMA1_TX_PLD_RNG_START_ADDR +#define WF_WFDMA_HOST_DMA1_TX_PLD_RNG_START_tx_pld_rng_start_MASK \ + 0xFFFFFFFF /* tx_pld_rng_start[31..0] */ +#define WF_WFDMA_HOST_DMA1_TX_PLD_RNG_START_tx_pld_rng_start_SHFT 0 + +/* +* ---TX_PLD_RNG_START_EXT (0x18025000 + 0x0D4)--- +* tx_pld_rng_start_ext[3..0] - (RW) TX PLD address range start [35:32] +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_TX_PLD_RNG_START_EXT_tx_pld_rng_start_ext_ADDR \ + WF_WFDMA_HOST_DMA1_TX_PLD_RNG_START_EXT_ADDR +#define WF_WFDMA_HOST_DMA1_TX_PLD_RNG_START_EXT_tx_pld_rng_start_ext_MASK \ + 0x0000000F /* tx_pld_rng_start_ext[3..0] */ +#define WF_WFDMA_HOST_DMA1_TX_PLD_RNG_START_EXT_tx_pld_rng_start_ext_SHFT 0 + +/* +* ---TX_PLD_RNG_END (0x18025000 + 0x0D8)--- +* tx_pld_rng_end[31..0] - (RW) TX PLD address range end [31:0] +*/ +#define WF_WFDMA_HOST_DMA1_TX_PLD_RNG_END_tx_pld_rng_end_ADDR \ + WF_WFDMA_HOST_DMA1_TX_PLD_RNG_END_ADDR +#define WF_WFDMA_HOST_DMA1_TX_PLD_RNG_END_tx_pld_rng_end_MASK \ + 0xFFFFFFFF /* tx_pld_rng_end[31..0] */ +#define WF_WFDMA_HOST_DMA1_TX_PLD_RNG_END_tx_pld_rng_end_SHFT 0 + +/* +* ---TX_PLD_RNG_END_EXT (0x18025000 + 0x0DC)--- +* tx_pld_rng_end_ext[3..0] - (RW) TX PLD address range end [35:32] +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_TX_PLD_RNG_END_EXT_tx_pld_rng_end_ext_ADDR \ + WF_WFDMA_HOST_DMA1_TX_PLD_RNG_END_EXT_ADDR +#define WF_WFDMA_HOST_DMA1_TX_PLD_RNG_END_EXT_tx_pld_rng_end_ext_MASK \ + 0x0000000F /* tx_pld_rng_end_ext[3..0] */ +#define WF_WFDMA_HOST_DMA1_TX_PLD_RNG_END_EXT_tx_pld_rng_end_ext_SHFT 0 + +/* +* ---RX_PLD_RNG_START (0x18025000 + 0x0E0)--- +* rx_pld_rng_start[31..0] - (RW) RX PLD address range start [31:0] +*/ +#define WF_WFDMA_HOST_DMA1_RX_PLD_RNG_START_rx_pld_rng_start_ADDR \ + WF_WFDMA_HOST_DMA1_RX_PLD_RNG_START_ADDR +#define WF_WFDMA_HOST_DMA1_RX_PLD_RNG_START_rx_pld_rng_start_MASK \ + 0xFFFFFFFF /* rx_pld_rng_start[31..0] */ +#define WF_WFDMA_HOST_DMA1_RX_PLD_RNG_START_rx_pld_rng_start_SHFT 0 + +/* +* ---RX_PLD_RNG_START_EXT (0x18025000 + 0x0E4)--- +* rx_pld_rng_start_ext[3..0] - (RW) RX PLD address range start [35:32] +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_RX_PLD_RNG_START_EXT_rx_pld_rng_start_ext_ADDR \ + WF_WFDMA_HOST_DMA1_RX_PLD_RNG_START_EXT_ADDR +#define WF_WFDMA_HOST_DMA1_RX_PLD_RNG_START_EXT_rx_pld_rng_start_ext_MASK \ + 0x0000000F /* rx_pld_rng_start_ext[3..0] */ +#define WF_WFDMA_HOST_DMA1_RX_PLD_RNG_START_EXT_rx_pld_rng_start_ext_SHFT 0 + +/* +* ---RX_PLD_RNG_END (0x18025000 + 0x0E8)--- +* rx_pld_rng_end[31..0] - (RW) RX PLD address range end [31:0] +*/ +#define WF_WFDMA_HOST_DMA1_RX_PLD_RNG_END_rx_pld_rng_end_ADDR \ + WF_WFDMA_HOST_DMA1_RX_PLD_RNG_END_ADDR +#define WF_WFDMA_HOST_DMA1_RX_PLD_RNG_END_rx_pld_rng_end_MASK \ + 0xFFFFFFFF /* rx_pld_rng_end[31..0] */ +#define WF_WFDMA_HOST_DMA1_RX_PLD_RNG_END_rx_pld_rng_end_SHFT 0 + +/* +* ---RX_PLD_RNG_END_EXT (0x18025000 + 0x0EC)--- +* rx_pld_rng_end_ext[3..0] - (RW) RX PLD address range end [35:32] +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_RX_PLD_RNG_END_EXT_rx_pld_rng_end_ext_ADDR \ + WF_WFDMA_HOST_DMA1_RX_PLD_RNG_END_EXT_ADDR +#define WF_WFDMA_HOST_DMA1_RX_PLD_RNG_END_EXT_rx_pld_rng_end_ext_MASK \ + 0x0000000F /* rx_pld_rng_end_ext[3..0] */ +#define WF_WFDMA_HOST_DMA1_RX_PLD_RNG_END_EXT_rx_pld_rng_end_ext_SHFT 0 + +/* +* ---CONN_HIF_RST (0x18025000 + 0x100)--- +* RESERVED0[3..0] - (RO) Reserved bits +* conn_hif_logic_rst_n[4] - (RW) This conn_hif_logic_rst_n would reset +* wpdma logic partial control register, include Tx/Rx ring control. +* Also, conn_hif_logic_rst_n would reset wifi +* data path, include tx fifo, rx fifo, r2x_bridge, axi_mux and other other +* asynchronous bridge. +* (Note : conn_hif_logic_rst_n would not +* reset hif_dmashdl logic) +* dmashdl_all_rst_n[5] - (RW) This dmashdl_all_rst_n would reset +* hif_dmashdl_top, include logic and control register. +* RESERVED6[31..6] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_RST_dmashdl_all_rst_n_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_RST_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_RST_dmashdl_all_rst_n_MASK \ + 0x00000020 /* dmashdl_all_rst_n[5] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_RST_dmashdl_all_rst_n_SHFT 5 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_RST_conn_hif_logic_rst_n_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_RST_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_RST_conn_hif_logic_rst_n_MASK \ + 0x00000010 /* conn_hif_logic_rst_n[4] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_RST_conn_hif_logic_rst_n_SHFT 4 + +/* +* ---CONN_HIF_TOP_MISC (0x18025000 + 0x104)--- +* ahb_mux_2to1_ultra[1..0] - (RW) conn _hif ahb mux ultra +* ahb_mux_2to1_qos_en[2] - (RW) conn_hif ahb mux qos enable +* RESERVED3[15..3] - (RO) Reserved bits +* pdma_rxring1_immint_en[16] - (RW) PDMA RX Ring 1 Immediate Interrupt +Enable +* RESERVED17[31..17] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_pdma_rxring1_immint_en_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_pdma_rxring1_immint_en_MASK \ + 0x00010000 /* pdma_rxring1_immint_en[16] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_pdma_rxring1_immint_en_SHFT 16 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_ahb_mux_2to1_qos_en_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_ahb_mux_2to1_qos_en_MASK \ + 0x00000004 /* ahb_mux_2to1_qos_en[2] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_ahb_mux_2to1_qos_en_SHFT 2 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_ahb_mux_2to1_ultra_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_ahb_mux_2to1_ultra_MASK \ + 0x00000003 /* ahb_mux_2to1_ultra[1..0] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_TOP_MISC_ahb_mux_2to1_ultra_SHFT 0 + +/* +* ---HOST2MCU_SW_INT_SET (0x18025000 + 0X108)--- +* host2mcu_sw_int_0_set[0] - (WO) Driver set this bit to generate MCU +* interrupt and 0x5000_0110[0] will be set to 1. +* host2mcu_sw_int_1_set[1] - (WO) Driver set this bit to generate MCU +* interrupt and 0x5000_0110[1] will be set to 1. +* host2mcu_sw_int_2_set[2] - (WO) Driver set this bit to generate MCU +* interrupt and 0x5000_0110[2] will be set to 1. +* host2mcu_sw_int_3_set[3] - (WO) Driver set [0x0_4108] bit[3] to generate +* MCU interrupt and 0x5000_0110[3] will be set to 1. +* host2mcu_sw_int_4_set[4] - (WO) Driver set [0x0_4108] bit[4] to generate +* MCU interrupt and 0x5000_0110[4] will be set to 1. +* host2mcu_sw_int_5_set[5] - (WO) Driver set [0x0_4108] bit[5] to generate +* MCU interrupt and 0x5000_0110[5] will be set to 1. +* host2mcu_sw_int_6_set[6] - (WO) Driver set [0x0_4108] bit[6] to generate +* MCU interrupt and 0x5000_0110[6] will be set to 1. +* host2mcu_sw_int_7_set[7] - (WO) Driver set [0x0_4108] bit[7] to generate +* MCU interrupt and 0x5000_0110[7] will be set to 1. +* RESERVED8[31..8] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_7_set_ADDR \ + WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_7_set_MASK \ + 0x00000080 /* host2mcu_sw_int_7_set[7] */ +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_7_set_SHFT 7 +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_6_set_ADDR \ + WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_6_set_MASK \ + 0x00000040 /* host2mcu_sw_int_6_set[6] */ +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_6_set_SHFT 6 +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_5_set_ADDR \ + WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_5_set_MASK \ + 0x00000020 /* host2mcu_sw_int_5_set[5] */ +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_5_set_SHFT 5 +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_4_set_ADDR \ + WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_4_set_MASK \ + 0x00000010 /* host2mcu_sw_int_4_set[4] */ +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_4_set_SHFT 4 +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_3_set_ADDR \ + WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_3_set_MASK \ + 0x00000008 /* host2mcu_sw_int_3_set[3] */ +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_3_set_SHFT 3 +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_2_set_ADDR \ + WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_2_set_MASK \ + 0x00000004 /* host2mcu_sw_int_2_set[2] */ +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_2_set_SHFT 2 +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_1_set_ADDR \ + WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_1_set_MASK \ + 0x00000002 /* host2mcu_sw_int_1_set[1] */ +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_1_set_SHFT 1 +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_0_set_ADDR \ + WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_0_set_MASK \ + 0x00000001 /* host2mcu_sw_int_0_set[0] */ +#define WF_WFDMA_HOST_DMA1_HOST2MCU_SW_INT_SET_host2mcu_sw_int_0_set_SHFT 0 + +/* +* ---MCU2HOST_SW_INT_SET (0x18025000 + 0x10C)--- +* mcu2host_sw_int_set_0[0] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[0] to check +* interrupt status +* mcu2host_sw_int_set_1[1] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[1] to check +* interrupt status +* mcu2host_sw_int_set_2[2] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[2] to check +* interrupt status +* mcu2host_sw_int_set_3[3] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[3] to check +* interrupt status +* mcu2host_sw_int_set_4[4] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[4] to check +* interrupt status +* mcu2host_sw_int_set_5[5] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[5] to check +* interrupt status +* mcu2host_sw_int_set_6[6] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[6] to check +* interrupt status +* mcu2host_sw_int_set_7[7] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[7] to check +* interrupt status +* mcu2host_sw_int_set_8[8] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[0] to check +* interrupt status +* mcu2host_sw_int_set_9[9] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[1] to check +* interrupt status +* mcu2host_sw_int_set_10[10] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[2] to check +* interrupt status +* mcu2host_sw_int_set_11[11] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[3] to check +* interrupt status +* mcu2host_sw_int_set_12[12] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[4] to check +* interrupt status +* mcu2host_sw_int_set_13[13] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[5] to check +* interrupt status +* mcu2host_sw_int_set_14[14] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[6] to check +* interrupt status +* mcu2host_sw_int_set_15[15] - (WO) Internal CPU writes this register will +* trigger MCU2HOST software interrupt interrupt to host. +* Host could read [0x0_41F0] bit[7] to check +* interrupt status +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_15_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_15_MASK \ + 0x00008000 /* mcu2host_sw_int_set_15[15] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_15_SHFT 15 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_14_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_14_MASK \ + 0x00004000 /* mcu2host_sw_int_set_14[14] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_14_SHFT 14 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_13_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_13_MASK \ + 0x00002000 /* mcu2host_sw_int_set_13[13] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_13_SHFT 13 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_12_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_12_MASK \ + 0x00001000 /* mcu2host_sw_int_set_12[12] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_12_SHFT 12 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_11_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_11_MASK \ + 0x00000800 /* mcu2host_sw_int_set_11[11] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_11_SHFT 11 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_10_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_10_MASK \ + 0x00000400 /* mcu2host_sw_int_set_10[10] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_10_SHFT 10 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_9_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_9_MASK \ + 0x00000200 /* mcu2host_sw_int_set_9[9] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_9_SHFT 9 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_8_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_8_MASK \ + 0x00000100 /* mcu2host_sw_int_set_8[8] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_8_SHFT 8 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_7_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_7_MASK \ + 0x00000080 /* mcu2host_sw_int_set_7[7] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_7_SHFT 7 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_6_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_6_MASK \ + 0x00000040 /* mcu2host_sw_int_set_6[6] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_6_SHFT 6 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_5_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_5_MASK \ + 0x00000020 /* mcu2host_sw_int_set_5[5] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_5_SHFT 5 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_4_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_4_MASK \ + 0x00000010 /* mcu2host_sw_int_set_4[4] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_4_SHFT 4 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_3_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_3_MASK \ + 0x00000008 /* mcu2host_sw_int_set_3[3] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_3_SHFT 3 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_2_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_2_MASK \ + 0x00000004 /* mcu2host_sw_int_set_2[2] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_2_SHFT 2 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_1_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_1_MASK \ + 0x00000002 /* mcu2host_sw_int_set_1[1] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_1_SHFT 1 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_0_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_0_MASK \ + 0x00000001 /* mcu2host_sw_int_set_0[0] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_SET_mcu2host_sw_int_set_0_SHFT 0 + +/* +* ---MCU_INT_STA (0x18025000 + 0X110)--- +* host2mcu_sw_int_sts[7..0] - (W1C) MCU interrupt status, write 1 to clear +* the interrupt +* wpdma_tx_timeout_int_sts[8] - (W1C) WPDMA TX dma timeout interrupt stauts, +* write 1 to clear the interrupt +* wpdma_rx_timeout_int_sts[9] - (W1C) WPDMA RX dma timeout interrupt stauts, +* write 1 to clear the interrupt +* wifi_txfifo0_wr_ovf_int_sts[10] - (W1C) conn_hif txfifo erorr detec +* interruptt. It indicate tx-fifo memory write overflow. +* wifi_txfifo1_wr_ovf_int_sts[11] - (W1C) conn_hif txfifo erorr detec +* interruptt. It indicate tx-fifo memory write overflow. +* wifi_rxfifo_wr_ovf_int_sts[12] - (W1C) conn_hif rxfifo erorr detect +* interrupt. It indicate rx-fifo memory write overflow. +* wpdma_tx_dmad_mem_range_err_mcu_int_sts[13] - (W1C) WPDMA tx dma descriptor +* memory range error detection mcu interrupt status +* When user setup WPDMA_TX_DMAD_RNG (not +* equal to zero), design would check tx_dmad address. If address range not +* correct, it would alarm memory range error interrupt +* wpdma_rx_dmad_mem_range_err_mcu_int_sts[14] - (W1C) WPDMA rx dma descriptor +* memory range error detection mcu interrupt status +* When user setup WPDMA_RX_DMAD_RNG (not +* equal to zero), design would check rx_dmad address. If address range not +* correct, it would alarm memory range error interrupt +* wpdma_tx_payload_mem_range_err_mcu_int_sts[15] - (W1C) WPDMA tx payload +* memory range error detection mcu interrupt status +* When user setup WPDMA_TX_PLD_RNG (not equal +* to zero), design would check tx_dma payload address. If address range not +* correct, it would alarm memory range error interrupt +* wpdma_rx_payload_mem_range_err_mcu_int_sts[16] - (W1C) WPDMA rx payload +* memory range error detection mcu interrupt status +* When user setup WPDMA_RX_PLD_RNG (not equal +* to zero), design would check rx_dma payload address. If address range not +* correct, it would alarm memory range error interrupt +* RESERVED17[31..17] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_rx_payload_mem_range_err_mcu_int_sts_ADDR \ + \ + WF_WFDMA_HOST_DMA1_MCU_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_rx_payload_mem_range_err_mcu_int_sts_MASK \ + \ + 0x00010000 /* wpdma_rx_payload_mem_range_err_mcu_int_sts[16] */ +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_rx_payload_mem_range_err_mcu_int_sts_SHFT \ + \ + 16 +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_tx_payload_mem_range_err_mcu_int_sts_ADDR \ + \ + WF_WFDMA_HOST_DMA1_MCU_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_tx_payload_mem_range_err_mcu_int_sts_MASK \ + \ + 0x00008000 /* wpdma_tx_payload_mem_range_err_mcu_int_sts[15] */ +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_tx_payload_mem_range_err_mcu_int_sts_SHFT \ + \ + 15 +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_rx_dmad_mem_range_err_mcu_int_sts_ADDR \ + \ + WF_WFDMA_HOST_DMA1_MCU_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_rx_dmad_mem_range_err_mcu_int_sts_MASK \ + \ + 0x00004000 /* wpdma_rx_dmad_mem_range_err_mcu_int_sts[14] */ +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_rx_dmad_mem_range_err_mcu_int_sts_SHFT \ + \ + 14 +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_tx_dmad_mem_range_err_mcu_int_sts_ADDR \ + \ + WF_WFDMA_HOST_DMA1_MCU_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_tx_dmad_mem_range_err_mcu_int_sts_MASK \ + \ + 0x00002000 /* wpdma_tx_dmad_mem_range_err_mcu_int_sts[13] */ +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_tx_dmad_mem_range_err_mcu_int_sts_SHFT \ + \ + 13 +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wifi_rxfifo_wr_ovf_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wifi_rxfifo_wr_ovf_int_sts_MASK \ + 0x00001000 /* wifi_rxfifo_wr_ovf_int_sts[12] */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wifi_rxfifo_wr_ovf_int_sts_SHFT 12 +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wifi_txfifo1_wr_ovf_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wifi_txfifo1_wr_ovf_int_sts_MASK \ + 0x00000800 /* wifi_txfifo1_wr_ovf_int_sts[11] */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wifi_txfifo1_wr_ovf_int_sts_SHFT 11 +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wifi_txfifo0_wr_ovf_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wifi_txfifo0_wr_ovf_int_sts_MASK \ + 0x00000400 /* wifi_txfifo0_wr_ovf_int_sts[10] */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wifi_txfifo0_wr_ovf_int_sts_SHFT 10 +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_rx_timeout_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_rx_timeout_int_sts_MASK \ + 0x00000200 /* wpdma_rx_timeout_int_sts[9] */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_rx_timeout_int_sts_SHFT 9 +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_tx_timeout_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_tx_timeout_int_sts_MASK \ + 0x00000100 /* wpdma_tx_timeout_int_sts[8] */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_wpdma_tx_timeout_int_sts_SHFT 8 +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_host2mcu_sw_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_host2mcu_sw_int_sts_MASK \ + 0x000000FF /* host2mcu_sw_int_sts[7..0] */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_STA_host2mcu_sw_int_sts_SHFT 0 + +/* +* ---MCU_INT_ENA (0x18025000 + 0X114)--- +* host2mcu_sw_int_ena[7..0] - (RW) host2mcu interrupt enable +* wpdma_tx_dma_timeout_int_ena[8] - (RW) WPDMA TX error detection interrupt +enable +* wpdma_rx_dma_timeout_int_ena[9] - (RW) WPDMA RX error detection interrupt +enable +* wifi_txfifo0_wr_ovf_int_ena[10] - (RW) conn_hif txfifo erorr detect +* interrupt enable. +* wifi_txfifo1_wr_ovf_int_ena[11] - (RW) conn_hif txfifo erorr detect +* interrupt enable. +* wifi_rxfifo_wr_ovf_int_ena[12] - (RW) conn_hif rxfifo erorr detect interrupt +enable. +* wpdma_tx_dmad_mem_range_err_mcu_int_ena[13] - (RW) WPDMA tx dma descriptor +* memory range error detection interrupt enable +* wpdma_rx_dmad_mem_range_err_mcu_int_ena[14] - (RW) WPDMA rx dma descriptor +* memory range error detection interrupt enable +* wpdma_tx_payload_mem_range_err_mcu_int_ena[15] - (RW) WPDMA tx payload +* memory range error detection interrupt enable +* wpdma_rx_payload_mem_range_err_mcu_int_ena[16] - (RW) WPDMA rx payload +* memory range error detection interrupt enable +* RESERVED17[31..17] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_rx_payload_mem_range_err_mcu_int_ena_ADDR \ + \ + WF_WFDMA_HOST_DMA1_MCU_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_rx_payload_mem_range_err_mcu_int_ena_MASK \ + \ + 0x00010000 /* wpdma_rx_payload_mem_range_err_mcu_int_ena[16] */ +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_rx_payload_mem_range_err_mcu_int_ena_SHFT \ + \ + 16 +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_tx_payload_mem_range_err_mcu_int_ena_ADDR \ + \ + WF_WFDMA_HOST_DMA1_MCU_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_tx_payload_mem_range_err_mcu_int_ena_MASK \ + \ + 0x00008000 /* wpdma_tx_payload_mem_range_err_mcu_int_ena[15] */ +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_tx_payload_mem_range_err_mcu_int_ena_SHFT \ + \ + 15 +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_rx_dmad_mem_range_err_mcu_int_ena_ADDR \ + \ + WF_WFDMA_HOST_DMA1_MCU_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_rx_dmad_mem_range_err_mcu_int_ena_MASK \ + \ + 0x00004000 /* wpdma_rx_dmad_mem_range_err_mcu_int_ena[14] */ +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_rx_dmad_mem_range_err_mcu_int_ena_SHFT \ + \ + 14 +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_tx_dmad_mem_range_err_mcu_int_ena_ADDR \ + \ + WF_WFDMA_HOST_DMA1_MCU_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_tx_dmad_mem_range_err_mcu_int_ena_MASK \ + \ + 0x00002000 /* wpdma_tx_dmad_mem_range_err_mcu_int_ena[13] */ +#define \ +WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_tx_dmad_mem_range_err_mcu_int_ena_SHFT \ + \ + 13 +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wifi_rxfifo_wr_ovf_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wifi_rxfifo_wr_ovf_int_ena_MASK \ + 0x00001000 /* wifi_rxfifo_wr_ovf_int_ena[12] */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wifi_rxfifo_wr_ovf_int_ena_SHFT 12 +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wifi_txfifo1_wr_ovf_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wifi_txfifo1_wr_ovf_int_ena_MASK \ + 0x00000800 /* wifi_txfifo1_wr_ovf_int_ena[11] */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wifi_txfifo1_wr_ovf_int_ena_SHFT 11 +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wifi_txfifo0_wr_ovf_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wifi_txfifo0_wr_ovf_int_ena_MASK \ + 0x00000400 /* wifi_txfifo0_wr_ovf_int_ena[10] */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wifi_txfifo0_wr_ovf_int_ena_SHFT 10 +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_rx_dma_timeout_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_rx_dma_timeout_int_ena_MASK \ + 0x00000200 /* wpdma_rx_dma_timeout_int_ena[9] */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_rx_dma_timeout_int_ena_SHFT 9 +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_tx_dma_timeout_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_tx_dma_timeout_int_ena_MASK \ + 0x00000100 /* wpdma_tx_dma_timeout_int_ena[8] */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_wpdma_tx_dma_timeout_int_ena_SHFT 8 +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_host2mcu_sw_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_MCU_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_host2mcu_sw_int_ena_MASK \ + 0x000000FF /* host2mcu_sw_int_ena[7..0] */ +#define WF_WFDMA_HOST_DMA1_MCU_INT_ENA_host2mcu_sw_int_ena_SHFT 0 + +/* +* ---CONN_HIF_DUMMY (0x18025000 + 0x120)--- +* CONN_HIF_DUMMY[31..0] - (RW) Reserved CR, SE will use it for pcie +calibration! +*/ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DUMMY_CONN_HIF_DUMMY_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_DUMMY_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DUMMY_CONN_HIF_DUMMY_MASK \ + 0xFFFFFFFF /* CONN_HIF_DUMMY[31..0] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DUMMY_CONN_HIF_DUMMY_SHFT 0 + +/* +* ---WPDMA_DBG_IDX (0x18025000 + 0x124)--- +* PDMA_DBG_IDX[7..0] - (RW) PDMA debug index +* PDMA_DBG_Enable[8] - (RW) PDMA Debug Enable +* 0: PDMA_DBG_port would has no function +* 1 : PDMA DBG_IDX select PDMA debug flag +index +* RESERVED9[31..9] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_DBG_IDX_PDMA_DBG_Enable_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_DBG_IDX_PDMA_DBG_Enable_MASK \ + 0x00000100 /* PDMA_DBG_Enable[8] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_DBG_IDX_PDMA_DBG_Enable_SHFT 8 +#define WF_WFDMA_HOST_DMA1_WPDMA_DBG_IDX_PDMA_DBG_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_DBG_IDX_PDMA_DBG_IDX_MASK \ + 0x000000FF /* PDMA_DBG_IDX[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_DBG_IDX_PDMA_DBG_IDX_SHFT 0 + +/* +* ---WPDMA_DBG_PROBE (0x18025000 + 0x128)--- +* PDMA_DBG_PROBE[31..0] - (RO) PDMA Debug probe read +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_DBG_PROBE_PDMA_DBG_PROBE_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_DBG_PROBE_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_DBG_PROBE_PDMA_DBG_PROBE_MASK \ + 0xFFFFFFFF /* PDMA_DBG_PROBE[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_DBG_PROBE_PDMA_DBG_PROBE_SHFT 0 + +/* +* ---CONN_HIF_DBG_IDX (0x18025000 + 0x12C)--- +* conn_hif_dbg_byt0_sel[2..0] - (RW) conn_hif_dbg_byt0_sel : Select +* conn_hif_dbg[7:0] from "pdma_dbg"/"hif_dmashdl_top" +* conn_hif_dbg_byt1_sel[5..3] - (RW) conn_hif_dbg_byt1_sel : Select +* conn_hif_dbg[15:8] from "pdma_dbg"/"hif_dmashdl_top" +* conn_hif_dbg_byt2_sel[8..6] - (RW) conn_hif_dbg_byt2_sel : Select +* conn_hif_dbg[23:16] from "pdma_dbg"/"hif_dmashdl_top" +* conn_hif_dbg_byt3_sel[11..9] - (RW) conn_hif_dbg_byt3_sel : Select +* conn_hif_dbg[31:24] from "pdma_dbg"/"hif_dmashdl_top" +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_conn_hif_dbg_byt3_sel_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_conn_hif_dbg_byt3_sel_MASK \ + 0x00000E00 /* conn_hif_dbg_byt3_sel[11..9] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_conn_hif_dbg_byt3_sel_SHFT 9 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_conn_hif_dbg_byt2_sel_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_conn_hif_dbg_byt2_sel_MASK \ + 0x000001C0 /* conn_hif_dbg_byt2_sel[8..6] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_conn_hif_dbg_byt2_sel_SHFT 6 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_conn_hif_dbg_byt1_sel_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_conn_hif_dbg_byt1_sel_MASK \ + 0x00000038 /* conn_hif_dbg_byt1_sel[5..3] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_conn_hif_dbg_byt1_sel_SHFT 3 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_conn_hif_dbg_byt0_sel_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_conn_hif_dbg_byt0_sel_MASK \ + 0x00000007 /* conn_hif_dbg_byt0_sel[2..0] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_IDX_conn_hif_dbg_byt0_sel_SHFT 0 + +/* +* ---CONN_HIF_DBG_PROBE (0x18025000 + 0x130)--- +* conn_hif_dbg_probe[31..0] - (RO) conn_hif_dbg_probe read +*/ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_PROBE_conn_hif_dbg_probe_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_PROBE_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_PROBE_conn_hif_dbg_probe_MASK \ + 0xFFFFFFFF /* conn_hif_dbg_probe[31..0] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DBG_PROBE_conn_hif_dbg_probe_SHFT 0 + +/* +* ---CONN_HIF_DMASHDL_DBG_PROBE (0x18025000 + 0x134)--- +* DMASHDL_DBG_PROBE[15..0] - (RO) conn_hif_dmashdl_dbg_probe read +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DMASHDL_DBG_PROBE_DMASHDL_DBG_PROBE_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_DMASHDL_DBG_PROBE_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DMASHDL_DBG_PROBE_DMASHDL_DBG_PROBE_MASK \ + 0x0000FFFF /* DMASHDL_DBG_PROBE[15..0] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_DMASHDL_DBG_PROBE_DMASHDL_DBG_PROBE_SHFT 0 + +/* +* ---CONN_HIF_BUSY_STATUS (0x18025000 + 0x138)--- +* conn_hif_txfifo0_busy[0] - (RO) conn_hif txfifo0 busy status +* 0 : txfifo empty +* 1 : txfifo non empty +* conn_hif_txfifo1_busy[1] - (RO) conn_hif txfifo1 busy status +* 0 : txfifo empty +* 1 : txfifo non empty +* conn_hif_rxfifo_busy[2] - (RO) conn_hif rxfifo busy status +* 0 : rxfifo empty +* 1 : rxfifo non empty +* RESERVED[30..3] - (RO) Reserved CR +* conn_hif_busy[31] - (RO) Over all conn_hif busy status, it was +* busy summation of bit[6] ~ bit[0] status +*/ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_conn_hif_busy_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_conn_hif_busy_MASK \ + 0x80000000 /* conn_hif_busy[31] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_conn_hif_busy_SHFT 31 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_conn_hif_rxfifo_busy_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_conn_hif_rxfifo_busy_MASK \ + 0x00000004 /* conn_hif_rxfifo_busy[2] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_conn_hif_rxfifo_busy_SHFT 2 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_conn_hif_txfifo1_busy_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_conn_hif_txfifo1_busy_MASK \ + 0x00000002 /* conn_hif_txfifo1_busy[1] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_conn_hif_txfifo1_busy_SHFT 1 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_conn_hif_txfifo0_busy_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_conn_hif_txfifo0_busy_MASK \ + 0x00000001 /* conn_hif_txfifo0_busy[0] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_STATUS_conn_hif_txfifo0_busy_SHFT 0 + +/* +* ---CONN_HIF_BUSY_ENA (0x18025000 + 0x13c)--- +* conn_hif_txfifo0_busy_enable[0] - (RW) busy enable control +* 0: ignore busy status +* 1: conn_hif_busy would tack care busy +status +* conn_hif_txfifo1_busy_enable[1] - (RW) busy enable control +* 0: ignore busy status +* 1: conn_hif_busy would tack care busy +status +* conn_hif_rxfifo_busy_enable[2] - (RW) busy enable control +* 0: ignore busy status +* 1: conn_hif_busy would tack care busy +status +* RESERVED3[4..3] - (RO) Reserved bits +* RESERVED[31..5] - (RW) Reserved CR +*/ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_conn_hif_rxfifo_busy_enable_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_conn_hif_rxfifo_busy_enable_MASK \ + 0x00000004 /* conn_hif_rxfifo_busy_enable[2] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_conn_hif_rxfifo_busy_enable_SHFT 2 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_conn_hif_txfifo1_busy_enable_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_conn_hif_txfifo1_busy_enable_MASK \ + 0x00000002 /* conn_hif_txfifo1_busy_enable[1] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_conn_hif_txfifo1_busy_enable_SHFT 1 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_conn_hif_txfifo0_busy_enable_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_conn_hif_txfifo0_busy_enable_MASK \ + 0x00000001 /* conn_hif_txfifo0_busy_enable[0] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_BUSY_ENA_conn_hif_txfifo0_busy_enable_SHFT 0 + +/* +* ---CONN_HIF_FIFO_TEST_MOD (0x18025000 + 0x140)--- +* csr_wfdma_loopback_en[0] - (RW) conn_hif fifo loopback enable +* NOTICE : when loopback, OMIT_TX_INFO and +* OMIT_RX_INFO sould be both set to 1'b1 +* csr_wfdma_loopback_qsel[2..1] - (RW) No USE for (conn_hif fifo loopback +* packet go into Rx-ring number) +* RESERVED3[31..3] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_qsel_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_FIFO_TEST_MOD_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_qsel_MASK \ + 0x00000006 /* csr_wfdma_loopback_qsel[2..1] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_qsel_SHFT 1 +#define WF_WFDMA_HOST_DMA1_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_en_ADDR \ + WF_WFDMA_HOST_DMA1_CONN_HIF_FIFO_TEST_MOD_ADDR +#define WF_WFDMA_HOST_DMA1_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_en_MASK \ + 0x00000001 /* csr_wfdma_loopback_en[0] */ +#define WF_WFDMA_HOST_DMA1_CONN_HIF_FIFO_TEST_MOD_csr_wfdma_loopback_en_SHFT 0 + +/* +* ---WPDMA2HOST_ERR_INT_STA (0x18025000 + 0x1E8)--- +* wpdma_tx_timeout_int_sts[0] - (W1C) WPDMA TX error detection interrupt +* stauts, write 1 to clear the interrupt +* wpdma_rx_timeout_int_sts[1] - (W1C) WPDMA RX error detection interrupt +* stauts, write 1 to clear the interrupt +* RESERVED2[31..2] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_rx_timeout_int_sts_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_rx_timeout_int_sts_MASK \ + \ + 0x00000002 /* wpdma_rx_timeout_int_sts[1] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_rx_timeout_int_sts_SHFT \ + \ + 1 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_tx_timeout_int_sts_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_tx_timeout_int_sts_MASK \ + \ + 0x00000001 /* wpdma_tx_timeout_int_sts[0] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_STA_wpdma_tx_timeout_int_sts_SHFT \ + \ + 0 + +/* +* ---WPDMA2HOST_ERR_INT_ENA (0x18025000 + 0x1EC)--- +* wpdma_rx_timeout_int_ena[0] - (RW) WPDMA TX error detection interrupt +enable +* wpdma_tx_timeout_int_ena[1] - (RW) WPDMA RX error detection interrupt +enable +* RESERVED2[31..2] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_timeout_int_ena_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_timeout_int_ena_MASK \ + \ + 0x00000002 /* wpdma_tx_timeout_int_ena[1] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_tx_timeout_int_ena_SHFT \ + \ + 1 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_timeout_int_ena_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_timeout_int_ena_MASK \ + \ + 0x00000001 /* wpdma_rx_timeout_int_ena[0] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA2HOST_ERR_INT_ENA_wpdma_rx_timeout_int_ena_SHFT \ + \ + 0 + +/* +* ---MCU2HOST_SW_INT_STA (0x18025000 + 0x1F0)--- +* mcu2host_sw_int_0[0] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_1[1] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_2[2] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_3[3] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_4[4] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_5[5] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_6[6] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_7[7] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_8[8] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_9[9] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_10[10] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_11[11] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_12[12] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_13[13] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_14[14] - (W1C) mcu2host interrupt status +* mcu2host_sw_int_15[15] - (W1C) mcu2host interrupt status +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_15_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_15_MASK \ + 0x00008000 /* mcu2host_sw_int_15[15] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_15_SHFT 15 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_14_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_14_MASK \ + 0x00004000 /* mcu2host_sw_int_14[14] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_14_SHFT 14 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_13_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_13_MASK \ + 0x00002000 /* mcu2host_sw_int_13[13] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_13_SHFT 13 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_12_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_12_MASK \ + 0x00001000 /* mcu2host_sw_int_12[12] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_12_SHFT 12 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_11_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_11_MASK \ + 0x00000800 /* mcu2host_sw_int_11[11] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_11_SHFT 11 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_10_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_10_MASK \ + 0x00000400 /* mcu2host_sw_int_10[10] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_10_SHFT 10 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_9_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_9_MASK \ + 0x00000200 /* mcu2host_sw_int_9[9] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_9_SHFT 9 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_8_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_8_MASK \ + 0x00000100 /* mcu2host_sw_int_8[8] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_8_SHFT 8 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_7_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_7_MASK \ + 0x00000080 /* mcu2host_sw_int_7[7] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_7_SHFT 7 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_6_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_6_MASK \ + 0x00000040 /* mcu2host_sw_int_6[6] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_6_SHFT 6 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_5_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_5_MASK \ + 0x00000020 /* mcu2host_sw_int_5[5] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_5_SHFT 5 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_4_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_4_MASK \ + 0x00000010 /* mcu2host_sw_int_4[4] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_4_SHFT 4 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_3_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_3_MASK \ + 0x00000008 /* mcu2host_sw_int_3[3] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_3_SHFT 3 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_2_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_2_MASK \ + 0x00000004 /* mcu2host_sw_int_2[2] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_2_SHFT 2 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_1_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_1_MASK \ + 0x00000002 /* mcu2host_sw_int_1[1] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_1_SHFT 1 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_0_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_0_MASK \ + 0x00000001 /* mcu2host_sw_int_0[0] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_STA_mcu2host_sw_int_0_SHFT 0 + +/* +* ---MCU2HOST_SW_INT_ENA (0x18025000 + 0x1F4)--- +* mcu2host_int_ena_0[0] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_1[1] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_2[2] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_3[3] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_4[4] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_5[5] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_6[6] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_7[7] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_8[8] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_9[9] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_10[10] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_11[11] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_12[12] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_13[13] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_14[14] - (RW) MCU2HOST software interrupt interrupt +enable +* mcu2host_int_ena_15[15] - (RW) MCU2HOST software interrupt interrupt +enable +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_15_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_15_MASK \ + 0x00008000 /* mcu2host_int_ena_15[15] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_15_SHFT 15 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_14_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_14_MASK \ + 0x00004000 /* mcu2host_int_ena_14[14] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_14_SHFT 14 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_13_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_13_MASK \ + 0x00002000 /* mcu2host_int_ena_13[13] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_13_SHFT 13 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_12_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_12_MASK \ + 0x00001000 /* mcu2host_int_ena_12[12] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_12_SHFT 12 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_11_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_11_MASK \ + 0x00000800 /* mcu2host_int_ena_11[11] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_11_SHFT 11 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_10_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_10_MASK \ + 0x00000400 /* mcu2host_int_ena_10[10] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_10_SHFT 10 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_9_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_9_MASK \ + 0x00000200 /* mcu2host_int_ena_9[9] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_9_SHFT 9 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_8_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_8_MASK \ + 0x00000100 /* mcu2host_int_ena_8[8] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_8_SHFT 8 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_7_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_7_MASK \ + 0x00000080 /* mcu2host_int_ena_7[7] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_7_SHFT 7 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_6_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_6_MASK \ + 0x00000040 /* mcu2host_int_ena_6[6] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_6_SHFT 6 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_5_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_5_MASK \ + 0x00000020 /* mcu2host_int_ena_5[5] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_5_SHFT 5 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_4_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_4_MASK \ + 0x00000010 /* mcu2host_int_ena_4[4] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_4_SHFT 4 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_3_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_3_MASK \ + 0x00000008 /* mcu2host_int_ena_3[3] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_3_SHFT 3 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_2_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_2_MASK \ + 0x00000004 /* mcu2host_int_ena_2[2] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_2_SHFT 2 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_1_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_1_MASK \ + 0x00000002 /* mcu2host_int_ena_1[1] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_1_SHFT 1 +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_0_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_0_MASK \ + 0x00000001 /* mcu2host_int_ena_0[0] */ +#define WF_WFDMA_HOST_DMA1_MCU2HOST_SW_INT_ENA_mcu2host_int_ena_0_SHFT 0 + +/* +* ---SUBSYS2HOST_INT_STA (0x18025000 + 0x1F8)--- +* mac_int_sts_0[0] - (RO) MAC interrupt 0: Band0 TBTT +* interrupt(Check wf_int_wakeup_top/hwisr0 [0x820Fc03c]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_1[1] - (RO) MAC interrupt 1: Band0 Pre-TBTT +* interrupt(Check wf_int_wakeup_top/hwisr1 [0x820Fc044]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_2[2] - (RO) MAC interrupt 2: Band0 TX status +* interrupt(Check wf_int_wakeup_top/hwisr2 [0x820Fc04c]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_3[3] - (RO) MAC interrupt 3: Band0 Auto wakeup +* interrupt (Check wf_int_wakeup_top/hwisr3 [0x820Fc054]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_4[4] - (RO) MAC interrupt 4: Band0 GP timer +* interrupt (Check wf_int_wakeup_top/hwisr4 [0x820Fc05c]) +* 0 : no interrupt +* 1 : interrupt assert +* RESERVED5[7..5] - (RO) Reserved bits +* conn_hif_on_host_int_sts[8] - (RO) CONN_HIF_ON interrupt enable +* 0 : no conn_hif_on_host_int interrupt +* 1 : conn_hif_on_host_int interrupt assert. +* User should check conn_hif_on (host_csr) interrupt status and clear interrupt. +* conn2ap_sw_irq_sts[9] - (RO) MCUSYS conn2ap_sw_irq status (Check +* conn_mcu_config/EMI_CTL [0x80000150] bit[4:0]) +* 0 : no conn2ap_sw_irq interrupt. +* 1 : conn2ap_sw_irq interrupt assert. User +* should check mcusys_n9 interrupt status and clear interrupt. +* (conn_mcu_config/EMI_CTL [0x80000150] bit[4:0] != 0) +* dmashdl_int_sts[10] - (RO) DMASHDL error interrupt +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_5[11] - (RO) MAC interrupt 5: Band1 TBTT +* interrupt(Check wf_int_wakeup_top/hwisr0 [0x820Fc03c]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_6[12] - (RO) MAC interrupt 6: Band1 Pre-TBTT +* interrupt(Check wf_int_wakeup_top/hwisr1 [0x820Fc044]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_7[13] - (RO) MAC interrupt 7: Band1 TX status +* interrupt(Check wf_int_wakeup_top/hwisr2 [0x820Fc04c]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_8[14] - (RO) MAC interrupt 8: Band1 Auto wakeup +* interrupt (Check wf_int_wakeup_top/hwisr3 [0x820Fc054]) +* 0 : no interrupt +* 1 : interrupt assert +* mac_int_sts_9[15] - (RO) MAC interrupt 9: Band1 GP timer +* interrupt (Check wf_int_wakeup_top/hwisr4 [0x820Fc05c]) +* 0 : no interrupt +* 1 : interrupt assert +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_9_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_9_MASK \ + 0x00008000 /* mac_int_sts_9[15] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_9_SHFT 15 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_8_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_8_MASK \ + 0x00004000 /* mac_int_sts_8[14] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_8_SHFT 14 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_7_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_7_MASK \ + 0x00002000 /* mac_int_sts_7[13] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_7_SHFT 13 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_6_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_6_MASK \ + 0x00001000 /* mac_int_sts_6[12] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_6_SHFT 12 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_5_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_5_MASK \ + 0x00000800 /* mac_int_sts_5[11] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_5_SHFT 11 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_dmashdl_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_dmashdl_int_sts_MASK \ + 0x00000400 /* dmashdl_int_sts[10] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_dmashdl_int_sts_SHFT 10 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_conn2ap_sw_irq_sts_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_conn2ap_sw_irq_sts_MASK \ + 0x00000200 /* conn2ap_sw_irq_sts[9] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_conn2ap_sw_irq_sts_SHFT 9 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_conn_hif_on_host_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_conn_hif_on_host_int_sts_MASK \ + 0x00000100 /* conn_hif_on_host_int_sts[8] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_conn_hif_on_host_int_sts_SHFT 8 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_4_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_4_MASK \ + 0x00000010 /* mac_int_sts_4[4] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_4_SHFT 4 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_3_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_3_MASK \ + 0x00000008 /* mac_int_sts_3[3] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_3_SHFT 3 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_2_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_2_MASK \ + 0x00000004 /* mac_int_sts_2[2] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_2_SHFT 2 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_1_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_1_MASK \ + 0x00000002 /* mac_int_sts_1[1] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_1_SHFT 1 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_0_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_0_MASK \ + 0x00000001 /* mac_int_sts_0[0] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_STA_mac_int_sts_0_SHFT 0 + +/* +* ---SUBSYS2HOST_INT_ENA (0x18025000 + 0x1FC)--- +* mac_int_ena_0[0] - (RW) MAC interrupt enable +* mac_int_ena_1[1] - (RW) MAC interrupt enable +* mac_int_ena_2[2] - (RW) MAC interrupt enable +* mac_int_ena_3[3] - (RW) MAC interrupt enable +* mac_int_ena_4[4] - (RW) MAC interrupt enable +* RESERVED5[7..5] - (RO) Reserved bits +* conn_hif_on_host_int_ena[8] - (RW) CONN_HIF_ON interrupt enable +* conn2ap_sw_irq_ena[9] - (RW) MCUSYS conn2ap_sw_irq enable +* dmashdl_int_ena[10] - (RW) DMASHDL interrupt enable +* mac_int_ena_5[11] - (RW) MAC interrupt enable +* mac_int_ena_6[12] - (RW) MAC interrupt enable +* mac_int_ena_7[13] - (RW) MAC interrupt enable +* mac_int_ena_8[14] - (RW) MAC interrupt enable +* mac_int_ena_9[15] - (RW) MAC interrupt enable +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_9_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_9_MASK \ + 0x00008000 /* mac_int_ena_9[15] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_9_SHFT 15 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_8_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_8_MASK \ + 0x00004000 /* mac_int_ena_8[14] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_8_SHFT 14 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_7_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_7_MASK \ + 0x00002000 /* mac_int_ena_7[13] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_7_SHFT 13 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_6_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_6_MASK \ + 0x00001000 /* mac_int_ena_6[12] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_6_SHFT 12 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_5_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_5_MASK \ + 0x00000800 /* mac_int_ena_5[11] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_5_SHFT 11 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_dmashdl_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_dmashdl_int_ena_MASK \ + 0x00000400 /* dmashdl_int_ena[10] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_dmashdl_int_ena_SHFT 10 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_conn2ap_sw_irq_ena_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_conn2ap_sw_irq_ena_MASK \ + 0x00000200 /* conn2ap_sw_irq_ena[9] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_conn2ap_sw_irq_ena_SHFT 9 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_conn_hif_on_host_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_conn_hif_on_host_int_ena_MASK \ + 0x00000100 /* conn_hif_on_host_int_ena[8] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_conn_hif_on_host_int_ena_SHFT 8 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_4_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_4_MASK \ + 0x00000010 /* mac_int_ena_4[4] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_4_SHFT 4 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_3_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_3_MASK \ + 0x00000008 /* mac_int_ena_3[3] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_3_SHFT 3 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_2_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_2_MASK \ + 0x00000004 /* mac_int_ena_2[2] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_2_SHFT 2 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_1_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_1_MASK \ + 0x00000002 /* mac_int_ena_1[1] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_1_SHFT 1 +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_0_ADDR \ + WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_0_MASK \ + 0x00000001 /* mac_int_ena_0[0] */ +#define WF_WFDMA_HOST_DMA1_SUBSYS2HOST_INT_ENA_mac_int_ena_0_SHFT 0 + +/* +* ---HOST_INT_STA (0x18025000 + 0x200)--- +* rx_done_int_sts_0[0] - (W1C) RX Queue#0 packet receive interrupt +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* rx_done_int_sts_1[1] - (W1C) RX Queue#1 packet receive interrupt +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* rx_done_int_sts_2[2] - (W1C) RX Queue#2 packet receive interrupt +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* rx_done_int_sts_3[3] - (W1C) RX Queue#3 packet receive interrupt +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* tx_done_int_sts_0[4] - (W1C) TX Queue#0 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_1[5] - (W1C) TX Queue#1 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_2[6] - (W1C) TX Queue#2 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_3[7] - (W1C) TX Queue#3 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_4[8] - (W1C) TX Queue#4 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_5[9] - (W1C) TX Queue#5 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_6[10] - (W1C) TX Queue#6 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_7[11] - (W1C) TX Queue#7 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_8[12] - (W1C) TX Queue#8 packet transmit +* interruptWrite 1 to clear the interrupt +* tx_done_int_sts_9[13] - (W1C) TX Queue#9 packet transmit +* interruptWrite 1 to clear the interrupt +* tx_done_int_sts_10[14] - (W1C) TX Queue#10 packet transmit +* interruptWrite 1 to clear the interrupt +* tx_done_int_sts_11[15] - (W1C) TX Queue#11 packet transmit +* interruptWrite 1 to clear the interrupt +* tx_done_int_sts_12[16] - (W1C) TX Queue#12 packet transmit +* interruptWrite 1 to clear the interrupt +* tx_done_int_sts_13[17] - (W1C) TX Queue#13 packet transmit +* interruptWrite 1 to clear the interrupt +* tx_done_int_sts_14[18] - (W1C) TX Queue#14 packet transmit +* interruptWrite 1 to clear the interrupt +* RESERVED19[19] - (RO) Reserved bits +* rx_coherent_int_sts[20] - (W1C) RX_DMA finds data coherent event when +* checking ddone bit +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* tx_coherent_int_sts[21] - (W1C) TX_DMA finds data coherent event when +* checking ddone bit +* Write 1 to clear the interrupt +* Read to get the raw interrupt status +* RESERVED[23..22] - (RO) reserved, originally used for delayed +* interrupt of legacy TX/RX done +* wpdma2host_err_int_sts[24] - (RO) wpdma interrupt overall status +* User should should check WPDMA_ERR_INT_STA +* for each wpdma error interrupt status +* Host could read [0x0_41E8] to check +* indivisual wpdma2host_error interrupt status +* RESERVED[25] - (RO) reserved, originally used for delayed +* interrupt of legacy TX/RX done +* tx_done_int_sts_16[26] - (W1C) TX Queue#16 packet transmit interrupt +* Write 1 to clear the interrupt +* tx_done_int_sts_17[27] - (W1C) TX Queue#17 packet transmit interrupt +* Write 1 to clear the interrupt +* subsys_int_sts[28] - (RO) subsys interrupt overall status +* User should should check +* SUBSYS2HOST_INT_STA for each interrupt status +* Host could read [0x0_41F8] to check +* indivisual subsys hw interrupt status +* mcu2host_sw_int_sts[29] - (RO) subsys interrupt overall status +* User should should check +* SUBSYS2HOST_INT_STA for each interrupt status +* Host could read [0x0_41F8] to check +* indivisual subsys hw interrupt status +* tx_done_int_sts_18[30] - (W1C) TX Queue#18 packet transmit interrupt +* Write 1 to clear the interrupt +* RESERVED[31] - (RO) reserved +*/ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_18_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_18_MASK \ + 0x40000000 /* tx_done_int_sts_18[30] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_18_SHFT 30 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_mcu2host_sw_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_mcu2host_sw_int_sts_MASK \ + 0x20000000 /* mcu2host_sw_int_sts[29] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_mcu2host_sw_int_sts_SHFT 29 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_subsys_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_subsys_int_sts_MASK \ + 0x10000000 /* subsys_int_sts[28] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_subsys_int_sts_SHFT 28 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_17_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_17_MASK \ + 0x08000000 /* tx_done_int_sts_17[27] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_17_SHFT 27 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_16_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_16_MASK \ + 0x04000000 /* tx_done_int_sts_16[26] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_16_SHFT 26 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_wpdma2host_err_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_wpdma2host_err_int_sts_MASK \ + 0x01000000 /* wpdma2host_err_int_sts[24] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_wpdma2host_err_int_sts_SHFT 24 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_coherent_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_coherent_int_sts_MASK \ + 0x00200000 /* tx_coherent_int_sts[21] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_coherent_int_sts_SHFT 21 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_coherent_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_coherent_int_sts_MASK \ + 0x00100000 /* rx_coherent_int_sts[20] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_coherent_int_sts_SHFT 20 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_14_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_14_MASK \ + 0x00040000 /* tx_done_int_sts_14[18] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_14_SHFT 18 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_13_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_13_MASK \ + 0x00020000 /* tx_done_int_sts_13[17] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_13_SHFT 17 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_12_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_12_MASK \ + 0x00010000 /* tx_done_int_sts_12[16] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_12_SHFT 16 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_11_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_11_MASK \ + 0x00008000 /* tx_done_int_sts_11[15] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_11_SHFT 15 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_10_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_10_MASK \ + 0x00004000 /* tx_done_int_sts_10[14] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_10_SHFT 14 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_9_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_9_MASK \ + 0x00002000 /* tx_done_int_sts_9[13] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_9_SHFT 13 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_8_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_8_MASK \ + 0x00001000 /* tx_done_int_sts_8[12] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_8_SHFT 12 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_7_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_7_MASK \ + 0x00000800 /* tx_done_int_sts_7[11] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_7_SHFT 11 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_6_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_6_MASK \ + 0x00000400 /* tx_done_int_sts_6[10] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_6_SHFT 10 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_5_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_5_MASK \ + 0x00000200 /* tx_done_int_sts_5[9] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_5_SHFT 9 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_4_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_4_MASK \ + 0x00000100 /* tx_done_int_sts_4[8] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_4_SHFT 8 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_3_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_3_MASK \ + 0x00000080 /* tx_done_int_sts_3[7] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_3_SHFT 7 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_2_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_2_MASK \ + 0x00000040 /* tx_done_int_sts_2[6] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_2_SHFT 6 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_1_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_1_MASK \ + 0x00000020 /* tx_done_int_sts_1[5] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_1_SHFT 5 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_0_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_0_MASK \ + 0x00000010 /* tx_done_int_sts_0[4] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_tx_done_int_sts_0_SHFT 4 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_done_int_sts_3_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_done_int_sts_3_MASK \ + 0x00000008 /* rx_done_int_sts_3[3] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_done_int_sts_3_SHFT 3 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_done_int_sts_2_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_done_int_sts_2_MASK \ + 0x00000004 /* rx_done_int_sts_2[2] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_done_int_sts_2_SHFT 2 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_done_int_sts_1_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_done_int_sts_1_MASK \ + 0x00000002 /* rx_done_int_sts_1[1] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_done_int_sts_1_SHFT 1 +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_done_int_sts_0_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_done_int_sts_0_MASK \ + 0x00000001 /* rx_done_int_sts_0[0] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_STA_rx_done_int_sts_0_SHFT 0 + +/* +* ---HOST_INT_ENA (0x18025000 + 0X204)--- +* HOST_RX_DONE_INT_ENA0[0] - (RW) RX Queue#0 packet receive interrupt +* HOST_RX_DONE_INT_ENA1[1] - (RW) RX Queue#1 packet receive interrupt +* HOST_RX_DONE_INT_ENA2[2] - (RW) RX Queue#2 packet receive interrupt +* HOST_RX_DONE_INT_ENA3[3] - (RW) RX Queue#3 packet receive interrupt +* HOST_TX_DONE_INT_ENA0[4] - (RW) TX Queue#0 packet transmit interrupt +* HOST_TX_DONE_INT_ENA1[5] - (RW) TX Queue#1 packet transmit interrupt +* HOST_TX_DONE_INT_ENA2[6] - (RW) TX Queue#2 packet transmit interrupt +* HOST_TX_DONE_INT_ENA3[7] - (RW) TX Queue#3 packet transmit interrupt +* HOST_TX_DONE_INT_ENA4[8] - (RW) TX Queue#4 packet transmit interrupt +* HOST_TX_DONE_INT_ENA5[9] - (RW) TX Queue#5 packet transmit interrupt +* HOST_TX_DONE_INT_ENA6[10] - (RW) TX Queue#6 packet transmit interrupt +* HOST_TX_DONE_INT_ENA7[11] - (RW) TX Queue#7 packet transmit interrupt +* HOST_TX_DONE_INT_ENA8[12] - (RW) TX Queue#8 packet transmit interrupt +* HOST_TX_DONE_INT_ENA9[13] - (RW) TX Queue#9 packet transmit interrupt +* HOST_TX_DONE_INT_ENA10[14] - (RW) TX Queue#10 packet transmit interrupt +* HOST_TX_DONE_INT_ENA11[15] - (RW) TX Queue#11 packet transmit interrupt +* HOST_TX_DONE_INT_ENA12[16] - (RW) TX Queue#12 packet transmit interrupt +* HOST_TX_DONE_INT_ENA13[17] - (RW) TX Queue#13 packet transmit interrupt +* HOST_TX_DONE_INT_ENA14[18] - (RW) TX Queue#14 packet transmit interrupt +* RESERVED19[19] - (RO) Reserved bits +* HOST_RX_COHERENT_EN[20] - (RW) Enable for RX_DMA data coherent +interrupt +* HOST_TX_COHERENT_EN[21] - (RW) Enable for TX_DMA data coherent +interrupt +* RESERVED[23..22] - (RO) reserved, originally used for delayed +* interrupt of legacy TX/RX done +* wpdma2host_err_int_ena[24] - (RW) Enable bit of wpdma2host_err_int +* RESERVED[25] - (RO) reserved +* HOST_TX_DONE_INT_ENA16[26] - (RW) TX Queue#16 packet transmit interrupt +* HOST_TX_DONE_INT_ENA17[27] - (RW) TX Queue#17 packet transmit interrupt +* subsys_int_ena[28] - (RW) Enable bit of subsys_int +* mcu2host_sw_int_ena[29] - (RW) Enable bit of mcu2host_sw_int +* HOST_TX_DONE_INT_ENA18[30] - (RW) TX Queue#18 packet transmit interrupt +* RESERVED[31] - (RO) reserved +*/ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA18_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA18_MASK \ + 0x40000000 /* HOST_TX_DONE_INT_ENA18[30] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA18_SHFT 30 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_mcu2host_sw_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_mcu2host_sw_int_ena_MASK \ + 0x20000000 /* mcu2host_sw_int_ena[29] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_mcu2host_sw_int_ena_SHFT 29 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_subsys_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_subsys_int_ena_MASK \ + 0x10000000 /* subsys_int_ena[28] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_subsys_int_ena_SHFT 28 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA17_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA17_MASK \ + 0x08000000 /* HOST_TX_DONE_INT_ENA17[27] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA17_SHFT 27 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA16_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA16_MASK \ + 0x04000000 /* HOST_TX_DONE_INT_ENA16[26] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA16_SHFT 26 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_wpdma2host_err_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_wpdma2host_err_int_ena_MASK \ + 0x01000000 /* wpdma2host_err_int_ena[24] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_wpdma2host_err_int_ena_SHFT 24 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_COHERENT_EN_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_COHERENT_EN_MASK \ + 0x00200000 /* HOST_TX_COHERENT_EN[21] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_COHERENT_EN_SHFT 21 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_COHERENT_EN_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_COHERENT_EN_MASK \ + 0x00100000 /* HOST_RX_COHERENT_EN[20] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_COHERENT_EN_SHFT 20 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA14_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA14_MASK \ + 0x00040000 /* HOST_TX_DONE_INT_ENA14[18] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA14_SHFT 18 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA13_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA13_MASK \ + 0x00020000 /* HOST_TX_DONE_INT_ENA13[17] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA13_SHFT 17 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA12_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA12_MASK \ + 0x00010000 /* HOST_TX_DONE_INT_ENA12[16] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA12_SHFT 16 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA11_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA11_MASK \ + 0x00008000 /* HOST_TX_DONE_INT_ENA11[15] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA11_SHFT 15 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA10_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA10_MASK \ + 0x00004000 /* HOST_TX_DONE_INT_ENA10[14] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA10_SHFT 14 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA9_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA9_MASK \ + 0x00002000 /* HOST_TX_DONE_INT_ENA9[13] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA9_SHFT 13 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA8_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA8_MASK \ + 0x00001000 /* HOST_TX_DONE_INT_ENA8[12] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA8_SHFT 12 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA7_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA7_MASK \ + 0x00000800 /* HOST_TX_DONE_INT_ENA7[11] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA7_SHFT 11 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA6_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA6_MASK \ + 0x00000400 /* HOST_TX_DONE_INT_ENA6[10] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA6_SHFT 10 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA5_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA5_MASK \ + 0x00000200 /* HOST_TX_DONE_INT_ENA5[9] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA5_SHFT 9 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA4_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA4_MASK \ + 0x00000100 /* HOST_TX_DONE_INT_ENA4[8] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA4_SHFT 8 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA3_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA3_MASK \ + 0x00000080 /* HOST_TX_DONE_INT_ENA3[7] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA3_SHFT 7 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA2_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA2_MASK \ + 0x00000040 /* HOST_TX_DONE_INT_ENA2[6] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA2_SHFT 6 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA1_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA1_MASK \ + 0x00000020 /* HOST_TX_DONE_INT_ENA1[5] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA1_SHFT 5 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA0_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA0_MASK \ + 0x00000010 /* HOST_TX_DONE_INT_ENA0[4] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_TX_DONE_INT_ENA0_SHFT 4 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_DONE_INT_ENA3_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_DONE_INT_ENA3_MASK \ + 0x00000008 /* HOST_RX_DONE_INT_ENA3[3] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_DONE_INT_ENA3_SHFT 3 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_DONE_INT_ENA2_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_DONE_INT_ENA2_MASK \ + 0x00000004 /* HOST_RX_DONE_INT_ENA2[2] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_DONE_INT_ENA2_SHFT 2 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_DONE_INT_ENA1_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_DONE_INT_ENA1_MASK \ + 0x00000002 /* HOST_RX_DONE_INT_ENA1[1] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_DONE_INT_ENA1_SHFT 1 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_DONE_INT_ENA0_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_DONE_INT_ENA0_MASK \ + 0x00000001 /* HOST_RX_DONE_INT_ENA0[0] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_HOST_RX_DONE_INT_ENA0_SHFT 0 + +/* +* ---WPDMA_GLO_CFG (0x18025000 + 0x208)--- +* TX_DMA_EN[0] - (RW) TX_DMA Enable +* 1: Enable TX_DMA, MUST wait until all +* prefetch rings' MAX_CNT(WPDMA_T(R)X_RING*_EXT_CTRL) of DMA including neighbor +* DMA have been configured successfully +* 0: Disable TX_DMA +* TX_DMA_BUSY[1] - (RO) TX_DMA Busy indicator +* 1: TX_DMA is busy +* 0: TX_DMA is not busy +* RX_DMA_EN[2] - (RW) RX_DMA Enable +* 1: Enable RX_DMA, MUST wait until all +* prefetch rings' MAX_CNT(WPDMA_T(R)X_RING*_EXT_CTRL) of DMA including neighbor +* DMA have been configured successfully +* 0: Disable RX_DMA +* RX_DMA_BUSY[3] - (RO) RX_DMA Busy indicator +* 1: RX_DMA is busy +* 0: RX_DMA is not busy +* PDMA_BT_SIZE[5..4] - (RW) Define the burst size of WPDMA +* 2'h0 : 4 DWORD (16bytes) +* 2'h1 : 8 DWORD (32 bytes) +* 2'h2 : 16 DWORD (64 bytes) +* 2'h3 : 32 DWORD (128 bytes) +* TX_WB_DDONE[6] - (RW) 1'b1 : TX engine will wait to assert IRQ +* util whole TX dmad has been fully written into AXI bus which represents HOST +* memory, 1'b0 : TX engine will assert IRQ once TX dmad write-back request have +* been ACKed +* BIG_ENDIAN[7] - (RW) The endian mode selection. DMA applies +* the endian rule to convert payload and TX/RX information. DMA won't apply +* endian rule to register or descriptor. +* 1: big endian. +* 0: little endian. +* DMAD_32B_EN[8] - (RW) DMA Descriptor 32-byte Enable +* 0: The size of descriptors is set to 16-byte +* 1: The size of descriptors is set to 32-byte +* FW_DWLD_Bypass_dmashdl[9] - (RW) No USE for (APSOC/PCIE) +* For firmware download packet, driver shold using tx-ring16 to download packet +* and set this bit to bypass dmashdl resource control. +* After firmware download finish, driver +* should clear this bit. +* After all, tx-ring16 could be used for normal data operation. +(USB) +* For USB test_mode, user could set this bit to bypass dmashdl with all endpoint +* CSR_WFDMA_DUMMY_REG[10] - (RW) dummy CR for use if ECO needed +* CSR_AXI_BUFRDY_BYP[11] - (RW) to disable read data fifo available checking +* before issuing next AXI read request +* FIFO_LITTLE_ENDIAN[12] - (RW) Determines the endianness of the FIFO side +* 0: Big-endian +* 1: Little-endian +* CSR_RX_WB_DDONE[13] - (RW) 1'b1 : RX engine will wait to assert IRQ +* util whole RX dmad has been fully written into AXI bus which represents HOST +* memory, 1'b0 : RX engine will assert IRQ once RX dmad write-back request have +* been ACKed +* CSR_PP_HIF_TXP_ACTIVE_EN[14] - (RW) 1'b1 : enable legacy pp_hif_txp_active +* function to lock tx engine for favor TXP transmit requested directly from PP, +* other pdma TX rings request will be masked until pp_hif_txp_active is +deasserted +* 1'b0 : disable legacy pp_hif_txp_active function, use latest TX source QoS +* design to change throttler settings to favor TXP transmit! +* CSR_DISP_BASE_PTR_CHAIN_EN[15] - (RW) Enable prefet sram ring address +* arrangement by hardware chain structure(DMA#N TX ring group -> DMA#N RX ring +* group -> DMA#M TX ring group -> DMA#M RX ring group and son on). If not +* enabled, firmware need to program DISP_BASE_PTR of WPDMA_T(R)X_RING*_EXT_CTRL +instead!! +* CSR_LBK_RX_Q_SEL[17..16] - (RW) loopback data from TXFIFO will be direct to +* this RX ring when CSR_LBK_RX_Q_SEL_EN in loopback mode, valid bit-width is +* equal to RX_RING_WIDTH which can be calculated from WPDMA_INFO 0x284[15:8] +RX_RING_NUMBER +* RESERVED18[19..18] - (RO) Reserved bits +* CSR_LBK_RX_Q_SEL_EN[20] - (RW) Force configured CSR_LBK_RX_Q_SEL to +* receive loopback data from TXFIFO +* RESERVED21[23..21] - (RO) Reserved bits +* CSR_SW_RST[24] - (RO) SW reset all designs (To be tested for SER in the +future) +* FORCE_TX_EOF[25] - (RW) Force to send an eof after PDMA being reset (for +Packet_Processor) +* 0: Disabled +* 1: Enabled +* PDMA_ADDR_EXT_EN[26] - (RW) No Fnction for now!! For PDMA Address 32bits +* extension. When this design option was enable. PDMA would change Tx/Rx +* descriptor format for address extension. +* 0 : PDMA 32bits address +* 1 : PDMA Tx descirptor DW3 (TXINFO) would used to extend address +* PDMA Rx descirpt DW2 (Reserved) would used to extend address. +* OMIT_RX_INFO[27] - (RW) For loopback mode, set to 1'b1. +* For normal wifi data operation. User should not set this option and should +* keep 1'b0 because UMAC will always add extra QW for checksum after received +* packet's laster QW +* VERY IMPORTANT : for cpu_dma0/1 where CR +* resides in 0x5100_0xxx, OMIT_RX_INFO MUST be set to 1'b1 +* Omit rx_info of all RX packets +* 0: All the PX packets should end with a rx_info +* 1: All the PX packets should NOT end with a rx_info but an eof +* OMIT_TX_INFO[28] - (RW) For loopback mode, set to 1'b1. +* For normal wifi data operation. User should +* set this option to +* Omit tx_info of all TX packets because UMAC +* design not support TXINFO +* 0: The tx_info in DMAD will be sent at the beginning +* 1: The tx_info in DMAD will NOT be sent at the beginning +* BYTE_SWAP[29] - (RW) Byte Swapping for TX/RX DMAD +* 0: Not to swap (Endian of DMAD unchanged) +* 1: Swap (Endian of DMAD reversed) +* CLK_GATE_DIS[30] - (RW) PDMA Clock Gated Function Disable +* 0: normal function +* 1: disable clock gated function +* RX_2B_OFFSET[31] - (RW) RX PBF 2-byte Offset +* 1: Skip the first two bytes of the RX PBF +* 0: Not to skip the first two bytes of the +* RX PBF +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_RX_2B_OFFSET_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_RX_2B_OFFSET_MASK \ + 0x80000000 /* RX_2B_OFFSET[31] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_RX_2B_OFFSET_SHFT 31 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CLK_GATE_DIS_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CLK_GATE_DIS_MASK \ + 0x40000000 /* CLK_GATE_DIS[30] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CLK_GATE_DIS_SHFT 30 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_BYTE_SWAP_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_BYTE_SWAP_MASK \ + 0x20000000 /* BYTE_SWAP[29] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_BYTE_SWAP_SHFT 29 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_OMIT_TX_INFO_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_OMIT_TX_INFO_MASK \ + 0x10000000 /* OMIT_TX_INFO[28] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_OMIT_TX_INFO_SHFT 28 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_OMIT_RX_INFO_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_OMIT_RX_INFO_MASK \ + 0x08000000 /* OMIT_RX_INFO[27] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_OMIT_RX_INFO_SHFT 27 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_PDMA_ADDR_EXT_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_PDMA_ADDR_EXT_EN_MASK \ + 0x04000000 /* PDMA_ADDR_EXT_EN[26] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_PDMA_ADDR_EXT_EN_SHFT 26 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_FORCE_TX_EOF_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_FORCE_TX_EOF_MASK \ + 0x02000000 /* FORCE_TX_EOF[25] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_FORCE_TX_EOF_SHFT 25 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_SW_RST_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_SW_RST_MASK \ + 0x01000000 /* CSR_SW_RST[24] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_SW_RST_SHFT 24 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_EN_MASK \ + 0x00100000 /* CSR_LBK_RX_Q_SEL_EN[20] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_EN_SHFT 20 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_MASK \ + 0x00030000 /* CSR_LBK_RX_Q_SEL[17..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_LBK_RX_Q_SEL_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN_MASK \ + 0x00008000 /* CSR_DISP_BASE_PTR_CHAIN_EN[15] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN_SHFT 15 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_PP_HIF_TXP_ACTIVE_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_PP_HIF_TXP_ACTIVE_EN_MASK \ + 0x00004000 /* CSR_PP_HIF_TXP_ACTIVE_EN[14] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_PP_HIF_TXP_ACTIVE_EN_SHFT 14 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_RX_WB_DDONE_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_RX_WB_DDONE_MASK \ + 0x00002000 /* CSR_RX_WB_DDONE[13] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_RX_WB_DDONE_SHFT 13 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN_MASK \ + 0x00001000 /* FIFO_LITTLE_ENDIAN[12] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN_SHFT 12 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_AXI_BUFRDY_BYP_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_AXI_BUFRDY_BYP_MASK \ + 0x00000800 /* CSR_AXI_BUFRDY_BYP[11] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_AXI_BUFRDY_BYP_SHFT 11 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_WFDMA_DUMMY_REG_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_WFDMA_DUMMY_REG_MASK \ + 0x00000400 /* CSR_WFDMA_DUMMY_REG[10] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_CSR_WFDMA_DUMMY_REG_SHFT 10 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_FW_DWLD_Bypass_dmashdl_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_FW_DWLD_Bypass_dmashdl_MASK \ + 0x00000200 /* FW_DWLD_Bypass_dmashdl[9] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_FW_DWLD_Bypass_dmashdl_SHFT 9 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_DMAD_32B_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_DMAD_32B_EN_MASK \ + 0x00000100 /* DMAD_32B_EN[8] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_DMAD_32B_EN_SHFT 8 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_BIG_ENDIAN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_BIG_ENDIAN_MASK \ + 0x00000080 /* BIG_ENDIAN[7] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_BIG_ENDIAN_SHFT 7 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_TX_WB_DDONE_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_TX_WB_DDONE_MASK \ + 0x00000040 /* TX_WB_DDONE[6] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_TX_WB_DDONE_SHFT 6 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_PDMA_BT_SIZE_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_PDMA_BT_SIZE_MASK \ + 0x00000030 /* PDMA_BT_SIZE[5..4] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_PDMA_BT_SIZE_SHFT 4 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_RX_DMA_BUSY_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_RX_DMA_BUSY_MASK \ + 0x00000008 /* RX_DMA_BUSY[3] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_RX_DMA_BUSY_SHFT 3 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_RX_DMA_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_RX_DMA_EN_MASK \ + 0x00000004 /* RX_DMA_EN[2] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_RX_DMA_EN_SHFT 2 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_TX_DMA_BUSY_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_TX_DMA_BUSY_MASK \ + 0x00000002 /* TX_DMA_BUSY[1] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_TX_DMA_BUSY_SHFT 1 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_TX_DMA_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_TX_DMA_EN_MASK \ + 0x00000001 /* TX_DMA_EN[0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_TX_DMA_EN_SHFT 0 + +/* +* ---WPDMA_RST_DTX_PTR (0x18025000 + 0x20C)--- +* RST_DTX_IDX0[0] - (WO) Write 1 to reset to TX_DMATX_IDX0 to 0 +* RST_DTX_IDX1[1] - (WO) Write 1 to reset to TX_DMATX_IDX1 to 0 +* RST_DTX_IDX2[2] - (WO) Write 1 to reset to TX_DMATX_IDX2 to 0 +* RST_DTX_IDX3[3] - (WO) Write 1 to reset to TX_DMATX_IDX3 to 0 +* RST_DTX_IDX4[4] - (WO) Write 1 to reset to TX_DMATX_IDX4 to 0 +* RST_DTX_IDX5[5] - (WO) Write 1 to reset to TX_DMATX_IDX5 to 0 +* RST_DTX_IDX6[6] - (WO) Write 1 to reset to TX_DMATX_IDX6 to 0 +* RST_DTX_IDX7[7] - (WO) Write 1 to reset to TX_DMATX_IDX7 to 0 +* RST_DTX_IDX8[8] - (WO) Write 1 to reset to TX_DMATX_IDX8 to 0 +* RST_DTX_IDX9[9] - (WO) Write 1 to reset to TX_DMATX_IDX9 to 0 +* RST_DTX_IDX10[10] - (WO) Write 1 to reset to TX_DMATX_IDX10 to 0 +* RST_DTX_IDX11[11] - (WO) Write 1 to reset to TX_DMATX_IDX11 to 0 +* RST_DTX_IDX12[12] - (WO) Write 1 to reset to TX_DMATX_IDX12 to 0 +* RST_DTX_IDX13[13] - (WO) Write 1 to reset to TX_DMATX_IDX13 to 0 +* RST_DTX_IDX14[14] - (WO) Write 1 to reset to TX_DMATX_IDX14 to 0 +* RST_DTX_IDX15[15] - (WO) Write 1 to reset to TX_DMATX_IDX15 to 0 +* RST_DTX_IDX16[16] - (WO) Write 1 to reset to TX_DMATX_IDX16 to 0 +* RST_DTX_IDX17[17] - (WO) Write 1 to reset to TX_DMATX_IDX17 to 0 +* RST_DTX_IDX18[18] - (WO) Write 1 to reset to TX_DMATX_IDX18 to 0 +* RST_DTX_IDX19[19] - (WO) Write 1 to reset to TX_DMATX_IDX19 to 0 +* RST_DTX_IDX20[20] - (WO) Write 1 to reset to TX_DMATX_IDX20 to 0 +* RESERVED21[31..21] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX20_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX20_MASK \ + 0x00100000 /* RST_DTX_IDX20[20] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX20_SHFT 20 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX19_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX19_MASK \ + 0x00080000 /* RST_DTX_IDX19[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX19_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX18_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX18_MASK \ + 0x00040000 /* RST_DTX_IDX18[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX18_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX17_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX17_MASK \ + 0x00020000 /* RST_DTX_IDX17[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX17_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX16_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX16_MASK \ + 0x00010000 /* RST_DTX_IDX16[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX16_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX15_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX15_MASK \ + 0x00008000 /* RST_DTX_IDX15[15] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX15_SHFT 15 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX14_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX14_MASK \ + 0x00004000 /* RST_DTX_IDX14[14] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX14_SHFT 14 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX13_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX13_MASK \ + 0x00002000 /* RST_DTX_IDX13[13] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX13_SHFT 13 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX12_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX12_MASK \ + 0x00001000 /* RST_DTX_IDX12[12] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX12_SHFT 12 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX11_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX11_MASK \ + 0x00000800 /* RST_DTX_IDX11[11] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX11_SHFT 11 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX10_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX10_MASK \ + 0x00000400 /* RST_DTX_IDX10[10] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX10_SHFT 10 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX9_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX9_MASK \ + 0x00000200 /* RST_DTX_IDX9[9] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX9_SHFT 9 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX8_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX8_MASK \ + 0x00000100 /* RST_DTX_IDX8[8] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX8_SHFT 8 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX7_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX7_MASK \ + 0x00000080 /* RST_DTX_IDX7[7] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX7_SHFT 7 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX6_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX6_MASK \ + 0x00000040 /* RST_DTX_IDX6[6] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX6_SHFT 6 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX5_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX5_MASK \ + 0x00000020 /* RST_DTX_IDX5[5] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX5_SHFT 5 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX4_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX4_MASK \ + 0x00000010 /* RST_DTX_IDX4[4] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX4_SHFT 4 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX3_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX3_MASK \ + 0x00000008 /* RST_DTX_IDX3[3] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX3_SHFT 3 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX2_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX2_MASK \ + 0x00000004 /* RST_DTX_IDX2[2] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX2_SHFT 2 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX1_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX1_MASK \ + 0x00000002 /* RST_DTX_IDX1[1] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX1_SHFT 1 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX0_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX0_MASK \ + 0x00000001 /* RST_DTX_IDX0[0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DTX_PTR_RST_DTX_IDX0_SHFT 0 + +/* +* ---WPDMA_PAUSE_TX_Q (0x18025000 + 0x224)--- +* TX_Q_PAUSE[31..0] - (RW) Pause signal for each TX ring (16 bits +* for 16 rings) +* Set 0: Normal function; Set 1: The +* corresponding TX ring is paused +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_TX_Q_TX_Q_PAUSE_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_TX_Q_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_TX_Q_TX_Q_PAUSE_MASK \ + 0xFFFFFFFF /* TX_Q_PAUSE[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_TX_Q_TX_Q_PAUSE_SHFT 0 + +/* +* ---HOST_INT_ENA_SET (0x18025000 + 0X228)--- +* HOST_RX_DONE_INT_ENA0[0] - (W1S) RX Queue#0 packet receive interrupt +* HOST_RX_DONE_INT_ENA1[1] - (W1S) RX Queue#1 packet receive interrupt +* HOST_RX_DONE_INT_ENA2[2] - (W1S) RX Queue#2 packet receive interrupt +* HOST_RX_DONE_INT_ENA3[3] - (W1S) RX Queue#3 packet receive interrupt +* HOST_TX_DONE_INT_ENA0[4] - (W1S) TX Queue#0 packet transmit interrupt +* HOST_TX_DONE_INT_ENA1[5] - (W1S) TX Queue#1 packet transmit interrupt +* HOST_TX_DONE_INT_ENA2[6] - (W1S) TX Queue#2 packet transmit interrupt +* HOST_TX_DONE_INT_ENA3[7] - (W1S) TX Queue#3 packet transmit interrupt +* HOST_TX_DONE_INT_ENA4[8] - (W1S) TX Queue#4 packet transmit interrupt +* HOST_TX_DONE_INT_ENA5[9] - (W1S) TX Queue#5 packet transmit interrupt +* HOST_TX_DONE_INT_ENA6[10] - (W1S) TX Queue#6 packet transmit interrupt +* HOST_TX_DONE_INT_ENA7[11] - (W1S) TX Queue#7 packet transmit interrupt +* HOST_TX_DONE_INT_ENA8[12] - (W1S) TX Queue#8 packet transmit interrupt +* HOST_TX_DONE_INT_ENA9[13] - (W1S) TX Queue#9 packet transmit interrupt +* HOST_TX_DONE_INT_ENA10[14] - (W1S) TX Queue#10 packet transmit interrupt +* HOST_TX_DONE_INT_ENA11[15] - (W1S) TX Queue#11 packet transmit interrupt +* HOST_TX_DONE_INT_ENA12[16] - (W1S) TX Queue#12 packet transmit interrupt +* HOST_TX_DONE_INT_ENA13[17] - (W1S) TX Queue#13 packet transmit interrupt +* HOST_TX_DONE_INT_ENA14[18] - (W1S) TX Queue#14 packet transmit interrupt +* RESERVED19[19] - (RO) Reserved bits +* HOST_RX_COHERENT_EN[20] - (W1S) Enable for RX_DMA data coherent +interrupt +* HOST_TX_COHERENT_EN[21] - (W1S) Enable for TX_DMA data coherent +interrupt +* RESERVED22[23..22] - (RO) Reserved bits +* wpdma2host_err_int_ena[24] - (W1S) Enable bit of wpdma2host_err_int +* RESERVED25[25] - (RO) Reserved bits +* HOST_TX_DONE_INT_ENA16[26] - (W1S) TX Queue#16 packet transmit interrupt +* HOST_TX_DONE_INT_ENA17[27] - (W1S) TX Queue#17 packet transmit interrupt +* subsys_int_ena[28] - (W1S) Enable bit of subsys_int +* mcu2host_sw_int_ena[29] - (W1S) Enable bit of mcu2host_sw_int +* HOST_TX_DONE_INT_ENA18[30] - (W1S) TX Queue#18 packet transmit interrupt +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA18_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA18_MASK \ + 0x40000000 /* HOST_TX_DONE_INT_ENA18[30] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA18_SHFT 30 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_mcu2host_sw_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_mcu2host_sw_int_ena_MASK \ + 0x20000000 /* mcu2host_sw_int_ena[29] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_mcu2host_sw_int_ena_SHFT 29 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_subsys_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_subsys_int_ena_MASK \ + 0x10000000 /* subsys_int_ena[28] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_subsys_int_ena_SHFT 28 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA17_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA17_MASK \ + 0x08000000 /* HOST_TX_DONE_INT_ENA17[27] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA17_SHFT 27 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA16_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA16_MASK \ + 0x04000000 /* HOST_TX_DONE_INT_ENA16[26] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA16_SHFT 26 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_wpdma2host_err_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_wpdma2host_err_int_ena_MASK \ + 0x01000000 /* wpdma2host_err_int_ena[24] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_wpdma2host_err_int_ena_SHFT 24 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_COHERENT_EN_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_COHERENT_EN_MASK \ + 0x00200000 /* HOST_TX_COHERENT_EN[21] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_COHERENT_EN_SHFT 21 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_RX_COHERENT_EN_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_RX_COHERENT_EN_MASK \ + 0x00100000 /* HOST_RX_COHERENT_EN[20] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_RX_COHERENT_EN_SHFT 20 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA14_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA14_MASK \ + 0x00040000 /* HOST_TX_DONE_INT_ENA14[18] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA14_SHFT 18 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA13_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA13_MASK \ + 0x00020000 /* HOST_TX_DONE_INT_ENA13[17] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA13_SHFT 17 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA12_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA12_MASK \ + 0x00010000 /* HOST_TX_DONE_INT_ENA12[16] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA12_SHFT 16 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA11_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA11_MASK \ + 0x00008000 /* HOST_TX_DONE_INT_ENA11[15] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA11_SHFT 15 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA10_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA10_MASK \ + 0x00004000 /* HOST_TX_DONE_INT_ENA10[14] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA10_SHFT 14 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA9_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA9_MASK \ + 0x00002000 /* HOST_TX_DONE_INT_ENA9[13] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA9_SHFT 13 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA8_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA8_MASK \ + 0x00001000 /* HOST_TX_DONE_INT_ENA8[12] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA8_SHFT 12 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA7_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA7_MASK \ + 0x00000800 /* HOST_TX_DONE_INT_ENA7[11] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA7_SHFT 11 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA6_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA6_MASK \ + 0x00000400 /* HOST_TX_DONE_INT_ENA6[10] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA6_SHFT 10 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA5_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA5_MASK \ + 0x00000200 /* HOST_TX_DONE_INT_ENA5[9] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA5_SHFT 9 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA4_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA4_MASK \ + 0x00000100 /* HOST_TX_DONE_INT_ENA4[8] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA4_SHFT 8 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA3_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA3_MASK \ + 0x00000080 /* HOST_TX_DONE_INT_ENA3[7] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA3_SHFT 7 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA2_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA2_MASK \ + 0x00000040 /* HOST_TX_DONE_INT_ENA2[6] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA2_SHFT 6 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA1_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA1_MASK \ + 0x00000020 /* HOST_TX_DONE_INT_ENA1[5] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA1_SHFT 5 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA0_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA0_MASK \ + 0x00000010 /* HOST_TX_DONE_INT_ENA0[4] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_TX_DONE_INT_ENA0_SHFT 4 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA3_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA3_MASK \ + 0x00000008 /* HOST_RX_DONE_INT_ENA3[3] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA3_SHFT 3 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA2_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA2_MASK \ + 0x00000004 /* HOST_RX_DONE_INT_ENA2[2] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA2_SHFT 2 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA1_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA1_MASK \ + 0x00000002 /* HOST_RX_DONE_INT_ENA1[1] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA1_SHFT 1 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA0_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA0_MASK \ + 0x00000001 /* HOST_RX_DONE_INT_ENA0[0] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_SET_HOST_RX_DONE_INT_ENA0_SHFT 0 + +/* +* ---HOST_INT_ENA_CLR (0x18025000 + 0X22C)--- +* HOST_RX_DONE_INT_ENA0[0] - (W1C) RX Queue#0 packet receive interrupt +* HOST_RX_DONE_INT_ENA1[1] - (W1C) RX Queue#1 packet receive interrupt +* HOST_RX_DONE_INT_ENA2[2] - (W1C) RX Queue#2 packet receive interrupt +* HOST_RX_DONE_INT_ENA3[3] - (W1C) RX Queue#3 packet receive interrupt +* HOST_TX_DONE_INT_ENA0[4] - (W1C) TX Queue#0 packet transmit interrupt +* HOST_TX_DONE_INT_ENA1[5] - (W1C) TX Queue#1 packet transmit interrupt +* HOST_TX_DONE_INT_ENA2[6] - (W1C) TX Queue#2 packet transmit interrupt +* HOST_TX_DONE_INT_ENA3[7] - (W1C) TX Queue#3 packet transmit interrupt +* HOST_TX_DONE_INT_ENA4[8] - (W1C) TX Queue#4 packet transmit interrupt +* HOST_TX_DONE_INT_ENA5[9] - (W1C) TX Queue#5 packet transmit interrupt +* HOST_TX_DONE_INT_ENA6[10] - (W1C) TX Queue#6 packet transmit interrupt +* HOST_TX_DONE_INT_ENA7[11] - (W1C) TX Queue#7 packet transmit interrupt +* HOST_TX_DONE_INT_ENA8[12] - (W1C) TX Queue#8 packet transmit interrupt +* HOST_TX_DONE_INT_ENA9[13] - (W1C) TX Queue#9 packet transmit interrupt +* HOST_TX_DONE_INT_ENA10[14] - (W1C) TX Queue#10 packet transmit interrupt +* HOST_TX_DONE_INT_ENA11[15] - (W1C) TX Queue#11 packet transmit interrupt +* HOST_TX_DONE_INT_ENA12[16] - (W1C) TX Queue#12 packet transmit interrupt +* HOST_TX_DONE_INT_ENA13[17] - (W1C) TX Queue#13 packet transmit interrupt +* HOST_TX_DONE_INT_ENA14[18] - (W1C) TX Queue#14 packet transmit interrupt +* RESERVED19[19] - (RO) Reserved bits +* HOST_RX_COHERENT_EN[20] - (W1C) Enable for RX_DMA data coherent +interrupt +* HOST_TX_COHERENT_EN[21] - (W1C) Enable for TX_DMA data coherent +interrupt +* RESERVED22[23..22] - (RO) Reserved bits +* wpdma2host_err_int_ena[24] - (W1C) Enable bit of wpdma2host_err_int +* RESERVED25[25] - (RO) Reserved bits +* HOST_TX_DONE_INT_ENA16[26] - (W1C) TX Queue#16 packet transmit interrupt +* HOST_TX_DONE_INT_ENA17[27] - (W1C) TX Queue#17 packet transmit interrupt +* subsys_int_ena[28] - (W1C) Enable bit of subsys_int +* mcu2host_sw_int_ena[29] - (W1C) Enable bit of mcu2host_sw_int +* HOST_TX_DONE_INT_ENA18[30] - (W1C) TX Queue#18 packet transmit interrupt +* RESERVED31[31] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA18_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA18_MASK \ + 0x40000000 /* HOST_TX_DONE_INT_ENA18[30] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA18_SHFT 30 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_mcu2host_sw_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_mcu2host_sw_int_ena_MASK \ + 0x20000000 /* mcu2host_sw_int_ena[29] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_mcu2host_sw_int_ena_SHFT 29 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_subsys_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_subsys_int_ena_MASK \ + 0x10000000 /* subsys_int_ena[28] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_subsys_int_ena_SHFT 28 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA17_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA17_MASK \ + 0x08000000 /* HOST_TX_DONE_INT_ENA17[27] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA17_SHFT 27 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA16_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA16_MASK \ + 0x04000000 /* HOST_TX_DONE_INT_ENA16[26] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA16_SHFT 26 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_wpdma2host_err_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_wpdma2host_err_int_ena_MASK \ + 0x01000000 /* wpdma2host_err_int_ena[24] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_wpdma2host_err_int_ena_SHFT 24 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_COHERENT_EN_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_COHERENT_EN_MASK \ + 0x00200000 /* HOST_TX_COHERENT_EN[21] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_COHERENT_EN_SHFT 21 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_RX_COHERENT_EN_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_RX_COHERENT_EN_MASK \ + 0x00100000 /* HOST_RX_COHERENT_EN[20] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_RX_COHERENT_EN_SHFT 20 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA14_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA14_MASK \ + 0x00040000 /* HOST_TX_DONE_INT_ENA14[18] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA14_SHFT 18 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA13_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA13_MASK \ + 0x00020000 /* HOST_TX_DONE_INT_ENA13[17] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA13_SHFT 17 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA12_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA12_MASK \ + 0x00010000 /* HOST_TX_DONE_INT_ENA12[16] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA12_SHFT 16 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA11_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA11_MASK \ + 0x00008000 /* HOST_TX_DONE_INT_ENA11[15] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA11_SHFT 15 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA10_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA10_MASK \ + 0x00004000 /* HOST_TX_DONE_INT_ENA10[14] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA10_SHFT 14 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA9_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA9_MASK \ + 0x00002000 /* HOST_TX_DONE_INT_ENA9[13] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA9_SHFT 13 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA8_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA8_MASK \ + 0x00001000 /* HOST_TX_DONE_INT_ENA8[12] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA8_SHFT 12 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA7_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA7_MASK \ + 0x00000800 /* HOST_TX_DONE_INT_ENA7[11] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA7_SHFT 11 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA6_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA6_MASK \ + 0x00000400 /* HOST_TX_DONE_INT_ENA6[10] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA6_SHFT 10 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA5_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA5_MASK \ + 0x00000200 /* HOST_TX_DONE_INT_ENA5[9] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA5_SHFT 9 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA4_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA4_MASK \ + 0x00000100 /* HOST_TX_DONE_INT_ENA4[8] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA4_SHFT 8 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA3_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA3_MASK \ + 0x00000080 /* HOST_TX_DONE_INT_ENA3[7] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA3_SHFT 7 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA2_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA2_MASK \ + 0x00000040 /* HOST_TX_DONE_INT_ENA2[6] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA2_SHFT 6 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA1_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA1_MASK \ + 0x00000020 /* HOST_TX_DONE_INT_ENA1[5] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA1_SHFT 5 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA0_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA0_MASK \ + 0x00000010 /* HOST_TX_DONE_INT_ENA0[4] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_TX_DONE_INT_ENA0_SHFT 4 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA3_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA3_MASK \ + 0x00000008 /* HOST_RX_DONE_INT_ENA3[3] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA3_SHFT 3 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA2_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA2_MASK \ + 0x00000004 /* HOST_RX_DONE_INT_ENA2[2] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA2_SHFT 2 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA1_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA1_MASK \ + 0x00000002 /* HOST_RX_DONE_INT_ENA1[1] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA1_SHFT 1 +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA0_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA0_MASK \ + 0x00000001 /* HOST_RX_DONE_INT_ENA0[0] */ +#define WF_WFDMA_HOST_DMA1_HOST_INT_ENA_CLR_HOST_RX_DONE_INT_ENA0_SHFT 0 + +/* +* ---WPDMA_TIMEOUT_CFG (0x18025000 + 0x230)--- +* WPDMA_TX_TIMEOUT_TH[7..0] - (RW) xxx +* WPDMA_TX_TIMEOUT_TICK[14..8] - (RW) xxx +* WPDMA_TX_TIMEOUT_ENA[15] - (RW) xxx +* WPDMA_RX_TIMEOUT_TH[23..16] - (RW) xxx +* WPDMA_RX_TIMEOUT_TICK[30..24] - (RW) xxx +* WPDMA_RX_TIMEOUT_ENA[31] - (RW) xxx +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_ENA_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_ENA_MASK \ + 0x80000000 /* WPDMA_RX_TIMEOUT_ENA[31] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_ENA_SHFT 31 +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TICK_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TICK_MASK \ + 0x7F000000 /* WPDMA_RX_TIMEOUT_TICK[30..24] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TICK_SHFT 24 +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TH_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TH_MASK \ + 0x00FF0000 /* WPDMA_RX_TIMEOUT_TH[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_RX_TIMEOUT_TH_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_ENA_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_ENA_MASK \ + 0x00008000 /* WPDMA_TX_TIMEOUT_ENA[15] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_ENA_SHFT 15 +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TICK_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TICK_MASK \ + 0x00007F00 /* WPDMA_TX_TIMEOUT_TICK[14..8] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TICK_SHFT 8 +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TH_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TH_MASK \ + 0x000000FF /* WPDMA_TX_TIMEOUT_TH[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TIMEOUT_CFG_WPDMA_TX_TIMEOUT_TH_SHFT 0 + +/* +* ---WPDMA_MISC_CFG (0x18025000 + 0x234)--- +* WPDMA_TX_TIMEOUT_SEL[0] - (RW) xxx +* WPDMA_RX_TIMEOUT_SEL[1] - (RW) xxx +* WPDMA_RX_FREE_Q_TH[5..2] - (RW) When loopback, this will be used to +* generate correct tx_pause to avlid deadlock which caused from situration that +* tx_dma will start reading tx packet from memory without considering lack of RX +* dmad in prefetch sram and needing to read RX dmad from memory which tx dma is +* reading tx packet too and rready is deasserted due to txfifo full !! +* RX dmad in prefetch sram should be greater +* than RX_FREE_Q_TH for rx_dma to start writing received packet into memory!! +* RESERVED6[31..6] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_MISC_CFG_WPDMA_RX_FREE_Q_TH_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_MISC_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_MISC_CFG_WPDMA_RX_FREE_Q_TH_MASK \ + 0x0000003C /* WPDMA_RX_FREE_Q_TH[5..2] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_MISC_CFG_WPDMA_RX_FREE_Q_TH_SHFT 2 +#define WF_WFDMA_HOST_DMA1_WPDMA_MISC_CFG_WPDMA_RX_TIMEOUT_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_MISC_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_MISC_CFG_WPDMA_RX_TIMEOUT_SEL_MASK \ + 0x00000002 /* WPDMA_RX_TIMEOUT_SEL[1] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_MISC_CFG_WPDMA_RX_TIMEOUT_SEL_SHFT 1 +#define WF_WFDMA_HOST_DMA1_WPDMA_MISC_CFG_WPDMA_TX_TIMEOUT_SEL_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_MISC_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_MISC_CFG_WPDMA_TX_TIMEOUT_SEL_MASK \ + 0x00000001 /* WPDMA_TX_TIMEOUT_SEL[0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_MISC_CFG_WPDMA_TX_TIMEOUT_SEL_SHFT 0 + +/* +* ---WPDMA_TX_WRR_ARB_GBF0 (0x18025000 + 0x240)--- +* WRR_REQ0_ARB_GBF[2..0] - (RW) WRR REQ#0 priority level, mapped to +* lumpped request from TX ring0~ring15 for host TXD +* WRR_REQ1_ARB_GBF[5..3] - (RW) WRR REQ#1 priority level, mapped to +* request from TX ring16 when dual tx fifo for host event packet +* WRR_REQ2_ARB_GBF[8..6] - (RW) WRR REQ#2 priority level, mapped to +* request from TX ring17 when dual tx fifo for host event packet +* WRR_REQ3_ARB_GBF[11..9] - (RW) WRR REQ#3 priority level, mapped to +* request from TX ring18 when dual tx fifo for host event packet +* WRR_REQ4_ARB_GBF[14..12] - (RW) WRR REQ#4 priority level, mapped to +* request from TX ring19 when dual tx fifo for host event packet +* RESERVED[31..15] - (RW) Reserved +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ4_ARB_GBF_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ4_ARB_GBF_MASK \ + 0x00007000 /* WRR_REQ4_ARB_GBF[14..12] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ4_ARB_GBF_SHFT 12 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ3_ARB_GBF_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ3_ARB_GBF_MASK \ + 0x00000E00 /* WRR_REQ3_ARB_GBF[11..9] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ3_ARB_GBF_SHFT 9 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ2_ARB_GBF_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ2_ARB_GBF_MASK \ + 0x000001C0 /* WRR_REQ2_ARB_GBF[8..6] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ2_ARB_GBF_SHFT 6 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ1_ARB_GBF_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ1_ARB_GBF_MASK \ + 0x00000038 /* WRR_REQ1_ARB_GBF[5..3] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ1_ARB_GBF_SHFT 3 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ0_ARB_GBF_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ0_ARB_GBF_MASK \ + 0x00000007 /* WRR_REQ0_ARB_GBF[2..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_WRR_ARB_GBF0_WRR_REQ0_ARB_GBF_SHFT 0 + +/* +* ---MD_INT_STA (0x18025000 + 0x250)--- +* MCU2MD_SW_INT_STS[15..0] - (W1C) MCU to MD S/W interrupt indicator +* CONN_HIF_ON_MD_INT_STS[16] - (RO) MD driver own interrupt indicator +* RESERVED17[31..17] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_MD_INT_STA_CONN_HIF_ON_MD_INT_STS_ADDR \ + WF_WFDMA_HOST_DMA1_MD_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MD_INT_STA_CONN_HIF_ON_MD_INT_STS_MASK \ + 0x00010000 /* CONN_HIF_ON_MD_INT_STS[16] */ +#define WF_WFDMA_HOST_DMA1_MD_INT_STA_CONN_HIF_ON_MD_INT_STS_SHFT 16 +#define WF_WFDMA_HOST_DMA1_MD_INT_STA_MCU2MD_SW_INT_STS_ADDR \ + WF_WFDMA_HOST_DMA1_MD_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_MD_INT_STA_MCU2MD_SW_INT_STS_MASK \ + 0x0000FFFF /* MCU2MD_SW_INT_STS[15..0] */ +#define WF_WFDMA_HOST_DMA1_MD_INT_STA_MCU2MD_SW_INT_STS_SHFT 0 + +/* +* ---MD_INT_ENA (0x18025000 + 0x254)--- +* MCU2MD_SW_INT_ENA[15..0] - (RW) MCU to MD S/W interrupt enable +* CONN_HIF_ON_MD_INT_ENA[16] - (RW) MD driver own interrupt enable +* RESERVED17[31..17] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_MD_INT_ENA_CONN_HIF_ON_MD_INT_ENA_ADDR \ + WF_WFDMA_HOST_DMA1_MD_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MD_INT_ENA_CONN_HIF_ON_MD_INT_ENA_MASK \ + 0x00010000 /* CONN_HIF_ON_MD_INT_ENA[16] */ +#define WF_WFDMA_HOST_DMA1_MD_INT_ENA_CONN_HIF_ON_MD_INT_ENA_SHFT 16 +#define WF_WFDMA_HOST_DMA1_MD_INT_ENA_MCU2MD_SW_INT_ENA_ADDR \ + WF_WFDMA_HOST_DMA1_MD_INT_ENA_ADDR +#define WF_WFDMA_HOST_DMA1_MD_INT_ENA_MCU2MD_SW_INT_ENA_MASK \ + 0x0000FFFF /* MCU2MD_SW_INT_ENA[15..0] */ +#define WF_WFDMA_HOST_DMA1_MD_INT_ENA_MCU2MD_SW_INT_ENA_SHFT 0 + +/* +* ---MCU2MD_SW_INT_SET (0x18025000 + 0x258)--- +* MCU2MD_SW_INT_SET[15..0] - (RO) MCU to MD S/W interrupt set +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_MCU2MD_SW_INT_SET_MCU2MD_SW_INT_SET_ADDR \ + WF_WFDMA_HOST_DMA1_MCU2MD_SW_INT_SET_ADDR +#define WF_WFDMA_HOST_DMA1_MCU2MD_SW_INT_SET_MCU2MD_SW_INT_SET_MASK \ + 0x0000FFFF /* MCU2MD_SW_INT_SET[15..0] */ +#define WF_WFDMA_HOST_DMA1_MCU2MD_SW_INT_SET_MCU2MD_SW_INT_SET_SHFT 0 + +/* +* ---WPDMA_PAUSE_RX_Q_TH10 (0x18025000 + 0x260)--- +* RX_DMAD_TH0[11..0] - (RW) RX Ring0 DMAD threshold to pause PP +* sending packet to RX FIFO +* pause_rx_q = (available RX DMAD counts) < + +* RESERVED12[15..12] - (RO) Reserved bits +* RX_DMAD_TH1[27..16] - (RW) RX Ring1 DMAD threshold to pause PP +* sending packet to RX FIFO +* pause_rx_q = (available RX DMAD counts) < + +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH1_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH10_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH1_MASK \ + 0x0FFF0000 /* RX_DMAD_TH1[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH1_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH0_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH10_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH0_MASK \ + 0x00000FFF /* RX_DMAD_TH0[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH10_RX_DMAD_TH0_SHFT 0 + +/* +* ---WPDMA_PAUSE_RX_Q_TH32 (0x18025000 + 0x264)--- +* RX_DMAD_TH2[11..0] - (RW) RX Ring2 DMAD threshold to pause PP +* sending packet to RX FIFO +* pause_rx_q = (available RX DMAD counts) < + +* RESERVED12[15..12] - (RO) Reserved bits +* RX_DMAD_TH3[27..16] - (RW) RX Ring3 DMAD threshold to pause PP +* sending packet to RX FIFO +* pause_rx_q = (available RX DMAD counts) < + +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH3_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH32_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH3_MASK \ + 0x0FFF0000 /* RX_DMAD_TH3[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH3_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH2_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH32_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH2_MASK \ + 0x00000FFF /* RX_DMAD_TH2[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH32_RX_DMAD_TH2_SHFT 0 + +/* +* ---WPDMA_PAUSE_RX_Q_TH54 (0x18025000 + 0x268)--- +* RX_DMAD_TH4[11..0] - (RW) RX Ring4 DMAD threshold to pause PP +* sending packet to RX FIFO +* pause_rx_q = (available RX DMAD counts) < + +* RESERVED12[15..12] - (RO) Reserved bits +* RX_DMAD_TH5[27..16] - (RW) RX Ring5 DMAD threshold to pause PP +* sending packet to RX FIFO +* pause_rx_q = (available RX DMAD counts) < + +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH5_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH54_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH5_MASK \ + 0x0FFF0000 /* RX_DMAD_TH5[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH5_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH4_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH54_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH4_MASK \ + 0x00000FFF /* RX_DMAD_TH4[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH54_RX_DMAD_TH4_SHFT 0 + +/* +* ---WPDMA_PAUSE_RX_Q_TH76 (0x18025000 + 0x26C)--- +* RX_DMAD_TH6[11..0] - (RW) RX Ring6 DMAD threshold to pause PP +* sending packet to RX FIFO +* pause_rx_q = (available RX DMAD counts) < + +* RESERVED12[15..12] - (RO) Reserved bits +* RX_DMAD_TH7[27..16] - (RW) RX Ring7 DMAD threshold to pause PP +* sending packet to RX FIFO +* pause_rx_q = (available RX DMAD counts) < + +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH7_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH76_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH7_MASK \ + 0x0FFF0000 /* RX_DMAD_TH7[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH7_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH6_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH76_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH6_MASK \ + 0x00000FFF /* RX_DMAD_TH6[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PAUSE_RX_Q_TH76_RX_DMAD_TH6_SHFT 0 + +/* +* ---WPDMA_RST_DRX_PTR (0x18025000 + 0x280)--- +* RST_DRX_IDX0[0] - (WO) Write 1 to reset to RX_DMARX_IDX0 to 0 +* RST_DRX_IDX1[1] - (WO) Write 1 to reset to RX_DMARX_IDX1 to 0 +* RST_DRX_IDX2[2] - (WO) Write 1 to reset to RX_DMARX_IDX2 to 0 +* RST_DRX_IDX3[3] - (WO) Write 1 to reset to RX_DMARX_IDX3 to 0 +* RESERVED[31..4] - (WO) Reserved +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_RST_DRX_IDX3_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_RST_DRX_IDX3_MASK \ + 0x00000008 /* RST_DRX_IDX3[3] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_RST_DRX_IDX3_SHFT 3 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_RST_DRX_IDX2_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_RST_DRX_IDX2_MASK \ + 0x00000004 /* RST_DRX_IDX2[2] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_RST_DRX_IDX2_SHFT 2 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_RST_DRX_IDX1_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_RST_DRX_IDX1_MASK \ + 0x00000002 /* RST_DRX_IDX1[1] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_RST_DRX_IDX1_SHFT 1 +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_RST_DRX_IDX0_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_RST_DRX_IDX0_MASK \ + 0x00000001 /* RST_DRX_IDX0[0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RST_DRX_PTR_RST_DRX_IDX0_SHFT 0 + +/* +* ---WPDMA_INFO (0x18025000 + 0x284)--- +* TX_RING_NUMBER[7..0] - (RO) TX_RING_NUMBER +* RX_RING_NUMBER[15..8] - (RO) RX_RING_NUMBER +* BASE_PTR_WIDTH[23..16] - (RO) {2'h0, 6'd32-'BASE_PTR_WIDTH[5:0]} +* INDEX_WIDTH[27..24] - (RO) RING_INDEX_WIDTH +* PDMA_PREFETCH_SRAM_SIZE[30..28] - (RO) PDMA prefetch sram size{3'h0 : 128 +* byte, 3'h1 : 256 byte, 3'h2 : 512 byte, 3'h3 : 1KB, 3'h4 : 2KB, 3'h5 : 4KB, +* 3'h6 : 8KB, 3'h7 : reserved}, be noticed that prefetch sram is shared outside +* with other DMAs, please check all DMAs' total prefetch ring number and max_cnt +* for each prefetch ring to make sure that total size of all configured prefetch +* dmad of all DMAs' prefetch ring should be less than PDMA_PREFETCH_SRAM_SIZE +* WFDMA_PDA_EXIST[31] - (RO) Only cpu_dma1 will support pda functions +* for firmware download and wfdma_pda_top resides in between cpu_dma0 and +cpu_dma1! +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_WFDMA_PDA_EXIST_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_WFDMA_PDA_EXIST_MASK \ + 0x80000000 /* WFDMA_PDA_EXIST[31] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_WFDMA_PDA_EXIST_SHFT 31 +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_PDMA_PREFETCH_SRAM_SIZE_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_PDMA_PREFETCH_SRAM_SIZE_MASK \ + 0x70000000 /* PDMA_PREFETCH_SRAM_SIZE[30..28] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_PDMA_PREFETCH_SRAM_SIZE_SHFT 28 +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_INDEX_WIDTH_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_INDEX_WIDTH_MASK \ + 0x0F000000 /* INDEX_WIDTH[27..24] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_INDEX_WIDTH_SHFT 24 +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_BASE_PTR_WIDTH_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_BASE_PTR_WIDTH_MASK \ + 0x00FF0000 /* BASE_PTR_WIDTH[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_BASE_PTR_WIDTH_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_RX_RING_NUMBER_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_RX_RING_NUMBER_MASK \ + 0x0000FF00 /* RX_RING_NUMBER[15..8] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_RX_RING_NUMBER_SHFT 8 +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_TX_RING_NUMBER_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INFO_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_TX_RING_NUMBER_MASK \ + 0x000000FF /* TX_RING_NUMBER[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_TX_RING_NUMBER_SHFT 0 + +/* +* ---WPDMA_INFO_EXT (0x18025000 + 0x288)--- +* TX_EVENT_RING_NUMBER[7..0] - (RO) When TX_EVENT_RING_NUMBER equal 8'h0, it +* means that this DMA doesn't support dual TX fifo, thus in default it only +* support TX_RING_NUMBER of TX rings !! +* But when TX_EVENT_RING_NUMBER NOT equal +* 8'h0, this dma is configured as dual TX fifo and +* TX_RING[16+TX_EVENT_RING_NUM-1:16] are for getting HOST EVENT packet from HOST +* to WX_CPU!! +* TX_DMAD_RING_NUMBER[15..8] - (RO) When TX_EVENT_RING_NUMBER not equal to +* 8'h0, it means that this DMA support dual TX fifo and TX +* ring[TX_DMAD_RING_NUMBER-1:0] are for getting TXD from HOST to UMAC!! +* RESERVED[30..16] - (RO) Reserved +* TX_DMASHDL_EXIST[31] - (RO) TX_DMASHDL_EXIST +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_EXT_TX_DMASHDL_EXIST_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INFO_EXT_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_EXT_TX_DMASHDL_EXIST_MASK \ + 0x80000000 /* TX_DMASHDL_EXIST[31] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_EXT_TX_DMASHDL_EXIST_SHFT 31 +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_EXT_TX_DMAD_RING_NUMBER_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INFO_EXT_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_EXT_TX_DMAD_RING_NUMBER_MASK \ + 0x0000FF00 /* TX_DMAD_RING_NUMBER[15..8] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_EXT_TX_DMAD_RING_NUMBER_SHFT 8 +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_EXT_TX_EVENT_RING_NUMBER_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_INFO_EXT_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_EXT_TX_EVENT_RING_NUMBER_MASK \ + 0x000000FF /* TX_EVENT_RING_NUMBER[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_INFO_EXT_TX_EVENT_RING_NUMBER_SHFT 0 + +/* +* ---WPDMA_INT_RX_PRI_SEL (0x18025000 + 0x298)--- +* WPDMA_INT_RX_RING0_PRI_SEL[0] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_RX_RING1_PRI_SEL[1] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_RX_RING2_PRI_SEL[2] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_RX_RING3_PRI_SEL[3] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* RESERVED4[31..4] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING3_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING3_PRI_SEL_MASK \ + \ + 0x00000008 /* WPDMA_INT_RX_RING3_PRI_SEL[3] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING3_PRI_SEL_SHFT \ + \ + 3 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING2_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING2_PRI_SEL_MASK \ + \ + 0x00000004 /* WPDMA_INT_RX_RING2_PRI_SEL[2] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING2_PRI_SEL_SHFT \ + \ + 2 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING1_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING1_PRI_SEL_MASK \ + \ + 0x00000002 /* WPDMA_INT_RX_RING1_PRI_SEL[1] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING1_PRI_SEL_SHFT \ + \ + 1 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING0_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING0_PRI_SEL_MASK \ + \ + 0x00000001 /* WPDMA_INT_RX_RING0_PRI_SEL[0] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_RX_PRI_SEL_WPDMA_INT_RX_RING0_PRI_SEL_SHFT \ + \ + 0 + +/* +* ---WPDMA_INT_TX_PRI_SEL (0x18025000 + 0x29C)--- +* WPDMA_INT_TX_RING0_PRI_SEL[0] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING1_PRI_SEL[1] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING2_PRI_SEL[2] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING3_PRI_SEL[3] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING4_PRI_SEL[4] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING5_PRI_SEL[5] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING6_PRI_SEL[6] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING7_PRI_SEL[7] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING8_PRI_SEL[8] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING9_PRI_SEL[9] - (RW) write 1 to enable corresponding ring to +* be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING10_PRI_SEL[10] - (RW) write 1 to enable corresponding ring +* to be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING11_PRI_SEL[11] - (RW) write 1 to enable corresponding ring +* to be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING12_PRI_SEL[12] - (RW) write 1 to enable corresponding ring +* to be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING13_PRI_SEL[13] - (RW) write 1 to enable corresponding ring +* to be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING14_PRI_SEL[14] - (RW) write 1 to enable corresponding ring +* to be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* RESERVED15[15] - (RO) Reserved bits +* WPDMA_INT_TX_RING16_PRI_SEL[16] - (RW) write 1 to enable corresponding ring +* to be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING17_PRI_SEL[17] - (RW) write 1 to enable corresponding ring +* to be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING18_PRI_SEL[18] - (RW) write 1 to enable corresponding ring +* to be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING19_PRI_SEL[19] - (RW) write 1 to enable corresponding ring +* to be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* WPDMA_INT_TX_RING20_PRI_SEL[20] - (RW) write 1 to enable corresponding ring +* to be priority-selected interrupt for MSI message[6:0] and CIRQ[45:38], write +* 1'b0 to disable and combine it into legacy interrupt +* RESERVED21[31..21] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING20_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING20_PRI_SEL_MASK \ + \ + 0x00100000 /* WPDMA_INT_TX_RING20_PRI_SEL[20] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING20_PRI_SEL_SHFT \ + \ + 20 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING19_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING19_PRI_SEL_MASK \ + \ + 0x00080000 /* WPDMA_INT_TX_RING19_PRI_SEL[19] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING19_PRI_SEL_SHFT \ + \ + 19 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING18_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING18_PRI_SEL_MASK \ + \ + 0x00040000 /* WPDMA_INT_TX_RING18_PRI_SEL[18] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING18_PRI_SEL_SHFT \ + \ + 18 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING17_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING17_PRI_SEL_MASK \ + \ + 0x00020000 /* WPDMA_INT_TX_RING17_PRI_SEL[17] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING17_PRI_SEL_SHFT \ + \ + 17 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING16_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING16_PRI_SEL_MASK \ + \ + 0x00010000 /* WPDMA_INT_TX_RING16_PRI_SEL[16] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING16_PRI_SEL_SHFT \ + \ + 16 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING14_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING14_PRI_SEL_MASK \ + \ + 0x00004000 /* WPDMA_INT_TX_RING14_PRI_SEL[14] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING14_PRI_SEL_SHFT \ + \ + 14 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING13_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING13_PRI_SEL_MASK \ + \ + 0x00002000 /* WPDMA_INT_TX_RING13_PRI_SEL[13] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING13_PRI_SEL_SHFT \ + \ + 13 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING12_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING12_PRI_SEL_MASK \ + \ + 0x00001000 /* WPDMA_INT_TX_RING12_PRI_SEL[12] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING12_PRI_SEL_SHFT \ + \ + 12 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING11_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING11_PRI_SEL_MASK \ + \ + 0x00000800 /* WPDMA_INT_TX_RING11_PRI_SEL[11] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING11_PRI_SEL_SHFT \ + \ + 11 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING10_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING10_PRI_SEL_MASK \ + \ + 0x00000400 /* WPDMA_INT_TX_RING10_PRI_SEL[10] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING10_PRI_SEL_SHFT \ + \ + 10 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING9_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING9_PRI_SEL_MASK \ + \ + 0x00000200 /* WPDMA_INT_TX_RING9_PRI_SEL[9] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING9_PRI_SEL_SHFT \ + \ + 9 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING8_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING8_PRI_SEL_MASK \ + \ + 0x00000100 /* WPDMA_INT_TX_RING8_PRI_SEL[8] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING8_PRI_SEL_SHFT \ + \ + 8 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING7_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING7_PRI_SEL_MASK \ + \ + 0x00000080 /* WPDMA_INT_TX_RING7_PRI_SEL[7] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING7_PRI_SEL_SHFT \ + \ + 7 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING6_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING6_PRI_SEL_MASK \ + \ + 0x00000040 /* WPDMA_INT_TX_RING6_PRI_SEL[6] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING6_PRI_SEL_SHFT \ + \ + 6 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING5_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING5_PRI_SEL_MASK \ + \ + 0x00000020 /* WPDMA_INT_TX_RING5_PRI_SEL[5] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING5_PRI_SEL_SHFT \ + \ + 5 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING4_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING4_PRI_SEL_MASK \ + \ + 0x00000010 /* WPDMA_INT_TX_RING4_PRI_SEL[4] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING4_PRI_SEL_SHFT \ + \ + 4 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING3_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING3_PRI_SEL_MASK \ + \ + 0x00000008 /* WPDMA_INT_TX_RING3_PRI_SEL[3] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING3_PRI_SEL_SHFT \ + \ + 3 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING2_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING2_PRI_SEL_MASK \ + \ + 0x00000004 /* WPDMA_INT_TX_RING2_PRI_SEL[2] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING2_PRI_SEL_SHFT \ + \ + 2 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING1_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING1_PRI_SEL_MASK \ + \ + 0x00000002 /* WPDMA_INT_TX_RING1_PRI_SEL[1] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING1_PRI_SEL_SHFT \ + \ + 1 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING0_PRI_SEL_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING0_PRI_SEL_MASK \ + \ + 0x00000001 /* WPDMA_INT_TX_RING0_PRI_SEL[0] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_INT_TX_PRI_SEL_WPDMA_INT_TX_RING0_PRI_SEL_SHFT \ + \ + 0 + +/* +* ---WPDMA_TX_DBG0 (0x18025000 + 0x2A0)--- +* WPDMA_TX_DBG0[31..0] - (RO) xxx +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_DBG0_WPDMA_TX_DBG0_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_DBG0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_DBG0_WPDMA_TX_DBG0_MASK \ + 0xFFFFFFFF /* WPDMA_TX_DBG0[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_DBG0_WPDMA_TX_DBG0_SHFT 0 + +/* +* ---WPDMA_TX_DBG1 (0x18025000 + 0x2A4)--- +* WPDMA_TX_DBG1[31..0] - (RO) xxx +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_DBG1_WPDMA_TX_DBG1_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_DBG1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_DBG1_WPDMA_TX_DBG1_MASK \ + 0xFFFFFFFF /* WPDMA_TX_DBG1[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_DBG1_WPDMA_TX_DBG1_SHFT 0 + +/* +* ---WPDMA_RX_DBG0 (0x18025000 + 0x2A8)--- +* WPDMA_RX_DBG0[31..0] - (RO) xxx +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_DBG0_WPDMA_RX_DBG0_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_DBG0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_DBG0_WPDMA_RX_DBG0_MASK \ + 0xFFFFFFFF /* WPDMA_RX_DBG0[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_DBG0_WPDMA_RX_DBG0_SHFT 0 + +/* +* ---WPDMA_RX_DBG1 (0x18025000 + 0x2AC)--- +* WPDMA_RX_DBG1[31..0] - (RO) xxx +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_DBG1_WPDMA_RX_DBG1_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_DBG1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_DBG1_WPDMA_RX_DBG1_MASK \ + 0xFFFFFFFF /* WPDMA_RX_DBG1[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_DBG1_WPDMA_RX_DBG1_SHFT 0 + +/* +* ---WPDMA_GLO_CFG_EXT0 (0x18025000 + 0x2B0)--- +* CSR_MAX_PREFETCH_CNT[1..0] - (RW) Max. dmad count per prefet request, +* 2'b00 : 1 entry, 2'b01 : 2 entries, 2'b10 : 4 entries, 2'b11 : 8 entries, Note +* : 1 entry(dmad size) is 16 bytes = 4 DWs = 2 QWs +* CSR_MEM_BST_SIZE[3..2] - (RW) Max. burst size per sram request. 00 : +* 16-byte, 01 : 32-byte, 10 : 64-byte, 11 : 128-byte +* CSR_MEM_ARB_LOCK_EN[4] - (RW) 1'b1 : Lock round-robin sram access +* arbiter until whole long burst request from dma FSM finish, 1'b0 : no lock +sram +* arbiter, grant will be change per request due to round-robin +* CSR_RX_DMA_WBQ_EN[5] - (RW) 1'b1 : RX dmad will be posted-write and +* deal with next received packet immediately, 1'b0 : RX dmad will be written +back +* immediately after received packet has been sent to host memory +* CSR_TX_DMASHDL_ENABLE[6] - (RW) 1'b1 : request DMASHDL before TX to +* select next TX ring, 1'b0 : disable DMASHDL and use round-robin arbiter to +* select next TX ring +* CSR_BRESP_ERROR_BYPASS_EN[7] - (RW) 1'b1 : Bypass AXI error bresp as a +* normal response. 1'b0 : Will not assert bready to error bresp(00 : OKAY, 01 : +* EXOKAY, 10 : SLVERR, 11 : DECERR) +* CSR_AXI_SLEEP_MODE[9..8] - (RW) 2'b00 : no sleep, normal TX/RX, 2b1* : +* sleep after AXI request, 2'b11 : force assertion of wvalid, rready and bready +* to finish all committed data phases, then sleep immediately +* RESERVED10[14..10] - (RO) Reserved bits +* CSR_Q_STATUS_IDX_BKRS_EN[15] - (RW) backup/restore enable bit for +* q_status(payload, prefetch and dispatch) index +* CSR_AXI_BST_SIZE[17..16] - (RW) AXI busrt length, 00 : 128-byte, 01 : +* 64-byte, 10 : 32-byte, 11 : 16-byte +* RESERVED18[18] - (RO) Reserved bits +* CSR_AXI_FAKE[19] - (RW) If set to 1'b1, all requests from DMA +* engine will not be sent to AXI INFRA, this try to fix AXI bus hang issue +temporarily! +* CSR_DMAD_PREFETCH_THRESHOLD[21..20] - (RW) trigger dmad prefetch when +* available dmad cnt >= {1(2'b00), 2(2'b01), 4(2'b10), 8(2'b11)} +* CSR_BID_CHECK_BYPASS_EN[22] - (RW) If set to 1'b0, axi master will check +* matching between awid and bid before assert bready, if set to 1'b1, it will +* bypass this checking and assert bready for each bvalid even though bid doesn't +* match any awid ever issued! +* CSR_RX_INFO_WB_EN[23] - (RW) If set to 1'b0, only DW0 and DW1 will be +* written back into memory after received RX packet process finished, this will +* save bus bandwidth a little because DW2 and DW3 are useless for FW +* CSR_AXI_OUTSTANDING_NUM[27..24] - (RW) decide max. outstanding AXI requests, +* common for AXI read or write! +* CSR_AXI_ARUSER_LOCK_EN[28] - (RW) on/off customized lock ctrl design thru AXI +* aruser signal, this will influence TX QoS ctrl +* CSR_AXI_AWUSER_LOCK_EN[29] - (RW) on/off customized lock ctrl design thru AXI +* awuser signal when RX dmad write-back have to be separately written into +* memory due to external dispatcher exists! +* CSR_AXI_LOCK_EN[30] - (RW) Global lock enable to on/off AXI spec. +* lock(axlock) behavior and also will on/off customized lock ctrl design thru +* AXI awuser signal +* CSR_AXI_CLKGATE_BYP[31] - (RW) To bypass functional CG enable which +* incduced from coding style for DC inserted CG cell in all AXI read/write +master +* design module +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_CLKGATE_BYP_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_CLKGATE_BYP_MASK \ + 0x80000000 /* CSR_AXI_CLKGATE_BYP[31] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_CLKGATE_BYP_SHFT 31 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_LOCK_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_LOCK_EN_MASK \ + 0x40000000 /* CSR_AXI_LOCK_EN[30] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_LOCK_EN_SHFT 30 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_AWUSER_LOCK_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_AWUSER_LOCK_EN_MASK \ + 0x20000000 /* CSR_AXI_AWUSER_LOCK_EN[29] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_AWUSER_LOCK_EN_SHFT 29 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_ARUSER_LOCK_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_ARUSER_LOCK_EN_MASK \ + 0x10000000 /* CSR_AXI_ARUSER_LOCK_EN[28] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_ARUSER_LOCK_EN_SHFT 28 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_OUTSTANDING_NUM_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_OUTSTANDING_NUM_MASK \ + 0x0F000000 /* CSR_AXI_OUTSTANDING_NUM[27..24] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_OUTSTANDING_NUM_SHFT 24 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_RX_INFO_WB_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_RX_INFO_WB_EN_MASK \ + 0x00800000 /* CSR_RX_INFO_WB_EN[23] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_RX_INFO_WB_EN_SHFT 23 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_BID_CHECK_BYPASS_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_BID_CHECK_BYPASS_EN_MASK \ + 0x00400000 /* CSR_BID_CHECK_BYPASS_EN[22] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_BID_CHECK_BYPASS_EN_SHFT 22 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_DMAD_PREFETCH_THRESHOLD_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_DMAD_PREFETCH_THRESHOLD_MASK \ + 0x00300000 /* CSR_DMAD_PREFETCH_THRESHOLD[21..20] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_DMAD_PREFETCH_THRESHOLD_SHFT \ + 20 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_FAKE_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_FAKE_MASK \ + 0x00080000 /* CSR_AXI_FAKE[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_FAKE_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_BST_SIZE_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_BST_SIZE_MASK \ + 0x00030000 /* CSR_AXI_BST_SIZE[17..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_BST_SIZE_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_Q_STATUS_IDX_BKRS_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_Q_STATUS_IDX_BKRS_EN_MASK \ + 0x00008000 /* CSR_Q_STATUS_IDX_BKRS_EN[15] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_Q_STATUS_IDX_BKRS_EN_SHFT 15 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_SLEEP_MODE_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_SLEEP_MODE_MASK \ + 0x00000300 /* CSR_AXI_SLEEP_MODE[9..8] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_AXI_SLEEP_MODE_SHFT 8 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_BRESP_ERROR_BYPASS_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_BRESP_ERROR_BYPASS_EN_MASK \ + 0x00000080 /* CSR_BRESP_ERROR_BYPASS_EN[7] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_BRESP_ERROR_BYPASS_EN_SHFT 7 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_TX_DMASHDL_ENABLE_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_TX_DMASHDL_ENABLE_MASK \ + 0x00000040 /* CSR_TX_DMASHDL_ENABLE[6] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_TX_DMASHDL_ENABLE_SHFT 6 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_RX_DMA_WBQ_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_RX_DMA_WBQ_EN_MASK \ + 0x00000020 /* CSR_RX_DMA_WBQ_EN[5] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_RX_DMA_WBQ_EN_SHFT 5 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_MEM_ARB_LOCK_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_MEM_ARB_LOCK_EN_MASK \ + 0x00000010 /* CSR_MEM_ARB_LOCK_EN[4] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_MEM_ARB_LOCK_EN_SHFT 4 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_MEM_BST_SIZE_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_MEM_BST_SIZE_MASK \ + 0x0000000C /* CSR_MEM_BST_SIZE[3..2] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_MEM_BST_SIZE_SHFT 2 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_MAX_PREFETCH_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_MAX_PREFETCH_CNT_MASK \ + 0x00000003 /* CSR_MAX_PREFETCH_CNT[1..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT0_CSR_MAX_PREFETCH_CNT_SHFT 0 + +/* +* ---WPDMA_GLO_CFG_EXT1 (0x18025000 + 0x2B4)--- +* CSR_TXFIFO0_RDY_THRESHOLD[7..0] - (RW) xxx +* CSR_TXFIFO1_RDY_THRESHOLD[15..8] - (RW) xxx +* CSR_TX_DISP_ARB_SCHEDULED_ACCESS_TIMER[23..16] - (RW) timer setting for +* SCHEDULED_ACCESS_TIME_ARB of csr_tx_disp_arb_mode +* CSR_TX_DISP_ARB_MODE[25..24] - (RW) 00 : FAIR_ARB, 01 : FIX_ARB, 10 : +* UNBALANCED_ARB, 11 : SCHEDULED_ACCESS_TIME_ARB +* CSR_FWDL_FLOW_CTRL_BYASS_EN[26] - (RW) To disable firmware download TX flow +* control of TX dma(host_dma1) when firmare download of RX dma(mcu_dma1) is in +* firmware download polling mode!! Remember to set to 1'b0 when firmware +download +* ring is set back to normal ring usage which should be in flow control for +* correct behavior!! +* CSR_FWDL_FLOW_CTRL_BYASS_LS_QSEL_EN[27] - (RW) select firmware download TX +* ring(LSB/MSB ring) to bypass TX flow control when firmare download RX +* ring(LSB/MSB ring) of RX dma(mcu_dma1) is in firmware download polling mode!! +* RESERVED[31..28] - (RW) reserved +*/ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_LS_QSEL_EN_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_LS_QSEL_EN_MASK \ + \ + 0x08000000 /* CSR_FWDL_FLOW_CTRL_BYASS_LS_QSEL_EN[27] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_LS_QSEL_EN_SHFT \ + \ + 27 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_EN_MASK \ + 0x04000000 /* CSR_FWDL_FLOW_CTRL_BYASS_EN[26] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_FWDL_FLOW_CTRL_BYASS_EN_SHFT \ + 26 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_MODE_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_MODE_MASK \ + 0x03000000 /* CSR_TX_DISP_ARB_MODE[25..24] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_MODE_SHFT 24 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_SCHEDULED_ACCESS_TIMER_AD\ +DR \ +\ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_SCHEDULED_ACCESS_TIMER_MA\ +SK \ +\ + 0x00FF0000 /* CSR_TX_DISP_ARB_SCHEDULED_ACCESS_TIMER[23..16] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_TX_DISP_ARB_SCHEDULED_ACCESS_TIMER_SH\ +FT \ +\ + 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO1_RDY_THRESHOLD_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO1_RDY_THRESHOLD_MASK \ + 0x0000FF00 /* CSR_TXFIFO1_RDY_THRESHOLD[15..8] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO1_RDY_THRESHOLD_SHFT 8 +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO0_RDY_THRESHOLD_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO0_RDY_THRESHOLD_MASK \ + 0x000000FF /* CSR_TXFIFO0_RDY_THRESHOLD[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_GLO_CFG_EXT1_CSR_TXFIFO0_RDY_THRESHOLD_SHFT 0 + +/* +* ---WPDMA_TX_QOS_LMT_CFG0 (0x18025000 + 0x2C0)--- +* CSR_TX_PLD_AXI_LIMITER_REQ[2..0] - (RW) QoS CR, Limiter Enable for packet +* traffice of type TX_PLD +* CSR_TX_PLD_AXI_LIMITER_EN_REQ[3] - (RW) QoS CR, Limiter Enable for packet +* traffice of type TX_PLD +* CSR_TX_PLD_AXI_LIMITER_PKT[6..4] - (RW) QoS CR, Limiter Enable for packet +* traffice of type TX_PLD +* CSR_TX_PLD_AXI_LIMITER_EN_PKT[7] - (RW) QoS CR, Limiter Enable for packet +* traffice of type TX_PLD +* CSR_RX_PLD_AXI_LIMITER_REQ[10..8] - (RW) QoS CR, Limiter Enable for request +* traffice of type RX_PLD +* CSR_RX_PLD_AXI_LIMITER_EN_REQ[11] - (RW) QoS CR, Limiter Enable for request +* traffice of type RX_PLD +* CSR_RX_PLD_AXI_LIMITER_PKT[14..12] - (RW) QoS CR, Limiter Enable for request +* traffice of type RX_PLD +* CSR_RX_PLD_AXI_LIMITER_EN_PKT[15] - (RW) QoS CR, Limiter Enable for request +* traffice of type RX_PLD +* RESERVED16[31..16] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_EN_PKT_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_EN_PKT_MASK \ + \ + 0x00008000 /* CSR_RX_PLD_AXI_LIMITER_EN_PKT[15] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_EN_PKT_SHFT \ + \ + 15 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_PKT_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_PKT_MASK \ + \ + 0x00007000 /* CSR_RX_PLD_AXI_LIMITER_PKT[14..12] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_PKT_SHFT \ + \ + 12 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_EN_REQ_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_EN_REQ_MASK \ + \ + 0x00000800 /* CSR_RX_PLD_AXI_LIMITER_EN_REQ[11] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_EN_REQ_SHFT \ + \ + 11 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_REQ_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_REQ_MASK \ + \ + 0x00000700 /* CSR_RX_PLD_AXI_LIMITER_REQ[10..8] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_RX_PLD_AXI_LIMITER_REQ_SHFT \ + \ + 8 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_AXI_LIMITER_EN_PKT_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_AXI_LIMITER_EN_PKT_MASK \ + \ + 0x00000080 /* CSR_TX_PLD_AXI_LIMITER_EN_PKT[7] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_AXI_LIMITER_EN_PKT_SHFT \ + \ + 7 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_AXI_LIMITER_PKT_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_AXI_LIMITER_PKT_MASK \ + \ + 0x00000070 /* CSR_TX_PLD_AXI_LIMITER_PKT[6..4] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_AXI_LIMITER_PKT_SHFT \ + \ + 4 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_AXI_LIMITER_EN_REQ_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_AXI_LIMITER_EN_REQ_MASK \ + \ + 0x00000008 /* CSR_TX_PLD_AXI_LIMITER_EN_REQ[3] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_AXI_LIMITER_EN_REQ_SHFT \ + \ + 3 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_AXI_LIMITER_REQ_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_AXI_LIMITER_REQ_MASK \ + \ + 0x00000007 /* CSR_TX_PLD_AXI_LIMITER_REQ[2..0] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG0_CSR_TX_PLD_AXI_LIMITER_REQ_SHFT \ + \ + 0 + +/* +* ---WPDMA_TX_QOS_LMT_CFG1 (0x18025000 + 0x2C4)--- +* CSR_AUX_TX_PLD_AXI_LIMITER_REQ[2..0] - (RW) QoS CR, Limiter value selected +* by PP dynamically +* RESERVED3[3] - (RO) Reserved bits +* CSR_AUX_TX_PLD_AXI_LIMITER_PKT[6..4] - (RW) QoS CR, Limiter value selected +* by PP dynamically +* RESERVED7[7] - (RO) Reserved bits +* CSR_AUX_RX_PLD_AXI_LIMITER_REQ[10..8] - (RW) QoS CR, Limiter value selected +* by PP dynamically +* RESERVED11[11] - (RO) Reserved bits +* CSR_AUX_RX_PLD_AXI_LIMITER_PKT[14..12] - (RW) QoS CR, Limiter value selected +* by PP dynamically +* RESERVED15[31..15] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_RX_PLD_AXI_LIMITER_PKT_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_RX_PLD_AXI_LIMITER_PKT_MASK \ + \ + 0x00007000 /* CSR_AUX_RX_PLD_AXI_LIMITER_PKT[14..12] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_RX_PLD_AXI_LIMITER_PKT_SHFT \ + \ + 12 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_RX_PLD_AXI_LIMITER_REQ_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_RX_PLD_AXI_LIMITER_REQ_MASK \ + \ + 0x00000700 /* CSR_AUX_RX_PLD_AXI_LIMITER_REQ[10..8] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_RX_PLD_AXI_LIMITER_REQ_SHFT \ + \ + 8 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_AXI_LIMITER_PKT_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_AXI_LIMITER_PKT_MASK \ + \ + 0x00000070 /* CSR_AUX_TX_PLD_AXI_LIMITER_PKT[6..4] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_AXI_LIMITER_PKT_SHFT \ + \ + 4 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_AXI_LIMITER_REQ_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_AXI_LIMITER_REQ_MASK \ + \ + 0x00000007 /* CSR_AUX_TX_PLD_AXI_LIMITER_REQ[2..0] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG1_CSR_AUX_TX_PLD_AXI_LIMITER_REQ_SHFT \ + \ + 0 + +/* +* ---WPDMA_TX_QOS_LMT_CFG2 (0x18025000 + 0x2C8)--- +* CSR_RX_RD_DMAD_AXI_LIMITER_REQ[2..0] - (RW) QoS CR, Limiter Value for +* packet traffice of type RX_RD_DMAD +* CSR_RX_RD_DMAD_AXI_LIMITER_EN_REQ[3] - (RW) QoS CR, Limiter Enable for +* request traffice of type RX_RD_DMAD +* CSR_RX_RD_DMAD_AXI_LIMITER_PKT[6..4] - (RW) QoS CR, Limiter Value for +* packet traffice of type RX_RD_DMAD +* CSR_RX_RD_DMAD_AXI_LIMITER_EN_PKT[7] - (RW) QoS CR, Limiter Enable for +* packet traffice of type RX_RD_DMAD +* CSR_RX_WR_DMAD_AXI_LIMITER_REQ[10..8] - (RW) QoS CR, Limiter Value for +* packet traffice of type RX_WR_DMAD +* CSR_RX_WR_DMAD_AXI_LIMITER_EN_REQ[11] - (RW) QoS CR, Limiter Enable for +* request traffice of type RX_WR_DMAD +* CSR_RX_WR_DMAD_AXI_LIMITER_PKT[14..12] - (RW) QoS CR, Limiter Value for +* packet traffice of type RX_WR_DMAD +* CSR_RX_WR_DMAD_AXI_LIMITER_EN_PKT[15] - (RW) QoS CR, Limiter Enable for +* packet traffice of type RX_WR_DMAD +* CSR_TX_RD_DMAD_AXI_LIMITER_REQ[18..16] - (RW) QoS CR, Limiter Value for +* packet traffice of type TX_RD_DMAD +* CSR_TX_RD_DMAD_AXI_LIMITER_EN_REQ[19] - (RW) QoS CR, Limiter Enable for +* request traffice of type TX_RD_DMAD +* CSR_TX_RD_DMAD_AXI_LIMITER_PKT[22..20] - (RW) QoS CR, Limiter Value for +* packet traffice of type TX_RD_DMAD +* CSR_TX_RD_DMAD_AXI_LIMITER_EN_PKT[23] - (RW) QoS CR, Limiter Enable for +* packet traffice of type TX_RD_DMAD +* CSR_TX_WR_DMAD_AXI_LIMITER_REQ[26..24] - (RW) QoS CR, Limiter Value for +* packet traffice of type TX_WR_DMAD +* CSR_TX_WR_DMAD_AXI_LIMITER_EN_REQ[27] - (RW) QoS CR, Limiter Enable for +* request traffice of type TX_WR_DMAD +* CSR_TX_WR_DMAD_AXI_LIMITER_PKT[30..28] - (RW) QoS CR, Limiter Value for +* packet traffice of type TX_WR_DMAD +* CSR_TX_WR_DMAD_AXI_LIMITER_EN_PKT[31] - (RW) QoS CR, Limiter Enable for +* packet traffice of type TX_WR_DMAD +*/ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_EN_PKT_ADDR\ +\ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_EN_PKT_MASK\ +\ + 0x80000000 /* CSR_TX_WR_DMAD_AXI_LIMITER_EN_PKT[31] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_EN_PKT_SHFT\ +\ + 31 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_PKT_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_PKT_MASK \ + \ + 0x70000000 /* CSR_TX_WR_DMAD_AXI_LIMITER_PKT[30..28] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_PKT_SHFT \ + \ + 28 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_EN_REQ_ADDR\ +\ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_EN_REQ_MASK\ +\ + 0x08000000 /* CSR_TX_WR_DMAD_AXI_LIMITER_EN_REQ[27] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_EN_REQ_SHFT\ +\ + 27 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_REQ_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_REQ_MASK \ + \ + 0x07000000 /* CSR_TX_WR_DMAD_AXI_LIMITER_REQ[26..24] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_WR_DMAD_AXI_LIMITER_REQ_SHFT \ + \ + 24 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_EN_PKT_ADDR\ +\ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_EN_PKT_MASK\ +\ + 0x00800000 /* CSR_TX_RD_DMAD_AXI_LIMITER_EN_PKT[23] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_EN_PKT_SHFT\ +\ + 23 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_PKT_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_PKT_MASK \ + \ + 0x00700000 /* CSR_TX_RD_DMAD_AXI_LIMITER_PKT[22..20] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_PKT_SHFT \ + \ + 20 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_EN_REQ_ADDR\ +\ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_EN_REQ_MASK\ +\ + 0x00080000 /* CSR_TX_RD_DMAD_AXI_LIMITER_EN_REQ[19] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_EN_REQ_SHFT\ +\ + 19 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_REQ_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_REQ_MASK \ + \ + 0x00070000 /* CSR_TX_RD_DMAD_AXI_LIMITER_REQ[18..16] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_TX_RD_DMAD_AXI_LIMITER_REQ_SHFT \ + \ + 16 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_EN_PKT_ADDR\ +\ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_EN_PKT_MASK\ +\ + 0x00008000 /* CSR_RX_WR_DMAD_AXI_LIMITER_EN_PKT[15] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_EN_PKT_SHFT\ +\ + 15 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_PKT_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_PKT_MASK \ + \ + 0x00007000 /* CSR_RX_WR_DMAD_AXI_LIMITER_PKT[14..12] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_PKT_SHFT \ + \ + 12 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_EN_REQ_ADDR\ +\ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_EN_REQ_MASK\ +\ + 0x00000800 /* CSR_RX_WR_DMAD_AXI_LIMITER_EN_REQ[11] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_EN_REQ_SHFT\ +\ + 11 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_REQ_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_REQ_MASK \ + \ + 0x00000700 /* CSR_RX_WR_DMAD_AXI_LIMITER_REQ[10..8] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_WR_DMAD_AXI_LIMITER_REQ_SHFT \ + \ + 8 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_EN_PKT_ADDR\ +\ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_EN_PKT_MASK\ +\ + 0x00000080 /* CSR_RX_RD_DMAD_AXI_LIMITER_EN_PKT[7] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_EN_PKT_SHFT\ +\ + 7 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_PKT_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_PKT_MASK \ + \ + 0x00000070 /* CSR_RX_RD_DMAD_AXI_LIMITER_PKT[6..4] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_PKT_SHFT \ + \ + 4 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_EN_REQ_ADDR\ +\ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_EN_REQ_MASK\ +\ + 0x00000008 /* CSR_RX_RD_DMAD_AXI_LIMITER_EN_REQ[3] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_EN_REQ_SHFT\ +\ + 3 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_REQ_ADDR \ + \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_REQ_MASK \ + \ + 0x00000007 /* CSR_RX_RD_DMAD_AXI_LIMITER_REQ[2..0] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG2_CSR_RX_RD_DMAD_AXI_LIMITER_REQ_SHFT \ + \ + 0 + +/* +* ---WPDMA_TX_QOS_LMT_CFG3 (0x18025000 + 0x2CC)--- +* CSR_AUX_RX_RD_DMAD_AXI_LIMITER_REQ[2..0] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED3[3] - (RO) Reserved bits +* CSR_AUX_RX_RD_DMAD_AXI_LIMITER_PKT[6..4] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED7[7] - (RO) Reserved bits +* CSR_AUX_RX_WR_DMAD_AXI_LIMITER_REQ[10..8] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED11[11] - (RO) Reserved bits +* CSR_AUX_RX_WR_DMAD_AXI_LIMITER_PKT[14..12] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED15[15] - (RO) Reserved bits +* CSR_AUX_TX_RD_DMAD_AXI_LIMITER_REQ[18..16] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED19[19] - (RO) Reserved bits +* CSR_AUX_TX_RD_DMAD_AXI_LIMITER_PKT[22..20] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED23[23] - (RO) Reserved bits +* CSR_AUX_TX_WR_DMAD_AXI_LIMITER_REQ[26..24] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED27[27] - (RO) Reserved bits +* CSR_AUX_TX_WR_DMAD_AXI_LIMITER_PKT[30..28] - (RW) QoS CR, Limiter value +* selected by PP dynamically +* RESERVED31[31] - (RO) Reserved bits +*/ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_WR_DMAD_AXI_LIMITER_PKT_ADD\ +R \ +\ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_WR_DMAD_AXI_LIMITER_PKT_MAS\ +K \ +\ + 0x70000000 /* CSR_AUX_TX_WR_DMAD_AXI_LIMITER_PKT[30..28] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_WR_DMAD_AXI_LIMITER_PKT_SHF\ +T \ +\ + 28 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_WR_DMAD_AXI_LIMITER_REQ_ADD\ +R \ +\ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_WR_DMAD_AXI_LIMITER_REQ_MAS\ +K \ +\ + 0x07000000 /* CSR_AUX_TX_WR_DMAD_AXI_LIMITER_REQ[26..24] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_WR_DMAD_AXI_LIMITER_REQ_SHF\ +T \ +\ + 24 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_RD_DMAD_AXI_LIMITER_PKT_ADD\ +R \ +\ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_RD_DMAD_AXI_LIMITER_PKT_MAS\ +K \ +\ + 0x00700000 /* CSR_AUX_TX_RD_DMAD_AXI_LIMITER_PKT[22..20] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_RD_DMAD_AXI_LIMITER_PKT_SHF\ +T \ +\ + 20 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_RD_DMAD_AXI_LIMITER_REQ_ADD\ +R \ +\ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_RD_DMAD_AXI_LIMITER_REQ_MAS\ +K \ +\ + 0x00070000 /* CSR_AUX_TX_RD_DMAD_AXI_LIMITER_REQ[18..16] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_TX_RD_DMAD_AXI_LIMITER_REQ_SHF\ +T \ +\ + 16 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_WR_DMAD_AXI_LIMITER_PKT_ADD\ +R \ +\ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_WR_DMAD_AXI_LIMITER_PKT_MAS\ +K \ +\ + 0x00007000 /* CSR_AUX_RX_WR_DMAD_AXI_LIMITER_PKT[14..12] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_WR_DMAD_AXI_LIMITER_PKT_SHF\ +T \ +\ + 12 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_WR_DMAD_AXI_LIMITER_REQ_ADD\ +R \ +\ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_WR_DMAD_AXI_LIMITER_REQ_MAS\ +K \ +\ + 0x00000700 /* CSR_AUX_RX_WR_DMAD_AXI_LIMITER_REQ[10..8] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_WR_DMAD_AXI_LIMITER_REQ_SHF\ +T \ +\ + 8 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_RD_DMAD_AXI_LIMITER_PKT_ADD\ +R \ +\ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_RD_DMAD_AXI_LIMITER_PKT_MAS\ +K \ +\ + 0x00000070 /* CSR_AUX_RX_RD_DMAD_AXI_LIMITER_PKT[6..4] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_RD_DMAD_AXI_LIMITER_PKT_SHF\ +T \ +\ + 4 +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_RD_DMAD_AXI_LIMITER_REQ_ADD\ +R \ +\ + WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_ADDR +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_RD_DMAD_AXI_LIMITER_REQ_MAS\ +K \ +\ + 0x00000007 /* CSR_AUX_RX_RD_DMAD_AXI_LIMITER_REQ[2..0] */ +#define \ +WF_WFDMA_HOST_DMA1_WPDMA_TX_QOS_LMT_CFG3_CSR_AUX_RX_RD_DMAD_AXI_LIMITER_REQ_SHF\ +T \ +\ + 0 + +/* +* ---HOST_PRI_INT_STA (0x18025000 + 0x2E0)--- +* host_pri_int_sts_0[0] - (W1C) tx_done_int[18], W1C to clear delay +interrupt +* host_pri_int_sts_1[1] - (W1C) tx_done_int[19], W1C to clear delay +interrupt +* host_pri_int_sts_2[2] - (W1C) rx_done_int[0], W1C to clear delay +interrupt +* host_pri_int_sts_3[3] - (W1C) rx_done_int[1], W1C to clear delay +interrupt +* host_pri_int_sts_4[4] - (W1C) rx_done_int[2], W1C to clear delay +interrupt +* RESERVED5[31..5] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_host_pri_int_sts_4_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_host_pri_int_sts_4_MASK \ + 0x00000010 /* host_pri_int_sts_4[4] */ +#define WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_host_pri_int_sts_4_SHFT 4 +#define WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_host_pri_int_sts_3_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_host_pri_int_sts_3_MASK \ + 0x00000008 /* host_pri_int_sts_3[3] */ +#define WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_host_pri_int_sts_3_SHFT 3 +#define WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_host_pri_int_sts_2_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_host_pri_int_sts_2_MASK \ + 0x00000004 /* host_pri_int_sts_2[2] */ +#define WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_host_pri_int_sts_2_SHFT 2 +#define WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_host_pri_int_sts_1_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_host_pri_int_sts_1_MASK \ + 0x00000002 /* host_pri_int_sts_1[1] */ +#define WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_host_pri_int_sts_1_SHFT 1 +#define WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_host_pri_int_sts_0_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_host_pri_int_sts_0_MASK \ + 0x00000001 /* host_pri_int_sts_0[0] */ +#define WF_WFDMA_HOST_DMA1_HOST_PRI_INT_STA_host_pri_int_sts_0_SHFT 0 + +/* +* ---HOST_PER_INT_ENA_STA (0x18025000 + 0x2E4)--- +* wpdma_per_int_sts[3..0] - (W1C) status bit for rx ring periodic delayed +* interrupt to tracking ring is full or not, start delayed interrupt timer when +* RX ring is not full from falling edge of full flag and reset when ring full +* flag is asserted +* RESERVED4[15..4] - (RO) Reserved bits +* wpdma_per_int_ena[19..16] - (RW) enable bit for rx ring periodic delayed +* interrupt to tracking ring is full or not, start delayed interrupt timer when +* RX ring is not full from falling edge of full flag and reset when ring full +* flag is asserted +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_HOST_PER_INT_ENA_STA_wpdma_per_int_ena_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_PER_INT_ENA_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_PER_INT_ENA_STA_wpdma_per_int_ena_MASK \ + 0x000F0000 /* wpdma_per_int_ena[19..16] */ +#define WF_WFDMA_HOST_DMA1_HOST_PER_INT_ENA_STA_wpdma_per_int_ena_SHFT 16 +#define WF_WFDMA_HOST_DMA1_HOST_PER_INT_ENA_STA_wpdma_per_int_sts_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_PER_INT_ENA_STA_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_PER_INT_ENA_STA_wpdma_per_int_sts_MASK \ + 0x0000000F /* wpdma_per_int_sts[3..0] */ +#define WF_WFDMA_HOST_DMA1_HOST_PER_INT_ENA_STA_wpdma_per_int_sts_SHFT 0 + +/* +* ---HOST_PER_DLY_INT_CFG (0x18025000 + 0x2E8)--- +* wpdma_per_max_ptime[7..0] - (RW) Specified Max pending time for the +* internal RX ring full flag falling edge. When the pending time equal or +greater +* PER_MAX_PTIME x 20us or the # of pended TX_DONE_INT equal or greater than +* TX_MAX_PINT (see above), an Final TX_DLY_INT is generated +* Set to 0 will disable pending interrupt +* time check +* wpdma_per_dly_int_en[11..8] - (RW) RX periodic Delayed Interrupt Enable +* 1: Enable RX periodic delayed interrupt +mechanism +* 0: Disable RX periodic delayed interrupt +mechanism +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_HOST_PER_DLY_INT_CFG_wpdma_per_dly_int_en_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_PER_DLY_INT_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_PER_DLY_INT_CFG_wpdma_per_dly_int_en_MASK \ + 0x00000F00 /* wpdma_per_dly_int_en[11..8] */ +#define WF_WFDMA_HOST_DMA1_HOST_PER_DLY_INT_CFG_wpdma_per_dly_int_en_SHFT 8 +#define WF_WFDMA_HOST_DMA1_HOST_PER_DLY_INT_CFG_wpdma_per_max_ptime_ADDR \ + WF_WFDMA_HOST_DMA1_HOST_PER_DLY_INT_CFG_ADDR +#define WF_WFDMA_HOST_DMA1_HOST_PER_DLY_INT_CFG_wpdma_per_max_ptime_MASK \ + 0x000000FF /* wpdma_per_max_ptime[7..0] */ +#define WF_WFDMA_HOST_DMA1_HOST_PER_DLY_INT_CFG_wpdma_per_max_ptime_SHFT 0 + +/* +* ---WPDMA_PRI_DLY_INT_CFG0 (0x18025000 + 0x2F0)--- +* PRI0_MAX_PTIME[7..0] - (RW) Specified Max pending time for the +* internal PRI0_DONE_INT. When the pending time equal or greater PRI0_MAX_PTIME +x +* 20us or the # of pended PRI0_DONE_INT equal or greater than PRI0_MAX_PINT (see +* above), an Final PRI0_DLY_INT is generated +* Set to 0 will disable pending interrupt +* time check +* PRI0_MAX_PINT[14..8] - (RW) Specified Max # of pended interrupts. +* When the # of pended interrupts equal or +* greater than the value specified here or interrupt pending time reach the +limit +* (See below), a Final PRI0_DLY_INT is generated. +* Set to 0 will disable pending interrupt +* count check +* PRI0_DLY_INT_EN[15] - (RW) Priority Delayed Interrupt Enable +* 1: Enable Priority delayed interrupt +mechanism +* 0: Disable Priority delayed interrupt +mechanism +* In AXE host_dma0, these PRI1_* settings are +* for rx_ring[1]_int, and PRI0_* settings are for rx_ring[0]_int +* In AXE host_dma1, these PRI1_* settings are +* for rx_ring[0]_int, and PRI0_* settings are for Ored-tx_ring[14:0]_int +* In AXE mcu_dma0 and mcu_dma1, there are no +* priority interrupt thus no this 0x2E0 CR!! +* PRI1_MAX_PTIME[23..16] - (RW) Specified Max pending time for the +* internal PRI1_DONE_INT. When the pending time equal or greater PRI1_MAX_PTIME +x +* 20us or the # of pended PRI1_DONE_INT equal or greater than PRI1_MAX_PINT (see +* above), an Final PRI1_DLY_INT is generated +* Set to 0 will disable pending interrupt +* time check +* PRI1_MAX_PINT[30..24] - (RW) Specified Max # of pended interrupts. +* When the # of pended interrupts equal or +* greater than the value specified here or interrupt pending time reach the +limit +* (See below), a Final PRI1_DLY_INT is generated. +* Set to 0 will disable pending interrupt +* count check +* PRI1_DLY_INT_EN[31] - (RW) Priority Delayed Interrupt Enable +* 1: Enable Priority delayed interrupt +mechanism +* 0: Disable Priority delayed interrupt +mechanism +* In AXE host_dma0, these PRI1_* settings are +* for rx_ring[1]_int, and PRI0_* settings are for rx_ring[0]_int +* In AXE host_dma1, these PRI1_* settings are +* for rx_ring[0]_int, and PRI0_* settings are for Ored-tx_ring[14:0]_int +* In AXE mcu_dma0 and mcu_dma1, there are no +* priority interrupt thus no this 0x2E0 CR!! +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI1_DLY_INT_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI1_DLY_INT_EN_MASK \ + 0x80000000 /* PRI1_DLY_INT_EN[31] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI1_DLY_INT_EN_SHFT 31 +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PINT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PINT_MASK \ + 0x7F000000 /* PRI1_MAX_PINT[30..24] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PINT_SHFT 24 +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PTIME_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PTIME_MASK \ + 0x00FF0000 /* PRI1_MAX_PTIME[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI1_MAX_PTIME_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI0_DLY_INT_EN_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI0_DLY_INT_EN_MASK \ + 0x00008000 /* PRI0_DLY_INT_EN[15] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI0_DLY_INT_EN_SHFT 15 +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PINT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PINT_MASK \ + 0x00007F00 /* PRI0_MAX_PINT[14..8] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PINT_SHFT 8 +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PTIME_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PTIME_MASK \ + 0x000000FF /* PRI0_MAX_PTIME[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_PRI_DLY_INT_CFG0_PRI0_MAX_PTIME_SHFT 0 + +/* +* ---WPDMA_TX_RING0_CTRL0 (0x18025000 + 0x300)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring0 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING0_CTRL1 (0x18025000 + 0x304)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring0. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring0 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING0_CTRL2 (0x18025000 + 0x308)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING0_CTRL3 (0x18025000 + 0x30c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING1_CTRL0 (0x18025000 + 0x310)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring1 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING1_CTRL1 (0x18025000 + 0x314)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring1. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring1 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING1_CTRL2 (0x18025000 + 0x318)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING1_CTRL3 (0x18025000 + 0x31c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING2_CTRL0 (0x18025000 + 0x320)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring2 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING2_CTRL1 (0x18025000 + 0x324)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring2. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring2 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING2_CTRL2 (0x18025000 + 0x328)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING2_CTRL3 (0x18025000 + 0x32c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING3_CTRL0 (0x18025000 + 0x330)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring3 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING3_CTRL1 (0x18025000 + 0x334)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring3. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring3 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING3_CTRL2 (0x18025000 + 0x338)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING3_CTRL3 (0x18025000 + 0x33c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING4_CTRL0 (0x18025000 + 0x340)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring4 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING4_CTRL1 (0x18025000 + 0x344)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring4. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring4 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING4_CTRL2 (0x18025000 + 0x348)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING4_CTRL3 (0x18025000 + 0x34c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING5_CTRL0 (0x18025000 + 0x350)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring5 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING5_CTRL1 (0x18025000 + 0x354)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring5. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring5 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING5_CTRL2 (0x18025000 + 0x358)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING5_CTRL3 (0x18025000 + 0x35c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING6_CTRL0 (0x18025000 + 0x360)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring6 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING6_CTRL1 (0x18025000 + 0x364)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring6. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring6 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING6_CTRL2 (0x18025000 + 0x368)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING6_CTRL3 (0x18025000 + 0x36c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING7_CTRL0 (0x18025000 + 0x370)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring7 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING7_CTRL1 (0x18025000 + 0x374)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring7. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring7 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING7_CTRL2 (0x18025000 + 0x378)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING7_CTRL3 (0x18025000 + 0x37c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING8_CTRL0 (0x18025000 + 0x380)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring0 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING8_CTRL1 (0x18025000 + 0x384)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring0. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring0 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING8_CTRL2 (0x18025000 + 0x388)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING8_CTRL3 (0x18025000 + 0x38c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING9_CTRL0 (0x18025000 + 0x390)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring1 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING9_CTRL1 (0x18025000 + 0x394)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring1. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring1 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING9_CTRL2 (0x18025000 + 0x398)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING9_CTRL3 (0x18025000 + 0x39c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING10_CTRL0 (0x18025000 + 0x3a0)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring2 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING10_CTRL1 (0x18025000 + 0x3a4)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring2. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring2 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING10_CTRL2 (0x18025000 + 0x3a8)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING10_CTRL3 (0x18025000 + 0x3ac)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING11_CTRL0 (0x18025000 + 0x3b0)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring3 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING11_CTRL1 (0x18025000 + 0x3b4)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring3. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring3 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING11_CTRL2 (0x18025000 + 0x3b8)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING11_CTRL3 (0x18025000 + 0x3bc)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING12_CTRL0 (0x18025000 + 0x3c0)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring4 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING12_CTRL1 (0x18025000 + 0x3c4)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring4. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring4 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING12_CTRL2 (0x18025000 + 0x3c8)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING12_CTRL3 (0x18025000 + 0x3cc)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING13_CTRL0 (0x18025000 + 0x3d0)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring5 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING13_CTRL1 (0x18025000 + 0x3d4)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring5. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring5 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING13_CTRL2 (0x18025000 + 0x3d8)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING13_CTRL3 (0x18025000 + 0x3dc)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING14_CTRL0 (0x18025000 + 0x3e0)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring6 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING14_CTRL1 (0x18025000 + 0x3e4)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring6. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring6 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING14_CTRL2 (0x18025000 + 0x3e8)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING14_CTRL3 (0x18025000 + 0x3ec)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING15_CTRL0 (0x18025000 + 0x3f0)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring7 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING15_CTRL1 (0x18025000 + 0x3f4)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring7. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring7 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING15_CTRL2 (0x18025000 + 0x3f8)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING15_CTRL3 (0x18025000 + 0x3fc)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING16_CTRL0 (0x18025000 + 0x400)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_RING16 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING16_CTRL1 (0x18025000 + 0x404)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_RING16. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring16 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING16_CTRL2 (0x18025000 + 0x408)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING16_CTRL3 (0x18025000 + 0x40c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING17_CTRL0 (0x18025000 + 0x410)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring17 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING17_CTRL1 (0x18025000 + 0x414)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring17. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring17 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING17_CTRL2 (0x18025000 + 0x418)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING17_CTRL3 (0x18025000 + 0x41c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING18_CTRL0 (0x18025000 + 0x420)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring18 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING18_CTRL1 (0x18025000 + 0x424)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring18. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring18 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING18_CTRL2 (0x18025000 + 0x428)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING18_CTRL3 (0x18025000 + 0x42c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING19_CTRL0 (0x18025000 + 0x430)--- +* BASE_PTR[31..0] - (RW) Point to the base address of TX_Ring19 +* (8-DWORD aligned address) +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_TX_RING19_CTRL1 (0x18025000 + 0x434)--- +* MAX_CNT[11..0] - (RW) The maximum number of TXD count in +TXD_Ring19. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* TX_Ring19 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING19_CTRL2 (0x18025000 + 0x438)--- +* CPU_IDX[11..0] - (RW) Point to the next TXD CPU wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING19_CTRL3 (0x18025000 + 0x43c)--- +* DMA_IDX[11..0] - (RO) Point to the next TXD DMA wants to use +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING0_CTRL0 (0x18025000 + 0x500)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #0 +* (GE ports). It should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING0_CTRL1 (0x18025000 + 0x504)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD +* Ring #0. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* RX_Ring0 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING0_CTRL2 (0x18025000 + 0x508)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to +* allocate to RXD Ring #0. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING0_CTRL3 (0x18025000 + 0x50c)--- +* DMA_IDX[11..0] - (RW) In normal operation, user dma_index +* would udated by hardware when moving rx packet done. User should not write +dma_index. +* Point to the next RXD DMA wants to use in +* FDS Ring#0. It should be a 8-DWORD aligned address. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING1_CTRL0 (0x18025000 + 0x510)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #1 +* (GE ports). It should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING1_CTRL1 (0x18025000 + 0x514)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD +* Ring #1. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* RX_Ring1 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING1_CTRL2 (0x18025000 + 0x518)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to +* allocate to RXD Ring #1. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING1_CTRL3 (0x18025000 + 0x51c)--- +* DMA_IDX[11..0] - (RW) In normal operation, user dma_index +* would udated by hardware when moving rx packet done. User should not write +dma_index. +* Point to the next RXD DMA wants to use in +* FDS Ring#1. It should be a 8-DWORD aligned address. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING2_CTRL0 (0x18025000 + 0x520)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #2 +* (GE ports). It should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING2_CTRL1 (0x18025000 + 0x524)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD +* Ring #2. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* RX_Ring2 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING2_CTRL2 (0x18025000 + 0x528)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to +* allocate to RXD Ring #2. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING2_CTRL3 (0x18025000 + 0x52C)--- +* DMA_IDX[11..0] - (RW) In normal operation, user dma_index +* would udated by hardware when moving rx packet done. User should not write +dma_index. +* Point to the next RXD DMA wants to use in +* FDS Ring#2. It should be a 8-DWORD aligned address. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING3_CTRL0 (0x18025000 + 0x530)--- +* BASE_PTR[31..0] - (RW) Point to the base address of RXD Ring #3 +* (GE ports). It should be a 8-DWORD aligned address +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL0_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL0_BASE_PTR_MASK \ + 0xFFFFFFFF /* BASE_PTR[31..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL0_BASE_PTR_SHFT 0 + +/* +* ---WPDMA_RX_RING3_CTRL1 (0x18025000 + 0x534)--- +* MAX_CNT[11..0] - (RW) The maximum number of RXD count in RXD +* Ring #3. +* RESERVED12[15..12] - (RO) Reserved bits +* BASE_PTR_EXT[19..16] - (RW) Point to the base address[35:32] of +* RX_Ring3 (8-DWORD aligned address) +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL1_BASE_PTR_EXT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL1_BASE_PTR_EXT_MASK \ + 0x000F0000 /* BASE_PTR_EXT[19..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL1_BASE_PTR_EXT_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL1_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL1_MAX_CNT_MASK \ + 0x00000FFF /* MAX_CNT[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL1_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING3_CTRL2 (0x18025000 + 0x538)--- +* CPU_IDX[11..0] - (RW) Point to the next RXD CPU wants to +* allocate to RXD Ring #3. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL2_CPU_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL2_CPU_IDX_MASK \ + 0x00000FFF /* CPU_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL2_CPU_IDX_SHFT 0 + +/* +* ---WPDMA_RX_RING3_CTRL3 (0x18025000 + 0x53C)--- +* DMA_IDX[11..0] - (RW) In normal operation, user dma_index +* would udated by hardware when moving rx packet done. User should not write +dma_index. +* Point to the next RXD DMA wants to use in +* FDS Ring#3. It should be a 8-DWORD aligned address. +* RESERVED12[31..12] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL3_DMA_IDX_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL3_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL3_DMA_IDX_MASK \ + 0x00000FFF /* DMA_IDX[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_CTRL3_DMA_IDX_SHFT 0 + +/* +* ---WPDMA_TX_RING0_EXT_CTRL (0x18025000 + 0x600)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #0 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING1_EXT_CTRL (0x18025000 + 0x604)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #1 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING2_EXT_CTRL (0x18025000 + 0x608)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #2 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING3_EXT_CTRL (0x18025000 + 0x60C)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #3 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING4_EXT_CTRL (0x18025000 + 0x610)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #4 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING5_EXT_CTRL (0x18025000 + 0x614)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #5 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING6_EXT_CTRL (0x18025000 + 0x618)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #6 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING7_EXT_CTRL (0x18025000 + 0x61C)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #7 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING8_EXT_CTRL (0x18025000 + 0x620)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #0 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING9_EXT_CTRL (0x18025000 + 0x624)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #1 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING10_EXT_CTRL (0x18025000 + 0x628)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #2 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING11_EXT_CTRL (0x18025000 + 0x62C)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #3 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING12_EXT_CTRL (0x18025000 + 0x630)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #4 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING13_EXT_CTRL (0x18025000 + 0x634)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #5 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING14_EXT_CTRL (0x18025000 + 0x638)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #6 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING15_EXT_CTRL (0x18025000 + 0x63C)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #7 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING16_EXT_CTRL (0x18025000 + 0x640)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #16 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING17_EXT_CTRL (0x18025000 + 0x644)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #17 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING18_EXT_CTRL (0x18025000 + 0x648)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #18 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING19_EXT_CTRL (0x18025000 + 0x64C)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) TXD Ring #19 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING0_EXT_CTRL (0x18025000 + 0x680)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #0 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING1_EXT_CTRL (0x18025000 + 0x684)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #1 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING2_EXT_CTRL (0x18025000 + 0x688)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #2 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_RX_RING3_EXT_CTRL (0x18025000 + 0x68C)--- +* DISP_MAX_CNT[7..0] - (RW) xxx +* RESERVED8[15..8] - (RO) Reserved bits +* DISP_BASE_PTR[31..16] - (RW) RXD Ring #3 Extension, to configure +* prefetch settings, like base_ptr means each prefetch ring's base address in +* internal prefetch sram, disp_max_cnt means each prefetch ring's depth +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_EXT_CTRL_DISP_BASE_PTR_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_EXT_CTRL_DISP_BASE_PTR_MASK \ + 0xFFFF0000 /* DISP_BASE_PTR[31..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_EXT_CTRL_DISP_BASE_PTR_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_EXT_CTRL_DISP_MAX_CNT_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_EXT_CTRL_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_EXT_CTRL_DISP_MAX_CNT_MASK \ + 0x000000FF /* DISP_MAX_CNT[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_EXT_CTRL_DISP_MAX_CNT_SHFT 0 + +/* +* ---WPDMA_TX_RING0_BKRS_CTRL0 (0x18025000 + 0xA00)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING0_BKRS_CTRL1 (0x18025000 + 0xA04)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING0_BKRS_CTRL2 (0x18025000 + 0xA08)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING0_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING1_BKRS_CTRL0 (0x18025000 + 0xA10)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING1_BKRS_CTRL1 (0x18025000 + 0xA14)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING1_BKRS_CTRL2 (0x18025000 + 0xA18)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING1_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING2_BKRS_CTRL0 (0x18025000 + 0xA20)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING2_BKRS_CTRL1 (0x18025000 + 0xA24)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING2_BKRS_CTRL2 (0x18025000 + 0xA28)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING2_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING3_BKRS_CTRL0 (0x18025000 + 0xA30)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING3_BKRS_CTRL1 (0x18025000 + 0xA34)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING3_BKRS_CTRL2 (0x18025000 + 0xA38)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING3_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING4_BKRS_CTRL0 (0x18025000 + 0xA40)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING4_BKRS_CTRL1 (0x18025000 + 0xA44)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING4_BKRS_CTRL2 (0x18025000 + 0xA48)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING4_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING5_BKRS_CTRL0 (0x18025000 + 0xA50)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING5_BKRS_CTRL1 (0x18025000 + 0xA54)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING5_BKRS_CTRL2 (0x18025000 + 0xA58)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING5_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING6_BKRS_CTRL0 (0x18025000 + 0xA60)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING6_BKRS_CTRL1 (0x18025000 + 0xA64)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING6_BKRS_CTRL2 (0x18025000 + 0xA68)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING6_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING7_BKRS_CTRL0 (0x18025000 + 0xA70)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING7_BKRS_CTRL1 (0x18025000 + 0xA74)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING7_BKRS_CTRL2 (0x18025000 + 0xA78)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING7_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING8_BKRS_CTRL0 (0x18025000 + 0xA80)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING8_BKRS_CTRL1 (0x18025000 + 0xA84)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING8_BKRS_CTRL2 (0x18025000 + 0xA88)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING8_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING9_BKRS_CTRL0 (0x18025000 + 0xA90)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING9_BKRS_CTRL1 (0x18025000 + 0xA94)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING9_BKRS_CTRL2 (0x18025000 + 0xA98)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING9_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING10_BKRS_CTRL0 (0x18025000 + 0xAA0)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING10_BKRS_CTRL1 (0x18025000 + 0xAA4)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING10_BKRS_CTRL2 (0x18025000 + 0xAA8)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING10_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING11_BKRS_CTRL0 (0x18025000 + 0xAB0)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING11_BKRS_CTRL1 (0x18025000 + 0xAB4)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING11_BKRS_CTRL2 (0x18025000 + 0xAB8)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING11_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING12_BKRS_CTRL0 (0x18025000 + 0xAC0)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING12_BKRS_CTRL1 (0x18025000 + 0xAC4)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING12_BKRS_CTRL2 (0x18025000 + 0xAC8)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING12_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING13_BKRS_CTRL0 (0x18025000 + 0xAD0)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING13_BKRS_CTRL1 (0x18025000 + 0xAD4)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING13_BKRS_CTRL2 (0x18025000 + 0xAD8)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING13_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING14_BKRS_CTRL0 (0x18025000 + 0xAE0)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING14_BKRS_CTRL1 (0x18025000 + 0xAE4)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING14_BKRS_CTRL2 (0x18025000 + 0xAE8)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING14_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING15_BKRS_CTRL0 (0x18025000 + 0xAF0)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING15_BKRS_CTRL1 (0x18025000 + 0xAF4)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING15_BKRS_CTRL2 (0x18025000 + 0xAF8)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING15_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING16_BKRS_CTRL0 (0x18025000 + 0xB00)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING16_BKRS_CTRL1 (0x18025000 + 0xB04)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING16_BKRS_CTRL2 (0x18025000 + 0xB08)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING16_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING17_BKRS_CTRL0 (0x18025000 + 0xB10)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING17_BKRS_CTRL1 (0x18025000 + 0xB14)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING17_BKRS_CTRL2 (0x18025000 + 0xB18)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING17_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING18_BKRS_CTRL0 (0x18025000 + 0xB20)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING18_BKRS_CTRL1 (0x18025000 + 0xB24)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING18_BKRS_CTRL2 (0x18025000 + 0xB28)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING18_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING19_BKRS_CTRL0 (0x18025000 + 0xB30)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING19_BKRS_CTRL1 (0x18025000 + 0xB34)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_TX_RING19_BKRS_CTRL2 (0x18025000 + 0xB38)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_TX_RING19_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING0_BKRS_CTRL0 (0x18025000 + 0xC00)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING0_BKRS_CTRL1 (0x18025000 + 0xC04)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING0_BKRS_CTRL2 (0x18025000 + 0xC08)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING0_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING1_BKRS_CTRL0 (0x18025000 + 0xC10)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING1_BKRS_CTRL1 (0x18025000 + 0xC14)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING1_BKRS_CTRL2 (0x18025000 + 0xC18)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING1_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING2_BKRS_CTRL0 (0x18025000 + 0xC20)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING2_BKRS_CTRL1 (0x18025000 + 0xC24)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING2_BKRS_CTRL2 (0x18025000 + 0xC28)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING2_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING3_BKRS_CTRL0 (0x18025000 + 0xC30)--- +* pld_didx_idx[11..0] - (RO) pld_didx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pf_didx_idx[27..16] - (RO) pf_didx_idx +* RESERVED28[31..28] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL0_pf_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL0_pf_didx_idx_MASK \ + 0x0FFF0000 /* pf_didx_idx[27..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL0_pf_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL0_pld_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL0_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL0_pld_didx_idx_MASK \ + 0x00000FFF /* pld_didx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL0_pld_didx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING3_BKRS_CTRL1 (0x18025000 + 0xC34)--- +* disp_cidx_idx[7..0] - (RO) disp_cidx_idx +* RESERVED8[15..8] - (RO) Reserved bits +* disp_didx_idx[23..16] - (RO) disp_didx_idx +* RESERVED24[31..24] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL1_disp_didx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL1_disp_didx_idx_MASK \ + 0x00FF0000 /* disp_didx_idx[23..16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL1_disp_didx_idx_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL1_disp_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL1_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL1_disp_cidx_idx_MASK \ + 0x000000FF /* disp_cidx_idx[7..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL1_disp_cidx_idx_SHFT 0 + +/* +* ---WPDMA_RX_RING3_BKRS_CTRL2 (0x18025000 + 0xC38)--- +* pld_cidx_idx[11..0] - (RO) pld_cidx_idx +* RESERVED12[15..12] - (RO) Reserved bits +* pld_ring_empty[16] - (RO) pld_ring_empty +* pf_ring_empty[17] - (RO) pf_ring_empty +* pf_dq_ring_empty[18] - (RO) pf_dq_ring_empty +* disp_ring_vld[19] - (RO) disp_ring_vld +* RESERVED20[31..20] - (RO) Reserved bits +*/ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_disp_ring_vld_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_disp_ring_vld_MASK \ + 0x00080000 /* disp_ring_vld[19] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_disp_ring_vld_SHFT 19 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_pf_dq_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_pf_dq_ring_empty_MASK \ + 0x00040000 /* pf_dq_ring_empty[18] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_pf_dq_ring_empty_SHFT 18 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_pf_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_pf_ring_empty_MASK \ + 0x00020000 /* pf_ring_empty[17] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_pf_ring_empty_SHFT 17 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_pld_ring_empty_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_pld_ring_empty_MASK \ + 0x00010000 /* pld_ring_empty[16] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_pld_ring_empty_SHFT 16 +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_pld_cidx_idx_ADDR \ + WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_ADDR +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_pld_cidx_idx_MASK \ + 0x00000FFF /* pld_cidx_idx[11..0] */ +#define WF_WFDMA_HOST_DMA1_WPDMA_RX_RING3_BKRS_CTRL2_pld_cidx_idx_SHFT 0 + +#ifdef __cplusplus +} +#endif + +#endif /* __WF_WFDMA_HOST_DMA1_REGS_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/connac.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/connac.h new file mode 100644 index 0000000000000..dbbf357f49163 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/connac.h @@ -0,0 +1,133 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/ + * MT6620_WIFI_DRIVER_V2_3/include/chips/connac.h#1 + */ + +/*! \file connac.h + * \brief This file contains the info of CONNAC + */ + +#ifdef CONNAC + +#ifndef _CONNAC_H +#define _CONNAC_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" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define CONNAC_CHIP_ID (0x0001) +#define CONNAC_CHIP_ADIE_INFO (0x6631) +#define CONNAC_SW_SYNC0 CONN_CFG_ON_CONN_ON_MISC_ADDR +#define CONNAC_SW_SYNC0_RDY_OFFSET \ + CONN_CFG_ON_CONN_ON_MISC_DRV_FM_STAT_SYNC_SHFT +#define CONNAC_PATCH_START_ADDR (0x0001C000) +#define CONNAC_TOP_CFG_BASE CONN_CFG_BASE +#define CONNAC_TX_DESC_APPEND_LENGTH 32 +#if (CFG_WIFI_IP_SET == 1) +#define CONNAC_RX_DESC_LENGTH 16 +#else +#define CONNAC_RX_DESC_LENGTH 20 +#endif +#define CONNAC_INIT_EVT_RX_DESC_LENGTH 16 +#define CONNAC_RX_INIT_EVENT_LENGTH 8 +#define CONNAC_RX_EVENT_HDR_LENGTH 12 +#define MTK_CUSTOM_OID_INTERFACE_VERSION 0x00006620 /* for WPDWifi DLL */ +#define MTK_EM_INTERFACE_VERSION 0x0000 + +/******************************************************************************* + * 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 /* _CONNAC_H */ + +#endif /* CONNAC */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/connac2x2.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/connac2x2.h new file mode 100644 index 0000000000000..031c5d398b8d9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/connac2x2.h @@ -0,0 +1,128 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/ + * MT6620_WIFI_DRIVER_V2_3/include/chips/connac.h#1 + */ + +/*! \file connac.h + * \brief This file contains the info of CONNAC + */ + +#ifdef CONNAC2X2 + +#ifndef _CONNAC2X2_H +#define _CONNAC2X2_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" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define CONNAC2X2_CHIP_ID (0x0001) +#define CONNAC_CHIP_ADIE_INFO (0x6635) +#define CONNAC2X2_SW_SYNC0 CONN_CFG_ON_CONN_ON_MISC_ADDR +#define CONNAC2X2_SW_SYNC0_RDY_OFFSET \ + CONN_CFG_ON_CONN_ON_MISC_DRV_FM_STAT_SYNC_SHFT +#define CONNAC2X2_PATCH_START_ADDR (0x0001C000) +#define CONNAC2X2_TOP_CFG_BASE CONN_CFG_BASE +#define CONNAC2X2_TX_DESC_APPEND_LENGTH 32 +#define CONNAC2X2_RX_DESC_LENGTH 20 +#define CONNAC2X2_RX_INIT_EVENT_LENGTH 8 +#define CONNAC2X2_RX_EVENT_HDR_LENGTH 12 +#define MTK_CUSTOM_OID_INTERFACE_VERSION 0x00000200 /* for WPDWifi DLL */ +#define MTK_EM_INTERFACE_VERSION 0x0001 + +/******************************************************************************* + * 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 /* _CONNAC2X2_H */ + +#endif /* CONNAC2X2 */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/dma_sch.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/dma_sch.h new file mode 100644 index 0000000000000..857ffbe9b2376 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/dma_sch.h @@ -0,0 +1,199 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + dma_sch.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ------------------------------------- +*/ + + +#ifndef __DMA_SCH_H__ +#define __DMA_SCH_H__ + +#define DMASHDL_BASE 0x5000a000 + +#define MT_HIF_DMASHDL_PKT_MAX_SIZE (DMASHDL_BASE + 0x1c) + +#define PLE_PKT_MAX_SIZE_MASK (0xfff << 0) +#define PLE_PKT_MAX_SIZE_NUM(p) (((p) & 0xfff) << 0) +#define GET_PLE_PKT_MAX_SIZE_NUM(p) (((p) & PLE_PKT_MAX_SIZE_MASK) >> 0) + +#define PSE_PKT_MAX_SIZE_MASK (0xfff << 16) +#define PSE_PKT_MAX_SIZE_NUM(p) (((p) & 0xfff) << 16) +#define GET_PSE_PKT_MAX_SIZE_NUM(p) (((p) & PSE_PKT_MAX_SIZE_MASK) >> 16) +#define MT_HIF_DMASHDL_OPTION_CTRL (DMASHDL_BASE + 0x08) +#define MT_HIF_DMASHDL_REFILL_CTRL (DMASHDL_BASE + 0x10) +#define MT_HIF_DMASHDL_GROUP0_CTRL (DMASHDL_BASE + 0x20) +#define MT_HIF_DMASHDL_GROUP1_CTRL (DMASHDL_BASE + 0x24) +#define MT_HIF_DMASHDL_GROUP2_CTRL (DMASHDL_BASE + 0x28) +#define MT_HIF_DMASHDL_GROUP3_CTRL (DMASHDL_BASE + 0x2c) +#define MT_HIF_DMASHDL_GROUP4_CTRL (DMASHDL_BASE + 0x30) +#define MT_HIF_DMASHDL_GROUP5_CTRL (DMASHDL_BASE + 0x34) +#define MT_HIF_DMASHDL_GROUP6_CTRL (DMASHDL_BASE + 0x38) +#define MT_HIF_DMASHDL_GROUP7_CTRL (DMASHDL_BASE + 0x3c) +#define MT_HIF_DMASHDL_GROUP8_CTRL (DMASHDL_BASE + 0x40) +#define MT_HIF_DMASHDL_GROUP9_CTRL (DMASHDL_BASE + 0x44) +#define MT_HIF_DMASHDL_GROUP10_CTRL (DMASHDL_BASE + 0x48) +#define MT_HIF_DMASHDL_GROUP11_CTRL (DMASHDL_BASE + 0x4c) +#define MT_HIF_DMASHDL_GROUP12_CTRL (DMASHDL_BASE + 0x50) +#define MT_HIF_DMASHDL_GROUP13_CTRL (DMASHDL_BASE + 0x54) +#define MT_HIF_DMASHDL_GROUP14_CTRL (DMASHDL_BASE + 0x58) +#define MT_HIF_DMASHDL_GROUP15_CTRL (DMASHDL_BASE + 0x5c) + +#define MT_HIF_DMASHDL_SHDL_SET0 (DMASHDL_BASE + 0xb0) +#define MT_HIF_DMASHDL_SHDL_SET1 (DMASHDL_BASE + 0xb4) + + +#define MT_HIF_DMASHDL_SLOT_SET0 (DMASHDL_BASE + 0xc4) +#define MT_HIF_DMASHDL_SLOT_SET1 (DMASHDL_BASE + 0xc8) + + +#define MT_HIF_DMASHDL_Q_MAP0 (DMASHDL_BASE + 0xd0) +#define MT_HIF_DMASHDL_Q_MAP1 (DMASHDL_BASE + 0xd4) +#define MT_HIF_DMASHDL_Q_MAP2 (DMASHDL_BASE + 0xd8) +#define MT_HIF_DMASHDL_Q_MAP3 (DMASHDL_BASE + 0xdc) + +#define MT_HIF_DMASHDL_PAGE_SET (DMASHDL_BASE + 0x0c) + +/* User program group sequence type control */ +/* 0: user program group sequence order type, + * 1: pre define each slot group strict order + */ +#define DMASHDL_GROUP_SEQ_ORDER_TYPE BIT(16) + + +#define MT_HIF_DMASHDL_CTRL_SIGNAL (DMASHDL_BASE + 0x18) +/* enable to clear the flag of PLE TXD size greater than ple max. size */ +#define DMASHDL_PLE_TXD_GT_MAX_SIZE_FLAG_CLR BIT(0) +/* enable packet in substration action from HIF ask period */ +#define DMASHDL_HIF_ASK_SUB_ENA BIT(16) +/* enable packet in substration action from PLE */ +#define DMASHDL_PLE_SUB_ENA BIT(17) +/* enable terminate refill period when PLE release packet to do addition */ +#define DMASHDL_PLE_ADD_INT_REFILL_ENA BIT(29) +/* enable terminate refill period when packet in to do addition */ +#define DMASHDL_PDMA_ADD_INT_REFILL_ENA BIT(30) +/* enable terminate refill period when packet in to do substration */ +#define DMASHDL_PKTIN_INT_REFILL_ENA BIT(31) + +#define MT_HIF_DMASHDL_ERROR_FLAG_CTRL (DMASHDL_BASE + 0x9c) + +#define MT_HIF_DMASHDL_STATUS_RD (DMASHDL_BASE + 0x100) +#define MT_HIF_DMASHDL_STATUS_RD_GP0 (DMASHDL_BASE + 0x140) +#define MT_HIF_DMASHDL_STATUS_RD_GP1 (DMASHDL_BASE + 0x144) +#define MT_HIF_DMASHDL_STATUS_RD_GP2 (DMASHDL_BASE + 0x148) +#define MT_HIF_DMASHDL_STATUS_RD_GP3 (DMASHDL_BASE + 0x14c) +#define MT_HIF_DMASHDL_STATUS_RD_GP4 (DMASHDL_BASE + 0x150) +#define MT_HIF_DMASHDL_STATUS_RD_GP5 (DMASHDL_BASE + 0x154) +#define MT_HIF_DMASHDL_STATUS_RD_GP6 (DMASHDL_BASE + 0x158) +#define MT_HIF_DMASHDL_STATUS_RD_GP7 (DMASHDL_BASE + 0x15c) +#define MT_HIF_DMASHDL_STATUS_RD_GP8 (DMASHDL_BASE + 0x160) +#define MT_HIF_DMASHDL_STATUS_RD_GP9 (DMASHDL_BASE + 0x164) +#define MT_HIF_DMASHDL_STATUS_RD_GP10 (DMASHDL_BASE + 0x168) +#define MT_HIF_DMASHDL_STATUS_RD_GP11 (DMASHDL_BASE + 0x16c) +#define MT_HIF_DMASHDL_STATUS_RD_GP12 (DMASHDL_BASE + 0x170) +#define MT_HIF_DMASHDL_STATUS_RD_GP13 (DMASHDL_BASE + 0x174) +#define MT_HIF_DMASHDL_STATUS_RD_GP14 (DMASHDL_BASE + 0x178) +#define MT_HIF_DMASHDL_STATUS_RD_GP15 (DMASHDL_BASE + 0x17c) +#define MT_HIF_DMASHDLRD_GP_PKT_CNT_0 (DMASHDL_BASE + 0x180) +#define MT_HIF_DMASHDLRD_GP_PKT_CNT_1 (DMASHDL_BASE + 0x184) +#define MT_HIF_DMASHDLRD_GP_PKT_CNT_2 (DMASHDL_BASE + 0x188) +#define MT_HIF_DMASHDLRD_GP_PKT_CNT_3 (DMASHDL_BASE + 0x18c) +#define MT_HIF_DMASHDLRD_GP_PKT_CNT_4 (DMASHDL_BASE + 0x190) +#define MT_HIF_DMASHDLRD_GP_PKT_CNT_5 (DMASHDL_BASE + 0x194) +#define MT_HIF_DMASHDLRD_GP_PKT_CNT_6 (DMASHDL_BASE + 0x198) +#define MT_HIF_DMASHDLRD_GP_PKT_CNT_7 (DMASHDL_BASE + 0x19c) + +#define DMASHDL_RSV_CNT_MASK (0xfff << 16) +#define DMASHDL_SRC_CNT_MASK (0xfff << 0) +#define DMASHDL_RSV_CNT_OFFSET 16 +#define DMASHDL_SRC_CNT_OFFSET 0 +#define DMASHDL_FREE_PG_CNT_MASK (0xfff << 16) +#define DMASHDL_FFA_CNT_MASK (0xfff << 0) +#define DMASHDL_FREE_PG_CNT_OFFSET 16 +#define DMASHDL_FFA_CNT_OFFSET 0 +#define DMASHDL_MAX_QUOTA_MASK (0xfff << 16) +#define DMASHDL_MIN_QUOTA_MASK (0xfff << 0) +#define DMASHDL_MAX_QUOTA_OFFSET 16 +#define DMASHDL_MIN_QUOTA_OFFSET 0 + +#define DMASHDL_MIN_QUOTA_NUM(p) (((p) & 0xfff) << DMASHDL_MIN_QUOTA_OFFSET) +#define GET_DMASHDL_MIN_QUOTA_NUM(p)\ + (((p) & DMASHDL_MIN_QUOTA_MASK) >> DMASHDL_MIN_QUOTA_OFFSET) + +#define DMASHDL_MAX_QUOTA_NUM(p) (((p) & 0xfff) << DMASHDL_MAX_QUOTA_OFFSET) +#define GET_DMASHDL_MAX_QUOTA_NUM(p)\ + (((p) & DMASHDL_MAX_QUOTA_MASK) >> DMASHDL_MAX_QUOTA_OFFSET) + + +#define ODD_GROUP_ASK_CN_MASK (0xff << 16) +#define ODD_GROUP_ASK_CN_OFFSET 16 +#define GET_ODD_GROUP_ASK_CNT(p)\ + (((p) & ODD_GROUP_ASK_CN_MASK) >> ODD_GROUP_ASK_CN_OFFSET) +#define ODD_GROUP_PKT_IN_CN_MASK (0xff << 24) +#define ODD_GROUP_PKT_IN_CN_OFFSET 24 +#define GET_ODD_GROUP_PKT_IN_CNT(p)\ + (((p) & ODD_GROUP_PKT_IN_CN_MASK) >> ODD_GROUP_PKT_IN_CN_OFFSET) +#define EVEN_GROUP_ASK_CN_MASK (0xff << 0) +#define EVEN_GROUP_ASK_CN_OFFSET 0 +#define GET_EVEN_GROUP_ASK_CNT(p)\ + (((p) & EVEN_GROUP_ASK_CN_MASK) >> EVEN_GROUP_ASK_CN_OFFSET) +#define EVEN_GROUP_PKT_IN_CN_MASK (0xff << 8) +#define EVEN_GROUP_PKT_IN_CN_OFFSET 8 +#define GET_EVEN_GROUP_PKT_IN_CNT(p)\ + (((p) & EVEN_GROUP_PKT_IN_CN_MASK) >> EVEN_GROUP_PKT_IN_CN_OFFSET) +#if defined(P18) || defined(MT7663) || defined(AXE) +#define HIF_DMASHDL_IO_READ32(_A, _R, _pV)\ + HW_IO_READ32(_A->hdev_ctrl, (0x6000+((uint32_t)_R&0xfff)), _pV) +#define HIF_DMASHDL_IO_WRITE32(_A, _R, _pV)\ + HW_IO_WRITE32(_A->hdev_ctrl, (0x6000+((uint32_t)_R&0xfff)), _pV) +#else +#define HIF_DMASHDL_IO_READ32(_A, _R, _pV)\ + do {\ + uint32_t restore_remap_addr;\ + HW_IO_READ32(_A->hdev_ctrl, 0x2504, &restore_remap_addr);\ + \ + HW_IO_WRITE32(_A->hdev_ctrl, 0x2504, DMASHDL_BASE);\ + HW_IO_READ32(_A->hdev_ctrl,\ + (0x80000+((uint32_t)_R&0xffff)), _pV);\ + \ + HW_IO_WRITE32(_A->hdev_ctrl, 0x2504, restore_remap_addr);\ + } while (0) + +#define HIF_DMASHDL_IO_WRITE32(_A, _R, _pV) \ + do {\ + uint32_t restore_remap_addr;\ + \ + HW_IO_READ32(_A->hdev_ctrl, 0x2504, &restore_remap_addr);\ + \ + HW_IO_WRITE32(_A->hdev_ctrl, 0x2504, DMASHDL_BASE);\ + HW_IO_WRITE32(_A->hdev_ctrl,\ + (0x80000+((uint32_t)_R&0xffff)), _pV);\ + \ + HW_IO_WRITE32(_A->hdev_ctrl, 0x2504, restore_remap_addr);\ + } while (0) +#endif + + +#endif /* __DMA_SCH_H__ */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/fw_dl.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/fw_dl.h new file mode 100644 index 0000000000000..f0a0ae2584725 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/fw_dl.h @@ -0,0 +1,413 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file fw_dl.h + */ + +#ifndef _FW_DL_H +#define _FW_DL_H + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/* PDA - Patch Decryption Accelerator */ +#define PDA_N9 0 +#define PDA_CR4 1 + +#define MAX_FWDL_SECTION_NUM 10 +#define N9_FWDL_SECTION_NUM 2 +#define CR4_FWDL_SECTION_NUM HIF_CR4_FWDL_SECTION_NUM +#define IMG_DL_STATUS_PORT_IDX HIF_IMG_DL_STATUS_PORT_IDX + +#define DOWNLOAD_CONFIG_ENCRYPTION_MODE BIT(0) +#define DOWNLOAD_CONFIG_KEY_INDEX_MASK BITS(1, 2) +#define DOWNLOAD_CONFIG_RESET_OPTION BIT(3) +#define DOWNLOAD_CONFIG_WORKING_PDA_OPTION BIT(4) +#define DOWNLOAD_CONFIG_VALID_RAM_ENTRY BIT(5) +#define DOWNLOAD_CONFIG_ENCRY_MODE_SEL BIT(6) /* 0 - AES, 1 - SCRAMBLE */ +#define DOWNLOAD_CONFIG_EMI BIT(7) +#define DOWNLOAD_CONFIG_ACK_OPTION BIT(31) + +/* + * FW feature set + * bit(0) : encrypt or not. + * bit(1,2): encrypt key index. + * bit(3) : compressed image or not. (added in CONNAC) + * bit(4) : encrypt mode, 1 for scramble, 0 for AES. + * bit(5) : replace RAM code starting address with image + * destination address or not. (added in CONNAC) + * bit(7) : download to EMI or not. (added in CONNAC) + */ +#define FW_FEATURE_SET_ENCRY BIT(0) +#define FW_FEATURE_SET_KEY_MASK BITS(1, 2) +#define GET_FW_FEATURE_SET_KEY(p) (((p) & FW_FEATURE_SET_KEY_MASK) >> 1) +#define FW_FEATURE_COMPRESS_IMG BIT(3) +#define FW_FEATURE_ENCRY_MODE BIT(4) +#define FW_FEATURE_OVERRIDE_RAM_ADDR BIT(5) +#define FW_FEATURE_NOT_DOWNLOAD BIT(6) +#define FW_FEATURE_DL_TO_EMI BIT(7) + +#if CFG_SUPPORT_COMPRESSION_FW_OPTION +#define COMPRESSION_OPTION_OFFSET 4 +#define COMPRESSION_OPTION_MASK BIT(4) +#endif + +#define RELEASE_INFO_SEPARATOR_LEN 16 + +#if CFG_MTK_ANDROID_EMI +#define WIFI_EMI_ADDR_MASK 0xFFFFFF +extern phys_addr_t gConEmiPhyBase; +extern unsigned long long gConEmiSize; +#endif + +/* + * patch format: + * PATCH_FORMAT_V1 support 7636, 7637, 7615, 7622, CONNAC (p18, 7663) + * PATCH_FORMAT_V2 support CONNANC2.0 (7915) + */ +/* Magic number, means use this multi-address patch header format*/ +#define PATCH_VERSION_MAGIC_NUM 0xffffffff +#define PATCH_SEC_TYPE_MASK 0x0000ffff +#define PATCH_SEC_TYPE_BIN_INFO 0x2 + +enum ENUM_IMG_DL_IDX_T { + IMG_DL_IDX_N9_FW, + IMG_DL_IDX_CR4_FW, + IMG_DL_IDX_PATCH, + IMG_DL_IDX_MCU_ROM_EMI, + IMG_DL_IDX_WIFI_ROM_EMI +}; + +struct FWDL_OPS_T { + /* load firmware bin priority */ + void (*constructFirmwarePrio)(struct GLUE_INFO *prGlueInfo, + uint8_t **apucNameTable, uint8_t **apucName, + uint8_t *pucNameIdx, uint8_t ucMaxNameIdx); + void (*constructPatchName)(struct GLUE_INFO *prGlueInfo, + uint8_t **apucName, uint8_t *pucNameIdx); + + uint32_t (*downloadPatch)(IN struct ADAPTER *prAdapter); + uint32_t (*downloadFirmware)(IN struct ADAPTER *prAdapter, + IN enum ENUM_IMG_DL_IDX_T eDlIdx); + uint32_t (*downloadByDynMemMap)( + IN struct ADAPTER *prAdapter, IN uint32_t u4Addr, + IN uint32_t u4Len, IN uint8_t *pucStartPtr, + IN enum ENUM_IMG_DL_IDX_T eDlIdx); + void (*getFwInfo)(IN struct ADAPTER *prAdapter, + IN uint8_t u4SecIdx, IN enum ENUM_IMG_DL_IDX_T eDlIdx, + OUT uint32_t *pu4Addr, OUT uint32_t *pu4Len, + OUT uint32_t *pu4DataMode, OUT u_int8_t *pfgIsEMIDownload, + OUT u_int8_t *pfgIsNotDownload); + unsigned int (*getFwDlInfo)(struct ADAPTER *prAdapter, + char *pcBuf, int i4TotalLen); + uint32_t (*phyAction)(IN struct ADAPTER *prAdapter); +}; + +#if (CFG_UMAC_GENERATION >= 0x20) +#define LEN_4_BYTE_CRC (4) + +struct TAILER_COMMON_FORMAT_T { + uint8_t ucChipInfo; + uint8_t ucEcoCode; + uint8_t ucRegionNum; + uint8_t ucFormatVer; + uint8_t ucFormatFlag; + uint8_t aucReserved[2]; + uint8_t aucRamVersion[10]; + uint8_t aucRamBuiltDate[15]; + uint32_t u4CRC; +}; + +struct TAILER_REGION_FORMAT_T { + uint32_t u4CRC; + uint32_t u4RealSize; + uint32_t u4BlockSize; + uint8_t aucReserved1[4]; + uint32_t u4Addr; + uint32_t u4Len; + uint8_t ucFeatureSet; + uint8_t aucReserved2[15]; +}; + +struct TAILER_FORMAT_T { + uint32_t addr; + uint8_t chip_info; + uint8_t feature_set; + uint8_t eco_code; + uint8_t ram_version[10]; + uint8_t ram_built_date[15]; + uint32_t len; +}; + +struct HEADER_RELEASE_INFO { + uint16_t u2Len; + uint8_t ucPaddingLen; + uint8_t ucTag; +}; + +#if CFG_SUPPORT_COMPRESSION_FW_OPTION +struct TAILER_FORMAT_T_2 { + uint32_t crc; + uint32_t addr; + uint32_t block_size; + uint32_t real_size; + uint8_t chip_info; + uint8_t feature_set; + uint8_t eco_code; + uint8_t ram_version[10]; + uint8_t ram_built_date[15]; + uint32_t len; +}; + +struct FW_IMAGE_TAILER_T_2 { + struct TAILER_FORMAT_T_2 ilm_info; + struct TAILER_FORMAT_T_2 dlm_info; +}; + +struct FW_IMAGE_TAILER_CHECK { + uint8_t chip_info; + uint8_t feature_set; + uint8_t eco_code; + uint8_t ram_version[10]; + uint8_t ram_built_date[15]; + uint32_t len; +}; +#endif + +struct PATCH_FORMAT_T { + uint8_t aucBuildDate[16]; + uint8_t aucPlatform[4]; + uint32_t u4SwHwVersion; + uint32_t u4PatchVersion; + uint16_t u2CRC; /* CRC calculated for image only */ + uint8_t ucPatchImage[0]; +}; + +struct PATCH_FORMAT_V2_T { + uint8_t aucBuildDate[16]; + uint8_t aucPlatform[4]; + uint32_t u4SwHwVersion; + uint32_t u4PatchVersion; + uint16_t u2Reserved; + uint16_t u2CRC; /* CRC calculated for image only */ +}; + +/* multi-addr patch format */ +struct PATCH_GLO_DESC { + uint32_t patch_ver; + uint32_t subsys; + uint32_t feature; + uint32_t section_num; + uint32_t crc; + uint32_t reserved[11]; +}; + +struct PATCH_SEC_MAP { + uint32_t section_type; + uint32_t section_offset; + uint32_t section_size; + union { + uint32_t section_spec[13]; + struct { + uint32_t dl_addr; + uint32_t dl_size; + uint32_t sec_key_idx; + uint32_t align_len; + uint32_t reserved[9]; + } bin_info_spec; + }; +}; + +struct patch_dl_buf { + uint8_t *img_ptr; + uint32_t img_dest_addr; + uint32_t img_size; + bool check_crc; +}; + +struct patch_dl_target { + struct patch_dl_buf *patch_region; + uint8_t num_of_region; +}; + +#endif + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +#if CFG_ENABLE_FW_DOWNLOAD +uint32_t wlanGetDataMode(IN struct ADAPTER *prAdapter, + IN enum ENUM_IMG_DL_IDX_T eDlIdx, IN uint8_t ucFeatureSet); + +void wlanGetHarvardFwInfo(IN struct ADAPTER *prAdapter, + IN uint8_t u4SecIdx, IN enum ENUM_IMG_DL_IDX_T eDlIdx, + OUT uint32_t *pu4Addr, OUT uint32_t *pu4Len, + OUT uint32_t *pu4DataMode, OUT u_int8_t *pfgIsEMIDownload, + OUT u_int8_t *pfgIsNotDownload); + +void wlanGetConnacFwInfo(IN struct ADAPTER *prAdapter, + IN uint8_t u4SecIdx, IN enum ENUM_IMG_DL_IDX_T eDlIdx, + OUT uint32_t *pu4Addr, OUT uint32_t *pu4Len, + OUT uint32_t *pu4DataMode, OUT u_int8_t *pfgIsEMIDownload, + OUT u_int8_t *pfgIsNotDownload); + +void wlanImageSectionGetPatchInfoV2(IN struct ADAPTER + *prAdapter, + IN void *pvFwImageMapFile, IN uint32_t u4FwImageFileLength, + OUT uint32_t *pu4DataMode, + struct patch_dl_target *target); + +void wlanImageSectionGetPatchInfo(IN struct ADAPTER + *prAdapter, + IN void *pvFwImageMapFile, IN uint32_t u4FwImageFileLength, + OUT uint32_t *pu4StartOffset, OUT uint32_t *pu4Addr, + OUT uint32_t *pu4Len, + OUT uint32_t *pu4DataMode); + +#if CFG_SUPPORT_COMPRESSION_FW_OPTION +uint32_t wlanCompressedImageSectionDownloadStage(IN struct ADAPTER *prAdapter, + IN void *pvFwImageMapFile, IN uint32_t u4FwImageFileLength, + uint8_t ucSectionNumber, IN enum ENUM_IMG_DL_IDX_T eDlIdx, + OUT uint8_t *ucIsCompressed, + OUT struct INIT_CMD_WIFI_DECOMPRESSION_START *prFwImageInFo); +#endif +uint32_t wlanImageSectionDownloadStage(IN struct ADAPTER *prAdapter, + IN void *pvFwImageMapFile, + IN uint32_t u4FwImageFileLength, IN uint8_t ucSectionNumber, + IN enum ENUM_IMG_DL_IDX_T eDlIdx, + OUT u_int8_t *pfgIsDynamicMemMap); + +uint32_t wlanPatchSendComplete(IN struct ADAPTER *prAdapter); + +#if (CFG_DOWNLOAD_DYN_MEMORY_MAP == 1) +uint32_t wlanPatchDynMemMapSendComplete(IN struct ADAPTER *prAdapter); + +uint32_t wlanRamCodeDynMemMapSendComplete(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnable, IN uint32_t u4StartAddress, + IN uint8_t ucPDA); +#endif + +uint32_t wlanDownloadSection(IN struct ADAPTER *prAdapter, + IN uint32_t u4Addr, IN uint32_t u4Len, + IN uint32_t u4DataMode, IN uint8_t *pucStartPtr, + IN enum ENUM_IMG_DL_IDX_T eDlIdx); + +uint32_t wlanDownloadSectionV2(IN struct ADAPTER *prAdapter, + IN uint32_t u4DataMode, + IN enum ENUM_IMG_DL_IDX_T eDlIdx, + struct patch_dl_target *target); + +uint32_t wlanDownloadEMISection(IN struct ADAPTER *prAdapter, + IN uint32_t u4DestAddr, + IN uint32_t u4Len, IN uint8_t *pucStartPtr); + +uint32_t wlanGetHarvardTailerInfo(IN struct ADAPTER *prAdapter, + IN void *prFwBuffer, IN uint32_t u4FwSize, + IN uint32_t ucTotSecNum, IN enum ENUM_IMG_DL_IDX_T eDlIdx); + +uint32_t wlanGetConnacTailerInfo(IN struct ADAPTER *prAdapter, + IN void *prFwBuffer, + IN uint32_t u4FwSize, IN enum ENUM_IMG_DL_IDX_T eDlIdx); + +uint32_t wlanImageSectionConfig(IN struct ADAPTER *prAdapter, + IN uint32_t u4DestAddr, IN uint32_t u4ImgSecSize, + IN uint32_t u4DataMode, + IN enum ENUM_IMG_DL_IDX_T eDlIdx); + +uint32_t wlanImageSectionDownload(IN struct ADAPTER *prAdapter, + IN uint32_t u4ImgSecSize, IN uint8_t *pucImgSecBuf); + +uint32_t wlanImageQueryStatus(IN struct ADAPTER *prAdapter); + +uint32_t wlanConfigWifiFuncStatus(IN struct ADAPTER *prAdapter, + IN uint8_t ucCmdSeqNum); + +uint32_t wlanConfigWifiFunc(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnable, IN uint32_t u4StartAddress, + IN uint8_t ucPDA); + +uint32_t wlanCRC32(uint8_t *buf, uint32_t len); + +uint32_t wlanDownloadCR4FW(IN struct ADAPTER *prAdapter, + void *prFwBuffer); + +uint32_t wlanDownloadFW(IN struct ADAPTER *prAdapter); + +uint32_t wlanDownloadPatch(IN struct ADAPTER *prAdapter); + +uint32_t wlanHarvardFormatDownload(IN struct ADAPTER *prAdapter, + IN enum ENUM_IMG_DL_IDX_T eDlIdx); + +uint32_t wlanConnacFormatDownload(IN struct ADAPTER *prAdapter, + IN enum ENUM_IMG_DL_IDX_T eDlIdx); + +uint32_t wlanGetPatchInfo(IN struct ADAPTER *prAdapter); + +uint32_t fwDlGetFwdlInfo(struct ADAPTER *prAdapter, + char *pcBuf, int i4TotalLen); + +void fwDlGetReleaseInfoSection(struct ADAPTER *prAdapter, uint8_t *pucStartPtr); +void fwDlGetReleaseManifest(struct ADAPTER *prAdapter, + struct HEADER_RELEASE_INFO *prRelInfo, + uint8_t *pucStartPtr); + +#endif + +#if (CFG_SUPPORT_CONNINFRA == 1) +extern void conninfra_get_phy_addr(unsigned int *addr, unsigned int *size); +#endif + +#endif /* _FW_DL_H */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/hal_dmashdl_mt7961.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/hal_dmashdl_mt7961.h new file mode 100644 index 0000000000000..389f9e9bc7efe --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/hal_dmashdl_mt7961.h @@ -0,0 +1,376 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2019 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2019 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file hal_dmashdl_mt7961.h +* \brief DMASHDL HAL API for MT7961 +* +* This file contains all routines which are exported + from MediaTek 802.11 Wireless LAN driver stack to GLUE Layer. +*/ + +#ifndef _HAL_DMASHDL_MT7961_H +#define _HAL_DMASHDL_MT7961_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 +******************************************************************************** +*/ +/* align MT7663 setting first */ +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + +/* 1: 3rd arbitration makes decision based on group priority in current slot. + * 0: 3rd arbitration makes decision based on fixed user-defined priority. + */ +#define MT7961_DMASHDL_SLOT_ARBITER_EN (0) +#define MT7961_DMASHDL_PKT_PLE_MAX_PAGE (0x1) +/* Buzzard CMD packet flow control is controlled by WFDMA, not DMASHDL. + * So, CMD packet (group 15) related CRs in DMASHDL are ignored. + */ +#define MT7961_DMASHDL_PKT_PSE_MAX_PAGE (0x0) +#define MT7961_DMASHDL_GROUP_0_REFILL_EN (1) +#define MT7961_DMASHDL_GROUP_1_REFILL_EN (0) +#define MT7961_DMASHDL_GROUP_2_REFILL_EN (0) +#define MT7961_DMASHDL_GROUP_3_REFILL_EN (0) +#define MT7961_DMASHDL_GROUP_4_REFILL_EN (0) +#define MT7961_DMASHDL_GROUP_5_REFILL_EN (0) +#define MT7961_DMASHDL_GROUP_6_REFILL_EN (0) +#define MT7961_DMASHDL_GROUP_7_REFILL_EN (0) +#define MT7961_DMASHDL_GROUP_8_REFILL_EN (0) +#define MT7961_DMASHDL_GROUP_9_REFILL_EN (0) +#define MT7961_DMASHDL_GROUP_10_REFILL_EN (0) +#define MT7961_DMASHDL_GROUP_11_REFILL_EN (0) +#define MT7961_DMASHDL_GROUP_12_REFILL_EN (0) +#define MT7961_DMASHDL_GROUP_13_REFILL_EN (0) +#define MT7961_DMASHDL_GROUP_14_REFILL_EN (0) +#define MT7961_DMASHDL_GROUP_15_REFILL_EN (0) +#define MT7961_DMASHDL_GROUP_0_MAX_QUOTA (0xFFF) +#define MT7961_DMASHDL_GROUP_1_MAX_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_2_MAX_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_3_MAX_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_4_MAX_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_5_MAX_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_6_MAX_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_7_MAX_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_8_MAX_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_9_MAX_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_10_MAX_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_11_MAX_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_12_MAX_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_13_MAX_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_14_MAX_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_15_MAX_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_0_MIN_QUOTA (0x3) +#define MT7961_DMASHDL_GROUP_1_MIN_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_2_MIN_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_3_MIN_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_4_MIN_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_5_MIN_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_6_MIN_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_7_MIN_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_8_MIN_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_9_MIN_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_10_MIN_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_11_MIN_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_12_MIN_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_13_MIN_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_14_MIN_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_15_MIN_QUOTA (0x0) +#define MT7961_DMASHDL_QUEUE_0_TO_GROUP (0x0) /* LMAC AC00 */ +#define MT7961_DMASHDL_QUEUE_1_TO_GROUP (0x0) /* LMAC AC01 */ +#define MT7961_DMASHDL_QUEUE_2_TO_GROUP (0x0) /* LMAC AC02 */ +#define MT7961_DMASHDL_QUEUE_3_TO_GROUP (0x0) /* LMAC AC03 */ +#define MT7961_DMASHDL_QUEUE_4_TO_GROUP (0x0) /* LMAC AC10 */ +#define MT7961_DMASHDL_QUEUE_5_TO_GROUP (0x0) /* LMAC AC11 */ +#define MT7961_DMASHDL_QUEUE_6_TO_GROUP (0x0) /* LMAC AC12 */ +#define MT7961_DMASHDL_QUEUE_7_TO_GROUP (0x0) /* LMAC AC13 */ +#define MT7961_DMASHDL_QUEUE_8_TO_GROUP (0x0) /* LMAC AC20 */ +#define MT7961_DMASHDL_QUEUE_9_TO_GROUP (0x0) /* LMAC AC21 */ +#define MT7961_DMASHDL_QUEUE_10_TO_GROUP (0x0) /* LMAC AC22 */ +#define MT7961_DMASHDL_QUEUE_11_TO_GROUP (0x0) /* LMAC AC23 */ +#define MT7961_DMASHDL_QUEUE_12_TO_GROUP (0x0) /* LMAC AC30 */ +#define MT7961_DMASHDL_QUEUE_13_TO_GROUP (0x0) /* LMAC AC31 */ +#define MT7961_DMASHDL_QUEUE_14_TO_GROUP (0x0) /* LMAC AC32 */ +#define MT7961_DMASHDL_QUEUE_15_TO_GROUP (0x0) /* LMAC AC33 */ +#define MT7961_DMASHDL_QUEUE_16_TO_GROUP (0x0) /* ALTX */ +#define MT7961_DMASHDL_QUEUE_17_TO_GROUP (0x0) /* BMC */ +#define MT7961_DMASHDL_QUEUE_18_TO_GROUP (0x0) /* BCN */ +#define MT7961_DMASHDL_QUEUE_19_TO_GROUP (0x1) /* HW Reserved */ +#define MT7961_DMASHDL_QUEUE_20_TO_GROUP (0x1) /* HW Reserved */ +#define MT7961_DMASHDL_QUEUE_21_TO_GROUP (0x1) /* HW Reserved */ +#define MT7961_DMASHDL_QUEUE_22_TO_GROUP (0x1) /* HW Reserved */ +#define MT7961_DMASHDL_QUEUE_23_TO_GROUP (0x1) /* HW Reserved */ +#define MT7961_DMASHDL_QUEUE_24_TO_GROUP (0x0) /* NAF */ +#define MT7961_DMASHDL_QUEUE_25_TO_GROUP (0x0) /* NBCN */ +#define MT7961_DMASHDL_QUEUE_26_TO_GROUP (0x0) /* FIXFID */ +#define MT7961_DMASHDL_QUEUE_27_TO_GROUP (0x1) /* Reserved */ +#define MT7961_DMASHDL_QUEUE_28_TO_GROUP (0x1) /* Reserved */ +#define MT7961_DMASHDL_QUEUE_29_TO_GROUP (0x1) /* Reserved */ +#define MT7961_DMASHDL_QUEUE_30_TO_GROUP (0x1) /* Reserved */ +#define MT7961_DMASHDL_QUEUE_31_TO_GROUP (0x1) /* Reserved */ +#define MT7961_DMASHDL_PRIORITY0_GROUP (0x0) +#define MT7961_DMASHDL_PRIORITY1_GROUP (0x1) +#define MT7961_DMASHDL_PRIORITY2_GROUP (0x2) +#define MT7961_DMASHDL_PRIORITY3_GROUP (0x3) +#define MT7961_DMASHDL_PRIORITY4_GROUP (0x4) +#define MT7961_DMASHDL_PRIORITY5_GROUP (0x5) +#define MT7961_DMASHDL_PRIORITY6_GROUP (0x6) +#define MT7961_DMASHDL_PRIORITY7_GROUP (0x7) +#define MT7961_DMASHDL_PRIORITY8_GROUP (0x8) +#define MT7961_DMASHDL_PRIORITY9_GROUP (0x9) +#define MT7961_DMASHDL_PRIORITY10_GROUP (0xA) +#define MT7961_DMASHDL_PRIORITY11_GROUP (0xB) +#define MT7961_DMASHDL_PRIORITY12_GROUP (0xC) +#define MT7961_DMASHDL_PRIORITY13_GROUP (0xD) +#define MT7961_DMASHDL_PRIORITY14_GROUP (0xE) +#define MT7961_DMASHDL_PRIORITY15_GROUP (0xF) + +#elif defined(_HIF_USB) + +/* 1: 3rd arbitration makes decision based on group priority in current slot. + * 0: 3rd arbitration makes decision based on fixed user-defined priority. + */ +#define MT7961_DMASHDL_SLOT_ARBITER_EN (0) +#define MT7961_DMASHDL_PKT_PLE_MAX_PAGE (0x1) +/* Buzzard CMD packet flow control is controlled by WFDMA, not DMASHDL. + * So, CMD packet (group 15) related CRs in DMASHDL are ignored. + */ +#define MT7961_DMASHDL_PKT_PSE_MAX_PAGE (0x0) +#define MT7961_DMASHDL_GROUP_0_REFILL_EN (1) +#define MT7961_DMASHDL_GROUP_1_REFILL_EN (1) +#define MT7961_DMASHDL_GROUP_2_REFILL_EN (1) +#define MT7961_DMASHDL_GROUP_3_REFILL_EN (1) +#define MT7961_DMASHDL_GROUP_4_REFILL_EN (1) +#define MT7961_DMASHDL_GROUP_5_REFILL_EN (0) +#define MT7961_DMASHDL_GROUP_6_REFILL_EN (0) +#define MT7961_DMASHDL_GROUP_7_REFILL_EN (0) +#define MT7961_DMASHDL_GROUP_8_REFILL_EN (0) +#define MT7961_DMASHDL_GROUP_9_REFILL_EN (0) +#define MT7961_DMASHDL_GROUP_10_REFILL_EN (0) +#define MT7961_DMASHDL_GROUP_11_REFILL_EN (0) +#define MT7961_DMASHDL_GROUP_12_REFILL_EN (0) +#define MT7961_DMASHDL_GROUP_13_REFILL_EN (0) +#define MT7961_DMASHDL_GROUP_14_REFILL_EN (0) +#define MT7961_DMASHDL_GROUP_15_REFILL_EN (0) +#define MT7961_DMASHDL_GROUP_0_MAX_QUOTA (0xFFF) +#define MT7961_DMASHDL_GROUP_1_MAX_QUOTA (0xFFF) +#define MT7961_DMASHDL_GROUP_2_MAX_QUOTA (0xFFF) +#define MT7961_DMASHDL_GROUP_3_MAX_QUOTA (0xFFF) +#define MT7961_DMASHDL_GROUP_4_MAX_QUOTA (0xFFF) +#define MT7961_DMASHDL_GROUP_5_MAX_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_6_MAX_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_7_MAX_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_8_MAX_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_9_MAX_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_10_MAX_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_11_MAX_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_12_MAX_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_13_MAX_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_14_MAX_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_15_MAX_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_0_MIN_QUOTA (0x3) +#define MT7961_DMASHDL_GROUP_1_MIN_QUOTA (0x3) +#define MT7961_DMASHDL_GROUP_2_MIN_QUOTA (0x3) +#define MT7961_DMASHDL_GROUP_3_MIN_QUOTA (0x3) +#define MT7961_DMASHDL_GROUP_4_MIN_QUOTA (0x3) +#define MT7961_DMASHDL_GROUP_5_MIN_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_6_MIN_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_7_MIN_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_8_MIN_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_9_MIN_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_10_MIN_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_11_MIN_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_12_MIN_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_13_MIN_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_14_MIN_QUOTA (0x0) +#define MT7961_DMASHDL_GROUP_15_MIN_QUOTA (0x0) +#define MT7961_DMASHDL_QUEUE_0_TO_GROUP (0x0) /* LMAC AC00 */ +#define MT7961_DMASHDL_QUEUE_1_TO_GROUP (0x1) /* LMAC AC01 */ +#define MT7961_DMASHDL_QUEUE_2_TO_GROUP (0x2) /* LMAC AC02 */ +#define MT7961_DMASHDL_QUEUE_3_TO_GROUP (0x3) /* LMAC AC03 */ +#define MT7961_DMASHDL_QUEUE_4_TO_GROUP (0x4) /* LMAC AC10 */ +#define MT7961_DMASHDL_QUEUE_5_TO_GROUP (0x4) /* LMAC AC11 */ +#define MT7961_DMASHDL_QUEUE_6_TO_GROUP (0x4) /* LMAC AC12 */ +#define MT7961_DMASHDL_QUEUE_7_TO_GROUP (0x4) /* LMAC AC13 */ +#define MT7961_DMASHDL_QUEUE_8_TO_GROUP (0x4) /* LMAC AC20 */ +#define MT7961_DMASHDL_QUEUE_9_TO_GROUP (0x4) /* LMAC AC21 */ +#define MT7961_DMASHDL_QUEUE_10_TO_GROUP (0x4) /* LMAC AC22 */ +#define MT7961_DMASHDL_QUEUE_11_TO_GROUP (0x4) /* LMAC AC23 */ +#define MT7961_DMASHDL_QUEUE_12_TO_GROUP (0x4) /* LMAC AC30 */ +#define MT7961_DMASHDL_QUEUE_13_TO_GROUP (0x4) /* LMAC AC31 */ +#define MT7961_DMASHDL_QUEUE_14_TO_GROUP (0x4) /* LMAC AC32 */ +#define MT7961_DMASHDL_QUEUE_15_TO_GROUP (0x4) /* LMAC AC33 */ +#define MT7961_DMASHDL_QUEUE_16_TO_GROUP (0x4) /* ALTX */ +#define MT7961_DMASHDL_QUEUE_17_TO_GROUP (0x4) /* BMC */ +#define MT7961_DMASHDL_QUEUE_18_TO_GROUP (0x4) /* BCN */ +#define MT7961_DMASHDL_QUEUE_19_TO_GROUP (0x5) /* HW Reserved */ +#define MT7961_DMASHDL_QUEUE_20_TO_GROUP (0x5) /* HW Reserved */ +#define MT7961_DMASHDL_QUEUE_21_TO_GROUP (0x5) /* HW Reserved */ +#define MT7961_DMASHDL_QUEUE_22_TO_GROUP (0x5) /* HW Reserved */ +#define MT7961_DMASHDL_QUEUE_23_TO_GROUP (0x5) /* HW Reserved */ +#define MT7961_DMASHDL_QUEUE_24_TO_GROUP (0x4) /* NAF */ +#define MT7961_DMASHDL_QUEUE_25_TO_GROUP (0x4) /* NBCN */ +#define MT7961_DMASHDL_QUEUE_26_TO_GROUP (0x4) /* FIXFID */ +#define MT7961_DMASHDL_QUEUE_27_TO_GROUP (0x5) /* Reserved */ +#define MT7961_DMASHDL_QUEUE_28_TO_GROUP (0x5) /* Reserved */ +#define MT7961_DMASHDL_QUEUE_29_TO_GROUP (0x5) /* Reserved */ +#define MT7961_DMASHDL_QUEUE_30_TO_GROUP (0x5) /* Reserved */ +#define MT7961_DMASHDL_QUEUE_31_TO_GROUP (0x5) /* Reserved */ +#define MT7961_DMASHDL_PRIORITY0_GROUP (0x3) +#define MT7961_DMASHDL_PRIORITY1_GROUP (0x2) +#define MT7961_DMASHDL_PRIORITY2_GROUP (0x1) +#define MT7961_DMASHDL_PRIORITY3_GROUP (0x0) +#define MT7961_DMASHDL_PRIORITY4_GROUP (0x4) +#define MT7961_DMASHDL_PRIORITY5_GROUP (0x5) +#define MT7961_DMASHDL_PRIORITY6_GROUP (0x6) +#define MT7961_DMASHDL_PRIORITY7_GROUP (0x7) +#define MT7961_DMASHDL_PRIORITY8_GROUP (0x8) +#define MT7961_DMASHDL_PRIORITY9_GROUP (0x9) +#define MT7961_DMASHDL_PRIORITY10_GROUP (0xA) +#define MT7961_DMASHDL_PRIORITY11_GROUP (0xB) +#define MT7961_DMASHDL_PRIORITY12_GROUP (0xC) +#define MT7961_DMASHDL_PRIORITY13_GROUP (0xD) +#define MT7961_DMASHDL_PRIORITY14_GROUP (0xE) +#define MT7961_DMASHDL_PRIORITY15_GROUP (0xF) + +#endif /* defined(_HIF_PCIE) || defined(_HIF_AXI) */ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +enum ENUM_MT7961_DMASHDL_GROUP_IDX { + ENUM_MT7961_DMASHDL_GROUP_0 = 0, + ENUM_MT7961_DMASHDL_GROUP_1, + ENUM_MT7961_DMASHDL_GROUP_2, + ENUM_MT7961_DMASHDL_GROUP_3, + ENUM_MT7961_DMASHDL_GROUP_4, + ENUM_MT7961_DMASHDL_GROUP_5, + ENUM_MT7961_DMASHDL_GROUP_6, + ENUM_MT7961_DMASHDL_GROUP_7, + ENUM_MT7961_DMASHDL_GROUP_8, + ENUM_MT7961_DMASHDL_GROUP_9, + ENUM_MT7961_DMASHDL_GROUP_10, + ENUM_MT7961_DMASHDL_GROUP_11, + ENUM_MT7961_DMASHDL_GROUP_12, + ENUM_MT7961_DMASHDL_GROUP_13, + ENUM_MT7961_DMASHDL_GROUP_14, + ENUM_MT7961_DMASHDL_GROUP_15, + ENUM_MT7961_DMASHDL_GROUP_NUM +}; + +struct MT7961_DMASHDL_CFG { + u_int8_t fgSlotArbiterEn; + uint16_t u2PktPleMaxPage; + uint16_t u2PktPseMaxPage; + u_int8_t afgRefillEn[ENUM_MT7961_DMASHDL_GROUP_NUM]; + uint16_t au2MaxQuota[ENUM_MT7961_DMASHDL_GROUP_NUM]; + uint16_t au2MinQuota[ENUM_MT7961_DMASHDL_GROUP_NUM]; + uint8_t aucQueue2Group[32]; + uint8_t aucPriority2Group[16]; +}; + +/******************************************************************************* +* P U B 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 mt7961HalDmashdlSetPlePktMaxPage(struct ADAPTER *prAdapter, + uint16_t u2MaxPage); + +void mt7961HalDmashdlSetPsePktMaxPage(struct ADAPTER *prAdapter, + uint16_t u2MaxPage); + +void mt7961HalDmashdlSetRefill(struct ADAPTER *prAdapter, uint8_t ucGroup, + u_int8_t fgEnable); + +void mt7961HalDmashdlSetMaxQuota(struct ADAPTER *prAdapter, uint8_t ucGroup, + uint16_t u2MaxQuota); + +void mt7961HalDmashdlSetMinQuota(struct ADAPTER *prAdatper, uint8_t ucGroup, + uint16_t u2MinQuota); + +void mt7961HalDmashdlSetQueueMapping(struct ADAPTER *prAdapter, uint8_t ucQueue, + uint8_t ucGroup); + +void mt7961DmashdlInit(struct ADAPTER *prAdapter); + +#endif /* _HAL_DMASHDL_MT7961_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/hal_dmashdl_soc3_0.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/hal_dmashdl_soc3_0.h new file mode 100644 index 0000000000000..67f263b44acad --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/hal_dmashdl_soc3_0.h @@ -0,0 +1,233 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +/*! \file hal_dmashdl_mt6885.h +* \brief DMASHDL HAL API for MT6885 +* +* This file contains all routines which are exported + from MediaTek 802.11 Wireless LAN driver stack to GLUE Layer. +*/ + +#ifndef _HAL_DMASHDL_MT6885_H +#define _HAL_DMASHDL_MT6885_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 +******************************************************************************** +*/ +/* align MT7663 setting first */ +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + +/* 1: 3rd arbitration makes decision based on group priority in current slot. + * 0: 3rd arbitration makes decision based on fixed user-defined priority. + */ +#define MT6885_DMASHDL_SLOT_ARBITER_EN (0) +#define MT6885_DMASHDL_PKT_PLE_MAX_PAGE (0x1) +#define MT6885_DMASHDL_PKT_PSE_MAX_PAGE (0x0) +#define MT6885_DMASHDL_GROUP_0_REFILL_EN (1) +#define MT6885_DMASHDL_GROUP_1_REFILL_EN (1) +#define MT6885_DMASHDL_GROUP_2_REFILL_EN (0) +#define MT6885_DMASHDL_GROUP_3_REFILL_EN (0) +#define MT6885_DMASHDL_GROUP_4_REFILL_EN (0) +#define MT6885_DMASHDL_GROUP_5_REFILL_EN (0) +#define MT6885_DMASHDL_GROUP_6_REFILL_EN (0) +#define MT6885_DMASHDL_GROUP_7_REFILL_EN (0) +#define MT6885_DMASHDL_GROUP_8_REFILL_EN (0) +#define MT6885_DMASHDL_GROUP_9_REFILL_EN (0) +#define MT6885_DMASHDL_GROUP_10_REFILL_EN (0) +#define MT6885_DMASHDL_GROUP_11_REFILL_EN (0) +#define MT6885_DMASHDL_GROUP_12_REFILL_EN (0) +#define MT6885_DMASHDL_GROUP_13_REFILL_EN (0) +#define MT6885_DMASHDL_GROUP_14_REFILL_EN (0) +#define MT6885_DMASHDL_GROUP_15_REFILL_EN (0) +#define MT6885_DMASHDL_GROUP_0_MAX_QUOTA (0x15D) +#define MT6885_DMASHDL_GROUP_1_MAX_QUOTA (0x15D) +#define MT6885_DMASHDL_GROUP_2_MAX_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_3_MAX_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_4_MAX_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_5_MAX_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_6_MAX_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_7_MAX_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_8_MAX_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_9_MAX_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_10_MAX_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_11_MAX_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_12_MAX_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_13_MAX_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_14_MAX_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_15_MAX_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_0_MIN_QUOTA (0x10) +#define MT6885_DMASHDL_GROUP_1_MIN_QUOTA (0x10) +#define MT6885_DMASHDL_GROUP_2_MIN_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_3_MIN_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_4_MIN_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_5_MIN_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_6_MIN_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_7_MIN_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_8_MIN_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_9_MIN_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_10_MIN_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_11_MIN_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_12_MIN_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_13_MIN_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_14_MIN_QUOTA (0x0) +#define MT6885_DMASHDL_GROUP_15_MIN_QUOTA (0x0) +#define MT6885_DMASHDL_QUEUE_0_TO_GROUP (0x0) /* LMAC AC00 */ +#define MT6885_DMASHDL_QUEUE_1_TO_GROUP (0x0) /* LMAC AC01 */ +#define MT6885_DMASHDL_QUEUE_2_TO_GROUP (0x0) /* LMAC AC02 */ +#define MT6885_DMASHDL_QUEUE_3_TO_GROUP (0x0) /* LMAC AC03 */ +#define MT6885_DMASHDL_QUEUE_4_TO_GROUP (0x1) /* LMAC AC10 */ +#define MT6885_DMASHDL_QUEUE_5_TO_GROUP (0x1) /* LMAC AC11 */ +#define MT6885_DMASHDL_QUEUE_6_TO_GROUP (0x1) /* LMAC AC12 */ +#define MT6885_DMASHDL_QUEUE_7_TO_GROUP (0x1) /* LMAC AC13 */ +#define MT6885_DMASHDL_QUEUE_8_TO_GROUP (0x0) /* LMAC AC20 */ +#define MT6885_DMASHDL_QUEUE_9_TO_GROUP (0x0) /* LMAC AC21 */ +#define MT6885_DMASHDL_QUEUE_10_TO_GROUP (0x0) /* LMAC AC22 */ +#define MT6885_DMASHDL_QUEUE_11_TO_GROUP (0x0) /* LMAC AC23 */ +#define MT6885_DMASHDL_QUEUE_12_TO_GROUP (0x0) /* LMAC AC30 */ +#define MT6885_DMASHDL_QUEUE_13_TO_GROUP (0x0) /* LMAC AC31 */ +#define MT6885_DMASHDL_QUEUE_14_TO_GROUP (0x0) /* LMAC AC32 */ +#define MT6885_DMASHDL_QUEUE_15_TO_GROUP (0x0) /* LMAC AC33 */ +#define MT6885_DMASHDL_QUEUE_16_TO_GROUP (0x0) /* ALTX */ +#define MT6885_DMASHDL_QUEUE_17_TO_GROUP (0x0) /* BMC */ +#define MT6885_DMASHDL_QUEUE_18_TO_GROUP (0x0) /* BCN */ +#define MT6885_DMASHDL_QUEUE_19_TO_GROUP (0x1) /* HW Reserved */ +#define MT6885_DMASHDL_QUEUE_20_TO_GROUP (0x1) /* HW Reserved */ +#define MT6885_DMASHDL_QUEUE_21_TO_GROUP (0x1) /* HW Reserved */ +#define MT6885_DMASHDL_QUEUE_22_TO_GROUP (0x1) /* HW Reserved */ +#define MT6885_DMASHDL_QUEUE_23_TO_GROUP (0x1) /* HW Reserved */ +#define MT6885_DMASHDL_QUEUE_24_TO_GROUP (0x0) /* NAF */ +#define MT6885_DMASHDL_QUEUE_25_TO_GROUP (0x0) /* NBCN */ +#define MT6885_DMASHDL_QUEUE_26_TO_GROUP (0x0) /* FIXFID */ +#define MT6885_DMASHDL_QUEUE_27_TO_GROUP (0x1) /* Reserved */ +#define MT6885_DMASHDL_QUEUE_28_TO_GROUP (0x1) /* Reserved */ +#define MT6885_DMASHDL_QUEUE_29_TO_GROUP (0x1) /* Reserved */ +#define MT6885_DMASHDL_QUEUE_30_TO_GROUP (0x1) /* Reserved */ +#define MT6885_DMASHDL_QUEUE_31_TO_GROUP (0x1) /* Reserved */ +#define MT6885_DMASHDL_PRIORITY0_GROUP (0x0) +#define MT6885_DMASHDL_PRIORITY1_GROUP (0x1) +#define MT6885_DMASHDL_PRIORITY2_GROUP (0x2) +#define MT6885_DMASHDL_PRIORITY3_GROUP (0x3) +#define MT6885_DMASHDL_PRIORITY4_GROUP (0x4) +#define MT6885_DMASHDL_PRIORITY5_GROUP (0x5) +#define MT6885_DMASHDL_PRIORITY6_GROUP (0x6) +#define MT6885_DMASHDL_PRIORITY7_GROUP (0x7) +#define MT6885_DMASHDL_PRIORITY8_GROUP (0x8) +#define MT6885_DMASHDL_PRIORITY9_GROUP (0x9) +#define MT6885_DMASHDL_PRIORITY10_GROUP (0xA) +#define MT6885_DMASHDL_PRIORITY11_GROUP (0xB) +#define MT6885_DMASHDL_PRIORITY12_GROUP (0xC) +#define MT6885_DMASHDL_PRIORITY13_GROUP (0xD) +#define MT6885_DMASHDL_PRIORITY14_GROUP (0xE) +#define MT6885_DMASHDL_PRIORITY15_GROUP (0xF) + +#endif /* defined(_HIF_PCIE) || defined(_HIF_AXI) */ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +enum ENUM_MT6885_DMASHDL_GROUP_IDX { + ENUM_MT6885_DMASHDL_GROUP_0 = 0, + ENUM_MT6885_DMASHDL_GROUP_1, + ENUM_MT6885_DMASHDL_GROUP_2, + ENUM_MT6885_DMASHDL_GROUP_3, + ENUM_MT6885_DMASHDL_GROUP_4, + ENUM_MT6885_DMASHDL_GROUP_5, + ENUM_MT6885_DMASHDL_GROUP_6, + ENUM_MT6885_DMASHDL_GROUP_7, + ENUM_MT6885_DMASHDL_GROUP_8, + ENUM_MT6885_DMASHDL_GROUP_9, + ENUM_MT6885_DMASHDL_GROUP_10, + ENUM_MT6885_DMASHDL_GROUP_11, + ENUM_MT6885_DMASHDL_GROUP_12, + ENUM_MT6885_DMASHDL_GROUP_13, + ENUM_MT6885_DMASHDL_GROUP_14, + ENUM_MT6885_DMASHDL_GROUP_15, + ENUM_MT6885_DMASHDL_GROUP_NUM +}; + +struct MT6885_DMASHDL_CFG { + u_int8_t fgSlotArbiterEn; + uint16_t u2PktPleMaxPage; + uint16_t u2PktPseMaxPage; + u_int8_t afgRefillEn[ENUM_MT6885_DMASHDL_GROUP_NUM]; + uint16_t au2MaxQuota[ENUM_MT6885_DMASHDL_GROUP_NUM]; + uint16_t au2MinQuota[ENUM_MT6885_DMASHDL_GROUP_NUM]; + uint8_t aucQueue2Group[32]; + uint8_t aucPriority2Group[16]; +}; + +/******************************************************************************* +* P U B 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 mt6885HalDmashdlSetPlePktMaxPage(struct ADAPTER *prAdapter, + uint16_t u2MaxPage); + +void mt6885HalDmashdlSetPsePktMaxPage(struct ADAPTER *prAdapter, + uint16_t u2MaxPage); + +void mt6885HalDmashdlSetRefill(struct ADAPTER *prAdapter, uint8_t ucGroup, + u_int8_t fgEnable); + +void mt6885HalDmashdlSetMaxQuota(struct ADAPTER *prAdapter, uint8_t ucGroup, + uint16_t u2MaxQuota); + +void mt6885HalDmashdlSetMinQuota(struct ADAPTER *prAdatper, uint8_t ucGroup, + uint16_t u2MinQuota); + +void mt6885HalDmashdlSetQueueMapping(struct ADAPTER *prAdapter, uint8_t ucQueue, + uint8_t ucGroup); + +void mt6885DmashdlInit(struct ADAPTER *prAdapter); + +void mt6885HalDmashdlGetPktMaxPage(struct ADAPTER *prAdapter); + +void mt6885HalDmashdlGetRefill(struct ADAPTER *prAdapter); + +void mt6885HalDmashdlGetGroupControl(struct ADAPTER *prAdapter, + uint8_t ucGroup); + +uint32_t mt6885HalDmashdlGetRsvCount(struct ADAPTER *prAdapter, + uint8_t ucGroup); + +uint32_t mt6885HalDmashdlGetSrcCount(struct ADAPTER *prAdapter, + uint8_t ucGroup); + +void mt6885HalDmashdlGetPKTCount(struct ADAPTER *prAdapter, + uint8_t ucGroup); +#endif /* _HAL_DMASHDL_MT6885_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/host_csr.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/host_csr.h new file mode 100644 index 0000000000000..0c1cfea8f4152 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/host_csr.h @@ -0,0 +1,104 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + host_csr.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- -------------------------------------- +*/ + +#ifndef __HOST_CSR_H__ +#define __HOST_CSR_H__ + +#define HOST_CSR_DRIVER_OWN_INFO 0x7000 +#define HOST_CSR_BASE 0x7100 + +/* MCU programming Counter info (no sync) */ +#define HOST_CSR_MCU_PORG_COUNT (HOST_CSR_BASE + 0x04) + +/* RGU Info */ +#define HOST_CSR_RGU (HOST_CSR_BASE + 0x08) + +/* HIF_BUSY / CIRQ / WFSYS_ON info */ +#define HOST_CSR_HIF_BUSY_CORQ_WFSYS_ON (HOST_CSR_BASE + 0x0C) + +/* Pinmux/mon_flag info */ +#define HOST_CSR_PINMUX_MON_FLAG (HOST_CSR_BASE + 0x10) + +/* Bit[5] mcu_pwr_stat */ +#define HOST_CSR_MCU_PWR_STAT (HOST_CSR_BASE + 0x14) + +/* Bit[15] fw_own_stat */ +#define HOST_CSR_FW_OWN_SET (HOST_CSR_BASE + 0x18) + +/* MCU SW Mailbox */ +#define HOST_CSR_MCU_SW_MAILBOX_0 (HOST_CSR_BASE + 0x1C) +#define HOST_CSR_MCU_SW_MAILBOX_1 (HOST_CSR_BASE + 0x20) +#define HOST_CSR_MCU_SW_MAILBOX_2 (HOST_CSR_BASE + 0x24) +#define HOST_CSR_MCU_SW_MAILBOX_3 (HOST_CSR_BASE + 0x28) + +/* Conn_cfg_on info */ +#define HOST_CSR_CONN_CFG_ON (HOST_CSR_BASE + 0x2C) + +/* Get conn_cfg_on IRQ ENA/IRQ Status 0xC_1170~0xC_1174 */ +#define HOST_CSR_IRQ_STA 0xC1170 +#define HOST_CSR_IRQ_ENA 0xC1174 + +/* Get mcu_cfg PC programming Counter log info 0x0_2450~0x0_24D0 */ +#define HOST_CSR_MCU_PROG_COUNT 0x2450 + +#if (CFG_ENABLE_HOST_BUS_TIMEOUT == 1) +#define HOST_CSR_BUS_TIMOUT_CTRL_ADDR (HOST_CSR_DRIVER_OWN_INFO + 0x44) +#define HOST_CSR_AP2CONN_AHB_HADDR (HOST_CSR_DRIVER_OWN_INFO + 0x4C) +#endif + +#if CFG_MTK_MCIF_WIFI_SUPPORT +/* Modem LP control */ +#define HOST_CSR_CONN_HIF_ON_MD_LPCTL_ADDR (HOST_CSR_DRIVER_OWN_INFO + 0x30) +/* Modem interrupt enable */ +#define HOST_CSR_CONN_HIF_ON_MD_IRQ_STAT_ADDR (HOST_CSR_DRIVER_OWN_INFO + 0x34) +/* Modem interrupt status */ +#define HOST_CSR_CONN_HIF_ON_MD_IRQ_ENA_ADDR (HOST_CSR_DRIVER_OWN_INFO + 0x38) +#endif + +/* +* AP2CONN_ADDR_MAP1[31..16] +* Mapping [0x180A_xxxx] to [ap2conn_addr_map0[15:0], xxxx] +* +* AP2CONN_ADDR_MAP0[15..0] +* Mapping [0x180D_xxxx] to [ap2conn_addr_map1[15:0], xxxx] +*/ +#define CONN_HIF_ON_ADDR_REMAP1 0x700C +#define AP2CONN_ADDR_MAP0 0xD0000 +#define AP2CONN_ADDR_MAP1 0xA0000 +/* +* AP2CONN_ADDR_MAP3[31..16] +* Mapping [0x180F_xxxx] to [ap2conn_addr_map3[15:0], xxxx] +* +* AP2CONN_ADDR_MAP2[15..0] +* Mapping [0x1804_xxxx] to [ap2conn_addr_map2[15:0], xxxx] +*/ +#define CONN_HIF_ON_ADDR_REMAP2 0x7010 +#define AP2CONN_ADDR_MAP3 0x40000 +#define AP2CONN_ADDR_MAP4 0xF0000 + +#endif /* __HOST_CSR_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/mt6632.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/mt6632.h new file mode 100644 index 0000000000000..0621852cd6440 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/mt6632.h @@ -0,0 +1,118 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/ + * MT6620_WIFI_DRIVER_V2_3/include/chips/mt6632.h#1 + */ + +/*! \file mt6632.h + * \brief This file contains the info of MT6632 + */ + +#ifndef _MT6632_H +#define _MT6632_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 MT6632_CHIP_ID (0x6632) +#define MT6632_SW_SYNC0 WIFI_CFG_SW_SYNC0 +#define MT6632_SW_SYNC0_RDY_OFFSET WIFI_CFG_SYNC0_RDY_OFFSET +#define MT6632_PATCH_START_ADDR (0x000B4000) +#define MT6632_TOP_CFG_BASE (0x0000) +#define MT6632_TX_DESC_APPEND_LENGTH 44 +#define MT6632_RX_DESC_LENGTH 16 +#define MT6632_RX_INIT_EVENT_LENGTH 8 +#define MT6632_RX_EVENT_HDR_LENGTH 12 + +/******************************************************************************* + * 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 /* _MT6632_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/mt7663.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/mt7663.h new file mode 100644 index 0000000000000..ca5b457160ba6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/mt7663.h @@ -0,0 +1,124 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/ + * MT6620_WIFI_DRIVER_V2_3/include/chips/mt7668.h#1 + */ + +/*! \file mt7663.h + * \brief This file contains the info of MT7663 + */ + +#ifdef MT7663 + +#ifndef _MT7663_H +#define _MT7663_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 MT7663_CHIP_ID (0x7663) +#define MT7663_SW_SYNC0 CONN_CFG_ON_CONN_ON_MISC_ADDR +#define MT7663_SW_SYNC0_RDY_OFFSET \ + CONN_CFG_ON_CONN_ON_MISC_DRV_FM_STAT_SYNC_SHFT +#define MT7663_PATCH_START_ADDR (0x000DC000) +#define MT7663_TOP_CFG_BASE CONN_CFG_BASE +#define MT7663_TX_DESC_APPEND_LENGTH 32 +#define MT7663_RX_DESC_LENGTH 16 +#define MT7663_RX_INIT_EVENT_LENGTH 8 +#define MT7663_RX_EVENT_HDR_LENGTH 12 + +/******************************************************************************* + * 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 /* _MT7663_H */ + +#endif /* MT7663 */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/mt7668.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/mt7668.h new file mode 100644 index 0000000000000..867cbc38601eb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/mt7668.h @@ -0,0 +1,120 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/ + * MT6620_WIFI_DRIVER_V2_3/include/chips/mt7668.h#1 + */ + +/*! \file mt7668.h + * \brief This file contains the info of MT7668 + */ + +#ifndef _MT7668_H +#define _MT7668_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 MT7668_CHIP_ID (0x7668) +#define MT7668_SW_SYNC0 WIFI_RGU_SW_SYNC0 +#define MT7668_SW_SYNC0_RDY_OFFSET WIFI_RGU_SYNC0_RDY_OFFSET +#define MT7668_PATCH_START_ADDR (0x000C8000) +#define MT7668_TOP_CFG_BASE (0x0000) +#define MT7668_TX_DESC_APPEND_LENGTH 44 +#define MT7668_RX_DESC_LENGTH 16 +#define MT7668_RX_INIT_EVENT_LENGTH 8 +#define MT7668_RX_EVENT_HDR_LENGTH 12 + +/******************************************************************************* + * 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 /* _MT7668_H */ + + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/mt7915.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/mt7915.h new file mode 100644 index 0000000000000..95f26ed56555a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/mt7915.h @@ -0,0 +1,139 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/*! \file mt7915.h +* \brief This file contains the info of MT7915 +*/ + +#ifdef MT7915 + +#ifndef _MT7915_H +#define _MT7915_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 +******************************************************************************** +*/ +/*TODO: To use correct ID after FPGA uses correct ID @20170927*/ + +#define CONNAC2X_TOP_HCR 0x70010200 +#define CONNAC2X_TOP_FVR 0x70010204 +#define CONNAC2X_TOP_HVR 0x70010208 +#define CONNAC2x_CONN_CFG_ON_BASE 0x7C060000 +#define CONNAC2x_CONN_CFG_ON_CONN_ON_MISC_ADDR \ + (CONNAC2x_CONN_CFG_ON_BASE + 0xF0) +#define CONNAC2x_CONN_CFG_ON_CONN_ON_MISC_DRV_FM_STAT_SYNC_SHFT 0 + +/* + * 0 is MT7915 E1 RX padding rule + * 1 is 8 bytes RX padding rule for MT7915e2 and chips after MT7915e2 + */ +#define CONNAC2X_WFDMA_RX_CSO_OPTION BIT(8) + +#define MT7915_CHIP_ID (0x7915) +#define MT7915_SW_SYNC0 CONNAC2x_CONN_CFG_ON_CONN_ON_MISC_ADDR +#define MT7915_SW_SYNC0_RDY_OFFSET \ + CONNAC2x_CONN_CFG_ON_CONN_ON_MISC_DRV_FM_STAT_SYNC_SHFT +#define MT7915_PATCH_START_ADDR (0x00200000) +#define MT7915_TOP_CFG_BASE CONN_CFG_BASE +#define MT7915_TX_DESC_APPEND_LENGTH 44 +#define MT7915_RX_DESC_LENGTH 24 +#define MT7915_ARB_AC_MODE_ADDR (0x820e3020) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +void mt7915_show_ple_info( + struct ADAPTER *prAdapter, + u_int8_t fgDumpTxd); +void mt7915_show_pse_info( + struct ADAPTER *prAdapter); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _MT7915_H */ +#endif /* MT7915 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/mt7961.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/mt7961.h new file mode 100644 index 0000000000000..d64b45ad4fc66 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/mt7961.h @@ -0,0 +1,141 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/*! \file mt7961.h +* \brief This file contains the info of MT7961 +*/ + +#ifdef MT7961 + +#ifndef _MT7961_H +#define _MT7961_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 +******************************************************************************** +*/ +/*TODO: To use correct ID after FPGA uses correct ID @20170927*/ + +#define CONNAC2X_TOP_HCR 0x70010200 +#define CONNAC2X_TOP_HVR 0x70010204 +#define CONNAC2X_TOP_FVR 0x70010208 +#define CONNAC2x_CONN_CFG_ON_BASE 0x7C060000 +#define CONNAC2x_CONN_CFG_ON_CONN_ON_MISC_ADDR \ + (CONNAC2x_CONN_CFG_ON_BASE + 0xF0) +#define CONNAC2x_CONN_CFG_ON_CONN_ON_MISC_DRV_FM_STAT_SYNC_SHFT 0 + +#define MT7961_CHIP_ID (0x7961) +#define MT7961_SW_SYNC0 CONNAC2x_CONN_CFG_ON_CONN_ON_MISC_ADDR +#define MT7961_SW_SYNC0_RDY_OFFSET \ + CONNAC2x_CONN_CFG_ON_CONN_ON_MISC_DRV_FM_STAT_SYNC_SHFT +#define MT7961_PATCH_START_ADDR (0x00900000) +#define MT7961_TOP_CFG_BASE CONN_CFG_BASE +#define MT7961_TX_DESC_APPEND_LENGTH 32 +#define MT7961_RX_DESC_LENGTH 24 +#define MT7961_ARB_AC_MODE_ADDR (0x820E315C) + +/*------------------------------------------------------------------------------ + * MACRO for WTBL INFO GET + *------------------------------------------------------------------------------ + */ + +#define MT7961_WIFI_LWTBL_BASE 0x820d4200 +#define MT7961_WIFI_UWTBL_BASE 0x820c4094 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +void mt7961_show_ple_info( + struct ADAPTER *prAdapter, + u_int8_t fgDumpTxd); +void mt7961_show_pse_info( + struct ADAPTER *prAdapter); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _MT7961_H */ + +#endif /* MT7961 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/mt_dmac.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/mt_dmac.h new file mode 100644 index 0000000000000..f2a20c6faf584 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/mt_dmac.h @@ -0,0 +1,362 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + mt_dmac.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ------------------------------------- +*/ + +#ifndef __MT_DMAC_H__ +#define __MT_DMAC_H__ + +struct TMAC_TXD_0 { + /* DWORD 0 */ + uint32_t TxByteCount : 16; + uint32_t EthTypeOffset : 7; + uint32_t IpChkSumOffload : 1; + uint32_t UdpTcpChkSumOffload : 1; + uint32_t rsv_25 : 1; + uint32_t q_idx : 5; + uint32_t p_idx : 1; /* P_IDX_XXX */ +}; + +/* TMAC_TXD_0.PIdx */ +#define P_IDX_LMAC 0 +#define P_IDX_MCU 1 +#define P_IDX_PLE_CTRL_PSE_PORT_3 3 + +#define UMAC_PLE_CTRL_P3_Q_0X1E 0x1e +#define UMAC_PLE_CTRL_P3_Q_0X1F 0x1f + +/* TMAC_TXD_0.QIdx */ +#define TxQ_IDX_AC0 0x00 +#define TxQ_IDX_AC1 0x01 +#define TxQ_IDX_AC2 0x02 +#define TxQ_IDX_AC3 0x03 +#define TxQ_IDX_AC10 0x04 +#define TxQ_IDX_AC11 0x05 +#define TxQ_IDX_AC12 0x06 +#define TxQ_IDX_AC13 0x07 +#define TxQ_IDX_AC20 0x08 +#define TxQ_IDX_AC21 0x09 +#define TxQ_IDX_AC22 0x0a +#define TxQ_IDX_AC23 0x0b +#define TxQ_IDX_AC30 0x0c +#define TxQ_IDX_AC31 0x0d +#define TxQ_IDX_AC32 0x0e +#define TxQ_IDX_AC33 0x0f + +#define TxQ_IDX_ALTX0 0x10 +#define TxQ_IDX_BMC0 0x11 +#define TxQ_IDX_BCN0 0x12 +#define TxQ_IDX_PSMP0 0x13 + +#define TxQ_IDX_ALTX1 0x14 +#define TxQ_IDX_BMC1 0x15 +#define TxQ_IDX_BCN1 0x16 +#define TxQ_IDX_PSMP1 0x17 + +#define TxQ_IDX_MCU0 0x00 +#define TxQ_IDX_MCU1 0x01 +#define TxQ_IDX_MCU2 0x02 +#define TxQ_IDX_MCU3 0x03 +#define TxQ_IDX_MCU_PDA 0x1e + + +/* TMAC_TXD_0.p_idx + TMAC_TXD_0.q_idx */ +#define PQ_IDX_WMM0_AC0 ((P_IDX_LMAC << 5) | (TxQ_IDX_AC0)) +#define PQ_IDX_WMM0_AC1 ((P_IDX_LMAC << 5) | (TxQ_IDX_AC1)) +#define PQ_IDX_WMM0_AC2 ((P_IDX_LMAC << 5) | (TxQ_IDX_AC2)) +#define PQ_IDX_WMM0_AC3 ((P_IDX_LMAC << 5) | (TxQ_IDX_AC3)) +#define PQ_IDX_WMM1_AC0 ((P_IDX_LMAC << 5) | (TxQ_IDX_AC10)) +#define PQ_IDX_WMM1_AC1 ((P_IDX_LMAC << 5) | (TxQ_IDX_AC11)) +#define PQ_IDX_WMM1_AC2 ((P_IDX_LMAC << 5) | (TxQ_IDX_AC12)) +#define PQ_IDX_WMM1_AC3 ((P_IDX_LMAC << 5) | (TxQ_IDX_AC13)) +#define PQ_IDX_WMM2_AC0 ((P_IDX_LMAC << 5) | (TxQ_IDX_AC20)) +#define PQ_IDX_WMM2_AC1 ((P_IDX_LMAC << 5) | (TxQ_IDX_AC21)) +#define PQ_IDX_WMM2_AC2 ((P_IDX_LMAC << 5) | (TxQ_IDX_AC22)) +#define PQ_IDX_WMM2_AC3 ((P_IDX_LMAC << 5) | (TxQ_IDX_AC23)) +#define PQ_IDX_WMM3_AC0 ((P_IDX_LMAC << 5) | (TxQ_IDX_AC30)) +#define PQ_IDX_WMM3_AC1 ((P_IDX_LMAC << 5) | (TxQ_IDX_AC31)) +#define PQ_IDX_WMM3_AC2 ((P_IDX_LMAC << 5) | (TxQ_IDX_AC32)) +#define PQ_IDX_WMM3_AC3 ((P_IDX_LMAC << 5) | (TxQ_IDX_AC33)) + +#define PQ_IDX_ALTX0 ((P_IDX_LMAC << 5) | (TxQ_IDX_ALTX0)) +#define PQ_IDX_BMC0 ((P_IDX_LMAC << 5) | (TxQ_IDX_ALTX0)) +#define PQ_IDX_BCN0 ((P_IDX_LMAC << 5) | (TxQ_IDX_ALTX0)) +#define PQ_IDX_PSMP0 ((P_IDX_LMAC << 5) | (TxQ_IDX_ALTX0)) + +#define PQ_IDX_MCU_RQ0 ((P_IDX_MCU << 5) | (TxQ_IDX_MCU0)) +#define PQ_IDX_MCU_RQ1 ((P_IDX_MCU << 5) | (TxQ_IDX_MCU1)) +#define PQ_IDX_MCU_RQ2 ((P_IDX_MCU << 5) | (TxQ_IDX_MCU2)) +#define PQ_IDX_MCU_RQ3 ((P_IDX_MCU << 5) | (TxQ_IDX_MCU3)) + +struct TMAC_TXD_1 { + /* DWORD 1 */ + uint32_t wlan_idx : 8; + uint32_t hdr_info : 5; /* in unit of WORD(2 bytes) */ + uint32_t hdr_format : 2; /* TMI_HDR_FT_XXX */ + uint32_t ft : 1; /* TMI_HDR_FT_XXX */ + uint32_t txd_len : 1; /* TMI_FT_XXXX */ + uint32_t hdr_pad : 2; + uint32_t UNxV : 1; + uint32_t amsdu : 1; + uint32_t tid : 3; + uint32_t pkt_ft : 2; + uint32_t OwnMacAddr : 6; +}; + +/* TMAC_TXD_1.pkt_ft */ +#define TMI_PKT_FT_HIF_CT 0 /* Cut-through */ +#define TMI_PKT_FT_HIF_SF 1 /* Store & forward */ +#define TMI_PKT_FT_HIF_CMD 2 /* Command frame to N9/CR4 */ +#define TMI_PKT_FT_HIF_FW 3 /* Firmware frame to PDA */ + +#define TMI_PKT_FT_MCU_CT 0 /* N9 Cut-through */ +#define TMI_PKT_FT_MCU_FW 3 /* N9 to UMAC/LMAC */ + +/* TMAC_TXD_1.hdr_format */ +#define TMI_HDR_FT_NON_80211 0x0 +#define TMI_HDR_FT_CMD 0x1 +#define TMI_HDR_FT_NOR_80211 0x2 +#define TMI_HDR_FT_ENH_80211 0x3 + +/* if TMAC_TXD_1.hdr_format == HDR_FORMAT_NON_80211 */ +#define TMI_HDR_INFO_0_BIT_MRD 0 +#define TMI_HDR_INFO_0_BIT_EOSP 1 +#define TMI_HDR_INFO_0_BIT_RMVL 2 +#define TMI_HDR_INFO_0_BIT_VLAN 3 +#define TMI_HDR_INFO_0_BIT_ETYP 4 +#define TMI_HDR_INFO_0_VAL(_mrd, _eosp, _rmvl, _vlan, _etyp) \ + ((((_mrd) ? 1 : 0) << TMI_HDR_INFO_0_BIT_MRD) | \ + (((_eosp) ? 1 : 0) << TMI_HDR_INFO_0_BIT_EOSP) |\ + (((_rmvl) ? 1 : 0) << TMI_HDR_INFO_0_BIT_RMVL) |\ + (((_vlan) ? 1 : 0) << TMI_HDR_INFO_0_BIT_VLAN) |\ + (((_etyp) ? 1 : 0) << TMI_HDR_INFO_0_BIT_ETYP)) + + +/* if TMAC_TXD_1.hdr_format == HDR_FORMAT_CMD */ +#define TMI_HDR_INFO_1_MASK_RSV (0x1f) +#define TMI_HDR_INFO_1_VAL 0 + +/* if TMAC_TXD_1.hdr_format == HDR_FORMAT_NOR_80211 */ +#define TMI_HDR_INFO_2_MASK_LEN (0x1f) +#define TMI_HDR_INFO_2_VAL(_len) (_len >> 1) + +/* if TMAC_TXD_1.hdr_format == HDR_FORMAT_ENH_80211 */ +#define TMI_HDR_INFO_3_BIT_EOSP 1 +#define TMI_HDR_INFO_3_BIT_AMS 2 +#define TMI_HDR_INFO_3_VAL(_eosp, _ams) \ + ((((_eosp) ? 1 : 0) << TMI_HDR_INFO_3_BIT_EOSP) | \ + (((_ams) ? 1 : 0) << TMI_HDR_INFO_3_BIT_AMS)) + +/* TMAC_TXD_1.TxDFmt */ +#define TMI_FT_SHORT 0 +#define TMI_FT_LONG 1 + +/* TMAC_TXD_1.HdrPad */ +#define TMI_HDR_PAD_BIT_MODE 1 +#define TMI_HDR_PAD_MODE_TAIL 0 +#define TMI_HDR_PAD_MODE_HEAD 1 +#define TMI_HDR_PAD_BIT_LEN 0 +#define TMI_HDR_PAD_MASK_LEN 0x3 + +struct TMAC_TXD_2 { + /* DWORD 2 */ + uint32_t sub_type : 4; + uint32_t frm_type : 2; + uint32_t ndp : 1; + uint32_t ndpa : 1; + uint32_t sounding : 1; + uint32_t rts : 1; + uint32_t bc_mc_pkt : 1; + uint32_t bip : 1; + uint32_t duration : 1; + uint32_t htc_vld : 1; + uint32_t frag : 2; + uint32_t max_tx_time : 8; + uint32_t pwr_offset : 5; + uint32_t ba_disable : 1; + uint32_t timing_measure : 1; + uint32_t fix_rate : 1; +}; + +struct TMAC_TXD_3 { + /* DWORD 3 */ + uint32_t no_ack : 1; + uint32_t protect_frm : 1; + uint32_t rsv_2_5 : 4; + uint32_t tx_cnt : 5; + uint32_t remain_tx_cnt : 5; + uint32_t sn : 12; + uint32_t rsv_28_29 : 2; + uint32_t pn_vld : 1; + uint32_t sn_vld : 1; +}; + +struct TMAC_TXD_4 { + /* DWORD 4 */ + uint32_t pn_low; +}; + +struct TMAC_TXD_5 { + /* DWORD 5 */ + uint32_t pid:8; + uint32_t tx_status_fmt:1; + uint32_t tx_status_2_mcu:1; + uint32_t tx_status_2_host:1; + uint32_t da_select:1; + uint32_t rsv_12:1; + uint32_t pwr_mgmt:1; + uint32_t rsv_14_15:2; + uint32_t pn_high:16; +}; + +/* TMAC_TXD_5.da_select */ +#define TMI_DAS_FROM_MPDU 0 +#define TMI_DAS_FROM_WTBL 1 + +/* TMAC_TXD_5.bar_sn_ctrl */ +#define TMI_BSN_CFG_BY_HW 0 +#define TMI_BSN_CFG_BY_SW 1 + +/* TMAC_TXD_5.pwr_mgmt */ +#define TMI_PM_BIT_CFG_BY_HW 0 +#define TMI_PM_BIT_CFG_BY_SW 1 + +struct TMAC_TXD_6 { + /* DWORD 6 */ + uint32_t bw:3; + uint32_t dyn_bw:1; + uint32_t ant_id:12; + uint32_t tx_rate:12; + uint32_t TxBF:1; + uint32_t ldpc:1; + uint32_t gi:1; + uint32_t fix_rate_mode:1; +}; + +/* TMAC_TXD_6.fix_rate_mode */ +#define TMI_FIX_RATE_BY_TXD 0 +#define TMI_FIX_RATE_BY_CR 1 + +#define TMI_TX_RATE_BIT_STBC 11 +#define TMI_TX_RATE_BIT_NSS 9 +#define TMI_TX_RATE_MASK_NSS 0x3 + +#define TMI_TX_RATE_BIT_MODE 6 +#define TMI_TX_RATE_MASK_MODE 0x7 +#define TMI_TX_RATE_MODE_CCK 0 +#define TMI_TX_RATE_MODE_OFDM 1 +#define TMI_TX_RATE_MODE_HTMIX 2 +#define TMI_TX_RATE_MODE_HTGF 3 +#define TMI_TX_RATE_MODE_VHT 4 + +#define SHORT_PREAMBLE 0 +#define LONG_PREAMBLE 1 + +#define TMI_TX_RATE_BIT_MCS 0 +#define TMI_TX_RATE_MASK_MCS 0x3f +#define TMI_TX_RATE_CCK_1M_LP 0 +#define TMI_TX_RATE_CCK_2M_LP 1 +#define TMI_TX_RATE_CCK_5M_LP 2 +#define TMI_TX_RATE_CCK_11M_LP 3 + +#define TMI_TX_RATE_CCK_2M_SP 5 +#define TMI_TX_RATE_CCK_5M_SP 6 +#define TMI_TX_RATE_CCK_11M_SP 7 + +#define TMI_TX_RATE_OFDM_6M 11 +#define TMI_TX_RATE_OFDM_9M 15 +#define TMI_TX_RATE_OFDM_12M 10 +#define TMI_TX_RATE_OFDM_18M 14 +#define TMI_TX_RATE_OFDM_24M 9 +#define TMI_TX_RATE_OFDM_36M 13 +#define TMI_TX_RATE_OFDM_48M 8 +#define TMI_TX_RATE_OFDM_54M 12 + +#define TMI_TX_RATE_HT_MCS0 0 +#define TMI_TX_RATE_HT_MCS1 1 +#define TMI_TX_RATE_HT_MCS2 2 +#define TMI_TX_RATE_HT_MCS3 3 +#define TMI_TX_RATE_HT_MCS4 4 +#define TMI_TX_RATE_HT_MCS5 5 +#define TMI_TX_RATE_HT_MCS6 6 +#define TMI_TX_RATE_HT_MCS7 7 +#define TMI_TX_RATE_HT_MCS8 8 +#define TMI_TX_RATE_HT_MCS9 9 +#define TMI_TX_RATE_HT_MCS10 10 +#define TMI_TX_RATE_HT_MCS11 11 +#define TMI_TX_RATE_HT_MCS12 12 +#define TMI_TX_RATE_HT_MCS13 13 +#define TMI_TX_RATE_HT_MCS14 14 +#define TMI_TX_RATE_HT_MCS15 15 +#define TMI_TX_RATE_HT_MCS16 16 +#define TMI_TX_RATE_HT_MCS17 17 +#define TMI_TX_RATE_HT_MCS18 18 +#define TMI_TX_RATE_HT_MCS19 19 +#define TMI_TX_RATE_HT_MCS20 20 +#define TMI_TX_RATE_HT_MCS21 21 +#define TMI_TX_RATE_HT_MCS22 22 +#define TMI_TX_RATE_HT_MCS23 23 + +#define TMI_TX_RATE_HT_MCS32 32 + +#define TMI_TX_RATE_VHT_MCS0 0 +#define TMI_TX_RATE_VHT_MCS1 1 +#define TMI_TX_RATE_VHT_MCS2 2 +#define TMI_TX_RATE_VHT_MCS3 3 +#define TMI_TX_RATE_VHT_MCS4 4 +#define TMI_TX_RATE_VHT_MCS5 5 +#define TMI_TX_RATE_VHT_MCS6 6 +#define TMI_TX_RATE_VHT_MCS7 7 +#define TMI_TX_RATE_VHT_MCS8 8 +#define TMI_TX_RATE_VHT_MCS9 9 + +struct TMAC_TXD_7 { + uint32_t sw_tx_time:10; + uint32_t rsv_10:1; + uint32_t spe_idx:5; + uint32_t pse_fid:14; + uint32_t hw_amsdu_cap:1; + uint32_t hif_err:1; +}; + +struct TMAC_TXD_L { + struct TMAC_TXD_0 TxD0; + struct TMAC_TXD_1 TxD1; + struct TMAC_TXD_2 TxD2; + struct TMAC_TXD_3 TxD3; + struct TMAC_TXD_4 TxD4; + struct TMAC_TXD_5 TxD5; + struct TMAC_TXD_6 TxD6; + struct TMAC_TXD_7 TxD7; +}; + +struct TMAC_TXD_S { + struct TMAC_TXD_0 TxD0; + struct TMAC_TXD_1 TxD1; + struct TMAC_TXD_7 TxD7; +}; + +#endif /* __MT_DMAC_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/pse.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/pse.h new file mode 100644 index 0000000000000..a21a2dfc6d912 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/pse.h @@ -0,0 +1,279 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + pse.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- -------------------------------------- +*/ + + +#ifndef __PSE_H__ +#define __PSE_H__ + +#define PSE_BASE 0xc000 + +/* PSE Reset Control Register */ +#define PSE_RESET (PSE_BASE + 0x00) +#define PSE_ALL_RST (1 << 0) +#define PSE_LOGICAL_RST (1 << 1) +#define PSE_INIT_DONE (1 << 2) +#define GET_PSE_INIT_DONE(p) (((p) & PSE_INIT_DONE) >> 2) + +/* PSE Buffer Control Register */ +#define PSE_PBUF_CTRL (PSE_BASE + 0x14) +#define PSE_TOTAL_PAGE_NUM_MASK (0xfff) +#define PSE_GET_TOTAL_PAGE_NUM(p) (((p) & 0xfff)) +#define PSE_TOTAL_PAGE_CFG_MASK (0xf << 16) +#define PSE_GET_TOTAL_PAGE_CFG(p) (((p) & PSE_TOTAL_PAGE_CFG_MASK) >> 16) + +#define PSE_PBUF_OFFSET_MASK (0xf << 20) +#define GET_PSE_PBUF_OFFSET(p) (((p) & PSE_PBUF_OFFSET_MASK) >> 20) + +#define PSE_GC (PSE_BASE) +#define PSE_INT_STS (PSE_BASE + 0x24) +#define PSE_INT_ERR_STS (PSE_BASE + 0x28) + +/* Queue Empty */ +#define PSE_QUEUE_EMPTY (PSE_BASE + 0xb0) + +/* Page Flow Control */ +#define PSE_FREEPG_CNT (PSE_BASE + 0x100) + +#define PSE_FREEPG_HEAD_TAIL (PSE_BASE + 0x104) + +#define PSE_ENQ_0 (PSE_BASE + 0x60) +#define PSE_DEQ_0 (PSE_BASE + 0x80) +#define PSE_ENDEQ_OFFSET 0x4 +#define PSE_ENDEQ_NUM 3 + +#define PSE_PG_HIF0_GROUP (PSE_BASE + 0x110) +#define PSE_HIF0_PG_INFO (PSE_BASE + 0x114) +#define PSE_PG_HIF1_GROUP (PSE_BASE + 0x118) +#define PSE_HIF1_PG_INFO (PSE_BASE + 0x11c) + +#define PSE_PG_CPU_GROUP (PSE_BASE + 0x150) +#define PSE_CPU_PG_INFO (PSE_BASE + 0x154) + +#define PSE_PG_LMAC0_GROUP (PSE_BASE + 0x170) +#define PSE_LMAC0_PG_INFO (PSE_BASE + 0x174) +#define PSE_PG_LMAC1_GROUP (PSE_BASE + 0x178) +#define PSE_LMAC1_PG_INFO (PSE_BASE + 0x17c) +#define PSE_PG_LMAC2_GROUP (PSE_BASE + 0x180) +#define PSE_LMAC2_PG_INFO (PSE_BASE + 0x184) +#define PSE_PG_PLE_GROUP (PSE_BASE + 0x190) +#define PSE_PLE_PG_INFO (PSE_BASE + 0x194) + +#define PSE_RL_BUF_CTRL_0 (PSE_BASE + 0x1a0) +#define PSE_RL_BUF_CTRL_1 (PSE_BASE + 0x1a4) + +/* Indirect path for read/write */ +#define PSE_FL_QUE_CTRL_0 (PSE_BASE + 0x1b0) +#define PSE_FL_QUE_CTRL_1 (PSE_BASE + 0x1b4) +#define PSE_FL_QUE_CTRL_2 (PSE_BASE + 0x1b8) +#define PSE_FL_QUE_CTRL_3 (PSE_BASE + 0x1bc) +#define PSE_PL_QUE_CTRL_0 (PSE_BASE + 0x1c0) + +/* PSE spare dummy CR */ +#define PSE_SPARE_DUMMY_CR1 (PSE_BASE + 0x1e4) +#define PSE_SPARE_DUMMY_CR2 (PSE_BASE + 0x1e8) +#define PSE_SPARE_DUMMY_CR3 (PSE_BASE + 0x2e8) +#define PSE_SPARE_DUMMY_CR4 (PSE_BASE + 0x2ec) + +#define PSE_PEEK_CR_0 (PSE_BASE + 0x3d0) +#define PSE_PEEK_CR_OFFSET 0x4 +#define PSE_PEEK_CR_NUM 9 + +/* CPU Interface Get First Frame ID Control Regitser */ +#define C_GFF (PSE_BASE + 0x24) +#define GET_FIRST_FID_MASK (0xfff) +#define GET_FIRST_FID(p) (((p) & GET_FIRST_FID_MASK)) +#define GET_QID_MASK (0x1f << 16) +#define SET_GET_QID(p) (((p) & 0x1f) << 16) +#define GET_QID(p) (((p) & GET_QID_MASK) >> 16) +#define GET_PID_MASK (0x3 << 21) +#define SET_GET_PID(p) (((p) & 0x3) << 21) +#define GET_PID(p) (((p) & GET_PID_MASK) >> 21) +#define GET_RVSE_MASK (1 << 23) +#define SET_GET_RVSE(p) (((p) & 0x1) << 23) +#define GET_RVSE(p) (((p) & GET_RVSE_MASK) >> 23) + +/* CPU Interface Get Frame ID Control Register */ +#define C_GF (PSE_BASE + 0x28) +#define GET_RETURN_FID_MASK (0xfff) +#define GET_RETURN_FID(p) (((p) & GET_RETURN_FID_MASK)) +#define CURR_FID_MASK (0xfff << 16) +#define SET_CURR_FID(p) (((p) & 0xfff) << 16) +#define GET_CURR_FID(p) (((p) & CURR_FID_MASK) >> 16) +#define GET_PREV_MASK (1 << 28) +#define SET_GET_PREV(p) (((p) & 0x1) << 28) +#define GET_PREV(p) (((p) & GET_PREV_MASK) >> 28) +#define GET_AUTO_MASK (1 << 29) +#define SET_GET_AUTO(p) (((p) & 0x1) >> 29) +#define GET_AUTO(p) (((p) & GET_AUTO_MASK) >> 29) + +/* Get Queue Length Control Register */ +#define GQC (PSE_BASE + 0x118) +#define QLEN_RETURN_VALUE_MASK (0xfff) +#define GET_QLEN_RETURN_VALUE(p) (((p) & QLEN_RETURN_VALUE_MASK)) +#define GET_QLEN_QID_MASK (0x1f << 16) +#define SET_GET_QLEN_QID(p) (((p) & 0x1f) << 16) +#define GET_QLEN_QID(p) (((p) & GET_QLEN_QID_MASK) >> 16) +#define GET_QLEN_PID_MASK (0x3 << 21) +#define SET_GET_QLEN_PID(p) (((p) & 0x3) << 21) +#define GET_QLEN_PID(p) (((p) & GET_QLEN_PID_MASK) >> 21) +#define QLEN_IN_PAGE (1 << 23) +#define GET_QLEN_IN_PAGE(p) (((p) & QLEN_IN_PAGE) >> 23) + +/* Flow Control P0 Control Register */ +#define FC_P0 (PSE_BASE + 0x120) +#define MIN_RSRV_P0_MASK (0xfff) +#define MIN_RSRV_P0(p) (((p) & 0xfff)) +#define GET_MIN_RSRV_P0(p) (((p) & MIN_RSRV_P0_MASK)) +#define MAX_QUOTA_P0_MASK (0xfff << 16) +#define MAX_QUOTA_P0(p) (((p) & 0xfff) << 16) +#define GET_MAX_QUOTA_P0(p) (((p) & MAX_QUOTA_P0_MASK) >> 16) + +/* Flow Control P1 Control Register */ +#define FC_P1 (PSE_BASE + 0x124) +#define MIN_RSRV_P1_MASK (0xfff) +#define MIN_RSRV_P1(p) (((p) & 0xfff)) +#define GET_MIN_RSRV_P1(p) (((p) & MIN_RSRV_P1_MASK)) +#define MAX_QUOTA_P1_MASK (0xfff << 16) +#define MAX_QUOTA_P1(p) (((p) & 0xfff) << 16) +#define GET_MAX_QUOTA_P1(p) (((p) & MAX_QUOTA_P1_MASK) >> 16) + +/* Flow Control P2_RQ0 Control Register */ +#define FC_P2Q0 (PSE_BASE + 0x128) +#define MIN_RSRV_P2_RQ0_MASK (0xfff) +#define MIN_RSRV_P2_RQ0(p) (((p) & 0xfff)) +#define GET_MIN_RSRV_P2_RQ0(p) (((p) & MIN_RSRV_P2_RQ0_MASK)) +#define MAX_QUOTA_P2_RQ0_MASK (0xfff << 16) +#define MAX_QUOTA_P2_RQ0(p) (((p) & 0xfff) << 16) +#define GET_MAX_QUOTA_P2_RQ0(p) (((p) & MAX_QUOTA_P2_RQ0_MASK) >> 16) + +/* Flow Control P2_RQ1 Control Register */ +#define FC_P2Q1 (PSE_BASE + 0x12c) +#define MIN_RSRV_P2_RQ1_MASK (0xfff) +#define MIN_RSRV_P2_RQ1(p) (((p) & 0xfff)) +#define GET_MIN_RSRV_P2_RQ1(p) (((p) & MIN_RSRV_P2_RQ1_MASK)) +#define MAX_QUOTA_P2_RQ1_MASK (0xfff << 16) +#define MAX_QUOTA_P2_RQ1(p) (((p) & 0xfff) << 16) +#define GET_MAX_QUOTA_P2_RQ1(p) (((p) & MAX_QUOTA_P2_RQ1_MASK) >> 16) + +/* Flow Control P2_RQ2 Control Register */ +#define FC_P2Q2 (PSE_BASE + 0x130) +#define MIN_RSRV_P2_RQ2_MASK (0xfff) +#define MIN_RSRV_P2_RQ2(p) (((p) & 0xfff)) +#define GET_MIN_RSRV_P2_RQ2(p) (((p) & MIN_RSRV_P2_RQ2_MASK)) +#define MAX_QUOTA_P2_RQ2_MASK (0xfff << 16) +#define MAX_QUOTA_P2_RQ2(p) (((p) & 0xfff) << 16) +#define GET_MAX_QUOTA_P2_RQ2(p) (((p) & MAX_QUOTA_P2_RQ2_MASK) >> 16) + +/* Flow Control Free for All and Free Page Counter Register */ +#define FC_FFC (PSE_BASE + 0x134) +#define FREE_PAGE_CNT_MASK (0xfff) +#define GET_FREE_PAGE_CNT(p) (((p) & FREE_PAGE_CNT_MASK)) +#define FFA_CNT_MASK (0xfff << 16) +#define GET_FFA_CNT(p) (((p) & FFA_CNT_MASK) >> 16) + +/* Flow Control Reserve from FFA priority Control Register */ +#define FC_FRP (PSE_BASE + 0x138) +#define RSRV_PRI_P0_MASK (0x7) +#define RSRV_PRI_P0(p) (((p) & 0x7)) +#define GET_RSRV_PRI_P0(p) (((p) & RSRV_PRI_P0_MASK)) +#define RSRV_PRI_P1_MASK (0x7 << 3) +#define RSRV_PRI_P1(p) (((p) & 0x7) << 3) +#define GET_RSRV_PRI_P1(p) (((p) & RSRV_PRI_P1_MASK) >> 3) +#define RSRV_PRI_P2_RQ0_MASK (0x7 << 6) +#define RSRV_PRI_P2_RQ0(p) (((p) & 0x7) << 6) +#define GET_RSRV_PRI_P2_RQ0(p) (((p) & RSRV_PRI_P2_RQ0_MASK) >> 6) +#define RSRV_PRI_P2_RQ1_MASK (0x7 << 9) +#define RSRV_PRI_P2_RQ1(p) (((p) & 0x7) << 9) +#define GET_RSRV_PRI_P2_RQ1(p) (((p) & RSRV_PRI_P2_RQ1_MASK) >> 9) +#define RSRV_PRI_P2_RQ2_MASK (0x7 << 12) +#define RSRV_PRI_P2_RQ2(p) (((p) & 0x7) << 12) +#define GET_RSRV_PRI_P2_RQ2(p) (((p) & RSRV_PRI_P2_RQ2_MASK) >> 12) + +/* Flow Control P0 and P1 Reserve Counter Register */ +#define FC_RP0P1 (PSE_BASE + 0x13c) +#define RSRV_CNT_P0_MASK (0xfff) +#define RSRV_CNT_P0(p) (((p) & 0xfff)) +#define GET_RSRV_CNT_P0(p) (((p) & RSRV_CNT_P0_MASK)) +#define RSRV_CNT_P1_MASK (0xfff << 16) +#define RSRV_CNT_P1(p) (((p) & 0xfff) << 16) +#define GET_RSRV_CNT_P1(p) (((p) & RSRV_CNT_P1_MASK) >> 16) + +/* Flow Control P2_RQ0 and P2_RQ1 Reserve Counter Register */ +#define FC_RP2Q0Q1 (PSE_BASE + 0x140) +#define RSRV_CNT_P2_RQ0_MASK (0xfff) +#define RSRV_CNT_P2_RQ0(p) (((p) & 0xfff)) +#define GET_RSRV_CNT_P2_RQ0(p) (((p) & RSRV_CNT_P2_RQ0_MASK)) +#define RSRV_CNT_P2_RQ1_MASK (0xfff << 16) +#define RSRV_CNT_P2_RQ1(p) (((p) & 0xfff) << 16) +#define GET_RSRV_CNT_P2_RQ1(p) (((p) & RSRV_CNT_P2_RQ1_MASK) >> 16) + +/* Flow Control P2_RQ2 Reserve Counter Register */ +#define FC_RP2Q2 (PSE_BASE + 0x144) +#define RSRV_CNT_P2_RQ2_MASK (0xfff) +#define RSRV_CNT_P2_RQ2(p) (((p) & 0xfff)) +#define GET_RSRV_CNT_P2_RQ2(p) (((p) & RSRV_CNT_P2_RQ2_MASK)) + +/* Flow Control P0 and P1 Source Counter Register */ +#define FC_SP0P1 (PSE_BASE + 0x148) +#define SRC_CNT_P0_MASK (0xfff) +#define GET_SRC_CNT_P0(p) (((p) & SRC_CNT_P0_MASK)) +#define SRC_CNT_P1_MASK (0xfff << 16) +#define GET_SRC_CNT_P1(p) (((p) & SRC_CNT_P1_MASK) >> 16) + +/* FLow Control P2_RQ0 and P2_RQ1 Source Counter Register */ +#define FC_SP2Q0Q1 (PSE_BASE + 0x14c) +#define SRC_CNT_P2_RQ0_MASK (0xfff) +#define GET_SRC_CNT_P2_RQ0(p) (((p) & SRC_CNT_P2_RQ0_MASK)) +#define SRC_CNT_P2_RQ1_MASK (0xfff << 16) +#define GET_SRC_CNT_P2_RQ1(p) (((p) & SRC_CNT_P2_RQ1_MASK) >> 16) + +/* Flow Control P2_RQ2 Source Counter Register */ +#define FC_SP2Q2 (PSE_BASE + 0x150) +#define SRC_CNT_P2_RQ2_MASK (0xfff) +#define GET_SRC_CNT_P2_RQ2(p) (((p) & 0xfff)) + +#define PSE_RTA (PSE_BASE + 0x194) +#define PSE_RTA_RD_RULE_QID_MASK (0x1f) +#define PSE_RTA_RD_RULE_QID(p) (((p) & 0x1f)) +#define GET_PSE_RTA_RD_RULE_QID(p) (((p) & PSE_RTA_RD_RULE_QID_MASK)) +#define PSE_RTA_RD_RULE_PID_MASK (0x3 << 5) +#define PSE_RTA_RD_RULE_PID(p) (((p) & 0x3) << 5) +#define GET_PSE_RTA_RD_RULE_PID(p) (((p) & PSE_RTA_RD_RULE_PID_MASK) >> 5) +#define PSE_RTA_RD_RULE_F (1 << 7) +#define GET_PSE_RTA_RD_RULE_F(p) (((p) & PSE_RTA_RD_RULE_F) >> 7) +#define PSE_RTA_TAG_MASK (0xff << 8) +#define PSE_RTA_TAG(p) (((p) & 0xff) << 8) +#define GET_PSE_RTA_TAG(p) (((p) & PSE_RTA_TAG_MASK) >> 8) +#define PSE_RTA_RD_RW (1 << 16) +#define PSE_RTA_RD_KICK_BUSY (1 << 31) +#define GET_PSE_RTA_RD_KICK_BUSY(p) (((p) & PSE_RTA_RD_KICK_BUSY) >> 31) + +#define PSE_PAYLOAD_BASE 0xB0000000 + +#endif /* _PSE */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/soc3_0.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/soc3_0.h new file mode 100644 index 0000000000000..9f65ace526775 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/soc3_0.h @@ -0,0 +1,395 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/*! \file soc3_0.h +* \brief This file contains the info of soc3_0 +*/ + +#ifdef SOC3_0 + +#ifndef _SOC3_0_H +#define _SOC3_0_H +#if (CFG_SUPPORT_CONNINFRA == 1) +#include "conninfra.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 CONNAC2X_TOP_HCR 0x88000000 /*no use, set HCR = HVR*/ +#define CONNAC2X_TOP_HVR 0x88000000 +#define CONNAC2X_TOP_FVR 0x88000004 +#define CONNAC2x_CONN_CFG_ON_BASE 0x7C060000 +#define CONNAC2x_CONN_CFG_ON_CONN_ON_MISC_ADDR \ + (CONNAC2x_CONN_CFG_ON_BASE + 0xF0) +#define CONNAC2x_CONN_CFG_ON_CONN_ON_MISC_DRV_FM_STAT_SYNC_SHFT 0 + +#define SOC3_0_CHIP_ID (0x7915) +#define SOC3_0_SW_SYNC0 CONNAC2x_CONN_CFG_ON_CONN_ON_MISC_ADDR +#define SOC3_0_SW_SYNC0_RDY_OFFSET \ + CONNAC2x_CONN_CFG_ON_CONN_ON_MISC_DRV_FM_STAT_SYNC_SHFT +#define SOC3_0_PATCH_START_ADDR (0x00100000) +#define SOC3_0_TOP_CFG_BASE CONN_CFG_BASE +#define SOC3_0_TX_DESC_APPEND_LENGTH 32 +#define SOC3_0_RX_DESC_LENGTH 24 +#define SOC3_0_ARB_AC_MODE_ADDR (0x820e3020) +#define MTK_CUSTOM_OID_INTERFACE_VERSION 0x00000200 /* for WPDWifi DLL */ +#define MTK_EM_INTERFACE_VERSION 0x0001 + +#define CONN_HOST_CSR_TOP_BASE_ADDR 0x18060000 +#define CONN_INFRA_CFG_BASE_ADDR 0x18001000 +#define CONN_INFRA_RGU_BASE_ADDR 0x18000000 +#define CONN_INFRA_BRCM_BASE_ADDR 0x1800E000 +#define WFDMA_AXI0_R2A_CTRL_0 0x7c027500 + +#define WF_TOP_MISC_OFF_BASE_ADDR 0x184B0000 +#define BID_CHK_BYP_EN_MASK 0x00000800 + +#define WF2CONN_SLPPROT_IDLE_ADDR 0x1800F004 + +#define CONN_INFRA_WAKEUP_WF_ADDR (CONN_HOST_CSR_TOP_BASE_ADDR + 0x01A4) +#define CONN_INFRA_ON2OFF_SLP_PROT_ACK_ADDR \ + (CONN_HOST_CSR_TOP_BASE_ADDR + 0x0184) +#define CONN_HW_VER_ADDR (CONN_INFRA_CFG_BASE_ADDR + 0x0000) +#define WFSYS_SW_RST_B_ADDR (CONN_INFRA_RGU_BASE_ADDR + 0x0018) +#define WFSYS_CPU_SW_RST_B_ADDR (CONN_INFRA_RGU_BASE_ADDR + 0x0010) +#define WFSYS_ON_TOP_PWR_CTL_ADDR (CONN_INFRA_RGU_BASE_ADDR + 0x0000) +#define TOP_DBG_DUMMY_3_CONNSYS_PWR_STATUS_ADDR \ + (CONN_HOST_CSR_TOP_BASE_ADDR + 0x02CC) +#define CONN_INFRA_WF_SLP_CTRL_R_ADDR (CONN_INFRA_CFG_BASE_ADDR + 0x0620) +#define CONN_INFRA_WFDMA_SLP_CTRL_R_ADDR (CONN_INFRA_CFG_BASE_ADDR + 0x0624) +#define CONN_INFRA_WFSYS_EMI_REQ_ADDR (CONN_INFRA_CFG_BASE_ADDR + 0x0c14) + +#define WF_VDNR_EN_ADDR (CONN_INFRA_BRCM_BASE_ADDR + 0x6C) +#define WFSYS_VERSION_ID_ADDR (WF_TOP_MISC_OFF_BASE_ADDR + 0x10) +#define CONN_CFG_AP2WF_REMAP_1_ADDR (CONN_INFRA_CFG_BASE_ADDR + 0x0120) +#define CONN_MCU_CONFG_HS_BASE 0x89040000 +#define WFSYS_VERSION_ID 0x20010000 +#define WF_DYNAMIC_BASE 0x18500000 +#define MCU_EMI_ENTRY_OFFSET 0x01DC +#define WF_EMI_ENTRY_OFFSET 0x01E0 +#define CONN_AFE_CTL_RG_DIG_EN_ADDR (0x18003008) + +#define CONNSYS_ROM_DONE_CHECK 0x00001D1E + +#define WF_ROM_CODE_INDEX_ADDR 0x184C1604 + +#define WF_TRIGGER_AP2CONN_EINT 0x10001F00 +#define WF_CONN_INFA_BUS_CLOCK_RATE 0x1000123C + +#define WFSYS_CPUPCR_ADDR (CONNAC2x_CONN_CFG_ON_BASE + 0x0204) +#define WFSYS_LP_ADDR (CONNAC2x_CONN_CFG_ON_BASE + 0x0208) + +#define WMMCU_ROM_PATCH_DATE_ADDR 0xF027F0D0 +#define WMMCU_MCU_ROM_EMI_DATE_ADDR 0xF027F0E0 +#define WMMCU_WIFI_ROM_EMI_DATE_ADDR 0xF027F0F0 +#define DATE_CODE_SIZE 16 + +union soc3_0_WPDMA_INT_MASK { + + struct { + uint32_t wfdma1_rx_done_0:1; + uint32_t wfdma1_rx_done_1:1; + uint32_t wfdma1_rx_done_2:1; + uint32_t wfdma1_rx_done_3:1; + uint32_t wfdma1_tx_done_0:1; + uint32_t wfdma1_tx_done_1:1; + uint32_t wfdma1_tx_done_2:1; + uint32_t wfdma1_tx_done_3:1; + uint32_t wfdma1_tx_done_4:1; + uint32_t wfdma1_tx_done_5:1; + uint32_t wfdma1_tx_done_6:1; + uint32_t wfdma1_tx_done_7:1; + uint32_t wfdma1_tx_done_8:1; + uint32_t wfdma1_tx_done_9:1; + uint32_t wfdma1_tx_done_10:1; + uint32_t wfdma1_tx_done_11:1; + uint32_t wfdma1_tx_done_12:1; + uint32_t wfdma1_tx_done_13:1; + uint32_t wfdma1_tx_done_14:1; + uint32_t reserved19:1; + uint32_t wfdma1_rx_coherent:1; + uint32_t wfdma1_tx_coherent:1; + uint32_t reserved:2; + uint32_t wpdma2host_err_int_en:1; + uint32_t reserved25:1; + uint32_t wfdma1_tx_done_16:1; + uint32_t wfdma1_tx_done_17:1; + uint32_t wfdma1_subsys_int_en:1; + uint32_t wfdma1_mcu2host_sw_int_en:1; + uint32_t wfdma1_tx_done_18:1; + uint32_t reserved31:1; + } field_wfdma1_ena; + + struct { + uint32_t wfdma0_rx_done_0:1; + uint32_t wfdma0_rx_done_1:1; + uint32_t wfdma0_rx_done_2:1; + uint32_t wfdma0_rx_done_3:1; + uint32_t wfdma0_tx_done_0:1; + uint32_t wfdma0_tx_done_1:1; + uint32_t wfdma0_tx_done_2:1; + uint32_t wfdma0_tx_done_3:1; + uint32_t reserved8:11; + uint32_t wfdma0_rx_done_6:1; + uint32_t wfdma0_rx_coherent:1; + uint32_t wfdma0_tx_coherent:1; + uint32_t wfdma0_rx_done_4:1; + uint32_t wfdma0_rx_done_5:1; + uint32_t wpdma2host_err_int_en:1; + uint32_t wfdma0_rx_done_7:1; + uint32_t reserved26:2; + uint32_t wfdma0_subsys_int_en:1; + uint32_t wfdma0_mcu2host_sw_int_en:1; + uint32_t reserved30:2; + } field_wfdma0_ena; + uint32_t word; +}; +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +enum ENUM_WLAN_POWER_ON_DOWNLOAD { + ENUM_WLAN_POWER_ON_DOWNLOAD_EMI = 0, + ENUM_WLAN_POWER_ON_DOWNLOAD_ROM_PATCH = 1, + ENUM_WLAN_POWER_ON_DOWNLOAD_WIFI_RAM_CODE = 2 +}; + +struct ROM_EMI_HEADER { + uint8_t ucDateTime[16]; + uint8_t ucPLat[4]; + uint16_t u2HwVer; + uint16_t u2SwVer; + uint32_t u4PatchAddr; + uint32_t u4PatchType; + uint32_t u4CRC[4]; +}; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +extern struct platform_device *g_prPlatDev; +#if (CFG_SUPPORT_CONNINFRA == 1) +extern u_int8_t g_IsWfsysBusHang; +extern struct completion g_triggerComp; +extern bool g_IsTriggerTimeout; +extern u_int8_t fgIsResetting; +extern u_int8_t g_fgRstRecover; +extern struct regmap *g_regmap; +#endif + +#if (CFG_ANDORID_CONNINFRA_COREDUMP_SUPPORT == 1) +extern u_int8_t g_IsNeedWaitCoredump; +#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 +******************************************************************************** +*/ +void soc3_0_show_ple_info( + struct ADAPTER *prAdapter, + u_int8_t fgDumpTxd); +void soc3_0_show_pse_info( + struct ADAPTER *prAdapter); + +void soc3_0_show_wfdma_info( + IN struct ADAPTER *prAdapter); + +void soc3_0_show_wfdma_info_by_type( + IN struct ADAPTER *prAdapter, + bool bShowWFDMA_type); + +void soc3_0_show_wfdma_info_by_type_without_adapter( + bool bIsHostDMA); + +void soc3_0_DumpWFDMACr(struct ADAPTER *prAdapter); + +void soc3_0_show_dmashdl_info( + IN struct ADAPTER *prAdapter); +void soc3_0_dump_mac_info( + IN struct ADAPTER *prAdapter); +void soc3_0EnableInterrupt( + struct ADAPTER *prAdapter); + +void soc3_0EnableInterrupt( + struct ADAPTER *prAdapter); +extern void kalConstructDefaultFirmwarePrio( + struct GLUE_INFO *prGlueInfo, + uint8_t **apucNameTable, + uint8_t **apucName, + uint8_t *pucNameIdx, + uint8_t ucMaxNameIdx); + +extern uint32_t kalFirmwareOpen( + IN struct GLUE_INFO *prGlueInfo, + IN uint8_t **apucNameTable); + + +extern uint32_t kalFirmwareSize( + IN struct GLUE_INFO *prGlueInfo, + OUT uint32_t *pu4Size); + +extern uint32_t kalFirmwareLoad( + IN struct GLUE_INFO *prGlueInfo, + OUT void *prBuf, IN uint32_t u4Offset, + OUT uint32_t *pu4Size); + +extern uint32_t kalFirmwareClose( + IN struct GLUE_INFO *prGlueInfo); + +extern void wlanWakeLockInit( + struct GLUE_INFO *prGlueInfo); + +extern void wlanWakeLockUninit( + struct GLUE_INFO *prGlueInfo); + +extern struct wireless_dev *wlanNetCreate( + void *pvData, + void *pvDriverData); + +extern void wlanNetDestroy( + struct wireless_dev *prWdev); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#if (CFG_DOWNLOAD_DYN_MEMORY_MAP == 1) +uint32_t soc3_0_DownloadByDynMemMap(IN struct ADAPTER *prAdapter, + IN uint32_t u4Addr, IN uint32_t u4Len, + IN uint8_t *pucStartPtr, IN enum ENUM_IMG_DL_IDX_T eDlIdx); +#endif +void soc3_0_DumpWfsyscpupcr(struct ADAPTER *prAdapter); +void soc3_0_WfdmaAxiCtrl(struct ADAPTER *prAdapter); + +int hifWmmcuPwrOn(void); +int hifWmmcuPwrOff(void); +int wf_ioremap_read(size_t addr, unsigned int *val); + +int wf_ioremap_write(phys_addr_t addr, unsigned int val); +int soc3_0_Trigger_fw_assert(void); +int soc3_0_CheckBusHang(void *adapter, + uint8_t ucWfResetEnable); +void soc3_0_DumpBusHangCr(struct ADAPTER *prAdapter); + +void wlanCoAntWiFi(void); +void wlanCoAntMD(void); +void wlanCoAntVFE28En(IN struct ADAPTER *prAdapter); +void wlanCoAntVFE28Dis(void); + +#if (CFG_SUPPORT_CONNINFRA == 1) +int wlanConnacPccifon(void); +int wlanConnacPccifoff(void); +int soc3_0_Trigger_whole_chip_rst(char *reason); +void soc3_0_Sw_interrupt_handler(struct ADAPTER *prAdapter); +void soc3_0_Conninfra_cb_register(void); +extern void update_driver_reset_status(uint8_t fgIsResetting); +extern int32_t get_wifi_process_status(void); +extern int32_t get_wifi_powered_status(void); +extern void update_pre_cal_status(uint8_t fgIsPreCal); +extern int8_t get_pre_cal_status(void); +#endif +void soc3_0_DumpWfsysdebugflag(void); +#if (CFG_POWER_ON_DOWNLOAD_EMI_ROM_PATCH == 1) +void soc3_0_ConstructFirmwarePrio(struct GLUE_INFO *prGlueInfo, + uint8_t **apucNameTable, uint8_t **apucName, + uint8_t *pucNameIdx, uint8_t ucMaxNameIdx); +void * +soc3_0_kalFirmwareImageMapping(IN struct GLUE_INFO *prGlueInfo, + OUT void **ppvMapFileBuf, OUT uint32_t *pu4FileLength, + IN enum ENUM_IMG_DL_IDX_T eDlIdx); +uint32_t soc3_0_wlanImageSectionDownloadStage( + IN struct ADAPTER *prAdapter, IN void *pvFwImageMapFile, + IN uint32_t u4FwImageFileLength, IN uint8_t ucSectionNumber, + IN enum ENUM_IMG_DL_IDX_T eDlIdx); +uint32_t soc3_0_wlanPowerOnDownload( + IN struct ADAPTER *prAdapter, + IN uint8_t ucDownloadItem); +int32_t soc3_0_wlanPowerOnInit( + enum ENUM_WLAN_POWER_ON_DOWNLOAD eDownloadItem); +#endif + +#if (CFG_SUPPORT_PRE_ON_PHY_ACTION == 1) +uint32_t soc3_0_wlanPhyAction(IN struct ADAPTER *prAdapter); +int soc3_0_wlanPreCalPwrOn(void); +int soc3_0_wlanPreCal(void); +uint8_t *soc3_0_wlanGetCalResult(uint32_t *prCalSize); +void soc3_0_wlanCalDebugCmd(uint32_t cmd, uint32_t para); +#endif /* (CFG_SUPPORT_PRE_ON_PHY_ACTION == 1) */ + +void soc3_0_icapRiseVcoreClockRate(void); +void soc3_0_icapDownVcoreClockRate(void); + +#endif /* _SOC3_0_H */ + +#endif /* soc3_0 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/wf_ple.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/wf_ple.h new file mode 100644 index 0000000000000..97d81df161a2f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/chips/wf_ple.h @@ -0,0 +1,233 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + wf_ple.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ------------------------------------- +*/ + +#ifndef __WF_PLE_H__ +#define __WF_PLE_H__ + +#define PLE_BASE 0x8000 + + +/* PLE Buffer Control Register */ +#define PLE_PBUF_CTRL (PLE_BASE + 0x14) +#define PLE_TOTAL_PAGE_NUM_MASK (0xfff) +#define PLE_GET_TOTAL_PAGE_NUM(p) (((p) & 0xfff)) +#define PLE_TOTAL_PAGE_CFG_MASK (0xf << 16) +#define PLE_GET_TOTAL_PAGE_CFG(p) (((p) & PSE_TOTAL_PAGE_CFG_MASK) >> 16) +#define PLE_PBUF_OFFSET_MASK (0xf << 20) +#define GET_PLE_PBUF_OFFSET(p) (((p) & PSE_PBUF_OFFSET_MASK) >> 20) + + +/* Release Control */ +#define PLE_RELEASE_CTRL (PLE_BASE + 0x30) +#define PLE_NORMAL_TX_RLS_QID_MASK (0x1f) +#define GET_PLE_NORMAL_TX_RLS_QID(p) (((p) & GET_FIRST_FID_MASK)) +#define PLE_NORMAL_TX_RLS_PID_MASK (0x3 << 6) +#define GET_PLE_NORMAL_TX_RLS_PID(p) (((p) & PLE_NORMAL_TX_RLS_PID_MASK) >> 6) + +#define BCNx_RLS_QID_MASK (0x1f) +#define BCNx_RLS_PID_MASK (0x3) +#define SET_BCN0_RLS_QID(p) (((p) & BCNx_RLS_QID_MASK) << 16) +#define SET_BCN0_RLS_PID(p) (((p) & BCNx_RLS_PID_MASK) << 22) +#define SET_BCN1_RLS_QID(p) (((p) & BCNx_RLS_QID_MASK) << 24) +#define SET_BCN1_RLS_PID(p) (((p) & BCNx_RLS_PID_MASK) << 30) + +#define PLE_GC (PLE_BASE) +#define PLE_INT_STS (PLE_BASE + 0x24) +#define PLE_INT_ERR_STS (PLE_BASE + 0x28) +#define PLE_QUEUE_CMD_ERR_STS (PLE_BASE + 0x550) + +/* HIF Report Control */ +#define PLE_HIF_REPORT (PLE_BASE + 0x34) + +/* CPU Interface get frame ID Control */ +#define PLE_C_GET_FID_0 (PLE_BASE + 0x40) + +/* CPU Interface get frame ID Control */ +#define PLE_C_GET_FID_1 (PLE_BASE + 0x44) + +#define PLE_C_EN_QUEUE_0 (PLE_BASE + 0x60) +#define PLE_C_EN_QUEUE_1 (PLE_BASE + 0x64) +#define PLE_C_EN_QUEUE_2 (PLE_BASE + 0x68) + +#define PLE_C_DE_QUEUE_0 (PLE_BASE + 0x80) +#define PLE_C_DE_QUEUE_1 (PLE_BASE + 0x84) +#define PLE_C_DE_QUEUE_2 (PLE_BASE + 0x88) +#define PLE_C_DE_QUEUE_3 (PLE_BASE + 0x8c) + +#define PLE_TO_N9_INT (PLE_BASE + 0xf0) +#define PLE_TO_N9_INT_TOGGLE_MASK 0x80000000 + + + +/* Queue Empty */ +#define PLE_QUEUE_EMPTY (PLE_BASE + 0xb0) +#define PLE_AC0_QUEUE_EMPTY_0 (PLE_BASE + 0x300) +#define PLE_AC0_QUEUE_EMPTY_1 (PLE_BASE + 0x304) +#define PLE_AC0_QUEUE_EMPTY_2 (PLE_BASE + 0x308) +#define PLE_AC0_QUEUE_EMPTY_3 (PLE_BASE + 0x30c) + +#define PLE_AC1_QUEUE_EMPTY_0 (PLE_BASE + 0x310) +#define PLE_AC1_QUEUE_EMPTY_1 (PLE_BASE + 0x314) +#define PLE_AC1_QUEUE_EMPTY_2 (PLE_BASE + 0x318) +#define PLE_AC1_QUEUE_EMPTY_3 (PLE_BASE + 0x31c) + +#define PLE_AC2_QUEUE_EMPTY_0 (PLE_BASE + 0x320) +#define PLE_AC2_QUEUE_EMPTY_1 (PLE_BASE + 0x324) +#define PLE_AC2_QUEUE_EMPTY_2 (PLE_BASE + 0x328) +#define PLE_AC2_QUEUE_EMPTY_3 (PLE_BASE + 0x32c) + +#define PLE_AC3_QUEUE_EMPTY_0 (PLE_BASE + 0x330) +#define PLE_AC3_QUEUE_EMPTY_1 (PLE_BASE + 0x334) +#define PLE_AC3_QUEUE_EMPTY_2 (PLE_BASE + 0x338) +#define PLE_AC3_QUEUE_EMPTY_3 (PLE_BASE + 0x33c) + +#define PLE_STATION_PAUSE0 (PLE_BASE + 0x360) +#define PLE_STATION_PAUSE1 (PLE_BASE + 0x364) +#define PLE_STATION_PAUSE2 (PLE_BASE + 0x368) +#define PLE_STATION_PAUSE3 (PLE_BASE + 0x36C) + +/* Page Flow Control */ +#define PLE_FREEPG_CNT (PLE_BASE + 0x100) + +#define PLE_FREEPG_HEAD_TAIL (PLE_BASE + 0x104) + +#define PLE_PG_HIF_GROUP (PLE_BASE + 0x110) +#define PLE_HIF_PG_INFO (PLE_BASE + 0x114) + +#define PLE_PG_CPU_GROUP (PLE_BASE + 0x150) +#define PLE_CPU_PG_INFO (PLE_BASE + 0x154) + + +/* Indirect path for read/write */ +#define PLE_FL_QUE_CTRL_0 (PLE_BASE + 0x1b0) +#define PLE_FL_QUE_CTRL_1 (PLE_BASE + 0x1b4) +#define PLE_FL_QUE_CTRL_2 (PLE_BASE + 0x1b8) +#define PLE_FL_QUE_CTRL_3 (PLE_BASE + 0x1bc) +#define PLE_PL_QUE_CTRL_0 (PLE_BASE + 0x1c0) + +/* Disable Station control */ +#define DIS_STA_MAP0 (PLE_BASE + 0x260) +#define DIS_STA_MAP1 (PLE_BASE + 0x264) +#define DIS_STA_MAP2 (PLE_BASE + 0x268) +#define DIS_STA_MAP3 (PLE_BASE + 0x26c) + +/* Station Pause control register */ +#define STATION_PAUSE0 (PLE_BASE + 0x360) +#define STATION_PAUSE1 (PLE_BASE + 0x364) +#define STATION_PAUSE2 (PLE_BASE + 0x368) +#define STATION_PAUSE3 (PLE_BASE + 0x36c) + +#define PLE_PEEK_CR_0 (PLE_BASE + 0x3d0) +#define PLE_PEEK_CR_OFFSET 0x4 +#define PLE_PEEK_CR_NUM 12 + +/* VOW Ctrl */ +#define VOW_RESET_DISABLE (1 << 26) +#define STA_MAX_DEFICIT_MASK (0x0000FFFF) +#define VOW_DBDC_BW_GROUP_CTRL (PLE_BASE + 0x2ec) +#define VOW_CONTROL (PLE_BASE + 0x370) +#define AIRTIME_DRR_SIZE (PLE_BASE + 0x374) + +#define PLE_PAYLOAD_BASE 0xA0000000 + +enum ENUM_UMAC_PORT { + ENUM_UMAC_HIF_PORT_0 = 0, + ENUM_UMAC_CPU_PORT_1 = 1, + ENUM_UMAC_LMAC_PORT_2 = 2, + ENUM_PLE_CTRL_PSE_PORT_3 = 3, + ENUM_UMAC_PSE_PLE_PORT_TOTAL_NUM = 4 +}; + +/* N9 MCU QUEUE LIST */ +enum ENUM_UMAC_CPU_P_QUEUE { + ENUM_UMAC_CTX_Q_0 = 0, + ENUM_UMAC_CTX_Q_1 = 1, + ENUM_UMAC_CTX_Q_2 = 2, + ENUM_UMAC_CTX_Q_3 = 3, + ENUM_UMAC_CRX = 0, + ENUM_UMAC_CIF_QUEUE_TOTAL_NUM = 4 +}; + + +/* LMAC PLE TX QUEUE LIST */ +enum ENUM_UMAC_LMAC_PLE_TX_P_QUEUE { + ENUM_UMAC_LMAC_PLE_TX_Q_00 = 0x00, + ENUM_UMAC_LMAC_PLE_TX_Q_01 = 0x01, + ENUM_UMAC_LMAC_PLE_TX_Q_02 = 0x02, + ENUM_UMAC_LMAC_PLE_TX_Q_03 = 0x03, + + ENUM_UMAC_LMAC_PLE_TX_Q_10 = 0x04, + ENUM_UMAC_LMAC_PLE_TX_Q_11 = 0x05, + ENUM_UMAC_LMAC_PLE_TX_Q_12 = 0x06, + ENUM_UMAC_LMAC_PLE_TX_Q_13 = 0x07, + + ENUM_UMAC_LMAC_PLE_TX_Q_20 = 0x08, + ENUM_UMAC_LMAC_PLE_TX_Q_21 = 0x09, + ENUM_UMAC_LMAC_PLE_TX_Q_22 = 0x0a, + ENUM_UMAC_LMAC_PLE_TX_Q_23 = 0x0b, + + ENUM_UMAC_LMAC_PLE_TX_Q_30 = 0x0c, + ENUM_UMAC_LMAC_PLE_TX_Q_31 = 0x0d, + ENUM_UMAC_LMAC_PLE_TX_Q_32 = 0x0e, + ENUM_UMAC_LMAC_PLE_TX_Q_33 = 0x0f, + + ENUM_UMAC_LMAC_PLE_TX_Q_ALTX_0 = 0x10, + ENUM_UMAC_LMAC_PLE_TX_Q_BMC_0 = 0x11, + ENUM_UMAC_LMAC_PLE_TX_Q_BNC_0 = 0x12, + ENUM_UMAC_LMAC_PLE_TX_Q_PSMP_0 = 0x13, + + ENUM_UMAC_LMAC_PLE_TX_Q_ALTX_1 = 0x14, + ENUM_UMAC_LMAC_PLE_TX_Q_BMC_1 = 0x15, + ENUM_UMAC_LMAC_PLE_TX_Q_BNC_1 = 0x16, + ENUM_UMAC_LMAC_PLE_TX_Q_PSMP_1 = 0x17, + ENUM_UMAC_LMAC_PLE_TX_Q_NAF = 0x18, + ENUM_UMAC_LMAC_PLE_TX_Q_NBCN = 0x19, +/* DE suggests not to use 0x1f, it's only for hw free queue */ + ENUM_UMAC_LMAC_PLE_TX_Q_RELEASE = 0x1f, + ENUM_UMAC_LMAC_QUEUE_TOTAL_NUM = 24, + +}; + +/* LMAC PLE For PSE Control P3 */ +enum ENUM_UMAC_PLE_CTRL_P3_QUEUE { + ENUM_UMAC_PLE_CTRL_P3_Q_0X1E = 0x1e, + ENUM_UMAC_PLE_CTRL_P3_Q_0X1F = 0x1f, + ENUM_UMAC_PLE_CTRL_P3_TOTAL_NUM = 2 +}; + + + +struct EMPTY_QUEUE_INFO { + int8_t *QueueName; + uint32_t Portid; + uint32_t Queueid; +}; + + +#endif /* __WF_PLE_H__ */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/config.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/config.h new file mode 100644 index 0000000000000..5b1b8921c5d11 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/config.h @@ -0,0 +1,1490 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/config.h#3 + */ + +/*! \file "config.h" + * \brief This file includes the various configurable parameters for + * customers + * + * This file ncludes the configurable parameters except the parameters + * indicate the turning-on/off of some features + */ + +#ifndef _CONFIG_H +#define _CONFIG_H + +#include + +/******************************************************************************* + * C O M P I L E 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 + ******************************************************************************* + */ +/* 2 Flags for OS capability */ + +#if defined(_HIF_SDIO) +/* #ifdef CONFIG_X86 */ +/*Kernel-3.10-ARM did not provide X86_FLAG & HIF shouldn't bind platform*/ +#if (CFG_MTK_ANDROID_WMT) +#define MTK_WCN_HIF_SDIO 1 +#else +#define MTK_WCN_HIF_SDIO 0 +#endif +#else +#define MTK_WCN_HIF_SDIO 0 +#endif + +#if defined(_HIF_AXI) +#ifdef LINUX +#ifdef CONFIG_X86 +#define MTK_WCN_HIF_AXI 0 +#else +#define MTK_WCN_HIF_AXI 1 +#endif +#else +#define MTK_WCN_HIF_AXI 0 +#endif +#else +#define MTK_WCN_HIF_AXI 0 +#endif + + + +/* Android build-in driver switch, Mike 2016/11/11*/ +#ifndef CFG_BUILT_IN_DRIVER +#define CFG_BUILT_IN_DRIVER 0 +#endif + +/* Mike 2016/09/01 ALPS update K3.18 80211_disconnect to K4.4 version*/ +/* work around for any alps K3.18 platform*/ +#ifndef CFG_WPS_DISCONNECT +#define CFG_WPS_DISCONNECT 0 +#endif + + +#if (CFG_SUPPORT_AEE == 1) +/* TODO: temp remove for 7663 on mobile */ +/* #define CFG_ENABLE_AEE_MSG 1 */ +#define CFG_ENABLE_AEE_MSG 0 +#else +#define CFG_ENABLE_AEE_MSG 0 +#endif + +#define CFG_ENABLE_EARLY_SUSPEND 0 +#define CFG_ENABLE_NET_DEV_NOTIFY 1 + +/* 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" */ +#define CFG_SUPPORT_DEBUG_FS 0 +#define CFG_SUPPORT_SET_CAM_BY_PROC 1 /*Enable/disable powersave mode*/ + +#ifndef LINUX +#define CFG_FW_FILENAME L"WIFI_RAM_CODE" +#define CFG_CR4_FW_FILENAME L"WIFI_RAM_CODE2" +#else +#define CFG_FW_FILENAME "WIFI_RAM_CODE" +#define CFG_CR4_FW_FILENAME "WIFI_RAM_CODE2" +#endif + +#ifndef CFG_MET_PACKET_TRACE_SUPPORT +#define CFG_MET_PACKET_TRACE_SUPPORT 0 /*move to wlan/MAKEFILE */ +#endif + +#ifndef CFG_MET_TAG_SUPPORT +#define CFG_MET_TAG_SUPPORT 0 +#endif + +#ifndef CFG_SUPPORT_PERF_IND +#define CFG_SUPPORT_PERF_IND 1 +#endif + +/* Support AP Selection */ +#define CFG_SUPPORT_RSN_SCORE 0 +#define CFG_SELECT_BSS_BASE_ON_MULTI_PARAM 1 +#define CFG_MAX_NUM_OF_CHNL_INFO 50 +#define CFG_SUPPORT_CHNL_CONFLICT_REVISE 0 + + +/*------------------------------------------------------------------------------ + * Driver config + *------------------------------------------------------------------------------ + */ + +#ifndef LINUX +#define CFG_SUPPORT_CFG_FILE 0 +#else +#define CFG_SUPPORT_CFG_FILE 1 +#endif + +/*!< 1(default): Enable 802.11d */ +#define CFG_SUPPORT_802_11D 1 +/* 0: Disable */ + +/* Radio Reasource Measurement (802.11k) */ +#define CFG_SUPPORT_RRM 0 + +/* DFS (802.11h) */ +#define CFG_SUPPORT_DFS 1 +#ifndef CFG_SUPPORT_DFS_MASTER +#define CFG_SUPPORT_DFS_MASTER 1 +/* SoftAp Cross Band Channel Switch */ +#define CFG_SUPPORT_IDC_CH_SWITCH 1 +#endif + +#if (CFG_SUPPORT_DFS == 1) /* Add by Enlai */ +/* Quiet (802.11h) */ +#define CFG_SUPPORT_QUIET 0 +/* Spectrum Management (802.11h): TPC and DFS */ +#define CFG_SUPPORT_SPEC_MGMT 1 +#else +/* Quiet (802.11h) */ +#define CFG_SUPPORT_QUIET 0 +/* Spectrum Management (802.11h): TPC and DFS */ +#define CFG_SUPPORT_SPEC_MGMT 0 +#endif + +/* 11n feature. RX RDG capability */ +#define CFG_SUPPORT_RX_RDG 0 + +/* 802.11n MCS Feedback responder */ +#define CFG_SUPPORT_MFB 0 + +/* 802.11n RX STBC (1SS) */ +#define CFG_SUPPORT_RX_STBC 1 + +/* 802.11n RX short GI for both 20M and 40M BW */ +#define CFG_SUPPORT_RX_SGI 1 + +/* 802.11n RX HT green-field capability */ +#define CFG_SUPPORT_RX_HT_GF 1 + +#define CFG_SUPPORT_BFER 0 +#define CFG_SUPPORT_BFEE 1 +/* Enable Bfee only when AP's Nss > STA's Nss */ +#define CFG_SUPPORT_CONDITIONAL_BFEE 1 + +#define CFG_SUPPORT_WAPI 1 + +/* Enable QA Tool Support */ +#define CFG_SUPPORT_QA_TOOL 1 + +/* Enable TX BF Support */ +#define CFG_SUPPORT_TX_BF 1 + +#define CFG_SUPPORT_TX_BF_FPGA 1 + +/* Enable MU MIMO Support */ +#define CFG_SUPPORT_MU_MIMO 1 + +/* Enable WOW Support */ +#define CFG_WOW_SUPPORT 1 + +/* Enable A-MSDU RX Reordering Support */ +#define CFG_SUPPORT_RX_AMSDU 1 + +/* Enable Android wake_lock operations */ +#ifndef CFG_ENABLE_WAKE_LOCK +#define CFG_ENABLE_WAKE_LOCK 1 +#endif + +#define CFG_SUPPORT_OSHARE 1 + +#define CFG_SUPPORT_LOWLATENCY_MODE 1 + +#define CFG_SUPPORT_ANT_SWAP 1 + +/* If skb_buff mark field marked with pre-defined value, change priority to VO*/ +#define CFG_CHANGE_PRIORITY_BY_SKB_MARK_FIELD 1 + +#if KERNEL_VERSION(4, 4, 0) <= LINUX_VERSION_CODE +#define CFG_SUPPORT_DATA_STALL 1 +#define CFG_SUPPORT_BIGDATA_PIP 1 +#else +#define CFG_SUPPORT_DATA_STALL 0 +#define CFG_SUPPORT_BIGDATA_PIP 0 +#endif + +#define CFG_SUPPORT_HE_ER 1 + +/*------------------------------------------------------------------------------ + * Flags of Buffer mode SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_BUFFER_MODE 1 + +/*------------------------------------------------------------------------------ + * SLT Option + *------------------------------------------------------------------------------ + */ +#define CFG_SLT_SUPPORT 0 + +#ifdef NDIS60_MINIPORT +#define CFG_NATIVE_802_11 1 + +#define CFG_TX_MAX_PKT_SIZE 2304 + +/* !< 1: Enable TCP/IP header checksum offload */ +#define CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 0 + +/* 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 +#define CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 0 +#define CFG_TX_MAX_PKT_SIZE 1600 +#define CFG_NATIVE_802_11 0 +#endif + +/* By using GRO at NAPI level, the driver is doing the aggregation to a large + * SKB very early, right at the receive completion handler. This means that all + * the next functions in the receive stack do much less processing. + * The GRO feature could enhance "Rx" tput. + */ +#define CFG_SUPPORT_RX_GRO 1 + +/* 2 Flags for Driver Parameters */ +/*------------------------------------------------------------------------------ + * Flags for EHPI Interface in Colibri Platform + *------------------------------------------------------------------------------ + */ +/*!< 1: Do workaround for faster bus timing */ +/* 0(default): Disable */ +#define CFG_EHPI_FASTER_BUS_TIMING 0 + +/*------------------------------------------------------------------------------ + * Flags for UMAC + *------------------------------------------------------------------------------ + */ +#define CFG_UMAC_GENERATION 0x20 + +/*------------------------------------------------------------------------------ + * Flags for HIFSYS Interface + *------------------------------------------------------------------------------ + */ +#ifdef _lint +/* #define _HIF_SDIO 1 */ +#endif + +/* 1(default): Enable SDIO ISR & TX/RX status enhance mode + * 0: Disable + */ +#define CFG_SDIO_INTR_ENHANCE 1 +/* 1(default): Enable SDIO ISR & TX/RX status enhance mode + * 0: Disable + */ +#define CFG_SDIO_RX_ENHANCE 1 +/* 1: Enable SDIO TX enhance mode(Multiple frames in single BLOCK CMD) + * 0(default): Disable + */ +#define CFG_SDIO_TX_AGG 1 + +/* 1: Enable SDIO RX enhance mode(Multiple frames in single BLOCK CMD) + * 0(default): Disable + */ +#define CFG_SDIO_RX_AGG 1 + +/* 1: Enable SDIO RX Tasklet De-Aggregation + * 0(default): Disable + */ +#ifndef CFG_SDIO_RX_AGG_TASKLET +#define CFG_SDIO_RX_AGG_TASKLET 0 +#endif + +#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 + +#ifdef WINDOWS_CE +/*!< 1: Support pass through (PATHRU) mode */ +#define CFG_SDIO_PATHRU_MODE 1 +/* 0: Disable */ +#else +/*!< 0: Always disable if WINDOWS_CE is not defined */ +#define CFG_SDIO_PATHRU_MODE 0 +#endif + +#define CFG_SDIO_ACCESS_N9_REGISTER_BY_MAILBOX 0 +#define CFG_MAX_RX_ENHANCE_LOOP_COUNT 3 + +#define CFG_USB_TX_AGG 1 +#define CFG_USB_CONSISTENT_DMA 0 +#define CFG_USB_TX_HANDLE_IN_HIF_THREAD 0 +#define CFG_USB_RX_HANDLE_IN_HIF_THREAD 0 + +#ifndef CFG_TX_DIRECT_USB +#define CFG_TX_DIRECT_USB 1 +#endif +#ifndef CFG_RX_DIRECT_USB +#define CFG_RX_DIRECT_USB 1 +#endif + +#define CFG_HW_WMM_BY_BSS 1 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Integration + *------------------------------------------------------------------------------ + */ + +#define CFG_MULTI_ECOVER_SUPPORT 1 + +#define CFG_ENABLE_CAL_LOG 1 +#define CFG_REPORT_RFBB_VERSION 1 + +#define MAX_BSSID_NUM 4 /* MAX BSSID number */ + +#define CFG_CHIP_RESET_SUPPORT 1 + +#if CFG_CHIP_RESET_SUPPORT +#define CFG_CHIP_RESET_HANG 0 +#else +#define CFG_CHIP_RESET_HANG 0 +#endif + +#define HW_BSSID_NUM 4 /* HW BSSID number by chip */ + +/*------------------------------------------------------------------------------ + * Flags for workaround + *------------------------------------------------------------------------------ + */ + +/*------------------------------------------------------------------------------ + * Flags for driver version + *------------------------------------------------------------------------------ + */ +#define CFG_DRV_OWN_VERSION ((uint16_t)((NIC_DRIVER_MAJOR_VERSION << 8) | \ + (NIC_DRIVER_MINOR_VERSION))) +#define CFG_DRV_PEER_VERSION ((uint16_t)0x0000) + +/*------------------------------------------------------------------------------ + * Flags and Parameters for TX path + *------------------------------------------------------------------------------ + */ + +/*! Maximum number of SW TX packet queue */ +#if (CFG_SUPPORT_CONNAC2X == 1) +#define CFG_TX_MAX_PKT_NUM 2048 +#else +#define CFG_TX_MAX_PKT_NUM 1024 +#endif + +/*! Maximum number of SW TX CMD packet buffer */ +#define CFG_TX_MAX_CMD_PKT_NUM 32 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for RX path + *------------------------------------------------------------------------------ + */ + +/*------------------------------------------------------------------------------ + * CONFIG_TITLE : Move BA from FW to Driver + * OWNER : Puff Wen + * Description : Move BA from FW to Driver + *------------------------------------------------------------------------------ + */ +#define CFG_M0VE_BA_TO_DRIVER 0 + +/*! 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 HIF_NUM_OF_QM_RX_PKT_NUM + +/*! 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 */ +/* TODO: it should be 4096 under emulation mode */ +#define CFG_RX_MAX_PKT_SIZE (28 + 2312 + 12 /*HIF_RX_HEADER_T*/) + +/*! 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 */ + +/*! RX BA capability */ +#define CFG_NUM_OF_RX_BA_AGREEMENTS 80 +#if CFG_M0VE_BA_TO_DRIVER +#define CFG_RX_BA_MAX_WINSIZE 64 +#endif +#define CFG_RX_BA_INC_SIZE 64 +#define CFG_RX_MAX_BA_TID_NUM 8 +#define CFG_RX_REORDERING_ENABLED 1 + +#define CFG_PF_ARP_NS_MAX_NUM 3 + +#define CFG_COMPRESSION_DEBUG 0 +#define CFG_DECOMPRESSION_TMP_ADDRESS 0 +#define CFG_SUPPORT_COMPRESSION_FW_OPTION 0 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for CMD/RESPONSE + *------------------------------------------------------------------------------ + */ +/* WMT expects wlan driver on/off to be completed within 4s. + * To avoid on/off timeout, only polling ready bit in 1s + * (CFG_RESPONSE_POLLING_TIMEOUT * CFG_RESPONSE_POLLING_DELAY). + */ +#if CFG_MTK_ANDROID_WMT +#define CFG_RESPONSE_POLLING_TIMEOUT 200 +#else +#define CFG_RESPONSE_POLLING_TIMEOUT 1000 +#endif +#define CFG_RESPONSE_POLLING_DELAY 5 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Protocol Stack + *------------------------------------------------------------------------------ + */ +/*! Maximum number of BSS in the SCAN list */ +#define CFG_MAX_NUM_BSS_LIST 192 + +#define CFG_MAX_COMMON_IE_BUF_LEN ((1500 * CFG_MAX_NUM_BSS_LIST) / 3) + +/*! Maximum size of Header buffer of each SCAN record */ +#define CFG_RAW_BUFFER_SIZE 1024 + +/*! Maximum size of IE buffer of each SCAN record */ +#define CFG_IE_BUFFER_SIZE 512 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Power management + *------------------------------------------------------------------------------ + */ +#define CFG_ENABLE_FULL_PM 1 +#define CFG_ENABLE_WAKEUP_ON_LAN 0 + +/* debug which packet wake up host */ +#define CFG_SUPPORT_WAKEUP_REASON_DEBUG 1 + +#define CFG_INIT_POWER_SAVE_PROF ENUM_PSP_FAST_SWITCH + +#define CFG_INIT_ENABLE_PATTERN_FILTER_ARP 0 + +/* (BIT(3) | BIT(2) | BIT(1) | BIT(0)) */ +#define CFG_INIT_UAPSD_AC_BMP 0 + +/* #define CFG_SUPPORT_WAPI 0 */ +#define CFG_SUPPORT_WPS 1 +#define CFG_SUPPORT_WPS2 1 + +/*------------------------------------------------------------------------------ + * Flags 1: drop all multicast packets when device suspend + * Flags 0: drop multicast packets except white list when device suspend + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_DROP_ALL_MC_PACKET 0 + +/*------------------------------------------------------------------------------ + * Auto Channel Selection maximun channel number + *------------------------------------------------------------------------------ + */ +/* ARRAY_SIZE(mtk_5ghz_channels) + ARRAY_SIZE(mtk_2ghz_channels) */ +#define MAX_CHN_NUM 39 + +#define MAX_2G_BAND_CHN_NUM 14 +#define MAX_5G_BAND_CHN_NUM (MAX_CHN_NUM - MAX_2G_BAND_CHN_NUM) +#define ACS_PRINT_BUFFER_LEN 200 + +/*------------------------------------------------------------------------------ + * 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) + +/*------------------------------------------------------------------------------ + * Maximum scan SSID number and channel number + * Should be aligned with FW scan command + *------------------------------------------------------------------------------ + */ +#define SCAN_CMD_SSID_NUM (4) +#define SCAN_CMD_CHNL_NUM (32) + +#if 0 +/* to be compatible with old FW, we set ssid num to 0 here, + * we should set correct num when query of scan capability from FW is done + */ +#define SCAN_CMD_EXT_SSID_NUM (0) +#define SCAN_CMD_EXT_CHNL_NUM (0) +#else +#define SCAN_CMD_EXT_SSID_NUM (6) +#define SCAN_CMD_EXT_CHNL_NUM (32) +#endif +#define CFG_SCAN_SSID_MAX_NUM (SCAN_CMD_SSID_NUM+SCAN_CMD_EXT_SSID_NUM) +#define MAXIMUM_OPERATION_CHANNEL_LIST (SCAN_CMD_CHNL_NUM+SCAN_CMD_EXT_CHNL_NUM) + + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Load Setup Default + *------------------------------------------------------------------------------ + */ + +/*------------------------------------------------------------------------------ + * Flags for enable 802.11A Band setting + *------------------------------------------------------------------------------ + */ + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Interrupt Process + *------------------------------------------------------------------------------ + */ +#define CFG_IST_LOOP_COUNT HIF_IST_LOOP_COUNT + +#define CFG_INT_WRITE_CLEAR 0 + +/* 2 Flags for Driver Debug Options */ +/*------------------------------------------------------------------------------ + * Flags of TX Debug Option. NOTE(Kevin): Confirm with SA before modifying + * following flags. + *------------------------------------------------------------------------------ + */ +/*!< 1: Debug statistics usage of MGMT Buffer */ +/* 0: Disable */ +#define CFG_DBG_MGT_BUF 1 + +#define CFG_HIF_STATISTICS 0 + +#define CFG_HIF_RX_STARVATION_WARNING 0 + +#define CFG_RX_PKTS_DUMP 0 + +#define CFG_SUPPORT_STATISTICS 1 + +#define CFG_ASSERT_DUMP 1 + +#define CFG_SUPPORT_TRACE_TC4 1 +/*------------------------------------------------------------------------------ + * Flags of Firmware Download Option. + *------------------------------------------------------------------------------ + */ +#define CFG_ENABLE_FW_DOWNLOAD 1 + +#define CFG_ENABLE_FW_DOWNLOAD_ACK 1 + +#ifndef CFG_WIFI_IP_SET +#define CFG_WIFI_IP_SET 1 +#endif + +/*------------------------------------------------------------------------------ + * Flags of Bluetooth-over-WiFi (BT 3.0 + HS) support + *------------------------------------------------------------------------------ + */ + +#define CFG_ENABLE_BT_OVER_WIFI 0 + +#define CFG_BOW_SEPARATE_DATA_PATH 1 + +#define CFG_BOW_PHYSICAL_LINK_NUM 4 + +#define CFG_BOW_LIMIT_AIS_CHNL 1 + +#define CFG_BOW_SUPPORT_11N 1 + +#define CFG_BOW_RATE_LIMITATION 1 + +/*------------------------------------------------------------------------------ + * Flags of Wi-Fi Direct support + *------------------------------------------------------------------------------ + */ +/*------------------------------------------------------------------------------ + * Support reporting all BSS networks to cfg80211 kernel when scan + * request is from P2P interface + * Originally only P2P networks will be reported when scan request is from p2p0 + *------------------------------------------------------------------------------ + */ +#ifndef CFG_P2P_SCAN_REPORT_ALL_BSS +#define CFG_P2P_SCAN_REPORT_ALL_BSS 0 +#endif + +/* Allow connection with no P2P IE device */ +#ifndef CFG_P2P_CONNECT_ALL_BSS +#define CFG_P2P_CONNECT_ALL_BSS 0 +#endif + +/* Allow setting max P2P GO client count */ +#ifndef CFG_P2P_DEFAULT_CLIENT_COUNT +#define CFG_P2P_DEFAULT_CLIENT_COUNT 0 +#endif + +/*------------------------------------------------------------------------------ + * Flags for GTK rekey offload + *------------------------------------------------------------------------------ + */ + +#ifdef LINUX +#ifdef CONFIG_X86 +#define CFG_ENABLE_WIFI_DIRECT 1 +#define CFG_SUPPORT_802_11W 1 +#define CONFIG_SUPPORT_GTK_REKEY 1 +#else +#define CFG_ENABLE_WIFI_DIRECT 1 + +/*!< 0(default): Disable 802.11W */ +#define CFG_SUPPORT_802_11W 1 + +#define CONFIG_SUPPORT_GTK_REKEY 1 +#endif +#else /* !LINUX */ +#define CFG_ENABLE_WIFI_DIRECT 0 +#define CFG_SUPPORT_802_11W 0 /* Not support at WinXP */ +#endif /* LINUX */ + +#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 + +#ifndef CONFIG_WLAN_DRV_BUILD_IN +#define CONFIG_WLAN_DRV_BUILD_IN 0 +#endif + +/* + * Enable cfg80211 option after Android 2.2(Froyo) is suggested, + * cfg80211 on linux 2.6.29 is not mature yet + */ +#define CFG_ENABLE_WIFI_DIRECT_CFG_80211 1 + +#define CFG_SUPPORT_HOTSPOT_OPTIMIZATION 0 +#define CFG_HOTSPOT_OPTIMIZATION_BEACON_INTERVAL 300 +#define CFG_HOTSPOT_OPTIMIZATION_DTIM 1 +#define CFG_AUTO_CHANNEL_SEL_SUPPORT 1 + +#define CFG_SUPPORT_SOFTAP_WPA3 1 + +#define CFG_HOTSPOT_SUPPORT_ADJUST_SCC 1 + +#if CFG_TC1_FEATURE +#define CFG_HOTSPOT_SUPPORT_FORCE_ACS_SCC 0 +#elif CFG_TC10_FEATURE +#define CFG_HOTSPOT_SUPPORT_FORCE_ACS_SCC 1 +#else +#define CFG_HOTSPOT_SUPPORT_FORCE_ACS_SCC 0 +#endif + +#ifndef CFG_ENABLE_UNIFY_WIPHY +#define CFG_ENABLE_UNIFY_WIPHY 1 +#endif + +#define CFG_ENABLE_OFFCHANNEL_TX 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 1000 + +/*------------------------------------------------------------------------------ + * Migration Option + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_ADHOC 1 +#define CFG_SUPPORT_AAA 1 + +#define CFG_SUPPORT_BCM 0 +#define CFG_SUPPORT_BCM_BWCS 0 +#define CFG_SUPPORT_BCM_BWCS_DEBUG 0 + +#define CFG_SUPPORT_RDD_TEST_MODE 0 + +#define CFG_SUPPORT_PWR_MGT 1 + +#define CFG_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_DETECT_SECURITY_MODE_CHANGE 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_TDLS 1 + +/* Enable/disable QoS TX, AMPDU */ +#define CFG_SUPPORT_QOS 1 + +#define CFG_SUPPORT_AMPDU_TX 1 +#define CFG_SUPPORT_AMPDU_RX 1 + +/* Enable/disable TS-related Action frames handling */ +#define CFG_SUPPORT_TSPEC 0 +#define CFG_SUPPORT_UAPSD 1 +#define CFG_SUPPORT_UL_PSMP 0 + +/* Roaming System */ +#ifndef CFG_SUPPORT_ROAMING +#define CFG_SUPPORT_ROAMING 1 +#endif + +#if (CFG_SUPPORT_ROAMING == 1) + +/* Roaming feature: skip roaming when only one ESSID AP + * Need Android background scan + * if no roaming event occurred + * to trigger roaming scan + * after skip roaming in one ESSID AP case + */ +#define CFG_SUPPORT_ROAMING_SKIP_ONE_AP 0 +#define CFG_SUPPORT_DRIVER_ROAMING 1 +#else +#define CFG_SUPPORT_ROAMING_SKIP_ONE_AP 0 +#define CFG_SUPPORT_DRIVER_ROAMING 0 + +#endif /* CFG_SUPPORT_ROAMING */ + +#define CFG_SUPPORT_SWCR 1 + +#define CFG_SUPPORT_ANTI_PIRACY 1 + +#define CFG_SUPPORT_OSC_SETTING 1 + +#define CFG_SUPPORT_P2P_RSSI_QUERY 0 + +#define CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP 0 + +#define CFG_SHOW_MACADDR_SOURCE 1 + +#define CFG_SHOW_FULL_MACADDR 1 + +#ifndef CFG_SUPPORT_VO_ENTERPRISE +#define CFG_SUPPORT_VO_ENTERPRISE 1 +#endif +#define CFG_SUPPORT_WMM_AC 1 +#if CFG_SUPPORT_VO_ENTERPRISE +#define CFG_SUPPORT_802_11R 1 +#define CFG_SUPPORT_802_11K 1 +#else +#define CFG_SUPPORT_802_11R 0 +#define CFG_SUPPORT_802_11K 0 +#endif +#define CFG_SUPPORT_MBO 1 + +#define CFG_SUPPORT_SUPPLICANT_SME 0 + +#if (CFG_SUPPORT_802_11K == 1) && (CFG_SUPPORT_SUPPLICANT_SME == 1) +/* Enable to do beacon reports by supplicant. + * Beacon report is a sub-feature of 802_11K(RRM) + * Supplicant only support RRM when SME supported. + */ +#define CFG_SUPPORT_RM_BEACON_REPORT_BY_SUPPLICANT 0 +#else +#define CFG_SUPPORT_RM_BEACON_REPORT_BY_SUPPLICANT 0 +#endif + +/* Support 802.11v Wireless Network Management */ +#ifndef CFG_SUPPORT_802_11V +#define CFG_SUPPORT_802_11V 1 +#endif +#if CFG_SUPPORT_802_11V +#define CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT 1 +#else +#define CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT 0 +#endif +#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 + +#define WNM_UNIT_TEST CFG_SUPPORT_802_11V + +#define CFG_SUPPORT_802_11V_MBSSID 0 +#if (CFG_SUPPORT_802_11AX == 1) +/*11v MBSSID is mandatory for 11ax*/ +#undef CFG_SUPPORT_802_11V_MBSSID +#define CFG_SUPPORT_802_11V_MBSSID 1 +#endif + +#define CFG_SUPPORT_PPR2 1 +#define CFG_DRIVER_COMPOSE_ASSOC_REQ 1 +#define CFG_SUPPORT_802_11AC 1 +#define CFG_STRICT_CHECK_CAPINFO_PRIVACY 0 + +#define CFG_SUPPORT_WFD 1 +#define CFG_SUPPORT_WFD_COMPOSE_IE 1 + +/* Support Customer vendor IE */ +#define CFG_SUPPORT_CUSTOM_VENDOR_IE 1 + +#define CFG_SUPPORT_HOTSPOT_WPS_MANAGER 1 +#define CFG_SUPPORT_NFC_BEAM_PLUS 1 + +/* Refer to CONFIG_MTK_STAGE_SCAN */ +#define CFG_MTK_STAGE_SCAN 1 + +/* Enable driver support multicore */ +#define CFG_SUPPORT_MULTITHREAD 1 + +#define CFG_SUPPORT_MTK_SYNERGY 1 + +#define CFG_SUPPORT_VHT_IE_IN_2G 1 + +#define CFG_SUPPORT_PWR_LIMIT_COUNTRY 1 + +#define CFG_SUPPORT_DYNAMIC_PWR_LIMIT 1 + +#define CFG_SUPPORT_ANT_SWAP 1 + +#define CFG_FIX_2_TX_PORT 0 + +#define CFG_CHANGE_CRITICAL_PACKET_PRIORITY 1 + +/*------------------------------------------------------------------------------ + * Flags of bus error tolerance + *------------------------------------------------------------------------------ + */ +#define CFG_FORCE_RESET_UNDER_BUS_ERROR 0 + +/*------------------------------------------------------------------------------ + * Build Date Code Integration + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_BUILD_DATE_CODE 0 + +/*------------------------------------------------------------------------------ + * Flags of SDIO test pattern support + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_SDIO_READ_WRITE_PATTERN 1 + +/*------------------------------------------------------------------------------ + * Flags of Workaround + *------------------------------------------------------------------------------ + */ +#define CFG_ENABLE_READ_EXTRA_4_BYTES 1 + +/* Handle IOT issue for 11ac certification */ +#define CFG_OPMODE_CONFLICT_OPINFO 1 + +/*------------------------------------------------------------------------------ + * Flags of Packet Lifetime Profiling Mechanism + *------------------------------------------------------------------------------ + */ +#define CFG_ENABLE_PKT_LIFETIME_PROFILE 1 +#define CFG_PRINT_PKT_LIFETIME_PROFILE 0 + +#define CFG_ENABLE_PER_STA_STATISTICS 1 + +#define CFG_ENABLE_PER_STA_STATISTICS_LOG 1 + +/*------------------------------------------------------------------------------ + * Flags for prepare the FW compile flag + *------------------------------------------------------------------------------ + */ +#define COMPILE_FLAG0_GET_STA_LINK_STATUS (1<<0) +#define COMPILE_FLAG0_WFD_ENHANCEMENT_PROTECT (1<<1) + +/*------------------------------------------------------------------------------ + * Flags of Batch Scan SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_BATCH_SCAN (0) +#define CFG_BATCH_MAX_MSCAN (2) + +/*------------------------------------------------------------------------------ + * Flags of SCHEDULE SCAN SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_SCHED_SCAN (1) +#define SCHED_SCAN_CMD_VERSION (1) + +/* this value should be aligned to auSsid in struct CMD_SCHED_SCAN_REQ */ +#define CFG_SCAN_HIDDEN_SSID_MAX_NUM (10) +/* this value should be aligned to auMatchSsid in struct CMD_SCHED_SCAN_REQ */ +#define CFG_SCAN_SSID_MATCH_MAX_NUM (16) + +/*------------------------------------------------------------------------------ + * Full2Partial Scan SUPPORT + *------------------------------------------------------------------------------ + */ +/* During a full2partial scan period, all online full scan requests would be + * changed to partial scan. The unit of this value is second + */ +#define CFG_SUPPORT_FULL2PARTIAL_SCAN (1) +#define CFG_SCAN_FULL2PARTIAL_PERIOD (60) + +/*------------------------------------------------------------------------------ + * Value of scan cache result + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_SCAN_CACHE_RESULT (1) +#define CFG_SCAN_CACHE_RESULT_PERIOD (7000) /* Unit: ms */ +#define CFG_SCAN_CACHE_MIN_CHANNEL_NUM (10) + +/*------------------------------------------------------------------------------ + * Default value: the duration in ms to check TRX + * while the beacon timeout event comes. + * This is the default value for + * prAdapter->rWifiVar.u4BeaconTimoutFilterDurationMs + * can customize + * 1. by project's requirement in this default value + * 2. or by define in wifi.cfg directly (BeaconTimoutFilterDurationMs) + * if the value set to 0, it means disable the filter. + * if the value set to 2000, it means the duration of fitler is 2000 ms + *------------------------------------------------------------------------------ + */ +#define CFG_BEACON_TIMEOUT_FILTER_DURATION_DEFAULT_VALUE 2000 + +/*------------------------------------------------------------------------------ + * Flags of Random MAC support + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_SCAN_RANDOM_MAC (1) + +/*------------------------------------------------------------------------------ + * Flags of Sniffer SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_SNIFFER 1 + +#define WLAN_INCLUDE_PROC 1 + +#if CFG_TC10_FEATURE +#define WLAN_INCLUDE_SYS 1 +#else +#define WLAN_INCLUDE_SYS 0 +#endif + +/*------------------------------------------------------------------------------ + * Flags of Sniffer SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_DUAL_P2PLIKE_INTERFACE 1 + +#define RUNNING_P2P_MODE 0 +#define RUNNING_AP_MODE 1 +#define RUNNING_DUAL_AP_MODE 2 +#define RUNNING_P2P_AP_MODE 3 +#define RUNNING_P2P_MODE_NUM 4 + +/*------------------------------------------------------------------------------ + * Flags of MSP SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_MSP 1 + + + +/*------------------------------------------------------------------------------ + * Flags of driver fw customization + *------------------------------------------------------------------------------ + */ + +#define CFG_SUPPORT_EASY_DEBUG 1 + + +/*------------------------------------------------------------------------------ + * Flags of driver delay calibration atfer efuse buffer mode CMD + *------------------------------------------------------------------------------ + */ + +#define CFG_EFUSE_BUFFER_MODE_DELAY_CAL 1 + +/*------------------------------------------------------------------------------ + * Flags of Drop Packet Replay SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_REPLAY_DETECTION 1 + +/*------------------------------------------------------------------------------ + * Flags of driver EEPROM pages for QA tool + *------------------------------------------------------------------------------ + */ + +#define CFG_EEPROM_PAGE_ACCESS 1 + +/*------------------------------------------------------------------------------ + * Flags for HOST_OFFLOAD + *------------------------------------------------------------------------------ + */ + +#define CFG_SUPPORT_WIFI_HOST_OFFLOAD 1 + +/*------------------------------------------------------------------------------ + * Flags for DBDC Feature + *------------------------------------------------------------------------------ + */ + +#define CFG_SUPPORT_DBDC 1 +#define CFG_SUPPORT_DBDC_NO_BLOCKING_OPMODE 1 +#define CFG_SUPPORT_SAP_DFS_CHANNEL 1 + +/*------------------------------------------------------------------------------ + * Flags for Using TC4 Resource in ROM code stage + *------------------------------------------------------------------------------ + */ + +#define CFG_USE_TC4_RESOURCE_FOR_INIT_CMD 0 + +/*------------------------------------------------------------------------------ + * Flags for Efuse Start and End address report from FW + *------------------------------------------------------------------------------ + */ + +#define CFG_FW_Report_Efuse_Address 1 + +/*------------------------------------------------------------------------------ + * FW name max length + *------------------------------------------------------------------------------ + */ +#define CFG_FW_NAME_MAX_LEN (64) + +/*------------------------------------------------------------------------------ + * Support WMT WIFI Path Config + *------------------------------------------------------------------------------ + */ +#define CFG_WMT_WIFI_PATH_SUPPORT 0 + +/*------------------------------------------------------------------------------ + * Support CFG_SISO_SW_DEVELOP + *------------------------------------------------------------------------------ + */ +#define CFG_SISO_SW_DEVELOP 1 + +/*------------------------------------------------------------------------------ + * Support spatial extension control + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_SPE_IDX_CONTROL 1 + +/*------------------------------------------------------------------------------ + * Flags for a Goal for MT6632 : Cal Result Backup in Host or NVRam when Android + * Boot + *------------------------------------------------------------------------------ + */ +#if 0 /*(MTK_WCN_HIF_SDIO) : 20161003 Default Off, later will enable + * by MTK_WCN_HIF_SDIO + */ +#define CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST 1 +#define CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST_DBGLOG 0 +#else +#define CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST 0 +#define CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST_DBGLOG 0 +#endif + +/*------------------------------------------------------------------------------ + * Enable SDIO 1-bit Data Mode. (Usually debug only) + *------------------------------------------------------------------------------ + */ +#define CFG_SDIO_1BIT_DATA_MODE 0 + +/*------------------------------------------------------------------------------ + * Single Sku + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_SINGLE_SKU 1 +#ifndef CFG_SUPPORT_SINGLE_SKU_LOCAL_DB +#define CFG_SUPPORT_SINGLE_SKU_LOCAL_DB 1 +#endif + + +/*------------------------------------------------------------------------------ + * Direct Control for RF/PHY/BB/MAC for Manual Configuration via command/api + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_ADVANCE_CONTROL 1 + + +/*------------------------------------------------------------------------------ + * Driver pre-allocate total size of memory in one time + *------------------------------------------------------------------------------ + */ +#ifndef CFG_PRE_ALLOCATION_IO_BUFFER +#define CFG_PRE_ALLOCATION_IO_BUFFER 0 +#endif + +/*------------------------------------------------------------------------------ + * Auto enable SDIO asynchronous interrupt mode + *------------------------------------------------------------------------------ + */ +#define CFG_SDIO_ASYNC_IRQ_AUTO_ENABLE 1 + +/*------------------------------------------------------------------------------ + * Flags to force enable performance monitor even when screen is OFF + *------------------------------------------------------------------------------ + */ +#define CFG_FORCE_ENABLE_PERF_MONITOR 0 + +/*------------------------------------------------------------------------------ + * Flags to ignore invalid auth tsn issue (ex. ALPS03089071) + *------------------------------------------------------------------------------ + */ +#define CFG_IGNORE_INVALID_AUTH_TSN 1 + +/*------------------------------------------------------------------------------ + * Flags of Network Controlled HandOver(NCHO) support + * TC10 only: To improve the voice quality during handover, + * the NCHO is required to precisely control scanning parameters + * CFG_SUPPORT_NCHO: 1: support, 0: not support + * CFG_SUPPORT_NCHO_AUTO_ENABLE: sub-feature depends with CFG_SUPPORT_NCHO + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_NCHO 0 +#define CFG_SUPPORT_NCHO_AUTO_ENABLE 0 + +/*------------------------------------------------------------------------------ + * Flags of Key Word Exception Mechanism + *------------------------------------------------------------------------------ + */ +#define CFG_ENABLE_KEYWORD_EXCEPTION_MECHANISM 0 + +/*------------------------------------------------------------------------------ + * Flags of WPA3 support + *------------------------------------------------------------------------------ + */ + +#define CFG_SUPPORT_WPA3 1 + +/*------------------------------------------------------------------------------ + * Driver supports preferred frequency list for p2p operating channel + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_P2P_PREFERRED_FREQ_LIST 1 + +/*------------------------------------------------------------------------------ + * Flag used for P2P GO to find the best channel list + * Value 0: Disable + * Value 1: Enable + * Note: Must Enable CFG_SUPPORT_P2P_PREFERRED_FREQ_LIST in advance + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_P2PGO_ACS 1 + +/*----------------------------------------------------------------------------- +* Flags to support IOT AP blacklist +*------------------------------------------------------------------------------ +*/ +#ifndef CFG_SUPPORT_IOT_AP_BLACKLIST +#if CFG_SUPPORT_DBDC +#define CFG_SUPPORT_IOT_AP_BLACKLIST 1 +#else +#define CFG_SUPPORT_IOT_AP_BLACKLIST 0 +#endif +#endif + +#if CFG_SUPPORT_IOT_AP_BLACKLIST +#define CFG_IOT_AP_RULE_MAX_CNT 32 +#define CFG_IOT_AP_DATA_MAX_LEN 16 +#endif +/*------------------------------------------------------------------------------ + * Driver supports reporting max tx rate instead of current tx rate + * in mtk_cfg80211_get_station + *------------------------------------------------------------------------------ + */ +#define CFG_REPORT_MAX_TX_RATE 1 + +/*------------------------------------------------------------------------------ + * Link Quality Monitor + * Link quality monitor execution period base on performance monitor timer + * CFG_LQ_MONITOR_FREQUENCY base on PERF_MON_UPDATE_INTERVAL + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_LINK_QUALITY_MONITOR +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR +#define CFG_LQ_MONITOR_FREQUENCY 1 +#endif /* CFG_SUPPORT_LINK_QUALITY_MONITOR */ + +/*------------------------------------------------------------------------------ + * Driver supports SYS DVT automation + *------------------------------------------------------------------------------ + */ +#ifndef CFG_SUPPORT_WIFI_SYSDVT +#define CFG_SUPPORT_WIFI_SYSDVT 0 +#endif + +#ifndef CFG_SUPPORT_DMASHDL_SYSDVT +#define CFG_SUPPORT_DMASHDL_SYSDVT 0 +#endif + +/*------------------------------------------------------------------------------ + * Flags of using wlan_assistant to read/write NVRAM + *------------------------------------------------------------------------------ + */ +#define CFG_WLAN_ASSISTANT_NVRAM 1 + +/*------------------------------------------------------------------------------ + * SW handles WTBL_SEARCH_FAIL + *------------------------------------------------------------------------------ + */ +#define CFG_WIFI_SW_WTBL_SEARCH_FAIL 1 + +/*------------------------------------------------------------------------------ + * SW enables CIPHER_MISMATCH + *------------------------------------------------------------------------------ + */ +#define CFG_WIFI_SW_CIPHER_MISMATCH 1 + +/*------------------------------------------------------------------------------ + * CONNINFRA SUPPORT (Without WMT) + * CFG_SUPPORT_CONNINFRA: 1 : conninfra driver exist + * 0 : conninfra driver doesn't exist + * We replace WMT driver with CONNINFRA driver in mobile project + * after connac2.0. + * CFG_MTK_ANDROID_WMT is used to separate between mobile project and others. + * Although WMT driver is removed, CFG_MTK_ANDROID_WMT still need to be set 1 + * for some code flow in mobile gen4m. + *------------------------------------------------------------------------------ + */ +#ifndef CFG_SUPPORT_CONNINFRA +#define CFG_SUPPORT_CONNINFRA 0 +#endif + +#ifndef CFG_SUPPORT_PRE_ON_PHY_ACTION +#define CFG_SUPPORT_PRE_ON_PHY_ACTION 0 +#endif + +#ifndef CFG_POWER_ON_DOWNLOAD_EMI_ROM_PATCH +#define CFG_POWER_ON_DOWNLOAD_EMI_ROM_PATCH 0 +#endif + +#ifndef CFG_DOWNLOAD_DYN_MEMORY_MAP +#define CFG_DOWNLOAD_DYN_MEMORY_MAP 0 +#endif + +#ifndef CFG_ROM_PATCH_NO_SEM_CTRL +#define CFG_ROM_PATCH_NO_SEM_CTRL 0 +#endif + +/*------------------------------------------------------------------------------ + * Flags of Disconnect with disable channel based on REGD update + *------------------------------------------------------------------------------ + */ +#ifndef CFG_SUPPORT_REGD_UPDATE_DISCONNECT_ALLOWED +#define CFG_SUPPORT_REGD_UPDATE_DISCONNECT_ALLOWED 0 +#endif + +/*------------------------------------------------------------------------------ + * Notify clients to reconnect when channel switch in hotspot mode to avoid IOT + * issues, eg. cross band switch. + *------------------------------------------------------------------------------ + */ +#define CFG_SEND_DEAUTH_DURING_CHNL_SWITCH 1 + +/*------------------------------------------------------------------------------ + *Smart Gear Feature Configure + *------------------------------------------------------------------------------ +*/ +#ifndef CFG_SUPPORT_SMART_GEAR +#define CFG_SUPPORT_SMART_GEAR 0 +#endif + +/*------------------------------------------------------------------------------ + * Flag used for AIS persistent netdev creating. + * Value 0: Create & register AIS netdev for each wifi on, + * and unregister & free AIS netdev for each wifi off. + * Value 1: Create & register AIS netdev for first wifi on, + * and unregister & free AIS netdev during module exit. + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_PERSIST_NETDEV 1 + + +/*------------------------------------------------------------------------------ + * Dynamic tx power control: + * Support additional tx power setting on OFDM + * + * No define: CCK,HT20L,HT20H,HT40L,HT40H,HT80L,HT80H,HT160L,HT160H + * Defined: CCK,OFDM_L,OFDM_H,HT20L,HT20H,HT40L,HT40H,HT80L,HT80H,HT160L,HT160H + * + * note: need to confirm firmware support this feature + * COUNTRY_CHANNEL_TXPOWER_LIMIT_TYPE_COMP_11AG_11N + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_DYNA_TX_PWR_CTRL_OFDM_SETTING 0 + +/*------------------------------------------------------------------------------ + * tx power control: + * Support additional tx power setting for HE + * + * support power limit for RU26/RU52/RU104/RU242/RU484/RU996 + * + * note: need to confirm firmware support HE (802.11AX) + *------------------------------------------------------------------------------ + */ +#if (CFG_SUPPORT_802_11AX == 1) +#define CFG_SUPPORT_PWR_LIMIT_HE 1 +#else +#define CFG_SUPPORT_PWR_LIMIT_HE 0 +#endif + +//Xiaomi add +#define ARP_BRUST_OPTIMIZE 1 +#define CFG_SUPPORT_SCAN_EXT_FLAG 1 +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#endif /* _CONFIG_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/debug.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/debug.h new file mode 100644 index 0000000000000..269ec1ff8e738 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/debug.h @@ -0,0 +1,655 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: include/debug.h + */ + +/*! \file debug.h + * \brief Definition of SW debugging level. + * + * In this file, it describes the definition of various SW debugging levels + * and assert functions. + */ + +#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 + +#define DBG_DISABLE_ALL_LOG 0 + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "gl_typedef.h" + +extern u_int8_t wlan_fb_power_down; +extern uint8_t aucDebugModule[]; +extern uint32_t au4LogLevel[]; + +extern void set_logtoomuch_enable(int value) __attribute__((weak)); +extern int get_logtoomuch_enable(void) __attribute__((weak)); + +extern struct MIB_INFO_STAT g_arMibInfo[ENUM_BAND_NUM]; + +/******************************************************************************* + * 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) + +#define DBG_LOG_LEVEL_DEFAULT \ + (DBG_CLASS_ERROR | \ + DBG_CLASS_WARN | \ + DBG_CLASS_STATE | \ + DBG_CLASS_EVENT | \ + DBG_CLASS_INFO) +#define DBG_LOG_LEVEL_MORE \ + (DBG_LOG_LEVEL_DEFAULT | \ + DBG_CLASS_TRACE) +#define DBG_LOG_LEVEL_EXTREME \ + (DBG_LOG_LEVEL_MORE | \ + DBG_CLASS_LOUD) + +#if defined(LINUX) +#define DBG_PRINTF_64BIT_DEC "lld" +#else /* Windows */ +#define DBG_PRINTF_64BIT_DEC "I64d" +#endif +#define DBG_ALL_MODULE_IDX 0xFFFFFFFF + +#define DEG_HIF_ALL BIT(0) +#define DEG_HIF_HOST_CSR BIT(1) +#define DEG_HIF_PDMA BIT(2) +#define DEG_HIF_DMASCH BIT(3) +#define DEG_HIF_PSE BIT(4) +#define DEG_HIF_PLE BIT(5) +#define DEG_HIF_MAC BIT(6) +#define DEG_HIF_PHY BIT(7) + +#define DEG_HIF_DEFAULT_DUMP \ + (DEG_HIF_HOST_CSR | DEG_HIF_PDMA | DEG_HIF_DMASCH | \ + DEG_HIF_PSE | DEG_HIF_PLE) + +#define HIF_CHK_TX_HANG BIT(1) +#define HIF_DRV_SER BIT(2) + +#define DUMP_MEM_SIZE 64 + +#if CFG_SUPPORT_ADVANCE_CONTROL +#define CMD_SW_DBGCTL_ADVCTL_SET_ID 0xa1260000 +#define CMD_SW_DBGCTL_ADVCTL_GET_ID 0xb1260000 +#endif + +#define CFG_STAT_DBG_PEER_NUM 10 +#define AGG_RANGE_SEL_4BYTE_NUM 4 + +#define AGG_RANGE_SEL_0_MASK BITS(0, 7) +#define AGG_RANGE_SEL_0_OFFSET 0 +#define AGG_RANGE_SEL_1_MASK BITS(8, 15) +#define AGG_RANGE_SEL_1_OFFSET 8 +#define AGG_RANGE_SEL_2_MASK BITS(16, 23) +#define AGG_RANGE_SEL_2_OFFSET 16 +#define AGG_RANGE_SEL_3_MASK BITS(24, 31) +#define AGG_RANGE_SEL_3_OFFSET 24 +#define AGG_RANGE_SEL_4_MASK AGG_RANGE_SEL_0_MASK +#define AGG_RANGE_SEL_4_OFFSET AGG_RANGE_SEL_0_OFFSET +#define AGG_RANGE_SEL_5_MASK AGG_RANGE_SEL_1_MASK +#define AGG_RANGE_SEL_5_OFFSET AGG_RANGE_SEL_1_OFFSET +#define AGG_RANGE_SEL_6_MASK AGG_RANGE_SEL_2_MASK +#define AGG_RANGE_SEL_6_OFFSET AGG_RANGE_SEL_2_OFFSET + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +/* Define debug module index */ +enum ENUM_DBG_MODULE { + DBG_INIT_IDX = 0, /* 0x00 *//* For driver initial */ + DBG_HAL_IDX, /* 0x01 *//* For HAL(HW) Layer */ + DBG_INTR_IDX, /* 0x02 *//* For Interrupt */ + DBG_REQ_IDX, /* 0x03 */ + DBG_TX_IDX, /* 0x04 */ + DBG_RX_IDX, /* 0x05 */ + DBG_RFTEST_IDX, /* 0x06 *//* For RF test mode */ + DBG_EMU_IDX, /* 0x07 *//* Developer specific */ + DBG_SW1_IDX, /* 0x08 *//* Developer specific */ + DBG_SW2_IDX, /* 0x09 *//* Developer specific */ + DBG_SW3_IDX, /* 0x0A *//* Developer specific */ + DBG_SW4_IDX, /* 0x0B *//* Developer specific */ + DBG_HEM_IDX, /* 0x0C *//* HEM */ + DBG_AIS_IDX, /* 0x0D *//* AIS */ + DBG_RLM_IDX, /* 0x0E *//* RLM */ + DBG_MEM_IDX, /* 0x0F *//* RLM */ + DBG_CNM_IDX, /* 0x10 *//* CNM */ + DBG_RSN_IDX, /* 0x11 *//* RSN */ + DBG_BSS_IDX, /* 0x12 *//* BSS */ + DBG_SCN_IDX, /* 0x13 *//* SCN */ + DBG_SAA_IDX, /* 0x14 *//* SAA */ + DBG_AAA_IDX, /* 0x15 *//* AAA */ + DBG_P2P_IDX, /* 0x16 *//* P2P */ + DBG_QM_IDX, /* 0x17 *//* QUE_MGT */ + DBG_SEC_IDX, /* 0x18 *//* SEC */ + DBG_BOW_IDX, /* 0x19 *//* BOW */ + DBG_WAPI_IDX, /* 0x1A *//* WAPI */ + DBG_ROAMING_IDX, /* 0x1B *//* ROAMING */ + DBG_TDLS_IDX, /* 0x1C *//* TDLS *//* CFG_SUPPORT_TDLS */ + DBG_PF_IDX, /* 0x1D *//* PF */ + DBG_OID_IDX, /* 0x1E *//* OID */ + DBG_NIC_IDX, /* 0x1F *//* NIC */ + DBG_WNM_IDX, /* 0x20 *//* WNM */ + DBG_WMM_IDX, /* 0x21 *//* WMM */ + DBG_TRACE_IDX, /* 0x22 *//* TRACE *//* don't add before */ + DBG_TWT_REQUESTER_IDX, + DBG_TWT_PLANNER_IDX, + DBG_RRM_IDX, + DBG_MODULE_NUM /* Notice the XLOG check */ +}; +enum ENUM_DBG_ASSERT_CTRL_LEVEL { + DBG_ASSERT_CTRL_LEVEL_ERROR, + DBG_ASSERT_CTRL_LEVEL_WARN, + DBG_ASSERT_CTRL_LEVEL_LITE +}; +enum ENUM_DBG_ASSERT_PATH { + DBG_ASSERT_PATH_WIFI, + DBG_ASSERT_PATH_WMT +}; + +struct CHIP_DBG_OPS { + void (*showPdmaInfo)(struct ADAPTER *prAdapter); + void (*showPseInfo)(struct ADAPTER *prAdapter); + void (*showPleInfo)(struct ADAPTER *prAdapter, u_int8_t fgDumpTxd); + void (*showTxdInfo)(struct ADAPTER *prAdapter, u_int32_t fid); + bool (*showCsrInfo)(struct ADAPTER *prAdapter); + void (*showDmaschInfo)(struct ADAPTER *prAdapter); + void (*dumpMacInfo)(struct ADAPTER *prAdapter); + int32_t (*showWtblInfo)( + struct ADAPTER *prAdapter, + uint32_t u4Index, + char *pcCommand, + int32_t i4TotalLen); +#if (CFG_SUPPORT_CONNAC2X == 1) + int32_t (*showUmacFwtblInfo)( + struct ADAPTER *prAdapter, + uint32_t u4Index, + char *pcCommand, + int32_t i4TotalLen); +#endif /* CFG_SUPPORT_CONNAC2X == 1 */ + void (*showHifInfo)(struct ADAPTER *prAdapter); + void (*printHifDbgInfo)(struct ADAPTER *prAdapter); + int32_t (*show_rx_rate_info)( + struct ADAPTER *prAdapter, + char *pcCommand, + int32_t i4TotalLen, + uint8_t ucStaIdx); + int32_t (*show_rx_rssi_info)( + struct ADAPTER *prAdapter, + char *pcCommand, + int32_t i4TotalLen, + uint8_t ucStaIdx); + int32_t (*show_stat_info)( + struct ADAPTER *prAdapter, + char *pcCommand, + int32_t i4TotalLen, + struct PARAM_HW_WLAN_INFO *prHwWlanInfo, + struct PARAM_GET_STA_STATISTICS *prQueryStaStatistics, + uint8_t fgResetCnt, + uint32_t u4StatGroup); +}; + +enum PKT_PHASE { + PHASE_XMIT_RCV, + PHASE_ENQ_QM, + PHASE_HIF_TX, +}; + +struct WLAN_DEBUG_INFO { + u_int8_t fgVoE5_7Test:1; + u_int8_t fgReserved:7; +}; + +#if (CFG_SUPPORT_STATISTICS == 1) +enum WAKE_DATA_TYPE { + WLAN_WAKE_ARP = 0, + WLAN_WAKE_IPV4, + WLAN_WAKE_IPV6, + WLAN_WAKE_1X, + WLAN_WAKE_TDLS, + WLAN_WAKE_OTHER, + WLAN_WAKE_MAX_NUM +}; +#endif + +#if MTK_WCN_HIF_SDIO +#define DBG_ASSERT_PATH_DEFAULT DBG_ASSERT_PATH_WMT +#else +#define DBG_ASSERT_PATH_DEFAULT DBG_ASSERT_PATH_WIFI +#endif +#define DBG_ASSERT_CTRL_LEVEL_DEFAULT DBG_ASSERT_CTRL_LEVEL_ERROR +/******************************************************************************* + * P U B 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) +#if CFG_SHOW_FULL_MACADDR +/* Debug print format string for the MAC Address */ +#define MACSTR "%pM" +/* Debug print argument for the MAC Address */ +#define MAC2STR(a) a +#else +#define MACSTR "%02x:%02x:**:**:**:%02x" +#define MAC2STR(a) ((uint8_t *)a)[0], ((uint8_t *)a)[1], ((uint8_t *)a)[5] +#endif +#define PMKSTR "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%03x%02x%02x" +/* Debug print format string for the IPv4 Address */ +#define IPV4STR "%pI4" +/* Debug print argument for the IPv4 Address */ +#define IPV4TOSTR(a) a +/* Debug print format string for the IPv6 Address */ +#define IPV6STR "%pI6" +/* Debug print argument for the IPv6 Address */ +#define IPV6TOSTR(a) a +/* The pre-defined format to dump the varaible value 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)) +/* Debug print format string for the floating point */ +#define FPSTR "%u.%u" +/* Debug print argument for the floating point */ +#define DIV2INT(_dividend, _divisor) \ + ((_divisor) ? (_dividend) / (_divisor) : 0) +#define DIV2DEC(_dividend, _divisor) \ + ((_divisor) ? (((_dividend) * 100) / (_divisor)) % 100 : 0) +/* for HIDE some information for user load */ +#ifdef BUILD_QA_DBG +#define HIDE(_str) _str +#else +#define HIDE(_str) "***" +#endif + +/* 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 kalPrint +#define LOG_FUNC_LIMITED kalPrintLimited + +/* If __FUNCTION__ is already defined by compiler, we just use it. */ +#define DEBUGFUNC(_Func) +/* Disabled due to AOSP + * #if defined(__FUNCTION__) + * #define DEBUGFUNC(_Func) + * #else + * #define DEBUGFUNC(_Func) static const char __FUNCTION__[] = _Func; + * #endif + */ +#if DBG_DISABLE_ALL_LOG +#define DBGLOG(_Module, _Class, _Fmt) +#define DBGLOG_LIMITED(_Module, _Class, _Fmt) +#define DBGLOG_MEM8(_Module, _Class, _StartAddr, _Length) +#define DBGLOG_MEM32(_Module, _Class, _StartAddr, _Length) +#else +#define DBGLOG(_Mod, _Clz, _Fmt, ...) \ + do { \ + if ((aucDebugModule[DBG_##_Mod##_IDX] & \ + DBG_CLASS_##_Clz) == 0) \ + break; \ + LOG_FUNC("[%u]%s:(" #_Mod " " #_Clz ") " _Fmt, \ + KAL_GET_CURRENT_THREAD_ID(), \ + __func__, ##__VA_ARGS__); \ + } while (0) +#define DBGLOG_LIMITED(_Mod, _Clz, _Fmt, ...) \ + do { \ + if ((aucDebugModule[DBG_##_Mod##_IDX] & \ + DBG_CLASS_##_Clz) == 0) \ + break; \ + LOG_FUNC_LIMITED("[%u]%s:(" #_Mod " " #_Clz ") " _Fmt, \ + KAL_GET_CURRENT_THREAD_ID(), \ + __func__, ##__VA_ARGS__); \ + } while (0) +#define DBGFWLOG(_Mod, _Clz, _Fmt, ...) \ + do { \ + if ((aucDebugModule[DBG_##_Mod##_IDX] & \ + DBG_CLASS_##_Clz) == 0) \ + break; \ + wlanPrintFwLog(NULL, 0, DEBUG_MSG_TYPE_DRIVER, \ + "[%u]%s:(" #_Mod " " #_Clz ") " _Fmt, \ + KAL_GET_CURRENT_THREAD_ID(), \ + __func__, ##__VA_ARGS__); \ + } while (0) +#define TOOL_PRINTLOG(_Mod, _Clz, _Fmt, ...) \ + do { \ + if ((aucDebugModule[DBG_##_Mod##_IDX] & \ + DBG_CLASS_##_Clz) == 0) \ + break; \ + LOG_FUNC(_Fmt, ##__VA_ARGS__); \ + } while (0) +#define DBGLOG_MEM8(_Mod, _Clz, _Adr, _Len) \ + { \ + if (aucDebugModule[DBG_##_Mod##_IDX] & DBG_CLASS_##_Clz) { \ + LOG_FUNC("%s:(" #_Mod " " #_Clz ")\n", __func__); \ + dumpMemory8((uint8_t *)(_Adr), (uint32_t)(_Len)); \ + } \ + } +#define DBGLOG_MEM32(_Mod, _Clz, _Adr, _Len) \ + { \ + if (aucDebugModule[DBG_##_Mod##_IDX] & DBG_CLASS_##_Clz) { \ + LOG_FUNC("%s:(" #_Mod " " #_Clz ")\n", __func__); \ + dumpMemory32((uint32_t *)(_Adr), (uint32_t)(_Len)); \ + } \ + } +#endif +#define DISP_STRING(_str) _str +#undef ASSERT +#undef ASSERT_REPORT +#if (BUILD_QA_DBG || DBG) +#define ASSERT_NOMEM() \ +{ \ + LOG_FUNC("alloate memory failed at %s:%d\n", __FILE__, __LINE__); \ + kalSendAeeWarning("Wlan_Gen4 No Mem", "Memory Alloate Failed %s:%d",\ + __FILE__, __LINE__); \ +} +#ifdef _lint +#define ASSERT(_exp) \ + { \ + if (!(_exp)) { \ + do {} while (1); \ + } \ + } +#define ASSERT_REPORT(_exp, _fmt) \ + { \ + LOG_FUNC("Assertion failed: %s:%d (%s)\n", \ + __FILE__, __LINE__, #_exp); \ + LOG_FUNC _fmt; \ + if (!(_exp)) { \ + do {} while (1); \ + } \ + } +#elif defined(WINDOWS_CE) +#define UNICODE_TEXT(_msg) TEXT(_msg) +#define ASSERT(_exp) \ + { \ + if (!(_exp)) { \ + 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)) { \ + 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_NOMEM() \ +{ \ + LOG_FUNC("alloate memory failed at %s:%d\n", __FILE__, __LINE__); \ + kalSendAeeWarning("Wlan_Gen4 No Mem", "Memory Alloate Failed %s:%d",\ + __FILE__, __LINE__); \ +} + +#define ASSERT(_exp) \ + { \ + if (!(_exp)) { \ + LOG_FUNC("Assertion failed: %s:%d (%s)\n", \ + __FILE__, __LINE__, #_exp); \ + kalBreakPoint(); \ + } \ + } +#define ASSERT_REPORT(_exp, _fmt) \ + { \ + if (!(_exp)) { \ + LOG_FUNC("Assertion failed: %s:%d (%s)\n", \ + __FILE__, __LINE__, #_exp); \ + LOG_FUNC _fmt; \ + kalBreakPoint(); \ + } \ + } +#endif /* WINDOWS_CE */ +#else +#define ASSERT_NOMEM() {} +#define ASSERT(_exp) {} +#define ASSERT_REPORT(_exp, _fmt) {} +#endif /* BUILD_QA_DBG */ +/* LOG function for print to buffer */ +/* If buffer pointer is NULL, redirect to normal DBGLOG */ +#define LOGBUF(_pucBuf, _maxLen, _curLen, _Fmt, ...) \ + { \ + if (_pucBuf) \ + (_curLen) += kalSnprintf((_pucBuf) + (_curLen), \ + (_maxLen) - (_curLen), _Fmt, ##__VA_ARGS__); \ + else \ + DBGLOG(SW4, INFO, _Fmt, ##__VA_ARGS__); \ + } +/* The following macro is used for debugging packed structures. */ +#ifndef DATA_STRUCT_INSPECTING_ASSERT +#define DATA_STRUCT_INSPECTING_ASSERT(expr) \ +{ \ + switch (0) {case 0: case (expr): default:; } \ +} +#endif + +/* Name alias of debug functions to skip check patch*/ +#define log_dbg DBGLOG +#define log_limited_dbg DBGLOG_LIMITED +#define log_fw_dbg DBGFWLOG +#define log_mem8_dbg DBGLOG_MEM8 +#define log_mem32_dbg DBGLOG_MEM32 +#define log_tool_dbg TOOL_PRINTLOG +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +void dumpMemory8(IN uint8_t *pucStartAddr, + IN uint32_t u4Length); +void dumpMemory32(IN uint32_t *pu4StartAddr, + IN uint32_t u4Length); +void wlanPrintFwLog(uint8_t *pucLogContent, + uint16_t u2MsgSize, uint8_t ucMsgType, + const uint8_t *pucFmt, ...); + +void wlanDbgLogLevelInit(void); +void wlanDbgLogLevelUninit(void); +uint32_t wlanDbgLevelUiSupport(IN struct ADAPTER *prAdapter, + uint32_t u4Version, uint32_t ucModule); +uint32_t wlanDbgGetLogLevelImpl(IN struct ADAPTER *prAdapter, + uint32_t u4Version, uint32_t ucModule); +void wlanDbgSetLogLevelImpl(IN struct ADAPTER *prAdapter, + uint32_t u4Version, uint32_t u4Module, uint32_t u4level); +void wlanDriverDbgLevelSync(void); +u_int8_t wlanDbgGetGlobalLogLevel(uint32_t u4Module, uint32_t *pu4Level); +u_int8_t wlanDbgSetGlobalLogLevel(uint32_t u4Module, uint32_t u4Level); + +void wlanFillTimestamp(struct ADAPTER *prAdapter, void *pvPacket, + uint8_t ucPhase); + +void halShowPseInfo(IN struct ADAPTER *prAdapter); +void halShowPleInfo(IN struct ADAPTER *prAdapter, + u_int8_t fgDumpTxd); +void halShowDmaschInfo(IN struct ADAPTER *prAdapter); +void haldumpMacInfo(IN struct ADAPTER *prAdapter); +void halGetPleTxdInfo(IN struct ADAPTER *prAdapter, + uint32_t fid, uint32_t *result); +void halGetPsePayload(IN struct ADAPTER *prAdapter, + uint32_t fid, uint32_t *result); +void halDumpTxdInfo(IN struct ADAPTER *prAdapter, uint32_t *tmac_info); +void halShowLitePleInfo(IN struct ADAPTER *prAdapter); +void halShowTxdInfo( + struct ADAPTER *prAdapter, + u_int32_t fid); +int32_t halShowStatInfo(struct ADAPTER *prAdapter, + IN char *pcCommand, IN int i4TotalLen, + struct PARAM_HW_WLAN_INFO *prHwWlanInfo, + struct PARAM_GET_STA_STATISTICS *prQueryStaStatistics, + u_int8_t fgResetCnt, uint32_t u4StatGroup); + + +#if (CFG_SUPPORT_CONNAC2X == 1) +void connac2x_show_txd_Info( + struct ADAPTER *prAdapter, + u_int32_t fid); +int32_t connac2x_show_wtbl_info( + struct ADAPTER *prAdapter, + uint32_t u4Index, + char *pcCommand, + int i4TotalLen); +int32_t connac2x_show_umac_wtbl_info( + struct ADAPTER *prAdapter, + uint32_t u4Index, + char *pcCommand, + int i4TotalLen); + +int32_t connac2x_show_rx_rate_info( + struct ADAPTER *prAdapter, + char *pcCommand, + int32_t i4TotalLen, + uint8_t ucStaIdx); + +int32_t connac2x_show_rx_rssi_info( + struct ADAPTER *prAdapter, + char *pcCommand, + int32_t i4TotalLen, + uint8_t ucStaIdx); + +int32_t connac2x_show_stat_info( + struct ADAPTER *prAdapter, + char *pcCommand, + int32_t i4TotalLen, + struct PARAM_HW_WLAN_INFO *prHwWlanInfo, + struct PARAM_GET_STA_STATISTICS *prQueryStaStatistics, + uint8_t fgResetCnt, + uint32_t u4StatGroup); + +#endif /* CFG_SUPPORT_CONNAC2X == 1 */ + +#if (CFG_SUPPORT_CONNINFRA == 1) +void fw_log_bug_hang_register(void *); +#endif + +#if (CFG_SUPPORT_STATISTICS == 1) +void wlanWakeStaticsInit(void); +void wlanWakeStaticsUninit(void); +uint32_t wlanWakeLogCmd(uint8_t ucCmdId); +uint32_t wlanWakeLogEvent(uint8_t ucEventId); +void wlanLogTxData(enum WAKE_DATA_TYPE dataType); +void wlanLogRxData(enum WAKE_DATA_TYPE dataType); +uint32_t wlanWakeDumpRes(void); +#endif + +#if (CFG_SUPPORT_RA_GEN == 1) +int32_t mt7663_show_stat_info(struct ADAPTER *prAdapter, + char *pcCommand, int32_t i4TotalLen, + struct PARAM_HW_WLAN_INFO *prHwWlanInfo, + struct PARAM_GET_STA_STATISTICS *prQueryStaStatistics, + uint8_t fgResetCnt, uint32_t u4StatGroup); +#endif + +#if (CFG_SUPPORT_RA_GEN == 0) +int32_t mt7668_show_stat_info(struct ADAPTER *prAdapter, + char *pcCommand, int32_t i4TotalLen, + struct PARAM_HW_WLAN_INFO *prHwWlanInfo, + struct PARAM_GET_STA_STATISTICS *prQueryStaStatistics, + uint8_t fgResetCnt, uint32_t u4StatGroup); + +int32_t mt6632_show_stat_info(struct ADAPTER *prAdapter, + char *pcCommand, int32_t i4TotalLen, + struct PARAM_HW_WLAN_INFO *prHwWlanInfo, + struct PARAM_GET_STA_STATISTICS *prQueryStaStatistics, + uint8_t fgResetCnt, uint32_t u4StatGroup); +#endif +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#endif /* _DEBUG_H */ + + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/dvt/dvt_common.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/dvt/dvt_common.h new file mode 100644 index 0000000000000..1461bdc810ec4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/dvt/dvt_common.h @@ -0,0 +1,387 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +/* + ** Id: include/dvt_common.h + */ + +/*! \file "dvt_common.h" + * \brief This file contains the declairations of sys dvt command + */ + +#ifndef _DVT_COMMON_H +#define _DVT_COMMON_H + +#if CFG_SUPPORT_WIFI_SYSDVT + +/******************************************************************************* + * C O M P I L E 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 PID_SIZE 256 +#define TXS_LIST_ELEM_NUM 4096 +#define TX_TEST_UNLIMITIED 0xFFFF +#define TX_TEST_UP_UNDEF 0xFF +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +#define IS_SKIP_CH_CHECK(_prAdapter) \ + ((_prAdapter)->auto_dvt && (_prAdapter)->auto_dvt->skip_legal_ch_enable) + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +enum ENUM_SYSDVT_CTRL_EXT_T { + EXAMPLE_FEATURE_ID = 0, + SYSDVT_CTRL_EXT_NUM +}; + +enum ENUM_AUTOMATION_TXS_TESTYPE { + TXS_INIT = 0, + TXS_COUNT_TEST, + TXS_BAR_TEST, + TXS_DEAUTH_TEST, + TXS_RTS_TEST, + TXS_BA_TEST, + TXS_DUMP_DATA, + TXS_NUM +}; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +enum ENUM_AUTOMATION_CSO_TESTYPE { + CSO_TX_IPV4 = BIT(0), + CSO_TX_IPV6 = BIT(1), + CSO_TX_TCP = BIT(2), + CSO_TX_UDP = BIT(3), + CSO_RX_IPV4 = BIT(4), + CSO_RX_IPV6 = BIT(5), + CSO_RX_TCP = BIT(6), + CSO_RX_UDP = BIT(7), +}; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +enum ENUM_AUTOMATION_INIT_TYPE { + TXS = 0, + RXV, +#if (CFG_SUPPORT_DMASHDL_SYSDVT) + DMASHDL, +#endif + CSO, + SKIP_CH +}; + +enum ENUM_AUTOMATION_FRAME_TYPE { + AUTOMATION_MANAGEMENT = 10, + AUTOMATION_CONTROL, + AUTOMATION_DATA +}; + +struct SYSDVT_CTRL_EXT_T { + /* DWORD_0 - Common Part */ + uint8_t ucCmdVer; + uint8_t aucPadding0[1]; + uint16_t u2CmdLen; /* Cmd size including common part and body */ + + /* DWORD_N - Body Part */ + uint32_t u4FeatureIdx; /* Feature ID */ + uint32_t u4Type; /* Test case ID (Type) */ + uint32_t u4Lth; /* dvt parameter's data struct size (Length) */ + uint8_t u1cBuffer[0]; /* dvt parameter's data struct (Value) */ +}; + +struct SYS_DVT_HANDLER { + uint32_t u4FeatureIdx; + uint8_t *str_feature_dvt; + int32_t (*pFeatureDvtHandler)(struct ADAPTER *, uint8_t *); + void (*pDoneHandler)(struct ADAPTER *, struct CMD_INFO *, uint8_t *); +}; + +struct TXS_CHECK_ITEM { + uint32_t time_stamp; +}; + +struct TXS_LIST_ENTRY { + struct list_head mList; + uint8_t wlan_idx; +}; + +struct TXS_LIST_POOL { + struct TXS_LIST_ENTRY Entry[TXS_LIST_ELEM_NUM]; + struct list_head List; +}; + +struct TXS_FREE_LIST_POOL { + struct TXS_LIST_ENTRY head; + struct TXS_LIST_POOL pool_head; + uint32_t entry_number; + spinlock_t Lock; + uint32_t txs_list_cnt; +}; + +struct TXS_LIST { + uint32_t Num; + spinlock_t lock; + struct TXS_LIST_ENTRY pHead[PID_SIZE]; + struct TXS_FREE_LIST_POOL *pFreeEntrylist; +}; + +struct TXS_TEST { + bool isinit; + uint32_t test_type; + uint8_t format; + + uint8_t pid; + uint8_t received_pid; + bool stop_send_test; + bool duplicate_txs; + + /* statistic */ + uint32_t total_req; + uint32_t total_rsp; + struct TXS_LIST txs_list; + struct TXS_CHECK_ITEM check_item[PID_SIZE]; +}; + +struct RXV_TEST { + bool enable; + bool rxv_test_result; + uint32_t rx_count; + + uint32_t rx_mode:3; + uint32_t rx_rate:7; + uint32_t rx_bw:2; + uint32_t rx_sgi:1; + uint32_t rx_stbc:2; + uint32_t rx_ldpc:1; + uint32_t rx_nss:1; +}; + +#if (CFG_SUPPORT_DMASHDL_SYSDVT) +struct DMASHDL_TEST { + uint8_t dvt_item; + uint8_t dvt_sub_item; + uint8_t dvt_queue_idx; + uint8_t dvt_ping_nums[32]; + uint8_t dvt_ping_seq[20]; +}; +#endif + +struct AUTOMATION_DVT { + uint8_t skip_legal_ch_enable; + struct TXS_TEST txs; + struct RXV_TEST rxv; +#if (CFG_SUPPORT_DMASHDL_SYSDVT) + struct DMASHDL_TEST dmashdl; +#endif + uint8_t cso_ctrl; +}; + +struct _FRAME_RTS { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ +}; + +/* 2-byte BAR CONTROL field in BAR frame */ +struct _BAR_CONTROL { + uint16_t ACKPolicy:1; /* 0:normal ack, 1:no ack. */ +/*if this bit1, use FRAME_MTBA_REQ, if 0, use FRAME_BA_REQ */ + uint16_t MTID:1; + uint16_t Compressed:1; + uint16_t Rsv1:9; + uint16_t TID:4; +}; + +/* 2-byte BA Starting Seq CONTROL field */ +union _BASEQ_CONTROL { + struct { + uint16_t FragNum:4; /* always set to 0 */ +/* sequence number of the 1st MSDU for which this BAR is sent */ + uint16_t StartSeq:12; + } field; + uint16_t word; +}; + +struct _FRAME_BA { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + struct _BAR_CONTROL BarControl; + union _BASEQ_CONTROL StartingSeq; + unsigned char bitmask[8]; +}; +#endif /* CFG_SUPPORT_WIFI_SYSDVT */ + +/******************************************************************************* + * P U B 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_TCP_IP_CHKSUM_OFFLOAD +#define CSO_TX_IPV4_ENABLED(pAd) \ + (pAd->auto_dvt && (pAd->auto_dvt->cso_ctrl & CSO_TX_IPV4)) +#define CSO_TX_IPV6_ENABLED(pAd) \ + (pAd->auto_dvt && (pAd->auto_dvt->cso_ctrl & CSO_TX_IPV6)) +#define CSO_TX_UDP_ENABLED(pAd) \ + (pAd->auto_dvt && (pAd->auto_dvt->cso_ctrl & CSO_TX_UDP)) +#define CSO_TX_TCP_ENABLED(pAd) \ + (pAd->auto_dvt && (pAd->auto_dvt->cso_ctrl & CSO_TX_TCP)) +#endif + +#define RXV_AUTODVT_DNABLED(pAd) \ + (pAd->auto_dvt && pAd->auto_dvt->rxv.enable) + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +#if CFG_SUPPORT_WIFI_SYSDVT +struct TXS_LIST_ENTRY *GetTxsEntryFromFreeList(void); + +int SendRTS( + struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + PFN_TX_DONE_HANDLER pfTxDoneHandler); + +int SendBA( + struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + PFN_TX_DONE_HANDLER pfTxDoneHandler); + +bool send_add_txs_queue(uint8_t pid, uint8_t wlan_idx); + +bool receive_del_txs_queue( + uint32_t sn, uint8_t pid, + uint8_t wlan_idx, + uint32_t time_stamp); + +int priv_driver_txs_test( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen); + +int priv_driver_txs_test_result( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen); + +int is_frame_test(struct ADAPTER *pAd, uint8_t send_received); + +uint32_t AutomationTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +int priv_driver_set_tx_test( + IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen); +int priv_driver_set_tx_test_ac( + IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen); + +/* RXV Test */ +int priv_driver_rxv_test( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen); + +int priv_driver_rxv_test_result( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen); + +void connac2x_rxv_correct_test( + IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +/* CSO Test */ +int priv_driver_cso_test( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen); + +/* skip legal channel sanity check for fpga dvt */ +int priv_driver_skip_legal_ch_check( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen); + +bool AutomationInit(struct ADAPTER *pAd, int32_t auto_type); + +#endif /* CFG_SUPPORT_WIFI_SYSDVT */ +#endif /* _DVT_COMMON_H */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/dvt/dvt_dmashdl.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/dvt/dvt_dmashdl.h new file mode 100644 index 0000000000000..caa14281816fa --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/dvt/dvt_dmashdl.h @@ -0,0 +1,258 @@ +/***************************************************************************** + *============================================================================ + * HISTORY + * Log + * + * 10 05 2018 Kai.lin + * commit id bece10b96739cf7ca196930c313eab8ddcef45b3 + * Porting from 7668 + * + ****************************************************************************/ + + +#ifndef __DVT_DMASHDL_H__ +#define __DVT_DMASHDL_H__ + +#if (CFG_SUPPORT_DMASHDL_SYSDVT) +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define WF_HIF_DMASHDL_TOP_BASE (0x7C026000) +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x00) /* 6000 */ +#define WF_HIF_DMASHDL_TOP_SW_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x04) /* 6004 */ +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x08) /* 6008 */ +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x0C) /* 600C */ +#define WF_HIF_DMASHDL_TOP_REFILL_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x10) /* 6010 */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x18) /* 6018 */ +#define WF_HIF_DMASHDL_TOP_PACKET_MAX_SIZE_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x1c) /* 601C */ +#define WF_HIF_DMASHDL_TOP_GROUP0_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x20) /* 6020 */ +#define WF_HIF_DMASHDL_TOP_GROUP1_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x24) /* 6024 */ +#define WF_HIF_DMASHDL_TOP_GROUP2_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x28) /* 6028 */ +#define WF_HIF_DMASHDL_TOP_GROUP3_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x2C) /* 602C */ +#define WF_HIF_DMASHDL_TOP_GROUP4_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x30) /* 6030 */ +#define WF_HIF_DMASHDL_TOP_GROUP15_CONTROL_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x5C) /* 605C */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING0_ADDR\ + (WF_HIF_DMASHDL_TOP_BASE + 0xB0) /* 60B0 */ +#define WF_HIF_DMASHDL_TOP_HIF_SCHEDULER_SETTING1_ADDR\ + (WF_HIF_DMASHDL_TOP_BASE + 0xB4) /* 60B4 */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING0_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0xd0) /* 60D0 */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING1_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0xd4) /* 60D4 */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING2_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0xd8) /* 60D8 */ +#define WF_HIF_DMASHDL_TOP_QUEUE_MAPPING3_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0xdc) /* 60DC */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x100) /* 6100 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x140) /* 6140 */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP15_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x17C) /* 617C */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT0_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x180) /* 6180 */ +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x98) /* 6098 */ +#define WF_HIF_DMASHDL_TOP_RD_GROUP_PKT_CNT7_ADDR \ + (WF_HIF_DMASHDL_TOP_BASE + 0x19c) /* 619C */ + +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_ACK_CNT_TH_MASK \ + 0x00FF0000 /* CR_HIF_ACK_CNT_TH[23..16] */ +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_ACK_CNT_TH_SHFT \ + 16 +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_GUP_ACT_MAP_MASK \ + 0x0000FFFF /* CR_HIF_GUP_ACT_MAP[15..0] */ +#define WF_HIF_DMASHDL_TOP_OPTIONAL_CONTROL_CR_HIF_GUP_ACT_MAP_SHFT \ + 0 +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_SRC_CNT_PRI_EN_MASK \ + 0x00100000 +#define WF_HIF_DMASHDL_TOP_PAGE_SETTING_GROUP_SEQUENCE_ORDER_TYPE_MASK \ + 0x00010000 /* GROUP_SEQUENCE_ORDER_TYPE[16] */ +#define WF_HIF_DMASHDL_TOP_CONTROL_SIGNAL_CR_WACPU_MODE_EN_MASK \ + 0x00000001 /* CR_WACPU_MODE_EN[0] */ +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_EXCUTE_MASK \ + 0x80000000 /* WACPU_EXCUTE[31] */ +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETRUN_MODE_SHFT \ + 24 +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETRUN_QID_SHFT \ + 16 +#define WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETURN_PAGE_CNT_SHFT \ + 0 +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_EXCUTE_MASK \ + 0x80000000 /* EXCUTE[31] */ +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_CPU_RETRUN_MODE_SHFT \ + 24 +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_CPU_RETRUN_GID_SHFT \ + 16 +#define WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_RETURN_PAGE_CNT_SHFT \ + 0 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_FREE_PAGE_CNT_MASK \ + 0x0FFF0000 /* FREE_PAGE_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_FREE_PAGE_CNT_SHFT \ + 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_FFA_CNT_MASK \ + 0x00000FFF /* FFA_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_FFA_CNT_SHFT \ + 0 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_RSV_CNT_MASK \ + 0x0FFF0000 /* G0_RSV_CNT[27..16] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_RSV_CNT_SHFT \ + 16 +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_SRC_CNT_MASK \ + 0x00000FFF /* G0_SRC_CNT[11..0] */ +#define WF_HIF_DMASHDL_TOP_STATUS_RD_GP0_G0_SRC_CNT_SHFT \ + 0 + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +/* HIF_RESET_SW_LOGIC */ +#define HIF_RESET_SW_LOGIC(prGlueInfo) \ + { \ + kalDevRegWrite(prGlueInfo, \ + WF_HIF_DMASHDL_TOP_SW_CONTROL_ADDR, 1); \ + kalDevRegWrite(prGlueInfo, \ + WF_HIF_DMASHDL_TOP_SW_CONTROL_ADDR, 0); \ + } + +#define HIF_CPU_RTN_CNT(prGlueInfo, ucGroup, ucRtnCnt) \ + kalDevRegWrite(prGlueInfo, WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_ADDR, \ + WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_EXCUTE_MASK | \ + 0x1 << WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_CPU_RETRUN_MODE_SHFT | \ + ucGroup << WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_CPU_RETRUN_GID_SHFT | \ + ucRtnCnt << WF_HIF_DMASHDL_TOP_CPU_QUOTA_SET_RETURN_PAGE_CNT_SHFT) + +/* HIF_ADD_RSV_CNT */ +#define HIF_ADD_RSV_CNT(prGlueInfo, ucQueue, ucRsvCnt) \ + kalDevRegWrite(prGlueInfo, WF_HIF_DMASHDL_TOP_WACPU_REFILL_ADDR, \ + WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_EXCUTE_MASK | \ + 0x1 << WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETRUN_MODE_SHFT | \ + ucQueue << WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETRUN_QID_SHFT | \ + ucRsvCnt << WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETURN_PAGE_CNT_SHFT) + +/* HIF_SUB_SRC_CNT */ +#define HIF_SUB_SRC_CNT(prGlueInfo, ucQueue, ucSrcCnt) \ + kalDevRegWrite(prGlueInfo, WF_HIF_DMASHDL_TOP_WACPU_REFILL_ADDR, \ + WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_EXCUTE_MASK | \ + 0x2 << WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETRUN_MODE_SHFT | \ + ucQueue << WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETRUN_QID_SHFT | \ + ucSrcCnt << WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETURN_PAGE_CNT_SHFT) + +/* HIF_ADD_SRC_CNT */ +#define HIF_ADD_SRC_CNT(prGlueInfo, ucQueue, ucSrcCnt) \ + kalDevRegWrite(prGlueInfo, WF_HIF_DMASHDL_TOP_WACPU_REFILL_ADDR, \ + WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_EXCUTE_MASK | \ + 0x3 << WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETRUN_MODE_SHFT | \ + ucQueue << WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETRUN_QID_SHFT | \ + ucSrcCnt << WF_HIF_DMASHDL_TOP_WACPU_REFILL_WACPU_RETURN_PAGE_CNT_SHFT) + +#define DMASHDL_DVT_SET_ITEM(pAd, item) \ + do { \ + if (pAd->auto_dvt) \ + pAd->auto_dvt->dmashdl.dvt_item = item; \ + } while (0) +#define DMASHDL_DVT_GET_ITEM(pAd) \ + ((pAd->auto_dvt)?pAd->auto_dvt->dmashdl.dvt_item:0) + +#define DMASHDL_DVT_SET_SUBITEM(pAd, subitem) \ + do { \ + if (pAd->auto_dvt) \ + pAd->auto_dvt->dmashdl.dvt_sub_item = subitem;\ + } while (0) +#define DMASHDL_DVT_GET_SUBITEM(pAd) \ + ((pAd->auto_dvt)?pAd->auto_dvt->dmashdl.dvt_sub_item:0) + +#define DMASHDL_DVT_RESET(pAd) \ + do { \ + if (pAd->auto_dvt) \ + memset(&(pAd->auto_dvt->dmashdl), \ + 0, sizeof(struct DMASHDL_TEST)); \ + } while (0) + +#define DMASHDL_DVT_ALLOW_PING_ONLY(pAd) \ + (pAd->auto_dvt && \ + (pAd->auto_dvt->dmashdl.dvt_item == DMASHDL_DVT_ITEM_1 ||\ + pAd->auto_dvt->dmashdl.dvt_item == DMASHDL_DVT_ITEM_3 ||\ + pAd->auto_dvt->dmashdl.dvt_item == DMASHDL_DVT_ITEM_4 ||\ + (pAd->auto_dvt->dmashdl.dvt_item == DMASHDL_DVT_ITEM_5 &&\ + pAd->auto_dvt->dmashdl.dvt_sub_item == DMASHDL_DVT_SUBITEM_2)\ + )) +#define DMASHDL_DVT_QUEUE_MAPPING_TYPE1(pAd) \ + (pAd->auto_dvt && \ + (pAd->auto_dvt->dmashdl.dvt_item == DMASHDL_DVT_ITEM_1 ||\ + pAd->auto_dvt->dmashdl.dvt_item == DMASHDL_DVT_ITEM_2 ||\ + pAd->auto_dvt->dmashdl.dvt_item == DMASHDL_DVT_ITEM_3 ||\ + pAd->auto_dvt->dmashdl.dvt_item == DMASHDL_DVT_ITEM_4)) +#define DMASHDL_DVT_QUEUE_MAPPING_TYPE2(pAd) \ + (pAd->auto_dvt && \ + (pAd->auto_dvt->dmashdl.dvt_item == DMASHDL_DVT_ITEM_5 &&\ + pAd->auto_dvt->dmashdl.dvt_sub_item == DMASHDL_DVT_SUBITEM_2)) +/* No check pAd->auto_dvt because */ +/* must call DMASHDL_DVT_QUEUE_MAPPING_TYPEX before call those MARCO */ +#define DMASHDL_DVT_GET_MAPPING_QID(pAd) \ + (pAd->auto_dvt->dmashdl.dvt_queue_idx) +#define DMASHDL_DVT_SET_MAPPING_QID(pAd, qidx) \ + (pAd->auto_dvt->dmashdl.dvt_queue_idx = (qidx)) +#define DMASHDL_DVT_INC_PING_PKT_CNT(pAd, qidx) \ + (pAd->auto_dvt->dmashdl.dvt_ping_nums[qidx]++) + + + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +/* ================ DMASHDL DVT ================ */ +enum _ENUM_DMASHDL_DVT_ITEM_T { + DMASHDL_DVT_RESULT = 0, + DMASHDL_DVT_ITEM_1 = 1, + DMASHDL_DVT_ITEM_2, + DMASHDL_DVT_ITEM_3, + DMASHDL_DVT_ITEM_4, + DMASHDL_DVT_ITEM_5, + DMASHDL_DVT_ITEM_6, + DMASHDL_DVT_ITEM_NUM +}; + +enum _ENUM_DMASHDL_DVT_SUBITEM_T { + DMASHDL_DVT_SUBITEM_1 = 1, + DMASHDL_DVT_SUBITEM_2 = 2, +}; + +struct DMASHDL_DVT_CMD_T { + uint8_t ucItemNo; + uint8_t ucSubItemNo; + uint8_t ucArgNo; + uint8_t ucReserve; +}; + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +int32_t priv_driver_dmashdl_dvt_item( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int32_t i4TotalLen); +int32_t priv_driver_show_dmashdl_allcr( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen); +#endif +#endif /* __DVT_DMASHDL_H__ */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/hif_cmm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/hif_cmm.h new file mode 100644 index 0000000000000..64fb849f4d3f8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/hif_cmm.h @@ -0,0 +1,139 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \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 + */ + + +#ifndef _HIF_CMM_H +#define _HIF_CMM_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 + ******************************************************************************* + */ + +/* Interface Type */ +enum MT_INF_TYPE { + MT_DEV_INF_UNKNOWN = 0, + MT_DEV_INF_PCI = 1, + MT_DEV_INF_USB = 2, + MT_DEV_INF_RBUS = 4, + MT_DEV_INF_PCIE = 5, + MT_DEV_INF_SDIO = 6, + MT_DEV_INF_EHPI = 7, + MT_DEV_INF_AXI = 8, + #ifdef UT_TEST_MODE + MT_DEV_INF_UT = 10, + #endif /* UT_TEST_MODE */ +}; + +/******************************************************************************* + * P U B 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 IS_SDIO_INF(__GlueInfo) \ + ((__GlueInfo)->u4InfType == MT_DEV_INF_SDIO) +#define IS_USB_INF(__GlueInfo) \ + ((__GlueInfo)->u4InfType == MT_DEV_INF_USB) +#define IS_PCIE_INF(__GlueInfo) \ + ((__GlueInfo)->u4InfType == MT_DEV_INF_PCIE) +#define IS_EHPI_INF(__GlueInfo) \ + ((__GlueInfo)->u4InfType == MT_DEV_INF_PCIE) + +#define HAL_WRITE_HIF_TXD(_prChipInfo, _pucOutputBuf, _u2InfoBufLen) \ +{ \ + uint16_t _u2DataLen = (uint16_t)(_u2InfoBufLen); \ + uint8_t *_prBuf = (_pucOutputBuf); \ + if (_prChipInfo->fillHifTxDesc) \ + _prChipInfo->fillHifTxDesc(&_prBuf, &_u2DataLen); \ +} + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#endif /* _HIF_CMM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/link.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/link.h new file mode 100644 index 0000000000000..f3b92fabc60ba --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/link.h @@ -0,0 +1,529 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: include/link.h + */ + +/*! \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. + */ + +#ifndef _LINK_H +#define _LINK_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "gl_typedef.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +/* May cause page fault & unalignment issue (data abort) */ +#define INVALID_LINK_POISON1 ((void *) 0x00100101) + +/* Used to verify that nonbody uses non-initialized link entries. */ +#define INVALID_LINK_POISON2 ((void *) 0x00100201) + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +/* Simple Doubly Linked List Structures - Entry Part */ +struct LINK_ENTRY { + struct LINK_ENTRY *prNext, *prPrev; +}; + +/* Simple Doubly Linked List Structures - List Part */ +struct LINK { + struct LINK_ENTRY *prNext; + struct LINK_ENTRY *prPrev; + uint32_t u4NumElem; +}; + +/* Support AP Selection */ +struct LINK_MGMT { + struct LINK rUsingLink; + struct LINK rFreeLink; +}; +/* end Support AP Selection */ +/******************************************************************************* + * P U B 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) \ + { (struct LINK_ENTRY *)(&(rLink)), \ + (struct LINK_ENTRY *)(&(rLink)), 0 } + +#define LINK_DECLARATION(rLink) \ + struct LINK rLink = LINK_ADDR(rLink) +#endif + +#define LINK_INITIALIZE(prLink) \ + do { \ + ((struct LINK *)(prLink))->prNext = \ + (struct LINK_ENTRY *)(prLink); \ + ((struct LINK *)(prLink))->prPrev = \ + (struct LINK_ENTRY *)(prLink); \ + ((struct LINK *)(prLink))->u4NumElem = 0; \ + } while (0) +/* Support AP Selection */ +#define LINK_MGMT_INIT(prLinkMgmt) \ + do { \ + LINK_INITIALIZE(&((struct LINK_MGMT *)prLinkMgmt)->rUsingLink); \ + LINK_INITIALIZE(&((struct LINK_MGMT *)prLinkMgmt)->rFreeLink); \ + } while (0) + +#define LINK_MGMT_GET_ENTRY(prLinkMgmt, prEntry, EntryType, memType) \ + do { \ + LINK_REMOVE_HEAD(&((struct LINK_MGMT *)prLinkMgmt)->rFreeLink, \ + prEntry, EntryType*); \ + if (!prEntry) \ + prEntry = kalMemAlloc(sizeof(EntryType), memType); \ + if (prEntry) {\ + kalMemZero(prEntry, sizeof(EntryType));\ + LINK_INSERT_TAIL( \ + &((struct LINK_MGMT *)prLinkMgmt)->rUsingLink, \ + &prEntry->rLinkEntry); \ + } \ + } while (0) + +#define LINK_MGMT_RETURN_ENTRY(prLinkMgmt, prEntry) \ + do {\ + if (!prEntry)\ + break;\ + LINK_REMOVE_KNOWN_ENTRY( \ + &((struct LINK_MGMT *)prLinkMgmt)->rUsingLink, \ + prEntry); \ + LINK_INSERT_TAIL(&((struct LINK_MGMT *)prLinkMgmt)->rFreeLink, \ + &prEntry->rLinkEntry); \ + } while (0) + +#define LINK_MGMT_UNINIT(prLinkMgmt, EntryType, memType) \ + do { \ + EntryType *prEntry = NULL; \ + struct LINK *prFreeList = &((struct LINK_MGMT *)prLinkMgmt)->rFreeLink; \ + struct LINK *prUsingList = &((struct LINK_MGMT *)prLinkMgmt)->rUsingLink; \ + LINK_REMOVE_HEAD(prFreeList, prEntry, EntryType *); \ + while (prEntry) { \ + kalMemFree(prEntry, memType, sizeof(EntryType)); \ + LINK_REMOVE_HEAD(prFreeList, prEntry, EntryType *); \ + } \ + LINK_REMOVE_HEAD(prUsingList, prEntry, EntryType *); \ + while (prEntry) { \ + kalMemFree(prEntry, memType, sizeof(EntryType)); \ + LINK_REMOVE_HEAD(prUsingList, prEntry, EntryType *); \ + } \ + } while (0) +/* end Support AP Selection */ + +#define LINK_ENTRY_INITIALIZE(prEntry) \ + do { \ + ((struct LINK_ENTRY *)(prEntry))->prNext = \ + (struct LINK_ENTRY *)NULL; \ + ((struct LINK_ENTRY *)(prEntry))->prPrev = \ + (struct LINK_ENTRY *)NULL; \ + } while (0) + +#define LINK_ENTRY_INVALID(prEntry) \ + do { \ + ((struct LINK_ENTRY *)(prEntry))->prNext = \ + (struct LINK_ENTRY *)INVALID_LINK_POISON1; \ + ((struct LINK_ENTRY *)(prEntry))->prPrev = \ + (struct LINK_ENTRY *)INVALID_LINK_POISON2; \ + } while (0) + +#define LINK_IS_EMPTY(prLink) \ + (((struct LINK *)(prLink))->prNext == (struct LINK_ENTRY *)(prLink)) + +#define LINK_ENTRY_IS_VALID(prEntry) \ + (((struct LINK_ENTRY *)(prEntry))->prNext != (struct LINK_ENTRY *)NULL && \ + ((struct LINK_ENTRY *)(prEntry))->prNext != \ + (struct LINK_ENTRY *)INVALID_LINK_POISON1 && \ + ((struct LINK_ENTRY *)(prEntry))->prPrev != (struct LINK_ENTRY *)NULL && \ + ((struct LINK_ENTRY *)(prEntry))->prPrev != \ + (struct LINK_ENTRY *)INVALID_LINK_POISON2) + + + +/* 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) \ + (((struct LINK *)(prLink))->prNext == (struct LINK_ENTRY *)NULL) + +#define LINK_IS_VALID(prLink) \ + (((struct LINK *)(prLink))->prNext != (struct LINK_ENTRY *)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)(((struct LINK *)(prLink))->prNext); \ + linkDel((struct LINK_ENTRY *)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((struct LINK_ENTRY *)prEntry); \ + ((prLink)->u4NumElem)--; \ + } + +/* Merge prSrcLink to prDstLink and put prSrcLink ahead of prDstLink */ +#define LINK_MERGE_TO_HEAD(prDstLink, prSrcLink) \ + { \ + if (!LINK_IS_EMPTY(prSrcLink)) { \ + linkMergeToHead((struct LINK *)prDstLink, \ + (struct LINK *)prSrcLink); \ + (prDstLink)->u4NumElem += (prSrcLink)->u4NumElem; \ + LINK_INITIALIZE(prSrcLink); \ + } \ + } + +/* Merge prSrcLink to prDstLink and put prSrcLink at tail */ +#define LINK_MERGE_TO_TAIL(prDstLink, prSrcLink) \ + { \ + if (!LINK_IS_EMPTY(prSrcLink)) { \ + linkMergeToTail((struct LINK *)prDstLink, \ + (struct LINK *)prSrcLink); \ + (prDstLink)->u4NumElem += (prSrcLink)->u4NumElem; \ + LINK_INITIALIZE(prSrcLink); \ + } \ + } + +/* Iterate over a link list */ +#define LINK_FOR_EACH(prEntry, prLink) \ + for (prEntry = (prLink)->prNext; \ + prEntry != (struct LINK_ENTRY *)(prLink); \ + prEntry = (struct LINK_ENTRY *)prEntry->prNext) + +/* Iterate over a link list backwards */ +#define LINK_FOR_EACH_PREV(prEntry, prLink) \ + for (prEntry = (prLink)->prPrev; \ + prEntry != (struct LINK_ENTRY *)(prLink); \ + prEntry = (struct LINK_ENTRY *)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 != (struct LINK_ENTRY *)(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 != (struct LINK_ENTRY *)(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 != (struct LINK_ENTRY *)(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 != (struct LINK_ENTRY *)(prLink); \ + prObj = prNextObj, \ + prNextObj = LINK_ENTRY(prNextObj->rMember.prNext, _TYPE, rMember)) + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is only for internal link list manipulation. + * + * \param[in] prNew Pointer of new link head + * \param[in] prPrev Pointer of previous link head + * \param[in] prNext Pointer of next link head + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void __linkAdd(IN struct LINK_ENTRY + *prNew, IN struct LINK_ENTRY *prPrev, + IN struct LINK_ENTRY *prNext) +{ + if (prNext) { + prNext->prPrev = prNew; + prNew->prNext = prNext; + } + if (prPrev) { + prNew->prPrev = prPrev; + prPrev->prNext = prNew; + } +} /* end of __linkAdd() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will add a new entry after the specified link head. + * + * \param[in] prNew New entry to be added + * \param[in] prHead Specified link head to add it after + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void linkAdd(IN struct LINK_ENTRY + *prNew, IN struct LINK *prLink) +{ + __linkAdd(prNew, (struct LINK_ENTRY *) prLink, + prLink->prNext); +} /* end of linkAdd() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will add a new entry before the specified link head. + * + * \param[in] prNew New entry to be added + * \param[in] prHead Specified link head to add it before + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void linkAddTail(IN struct LINK_ENTRY + *prNew, IN struct LINK *prLink) +{ + __linkAdd(prNew, prLink->prPrev, + (struct LINK_ENTRY *) prLink); +} /* end of linkAddTail() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is only for internal link list manipulation. + * + * \param[in] prPrev Pointer of previous link head + * \param[in] prNext Pointer of next link head + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void __linkDel(IN struct LINK_ENTRY + *prPrev, IN struct LINK_ENTRY *prNext) +{ + if (prNext) + prNext->prPrev = prPrev; + if (prPrev) + prPrev->prNext = prNext; +} /* end of __linkDel() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will delete a specified entry from link list. + * NOTE: the entry is in an initial state. + * + * \param prEntry Specified link head(entry) + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void linkDel(IN struct LINK_ENTRY + *prEntry) +{ + __linkDel(prEntry->prPrev, prEntry->prNext); + + LINK_ENTRY_INITIALIZE(prEntry); +} /* end of linkDel() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will delete a specified entry from link list + * and then add it after the specified link head. + * + * \param[in] prEntry Specified link head(entry) + * \param[in] prOtherHead Another link head to add it after + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void linkMove(IN struct LINK_ENTRY + *prEntry, IN struct LINK *prLink) +{ + __linkDel(prEntry->prPrev, prEntry->prNext); + linkAdd(prEntry, prLink); +} /* end of linkMove() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will delete a specified entry from link list + * and then add it before the specified link head. + * + * \param[in] prEntry Specified link head(entry) + * \param[in] prOtherHead Another link head to add it before + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void linkMoveTail(IN struct LINK_ENTRY + *prEntry, IN struct LINK *prLink) +{ + __linkDel(prEntry->prPrev, prEntry->prNext); + linkAddTail(prEntry, prLink); +} /* end of linkMoveTail() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will merge source link to the tail of destination link. +* +* \param[in] prDst destination link +* \param[in] prSrc source link +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void linkMergeToTail(struct LINK *prDst, + struct LINK *prSrc) +{ + prSrc->prNext->prPrev = prDst->prPrev; + prSrc->prPrev->prNext = (struct LINK_ENTRY *)prDst; + prDst->prPrev->prNext = prSrc->prNext; + prDst->prPrev = prSrc->prPrev; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will merge source link to the head of destination link. +* +* \param[in] prDst destination link +* \param[in] prSrc source link + +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void linkMergeToHead(struct LINK *prDst, + struct LINK *prSrc) +{ + prSrc->prNext->prPrev = (struct LINK_ENTRY *)prDst; + prSrc->prPrev->prNext = prDst->prNext; + prDst->prNext->prPrev = prSrc->prPrev; + prDst->prNext = prSrc->prNext; +} + +#endif /* _LINK_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/link_drv.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/link_drv.h new file mode 100644 index 0000000000000..715796f7f4471 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/link_drv.h @@ -0,0 +1,527 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: include/link.h + */ + +/*! \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. + */ + +#ifndef _LINK_H +#define _LINK_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "gl_typedef.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +/* May cause page fault & unalignment issue (data abort) */ +#define INVALID_LINK_POISON1 ((void *) 0x00100101) + +/* Used to verify that nonbody uses non-initialized link entries. */ +#define INVALID_LINK_POISON2 ((void *) 0x00100201) + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +/* Simple Doubly Linked List Structures - Entry Part */ +struct LINK_ENTRY { + struct LINK_ENTRY *prNext, *prPrev; +}; + +/* Simple Doubly Linked List Structures - List Part */ +struct LINK { + struct LINK_ENTRY *prNext; + struct LINK_ENTRY *prPrev; + uint32_t u4NumElem; +}; + +/* Support AP Selection */ +struct LINK_MGMT { + struct LINK rUsingLink; + struct LINK rFreeLink; +}; +/* end Support AP Selection */ +/******************************************************************************* + * P U B 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) \ + { (struct LINK_ENTRY *)(&(rLink)), \ + (struct LINK_ENTRY *)(&(rLink)), 0 } + +#define LINK_DECLARATION(rLink) \ + struct LINK rLink = LINK_ADDR(rLink) +#endif + +#define LINK_INITIALIZE(prLink) \ + do { \ + ((struct LINK *)(prLink))->prNext = \ + (struct LINK_ENTRY *)(prLink); \ + ((struct LINK *)(prLink))->prPrev = \ + (struct LINK_ENTRY *)(prLink); \ + ((struct LINK *)(prLink))->u4NumElem = 0; \ + } while (0) +/* Support AP Selection */ +#define LINK_MGMT_INIT(prLinkMgmt) \ +do { \ + LINK_INITIALIZE(&((struct LINK_MGMT *)prLinkMgmt)->rUsingLink); \ + LINK_INITIALIZE(&((struct LINK_MGMT *)prLinkMgmt)->rFreeLink); \ +} while (0) + +#define LINK_MGMT_GET_ENTRY(prLinkMgmt, prEntry, EntryType, memType) \ + do { \ + LINK_REMOVE_HEAD(&((struct LINK_MGMT *)prLinkMgmt)->rFreeLink, \ + prEntry, EntryType*); \ + if (!prEntry) \ + prEntry = kalMemAlloc(sizeof(EntryType), memType); \ + if (prEntry) {\ + kalMemZero(prEntry, sizeof(EntryType));\ + LINK_INSERT_TAIL( \ + &((struct LINK_MGMT *)prLinkMgmt)->rUsingLink, \ + &prEntry->rLinkEntry); \ + } \ + } while (0) + +#define LINK_MGMT_RETURN_ENTRY(prLinkMgmt, prEntry) \ + do {\ + if (!prEntry)\ + break;\ + LINK_REMOVE_KNOWN_ENTRY( \ + &((struct LINK_MGMT *)prLinkMgmt)->rUsingLink, \ + prEntry); \ + LINK_INSERT_TAIL(&((struct LINK_MGMT *)prLinkMgmt)->rFreeLink, \ + &prEntry->rLinkEntry); \ + } while (0) + +#define LINK_MGMT_UNINIT(prLinkMgmt, EntryType, memType) \ + do { \ + EntryType *prEntry = NULL; \ + struct LINK *prFreeList = \ + &((struct LINK_MGMT *)prLinkMgmt)->rFreeLink; \ + struct LINK *prUsingList = \ + &((struct LINK_MGMT *)prLinkMgmt)->rUsingLink; \ + LINK_REMOVE_HEAD(prFreeList, prEntry, EntryType *); \ + while (prEntry) { \ + kalMemFree(prEntry, memType, sizeof(EntryType)); \ + LINK_REMOVE_HEAD(prFreeList, prEntry, EntryType *); \ + } \ + LINK_REMOVE_HEAD(prUsingList, prEntry, EntryType *); \ + while (prEntry) { \ + kalMemFree(prEntry, memType, sizeof(EntryType)); \ + LINK_REMOVE_HEAD(prUsingList, prEntry, EntryType *); \ + } \ + } while (0) +/* end Support AP Selection */ + +#define LINK_ENTRY_INITIALIZE(prEntry) \ + do { \ + ((struct LINK_ENTRY *)(prEntry))->prNext = \ + (struct LINK_ENTRY *)NULL; \ + ((struct LINK_ENTRY *)(prEntry))->prPrev = \ + (struct LINK_ENTRY *)NULL; \ + } while (0) + +#define LINK_ENTRY_INVALID(prEntry) \ + do { \ + ((struct LINK_ENTRY *)(prEntry))->prNext = \ + (struct LINK_ENTRY *)INVALID_LINK_POISON1; \ + ((struct LINK_ENTRY *)(prEntry))->prPrev = \ + (struct LINK_ENTRY *)INVALID_LINK_POISON2; \ + } while (0) + +#define LINK_IS_EMPTY(prLink) \ + (((struct LINK *)(prLink))->prNext == (struct LINK_ENTRY *)(prLink)) + +#define LINK_ENTRY_IS_VALID(prEntry) \ + (((struct LINK_ENTRY *)(prEntry))->prNext != \ + (struct LINK_ENTRY *)NULL && \ + ((struct LINK_ENTRY *)(prEntry))->prNext != \ + (struct LINK_ENTRY *)INVALID_LINK_POISON1 && \ + ((struct LINK_ENTRY *)(prEntry))->prPrev != \ + (struct LINK_ENTRY *)NULL && \ + ((struct LINK_ENTRY *)(prEntry))->prPrev != \ + (struct LINK_ENTRY *)INVALID_LINK_POISON2) + + + +/* 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) \ + (((struct LINK *)(prLink))->prNext == (struct LINK_ENTRY *)NULL) + +#define LINK_IS_VALID(prLink) \ + (((struct LINK *)(prLink))->prNext != (struct LINK_ENTRY *)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)(((struct LINK *)(prLink))->prNext); \ + linkDel((struct LINK_ENTRY *)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((struct LINK_ENTRY *)prEntry); \ + ((prLink)->u4NumElem)--; \ + } + +/* Merge prSrcLink to prDstLink and put prSrcLink ahead of prDstLink */ +#define LINK_MERGE_TO_HEAD(prDstLink, prSrcLink) \ + { \ + if (!LINK_IS_EMPTY(prSrcLink)) { \ + linkMergeToHead((struct LINK *)prDstLink, \ + (struct LINK *)prSrcLink); \ + (prDstLink)->u4NumElem += (prSrcLink)->u4NumElem; \ + LINK_INITIALIZE(prSrcLink); \ + } \ + } + +/* Merge prSrcLink to prDstLink and put prSrcLink at tail */ +#define LINK_MERGE_TO_TAIL(prDstLink, prSrcLink) \ + { \ + if (!LINK_IS_EMPTY(prSrcLink)) { \ + linkMergeToTail((struct LINK *)prDstLink, \ + (struct LINK *)prSrcLink); \ + (prDstLink)->u4NumElem += (prSrcLink)->u4NumElem; \ + LINK_INITIALIZE(prSrcLink); \ + } \ + } + +/* Iterate over a link list */ +#define LINK_FOR_EACH(prEntry, prLink) \ + for (prEntry = (prLink)->prNext; \ + prEntry != (struct LINK_ENTRY *)(prLink); \ + prEntry = (struct LINK_ENTRY *)prEntry->prNext) + +/* Iterate over a link list backwards */ +#define LINK_FOR_EACH_PREV(prEntry, prLink) \ + for (prEntry = (prLink)->prPrev; \ + prEntry != (struct LINK_ENTRY *)(prLink); \ + prEntry = (struct LINK_ENTRY *)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 != (struct LINK_ENTRY *)(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 != (struct LINK_ENTRY *)(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 != (struct LINK_ENTRY *)(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 != (struct LINK_ENTRY *)(prLink); \ + prObj = prNextObj, \ + prNextObj = LINK_ENTRY(prNextObj->rMember.prNext, _TYPE, rMember)) + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is only for internal link list manipulation. + * + * \param[in] prNew Pointer of new link head + * \param[in] prPrev Pointer of previous link head + * \param[in] prNext Pointer of next link head + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void __linkAdd(IN struct LINK_ENTRY + *prNew, IN struct LINK_ENTRY *prPrev, + IN struct LINK_ENTRY *prNext) +{ + prNext->prPrev = prNew; + prNew->prNext = prNext; + prNew->prPrev = prPrev; + prPrev->prNext = prNew; +} /* end of __linkAdd() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will add a new entry after the specified link head. + * + * \param[in] prNew New entry to be added + * \param[in] prHead Specified link head to add it after + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void linkAdd(IN struct LINK_ENTRY + *prNew, IN struct LINK *prLink) +{ + __linkAdd(prNew, (struct LINK_ENTRY *) prLink, + prLink->prNext); +} /* end of linkAdd() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will add a new entry before the specified link head. + * + * \param[in] prNew New entry to be added + * \param[in] prHead Specified link head to add it before + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void linkAddTail(IN struct LINK_ENTRY + *prNew, IN struct LINK *prLink) +{ + __linkAdd(prNew, prLink->prPrev, + (struct LINK_ENTRY *) prLink); +} /* end of linkAddTail() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is only for internal link list manipulation. + * + * \param[in] prPrev Pointer of previous link head + * \param[in] prNext Pointer of next link head + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void __linkDel(IN struct LINK_ENTRY + *prPrev, IN struct LINK_ENTRY *prNext) +{ + prNext->prPrev = prPrev; + prPrev->prNext = prNext; +} /* end of __linkDel() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will delete a specified entry from link list. + * NOTE: the entry is in an initial state. + * + * \param prEntry Specified link head(entry) + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void linkDel(IN struct LINK_ENTRY + *prEntry) +{ + __linkDel(prEntry->prPrev, prEntry->prNext); + + LINK_ENTRY_INITIALIZE(prEntry); +} /* end of linkDel() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will delete a specified entry from link list + * and then add it after the specified link head. + * + * \param[in] prEntry Specified link head(entry) + * \param[in] prOtherHead Another link head to add it after + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void linkMove(IN struct LINK_ENTRY + *prEntry, IN struct LINK *prLink) +{ + __linkDel(prEntry->prPrev, prEntry->prNext); + linkAdd(prEntry, prLink); +} /* end of linkMove() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will delete a specified entry from link list + * and then add it before the specified link head. + * + * \param[in] prEntry Specified link head(entry) + * \param[in] prOtherHead Another link head to add it before + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void linkMoveTail(IN struct LINK_ENTRY + *prEntry, IN struct LINK *prLink) +{ + __linkDel(prEntry->prPrev, prEntry->prNext); + linkAddTail(prEntry, prLink); +} /* end of linkMoveTail() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will merge source link to the tail of destination link. +* +* \param[in] prDst destination link +* \param[in] prSrc source link +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void linkMergeToTail(struct LINK *prDst, + struct LINK *prSrc) +{ + prSrc->prNext->prPrev = prDst->prPrev; + prSrc->prPrev->prNext = (struct LINK_ENTRY *)prDst; + prDst->prPrev->prNext = prSrc->prNext; + prDst->prPrev = prSrc->prPrev; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will merge source link to the head of destination link. +* +* \param[in] prDst destination link +* \param[in] prSrc source link + +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void linkMergeToHead(struct LINK *prDst, + struct LINK *prSrc) +{ + prSrc->prNext->prPrev = (struct LINK_ENTRY *)prDst; + prSrc->prPrev->prNext = prDst->prNext; + prDst->prNext->prPrev = prSrc->prPrev; + prDst->prNext = prSrc->prNext; +} + +#endif /* _LINK_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mtk_wifi_trace.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mtk_wifi_trace.h new file mode 100644 index 0000000000000..29d9a08411991 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mtk_wifi_trace.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Copyright (c) 2020 MediaTek Inc. + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM mtk_wifi_trace + +#if !defined(_TRACE_MTK_WIFI_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_MTK_WIFI_TRACE_H + +#include + +#define WIFI_LOG_MSG_MAX (512) + +TRACE_EVENT(wifi_standalone_log, + TP_PROTO(const char *str), + + TP_ARGS(str), + + TP_STRUCT__entry( + __string(msg, str) + ), + + TP_fast_assign( + __assign_str(msg, str); + ), + + TP_printk("[wlan]%s", __get_str(msg)) +); + +#endif +/* if !defined(_TRACE_MTK_WIFI_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) */ + +/* This part must be outside protection */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE mtk_wifi_trace +#include diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/adapter.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/adapter.h new file mode 100644 index 0000000000000..c9def8e37d274 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/adapter.h @@ -0,0 +1,1927 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \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. + */ + +#ifndef _ADAPTER_H +#define _ADAPTER_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#if CFG_SUPPORT_PASSPOINT +#include "hs20.h" +#endif /* CFG_SUPPORT_PASSPOINT */ +#include "gl_os.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +#define MIN_TX_DURATION_TIME_MS 100 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +enum { + ENUM_SW_TEST_MODE_NONE = 0, + ENUM_SW_TEST_MODE_SIGMA_AC = 0x1, + ENUM_SW_TEST_MODE_SIGMA_WFD = 0x2, + ENUM_SW_TEST_MODE_CTIA = 0x3, + ENUM_SW_TEST_MODE_SIGMA_TDLS = 0x4, + ENUM_SW_TEST_MODE_SIGMA_P2P = 0x5, + ENUM_SW_TEST_MODE_SIGMA_N = 0x6, + ENUM_SW_TEST_MODE_SIGMA_HS20_R1 = 0x7, + ENUM_SW_TEST_MODE_SIGMA_HS20_R2 = 0x8, + ENUM_SW_TEST_MODE_SIGMA_PMF = 0x9, + ENUM_SW_TEST_MODE_SIGMA_WMMPS = 0xA, + ENUM_SW_TEST_MODE_SIGMA_AC_R2 = 0xB, + ENUM_SW_TEST_MODE_SIGMA_NAN = 0xC, + ENUM_SW_TEST_MODE_SIGMA_AC_AP = 0xD, + ENUM_SW_TEST_MODE_SIGMA_N_AP = 0xE, + ENUM_SW_TEST_MODE_SIGMA_WFDS = 0xF, + ENUM_SW_TEST_MODE_SIGMA_WFD_R2 = 0x10, + ENUM_SW_TEST_MODE_SIGMA_LOCATION = 0x11, + ENUM_SW_TEST_MODE_SIGMA_TIMING_MANAGEMENT = 0x12, + ENUM_SW_TEST_MODE_SIGMA_WMMAC = 0x13, + ENUM_SW_TEST_MODE_SIGMA_VOICE_ENT = 0x14, + ENUM_SW_TEST_MODE_SIGMA_AX = 0x15, + ENUM_SW_TEST_MODE_SIGMA_AX_AP = 0x16, + ENUM_SW_TEST_MODE_NUM +}; + +struct ESS_SCAN_RESULT_T { + uint8_t aucBSSID[MAC_ADDR_LEN]; + uint16_t u2SSIDLen; + uint8_t aucSSID[PARAM_MAX_LEN_SSID]; +}; + +struct WLAN_INFO { + struct PARAM_BSSID_EX rCurrBssId[KAL_AIS_NUM]; + + /* Scan Result */ + struct PARAM_BSSID_EX arScanResult[CFG_MAX_NUM_BSS_LIST]; + uint8_t *apucScanResultIEs[CFG_MAX_NUM_BSS_LIST]; + uint32_t u4ScanResultNum; + + struct ESS_SCAN_RESULT_T arScanResultEss[CFG_MAX_NUM_BSS_LIST]; + uint32_t u4ScanResultEssNum; + uint32_t u4ScanDbgTimes1; + uint32_t u4ScanDbgTimes2; + uint32_t u4ScanDbgTimes3; + uint32_t u4ScanDbgTimes4; + + /* IE pool for Scanning Result */ + uint8_t aucScanIEBuf[CFG_MAX_COMMON_IE_BUF_LEN]; + uint32_t u4ScanIEBufferUsage; + + OS_SYSTIME u4SysTime; + + /* connection parameter (for Ad-Hoc) */ + uint16_t u2BeaconPeriod; + uint16_t u2AtimWindow; + + uint8_t eDesiredRates[PARAM_MAX_LEN_RATES]; + struct CMD_LINK_ATTRIB eLinkAttr; +/* CMD_PS_PROFILE_T ePowerSaveMode; */ + struct CMD_PS_PROFILE arPowerSaveMode[MAX_BSSID_NUM]; + + /* Support power save flag for the caller */ + uint32_t u4PowerSaveFlag[MAX_BSSID_NUM]; + + /* trigger parameter */ + enum ENUM_RSSI_TRIGGER_TYPE eRssiTriggerType; + int32_t rRssiTriggerValue; + + /* Privacy Filter */ + enum ENUM_PARAM_PRIVACY_FILTER ePrivacyFilter; + + /* RTS Threshold */ + uint32_t eRtsThreshold; + + /* Network Type */ + uint8_t ucNetworkType[KAL_AIS_NUM]; + + /* Network Type In Use */ + uint8_t ucNetworkTypeInUse; + + /* Force enable/disable power save mode*/ + u_int8_t fgEnSpecPwrMgt; + +}; + +/* Session for CONNECTION SETTINGS */ +struct CONNECTION_SETTINGS { + + uint8_t aucMacAddress[MAC_ADDR_LEN]; + + uint8_t ucDelayTimeOfDisconnectEvent; + + u_int8_t fgIsConnByBssidIssued; + uint8_t aucBSSID[MAC_ADDR_LEN]; + uint8_t aucBSSIDHint[MAC_ADDR_LEN]; + + uint8_t ucSSIDLen; + uint8_t aucSSID[ELEM_MAX_LEN_SSID]; + + enum ENUM_PARAM_OP_MODE eOPMode; + + enum ENUM_PARAM_CONNECTION_POLICY eConnectionPolicy; + + enum ENUM_PARAM_AD_HOC_MODE eAdHocMode; + + enum ENUM_PARAM_AUTH_MODE eAuthMode; + + enum ENUM_WEP_STATUS eEncStatus; + + u_int8_t fgIsScanReqIssued; + + /* MIB attributes */ + uint16_t u2BeaconPeriod; + + uint16_t u2RTSThreshold; /* User desired setting */ + + uint16_t u2DesiredNonHTRateSet; /* User desired setting */ + + uint8_t ucAdHocChannelNum; /* For AdHoc */ + + enum ENUM_BAND eAdHocBand; /* For AdHoc */ + + uint32_t u4FreqInKHz; /* Center frequency */ + + /* ATIM windows using for IBSS power saving function */ + uint16_t u2AtimWindow; + + /* Features */ + u_int8_t fgIsEnableRoaming; + + u_int8_t fgIsAdHocQoSEnable; + + enum ENUM_PARAM_PHY_CONFIG eDesiredPhyConfig; + +#if CFG_SUPPORT_802_11D + u_int8_t fgMultiDomainCapabilityEnabled; +#endif /* CFG_SUPPORT_802_11D */ + +#if 1 /* CFG_SUPPORT_WAPI */ + u_int8_t fgWapiMode; + uint32_t u4WapiSelectedGroupCipher; + uint32_t u4WapiSelectedPairwiseCipher; + uint32_t u4WapiSelectedAKMSuite; +#endif + + /* for cfg80211 connected indication */ + uint32_t u4RspIeLength; + uint8_t aucRspIe[CFG_CFG80211_IE_BUF_LEN]; + + uint32_t u4ReqIeLength; + uint8_t aucReqIe[CFG_CFG80211_IE_BUF_LEN]; + + u_int8_t fgWpsActive; + uint8_t aucWSCIE[GLUE_INFO_WSCIE_LENGTH]; /*for probe req */ + uint16_t u2WSCIELen; + + /* + * Buffer to hold non-wfa vendor specific IEs set + * from wpa_supplicant. This is used in sending + * Association Request in AIS mode. + */ + uint16_t non_wfa_vendor_ie_len; + uint8_t non_wfa_vendor_ie_buf[NON_WFA_VENDOR_IE_MAX_LEN]; + + /* 11R */ + struct FT_IES rFtIeForTx; + struct cfg80211_ft_event_params rFtEventParam; + + /* CR1486, CR1640 */ + /* for WPS, disable the privacy check for AP selection policy */ + u_int8_t fgPrivacyCheckDisable; + + /* b0~3: trigger-en AC0~3. b4~7: delivery-en AC0~3 */ + uint8_t bmfgApsdEnAc; + + /* for RSN info store, when upper layer set rsn info */ + struct RSN_INFO rRsnInfo; + +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE + u_int8_t fgSecModeChangeStartTimer; +#endif + + uint8_t *pucAssocIEs; + size_t assocIeLen; +}; + +struct BSS_INFO { + + enum ENUM_NETWORK_TYPE eNetworkType; + + /* Private data parameter for each NETWORK type usage. */ + uint32_t u4PrivateData; + /* P2P network type has 3 network interface to distinguish. */ + + /* Connected Flag used in AIS_NORMAL_TR */ + enum ENUM_PARAM_MEDIA_STATE eConnectionState; + /* The Media State that report to HOST */ + enum ENUM_PARAM_MEDIA_STATE eConnectionStateIndicated; + + /* Current Operation Mode - Infra/IBSS */ + enum ENUM_OP_MODE eCurrentOPMode; +#if CFG_ENABLE_WIFI_DIRECT + enum ENUM_OP_MODE eIntendOPMode; +#endif + +#if (CFG_SUPPORT_DFS_MASTER == 1) + u_int8_t fgIsDfsActive; +#endif + + u_int8_t fgIsInUse; /* For CNM to assign BSS_INFO */ + u_int8_t fgIsNetActive; /* TRUE if this network has been activated */ + + uint8_t ucBssIndex; /* BSS_INFO_T index */ + + uint8_t ucReasonOfDisconnect; /* Used by media state indication */ + + uint8_t ucSSIDLen; /* Length of SSID */ + +#if CFG_ENABLE_WIFI_DIRECT + /* For Hidden SSID usage. */ + enum ENUM_HIDDEN_SSID_TYPE eHiddenSsidType; +#endif + + uint8_t aucSSID[ELEM_MAX_LEN_SSID]; /* SSID used in this BSS */ + + uint8_t aucBSSID[MAC_ADDR_LEN]; /* The BSSID of the associated BSS */ + + /* Owned MAC Address used in this BSS */ + uint8_t aucOwnMacAddr[MAC_ADDR_LEN]; + + uint8_t ucOwnMacIndex; /* Owned MAC index used in this BSS */ + + /* For Infra Mode, and valid only if + * eConnectionState == MEDIA_STATE_CONNECTED + */ + struct STA_RECORD *prStaRecOfAP; + /* For IBSS/AP Mode, all known STAs in current BSS */ + struct LINK rStaRecOfClientList; + + /* For open Mode, BC/MC Tx wlan index, For STA, BC/MC Rx wlan index */ + uint8_t ucBMCWlanIndex; + + /* For AP Mode, BC/MC Tx wlan index, For STA, BC/MC Rx wlan index */ + uint8_t ucBMCWlanIndexS[MAX_KEY_NUM]; + uint8_t ucBMCWlanIndexSUsed[MAX_KEY_NUM]; + + u_int8_t fgBcDefaultKeyExist; /* Bc Transmit key exist or not */ + /* Bc default key idx, for STA, the Rx just set, + * for AP, the tx key id + */ + uint8_t ucBcDefaultKeyIdx; + + uint8_t wepkeyUsed[MAX_KEY_NUM]; + uint8_t wepkeyWlanIdx; /* wlan index of the wep key */ + + uint16_t u2CapInfo; /* Change Detection */ + + uint16_t u2BeaconInterval; /* The Beacon Interval of this BSS */ + + uint16_t u2ATIMWindow; /* For IBSS Mode */ + + /* For Infra Mode, it is the Assoc ID assigned by AP. */ + uint16_t u2AssocId; + + uint8_t ucDTIMPeriod; /* For Infra/AP Mode */ + u_int8_t fgTIMPresent; + + /* For AP Mode, it is the DTIM value we should carried in + * the Beacon of next TBTT. + */ + uint8_t ucDTIMCount; + + /* Available PHY Type Set of this peer + * (This is deduced from received struct BSS_DESC) + */ + uint8_t ucPhyTypeSet; + + /* The Basic PHY Type Index, used to setup Phy Capability */ + uint8_t ucNonHTBasicPhyType; + /* The configuration of AdHoc/AP Mode. e.g. 11g or 11b */ + uint8_t ucConfigAdHocAPMode; + u_int8_t fgIsWepCipherGroup; + + /* For Infra/AP Mode, it is a threshold of Beacon Lost Count to + * confirm connection was lost + */ + uint8_t ucBeaconTimeoutCount; + + /* For IBSS Mode, to keep use same BSSID + * to extend the life cycle of an IBSS + */ + u_int8_t fgHoldSameBssidForIBSS; + /* For AP/IBSS Mode, it is used to indicate that Beacon is sending */ + u_int8_t fgIsBeaconActivated; + + struct MSDU_INFO *prBeacon; /* For AP/IBSS Mode - Beacon Frame */ + + /* For IBSS Mode - To indicate that we can reply ProbeResp Frame. + * In current TBTT interval + */ + u_int8_t fgIsIBSSMaster; + + /* From Capability Info. of AssocResp Frame + * AND of Beacon/ProbeResp Frame + */ + u_int8_t fgIsShortPreambleAllowed; + /* Short Preamble is enabled in current BSS. */ + u_int8_t fgUseShortPreamble; + /* Short Slot Time is enabled in current BSS. */ + u_int8_t fgUseShortSlotTime; + + /* Operational Rate Set of current BSS */ + uint16_t u2OperationalRateSet; + uint16_t u2BSSBasicRateSet; /* Basic Rate Set of current BSS */ + + /* Used for composing Beacon Frame in AdHoc or AP Mode */ + uint8_t ucAllSupportedRatesLen; + uint8_t aucAllSupportedRates[RATE_NUM_SW]; + /* TODO(Kevin): Number of associated clients */ + uint8_t ucAssocClientCnt; + + u_int8_t fgIsProtection; + /* For Infra/AP/IBSS Mode, it is used to indicate if we support WMM in + * current BSS. + */ + u_int8_t fgIsQBSS; + u_int8_t fgIsNetAbsent; /* TRUE: BSS is absent, FALSE: BSS is present */ + + uint32_t u4RsnSelectedGroupCipher; + uint32_t u4RsnSelectedPairwiseCipher; + uint32_t u4RsnSelectedAKMSuite; + uint16_t u2RsnSelectedCapInfo; + + /*-------------------------------------------------------------------*/ + /* Operation mode change notification */ + /*-------------------------------------------------------------------*/ + /*Need to change OpMode channel width*/ + u_int8_t fgIsOpChangeChannelWidth; + /* The OpMode channel width that we want to change to*/ + /* 0:20MHz, 1:40MHz, 2:80MHz, 3:160MHz 4:80+80MHz*/ + uint8_t ucOpChangeChannelWidth; + + /* Need to change OpMode RxNss */ + uint8_t fgIsOpChangeRxNss; + /* The OpMode RxNss that we want to change to */ + uint8_t ucOpChangeRxNss; + + /* Need to change OpMode TxNss */ + uint8_t fgIsOpChangeTxNss; + /* The OpMode TxNss that we want to change to */ + uint8_t ucOpChangeTxNss; + + PFN_OPMODE_NOTIFY_DONE_FUNC pfOpChangeHandler; + + uint8_t aucOpModeChangeState[OP_NOTIFY_TYPE_NUM]; + + uint8_t aucOpModeChangeRetryCnt[OP_NOTIFY_TYPE_NUM]; + + + /*-------------------------------------------------------------------*/ + /* Power Management related information */ + /*-------------------------------------------------------------------*/ + struct PM_PROFILE_SETUP_INFO rPmProfSetupInfo; + + /*-------------------------------------------------------------------*/ + /* WMM/QoS related information */ + /*-------------------------------------------------------------------*/ + /* Used to detect the change of EDCA parameters. For AP mode, + * the value is used in WMM IE + */ + uint8_t ucWmmParamSetCount; + + struct AC_QUE_PARMS arACQueParms[WMM_AC_INDEX_NUM]; + /* For AP mode, broadcast the CWminLog2 */ + uint8_t aucCWminLog2ForBcast[WMM_AC_INDEX_NUM]; + /* For AP mode, broadcast the CWmaxLog2 */ + uint8_t aucCWmaxLog2ForBcast[WMM_AC_INDEX_NUM]; + /* For AP mode, broadcast the value */ + struct AC_QUE_PARMS arACQueParmsForBcast[WMM_AC_INDEX_NUM]; + uint8_t ucWmmQueSet; +#if (CFG_SUPPORT_802_11AX == 1) + uint8_t ucMUEdcaUpdateCnt; + /* + * Store MU EDCA params for each ACs in BSS info + * Use the same format as the update cmd for memory copy + */ + struct _CMD_MU_EDCA_PARAMS_T arMUEdcaParams[WMM_AC_INDEX_NUM]; + + /* Spatial Reuse Parameter Set for the BSS */ + uint8_t ucSRControl; + uint8_t ucNonSRGObssPdMaxOffset; + uint8_t ucSRGObssPdMinOffset; + uint8_t ucSRGObssPdMaxOffset; + uint64_t u8SRGBSSColorBitmap; + uint64_t u8SRGPartialBSSIDBitmap; +#endif + +#if (CFG_HW_WMM_BY_BSS == 1) + u_int8_t fgIsWmmInited; +#endif + + /*-------------------------------------------------------------------*/ + /* 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 ENUM_BAND eBand; + uint8_t ucPrimaryChannel; + uint8_t ucHtOpInfo1; + uint16_t u2HtOpInfo2; + uint16_t u2HtOpInfo3; + uint8_t ucOpRxNss; /* Own OP RxNss */ + uint8_t ucOpTxNss; /* Own OP TxNss */ + + /*-------------------------------------------------------------------*/ + /* 802.11ac VHT operation IE when (prStaRec->ucPhyTypeSet */ + /* & PHY_TYPE_BIT_VHT) is true. They have the same definition with */ + /* fields of information element (EASON) */ + /*-------------------------------------------------------------------*/ +#if 1 /* CFG_SUPPORT_802_11AC */ + uint8_t ucVhtChannelWidth; + uint8_t ucVhtChannelFrequencyS1; + uint8_t ucVhtChannelFrequencyS2; + uint16_t u2VhtBasicMcsSet; +#endif +#if (CFG_SUPPORT_802_11AX == 1) + uint8_t ucHeOpParams[HE_OP_BYTE_NUM]; + uint8_t ucBssColorInfo; + uint16_t u2HeBasicMcsSet; +#endif + +#if (CFG_SUPPORT_802_11V_MBSSID == 1) + uint8_t ucMaxBSSIDIndicator; + uint8_t ucMBSSIDIndex; +#endif + + /*-------------------------------------------------------------------*/ + /* Required protection modes (CM) */ + /*-------------------------------------------------------------------*/ + u_int8_t fgErpProtectMode; + enum ENUM_HT_PROTECT_MODE eHtProtectMode; + enum ENUM_GF_MODE eGfOperationMode; + enum ENUM_RIFS_MODE eRifsOperationMode; + + u_int8_t fgObssErpProtectMode; /* GO only */ + enum ENUM_HT_PROTECT_MODE eObssHtProtectMode; /* GO only */ + enum ENUM_GF_MODE eObssGfOperationMode; /* GO only */ + u_int8_t fgObssRifsOperationMode; /* GO only */ + + /*-------------------------------------------------------------------*/ + /* OBSS to decide if 20/40M bandwidth is permitted. */ + /* The first member indicates the following channel list length. */ + /*-------------------------------------------------------------------*/ + u_int8_t fgAssoc40mBwAllowed; + u_int8_t fg40mBwAllowed; + enum ENUM_CHNL_EXT eBssSCO; /* Real setting for HW + * 20/40M AP mode will always set 40M, + * but its OP IE can be changed. + */ + uint8_t auc2G_20mReqChnlList[CHNL_LIST_SZ_2G + 1]; + uint8_t auc2G_NonHtChnlList[CHNL_LIST_SZ_2G + 1]; + uint8_t auc2G_PriChnlList[CHNL_LIST_SZ_2G + 1]; + uint8_t auc2G_SecChnlList[CHNL_LIST_SZ_2G + 1]; + + uint8_t auc5G_20mReqChnlList[CHNL_LIST_SZ_5G + 1]; + uint8_t auc5G_NonHtChnlList[CHNL_LIST_SZ_5G + 1]; + uint8_t auc5G_PriChnlList[CHNL_LIST_SZ_5G + 1]; + uint8_t auc5G_SecChnlList[CHNL_LIST_SZ_5G + 1]; + + /*-------------------------------------------------------------------*/ + /* Scan related information */ + /*-------------------------------------------------------------------*/ + /* Set scanning MAC OUI */ + u_int8_t fgIsScanOuiSet; + uint8_t ucScanOui[MAC_OUI_LEN]; + + struct TIMER rObssScanTimer; + uint16_t u2ObssScanInterval; /* in unit of sec */ + + u_int8_t fgObssActionForcedTo20M; /* GO only */ + u_int8_t fgObssBeaconForcedTo20M; /* GO only */ + + /*--------------------------------------------------------------------*/ + /* HW Related Fields (Kevin) */ + /*--------------------------------------------------------------------*/ + /* The default rate code copied to MAC TX Desc */ + uint16_t u2HwDefaultFixedRateCode; + uint16_t u2HwLPWakeupGuardTimeUsec; + + uint8_t ucBssFreeQuota; /* The value is updated from FW */ + +#if CFG_ENABLE_GTK_FRAME_FILTER + struct IPV4_NETWORK_ADDRESS_LIST *prIpV4NetAddrList; +#endif + uint16_t u2DeauthReason; + +#if CFG_SUPPORT_TDLS + u_int8_t fgTdlsIsProhibited; + u_int8_t fgTdlsIsChSwProhibited; +#endif + + /*link layer statistics */ + struct WIFI_WMM_AC_STAT arLinkStatistics[WMM_AC_INDEX_NUM]; + + uint32_t u4CoexPhyRateLimit; + + u_int8_t fgIsGranted; + enum ENUM_BAND eBandGranted; + uint8_t ucPrimaryChannelGranted; + struct PARAM_CUSTOM_ACL rACL; + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + struct AP_PMF_CFG rApPmfCfg; + /* STA PMF: for encrypted deauth frame */ + struct completion rDeauthComp; + u_int8_t encryptedDeauthIsInProcess; +#endif + +#if (CFG_SUPPORT_HE_ER == 1) + uint8_t ucErMode; +#endif + + uint8_t ucCountryIELen; + uint8_t aucCountryStr[3]; + uint8_t aucSubbandTriplet[253]; + enum ENUM_IFTYPE eIftype; + + /* Buffer for WPA2 PMKID */ + /* The PMKID cache lifetime is expire by media_disconnect_indication */ + struct LINK rPmkidCache; +}; + +/* Support AP Selection */ +struct ESS_CHNL_INFO { + uint8_t ucChannel; + uint8_t ucUtilization; + uint8_t ucApNum; +}; +/* end Support AP Selection */ + +struct NEIGHBOR_AP_T { + struct LINK_ENTRY rLinkEntry; + uint8_t aucBssid[MAC_ADDR_LEN]; + u_int8_t fgHT:1; + u_int8_t fgSameMD:1; + u_int8_t fgRmEnabled:1; + u_int8_t fgFromBtm:1; + u_int8_t fgQoS:1; + uint8_t ucReserved:3; + u_int8_t fgPrefPresence; + uint8_t ucPreference; + uint8_t ucChannel; + uint64_t u8TermTsf; +}; + +struct AIS_SPECIFIC_BSS_INFO { + /* This value indicate the roaming type used in AIS_JOIN */ + uint8_t ucRoamingAuthTypes; + + u_int8_t fgIsIBSSActive; + + /*! \brief Global flag to let arbiter stay at standby + * and not connect to any network + */ + u_int8_t fgCounterMeasure; + +#if 0 + u_int8_t fgWepWapiBcKeyExist; /* WEP WAPI BC key exist flag */ + uint8_t ucWepWapiBcWlanIndex; /* WEP WAPI BC wlan index */ + + /* RSN BC key exist flag, map to key id 0, 1, 2, 3 */ + u_int8_t fgRsnBcKeyExist[4]; + /* RSN BC wlan index, map to key id 0, 1, 2, 3 */ + uint8_t ucRsnBcWlanIndex[4]; +#endif + + /* While Do CounterMeasure procedure, + * check the EAPoL Error report have send out + */ + u_int8_t fgCheckEAPoLTxDone; + + uint32_t u4RsnaLastMICFailTime; + + /* 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 + */ + struct TIMER rRsnaBlockTrafficTimer; + struct TIMER rRsnaEAPoLReportTimeoutTimer; + + /* For Keep the Tx/Rx Mic key for TKIP SW Calculate Mic */ + /* This is only one for AIS/AP */ + uint8_t aucTxMicKey[8]; + uint8_t aucRxMicKey[8]; + + /* Buffer for WPA2 PMKID */ + /* The PMKID cache lifetime is expire by media_disconnect_indication */ + struct LINK rPmkidCache; +#if CFG_SUPPORT_802_11W + u_int8_t fgMgmtProtection; + uint32_t u4SaQueryStart; + uint32_t u4SaQueryCount; + uint8_t ucSaQueryTimedOut; + uint8_t *pucSaQueryTransId; + struct TIMER rSaQueryTimer; + u_int8_t fgBipKeyInstalled; +#endif + uint8_t ucKeyAlgorithmId; + + /* Support AP Selection */ +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + uint8_t ucRoamSkipTimes; + u_int8_t fgGoodRcpiArea; + u_int8_t fgPoorRcpiArea; +#endif + struct ESS_CHNL_INFO arCurEssChnlInfo[CFG_MAX_NUM_OF_CHNL_INFO]; + uint8_t ucCurEssChnlInfoNum; + struct LINK rCurEssLink; + /* end Support AP Selection */ + + struct BSS_TRANSITION_MGT_PARAM_T rBTMParam; + struct LINK_MGMT rNeighborApList; + OS_SYSTIME rNeiApRcvTime; + uint32_t u4NeiApValidInterval; +}; + +struct BOW_SPECIFIC_BSS_INFO { + uint16_t u2Reserved; /* Reserved for Data Type Check */ +}; + +#if CFG_SLT_SUPPORT +struct SLT_INFO { + + struct BSS_DESC *prPseudoBssDesc; + uint16_t u2SiteID; + uint8_t ucChannel2G4; + uint8_t ucChannel5G; + u_int8_t fgIsDUT; + uint32_t u4BeaconReceiveCnt; + /* ///////Deprecated///////// */ + struct STA_RECORD *prPseudoStaRec; +}; +#endif + +struct WLAN_TABLE { + uint8_t ucUsed; + uint8_t ucBssIndex; + uint8_t ucKeyId; + uint8_t ucPairwise; + uint8_t aucMacAddr[MAC_ADDR_LEN]; + uint8_t ucStaIndex; +}; + +/* Major member variables for WiFi FW operation. + * Variables within this region will be ready for + * access after WIFI function is enabled. + */ +struct WIFI_VAR { + u_int8_t fgIsRadioOff; + + u_int8_t fgIsEnterD3ReqIssued; + + u_int8_t fgDebugCmdResp; + + /* Common connection settings start */ + /* Used for AP mode for desired channel and bandwidth */ + uint16_t u2CountryCode; + uint8_t uc2G4BandwidthMode; /* 20/40M or 20M only *//* Not used */ + uint8_t uc5GBandwidthMode; /* 20/40M or 20M only *//* Not used */ + /* Support AP Selection */ + struct LINK_MGMT rBlackList; +#if CFG_SUPPORT_MBO + struct PARAM_BSS_DISALLOWED_LIST rBssDisallowedList; +#endif + enum ENUM_PARAM_PHY_CONFIG eDesiredPhyConfig; + /* Common connection settings end */ + + struct CONNECTION_SETTINGS rConnSettings[KAL_AIS_NUM]; + + struct SCAN_INFO rScanInfo; + +#if CFG_SUPPORT_ROAMING + struct ROAMING_INFO rRoamingInfo[KAL_AIS_NUM]; +#endif /* CFG_SUPPORT_ROAMING */ + + struct AIS_FSM_INFO rAisFsmInfo[KAL_AIS_NUM]; + + enum ENUM_PWR_STATE aePwrState[MAX_BSSID_NUM + 1]; + + struct BSS_INFO arBssInfoPool[MAX_BSSID_NUM]; + + struct BSS_INFO rP2pDevInfo; + + struct AIS_SPECIFIC_BSS_INFO rAisSpecificBssInfo[KAL_AIS_NUM]; + +#if CFG_ENABLE_WIFI_DIRECT + struct P2P_CONNECTION_SETTINGS *prP2PConnSettings[BSS_P2P_NUM]; + + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo[BSS_P2P_NUM]; + +/* P_P2P_FSM_INFO_T prP2pFsmInfo; */ + + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo; + + /* Currently we only support 2 p2p interface. */ + struct P2P_ROLE_FSM_INFO *aprP2pRoleFsmInfo[BSS_P2P_NUM]; + +#if CFG_ENABLE_PER_STA_STATISTICS_LOG + struct PARAM_GET_STA_STATISTICS *prP2pQueryStaStatistics[BSS_P2P_NUM]; +#endif + +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +#if CFG_ENABLE_BT_OVER_WIFI + struct BOW_SPECIFIC_BSS_INFO rBowSpecificBssInfo; + struct BOW_FSM_INFO rBowFsmInfo; +#endif /* CFG_ENABLE_BT_OVER_WIFI */ + + struct WLAN_TABLE arWtbl[WTBL_SIZE]; + + struct DEAUTH_INFO arDeauthInfo[MAX_DEAUTH_INFO_COUNT]; + + /* Current Wi-Fi Settings and Flags */ + uint8_t aucPermanentAddress[MAC_ADDR_LEN]; + uint8_t aucMacAddress[MAC_ADDR_LEN]; + uint8_t aucMacAddress1[MAC_ADDR_LEN]; + uint8_t aucDeviceAddress[MAC_ADDR_LEN]; + uint8_t aucInterfaceAddress[KAL_P2P_NUM][MAC_ADDR_LEN]; + + uint8_t ucAvailablePhyTypeSet; + + /* Basic Phy Type used by SCN according + * to the set of Available PHY Types + */ + enum ENUM_PHY_TYPE_INDEX eNonHTBasicPhyType2G4; + + enum ENUM_PARAM_PREAMBLE_TYPE ePreambleType; + enum ENUM_REGISTRY_FIXED_RATE eRateSetting; + + u_int8_t fgIsShortSlotTimeOptionEnable; + /* User desired setting, but will honor the capability of AP */ + + u_int8_t fgEnableJoinToHiddenSSID; + u_int8_t fgSupportWZCDisassociation; + +#if CFG_SUPPORT_WFD + struct WFD_CFG_SETTINGS rWfdConfigureSettings; +#endif + +#if CFG_SLT_SUPPORT + struct SLT_INFO rSltInfo; +#endif + +#if CFG_SUPPORT_PASSPOINT + struct HS20_INFO rHS20Info[KAL_AIS_NUM]; +#endif /* CFG_SUPPORT_PASSPOINT */ + uint8_t aucMediatekOuiIE[64]; + uint16_t u2MediatekOuiIELen; + + /* Feature Options */ + uint8_t ucQoS; + + uint8_t ucStaHt; + uint8_t ucStaVht; +#if (CFG_SUPPORT_802_11AX == 1) + uint8_t ucStaHe; + uint8_t ucApHe; + uint8_t ucP2pGoHe; + uint8_t ucP2pGcHe; + uint8_t ucApSelAxWeight; + uint8_t ucApSelAxScoreDiv; +#endif + uint8_t ucApHt; + uint8_t ucApVht; + uint8_t ucP2pGoHt; + uint8_t ucP2pGoVht; + uint8_t ucP2pGcHt; + uint8_t ucP2pGcVht; + + /* NIC capability from FW event*/ + uint8_t ucHwNotSupportAC; + + uint8_t ucAmpduTx; + uint8_t ucAmpduRx; + uint8_t ucAmsduInAmpduTx; + uint8_t ucAmsduInAmpduRx; + uint8_t ucHtAmsduInAmpduTx; + uint8_t ucHtAmsduInAmpduRx; + uint8_t ucVhtAmsduInAmpduTx; + uint8_t ucVhtAmsduInAmpduRx; +#if (CFG_SUPPORT_802_11AX == 1) + uint8_t ucHeAmsduInAmpduTx; + uint8_t ucHeAmsduInAmpduRx; + uint8_t ucHeCertForceAmsdu; + uint8_t ucTrigMacPadDur; + uint8_t ucStaHeBfee; +#endif +#if (CFG_SUPPORT_TWT == 1) + uint8_t ucTWTRequester; + uint8_t ucTWTResponder; + uint8_t ucTWTStaBandBitmap; +#endif + + uint8_t ucTspec; + uint8_t ucUapsd; + uint8_t ucStaUapsd; + uint8_t ucApUapsd; + uint8_t ucP2pUapsd; + + uint8_t ucTxShortGI; + uint8_t ucRxShortGI; + uint8_t ucTxLdpc; + uint8_t ucRxLdpc; + uint8_t ucTxStbc; + uint8_t ucRxStbc; + uint8_t ucRxStbcNss; + uint8_t ucTxGf; + uint8_t ucRxGf; + + uint8_t ucMCS32; + + uint8_t ucTxopPsTx; + uint8_t ucSigTaRts; + uint8_t ucDynBwRts; + + uint8_t ucStaHtBfee; + uint8_t ucStaVhtBfee; + uint8_t ucStaHtBfer; + uint8_t ucStaVhtBfer; + uint8_t ucStaVhtMuBfee; + uint8_t fgForceSTSNum; + + uint8_t ucDataTxDone; + uint8_t ucDataTxRateMode; + uint32_t u4DataTxRateCode; + + uint8_t ucApWpsMode; + uint8_t ucApChannel; + + uint8_t ucApSco; + uint8_t ucP2pGoSco; + + uint8_t ucStaBandwidth; + uint8_t ucSta5gBandwidth; + uint8_t ucSta2gBandwidth; + uint8_t ucApBandwidth; + uint8_t ucAp2gBandwidth; + uint8_t ucAp5gBandwidth; + uint8_t ucP2p5gBandwidth; + uint8_t ucP2p2gBandwidth; + + /* If enable, AP channel bandwidth Channel + * Center Frequency Segment 0/1 + */ + /* and secondary channel offset will align wifi.cfg */ + /* Otherwise align cfg80211 */ + uint8_t ucApChnlDefFromCfg; + + /* + * According TGn/TGac 4.2.44, AP should not connect + * with TKIP client with HT/VHT capabilities. We leave + * a wifi.cfg item for user to decide whether to + * enable HT/VHT capabilities in that case + */ + uint8_t ucApAllowHtVhtTkip; + + uint8_t ucNSS; + uint8_t fgSta1NSS; /* Less or euqal than ucNss */ + uint8_t ucAp5gNSS; /* Less or euqal than ucNss */ + uint8_t ucAp2gNSS; /* Less or euqal than ucNss */ + uint8_t ucGo5gNSS; /* Less or euqal than ucNss */ + uint8_t ucGo2gNSS; /* Less or euqal than ucNss */ + + uint8_t ucRxMaxMpduLen; + uint32_t u4TxMaxAmsduInAmpduLen; + + uint8_t ucTxBaSize; + uint8_t ucRxHtBaSize; + uint8_t ucRxVhtBaSize; +#if (CFG_SUPPORT_802_11AX == 1) + uint16_t u2RxHeBaSize; + uint16_t u2TxHeBaSize; +#endif + + uint8_t ucThreadScheduling; + uint8_t ucThreadPriority; + int8_t cThreadNice; + + uint8_t ucTcRestrict; + uint32_t u4MaxTxDeQLimit; + uint8_t ucAlwaysResetUsedRes; + + uint32_t u4NetifStopTh; + uint32_t u4NetifStartTh; + struct PARAM_GET_CHN_INFO rChnLoadInfo; + +#if CFG_SUPPORT_MTK_SYNERGY + uint8_t ucMtkOui; + uint32_t u4MtkOuiCap; + uint8_t aucMtkFeature[4]; + u_int8_t ucGbandProbe256QAM; +#endif +#if CFG_SUPPORT_VHT_IE_IN_2G + uint8_t ucVhtIeIn2g; +#endif + u_int8_t fgCsaInProgress; + uint8_t ucChannelSwitchMode; + uint8_t ucNewChannelNumber; + uint8_t ucChannelSwitchCount; + + uint32_t u4HifIstLoopCount; + uint32_t u4Rx2OsLoopCount; + uint32_t u4HifTxloopCount; + uint32_t u4TxRxLoopCount; + uint32_t u4TxFromOsLoopCount; + uint32_t u4TxIntThCount; + + uint32_t au4TcPageCount[TC_NUM]; + uint32_t au4TcPageCountPle[TC_NUM]; + uint8_t ucExtraTxDone; + uint8_t ucTxDbg; + + uint8_t ucCmdRsvResource; + uint32_t u4MgmtQueueDelayTimeout; + + uint32_t u4StatsLogTimeout; + uint32_t u4StatsLogDuration; + uint8_t ucDhcpTxDone; + uint8_t ucArpTxDone; + + uint8_t ucMacAddrOverride; + uint8_t aucMacAddrStr[WLAN_CFG_VALUE_LEN_MAX]; + + uint8_t ucCtiaMode; + uint8_t ucTpTestMode; + uint8_t ucSigmaTestMode; +#if CFG_SUPPORT_DBDC + enum ENUM_CNM_DBDC_MODE eDbdcMode; + u_int8_t fgDbDcModeEn; +#endif + uint8_t u4ScanCtrl; + uint8_t ucScanChannelListenTime; + +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1) + uint8_t ucEfuseBufferModeCal; +#endif + uint8_t ucCalTimingCtrl; + uint8_t ucWow; + uint8_t ucOffload; + uint8_t ucAdvPws; /* enable LP multiple DTIM function, default enable */ + uint8_t ucWowOnMdtim; /* multiple DTIM if WOW enable, default 1 */ + uint8_t ucWowOffMdtim; /* multiple DTIM if WOW disable, default 3 */ + + uint8_t u4SwTestMode; + uint8_t ucCtrlFlagAssertPath; + uint8_t ucCtrlFlagDebugLevel; + uint32_t u4WakeLockRxTimeout; + uint32_t u4WakeLockThreadWakeup; + uint32_t u4RegP2pIfAtProbe; /* register p2p interface during probe */ + /* p2p group interface use the same mac addr as p2p device interface */ + uint8_t ucP2pShareMacAddr; + uint8_t ucSmartRTS; + + uint32_t u4UapsdAcBmp; + uint32_t u4MaxSpLen; + /* 0: enable online scan, non-zero: disable online scan */ + uint32_t fgDisOnlineScan; + uint32_t fgDisBcnLostDetection; + uint32_t fgDisRoaming; /* 0:enable roaming 1:disable */ + uint32_t u4AisRoamingNumber; + uint32_t fgEnArpFilter; + + uint8_t uDeQuePercentEnable; + uint32_t u4DeQuePercentVHT80Nss1; + uint32_t u4DeQuePercentVHT40Nss1; + uint32_t u4DeQuePercentVHT20Nss1; + uint32_t u4DeQuePercentHT40Nss1; + uint32_t u4DeQuePercentHT20Nss1; + + uint32_t u4PerfMonUpdatePeriod; + uint32_t u4PerfMonTpTh[PERF_MON_TP_MAX_THRESHOLD]; + uint32_t u4BoostCpuTh; + + uint32_t u4PerfMonPendingTh; + uint32_t u4PerfMonUsedTh; + + u_int8_t fgTdlsBufferSTASleep; /* Support TDLS 5.5.4.2 optional case */ + u_int8_t fgChipResetRecover; + enum PARAM_POWER_MODE ePowerMode; + + u_int8_t fgNvramCheckEn; /* nvram checking in scan result*/ + + uint8_t fgEnableSer; + uint8_t fgRstRecover; + +#if CFG_SUPPORT_SPE_IDX_CONTROL + u_int8_t ucSpeIdxCtrl; /* 0: WF0, 1: WF1, 2: duplicate */ +#endif + +#if CFG_SUPPORT_LOWLATENCY_MODE + uint8_t ucLowLatencyModeScan; + uint8_t ucLowLatencyModeReOrder; + uint8_t ucLowLatencyModePower; + uint8_t ucLowLatencyPacketPriority; + uint8_t ucLowLatencyCmdData; + uint8_t ucLowLatencyCmdDataAllPacket; +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ +#if CFG_SUPPORT_IDC_CH_SWITCH + uint8_t ucChannelSwtichColdownTime; + uint8_t fgCrossBandSwitchEn; +#endif +#if CFG_SUPPORT_PERF_IND + u_int8_t fgPerfIndicatorEn; +#endif + + /* 11K */ + struct RADIO_MEASUREMENT_REQ_PARAMS rRmReqParams[KAL_AIS_NUM]; + struct RADIO_MEASUREMENT_REPORT_PARAMS rRmRepParams[KAL_AIS_NUM]; + + /* WMMAC */ + struct WMM_INFO rWmmInfo[KAL_AIS_NUM]; + + /* Tx Msdu Queue method */ + uint8_t ucTxMsduQueue; + uint8_t ucTxMsduQueueInit; + uint32_t u4TxHifRes; + + uint32_t u4MTU; /* net device maximum transmission unit */ +#if CFG_SUPPORT_RX_GRO + uint32_t ucGROFlushTimeout; /* Flush packet timeout (ms) */ + uint32_t ucGROEnableTput; /* Threshold of enable GRO Tput */ +#endif + +#if CFG_SUPPORT_IOT_AP_BLACKLIST + uint8_t fgEnDefaultIotApRule; +#endif + uint8_t ucMsduReportTimeout; + +#if CFG_SUPPORT_DATA_STALL + uint32_t u4PerHighThreshole; + uint32_t u4TxLowRateThreshole; + uint32_t u4RxLowRateThreshole; + uint32_t u4ReportEventInterval; + uint32_t u4TrafficThreshold; +#endif + +#if CFG_SUPPORT_HE_ER + uint8_t u4ExtendedRange; +#endif +#if CFG_SUPPORT_SMART_GEAR + uint8_t ucSGCfg; + uint8_t ucSG24GFavorANT; + uint8_t ucSG5GFavorANT; +#endif +#if (CFG_SUPPORT_P2PGO_ACS == 1) + uint8_t ucP2pGoACS; +#endif + uint8_t fgReuseRSNIE; + + uint32_t u4DiscoverTimeout; + uint32_t u4InactiveTimeout; +#if ARP_MONITER_ENABLE + uint32_t uArpMonitorNumber; + uint32_t uArpMonitorRxPktNum; +#endif /* ARP_MONITER_ENABLE */ + + uint8_t fgSapCheckPmkidInDriver; +}; + +/* cnm_timer module */ +struct ROOT_TIMER { + struct LINK rLinkHead; + OS_SYSTIME rNextExpiredSysTime; + KAL_WAKE_LOCK_T *rWakeLock; + u_int8_t fgWakeLocked; +}; + +/* FW/DRV/NVRAM version information */ +struct WIFI_VER_INFO { + + /* NVRAM or Registry */ + uint16_t u2Part1CfgOwnVersion; + uint16_t u2Part1CfgPeerVersion; + uint16_t u2Part2CfgOwnVersion; + uint16_t u2Part2CfgPeerVersion; + + /* Firmware */ + uint8_t aucReleaseManifest[256]; + + /* N9 SW */ + uint16_t u2FwProductID; + uint16_t u2FwOwnVersion; + uint16_t u2FwPeerVersion; + uint8_t ucFwBuildNumber; + uint8_t aucFwBranchInfo[4]; + uint8_t aucFwDateCode[16]; + + struct TAILER_COMMON_FORMAT_T rCommonTailer; + struct TAILER_REGION_FORMAT_T rRegionTailers[MAX_FWDL_SECTION_NUM]; + + /* N9 tailer */ + struct TAILER_FORMAT_T rN9tailer[N9_FWDL_SECTION_NUM]; + + /* CR4 tailer */ + struct TAILER_FORMAT_T rCR4tailer[CR4_FWDL_SECTION_NUM]; +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + /* N9 Compressed tailer */ + struct TAILER_FORMAT_T_2 rN9Compressedtailer; + /* CR4 tailer */ + struct TAILER_FORMAT_T_2 rCR4Compressedtailer; + u_int8_t fgIsN9CompressedFW; + u_int8_t fgIsCR4CompressedFW; +#endif + /* Patch header */ + struct PATCH_FORMAT_T rPatchHeader; + u_int8_t fgPatchIsDlByDrv; +}; + +#if CFG_ENABLE_WIFI_DIRECT +/* + * p2p function pointer structure + */ + +struct P2P_FUNCTION_LINKER { + P2P_REMOVE prP2pRemove; + + P2P_GENERATE_P2P_IE prP2pGenerateWSC_IEForBeacon; + + P2P_NET_REGISTER prP2pNetRegister; + P2P_NET_UNREGISTER prP2pNetUnregister; + /* All IEs generated from supplicant. */ + P2P_CALCULATE_P2P_IE_LEN prP2pCalculateP2p_IELenForAssocReq; + /* All IEs generated from supplicant. */ + P2P_GENERATE_P2P_IE prP2pGenerateP2p_IEForAssocReq; +}; + +#endif + +struct CFG_SCAN_CHNL { + uint8_t ucChannelListNum; + struct RF_CHANNEL_INFO arChnlInfoList[MAXIMUM_OPERATION_CHANNEL_LIST]; +}; + +#if CFG_SUPPORT_NCHO +enum ENUM_NCHO_ITEM_SET_TYPE { + ITEM_SET_TYPE_NUM, + ITEM_SET_TYPE_STR +}; + +enum ENUM_NCHO_BAND { + NCHO_BAND_AUTO = 0, + NCHO_BAND_5G, + NCHO_BAND_2G4, + NCHO_BAND_NUM +}; + +enum ENUM_NCHO_DFS_SCN_MODE { + NCHO_DFS_SCN_DISABLE = 0, + NCHO_DFS_SCN_ENABLE1, + NCHO_DFS_SCN_ENABLE2, + NCHO_DFS_SCN_NUM +}; + +struct CFG_NCHO_RE_ASSOC { + /*!< SSID length in bytes. Zero length is broadcast(any) SSID */ + uint32_t u4SsidLen; + uint8_t aucSsid[ELEM_MAX_LEN_SSID]; + uint8_t aucBssid[MAC_ADDR_LEN]; + uint32_t u4CenterFreq; +}; + +#define CFG_NCHO_SCAN_CHNL CFG_SCAN_CHNL + +struct NCHO_ACTION_FRAME_PARAMS { + uint8_t aucBssid[MAC_ADDR_LEN]; + int32_t i4channel; + int32_t i4DwellTime; + int32_t i4len; + uint8_t aucData[520]; +}; + +struct NCHO_AF_INFO { + uint8_t *aucBssid; + int32_t i4channel; + int32_t i4DwellTime; + int32_t i4len; + uint8_t *pucData; +}; + +struct NCHO_INFO { + u_int8_t fgNCHOEnabled; + u_int8_t fgChGranted; + u_int8_t fgIsSendingAF; + int32_t i4RoamTrigger; /* db */ + int32_t i4RoamDelta; /* db */ + uint32_t u4RoamScanPeriod; /* ms */ + uint32_t u4ScanChannelTime; /* ms */ + uint32_t u4ScanHomeTime; /* ms */ + uint32_t u4ScanHomeawayTime; /* ms */ + uint32_t u4ScanNProbes; + uint32_t u4WesMode; + enum ENUM_NCHO_BAND eBand; + enum ENUM_NCHO_DFS_SCN_MODE eDFSScnMode; + uint32_t u4RoamScanControl; + struct CFG_NCHO_SCAN_CHNL rRoamScnChnl; + struct CFG_NCHO_SCAN_CHNL rAddRoamScnChnl; + struct NCHO_ACTION_FRAME_PARAMS rParamActionFrame; +}; +#endif + +struct WIFI_FEM_CFG { + /* WiFi FEM path */ + uint16_t u2WifiPath; + uint16_t u2Reserved; + /* Reserved */ + uint32_t au4Reserved[4]; +}; +/* + * State Machine: + * -->STOP: No Tx/Rx traffic + * -->DISABLE: Screen is off + * -->RUNNING: Screen is on && Tx/Rx traffic is active + */ +struct PERF_MONITOR { + struct TIMER rPerfMonTimer; + OS_SYSTIME rLastUpdateTime; + unsigned long ulPerfMonFlag; + unsigned long ulLastTxBytes[BSS_DEFAULT_NUM]; + unsigned long ulLastRxBytes[BSS_DEFAULT_NUM]; + unsigned long ulLastTxPackets[BSS_DEFAULT_NUM]; + unsigned long ulLastRxPackets[BSS_DEFAULT_NUM]; + uint64_t ulThroughput; /* in bps */ + unsigned long ulTxTp[BSS_DEFAULT_NUM]; /* in Bps */ + unsigned long ulRxTp[BSS_DEFAULT_NUM]; /* in Bps */ + uint32_t u4UpdatePeriod; /* in ms */ + uint32_t u4TarPerfLevel; + uint32_t u4CurrPerfLevel; + uint32_t u4UsedCnt; + unsigned long ulTotalTxSuccessCount; + unsigned long ulTotalTxFailCount; +}; + +struct HIF_STATS { + unsigned long ulUpdatePeriod; /* in ms */ + uint32_t u4HwIsrCount; + uint32_t u4SwIsrCount; + uint32_t u4CmdInCount; /* cmd from main_thread to hif_thread */ + uint32_t u4CmdTxCount; /* cmd from hif_thread to DMA */ + uint32_t u4CmdTxdoneCount; /* cmd from DMA to consys */ + uint32_t u4DataInCount; /* data from main_thread to hif_thread */ + uint32_t u4DataTxCount; /* data from hif_thread to DMA */ + uint32_t u4DataTxdoneCount; /* data from DMA to consys */ + uint32_t u4DataMsduRptCount; /* data from consys to air */ + uint32_t u4EventRxCount; /* event from DMA to hif_thread */ + uint32_t u4DataRxCount; /* data from DMA to hif_thread */ +}; +#if ARP_BRUST_OPTIMIZE +struct arp_burst_stat { + uint32_t brust; + uint32_t brust_signify; + uint32_t interval; + uint32_t pass_count; + uint32_t pass_signify_count; + uint32_t drop_count; + uint32_t begin; + uint32_t apIp; + uint32_t gatewayIp; +}; +#endif +/* + * Major ADAPTER structure + * Major data structure for driver operation + */ +struct ADAPTER { + struct mt66xx_chip_info *chip_info; + uint8_t ucRevID; + u_int8_t fgIsReadRevID; + + uint16_t u2NicOpChnlNum; + + u_int8_t fgIsEnableWMM; + /* This flag is used to indicate that WMM is enable in current BSS */ + u_int8_t fgIsWmmAssoc; + + uint32_t u4OsPacketFilter; /* packet filter used by OS */ + u_int8_t fgAllMulicastFilter; /* mDNS filter used by OS */ + + struct BSS_INFO *aprBssInfo[MAX_BSSID_NUM + 1]; + struct BSS_INFO *prAisBssInfo[KAL_AIS_NUM]; + uint8_t ucHwBssIdNum; + uint8_t ucWmmSetNum; + uint8_t ucWtblEntryNum; + uint8_t ucTxDefaultWlanIndex; + uint8_t ucP2PDevBssIdx; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + /* Does FW support Checksum Offload feature */ + u_int8_t fgIsSupportCsumOffload; + uint32_t u4CSUMFlags; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + enum ENUM_BAND aePreferBand[NETWORK_TYPE_NUM]; + + /* ADAPTER flags */ + uint32_t u4Flags; + uint32_t u4HwFlags; + + u_int8_t fgIsRadioOff; + + u_int8_t fgIsEnterD3ReqIssued; + + uint8_t aucMacAddress[MAC_ADDR_LEN]; + + /* Current selection basing on the set of Available PHY Types */ + enum ENUM_PHY_TYPE_INDEX eCurrentPhyType; + + uint32_t u4CoalescingBufCachedSize; + uint8_t *pucCoalescingBufCached; + + /* Buffer for CMD_INFO_T, Mgt packet and mailbox message */ + struct BUF_INFO rMgtBufInfo; + struct BUF_INFO rMsgBufInfo; + uint8_t *pucMgtBufCached; + uint32_t u4MgtBufCachedSize; + uint8_t aucMsgBuf[MSG_BUFFER_SIZE]; +#if CFG_DBG_MGT_BUF + uint32_t u4MemAllocDynamicCount; /* Debug only */ + uint32_t u4MemFreeDynamicCount; /* Debug only */ +#endif + + struct STA_RECORD arStaRec[CFG_STA_REC_NUM]; + + /* Element for TX PATH */ + struct TX_CTRL rTxCtrl; + struct QUE rFreeCmdList; + struct CMD_INFO arHifCmdDesc[CFG_TX_MAX_CMD_PKT_NUM]; + + /* Element for RX PATH */ + struct RX_CTRL rRxCtrl; + + /* Timer for restarting RFB setup procedure */ + struct TIMER rPacketDelaySetupTimer; + + uint32_t u4IntStatus; + + enum ENUM_ACPI_STATE rAcpiState; + + u_int8_t fgIsIntEnable; + u_int8_t fgIsIntEnableWithLPOwnSet; + + u_int8_t fgIsFwOwn; + u_int8_t fgWiFiInSleepyState; + + /* Set by callback to make sure WOW done before system suspend */ + u_int8_t fgSetPfCapabilityDone; + u_int8_t fgSetWowDone; + + OS_SYSTIME rLastOwnFailedLogTime; + uint32_t u4OwnFailedCount; + uint32_t u4OwnFailedLogCount; + + uint32_t u4PwrCtrlBlockCnt; + + /* TX Direct related : BEGIN */ + u_int8_t fgTxDirectInited; + + #define TX_DIRECT_CHECK_INTERVAL (1000 * HZ / USEC_PER_SEC) + /* check if an empty MsduInfo is available */ + struct timer_list rTxDirectSkbTimer; + /* check if HIF port is ready to accept a new Msdu */ + struct timer_list rTxDirectHifTimer; + + struct sk_buff_head rTxDirectSkbQueue; + struct QUE rTxDirectHifQueue[TX_PORT_NUM]; + + struct QUE rStaPsQueue[CFG_STA_REC_NUM]; + uint32_t u4StaPsBitmap; + struct QUE rBssAbsentQueue[MAX_BSSID_NUM + 1]; + uint32_t u4BssAbsentBitmap; + /* TX Direct related : END */ + + struct QUE rPendingCmdQueue; + +#if CFG_SUPPORT_MULTITHREAD + struct QUE rTxCmdQueue; + struct QUE rTxCmdDoneQueue; +#if CFG_FIX_2_TX_PORT + struct QUE rTxP0Queue; + struct QUE rTxP1Queue; +#else + struct QUE rTxPQueue[BSS_DEFAULT_NUM][TX_PORT_NUM]; +#endif + struct QUE rRxQueue; + struct QUE rTxDataDoneQueue; +#endif + + struct GLUE_INFO *prGlueInfo; + + uint8_t ucCmdSeqNum; + uint8_t ucTxSeqNum; + uint8_t aucPidPool[WTBL_SIZE]; + +#if 1 /* CFG_SUPPORT_WAPI */ + u_int8_t fgUseWapi; +#endif + + /* RF Test flags */ + u_int8_t fgTestMode; + u_int8_t fgIcapMode; + + /* WLAN Info for DRIVER_CORE OID query */ + struct WLAN_INFO rWlanInfo; + +#if CFG_ENABLE_WIFI_DIRECT + uint8_t u4P2pMode; + u_int8_t fgIsP2PRegistered; + /* flag to report all networks in p2p scan */ + u_int8_t p2p_scan_report_all_bss; + enum ENUM_NET_REG_STATE rP2PNetRegState; + /* BOOLEAN fgIsWlanLaunched; */ + struct P2P_INFO *prP2pInfo; +#if CFG_SUPPORT_P2P_RSSI_QUERY + OS_SYSTIME rP2pLinkQualityUpdateTime; + u_int8_t fgIsP2pLinkQualityValid; + struct LINK_QUALITY rP2pLinkQuality; +#endif +#endif + + /* Online Scan Option */ + u_int8_t fgEnOnlineScan; + + /* Online Scan Option */ + u_int8_t fgDisBcnLostDetection; + + /* MAC address */ + uint8_t rMyMacAddr[PARAM_MAC_ADDR_LEN]; + + /* Wake-up Event for WOL */ + uint32_t u4WakeupEventEnable; + + /* Event Buffering */ + struct EVENT_STATISTICS rStatStruct; + OS_SYSTIME rStatUpdateTime; + u_int8_t fgIsStatValid; + +#if CFG_SUPPORT_MSP + struct EVENT_WLAN_INFO rEventWlanInfo; +#endif + + struct PARAM_LINK_SPEED_EX rLinkQuality; + + /* WIFI_VAR_T */ + struct WIFI_VAR rWifiVar; + + /* MTK WLAN NIC driver IEEE 802.11 MIB */ + struct IEEE_802_11_MIB rMib[KAL_AIS_NUM]; + + /* Mailboxs for inter-module communication */ + struct MBOX arMbox[MBOX_ID_TOTAL_NUM]; + + /* Timers for OID Pending Handling */ + struct TIMER rOidTimeoutTimer; + uint8_t ucOidTimeoutCount; + + /* Root Timer for cnm_timer module */ + struct ROOT_TIMER rRootTimer; + + u_int8_t fgIsChipNoAck; + u_int8_t fgIsChipAssert; + + /* RLM maintenance */ + enum ENUM_CHNL_EXT eRfSco; + enum ENUM_SYS_PROTECT_MODE eSysProtectMode; + enum ENUM_GF_MODE eSysHtGfMode; + enum ENUM_RIFS_MODE eSysTxRifsMode; + enum ENUM_SYS_PCO_PHASE eSysPcoPhase; + + struct DOMAIN_INFO_ENTRY *prDomainInfo; + + /* QM */ + struct QUE_MGT rQM; + + struct CNM_INFO rCnmInfo; + + uint32_t u4PowerMode; + + uint32_t u4CtiaPowerMode; + u_int8_t fgEnCtiaPowerMode; + + uint32_t fgEnArpFilter; + + uint32_t u4UapsdAcBmp; + + uint32_t u4MaxSpLen; + + uint32_t u4PsCurrentMeasureEn; + + /* Version Information */ + struct WIFI_VER_INFO rVerInfo; + + /* 5GHz support (from F/W) */ + u_int8_t fgIsHw5GBandDisabled; + u_int8_t fgEnable5GBand; + u_int8_t fgIsEepromUsed; + u_int8_t fgIsEfuseValid; + u_int8_t fgIsEmbbededMacAddrValid; + +#if CFG_SUPPORT_ANT_SWAP + u_int8_t fgIsSupportAntSwp; +#endif +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + u_int8_t fgIsPowerLimitTableValid; +#endif + + /* Packet Forwarding Tracking */ + int32_t i4PendingFwdFrameCount; + +#if CFG_SUPPORT_RDD_TEST_MODE + uint8_t ucRddStatus; +#endif + + u_int8_t fgDisStaAgingTimeoutDetection; + + uint32_t u4FwCompileFlag0; + uint32_t u4FwCompileFlag1; + uint32_t u4FwFeatureFlag0; + uint32_t u4FwFeatureFlag1; + +#if CFG_SUPPORT_CFG_FILE + struct WLAN_CFG *prWlanCfg; + struct WLAN_CFG rWlanCfg; + + struct WLAN_CFG_REC *prWlanCfgRec; + struct WLAN_CFG_REC rWlanCfgRec; + + struct WLAN_CFG *prWlanCfgEm; + struct WLAN_CFG rWlanCfgEm; +#endif + +#if CFG_M0VE_BA_TO_DRIVER + struct TIMER rMqmIdleRxBaDetectionTimer; + uint32_t u4FlagBitmap; +#endif +#if CFG_ASSERT_DUMP + struct TIMER rN9CorDumpTimer; + struct TIMER rCr4CorDumpTimer; + u_int8_t fgN9CorDumpFileOpend; + u_int8_t fgCr4CorDumpFileOpend; + u_int8_t fgN9AssertDumpOngoing; + u_int8_t fgCr4AssertDumpOngoing; + u_int8_t fgKeepPrintCoreDump; +#endif + /* Tx resource information */ + u_int8_t fgIsNicTxReousrceValid; + struct tx_resource_info nicTxReousrce; + + /* Efuse Start and End address */ + uint32_t u4EfuseStartAddress; + uint32_t u4EfuseEndAddress; + + /* COEX feature */ + uint32_t u4FddMode; + + /* host status EMI offset*/ + uint32_t u4HostStatusEmiOffset; + +#if CFG_WOW_SUPPORT + struct WOW_CTRL rWowCtrl; +#endif + +#if CFG_SUPPORT_NCHO /* NCHO information */ + struct NCHO_INFO rNchoInfo; +#endif + struct CFG_SCAN_CHNL rAddRoamScnChnl; + +/*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ + uint8_t aucEepromVaule[16]; /* HQA CMD for Efuse Block size contents */ + uint32_t u4FreeBlockNum; + uint32_t u4GetTxPower; +/*#endif*/ + u_int8_t fgIsCr4FwDownloaded; + u_int8_t fgIsFwDownloaded; + u_int8_t fgIsSupportBufferBinSize16Byte; + u_int8_t fgIsSupportDelayCal; + u_int8_t fgIsSupportGetFreeEfuseBlockCount; + u_int8_t fgIsSupportQAAccessEfuse; + u_int8_t fgIsSupportPowerOnSendBufferModeCMD; + u_int8_t fgIsSupportGetTxPower; + u_int8_t fgIsEnableLpdvt; + + /* SER related info */ + uint8_t ucSerState; + +#if (CFG_HW_WMM_BY_BSS == 1) + uint8_t ucHwWmmEnBit; +#endif + unsigned long ulSuspendFlag; + struct WIFI_FEM_CFG rWifiFemCfg; + + /* Smar Gear */ + uint8_t ucSmarGearSupportSisoOnly; + uint8_t ucSmartGearWfPathSupport; + + struct PERF_MONITOR rPerMonitor; + struct ICAP_INFO_T rIcapInfo; + struct RECAL_INFO_T rReCalInfo; + + /* Support change QM RX BA entry miss timeout (unit: ms) dynamically */ + uint32_t u4QmRxBaMissTimeout; + +#if CFG_SUPPORT_LOWLATENCY_MODE + u_int8_t fgEnLowLatencyMode; + u_int8_t fgEnCfg80211Scan; + u_int8_t fgEnTxDupDetect; + u_int8_t fgTxDupCertificate; + OS_SYSTIME tmTxDataInterval; +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + +#if (CFG_SUPPORT_802_11AX == 1) + struct __HE_CFG_INFO_T rHeCfg; + uint8_t ucMcsMapSetFromSigma; + u_int8_t fgMcsMapBeenSet; + u_int8_t fgMuEdcaOverride; + uint32_t u4MBACount; + uint32_t u4HeHtcOM; + uint8_t fgEnShowHETrigger; + uint8_t fgTxPPDU; +#endif /* CFG_SUPPORT_802_11AX == 1 */ +#if (CFG_SUPPORT_TWT == 1) + struct _TWT_PLANNER_T rTWTPlanner; +#endif + +#if CFG_SUPPORT_WIFI_SYSDVT + struct AUTOMATION_DVT *auto_dvt; + uint16_t u2TxTest; + uint16_t u2TxTestCount; + uint8_t ucTxTestUP; +#endif /* CFG_SUPPORT_WIFI_SYSDVT */ + + bool fgEnHifDbgInfo; + uint32_t u4HifDbgFlag; + uint32_t u4HifChkFlag; + uint32_t u4TxHangFlag; + uint32_t u4NoMoreRfb; + + /* Only for PCIE DmaSchdl usage so far. */ + struct { + bool fgRun; + uint32_t u4Quota; + } rWmmQuotaReqCS[BSS_DEFAULT_NUM]; + + /* TX HIF Control falgs */ + uint32_t au4TxHifResCtl[TX_PORT_NUM]; + uint32_t u4TxHifResCtlIdx; + uint32_t u4TxHifResCtlNum; + +#if CFG_SUPPORT_OSHARE + bool fgEnOshareMode; +#endif + +#if CFG_MTK_MCIF_WIFI_SUPPORT + bool fgMddpActivated; +#endif + + struct WLAN_DEBUG_INFO rDebugInfo; +#if CFG_SUPPORT_IOT_AP_BLACKLIST + struct WLAN_IOT_AP_RULE_T rIotApRule[CFG_IOT_AP_RULE_MAX_CNT]; +#endif + +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR + uint32_t u4LastLinkQuality; + uint32_t u4LinkQualityCounter; + struct WIFI_LINK_QUALITY_INFO rLinkQualityInfo; + struct PARAM_GET_STA_STATISTICS rQueryStaStatistics; + struct PARAM_802_11_STATISTICS_STRUCT rStat; + uint32_t u4BufLen; +#endif /* CFG_SUPPORT_LINK_QUALITY_MONITOR */ + +#if CFG_SUPPORT_DYNAMIC_PWR_LIMIT + /* dynamic tx power control */ + struct LINK rTxPwr_DefaultList; + struct LINK rTxPwr_DynamicList; +#endif + +#if CFG_DBG_MGT_BUF + struct LINK rMemTrackLink; +#endif + +#if CFG_SUPPORT_DATA_STALL + OS_SYSTIME tmReportinterval; +#endif + +#if CFG_SUPPORT_BIGDATA_PIP + OS_SYSTIME tmDataPipReportinterval; +#endif + + int8_t cArpNoResponseIdx; + + u_int8_t fgEnDbgPowerMode; + + struct HIF_STATS rHifStats; +#if ARP_BRUST_OPTIMIZE + struct arp_burst_stat arp_b_stat; +#endif +}; /* end of _ADAPTER_T */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +#define SUSPEND_FLAG_FOR_WAKEUP_REASON (0) +#define SUSPEND_FLAG_CLEAR_WHEN_RESUME (1) + +/* Macros for argument _BssIndex */ +#define IS_NET_ACTIVE(_prAdapter, _BssIndex) \ + ((_prAdapter)->aprBssInfo[(_BssIndex)]->fgIsNetActive) + +/* Macros for argument _prBssInfo */ +#define IS_BSS_ACTIVE(_prBssInfo) ((_prBssInfo)->fgIsNetActive) + +#define IS_BSS_AIS(_prBssInfo) \ + ((_prBssInfo)->eNetworkType == NETWORK_TYPE_AIS) + +#define IS_BSS_INDEX_AIS(_prAdapter, _BssIndex) \ + (_BssIndex < KAL_AIS_NUM) + +#define IS_BSS_P2P(_prBssInfo) \ + ((_prBssInfo)->eNetworkType == NETWORK_TYPE_P2P) + +#define IS_BSS_BOW(_prBssInfo) \ + ((_prBssInfo)->eNetworkType == NETWORK_TYPE_BOW) + +#define IS_BSS_APGO(_prBssInfo) \ + (IS_BSS_P2P(_prBssInfo) && \ + (_prBssInfo)->eCurrentOPMode == OP_MODE_ACCESS_POINT) + +#define SET_NET_ACTIVE(_prAdapter, _BssIndex) \ + {(_prAdapter)->aprBssInfo[(_BssIndex)]->fgIsNetActive = TRUE; } + +#define UNSET_NET_ACTIVE(_prAdapter, _BssIndex) \ + {(_prAdapter)->aprBssInfo[(_BssIndex)]->fgIsNetActive = FALSE; } + +#define BSS_INFO_INIT(_prAdapter, _prBssInfo) \ +{ uint8_t _aucZeroMacAddr[] = NULL_MAC_ADDR; \ + \ + (_prBssInfo)->eConnectionState = MEDIA_STATE_DISCONNECTED; \ + (_prBssInfo)->eConnectionStateIndicated = \ + MEDIA_STATE_DISCONNECTED; \ + (_prBssInfo)->eCurrentOPMode = OP_MODE_INFRASTRUCTURE; \ + (_prBssInfo)->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_RESERVED; \ + COPY_MAC_ADDR((_prBssInfo)->aucBSSID, _aucZeroMacAddr); \ + LINK_INITIALIZE(&((_prBssInfo)->rStaRecOfClientList)); \ + (_prBssInfo)->fgIsBeaconActivated = FALSE; \ + (_prBssInfo)->u2HwDefaultFixedRateCode = RATE_CCK_1M_LONG; \ +} + +/*----------------------------------------------------------------------------*/ +/* Macros for Power State */ +/*----------------------------------------------------------------------------*/ +#define SET_NET_PWR_STATE_IDLE(_prAdapter, _BssIndex) \ + {_prAdapter->rWifiVar.aePwrState[(_BssIndex)] = PWR_STATE_IDLE; } + +#define SET_NET_PWR_STATE_ACTIVE(_prAdapter, _BssIndex) \ + {_prAdapter->rWifiVar.aePwrState[(_BssIndex)] = PWR_STATE_ACTIVE; } + +#define SET_NET_PWR_STATE_PS(_prAdapter, _BssIndex) \ + {_prAdapter->rWifiVar.aePwrState[(_BssIndex)] = PWR_STATE_PS; } + +#define IS_NET_PWR_STATE_ACTIVE(_prAdapter, _BssIndex) \ + (_prAdapter->rWifiVar.aePwrState[(_BssIndex)] == PWR_STATE_ACTIVE) + +#define IS_NET_PWR_STATE_IDLE(_prAdapter, _BssIndex) \ + (_prAdapter->rWifiVar.aePwrState[(_BssIndex)] == 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) + +#define IS_WIFI_2G4_WF0_SUPPORT(_prAdapter) \ + ((_prAdapter)->rWifiFemCfg.u2WifiPath & WLAN_FLAG_2G4_WF0) + +#define IS_WIFI_5G_WF0_SUPPORT(_prAdapter) \ + ((_prAdapter)->rWifiFemCfg.u2WifiPath & WLAN_FLAG_5G_WF0) + +#define IS_WIFI_2G4_WF1_SUPPORT(_prAdapter) \ + ((_prAdapter)->rWifiFemCfg.u2WifiPath & WLAN_FLAG_2G4_WF1) + +#define IS_WIFI_5G_WF1_SUPPORT(_prAdapter) \ + ((_prAdapter)->rWifiFemCfg.u2WifiPath & WLAN_FLAG_5G_WF1) + +#define IS_WIFI_2G4_SISO(_prAdapter) \ + ((IS_WIFI_2G4_WF0_SUPPORT(_prAdapter) && \ + !(IS_WIFI_2G4_WF1_SUPPORT(_prAdapter))) || \ + (IS_WIFI_2G4_WF1_SUPPORT(_prAdapter) && \ + !(IS_WIFI_2G4_WF0_SUPPORT(_prAdapter)))) + +#define IS_WIFI_5G_SISO(_prAdapter) \ + ((IS_WIFI_5G_WF0_SUPPORT(_prAdapter) && \ + !(IS_WIFI_5G_WF1_SUPPORT(_prAdapter))) || \ + (IS_WIFI_5G_WF1_SUPPORT(_prAdapter) && \ + !(IS_WIFI_5G_WF0_SUPPORT(_prAdapter)))) + +#define IS_WIFI_SMART_GEAR_SUPPORT_WF0_SISO(_prAdapter) \ + ((_prAdapter)->ucSmarGearSupportSisoOnly && \ + ((_prAdapter)->ucSmartGearWfPathSupport == BIT(ANTENNA_WF0))) + +#define IS_WIFI_SMART_GEAR_SUPPORT_WF1_SISO(_prAdapter) \ + ((_prAdapter)->ucSmarGearSupportSisoOnly && \ + ((_prAdapter)->ucSmartGearWfPathSupport == BIT(ANTENNA_WF1))) + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _ADAPTER_H */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/bow.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/bow.h new file mode 100644 index 0000000000000..c7e7cbe85b8e1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/bow.h @@ -0,0 +1,266 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/bow.h#1 +*/ + + +#ifndef _BOW_H_ +#define _BOW_H_ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define BOWDEVNAME "bow0" + +#define MAX_BOW_NUMBER_OF_CHANNEL_2G4 14 +#define MAX_BOW_NUMBER_OF_CHANNEL_5G 4 +/* (MAX_BOW_NUMBER_OF_CHANNEL_2G4 + MAX_BOW_NUMBER_OF_CHANNEL_5G) */ +#define MAX_BOW_NUMBER_OF_CHANNEL 18 + +#define MAX_ACTIVITY_REPORT 2 +#define MAX_ACTIVITY_REPROT_TIME 660 + +#define ACTIVITY_REPORT_STATUS_SUCCESS 0 +#define ACTIVITY_REPORT_STATUS_FAILURE 1 +#define ACTIVITY_REPORT_STATUS_TIME_INVALID 2 +#define ACTIVITY_REPORT_STATUS_OTHERS 3 + +#define ACTIVITY_REPORT_SCHEDULE_UNKNOWN 0 /* Does not know the schedule of the interference */ +#define ACTIVITY_REPORT_SCHEDULE_KNOWN 1 + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +struct BT_OVER_WIFI_COMMAND_HEADER { + uint8_t ucCommandId; + uint8_t ucSeqNumber; + uint16_t u2PayloadLength; +}; + +struct BT_OVER_WIFI_COMMAND { + struct BT_OVER_WIFI_COMMAND_HEADER rHeader; + uint8_t aucPayload[0]; +}; + +struct BT_OVER_WIFI_EVENT_HEADER { + uint8_t ucEventId; + uint8_t ucSeqNumber; + uint16_t u2PayloadLength; +}; + +struct BT_OVER_WIFI_EVENT { + struct BT_OVER_WIFI_EVENT_HEADER rHeader; + uint8_t aucPayload[0]; +}; + +struct CHANNEL_DESC { + uint8_t ucChannelBand; + uint8_t ucChannelNum; +}; + +/* Command Structures */ +struct BOW_SETUP_CONNECTION { +/* Fixed to 2.4G */ + uint8_t ucChannelNum; + uint8_t ucReserved1; + uint8_t aucPeerAddress[6]; + uint16_t u2BeaconInterval; + uint8_t ucTimeoutDiscovery; + uint8_t ucTimeoutInactivity; + uint8_t ucRole; + uint8_t ucPAL_Capabilities; + int8_t cMaxTxPower; + uint8_t 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]; + */ +}; + +struct BOW_DESTROY_CONNECTION { + uint8_t aucPeerAddress[6]; + uint8_t aucReserved[2]; +}; + +struct BOW_SET_PTK { + uint8_t aucPeerAddress[6]; + uint8_t aucReserved[2]; + uint8_t aucTemporalKey[16]; +}; + +struct BOW_READ_RSSI { + uint8_t aucPeerAddress[6]; + uint8_t aucReserved[2]; +}; + +struct BOW_READ_LINK_QUALITY { + uint8_t aucPeerAddress[6]; + uint8_t aucReserved[2]; +}; + +struct BOW_SHORT_RANGE_MODE { + uint8_t aucPeerAddress[6]; + int8_t cTxPower; + uint8_t ucReserved; +}; + +/* Event Structures */ +struct BOW_COMMAND_STATUS { + uint8_t ucStatus; + uint8_t ucReserved[3]; +}; + +struct BOW_MAC_STATUS { + uint8_t aucMacAddr[6]; + uint8_t ucAvailability; + uint8_t ucNumOfChannel; + struct CHANNEL_DESC arChannelList[MAX_BOW_NUMBER_OF_CHANNEL]; +}; + +struct BOW_LINK_CONNECTED { + struct CHANNEL_DESC rChannel; + uint8_t aucReserved; + uint8_t aucPeerAddress[6]; +}; + +struct BOW_LINK_DISCONNECTED { + uint8_t ucReason; + uint8_t aucReserved; + uint8_t aucPeerAddress[6]; +}; + +struct BOW_RSSI { + int8_t cRssi; + uint8_t aucReserved[3]; +}; + +struct BOW_LINK_QUALITY { + uint8_t ucLinkQuality; + uint8_t aucReserved[3]; +}; + +enum ENUM_BOW_CMD_ID { + 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 ENUM_BOW_EVENT_ID { + 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 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 +}; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#endif /*_BOW_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/cmd_buf.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/cmd_buf.h new file mode 100644 index 0000000000000..fc879d56f4a5c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/cmd_buf.h @@ -0,0 +1,227 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + + +#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 + ******************************************************************************* + */ + +enum COMMAND_TYPE { + COMMAND_TYPE_GENERAL_IOCTL, + COMMAND_TYPE_NETWORK_IOCTL, + COMMAND_TYPE_SECURITY_FRAME, + COMMAND_TYPE_MANAGEMENT_FRAME, + COMMAND_TYPE_DATA_FRAME, + COMMAND_TYPE_NUM +}; + +typedef void(*PFN_CMD_DONE_HANDLER) (IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +typedef void(*PFN_CMD_TIMEOUT_HANDLER) (IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo); + +typedef void(*PFN_HIF_TX_CMD_DONE_CB) (IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo); + +struct CMD_INFO { + struct QUE_ENTRY rQueEntry; + + enum COMMAND_TYPE eCmdType; + + uint16_t u2InfoBufLen; /* This is actual CMD buffer length */ + uint8_t *pucInfoBuffer; /* May pointer to structure in prAdapter */ + struct MSDU_INFO + *prMsduInfo; /* only valid when it's a security/MGMT frame */ + void *prPacket; /* only valid when it's a security frame */ + + PFN_CMD_DONE_HANDLER pfCmdDoneHandler; + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler; + PFN_HIF_TX_CMD_DONE_CB pfHifTxCmdDoneCb; + + u_int8_t fgIsOid; /* Used to check if we need indicate */ + + uint8_t ucCID; + u_int8_t fgSetQuery; + u_int8_t fgNeedResp; + uint8_t ucCmdSeqNum; + uint32_t u4SetInfoLen; /* Indicate how many byte we read for Set OID */ + + /* information indicating by OID/ioctl */ + void *pvInformationBuffer; + uint32_t u4InformationBufferLength; + + /* private data */ + uint32_t u4PrivateData; + + /* TXD/TXP pointer/len for hif tx copy */ + uint32_t u4TxdLen; + uint32_t u4TxpLen; + uint8_t *pucTxd; + uint8_t *pucTxp; +}; + +/******************************************************************************* + * P U B 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_DBG_MGT_BUF +#define cmdBufAllocateCmdInfo(_prAdapter, u4Length) \ + cmdBufAllocateCmdInfoX(_prAdapter, u4Length, \ + __FILE__ ":" STRLINE(__LINE__)) +#endif + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +void cmdBufInitialize(IN struct ADAPTER *prAdapter); + +#if CFG_DBG_MGT_BUF +struct CMD_INFO *cmdBufAllocateCmdInfoX(IN struct ADAPTER + *prAdapter, IN uint32_t u4Length, + uint8_t *fileAndLine); +#else +struct CMD_INFO *cmdBufAllocateCmdInfo(IN struct ADAPTER + *prAdapter, IN uint32_t u4Length); +#endif + +void cmdBufFreeCmdInfo(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo); + +/*----------------------------------------------------------------------------*/ +/* Routines for CMDs */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanSendSetQueryCmd(IN struct ADAPTER *prAdapter, + uint8_t ucCID, + u_int8_t fgSetQuery, + u_int8_t fgNeedResp, + u_int8_t fgIsOid, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + uint32_t u4SetQueryInfoLen, + uint8_t *pucInfoBuffer, OUT void *pvSetQueryBuffer, + IN uint32_t u4SetQueryBufferLen); + +#if CFG_SUPPORT_TX_BF +uint32_t +wlanSendSetQueryExtCmd(IN struct ADAPTER *prAdapter, + uint8_t ucCID, + uint8_t ucExtCID, + u_int8_t fgSetQuery, + u_int8_t fgNeedResp, + u_int8_t fgIsOid, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + uint32_t u4SetQueryInfoLen, + uint8_t *pucInfoBuffer, OUT void *pvSetQueryBuffer, + IN uint32_t u4SetQueryBufferLen); +#endif + +void cmdBufDumpCmdQueue(struct QUE *prQueue, + int8_t *queName); +#if (CFG_SUPPORT_TRACE_TC4 == 1) +void wlanDebugTC4Init(void); +void wlanDebugTC4Uninit(void); +void wlanTraceReleaseTcRes(struct ADAPTER *prAdapter, + uint32_t u4TxRlsCnt, uint32_t u4Available); +void wlanTraceTxCmd(struct CMD_INFO *prCmd); +void wlanDumpTcResAndTxedCmd(uint8_t *pucBuf, + uint32_t maxLen); +#endif + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#endif /* _CMD_BUF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/connac_dmashdl.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/connac_dmashdl.h new file mode 100644 index 0000000000000..51750e81530be --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/connac_dmashdl.h @@ -0,0 +1,458 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "connac_dmashdl.h" + * \brief The common register definition of MT6630 + * + * N/A + */ + + + +#ifndef _CONNAC_DMASHDL_H +#define _CONNAC_DMASHDL_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 + ******************************************************************************* + */ + +#if defined(_HIF_PCIE) || defined(_HIF_AXI) +#define PCIE_HIF_DMASHDL_BASE 0x6000 +#endif /* _HIF_PCIE */ + +#if defined(_HIF_USB) +#define USB_HIF_DMASHDL_BASE 0x5000A000 +#endif /* _HIF_USB */ + +#define CONN_HIF_DMASHDL_SW_CONTROL(_base) (_base + 0x04) +#define CONN_HIF_DMASHDL_OPTIONAL_CONTROL(_base) (_base + 0x08) + +#define CONN_HIF_DMASHDL_PAGE_SETTING(_base) (_base + 0x0C) +/* User program group sequence type control */ +/* 0: user program group sequence order type, + * 1: pre define each slot group strict order + */ +#define CONN_HIF_DMASHDL_GROUP_SEQ_ORDER_TYPE BIT(16) + +#define CONN_HIF_DMASHDL_REFILL_CONTROL(_base) (_base + 0x10) +#define CONN_HIF_DMASHDL_TX_PACKET_SIZE_PAGE_MAP(_base) (_base + 0x14) + +#define CONN_HIF_DMASHDL_CONTROL_SIGNAL(_base) (_base + 0x18) +/* enable to clear the flag of PLE TXD size greater than ple max. size */ +#define CONN_HIF_DMASHDL_PLE_TXD_GT_MAX_SIZE_FLAG_CLR \ + BIT(0) +#define CONN_HIF_DMASHDL_HIF_ASK_SUB_ENA \ + BIT(16) /* enable packet in substration action from HIF ask period */ +#define CONN_HIF_DMASHDL_PLE_SUB_ENA \ + BIT(17) /* enable packet in substration action from PLE */ +/* enable terminate refill period when PLE release packet to do addition */ +#define CONN_HIF_DMASHDL_PLE_ADD_INT_REFILL_ENA \ + BIT(29) +/* enable terminate refill period when packet in to do addition */ +#define CONN_HIF_DMASHDL_PDMA_ADD_INT_REFILL_ENA \ + BIT(30) +/* enable terminate refill period when packet in to do substration */ +#define CONN_HIF_DMASHDL_PKTIN_INT_REFILL_ENA \ + BIT(31) + +#define CONN_HIF_DMASHDL_PACKET_MAX_SIZE(_base) (_base + 0x1C) +#define CONN_HIF_DMASHDL_GROUP0_CONTROL(_base) (_base + 0x20) +#define CONN_HIF_DMASHDL_REFILL_CTRL(_base) (_base + 0x10) +#define CONN_HIF_DMASHDL_GROUP0_CTRL(_base) (_base + 0x20) +#define CONN_HIF_DMASHDL_GROUP1_CTRL(_base) (_base + 0x24) +#define CONN_HIF_DMASHDL_GROUP2_CTRL(_base) (_base + 0x28) +#define CONN_HIF_DMASHDL_GROUP3_CTRL(_base) (_base + 0x2c) +#define CONN_HIF_DMASHDL_GROUP4_CTRL(_base) (_base + 0x30) +#define CONN_HIF_DMASHDL_GROUP5_CTRL(_base) (_base + 0x34) +#define CONN_HIF_DMASHDL_GROUP6_CTRL(_base) (_base + 0x38) +#define CONN_HIF_DMASHDL_GROUP7_CTRL(_base) (_base + 0x3c) +#define CONN_HIF_DMASHDL_GROUP8_CTRL(_base) (_base + 0x40) +#define CONN_HIF_DMASHDL_GROUP9_CTRL(_base) (_base + 0x44) +#define CONN_HIF_DMASHDL_GROUP10_CTRL(_base) (_base + 0x48) +#define CONN_HIF_DMASHDL_GROUP11_CTRL(_base) (_base + 0x4c) +#define CONN_HIF_DMASHDL_GROUP12_CTRL(_base) (_base + 0x50) +#define CONN_HIF_DMASHDL_GROUP13_CTRL(_base) (_base + 0x54) +#define CONN_HIF_DMASHDL_GROUP14_CTRL(_base) (_base + 0x58) +#define CONN_HIF_DMASHDL_GROUP15_CTRL(_base) (_base + 0x5c) +#define CONN_HIF_DMASHDL_SHDL_SET0(_base) (_base + 0xb0) +#define CONN_HIF_DMASHDL_SHDL_SET1(_base) (_base + 0xb4) +#define CONN_HIF_DMASHDL_SLOT_SET0(_base) (_base + 0xc4) +#define CONN_HIF_DMASHDL_SLOT_SET1(_base) (_base + 0xc8) +#define CONN_HIF_DMASHDL_Q_MAP0(_base) (_base + 0xd0) +#define CONN_HIF_DMASHDL_Q_MAP1(_base) (_base + 0xd4) +#define CONN_HIF_DMASHDL_Q_MAP2(_base) (_base + 0xd8) +#define CONN_HIF_DMASHDL_Q_MAP3(_base) (_base + 0xdc) + +#define CONN_HIF_DMASHDL_ERROR_FLAG_CTRL(_base) (_base + 0x9c) + +#define CONN_HIF_DMASHDL_STATUS_RD(_base) (_base + 0x100) +#define CONN_HIF_DMASHDL_STATUS_RD_GP0(_base) (_base + 0x140) +#define CONN_HIF_DMASHDL_STATUS_RD_GP1(_base) (_base + 0x144) +#define CONN_HIF_DMASHDL_STATUS_RD_GP2(_base) (_base + 0x148) +#define CONN_HIF_DMASHDL_STATUS_RD_GP3(_base) (_base + 0x14c) +#define CONN_HIF_DMASHDL_STATUS_RD_GP4(_base) (_base + 0x150) +#define CONN_HIF_DMASHDL_STATUS_RD_GP5(_base) (_base + 0x154) +#define CONN_HIF_DMASHDL_STATUS_RD_GP6(_base) (_base + 0x158) +#define CONN_HIF_DMASHDL_STATUS_RD_GP7(_base) (_base + 0x15c) +#define CONN_HIF_DMASHDL_STATUS_RD_GP8(_base) (_base + 0x160) +#define CONN_HIF_DMASHDL_STATUS_RD_GP9(_base) (_base + 0x164) +#define CONN_HIF_DMASHDL_STATUS_RD_GP10(_base) (_base + 0x168) +#define CONN_HIF_DMASHDL_STATUS_RD_GP11(_base) (_base + 0x16c) +#define CONN_HIF_DMASHDL_STATUS_RD_GP12(_base) (_base + 0x170) +#define CONN_HIF_DMASHDL_STATUS_RD_GP13(_base) (_base + 0x174) +#define CONN_HIF_DMASHDL_STATUS_RD_GP14(_base) (_base + 0x178) +#define CONN_HIF_DMASHDL_STATUS_RD_GP15(_base) (_base + 0x17c) +#define CONN_HIF_DMASHDLRD_GP_PKT_CNT_0(_base) (_base + 0x180) +#define CONN_HIF_DMASHDLRD_GP_PKT_CNT_1(_base) (_base + 0x184) +#define CONN_HIF_DMASHDLRD_GP_PKT_CNT_2(_base) (_base + 0x188) +#define CONN_HIF_DMASHDLRD_GP_PKT_CNT_3(_base) (_base + 0x18c) +#define CONN_HIF_DMASHDLRD_GP_PKT_CNT_4(_base) (_base + 0x190) +#define CONN_HIF_DMASHDLRD_GP_PKT_CNT_5(_base) (_base + 0x194) +#define CONN_HIF_DMASHDLRD_GP_PKT_CNT_6(_base) (_base + 0x198) +#define CONN_HIF_DMASHDLRD_GP_PKT_CNT_7(_base) (_base + 0x19c) + +/* ============================================================================ + * + * ---REFILL_CONTROL (0x5000A000 + 0x10)--- + * + * GROUP0_REFILL_DISABLE[16] - (RW) Group0 refill control + * GROUP1_REFILL_DISABLE[17] - (RW) Group1 refill control + * GROUP2_REFILL_DISABLE[18] - (RW) Group2 refill control + * GROUP3_REFILL_DISABLE[19] - (RW) Group3 refill control + * GROUP4_REFILL_DISABLE[20] - (RW) Group4 refill control + * GROUP5_REFILL_DISABLE[21] - (RW) Group5 refill control + * GROUP6_REFILL_DISABLE[22] - (RW) Group6 refill control + * GROUP7_REFILL_DISABLE[23] - (RW) Group7 refill control + * GROUP8_REFILL_DISABLE[24] - (RW) Group8 refill control + * GROUP9_REFILL_DISABLE[25] - (RW) Group9 refill control + * GROUP10_REFILL_DISABLE[26] - (RW) Group10 refill control + * GROUP11_REFILL_DISABLE[27] - (RW) Group11 refill control + * GROUP12_REFILL_DISABLE[28] - (RW) Group12 refill control + * GROUP13_REFILL_DISABLE[29] - (RW) Group13 refill control + * GROUP14_REFILL_DISABLE[30] - (RW) Group14 refill control + * GROUP15_REFILL_DISABLE[31] - (RW) Group15 refill control + * + * ============================================================================ + */ +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP15_REFILL_DISABLE_MASK \ + 0x80000000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP14_REFILL_DISABLE_MASK \ + 0x40000000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP13_REFILL_DISABLE_MASK \ + 0x20000000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP12_REFILL_DISABLE_MASK \ + 0x10000000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP11_REFILL_DISABLE_MASK \ + 0x08000000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP10_REFILL_DISABLE_MASK \ + 0x04000000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP9_REFILL_DISABLE_MASK \ + 0x02000000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP8_REFILL_DISABLE_MASK \ + 0x01000000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP7_REFILL_DISABLE_MASK \ + 0x00800000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP6_REFILL_DISABLE_MASK \ + 0x00400000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP5_REFILL_DISABLE_MASK \ + 0x00200000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP4_REFILL_DISABLE_MASK \ + 0x00100000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP3_REFILL_DISABLE_MASK \ + 0x00080000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP2_REFILL_DISABLE_MASK \ + 0x00040000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP1_REFILL_DISABLE_MASK \ + 0x00020000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP0_REFILL_DISABLE_MASK \ + 0x00010000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP15_REFILL_PRIORITY_MASK \ + 0x00008000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP14_REFILL_PRIORITY_MASK \ + 0x00004000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP13_REFILL_PRIORITY_MASK \ + 0x00002000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP12_REFILL_PRIORITY_MASK \ + 0x00001000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP11_REFILL_PRIORITY_MASK \ + 0x00000800 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP10_REFILL_PRIORITY_MASK \ + 0x00000400 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP9_REFILL_PRIORITY_MASK \ + 0x00000200 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP8_REFILL_PRIORITY_MASK \ + 0x00000100 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP7_REFILL_PRIORITY_MASK \ + 0x00000080 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP6_REFILL_PRIORITY_MASK \ + 0x00000040 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP5_REFILL_PRIORITY_MASK \ + 0x00000020 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP4_REFILL_PRIORITY_MASK \ + 0x00000010 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP3_REFILL_PRIORITY_MASK \ + 0x00000008 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP2_REFILL_PRIORITY_MASK \ + 0x00000004 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP1_REFILL_PRIORITY_MASK \ + 0x00000002 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP0_REFILL_PRIORITY_MASK \ + 0x00000001 + +/* ============================================================================ + * + * ---QUEUE_MAPPING0 (0x5000A000 + 0xd0)--- + * + * QUEUE0_MAPPING[3..0] - (RW) queue 0 use which group ID + * QUEUE1_MAPPING[7..4] - (RW) queue 1 use which group ID + * QUEUE2_MAPPING[11..8] - (RW) queue 2 use which group ID + * QUEUE3_MAPPING[15..12] - (RW) queue 3 use which group ID + * QUEUE4_MAPPING[19..16] - (RW) queue 4 use which group ID + * QUEUE5_MAPPING[23..20] - (RW) queue 5 use which group ID + * QUEUE6_MAPPING[27..24] - (RW) queue 6 use which group ID + * QUEUE7_MAPPING[31..28] - (RW) queue 7 use which group ID + * + * ============================================================================ + */ +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE7_MAPPING 28 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE6_MAPPING 24 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE5_MAPPING 20 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE4_MAPPING 16 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE3_MAPPING 12 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE2_MAPPING 8 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE1_MAPPING 4 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE0_MAPPING 0 + +/* ============================================================================ + * + * ---QUEUE_MAPPING1 (0x5000A000 + 0xd4)--- + * + * QUEUE8_MAPPING[3..0] - (RW) queue 8 use which group ID + * QUEUE9_MAPPING[7..4] - (RW) queue 9 use which group ID + * QUEUE10_MAPPING[11..8] - (RW) queue 10 use which group ID + * QUEUE11_MAPPING[15..12] - (RW) queue 11 use which group ID + * QUEUE12_MAPPING[19..16] - (RW) queue 12 use which group ID + * QUEUE13_MAPPING[23..20] - (RW) queue 13 use which group ID + * QUEUE14_MAPPING[27..24] - (RW) queue 14 use which group ID + * QUEUE15_MAPPING[31..28] - (RW) queue 15 use which group ID + * + * ============================================================================ + */ +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE15_MAPPING 28 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE14_MAPPING 24 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE13_MAPPING 20 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE12_MAPPING 16 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE11_MAPPING 12 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE10_MAPPING 8 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE9_MAPPING 4 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE8_MAPPING 0 + +/* ============================================================================ + * + * ---QUEUE_MAPPING2 (0x5000A000 + 0xd8)--- + * + * QUEUE16_MAPPING[3..0] - (RW) queue 16 use which group ID + * QUEUE17_MAPPING[7..4] - (RW) queue 17 use which group ID + * QUEUE18_MAPPING[11..8] - (RW) queue 18 use which group ID + * QUEUE19_MAPPING[15..12] - (RW) queue 19 use which group ID + * QUEUE20_MAPPING[19..16] - (RW) queue 20 use which group ID + * QUEUE21_MAPPING[23..20] - (RW) queue 21 use which group ID + * QUEUE22_MAPPING[27..24] - (RW) queue 22 use which group ID + * QUEUE23_MAPPING[31..28] - (RW) queue 23 use which group ID + * + * ============================================================================= + */ +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE23_MAPPING 28 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE22_MAPPING 24 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE21_MAPPING 20 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE20_MAPPING 16 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE19_MAPPING 12 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE18_MAPPING 8 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE17_MAPPING 4 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE16_MAPPING 0 + +#define DMASHDL_RSV_CNT_MASK (0xfff << 16) +#define DMASHDL_SRC_CNT_MASK (0xfff << 0) +#define DMASHDL_RSV_CNT_OFFSET 16 +#define DMASHDL_SRC_CNT_OFFSET 0 +#define DMASHDL_FREE_PG_CNT_MASK (0xfff << 16) +#define DMASHDL_FFA_CNT_MASK (0xfff << 0) +#define DMASHDL_FREE_PG_CNT_OFFSET 16 +#define DMASHDL_FFA_CNT_OFFSET 0 +#define DMASHDL_MAX_QUOTA_MASK (0xfff << 16) +#define DMASHDL_MIN_QUOTA_MASK (0xfff << 0) +#define DMASHDL_MAX_QUOTA_OFFSET 16 +#define DMASHDL_MIN_QUOTA_OFFSET 0 + +#define DMASHDL_MIN_QUOTA_NUM(p) (((p) & 0xfff) << DMASHDL_MIN_QUOTA_OFFSET) +#define GET_DMASHDL_MIN_QUOTA_NUM(p) \ + (((p) & DMASHDL_MIN_QUOTA_MASK) >> DMASHDL_MIN_QUOTA_OFFSET) + +#define DMASHDL_MAX_QUOTA_NUM(p) \ + (((p) & 0xfff) << DMASHDL_MAX_QUOTA_OFFSET) +#define GET_DMASHDL_MAX_QUOTA_NUM(p) \ + (((p) & DMASHDL_MAX_QUOTA_MASK) >> DMASHDL_MAX_QUOTA_OFFSET) + +#define ODD_GROUP_ASK_CN_MASK (0xff << 16) +#define ODD_GROUP_ASK_CN_OFFSET 16 +#define GET_ODD_GROUP_ASK_CNT(p) \ + (((p) & ODD_GROUP_ASK_CN_MASK) >> ODD_GROUP_ASK_CN_OFFSET) +#define ODD_GROUP_PKT_IN_CN_MASK (0xff << 24) +#define ODD_GROUP_PKT_IN_CN_OFFSET 24 +#define GET_ODD_GROUP_PKT_IN_CNT(p) \ + (((p) & ODD_GROUP_PKT_IN_CN_MASK) >> ODD_GROUP_PKT_IN_CN_OFFSET) +#define EVEN_GROUP_ASK_CN_MASK (0xff << 0) +#define EVEN_GROUP_ASK_CN_OFFSET 0 +#define GET_EVEN_GROUP_ASK_CNT(p) \ + (((p) & EVEN_GROUP_ASK_CN_MASK) >> EVEN_GROUP_ASK_CN_OFFSET) +#define EVEN_GROUP_PKT_IN_CN_MASK (0xff << 8) +#define EVEN_GROUP_PKT_IN_CN_OFFSET 8 +#define GET_EVEN_GROUP_PKT_IN_CNT(p) \ + (((p) & EVEN_GROUP_PKT_IN_CN_MASK) >> EVEN_GROUP_PKT_IN_CN_OFFSET) + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +#if defined(_HIF_PCIE) || defined(_HIF_AXI) +/* DMASHDL_REFILL_CONTROL */ +union _DMASHDL_REFILL_CONTROL { + struct { + uint32_t PRIORITY:16; + uint32_t DISABLE:16; + } field; + + uint32_t word; +}; + +/* DMASHDL_PACKET_MAX_SIZE */ +union _DMASHDL_PACKET_MAX_SIZE { + struct { + uint32_t PLE_SIZE:12; + uint32_t RSV_12_15:4; + uint32_t PSE_SIZE:12; + uint32_t RSV_28_31:4; + } field; + + uint32_t word; +}; + +/* DMASHDL_GROUP_CONTROL */ +union _DMASHDL_GROUP_CONTROL { + struct { + uint32_t MIN_QUOTAE:12; + uint32_t RSV_12_15:4; + uint32_t MAX_QUOTAE:12; + uint32_t RSV_28_31:4; + } field; + + uint32_t word; +}; +#endif /* _HIF_PCIE */ + +/* Group index */ +enum _ENUM_GROUP_INDEX_T { + GROUP0_INDEX = 0, + GROUP1_INDEX, + GROUP2_INDEX, + GROUP3_INDEX, + GROUP4_INDEX, + GROUP5_INDEX, + GROUP6_INDEX, + GROUP7_INDEX, + GROUP8_INDEX, + GROUP9_INDEX, + GROUP10_INDEX, + GROUP11_INDEX, + GROUP12_INDEX, + GROUP13_INDEX, + GROUP14_INDEX, + GROUP15_INDEX, + MAX_GROUP_NUM +}; + +/******************************************************************************* + * P U B 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 diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/connac_reg.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/connac_reg.h new file mode 100644 index 0000000000000..8a9221705d6fe --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/connac_reg.h @@ -0,0 +1,269 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "connac_reg.h" + * \brief The common register definition of MT6630 + * + * N/A + */ + + + +#ifndef _CONNAC_REG_H +#define _CONNAC_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 + ******************************************************************************* + */ +#define CONN_CFG_BASE 0x80020000 + +#define CONN_CFG_ON_BASE 0x81021000 + +#define CONN_CFG_ON_CONN_ON_MISC_ADDR (CONN_CFG_ON_BASE + 0x140) +#define CONN_CFG_CHIP_ID_ADDR (CONN_CFG_BASE + 0x1010) + +#define CONN_MCU_CONFG_ON_BASE 0x81030000 + +#define CONN_MCU_CONFG_ON_HOST_MAILBOX_WF_ADDR \ + (CONN_MCU_CONFG_ON_BASE + 0x100) + +/* + * ============================================================================ + * + * ---CONN_ON_MISC (0x81021000 + 0x140)--- + * + * HOST_LPCR_FW_OWN[0] - (W1C) xxx + * DRV_FM_STAT_SYNC[3..1] - (RW) xxx + * RBIST_MODE[4] - (RW) xxx + * RESERVED5[31..5] - (RO) Reserved bits + * + * ============================================================================ + */ +#define CONN_CFG_ON_CONN_ON_MISC_RBIST_MODE_ADDR \ + CONN_CFG_ON_CONN_ON_MISC_ADDR +#define CONN_CFG_ON_CONN_ON_MISC_RBIST_MODE_MASK \ + 0x00000010/*RBIST_MODE[4]*/ +#define CONN_CFG_ON_CONN_ON_MISC_RBIST_MODE_SHFT 4 +#define CONN_CFG_ON_CONN_ON_MISC_DRV_FM_STAT_SYNC_ADDR \ + CONN_CFG_ON_CONN_ON_MISC_ADDR +#define CONN_CFG_ON_CONN_ON_MISC_DRV_FM_STAT_SYNC_MASK \ + 0x0000000E/*DRV_FM_STAT_SYNC[3..1]*/ +#define CONN_CFG_ON_CONN_ON_MISC_DRV_FM_STAT_SYNC_SHFT 1 +#define CONN_CFG_ON_CONN_ON_MISC_HOST_LPCR_FW_OWN_ADDR \ + CONN_CFG_ON_CONN_ON_MISC_ADDR +#define CONN_CFG_ON_CONN_ON_MISC_HOST_LPCR_FW_OWN_MASK \ + 0x00000001/*HOST_LPCR_FW_OWN[0]*/ +#define CONN_CFG_ON_CONN_ON_MISC_HOST_LPCR_FW_OWN_SHFT 0 + +#define CONN_HIF_BASE 0x7000 +#define CONN_HIF_ON_LPCTL (CONN_HIF_BASE) +#define CONN_HIF_ON_IRQ_STAT (CONN_HIF_BASE + 0x4) +#define CONN_HIF_ON_IRQ_ENA (CONN_HIF_BASE + 0x8) +#define CONN_HIF_ON_DBGCR01 (CONN_HIF_BASE + 0x104) + +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + +/* MCU Interrupt Event */ +#define HOST2MCU_SW_INT_SET (PCIE_HIF_BASE + 0x0108) + +/* MCU2HOST Software interrupt set */ +#define MCU2HOST_SW_INT_SET (PCIE_HIF_BASE + 0x010C) + +/* MCU to Host interrupt status */ +#define MCU2HOST_SW_INT_STA (PCIE_HIF_BASE + 0x01F0) + +/* MCU to Host interrupt enable */ +#define MCU2HOST_SW_INT_ENA (PCIE_HIF_BASE + 0x01F4) + +#define WPDMA_PAUSE_TX_Q (PCIE_HIF_BASE + 0x0224) + +/* Configuraiton Push */ +#define PCIE_DOORBELL_PUSH (0x484) +#define CR_PCIE_CFG_SET_OWN (0x1 << 0) +#define CR_PCIE_CFG_CLEAR_OWN (0x1 << 1) +#endif /* _HIF_PCIE */ + +#if defined(_HIF_USB) +#define CONNAC_UDMA_BASE 0x7C000000 +#define CONNAC_UDMA_TX_QSEL (CONNAC_UDMA_BASE + 0x8) +#define CONNAC_UDMA_RESET (CONNAC_UDMA_BASE + 0x14) +#define CONNAC_UDMA_WLCFG_1 (CONNAC_UDMA_BASE + 0xc) +#define CONNAC_UDMA_WLCFG_0 (CONNAC_UDMA_BASE + 0x18) + +#define UDMA_WLCFG_0_TX_BUSY_MASK (0x1 << 31) +#define UDMA_WLCFG_0_1US_TIMER_EN_MASK (0x1 << 20) +#define UDMA_WLCFG_0_1US_TIMER_EN(p) (((p) & 0x1) << 20) +#define UDMA_WLCFG_0_RX_FLUSH_MASK (0x1 << 19) +#define UDMA_WLCFG_0_TX_TIMEOUT_EN_MASK (0x1 << 16) + +#define UDMA_WLCFG_1_TX_TIMEOUT_LIMIT_MASK (0xFFFFF << 8) +#define UDMA_WLCFG_1_TX_TIMEOUT_LIMIT(p) (((p) & 0xFFFFF) << 8) +#define UDMA_TX_TIMEOUT_STATUS_MASK (0x1 << 13) + +#define UDMA_TX_TIMEOUT_LIMIT (50000) + +#define UDMA_TX_IDLE_MASK 0x00003f00 + +#define PDMA_IF_MISC 0x500000a8 +#define PDMA_IF_MISC_TX_ENABLE_MASK 0x00000001 + +#define PDMA_HIF_RESET 0x50000100 +#define DPMA_HIF_LOGIC_RESET_MASK (0x1 << 4) + +#define PDMA_DEBUG_EN 0x50000124 +#define PDMA_DEBUG_STATUS 0x50000128 +#define PDMA_DEBUG_TX_STATUS_MASK 0x004c0000 /* 0x00400000 */ +#define PDMA_DEBUG_DMASHDL_REQUEST_DONE_MASK 0x00100000 + +#define PDMA_BUSY_STATUS 0x50000168 +#define PDMA_TX_BUSY_MASK 0x00000001 + +#define PDMA_TX_IDLE_WAIT_COUNT 30 +#endif /* _HIF_USB */ + +#if defined(_HIF_PCIE) || defined(_HIF_AXI) +#define PDMA_DEBUG_EN 0x50000124 +#define PDMA_DEBUG_STATUS 0x50000128 +#define AXI_DEBUG_DEBUG_EN 0x5000012C +#define CONN_HIF_DEBUG_STATUS 0x50000130 +#define PDMA_DEBUG_HIF_BUSY_STATUS 0x50000138 +#define PDMA_DEBUG_BUSY_STATUS 0x50000168 +#define PDMA_DEBUG_REFill 0x5000A010 + +#define PDMA_AXI_DEBUG_FLAG 0x2222 +#define GALS_AXI_DEBUG_FLAG 0x3333 +#define MCU_AXI_DEBUG_FLAG 0x4444 +#define RBUS_DEBUG_FLAG 0x118 + +#define WPDMA_PAUSE_TX_Q_RINGIDX_OFFSET 16 +#define WPDMA_PAUSE_TX_Q_RINGIDX_MASK 0xFFFF0000 +#endif /* _HIF_PCIE */ + + +#define PLE_PKT_MAX_SIZE_MASK (0xfff << 0) +#define PLE_PKT_MAX_SIZE_NUM(p) (((p) & 0xfff) << 0) +#define GET_PLE_PKT_MAX_SIZE_NUM(p) (((p) & PLE_PKT_MAX_SIZE_MASK) >> 0) + +#define PSE_PKT_MAX_SIZE_MASK (0xfff << 16) +#define PSE_PKT_MAX_SIZE_NUM(p) (((p) & 0xfff) << 16) +#define GET_PSE_PKT_MAX_SIZE_NUM(p) (((p) & PSE_PKT_MAX_SIZE_MASK) >> 16) + +#define EXTRA_TXD_SIZE_FOR_TX_BYTE_COUNT 32 + +#define MCU_INT_PDMA0_STOP_DONE BIT(0) +#define MCU_INT_PDMA0_INIT_DONE BIT(1) +#define MCU_INT_SER_TRIGGER_FROM_HOST BIT(2) +#define MCU_INT_PDMA0_RECOVERY_DONE BIT(3) +#define MCU_INT_DRIVER_SER BIT(4) +#define CONNAC_MCU_SW_INT BIT(29) + +#define ERROR_DETECT_STOP_PDMA_WITH_FW_RELOAD BIT(1) +#define ERROR_DETECT_STOP_PDMA BIT(2) +#define ERROR_DETECT_RESET_DONE BIT(3) +#define ERROR_DETECT_RECOVERY_DONE BIT(4) +#define ERROR_DETECT_MCU_NORMAL_STATE BIT(5) +#define CP_LMAC_HANG_WORKAROUND_STEP1 BIT(8) +#define CP_LMAC_HANG_WORKAROUND_STEP2 BIT(9) +#define ERROR_DETECT_LMAC_ERROR BIT(24) +#define ERROR_DETECT_PSE_ERROR BIT(25) +#define ERROR_DETECT_PLE_ERROR BIT(26) +#define ERROR_DETECT_PDMA_ERROR BIT(27) +#define ERROR_DETECT_PCIE_ERROR BIT(28) + +#define ERROR_DETECT_MASK \ + (ERROR_DETECT_STOP_PDMA \ + | ERROR_DETECT_RESET_DONE \ + | ERROR_DETECT_RECOVERY_DONE \ + | ERROR_DETECT_MCU_NORMAL_STATE) + + +/******************************************************************************* + * 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 diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/hal.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/hal.h new file mode 100644 index 0000000000000..437e1a86c0843 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/hal.h @@ -0,0 +1,1231 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "hal.h" + * \brief The declaration of hal functions + * + * N/A + */ + + +#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 + ******************************************************************************* + */ +#define WIFI_SER_SYNC_TIMER_TIMEOUT_IN_MS (100) + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +enum ERR_RECOVERY_STATE { + ERR_RECOV_STOP_IDLE = 0, + ERR_RECOV_STOP_PDMA0, + ERR_RECOV_RESET_PDMA0, + ERR_RECOV_WAIT_MCU_NORMAL, + ERR_RECOV_STATE_NUM +}; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +#if defined(_HIF_USB) +extern struct TIMER rSerSyncTimer; +#endif + +/******************************************************************************* + * 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 CFG_SUPPORT_SNIFFER +#define HAL_MON_EN(_prAdapter) (_prAdapter->prGlueInfo->fgIsEnableMon) +#else +#define HAL_MON_EN(_prAdapter) FALSE +#endif + +#if defined(_HIF_SDIO) +#define HAL_MCR_RD(_prAdapter, _u4Offset, _pu4Value) \ +do { \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (_u4Offset > 0xFFFF) { \ + if (kalDevRegRead_mac(_prAdapter->prGlueInfo, \ + _u4Offset, _pu4Value) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, \ + "HAL_MCR_RD (MAC) access fail! 0x%x: 0x%x\n", \ + (uint32_t) (_u4Offset), \ + *((uint32_t *) (_pu4Value))); \ + } \ + } else { \ + if (kalDevRegRead(_prAdapter->prGlueInfo, \ + _u4Offset, _pu4Value) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, \ + "HAL_MCR_RD (SDIO) access fail! 0x%x: 0x%x\n", \ + (uint32_t) (_u4Offset), \ + *((uint32_t *) (_pu4Value))); \ + } \ + } \ + } else { \ + DBGLOG(HAL, WARN, "ignore HAL_MCR_RD access! 0x%x\n", \ + (uint32_t) (_u4Offset)); \ + } \ +} while (0) + +#define HAL_MCR_WR(_prAdapter, _u4Offset, _u4Value) \ +do { \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (_u4Offset > 0xFFFF) { \ + if (kalDevRegWrite_mac(_prAdapter->prGlueInfo, \ + _u4Offset, _u4Value) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, \ + "HAL_MCR_WR (MAC) access fail! 0x%x: 0x%x\n", \ + (uint32_t) (_u4Offset), \ + (uint32_t) (_u4Value)); \ + } \ + } else { \ + if (kalDevRegWrite(_prAdapter->prGlueInfo, \ + _u4Offset, _u4Value) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, \ + "HAL_MCR_WR (SDIO) access fail! 0x%x: 0x%x\n", \ + (uint32_t) (_u4Offset), \ + (uint32_t) (_u4Value)); \ + } \ + } \ + } else { \ + DBGLOG(HAL, WARN, "ignore HAL_MCR_WR access! 0x%x: 0x%x\n", \ + (uint32_t) (_u4Offset), (uint32_t) (_u4Value)); \ + } \ +} while (0) + +#define HAL_PORT_RD(_prAdapter, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ +{ \ + /*fgResult = FALSE; */\ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (kalDevPortRead(_prAdapter->prGlueInfo, _u4Port, _u4Len, \ + _pucBuf, _u4ValidBufSize) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, "HAL_PORT_RD access fail! 0x%x\n", \ + (uint32_t) (_u4Port)); \ + } \ + else { \ + /*fgResult = TRUE;*/ } \ + } else { \ + DBGLOG(HAL, WARN, "ignore HAL_PORT_RD access! 0x%x\n", \ + (uint32_t) (_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", \ + (uint32_t) (_u4Port)); \ + } \ + else \ + ; /*fgResult = TRUE;*/ \ + } else { \ + DBGLOG(HAL, WARN, "ignore HAL_PORT_WR access! 0x%x\n", \ + (uint32_t) (_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", \ + (uint32_t)(_u4Port)); \ + } \ + else { \ + /* Todo:: Nothing*/ \ + } \ + } \ + else { \ + DBGLOG(HAL, WARN, "ignore HAL_BYTE_WR access! 0x%x\n", \ + (uint32_t) (_u4Port)); \ + } \ +} + +#define HAL_DRIVER_OWN_BY_SDIO_CMD52(_prAdapter, _pfgDriverIsOwnReady) \ +{ \ + uint8_t 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) \ +{ \ + HAL_MCR_WR(_prAdapter, _u4Port, (uint32_t)_ucBuf); \ +} + +#endif /* #if defined(_HIF_SDIO) */ + +#define HAL_WRITE_TX_DATA(_prAdapter, _prMsduInfo) \ +{ \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + kalDevWriteData(_prAdapter->prGlueInfo, _prMsduInfo); \ +} + +#define HAL_KICK_TX_DATA(_prAdapter) \ +{ \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + kalDevKickData(_prAdapter->prGlueInfo); \ +} + +#define HAL_WRITE_TX_CMD(_prAdapter, _prCmdInfo, _ucTC) \ +{ \ + enum ENUM_CMD_TX_RESULT ret; \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + ret = kalDevWriteCmd(_prAdapter->prGlueInfo, _prCmdInfo, _ucTC); \ + if (ret == CMD_TX_RESULT_SUCCESS) { \ + if (_prCmdInfo && _prCmdInfo->pfHifTxCmdDoneCb) \ + _prCmdInfo->pfHifTxCmdDoneCb(_prAdapter, _prCmdInfo); \ + } \ +} + +#if defined(_HIF_PCIE) || defined(_HIF_AXI) +#define HAL_READ_RX_PORT(prAdapter, u4PortId, u4Len, pvBuf, _u4ValidBufSize) \ +{ \ + ASSERT(u4PortId < 2); \ + HAL_PORT_RD(prAdapter, \ + u4PortId, \ + u4Len, \ + pvBuf, \ + _u4ValidBufSize/*temp!!*//*4Kbyte*/) \ +} + +#define HAL_WRITE_TX_PORT(_prAdapter, _u4PortId, _u4Len, _pucBuf, _u4BufSize) \ +{ \ + HAL_PORT_WR(_prAdapter, \ + _u4PortId, \ + _u4Len, \ + _pucBuf, \ + _u4BufSize/*temp!!*//*4KByte*/) \ +} + +#define HAL_MCR_RD_AND_WAIT(_pAdapter, _offset, _pReadValue, \ + _waitCondition, _waitDelay, _waitCount, _status) + +#define HAL_MCR_WR_AND_WAIT(_pAdapter, _offset, _writeValue, \ + _busyMask, _waitDelay, _waitCount, _status) + +#define HAL_GET_CHIP_ID_VER(_prAdapter, pu2ChipId, pu2Version) \ +{ \ + uint32_t u4Value = 0; \ + HAL_MCR_RD(_prAdapter, HIF_SYS_REV, &u4Value); \ + *pu2ChipId = ((u4Value & PCIE_HIF_SYS_PROJ) >> 16); \ + *pu2Version = (u4Value & PCIE_HIF_SYS_REV); \ +} + +#define HAL_WIFI_FUNC_READY_CHECK(_prAdapter, _checkItem, _pfgResult) \ +do { \ + struct mt66xx_chip_info *prChipInfo = NULL; \ + uint32_t u4Value = 0; \ + if (!_prAdapter->chip_info) \ + ASSERT(0); \ + *_pfgResult = FALSE; \ + prChipInfo = _prAdapter->chip_info; \ + HAL_MCR_RD(_prAdapter, prChipInfo->sw_sync0, &u4Value); \ + if ((u4Value & (_checkItem << prChipInfo->sw_ready_bit_offset)) \ + == (_checkItem << prChipInfo->sw_ready_bit_offset)) \ + *_pfgResult = TRUE; \ +} while (0) + +#define HAL_WIFI_FUNC_OFF_CHECK(_prAdapter, _checkItem, _pfgResult) \ +do { \ + u_int8_t fgLpOwnResult; \ + HAL_WIFI_FUNC_READY_CHECK(_prAdapter, _checkItem, _pfgResult); \ + if (*_pfgResult) { \ + HAL_LP_OWN_RD(_prAdapter, &fgLpOwnResult); \ + if (fgLpOwnResult == FALSE) { \ + DBGLOG(INIT, INFO, \ + "HAL_LP_OWN_RD %d\n", fgLpOwnResult); \ + HAL_LP_OWN_SET(prAdapter, &fgLpOwnResult); \ + DBGLOG(INIT, INFO, \ + "HAL_LP_OWN_SET %d\n", fgLpOwnResult); \ + } \ + } \ + *_pfgResult = !*_pfgResult; \ +} while (0) + +#define HAL_WIFI_FUNC_GET_STATUS(_prAdapter, _u4Result) \ +do { \ + struct mt66xx_chip_info *prChipInfo = NULL; \ + struct BUS_INFO *prBusInfo = NULL; \ + uint32_t u4Value = 0; \ + if (!_prAdapter->chip_info || !_prAdapter->chip_info->bus_info) \ + ASSERT(0); \ + prChipInfo = _prAdapter->chip_info; \ + prBusInfo = prChipInfo->bus_info; \ + HAL_MCR_RD(_prAdapter, prChipInfo->sw_sync0, &_u4Result); \ + if (prBusInfo->getMailboxStatus) { \ + prBusInfo->getMailboxStatus(_prAdapter, &u4Value); \ + DBGLOG(INIT, INFO, "Mailbox: 0x%x\n", u4Value); \ + } \ +} while (0) + +#define HAL_INTR_DISABLE(_prAdapter) + +#define HAL_INTR_ENABLE(_prAdapter) + +#define HAL_INTR_ENABLE_AND_LP_OWN_SET(_prAdapter) + +/* Polling interrupt status bit due to CFG_PCIE_LPCR_HOST + * status bit not work when chip sleep + */ +#define HAL_LP_OWN_RD(_prAdapter, _pfgResult) \ +do { \ + struct mt66xx_chip_info *prChipInfo = NULL; \ + struct BUS_INFO *prBusInfo = NULL; \ + if (!_prAdapter->chip_info || !_prAdapter->chip_info->bus_info) \ + ASSERT(0); \ + prChipInfo = _prAdapter->chip_info; \ + prBusInfo = prChipInfo->bus_info; \ + prBusInfo->lowPowerOwnRead(_prAdapter, _pfgResult); \ +} while (0) + +#define HAL_LP_OWN_SET(_prAdapter, _pfgResult) \ +do { \ + struct mt66xx_chip_info *prChipInfo = NULL; \ + struct BUS_INFO *prBusInfo = NULL; \ + if (!_prAdapter->chip_info || !_prAdapter->chip_info->bus_info) \ + ASSERT(0); \ + prChipInfo = _prAdapter->chip_info; \ + prBusInfo = prChipInfo->bus_info; \ + prBusInfo->lowPowerOwnSet(_prAdapter, _pfgResult); \ +} while (0) + +#define HAL_LP_OWN_CLR(_prAdapter, _pfgResult) \ +do { \ + struct mt66xx_chip_info *prChipInfo = NULL; \ + struct BUS_INFO *prBusInfo = NULL; \ + if (!_prAdapter->chip_info || !_prAdapter->chip_info->bus_info) \ + ASSERT(0); \ + prChipInfo = _prAdapter->chip_info; \ + prBusInfo = prChipInfo->bus_info; \ + prBusInfo->lowPowerOwnClear(_prAdapter, _pfgResult); \ +} while (0) + +#define HAL_GET_ABNORMAL_INTERRUPT_REASON_CODE(_prAdapter, pu4AbnormalReason) + +#define HAL_DISABLE_RX_ENHANCE_MODE(_prAdapter) + +#define HAL_ENABLE_RX_ENHANCE_MODE(_prAdapter) + +#define HAL_CFG_MAX_HIF_RX_LEN_NUM(_prAdapter, _ucNumOfRxLen) + +#define HAL_SET_INTR_STATUS_READ_CLEAR(prAdapter) + +#define HAL_SET_INTR_STATUS_WRITE_1_CLEAR(prAdapter) + +#define HAL_READ_INTR_STATUS(prAdapter, length, pvBuf) + +#define HAL_READ_TX_RELEASED_COUNT(_prAdapter, au2TxReleaseCount) + +#define HAL_READ_RX_LENGTH(prAdapter, pu2Rx0Len, pu2Rx1Len) + +#define HAL_GET_INTR_STATUS_FROM_ENHANCE_MODE_STRUCT(pvBuf, u2Len, pu4Status) + +#define HAL_GET_TX_STATUS_FROM_ENHANCE_MODE_STRUCT(pvInBuf, \ + pu4BufOut, u4LenBufOut) + +#define HAL_GET_RX_LENGTH_FROM_ENHANCE_MODE_STRUCT(pvInBuf, \ + pu2Rx0Num, au2Rx0Len, pu2Rx1Num, au2Rx1Len) + +#define HAL_GET_MAILBOX_FROM_ENHANCE_MODE_STRUCT(pvInBuf, \ + pu4Mailbox0, pu4Mailbox1) + +#define HAL_IS_TX_DONE_INTR(u4IntrStatus) \ + ((u4IntrStatus & (WPDMA_TX_DONE_INT0 | \ + WPDMA_TX_DONE_INT1 | WPDMA_TX_DONE_INT2 | WPDMA_TX_DONE_INT3 | \ + WPDMA_TX_DONE_INT15)) ? TRUE : FALSE) + +#define HAL_IS_RX_DONE_INTR(u4IntrStatus) \ + ((u4IntrStatus & (WPDMA_RX_DONE_INT0 | WPDMA_RX_DONE_INT1)) \ + ? TRUE : FALSE) + +#define HAL_IS_ABNORMAL_INTR(u4IntrStatus) + +#define HAL_IS_FW_OWNBACK_INTR(u4IntrStatus) + +#define HAL_PUT_MAILBOX(prAdapter, u4MboxId, u4Data) + +#define HAL_GET_MAILBOX(prAdapter, u4MboxId, pu4Data) + +#define HAL_SET_MAILBOX_READ_CLEAR(prAdapter, fgEnableReadClear) \ +{ \ + prAdapter->prGlueInfo->rHifInfo.fgMbxReadClear = fgEnableReadClear;\ +} + +#define HAL_GET_MAILBOX_READ_CLEAR(prAdapter) \ + (prAdapter->prGlueInfo->rHifInfo.fgMbxReadClear) + +#define HAL_READ_INT_STATUS(_prAdapter, _pu4IntStatus) \ +{ \ + struct BUS_INFO *prBusInfo; \ + prBusInfo = _prAdapter->chip_info->bus_info; \ + if (prBusInfo->devReadIntStatus) \ + prBusInfo->devReadIntStatus(_prAdapter, _pu4IntStatus); \ + else \ + kalDevReadIntStatus(_prAdapter, _pu4IntStatus);\ + if (_prAdapter->u4NoMoreRfb != 0) \ + *_pu4IntStatus |= WHISR_RX0_DONE_INT; \ +} + +#define HAL_HIF_INIT(prAdapter) + +#define HAL_ENABLE_FWDL(_prAdapter, _fgEnable) \ +{ \ + halEnableFWDownload(_prAdapter, _fgEnable); \ +} + +#define HAL_WAKE_UP_WIFI(_prAdapter) \ +{ \ + halWakeUpWiFi(_prAdapter);\ +} + +#define HAL_CLEAR_DUMMY_REQ(_prAdapter) \ +{ \ + struct mt66xx_chip_info *prChipInfo = NULL; \ + uint32_t u4Value = 0; \ + if (!_prAdapter->chip_info) {\ + ASSERT(0); \ + } else {\ + prChipInfo = _prAdapter->chip_info; \ + HAL_MCR_RD(_prAdapter, prChipInfo->sw_sync0, &u4Value); \ + u4Value &= ~(WIFI_FUNC_DUMMY_REQ << \ + prChipInfo->sw_ready_bit_offset);\ + HAL_MCR_WR(prAdapter, prChipInfo->sw_sync0, u4Value);\ + } \ +} + +#define HAL_IS_TX_DIRECT(_prAdapter) FALSE + +#define HAL_IS_RX_DIRECT(_prAdapter) FALSE + +#endif + +#if defined(_HIF_SDIO) +#define HIF_H2D_SW_INT_SHFT (16) +/* bit16 */ +#define SDIO_MAILBOX_FUNC_READ_REG_IDX (BIT(0) << HIF_H2D_SW_INT_SHFT) +/* bit17 */ +#define SDIO_MAILBOX_FUNC_WRITE_REG_IDX (BIT(1) << HIF_H2D_SW_INT_SHFT) +/* bit18 */ +#define SDIO_MAILBOX_FUNC_CHECKSUN16_IDX (BIT(2) << HIF_H2D_SW_INT_SHFT) + +#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, _u4PortId, _u4Len, _pucBuf, _u4BufSize) \ +{ \ + if ((_u4BufSize - _u4Len) >= sizeof(uint32_t)) { \ + /* fill with single dword of zero as TX-aggregation end */ \ + *(uint32_t *) (&((_pucBuf)[ALIGN_4(_u4Len)])) = 0; \ + } \ + HAL_PORT_WR(_prAdapter, \ + MCR_WTDR1, \ + _u4Len, \ + _pucBuf, \ + _u4BufSize/*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) \ + { \ + uint32_t count = 0; \ + (_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) \ + { \ + uint32_t u4Temp = 0; \ + uint32_t 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) \ +{ \ + uint32_t u4Value = 0; \ + HAL_MCR_RD(_prAdapter, \ + MCR_WCIR, \ + &u4Value); \ + *pu2ChipId = (uint16_t)(u4Value & WCIR_CHIP_ID); \ + *pu2Version = (uint16_t)(u4Value & WCIR_REVISION_ID) >> 16; \ +} + +#define HAL_WIFI_FUNC_READY_CHECK(_prAdapter, _checkItem, _pfgResult) \ +do { \ + uint32_t u4Value = 0; \ + *_pfgResult = FALSE; \ + HAL_MCR_RD(_prAdapter, \ + MCR_WCIR, \ + &u4Value); \ + if (u4Value & WCIR_WLAN_READY) { \ + *_pfgResult = TRUE; \ + } \ +} while (0) + +#define HAL_WIFI_FUNC_OFF_CHECK(_prAdapter, _checkItem, _pfgResult) \ +do { \ + uint32_t u4Value = 0; \ + *_pfgResult = FALSE; \ + HAL_MCR_RD(_prAdapter, MCR_WCIR, &u4Value); \ + if ((u4Value & WCIR_WLAN_READY) == 0) { \ + *_pfgResult = TRUE; \ + } \ + halPrintMailbox(_prAdapter);\ + halPollDbgCr(_prAdapter, LP_DBGCR_POLL_ROUND); \ +} while (0) + +#define HAL_WIFI_FUNC_GET_STATUS(_prAdapter, _u4Result) \ + halGetMailbox(_prAdapter, 0, &_u4Result) + +#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_RD(_prAdapter, _pfgResult) \ +{ \ + uint32_t u4RegValue = 0; \ + *_pfgResult = FALSE; \ + HAL_MCR_RD(_prAdapter, MCR_WHLPCR, &u4RegValue); \ + if (u4RegValue & WHLPCR_IS_DRIVER_OWN) { \ + *_pfgResult = TRUE; \ + } \ +} + +#define HAL_LP_OWN_SET(_prAdapter, _pfgResult) \ +{ \ + uint32_t u4RegValue = 0; \ + *_pfgResult = FALSE; \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHLPCR, \ + WHLPCR_FW_OWN_REQ_SET); \ + HAL_MCR_RD(_prAdapter, MCR_WHLPCR, &u4RegValue); \ + if (u4RegValue & WHLPCR_IS_DRIVER_OWN) { \ + *_pfgResult = TRUE; \ + } \ +} + +#define HAL_LP_OWN_CLR(_prAdapter, _pfgResult) \ +{ \ + uint32_t u4RegValue = 0; \ + *_pfgResult = FALSE; \ + /* Software get LP ownership */ \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHLPCR, \ + WHLPCR_FW_OWN_REQ_CLR); \ + HAL_MCR_RD(_prAdapter, MCR_WHLPCR, &u4RegValue); \ + if (u4RegValue & WHLPCR_IS_DRIVER_OWN) { \ + *_pfgResult = TRUE; \ + } \ +} + +#define HAL_GET_ABNORMAL_INTERRUPT_REASON_CODE(_prAdapter, pu4AbnormalReason) \ +{ \ + HAL_MCR_RD(_prAdapter, \ + MCR_WASR, \ + pu4AbnormalReason); \ +} + +#define HAL_DISABLE_RX_ENHANCE_MODE(_prAdapter) \ +{ \ + uint32_t u4Value = 0; \ + 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) \ +{ \ + uint32_t u4Value = 0; \ + 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) \ +{ \ + uint32_t u4Value = 0, ucNum; \ + ucNum = ((_ucNumOfRxLen >= 16) ? 0 : _ucNumOfRxLen); \ + HAL_MCR_RD(_prAdapter, \ + MCR_WHCR, \ + &u4Value); \ + u4Value &= ~WHCR_MAX_HIF_RX_LEN_NUM; \ + u4Value |= ((((uint32_t)ucNum) << WHCR_OFFSET_MAX_HIF_RX_LEN_NUM) \ + & WHCR_MAX_HIF_RX_LEN_NUM); \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHCR, \ + u4Value); \ +} + +#define HAL_SET_INTR_STATUS_READ_CLEAR(prAdapter) \ +{ \ + uint32_t u4Value = 0; \ + 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) \ +{ \ + uint32_t u4Value = 0; \ + 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, au2TxReleaseCount) \ +{ \ + uint32_t *pu4Value = (uint32_t *)au2TxReleaseCount; \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTQCR0, \ + &pu4Value[0]); \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTQCR1, \ + &pu4Value[1]); \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTQCR2, \ + &pu4Value[2]); \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTQCR3, \ + &pu4Value[3]); \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTQCR4, \ + &pu4Value[4]); \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTQCR5, \ + &pu4Value[5]); \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTQCR6, \ + &pu4Value[6]); \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTQCR7, \ + &pu4Value[7]); \ +} + +#define HAL_READ_RX_LENGTH(prAdapter, pu2Rx0Len, pu2Rx1Len) \ +{ \ + uint32_t u4Value = 0; \ + HAL_MCR_RD(prAdapter, \ + MCR_WRPLR, \ + &u4Value); \ + *pu2Rx0Len = (uint16_t)u4Value; \ + *pu2Rx1Len = (uint16_t)(u4Value >> 16); \ +} + +#define HAL_GET_INTR_STATUS_FROM_ENHANCE_MODE_STRUCT(pvBuf, \ + u2Len, pu4Status) \ +{ \ + uint32_t *pu4Buf = (uint32_t *)pvBuf; \ + *pu4Status = pu4Buf[0]; \ +} + +#define HAL_GET_TX_STATUS_FROM_ENHANCE_MODE_STRUCT(pvInBuf, \ + pu4BufOut, u4LenBufOut) \ +{ \ + uint32_t *pu4Buf = (uint32_t *)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) \ +{ \ + uint32_t *pu4Buf = (uint32_t *)pvInBuf; \ + ASSERT((sizeof(au2Rx0Len) / sizeof(uint16_t)) >= 16); \ + ASSERT((sizeof(au2Rx1Len) / sizeof(uint16_t)) >= 16); \ + *pu2Rx0Num = (uint16_t)pu4Buf[3]; \ + *pu2Rx1Num = (uint16_t)(pu4Buf[3] >> 16); \ + kalMemCopy(au2Rx0Len, &pu4Buf[4], 8); \ + kalMemCopy(au2Rx1Len, &pu4Buf[12], 8); \ +} + +#define HAL_GET_MAILBOX_FROM_ENHANCE_MODE_STRUCT(pvInBuf, \ + pu4Mailbox0, pu4Mailbox1) \ +{ \ + uint32_t *pu4Buf = (uint32_t *)pvInBuf; \ + *pu4Mailbox0 = (uint16_t)pu4Buf[21]; \ + *pu4Mailbox1 = (uint16_t)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) \ +{ \ + uint32_t u4Value = 0; \ + HAL_MCR_RD(prAdapter, MCR_WHCR, &u4Value);\ + HAL_MCR_WR(prAdapter, MCR_WHCR, \ + (fgEnableReadClear) ? \ + (u4Value | WHCR_RECV_MAILBOX_RD_CLR_EN) : \ + (u4Value & ~WHCR_RECV_MAILBOX_RD_CLR_EN)); \ + prAdapter->prGlueInfo->rHifInfo.fgMbxReadClear = fgEnableReadClear;\ +} + +#define HAL_GET_MAILBOX_READ_CLEAR(prAdapter) \ + (prAdapter->prGlueInfo->rHifInfo.fgMbxReadClear) + +#define HAL_READ_INT_STATUS(prAdapter, _pu4IntStatus) \ +{ \ + kalDevReadIntStatus(prAdapter, _pu4IntStatus);\ +} + +#define HAL_HIF_INIT(_prAdapter) \ +{ \ + halDevInit(_prAdapter);\ +} + +#define HAL_ENABLE_FWDL(_prAdapter, _fgEnable) + +#define HAL_WAKE_UP_WIFI(_prAdapter) \ +{ \ + halWakeUpWiFi(_prAdapter);\ +} + +#define HAL_IS_TX_DIRECT(_prAdapter) FALSE + +#define HAL_IS_RX_DIRECT(_prAdapter) FALSE + +#endif + +#if defined(_HIF_USB) +#define HAL_GET_ABNORMAL_INTERRUPT_REASON_CODE(_prAdapter, \ + pu4AbnormalReason) + +#define HAL_DISABLE_RX_ENHANCE_MODE(_prAdapter) + +#define HAL_ENABLE_RX_ENHANCE_MODE(_prAdapter) + +#define HAL_CFG_MAX_HIF_RX_LEN_NUM(_prAdapter, _ucNumOfRxLen) + +#define HAL_SET_INTR_STATUS_READ_CLEAR(prAdapter) + +#define HAL_SET_INTR_STATUS_WRITE_1_CLEAR(prAdapter) + +#define HAL_READ_INTR_STATUS(prAdapter, length, pvBuf) + +#define HAL_READ_TX_RELEASED_COUNT(_prAdapter, au2TxReleaseCount) + +#define HAL_READ_RX_LENGTH(prAdapter, pu2Rx0Len, pu2Rx1Len) + +#define HAL_GET_INTR_STATUS_FROM_ENHANCE_MODE_STRUCT(pvBuf, \ + u2Len, pu4Status) + +#define HAL_GET_TX_STATUS_FROM_ENHANCE_MODE_STRUCT(pvInBuf, \ + pu4BufOut, u4LenBufOut) + +#define HAL_GET_RX_LENGTH_FROM_ENHANCE_MODE_STRUCT(pvInBuf, \ + pu2Rx0Num, au2Rx0Len, pu2Rx1Num, au2Rx1Len) + +#define HAL_GET_MAILBOX_FROM_ENHANCE_MODE_STRUCT(pvInBuf, \ + pu4Mailbox0, pu4Mailbox1) + +#define HAL_READ_TX_RELEASED_COUNT(_prAdapter, au2TxReleaseCount) + +#define HAL_IS_TX_DONE_INTR(u4IntrStatus) FALSE + +#define HAL_IS_RX_DONE_INTR(u4IntrStatus) + +#define HAL_IS_ABNORMAL_INTR(u4IntrStatus) + +#define HAL_IS_FW_OWNBACK_INTR(u4IntrStatus) + +#define HAL_PUT_MAILBOX(prAdapter, u4MboxId, u4Data) + +#define HAL_GET_MAILBOX(prAdapter, u4MboxId, pu4Data) TRUE + +#define HAL_SET_MAILBOX_READ_CLEAR(prAdapter, fgEnableReadClear) + +#define HAL_GET_MAILBOX_READ_CLEAR(prAdapter) TRUE + +#define HAL_WIFI_FUNC_POWER_ON(_prAdapter) \ + mtk_usb_vendor_request(_prAdapter->prGlueInfo, 0, \ + _prAdapter->chip_info->bus_info->u4device_vender_request_out, \ + VND_REQ_POWER_ON_WIFI, 0, 1, NULL, 0) + +#define HAL_WIFI_FUNC_CHIP_RESET(_prAdapter) \ + mtk_usb_vendor_request(_prAdapter->prGlueInfo, 0, \ + _prAdapter->chip_info->bus_info->u4device_vender_request_out, \ + VND_REQ_POWER_ON_WIFI, 1, 1, NULL, 0) + +#define HAL_WIFI_FUNC_READY_CHECK(_prAdapter, _checkItem, _pfgResult) \ +do { \ + struct mt66xx_chip_info *prChipInfo = NULL; \ + uint32_t u4Value = 0; \ + if (!_prAdapter->chip_info) \ + ASSERT(0); \ + *_pfgResult = FALSE; \ + prChipInfo = _prAdapter->chip_info; \ + HAL_MCR_RD(_prAdapter, prChipInfo->sw_sync0, &u4Value); \ + if ((u4Value & (_checkItem << prChipInfo->sw_ready_bit_offset)) \ + == (_checkItem << prChipInfo->sw_ready_bit_offset)) \ + *_pfgResult = TRUE; \ +} while (0) + +#define HAL_WIFI_FUNC_OFF_CHECK(_prAdapter, _checkItem, _pfgResult) \ +do { \ + struct mt66xx_chip_info *prChipInfo = NULL; \ + uint32_t u4Value = 0; \ + if (!_prAdapter->chip_info) \ + ASSERT(0); \ + *_pfgResult = FALSE; \ + prChipInfo = _prAdapter->chip_info; \ + HAL_MCR_RD(_prAdapter, prChipInfo->sw_sync0, &u4Value); \ + if ((u4Value & (_checkItem << prChipInfo->sw_ready_bit_offset)) == 0) \ + *_pfgResult = TRUE; \ +} while (0) + +#define HAL_WIFI_FUNC_GET_STATUS(_prAdapter, _u4Result) \ +do { \ + struct mt66xx_chip_info *prChipInfo = NULL; \ + if (!_prAdapter->chip_info) \ + ASSERT(0); \ + prChipInfo = _prAdapter->chip_info; \ + HAL_MCR_RD(_prAdapter, prChipInfo->sw_sync0, &_u4Result); \ +} while (0) + +#define HAL_INTR_DISABLE(_prAdapter) + +#define HAL_INTR_ENABLE(_prAdapter) + +#define HAL_INTR_ENABLE_AND_LP_OWN_SET(_prAdapter) + +#define HAL_READ_INT_STATUS(prAdapter, _pu4IntStatus) \ +{ \ + halGetCompleteStatus(prAdapter, _pu4IntStatus); \ +} + +#define HAL_HIF_INIT(_prAdapter) \ +{ \ + halDevInit(_prAdapter);\ +} + +#define HAL_ENABLE_FWDL(_prAdapter, _fgEnable) \ +{ \ + halEnableFWDownload(_prAdapter, _fgEnable);\ +} + +#define HAL_WAKE_UP_WIFI(_prAdapter) \ +{ \ + halWakeUpWiFi(_prAdapter);\ +} + +#define HAL_LP_OWN_RD(_prAdapter, _pfgResult) + +#define HAL_LP_OWN_SET(_prAdapter, _pfgResult) + +#define HAL_LP_OWN_CLR(_prAdapter, _pfgResult) + +#define HAL_WRITE_TX_PORT(_prAdapter, _u4PortId, _u4Len, _pucBuf, _u4BufSize) \ +{ \ + HAL_PORT_WR(_prAdapter, \ + _u4PortId, \ + _u4Len, \ + _pucBuf, \ + _u4BufSize/*temp!!*//*4KByte*/) \ +} + +#define HAL_IS_TX_DIRECT(_prAdapter) \ + ((CFG_TX_DIRECT_USB) ? TRUE : FALSE) + +#define HAL_IS_RX_DIRECT(_prAdapter) \ + ((CFG_RX_DIRECT_USB) ? TRUE : FALSE) + +#endif + +/* + * TODO: os-related, should we separate the file just leave API here and + * do the implementation in os folder (?) + * followings are the necessary API for build PASS + */ +#ifdef CFG_VIRTUAL_OS +#define HAL_WRITE_TX_PORT(_prAd, _u4PortId, _u4Len, _pucBuf, _u4BufSize) \ + kal_virt_write_tx_port(_prAd, _u4PortId, _u4Len, _pucBuf, _u4BufSize) + +#define HAL_WIFI_FUNC_GET_STATUS(_prAdapter, _u4Result) \ + kal_virt_get_wifi_func_stat(_prAdapter, &_u4Result) + +#define HAL_WIFI_FUNC_OFF_CHECK(_prAdapter, _checkItem, _pfgResult) \ + kal_virt_chk_wifi_func_off(_prAdapter, _checkItem, _pfgResult) + +#define HAL_WIFI_FUNC_READY_CHECK(_prAdapter, _checkItem, _pfgResult) \ + kal_virt_chk_wifi_func_ready(_prAdapter, _checkItem, _pfgResult) + +#define HAL_SET_MAILBOX_READ_CLEAR(_prAdapter, _fgEnableReadClear) \ + kal_virt_set_mailbox_readclear(_prAdapter, _fgEnableReadClear) + +#define HAL_SET_INTR_STATUS_READ_CLEAR(_prAdapter) \ + kal_virt_set_int_stat_readclear(_prAdapter) + +#define HAL_HIF_INIT(_prAdapter) \ + kal_virt_init_hif(_prAdapter) + +#define HAL_ENABLE_FWDL(_prAdapter, _fgEnable) \ + kal_virt_enable_fwdl(_prAdapter, _fgEnable) + +#define HAL_READ_INT_STATUS(_prAdapter, _pu4IntStatus) \ + kal_virt_get_int_status(_prAdapter, _pu4IntStatus) + +#define HAL_IS_TX_DIRECT(_prAdapter) FALSE + +#define HAL_IS_RX_DIRECT(_prAdapter) FALSE +#endif +#define INVALID_VERSION 0xFFFF /* used by HW/FW version */ +/******************************************************************************* + * 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 + ******************************************************************************* + */ + +u_int8_t halVerifyChipID(IN struct ADAPTER *prAdapter); +uint32_t halGetChipHwVer(IN struct ADAPTER *prAdapter); +uint32_t halGetChipSwVer(IN struct ADAPTER *prAdapter); + +uint32_t halRxWaitResponse(IN struct ADAPTER *prAdapter, + IN uint8_t ucPortIdx, OUT uint8_t *pucRspBuffer, + IN uint32_t u4MaxRespBufferLen, OUT uint32_t *pu4Length); + +void halEnableInterrupt(IN struct ADAPTER *prAdapter); +void halDisableInterrupt(IN struct ADAPTER *prAdapter); + +u_int8_t halSetDriverOwn(IN struct ADAPTER *prAdapter); +void halSetFWOwn(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnableGlobalInt); + +void halDevInit(IN struct ADAPTER *prAdapter); +void halEnableFWDownload(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnable); +void halWakeUpWiFi(IN struct ADAPTER *prAdapter); +void halTxCancelSendingCmd(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo); +void halTxCancelAllSending(IN struct ADAPTER *prAdapter); +u_int8_t halTxIsDataBufEnough(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); +void halProcessTxInterrupt(IN struct ADAPTER *prAdapter); +uint32_t halTxPollingResource(IN struct ADAPTER *prAdapter, + IN uint8_t ucTC); +void halSerHifReset(IN struct ADAPTER *prAdapter); + +void halProcessRxInterrupt(IN struct ADAPTER *prAdapter); +void halProcessAbnormalInterrupt(IN struct ADAPTER *prAdapter); +void halProcessSoftwareInterrupt(IN struct ADAPTER *prAdapter); +/* Hif power off wifi */ +uint32_t halHifPowerOffWifi(IN struct ADAPTER *prAdapter); + + +bool halHifSwInfoInit(IN struct ADAPTER *prAdapter); +void halHifSwInfoUnInit(IN struct GLUE_INFO *prGlueInfo); +void halRxProcessMsduReport(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb); +uint32_t halTxGetPageCount(IN struct ADAPTER *prAdapter, + IN uint32_t u4FrameLength, IN u_int8_t fgIncludeDesc); +uint32_t halDumpHifStatus(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, IN uint32_t u4Max); +u_int8_t halIsPendingRx(IN struct ADAPTER *prAdapter); +uint32_t halGetValidCoalescingBufSize(IN struct ADAPTER *prAdapter); +uint32_t halAllocateIOBuffer(IN struct ADAPTER *prAdapter); +uint32_t halReleaseIOBuffer(IN struct ADAPTER *prAdapter); +void halDeAggRxPktWorker(struct work_struct *work); +void halRxTasklet(unsigned long data); +void halTxCompleteTasklet(unsigned long data); +void halPrintHifDbgInfo(IN struct ADAPTER *prAdapter); +u_int8_t halIsTxResourceControlEn(IN struct ADAPTER *prAdapter); +void halTxResourceResetHwTQCounter(IN struct ADAPTER *prAdapter); +uint32_t halGetHifTxPageSize(IN struct ADAPTER *prAdapter); +void halTxReturnFreeResource(IN struct ADAPTER *prAdapter, + IN uint16_t *au2TxDoneCnt); +void halTxGetFreeResource(IN struct ADAPTER *prAdapter, + IN uint16_t *au2TxDoneCnt, IN uint16_t *au2TxRlsCnt); +void halRestoreTxResource(IN struct ADAPTER *prAdapter); +void halRestoreTxResource_v1(IN struct ADAPTER *prAdapter); +void halUpdateTxDonePendingCount_v1(IN struct ADAPTER *prAdapter, + IN u_int8_t isIncr, IN uint8_t ucTc, IN uint16_t u2Cnt); +void halUpdateTxDonePendingCount(IN struct ADAPTER *prAdapter, + IN u_int8_t isIncr, IN uint8_t ucTc, IN uint32_t u4Len); +void halTxReturnFreeResource_v1(IN struct ADAPTER *prAdapter, + IN uint16_t *au2TxDoneCnt); +uint8_t halTxRingDataSelect(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); +void halUpdateTxMaxQuota(IN struct ADAPTER *prAdapter); + +#if defined(_HIF_USB) +void halSerSyncTimerHandler(IN struct ADAPTER *prAdapter); +#endif /* defined(_HIF_USB) */ +bool halIsHifStateReady(IN struct ADAPTER *prAdapter, uint8_t *pucState); +bool halIsHifStateLinkup(IN struct ADAPTER *prAdapter); +bool halIsHifStateSuspend(IN struct ADAPTER *prAdapter); + +#if defined(_HIF_PCIE) || defined(_HIF_AXI) +void halRxReceiveRFBs(IN struct ADAPTER *prAdapter, uint32_t u4Port, + uint8_t fgRxData); +u_int8_t halWpdmaWaitIdle(struct GLUE_INFO *prGlueInfo, + int32_t round, int32_t wait_us); +bool halWpdmaAllocRxRing(struct GLUE_INFO *prGlueInfo, uint32_t u4Num, + uint32_t u4Size, uint32_t u4DescSize, + uint32_t u4BufSize, bool fgAllocMem); +#endif /* defined(_HIF_PCIE) || defined(_HIF_AXI) */ + +#endif /* _HAL_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/hif_rx.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/hif_rx.h new file mode 100644 index 0000000000000..2df38d9cd267c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/hif_rx.h @@ -0,0 +1,156 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 + */ + + +#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 + ******************************************************************************* + */ + +/******************************************************************************* + * P U B 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 __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. + */ +static __KAL_INLINE__ void hifDataTypeCheck(void) +{ +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/hif_tx.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/hif_tx.h new file mode 100644 index 0000000000000..39336abd2ede1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/hif_tx.h @@ -0,0 +1,169 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/ + * MT6620_WIFI_DRIVER_V2_3/include/nic/hif_tx.h#1 + */ + + +#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 */ +/* Reserved field was not included */ +#define HIF_TX_BUFF_MAX_SIZE 1552 + +/* Maximum buffer count for individual HIF TCQ */ +#if 0 +#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 +#endif + +#define TX_HDR_SIZE sizeof(struct HIF_TX_HEADER) + +/* !< 2048 Bytes CMD payload buffer */ +#define CMD_PKT_SIZE_FOR_IMAGE 2048 + +/*! NIC_HIF_TX_HEADER_T (for short-header format) */ +/* DW 0, Byte 0,1 */ +#define HIF_TX_HDR_TX_BYTE_COUNT_MASK BITS(0, 15) + +/* DW 0, Byte 2 */ +#define HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK BITS(0, 6) +#define HIF_TX_HDR_IP_CSUM BIT(7) + +/* DW 0, Byte 3 */ +#define HIF_TX_HDR_TCP_CSUM BIT(0) +#define HIF_TX_HDR_QUEUE_IDX_MASK BITS(3, 6) +#define HIF_TX_HDR_QUEUE_IDX_OFFSET 3 +#define HIF_TX_HDR_PORT_IDX_MASK BIT(7) +#define HIF_TX_HDR_PORT_IDX_OFFSET 7 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +struct HIF_HW_TX_HEADER { + uint16_t u2TxByteCount; + uint8_t ucEtherTypeOffset; + uint8_t ucCSflags; + uint8_t aucBuffer[0]; +}; + +struct HIF_TX_HEADER { + uint16_t u2TxByteCount_UserPriority; + uint8_t ucEtherTypeOffset; + uint8_t ucResource_PktType_CSflags; + uint8_t ucWlanHeaderLength; + uint8_t ucPktFormtId_Flags; + uint16_t u2LLH; /* for BOW */ + uint16_t u2SeqNo; /* for BOW */ + uint8_t ucStaRecIdx; + uint8_t ucForwardingType_SessionID_Reserved; + uint8_t ucPacketSeqNo; + uint8_t ucAck_BIP_BasicRate; + uint8_t aucReserved[2]; +}; + +enum ENUM_HIF_OOB_CTRL_PKT_TYPE { + HIF_OOB_CTRL_PKT_TYPE_LOOPBACK = 1, + HIF_OOB_CTRL_PKT_TYP_NUM +}; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +#define TFCB_FRAME_PAD_TO_DW(u2Length) ALIGN_4(u2Length) + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +/* Kevin: we don't have to call following function to inspect the data + * structure. It will check automatically while at compile time. + */ +static __KAL_INLINE__ void hif_txDataTypeCheck(void); + +static __KAL_INLINE__ void hif_txDataTypeCheck(void) +{ + DATA_STRUCT_INSPECTING_ASSERT(sizeof(struct HIF_TX_HEADER) == 16); +} + +#endif /*_HIF_TX_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/mac.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/mac.h new file mode 100644 index 0000000000000..e924284d68b23 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/mac.h @@ -0,0 +1,3684 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "mac.h" + * \brief Brief description. + * + * Detail description. + */ + + +#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_OUI_LEN (3) + +#define MAC_ADDR_LOCAL_ADMIN BIT(1) + +#define ETH_P_IPV4 0x0800 +#define ETH_P_ARP 0x0806 +#define ETH_P_IPX 0x8137 /* Novell IPX */ +/* AppleTalk Address Resolution Protocol (AARP) */ +#define ETH_P_AARP 0x80F3 +#define ETH_P_IPV6 0x86DD +#define ETH_P_VLAN 0x8100 + +#define IP_PRO_ICMP 0x01 +#define IP_PRO_UDP 0x11 +#define IP_PRO_TCP 0x06 + +#define UDP_PORT_DHCPS 0x43 +#define UDP_PORT_DHCPC 0x44 +#define UDP_PORT_DNS 0x35 + +#define ETH_P_1X 0x888E +#define ETH_P_PRE_1X 0x88C7 +#if CFG_SUPPORT_WAPI +#define ETH_WPI_1X 0x88B4 +#endif +#define ETH_EAPOL_KEY 3 + +#define ETH_PRO_TDLS 0x890d + +/* 802.3 Frame If Ether Type/Len <= 1500 */ +#define ETH_802_3_MAX_LEN 1500 + +/* IP Header definition */ +#define IP_VERSION_MASK BITS(4, 7) +#define IP_VERSION_OFFSET 4 +#define IP_VERSION_4 4 +#define IP_VERSION_6 6 + +#define IP_PRO_ICMP 0x01 +#define IP_PRO_UDP 0x11 +#define IP_PRO_TCP 0x06 + +#define UDP_PORT_DHCPS 0x43 +#define UDP_PORT_DHCPC 0x44 +#define UDP_PORT_DNS 0x35 + +/* IPv4 Header definition */ +#define IPV4_HDR_TOS_OFFSET 1 +#define IPV4_HDR_TOS_PREC_MASK BITS(5, 7) +#define IPV4_HDR_TOS_PREC_OFFSET 5 +#define IPV4_HDR_IP_IDENTIFICATION_OFFSET 4 +#define IPV4_HDR_IP_PROTOCOL_OFFSET 9 +#define IPV4_HDR_IP_CSUM_OFFSET 10 +#define IPV4_HDR_IP_SRC_ADDR_OFFSET 12 +#define IPV4_HDR_IP_DST_ADDR_OFFSET 16 + +#define IPV4_HDR_LEN 20 +#define IPV4_ADDR_LEN 4 + +#define IPV6_HDR_IP_PROTOCOL_OFFSET 6 +#define IPV6_HDR_IP_SRC_ADDR_OFFSET 8 +#define IPV6_HDR_IP_DST_ADDR_OFFSET 24 +#define IPV6_HDR_IP_DST_ADDR_MAC_HIGH_OFFSET 32 +#define IPV6_HDR_IP_DST_ADDR_MAC_LOW_OFFSET 37 +#define IPV6_PROTOCOL_ICMPV6 0x3A + +#define IPV6_HDR_TC_PREC_OFFSET 1 +#define IPV6_HDR_TC_PREC_MASK BITS(1, 3) +#define IPV6_HDR_PROTOCOL_OFFSET 6 +#define IPV6_HDR_LEN 40 + +#define IPV6_ADDR_LEN 16 + +#define ICMPV6_TYPE_OFFSET 0 +#define ICMPV6_FLAG_OFFSET 4 +#define ICMPV6_TARGET_ADDR_OFFSET 8 +#define ICMPV6_TARGET_LL_ADDR_TYPE_OFFSET 24 +#define ICMPV6_TARGET_LL_ADDR_LEN_OFFSET 25 +#define ICMPV6_TARGET_LL_ADDR_TA_OFFSET 26 + +#define ICMPV6_FLAG_ROUTER_BIT BIT(7) +#define ICMPV6_FLAG_SOLICITED_BIT BIT(6) +#define ICMPV6_FLAG_OVERWRITE_BIT BIT(5) +#define ICMPV6_TYPE_NEIGHBOR_SOLICITATION 0x87 +#define ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT 0x88 + +#define TCP_HDR_TCP_CSUM_OFFSET 16 + +#define UDP_HDR_LEN 8 + +#define UDP_HDR_SRC_PORT_OFFSET 0 +#define UDP_HDR_DST_PORT_OFFSET 2 +#define UDP_HDR_UDP_CSUM_OFFSET 6 + +#define IP_PORT_BOOTP_SERVER 67 +#define IP_PORT_BOOTP_CLIENT 68 + +#define DHCP_MAGIC_NUMBER 0x63825363 + +#define ARP_OPERATION_OFFSET 6 +#define ARP_SENDER_MAC_OFFSET 8 +#define ARP_SENDER_IP_OFFSET 14 +#define ARP_TARGET_MAC_OFFSET 18 +#define ARP_TARGET_IP_OFFSET 24 +#define ARP_OPERATION_REQUEST 0x0001 +#define ARP_OPERATION_RESPONSE 0x0002 + +#define ARP_PRO_REQ 1 +#define ARP_PRO_RSP 2 + +#define TDLS_ACTION_CODE_OFFSET 2 + +/* LLC(3) + SNAP(3) + EtherType(2) */ +#define LLC_LEN 8 + +#define NULL_MAC_ADDR {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} +#define BC_MAC_ADDR {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} + +#if 1 + +#define ETH_HLEN 14 +#define ETH_TYPE_LEN_OFFSET 12 + +#define IPVERSION 4 +#define IP_HEADER_LEN 20 +#define IP_PROTO_HLEN 9 + +#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 + +#define LOOK_AHEAD_LEN \ + (ETH_HLEN + IP_HEADER_LEN + SOURCE_PORT_LEN) + +#endif + +/* 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 + +#define ETHER_TYPE_LEN_OFFSET 12 + +/* 802.1Q (VLAN) */ +#define ETH_802_1Q_HEADER_LEN 4 + +/* 802.2 LLC/SNAP */ +#define ETH_LLC_OFFSET (ETHER_HEADER_LEN) +#define ETH_LLC_LEN 3 +#define ETH_LLC_DSAP_SNAP 0xAA +#define ETH_LLC_SSAP_SNAP 0xAA +#define ETH_LLC_CONTROL_UNNUMBERED_INFORMATION 0x03 +#define ETH_LLC \ + {ETH_LLC_DSAP_SNAP, ETH_LLC_SSAP_SNAP, \ + ETH_LLC_CONTROL_UNNUMBERED_INFORMATION} + +/* Bluetooth SNAP */ +#define ETH_SNAP_OFFSET (ETHER_HEADER_LEN + ETH_LLC_LEN) +#define ETH_SNAP_LEN 5 +#define ETH_SNAP_OUI_LEN 3 +#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 ETH_SNAP_BT_SIG_OUI \ + {ETH_SNAP_BT_SIG_OUI_0, ETH_SNAP_BT_SIG_OUI_1, ETH_SNAP_BT_SIG_OUI_2} + +#define BOW_PROTOCOL_ID_SECURITY_FRAME 0x0003 + +/* IEEE 802.11 WLAN Frame Field Size, in byte */ +/* Address 4 excluded */ +#define WLAN_MAC_HEADER_LEN 24 +/* Address 4 included */ +#define WLAN_MAC_HEADER_A4_LEN 30 +/* QoS Control included */ +#define WLAN_MAC_HEADER_QOS_LEN 26 +/* QoS Control and HTC included */ +#define WLAN_MAC_HEADER_QOS_HTC_LEN 30 +/* Address 4 and QoS Control included */ +#define WLAN_MAC_HEADER_A4_QOS_LEN 32 +/* Address 4, QoS Control and HTC included */ +#define WLAN_MAC_HEADER_A4_QOS_HTC_LEN 36 +/* Address 4 excluded */ +#define WLAN_MAC_MGMT_HEADER_LEN 24 +/* HTC included */ +#define WLAN_MAC_MGMT_HEADER_HTC_LEN 28 + +#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 */ +/* In unit of AP's DTIM interval, */ +#define DEFAULT_LISTEN_INTERVAL_BY_DTIM_PERIOD 2 +#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 */ + +/* BSS Selector - Clause 22. HT PHY */ +#define RATE_VHT_PHY 126 +/* BSS Selector - Clause 20. HT PHY */ +#define RATE_HT_PHY 127 +/* mask bits for the rate */ +#define RATE_MASK BITS(0, 6) +/* mask bit for the rate belonging to the BSSBasicRateSet */ +#define RATE_BASIC_BIT BIT(7) + +/* 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 */ +/* Accept Class 1 frames */ +#define STA_STATE_1 0 +/* Accept Class 1 & 2 frames */ +#define STA_STATE_2 1 +/* Accept Class 1,2 & 3 frames */ +#define STA_STATE_3 2 + +/* 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) */ +/* Long Slot Time */ +#define SLOT_TIME_LONG 20 +/* Short Slot Time */ +#define SLOT_TIME_SHORT 9 + +/* 802.11b aSlotTime */ +#define SLOT_TIME_HR_DSSS SLOT_TIME_LONG +/* 802.11a aSlotTime(20M Spacing) */ +#define SLOT_TIME_OFDM SLOT_TIME_SHORT +/* 802.11a aSlotTime(10M Spacing) */ +#define SLOT_TIME_OFDM_10M_SPACING 13 +/* 802.11g aSlotTime(Long) */ +#define SLOT_TIME_ERP_LONG SLOT_TIME_LONG +/* 802.11g aSlotTime(Short) */ +#define SLOT_TIME_ERP_SHORT SLOT_TIME_SHORT + +/* 17.4.4/18.3.3/19.8.4 Contention Window (aCWmin & aCWmax) */ +/* 802.11a aCWmin */ +#define CWMIN_OFDM 15 +/* 802.11a aCWmax */ +#define CWMAX_OFDM 1023 + +/* 802.11b aCWmin */ +#define CWMIN_HR_DSSS 31 +/* 802.11b aCWmax */ +#define CWMAX_HR_DSSS 1023 + +/* 802.11g aCWmin(0) - for only have 1/2/5/11Mbps Rates */ +#define CWMIN_ERP_0 31 +/* 802.11g aCWmin(1) */ +#define CWMIN_ERP_1 15 +/* 802.11g aCWmax */ +#define CWMAX_ERP 1023 + +/* 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 + +/* 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 + +/* 802.11 define 512 */ +/* MT5921 only aceept N <= 4095 */ +#define DOT11_TRANSMIT_MSDU_LIFETIME_TU_DEFAULT 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_HE_TRIGGER (MAC_FRAME_TYPE_CTRL | 0x0020) +#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) + +/* According to 6.2.1.1.2 + * FRAG_NUM won't equal to 15 + */ +#define INVALID_SEQ_CTRL_NUM 0x000F + +/* 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 + +#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 */ +#define AUTH_ALGORITHM_NUM_SAE 3 /* WPA3 - SAE */ + +/* 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_RADIO_MEASUREMENT 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 + +/* Reseved */ +#define REASON_CODE_RESERVED 0 +/* Unspecified reason */ +#define REASON_CODE_UNSPECIFIED 1 +/* Previous auth no longer valid */ +#define REASON_CODE_PREV_AUTH_INVALID 2 +/* Deauth because sending STA is leaving BSS */ +#define REASON_CODE_DEAUTH_LEAVING_BSS 3 +/* Disassoc due to inactivity */ +#define REASON_CODE_DISASSOC_INACTIVITY 4 +/* Disassoc because AP is unable to handle all assoc STAs */ +#define REASON_CODE_DISASSOC_AP_OVERLOAD 5 +/* Class 2 frame rx from nonauth STA */ +#define REASON_CODE_CLASS_2_ERR 6 +/* Class 3 frame rx from nonassoc STA */ +#define REASON_CODE_CLASS_3_ERR 7 +/* Disassoc because sending STA is leaving BSS */ +#define REASON_CODE_DISASSOC_LEAVING_BSS 8 +/* STA requesting (re)assoc is not auth with responding STA */ +#define REASON_CODE_ASSOC_BEFORE_AUTH 9 +/* Disassoc because the info in Power Capability is unacceptable */ +#define REASON_CODE_DISASSOC_PWR_CAP_UNACCEPTABLE 10 +/* Disassoc because the info in Supported Channels is unacceptable */ +#define REASON_CODE_DISASSOC_SUP_CHS_UNACCEPTABLE 11 +/* Invalid information element */ +#define REASON_CODE_INVALID_INFO_ELEM 13 +/* MIC failure */ +#define REASON_CODE_MIC_FAILURE 14 +/* 4-way handshake timeout */ +#define REASON_CODE_4_WAY_HANDSHAKE_TIMEOUT 15 +/* Group key update timeout */ +#define REASON_CODE_GROUP_KEY_UPDATE_TIMEOUT 16 +/* Info element in 4-way handshake different from */ +/* (Re-)associate request/Probe response/Beacon */ +#define REASON_CODE_DIFFERENT_INFO_ELEM 17 +/* Multicast Cipher is not valid */ +#define REASON_CODE_MULTICAST_CIPHER_NOT_VALID 18 +/* Unicast Cipher is not valid */ +#define REASON_CODE_UNICAST_CIPHER_NOT_VALID 19 +/* AKMP is not valid */ +#define REASON_CODE_AKMP_NOT_VALID 20 +/* Unsupported RSNE version */ +#define REASON_CODE_UNSUPPORTED_RSNE_VERSION 21 +/* Invalid RSNE Capabilities */ +#define REASON_CODE_INVALID_RSNE_CAPABILITIES 22 +/* IEEE 802.1X Authentication failed */ +#define REASON_CODE_IEEE_802_1X_AUTH_FAILED 23 +/* Cipher suite rejected because of the security policy */ +#define REASON_CODE_CIPHER_REJECT_SEC_POLICY 24 +/* Disassoc for unspecified, QoS-related reason */ +#define REASON_CODE_DISASSOC_UNSPECIFIED_QOS 32 +/* Disassoc because QAP lacks sufficient bandwidth for this QSTA */ +#define REASON_CODE_DISASSOC_LACK_OF_BANDWIDTH 33 +/* Disassoc because of too many ACKs lost for AP transmissions */ +/* and/or poor channel conditions */ +#define REASON_CODE_DISASSOC_ACK_LOST_POOR_CHANNEL 34 +/* Disassoc because QSTA is transmitting outside the limits of its TXOPs */ +#define REASON_CODE_DISASSOC_TX_OUTSIDE_TXOP_LIMIT 35 +/* QSTA is leaving the QBSS or resetting */ +#define REASON_CODE_PEER_WHILE_LEAVING 36 +/* Peer does not want to use this mechanism */ +#define REASON_CODE_PEER_REFUSE_DLP 37 +/* Frames received but a setup is reqired */ +#define REASON_CODE_PEER_SETUP_REQUIRED 38 +/* Time out */ +#define REASON_CODE_PEER_TIME_OUT 39 +/* Peer does not support the requested cipher suite */ +#define REASON_CODE_PEER_CIPHER_UNSUPPORTED 45 +/* for beacon timeout, defined by mediatek */ +#define REASON_CODE_BEACON_TIMEOUT 100 +/* 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 +/* Reserved - Used by TX Auth */ +#define STATUS_CODE_RESERVED 0 +/* Successful */ +#define STATUS_CODE_SUCCESSFUL 0 +/* Unspecified failure */ +#define STATUS_CODE_UNSPECIFIED_FAILURE 1 +/* Cannot support all requested cap in the Cap Info field */ +#define STATUS_CODE_CAP_NOT_SUPPORTED 10 +/* Reassoc denied due to inability to confirm that assoc exists */ +#define STATUS_CODE_REASSOC_DENIED_WITHOUT_ASSOC 11 +/* Assoc denied due to reason outside the scope of this std. */ +#define STATUS_CODE_ASSOC_DENIED_OUTSIDE_STANDARD 12 +/* Responding STA does not support the specified auth algorithm */ +#define STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED 13 +/* Rx an auth frame with auth transaction seq num out of expected seq */ +#define STATUS_CODE_AUTH_OUT_OF_SEQ 14 +/* Auth rejected because of challenge failure */ +#define STATUS_CODE_AUTH_REJECTED_CHAL_FAIL 15 +/* Auth rejected due to timeout waiting for next frame in sequence */ +#define STATUS_CODE_AUTH_REJECTED_TIMEOUT 16 +/* Assoc denied because AP is unable to handle additional assoc STAs */ +#define STATUS_CODE_ASSOC_DENIED_AP_OVERLOAD 17 +/* Assoc denied due to requesting STA not supporting all of basic rates */ +#define STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED 18 +/* Assoc denied due to requesting STA not supporting short preamble */ +#define STATUS_CODE_ASSOC_DENIED_NO_SHORT_PREAMBLE 19 +/* Assoc denied due to requesting STA not supporting PBCC */ +#define STATUS_CODE_ASSOC_DENIED_NO_PBCC 20 +/* Assoc denied due to requesting STA not supporting channel agility */ +#define STATUS_CODE_ASSOC_DENIED_NO_CH_AGILITY 21 +/* Assoc rejected because Spectrum Mgt capability is required */ +#define STATUS_CODE_ASSOC_REJECTED_NO_SPEC_MGT 22 +/* Assoc rejected because the info in Power Capability is unacceptable */ +#define STATUS_CODE_ASSOC_REJECTED_PWR_CAP 23 +/* Assoc rejected because the info in Supported Channels is unacceptable */ +#define STATUS_CODE_ASSOC_REJECTED_SUP_CHS 24 +/* Assoc denied due to requesting STA not supporting short slot time */ +#define STATUS_CODE_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25 +/* Assoc denied due to requesting STA not supporting DSSS-OFDM */ +#define STATUS_CODE_ASSOC_DENIED_NO_DSSS_OFDM 26 +#if CFG_SUPPORT_802_11W +/* IEEE 802.11w, Assoc denied due to the SA query */ +#define STATUS_CODE_ASSOC_REJECTED_TEMPORARILY 30 +/* IEEE 802.11w, Assoc denied due to the MFP select policy */ +#define STATUS_CODE_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31 +#endif +/* Unspecified, QoS-related failure */ +#define STATUS_CODE_UNSPECIFIED_QOS_FAILURE 32 +/* Assoc denied due to insufficient bandwidth to handle another QSTA */ +#define STATUS_CODE_ASSOC_DENIED_BANDWIDTH 33 +/* Assoc denied due to excessive frame loss + * rates and/or poor channel conditions + */ +#define STATUS_CODE_ASSOC_DENIED_POOR_CHANNEL 34 +/* Assoc denied due to requesting STA not supporting QoS facility */ +#define STATUS_CODE_ASSOC_DENIED_NO_QOS_FACILITY 35 +/* Request has been declined */ +#define STATUS_CODE_REQ_DECLINED 37 +/* Request has not been successful as one + * or more parameters have invalid values + */ +#define STATUS_CODE_REQ_INVALID_PARAMETER_VALUE 38 +/* TS not created because request cannot be honored. */ +/* Suggested TSPEC provided. */ +#define STATUS_CODE_REQ_NOT_HONORED_TSPEC 39 +/* Invalid information element */ +#define STATUS_CODE_INVALID_INFO_ELEMENT 40 +/* Invalid group cipher */ +#define STATUS_CODE_INVALID_GROUP_CIPHER 41 +/* Invalid pairwise cipher */ +#define STATUS_CODE_INVALID_PAIRWISE_CIPHER 42 +/* Invalid AKMP */ +#define STATUS_CODE_INVALID_AKMP 43 +/* Unsupported RSN information element version */ +#define STATUS_CODE_UNSUPPORTED_RSN_IE_VERSION 44 +/* Invalid RSN information element capabilities */ +#define STATUS_CODE_INVALID_RSN_IE_CAP 45 +/* Cipher suite rejected because of security policy */ +#define STATUS_CODE_CIPHER_SUITE_REJECTED 46 +/* TS not created because request cannot be honored. */ +/* Attempt to create a TS later. */ +#define STATUS_CODE_REQ_NOT_HONORED_TS_DELAY 47 +/* Direct Link is not allowed in the BSS by policy */ +#define STATUS_CODE_DIRECT_LINK_NOT_ALLOWED 48 +/* Destination STA is not present within this QBSS */ +#define STATUS_CODE_DESTINATION_STA_NOT_PRESENT 49 +/* Destination STA is not a QSTA */ +#define STATUS_CODE_DESTINATION_STA_NOT_QSTA 50 +/* Association denied because the ListenInterval is too large */ +#define STATUS_CODE_ASSOC_DENIED_LARGE_LIS_INTERVAL 51 +/* Invalid pairwise master key identifier (PMKID) */ +#define STATUS_INVALID_PMKID 53 + +/* proprietary definition of reserved field of Status Code */ +/* Join failure */ +#define STATUS_CODE_JOIN_FAILURE 0xFFF0 +/* Join timeout */ +#define STATUS_CODE_JOIN_TIMEOUT 0xFFF1 +/* Authentication timeout */ +#define STATUS_CODE_AUTH_TIMEOUT 0xFFF2 +/* (Re)Association timeout */ +#define STATUS_CODE_ASSOC_TIMEOUT 0xFFF3 +/* CCX CCKM reassociation failure */ +#define STATUS_CODE_CCX_CCKM_REASSOC_FAILURE 0xFFF4 + +/* 7.3.1.10 Timestamp field */ +#define TIMESTAMP_FIELD_LEN 8 + +/* 80211-2016 Table 9-47 Category of Action field */ +#define CATEGORY_SPEC_MGT 0 +/* QoS action */ +#define CATEGORY_QOS_ACTION 1 +/* Direct Link Protocol (DLP) action */ +#define CATEGORY_DLS_ACTION 2 +/* Block ack action */ +#define CATEGORY_BLOCK_ACK_ACTION 3 +/* Public action */ +#define CATEGORY_PUBLIC_ACTION 4 +/* Radio measurement action */ +#define CATEGORY_RM_ACTION 5 +/* Fast BSS Transition */ +#define CATEGORY_FT_ACTION 6 +/* HT */ +#define CATEGORY_HT_ACTION 7 +/* SA Qurery */ +#define CATEGORY_SA_QUERY_ACTION 8 +/* Protected Dual of Public Action */ +#define CATEGORY_PROTECTED_DUAL_OF_PUBLIC_ACTION 9 +/* 802.11v Wireless Network Management */ +#define CATEGORY_WNM_ACTION 10 +/* 802.11v Unprotected Wireless Network Management */ +#define CATEGORY_UNPROTECTED_WNM_ACTION 11 +/* TDLS */ +#define CATEGORY_TDLS_ACTION 12 +/* Mesh */ +#define CATEGORY_MESH_ACTION 13 +/* Multihop */ +#define CATEGORY_MULTIHOP_ACTION 14 +/* Self-protected */ +#define CATEGORY_SELF_PROTECTED_ACTION 15 +/* Directional Multi-Gigabit */ +#define CATEGORY_DMG_ACTION 16 +/* WME management notification */ +#define CATEGORY_WME_MGT_NOTIFICATION 17 +/* Fast Session Transfer */ +#define CATEGORY_FST_ACTION 18 +/* Robust AV Streaming */ +#define CATEGORY_ROBUST_AV_STREAMING_ACTION 19 +/* Unprotected DMG */ +#define CATEGORY_UNPROTECTED_DMG_ACTION 20 +/* VHT action */ +#define CATEGORY_VHT_ACTION 21 +#if (CFG_SUPPORT_TWT == 1) +#define CATEGORY_S1G_ACTION 22 /* S1G action */ +#endif +/* Vendor-specific Protected */ +#define CATEGORY_VENDOR_SPECIFIC_PROTECTED_ACTION 126 +/* Vendor-specific */ +#define CATEGORY_VENDOR_SPECIFIC_ACTION 127 + +/* 7.3.1.14 Block Ack Parameter Set field */ +#define BA_PARAM_SET_ACK_POLICY_MASK BIT(1) +#define BA_PARAM_SET_ACK_POLICY_MASK_OFFSET 1 +#define BA_PARAM_SET_TID_MASK BITS(2, 5) +#define BA_PARAM_SET_TID_MASK_OFFSET 2 +#define BA_PARAM_SET_BUFFER_SIZE_MASK BITS(6, 15) +#define BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET 6 + +#define BA_PARAM_SET_ACK_POLICY_IMMEDIATE_BA 1 +#define BA_PARAM_SET_ACK_POLICY_DELAYED_BA 0 + +/* 3 Management frame body components (II): Information Elements. */ +/* 7.3.2 Element IDs of information elements */ +#define ELEM_HDR_LEN 2 + +#define ELEM_ID_SSID \ + 0 /* SSID */ +#define ELEM_ID_SUP_RATES \ + 1 /* Supported rates */ +#define ELEM_ID_FH_PARAM_SET \ + 2 /* FH parameter set */ +#define ELEM_ID_DS_PARAM_SET \ + 3 /* DS parameter set */ +#define ELEM_ID_CF_PARAM_SET \ + 4 /* CF parameter set */ +#define ELEM_ID_TIM \ + 5 /* TIM */ +#define ELEM_ID_IBSS_PARAM_SET \ + 6 /* IBSS parameter set */ +#define ELEM_ID_COUNTRY_INFO \ + 7 /* Country information */ +#define ELEM_ID_HOPPING_PATTERN_PARAM \ + 8 /* Hopping pattern parameters */ +#define ELEM_ID_HOPPING_PATTERN_TABLE \ + 9 /* Hopping pattern table */ +#define ELEM_ID_REQUEST \ + 10 /* Request */ +#define ELEM_ID_BSS_LOAD \ + 11 /* BSS load */ +#define ELEM_ID_EDCA_PARAM_SET \ + 12 /* EDCA parameter set */ +#define ELEM_ID_TSPEC \ + 13 /* Traffic specification (TSPEC) */ +#define ELEM_ID_TCLAS \ + 14 /* Traffic classification (TCLAS) */ +#define ELEM_ID_SCHEDULE \ + 15 /* Schedule */ +#define ELEM_ID_CHALLENGE_TEXT \ + 16 /* Challenge text */ + +#define ELEM_ID_PWR_CONSTRAINT \ + 32 /* Power constraint */ +#define ELEM_ID_PWR_CAP \ + 33 /* Power capability */ +#define ELEM_ID_TPC_REQ \ + 34 /* TPC request */ +#define ELEM_ID_TPC_REPORT \ + 35 /* TPC report */ +#define ELEM_ID_SUP_CHS \ + 36 /* Supported channels */ +#define ELEM_ID_CH_SW_ANNOUNCEMENT \ + 37 /* Channel switch announcement */ +#define ELEM_ID_MEASUREMENT_REQ \ + 38 /* Measurement request */ +#define ELEM_ID_MEASUREMENT_REPORT \ + 39 /* Measurement report */ +#define ELEM_ID_QUIET \ + 40 /* Quiet */ +#define ELEM_ID_IBSS_DFS \ + 41 /* IBSS DFS */ +#define ELEM_ID_ERP_INFO \ + 42 /* ERP information */ +#define ELEM_ID_TS_DELAY \ + 43 /* TS delay */ +#define ELEM_ID_TCLAS_PROCESSING \ + 44 /* TCLAS processing */ +#define ELEM_ID_HT_CAP \ + 45 /* HT Capabilities subelement */ +#define ELEM_ID_QOS_CAP \ + 46 /* QoS capability */ +#define ELEM_ID_RSN \ + 48 /* RSN IE */ +#define ELEM_ID_EXTENDED_SUP_RATES \ + 50 /* Extended supported rates */ +#define ELEM_ID_AP_CHANNEL_REPORT \ + 51 /* AP Channel Report Element */ +#define ELEM_ID_NEIGHBOR_REPORT \ + 52 /* Neighbor Report */ +#define ELEM_ID_MOBILITY_DOMAIN \ + 54 /* Mobility Domain for 802.11R */ +#define ELEM_ID_FAST_TRANSITION \ + 55 /* Fast Bss Transition for 802.11 R */ +#if CFG_SUPPORT_802_11W +#define ELEM_ID_TIMEOUT_INTERVAL \ + 56 /* 802.11w SA Timeout interval */ +#endif +#define ELEM_ID_RESOURCE_INFO_CONTAINER \ + 57 /* Resource Information Container for 802.11 R */ +#define ELEM_ID_SUP_OPERATING_CLASS \ + 59 /* Supported Operating Classes */ + +#define ELEM_ID_HT_OP \ + 61 /* HT Operation */ +#define ELEM_ID_SCO \ + 62 /* Secondary Channel Offset */ +#define ELEM_ID_RRM_ENABLED_CAP \ + 70 /* Radio Resource Management Enabled Capabilities */ +#define ELEM_ID_MBSSID \ + 71 /* Multiple BSSID element */ +#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_MBSSID_INDEX \ + 85 /* Multiple BSSID-Index element */ +#define ELEM_ID_EXTENDED_CAP \ + 127 /* Extended capabilities */ + +#define ELEM_ID_INTERWORKING \ + 107 /* Interworking with External Network */ +#define ELEM_ID_ADVERTISEMENT_PROTOCOL \ + 108 /* Advertisement Protocol */ +#define ELEM_ID_QOS_MAP_SET \ + 110 /* QoS Map Set */ +#define ELEM_ID_ROAMING_CONSORTIUM \ + 111 /* Roaming Consortium */ +#define ELEM_ID_EXTENDED_CAP \ + 127 /* Extended capabilities */ + +#if (CFG_SUPPORT_TWT == 1) +#define ELEM_ID_TWT \ + 216 /* Target Wake Time (TWT) @11ah/11ax */ +#endif + +#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_WSC \ + ELEM_ID_VENDOR /* WSC IE */ + +#define ELEM_ID_VHT_CAP \ + 191 /* VHT Capabilities subelement */ +#define ELEM_ID_VHT_OP \ + 192 /* VHT Operation information */ +#define ELEM_ID_WIDE_BAND_CHANNEL_SWITCH \ + 194 /*Wide Bandwidth Channel Switch */ +#define ELEM_ID_OP_MODE \ + 199 /* Operation Mode Notification */ +#define ELEM_ID_RESERVED \ + 255 /* Reserved */ + +#if CFG_SUPPORT_MBO +/* MBO v0.0_r19, 4.2: MBO Attributes */ +/* Table 4-5: MBO Attributes */ +/* OCE v0.0.10, Table 4-3: OCE Attributes */ +enum MBO_ATTR_ID { + MBO_ATTR_ID_AP_CAPA_IND = 1, + MBO_ATTR_ID_NON_PREF_CHAN_REPORT = 2, + MBO_ATTR_ID_CELL_DATA_CAPA = 3, + MBO_ATTR_ID_ASSOC_DISALLOW = 4, + MBO_ATTR_ID_CELL_DATA_PREF = 5, + MBO_ATTR_ID_TRANSITION_REASON = 6, + MBO_ATTR_ID_TRANSITION_REJECT_REASON = 7, + MBO_ATTR_ID_ASSOC_RETRY_DELAY = 8, + OCE_ATTR_ID_CAPA_IND = 101, + OCE_ATTR_ID_RSSI_BASED_ASSOC_REJECT = 102, + OCE_ATTR_ID_REDUCED_WAN_METRICS = 103, + OCE_ATTR_ID_RNR_COMPLETENESS = 104, +}; +#endif + +/* 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 + +#define ELEM_MAX_LEN_SUP_RATES_IOT 16 + +/* 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 */ +/* NonERP_Present bit */ +#define ERP_INFO_NON_ERP_PRESENT BIT(0) +/* Use_Protection bit */ +#define ERP_INFO_USE_PROTECTION BIT(1) +/* Barker_Preamble_Mode bit */ +#define ERP_INFO_BARKER_PREAMBLE_MODE BIT(2) + +#define ELEM_MAX_LEN_SUPPORTED_CHANNELS (MAX_CHN_NUM * 2) + +/* 7.3.2.14 Extended Supported Rates */ +#define ELEM_MAX_LEN_EXTENDED_SUP_RATES 255 + +/* 7.3.2.16 Power Capability element */ +#define ELEM_MAX_LEN_POWER_CAP 2 + + +/* 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_TSM_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_TSM_REPORT 9 + +/* 7.3.2.37 Subelement IDs for Neighbor Report, Table 7-43b */ +#define ELEM_ID_NR_BSS_TRANSITION_CAND_PREF 3 +#define ELEM_ID_NR_BSS_TERMINATION_DURATION 4 + +/* + * IEEE Std 802.11-2016, Table 9-87 - Measurement Mode definitions for Beacon + * request + */ +enum BEACON_REPORT_MODE { + BEACON_REPORT_MODE_PASSIVE = 0, + BEACON_REPORT_MODE_ACTIVE = 1, + BEACON_REPORT_MODE_TABLE = 2, +}; + +/* IEEE Std 802.11-2016, Table 9-88 - Beacon Request subelement IDs + * IEEE P802.11-REVmd/D2.0, Table 9-106 - Optional subelement IDs for + * Beacon request + */ +#define BEACON_REQUEST_SUBELEM_SSID 0 +#define BEACON_REQUEST_SUBELEM_INFO 1 /* Beacon Reporting */ +#define BEACON_REQUEST_SUBELEM_DETAIL 2 /* Reporting Detail */ +#define BEACON_REQUEST_SUBELEM_REQUEST 10 +#define BEACON_REQUEST_SUBELEM_AP_CHANNEL 51 /* AP Channel Report */ +#define BEACON_REQUEST_SUBELEM_LAST_INDICATION 164 +#define BEACON_REQUEST_SUBELEM_VENDOR 221 + +/* + * IEEE Std 802.11-2016, Table 9-90 - Reporting Detail values + */ +enum BEACON_REPORT_DETAIL { + /* No fixed-length fields or elements */ + BEACON_REPORT_DETAIL_NONE = 0, + /* All fixed-length fields and any requested elements in the Request + * element if resent + */ + BEACON_REPORT_DETAIL_REQUESTED_ONLY = 1, + /* All fixed-length fields and elements (default, used when Reporting + * Detail subelement is not included in a Beacon request) + */ + BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS = 2, +}; + +/* IEEE Std 802.11-2016, Table 9-112 - Beacon report Subelement IDs + * IEEE P802.11-REVmd/D2.0, Table 9-130 - Optional subelement IDs for + * Beacon report + */ +#define BEACON_REPORT_SUBELEM_FRAME_BODY 1 +#define BEACON_REPORT_SUBELEM_FRAME_BODY_FRAGMENT_ID 2 +#define BEACON_REPORT_SUBELEM_LAST_INDICATION 164 +#define BEACON_REPORT_SUBELEM_VENDOR 221 + +/* IEEE P802.11-REVmd/D2.0, Table 9-232 - Data field format of the + * Reported Frame Body Fragment ID subelement + */ +#define REPORTED_FRAME_BODY_SUBELEM_LEN 4 +#define REPORTED_FRAME_BODY_MORE_FRAGMENTS BIT(7) + +/* IEEE P802.11-REVmd/D2.0, 9.4.2.21.7 - Beacon report */ +#define BEACON_REPORT_LAST_INDICATION_SUBELEM_LEN 3 + +/* IEEE Std 802.11-2016, Figure 9-192 - Measurement Report Mode field */ +#define MEASUREMENT_REPORT_MODE_ACCEPT 0 +#define MEASUREMENT_REPORT_MODE_REJECT_LATE BIT(0) +#define MEASUREMENT_REPORT_MODE_REJECT_INCAPABLE BIT(1) +#define MEASUREMENT_REPORT_MODE_REJECT_REFUSED BIT(2) + +/* 7.3.2.25 RSN information element */ +/* two pairwise, one AKM suite, one PMKID */ +#define ELEM_MAX_LEN_WPA 38 +/* two pairwise, one AKM suite, one PMKID */ +#define ELEM_MAX_LEN_RSN 42 +/* one pairwise, one AKM suite, one BKID */ +#define ELEM_MAX_LEN_WAPI 38 +/* one pairwise, one AKM suite, one BKID */ +#define ELEM_MAX_LEN_WSC 200 + +#if CFG_SUPPORT_802_11W +#define ELEM_WPA_CAP_MFPR BIT(6) +#define ELEM_WPA_CAP_MFPC BIT(7) +#endif + +/* 7.3.2.27 Extended Capabilities information element */ +#define ELEM_EXT_CAP_20_40_COEXIST_SUPPORT BIT(0) +#define ELEM_EXT_CAP_PSMP_CAP BIT(4) +#define ELEM_EXT_CAP_SERVICE_INTERVAL_GRANULARITY BIT(5) +#define ELEM_EXT_CAP_SCHEDULE_PSMP BIT(6) + +#define ELEM_EXT_CAP_BSS_TRANSITION_BIT 19 +#define ELEM_EXT_CAP_MBSSID_BIT 22 +#define ELEM_EXT_CAP_UTC_TSF_OFFSET_BIT 27 +#define ELEM_EXT_CAP_INTERWORKING_BIT 31 +#define ELEM_EXT_CAP_QOSMAPSET_BIT 32 +#define ELEM_EXT_CAP_WNM_NOTIFICATION_BIT 46 +#define ELEM_EXT_CAP_WNM_NOTIFICATION_BIT 46 +#define ELEM_EXT_CAP_OP_MODE_NOTIFICATION_BIT 62 +#if (CFG_SUPPORT_TWT == 1) +#define ELEM_EXT_CAP_TWT_REQUESTER_BIT 77 +#endif + +#define ELEM_MAX_LEN_EXT_CAP_11ABGNAC (8) + +#if (CFG_SUPPORT_802_11AX == 1) +#define ELEM_MAX_LEN_EXT_CAP (10) +#else +#define ELEM_MAX_LEN_EXT_CAP (8) +#endif + +/* 7.3.2.30 TSPEC element */ +/* WMM: 0 (Asynchronous TS of low-duty cycles) */ +#define TS_INFO_TRAFFIC_TYPE_MASK BIT(0) +#define TS_INFO_TID_OFFSET 1 +#define TS_INFO_TID_MASK BITS(1, 4) +#define TS_INFO_DIRECTION_OFFSET 5 +#define TS_INFO_DIRECTION_MASK BITS(5, 6) +#define TS_INFO_ACCESS_POLICY_OFFSET 7 +#define TS_INFO_ACCESS_POLICY_MASK BITS(7, 8) +#define TS_INFO_AGGREGATION_MASK BIT(9) /* WMM: 0 */ +#define TS_INFO_APSD_MASK BIT(10) +#define TS_INFO_UP_OFFSET 11 +#define TS_INFO_UP_MASK BITS(11, 13) +#define TS_INFO_ACK_POLICY_OFFSET 14 +#define TS_INFO_ACK_POLICY_MASK BITS(14, 15) +#define TS_INFO_SCHEDULE_MASK 16 + +/* 7.3.2.45 RRM Enabled Capbility element */ +#define ELEM_MAX_LEN_RRM_CAP 5 +#define RRM_CAP_INFO_LINK_MEASURE_BIT 0 +#define RRM_CAP_INFO_NEIGHBOR_REPORT_BIT 1 +#define RRM_CAP_INFO_REPEATED_MEASUREMENT 3 +#define RRM_CAP_INFO_BEACON_PASSIVE_MEASURE_BIT 4 +#define RRM_CAP_INFO_BEACON_ACTIVE_MEASURE_BIT 5 +#define RRM_CAP_INFO_BEACON_TABLE_BIT 6 +#define RRM_CAP_INFO_TSM_BIT 14 +#define RRM_CAP_INFO_RRM_BIT 17 + +/* 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_SM_POWER_SAVE_OFFSET 2 +#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 + +#define ELEM_MAX_LEN_VHT_CAP \ + (14 - ELEM_HDR_LEN) /* sizeof(IE_VHT_CAP_T)-2 */ +/* 8.4.2.161 VHT Operation element */ +#define ELEM_MAX_LEN_VHT_OP \ + (7 - ELEM_HDR_LEN) /* sizeof(IE_VHT_OP_T)-2 */ + +#define ELEM_MAX_LEN_VHT_OP_MODE_NOTIFICATION \ + (3 - ELEM_HDR_LEN) /* sizeof(IE_VHT_OP_MODE_T)-2 */ + +/*8.4.2.160.3 VHT Supported MCS Set field*/ + +/*8.4.2.160.2 VHT Capabilities Info field*/ +#define VHT_CAP_INFO_MAX_MPDU_LEN_3K 0 +#define VHT_CAP_INFO_MAX_MPDU_LEN_8K BIT(0) +#define VHT_CAP_INFO_MAX_MPDU_LEN_11K BIT(1) +#define VHT_CAP_INFO_MAX_MPDU_LEN_MASK BITS(0, 1) + +#define VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_SET_NONE 0 +#define VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_SET_160 BIT(2) +#define VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_SET_160_80P80 BIT(3) +#define VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_MASK BITS(2, 3) + +#define VHT_CAP_INFO_RX_LDPC BIT(4) +#define VHT_CAP_INFO_SHORT_GI_80 BIT(5) +#define VHT_CAP_INFO_SHORT_GI_160_80P80 BIT(6) +#define VHT_CAP_INFO_TX_STBC BIT(7) + +#define VHT_CAP_INFO_RX_STBC_NONE 0 +#define VHT_CAP_INFO_RX_STBC_MASK BITS(8, 10) +#define VHT_CAP_INFO_RX_STBC_OFFSET 8 +#define VHT_CAP_INFO_RX_STBC_ONE_STREAM BIT(8) +#define VHT_CAP_INFO_RX_STBC_TWO_STREAM BIT(9) +#define VHT_CAP_INFO_RX_STBC_THREE_STREAM BITS(8, 9) +#define VHT_CAP_INFO_RX_STBC_FOUR_STREAM BIT(10) + +#define VHT_CAP_INFO_SU_BEAMFORMER_CAPABLE BIT(11) +#define VHT_CAP_INFO_SU_BEAMFORMEE_CAPABLE BIT(12) + +/* VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF + * _BEAMFORMER_ANTENNAS_SUPPOERTED + */ +#define VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF_BEAMFORMER_ANTENNAS_SUP_OFF \ + 13 +#define VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF_BEAMFORMER_ANTENNAS_SUP \ + BITS(13, 15) +#define VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF_BEAMFORMER_ANTENNAS_2_SUP \ + BIT(13) +#define VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF_BEAMFORMER_ANTENNAS_3_SUP \ + BIT(14) +#define VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF_BEAMFORMER_ANTENNAS_4_SUP \ + BITS(13, 14) + +#define VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS_OFFSET 16 +#define VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS BITS(16, 18) +#define VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS_2_SUPPORTED BIT(16) +#define VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS_3_SUPPORTED BIT(17) +#define VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS_4_SUPPORTED BITS(16, 17) + +#define VHT_CAP_INFO_MU_BEAMFOMER_CAPABLE BIT(19) +#define VHT_CAP_INFO_MU_BEAMFOMEE_CAPABLE BIT(20) +#define VHT_CAP_INFO_VHT_TXOP_PS BIT(21) +#define VHT_CAP_INFO_HTC_VHT_CAPABLE BIT(22) + +#define VHT_CAP_INFO_MAX_AMPDU_LENGTH_OFFSET 23 + +#define VHT_CAP_INFO_VHT_LINK_ADAPTATION_CAPABLE_NOFEEDBACK 0 +#define VHT_CAP_INFO_VHT_LINK_ADAPTATION_CAPABLE_UNSOLICITED BITS(27) +#define VHT_CAP_INFO_VHT_LINK_ADAPTATION_CAPABLE_BOTH BITS(26, 27) + +#define VHT_CAP_INFO_RX_ANTENNA_PATTERN_CONSISTENCY BIT(28) +#define VHT_CAP_INFO_TX_ANTENNA_PATTERN_CONSISTENCY BIT(29) + +#define VHT_CAP_INFO_MCS_MAP_MCS7 0 +#define VHT_CAP_INFO_MCS_MAP_MCS8 BIT(0) +#define VHT_CAP_INFO_MCS_MAP_MCS9 BIT(1) +#define VHT_CAP_INFO_MCS_NOT_SUPPORTED BITS(0, 1) + +#define VHT_CAP_INFO_MCS_1SS_OFFSET 0 +#define VHT_CAP_INFO_MCS_2SS_OFFSET 2 +#define VHT_CAP_INFO_MCS_3SS_OFFSET 4 +#define VHT_CAP_INFO_MCS_4SS_OFFSET 6 +#define VHT_CAP_INFO_MCS_5SS_OFFSET 8 +#define VHT_CAP_INFO_MCS_6SS_OFFSET 10 +#define VHT_CAP_INFO_MCS_7SS_OFFSET 12 +#define VHT_CAP_INFO_MCS_8SS_OFFSET 14 + +#define VHT_CAP_INFO_MCS_1SS_MASK BITS(0, 1) +#define VHT_CAP_INFO_MCS_2SS_MASK BITS(2, 3) +#define VHT_CAP_INFO_MCS_3SS_MASK BITS(4, 5) +#define VHT_CAP_INFO_MCS_4SS_MASK BITS(6, 7) +#define VHT_CAP_INFO_MCS_5SS_MASK BITS(8, 9) +#define VHT_CAP_INFO_MCS_6SS_MASK BITS(10, 11) +#define VHT_CAP_INFO_MCS_7SS_MASK BITS(12, 13) +#define VHT_CAP_INFO_MCS_8SS_MASK BITS(14, 15) + +#define VHT_OP_CHANNEL_WIDTH_20_40 0 +#define VHT_OP_CHANNEL_WIDTH_80 1 +#define VHT_OP_CHANNEL_WIDTH_160 2 +#define VHT_OP_CHANNEL_WIDTH_80P80 3 + +/*8.4.1.50 Operating Mode Field*/ +#define VHT_OP_MODE_CHANNEL_WIDTH BITS(0, 1) +#define VHT_OP_MODE_RX_NSS BITS(4, 6) +#define VHT_OP_MODE_RX_NSS_TYPE BIT(7) + +#define VHT_OP_MODE_NSS_1 0x00 +#define VHT_OP_MODE_NSS_2 0x01 + +#define VHT_OP_MODE_CHANNEL_WIDTH_OFFSET 0 +#define VHT_OP_MODE_RX_NSS_OFFSET 4 +#define VHT_OP_MODE_RX_NSS_TYPE_OFFSET 7 + +#define VHT_OP_MODE_CHANNEL_WIDTH_20 0 +#define VHT_OP_MODE_CHANNEL_WIDTH_40 1 +#define VHT_OP_MODE_CHANNEL_WIDTH_80 2 +#define VHT_OP_MODE_CHANNEL_WIDTH_160_80P80 3 + +/* 8.4.1.22 SM Power Control field*/ +#define HT_SM_POWER_SAVE_CONTROL_ENABLED BIT(0) +/* 0:static, 1:dynamic */ +#define HT_SM_POWER_SAVE_CONTROL_SM_MODE BIT(1) +#define HT_SM_POWER_SAVE_CONTROL_SM_MODE_OFFSET 1 + +/* 8.4.1.21 Channel Width field */ +#define HT_NOTIFY_CHANNEL_WIDTH_20 0 +#define HT_NOTIFY_CHANNEL_WIDTH_ANY_SUPPORT_CAHNNAEL_WIDTH 1 + +/* 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_MAX_AMPDU_LEN_128K BIT(2) +#define AMPDU_PARAM_MAX_AMPDU_LEN_256K (BIT(2) | BIT(0)) +#define AMPDU_PARAM_MAX_AMPDU_LEN_512K BITS(1, 2) +#define AMPDU_PARAM_MAX_AMPDU_LEN_1024K BITS(0, 2) + +#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 */ +#define TXBF_IMPLICIT_RX_CAPABLE BIT(0) +#define TXBF_RX_STAGGERED_SOUNDING_CAPABLE BIT(1) +#define TXBF_TX_STAGGERED_SOUNDING_CAPABLE BIT(2) +#define TXBF_RX_NDP_CAPABLE BIT(3) +#define TXBF_TX_NDP_CAPABLE BIT(4) +#define TXBF_IMPLICIT_TX_CAPABLE BIT(5) +#define TXBF_CALIBRATION_CAPABLE BITS(6, 7) +#define TXBF_EXPLICIT_CSI_TX_CAPABLE BIT(8) +#define TXBF_EXPLICIT_NONCOMPRESSED_TX_CAPABLE BIT(9) +#define TXBF_EXPLICIT_COMPRESSED_TX_CAPAB BIT(10) +#define TXBF_EXPLICIT_CSI_FEEDBACK_CAPABLE BITS(11, 12) +#define TXBF_EXPLICIT_NONCOMPRESSED_FEEDBACK_CAPABLE BITS(13, 14) + +#define TXBF_EXPLICIT_COMPRESSED_FEEDBACK_CAPABLE BITS(15, 16) +#define TXBF_EXPLICIT_COMPRESSED_FEEDBACK_IMMEDIATE_CAPABLE BIT(16) + +#define TXBF_MINIMAL_GROUPING_CAPABLE BITS(17, 18) +#define TXBF_MINIMAL_GROUPING_1_2_3_CAPABLE BITS(17, 18) + +#define TXBF_CSI_BFER_ANTENNANUM_SUPPORTED BITS(19, 20) +#define TXBF_NONCOMPRESSED_TX_ANTENNANUM_SUPPORTED BITS(21, 22) + +#define TXBF_COMPRESSED_TX_ANTENNANUM_SUPPORTED BITS(23, 24) +#define TXBF_COMPRESSED_TX_ANTENNANUM_4_SUPPORTED BITS(23, 24) + +#define TXBF_CSI_MAX_ROWS_BFER_SUPPORTED BITS(25, 26) + +#define TXBF_CHANNEL_ESTIMATION_CAPABILITY BITS(27, 28) +#define TXBF_CHANNEL_ESTIMATION_4STS_CAPABILITY BITS(27, 28) + +/* 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 */ +/* sizeof(IE_HT_OP_T)-2 */ +#define ELEM_MAX_LEN_HT_OP (24 - ELEM_HDR_LEN) + +#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_INFO1_STA_CHNL_WIDTH_OFFSET 2 + +#define HT_OP_INFO2_HT_PROTECTION BITS(0, 1) +#define HT_OP_INFO2_NON_GF_HT_STA_PRESENT BIT(2) +#define HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT BIT(4) + +#define HT_OP_INFO3_DUAL_BEACON BIT(6) +#define HT_OP_INFO3_DUAL_CTS_PROTECTION BIT(7) +#define HT_OP_INFO3_STBC_BEACON BIT(8) +#define HT_OP_INFO3_LSIG_TXOP_FULL_SUPPORT BIT(9) +#define HT_OP_INFO3_PCO_ACTIVE BIT(10) +#define HT_OP_INFO3_PCO_PHASE BIT(11) + +/* 7.3.2.59 OBSS Scan Parameter element */ +#define ELEM_MAX_LEN_OBSS_SCAN (16 - ELEM_HDR_LEN) + +/* 7.3.2.60 20/40 BSS Coexistence element */ +#define ELEM_MAX_LEN_20_40_BSS_COEXIST (3 - ELEM_HDR_LEN) + +#define BSS_COEXIST_INFO_REQ BIT(0) +#define BSS_COEXIST_40M_INTOLERANT BIT(1) +#define BSS_COEXIST_20M_REQ BIT(2) +#define BSS_COEXIST_OBSS_SCAN_EXEMPTION_REQ BIT(3) +#define BSS_COEXIST_OBSS_SCAN_EXEMPTION_GRANT BIT(4) + +/* 802.11u 7.3.2.92 Interworking IE */ +#define ELEM_MAX_LEN_INTERWORKING (11 - ELEM_HDR_LEN) + +/* 802.11u 7.3.2.93 Advertisement Protocol IE */ +#define ELEM_MAX_LEN_ADV_PROTOCOL (4 - ELEM_HDR_LEN) + +/* 802.11u 7.3.2.96 Roaming Consortium IE */ +#define ELEM_MAX_LEN_ROAMING_CONSORTIUM (19 - ELEM_HDR_LEN) + +#define IW_IE_LENGTH_ANO 1 +#define IW_IE_LENGTH_ANO_VENUE 3 +#define IW_IE_LENGTH_ANO_HESSID 7 +#define IW_IE_LENGTH_ANO_VENUE_HESSID 9 + +#if CFG_SUPPORT_PASSPOINT +/* HOTSPOT 2.0 Indication IE*/ +#define ELEM_MAX_LEN_HS20_INDICATION 5 +#define ELEM_MIN_LEN_HS20_INDICATION 4 + +/* Hotspot Configuration*/ +/* Downstream Group-Addressed Forwarding */ +#define ELEM_HS_CONFIG_DGAF_DISABLED_MASK BIT(0) +#endif /* CFG_SUPPORT_PASSPOINT */ + +/* MTK Vendor Specific OUI */ +#define ELEM_MIN_LEN_MTK_OUI 7 +#define VENDOR_OUI_MTK { 0x00, 0x0C, 0xE7 } +#define MTK_SYNERGY_CAP_SUPPORT_24G_MCS89 BIT(3) +#define MTK_SYNERGY_CAP_SUPPORT_24G_MCS89_PROBING BIT(4) +#define MTK_SYNERGY_CAP0 \ + (MTK_SYNERGY_CAP_SUPPORT_24G_MCS89) +#define MTK_SYNERGY_CAP1 0x0 +#define MTK_SYNERGY_CAP2 0x0 +#define MTK_SYNERGY_CAP3 0x0 + +/* 802.11h CSA element */ +#define ELEM_MIN_LEN_CSA 3 + +/* 3 Management frame body components (III): 7.4 Action frame format details. */ +/* 7.4.1 Spectrum Measurement Action frame details */ +/* Spectrum measurement request */ +#define ACTION_MEASUREMENT_REQ 0 +/* Spectrum measurement report */ +#define ACTION_MEASUREMENT_REPORT 1 +/* TPC request */ +#define ACTION_TPC_REQ 2 +/* TPC report */ +#define ACTION_TPC_REPORT 3 +/* Channel Switch Announcement */ +#define ACTION_CHNL_SWITCH 4 + +#define ACTION_SM_TPC_REQ_LEN 5 +#define ACTION_SM_TPC_REPORT_LEN 7 +#define ACTION_SM_MEASURE_REQ_LEN 19 +#define ACTION_SM_MEASURE_REPORT_LEN 8 +#define ACTION_SM_BASIC_REPORT_LEN 12 +#define ACTION_SM_CCA_REPORT_LEN 12 +#define ACTION_SM_PRI_REPORT_LEN 19 +/* Negative value ((dBm) */ +#define MIN_RCV_PWR 100 + +/* 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_QOS_MAP_CONFIGURE 4 /*Qos Map Configure*/ + +/* WMM TSPEC IE: 63 */ +#define ACTION_ADDTS_REQ_FRAME_LEN (24+3+63) +/* WMM Status Code: 1; WMM TSPEC IE: 63 */ +#define ACTION_ADDTS_RSP_FRAME_LEN (24 + 4 + 63) +/*category + action + WMM TSinfo:3 + reason:2*/ +#define ACTION_DELTS_FRAME_LEN (24 + 7) + +/* 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 */ +/* Radio measurement request */ +#define ACTION_RM_REQ 0 +/* Radio measurement report */ +#define ACTION_RM_REPORT 1 +/* Link measurement request */ +#define ACTION_LM_REQ 2 +/* Link measurement report */ +#define ACTION_LM_REPORT 3 +/* Neighbor report request */ +#define ACTION_NEIGHBOR_REPORT_REQ 4 +/* Neighbor report response */ +#define ACTION_NEIGHBOR_REPORT_RSP 5 + +/* 7.4.7 Public Action frame details */ +/* 20/40 BSS coexistence */ +#define ACTION_PUBLIC_20_40_COEXIST 0 + +#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 */ +/* Notify Channel Width */ +#define ACTION_HT_NOTIFY_CHANNEL_WIDTH 0 +/* SM Power Save */ +#define ACTION_HT_SM_POWER_SAVE 1 +/* PSMP */ +#define ACTION_HT_PSMP 2 +/* Set PCO Phase */ +#define ACTION_HT_SET_PCO_PHASE 3 +/* CSI */ +#define ACTION_HT_CSI 4 +/* Non-compressed Beamforming */ +#define ACTION_HT_NON_COMPRESSED_BEAMFORM 5 +/* Compressed Beamforming */ +#define ACTION_HT_COMPRESSED_BEAMFORM 6 +/* Antenna Selection Indices Feedback */ +#define ACTION_HT_ANT_SEL_INDICES_FB 7 + +#define ACTION_WNM_NOTIFICATION_REQUEST 26 +/* 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_WNM_BSS_TRANSITION_MANAGEMENT_QUERY 6 +#define ACTION_WNM_BSS_TRANSITION_MANAGEMENT_REQ 7 +#define ACTION_WNM_BSS_TRANSITION_MANAGEMENT_RSP 8 +#define ACTION_UNPROTECTED_WNM_TIMING_MEAS_LEN 12 + +/* 8.5.23.1 VHT Action */ +#define ACTION_VHT_COMPRESSED_BFEAMFORMING 0 +#define ACTION_GROUP_ID_MANAGEMENT 1 +#define ACTION_OPERATING_MODE_NOTIFICATION 2 + +#if (CFG_SUPPORT_TWT == 1) +/* S1G Action */ +#define ACTION_S1G_TWT_SETUP 6 +#define ACTION_S1G_TWT_TEARDOWN 7 +#define ACTION_S1G_TWT_INFORMATION 11 +#endif + +/* 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 + +/* Epigram IE */ +#define VENDOR_IE_EPIGRAM_OUI 0x00904c +#define VENDOR_IE_EPIGRAM_VHTTYPE1 0x0400 +#define VENDOR_IE_EPIGRAM_VHTTYPE2 0x0408 +#define VENDOR_IE_EPIGRAM_VHTTYPE3 0x0418 + +/* Cisco IE */ +#define VENDOR_IE_CISCO_OUI 0x004096 +#define VENDOR_IE_CISCO_TYPE 0x2C + +#if CFG_SUPPORT_PASSPOINT +#define VENDOR_OUI_TYPE_HS20 16 +#endif /* CFG_SUPPORT_PASSPOINT */ + +/* Length of OUI and Type */ +#define VENDOR_OUI_TYPE_LEN 4 + +/* VERSION(2 octets for WPA) / SUBTYPE(1 octet)-VERSION(1 octet) + * fields for WMM in WFA IE + */ +/* Little Endian Format */ +#define VERSION_WPA 0x0001 +#define VENDOR_OUI_SUBTYPE_VERSION_WMM_INFO 0x0100 +#define VENDOR_OUI_SUBTYPE_VERSION_WMM_PARAM 0x0101 + +/* SUBTYPE(1 octet) for WMM */ +/* WMM Spec version 1.1 */ +#define VENDOR_OUI_SUBTYPE_WMM_INFO 0x00 +#define VENDOR_OUI_SUBTYPE_WMM_PARAM 0x01 +#define VENDOR_OUI_SUBTYPE_WMM_TSPEC 0x02 + +/* VERSION(1 octet) for WMM */ +/* WMM Spec version 1.1 */ +#define VERSION_WMM 0x01 + +/* 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_CONTROL_TID_OFFSET 12 +#define CTRL_BAR_BAR_INFORMATION_OFFSET 18 +#define CTRL_BAR_BAR_INFORMATION_SSN_OFFSET 4 + +/* 802.11-2012, 8.5.7 Radio Measurement action fields, table 8-206 */ +#define RM_ACTION_RM_REQUEST 0 +#define RM_ACTION_RM_REPORT 1 +#define RM_ACTION_LM_REQUEST 2 +#define RM_ACTION_LM_REPORT 3 +#define RM_ACTION_NEIGHBOR_REQUEST 4 +#define RM_ACTION_REIGHBOR_RESPONSE 5 + +#if (CFG_SUPPORT_TWT == 1) +/* TWT element */ +#define TWT_CTRL_NDP_PAGING_INDICATOR BIT(0) +#define TWT_CTRL_RESPONDER_PM_MODE BIT(1) +#define TWT_CTRL_BROADCAST BIT(2) +#define TWT_CTRL_WAKE_TBTT_NEGOTIATION BIT(3) + +#define TWT_REQ_TYPE_TWT_REQUEST BIT(0) +#define TWT_REQ_TYPE_TWT_SETUP_COMMAND BITS(1, 3) +#define TWT_REQ_TYPE_TRIGGER BIT(4) +#define TWT_REQ_TYPE_IMPLICIT_LAST_BCAST_PARAM BIT(5) +#define TWT_REQ_TYPE_FLOWTYPE BIT(6) +#define TWT_REQ_TYPE_TWT_FLOW_IDENTIFIER BITS(7, 9) +#define TWT_REQ_TYPE_TWT_WAKE_INTVAL_EXP BITS(10, 14) +#define TWT_REQ_TYPE_TWT_PROTECTION BIT(15) + +#define TWT_REQ_TYPE_TWT_REQUEST_OFFSET 0 +#define TWT_REQ_TYPE_TWT_SETUP_COMMAND_OFFSET 1 +#define TWT_REQ_TYPE_TRIGGER_OFFSET 4 +#define TWT_REQ_TYPE_IMPLICIT_LAST_BCAST_PARAM_OFFSET 5 +#define TWT_REQ_TYPE_FLOWTYPE_OFFSET 6 +#define TWT_REQ_TYPE_TWT_FLOW_IDENTIFIER_OFFSET 7 +#define TWT_REQ_TYPE_TWT_WAKE_INTVAL_EXP_OFFSET 10 +#define TWT_REQ_TYPE_TWT_PROTECTION_OFFSET 15 + +#define TWT_SETUP_CMD_REQUEST 0 +#define TWT_SETUP_CMD_SUGGEST 1 +#define TWT_SETUP_CMD_DEMAND 2 +#define TWT_SETUP_CMD_GROUPING 3 +#define TWT_SETUP_CMD_ACCEPT 4 +#define TWT_SETUP_CMD_ALTERNATE 5 +#define TWT_SETUP_CMD_DICTATE 6 +#define TWT_SETUP_CMD_REJECT 7 + +/* TWT Flow Field in teardown frame */ +#define TWT_TEARDOWN_FLOW_ID BITS(0, 2) + +/* TWT Information Field */ +#define TWT_INFO_FLOW_ID BITS(0, 2) +#define TWT_INFO_RESP_REQUESTED BIT(3) +#define TWT_INFO_NEXT_TWT_REQ BIT(4) +#define TWT_INFO_NEXT_TWT_SIZE BITS(5, 6) +#define TWT_INFO_BCAST_RESCHED BIT(7) + +#define TWT_INFO_FLOW_ID_OFFSET 0 +#define TWT_INFO_RESP_REQUESTED_OFFSET 3 +#define TWT_INFO_NEXT_TWT_REQ_OFFSET 4 +#define TWT_INFO_NEXT_TWT_SIZE_OFFSET 5 +#define TWT_INFO_BCAST_RESCHED_OFFSET 7 + +#define NEXT_TWT_SUBFIELD_ZERO_BIT 0 +#define NEXT_TWT_SUBFIELD_32_BITS 1 +#define NEXT_TWT_SUBFIELD_48_BITS 2 +#define NEXT_TWT_SUBFIELD_64_BITS 3 +#endif + +/* 9.4.2.46 Multiple BSSID element */ +/* Nontransmitted BSSID Profile */ +#define NON_TX_BSSID_PROFILE 0 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +#if defined(WINDOWS_DDK) || defined(WINDOWS_CE) +#pragma pack(1) +#endif + +struct LLC_SNAP_HEADER { + uint8_t ucDSAP; + uint8_t ucSSAP; + uint8_t ucControl; + uint8_t aucCode[3]; + uint16_t u2Type; +} __KAL_ATTRIB_PACKED__; + +/* 3 MAC Header. */ +/* Ethernet Frame Header */ +struct ETH_FRAME_HEADER { + uint8_t aucDestAddr[MAC_ADDR_LEN]; + uint8_t aucSrcAddr[MAC_ADDR_LEN]; + uint16_t u2TypeLen; +} __KAL_ATTRIB_PACKED__; + +/* Ethernet Frame Structure */ +struct ETH_FRAME { + uint8_t aucDestAddr[MAC_ADDR_LEN]; + uint8_t aucSrcAddr[MAC_ADDR_LEN]; + uint16_t u2TypeLen; + uint8_t aucData[1]; +} __KAL_ATTRIB_PACKED__; + +struct BOOTP_PROTOCOL { + uint8_t ucOperation; + uint8_t ucHdrType; + uint8_t ucHdrLen; + uint8_t ucHops; + uint32_t u4TransId; + uint16_t u2Seconds; + uint16_t u2Flags; + uint32_t u4CIAddr; + uint32_t u4YIAddr; + uint32_t u4SIAddr; + uint32_t u4GIAddr; + uint8_t aucCHAddr[16]; + uint8_t aucServerName[64]; + uint8_t aucFileName[128]; + uint8_t aucOptions[0]; +} __KAL_ATTRIB_PACKED__; + +/* IEEE 802.11 WLAN Frame Structure */ +/* WLAN MAC Header (without Address 4 and QoS Control fields) */ +struct WLAN_MAC_HEADER { + uint16_t u2FrameCtrl; + uint16_t u2DurationID; + uint8_t aucAddr1[MAC_ADDR_LEN]; + uint8_t aucAddr2[MAC_ADDR_LEN]; + uint8_t aucAddr3[MAC_ADDR_LEN]; + uint16_t u2SeqCtrl; +} __KAL_ATTRIB_PACKED__; + +/* WLAN MAC Header (QoS Control fields included) */ +struct WLAN_MAC_HEADER_QOS { + uint16_t u2FrameCtrl; + uint16_t u2DurationID; + uint8_t aucAddr1[MAC_ADDR_LEN]; + uint8_t aucAddr2[MAC_ADDR_LEN]; + uint8_t aucAddr3[MAC_ADDR_LEN]; + uint16_t u2SeqCtrl; + uint16_t u2QosCtrl; +} __KAL_ATTRIB_PACKED__; + +/* WLAN MAC Header (HT Control fields included) */ +struct WLAN_MAC_HEADER_HT { + uint16_t u2FrameCtrl; + uint16_t u2DurationID; + uint8_t aucAddr1[MAC_ADDR_LEN]; + uint8_t aucAddr2[MAC_ADDR_LEN]; + uint8_t aucAddr3[MAC_ADDR_LEN]; + uint16_t u2SeqCtrl; + uint16_t u2QosCtrl; + uint32_t u4HtCtrl; +} __KAL_ATTRIB_PACKED__; + +/* WLAN MAC Header (Address 4 included) */ +struct WLAN_MAC_HEADER_A4 { + uint16_t u2FrameCtrl; + uint16_t u2DurationID; + uint8_t aucAddr1[MAC_ADDR_LEN]; + uint8_t aucAddr2[MAC_ADDR_LEN]; + uint8_t aucAddr3[MAC_ADDR_LEN]; + uint16_t u2SeqCtrl; + uint8_t aucAddr4[MAC_ADDR_LEN]; +} __KAL_ATTRIB_PACKED__; + +/* WLAN MAC Header (Address 4 and QoS Control fields included) */ +struct WLAN_MAC_HEADER_A4_QOS { + uint16_t u2FrameCtrl; + uint16_t u2DurationID; + uint8_t aucAddr1[MAC_ADDR_LEN]; + uint8_t aucAddr2[MAC_ADDR_LEN]; + uint8_t aucAddr3[MAC_ADDR_LEN]; + uint16_t u2SeqCtrl; + uint8_t aucAddr4[MAC_ADDR_LEN]; + uint16_t u2QosCtrl; +} __KAL_ATTRIB_PACKED__; + +struct WLAN_MAC_HEADER_A4_HT { + uint16_t u2FrameCtrl; + uint16_t u2DurationID; + uint8_t aucAddr1[MAC_ADDR_LEN]; + uint8_t aucAddr2[MAC_ADDR_LEN]; + uint8_t aucAddr3[MAC_ADDR_LEN]; + uint16_t u2SeqCtrl; + uint8_t aucAddr4[MAC_ADDR_LEN]; + uint16_t u2QosCtrl; + uint32_t u4HtCtrl; +} __KAL_ATTRIB_PACKED__; + +/* 7.2.3 WLAN MAC Header for Management Frame - MMPDU */ +struct WLAN_MAC_MGMT_HEADER { + uint16_t u2FrameCtrl; + uint16_t u2Duration; + uint8_t aucDestAddr[MAC_ADDR_LEN]; + uint8_t aucSrcAddr[MAC_ADDR_LEN]; + uint8_t aucBSSID[MAC_ADDR_LEN]; + uint16_t u2SeqCtrl; +} __KAL_ATTRIB_PACKED__; + +/* WLAN MAC Header for Management Frame (HT Control fields included) */ +struct WLAN_MAC_MGMT_HEADER_HT { + uint16_t u2FrameCtrl; + uint16_t u2DurationID; + uint8_t aucAddr1[MAC_ADDR_LEN]; + uint8_t aucAddr2[MAC_ADDR_LEN]; + uint8_t aucAddr3[MAC_ADDR_LEN]; + uint16_t u2SeqCtrl; + uint32_t u4HtCtrl; +} __KAL_ATTRIB_PACKED__; + +/* 3 WLAN CONTROL Frame */ +/* 7.2.1.4 WLAN Control Frame - PS-POLL Frame */ +struct CTRL_PSPOLL_FRAME { + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2AID; /* AID */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint8_t aucTA[MAC_ADDR_LEN]; /* TA */ +} __KAL_ATTRIB_PACKED__; + +/* BAR */ +struct CTRL_BAR_FRAME { + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* RA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* TA */ + uint16_t u2BarControl; + uint8_t aucBarInfo[2]; /* Variable size */ +} __KAL_ATTRIB_PACKED__; + +/* 3 WLAN Management Frame. */ +/* 7.2.3.1 WLAN Management Frame - Beacon Frame */ +struct WLAN_BEACON_FRAME { + /* Beacon header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Beacon frame body */ + uint32_t au4Timestamp[2]; /* Timestamp */ + uint16_t u2BeaconInterval; /* Beacon Interval */ + uint16_t u2CapInfo; /* Capability */ + uint8_t aucInfoElem[1]; /* Various IEs, start from SSID */ +} __KAL_ATTRIB_PACKED__; + +struct WLAN_BEACON_FRAME_BODY { + /* Beacon frame body */ + uint32_t au4Timestamp[2]; /* Timestamp */ + uint16_t u2BeaconInterval; /* Beacon Interval */ + uint16_t u2CapInfo; /* Capability */ + uint8_t aucInfoElem[1]; /* Various IEs, start from SSID */ +} __KAL_ATTRIB_PACKED__; + +/* 7.2.3.3 WLAN Management Frame - Disassociation Frame */ +struct WLAN_DISASSOC_FRAME { + /* Authentication MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Disassociation frame body */ + uint16_t u2ReasonCode; /* Reason code */ + uint8_t aucInfoElem[1]; /* Various IEs, possible no. */ +} __KAL_ATTRIB_PACKED__; + +/* 7.2.3.4 WLAN Management Frame - Association Request frame */ +struct WLAN_ASSOC_REQ_FRAME { + /* Association Request MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Association Request frame body */ + uint16_t u2CapInfo; /* Capability information */ + uint16_t u2ListenInterval; /* Listen interval */ + uint8_t aucInfoElem[1]; /* Information elements, include WPA IE */ +} __KAL_ATTRIB_PACKED__; + +/* 7.2.3.5 WLAN Management Frame - Association Response frame */ +struct WLAN_ASSOC_RSP_FRAME { + /* Association Response MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Association Response frame body */ + uint16_t u2CapInfo; /* Capability information */ + uint16_t u2StatusCode; /* Status code */ + uint16_t u2AssocId; /* Association ID */ + uint8_t aucInfoElem[1]; /* Information elements, such as */ + /* supported rates, and etc. */ +} __KAL_ATTRIB_PACKED__; + +/* 7.2.3.6 WLAN Management Frame - Reassociation Request frame */ +struct WLAN_REASSOC_REQ_FRAME { + /* Reassociation Request MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Reassociation Request frame body */ + uint16_t u2CapInfo; /* Capability information */ + uint16_t u2ListenInterval; /* Listen interval */ + uint8_t aucCurrentAPAddr[MAC_ADDR_LEN]; /* Current AP address */ + uint8_t aucInfoElem[1]; /* Information elements, include WPA IE */ +} __KAL_ATTRIB_PACKED__; + +/* 7.2.3.7 WLAN Management Frame - Reassociation Response frame */ +/* (the same as Association Response frame) */ + +/* 7.2.3.9 WLAN Management Frame - Probe Response Frame */ + +/* 7.2.3.10 WLAN Management Frame - Authentication Frame */ +struct WLAN_AUTH_FRAME { + /* Authentication MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Authentication frame body */ + uint16_t u2AuthAlgNum; /* Authentication algorithm number */ + /* Authentication transaction sequence number */ + uint16_t u2AuthTransSeqNo; + uint16_t u2StatusCode; /* Status code */ + uint8_t aucInfoElem[1]; /* Various IEs for Fast BSS Transition */ +} __KAL_ATTRIB_PACKED__; + +/* 7.2.3.11 WLAN Management Frame - Deauthentication Frame */ +struct WLAN_DEAUTH_FRAME { + /* Authentication MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Deauthentication frame body */ + uint16_t u2ReasonCode; /* Reason code */ + uint8_t aucInfoElem[1]; /* Various IEs, possible no. */ +} __KAL_ATTRIB_PACKED__; + +/* 3 Information Elements. */ +/* 7.3.2 Generic element format */ +struct IE_HDR { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucInfo[1]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.1 SSID element */ +struct IE_SSID { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucSSID[ELEM_MAX_LEN_SSID]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.2 Supported Rates element */ +struct IE_SUPPORTED_RATE { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucSupportedRates[ELEM_MAX_LEN_SUP_RATES]; +} __KAL_ATTRIB_PACKED__; + +/* Some IOT AP will carry Rates > 8*/ +struct IE_SUPPORTED_RATE_IOT { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucSupportedRates[ELEM_MAX_LEN_SUP_RATES_IOT]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.4 DS Parameter Set element */ +struct IE_DS_PARAM_SET { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucCurrChnl; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.5 CF Parameter Set element */ +struct IE_CF_PARAM_SET { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucCFPCount; + uint8_t ucCFPPeriod; + uint16_t u2CFPMaxDur; + uint16_t u2DurRemaining; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.6 TIM */ +struct IE_TIM { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucDTIMCount; + uint8_t ucDTIMPeriod; + uint8_t ucBitmapControl; + uint8_t aucPartialVirtualMap[1]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.7 IBSS Parameter Set element */ +struct IE_IBSS_PARAM_SET { + uint8_t ucId; + uint8_t ucLength; + uint16_t u2ATIMWindow; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.8 Challenge Text element */ +struct IE_CHALLENGE_TEXT { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucChallengeText[ELEM_MAX_LEN_CHALLENGE_TEXT]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.9 Country information element */ +#if CFG_SUPPORT_802_11D +/*! \brief COUNTRY_INFO_TRIPLET + * is defined for the COUNTRY_INFO_ELEM structure. + */ +struct COUNTRY_INFO_TRIPLET { + /*!< If param1 >= 201, this triplet is referred to as + * Regulatory Triplet in 802_11J. + */ + uint8_t ucParam1; + uint8_t ucParam2; + uint8_t ucParam3; +} __KAL_ATTRIB_PACKED__; + +struct COUNTRY_INFO_SUBBAND_TRIPLET { + uint8_t ucFirstChnlNum; /*!< First Channel Number */ + uint8_t ucNumOfChnl; /*!< Number of Channels */ + int8_t cMaxTxPwrLv; /*!< Maximum Transmit Power Level */ +} __KAL_ATTRIB_PACKED__; + +struct COUNTRY_INFO_REGULATORY_TRIPLET { + uint8_t ucRegExtId; /*!< Regulatory Extension Identifier, should */ + /* be greater than or equal to 201 */ + uint8_t ucRegClass; /*!< Regulatory Class */ + /*!< Coverage Class, unsigned 1-octet value 0~31 */ + uint8_t ucCoverageClass; + /* , 32~255 reserved */ +} __KAL_ATTRIB_PACKED__; + +struct IE_COUNTRY { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucCountryStr[3]; + struct COUNTRY_INFO_SUBBAND_TRIPLET arCountryStr[1]; +} __KAL_ATTRIB_PACKED__; +#endif /* CFG_SUPPORT_802_11D */ + +/* 7.3.2.13 ERP element */ +struct IE_ERP { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucERP; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.14 Extended Supported Rates element */ +struct IE_EXT_SUPPORTED_RATE { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucExtSupportedRates[ELEM_MAX_LEN_EXTENDED_SUP_RATES]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.15 Power Constraint element */ +struct IE_POWER_CONSTRAINT { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucLocalPowerConstraint; /* Unit: dBm */ +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.16 Power Capability element */ +struct IE_POWER_CAP { + uint8_t ucId; + uint8_t ucLength; + int8_t cMinTxPowerCap; /* Unit: dBm */ + int8_t cMaxTxPowerCap; /* Unit: dBm */ +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.17 TPC request element */ +struct IE_TPC_REQ { + uint8_t ucId; + uint8_t ucLength; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.18 TPC report element */ +struct IE_TPC_REPORT { + uint8_t ucId; + uint8_t ucLength; + int8_t cTxPower; /* Unit: dBm */ + int8_t cLinkMargin; /* Unit: dB */ +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.19 Supported Channels element*/ +struct IE_SUPPORTED_CHANNELS { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucChannelNum[0]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.20 Channel Switch Announcement element*/ +struct IE_CHANNEL_SWITCH { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucChannelSwitchMode; + uint8_t ucNewChannelNum; + uint8_t ucChannelSwitchCount; +} __KAL_ATTRIB_PACKED__; + +struct IE_TIMEOUT_INTERVAL { + uint8_t ucId; + uint8_t ucLength; +#define IE_TIMEOUT_INTERVAL_TYPE_RESERVED 0 +#define IE_TIMEOUT_INTERVAL_TYPE_REASSOC 1 +#define IE_TIMEOUT_INTERVAL_TYPE_KEY_LIFETIME 43200 +#define IE_TIMEOUT_INTERVAL_TYPE_ASSOC_COMEBACK 3 + uint8_t ucType; + uint32_t u4Value; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.20 Channel Switch Announcement element */ +struct IE_CHNL_SWITCH { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucSwitchMode; + uint8_t ucNewChannel; + uint8_t ucSwitchCount; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.21 Measurement Request element */ +struct IE_MEASUREMENT_REQ { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucToken; + uint8_t ucRequestMode; + uint8_t ucMeasurementType; + uint8_t aucRequestFields[0]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.60 20/40 BSS Coexistence element */ +struct IE_SUP_OPERATING_CLASS { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucCur; + uint8_t ucSup[255]; +} __KAL_ATTRIB_PACKED__; + +/* 8.4.2.30 BSS Load element */ +struct IE_BSS_LOAD { + uint8_t ucId; + uint8_t ucLength; + uint16_t u2StaCnt; + uint8_t ucChnlUtilizaion; + uint16_t u2AvailabeAC; +} __KAL_ATTRIB_PACKED__; + +/* 8.4.2.39 Neighbor Report Element */ +struct IE_NEIGHBOR_REPORT { + uint8_t ucId; /* Element ID */ + uint8_t ucLength; /* Length */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* OUI */ + uint32_t u4BSSIDInfo; /* Type */ + uint8_t ucOperClass; /* Hotspot Configuration */ + uint8_t ucChnlNumber; + uint8_t ucPhyType; + uint8_t aucSubElem[0]; +} __KAL_ATTRIB_PACKED__; + +struct IE_MBO_OCE { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucOui[3]; + uint8_t ucOuiType; + uint8_t aucSubElements[1]; +} __KAL_ATTRIB_PACKED__; + +/* 8.5.7.6/8.5.7.7 Neighbor Report Request/Response frame format */ +struct ACTION_NEIGHBOR_REPORT_FRAME { + /* Neighbor Report Request/Response MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Neighbor Report Request/Response frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token */ + uint8_t aucInfoElem[1]; /* subelements */ +} __KAL_ATTRIB_PACKED__; + +struct SUB_ELEMENT { + uint8_t ucSubID; + uint8_t ucLength; + uint8_t aucOptInfo[1]; +} __KAL_ATTRIB_PACKED__; + +struct SM_BASIC_REQ { + uint8_t ucChannel; + uint32_t au4StartTime[2]; + uint16_t u2Duration; +} __KAL_ATTRIB_PACKED__; + +/* SM_COMMON_REQ_T is not specified in Spec. Use it as common structure of SM */ + +struct RM_CHNL_LOAD_REQ { + uint8_t ucRegulatoryClass; + uint8_t ucChannel; + uint16_t u2RandomInterval; + uint16_t u2Duration; + uint8_t aucSubElements[1]; +} __KAL_ATTRIB_PACKED__; + + +struct RM_BCN_REQ { + uint8_t ucRegulatoryClass; + uint8_t ucChannel; + uint16_t u2RandomInterval; + uint16_t u2Duration; + uint8_t ucMeasurementMode; + uint8_t aucBssid[6]; + uint8_t aucSubElements[1]; +} __KAL_ATTRIB_PACKED__; + +struct RM_FRAME_REQ { + uint8_t ucRegulatoryClass; + uint8_t ucChannel; + uint16_t u2RandomInterval; + uint16_t u2Duration; + uint8_t ucFrameReqType; + uint8_t aucMacAddr[6]; + uint8_t aucSubElements[1]; +} __KAL_ATTRIB_PACKED__; + +struct RM_STA_STATS_REQ { + uint8_t aucPeerMacAddr[6]; + uint16_t u2RandomInterval; + uint16_t u2Duration; + uint8_t ucGroupID; + uint8_t aucSubElements[1]; +} __KAL_ATTRIB_PACKED__; + +struct RM_LCI_REQ { + uint8_t ucLocationSubject; + uint8_t ucLatitudeResolution; + uint8_t ucLongitudeResolution; + uint8_t ucAltitudeResolution; + uint8_t aucSubElements[1]; +} __KAL_ATTRIB_PACKED__; + +struct RM_TS_MEASURE_REQ { + uint16_t u2RandomInterval; + uint16_t u2Duration; + uint8_t aucPeerStaAddr[6]; + uint8_t ucTrafficID; + uint8_t ucBin0Range; + uint8_t aucSubElements[1]; +} __KAL_ATTRIB_PACKED__; + +struct RM_MEASURE_PAUSE_REQ { + uint16_t u2PauseTime; + uint8_t aucSubElements[1]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.22 Measurement Report element */ +struct IE_MEASUREMENT_REPORT { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucToken; + uint8_t ucReportMode; + uint8_t ucMeasurementType; + uint8_t aucReportFields[0]; +} __KAL_ATTRIB_PACKED__; + +struct SM_BASIC_REPORT { + uint8_t ucChannel; + uint32_t u4StartTime[2]; + uint16_t u2Duration; + uint8_t ucMap; +} __KAL_ATTRIB_PACKED__; + +struct SM_CCA_REPORT { + uint8_t ucChannel; + uint32_t u4StartTime[2]; + uint16_t u2Duration; + uint8_t ucCcaBusyFraction; +} __KAL_ATTRIB_PACKED__; + +struct SM_RPI_REPORT { + uint8_t ucChannel; + uint32_t u4StartTime[2]; + uint16_t u2Duration; + uint8_t aucRPI[8]; +} __KAL_ATTRIB_PACKED__; + +struct RM_CHNL_LOAD_REPORT { + uint8_t ucRegulatoryClass; + uint8_t ucChannel; + uint32_t u4StartTime[2]; + uint16_t u2Duration; + uint8_t ucChnlLoad; +} __KAL_ATTRIB_PACKED__; + +struct RM_IPI_REPORT { + uint8_t ucRegulatoryClass; + uint8_t ucChannel; + uint32_t u4StartTime[2]; + uint16_t u2Duration; + uint8_t ucAntennaId; + int8_t cANPI; + uint8_t aucIPI[11]; +} __KAL_ATTRIB_PACKED__; + +struct RM_BCN_REPORT { + uint8_t ucRegulatoryClass; + uint8_t ucChannel; + uint8_t aucStartTime[8]; + uint16_t u2Duration; + uint8_t ucReportInfo; + uint8_t ucRCPI; + uint8_t ucRSNI; + uint8_t aucBSSID[MAC_ADDR_LEN]; + uint8_t ucAntennaID; + uint8_t aucParentTSF[4]; + uint8_t aucOptElem[0]; +} __KAL_ATTRIB_PACKED__; + +struct RM_TSM_REPORT { + uint64_t u8ActualStartTime; + uint16_t u2Duration; + uint8_t aucPeerAddress[MAC_ADDR_LEN]; + uint8_t ucTID; + uint8_t ucReason; + uint32_t u4TransmittedMsduCnt; + uint32_t u4DiscardedMsduCnt; + uint32_t u4FailedMsduCnt; + uint32_t u4MultiRetryCnt; + uint32_t u4CfPollLostCnt; + uint32_t u4AvgQueDelay; + uint32_t u4AvgDelay; + uint8_t ucBin0Range; + uint32_t u4Bin[6]; + uint8_t aucOptSubElems[0]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.23 Quiet element */ +struct IE_QUIET { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucCount; + uint8_t ucPeriod; + uint16_t u2Duration; + uint16_t u2Offset; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.27 Extended Capabilities element */ +struct IE_EXT_CAP { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucCapabilities[1]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.27 hs20 Extended Capabilities element */ +struct IE_HS20_EXT_CAP_T { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucCapabilities[6]; +}; + +/* 7.3.2.27 Extended Capabilities element */ +struct IE_RRM_ENABLED_CAP { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucCap[5]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.56 HT Capabilities element */ +struct SUP_MCS_SET_FIELD { + uint8_t aucRxMcsBitmask[SUP_MCS_RX_BITMASK_OCTET_NUM]; + uint16_t u2RxHighestSupportedRate; + uint32_t u4TxRateInfo; +} __KAL_ATTRIB_PACKED__; + +struct IE_HT_CAP { + uint8_t ucId; + uint8_t ucLength; + uint16_t u2HtCapInfo; + uint8_t ucAmpduParam; + struct SUP_MCS_SET_FIELD rSupMcsSet; + uint16_t u2HtExtendedCap; + uint32_t u4TxBeamformingCap; + uint8_t ucAselCap; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.57 HT Operation element */ +struct IE_HT_OP { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucPrimaryChannel; + uint8_t ucInfo1; + uint16_t u2Info2; + uint16_t u2Info3; + uint8_t aucBasicMcsSet[16]; +} __KAL_ATTRIB_PACKED__; + +/*8.4.2.160.3 VHT Supported MCS Set field*/ +struct VHT_SUPPORTED_MCS_FIELD { + uint16_t u2RxMcsMap; + uint16_t u2RxHighestSupportedDataRate; + uint16_t u2TxMcsMap; + uint16_t u2TxHighestSupportedDataRate; +} __KAL_ATTRIB_PACKED__; + +struct IE_VHT_CAP { + uint8_t ucId; + uint8_t ucLength; + uint32_t u4VhtCapInfo; + struct VHT_SUPPORTED_MCS_FIELD rVhtSupportedMcsSet; +} __KAL_ATTRIB_PACKED__; + +/*8.4.2.161 VHT Operation element*/ +struct IE_VHT_OP { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucVhtOperation[3]; + uint16_t u2VhtBasicMcsSet; +} __KAL_ATTRIB_PACKED__; + +struct IE_VENDOR_EPIGRAM_IE { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucOui[3]; + uint8_t aucVendorType[2]; + uint8_t pucData[1]; +} __KAL_ATTRIB_PACKED__; + +struct IE_VENDOR_ADAPTIVE_11R_IE { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucOui[3]; + uint8_t aucVendorType[1]; + uint8_t pucData[1]; +} __KAL_ATTRIB_PACKED__; + +/*8.4.1.50 Operating Mode field*/ +struct IE_VHT_OP_MODE_NOTIFICATION { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucOperatingMode; +} __KAL_ATTRIB_PACKED__; + + +/*8.4.2.22 Secondary Channel Offset element*/ +struct IE_SECONDARY_OFFSET { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucSecondaryOffset; +} __KAL_ATTRIB_PACKED__; + +/*8.4.2.105 Mesh Channel Switch Parameters element*/ +struct IE_MESH_CHANNEL { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucTimetoLive; + uint8_t ucFlags; + uint16_t u2ReasonCodes; + uint16_t u2ProcedenceValue; +} __KAL_ATTRIB_PACKED__; + +/*8.4.2.163 Wide Bandwidth Channel Switch element*/ +struct IE_WIDE_BAND_CHANNEL { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucNewChannelWidth; + uint8_t ucChannelS1; + uint8_t ucChannelS2; +} __KAL_ATTRIB_PACKED__; + +/*8.4.2.168 Operating Mode Notification element*/ +struct IE_OP_MODE_NOTIFICATION { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucOpMode; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.25 RSN Information element format */ +struct RSN_INFO_ELEM { + uint8_t ucElemId; + uint8_t ucLength; + uint16_t u2Version; + uint32_t u4GroupKeyCipherSuite; + uint16_t u2PairwiseKeyCipherSuiteCount; + uint8_t aucPairwiseKeyCipherSuite1[4]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.26 WPA Information element format */ +struct WPA_INFO_ELEM { + uint8_t ucElemId; + uint8_t ucLength; + uint8_t aucOui[3]; + uint8_t ucOuiType; + uint16_t u2Version; + uint32_t u4GroupKeyCipherSuite; + uint16_t u2PairwiseKeyCipherSuiteCount; + uint8_t aucPairwiseKeyCipherSuite1[4]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.58 20/40 BSS Intolerant Channel Report element */ +struct IE_INTOLERANT_CHNL_REPORT { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucRegulatoryClass; + uint8_t aucChannelList[1]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.59 OBSS Scan Parameters element */ +struct IE_OBSS_SCAN_PARAM { + uint8_t ucId; + uint8_t ucLength; + uint16_t u2ScanPassiveDwell; + uint16_t u2ScanActiveDwell; + uint16_t u2TriggerScanInterval; + uint16_t u2ScanPassiveTotalPerChnl; + uint16_t u2ScanActiveTotalPerChnl; + uint16_t u2WidthTransDelayFactor; + uint16_t u2ScanActivityThres; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.60 20/40 BSS Coexistence element */ +struct IE_20_40_COEXIST { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucData; +} __KAL_ATTRIB_PACKED__; + +#if (CFG_SUPPORT_TWT == 1) +/* 11ax TWT element */ +struct _IE_TWT_T { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucCtrl; /* Control */ + uint16_t u2ReqType; /* Request Type */ + uint64_t u8TWT; /* Target Wake Time 64 bits */ + uint8_t ucMinWakeDur; /* Nominal Minimum TWT Wake Duration */ + uint16_t u2WakeIntvalMantiss; /* TWT Wake Interval Mantissa */ + uint8_t ucReserved; /* TWT Channel for 11ah. Reserved for 11ax */ +} __KAL_ATTRIB_PACKED__; +#endif + +/* 3 7.4 Action Frame. */ +/* 7.4 Action frame format */ +struct WLAN_ACTION_FRAME { + /* Action MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Action frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucActionDetails[1]; /* Action details */ +} __KAL_ATTRIB_PACKED__; + +/* public Action frame format */ +struct WLAN_PUBLIC_VENDOR_ACTION_FRAME { + /* Action MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Action frame body */ + uint8_t ucCategory; /* Category: should be 0x4 */ + uint8_t ucAction; /* Action Value: should be 0x9 */ + uint8_t ucOUI[3]; + uint8_t ucSubType; + uint8_t ucPubSubType; +} __KAL_ATTRIB_PACKED__; + + +/* 7.4.1.1 Spectrum Measurement Request frame format */ +struct ACTION_SM_REQ_FRAME { + /* ADDTS Request MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* ADDTS Request frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token */ + uint8_t aucInfoElem[1]; /* Information elements */ +} __KAL_ATTRIB_PACKED__; + +/* 7.4.1.2 Spectrum Measurement Report frame format */ + +/* 7.4.1.3 Spectrum TPC Request frame format */ +struct ACTION_TPC_REQ_FRAME { + /* ADDTS Request MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* ADDTS Request frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token */ + uint8_t ucElemId; /* Element ID */ + uint8_t ucLength; /* Length */ +} __KAL_ATTRIB_PACKED__; + +/* 7.4.1.4 Spectrum TPC Report frame format */ +struct ACTION_TPC_REPORT_FRAME { + /* ADDTS Request MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* ADDTS Request frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token */ + uint8_t ucElemId; /* Element ID */ + uint8_t ucLength; /* Length */ + uint8_t ucTransPwr; /* Transmit Power */ + uint8_t ucLinkMargin; /* Link Margin */ +} __KAL_ATTRIB_PACKED__; + +/* 7.4.1.5 Channel Switch Announcement frame format */ +struct ACTION_CHANNEL_SWITCH_FRAME { + /* ADDTS Request MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* ADDTS Request frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t aucInfoElem[5]; /* Information elements */ +} __KAL_ATTRIB_PACKED__; + +/* 7.4.2.1 ADDTS Request frame format */ +struct ACTION_ADDTS_REQ_FRAME { + /* ADDTS Request MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* ADDTS Request frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token */ + uint8_t aucInfoElem[1]; /* Information elements, such as */ + /* TS Delay, and etc. */ +} __KAL_ATTRIB_PACKED__; + +/* 7.4.2.2 ADDTS Response frame format */ +struct ACTION_ADDTS_RSP_FRAME { + /* ADDTS Response MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* ADDTS Response frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token */ + uint8_t ucStatusCode; /* WMM Status Code is of one byte */ + uint8_t aucInfoElem[1]; /* Information elements, such as */ + /* TS Delay, and etc. */ +} __KAL_ATTRIB_PACKED__; + +/* 7.4.2.3 DELTS frame format */ +struct ACTION_DELTS_FRAME { + /* DELTS MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* DELTS frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t aucTsInfo[3]; /* TS Info */ +} __KAL_ATTRIB_PACKED__; + +/* 7.4.2.3 QOSMAPSET CONFIGURATE frame format */ +struct _ACTION_QOS_MAP_CONFIGURE_FRAME { + /* QOSMAP CONFIGURE MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* DELTS frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t qosMapSet[1]; /* qosmapset IE */ +}; + +/* 7.4.4.1 ADDBA Request frame format */ +struct ACTION_ADDBA_REQ_FRAME { + /* Action MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Action frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token chosen by the sender */ + uint8_t aucBAParameterSet[2]; /* BA policy, TID, buffer size */ + uint8_t aucBATimeoutValue[2]; + uint8_t aucBAStartSeqCtrl[2]; /* SSN */ +} __KAL_ATTRIB_PACKED__; + +struct ACTION_ADDBA_REQ_BODY { + uint16_t u2BAParameterSet; /* BA policy, TID, buffer size */ + uint16_t u2BATimeoutValue; + uint16_t u2BAStartSeqCtrl; /* SSN */ +} __KAL_ATTRIB_PACKED__; + +/* 7.4.4.2 ADDBA Response frame format */ +struct ACTION_ADDBA_RSP_FRAME { + /* Action MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Action frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token chosen by the sender */ + uint8_t aucStatusCode[2]; + uint8_t aucBAParameterSet[2]; /* BA policy, TID, buffer size */ + uint8_t aucBATimeoutValue[2]; +} __KAL_ATTRIB_PACKED__; + +struct ACTION_ADDBA_RSP_BODY { + uint16_t u2StatusCode; + uint16_t u2BAParameterSet; /* BA policy, TID, buffer size */ + uint16_t u2BATimeoutValue; +} __KAL_ATTRIB_PACKED__; + +/* 7.4.4.3 DELBA frame format */ +struct ACTION_DELBA_FRAME { + /* Action MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Action frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint16_t u2DelBaParameterSet; /* Bit 11 Initiator, Bits 12-15 TID */ + uint16_t u2ReasonCode; /* 7.3.1.7 */ +} __KAL_ATTRIB_PACKED__; + +#if CFG_SUPPORT_NCHO +/* 7.4.5.1 vendor-specific frame format */ +struct _ACTION_VENDOR_SPEC_FRAME_T { + /* Action MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + uint8_t aucElemInfo[0]; /* Pointer to frame data */ +}; +#endif + +/* 7.4.6.1 Radio Measurement Request frame format */ +struct ACTION_RM_REQ_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Radio Measurement Request frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token */ + uint16_t u2Repetitions; /* Number of repetitions */ + uint8_t aucInfoElem[1]; /* Measurement Request elements, such as */ + /* channel load request, and etc. */ +} __KAL_ATTRIB_PACKED__; + +/* 7.4.6.2 Radio Measurement Report frame format */ +struct ACTION_RM_REPORT_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Radio Measurement Report frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token */ + uint8_t aucInfoElem[0]; /* Measurement Report elements, such as */ + /* channel load report, and etc. */ +} __KAL_ATTRIB_PACKED__; + +/* 7.4.7.1a 20/40 BSS Coexistence Management frame format */ +struct ACTION_20_40_COEXIST_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* BSS Coexistence Management frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + + /* 20/40 BSS coexistence element */ + struct IE_20_40_COEXIST rBssCoexist; + /* Intolerant channel report */ + struct IE_INTOLERANT_CHNL_REPORT rChnlReport; + +} __KAL_ATTRIB_PACKED__; + +#if CFG_SUPPORT_802_11W +/* 7.4.9 SA Query Management frame format */ +struct ACTION_SA_QUERY_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* BSS Coexistence Management frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + + uint8_t ucTransId[ACTION_SA_QUERY_TR_ID_LEN]; /* Transaction id */ + +} __KAL_ATTRIB_PACKED__; +#endif + +/* 7.4.10 Notify Channel Width Management frame format */ +struct ACTION_NOTIFY_CHNL_WIDTH_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* BSS Coexistence Management frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucChannelWidth; /* Channel Width */ +} __KAL_ATTRIB_PACKED__; + +/* 802.11v Wireless Network Management: Timing Measurement Request */ +struct ACTION_WNM_TIMING_MEAS_REQ_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Timing Measurement Request Management frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucTrigger; /* Trigger */ +} __KAL_ATTRIB_PACKED__; + +/* 802.11v Wireless Network Management: Timing Measurement */ +struct ACTION_UNPROTECTED_WNM_TIMING_MEAS_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Timing Measurement Management frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token */ + uint8_t ucFollowUpDialogToken; /* Follow Up Dialog Token */ + uint32_t u4ToD; /* Timestamp of Departure [10ns] */ + uint32_t u4ToA; /* Timestamp of Arrival [10ns] */ + uint8_t ucMaxToDErr; /* Maximum of ToD Error [10ns] */ + uint8_t ucMaxToAErr; /* Maximum of ToA Error [10ns] */ +} __KAL_ATTRIB_PACKED__; + +struct IE_WFA_OSEN { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucOui[3]; + uint8_t ucOuiType; + uint32_t u4GroupKeyCipherSuite; + uint16_t u2PairwiseKeyCipherSuiteCount; + uint8_t aucPairwiseKeyCipherSuite1[4]; +}; + +/* 8.5.23.4 Operating Mode Notification frame format */ +struct ACTION_OP_MODE_NOTIFICATION_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Operating Mode Notification frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucOperatingMode; /* Operating Mode */ +} __KAL_ATTRIB_PACKED__; + +/* 8.5.12.3 SM Power Save frame format */ +struct ACTION_SM_POWER_SAVE_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* SM power save frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucSmPowerCtrl; /* SM Power Control (see 8.4.1.22) */ +} __KAL_ATTRIB_PACKED__; + +/* 8.5.12.2 Notify Channel Width frame format */ +struct ACTION_NOTIFY_CHANNEL_WIDTH_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* SM power save frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucChannelWidth; /* Channel Width (see 8.4.1.21) */ +} __KAL_ATTRIB_PACKED__; + +#if (CFG_SUPPORT_TWT == 1) +/* 11ax TWT Setup frame format */ +struct _ACTION_TWT_SETUP_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* TWT Setup frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token */ + struct _IE_TWT_T rTWT; /* TWT element */ +} __KAL_ATTRIB_PACKED__; + +/* 11ax TWT Teardown frame format */ +struct _ACTION_TWT_TEARDOWN_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* TWT Teardown frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucTWTFlow; /* TWT Flow */ +} __KAL_ATTRIB_PACKED__; + +/* 11ax TWT Information frame format */ +struct _ACTION_TWT_INFO_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* TWT Information frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucNextTWTCtrl; + uint8_t aucNextTWT[0]; +} __KAL_ATTRIB_PACKED__; +#endif + +/* 3 Information Elements from WFA. */ +struct IE_WFA { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucOui[3]; + uint8_t ucOuiType; + uint8_t aucOuiSubTypeVersion[2]; + /*!< Please be noted. WPA defines a 16 bit field version */ + /* instead of one subtype field and one version field */ +} __KAL_ATTRIB_PACKED__; + +#if CFG_SUPPORT_PASSPOINT +/* HS20 3.1 - HS 2.0 Indication Information Element */ +struct IE_HS20_INDICATION { + uint8_t ucId; /* Element ID */ + uint8_t ucLength; /* Length */ + uint8_t aucOui[3]; /* OUI */ + uint8_t ucType; /* Type */ + uint8_t ucHotspotConfig; /* Hotspot Configuration */ +} __KAL_ATTRIB_PACKED__; +#endif /* CFG_SUPPORT_PASSPOINT */ + +/* WAPI Information element format */ +struct WAPI_INFO_ELEM { + uint8_t ucElemId; + uint8_t ucLength; + uint16_t u2Version; + uint16_t u2AKMSuiteCount; + uint32_t u4AKMSuite; + uint16_t u2PairSuiteCount; + uint32_t u4PairSuite; + uint32_t u4GroupSuite; + uint16_t u2WapiCap; +} __KAL_ATTRIB_PACKED__; + +/* Information Elements from MTK Synergies.*/ +struct IE_MTK_OUI { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucOui[3]; + uint8_t aucCapability[4]; + uint8_t aucInfoElem[1]; +} __KAL_ATTRIB_PACKED__; + +struct SUB_IE_BSS_TERM_DURATION { + uint8_t ucSubId; + uint8_t ucLength; + uint8_t aucTermTsf[8]; + uint16_t u2Duration; +} __KAL_ATTRIB_PACKED__; + +struct SUB_IE_BSS_CAND_PREFERENCE { + uint8_t ucSubId; + uint8_t ucLength; + uint8_t ucPreference; +} __KAL_ATTRIB_PACKED__; + +struct ACTION_BTM_QUERY_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* BSS Coexistence Management frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + + uint8_t ucDialogToken; + uint8_t ucQueryReason; + uint8_t *pucNeighborBss; +} __KAL_ATTRIB_PACKED__; + +struct ACTION_BTM_REQ_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* BSS Coexistence Management frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + + uint8_t ucDialogToken; + uint8_t ucRequestMode; + uint16_t u2DisassocTimer; + uint8_t ucValidityInterval; + uint8_t aucOptInfo[0]; + /* Optional: Bss Termination Duration(0~12 bytes), + ** Session Information URL, Bss Transition Candidate List + */ +} __KAL_ATTRIB_PACKED__; + +struct ACTION_BTM_RSP_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* BSS Coexistence Management frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + + uint8_t ucDialogToken; + uint8_t ucStatusCode; + uint8_t ucBssTermDelay; + uint8_t aucOptInfo[0]; + /* Optional Target BSSID and Transition Candidate Entry list */ +} __KAL_ATTRIB_PACKED__; + +struct IE_MOBILITY_DOMAIN { + uint8_t ucId; /* Element ID = 54 */ + uint8_t ucLength; /* Length is 3 */ + uint16_t u2MDID; + /* Bit 0: FT over DS; Bit 1: Resource Request Protocol Capbility, + ** others: reserved + */ + uint8_t ucBitMap; +} __KAL_ATTRIB_PACKED__; + +struct IE_FAST_TRANSITION { + uint8_t ucId; /* Element ID = 55 */ + uint8_t ucLength; /* Length is variable */ + /* Bit 0 ~ Bit 7: reserved; Bit 8 ~ Bit 15: IE count + ** used to calculate MIC, 0 means No MIC + */ + uint8_t ucMicCtrl; + uint8_t aucMic[16]; /* */ + uint8_t aucANonce[32]; /* Nonce of R1KH */ + uint8_t aucSNonce[32]; /* Nonce of S1KH */ + uint8_t aucOptParam[0]; +} __KAL_ATTRIB_PACKED__; + +struct SUB_IE_FAST_TRANSITION { + uint8_t ucSubId; /* 0, 4-255: reserved; 1: R1KH-ID; 2: GTK; 3: R0KH-ID + */ + uint8_t ucLength; /* bytes, R1KH-ID: 6; GTK: 15-42; R0KH-ID: 1-48 */ + uint8_t aucData[1]; +} __KAL_ATTRIB_PACKED__; + +struct SUB_IE_GTK { + uint8_t ucSubId; /* subId=2 */ + uint8_t ucLength; /* length is 15-42 */ + uint16_t u2KeyInfo; /* Bit0-Bit1: Key ID; Bit2-Bit15: reserved */ + uint8_t ucKeyLength; + uint8_t aucRsc[8]; + uint8_t aucKey[5]; +} __KAL_ATTRIB_PACKED__; + +/* 8.5.7.4 Link Measurement Request frame format */ +struct ACTION_LM_REQUEST_FRAME { + /* Link Measurement Request MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Link Measurement Request frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token */ + uint8_t ucTxPowerUsed; /* */ + uint8_t ucTxPowerMax; /* */ + uint8_t aucInfoElem[1]; /* subelements */ +} __KAL_ATTRIB_PACKED__; + +/* 8.5.7.5 Link Measurement Report frame format */ +struct ACTION_LM_REPORT_FRAME { + /* Link Measurement Report MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Link Measurement Report frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token */ + uint8_t aucTpcReportIE[4]; /* */ + uint8_t ucRxAntennaID; + uint8_t ucTxAntennaID; + uint8_t ucRCPI; + uint8_t ucRSNI; + uint8_t aucInfoElem[1]; /* subelements */ +} __KAL_ATTRIB_PACKED__; + +struct IE_REQUEST { + uint8_t ucId; /* ELEM_ID_REQUEST */ + uint8_t ucLength; /* 0 to 237 */ + uint8_t aucReqIds[0]; +} __KAL_ATTRIB_PACKED__; + +struct IE_AP_CHNL_REPORT { + uint8_t ucId; /* ELEM_ID_AP_CHANNEL_REPORT */ + uint8_t ucLength; /* 1 to 237 */ + uint8_t ucOpClass; + uint8_t aucChnlList[0]; +} __KAL_ATTRIB_PACKED__; + +struct SUB_IE_REPORTING_DETAIL { + uint8_t ucSubID; /* 2 */ + uint8_t ucLength; + /* 0: No fixed length fields or elemets. 1: all fixed length fields and + ** requested IEs 2: + */ + uint8_t ucDetailValue; +} __KAL_ATTRIB_PACKED__; + +struct IE_TSPEC_BODY { + uint8_t aucTsInfo[3]; /* TS info field */ + uint16_t u2NominalMSDUSize; /* nominal MSDU size */ + uint16_t u2MaxMSDUsize; /* maximum MSDU size */ + uint32_t u4MinSvcIntv; /* minimum service interval */ + uint32_t u4MaxSvcIntv; /* maximum service interval */ + uint32_t u4InactIntv; /* inactivity interval */ + uint32_t u4SpsIntv; /* suspension interval */ + uint32_t u4SvcStartTime; /* service start time */ + uint32_t u4MinDataRate; /* minimum Data rate */ + uint32_t u4MeanDataRate; /* mean data rate */ + uint32_t u4PeakDataRate; /* peak data rate */ + uint32_t u4MaxBurstSize; /* maximum burst size */ + uint32_t u4DelayBound; /* delay bound */ + uint32_t u4MinPHYRate; /* minimum PHY rate */ + uint16_t u2Sba; /* surplus bandwidth allowance */ + uint16_t u2MediumTime; /* medium time */ +} __KAL_ATTRIB_PACKED__; + +struct WMM_ACTION_TSPEC_FRAME { + /* DELTS MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* DELTS frame body */ + uint8_t ucCategory; /* Category, value is 17 */ + uint8_t ucAction; /* Action Value, value: 2, delts */ + uint8_t ucDlgToken; + uint8_t ucStatusCode; + uint8_t aucInfoElem[1]; +} __KAL_ATTRIB_PACKED__; + +/* 9.4.2.46 Multiple BSSID element */ +struct IE_MBSSID { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucMaxBSSIDIndicator; + uint8_t ucSubelements[1]; +} __KAL_ATTRIB_PACKED__; + +/* 9.4.2.74 Multiple BSSID-Index element */ +struct IE_MBSSID_INDEX { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucBSSIDIndex; + uint8_t ucDtimPeriod; + uint8_t ucDtimCount; +} __KAL_ATTRIB_PACKED__; + +#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) \ + ((int32_t)(((_rcpi) > RCPI_HIGH_BOUND ? \ + RCPI_HIGH_BOUND : (_rcpi)) >> 1) - NDBM_LOW_BOUND_FOR_RCPI) + +/* Convert the dBm to RCPI */ +#define dBm_TO_RCPI(_dbm) \ + (uint8_t)(((((int32_t)(_dbm) + NDBM_LOW_BOUND_FOR_RCPI) << 1) \ + > RCPI_HIGH_BOUND) ? RCPI_HIGH_BOUND : \ + ((((int32_t)(_dbm) + NDBM_LOW_BOUND_FOR_RCPI) << 1) \ + < RCPI_LOW_BOUND ? RCPI_LOW_BOUND : \ + (((int32_t)(_dbm) + NDBM_LOW_BOUND_FOR_RCPI) << 1))) + +/* Convert an unsigned char pointer to an information element pointer */ +#define IE_ID(fp) (((struct IE_HDR *) fp)->ucId) +#define IE_LEN(fp) (((struct IE_HDR *) fp)->ucLength) +#define IE_ID_EXT(fp) (((struct IE_HDR *) fp)->aucInfo[0]) +#define IE_SIZE(fp) (ELEM_HDR_LEN + IE_LEN(fp)) + +#define SSID_IE(fp) ((struct IE_SSID *) fp) + +#define SUP_RATES_IE(fp) ((struct IE_SUPPORTED_RATE *) fp) + +#define SUP_RATES_IOT_IE(fp) ((struct IE_SUPPORTED_RATE_IOT *) fp) + +#define DS_PARAM_IE(fp) ((struct IE_DS_PARAM_SET *) fp) + +#define TIM_IE(fp) ((struct IE_TIM *) fp) + +#define IBSS_PARAM_IE(fp) ((struct IE_IBSS_PARAM_SET *) fp) + +#define ERP_INFO_IE(fp) ((struct IE_ERP *) fp) + +#define EXT_SUP_RATES_IE(fp) ((struct IE_EXT_SUPPORTED_RATE *) fp) + +#define WFA_IE(fp) ((struct IE_WFA *) fp) + +#if CFG_SUPPORT_802_11D +#define COUNTRY_IE(fp) ((struct IE_COUNTRY *) fp) +#endif + +#define EXT_CAP_IE(fp) ((struct IE_EXT_CAP *) fp) + +#define HT_CAP_IE(fp) ((struct IE_HT_CAP *) fp) + +#define POWER_CAP_IE(fp) ((struct IE_POWER_CAP *) fp) + +#define SUP_CH_IE(fp) ((struct IE_SUPPORTED_CHANNELS *) fp) + +#define HT_OP_IE(fp) ((struct IE_HT_OP *) fp) + +#define VHT_CAP_IE(fp) ((struct IE_VHT_CAP *) fp) + +#define VHT_OP_IE(fp) ((struct IE_VHT_OP *) fp) + +#define OBSS_SCAN_PARAM_IE(fp) ((struct IE_OBSS_SCAN_PARAM *) fp) + +#define BSS_20_40_COEXIST_IE(fp) ((struct IE_20_40_COEXIST *) fp) + +#define SUP_OPERATING_CLASS_IE(fp) ((struct IE_SUP_OPERATING_CLASS *) fp) + +#define QUIET_IE(fp) ((struct IE_QUIET *) fp) + +#define MTK_OUI_IE(fp) ((struct IE_MTK_OUI *) fp) + +#define CSA_IE(fp) ((struct IE_CHANNEL_SWITCH *) fp) + +#define SUPPORTED_CHANNELS_IE(fp) ((struct IE_SUPPORTED_CHANNELS *)fp) +#define TIMEOUT_INTERVAL_IE(fp) ((struct IE_TIMEOUT_INTERVAL *)fp) + +#define SM_TPC_REQ_IE(fp) ((struct IE_TPC_REQ *) fp) +#define SM_TPC_REP_IE(fp) ((struct IE_TPC_REPORT *) fp) +#define SM_MEASUREMENT_REQ_IE(fp) ((struct IE_MEASUREMENT_REQ *) fp) +#define SM_MEASUREMENT_REP_IE(fp) ((struct IE_MEASUREMENT_REPORT *) fp) +#define SM_BASIC_REQ_IE(fp) ((struct SM_BASIC_REQ *) fp) + +#define MBSSID_IE(fp) ((struct IE_MBSSID *) fp) +#define MBSSID_INDEX_IE(fp) ((struct IE_MBSSID_INDEX *) fp) + +/* The macro to check if the MAC address is B/MCAST Address */ +#define IS_BMCAST_MAC_ADDR(_pucDestAddr) \ + ((u_int8_t) (((uint8_t *)(_pucDestAddr))[0] & BIT(0))) + +/* The macro to check if the MAC address is UCAST Address */ +#define IS_UCAST_MAC_ADDR(_pucDestAddr) \ + ((u_int8_t) !(((uint8_t *)(_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 > ELEM_MAX_LEN_SSID) \ + ? ELEM_MAX_LEN_SSID : ucSrcSsidLen; \ + if (ucDestSsidLen) { \ + kalMemCopy(pucDestSsid, pucSrcSsid, ucDestSsidLen); \ + } \ + } while (FALSE) + +/* The macro to copy the IE */ +#define COPY_IE(pucDestIE, pucSrcIE) \ + do { \ + kalMemCopy((uint8_t *)pucDestIE, \ + (uint8_t *)pucSrcIE,\ + IE_SIZE(pucSrcIE)); \ + } while (FALSE) + +#define IE_FOR_EACH(_pucIEsBuf, _u2IEsBufLen, _u2Offset) \ +for ((_u2Offset) = 0; \ + ((((_u2Offset) + 2) <= (_u2IEsBufLen)) && \ + (((_u2Offset) + IE_SIZE(_pucIEsBuf)) <= (_u2IEsBufLen))); \ + (_u2Offset) += IE_SIZE(_pucIEsBuf), (_pucIEsBuf) += IE_SIZE(_pucIEsBuf)) + +#define SET_EXT_CAP(_aucField, _ucFieldLength, _ucBit) \ +do { \ + if ((_ucBit) < ((_ucFieldLength) * 8)) { \ + uint8_t *aucExtCap = (uint8_t *)(_aucField); \ + ((aucExtCap)[(_ucBit) / 8]) |= BIT((_ucBit) % 8); \ + } \ +} while (FALSE) + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _MAC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/mt66xx_reg.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/mt66xx_reg.h new file mode 100644 index 0000000000000..9ea18667eb2cc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/mt66xx_reg.h @@ -0,0 +1,1437 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "mt66xx_reg.h" + * \brief The common register definition of MT6630 + * + * N/A + */ + + + +#ifndef _MT66XX_REG_H +#define _MT66XX_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 + ******************************************************************************* + */ +#ifdef MT6632 +extern struct mt66xx_hif_driver_data mt66xx_driver_data_mt6632; +#endif /* MT6632 */ +#ifdef MT7668 +extern struct mt66xx_hif_driver_data mt66xx_driver_data_mt7668; +#endif /* MT7668 */ +#ifdef MT7663 +extern struct mt66xx_hif_driver_data mt66xx_driver_data_mt7663; +#endif /* MT7663 */ +#ifdef CONNAC +extern struct mt66xx_hif_driver_data mt66xx_driver_data_connac; +#endif /* CONNAC */ +#ifdef CONNAC2X2 +extern struct mt66xx_hif_driver_data mt66xx_driver_data_connac2x2; +#endif /* CONNAC2X2 */ +#ifdef UT_TEST_MODE +extern struct mt66xx_hif_driver_data mt66xx_driver_data_ut; +#endif /* UT_TEST_MODE */ +#ifdef MT7915 +extern struct mt66xx_hif_driver_data mt66xx_driver_data_mt7915; +#endif /* MT7915 */ +#ifdef SOC3_0 +extern struct mt66xx_hif_driver_data mt66xx_driver_data_soc3_0; +#endif /* SOC3_0 */ +#ifdef MT7961 +extern struct mt66xx_hif_driver_data mt66xx_driver_data_mt7961; +#endif /* MT7961 */ + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +/* 1 MT6630 MCR Definition */ + +/* 2 Host Interface */ + +/* #define TOP_CFG_BASE 0x0000 */ +#define TOP_CFG_BASE 0x80020000 +#define TOP_RGU_BASE 0x81020000 +#define TOP_CFG_AON_base 0x81021000 +#define MCU_CFG_BASE 0x80000000 + +#define TOP_HVR (TOP_CFG_BASE + 0x1000) +#define HW_VER_MASK (0xffff) +#define GET_HW_VER(p) (((p) & HW_VER_MASK)) +#define RESC_CID_MASK (0xf << 28) +#define GET_RESC_CID(p) (((p) & RESC_CID_MASK) >> 28) + +#define TOP_FVR (TOP_CFG_BASE + 0x1004) +#define FW_VER_MASK (0xffff) +#define GET_FW_VER(p) (((p) & FW_VER_MASK)) + +#define TOP_HCR (TOP_CFG_BASE + 0x1008) +#define HW_CODE_MASK (0xffff) +#define GET_HW_CODE(p) (((p) & HW_CODE_MASK)) + +#define STRAP_STA (TOP_CFG_BASE + 0x1010) +#define XTAL_SEL_MASK (0x3) +#define GET_XTAL_SEL(p) (((p) & XTAL_SEL_MASK)) +#define EEPROM_SEL (1 << 2) +#define GET_EEPROM_SEL(p) (((p) & EEPROM_SEL) >> 2) +#define CO_CLOCK_SEL (1 << 8) +#define GET_CO_CLOCK_SEL(p) (((p) & CO_CLOCK_SEL) >> 8) +#define ONE_ANT (1 << 24) +#define GET_ONE_ANT(p) (((p) & ONE_ANT) >> 24) +#define USB_MODE (1 << 25) +#define GET_USB_MODE(p) (((p) & USB_MODE) >> 25) + +#define TOP_MISC2 (TOP_CFG_BASE + 0x1134) + +#define TOP_CKGEN2_CR_PMIC_CK_MANUAL (TOP_CFG_AON_base + 0x00000108) +#define TOP_CKGEN2_CR_PMIC_CK_MANUAL_MASK 0x00080000 + +#define MTK_CHIP_REV 0x00006632 + +#define WIFI_RGU_SW_SYNC0 (TOP_RGU_BASE + 0x1250) +#define WIFI_RGU_SYNC0_RDY_OFFSET (0) +#define MCU_CFG_PCIE_REMAP1 (MCU_CFG_BASE + 0x0500) +#define PCIE_REMAP1_OFFSET (18) +#define PCIE_REMAP1_MASK (BITS(18, 31)) +#define PCIE_REMAP1_BUS_ADDR (0x40000) +#define MCU_CFG_PCIE_REMAP2 (MCU_CFG_BASE + 0x0504) +#define PCIE_REMAP2_OFFSET (19) +#define PCIE_REMAP2_MASK (BITS(19, 31)) +#define PCIE_REMAP2_BUS_ADDR (0x80000) + + + +/* UMAC Register */ +#define UMAC_PLE_CR_CFG_BASE_ADDR 0x82060000 +#define UMAC_PSE_CR_CFG_BASE_ADDR 0x82068000 + +#define UMAC_PSE_PLE_CR_ADDR_DIFF \ + (UMAC_PSE_CR_CFG_BASE_ADDR - UMAC_PLE_CR_CFG_BASE_ADDR) +#define UMAC_PSE_CR_BITMAP_OFFSET 15 +#define UMAC_PSE_PLE_ADDR_DIFF_MAR(_x) \ + (_x << UMAC_PSE_CR_BITMAP_OFFSET) + + +#define UMAC_PLE_BASE_ADDRESS (0xa << 28) + +#define UMAC_PSE_BASE_ADDRESS (0xb << 28) + +#define UMAC_FID_SHIFT_16_BIT_VM_MAP 16 + +#define UMAC_BASE(_x) \ + (UMAC_PLE_CR_CFG_BASE_ADDR | (_x << UMAC_PSE_CR_BITMAP_OFFSET)) + +#define UMAC_RESET(_x) (UMAC_BASE(_x) + 0x00000000) + +#define UMAC_INT_CR4_EN_MASK(_x) (UMAC_BASE(_x) + 0x00000004) +#define UMAC_INT_CR4_STS(_x) (UMAC_BASE(_x) + 0x00000008) +#define UMAC_INT_CR4_ERR_RES(_x) (UMAC_BASE(_x) + 0x0000000C) +#define UMAC_INT_CR4_ERR_MASK(_x) (UMAC_BASE(_x) + 0x00000010) + + + +#define UMAC_PBUF_CTRL(_x) (UMAC_BASE(_x) + 0x00000014) + +#define UMAC_CHIP_ID_VER(_x) (UMAC_BASE(_x) + 0x00000018) + +#define UMAC_TIMER_CNF(_x) (UMAC_BASE(_x) + 0x0000001C) + +#define UMAC_INT_N9_EN_MASK(_x) (UMAC_BASE(_x) + 0x00000020) +#define UMAC_INT_N9_STS(_x) (UMAC_BASE(_x) + 0x00000024) +#define UMAC_INT_N9_ERR_STS(_x) (UMAC_BASE(_x) + 0x00000028) +#define UMAC_INT_N9_ERR_MASK(_x) (UMAC_BASE(_x) + 0x0000002C) +#define UMAC_IGNORE_BUSY_EN_MASK(_x) (UMAC_BASE(_x) + 0x0000038C) + +#define UMAC_RELEASE_CTRL(_x) (UMAC_BASE(_x) + 0x00000030) + +#define UMAC_HIF_REPROT(_x) (UMAC_BASE(_x) + 0x00000034) + + +#define UMAC_C_GET_FID_0(_x) (UMAC_BASE(_x) + 0x00000040) +#define UMAC_C_GET_FID_1(_x) (UMAC_BASE(_x) + 0x00000044) + +#define UMAC_C_EN_QUEUE_0(_x) (UMAC_BASE(_x) + 0x00000060) +#define UMAC_C_EN_QUEUE_1(_x) (UMAC_BASE(_x) + 0x00000064) +#define UMAC_C_EN_QUEUE_2(_x) (UMAC_BASE(_x) + 0x00000068) + + +#define UMAC_C_DE_QUEUE_0(_x) (UMAC_BASE(_x) + 0x00000080) +#define UMAC_C_DE_QUEUE_1(_x) (UMAC_BASE(_x) + 0x00000084) +#define UMAC_C_DE_QUEUE_2(_x) (UMAC_BASE(_x) + 0x00000088) +#define UMAC_C_DE_QUEUE_3(_x) (UMAC_BASE(_x) + 0x0000008C) + +#define UMAC_ALLOCATE_0(_x) (UMAC_BASE(_x) + 0x000000A0) +#define UMAC_ALLOCATE_1(_x) (UMAC_BASE(_x) + 0x000000A4) +#define UMAC_ALLOCATE_2(_x) (UMAC_BASE(_x) + 0x000000A8) + +#define UMAC_QUEUE_EMPTY(_x) (UMAC_BASE(_x) + 0x000000B0) + +/* 0x820680B4 QUEUE_EMPTY_MASK Queue empty status mask register, + * 7615 E3 eco item only PSE with this setting, but ple + */ +#define UMAC_QUEUE_EMPTY_MASK \ + (UMAC_BASE(UMAC_PSE_CFG_POOL_INDEX) + 0x000000B4) + +#define UMAC_TO_CR4_INT(_x) (UMAC_BASE(_x) + 0x000000e0) +#define UMAC_TO_N9_INT(_x) (UMAC_BASE(_x) + 0x000000f0) + + +#define UMAC_FREEPG_CNT(_x) (UMAC_BASE(_x) + 0x00000100) + +#define UMAC_FREEPG_HEAD_TAIL(_x) (UMAC_BASE(_x) + 0x00000104) + + +#define UMAC_PG_HIF0_GROUP(_x) (UMAC_BASE(_x) + 0x00000110) +#define UMAC_HIF0_PG_INFO(_x) (UMAC_BASE(_x) + 0x00000114) + +#define UMAC_PG_HIF1_GROUP(_x) (UMAC_BASE(_x) + 0x00000118) +#define UMAC_HIF1_PG_INFO(_x) (UMAC_BASE(_x) + 0x0000011C) + +#define UMAC_PG_CPU_GROUP(_x) (UMAC_BASE(_x) + 0x00000150) +#define UMAC_CPU_PG_INFO(_x) (UMAC_BASE(_x) + 0x00000154) + + +#define UMAC_PG_LMAC0_GROUP(_x) (UMAC_BASE(_x) + 0x00000170) +#define UMAC_LMAC0_PG_INFO(_x) (UMAC_BASE(_x) + 0x00000174) + +#define UMAC_PG_LMAC1_GROUP(_x) (UMAC_BASE(_x) + 0x00000178) +#define UMAC_LMAC1_PG_INFO(_x) (UMAC_BASE(_x) + 0x0000017C) + + +#define UMAC_PG_LMAC2_GROUP(_x) (UMAC_BASE(_x) + 0x00000180) +#define UMAC_LMAC2_PG_INFO(_x) (UMAC_BASE(_x) + 0x00000184) + +#define UMAC_PG_PLE_GROUP(_x) (UMAC_BASE(_x) + 0x00000190) +#define UMAC_PLE_PG_INFO(_x) (UMAC_BASE(_x) + 0x00000194) + + +#define UMAC_RL_BUF_CTRL_0(_x) (UMAC_BASE(_x) + 0x000001A0) +#define UMAC_RL_BUF_CTRL_1(_x) (UMAC_BASE(_x) + 0x000001A4) + +#define UMAC_FL_QUE_CTRL_0(_x) (UMAC_BASE(_x) + 0x000001B0) +#define UMAC_FL_QUE_CTRL_1(_x) (UMAC_BASE(_x) + 0x000001B4) +#define UMAC_FL_QUE_CTRL_2(_x) (UMAC_BASE(_x) + 0x000001B8) +#define UMAC_FL_QUE_CTRL_3(_x) (UMAC_BASE(_x) + 0x000001BC) + +#define UMAC_HIF_ENQ_PKT_NUM(_x) (UMAC_BASE(_x) + 0x000001F0) +#define UMAC_CPU_ENQ_PKT_NUM(_x) (UMAC_BASE(_x) + 0x000001F4) +#define UMAC_RLS_MSDU_PKT_NUM(_x) (UMAC_BASE(_x) + 0x000001F8) +#define UMAC_HOST_REPORT_NUM(_x) (UMAC_BASE(_x) + 0x000001FC) + +#define UMAC_PL_QUE_CTRL_0(_x) (UMAC_BASE(_x) + 0x000001C0) + +#define UMAC_TP_HIF_EN(_x) (UMAC_BASE(_x) + 0x00000200) + +#define UMAC_TP_HIF_Q_CTRL0(_x) (UMAC_BASE(_x) + 0x00000204) +#define UMAC_TP_HIF_Q_CTRL1(_x) (UMAC_BASE(_x) + 0x00000208) +#define UMAC_TP_HIF_Q_CTRL2(_x) (UMAC_BASE(_x) + 0x0000020C) + +#define UMAC_TP_HIF_ALLOC0(_x) (UMAC_BASE(_x) + 0x00000210) +#define UMAC_TP_HIF_ALLOC1(_x) (UMAC_BASE(_x) + 0x00000214) + +#define UMAC_TP_HIF_OPER0(_x) (UMAC_BASE(_x) + 0x00000218) +#define UMAC_TP_HIF_OPER1(_x) (UMAC_BASE(_x) + 0x0000021C) + + +#define UMAC_TP_LMAC_EN(_x) (UMAC_BASE(_x) + 0x00000220) + +#define UMAC_TP_LMAC_Q_CTRL0(_x) (UMAC_BASE(_x) + 0x00000224) +#define UMAC_TP_LMAC_Q_CTRL1(_x) (UMAC_BASE(_x) + 0x00000228) +#define UMAC_TP_LMAC_Q_CTRL2(_x) (UMAC_BASE(_x) + 0x0000022C) + +#define UMAC_TP_LMAC_ALLOC0(_x) (UMAC_BASE(_x) + 0x00000230) +#define UMAC_TP_LMAC_ALLOC1(_x) (UMAC_BASE(_x) + 0x00000234) + +#define UMAC_TP_LMAC_OPER0(_x) (UMAC_BASE(_x) + 0x00000238) +#define UMAC_TP_LMAC_OPER1(_x) (UMAC_BASE(_x) + 0x0000023C) + +#define UMAC_STATE_IDLE_CTL(_x) (UMAC_BASE(_x) + 0x0000024C) + +#define UMAC_DIS_STA_MAP0(_x) (UMAC_BASE(_x) + 0x00000260) +#define UMAC_DIS_STA_MAP1(_x) (UMAC_BASE(_x) + 0x00000264) +#define UMAC_DIS_STA_MAP2(_x) (UMAC_BASE(_x) + 0x00000268) +#define UMAC_DIS_STA_MAP3(_x) (UMAC_BASE(_x) + 0x0000026c) + +#define UMAC_AC0_QUEUE_EMPTY0(_x) (UMAC_BASE(_x) + 0x00000300) +#define UMAC_AC0_QUEUE_EMPTY1(_x) (UMAC_BASE(_x) + 0x00000304) +#define UMAC_AC0_QUEUE_EMPTY2(_x) (UMAC_BASE(_x) + 0x00000308) +#define UMAC_AC0_QUEUE_EMPTY3(_x) (UMAC_BASE(_x) + 0x0000030C) + +#define UMAC_AC1_QUEUE_EMPTY0(_x) (UMAC_BASE(_x) + 0x00000310) +#define UMAC_AC1_QUEUE_EMPTY1(_x) (UMAC_BASE(_x) + 0x00000314) +#define UMAC_AC1_QUEUE_EMPTY2(_x) (UMAC_BASE(_x) + 0x00000318) +#define UMAC_AC1_QUEUE_EMPTY3(_x) (UMAC_BASE(_x) + 0x0000031C) + +#define UMAC_AC2_QUEUE_EMPTY0(_x) (UMAC_BASE(_x) + 0x00000320) +#define UMAC_AC2_QUEUE_EMPTY1(_x) (UMAC_BASE(_x) + 0x00000324) +#define UMAC_AC2_QUEUE_EMPTY2(_x) (UMAC_BASE(_x) + 0x00000328) +#define UMAC_AC2_QUEUE_EMPTY3(_x) (UMAC_BASE(_x) + 0x0000032C) + +#define UMAC_AC3_QUEUE_EMPTY0(_x) (UMAC_BASE(_x) + 0x00000330) +#define UMAC_AC3_QUEUE_EMPTY1(_x) (UMAC_BASE(_x) + 0x00000334) +#define UMAC_AC3_QUEUE_EMPTY2(_x) (UMAC_BASE(_x) + 0x00000338) +#define UMAC_AC3_QUEUE_EMPTY3(_x) (UMAC_BASE(_x) + 0x0000033C) + +#define UMAC_QUEUE_EMPTY_MASK \ + (UMAC_BASE(UMAC_PSE_CFG_POOL_INDEX) + 0x000000B4) + +/* BSS PS INT */ +#define UMAC_N9_BSS_PS_INT_EN \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000000F4) +#define UMAC_N9_BSS_PS_INT_STS \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000000F8) + +/* CR for VoW and BW Ctrl */ + +#define UMAC_DRR_TABLE_CTRL0 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000388) + +#define UMAC_DRR_TABLE_WDATA0 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000340) +#define UMAC_DRR_TABLE_WDATA1 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000344) +#define UMAC_DRR_TABLE_WDATA2 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000348) +#define UMAC_DRR_TABLE_WDATA3 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x0000034C) + + +#define UMAC_DRR_TABLE_RDATA0 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000350) +#define UMAC_DRR_TABLE_RDATA1 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000354) +#define UMAC_DRR_TABLE_RDATA2 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000358) +#define UMAC_DRR_TABLE_RDATA3 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x0000035C) + + +#define UMAC_STATION_PAUSE_0 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000360) +#define UMAC_STATION_PAUSE_1 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000364) +#define UMAC_STATION_PAUSE_2 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000368) +#define UMAC_STATION_PAUSE_3 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x0000036C) +#define UMAC_VOW_ENABLE \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000370) +#define UMAC_AIR_TIME_DRR_SIZE \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000374) +#define UMAC_CHECK_TIME_TOKEN \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000378) +#define UMAC_CHECK_LENGTH_TOKEN \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x0000037C) +#define UMAC_WDRR0 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000380) +#define UMAC_WDRR1 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000384) + +#define UMAC_VOW_CTRL1 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x0000038C) + +#define UMAC_VOW_DBG_MUX \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000003A0) +#define UMAC_AIRTIME_DBG_INFO0 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000003A4) +#define UMAC_AIRTIME_DBG_INFO1 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000003A8) + +#define UMAC_BW_DBG_INFO \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000003AC) + +#define UMAC_BW_WDRR0 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000003B0) +#define UMAC_BW_WDRR1 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000003B4) +#define UMAC_BW_WDRR2 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000003B8) +#define UMAC_BW_WDRR3 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000003BC) +/* UMAC Register */ + + +#if defined(_HIF_USB) + +#define WIFI_CFG_SW_SYNC0 (TOP_CFG_BASE + 0x1128) +#define WIFI_CFG_SYNC0_RDY_OFFSET (16) + +/* UDMA register */ +#define UDMA_BASE 0x50029000 +#define UDMA_TX_QSEL (UDMA_BASE + 0x8) +#define FW_DL_EN (1 << 3) + +#define UDMA_RESET (UDMA_BASE + 0x14) + +#define UDMA_WLCFG_1 (UDMA_BASE + 0xc) +#define UDMA_WLCFG_1_TX_TMOUT_LMT_MASK (0xfffff << 8) +#define UDMA_WLCFG_1_TX_TMOUT_LMT(p) (((p) & 0xfffff) << 8) +#define UDMA_WLCFG_1_RX_AGG_PKT_LMT_MASK (0xff << 0) +#define UDMA_WLCFG_1_RX_AGG_PKT_LMT(p) (((p) & 0xff) << 0) + +#define UDMA_WLCFG_0 (UDMA_BASE + 0x18) +#define UDMA_WLCFG_0_TX_BT_SIZE_MASK (0x07 << 27) +#define UDMA_WLCFG_0_TX_BT_SIZE(p) (((p) & 0x07) << 27) +#define UDMA_WLCFG_0_RX_BT_SIZE_MASK (0x07 << 24) +#define UDMA_WLCFG_0_RX_BT_SIZE(p) (((p) & 0x07) << 24) +#define UDMA_WLCFG_0_TX_EN_MASK (0x1 << 23) +#define UDMA_WLCFG_0_TX_EN(p) (((p) & 0x1) << 23) +#define UDMA_WLCFG_0_RX_EN_MASK (0x1 << 22) +#define UDMA_WLCFG_0_RX_EN(p) (((p) & 0x1) << 22) +#define UDMA_WLCFG_0_RX_AGG_EN_MASK (0x1 << 21) +#define UDMA_WLCFG_0_RX_AGG_EN(p) (((p) & 0x1) << 21) +#define UDMA_WLCFG_0_LPK_EN_MASK (0x1 << 20) +#define UDMA_WLCFG_0_LPK_EN(p) (((p) & 0x1) << 20) +#define UDMA_WLCFG_0_RX_MPSZ_PAD0_MASK (0x1 << 18) +#define UDMA_WLCFG_0_RX_MPSZ_PAD0(p) (((p) & 0x1) << 18) +#define UDMA_WLCFG_0_RX_AGG_LMT_MASK (0xff << 8) +#define UDMA_WLCFG_0_RX_AGG_LMT(p) (((p) & 0xff) << 8) +#define UDMA_WLCFG_0_RX_AGG_TO_MASK (0xff << 0) +#define UDMA_WLCFG_0_RX_AGG_TO(p) (((p) & 0xff) << 0) + +#define PP_R_RXCUTDISP0 (0x8206C054) +#define PP_R_RXCUTDISP0_CT_EN_MASK (0x1 << 0) +#define PP_R_RXCUTDISP0_CT_EN(p) (((p) & 0x1) << 0) +#define PP_R_RXCUTDISP0_CR4_EN_MASK (0x1 << 1) +#define PP_R_RXCUTDISP0_CR4_EN(p) (((p) & 0x1) << 1) +#define PP_R_RXCUTDISP0_START_OFFSET_MASK (0x3fff << 2) +#define PP_R_RXCUTDISP0_START_OFFSET(p) (((p) & 0x3fff) << 2) +#define PP_R_RXCUTDISP0_END_OFFSET_MASK (0x3fff << 18) +#define PP_R_RXCUTDISP0_END_OFFSET(p) (((p) & 0x3fff) << 18) + + +#elif defined(_HIF_PCIE) || defined(_HIF_AXI) +#define RTC_TOP_BASE 0x0000 + +#define RTC_TOP_MISC2 (RTC_TOP_BASE + 0x1128) + +#define TOP_HIF_BASE 0x0000 +#define TOP_HW_VERSION 0x1000 +#define TOP_HW_CONTROL 0x1008 + +#define WIFI_CFG_SW_SYNC0 RTC_TOP_MISC2 +#define WIFI_CFG_SYNC0_RDY_OFFSET (16) + +#define PCIE_HIF_BASE 0x4000 +#define PCIE_NEW_HIF_BASE 0x7c030000 + +/* HIF Sys Revision */ +#define HIF_SYS_REV (PCIE_HIF_BASE + 0x0000) + +/* Check Enter Slepp Mode Register */ +#define CONN_DUMMY_CR (PCIE_HIF_BASE + 0x00A8) + +#define CONN_HIF_RST (PCIE_HIF_BASE + 0x0100) + +#define WPDMA_FIFO_TEST_MOD (PCIE_HIF_BASE + 0x0140) + +#define WPDMA_APSRC_ACK_LOCK_SLPPROT (PCIE_HIF_BASE + 0x0160) + +/* HIF Low Power Control Host Register */ +#define CFG_PCIE_LPCR_HOST (PCIE_HIF_BASE + 0x01F0) + +/* HIF Low Power Control Fw Register */ +#define CFG_PCIE_LPCR_FW (PCIE_HIF_BASE + 0x01F4) + +/* Interrupt Status */ +#define WPDMA_INT_STA (PCIE_HIF_BASE + 0x0200) + +/* Interrupt Mask */ +#define WPDMA_INT_MSK (PCIE_HIF_BASE + 0x0204) + +/* Global Configuration */ +#define WPDMA_GLO_CFG (PCIE_HIF_BASE + 0x0208) + +/* Pointer Reset */ +#define WPDMA_RST_PTR (PCIE_HIF_BASE + 0x020C) + +/* Configuration for WPDMA Delayed Interrupt */ +#define WPDMA_DELAY_INT_CFG (PCIE_HIF_BASE + 0x0210) + +#define WPDMA_PAUSE_RX_Q_TH10 (PCIE_HIF_BASE + 0x0260) +#define WPDMA_PAUSE_RX_Q_TH32 (PCIE_HIF_BASE + 0x0264) +#define WPDMA_PAUSE_RX_Q_TH0 1 +#define WPDMA_PAUSE_RX_Q_TH1 1 +#define WPDMA_PAUSE_RX_Q_TH2 1 +#define WPDMA_PAUSE_RX_Q_TH3 1 +#define WPDMA_PAUSE_RX_Q_TH0_MASK 0x00000FFF +#define WPDMA_PAUSE_RX_Q_TH1_MASK 0x0FFF0000 +#define WPDMA_PAUSE_RX_Q_TH2_MASK 0x00000FFF +#define WPDMA_PAUSE_RX_Q_TH3_MASK 0x0FFF0000 +#define WPDMA_PAUSE_RX_Q_TH0_SHFT 0 +#define WPDMA_PAUSE_RX_Q_TH1_SHFT 16 +#define WPDMA_PAUSE_RX_Q_TH2_SHFT 0 +#define WPDMA_PAUSE_RX_Q_TH3_SHFT 16 + +/* TX Ring0 Control 0 */ +#define WPDMA_TX_RING0_CTRL0 (PCIE_HIF_BASE + 0x0300) + +/* TX Ring0 Control 1 */ +#define WPDMA_TX_RING0_CTRL1 (PCIE_HIF_BASE + 0x0304) + +/* TX Ring0 Control 2 */ +#define WPDMA_TX_RING0_CTRL2 (PCIE_HIF_BASE + 0x0308) + +/* TX Ring0 Control 3 */ +#define WPDMA_TX_RING0_CTRL3 (PCIE_HIF_BASE + 0x030C) + +/* RX Ring0 Control 0 */ +#define WPDMA_RX_RING0_CTRL0 (PCIE_HIF_BASE + 0x0400) + +/* RX Ring0 Control 1 */ +#define WPDMA_RX_RING0_CTRL1 (PCIE_HIF_BASE + 0x0404) + +/* RX Ring0 Control 2 */ +#define WPDMA_RX_RING0_CTRL2 (PCIE_HIF_BASE + 0x0408) + +/* RX Ring0 Control 3 */ +#define WPDMA_RX_RING0_CTRL3 (PCIE_HIF_BASE + 0x040C) + +/* TX RING more than 32bits extension */ +#define WPDMA_TX_RING0_BASE_PTR_EXT (PCIE_HIF_BASE + 0x0500) + +/* RX RING more than 32bits extension */ +#define WPDMA_RX_RING0_BASE_PTR_EXT (PCIE_HIF_BASE + 0x0580) + +#define MT_WPDMA_GLO_CFG_1 (PCIE_HIF_BASE + 0x0500) + +#define MT_WPDMA_TX_PRE_CFG (PCIE_HIF_BASE + 0x0510) + +#define MT_WPDMA_RX_PRE_CFG (PCIE_HIF_BASE + 0x0520) + +#define MT_WPDMA_ABT_CFG (PCIE_HIF_BASE + 0x0530) + +#define MT_WPDMA_ABT_CFG1 (PCIE_HIF_BASE + 0x0534) + +#define MT_PCIE_IRQ_ENABLE (PCIE_NEW_HIF_BASE + 0x0188) + +#define MD_INT_STA (PCIE_HIF_BASE + 0x01C0) +#define MD_WPDMA_GLO_CFG (PCIE_HIF_BASE + 0x01D0) +#define MD_INT_ENA (PCIE_HIF_BASE + 0x01D4) +#define MD_WPDMA_DLY_INIT_CFG (PCIE_HIF_BASE + 0x01D8) +#define MD_WPDMA_MISC (PCIE_HIF_BASE + 0x01DC) + +#define CONN_HIF_PDMA_CSR_PDMA_SLP_PROT_ADDR (PCIE_HIF_BASE + 0x154) +#define CONN_HIF_PDMA_CSR_PDMA_SLP_PROT_PDMA_AXI_SLPPROT_ENABLE_MASK BIT(0) +#define CONN_HIF_PDMA_CSR_PDMA_SLP_PROT_PDMA_AXI_SLPPROT_RDY_MASK BIT(16) + +/* WPDMA_INT_STA */ +union WPDMA_INT_STA_STRUCT { + struct { + uint32_t rx_done_0:1; + uint32_t rx_done_1:1; + uint32_t err_det_int_0:1; + uint32_t err_det_int_1:1; + uint32_t tx_done:16; + uint32_t rx_coherent:1; + uint32_t tx_coherent:1; + uint32_t rx_dly_int:1; + uint32_t tx_dly_int:1; + uint32_t wf_mac_int_0:1; + uint32_t wf_mac_int_1:1; + uint32_t wf_mac_int_2:1; + uint32_t wf_mac_int_3:1; + uint32_t wf_mac_int_4:1; + uint32_t wf_mac_int_5:1; + uint32_t mcu_cmd_int:1; + uint32_t fw_clr_own:1; + } field; + + struct { + uint32_t rx_done_0:1; + uint32_t rx_done_1:1; + uint32_t rx_done_2:1; + uint32_t rx_done_3:1; + uint32_t tx_done:16; + uint32_t rx_coherent:1; + uint32_t tx_coherent:1; + uint32_t reserved:2; + uint32_t wpdma2host_err_int_en:1; + uint32_t tx_done_20:1; + uint32_t tx_done_16:1; + uint32_t tx_done_17:1; + uint32_t subsys_int_en:1; + uint32_t mcu2host_sw_int_en:1; + uint32_t tx_done_18:1; + uint32_t tx_done_19:1; + } field_conn2x; + + struct { + uint32_t wfdma1_rx_done_0:1; + uint32_t wfdma1_rx_done_1:1; + uint32_t wfdma1_rx_done_2:1; + uint32_t wfdma1_rx_done_3:1; + uint32_t wfdma1_tx_done_0:1; + uint32_t wfdma1_tx_done_1:1; + uint32_t wfdma1_tx_done_2:1; + uint32_t wfdma1_tx_done_3:1; + uint32_t wfdma1_tx_done_4:1; + uint32_t wfdma1_tx_done_5:1; + uint32_t wfdma1_tx_done_6:1; + uint32_t wfdma1_tx_done_7:1; + uint32_t wfdma1_tx_done_8:1; + uint32_t reserved13:2; + uint32_t wfdma1_tx_done_20:1; + uint32_t wfdma0_rx_done_0:1; + uint32_t wfdma0_rx_done_1:1; + uint32_t wfdma0_rx_done_2:1; + uint32_t wfdma0_rx_done_3:1; + uint32_t wfdma1_rx_coherent:1; + uint32_t wfdma1_tx_coherent:1; + uint32_t wfdma0_rx_coherent:1; + uint32_t wfdma0_tx_coherent:1; + uint32_t wpdma2host1_err_int_en:1; + uint32_t wpdma2host0_err_int_en:1; + uint32_t wfdma1_tx_done_16:1; + uint32_t wfdma1_tx_done_17:1; + uint32_t wfdma1_subsys_int_en:1; + uint32_t wfdma1_mcu2host_sw_int_en:1; + uint32_t wfdma1_tx_done_18:1; + uint32_t wfdma1_tx_done_19:1; + } field_conn2x_ext; + + struct { + uint32_t wfdma0_rx_done_0:1; + uint32_t wfdma0_rx_done_1:1; + uint32_t wfdma0_rx_done_2:1; + uint32_t wfdma0_rx_done_3:1; + uint32_t wfdma0_tx_done_0:1; + uint32_t wfdma0_tx_done_1:1; + uint32_t wfdma0_tx_done_2:1; + uint32_t wfdma0_tx_done_3:1; + uint32_t wfdma0_tx_done_4:1; + uint32_t wfdma0_tx_done_5:1; + uint32_t wfdma0_tx_done_6:1; + uint32_t wfdma0_tx_done_7:1; + uint32_t wfdma0_tx_done_8:1; + uint32_t wfdma0_tx_done_9:1; + uint32_t wfdma0_tx_done_10:1; + uint32_t wfdma0_tx_done_11:1; + uint32_t wfdma0_tx_done_12:1; + uint32_t wfdma0_tx_done_13:1; + uint32_t wfdma0_tx_done_14:1; + uint32_t reserved19:1; + uint32_t wfdma0_rx_coherent:1; + uint32_t wfdma0_tx_coherent:1; + uint32_t wfdma0_rx_done_4:1; + uint32_t wfdma0_rx_done_5:1; + uint32_t wpdma2host0_err_int_en:1; + uint32_t reserved25:1; + uint32_t wfdma0_tx_done_16:1; + uint32_t wfdma0_tx_done_17:1; + uint32_t wfdma0_subsys_int_en:1; + uint32_t wfdma0_mcu2host_sw_int_en:1; + uint32_t wfdma0_tx_done_18:1; + uint32_t reserved31:1; + } field_conn2x_single; + + uint32_t word; +}; + +/* WPDMA_INT_MSK */ +union WPDMA_INT_MASK { + struct { + uint32_t rx_done_0:1; + uint32_t rx_done_1:1; + uint32_t err_det_int_0:1; + uint32_t err_det_int_1:1; + uint32_t tx_done:16; + uint32_t rx_coherent:1; + uint32_t tx_coherent:1; + uint32_t rx_dly_int:1; + uint32_t tx_dly_int:1; + uint32_t wf_mac_int_0:1; + uint32_t wf_mac_int_1:1; + uint32_t wf_mac_int_2:1; + uint32_t wf_mac_int_3:1; + uint32_t wf_mac_int_4:1; + uint32_t wf_mac_int_5:1; + uint32_t mcu_cmd_int:1; + uint32_t fw_clr_own:1; + } field; + + struct { + uint32_t rx_done_0:1; + uint32_t rx_done_1:1; + uint32_t err_det_int_0:1; + uint32_t err_det_int_1:1; + uint32_t tx_done:16; + uint32_t rx_coherent:1; + uint32_t tx_coherent:1; + uint32_t rx_dly_int:1; + uint32_t tx_dly_int:1; + uint32_t wpdma2host_err_int_ena:1; + uint32_t rsv_25_27:3; + uint32_t subsys_int_ena:1; + uint32_t mcu2host_sw_int_ena:1; + uint32_t rsv_30_31:2; + } field_conn; + + struct { + uint32_t rx_done_0:1; + uint32_t rx_done_1:1; + uint32_t rx_done_2:1; + uint32_t rx_done_3:1; + uint32_t tx_done:16; + uint32_t rx_coherent:1; + uint32_t tx_coherent:1; + uint32_t reserved:2; + uint32_t wpdma2host_err_int_en:1; + uint32_t tx_done_20:1; + uint32_t tx_done_16:1; + uint32_t tx_done_17:1; + uint32_t subsys_int_en:1; + uint32_t mcu2host_sw_int_en:1; + uint32_t tx_done_18:1; + uint32_t tx_done_19:1; + } field_conn2x; + + struct { + uint32_t wfdma1_rx_done_0:1; + uint32_t wfdma1_rx_done_1:1; + uint32_t wfdma1_rx_done_2:1; + uint32_t wfdma1_rx_done_3:1; + uint32_t wfdma1_tx_done_0:1; + uint32_t wfdma1_tx_done_1:1; + uint32_t wfdma1_tx_done_2:1; + uint32_t wfdma1_tx_done_3:1; + uint32_t wfdma1_tx_done_4:1; + uint32_t wfdma1_tx_done_5:1; + uint32_t wfdma1_tx_done_6:1; + uint32_t wfdma1_tx_done_7:1; + uint32_t wfdma1_tx_done_8:1; + uint32_t reserved13:2; + uint32_t wfdma1_tx_done_20:1; + uint32_t wfdma0_rx_done_0:1; + uint32_t wfdma0_rx_done_1:1; + uint32_t wfdma0_rx_done_2:1; + uint32_t wfdma0_rx_done_3:1; + uint32_t wfdma1_rx_coherent:1; + uint32_t wfdma1_tx_coherent:1; + uint32_t wfdma0_rx_coherent:1; + uint32_t wfdma0_tx_coherent:1; + uint32_t wpdma2host1_err_int_en:1; + uint32_t wpdma2host0_err_int_en:1; + uint32_t wfdma1_tx_done_16:1; + uint32_t wfdma1_tx_done_17:1; + uint32_t wfdma1_subsys_int_en:1; + uint32_t wfdma1_mcu2host_sw_int_en:1; + uint32_t wfdma1_tx_done_18:1; + uint32_t wfdma1_tx_done_19:1; + } field_conn2x_ext; + + struct { + uint32_t wfdma0_rx_done_0:1; + uint32_t wfdma0_rx_done_1:1; + uint32_t wfdma0_rx_done_2:1; + uint32_t wfdma0_rx_done_3:1; + uint32_t wfdma0_tx_done_0:1; + uint32_t wfdma0_tx_done_1:1; + uint32_t wfdma0_tx_done_2:1; + uint32_t wfdma0_tx_done_3:1; + uint32_t wfdma0_tx_done_4:1; + uint32_t wfdma0_tx_done_5:1; + uint32_t wfdma0_tx_done_6:1; + uint32_t wfdma0_tx_done_7:1; + uint32_t wfdma0_tx_done_8:1; + uint32_t wfdma0_tx_done_9:1; + uint32_t wfdma0_tx_done_10:1; + uint32_t wfdma0_tx_done_11:1; + uint32_t wfdma0_tx_done_12:1; + uint32_t wfdma0_tx_done_13:1; + uint32_t wfdma0_tx_done_14:1; + uint32_t reserved19:1; + uint32_t wfdma0_rx_coherent:1; + uint32_t wfdma0_tx_coherent:1; + uint32_t wfdma0_rx_done_4:1; + uint32_t wfdma0_rx_done_5:1; + uint32_t wpdma2host0_err_int_en:1; + uint32_t reserved25:1; + uint32_t wfdma0_tx_done_16:1; + uint32_t wfdma0_tx_done_17:1; + uint32_t wfdma0_subsys_int_en:1; + uint32_t wfdma0_mcu2host_sw_int_en:1; + uint32_t wfdma0_tx_done_18:1; + uint32_t reserved31:1; + } field_conn2x_single; + uint32_t word; +}; + +/* WPDMA_GLO_CFG */ +union WPDMA_GLO_CFG_STRUCT { + struct { + uint32_t EnableTxDMA:1; + uint32_t TxDMABusy:1; + uint32_t EnableRxDMA:1; + uint32_t RxDMABusy:1; + uint32_t WPDMABurstSIZE:2; + uint32_t EnTXWriteBackDDONE:1; + uint32_t BigEndian:1; + uint32_t Desc32BEn:1; + uint32_t share_fifo_en:1; + uint32_t multi_dma_en:2; + uint32_t fifo_little_endian:1; + uint32_t mi_depth:3; + uint32_t err_det_th:8; + uint32_t sw_rst:1; + uint32_t force_tx_eof:1; + uint32_t rsv_26:1; + uint32_t omit_rx_info:1; + uint32_t omit_tx_info:1; + uint32_t byte_swap:1; + uint32_t clk_gate_dis:1; + uint32_t rx_2b_offset:1; + } field; + + struct { + uint32_t EnableTxDMA:1; + uint32_t TxDMABusy:1; + uint32_t EnableRxDMA:1; + uint32_t RxDMABusy:1; + uint32_t WPDMABurstSIZE:2; + uint32_t EnTXWriteBackDDONE:1; + uint32_t BigEndian:1; + uint32_t dis_bt_size_align:1; + uint32_t tx_bt_size:1; + uint32_t multi_dma_en:2; + uint32_t fifo_little_endian:1; + uint32_t mi_depth:3; + uint32_t mi_depth_rd_3_5:3; + uint32_t mi_depth_rd_8_6:3; + uint32_t tx_bt_size_bit21:2; + uint32_t sw_rst:1; + uint32_t force_tx_eof:1; + uint32_t first_token:1; + uint32_t omit_rx_info:1; + uint32_t omit_tx_info:1; + uint32_t byte_swap:1; + uint32_t reserve_30:1; + uint32_t rx_2b_offset:1; + } field_1; + + struct { + uint32_t tx_dma_en:1; + uint32_t tx_dma_busy:1; + uint32_t rx_dma_en:1; + uint32_t rx_dma_busy:1; + uint32_t pdma_bt_size:2; + uint32_t tx_wb_ddone:1; + uint32_t big_endian:1; + uint32_t dmad_32b_en:1; + uint32_t bypass_dmashdl_txring3:1; + uint32_t multi_dma_en:2; + uint32_t fifo_little_endian:1; + uint32_t mi_depth:3; + uint32_t dfet_arb_mi_depth:3; + uint32_t pfet_arb_mi_depth:3; + uint32_t reserved22:3; + uint32_t force_tx_eof:1; + uint32_t pdma_addr_ext_en:1; + uint32_t omit_rx_info:1; + uint32_t omit_tx_info:1; + uint32_t byte_swap:1; + uint32_t clk_gate_dis:1; + uint32_t rx_2b_offset:1; + } field_conn; + + struct { + uint32_t tx_dma_en:1; + uint32_t tx_dma_busy:1; + uint32_t rx_dma_en:1; + uint32_t rx_dma_busy:1; + uint32_t pdma_bt_size:2; + uint32_t tx_wb_ddone:1; + uint32_t big_endian:1; + uint32_t dmad_32b_en:1; + uint32_t bypass_dmashdl_txring:1; + uint32_t reserved10:2; + uint32_t fifo_little_endian:1; + uint32_t csr_rx_wb_ddone:1; + uint32_t csr_pp_hif_txp_active_en:1; + uint32_t csr_disp_base_ptr_chain_en:1; + uint32_t csr_lbk_rx_q_sel:4; + uint32_t csr_lbk_rx_q_sel_en:1; + /* define after Buzzard (rsv before) */ + uint32_t omit_rx_info_pfet2:1; + uint32_t reserved22:2; + uint32_t csr_sw_rst:1; + uint32_t force_tx_eof:1; + uint32_t pdma_addr_ext_en:1; + uint32_t omit_rx_info:1; + uint32_t omit_tx_info:1; + uint32_t byte_swap:1; + uint32_t clk_gate_dis:1; + uint32_t rx_2b_offset:1; + } field_conn2x; + + uint32_t word; +}; + +/* WPDMA_RST_PTR */ +union WPDMA_RST_IDX_STRUCT { + struct { + uint32_t RST_DTX_IDX0:1; + uint32_t RST_DTX_IDX1:1; + uint32_t rsv_2_15:14; + uint32_t RST_DRX_IDX0:1; + uint32_t RST_DRX_IDX1:1; + uint32_t rsv_18_31:14; + } field; + + uint32_t word; +}; + +/* WPDMA_DELAY_INT_CFG */ +union DELAY_INT_CFG_STRUCT { + struct { + uint32_t RXMAX_PTIME:8; + uint32_t RXMAX_PINT:7; + uint32_t RXDLY_INT_EN:1; + uint32_t TXMAX_PTIME:8; + uint32_t TXMAX_PINT:7; + uint32_t TXDLY_INT_EN:1; + } field; + + uint32_t word; +}; + +/* RTC_TOP_MISC2 */ +#define TOP_MISC2_CR4_INIT_DONE BIT(18) +#define TOP_MISC2_N9_INIT_DONE BIT(17) +#define TOP_MISC2_FW_READY BIT(16) +#define WLAN_READY_BITS BITS(16, 18) + +/* HIF_SYS_REV */ +#define PCIE_HIF_SYS_PROJ BITS(16, 31) +#define PCIE_HIF_SYS_REV BITS(0, 15) + +/* CFG_PCIE_LPCR_HOST */ +#define PCIE_LPCR_AP_HOST_OWNER_STATE_SYNC BIT(2) +#define PCIE_LPCR_HOST_CLR_OWN BIT(1) +#define PCIE_LPCR_HOST_SET_OWN BIT(0) + +/* CFG_PCIE_LPCR_FW */ +#define PCIE_LPCR_FW_CLR_OWN BIT(0) + +/* WPDMA_INT_STA */ +#define WPDMA_FW_CLR_OWN_INT BIT(31) +#define WPDMA_TX_DONE_INT15 BIT(19) +#define WPDMA_TX_DONE_INT3 BIT(7) +#define WPDMA_TX_DONE_INT2 BIT(6) +#define WPDMA_TX_DONE_INT1 BIT(5) +#define WPDMA_TX_DONE_INT0 BIT(4) +#define WPDMA_RX_DONE_INT3 BIT(3) +#define WPDMA_RX_DONE_INT2 BIT(2) +#define WPDMA_RX_DONE_INT1 BIT(1) +#define WPDMA_RX_DONE_INT0 BIT(0) + +#else +#define WIFI_CFG_SW_SYNC0 0 +#define WIFI_CFG_SYNC0_RDY_OFFSET 0 +#endif + +/* 4 CHIP ID Register */ +#define MCR_WCIR 0x0000 + +/* 4 HIF Low Power Control Register */ +#define MCR_WHLPCR 0x0004 + +/* 4 Control Status Register */ +#define MCR_WSDIOCSR 0x0008 + +/* 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 0x0020 + +/* 4 WLAN Software Interrupt Control Register */ +#define MCR_WSICR 0x0024 + +/* 4 WLAN TX Data Register 1 */ +#define MCR_WTDR1 0x0034 + +/* 4 WLAN RX Data Register 0 */ +#define MCR_WRDR0 0x0050 + +/* 4 WLAN RX Data Register 1 */ +#define MCR_WRDR1 0x0054 + +/* 4 Host to Device Send Mailbox 0 Register */ +#define MCR_H2DSM0R 0x0070 + +/* 4 Host to Device Send Mailbox 1 Register */ +#define MCR_H2DSM1R 0x0074 + +/* 4 Device to Host Receive Mailbox 0 Register */ +#define MCR_D2HRM0R 0x0078 + +/* 4 Device to Host Receive Mailbox 1 Register */ +#define MCR_D2HRM1R 0x007c + +/* 4 Device to Host Receive Mailbox 2 Register */ +#define MCR_D2HRM2R 0x0080 + +/* 4 WLAN RX Packet Length Register */ +#define MCR_WRPLR 0x0090 + +/* 4 Test Mode Data Port */ +#define MCR_WTMDR 0x00b0 + +/* 4 Test Mode Control Register */ +#define MCR_WTMCR 0x00b4 + +/* 4 Test Mode Data Pattern Control Register #0 */ +#define MCR_WTMDPCR0 0x00b8 + +/* 4 Test Mode Data Pattern Control Register #1 */ +#define MCR_WTMDPCR1 0x00bc + +/* 4 WLAN Packet Length Report Control Register */ +#define MCR_WPLRCR 0x00d4 + +/* 4 WLAN Snapshot Register */ +#define MCR_WSR 0x00D8 + +/* 4 Clock Pad Macro IO Control Register */ +#define MCR_CLKIOCR 0x0100 + +/* 4 Command Pad Macro IO Control Register */ +#define MCR_CMDIOCR 0x0104 + +/* 4 Data 0 Pad Macro IO Control Register */ +#define MCR_DAT0IOCR 0x0108 + +/* 4 Data 1 Pad Macro IO Control Register */ +#define MCR_DAT1IOCR 0x010C + +/* 4 Data 2 Pad Macro IO Control Register */ +#define MCR_DAT2IOCR 0x0110 + +/* 4 Data 3 Pad Macro IO Control Register */ +#define MCR_DAT3IOCR 0x0114 + +/* 4 Clock Pad Macro Delay Chain Control Register */ +#define MCR_CLKDLYCR 0x0118 + +/* 4 Command Pad Macro Delay Chain Control Register */ +#define MCR_CMDDLYCR 0x011C + +/* 4 SDIO Output Data Delay Chain Control Register */ +#define MCR_ODATDLYCR 0x0120 + +/* 4 SDIO Input Data Delay Chain Control Register 1 */ +#define MCR_IDATDLYCR1 0x0124 + +/* 4 SDIO Input Data Delay Chain Control Register 2 */ +#define MCR_IDATDLYCR2 0x0128 + +/* 4 SDIO Input Data Latch Time Control Register */ +#define MCR_ILCHCR 0x012C + +/* 4 WLAN TXQ Count Register 0 */ +#define MCR_WTQCR0 0x0130 + +/* 4 WLAN TXQ Count Register 1 */ +#define MCR_WTQCR1 0x0134 + +/* 4 WLAN TXQ Count Register 2 */ +#define MCR_WTQCR2 0x0138 + +/* 4 WLAN TXQ Count Register 3 */ +#define MCR_WTQCR3 0x013C + +/* 4 WLAN TXQ Count Register 4 */ +#define MCR_WTQCR4 0x0140 + +/* 4 WLAN TXQ Count Register 5 */ +#define MCR_WTQCR5 0x0144 + +/* 4 WLAN TXQ Count Register 6 */ +#define MCR_WTQCR6 0x0148 + +/* 4 WLAN TXQ Count Register 7 */ +#define MCR_WTQCR7 0x014C + +/* WLAN/Common PC value Debug registre */ +#define MCR_SWPCDBGR 0x0154 + +/* #if CFG_SDIO_INTR_ENHANCE */ +struct ENHANCE_MODE_DATA_STRUCT { + uint32_t u4WHISR; + union { + struct { + uint16_t u2TQ0Cnt; + uint16_t u2TQ1Cnt; + uint16_t u2TQ2Cnt; + uint16_t u2TQ3Cnt; + uint16_t u2TQ4Cnt; + uint16_t u2TQ5Cnt; + uint16_t u2TQ6Cnt; + uint16_t u2TQ7Cnt; + uint16_t u2TQ8Cnt; + uint16_t u2TQ9Cnt; + uint16_t u2TQ10Cnt; + uint16_t u2TQ11Cnt; + uint16_t u2TQ12Cnt; + uint16_t u2TQ13Cnt; + uint16_t u2TQ14Cnt; + uint16_t u2TQ15Cnt; + } u; + uint32_t au4WTSR[8]; + } rTxInfo; + union { + struct { + uint16_t u2NumValidRx0Len; + uint16_t u2NumValidRx1Len; + uint16_t au2Rx0Len[16]; + uint16_t au2Rx1Len[16]; + } u; + uint32_t au4RxStatusRaw[17]; + } rRxInfo; + uint32_t u4RcvMailbox0; + uint32_t u4RcvMailbox1; +}; +/* #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 0x00006632 +#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_DB_CMD7_RESELECT_DIS BIT(4) +#define WSDIOCSR_DB_WR_BUSY_EN BIT(3) +#define WSDIOCSR_DB_RD_BUSY_EN BIT(2) +#define WSDIOCSR_SDIO_INT_CTL BIT(1) +#define WSDIOCSR_SDIO_RE_INIT_EN BIT(0) + +/* 3 WHCR 0x000C */ +#define WHCR_RX_ENHANCE_MODE_EN BIT(16) +#define WHCR_MAX_HIF_RX_LEN_NUM BITS(8, 13) +#define WHCR_RPT_OWN_RX_PACKET_LEN BIT(3) +#define WHCR_RECV_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 8 + +/* 3 WHISR 0x0010 */ +#define WHISR_D2H_SW_INT BITS(8, 31) +#define WHISR_D2H_SW_ASSERT_INFO_INT BIT(31) +#define WHISR_D2H_WKUP_BY_RX_PACKET BIT(30) +#define WHISR_D2H_SW_RD_MAILBOX_INT BIT(29) +#define WHISR_FW_OWN_BACK_INT BIT(7) +#define WHISR_ABNORMAL_INT BIT(6) +#define WHISR_RX1_DONE_INT BIT(2) +#define WHISR_RX0_DONE_INT BIT(1) +#define WHISR_TX_DONE_INT BIT(0) + +/* 3 WHIER 0x0014 */ +#define WHIER_D2H_SW_INT BITS(8, 31) +#define WHIER_FW_OWN_BACK_INT_EN BIT(7) +#define WHIER_ABNORMAL_INT_EN BIT(6) +#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 0x0020 */ +#define WASR_FW_OWN_INVALID_ACCESS BIT(16) +#define WASR_RX1_UNDER_FLOW BIT(9) +#define WASR_RX0_UNDER_FLOW BIT(8) +#define WASR_TX1_OVER_FLOW BIT(1) + +/* 3 WSICR 0x0024 */ +#define WSICR_H2D_SW_INT_SET BITS(16, 31) + +/* 3 WRPLR 0x0090 */ +#define WRPLR_RX1_PACKET_LENGTH BITS(16, 31) +#define WRPLR_RX0_PACKET_LENGTH BITS(0, 15) + +/* 3 WTMCR 0x00b4 */ +#define WMTCR_TEST_MODE_FW_OWN BIT(24) +#define WMTCR_PRBS_INIT_VAL BITS(16, 23) +#define WMTCR_TEST_MODE_STATUS BIT(8) +#define WMTCR_TEST_MODE_SELECT BITS(0, 1) + + + +/* Support features */ +/* Options for VLAN-over-ethernet pkt to/from 802.11 LLC VLAN pkt. + * This should depend on the configurations of HW-header-translation. + */ +#define FEAT_BITS_LLC_VLAN_TX BIT(0) +#define FEAT_BITS_LLC_VLAN_RX BIT(1) + +/* Support features API */ +#define FEAT_SUP_LLC_VLAN_TX(__chip_info) \ + ((__chip_info)->features & FEAT_BITS_LLC_VLAN_TX) +#define FEAT_SUP_LLC_VLAN_RX(__chip_info) \ + ((__chip_info)->features & FEAT_BITS_LLC_VLAN_RX) + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +enum ENUM_WIFI_FUNC { + WIFI_FUNC_INIT_DONE = BIT(0), + WIFI_FUNC_N9_DONE = BIT(1), + WIFI_FUNC_NO_CR4_READY_BITS = BITS(0, 1), + WIFI_FUNC_CR4_READY = BIT(2), + WIFI_FUNC_READY_BITS = BITS(0, 2), + WIFI_FUNC_DUMMY_REQ = BIT(3) +}; + +enum enum_mt66xx_chip { + MT66XX_CHIP_6632 = 0, + MT66XX_CHIP_7666, + MT66XX_CHIP_7668, + MT66XX_CHIP_NUM +}; + +enum enum_workAround { + WORKAROUND_MT7663_BRINGUP_20171205 = 0, + WORKAROUND_NUM +}; + +struct mt66xx_chip_info { + struct BUS_INFO *bus_info; + struct FWDL_OPS_T *fw_dl_ops; + struct TX_DESC_OPS_T *prTxDescOps; + struct RX_DESC_OPS_T *prRxDescOps; +#if CFG_SUPPORT_QA_TOOL + struct ATE_OPS_T *prAteOps; +#endif + struct CHIP_DBG_OPS *prDebugOps; + + const unsigned int chip_id; /* chip id */ + const unsigned int should_verify_chip_id; /* verify chip id */ + const unsigned int sw_sync0; /* sw_sync0 address */ + const unsigned int sw_ready_bits; /* sw_sync0 ready bits */ + const unsigned int sw_ready_bit_offset; /* sw_sync0 ready bit offset */ + const unsigned int patch_addr; /* patch download start address */ + const unsigned int is_support_cr4; /* support CR4 */ + const unsigned int is_support_wacpu; /* support WA-CPU */ + const unsigned int txd_append_size; /* hw mac txd append */ + const unsigned int rxd_size; /* hw mac rxd size */ + const unsigned int init_evt_rxd_size; /* init event rxd size */ + const unsigned int pse_header_length; /* NIC_TX_PSE_HEADER_LENGTH */ + const unsigned int init_event_size; /* init event w/o rxd size */ + const unsigned int event_hdr_size; /* event w/o rxd size */ + const unsigned int isNicCapV1; + const unsigned int is_support_efuse; /* efuse support */ + const unsigned int top_hcr; /* TOP_HCR */ + const unsigned int top_hvr; /* TOP_HVR */ + const unsigned int top_fvr; /* TOP_FVR */ +#if (CFG_SUPPORT_802_11AX == 1) + const unsigned int arb_ac_mode_addr; +#endif /* CFG_SUPPORT_802_11AX == 1 */ + const unsigned int custom_oid_interface_version; + const unsigned int em_interface_version; + const unsigned int cmd_max_pkt_size; + + const struct ECO_INFO *eco_info; /* chip version table */ + uint8_t eco_ver; /* chip version */ + uint8_t ucPacketFormat; + + uint16_t u2TxInitCmdPort; + uint16_t u2TxFwDlPort; + uint16_t u2HifTxdSize; + uint16_t u2CmdTxHdrSize; + uint16_t u2RxSwPktBitMap; + uint16_t u2RxSwPktEvent; + uint16_t u2RxSwPktFrame; + + /* Extra TXD Size for TX Byte Count field (in unit of Byte) */ + uint32_t u4ExtraTxByteCount; + uint32_t u4HifDmaShdlBaseAddr; + /* chip ip version from FW */ + uint32_t u4ChipIpVersion; + uint32_t u4ChipIpConfig; + uint16_t u2ADieChipVersion; + + void (*asicCapInit)(IN struct ADAPTER *prAdapter); + void (*asicEnableFWDownload)(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnable); + void (*asicFillInitCmdTxd)(IN struct ADAPTER *prAdapter, + IN struct WIFI_CMD_INFO *prCmdInfo, + OUT uint16_t *pu2BufInfoLen, OUT uint8_t *pucSeqNum, + OUT void **pCmdBuf); + void (*asicFillCmdTxd)(IN struct ADAPTER *prAdapter, + IN struct WIFI_CMD_INFO *prCmdInfo, + OUT uint8_t *pucSeqNum, OUT void **pCmdBuf); + uint32_t (*asicGetChipID)(IN struct ADAPTER *prAdapter); + void (*fillHifTxDesc)(IN uint8_t **pDest, IN uint16_t *pInfoBufLen); + uint32_t (*downloadBufferBin)(IN struct ADAPTER *prAdapter); + void (*asicRxProcessRxvforMSP)(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prRetSwRfb); + uint8_t (*asicRxGetRcpiValueFromRxv)( + IN uint8_t ucRcpiMode, + IN struct SW_RFB *prSwRfb); + void (*asicRxPerfIndProcessRXV)( + IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint8_t ucBssIndex); + + const uint32_t features; /* feature bits */ + u_int8_t is_support_hw_amsdu; + uint8_t ucMaxSwAmsduNum; + uint8_t ucMaxSwapAntenna; + uint32_t workAround; + char *prTxPwrLimitFile; + uint8_t ucTxPwrLimitBatchSize; + u_int8_t is_support_asic_lp; + u_int8_t is_support_wfdma1; + u_int8_t is_support_dma_shdl; + u_int8_t rx_event_port; +#if defined(_HIF_USB) + void (*asicUsbInit)(IN struct ADAPTER *prAdapter, + IN struct mt66xx_chip_info *prChipInfo); + void (*asicUsbInit_ic_specific)(IN struct ADAPTER *prAdapter, + IN struct mt66xx_chip_info *prChipInfo); + uint32_t u4SerUsbMcuEventAddr; + uint32_t u4SerUsbHostAckAddr; +#endif + void (*asicDumpSerDummyCR)(IN struct ADAPTER *prAdapter); + void (*asicWfdmaReInit)(IN struct ADAPTER *prAdapter); + void (*asicWfdmaReInit_handshakeInit)(IN struct ADAPTER *prAdapter); + void *pdev; + uint32_t group5_size; + void (*wlanCheckAsicCap)(IN struct ADAPTER *prAdapter); +#if (CFG_CHIP_RESET_SUPPORT == 1) && (CFG_WMT_RESET_API_SUPPORT == 0) + u_int8_t (*rst_L0_notify_step2)(void); +#endif + uint32_t u4LmacWtblDUAddr; + uint32_t u4UmacWtblDUAddr; + int (*wmmcupwron)(void); + int (*wmmcupwroff)(void); + uint32_t (*pwrondownload)(IN struct ADAPTER *prAdapter, + IN uint8_t ucDownloadItem); + int (*triggerfwassert)(void); + int (*coexpccifon)(void); + int (*coexpccifoff)(void); + void (*coantSetWiFi)(void); + void (*coantSetMD)(void); + void (*coantVFE28En)(IN struct ADAPTER *prAdapter); + void (*coantVFE28Dis)(void); + int (*trigger_wholechiprst)(char *reason); + void (*sw_interrupt_handler)(IN struct ADAPTER *prAdapter); + void (*conninra_cb_register)(void); + void (*dumpwfsyscpupcr)(IN struct ADAPTER *prAdapter); + uint8_t* (*getCalResult)(OUT uint32_t *prCalSize); + void (*calDebugCmd)(uint32_t cmd, uint32_t para); + u_int8_t is_support_nvram_fragment; + int (*checkbushang)(void *prAdapter, + uint8_t ucWfResetEnable); + void (*dumpBusHangCr)(IN struct ADAPTER *prAdapter); +}; + +struct mt66xx_hif_driver_data { + struct mt66xx_chip_info *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 + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic.h new file mode 100644 index 0000000000000..0175869f506a9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic.h @@ -0,0 +1,481 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + + +#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 + ******************************************************************************* + */ +#define PS_SYNC_WITH_FW BIT(31) + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +struct REG_ENTRY { + uint32_t u4Offset; + uint32_t u4Value; +}; + +struct _TABLE_ENTRY_T { + struct REG_ENTRY *pu4TablePtr; + uint16_t u2Size; +}; + +/*! INT status to event map */ +struct INT_EVENT_MAP { + uint32_t u4Int; + uint32_t u4Event; +}; + +struct ECO_INFO { + uint8_t ucHwVer; + uint8_t ucRomVer; + uint8_t ucFactoryVer; + uint8_t ucEcoVer; +}; + +enum ENUM_INT_EVENT_T { + INT_EVENT_ABNORMAL, + INT_EVENT_SW_INT, + INT_EVENT_TX, + INT_EVENT_RX, + INT_EVENT_NUM +}; + +enum ENUM_IE_UPD_METHOD { + IE_UPD_METHOD_UPDATE_RANDOM, + IE_UPD_METHOD_UPDATE_ALL, + IE_UPD_METHOD_DELETE_ALL, +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP + IE_UPD_METHOD_UPDATE_PROBE_RSP, +#endif +}; + +enum ENUM_SER_STATE { + SER_IDLE_DONE, /* SER is idle or done */ + SER_STOP_HOST_TX, /* Host HIF Tx is stopped */ + SER_STOP_HOST_TX_RX, /* Host HIF Tx/Rx is stopped */ + SER_REINIT_HIF, /* Host HIF is reinit */ + + SER_STATE_NUM +}; + +/* The bit map for the caller to set the power save flag */ +enum POWER_SAVE_CALLER { + PS_CALLER_COMMON = 0, + PS_CALLER_CTIA, + PS_CALLER_SW_WRITE, + PS_CALLER_CTIA_CAM, + PS_CALLER_P2P, + PS_CALLER_CAMCFG, + PS_CALLER_GPU, + PS_CALLER_TP, + PS_CALLER_NO_TIM, + PS_CALLER_MAX_NUM = 24 +}; + +enum ENUM_ECO_VER { + ECO_VER_1 = 1, + ECO_VER_2, + ECO_VER_3 +}; + +enum ENUM_REMOVE_BY_MSDU_TPYE { + MSDU_REMOVE_BY_WLAN_INDEX = 0, + MSDU_REMOVE_BY_BSS_INDEX, + MSDU_REMOVE_BY_ALL, + ENUM_REMOVE_BY_MSDU_TPYE_NUM +}; + +/* Test mode bitmask of disable flag */ +#define TEST_MODE_DISABLE_ONLINE_SCAN BIT(0) +#define TEST_MODE_DISABLE_ROAMING BIT(1) +#define TEST_MODE_FIXED_CAM_MODE BIT(2) +#define TEST_MODE_DISABLE_BCN_LOST_DET BIT(3) +#define TEST_MODE_NONE 0 +#define TEST_MODE_THROUGHPUT \ + (TEST_MODE_DISABLE_ONLINE_SCAN | TEST_MODE_DISABLE_ROAMING | \ + TEST_MODE_FIXED_CAM_MODE | TEST_MODE_DISABLE_BCN_LOST_DET) +#define TEST_MODE_SIGMA_AC_N_PMF \ + (TEST_MODE_DISABLE_ONLINE_SCAN | TEST_MODE_FIXED_CAM_MODE) +#define TEST_MODE_SIGMA_WMM_PS (TEST_MODE_DISABLE_ONLINE_SCAN) +/******************************************************************************* + * 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 */ +/*----------------------------------------------------------------------------*/ +uint32_t nicAllocateAdapterMemory(IN struct ADAPTER + *prAdapter); + +void nicReleaseAdapterMemory(IN struct ADAPTER *prAdapter); + +void nicDisableInterrupt(IN struct ADAPTER *prAdapter); + +void nicEnableInterrupt(IN struct ADAPTER *prAdapter); + +uint32_t nicProcessIST(IN struct ADAPTER *prAdapter); + +uint32_t nicProcessISTWithSpecifiedCount(IN struct ADAPTER *prAdapter, + IN uint32_t u4HifIstLoopCount); + +uint32_t nicProcessIST_impl(IN struct ADAPTER *prAdapter, + IN uint32_t u4IntStatus); + +uint32_t nicInitializeAdapter(IN struct ADAPTER *prAdapter); + +void nicMCRInit(IN struct ADAPTER *prAdapter); + +u_int8_t nicVerifyChipID(IN struct ADAPTER *prAdapter); + +void nicpmWakeUpWiFi(IN struct ADAPTER *prAdapter); + +u_int8_t nicpmSetDriverOwn(IN struct ADAPTER *prAdapter); + +void nicpmSetFWOwn(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnableGlobalInt); + +u_int8_t nicpmSetAcpiPowerD0(IN struct ADAPTER *prAdapter); + +u_int8_t nicpmSetAcpiPowerD3(IN struct ADAPTER *prAdapter); + +#if defined(_HIF_SPI) +void nicRestoreSpiDefMode(IN struct ADAPTER *prAdapter); +#endif + +void nicProcessSoftwareInterrupt(IN struct ADAPTER + *prAdapter); + +void nicProcessAbnormalInterrupt(IN struct ADAPTER + *prAdapter); + +void nicSetSwIntr(IN struct ADAPTER *prAdapter, + IN uint32_t u4SwIntrBitmap); + +struct CMD_INFO *nicGetPendingCmdInfo(IN struct ADAPTER + *prAdapter, IN uint8_t ucSeqNum); + +struct MSDU_INFO *nicGetPendingTxMsduInfo( + IN struct ADAPTER *prAdapter, IN uint8_t ucWlanIndex, + IN uint8_t ucSeqNum); + +void nicFreePendingTxMsduInfo(IN struct ADAPTER *prAdapter, + IN uint8_t ucIndex, IN enum ENUM_REMOVE_BY_MSDU_TPYE ucFreeType); + +uint8_t nicIncreaseCmdSeqNum(IN struct ADAPTER *prAdapter); + +uint8_t nicIncreaseTxSeqNum(IN struct ADAPTER *prAdapter); + +/* Media State Change */ +uint32_t +nicMediaStateChange(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct EVENT_CONNECTION_STATUS *prConnectionStatus); + +uint32_t nicMediaJoinFailure(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN uint32_t rStatus); + +/* Utility function for channel number conversion */ +uint32_t nicChannelNum2Freq(IN uint32_t u4ChannelNum); + +uint32_t nicFreq2ChannelNum(IN uint32_t u4FreqInKHz); + +uint8_t nicGetVhtS1(IN uint8_t ucPrimaryChannel, + IN uint8_t ucBandwidth); + +/* firmware command wrapper */ +/* NETWORK (WIFISYS) */ +uint32_t nicActivateNetwork(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +uint32_t nicDeactivateNetwork(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +/* BSS-INFO */ +uint32_t nicUpdateBss(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +/* BSS-INFO Indication (PM) */ +uint32_t nicPmIndicateBssCreated(IN struct ADAPTER + *prAdapter, IN uint8_t ucBssIndex); + +uint32_t nicPmIndicateBssConnected(IN struct ADAPTER + *prAdapter, IN uint8_t ucBssIndex); + +uint32_t nicPmIndicateBssAbort(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +/* Beacon Template Update */ +uint32_t +nicUpdateBeaconIETemplate(IN struct ADAPTER *prAdapter, + IN enum ENUM_IE_UPD_METHOD eIeUpdMethod, + IN uint8_t ucBssIndex, IN uint16_t u2Capability, + IN uint8_t *aucIe, IN uint16_t u2IELen); + +uint32_t nicQmUpdateWmmParms(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +#if (CFG_SUPPORT_802_11AX == 1) +uint32_t nicQmUpdateMUEdcaParams(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); +uint32_t nicRlmUpdateSRParams(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); +#endif + +uint32_t nicSetAutoTxPower(IN struct ADAPTER *prAdapter, + IN struct CMD_AUTO_POWER_PARAM *prAutoPwrParam); + +/*----------------------------------------------------------------------------*/ +/* Calibration Control */ +/*----------------------------------------------------------------------------*/ +uint32_t nicUpdateTxPower(IN struct ADAPTER *prAdapter, + IN struct CMD_TX_PWR *prTxPwrParam); + +uint32_t nicUpdate5GOffset(IN struct ADAPTER *prAdapter, + IN struct CMD_5G_PWR_OFFSET *pr5GPwrOffset); + +uint32_t nicUpdateDPD(IN struct ADAPTER *prAdapter, + IN struct CMD_PWR_PARAM *prDpdCalResult); + +/*----------------------------------------------------------------------------*/ +/* PHY configuration */ +/*----------------------------------------------------------------------------*/ +void nicSetAvailablePhyTypeSet(IN struct ADAPTER + *prAdapter); + +/*----------------------------------------------------------------------------*/ +/* MGMT and System Service Control */ +/*----------------------------------------------------------------------------*/ +void nicInitSystemService(IN struct ADAPTER *prAdapter, + IN const u_int8_t bAtResetFlow); + +void nicResetSystemService(IN struct ADAPTER *prAdapter); + +void nicUninitSystemService(IN struct ADAPTER *prAdapter); + +void nicInitMGMT(IN struct ADAPTER *prAdapter, + IN struct REG_INFO *prRegInfo); + +void nicUninitMGMT(IN struct ADAPTER *prAdapter); + +void +nicPowerSaveInfoMap(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN enum PARAM_POWER_MODE ePowerMode, + IN enum POWER_SAVE_CALLER ucCaller); + +uint32_t +nicConfigPowerSaveProfile(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN enum PARAM_POWER_MODE ePwrMode, + IN u_int8_t fgEnCmdEvent, IN enum POWER_SAVE_CALLER ucCaller); + +uint32_t +nicConfigProcSetCamCfgWrite(IN struct ADAPTER *prAdapter, + IN u_int8_t enabled, IN uint8_t ucBssIndex); + +uint32_t nicEnterCtiaMode(IN struct ADAPTER *prAdapter, + u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent); + +uint32_t nicEnterTPTestMode(IN struct ADAPTER *prAdapter, + IN uint8_t ucFuncMask); + +uint32_t nicEnterCtiaModeOfScan(IN struct ADAPTER + *prAdapter, u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent); + +uint32_t nicEnterCtiaModeOfRoaming(IN struct ADAPTER + *prAdapter, u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent); + +uint32_t nicEnterCtiaModeOfCAM(IN struct ADAPTER *prAdapter, + u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent); + +uint32_t nicEnterCtiaModeOfBCNTimeout(IN struct ADAPTER + *prAdapter, u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent); + +uint32_t nicEnterCtiaModeOfAutoTxPower(IN struct ADAPTER + *prAdapter, u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent); + +uint32_t nicEnterCtiaModeOfFIFOFullNoAck(IN struct ADAPTER + *prAdapter, u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent); +/*----------------------------------------------------------------------------*/ +/* Scan Result Processing */ +/*----------------------------------------------------------------------------*/ +void +nicAddScanResult(IN struct ADAPTER *prAdapter, + IN uint8_t rMacAddr[PARAM_MAC_ADDR_LEN], + IN struct PARAM_SSID *prSsid, + IN uint16_t u2CapInfo, + IN int32_t rRssi, + IN enum ENUM_PARAM_NETWORK_TYPE eNetworkType, + IN struct PARAM_802_11_CONFIG *prConfiguration, + IN enum ENUM_PARAM_OP_MODE eOpMode, + IN uint8_t rSupportedRates[PARAM_MAX_LEN_RATES_EX], + IN uint16_t u2IELength, IN uint8_t *pucIEBuf); + +void nicFreeScanResultIE(IN struct ADAPTER *prAdapter, + IN uint32_t u4Idx); + +/*----------------------------------------------------------------------------*/ +/* Fixed Rate Hacking */ +/*----------------------------------------------------------------------------*/ +uint32_t +nicUpdateRateParams(IN struct ADAPTER *prAdapter, + IN enum ENUM_REGISTRY_FIXED_RATE eRateSetting, + IN uint8_t *pucDesiredPhyTypeSet, + IN uint16_t *pu2DesiredNonHTRateSet, + IN uint16_t *pu2BSSBasicRateSet, + IN uint8_t *pucMcsSet, IN uint8_t *pucSupMcs32, + IN uint16_t *u2HtCapInfo); + +/*----------------------------------------------------------------------------*/ +/* Write registers */ +/*----------------------------------------------------------------------------*/ +uint32_t nicWriteMcr(IN struct ADAPTER *prAdapter, + IN uint32_t u4Address, IN uint32_t u4Value); + +/*----------------------------------------------------------------------------*/ +/* Update auto rate */ +/*----------------------------------------------------------------------------*/ +uint32_t +nicRlmArUpdateParms(IN struct ADAPTER *prAdapter, + IN uint32_t u4ArSysParam0, + IN uint32_t u4ArSysParam1, IN uint32_t u4ArSysParam2, + IN uint32_t u4ArSysParam3); + +/*----------------------------------------------------------------------------*/ +/* Link Quality Updating */ +/*----------------------------------------------------------------------------*/ +void +nicUpdateLinkQuality(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct EVENT_LINK_QUALITY *prEventLinkQuality); + +void nicUpdateRSSI(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN int8_t cRssi, + IN int8_t cLinkQuality); + +void nicUpdateLinkSpeed(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN uint16_t u2LinkSpeed); + +#if CFG_SUPPORT_RDD_TEST_MODE +uint32_t nicUpdateRddTestMode(IN struct ADAPTER *prAdapter, + IN struct CMD_RDD_CH *prRddChParam); +#endif + +/*----------------------------------------------------------------------------*/ +/* Address Setting Apply */ +/*----------------------------------------------------------------------------*/ +uint32_t nicApplyNetworkAddress(IN struct ADAPTER + *prAdapter); + +/*----------------------------------------------------------------------------*/ +/* ECO Version */ +/*----------------------------------------------------------------------------*/ +uint8_t nicGetChipEcoVer(IN struct ADAPTER *prAdapter); +u_int8_t nicIsEcoVerEqualTo(IN struct ADAPTER *prAdapter, + uint8_t ucEcoVer); +u_int8_t nicIsEcoVerEqualOrLaterTo(IN struct ADAPTER + *prAdapter, uint8_t ucEcoVer); +uint8_t nicSetChipHwVer(uint8_t value); +uint8_t nicSetChipSwVer(uint8_t value); +uint8_t nicSetChipFactoryVer(uint8_t value); + +void nicSerStopTxRx(IN struct ADAPTER *prAdapter); +void nicSerStopTx(IN struct ADAPTER *prAdapter); +void nicSerStartTxRx(IN struct ADAPTER *prAdapter); +u_int8_t nicSerIsWaitingReset(IN struct ADAPTER *prAdapter); +u_int8_t nicSerIsTxStop(IN struct ADAPTER *prAdapter); +u_int8_t nicSerIsRxStop(IN struct ADAPTER *prAdapter); +void nicSerReInitBeaconFrame(IN struct ADAPTER *prAdapter); +void nicSerInit(IN struct ADAPTER *prAdapter); +void nicSerDeInit(IN struct ADAPTER *prAdapter); + +#endif /* _NIC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_connac2x_rx.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_connac2x_rx.h new file mode 100644 index 0000000000000..a877b40abf7ba --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_connac2x_rx.h @@ -0,0 +1,375 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/*! \file nic_connac2x_rx.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. +* +*/ + + +#ifndef _NIC_CONNAC2X_RX_H +#define _NIC_CONNAC2X_RX_H + +#if (CFG_SUPPORT_CONNAC2X == 1) +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define CONNAC2X_RX_STATUS_PKT_TYPE_SW_BITMAP 0x380F +#define CONNAC2X_RX_STATUS_PKT_TYPE_SW_EVENT 0x3800 +#define CONNAC2X_RX_STATUS_PKT_TYPE_SW_FRAME 0x3801 + +/*------------------------------------------------------------------------------ + * Bit fields for HW_MAC_RX_DESC_T + *------------------------------------------------------------------------------ +*/ + +/*! MAC CONNAC2X RX DMA Descriptor */ +/* DW 0*/ +#define CONNAC2X_RX_STATUS_RX_BYTE_COUNT_MASK BITS(0, 15) +#define CONNAC2X_RX_STATUS_RX_BYTE_COUNT_OFFSET 0 +#define CONNAC2X_RX_STATUS_ETH_TYPE_MASK BITS(16, 22) +#define CONNAC2X_RX_STATUS_ETH_TYPE_OFFSET 16 +#define CONNAC2X_RX_STATUS_IP_CHKSUM BIT(23) +#define CONNAC2X_RX_STATUS_UDP_TCP_CHKSUM BIT(24) +#define CONNAC2X_RX_STATUS_DW0_HW_INFO_MASK BITS(25, 26) +#define CONNAC2X_RX_STATUS_DW0_HW_INFO_OFFSET 25 +#define CONNAC2X_RX_STATUS_PKT_TYPE_MASK BITS(27, 31) +#define CONNAC2X_RX_STATUS_PKT_TYPE_OFFSET 27 + +/* DW 1 */ +#define CONNAC2X_RX_STATUS_WLAN_INDEX_MASK BITS(0, 9) +#define CONNAC2X_RX_STATUS_WLAN_INDEX_OFFSET 0 +#define CONNAC2X_RX_STATUS_GROUP_VLD_MASK BITS(11, 15) +#define CONNAC2X_RX_STATUS_GROUP_VLD_OFFSET 11 +#define CONNAC2X_RX_STATUS_SEC_MASK BITS(16, 20) +#define CONNAC2X_RX_STATUS_SEC_OFFSET 16 +#define CONNAC2X_RX_STATUS_KEYID_MASK BITS(21, 22) +#define CONNAC2X_RX_STATUS_KEYID_OFFSET 21 +#define CONNAC2X_RX_STATUS_FLAG_CIPHER_MISMATCH BIT(23) +#define CONNAC2X_RX_STATUS_FLAG_CIPHER_LENGTH_MISMATCH BIT(24) +#define CONNAC2X_RX_STATUS_FLAG_ICV_ERROR BIT(25) +#define CONNAC2X_RX_STATUS_FLAG_TKIPMIC_ERROR BIT(26) +#define CONNAC2X_RX_STATUS_FLAG_FCS_ERROR BIT(27) +#define CONNAC2X_RX_STATUS_DW1_HW_INFO_MASK BITS(29, 31) +#define CONNAC2X_RX_STATUS_DW1_HW_INFO_OFFSET 29 +#define CONNAC2X_RX_STATUS_DW1_BAND_MASK BIT(28) +#define CONNAC2X_RX_STATUS_DW1_BAND_OFFSET 28 + + +#define CONNAC2X_RX_STATUS_FLAG_ERROR_MASK (CONNAC2X_RX_STATUS_FLAG_FCS_ERROR\ + | CONNAC2X_RX_STATUS_FLAG_ICV_ERROR \ + | CONNAC2X_RX_STATUS_FLAG_CIPHER_LENGTH_MISMATCH)/* No TKIP MIC error */ + +/* DW 2 */ +#define CONNAC2X_RX_STATUS_BSSID_MASK BITS(0, 5) +#define CONNAC2X_RX_STATUS_BSSID_OFFSET 0 +#define CONNAC2X_RX_STATUS_FLAG_BF_CQI BIT(7) +#define CONNAC2X_RX_STATUS_HEADER_LEN_MASK BITS(8, 12) +#define CONNAC2X_RX_STATUS_HEADER_LEN_OFFSET 8 +#define CONNAC2X_RX_STATUS_FLAG_HEADER_TRAN BIT(13) +#define CONNAC2X_RX_STATUS_HEADER_OFFSET_MASK BITS(14, 15) +#define CONNAC2X_RX_STATUS_HEADER_OFFSET_OFFSET 14 +#define CONNAC2X_RX_STATUS_TID_MASK BITS(16, 19) +#define CONNAC2X_RX_STATUS_TID_OFFSET 16 +#define CONNAC2X_RX_STATUS_FLAG_SW_BIT BIT(22) +#define CONNAC2X_RX_STATUS_FLAG_DE_AMSDU_FAIL BIT(23) +#define CONNAC2X_RX_STATUS_FLAG_EXCEED_LEN BIT(24) +#define CONNAC2X_RX_STATUS_FLAG_TRANS_FAIL BIT(25) +#define CONNAC2X_RX_STATUS_FLAG_INTF BIT(26) +#define CONNAC2X_RX_STATUS_FLAG_FRAG BIT(27) +#define CONNAC2X_RX_STATUS_FLAG_NULL BIT(28) +#define CONNAC2X_RX_STATUS_FLAG_NDATA BIT(29) +#define CONNAC2X_RX_STATUS_FLAG_NAMP BIT(30) +#define CONNAC2X_RX_STATUS_FLAG_BF_RPT BIT(31) + +/* DW 3 */ +#define CONNAC2X_RX_STATUS_RXV_SEQ_NO_MASK BITS(0, 7) +#define CONNAC2X_RX_STATUS_RXV_SEQ_NO_OFFSET 0 +#define CONNAC2X_RX_STATUS_CH_FREQ_MASK BITS(8, 15) +#define CONNAC2X_RX_STATUS_CH_FREQ_OFFSET 8 +#define CONNAC2X_RX_STATUS_A1_TYPE_MASK BITS(16, 17) +#define CONNAC2X_RX_STATUS_A1_TYPE_OFFSET 16 +#define CONNAC2X_RX_STATUS_UC2ME BIT(16) +#define CONNAC2X_RX_STATUS_MC_FRAME BIT(17) +#define CONNAC2X_RX_STATUS_BC_FRAME BITS(16, 17) + +#define CONNAC2X_RX_STATUS_FLAG_HTC BIT(18) +#define CONNAC2X_RX_STATUS_FLAG_TCL BIT(19) +#define CONNAC2X_RX_STATUS_FLAG_BBM BIT(20) +#define CONNAC2X_RX_STATUS_FLAG_BU BIT(21) +#define CONNAC2X_RX_STATUS_DW3_HW_INFO_MASK BITS(22, 31) +#define CONNAC2X_RX_STATUS_DW3_HW_INFO_OFFSET 22 + +/* DW 4 */ +#define CONNAC2X_RX_STATUS_PF_MASK BITS(0, 1) +#define CONNAC2X_RX_STATUS_PF_OFFSET 0 +#define CONNAC2X_RX_STATUS_FLAG_DP BIT(9) +#define CONNAC2X_RX_STATUS_FLAG_CLS BIT(10) +#define CONNAC2X_RX_STATUS_OFLD_MASK BITS(11, 12) +#define CONNAC2X_RX_STATUS_OFLD_OFFSET 11 +#define CONNAC2X_RX_STATUS_FLAG_MGC BIT(13) +#define CONNAC2X_RX_STATUS_WOL_MASK BITS(14, 18) +#define CONNAC2X_RX_STATUS_WOL_OFFSET 14 +#define CONNAC2X_RX_STATUS_CLS_BITMAP_MASK BITS(19, 28) +#define CONNAC2X_RX_STATUS_CLS_BITMAP_OFFSET 19 +#define CONNAC2X_RX_STATUS_FLAG_PF_MODE BIT(29) +#define CONNAC2X_RX_STATUS_PF_STS_MASK BITS(30, 31) +#define CONNAC2X_RX_STATUS_PF_STS_OFFSET 30 + +/* DW 5 */ +#define CONNAC2X_RX_STATUS_DW5_CLS_BITMAP_MASK BITS(0, 9) +#define CONNAC2X_RX_STATUS_DW5_CLS_BITMAP_OFFSET 0 +#define CONNAC2X_RX_STATUS_MAC_MASK BIT(31) +#define CONNAC2X_RX_STATUS_MAC_OFFSET 31 + + +/* + * GROUP_VLD: RFB Group valid indicators + * Bit[0] indicates GROUP1 (DW10~DW13) + * Bit[1] indicates GROUP2 (DW14~DW15) + * Bit[2] indicates GROUP3 (DW16~DW17) + * Bit[3] indicates GROUP4 (DW6~DW9) + * Bit[4] indicates GROUP5 (DW18~DW33) + */ +#define CONNAC2X_RX_STATUS_GROUP1_VALID BIT(0) +#define CONNAC2X_RX_STATUS_GROUP2_VALID BIT(1) +#define CONNAC2X_RX_STATUS_GROUP3_VALID BIT(2) +#define CONNAC2X_RX_STATUS_GROUP4_VALID BIT(3) +#define CONNAC2X_RX_STATUS_GROUP5_VALID BIT(4) + +#define CONNAC2X_RX_STATUS_FIXED_LEN 24 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/*! A data structure which is identical with MAC RX DMA Descriptor */ +struct HW_MAC_CONNAC2X_RX_DESC { + uint32_t u4DW0; + uint32_t u4DW1; + uint32_t u4DW2; + uint32_t u4DW3; + uint32_t u4DW4; + uint32_t u4DW5; +}; + +/******************************************************************************* +* P U B 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_DESC_GET_FIELD(_rHwMacTxDescField, _mask, _offset) \ + (((_rHwMacTxDescField) & (_mask)) >> (_offset)) + +/*------------------------------------------------------------------------------ + * MACRO for HW_MAC_RX_DESC_T + *------------------------------------------------------------------------------ +*/ + +#define HAL_MAC_CONNAC2X_RX_STATUS_GET_RX_BYTE_CNT(_prHwMacRxDesc) \ + RX_DESC_GET_FIELD((_prHwMacRxDesc)->u4DW0, \ + CONNAC2X_RX_STATUS_RX_BYTE_COUNT_MASK, \ + CONNAC2X_RX_STATUS_RX_BYTE_COUNT_OFFSET) + +#define HAL_MAC_CONNAC2X_RX_STATUS_GET_ETH_TYPE_OFFSET(_prHwMacRxDesc) \ +RX_DESC_GET_FIELD((_prHwMacRxDesc)->u4DW0, \ +CONNAC2X_RX_STATUS_ETH_TYPE_MASK, CONNAC2X_RX_STATUS_ETH_TYPE_OFFSET) + +#define HAL_MAC_CONNAC2X_RX_STATUS_GET_PKT_TYPE(_prHwMacRxDesc) \ +RX_DESC_GET_FIELD((_prHwMacRxDesc)->u4DW0, \ +CONNAC2X_RX_STATUS_PKT_TYPE_MASK, CONNAC2X_RX_STATUS_PKT_TYPE_OFFSET) + +#define HAL_MAC_CONNAC2X_RX_STATUS_GET_WLAN_IDX(_prHwMacRxDesc) \ +RX_DESC_GET_FIELD((_prHwMacRxDesc)->u4DW1, \ +CONNAC2X_RX_STATUS_WLAN_INDEX_MASK, CONNAC2X_RX_STATUS_WLAN_INDEX_OFFSET) + +#define HAL_MAC_CONNAC2X_RX_STATUS_GET_GROUP_VLD(_prHwMacRxDesc) \ +RX_DESC_GET_FIELD((_prHwMacRxDesc)->u4DW1, \ +CONNAC2X_RX_STATUS_GROUP_VLD_MASK, CONNAC2X_RX_STATUS_GROUP_VLD_OFFSET) + +#define HAL_MAC_CONNAC2X_RX_STATUS_GET_SEC_MODE(_prHwMacRxDesc) \ +RX_DESC_GET_FIELD((_prHwMacRxDesc)->u4DW1, \ +CONNAC2X_RX_STATUS_SEC_MASK, CONNAC2X_RX_STATUS_SEC_OFFSET) + +#define HAL_MAC_CONNAC2X_RX_STATUS_GET_KID(_prHwMacRxDesc) \ +RX_DESC_GET_FIELD((_prHwMacRxDesc)->u4DW1, \ +CONNAC2X_RX_STATUS_KEYID_MASK, CONNAC2X_RX_STATUS_KEYID_OFFSET) + +#define HAL_MAC_CONNAC2X_RX_STATUS_IS_CIPHER_MISMATCH(_prHwMacRxDesc) \ +(((_prHwMacRxDesc)->u4DW1 & CONNAC2X_RX_STATUS_FLAG_CIPHER_MISMATCH) \ + ? TRUE : FALSE) +#define HAL_MAC_CONNAC2X_RX_STATUS_IS_CLM_ERROR(_prHwMacRxDesc) \ +(((_prHwMacRxDesc)->u4DW1 & CONNAC2X_RX_STATUS_FLAG_CIPHER_LENGTH_MISMATCH) \ + ? TRUE : FALSE) +#define HAL_MAC_CONNAC2X_RX_STATUS_IS_ICV_ERROR(_prHwMacRxDesc) \ +(((_prHwMacRxDesc)->u4DW1 & CONNAC2X_RX_STATUS_FLAG_ICV_ERROR)?TRUE:FALSE) + +#define HAL_MAC_CONNAC2X_RX_STATUS_IS_TKIP_MIC_ERROR(_prHwMacRxDesc) \ +(((_prHwMacRxDesc)->u4DW1 & CONNAC2X_RX_STATUS_FLAG_TKIPMIC_ERROR)?TRUE:FALSE) + +#define HAL_MAC_CONNAC2X_RX_STATUS_IS_FCS_ERROR(_prHwMacRxDesc) \ +(((_prHwMacRxDesc)->u4DW1 & CONNAC2X_RX_STATUS_FLAG_FCS_ERROR)?TRUE:FALSE) + +#define HAL_MAC_CONNAC2X_RX_STATUS_IS_ERROR(_prHwMacRxDesc) \ +(((_prHwMacRxDesc)->u4DW1 & CONNAC2X_RX_STATUS_FLAG_ERROR_MASK)?TRUE:FALSE) + +#define HAL_MAC_CONNAC2X_RX_STATUS_GET_HEADER_OFFSET(_prHwMacRxDesc) \ +((RX_DESC_GET_FIELD((_prHwMacRxDesc)->u4DW2, \ +CONNAC2X_RX_STATUS_HEADER_OFFSET_MASK, \ +CONNAC2X_RX_STATUS_HEADER_OFFSET_OFFSET)) << 1) + +#define HAL_MAC_CONNAC2X_RX_STATUS_GET_HEADER_LEN(_prHwMacRxDesc) \ +(RX_DESC_GET_FIELD((_prHwMacRxDesc)->u4DW2, \ +CONNAC2X_RX_STATUS_HEADER_LEN_MASK, CONNAC2X_RX_STATUS_HEADER_LEN_OFFSET) << 1) + +#define HAL_MAC_CONNAC2X_RX_STATUS_IS_HEADER_TRAN(_prHwMacRxDesc) \ +(((_prHwMacRxDesc)->u4DW2 & CONNAC2X_RX_STATUS_FLAG_HEADER_TRAN)?TRUE:FALSE) + +#define HAL_MAC_CONNAC2X_RX_STATUS_IS_DAF(_prHwMacRxDesc) \ +(((_prHwMacRxDesc)->u4DW2 & CONNAC2X_RX_STATUS_FLAG_DE_AMSDU_FAIL)?TRUE:FALSE) + +#define HAL_MAC_CONNAC2X_RX_STATUS_IS_FRAG(_prHwMacRxDesc) \ +(((_prHwMacRxDesc)->u4DW2 & CONNAC2X_RX_STATUS_FLAG_FRAG)?TRUE:FALSE) + +#define HAL_MAC_CONNAC2X_RX_STATUS_IS_NDATA(_prHwMacRxDesc) \ +(((_prHwMacRxDesc)->u4DW2 & CONNAC2X_RX_STATUS_FLAG_NDATA)?TRUE:FALSE) + +#define HAL_MAC_CONNAC2X_RX_STATUS_IS_NAMP(_prHwMacRxDesc) \ +(((_prHwMacRxDesc)->u4DW2 & CONNAC2X_RX_STATUS_FLAG_NAMP)?TRUE:FALSE) + +#define HAL_MAC_CONNAC2X_RX_STATUS_IS_SW_DEFINE_RX_CLASSERR(_prHwMacRxDesc) \ +(((_prHwMacRxDesc)->u4DW2 & CONNAC2X_RX_STATUS_FLAG_SW_BIT)?TRUE:FALSE) + +#define HAL_MAC_CONNAC2X_RX_STATUS_IS_LLC_MIS(_prHwMacRxDesc) \ +(((_prHwMacRxDesc)->u4DW2 & CONNAC2X_RX_STATUS_FLAG_TRANS_FAIL)?TRUE:FALSE) + +#define HAL_MAC_CONNAC2X_RX_STATUS_GET_TID(_prHwMacRxDesc) \ +RX_DESC_GET_FIELD((_prHwMacRxDesc)->u4DW2, \ +CONNAC2X_RX_STATUS_TID_MASK, CONNAC2X_RX_STATUS_TID_OFFSET) + +#define HAL_MAC_CONNAC2X_RX_STATUS_GET_RXV_SEQ_NO(_prHwMacRxDesc) \ +RX_DESC_GET_FIELD((_prHwMacRxDesc)->u4DW3, \ +CONNAC2X_RX_STATUS_RXV_SEQ_NO_MASK, CONNAC2X_RX_STATUS_RXV_SEQ_NO_OFFSET) + +#define HAL_MAC_CONNAC2X_RX_STATUS_IS_UC2ME(_prHwMacRxDesc) \ +(((_prHwMacRxDesc)->u4DW3 & CONNAC2X_RX_STATUS_UC2ME)?TRUE:FALSE) + +#define HAL_MAC_CONNAC2X_RX_STATUS_IS_MC(_prHwMacRxDesc) \ +(((_prHwMacRxDesc)->u4DW3 & CONNAC2X_RX_STATUS_MC_FRAME)?TRUE:FALSE) + +#define HAL_MAC_CONNAC2X_RX_STATUS_IS_BC(_prHwMacRxDesc) \ +(((_prHwMacRxDesc)->u4DW3 & CONNAC2X_RX_STATUS_BC_FRAME) \ + == CONNAC2X_RX_STATUS_BC_FRAME?TRUE:FALSE) + +#define HAL_RX_CONNAC2X_STATUS_GET_PAYLOAD_FORMAT(_prHwMacRxDesc) \ +RX_DESC_GET_FIELD((_prHwMacRxDesc)->u4DW4, \ +CONNAC2X_RX_STATUS_PF_MASK, CONNAC2X_RX_STATUS_PF_OFFSET) + +#define HAL_MAC_CONNAC2X_RX_STATUS_GET_RF_BAND(_prHwMacRxDesc) \ +(((RX_DESC_GET_FIELD((_prHwMacRxDesc)->u4DW3, \ +CONNAC2X_RX_STATUS_CH_FREQ_MASK, CONNAC2X_RX_STATUS_CH_FREQ_OFFSET)) \ +<= HW_CHNL_NUM_MAX_2G4) ? BAND_2G4 : BAND_5G) + +#define HAL_MAC_CONNAC2X_RX_STATUS_GET_CHNL_NUM(_prHwMacRxDesc) \ +(RX_DESC_GET_FIELD((_prHwMacRxDesc)->u4DW3, \ +CONNAC2X_RX_STATUS_CH_FREQ_MASK, CONNAC2X_RX_STATUS_CH_FREQ_OFFSET)) + +#define HAL_MAC_CONNAC2X_RX_STATUS_GET_TCL(_prHwMacRxDesc) \ +(((_prHwMacRxDesc)->u4DW3 & CONNAC2X_RX_STATUS_FLAG_TCL)?TRUE:FALSE) + +#define HAL_MAC_CONNAC2X_RX_STATUS_GET_PAYLOAD_FORMAT(_prHwMacRxDesc) \ +RX_DESC_GET_FIELD((_prHwMacRxDesc)->u4DW4, \ +CONNAC2X_RX_STATUS_PF_MASK, CONNAC2X_RX_STATUS_PF_OFFSET) + +#define HAL_MAC_CONNAC2X_RX_STATUS_GET_OFLD(_prHwMacRxDesc) \ +(((_prHwMacRxDesc)->u4DW4 & CONNAC2X_RX_STATUS_OFLD_MASK) >> \ +CONNAC2X_RX_STATUS_OFLD_OFFSET) + +/******************************************************************************* +* 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_SUPPORT_CONNAC2X == 1 */ +#endif /* _NIC_CONNAC2X_RX_H */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_connac2x_tx.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_connac2x_tx.h new file mode 100644 index 0000000000000..2fa626e0d958f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_connac2x_tx.h @@ -0,0 +1,871 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file nic_connac2x_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. +* +*/ + + +#ifndef _NIC_CONNAC2X_TX_H +#define _NIC_CONNAC2X_TX_H + +#if (CFG_SUPPORT_CONNAC2X == 1) +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define NORMAL_GI 0 +#define SHORT_GI 1 +#define CONNAC2X_TX_DESC_LIFE_TIME_UNIT_IN_POWER_OF_2 6 + +/*------------------------------------------------------------------------*/ +/* Tx descriptor field related information */ +/*------------------------------------------------------------------------*/ +/* DW 0 */ +#define CONNAC2X_TX_DESC_TX_BYTE_COUNT_MASK BITS(0, 15) +#define CONNAC2X_TX_DESC_TX_BYTE_COUNT_OFFSET 0 + +#define CONNAC2X_TX_DESC_ETHER_TYPE_OFFSET_MASK BITS(16, 22) +#define CONNAC2X_TX_DESC_ETHER_TYPE_OFFSET_OFFSET 16 + +#define CONNAC2X_TX_DESC_PACKET_FORMAT_MASK BITS(23, 24) +#define CONNAC2X_TX_DESC_PACKET_FORMAT_OFFSET 23 + +#define CONNAC2X_TX_DESC_QUEUE_INDEX_MASK BITS(25, 31) +#define CONNAC2X_TX_DESC_QUEUE_INDEX_OFFSET 25 + +/* DW 1 */ +#define CONNAC2X_TX_DESC_WLAN_INDEX_MASK BITS(0, 9) +#define CONNAC2X_TX_DESC_WLAN_INDEX_OFFSET 0 +#define CONNAC2X_TX_DESC_VTA_MASK BIT(10) +#define CONNAC2X_TX_DESC_VTA_OFFSET 10 + + +#define CONNAC2X_TX_DESC_HEADER_FORMAT_MASK BITS(16, 17) +#define CONNAC2X_TX_DESC_HEADER_FORMAT_OFFSET 16 + +#define CONNAC2X_TX_DESC_NON_802_11_MORE_DATA BIT(11) +#define CONNAC2X_TX_DESC_NON_802_11_EOSP BIT(12) +#define CONNAC2X_TX_DESC_NON_802_11_REMOVE_VLAN BIT(13) +#define CONNAC2X_TX_DESC_NON_802_11_VLAN_FIELD BIT(14) +#define CONNAC2X_TX_DESC_NON_802_11_ETHERNET_II BIT(15) +#define CONNAC2X_TX_DESC_NOR_802_11_HEADER_LENGTH_MASK BITS(11, 15) +#define CONNAC2X_TX_DESC_NOR_802_11_HEADER_LENGTH_OFFSET 11 +#define CONNAC2X_TX_DESC_ENH_802_11_EOSP BIT(12) +#define CONNAC2X_TX_DESC_ENH_802_11_AMSDU BIT(13) + +#define CONNAC2X_TX_DESC_HEADER_PADDING_LENGTH_MASK BIT(18) +#define CONNAC2X_TX_DESC_HEADER_PADDING_LENGTH_OFFSET 18 +#define CONNAC2X_TX_DESC_HEADER_PADDING_MODE BIT(19) + +#define CONNAC2X_TX_DESC_TID_MASK BITS(20, 22) +#define CONNAC2X_TX_DESC_TID_OFFSET 20 +#define CONNAC2X_TX_DESC_TID_NUM 8 + +#define CONNAC2X_TX_DESC_TXD_UTXB_AMSDU_MASK BIT(23) +#define CONNAC2X_TX_DESC_TXD_UTXB_AMSDU_OFFSET 23 + +#define CONNAC2X_TX_DESC_OWN_MAC_MASK BITS(24, 29) +#define CONNAC2X_TX_DESC_OWN_MAC_OFFSET 24 + + #define CONNAC2X_TX_DESC_TGID_MASK BIT(30) +#define CONNAC2X_TX_DESC_TGID_OFFSET 30 +#define CONNAC2X_TX_DESC_FORMAT BIT(31) + +/* DW 2 */ +#define CONNAC2X_TX_DESC_SUB_TYPE_MASK BITS(0, 3) +#define CONNAC2X_TX_DESC_SUB_TYPE_OFFSET 0 +#define CONNAC2X_TX_DESC_TYPE_MASK BITS(4, 5) +#define CONNAC2X_TX_DESC_TYPE_OFFSET 4 +#define CONNAC2X_TX_DESC_NDP BIT(6) +#define CONNAC2X_TX_DESC_NDPA BIT(7) + +#define CONNAC2X_TX_DESC_SOUNDING BIT(8) +#define CONNAC2X_TX_DESC_FORCE_RTS_CTS BIT(9) +#define CONNAC2X_TX_DESC_BROADCAST_MULTICAST BIT(10) +#define CONNAC2X_TX_DESC_BIP_PROTECTED BIT(11) +#define CONNAC2X_TX_DESC_DURATION_FIELD_CONTROL BIT(12) +#define CONNAC2X_TX_DESC_HTC_EXISTS BIT(13) +#define CONNAC2X_TX_DESC_FRAGMENT_MASK BITS(14, 15) +#define CONNAC2X_TX_DESC_FRAGMENT_OFFSET 14 + +#define CONNAC2X_TX_DESC_REMAINING_MAX_TX_TIME_MASK BITS(16, 23) +#define CONNAC2X_TX_DESC_REMAINING_MAX_TX_TIME_OFFSET 16 + +#define CONNAC2X_TX_DESC_POWER_OFFSET_MASK BITS(24, 29) +#define CONNAC2X_TX_DESC_POWER_OFFSET_OFFSET 24 +#define CONNAC2X_TX_DESC_FIXED_RATE_MODE BIT(30) +#define CONNAC2X_TX_DESC_FIXED_RATE BIT(31) + +/* DW 3 */ +#define CONNAC2X_TX_DESC_NO_ACK BIT(0) +#define CONNAC2X_TX_DESC_PROTECTED_FRAME BIT(1) +#define CONNAC2X_TX_DESC_EXTEND_MORE_DATA BIT(2) +#define CONNAC2X_TX_DESC_EXTEND_EOSP BIT(3) +#define CONNAC2X_TX_DESC_DA_SOURCE BIT(4) +#define CONNAC2X_TX_DESC_TIMING_MEASUREMENT BIT(5) +#define CONNAC2X_TX_DESC_TX_COUNT_MASK BITS(6, 10) +#define CONNAC2X_TX_DESC_TX_COUNT_OFFSET 6 +#define CONNAC2X_TX_DESC_REMAINING_TX_COUNT_MASK BITS(11, 15) +#define CONNAC2X_TX_DESC_REMAINING_TX_COUNT_OFFSET 11 +#define CONNAC2X_TX_DESC_SEQUENCE_NUMBER_MASK BITS(16, 27) +#define CONNAC2X_TX_DESC_SEQUENCE_NUMBER_MASK_OFFSET 16 +#define CONNAC2X_TX_DESC_BA_DISABLE BIT(28) +#define CONNAC2X_TX_DESC_POWER_MANAGEMENT_CONTROL BIT(29) +#define CONNAC2X_TX_DESC_PN_IS_VALID BIT(30) +#define CONNAC2X_TX_DESC_SN_IS_VALID BIT(31) + +/* DW 4 */ +#define CONNAC2X_TX_DESC_PN_PART1 BITS(0, 31) + +/* DW 5 */ +#define CONNAC2X_TX_DESC_PACKET_ID_MASK BITS(0, 7) +#define CONNAC2X_TX_DESC_PACKET_ID_OFFSET 0 +#define CONNAC2X_TX_DESC_TX_STATUS_FORMAT BIT(8) +#define CONNAC2X_TX_DESC_TX_STATUS_FORMAT_OFFSET 8 +#define CONNAC2X_TX_DESC_TX_STATUS_TO_MCU BIT(9) +#define CONNAC2X_TX_DESC_TX_STATUS_TO_HOST BIT(10) +#define CONNAC2X_TX_DESC_ADD_BA BIT(14) +#define CONNAC2X_TX_DESC_ADD_BA_OFFSET 14 +#define CONNAC2X_TX_DESC_MD_MASK BIT(15) +#define CONNAC2X_TX_DESC_MD_OFFSET 15 +#define CONNAC2X_TX_DESC_PN_PART2_MASK BITS(16, 31) +#define CONNAC2X_TX_DESC_PN_PART2__OFFSET 16 + +/* DW 6 *//* FR = 1 */ +#define CONNAC2X_TX_DESC_BANDWIDTH_MASK BITS(0, 2) +#define CONNAC2X_TX_DESC_BANDWIDTH_OFFSET 0 +#define CONNAC2X_TX_DESC_DYNAMIC_BANDWIDTH BIT(3) + #define CONNAC2X_TX_DESC_ANTENNA_INDEX_MASK BITS(4, 7) +#define CONNAC2X_TX_DESC_ANTENNA_INDEX_OFFSET 4 +#define CONNAC2X_TX_DESC_SPE_IDX_SEL BIT(10) +#define CONNAC2X_TX_DESC_SPE_IDX_SEL_OFFSET 10 +/* in DW5 for AXE : LDPC, HE_LTF, GI_TYPE*/ +#define CONNAC2X_TX_DESC_LDPC BIT(11) +#define CONNAC2X_TX_DESC_LDPC_OFFSET 11 +#define CONNAC2X_TX_DESC_HE_LTF_MASK BITS(12, 13) +#define CONNAC2X_TX_DESC_HE_LTF_OFFSET 12 +#define CONNAC2X_TX_DESC_GI_TYPE BITS(14, 15) +#define CONNAC2X_TX_DESC_GI_TYPE_OFFSET 14 +#define CONNAC2X_TX_DESC_FIXDE_RATE_MASK BITS(16, 29) +#define CONNAC2X_TX_DESC_FIXDE_RATE_OFFSET 16 +#define CONNAC2X_TX_DESC_TXE_BF BIT(30) +#define CONNAC2X_TX_DESC_TXI_BF BIT(31) + +/* DW 7 */ +#define CONNAC2X_TX_DESC_TXD_ARRIVAL_TIME_MASK BITS(0, 9) + +#define CONNAC2X_TX_DESC_HW_AMSDU BIT(10) +#define CONNAC2X_TX_DESC_SPE_EXT_IDX_MASK BITS(11, 15) +#define CONNAC2X_TX_DESC_SPE_EXT_IDX_OFFSET 11 +/* For cut-through only */ +#define CONNAC2X_TX_DESC7_SUB_TYPE_MASK BITS(16, 19) +#define CONNAC2X_TX_DESC7_SUB_TYPE_OFFSET 16 +/* For cut-through only */ +#define CONNAC2X_TX_DESC7_TYPE_MASK BITS(20, 21) +#define CONNAC2X_TX_DESC7_TYPE_OFFSET 20 + +#define CONNAC2X_TX_DESC_IP_CHKSUM_OFFLOAD BIT(28) +#define CONNAC2X_TX_DESC_TCP_UDP_CHKSUM_OFFLOAD BIT(29) +#define CONNAC2X_TX_DESC_TXD_LENGTH_MASK BITS(30, 31) +#define CONNAC2X_TX_DESC_TXD_LENGTH_OFFSET 30 + +/* For Debug Information Use */ +#define CONNAC2X_TX_DESC_PSE_FID_MASK BITS(16, 27) +#define CONNAC2X_TX_DESC_PSE_FID_OFFSET 16 +#define CONNAC2X_TX_DESC_CTXD_CNT_MASK BITS(23, 25) +#define CONNAC2X_TX_DESC_CTXD_CNT_OFFSET 23 +#define CONNAC2X_TX_DESC_CTXD BIT(26) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +struct HW_MAC_CONNAC2X_TX_DESC { + uint32_t u4DW0; + uint32_t u4DW1; + uint32_t u4DW2; + uint32_t u4DW3; + uint32_t u4PN1; + uint16_t u2DW5_0; + uint16_t u2PN2; + uint32_t u4DW6; + uint32_t u4DW7; +}; + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/*------------------------------------------------------------------------------ + * MACRO for HW_MAC_TX_DESC_T + *------------------------------------------------------------------------------ + */ + +#define HAL_MAC_CONNAC2X_TXD_GET_TX_BYTE_COUNT(_prHwMacTxDesc) \ +TX_DESC_GET_FIELD((_prHwMacTxDesc)->u4DW0, \ +CONNAC2X_TX_DESC_TX_BYTE_COUNT_MASK, CONNAC2X_TX_DESC_TX_BYTE_COUNT_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_SET_TX_BYTE_COUNT(_prHwMacTxD, _u2TxByteCount)\ +TX_DESC_SET_FIELD(((_prHwMacTxD)->u4DW0), ((uint16_t)_u2TxByteCount), \ +CONNAC2X_TX_DESC_TX_BYTE_COUNT_MASK, CONNAC2X_TX_DESC_TX_BYTE_COUNT_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_GET_ETHER_TYPE_OFFSET(_prHwMacTxDesc) \ +TX_DESC_GET_FIELD((_prHwMacTxDesc)->u4DW0, \ +CONNAC2X_TX_DESC_ETHER_TYPE_OFFSET_MASK, \ +CONNAC2X_TX_DESC_ETHER_TYPE_OFFSET_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_SET_ETHER_TYPE_OFFSET(_prHwMacTxD, _ucEthTypOff)\ +TX_DESC_SET_FIELD(((_prHwMacTxD)->u4DW0), ((uint8_t)_ucEthTypOff), \ +CONNAC2X_TX_DESC_ETHER_TYPE_OFFSET_MASK, \ +CONNAC2X_TX_DESC_ETHER_TYPE_OFFSET_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_IS_IP_CHKSUM_ENABLED(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW7 & CONNAC2X_TX_DESC_IP_CHKSUM_OFFLOAD)?FALSE:TRUE) + +#define HAL_MAC_CONNAC2X_TXD_SET_IP_CHKSUM(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW7 |= CONNAC2X_TX_DESC_IP_CHKSUM_OFFLOAD) + +#define HAL_MAC_CONNAC2X_TXD_UNSET_IP_CHKSUM(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW7 &= ~CONNAC2X_TX_DESC_IP_CHKSUM_OFFLOAD) + +#define HAL_MAC_CONNAC2X_TXD_IS_TCP_UDP_CHKSUM_ENABLED(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW7 & CONNAC2X_TX_DESC_TCP_UDP_CHKSUM_OFFLOAD)?FALSE:TRUE) + +#define HAL_MAC_CONNAC2X_TXD_SET_TCP_UDP_CHKSUM(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW7 |= CONNAC2X_TX_DESC_TCP_UDP_CHKSUM_OFFLOAD) + +#define HAL_MAC_CONNAC2X_TXD_UNSET_TCP_UDP_CHKSUM(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW7 &= ~CONNAC2X_TX_DESC_TCP_UDP_CHKSUM_OFFLOAD) + +#define HAL_MAC_CONNAC2X_TXD_GET_QUEUE_INDEX(_prHwMacTxDesc) \ +TX_DESC_GET_FIELD((_prHwMacTxDesc)->u4DW0,\ +CONNAC2X_TX_DESC_QUEUE_INDEX_MASK, CONNAC2X_TX_DESC_QUEUE_INDEX_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_SET_QUEUE_INDEX(_prHwMacTxDesc, _ucQueueIndex) \ +TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u4DW0), ((uint8_t)_ucQueueIndex), \ +CONNAC2X_TX_DESC_QUEUE_INDEX_MASK, CONNAC2X_TX_DESC_QUEUE_INDEX_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_GET_WLAN_INDEX(_prHwMacTxDesc) \ +TX_DESC_GET_FIELD((_prHwMacTxDesc)->u4DW1,\ +CONNAC2X_TX_DESC_WLAN_INDEX_MASK, CONNAC2X_TX_DESC_WLAN_INDEX_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_SET_WLAN_INDEX(_prHwMacTxDesc, _ucWlanIdx) \ +TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u4DW1), ((uint8_t)_ucWlanIdx), \ +CONNAC2X_TX_DESC_WLAN_INDEX_MASK, CONNAC2X_TX_DESC_WLAN_INDEX_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_IS_LONG_FORMAT(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW1 & CONNAC2X_TX_DESC_FORMAT)?TRUE:FALSE) + +#define HAL_MAC_CONNAC2X_TXD_SET_LONG_FORMAT(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW1 |= CONNAC2X_TX_DESC_FORMAT) + +#define HAL_MAC_CONNAC2X_TXD_SET_SHORT_FORMAT(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW1 &= ~CONNAC2X_TX_DESC_FORMAT) + +#define HAL_MAC_CONNAC2X_TXD_GET_HEADER_FORMAT(_prHwMacTxDesc) \ +TX_DESC_GET_FIELD((_prHwMacTxDesc)->u4DW1, \ +CONNAC2X_TX_DESC_HEADER_FORMAT_MASK, CONNAC2X_TX_DESC_HEADER_FORMAT_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_SET_HEADER_FORMAT(_prHwMacTxDesc, _ucHdrFormat) \ +TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u4DW1), \ +((uint8_t)_ucHdrFormat), CONNAC2X_TX_DESC_HEADER_FORMAT_MASK,\ +CONNAC2X_TX_DESC_HEADER_FORMAT_OFFSET) + +/* HF = 0x00, 802.11 normal mode */ +#define HAL_MAC_CONNAC2X_TXD_IS_MORE_DATA(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW1 & CONNAC2X_TX_DESC_NON_802_11_MORE_DATA)?TRUE:FALSE) +#define HAL_MAC_CONNAC2X_TXD_SET_MORE_DATA(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW1 |= CONNAC2X_TX_DESC_NON_802_11_MORE_DATA) +#define HAL_MAC_CONNAC2X_TXD_UNSET_MORE_DATA(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW1 &= ~CONNAC2X_TX_DESC_NON_802_11_MORE_DATA) + +#define HAL_MAC_CONNAC2X_TXD_IS_REMOVE_VLAN(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW1 & CONNAC2X_TX_DESC_NON_802_11_REMOVE_VLAN)?TRUE:FALSE) +#define HAL_MAC_CONNAC2X_TXD_SET_REMOVE_VLAN(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW1 |= CONNAC2X_TX_DESC_NON_802_11_REMOVE_VLAN) +#define HAL_MAC_CONNAC2X_TXD_UNSET_REMOVE_VLAN(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW1 &= ~CONNAC2X_TX_DESC_NON_802_11_REMOVE_VLAN) + +#define HAL_MAC_CONNAC2X_TXD_IS_VLAN(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW1 & CONNAC2X_TX_DESC_NON_802_11_VLAN_FIELD)?TRUE:FALSE) +#define HAL_MAC_CONNAC2X_TXD_SET_VLAN(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW1 |= CONNAC2X_TX_DESC_NON_802_11_VLAN_FIELD) +#define HAL_MAC_CONNAC2X_TXD_UNSET_VLAN(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW1 &= ~CONNAC2X_TX_DESC_NON_802_11_VLAN_FIELD) + +#define HAL_MAC_CONNAC2X_TXD_IS_ETHERNET_II(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW1 & CONNAC2X_TX_DESC_NON_802_11_ETHERNET_II)?TRUE:FALSE) +#define HAL_MAC_CONNAC2X_TXD_SET_ETHERNET_II(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW1 |= CONNAC2X_TX_DESC_NON_802_11_ETHERNET_II) +#define HAL_MAC_CONNAC2X_TXD_UNSET_ETHERNET_II(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW1 &= ~CONNAC2X_TX_DESC_NON_802_11_ETHERNET_II) + +/* HF = 0x00/0x11, 802.11 normal/enhancement mode */ +#define HAL_MAC_CONNAC2X_TXD_IS_EOSP(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW1 & CONNAC2X_TX_DESC_NON_802_11_EOSP)?TRUE:FALSE) +#define HAL_MAC_CONNAC2X_TXD_SET_EOSP(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW1 |= CONNAC2X_TX_DESC_NON_802_11_EOSP) +#define HAL_MAC_CONNAC2X_TXD_UNSET_EOSP(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW1 &= ~CONNAC2X_TX_DESC_NON_802_11_EOSP) + +/* HF = 0x11, 802.11 enhancement mode */ +#define HAL_MAC_CONNAC2X_TXD_IS_AMSDU(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW1 & CONNAC2X_TX_DESC_ENH_802_11_AMSDU)?TRUE:FALSE) +#define HAL_MAC_CONNAC2X_TXD_SET_AMSDU(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW1 |= CONNAC2X_TX_DESC_ENH_802_11_AMSDU) +#define HAL_MAC_CONNAC2X_TXD_UNSET_AMSDU(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW1 &= ~CONNAC2X_TX_DESC_ENH_802_11_AMSDU) + +/* HF = 0x10, non-802.11 */ +#define HAL_MAC_CONNAC2X_TXD_GET_802_11_HEADER_LENGTH(_prHwMacTxDesc) \ +TX_DESC_GET_FIELD((_prHwMacTxDesc)->u4DW1, \ +CONNAC2X_TX_DESC_NOR_802_11_HEADER_LENGTH_MASK, \ +CONNAC2X_TX_DESC_NOR_802_11_HEADER_LENGTH_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_SET_802_11_HEADER_LENGTH(_prHwMacTxD, _ucHdrLen)\ +TX_DESC_SET_FIELD(((_prHwMacTxD)->u4DW1), ((uint8_t)_ucHdrLen), \ +CONNAC2X_TX_DESC_NOR_802_11_HEADER_LENGTH_MASK, \ +CONNAC2X_TX_DESC_NOR_802_11_HEADER_LENGTH_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_GET_TXD_LENGTH(_prHwMacTxDesc) \ +TX_DESC_GET_FIELD((_prHwMacTxDesc)->u4DW7, \ +CONNAC2X_TX_DESC_TXD_LENGTH_MASK, CONNAC2X_TX_DESC_TXD_LENGTH_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_SET_TXD_LENGTH(_prHwMacTxDesc, _ucHdrPadding) \ +TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u4DW7), ((uint8_t)_ucHdrPadding), \ +CONNAC2X_TX_DESC_TXD_LENGTH_MASK, CONNAC2X_TX_DESC_TXD_LENGTH_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_GET_HEADER_PADDING(_prHwMacTxDesc) \ +TX_DESC_GET_FIELD((_prHwMacTxDesc)->u4DW1, \ +CONNAC2X_TX_DESC_HEADER_PADDING_LENGTH_MASK, \ +CONNAC2X_TX_DESC_HEADER_PADDING_LENGTH_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_SET_HEADER_PADDING(_prHwMacTxD, _ucHdrPadding) \ +TX_DESC_SET_FIELD(((_prHwMacTxD)->u4DW1), ((uint8_t)_ucHdrPadding), \ +CONNAC2X_TX_DESC_HEADER_PADDING_LENGTH_MASK, \ +CONNAC2X_TX_DESC_HEADER_PADDING_LENGTH_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_GET_UTXB_AMSDU(_prHwMacTxDesc) \ +TX_DESC_GET_FIELD((_prHwMacTxDesc)->u4DW1, \ +CONNAC2X_TX_DESC_TXD_UTXB_AMSDU_MASK, CONNAC2X_TX_DESC_TXD_UTXB_AMSDU_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_SET_UTXB_AMSDU(_prHwMacTxDesc, _ucHdrPadding) \ +TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u4DW1), ((uint8_t)_ucHdrPadding), \ +CONNAC2X_TX_DESC_TXD_UTXB_AMSDU_MASK, CONNAC2X_TX_DESC_TXD_UTXB_AMSDU_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_IS_HEADER_PADDING_IN_THE_HEAD(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW1 & CONNAC2X_TX_DESC_HEADER_PADDING_MODE)?TRUE:FALSE) +#define HAL_MAC_CONNAC2X_TXD_SET_HEADER_PADDING_IN_THE_HEAD(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW1 |= CONNAC2X_TX_DESC_HEADER_PADDING_MODE) +#define HAL_MAC_CONNAC2X_TXD_SET_HEADER_PADDING_IN_THE_TAIL(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW1 &= ~CONNAC2X_TX_DESC_HEADER_PADDING_MODE) + +#define HAL_MAC_CONNAC2X_TXD_GET_TID(_prHwMacTxDesc) \ +TX_DESC_GET_FIELD((_prHwMacTxDesc)->u4DW1, CONNAC2X_TX_DESC_TID_MASK, \ +CONNAC2X_TX_DESC_TID_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_SET_TID(_prHwMacTxDesc, _ucTID) \ +TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u4DW1), \ +((uint8_t)_ucTID), CONNAC2X_TX_DESC_TID_MASK, CONNAC2X_TX_DESC_TID_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_GET_PKT_FORMAT(_prHwMacTxDesc) \ +TX_DESC_GET_FIELD((_prHwMacTxDesc)->u4DW0, \ +CONNAC2X_TX_DESC_PACKET_FORMAT_MASK, CONNAC2X_TX_DESC_PACKET_FORMAT_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_SET_PKT_FORMAT(_prHwMacTxDesc, _ucPktFormat) \ +TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u4DW0), ((uint8_t)_ucPktFormat), \ +CONNAC2X_TX_DESC_PACKET_FORMAT_MASK, CONNAC2X_TX_DESC_PACKET_FORMAT_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_GET_OWN_MAC_INDEX(_prHwMacTxDesc) \ +TX_DESC_GET_FIELD((_prHwMacTxDesc)->u4DW1, \ +CONNAC2X_TX_DESC_OWN_MAC_MASK, CONNAC2X_TX_DESC_OWN_MAC_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_SET_OWN_MAC_INDEX(_prHwMacTxDesc, _ucOwnMacIdx) \ +TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u4DW1), ((uint8_t)_ucOwnMacIdx), \ +CONNAC2X_TX_DESC_OWN_MAC_MASK, CONNAC2X_TX_DESC_OWN_MAC_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_GET_SUB_TYPE(_prHwMacTxDesc) \ +TX_DESC_GET_FIELD((_prHwMacTxDesc)->u4DW2, \ +CONNAC2X_TX_DESC_SUB_TYPE_MASK, CONNAC2X_TX_DESC_SUB_TYPE_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_SET_SUB_TYPE(_prHwMacTxDesc, _ucSubType) \ +TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u4DW2), ((uint8_t)_ucSubType), \ +CONNAC2X_TX_DESC_SUB_TYPE_MASK, CONNAC2X_TX_DESC_SUB_TYPE_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_GET_TYPE(_prHwMacTxDesc) \ +TX_DESC_GET_FIELD((_prHwMacTxDesc)->u4DW2, CONNAC2X_TX_DESC_TYPE_MASK, \ +CONNAC2X_TX_DESC_TYPE_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_SET_TYPE(_prHwMacTxDesc, _ucType) \ +TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u4DW2), ((uint8_t)_ucType), \ +CONNAC2X_TX_DESC_TYPE_MASK, CONNAC2X_TX_DESC_TYPE_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_IS_NDP(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW2 & CONNAC2X_TX_DESC_NDP)?TRUE:FALSE) + +#define HAL_MAC_CONNAC2X_TXD_SET_NDP(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW2 |= CONNAC2X_TX_DESC_NDP) + +#define HAL_MAC_CONNAC2X_TXD_UNSET_NDP(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW2 &= ~CONNAC2X_TX_DESC_NDP) + +#define HAL_MAC_CONNAC2X_TXD_IS_NDPA(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW2 & CONNAC2X_TX_DESC_NDPA)?TRUE:FALSE) + +#define HAL_MAC_CONNAC2X_TXD_SET_NDPA(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW2 |= CONNAC2X_TX_DESC_NDPA) + +#define HAL_MAC_CONNAC2X_TXD_UNSET_NDPA(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW2 &= ~CONNAC2X_TX_DESC_NDPA) + +#define HAL_MAC_CONNAC2X_TXD_IS_SOUNDING_FRAME(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW2 & CONNAC2X_TX_DESC_SOUNDING)?TRUE:FALSE) + +#define HAL_MAC_CONNAC2X_TXD_SET_SOUNDING_FRAME(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW2 |= CONNAC2X_TX_DESC_SOUNDING) + +#define HAL_MAC_CONNAC2X_TXD_UNSET_SOUNDING_FRAME(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW2 &= ~CONNAC2X_TX_DESC_SOUNDING) + +#define HAL_MAC_CONNAC2X_TXD_IS_FORCE_RTS_CTS_EN(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW2 & CONNAC2X_TX_DESC_FORCE_RTS_CTS)?TRUE:FALSE) + +#define HAL_MAC_CONNAC2X_TXD_SET_FORCE_RTS_CTS(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW2 |= CONNAC2X_TX_DESC_FORCE_RTS_CTS) + +#define HAL_MAC_CONNAC2X_TXD_UNSET_FORCE_RTS_CTS(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW2 &= ~CONNAC2X_TX_DESC_FORCE_RTS_CTS) + +#define HAL_MAC_CONNAC2X_TXD_IS_BMC(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW2 & CONNAC2X_TX_DESC_BROADCAST_MULTICAST)?TRUE:FALSE) + +#define HAL_MAC_CONNAC2X_TXD_SET_BMC(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW2 |= CONNAC2X_TX_DESC_BROADCAST_MULTICAST) + +#define HAL_MAC_CONNAC2X_TXD_UNSET_BMC(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW2 &= ~CONNAC2X_TX_DESC_BROADCAST_MULTICAST) + +#define HAL_MAC_CONNAC2X_TXD_IS_BIP(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW2 & CONNAC2X_TX_DESC_BIP_PROTECTED)?TRUE:FALSE) + +#define HAL_MAC_CONNAC2X_TXD_SET_BIP(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW2 |= CONNAC2X_TX_DESC_BIP_PROTECTED) + +#define HAL_MAC_CONNAC2X_TXD_UNSET_BIP(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW2 &= ~CONNAC2X_TX_DESC_BIP_PROTECTED) + +#define HAL_MAC_CONNAC2X_TXD_IS_DURATION_CONTROL_BY_SW(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW2 & CONNAC2X_TX_DESC_DURATION_FIELD_CONTROL)?TRUE:FALSE) + +#define HAL_MAC_CONNAC2X_TXD_SET_DURATION_CONTROL_BY_SW(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW2 |= CONNAC2X_TX_DESC_DURATION_FIELD_CONTROL) + +#define HAL_MAC_CONNAC2X_TXD_SET_DURATION_CONTROL_BY_HW(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW2 &= ~CONNAC2X_TX_DESC_DURATION_FIELD_CONTROL) + +#define HAL_MAC_CONNAC2X_TXD_IS_HTC_EXIST(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW2 & CONNAC2X_TX_DESC_HTC_EXISTS)?TRUE:FALSE) + +#define HAL_MAC_CONNAC2X_TXD_SET_HTC_EXIST(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW2 |= CONNAC2X_TX_DESC_HTC_EXISTS) + +#define HAL_MAC_CONNAC2X_TXD_UNSET_HTC_EXIST(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW2 &= ~CONNAC2X_TX_DESC_HTC_EXISTS) + +#define HAL_MAC_CONNAC2X_TXD_IS_FRAG_PACKET(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW2 & CONNAC2X_TX_DESC_FRAGMENT_MASK)?TRUE:FALSE) + +#define HAL_MAC_CONNAC2X_TXD_GET_FRAG_PACKET_POS(_prHwMacTxDesc) \ +TX_DESC_GET_FIELD((_prHwMacTxDesc)->u4DW2, CONNAC2X_TX_DESC_FRAGMENT_MASK, \ +CONNAC2X_TX_DESC_FRAGMENT_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_SET_FRAG_PACKET_POS(_prHwMacTxDesc, _ucFragPos)\ +TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u4DW2), ((uint8_t)_ucFragPos), \ +CONNAC2X_TX_DESC_FRAGMENT_MASK, CONNAC2X_TX_DESC_FRAGMENT_OFFSET) + +/* For driver */ +/* in unit of 32TU */ +#define HAL_MAC_CONNAC2X_TXD_GET_REMAINING_LIFE_TIME(_prHwMacTxDesc) \ +TX_DESC_GET_FIELD((_prHwMacTxDesc)->u4DW2, \ +CONNAC2X_TX_DESC_REMAINING_MAX_TX_TIME_MASK, \ +CONNAC2X_TX_DESC_REMAINING_MAX_TX_TIME_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_SET_REMAINING_LIFE_TIME(_prHwMacTxD, _LifeTime) \ +TX_DESC_SET_FIELD(((_prHwMacTxD)->u4DW2), ((uint8_t)_LifeTime), \ +CONNAC2X_TX_DESC_REMAINING_MAX_TX_TIME_MASK, \ +CONNAC2X_TX_DESC_REMAINING_MAX_TX_TIME_OFFSET) + +/* in unit of ms (minimal value is about 40ms) */ +#define HAL_MAC_CONNAC2X_TXD_GET_REMAINING_LIFE_TIME_IN_MS(_prHwMacTxDesc) \ +(TU_TO_MSEC(HAL_MAC_CONNAC2X_TXD_GET_REMAINING_LIFE_TIME(_prHwMacTxDesc)\ +<< CONNAC2X_TX_DESC_LIFE_TIME_UNIT_IN_POWER_OF_2)) + + +/* +* Remaining Life Time/ Max TX Time: This field indicates the remaining life +* time in unit of 64TU used for this packet. +* 8'h0: No life time for current packet, HW should NOT change this field +* 8'hN: N is not 0, HW will calculation a Max. TX time and replace remaining +* TX time with it. The Max. value is 127. +* The MSB bit is reserved for HW and SW should set to 0 +* Due to HW design issue, the remaining life time sometimes may have 32TU +* more than configured. +* PP will replace this field with "Max. TX Time". +* (SUM of (Remaining Life Time + Internal Free-run Timer)). +* If the SUM is 0, PP will add 1 to it. +*/ +#define HAL_MAC_CONNAC2X_TXD_SET_REMAINING_LIFE_TIME_IN_MS(_prHwTxD, _LifeMs)\ +do { \ +uint32_t u4LifeTimeInUnit = ((MSEC_TO_USEC(_LifeMs) / USEC_PER_TU) \ + >> CONNAC2X_TX_DESC_LIFE_TIME_UNIT_IN_POWER_OF_2); \ +if (u4LifeTimeInUnit >= BIT(7)) \ + u4LifeTimeInUnit = BITS(0, 6); \ +else if ((u4LifeTimeInUnit != TX_DESC_TX_TIME_NO_LIMIT) \ + && (u4LifeTimeInUnit == TX_DESC_TX_TIME_NO_LIMIT)) \ + u4LifeTimeInUnit = 1; \ +HAL_MAC_CONNAC2X_TXD_SET_REMAINING_LIFE_TIME(_prHwTxD, \ + (uint8_t)u4LifeTimeInUnit); \ +} while (0) + +#define HAL_MAC_CONNAC2X_TXD_GET_POWER_OFFSET(_prHwMacTxDesc) \ +TX_DESC_GET_FIELD((_prHwMacTxDesc)->u4DW2, \ +CONNAC2X_TX_DESC_POWER_OFFSET_MASK, CONNAC2X_TX_DESC_POWER_OFFSET_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_SET_POWER_OFFSET(_prHwTxD, _ucPowerOffset) \ +TX_DESC_SET_FIELD(((_prHwTxD)->u4DW2), ((uint8_t)_ucPowerOffset), \ +CONNAC2X_TX_DESC_POWER_OFFSET_MASK, CONNAC2X_TX_DESC_POWER_OFFSET_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_IS_CR_FIXED_RATE_MODE(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW2 & CONNAC2X_TX_DESC_FIXED_RATE_MODE)?TRUE:FALSE) +#define HAL_MAC_CONNAC2X_TXD_SET_FIXED_RATE_MODE_TO_DESC(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW2 &= ~CONNAC2X_TX_DESC_FIXED_RATE_MODE) +#define HAL_MAC_CONNAC2X_TXD_SET_FIXED_RATE_MODE_TO_CR(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW2 |= CONNAC2X_TX_DESC_FIXED_RATE_MODE) + +#define HAL_MAC_CONNAC2X_TXD_IS_FIXED_RATE_ENABLE(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW2 & CONNAC2X_TX_DESC_FIXED_RATE)?TRUE:FALSE) +#define HAL_MAC_CONNAC2X_TXD_SET_FIXED_RATE_ENABLE(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW2 |= CONNAC2X_TX_DESC_FIXED_RATE) +#define HAL_MAC_CONNAC2X_TXD_SET_FIXED_RATE_DISABLE(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW2 &= ~CONNAC2X_TX_DESC_FIXED_RATE) + +#define HAL_MAC_CONNAC2X_TXD_IS_BA_DISABLE(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW3 & CONNAC2X_TX_DESC_BA_DISABLE)?TRUE:FALSE) + +#define HAL_MAC_CONNAC2X_TXD_SET_BA_DISABLE(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW3 |= CONNAC2X_TX_DESC_BA_DISABLE) +#define HAL_MAC_CONNAC2X_TXD_SET_BA_ENABLE(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW3 &= ~CONNAC2X_TX_DESC_BA_DISABLE) + +#define HAL_MAC_CONNAC2X_TXD_IS_TIMING_MEASUREMENT(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW3 & CONNAC2X_TX_DESC_TIMING_MEASUREMENT)?TRUE:FALSE) +#define HAL_MAC_CONNAC2X_TXD_SET_TIMING_MEASUREMENT(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW3 |= CONNAC2X_TX_DESC_TIMING_MEASUREMENT) +#define HAL_MAC_CONNAC2X_TXD_UNSET_TIMING_MEASUREMENT(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW3 &= ~CONNAC2X_TX_DESC_TIMING_MEASUREMENT) + +#define HAL_MAC_CONNAC2X_TXD_IS_NO_ACK(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW3 & CONNAC2X_TX_DESC_NO_ACK)?TRUE:FALSE) +#define HAL_MAC_CONNAC2X_TXD_SET_NO_ACK(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW3 |= CONNAC2X_TX_DESC_NO_ACK) +#define HAL_MAC_CONNAC2X_TXD_UNSET_NO_ACK(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW3 &= ~CONNAC2X_TX_DESC_NO_ACK) + +#define HAL_MAC_CONNAC2X_TXD_IS_PROTECTION(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW3 & CONNAC2X_TX_DESC_PROTECTED_FRAME)?TRUE:FALSE) +#define HAL_MAC_CONNAC2X_TXD_SET_PROTECTION(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW3 |= CONNAC2X_TX_DESC_PROTECTED_FRAME) +#define HAL_MAC_CONNAC2X_TXD_UNSET_PROTECTION(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW3 &= ~CONNAC2X_TX_DESC_PROTECTED_FRAME) + +#define HAL_MAC_CONNAC2X_TXD_IS_EXTEND_MORE_DATA(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW3 & CONNAC2X_TX_DESC_EXTEND_MORE_DATA)?TRUE:FALSE) +#define HAL_MAC_CONNAC2X_TXD_SET_EXTEND_MORE_DATA(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW3 |= CONNAC2X_TX_DESC_EXTEND_MORE_DATA) +#define HAL_MAC_CONNAC2X_TXD_UNSET_EXTEND_MORE_DATA(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW3 &= ~CONNAC2X_TX_DESC_EXTEND_MORE_DATA) + +#define HAL_MAC_CONNAC2X_TXD_IS_EXTEND_EOSP(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW3 & CONNAC2X_TX_DESC_EXTEND_EOSP)?TRUE:FALSE) +#define HAL_MAC_CONNAC2X_TXD_SET_EXTEND_EOSP(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW3 |= CONNAC2X_TX_DESC_EXTEND_EOSP) +#define HAL_MAC_CONNAC2X_TXD_UNSET_EXTEND_EOSP(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW3 &= ~CONNAC2X_TX_DESC_EXTEND_EOSP) + +#define HAL_MAC_CONNAC2X_TXD_GET_TX_COUNT(_prHwMacTxDesc) \ +TX_DESC_GET_FIELD((_prHwMacTxDesc)->u4DW3, \ +CONNAC2X_TX_DESC_TX_COUNT_MASK, CONNAC2X_TX_DESC_TX_COUNT_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_SET_TX_COUNT(_prHwMacTxDesc, _ucTxCountLimit) \ +TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u4DW3), ((uint8_t)_ucTxCountLimit), \ +CONNAC2X_TX_DESC_TX_COUNT_MASK, CONNAC2X_TX_DESC_TX_COUNT_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_GET_REMAINING_TX_COUNT(_prHwMacTxDesc) \ +TX_DESC_GET_FIELD((_prHwMacTxDesc)->u4DW3, \ +CONNAC2X_TX_DESC_REMAINING_TX_COUNT_MASK, \ +CONNAC2X_TX_DESC_REMAINING_TX_COUNT_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_SET_REMAINING_TX_COUNT(_prHwTxD, _ucTxCntLimit) \ +TX_DESC_SET_FIELD(((_prHwTxD)->u4DW3), ((uint8_t)_ucTxCntLimit), \ +CONNAC2X_TX_DESC_REMAINING_TX_COUNT_MASK, \ +CONNAC2X_TX_DESC_REMAINING_TX_COUNT_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_GET_SEQUENCE_NUMBER(_prHwMacTxDesc) \ +TX_DESC_GET_FIELD((_prHwMacTxDesc)->u4DW3, \ +CONNAC2X_TX_DESC_SEQUENCE_NUMBER_MASK, \ +CONNAC2X_TX_DESC_SEQUENCE_NUMBER_MASK_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_SET_SEQUENCE_NUMBER(_prHwMacTxDesc, _u2SN) \ +TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u4DW3), \ +((uint16_t)_u2SN), CONNAC2X_TX_DESC_SEQUENCE_NUMBER_MASK, \ +CONNAC2X_TX_DESC_SEQUENCE_NUMBER_MASK_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_IS_TXD_SN_VALID(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW3 & CONNAC2X_TX_DESC_SN_IS_VALID)?TRUE:FALSE) +#define HAL_MAC_CONNAC2X_TXD_SET_TXD_SN_VALID(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW3 |= CONNAC2X_TX_DESC_SN_IS_VALID) +#define HAL_MAC_CONNAC2X_TXD_SET_TXD_SN_INVALID(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW3 &= ~CONNAC2X_TX_DESC_SN_IS_VALID) + +#define HAL_MAC_CONNAC2X_TXD_IS_TXD_PN_VALID(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW3 & CONNAC2X_TX_DESC_PN_IS_VALID)?TRUE:FALSE) +#define HAL_MAC_CONNAC2X_TXD_SET_TXD_PN_VALID(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW3 |= CONNAC2X_TX_DESC_PN_IS_VALID) +#define HAL_MAC_CONNAC2X_TXD_SET_TXD_PN_INVALID(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW3 &= ~CONNAC2X_TX_DESC_PN_IS_VALID) + +#define HAL_MAC_CONNAC2X_TXD_ASSIGN_SN_BY_SW(_prHwMacTxDesc, _u2SN) \ +{ \ + HAL_MAC_CONNAC2X_TXD_SET_SEQUENCE_NUMBER(_prHwMacTxDesc, _u2SN); \ + HAL_MAC_CONNAC2X_TXD_SET_TXD_SN_VALID(_prHwMacTxDesc); \ +} +#define HAL_MAC_CONNAC2X_TXD_ASSIGN_SN_BY_HW(_prHwMacTxDesc) \ +{ \ + HAL_MAC_CONNAC2X_TXD_SET_SEQUENCE_NUMBER(_prHwMacTxDesc, 0); \ + HAL_MAC_CONNAC2X_TXD_SET_TXD_SN_INVALID(_prHwMacTxDesc); \ +} + +#if 0 +#define HAL_MAC_FALCON_TX_DESC_GET_PN(_prHwMacTxDesc, _u4PN_0_31, _u2PN_32_47) \ +{ \ + ((UINT_32)_u4PN_0_31) = (_prHwMacTxDesc)->u4PN1; \ + ((UINT_16)_u2PN_32_47) = (_prHwMacTxDesc)->u2PN2; \ +} +#define HAL_MAC_FALCON_TX_DESC_SET_PN(_prHwMacTxDesc, _u4PN_0_31, _u2PN_32_47) \ +{ \ + (_prHwMacTxDesc)->u4PN1 = ((UINT_32)_u4PN_0_31); \ + (_prHwMacTxDesc)->u2PN2 = ((UINT_16)_u2PN_32_47); \ +} +#endif + +#define HAL_MAC_CONNAC2X_TXD_ASSIGN_PN_BY_SW(_prHwTxD, _u4PN0_31, _u2PN32_47)\ +{ \ + HAL_MAC_TX_DESC_SET_PN(_prHwTxD, _u4PN0_31, _u2PN32_47); \ + HAL_MAC_CONNAC2X_TXD_SET_TXD_PN_VALID(_prHwTxD); \ +} +#define HAL_MAC_CONNAC2X_TXD_ASSIGN_PSN_BY_HW(_prHwMacTxDesc) \ +{ \ + HAL_MAC_TX_DESC_SET_PN(_prHwMacTxDesc, 0, 0); \ + HAL_MAC_CONNAC2X_TXD_SET_TXD_PN_INVALID(_prHwMacTxDesc); \ +} + +#define HAL_MAC_CONNAC2X_TXD_GET_PID(_prHwMacTxDesc) \ +TX_DESC_GET_FIELD((_prHwMacTxDesc)->u2DW5_0, \ +CONNAC2X_TX_DESC_PACKET_ID_MASK, CONNAC2X_TX_DESC_PACKET_ID_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_SET_PID(_prHwMacTxDesc, _ucPID) \ +TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2DW5_0), ((uint8_t)_ucPID), \ +CONNAC2X_TX_DESC_PACKET_ID_MASK, CONNAC2X_TX_DESC_PACKET_ID_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_GET_TXS_FORMAT(_prHwMacTxDesc) \ +TX_DESC_GET_FIELD((_prHwMacTxDesc)->u2DW5_0, \ +CONNAC2X_TX_DESC_TX_STATUS_FORMAT, CONNAC2X_TX_DESC_TX_STATUS_FORMAT_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_SET_TXS_FORMAT(_prHwMacTxDesc, _ucTXSFormat) \ +TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2DW5_0), ((uint8_t)_ucTXSFormat), \ +CONNAC2X_TX_DESC_TX_STATUS_FORMAT, CONNAC2X_TX_DESC_TX_STATUS_FORMAT_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_IS_TXS_TO_MCU(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u2DW5_0 & CONNAC2X_TX_DESC_TX_STATUS_TO_MCU)?TRUE:FALSE) +#define HAL_MAC_CONNAC2X_TXD_SET_TXS_TO_MCU(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u2DW5_0 |= CONNAC2X_TX_DESC_TX_STATUS_TO_MCU) +#define HAL_MAC_CONNAC2X_TXD_UNSET_TXS_TO_MCU(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u2DW5_0 &= ~CONNAC2X_TX_DESC_TX_STATUS_TO_MCU) + +#define HAL_MAC_CONNAC2X_TXD_IS_TXS_TO_HOST(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u2DW5_0 & CONNAC2X_TX_DESC_TX_STATUS_TO_HOST)?TRUE:FALSE) +#define HAL_MAC_CONNAC2X_TXD_SET_TXS_TO_HOST(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u2DW5_0 |= CONNAC2X_TX_DESC_TX_STATUS_TO_HOST) +#define HAL_MAC_CONNAC2X_TXD_UNSET_TXS_TO_HOST(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u2DW5_0 &= ~CONNAC2X_TX_DESC_TX_STATUS_TO_HOST) + +#define HAL_MAC_CONNAC2X_TXD_IS_DA_FROM_WTBL(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u2DW5_0 & TX_DESC_DA_SOURCE)?TRUE:FALSE) +#define HAL_MAC_CONNAC2X_TXD_SET_DA_FROM_WTBL(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u2DW5_0 |= TX_DESC_DA_SOURCE) +#define HAL_MAC_CONNAC2X_TXD_SET_DA_FROM_MSDU(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u2DW5_0 &= ~TX_DESC_DA_SOURCE) + +#define HAL_MAC_CONNAC2X_TXD_IS_SW_PM_CONTROL(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW3 & CONNAC2X_TX_DESC_POWER_MANAGEMENT_CONTROL) ?\ + TRUE : FALSE) + +#define HAL_MAC_CONNAC2X_TXD_SET_SW_PM_CONTROL(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW3 |= CONNAC2X_TX_DESC_POWER_MANAGEMENT_CONTROL) + +#define HAL_MAC_CONNAC2X_TXD_SET_HW_PM_CONTROL(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW3 &= ~CONNAC2X_TX_DESC_POWER_MANAGEMENT_CONTROL) + +#define HAL_MAC_CONNAC2X_TXD_SET_FR_BW(_prHwMacTxDesc, ucBw) \ +TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u4DW6), ((uint8_t)ucBw), \ +CONNAC2X_TX_DESC_BANDWIDTH_MASK, CONNAC2X_TX_DESC_BANDWIDTH_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_SET_FR_DYNAMIC_BW_RTS(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW6 |= CONNAC2X_TX_DESC_DYNAMIC_BANDWIDTH) + +#define HAL_MAC_CONNAC2X_TXD_SET_FR_ANTENNA_ID(_prHwMacTxDesc, _ucAntId) \ +TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u4DW6), ((uint8_t)_ucAntId), \ +CONNAC2X_TX_DESC_ANTENNA_INDEX_MASK, CONNAC2X_TX_DESC_ANTENNA_INDEX_OFFSET) +#define HAL_MAC_CONNAC2X_TXD_SET_SPE_IDX_SEL(_prHwMacTxDesc, _ucSpeIdxSel) \ +TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u4DW6), ((uint8_t)_ucSpeIdxSel), \ +CONNAC2X_TX_DESC_SPE_IDX_SEL, CONNAC2X_TX_DESC_SPE_IDX_SEL_OFFSET) +#define HAL_MAC_CONNAC2X_TXD_SET_LDPC(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW6 |= CONNAC2X_TX_DESC_LDPC) + +#define HAL_MAC_CONNAC2X_TXD_SET_HE_LTF(_prHwMacTxDesc, _ucHeLtf) \ +TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u4DW6), ((uint8_t)_ucHeLtf), \ +CONNAC2X_TX_DESC_HE_LTF_MASK, CONNAC2X_TX_DESC_HE_LTF_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_GET_HE_LTF(_prHwMacTxDesc) \ +TX_DESC_GET_FIELD(((_prHwMacTxDesc)->u4DW6), \ +CONNAC2X_TX_DESC_HE_LTF_MASK, CONNAC2X_TX_DESC_HE_LTF_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_SET_GI_TYPE(_prHwMacTxDesc, _ucGIType) \ +TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u4DW6), ((uint8_t)_ucGIType), \ +CONNAC2X_TX_DESC_GI_TYPE, CONNAC2X_TX_DESC_GI_TYPE_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_GET_GI_TYPE(_prHwMacTxDesc) \ +TX_DESC_GET_FIELD(((_prHwMacTxDesc)->u4DW6), \ +CONNAC2X_TX_DESC_GI_TYPE, CONNAC2X_TX_DESC_GI_TYPE_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_SET_FR_RATE(_prHwMacTxDesc, _u2RatetoFixed) \ +TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u4DW6), ((uint8_t)_u2RatetoFixed), \ +CONNAC2X_TX_DESC_FIXDE_RATE_MASK, CONNAC2X_TX_DESC_FIXDE_RATE_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_SET_SPE_IDX(_prHwMacTxDesc, _ucSpeIdx) \ +TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u4DW7), ((uint16_t)_ucSpeIdx), \ +CONNAC2X_TX_DESC_SPE_EXT_IDX_MASK, CONNAC2X_TX_DESC_SPE_EXT_IDX_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD_IS_HW_AMSDU(_prHwMacTxDesc) \ +(((_prHwMacTxDesc)->u4DW7 & CONNAC2X_TX_DESC_HW_AMSDU)?TRUE:FALSE) +#define HAL_MAC_CONNAC2X_TXD_SET_HW_AMSDU(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW7 |= CONNAC2X_TX_DESC_HW_AMSDU) +#define HAL_MAC_CONNAC2X_TXD_UNSET_HW_AMSDU(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->u4DW7 &= ~CONNAC2X_TX_DESC_HW_AMSDU) + +#define HAL_MAC_CONNAC2X_TXD7_GET_SUB_TYPE(_prHwMacTxDesc) \ +TX_DESC_GET_FIELD((_prHwMacTxDesc)->u4DW7, \ +CONNAC2X_TX_DESC7_SUB_TYPE_MASK, CONNAC2X_TX_DESC7_SUB_TYPE_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD7_SET_SUB_TYPE(_prHwMacTxDesc, _ucSubType) \ +TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u4DW7), ((uint8_t)_ucSubType), \ +CONNAC2X_TX_DESC7_SUB_TYPE_MASK, CONNAC2X_TX_DESC7_SUB_TYPE_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD7_GET_TYPE(_prHwMacTxDesc) \ +TX_DESC_GET_FIELD((_prHwMacTxDesc)->u4DW7, \ +CONNAC2X_TX_DESC7_TYPE_MASK, CONNAC2X_TX_DESC7_TYPE_OFFSET) + +#define HAL_MAC_CONNAC2X_TXD7_SET_TYPE(_prHwMacTxDesc, _ucType) \ +TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u4DW7), ((uint8_t)_ucType), \ +CONNAC2X_TX_DESC7_TYPE_MASK, CONNAC2X_TX_DESC7_TYPE_OFFSET) + +/******************************************************************************* +* 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_SUPPORT_CONNAC2X == 1 */ +#endif /* _NIC_CONNAC2X_TX_H */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_rate.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_rate.h new file mode 100644 index 0000000000000..7fcf4a9b69f9f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_rate.h @@ -0,0 +1,292 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/ + * MT6620_WIFI_DRIVER_V2_3/include/nic/nic_rate.h#1 + */ + +/*! \file nic_rate.h + * \brief This file contains the rate utility function of + * IEEE 802.11 family for MediaTek 802.11 Wireless LAN Adapters. + */ + + +#ifndef _NIC_RATE_H +#define _NIC_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 + ******************************************************************************* + */ +extern char *HW_TX_MODE_STR[]; +extern char *HW_TX_RATE_CCK_STR[]; +extern char *HW_TX_RATE_OFDM_STR[]; +extern char *HW_TX_RATE_BW[]; + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define BW_20 0 +#define BW_40 1 +#define BW_80 2 +#define BW_160 3 +#define BW_10 4 +#define BW_5 6 +#define BW_8080 7 +#define BW_ALL 0xFF + +#define TX_RATE_MODE_CCK 0 +#define TX_RATE_MODE_OFDM 1 +#define TX_RATE_MODE_HTMIX 2 +#define TX_RATE_MODE_HTGF 3 +#define TX_RATE_MODE_VHT 4 +#define TX_RATE_MODE_PLR 5 +#define TX_RATE_MODE_HE_SU 8 +#define TX_RATE_MODE_HE_ER 9 +#define TX_RATE_MODE_HE_TRIG 10 +#define TX_RATE_MODE_HE_MU 11 + +#define RATE_VER_1 0 /* AC */ +#define RATE_VER_2 1 /* HE */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +enum ENUM_TX_MODE_STR_IDX { + ENUM_TX_MODE_CCK = 0, + ENUM_TX_MODE_OFDM, + ENUM_TX_MODE_MM, + ENUM_TX_MODE_GF, + ENUM_TX_MODE_VHT, +#if (CFG_SUPPORT_802_11AX == 1) + ENUM_TX_MODE_PLR, + ENUM_TX_MODE_HE_SU = 8, + ENUM_TX_MODE_HE_ER, + ENUM_TX_MODE_HE_TRIG, + ENUM_TX_MODE_HE_MU, +#endif + ENUM_TX_MODE_NUM +}; + +struct FIXED_RATE_INFO { + uint32_t u4Mode; + uint32_t u4Bw; + uint32_t u4Mcs; + uint32_t u4VhtNss; + uint32_t u4SGI; + uint32_t u4Preamble; + uint32_t u4STBC; + uint32_t u4LDPC; + uint32_t u4SpeEn; + uint32_t u4HeLTF; + uint32_t u4HeErDCM; + uint32_t u4HeEr106t; +}; + +enum GI_HE { + GI_HE_SGI = 0, + GI_HE_MGI, + GI_HE_LGI, + GI_HE_NUM +}; + +enum HE_LTF { + HE_LTF_1X = 0, + HE_LTF_2X, + HE_LTF_4X +}; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +#if (CFG_SUPPORT_CONNAC2X == 1) +#define HW_TX_RATE_TO_MODE(_x) CONNAC2X_HW_TX_RATE_TO_MODE(_x) +#define HW_TX_RATE_TO_NSS(_x) CONNAC2X_HW_TX_RATE_TO_NSS(_x) +#define HW_TX_RATE_TO_STBC(_x) CONNAC2X_HW_TX_RATE_TO_STBC(_x) +#else +#define HW_TX_RATE_TO_MODE(_x) (((_x) & (0x7 << 6)) >> 6) +#define HW_TX_RATE_TO_NSS(_x) (((_x) & (0x3 << 9)) >> 9) +#define HW_TX_RATE_TO_STBC(_x) (((_x) & (0x1 << 11)) >> 11) +#endif +#define HW_TX_RATE_TO_MCS(_x) ((_x) & (0x3f)) + +#if (CFG_SUPPORT_CONNAC2X == 1) +#define TX_VECTOR_GET_TX_RATE(_txv) CONNAC2X_TXV_GET_TX_RATE(_txv) +#define TX_VECTOR_GET_TX_LDPC(_txv) CONNAC2X_TXV_GET_TX_LDPC(_txv) +#define TX_VECTOR_GET_TX_STBC(_txv) CONNAC2X_TXV_GET_TX_STBC(_txv) +#define TX_VECTOR_GET_TX_FRMODE(_txv) CONNAC2X_TXV_GET_TX_FRMODE(_txv) +#define TX_VECTOR_GET_TX_MODE(_txv) CONNAC2X_TXV_GET_TX_MODE(_txv) +#define TX_VECTOR_GET_TX_NSTS(_txv) CONNAC2X_TXV_GET_TX_NSTS(_txv) +#define TX_VECTOR_GET_TX_PWR(_txv) CONNAC2X_TXV_GET_TX_PWR(_txv) +#define TX_VECTOR_GET_TX_SGI(_txv) CONNAC2X_TXV_GET_TX_SGI(_txv) +#else +#define TX_VECTOR_GET_TX_RATE(_txv) (((_txv)->u4TxV[0]) & BITS(0, 6)) +#define TX_VECTOR_GET_TX_LDPC(_txv) ((((_txv)->u4TxV[0]) >> 7) & BIT(0)) +#define TX_VECTOR_GET_TX_STBC(_txv) ((((_txv)->u4TxV[0]) >> 8) & \ + BITS(0, 1)) +#define TX_VECTOR_GET_TX_FRMODE(_txv) ((((_txv)->u4TxV[0]) >> 10) & \ + BITS(0, 1)) +#define TX_VECTOR_GET_TX_MODE(_txv) ((((_txv)->u4TxV[0]) >> 12) & \ + BITS(0, 2)) +#define TX_VECTOR_GET_TX_NSTS(_txv) ((((_txv)->u4TxV[0]) >> 21) & \ + BITS(0, 1)) +#define TX_VECTOR_GET_TX_PWR(_txv) ((((_txv)->u4TxV[0]) >> 24) & \ + BITS(0, 6)) +#define TX_VECTOR_GET_TX_SGI(_txv) ((((_txv)->u4TxV[2]) >> 27) & BIT(0)) +#endif + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +uint32_t +nicGetPhyRateByMcsRate( + IN uint8_t ucIdx, + IN uint8_t ucBw, + IN uint8_t ucGI +); + +uint32_t +nicGetHwRateByPhyRate( + IN uint8_t ucIdx +); + +uint32_t +nicSwIndex2RateIndex( + IN uint8_t ucRateSwIndex, + OUT uint8_t *pucRateIndex, + OUT uint8_t *pucPreambleOption +); + +uint32_t +nicRateIndex2RateCode( + IN uint8_t ucPreambleOption, + IN uint8_t ucRateIndex, + OUT uint16_t *pu2RateCode +); + +uint32_t +nicRateCode2PhyRate( + IN uint16_t u2RateCode, + IN uint8_t ucBandwidth, + IN uint8_t ucGI, + IN uint8_t ucRateNss +); + +uint32_t +nicRateCode2DataRate( + IN uint16_t u2RateCode, + IN uint8_t ucBandwidth, + IN uint8_t ucGI +); + +u_int8_t +nicGetRateIndexFromRateSetWithLimit( + IN uint16_t u2RateSet, + IN uint32_t u4PhyRateLimit, + IN u_int8_t fgGetLowest, + OUT uint8_t *pucRateSwIndex +); + +char *nicHwRateOfdmStr( + uint16_t ofdm_idx); + +uint32_t nicSetFixedRateData( + struct FIXED_RATE_INFO *pFixedRate, + uint32_t *pu4Data); + +uint32_t nicRateHeLtfCheckGi( + struct FIXED_RATE_INFO *pFixedRate); + +uint8_t nicGetTxSgiInfo( + IN struct PARAM_PEER_CAP *prWtblPeerCap, + IN uint8_t u1TxMode); + +uint8_t nicGetTxLdpcInfo( + IN struct PARAM_TX_CONFIG *prWtblTxConfig); + +int32_t nicGetTxRateInfo(IN char *pcCommand, IN int i4TotalLen, + u_int8_t fgDumpAll, + struct PARAM_HW_WLAN_INFO *prHwWlanInfo, + struct PARAM_GET_STA_STATISTICS *prQueryStaStatistics); + +int32_t nicGetRxRateInfo(struct ADAPTER *prAdapter, IN char *pcCommand, + IN int i4TotalLen, IN uint8_t ucWlanIdx); + +uint16_t nicGetStatIdxInfo(IN struct ADAPTER *prAdapter, + IN uint8_t ucWlanIdx); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _NIC_RATE_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_rx.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_rx.h new file mode 100644 index 0000000000000..4ba3797dea7df --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_rx.h @@ -0,0 +1,1393 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "nic_rx.h" + * \brief The declaration of the nic rx functions + * + */ + + +#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 UNIFIED_MAC_RX_FORMAT 1 + +#define MAX_SEQ_NO 4095 +#define MAX_SEQ_NO_COUNT 4096 +#define HALF_SEQ_NO_CNOUT 2048 + +#define HALF_SEQ_NO_COUNT 2048 +#define QUARTER_SEQ_NO_COUNT 1024 + +#define MT6620_FIXED_WIN_SIZE 64 +#define CFG_RX_MAX_BA_ENTRY 4 +#define CFG_RX_MAX_BA_TID_NUM 8 + +#define RX_STATUS_FLAG_MORE_PACKET BIT(30) +#define RX_STATUS_CHKSUM_MASK BITS(0, 10) + +#define RX_RFB_LEN_FIELD_LEN 4 +#define RX_HEADER_OFFSET 2 + +#define RX_RETURN_INDICATED_RFB_TIMEOUT_SEC 3 + +#define RX_PROCESS_TIMEOUT 1000 + +#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 + +/* RXM Definitions */ +/* The payload format of a RX packet */ +#define RX_PAYLOAD_FORMAT_MSDU 0 +#define RX_PAYLOAD_FORMAT_FIRST_SUB_AMSDU 3 +#define RX_PAYLOAD_FORMAT_MIDDLE_SUB_AMSDU 2 +#define RX_PAYLOAD_FORMAT_LAST_SUB_AMSDU 1 + +/* HAL RX from hal_hw_def_rom.h */ +/*------------------------------------------------------------------------------ + * Cipher define + *------------------------------------------------------------------------------ + */ +#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 CIPHER_SUITE_CCMP_W_CCX 9 +#define CIPHER_SUITE_GCMP 10 + +/*------------------------------------------------------------------------------ + * Bit fields for HW_MAC_RX_DESC_T + *------------------------------------------------------------------------------ + */ + +/*! MAC RX DMA Descriptor */ +/* DW 0*/ +/* Word 0 */ +#define RX_STATUS_RX_BYTE_COUNT_MASK BITS(0, 16) +/* Word 1 */ +#define RX_STATUS_ETH_TYPE_OFFSET_MASK BITS(0, 6) +#define RX_STATUS_ETH_TYPE_OFFSET 0 +#define RX_STATUS_IP_CHKSUM BIT(7) +#define RX_STATUS_UDP_TCP_CHKSUM BIT(8) +#define RX_STATUS_GROUP_VLD_MASK BITS(9, 12) +#define RX_STATUS_GROUP_VLD_OFFSET 9 +#define RX_STATUS_PKT_TYPE_MASK BITS(13, 15) +#define RX_STATUS_PKT_TYPE_OFFSET 13 + +/* DW 1 */ +/* Byte 0 */ +#define RX_STATUS_HTC BIT(0) +#define RX_STATUS_UC2ME BIT(1) +#define RX_STATUS_MC_FRAME BIT(2) +#define RX_STATUS_BC_FRAME BIT(3) +#define RX_STATUS_BCN_WITH_BMC BIT(4) +#define RX_STATUS_BCN_WITH_UC BIT(5) +#define RX_STATUS_KEYID_MASK BITS(6, 7) +#define RX_STATUS_KEYID_OFFSET 6 + +/* Byte 1 */ +#define RX_STATUS_CHAN_FREQ_MASK BITS(0, 7) +/* Byte 2 */ +#define RX_STATUS_HEADER_LEN_MASK BITS(0, 5) +#define RX_STATUS_HEADER_OFFSET BIT(6) +#define RX_STATUS_HEADER_TRAN BIT(7) +/* Byte 3 */ +#define RX_STATUS_PAYLOAD_FORMAT_MASK BITS(0, 1) +#define RX_STATUS_PAYLOAD_FORMAT_OFFSET 0 +#define RX_STATUS_BSSID_MASK BITS(2, 7) +#define RX_STATUS_BSSID_OFFSET 2 + +/* DW 2 */ +/* Byte 1 */ +#define RX_STATUS_TID_MASK BITS(0, 3) +#define RX_STATUS_SEC_MASK BITS(4, 7) +#define RX_STATUS_SEC_OFFSET 4 +/* Byte 2-3 */ +#define RX_STATUS_SW_BIT BIT(0) +#define RX_STATUS_FLAG_FCS_ERROR BIT(1) +#define RX_STATUS_FLAG_CIPHER_MISMATCH BIT(2) +#define RX_STATUS_FLAG_CIPHER_LENGTH_MISMATCH BIT(3) +#define RX_STATUS_FLAG_ICV_ERROR BIT(4) +#define RX_STATUS_FLAG_TKIPMIC_ERROR BIT(5) +#define RX_STATUS_FLAG_LEN_MISMATCH BIT(6) +#define RX_STATUS_FLAG_DE_AMSDU_FAIL BIT(7) +#define RX_STATUS_FLAG_EXCEED_LEN BIT(8) +#define RX_STATUS_LLC_MIS BIT(9) +#define RX_STATUS_UDF_VLT BIT(10) +#define RX_STATUS_FRAG BIT(11) +#define RX_STATUS_NULL BIT(12) +#define RX_STATUS_DATA BIT(13) +#define RX_STATUS_AMPDU_SUB_FRAME BIT(14) +#define RX_STATUS_AMPDU_FORMAT BIT(15) +#define PAYLOAD_FORMAT_IS_MSDU_FRAME 0 +#define RX_STATUS_FLAG_ERROR_MASK \ + (RX_STATUS_FLAG_FCS_ERROR | RX_STATUS_FLAG_ICV_ERROR | \ + RX_STATUS_FLAG_CIPHER_LENGTH_MISMATCH) /* No TKIP MIC error */ + +/* DW 3 */ +#define RX_STATUS_RXV_SEQ_NO_MASK BITS(0, 7) +#define RX_STATUS_TCL BIT(8) +#define RX_STATUS_CLS BIT(11) +#define RX_STATUS_OFLD_MASK BITS(12, 13) +#define RX_STATUS_OFLD_OFFSET 12 +#define RX_STATUS_EAPOL_PACKET BIT(12) +#define RX_STATUS_ARP_NS_PACKET BIT(13) +#define RX_STATUS_TDLS_PACKET BITS(12, 13) +#define RX_STATUS_MGC BIT(14) +#define RX_STATUS_WOL_MASK BITS(15, 19) +#define RX_STATUS_WOL_OFFSET 15 +#define RX_STATUS_CLS_BITMAP_MASK BITS(20, 29) +#define RX_STATUS_CLS_BITMAP_OFFSET 20 +#define RX_STATUS_PF_MODE_BLACK_LIST BIT(30) +#define RX_STATUS_PF_STS_CHECKED BIT(31) + +/* DW 12 */ +#define RX_STATUS_FRAG_NUM_MASK BITS(0, 3) +#define RX_STATUS_SEQ_NUM_MASK BITS(4, 15) +#define RX_STATUS_SEQ_NUM_OFFSET 4 + +#define RX_STATUS_GROUP1_VALID BIT(0) +#define RX_STATUS_GROUP2_VALID BIT(1) +#define RX_STATUS_GROUP3_VALID BIT(2) +#define RX_STATUS_GROUP4_VALID BIT(3) + +#define RX_STATUS_FIXED_LEN 16 + +#define RX_STATUS_CHAN_FREQ_MASK_FOR_BY_PASS_MPDE BITS(0, 7) +#define RX_STATUS_FLAG_FCS_ERROR_FOR_BY_PASS_MODE BIT(16) + +/* Timing Measurement Report */ +/* DW0 Word 1 */ +#define RX_TMR_TOA_VALID BIT(11) +#define RX_TMR_TOD_VALID BIT(10) +#define RX_TMR_TYPE_MASK BITS(8, 9) +#define RX_TMR_TYPE_OFFSET 8 +#define RX_TMR_SUBTYPE_MASK BITS(4, 7) +#define RX_TMR_SUBTYPE_OFFSET 4 + +/* DW0 Byte 1*/ +#define RX_TMR_TM_FAILED BIT(2) +#define RX_TMR_NOISY_CHAN BIT(1) +#define RX_TMR_RESPONDER BIT(0) + +/* TBD */ +#define DMA_OWN_TO_HW BIT(0) +#define DMA_OWN_TO_FW_PENDING BIT(1) +#define STATUS_IS_OWN_TO_FW(flag) \ + (((flag) & DMA_OWN_TO_HW) ? FALSE : TRUE) +#define STATUS_IS_FW_PENDING(flag) \ + (((flag) & DMA_OWN_TO_FW_PENDING) ? TRUE : FALSE) + +/* DW 2 */ +#define RX_STATUS_PACKET_LENGTH_MASK BITS(0, 16) + +#define RX_STATUS_HEADER_TRAN_MASK BIT(7) +#define RX_STATUS_HEADER_TRAN_OFFSET 7 +#define RX_STATUS_HEADER_TRAN_BSS0_MASK BIT(6) +#define RX_STATUS_HEADER_TRAN_BSS0_OFFSET 6 +#define RX_STATUS_HEADER_TRAN_BSS1_MASK BIT(7) +#define RX_STATUS_HEADER_TRAN_BSS1_OFFSET 7 + +/* DW 4 */ +#define RX_STATUS_MATCH_PACKET BIT(4) + +#define RX_STATUS_HEADER_OFFSET_MASK 0xC0 +#define RX_STATUS_HEADER_OFFSET_OFFSET 6 + +/*------------------------------------------------------------------------------ + * Bit fields for HW_RX_VECTOR_DESC_T + *------------------------------------------------------------------------------ + */ +/* DW 2 */ +#define RX_VECTOR_FOR_BA_ACK BIT(7) + +/*! HIF RX DMA Descriptor */ +/* DW 2 */ +#define HIF_RX_DESC_BUFFER_LEN BITS(0, 15) +#define HIF_RX_DESC_ETHER_TYPE_OFFSET_MASK BITS(16, 23) +#define HIF_RX_DESC_ETHER_TYPE_OFFSET_OFFSET 16 +#define HIF_RX_DESC_IP_CHKSUM_CHECK BIT(24) +#define HIF_RX_DESC_TCP_UDP_CHKSUM_CHECK BIT(25) + +#define HIF_RX_DATA_QUEUE 0 +#define HIF_RX_EVENT_QUEUE 1 + +/*------------------------------------------------------------------------------ + * Bit fields for PHY Vector + *------------------------------------------------------------------------------ + */ + +/* RX Vector, 1st Cycle */ +#define RX_VT_RX_RATE_AC_MASK BITS(0, 3) +#define RX_VT_RX_RATE_MASK BITS(0, 6) +#define RX_VT_RX_RATE_OFFSET 0 +#define RX_VT_STBC_MASK BITS(7, 8) +#define RX_VT_STBC_OFFSET 7 +#define RX_VT_LDPC BIT(9) +#define RX_VT_NESS_MASK BITS(10, 11) +#define RX_VT_NESS_OFFSET 10 +#define RX_VT_RX_MODE_MASK BITS(12, 14) +#define RX_VT_RX_MODE_OFFSET 12 +#define RX_VT_RX_MODE_VHT BIT(14) +#define RX_VT_FR_MODE_MASK BITS(15, 16) +#define RX_VT_FR_MODE_OFFSET 15 +#define RX_VT_TXOP_PS_NOT_ALLOWED BIT(17) +#define RX_VT_AGGREGATION BIT(18) +#define RX_VT_SHORT_GI BIT(19) +#define RX_VT_SMOOTH BIT(20) +#define RX_VT_NO_SOUNDING BIT(21) +#define RX_VT_SOUNDING BIT(21) +#if 0 +/* VHT_SIG_A2[B1], not defined in MT6632 */ +#define RX_VT_SHORT_GI_NSYM BIT(22) +/* VHT_SIG_A2[B2:B3], not defined in MT6632 */ +#define RX_VT_CODING_MASK BITS(23, 24) +#define RX_VT_CODING_OFFSET 23 +#endif +#define RX_VT_NUM_RX_MASK BITS(22, 23) +#define RX_VT_NUM_RX_OFFSET 22 +#define RX_VT_LDPC_EXTRA_OFDM_SYM BIT(24) /* VHT_SIG_A2[B3] */ +#define RX_VT_SU_VHT_MU1_3_CODING BITS(25, 28) /* VHT_SIG_A2[B4:B7] */ +#define RX_VT_SU_VHT_MU1_3_CODING_OFFSET 25 +#define RX_VT_BEAMFORMED BIT(29) /* VHT_SIG_A2[B8] */ +#define RX_VT_ACID_DET_LOW BIT(30) +#define RX_VT_ACID_DET_HIGH BIT(31) + +#define RX_VT_RX_RATE_1M 0x0 +#define RX_VT_RX_RATE_2M 0x1 +#define RX_VT_RX_RATE_5M 0x2 +#define RX_VT_RX_RATE_11M 0x3 +#define RX_VT_RX_RATE_6M 0xB +#define RX_VT_RX_RATE_9M 0xF +#define RX_VT_RX_RATE_12M 0xA +#define RX_VT_RX_RATE_18M 0xE +#define RX_VT_RX_RATE_24M 0x9 +#define RX_VT_RX_RATE_36M 0xD +#define RX_VT_RX_RATE_48M 0x8 +#define RX_VT_RX_RATE_54M 0xC + +#define RX_VT_RX_RATE_MCS0 0 +#define RX_VT_RX_RATE_MCS1 1 +#define RX_VT_RX_RATE_MCS2 2 +#define RX_VT_RX_RATE_MCS3 3 +#define RX_VT_RX_RATE_MCS4 4 +#define RX_VT_RX_RATE_MCS5 5 +#define RX_VT_RX_RATE_MCS6 6 +#define RX_VT_RX_RATE_MCS7 7 +#define RX_VT_RX_RATE_MCS32 32 + +#define RX_VT_LEGACY_CCK 0 +#define RX_VT_LEGACY_OFDM 1 +#define RX_VT_MIXED_MODE 2 +#define RX_VT_GREEN_MODE 3 +#define RX_VT_VHT_MODE 4 + +#define RX_VT_LG20_HT20 0 +#define RX_VT_DL40_HT40 1 +#define RX_VT_U20 2 +#define RX_VT_L20 3 + +#define RX_VT_FR_MODE_20 0 +#define RX_VT_FR_MODE_40 1 +#define RX_VT_FR_MODE_80 2 +#define RX_VT_FR_MODE_160 3 /*BW160 or BW80+80*/ + +#define RX_VT_CCK_SHORT_PREAMBLE BIT(2) + +/* RX Vector, 2nd Cycle */ +#define RX_VT_RX_LEN_HT_MASK BITS(0, 15) +#define RX_VT_RX_LEN_LEACY_MASK BITS(0, 11) +#define RX_VT_RX_LEN_VHT_MASK BITS(0, 20) +#define RX_VT_GROUP_ID_MASK BITS(21, 26) +#define RX_VT_GROUP_ID_OFFSET 21 +#define RX_VT_GROUPID_0_MASK BITS(21, 22) /* VHT_SIG_A1[B4:B5] */ +#define RX_VT_GROUPID_0_OFFSET 21 +#define RX_VT_GROUPID_1_MASK BITS(23, 26) /* VHT_SIG_A1[B6:B9] */ +#define RX_VT_GROUPID_1_OFFSET 23 + +#define RX_VT_NSTS_MASK BITS(27, 29) +#define RX_VT_NSTS_OFFSET 27 +#define RX_VT_RX_INDICATOR BIT(30) +#define RX_VT_SEL_ANT BIT(31) /* Not use in MT7615 and MT6632 */ + +/* RX Vector, 3rd Cycle */ +#define RX_VT_PART_AID_MASK BITS(3, 11) +#define RX_VT_PART_AID_OFFSET 3 +#define RX_VT_AID_0_MASK BITS(3, 6) /* VHT_SIG_A1[B13:B16] */ +#define RX_VT_AID_0_OFFSET 3 +#define RX_VT_AID_1_MASK BITS(7, 11) /* VHT_SIG_A1[B17:B21] */ +#define RX_VT_AID_1_OFFSET 7 + + +#define RX_VT_NSTS_PART_AID_MASK BITS(0, 11) +#define RX_VT_NSTS_PART_AID_OFFSET 0 +#define RX_VT_POP_EVER_TRIG BIT(12) +#define RX_VT_FAGC_LNA_RX_MASK BITS(13, 15) +#define RX_VT_FAGC_LNA_RX_OFFSET 13 +#define RX_VT_IB_RSSI_MASK BITS(16, 23) +#define RX_VT_IB_RSSI_OFFSET 16 +#define RX_VT_WB_RSSI_MASK BITS(24, 31) +#define RX_VT_WB_RSSI_OFFSET 24 + +/* RX Vector, 4th Cycle */ +#define RX_VT_RCPI0_MASK BITS(0, 7) +#define RX_VT_RCPI0_OFFSET 0 +#define RX_VT_RCPI1_MASK BITS(8, 15) +#define RX_VT_RCPI1_OFFSET 8 +#define RX_VT_RCPI2_MASK BITS(16, 23) +#define RX_VT_RCPI2_OFFSET 16 +#define RX_VT_RCPI3_MASK BITS(24, 31) +#define RX_VT_RCPI3_OFFSET 24 + +/* RX Vector, 5th Cycle */ +#define RX_VT_FAGC_LNA_GAIN_MASK BITS(0, 2) +#define RX_VT_FAGC_LNA_GAIN_OFFSET 0 +#define RX_VT_FAGC_LPF_GAIN_MASK BITS(3, 6) +#define RX_VT_FAGC_LPF_GAIN_OFFSET 3 +#define RX_VT_OFDM_FOE_MASK BITS(7, 18) +#define RX_VT_OFDM_FOE_OFFSET 7 +#define RX_VT_LTF_PROC_TIME_MASK BITS(19, 25) +#define RX_VT_LTF_PROC_TIME_OFFSET 19 +#define RX_VT_LTF_SNR_MASK BITS(26, 31) +#define RX_VT_LTF_SNR_OFFSET 26 + +/*RX Vector, 6th Cycle*/ +#define RX_VT_NF0_MASK BITS(0, 7) +#define RX_VT_NF0_OFFSET 0 +#define RX_VT_NF1_MASK BITS(8, 15) +#define RX_VT_NF1_OFFSET 8 +#define RX_VT_NF2_MASK BITS(16, 23) +#define RX_VT_NF2_OFFSET 16 +#define RX_VT_NF3_MASK BITS(24, 31) +#define RX_VT_NF3_OFFSET 24 + +/* RX Vector Group 2, the 1st cycle */ +#define RX_VT_PRIM_ITFR_ENV BIT(0) +#define RX_VT_SEC_ITFR_ENV BIT(1) +#define RX_VT_SEC40_ITFR_ENV BIT(2) +#define RX_VT_SEC80_ITFR_ENV BIT(3) +#define RX_VT_OFDM_LQ_BPSK_MASK BITS(4, 10) +#define RX_VT_OFDM_LQ_BPSK_OFFSET 4 +#define RX_VT_OFDM_CAPACITY_LQ_MASK BITS(11, 17) +#define RX_VT_OFDM_CAPACITY_LQ_OFFSET 11 +#define RX_VT_CCK_LQ_MASK BITS(4, 13) +#define RX_VT_CCK_LQ_OFFSET 4 + +/* RX Vector Group 2, the 2nd cycle */ +#define RX_VT_DYNA_BW_IN_NON_HT_DYNA BIT(19) +#define RX_VT_CH_BW_IN_NON_HT_MASK BITS(20, 21) +#define RX_VT_CH_BW_IN_NON_HT_OFFSET 20 + +#define RX_VT_CH_BW_IN_NON_HT_CBW40 BIT(20) +#define RX_VT_CH_BW_IN_NON_HT_CBW80 BIT(21) +#define RX_VT_CH_BW_IN_NON_HT_CBW160 BITS(20, 21) + +/* RX Data Type */ +#define RX_DATA_TYPE_RX_VECTOR 0 +#define RX_DATA_TYPE_RX_DATA 1 +#define RX_DATA_TYPE_RX_EVM 2 +#define RX_DATA_TYPE_RX_AMBI 3 +#define RX_DATA_TYPE_RX_BT 4 + +/*------------------------------------------------------------------------------ + * Radiotap define + *------------------------------------------------------------------------------ + */ + +/*Radiotap VHT*/ +#define RADIOTAP_VHT_ALL_KNOWN BITS(0, 8) +#define RADIOTAP_VHT_STBC_KNOWN BIT(0) +#define RADIOTAP_VHT_TXOP_PS_NOT_ALLOWED_KNOWN BIT(1) +#define RADIOTAP_VHT_GI_KNOWN BIT(2) +#define RADIOTAP_VHT_SHORT_GI_NSYM_KNOWN BIT(3) +#define RADIOTAP_VHT_LDPC_EXTRA_OFDM_SYM_KNOWN BIT(4) +#define RADIOTAP_VHT_BEAMFORMED_KNOWN BIT(5) +#define RADIOTAP_VHT_BAND_WIDTH_KNOWN BIT(6) +#define RADIOTAP_VHT_BAND_GROUP_ID_KNOWN BIT(7) +#define RADIOTAP_VHT_BAND_PARTIAL_AID_KNOWN BIT(8) + +#if CFG_MTK_MCIF_WIFI_SUPPORT +#define NIC_RX_ROOM_SIZE (32 + 32) +#endif + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +enum ENUM_RX_STATISTIC_COUNTER { + RX_MPDU_TOTAL_COUNT = 0, + RX_SIZE_ERR_DROP_COUNT, + + RX_DATA_INDICATION_COUNT, + RX_DATA_RETURNED_COUNT, + RX_DATA_RETAINED_COUNT, + + RX_DATA_REORDER_TOTAL_COUNT, + RX_DATA_REORDER_MISS_COUNT, + RX_DATA_REORDER_WITHIN_COUNT, + RX_DATA_REORDER_AHEAD_COUNT, + RX_DATA_REORDER_BEHIND_COUNT, + + RX_DATA_MSDU_IN_AMSDU_COUNT, + RX_DATA_AMSDU_MISS_COUNT, + RX_DATA_AMSDU_COUNT, + + RX_DROP_TOTAL_COUNT, + + RX_NO_STA_DROP_COUNT, + RX_INACTIVE_BSS_DROP_COUNT, + RX_HS20_DROP_COUNT, + RX_LESS_SW_RFB_DROP_COUNT, + RX_DUPICATE_DROP_COUNT, + RX_MIC_ERROR_DROP_COUNT, + RX_BAR_DROP_COUNT, + RX_NO_INTEREST_DROP_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 ENUM_RX_PKT_DESTINATION { + /* to OS */ + RX_PKT_DESTINATION_HOST, + /* to TX queue for forward, AP mode */ + RX_PKT_DESTINATION_FORWARD, + /* to both TX and OS, AP mode broadcast packet */ + RX_PKT_DESTINATION_HOST_WITH_FORWARD, + /* packet to be freed */ + RX_PKT_DESTINATION_NULL, + RX_PKT_DESTINATION_NUM +}; + +/* Used for MAC RX */ +enum ENUM_MAC_RX_PKT_TYPE { + RX_PKT_TYPE_TX_STATUS = 0, + RX_PKT_TYPE_RX_VECTOR, + RX_PKT_TYPE_RX_DATA, + RX_PKT_TYPE_DUP_RFB, + RX_PKT_TYPE_TM_REPORT, + RX_PKT_TYPE_MSDU_REPORT = 6, + RX_PKT_TYPE_SW_DEFINED = 7 +}; + +enum ENUM_MAC_RX_GROUP_VLD { + RX_GROUP_VLD_1 = 0, + RX_GROUP_VLD_2, + RX_GROUP_VLD_3, + RX_GROUP_VLD_4, +#if (CFG_SUPPORT_CONNAC2X == 1) + RX_GROUP_VLD_5, +#endif /* CFG_SUPPORT_CONNAC2X == 1 */ + RX_GROUP_VLD_NUM +}; + +enum ENUM_MAC_GI_INFO { + MAC_GI_NORMAL = 0, + MAC_GI_SHORT +}; + +enum ENUM_RXPI_MODE { + RCPI_MODE_WF0 = 0, + RCPI_MODE_WF1, + RCPI_MODE_WF2, + RCPI_MODE_WF3, + RCPI_MODE_AVG, + RCPI_MODE_MAX, + RCPI_MODE_MIN, + RCPI_MODE_NUM +}; + +#define RXM_RXD_PKT_TYPE_SW_BITMAP 0xE00F +#define RXM_RXD_PKT_TYPE_SW_EVENT 0xE000 +#define RXM_RXD_PKT_TYPE_SW_FRAME 0xE001 + +/* AMPDU data frame with no errors including + * FC/FM/I/T/LM/DAF/EL/LLC-MIS/ UDFVLT and Class 3 error + */ +#define RXS_DW2_AMPDU_nERR_BITMAP 0xFFFB /* ignore CM bit (2) 0xFFFF */ +#define RXS_DW2_AMPDU_nERR_VALUE 0x0000 +/* no error including FC/CLM/I/T/LM/DAF/EL/HTF */ +#define RXS_DW2_RX_nERR_BITMAP 0x03FA /* ignore CM bit (2) 0x03FE */ +#define RXS_DW2_RX_nERR_VALUE 0x0000 +/* Non-Data frames */ +#define RXS_DW2_RX_nDATA_BITMAP 0x3000 +#define RXS_DW2_RX_nDATA_VALUE 0x2000 +/* Claas Error */ +#define RXS_DW2_RX_CLASSERR_BITMAP 0x0001 +#define RXS_DW2_RX_CLASSERR_VALUE 0x0001 +/* Fragmentation */ +#define RXS_DW2_RX_FRAG_BITMAP 0x3800 +#define RXS_DW2_RX_FRAG_VALUE 0x0800 + + +/* TX Free Done Event Definition + * Format version of this tx done event. + * 0: MT7615 + * 1: MT7622, CONNAC (X18/P18/MT7663) + * 2: MT7619_AXE, MT7915 E1, Petrus + * 3: MT7915 E2, Buzzard + */ +enum { + TFD_EVT_VER_0, + TFD_EVT_VER_1, + TFD_EVT_VER_2, + TFD_EVT_VER_3, +}; + +#define RX_TFD_EVT_V3_PAIR_SHIFT 31 +#define RX_TFD_EVT_V3_PAIR_MASK BIT(31) +#define RX_TFD_EVT_V3_QID_SHIFT 24 +#define RX_TFD_EVT_V3_QID_MASK BITS(24, 30) +#define RX_TFD_EVT_V3_WLAN_ID_SHIFT 14 +#define RX_TFD_EVT_V3_WLAN_ID_MASK BITS(14, 23) +#define RX_TFD_EVT_V3_MSDU_ID_SHIFT 16 +#define RX_TFD_EVT_V3_MSDU_ID_MASK BITS(16, 30) + +#define RX_TFD_EVT_V3_GET_PAIR_BIT(_rField) \ + (((_rField) & (RX_TFD_EVT_V3_PAIR_MASK)) >> (RX_TFD_EVT_V3_PAIR_SHIFT)) +#define RX_TFD_EVT_V3_GET_MSDU_ID(_rField) \ + (((_rField) & (RX_TFD_EVT_V3_MSDU_ID_MASK)) \ + >> (RX_TFD_EVT_V3_MSDU_ID_SHIFT)) + + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/*! A data structure which is identical with MAC RX DMA Descriptor */ +struct HW_MAC_RX_DESC { + uint16_t u2RxByteCount; /* DW 0 */ + uint16_t u2PktTYpe; + uint8_t ucMatchPacket; /* DW 1 */ + uint8_t ucChanFreq; + uint8_t ucHeaderLen; + uint8_t ucBssid; + uint8_t ucWlanIdx; /* DW 2 */ + uint8_t ucTidSecMode; + uint16_t u2StatusFlag; + uint32_t u4PatternFilterInfo; /* DW 3 */ + uint32_t u4PatternFilterInfo2; /* DW 4 */ +}; + +struct HW_MAC_RX_STS_GROUP_1 { + uint8_t aucPN[16]; +}; + +struct HW_MAC_RX_STS_GROUP_2 { + uint32_t u4Timestamp; /* DW 12 */ + uint32_t u4CRC; /* DW 13 */ +}; + +struct HW_MAC_RX_STS_GROUP_4 { + /* For HDR_TRAN */ + uint16_t u2FrameCtl; /* DW 4 */ + uint8_t aucTA[6]; /* DW 4~5 */ + uint16_t u2SeqFrag; /* DW 6 */ + uint16_t u2Qos; /* DW 6 */ + uint32_t u4HTC; /* DW 7 */ +}; + +struct HW_MAC_RX_STS_GROUP_3 { + /*! RX Vector Info */ + uint32_t u4RxVector[6]; /* DW 14~19 */ +}; + +#if (CFG_SUPPORT_CONNAC2X == 1) +struct HW_MAC_RX_STS_GROUP_3_V2 { + /* PRXVector Info */ + uint32_t u4RxVector[2]; /* FALCON: DW 16~17 */ +}; + +struct HW_MAC_RX_STS_GROUP_5 { + /* CRXVector Info */ + /* FALCON: DW 18~33 for harrier E1, DW 18~35 for harrier E2 + * Other project: give group5_size in chip info, + * e.g Soc3_0.c +, + * or modify prChipInfo->group5_size when doing wlanCheckAsicCap, + * e.g. Harrier E1 + */ + uint32_t u4RxVector[18]; +}; + +struct HW_MAC_RX_STS_HARRIER_E1_GROUP_5 { + /* CRXVector Info */ + /* FALCON: DW 18~33 for harrier E1, DW 18~35 for harrier E2 */ + uint32_t u4RxVector[16]; +}; + + +#define CONNAC2X_RSSI_MASK BITS(0, 31) +#define CONNAC2X_SEL_ANT BITS(28, 30) +#endif /* CFG_SUPPORT_CONNAC2X == 1 */ + +struct HW_MAC_RX_TMRI_PKT_FORMAT { + uint8_t ucPID; + uint8_t ucStatus; + uint16_t u2PktTYpe; + uint32_t u4Reserved[2]; + uint32_t u4ToA; + uint32_t u4ToD; +}; + +struct HW_MAC_RX_TMRR_PKT_FORMAT { + uint8_t ucVtSeq; + uint8_t ucStatus; + uint16_t u2PktTYpe; + uint8_t aucTALow[2]; + uint16_t u2SnField; + uint8_t aucTAHigh[4]; + uint32_t u4ToA; + uint32_t u4ToD; +}; + +/*! A data structure which is identical with MAC RX Vector DMA Descriptor */ +struct HW_RX_VECTOR_DESC { + uint8_t aucTA[6]; /* DW 0~1 */ + uint8_t ucRxVtSeqNo; + /*! RX Vector Info */ + uint32_t u4RxVector[9]; /* DW 2~10 */ + +}; + +union HW_MAC_MSDU_TOKEN_T { + struct { + uint16_t u2MsduID[2]; + } rFormatV0; + struct { + uint16_t u2MsduID; + uint16_t u2WlanID:10; + uint16_t u2Rsv:1; + uint16_t u2QueIdx:5; + } rFormatV1; + struct { + uint32_t u2MsduID:15; + uint32_t u2WlanID:10; + uint32_t u2QueIdx:7; + } rFormatV2; + union { + struct { + uint32_t u4TxCnt:13; + uint32_t u4Stat:2; + uint32_t u4H:1; + uint32_t u4MsduID:15; + uint32_t u4Pair:1; + } rP0; + struct { + uint32_t u4BW:2; + uint32_t u4Rate:4; + uint32_t u4GI:2; + uint32_t u4TxMode:2; + uint32_t u4Nsts:3; + uint32_t u4DCM:1; + uint32_t u4WlanID:10; + uint32_t u4QID:7; + uint32_t u4Pair:1; + } rP1; + } rFormatV3; +}; + +struct HW_MAC_MSDU_REPORT { + /* DW 0 */ + union { + struct { + uint16_t u2BufByteCount; + uint16_t u2MsduCount:7; + uint16_t u2TxDoneInfo:9; + } field; + + struct { + uint16_t u2BufByteCount; + uint16_t u2MsduCount:10; + uint16_t u2Rsv:1; + uint16_t u2PktType:5; + } field_v3; + + uint32_t word; + } DW0; + + /* DW 1 */ + union { + struct { + uint32_t u4TxdCount:8; + uint32_t u4Rsv1:8; + uint32_t u4Ver:3; + uint32_t u4Rsv2:13; + } field; + + uint32_t word; + } DW1; + + /* DW 2 */ + /* MSDU token array */ + union HW_MAC_MSDU_TOKEN_T au4MsduToken[0]; +}; + +struct SW_RFB { + struct QUE_ENTRY rQueEntry; + void *pvPacket; /*!< ptr to rx Packet Descriptor */ + uint8_t *pucRecvBuff; /*!< ptr to receive data buffer */ + + /* add fot mt6630 */ + uint8_t ucGroupVLD; + uint16_t u2RxStatusOffst; + void *prRxStatus; + struct HW_MAC_RX_STS_GROUP_1 *prRxStatusGroup1; + struct HW_MAC_RX_STS_GROUP_2 *prRxStatusGroup2; + void *prRxStatusGroup3; + struct HW_MAC_RX_STS_GROUP_4 *prRxStatusGroup4; +#if (CFG_SUPPORT_CONNAC2X == 1) + struct HW_MAC_RX_STS_GROUP_5 *prRxStatusGroup5; +#endif /* CFG_SUPPORT_CONNAC2X == 1 */ + + /* rx data information */ + void *pvHeader; + uint16_t u2RxByteCount; + uint16_t u2PacketLen; + uint16_t u2HeaderLen; + + uint8_t *pucPayload; + uint16_t u2PayloadLength; + + struct STA_RECORD *prStaRec; + + uint8_t ucPacketType; + uint8_t ucPayloadFormat; + uint8_t ucSecMode; + uint8_t ucOFLD; + uint8_t ucKeyID; + uint8_t ucChanFreq; + uint8_t ucRxvSeqNo; + uint8_t ucChnlNum; + + /* rx sta record */ + uint8_t ucWlanIdx; + uint8_t ucStaRecIdx; + + u_int8_t fgReorderBuffer; + u_int8_t fgDataFrame; + u_int8_t fgFragFrame; + u_int8_t fgHdrTran; + u_int8_t fgIcvErr; + u_int8_t fgIsBC; + u_int8_t fgIsMC; + u_int8_t fgIsCipherMS; + u_int8_t fgIsCipherLenMS; + u_int8_t fgIsFrag; + u_int8_t fgIsFCS; + u_int8_t fgIsAmpdu; + /* duplicate detection */ + uint16_t u2FrameCtrl; + uint16_t u2SequenceControl; + uint16_t u2SSN; + uint8_t ucTid; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + uint32_t u4TcpUdpIpCksStatus; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + enum ENUM_CSUM_RESULT aeCSUM[CSUM_TYPE_NUM]; + enum ENUM_RX_PKT_DESTINATION eDst; + /* only valid when eDst == FORWARD */ + enum ENUM_TRAFFIC_CLASS_INDEX eTC; +#if 0 + /* RX reorder for one MSDU in AMSDU issue */ + /*QUE_T rAmsduQue;*/ +#endif + uint64_t rIntTime; +}; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +struct RX_CSO_REPORT_T { + uint32_t u4IpV4CksStatus:1; + uint32_t u4Reserved1:1; + uint32_t u4TcpCksStatus:1; + uint32_t u4UdpCksStatus:1; + uint32_t u4IpV4CksType:1; + uint32_t u4IpV6CksType:1; + uint32_t u4TcpCksType:1; + uint32_t u4UdpCksType:1; + uint32_t u4IpDataLenMismatch:1; + uint32_t u4IpFragPkg:1; + uint32_t u4UnknowNextHeader:1; + uint32_t u4Reserved2:21; +}; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +/*! RX configuration type structure */ +struct RX_CTRL { + uint32_t u4RxCachedSize; + uint8_t *pucRxCached; + struct QUE rFreeSwRfbList; + struct QUE rReceivedRfbList; + struct QUE rIndicatedRfbList; + +#if CFG_SDIO_RX_AGG + uint8_t *pucRxCoalescingBufPtr; +#endif + + void *apvIndPacket[CFG_RX_MAX_PKT_NUM]; + void *apvRetainedPacket[CFG_RX_MAX_PKT_NUM]; + + uint8_t ucNumIndPacket; + uint8_t ucNumRetainedPacket; + /*!< RX Counters */ + uint64_t au8Statistics[RX_STATISTIC_COUNTER_NUM]; + +#if CFG_HIF_STATISTICS + uint32_t u4TotalRxAccessNum; + uint32_t u4TotalRxPacketNum; +#endif + +#if CFG_HIF_RX_STARVATION_WARNING + uint32_t u4QueuedCnt; + uint32_t u4DequeuedCnt; +#endif + +#if CFG_RX_PKTS_DUMP + uint32_t u4RxPktsDumpTypeMask; +#endif + +#if CFG_SUPPORT_SNIFFER + uint32_t u4AmpduRefNum; +#endif + + /* Store SysTime of Last Rx */ + uint32_t u4LastRxTime[MAX_BSSID_NUM]; +}; + +struct RX_MAILBOX { + uint32_t u4RxMailbox[2]; /* for Device-to-Host Mailbox */ +}; + +typedef uint32_t(*PROCESS_RX_MGT_FUNCTION) (struct ADAPTER *, struct SW_RFB *); + +typedef void(*PROCESS_RX_EVENT_FUNCTION) (struct ADAPTER *, + struct WIFI_EVENT *); + +struct RX_EVENT_HANDLER { + enum ENUM_EVENT_ID eEID; + PROCESS_RX_EVENT_FUNCTION pfnHandler; +}; + +struct EMU_MAC_RATE_INFO { + uint8_t ucPhyRateCode; + uint32_t u4PhyRate[4][2]; +}; + +struct RX_DESC_OPS_T { + uint16_t (*nic_rxd_get_rx_byte_count)( + void *prRxStatus); + uint8_t (*nic_rxd_get_pkt_type)( + void *prRxStatus); + uint8_t (*nic_rxd_get_wlan_idx)( + void *prRxStatus); + uint8_t (*nic_rxd_get_sec_mode)( + void *prRxStatus); + uint8_t (*nic_rxd_get_sw_class_error_bit)( + void *prRxStatus); + uint8_t (*nic_rxd_get_ch_num)( + void *prRxStatus); + uint8_t (*nic_rxd_get_rf_band)( + void *prRxStatus); + uint8_t (*nic_rxd_get_tcl)( + void *prRxStatus); + uint8_t (*nic_rxd_get_ofld)( + void *prRxStatus); + void (*nic_rxd_fill_rfb)( + struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); + u_int8_t (*nic_rxd_sanity_check)( + struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG + void (*nic_rxd_check_wakeup_reason)( + struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); +#endif /* CFG_SUPPORT_WAKEUP_REASON_DEBUG */ +}; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +#define NIC_RX_GET_U2_SW_PKT_TYPE(__rx_status) \ + (uint16_t)((*(uint32_t *)(__rx_status) & (BITS(16, 31))) >> (16)) + +#define RATE_INFO(_RateCode, _Bw20, _Bw20SGI, _Bw40, _BW40SGI, \ + _Bw80, _Bw80SGI, _Bw160, _Bw160SGI) \ + { \ + .ucPhyRateCode = (_RateCode), \ + .u4PhyRate[RX_VT_FR_MODE_20][MAC_GI_NORMAL] = (_Bw20), \ + .u4PhyRate[RX_VT_FR_MODE_20][MAC_GI_SHORT] = (_Bw20SGI), \ + .u4PhyRate[RX_VT_FR_MODE_40][MAC_GI_NORMAL] = (_Bw40), \ + .u4PhyRate[RX_VT_FR_MODE_40][MAC_GI_SHORT] = (_BW40SGI), \ + .u4PhyRate[RX_VT_FR_MODE_80][MAC_GI_NORMAL] = (_Bw80), \ + .u4PhyRate[RX_VT_FR_MODE_80][MAC_GI_SHORT] = (_Bw80SGI), \ + .u4PhyRate[RX_VT_FR_MODE_160][MAC_GI_NORMAL] = (_Bw160), \ + .u4PhyRate[RX_VT_FR_MODE_160][MAC_GI_SHORT] = (_Bw160SGI), \ + } + +#define RX_INC_CNT(prRxCtrl, eCounter) \ + {((struct RX_CTRL *)prRxCtrl)->au8Statistics[eCounter]++; } + +#define RX_ADD_CNT(prRxCtrl, eCounter, u8Amount) \ + {((struct RX_CTRL *)prRxCtrl)->au8Statistics[eCounter] += \ + (uint64_t)u8Amount; } + +#define RX_GET_CNT(prRxCtrl, eCounter) \ + (((struct RX_CTRL *)prRxCtrl)->au8Statistics[eCounter]) + +#define RX_RESET_ALL_CNTS(prRxCtrl) \ + {kalMemZero(&prRxCtrl->au8Statistics[0], \ + sizeof(prRxCtrl->au8Statistics)); } + +#define RX_STATUS_TEST_MORE_FLAG(flag) \ + ((u_int8_t)((flag & RX_STATUS_FLAG_MORE_PACKET) ? TRUE : FALSE)) + +#define RX_STATUS_GET(__RxDescOps, __out_buf, __fn_name, __rx_status) { \ + if (__RxDescOps->nic_rxd_##__fn_name) \ + __out_buf = __RxDescOps->nic_rxd_##__fn_name(__rx_status); \ + else {\ + __out_buf = 0; \ + DBGLOG(RX, ERROR, "%s:: no hook api??\n", \ + __func__); \ + } \ +} \ +/*------------------------------------------------------------------------------ + * MACRO for HW_MAC_RX_DESC_T + *------------------------------------------------------------------------------ + */ +/* DW 0 */ +#define HAL_RX_STATUS_GET_RX_BYTE_CNT(_prHwMacRxDesc) \ + ((_prHwMacRxDesc)->u2RxByteCount) +#define HAL_RX_STATUS_GET_ETH_TYPE_OFFSET(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2PktTYpe & RX_STATUS_ETH_TYPE_OFFSET_MASK) >> \ + RX_STATUS_ETH_TYPE_OFFSET) +#define HAL_RX_STATUS_GET_GROUP_VLD(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2PktTYpe & RX_STATUS_GROUP_VLD_MASK) >> \ + RX_STATUS_GROUP_VLD_OFFSET) +#define HAL_RX_STATUS_GET_PKT_TYPE(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2PktTYpe & RX_STATUS_PKT_TYPE_MASK) \ + >> RX_STATUS_PKT_TYPE_OFFSET) + +/* DW 1 */ +#define HAL_RX_STATUS_IS_HTC_EXIST(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_HTC)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_UC2ME(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_UC2ME) \ + ? TRUE : FALSE) +#define HAL_RX_STATUS_IS_MC(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_MC_FRAME)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_BC(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_BC_FRAME)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_BCN_WITH_BMC(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_BCN_WITH_BMC)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_BCN_WITH_UC(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_BCN_WITH_UC)?TRUE:FALSE) +#define HAL_RX_STATUS_GET_KEY_ID(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_KEYID_MASK) >> \ + RX_STATUS_KEYID_OFFSET) +#define HAL_RX_STATUS_GET_CHAN_FREQ(_prHwMacRxDesc) \ + ((_prHwMacRxDesc)->ucChanFreq) +#define HAL_RX_STATUS_GET_HEADER_LEN(_prHwMacRxDesc) \ + ((_prHwMacRxDesc)->ucHeaderLen & RX_STATUS_HEADER_LEN_MASK) +#define HAL_RX_STATUS_IS_HEADER_OFFSET(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucHeaderLen & RX_STATUS_HEADER_OFFSET)?TRUE:FALSE) +#define HAL_RX_STATUS_GET_HEADER_OFFSET(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucHeaderLen & RX_STATUS_HEADER_OFFSET) ? 2 : 0) +#define HAL_RX_STATUS_IS_HEADER_TRAN(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucHeaderLen & RX_STATUS_HEADER_TRAN)?TRUE:FALSE) +#define HAL_RX_STATUS_GET_HEADER_TRAN(_prHwMacRxDesc) \ + HAL_RX_STATUS_IS_HEADER_TRAN(_prHwMacRxDesc) +#define HAL_RX_STATUS_GET_PAYLOAD_FORMAT(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucBssid & RX_STATUS_PAYLOAD_FORMAT_MASK) >> \ + RX_STATUS_PAYLOAD_FORMAT_OFFSET) +#define HAL_RX_STATUS_GET_BSSID(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucBssid & RX_STATUS_BSSID_MASK) >> \ + RX_STATUS_BSSID_OFFSET) + +/* DW 2 */ +#define HAL_RX_STATUS_GET_WLAN_IDX(_prHwMacRxDesc) \ + ((_prHwMacRxDesc)->ucWlanIdx) +#define HAL_RX_STATUS_GET_TID(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucTidSecMode & RX_STATUS_TID_MASK)) +#define HAL_RX_STATUS_GET_SEC_MODE(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucTidSecMode & RX_STATUS_SEC_MASK) >> \ + RX_STATUS_SEC_OFFSET) +#define HAL_RX_STATUS_GET_SW_BIT(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_SW_BIT)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_FCS_ERROR(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_FCS_ERROR)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_CIPHER_MISMATCH(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_CIPHER_MISMATCH) \ + ? TRUE : FALSE) +#define HAL_RX_STATUS_IS_CLM_ERROR(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & \ + RX_STATUS_FLAG_CIPHER_LENGTH_MISMATCH) \ + ? TRUE : FALSE) +#define HAL_RX_STATUS_IS_ICV_ERROR(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_ICV_ERROR)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_TKIP_MIC_ERROR(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_TKIPMIC_ERROR) > 0 \ + ? TRUE : FALSE) +#define HAL_RX_STATUS_IS_ERROR(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_ERROR_MASK) \ + ? TRUE : FALSE) +#define HAL_RX_STATUS_IS_LEN_MISMATCH(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_LEN_MISMATCH) \ + ? TRUE : FALSE) +#define HAL_RX_STATUS_IS_DE_AMSDU_FAIL(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_DE_AMSDU_FAIL) \ + ? TRUE : FALSE) +#define HAL_RX_STATUS_IS_EXCEED_LEN(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_EXCEED_LEN) \ + ? TRUE : FALSE) +#define HAL_RX_STATUS_IS_LLC_MIS(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_LLC_MIS)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_UDF_VLT(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_UDF_VLT)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_FRAG(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FRAG)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_NULL(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_NULL)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_DATA(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_DATA)?FALSE:TRUE) +#define HAL_RX_STATUS_IS_AMPDU_SUB_FRAME(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_AMPDU_SUB_FRAME) \ + ? FALSE : TRUE) +#define HAL_RX_STATUS_IS_AMPDU_FORMAT(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_AMPDU_FORMAT)?FALSE:TRUE) + +/* DW 3 */ +#define HAL_RX_STATUS_IS_RV_VALID(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_RXV_SEQ_NO_MASK) \ + ? TRUE : FALSE) +#define HAL_RX_STATUS_GET_RXV_SEQ_NO(_prHwMacRxDesc) \ + ((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_RXV_SEQ_NO_MASK) +#define HAL_RX_STATUS_GET_TCL(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_TCL)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_CLS(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_CLS)?TRUE:FALSE) +#define HAL_RX_STATUS_GET_OFLD(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_OFLD_MASK) >> \ + RX_STATUS_OFLD_OFFSET) +#define HAL_RX_STATUS_IS_MGC(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_MGC)?TRUE:FALSE) +#define HAL_RX_STATUS_GET_WOL(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_WOL_MASK) >> \ + RX_STATUS_WOL_OFFSET) +#define HAL_RX_STATUS_GET_CLS_BITMAP(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_CLS_BITMAP_MASK) \ + >> RX_STATUS_CLS_BITMAP_OFFSET) +#define HAL_RX_STATUS_IS_PF_BLACK_LIST(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo \ + & RX_STATUS_PF_MODE_BLACK_LIST) ? TRUE : FALSE) +#define HAL_RX_STATUS_IS_PF_CHECKED(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_PF_STS_CHECKED) \ + ? TRUE : FALSE) + +/* DW 4~7 */ +#define HAL_RX_STATUS_GET_FRAME_CTL_FIELD(_prHwMacRxStsGroup4) \ + ((_prHwMacRxStsGroup4)->u2FrameCtl) +#define HAL_RX_STATUS_GET_TA(_prHwMacRxStsGroup4, pucTA) \ +{\ + kalMemCopy(pucTA, &(_prHwMacRxStsGroup4)->aucTA[0], 6); \ +} +#define HAL_RX_STATUS_GET_SEQ_FRAG_NUM(_prHwMacRxStsGroup4) \ + ((_prHwMacRxStsGroup4)->u2SeqFrag) +#define HAL_RX_STATUS_GET_QOS_CTL_FIELD(_prHwMacRxStsGroup4) \ + ((_prHwMacRxStsGroup4)->u2Qos) + +#define HAL_RX_STATUS_GET_SEQFrag_NUM(_prHwMacRxStsGroup4) \ + ((_prHwMacRxStsGroup4)->u2SeqFrag) +#define HAL_RX_STATUS_GET_HTC(_prHwMacRxStsGroup4) \ + ((_prHwMacRxStsGroup4)->u4HTC) + +/* DW 8~11 */ +#define HAL_RX_STATUS_GET_RSC(_prHwMacRxStsGroup1, pucRSC) \ +{\ + kalMemCopy(pucRSC, &(_prHwMacRxStsGroup1)->aucPN[0], 6); \ +} + +#define HAL_RX_STATUS_GET_PN(_prHwMacRxStsGroup1, pucPN) \ +{\ + kalMemCopy(pucPN, &(_prHwMacRxStsGroup1)->aucPN[0], 16); \ +} + +/* DW 12~13 */ +#define HAL_RX_STATUS_GET_TIMESTAMP(_prHwMacRxStsGroup2, _ucIdx) \ + ((_prHwMacRxStsGroup2)->u4Timestamp) +#define HAL_RX_STATUS_GET_FCS32(_prHwMacRxStsGroup2) \ + ((_prHwMacRxStsGroup2)->u4CRC) + +/* DW 14~19 */ +#define HAL_RX_STATUS_GET_RX_VECTOR(_prHwMacRxStsGroup3, _ucIdx) \ + ((_prHwMacRxStsGroup3)->u4RxVector[_ucIdx]) + +#define HAL_RX_STATUS_GET_RX_NUM(_prHwMacRxStsGroup3) \ + (((_prHwMacRxStsGroup3)->u4RxVector[0] & RX_VT_NUM_RX_MASK) >> \ + RX_VT_NUM_RX_OFFSET) + +#if (CFG_SUPPORT_CONNAC2X == 1) +#define HAL_RX_STATUS_GET_RCPI0(_prHwMacRxStsGroup3) \ + (((_prHwMacRxStsGroup3)->u4RxVector[1] & RX_VT_RCPI0_MASK) >> \ + RX_VT_RCPI0_OFFSET) +#define HAL_RX_STATUS_GET_RCPI1(_prHwMacRxStsGroup3) \ + (((_prHwMacRxStsGroup3)->u4RxVector[1] & RX_VT_RCPI1_MASK) >> \ + RX_VT_RCPI1_OFFSET) +#define HAL_RX_STATUS_GET_RCPI2(_prHwMacRxStsGroup3) \ + (((_prHwMacRxStsGroup3)->u4RxVector[1] & RX_VT_RCPI2_MASK) >> \ + RX_VT_RCPI0_OFFSET) +#define HAL_RX_STATUS_GET_RCPI3(_prHwMacRxStsGroup3) \ + (((_prHwMacRxStsGroup3)->u4RxVector[1] & RX_VT_RCPI3_MASK) >> \ + RX_VT_RCPI1_OFFSET) +#else +#define HAL_RX_STATUS_GET_RCPI0(_prHwMacRxStsGroup3) \ + (((_prHwMacRxStsGroup3)->u4RxVector[3] & RX_VT_RCPI0_MASK) >> \ + RX_VT_RCPI0_OFFSET) +#define HAL_RX_STATUS_GET_RCPI1(_prHwMacRxStsGroup3) \ + (((_prHwMacRxStsGroup3)->u4RxVector[3] & RX_VT_RCPI1_MASK) >> \ + RX_VT_RCPI1_OFFSET) +#endif + +/* TBD */ +#define HAL_RX_STATUS_GET_RX_PACKET_LEN(_prHwMacRxDesc) +#define HAL_RX_STATUS_IS_MATCH_PACKET(_prHwMacRxDesc) + +#define HAL_RX_STATUS_GET_CHNL_NUM(_prHwMacRxDesc) \ + ((((_prHwMacRxDesc)->ucChanFreq) > HW_CHNL_NUM_MAX_4G_5G) ? \ + (((_prHwMacRxDesc)->ucChanFreq) - HW_CHNL_NUM_MAX_4G_5G) : \ + ((_prHwMacRxDesc)->ucChanFreq)) + +/* To do: support more bands other than 2.4G and 5G */ +#define HAL_RX_STATUS_GET_RF_BAND(_prHwMacRxDesc) \ + ((((_prHwMacRxDesc)->ucChanFreq) <= HW_CHNL_NUM_MAX_2G4) ? \ + BAND_2G4 : BAND_5G) + +/*------------------------------------------------------------------------------ + * MACRO for HW_RX_VECTOR_DESC_T + *------------------------------------------------------------------------------ + */ +#define HAL_RX_VECTOR_GET_TA(_prHwRxVector, pucTA) \ +{\ + kalMemCopy(pucTA, &(_prHwRxVector)->aucTA[0], 6); \ +} + +#define HAL_RX_VECTOR_GET_SEQ_NO(_prHwRxVector) \ + ((_prHwRxVector)->ucRxVtSeqNo & RX_STATUS_RXV_SEQ_NO_MASK) +#define HAL_RX_VECTOR_IS_FOR_BA_ACK(_prHwRxVector) \ + (((_prHwRxVector)->ucRxVtSeqNo & RX_VECTOR_FOR_BA_ACK)?TRUE:FALSE) +#define HAL_RX_VECTOR_GET_RX_VECTOR(_prHwRxVector, _ucIdx) \ + ((_prHwRxVector)->u4RxVector[_ucIdx]) + +#define RXM_IS_QOS_DATA_FRAME(_u2FrameCtrl) \ + (((_u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_QOS_DATA) \ + ? TRUE : FALSE) + +#define RXM_IS_DATA_FRAME(_u2FrameCtrl) \ + (((_u2FrameCtrl & MASK_FC_TYPE) == MAC_FRAME_TYPE_DATA) ? TRUE : FALSE) + +#define RXM_IS_CTRL_FRAME(_u2FrameCtrl) \ + (((_u2FrameCtrl & MASK_FC_TYPE) == MAC_FRAME_TYPE_CTRL) ? TRUE : FALSE) + +#define RXM_IS_TRIGGER_FRAME(_u2FrameCtrl) \ + (((_u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_HE_TRIGGER) ?\ + TRUE : FALSE) + +#define RXM_IS_BLOCK_ACK_FRAME(_u2FrameCtrl) \ + (((_u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_BLOCK_ACK) ?\ + TRUE : FALSE) + +#define RXM_IS_MGMT_FRAME(_u2FrameCtrl) \ + (((_u2FrameCtrl & MASK_FC_TYPE) == MAC_FRAME_TYPE_MGT) ? TRUE : FALSE) + +#define RXM_IS_PROTECTED_FRAME(_u2FrameCtrl) \ + ((_u2FrameCtrl & MASK_FC_PROTECTED_FRAME) ? 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 struct ADAPTER *prAdapter); + +void nicRxUninitialize(IN struct ADAPTER *prAdapter); + +void nicRxProcessRFBs(IN struct ADAPTER *prAdapter); + +void nicRxProcessMsduReport(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb); + +uint32_t nicRxSetupRFB(IN struct ADAPTER *prAdapter, IN struct SW_RFB *prRfb); + +void nicRxReturnRFB(IN struct ADAPTER *prAdapter, IN struct SW_RFB *prRfb); + +void nicProcessRxInterrupt(IN struct ADAPTER *prAdapter); + +void nicRxProcessPktWithoutReorder(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +u_int8_t nicRxCheckForwardPktResource( + IN struct ADAPTER *prAdapter, uint32_t ucTid); + +void nicRxProcessForwardPkt(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +void nicRxProcessGOBroadcastPkt(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +void nicRxFillRFB(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb); + +struct SW_RFB *nicRxDefragMPDU(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSWRfb, OUT struct QUE *prReturnedQue); + +u_int8_t nicRxIsDuplicateFrame(IN OUT struct SW_RFB *prSwRfb); + +void nicRxProcessMonitorPacket(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb); +#if CFG_SUPPORT_PERF_IND +void nicRxPerfIndProcessRXV(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint8_t ucBssIndex); +#endif + +void nicRxProcessDataPacket(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb); + +void nicRxProcessEventPacket(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb); + +void nicRxProcessMgmtPacket(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +void nicRxFillChksumStatus(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb); + +void nicRxUpdateCSUMStatistics(IN struct ADAPTER *prAdapter, + IN const enum ENUM_CSUM_RESULT aeCSUM[]); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +void nicRxQueryStatus(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuffer, OUT uint32_t *pu4Count); + +void nicRxClearStatistics(IN struct ADAPTER *prAdapter); + +void nicRxQueryStatistics(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuffer, OUT uint32_t *pu4Count); + +uint32_t nicRxWaitResponse(IN struct ADAPTER *prAdapter, + IN uint8_t ucPortIdx, OUT uint8_t *pucRspBuffer, + IN uint32_t u4MaxRespBufferLen, OUT uint32_t *pu4Length); + +void nicRxEnablePromiscuousMode(IN struct ADAPTER *prAdapter); + +void nicRxDisablePromiscuousMode(IN struct ADAPTER *prAdapter); + +uint32_t nicRxFlush(IN struct ADAPTER *prAdapter); + +uint32_t nicRxProcessActionFrame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +uint8_t nicRxGetRcpiValueFromRxv( + IN struct ADAPTER *prAdapter, + IN uint8_t ucRcpiMode, + IN struct SW_RFB *prSwRfb); + +int32_t nicRxGetLastRxRssi(struct ADAPTER *prAdapter, IN char *pcCommand, + IN int i4TotalLen, IN uint8_t ucWlanIdx); + +#endif /* _NIC_RX_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_rxd_v1.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_rxd_v1.h new file mode 100644 index 0000000000000..29e60db520666 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_rxd_v1.h @@ -0,0 +1,110 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + * + */ + + +#ifndef _NIC_RXD_V1_H +#define _NIC_RXD_V1_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 + ******************************************************************************* + */ + +uint16_t nic_rxd_v1_get_rx_byte_count( + void *prRxStatus); +uint8_t nic_rxd_v1_get_packet_type( + void *prRxStatus); +uint8_t nic_rxd_v1_get_wlan_idx( + void *prRxStatus); +uint8_t nic_rxd_v1_get_sec_mode( + void *prRxStatus); +uint8_t nic_rxd_v1_get_sw_class_error_bit( + void *prRxStatus); +uint8_t nic_rxd_v1_get_ch_num( + void *prRxStatus); +uint8_t nic_rxd_v1_get_rf_band( + void *prRxStatus); +uint8_t nic_rxd_v1_get_tcl( + void *prRxStatus); +uint8_t nic_rxd_v1_get_ofld( + void *prRxStatus); +void nic_rxd_v1_fill_rfb( + struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); +u_int8_t nic_rxd_v1_sanity_check( + struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); + +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG +void nic_rxd_v1_check_wakeup_reason( + struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); +#endif /* CFG_SUPPORT_WAKEUP_REASON_DEBUG */ + +#endif /* _NIC_RXD_V1_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_rxd_v2.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_rxd_v2.h new file mode 100644 index 0000000000000..cfd02d9f65caf --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_rxd_v2.h @@ -0,0 +1,112 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + * + */ + + +#ifndef _NIC_RXD_V2_H +#define _NIC_RXD_V2_H + +#if (CFG_SUPPORT_CONNAC2X == 1) +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ + +uint16_t nic_rxd_v2_get_rx_byte_count( + void *prRxStatus); +uint8_t nic_rxd_v2_get_packet_type( + void *prRxStatus); +uint8_t nic_rxd_v2_get_wlan_idx( + void *prRxStatus); +uint8_t nic_rxd_v2_get_sec_mode( + void *prRxStatus); +uint8_t nic_rxd_v2_get_sw_class_error_bit( + void *prRxStatus); +uint8_t nic_rxd_v2_get_ch_num( + void *prRxStatus); +uint8_t nic_rxd_v2_get_rf_band( + void *prRxStatus); +uint8_t nic_rxd_v2_get_tcl( + void *prRxStatus); +uint8_t nic_rxd_v2_get_ofld( + void *prRxStatus); +void nic_rxd_v2_fill_rfb( + struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); +u_int8_t nic_rxd_v2_sanity_check( + struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); + +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG +void nic_rxd_v2_check_wakeup_reason( + struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); +#endif /* CFG_SUPPORT_WAKEUP_REASON_DEBUG */ + +#endif /* CFG_SUPPORT_CONNAC2X == 1 */ +#endif /* _NIC_RXD_V2_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_tx.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_tx.h new file mode 100644 index 0000000000000..6e1d79987ec44 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_tx.h @@ -0,0 +1,2032 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + * + */ + + +#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 UNIFIED_MAC_TX_FORMAT 1 + +#define MAC_TX_RESERVED_FIELD 0 + +#define NIC_TX_RESOURCE_POLLING_TIMEOUT 256 +#define NIC_TX_RESOURCE_POLLING_DELAY_MSEC 5 + +#define NIC_TX_CMD_INFO_RESERVED_COUNT 4 + +/* Maximum buffer count for individual HIF TCQ */ +#define NIC_TX_PAGE_COUNT_TC0 \ + (NIC_TX_BUFF_COUNT_TC0 * nicTxGetMaxPageCntPerFrame(prAdapter)) +#define NIC_TX_PAGE_COUNT_TC1 \ + (NIC_TX_BUFF_COUNT_TC1 * nicTxGetMaxPageCntPerFrame(prAdapter)) +#define NIC_TX_PAGE_COUNT_TC2 \ + (NIC_TX_BUFF_COUNT_TC2 * nicTxGetMaxPageCntPerFrame(prAdapter)) +#define NIC_TX_PAGE_COUNT_TC3 \ + (NIC_TX_BUFF_COUNT_TC3 * nicTxGetMaxPageCntPerFrame(prAdapter)) +#define NIC_TX_PAGE_COUNT_TC4 \ + (NIC_TX_BUFF_COUNT_TC4 * nicTxGetMaxPageCntPerFrame(prAdapter)) +#define NIC_TX_PAGE_COUNT_TC5 \ + (NIC_TX_BUFF_COUNT_TC5 * nicTxGetMaxPageCntPerFrame(prAdapter)) + +#define NIC_TX_BUFF_COUNT_TC0 HIF_TX_BUFF_COUNT_TC0 +#define NIC_TX_BUFF_COUNT_TC1 HIF_TX_BUFF_COUNT_TC1 +#define NIC_TX_BUFF_COUNT_TC2 HIF_TX_BUFF_COUNT_TC2 +#define NIC_TX_BUFF_COUNT_TC3 HIF_TX_BUFF_COUNT_TC3 +#define NIC_TX_BUFF_COUNT_TC4 HIF_TX_BUFF_COUNT_TC4 +#define NIC_TX_BUFF_COUNT_TC5 HIF_TX_BUFF_COUNT_TC5 + +#define NIC_TX_RESOURCE_CTRL \ + HIF_TX_RESOURCE_CTRL /* to enable/disable TX resource control */ +#define NIC_TX_RESOURCE_CTRL_PLE \ + HIF_TX_RESOURCE_CTRL_PLE /* to enable/disable TX resource control */ + + +#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 8 +#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) + +#define NIC_TX_INIT_PAGE_COUNT_TC0 \ + (NIC_TX_INIT_BUFF_COUNT_TC0 * nicTxGetMaxPageCntPerFrame(prAdapter)) +#define NIC_TX_INIT_PAGE_COUNT_TC1 \ + (NIC_TX_INIT_BUFF_COUNT_TC1 * nicTxGetMaxPageCntPerFrame(prAdapter)) +#define NIC_TX_INIT_PAGE_COUNT_TC2 \ + (NIC_TX_INIT_BUFF_COUNT_TC2 * nicTxGetMaxPageCntPerFrame(prAdapter)) +#define NIC_TX_INIT_PAGE_COUNT_TC3 \ + (NIC_TX_INIT_BUFF_COUNT_TC3 * nicTxGetMaxPageCntPerFrame(prAdapter)) +#define NIC_TX_INIT_PAGE_COUNT_TC4 \ + (NIC_TX_INIT_BUFF_COUNT_TC4 * nicTxGetMaxPageCntPerFrame(prAdapter)) +#define NIC_TX_INIT_PAGE_COUNT_TC5 \ + (NIC_TX_INIT_BUFF_COUNT_TC5 * nicTxGetMaxPageCntPerFrame(prAdapter)) + +#endif + +/* 4 TODO: The following values shall be got from FW by query CMD */ +/*------------------------------------------------------------------------*/ +/* Resource Management related information */ +/*------------------------------------------------------------------------*/ +#define NIC_TX_PAGE_SIZE_IS_POWER_OF_2 TRUE +#define NIC_TX_PAGE_SIZE_IN_POWER_OF_2 HIF_TX_PAGE_SIZE_IN_POWER_OF_2 +#define NIC_TX_PAGE_SIZE HIF_TX_PAGE_SIZE + +/* For development only */ +/* calculated by MS native 802.11 format */ +#define NIC_TX_MAX_SIZE_PER_FRAME 1532 +#define NIC_TX_MAX_PAGE_PER_FRAME \ + ((NIC_TX_DESC_AND_PADDING_LENGTH + NIC_TX_DESC_HEADER_PADDING_LENGTH + \ + NIC_TX_MAX_SIZE_PER_FRAME + NIC_TX_PAGE_SIZE - 1) / NIC_TX_PAGE_SIZE) + +#define NIX_TX_PLE_PAGE_CNT_PER_FRAME 1 +#define NIC_TX_LEN_ADDING_LENGTH 8 /*0x8206_C000[15:8] x 4.*/ + +/*------------------------------------------------------------------------*/ +/* Tx descriptor related information */ +/*------------------------------------------------------------------------*/ + +/* Frame Buffer + * |<--Tx Descriptor-->|<--Tx descriptor padding-->| + * <--802.3/802.11 Header-->|<--Header padding-->|<--Payload-->| + */ + +/* Tx descriptor length by format (TXD.FT) */ +/* in unit of double word */ +#define NIC_TX_DESC_LONG_FORMAT_LENGTH_DW 8 +#define NIC_TX_DESC_LONG_FORMAT_LENGTH \ + DWORD_TO_BYTE(NIC_TX_DESC_LONG_FORMAT_LENGTH_DW) +/* in unit of double word */ +#define NIC_TX_DESC_SHORT_FORMAT_LENGTH_DW 3 +#define NIC_TX_DESC_SHORT_FORMAT_LENGTH \ + DWORD_TO_BYTE(NIC_TX_DESC_SHORT_FORMAT_LENGTH_DW) + +/* Tx descriptor padding length (DMA.MICR.TXDSCR_PAD) */ +#define NIC_TX_DESC_PADDING_LENGTH_DW 0 /* in unit of double word */ +#define NIC_TX_DESC_PADDING_LENGTH \ + DWORD_TO_BYTE(NIC_TX_DESC_PADDING_LENGTH_DW) + +#define NIC_TX_DESC_AND_PADDING_LENGTH \ + (NIC_TX_DESC_LONG_FORMAT_LENGTH + NIC_TX_DESC_PADDING_LENGTH) + +/* Tx header padding (TXD.HeaderPadding) */ +/* Warning!! To use MAC header padding, every Tx packet must be decomposed */ +#define NIC_TX_DESC_HEADER_PADDING_LENGTH 0 /* in unit of bytes */ + +#define NIC_TX_DESC_PID_RESERVED 0 +#define NIC_TX_DESC_DRIVER_PID_MIN 1 +#define NIC_TX_DESC_DRIVER_PID_MAX 127 + +#define NIC_TX_DATA_DEFAULT_RETRY_COUNT_LIMIT 30 +#define NIC_TX_MGMT_DEFAULT_RETRY_COUNT_LIMIT 30 + +/* in unit of ms */ +#define NIC_TX_AC_BE_REMAINING_TX_TIME TX_DESC_TX_TIME_NO_LIMIT +#define NIC_TX_AC_BK_REMAINING_TX_TIME TX_DESC_TX_TIME_NO_LIMIT +#define NIC_TX_AC_VO_REMAINING_TX_TIME TX_DESC_TX_TIME_NO_LIMIT +#define NIC_TX_AC_VI_REMAINING_TX_TIME TX_DESC_TX_TIME_NO_LIMIT +#define NIC_TX_MGMT_REMAINING_TX_TIME 2000 + +#define NIC_TX_CRITICAL_DATA_TID 7 +/*802.1d Voice Traffic,use AC_VO */ +#define NIC_TX_PRIORITY_DATA_TID 6 + +/*Customization: sk_buff mark for special packet that need raise priority */ +#define NIC_TX_SKB_PRIORITY_MARK1 0x5a /* customer special value*/ +#define NIC_TX_SKB_PRIORITY_MARK_BIT 31 /*Mediatek define, 0x80000000*/ +#define NIC_TX_SKB_DUP_DETECT_MARK_BIT 30 /*Mediatek define, 0x40000000*/ + +#define HW_MAC_TX_DESC_APPEND_T_LENGTH 44 +#define NIC_TX_HEAD_ROOM \ + (NIC_TX_DESC_LONG_FORMAT_LENGTH + NIC_TX_DESC_PADDING_LENGTH \ + + HW_MAC_TX_DESC_APPEND_T_LENGTH) + +#define NIC_MSDU_REPORT_DUMP_TIMEOUT 5 /* sec */ + +/*------------------------------------------------------------------------*/ +/* Tx status related information */ +/*------------------------------------------------------------------------*/ + +/* Tx status header & content length */ +#define NIC_TX_STATUS_HEADER_LENGTH_DW \ + 1 /* in unit of double word */ +#define NIC_TX_STATUS_HEADER_LENGTH \ + DWORD_TO_BYTE(NIC_TX_STATUS_HEADER_LENGTH_DW) +#define NIC_TX_STATUS_LENGTH_DW \ + 7 /* in unit of double word */ +#define NIC_TX_STATUS_LENGTH \ + DWORD_TO_BYTE(NIC_TX_STATUS_LENGTH_DW) + +/*------------------------------------------------------------------------*/ +/* Tx descriptor field related information */ +/*------------------------------------------------------------------------*/ +/* DW 0 */ +#define TX_DESC_TX_BYTE_COUNT_MASK BITS(0, 15) +#define TX_DESC_TX_BYTE_COUNT_OFFSET 0 + +#define TX_DESC_ETHER_TYPE_OFFSET_MASK BITS(0, 6) +#define TX_DESC_ETHER_TYPE_OFFSET_OFFSET 0 +#define TX_DESC_IP_CHKSUM_OFFLOAD BIT(7) +#define TX_DESC_TCP_UDP_CHKSUM_OFFLOAD BIT(0) +#define TX_DESC_QUEUE_INDEX_MASK BITS(2, 6) +#define TX_DESC_QUEUE_INDEX_OFFSET 2 +#define TX_DESC_PORT_INDEX BIT(7) +#define TX_DESC_PORT_INDEX_OFFSET 7 + +#define PORT_INDEX_LMAC 0 +#define PORT_INDEX_MCU 1 + +/* DW 1 */ +#define TX_DESC_WLAN_INDEX_MASK BITS(0, 7) +#define TX_DESC_WLAN_INDEX_OFFSET 0 +#define TX_DESC_HEADER_FORMAT_MASK BITS(5, 6) +#define TX_DESC_HEADER_FORMAT_OFFSET 5 + +#define HEADER_FORMAT_NON_802_11 0 /* Non-802.11 */ +#define HEADER_FORMAT_COMMAND 1 /* Command */ +#define HEADER_FORMAT_802_11_NORMAL_MODE \ + 2 /* 802.11 (normal mode) */ +#define HEADER_FORMAT_802_11_ENHANCE_MODE \ + 3 /* 802.11 (Enhancement mode) */ +#define HEADER_FORMAT_802_11_MASK BIT(1) + +#define TX_DESC_NON_802_11_MORE_DATA BIT(0) +#define TX_DESC_NON_802_11_EOSP BIT(1) +#define TX_DESC_NON_802_11_REMOVE_VLAN BIT(2) +#define TX_DESC_NON_802_11_VLAN_FIELD BIT(3) +#define TX_DESC_NON_802_11_ETHERNET_II BIT(4) +#define TX_DESC_NOR_802_11_HEADER_LENGTH_MASK BITS(0, 4) +#define TX_DESC_NOR_802_11_HEADER_LENGTH_OFFSET 0 +#define TX_DESC_ENH_802_11_EOSP BIT(1) +#define TX_DESC_ENH_802_11_AMSDU BIT(2) + +#define TX_DESC_FORMAT BIT(7) +#define TX_DESC_SHORT_FORMAT 0 +#define TX_DESC_LONG_FORMAT 1 + +#define TX_DESC_TXD_LENGTH_MASK BIT(0) +#define TX_DESC_TXD_LENGTH_OFFSET 0 + +#define TX_DESC_HEADER_PADDING_LENGTH_MASK BIT(1) +#define TX_DESC_HEADER_PADDING_LENGTH_OFFSET 1 +#define TX_DESC_HEADER_PADDING_MODE BIT(2) + +#define TX_DESC_TXD_EXTEND_LENGTH_MASK BIT(3) +#define TX_DESC_TXD_EXTEND_LENGTH_OFFSET 3 + +#define TX_DESC_TXD_UTXB_AMSDU_MASK BIT(4) +#define TX_DESC_TXD_UTXB_AMSDU_OFFSET 4 + +#define TX_DESC_TID_MASK BITS(5, 7) +#define TX_DESC_TID_OFFSET 5 +#define TX_DESC_TID_NUM 8 + +#define TX_DESC_PACKET_FORMAT_MASK BITS(0, 1) /* SW Field */ +#define TX_DESC_PACKET_FORMAT_OFFSET 0 +#define TX_DESC_OWN_MAC_MASK BITS(2, 7) +#define TX_DESC_OWN_MAC_OFFSET 2 + +/* DW 2 */ +#define TX_DESC_SUB_TYPE_MASK BITS(0, 3) +#define TX_DESC_SUB_TYPE_OFFSET 0 +#define TX_DESC_TYPE_MASK BITS(4, 5) +#define TX_DESC_TYPE_OFFSET 4 +#define TX_DESC_NDP BIT(6) +#define TX_DESC_NDPA BIT(7) + +#define TX_DESC_SOUNDING BIT(0) +#define TX_DESC_FORCE_RTS_CTS BIT(1) +#define TX_DESC_BROADCAST_MULTICAST BIT(2) +#define TX_DESC_BIP_PROTECTED BIT(3) +#define TX_DESC_DURATION_FIELD_CONTROL BIT(4) +#define TX_DESC_HTC_EXISTS BIT(5) +#define TX_DESC_FRAGMENT_MASK BITS(6, 7) +#define TX_DESC_FRAGMENT_OFFSET 6 +#define FRAGMENT_FISRT_PACKET 1 +#define FRAGMENT_MIDDLE_PACKET 2 +#define FRAGMENT_LAST_PACKET 3 + +#define TX_DESC_REMAINING_MAX_TX_TIME BITS(0, 7) +#define TX_DESC_TX_TIME_NO_LIMIT 0 +/* Unit of life time calculation of Tx descriptor */ +#define TX_DESC_LIFE_TIME_UNIT_IN_POWER_OF_2 5 +#define TX_DESC_LIFE_TIME_UNIT \ + POWER_OF_2(TX_DESC_LIFE_TIME_UNIT_IN_POWER_OF_2) +#define TX_DESC_POWER_OFFSET_MASK BITS(0, 4) +#define TX_DESC_BA_DISABLE BIT(5) +#define TX_DESC_TIMING_MEASUREMENT BIT(6) +#define TX_DESC_FIXED_RATE BIT(7) + +/* DW 3 */ +#define TX_DESC_NO_ACK BIT(0) +#define TX_DESC_PROTECTED_FRAME BIT(1) +#define TX_DESC_EXTEND_MORE_DATA BIT(2) +#define TX_DESC_EXTEND_EOSP BIT(3) + +#define TX_DESC_SW_RESERVED_MASK BITS(4, 5) +#define TX_DESC_SW_RESERVED_OFFSET 4 + +#define TX_DESC_TX_COUNT_MASK BITS(6, 10) +#define TX_DESC_TX_COUNT_OFFSET 6 +#define TX_DESC_TX_COUNT_NO_ATTEMPT 0 +#define TX_DESC_TX_COUNT_NO_LIMIT 31 +#define TX_DESC_REMAINING_TX_COUNT_MASK BITS(11, 15) +#define TX_DESC_REMAINING_TX_COUNT_OFFSET 11 +#define TX_DESC_SEQUENCE_NUMBER BITS(0, 11) +#define TX_DESC_HW_RESERVED_MASK BITS(12, 13) +#define TX_DESC_HW_RESERVED_OFFSET 12 +#define TX_DESC_PN_IS_VALID BIT(14) +#define TX_DESC_SN_IS_VALID BIT(15) + +/* DW 4 */ +#define TX_DESC_PN_PART1 BITS(0, 31) + +/* DW 5 */ +#define TX_DESC_PACKET_ID BIT(0, 7) +#define TX_DESC_TX_STATUS_FORMAT BIT(0) +#define TX_DESC_TX_STATUS_FORMAT_OFFSET 0 +#define TX_DESC_TX_STATUS_TO_MCU BIT(1) +#define TX_DESC_TX_STATUS_TO_HOST BIT(2) +#define TX_DESC_DA_SOURCE BIT(3) +#define TX_DESC_POWER_MANAGEMENT_CONTROL BIT(5) +#define TX_DESC_PN_PART2 BITS(0, 15) + +/* DW 6 *//* FR = 1 */ +#define TX_DESC_BANDWIDTH_MASK BITS(0, 2) +#define TX_DESC_BANDWIDTH_OFFSET 0 +#define TX_DESC_DYNAMIC_BANDWIDTH BIT(3) +#define TX_DESC_ANTENNA_INDEX_MASK BITS(4, 15) +#define TX_DESC_ANTENNA_INDEX_OFFSET 4 + +#define TX_DESC_FIXDE_RATE_MASK BITS(0, 11) +#define TX_DESC_FIXDE_RATE_OFFSET 0 +#define TX_DESC_TX_RATE BITS(0, 5) +#define TX_DESC_TX_RATE_OFFSET 0 +#define TX_DESC_TX_MODE BITS(6, 8) +#define TX_DESC_TX_MODE_OFFSET 6 +#define TX_DESC_NSTS_MASK BITS(9, 10) +#define TX_DESC_NSTS_OFFSET 9 +#define TX_DESC_STBC BIT(11) +#define TX_DESC_BF BIT(12) +#define TX_DESC_LDPC BIT(13) +#define TX_DESC_GUARD_INTERVAL BIT(14) +#define TX_DESC_FIXED_RATE_MODE BIT(15) + +/* DW 7 */ +#define TX_DESC_SPE_EXT_IDX_SEL_MASK BIT(10) +#define TX_DESC_SPE_EXT_IDX_SEL_OFFSET 10 +#define TX_DESC_SPE_EXT_IDX_MASK BITS(11, 15) +#define TX_DESC_SPE_EXT_IDX_OFFSET 11 +#define TX_DESC_PSE_FID_MASK BITS(0, 13) +#define TX_DESC_PSE_FID_OFFSET 0 +#define TX_DESC_HW_AMSDU BIT(14) +#define TX_DESC_HIF_ERR BIT(15) + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE +#define NIC_TX_TIME_THRESHOLD 100 /* in unit of ms */ +#endif + +#define NIC_TX_INIT_CMD_PORT HIF_TX_INIT_CMD_PORT + +#define NIC_TX_REMAINING_LIFE_TIME 2000 /* in unit of ms */ + +/******************************************************************************* + * 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. + */ +/* TXD_PKT_FORMAT options*/ +enum ENUM_TXD_PKT_FORMAT_OPTION { + TXD_PKT_FORMAT_TXD = 0, /* TXD only */ + TXD_PKT_FORMAT_TXD_PAYLOAD, /* TXD and paload */ + TXD_PKT_FORMAT_COMMAND, /* Command */ + TXD_PKT_FORMAT_FWDL, /* Firmware download */ + TXD_PKT_FORMAT_NUM, +}; + +/* HIF Tx interrupt status queue index*/ +enum ENUM_HIF_TX_INDEX { + HIF_TX_AC0_INDEX = 0, + HIF_TX_AC1_INDEX, + HIF_TX_AC2_INDEX, + HIF_TX_AC3_INDEX, + + HIF_TX_AC10_INDEX, + HIF_TX_AC11_INDEX, + HIF_TX_AC12_INDEX, + HIF_TX_AC13_INDEX, + + HIF_TX_AC20_INDEX, + HIF_TX_AC21_INDEX, + HIF_TX_AC22_INDEX, + HIF_TX_AC23_INDEX, + + HIF_TX_RSV0_INDEX, + HIF_TX_RSV1_INDEX, + HIF_TX_FFA_INDEX, + HIF_TX_CPU_INDEX, + + HIF_TX_NUM +}; + +/* LMAC Tx queue index */ +enum ENUM_MAC_TXQ_INDEX { + MAC_TXQ_AC0_INDEX = 0, + MAC_TXQ_AC1_INDEX, + MAC_TXQ_AC2_INDEX, + MAC_TXQ_AC3_INDEX, + + MAC_TXQ_AC10_INDEX, + MAC_TXQ_AC11_INDEX, + MAC_TXQ_AC12_INDEX, + MAC_TXQ_AC13_INDEX, + + MAC_TXQ_AC20_INDEX, + MAC_TXQ_AC21_INDEX, + MAC_TXQ_AC22_INDEX, + MAC_TXQ_AC23_INDEX, + + MAC_TXQ_AC30_INDEX, + MAC_TXQ_AC31_INDEX, + MAC_TXQ_AC32_INDEX, + MAC_TXQ_AC33_INDEX, + + MAC_TXQ_ALTX_0_INDEX, + MAC_TXQ_BMC_0_INDEX, + MAC_TXQ_BCN_0_INDEX, + MAC_TXQ_PSMP_0_INDEX, + + MAC_TXQ_ALTX_1_INDEX, + MAC_TXQ_BMC_1_INDEX, + MAC_TXQ_BCN_1_INDEX, + MAC_TXQ_PSMP_1_INDEX, + + MAC_TXQ_NAF_INDEX, + MAC_TXQ_NBCN_INDEX, + + MAC_TXQ_NUM +}; + +/* MCU quque index */ +enum ENUM_MCU_Q_INDEX { + MCU_Q0_INDEX = 0, + MCU_Q1_INDEX, + MCU_Q2_INDEX, + MCU_Q3_INDEX, + MCU_Q_NUM +}; + +#define TX_PORT_NUM (TC_NUM) + +#define BMC_TC_INDEX TC1_INDEX + +/* per-Network Tc Resource index */ +enum ENUM_NETWORK_TC_RESOURCE_INDEX { + /* QoS Data frame, WMM AC index */ + NET_TC_WMM_AC_BE_INDEX = 0, + NET_TC_WMM_AC_BK_INDEX, + NET_TC_WMM_AC_VI_INDEX, + NET_TC_WMM_AC_VO_INDEX, + /* Mgmt frame */ + NET_TC_MGMT_INDEX, + /* nonQoS / non StaRec frame (BMC/non-associated frame) */ + NET_TC_BMC_INDEX, + + NET_TC_NUM +}; + +enum ENUM_TX_STATISTIC_COUNTER { + 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 ENUM_FIX_BW { + FIX_BW_NO_FIXED = 0, + FIX_BW_20 = 4, + FIX_BW_40, + FIX_BW_80, + FIX_BW_160, + FIX_BW_NUM +}; + +enum ENUM_MSDU_OPTION { + MSDU_OPT_NO_ACK = BIT(0), + MSDU_OPT_NO_AGGREGATE = BIT(1), + MSDU_OPT_TIMING_MEASURE = BIT(2), + MSDU_OPT_RCPI_NOISE_STATUS = BIT(3), + + /* Option by Frame Format */ + /* Non-80211 */ + MSDU_OPT_MORE_DATA = BIT(4), + MSDU_OPT_REMOVE_VLAN = BIT(5), /* Remove VLAN tag if exists */ + + /* 80211-enhanced */ + MSDU_OPT_AMSDU = BIT(6), + + /* 80211-enhanced & Non-80211 */ + MSDU_OPT_EOSP = BIT(7), + + /* Beamform */ + MSDU_OPT_NDP = BIT(8), + MSDU_OPT_NDPA = BIT(9), + MSDU_OPT_SOUNDING = BIT(10), + + /* Protection */ + MSDU_OPT_FORCE_RTS = BIT(11), + + /* Security */ + MSDU_OPT_BIP = BIT(12), + MSDU_OPT_PROTECTED_FRAME = BIT(13), + + /* SW Field */ + MSDU_OPT_SW_DURATION = BIT(14), + MSDU_OPT_SW_PS_BIT = BIT(15), + MSDU_OPT_SW_HTC = BIT(16), + MSDU_OPT_SW_BAR_SN = BIT(17), + + /* Manual Mode */ + MSDU_OPT_MANUAL_FIRST_BIT = BIT(18), + + MSDU_OPT_MANUAL_LIFE_TIME = MSDU_OPT_MANUAL_FIRST_BIT, + MSDU_OPT_MANUAL_RETRY_LIMIT = BIT(19), + MSDU_OPT_MANUAL_POWER_OFFSET = BIT(20), + MSDU_OPT_MANUAL_TX_QUE = BIT(21), + MSDU_OPT_MANUAL_SN = BIT(22), + + MSDU_OPT_MANUAL_LAST_BIT = MSDU_OPT_MANUAL_SN +}; + +enum ENUM_MSDU_CONTROL_FLAG { + MSDU_CONTROL_FLAG_FORCE_TX = BIT(0) +}; + +enum ENUM_MSDU_RATE_MODE { + MSDU_RATE_MODE_AUTO = 0, + MSDU_RATE_MODE_MANUAL_DESC, + /* The following rate mode is not implemented yet */ + /* DON'T use!!! */ + MSDU_RATE_MODE_MANUAL_CR, + MSDU_RATE_MODE_LOWEST_RATE +}; + +enum ENUM_DATA_RATE_MODE { + DATA_RATE_MODE_AUTO = 0, + DATA_RATE_MODE_MANUAL, + DATA_RATE_MODE_BSS_LOWEST +}; + +struct TX_TCQ_STATUS { + /* HIF reported page count delta */ + uint32_t au4TxDonePageCount[TC_NUM]; /* other TC */ + uint32_t au4PreUsedPageCount[TC_NUM]; + uint32_t u4AvaliablePageCount; /* FFA */ + uint8_t ucNextTcIdx; /* For round-robin distribute free page count */ + + /* distributed page count */ + uint32_t au4FreePageCount[TC_NUM]; + uint32_t au4MaxNumOfPage[TC_NUM]; + + /* buffer count */ + uint32_t au4FreeBufferCount[TC_NUM]; + uint32_t au4MaxNumOfBuffer[TC_NUM]; + + /* + * PLE part + */ + + u_int8_t fgNeedPleCtrl; + + /* HIF reported page count delta */ + uint32_t au4TxDonePageCount_PLE[TC_NUM]; /* other TC */ + uint32_t au4PreUsedPageCoun_PLE[TC_NUM]; + uint32_t u4AvaliablePageCount_PLE; /* FFA */ + + /* distributed page count */ + uint32_t au4FreePageCount_PLE[TC_NUM]; + uint32_t au4MaxNumOfPage_PLE[TC_NUM]; + + /* buffer count */ + uint32_t au4FreeBufferCount_PLE[TC_NUM]; + uint32_t au4MaxNumOfBuffer_PLE[TC_NUM]; +}; + +struct TX_TCQ_ADJUST { + int32_t ai4Variation[TC_NUM]; +}; + +struct TX_CTRL { + uint32_t u4TxCachedSize; + uint8_t *pucTxCached; + + uint32_t u4PageSize; + + uint32_t u4TotalPageNum; + + uint32_t u4TotalPageNumPle; + uint32_t u4TotalTxRsvPageNum; + +/* Elements below is classified according to TC (Traffic Class) value. */ + + struct TX_TCQ_STATUS rTc; + + uint8_t *pucTxCoalescingBufPtr; + + uint32_t u4WrIdx; + + struct QUE rFreeMsduInfoList; + + /* Management Frame Tracking */ + /* number of management frames to be sent */ + int32_t i4TxMgmtPendingNum; + + /* to tracking management frames need TX done callback */ + struct QUE rTxMgmtTxingQueue; + +#if CFG_HIF_STATISTICS + uint32_t u4TotalTxAccessNum; + uint32_t u4TotalTxPacketNum; +#endif + uint32_t au4Statistics[TX_STATISTIC_COUNTER_NUM]; + + /* Number to track forwarding frames */ + int32_t i4PendingFwdFrameCount; + /* Number to track forwarding frames for WMM resource control */ + int32_t i4PendingFwdFrameWMMCount[TC_NUM]; + + /* enable/disable TX resource control */ + u_int8_t fgIsTxResourceCtrl; + /* page counts for a wifi frame */ + uint32_t u4MaxPageCntPerFrame; + + /* Store SysTime of Last TxDone successfully */ + uint32_t u4LastTxTime[MAX_BSSID_NUM]; +}; + +enum ENUM_TX_PACKET_TYPE { + TX_PACKET_TYPE_DATA = 0, + TX_PACKET_TYPE_MGMT, + /* TX_PACKET_TYPE_1X, */ + X_PACKET_TYPE_NUM +}; + +enum ENUM_TX_PACKET_SRC { + TX_PACKET_OS, + TX_PACKET_OS_OID, + TX_PACKET_FORWARDING, + TX_PACKET_MGMT, + TX_PACKET_NUM +}; + +/* TX Call Back Function */ +typedef uint32_t(*PFN_TX_DONE_HANDLER) (IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +typedef void(*PFN_HIF_TX_MSDU_DONE_CB) (IN struct ADAPTER + *prAdapter, IN struct MSDU_INFO *prMsduInfo); + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE +struct PKT_PROFILE { + u_int8_t fgIsValid; +#if CFG_PRINT_PKT_LIFETIME_PROFILE + u_int8_t fgIsPrinted; + uint16_t u2IpSn; + uint16_t u2RtpSn; + uint8_t ucTcxFreeCount; +#endif + OS_SYSTIME rHardXmitArrivalTimestamp; + OS_SYSTIME rEnqueueTimestamp; + OS_SYSTIME rDequeueTimestamp; + OS_SYSTIME rHifTxDoneTimestamp; +}; +#endif + +enum ENUM_EAPOL_KEY_TYPE_T { + EAPOL_KEY_NOT_KEY = 0, + EAPOL_KEY_1_OF_4, + EAPOL_KEY_2_OF_4, + EAPOL_KEY_3_OF_4, + EAPOL_KEY_4_OF_4, + EAPOL_KEY_NUM +}; + +/* 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 { + struct QUE_ENTRY rQueEntry; + void *prPacket; /* Pointer to packet buffer */ + + enum ENUM_TX_PACKET_SRC eSrc; /* specify OS/FORWARD packet */ + uint8_t ucUserPriority; /* QoS parameter, convert to TID */ + + /* For composing TX descriptor header */ + uint8_t ucTC; /* Traffic Class: 0~4 (HIF TX0), 5 (HIF TX1) */ + uint8_t ucPacketType; /* 0: Data, 1: Management Frame */ + uint8_t ucStaRecIndex; /* STA_REC index */ + uint8_t ucBssIndex; /* BSS_INFO_T index */ + uint8_t ucWlanIndex; /* Wlan entry index */ + uint8_t ucPacketFormat; /* TXD.DW1[25:24] Packet Format */ + + u_int8_t fgIs802_1x; /* TRUE: 802.1x frame */ + /* TRUE: 802.1x frame - Non-Protected */ + u_int8_t fgIs802_1x_NonProtected; + u_int8_t fgIs802_11; /* TRUE: 802.11 header is present */ + u_int8_t fgIs802_3; /* TRUE: 802.3 frame */ + u_int8_t fgIsVlanExists; /* TRUE: VLAN tag is exists */ + + /* Special Option */ + uint32_t u4Option; /* Special option in bitmask, no ACK, etc... */ + int8_t cPowerOffset; /* Per-packet power offset, in 2's complement */ + uint16_t u2SwSN; /* SW assigned sequence number */ + uint8_t ucRetryLimit; /* The retry limit */ + uint32_t u4RemainingLifetime; /* Remaining lifetime, unit:ms */ + + /* Control flag */ + uint8_t ucControlFlag; /* Control flag in bitmask */ + + /* Fixed Rate Option */ + uint8_t ucRateMode; /* Rate mode: AUTO, MANUAL_DESC, MANUAL_CR */ + /* The rate option, rate code, GI, etc... */ + uint32_t u4FixedRateOption; + + /* There is a valid Tx descriptor for this packet */ + u_int8_t fgIsTXDTemplateValid; + + /* flattened from PACKET_INFO_T */ + uint8_t ucMacHeaderLength; /* MAC header legth */ + uint8_t ucLlcLength; /* w/o EtherType */ + uint16_t u2FrameLength; /* Total frame length */ + /* Ethernet Destination Address */ + uint8_t aucEthDestAddr[MAC_ADDR_LEN]; + uint32_t u4PageCount; /* Required page count for this MSDU */ + + /* for TX done tracking */ + uint8_t ucTxSeqNum; /* MGMT frame serial number */ + uint8_t ucPID; /* PID */ + uint8_t ucWmmQueSet; /* WMM Set */ + PFN_TX_DONE_HANDLER pfTxDoneHandler; /* Tx done handler */ + PFN_HIF_TX_MSDU_DONE_CB pfHifTxMsduDoneCb; + uint32_t u4TxDoneTag; /* Tag for data frame Tx done log */ + uint8_t ucPktType; + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + struct PKT_PROFILE rPktProfile; +#endif + + /* To be removed */ + uint8_t ucFormatID; /* 0: MAUI, Linux, Windows NDIS 5.1 */ + /* UINT_16 u2PalLLH; */ /* PAL Logical Link Header (for BOW network) */ + /* UINT_16 u2AclSN; */ /* ACL Sequence Number (for BOW network) */ + uint8_t ucPsForwardingType; /* See ENUM_PS_FORWARDING_TYPE_T */ + /* PS Session ID specified by the FW for the STA */ + /* UINT_8 ucPsSessionID; */ + /* TRUE means this is the last packet of the burst for (STA, TID) */ + /* BOOLEAN fgIsBurstEnd; */ +#if CFG_M0VE_BA_TO_DRIVER + uint8_t ucTID; +#endif + +#if CFG_SUPPORT_MULTITHREAD + /* Compose TxDesc in main_thread and place here */ + uint8_t aucTxDescBuffer[NIC_TX_DESC_AND_PADDING_LENGTH]; +#endif + +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + struct MSDU_TOKEN_ENTRY *prToken; + struct TX_DATA_REQ rTxReq; +#endif + enum ENUM_EAPOL_KEY_TYPE_T eEapolKeyType; +#if (CFG_SUPPORT_DMASHDL_SYSDVT) + uint8_t ucTarQueue; +#endif + uint8_t fgMgmtUseDataQ; +}; + +#define HIF_PKT_FLAGS_CT_INFO_APPLY_TXD BIT(0) +#define HIF_PKT_FLAGS_COPY_HOST_TXD_ALL BIT(1) +#define HIF_PKT_FLAGS_CT_INFO_MGN_FRAME BIT(2) +#define HIF_PKT_FLAGS_CT_INFO_NONE_CIPHER_FRAME BIT(3) +#define HIF_PKT_FLAGS_CT_INFO_HSR2_TX BIT(4) + +#define MAX_BUF_NUM_PER_PKT 6 + +#define NUM_OF_MSDU_ID_IN_TXD 4 +#define TXD_MAX_BUF_NUM 4 +#define TXD_MSDU_ID_VLD BIT(15) /* MSDU valid */ +#define TXD_LEN_AL BIT(15) /* A-MSDU last */ +#define TXD_LEN_ML BIT(14) /* MSDU last */ +#define TXD_LEN_ML_V2 BIT(15) /* MSDU last */ +#define TXD_LEN_MASK_V2 BITS(0, 11) +#define TXD_ADDR2_MASK BITS(12, 14) +#define TXD_ADDR2_OFFSET 20 + + +struct TXD_PTR_LEN { + uint32_t u4Ptr0; + uint16_t u2Len0; /* Bit15: AL, Bit14: ML */ + uint16_t u2Len1; /* Bit15: AL, Bit14: ML */ + uint32_t u4Ptr1; +}; + +union HW_MAC_TX_DESC_APPEND { + struct { + uint16_t u2PktFlags; + uint16_t u2MsduToken; + uint8_t ucBssIndex; + uint8_t ucWtblIndex; + uint8_t aucReserved[1]; + uint8_t ucBufNum; + uint32_t au4BufPtr[MAX_BUF_NUM_PER_PKT]; + uint16_t au2BufLen[MAX_BUF_NUM_PER_PKT]; + } CR4_APPEND; + + struct { + /* Bit15 indicate valid */ + uint16_t au2MsduId[NUM_OF_MSDU_ID_IN_TXD]; + struct TXD_PTR_LEN arPtrLen[TXD_MAX_BUF_NUM / 2]; + } CONNAC_APPEND; +}; + +/*!A data structure which is identical with HW MAC TX DMA Descriptor */ +struct HW_MAC_TX_DESC { + /* DW 0 */ + uint16_t u2TxByteCount; + uint8_t ucEtherOffset; /* Ether-Type Offset, IP checksum offload */ + /* UDP/TCP checksum offload, + * USB NextVLD/TxBURST, Queue index, Port index + */ + uint8_t ucPortIdx_QueueIdx; + /* DW 1 */ + uint8_t ucWlanIdx; + /* Header format, TX descriptor format */ + uint8_t ucHeaderFormat; + /* Header padding, no ACK, TID, Protect frame */ + uint8_t ucHeaderPadding; + uint8_t ucOwnMAC; + + /* Long Format, the following structure is for long format ONLY */ + /* DW 2 */ + uint8_t ucType_SubType; /* Type, Sub-type, NDP, NDPA */ + /* Sounding, force RTS/CTS, BMC, BIP, Duration, HTC exist, Fragment */ + uint8_t ucFrag; + uint8_t ucRemainingMaxTxTime; + /* Power offset, Disable BA, Timing measurement, Fixed rate */ + uint8_t ucPowerOffset; + /* DW 3 */ + uint16_t u2TxCountLimit; /* TX count limit */ + uint16_t u2SN; /* SN, HW own, PN valid, SN valid */ + /* DW 4 */ + uint32_t u4PN1; + /* DW 5 */ + uint8_t ucPID; + /* TXS format, TXS to mcu, + * TXS to host, DA source, BAR SSN, Power management + */ + uint8_t ucTxStatus; + uint16_t u2PN2; + /* DW 6 */ + uint16_t u2AntID; /* Fixed rate, Antenna ID */ + /* Explicit/implicit beamforming, Fixed rate table, LDPC, GI */ + uint16_t u2FixedRate; + /* DW 7 */ + uint16_t u2SwTxTime; /* Sw Tx time[9:0], SPE_IDX[15:11] */ + uint16_t u2PseFid; /* indicate frame ID in PSE for this TXD */ +}; + +struct TX_RESOURCE_CONTROL { + /* HW TX queue definition */ + uint8_t ucDestPortIndex; + uint8_t ucDestQueueIndex; + /* HIF Interrupt status index */ + uint8_t ucHifTxQIndex; +}; + +struct TX_TC_TRAFFIC_SETTING { + uint32_t u4TxDescLength; + uint32_t u4RemainingTxTime; + uint8_t ucTxCountLimit; +}; + +typedef void (*PFN_TX_DATA_DONE_CB) (IN struct GLUE_INFO *prGlueInfo, + IN struct QUE *prQue); + +struct tx_resource_info { + /* PSE */ + /* the total usable resource for MCU port */ + uint32_t u4CmdTotalResource; + /* the unit of a MCU resource */ + uint32_t u4CmdResourceUnit; + /* the total usable resource for LMAC port */ + uint32_t u4DataTotalResource; + /* the unit of a LMAC resource */ + uint32_t u4DataResourceUnit; + + /* PLE */ + /* the total usable resource for MCU port */ + uint32_t u4CmdTotalResourcePle; + /* the unit of a MCU resource */ + uint32_t u4CmdResourceUnitPle; + /* the total usable resource for LMAC port */ + uint32_t u4DataTotalResourcePle; + /* the unit of a LMAC resource */ + uint32_t u4DataResourceUnitPle; + + /* Packet Processor 0x8206C000[15:8] + * 4. Extra PSE resource is needed for HW. + */ + uint8_t ucPpTxAddCnt;/* in unit of byte */ + + /* update resource callback */ + void (*txResourceInit)(IN struct ADAPTER *prAdapter); +}; + +struct TX_DESC_OPS_T { + void (*fillNicAppend)(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + OUT uint8_t *prTxDescBuffer); + void (*fillHifAppend)(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN uint16_t u4MsduId, + IN dma_addr_t rDmaAddr, IN uint32_t u4Idx, IN u_int8_t fgIsLast, + OUT uint8_t *pucBuffer); + void (*fillTxByteCount)(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + void *prTxDesc); + + /* TXD Handle APIs */ + uint8_t (*nic_txd_long_format_op)( + void *prTxDesc, + uint8_t fgSet); + uint8_t (*nic_txd_tid_op)( + void *prTxDesc, + uint8_t ucTid, + uint8_t fgSet); + uint8_t (*nic_txd_queue_idx_op)( + void *prTxDesc, + uint8_t ucQueIdx, + uint8_t fgSet); +#if (CFG_TCP_IP_CHKSUM_OFFLOAD == 1) + void (*nic_txd_chksum_op)( + void *prTxDesc, + uint8_t ucChksumFlag); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD == 1 */ + void (*nic_txd_header_format_op)( + void *prTxDesc, + struct MSDU_INFO *prMsduInfo); + void (*nic_txd_fill_by_pkt_option)( + struct MSDU_INFO *prMsduInfo, + void *prTxD); + void (*nic_txd_compose)( + struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + u_int32_t u4TxDescLength, + u_int8_t fgIsTemplate, + u_int8_t *prTxDescBuffer); + void (*nic_txd_compose_security_frame)( + struct ADAPTER *prAdapter, + struct CMD_INFO *prCmdInfo, + uint8_t *prTxDescBuffer, + uint8_t *pucTxDescLength); + void (*nic_txd_set_pkt_fixed_rate_option_full)( + struct MSDU_INFO *prMsduInfo, + uint16_t u2RateCode, + uint8_t ucBandwidth, + u_int8_t fgShortGI, + u_int8_t fgLDPC, + u_int8_t fgDynamicBwRts, u_int8_t fgBeamforming, + uint8_t ucAntennaIndex); + void (*nic_txd_set_pkt_fixed_rate_option)( + struct MSDU_INFO *prMsduInfo, + uint16_t u2RateCode, + uint8_t ucBandwidth, + u_int8_t fgShortGI, + u_int8_t fgDynamicBwRts); + void (*nic_txd_set_hw_amsdu_template)( + struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t ucTid, + u_int8_t fgSet); + void (*nic_txd_change_data_port_by_ac)( + struct STA_RECORD *prStaRec, + uint8_t ucAci, + u_int8_t fgToMcu); +}; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +extern PFN_TX_DATA_DONE_CB g_pfTxDataDoneCb; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +#define TX_INC_CNT(prTxCtrl, eCounter) \ + {((struct TX_CTRL *)prTxCtrl)->au4Statistics[eCounter]++; } + +#define TX_ADD_CNT(prTxCtrl, eCounter, u8Amount) \ + {((struct TX_CTRL *)prTxCtrl)->au4Statistics[eCounter] += \ + (uint32_t)u8Amount; } + +#define TX_GET_CNT(prTxCtrl, eCounter) \ + (((struct TX_CTRL *)prTxCtrl)->au4Statistics[eCounter]) + +#define TX_RESET_ALL_CNTS(prTxCtrl) \ + {kalMemZero(&prTxCtrl->au4Statistics[0], \ + sizeof(prTxCtrl->au4Statistics)); } +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + +#if CFG_PRINT_PKT_LIFETIME_PROFILE +#define PRINT_PKT_PROFILE(_pkt_profile, _note) \ +do { \ + if (!(_pkt_profile)->fgIsPrinted) { \ + DBGLOG(TX, TRACE, \ + "X[%lu] E[%lu] D[%lu] HD[%lu] B[%d] RTP[%d] %s\n", \ + (uint32_t)((_pkt_profile)->rHardXmitArrivalTimestamp), \ + (uint32_t)((_pkt_profile)->rEnqueueTimestamp), \ + (uint32_t)((_pkt_profile)->rDequeueTimestamp), \ + (uint32_t)((_pkt_profile)->rHifTxDoneTimestamp), \ + (uint8_t)((_pkt_profile)->ucTcxFreeCount), \ + (uint16_t)((_pkt_profile)->u2RtpSn), \ + (_note))); \ + (_pkt_profile)->fgIsPrinted = TRUE; \ + } \ +} while (0) +#else +#define PRINT_PKT_PROFILE(_pkt_profile, _note) +#endif + +#define CHK_PROFILES_DELTA(_pkt1, _pkt2, _delta) \ + (CHECK_FOR_TIMEOUT((_pkt1)->rHardXmitArrivalTimestamp, \ + (_pkt2)->rHardXmitArrivalTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt1)->rEnqueueTimestamp, \ + (_pkt2)->rEnqueueTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt1)->rDequeueTimestamp, \ + (_pkt2)->rDequeueTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt1)->rHifTxDoneTimestamp, \ + (_pkt2)->rHifTxDoneTimestamp, (_delta))) + +#define CHK_PROFILE_DELTA(_pkt, _delta) \ + (CHECK_FOR_TIMEOUT((_pkt)->rEnqueueTimestamp, \ + (_pkt)->rHardXmitArrivalTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt)->rDequeueTimestamp, \ + (_pkt)->rEnqueueTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt)->rHifTxDoneTimestamp, \ + (_pkt)->rDequeueTimestamp, (_delta))) +#endif + +/*------------------------------------------------------------------------------ + * MACRO for MSDU_INFO + *------------------------------------------------------------------------------ + */ +#define TX_SET_MMPDU nicTxSetMngPacket +#define TX_SET_DATA_PACKET nicTxSetDataPacket + +/*------------------------------------------------------------------------------ + * MACRO for HW_MAC_TX_DESC_T + *------------------------------------------------------------------------------ + */ +#define TX_DESC_GET_FIELD(_rHwMacTxDescField, _mask, _offset) \ + (((_rHwMacTxDescField) & (_mask)) >> (_offset)) +#define TX_DESC_SET_FIELD(_rHwMacTxDescField, _value, _mask, _offset) \ +{ \ + (_rHwMacTxDescField) &= ~(_mask); \ + (_rHwMacTxDescField) |= (((_value) << (_offset)) & (_mask)); \ +} + +#define HAL_MAC_TX_DESC_SET_DW(_prHwMacTxDesc, _ucOffsetInDw, \ + _ucLengthInDw, _pucValueAddr) \ + kalMemCopy((uint32_t *)(_prHwMacTxDesc) + (_ucOffsetInDw), \ + (uint8_t *)(_pucValueAddr), DWORD_TO_BYTE(_ucLengthInDw)) +#define HAL_MAC_TX_DESC_GET_DW(_prHwMacTxDesc, _ucOffsetInDw, \ + _ucLengthInDw, _pucValueAddr) \ + kalMemCopy((uint8_t *)(_pucValueAddr), \ + (uint32_t *)(_prHwMacTxDesc) + (_ucOffsetInDw), \ + DWORD_TO_BYTE(_ucLengthInDw)) + +/* DW 0 */ +#define HAL_MAC_TX_DESC_GET_TX_BYTE_COUNT(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2TxByteCount) +#define HAL_MAC_TX_DESC_SET_TX_BYTE_COUNT(_prHwMacTxDesc, _u2TxByteCount) \ + (((_prHwMacTxDesc)->u2TxByteCount) = ((uint16_t)_u2TxByteCount)) + +#define HAL_MAC_TX_DESC_GET_ETHER_TYPE_OFFSET(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucEtherOffset, \ + TX_DESC_ETHER_TYPE_OFFSET_MASK, \ + TX_DESC_ETHER_TYPE_OFFSET_OFFSET) +#define HAL_MAC_TX_DESC_SET_ETHER_TYPE_OFFSET(_prHwMacTxDesc, \ + _ucEtherTypeOffset) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucEtherOffset), \ + ((uint8_t)_ucEtherTypeOffset), \ + TX_DESC_ETHER_TYPE_OFFSET_MASK, TX_DESC_ETHER_TYPE_OFFSET_OFFSET) + +#define HAL_MAC_TX_DESC_IS_IP_CHKSUM_ENABLED(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucEtherOffset & TX_DESC_IP_CHKSUM_OFFLOAD) \ + ? FALSE : TRUE) +#define HAL_MAC_TX_DESC_SET_IP_CHKSUM(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucEtherOffset |= TX_DESC_IP_CHKSUM_OFFLOAD) +#define HAL_MAC_TX_DESC_UNSET_IP_CHKSUM(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucEtherOffset &= ~TX_DESC_IP_CHKSUM_OFFLOAD) + +#define HAL_MAC_TX_DESC_IS_TCP_UDP_CHKSUM_ENABLED(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPortIdx_QueueIdx & \ + TX_DESC_TCP_UDP_CHKSUM_OFFLOAD) ? FALSE : TRUE) +#define HAL_MAC_TX_DESC_SET_TCP_UDP_CHKSUM(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPortIdx_QueueIdx |= TX_DESC_TCP_UDP_CHKSUM_OFFLOAD) +#define HAL_MAC_TX_DESC_UNSET_TCP_UDP_CHKSUM(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPortIdx_QueueIdx &= \ + ~TX_DESC_TCP_UDP_CHKSUM_OFFLOAD) + +#if 0 /* USB HIF doesn't use this field. */ +#define HAL_MAC_TX_DESC_IS_USB_NEXT_VLD_ENABLED(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPortIdx_QueueIdx & TX_DESC_USB_NEXT_VLD) \ + ? TRUE : FALSE) +#define HAL_MAC_TX_DESC_SET_USB_NEXT_VLD(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPortIdx_QueueIdx |= TX_DESC_USB_NEXT_VLD) +#define HAL_MAC_TX_DESC_UNSET_USB_NEXT_VLD(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPortIdx_QueueIdx &= ~TX_DESC_USB_NEXT_VLD) +#endif /* if 0 */ + +#define HAL_MAC_TX_DESC_GET_QUEUE_INDEX(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucPortIdx_QueueIdx, \ + TX_DESC_QUEUE_INDEX_MASK, TX_DESC_QUEUE_INDEX_OFFSET) +#define HAL_MAC_TX_DESC_SET_QUEUE_INDEX(_prHwMacTxDesc, _ucQueueIndex) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucPortIdx_QueueIdx), \ + ((uint8_t)_ucQueueIndex), \ + TX_DESC_QUEUE_INDEX_MASK, TX_DESC_QUEUE_INDEX_OFFSET) + +#define HAL_MAC_TX_DESC_GET_PORT_INDEX(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucPortIdx_QueueIdx, \ + TX_DESC_PORT_INDEX, TX_DESC_PORT_INDEX_OFFSET) +#define HAL_MAC_TX_DESC_SET_PORT_INDEX(_prHwMacTxDesc, _ucPortIndex) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucPortIdx_QueueIdx), \ + ((uint8_t)_ucPortIndex), \ + TX_DESC_PORT_INDEX, TX_DESC_PORT_INDEX_OFFSET) + +/* DW 1 */ +#define HAL_MAC_TX_DESC_GET_WLAN_INDEX(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucWlanIdx) +#define HAL_MAC_TX_DESC_SET_WLAN_INDEX(_prHwMacTxDesc, _ucWlanIdx) \ + (((_prHwMacTxDesc)->ucWlanIdx) = (_ucWlanIdx)) + +#define HAL_MAC_TX_DESC_IS_LONG_FORMAT(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_FORMAT)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_LONG_FORMAT(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_FORMAT) +#define HAL_MAC_TX_DESC_SET_SHORT_FORMAT(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_FORMAT) + +#define HAL_MAC_TX_DESC_GET_HEADER_FORMAT(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucHeaderFormat, \ + TX_DESC_HEADER_FORMAT_MASK, TX_DESC_HEADER_FORMAT_OFFSET) +#define HAL_MAC_TX_DESC_SET_HEADER_FORMAT(_prHwMacTxDesc, _ucHdrFormat) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucHeaderFormat), \ + ((uint8_t)_ucHdrFormat), TX_DESC_HEADER_FORMAT_MASK, \ + TX_DESC_HEADER_FORMAT_OFFSET) + +/* HF = 0x00, 802.11 normal mode */ +#define HAL_MAC_TX_DESC_IS_MORE_DATA(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_NON_802_11_MORE_DATA) \ + ? TRUE : FALSE) +#define HAL_MAC_TX_DESC_SET_MORE_DATA(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_NON_802_11_MORE_DATA) +#define HAL_MAC_TX_DESC_UNSET_MORE_DATA(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_NON_802_11_MORE_DATA) + +#define HAL_MAC_TX_DESC_IS_REMOVE_VLAN(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_NON_802_11_REMOVE_VLAN) \ + ? TRUE : FALSE) +#define HAL_MAC_TX_DESC_SET_REMOVE_VLAN(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_NON_802_11_REMOVE_VLAN) +#define HAL_MAC_TX_DESC_UNSET_REMOVE_VLAN(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_NON_802_11_REMOVE_VLAN) + +#define HAL_MAC_TX_DESC_IS_VLAN(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_NON_802_11_VLAN_FIELD) \ + ? TRUE : FALSE) +#define HAL_MAC_TX_DESC_SET_VLAN(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_NON_802_11_VLAN_FIELD) +#define HAL_MAC_TX_DESC_UNSET_VLAN(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_NON_802_11_VLAN_FIELD) + +#define HAL_MAC_TX_DESC_IS_ETHERNET_II(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_NON_802_11_ETHERNET_II) \ + ? TRUE : FALSE) +#define HAL_MAC_TX_DESC_SET_ETHERNET_II(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_NON_802_11_ETHERNET_II) +#define HAL_MAC_TX_DESC_UNSET_ETHERNET_II(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_NON_802_11_ETHERNET_II) + +/* HF = 0x00/0x11, 802.11 normal/enhancement mode */ +#define HAL_MAC_TX_DESC_IS_EOSP(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_NON_802_11_EOSP) \ + ? TRUE : FALSE) +#define HAL_MAC_TX_DESC_SET_EOSP(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_NON_802_11_EOSP) +#define HAL_MAC_TX_DESC_UNSET_EOSP(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_NON_802_11_EOSP) + +/* HF = 0x11, 802.11 enhancement mode */ +#define HAL_MAC_TX_DESC_IS_AMSDU(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_ENH_802_11_AMSDU) \ + ? TRUE : FALSE) +#define HAL_MAC_TX_DESC_SET_AMSDU(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_ENH_802_11_AMSDU) +#define HAL_MAC_TX_DESC_UNSET_AMSDU(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_ENH_802_11_AMSDU) + +/* HF = 0x10, non-802.11 */ +#define HAL_MAC_TX_DESC_GET_802_11_HEADER_LENGTH(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucHeaderFormat, \ + TX_DESC_NOR_802_11_HEADER_LENGTH_MASK, \ + TX_DESC_NOR_802_11_HEADER_LENGTH_OFFSET) +#define HAL_MAC_TX_DESC_SET_802_11_HEADER_LENGTH(_prHwMacTxDesc, \ + _ucHdrLength) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucHeaderFormat), \ + ((uint8_t)_ucHdrLength), \ + TX_DESC_NOR_802_11_HEADER_LENGTH_MASK, \ + TX_DESC_NOR_802_11_HEADER_LENGTH_OFFSET) + +#define HAL_MAC_TX_DESC_GET_TXD_LENGTH(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucHeaderPadding, \ + TX_DESC_TXD_LENGTH_MASK, TX_DESC_TXD_LENGTH_OFFSET) +#define HAL_MAC_TX_DESC_SET_TXD_LENGTH(_prHwMacTxDesc, _ucHdrPadding) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucHeaderPadding), \ + ((uint8_t)_ucHdrPadding), \ + TX_DESC_TXD_LENGTH_MASK, TX_DESC_TXD_LENGTH_OFFSET) + +#define HAL_MAC_TX_DESC_GET_TXD_EXTEND_LENGTH(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucHeaderPadding, \ + TX_DESC_TXD_EXTEND_LENGTH_MASK, \ + TX_DESC_TXD_EXTEND_LENGTH_OFFSET) +#define HAL_MAC_TX_DESC_SET_TXD_EXTEND_LENGTH(_prHwMacTxDesc, _ucHdrPadding) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucHeaderPadding), \ + ((uint8_t)_ucHdrPadding), \ + TX_DESC_TXD_EXTEND_LENGTH_MASK, TX_DESC_TXD_EXTEND_LENGTH_OFFSET) + +#define HAL_MAC_TX_DESC_GET_HEADER_PADDING(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucHeaderPadding, \ + TX_DESC_HEADER_PADDING_LENGTH_MASK, \ + TX_DESC_HEADER_PADDING_LENGTH_OFFSET) +#define HAL_MAC_TX_DESC_SET_HEADER_PADDING(_prHwMacTxDesc, _ucHdrPadding) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucHeaderPadding), \ + ((uint8_t)_ucHdrPadding), \ + TX_DESC_HEADER_PADDING_LENGTH_MASK, \ + TX_DESC_HEADER_PADDING_LENGTH_OFFSET) + +#define HAL_MAC_TX_DESC_GET_UTXB_AMSDU(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucHeaderPadding, \ + TX_DESC_TXD_UTXB_AMSDU_MASK, TX_DESC_TXD_UTXB_AMSDU_OFFSET) +#define HAL_MAC_TX_DESC_SET_UTXB_AMSDU(_prHwMacTxDesc, _ucHdrPadding) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucHeaderPadding), \ + ((uint8_t)_ucHdrPadding), \ + TX_DESC_TXD_UTXB_AMSDU_MASK, TX_DESC_TXD_UTXB_AMSDU_OFFSET) + +#define HAL_MAC_TX_DESC_IS_HEADER_PADDING_IN_THE_HEAD(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderPadding & TX_DESC_HEADER_PADDING_MODE) \ + ? TRUE : FALSE) +#define HAL_MAC_TX_DESC_SET_HEADER_PADDING_IN_THE_HEAD(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderPadding |= TX_DESC_HEADER_PADDING_MODE) +#define HAL_MAC_TX_DESC_SET_HEADER_PADDING_IN_THE_TAIL(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderPadding &= ~TX_DESC_HEADER_PADDING_MODE) + +#define HAL_MAC_TX_DESC_GET_TID(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucHeaderPadding, \ + TX_DESC_TID_MASK, TX_DESC_TID_OFFSET) +#define HAL_MAC_TX_DESC_SET_TID(_prHwMacTxDesc, _ucTID) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucHeaderPadding), \ + ((uint8_t)_ucTID), TX_DESC_TID_MASK, TX_DESC_TID_OFFSET) + +#define HAL_MAC_TX_DESC_GET_PKT_FORMAT(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucOwnMAC, \ + TX_DESC_PACKET_FORMAT_MASK, \ + TX_DESC_PACKET_FORMAT_OFFSET) +#define HAL_MAC_TX_DESC_SET_PKT_FORMAT(_prHwMacTxDesc, _ucPktFormat) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucOwnMAC), \ + ((uint8_t)_ucPktFormat), \ + TX_DESC_PACKET_FORMAT_MASK, TX_DESC_PACKET_FORMAT_OFFSET) + +#define HAL_MAC_TX_DESC_GET_OWN_MAC_INDEX(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucOwnMAC, \ + TX_DESC_OWN_MAC_MASK, TX_DESC_OWN_MAC_OFFSET) +#define HAL_MAC_TX_DESC_SET_OWN_MAC_INDEX(_prHwMacTxDesc, _ucOwnMacIdx) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucOwnMAC), \ + ((uint8_t)_ucOwnMacIdx), \ + TX_DESC_OWN_MAC_MASK, TX_DESC_OWN_MAC_OFFSET) + +/* DW 2 */ +#define HAL_MAC_TX_DESC_GET_SUB_TYPE(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucType_SubType, \ + TX_DESC_SUB_TYPE_MASK, TX_DESC_SUB_TYPE_OFFSET) +#define HAL_MAC_TX_DESC_SET_SUB_TYPE(_prHwMacTxDesc, _ucSubType) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucType_SubType), \ + ((uint8_t)_ucSubType), \ + TX_DESC_SUB_TYPE_MASK, TX_DESC_SUB_TYPE_OFFSET) + +#define HAL_MAC_TX_DESC_GET_TYPE(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucType_SubType, \ + TX_DESC_TYPE_MASK, TX_DESC_TYPE_OFFSET) +#define HAL_MAC_TX_DESC_SET_TYPE(_prHwMacTxDesc, _ucType) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucType_SubType), \ + ((uint8_t)_ucType), TX_DESC_TYPE_MASK, TX_DESC_TYPE_OFFSET) + +#define HAL_MAC_TX_DESC_IS_NDP(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucType_SubType & TX_DESC_NDP)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_NDP(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucType_SubType |= TX_DESC_NDP) +#define HAL_MAC_TX_DESC_UNSET_NDP(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucType_SubType &= ~TX_DESC_NDP) + +#define HAL_MAC_TX_DESC_IS_NDPA(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucType_SubType & TX_DESC_NDPA)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_NDPA(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucType_SubType |= TX_DESC_NDPA) +#define HAL_MAC_TX_DESC_UNSET_NDPA(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucType_SubType &= ~TX_DESC_NDPA) + +#define HAL_MAC_TX_DESC_IS_SOUNDING_FRAME(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucFrag & TX_DESC_SOUNDING)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_SOUNDING_FRAME(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucFrag |= TX_DESC_SOUNDING) +#define HAL_MAC_TX_DESC_UNSET_SOUNDING_FRAME(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucFrag &= ~TX_DESC_SOUNDING) + +#define HAL_MAC_TX_DESC_IS_FORCE_RTS_CTS_EN(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucFrag & TX_DESC_FORCE_RTS_CTS)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_FORCE_RTS_CTS(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucFrag |= TX_DESC_FORCE_RTS_CTS) +#define HAL_MAC_TX_DESC_UNSET_FORCE_RTS_CTS(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucFrag &= ~TX_DESC_FORCE_RTS_CTS) + +#define HAL_MAC_TX_DESC_IS_BMC(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucFrag & TX_DESC_BROADCAST_MULTICAST)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_BMC(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->ucFrag |= TX_DESC_BROADCAST_MULTICAST) +#define HAL_MAC_TX_DESC_UNSET_BMC(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucFrag &= ~TX_DESC_BROADCAST_MULTICAST) + +#define HAL_MAC_TX_DESC_IS_BIP(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucFrag & TX_DESC_BIP_PROTECTED)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_BIP(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucFrag |= TX_DESC_BIP_PROTECTED) +#define HAL_MAC_TX_DESC_UNSET_BIP(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucFrag &= ~TX_DESC_BIP_PROTECTED) + +#define HAL_MAC_TX_DESC_IS_DURATION_CONTROL_BY_SW(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucFrag & TX_DESC_DURATION_FIELD_CONTROL)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_DURATION_CONTROL_BY_SW(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucFrag |= TX_DESC_DURATION_FIELD_CONTROL) +#define HAL_MAC_TX_DESC_SET_DURATION_CONTROL_BY_HW(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucFrag &= ~TX_DESC_DURATION_FIELD_CONTROL) + +#define HAL_MAC_TX_DESC_IS_HTC_EXIST(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucFrag & TX_DESC_HTC_EXISTS)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_HTC_EXIST(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->ucFrag |= TX_DESC_HTC_EXISTS) +#define HAL_MAC_TX_DESC_UNSET_HTC_EXIST(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucFrag &= ~TX_DESC_HTC_EXISTS) + +#define HAL_MAC_TX_DESC_IS_FRAG_PACKET(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucFrag & TX_DESC_FRAGMENT_MASK)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_GET_FRAG_PACKET_POS(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucFrag, \ + TX_DESC_FRAGMENT_MASK, TX_DESC_FRAGMENT_OFFSET) +#define HAL_MAC_TX_DESC_SET_FRAG_PACKET_POS(_prHwMacTxDesc, _ucFragPos) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucFrag), ((uint8_t)_ucFragPos), \ + TX_DESC_FRAGMENT_MASK, TX_DESC_FRAGMENT_OFFSET) + +/* For driver */ +/* in unit of 32TU */ +#define HAL_MAC_TX_DESC_GET_REMAINING_LIFE_TIME(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucRemainingMaxTxTime) +#define HAL_MAC_TX_DESC_SET_REMAINING_LIFE_TIME(_prHwMacTxDesc, _ucLifeTime) \ + ((_prHwMacTxDesc)->ucRemainingMaxTxTime = (_ucLifeTime)) +/* in unit of ms (minimal value is about 40ms) */ +#define HAL_MAC_TX_DESC_GET_REMAINING_LIFE_TIME_IN_MS(_prHwMacTxDesc) \ + (TU_TO_MSEC(HAL_MAC_TX_DESC_GET_REMAINING_LIFE_TIME(_prHwMacTxDesc) \ + << TX_DESC_LIFE_TIME_UNIT_IN_POWER_OF_2)) +#define HAL_MAC_TX_DESC_SET_REMAINING_LIFE_TIME_IN_MS(_prHwMacTxDesc, \ + _u4LifeTimeMs) \ +do { \ + uint32_t u4LifeTimeInUnit = \ + ((MSEC_TO_USEC(_u4LifeTimeMs) / USEC_PER_TU) \ + >> TX_DESC_LIFE_TIME_UNIT_IN_POWER_OF_2); \ + if (u4LifeTimeInUnit >= BIT(8)) \ + u4LifeTimeInUnit = BITS(0, 7); \ + else if ((_u4LifeTimeMs != TX_DESC_TX_TIME_NO_LIMIT) && \ + (u4LifeTimeInUnit == TX_DESC_TX_TIME_NO_LIMIT)) \ + u4LifeTimeInUnit = 1; \ + HAL_MAC_TX_DESC_SET_REMAINING_LIFE_TIME(_prHwMacTxDesc, \ + (uint8_t)u4LifeTimeInUnit); \ +} while (0) + +#define HAL_MAC_TX_DESC_GET_POWER_OFFSET(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucPowerOffset, \ + TX_DESC_POWER_OFFSET_MASK, 0) +#define HAL_MAC_TX_DESC_SET_POWER_OFFSET(_prHwMacTxDesc, _ucPowerOffset) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucPowerOffset), \ + ((uint8_t)_ucPowerOffset), TX_DESC_POWER_OFFSET_MASK, 0) + +#define HAL_MAC_TX_DESC_IS_BA_DISABLE(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPowerOffset & TX_DESC_BA_DISABLE)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_BA_DISABLE(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset |= TX_DESC_BA_DISABLE) +#define HAL_MAC_TX_DESC_SET_BA_ENABLE(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset &= ~TX_DESC_BA_DISABLE) + +#define HAL_MAC_TX_DESC_IS_TIMING_MEASUREMENT(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPowerOffset & TX_DESC_TIMING_MEASUREMENT) \ + ? TRUE : FALSE) +#define HAL_MAC_TX_DESC_SET_TIMING_MEASUREMENT(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset |= TX_DESC_TIMING_MEASUREMENT) +#define HAL_MAC_TX_DESC_UNSET_TIMING_MEASUREMENT(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset &= ~TX_DESC_TIMING_MEASUREMENT) + +#define HAL_MAC_TX_DESC_IS_FIXED_RATE_ENABLE(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPowerOffset & TX_DESC_FIXED_RATE)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_FIXED_RATE_ENABLE(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset |= TX_DESC_FIXED_RATE) +#define HAL_MAC_TX_DESC_SET_FIXED_RATE_DISABLE(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset &= ~TX_DESC_FIXED_RATE) + +/* DW 3 */ +#define HAL_MAC_TX_DESC_IS_NO_ACK(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->u2TxCountLimit & TX_DESC_NO_ACK)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_NO_ACK(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2TxCountLimit |= TX_DESC_NO_ACK) +#define HAL_MAC_TX_DESC_UNSET_NO_ACK(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2TxCountLimit &= ~TX_DESC_NO_ACK) + +#define HAL_MAC_TX_DESC_IS_PROTECTION(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->u2TxCountLimit & TX_DESC_PROTECTED_FRAME) \ + ? TRUE : FALSE) +#define HAL_MAC_TX_DESC_SET_PROTECTION(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2TxCountLimit |= TX_DESC_PROTECTED_FRAME) +#define HAL_MAC_TX_DESC_UNSET_PROTECTION(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2TxCountLimit &= ~TX_DESC_PROTECTED_FRAME) + +#define HAL_MAC_TX_DESC_IS_EXTEND_MORE_DATA(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->u2TxCountLimit & TX_DESC_EXTEND_MORE_DATA) \ + ? TRUE : FALSE) +#define HAL_MAC_TX_DESC_SET_EXTEND_MORE_DATA(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2TxCountLimit |= TX_DESC_EXTEND_MORE_DATA) +#define HAL_MAC_TX_DESC_UNSET_EXTEND_MORE_DATA(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2TxCountLimit &= ~TX_DESC_EXTEND_MORE_DATA) + +#define HAL_MAC_TX_DESC_IS_EXTEND_EOSP(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->u2TxCountLimit & TX_DESC_EXTEND_EOSP)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_EXTEND_EOSP(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2TxCountLimit |= TX_DESC_EXTEND_EOSP) +#define HAL_MAC_TX_DESC_UNSET_EXTEND_EOSP(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2TxCountLimit &= ~TX_DESC_EXTEND_EOSP) + +#define HAL_MAC_TX_DESC_GET_SW_RESERVED(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->u2TxCountLimit, \ + TX_DESC_SW_RESERVED_MASK, TX_DESC_SW_RESERVED_OFFSET) +#define HAL_MAC_TX_DESC_SET_SW_RESERVED(_prHwMacTxDesc, _ucSwReserved) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2TxCountLimit), \ + ((uint8_t)_ucSwReserved), \ + TX_DESC_SW_RESERVED_MASK, TX_DESC_SW_RESERVED_OFFSET) +#define HAL_MAC_TX_DESC_GET_TX_COUNT(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->u2TxCountLimit, \ + TX_DESC_TX_COUNT_MASK, TX_DESC_TX_COUNT_OFFSET) +#define HAL_MAC_TX_DESC_SET_TX_COUNT(_prHwMacTxDesc, _ucTxCountLimit) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2TxCountLimit), \ + ((uint8_t)_ucTxCountLimit), \ + TX_DESC_TX_COUNT_MASK, TX_DESC_TX_COUNT_OFFSET) +#define HAL_MAC_TX_DESC_GET_REMAINING_TX_COUNT(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->u2TxCountLimit, \ + TX_DESC_REMAINING_TX_COUNT_MASK, \ + TX_DESC_REMAINING_TX_COUNT_OFFSET) +#define HAL_MAC_TX_DESC_SET_REMAINING_TX_COUNT(_prHwMacTxDesc, \ + _ucTxCountLimit) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2TxCountLimit), \ + ((uint8_t)_ucTxCountLimit), \ + TX_DESC_REMAINING_TX_COUNT_MASK, \ + TX_DESC_REMAINING_TX_COUNT_OFFSET) +#define HAL_MAC_TX_DESC_GET_SEQUENCE_NUMBER(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->u2SN, TX_DESC_SEQUENCE_NUMBER, 0) +#define HAL_MAC_TX_DESC_SET_SEQUENCE_NUMBER(_prHwMacTxDesc, _u2SN) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2SN), ((uint16_t)_u2SN), \ + TX_DESC_SEQUENCE_NUMBER, 0) +#define HAL_MAC_TX_DESC_SET_HW_RESERVED(_prHwMacTxDesc, _ucHwReserved) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2SN), ((uint8_t)_ucHwReserved), \ + TX_DESC_HW_RESERVED_MASK, TX_DESC_HW_RESERVED_OFFSET) +#define HAL_MAC_TX_DESC_IS_TXD_SN_VALID(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->u2SN & TX_DESC_SN_IS_VALID)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_TXD_SN_VALID(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2SN |= TX_DESC_SN_IS_VALID) +#define HAL_MAC_TX_DESC_SET_TXD_SN_INVALID(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2SN &= ~TX_DESC_SN_IS_VALID) + +#define HAL_MAC_TX_DESC_IS_TXD_PN_VALID(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->u2SN & TX_DESC_PN_IS_VALID)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_TXD_PN_VALID(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2SN |= TX_DESC_PN_IS_VALID) +#define HAL_MAC_TX_DESC_SET_TXD_PN_INVALID(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2SN &= ~TX_DESC_PN_IS_VALID) + +#define HAL_MAC_TX_DESC_ASSIGN_SN_BY_SW(_prHwMacTxDesc, _u2SN) \ +{ \ + HAL_MAC_TX_DESC_SET_SEQUENCE_NUMBER(_prHwMacTxDesc, _u2SN); \ + HAL_MAC_TX_DESC_SET_TXD_SN_VALID(_prHwMacTxDesc); \ +} +#define HAL_MAC_TX_DESC_ASSIGN_SN_BY_HW(_prHwMacTxDesc) \ +{ \ + HAL_MAC_TX_DESC_SET_SEQUENCE_NUMBER(_prHwMacTxDesc, 0); \ + HAL_MAC_TX_DESC_SET_TXD_SN_INVALID(_prHwMacTxDesc); \ +} + +/* DW 4 */ +#define HAL_MAC_TX_DESC_GET_PN(_prHwMacTxDesc, _u4PN_0_31, _u2PN_32_47) \ +{ \ + ((uint32_t)_u4PN_0_31) = (_prHwMacTxDesc)->u4PN1; \ + ((uint16_t)_u2PN_32_47) = (_prHwMacTxDesc)->u2PN2; \ +} +#define HAL_MAC_TX_DESC_SET_PN(_prHwMacTxDesc, _u4PN_0_31, _u2PN_32_47) \ +{ \ + (_prHwMacTxDesc)->u4PN1 = ((uint32_t)_u4PN_0_31); \ + (_prHwMacTxDesc)->u2PN2 = ((uint16_t)_u2PN_32_47); \ +} + +#define HAL_MAC_TX_DESC_ASSIGN_PN_BY_SW(_prTxDesc, _u4PN_0_31, _u2PN_32_47) \ +{ \ + HAL_MAC_TX_DESC_SET_PN(_prTxDesc, _u4PN_0_31, _u2PN_32_47); \ + HAL_MAC_TX_DESC_SET_TXD_PN_VALID(_prTxDesc); \ +} +#define HAL_MAC_TX_DESC_ASSIGN_PSN_BY_HW(_prHwMacTxDesc) \ +{ \ + HAL_MAC_TX_DESC_SET_PN(_prHwMacTxDesc, 0, 0); \ + HAL_MAC_TX_DESC_SET_TXD_PN_INVALID(_prHwMacTxDesc); \ +} + +/* DW 5 */ +#define HAL_MAC_TX_DESC_GET_PID(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPID) +#define HAL_MAC_TX_DESC_SET_PID(_prHwMacTxDesc, _ucPID) \ + (((_prHwMacTxDesc)->ucPID) = (_ucPID)) + +#define HAL_MAC_TX_DESC_GET_TXS_FORMAT(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucTxStatus, \ + TX_DESC_TX_STATUS_FORMAT, TX_DESC_TX_STATUS_FORMAT_OFFSET) +#define HAL_MAC_TX_DESC_SET_TXS_FORMAT(_prHwMacTxDesc, _ucTXSFormat) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucTxStatus), \ + ((uint8_t)_ucTXSFormat), \ + TX_DESC_TX_STATUS_FORMAT, TX_DESC_TX_STATUS_FORMAT_OFFSET) + +#define HAL_MAC_TX_DESC_IS_TXS_TO_MCU(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucTxStatus & TX_DESC_TX_STATUS_TO_MCU)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_TXS_TO_MCU(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucTxStatus |= TX_DESC_TX_STATUS_TO_MCU) +#define HAL_MAC_TX_DESC_UNSET_TXS_TO_MCU(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucTxStatus &= ~TX_DESC_TX_STATUS_TO_MCU) + +#define HAL_MAC_TX_DESC_IS_TXS_TO_HOST(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucTxStatus & TX_DESC_TX_STATUS_TO_HOST)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_TXS_TO_HOST(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucTxStatus |= TX_DESC_TX_STATUS_TO_HOST) +#define HAL_MAC_TX_DESC_UNSET_TXS_TO_HOST(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucTxStatus &= ~TX_DESC_TX_STATUS_TO_HOST) + +#define HAL_MAC_TX_DESC_IS_DA_FROM_WTBL(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPowerOffset & TX_DESC_DA_SOURCE)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_DA_FROM_WTBL(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset |= TX_DESC_DA_SOURCE) +#define HAL_MAC_TX_DESC_SET_DA_FROM_MSDU(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset &= ~TX_DESC_DA_SOURCE) + +#define HAL_MAC_TX_DESC_IS_SW_PM_CONTROL(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPowerOffset & TX_DESC_POWER_MANAGEMENT_CONTROL) \ + ? TRUE : FALSE) +#define HAL_MAC_TX_DESC_SET_SW_PM_CONTROL(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset |= TX_DESC_POWER_MANAGEMENT_CONTROL) +#define HAL_MAC_TX_DESC_SET_HW_PM_CONTROL(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset &= ~TX_DESC_POWER_MANAGEMENT_CONTROL) + +/* DW 6 */ +#define HAL_MAC_TX_DESC_SET_FR_BW(_prHwMacTxDesc, ucBw) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2AntID), \ + ((uint8_t)ucBw), TX_DESC_BANDWIDTH_MASK, TX_DESC_BANDWIDTH_OFFSET) + +#define HAL_MAC_TX_DESC_SET_FR_DYNAMIC_BW_RTS(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2AntID |= TX_DESC_DYNAMIC_BANDWIDTH) + +#define HAL_MAC_TX_DESC_SET_FR_ANTENNA_ID(_prHwMacTxDesc, _ucAntId) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2AntID), \ + ((uint8_t)_ucAntId), \ + TX_DESC_ANTENNA_INDEX_MASK, TX_DESC_ANTENNA_INDEX_OFFSET) + +#define HAL_MAC_TX_DESC_SET_FR_RATE(_prHwMacTxDesc, _u2RatetoFixed) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2FixedRate), \ + ((uint8_t)_u2RatetoFixed), \ + TX_DESC_FIXDE_RATE_MASK, TX_DESC_FIXDE_RATE_OFFSET) + +#define HAL_MAC_TX_DESC_SET_FR_BF(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2FixedRate |= TX_DESC_BF) + +#define HAL_MAC_TX_DESC_SET_FR_LDPC(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2FixedRate |= TX_DESC_LDPC) + +#define HAL_MAC_TX_DESC_SET_FR_SHORT_GI(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2FixedRate |= TX_DESC_GUARD_INTERVAL) + +#define HAL_MAC_TX_DESC_SET_FR_NORMAL_GI(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2FixedRate &= ~TX_DESC_GUARD_INTERVAL) + +#define HAL_MAC_TX_DESC_IS_CR_FIXED_RATE_MODE(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->u2FixedRate & TX_DESC_FIXED_RATE_MODE)?TRUE:FALSE) + +#define HAL_MAC_TX_DESC_SET_FIXED_RATE_MODE_TO_DESC(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2FixedRate &= ~TX_DESC_FIXED_RATE_MODE) +#define HAL_MAC_TX_DESC_SET_FIXED_RATE_MODE_TO_CR(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2FixedRate |= TX_DESC_FIXED_RATE_MODE) + +/* DW 7 */ +#define HAL_MAC_TX_DESC_SET_SPE_IDX_SEL(_prHwMacTxDesc, _ucSpeIdxSel) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2SwTxTime), \ + ((uint16_t)_ucSpeIdxSel), \ + TX_DESC_SPE_EXT_IDX_SEL_MASK, TX_DESC_SPE_EXT_IDX_SEL_OFFSET) +#define HAL_MAC_TX_DESC_SET_SPE_IDX(_prHwMacTxDesc, _ucSpeIdx) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2SwTxTime), \ + ((uint16_t)_ucSpeIdx), \ + TX_DESC_SPE_EXT_IDX_MASK, TX_DESC_SPE_EXT_IDX_OFFSET) + +#define HAL_MAC_TX_DESC_IS_HW_AMSDU(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->u2PseFid & TX_DESC_HW_AMSDU)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_HW_AMSDU(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2PseFid |= TX_DESC_HW_AMSDU) +#define HAL_MAC_TX_DESC_UNSET_HW_AMSDU(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2PseFid &= ~TX_DESC_HW_AMSDU) + +#define HAL_MAC_TX_DESC_IS_HIF_ERR(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->u2PseFid & TX_DESC_HIF_ERR)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_HIF_ERR(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2PseFid |= TX_DESC_HIF_ERR) +#define HAL_MAC_TX_DESC_UNSET_HIF_ERR(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2PseFid &= ~TX_DESC_HIF_ERR) + + +#define nicTxReleaseResource_PSE(prAdapter, ucTc, u4PageCount, fgReqLock) \ + nicTxReleaseResource(prAdapter, ucTc, u4PageCount, fgReqLock, FALSE) + +#define nicTxReleaseResource_PLE(prAdapter, ucTc, u4PageCount, fgReqLock) \ + nicTxReleaseResource(prAdapter, ucTc, u4PageCount, fgReqLock, TRUE) + +#if (CFG_SUPPORT_802_11AX == 1) +#define NIC_TX_PPDU_ENABLE(__pAd) \ + HAL_MCR_WR( \ + __pAd, \ + __pAd->chip_info->arb_ac_mode_addr, \ + 0x0) + +#define NIC_TX_PPDU_DISABLE(__pAd) \ + HAL_MCR_WR( \ + __pAd, \ + __pAd->chip_info->arb_ac_mode_addr, \ + 0xFFFFFFFF) +#endif /* CFG_SUPPORT_802_11AX == 1 */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +void nicTxInitialize(IN struct ADAPTER *prAdapter); + +uint32_t nicTxAcquireResource(IN struct ADAPTER *prAdapter, + IN uint8_t ucTC, IN uint32_t u4PageCount, + IN u_int8_t fgReqLock); + +uint32_t nicTxPollingResource(IN struct ADAPTER *prAdapter, + IN uint8_t ucTC); + +u_int8_t nicTxReleaseResource(IN struct ADAPTER *prAdapter, + IN uint8_t ucTc, IN uint32_t u4PageCount, + IN u_int8_t fgReqLock, IN u_int8_t fgPLE); + +void nicTxReleaseMsduResource(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfoListHead); + +uint32_t nicTxResetResource(IN struct ADAPTER *prAdapter); + +#if defined(_HIF_SDIO) +uint32_t nicTxGetAdjustableResourceCnt(IN struct ADAPTER *prAdapter); +#endif + +uint16_t nicTxGetResource(IN struct ADAPTER *prAdapter, + IN uint8_t ucTC); + +uint8_t nicTxGetFrameResourceType(IN uint8_t eFrameType, + IN struct MSDU_INFO *prMsduInfo); + +uint8_t nicTxGetCmdResourceType(IN struct CMD_INFO *prCmdInfo); + +u_int8_t nicTxSanityCheckResource(IN struct ADAPTER *prAdapter); + +void nicTxFillDesc(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, OUT uint8_t *prTxDescBuffer, + OUT uint32_t *pu4TxDescLength); + +void nicTxFillDataDesc(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +void nicTxComposeSecurityFrameDesc(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, + OUT uint8_t *prTxDescBuffer, OUT uint8_t *pucTxDescLength); + +uint32_t nicTxMsduInfoList(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfoListHead); + +uint8_t nicTxGetTxQByTc(IN struct ADAPTER *prAdapter, IN uint8_t ucTc); +uint8_t nicTxGetTxDestPortIdxByTc(IN uint8_t ucTc); +uint8_t nicTxGetTxDestQIdxByTc(IN uint8_t ucTc); +uint32_t nicTxGetRemainingTxTimeByTc(IN uint8_t ucTc); +uint8_t nicTxGetTxCountLimitByTc(IN uint8_t ucTc); +#if CFG_SUPPORT_MULTITHREAD +uint32_t nicTxMsduInfoListMthread(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfoListHead); + +uint32_t nicTxMsduQueueMthread(IN struct ADAPTER *prAdapter); + +void nicTxMsduQueueByPrio(struct ADAPTER *prAdapter); +void nicTxMsduQueueByRR(struct ADAPTER *prAdapter); + +uint32_t nicTxGetMsduPendingCnt(IN struct ADAPTER *prAdapter); +#endif + +uint32_t nicTxMsduQueue(IN struct ADAPTER *prAdapter, + uint8_t ucPortIdx, struct QUE *prQue); + +uint32_t nicTxCmd(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t ucTC); + +void nicTxRelease(IN struct ADAPTER *prAdapter, + IN u_int8_t fgProcTxDoneHandler); + +void nicProcessTxInterrupt(IN struct ADAPTER *prAdapter); + +void nicTxFreeMsduInfoPacket(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfoListHead); + +void nicTxReturnMsduInfo(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfoListHead); + +u_int8_t nicTxFillMsduInfo(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN void *prNdisPacket); + +uint32_t nicTxAdjustTcq(IN struct ADAPTER *prAdapter); + +uint32_t nicTxFlush(IN struct ADAPTER *prAdapter); + +#if CFG_ENABLE_FW_DOWNLOAD +uint32_t nicTxInitCmd(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint16_t u2Port); + +uint32_t nicTxInitResetResource(IN struct ADAPTER *prAdapter); +#endif + +u_int8_t nicTxProcessCmdDataPacket(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +uint32_t nicTxEnqueueMsdu(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +uint8_t nicTxGetWlanIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, IN uint8_t ucStaRecIdx); + +u_int8_t nicTxIsMgmtResourceEnough(IN struct ADAPTER *prAdapter); + +uint32_t nicTxGetFreeCmdCount(IN struct ADAPTER *prAdapter); + +uint32_t nicTxGetPageCount(IN struct ADAPTER *prAdapter, + IN uint32_t u4FrameLength, IN u_int8_t fgIncludeDesc); + +uint32_t nicTxGetCmdPageCount(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo); + +uint32_t nicTxGenerateDescTemplate(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +void nicTxFreeDescTemplate(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +void nicTxSetHwAmsduDescTemplate(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN uint8_t ucTid, IN u_int8_t fgSet); + +void nicTxFreePacket(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN u_int8_t fgDrop); + +void nicTxSetMngPacket(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN uint8_t ucBssIndex, + IN uint8_t ucStaRecIndex, + IN uint8_t ucMacHeaderLength, + IN uint16_t u2FrameLength, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler, + IN uint8_t ucRateMode); + +void nicTxSetDataPacket(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN uint8_t ucBssIndex, + IN uint8_t ucStaRecIndex, + IN uint8_t ucMacHeaderLength, + IN uint16_t u2FrameLength, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler, + IN uint8_t ucRateMode, + IN enum ENUM_TX_PACKET_SRC eSrc, IN uint8_t ucTID, + IN u_int8_t fgIs802_11Frame, IN u_int8_t fgIs1xFrame); + +void nicTxFillDescByPktOption( + IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN void *prTxDesc); + +void nicTxConfigPktOption(IN struct MSDU_INFO *prMsduInfo, + IN uint32_t u4OptionMask, IN u_int8_t fgSetOption); + +void nicTxFillDescByPktControl(struct MSDU_INFO *prMsduInfo, + void *prTxDesc); + +void nicTxConfigPktControlFlag(IN struct MSDU_INFO *prMsduInfo, + IN uint8_t ucControlFlagMask, IN u_int8_t fgSetFlag); + +void nicTxSetPktLifeTime(IN struct MSDU_INFO *prMsduInfo, + IN uint32_t u4TxLifeTimeInMs); + +void nicTxSetPktRetryLimit(IN struct MSDU_INFO *prMsduInfo, + IN uint8_t ucRetryLimit); + +void nicTxSetPktPowerOffset(IN struct MSDU_INFO *prMsduInfo, + IN int8_t cPowerOffset); + +void nicTxSetPktSequenceNumber(IN struct MSDU_INFO *prMsduInfo, + IN uint16_t u2SN); + +void nicTxSetPktMacTxQue(IN struct MSDU_INFO *prMsduInfo, + IN uint8_t ucMacTxQue); + +void nicTxSetPktFixedRateOptionFull( + struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + uint16_t u2RateCode, + uint8_t ucBandwidth, + u_int8_t fgShortGI, + u_int8_t fgLDPC, + u_int8_t fgDynamicBwRts, + u_int8_t fgBeamforming, + uint8_t ucAntennaIndex); + +void nicTxSetPktFixedRateOption( + struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + uint16_t u2RateCode, + uint8_t ucBandwidth, + u_int8_t fgShortGI, + u_int8_t fgDynamicBwRts); + +void nicTxSetPktLowestFixedRate(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +void nicTxSetPktMoreData(IN struct MSDU_INFO *prCurrentMsduInfo, + IN u_int8_t fgSetMoreDataBit); + +void nicTxSetPktEOSP(IN struct MSDU_INFO *prCurrentMsduInfo, + IN u_int8_t fgSetEOSPBit); + +uint8_t nicTxAssignPID(IN struct ADAPTER *prAdapter, + IN uint8_t ucWlanIndex); + +uint32_t +nicTxDummyTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +void nicTxUpdateBssDefaultRate(IN struct BSS_INFO *prBssInfo); + +void nicTxUpdateStaRecDefaultRate(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +void nicTxPrintMetRTP(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN void *prPacket, + IN uint32_t u4PacketLen, IN u_int8_t bFreeSkb); + +void nicTxProcessTxDoneEvent(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); + +void nicTxChangeDataPortByAc( + struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t ucAci, + u_int8_t fgToMcu); + +void nicTxHandleRoamingDone(struct ADAPTER *prAdapter, + struct STA_RECORD *prOldStaRec, + struct STA_RECORD *prNewStaRec); + +void nicTxMsduDoneCb(IN struct GLUE_INFO *prGlueInfo, IN struct QUE *prQue); + +void nicTxCancelSendingCmd(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo); +uint32_t nicTxGetMaxPageCntPerFrame(IN struct ADAPTER *prAdapter); + +/* TX Direct functions : BEGIN */ +void nicTxDirectStartCheckQTimer(IN struct ADAPTER *prAdapter); +void nicTxDirectClearSkbQ(IN struct ADAPTER *prAdapter); +void nicTxDirectClearHifQ(IN struct ADAPTER *prAdapter); +void nicTxDirectClearStaPsQ(IN struct ADAPTER *prAdapter, + uint8_t ucStaRecIndex); +void nicTxDirectClearBssAbsentQ(IN struct ADAPTER *prAdapter, + uint8_t ucBssIndex); +void nicTxDirectClearAllStaPsQ(IN struct ADAPTER *prAdapter); + +#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE +void nicTxDirectTimerCheckSkbQ(struct timer_list *timer); +void nicTxDirectTimerCheckHifQ(struct timer_list *timer); +#else +void nicTxDirectTimerCheckSkbQ(unsigned long data); +void nicTxDirectTimerCheckHifQ(unsigned long data); +#endif + +uint32_t nicTxDirectStartXmit(struct sk_buff *prSkb, + struct GLUE_INFO *prGlueInfo); +/* TX Direct functions : END */ + +uint32_t nicTxResourceGetPleFreeCount(IN struct ADAPTER *prAdapter, + IN uint8_t ucTC); +u_int8_t nicTxResourceIsPleCtrlNeeded(IN struct ADAPTER *prAdapter, + IN uint8_t ucTC); +void nicTxResourceUpdate_v1(IN struct ADAPTER *prAdapter); + +int32_t nicTxGetVectorInfo(IN char *pcCommand, IN int i4TotalLen, + IN struct TX_VECTOR_BBP_LATCH *prTxV); + +void nicHifTxMsduDoneCb(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _NIC_TX_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_txd_v1.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_txd_v1.h new file mode 100644 index 0000000000000..e33e424c87a4f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_txd_v1.h @@ -0,0 +1,138 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + * + */ + + +#ifndef _NIC_TXD_V1_H +#define _NIC_TXD_V1_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 + ******************************************************************************* + */ + +uint8_t nic_txd_v1_long_format_op( + void *prTxDesc, + uint8_t fgSet); +uint8_t nic_txd_v1_tid_op( + void *prTxDesc, + uint8_t ucTid, + uint8_t fgSet); +uint8_t nic_txd_v1_queue_idx_op( + void *prTxDesc, + uint8_t ucQueIdx, + uint8_t fgSet); +#if (CFG_TCP_IP_CHKSUM_OFFLOAD == 1) +void nic_txd_v1_chksum_op( + void *prTxDesc, + uint8_t ucChksumFlag); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD == 1 */ +void nic_txd_v1_header_format_op( + void *prTxDesc, + struct MSDU_INFO *prMsduInfo); + +void nic_txd_v1_fill_by_pkt_option( + struct MSDU_INFO *prMsduInfo, + void *prTxD); + +void nic_txd_v1_compose( + struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + u_int32_t u4TxDescLength, + u_int8_t fgIsTemplate, + u_int8_t *prTxDescBuffer); +void nic_txd_v1_compose_security_frame( + struct ADAPTER *prAdapter, + struct CMD_INFO *prCmdInfo, + uint8_t *prTxDescBuffer, + uint8_t *pucTxDescLength); +void nic_txd_v1_set_pkt_fixed_rate_option_full( + struct MSDU_INFO *prMsduInfo, + uint16_t u2RateCode, + uint8_t ucBandwidth, + u_int8_t fgShortGI, + u_int8_t fgLDPC, + u_int8_t fgDynamicBwRts, + u_int8_t fgBeamforming, + uint8_t ucAntennaIndex); +void nic_txd_v1_set_pkt_fixed_rate_option( + struct MSDU_INFO *prMsduInfo, + uint16_t u2RateCode, + uint8_t ucBandwidth, + u_int8_t fgShortGI, + u_int8_t fgDynamicBwRts); +void nic_txd_v1_set_hw_amsdu_template( + struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t ucTid, + u_int8_t fgSet); +void nic_txd_v1_change_data_port_by_ac( + struct STA_RECORD *prStaRec, + uint8_t ucAci, + u_int8_t fgToMcu); +#endif /* _NIC_TXD_V1_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_txd_v2.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_txd_v2.h new file mode 100644 index 0000000000000..0f14ab374e235 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_txd_v2.h @@ -0,0 +1,136 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + * + */ + + +#ifndef _NIC_TXD_V2_H +#define _NIC_TXD_V2_H + +#if (CFG_SUPPORT_CONNAC2X == 1) +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ + +uint8_t nic_txd_v2_long_format_op( + void *prTxDesc, + uint8_t fgSet); +uint8_t nic_txd_v2_tid_op( + void *prTxDesc, + uint8_t ucTid, + uint8_t fgSet); +uint8_t nic_txd_v2_queue_idx_op( + void *prTxDesc, + uint8_t ucQueIdx, + uint8_t fgSet); +#if (CFG_TCP_IP_CHKSUM_OFFLOAD == 1) +void nic_txd_v2_chksum_op( + void *prTxDesc, + uint8_t ucChksumFlag); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD == 1 */ +void nic_txd_v2_header_format_op( + void *prTxDesc, + struct MSDU_INFO *prMsduInfo); + +void nic_txd_v2_fill_by_pkt_option( + struct MSDU_INFO *prMsduInfo, + void *prTxD); + +void nic_txd_v2_compose( + struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + u_int32_t u4TxDescLength, + u_int8_t fgIsTemplate, + u_int8_t *prTxDescBuffer); +void nic_txd_v2_compose_security_frame( + struct ADAPTER *prAdapter, + struct CMD_INFO *prCmdInfo, + uint8_t *prTxDescBuffer, + uint8_t *pucTxDescLength); +void nic_txd_v2_set_pkt_fixed_rate_option_full( + struct MSDU_INFO *prMsduInfo, + uint16_t u2RateCode, + uint8_t ucBandwidth, + u_int8_t fgShortGI, + u_int8_t fgLDPC, + u_int8_t fgDynamicBwRts, + u_int8_t fgBeamforming, + uint8_t ucAntennaIndex); +void nic_txd_v2_set_pkt_fixed_rate_option( + struct MSDU_INFO *prMsduInfo, + uint16_t u2RateCode, + uint8_t ucBandwidth, + u_int8_t fgShortGI, + u_int8_t fgDynamicBwRts); +void nic_txd_v2_set_hw_amsdu_template( + struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t ucTid, + u_int8_t fgSet); +#endif /* CFG_SUPPORT_CONNAC2X == 1 */ +#endif /* _NIC_TXD_V2_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_umac.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_umac.h new file mode 100644 index 0000000000000..a6a46f57668ab --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/nic_umac.h @@ -0,0 +1,140 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/ + * MT6620_WIFI_DRIVER_V2_3/include/nic/nic_umac.h#1 + */ + +/*! \file "nic_umac.h" + * \brief The declaration of the nic umac debug functions + * + */ + + +#ifndef _NIC_UMAC_H +#define _NIC_UMAC_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 + ******************************************************************************* + */ + +#define UMAC_FID_MASK 0xFFF + +#define UMAC_FID_FAULT 0xFFF + +#define UMAC_PLE_CFG_POOL_INDEX 0 +#define UMAC_PSE_CFG_POOL_INDEX 1 + +#define UMAC_PG_HIF0_GROUP_0 0 +#define UMAC_PG_HIF1_GROUP_1 1 +#define UMAC_PG_CPU_GROUP_2 2 +#define UMAC_PG_LMAC0_GROUP_3 3 +#define UMAC_PG_LMAC1_GROUP_4 4 +#define UMAC_PG_LMAC2_GROUP_5 5 +#define UMAC_PG_PLE_GROUP_6 6 + +#define UMAC_PBUF_CTRL_TOTAL_PAGE_NUM_MASK BITS(0, 11) +#define UMAC_PBUF_CTRL_TOTAL_PAGE_NUM_OFFSET 0 + +#define UMAC_FREEPG_CNT_FREEPAGE_CNT_MASK BITS(0, 11) +#define UMAC_FREEPG_CNT_FREEPAGE_CNT_OFFSET 0 + +#define UMAC_FREEPG_CNT_FFA_CNT_MASK BITS(16, 27) +#define UMAC_FREEPG_CNT_FFA_CNT_OFFSET 16 + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +OUT u_int8_t +halUmacInfoGetMiscStatus(IN struct ADAPTER *prAdapter, + IN struct UMAC_STAT2_GET *pUmacStat2Get); + +#endif /* _NIC_UMAC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/p2p.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/p2p.h new file mode 100644 index 0000000000000..b6ab98acfb46f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/p2p.h @@ -0,0 +1,409 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/nic/p2p.h#3 + */ + + +#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 + +/* Device Capability Definition. */ +#define P2P_MAXIMUM_NOA_COUNT 8 + +#define P2P_MAX_AKM_SUITES 2 + +#define P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE 51 /* Contains 6 sub-band. */ + +/* Memory Size Definition. */ +#define P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE 768 +#define WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE 300 + +#define P2P_WILDCARD_SSID "DIRECT-" + +/* Device Charactoristic. */ +/* 1000 is too short , the deauth would block in the queue */ +#define P2P_AP_CHNL_HOLD_TIME_MS 5000 +#define P2P_DEFAULT_LISTEN_CHANNEL 1 + +#if (CFG_SUPPORT_DFS_MASTER == 1) +#define P2P_AP_CAC_WEATHER_CHNL_HOLD_TIME_MS (600*1000) +#endif + +#define P2P_DEAUTH_TIMEOUT_TIME_MS 1000 + +#define P2P_SAA_RETRY_COUNT 5 + +#define AP_DEFAULT_CHANNEL_2G 6 +#define AP_DEFAULT_CHANNEL_5G 36 + +/****************************************************************************** + * M A C R O S + ****************************************************************************** + */ + +#if DBG +#define ASSERT_BREAK(_exp) \ + { \ + if (!(_exp)) { \ + ASSERT(FALSE); \ + break; \ + } \ + } + +#else +#define ASSERT_BREAK(_exp) +#endif + +#define p2pChangeMediaState(_prAdapter, _prP2pBssInfo, _eNewMediaState) \ + (_prP2pBssInfo->eConnectionState = (_eNewMediaState)) + +/****************************************************************************** + * D A T A T Y P E S + ****************************************************************************** + */ +/* if driver need wait for a longger time when do p2p connection */ +enum ENUM_P2P_CONNECT_STATE { + P2P_CNN_NORMAL = 0, + P2P_CNN_GO_NEG_REQ, + P2P_CNN_GO_NEG_RESP, + P2P_CNN_GO_NEG_CONF, + P2P_CNN_INVITATION_REQ, + P2P_CNN_INVITATION_RESP, + P2P_CNN_DEV_DISC_REQ, + P2P_CNN_DEV_DISC_RESP, + P2P_CNN_PROV_DISC_REQ, + P2P_CNN_PROV_DISC_RESP +}; + +struct P2P_INFO { + uint32_t u4DeviceNum; + enum ENUM_P2P_CONNECT_STATE eConnState; + struct EVENT_P2P_DEV_DISCOVER_RESULT + arP2pDiscoverResult[CFG_MAX_NUM_BSS_LIST]; + uint8_t *pucCurrIePtr; + /* A common pool for IE of all scan results. */ + uint8_t aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN]; + uint8_t ucExtendChanFlag; +}; + +enum ENUM_P2P_PEER_TYPE { + ENUM_P2P_PEER_GROUP, + ENUM_P2P_PEER_DEVICE, + ENUM_P2P_PEER_NUM +}; + +struct P2P_DEVICE_INFO { + uint8_t aucDevAddr[PARAM_MAC_ADDR_LEN]; + uint8_t aucIfAddr[PARAM_MAC_ADDR_LEN]; + uint8_t ucDevCapabilityBitmap; + int32_t i4ConfigMethod; + uint8_t aucPrimaryDeviceType[8]; + uint8_t aucSecondaryDeviceType[8]; + uint8_t aucDeviceName[P2P_DEVICE_NAME_LENGTH]; +}; + +struct P2P_GROUP_INFO { + struct PARAM_SSID rGroupID; + struct P2P_DEVICE_INFO rGroupOwnerInfo; + uint8_t ucMemberNum; + struct P2P_DEVICE_INFO arMemberInfo[P2P_MEMBER_NUM]; +}; + +struct P2P_NETWORK_INFO { + enum ENUM_P2P_PEER_TYPE eNodeType; + + union { + struct P2P_GROUP_INFO rGroupInfo; + struct P2P_DEVICE_INFO rDeviceInfo; + } node; +}; + +struct P2P_NETWORK_LIST { + uint8_t ucNetworkNum; + struct P2P_NETWORK_INFO rP2PNetworkInfo[P2P_NETWORK_NUM]; +}; + +struct P2P_DISCONNECT_INFO { + uint8_t ucRole; + uint8_t ucRsv[3]; +}; + +struct P2P_SSID_STRUCT { + uint8_t aucSsid[32]; + uint8_t ucSsidLen; +}; + +enum ENUM_SCAN_REASON { + SCAN_REASON_UNKNOWN = 0, + SCAN_REASON_CONNECT, + SCAN_REASON_STARTAP, + SCAN_REASON_ACS, + SCAN_REASON_NUM, +}; + +struct P2P_SCAN_REQ_INFO { + enum ENUM_SCAN_TYPE eScanType; + enum ENUM_SCAN_CHANNEL eChannelSet; + uint16_t u2PassiveDewellTime; + uint8_t ucSeqNumOfScnMsg; + u_int8_t fgIsAbort; + u_int8_t fgIsScanRequest; + uint8_t ucNumChannelList; + struct RF_CHANNEL_INFO + arScanChannelList[MAXIMUM_OPERATION_CHANNEL_LIST]; + uint32_t u4BufLength; + uint8_t aucIEBuf[MAX_IE_LENGTH]; + uint8_t ucSsidNum; + enum ENUM_SCAN_REASON eScanReason; + /* Currently we can only take one SSID scan request */ + struct P2P_SSID_STRUCT arSsidStruct[SCN_SSID_MAX_NUM]; +}; + +enum P2P_VENDOR_ACS_HW_MODE { + P2P_VENDOR_ACS_HW_MODE_11B, + P2P_VENDOR_ACS_HW_MODE_11G, + P2P_VENDOR_ACS_HW_MODE_11A, + P2P_VENDOR_ACS_HW_MODE_11AD, + P2P_VENDOR_ACS_HW_MODE_11ANY +}; + +struct P2P_ACS_REQ_INFO { + uint8_t ucRoleIdx; + u_int8_t fgIsProcessing; + u_int8_t fgIsHtEnable; + u_int8_t fgIsHt40Enable; + u_int8_t fgIsVhtEnable; + enum ENUM_MAX_BANDWIDTH_SETTING eChnlBw; + enum P2P_VENDOR_ACS_HW_MODE eHwMode; + uint32_t u4LteSafeChnMask_2G; + uint32_t u4LteSafeChnMask_5G_1; + uint32_t u4LteSafeChnMask_5G_2; + + /* output only */ + uint8_t ucPrimaryCh; + uint8_t ucSecondCh; + uint8_t ucCenterFreqS1; + uint8_t ucCenterFreqS2; +}; + +struct P2P_CHNL_REQ_INFO { + struct LINK rP2pChnlReqLink; + u_int8_t fgIsChannelRequested; + uint8_t ucSeqNumOfChReq; + uint64_t u8Cookie; + uint8_t ucReqChnlNum; + enum ENUM_BAND eBand; + enum ENUM_CHNL_EXT eChnlSco; + uint8_t ucOriChnlNum; + enum ENUM_CHANNEL_WIDTH eChannelWidth; /*VHT operation ie */ + uint8_t ucCenterFreqS1; + uint8_t ucCenterFreqS2; + enum ENUM_BAND eOriBand; + enum ENUM_CHNL_EXT eOriChnlSco; + uint32_t u4MaxInterval; + enum ENUM_CH_REQ_TYPE eChnlReqType; +#if CFG_SUPPORT_NFC_BEAM_PLUS + uint32_t NFC_BEAM; /*NFC Beam + Indication */ +#endif +}; + +/* Glubal Connection Settings. */ +struct P2P_CONNECTION_SETTINGS { + /*UINT_8 ucRfChannelListSize;*/ +#if P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE + /*UINT_8 aucChannelEntriesField[P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE];*/ +#endif + + u_int8_t fgIsApMode; +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + u_int8_t fgIsWPSMode; +#endif +}; + +struct NOA_TIMING { + u_int8_t fgIsInUse; /* Indicate if this entry is in use or not */ + uint8_t ucCount; /* Count */ + + uint8_t aucReserved[2]; + + uint32_t u4Duration; /* Duration */ + uint32_t u4Interval; /* Interval */ + uint32_t u4StartTime; /* Start Time */ +}; + +struct P2P_SPECIFIC_BSS_INFO { + /* For GO(AP) Mode - Compose TIM IE */ + /*UINT_16 u2SmallestAID;*//* TH3 multiple P2P */ + /*UINT_16 u2LargestAID;*//* TH3 multiple P2P */ + /*UINT_8 ucBitmapCtrl;*//* TH3 multiple P2P */ + /* UINT_8 aucPartialVirtualBitmap[MAX_LEN_TIM_PARTIAL_BMP]; */ + + /* For GC/GO OppPS */ + u_int8_t fgEnableOppPS; + uint16_t u2CTWindow; + + /* For GC/GO NOA */ + uint8_t ucNoAIndex; + uint8_t ucNoATimingCount; /* Number of NoA Timing */ + struct NOA_TIMING arNoATiming[P2P_MAXIMUM_NOA_COUNT]; + + u_int8_t fgIsNoaAttrExisted; + + /* For P2P Device */ + /* TH3 multiple P2P */ /* Regulatory Class for channel. */ + /*UINT_8 ucRegClass;*/ + /* Linten Channel only on channels 1, 6 and 11 in the 2.4 GHz. */ + /*UINT_8 ucListenChannel;*//* TH3 multiple P2P */ + + /* Operating Channel, should be one of channel */ + /* list in p2p connection settings. */ + uint8_t ucPreferredChannel; + enum ENUM_CHNL_EXT eRfSco; + enum ENUM_BAND eRfBand; + + /* Extended Listen Timing. */ + uint16_t u2AvailabilityPeriod; + uint16_t u2AvailabilityInterval; + + uint16_t u2AttributeLen; + uint8_t aucAttributesCache[P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; + + /*UINT_16 u2WscAttributeLen;*//* TH3 multiple P2P */ + /* TH3 multiple P2P */ + /*UINT_8 aucWscAttributesCache[WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE];*/ + + /*UINT_8 aucGroupID[MAC_ADDR_LEN];*//* TH3 multiple P2P */ + uint16_t u2GroupSsidLen; + uint8_t aucGroupSsid[ELEM_MAX_LEN_SSID]; + + struct PARAM_CUSTOM_NOA_PARAM_STRUCT rNoaParam; + struct PARAM_CUSTOM_OPPPS_PARAM_STRUCT rOppPsParam; + + uint32_t u4KeyMgtSuiteCount; + uint32_t au4KeyMgtSuite[P2P_MAX_AKM_SUITES]; + + uint16_t u2WpaIeLen; + uint8_t aucWpaIeBuffer[ELEM_HDR_LEN + ELEM_MAX_LEN_WPA]; + + uint16_t u2RsnIeLen; + uint8_t aucRsnIeBuffer[ELEM_HDR_LEN + ELEM_MAX_LEN_RSN]; +}; + +struct P2P_QUEUED_ACTION_FRAME { + uint8_t ucRoleIdx; + int32_t u4Freq; + uint8_t *prHeader; + uint16_t u2Length; +}; + +struct P2P_MGMT_TX_REQ_INFO { + struct LINK rTxReqLink; + struct MSDU_INFO *prMgmtTxMsdu; + u_int8_t fgIsWaitRsp; +}; + +/****************************************************************************** + * P U B L I C D A T A + ****************************************************************************** + */ + +/****************************************************************************** + * P R I V A T E D A T A + ****************************************************************************** + */ + +/****************************************************************************** + * F U N C T I O N D E C L A R A T I O N S + ****************************************************************************** + */ + +#endif /*_P2P_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/p2p_cmd_buf.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/p2p_cmd_buf.h new file mode 100644 index 0000000000000..7dbf951a20789 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/p2p_cmd_buf.h @@ -0,0 +1,121 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + + +#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 + ****************************************************************************** + */ + +/****************************************************************************** + * 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 + ****************************************************************************** + */ + + +/*--------------------------------------------------------------*/ +/* Firmware Command Packer */ +/*--------------------------------------------------------------*/ +uint32_t +wlanoidSendSetQueryP2PCmd(IN struct ADAPTER *prAdapter, IN uint8_t ucCID, + IN uint8_t ucBssIdx, IN u_int8_t fgSetQuery, + IN u_int8_t fgNeedResp, IN u_int8_t fgIsOid, + IN PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + IN PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + IN uint32_t u4SetQueryInfoLen, + IN uint8_t *pucInfoBuffer, OUT void *pvSetQueryBuffer, + IN uint32_t u4SetQueryBufferLen); + +#endif /* _P2P_CMD_BUF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/p2p_mac.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/p2p_mac.h new file mode 100644 index 0000000000000..46a54d5056913 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/p2p_mac.h @@ -0,0 +1,438 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 + ****************************************************************************** + */ + +/* --------------- WPS Data Element Definitions --------------- */ +/* P2P 4.2.2 - General WSC Attribute */ +/* ID(2 octet) + Length(2 octets) */ +#define WSC_ATTRI_HDR_LEN 4 +#define WSC_ATTRI_MAX_LEN_VERSION 1 +#define WSC_ATTRI_MAX_LEN_DEVICE_PASSWORD_ID 2 +#define WSC_ATTRI_LEN_CONFIG_METHOD 2 + +/* --------------- WFA P2P IE --------------- */ +/* P2P 4.1.1 - P2P IE format */ +#define P2P_OUI_TYPE_LEN 4 +/* == OFFSET_OF(IE_P2P_T, aucP2PAttributes[0]) */ +#define P2P_IE_OUI_HDR (ELEM_HDR_LEN + P2P_OUI_TYPE_LEN) + +/* 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 */ +#define P2P_ATTRI_MAX_LEN_LISTEN_CHANNEL 5 /* 6 */ +#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_MAXIMUM_ATTRIBUTE_LEN 251 + +/* 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.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) +/* Action frame categories (IEEE 802.11-2007, 7.3.1.11, Table 7-24) */ +#define WLAN_ACTION_SPECTRUM_MGMT 0 +#define WLAN_ACTION_QOS 1 +#define WLAN_ACTION_DLS 2 +#define WLAN_ACTION_BLOCK_ACK 3 +#define WLAN_ACTION_PUBLIC 4 +#define WLAN_ACTION_RADIO_MEASUREMENT 5 +#define WLAN_ACTION_FT 6 +#define WLAN_ACTION_HT 7 +#define WLAN_ACTION_SA_QUERY 8 +#define WLAN_ACTION_PROTECTED_DUAL 9 +#define WLAN_ACTION_WNM 10 +#define WLAN_ACTION_UNPROTECTED_WNM 11 +#define WLAN_ACTION_TDLS 12 +#define WLAN_ACTION_SELF_PROTECTED 15 +#define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */ +#define WLAN_ACTION_VENDOR_SPECIFIC 127 +#define P2P_IE_VENDOR_TYPE 0x506f9a09 +#define WFD_IE_VENDOR_TYPE 0x506f9a0a + +/* Public action codes */ +#define WLAN_PA_20_40_BSS_COEX 0 +#define WLAN_PA_VENDOR_SPECIFIC 9 +#define WLAN_PA_GAS_INITIAL_REQ 10 +#define WLAN_PA_GAS_INITIAL_RESP 11 +#define WLAN_PA_GAS_COMEBACK_REQ 12 +#define WLAN_PA_GAS_COMEBACK_RESP 13 +#define WLAN_TDLS_DISCOVERY_RESPONSE 14 + +/* P2P public action frames */ +enum ENUM_P2P_ACTION_FRAME_TYPE { + P2P_GO_NEG_REQ = 0, + P2P_GO_NEG_RESP = 1, + P2P_GO_NEG_CONF = 2, + P2P_INVITATION_REQ = 3, + P2P_INVITATION_RESP = 4, + P2P_DEV_DISC_REQ = 5, + P2P_DEV_DISC_RESP = 6, + P2P_PROV_DISC_REQ = 7, + P2P_PROV_DISC_RESP = 8 +}; + +/* --------------- WFA P2P IE and Attributes --------------- */ + +/* P2P 4.1.1 - P2P Information Element */ +struct IE_P2P { + uint8_t ucId; /* Element ID */ + uint8_t ucLength; /* Length */ + uint8_t aucOui[3]; /* OUI */ + uint8_t ucOuiType; /* OUI Type */ + uint8_t aucP2PAttributes[1]; /* P2P Attributes */ +} __KAL_ATTRIB_PACKED__; + +/* P2P 4.1.1 - General WSC Attribute */ +struct WSC_ATTRIBUTE { + uint16_t u2Id; /* Attribute ID */ + uint16_t u2Length; /* Length */ + uint8_t aucBody[1]; /* Body field */ +} __KAL_ATTRIB_PACKED__; + +/* P2P 4.1.2 - P2P Status Attribute */ +struct P2P_ATTRI_STATUS { + uint8_t ucId; /* Attribute ID */ + uint16_t u2Length; /* Length */ + uint8_t ucStatusCode; /* Status Code */ +} __KAL_ATTRIB_PACKED__; + +/* P2P 4.1.10 - Extended Listen Timing Attribute */ +struct P2P_ATTRI_EXT_LISTEN_TIMING { + uint8_t ucId; /* Attribute ID */ + uint16_t u2Length; /* Length */ + uint16_t u2AvailPeriod; /* Availability Period */ + uint16_t u2AvailInterval; /* Availability Interval */ +} __KAL_ATTRIB_PACKED__; + +/* P2P 4.2.8.2 P2P Public Action Frame Format */ +struct P2P_PUBLIC_ACTION_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* P2P Public Action Frame Body */ + uint8_t ucCategory; /* Category, 0x04 */ + uint8_t ucAction; /* Action Value, 0x09 */ + uint8_t aucOui[3]; /* 0x50, 0x6F, 0x9A */ + uint8_t ucOuiType; /* 0x09 */ + /* GO Nego Req/Rsp/Cfm, P2P Invittion Req/Rsp, */ + uint8_t ucOuiSubtype; + /* Device Discovery Req/Rsp */ + uint8_t ucDialogToken; /* Dialog Token. */ + uint8_t aucInfoElem[1]; /* P2P IE, WSC IE. */ +} __KAL_ATTRIB_PACKED__; + +/* P2P 4.2.9.1 - General Action Frame Format. */ +struct P2P_ACTION_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* P2P Action Frame Body */ + uint8_t ucCategory; /* 0x7F */ + uint8_t aucOui[3]; /* 0x50, 0x6F, 0x9A */ + uint8_t ucOuiType; /* 0x09 */ + uint8_t ucOuiSubtype; /* */ + uint8_t ucDialogToken; + uint8_t aucInfoElem[1]; +} __KAL_ATTRIB_PACKED__; + +/* P2P C.1 GAS Public Action Initial Request Frame Format */ +struct GAS_PUBLIC_ACTION_INITIAL_REQUEST_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + /* P2P Public Action Frame Body */ + uint16_t u2SeqCtrl; /* Sequence Control */ + uint8_t ucCategory; /* Category, 0x04 */ + uint8_t ucAction; /* Action Value, 0x09 */ + uint8_t ucDialogToken; /* Dialog Token. */ + uint8_t aucInfoElem[1]; /* Advertisement IE. */ +} __KAL_ATTRIB_PACKED__; + +/* P2P C.2 GAS Public Action Initial Response Frame Format */ +struct GAS_PUBLIC_ACTION_INITIAL_RESPONSE_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* P2P Public Action Frame Body */ + uint8_t ucCategory; /* Category, 0x04 */ + uint8_t ucAction; /* Action Value, 0x09 */ + uint8_t ucDialogToken; /* Dialog Token. */ + uint16_t u2StatusCode; /* Initial Response. */ + uint16_t u2ComebackDelay; + /* Initial Response. *//* In unit of TU. */ + uint8_t aucInfoElem[1]; /* Advertisement IE. */ +} __KAL_ATTRIB_PACKED__; + +/* P2P C.3-1 GAS Public Action Comeback Request Frame Format */ +struct GAS_PUBLIC_ACTION_COMEBACK_REQUEST_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* P2P Public Action Frame Body */ + uint8_t ucCategory; /* Category, 0x04 */ + uint8_t ucAction; /* Action Value, 0x09 */ + uint8_t ucDialogToken; /* Dialog Token. */ +} __KAL_ATTRIB_PACKED__; + +/* P2P C.3-2 GAS Public Action Comeback Response Frame Format */ +struct GAS_PUBLIC_ACTION_COMEBACK_RESPONSE_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* P2P Public Action Frame Body */ + uint8_t ucCategory; /* Category, 0x04 */ + uint8_t ucAction; /* Action Value, 0x09 */ + uint8_t ucDialogToken; /* Dialog Token. */ + uint16_t u2StatusCode; /* Comeback Response. */ + uint8_t ucFragmentID; /*Comeback Response. */ + uint16_t u2ComebackDelay; /* Comeback Response. */ + uint8_t aucInfoElem[1]; /* Advertisement IE. */ +} __KAL_ATTRIB_PACKED__; + +struct P2P_SD_VENDER_SPECIFIC_CONTENT { + /* Service Discovery Vendor-specific Content. */ + uint8_t ucOuiSubtype; /* 0x09 */ + uint16_t u2ServiceUpdateIndicator; + uint8_t aucServiceTLV[1]; +} __KAL_ATTRIB_PACKED__; + +struct P2P_SERVICE_REQUEST_TLV { + uint16_t u2Length; + uint8_t ucServiceProtocolType; + uint8_t ucServiceTransID; + uint8_t aucQueryData[1]; +} __KAL_ATTRIB_PACKED__; + +struct P2P_SERVICE_RESPONSE_TLV { + uint16_t u2Length; + uint8_t ucServiceProtocolType; + uint8_t ucServiceTransID; + uint8_t ucStatusCode; + uint8_t aucResponseData[1]; +} __KAL_ATTRIB_PACKED__; + +/* P2P 4.1.1 - General P2P Attribute */ +struct P2P_ATTRIBUTE { + uint8_t ucId; /* Attribute ID */ + uint16_t u2Length; /* Length */ + uint8_t aucBody[1]; /* Body field */ +} __KAL_ATTRIB_PACKED__; + +/* P2P 4.1.14 - Notice of Absence Attribute */ +struct P2P_ATTRI_NOA { + uint8_t ucId; /* Attribute ID */ + uint16_t u2Length; /* Length */ + uint8_t ucIndex; /* Index */ + uint8_t ucCTWOppPSParam; /* CTWindow and OppPS Parameters */ + uint8_t aucNoADesc[1]; /* NoA Descriptor */ +} __KAL_ATTRIB_PACKED__; + +struct NOA_DESCRIPTOR { + uint8_t ucCountType; /* Count/Type */ + uint32_t u4Duration; /* Duration */ + uint32_t u4Interval; /* Interval */ + uint32_t u4StartTime; /* Start Time */ +} __KAL_ATTRIB_PACKED__; +struct CHANNEL_ENTRY_FIELD { + uint8_t ucRegulatoryClass; /* Regulatory Class */ + uint8_t ucNumberOfChannels; /* Number Of Channels */ + uint8_t aucChannelList[1]; /* Channel List */ +} __KAL_ATTRIB_PACKED__; + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/p2p_nic.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/p2p_nic.h new file mode 100644 index 0000000000000..349c907fecf89 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/p2p_nic.h @@ -0,0 +1,116 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct EVENT_CONNECTION_STATUS *prConnectionStatus); + +void +nicRxAddP2pDevice(IN struct ADAPTER *prAdapter, + IN struct EVENT_P2P_DEV_DISCOVER_RESULT *prP2pResult, + IN uint8_t *pucRxIEBuf, + IN uint16_t u2RxIELength); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/p2p_nic_cmd_event.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/p2p_nic_cmd_event.h new file mode 100644 index 0000000000000..0978fd0c1c677 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/p2p_nic_cmd_event.h @@ -0,0 +1,122 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 + ****************************************************************************** + */ + +struct EVENT_P2P_DEV_DISCOVER_RESULT { +/* UINT_8 aucCommunicateAddr[MAC_ADDR_LEN]; // Deprecated. */ + uint8_t aucDeviceAddr[MAC_ADDR_LEN]; /* Device Address. */ + uint8_t aucInterfaceAddr[MAC_ADDR_LEN]; /* Device Address. */ + uint8_t ucDeviceCapabilityBitmap; + uint8_t ucGroupCapabilityBitmap; + uint16_t u2ConfigMethod; /* Configure Method. */ + struct P2P_DEVICE_TYPE rPriDevType; + uint8_t ucSecDevTypeNum; + struct P2P_DEVICE_TYPE arSecDevType[2]; + uint16_t u2NameLength; + uint8_t aucName[32]; + uint8_t *pucIeBuf; + uint16_t u2IELength; + uint8_t aucBSSID[MAC_ADDR_LEN]; + /* TODO: Service Information or PasswordID valid? */ +}; + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/que_mgt.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/que_mgt.h new file mode 100644 index 0000000000000..11b753954f61a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/que_mgt.h @@ -0,0 +1,1241 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/ + MT6620_WIFI_DRIVER_V2_3/include/nic/que_mgt.h#2 + */ + +/*! \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. + */ + + +#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 + ******************************************************************************* + */ +extern uint8_t g_arTdlsLink[MAXNUM_TDLS_PEER]; +extern const uint8_t *apucACI2Str[4]; +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/* Queue Manager Features */ +/* 1: Indicate the last TX packet to the FW for each burst */ +#define QM_BURST_END_INFO_ENABLED 0 +/* 1: To fairly share TX resource among active STAs */ +#define QM_FORWARDING_FAIRNESS 1 +#if defined(_HIF_SDIO) +/* 1: To adaptively adjust resource for each TC */ +#define QM_ADAPTIVE_TC_RESOURCE_CTRL 1 +/* 1: To fast adjust resource for EMPTY TC (assigned resource is 0) */ +#define QM_FAST_TC_RESOURCE_CTRL 1 +#else +/* 1: To adaptively adjust resource for each TC */ +#define QM_ADAPTIVE_TC_RESOURCE_CTRL 0 +/* 1: To fast adjust resource for EMPTY TC (assigned resource is 0) */ +#define QM_FAST_TC_RESOURCE_CTRL 0 +#endif +/* 1: To print TC resource adjustment results */ +#define QM_PRINT_TC_RESOURCE_CTRL 0 +/* 1: If pkt with SSN is missing, auto advance the RX reordering window */ +#define QM_RX_WIN_SSN_AUTO_ADVANCING 1 +/* 1: Indicate the packets falling behind to OS + * before the frame with SSN is received + */ +#define QM_RX_INIT_FALL_BEHIND_PASS 1 +/* 1: Count times of TC resource empty happened */ +#define QM_TC_RESOURCE_EMPTY_COUNTER 1 + +/* Parameters */ +/* p: Update queue lengths when p TX packets are enqueued */ +#define QM_INIT_TIME_TO_UPDATE_QUE_LEN 256 +/* s: Adjust the TC resource every s updates of queue lengths */ +#define QM_INIT_TIME_TO_ADJUST_TC_RSC 2 +/* Factor for Que Len averaging */ +#define QM_QUE_LEN_MOVING_AVE_FACTOR 3 + +#define QM_MIN_RESERVED_TC0_RESOURCE 0 +#define QM_MIN_RESERVED_TC1_RESOURCE 1 +#define QM_MIN_RESERVED_TC2_RESOURCE 0 +#define QM_MIN_RESERVED_TC3_RESOURCE 0 +/* Resource for TC4 is not adjustable */ +#define QM_MIN_RESERVED_TC4_RESOURCE 2 +#define QM_MIN_RESERVED_TC5_RESOURCE 0 + +#define QM_GUARANTEED_TC0_RESOURCE 4 +#define QM_GUARANTEED_TC1_RESOURCE 4 +#define QM_GUARANTEED_TC2_RESOURCE 9 +#define QM_GUARANTEED_TC3_RESOURCE 11 +/* Resource for TC4 is not adjustable */ +#define QM_GUARANTEED_TC4_RESOURCE 2 +#define QM_GUARANTEED_TC5_RESOURCE 4 + +#define QM_EXTRA_RESERVED_RESOURCE_WHEN_BUSY 0 + +#define QM_AVERAGE_TC_RESOURCE 6 + +#define QM_ACTIVE_TC_NUM TC_NUM + +#define QM_MGMT_QUEUED_THRESHOLD 6 +#define QM_CMD_RESERVED_THRESHOLD 4 +#define QM_MGMT_QUEUED_TIMEOUT 1000 /* ms */ + +#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 */ +/* Per-Type Queues: [0] BMCAST */ +#define NUM_OF_PER_STA_TX_QUEUES 4 +#define NUM_OF_PER_TYPE_TX_QUEUES 1 + +/* TX Queue Index */ +/* Per-Type */ +#define TX_QUEUE_INDEX_BMCAST 0 +#define TX_QUEUE_INDEX_NO_STA_REC 0 + +/* Per-STA */ +#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_NON_QOS TX_QUEUE_INDEX_AC1 + +#define QM_DEFAULT_USER_PRIORITY 0 + +#define QM_STA_FORWARD_COUNT_UNLIMITED 0xFFFFFFFF +/* Pending Forwarding Frame Threshold: + * + * A conservative estimated value, to reserve enough free MSDU resource for + * OS packet, rather than full consumed by the pending forwarding frame. + * + * Indeed, even if network subqueue is not stopped when no MSDU resource, the + * new arriving skb will be queued in prGlueInfo->rTxQueue and not be dropped. + */ +#define QM_FWD_PKT_QUE_THRESHOLD (CFG_TX_MAX_PKT_NUM >> 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 (200) +#if CFG_SUPPORT_LOWLATENCY_MODE +#define QM_RX_BA_ENTRY_MISS_TIMEOUT_MS_SHORT (50) +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + +#if CFG_M0VE_BA_TO_DRIVER +/* MQM internal control bitmap per-bit usage + * (for operations on g_prMqm->u4FlagBitmap) + */ +#define MQM_FLAG_TSPEC_NEGO_ADD_IN_PROGRESS 0 +#define MQM_FLAG_IDLE_TX_BA_TIMER_STARTED 1 +#define MQM_FLAG_IDLE_RX_BA_TIMER_STARTED 2 + +#define MQM_IDLE_RX_BA_DETECTION 0 +#define MQM_IDLE_RX_BA_CHECK_INTERVAL 5000 /* in msec */ +#define MQM_DEL_IDLE_RXBA_THRESHOLD_BK 6 +#define MQM_DEL_IDLE_RXBA_THRESHOLD_BE 12 +#define MQM_DEL_IDLE_RXBA_THRESHOLD_VI 6 +#define MQM_DEL_IDLE_RXBA_THRESHOLD_VO 6 + +/* For indicating whether the role when generating a DELBA message */ +#define DELBA_ROLE_INITIATOR TRUE +#define DELBA_ROLE_RECIPIENT FALSE + +#define MQM_SET_FLAG(_Bitmap, _flag) { (_Bitmap) |= (BIT((_flag))); } +#define MQM_CLEAR_FLAG(_Bitmap, _flag) { (_Bitmap) &= (~BIT((_flag))); } +#define MQM_CHECK_FLAG(_Bitmap, _flag) ((_Bitmap) & (BIT((_flag)))) + +enum ENUM_BA_RESET_SEL { + MAC_ADDR_TID_MATCH = 0, + MAC_ADDR_MATCH, + ALWAYS_MATCH, + MATCH_NUM +}; + +#endif +/* BW80 NSS1 rate: MCS9 433 Mbps */ +#define QM_DEQUE_PERCENT_VHT80_NSS1 23 +/* BW40 NSS1 Max rate: 200 Mbps */ +#define QM_DEQUE_PERCENT_VHT40_NSS1 10 +/* BW20 NSS1 Max rate: 86.7Mbps */ +#define QM_DEQUE_PERCENT_VHT20_NSS1 5 + +/* BW40 NSS1 Max rate: 150 Mbps (MCS9 200Mbps)*/ +#define QM_DEQUE_PERCENT_HT40_NSS1 10 +/* BW20 NSS1 Max rate: 72.2Mbps (MCS8 86.7Mbps)*/ +#define QM_DEQUE_PERCENT_HT20_NSS1 5 + +/******************************************************************************* + * 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 */ +enum ENUM_MAC_TX_QUEUE_INDEX { + 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 +}; + +struct RX_BA_ENTRY { + u_int8_t fgIsValid; + struct QUE rReOrderQue; + uint16_t u2WinStart; + uint16_t u2WinEnd; + uint16_t u2WinSize; + + /* For identifying the RX BA agreement */ + uint8_t ucStaRecIdx; + uint8_t ucTid; + + u_int8_t fgIsWaitingForPktWithSsn; + + struct TIMER rReorderBubbleTimer; + uint16_t u2FirstBubbleSn; + u_int8_t fgHasBubble; + +#if CFG_M0VE_BA_TO_DRIVER + uint8_t ucStatus; + uint8_t ucIdleCount; + uint16_t u2SnapShotSN; +#endif + /* UINT_8 ucTxBufferSize; */ + /* BOOL fgIsAcConstrain; */ + /* BOOL fgIsBaEnabled; */ +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + /* P_SW_RFB_T prMpduSwRfb; */ + uint32_t u4SeqNo; /* for statistic */ + u_int8_t fgAmsduNeedLastFrame; /* for statistic */ + uint8_t u8LastAmsduSubIdx; + u_int8_t fgIsAmsduDuplicated; + u_int8_t fgNoDrop; + uint32_t u4SNOverlapCount; +#endif +}; + +typedef uint32_t(*PFN_DEQUEUE_FUNCTION) (IN struct ADAPTER *prAdapter, + OUT struct QUE *prQue, IN uint8_t ucTC, + IN uint32_t u4CurrentQuota, + IN uint32_t *prPleCurrentQuota, IN uint32_t u4TotalQuota); + +/* The mailbox message + * (could be used for Host-To-Device or Device-To-Host Mailbox) + */ +struct MAILBOX_MSG { + /* [0]: D2HRM0R or H2DRM0R, [1]: D2HRM1R or H2DRM1R */ + uint32_t u4Msg[2]; +}; + +/* Used for adaptively adjusting TC resources */ +struct TC_RESOURCE_CTRL { + /* TC0, TC1, TC2, TC3, TC5 */ + uint32_t au4AverageQueLen[TC_NUM - 1]; +}; + +struct QUE_MGT { /* Queue Management Control Info */ + /* Per-Type Queues: [0] BMCAST or UNKNOWN-STA packets */ + struct QUE arTxQueue[NUM_OF_PER_TYPE_TX_QUEUES]; + +#if 0 + /* For TX Scheduling */ + uint8_t arRemainingTxOppt[NUM_OF_PER_STA_TX_QUEUES]; + uint8_t arCurrentTxStaIndex[NUM_OF_PER_STA_TX_QUEUES]; + +#endif + + /* Reordering Queue Parameters */ + struct RX_BA_ENTRY arRxBaTable[CFG_NUM_OF_RX_BA_AGREEMENTS]; + + /* Current number of activated + * RX BA agreements <= CFG_NUM_OF_RX_BA_AGREEMENTS + */ + uint8_t ucRxBaCount; + +#if QM_TEST_MODE + uint32_t u4PktCount; + struct ADAPTER *prAdapter; + +#if QM_TEST_FAIR_FORWARDING + uint32_t u4CurrentStaRecIndexToEnqueue; +#endif + +#endif + +#if QM_FORWARDING_FAIRNESS + /* The current resource used count + * for a STA with respect to a TC index + */ + uint32_t au4ResourceUsedCount[NUM_OF_PER_STA_TX_QUEUES]; + + /* The current serving STA with respect to a TC index */ + uint32_t au4HeadStaRecIndex[NUM_OF_PER_STA_TX_QUEUES]; + + /* The current serving BssInfo */ + uint32_t u4HeadBssInfoIndex; + + /* For TC5 only */ + u_int8_t fgGlobalQFirst; + uint32_t u4GlobalResourceUsedCount; +#endif + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + uint32_t au4AverageQueLen[TC_NUM]; + uint32_t au4CurrentTcResource[TC_NUM]; /* unit: frame */ + /* The minimum amount of resource no matter busy or idle */ + uint32_t au4MinReservedTcResource[TC_NUM]; + /* The minimum amount of resource when extremely busy */ + uint32_t au4GuaranteedTcResource[TC_NUM]; + + uint32_t u4TimeToAdjustTcResource; + uint32_t u4TimeToUpdateQueLen; + + uint32_t u4QueLenMovingAverage; + uint32_t u4ExtraReservedTcResource; + uint32_t u4ResidualTcResource; + + /* 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) */ + u_int8_t fgTcResourcePostAnnealing; + +#if QM_FAST_TC_RESOURCE_CTRL + u_int8_t fgTcResourceFastReaction; +#endif + + u_int8_t fgForceReassign; + +#endif + +#if QM_DEBUG_COUNTER + uint32_t au4QmDebugCounters[QM_DBG_CNT_NUM]; +#endif + + uint32_t u4TxAllowedStaCount; + +#if QM_TC_RESOURCE_EMPTY_COUNTER + uint32_t au4QmTcResourceEmptyCounter[MAX_BSSID_NUM][TC_NUM]; + uint32_t au4DequeueNoTcResourceCounter[TC_NUM]; + /* + * how many page count back during statistics intervals + */ + uint32_t au4QmTcResourceBackCounter[TC_NUM]; + /* + * how many page count used to TX frame during statistics intervals + */ + uint32_t au4QmTcUsedPageCounter[TC_NUM]; + uint32_t au4QmTcWantedPageCounter[TC_NUM]; + + uint32_t u4EnqueueCounter; + uint32_t u4DequeueCounter; +#endif + + uint32_t u4MaxForwardBufferCount; + + OS_SYSTIME rLastTxPktDumpTime; + u_int8_t fgIsTxResrouceControlEn; +}; + +struct EVENT_TX_ADDBA { + uint8_t ucStaRecIdx; + uint8_t ucTid; + uint8_t ucWinSize; + /* AMSDU in AMPDU is enabled or not (TID bitmap)*/ + uint8_t ucAmsduEnBitmap; + uint16_t u2SSN; + + /* + * AMSDU count/length limits by count *OR* length + * Count: MPDU count in an AMSDU shall not exceed ucMaxMpduCount + * Length: AMSDU length shall not exceed u4MaxMpduLen + */ + uint8_t + ucMaxMpduCount; /* Max MPDU count in an AMSDU */ + uint8_t aucReserved1[1]; + uint32_t u4MaxMpduLen; /* Max AMSDU length */ + + /* + * Note: If length of a packet < u4MinMpduLen then it shall not be + * aggregated in an AMSDU + */ + uint32_t + u4MinMpduLen; /* Min MPDU length to be AMSDU */ + uint8_t aucReserved2[16]; +}; + +struct EVENT_RX_ADDBA { + /* Fields not present in the received ADDBA_REQ */ + uint8_t ucStaRecIdx; + + /* Fields that are present in the received ADDBA_REQ */ + uint8_t ucDialogToken; /* Dialog Token chosen by the sender */ + uint16_t u2BAParameterSet; /* BA policy, TID, buffer size */ + uint16_t u2BATimeoutValue; + uint16_t u2BAStartSeqCtrl; /* SSN */ +}; + +struct EVENT_RX_DELBA { + /* Fields not present in the received ADDBA_REQ */ + uint8_t ucStaRecIdx; + uint8_t ucTid; + uint8_t aucReserved[2]; +}; + +struct EVENT_BSS_ABSENCE_PRESENCE { + /* Event Body */ + uint8_t ucBssIndex; + uint8_t ucIsAbsent; + uint8_t ucBssFreeQuota; + uint8_t aucReserved[1]; +}; + +struct EVENT_STA_CHANGE_PS_MODE { + /* Event Body */ + uint8_t ucStaRecIdx; + uint8_t ucIsInPs; + uint8_t ucUpdateMode; + uint8_t ucFreeQuota; +}; + +/* The free quota is used by PS only now */ +/* The event may be used by per STA flow conttrol in general */ +struct EVENT_STA_UPDATE_FREE_QUOTA { + /* Event Body */ + uint8_t ucStaRecIdx; + uint8_t ucUpdateMode; + uint8_t ucFreeQuota; + uint8_t aucReserved[1]; +}; + +struct EVENT_CHECK_REORDER_BUBBLE { + /* Event Body */ + uint8_t ucStaRecIdx; + uint8_t ucTid; +}; + +/* WMM-2.2.1 WMM Information Element */ +struct IE_WMM_INFO { + uint8_t ucId; /* Element ID */ + uint8_t ucLength; /* Length */ + uint8_t aucOui[3]; /* OUI */ + uint8_t ucOuiType; /* OUI Type */ + uint8_t ucOuiSubtype; /* OUI Subtype */ + uint8_t ucVersion; /* Version */ + uint8_t ucQosInfo; /* QoS Info field */ + uint8_t ucDummy[3]; /* Dummy for pack */ +}; + +struct WMM_AC_PARAM { + uint8_t ucAciAifsn; + uint8_t ucEcw; + uint16_t u2TxopLimit; +}; + +/* WMM-2.2.2 WMM Parameter Element */ +struct IE_WMM_PARAM { + uint8_t ucId; /* Element ID */ + uint8_t ucLength; /* Length */ + + /* IE Body */ + uint8_t aucOui[3]; /* OUI */ + uint8_t ucOuiType; /* OUI Type */ + uint8_t ucOuiSubtype; /* OUI Subtype */ + uint8_t ucVersion; /* Version */ + + /* WMM IE Body */ + uint8_t ucQosInfo; /* QoS Info field */ + uint8_t ucReserved; + + /* AC Parameters */ +#if 1 + struct WMM_AC_PARAM arAcParam[4]; +#else + uint8_t ucAciAifsn_BE; + uint8_t ucEcw_BE; + uint8_t aucTxopLimit_BE[2]; + + uint8_t ucAciAifsn_BG; + uint8_t ucEcw_BG; + uint8_t aucTxopLimit_BG[2]; + + uint8_t ucAciAifsn_VI; + uint8_t ucEcw_VI; + uint8_t aucTxopLimit_VI[2]; + + uint8_t ucAciAifsn_VO; + uint8_t ucEcw_VO; + uint8_t aucTxopLimit_VO[2]; +#endif +}; + +struct IE_WMM_TSPEC { + uint8_t ucId; /* Element ID */ + uint8_t ucLength; /* Length */ + uint8_t aucOui[3]; /* OUI */ + uint8_t ucOuiType; /* OUI Type */ + uint8_t ucOuiSubtype; /* OUI Subtype */ + uint8_t ucVersion; /* Version */ + /* WMM TSPEC body */ + uint8_t aucTsInfo[3]; /* TS Info */ + /* Note: Utilize PARAM_QOS_TSPEC to fill (memory copy) */ + uint8_t aucTspecBodyPart[1]; +}; + +struct IE_WMM_HDR { + uint8_t ucId; /* Element ID */ + uint8_t ucLength; /* Length */ + uint8_t aucOui[3]; /* OUI */ + uint8_t ucOuiType; /* OUI Type */ + uint8_t ucOuiSubtype; /* OUI Subtype */ + uint8_t ucVersion; /* Version */ + uint8_t aucBody[1]; /* IE body */ +}; + +struct AC_QUE_PARMS { + uint16_t u2CWmin; /*!< CWmin */ + uint16_t u2CWmax; /*!< CWmax */ + uint16_t u2TxopLimit; /*!< TXOP limit */ + uint16_t u2Aifsn; /*!< AIFSN */ + uint8_t ucGuradTime; /*!< GuardTime for STOP/FLUSH. */ + uint8_t ucIsACMSet; +}; + +#if (CFG_SUPPORT_802_11AX == 1) +/* MU EDCA parameters for each AC */ +struct _CMD_MU_EDCA_PARAMS_T { + uint8_t ucECWmin; /* CWmin */ + uint8_t ucECWmax; /* CWmax */ + uint8_t ucAifsn; /* AIFSN */ + uint8_t ucIsACMSet; + uint8_t ucMUEdcaTimer; + uint8_t aucPadding[3]; +}; +#endif + +/* WMM ACI (AC index) */ +enum ENUM_WMM_ACI { + WMM_AC_BE_INDEX = 0, + WMM_AC_BK_INDEX, + WMM_AC_VI_INDEX, + WMM_AC_VO_INDEX, + WMM_AC_INDEX_NUM +}; + +/* Used for CMD Queue Operation */ +enum ENUM_FRAME_ACTION { + FRAME_ACTION_DROP_PKT = 0, + FRAME_ACTION_QUEUE_PKT, + FRAME_ACTION_TX_PKT, + FRAME_ACTION_NUM +}; + +enum ENUM_FRAME_TYPE_IN_CMD_Q { + FRAME_TYPE_802_1X = 0, + FRAME_TYPE_MMPDU, + FRAME_TYPE_NUM +}; + +enum ENUM_FREE_QUOTA_MODET { + FREE_QUOTA_UPDATE_MODE_INIT = 0, + FREE_QUOTA_UPDATE_MODE_OVERWRITE, + FREE_QUOTA_UPDATE_MODE_INCREASE, + FREE_QUOTA_UPDATE_MODE_DECREASE +}; + +struct CMD_UPDATE_WMM_PARMS { + struct AC_QUE_PARMS arACQueParms[AC_NUM]; + uint8_t ucBssIndex; + uint8_t fgIsQBSS; + uint8_t ucWmmSet; + uint8_t aucReserved; +}; + +#if (CFG_SUPPORT_802_11AX == 1) +struct _CMD_MQM_UPDATE_MU_EDCA_PARMS_T { + /* DWORD_0 - Common Part */ + uint8_t ucCmdVer; + uint8_t aucPadding0[1]; + uint16_t u2CmdLen; /* Cmd size including common part and body */ + + /* DWORD_1 afterwards - Command Body */ + uint8_t ucBssIndex; + uint8_t fgIsQBSS; + uint8_t ucWmmSet; + uint8_t aucPadding1[1]; + + struct _CMD_MU_EDCA_PARAMS_T arMUEdcaParams[AC_NUM]; + uint8_t aucPadding[32]; +}; +#endif + +struct CMD_TX_AMPDU { + u_int8_t fgEnable; + uint8_t aucReserved[3]; +}; + +struct CMD_ADDBA_REJECT { + u_int8_t fgEnable; + uint8_t aucReserved[3]; +}; + +#if CFG_M0VE_BA_TO_DRIVER +/* The status of an TX/RX BA entry in FW + * (NEGO means the negotiation process is in progress) + */ +enum ENUM_BA_ENTRY_STATUS { + BA_ENTRY_STATUS_INVALID = 0, + BA_ENTRY_STATUS_NEGO, + BA_ENTRY_STATUS_ACTIVE, + BA_ENTRY_STATUS_DELETING +}; +#endif + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +#define QM_TX_SET_NEXT_MSDU_INFO(_prMsduInfoPreceding, _prMsduInfoNext) \ + ((((_prMsduInfoPreceding)->rQueEntry).prNext) = \ + (struct QUE_ENTRY *)(_prMsduInfoNext)) + +#define QM_TX_SET_NEXT_SW_RFB(_prSwRfbPreceding, _prSwRfbNext) \ + ((((_prSwRfbPreceding)->rQueEntry).prNext) = \ + (struct QUE_ENTRY *)(_prSwRfbNext)) + +#define QM_TX_GET_NEXT_MSDU_INFO(_prMsduInfo) \ + ((struct MSDU_INFO *)(((_prMsduInfo)->rQueEntry).prNext)) + +#define QM_RX_SET_NEXT_SW_RFB(_prSwRfbPreceding, _prSwRfbNext) \ + ((((_prSwRfbPreceding)->rQueEntry).prNext) = \ + (struct QUE_ENTRY *)(_prSwRfbNext)) + +#define QM_RX_GET_NEXT_SW_RFB(_prSwRfb) \ + ((struct SW_RFB *)(((_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) + +#if 0 +#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); \ + } +#else +#define QM_TX_SET_MSDU_INFO_FOR_DATA_PACKET( \ + _prMsduInfo, \ + _ucTC, \ + _ucPacketType, \ + _ucFormatID, \ + _fgIs802_1x, \ + _fgIs802_11, \ + _ucPsForwardingType \ + ) \ + { \ + ASSERT(_prMsduInfo); \ + (_prMsduInfo)->ucTC = (_ucTC); \ + (_prMsduInfo)->ucPacketType = (_ucPacketType); \ + (_prMsduInfo)->ucFormatID = (_ucFormatID); \ + (_prMsduInfo)->fgIs802_1x = (_fgIs802_1x); \ + (_prMsduInfo)->fgIs802_11 = (_fgIs802_11); \ + (_prMsduInfo)->ucPsForwardingType = (_ucPsForwardingType); \ + } +#endif + +#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)] >> \ + (_prAdapter)->rQM.u4QueLenMovingAverage)) +#endif + +#define WMM_IE_OUI_TYPE(fp) (((struct IE_WMM_HDR *)(fp))->ucOuiType) +#define WMM_IE_OUI_SUBTYPE(fp) (((struct IE_WMM_HDR *)(fp))->ucOuiSubtype) +#define WMM_IE_OUI(fp) (((struct IE_WMM_HDR *)(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 struct ADAPTER *prAdapter, + IN u_int8_t isTxResrouceControlEn); + +#if QM_TEST_MODE +void qmTestCases(IN struct ADAPTER *prAdapter); +#endif + +void qmActivateStaRec(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +void qmDeactivateStaRec(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +void qmUpdateStaRec(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +/*----------------------------------------------------------------------------*/ +/* TX-Related Queue Management */ +/*----------------------------------------------------------------------------*/ + +struct MSDU_INFO *qmFlushTxQueues(IN struct ADAPTER + *prAdapter); + +struct MSDU_INFO *qmFlushStaTxQueues(IN struct ADAPTER + *prAdapter, IN uint32_t u4StaRecIdx); + +struct MSDU_INFO *qmEnqueueTxPackets(IN struct ADAPTER + *prAdapter, IN struct MSDU_INFO *prMsduInfoListHead); + +struct MSDU_INFO *qmDequeueTxPackets(IN struct ADAPTER + *prAdapter, IN struct TX_TCQ_STATUS *prTcqStatus); + +#if CFG_SUPPORT_MULTITHREAD +struct MSDU_INFO *qmDequeueTxPacketsMthread( + IN struct ADAPTER *prAdapter, + IN struct TX_TCQ_STATUS *prTcqStatus); + +u_int8_t +qmAdjustTcQuotasMthread(IN struct ADAPTER *prAdapter, + OUT struct TX_TCQ_ADJUST *prTcqAdjust, + IN struct TX_TCQ_STATUS *prTcqStatus); +#endif + +u_int8_t qmAdjustTcQuotas(IN struct ADAPTER *prAdapter, + OUT struct TX_TCQ_ADJUST *prTcqAdjust, + IN struct TX_TCQ_STATUS *prTcqStatus); + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL +void qmReassignTcResource(IN struct ADAPTER *prAdapter); + +void qmUpdateAverageTxQueLen(IN struct ADAPTER *prAdapter); + +void qmDoAdaptiveTcResourceCtrl(IN struct ADAPTER + *prAdapter); + +void qmCheckForFastTcResourceCtrl(IN struct ADAPTER + *prAdapter, IN uint8_t ucTc); + +#endif + +void qmDetermineStaRecIndex(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +uint32_t qmDequeueTxPacketsFromPerStaQueues(IN struct ADAPTER + *prAdapter, OUT struct QUE *prQue, IN uint8_t ucTC, + IN uint32_t + u4CurrentQuota, + IN uint32_t + *prPleCurrentQuota, IN uint32_t u4TotalQuota); + +void qmDequeueTxPacketsFromPerTypeQueues(IN struct ADAPTER + *prAdapter, OUT struct QUE *prQue, IN uint8_t ucTC, + IN uint32_t + u4CurrentQuota, + IN uint32_t + *prPleCurrentQuota, IN uint32_t u4TotalQuota); + +uint32_t qmDequeueTxPacketsFromGlobalQueue(IN struct ADAPTER + *prAdapter, OUT struct QUE *prQue, IN uint8_t ucTC, + IN uint32_t + u4CurrentQuota, + IN uint32_t + *prPleCurrentQuota, IN uint32_t u4TotalQuota); + +void qmSetStaRecTxAllowed(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, IN u_int8_t fgIsTxAllowed); + +uint32_t gmGetDequeueQuota( + IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct BSS_INFO *prBssInfo, + IN uint32_t u4TotalQuota +); + +/*----------------------------------------------------------------------------*/ +/* RX-Related Queue Management */ +/*----------------------------------------------------------------------------*/ + +void qmInitRxQueues(IN struct ADAPTER *prAdapter); + +struct SW_RFB *qmFlushRxQueues(IN struct ADAPTER + *prAdapter); + +struct QUE *qmDetermineStaTxQueue(IN struct ADAPTER + *prAdapter, IN struct MSDU_INFO *prMsduInfo, + IN uint8_t ucActiveTs, OUT uint8_t *pucTC); + +void qmSetTxPacketDescTemplate(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +struct SW_RFB *qmHandleRxPackets(IN struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfbListHead); + +void qmProcessPktWithReordering(IN struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfb, + OUT struct QUE *prReturnedQue); + +void qmProcessBarFrame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, OUT struct QUE *prReturnedQue); + +void qmInsertReorderPkt(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN struct RX_BA_ENTRY *prReorderQueParm, + OUT struct QUE *prReturnedQue); + +void qmInsertFallWithinReorderPkt(IN struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfb, + IN struct RX_BA_ENTRY *prReorderQueParm, + OUT struct QUE *prReturnedQue); + +void qmInsertFallAheadReorderPkt(IN struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfb, + IN struct RX_BA_ENTRY *prReorderQueParm, + OUT struct QUE *prReturnedQue); + +void qmPopOutReorderPkt(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, OUT struct QUE *prReturnedQue, + IN enum ENUM_RX_STATISTIC_COUNTER eRxCounter); + +void qmPopOutDueToFallWithin(IN struct ADAPTER *prAdapter, + IN struct RX_BA_ENTRY *prReorderQueParm, + OUT struct QUE *prReturnedQue); + +void qmPopOutDueToFallAhead(IN struct ADAPTER *prAdapter, + IN struct RX_BA_ENTRY *prReorderQueParm, + OUT struct QUE *prReturnedQue); + +void qmHandleReorderBubbleTimeout(IN struct ADAPTER + *prAdapter, IN unsigned long ulParamPtr); + +void qmHandleEventCheckReorderBubble(IN struct ADAPTER *prAdapter, + struct RX_BA_ENTRY *prReorderQueParm); + +void qmHandleMailboxRxMessage(IN struct MAILBOX_MSG + prMailboxRxMsg); + +u_int8_t qmCompareSnIsLessThan(IN uint32_t u4SnLess, + IN uint32_t u4SnGreater); + +void qmHandleEventTxAddBa(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); + +void qmHandleEventRxAddBa(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); + +void qmHandleEventRxDelBa(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); + +struct RX_BA_ENTRY *qmLookupRxBaEntry(IN struct ADAPTER + *prAdapter, IN uint8_t ucStaRecIdx, IN uint8_t ucTid); + +u_int8_t +qmAddRxBaEntry(IN struct ADAPTER *prAdapter, + IN uint8_t ucStaRecIdx, IN uint8_t ucTid, + IN uint16_t u2WinStart, IN uint16_t + u2WinSize); + +void qmDelRxBaEntry(IN struct ADAPTER *prAdapter, + IN uint8_t ucStaRecIdx, IN uint8_t ucTid, + IN u_int8_t fgFlushToHost); + +u_int8_t qmIsIndependentPkt(IN struct SW_RFB *prSwRfb); + +void mqmProcessAssocRsp(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, IN uint8_t *pucIE, + IN uint16_t u2IELength); + +void mqmProcessBcn(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, IN uint8_t *pucIE, + IN uint16_t u2IELength); + +#if (CFG_SUPPORT_802_11AX == 1) +u_int8_t mqmCompareMUEdcaParameters( + struct _IE_MU_EDCA_PARAM_T *prIeMUEdcaParam, + struct BSS_INFO *prBssInfo); + +u_int8_t +mqmParseMUEdcaParams( + struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb, + u_int8_t *pucIE, + u_int16_t u2IELength, + u_int8_t fgForceOverride); +#endif + +u_int8_t +mqmParseEdcaParameters(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, IN uint8_t *pucIE, + IN uint16_t u2IELength, IN + u_int8_t fgForceOverride); + +u_int8_t mqmCompareEdcaParameters(IN struct IE_WMM_PARAM + *prIeWmmParam, IN struct BSS_INFO *prBssInfo); + +void mqmFillAcQueParam(IN struct IE_WMM_PARAM *prIeWmmParam, + IN uint32_t u4AcOffset, + OUT struct AC_QUE_PARMS *prAcQueParams); + +void mqmProcessScanResult(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prScanResult, + OUT struct STA_RECORD *prStaRec); + +uint32_t mqmFillWmmInfoIE(uint8_t *pucOutBuf, + u_int8_t fgSupportUAPSD, uint8_t ucBmpDeliveryAC, + uint8_t ucBmpTriggerAC, uint8_t ucUapsdSp); + +uint32_t mqmGenerateWmmInfoIEByStaRec(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, struct STA_RECORD *prStaRec, + uint8_t * + pucOutBuf); + +void mqmGenerateWmmInfoIE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +void mqmGenerateWmmParamIE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +#if CFG_SUPPORT_TDLS + +uint32_t mqmGenerateWmmParamIEByParam(struct ADAPTER + *prAdapter, struct BSS_INFO *prBssInfo, uint8_t *pOutBuf); +#endif + +enum ENUM_FRAME_ACTION qmGetFrameAction(IN struct ADAPTER + *prAdapter, + IN uint8_t ucBssIndex, IN uint8_t ucStaRecIdx, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_FRAME_TYPE_IN_CMD_Q eFrameType, + IN uint16_t u2FrameLength); + +void qmHandleEventBssAbsencePresence(IN struct ADAPTER + *prAdapter, IN struct WIFI_EVENT *prEvent); + +void qmHandleEventStaChangePsMode(IN struct ADAPTER + *prAdapter, IN struct WIFI_EVENT *prEvent); + +void mqmProcessAssocReq(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, IN uint8_t *pucIE, + IN uint16_t u2IELength); + +void qmHandleEventStaUpdateFreeQuota(IN struct ADAPTER + *prAdapter, IN struct WIFI_EVENT *prEvent); + +void +qmUpdateFreeQuota(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, IN uint8_t ucUpdateMode, + IN uint8_t ucFreeQuota); + +void qmFreeAllByBssIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +uint32_t qmGetRxReorderQueuedBufferCount(IN struct ADAPTER + *prAdapter); + +uint32_t qmDumpQueueStatus(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, IN uint32_t u4MaxLen); + +#if CFG_M0VE_BA_TO_DRIVER +void +mqmSendDelBaFrame(IN struct ADAPTER *prAdapter, + IN u_int8_t fgIsInitiator, IN struct STA_RECORD *prStaRec, + IN uint32_t u4Tid, IN + uint32_t u4ReasonCode); + +uint32_t +mqmCallbackAddBaRspSent(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +void mqmTimeoutCheckIdleRxBa(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr); + +void +mqmRxModifyBaEntryStatus(IN struct ADAPTER *prAdapter, + IN struct RX_BA_ENTRY *prRxBaEntry, + IN enum ENUM_BA_ENTRY_STATUS eStatus); + +void mqmHandleAddBaReq(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +void mqmHandleBaActionFrame(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); +#endif + +void qmResetTcControlResource(IN struct ADAPTER *prAdapter); +void qmAdjustTcQuotaPle(IN struct ADAPTER *prAdapter, + OUT struct TX_TCQ_ADJUST *prTcqAdjust, + IN struct TX_TCQ_STATUS *prTcqStatus); + +#if ARP_MONITER_ENABLE +void qmDetectArpNoResponse(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); +void qmResetArpDetect(void); +void qmHandleRxArpPackets(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); +void qmHandleRxDhcpPackets(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); +#endif +#ifdef CFG_SUPPORT_REPLAY_DETECTION +u_int8_t qmHandleRxReplay(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); +#endif + +u_int8_t +qmIsNoDropPacket(IN struct ADAPTER *prAdapter, IN struct SW_RFB *prSwRfb); + +void qmMoveStaTxQueue(struct STA_RECORD *prSrcStaRec, + struct STA_RECORD *prDstStaRec); +void qmHandleDelTspec(struct ADAPTER *prAdapter, struct STA_RECORD *prStaRec, + enum ENUM_ACI eAci); +void qmReleaseCHAtFinishedDhcp(struct ADAPTER *prAdapter, + struct TIMER *prTimer, + uint8_t ucBssIndex); +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#if QM_TEST_MODE +extern struct QUE_MGT g_rQM; +#endif +extern const uint8_t aucTid2ACI[TX_DESC_TID_NUM]; +extern const uint8_t aucACI2TxQIdx[WMM_AC_INDEX_NUM]; +extern const uint8_t arNetwork2TcResource[MAX_BSSID_NUM + + 1][NET_TC_NUM]; + +#endif /* _QUE_MGT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/wlan_def.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/wlan_def.h new file mode 100644 index 0000000000000..a25ec73dec310 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic/wlan_def.h @@ -0,0 +1,1199 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 + * + */ + + +#ifndef _WLAN_DEF_H +#define _WLAN_DEF_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +/* disconnect reason */ +#define DISCONNECT_REASON_CODE_RESERVED 0 +#define DISCONNECT_REASON_CODE_RADIO_LOST 1 +#define DISCONNECT_REASON_CODE_DEAUTHENTICATED 2 +#define DISCONNECT_REASON_CODE_DISASSOCIATED 3 +#define DISCONNECT_REASON_CODE_NEW_CONNECTION 4 +#define DISCONNECT_REASON_CODE_REASSOCIATION 5 +#define DISCONNECT_REASON_CODE_ROAMING 6 +#define DISCONNECT_REASON_CODE_CHIPRESET 7 +#define DISCONNECT_REASON_CODE_LOCALLY 8 +#define DISCONNECT_REASON_CODE_RADIO_LOST_TX_ERR 9 + +/* 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 TX_MODE_VHT 0x100 +#define TX_MODE_HE_SU 0x200 +#define TX_MODE_HE_ER_SU 0x240 +#define TX_MODE_HE_TB 0X280 + +#define RATE_CCK_SHORT_PREAMBLE 0x4 + +#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_MCS8 0x8 +#define PHY_RATE_MCS9 0x9 +#define PHY_RATE_MCS32 0x20 + +#define PHY_RATE_DCM 0x10 +#define PHY_RATE_TONE_106 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 | PHY_RATE_6M) +#define RATE_OFDM_9M (TX_MODE_OFDM | PHY_RATE_9M) +#define RATE_OFDM_12M (TX_MODE_OFDM | PHY_RATE_12M) +#define RATE_OFDM_18M (TX_MODE_OFDM | PHY_RATE_18M) +#define RATE_OFDM_24M (TX_MODE_OFDM | PHY_RATE_24M) +#define RATE_OFDM_36M (TX_MODE_OFDM | PHY_RATE_36M) +#define RATE_OFDM_48M (TX_MODE_OFDM | PHY_RATE_48M) +#define RATE_OFDM_54M (TX_MODE_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_VHT_MCS_0 (TX_MODE_VHT | PHY_RATE_MCS0) +#define RATE_VHT_MCS_1 (TX_MODE_VHT | PHY_RATE_MCS1) +#define RATE_VHT_MCS_2 (TX_MODE_VHT | PHY_RATE_MCS2) +#define RATE_VHT_MCS_3 (TX_MODE_VHT | PHY_RATE_MCS3) +#define RATE_VHT_MCS_4 (TX_MODE_VHT | PHY_RATE_MCS4) +#define RATE_VHT_MCS_5 (TX_MODE_VHT | PHY_RATE_MCS5) +#define RATE_VHT_MCS_6 (TX_MODE_VHT | PHY_RATE_MCS6) +#define RATE_VHT_MCS_7 (TX_MODE_VHT | PHY_RATE_MCS7) +#define RATE_VHT_MCS_8 (TX_MODE_VHT | PHY_RATE_MCS8) +#define RATE_VHT_MCS_9 (TX_MODE_VHT | PHY_RATE_MCS9) + +#define RATE_HE_ER_DCM_MCS_0 (TX_MODE_HE_ER_SU | PHY_RATE_DCM) +#define RATE_HE_ER_TONE_106_MCS_0 (TX_MODE_HE_ER_SU | PHY_RATE_TONE_106) + +#define RATE_NSTS_MASK BITS(9, 10) +#define RATE_NSTS_OFFSET 9 +#define RATE_TX_MODE_MASK BITS(6, 8) +#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(2) +#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 27 + +/* PHY TYPE bit definitions */ +/* HR/DSSS PHY (clause 18) */ +#define PHY_TYPE_BIT_HR_DSSS BIT(PHY_TYPE_HR_DSSS_INDEX) +/* ERP PHY (clause 19) */ +#define PHY_TYPE_BIT_ERP BIT(PHY_TYPE_ERP_INDEX) +/* OFDM 5 GHz PHY (clause 17) */ +#define PHY_TYPE_BIT_OFDM BIT(PHY_TYPE_OFDM_INDEX) +/* HT PHY (clause 20) */ +#define PHY_TYPE_BIT_HT BIT(PHY_TYPE_HT_INDEX) +/* HT PHY (clause 22) */ +#define PHY_TYPE_BIT_VHT BIT(PHY_TYPE_VHT_INDEX) + +#if (CFG_SUPPORT_802_11AX == 1) +/* HE PHY */ +#define PHY_TYPE_BIT_HE BIT(PHY_TYPE_HE_INDEX) +#endif + +/* 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) + +#define PHY_TYPE_SET_802_11AC (PHY_TYPE_BIT_VHT) + +#define PHY_TYPE_SET_802_11ANAC (PHY_TYPE_BIT_OFDM | \ + PHY_TYPE_BIT_HT | \ + PHY_TYPE_BIT_VHT) + +#define PHY_TYPE_SET_802_11ABGNAC (PHY_TYPE_BIT_OFDM | \ + PHY_TYPE_BIT_HR_DSSS | \ + PHY_TYPE_BIT_ERP | \ + PHY_TYPE_BIT_HT | \ + PHY_TYPE_BIT_VHT) + +#if (CFG_SUPPORT_802_11AX == 1) +#define PHY_TYPE_SET_802_11AX (PHY_TYPE_BIT_HE) + +#define PHY_TYPE_SET_802_11ABGNACAX (PHY_TYPE_BIT_OFDM | \ + PHY_TYPE_BIT_HR_DSSS | \ + PHY_TYPE_BIT_ERP | \ + PHY_TYPE_BIT_HT | \ + PHY_TYPE_BIT_VHT | \ + PHY_TYPE_BIT_HE) +#endif /* CFG_SUPPORT_802_11AX == 1 */ + +/* Rate set bit definitions */ +#define RATE_SET_BIT_1M BIT(RATE_1M_SW_INDEX) /* Bit 0: 1M */ +#define RATE_SET_BIT_2M BIT(RATE_2M_SW_INDEX) /* Bit 1: 2M */ +#define RATE_SET_BIT_5_5M BIT(RATE_5_5M_SW_INDEX) /* Bit 2: 5.5M */ +#define RATE_SET_BIT_11M BIT(RATE_11M_SW_INDEX) /* Bit 3: 11M */ +#define RATE_SET_BIT_22M BIT(RATE_22M_SW_INDEX) /* Bit 4: 22M */ +#define RATE_SET_BIT_33M BIT(RATE_33M_SW_INDEX) /* Bit 5: 33M */ +#define RATE_SET_BIT_6M BIT(RATE_6M_SW_INDEX) /* Bit 6: 6M */ +#define RATE_SET_BIT_9M BIT(RATE_9M_SW_INDEX) /* Bit 7: 9M */ +#define RATE_SET_BIT_12M BIT(RATE_12M_SW_INDEX) /* Bit 8: 12M */ +#define RATE_SET_BIT_18M BIT(RATE_18M_SW_INDEX) /* Bit 9: 18M */ +#define RATE_SET_BIT_24M BIT(RATE_24M_SW_INDEX) /* Bit 10: 24M */ +#define RATE_SET_BIT_36M BIT(RATE_36M_SW_INDEX) /* Bit 11: 36M */ +#define RATE_SET_BIT_48M BIT(RATE_48M_SW_INDEX) /* Bit 12: 48M */ +#define RATE_SET_BIT_54M BIT(RATE_54M_SW_INDEX) /* Bit 13: 54M */ +/* Bit 14: BSS Selector */ +#define RATE_SET_BIT_VHT_PHY BIT(RATE_VHT_PHY_SW_INDEX) +/* Bit 15: BSS Selector */ +#define RATE_SET_BIT_HT_PHY BIT(RATE_HT_PHY_SW_INDEX) + +/* 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_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 +/* Available AID: 1 ~ 20(STA_REC_NUM) */ +#define MAX_ASSOC_ID (CFG_STA_REC_NUM) +/* NOTE(Kevin): Used in auth.c */ +#define MAX_DEAUTH_INFO_COUNT 4 +/* The minimum interval if continuously send Deauth Frame */ +#define MIN_DEAUTH_INTERVAL_MSEC 500 + +/* 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) +#define AUTH_TYPE_SAE \ + BIT(AUTH_ALGORITHM_NUM_SAE) + +/* Authentication Retry Limit */ +#define TX_AUTH_ASSOCI_RETRY_LIMIT 2 +#define TX_AUTH_ASSOCI_RETRY_LIMIT_FOR_ROAMING 1 + +/* WMM-2.2.1 WMM Information Element */ +#define ELEM_MAX_LEN_WMM_INFO 7 + +/* */ +#define RA_ER_Disable 0 +#define RA_DCM 1 +#define RA_ER_106 2 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +enum ENUM_HW_BSSID { + BSSID_0 = 0, + BSSID_1, + BSSID_2, + BSSID_3, + BSSID_NUM +}; + +enum ENUM_HW_MAC_ADDR { + MAC_ADDR_0 = 0, + MAC_ADDR_1, + MAC_ADDR_NUM +}; + +enum ENUM_HW_OP_MODE { + HW_OP_MODE_STA = 0, + HW_OP_MODE_AP, + HW_OP_MODE_ADHOC, + HW_OP_MODE_NUM +}; + +enum ENUM_TSF { + ENUM_LOCAL_TSF_0, + ENUM_LOCAL_TSF_1, + ENUM_LOCAL_TSF_NUM +}; + +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 +}; + +enum ENUM_AC { + AC0 = 0, + AC1, + AC2, + AC3, + AC_NUM +}; + +enum ENUM_NETWORK_TYPE { + NETWORK_TYPE_AIS, + NETWORK_TYPE_P2P, + NETWORK_TYPE_BOW, + NETWORK_TYPE_MBSS, + NETWORK_TYPE_NUM +}; + +/* The Type of STA Type. */ +enum ENUM_STA_TYPE_INDEX { + STA_TYPE_LEGACY_INDEX = 0, + STA_TYPE_P2P_INDEX, + STA_TYPE_BOW_INDEX, + STA_TYPE_INDEX_NUM +}; + +enum ENUM_PHY_MODE_TYPE { + PHY_MODE_CCK = 0, + PHY_MODE_OFDM = 1, + PHY_MODE_HT20 = 2, + PHY_MODE_HT40 = 3, + PHY_MODE_VHT20 = 4, + PHY_MODE_VHT40 = 5, + PHY_MODE_VHT80 = 6, + PHY_MODE_VHT160 = 7, + PHY_MODE_SU20 = 8, + PHY_MODE_SU40 = 9, + PHY_MODE_SU80 = 10, + PHY_MODE_RU26 = 11, + PHY_MODE_RU52 = 12, + PHY_MODE_RU106 = 13, + PHY_MODE_RU242 = 14, + PHY_MODE_RU484 = 15, + PHY_MODE_RU996 = 16, + PHY_MODE_TYPE_NUM +}; + + +#define STA_ROLE_BASE_INDEX 4 + +enum ENUM_STA_ROLE_INDEX { + STA_ROLE_ADHOC_INDEX = STA_ROLE_BASE_INDEX, /* 4 */ + STA_ROLE_CLIENT_INDEX, + STA_ROLE_AP_INDEX, + STA_ROLE_DLS_INDEX, + STA_ROLE_MAX_INDEX +}; + +#define STA_ROLE_INDEX_NUM (STA_ROLE_MAX_INDEX - STA_ROLE_BASE_INDEX) + +/* The Power State of a specific Network */ +enum ENUM_PWR_STATE { + PWR_STATE_IDLE = 0, + PWR_STATE_ACTIVE, + PWR_STATE_PS, + PWR_STATE_NUM +}; + +enum ENUM_PHY_TYPE_INDEX { + /* 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_VHT_INDEX, /* HT PHY (clause 22) */ +#if (CFG_SUPPORT_802_11AX == 1) + PHY_TYPE_HE_INDEX, /* HE PHY */ +#endif /* CFG_SUPPORT_802_11AX == 1 */ + + PHY_TYPE_INDEX_NUM /* 6 */ +}; + +enum ENUM_SW_RATE_INDEX { + RATE_1M_SW_INDEX = 0, /* 1M */ + RATE_2M_SW_INDEX, /* 2M */ + RATE_5_5M_SW_INDEX, /* 5.5M */ + RATE_11M_SW_INDEX, /* 11M */ + RATE_22M_SW_INDEX, /* 22M */ + RATE_33M_SW_INDEX, /* 33M */ + RATE_6M_SW_INDEX, /* 6M */ + RATE_9M_SW_INDEX, /* 9M */ + RATE_12M_SW_INDEX, /* 12M */ + RATE_18M_SW_INDEX, /* 18M */ + RATE_24M_SW_INDEX, /* 24M */ + RATE_36M_SW_INDEX, /* 36M */ + RATE_48M_SW_INDEX, /* 48M */ + RATE_54M_SW_INDEX, /* 54M */ + RATE_VHT_PHY_SW_INDEX, /* BSS Selector - VHT PHY */ + RATE_HT_PHY_SW_INDEX, /* BSS Selector - HT PHY */ + RATE_NUM_SW /* 16 */ +}; + +enum ENUM_CCK_RATE_INDEX { + RATE_1M_INDEX = 0, /* 1M */ + RATE_2M_INDEX, /* 2M */ + RATE_5_5M_INDEX, /* 5.5M */ + RATE_11M_INDEX, /* 11M */ + CCK_RATE_NUM /* 4 */ +}; + +enum ENUM_OFDM_RATE_INDEX { + RATE_6M_INDEX = 0, /* 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 */ + OFDM_RATE_NUM /* 8 */ +}; + +enum ENUM_HT_RATE_INDEX { + HT_RATE_MCS32_INDEX = 0, + HT_RATE_MCS0_INDEX, + 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_MCS8_INDEX, + HT_RATE_MCS9_INDEX, + HT_RATE_MCS10_INDEX, + HT_RATE_MCS11_INDEX, + HT_RATE_MCS12_INDEX, + HT_RATE_MCS13_INDEX, + HT_RATE_MCS14_INDEX, + HT_RATE_MCS15_INDEX, + HT_RATE_NUM /* 16 */ +}; + +enum ENUM_VHT_RATE_INDEX { + VHT_RATE_MCS0_INDEX = 0, + VHT_RATE_MCS1_INDEX, + VHT_RATE_MCS2_INDEX, + VHT_RATE_MCS3_INDEX, + VHT_RATE_MCS4_INDEX, + VHT_RATE_MCS5_INDEX, + VHT_RATE_MCS6_INDEX, + VHT_RATE_MCS7_INDEX, + VHT_RATE_MCS8_INDEX, + VHT_RATE_MCS9_INDEX, + VHT_RATE_NUM /* 10 */ +}; + +enum ENUM_PREMABLE_OPTION { + /* LONG for PHY_TYPE_HR_DSSS, NONE for PHY_TYPE_OFDM */ + PREAMBLE_DEFAULT_LONG_NONE = 0, + /* SHORT mandatory for PHY_TYPE_ERP, + * SHORT option for PHY_TYPE_HR_DSSS + */ + PREAMBLE_OPTION_SHORT, + PREAMBLE_OFDM_MODE, + PREAMBLE_HT_MIXED_MODE, + PREAMBLE_HT_GREEN_FIELD, + PREAMBLE_VHT_FIELD, + PREAMBLE_OPTION_NUM +}; + +enum ENUM_MODULATION_SYSTEM { + MODULATION_SYSTEM_CCK = 0, + MODULATION_SYSTEM_OFDM, + MODULATION_SYSTEM_HT20, + MODULATION_SYSTEM_HT40, + MODULATION_SYSTEM_NUM +}; + +enum ENUM_MODULATION_TYPE { + MODULATION_TYPE_CCK_BPSK = 0, + MODULATION_TYPE_QPSK, + MODULATION_TYPE_16QAM, + MODULATION_TYPE_64QAM, + MODULATION_TYPE_NUM +}; + +enum ENUM_ACPI_STATE { + ACPI_STATE_D0 = 0, + ACPI_STATE_D1, + ACPI_STATE_D2, + ACPI_STATE_D3 +}; + +/* The operation mode of a specific Network */ +enum ENUM_OP_MODE { + 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 +}; + +/* + * NL80211 interface type. + * Refer to the definition of nl80211_iftype in kernel/nl80211.h + */ +enum ENUM_IFTYPE { + IFTYPE_UNSPECIFIED = 0, + IFTYPE_ADHOC, + IFTYPE_STATION, + IFTYPE_AP, + IFTYPE_AP_VLAN, + IFTYPE_WDS, + IFTYPE_MONITOR, + IFTYPE_MESH_POINT, + IFTYPE_P2P_CLIENT, + IFTYPE_P2P_GO, + IFTYPE_P2P_DEVICE, + IFTYPE_OCB, + IFTYPE_NAN, + IFTYPE_NUM +}; + +/* Concurrency mode for p2p preferred freq list*/ +enum CONN_MODE_IFACE_TYPE { + CONN_MODE_IFACE_TYPE_STA = 0, + CONN_MODE_IFACE_TYPE_SAP, + CONN_MODE_IFACE_TYPE_P2P_GC, + CONN_MODE_IFACE_TYPE_P2P_GO, + CONN_MODE_IFACE_TYPE_IBSS, + CONN_MODE_IFACE_TYPE_TDLS, + CONN_MODE_IFACE_TYPE_NUM +}; + +enum ENUM_CHNL_EXT { + CHNL_EXT_SCN = 0, + CHNL_EXT_SCA = 1, + CHNL_EXT_RES = 2, + CHNL_EXT_SCB = 3 +}; + +enum ENUM_CHANNEL_WIDTH { + CW_20_40MHZ = 0, + CW_80MHZ = 1, + CW_160MHZ = 2, + CW_80P80MHZ = 3 +}; + +/* This starting freq of the band is unit of kHz */ +enum ENUM_BAND { + BAND_NULL, + BAND_2G4, + BAND_5G, + BAND_NUM +}; + +enum ENUM_CH_REQ_TYPE { + CH_REQ_TYPE_JOIN, + CH_REQ_TYPE_ROC, /* requested by remain on channel type */ + CH_REQ_TYPE_OFFCHNL_TX, + CH_REQ_TYPE_GO_START_BSS, +#if (CFG_SUPPORT_DFS_MASTER == 1) + CH_REQ_TYPE_DFS_CAC, +#endif + CH_REQ_TYPE_NUM +}; + +enum ENUM_DBDC_BN { + ENUM_BAND_0, + ENUM_BAND_1, + ENUM_BAND_NUM, + ENUM_BAND_ALL, + ENUM_BAND_AUTO /*Auto select by A/G band, Driver only*/ +}; + +/* Provide supported channel list to other components in array format */ +struct RF_CHANNEL_INFO { + enum ENUM_BAND eBand; + /* To record Channel Center Frequency Segment 0 (MHz) from CFG80211 */ + uint32_t u4CenterFreq1; + /* To record Channel Center Frequency Segment 1 (MHz) from CFG80211 */ + uint32_t u4CenterFreq2; + /* To record primary channel frequency (MHz) from CFG80211 */ + uint16_t u2PriChnlFreq; + /* To record channel bandwidth from CFG80211 */ + uint8_t ucChnlBw; + uint8_t ucChannelNum; + enum nl80211_dfs_state eDFS; +}; + +enum ENUM_PS_FORWARDING_TYPE { + 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 ENUM_AR_SS { + AR_SS_NULL = 0, + AR_SS_1, + AR_SS_2, + AR_SS_3, + AR_SS_4, + AR_SS_NUM +}; + +enum ENUM_MAC_BANDWIDTH { + MAC_BW_20 = 0, + MAC_BW_40, + MAC_BW_80, + MAC_BW_160 +}; + +struct DEAUTH_INFO { + uint8_t aucRxAddr[MAC_ADDR_LEN]; + OS_SYSTIME rLastSendTime; +}; + +enum ENUM_CHNL_SWITCH_POLICY { + CHNL_SWITCH_POLICY_NONE, + CHNL_SWITCH_POLICY_DEAUTH, + CHNL_SWITCH_POLICY_CSA +}; + +enum ENUM_CHNL_SORT_POLICY { + CHNL_SORT_POLICY_NONE, + CHNL_SORT_POLICY_ALL_CN, + CHNL_SORT_POLICY_BY_CH_DOMAIN +}; + +/*----------------------------------------------------------------------------*/ +/* Information Element (IE) handlers */ +/*----------------------------------------------------------------------------*/ +typedef void(*PFN_APPEND_IE_FUNC) (struct ADAPTER *, + struct MSDU_INFO *); +typedef void(*PFN_HANDLE_IE_FUNC) (struct ADAPTER *, + struct SW_RFB *, struct IE_HDR *); +typedef void(*PFN_VERIFY_IE_FUNC) (struct ADAPTER *, + struct SW_RFB *, struct IE_HDR *, + uint16_t *); +typedef uint32_t(*PFN_CALCULATE_VAR_IE_LEN_FUNC) ( + struct ADAPTER *, uint8_t, struct STA_RECORD *); + +struct APPEND_IE_ENTRY { + uint16_t u2EstimatedIELen; + PFN_APPEND_IE_FUNC pfnAppendIE; +}; + +struct APPEND_VAR_IE_ENTRY { + uint16_t u2EstimatedFixedIELen; /* For Fixed Length */ + PFN_CALCULATE_VAR_IE_LEN_FUNC pfnCalculateVariableIELen; + PFN_APPEND_IE_FUNC pfnAppendIE; +}; + +struct HANDLE_IE_ENTRY { + uint8_t ucElemID; + PFN_HANDLE_IE_FUNC pfnHandleIE; +}; + +struct VERIFY_IE_ENTRY { + uint8_t ucElemID; + PFN_VERIFY_IE_FUNC pfnVarifyIE; +}; + +/*----------------------------------------------------------------------------*/ +/* Parameters of User Configuration */ +/*----------------------------------------------------------------------------*/ +enum ENUM_PARAM_CONNECTION_POLICY { + 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_BSSID_HINT, + CONNECT_BY_CUSTOMIZED_RULE /* NOTE(Kevin): TBD */ +}; + +enum ENUM_PARAM_PREAMBLE_TYPE { + PREAMBLE_TYPE_LONG = 0, + PREAMBLE_TYPE_SHORT, + /*!< Try preamble short first, if fail tray preamble long. */ + PREAMBLE_TYPE_AUTO +}; + +/* This is enum defined for user to select a phy config listed in combo box */ +enum ENUM_PARAM_PHY_CONFIG { + /* Can associated with 802.11abg AP but without n capability, + * Scan dual band. + */ + PHY_CONFIG_802_11ABG = 0, + /* Can associated with 802_11bg AP, + * Scan single band and not report 5G BSSs. + */ + PHY_CONFIG_802_11BG, + /* Can associated with 802_11g only AP, + * Scan single band and not report 5G BSSs. + */ + PHY_CONFIG_802_11G, + /* Can associated with 802_11a only AP, + * Scan single band and not report 2.4G BSSs. + */ + PHY_CONFIG_802_11A, + /* Can associated with 802_11b only AP, + * Scan single band and not report 5G BSSs. + */ + PHY_CONFIG_802_11B, + /* Can associated with 802.11abgn AP, Scan dual band. */ + PHY_CONFIG_802_11ABGN, + /* Can associated with 802_11bgn AP, + * Scan single band and not report 5G BSSs. + */ + PHY_CONFIG_802_11BGN, + /* Can associated with 802_11an AP, + * Scan single band and not report 2.4G BSSs. + */ + PHY_CONFIG_802_11AN, + /* Can associated with 802_11gn AP, + * Scan single band and not report 5G BSSs. + */ + PHY_CONFIG_802_11GN, + PHY_CONFIG_802_11AC, + PHY_CONFIG_802_11ANAC, + PHY_CONFIG_802_11ABGNAC, +#if (CFG_SUPPORT_802_11AX == 1) + PHY_CONFIG_802_11ABGNACAX, +#endif + PHY_CONFIG_NUM /* 12 */ +}; + +/* This is enum defined for user to select an AP Mode */ +enum ENUM_PARAM_AP_MODE { + /* Create 11b BSS if we support 802.11abg/802.11bg. */ + AP_MODE_11B = 0, + /* Create 11bg mixed BSS if we support 802.11abg/802.11bg/802.11g. */ + AP_MODE_MIXED_11BG, + /* Create 11g only BSS if we support 802.11abg/802.11bg/802.11g. */ + AP_MODE_11G, + /* Create 11g only BSS for P2P + * if we support 802.11abg/802.11bg/802.11g. + */ + AP_MODE_11G_P2P, + /* Create 11a only BSS if we support 802.11abg. */ + AP_MODE_11A, + AP_MODE_NUM /* 4 */ +}; + +/* Masks for determining the Network Type + * or the Station Role, given the ENUM_STA_TYPE_T + */ +#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) \ + (prAdapter->aprBssInfo[(_prStaRec)->ucBssIndex]->eNetworkType \ + == NETWORK_TYPE_AIS) +#define IS_STA_IN_P2P(_prStaRec) \ + (prAdapter->aprBssInfo[(_prStaRec)->ucBssIndex]->eNetworkType \ + == NETWORK_TYPE_P2P) +#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. + */ +enum ENUM_STA_TYPE { + 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), +}; + +/* The type of BSS we discovered */ +enum ENUM_BSS_TYPE { + BSS_TYPE_INFRASTRUCTURE = 1, + BSS_TYPE_IBSS, + BSS_TYPE_P2P_DEVICE, + BSS_TYPE_BOW_DEVICE, + BSS_TYPE_NUM +}; + +enum ENUM_ANTENNA_NUM { + ANTENNA_WF0 = 0, + ANTENNA_WF1 = 1, + MAX_ANTENNA_NUM +}; + +/*----------------------------------------------------------------------------*/ +/* RSN structures */ +/*----------------------------------------------------------------------------*/ +/* #if defined(WINDOWS_DDK) || defined(WINDOWS_CE) */ +/* #pragma pack(1) */ +/* #endif */ + +/* max number of supported cipher suites */ +#define MAX_NUM_SUPPORTED_CIPHER_SUITES 10 +#if CFG_SUPPORT_802_11W +/* max number of supported AKM suites */ +#define MAX_NUM_SUPPORTED_AKM_SUITES 15 +#else +/* max number of supported AKM suites */ +#define MAX_NUM_SUPPORTED_AKM_SUITES 13 +#endif + +/* Structure of RSN Information */ +struct RSN_INFO { + uint8_t ucElemId; + uint16_t u2Version; + uint32_t u4GroupKeyCipherSuite; + uint32_t u4PairwiseKeyCipherSuiteCount; + uint32_t au4PairwiseKeyCipherSuite[MAX_NUM_SUPPORTED_CIPHER_SUITES]; + uint32_t u4AuthKeyMgtSuiteCount; + uint32_t au4AuthKeyMgtSuite[MAX_NUM_SUPPORTED_AKM_SUITES]; + uint16_t u2RsnCap; + u_int8_t fgRsnCapPresent; + uint16_t u2PmkidCount; + uint8_t aucPmkid[IW_PMKID_LEN]; +} __KAL_ATTRIB_PACKED__; + +/* max number of supported AKM suites */ +#define MAX_NUM_SUPPORTED_WAPI_AKM_SUITES 1 +/* max number of supported cipher suites */ +#define MAX_NUM_SUPPORTED_WAPI_CIPHER_SUITES 1 + +/* Structure of WAPI Information */ +struct WAPI_INFO { + uint8_t ucElemId; + uint8_t ucLength; + uint16_t u2Version; + uint32_t u4AuthKeyMgtSuiteCount; + uint32_t au4AuthKeyMgtSuite[MAX_NUM_SUPPORTED_WAPI_AKM_SUITES]; + uint32_t u4PairwiseKeyCipherSuiteCount; + + uint32_t + au4PairwiseKeyCipherSuite[MAX_NUM_SUPPORTED_WAPI_CIPHER_SUITES]; + uint32_t u4GroupKeyCipherSuite; + uint16_t u2WapiCap; + uint16_t u2Bkid; + uint8_t aucBkid[1][16]; +} __KAL_ATTRIB_PACKED__; + +/* #if defined(WINDOWS_DDK) || defined(WINDOWS_CE) */ +/* #pragma pack() */ +/* #endif */ + +#if CFG_ENABLE_WIFI_DIRECT + +struct P2P_DEVICE_TYPE { + uint16_t u2CategoryID; + uint16_t u2SubCategoryID; +}; + +struct P2P_DEVICE_DESC { + struct LINK_ENTRY rLinkEntry; + u_int8_t fgDevInfoValid; + uint8_t aucDeviceAddr[MAC_ADDR_LEN]; /* Device Address. */ + uint8_t aucInterfaceAddr[MAC_ADDR_LEN]; /* Interface Address. */ + uint8_t ucDeviceCapabilityBitmap; + uint8_t ucGroupCapabilityBitmap; + uint16_t u2ConfigMethod; /* Configure Method support. */ + struct P2P_DEVICE_TYPE rPriDevType; + uint8_t ucSecDevTypeNum; + /* Reference to P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT */ + struct P2P_DEVICE_TYPE arSecDevType[8]; + uint16_t u2NameLength; + uint8_t aucName[32]; /* Reference to WPS_ATTRI_MAX_LEN_DEVICE_NAME */ + /* TODO: Service Information or PasswordID valid? */ +}; + +#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 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) \ + { \ + uint8_t *__cp = (uint8_t *)(_memAddr_p); \ + *(uint16_t *)(_value_p) = ((uint16_t)__cp[0]) | \ + ((uint16_t)__cp[1] << 8); \ + } + +#define WLAN_GET_FIELD_BE16(_memAddr_p, _value_p) \ + { \ + uint8_t *__cp = (uint8_t *)(_memAddr_p); \ + *(uint16_t *)(_value_p) = ((uint16_t)__cp[0] << 8) | \ + ((uint16_t)__cp[1]); \ + } + +#define WLAN_GET_FIELD_24(_memAddr_p, _value_p) \ + { \ + uint8_t *__cp = (uint8_t *)(_memAddr_p); \ + *(uint32_t *)(_value_p) = 0; \ + *(uint32_t *)(_value_p) = ((uint32_t)__cp[0]) | \ + ((uint32_t)__cp[1] << 8) | \ + ((uint32_t)__cp[2] << 16); \ + } + +#define WLAN_GET_FIELD_BE24(_memAddr_p, _value_p) \ + { \ + uint8_t *__cp = (uint8_t *)(_memAddr_p); \ + *(uint32_t *)(_value_p) = 0; \ + *(uint32_t *)(_value_p) = ((uint32_t)__cp[0] << 16) | \ + ((uint32_t)__cp[1] << 8) | (uint32_t)__cp[2]; \ + } + +#define WLAN_GET_FIELD_32(_memAddr_p, _value_p) \ + { \ + uint8_t *__cp = (uint8_t *)(_memAddr_p); \ + *(uint32_t *)(_value_p) = ((uint32_t)__cp[0]) | \ + ((uint32_t)__cp[1] << 8) | \ + ((uint32_t)__cp[2] << 16) | ((uint32_t)__cp[3] << 24); \ + } + +#define WLAN_GET_FIELD_BE32(_memAddr_p, _value_p) \ + { \ + uint8_t *__cp = (uint8_t *)(_memAddr_p); \ + *(uint32_t *)(_value_p) = ((uint32_t)__cp[0] << 24) | \ + ((uint32_t)__cp[1] << 16) | ((uint32_t)__cp[2] << 8) | \ + ((uint32_t)__cp[3]); \ + } + +#define WLAN_GET_FIELD_64(_memAddr_p, _value_p) \ + { \ + uint8_t *__cp = (uint8_t *)(_memAddr_p); \ + *(uint64_t *)(_value_p) = \ + ((uint64_t)__cp[0]) | ((uint64_t)__cp[1] << 8) | \ + ((uint64_t)__cp[2] << 16) | \ + ((uint64_t)__cp[3] << 24) | \ + ((uint64_t)__cp[4] << 32) | \ + ((uint64_t)__cp[5] << 40) | \ + ((uint64_t)__cp[6] << 48) | \ + ((uint64_t)__cp[7] << 56); \ + } + +#define WLAN_SET_FIELD_16(_memAddr_p, _value) \ + { \ + uint8_t *__cp = (uint8_t *)(_memAddr_p); \ + __cp[0] = (uint8_t)(_value); \ + __cp[1] = (uint8_t)((_value) >> 8); \ + } + +#define WLAN_SET_FIELD_64(_memAddr_p, _value) \ + { \ + uint8_t *__cp = (uint8_t *)(_memAddr_p); \ + __cp[0] = (uint8_t)((_value) & 0xff); \ + __cp[1] = (uint8_t)((_value) >> 8); \ + __cp[2] = (uint8_t)((_value) >> 16); \ + __cp[3] = (uint8_t)((_value) >> 24); \ + __cp[4] = (uint8_t)((_value) >> 32); \ + __cp[5] = (uint8_t)((_value) >> 40); \ + __cp[6] = (uint8_t)((_value) >> 48); \ + __cp[7] = (uint8_t)((_value) >> 56); \ + } + +#define WLAN_SET_FIELD_BE16(_memAddr_p, _value) \ + { \ + uint8_t *__cp = (uint8_t *)(_memAddr_p); \ + __cp[0] = (uint8_t)((_value) >> 8); \ + __cp[1] = (uint8_t)(_value); \ + } + +#define WLAN_SET_FIELD_32(_memAddr_p, _value) \ + { \ + uint8_t *__cp = (uint8_t *)(_memAddr_p); \ + __cp[0] = (uint8_t)(_value); \ + __cp[1] = (uint8_t)((_value) >> 8); \ + __cp[2] = (uint8_t)((_value) >> 16); \ + __cp[3] = (uint8_t)((_value) >> 24); \ + } + +#define WLAN_SET_FIELD_BE24(_memAddr_p, _value) \ + { \ + uint8_t *__cp = (uint8_t *)(_memAddr_p); \ + __cp[0] = (uint8_t)((_value) >> 16); \ + __cp[1] = (uint8_t)((_value) >> 8); \ + __cp[2] = (uint8_t)(_value); \ + } + +#define WLAN_SET_FIELD_BE32(_memAddr_p, _value) \ + { \ + uint8_t *__cp = (uint8_t *)(_memAddr_p); \ + __cp[0] = (uint8_t)((_value) >> 24); \ + __cp[1] = (uint8_t)((_value) >> 16); \ + __cp[2] = (uint8_t)((_value) >> 8); \ + __cp[3] = (uint8_t)(_value); \ + } + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _WLAN_DEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic_cmd_event.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic_cmd_event.h new file mode 100644 index 0000000000000..00254dbfed31d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic_cmd_event.h @@ -0,0 +1,3267 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + +#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 + ******************************************************************************* + */ +#include "gl_vendor.h" + +#if (CFG_SUPPORT_802_11AX == 1) +#include "he_ie.h" +#endif + +#include "wsys_cmd_handler_fw.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define CMD_PQ_ID (0x8000) +#define CMD_PACKET_TYPE_ID (0xA0) + +#define PKT_FT_CMD 0x2 + +#define CMD_STATUS_SUCCESS 0 +#define CMD_STATUS_REJECTED 1 +#define CMD_STATUS_UNKNOWN 2 + +#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 + +/*CMD_POWER_OFFSET_T , follow 5G sub-band*/ +/* #define MAX_SUBBAND_NUM 8 */ +/* */ +/* */ +/* */ +/* */ +#define S2D_INDEX_CMD_H2N 0x0 +#define S2D_INDEX_CMD_C2N 0x1 +#define S2D_INDEX_CMD_H2C 0x2 +#define S2D_INDEX_CMD_H2N_H2C 0x3 + +#define S2D_INDEX_EVENT_N2H 0x0 +#define S2D_INDEX_EVENT_N2C 0x1 +#define S2D_INDEX_EVENT_C2H 0x2 +#define S2D_INDEX_EVENT_N2H_N2C 0x3 + +#define RDD_EVENT_HDR_SIZE 20 +#define RDD_ONEPLUSE_SIZE 8 /* size of one pulse is 8 bytes */ +#define RDD_PULSE_OFFSET0 0 +#define RDD_PULSE_OFFSET1 1 +#define RDD_PULSE_OFFSET2 2 +#define RDD_PULSE_OFFSET3 3 +#define RDD_PULSE_OFFSET4 4 +#define RDD_PULSE_OFFSET5 5 +#define RDD_PULSE_OFFSET6 6 +#define RDD_PULSE_OFFSET7 7 + +#if (CFG_SUPPORT_DFS_MASTER == 1) +#define RDD_IN_SEL_0 0 +#define RDD_IN_SEL_1 1 +#endif + +#if (CFG_SUPPORT_TXPOWER_INFO == 1) +#define TXPOWER_EVENT_SHOW_ALL_RATE_TXPOWER_INFO 0x5 +#endif + +#if CFG_SUPPORT_QA_TOOL +#define IQ_FILE_LINE_OFFSET 18 +#define IQ_FILE_IQ_STR_LEN 8 +#define RTN_IQ_DATA_LEN 1024 /* return 1k per packet */ + +#define MCAST_WCID_TO_REMOVE 0 + +/* Network type */ +#define NETWORK_INFRA BIT(16) +#define NETWORK_P2P BIT(17) +#define NETWORK_IBSS BIT(18) +#define NETWORK_MESH BIT(19) +#define NETWORK_BOW BIT(20) +#define NETWORK_WDS BIT(21) + +/* Station role */ +#define STA_TYPE_STA BIT(0) +#define STA_TYPE_AP BIT(1) +#define STA_TYPE_ADHOC BIT(2) +#define STA_TYPE_TDLS BIT(3) +#define STA_TYPE_WDS BIT(4) + +/* Connection type */ +#define CONNECTION_INFRA_STA (STA_TYPE_STA|NETWORK_INFRA) +#define CONNECTION_INFRA_AP (STA_TYPE_AP|NETWORK_INFRA) +#define CONNECTION_P2P_GC (STA_TYPE_STA|NETWORK_P2P) +#define CONNECTION_P2P_GO (STA_TYPE_AP|NETWORK_P2P) +#define CONNECTION_MESH_STA (STA_TYPE_STA|NETWORK_MESH) +#define CONNECTION_MESH_AP (STA_TYPE_AP|NETWORK_MESH) +#define CONNECTION_IBSS_ADHOC (STA_TYPE_ADHOC|NETWORK_IBSS) +#define CONNECTION_TDLS \ + (STA_TYPE_STA|NETWORK_INFRA|STA_TYPE_TDLS) +#define CONNECTION_WDS (STA_TYPE_WDS|NETWORK_WDS) + +#define ICAP_CONTENT_ADC 0x10000006 +#define ICAP_CONTENT_TOAE 0x7 +#define ICAP_CONTENT_SPECTRUM 0xB +#define ICAP_CONTENT_RBIST 0x10 +#define ICAP_CONTENT_DCOC 0x20 +#define ICAP_CONTENT_FIIQ 0x48 +#define ICAP_CONTENT_FDIQ 0x49 + +#if CFG_SUPPORT_BUFFER_MODE + +struct CMD_EFUSE_BUFFER_MODE { + uint8_t ucSourceMode; + uint8_t ucCount; + uint8_t ucCmdType; /* 0:6632, 1: 7668 */ + uint8_t ucReserved; + uint8_t aBinContent[MAX_EEPROM_BUFFER_SIZE]; +}; + +struct CMD_EFUSE_BUFFER_MODE_CONNAC_T { + uint8_t ucSourceMode; + uint8_t ucContentFormat; + uint16_t u2Count; + uint8_t aBinContent[MAX_EEPROM_BUFFER_SIZE]; +}; + +/*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ +struct CMD_ACCESS_EFUSE { + uint32_t u4Address; + uint32_t u4Valid; + uint8_t aucData[16]; +}; + +struct CMD_EFUSE_FREE_BLOCK { + uint8_t ucGetFreeBlock; + uint8_t aucReserved[3]; +}; + + +struct CMD_GET_TX_POWER { + uint8_t ucTxPwrType; + uint8_t ucCenterChannel; + uint8_t ucDbdcIdx; /* 0:Band 0, 1: Band1 */ + uint8_t ucBand; /* 0:G-band 1: A-band*/ + uint8_t ucReserved[4]; +}; + +/*#endif*/ + +#endif /* CFG_SUPPORT_BUFFER_MODE */ + + +struct CMD_SET_TX_TARGET_POWER { + int8_t cTxPwr2G4Cck; /* signed, in unit of 0.5dBm */ + int8_t cTxPwr2G4Dsss; /* signed, in unit of 0.5dBm */ + uint8_t ucTxTargetPwr; /* Tx target power base for all*/ + uint8_t ucReserved; + + int8_t cTxPwr2G4OFDM_BPSK; + int8_t cTxPwr2G4OFDM_QPSK; + int8_t cTxPwr2G4OFDM_16QAM; + int8_t cTxPwr2G4OFDM_Reserved; + int8_t cTxPwr2G4OFDM_48Mbps; + int8_t cTxPwr2G4OFDM_54Mbps; + + int8_t cTxPwr2G4HT20_BPSK; + int8_t cTxPwr2G4HT20_QPSK; + int8_t cTxPwr2G4HT20_16QAM; + int8_t cTxPwr2G4HT20_MCS5; + int8_t cTxPwr2G4HT20_MCS6; + int8_t cTxPwr2G4HT20_MCS7; + + int8_t cTxPwr2G4HT40_BPSK; + int8_t cTxPwr2G4HT40_QPSK; + int8_t cTxPwr2G4HT40_16QAM; + int8_t cTxPwr2G4HT40_MCS5; + int8_t cTxPwr2G4HT40_MCS6; + int8_t cTxPwr2G4HT40_MCS7; + + int8_t cTxPwr5GOFDM_BPSK; + int8_t cTxPwr5GOFDM_QPSK; + int8_t cTxPwr5GOFDM_16QAM; + int8_t cTxPwr5GOFDM_Reserved; + int8_t cTxPwr5GOFDM_48Mbps; + int8_t cTxPwr5GOFDM_54Mbps; + + int8_t cTxPwr5GHT20_BPSK; + int8_t cTxPwr5GHT20_QPSK; + int8_t cTxPwr5GHT20_16QAM; + int8_t cTxPwr5GHT20_MCS5; + int8_t cTxPwr5GHT20_MCS6; + int8_t cTxPwr5GHT20_MCS7; + + int8_t cTxPwr5GHT40_BPSK; + int8_t cTxPwr5GHT40_QPSK; + int8_t cTxPwr5GHT40_16QAM; + int8_t cTxPwr5GHT40_MCS5; + int8_t cTxPwr5GHT40_MCS6; + int8_t cTxPwr5GHT40_MCS7; +}; + + +/* + * Definitions for extension CMD_ID + */ +enum ENUM_EXT_CMD_ID { + EXT_CMD_ID_EFUSE_ACCESS = 0x01, + EXT_CMD_ID_RF_REG_ACCESS = 0x02, + EXT_CMD_ID_EEPROM_ACCESS = 0x03, + EXT_CMD_ID_RF_TEST = 0x04, + EXT_CMD_ID_RADIO_ON_OFF_CTRL = 0x05, + EXT_CMD_ID_WIFI_RX_DISABLE = 0x06, + EXT_CMD_ID_PM_STATE_CTRL = 0x07, + EXT_CMD_ID_CHANNEL_SWITCH = 0x08, + EXT_CMD_ID_NIC_CAPABILITY = 0x09, + EXT_CMD_ID_AP_PWR_SAVING_CLEAR = 0x0A, + EXT_CMD_ID_SET_WTBL2_RATETABLE = 0x0B, + EXT_CMD_ID_GET_WTBL_INFORMATION = 0x0C, + EXT_CMD_ID_ASIC_INIT_UNINIT_CTRL = 0x0D, + EXT_CMD_ID_MULTIPLE_REG_ACCESS = 0x0E, + EXT_CMD_ID_AP_PWR_SAVING_CAPABILITY = 0x0F, + EXT_CMD_ID_SECURITY_ADDREMOVE_KEY = 0x10, + EXT_CMD_ID_SET_TX_POWER_CONTROL = 0x11, + EXT_CMD_ID_SET_THERMO_CALIBRATION = 0x12, + EXT_CMD_ID_FW_LOG_2_HOST = 0x13, + EXT_CMD_ID_AP_PWR_SAVING_START = 0x14, + EXT_CMD_ID_MCC_OFFLOAD_START = 0x15, + EXT_CMD_ID_MCC_OFFLOAD_STOP = 0x16, + EXT_CMD_ID_LED = 0x17, + EXT_CMD_ID_PACKET_FILTER = 0x18, + EXT_CMD_ID_COEXISTENCE = 0x19, + EXT_CMD_ID_PWR_MGT_BIT_WIFI = 0x1B, + EXT_CMD_ID_GET_TX_POWER = 0x1C, + EXT_CMD_ID_BF_ACTION = 0x1E, + + EXT_CMD_ID_WMT_CMD_OVER_WIFI = 0x20, + EXT_CMD_ID_EFUSE_BUFFER_MODE = 0x21, + EXT_CMD_ID_OFFLOAD_CTRL = 0x22, + EXT_CMD_ID_THERMAL_PROTECT = 0x23, + EXT_CMD_ID_CLOCK_SWITCH_DISABLE = 0x24, + EXT_CMD_ID_STAREC_UPDATE = 0x25, + EXT_CMD_ID_BSSINFO_UPDATE = 0x26, + EXT_CMD_ID_EDCA_SET = 0x27, + EXT_CMD_ID_SLOT_TIME_SET = 0x28, + EXT_CMD_ID_DEVINFO_UPDATE = 0x2A, + EXT_CMD_ID_NOA_OFFLOAD_CTRL = 0x2B, + EXT_CMD_ID_GET_SENSOR_RESULT = 0x2C, + EXT_CMD_ID_TMR_CAL = 0x2D, + EXT_CMD_ID_WAKEUP_OPTION = 0x2E, + EXT_CMD_ID_OBTW = 0x2F, + + EXT_CMD_ID_GET_TX_STATISTICS = 0x30, + EXT_CMD_ID_AC_QUEUE_CONTROL = 0x31, + EXT_CMD_ID_WTBL_UPDATE = 0x32, + EXT_CMD_ID_BCN_UPDATE = 0x33, + + EXT_CMD_ID_DRR_CTRL = 0x36, + EXT_CMD_ID_BSSGROUP_CTRL = 0x37, + EXT_CMD_ID_VOW_FEATURE_CTRL = 0x38, + EXT_CMD_ID_PKT_PROCESSOR_CTRL = 0x39, + EXT_CMD_ID_PALLADIUM = 0x3A, + EXT_CMD_ID_GET_MAC_INFO = 0x3C, +#if CFG_SUPPORT_MU_MIMO + EXT_CMD_ID_MU_CTRL = 0x40, +#endif /* CFG_SUPPORT_MU_MIMO */ + + EXT_CMD_ID_EFUSE_FREE_BLOCK = 0x4F, + EXT_CMD_ID_DUMP_MEM = 0x57, + EXT_CMD_ID_TX_POWER_FEATURE_CTRL = 0x58, + EXT_CMD_ID_SER = 0x81, +#if (CFG_SUPPORT_TWT == 1) + EXT_CMD_ID_TWT_AGRT_UPDATE = 0x94, +#endif + EXT_CMD_ID_SYSDVT_TEST = 0x99, + EXT_CMD_ID_CR4_DMASHDL_DVT = 0xAB +}; + +enum NDIS_802_11_WEP_STATUS { + Ndis802_11WEPEnabled, + Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, + Ndis802_11WEPDisabled, + Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, + Ndis802_11WEPKeyAbsent, + Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, + Ndis802_11WEPNotSupported, + Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, + Ndis802_11TKIPEnable, + Ndis802_11Encryption2Enabled = Ndis802_11TKIPEnable, + Ndis802_11Encryption2KeyAbsent, + Ndis802_11AESEnable, + Ndis802_11Encryption3Enabled = Ndis802_11AESEnable, + Ndis802_11CCMP256Enable, + Ndis802_11GCMP128Enable, + Ndis802_11GCMP256Enable, + Ndis802_11Encryption3KeyAbsent, + Ndis802_11TKIPAESMix, + /* TKIP or AES mix */ + Ndis802_11Encryption4Enabled = Ndis802_11TKIPAESMix, + Ndis802_11Encryption4KeyAbsent, + Ndis802_11GroupWEP40Enabled, + Ndis802_11GroupWEP104Enabled, +#ifdef WAPI_SUPPORT + Ndis802_11EncryptionSMS4Enabled, /* WPI SMS4 support */ +#endif /* WAPI_SUPPORT */ +}; + +#if CFG_SUPPORT_MU_MIMO +enum { + /* debug commands */ + MU_SET_ENABLE = 0, + MU_GET_ENABLE, + MU_SET_MUPROFILE_ENTRY, + MU_GET_MUPROFILE_ENTRY, + MU_SET_GROUP_TBL_ENTRY, + MU_GET_GROUP_TBL_ENTRY, + MU_SET_CLUSTER_TBL_ENTRY, + MU_GET_CLUSTER_TBL_ENTRY, + MU_SET_GROUP_USER_THRESHOLD, + MU_GET_GROUP_USER_THRESHOLD, + MU_SET_GROUP_NSS_THRESHOLD, + MU_GET_GROUP_NSS_THRESHOLD, + MU_SET_TXREQ_MIN_TIME, + MU_GET_TXREQ_MIN_TIME, + MU_SET_SU_NSS_CHECK, + MU_GET_SU_NSS_CHECK, + MU_SET_CALC_INIT_MCS, + MU_GET_CALC_INIT_MCS, + MU_SET_TXOP_DEFAULT, + MU_GET_TXOP_DEFAULT, + MU_SET_SU_LOSS_THRESHOLD, + MU_GET_SU_LOSS_THRESHOLD, + MU_SET_MU_GAIN_THRESHOLD, + MU_GET_MU_GAIN_THRESHOLD, + MU_SET_SECONDARY_AC_POLICY, + MU_GET_SECONDARY_AC_POLICY, + MU_SET_GROUP_TBL_DMCS_MASK, + MU_GET_GROUP_TBL_DMCS_MASK, + MU_SET_MAX_GROUP_SEARCH_CNT, + MU_GET_MAX_GROUP_SEARCH_CNT, + MU_GET_MU_PROFILE_TX_STATUS_CNT, + MU_SET_TRIGGER_MU_TX, + /* F/W flow test commands */ + MU_SET_TRIGGER_GID_MGMT_FRAME, + /* HQA STA commands */ + MU_HQA_SET_STA_PARAM = 60, + /* HQA AP Commands*/ + MU_HQA_SET_ENABLE = 70, + MU_HQA_SET_SNR_OFFSET, + MU_HQA_SET_ZERO_NSS, + MU_HQA_SET_SPEED_UP_LQ, + MU_HQA_SET_GROUP, + MU_HQA_SET_MU_TABLE, + MU_HQA_SET_SU_TABLE, + MU_HQA_SET_CALC_LQ, + MU_HQA_GET_CALC_LQ, + MU_HQA_SET_CALC_INIT_MCS, + MU_HQA_GET_CALC_INIT_MCS, + MU_HQA_GET_QD, +}; +#endif /* CFG_SUPPORT_MU_MIMO */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +#if CFG_WOW_SUPPORT + +/* Filter Flag */ +#define WOWLAN_FF_DROP_ALL BIT(0) +#define WOWLAN_FF_SEND_MAGIC_TO_HOST BIT(1) +#define WOWLAN_FF_ALLOW_ARP BIT(2) +#define WOWLAN_FF_ALLOW_BMC BIT(3) +#define WOWLAN_FF_ALLOW_UC BIT(4) +#define WOWLAN_FF_ALLOW_1X BIT(5) +#define WOWLAN_FF_ALLOW_ARP_REQ2ME BIT(6) + +/* wow detect type */ +#define WOWLAN_DETECT_TYPE_MAGIC BIT(0) +#define WOWLAN_DETECT_TYPE_ALLOW_NORMAL BIT(1) +#define WOWLAN_DETECT_TYPE_ONLY_PHONE_SUSPEND BIT(2) +#define WOWLAN_DETECT_TYPE_DISASSOCIATION BIT(3) +#define WOWLAN_DETECT_TYPE_BCN_LOST BIT(4) + +/* Wakeup command bit define */ +#define PF_WAKEUP_CMD_BIT0_OUTPUT_MODE_EN BIT(0) +#define PF_WAKEUP_CMD_BIT1_OUTPUT_DATA BIT(1) +#define PF_WAKEUP_CMD_BIT2_WAKEUP_LEVEL BIT(2) + +#define PM_WOWLAN_REQ_START 0x1 +#define PM_WOWLAN_REQ_STOP 0x2 + +struct EVENT_WOWLAN_NOTIFY { + uint8_t ucNetTypeIndex; + uint8_t aucReserved[3]; +}; + +/* PACKETFILTER CAPABILITY TYPE */ + +#define PACKETF_CAP_TYPE_ARP BIT(1) +#define PACKETF_CAP_TYPE_MAGIC BIT(2) +#define PACKETF_CAP_TYPE_BITMAP BIT(3) +#define PACKETF_CAP_TYPE_EAPOL BIT(4) +#define PACKETF_CAP_TYPE_TDLS BIT(5) +#define PACKETF_CAP_TYPE_CF BIT(6) +#define PACKETF_CAP_TYPE_HEARTBEAT BIT(7) +#define PACKETF_CAP_TYPE_TCP_SYN BIT(8) +#define PACKETF_CAP_TYPE_UDP_SYN BIT(9) +#define PACKETF_CAP_TYPE_BCAST_SYN BIT(10) +#define PACKETF_CAP_TYPE_MCAST_SYN BIT(11) +#define PACKETF_CAP_TYPE_V6 BIT(12) +#define PACKETF_CAP_TYPE_TDIM BIT(13) + + +enum _ENUM_FUNCTION_SELECT { + FUNCTION_PF = 1, + FUNCTION_BITMAP = 2, + FUNCTION_EAPOL = 3, + FUNCTION_TDLS = 4, + FUNCTION_ARPNS = 5, + FUNCTION_CF = 6, + FUNCTION_MODE = 7, + FUNCTION_BSSID = 8, + FUNCTION_MGMT = 9, + FUNCTION_BMC_DROP = 10, + FUNCTION_UC_DROP = 11, + FUNCTION_ALL_TOMCU = 12, +}; + +enum ENUM_PF_OPCODE { + PF_OPCODE_ADD = 0, + PF_OPCODE_DEL, + PF_OPCODE_ENABLE, + PF_OPCODE_DISABLE, + PF_OPCODE_NUM +}; + +enum ENUM_SCN_FUNC_MASK { + ENUM_SCN_RANDOM_MAC_EN = (1 << 0), + ENUM_SCN_DBDC_SCAN_DIS = (1 << 1), + ENUM_SCN_DBDC_SCAN_TYPE3 = (1 << 2), + ENUM_SCN_USE_PADDING_AS_BSSID = (1 << 3), + ENUM_SCN_RANDOM_SN_EN = (1 << 4), +}; + +struct CMD_PACKET_FILTER_CAP { + uint8_t ucCmd; + uint16_t packet_cap_type; + uint8_t aucReserved1[1]; + /* GLOBAL */ + uint32_t PFType; + uint32_t FunctionSelect; + uint32_t Enable; + /* MAGIC */ + uint8_t ucBssid; + uint16_t usEnableBits; + uint8_t aucReserved5[1]; + /* DTIM */ + uint8_t DtimEnable; + uint8_t DtimValue; + uint8_t aucReserved2[2]; + /* BITMAP_PATTERN_T */ + uint32_t Index; + uint32_t Offset; + uint32_t FeatureBits; + uint32_t Resv; + uint32_t PatternLength; + uint32_t Mask[4]; + uint32_t Pattern[32]; + /* COALESCE */ + uint32_t FilterID; + uint32_t PacketType; + uint32_t CoalesceOP; + uint8_t FieldLength; + uint8_t CompareOP; + uint8_t FieldID; + uint8_t aucReserved3[1]; + uint32_t Pattern3[4]; + /* TCPSYN */ + uint32_t AddressType; + uint32_t TCPSrcPort; + uint32_t TCPDstPort; + uint32_t SourceIP[4]; + uint32_t DstIP[4]; + uint8_t aucReserved4[64]; +}; +#endif /*CFG_WOW_SUPPORT*/ + +#if CFG_SUPPORT_WIFI_HOST_OFFLOAD +struct CMD_TCP_GENERATOR { + enum ENUM_PF_OPCODE eOpcode; + uint32_t u4ReplyId; + uint32_t u4Period; + uint32_t u4Timeout; + uint32_t u4IpId; + uint32_t u4DestPort; + uint32_t u4SrcPort; + uint32_t u4Seq; + uint8_t aucDestIp[4]; + uint8_t aucSrcIp[4]; + uint8_t aucDestMac[6]; + uint8_t ucBssId; + uint8_t aucReserved1[1]; + uint8_t aucReserved2[64]; +}; + +struct CMD_PATTERN_GENERATOR { + enum ENUM_PF_OPCODE eOpcode; + uint32_t u4ReplyId; + uint32_t u4EthernetLength; + uint32_t u4Period; + uint8_t aucEthernetFrame[128]; + uint8_t ucBssId; + uint8_t aucReserved1[3]; + uint8_t aucReserved2[64]; +}; + +struct CMD_BITMAP_FILTER { + enum ENUM_PF_OPCODE eOpcode; + uint32_t u4ReplyId; + uint32_t u4Offset; + uint32_t u4Length; + uint8_t aucPattern[64]; + uint8_t aucBitMask[64]; + u_int8_t fgIsEqual; + u_int8_t fgIsAccept; + uint8_t ucBssId; + uint8_t aucReserved1[1]; + uint8_t aucReserved2[64]; +}; + +#endif /*CFG_SUPPORT_WIFI_HOST_OFFLOAD*/ + +struct CMD_RX_PACKET_FILTER { + uint32_t u4RxPacketFilter; + uint8_t aucReserved[64]; +}; + + +#if defined(MT6632) +#define S2D_INDEX_CMD_H2N 0x0 +#define S2D_INDEX_CMD_C2N 0x1 +#define S2D_INDEX_CMD_H2C 0x2 +#define S2D_INDEX_CMD_H2N_H2C 0x3 + +#define S2D_INDEX_EVENT_N2H 0x0 +#define S2D_INDEX_EVENT_N2C 0x1 +#define S2D_INDEX_EVENT_C2H 0x2 +#define S2D_INDEX_EVENT_N2H_N2C 0x3 +#endif + +#define EXT_EVENT_TARGET_TX_POWER 0x1 + +#define EXT_EVENT_ID_CMD_RESULT 0x00 +#define EXT_EVENT_ID_EFUSE_ACCESS 0x01 +#define EXT_EVENT_ID_RF_REG_ACCESS 0x02 +#define EXT_EVENT_ID_EEPROM_ACCESS 0x03 +#define EXT_EVENT_ID_RF_TEST 0x04 +#define EXT_EVENT_ID_PS_SYNC 0x05 +#define EXT_EVENT_ID_SLEEPY_NOTIFY 0x06 +#define EXT_EVENT_ID_WLAN_ERROR 0x07 +#define EXT_EVENT_ID_NIC_CAPABILITY 0x09 +#define EXT_EVENT_ID_AP_PWR_SAVING_CLEAR 0x0A +#define EXT_EVENT_ID_SET_WTBL2_RATETABLE 0x0B +#define EXT_EVENT_ID_GET_WTBL2_INFORMATION 0x0C +#define EXT_EVENT_ID_MULTIPLE_REG_ACCESS 0x0E +#define EXT_EVENT_ID_AP_PWR_SAVING_CAPABILITY 0x0F +#define EXT_EVENT_ID_SECURITY_ADDREMOVE_KEY 0x10 +#define EXT_EVENT_ID_FW_LOG_2_HOST 0x13 +#define EXT_EVENT_ID_AP_PWR_SAVING_START 0x14 +#define EXT_EVENT_ID_PACKET_FILTER 0x18 +#define EXT_EVENT_ID_COEXISTENCE 0x19 +#define EXT_EVENT_ID_BEACON_LOSS 0x1A +#define EXT_EVENT_ID_PWR_MGT_BIT_WIFI 0x1B +#define EXT_EVENT_ID_GET_TX_POWER 0x1C + +#define EXT_EVENT_ID_WMT_EVENT_OVER_WIFI 0x20 +#define EXT_EVENT_ID_MCC_TRIGGER 0x21 +#define EXT_EVENT_ID_THERMAL_PROTECT 0x22 +#define EXT_EVENT_ID_ASSERT_DUMP 0x23 +#define EXT_EVENT_ID_GET_SENSOR_RESULT 0x2C +#define EXT_EVENT_ID_ROAMING_DETECT_NOTIFICATION 0x2D +#define EXT_EVENT_ID_TMR_CAL 0x2E +#define EXT_EVENT_ID_RA_THROUGHPUT_BURST 0x2F + +#define EXT_EVENT_ID_GET_TX_STATISTIC 0x30 +#define EXT_EVENT_ID_PRETBTT_INT 0x31 +#define EXT_EVENT_ID_WTBL_UPDATE 0x32 + +#define EXT_EVENT_ID_BF_STATUS_READ 0x35 +#define EXT_EVENT_ID_DRR_CTRL 0x36 +#define EXT_EVENT_ID_BSSGROUP_CTRL 0x37 +#define EXT_EVENT_ID_VOW_FEATURE_CTRL 0x38 +#define EXT_EVENT_ID_PKT_PROCESSOR_CTRL 0x39 +#define EXT_EVENT_ID_RDD_REPORT 0x3A +#define EXT_EVENT_ID_DEVICE_CAPABILITY 0x3B +#define EXT_EVENT_ID_MAC_INFO 0x3C +#define EXT_EVENT_ID_ATE_TEST_MODE 0x3D +#define EXT_EVENT_ID_CAC_END 0x3E +#define EXT_EVENT_ID_MU_CTRL 0x40 + +#define EXT_EVENT_ID_DBDC_CTRL 0x45 +#define EXT_EVENT_ID_CONFIG_MUAR 0x48 + +#define EXT_EVENT_ID_RX_AIRTIME_CTRL 0x4a +#define EXT_EVENT_ID_AT_PROC_MODULE 0x4b +#define EXT_EVENT_ID_MAX_AMSDU_LENGTH_UPDATE 0x4c +#define EXT_EVENT_ID_EFUSE_FREE_BLOCK 0x4d +#define EXT_EVENT_ID_MURA_CTRL 0x4d +#define EXT_EVENT_ID_CSA_NOTIFY 0x4F +#define EXT_EVENT_ID_WIFI_SPECTRUM 0x50 +#define EXT_EVENT_ID_TMR_CALCU_INFO 0x51 +#define EXT_EVENT_ID_DUMP_MEM 0x57 +#define EXT_EVENT_ID_TX_POWER_FEATURE_CTRL 0x58 + +#define EXT_EVENT_ID_G_BAND_256QAM_PROBE_RESULT 0x6B +#define EXT_EVENT_ID_MPDU_TIME_UPDATE 0x6F +#define EXT_EVENT_ID_SYSDVT_TEST 0x99 +/*#endif*/ + +#if (CFG_SUPPORT_TXPOWER_INFO == 1) +#define EXT_EVENT_ID_TX_POWER_FEATURE_CTRL 0x58 +#endif + +#define SCHED_SCAN_CHANNEL_TYPE_SPECIFIED (0) +#define SCHED_SCAN_CHANNEL_TYPE_DUAL_BAND (1) +#define SCHED_SCAN_CHANNEL_TYPE_2G4_ONLY (2) +#define SCHED_SCAN_CHANNEL_TYPE_5G_ONLY (3) + +#if (CFG_SUPPORT_TWT == 1) +/* TWT related definitions */ +#define TWT_AGRT_MAX_NUM 16 +#define TWT_GRP_MAX_NUM 8 +#define TWT_GRP_MAX_MEMBER_CNT 8 + +/* + * Bitmap definition for ucAgrtParaBitmap field + * in struct _EXT_CMD_TWT_ARGT_UPDATE_T + */ +#define TWT_AGRT_PARA_BITMAP_IS_TRIGGER BIT(0) +#define TWT_AGRT_PARA_BITMAP_IS_ANNOUNCE BIT(1) +#define TWT_AGRT_PARA_BITMAP_IS_PROTECT BIT(2) + +#define TWT_AGRT_PARA_BITMAP_TRIGGER_OFFSET 0 +#define TWT_AGRT_PARA_BITMAP_ANNCE_OFFSET 1 +#define TWT_AGRT_PARA_BITMAP_PROTECT_OFFSET 2 + +enum _TWT_AGRT_CTRL_CODE_T { + TWT_AGRT_CTRL_ADD = 0, + TWT_AGRT_CTRL_MODIFY, + TWT_AGRT_CTRL_DELETE, + TWT_AGRT_CTRL_TEARDOWN, + TWT_AGRT_CTRL_RESET +}; +#endif + +/* ID for different MAC Info */ +enum { + MAC_INFO_TYPE_RESERVE = 0, + MAC_INFO_TYPE_CHANNEL_BUSY_CNT = 0x1, + MAC_INFO_TYPE_TSF = 0x2, + MAC_INFO_TYPE_MIB = 0x3, + MAC_INFO_TYPE_EDCA = 0x4, + MAC_INFO_TYPE_WIFI_INT_CNT = 0x5, +}; + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +#ifndef LINUX +#endif +/* for Event Packet (via HIF-RX) */ +struct PSE_CMD_HDR { + /* DW0 */ + uint16_t u2TxByteCount; + uint16_t u2Reserved1: 10; + uint16_t u2Qidx: 5; + uint16_t u2Pidx: 1; + + /* DW1 */ + uint16_t u2Reserved2: 13; + uint16_t u2Hf: 2; + uint16_t u2Ft: 1; + uint16_t u2Reserved3: 8; + uint16_t u2PktFt: 2; + uint16_t u2Reserved4: 6; + + /* DW2~7 */ + uint32_t au4Reserved[6]; +}; + +struct WIFI_CMD { + uint16_t u2TxByteCount; /* Max value is over 2048 */ + uint16_t u2PQ_ID; /* Must be 0x8000 (Port1, Queue 0) */ + + uint8_t ucWlanIdx; + uint8_t ucHeaderFormat; + uint8_t ucHeaderPadding; + uint8_t ucPktFt: 2; + uint8_t ucOwnMAC: 6; + uint32_t au4Reserved1[6]; + + uint16_t u2Length; + uint16_t u2PqId; + + uint8_t ucCID; + uint8_t ucPktTypeID; /* Must be 0x20 (CMD Packet) */ + uint8_t ucSetQuery; + uint8_t ucSeqNum; + + /* padding fields, hw may auto modify this field */ + uint8_t ucD2B0Rev; + uint8_t ucExtenCID; /* Extend CID */ + uint8_t ucS2DIndex; /* Index for Src to Dst in CMD usage */ + uint8_t ucExtCmdOption; /* Extend CID option */ + + uint8_t ucCmdVersion; + uint8_t ucReserved2[3]; + uint32_t au4Reserved3[4]; /* padding fields */ + + uint8_t aucBuffer[0]; +}; + +/* for Command Packet (via HIF-TX) */ +/* following CM's documentation v0.7 */ +struct WIFI_EVENT { + uint16_t u2PacketLength; + uint16_t u2PacketType; /* Must be filled with 0xE000 (EVENT Packet) */ + uint8_t ucEID; + uint8_t ucSeqNum; + uint8_t ucEventVersion; + uint8_t aucReserved[1]; + + uint8_t ucExtenEID; + uint8_t aucReserved2[2]; + uint8_t ucS2DIndex; + + uint8_t aucBuffer[0]; +}; + +/* CMD_ID_TEST_CTRL */ +struct CMD_TEST_CTRL { + uint8_t ucAction; + uint8_t aucReserved[3]; + union { + uint32_t u4OpMode; + uint32_t u4ChannelFreq; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + } u; +}; + +struct CMD_TEST_CTRL_EXT_T { + uint8_t ucAction; + uint8_t ucIcapLen; + uint8_t aucReserved[2]; + union { + uint32_t u4OpMode; + uint32_t u4ChannelFreq; + struct PARAM_MTK_WIFI_TEST_STRUCT_EXT_T rRfATInfo; + } u; +}; + +/* EVENT_TEST_STATUS */ +struct PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT { + uint32_t u4PktSentStatus; + uint32_t u4PktSentCount; + uint16_t u2AvgAlc; + uint8_t ucCckGainControl; + uint8_t ucOfdmGainControl; +}; + +struct PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT { + /*!< number of packets that Rx ok from interrupt */ + uint32_t u4IntRxOk; + /*!< number of packets that CRC error from interrupt */ + uint32_t u4IntCrcErr; + /*!< number of packets that is short preamble from interrupt */ + uint32_t u4IntShort; + /*!< number of packets that is long preamble from interrupt */ + uint32_t u4IntLong; + /*!< number of packets that Rx ok from PAU */ + uint32_t u4PauRxPktCount; + /*!< number of packets that CRC error from PAU */ + uint32_t u4PauCrcErrCount; + /*!< number of packets that is short preamble from PAU */ + uint32_t u4PauRxFifoFullCount; + uint32_t u4PauCCACount; /*!< CCA rising edge count */ +}; + +union EVENT_TEST_STATUS { + struct PARAM_MTK_WIFI_TEST_STRUCT rATInfo; + /* PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T rTxStatus; */ + /* PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T rRxStatus; */ +}; + +/* CMD_ID_DEFAULT_KEY_ID */ +struct CMD_DEFAULT_KEY { + uint8_t ucBssIdx; + uint8_t ucKeyId; + uint8_t ucWlanIndex; + uint8_t ucMulticast; +}; + +/* WPA2 PMKID cache structure */ +struct PMKID_ENTRY { + struct LINK_ENTRY rLinkEntry; + struct PARAM_PMKID rBssidInfo; +}; + +struct CMD_802_11_PMKID { + uint32_t u4BSSIDInfoCount; + struct PMKID_ENTRY *arPMKIDInfo[1]; +}; + +struct CMD_GTK_REKEY_DATA { + uint8_t aucKek[16]; + uint8_t aucKck[16]; + uint8_t aucReplayCtr[8]; +}; + +struct CMD_CSUM_OFFLOAD { + uint16_t u2RxChecksum; /* bit0: IP, bit1: UDP, bit2: TCP */ + uint16_t u2TxChecksum; /* bit0: IP, bit1: UDP, bit2: TCP */ +}; + +/* CMD_BASIC_CONFIG */ +struct CMD_BASIC_CONFIG { + uint8_t ucNative80211; + uint8_t ucCtrlFlagAssertPath; + uint8_t ucCtrlFlagDebugLevel; + uint8_t aucReserved[1]; + struct CMD_CSUM_OFFLOAD rCsumOffload; + uint8_t ucCrlFlagSegememt; + uint8_t aucReserved2[3]; +}; + +/* CMD_MAC_MCAST_ADDR */ +struct CMD_MAC_MCAST_ADDR { + uint32_t u4NumOfGroupAddr; + uint8_t ucBssIndex; + uint8_t aucReserved[3]; + uint8_t arAddress[MAX_NUM_GROUP_ADDR][PARAM_MAC_ADDR_LEN]; +}; + +/* CMD_ACCESS_EEPROM */ +struct CMD_ACCESS_EEPROM { + uint16_t u2Offset; + uint16_t u2Data; +}; + +/* EVENT_CONNECTION_STATUS */ +struct EVENT_CONNECTION_STATUS { + uint8_t ucMediaStatus; + uint8_t ucReasonOfDisconnect; + + uint8_t ucInfraMode; + uint8_t ucSsidLen; + uint8_t aucSsid[PARAM_MAX_LEN_SSID]; + uint8_t aucBssid[PARAM_MAC_ADDR_LEN]; + uint8_t ucAuthenMode; + uint8_t ucEncryptStatus; + uint16_t u2BeaconPeriod; + uint16_t u2AID; + uint16_t u2ATIMWindow; + uint8_t ucNetworkType; + uint8_t aucReserved[1]; + uint32_t u4FreqInKHz; + +#if CFG_ENABLE_WIFI_DIRECT + uint8_t aucInterfaceAddr[PARAM_MAC_ADDR_LEN]; +#endif + +}; + +/* EVENT_NIC_CAPABILITY */ +#define FEATURE_FLAG0_NIC_CAPABILITY_V2 BIT(0) + +struct EVENT_NIC_CAPABILITY { + uint16_t u2ProductID; + uint16_t u2FwVersion; + uint16_t u2DriverVersion; + uint8_t ucHw5GBandDisabled; + uint8_t ucEepromUsed; + uint8_t aucMacAddr[6]; + uint8_t ucEndianOfMacAddrNumber; + uint8_t ucHwNotSupportAC; + + uint8_t ucRfVersion; + uint8_t ucPhyVersion; + uint8_t ucRfCalFail; + uint8_t ucBbCalFail; + uint8_t aucDateCode[16]; + uint32_t u4FeatureFlag0; + uint32_t u4FeatureFlag1; + uint32_t u4CompileFlag0; + uint32_t u4CompileFlag1; + uint8_t aucBranchInfo[4]; + uint8_t ucFwBuildNumber; + uint8_t ucHwSetNss1x1; + uint8_t ucHwNotSupportDBDC; + uint8_t ucHwBssIdNum; + uint8_t aucReserved1[56]; +}; + +struct EVENT_NIC_CAPABILITY_V2 { + uint16_t u2TotalElementNum; + uint8_t aucReserved[2]; + uint8_t aucBuffer[0]; +}; + +struct NIC_CAPABILITY_V2_ELEMENT { + uint32_t tag_type; /* NIC_CAPABILITY_V2_TAG_T */ + uint32_t body_len; + uint8_t aucbody[0]; +}; + +typedef uint32_t(*NIC_CAP_V2_ELEMENT_HDLR)( + struct ADAPTER *prAdapter, uint8_t *buff); +struct NIC_CAPABILITY_V2_REF_TABLE { + uint32_t tag_type; /* NIC_CAPABILITY_V2_TAG_T */ + NIC_CAP_V2_ELEMENT_HDLR hdlr; +}; + +enum NIC_CAPABILITY_V2_TAG { + TAG_CAP_TX_RESOURCE = 0x0, + TAG_CAP_TX_EFUSEADDRESS = 0x1, + TAG_CAP_COEX_FEATURE = 0x2, + TAG_CAP_SINGLE_SKU = 0x3, + TAG_CAP_CSUM_OFFLOAD = 0x4, + TAG_CAP_HW_VERSION = 0x5, + TAG_CAP_SW_VERSION = 0x6, + TAG_CAP_MAC_ADDR = 0x7, + TAG_CAP_PHY_CAP = 0x8, + TAG_CAP_MAC_CAP = 0x9, + TAG_CAP_FRAME_BUF_CAP = 0xa, + TAG_CAP_BEAMFORM_CAP = 0xb, + TAG_CAP_LOCATION_CAP = 0xc, + TAG_CAP_MUMIMO_CAP = 0xd, + TAG_CAP_BUFFER_MODE_INFO = 0xe, + TAG_CAP_HW_ADIE_VERSION = 0x14, +#if CFG_SUPPORT_ANT_SWAP + TAG_CAP_ANTSWP = 0x16, +#endif +#if (CFG_SUPPORT_P2PGO_ACS == 1) + TAG_CAP_P2P = 0x17, +#endif + TAG_CAP_HOST_STATUS_EMI_OFFSET = 0x19, + TAG_CAP_TOTAL +}; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +struct NIC_CSUM_OFFLOAD { + uint8_t ucIsSupportCsumOffload; /* 1: Support, 0: Not Support */ + uint8_t aucReseved[3]; +}; +#endif + +struct NIC_COEX_FEATURE { + uint32_t u4FddMode; /* TRUE for COEX FDD mode */ +}; + +struct NIC_EFUSE_ADDRESS { + uint32_t u4EfuseStartAddress; /* Efuse Start Address */ + uint32_t u4EfuseEndAddress; /* Efuse End Address */ +}; + +struct CAP_HW_VERSION { + uint16_t u2ProductID; /* CHIP ID */ + uint8_t ucEcoVersion; /* ECO version */ + uint8_t ucReserved; + uint32_t u4MacIpID; /* MAC IP version */ + uint32_t u4BBIpID; /* Baseband IP version */ + uint32_t u4TopIpID; /* TOP IP version */ + uint32_t u4ConfigId; /* Configuration ID */ +}; + +struct CAP_HW_ADIE_VERSION { + uint16_t u2ProductID; /* CHIP ID */ + uint16_t u2EcoVersion; /* ECO version */ + uint32_t aucReserved[4]; +}; + +struct CAP_SW_VERSION { + uint16_t u2FwVersion; /* FW version */ + uint16_t u2FwBuildNumber; /* FW build number */ + uint8_t aucBranchInfo[4]; /* Branch name in ASCII */ + uint8_t aucDateCode[16]; /* FW build data code */ +}; + +struct CAP_MAC_ADDR { + uint8_t aucMacAddr[6]; + uint8_t aucReserved[2]; +}; + +struct CAP_PHY_CAP { + uint8_t ucHt; /* 1:support, 0:not*/ + uint8_t ucVht; /* 1:support, 0:not*/ + uint8_t uc5gBand; /* 1:support, 0:not*/ + /* 0: BW20, 1:BW40, 2:BW80, 3:BW160, 4:BW80+80 */ + uint8_t ucMaxBandwidth; + uint8_t ucNss; /* 1:1x1, 2:2x2, ... */ + uint8_t ucDbdc; /* 1:support, 0:not*/ + uint8_t ucTxLdpc; /* 1:support, 0:not*/ + uint8_t ucRxLdpc; /* 1:support, 0:not*/ + uint8_t ucTxStbc; /* 1:support, 0:not*/ + uint8_t ucRxStbc; /* 1:support, 0:not*/ + /* BIT(0): WLAN_FLAG_2G4_WF0 + * BIT(1): WLAN_FLAG_5G_WF0 + * BIT(2): WLAN_FLAG_2G4_WF1 + * BIT(3): WLAN_FLAG_5G_WF1 + */ + uint8_t ucWifiPath; + uint8_t ucHe; /* 1:support, 0:not*/ +}; + +struct CAP_MAC_CAP { + uint8_t ucHwBssIdNum; /* HW BSSID number */ + uint8_t ucWmmSet; /* 1: AC0~3, 2: AC0~3 and AC10~13, ... */ + uint8_t ucWtblEntryNum; /* WTBL entry number */ + uint8_t ucReserved; +}; + +struct CAP_FRAME_BUF_CAP { + /* 1: support in-chip Tx AMSDU (HW or CR4) */ + uint8_t ucChipTxAmsdu; + /* 2: support 2 MSDU in AMSDU, 3:support 3 MSDU in AMSDU,...*/ + uint8_t ucTxAmsduNum; + /* Rx AMSDU size, 0:4K, 1:8K,2:12K */ + uint8_t ucRxAmsduSize; + uint8_t ucReserved; + /* Txd entry number */ + uint32_t u4TxdCount; + /* Txd and packet buffer in KB (cut through sysram size) */ + uint32_t u4PacketBufSize; +}; + +struct CAP_BEAMFORM_CAP { + uint8_t ucBFer; /* Tx beamformer, 1:support, 0:not*/ + uint8_t ucIBFer; /* Tx implicit beamformer 1:support, 0:not*/ + uint8_t ucBFee; /* Rx beamformee, 1:support, 0:not */ + uint8_t ucReserved; + uint32_t u4BFerCap; /* Tx beamformere cap */ + uint32_t u4BFeeCap; /* Rx beamformee cap */ +}; + +struct CAP_LOCATION_CAP { + uint8_t ucTOAE; /* 1:support, 0:not */ + uint8_t aucReserved[3]; +}; + +struct CAP_MUMIMO_CAP { + uint8_t ucMuMimoRx; /* 1:support, 0:not */ + uint8_t ucMuMimoTx; /* 1:support, 0:not */ + uint8_t aucReserved[2]; +}; + +#if CFG_SUPPORT_ANT_SWAP +struct CAP_ANTSWP { + uint8_t ucVersion; + uint8_t ucRsvd; + uint8_t ucIsSupported; /* 1:support, 0:not */ + uint8_t ucReserved[1]; +}; +#endif + +struct NIC_HOST_STATUS_EMI_OFFSET { + uint32_t u4EmiOffset; /* TRUE for COEX FDD mode */ +}; + +#define EFUSE_SECTION_TABLE_SIZE (10) /* It should not be changed. */ + +struct EFUSE_SECTION_T { + uint16_t u2StartOffset; + uint16_t u2Length; +}; + +struct CAP_BUFFER_MODE_INFO_T { + uint8_t ucVersion; /* Version */ + uint8_t ucFormatSupportBitmap; /* Format Support Bitmap*/ + uint16_t u2EfuseTotalSize; /* Total eFUSE Size */ + struct EFUSE_SECTION_T arSections[EFUSE_SECTION_TABLE_SIZE]; + /* NOTE: EFUSE_SECTION_TABLE_SIZE should be fixed to + * 10 so that driver don't change. + */ +}; + +/* + * NIC_TX_RESOURCE_REPORT_EVENT related definition + */ + +#define NIC_TX_RESOURCE_REPORT_VERSION_PREFIX (0x80000000) +#define NIC_TX_RESOURCE_REPORT_VERSION_1 \ + (NIC_TX_RESOURCE_REPORT_VERSION_PREFIX | 0x1) + +struct nicTxRsrcEvtHdlr { + uint32_t u4Version; + + uint32_t(*nicEventTxResource) + (IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf); + void (*nicTxResourceInit)(IN struct ADAPTER *prAdapter); +}; + +struct NIC_TX_RESOURCE { + /* the total usable resource for MCU port */ + uint32_t u4CmdTotalResource; + /* the unit of a MCU resource */ + uint32_t u4CmdResourceUnit; + /* the total usable resource for LMAC port */ + uint32_t u4DataTotalResource; + /* the unit of a LMAC resource */ + uint32_t u4DataResourceUnit; +}; + +struct tx_resource_report_v1 { + /* + * u4Version: NIC_TX_RESOURCE_REPORT_VERSION_1 + */ + uint32_t u4Version; + + /* + * the followings are content for u4Verion = 0x80000001 + */ + uint32_t u4HifDataPsePageQuota; + uint32_t u4HifCmdPsePageQuota; + uint32_t u4HifDataPlePageQuota; + uint32_t u4HifCmdPlePageQuota; + + /* + * u4PlePsePageSize: the unit of a page in PLE and PSE + * [31:16] PLE page size + * [15:0] PLE page size + */ + uint32_t u4PlePsePageSize; + + /* + * ucPpTxAddCnt: the extra pse resource needed by HW + */ + uint8_t ucPpTxAddCnt; + + uint8_t ucReserved[3]; +}; + + +/* modified version of WLAN_BEACON_FRAME_BODY_T for simplier buffering */ +struct WLAN_BEACON_FRAME_BODY_T_LOCAL { + /* Beacon frame body */ + uint32_t au4Timestamp[2]; /* Timestamp */ + uint16_t u2BeaconInterval; /* Beacon Interval */ + uint16_t u2CapInfo; /* Capability */ + /* Various IEs, start from SSID */ + uint8_t aucInfoElem[MAX_IE_LENGTH]; + /* This field is *NOT* carried by F/W but caculated by nic_rx */ + uint16_t u2IELength; +}; + +/* EVENT_SCAN_RESULT */ +struct EVENT_SCAN_RESULT { + int32_t i4RSSI; + uint32_t u4LinkQuality; + uint32_t u4DSConfig; /* Center frequency */ + uint32_t u4DomainInfo; /* Require CM opinion */ + uint32_t u4Reserved; + uint8_t ucNetworkType; + uint8_t ucOpMode; + uint8_t aucBssid[MAC_ADDR_LEN]; + uint8_t aucRatesEx[PARAM_MAX_LEN_RATES_EX]; + struct WLAN_BEACON_FRAME_BODY_T_LOCAL rBeaconFrameBody; +}; + +struct EVENT_PMKID_CANDIDATE_LIST { + uint32_t u4Version; /*!< Version */ + uint32_t u4NumCandidates; /*!< How many candidates follow */ + struct PARAM_PMKID_CANDIDATE arCandidateList[1]; +}; + +struct EVENT_CMD_RESULT { + uint8_t ucCmdID; + uint8_t ucStatus; + uint8_t aucReserved[2]; +}; + +/* CMD_ID_ACCESS_REG & EVENT_ID_ACCESS_REG */ +struct CMD_ACCESS_REG { + uint32_t u4Address; + uint32_t u4Data; +}; + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +/* CMD_ID_CAL_BACKUP_IN_HOST_V2 & EVENT_ID_CAL_BACKUP_IN_HOST_V2 */ +struct CMD_CAL_BACKUP_STRUCT_V2 { + uint8_t ucReason; + uint8_t ucAction; + uint8_t ucNeedResp; + uint8_t ucFragNum; + uint8_t ucRomRam; + uint32_t u4ThermalValue; + uint32_t u4Address; + uint32_t u4Length; + uint32_t u4RemainLength; + uint32_t au4Buffer[PARAM_CAL_DATA_DUMP_MAX_NUM]; +}; + +struct CMD_CAL_BACKUP_STRUCT { + uint8_t ucReason; + uint8_t ucAction; + uint8_t ucNeedResp; + uint8_t ucFragNum; + uint8_t ucRomRam; + uint32_t u4ThermalValue; + uint32_t u4Address; + uint32_t u4Length; + uint32_t u4RemainLength; +}; +#endif + +struct CMD_ACCESS_CHN_LOAD { + uint32_t u4Address; + uint32_t u4Data; + uint16_t u2Channel; + uint8_t aucReserved[2]; +}; + +struct CMD_GET_LTE_SAFE_CHN { + uint8_t ucIndex; + uint8_t ucFlags; + uint8_t aucReserved0[2]; + uint8_t aucReserved2[16]; +}; + +/* CMD_DUMP_MEMORY */ +struct CMD_DUMP_MEM { + uint32_t u4Address; + uint32_t u4Length; + uint32_t u4RemainLength; +#if CFG_SUPPORT_QA_TOOL + uint32_t u4IcapContent; +#endif /* CFG_SUPPORT_QA_TOOL */ + uint8_t ucFragNum; +}; + +struct EVENT_DUMP_MEM { + uint32_t u4Address; + uint32_t u4Length; + uint32_t u4RemainLength; +#if CFG_SUPPORT_QA_TOOL + uint32_t eIcapContent; +#endif /* CFG_SUPPORT_QA_TOOL */ + uint8_t ucFragNum; + uint8_t aucBuffer[1]; +}; + +#if CFG_SUPPORT_QA_TOOL +struct CMD_ACCESS_RX_STAT { + uint32_t u4SeqNum; + uint32_t u4TotalNum; +}; + +struct EVENT_ACCESS_RX_STAT { + uint32_t u4SeqNum; + uint32_t u4TotalNum; + uint32_t au4Buffer[1]; +}; + +#if CFG_SUPPORT_TX_BF +union CMD_TXBF_ACTION { + struct PROFILE_TAG_READ rProfileTagRead; + struct PROFILE_TAG_WRITE rProfileTagWrite; + struct PROFILE_DATA_READ rProfileDataRead; + struct PROFILE_DATA_WRITE rProfileDataWrite; + struct PROFILE_PN_READ rProfilePnRead; + struct PROFILE_PN_WRITE rProfilePnWrite; + struct TX_BF_SOUNDING_START rTxBfSoundingStart; + struct TX_BF_SOUNDING_STOP rTxBfSoundingStop; + struct TX_BF_TX_APPLY rTxBfTxApply; + struct TX_BF_PFMU_MEM_ALLOC rTxBfPfmuMemAlloc; + struct TX_BF_PFMU_MEM_RLS rTxBfPfmuMemRls; +#if CFG_SUPPORT_TX_BF_FPGA + struct TX_BF_PROFILE_SW_TAG_WRITE rTxBfProfileSwTagWrite; +#endif +}; + +#define CMD_DEVINFO_UPDATE_HDR_SIZE 8 +struct CMD_DEV_INFO_UPDATE { + uint8_t ucOwnMacIdx; + uint8_t ucReserve; + uint16_t u2TotalElementNum; + uint8_t ucAppendCmdTLV; + uint8_t aucReserve[3]; + uint8_t aucBuffer[0]; + /* CMD_DEVINFO_ACTIVE_T rCmdDevInfoActive; */ +}; + +#define CMD_BSSINFO_UPDATE_HDR_SIZE 8 +struct CMD_BSS_INFO_UPDATE { + uint8_t ucBssIndex; + uint8_t ucReserve; + uint16_t u2TotalElementNum; + uint32_t u4Reserve; + /* CMD_BSSINFO_BASIC_T rCmdBssInfoBasic; */ + uint8_t aucBuffer[0]; +}; + +/* STA record command */ +#define CMD_STAREC_UPDATE_HDR_SIZE 8 +struct CMD_STAREC_UPDATE { + uint8_t ucBssIndex; + uint8_t ucWlanIdx; + uint16_t u2TotalElementNum; + uint32_t u4Reserve; + uint8_t aucBuffer[0]; +}; + +struct EXT_EVENT_BF_STATUS_T { + uint8_t ucEventCategoryID; + uint8_t ucBw; + uint16_t u2SubCarrIdx; + u_int8_t fgBFer; + uint8_t aucReserved[3]; + uint8_t aucBuf[1000]; /* temp size */ +}; + +struct EVENT_PFMU_TAG_READ { + union PFMU_PROFILE_TAG1 ru4TxBfPFMUTag1; + union PFMU_PROFILE_TAG2 ru4TxBfPFMUTag2; +}; + +#if CFG_SUPPORT_MU_MIMO +struct EVENT_HQA_GET_QD { + uint32_t u4EventId; + uint32_t au4RawData[14]; +}; + +struct EVENT_HQA_GET_MU_CALC_LQ { + uint32_t u4EventId; + struct MU_STRUCT_LQ_REPORT rEntry; +}; + +struct EVENT_SHOW_GROUP_TBL_ENTRY { + uint32_t u4EventId; + uint8_t index; + uint8_t numUser: 2; + uint8_t BW: 2; + uint8_t NS0: 2; + uint8_t NS1: 2; + /* UINT_8 NS2:1; */ + /* UINT_8 NS3:1; */ + uint8_t PFIDUser0; + uint8_t PFIDUser1; + /* UINT_8 PFIDUser2; */ + /* UINT_8 PFIDUser3; */ + u_int8_t fgIsShortGI; + u_int8_t fgIsUsed; + u_int8_t fgIsDisable; + uint8_t initMcsUser0: 4; + uint8_t initMcsUser1: 4; + /* UINT_8 initMcsUser2:4; */ + /* UINT_8 initMcsUser3:4; */ + uint8_t dMcsUser0: 4; + uint8_t dMcsUser1: 4; + /* UINT_8 dMcsUser2:4; */ + /* UINT_8 dMcsUser3:4; */ +}; + +union CMD_MUMIMO_ACTION { + uint8_t ucMuMimoCategory; + uint8_t aucRsv[3]; + union { + struct MU_GET_CALC_INIT_MCS rMuGetCalcInitMcs; + struct MU_SET_INIT_MCS rMuSetInitMcs; + struct MU_SET_CALC_LQ rMuSetCalcLq; + struct MU_GET_LQ rMuGetLq; + struct MU_SET_SNR_OFFSET rMuSetSnrOffset; + struct MU_SET_ZERO_NSS rMuSetZeroNss; + struct MU_SPEED_UP_LQ rMuSpeedUpLq; + struct MU_SET_MU_TABLE rMuSetMuTable; + struct MU_SET_GROUP rMuSetGroup; + struct MU_GET_QD rMuGetQd; + struct MU_SET_ENABLE rMuSetEnable; + struct MU_SET_GID_UP rMuSetGidUp; + struct MU_TRIGGER_MU_TX rMuTriggerMuTx; + } unMuMimoParam; +}; +#endif /* CFG_SUPPORT_MU_MIMO */ +#endif /* CFG_SUPPORT_TX_BF */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +struct CMD_SW_DBG_CTRL { + uint32_t u4Id; + uint32_t u4Data; + /* Debug Support */ + uint32_t u4DebugCnt[64]; +}; + +struct CMD_FW_LOG_2_HOST_CTRL { + uint8_t ucFwLog2HostCtrl; + uint8_t ucMcuDest; + uint8_t ucReserve[2]; +}; + +struct CMD_CHIP_CONFIG { + uint16_t u2Id; + uint8_t ucType; + uint8_t ucRespType; + uint16_t u2MsgSize; + uint8_t aucReserved0[2]; + uint8_t aucCmd[CHIP_CONFIG_RESP_SIZE]; +}; + +/* CMD_ID_LINK_ATTRIB */ +struct CMD_LINK_ATTRIB { + int8_t cRssiTrigger; + uint8_t ucDesiredRateLen; + uint16_t u2DesiredRate[32]; + uint8_t ucMediaStreamMode; + uint8_t aucReserved[1]; +}; + +/* CMD_ID_NIC_POWER_CTRL */ +struct CMD_NIC_POWER_CTRL { + uint8_t ucPowerMode; + uint8_t aucReserved[3]; +}; + +/* CMD_ID_POWER_SAVE_MODE */ +struct CMD_PS_PROFILE { + uint8_t ucBssIndex; + uint8_t ucPsProfile; + uint8_t aucReserved[2]; +}; + +#if CFG_SUPPORT_LOWLATENCY_MODE +/* CMD_ID_SET_LOW_LATENCY_MODE */ +struct LOW_LATENCY_MODE_SETTING { + u_int8_t fgEnable; /* Low Latency mode on/off */ + u_int8_t fgTxDupDetect; /* Start/stop Tx dup detect */ + u_int8_t fgTxDupCertQuery; /* Get Tx Dup Certificate */ + uint8_t aucReserved[5]; +}; + +struct CMD_LOW_LATENCY_MODE_HEADER { + uint8_t ucVersion; + uint8_t ucType; + uint8_t ucMagicCode; + uint8_t ucBufferLen; + struct LOW_LATENCY_MODE_SETTING rSetting; +}; +#endif + + +#if CFG_SUPPORT_P2P_RSSI_QUERY +/* EVENT_LINK_QUALITY */ +struct EVENT_LINK_QUALITY_EX { + int8_t cRssi; + int8_t cLinkQuality; + uint16_t u2LinkSpeed; + uint8_t ucMediumBusyPercentage; + uint8_t ucIsLQ0Rdy; + int8_t cRssiP2P; /* For P2P Network. */ + int8_t cLinkQualityP2P; + uint16_t u2LinkSpeedP2P; + uint8_t ucMediumBusyPercentageP2P; + uint8_t ucIsLQ1Rdy; +}; +#endif + +/* EVENT_ID_FW_SLEEPY_NOTIFY */ +struct EVENT_SLEEPY_INFO { + uint8_t ucSleepyState; + uint8_t aucReserved[3]; +}; + +/* CMD_BT_OVER_WIFI */ +struct CMD_BT_OVER_WIFI { + uint8_t ucAction; /* 0: query, 1: setup, 2: destroy */ + uint8_t ucChannelNum; + uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN]; + uint16_t u2BeaconInterval; + uint8_t ucTimeoutDiscovery; + uint8_t ucTimeoutInactivity; + uint8_t ucRole; + uint8_t PAL_Capabilities; + uint8_t cMaxTxPower; + uint8_t ucChannelBand; + uint8_t ucReserved[1]; +}; + +#if (CFG_SUPPORT_DFS_MASTER == 1) +enum ENUM_REG_DOMAIN { + REG_DEFAULT = 0, + REG_JP_53, + REG_JP_56 +}; + +struct CMD_RDD_ON_OFF_CTRL { + uint8_t ucDfsCtrl; + uint8_t ucRddIdx; + uint8_t ucRddRxSel; + uint8_t ucSetVal; + uint8_t aucReserve[4]; +}; +#endif + +struct CMD_PERF_IND { + /* DWORD_0 - Common Part */ + uint8_t ucCmdVer; + uint8_t aucPadding0[1]; + uint16_t u2CmdLen; /* cmd size including common part and body. */ + /* DWORD_1 ~ x - Command Body */ + uint32_t u4VaildPeriod; /* in ms */ + /* Current State */ + uint32_t ulCurTxBytes[4]; /* in Bps */ + uint32_t ulCurRxBytes[4]; /* in Bps */ + uint16_t u2CurRxRate[4]; /* Unit 500 Kbps */ + uint8_t ucCurRxRCPI0[4]; + uint8_t ucCurRxRCPI1[4]; + uint8_t ucCurRxNss[4]; + uint32_t au4Reserve[63]; +}; + +#if CFG_SUPPORT_SMART_GEAR +struct CMD_SMART_GEAR_PARAM { + uint8_t ucSGEnable;/*0: disable, 1: Enable, 2: Action for ucSGSpcCmd*/ + uint8_t ucSGSpcCmd;/* 1: Force 1x1, 2: Force 2x2, 0: Automatic*/ + uint8_t ucNSSCap; /*NSS Capbility*/ + uint8_t ucSGCfg; /* DON'T SET, IT IS USED FOR WIFI.CFG WIFI*/ + /* DON'T SET, IT IS USED FOR WIFI.CFG WIFI 2.4G Favor ANT path*/ + uint8_t ucSG24GFavorANT; + /* DON'T SET, IT IS USED FOR WIFI.CFG WIFI 5G Favor ANT path*/ + uint8_t ucSG5GFavorANT; +}; + +struct EVENT_SMART_GEAT_STATE { + bool fgIsEnable; + uint32_t u4StateIdx; +}; +#endif + +/* EVENT_BT_OVER_WIFI */ +struct EVENT_BT_OVER_WIFI { + uint8_t ucLinkStatus; + uint8_t ucSelectedChannel; + int8_t cRSSI; + uint8_t ucReserved[1]; +}; + +/* Same with DOMAIN_SUBBAND_INFO */ +struct CMD_SUBBAND_INFO { + uint8_t ucRegClass; + uint8_t ucBand; + uint8_t ucChannelSpan; + uint8_t ucFirstChannelNum; + uint8_t ucNumChannels; + uint8_t aucReserved[3]; +}; + +/* CMD_SET_DOMAIN_INFO */ +struct CMD_SET_DOMAIN_INFO { + uint16_t u2CountryCode; + uint16_t u2IsSetPassiveScan; + struct CMD_SUBBAND_INFO rSubBand[6]; + + uint8_t uc2G4Bandwidth; /* CONFIG_BW_20_40M or CONFIG_BW_20M */ + uint8_t uc5GBandwidth; /* CONFIG_BW_20_40M or CONFIG_BW_20M */ + uint8_t aucReserved[2]; +}; + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +enum ENUM_PWR_LIMIT_TYPE { + PWR_LIMIT_TYPE_COMP_11AC = 0, + PWR_LIMIT_TYPE_COMP_11AG_11N = 1, + PWR_LIMIT_TYPE_COMP_11AX = 2, + PWR_LIMIT_TYPE_COMP_NUM, +}; + + +/* CMD_SET_PWR_LIMIT_TABLE */ +struct CMD_CHANNEL_POWER_LIMIT { + uint8_t ucCentralCh; + + int8_t cPwrLimitCCK; +#if (CFG_SUPPORT_DYNA_TX_PWR_CTRL_OFDM_SETTING == 1) + int8_t cPwrLimitOFDM_L; /* OFDM_L, 6M ~ 18M */ + int8_t cPwrLimitOFDM_H; /* OFDM_H, 24M ~ 54M */ +#endif /* CFG_SUPPORT_DYNA_TX_PWR_CTRL_OFDM_SETTING */ + int8_t cPwrLimit20L; /* MCS0~4 */ + int8_t cPwrLimit20H; /* MCS5~8 */ + int8_t cPwrLimit40L; /* MCS0~4 */ + int8_t cPwrLimit40H; /* MCS5~9 */ + int8_t cPwrLimit80L; /* MCS0~4 */ + int8_t cPwrLimit80H; /* MCS5~9 */ + int8_t cPwrLimit160L; /* MCS0~4 */ + int8_t cPwrLimit160H; /* MCS5~9 */ + + uint8_t ucFlag; /*Not used in driver*/ + uint8_t aucReserved[1]; +}; +struct CMD_CHANNEL_POWER_LIMIT_HE { /*HE SU design*/ + uint8_t ucCentralCh; + int8_t cPwrLimitRU26L; /* MCS0~4 */ + int8_t cPwrLimitRU26H; /* MCS5~9 */ + int8_t cPwrLimitRU26U; /* MCS10~11 */ + + int8_t cPwrLimitRU52L; /* MCS0~4 */ + int8_t cPwrLimitRU52H; /* MCS5~9 */ + int8_t cPwrLimitRU52U; /* MCS10~11 */ + + int8_t cPwrLimitRU106L; /* MCS0~4 */ + int8_t cPwrLimitRU106H; /* MCS5~9 */ + int8_t cPwrLimitRU106U; /* MCS10~11 */ + /*RU242/SU20*/ + int8_t cPwrLimitRU242L; /* MCS0~4 */ + int8_t cPwrLimitRU242H; /* MCS5~9 */ + int8_t cPwrLimitRU242U; /* MCS10~11 */ + /*RU484/SU40*/ + int8_t cPwrLimitRU484L; /* MCS0~4 */ + int8_t cPwrLimitRU484H; /* MCS5~9 */ + int8_t cPwrLimitRU484U; /* MCS10~11 */ + /*RU996/SU80*/ + int8_t cPwrLimitRU996L; /* MCS0~4 */ + int8_t cPwrLimitRU996H; /* MCS5~9 */ + int8_t cPwrLimitRU996U; /* MCS10~11 */ + + uint8_t ucFlag; + uint8_t ucValid; + +}; + +struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT { + /* D-WORD 0 */ + uint16_t u2CountryCode; + uint8_t ucCountryFlag; /*Not used in driver*/ + uint8_t ucNum; /*Numbers of channel to set power limit*/ + + /* D-WORD 1 */ + u_int8_t fgPwrTblKeep; + uint8_t ucBandIdx; + /* u1LimitType: enum ENUM_COUNTRY_CHANNEL_TXPOWER_LIMIT_FORMAT */ + uint8_t ucLimitType; + uint8_t au1Reserved[1]; + union { + /*Channel power limit entries to be set*/ + struct CMD_CHANNEL_POWER_LIMIT + rChannelPowerLimit[MAX_CMD_SUPPORT_CHANNEL_NUM]; + /*Channel HE power limit entries to be set*/ + struct CMD_CHANNEL_POWER_LIMIT_HE + rChPwrLimtHE[MAX_CMD_SUPPORT_CHANNEL_NUM]; + } u; + +}; + +#if (CFG_SUPPORT_SINGLE_SKU == 1) +struct CMD_CHANNEL_POWER_LIMIT_V2 { + uint8_t ucCentralCh; + uint8_t ucReserved[3]; + + uint8_t tx_pwr_dsss_cck; + uint8_t tx_pwr_dsss_bpsk; + + uint8_t tx_pwr_ofdm_bpsk; /* 6M, 9M */ + uint8_t tx_pwr_ofdm_qpsk; /* 12M, 18M */ + uint8_t tx_pwr_ofdm_16qam; /* 24M, 36M */ + uint8_t tx_pwr_ofdm_48m; + uint8_t tx_pwr_ofdm_54m; + + uint8_t tx_pwr_ht20_bpsk; /* MCS0*/ + uint8_t tx_pwr_ht20_qpsk; /* MCS1, MCS2*/ + uint8_t tx_pwr_ht20_16qam; /* MCS3, MCS4*/ + uint8_t tx_pwr_ht20_mcs5; /* MCS5*/ + uint8_t tx_pwr_ht20_mcs6; /* MCS6*/ + uint8_t tx_pwr_ht20_mcs7; /* MCS7*/ + + uint8_t tx_pwr_ht40_bpsk; /* MCS0*/ + uint8_t tx_pwr_ht40_qpsk; /* MCS1, MCS2*/ + uint8_t tx_pwr_ht40_16qam; /* MCS3, MCS4*/ + uint8_t tx_pwr_ht40_mcs5; /* MCS5*/ + uint8_t tx_pwr_ht40_mcs6; /* MCS6*/ + uint8_t tx_pwr_ht40_mcs7; /* MCS7*/ + uint8_t tx_pwr_ht40_mcs32; /* MCS32*/ + + uint8_t tx_pwr_vht20_bpsk; /* MCS0*/ + uint8_t tx_pwr_vht20_qpsk; /* MCS1, MCS2*/ + uint8_t tx_pwr_vht20_16qam; /* MCS3, MCS4*/ + uint8_t tx_pwr_vht20_64qam; /* MCS5, MCS6*/ + uint8_t tx_pwr_vht20_mcs7; + uint8_t tx_pwr_vht20_mcs8; + uint8_t tx_pwr_vht20_mcs9; + + uint8_t tx_pwr_vht_40; + uint8_t tx_pwr_vht_80; + uint8_t tx_pwr_vht_160c; + uint8_t tx_pwr_vht_160nc; + uint8_t tx_pwr_lg_40; + uint8_t tx_pwr_lg_80; + + uint8_t tx_pwr_1ss_delta; + uint8_t ucReserved_1[2]; +}; + +struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2 { + uint8_t ucNum; + uint8_t eband; /*ENUM_BAND_T*/ + uint8_t usReserved[2]; + uint32_t countryCode; + struct CMD_CHANNEL_POWER_LIMIT_V2 rChannelPowerLimit[0]; +}; + +#define BF_TX_PWR_LIMIT_SECTION_NUM 17 +#define BF_TX_PWR_LIMIT_ELEMENT_NUM 10 +#define TX_PWR_LIMIT_SECTION_NUM 9 +#define TX_PWR_LIMIT_ELEMENT_NUM 10 +#define TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN 4 +#define TX_PWR_LIMIT_MAX_VAL 63 + +#define POWER_LIMIT_SKU_CCK_NUM 4 +#define POWER_LIMIT_SKU_OFDM_NUM 8 +#define POWER_LIMIT_SKU_HT20_NUM 8 +#define POWER_LIMIT_SKU_HT40_NUM 9 +#define POWER_LIMIT_SKU_VHT20_NUM 10 +#define POWER_LIMIT_SKU_VHT40_NUM 10 +#define POWER_LIMIT_SKU_VHT80_NUM 10 +#define POWER_LIMIT_SKU_VHT160_NUM 10 + +struct CHANNEL_TX_PWR_LIMIT { + uint8_t ucChannel; + int8_t rTxPwrLimitValue[TX_PWR_LIMIT_SECTION_NUM] + [TX_PWR_LIMIT_ELEMENT_NUM]; + int8_t rTxBfBackoff[POWER_LIMIT_TXBF_BACKOFF_PARAM_NUM]; +}; + +struct TX_PWR_LIMIT_DATA { + uint32_t countryCode; + uint32_t ucChNum; + struct CHANNEL_TX_PWR_LIMIT *rChannelTxPwrLimit; +}; + +#endif + +#endif + +struct PATTERN_DESCRIPTION { + uint8_t fgCheckBcA1; + uint8_t fgCheckMcA1; + uint8_t ePatternHeader; + uint8_t fgAndOp; + uint8_t fgNotOp; + uint8_t ucPatternMask; + uint16_t u2PatternOffset; + uint8_t aucPattern[8]; +}; + +struct CMD_RAW_PATTERN_CONFIGURATION { + struct PATTERN_DESCRIPTION arPatternDesc[4]; +}; + +struct CMD_PATTERN_FUNC_CONFIG { + u_int8_t fgBcA1En; + u_int8_t fgMcA1En; + u_int8_t fgBcA1MatchDrop; + u_int8_t fgMcA1MatchDrop; +}; + +struct EVENT_TX_DONE { + uint8_t ucPacketSeq; + uint8_t ucStatus; + uint16_t u2SequenceNumber; + + uint8_t ucWlanIndex; + uint8_t ucTxCount; + uint16_t u2TxRate; + + uint8_t ucFlag; + uint8_t ucTid; + uint8_t ucRspRate; + uint8_t ucRateTableIdx; + + uint8_t ucBandwidth; + uint8_t ucTxPower; + uint8_t ucFlushReason; + uint8_t aucReserved0[1]; + + uint32_t u4TxDelay; + uint32_t u4Timestamp; + uint32_t u4AppliedFlag; + + uint8_t aucRawTxS[28]; + + uint8_t aucReserved1[32]; +}; + +enum ENUM_TXS_APPLIED_FLAG { + TX_FRAME_IN_AMPDU_FORMAT = 0, + TX_FRAME_EXP_BF, + TX_FRAME_IMP_BF, + TX_FRAME_PS_BIT +}; + +enum ENUM_TXS_CONTROL_FLAG { + TXS_WITH_ADVANCED_INFO = 0, + TXS_IS_EXIST +}; + +#if (CFG_SUPPORT_DFS_MASTER == 1) +enum ENUM_DFS_CTRL { + RDD_STOP = 0, + RDD_START, + RDD_DET_MODE, + RDD_RADAR_EMULATE, + RDD_START_TXQ +}; +#endif + +struct CMD_BSS_ACTIVATE_CTRL { + uint8_t ucBssIndex; + uint8_t ucActive; + uint8_t ucNetworkType; + uint8_t ucOwnMacAddrIndex; + uint8_t aucBssMacAddr[6]; + uint8_t ucBMCWlanIndex; + uint8_t ucReserved; +}; + +enum ENUM_RTS_POLICY { + RTS_POLICY_AUTO, + RTS_POLICY_STATIC_BW, + RTS_POLICY_DYNAMIC_BW, + RTS_POLICY_LEGACY, + RTS_POLICY_NO_RTS +}; + +enum _ENUM_CMD_UPDATE_STA_RECORD_VER_T { + CMD_UPDATE_STAREC_VER0 = 0, + CMD_UPDATE_STAREC_VER1, + CMD_UPDATE_STAREC_VER_MAX +}; + +struct CMD_BEACON_TEMPLATE_UPDATE { + /* 0: update randomly, + * 1: update all, + * 2: delete all (1 and 2 will update directly without search) + */ + uint8_t ucUpdateMethod; + uint8_t ucBssIndex; + uint8_t aucReserved[2]; + uint16_t u2Capability; + uint16_t u2IELen; + uint8_t aucIE[MAX_IE_LENGTH]; +}; + +struct GSCN_CHANNEL_INFO { + uint8_t ucBand; + uint8_t ucChannelNumber; /* Channel Number */ + uint8_t ucPassive; /* 0:active, 1:passive scan; ignored for DFS */ + uint8_t aucReserved[1]; + uint32_t u4DwellTimeMs; /* dwell time hint */ +}; + +enum ENUM_WIFI_BAND { + WIFI_BAND_UNSPECIFIED, + WIFI_BAND_BG = 1, /* 2.4 GHz */ + WIFI_BAND_A = 2, /* 5 GHz without DFS */ + WIFI_BAND_A_DFS = 4, /* 5 GHz DFS only */ + WIFI_BAND_A_WITH_DFS = 6, /* 5 GHz with DFS */ + WIFI_BAND_ABG = 3, /* 2.4 GHz + 5 GHz; no DFS */ + WIFI_BAND_ABG_WITH_DFS = 7, /* 2.4 GHz + 5 GHz with DFS */ +}; + +struct GSCAN_BUCKET { + uint16_t u2BucketIndex; /* bucket index, 0 based */ + /* desired period, in millisecond; + * if this is too low, the firmware should choose to generate + * results as fast as it can instead of failing the command + */ + uint8_t ucBucketFreqMultiple; + /* report_events semantics - + * This is a bit field; which defines following bits - + * REPORT_EVENTS_EACH_SCAN + * report a scan completion event after scan. If this is not set + * then scan completion events should be reported if + * report_threshold_percent or report_threshold_num_scans is + * reached. + * REPORT_EVENTS_FULL_RESULTS + * forward scan results (beacons/probe responses + IEs) + * in real time to HAL, in addition to completion events + * Note: To keep backward compatibility, fire completion + * events regardless of REPORT_EVENTS_EACH_SCAN. + * REPORT_EVENTS_NO_BATCH + * controls if scans for this bucket should be placed in the + * history buffer + */ + uint8_t ucReportFlag; + uint8_t ucMaxBucketFreqMultiple; /* max_period / base_period */ + uint8_t ucStepCount; + uint8_t ucNumChannels; + uint8_t aucReserved[1]; + enum ENUM_WIFI_BAND + eBand; /* when UNSPECIFIED, use channel list */ + /* channels to scan; these may include DFS channels */ + struct GSCN_CHANNEL_INFO arChannelList[8]; +}; + +struct CMD_GSCN_REQ { + uint8_t ucFlags; + uint8_t ucNumScnToCache; + uint8_t aucReserved[2]; + uint32_t u4BufferThreshold; + uint32_t u4BasePeriod; /* base timer period in ms */ + uint32_t u4NumBuckets; + /* number of APs to store in each scan in the */ + uint32_t u4MaxApPerScan; + /* BSSID/RSSI history buffer (keep the highest RSSI APs) */ + struct GSCAN_BUCKET arBucket[8]; +}; + +struct CMD_GSCN_SCN_COFIG { + uint8_t ucNumApPerScn; /* GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN */ + uint32_t u4BufferThreshold; /* GSCAN_ATTRIBUTE_REPORT_THRESHOLD */ + uint32_t u4NumScnToCache; /* GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE */ +}; + +/* 20150107 Daniel Added complete channels number in the scan done event */ +/* before*/ +/* + * typedef struct EVENT_SCAN_DONE { + * UINT_8 ucSeqNum; + * UINT_8 ucSparseChannelValid; + * CHANNEL_INFO_T rSparseChannel; + * } EVENT_SCAN_DONE, *P_EVENT_SCAN_DONE; + */ +/* after */ + +struct CMD_BATCH_REQ { + uint8_t ucSeqNum; + uint8_t ucNetTypeIndex; + uint8_t ucCmd; /* Start/ Stop */ + /* an integer number of scans per batch */ + uint8_t ucMScan; + /* an integer number of the max AP to remember per scan */ + uint8_t ucBestn; + /* an integer number of highest-strength AP for which we'd */ + uint8_t ucRtt; + /* like approximate distance reported */ + uint8_t ucChannel; /* channels */ + uint8_t ucChannelType; + uint8_t ucChannelListNum; + uint8_t aucReserved[3]; + uint32_t u4Scanfreq; /* an integer number of seconds between scans */ + struct CHANNEL_INFO arChannelList[32]; /* channels */ +}; + +struct CMD_CH_PRIVILEGE { + uint8_t ucBssIndex; + uint8_t ucTokenID; + uint8_t ucAction; + uint8_t ucPrimaryChannel; + uint8_t ucRfSco; + uint8_t ucRfBand; + uint8_t ucRfChannelWidth; /* To support 80/160MHz bandwidth */ + uint8_t ucRfCenterFreqSeg1; /* To support 80/160MHz bandwidth */ + uint8_t ucRfCenterFreqSeg2; /* To support 80/160MHz bandwidth */ + uint8_t ucReqType; + uint8_t ucDBDCBand; + uint8_t aucReserved; + uint32_t u4MaxInterval; /* In unit of ms */ + uint8_t aucReserved2[8]; +}; + +struct CMD_TX_PWR { + int8_t cTxPwr2G4Cck; /* signed, in unit of 0.5dBm */ + int8_t cTxPwr2G4Dsss; /* signed, in unit of 0.5dBm */ + int8_t acReserved[2]; + + int8_t cTxPwr2G4OFDM_BPSK; + int8_t cTxPwr2G4OFDM_QPSK; + int8_t cTxPwr2G4OFDM_16QAM; + int8_t cTxPwr2G4OFDM_Reserved; + int8_t cTxPwr2G4OFDM_48Mbps; + int8_t cTxPwr2G4OFDM_54Mbps; + + int8_t cTxPwr2G4HT20_BPSK; + int8_t cTxPwr2G4HT20_QPSK; + int8_t cTxPwr2G4HT20_16QAM; + int8_t cTxPwr2G4HT20_MCS5; + int8_t cTxPwr2G4HT20_MCS6; + int8_t cTxPwr2G4HT20_MCS7; + + int8_t cTxPwr2G4HT40_BPSK; + int8_t cTxPwr2G4HT40_QPSK; + int8_t cTxPwr2G4HT40_16QAM; + int8_t cTxPwr2G4HT40_MCS5; + int8_t cTxPwr2G4HT40_MCS6; + int8_t cTxPwr2G4HT40_MCS7; + + int8_t cTxPwr5GOFDM_BPSK; + int8_t cTxPwr5GOFDM_QPSK; + int8_t cTxPwr5GOFDM_16QAM; + int8_t cTxPwr5GOFDM_Reserved; + int8_t cTxPwr5GOFDM_48Mbps; + int8_t cTxPwr5GOFDM_54Mbps; + + int8_t cTxPwr5GHT20_BPSK; + int8_t cTxPwr5GHT20_QPSK; + int8_t cTxPwr5GHT20_16QAM; + int8_t cTxPwr5GHT20_MCS5; + int8_t cTxPwr5GHT20_MCS6; + int8_t cTxPwr5GHT20_MCS7; + + int8_t cTxPwr5GHT40_BPSK; + int8_t cTxPwr5GHT40_QPSK; + int8_t cTxPwr5GHT40_16QAM; + int8_t cTxPwr5GHT40_MCS5; + int8_t cTxPwr5GHT40_MCS6; + int8_t cTxPwr5GHT40_MCS7; +}; + +struct CMD_TX_AC_PWR { + int8_t ucBand; +#if 0 + int8_t c11AcTxPwr_BPSK; + int8_t c11AcTxPwr_QPSK; + int8_t c11AcTxPwr_16QAM; + int8_t c11AcTxPwr_MCS5_MCS6; + int8_t c11AcTxPwr_MCS7; + int8_t c11AcTxPwr_MCS8; + int8_t c11AcTxPwr_MCS9; + int8_t c11AcTxPwrVht40_OFFSET; + int8_t c11AcTxPwrVht80_OFFSET; + int8_t c11AcTxPwrVht160_OFFSET; +#else + struct AC_PWR_SETTING_STRUCT rAcPwr; +#endif +}; + +struct CMD_RSSI_PATH_COMPASATION { + int8_t c2GRssiCompensation; + int8_t c5GRssiCompensation; +}; +struct CMD_5G_PWR_OFFSET { + int8_t cOffsetBand0; /* 4.915-4.980G */ + int8_t cOffsetBand1; /* 5.000-5.080G */ + int8_t cOffsetBand2; /* 5.160-5.180G */ + int8_t cOffsetBand3; /* 5.200-5.280G */ + int8_t cOffsetBand4; /* 5.300-5.340G */ + int8_t cOffsetBand5; /* 5.500-5.580G */ + int8_t cOffsetBand6; /* 5.600-5.680G */ + int8_t cOffsetBand7; /* 5.700-5.825G */ +}; + +struct CMD_PWR_PARAM { + uint32_t au4Data[28]; + uint32_t u4RefValue1; + uint32_t u4RefValue2; +}; + +struct CMD_PHY_PARAM { + uint8_t aucData[144]; /* eFuse content */ +}; + +struct CMD_AUTO_POWER_PARAM { + /* 0: Disable 1: Enalbe 0x10: Change parameters */ + uint8_t ucType; + uint8_t ucBssIndex; + uint8_t aucReserved[2]; + uint8_t aucLevelRcpiTh[3]; + uint8_t aucReserved2[1]; + int8_t aicLevelPowerOffset[3]; /* signed, in unit of 0.5dBm */ + uint8_t aucReserved3[1]; + uint8_t aucReserved4[8]; +}; + +/*for WMMAC, CMD_ID_UPDATE_AC_PARAMS*/ +struct CMD_UPDATE_AC_PARAMS { + uint8_t ucAcIndex; /*0 ~3, from AC0 to AC3*/ + uint8_t ucBssIdx; /*no use*/ + /* if 0, disable ACM for ACx specified by + ** ucAcIndex, otherwise in unit of 32us + */ + uint16_t u2MediumTime; + /* rate to be used to tx packet with priority + ** ucAcIndex , unit: bps + */ + uint32_t u4PhyRate; + uint16_t u2EDCALifeTime; /* msdu life time for this TC, unit: 2TU */ + /* if we use fix rate to tx packets, should tell + ** firmware the limited retries + */ + uint8_t ucRetryCount; + uint8_t aucReserved[5]; +}; + +/* S56 Traffic Stream Metrics */ +struct CMD_SET_TSM_STATISTICS_REQUEST { + uint8_t ucEnabled; /* 0, disable; 1, enable; */ + uint8_t ucBssIdx; /* always AIS Bss index now */ + uint8_t ucAcIndex; /* wmm ac index, the statistics should be on this TC + */ + uint8_t ucTid; + + uint8_t aucPeerAddr + [MAC_ADDR_LEN]; /* packet to the target address to be mesured */ + uint8_t ucBin0Range; + uint8_t aucReserved[3]; + + /* if this variable is 0, followed variables are meaningless + ** only report once for a same trigger condition in this time frame + ** for triggered mode: bit(0):average, bit(1):consecutive, + ** bit(2):delay + */ + uint8_t ucTriggerCondition; + uint8_t ucAvgErrThreshold; + uint8_t ucConsecutiveErrThreshold; + uint8_t ucDelayThreshold; + uint8_t ucMeasureCount; + uint8_t ucTriggerTimeout; /* unit: 100 TU*/ +}; + +struct CMD_GET_TSM_STATISTICS { + uint8_t ucBssIdx; /* always AIS Bss now */ + /* wmm ac index, the statistics should be on this TC or TS */ + uint8_t ucAcIndex; + uint8_t ucTid; /* */ + + uint8_t aucPeerAddr + [MAC_ADDR_LEN]; /* indicating the RA for the measured frames */ + /* for triggered mode: bit(0):average, bit(1):consecutive, + ** bit(2):delay + */ + uint8_t ucReportReason; + uint16_t u2Reserved; + + uint32_t u4PktTxDoneOK; + uint32_t u4PktDiscard; /* u2PktTotal - u2PktTxDoneOK */ + uint32_t u4PktFail; /* failed count for exceeding retry limit */ + uint32_t u4PktRetryTxDoneOK; + uint32_t u4PktQosCfPollLost; + + /* 802.11k - Average Packet Transmission delay for all packets per this + ** TC or TS + */ + uint32_t u4AvgPktTxDelay; + /* 802.11k - Average Packet Queue Delay */ + uint32_t u4AvgPktQueueDelay; + uint64_t u8StartTime; /* represented by TSF */ + /* sum of packets whose packet tx delay is less than Bi (i=0~6) range + ** value(unit: TU) + */ + uint32_t au4PktCntBin[6]; +}; + +struct CMD_DBDC_SETTING { + uint8_t ucDbdcEn; + uint8_t ucWmmBandBitmap; + uint8_t ucUpdateSettingNextChReq; + uint8_t aucPadding0[1]; + uint8_t ucCmdVer; + uint8_t aucPadding1[1]; + uint16_t u2CmdLen; + uint8_t ucPrimaryChannel; + uint8_t ucWmmQueIdx; + uint8_t aucPadding2[2]; + uint8_t aucPadding3[24]; +}; + +#if (CFG_SUPPORT_DFS_MASTER == 1) +struct LONG_PULSE_BUFFER { + uint32_t u4LongStartTime; + uint16_t u2LongPulseWidth; +}; + +struct PERIODIC_PULSE_BUFFER { + uint32_t u4PeriodicStartTime; + uint16_t u2PeriodicPulseWidth; + int16_t i2PeriodicPulsePower; +}; + +struct EVENT_RDD_REPORT { + /*0: Only report radar detected; 1: Add parameter reports*/ + uint8_t ucRadarReportMode; + uint8_t ucRddIdx; + uint8_t ucLongDetected; + uint8_t ucPeriodicDetected; + uint8_t ucLPBNum; + uint8_t ucPPBNum; + uint8_t ucLPBPeriodValid; + uint8_t ucLPBWidthValid; + uint8_t ucPRICountM1; + uint8_t ucPRICountM1TH; + uint8_t ucPRICountM2; + uint8_t ucPRICountM2TH; + uint32_t u4PRI1stUs; + struct LONG_PULSE_BUFFER arLpbContent[32]; + struct PERIODIC_PULSE_BUFFER arPpbContent[32]; +}; +#endif + +struct EVENT_DEBUG_MSG { + uint16_t u2DebugMsgId; + uint8_t ucMsgType; + uint8_t ucFlags; /* unused */ + uint32_t u4Value; /* memory addre or ... */ + uint16_t u2MsgSize; + uint8_t aucReserved0[2]; + uint8_t aucMsg[1]; +}; + +struct CMD_EDGE_TXPWR_LIMIT { + int8_t cBandEdgeMaxPwrCCK; + int8_t cBandEdgeMaxPwrOFDM20; + int8_t cBandEdgeMaxPwrOFDM40; + int8_t cBandEdgeMaxPwrOFDM80; +}; + +struct CMD_POWER_OFFSET { + uint8_t ucBand; /*1:2.4G ; 2:5G */ + /*the max num subband is 5G, devide with 8 subband */ + uint8_t ucSubBandOffset[MAX_SUBBAND_NUM_5G]; + uint8_t aucReverse[3]; + +}; + +struct CMD_NVRAM_SETTING { + + struct WIFI_CFG_PARAM_STRUCT rNvramSettings; + +}; +struct CMD_NVRAM_FRAGMENT { + /*restrict NVRAM TX CMD size to 1500 bytes*/ + /*because FW WFDMA MAX buf size is 1600 Byte*/ + uint8_t aucReverse[1500]; +}; +#if CFG_SUPPORT_TDLS +struct CMD_TDLS_CH_SW { + u_int8_t fgIsTDLSChSwProhibit; + /* uint8_t ucBssIndex; */ +}; +#endif + +struct CMD_SET_DEVICE_MODE { + uint16_t u2ChipID; + uint16_t u2Mode; +}; + +#if CFG_SUPPORT_RDD_TEST_MODE +struct CMD_RDD_CH { + uint8_t ucRddTestMode; + uint8_t ucRddShutCh; + uint8_t ucRddStartCh; + uint8_t ucRddStopCh; + uint8_t ucRddDfs; + uint8_t ucReserved; + uint8_t ucReserved1; + uint8_t ucReserved2; +}; +#endif + +struct EVENT_ICAP_STATUS { + uint8_t ucRddStatus; + uint8_t aucReserved[3]; + uint32_t u4StartAddress; + uint32_t u4IcapSieze; +#if CFG_SUPPORT_QA_TOOL + uint32_t u4IcapContent; +#endif /* CFG_SUPPORT_QA_TOOL */ +}; + +#if CFG_SUPPORT_QA_TOOL +struct ADC_BUS_FMT { + uint32_t u4Dcoc0Q: 14; /* [13:0] */ + uint32_t u4Dcoc0I: 14; /* [27:14] */ + uint32_t u4DbgData1: 4; /* [31:28] */ + + uint32_t u4Dcoc1Q: 14; /* [45:32] */ + uint32_t u4Dcoc1I: 14; /* [46:59] */ + uint32_t u4DbgData2: 4; /* [63:60] */ + + uint32_t u4DbgData3; /* [95:64] */ +}; + +struct IQC_BUS_FMT { + int32_t u4Iqc0Q: 12; /* [11:0] */ + int32_t u4Iqc0I: 12; /* [23:12] */ + int32_t u4Na1: 8; /* [31:24] */ + + int32_t u4Iqc1Q: 12; /* [43:32] */ + int32_t u4Iqc1I: 12; /* [55:44] */ + int32_t u4Na2: 8; /* [63:56] */ + + int32_t u4Na3; /* [95:64] */ +}; + +struct IQC_160_BUS_FMT { + int32_t u4Iqc0Q1: 12; /* [11:0] */ + int32_t u4Iqc0I1: 12; /* [23:12] */ + uint32_t u4Iqc0Q0P1: 8; /* [31:24] */ + + int32_t u4Iqc0Q0P2: 4; /* [35:32] */ + int32_t u4Iqc0I0: 12; /* [47:36] */ + int32_t u4Iqc1Q1: 12; /* [59:48] */ + uint32_t u4Iqc1I1P1: 4; /* [63:60] */ + + int32_t u4Iqc1I1P2: 8; /* [71:64] */ + int32_t u4Iqc1Q0: 12; /* [83:72] */ + int32_t u4Iqc1I0: 12; /* [95:84] */ +}; + +struct SPECTRUM_BUS_FMT { + int32_t u4DcocQ: 12; /* [11:0] */ + int32_t u4DcocI: 12; /* [23:12] */ + int32_t u4LpfGainIdx: 4; /* [27:24] */ + int32_t u4LnaGainIdx: 2; /* [29:28] */ + int32_t u4AssertData: 2; /* [31:30] */ +}; + +struct PACKED_ADC_BUS_FMT { + uint32_t u4AdcQ0T2: 4; /* [19:16] */ + uint32_t u4AdcQ0T1: 4; /* [11:8] */ + uint32_t u4AdcQ0T0: 4; /* [3:0] */ + + uint32_t u4AdcI0T2: 4; /* [23:20] */ + uint32_t u4AdcI0T1: 4; /* [15:12] */ + uint32_t u4AdcI0T0: 4; /* [7:4] */ + + uint32_t u4AdcQ0T5: 4; /* [43:40] */ + uint32_t u4AdcQ0T4: 4; /* [35:32] */ + uint32_t u4AdcQ0T3: 4; /* [27:24] */ + + uint32_t u4AdcI0T5: 4; /* [47:44] */ + uint32_t u4AdcI0T4: 4; /* [39:36] */ + uint32_t u4AdcI0T3: 4; /* [31:28] */ + + uint32_t u4AdcQ1T2: 4; /* [19:16] */ + uint32_t u4AdcQ1T1: 4; /* [11:8] */ + uint32_t u4AdcQ1T0: 4; /* [3:0] */ + + uint32_t u4AdcI1T2: 4; /* [23:20] */ + uint32_t u4AdcI1T1: 4; /* [15:12] */ + uint32_t u4AdcI1T0: 4; /* [7:4] */ + + uint32_t u4AdcQ1T5: 4; /* [43:40] */ + uint32_t u4AdcQ1T4: 4; /* [35:32] */ + uint32_t u4AdcQ1T3: 4; /* [27:24] */ + + uint32_t u4AdcI1T5: 4; /* [47:44] */ + uint32_t u4AdcI1T4: 4; /* [39:36] */ + uint32_t u4AdcI1T3: 4; /* [31:28] */ +}; + +union ICAP_BUS_FMT { + struct ADC_BUS_FMT rAdcBusData; /* 12 bytes */ + struct IQC_BUS_FMT rIqcBusData; /* 12 bytes */ + struct IQC_160_BUS_FMT rIqc160BusData; /* 12 bytes */ + struct SPECTRUM_BUS_FMT rSpectrumBusData; /* 4 bytes */ + struct PACKED_ADC_BUS_FMT rPackedAdcBusData; /* 12 bytes */ +}; +#endif /* CFG_SUPPORT_QA_TOOL */ + +struct CMD_SET_TXPWR_CTRL { + int8_t c2GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0 */ + int8_t c2GHotspotPwrOffset; + int8_t c2GP2pPwrOffset; + int8_t c2GBowPwrOffset; + int8_t c5GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0 */ + int8_t c5GHotspotPwrOffset; + int8_t c5GP2pPwrOffset; + int8_t c5GBowPwrOffset; + /* TX power policy when concurrence + * in the same channel + * 0: Highest power has priority + * 1: Lowest power has priority + */ + uint8_t ucConcurrencePolicy; + int8_t acReserved1[3]; /* Must be zero */ + + /* Power limit by channel for all data rates */ + int8_t acTxPwrLimit2G[14]; /* Channel 1~14, Unit: 0.5dBm */ + int8_t acTxPwrLimit5G[4]; /* UNII 1~4 */ + int8_t acReserved2[2]; /* Must be zero */ +}; + +struct SSID_MATCH_SETS { + int32_t i4RssiThresold; + uint8_t aucSsid[32]; + uint8_t ucSsidLen; + uint8_t aucPadding_1[3]; +}; + +struct CMD_SCHED_SCAN_REQ { + uint8_t ucVersion; + uint8_t ucSeqNum; + uint8_t fgStopAfterIndication; + uint8_t ucSsidNum; + uint8_t ucMatchSsidNum; + uint8_t aucPadding_0; + uint16_t u2IELen; + struct PARAM_SSID auSsid[10]; + struct SSID_MATCH_SETS auMatchSsid[16]; + uint8_t ucChannelType; + uint8_t ucChnlNum; + uint8_t ucMspEntryNum; + uint8_t ucScnFuncMask; + struct CHANNEL_INFO aucChannel[64]; + uint16_t au2MspList[10]; + uint8_t ucBssIndex; + uint32_t u4DelayStartInSec; + uint32_t u4FastScanIteration; + uint32_t u4FastScanPeriod; + uint32_t u4SlowScanPeriod; + uint8_t aucPadding_3[47]; + /* keep last */ + uint8_t aucIE[0]; /* MUST be the last for IE content */ +}; + +struct EVENT_SCHED_SCAN_DONE { + uint8_t ucSeqNum; + uint8_t ucStatus; + uint8_t aucReserved[2]; +}; + +enum ENUM_HIF_TYPE { + ENUM_HIF_TYPE_SDIO = 0x00, + ENUM_HIF_TYPE_USB = 0x01, + ENUM_HIF_TYPE_PCIE = 0x02, + ENUM_HIF_TYPE_GPIO = 0x03, +}; + +enum ENUM_HIF_DIRECTION { + ENUM_HIF_TX = 0x01, + ENUM_HIF_RX = 0x02, + ENUM_HIF_TRX = 0x03, +}; + +enum ENUM_HIF_TRAFFIC_STATUS { + ENUM_HIF_TRAFFIC_BUSY = 0x01, + ENUM_HIF_TRAFFIC_IDLE = 0x02, + ENUM_HIF_TRAFFIC_INVALID = 0x3, +}; + +struct EVENT_HIF_CTRL { + uint8_t ucHifType; + uint8_t ucHifTxTrafficStatus; + uint8_t ucHifRxTrafficStatus; + uint8_t ucHifSuspend; + uint8_t aucReserved2[32]; +}; + +#if CFG_SUPPORT_BUILD_DATE_CODE +struct CMD_GET_BUILD_DATE_CODE { + uint8_t aucReserved[4]; +}; +#endif + +struct CMD_GET_STA_STATISTICS { + uint8_t ucIndex; + uint8_t ucFlags; + uint8_t ucReadClear; + uint8_t ucLlsReadClear; + uint8_t aucMacAddr[MAC_ADDR_LEN]; + uint8_t ucResetCounter; + uint8_t aucReserved1[1]; + uint8_t aucReserved2[16]; +}; + +/* per access category statistics */ +struct WIFI_WMM_AC_STAT_GET_FROM_FW { + uint32_t u4TxFailMsdu; + uint32_t u4TxRetryMsdu; +}; + +/* CFG_SUPPORT_WFD */ +struct EVENT_STA_STATISTICS { + /* Event header */ + /* UINT_16 u2Length; */ + /* Must be filled with 0x0001 (EVENT Packet) */ + /* UINT_16 u2Reserved1; */ + /* UINT_8 ucEID; */ + /* UINT_8 ucSeqNum; */ + /* UINT_8 aucReserved2[2]; */ + + /* Event Body */ + uint8_t ucVersion; + uint8_t aucReserved1[3]; + uint32_t u4Flags; /* Bit0: valid */ + + uint8_t ucStaRecIdx; + uint8_t ucNetworkTypeIndex; + uint8_t ucWTEntry; + uint8_t aucReserved4[1]; + + uint8_t ucMacAddr[MAC_ADDR_LEN]; + uint8_t ucPer; /* base: 128 */ + uint8_t ucRcpi; + + uint32_t u4PhyMode; /* SGI BW */ + uint16_t u2LinkSpeed; /* unit is 0.5 Mbits */ + uint8_t ucLinkQuality; + uint8_t ucLinkReserved; + + uint32_t u4TxCount; + uint32_t u4TxFailCount; + uint32_t u4TxLifeTimeoutCount; + uint32_t u4TxDoneAirTime; + /* Transmit in the air (wtbl) */ + uint32_t u4TransmitCount; + /* Transmit without ack/ba in the air (wtbl) */ + uint32_t u4TransmitFailCount; + + struct WIFI_WMM_AC_STAT_GET_FROM_FW + arLinkStatistics[AC_NUM]; /*link layer statistics */ + + uint8_t ucTemperature; + uint8_t ucSkipAr; + uint8_t ucArTableIdx; + uint8_t ucRateEntryIdx; + uint8_t ucRateEntryIdxPrev; + uint8_t ucTxSgiDetectPassCnt; + uint8_t ucAvePer; +#if (CFG_SUPPORT_RA_GEN == 0) + uint8_t aucArRatePer[AR_RATE_TABLE_ENTRY_MAX]; + uint8_t aucRateEntryIndex[AUTO_RATE_NUM]; +#else + uint32_t u4AggRangeCtrl_0; + uint32_t u4AggRangeCtrl_1; + uint8_t ucRangeType; +#if (CFG_SUPPORT_CONNAC2X == 0) + uint8_t aucReserved5[24]; +#else + uint32_t u4AggRangeCtrl_2; + uint32_t u4AggRangeCtrl_3; + uint8_t aucReserved5[16]; +#endif +#endif + uint8_t ucArStateCurr; + uint8_t ucArStatePrev; + uint8_t ucArActionType; + uint8_t ucHighestRateCnt; + uint8_t ucLowestRateCnt; + uint16_t u2TrainUp; + uint16_t u2TrainDown; + uint32_t u4Rate1TxCnt; + uint32_t u4Rate1FailCnt; + struct TX_VECTOR_BBP_LATCH rTxVector[ENUM_BAND_NUM]; + struct MIB_INFO_STAT rMibInfo[ENUM_BAND_NUM]; + u_int8_t fgIsForceTxStream; + u_int8_t fgIsForceSeOff; +#if (CFG_SUPPORT_RA_GEN == 0) + uint8_t aucReserved6[17]; +#else + uint16_t u2RaRunningCnt; + uint8_t ucRaStatus; + uint8_t ucFlag; + uint8_t aucTxQuality[MAX_TX_QUALITY_INDEX]; + uint8_t ucTxRateUpPenalty; + uint8_t ucLowTrafficMode; + uint8_t ucLowTrafficCount; + uint8_t ucLowTrafficDashBoard; + uint8_t ucDynamicSGIState; + uint8_t ucDynamicSGIScore; + uint8_t ucDynamicBWState; + uint8_t ucDynamicGband256QAMState; + uint8_t ucVhtNonSpRateState; +#endif + uint8_t aucReserved[4]; +}; + +struct EVENT_LTE_SAFE_CHN { + uint8_t ucVersion; + uint8_t aucReserved[3]; + uint32_t u4Flags; /* Bit0: valid */ + struct LTE_SAFE_CHN_INFO rLteSafeChn; +}; + +#if CFG_SUPPORT_SNIFFER +struct CMD_MONITOR_SET_INFO { + uint8_t ucEnable; + uint8_t ucBand; + uint8_t ucPriChannel; + uint8_t ucSco; + uint8_t ucChannelWidth; + uint8_t ucChannelS1; + uint8_t ucChannelS2; + uint8_t aucResv[9]; +}; +#endif + +struct CMD_STATS_LOG { + uint32_t u4DurationInMs; + uint8_t aucReserved[32]; +}; + +struct EVENT_WIFI_RDD_TEST { + uint32_t u4FuncIndex; + uint32_t u4FuncLength; + uint32_t u4Prefix; + uint32_t u4Count; + uint8_t ucRddIdx; + uint8_t aucReserve[3]; + uint8_t aucBuffer[0]; +}; + +#if CFG_SUPPORT_MSP +/* EVENT_ID_WTBL_INFO */ +struct EVENT_WLAN_INFO { + + struct PARAM_TX_CONFIG rWtblTxConfig; + struct PARAM_SEC_CONFIG rWtblSecConfig; + struct PARAM_KEY_CONFIG rWtblKeyConfig; + struct PARAM_PEER_RATE_INFO rWtblRateInfo; + struct PARAM_PEER_BA_CONFIG rWtblBaConfig; + struct PARAM_PEER_CAP rWtblPeerCap; + struct PARAM_PEER_RX_COUNTER_ALL rWtblRxCounter; + struct PARAM_PEER_TX_COUNTER_ALL rWtblTxCounter; +}; + +/* EVENT_ID_MIB_INFO */ +struct EVENT_MIB_INFO { + struct HW_MIB_COUNTER rHwMibCnt; + struct HW_MIB2_COUNTER rHwMib2Cnt; + struct HW_TX_AMPDU_METRICS rHwTxAmpduMts; + +}; +#endif + +/*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ +struct EVENT_ACCESS_EFUSE { + + uint32_t u4Address; + uint32_t u4Valid; + uint8_t aucData[16]; + +}; + +struct EXT_EVENT_EFUSE_FREE_BLOCK { + uint16_t u2FreeBlockNum; + uint8_t aucReserved[2]; +}; + +struct EXT_EVENT_GET_TX_POWER { + + uint8_t ucTxPwrType; + uint8_t ucEfuseAddr; + uint8_t ucTx0TargetPower; + uint8_t ucDbdcIdx; + +}; + +struct EXT_EVENT_RF_TEST_RESULT_T { + uint32_t u4FuncIndex; + uint32_t u4PayloadLength; + uint8_t aucEvent[0]; +}; + +struct EXT_EVENT_RBIST_DUMP_DATA_T { + uint32_t u4FuncIndex; + uint32_t u4PktNum; + uint32_t u4Bank; + uint32_t u4DataLength; + uint32_t u4WFCnt; + uint32_t u4SmplCnt; + uint32_t u4Reserved[6]; + uint32_t u4Data[256]; +}; + +struct EXT_EVENT_RBIST_CAP_STATUS_T { + uint32_t u4FuncIndex; + uint32_t u4CapDone; + uint32_t u4Reserved[15]; +}; + +struct EXT_EVENT_RECAL_DATA_T { + uint32_t u4FuncIndex; + uint32_t u4Type; /* 0 for string, 1 for int data */ + union { + uint8_t ucData[32]; + uint32_t u4Data[3]; + } u; +}; + + +struct CMD_SUSPEND_MODE_SETTING { + uint8_t ucBssIndex; + uint8_t ucEnableSuspendMode; + uint8_t ucMdtim; /* LP parameter */ + uint8_t ucReserved1[1]; + uint8_t ucReserved2[64]; +}; + +struct EVENT_UPDATE_COEX_PHYRATE { + uint8_t ucVersion; + uint8_t aucReserved1[3]; /* 4 byte alignment */ + uint32_t u4Flags; + uint32_t au4PhyRateLimit[MAX_BSSID_NUM + 1]; + uint8_t ucSupportSisoOnly; + uint8_t ucWfPathSupport; + uint8_t aucReserved2[2]; /* 4 byte alignment */ +}; + +#if (CFG_SUPPORT_TWT == 1) +/* + * Important: Used for Communication between Host and WM-CPU, + * should be packed and DW-aligned and in little-endian format + */ +struct _EXT_CMD_TWT_ARGT_UPDATE_T { + /* DW0 */ + uint8_t ucAgrtTblIdx; + uint8_t ucAgrtCtrlFlag; + uint8_t ucOwnMacId; + uint8_t ucFlowId; + /* DW1 */ + /* Specify the peer ID (MSB=0) or group ID (MSB=1) + * (10 bits for StaIdx, MSB to identify if it is for groupId) + */ + uint16_t u2PeerIdGrpId; + + /* Same as SPEC definition. 8 bits, in unit of 256 us */ + uint8_t ucAgrtSpDuration; + /* So that we know which BSS TSF should be used for this AGRT */ + uint8_t ucBssIndex; + /* DW2, DW3, DW4 */ + uint32_t u4AgrtSpStartTsfLow; + uint32_t u4AgrtSpStartTsfHigh; + uint16_t u2AgrtSpWakeIntvlMantissa; + uint8_t ucAgrtSpWakeIntvlExponent; + uint8_t ucIsRoleAp; /* 1: AP, 0: STA */ + /* DW5 */ + /* For Bitmap definition, please refer to + * TWT_AGRT_PARA_BITMAP_IS_TRIGGER and etc + */ + uint8_t ucAgrtParaBitmap; + uint8_t ucReserved_a; + /* Following field is valid ONLY when peerIdGrpId is a group ID */ + uint16_t u2Reserved_b; + /* DW6 */ + uint8_t ucGrpMemberCnt; + uint8_t ucReserved_c; + uint16_t u2Reserved_d; + /* DW7 ~ DW10 */ + uint16_t au2StaList[TWT_GRP_MAX_MEMBER_CNT]; +}; +#endif + +#if (CFG_SUPPORT_802_11AX == 1) +struct _CMD_RLM_UPDATE_SR_PARMS_T { + /* DWORD_0 - Common Part */ + uint8_t ucCmdVer; + uint8_t aucPadding0[1]; + uint16_t u2CmdLen; /* Cmd size including common part and body */ + + /* DWORD_1 afterwards - Command Body */ + uint8_t ucBssIndex; + uint8_t ucSRControl; + uint8_t ucNonSRGObssPdMaxOffset; + uint8_t ucSRGObssPdMinOffset; + uint8_t ucSRGObssPdMaxOffset; + uint8_t aucPadding1[3]; + uint32_t u4SRGBSSColorBitmapLow; + uint32_t u4SRGBSSColorBitmapHigh; + uint32_t u4SRGPartialBSSIDBitmapLow; + uint32_t u4SRGPartialBSSIDBitmapHigh; + + uint8_t aucPadding2[32]; +}; + +struct _EXTRA_ARG_TSF_T { + uint8_t ucHwBssidIndex; + uint8_t aucReserved[3]; +}; + +union _EXTRA_ARG_MAC_INFO_T { + struct _EXTRA_ARG_TSF_T rTsfArg; +}; + +struct _EXT_CMD_GET_MAC_INFO_T { + uint16_t u2MacInfoId; + uint8_t aucReserved[2]; + union _EXTRA_ARG_MAC_INFO_T rExtraArgument; +}; +#endif + +struct TSF_RESULT_T { + uint32_t u4TsfBitsLow; + uint32_t u4TsfBitsHigh; +}; + +union MAC_INFO_RESULT_T { + struct TSF_RESULT_T rTsfResult; +}; + +struct EXT_EVENT_MAC_INFO_T { + uint16_t u2MacInfoId; + uint8_t aucReserved[2]; + union MAC_INFO_RESULT_T rMacInfoResult; +}; + +struct EXT_CMD_EVENT_DUMP_MEM_T { + uint32_t u4MemAddr; + uint8_t ucData[64]; +}; + +/*#endif*/ +struct CMD_TDLS_PS_T { + /* 0: disable tdls power save; 1: enable tdls power save */ + uint8_t ucIsEnablePs; + uint8_t aucReserved[3]; +}; + +/** struct for power rate control command **/ +struct CMD_POWER_RATE_TXPOWER_CTRL_T { + uint8_t u1PowerCtrlFormatId; + uint8_t u1PhyMode; + uint8_t u1TxRate; + uint8_t u1BW; + uint8_t u1BandIdx; + int8_t i1TxPower; + uint8_t u1Reserved[2]; +}; + + +#if (CFG_SUPPORT_TXPOWER_INFO == 1) +struct CMD_TX_POWER_SHOW_INFO_T { + uint8_t ucPowerCtrlFormatId; + uint8_t ucTxPowerInfoCatg; + uint8_t ucBandIdx; + uint8_t ucReserved; +}; + +struct EXT_EVENT_TXPOWER_ALL_RATE_POWER_INFO_T { + uint8_t ucTxPowerCategory; + uint8_t ucBandIdx; + uint8_t ucChBand; + uint8_t ucReserved; + + /* Rate power info */ + struct FRAME_POWER_CONFIG_INFO_T rRatePowerInfo; + + /* tx Power Max/Min Limit info */ + int8_t icPwrMaxBnd; + int8_t icPwrMinBnd; + uint8_t ucReserved2; +}; +#endif + +struct EXT_EVENT_MAX_AMSDU_LENGTH_UPDATE { + uint8_t ucWlanIdx; + uint8_t ucAmsduLen; +}; + +struct EVENT_LOW_LATENCY_INFO { + /* DWORD_0 - Common Part */ + uint8_t ucEvtVer; + uint8_t aucPadding0[1]; + uint16_t u2EvtLen; + + /* DWORD_1 - afterwards */ + u_int8_t fgTxDupCert; + u_int8_t fgTxDupEnable; + uint8_t aucPadding1[2]; + uint8_t aucPayload[1024]; +}; + +/******************************************************************************* + * P U B 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 NIC_FILL_CMD_TX_HDR(__prAd, __pucInfoBuffer, __u2InfoBufLen, \ + __ucCID, __ucPktTypeID, __pucSeqNum, __fgSetQuery, __ppCmdBuf, \ + __bucInitCmd, __ucExtCID, __ucS2DIndex) \ +{ \ + struct mt66xx_chip_info *__prChipInfo; \ + struct WIFI_CMD_INFO __wifi_cmd_info; \ + __prChipInfo = __prAd->chip_info; \ + __wifi_cmd_info.pucInfoBuffer = __pucInfoBuffer; \ + __wifi_cmd_info.u2InfoBufLen = __u2InfoBufLen; \ + __wifi_cmd_info.ucCID = __ucCID; \ + __wifi_cmd_info.ucExtCID = __ucExtCID; \ + __wifi_cmd_info.ucPktTypeID = __ucPktTypeID; \ + __wifi_cmd_info.ucSetQuery = __fgSetQuery; \ + __wifi_cmd_info.ucS2DIndex = __ucS2DIndex; \ + if (__bucInitCmd) { \ + ASSERT(__prChipInfo->asicFillInitCmdTxd); \ + __prChipInfo->asicFillInitCmdTxd(__prAd, &(__wifi_cmd_info), \ + (&__u2InfoBufLen), __pucSeqNum, (void **)__ppCmdBuf); \ + } else { \ + ASSERT(__prChipInfo->asicFillCmdTxd); \ + __prChipInfo->asicFillCmdTxd(__prAd, &(__wifi_cmd_info), \ + __pucSeqNum, (void **)__ppCmdBuf); \ + } \ +} + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +void nicCmdEventQueryMcrRead(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventQueryCfgRead(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +#if CFG_SUPPORT_QA_TOOL +void nicCmdEventQueryRxStatistics(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +uint32_t nicTsfRawData2IqFmt(struct EVENT_DUMP_MEM *prEventDumpMem, + struct ICAP_INFO_T *prIcap); +uint32_t nicExtTsfRawData2IqFmt( + struct EXT_EVENT_RBIST_DUMP_DATA_T *prEventDumpMem, + struct ICAP_INFO_T *prIcap); + +int32_t GetIQData(struct ADAPTER *prAdapter, + int32_t **prIQAry, uint32_t *prDataLen, uint32_t u4IQ, + uint32_t u4GetWf1); + +#if CFG_SUPPORT_TX_BF +void nicCmdEventPfmuDataRead(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventPfmuTagRead(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); +#endif /* CFG_SUPPORT_TX_BF */ +#if CFG_SUPPORT_MU_MIMO +void nicCmdEventGetQd(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); +void nicCmdEventGetCalcLq(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); +void nicCmdEventGetCalcInitMcs(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); +#endif /* CFG_SUPPORT_MU_MIMO */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +void nicCmdEventQueryCalBackupV2(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); +#endif +#if 0 +void nicEventQueryMemDump(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf); +#endif + +void nicCmdEventQueryMemDump(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventQuerySwCtrlRead(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +void nicCmdEventQueryChipConfig(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +void nicCmdEventQueryRfTestATInfo(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +void nicCmdEventSetCommon(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventSetIpAddress(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventQueryLinkQuality(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +void nicCmdEventQueryLinkSpeed(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventQueryLinkSpeedEx(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventQueryStatistics(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +void nicCmdEventEnterRfTest(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventLeaveRfTest(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventQueryMcastAddr(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventQueryEepromRead(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +void nicCmdEventSetMediaStreamMode(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +void nicCmdEventSetStopSchedScan(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +/* for timeout check */ +void nicOidCmdTimeoutCommon(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo); + +void nicCmdTimeoutCommon(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo); + +void nicOidCmdEnterRFTestTimeout(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo); + +#if CFG_SUPPORT_BUILD_DATE_CODE +void nicCmdEventBuildDateCode(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); +#endif + +void nicCmdEventQueryStaStatistics(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +void nicCmdEventQueryBugReport(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventQueryLteSafeChn(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +#if CFG_SUPPORT_BATCH_SCAN +void nicCmdEventBatchScanResult(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); +#endif + +void nicEventRddPulseDump(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf); + +#if (CFG_SUPPORT_TXPOWER_INFO == 1) +void nicCmdEventQueryTxPowerInfo(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); +#endif + +void nicCmdEventQueryWlanInfo(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventQueryMibInfo(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventQueryNicCapabilityV2(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); + +uint32_t nicCmdEventQueryNicTxResource(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); +uint32_t nicCmdEventQueryNicEfuseAddr(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); +uint32_t nicCmdEventQueryNicCoexFeature(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); +#if CFG_TCP_IP_CHKSUM_OFFLOAD +uint32_t nicCmdEventQueryNicCsumOffload(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); +#endif +uint32_t nicCfgChipCapHwVersion(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); +uint32_t nicCfgChipCapSwVersion(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); +uint32_t nicCfgChipCapMacAddr(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf); +uint32_t nicCfgChipCapPhyCap(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf); +uint32_t nicCfgChipCapMacCap(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf); +uint32_t nicCfgChipCapFrameBufCap(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); +uint32_t nicCfgChipCapBeamformCap(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); +uint32_t nicCfgChipCapLocationCap(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); +uint32_t nicCfgChipCapMuMimoCap(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); +uint32_t nicCfgChipAdieHwVersion(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf); +#if CFG_SUPPORT_ANT_SWAP +uint32_t nicCfgChipCapAntSwpCap(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf); +#endif + +#if (CFG_SUPPORT_P2PGO_ACS == 1) + uint32_t nicCfgChipP2PCap(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf); + +#endif + +uint32_t nicCmdEventHostStatusEmiOffset(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf); + +void nicExtEventICapIQData(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf); +void nicExtEventQueryMemDump(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf); +void nicEventLinkQuality(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventLayer0ExtMagic(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventMicErrorInfo(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventScanDone(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventSchedScanDone(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventSleepyNotify(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventBtOverWifi(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventStatistics(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventWlanInfo(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventMibInfo(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventBeaconTimeout(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventUpdateNoaParams(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventStaAgingTimeout(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventApObssStatus(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventRoamingStatus(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventSendDeauth(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventUpdateRddStatus(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventUpdateBwcsStatus(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventUpdateBcmDebug(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventAddPkeyDone(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventIcapDone(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +void nicEventCalAllDone(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +#endif + +void nicEventDebugMsg(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventTdls(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventRssiMonitor(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventDumpMem(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventAssertDump(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventHifCtrl(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventRddSendPulse(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventUpdateCoexPhyrate(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +uint32_t nicEventQueryTxResource_v1(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); +uint32_t nicEventQueryTxResourceEntry(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); +uint32_t nicEventQueryTxResource(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); +void nicCmdEventQueryCnmInfo(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); +void nicEventCnmInfo(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +#if CFG_SUPPORT_REPLAY_DETECTION +void nicCmdEventSetAddKey(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); +void nicOidCmdTimeoutSetAddKey(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo); +#endif + +#if CFG_SUPPORT_LOWLATENCY_MODE +void nicEventUpdateLowLatencyInfoStatus(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +#endif + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _NIC_CMD_EVENT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic_ext_cmd_event.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic_ext_cmd_event.h new file mode 100644 index 0000000000000..e0b00c13c8a8e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic_ext_cmd_event.h @@ -0,0 +1,215 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "nic_ext_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. + */ + +#ifndef _NIC_EXT_CMD_EVENT_H +#define _NIC_EXT_CMD_EVENT_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ +#if (CFG_SUPPORT_CONNAC2X == 1) + +/******************************************************************************* + * 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 STAREC_COMMON_EXTRAINFO_V2 BIT(0) +#define STAREC_COMMON_EXTRAINFO_NEWSTAREC BIT(1) + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +struct STAREC_COMMON_T { + /* Basic STA record (Group0) */ + uint16_t u2Tag; /* Tag = 0x00 */ + uint16_t u2Length; + uint32_t u4ConnectionType; + uint8_t ucConnectionState; + uint8_t ucIsQBSS; + uint16_t u2AID; + uint8_t aucPeerMacAddr[6]; + uint16_t u2ExtraInfo; +} __KAL_ATTRIB_PACKED__; + +struct CMD_STAREC_UPDATE_T { + uint8_t ucBssIndex; + uint8_t ucWlanIdx; + uint16_t u2TotalElementNum; + uint8_t ucAppendCmdTLV; + uint8_t ucMuarIdx; + uint8_t aucReserve[2]; + uint8_t aucBuffer[]; +} __KAL_ATTRIB_PACKED__; + +struct STAREC_HANDLE_T { + uint32_t StaRecTag; + uint32_t StaRecTagLen; + int32_t (*StaRecTagHandler)( + struct ADAPTER *pAd, uint8_t *pMsgBuf, void *args); +}; + +#if (CFG_SUPPORT_DMASHDL_SYSDVT) +struct EXT_CMD_CR4_DMASHDL_DVT_T { + uint8_t ucItemNo; + uint8_t ucSubItemNo; + uint8_t ucReserve[2]; +}; +#endif /* CFG_SUPPORT_DMASHDL_SYSDVT */ + +struct CMD_BSSINFO_UPDATE_T { + uint8_t ucBssIndex; + uint8_t ucReserve; + uint16_t u2TotalElementNum; + uint32_t u4Reserve; + uint8_t aucBuffer[]; +} __KAL_ATTRIB_PACKED__; + + +/* TAG ID 0x00: */ +struct BSSINFO_CONNECT_OWN_DEV_T { + /* BSS connect to own dev (Tag0) */ + uint16_t u2Tag; /* Tag = 0x00 */ + uint16_t u2Length; + uint8_t ucHwBSSIndex; + uint8_t ucOwnMacIdx; + uint8_t aucReserve[2]; + uint32_t ucConnectionType; + uint32_t u4Reserved; +} __KAL_ATTRIB_PACKED__; + +/* TAG ID 0x01: */ +struct BSSINFO_BASIC_T { + /* Basic BSS information (Tag1) */ + uint16_t u2Tag; /* Tag = 0x01 */ + uint16_t u2Length; + uint32_t u4NetworkType; + uint8_t ucActive; + uint8_t ucReserve0; + uint16_t u2BcnInterval; + uint8_t aucBSSID[6]; + uint8_t ucWmmIdx; + uint8_t ucDtimPeriod; +/* indicate which wlan-idx used for MC/BC transmission */ + uint8_t ucBcMcWlanidx; + uint8_t ucCipherSuit; + uint8_t acuReserve[6]; +} __KAL_ATTRIB_PACKED__; + + +struct CMD_DEVINFO_UPDATE_T { + uint8_t ucOwnMacIdx; + uint8_t ucReserve; + uint16_t u2TotalElementNum; + uint32_t aucReserve; + uint8_t aucBuffer[]; +} __KAL_ATTRIB_PACKED__; + +struct CMD_DEVINFO_ACTIVE_T { + uint16_t u2Tag; /* Tag = 0x00 */ + uint16_t u2Length; + uint8_t ucActive; + uint8_t ucDbdcIdx; + uint8_t aucOwnMacAddr[6]; + uint8_t aucReserve[4]; +} __KAL_ATTRIB_PACKED__; + + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +uint32_t CmdExtStaRecUpdate2WA( + struct ADAPTER *pAd, + struct STA_RECORD *pStaRecCfg); + +#if (CFG_SUPPORT_DMASHDL_SYSDVT) +uint32_t CmdExtDmaShdlDvt2WA( + struct ADAPTER *pAd, + uint8_t ucItemNo, + uint8_t ucSubItemNo); +#endif /* CFG_SUPPORT_DMASHDL_SYSDVT */ + +uint32_t CmdExtBssInfoUpdate2WA( + struct ADAPTER *pAd, + uint8_t ucBssIndex); + +uint32_t CmdExtDevInfoUpdate2WA( + struct ADAPTER *pAd, + uint8_t ucBssIndex); + +#endif /* CFG_SUPPORT_CONNAC2X == 1 */ + +#endif /* _NIC_EXT_CMD_EVENT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic_init_cmd_event.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic_init_cmd_event.h new file mode 100644 index 0000000000000..ff4c704f3a1a4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/nic_init_cmd_event.h @@ -0,0 +1,326 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + +#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" +#include "wsys_cmd_handler_fw.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 INIT_PKT_FT_CMD 0x2 +#define INIT_PKT_FT_PDA_FWDL 0x3 + +#define INIT_CMD_PQ_ID (0x8000) +#define INIT_CMD_PACKET_TYPE_ID (0xA0) + +#define INIT_CMD_PDA_PQ_ID (0xF800) +#define INIT_CMD_PDA_PACKET_TYPE_ID (0xA0) + +#if (CFG_UMAC_GENERATION >= 0x20) +#define TXD_Q_IDX_MCU_RQ0 0 +#define TXD_Q_IDX_MCU_RQ1 1 +#define TXD_Q_IDX_MCU_RQ2 2 +#define TXD_Q_IDX_MCU_RQ3 3 + +#define TXD_Q_IDX_PDA_FW_DL 0x1E + +/* DW0 Bit31 */ +#define TXD_P_IDX_LMAC 0 +#define TXD_P_IDX_MCU 1 + +/* DW1 Bit 14:13 */ +#define TXD_HF_NON_80211_FRAME 0x0 +#define TXD_HF_CMD 0x1 +#define TXD_HF_80211_NORMAL 0x2 +#define TXD_HF_80211_ENHANCEMENT 0x3 + +/* DW1 Bit 15 */ +#define TXD_FT_OFFSET 15 +#define TXD_FT_SHORT_FORMAT 0x0 +#define TXD_FT_LONG_FORMAT 0x1 + +/* DW1 Bit 16 */ +#define TXD_TXDLEN_OFFSET 16 +#define TXD_TXDLEN_1PAGE 0x0 +#define TXD_TXDLEN_2PAGE 0x1 + +/* DW1 Bit 25:24 */ +#define TXD_PKT_FT_CUT_THROUGH 0x0 +#define TXD_PKT_FT_STORE_FORWARD 0X1 +#define TXD_PKT_FT_CMD 0X2 +#define TXD_PKT_FT_PDA_FW 0X3 +#endif + +enum ENUM_INIT_CMD_ID { + INIT_CMD_ID_DOWNLOAD_CONFIG = 1, + INIT_CMD_ID_WIFI_START, + INIT_CMD_ID_ACCESS_REG, + INIT_CMD_ID_QUERY_PENDING_ERROR, + INIT_CMD_ID_PATCH_START, + INIT_CMD_ID_PATCH_WRITE, + INIT_CMD_ID_PATCH_FINISH, + INIT_CMD_ID_PHY_ACTION, + + INIT_CMD_ID_PATCH_SEMAPHORE_CONTROL = 0x10, + INIT_CMD_ID_HIF_LOOPBACK = 0x20, + +#if (CFG_DOWNLOAD_DYN_MEMORY_MAP == 1) + INIT_CMD_ID_DYN_MEM_MAP_PATCH_FINISH = 0x40, + INIT_CMD_ID_DYN_MEM_MAP_FW_FINISH = 0x41, +#endif + +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + INIT_CMD_ID_DECOMPRESSED_WIFI_START = 0xFF, +#endif + INIT_CMD_ID_NUM +}; + +enum ENUM_INIT_EVENT_ID { + INIT_EVENT_ID_CMD_RESULT = 1, + INIT_EVENT_ID_ACCESS_REG, + INIT_EVENT_ID_PENDING_ERROR, + INIT_EVENT_ID_PATCH_SEMA_CTRL, + INIT_EVENT_ID_PHY_ACTION +}; + +enum ENUM_INIT_PATCH_STATUS { + PATCH_STATUS_NO_SEMA_NEED_PATCH = 0, /* no SEMA, need patch */ + PATCH_STATUS_NO_NEED_TO_PATCH, /* patch is DL & ready */ + PATCH_STATUS_GET_SEMA_NEED_PATCH, /* get SEMA, need patch */ + PATCH_STATUS_RELEASE_SEMA /* release SEMA */ +}; + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +struct WIFI_CMD_INFO { + uint16_t u2InfoBufLen; + uint8_t *pucInfoBuffer; + uint8_t ucCID; + uint8_t ucExtCID; + uint8_t ucPktTypeID; + uint8_t ucSetQuery; + uint8_t ucS2DIndex; +}; + +/* commands */ +struct INIT_CMD_DOWNLOAD_CONFIG { + uint32_t u4Address; + uint32_t u4Length; + uint32_t u4DataMode; +}; + +#define START_OVERRIDE_START_ADDRESS BIT(0) +#define START_DELAY_CALIBRATION BIT(1) +#define START_WORKING_PDA_OPTION BIT(2) +#define START_CRC_CHECK BIT(3) +#define CHANGE_DECOMPRESSION_TMP_ADDRESS BIT(4) + +#if CFG_SUPPORT_COMPRESSION_FW_OPTION +#define WIFI_FW_DECOMPRESSION_FAILED 0xFF +struct INIT_CMD_WIFI_DECOMPRESSION_START { + uint32_t u4Override; + uint32_t u4Address; + uint32_t u4Region1length; + uint32_t u4Region2length; + uint32_t u4Region1Address; + uint32_t u4Region2Address; + uint32_t u4BlockSize; + uint32_t u4Region1CRC; + uint32_t u4Region2CRC; + uint32_t u4DecompressTmpAddress; +}; +#endif + +struct INIT_CMD_WIFI_START { + uint32_t u4Override; + uint32_t u4Address; +}; + +#define PATCH_GET_SEMA_CONTROL 1 +#define PATCH_RELEASE_SEMA_CONTROL 0 +struct INIT_CMD_PATCH_SEMA_CONTROL { + uint8_t ucGetSemaphore; + uint8_t aucReserved[3]; +}; + +struct INIT_CMD_PATCH_FINISH { + uint8_t ucCheckCrc; + uint8_t aucReserved[3]; +}; + +struct INIT_CMD_ACCESS_REG { + uint8_t ucSetQuery; + uint8_t aucReserved[3]; + uint32_t u4Address; + uint32_t u4Data; +}; + +#if (CFG_SUPPORT_PRE_ON_PHY_ACTION == 1) +#define HAL_PHY_ACTION_MAGIC_NUM 0x556789AA +#define HAL_PHY_ACTION_VERSION 0x01 + +#define HAL_PHY_ACTION_CAL_FORCE_CAL_REQ 0x01 +#define HAL_PHY_ACTION_CAL_FORCE_CAL_RSP 0x81 +#define HAL_PHY_ACTION_CAL_USE_BACKUP_REQ 0x02 +#define HAL_PHY_ACTION_CAL_USE_BACKUP_RSP 0x82 +#define HAL_PHY_ACTION_ERROR 0xff + +enum ENUM_HAL_PHY_ACTION_STATUS { + HAL_PHY_ACTION_STATUS_SUCCESS = 0x00, + HAL_PHY_ACTION_STATUS_FAIL, + HAL_PHY_ACTION_STATUS_RECAL, + HAL_PHY_ACTION_STATUS_EPA_ELNA, +}; + +struct INIT_CMD_PHY_ACTION_CAL { + uint8_t ucCmd; + uint8_t aucReserved[3]; +}; + +struct INIT_EVENT_PHY_ACTION_RSP { + uint8_t ucEvent; + uint8_t ucStatus; + uint8_t aucReserved[2]; + uint32_t u4EmiAddress; + uint32_t u4EmiLength; + uint32_t u4Temperatue; +}; + +enum ENUM_HAL_PHY_ACTION_TAG { + HAL_PHY_ACTION_TAG_FEM, + HAL_PHY_ACTION_TAG_CAL, + + HAL_PHY_ACTION_TAG_NUM, +}; + +struct HAL_PHY_ACTION_TLV { + uint16_t u2Tag; + uint16_t u2BufLength; + uint8_t aucBuffer[0]; +}; + +struct HAL_PHY_ACTION_TLV_HEADER { + uint32_t u4MagicNum; + uint8_t ucTagNums; + uint8_t ucVersion; + uint16_t u2BufLength; + uint8_t aucBuffer[0]; +}; +#endif /* (CFG_SUPPORT_PRE_ON_PHY_ACTION == 1) */ + +/* Events */ +struct INIT_HIF_RX_HEADER { + struct INIT_WIFI_EVENT rInitWifiEvent; +}; + +struct INIT_EVENT_ACCESS_REG { + uint32_t u4Address; + uint32_t u4Data; +}; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _NIC_INIT_CMD_EVENT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/p2p_precomp.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/p2p_precomp.h new file mode 100644 index 0000000000000..b4cfd5c45c282 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/p2p_precomp.h @@ -0,0 +1,247 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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" + +#include "nic_rate.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" + +#include "mt66xx_reg.h" + +#include "rlm.h" +#include "rlm_domain.h" +#include "rlm_protection.h" +#include "rlm_obss.h" +#include "rate.h" +#include "wnm.h" + +#include "aa_fsm.h" + +#include "cnm_timer.h" +#include "que_mgt.h" +#include "wmm.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_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 "rftest.h" + +#include "rsn.h" + +#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 + ****************************************************************************** + */ + +/****************************************************************************** + * 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 + ****************************************************************************** + */ + +#endif /*_P2P_PRECOMP_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/p2p_typedef.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/p2p_typedef.h new file mode 100644 index 0000000000000..f8a5cf91869c8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/p2p_typedef.h @@ -0,0 +1,246 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 + ****************************************************************************** + */ + +/****************************************************************************** + * M A C R O S + ****************************************************************************** + */ + +/****************************************************************************** + * D A T A T Y P E S + ****************************************************************************** + */ + +/* + * type definition of pointer to p2p structure + */ +/* typedef struct GL_P2P_INFO GL_P2P_INFO_T, *P_GL_P2P_INFO_T; */ +struct P2P_INFO; /* declare P2P_INFO_T */ + +struct P2P_FSM_INFO; /* declare P2P_FSM_INFO_T */ + +struct P2P_DEV_FSM_INFO; /* declare P2P_DEV_FSM_INFO_T */ + +struct P2P_ROLE_FSM_INFO; /* declare P2P_ROLE_FSM_INFO_T */ + +struct P2P_CONNECTION_SETTINGS; /* declare P2P_CONNECTION_SETTINGS_T */ + +/* Type definition for function pointer to p2p function*/ +typedef u_int8_t(*P2P_LAUNCH) (struct GLUE_INFO *prGlueInfo); + +typedef u_int8_t(*P2P_REMOVE) (struct GLUE_INFO *prGlueInfo, + u_int8_t fgIsWlanLaunched); + +typedef u_int8_t(*KAL_P2P_GET_CIPHER) (IN struct GLUE_INFO *prGlueInfo); + +typedef u_int8_t(*KAL_P2P_GET_TKIP_CIPHER) (IN struct GLUE_INFO *prGlueInfo); + +typedef u_int8_t(*KAL_P2P_GET_CCMP_CIPHER) (IN struct GLUE_INFO *prGlueInfo); + +typedef u_int8_t(*KAL_P2P_GET_WSC_MODE) (IN struct GLUE_INFO *prGlueInfo); + +typedef struct net_device *(*KAL_P2P_GET_DEV_HDLR) ( + struct GLUE_INFO *prGlueInfo); + +typedef void(*KAL_P2P_SET_MULTICAST_WORK_ITEM) (struct GLUE_INFO *prGlueInfo); + +typedef void(*P2P_NET_REGISTER) (struct GLUE_INFO *prGlueInfo); + +typedef void(*P2P_NET_UNREGISTER) (struct GLUE_INFO *prGlueInfo); + +typedef void(*KAL_P2P_UPDATE_ASSOC_INFO) (IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucFrameBody, + IN uint32_t u4FrameBodyLen, + IN u_int8_t fgReassocRequest); + +typedef u_int8_t(*P2P_VALIDATE_AUTH) (IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN struct STA_RECORD **pprStaRec, + OUT uint16_t *pu2StatusCode); + +typedef u_int8_t(*P2P_VALIDATE_ASSOC_REQ) (IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + OUT uint16_t *pu4ControlFlags); + +typedef void(*P2P_RUN_EVENT_AAA_TX_FAIL) (IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +typedef u_int8_t(*P2P_PARSE_CHECK_FOR_P2P_INFO_ELEM) ( + IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, + OUT uint8_t *pucOuiType); + +typedef uint32_t(*P2P_RUN_EVENT_AAA_COMPLETE) (IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +typedef void(*P2P_PROCESS_EVENT_UPDATE_NOA_PARAM) ( + IN struct ADAPTER *prAdapter, + uint8_t ucNetTypeIndex, + struct EVENT_UPDATE_NOA_PARAMS *prEventUpdateNoaParam); + +typedef void(*SCAN_P2P_PROCESS_BEACON_AND_PROBE_RESP) ( + IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint32_t *prStatus, + IN struct BSS_DESC *prBssDesc, + IN struct WLAN_BEACON_FRAME *prWlanBeaconFrame); + +typedef void(*P2P_RX_PUBLIC_ACTION_FRAME) (struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +typedef void(*RLM_RSP_GENERATE_OBSS_SCAN_IE) (struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +typedef void(*RLM_UPDATE_BW_BY_CH_LIST_FOR_AP) (struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo); + +typedef void(*RLM_PROCESS_PUBLIC_ACTION) (struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); + +typedef void(*RLM_PROCESS_HT_ACTION) (struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); + +typedef void(*RLM_UPDATE_PARAMS_FOR_AP) (struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, u_int8_t fgUpdateBeacon); + +typedef void(*RLM_HANDLE_OBSS_STATUS_EVENT_PKT) (struct ADAPTER *prAdapter, + struct EVENT_AP_OBSS_STATUS *prObssStatus); + +typedef u_int8_t(*P2P_FUNC_VALIDATE_PROBE_REQ) (IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + OUT uint32_t *pu4ControlFlags); + +typedef void(*RLM_BSS_INIT_FOR_AP) (struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo); + +typedef uint32_t(*P2P_GET_PROB_RSP_IE_TABLE_SIZE) (void); + +typedef uint8_t *(*P2P_BUILD_REASSOC_REQ_FRAME_COMMON_IES) ( + IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN uint8_t *pucBuffer); + +typedef void(*P2P_FUNC_DISCONNECT) (IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN u_int8_t fgSendDeauth, IN uint16_t u2ReasonCode); + +typedef void(*P2P_FSM_RUN_EVENT_RX_DEAUTH) (IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct SW_RFB *prSwRfb); + +typedef void(*P2P_FSM_RUN_EVENT_RX_DISASSOC) (IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct SW_RFB *prSwRfb); + +typedef u_int8_t(*P2P_FUN_IS_AP_MODE) (IN struct P2P_FSM_INFO *prP2pFsmInfo); + +typedef void(*P2P_FSM_RUN_EVENT_BEACON_TIMEOUT) (IN struct ADAPTER *prAdapter); + +typedef void(*P2P_FUNC_STORE_ASSOC_RSP_IE_BUFFER) ( + IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +typedef void(*P2P_GENERATE_P2P_IE) (IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +typedef uint32_t(*P2P_CALCULATE_P2P_IE_LEN) (IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN struct STA_RECORD *prStaRec); + +/****************************************************************************** + * 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 /*CFG_ENABLE_WIFI_DIRECT */ + +#endif /* _P2P_TYPEDEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/precomp.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/precomp.h new file mode 100644 index 0000000000000..b0b6cfa87e020 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/precomp.h @@ -0,0 +1,342 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + * 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. + */ + +#ifndef _PRECOMP_H +#define _PRECOMP_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +#ifdef __GNUC__ +#if (DBG == 0) +#pragma GCC diagnostic ignored "-Wformat" +#endif +#endif + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "hif_cmm.h" +#include "gl_os.h" /* Include "config.h" */ +#include "gl_cfg80211.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_802_11AX == 1) +#include "he_ie.h" +#endif + +#if CFG_SUPPORT_SWCR +#include "swcr.h" +#endif + +#include "rlm_obss.h" +#include "cnm_timer.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" +#include "nic_ext_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_connac2x_tx.h" +#include "nic_tx.h" +#include "nic_txd_v1.h" +#include "nic_txd_v2.h" +#include "nic_rxd_v1.h" +#include "nic_rxd_v2.h" + +#include "nic_connac2x_rx.h" +/* Dependency: hif_rx.h (P_HIF_RX_HEADER_T) */ +#include "nic_rx.h" + +#include "nic_umac.h" + +#include "bss.h" + +#include "nic_rate.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 + *------------------------------------------------------------------------------ + */ +#if (CFG_SUPPORT_TWT == 1) +#include "twt.h" +#endif /* CFG_SUPPORT_802_11AX */ + +#include "hem_mbox.h" + +#include "scan.h" + +#include "wlan_lib.h" +#include "wlan_oid.h" +#include "wlan_bow.h" + +#include "fw_dl.h" + +#if CFG_ENABLE_WIFI_DIRECT +#include "wlan_p2p.h" +#endif + +#include "hal.h" + +#include "mt66xx_reg.h" + +#include "connac_reg.h" +#include "connac_dmashdl.h" +#include "cmm_asic_connac.h" +#include "cmm_asic_connac2x.h" + +#if (CFG_SUPPORT_802_11AX == 1) +#include "he_rlm.h" +#include "wlan_he.h" +#endif /* CFG_SUPPORT_802_11AX == 1 */ + +#if (CFG_SUPPORT_TWT == 1) +#include "twt_req_fsm.h" +#include "twt_planner.h" +#endif + +#include "rlm.h" +#include "rlm_domain.h" +#include "rlm_protection.h" +#include "rlm_obss.h" +#include "rate.h" +#include "wnm.h" +#include "rrm.h" + +#include "qosmap.h" + +#include "aa_fsm.h" + +#include "que_mgt.h" + +#include "wmm.h" +#if CFG_ENABLE_BT_OVER_WIFI +#include "bow.h" +#include "bow_fsm.h" +#endif + +#include "pwr_mgt.h" + +#if (CFG_SUPPORT_STATISTICS == 1) +#include "stats.h" +#endif /* CFG_SUPPORT_STATISTICS */ + +#include "cnm.h" +/* Dependency: aa_fsm.h (ENUM_AA_STATE_T), p2p_fsm.h + * (WPS_ATTRI_MAX_LEN_DEVICE_NAME) + */ +#include "cnm_mem.h" +#include "cnm_scan.h" + +#if CFG_ENABLE_WIFI_DIRECT +#include "p2p_rlm_obss.h" +#include "p2p_bss.h" +#include "p2p.h" + +#include "p2p_rlm.h" +#include "p2p_assoc.h" +#include "p2p_ie.h" +#include "p2p_role.h" + +#include "p2p_func.h" +#include "p2p_scan.h" +#include "p2p_dev.h" +#include "p2p_fsm.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" + +#include "rsn.h" + +#if CFG_SUPPORT_WAPI +#include "wapi.h" +#endif + +/* Support AP Selection */ +#include "ap_selection.h" + +/*------------------------------------------------------------------------------ + * NVRAM structure + *------------------------------------------------------------------------------ + */ +#include "CFG_Wifi_File.h" + +#if CFG_ENABLE_WIFI_DIRECT +#include "gl_p2p_kal.h" +#endif + +#if CFG_SUPPORT_TDLS +#include "tdls.h" +#endif + +#if CFG_SUPPORT_QA_TOOL +#include "gl_qa_agent.h" +#include "gl_ate_agent.h" +#endif + +#if CFG_SUPPORT_WIFI_SYSDVT +#include "dvt_common.h" +#if (CFG_SUPPORT_DMASHDL_SYSDVT) +#include "dvt_dmashdl.h" +#endif +#endif + +#ifdef UT_TEST_MODE +#include "ut_lib.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/misc/mediatek/connectivity/wlan/core/gen4m/include/pwr_mgt.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/pwr_mgt.h new file mode 100644 index 0000000000000..d7a93239e6e0b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/pwr_mgt.h @@ -0,0 +1,156 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + +#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 + +#define LP_OWN_BACK_TOTAL_DELAY_MS 2048 /* exponential of 2 */ +#define LP_OWN_BACK_LOOP_DELAY_MS 1 /* exponential of 2 */ +#define LP_OWN_REQ_CLR_INTERVAL_MS 200 +#define LP_OWN_BACK_FAILED_RETRY_CNT 5 +#define LP_OWN_BACK_FAILED_LOG_SKIP_MS 2000 +#define LP_OWN_BACK_FAILED_RESET_CNT 5 +#define LP_OWN_BACK_FAILED_DBGCR_POLL_ROUND 5 +#define LP_DBGCR_POLL_ROUND 1 +#define LP_OWN_BACK_LOOP_DELAY_MIN_US 900 +#define LP_OWN_BACK_LOOP_DELAY_MAX_US 1000 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +struct PM_PROFILE_SETUP_INFO { + /* Profile setup */ + /* 0: AC_BE, 1: AC_BK, 2: AC_VI, 3: AC_VO */ + uint8_t ucBmpDeliveryAC; + /* 0: AC_BE, 1: AC_BK, 2: AC_VI, 3: AC_VO */ + uint8_t ucBmpTriggerAC; + + uint8_t ucUapsdSp; /* Number of triggered packets in UAPSD */ + +}; + +/******************************************************************************* + * P U B 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) \ + { \ + nicpmSetDriverOwn(_prAdapter); \ + } + +#define RECLAIM_POWER_CONTROL_TO_PM(_prAdapter, _fgEnableGINT_in_IST) \ + { \ + nicpmSetFWOwn(_prAdapter, _fgEnableGINT_in_IST); \ + } +#endif + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _PWR_MGT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/queue.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/queue.h new file mode 100644 index 0000000000000..facc628e459d6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/queue.h @@ -0,0 +1,241 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + +#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 */ +struct QUE_ENTRY { + struct QUE_ENTRY *prNext; + struct QUE_ENTRY + *prPrev; /* For Rx buffer reordering used only */ +}; + +/* Singly Queue Structures - Queue Part */ +struct QUE { + struct QUE_ENTRY *prHead; + struct QUE_ENTRY *prTail; + uint32_t u4NumElem; +}; + +/******************************************************************************* + * P U B 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 MAXNUM_TDLS_PEER 4 + +#define QUEUE_INITIALIZE(prQueue) \ + { \ + (prQueue)->prHead = (struct QUE_ENTRY *)NULL; \ + (prQueue)->prTail = (struct QUE_ENTRY *)NULL; \ + (prQueue)->u4NumElem = 0; \ + } + +#define QUEUE_IS_EMPTY(prQueue) \ + (((struct QUE *)(prQueue))->prHead == (struct QUE_ENTRY *)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 == (struct QUE_ENTRY *)NULL) { \ + (prQueue)->prTail = (prQueueEntry); \ + } \ + ((prQueue)->u4NumElem)++; \ + } + +#define QUEUE_INSERT_TAIL(prQueue, prQueueEntry) \ + { \ + ASSERT(prQueue); \ + ASSERT(prQueueEntry); \ + (prQueueEntry)->prNext = (struct QUE_ENTRY *)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 = \ + ((struct QUE_ENTRY *)(prQueueEntry))->prNext; \ + if ((prQueue)->prHead == (struct QUE_ENTRY *)NULL) { \ + (prQueue)->prTail = (struct QUE_ENTRY *)NULL; \ + } \ + ((struct QUE_ENTRY *)(prQueueEntry))->prNext = \ + (struct QUE_ENTRY *)NULL; \ + ((prQueue)->u4NumElem)--; \ + } \ + } + +#define QUEUE_MOVE_ALL(prDestQueue, prSrcQueue) \ + { \ + ASSERT(prDestQueue); \ + ASSERT(prSrcQueue); \ + *(struct QUE *)prDestQueue = *(struct QUE *)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); \ + } \ + } + +#define QUEUE_CONCATENATE_QUEUES_HEAD(prDestQueue, prSrcQueue) \ + { \ + ASSERT(prDestQueue); \ + ASSERT(prSrcQueue); \ + if ((prSrcQueue)->u4NumElem > 0 && (prSrcQueue)->prTail) { \ + ((prSrcQueue)->prTail)->prNext = \ + (prDestQueue)->prHead; \ + (prDestQueue)->prHead = (prSrcQueue)->prHead; \ + ((prDestQueue)->u4NumElem) += \ + ((prSrcQueue)->u4NumElem); \ + if ((prDestQueue)->prTail == NULL) { \ + (prDestQueue)->prTail = (prSrcQueue)->prTail; \ + } \ + QUEUE_INITIALIZE(prSrcQueue); \ + } \ + } + +/******************************************************************************* + * E X T E R N A L D A T A + ******************************************************************************* + */ +extern uint8_t g_arTdlsLink[MAXNUM_TDLS_PEER]; + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _QUEUE_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/rftest.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/rftest.h new file mode 100644 index 0000000000000..5b72826135358 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/rftest.h @@ -0,0 +1,438 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: include/rftest.h + */ + +/*! \file "rftest.h" + * \brief definitions for RF Productino test + * + */ + +#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 \ + ((uint16_t)(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 */ +enum ENUM_RF_AT_FUNCID { + 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, + RF_AT_FUNCID_PWR_DETECTOR, + RF_AT_FUNCID_WBRSSI_IBSSI, + + /* 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, + RF_AT_FUNCID_SET_TA, + RF_AT_FUNCID_SET_RX_MATCH_RULE, + + /* 80211AC & Jmode */ + RF_AT_FUNCID_SET_CBW = 71, + RF_AT_FUNCID_SET_DBW, + RF_AT_FUNCID_SET_PRIMARY_CH, + RF_AT_FUNCID_SET_ENCODE_MODE, + RF_AT_FUNCID_SET_J_MODE, + + /* ICAP command */ + RF_AT_FUNCID_SET_ICAP_CONTENT = 80, + RF_AT_FUNCID_SET_ICAP_MODE, + RF_AT_FUNCID_SET_ICAP_STARTCAP, + RF_AT_FUNCID_SET_ICAP_SIZE = 83, + RF_AT_FUNCID_SET_ICAP_TRIGGER_OFFSET, + RF_AT_FUNCID_QUERY_ICAP_DUMP_FILE = 85, + +#if CFG_SUPPORT_QA_TOOL + /* 2G 5G Band */ + RF_AT_FUNCID_SET_BAND = 90, + + /* Reset Counter */ + RF_AT_FUNCID_RESETTXRXCOUNTER = 91, + + /* FAGC RSSI Path */ + RF_AT_FUNCID_FAGC_RSSI_PATH = 92, + + /* Set RX Filter Packet Length */ + RF_AT_FUNCID_RX_FILTER_PKT_LEN = 93, + + /* Tone */ + RF_AT_FUNCID_SET_TONE_RF_GAIN = 96, + RF_AT_FUNCID_SET_TONE_DIGITAL_GAIN = 97, + RF_AT_FUNCID_SET_TONE_TYPE = 98, + RF_AT_FUNCID_SET_TONE_DC_OFFSET = 99, + RF_AT_FUNCID_SET_TONE_BW = 100, + + /* MT6632 Add */ + RF_AT_FUNCID_SET_MAC_HEADER = 101, + RF_AT_FUNCID_SET_SEQ_CTRL = 102, + RF_AT_FUNCID_SET_PAYLOAD = 103, + RF_AT_FUNCID_SET_DBDC_BAND_IDX = 104, + RF_AT_FUNCID_SET_BYPASS_CAL_STEP = 105, + + /* Set RX Path */ + RF_AT_FUNCID_SET_RX_PATH = 106, + + /* Set Frequency Offset */ + RF_AT_FUNCID_SET_FRWQ_OFFSET = 107, + + /* Get Frequency Offset */ + RF_AT_FUNCID_GET_FREQ_OFFSET = 108, + + /* Set RXV Debug Index */ + RF_AT_FUNCID_SET_RXV_INDEX = 109, + + /* Set Test Mode DBDC Enable */ + RF_AT_FUNCID_SET_DBDC_ENABLE = 110, + + /* Get Test Mode DBDC Enable */ + RF_AT_FUNCID_GET_DBDC_ENABLE = 111, + + /* Set ICAP Ring Capture */ + RF_AT_FUNCID_SET_ICAP_RING = 112, + + /* Set TX Path */ + RF_AT_FUNCID_SET_TX_PATH = 113, + + /* Set Nss */ + RF_AT_FUNCID_SET_NSS = 114, + + /* Set TX Antenna Mask */ + RF_AT_FUNCID_SET_ANTMASK = 115, + + /* TMR set command */ + RF_AT_FUNCID_SET_TMR_ROLE = 116, + RF_AT_FUNCID_SET_TMR_MODULE = 117, + RF_AT_FUNCID_SET_TMR_DBM = 118, + RF_AT_FUNCID_SET_TMR_ITER = 119, + + /* Set ADC For IRR Feature */ + RF_AT_FUNCID_SET_ADC = 120, + + /* Set RX Gain For IRR Feature */ + RF_AT_FUNCID_SET_RX_GAIN = 121, + + /* Set TTG For IRR Feature */ + RF_AT_FUNCID_SET_TTG = 122, + + /* Set TTG ON/OFF For IRR Feature */ + RF_AT_FUNCID_TTG_ON_OFF = 123, + + /* Set TSSI for QA Tool Setting */ + RF_AT_FUNCID_SET_TSSI = 124, + + /* Set Recal Cal Step */ + RF_AT_FUNCID_SET_RECAL_CAL_STEP = 125, + + /* Set iBF/eBF enable */ + RF_AT_FUNCID_SET_IBF_ENABLE = 126, + RF_AT_FUNCID_SET_EBF_ENABLE = 127, + + /* Set MPS Setting */ + RF_AT_FUNCID_SET_MPS_SIZE = 128, + RF_AT_FUNCID_SET_MPS_SEQ_DATA = 129, + RF_AT_FUNCID_SET_MPS_PAYLOAD_LEN = 130, + RF_AT_FUNCID_SET_MPS_PKT_CNT = 131, + RF_AT_FUNCID_SET_MPS_PWR_GAIN = 132, + RF_AT_FUNCID_SET_MPS_NSS = 133, + RF_AT_FUNCID_SET_MPS_PACKAGE_BW = 134, +#endif +#if CFG_SUPPORT_ANT_SWAP + /* Antenna swap feature*/ + RF_AT_FUNCID_SET_ANT_SWP = 153, +#endif + +}; + +/* Command */ +enum ENUM_RF_AT_COMMAND { + RF_AT_COMMAND_STOPTEST = 0, + RF_AT_COMMAND_STARTTX, + RF_AT_COMMAND_STARTRX, + RF_AT_COMMAND_RESET, + RF_AT_COMMAND_OUTPUT_POWER, /* Payload */ + /* Local freq is renamed to Local leakage */ + RF_AT_COMMAND_LO_LEAKAGE, + /* OFDM (LTF/STF), CCK (PI,PI/2) */ + RF_AT_COMMAND_CARRIER_SUPPR, + RF_AT_COMMAND_TRX_IQ_CAL, + RF_AT_COMMAND_TSSI_CAL, + RF_AT_COMMAND_DPD_CAL, + RF_AT_COMMAND_CW, + RF_AT_COMMAND_ICAP, + RF_AT_COMMAND_RDD, + RF_AT_COMMAND_CH_SWITCH_FOR_ICAP, + RF_AT_COMMAND_RESET_DUMP_NAME, + RF_AT_COMMAND_SINGLE_TONE, + RF_AT_COMMAND_RDD_OFF, + RF_AT_COMMAND_NUM +}; + +/* Preamble */ +enum ENUM_RF_AT_PREAMBLE { + RF_AT_PREAMBLE_NORMAL = 0, + RF_AT_PREAMBLE_CCK_SHORT, + RF_AT_PREAMBLE_11N_MM, + RF_AT_PREAMBLE_11N_GF, + RF_AT_PREAMBLE_11AC, + RF_AT_PREAMBLE_NUM +}; + +/* Ack Policy */ +enum ENUM_RF_AT_ACK_POLICY { + 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 ENUM_RF_AUTOTEST_STATE { + 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 +}; + +/******************************************************************************* + * P U B 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 + ******************************************************************************* + */ + +uint32_t rftestSetATInfo(IN struct ADAPTER *prAdapter, + uint32_t u4FuncIndex, uint32_t u4FuncData); + +uint32_t rftestQueryATInfo(IN struct ADAPTER *prAdapter, + uint32_t u4FuncIndex, uint32_t u4FuncData, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen); + +uint32_t rftestSetFrequency(IN struct ADAPTER *prAdapter, + IN uint32_t u4FreqInKHz, IN uint32_t *pu4SetInfoLen); + +#endif /* _RFTEST_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/typedef.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/typedef.h new file mode 100644 index 0000000000000..2fb0ff00bde7c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/typedef.h @@ -0,0 +1,204 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: include/typedef.h + */ + +/*! \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. + */ + +#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 ((uint32_t) 0x00000000L) +#define WLAN_STATUS_PENDING ((uint32_t) 0x00000103L) +#define WLAN_STATUS_NOT_ACCEPTED ((uint32_t) 0x00010003L) + +#define WLAN_STATUS_MEDIA_CONNECT ((uint32_t) 0x4001000BL) +#define WLAN_STATUS_MEDIA_DISCONNECT ((uint32_t) 0x4001000CL) +#define WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY ((uint32_t) 0x4001000DL) +#define WLAN_STATUS_MEDIA_SPECIFIC_INDICATION ((uint32_t) 0x40010012L) + +#define WLAN_STATUS_SCAN_COMPLETE ((uint32_t) 0x60010001L) +#define WLAN_STATUS_MSDU_OK ((uint32_t) 0x60010002L) + +/* TODO(Kevin): double check if 0x60010001 & 0x60010002 is proprietary */ +#define WLAN_STATUS_ROAM_OUT_FIND_BEST ((uint32_t) 0x60010101L) +#define WLAN_STATUS_ROAM_DISCOVERY ((uint32_t) 0x60010102L) + +#define WLAN_STATUS_FAILURE ((uint32_t) 0xC0000001L) +#define WLAN_STATUS_RESOURCES ((uint32_t) 0xC000009AL) +#define WLAN_STATUS_NOT_SUPPORTED ((uint32_t) 0xC00000BBL) + +#define WLAN_STATUS_MULTICAST_FULL ((uint32_t) 0xC0010009L) +#define WLAN_STATUS_INVALID_PACKET ((uint32_t) 0xC001000FL) +#define WLAN_STATUS_ADAPTER_NOT_READY ((uint32_t) 0xC0010011L) +#define WLAN_STATUS_NOT_INDICATING ((uint32_t) 0xC0010013L) +#define WLAN_STATUS_INVALID_LENGTH ((uint32_t) 0xC0010014L) +#define WLAN_STATUS_INVALID_DATA ((uint32_t) 0xC0010015L) +#define WLAN_STATUS_BUFFER_TOO_SHORT ((uint32_t) 0xC0010016L) +#define WLAN_STATUS_BWCS_UPDATE ((uint32_t) 0xC0010017L) + +#define WLAN_STATUS_JOIN_FAILURE ((uint32_t) 0xc0010018L) + +/* NIC status flags */ +#define ADAPTER_FLAG_HW_ERR 0x00400000 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +/* Type definition for GLUE_INFO structure */ +struct GLUE_INFO; /* declare GLUE_INFO_T */ + +/* Type definition for WLAN STATUS */ + +/* Type definition for ADAPTER structure */ +struct ADAPTER; /* declare ADAPTER_T */ + +/* Type definition for MESSAGE HEADER structure */ +struct MSG_HDR; /* declare MSG_HDR_T */ + +/* Type definition for Pointer to OS Native Packet */ + +/* Type definition for WLAN configuration */ +struct WLAN_CFG; /* declare WLAN_CFG_T */ + +struct WLAN_CFG_REC; /* declare WLAN_CFG_REC_T */ + + +/* Type definition for WLAN configuration entry */ +struct WLAN_CFG_ENTRY; /* declare WLAN_CFG_ENTRY_T */ + +/* Type definition for WLAN configuration callback */ +typedef uint32_t(*WLAN_CFG_SET_CB) (struct ADAPTER + *prAdapter, + uint8_t *pucKey, + uint8_t *pucValue, + void *pPrivate, + uint32_t u4Flags); + +/* Type definition for STA_RECORD_T structure to handle the connectivity + * and packet reception for a particular STA. + */ +struct STA_RECORD; /* declare 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. + */ +struct CMD_INFO; /* declare CMD_INFO_T */ + +/* Following typedef should be removed later, because Glue Layer + * should not be aware of following data type. + */ +struct SW_RFB; /* declare SW_RFB_T */ + +struct MSDU_INFO; /* declare MSDU_INFO_T */ + +struct REG_ENTRY; /* declare REG_ENTRY_T */ + +/* IST handler definition */ +typedef void(*IST_EVENT_FUNCTION) (struct ADAPTER *); + +/* Type definition for function pointer of timer handler */ +typedef void(*PFN_TIMER_CALLBACK) (IN struct GLUE_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 + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#endif /* _TYPEDEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/wlan_bow.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/wlan_bow.h new file mode 100644 index 0000000000000..1c8a63625264e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/wlan_bow.h @@ -0,0 +1,302 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +#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 + +extern uint32_t g_arBowRevPalPacketTime[32]; + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + +struct BOW_TABLE { + uint8_t ucAcquireID; + u_int8_t fgIsValid; + enum ENUM_BOW_DEVICE_STATE eState; + uint8_t aucPeerAddress[6]; + /* UINT_8 ucRole; */ + /* UINT_8 ucChannelNum; */ + uint16_t u2Reserved; +}; + +typedef uint32_t(*PFN_BOW_CMD_HANDLE) (struct ADAPTER *, struct BT_OVER_WIFI_COMMAND *); + +struct BOW_CMD { + uint8_t uCmdID; + PFN_BOW_CMD_HANDLE pfCmdHandle; +}; + +struct BOW_EVENT_ACTIVITY_REPORT { + uint8_t ucReason; + uint8_t aucReserved; + uint8_t aucPeerAddress[6]; +}; + +/* +*ucReason: 0: success +* 1: general failure +* 2: too much time (> 2/3 second totally) requested for scheduling. +* Others: reserved. +*/ + +struct BOW_EVENT_SYNC_TSF { + uint64_t u4TsfTime; + uint32_t u4TsfSysTime; + uint32_t u4ScoTime; + uint32_t u4ScoSysTime; +}; + +struct BOW_ACTIVITY_REPORT_BODY { + uint32_t u4StartTime; + uint32_t u4Duration; + uint32_t u4Periodicity; +}; + +struct BOW_ACTIVITY_REPORT { + uint8_t aucPeerAddress[6]; + uint8_t ucScheduleKnown; + uint8_t ucNumReports; + struct BOW_ACTIVITY_REPORT_BODY arBowActivityReportBody[MAX_ACTIVITY_REPORT]; +}; + +/******************************************************************************* +* 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 */ +/*--------------------------------------------------------------*/ +uint32_t +wlanoidSendSetQueryBowCmd(IN struct ADAPTER *prAdapter, + uint8_t ucCID, + IN uint8_t ucBssIdx, + u_int8_t fgSetQuery, + u_int8_t fgNeedResp, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + uint32_t u4SetQueryInfoLen, uint8_t *pucInfoBuffer, IN uint8_t ucSeqNumber); + +/*--------------------------------------------------------------*/ +/* Command Dispatcher */ +/*--------------------------------------------------------------*/ +uint32_t wlanbowHandleCommand(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd); + +/*--------------------------------------------------------------*/ +/* Routines to handle command */ +/*--------------------------------------------------------------*/ +uint32_t bowCmdGetMacStatus(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd); + +uint32_t bowCmdSetupConnection(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd); + +uint32_t bowCmdDestroyConnection(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd); + +uint32_t bowCmdSetPTK(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd); + +uint32_t bowCmdReadRSSI(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd); + +uint32_t bowCmdReadLinkQuality(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd); + +uint32_t bowCmdShortRangeMode(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd); + +uint32_t bowCmdGetChannelList(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd); + +void wlanbowCmdEventSetStatus(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd, IN uint8_t ucEventBuf); + +/*--------------------------------------------------------------*/ +/* Callbacks for event indication */ +/*--------------------------------------------------------------*/ +void wlanbowCmdEventSetCommon(IN struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void wlanbowCmdEventLinkConnected(IN struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void wlanbowCmdEventLinkDisconnected(IN struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void wlanbowCmdEventSetSetupConnection(IN struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void wlanbowCmdEventReadLinkQuality(IN struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void wlanbowCmdEventReadRssi(IN struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +uint8_t bowInit(IN struct ADAPTER *prAdapter); + +void bowUninit(IN struct ADAPTER *prAdapter); + +void wlanbowCmdTimeoutHandler(IN struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo); + +void bowStopping(IN struct ADAPTER *prAdapter); + +void bowStarting(IN struct ADAPTER *prAdapter); + +void bowAssignSsid(IN uint8_t *pucSsid, IN uint8_t *pucSsidLen); + +u_int8_t bowValidateProbeReq(IN struct ADAPTER *prAdapter, IN struct SW_RFB *prSwRfb, OUT uint32_t *pu4ControlFlags); + +void bowSendBeacon(IN struct ADAPTER *prAdapter, unsigned long ulParamPtr); + +void bowResponderScan(IN struct ADAPTER *prAdapter); + +void bowResponderScanDone(IN struct ADAPTER *prAdapter, IN struct MSG_HDR *prMsgHdr); + +void bowResponderCancelScan(IN struct ADAPTER *prAdapter, IN u_int8_t fgIsChannelExtention); + +void bowResponderJoin(IN struct ADAPTER *prAdapter, struct BSS_DESC *prBssDesc); + +void bowFsmRunEventJoinComplete(IN struct ADAPTER *prAdapter, IN struct MSG_HDR *prMsgHdr); + +void +bowIndicationOfMediaStateToHost(IN struct ADAPTER *prAdapter, + enum ENUM_PARAM_MEDIA_STATE eConnectionState, u_int8_t fgDelayIndication); + +void bowRunEventAAATxFail(IN struct ADAPTER *prAdapter, IN struct STA_RECORD *prStaRec); + +uint32_t bowRunEventAAAComplete(IN struct ADAPTER *prAdapter, IN struct STA_RECORD *prStaRec); + +uint32_t bowRunEventRxDeAuth(IN struct ADAPTER *prAdapter, IN struct STA_RECORD *prStaRec, IN struct SW_RFB *prSwRfb); + +void bowDisconnectLink(IN struct ADAPTER *prAdapter, IN struct MSDU_INFO *prMsduInfo, IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +u_int8_t bowValidateAssocReq(IN struct ADAPTER *prAdapter, IN struct SW_RFB *prSwRfb, OUT uint16_t *pu2StatusCode); + +u_int8_t +bowValidateAuth(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, IN struct STA_RECORD **pprStaRec, OUT uint16_t *pu2StatusCode); + +void bowRunEventChGrant(IN struct ADAPTER *prAdapter, IN struct MSG_HDR *prMsgHdr); + +void bowRequestCh(IN struct ADAPTER *prAdapter); + +void bowReleaseCh(IN struct ADAPTER *prAdapter); + +void bowChGrantedTimeout(IN struct ADAPTER *prAdapter, IN unsigned long ulParamPtr); + +u_int8_t bowNotifyAllLinkDisconnected(IN struct ADAPTER *prAdapter); + +u_int8_t bowCheckBowTableIfVaild(IN struct ADAPTER *prAdapter, IN uint8_t aucPeerAddress[6]); + +u_int8_t bowGetBowTableContent(IN struct ADAPTER *prAdapter, IN uint8_t ucBowTableIdx, OUT struct BOW_TABLE *prBowTable); + +u_int8_t +bowGetBowTableEntryByPeerAddress(IN struct ADAPTER *prAdapter, IN uint8_t aucPeerAddress[6], OUT uint8_t *pucBowTableIdx); + +u_int8_t bowGetBowTableFreeEntry(IN struct ADAPTER *prAdapter, OUT uint8_t *pucBowTableIdx); + +enum ENUM_BOW_DEVICE_STATE bowGetBowTableState(IN struct ADAPTER *prAdapter, IN uint8_t aucPeerAddress[6]); + +u_int8_t bowSetBowTableState(IN struct ADAPTER *prAdapter, IN uint8_t aucPeerAddress[6], IN enum ENUM_BOW_DEVICE_STATE eState); + +u_int8_t bowSetBowTableContent(IN struct ADAPTER *prAdapter, IN uint8_t ucBowTableIdx, IN struct BOW_TABLE *prBowTable); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif +#endif /* _WLAN_BOW_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/wlan_he.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/wlan_he.h new file mode 100644 index 0000000000000..f0ff14f764be4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/wlan_he.h @@ -0,0 +1,107 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "wlan_he.h" +* \brief This file contains the declairations of HE(802.11ax) +* processing routines for MediaTek Inc. 802.11 Wireless LAN Adapters. +*/ + + +#ifndef _WLAN_HE_H +#define _WLAN_HE_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +extern uint8_t fgEfuseCtrlAxOn; + +#if (CFG_SUPPORT_802_11AX == 1) +/******************************************************************************* +* C O N S T A N T 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 /* CFG_SUPPORT_802_11AX == 1 */ +#endif /* _WLAN_HE_H */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/wlan_lib.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/wlan_lib.h new file mode 100644 index 0000000000000..fabb4f3076737 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/wlan_lib.h @@ -0,0 +1,1851 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include + * /wlan_lib.h#3 + */ + +/*! \file "wlan_lib.h" + * \brief The declaration of the functions of the wlanAdpater objects + * + * Detail description. + */ + +#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 "nic_init_cmd_event.h" +#include "fw_dl.h" +#include "queue.h" +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +/* These values must sync from Wifi HAL + * /hardware/libhardware_legacy/include/hardware_legacy/wifi_hal.h + */ +/* Basic infrastructure mode */ +#define WIFI_FEATURE_INFRA (0x0001) +/* Support for 5 GHz Band */ +#define WIFI_FEATURE_INFRA_5G (0x0002) +/* Support for GAS/ANQP */ +#define WIFI_FEATURE_HOTSPOT (0x0004) +/* Wifi-Direct */ +#define WIFI_FEATURE_P2P (0x0008) +/* Soft AP */ +#define WIFI_FEATURE_SOFT_AP (0x0010) +/* Google-Scan APIs */ +#define WIFI_FEATURE_GSCAN (0x0020) +/* Neighbor Awareness Networking */ +#define WIFI_FEATURE_NAN (0x0040) +/* Device-to-device RTT */ +#define WIFI_FEATURE_D2D_RTT (0x0080) +/* Device-to-AP RTT */ +#define WIFI_FEATURE_D2AP_RTT (0x0100) +/* Batched Scan (legacy) */ +#define WIFI_FEATURE_BATCH_SCAN (0x0200) +/* Preferred network offload */ +#define WIFI_FEATURE_PNO (0x0400) +/* Support for two STAs */ +#define WIFI_FEATURE_ADDITIONAL_STA (0x0800) +/* Tunnel directed link setup */ +#define WIFI_FEATURE_TDLS (0x1000) +/* Support for TDLS off channel */ +#define WIFI_FEATURE_TDLS_OFFCHANNEL (0x2000) +/* Enhanced power reporting */ +#define WIFI_FEATURE_EPR (0x4000) +/* Support for AP STA Concurrency */ +#define WIFI_FEATURE_AP_STA (0x8000) +/* Link layer stats collection */ +#define WIFI_FEATURE_LINK_LAYER_STATS (0x10000) +/* WiFi Logger */ +#define WIFI_FEATURE_LOGGER (0x20000) +/* WiFi PNO enhanced */ +#define WIFI_FEATURE_HAL_EPNO (0x40000) +/* RSSI Monitor */ +#define WIFI_FEATURE_RSSI_MONITOR (0x80000) +/* WiFi mkeep_alive */ +#define WIFI_FEATURE_MKEEP_ALIVE (0x100000) +/* ND offload configure */ +#define WIFI_FEATURE_CONFIG_NDO (0x200000) +/* Capture Tx transmit power levels */ +#define WIFI_FEATURE_TX_TRANSMIT_POWER (0x400000) +/* Enable/Disable firmware roaming */ +#define WIFI_FEATURE_CONTROL_ROAMING (0x800000) +/* Support Probe IE white listing */ +#define WIFI_FEATURE_IE_WHITELIST (0x1000000) +/* Support MAC & Probe Sequence Number randomization */ +#define WIFI_FEATURE_SCAN_RAND (0x2000000) +/* Support Tx Power Limit setting */ +#define WIFI_FEATURE_SET_TX_POWER_LIMIT (0x4000000) +/* Support Using Body/Head Proximity for SAR */ +#define WIFI_FEATURE_USE_BODY_HEAD_SAR (0x8000000) +/* Support Random P2P MAC */ +#define WIFI_FEATURE_P2P_RAND_MAC (0x80000000) + +/* note: WIFI_FEATURE_GSCAN be enabled just for ACTS test item: scanner */ +#define WIFI_HAL_FEATURE_SET ((WIFI_FEATURE_P2P) |\ + (WIFI_FEATURE_SOFT_AP) |\ + (WIFI_FEATURE_PNO) |\ + (WIFI_FEATURE_TDLS) |\ + (WIFI_FEATURE_RSSI_MONITOR) |\ + (WIFI_FEATURE_CONTROL_ROAMING) |\ + (WIFI_FEATURE_SET_TX_POWER_LIMIT) |\ + (WIFI_FEATURE_P2P_RAND_MAC)\ + ) + +#define MAX_NUM_GROUP_ADDR 32 /* max number of group addresses */ +#define AUTO_RATE_NUM 8 +#define AR_RATE_TABLE_ENTRY_MAX 25 +#define AR_RATE_ENTRY_INDEX_NULL 0x80 +#define MAX_TX_QUALITY_INDEX 4 + +#define TX_CS_TCP_UDP_GEN BIT(1) +#define TX_CS_IP_GEN BIT(0) + +#define CSUM_OFFLOAD_EN_TX_TCP BIT(0) +#define CSUM_OFFLOAD_EN_TX_UDP BIT(1) +#define CSUM_OFFLOAD_EN_TX_IP BIT(2) +#define CSUM_OFFLOAD_EN_RX_TCP BIT(3) +#define CSUM_OFFLOAD_EN_RX_UDP BIT(4) +#define CSUM_OFFLOAD_EN_RX_IPv4 BIT(5) +#define CSUM_OFFLOAD_EN_RX_IPv6 BIT(6) +#define CSUM_OFFLOAD_EN_TX_MASK BITS(0, 2) +#define CSUM_OFFLOAD_EN_ALL BITS(0, 6) + +/* TCP, UDP, IP Checksum */ +#define RX_CS_TYPE_UDP BIT(7) +#define RX_CS_TYPE_TCP BIT(6) +#define RX_CS_TYPE_IPv6 BIT(5) +#define RX_CS_TYPE_IPv4 BIT(4) + +#define RX_CS_STATUS_UDP BIT(3) +#define RX_CS_STATUS_TCP BIT(2) +#define RX_CS_STATUS_IP BIT(0) + +#define CSUM_NOT_SUPPORTED 0x0 + +#define TXPWR_USE_PDSLOPE 0 + +/* NVRAM error code definitions */ +#define NVRAM_ERROR_VERSION_MISMATCH BIT(1) +#define NVRAM_ERROR_INVALID_TXPWR BIT(2) +#define NVRAM_ERROR_INVALID_DPD BIT(3) +#define NVRAM_ERROR_INVALID_MAC_ADDR BIT(4) +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY +#define NVRAM_POWER_LIMIT_TABLE_INVALID BIT(5) +#endif + +#define NUM_TC_RESOURCE_TO_STATISTICS 4 +#if CFG_SUPPORT_NCHO +#define WLAN_CFG_ARGV_MAX 64 +#else +#define WLAN_CFG_ARGV_MAX 20 +#endif +#define WLAN_CFG_ARGV_MAX_LONG 22 /* for WOW, 2+20 */ +#define WLAN_CFG_ENTRY_NUM_MAX 400 /* 128 */ +#define WLAN_CFG_KEY_LEN_MAX 32 /* include \x00 EOL */ +#define WLAN_CFG_VALUE_LEN_MAX 128 /* include \x00 EOL */ +#define WLAN_CFG_FLAG_SKIP_CB BIT(0) +#define WLAN_CFG_FILE_BUF_SIZE 2048 + +#define WLAN_CFG_REC_ENTRY_NUM_MAX 400 + + + +#define WLAN_CFG_SET_CHIP_LEN_MAX 10 +#define WLAN_CFG_SET_DEBUG_LEVEL_LEN_MAX 10 +#define WLAN_CFG_SET_SW_CTRL_LEN_MAX 10 + +/* OID timeout (in ms) */ +#define WLAN_OID_TIMEOUT_THRESHOLD 2000 + +/* OID timeout during chip-resetting (in ms) */ +#define WLAN_OID_TIMEOUT_THRESHOLD_IN_RESETTING 300 + +#define WLAN_OID_NO_ACK_THRESHOLD 3 + + +/* If not setting the priority, 0 is the default */ +#define WLAN_THREAD_TASK_PRIORITY 0 + +/* If not setting the nice, -10 is the default */ +#define WLAN_THREAD_TASK_NICE (-10) + +#define WLAN_TX_STATS_LOG_TIMEOUT 30000 +#define WLAN_TX_STATS_LOG_DURATION 1500 + +/* Define for wifi path usage */ +#define WLAN_FLAG_2G4_WF0 BIT(0) /*1: support, 0: NOT support */ +#define WLAN_FLAG_5G_WF0 BIT(1) /*1: support, 0: NOT support */ +#define WLAN_FLAG_2G4_WF1 BIT(2) /*1: support, 0: NOT support */ +#define WLAN_FLAG_5G_WF1 BIT(3) /*1: support, 0: NOT support */ +#define WLAN_FLAG_2G4_COANT_SUPPORT BIT(4) /*1: support, 0: NOT support */ +#define WLAN_FLAG_2G4_COANT_PATH BIT(5) /*1: WF1, 0:WF0 */ +#define WLAN_FLAG_5G_COANT_SUPPORT BIT(6) /*1: support, 0: NOT support */ +#define WLAN_FLAG_5G_COANT_PATH BIT(7) /*1: WF1, 0:WF0 */ + +/* Define concurrent network channel number, using by CNM/CMD */ +#define MAX_OP_CHNL_NUM 3 + +/* Stat CMD will have different format due to different algorithm support */ +#if (defined(MT6632) || defined(MT7668)) +#define CFG_SUPPORT_RA_GEN 0 +#define CFG_SUPPORT_TXPOWER_INFO 0 +#else +#define CFG_SUPPORT_RA_GEN 1 +#define CFG_SUPPORT_TXPOWER_INFO 1 +#endif + +#if (CFG_SUPPORT_CONNAC2X == 1) +#define AGG_RANGE_SEL_NUM 15 +#else +#define AGG_RANGE_SEL_NUM 7 +#endif + +#if CFG_SUPPORT_EASY_DEBUG + +#define MAX_CMD_ITEM_MAX 4 /* Max item per cmd. */ +#define MAX_CMD_NAME_MAX_LENGTH 32 /* Max name string length */ +#define MAX_CMD_VALUE_MAX_LENGTH 32 /* Max value string length */ +#define MAX_CMD_TYPE_LENGTH 1 +#define MAX_CMD_STRING_LENGTH 1 +#define MAX_CMD_VALUE_LENGTH 1 +#define MAX_CMD_RESERVE_LENGTH 1 + +#define CMD_FORMAT_V1_LENGTH \ + (MAX_CMD_NAME_MAX_LENGTH + MAX_CMD_VALUE_MAX_LENGTH + \ + MAX_CMD_TYPE_LENGTH + MAX_CMD_STRING_LENGTH + MAX_CMD_VALUE_LENGTH + \ + MAX_CMD_RESERVE_LENGTH) + +#define MAX_CMD_BUFFER_LENGTH (CMD_FORMAT_V1_LENGTH * MAX_CMD_ITEM_MAX) + +#if 1 +#define ED_STRING_SITE 0 +#define ED_VALUE_SITE 1 + + +#else +#define ED_ITEMTYPE_SITE 0 +#define ED_STRING_SITE 1 +#define ED_VALUE_SITE 2 +#endif + +#define ACS_AP_RSSI_LEVEL_HIGH -50 +#define ACS_AP_RSSI_LEVEL_LOW -80 +#define ACS_DIRTINESS_LEVEL_HIGH 52 +#define ACS_DIRTINESS_LEVEL_MID 40 +#define ACS_DIRTINESS_LEVEL_LOW 32 + + +enum CMD_VER { + CMD_VER_1, /* Type[2]+String[32]+Value[32] */ + CMD_VER_1_EXT +}; + + +#if 0 +enum ENUM_AIS_REQUEST_TYPE { + AIS_REQUEST_SCAN, + AIS_REQUEST_RECONNECT, + AIS_REQUEST_ROAMING_SEARCH, + AIS_REQUEST_ROAMING_CONNECT, + AIS_REQUEST_REMAIN_ON_CHANNEL, + AIS_REQUEST_NUM +}; +#endif +enum CMD_TYPE { + CMD_TYPE_QUERY, + CMD_TYPE_SET +}; + +enum WLAN_CFG_TPYE { + WLAN_CFG_DEFAULT = 0x00, + WLAN_CFG_REC = 0x01, + WLAN_CFG_EM = 0x02, + WLAN_CFG_NUM +}; + +enum POWER_ACTION_CATEGORY { + SKU_POWER_LIMIT_CTRL = 0x0, + PERCENTAGE_CTRL = 0x1, + PERCENTAGE_DROP_CTRL = 0x2, + BACKOFF_POWER_LIMIT_CTRL = 0x3, + POWER_LIMIT_TABLE_CTRL = 0x4, + RF_TXANT_CTRL = 0x5, + ATEMODE_CTRL = 0x6, + TX_POWER_SHOW_INFO = 0x7, + TPC_FEATURE_CTRL = 0x8, + MU_TX_POWER_CTRL = 0x9, + BF_NDPA_TXD_CTRL = 0xa, + TSSI_WORKAROUND = 0xb, + THERMAL_COMPENSATION_CTRL = 0xc, + TX_RATE_POWER_CTRL = 0xd, + TXPOWER_UP_TABLE_CTRL = 0xe, + TX_POWER_SET_TARGET_POWER = 0xf, + TX_POWER_GET_TARGET_POWER = 0x10, + POWER_ACTION_NUM +}; + +#define ITEM_TYPE_DEC 1 +#define ITEM_TYPE_HEX 2 +#define ITEM_TYPE_STR 3 + +enum CMD_DEFAULT_SETTING_VALUE { + CMD_PNO_ENABLE, + CMD_PNO_SCAN_PERIOD, + CMD_SCN_CHANNEL_PLAN, + CMD_SCN_DWELL_TIME, + CMD_SCN_STOP_SCAN, + CMD_MAX, +}; + +enum CMD_DEFAULT_STR_SETTING_VALUE { + CMD_STR_TEST_STR, + CMD_STR_MAX, +}; + +struct CMD_FORMAT_V1 { + uint8_t itemType; + uint8_t itemStringLength; + uint8_t itemValueLength; + uint8_t Reserved; + uint8_t itemString[MAX_CMD_NAME_MAX_LENGTH]; + uint8_t itemValue[MAX_CMD_VALUE_MAX_LENGTH]; +}; + +struct CMD_HEADER { + enum CMD_VER cmdVersion; + enum CMD_TYPE cmdType; + uint8_t itemNum; + uint16_t cmdBufferLen; + uint8_t buffer[MAX_CMD_BUFFER_LENGTH]; +}; + +struct CFG_DEFAULT_SETTING_TABLE { + uint32_t itemNum; + const char *String; + uint8_t itemType; + uint32_t defaultValue; + uint32_t minValue; + uint32_t maxValue; +}; + +struct CFG_DEFAULT_SETTING_STR_TABLE { + uint32_t itemNum; + const char *String; + uint8_t itemType; + const char *DefString; + uint16_t minLen; + uint16_t maxLen; +}; + +struct CFG_QUERY_FORMAT { + uint32_t Length; + uint32_t Value; + uint32_t Type; + uint32_t *ptr; +}; + +/*Globol Configure define */ +struct CFG_SETTING { + uint8_t PnoEnable; + uint32_t PnoScanPeriod; + uint8_t ScnChannelPlan; + uint16_t ScnDwellTime; + uint8_t ScnStopScan; + uint8_t TestStr[80]; +}; + +#endif + +#if CFG_SUPPORT_NCHO +#define FW_CFG_KEY_NCHO_ENABLE "NCHOEnable" +#define FW_CFG_KEY_NCHO_ROAM_RCPI "RoamingRCPIValue" +#define FW_CFG_KEY_NCHO_SCN_CHANNEL_TIME "NCHOScnChannelTime" +#define FW_CFG_KEY_NCHO_SCN_HOME_TIME "NCHOScnHomeTime" +#define FW_CFG_KEY_NCHO_SCN_HOME_AWAY_TIME "NCHOScnHomeAwayTime" +#define FW_CFG_KEY_NCHO_SCN_NPROBES "NCHOScnNumProbs" +#define FW_CFG_KEY_NCHO_WES_MODE "NCHOWesMode" +#define FW_CFG_KEY_NCHO_SCAN_DFS_MODE "NCHOScnDfsMode" +#define FW_CFG_KEY_NCHO_SCAN_PERIOD "NCHOScnPeriod" +#endif + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +typedef uint32_t(*PFN_OID_HANDLER_FUNC) (IN struct ADAPTER *prAdapter, + IN void *pvBuf, IN uint32_t u4BufLen, + OUT uint32_t *pu4OutInfoLen); + +enum ENUM_CSUM_TYPE { + CSUM_TYPE_IPV4, + CSUM_TYPE_IPV6, + CSUM_TYPE_TCP, + CSUM_TYPE_UDP, + CSUM_TYPE_NUM +}; + +enum ENUM_CSUM_RESULT { + CSUM_RES_NONE, + CSUM_RES_SUCCESS, + CSUM_RES_FAILED, + CSUM_RES_NUM +}; + +enum ENUM_PHY_MODE { + 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 ENUM_POWER_SAVE_POLL_MODE { + ENUM_POWER_SAVE_POLL_DISABLE, + ENUM_POWER_SAVE_POLL_LEGACY_NULL, + ENUM_POWER_SAVE_POLL_QOS_NULL, + ENUM_POWER_SAVE_POLL_NUM +}; + +enum ENUM_AC_TYPE { + 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 ENUM_ADV_AC_TYPE { + 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 ENUM_REG_CH_MAP { + REG_CH_MAP_COUNTRY_CODE, + REG_CH_MAP_TBL_IDX, + REG_CH_MAP_CUSTOMIZED, + REG_CH_MAP_NUM +}; + +enum ENUM_FEATURE_OPTION { + FEATURE_DISABLED, + FEATURE_ENABLED, + FEATURE_FORCE_ENABLED +}; + +/* This enum is for later added feature options which use command reserved field + * as option switch + */ +enum ENUM_FEATURE_OPTION_IN_CMD { + FEATURE_OPT_CMD_AUTO, + FEATURE_OPT_CMD_DISABLED, + FEATURE_OPT_CMD_ENABLED, + FEATURE_OPT_CMD_FORCE_ENABLED +}; + +#define DEBUG_MSG_SIZE_MAX 1200 +enum { + DEBUG_MSG_ID_UNKNOWN = 0x00, + DEBUG_MSG_ID_PRINT = 0x01, + DEBUG_MSG_ID_FWLOG = 0x02, + DEBUG_MSG_ID_END +}; + +enum { + DEBUG_MSG_TYPE_UNKNOWN = 0x00, + DEBUG_MSG_TYPE_MEM8 = 0x01, + DEBUG_MSG_TYPE_MEM32 = 0x02, + DEBUG_MSG_TYPE_ASCII = 0x03, + DEBUG_MSG_TYPE_BINARY = 0x04, + DEBUG_MSG_TYPE_DRIVER = 0x05, + DEBUG_MSG_TYPE_END +}; + +#define CHIP_CONFIG_RESP_SIZE 320 +enum { + CHIP_CONFIG_TYPE_WO_RESPONSE = 0x00, + CHIP_CONFIG_TYPE_MEM8 = 0x01, + CHIP_CONFIG_TYPE_MEM32 = 0x02, + CHIP_CONFIG_TYPE_ASCII = 0x03, + CHIP_CONFIG_TYPE_BINARY = 0x04, + CHIP_CONFIG_TYPE_DRV_PASSTHROUGH = 0x05, + CHIP_CONFIG_TYPE_END +}; + +struct SET_TXPWR_CTRL { + int8_t c2GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0 */ + int8_t c2GHotspotPwrOffset; + int8_t c2GP2pPwrOffset; + int8_t c2GBowPwrOffset; + int8_t c5GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0 */ + int8_t c5GHotspotPwrOffset; + int8_t c5GP2pPwrOffset; + int8_t c5GBowPwrOffset; + uint8_t ucConcurrencePolicy; /* TX power policy when concurrence + * in the same channel + * 0: Highest power has priority + * 1: Lowest power has priority + */ + + int8_t acReserved1[3]; /* Must be zero */ + + /* Power limit by channel for all data rates */ + int8_t acTxPwrLimit2G[14]; /* Channel 1~14, Unit: 0.5dBm */ + int8_t acTxPwrLimit5G[4]; /* UNII 1~4 */ + int8_t acReserved2[2]; /* Must be zero */ +}; + +#if CFG_WOW_SUPPORT + +struct WOW_WAKE_HIF { + /* use in-band signal to wakeup system, ENUM_HIF_TYPE */ + uint8_t ucWakeupHif; + + /* GPIO Pin */ + uint8_t ucGpioPin; + + /* refer to PF_WAKEUP_CMD_BIT0_OUTPUT_MODE_EN */ + uint8_t ucTriggerLvl; + + /* non-zero means output reverse wakeup signal after delay time */ + uint32_t u4GpioInterval; + + uint8_t aucResv[5]; +}; + +struct WOW_CTRL { + uint8_t fgWowEnable; /* 0: disable, 1: wow enable */ + uint8_t ucScenarioId; /* just a profile ID */ + uint8_t ucBlockCount; + uint8_t aucReserved1[1]; + struct WOW_WAKE_HIF astWakeHif[2]; + struct WOW_PORT stWowPort; +}; + +#endif + +#if (CFG_SUPPORT_TWT == 1) +enum _TWT_GET_TSF_REASON { + TWT_GET_TSF_FOR_ADD_AGRT_BYPASS = 1, + TWT_GET_TSF_FOR_ADD_AGRT = 2, + TWT_GET_TSF_FOR_RESUME_AGRT = 3, + TWT_GET_TSF_REASON_MAX +}; + +struct _TWT_PARAMS_T { + uint8_t fgReq; + uint8_t fgTrigger; + uint8_t fgProtect; + uint8_t fgUnannounced; + uint8_t ucSetupCmd; + uint8_t ucMinWakeDur; + uint8_t ucWakeIntvalExponent; + uint16_t u2WakeIntvalMantiss; + uint64_t u8TWT; +}; + +struct _NEXT_TWT_INFO_T { + uint64_t u8NextTWT; + uint8_t ucNextTWTSize; +}; + +struct _TWT_CTRL_T { + uint8_t ucBssIdx; + uint8_t ucCtrlAction; + uint8_t ucTWTFlowId; + struct _TWT_PARAMS_T rTWTParams; +}; + +struct _TWT_GET_TSF_CONTEXT_T { + enum _TWT_GET_TSF_REASON ucReason; + uint8_t ucBssIdx; + uint8_t ucTWTFlowId; + uint8_t fgIsOid; + struct _TWT_PARAMS_T rTWTParams; +}; + +#endif + +enum ENUM_NVRAM_MTK_FEATURE { + MTK_FEATURE_2G_256QAM_DISABLED = 0, + MTK_FEATURE_NUM +}; + +/* For storing driver initialization value from glue layer */ +struct REG_INFO { + uint32_t u4SdBlockSize; /* SDIO block size */ + uint32_t u4SdBusWidth; /* SDIO bus width. 1 or 4 */ + uint32_t u4SdClockRate; /* SDIO clock rate. (in unit of HZ) */ + + /* Start Frequency for Ad-Hoc network : in unit of KHz */ + uint32_t u4StartFreq; + + /* Default mode for Ad-Hoc network : ENUM_PARAM_AD_HOC_MODE_T */ + uint32_t u4AdhocMode; + + uint32_t u4RddStartFreq; + uint32_t u4RddStopFreq; + uint32_t u4RddTestMode; + uint32_t u4RddShutFreq; + uint32_t u4RddDfs; + int32_t i4HighRssiThreshold; + int32_t i4MediumRssiThreshold; + int32_t i4LowRssiThreshold; + int32_t au4TxPriorityTag[ENUM_AC_TYPE_NUM]; + int32_t au4RxPriorityTag[ENUM_AC_TYPE_NUM]; + int32_t au4AdvPriorityTag[ENUM_ADV_AC_TYPE_NUM]; + uint32_t u4FastPSPoll; + uint32_t u4PTA; /* 0: disable, 1: enable */ + uint32_t u4TXLimit; /* 0: disable, 1: enable */ + uint32_t u4SilenceWindow; /* range: 100 - 625, unit: us */ + uint32_t u4TXLimitThreshold; /* range: 250 - 1250, unit: us */ + uint32_t u4PowerMode; + uint32_t fgEnArpFilter; + uint32_t u4PsCurrentMeasureEn; + uint32_t u4UapsdAcBmp; + uint32_t u4MaxSpLen; + + /* 0: enable online scan, non-zero: disable online scan */ + uint32_t fgDisOnlineScan; + + /* 0: enable online scan, non-zero: disable online scan */ + uint32_t fgDisBcnLostDetection; + + /* 0: automatic, non-zero: fixed rate */ + uint32_t u4FixedRate; + + uint32_t u4ArSysParam0; + uint32_t u4ArSysParam1; + uint32_t u4ArSysParam2; + uint32_t u4ArSysParam3; + + /* 0:enable roaming 1:disable */ + uint32_t fgDisRoaming; + + /* NVRAM - MP Data -START- */ +#if 1 + uint16_t u2Part1OwnVersion; + uint16_t u2Part1PeerVersion; +#endif + uint8_t aucMacAddr[6]; + /* Country code (in ISO 3166-1 expression, ex: "US", "TW") */ + uint16_t au2CountryCode[4]; + uint8_t ucSupport5GBand; + + enum ENUM_REG_CH_MAP eRegChannelListMap; + uint8_t ucRegChannelListIndex; + struct DOMAIN_INFO_ENTRY rDomainInfo; + struct RSSI_PATH_COMPASATION rRssiPathCompasation; + uint8_t ucRssiPathCompasationUsed; + /* NVRAM - MP Data -END- */ + + /* NVRAM - Functional Data -START- */ + uint8_t ucEnable5GBand; + /* NVRAM - Functional Data -END- */ + + struct NEW_EFUSE_MAPPING2NVRAM *prOldEfuseMapping; + + uint8_t aucNvram[512]; + struct WIFI_CFG_PARAM_STRUCT *prNvramSettings; +}; + +/* for divided firmware loading */ +struct FWDL_SECTION_INFO { +#if 0 + uint32_t u4Offset; + uint32_t u4Reserved; + uint32_t u4Length; + uint32_t u4DestAddr; +#endif + uint32_t u4DestAddr; + uint8_t ucChipInfo; + uint8_t ucFeatureSet; + uint8_t ucEcoCode; + uint8_t aucReserved[9]; + uint8_t aucBuildDate[16]; + uint32_t u4Length; +}; + +struct FIRMWARE_DIVIDED_DOWNLOAD { +#if 0 + uint32_t u4Signature; + + /* CRC calculated without first 8 bytes included */ + uint32_t u4CRC; + + uint32_t u4NumOfEntries; + uint32_t u4Reserved; + struct FWDL_SECTION_INFO arSection[]; +#endif + struct FWDL_SECTION_INFO arSection[2]; +}; + +struct PARAM_MCR_RW_STRUCT { + uint32_t u4McrOffset; + uint32_t u4McrData; +}; + +/* per access category statistics */ +struct WIFI_WMM_AC_STAT { + uint32_t u4TxMsdu; + uint32_t u4RxMsdu; + uint32_t u4TxDropMsdu; + uint32_t u4TxFailMsdu; + uint32_t u4TxRetryMsdu; +}; + +struct TX_VECTOR_BBP_LATCH { + uint32_t u4TxV[3]; +}; + +struct MIB_INFO_STAT { + uint32_t u4RxMpduCnt; + uint32_t u4FcsError; + uint32_t u4RxFifoFull; + uint32_t u4AmpduTxSfCnt; + uint32_t u4AmpduTxAckSfCnt; + uint16_t au2TxRangeAmpduCnt[AGG_RANGE_SEL_NUM + 1]; +}; + +struct PARAM_GET_STA_STATISTICS { + /* Per-STA statistic */ + uint8_t ucInvalid; + uint8_t ucVersion; + uint8_t aucMacAddr[MAC_ADDR_LEN]; + + uint32_t u4LinkScore; + uint32_t u4Flag; + + uint8_t ucReadClear; + uint8_t ucLlsReadClear; + + /* From driver */ + uint32_t u4TxTotalCount; + uint32_t u4TxExceedThresholdCount; + + uint32_t u4TxMaxTime; + uint32_t u4TxAverageProcessTime; + + uint32_t u4TxMaxHifTime; + uint32_t u4TxAverageHifTime; + + uint32_t u4RxTotalCount; + + /* + * How many packages Enqueue/Deqeue during statistics interval + */ + uint32_t u4EnqueueCounter; + uint32_t u4DequeueCounter; + + uint32_t u4EnqueueStaCounter; + uint32_t u4DequeueStaCounter; + + uint32_t IsrCnt; + uint32_t IsrPassCnt; + uint32_t TaskIsrCnt; + + uint32_t IsrAbnormalCnt; + uint32_t IsrSoftWareCnt; + uint32_t IsrRxCnt; + uint32_t IsrTxCnt; + + uint32_t au4TcResourceEmptyCount[NUM_TC_RESOURCE_TO_STATISTICS]; + uint32_t au4DequeueNoTcResource[NUM_TC_RESOURCE_TO_STATISTICS]; + uint32_t au4TcResourceBackCount[NUM_TC_RESOURCE_TO_STATISTICS]; + uint32_t au4TcResourceUsedPageCount[NUM_TC_RESOURCE_TO_STATISTICS]; + uint32_t au4TcResourceWantedPageCount[NUM_TC_RESOURCE_TO_STATISTICS]; + + uint32_t au4TcQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + + /* From FW */ + uint8_t ucPer; /* base: 128 */ + uint8_t ucRcpi; + uint32_t u4PhyMode; + uint16_t u2LinkSpeed; /* unit is 0.5 Mbits */ + + uint32_t u4TxFailCount; + uint32_t u4TxLifeTimeoutCount; + + uint32_t u4TxAverageAirTime; + + /* Transmit in the air (wtbl) */ + uint32_t u4TransmitCount; + + /* Transmit without ack/ba in the air (wtbl) */ + uint32_t u4TransmitFailCount; + + /*link layer statistics */ + struct WIFI_WMM_AC_STAT arLinkStatistics[AC_NUM]; + + /* Global queue management statistic */ + uint32_t au4TcAverageQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + uint32_t au4TcCurrentQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + + uint8_t ucTemperature; + uint8_t ucSkipAr; + uint8_t ucArTableIdx; + uint8_t ucRateEntryIdx; + uint8_t ucRateEntryIdxPrev; + uint8_t ucTxSgiDetectPassCnt; + uint8_t ucAvePer; +#if (CFG_SUPPORT_RA_GEN == 0) + uint8_t aucArRatePer[AR_RATE_TABLE_ENTRY_MAX]; + uint8_t aucRateEntryIndex[AUTO_RATE_NUM]; +#else + uint32_t u4AggRangeCtrl_0; + uint32_t u4AggRangeCtrl_1; + uint8_t ucRangeType; +#if (CFG_SUPPORT_CONNAC2X == 0) + uint8_t aucReserved5[24]; +#else + uint32_t u4AggRangeCtrl_2; + uint32_t u4AggRangeCtrl_3; + uint8_t aucReserved5[16]; +#endif +#endif + uint8_t ucArStateCurr; + uint8_t ucArStatePrev; + uint8_t ucArActionType; + uint8_t ucHighestRateCnt; + uint8_t ucLowestRateCnt; + uint16_t u2TrainUp; + uint16_t u2TrainDown; + uint32_t u4Rate1TxCnt; + uint32_t u4Rate1FailCnt; + struct TX_VECTOR_BBP_LATCH rTxVector[ENUM_BAND_NUM]; + struct MIB_INFO_STAT rMibInfo[ENUM_BAND_NUM]; + uint8_t ucResetCounter; + u_int8_t fgIsForceTxStream; + u_int8_t fgIsForceSeOff; +#if (CFG_SUPPORT_RA_GEN == 0) + uint8_t aucReserved6[17]; +#else + uint16_t u2RaRunningCnt; + uint8_t ucRaStatus; + uint8_t ucFlag; + uint8_t aucTxQuality[MAX_TX_QUALITY_INDEX]; + uint8_t ucTxRateUpPenalty; + uint8_t ucLowTrafficMode; + uint8_t ucLowTrafficCount; + uint8_t ucLowTrafficDashBoard; + uint8_t ucDynamicSGIState; + uint8_t ucDynamicSGIScore; + uint8_t ucDynamicBWState; + uint8_t ucDynamicGband256QAMState; + uint8_t ucVhtNonSpRateState; +#endif + /* Reserved fields */ + uint8_t au4Reserved[3]; +}; + +struct PARAM_GET_BSS_STATISTICS { + /* Per-STA statistic */ + uint8_t aucMacAddr[MAC_ADDR_LEN]; + + uint32_t u4Flag; + + uint8_t ucReadClear; + + uint8_t ucLlsReadClear; + + uint8_t ucBssIndex; + + /* From driver */ + uint32_t u4TxTotalCount; + uint32_t u4TxExceedThresholdCount; + + uint32_t u4TxMaxTime; + uint32_t u4TxAverageProcessTime; + + uint32_t u4RxTotalCount; + + uint32_t au4TcResourceEmptyCount[NUM_TC_RESOURCE_TO_STATISTICS]; + uint32_t au4TcQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + + /* From FW */ + uint8_t ucPer; /* base: 128 */ + uint8_t ucRcpi; + uint32_t u4PhyMode; + uint16_t u2LinkSpeed; /* unit is 0.5 Mbits */ + + uint32_t u4TxFailCount; + uint32_t u4TxLifeTimeoutCount; + + uint32_t u4TxAverageAirTime; + + /* Transmit in the air (wtbl) */ + uint32_t u4TransmitCount; + + /* Transmit without ack/ba in the air (wtbl) */ + uint32_t u4TransmitFailCount; + + /*link layer statistics */ + struct WIFI_WMM_AC_STAT arLinkStatistics[AC_NUM]; + + /* Global queue management statistic */ + uint32_t au4TcAverageQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + uint32_t au4TcCurrentQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + + /* Reserved fields */ + uint8_t au4Reserved[32]; /* insufficient for LLS?? */ +}; + +struct PARAM_GET_DRV_STATISTICS { + int32_t i4TxPendingFrameNum; + int32_t i4TxPendingSecurityFrameNum; + int32_t i4TxPendingCmdNum; + + /* sync i4PendingFwdFrameCount in _TX_CTRL_T */ + int32_t i4PendingFwdFrameCount; + + /* sync pad->rTxCtrl.rFreeMsduInfoList.u4NumElem */ + uint32_t u4MsduNumElem; + + /* sync pad->rTxCtrl.rTxMgmtTxingQueue.u4NumElem */ + uint32_t u4TxMgmtTxringQueueNumElem; + + /* sync pad->prRxCtrl.rFreeSwRfbList.u4NumElem */ + uint32_t u4RxFreeSwRfbMsduNumElem; + + /* sync pad->prRxCtrl.rReceivedRfbList.u4NumElem */ + uint32_t u4RxReceivedRfbNumElem; + + /* sync pad->prRxCtrl.rIndicatedRfbList.u4NumElem */ + uint32_t u4RxIndicatedNumElem; +}; + +struct NET_INTERFACE_INFO { + uint8_t ucBssIndex; + void *pvNetInterface; +}; + +enum ENUM_TX_RESULT_CODE { + 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_BIP_ERROR, + TX_RESULT_UNSPECIFIED_ERROR, + TX_RESULT_DROPPED_IN_DRIVER = 32, + TX_RESULT_DROPPED_IN_FW, + TX_RESULT_QUEUE_CLEARANCE, + TX_RESULT_INACTIVE_BSS, + TX_RESULT_NUM +}; + +/* enum of BEACON_TIMEOUT_REASON */ +enum _ENUM_PM_BEACON_TIME_OUT_REACON_CODE_T { + BEACON_TIMEOUT_DUE_2_HW_BEACON_LOST_NONADHOC, + BEACON_TIMEOUT_DUE_2_HW_BEACON_LOST_ADHOC, + BEACON_TIMEOUT_DUE_2_HW_TSF_DRIFT, + BEACON_TIMEOUT_DUE_2_NULL_FRAME_THRESHOLD, + BEACON_TIMEOUT_DUE_2_AGING_THRESHOLD, + BEACON_TIMEOUT_DUE_2_BSSID_BEACON_PEIROD_NOT_ILLIGAL, + BEACON_TIMEOUT_DUE_2_CONNECTION_FAIL, + BEACON_TIMEOUT_DUE_2_ALLOCAT_NULL_PKT_FAIL_THRESHOLD, + BEACON_TIMEOUT_DUE_2_NO_TX_DONE_EVENT, + BEACON_TIMEOUT_DUE_2_UNSPECIF_REASON, + BEACON_TIMEOUT_DUE_2_SET_CHIP, + BEACON_TIMEOUT_DUE_2_KEEP_SCAN_AP_MISS_CHECK_FAIL, + BEACON_TIMEOUT_DUE_2_KEEP_UNCHANGED_LOW_RSSI_CHECK_FAIL, + BEACON_TIMEOUT_DUE_2_NULL_FRAME_LIFE_TIMEOUT, + BEACON_TIMEOUT_DUE_2_APR_NO_RESPONSE, + BEACON_TIMEOUT_DUE_2_NUM +}; + +struct WLAN_CFG_ENTRY { + uint8_t aucKey[WLAN_CFG_KEY_LEN_MAX]; + uint8_t aucValue[WLAN_CFG_VALUE_LEN_MAX]; + WLAN_CFG_SET_CB pfSetCb; + void *pPrivate; + uint32_t u4Flags; +}; + +struct WLAN_CFG { + uint32_t u4WlanCfgEntryNumMax; + uint32_t u4WlanCfgKeyLenMax; + uint32_t u4WlanCfgValueLenMax; + struct WLAN_CFG_ENTRY arWlanCfgBuf[WLAN_CFG_ENTRY_NUM_MAX]; +}; + +struct WLAN_CFG_REC { + uint32_t u4WlanCfgEntryNumMax; + uint32_t u4WlanCfgKeyLenMax; + uint32_t u4WlanCfgValueLenMax; + struct WLAN_CFG_ENTRY arWlanCfgBuf[WLAN_CFG_REC_ENTRY_NUM_MAX]; +}; + +enum ENUM_MAX_BANDWIDTH_SETTING { + MAX_BW_20MHZ = 0, + MAX_BW_40MHZ, + MAX_BW_80MHZ, + MAX_BW_160MHZ, + MAX_BW_80_80_MHZ, + MAX_BW_UNKNOWN +}; + +struct TX_PACKET_INFO { + uint8_t ucPriorityParam; + uint32_t u4PacketLen; + uint8_t aucEthDestAddr[MAC_ADDR_LEN]; + uint16_t u2Flag; + +#if 0 + u_int8_t fgIs1X; + u_int8_t fgIsPAL; + u_int8_t fgIs802_3; + u_int8_t fgIsVlanExists; + u_int8_t fgIsDhcp; + u_int8_t fgIsArp; +#endif +}; + +enum ENUM_TX_PROFILING_TAG { + TX_PROF_TAG_OS_TO_DRV = 0, + TX_PROF_TAG_DRV_ENQUE, + TX_PROF_TAG_DRV_DEQUE, + TX_PROF_TAG_DRV_TX_DONE, + TX_PROF_TAG_DRV_FREE +}; + +#if (CFG_SUPPORT_SPE_IDX_CONTROL == 1) +enum ENUM_WF_PATH_FAVOR_T { + ENUM_WF_NON_FAVOR = 0xff, + ENUM_WF_0_ONE_STREAM_PATH_FAVOR = 0, + ENUM_WF_1_ONE_STREAM_PATH_FAVOR = 1, + ENUM_WF_0_1_TWO_STREAM_PATH_FAVOR = 2, + ENUM_WF_0_1_DUP_STREAM_PATH_FAVOR = 3, +}; + +enum ENUM_SPE_SEL_BY_T { + ENUM_SPE_SEL_BY_TXD = 0, + ENUM_SPE_SEL_BY_WTBL = 1, +}; +#endif + +struct PARAM_GET_CNM_T { + uint8_t fgIsDbdcEnable; + + uint8_t ucOpChNum[ENUM_BAND_NUM]; + uint8_t ucChList[ENUM_BAND_NUM][MAX_OP_CHNL_NUM]; + uint8_t ucChBw[ENUM_BAND_NUM][MAX_OP_CHNL_NUM]; + uint8_t ucChSco[ENUM_BAND_NUM][MAX_OP_CHNL_NUM]; + uint8_t ucChNetNum[ENUM_BAND_NUM][MAX_OP_CHNL_NUM]; + uint8_t ucChBssList[ENUM_BAND_NUM][MAX_OP_CHNL_NUM][BSSID_NUM]; + + uint8_t ucBssInuse[BSSID_NUM + 1]; + uint8_t ucBssActive[BSSID_NUM + 1]; + uint8_t ucBssConnectState[BSSID_NUM + 1]; + + uint8_t ucBssCh[BSSID_NUM + 1]; + uint8_t ucBssDBDCBand[BSSID_NUM + 1]; + uint8_t ucBssWmmSet[BSSID_NUM + 1]; + uint8_t ucBssWmmDBDCBand[BSSID_NUM + 1]; + uint8_t ucBssOMACSet[BSSID_NUM + 1]; + uint8_t ucBssOMACDBDCBand[BSSID_NUM + 1]; + + /* Reserved fields */ + uint8_t au4Reserved[65]; /*Total 160 byte*/ +}; + +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR +struct WIFI_LINK_QUALITY_INFO { + uint32_t u4CurTxRate; /* current tx link speed */ + uint64_t u8TxTotalCount; /* tx total accumulated count */ + uint64_t u8TxRetryCount; /* tx retry count */ + uint64_t u8TxFailCount; /* tx fail count */ + uint64_t u8TxRtsFailCount; /* tx RTS fail count */ + uint64_t u8TxAckFailCount; /* tx ACK fail count */ + + uint32_t u4CurRxRate; /* current rx link speed */ + uint64_t u8RxTotalCount; /* rx total packages */ + uint32_t u4RxDupCount; /* rx duplicate package count */ + uint64_t u8RxErrCount; /* rx fcs fail count */ + + uint32_t u4CurTxPer; /* current Tx PER */ + uint64_t u8MdrdyCount; + uint64_t u8IdleSlotCount; /* congestion stats: idle slot */ + uint64_t u8DiffIdleSlotCount; + uint32_t u4HwMacAwakeDuration; + uint16_t u2FlagScanning; + + uint32_t u4PhyMode; + uint16_t u2LinkSpeed; + + uint64_t u8LastTxTotalCount; + uint64_t u8LastTxFailCount; + uint64_t u8LastIdleSlotCount; +}; +#endif /* CFG_SUPPORT_LINK_QUALITY_MONITOR */ + +#if CFG_SUPPORT_IOT_AP_BLACKLIST +enum ENUM_WLAN_IOT_AP_FLAG_T { + WLAN_IOT_AP_FG_VERSION = 0, + WLAN_IOT_AP_FG_OUI, + WLAN_IOT_AP_FG_DATA, + WLAN_IOT_AP_FG_DATA_MASK, + WLAN_IOT_AP_FG_BSSID, + WLAN_IOT_AP_FG_BSSID_MASK, + WLAN_IOT_AP_FG_NSS, + WLAN_IOT_AP_FG_HT, + WLAN_IOT_AP_FG_BAND, + WLAN_IOT_AP_FG_ACTION, + WLAN_IOT_AP_FG_MAX +}; + +enum ENUM_WLAN_IOT_AP_HANDLE_ACTION { + WLAN_IOT_AP_VOID = 0, + WLAN_IOT_AP_DBDC_1SS, + WLAN_IOT_AP_DIS_SG, + WLAN_IOT_AP_COEX_CTS2SELF, + WLAN_IOT_AP_FIX_MODE, + WLAN_IOT_AP_DIS_2GHT40, + WLAN_IOT_AP_KEEP_EDCA_PARAM = 6, + WLAN_IOT_AP_ACT_MAX +}; + +struct WLAN_IOT_AP_RULE_T { + uint16_t u2MatchFlag; + uint8_t ucDataLen; + uint8_t ucDataMaskLen; + uint8_t ucVersion; + uint8_t aVendorOui[MAC_OUI_LEN]; + uint8_t aVendorData[CFG_IOT_AP_DATA_MAX_LEN]; + uint8_t aVendorDataMask[CFG_IOT_AP_DATA_MAX_LEN]; + uint8_t aBssid[MAC_ADDR_LEN]; + uint8_t aBssidMask[MAC_ADDR_LEN]; + uint8_t ucNss; + uint8_t ucHtType; + uint8_t ucBand; + uint8_t ucAction; +}; +#endif +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +#define BUILD_SIGN(ch0, ch1, ch2, ch3) \ + ((uint32_t)(uint8_t)(ch0) | ((uint32_t)(uint8_t)(ch1) << 8) | \ + ((uint32_t)(uint8_t)(ch2) << 16) | ((uint32_t)(uint8_t)(ch3) << 24)) + +#define MTK_WIFI_SIGNATURE BUILD_SIGN('M', 'T', 'K', 'W') + +#define IS_FEATURE_ENABLED(_ucFeature) \ + (((_ucFeature) == FEATURE_ENABLED) || \ + ((_ucFeature) == FEATURE_FORCE_ENABLED)) +#define IS_FEATURE_FORCE_ENABLED(_ucFeature) \ + ((_ucFeature) == FEATURE_FORCE_ENABLED) +#define IS_FEATURE_DISABLED(_ucFeature) ((_ucFeature) == FEATURE_DISABLED) + +/* This macro is for later added feature options which use command reserved + * field as option switch + */ +/* 0: AUTO + * 1: Disabled + * 2: Enabled + * 3: Force disabled + */ +#define FEATURE_OPT_IN_COMMAND(_ucFeature) ((_ucFeature) + 1) + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +struct ADAPTER *wlanAdapterCreate(IN struct GLUE_INFO *prGlueInfo); + +void wlanAdapterDestroy(IN struct ADAPTER *prAdapter); + +void wlanCardEjected(IN struct ADAPTER *prAdapter); + +void wlanIST(IN struct ADAPTER *prAdapter, bool fgEnInt); + +u_int8_t wlanISR(IN struct ADAPTER *prAdapter, IN u_int8_t fgGlobalIntrCtrl); + +uint32_t wlanProcessCommandQueue(IN struct ADAPTER *prAdapter, + IN struct QUE *prCmdQue); + +uint32_t wlanSendCommand(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo); + +#if CFG_SUPPORT_MULTITHREAD +uint32_t wlanSendCommandMthread(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo); + +uint32_t wlanTxCmdMthread(IN struct ADAPTER *prAdapter); + +uint32_t wlanTxCmdDoneMthread(IN struct ADAPTER *prAdapter); + +void wlanClearTxCommandQueue(IN struct ADAPTER *prAdapter); + +void wlanClearTxCommandDoneQueue(IN struct ADAPTER *prAdapter); + +void wlanClearDataQueue(IN struct ADAPTER *prAdapter); + +void wlanClearRxToOsQueue(IN struct ADAPTER *prAdapter); +#endif + +void wlanClearPendingCommandQueue(IN struct ADAPTER *prAdapter); + +void wlanReleaseCommand(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +void wlanReleasePendingOid(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr); + +void wlanReleasePendingCMDbyBssIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +void wlanReturnPacketDelaySetupTimeout(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr); + +void wlanReturnPacket(IN struct ADAPTER *prAdapter, IN void *pvPacket); + +uint32_t +wlanQueryInformation(IN struct ADAPTER *prAdapter, + IN PFN_OID_HANDLER_FUNC pfOidQryHandler, + IN void *pvInfoBuf, IN uint32_t u4InfoBufLen, + OUT uint32_t *pu4QryInfoLen); + +uint32_t +wlanSetInformation(IN struct ADAPTER *prAdapter, + IN PFN_OID_HANDLER_FUNC pfOidSetHandler, + IN void *pvInfoBuf, IN uint32_t u4InfoBufLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanAdapterStart(IN struct ADAPTER *prAdapter, + IN struct REG_INFO *prRegInfo, + IN const u_int8_t bAtResetFlow); + +uint32_t wlanAdapterStop(IN struct ADAPTER *prAdapter, + IN const u_int8_t bAtResetFlow); + +void wlanCheckAsicCap(IN struct ADAPTER *prAdapter); + +uint32_t wlanCheckWifiFunc(IN struct ADAPTER *prAdapter, + IN u_int8_t fgRdyChk); + +void wlanReturnRxPacket(IN void *pvAdapter, IN void *pvPacket); + +void wlanRxSetBroadcast(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnableBroadcast); + +u_int8_t wlanIsHandlerNeedHwAccess(IN PFN_OID_HANDLER_FUNC pfnOidHandler, + IN u_int8_t fgSetInfo); + +void wlanSetPromiscuousMode(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnablePromiscuousMode); + +uint32_t wlanSendDummyCmd(IN struct ADAPTER *prAdapter, + IN u_int8_t fgIsReqTxRsrc); + +uint32_t wlanSendNicPowerCtrlCmd(IN struct ADAPTER *prAdapter, + IN uint8_t ucPowerMode); + +u_int8_t wlanIsHandlerAllowedInRFTest(IN PFN_OID_HANDLER_FUNC pfnOidHandler, + IN u_int8_t fgSetInfo); + +uint32_t wlanProcessQueuedSwRfb(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfbListHead); + +uint32_t wlanProcessQueuedMsduInfo(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfoListHead); + +u_int8_t wlanoidTimeoutCheck(IN struct ADAPTER *prAdapter, + IN PFN_OID_HANDLER_FUNC pfnOidHandler); + +void wlanoidClearTimeoutCheck(IN struct ADAPTER *prAdapter); + +uint32_t wlanUpdateNetworkAddress(IN struct ADAPTER *prAdapter); + +uint32_t wlanUpdateBasicConfig(IN struct ADAPTER *prAdapter); + +u_int8_t wlanQueryTestMode(IN struct ADAPTER *prAdapter); + +u_int8_t wlanProcessTxFrame(IN struct ADAPTER *prAdapter, + IN void *prPacket); + +/* Security Frame Handling */ +u_int8_t wlanProcessSecurityFrame(IN struct ADAPTER *prAdapter, + IN void *prPacket); + +uint32_t wlanProcessCmdDataFrame(IN struct ADAPTER + *prAdapter, IN void *prPacket); + +void wlanSecurityFrameTxDone(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +void wlanSecurityAndCmdDataFrameTxTimeout(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo); + +void wlanCmdDataFrameTxDone(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + + +/*----------------------------------------------------------------------------*/ +/* OID/IOCTL Handling */ +/*----------------------------------------------------------------------------*/ +void wlanClearScanningResult(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +void wlanClearBssInScanningResult(IN struct ADAPTER *prAdapter, + IN uint8_t *arBSSID); + +#if CFG_TEST_WIFI_DIRECT_GO +void wlanEnableP2pFunction(IN struct ADAPTER *prAdapter); + +void wlanEnableATGO(IN struct ADAPTER *prAdapter); +#endif + +/*----------------------------------------------------------------------------*/ +/* NIC Capability Retrieve by Polling */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanQueryNicCapability(IN struct ADAPTER *prAdapter); + +/*----------------------------------------------------------------------------*/ +/* PD MCR Retrieve by Polling */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanQueryPdMcr(IN struct ADAPTER *prAdapter, + IN struct PARAM_MCR_RW_STRUCT *prMcrRdInfo); + +/*----------------------------------------------------------------------------*/ +/* Get minimal tx power setting from NVRAM */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanGetMiniTxPower(IN struct ADAPTER *prAdapter, + IN enum ENUM_BAND eBand, + IN enum ENUM_PHY_MODE_TYPE ePhyMode, + OUT int8_t *pTxPwr); +/*----------------------------------------------------------------------------*/ +/* Loading Manufacture Data */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanLoadManufactureData(IN struct ADAPTER *prAdapter, + IN struct REG_INFO *prRegInfo); + +/*----------------------------------------------------------------------------*/ +/* Media Stream Mode */ +/*----------------------------------------------------------------------------*/ +u_int8_t wlanResetMediaStreamMode(IN struct ADAPTER *prAdapter); + +/*----------------------------------------------------------------------------*/ +/* Timer Timeout Check (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanTimerTimeoutCheck(IN struct ADAPTER *prAdapter); + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Check (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanProcessMboxMessage(IN struct ADAPTER *prAdapter); + +/*----------------------------------------------------------------------------*/ +/* TX Pending Packets Handling (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanEnqueueTxPacket(IN struct ADAPTER *prAdapter, + IN void *prNativePacket); + +uint32_t wlanFlushTxPendingPackets(IN struct ADAPTER *prAdapter); + +uint32_t wlanTxPendingPackets(IN struct ADAPTER *prAdapter, + IN OUT u_int8_t *pfgHwAccess); + +/*----------------------------------------------------------------------------*/ +/* Low Power Acquire/Release (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanAcquirePowerControl(IN struct ADAPTER *prAdapter); + +uint32_t wlanReleasePowerControl(IN struct ADAPTER *prAdapter); + +/*----------------------------------------------------------------------------*/ +/* Pending Packets Number Reporting (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanGetTxPendingFrameCount(IN struct ADAPTER *prAdapter); + +/*----------------------------------------------------------------------------*/ +/* ACPI state inquiry (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +enum ENUM_ACPI_STATE wlanGetAcpiState(IN struct ADAPTER *prAdapter); + +void wlanSetAcpiState(IN struct ADAPTER *prAdapter, + IN enum ENUM_ACPI_STATE ePowerState); + + +/*----------------------------------------------------------------------------*/ +/* get ECO version from Revision ID register (for Win32) */ +/*----------------------------------------------------------------------------*/ +uint8_t wlanGetEcoVersion(IN struct ADAPTER *prAdapter); + +/*----------------------------------------------------------------------------*/ +/* set preferred band configuration corresponding to network type */ +/*----------------------------------------------------------------------------*/ +void wlanSetPreferBandByNetwork(IN struct ADAPTER *prAdapter, + IN enum ENUM_BAND eBand, IN uint8_t ucBssIndex); + +/*----------------------------------------------------------------------------*/ +/* get currently operating channel information */ +/*----------------------------------------------------------------------------*/ +uint8_t wlanGetChannelNumberByNetwork(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +/*----------------------------------------------------------------------------*/ +/* check for system configuration to generate message on scan list */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanCheckSystemConfiguration(IN struct ADAPTER *prAdapter); + +/*----------------------------------------------------------------------------*/ +/* query bss statistics information from driver and firmware */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryBssStatistics(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +/*----------------------------------------------------------------------------*/ +/* dump per-BSS statistics */ +/*----------------------------------------------------------------------------*/ +void wlanDumpBssStatistics(IN struct ADAPTER *prAdapter, uint8_t ucBssIndex); + +/*----------------------------------------------------------------------------*/ +/* query sta statistics information from driver and firmware */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryStaStatistics(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanQueryStaStatistics(IN struct ADAPTER *prAdapter, IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen, + u_int8_t fgIsOid); + +uint32_t +wlanQueryStatistics(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen, IN uint8_t fgIsOid); + +/*----------------------------------------------------------------------------*/ +/* query NIC resource information from chip and reset Tx resource for normal */ +/* operation */ +/*----------------------------------------------------------------------------*/ +void wlanQueryNicResourceInformation(IN struct ADAPTER *prAdapter); + +uint32_t wlanQueryNicCapabilityV2(IN struct ADAPTER *prAdapter); + +void wlanUpdateNicResourceInformation(IN struct ADAPTER *prAdapter); + +/*----------------------------------------------------------------------------*/ +/* GET/SET BSS index mapping for network interfaces */ +/*----------------------------------------------------------------------------*/ +void wlanBindNetInterface(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucNetInterfaceIndex, + IN void *pvNetInterface); + +void wlanBindBssIdxToNetInterface(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucBssIndex, + IN void *pvNetInterface); + +uint8_t wlanGetBssIdxByNetInterface(IN struct GLUE_INFO *prGlueInfo, + IN void *pvNetInterface); + +void *wlanGetNetInterfaceByBssIdx(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucBssIndex); + +/* for windows as windows glue cannot see through P_ADAPTER_T */ + +void wlanInitFeatureOption(IN struct ADAPTER *prAdapter); + +void wlanCfgSetSwCtrl(IN struct ADAPTER *prAdapter); + +void wlanCfgSetChip(IN struct ADAPTER *prAdapter); + +#if (CFG_SUPPORT_CONNINFRA == 1) +void wlanCfgSetChipSyncTime(IN struct ADAPTER *prAdapter); +#endif + +void wlanCfgSetDebugLevel(IN struct ADAPTER *prAdapter); + +void wlanCfgSetCountryCode(IN struct ADAPTER *prAdapter); + +struct WLAN_CFG_ENTRY *wlanCfgGetEntry(IN struct ADAPTER *prAdapter, + const int8_t *pucKey, + uint32_t u4Flags); + +uint32_t +wlanCfgGet(IN struct ADAPTER *prAdapter, const int8_t *pucKey, int8_t *pucValue, + int8_t *pucValueDef, uint32_t u4Flags); + +uint32_t wlanCfgGetUint32(IN struct ADAPTER *prAdapter, const int8_t *pucKey, + uint32_t u4ValueDef); + +int32_t wlanCfgGetInt32(IN struct ADAPTER *prAdapter, const int8_t *pucKey, + int32_t i4ValueDef); + +uint32_t wlanCfgSetUint32(IN struct ADAPTER *prAdapter, const int8_t *pucKey, + uint32_t u4Value); + +uint32_t wlanCfgSet(IN struct ADAPTER *prAdapter, const int8_t *pucKey, + int8_t *pucValue, uint32_t u4Flags); + +uint32_t wlanCfgSetCb(IN struct ADAPTER *prAdapter, const int8_t *pucKey, + WLAN_CFG_SET_CB pfSetCb, void *pPrivate, + uint32_t u4Flags); + +#if CFG_SUPPORT_EASY_DEBUG + +uint32_t wlanCfgParse(IN struct ADAPTER *prAdapter, uint8_t *pucConfigBuf, + uint32_t u4ConfigBufLen, u_int8_t isFwConfig); +void wlanFeatureToFw(IN struct ADAPTER *prAdapter, uint32_t u4Flag); +#endif + +void wlanLoadDefaultCustomerSetting(IN struct ADAPTER *prAdapter); + +uint32_t wlanCfgInit(IN struct ADAPTER *prAdapter, uint8_t *pucConfigBuf, + uint32_t u4ConfigBufLen, uint32_t u4Flags); + +uint32_t wlanCfgParseArgument(int8_t *cmdLine, int32_t *argc, int8_t *argv[]); + +#if CFG_WOW_SUPPORT +uint32_t wlanCfgParseArgumentLong(int8_t *cmdLine, int32_t *argc, + int8_t *argv[]); +#endif + +#if CFG_SUPPORT_IOT_AP_BLACKLIST +void wlanCfgLoadIotApRule(IN struct ADAPTER *prAdapter); +void wlanCfgDumpIotApRule(IN struct ADAPTER *prAdapter); +#endif + +int32_t wlanHexToNum(int8_t c); + +int32_t wlanHexToByte(int8_t *hex); + +int32_t wlanHexToArray(int8_t *hexString, int8_t *hexArray, uint8_t arrayLen); +int32_t wlanHexToArrayR(int8_t *hexString, int8_t *hexArray, uint8_t arrayLen); + + +int32_t wlanHwAddrToBin(int8_t *txt, uint8_t *addr); + +u_int8_t wlanIsChipNoAck(IN struct ADAPTER *prAdapter); + +u_int8_t wlanIsChipRstRecEnabled(IN struct ADAPTER *prAdapter); + +u_int8_t wlanIsChipAssert(IN struct ADAPTER *prAdapter); + +void wlanChipRstPreAct(IN struct ADAPTER *prAdapter); + +void wlanTxProfilingTagPacket(IN struct ADAPTER *prAdapter, IN void *prPacket, + IN enum ENUM_TX_PROFILING_TAG eTag); + +void wlanTxProfilingTagMsdu(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_PROFILING_TAG eTag); + +void wlanTxLifetimeTagPacket(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfoListHead, + IN enum ENUM_TX_PROFILING_TAG eTag); + +#if CFG_ASSERT_DUMP +void wlanCorDumpTimerInit(IN struct ADAPTER *prAdapter, u_int8_t fgIsResetN9); + +void wlanCorDumpTimerReset(IN struct ADAPTER *prAdapter, u_int8_t fgIsResetN9); + +void wlanN9CorDumpTimeOut(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr); + +void wlanCr4CorDumpTimeOut(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr); +#endif +#endif /* _WLAN_LIB_H */ + + +u_int8_t wlanGetWlanIdxByAddress(IN struct ADAPTER *prAdapter, + IN uint8_t *pucAddr, OUT uint8_t *pucIndex); + +uint8_t *wlanGetStaAddrByWlanIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucIndex); + +struct WLAN_CFG_ENTRY *wlanCfgGetEntryByIndex(IN struct ADAPTER *prAdapter, + const uint8_t ucIdx, + uint32_t flag); + +uint32_t wlanCfgGetTotalCfgNum( + IN struct ADAPTER *prAdapter, uint32_t flag); + + +uint32_t wlanGetStaIdxByWlanIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucIndex, OUT uint8_t *pucStaIdx); + +uint8_t wlanGetBssIdx(struct net_device *ndev); + +struct net_device *wlanGetNetDev(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucBssIndex); + +struct wiphy *wlanGetWiphy(void); + +u_int8_t wlanIsAisDev(struct net_device *prDev); + +/*----------------------------------------------------------------------------*/ +/* update per-AC statistics for LLS */ +/*----------------------------------------------------------------------------*/ +void wlanUpdateTxStatistics(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, u_int8_t fgTxDrop); + +void wlanUpdateRxStatistics(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +uint32_t wlanTriggerStatsLog(IN struct ADAPTER *prAdapter, + IN uint32_t u4DurationInMs); + +uint32_t wlanPktTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +uint32_t wlanPowerOffWifi(IN struct ADAPTER *prAdapter); + +void wlanPrintVersion(struct ADAPTER *prAdapter); + +uint32_t wlanAccessRegister(IN struct ADAPTER *prAdapter, + IN uint32_t u4Addr, IN uint32_t *pru4Result, + IN uint32_t u4Data, + IN uint8_t ucSetQuery); + +uint32_t wlanAccessRegisterStatus(IN struct ADAPTER + *prAdapter, IN uint8_t ucCmdSeqNum, + IN uint8_t ucSetQuery, IN void *prEvent, + IN uint32_t u4EventLen); + +uint32_t wlanSetChipEcoInfo(IN struct ADAPTER *prAdapter); + +void wlanNotifyFwSuspend(struct GLUE_INFO *prGlueInfo, + struct net_device *prDev, u_int8_t fgSuspend); + +void wlanClearPendingInterrupt(IN struct ADAPTER *prAdapter); + +#if CFG_WMT_WIFI_PATH_SUPPORT +extern int32_t mtk_wcn_wmt_wifi_fem_cfg_report(void *pvInfoBuf); +#endif + +#if ((CFG_SISO_SW_DEVELOP == 1) || (CFG_SUPPORT_SPE_IDX_CONTROL == 1)) +uint8_t wlanGetAntPathType(IN struct ADAPTER *prAdapter, + IN enum ENUM_WF_PATH_FAVOR_T eWfPathFavor); +#endif + +uint8_t wlanGetSpeIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN enum ENUM_WF_PATH_FAVOR_T eWfPathFavor); + +uint8_t wlanGetSupportNss(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIndex); + +#if CFG_SUPPORT_LOWLATENCY_MODE +uint32_t wlanAdapterStartForLowLatency(IN struct ADAPTER *prAdapter); +uint32_t wlanProbeSuccessForLowLatency(IN struct ADAPTER *prAdapter); +uint32_t wlanConnectedForLowLatency(IN struct ADAPTER *prAdapter); +uint32_t wlanSetLowLatencyCommand(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnLowLatencyMode, + IN u_int8_t fgEnTxDupDetect, + IN u_int8_t fgTxDupCertQuery); +uint32_t wlanSetLowLatencyMode(IN struct ADAPTER *prAdapter, + IN uint32_t u4Events); +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ +int32_t wlanGetFileContent(struct ADAPTER *prAdapter, + const uint8_t *pcFileName, uint8_t *pucBuf, + uint32_t u4MaxFileLen, uint32_t *pu4ReadFileLen, u_int8_t bReqFw); + +#if CFG_SUPPORT_EASY_DEBUG +uint32_t wlanFwCfgParse(IN struct ADAPTER *prAdapter, uint8_t *pucConfigBuf); +#endif /* CFG_SUPPORT_EASY_DEBUG */ + +void wlanReleasePendingCmdById(struct ADAPTER *prAdapter, uint8_t ucCid); + +uint32_t wlanDecimalStr2Hexadecimals(uint8_t *pucDecimalStr, uint16_t *pu2Out); + +uint64_t wlanGetSupportedFeatureSet(IN struct GLUE_INFO *prGlueInfo); + +uint32_t +wlanQueryLteSafeChannel(IN struct ADAPTER *prAdapter, + IN uint8_t ucRoleIndex); + +uint32_t +wlanCalculateAllChannelDirtiness(IN struct ADAPTER *prAdapter); + +void +wlanInitChnLoadInfoChannelList(IN struct ADAPTER *prAdapter); + +uint8_t +wlanGetChannelIndex(IN uint8_t channel); + +uint8_t +wlanGetChannelNumFromIndex(IN uint8_t ucIdx); + +void +wlanSortChannel(IN struct ADAPTER *prAdapter, + IN enum ENUM_CHNL_SORT_POLICY ucSortType); + +void wlanSuspendPmHandle(struct GLUE_INFO *prGlueInfo); +void wlanResumePmHandle(struct GLUE_INFO *prGlueInfo); + +#if defined(CFG_REPORT_MAX_TX_RATE) && (CFG_REPORT_MAX_TX_RATE == 1) +int wlanGetMaxTxRate(IN struct ADAPTER *prAdapter, + IN void *prBssPtr, IN struct STA_RECORD *prStaRec, + OUT uint32_t *pu4CurRate, OUT uint32_t *pu4MaxRate); +#endif /* CFG_REPORT_MAX_TX_RATE */ + +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR +int wlanGetRxRate(IN struct GLUE_INFO *prGlueInfo, + OUT uint32_t *pu4CurRate, OUT uint32_t *pu4MaxRate); +uint32_t wlanLinkQualityMonitor(struct GLUE_INFO *prGlueInfo, bool bFgIsOid); +void wlanFinishCollectingLinkQuality(struct GLUE_INFO *prGlueInfo); +#endif /* CFG_SUPPORT_LINK_QUALITY_MONITOR */ +u_int8_t wlanIsDriverReady(IN struct GLUE_INFO *prGlueInfo); +void wlanOffUninitNicModule(IN struct ADAPTER *prAdapter, + IN const u_int8_t bAtResetFlow); +void wlanOffClearAllQueues(IN struct ADAPTER *prAdapter); +uint8_t wlanGetBssIdx(struct net_device *ndev); +int wlanQueryRateByTable(uint32_t txmode, uint32_t rate, + uint32_t frmode, uint32_t sgi, uint32_t nsts, + uint32_t *pu4CurRate, uint32_t *pu4MaxRate); + +#if CFG_SUPPORT_DATA_STALL +void wlanCustomMonitorFunction(struct ADAPTER *prAdapter, + struct WIFI_LINK_QUALITY_INFO *prLinkQualityInfo, uint8_t ucBssIdx); +#endif /* CFG_SUPPORT_DATA_STALL */ +uint32_t wlanSetForceRTS(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnForceRTS); + +void +wlanBackupEmCfgSetting(IN struct ADAPTER *prAdapter); + +void +wlanResoreEmCfgSetting(IN struct ADAPTER *prAdapter); + +void +wlanCleanAllEmCfgSetting(IN struct ADAPTER *prAdapter); + +#if CFG_SUPPORT_NCHO +void wlanNchoInit(IN struct ADAPTER *prAdapter, IN uint8_t fgFwSync); +uint32_t wlanNchoSetFWEnable(IN struct ADAPTER *prAdapter, IN uint8_t fgEnable); +uint32_t wlanNchoSetFWRssiTrigger(IN struct ADAPTER *prAdapter, + IN int32_t i4RoamTriggerRssi); +uint32_t wlanNchoSetFWScanPeriod(IN struct ADAPTER *prAdapter, + IN uint32_t u4RoamScanPeriod); +#endif + +u_int8_t wlanWfdEnabled(struct ADAPTER *prAdapter); + +int wlanChipConfig(struct ADAPTER *prAdapter, + char *pcCommand, int i4TotalLen); diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/wlan_oid.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/wlan_oid.h new file mode 100644 index 0000000000000..cb0c1e30233c9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/wlan_oid.h @@ -0,0 +1,4182 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include + * /wlan_oid.h#4 + */ + +/*! \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. + */ + +#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_GETSIZE 0 +#define PARAM_EEPROM_READ_METHOD_READ 1 +#define PARAM_EEPROM_READ_NVRAM 2 +#define PARAM_EEPROM_WRITE_NVRAM 3 + + +#define PARAM_WHQL_RSSI_MAX_DBM (-10) +#define PARAM_WHQL_RSSI_INITIAL_DBM (-50) +#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 0xF0000000 +#define PARAM_PACKET_FILTER_PROBE_REQ 0x80000000 +#define PARAM_PACKET_FILTER_ACTION_FRAME 0x40000000 +#define PARAM_PACKET_FILTER_AUTH 0x20000000 +#define PARAM_PACKET_FILTER_ASSOC_REQ 0x10000000 +#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 | \ + PARAM_PACKET_FILTER_ALL_MULTICAST) +#endif + +#define PARAM_MEM_DUMP_MAX_SIZE 1536 + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +#define PARAM_CAL_DATA_DUMP_MAX_SIZE 1200 +#define PARAM_CAL_DATA_DUMP_MAX_NUM 300 +#endif + +#define BT_PROFILE_PARAM_LEN 8 + +/* Based on EEPROM layout 20160120 */ +#define EFUSE_ADDR_MAX 0x3BF +#if CFG_SUPPORT_BUFFER_MODE + +/* For MT7668 */ +#define EFUSE_CONTENT_BUFFER_START 0x03A +#define EFUSE_CONTENT_BUFFER_END 0x1D9 +#define EFUSE_CONTENT_BUFFER_SIZE (EFUSE_CONTENT_BUFFER_END - \ + EFUSE_CONTENT_BUFFER_START + 1) + +/* For MT6632 */ +#define EFUSE_CONTENT_SIZE 16 + +#define EFUSE_BLOCK_SIZE 16 +#define EEPROM_SIZE 1184 +#define MAX_EEPROM_BUFFER_SIZE 1450 +#endif /* CFG_SUPPORT_BUFFER_MODE */ + +#if CFG_SUPPORT_TX_BF +#define TXBF_CMD_NEED_TO_RESPONSE(u4TxBfCmdId) \ + (u4TxBfCmdId == BF_PFMU_TAG_READ || \ + u4TxBfCmdId == BF_PROFILE_READ) +#endif /* CFG_SUPPORT_TX_BF */ +#define MU_CMD_NEED_TO_RESPONSE(u4MuCmdId) \ + (u4MuCmdId == MU_GET_CALC_INIT_MCS || \ + u4MuCmdId == MU_HQA_GET_QD || \ + u4MuCmdId == MU_HQA_GET_CALC_LQ) +#if CFG_SUPPORT_MU_MIMO +/* @NITESH: MACROS For Init MCS calculation (MU Metric Table) */ +#define NUM_MUT_FEC 2 +#define NUM_MUT_MCS 10 +#define NUM_MUT_NR_NUM 3 +#define NUM_MUT_INDEX 8 + +#define NUM_OF_USER 2 +#define NUM_OF_MODUL 5 +#endif /* CFG_SUPPORT_MU_MIMO */ + +#define SER_ACTION_QUERY 0 +#define SER_ACTION_SET 1 +#define SER_ACTION_SET_ENABLE_MASK 2 +#define SER_ACTION_RECOVER 3 + +/* SER_ACTION_SET sub action */ +#define SER_SET_DISABLE 0 +#define SER_SET_ENABLE 1 + +/* SER_ACTION_SET_ENABLE_MASK mask define */ +#define SER_ENABLE_TRACKING BIT(0) +#define SER_ENABLE_L1_RECOVER BIT(1) +#define SER_ENABLE_L2_RECOVER BIT(2) +#define SER_ENABLE_L3_RX_ABORT BIT(3) +#define SER_ENABLE_L3_TX_ABORT BIT(4) +#define SER_ENABLE_L3_TX_DISABLE BIT(5) +#define SER_ENABLE_L3_BF_RECOVER BIT(6) + +/* SER_ACTION_RECOVER recover method */ +#define SER_SET_L0_RECOVER 0 +#define SER_SET_L1_RECOVER 1 +#define SER_SET_L2_RECOVER 2 +#define SER_SET_L3_RX_ABORT 3 +#define SER_SET_L3_TX_ABORT 4 +#define SER_SET_L3_TX_DISABLE 5 +#define SER_SET_L3_BF_RECOVER 6 + + +/* SER user command */ +#define SER_USER_CMD_DISABLE 0 +#define SER_USER_CMD_ENABLE 1 + +#define SER_USER_CMD_ENABLE_MASK_TRACKING_ONLY (200) +#define SER_USER_CMD_ENABLE_MASK_L1_RECOVER_ONLY (201) +#define SER_USER_CMD_ENABLE_MASK_L2_RECOVER_ONLY (202) +#define SER_USER_CMD_ENABLE_MASK_L3_RX_ABORT_ONLY (203) +#define SER_USER_CMD_ENABLE_MASK_L3_TX_ABORT_ONLY (204) +#define SER_USER_CMD_ENABLE_MASK_L3_TX_DISABLE_ONLY (205) +#define SER_USER_CMD_ENABLE_MASK_L3_BFRECOVER_ONLY (206) +#define SER_USER_CMD_ENABLE_MASK_RECOVER_ALL (207) + + +/* Use a magic number to prevent human mistake */ +#define SER_USER_CMD_L0_RECOVER 956 +#define SER_USER_CMD_L1_RECOVER 995 + +#define SER_USER_CMD_L2_BN0_RECOVER (300) +#define SER_USER_CMD_L2_BN1_RECOVER (301) +#define SER_USER_CMD_L3_RX0_ABORT (302) +#define SER_USER_CMD_L3_RX1_ABORT (303) +#define SER_USER_CMD_L3_TX0_ABORT (304) +#define SER_USER_CMD_L3_TX1_ABORT (305) +#define SER_USER_CMD_L3_TX0_DISABLE (306) +#define SER_USER_CMD_L3_TX1_DISABLE (307) +#define SER_USER_CMD_L3_BF_RECOVER (308) + + +#define TXPOWER_MAN_SET_INPUT_ARG_NUM 4 + +#if (CFG_SUPPORT_TXPOWER_INFO == 1) +#define TXPOWER_INFO_INPUT_ARG_NUM 2 +#define TXPOWER_FORMAT_LEGACY 0 +#define TXPOWER_FORMAT_HE 1 + +/* 1M, 2M, 5.5M, 11M */ +#define MODULATION_SYSTEM_CCK_NUM 4 + +/* 6M, 9M, 12M, 18M, 24M, 36M, 48M, 54M */ +#define MODULATION_SYSTEM_OFDM_NUM 8 + +#define MODULATION_SYSTEM_HT20_NUM 8 /* MCS0~7 */ +#define MODULATION_SYSTEM_HT40_NUM 9 /* MCS0~7, MCS32 */ +#define MODULATION_SYSTEM_VHT20_NUM 10 /* MCS0~9 */ +#define MODULATION_SYSTEM_VHT40_NUM MODULATION_SYSTEM_VHT20_NUM +#define MODULATION_SYSTEM_VHT80_NUM MODULATION_SYSTEM_VHT20_NUM +#define MODULATION_SYSTEM_VHT160_NUM MODULATION_SYSTEM_VHT20_NUM + +#define MODULATION_SYSTEM_HE_26_MCS_NUM 12 +#define MODULATION_SYSTEM_HE_52_MCS_NUM 12 +#define MODULATION_SYSTEM_HE_106_MCS_NUM 12 +#define MODULATION_SYSTEM_HE_242_MCS_NUM 12 +#define MODULATION_SYSTEM_HE_484_MCS_NUM 12 +#define MODULATION_SYSTEM_HE_996_MCS_NUM 12 +#define MODULATION_SYSTEM_HE_996X2_MCS_NUM 12 + +#define TXPOWER_RATE_CCK_OFFSET (0) +#define TXPOWER_RATE_OFDM_OFFSET (TXPOWER_RATE_CCK_OFFSET + \ + MODULATION_SYSTEM_CCK_NUM) +#define TXPOWER_RATE_HT20_OFFSET (TXPOWER_RATE_OFDM_OFFSET + \ + MODULATION_SYSTEM_OFDM_NUM) +#define TXPOWER_RATE_HT40_OFFSET (TXPOWER_RATE_HT20_OFFSET + \ + MODULATION_SYSTEM_HT20_NUM) +#define TXPOWER_RATE_VHT20_OFFSET (TXPOWER_RATE_HT40_OFFSET + \ + MODULATION_SYSTEM_HT40_NUM) +#define TXPOWER_RATE_VHT40_OFFSET (TXPOWER_RATE_VHT20_OFFSET + \ + MODULATION_SYSTEM_VHT20_NUM) +#define TXPOWER_RATE_VHT80_OFFSET (TXPOWER_RATE_VHT40_OFFSET + \ + MODULATION_SYSTEM_VHT40_NUM) +#define TXPOWER_RATE_VHT160_OFFSET (TXPOWER_RATE_VHT80_OFFSET + \ + MODULATION_SYSTEM_VHT80_NUM) + +#define TXPOWER_RATE_HE26_OFFSET (TXPOWER_RATE_VHT160_OFFSET) +#define TXPOWER_RATE_HE52_OFFSET (TXPOWER_RATE_HE26_OFFSET + \ + MODULATION_SYSTEM_HE_26_MCS_NUM) +#define TXPOWER_RATE_HE106_OFFSET (TXPOWER_RATE_HE52_OFFSET + \ + MODULATION_SYSTEM_HE_52_MCS_NUM) +#define TXPOWER_RATE_HE242_OFFSET (TXPOWER_RATE_HE106_OFFSET + \ + MODULATION_SYSTEM_HE_106_MCS_NUM) +#define TXPOWER_RATE_HE484_OFFSET (TXPOWER_RATE_HE242_OFFSET + \ + MODULATION_SYSTEM_HE_242_MCS_NUM) +#define TXPOWER_RATE_HE996_OFFSET (TXPOWER_RATE_HE484_OFFSET + \ + MODULATION_SYSTEM_HE_484_MCS_NUM) +#define TXPOWER_RATE_HE996X2_OFFSET (TXPOWER_RATE_HE996_OFFSET + \ + MODULATION_SYSTEM_HE_996_MCS_NUM) +#define TXPOWER_RATE_NUM (TXPOWER_RATE_HE996X2_OFFSET + \ + MODULATION_SYSTEM_HE_996X2_MCS_NUM) +#endif + +#if CFG_SUPPORT_LOWLATENCY_MODE +#define GED_EVENT_GAS (1 << 4) +#define GED_EVENT_NETWORK (1 << 11) +#define GED_EVENT_DOPT_WIFI_SCAN (1 << 12) +#define GED_EVENT_TX_DUP_DETECT (1 << 13) + +#define LOW_LATENCY_MODE_MAGIC_CODE 0x86 +#define LOW_LATENCY_MODE_CMD_V2 0x2 +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +/*----------------------------------------------------------------------------*/ +/* Parameters of User Configuration which match to NDIS5.1 */ +/*----------------------------------------------------------------------------*/ + +enum ENUM_PARAM_PHY_TYPE { + 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 ENUM_PARAM_OP_MODE { + 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 */ +}; + +struct PARAM_CONNECT { + uint32_t u4SsidLen; /*!< SSID length in bytes. + * Zero length is broadcast(any) SSID + */ + uint8_t *pucSsid; + uint8_t *pucBssid; + uint8_t *pucBssidHint; + uint32_t u4CenterFreq; + uint8_t ucBssIdx; +}; + +struct PARAM_EXTERNAL_AUTH { + uint8_t bssid[PARAM_MAC_ADDR_LEN]; + uint16_t status; + uint8_t ucBssIdx; +}; + +struct PARAM_OP_MODE { + enum ENUM_PARAM_OP_MODE eOpMode; + uint8_t ucBssIdx; +}; + +/* This is enum defined for user to select an AdHoc Mode */ +enum ENUM_PARAM_AD_HOC_MODE { + 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 ENUM_PARAM_NETWORK_TYPE { + 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 */ +}; + +struct PARAM_NETWORK_TYPE_LIST { + uint32_t NumberOfItems; /*!< At least 1 */ + enum ENUM_PARAM_NETWORK_TYPE eNetworkType[1]; +}; + +enum ENUM_PARAM_PRIVACY_FILTER { + PRIVACY_FILTER_ACCEPT_ALL, + PRIVACY_FILTER_8021xWEP, + PRIVACY_FILTER_NUM +}; + +enum ENUM_RELOAD_DEFAULTS { + ENUM_RELOAD_WEP_KEYS +}; + +struct PARAM_PM_PACKET_PATTERN { + uint32_t Priority; /* Importance of the given pattern. */ + uint32_t Reserved; /* Context information for transports. */ + uint32_t MaskSize; /* Size in bytes of the pattern mask. */ + uint32_t PatternOffset; /* Offset from beginning of this */ + /* structure to the pattern bytes. */ + uint32_t PatternSize; /* Size in bytes of the pattern. */ + uint32_t PatternFlags; /* Flags (TBD). */ +}; + + +/* Combine ucTpTestMode and ucSigmaTestMode in one flag */ +/* ucTpTestMode == 0, for normal driver */ +/* ucTpTestMode == 1, for pure throughput test mode (ex: RvR) */ +/* ucTpTestMode == 2, for sigma TGn/TGac/PMF */ +/* ucTpTestMode == 3, for sigma WMM PS */ +enum ENUM_TP_TEST_MODE { + ENUM_TP_TEST_MODE_NORMAL = 0, + ENUM_TP_TEST_MODE_THROUGHPUT, + ENUM_TP_TEST_MODE_SIGMA_AC_N_PMF, + ENUM_TP_TEST_MODE_SIGMA_WMM_PS, + ENUM_TP_TEST_MODE_NUM +}; + +/*--------------------------------------------------------------*/ +/*! \brief Struct definition to indicate specific event. */ +/*--------------------------------------------------------------*/ +enum ENUM_STATUS_TYPE { + ENUM_STATUS_TYPE_AUTHENTICATION, + ENUM_STATUS_TYPE_MEDIA_STREAM_MODE, + ENUM_STATUS_TYPE_CANDIDATE_LIST, + ENUM_STATUS_TYPE_FT_AUTH_STATUS, + ENUM_STATUS_TYPE_NUM /*!< Upper bound, not real case */ +}; + +struct PARAM_802_11_CONFIG_FH { + uint32_t u4Length; /*!< Length of structure */ + uint32_t u4HopPattern; /*!< Defined as 802.11 */ + uint32_t u4HopSet; /*!< to one if non-802.11 */ + uint32_t u4DwellTime; /*!< In unit of Kusec */ +}; + +struct PARAM_802_11_CONFIG { + uint32_t u4Length; /*!< Length of structure */ + uint32_t u4BeaconPeriod; /*!< In unit of Kusec */ + uint32_t u4ATIMWindow; /*!< In unit of Kusec */ + uint32_t u4DSConfig; /*!< Channel frequency in unit of kHz */ + struct PARAM_802_11_CONFIG_FH rFHConfig; +}; + +struct PARAM_STATUS_INDICATION { + enum ENUM_STATUS_TYPE eStatusType; +}; + +struct PARAM_AUTH_REQUEST { + uint32_t u4Length; /*!< Length of this struct */ + uint8_t arBssid[PARAM_MAC_ADDR_LEN]; + uint32_t u4Flags; /*!< Definitions are as follows */ +}; + +struct PARAM_PMKID { + uint8_t arBSSID[PARAM_MAC_ADDR_LEN]; + uint8_t arPMKID[IW_PMKID_LEN]; + uint8_t ucBssIdx; +}; + +struct PARAM_PMKID_CANDIDATE { + uint8_t arBSSID[PARAM_MAC_ADDR_LEN]; + uint32_t u4Flags; +}; + +struct PARAM_INDICATION_EVENT { + struct PARAM_STATUS_INDICATION rStatus; + union { + struct PARAM_AUTH_REQUEST rAuthReq; + struct PARAM_PMKID_CANDIDATE rCandi; + }; +}; + +/*! \brief Capabilities, privacy, rssi and IEs of each BSSID */ +struct PARAM_BSSID_EX { + uint32_t u4Length; /*!< Length of structure */ + uint8_t arMacAddress[PARAM_MAC_ADDR_LEN]; /*!< BSSID */ + uint8_t Reserved[2]; + struct PARAM_SSID rSsid; /*!< SSID */ + uint32_t u4Privacy; /*!< Need WEP encryption */ + int32_t rRssi; /*!< in dBm */ + enum ENUM_PARAM_NETWORK_TYPE eNetworkTypeInUse; + struct PARAM_802_11_CONFIG rConfiguration; + enum ENUM_PARAM_OP_MODE eOpMode; + uint8_t rSupportedRates[PARAM_MAX_LEN_RATES_EX]; + uint32_t u4IELength; + uint8_t aucIEs[1]; +}; + +struct PARAM_BSSID_LIST_EX { + uint32_t u4NumberOfItems; /*!< at least 1 */ + struct PARAM_BSSID_EX arBssid[1]; +}; + +struct PARAM_WEP { + uint32_t u4Length; /*!< Length of structure */ + uint32_t u4KeyIndex; /*!< 0: pairwise key, others group keys */ + uint32_t u4KeyLength; /*!< Key length in bytes */ + uint8_t aucKeyMaterial[32]; /*!< Key content by above setting */ +}; + +/*! \brief Key mapping of BSSID */ +struct PARAM_KEY { + uint32_t u4Length; /*!< Length of structure */ + uint32_t u4KeyIndex; /*!< KeyID */ + uint32_t u4KeyLength; /*!< Key length in bytes */ + uint8_t arBSSID[PARAM_MAC_ADDR_LEN]; /*!< MAC address */ + uint64_t rKeyRSC; + uint8_t ucBssIdx; + uint8_t ucCipher; + uint8_t aucKeyMaterial[32]; /*!< Key content by above setting */ + /* Following add to change the original windows structure */ +}; + +struct PARAM_REMOVE_KEY { + uint32_t u4Length; /*!< Length of structure */ + uint32_t u4KeyIndex; /*!< KeyID */ + uint8_t arBSSID[PARAM_MAC_ADDR_LEN]; /*!< MAC address */ + uint8_t ucBssIdx; +}; + +/*! \brief Default key */ +struct PARAM_DEFAULT_KEY { + uint8_t ucKeyID; + uint8_t ucUnicast; + uint8_t ucMulticast; + uint8_t ucBssIdx; +}; + +#if CFG_SUPPORT_WAPI +enum ENUM_KEY_TYPE { + ENUM_WPI_PAIRWISE_KEY = 0, + ENUM_WPI_GROUP_KEY +}; + +enum ENUM_WPI_PROTECT_TYPE { + ENUM_WPI_NONE, + ENUM_WPI_RX, + ENUM_WPI_TX, + ENUM_WPI_RX_TX +}; + +struct PARAM_WPI_KEY { + enum ENUM_KEY_TYPE eKeyType; + enum ENUM_WPI_PROTECT_TYPE eDirection; + uint8_t ucKeyID; + uint8_t aucRsv[3]; + uint8_t aucAddrIndex[12]; + uint32_t u4LenWPIEK; + uint8_t aucWPIEK[256]; + uint32_t u4LenWPICK; + uint8_t aucWPICK[256]; + uint8_t aucPN[16]; + uint8_t ucBssIdx; +}; +#endif + +enum PARAM_POWER_MODE { + Param_PowerModeCAM, + Param_PowerModeMAX_PSP, + Param_PowerModeFast_PSP, + Param_PowerModeMax /* Upper bound, not real case */ +}; + +enum PARAM_DEVICE_POWER_STATE { + ParamDeviceStateUnspecified = 0, + ParamDeviceStateD0, + ParamDeviceStateD1, + ParamDeviceStateD2, + ParamDeviceStateD3, + ParamDeviceStateMaximum +}; + +struct PARAM_POWER_MODE_ { + uint8_t ucBssIdx; + enum PARAM_POWER_MODE ePowerMode; +}; + +#if CFG_SUPPORT_802_11D + +/*! \brief The enumeration definitions for OID_IPN_MULTI_DOMAIN_CAPABILITY */ +enum PARAM_MULTI_DOMAIN_CAPABILITY { + ParamMultiDomainCapDisabled, + ParamMultiDomainCapEnabled +}; +#endif + +struct COUNTRY_STRING_ENTRY { + uint8_t aucCountryCode[2]; + uint8_t aucEnvironmentCode[2]; +}; + +/* 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) + +enum ENUM_POWER_SAVE_PROFILE { + ENUM_PSP_CONTINUOUS_ACTIVE = 0, + ENUM_PSP_CONTINUOUS_POWER_SAVE, + ENUM_PSP_FAST_SWITCH, + ENUM_PSP_NUM +}; + +struct LINK_SPEED_EX_ { + int8_t cRssi; + + uint8_t fgIsLinkQualityValid; + OS_SYSTIME rLinkQualityUpdateTime; + int8_t cLinkQuality; + + uint8_t fgIsLinkRateValid; + OS_SYSTIME rLinkRateUpdateTime; + uint32_t u2LinkSpeed; + + uint8_t ucMediumBusyPercentage; + uint8_t ucIsLQ0Rdy; +}; + +struct PARAM_LINK_SPEED_EX { + struct LINK_SPEED_EX_ rLq[BSSID_NUM]; +}; + +/*--------------------------------------------------------------*/ +/*! \brief Set/Query authentication and encryption capability. */ +/*--------------------------------------------------------------*/ +struct PARAM_AUTH_ENCRYPTION { + enum ENUM_PARAM_AUTH_MODE eAuthModeSupported; + enum ENUM_WEP_STATUS eEncryptStatusSupported; +}; + +struct PARAM_CAPABILITY { + uint32_t u4Length; + uint32_t u4Version; + uint32_t u4NoOfAuthEncryptPairsSupported; + struct PARAM_AUTH_ENCRYPTION + arAuthenticationEncryptionSupported[1]; +}; + +#define NL80211_KCK_LEN 16 +#define NL80211_KEK_LEN 16 +#define NL80211_REPLAY_CTR_LEN 8 + +struct PARAM_GTK_REKEY_DATA { + uint8_t aucKek[NL80211_KEK_LEN]; + uint8_t aucKck[NL80211_KCK_LEN]; + uint8_t aucReplayCtr[NL80211_REPLAY_CTR_LEN]; + uint8_t ucBssIndex; + uint8_t ucRsv[3]; + uint32_t u4Proto; + uint32_t u4PairwiseCipher; + uint32_t u4GroupCipher; + uint32_t u4KeyMgmt; + uint32_t u4MgmtGroupCipher; +}; + +struct PARAM_CUSTOM_MCR_RW_STRUCT { + uint32_t u4McrOffset; + uint32_t u4McrData; +}; + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +/* + * Description of Each Parameters : + * ucReason : + * 0 : Query Information of Thermal or Cal Data Length + * 1 : Trigger FW do or don't All Cal + * 2 : Dump Data to Host + * 3 : Send Backupped Cal Data to FW + * 4 : For Debug Use, Tell FW Print Cal Data (Rom or Ram) + * ucAction : + * 0 : Read Thermal Value + * 1 : Ask the Cal Data Total Length (Rom and Ram) + * 2 : Tell FW do All Cal + * 3 : Tell FW don't do Cal + * 4 : Dump Data to Host (Rom or Ram) + * 5 : Send Backupped Cal Data to FW (Rom or Ram) + * 6 : For Debug Use, Tell FW Print Cal Data (Rom or Ram) + * ucNeedResp : + * 0 : FW No Need to Response an EVENT + * 1 : FW Need to Response an EVENT + * ucFragNum : + * Sequence Number + * ucRomRam : + * 0 : Operation for Rom Cal Data + * 1 : Operation for Ram Cal Data + * u4ThermalValue : + * Field for filling the Thermal Value in FW + * u4Address : + * Dumpped Starting Address + * Used for Dump and Send Cal Data Between Driver and FW + * u4Length : + * Memory Size need to allocated in Driver or Data Size in an EVENT + * Used for Dump and Send Cal Data Between Driver and FW + * u4RemainLength : + * Remain Length need to Dump + * Used for Dump and Send Cal Data Between Driver and FW + */ +struct PARAM_CAL_BACKUP_STRUCT_V2 { + uint8_t ucReason; + uint8_t ucAction; + uint8_t ucNeedResp; + uint8_t ucFragNum; + uint8_t ucRomRam; + uint32_t u4ThermalValue; + uint32_t u4Address; + uint32_t u4Length; + uint32_t u4RemainLength; +}; +#endif + +#if CFG_SUPPORT_QA_TOOL +#if CFG_SUPPORT_BUFFER_MODE +struct BIN_CONTENT { + uint16_t u2Addr; + uint8_t ucValue; + uint8_t ucReserved; +}; + +struct PARAM_CUSTOM_EFUSE_BUFFER_MODE { + uint8_t ucSourceMode; + uint8_t ucCount; + uint8_t ucCmdType; + uint8_t ucReserved; + uint8_t aBinContent[MAX_EEPROM_BUFFER_SIZE]; +}; + +struct PARAM_CUSTOM_EFUSE_BUFFER_MODE_CONNAC_T { + uint8_t ucSourceMode; + uint8_t ucContentFormat; + uint16_t u2Count; + uint8_t aBinContent[MAX_EEPROM_BUFFER_SIZE]; +}; + +/*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ +struct PARAM_CUSTOM_ACCESS_EFUSE { + uint32_t u4Address; + uint32_t u4Valid; + uint8_t aucData[16]; +}; + +struct PARAM_CUSTOM_EFUSE_FREE_BLOCK { + uint8_t ucGetFreeBlock; + uint8_t aucReserved[3]; +}; + +struct PARAM_CUSTOM_GET_TX_POWER { + uint8_t ucTxPwrType; + uint8_t ucCenterChannel; + uint8_t ucDbdcIdx; /* 0:Band 0, 1: Band1 */ + uint8_t ucBand; /* 0:G-band 1: A-band*/ + uint8_t ucReserved[4]; +}; + +/*#endif*/ + +#endif /* CFG_SUPPORT_BUFFER_MODE */ + +struct PARAM_CUSTOM_SET_TX_TARGET_POWER { + int8_t cTxPwr2G4Cck; /* signed, in unit of 0.5dBm */ + int8_t cTxPwr2G4Dsss; /* signed, in unit of 0.5dBm */ + uint8_t ucTxTargetPwr; /* Tx target power base for all*/ + uint8_t ucReserved; + + int8_t cTxPwr2G4OFDM_BPSK; + int8_t cTxPwr2G4OFDM_QPSK; + int8_t cTxPwr2G4OFDM_16QAM; + int8_t cTxPwr2G4OFDM_Reserved; + int8_t cTxPwr2G4OFDM_48Mbps; + int8_t cTxPwr2G4OFDM_54Mbps; + + int8_t cTxPwr2G4HT20_BPSK; + int8_t cTxPwr2G4HT20_QPSK; + int8_t cTxPwr2G4HT20_16QAM; + int8_t cTxPwr2G4HT20_MCS5; + int8_t cTxPwr2G4HT20_MCS6; + int8_t cTxPwr2G4HT20_MCS7; + + int8_t cTxPwr2G4HT40_BPSK; + int8_t cTxPwr2G4HT40_QPSK; + int8_t cTxPwr2G4HT40_16QAM; + int8_t cTxPwr2G4HT40_MCS5; + int8_t cTxPwr2G4HT40_MCS6; + int8_t cTxPwr2G4HT40_MCS7; + + int8_t cTxPwr5GOFDM_BPSK; + int8_t cTxPwr5GOFDM_QPSK; + int8_t cTxPwr5GOFDM_16QAM; + int8_t cTxPwr5GOFDM_Reserved; + int8_t cTxPwr5GOFDM_48Mbps; + int8_t cTxPwr5GOFDM_54Mbps; + + int8_t cTxPwr5GHT20_BPSK; + int8_t cTxPwr5GHT20_QPSK; + int8_t cTxPwr5GHT20_16QAM; + int8_t cTxPwr5GHT20_MCS5; + int8_t cTxPwr5GHT20_MCS6; + int8_t cTxPwr5GHT20_MCS7; + + int8_t cTxPwr5GHT40_BPSK; + int8_t cTxPwr5GHT40_QPSK; + int8_t cTxPwr5GHT40_16QAM; + int8_t cTxPwr5GHT40_MCS5; + int8_t cTxPwr5GHT40_MCS6; + int8_t cTxPwr5GHT40_MCS7; +}; + +#if (CFG_SUPPORT_DFS_MASTER == 1) +struct PARAM_CUSTOM_SET_RDD_REPORT { + uint8_t ucDbdcIdx; /* 0:Band 0, 1: Band1 */ +}; + +struct PARAM_CUSTOM_SET_RADAR_DETECT_MODE { + /* 0:Switch channel, 1: Don't switch channel */ + uint8_t ucRadarDetectMode; +}; +#endif + +struct PARAM_CUSTOM_ACCESS_RX_STAT { + uint32_t u4SeqNum; + uint32_t u4TotalNum; +}; + +/* Ext DevInfo Tag */ +enum EXT_ENUM_DEVINFO_TAG_HANDLE { + DEV_INFO_ACTIVE = 0, + DEV_INFO_BSSID, + DEV_INFO_MAX_NUM +}; + +/* STA record TLV tag */ +enum EXT_ENUM_STAREC_TAG_HANDLE { + STA_REC_BASIC = 0, + STA_REC_RA, + STA_REC_RA_COMMON_INFO, + STA_REC_RA_UPDATE, + STA_REC_BF, + STA_REC_MAUNAL_ASSOC, + STA_REC_BA = 6, + STA_REC_MAX_NUM +}; + +#if CFG_SUPPORT_TX_BF +enum BF_ACTION_CATEGORY { + BF_SOUNDING_OFF = 0, + BF_SOUNDING_ON, + BF_DATA_PACKET_APPLY, + BF_PFMU_MEM_ALLOCATE, + BF_PFMU_MEM_RELEASE, + BF_PFMU_TAG_READ, + BF_PFMU_TAG_WRITE, + BF_PROFILE_READ, + BF_PROFILE_WRITE, + BF_PN_READ, + BF_PN_WRITE, + BF_PFMU_MEM_ALLOC_MAP_READ, +#if CFG_SUPPORT_TX_BF_FPGA + BF_PFMU_SW_TAG_WRITE = 23 +#endif +}; + +enum { + DEVINFO_ACTIVE = 0, + DEVINFO_MAX_NUM = 1, +}; + +enum { + DEVINFO_ACTIVE_FEATURE = (1 << DEVINFO_ACTIVE), + DEVINFO_MAX_NUM_FEATURE = (1 << DEVINFO_MAX_NUM) +}; + +enum { + BSS_INFO_OWN_MAC = 0, + BSS_INFO_BASIC = 1, + BSS_INFO_RF_CH = 2, + BSS_INFO_PM = 3, + BSS_INFO_UAPSD = 4, + BSS_INFO_ROAM_DETECTION = 5, + BSS_INFO_LQ_RM = 6, + BSS_INFO_EXT_BSS = 7, + BSS_INFO_BROADCAST_INFO = 8, + BSS_INFO_SYNC_MODE = 9, + BSS_INFO_MAX_NUM +}; + +union PFMU_PROFILE_TAG1 { + struct { + /* [6:0] : 0 ~ 63 */ + uint32_t ucProfileID: 7; + + /* [7] : 0: iBF, 1: eBF */ + uint32_t ucTxBf: 1; + + /* [9:8] : 0/1/2/3: DW20/40/80/160NC */ + uint32_t ucDBW: 2; + + /* [10] : 0:SU, 1: MU */ + uint32_t ucSU_MU: 1; + + /* [11] : 0: default, 1: This profile number is invalid by SW */ + uint32_t ucInvalidProf: 1; + + /* [14:12] : RMSD value from CE */ + uint32_t ucRMSD: 3; + + /* [17 : 15] : column index : 0 ~ 5 */ + uint32_t ucMemAddr1ColIdx: 3; + + /* [23 : 18] : row index : 0 ~ 63 */ + uint32_t ucMemAddr1RowIdx: 6; + + /* [26 : 24] : column index : 0 ~ 5 */ + uint32_t ucMemAddr2ColIdx: 3; + + /* [31 : 27] : row index : 0 ~ 63 */ + uint32_t ucMemAddr2RowIdx: 5; + + /* [32] : MSB of row index */ + uint32_t ucMemAddr2RowIdxMsb: 1; + + /* [35 : 33] : column index : 0 ~ 5 */ + uint32_t ucMemAddr3ColIdx: 3; + + /* [41 : 36] : row index : 0 ~ 63 */ + uint32_t ucMemAddr3RowIdx: 6; + + /* [44 : 42] : column index : 0 ~ 5 */ + uint32_t ucMemAddr4ColIdx: 3; + + /* [50 : 45] : row index : 0 ~ 63 */ + uint32_t ucMemAddr4RowIdx: 6; + + /* [51] : Reserved */ + uint32_t ucReserved: 1; + + /* [53 : 52] : Nrow */ + uint32_t ucNrow: 2; + + /* [55 : 54] : Ncol */ + uint32_t ucNcol: 2; + + /* [57 : 56] : Ngroup */ + uint32_t ucNgroup: 2; + + /* [59 : 58] : 0/1/2 */ + uint32_t ucLM: 2; + + /* [61:60] : Code book */ + uint32_t ucCodeBook: 2; + + /* [62] : HtcExist */ + uint32_t ucHtcExist: 1; + + /* [63] : Reserved */ + uint32_t ucReserved1: 1; + + /* [71:64] : SNR_STS0 */ + uint32_t ucSNR_STS0: 8; + + /* [79:72] : SNR_STS1 */ + uint32_t ucSNR_STS1: 8; + + /* [87:80] : SNR_STS2 */ + uint32_t ucSNR_STS2: 8; + + /* [95:88] : SNR_STS3 */ + uint32_t ucSNR_STS3: 8; + + /* [103:96] : iBF LNA index */ + uint32_t ucIBfLnaIdx: 8; + } rField; + uint32_t au4RawData[4]; +}; + +union PFMU_PROFILE_TAG2 { + struct { + uint32_t u2SmartAnt: 12;/* [11:0] : Smart Ant config */ + uint32_t ucReserved0: 3;/* [14:12] : Reserved */ + uint32_t ucSEIdx: 5; /* [19:15] : SE index */ + uint32_t ucRMSDThd: 3; /* [22:20] : RMSD Threshold */ + uint32_t ucReserved1: 1;/* [23] : Reserved */ + uint32_t ucMCSThL1SS: 4;/* [27:24] : MCS TH long 1SS */ + uint32_t ucMCSThS1SS: 4;/* [31:28] : MCS TH short 1SS */ + uint32_t ucMCSThL2SS: 4;/* [35:32] : MCS TH long 2SS */ + uint32_t ucMCSThS2SS: 4;/* [39:36] : MCS TH short 2SS */ + uint32_t ucMCSThL3SS: 4;/* [43:40] : MCS TH long 3SS */ + uint32_t ucMCSThS3SS: 4;/* [47:44] : MCS TH short 3SS */ + uint32_t uciBfTimeOut: 8;/* [55:48] : iBF timeout limit */ + uint32_t ucReserved2: 8;/* [63:56] : Reserved */ + uint32_t ucReserved3: 8;/* [71:64] : Reserved */ + uint32_t ucReserved4: 8;/* [79:72] : Reserved */ + uint32_t uciBfDBW: 2; /* [81:80] : iBF desired DBW 0/1/2/3 : + * BW20/40/80/160NC + */ + uint32_t uciBfNcol: 2; /* [83:82] : iBF desired Ncol = 1 ~ 3 */ + uint32_t uciBfNrow: 2; /* [85:84] : iBF desired Nrow = 1 ~ 4 */ + uint32_t u2Reserved5: 10;/* [95:86] : Reserved */ + } rField; + uint32_t au4RawData[3]; +}; + +union PFMU_DATA { + struct { + uint32_t u2Phi11: 9; + uint32_t ucPsi21: 7; + uint32_t u2Phi21: 9; + uint32_t ucPsi31: 7; + uint32_t u2Phi31: 9; + uint32_t ucPsi41: 7; + uint32_t u2Phi22: 9; + uint32_t ucPsi32: 7; + uint32_t u2Phi32: 9; + uint32_t ucPsi42: 7; + uint32_t u2Phi33: 9; + uint32_t ucPsi43: 7; + uint32_t u2dSNR00: 4; + uint32_t u2dSNR01: 4; + uint32_t u2dSNR02: 4; + uint32_t u2dSNR03: 4; + uint32_t u2Reserved: 16; + } rField; + uint32_t au4RawData[5]; +}; + +struct PROFILE_TAG_READ { + uint8_t ucTxBfCategory; + uint8_t ucProfileIdx; + u_int8_t fgBfer; + uint8_t ucRsv; +}; + +struct PROFILE_TAG_WRITE { + uint8_t ucTxBfCategory; + uint8_t ucPfmuId; + uint8_t ucBuffer[28]; +}; + +struct PROFILE_DATA_READ { + uint8_t ucTxBfCategory; + uint8_t ucPfmuIdx; + u_int8_t fgBFer; + uint8_t ucReserved[3]; + uint8_t ucSubCarrIdxLsb; + uint8_t ucSubCarrIdxMsb; +}; + +struct PROFILE_DATA_WRITE { + uint8_t ucTxBfCategory; + uint8_t ucPfmuIdx; + uint8_t u2SubCarrIdxLsb; + uint8_t u2SubCarrIdxMsb; + union PFMU_DATA rTxBfPfmuData; +}; + +struct PROFILE_PN_READ { + uint8_t ucTxBfCategory; + uint8_t ucPfmuIdx; + uint8_t ucReserved[2]; +}; + +struct PROFILE_PN_WRITE { + uint8_t ucTxBfCategory; + uint8_t ucPfmuIdx; + uint16_t u2bw; + uint8_t ucBuf[32]; +}; + +enum BF_SOUNDING_MODE { + SU_SOUNDING = 0, + MU_SOUNDING, + SU_PERIODIC_SOUNDING, + MU_PERIODIC_SOUNDING +}; + +struct EXT_CMD_ETXBf_SND_PERIODIC_TRIGGER_CTRL { + uint8_t ucCmdCategoryID; + uint8_t ucSuMuSndMode; + uint8_t ucWlanIdx; + uint32_t u4SoundingInterval; /* By ms */ +}; + +struct EXT_CMD_ETXBf_MU_SND_PERIODIC_TRIGGER_CTRL { + uint8_t ucCmdCategoryID; + uint8_t ucSuMuSndMode; + uint8_t ucWlanId[4]; + uint8_t ucStaNum; + uint32_t u4SoundingInterval; /* By ms */ +}; + +/* Device information (Tag0) */ +struct CMD_DEVINFO_ACTIVE { + uint16_t u2Tag; /* Tag = 0x00 */ + uint16_t u2Length; + uint8_t ucActive; + uint8_t ucBandNum; + uint8_t aucOwnMacAddr[6]; + uint8_t aucReserve[4]; +}; + +struct BSSINFO_BASIC { + /* Basic BSS information (Tag1) */ + uint16_t u2Tag; /* Tag = 0x01 */ + uint16_t u2Length; + uint32_t u4NetworkType; + uint8_t ucActive; + uint8_t ucReserve0; + uint16_t u2BcnInterval; + uint8_t aucBSSID[6]; + uint8_t ucWmmIdx; + uint8_t ucDtimPeriod; + uint8_t ucBcMcWlanidx; /* indicate which wlan-idx used for MC/BC + * transmission. + */ + uint8_t ucCipherSuit; + uint8_t acuReserve[6]; +}; + +struct TXBF_PFMU_STA_INFO { + uint16_t u2PfmuId; /* 0xFFFF means no access right for PFMU */ + uint8_t fgSU_MU; /* 0 : SU, 1 : MU */ + uint8_t fgETxBfCap; /* 0 : ITxBf, 1 : ETxBf */ + uint8_t ucSoundingPhy; /* 0: legacy, 1: OFDM, 2: HT, 4: VHT */ + uint8_t ucNdpaRate; + uint8_t ucNdpRate; + uint8_t ucReptPollRate; + uint8_t ucTxMode; /* 0: legacy, 1: OFDM, 2: HT, 4: VHT */ + uint8_t ucNc; + uint8_t ucNr; + uint8_t ucCBW; /* 0 : 20M, 1 : 40M, 2 : 80M, 3 : 80 + 80M */ + uint8_t ucTotMemRequire; + uint8_t ucMemRequire20M; + uint8_t ucMemRow0; + uint8_t ucMemCol0; + uint8_t ucMemRow1; + uint8_t ucMemCol1; + uint8_t ucMemRow2; + uint8_t ucMemCol2; + uint8_t ucMemRow3; + uint8_t ucMemCol3; + uint16_t u2SmartAnt; + uint8_t ucSEIdx; + uint8_t uciBfTimeOut; + uint8_t uciBfDBW; + uint8_t uciBfNcol; + uint8_t uciBfNrow; + uint8_t aucReserved[3]; +}; + +struct STA_REC_UPD_ENTRY { + struct TXBF_PFMU_STA_INFO rTxBfPfmuStaInfo; + uint8_t aucAddr[PARAM_MAC_ADDR_LEN]; + uint8_t ucAid; + uint8_t ucRsv; +}; + +struct STAREC_COMMON { + /* Basic STA record (Group0) */ + uint16_t u2Tag; /* Tag = 0x00 */ + uint16_t u2Length; + uint32_t u4ConnectionType; + uint8_t ucConnectionState; + uint8_t ucIsQBSS; + uint16_t u2AID; + uint8_t aucPeerMacAddr[6]; + uint16_t u2Reserve1; +}; + +struct CMD_STAREC_BF { + uint16_t u2Tag; /* Tag = 0x02 */ + uint16_t u2Length; + struct TXBF_PFMU_STA_INFO rTxBfPfmuInfo; + uint8_t ucReserved[3]; +}; + +/* QA tool: maunal assoc */ +struct CMD_MANUAL_ASSOC_STRUCT { + /* + * uint8_t ucBssIndex; + * uint8_t ucWlanIdx; + * uint16_t u2TotalElementNum; + * uint32_t u4Reserve; + */ + /* extension */ + uint16_t u2Tag; /* Tag = 0x05 */ + uint16_t u2Length; + uint8_t aucMac[MAC_ADDR_LEN]; + uint8_t ucType; + uint8_t ucWtbl; + uint8_t ucOwnmac; + uint8_t ucMode; + uint8_t ucBw; + uint8_t ucNss; + uint8_t ucPfmuId; + uint8_t ucMarate; + uint8_t ucSpeIdx; + uint8_t ucaid; +}; + +struct TX_BF_SOUNDING_START { + union { + struct EXT_CMD_ETXBf_SND_PERIODIC_TRIGGER_CTRL + rExtCmdExtBfSndPeriodicTriggerCtrl; + struct EXT_CMD_ETXBf_MU_SND_PERIODIC_TRIGGER_CTRL + rExtCmdExtBfMuSndPeriodicTriggerCtrl; + } rTxBfSounding; +}; + +struct TX_BF_SOUNDING_STOP { + uint8_t ucTxBfCategory; + uint8_t ucSndgStop; + uint8_t ucReserved[2]; +}; + +struct TX_BF_TX_APPLY { + uint8_t ucTxBfCategory; + uint8_t ucWlanId; + uint8_t fgETxBf; + uint8_t fgITxBf; + uint8_t fgMuTxBf; + uint8_t ucReserved[3]; +}; + +struct TX_BF_PFMU_MEM_ALLOC { + uint8_t ucTxBfCategory; + uint8_t ucSuMuMode; + uint8_t ucWlanIdx; + uint8_t ucReserved; +}; + +struct TX_BF_PFMU_MEM_RLS { + uint8_t ucTxBfCategory; + uint8_t ucWlanId; + uint8_t ucReserved[2]; +}; + +#if CFG_SUPPORT_TX_BF_FPGA +struct TX_BF_PROFILE_SW_TAG_WRITE { + uint8_t ucTxBfCategory; + uint8_t ucLm; + uint8_t ucNr; + uint8_t ucNc; + uint8_t ucBw; + uint8_t ucCodebook; + uint8_t ucgroup; + uint8_t ucReserved; +}; +#endif + +union PARAM_CUSTOM_TXBF_ACTION_STRUCT { + struct PROFILE_TAG_READ rProfileTagRead; + struct PROFILE_TAG_WRITE rProfileTagWrite; + struct PROFILE_DATA_READ rProfileDataRead; + struct PROFILE_DATA_WRITE rProfileDataWrite; + struct PROFILE_PN_READ rProfilePnRead; + struct PROFILE_PN_WRITE rProfilePnWrite; + struct TX_BF_SOUNDING_START rTxBfSoundingStart; + struct TX_BF_SOUNDING_STOP rTxBfSoundingStop; + struct TX_BF_TX_APPLY rTxBfTxApply; + struct TX_BF_PFMU_MEM_ALLOC rTxBfPfmuMemAlloc; + struct TX_BF_PFMU_MEM_RLS rTxBfPfmuMemRls; +#if CFG_SUPPORT_TX_BF_FPGA + struct TX_BF_PROFILE_SW_TAG_WRITE rTxBfProfileSwTagWrite; +#endif +}; + +struct PARAM_CUSTOM_STA_REC_UPD_STRUCT { + uint8_t ucBssIndex; + uint8_t ucWlanIdx; + uint16_t u2TotalElementNum; + uint8_t ucAppendCmdTLV; + uint8_t ucMuarIdx; + uint8_t aucReserve[2]; + uint32_t *prStaRec; + struct CMD_STAREC_BF rCmdStaRecBf; +}; + +struct BSSINFO_ARGUMENT { + uint8_t OwnMacIdx; + uint8_t ucBssIndex; + uint8_t Bssid[PARAM_MAC_ADDR_LEN]; + uint8_t ucBcMcWlanIdx; + uint8_t ucPeerWlanIdx; + uint32_t NetworkType; + uint32_t u4ConnectionType; + uint8_t CipherSuit; + uint8_t Active; + uint8_t WmmIdx; + uint32_t u4BssInfoFeature; + uint8_t aucBuffer[0]; +}; + +struct PARAM_CUSTOM_PFMU_TAG_READ_STRUCT { + union PFMU_PROFILE_TAG1 ru4TxBfPFMUTag1; + union PFMU_PROFILE_TAG2 ru4TxBfPFMUTag2; +}; + +#if CFG_SUPPORT_MU_MIMO +struct PARAM_CUSTOM_SHOW_GROUP_TBL_ENTRY_STRUCT { + uint32_t u4EventId; + uint8_t index; + uint8_t numUser: 2; + uint8_t BW: 2; + uint8_t NS0: 2; + uint8_t NS1: 2; + /* UINT_8 NS2:1; */ + /* UINT_8 NS3:1; */ + uint8_t PFIDUser0; + uint8_t PFIDUser1; + /* UINT_8 PFIDUser2; */ + /* UINT_8 PFIDUser3; */ + u_int8_t fgIsShortGI; + u_int8_t fgIsUsed; + u_int8_t fgIsDisable; + uint8_t initMcsUser0: 4; + uint8_t initMcsUser1: 4; + /* UINT_8 initMcsUser2:4; */ + /* UINT_8 initMcsUser3:4; */ + uint8_t dMcsUser0: 4; + uint8_t dMcsUser1: 4; + /* UINT_8 dMcsUser2:4; */ + /* UINT_8 dMcsUser3:4; */ +}; + +struct PARAM_CUSTOM_GET_QD_STRUCT { + uint32_t u4EventId; + uint32_t au4RawData[14]; +}; + +struct MU_STRUCT_LQ_REPORT { + int lq_report[NUM_OF_USER][NUM_OF_MODUL]; +}; + +struct PARAM_CUSTOM_GET_MU_CALC_LQ_STRUCT { + uint32_t u4EventId; + struct MU_STRUCT_LQ_REPORT rEntry; +}; + +struct MU_GET_CALC_INIT_MCS { + uint8_t ucgroupIdx; + uint8_t ucRsv[3]; +}; + +struct MU_SET_INIT_MCS { + uint8_t ucNumOfUser; /* zero-base: 0~3: means 1~2 users */ + uint8_t ucBandwidth; /* zero-base: 0:20 hz 1:40 hz 2: 80 hz 3: 160 */ + uint8_t ucNssOfUser0; /* zero-base: 0~1 means uesr0 use 1~2 ss, + * if no use keep 0 + */ + uint8_t ucNssOfUser1; /* zero-base: 0~1 means uesr0 use 1~2 ss, + * if no use keep 0 + */ + uint8_t ucPfMuIdOfUser0;/* zero-base: for now, uesr0 use pf mu id 0 */ + uint8_t ucPfMuIdOfUser1;/* zero-base: for now, uesr1 use pf mu id 1 */ + uint8_t ucNumOfTxer; /* 0~3: mean use 1~4 anntain, for now, + * should fix 3 + */ + uint8_t ucSpeIndex; /* add new field to fill"special extension + * index" which replace reserve + */ + uint32_t u4GroupIndex; /* 0~ :the index of group table entry for + * calculation + */ +}; + +struct MU_SET_CALC_LQ { + uint8_t ucNumOfUser; /* zero-base: 0~3: means 1~2 users */ + uint8_t ucBandwidth; /* zero-base: 0:20 hz 1:40 hz 2: 80 hz 3: 160 */ + uint8_t ucNssOfUser0; /* zero-base: 0~1 means uesr0 use 1~2 ss, + * if no use keep 0 + */ + uint8_t ucNssOfUser1; /* zero-base: 0~1 means uesr0 use 1~2 ss, + * if no use keep 0 + */ + uint8_t ucPfMuIdOfUser0;/* zero-base: for now, uesr0 use pf mu id 0 */ + uint8_t ucPfMuIdOfUser1;/* zero-base: for now, uesr1 use pf mu id 1 */ + uint8_t ucNumOfTxer; /* 0~3: mean use 1~4 anntain, for now, + * should fix 3 + */ + uint8_t ucSpeIndex; /* add new field to fill"special extension + * index" which replace reserve + */ + uint32_t u4GroupIndex; /* 0~ : the index of group table entry for + * calculation + */ +}; + +struct MU_GET_LQ { + uint8_t ucType; + uint8_t ucRsv[3]; +}; + +struct MU_SET_SNR_OFFSET { + uint8_t ucVal; + uint8_t ucRsv[3]; +}; + +struct MU_SET_ZERO_NSS { + uint8_t ucVal; + uint8_t ucRsv[3]; +}; + +struct MU_SPEED_UP_LQ { + uint32_t u4Val; +}; + +struct MU_SET_MU_TABLE { + /* UINT_16 u2Type; */ + /* UINT_32 u4Length; */ + uint8_t aucMetricTable[NUM_MUT_NR_NUM * NUM_MUT_FEC * + NUM_MUT_MCS * NUM_MUT_INDEX]; +}; + +struct MU_SET_GROUP { + uint32_t u4GroupIndex; /* Group Table Idx */ + uint32_t u4NumOfUser; + uint32_t u4User0Ldpc; + uint32_t u4User1Ldpc; + uint32_t u4ShortGI; + uint32_t u4Bw; + uint32_t u4User0Nss; + uint32_t u4User1Nss; + uint32_t u4GroupId; + uint32_t u4User0UP; + uint32_t u4User1UP; + uint32_t u4User0MuPfId; + uint32_t u4User1MuPfId; + uint32_t u4User0InitMCS; + uint32_t u4User1InitMCS; + uint8_t aucUser0MacAddr[PARAM_MAC_ADDR_LEN]; + uint8_t aucUser1MacAddr[PARAM_MAC_ADDR_LEN]; +}; + +struct MU_GET_QD { + uint8_t ucSubcarrierIndex; + /* UINT_32 u4Length; */ + /* UINT_8 *prQd; */ +}; + +struct MU_SET_ENABLE { + uint8_t ucVal; + uint8_t ucRsv[3]; +}; + +struct MU_SET_GID_UP { + uint32_t au4Gid[2]; + uint32_t au4Up[4]; +}; + +struct MU_TRIGGER_MU_TX { + uint8_t fgIsRandomPattern; /* is random pattern or not */ + uint32_t u4MsduPayloadLength0; /* payload length of the MSDU for + * user 0 + */ + uint32_t u4MsduPayloadLength1; /* payload length of the MSDU for + * user 1 + */ + uint32_t u4MuPacketCount; /* MU TX count */ + uint32_t u4NumOfSTAs; /* number of user in the MU TX */ + uint8_t aucMacAddrs[2][6]; /* MAC address of users*/ +}; + +struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT { + uint8_t ucMuMimoCategory; + uint8_t aucRsv[3]; + union { + struct MU_GET_CALC_INIT_MCS rMuGetCalcInitMcs; + struct MU_SET_INIT_MCS rMuSetInitMcs; + struct MU_SET_CALC_LQ rMuSetCalcLq; + struct MU_GET_LQ rMuGetLq; + struct MU_SET_SNR_OFFSET rMuSetSnrOffset; + struct MU_SET_ZERO_NSS rMuSetZeroNss; + struct MU_SPEED_UP_LQ rMuSpeedUpLq; + struct MU_SET_MU_TABLE rMuSetMuTable; + struct MU_SET_GROUP rMuSetGroup; + struct MU_GET_QD rMuGetQd; + struct MU_SET_ENABLE rMuSetEnable; + struct MU_SET_GID_UP rMuSetGidUp; + struct MU_TRIGGER_MU_TX rMuTriggerMuTx; + } unMuMimoParam; +}; +#endif /* CFG_SUPPORT_MU_MIMO */ +#endif /* CFG_SUPPORT_TX_BF */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +struct PARAM_CUSTOM_MEM_DUMP_STRUCT { + uint32_t u4Address; + uint32_t u4Length; + uint32_t u4RemainLength; +#if CFG_SUPPORT_QA_TOOL + uint32_t u4IcapContent; +#endif /* CFG_SUPPORT_QA_TOOL */ + uint8_t ucFragNum; +}; + +struct PARAM_CUSTOM_SW_CTRL_STRUCT { + uint32_t u4Id; + uint32_t u4Data; +}; + +struct PARAM_CUSTOM_CHIP_CONFIG_STRUCT { + uint16_t u2Id; + uint8_t ucType; + uint8_t ucRespType; + uint16_t u2MsgSize; + uint8_t aucReserved0[2]; + uint8_t aucCmd[CHIP_CONFIG_RESP_SIZE]; +}; + +struct PARAM_CUSTOM_KEY_CFG_STRUCT { + uint8_t aucKey[WLAN_CFG_KEY_LEN_MAX]; + uint8_t aucValue[WLAN_CFG_VALUE_LEN_MAX]; + uint32_t u4Flag; +}; + +struct EEPROM_RW_INFO { + uint8_t ucEepromIndex; + uint8_t reserved; + uint16_t u2EepromData; +}; +struct NVRAM_RW_INFO { + uint16_t u2NvIndex; + uint16_t u2NvData; +}; + +struct PARAM_CUSTOM_EEPROM_RW_STRUCT { + uint8_t ucMethod; + union { + struct EEPROM_RW_INFO rEeprom; + struct NVRAM_RW_INFO rNvram; + } info; +}; + +struct PARAM_CUSTOM_WMM_PS_TEST_STRUCT { + uint8_t bmfgApsdEnAc; /* b0~3: trigger-en AC0~3. + * b4~7: delivery-en AC0~3 + */ + uint8_t ucIsEnterPsAtOnce; /* enter PS immediately without 5 second + * guard after connected + */ + uint8_t ucIsDisableUcTrigger; /* not to trigger UC on beacon TIM is + * matched (under U-APSD) + */ + uint8_t reserved; + uint8_t ucBssIdx; +}; + +struct PARAM_CUSTOM_NOA_PARAM_STRUCT { + uint32_t u4NoaDurationMs; + uint32_t u4NoaIntervalMs; + uint32_t u4NoaCount; + uint8_t ucBssIdx; +}; + +struct PARAM_CUSTOM_OPPPS_PARAM_STRUCT { + uint32_t u4CTwindowMs; + uint8_t ucBssIdx; +}; + +struct PARAM_CUSTOM_UAPSD_PARAM_STRUCT { + uint8_t ucBssIdx; + uint8_t fgEnAPSD; + uint8_t fgEnAPSD_AcBe; + uint8_t fgEnAPSD_AcBk; + uint8_t fgEnAPSD_AcVo; + uint8_t fgEnAPSD_AcVi; + uint8_t ucMaxSpLen; + uint8_t aucResv[2]; +}; + +struct PARAM_CUSTOM_P2P_SET_STRUCT { + uint32_t u4Enable; + uint32_t u4Mode; +}; + +#define MAX_NUMBER_OF_ACL 20 + +enum ENUM_PARAM_CUSTOM_ACL_POLICY { + PARAM_CUSTOM_ACL_POLICY_DISABLE, + PARAM_CUSTOM_ACL_POLICY_ACCEPT, + PARAM_CUSTOM_ACL_POLICY_DENY, + PARAM_CUSTOM_ACL_POLICY_NUM +}; + +struct PARAM_CUSTOM_ACL_ENTRY { + uint8_t aucAddr[MAC_ADDR_LEN]; + uint16_t u2Rsv; +}; + +struct PARAM_CUSTOM_ACL { + enum ENUM_PARAM_CUSTOM_ACL_POLICY ePolicy; + uint32_t u4Num; + struct PARAM_CUSTOM_ACL_ENTRY rEntry[MAX_NUMBER_OF_ACL]; +}; + +enum ENUM_CFG_SRC_TYPE { + CFG_SRC_TYPE_EEPROM, + CFG_SRC_TYPE_NVRAM, + CFG_SRC_TYPE_UNKNOWN, + CFG_SRC_TYPE_NUM +}; + +enum ENUM_EEPROM_TYPE { + EEPROM_TYPE_NO, + EEPROM_TYPE_PRESENT, + EEPROM_TYPE_NUM +}; + +enum ENUM_ICAP_STATE { + ICAP_STATE_INIT = 0, + ICAP_STATE_START = 1, + ICAP_STATE_QUERY_STATUS = 2, + ICAP_STATE_FW_DUMPING = 3, + ICAP_STATE_FW_DUMP_DONE = 4, + ICAP_STATE_QA_TOOL_CAPTURE = 5, + ICAP_STATE_NUM +}; + + +struct PARAM_QOS_TSINFO { + uint8_t ucTrafficType; /* Traffic Type: 1 for isochronous 0 for + * asynchronous + */ + uint8_t ucTid; /* TSID: must be between 8 ~ 15 */ + uint8_t ucDirection; /* direction */ + uint8_t ucAccessPolicy; /* access policy */ + uint8_t ucAggregation; /* aggregation */ + uint8_t ucApsd; /* APSD */ + uint8_t ucuserPriority; /* user priority */ + uint8_t ucTsInfoAckPolicy; /* TSINFO ACK policy */ + uint8_t ucSchedule; /* Schedule */ +}; + +struct PARAM_QOS_TSPEC { + struct PARAM_QOS_TSINFO rTsInfo; /* TS info field */ + uint16_t u2NominalMSDUSize; /* nominal MSDU size */ + uint16_t u2MaxMSDUsize; /* maximum MSDU size */ + uint32_t u4MinSvcIntv; /* minimum service interval */ + uint32_t u4MaxSvcIntv; /* maximum service interval */ + uint32_t u4InactIntv; /* inactivity interval */ + uint32_t u4SpsIntv; /* suspension interval */ + uint32_t u4SvcStartTime; /* service start time */ + uint32_t u4MinDataRate; /* minimum Data rate */ + uint32_t u4MeanDataRate; /* mean data rate */ + uint32_t u4PeakDataRate; /* peak data rate */ + uint32_t u4MaxBurstSize; /* maximum burst size */ + uint32_t u4DelayBound; /* delay bound */ + uint32_t u4MinPHYRate; /* minimum PHY rate */ + uint16_t u2Sba; /* surplus bandwidth allowance */ + uint16_t u2MediumTime; /* medium time */ + uint8_t ucDialogToken; +}; + +struct PARAM_QOS_ADDTS_REQ_INFO { + struct PARAM_QOS_TSPEC rTspec; +}; + +struct PARAM_VOIP_CONFIG { + uint32_t u4VoipTrafficInterval; /* 0: disable VOIP configuration */ +}; + +/*802.11 Statistics Struct*/ +struct PARAM_802_11_STATISTICS_STRUCT { + uint8_t ucInvalid; + union LARGE_INTEGER rTransmittedFragmentCount; + union LARGE_INTEGER rMulticastTransmittedFrameCount; + union LARGE_INTEGER rFailedCount; + union LARGE_INTEGER rRetryCount; + union LARGE_INTEGER rMultipleRetryCount; + union LARGE_INTEGER rRTSSuccessCount; + union LARGE_INTEGER rRTSFailureCount; + union LARGE_INTEGER rACKFailureCount; + union LARGE_INTEGER rFrameDuplicateCount; + union LARGE_INTEGER rReceivedFragmentCount; + union LARGE_INTEGER rMulticastReceivedFrameCount; + union LARGE_INTEGER rFCSErrorCount; + union LARGE_INTEGER rMdrdyCnt; + union LARGE_INTEGER rChnlIdleCnt; + uint32_t u4HwAwakeDuration; + uint32_t u4RstReason; + uint64_t u8RstTime; + uint32_t u4RoamFailCnt; + uint64_t u8RoamFailTime; + uint8_t u2TxDoneDelayIsARP; + uint32_t u4ArriveDrvTick; + uint32_t u4EnQueTick; + uint32_t u4DeQueTick; + uint32_t u4LeaveDrvTick; + uint32_t u4CurrTick; + uint64_t u8CurrTime; +}; + +/* Linux Network Device Statistics Struct */ +struct PARAM_LINUX_NETDEV_STATISTICS { + uint32_t u4RxPackets; + uint32_t u4TxPackets; + uint32_t u4RxBytes; + uint32_t u4TxBytes; + uint32_t u4RxErrors; + uint32_t u4TxErrors; + uint32_t u4Multicast; +}; + +struct PARAM_MTK_WIFI_TEST_STRUCT { + uint32_t u4FuncIndex; + uint32_t u4FuncData; +}; + +struct _RBIST_IQ_DATA_T { + int32_t u4IQArray[4][2]; /* IQ_Array[WF][IQ] */ +}; + +struct RECAL_DATA_T { + uint32_t u4CalId; + uint32_t u4CalAddr; + uint32_t u4CalValue; +}; + +struct RECAL_INFO_T { + u_int8_t fgDumped; + uint32_t u4Count; + struct RECAL_DATA_T *prCalArray; +}; + +struct ICAP_INFO_T { + enum ENUM_ICAP_STATE eIcapState; + uint32_t u4CapNode; + +#if CFG_SUPPORT_QA_TOOL + /* for MT6632/MT7668 file dump mode */ + uint16_t u2DumpIndex; + uint32_t au4Offset[2][2]; + uint32_t au4IQData[256]; + + /* for MT7663/Connad FW parser mode */ + uint32_t u4IQArrayIndex; + uint32_t u4ICapEventCnt; /* Count of packet getting from FW */ + uint32_t au4ICapDumpIndex[4][2];/* Count of packet sent to QA Tool, + * 4 WF * 2 I/Q + */ + struct _RBIST_IQ_DATA_T *prIQArray; +#endif +}; + +struct RF_TEST_CALIBRATION_T { + uint32_t u4FuncData; + uint8_t ucDbdcIdx; + uint8_t aucReserved[3]; +}; + +struct TX_TONE_PARAM_T { + uint8_t ucAntIndex; + uint8_t ucToneType; + uint8_t ucToneFreq; + uint8_t ucDbdcIdx; + int32_t i4DcOffsetI; + int32_t i4DcOffsetQ; + uint32_t u4Band; +}; + +struct CONTINUOUS_TX_PARAM_T { + uint8_t ucCtrlCh; + uint8_t ucCentralCh; + uint8_t ucBW; + uint8_t ucAntIndex; + uint16_t u2RateCode; + uint8_t ucBand; + uint8_t ucTxfdMode; +}; + +struct TX_TONE_POWER_GAIN_T { + uint8_t ucAntIndex; + uint8_t ucTonePowerGain; + uint8_t ucBand; + uint8_t aucReserved[1]; +}; + +struct EXT_CMD_RDD_ON_OFF_CTRL_T { + uint8_t ucDfsCtrl; + uint8_t ucRddIdx; + uint8_t ucRddRxSel; + uint8_t ucSetVal; + uint8_t aucReserved[4]; +}; + +struct SET_ADC_T { + uint32_t u4ChannelFreq; + uint8_t ucAntIndex; + uint8_t ucBW; + uint8_t ucSX; + uint8_t ucDbdcIdx; + uint8_t ucRunType; + uint8_t ucFType; + uint8_t aucReserved[2]; /* Reserving For future */ +}; + +struct SET_RX_GAIN_T { + uint8_t ucLPFG; + uint8_t ucLNA; + uint8_t ucDbdcIdx; + uint8_t ucAntIndex; +}; + +struct SET_TTG_T { + uint32_t u4ChannelFreq; + uint32_t u4ToneFreq; + uint8_t ucTTGPwrIdx; + uint8_t ucDbdcIdx; + uint8_t ucXtalFreq; + uint8_t aucReserved[1]; +}; + +struct TTG_ON_OFF_T { + uint8_t ucTTGEnable; + uint8_t ucDbdcIdx; + uint8_t ucAntIndex; + uint8_t aucReserved[1]; +}; + +struct RBIST_CAP_START_T { + uint32_t u4Trigger; + uint32_t u4RingCapEn; + uint32_t u4TriggerEvent; + uint32_t u4CaptureNode; + uint32_t u4CaptureLen; /* Unit : IQ Sample */ + uint32_t u4CapStopCycle; /* Unit : IQ Sample */ + uint32_t u4MacTriggerEvent; + uint32_t u4SourceAddressLSB; + uint32_t u4SourceAddressMSB; + uint32_t u4BandIdx; + uint32_t u4BW; + uint32_t u4EnBitWidth;/* 0:32bit, 1:96bit, 2:128bit */ + uint32_t u4Architech;/* 0:on-chip, 1:on-the-fly */ + uint32_t u4PhyIdx; + uint32_t u4EmiStartAddress; + uint32_t u4EmiEndAddress; + uint32_t u4EmiMsbAddress; + uint32_t u4CapSource; + uint32_t u4Reserved[2]; +}; + +struct RBIST_DUMP_IQ_T { + uint32_t u4WfNum; + uint32_t u4IQType; + uint32_t u4IcapCnt; /*IQ Sample Count*/ + uint32_t u4IcapDataLen; + uint8_t *pucIcapData; +}; + + +struct RBIST_DUMP_RAW_DATA_T { + uint32_t u4Address; + uint32_t u4AddrOffset; + uint32_t u4Bank; + uint32_t u4BankSize;/* Uint:Kbytes */ + uint32_t u4Reserved[8]; +}; + +/* FuncIndex */ +enum FUNC_IDX { + RE_CALIBRATION = 0x01, + CALIBRATION_BYPASS = 0x02, + TX_TONE_START = 0x03, + TX_TONE_STOP = 0x04, + CONTINUOUS_TX_START = 0x05, + CONTINUOUS_TX_STOP = 0x06, + RF_AT_EXT_FUNCID_TX_TONE_RF_GAIN = 0x07, + RF_AT_EXT_FUNCID_TX_TONE_DIGITAL_GAIN = 0x08, + CAL_RESULT_DUMP_FLAG = 0x09, + RDD_TEST_MODE = 0x0A, + SET_ICAP_CAPTURE_START = 0x0B, + GET_ICAP_CAPTURE_STATUS = 0x0C, + SET_ADC = 0x0D, + SET_RX_GAIN = 0x0E, + SET_TTG = 0x0F, + TTG_ON_OFF = 0x10, + GET_ICAP_RAW_DATA = 0x11 +}; + +struct PARAM_MTK_WIFI_TEST_STRUCT_EXT_T { + uint32_t u4FuncIndex; + union { + uint32_t u4FuncData; + uint32_t u4CalDump; + struct RF_TEST_CALIBRATION_T rCalParam; + struct TX_TONE_PARAM_T rTxToneParam; + struct CONTINUOUS_TX_PARAM_T rConTxParam; + struct TX_TONE_POWER_GAIN_T rTxToneGainParam; + struct RBIST_CAP_START_T rICapInfo; + struct RBIST_DUMP_RAW_DATA_T rICapDump; + struct EXT_CMD_RDD_ON_OFF_CTRL_T rRDDParam; + struct SET_ADC_T rSetADC; + struct SET_RX_GAIN_T rSetRxGain; + struct SET_TTG_T rSetTTG; + struct TTG_ON_OFF_T rTTGOnOff; + } Data; +}; + +/* 802.11 Media stream constraints */ +enum ENUM_MEDIA_STREAM_MODE { + ENUM_MEDIA_STREAM_OFF, + ENUM_MEDIA_STREAM_ON +}; + +/* for NDIS 5.1 Media Streaming Change */ +struct PARAM_MEDIA_STREAMING_INDICATION { + struct PARAM_STATUS_INDICATION rStatus; + enum ENUM_MEDIA_STREAM_MODE eMediaStreamMode; +}; + +#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 */ +struct PARAM_NETWORK_ADDRESS_IP { + uint16_t sin_port; + uint32_t in_addr; + uint8_t sin_zero[8]; +}; + +struct PARAM_NETWORK_ADDRESS { + uint16_t u2AddressLength;/* length in bytes of Address[] in this */ + uint16_t u2AddressType; /* type of this address + * (PARAM_PROTOCOL_ID_XXX above) + */ + uint8_t aucAddress[1]; /* actually AddressLength bytes long */ +}; + +/* The following is used with OID_GEN_NETWORK_LAYER_ADDRESSES to set network + * layer addresses on an interface + */ + +struct PARAM_NETWORK_ADDRESS_LIST { + uint8_t ucBssIdx; + uint32_t u4AddressCount;/* number of addresses following */ + uint16_t u2AddressType; /* type of this address + * (NDIS_PROTOCOL_ID_XXX above) + */ + struct PARAM_NETWORK_ADDRESS + arAddress[1]; /* actually AddressCount elements long */ +}; + +#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. */ + +enum ENUM_MTK_LP_TEST_MODE { + ENUM_MTK_LP_TEST_NORMAL, + ENUM_MTK_LP_TEST_GOLDEN_SAMPLE, + ENUM_MTK_LP_TEST_DUT, + ENUM_MTK_LP_TEST_MODE_NUM +}; + +enum ENUM_MTK_SLT_FUNC_IDX { + 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 +}; + +struct PARAM_MTK_SLT_LP_TEST_STRUCT { + enum ENUM_MTK_LP_TEST_MODE rLpTestMode; + uint32_t u4BcnRcvNum; +}; + +struct PARAM_MTK_SLT_TR_TEST_STRUCT { + enum ENUM_PARAM_NETWORK_TYPE + rNetworkType; /* Network Type OFDM5G or OFDM2.4G */ + uint32_t u4FixedRate; /* Fixed Rate including BW */ +}; + +struct PARAM_MTK_SLT_INITIAL_STRUCT { + uint8_t aucTargetMacAddr[PARAM_MAC_ADDR_LEN]; + uint16_t u2SiteID; +}; + +struct PARAM_MTK_SLT_TEST_STRUCT { + enum ENUM_MTK_SLT_FUNC_IDX rSltFuncIdx; + uint32_t u4Length; /* Length of structure, */ + /* including myself */ + uint32_t u4FuncInfoLen; /* Include following content */ + /* field and myself */ + union { + struct PARAM_MTK_SLT_INITIAL_STRUCT rMtkInitTest; + struct PARAM_MTK_SLT_LP_TEST_STRUCT rMtkLpTest; + struct PARAM_MTK_SLT_TR_TEST_STRUCT rMtkTRTest; + } unFuncInfoContent; + +}; + +#endif + +#if CFG_SUPPORT_MSP +/* Should by chip */ +struct PARAM_SEC_CONFIG { + u_int8_t fgWPIFlag; + u_int8_t fgRV; + u_int8_t fgIKV; + u_int8_t fgRKV; + + u_int8_t fgRCID; + u_int8_t fgRCA1; + u_int8_t fgRCA2; + u_int8_t fgEvenPN; + + uint8_t ucKeyID; + uint8_t ucMUARIdx; + uint8_t ucCipherSuit; + uint8_t aucReserved[1]; +}; + +struct PARAM_TX_CONFIG { + uint8_t aucPA[6]; + u_int8_t fgSW; + u_int8_t fgDisRxHdrTran; + + u_int8_t fgAADOM; + uint8_t ucPFMUIdx; + uint16_t u2PartialAID; + + u_int8_t fgTIBF; + u_int8_t fgTEBF; + u_int8_t fgIsHT; + u_int8_t fgIsVHT; + + u_int8_t fgMesh; + u_int8_t fgBAFEn; + u_int8_t fgCFAck; + u_int8_t fgRdgBA; + + u_int8_t fgRDG; + u_int8_t fgIsPwrMgt; + u_int8_t fgRTS; + u_int8_t fgSMPS; + + u_int8_t fgTxopPS; + u_int8_t fgDonotUpdateIPSM; + u_int8_t fgSkipTx; + u_int8_t fgLDPC; + + u_int8_t fgIsQoS; + u_int8_t fgIsFromDS; + u_int8_t fgIsToDS; + u_int8_t fgDynBw; + + u_int8_t fgIsAMSDUCrossLG; + u_int8_t fgCheckPER; + u_int8_t fgIsGID63; + u_int8_t fgIsHE; + + u_int8_t fgVhtTIBF; + u_int8_t fgVhtTEBF; + u_int8_t fgVhtLDPC; + u_int8_t fgHeLDPC; +}; + +struct PARAM_KEY_CONFIG { + uint8_t aucKey[32]; +}; + +struct PARAM_PEER_RATE_INFO { + uint8_t ucCounterMPDUFail; + uint8_t ucCounterMPDUTx; + uint8_t ucRateIdx; + uint8_t ucReserved[1]; + + uint16_t au2RateCode[AUTO_RATE_NUM]; +}; + +struct PARAM_PEER_BA_CONFIG { + uint8_t ucBaEn; + uint8_t ucRsv[3]; + uint32_t u4BaWinSize; +}; + +struct PARAM_ANT_ID_CONFIG { + uint8_t ucANTIDSts0; + uint8_t ucANTIDSts1; + uint8_t ucANTIDSts2; + uint8_t ucANTIDSts3; +}; + +struct PARAM_PEER_CAP { + struct PARAM_ANT_ID_CONFIG rAntIDConfig; + + uint8_t ucTxPowerOffset; + uint8_t ucCounterBWSelector; + uint8_t ucChangeBWAfterRateN; + uint8_t ucFrequencyCapability; + uint8_t ucSpatialExtensionIndex; + + u_int8_t fgG2; + u_int8_t fgG4; + u_int8_t fgG8; + u_int8_t fgG16; + + uint8_t ucMMSS; + uint8_t ucAmpduFactor; + uint8_t ucReserved[1]; +}; + +struct PARAM_PEER_RX_COUNTER_ALL { + uint8_t ucRxRcpi0; + uint8_t ucRxRcpi1; + uint8_t ucRxRcpi2; + uint8_t ucRxRcpi3; + + uint8_t ucRxCC0; + uint8_t ucRxCC1; + uint8_t ucRxCC2; + uint8_t ucRxCC3; + + u_int8_t fgRxCCSel; + uint8_t ucCeRmsd; + uint8_t aucReserved[2]; +}; + +struct PARAM_PEER_TX_COUNTER_ALL { + uint16_t u2Rate1TxCnt; + uint16_t u2Rate1FailCnt; + uint16_t u2Rate2OkCnt; + uint16_t u2Rate3OkCnt; + uint16_t u2CurBwTxCnt; + uint16_t u2CurBwFailCnt; + uint16_t u2OtherBwTxCnt; + uint16_t u2OtherBwFailCnt; +}; + +struct PARAM_HW_WLAN_INFO { + uint32_t u4Index; + struct PARAM_TX_CONFIG rWtblTxConfig; + struct PARAM_SEC_CONFIG rWtblSecConfig; + struct PARAM_KEY_CONFIG rWtblKeyConfig; + struct PARAM_PEER_RATE_INFO rWtblRateInfo; + struct PARAM_PEER_BA_CONFIG rWtblBaConfig; + struct PARAM_PEER_CAP rWtblPeerCap; + struct PARAM_PEER_RX_COUNTER_ALL rWtblRxCounter; + struct PARAM_PEER_TX_COUNTER_ALL rWtblTxCounter; +}; + +struct HW_TX_AMPDU_METRICS { + uint32_t u4TxSfCnt; + uint32_t u4TxAckSfCnt; + uint32_t u2TxAmpduCnt; + uint32_t u2TxRspBaCnt; + uint16_t u2TxEarlyStopCnt; + uint16_t u2TxRange1AmpduCnt; + uint16_t u2TxRange2AmpduCnt; + uint16_t u2TxRange3AmpduCnt; + uint16_t u2TxRange4AmpduCnt; + uint16_t u2TxRange5AmpduCnt; + uint16_t u2TxRange6AmpduCnt; + uint16_t u2TxRange7AmpduCnt; + uint16_t u2TxRange8AmpduCnt; + uint16_t u2TxRange9AmpduCnt; +#if (CFG_SUPPORT_802_11AX == 1) + uint16_t u2TxRange10AmpduCnt; + uint16_t u2TxRange11AmpduCnt; + uint16_t u2TxRange12AmpduCnt; + uint16_t u2TxRange13AmpduCnt; + uint16_t u2TxRange14AmpduCnt; + uint16_t u2TxRange15AmpduCnt; + uint16_t u2TxRange16AmpduCnt; +#endif +}; + +struct HW_MIB_COUNTER { + uint32_t u4RxFcsErrCnt; + uint32_t u4RxFifoFullCnt; + uint32_t u4RxMpduCnt; + uint32_t u4RxAMPDUCnt; + uint32_t u4RxTotalByte; + uint32_t u4RxValidAMPDUSF; + uint32_t u4RxValidByte; + uint32_t u4ChannelIdleCnt; + uint32_t u4RxVectorDropCnt; + uint32_t u4DelimiterFailedCnt; + uint32_t u4RxVectorMismatchCnt; + uint32_t u4MdrdyCnt; + uint32_t u4CCKMdrdyCnt; + uint32_t u4OFDMLGMixMdrdy; + uint32_t u4OFDMGreenMdrdy; + uint32_t u4PFDropCnt; + uint32_t u4RxLenMismatchCnt; + uint32_t u4PCcaTime; + uint32_t u4SCcaTime; + uint32_t u4CcaNavTx; + uint32_t u4PEDTime; + uint32_t u4BeaconTxCnt; + uint32_t au4BaMissedCnt[BSSID_NUM]; + uint32_t au4RtsTxCnt[BSSID_NUM]; + uint32_t au4FrameRetryCnt[BSSID_NUM]; + uint32_t au4FrameRetry2Cnt[BSSID_NUM]; + uint32_t au4RtsRetryCnt[BSSID_NUM]; + uint32_t au4AckFailedCnt[BSSID_NUM]; +}; + +struct HW_MIB2_COUNTER { + uint32_t u4Tx40MHzCnt; + uint32_t u4Tx80MHzCnt; + uint32_t u4Tx160MHzCnt; +}; + +struct PARAM_HW_MIB_INFO { + uint32_t u4Index; + struct HW_MIB_COUNTER rHwMibCnt; + struct HW_MIB2_COUNTER rHwMib2Cnt; + struct HW_TX_AMPDU_METRICS rHwTxAmpduMts; +}; +#endif + + +/*--------------------------------------------------------------*/ +/*! \brief For Fixed Rate Configuration (Registry) */ +/*--------------------------------------------------------------*/ +enum ENUM_REGISTRY_FIXED_RATE { + 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 ENUM_BT_CMD { + BT_CMD_PROFILE = 0, + BT_CMD_UPDATE, + BT_CMD_NUM +}; + +enum ENUM_BT_PROFILE { + BT_PROFILE_CUSTOM = 0, + BT_PROFILE_SCO, + BT_PROFILE_ACL, + BT_PROFILE_MIXED, + BT_PROFILE_NO_CONNECTION, + BT_PROFILE_NUM +}; + +struct PTA_PROFILE { + enum ENUM_BT_PROFILE eBtProfile; + union { + uint8_t 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. + */ + uint32_t au4Btcr[4]; + } u; +}; + +struct PTA_IPC { + uint8_t ucCmd; + uint8_t ucLen; + union { + struct PTA_PROFILE rProfile; + uint8_t aucBTPParams[BT_PROFILE_PARAM_LEN]; + } u; +}; + +/*--------------------------------------------------------------*/ +/*! \brief CFG80211 Scan Request Container */ +/*--------------------------------------------------------------*/ +struct PARAM_SCAN_REQUEST_EXT { + struct PARAM_SSID rSsid; + uint32_t u4IELength; + uint8_t *pucIE; + uint8_t ucBssIndex; +}; + +struct PARAM_SCAN_REQUEST_ADV { + uint32_t u4SsidNum; + struct PARAM_SSID rSsid[CFG_SCAN_SSID_MAX_NUM]; + uint8_t ucScanType; + uint32_t u4IELength; + uint8_t *pucIE; + uint32_t u4ChannelNum; + struct RF_CHANNEL_INFO + arChannel[MAXIMUM_OPERATION_CHANNEL_LIST]; + uint8_t ucScnFuncMask; + uint8_t aucRandomMac[MAC_ADDR_LEN]; + uint8_t ucBssIndex; + uint32_t u4Flags; +}; + +/*--------------------------------------------------------------*/ +/*! \brief CFG80211 Scheduled Scan Request Container */ +/*--------------------------------------------------------------*/ +#if CFG_SUPPORT_SCHED_SCAN +struct PARAM_SCHED_SCAN_REQUEST { + uint32_t u4SsidNum; /* passed in the probe_reqs */ + struct PARAM_SSID arSsid[CFG_SCAN_HIDDEN_SSID_MAX_NUM]; + uint32_t u4MatchSsidNum; /* matched for a scan request */ + struct PARAM_SSID arMatchSsid[CFG_SCAN_SSID_MATCH_MAX_NUM]; + int32_t ai4RssiThold[CFG_SCAN_SSID_MATCH_MAX_NUM]; + int32_t i4MinRssiThold; + uint8_t ucScnFuncMask; + uint8_t aucRandomMac[MAC_ADDR_LEN]; + uint8_t aucRandomMacMask[MAC_ADDR_LEN]; + uint32_t u4IELength; + uint8_t *pucIE; + uint16_t u2ScanInterval; /* in second */ + uint8_t ucChnlNum; + uint8_t *pucChannels; + uint8_t ucBssIndex; +}; +#endif /* CFG_SUPPORT_SCHED_SCAN */ + +#if CFG_SUPPORT_PASSPOINT +struct PARAM_HS20_SET_BSSID_POOL { + u_int8_t fgIsEnable; + uint8_t ucNumBssidPool; + uint8_t arBSSID[8][PARAM_MAC_ADDR_LEN]; + uint8_t ucBssIndex; +}; + +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_SNIFFER +struct PARAM_CUSTOM_MONITOR_SET_STRUCT { + uint8_t ucEnable; + uint8_t ucBand; + uint8_t ucPriChannel; + uint8_t ucSco; + uint8_t ucChannelWidth; + uint8_t ucChannelS1; + uint8_t ucChannelS2; + uint8_t aucResv[9]; +}; +#endif + +/*--------------------------------------------------------------*/ +/*! \brief MTK Auto Channel Selection related Container */ +/*--------------------------------------------------------------*/ +enum ENUM_SAFE_CH_MASK { + ENUM_SAFE_CH_MASK_BAND_2G4 = 0, + ENUM_SAFE_CH_MASK_BAND_5G_0 = 1, + ENUM_SAFE_CH_MASK_BAND_5G_1 = 2, + ENUM_SAFE_CH_MASK_BAND_5G_2 = 3, + ENUM_SAFE_CH_MASK_MAX_NUM = 4, +}; + +struct LTE_SAFE_CHN_INFO { + /* ENUM_SAFE_CH_MASK_MAX_NUM */ + uint32_t au4SafeChannelBitmask[ENUM_SAFE_CH_MASK_MAX_NUM]; +}; + +struct PARAM_CHN_LOAD_INFO { + /* Per-CHN Load */ + uint8_t ucChannel; + uint16_t u2APNum; + uint32_t u4Dirtiness; + uint8_t ucReserved; +}; + +struct PARAM_CHN_RANK_INFO { + uint8_t ucChannel; + uint32_t u4Dirtiness; + uint8_t ucReserved; +}; + +struct PARAM_GET_CHN_INFO { + uint8_t ucRoleIndex; + struct LTE_SAFE_CHN_INFO rLteSafeChnList; + struct PARAM_CHN_LOAD_INFO rEachChnLoad[MAX_CHN_NUM]; + struct PARAM_CHN_RANK_INFO rChnRankList[MAX_CHN_NUM]; + uint8_t aucReserved[3]; +}; + +struct PARAM_PREFER_CHN_INFO { + uint8_t ucChannel; + uint8_t aucReserved[3]; + uint32_t u4Dirtiness; +}; + +struct UMAC_STAT2_GET { + uint16_t u2PleRevPgHif0Group0; + uint16_t u2PleRevPgCpuGroup2; + + uint16_t u2PseRevPgHif0Group0; + uint16_t u2PseRevPgHif1Group1; + uint16_t u2PseRevPgCpuGroup2; + uint16_t u2PseRevPgLmac0Group3; + uint16_t u2PseRevPgLmac1Group4; + uint16_t u2PseRevPgLmac2Group5; + uint16_t u2PseRevPgPleGroup6; + + uint16_t u2PleSrvPgHif0Group0; + uint16_t u2PleSrvPgCpuGroup2; + + uint16_t u2PseSrvPgHif0Group0; + uint16_t u2PseSrvPgHif1Group1; + uint16_t u2PseSrvPgCpuGroup2; + uint16_t u2PseSrvPgLmac0Group3; + uint16_t u2PseSrvPgLmac1Group4; + uint16_t u2PseSrvPgLmac2Group5; + uint16_t u2PseSrvPgPleGroup6; + + uint16_t u2PleTotalPageNum; + uint16_t u2PleFreePageNum; + uint16_t u2PleFfaNum; + + uint16_t u2PseTotalPageNum; + uint16_t u2PseFreePageNum; + uint16_t u2PseFfaNum; +}; + +struct CNM_STATUS { + uint8_t fgDbDcModeEn; + uint8_t ucChNumB0; + uint8_t ucChNumB1; + uint8_t usReserved; +}; + +struct CNM_CH_LIST { + uint8_t ucChNum[4]; +}; + +struct EXT_CMD_SER_T { + uint8_t ucAction; + uint8_t ucSerSet; + uint8_t ucDbdcIdx; + uint8_t aucReserve[1]; +}; + +#if (CFG_SUPPORT_TXPOWER_INFO == 1) +struct HAL_FRAME_POWER_SET_T { + int8_t icFramePowerDbm; +}; + +struct FRAME_POWER_CONFIG_INFO_T { + struct HAL_FRAME_POWER_SET_T + aicFramePowerConfig[TXPOWER_RATE_NUM][ENUM_BAND_NUM]; +}; + +struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T { + uint8_t ucTxPowerCategory; + uint8_t ucBandIdx; + uint8_t ucChBand; + uint8_t u1Format;/*0:Legacy,1:HE format*/ + + /* Rate power info */ + struct FRAME_POWER_CONFIG_INFO_T rRatePowerInfo; + + /* tx Power Max/Min Limit info */ + int8_t icPwrMaxBnd; + int8_t icPwrMinBnd; + int8_t ucReserved2; +}; +#endif + + +struct PARAM_TXPOWER_BY_RATE_SET_T { + uint8_t u1PhyMode; + uint8_t u1TxRate; + uint8_t u1BW; + int8_t i1TxPower; +}; + +#if CFG_SUPPORT_OSHARE +/* OSHARE Mode */ +#define MAX_OSHARE_MODE_LENGTH 64 +#define OSHARE_MODE_MAGIC_CODE 0x18 +#define OSHARE_MODE_CMD_V1 0x1 + +struct OSHARE_MODE_T { + uint8_t cmdVersion; /* CMD version = OSHARE_MODE_CMD_V1 */ + uint8_t cmdType; /* 1-set 0-query */ + uint8_t magicCode; /* It's like CRC, OSHARE_MODE_MAGIC_CODE */ + uint8_t cmdBufferLen; /* buffer length <= 64 */ + uint8_t buffer[MAX_OSHARE_MODE_LENGTH]; +}; + +struct OSHARE_MODE_SETTING_V1_T { + uint8_t osharemode; /* 0: disable, 1:Enable */ + uint8_t reserved[7]; +}; +#endif + +struct PARAM_WIFI_LOG_LEVEL_UI { + uint32_t u4Version; + uint32_t u4Module; + uint32_t u4Enable; +}; + +struct PARAM_WIFI_LOG_LEVEL { + uint32_t u4Version; + uint32_t u4Module; + uint32_t u4Level; +}; + +struct PARAM_GET_WIFI_TYPE { + struct net_device *prNetDev; + uint8_t arWifiTypeName[8]; +}; + +enum ENUM_WIFI_LOG_LEVEL_VERSION_T { + ENUM_WIFI_LOG_LEVEL_VERSION_V1 = 1, + ENUM_WIFI_LOG_LEVEL_VERSION_NUM +}; + +enum ENUM_WIFI_LOG_LEVEL_T { + ENUM_WIFI_LOG_LEVEL_DEFAULT = 0, + ENUM_WIFI_LOG_LEVEL_MORE, + ENUM_WIFI_LOG_LEVEL_EXTREME, + ENUM_WIFI_LOG_LEVEL_NUM +}; + +enum ENUM_WIFI_LOG_MODULE_T { + ENUM_WIFI_LOG_MODULE_DRIVER = 0, + ENUM_WIFI_LOG_MODULE_FW, + ENUM_WIFI_LOG_MODULE_NUM, +}; + +enum ENUM_WIFI_LOG_LEVEL_SUPPORT_T { + ENUM_WIFI_LOG_LEVEL_SUPPORT_DISABLE = 0, + ENUM_WIFI_LOG_LEVEL_SUPPORT_ENABLE, + ENUM_WIFI_LOG_LEVEL_SUPPORT_NUM +}; + +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR +struct PARAM_GET_LINK_QUALITY_INFO { + uint8_t ucBssIdx; + struct WIFI_LINK_QUALITY_INFO *prLinkQualityInfo; +}; +#endif /* CFG_SUPPORT_LINK_QUALITY_MONITOR */ + +#if CFG_SUPPORT_MBO +struct PARAM_BSS_DISALLOWED_LIST { + uint32_t u4NumBssDisallowed; + /* MAX_FW_ROAMING_BLACKLIST_SIZE */ + uint8_t aucList[MAC_ADDR_LEN * 16]; +}; +#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 + ******************************************************************************* + */ +/*--------------------------------------------------------------*/ +/* Routines to set parameters or query information. */ +/*--------------------------------------------------------------*/ +/***** Routines in wlan_oid.c *****/ +uint32_t +wlanoidQueryNetworkTypesSupported(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryNetworkTypeInUse(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetNetworkTypeInUse(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryBssid(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetBssidListScan(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetBssidListScanExt(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetBssidListScanAdv(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryBssidList(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetBssid(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetConnect(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetSsid(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQuerySsid(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryInfrastructureMode(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetInfrastructureMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryAuthMode(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetAuthMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#if 0 +uint32_t +wlanoidQueryPrivacyFilter(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetPrivacyFilter(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif + +uint32_t +wlanoidSetEncryptionStatus(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryEncryptionStatus(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetAddWep(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetRemoveWep(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetAddKey(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetRemoveKey(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetReloadDefaults(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryCapability(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryFrequency(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetFrequency(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryAtimWindow(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetAtimWindow(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetChannel(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidRssiMonitor(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryRssi(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryRssiTrigger(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetRssiTrigger(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryRtsThreshold(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetRtsThreshold(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQuery802dot11PowerSaveProfile(IN struct ADAPTER + *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSet802dot11PowerSaveProfile(IN struct ADAPTER + *prAdapter, + IN void *prSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetPmkid(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidDelPmkid(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidFlushPmkid(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQuerySupportedRates(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryDesiredRates(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetDesiredRates(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryPermanentAddr(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuf, + IN uint32_t u4QueryBufLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryCurrentAddr(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuf, + IN uint32_t u4QueryBufLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryPermanentAddr(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuf, + IN uint32_t u4QueryBufLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryMaxLinkSpeed(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryLinkSpeed(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanQueryLinkSpeed(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen, + IN uint8_t fgIsOid); + +uint32_t +wlanoidQueryLinkSpeedEx(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +#if CFG_SUPPORT_QA_TOOL +#if CFG_SUPPORT_BUFFER_MODE +uint32_t wlanoidSetEfusBufferMode(IN struct ADAPTER + *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanoidConnacSetEfusBufferMode(IN struct ADAPTER + *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +/* #if (CFG_EEPROM_PAGE_ACCESS == 1) */ +uint32_t +wlanoidQueryProcessAccessEfuseRead(IN struct ADAPTER + *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryProcessAccessEfuseWrite(IN struct ADAPTER + *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryEfuseFreeBlock(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryGetTxPower(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +/*#endif*/ + +#endif /* CFG_SUPPORT_BUFFER_MODE */ +uint32_t +wlanoidQueryRxStatistics(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidBssInfoBasic(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidDevInfoActive(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidManualAssoc(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#if CFG_SUPPORT_TX_BF +uint32_t +wlanoidTxBfAction(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanoidMuMimoAction(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanoidStaRecUpdate(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanoidStaRecBFUpdate(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif /* CFG_SUPPORT_TX_BF */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +uint32_t +wlanoidSendCalBackupV2Cmd(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen); + +uint32_t +wlanoidSetCalBackup(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryCalBackupV2(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); +#endif + +#if CFG_SUPPORT_SMART_GEAR +uint32_t +wlandioSetSGStatus(IN struct ADAPTER *prAdapter, + IN uint8_t ucSGEnable, + IN uint8_t ucSGSpcCmd, + IN uint8_t ucNSS); +#endif + +uint32_t +wlanoidQueryMcrRead(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryMemDump(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetMcrWrite(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryDrvMcrRead(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetDrvMcrWrite(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQuerySwCtrlRead(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetSwCtrlWrite(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetChipConfig(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryChipConfig(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetKeyCfg(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryEepromRead(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetEepromWrite(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryRfTestRxStatus(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryRfTestTxStatus(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryOidInterfaceVersion(IN struct ADAPTER + *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryVendorId(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryMulticastList(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetMulticastList(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryRcvError(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryRcvNoBuffer(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryRcvCrcError(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryStatistics(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryBugReport(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +#ifdef LINUX + +uint32_t +wlanoidQueryStatisticsForLinux(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +#endif + +uint32_t +wlanoidQueryMediaStreamMode(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetMediaStreamMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryRcvOk(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryXmitOk(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryXmitError(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryXmitOneCollision(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryXmitMoreCollisions(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryXmitMaxCollisions(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetCurrentPacketFilter(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanoidSetPacketFilter(struct ADAPTER *prAdapter, + void *pvPacketFiltr, + u_int8_t fgIsOid, + void *pvSetBuffer, + uint32_t u4SetBufferLen); + +uint32_t +wlanoidQueryCurrentPacketFilter(IN struct ADAPTER + *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetAcpiDevicePowerState(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryAcpiDevicePowerState(IN struct ADAPTER + *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetDisassociate(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryFragThreshold(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetFragThreshold(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryAdHocMode(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetAdHocMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryBeaconInterval(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetBeaconInterval(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetCurrentAddr(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +uint32_t +wlanoidSetCSUMOffload(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +uint32_t +wlanoidSetNetworkAddress(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryMaxFrameSize(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryMaxTotalSize(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetCurrentLookahead(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +/* RF Test related APIs */ +uint32_t +wlanoidRftestSetTestMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidRftestSetTestIcapMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidRftestSetAbortTestMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidRftestQueryAutoTest(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidRftestSetAutoTest(IN struct ADAPTER *prAdapter, + OUT void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +uint32_t +wlanoidExtRfTestICapStart(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +uint32_t +wlanoidExtRfTestICapStatus(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +void wlanoidRfTestICapRawDataProc(IN struct ADAPTER *prAdapter, + uint32_t u4CapStartAddr, + uint32_t u4TotalBufferSize); + +#if CFG_SUPPORT_WAPI +uint32_t +wlanoidSetWapiMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetWapiAssocInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetWapiKey(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif + +#if CFG_ENABLE_WAKEUP_ON_LAN +uint32_t +wlanoidSetAddWakeupPattern(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetRemoveWakeupPattern(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryEnableWakeup(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *u4QueryInfoLen); + +uint32_t +wlanoidSetEnableWakeup(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif + +uint32_t +wlanoidSetWiFiWmmPsTest(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetTxAmpdu(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetAddbaReject(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNvramRead(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetNvramWrite(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryCfgSrcType(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryEepromType(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetCountryCode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetScanMacOui(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanSendMemDumpCmd(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen); + +#if CFG_SLT_SUPPORT + +uint32_t +wlanoidQuerySLTStatus(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidUpdateSLTMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#endif + +uint32_t +wlanoidQueryWlanInfo(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanQueryWlanInfo(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen, + IN uint8_t fgIsOid); + +uint32_t +wlanoidQueryMibInfo(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanQueryMibInfo(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen, + IN uint8_t fgIsOid); + +uint32_t +wlanoidSetFwLog2Host(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#if 0 +uint32_t +wlanoidSetNoaParam(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetOppPsParam(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetUApsdParam(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif + +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetBT(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryBT(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetTxPower(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#if 0 +uint32_t +wlanoidQueryBtSingleAntenna( + IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetBtSingleAntenna( + IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetPta( + IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryPta( + IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); +#endif + +#if CFG_ENABLE_WIFI_DIRECT +uint32_t +wlanoidSetP2pMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif + +uint32_t +wlanoidSetDefaultKey(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetGtkRekeyData(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#if CFG_SUPPORT_SCHED_SCAN +uint32_t +wlanoidSetStartSchedScan(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetStopSchedScan(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif /* CFG_SUPPORT_SCHED_SCAN */ + +#if CFG_M0VE_BA_TO_DRIVER +uint32_t wlanoidResetBAScoreboard(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen); +#endif + +#if CFG_SUPPORT_BATCH_SCAN +uint32_t +wlanoidSetBatchScanReq(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryBatchScanResult(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); +#endif + +#if CFG_SUPPORT_PASSPOINT +uint32_t +wlanoidSetHS20Info(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetHS20BssidPool(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_SNIFFER +uint32_t wlanoidSetMonitor(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif + +uint32_t +wlanoidNotifyFwSuspend(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryCnm( + IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidPacketKeepAlive(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#if CFG_SUPPORT_DBDC +uint32_t +wlanoidSetDbdcEnable(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif /*#if CFG_SUPPORT_DBDC*/ + +uint32_t +wlanoidQuerySetTxTargetPower(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#if (CFG_SUPPORT_DFS_MASTER == 1) +uint32_t +wlanoidQuerySetRddReport(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQuerySetRadarDetectMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif + +uint32_t +wlanoidLinkDown(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidDisableTdlsPs(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanoidSetSer(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanoidSerExtCmd(IN struct ADAPTER *prAdapter, + uint8_t ucAction, + uint8_t ucSerSet, + uint8_t ucDbdcIdx); + +#if CFG_SUPPORT_NCHO +#define NCHO_CMD_MAX_LENGTH 128 + +uint32_t +wlanoidSetNchoRoamTrigger(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNchoRoamTrigger(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetNchoRoamDelta(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNchoRoamDelta(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetNchoRoamScnPeriod(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNchoRoamScnPeriod(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetNchoRoamScnChnl(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidAddNchoRoamScnChnl(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNchoRoamScnChnl(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetNchoRoamScnCtrl(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNchoRoamScnCtrl(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetNchoScnChnlTime(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNchoScnChnlTime(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetNchoScnHomeTime(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNchoScnHomeTime(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetNchoScnHomeAwayTime(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNchoScnHomeAwayTime(IN struct ADAPTER + *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetNchoScnNprobes(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNchoScnNprobes(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidGetNchoReassocInfo(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSendNchoActionFrameStart(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSendNchoActionFrameEnd(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetNchoWesMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNchoWesMode(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetNchoBand(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNchoBand(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetNchoDfsScnMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNchoDfsScnMode(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetNchoEnable(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNchoEnable(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +#endif /* CFG_SUPPORT_NCHO */ + +uint32_t +wlanoidAddRoamScnChnl(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidAbortScan(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t wlanoidSetDrvSer(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +uint32_t wlanoidSetAmsduNum(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +uint32_t wlanoidSetAmsduSize(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +/* Show Consys debug information*/ +uint32_t +wlanoidShowPdmaInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +uint32_t +wlanoidShowPseInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +uint32_t +wlanoidShowPleInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +uint32_t +wlanoidShowCsrInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +uint32_t +wlanoidShowDmaschInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +/* end Show Consys debug information*/ + +uint32_t +wlanoidSetTxPowerByRateManual(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#if (CFG_SUPPORT_TXPOWER_INFO == 1) +uint32_t +wlanoidQueryTxPowerInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif + +#if CFG_SUPPORT_MBO +uint32_t wlanoidBssDisallowedList(IN struct ADAPTER + *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#endif + +uint32_t wlanoidSetDrvRoamingPolicy(IN struct ADAPTER + *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#if CFG_SUPPORT_OSHARE +uint32_t +wlanoidSetOshareMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif + +uint32_t +wlanoidQueryWifiLogLevelSupport(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryWifiLogLevel(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetWifiLogLevel(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#if CFG_SUPPORT_LOWLATENCY_MODE +uint32_t +wlanoidSetLowLatencyMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + +#if CFG_SUPPORT_ANT_SWAP +uint32_t wlanoidQueryAntennaSwap(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); +#endif + + +#if CFG_SUPPORT_EASY_DEBUG +uint32_t wlanoidSetFwParam(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif /* CFG_SUPPORT_EASY_DEBUG */ + +uint32_t wlanoidUpdateFtIes(IN struct ADAPTER *prAdapter, IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanoidSync11kCapabilities(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanoidSendNeighborRequest(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanoidSendBTMQuery(IN struct ADAPTER *prAdapter, IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanoidPktProcessIT(struct ADAPTER *prAdapter, void *pvBuffer, + uint32_t u4BufferLen, uint32_t *pu4InfoLen); + +uint32_t wlanoidFwEventIT(struct ADAPTER *prAdapter, void *pvBuffer, + uint32_t u4BufferLen, uint32_t *pu4InfoLen); + +uint32_t wlanoidTspecOperation(IN struct ADAPTER *prAdapter, IN void *pvBuffer, + IN uint32_t u4BufferLen, + OUT uint32_t *pu4InfoLen); + +uint32_t wlanoidDumpUapsdSetting(struct ADAPTER *prAdapter, void *pvBuffer, + uint32_t u4BufferLen, uint32_t *pu4InfoLen); + +uint32_t wlanoidGetWifiType(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanoidRfTestICapGetIQData(IN struct ADAPTER *prAdapter, + OUT void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + + +#ifdef CFG_SUPPORT_LINK_QUALITY_MONITOR +uint32_t wlanoidGetLinkQualityInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif /* CFG_SUPPORT_LINK_QUALITY_MONITOR */ + +#if CFG_SUPPORT_DYNAMIC_PWR_LIMIT +/* dynamic tx power control */ +uint32_t wlanoidTxPowerControl(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif + +uint32_t +wlanoidExternalAuthDone(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +uint32_t +wlanoidIndicateBssInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#endif /* _WLAN_OID_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/wlan_p2p.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/wlan_p2p.h new file mode 100644 index 0000000000000..bad8fdd0cd06e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/wlan_p2p.h @@ -0,0 +1,318 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + + +#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 */ +struct PARAM_P2P_SEND_SD_RESPONSE { + uint8_t rReceiverAddr[PARAM_MAC_ADDR_LEN]; + uint8_t fgNeedTxDoneIndication; + uint8_t ucChannelNum; + uint16_t u2PacketLength; + uint8_t aucPacketContent[0]; /*native 802.11 */ +}; + +struct PARAM_P2P_GET_SD_REQUEST { + uint8_t rTransmitterAddr[PARAM_MAC_ADDR_LEN]; + uint16_t u2PacketLength; + uint8_t aucPacketContent[0]; /*native 802.11 */ +}; + +struct PARAM_P2P_GET_SD_REQUEST_EX { + uint8_t rTransmitterAddr[PARAM_MAC_ADDR_LEN]; + uint16_t u2PacketLength; + /* Channel Number Where SD Request is received. */ + uint8_t ucChannelNum; + uint8_t ucSeqNum; /* Get SD Request by sequence number. */ + uint8_t aucPacketContent[0]; /*native 802.11 */ +}; + +struct PARAM_P2P_SEND_SD_REQUEST { + uint8_t rReceiverAddr[PARAM_MAC_ADDR_LEN]; + uint8_t fgNeedTxDoneIndication; + /* Indicate the Service Discovery Supplicant Version. */ + uint8_t ucVersionNum; + uint16_t u2PacketLength; + uint8_t aucPacketContent[0]; /*native 802.11 */ +}; + +/* Service Discovery 1.0. */ +struct PARAM_P2P_GET_SD_RESPONSE { + uint8_t rTransmitterAddr[PARAM_MAC_ADDR_LEN]; + uint16_t u2PacketLength; + uint8_t aucPacketContent[0]; /*native 802.11 */ +}; + +/* Service Discovery 2.0. */ +struct PARAM_P2P_GET_SD_RESPONSE_EX { + uint8_t rTransmitterAddr[PARAM_MAC_ADDR_LEN]; + uint16_t u2PacketLength; + uint8_t ucSeqNum; /* Get SD Response by sequence number. */ + uint8_t aucPacketContent[0]; /*native 802.11 */ +}; + +struct PARAM_P2P_TERMINATE_SD_PHASE { + uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN]; +}; + +/*! \brief Key mapping of BSSID */ +struct P2P_PARAM_KEY { + uint32_t u4Length; /*!< Length of structure */ + uint32_t u4KeyIndex; /*!< KeyID */ + uint32_t u4KeyLength; /*!< Key length in bytes */ + uint8_t arBSSID[PARAM_MAC_ADDR_LEN]; /*!< MAC address */ + uint64_t rKeyRSC; + /* Following add to change the original windows structure */ + uint8_t ucBssIdx; /* for specific P2P BSS interface. */ + uint8_t ucCipher; + uint8_t aucKeyMaterial[32]; /*!< Key content by above setting */ +}; + +/****************************************************************************** + * 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); + */ + +uint32_t +wlanoidSetNetworkAddress(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetP2PMulticastList(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +/*--------------------------------------------------------------*/ +/* Service Discovery Subroutines */ +/*--------------------------------------------------------------*/ +uint32_t +wlanoidSendP2PSDRequest(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSendP2PSDResponse(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidGetP2PSDRequest(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidGetP2PSDResponse(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *puQueryInfoLen); + +uint32_t +wlanoidSetP2PTerminateSDPhase(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +#if CFG_SUPPORT_ANTI_PIRACY +uint32_t +wlanoidSetSecCheckRequest(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +/*WLAN_STATUS + *wlanoidGetSecCheckResponse(IN P_ADAPTER_T prAdapter, + * IN PVOID pvQueryBuffer, + * IN UINT_32 u4QueryBufferLen, + * OUT PUINT_32 pu4QueryInfoLen); + */ +#endif + +uint32_t +wlanoidSetNoaParam(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetOppPsParam(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetUApsdParam(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryP2pPowerSaveProfile(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetP2pPowerSaveProfile(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetP2pSetNetworkAddress(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryP2pVersion(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetP2pSupplicantVersion(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER +uint32_t +wlanoidSetP2pWPSmode(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); +#endif + +#if CFG_SUPPORT_P2P_RSSI_QUERY +uint32_t +wlanoidQueryP2pRssi(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); +#endif + +uint32_t +wlanoidAbortP2pScan(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +/*--------------------------------------------------------------*/ +/* Callbacks for event indication */ +/*--------------------------------------------------------------*/ + +#endif +#endif /* _WLAN_P2P_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/wsys_cmd_handler_fw.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/wsys_cmd_handler_fw.h new file mode 100644 index 0000000000000..5d878c730bde5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/wsys_cmd_handler_fw.h @@ -0,0 +1,2033 @@ + +/*! \file wsys_cmd_handler.h +*/ + +/***************************************************************************** +* Copyright (c) 2017 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 _WSYS_CMD_HANDLER_FW_H +#define _WSYS_CMD_HANDLER_FW_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 "mac.h" + +/***************************************************************************** +* C O N S T A N T S +****************************************************************************** +*/ +#define EVENT_PACKET_TYPE (0xE000) + +#define PARAM_MAX_LEN_RATES_EX 16 + + +#define BKSCAN_CHANNEL_NUM_MAX 64 + +#define DISCONNECT_REASON_CODE_RESERVED 0 +#define DISCONNECT_REASON_CODE_RADIO_LOST 1 +#define DISCONNECT_REASON_CODE_DEAUTHENTICATED 2 +#define DISCONNECT_REASON_CODE_DISASSOCIATED 3 +#define DISCONNECT_REASON_CODE_NEW_CONNECTION 4 + + +/* Define bandwidth, band, channel and SCO configurations from host command, + * whose CMD ID is 0x13. + */ +#define CONFIG_BW_20_40M 0 +#define CONFIG_BW_20M 1 /* 20MHz only */ +#define CONFIG_BW_20_40_80M 2 +#define CONFIG_BW_20_40_80_160M 3 +#define CONFIG_BW_20_40_80_8080M 4 + +/* Band definition in CMD EVENT */ +#define CMD_BAND_NULL 0 +#define CMD_BAND_2G4 1 +#define CMD_BAND_5G 2 + + +/* Action field in structure CMD_CH_PRIVILEGE_T */ +#define CMD_CH_ACTION_REQ 0 +#define CMD_CH_ACTION_ABORT 1 + +/* Status field in structure EVENT_CH_PRIVILEGE_T */ +#define EVENT_CH_STATUS_GRANT 0 +#define EVENT_CH_STATUS_REJECT 1 +#define EVENT_CH_STATUS_RECOVER 2 +#define EVENT_CH_STATUS_REMOVE_REQ 3 + +#define WIFI_RESTART_DOWNLOAD_STATUS_NO_ERROR 0 +#define WIFI_RESTART_DOWNLOAD_STATUS_ERROR 1 + +#define PM_WOWLAN_REQ_START 0x1 +#define PM_WOWLAN_REQ_STOP 0x2 + + +#define PACKETF_CAP_TYPE_ARP BIT(1) +#define PACKETF_CAP_TYPE_MAGIC BIT(2) +#define PACKETF_CAP_TYPE_BITMAP BIT(3) +#define PACKETF_CAP_TYPE_EAPOL BIT(4) +#define PACKETF_CAP_TYPE_TDLS BIT(5) +#define PACKETF_CAP_TYPE_CF BIT(6) +#define PACKETF_CAP_TYPE_HEARTBEAT BIT(7) +#define PACKETF_CAP_TYPE_TCP_SYN BIT(8) +#define PACKETF_CAP_TYPE_UDP_SYN BIT(9) +#define PACKETF_CAP_TYPE_BCAST_SYN BIT(10) +#define PACKETF_CAP_TYPE_MCAST_SYN BIT(11) +#define PACKETF_CAP_TYPE_V6 BIT(12) +#define PACKETF_CAP_TYPE_TDIM BIT(13) + +/*--------------------------------------------------------------------------- + * Config for scan global controls + *--------------------------------------------------------------------------- + */ + +#define PSCAN_MAX_CHANNELS 8 +#define PSCAN_MAX_BUCKETS 8 + +#define PSCAN_MAX_SCAN_CACHE_SIZE 8 +/*GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE*/ +#define PSCAN_MAX_AP_CACHE_PER_SCAN 64 +#define PSCAN_MAX_SCAN_REPORTING_THRETHOLD 8 +#define PSCAN_MAX_BUFFER_THRETHOLD 80 + +#define PSCAN_SCAN_HISTORY_MAX_NUM PSCAN_MAX_AP_CACHE_PER_SCAN +/*Broadcom is 64*/ + +#define PSCAN_SWC_MAX_NUM 8 /*PFN_SWC_MAX_NUM_APS*/ +#define PSCAN_SWC_RSSI_WIN_MAX 8 /*PFN_SWC_RSSI_WINDOW_MAX*/ +#define PSCAN_SWC_LOSTAP_WIN_MAX 8 + +/** + * If there is no bucket base freq setting from pscan->gscan + * we will set this value as default pscan bucket base freq + */ +#define PSCAN_PNO_BUCKET_BASE_FREQ 30000 + +#define PSCAN_HOTLIST_MAX_NUM 8 /*PFN_HOTLIST_MAX_NUM_APS*/ +#define PSCAN_HOTLIST_LOST_AP_WINDOW_DEFAULT 8 +/*GSCAN_LOST_AP_WINDOW_DEFAULT*/ +#define PSCAN_HOTLIST_REPORT_MAX_NUM 8 /**/ + +#define SCAN_DONE_EVENT_MAX_CHANNEL_NUM 64 +#define SCAN_INFO_CHANNEL_NUM_MAX 64 + +/* PF TCP/UDP max port number */ +#define MAX_TCP_UDP_PORT 20 + +#define HE_OP_BYTE_NUM 3 +#define HE_MAC_CAP_BYTE_NUM 6 +#define HE_PHY_CAP_BYTE_NUM 11 + +/***************************************************************************** +* D A T A T Y P E S +****************************************************************************** +*/ + +/* Define CMD ID from Host to firmware (v0.07) */ +enum ENUM_CMD_ID { + CMD_ID_DUMMY_RSV = 0x00, /* 0x00 (Set) */ + CMD_ID_TEST_CTRL = 0x01, /* 0x01 (Set) */ + CMD_ID_BASIC_CONFIG, /* 0x02 (Set) */ + CMD_ID_SCAN_REQ_V2, /* 0x03 (Set) */ + CMD_ID_NIC_POWER_CTRL, /* 0x04 (Set) */ + CMD_ID_POWER_SAVE_MODE, /* 0x05 (Set) */ + CMD_ID_LINK_ATTRIB, /* 0x06 (Set) */ + CMD_ID_ADD_REMOVE_KEY, /* 0x07 (Set) */ + CMD_ID_DEFAULT_KEY_ID, /* 0x08 (Set) */ + CMD_ID_INFRASTRUCTURE, /* 0x09 (Set) */ + CMD_ID_SET_RX_FILTER, /* 0x0a (Set) */ + CMD_ID_DOWNLOAD_BUF, /* 0x0b (Set) */ + CMD_ID_WIFI_START, /* 0x0c (Set) */ + CMD_ID_CMD_BT_OVER_WIFI, /* 0x0d (Set) */ + CMD_ID_SET_MEDIA_CHANGE_DELAY_TIME, /* 0x0e (Set) */ + CMD_ID_SET_DOMAIN_INFO, /* 0x0f (Set) */ + CMD_ID_SET_IP_ADDRESS, /* 0x10 (Set) */ + CMD_ID_BSS_ACTIVATE_CTRL, /* 0x11 (Set) */ + CMD_ID_SET_BSS_INFO, /* 0x12 (Set) */ + CMD_ID_UPDATE_STA_RECORD, /* 0x13 (Set) */ + CMD_ID_REMOVE_STA_RECORD, /* 0x14 (Set) */ + CMD_ID_INDICATE_PM_BSS_CREATED, /* 0x15 (Set) */ + CMD_ID_INDICATE_PM_BSS_CONNECTED, /* 0x16 (Set) */ + CMD_ID_INDICATE_PM_BSS_ABORT, /* 0x17 (Set) */ + CMD_ID_UPDATE_BEACON_CONTENT, /* 0x18 (Set) */ + CMD_ID_SET_BSS_RLM_PARAM, /* 0x19 (Set) */ + CMD_ID_SCAN_REQ, /* 0x1a (Set) */ + CMD_ID_SCAN_CANCEL, /* 0x1b (Set) */ + CMD_ID_CH_PRIVILEGE, /* 0x1c (Set) */ + CMD_ID_UPDATE_WMM_PARMS, /* 0x1d (Set) */ + CMD_ID_SET_WMM_PS_TEST_PARMS, /* 0x1e (Set) */ + CMD_ID_TX_AMPDU, /* 0x1f (Set) */ + CMD_ID_ADDBA_REJECT, /* 0x20 (Set) */ + CMD_ID_SET_PS_PROFILE_ADV, /* 0x21 (Set) */ + CMD_ID_SET_RAW_PATTERN, /* 0x22 (Set) */ + CMD_ID_CONFIG_PATTERN_FUNC, /* 0x23 (Set) */ + CMD_ID_SET_TX_PWR, /* 0x24 (Set) */ + CMD_ID_SET_PWR_PARAM, /* 0x25 (Set) */ + CMD_ID_P2P_ABORT, /* 0x26 (Set) */ + CMD_ID_SET_TX_EXTEND_PWR, /* 0x27 (Set) */ + CMD_ID_SET_DBDC_PARMS, /* 0x28 (Set) */ + CMD_ID_SET_FILTER_COEFFICIENT, /* 0x29 (Set) */ + + /* SLT commands */ + 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 ) */ + + CMD_ID_ROAMING_TRANSIT = 0x30, /* 0x30 (Set) */ + CMD_ID_SET_PHY_PARAM, /* 0x31 (Set) */ + CMD_ID_SET_NOA_PARAM, /* 0x32 (Set) */ + CMD_ID_SET_OPPPS_PARAM, /* 0x33 (Set) */ + CMD_ID_SET_UAPSD_PARAM, /* 0x34 (Set) */ + CMD_ID_SET_SIGMA_STA_SLEEP, /* 0x35 (Set) */ + CMD_ID_SET_EDGE_TXPWR_LIMIT, /* 0x36 (Set) */ + CMD_ID_SET_DEVICE_MODE, /* 0x37 (Set) */ + CMD_ID_SET_TXPWR_CTRL, /* 0x38 (Set) */ + CMD_ID_SET_AUTOPWR_CTRL, /* 0x39 (Set) */ + CMD_ID_SET_WFD_CTRL, /* 0x3a (Set) */ + CMD_ID_SET_NLO_REQ, /* 0x3b (Set), NO USE */ + CMD_ID_SET_NLO_CANCEL, /* 0x3c (Set), NO USE */ + CMD_ID_SET_GTK_REKEY_DATA, /* 0x3d (Set) */ + CMD_ID_ROAMING_CONTROL, /* 0x3e (Set) */ + CMD_ID_RESET_BA_SCOREBOARD = 0x3f, /* 0x3f (Set) */ + CMD_ID_SET_EDGE_TXPWR_LIMIT_5G = 0x40, /* 0x40 (Set) */ + CMD_ID_SET_CHANNEL_PWR_OFFSET, /* 0x41 (Set) */ + CMD_ID_SET_80211AC_TX_PWR, /* 0x42 (Set) */ + CMD_ID_SET_PATH_COMPASATION, /* 0x43 (Set) */ + CMD_ID_SET_RTT_REQ = 0x44, /* 0x44 (Set) */ + CMD_ID_SET_RTT_CALIBR, /* 0x45 (Set) */ + CMD_ID_GET_RTT_RANGE_UPDATE, /* 0x46 (Set) */ + CMD_ID_SET_BATCH_REQ, /* 0x47 (Set), NO USE */ + CMD_ID_SET_NVRAM_SETTINGS, /* 0x48 (Set) */ + CMD_ID_SET_COUNTRY_POWER_LIMIT, /* 0x49 (Set) */ + CMD_ID_SET_WOWLAN = 0x4A, /* 0x4A (Set) */ + CMD_ID_SET_IPV6_ADDRESS, /* 0x4B (Set) */ + + CMD_ID_SET_SLTINFO = 0x50, /* 0x50 (Set) */ + CMD_ID_UART_ACK, /* 0x51 (Set) */ + CMD_ID_UART_NAK, /* 0x52 (Set) */ + CMD_ID_GET_CHIPID, + + CMD_ID_SET_MDDP_FILTER_RULE = 0x54, /* 0x54 (Set) */ + CMD_ID_SET_AM_FILTER = 0x55, /* 0x55 (Set) */ + CMD_ID_SET_AM_HEARTBEAT, /* 0x56 (Set) */ + CMD_ID_SET_AM_TCP, /* 0x57 (Set) */ + CMD_ID_SET_SUSPEND_MODE = 0x58, /* 0x58 (Set) */ + CMD_ID_SET_PF_CAPABILITY = 0x59, /* 0x59 (Set) */ + CMD_ID_SET_RRM_CAPABILITY = 0x5A, /* 0x5A (Set) */ + CMD_ID_SET_AP_CONSTRAINT_PWR_LIMIT = 0x5B, /* 0x5B (Set) */ + CMD_ID_SET_COUNTRY_POWER_LIMIT_PER_RATE = 0x5D, /* 0x5D (Set) */ + CMD_ID_SET_TSM_STATISTICS_REQUEST = 0x5E, + CMD_ID_GET_TSM_STATISTICS = 0x5F, + /* CFG_SUPPORT_GSCN */ + CMD_ID_GET_PSCAN_CAPABILITY = 0x60, /* 0x60 (Set), NO USE */ + CMD_ID_SET_SCAN_SCHED_ENABLE, /* 0x61 (Set) */ + CMD_ID_SET_SCAN_SCHED_REQ, /* 0x62 (Set) */ + CMD_ID_SET_GSCAN_ADD_HOTLIST_BSSID, /* 0x63 (Set), NO USE */ + CMD_ID_SET_GSCAN_ADD_SWC_BSSID, /* 0x64 (Set), NO USE */ + CMD_ID_SET_GSCAN_MAC_ADDR, /* 0x65 (Set), NO USE */ + CMD_ID_GET_GSCAN_RESULT, /* 0x66 (Get), NO USE */ + CMD_ID_SET_PSCAN_MAC_ADDR, /* 0x67 (Get), NO USE */ + CMD_ID_FAST_SCAN_DUMMY2, /* 0x68 (Get), NO USE */ + CMD_ID_FAST_SCAN_DUMMY3, /* 0x69 (Get), NO USE */ + + CMD_ID_UPDATE_AC_PARMS = 0x6A, /* 0x6A (Set) */ + CMD_ID_SET_ROAMING_SKIP = 0x6D, + /* 0x6D (Set) used to setting roaming skip*/ + CMD_ID_SET_DROP_PACKET_CFG = 0x6E, + /* 0x6E (Set/Query) used to setting drop packet */ + + /*CFG_SUPPORT_EASY_DEBUG*/ + CMD_ID_GET_SET_CUSTOMER_CFG = 0x70, /* 0x70 (Set/Query) */ + CMD_ID_SET_ALWAYS_SCAN_PARAM = 0x73,/* 0x73 (Set) */ + CMD_ID_TDLS_PS = 0x75, /* 0x75 (Set) */ + + CMD_ID_GET_CNM = 0x79, + + CMD_ID_FRM_IND_FROM_HOST = 0x7D, /* 0x7D (Set) */ + CMD_ID_PERF_IND = 0x7E, /* 0x7E(Set) */ +#if CFG_SUPPORT_SMART_GEAR + CMD_ID_SG_PARAM = 0x7F, /* 0x7F(Set) */ +#endif + 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_STA_STATISTICS = 0x85, /* 0x85 (Query) */ + CMD_ID_GET_LTE_CHN = 0x87, /* 0x87 (Query) */ + CMD_ID_GET_BUG_REPORT = 0x89, /* 0x89 (Query) */ + CMD_ID_GET_NIC_CAPABILITY_V2 = 0x8A,/* 0x8A (Query) */ +#if CFG_SUPPORT_LOWLATENCY_MODE + CMD_ID_SET_LOW_LATENCY_MODE = 0x8B, /* 0x8B (Set) */ +#endif + CMD_ID_LOG_UI_INFO = 0x8D, /* 0x8D (Set / Query) */ + /* Oshare mode*/ + CMD_ID_SET_OSHARE_MODE = 0x8E, + CMD_ID_RDD_ON_OFF_CTRL = 0x8F, /* 0x8F(Set) */ + CMD_ID_SET_FORCE_RTS = 0x90, + CMD_ID_WFC_KEEP_ALIVE = 0xA0, /* 0xA0 (Set) */ + CMD_ID_RSSI_MONITOR = 0xA1, /* 0xA1 (Set) */ + CMD_ID_CAL_BACKUP_IN_HOST_V2 = 0xAE, /* 0xAE (Set / Query) */ + + CMD_ID_MQM_UPDATE_MU_EDCA_PARMS = 0xB0, /* 0xB0 (Set) */ + CMD_ID_RLM_UPDATE_SR_PARAMS = 0xB1, /* 0xB1 (Set) */ + + CMD_ID_ACCESS_REG = 0xc0, /* 0xc0 (Set / Query) */ + CMD_ID_MAC_MCAST_ADDR, /* 0xc1 (Set / Query) */ + CMD_ID_802_11_PMKID, /* 0xc2 (Set / Query) */ + CMD_ID_ACCESS_EEPROM, /* 0xc3 (Set / Query) */ + CMD_ID_SW_DBG_CTRL, /* 0xc4 (Set / Query) */ + CMD_ID_FW_LOG_2_HOST, /* 0xc5 (Set) */ + CMD_ID_DUMP_MEM, /* 0xc6 (Query) */ + CMD_ID_RESOURCE_CONFIG, /* 0xc7 (Set / Query) */ + CMD_ID_ACCESS_RX_STAT, /* 0xc8 (Query) */ + + CMD_ID_CHIP_CONFIG = 0xCA, /* 0xca (Set / Query) */ + CMD_ID_STATS_LOG = 0xCB, + + CMD_ID_WTBL_INFO = 0xCD, /* 0xcd (Query) */ + CMD_ID_MIB_INFO = 0xCE, /* 0xce (Query) */ + + CMD_ID_SET_TXBF_BACKOFF = 0xD1, + + CMD_ID_SET_RDD_CH = 0xE1, + + CMD_ID_LAYER_0_EXT_MAGIC_NUM = 0xED, + /* magic number for Extending MT6630 original CMD header */ + /*CMD_ID_LAYER_1_MAGIC_NUM = 0xEE, */ + /* magic number for backward compatible with MT76xx CMD */ + CMD_ID_INIT_CMD_WIFI_RESTART = 0xEF, + /* 0xef (reload firmware use) wayne_note 2013.09.26 */ + + CMD_ID_SET_BWCS = 0xF1, + CMD_ID_SET_OSC = 0xF2, + CMD_ID_HIF_CTRL = 0xF6, + /* 0xF6 (Set) USB suspend/resume */ + CMD_ID_GET_BUILD_DATE_CODE = 0xF8, /* 0xf8 (Query) */ + CMD_ID_GET_BSS_INFO = 0xF9, /* 0xF9 (Query) */ + CMD_ID_SET_HOTSPOT_OPTIMIZATION = 0xFA, /* 0xFA (Set) */ + + CMD_ID_SET_TDLS_CH_SW = 0xFB, + + CMD_ID_SET_MONITOR = 0xFC, /* 0xfc (Set) */ + CMD_ID_SET_CCK_1M_PWR = 0xFD, /* 0xFC (Set) */ + CMD_ID_END +}; + +/* Define EVENT ID from firmware to Host (v0.09) */ +enum ENUM_EVENT_ID { + EVENT_ID_NIC_CAPABILITY = 0x01, /* 0x01 (Query) */ + EVENT_ID_LINK_QUALITY, /* 0x02 (Query / Unsolicited) */ + EVENT_ID_STATISTICS, /* 0x03 (Query) */ + EVENT_ID_MIC_ERR_INFO, /* 0x04 (Unsolicited) */ + EVENT_ID_ACCESS_REG, + /* 0x05 (Query - CMD_ID_ACCESS_REG) */ + EVENT_ID_ACCESS_EEPROM, + /* 0x06 (Query - CMD_ID_ACCESS_EEPROM) */ + EVENT_ID_SLEEPY_INFO, /* 0x07 (Unsolicited) */ + EVENT_ID_BT_OVER_WIFI, /* 0x08 (Unsolicited) */ + EVENT_ID_TEST_STATUS, + /* 0x09 (Query - CMD_ID_TEST_CTRL) */ + EVENT_ID_RX_ADDBA, /* 0x0a (Unsolicited) */ + EVENT_ID_RX_DELBA, /* 0x0b (Unsolicited) */ + EVENT_ID_ACTIVATE_STA_REC, /* 0x0c (Response) */ + EVENT_ID_SCAN_DONE, /* 0x0d (Unsoiicited) */ + EVENT_ID_RX_FLUSH, /* 0x0e (Unsolicited) */ + EVENT_ID_TX_DONE, /* 0x0f (Unsolicited) */ + EVENT_ID_CH_PRIVILEGE, /* 0x10 (Unsolicited) */ + EVENT_ID_BSS_ABSENCE_PRESENCE, /* 0x11 (Unsolicited) */ + EVENT_ID_STA_CHANGE_PS_MODE, /* 0x12 (Unsolicited) */ + EVENT_ID_BSS_BEACON_TIMEOUT, /* 0x13 (Unsolicited) */ + EVENT_ID_UPDATE_NOA_PARAMS, /* 0x14 (Unsolicited) */ + EVENT_ID_AP_OBSS_STATUS, /* 0x15 (Unsolicited) */ + EVENT_ID_STA_UPDATE_FREE_QUOTA, /* 0x16 (Unsolicited) */ + EVENT_ID_SW_DBG_CTRL, + /* 0x17 (Query - CMD_ID_SW_DBG_CTRL) */ + EVENT_ID_ROAMING_STATUS, /* 0x18 (Unsolicited) */ + EVENT_ID_STA_AGING_TIMEOUT, /* 0x19 (Unsolicited) */ + EVENT_ID_SEC_CHECK_RSP, + /* 0x1a (Query - CMD_ID_SEC_CHECK) */ + EVENT_ID_SEND_DEAUTH, /* 0x1b (Unsolicited) */ + EVENT_ID_UPDATE_RDD_STATUS, /* 0x1c (Unsolicited) */ + EVENT_ID_UPDATE_BWCS_STATUS, /* 0x1d (Unsolicited) */ + EVENT_ID_UPDATE_BCM_DEBUG, /* 0x1e (Unsolicited) */ + EVENT_ID_RX_ERR, /* 0x1f (Unsolicited) */ + EVENT_ID_DUMP_MEM = 0x20, + /* 0x20 (Query - CMD_ID_DUMP_MEM) */ + EVENT_ID_STA_STATISTICS, /* 0x21 (Query ) */ + EVENT_ID_STA_STATISTICS_UPDATE, /* 0x22 (Unsolicited) */ + EVENT_ID_SCHED_SCAN_DONE, /* 0x23 (Unsoiicited) */ + EVENT_ID_ADD_PKEY_DONE, /* 0x24 (Unsoiicited) */ + EVENT_ID_ICAP_DONE, /* 0x25 (Unsoiicited) */ + EVENT_ID_RESOURCE_CONFIG = 0x26, + /* 0x26 (Query - CMD_ID_RESOURCE_CONFIG) */ + EVENT_ID_DEBUG_MSG = 0x27, /* 0x27 (Unsoiicited) */ + EVENT_ID_RTT_DISCOVER_PEER = 0x28, /* 0x28 (Unsoiicited) */ + EVENT_ID_RTT_UPDATE_RANGE = 0x29, /* 0x29 (Unsoiicited) */ + EVENT_ID_CHECK_REORDER_BUBBLE = 0x2a, /* 0x2a (Unsoiicited) */ + EVENT_ID_BATCH_RESULT = 0x2b, /* 0x2b (Query) */ + EVENT_ID_STA_ABSENCE_TX = 0x2c, /* 0x2c (Unsoiicited) */ + EVENT_ID_RTT_UPDATE_LOCATION = 0x2d, /* 0x2c (Unsoiicited) */ + EVENT_ID_TX_ADDBA = 0x2e, + EVENT_ID_LTE_SAFE_CHN = 0x2f, /* 0x2f (Query ) */ + + + + /* CFG_SUPPORT_GSCN */ + EVENT_ID_GSCAN_CAPABILITY = 0x30, + EVENT_ID_GSCAN_SCAN_COMPLETE = 0x31, + EVENT_ID_GSCAN_FULL_RESULT = 0x32, + EVENT_ID_GSCAN_SIGNIFICANT_CHANGE = 0x33, + EVENT_ID_GSCAN_GEOFENCE_FOUND = 0x34, + EVENT_ID_GSCAN_SCAN_AVAILABLE = 0x35, + EVENT_ID_GSCAN_RESULT = 0x36, + EVENT_ID_GSCAN_HOTLIST_RESULTS_FOUND = 0x37, + EVENT_ID_GSCAN_HOTLIST_RESULTS_LOST = 0x38, + EVENT_ID_FAST_SCAN_DUMMY1 = 0x39, + EVENT_ID_FAST_SCAN_DUMMY2 = 0x3a, + EVENT_ID_FAST_SCAN_DUMMY3 = 0x3b, + + EVENT_ID_UART_ACK = 0x40, /* 0x40 (Unsolicited) */ + EVENT_ID_UART_NAK, /* 0x41 (Unsolicited) */ + EVENT_ID_GET_CHIPID, + /* 0x42 (Query - CMD_ID_GET_CHIPID) */ + EVENT_ID_SLT_STATUS, + /* 0x43 (Query - CMD_ID_SET_SLTINFO) */ + EVENT_ID_CHIP_CONFIG, + /* 0x44 (Query - CMD_ID_CHIP_CONFIG) */ + EVENT_ID_ACCESS_RX_STAT = 0x45, + /* 0x45 (Query - CMD_ID_ACCESS_RX_STAT) */ + + EVENT_ID_RDD_SEND_PULSE = 0x50, + EVENT_ID_PFMU_TAG_READ = 0x51, + EVENT_ID_PFMU_DATA_READ = 0x52, + EVENT_ID_MU_GET_QD = 0x53, + EVENT_ID_MU_GET_LQ = 0x54, + EVENT_ID_AM_FILTER = 0x55, + /* 0x55 (Query - CMD_ID_SET_AM_FILTER) */ + EVENT_ID_AM_HEARTBEAT = 0x56, + /* 0x56 (Query - CMD_ID_SET_AM_HEARTBEAT) */ + EVENT_ID_AM_TCP = 0x57, + /* 0x57 (Query - CMD_ID_SET_AM_TCP) */ + EVENT_ID_HEARTBEAT_INFO = 0x58, /* 0x58 (Unsolicited) */ + EVENT_ID_MDDP_FILTER_RULE = 0x59, + /* 0x59 (Query - CMD_ID_SET_MDDP_FILTER_RULE) */ + EVENT_ID_BA_FW_DROP_SN = 0x5A, /* 0x5A (Unsolicited) */ + EVENT_ID_LOW_LATENCY_INFO = 0x5B, /* 0x5B (Unsolicited) */ + EVENT_ID_RDD_REPORT = 0x60, + EVENT_ID_CSA_DONE = 0x61, + + EVENT_ID_OPMODE_CHANGE = 0x63, +#if CFG_SUPPORT_IDC_CH_SWITCH + EVENT_ID_LTE_IDC_REPORT = 0x64, +#endif + +#if CFG_SUPPORT_SMART_GEAR + EVENT_ID_SG_STATUS = 0x65, +#endif + +#if CFG_SUPPORT_HE_ER + EVENT_ID_BSS_ER_TX_MODE = 0x66, /* 0x66 BSS Extend Rage (ER) mode */ +#endif + + EVENT_ID_GET_CMD_INFO = 0x70, + /* 0x70 (Query - EVENT_ID_GET_CMD_INFO) */ + /*query info from cmd.*/ + EVENT_ID_DBDC_SWITCH_DONE = 0x78, + EVENT_ID_GET_CNM = 0x79, + + EVENT_ID_FRM_IND_FROM_HOST = 0x7D, + + EVENT_ID_TDLS = 0x80, + + EVENT_ID_LOG_UI_INFO = 0x8D, /* 0x8D (Set / Query) */ + EVENT_ID_UPDATE_COEX_PHYRATE = 0x90, /* 0x90 (Unsolicited) */ + + EVENT_ID_RSSI_MONITOR = 0xA1, /* Event ID for Rssi monitoring */ + EVENT_ID_CAL_BACKUP_IN_HOST_V2 = 0xAE, + /* 0xAE (Query - CMD_ID_CAL_BACKUP) */ + EVENT_ID_CAL_ALL_DONE = 0xAF, /* 0xAF (FW Cal All Done Event) */ + + EVENT_ID_WTBL_INFO = 0xCD, /* 0xCD (Query) */ + EVENT_ID_MIB_INFO = 0xCE, /* 0xCE (Query) */ + + EVENT_ID_NIC_CAPABILITY_V2 = 0xEC, + /* 0xEC (Query - CMD_ID_GET_NIC_CAPABILITY_V2) */ + EVENT_ID_LAYER_0_EXT_MAGIC_NUM = 0xED, + /* magic number for Extending MT6630 original EVENT header */ + EVENT_ID_ASSERT_DUMP = 0xF0, + EVENT_ID_HIF_CTRL = 0xF6, + EVENT_ID_BUILD_DATE_CODE = 0xF8, + EVENT_ID_GET_AIS_BSS_INFO = 0xF9, + EVENT_ID_DEBUG_CODE = 0xFB, + EVENT_ID_RFTEST_READY = 0xFC, /* 0xFC */ + + EVENT_ID_INIT_EVENT_CMD_RESULT = 0xFD, + /* 0xFD (Generic event for cmd not found, added by CONNAC) */ + + EVENT_ID_END +}; + +/* commands */ + +/* already define at wifi_task.h!!! */ +/*chiahsuan: ReStart Download Firmware + *Request/Response Start. (duplicated one. + * it is copy from ROM) + */ +struct INIT_WIFI_CMD { + uint8_t ucCID; + uint8_t ucPktTypeID; /* Must be 0xA0 (CMD Packet) */ + uint8_t ucReserved; + uint8_t ucSeqNum; + uint32_t u4Reserved; + /* add one DW to compatible with normal TXD format. */ + uint32_t au4D3toD7Rev[5]; + /* add 5 DW to compatible with normal TXD format. */ + uint8_t aucBuffer[0]; +}; + +struct INIT_WIFI_EVENT { + uint16_t u2RxByteCount; + uint16_t u2PacketType; + /* Must be filled with 0xE000 (EVENT Packet) */ + uint8_t ucEID; + uint8_t ucSeqNum; + uint8_t aucReserved[2]; + + uint8_t aucBuffer[0]; +}; + +struct INIT_HIF_TX_HEADER { + uint16_t u2TxByteCount; + uint16_t u2PQ_ID; /* Must be 0x8000 (Port1, Queue 0) */ + struct INIT_WIFI_CMD rInitWifiCmd; +}; + +struct INIT_HIF_TX_HEADER_PENDING_FOR_HW_32BYTES { + uint16_t u2TxByteCount; + uint16_t u2PQ_ID; /* Must be 0x8000 (Port1, Queue 0) */ + + uint8_t ucWlanIdx; + uint8_t ucHeaderFormat; + uint8_t ucHeaderPadding; + uint8_t ucPktFt: 2; + uint8_t ucOwnMAC: 6; + uint32_t au4D2toD7Rev[6]; +}; + +struct INIT_EVENT_CMD_RESULT { + uint8_t ucStatus; + /* 0: success, 0xFE command not support, others: failure */ + uint8_t ucCID; + uint8_t aucReserved[2]; +}; + +/*---------------------------------------------------------------------------*/ +/* Parameters of User Configuration which match to NDIS5.1 */ +/*---------------------------------------------------------------------------*/ +typedef int32_t PARAM_RSSI; + +/* NDIS_802_11_RATES_EX */ +typedef uint8_t PARAM_RATES_EX[PARAM_MAX_LEN_RATES_EX]; + +/* NDIS_802_11_NETWORK_TYPE */ +enum ENUM_PARAM_PHY_NET_TYPE { + PHY_NET_TYPE_FH, + PHY_NET_TYPE_DS, + PHY_NET_TYPE_OFDM5, + PHY_NET_TYPE_OFDM24, + PHY_NET_TYPE_AUTOMODE, + PHY_NET_TYPE_NUM /*!< Upper bound, not real case */ +}; + +/* NDIS_802_11_AUTHENTICATION_MODE */ +enum ENUM_PARAM_AUTH_MODE { + AUTH_MODE_OPEN = 0, /*!< 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_WPA2_FT, /* 802.11r */ + AUTH_MODE_WPA2_FT_PSK, /* 802.11r */ + AUTH_MODE_WPA_OSEN, + AUTH_MODE_WPA3_SAE, + AUTH_MODE_WPA3_OWE, + AUTH_MODE_NUM /*!< Upper bound, not real case */ +}; + +/* NDIS_802_11_ENCRYPTION_STATUS */ +enum ENUM_WEP_STATUS { + ENUM_WEP_ENABLED, + ENUM_ENCRYPTION1_ENABLED = ENUM_WEP_ENABLED, /* WEP */ + ENUM_WEP_DISABLED, + ENUM_ENCRYPTION_DISABLED = ENUM_WEP_DISABLED, /* OPEN */ + 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, /* TKIP(WPA/WPA2) */ + ENUM_ENCRYPTION2_KEY_ABSENT, + ENUM_ENCRYPTION3_ENABLED, /* CCMP(WPA/WPA2) */ + ENUM_ENCRYPTION3_KEY_ABSENT, + ENUM_ENCRYPTION4_ENABLED, /* GCMP256(WPA2/WPA3) */ + ENUM_ENCRYPTION4_KEY_ABSENT, + ENUM_ENCRYPTION_NUM +}; + +/*---------------------------------------------------------------------------*/ +/* CMD Packets */ +/*---------------------------------------------------------------------------*/ +struct CMD_BUILD_CONNECTION { + uint8_t ucInfraMode; + uint8_t ucAuthMode; + uint8_t ucEncryptStatus; + uint8_t ucSsidLen; + uint8_t aucSsid[32]; + uint8_t aucBssid[6]; + + /* The following parameters are for Ad-hoc network */ + uint16_t u2BeaconPeriod; + uint16_t u2ATIMWindow; + uint8_t ucJoinOnly; + uint8_t ucReserved; + uint32_t u4FreqInKHz; + +}; + +struct CMD_802_11_KEY { + uint8_t ucAddRemove; + uint8_t ucTxKey; /* 1 : Tx key */ + uint8_t ucKeyType; /* 0 : group Key, 1 : Pairwise key */ + uint8_t ucIsAuthenticator; /* 1 : authenticator */ + uint8_t aucPeerAddr[6]; + uint8_t ucBssIdx; /* the BSS index */ + uint8_t ucAlgorithmId; + uint8_t ucKeyId; + uint8_t ucKeyLen; + uint8_t ucWlanIndex; + uint8_t ucMgmtProtection; + uint8_t aucKeyMaterial[32]; + uint8_t aucKeyRsc[16]; +}; + +struct CMD_DEFAULT_KEY_ID { + uint8_t ucBssIdx; + uint8_t ucKeyId; + uint8_t ucUnicast; + uint8_t ucMulticast; +}; + + +/* CMD for PMKID and related structure */ +typedef uint8_t PARAM_PMKID_VALUE[16]; + +struct PARAM_BSSID_INFO { + uint8_t aucBssid[MAC_ADDR_LEN]; /* MAC address */ + PARAM_PMKID_VALUE arPMKID; +}; + +/* This struct only uses uint16_t, + * compiler will use 2-byte alignment. + * sizeof(struct CMD_SET_BSS_RLM_PARAM) is 22 + */ +struct CMD_SET_BSS_RLM_PARAM { + uint8_t ucBssIndex; + uint8_t ucRfBand; + uint8_t ucPrimaryChannel; + uint8_t ucRfSco; + uint8_t ucErpProtectMode; + uint8_t ucHtProtectMode; + uint8_t ucGfOperationMode; + uint8_t ucTxRifsMode; + uint16_t u2HtOpInfo3; + uint16_t u2HtOpInfo2; + uint8_t ucHtOpInfo1; + uint8_t ucUseShortPreamble; + uint8_t ucUseShortSlotTime; + uint8_t ucVhtChannelWidth; + uint8_t ucVhtChannelFrequencyS1; + uint8_t ucVhtChannelFrequencyS2; + uint16_t u2VhtBasicMcsSet; + uint8_t ucTxNss; + uint8_t ucRxNss; +}; + +/*CMD_ID_FRM_IND_FROM_HOST 0x7D*/ + +/*ver 1 structure*/ +struct CMD_FRM_IND_FROM_HOST { + /* DWORD_0 - Common Part*/ + uint8_t ucCmdVer; + uint8_t aucPadding0[1]; + uint16_t u2CmdLen; /* cmd size including common part and body.*/ + + /* DWORD_1 ~ x - Command Body*/ + uint8_t ucStaIdx; + uint8_t ucBssIdx; + /** TX/RX/TXS(future used) ENUM_CMD_FRM_IND_FROM_HOST_TRANSMIT_TYPE */ + uint8_t ucTransmitType; + /** ENUM_CMD_FRM_IND_FROM_HOST_PROTOCOL_TYPE */ + uint8_t ucProtocolType; + /** ENUM_CMD_FRM_IND_FROM_HOST_EAP_MSG_TYPE, + * ENUM_CMD_M_IND_FROM_HOST_DHCP_MSG_TYPE + */ + /** depend on ucProtocolType */ + uint8_t ucProtocolSubType; + uint8_t ucRateValid; + uint8_t aucPadding1[2]; + /** TX Rate, Rx Rate, TxS Rate */ + uint32_t u4Rate; + uint32_t u4Len; + /** Only TXS type value in txS*/ + uint8_t TxS; + uint8_t aucPadding3[3]; + uint8_t aucPadding4[64]; +}; + +enum ENUM_FRM_IND_FROM_HOST_VER { + CMD_FRM_IND_FROM_HOST_VER_INIT = 0x0, + CMD_FRM_IND_FROM_HOST_VER_1ST = 0x1, + CMD_FRM_IND_FROM_HOST_VER_MAX = 0x2, +}; + +enum ENUM_CMD_FRM_IND_FROM_HOST_TRANSMIT_TYPE { + CMD_FRM_IND_FROM_HOST_TRANSMIT_TYPE_TX = 0x00, + CMD_FRM_IND_FROM_HOST_TRANSMIT_TYPE_RX = 0x01, + CMD_FRM_IND_FROM_HOST_TRANSMIT_TYPE_TXS = 0x02, + CMD_FRM_IND_FROM_HOST_TRANSMIT_TYPE_MAX = 0x03, +}; + +enum ENUM_CMD_FRM_IND_FROM_HOST_PROTOCOL_TYPE { + CMD_FRM_IND_FROM_HOST_PROTOCOL_TYPE_NON_SPECIFIC = 0x00, + CMD_FRM_IND_FROM_HOST_PROTOCOL_TYPE_EAP = 0x01, + CMD_FRM_IND_FROM_HOST_PROTOCOL_TYPE_DHCP = 0x02, + CMD_FRM_IND_FROM_HOST_PROTOCOL_TYPE_MAX = 0x03, +}; + +enum ENUM_CMD_FRM_IND_FROM_HOST_EAP_MSG_TYPE { + CMD_FRM_IND_FROM_HOST_EAP_MSG_NON_SPECIFIC = 0x00, + CMD_FRM_IND_FROM_HOST_EAP_MSG_4WAY_1 = 0x01, + CMD_FRM_IND_FROM_HOST_EAP_MSG_4WAY_2 = 0x02, + CMD_FRM_IND_FROM_HOST_EAP_MSG_4WAY_3 = 0x03, + CMD_FRM_IND_FROM_HOST_EAP_MSG_4WAY_4 = 0x04, + CMD_FRM_IND_FROM_HOST_EAP_MSG_GROUP_1 = 0x05, + CMD_FRM_IND_FROM_HOST_EAP_MSG_GROUP_2 = 0x06, + CMD_FRM_IND_FROM_HOST_EAP_MSG_MAX = 0x07, +}; + +enum ENUM_CMD_FRM_IND_FROM_HOST_DHCP_MSG_TYPE { + CMD_FRM_IND_FROM_HOST_DHCP_MSG_NON_SPECIFIC = 0x00, + CMD_FRM_IND_FROM_HOST_DHCP_MSG_DISCOVER = 0x01, + CMD_FRM_IND_FROM_HOST_DHCP_MSG_OFFER = 0x02, + CMD_FRM_IND_FROM_HOST_DHCP_MSG_REQUEST = 0x03, + CMD_FRM_IND_FROM_HOST_DHCP_MSG_ACK = 0x04, + CMD_FRM_IND_FROM_HOST_DHCP_MSG_MAX = 0x05, +}; + +/* This struct uses uint32_t, compiler will use 4-byte alignment. + * sizeof(struct CMD_SET_BSS_INFO) is 116 + */ +struct CMD_SET_BSS_INFO { + uint8_t ucBssIndex; + uint8_t ucConnectionState; + uint8_t ucCurrentOPMode; + uint8_t ucSSIDLen; + uint8_t aucSSID[32]; + uint8_t aucBSSID[6]; + uint8_t ucIsQBSS; + uint8_t ucVersion; + uint16_t u2OperationalRateSet; + uint16_t u2BSSBasicRateSet; + uint8_t ucStaRecIdxOfAP; + uint8_t aucPadding0[1]; + uint16_t u2HwDefaultFixedRateCode; + uint8_t ucNonHTBasicPhyType; /* For Slot Time and CWmin */ + uint8_t ucAuthMode; + uint8_t ucEncStatus; + uint8_t ucPhyTypeSet; + uint8_t ucWapiMode; + uint8_t ucIsApMode; + uint8_t ucBMCWlanIndex; + uint8_t ucHiddenSsidMode; + uint8_t ucDisconnectDetectThreshold; + uint8_t ucIotApAct; + uint8_t aucPadding1[2]; + uint32_t u4PrivateData; + struct CMD_SET_BSS_RLM_PARAM rBssRlmParam; /*68*/ + uint8_t ucDBDCBand; /*90, ENUM_CMD_REQ_DBDC_BAND_T*/ + uint8_t ucWmmSet; + uint8_t ucDBDCAction; + uint8_t ucNss; + uint8_t aucPadding2[2]; + uint8_t ucHeOpParams[HE_OP_BYTE_NUM]; + uint8_t ucBssColorInfo; + uint16_t u2HeBasicMcsSet; + uint8_t ucMaxBSSIDIndicator; + uint8_t ucMBSSIDIndex; + uint8_t aucPadding[12]; +}; + +struct CMD_HTVHT_BA_SIZE { + uint8_t ucTxBaSize; + uint8_t ucRxBaSize; + uint8_t aucReserved[2]; +}; + +struct CMD_HE_BA_SIZE { + uint16_t u2TxBaSize; + uint16_t u2RxBaSize; +}; + +struct CMD_UPDATE_STA_RECORD { + uint8_t ucStaIndex; + uint8_t ucStaType; + uint8_t aucMacAddr[MAC_ADDR_LEN]; + /* This field should assign at create and keep consistency for update + * usage + */ + + uint16_t u2AssocId; + uint16_t u2ListenInterval; + uint8_t ucBssIndex; + /* This field should assign at create and keep consistency for update + * usage + */ + uint8_t ucDesiredPhyTypeSet; + uint16_t u2DesiredNonHTRateSet; + + uint16_t u2BSSBasicRateSet; + uint8_t ucIsQoS; + uint8_t ucIsUapsdSupported; + uint8_t ucStaState; + uint8_t ucMcsSet; + uint8_t ucSupMcs32; + uint8_t ucVersion; + /* Original padding is used for version now */ + + uint8_t aucRxMcsBitmask[10]; + uint16_t u2RxHighestSupportedRate; + uint32_t u4TxRateInfo; + + uint16_t u2HtCapInfo; + uint16_t u2HtExtendedCap; + uint32_t u4TxBeamformingCap; + + uint8_t ucAmpduParam; + uint8_t ucAselCap; + uint8_t ucRCPI; + uint8_t ucNeedResp; + uint8_t ucUapsdAc; + /* b0~3: Trigger enabled, b4~7: Delivery enabled */ + uint8_t ucUapsdSp; + /* 0: all, 1: max 2, 2: max 4, 3: max 6 */ + uint8_t ucWlanIndex; + /* This field should assign at create and keep consistency for update + * usage + */ + uint8_t ucBMCWlanIndex; + /* This field should assign at create and keep consistency for update + * usage + */ + + uint32_t u4VhtCapInfo; + uint16_t u2VhtRxMcsMap; + uint16_t u2VhtRxHighestSupportedDataRate; + uint16_t u2VhtTxMcsMap; + uint16_t u2VhtTxHighestSupportedDataRate; + uint8_t ucRtsPolicy; + /* 0: auto 1: Static BW 2: Dynamic BW 3: Legacy 7: WoRts */ + uint8_t ucVhtOpMode; + /* VHT operting mode, bit 7: Rx NSS Type, bit 4-6: Rx NSS, bit 0-1: + * Channel Width + */ + + uint8_t ucTrafficDataType; + uint8_t ucTxGfMode; /* ENUM_FEATURE_OPTION */ + uint8_t ucTxSgiMode; /* ENUM_FEATURE_OPTION */ + uint8_t ucTxStbcMode; /* ENUM_FEATURE_OPTION unused */ + uint16_t u2HwDefaultFixedRateCode; + uint8_t ucTxAmpdu; + uint8_t ucRxAmpdu; + uint32_t u4FixedPhyRate; + /* 0: desable BIT(31)==1,BITS(0,15) rate code */ + uint16_t u2MaxLinkSpeed; + /* 0: unlimit ohter: unit is 0.5 Mbps */ + uint16_t u2MinLinkSpeed; + + uint32_t u4Flags; + + union BA_SIZE { + struct CMD_HTVHT_BA_SIZE rHtVhtBaSize; + struct CMD_HE_BA_SIZE rHeBaSize; + } rBaSize; + + uint16_t u2PfmuId; /* 0xFFFF means no access right for PFMU*/ + uint8_t fgSU_MU; /* 0 : SU, 1 : MU*/ + uint8_t fgETxBfCap; /* 0 : ITxBf, 1 : ETxBf*/ + uint8_t ucSoundingPhy; + uint8_t ucNdpaRate; + uint8_t ucNdpRate; + uint8_t ucReptPollRate; + uint8_t ucTxMode; + uint8_t ucNc; + uint8_t ucNr; + uint8_t ucCBW; /* 0 : 20M, 1 : 40M, 2 : 80M, 3 : 80 + 80M*/ + uint8_t ucTotMemRequire; + uint8_t ucMemRequire20M; + uint8_t ucMemRow0; + uint8_t ucMemCol0; + uint8_t ucMemRow1; + uint8_t ucMemCol1; + uint8_t ucMemRow2; + uint8_t ucMemCol2; + uint8_t ucMemRow3; + uint8_t ucMemCol3; + uint16_t u2SmartAnt; + uint8_t ucSEIdx; + uint8_t uciBfTimeOut; + uint8_t uciBfDBW; + uint8_t uciBfNcol; + uint8_t uciBfNrow; + uint8_t aucPadding1[3]; + + uint8_t ucTxAmsduInAmpdu; + uint8_t ucRxAmsduInAmpdu; + uint8_t aucPadding2[2]; + uint32_t u4TxMaxAmsduInAmpduLen; + +#if CFG_SUPPORT_802_11AX + /* These fields can only be accessed if ucVersion = 1*/ + uint8_t ucHeMacCapInfo[HE_MAC_CAP_BYTE_NUM]; + uint8_t ucHePhyCapInfo[HE_PHY_CAP_BYTE_NUM]; + uint8_t aucPadding3[2]; + uint16_t u2HeRxMcsMapBW80; + uint16_t u2HeTxMcsMapBW80; + uint16_t u2HeRxMcsMapBW160; + uint16_t u2HeTxMcsMapBW160; + uint16_t u2HeRxMcsMapBW80P80; + uint16_t u2HeTxMcsMapBW80P80; +#endif + uint8_t aucPadding4[32]; +}; + +struct CMD_REMOVE_STA_RECORD { + uint8_t ucActionType; + uint8_t ucStaIndex; + uint8_t ucBssIndex; + uint8_t ucReserved; +}; + +struct CMD_INDICATE_PM_BSS_CREATED { + uint8_t ucBssIndex; + uint8_t ucDtimPeriod; + uint16_t u2BeaconInterval; + uint16_t u2AtimWindow; + uint8_t aucReserved[2]; +}; + +struct CMD_INDICATE_PM_BSS_CONNECTED { + uint8_t ucBssIndex; + uint8_t ucDtimPeriod; + uint16_t u2AssocId; + uint16_t u2BeaconInterval; + uint16_t u2AtimWindow; + uint8_t fgIsUapsdConnection; + uint8_t ucBmpDeliveryAC; + uint8_t ucBmpTriggerAC; + uint8_t aucReserved[1]; +}; + +struct CMD_INDICATE_PM_BSS_ABORT { + uint8_t ucBssIndex; + uint8_t aucReserved[3]; +}; + +struct CMD_SET_WMM_PS_TEST_STRUCT { + uint8_t ucBssIndex; + uint8_t bmfgApsdEnAc; + /* b0~3: trigger-en AC0~3. b4~7: delivery-en AC0~3 */ + uint8_t ucIsEnterPsAtOnce; + /* enter PS immediately without 5 second guard after connected */ + uint8_t ucIsDisableUcTrigger; + /* not to trigger UC on beacon TIM is matched (under U-APSD) */ +}; + +struct CMD_CUSTOM_NOA_PARAM_STRUCT { + uint32_t u4NoaDurationMs; /* unit: msec*/ + uint32_t u4NoaIntervalMs; /* unit: msec*/ + uint32_t u4NoaCount; + uint8_t ucBssIdx; + uint8_t aucReserved[3]; +}; + +struct CMD_CUSTOM_OPPPS_PARAM_STRUCT { + uint32_t u4CTwindowMs; + /* bit0~6 : CTWindow(unit: TU), bit7:OppPS bit (1:enable, 0:disable)*/ + uint8_t ucBssIdx; + uint8_t aucReserved[3]; +}; + +struct CMD_CUSTOM_UAPSD_PARAM_STRUCT { + uint8_t fgEnAPSD; + uint8_t fgEnAPSD_AcBe; + uint8_t fgEnAPSD_AcBk; + uint8_t fgEnAPSD_AcVo; + uint8_t fgEnAPSD_AcVi; + uint8_t ucMaxSpLen; + uint8_t aucResv[2]; +}; + +/* Definition for CHANNEL_INFO.ucBand: + * 0: Reserved + * 1: BAND_2G4 + * 2: BAND_5G + * Others: Reserved + */ +struct CHANNEL_INFO { + uint8_t ucBand; + uint8_t ucChannelNum; +}; + +struct CMD_SCAN_REQ { + uint8_t ucSeqNum; + uint8_t ucBssIndex; + uint8_t ucScanType; + uint8_t ucSSIDType; + uint8_t ucSSIDLength; + uint8_t ucNumProbeReq; + uint16_t u2ChannelMinDwellTime; + uint16_t u2ChannelDwellTime; + uint16_t u2TimeoutValue; + uint8_t aucSSID[32]; + uint8_t ucChannelType; + uint8_t ucChannelListNum; + uint8_t aucReserved[2]; + struct CHANNEL_INFO arChannelList[32]; + uint16_t u2IELen; + uint8_t aucIE[0]; /*depends on u2IELen*/ +}; + +struct PARAM_SSID { + uint32_t u4SsidLen; + /*!< SSID length in bytes. Zero length is broadcast(any) SSID */ + uint8_t aucSsid[ELEM_MAX_LEN_SSID]; +}; + +#define CMD_SCAN_REQ_V2_FUNC_RANDOM_MAC_MASK BIT(0) +#define CMD_SCAN_REQ_V2_FUNC_DIS_DBDC_SCAN_MASK BIT(1) +#define CMD_SCAN_REQ_V2_FUNC_DBDC_SCAN_TYPE_3_MASK BIT(2) +/* use 6*4 = 24 bytes as bssid of being scanned ap */ +#define CMD_SCAN_REQ_V2_FUNC_USE_PADDING_AS_BSSID BIT(3) +#define CMD_SCAN_REQ_V2_FUNC_RANDOM_PROBE_REQ_SN_MASK BIT(4) + +struct CMD_SCAN_REQ_V2 { + uint8_t ucSeqNum; + uint8_t ucBssIndex; + uint8_t ucScanType; + uint8_t ucSSIDType; + uint8_t ucSSIDNum; + uint8_t ucNumProbeReq; + uint8_t ucScnFuncMask; + uint8_t auVersion[1]; + struct PARAM_SSID arSSID[4]; + uint16_t u2ProbeDelayTime; + uint16_t u2ChannelDwellTime; + uint16_t u2TimeoutValue; + uint8_t ucChannelType; + uint8_t ucChannelListNum; + struct CHANNEL_INFO arChannelList[32]; + uint16_t u2IELen; + uint8_t aucIE[600]; /*depends on u2IELen*/ + uint8_t ucChannelListExtNum; + uint8_t ucSSIDExtNum; + uint16_t u2ChannelMinDwellTime; + struct CHANNEL_INFO arChannelListExtend[32]; + struct PARAM_SSID arSSIDExtend[6]; + uint8_t aucBSSID[MAC_ADDR_LEN]; + uint8_t aucRandomMac[MAC_ADDR_LEN]; + uint8_t aucPadding_3[64]; +}; + +/* TLV for CMD_ID_SCAN_REQ_V2*/ +enum ENUM_CMD_ID_SCAN_REQ_V2_TAG_ID { + CMD_ID_SCAN_REQ_V2_TAG_00_TBD = 0, + CMD_ID_SCAN_REQ_V2_TAG_01_BSSID_AND_RANDOM_MAC = 1, + CMD_ID_SCAN_REQ_V2_TAG_ID_NUM +}; + +struct CMD_ID_SCAN_REQ_V2_TAG_01_BSSID_AND_RANDOM_MAC { + uint8_t aucRandomMacAddr[6]; + uint8_t aucBSSID[6]; +}; + + +struct CMD_SCAN_CANCEL { + uint8_t ucSeqNum; + uint8_t ucIsExtChannel; /* For P2P channel extension. */ + uint8_t aucReserved[2]; +}; + +struct CMD_P2P_SEC_CHECK { + uint32_t u4KeyId; + uint8_t aucBuffer[32]; +}; + + +struct CMD_RESET_BA_SCOREBOARD { + uint8_t ucflag; + uint8_t ucTID; + uint8_t aucMacAddr[MAC_ADDR_LEN]; +}; + + +struct CMD_IPV4_NETWORK_ADDRESS_V0 { + uint8_t aucIpAddr[IPV4_ADDR_LEN]; +}; + +struct CMD_IPV4_NETWORK_ADDRESS { + uint8_t aucIpAddr[IPV4_ADDR_LEN]; + uint8_t aucIpMask[IPV4_ADDR_LEN]; +}; + +struct CMD_SET_NETWORK_ADDRESS_LIST { + uint8_t ucBssIndex; + uint8_t ucAddressCount; + uint8_t ucVersion; + uint8_t ucReserved[1]; + struct CMD_IPV4_NETWORK_ADDRESS arNetAddress[1]; +}; + +struct CMD_IPV6_NETWORK_ADDRESS { + uint8_t aucIpAddr[IPV6_ADDR_LEN]; +}; + +struct CMD_IPV6_NETWORK_ADDRESS_LIST { + uint8_t ucBssIndex; + uint8_t ucAddressCount; + uint8_t ucReserved[2]; + struct CMD_IPV6_NETWORK_ADDRESS arNetAddress[1]; +}; + +struct CMD_SET_RRM_CAPABILITY { + /* DWORD_0 - Common Part*/ + uint8_t ucCmdVer; + uint8_t aucPadding0[1]; + uint16_t u2CmdLen; + /* Cmd size including common part and body */ + + /* DWORD_1 afterwards - Command Body*/ + uint8_t ucBssIndex; + uint8_t ucRrmEnable; /* 802.11k rrm flag */ + uint8_t ucCapabilities[5]; + /* Table 7-43e, RRM Enabled Capabilities Field */ + uint8_t aucPadding1[1]; + + uint8_t aucPadding2[32]; /* for new param in the future */ +}; + +struct CMD_SET_AP_CONSTRAINT_PWR_LIMIT { + /* DWORD_0 - Common Part*/ + uint8_t ucCmdVer; + uint8_t aucPadding0[1]; + uint16_t u2CmdLen; + /* Cmd size including common part and body */ + + /* DWORD_1 afterwards - Command Body*/ + uint8_t ucBssIndex; + uint8_t ucPwrSetEnable; + int8_t cMaxTxPwr; /* In unit of 0.5 dBm (signed) */ + int8_t cMinTxPwr; /* In unit of 0.5 dBm (signed) */ + + uint8_t aucPadding1[32]; /* for new param in the future */ +}; + +/* RTT */ +struct CMD_RTT_REQ { + uint8_t ucSeqNum; + uint8_t ucBssIndex; + uint8_t ucRttType; + uint8_t ucRttRole; + bool fgRttTrigger; + uint8_t ucNumRttReq; + uint16_t u2UpdatePeriodIn10MS; +}; + +struct CMD_RTT_CALIBR { + uint8_t aucMacAddr[MAC_ADDR_LEN]; + uint8_t ucNumRttMeas; + uint8_t ucReserved; +}; + +struct CMD_SET_SCHED_SCAN_ENABLE { + uint8_t ucSchedScanAct; /*ENUM_SCHED_SCAN_ACT*/ + uint8_t aucReserved[3]; +}; + +struct SCAN_SCHED_SSID_MATCH_SETS { + uint32_t cRssiThresold; + uint8_t aucSsid[32]; + uint8_t u4SsidLen; + uint8_t aucPadding_1[3]; +}; + +struct CMD_SCAN_SCHED_REQ { + uint8_t ucVersion; + uint8_t ucSeqNum; + /* Fw SCHED SCAN DONE after stop */ + uint8_t fgStopAfterIndication; + uint8_t ucSsidNum; + uint8_t ucMatchSsidNum; + uint8_t aucPadding_0; + uint16_t u2IELen; + /* Send prob request SSID set */ + struct PARAM_SSID auSsid[10]; + /* Match SSID set */ + struct SCAN_SCHED_SSID_MATCH_SETS auMatchSsid[16]; + uint8_t ucChannelType; + uint8_t ucChnlNum; + uint8_t ucMspEntryNum; + uint8_t ScnFuncMask; + struct CHANNEL_INFO aucChannel[64]; + /* SCHED SCN Interval */ + uint16_t au2MspList[10]; + uint8_t aucPadding_3[64]; + uint8_t aucIE[0]; +}; + +enum WIFI_SCAN_EVENT { + WIFI_SCAN_BUFFER_FULL = 0, + WIFI_SCAN_COMPLETE, +}; + +struct CMD_HIF_CTRL { + uint8_t ucHifType; + uint8_t ucHifDirection; + uint8_t ucHifStop; + uint8_t ucHifSuspend; + uint8_t aucReserved2[32]; +}; + +struct CMD_MU_EDCA_PARAMS { + uint8_t ucECWmin; + uint8_t ucECWmax; + uint8_t ucAifsn; + uint8_t ucIsACMSet; + uint8_t ucMUEdcaTimer; + uint8_t aucPadding[3]; +}; + +struct CMD_MQM_UPDATE_MU_EDCA_PARMS { + /* DWORD_0 - Common Part*/ + uint8_t ucCmdVer; + uint8_t aucPadding0[1]; + uint16_t u2CmdLen; /* Cmd size including common part and body */ + + /* DWORD_1 afterwards - Command Body*/ + uint8_t ucBssIndex; + uint8_t fgIsQBSS; + uint8_t ucWmmSet; + uint8_t aucPadding1[1]; + + struct CMD_MU_EDCA_PARAMS arMUEdcaParams[4]; /* number of ACs */ + uint8_t aucPadding2[32]; +}; + +struct CMD_RLM_UPDATE_SR_PARMS { + /* DWORD_0 - Common Part*/ + uint8_t ucCmdVer; + uint8_t aucPadding0[1]; + uint16_t u2CmdLen; /* Cmd size including common part and body */ + + /* DWORD_1 afterwards - Command Body*/ + uint8_t ucBssIndex; + uint8_t ucSRControl; + uint8_t ucNonSRGObssPdMaxOffset; + uint8_t ucSRGObssPdMinOffset; + uint8_t ucSRGObssPdMaxOffset; + uint8_t aucPadding1[3]; + uint32_t u4SRGBSSColorBitmapLow; + uint32_t u4SRGBSSColorBitmapHigh; + uint32_t u4SRGPartialBSSIDBitmapLow; + uint32_t u4SRGPartialBSSIDBitmapHigh; + + uint8_t aucPadding2[32]; +}; + +struct CMD_MDDP_FILTER_RULE { + /* DWORD_0 - Common Part*/ + uint8_t ucCmdVer; + uint8_t aucPadding0[1]; + uint16_t u2CmdLen; /* Cmd size including common part and body */ + + /* DWORD_1 afterwards - Command Body*/ + uint8_t ucPfType; + uint8_t ucPfNum; + uint8_t aucPadding1[2]; + uint8_t aucWhPfClsFilterMddp[0]; +}; + +/*---------------------------------------------------------------------------*/ +/* EVENT Packets */ +/*---------------------------------------------------------------------------*/ + +/* event of tkip mic error */ +struct EVENT_MIC_ERR_INFO { + uint32_t u4Flags; + uint8_t aucStaAddr[6]; +}; + +/* event of add key done for port control */ +struct EVENT_ADD_KEY_DONE_INFO { + uint8_t ucBSSIndex; + uint8_t ucReserved; + uint8_t aucStaAddr[6]; +}; + +struct LINK_QUALITY { + int8_t cRssi; /* AIS Network. */ + int8_t cLinkQuality; + uint16_t u2LinkSpeed; /* TX rate1 */ + uint8_t ucMediumBusyPercentage; /* Read clear */ + uint8_t ucIsLQ0Rdy; + /* Link Quality BSS0 Ready. */ + uint8_t aucReserve[2]; +}; + +struct EVENT_LINK_QUALITY { + struct LINK_QUALITY rLq[4]; + /*Refer to BSS_INFO_NUM, but event should not use HW realted + * definition + */ +}; + +struct EVENT_ACTIVATE_STA_REC { + uint8_t aucMacAddr[6]; + uint8_t ucStaRecIdx; + uint8_t ucBssIndex; +}; + +struct EVENT_DEACTIVATE_STA_REC { + uint8_t ucStaRecIdx; + uint8_t aucReserved[3]; +}; + +struct EVENT_BUG_REPORT { + + /* BugReportVersion */ + uint32_t u4BugReportVersion; + + /* FW Module State */ + uint32_t u4FWState; /*LP, roaming*/ + uint32_t u4FWScanState; + uint32_t u4FWCnmState; + + /* Scan Counter */ + uint32_t u4ReceivedBeaconCount; + uint32_t u4ReceivedProbeResponseCount; + uint32_t u4SentProbeRequestCount; + uint32_t u4SentProbeRequestFailCount; + + /* Roaming Counter */ + uint32_t u4RoamingDebugFlag; + uint32_t u4RoamingThreshold; + uint32_t u4RoamingCurrentRcpi; + + /* RF Counter */ + uint32_t u4RFPriChannel; + uint32_t u4RFChannelS1; + uint32_t u4RFChannelS2; + uint32_t u4RFChannelWidth; + uint32_t u4RFSco; + + /* Coex Counter */ + uint32_t u4BTProfile; + uint32_t u4BTOn; + uint32_t u4LTEOn; + + /* Low Power Counter */ + uint32_t u4LPTxUcPktNum; + uint32_t u4LPRxUcPktNum; + uint32_t u4LPPSProfile; + + /* Base Band Counter */ + uint32_t u4OfdmPdCnt; + uint32_t u4CckPdCnt; + uint32_t u4CckSigErrorCnt; + uint32_t u4CckSfdErrorCnt; + uint32_t u4OfdmSigErrorCnt; + uint32_t u4OfdmTaqErrorCnt; + uint32_t u4OfdmFcsErrorCnt; + uint32_t u4CckFcsErrorCnt; + uint32_t u4OfdmMdrdyCnt; + uint32_t u4CckMdrdyCnt; + uint32_t u4PhyCcaStatus; + uint32_t u4WifiFastSpiStatus; + + /* Mac RX Counter */ + uint32_t u4RxMdrdyCount; + uint32_t u4RxFcsErrorCount; + uint32_t u4RxbFifoFullCount; + uint32_t u4RxMpduCount; + uint32_t u4RxLengthMismatchCount; + uint32_t u4RxCcaPrimCount; + uint32_t u4RxEdCount; + + uint32_t u4LmacFreeRunTimer; + uint32_t u4WtblReadPointer; + uint32_t u4RmacWritePointer; + uint32_t u4SecWritePointer; + uint32_t u4SecReadPointer; + uint32_t u4DmaReadPointer; + + /* Mac TX Counter */ + uint32_t u4TxChannelIdleCount; + uint32_t u4TxCcaNavTxTime; + +}; + +struct CMD_GET_STATISTICS { +/* DWORD_0 - Common Part*/ + uint8_t ucCmdVer; + /* if the structure size is changed, the ucCmdVer shall be increased.*/ + uint8_t aucPadding0[1]; + uint16_t u2CmdLen; /* cmd size including common part and body.*/ + /** general use */ + uint8_t ucGeneralFlags; + /** TRUE: ucBssIndex is valid */ + uint8_t ucBssIndexValid; + uint8_t ucBssIndex; + uint8_t aucPadding1[1]; + /** Request the value for specific BSS */ + uint8_t aucPadding2[64]; +}; + +struct EVENT_STATISTICS { + /* Link quality for customer */ + union LARGE_INTEGER rTransmittedFragmentCount; + union LARGE_INTEGER rMulticastTransmittedFrameCount; + union LARGE_INTEGER rFailedCount; + union LARGE_INTEGER rRetryCount; + union LARGE_INTEGER rMultipleRetryCount; + union LARGE_INTEGER rRTSSuccessCount; + union LARGE_INTEGER rRTSFailureCount; + union LARGE_INTEGER rACKFailureCount; + union LARGE_INTEGER rFrameDuplicateCount; + union LARGE_INTEGER rReceivedFragmentCount; + union LARGE_INTEGER rMulticastReceivedFrameCount; + union LARGE_INTEGER rFCSErrorCount; + union LARGE_INTEGER rMdrdyCnt; + union LARGE_INTEGER rChnlIdleCnt; + uint32_t u4HwMacAwakeDuration; + uint32_t au4Padding3[15]; + + /* wifi_radio_stat */ + int32_t i4RadioIdx; + uint32_t u4OnTime; + uint32_t u4TxTime; + uint32_t u4NumTxLevels; /* for au4TxTimePerLevels */ + uint32_t u4RxTime; + uint32_t u4OnTimeScan; + uint32_t u4OnTimeNbd; + uint32_t u4OnTimeGscan; + uint32_t u4OnTimeRoamScan; + uint32_t u4OnTimePnoScan; + uint32_t u4OnTimeHs20; + uint32_t u4NumChannels; + uint32_t au4TxTimePerLevels[78]; + + /* wifi_iface_stat */ + int32_t i4IfaceIdx; + uint32_t u4NumWifiInterfaceLinkLayerInfo; + uint32_t u4BeaconRx; + uint32_t u4AverageTsfOffsetHigh; + uint32_t u4AverageTsfOffsetLow; + uint32_t u4LeakyApDetected; + uint32_t u4LeakyApAvgNumFramesLeaked; + uint32_t u4Leaky_ap_guard_time; + uint32_t u4MgmtRx; + uint32_t u4MgmtActionRx; + uint32_t u4MgmtActionTx; + int32_t i4RssiMgmt; + int32_t i4RssiData; + int32_t i4RssiAck; + uint32_t u4NumAc; + uint32_t u4NumPeers; + + /* wifi_interface_link_layer_info */ + int16_t i2Mode; + uint8_t aucMacAddr[6]; + int16_t i2State; + int16_t i2Roaming; + uint32_t u4Capabilities; + uint8_t aucSsid[33]; + uint8_t aucPadding4[1]; + uint8_t aucBssid[6]; + uint8_t aucPadding5[2]; + uint8_t aucApCountryStr[3]; + uint8_t aucPadding6[1]; + uint8_t aucCountryStr[3]; + uint8_t aucPadding7[1]; + + /* wifi_wmm_ac_stat: VO */ + uint32_t u4VoTxMpdu; + uint32_t u4VoRxMpdu; + uint32_t u4VoTxMcast; + uint32_t u4VoRxMcast; + uint32_t u4VoRxAmpdu; + uint32_t u4VoTxAmpdu; + uint32_t u4VoMpduLost; + uint32_t u4VoRetries; + uint32_t u4VoRetriesShort; + uint32_t u4VoRetriesLong; + uint32_t u4VoContentionTimeMin; + uint32_t u4VoContentionTimeMax; + uint32_t u4VoContentionTimeAvg; + uint32_t u4VoContentionNumSamples; + + /* wifi_wmm_ac_stat: VI */ + uint32_t u4ViTxMpdu; + uint32_t u4ViRxMpdu; + uint32_t u4ViTxMcast; + uint32_t u4ViRxMcast; + uint32_t u4ViRxAmpdu; + uint32_t u4ViTxAmpdu; + uint32_t u4ViMpduLost; + uint32_t u4ViRetries; + uint32_t u4ViRetriesShort; + uint32_t u4ViRetriesLong; + uint32_t u4ViContentionTimeMin; + uint32_t u4ViContentionTimeMax; + uint32_t u4ViContentionTimeAvg; + uint32_t u4ViContentionNumSamples; + + /* wifi_wmm_ac_stat: BE */ + uint32_t u4BeTxMpdu; + uint32_t u4BeRxMpdu; + uint32_t u4BeTxMcast; + uint32_t u4BeRxMcast; + uint32_t u4BeRxAmpdu; + uint32_t u4BeTxAmpdu; + uint32_t u4BeMpduLost; + uint32_t u4BeRetries; + uint32_t u4BeRetriesShort; + uint32_t u4BeRetriesLong; + uint32_t u4BeContentionTimeMin; + uint32_t u4BeContentionTimeMax; + uint32_t u4BeContentionTimeAvg; + uint32_t u4BeContentionNumSamples; + + /* wifi_wmm_ac_stat: BK */ + uint32_t u4BkTxMpdu; + uint32_t u4BkRxMpdu; + uint32_t u4BkTxMcast; + uint32_t u4BkRxMcast; + uint32_t u4BkRxAmpdu; + uint32_t u4BkTxAmpdu; + uint32_t u4BkMpduLost; + uint32_t u4BkRetries; + uint32_t u4BkRetriesShort; + uint32_t u4BkRetriesLong; + uint32_t u4BkContentionTimeMin; + uint32_t u4BkContentionTimeMax; + uint32_t u4BkContentionTimeAvg; + uint32_t u4BkContentionNumSamples; + + uint32_t au4PaddingTail[128]; +}; + +struct EVENT_SCAN_DONE { + uint8_t ucSeqNum; + uint8_t ucSparseChannelValid; + struct CHANNEL_INFO rSparseChannel; + uint8_t ucCompleteChanCount; + uint8_t ucCurrentState; + uint8_t ucScanDoneVersion; + uint8_t ucReserved; + uint32_t u4ScanDurBcnCnt; + uint8_t fgIsPNOenabled; + uint8_t aucReserving[3]; + /*channel idle count # Mike */ + uint8_t ucSparseChannelArrayValidNum; + uint8_t aucReserved[3]; + uint8_t aucChannelNum[SCAN_DONE_EVENT_MAX_CHANNEL_NUM]; + /* Idle format for au2ChannelIdleTime */ + /* 0: first bytes: idle time(ms) 2nd byte: dwell time(ms) */ + /* 1: first bytes: idle time(8ms) 2nd byte: dwell time(8ms) */ + /* 2: dwell time (16us) */ + uint16_t au2ChannelIdleTime[SCAN_DONE_EVENT_MAX_CHANNEL_NUM]; + /* Beacon and Probe Response Count in each Channel */ + uint8_t aucChannelBAndPCnt[SCAN_DONE_EVENT_MAX_CHANNEL_NUM]; + /* Mdrdy Count in each Channel */ + uint8_t aucChannelMDRDYCnt[SCAN_DONE_EVENT_MAX_CHANNEL_NUM]; + uint32_t u4ScanDurBcnCnt2G4; + uint32_t u4ScanDurBcnCnt5G; + uint16_t au2ChannelScanTime[SCAN_DONE_EVENT_MAX_CHANNEL_NUM]; +}; + +struct EVENT_CH_PRIVILEGE { + uint8_t ucBssIndex; + uint8_t ucTokenID; + uint8_t ucStatus; + uint8_t ucPrimaryChannel; + uint8_t ucRfSco; + uint8_t ucRfBand; + uint8_t ucRfChannelWidth; + /* To support 80/160MHz bandwidth */ + uint8_t ucRfCenterFreqSeg1; + /* To support 80/160MHz bandwidth */ + uint8_t ucRfCenterFreqSeg2; + /* To support 80/160MHz bandwidth */ + uint8_t ucReqType; + uint8_t ucDBDCBand; /* ENUM_CMD_REQ_DBDC_BAND_T*/ + uint8_t aucReserved; + uint32_t u4GrantInterval; /* In unit of ms */ + uint8_t aucReserved2[8]; +}; + +enum ENUM_BEACON_TIMEOUT_REASON { + BEACON_TIMEOUT_REASON_HW_BEACON_LOST_NONADHOC, + BEACON_TIMEOUT_REASON_HW_BEACON_LOST_ADHOC, + BEACON_TIMEOUT_REASON_HW_TSF_DRIFT, + BEACON_TIMEOUT_REASON_NULL_FRAME_THRESHOLD, + BEACON_TIMEOUT_REASON_AGING_THRESHOLD, + BEACON_TIMEOUT_REASON_BSSID_BEACON_PEIROD_NOT_ILLIGAL, + BEACON_TIMEOUT_REASON_CONNECTION_FAIL, + BEACON_TIMEOUT_REASON_ALLOCAT_NULL_PKT_FAIL_THRESHOLD, + BEACON_TIMEOUT_REASON_NO_TX_DONE_EVENT, + BEACON_TIMEOUT_REASON_UNSPECIF_REASON, + BEACON_TIMEOUT_REASON_SET_CHIP, + BEACON_TIMEOUT_REASON_KEEP_SCAN_AP_MISS_CHECK_FAIL, + BEACON_TIMEOUT_REASON_KEEP_UNCHANGED_LOW_RSSI_CHECK_FAIL, + BEACON_TIMEOUT_REASON_NULL_FRAME_LIFE_TIMEOUT, + BEACON_TIMEOUT_REASON_HIGH_PER, + BEACON_TIMEOUT_REASON_NUM +}; + +struct EVENT_BSS_BEACON_TIMEOUT { + uint8_t ucBssIndex; + uint8_t ucReasonCode; + uint8_t aucReserved[2]; +}; + +struct EVENT_STA_AGING_TIMEOUT { + uint8_t ucStaRecIdx; + uint8_t aucReserved[3]; +}; + +struct EVENT_NOA_TIMING { + uint8_t ucIsInUse; + /* Indicate if this entry is in use or not */ + uint8_t ucCount; /* Count */ + uint8_t aucReserved[2]; + + uint32_t u4Duration; /* Duration */ + uint32_t u4Interval; /* Interval */ + uint32_t u4StartTime; /* Start Time */ +}; + +struct EVENT_UPDATE_NOA_PARAMS { + uint8_t ucBssIndex; + uint8_t aucReserved[2]; + uint8_t ucEnableOppPS; + uint16_t u2CTWindow; + + uint8_t ucNoAIndex; + uint8_t ucNoATimingCount; /* Number of NoA Timing */ + struct EVENT_NOA_TIMING arEventNoaTiming[8/*P2P_MAXIMUM_NOA_COUNT*/]; +}; + +struct EVENT_AP_OBSS_STATUS { + uint8_t ucBssIndex; + uint8_t ucObssErpProtectMode; + uint8_t ucObssHtProtectMode; + uint8_t ucObssGfOperationMode; + uint8_t ucObssRifsOperationMode; + uint8_t ucObssBeaconForcedTo20M; + uint8_t aucReserved[2]; +}; + +struct EVENT_RDD_STATUS { + uint8_t ucRddStatus; + uint8_t aucReserved[3]; +}; + +struct EVENT_NLO_DONE { + uint8_t ucSeqNum; + uint8_t ucStatus; /* 0: Found / other: reserved */ + uint8_t aucReserved[2]; +}; + +/* RTT */ +struct RTT_PEER { + uint8_t aucBssid[MAC_ADDR_LEN]; + uint16_t u2CalibrInNS; + uint32_t u4RangeInNS; + uint32_t u4AccuracyInNS; + + uint32_t u4RangeInCM; + uint32_t u4AccuracyInCM; + uint32_t *pu4APLon; + uint32_t *pu4APLat; + PARAM_RSSI rRssi; +}; + +#define PARAM_MAX_RTT_PEERS 8 +struct EVENT_RTT_UPDATE_RANGE { + uint8_t ucNumPeer; + uint8_t aucReserved[3]; + struct RTT_PEER arPeers[PARAM_MAX_RTT_PEERS]; + uint16_t au2Event[25]; + uint16_t u2Timer; +}; +struct EVENT_RTT_UPDATE_LOCATION { + uint8_t ucNumPeer; + uint8_t aucReserved[3]; + struct RTT_PEER arPeers[PARAM_MAX_RTT_PEERS]; + uint16_t au2Event[25]; + uint16_t u2Timer; +}; + +struct EVENT_RTT_DISCOVER_PEER { + uint16_t au2Event[25]; + uint16_t u2Timer; +}; + +struct EVENT_BUILD_DATE_CODE { + uint8_t aucDateCode[16]; +}; + +struct EVENT_BATCH_RESULT_ENTRY { + uint8_t aucBssid[MAC_ADDR_LEN]; + uint8_t aucSSID[ELEM_MAX_LEN_SSID]; + uint8_t ucSSIDLen; + int8_t cRssi; + uint32_t ucFreq; + uint32_t u4Age; + uint32_t u4Dist; + uint32_t u4Distsd; +}; + +struct EVENT_BATCH_RESULT { + uint8_t ucScanCount; + uint8_t aucReserved[3]; + struct EVENT_BATCH_RESULT_ENTRY arBatchResult[12]; + /* Must be the same with SCN_BATCH_STORE_MAX_NUM*/ +}; + +struct CMD_SET_FILTER_COEFFICIENT { + uint32_t u4BssIndex; + int32_t i4FilterCoefficient; + uint8_t aucReserved[8]; +}; + +#define BA_FW_DROP_SN_BMAP_SZ 8 +struct EVENT_BA_FW_DROP_RECORD { + uint8_t ucStaRecIdx; + uint8_t ucTid; + uint16_t u2DropSnStart; + uint32_t u4DropReason; + uint8_t aucSnBmap[BA_FW_DROP_SN_BMAP_SZ]; + uint8_t aucDropLastAmsduSnBmap[BA_FW_DROP_SN_BMAP_SZ]; + uint8_t aucReserved[4]; +}; + +struct EVENT_BA_FW_DROP_SN { + uint8_t ucEvtVer; + uint8_t aucPadding0[1]; + uint16_t ucEvtLen; + uint8_t ucRecordNum; + uint8_t aucPadding1[3]; + struct EVENT_BA_FW_DROP_RECORD arBaFwDropRecord[8]; + /*CFG_NUM_OF_RX_BA_AGREEMENTS*/ +}; + +/* NDIS_MEDIA_STATE */ +enum ENUM_PARAM_MEDIA_STATE { + MEDIA_STATE_CONNECTED = 0, + MEDIA_STATE_DISCONNECTED, + MEDIA_STATE_ROAMING_DISC_PREV, + /* transient disconnected state for normal/fast roamming purpose */ + MEDIA_STATE_TO_BE_INDICATED, + MEDIA_STATE_NUM +}; + +enum ENUM_LOG_UI_LVL { + ENUM_LOG_UI_LVL_DEFAULT = 0, + ENUM_LOG_UI_LVL_MORE = 1, + ENUM_LOG_UI_LVL_EXTREME = 2, +}; + +struct CMD_EVENT_LOG_UI_INFO { + uint32_t ucVersion; /* default is 1*/ + uint32_t ucLogLevel; /* 0: Default, 1: More, 2: Extreme*/ + uint8_t aucReserved[4]; /*reserved*/ +}; + +struct CMD_WAKE_HIF { + /* use in-band signal to wakeup system, ENUM_HIF_TYPE */ + uint8_t ucWakeupHif; + uint8_t ucGpioPin; /* GPIO Pin */ + uint8_t ucTriggerLvl; /* GPIO Pin */ + uint8_t aucResv1[1]; + /* 0: low to high, 1: high to low */ + uint32_t u4GpioInterval; + uint8_t aucResv2[4]; +}; + +struct WOW_PORT { + uint8_t ucIPv4UdpPortCnt; + uint8_t ucIPv4TcpPortCnt; + uint8_t ucIPv6UdpPortCnt; + uint8_t ucIPv6TcpPortCnt; + uint16_t ausIPv4UdpPort[MAX_TCP_UDP_PORT]; + uint16_t ausIPv4TcpPort[MAX_TCP_UDP_PORT]; + uint16_t ausIPv6UdpPort[MAX_TCP_UDP_PORT]; + uint16_t ausIPv6TcpPort[MAX_TCP_UDP_PORT]; +}; + +struct CMD_WOWLAN_PARAM { + uint8_t ucCmd; + uint8_t ucDetectType; + uint16_t u2FilterFlag; /* ARP/MC/DropExceptMagic/SendMagicToHost */ + uint8_t ucScenarioID; /* WOW/WOBLE/Proximity */ + uint8_t ucBlockCount; + uint8_t aucReserved1[2]; + struct CMD_WAKE_HIF astWakeHif[2]; + struct WOW_PORT stWowPort; + uint8_t aucReserved2[32]; +}; + +/*Oshare mode*/ +#define CMD_OSHARE_LENGTH_MAX 64 +struct CMD_OSHARE { + uint8_t ucCmdVersion; /* CMD version = OSHARE_CMD_V1*/ + uint8_t ucCmdType; + uint8_t ucMagicCode; + /* It's like CRC, OSHARE_MAGIC_CODE*/ + uint8_t ucCmdBufferLen; /*buffer length <= 64*/ + uint8_t aucBuffer[CMD_OSHARE_LENGTH_MAX]; +}; + +struct EVENT_MDDP_FILTER_RULE { + /* DWORD_0 - Common Part*/ + uint8_t ucEvtVer; + uint8_t aucPadding0[1]; + uint16_t u2EvtLen; + + /* DWORD_1 - afterwards*/ + uint8_t ucPfType; + uint8_t ucPfNum; + uint8_t aucPadding1[2]; + uint32_t au4PfStatusBitmap[64]; +}; + +struct CMD_DOMAIN_CHANNEL { + uint16_t u2ChNum; + uint8_t aucPadding[2]; + uint32_t eFlags; /*enum ieee80211_channel_flags*/ +}; + +struct CMD_DOMAIN_ACTIVE_CHANNEL_LIST { + uint8_t u1ActiveChNum2g; + uint8_t u1ActiveChNum5g; + uint8_t aucPadding[2]; + struct CMD_DOMAIN_CHANNEL arChannels[0]; +}; + +struct CMD_SET_DOMAIN_INFO_V2 { + /* DWORD_0 - Country code*/ + uint32_t u4CountryCode; + + /* DWORD_1 - 2.4G & 5G BW info*/ + uint8_t uc2G4Bandwidth; /* CONFIG_BW_20_40M or CONFIG_BW_20M */ + uint8_t uc5GBandwidth; /* CONFIG_BW_20_40M or CONFIG_BW_20M */ + uint8_t aucPadding[2]; + + /* DWORD_2 ~ - 2.4G & 5G active channel info*/ + struct CMD_DOMAIN_ACTIVE_CHANNEL_LIST arActiveChannels; +}; + +#define SINGLE_SKU_PARAM_NUM 69 +struct CMD_SKU_TABLE_TYPE { + int8_t i1PwrLimit[SINGLE_SKU_PARAM_NUM]; +}; + +struct CMD_TXPOWER_CHANNEL_POWER_LIMIT_PER_RATE { + uint8_t u1CentralCh; + struct CMD_SKU_TABLE_TYPE aucTxPwrLimit; +}; + +struct CMD_SET_TXPOWER_COUNTRY_TX_POWER_LIMIT_PER_RATE { + /* DWORD_0 - Common info*/ + uint8_t ucCmdVer; + uint8_t aucPadding0[1]; + uint16_t u2CmdLen; + + /* DWORD_1 - CMD hint*/ + uint8_t ucNum; /* channel #*/ + uint8_t eBand; /* 2.4g or 5g*/ + uint8_t bCmdFinished; + /* hint for whether 2.4g/5g tx power limit value all be sent*/ + uint8_t aucPadding1[1]; + + /* DWORD_2 - Country code*/ + uint32_t u4CountryCode; + + /* WORD_3 ~ 10 - Padding*/ + uint8_t aucPadding2[32]; + + /* DWORD_11 ~ - Tx power limit values*/ + struct CMD_TXPOWER_CHANNEL_POWER_LIMIT_PER_RATE rChannelPowerLimit[0]; +}; + +#define POWER_LIMIT_TXBF_BACKOFF_PARAM_NUM 6 +struct CMD_TXPWR_TXBF_CHANNEL_BACKOFF { + uint8_t ucCentralCh; + uint8_t aucPadding0[1]; + int8_t acTxBfBackoff[POWER_LIMIT_TXBF_BACKOFF_PARAM_NUM]; +}; + +#define CMD_POWER_LIMIT_TABLE_SUPPORT_CHANNEL_NUM 64 +struct CMD_TXPWR_TXBF_SET_BACKOFF { + uint8_t ucCmdVer; + uint8_t aucPadding0[1]; + uint16_t u2CmdLen; + uint8_t ucNum; + uint8_t ucBssIdx; + uint8_t aucPadding1[2]; + uint8_t aucPadding2[32]; + struct CMD_TXPWR_TXBF_CHANNEL_BACKOFF + rChannelTxBfBackoff[CMD_POWER_LIMIT_TABLE_SUPPORT_CHANNEL_NUM]; +}; + +/* The DBDC band request from driver. + * So far, the actual used DBDC band is decdied in firmware by channel. + * Driver should use ENUM_CMD_REQ_BAND_AUTO only. + */ +enum ENUM_CMD_REQ_DBDC_BAND { + ENUM_CMD_REQ_BAND_0 = 0, + ENUM_CMD_REQ_BAND_1 = 1, + ENUM_CMD_REQ_BAND_ALL = 3, + ENUM_CMD_REQ_BAND_AUTO = 4, + ENUM_CMD_REQ_BAND_NUM /*Just for checking.*/ +}; + +enum ENUM_EVENT_OPMODE_CHANGE_REASON { + EVENT_OPMODE_CHANGE_REASON_DBDC = 0, + EVENT_OPMODE_CHANGE_REASON_COANT = 1, + EVENT_OPMODE_CHANGE_REASON_DBDC_SCAN = 2, + EVENT_OPMODE_CHANGE_REASON_SMARTGEAR = 3, + EVENT_OPMODE_CHANGE_REASON_COEX = 4, + EVENT_OPMODE_CHANGE_REASON_SMARTGEAR_1T2R = 5, +}; + +struct EVENT_OPMODE_CHANGE { + /* DWORD_0 - Common Part*/ + uint8_t ucEvtVer; + uint8_t aucPadding0[1]; + uint16_t u2EvtLen; + + uint8_t ucBssBitmap; /*Bit[3:0]*/ + uint8_t ucEnable; /*Enable OpTxRx limitation/change*/ + uint8_t ucOpTxNss; /*0: don't care*/ + uint8_t ucOpRxNss; /*0: don't care*/ + + uint8_t ucReason; /* ENUM_EVENT_OPMODE_CHANGE_REASON_T*/ + uint8_t aucPadding1[63]; +}; + +#define EVENT_GET_CNM_BAND_NUM 2 /* ENUM_BAND_NUM*/ +#define EVENT_GET_CNM_MAX_OP_CHNL_NUM 3 /* MAX_OP_CHNL_NUM*/ +#define EVENT_GET_CNM_MAX_BSS_NUM 4 /* BSS_INFO_NUM*/ +#define EVENT_GET_CNM_AMX_BSS_FULL_NUM 5 /* BSS_INFO_FULL_NUM*/ +struct EVENT_GET_CNM { + uint8_t fgIsDbdcEnable; + + uint8_t ucOpChNum[EVENT_GET_CNM_BAND_NUM]; + uint8_t ucChList[EVENT_GET_CNM_BAND_NUM] + [EVENT_GET_CNM_MAX_OP_CHNL_NUM]; + uint8_t ucChBw[EVENT_GET_CNM_BAND_NUM] + [EVENT_GET_CNM_MAX_OP_CHNL_NUM]; + uint8_t ucChSco[EVENT_GET_CNM_BAND_NUM] + [EVENT_GET_CNM_MAX_OP_CHNL_NUM]; + uint8_t ucChNetNum[EVENT_GET_CNM_BAND_NUM] + [EVENT_GET_CNM_MAX_OP_CHNL_NUM]; + uint8_t ucChBssList[EVENT_GET_CNM_BAND_NUM] + [EVENT_GET_CNM_MAX_OP_CHNL_NUM][EVENT_GET_CNM_MAX_BSS_NUM]; + /* BAND/CH/BSS */ + + uint8_t ucBssInuse[EVENT_GET_CNM_AMX_BSS_FULL_NUM]; + uint8_t ucBssActive[EVENT_GET_CNM_AMX_BSS_FULL_NUM]; + uint8_t ucBssConnectState[EVENT_GET_CNM_AMX_BSS_FULL_NUM]; + + uint8_t ucBssCh[EVENT_GET_CNM_AMX_BSS_FULL_NUM]; + uint8_t ucBssDBDCBand[EVENT_GET_CNM_AMX_BSS_FULL_NUM]; + uint8_t ucBssWmmSet[EVENT_GET_CNM_AMX_BSS_FULL_NUM]; + uint8_t ucBssWmmDBDCBand[EVENT_GET_CNM_AMX_BSS_FULL_NUM]; + uint8_t ucBssOMACSet[EVENT_GET_CNM_AMX_BSS_FULL_NUM]; + uint8_t ucBssOMACDBDCBand[EVENT_GET_CNM_AMX_BSS_FULL_NUM]; + + /* Reserved fields */ + uint8_t au4Reserved[68]; /*Total 164 byte*/ +}; + +struct CMD_SET_FORCE_RTS { + uint8_t ucForceRtsEn; + uint8_t ucRtsPktNum; + uint8_t aucReserved[2]; +}; + +#endif /* _WSYS_CMD_HANDLER_FW_H */ + + From c0f124aaf85a346c33ccb749c083d1881b530994 Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 22:15:10 +0800 Subject: [PATCH 25/32] Add files via upload --- .../wlan/core/gen4m/include/mgmt/aa_fsm.h | 234 +++ .../wlan/core/gen4m/include/mgmt/ais_fsm.h | 757 ++++++++ .../core/gen4m/include/mgmt/ap_selection.h | 78 + .../wlan/core/gen4m/include/mgmt/assoc.h | 157 ++ .../wlan/core/gen4m/include/mgmt/auth.h | 182 ++ .../wlan/core/gen4m/include/mgmt/bow_fsm.h | 189 ++ .../wlan/core/gen4m/include/mgmt/bss.h | 300 +++ .../wlan/core/gen4m/include/mgmt/cnm.h | 417 +++++ .../wlan/core/gen4m/include/mgmt/cnm_mem.h | 1213 +++++++++++++ .../wlan/core/gen4m/include/mgmt/cnm_scan.h | 164 ++ .../wlan/core/gen4m/include/mgmt/cnm_timer.h | 260 +++ .../wlan/core/gen4m/include/mgmt/he_ie.h | 733 ++++++++ .../wlan/core/gen4m/include/mgmt/he_rlm.h | 187 ++ .../wlan/core/gen4m/include/mgmt/hem_mbox.h | 452 +++++ .../wlan/core/gen4m/include/mgmt/hs20.h | 200 ++ .../wlan/core/gen4m/include/mgmt/mddp.h | 84 + .../wlan/core/gen4m/include/mgmt/mib.h | 189 ++ .../wlan/core/gen4m/include/mgmt/p2p_assoc.h | 104 ++ .../wlan/core/gen4m/include/mgmt/p2p_bss.h | 109 ++ .../wlan/core/gen4m/include/mgmt/p2p_dev.h | 270 +++ .../core/gen4m/include/mgmt/p2p_dev_state.h | 107 ++ .../wlan/core/gen4m/include/mgmt/p2p_fsm.h | 92 + .../wlan/core/gen4m/include/mgmt/p2p_func.h | 485 +++++ .../wlan/core/gen4m/include/mgmt/p2p_ie.h | 102 ++ .../wlan/core/gen4m/include/mgmt/p2p_rlm.h | 136 ++ .../core/gen4m/include/mgmt/p2p_rlm_obss.h | 118 ++ .../wlan/core/gen4m/include/mgmt/p2p_role.h | 501 +++++ .../core/gen4m/include/mgmt/p2p_role_state.h | 160 ++ .../wlan/core/gen4m/include/mgmt/p2p_scan.h | 125 ++ .../wlan/core/gen4m/include/mgmt/privacy.h | 295 +++ .../wlan/core/gen4m/include/mgmt/qosmap.h | 122 ++ .../wlan/core/gen4m/include/mgmt/rate.h | 133 ++ .../wlan/core/gen4m/include/mgmt/rlm.h | 512 ++++++ .../wlan/core/gen4m/include/mgmt/rlm_domain.h | 1147 ++++++++++++ .../wlan/core/gen4m/include/mgmt/rlm_obss.h | 148 ++ .../core/gen4m/include/mgmt/rlm_protection.h | 142 ++ .../core/gen4m/include/mgmt/rlm_txpwr_init.h | 1609 +++++++++++++++++ .../core/gen4m/include/mgmt/roaming_fsm.h | 232 +++ .../wlan/core/gen4m/include/mgmt/rrm.h | 201 ++ .../wlan/core/gen4m/include/mgmt/rsn.h | 343 ++++ .../wlan/core/gen4m/include/mgmt/scan.h | 940 ++++++++++ .../wlan/core/gen4m/include/mgmt/stats.h | 104 ++ .../wlan/core/gen4m/include/mgmt/swcr.h | 269 +++ .../wlan/core/gen4m/include/mgmt/tdls.h | 485 +++++ .../wlan/core/gen4m/include/mgmt/twt.h | 246 +++ .../core/gen4m/include/mgmt/twt_planner.h | 177 ++ .../core/gen4m/include/mgmt/twt_req_fsm.h | 154 ++ .../wlan/core/gen4m/include/mgmt/wapi.h | 133 ++ .../core/gen4m/include/mgmt/wlan_typedef.h | 156 ++ .../wlan/core/gen4m/include/mgmt/wmm.h | 211 +++ .../wlan/core/gen4m/include/mgmt/wnm.h | 184 ++ 51 files changed, 16048 insertions(+) create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/aa_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/ais_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/ap_selection.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/assoc.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/auth.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/bow_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/bss.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/cnm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/cnm_mem.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/cnm_scan.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/cnm_timer.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/he_ie.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/he_rlm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/hem_mbox.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/hs20.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/mddp.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/mib.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_assoc.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_bss.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_dev.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_dev_state.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_func.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_ie.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_rlm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_rlm_obss.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_role.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_role_state.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_scan.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/privacy.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/qosmap.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rate.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rlm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rlm_domain.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rlm_obss.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rlm_protection.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rlm_txpwr_init.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/roaming_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rrm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rsn.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/scan.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/stats.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/swcr.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/tdls.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/twt.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/twt_planner.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/twt_req_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/wapi.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/wlan_typedef.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/wmm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/wnm.h diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/aa_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/aa_fsm.h new file mode 100644 index 0000000000000..5db7bf6e5f126 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/aa_fsm.h @@ -0,0 +1,234 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + +#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. */ +/* Beacon Interval, 20 * 100TU = 2 sec. */ +#define JOIN_FAILURE_TIMEOUT_BEACON_INTERVAL 20 + +/* 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 */ + +#define TX_AUTHENTICATION_RESPONSE_TIMEOUT_TU 512 /* TU. */ + +#define TX_ASSOCIATE_TIMEOUT_TU 2048 /* TU. */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +enum ENUM_AA_STATE { + AA_STATE_IDLE = 0, + SAA_STATE_SEND_AUTH1, + SAA_STATE_WAIT_AUTH2, + SAA_STATE_SEND_AUTH3, + SAA_STATE_WAIT_AUTH4, + SAA_STATE_EXTERNAL_AUTH, + 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 ENUM_AA_FRM_TYPE { + FRM_DISASSOC = 0, + FRM_DEAUTH +}; + +/******************************************************************************* + * P U B 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 struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN enum ENUM_AA_STATE eNextState, + IN struct SW_RFB *prRetainedSwRfb); + +uint32_t +saaFsmSendEventJoinComplete(IN struct ADAPTER *prAdapter, + uint32_t rJoinStatus, struct STA_RECORD *prStaRec, + struct SW_RFB *prSwRfb); + +void saaFsmRunEventStart(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +uint32_t +saaFsmRunEventTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +void saaFsmRunEventTxReqTimeOut(IN struct ADAPTER + *prAdapter, IN unsigned long plParamPtr); + +void saaFsmRunEventRxRespTimeOut(IN struct ADAPTER + *prAdapter, IN unsigned long ulParamPtr); + +void saaFsmRunEventRxAuth(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +uint32_t saaFsmRunEventRxAssoc(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +uint32_t saaFsmRunEventRxDeauth(IN struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfb); + +uint32_t saaFsmRunEventRxDisassoc(IN struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfb); + +void saaFsmRunEventAbort(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void saaChkDeauthfrmParamHandler(IN struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfb, + IN struct STA_RECORD *prStaRec); + +void +saaChkDisassocfrmParamHandler(IN struct ADAPTER *prAdapter, + IN struct WLAN_DISASSOC_FRAME *prDisassocFrame, + IN struct STA_RECORD *prStaRec, + IN struct SW_RFB *prSwRfb); + +void +saaSendDisconnectMsgHandler(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct BSS_INFO *prAisBssInfo, + IN enum ENUM_AA_FRM_TYPE eFrmType); + +void saaFsmRunEventFTContinue(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void saaFsmRunEventExternalAuthDone(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +/*----------------------------------------------------------------------------*/ +/* Routines in aaa_fsm.c */ +/*----------------------------------------------------------------------------*/ +void aaaFsmRunEventRxAuth(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +uint32_t aaaFsmRunEventRxAssoc(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +uint32_t +aaaFsmRunEventTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + + +#endif /* _AA_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/ais_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/ais_fsm.h new file mode 100644 index 0000000000000..fc68d31c7c5c4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/ais_fsm.h @@ -0,0 +1,757 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/ + * include/mgmt/ais_fsm.h#2 + */ + +/*! \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. + */ + + +#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 5 /* 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 4000 +#define AIS_SCN_DONE_TIMEOUT_SEC 15 /* 15 for 2.4G + 5G */ /* 5 */ +#define AIS_SCN_REPORT_SEQ_NOT_SET (0xFFFF) + +/* Support AP Selection*/ +#define AIS_BLACKLIST_TIMEOUT 15 /* seconds */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +enum ENUM_AIS_STATE { + 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_JOIN_FAILURE, + AIS_STATE_IBSS_ALONE, + AIS_STATE_IBSS_MERGE, + AIS_STATE_NORMAL_TR, + AIS_STATE_DISCONNECTING, + AIS_STATE_REQ_REMAIN_ON_CHANNEL, + AIS_STATE_REMAIN_ON_CHANNEL, + AIS_STATE_OFF_CHNL_TX, + AIS_STATE_NUM +}; + +/* reconnect level for determining if we should reconnect */ +enum ENUM_RECONNECT_LEVEL_T { + RECONNECT_LEVEL_MIN = 0, + RECONNECT_LEVEL_ROAMING_FAIL, /* roaming failed */ + RECONNECT_LEVEL_BEACON_TIMEOUT, /* driver beacon timeout */ + RECONNECT_LEVEL_USER_SET, /* user set connect */ + /* or disassociate */ + RECONNECT_LEVEL_MAX +}; + +struct MSG_AIS_ABORT { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucReasonOfDisconnect; + u_int8_t fgDelayIndication; + uint8_t ucBssIndex; +}; + +struct MSG_AIS_IBSS_PEER_FOUND { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucBssIndex; + u_int8_t fgIsMergeIn; /* TRUE: Merge In, FALSE: Merge Out */ + struct STA_RECORD *prStaRec; +}; + +enum ENUM_AIS_REQUEST_TYPE { + AIS_REQUEST_SCAN, + AIS_REQUEST_RECONNECT, + AIS_REQUEST_ROAMING_SEARCH, + AIS_REQUEST_ROAMING_CONNECT, + AIS_REQUEST_REMAIN_ON_CHANNEL, + AIS_REQUEST_NUM +}; + +struct AIS_REQ_HDR { + struct LINK_ENTRY rLinkEntry; + enum ENUM_AIS_REQUEST_TYPE eReqType; +}; + +struct AIS_REQ_CHNL_INFO { + enum ENUM_BAND eBand; + enum ENUM_CHNL_EXT eSco; + uint8_t ucChannelNum; + uint32_t u4DurationMs; + uint64_t u8Cookie; + enum ENUM_CH_REQ_TYPE eReqType; +}; + +struct AIS_MGMT_TX_REQ_INFO { + struct LINK rTxReqLink; + u_int8_t fgIsMgmtTxRequested; + struct MSDU_INFO *prMgmtTxMsdu; + uint64_t u8Cookie; +}; + +/* Support AP Selection */ +struct AIS_BLACKLIST_ITEM { + struct LINK_ENTRY rLinkEntry; + + uint8_t aucBSSID[MAC_ADDR_LEN]; + uint16_t u2DeauthReason; + uint16_t u2AuthStatus; + uint8_t ucCount; + uint8_t ucSSIDLen; + uint8_t aucSSID[32]; + OS_SYSTIME rAddTime; + u_int8_t fgDeauthLastTime; + u_int8_t fgIsInFWKBlacklist; +}; +/* end Support AP Selection */ + +struct AIS_FSM_INFO { + enum ENUM_AIS_STATE ePreviousState; + enum ENUM_AIS_STATE eCurrentState; + + u_int8_t fgIsScanning; + + u_int8_t fgIsChannelRequested; + u_int8_t fgIsChannelGranted; + + uint8_t ucAvailableAuthTypes; /* Used for AUTH_MODE_AUTO_SWITCH */ + + struct BSS_DESC *prTargetBssDesc; /* For destination */ + + struct STA_RECORD *prTargetStaRec; /* For JOIN Abort */ + + uint32_t u4SleepInterval; + + struct TIMER rBGScanTimer; + + struct TIMER rIbssAloneTimer; + + uint32_t u4PostponeIndStartTime; + + struct TIMER rJoinTimeoutTimer; + + struct TIMER rChannelTimeoutTimer; + + struct TIMER rScanDoneTimer; + + struct TIMER rDeauthDoneTimer; + +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE + struct TIMER rSecModeChangeTimer; +#endif + + uint8_t ucSeqNumOfReqMsg; + uint8_t ucSeqNumOfChReq; + uint8_t ucSeqNumOfScanReq; + + /* Save SeqNum for reporting scan done. + * In order to distinguish seq num and default value, make sure that + * sizeof(u2SeqNumOfScanReport) > sizeof(ucSeqNumOfScanReq). + * Set AIS_SCN_REPORT_SEQ_NOT_SET as default value + */ + uint16_t u2SeqNumOfScanReport; + + uint32_t u4ChGrantedInterval; + + uint8_t ucConnTrialCount; + uint8_t ucConnTrialCountLimit; + + struct PARAM_SCAN_REQUEST_ADV rScanRequest; + uint8_t aucScanIEBuf[MAX_IE_LENGTH]; + + u_int8_t fgIsScanOidAborted; + + /* Pending Request List */ + struct LINK rPendingReqList; + + /* Join Request Timestamp */ + OS_SYSTIME rJoinReqTime; + + /* for cfg80211 REMAIN_ON_CHANNEL support */ + struct AIS_REQ_CHNL_INFO rChReqInfo; + + /* Mgmt tx related. */ + struct AIS_MGMT_TX_REQ_INFO rMgmtTxInfo; + + /* Packet filter for AIS module. */ + uint32_t u4AisPacketFilter; + + /* for roaming target */ + struct PARAM_SSID rRoamingSSID; + + /* Support AP Selection */ + uint8_t ucJoinFailCntAfterScan; + /* end Support AP Selection */ + + /* Scan target channel when device roaming */ + uint8_t fgTargetChnlScanIssued; +}; + +struct AIS_OFF_CHNL_TX_REQ_INFO { + struct LINK_ENTRY rLinkEntry; + struct MSDU_INFO *prMgmtTxMsdu; + u_int8_t fgNoneCckRate; + struct RF_CHANNEL_INFO rChannelInfo; /* Off channel TX. */ + enum ENUM_CHNL_EXT eChnlExt; + /* See if driver should keep at the same channel. */ + u_int8_t fgIsWaitRsp; + uint64_t u8Cookie; /* cookie used to match with supplicant */ + uint32_t u4Duration; /* wait time for tx request */ +}; + +enum WNM_AIS_BSS_TRANSITION { + BSS_TRANSITION_NO_MORE_ACTION, + BSS_TRANSITION_REQ_ROAMING, + BSS_TRANSITION_DISASSOC, + BSS_TRANSITION_MAX_NUM +}; +struct MSG_AIS_BSS_TRANSITION_T { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucToken; + u_int8_t fgNeedResponse; + uint8_t ucValidityInterval; + enum WNM_AIS_BSS_TRANSITION eTransitionType; + uint16_t u2CandListLen; + uint8_t *pucCandList; + uint8_t ucBssIndex; +}; +/******************************************************************************* + * P U B 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(_prAisBssInfo, _eNewMediaState) \ + (_prAisBssInfo->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 struct ADAPTER + *prAdapter, IN struct REG_INFO *prRegInfo, + IN uint8_t ucBssIndex); + +void aisFsmInit(IN struct ADAPTER *prAdapter, uint8_t ucBssIndex); + +void aisFsmUninit(IN struct ADAPTER *prAdapter, uint8_t ucBssIndex); + +bool aisFsmIsInProcessPostpone(IN struct ADAPTER *prAdapter, + uint8_t ucBssIndex); + +bool aisFsmIsInBeaconTimeout(IN struct ADAPTER *prAdapter, + uint8_t ucBssIndex); + +void aisFsmStateInit_JOIN(IN struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc, uint8_t ucBssIndex); + +u_int8_t aisFsmStateInit_RetryJOIN(IN struct ADAPTER + *prAdapter, IN struct STA_RECORD *prStaRec, + uint8_t ucBssIndex); + +void aisFsmStateInit_IBSS_ALONE(IN struct ADAPTER + *prAdapter, uint8_t ucBssIndex); + +void aisFsmStateInit_IBSS_MERGE(IN struct ADAPTER + *prAdapter, struct BSS_DESC *prBssDesc, uint8_t ucBssIndex); + +void aisFsmStateAbort(IN struct ADAPTER *prAdapter, + uint8_t ucReasonOfDisconnect, u_int8_t fgDelayIndication, + uint8_t ucBssIndex); + +void aisFsmStateAbort_JOIN(IN struct ADAPTER *prAdapter, uint8_t ucBssIndex); + +void aisFsmStateAbort_SCAN(IN struct ADAPTER *prAdapter, uint8_t ucBssIndex); + +void aisFsmStateAbort_NORMAL_TR(IN struct ADAPTER + *prAdapter, uint8_t ucBssIndex); + +void aisFsmStateAbort_IBSS(IN struct ADAPTER *prAdapter, uint8_t ucBssIndex); + +void aisFsmSteps(IN struct ADAPTER *prAdapter, + enum ENUM_AIS_STATE eNextState, uint8_t ucBssIndex); + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Handling */ +/*----------------------------------------------------------------------------*/ +void aisFsmRunEventScanDone(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void aisFsmRunEventAbort(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void aisFsmRunEventJoinComplete(IN struct ADAPTER + *prAdapter, IN struct MSG_HDR *prMsgHdr); + +enum ENUM_AIS_STATE aisFsmJoinCompleteAction( + IN struct ADAPTER *prAdapter, IN struct MSG_HDR *prMsgHdr); + +void aisFsmRunEventFoundIBSSPeer(IN struct ADAPTER + *prAdapter, IN struct MSG_HDR *prMsgHdr); + +void aisFsmRunEventRemainOnChannel(IN struct ADAPTER + *prAdapter, IN struct MSG_HDR *prMsgHdr); + +void aisFsmRunEventCancelRemainOnChannel(IN struct ADAPTER + *prAdapter, IN struct MSG_HDR *prMsgHdr); + +/*----------------------------------------------------------------------------*/ +/* Handling for Ad-Hoc Network */ +/*----------------------------------------------------------------------------*/ +void aisFsmCreateIBSS(IN struct ADAPTER *prAdapter, uint8_t ucBssIndex); + +void aisFsmMergeIBSS(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +/*----------------------------------------------------------------------------*/ +/* Handling of Incoming Mailbox Message from CNM */ +/*----------------------------------------------------------------------------*/ +void aisFsmRunEventChGrant(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +/*----------------------------------------------------------------------------*/ +/* Generating Outgoing Mailbox Message to CNM */ +/*----------------------------------------------------------------------------*/ +void aisFsmReleaseCh(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIndex); + +/*----------------------------------------------------------------------------*/ +/* Event Indication */ +/*----------------------------------------------------------------------------*/ +void +aisIndicationOfMediaStateToHost(IN struct ADAPTER + *prAdapter, + enum ENUM_PARAM_MEDIA_STATE eConnectionState, + u_int8_t fgDelayIndication, + uint8_t ucBssIndex); + +void aisPostponedEventOfDisconnTimeout(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +void aisUpdateBssInfoForJOIN(IN struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + struct SW_RFB *prAssocRspSwRfb); + +void aisUpdateBssInfoForCreateIBSS(IN struct ADAPTER *prAdapter, + uint8_t ucBssIndex); + +void aisUpdateBssInfoForMergeIBSS(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +u_int8_t aisValidateProbeReq(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint8_t ucBssIndex, + OUT uint32_t *pu4ControlFlags); + +uint32_t +aisFsmRunEventMgmtFrameTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +/*----------------------------------------------------------------------------*/ +/* Disconnection Handling */ +/*----------------------------------------------------------------------------*/ +void aisFsmDisconnect(IN struct ADAPTER *prAdapter, + IN u_int8_t fgDelayIndication, + IN uint8_t ucBssIndex); + +/*----------------------------------------------------------------------------*/ +/* Event Handling */ +/*----------------------------------------------------------------------------*/ +void aisBssBeaconTimeout(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +void aisBssBeaconTimeout_impl(IN struct ADAPTER *prAdapter, + IN uint8_t ucBcnTimeoutReason, IN uint8_t ucDisconnectReason, + IN uint8_t ucBssIndex); + +void aisBssLinkDown(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE +void aisBssSecurityChanged(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); +#endif + +uint32_t +aisDeauthXmitComplete(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); +uint32_t +aisDeauthXmitCompleteBss(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +#if CFG_SUPPORT_ROAMING +void aisFsmRunEventRoamingDiscovery( + IN struct ADAPTER *prAdapter, + uint32_t u4ReqScan, + uint8_t ucBssIndex); + +enum ENUM_AIS_STATE aisFsmRoamingScanResultsUpdate( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +void aisFsmRoamingDisconnectPrevAP(IN struct ADAPTER + *prAdapter, + IN struct STA_RECORD *prTargetStaRec); + +void aisUpdateBssInfoForRoamingAP(IN struct ADAPTER + *prAdapter, IN struct STA_RECORD *prStaRec, + IN struct SW_RFB *prAssocRspSwRfb); +#endif /*CFG_SUPPORT_ROAMING */ + +/*----------------------------------------------------------------------------*/ +/* Timeout Handling */ +/*----------------------------------------------------------------------------*/ +void aisFsmRunEventBGSleepTimeOut(IN struct ADAPTER + *prAdapter, unsigned long ulParamPtr); + +void aisFsmRunEventIbssAloneTimeOut(IN struct ADAPTER + *prAdapter, unsigned long ulParamPtr); + +void aisFsmRunEventJoinTimeout(IN struct ADAPTER *prAdapter, + unsigned long ulParamPtr); + +void aisFsmRunEventChannelTimeout(IN struct ADAPTER + *prAdapter, unsigned long ulParamPtr); + +void aisFsmRunEventDeauthTimeout(IN struct ADAPTER + *prAdapter, unsigned long ulParamPtr); + +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE +void aisFsmRunEventSecModeChangeTimeout(IN struct ADAPTER + *prAdapter, unsigned long ulParamPtr); +#endif + +/*----------------------------------------------------------------------------*/ +/* OID/IOCTL Handling */ +/*----------------------------------------------------------------------------*/ +void aisFsmScanRequest(IN struct ADAPTER *prAdapter, + IN struct PARAM_SSID *prSsid, IN uint8_t *pucIe, + IN uint32_t u4IeLength, + IN uint8_t ucBssIndex); + +void +aisFsmScanRequestAdv(IN struct ADAPTER *prAdapter, + IN struct PARAM_SCAN_REQUEST_ADV *prRequestIn); + +/*----------------------------------------------------------------------------*/ +/* Internal State Checking */ +/*----------------------------------------------------------------------------*/ +u_int8_t aisFsmIsRequestPending(IN struct ADAPTER *prAdapter, + IN enum ENUM_AIS_REQUEST_TYPE eReqType, + IN u_int8_t bRemove, + IN uint8_t ucBssIndex); + +void aisFsmRemoveRoamingRequest( + IN struct ADAPTER *prAdapter, IN uint8_t ucBssIndex); + +struct AIS_REQ_HDR *aisFsmGetNextRequest(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +u_int8_t aisFsmInsertRequest(IN struct ADAPTER *prAdapter, + IN enum ENUM_AIS_REQUEST_TYPE eReqType, + IN uint8_t ucBssIndex); + +u_int8_t aisFsmInsertRequestToHead(IN struct ADAPTER *prAdapter, + IN enum ENUM_AIS_REQUEST_TYPE eReqType, + IN uint8_t ucBssIndex); + +u_int8_t aisFsmClearRequest(IN struct ADAPTER *prAdapter, + IN enum ENUM_AIS_REQUEST_TYPE eReqType, + IN uint8_t ucBssIndex); + +void aisFsmFlushRequest(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +uint32_t +aisFuncTxMgmtFrame(IN struct ADAPTER *prAdapter, + IN struct AIS_MGMT_TX_REQ_INFO *prMgmtTxReqInfo, + IN struct MSDU_INFO *prMgmtTxMsdu, IN uint64_t u8Cookie, + IN uint8_t ucBssIndex); + +void aisFsmRunEventMgmtFrameTx(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +#if CFG_SUPPORT_NCHO +void aisFsmRunEventNchoActionFrameTx(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); +#endif + +void aisFuncValidateRxActionFrame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +void aisFsmRunEventBssTransition(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void aisFsmRunEventCancelTxWait(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +enum ENUM_AIS_STATE aisFsmStateSearchAction( + IN struct ADAPTER *prAdapter, uint8_t ucBssIndex); +#if defined(CFG_TEST_MGMT_FSM) && (CFG_TEST_MGMT_FSM != 0) +void aisTest(void); +#endif /* CFG_TEST_MGMT_FSM */ + +/* Support AP Selection */ +void aisRefreshFWKBlacklist(struct ADAPTER *prAdapter); +struct AIS_BLACKLIST_ITEM *aisAddBlacklist(struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc); +void aisRemoveBlackList(struct ADAPTER *prAdapter, struct BSS_DESC *prBssDesc); +void aisRemoveTimeoutBlacklist(struct ADAPTER *prAdapter); +struct AIS_BLACKLIST_ITEM *aisQueryBlackList(struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc); +/* end Support AP Selection */ + +/* Support 11K */ +void aisResetNeighborApList(struct ADAPTER *prAdapter, + uint8_t ucBssIndex); +#if CFG_SUPPORT_802_11K +void aisCollectNeighborAP(struct ADAPTER *prAdapter, uint8_t *pucApBuf, + uint16_t u2ApBufLen, uint8_t ucValidInterval, + uint8_t ucBssIndex); +#endif +void aisSendNeighborRequest(struct ADAPTER *prAdapter, + uint8_t ucBssIndex); +/* end Support 11K */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#define AIS_DEFAULT_INDEX (0) + +struct AIS_FSM_INFO *aisGetAisFsmInfo( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +struct AIS_SPECIFIC_BSS_INFO *aisGetAisSpecBssInfo( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +struct BSS_TRANSITION_MGT_PARAM_T * + aisGetBTMParam( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +struct BSS_INFO *aisGetConnectedBssInfo( + IN struct ADAPTER *prAdapter); + +struct BSS_INFO *aisGetAisBssInfo( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +struct STA_RECORD *aisGetStaRecOfAP( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +struct BSS_DESC *aisGetTargetBssDesc( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +struct STA_RECORD *aisGetTargetStaRec( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +uint8_t aisGetTargetBssDescChannel( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE +struct TIMER *aisGetSecModeChangeTimer( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); +#endif + +struct TIMER *aisGetScanDoneTimer( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +enum ENUM_AIS_STATE aisGetCurrState( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +struct CONNECTION_SETTINGS * + aisGetConnSettings( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +struct GL_WPA_INFO *aisGetWpaInfo( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +u_int8_t aisGetWapiMode( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +enum ENUM_PARAM_AUTH_MODE aisGetAuthMode( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +enum ENUM_PARAM_OP_MODE aisGetOPMode( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +enum ENUM_WEP_STATUS aisGetEncStatus( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +struct IEEE_802_11_MIB *aisGetMib( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +struct ROAMING_INFO *aisGetRoamingInfo( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +struct PARAM_BSSID_EX *aisGetCurrBssId( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +#if CFG_SUPPORT_PASSPOINT +struct HS20_INFO *aisGetHS20Info( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); +#endif + +struct RADIO_MEASUREMENT_REQ_PARAMS *aisGetRmReqParam( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +struct RADIO_MEASUREMENT_REPORT_PARAMS * + aisGetRmReportParam( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +struct WMM_INFO * + aisGetWMMInfo( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +#ifdef CFG_SUPPORT_REPLAY_DETECTION +struct GL_DETECT_REPLAY_INFO * + aisGetDetRplyInfo( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); +#endif + +uint8_t * + aisGetFsmState( + IN enum ENUM_AIS_STATE); + +struct FT_IES * + aisGetFtIe( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +struct cfg80211_ft_event_params * + aisGetFtEventParam( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +#endif /* _AIS_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/ap_selection.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/ap_selection.h new file mode 100644 index 0000000000000..fb45704a6f6a6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/ap_selection.h @@ -0,0 +1,78 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +#ifndef _AP_SELECTION_H +#define _AP_SELECTION_H + +/* Support AP Selection */ +#if (CFG_SUPPORT_802_11AX == 1) +#define AX_SEL_DEF_WEIGHT (0) +#define AX_SEL_DEF_DIVIDER (1) +#endif + +enum ROAM_TYPE { + ROAM_TYPE_RCPI, + ROAM_TYPE_PER, + ROAM_TYPE_NUM +}; + +struct BSS_DESC *scanSearchBssDescByScoreForAis(struct ADAPTER *prAdapter, + enum ENUM_ROAMING_REASON eRoamReason, uint8_t ucBssIndex); +void scanGetCurrentEssChnlList(struct ADAPTER *prAdapter, uint8_t ucBssIndex); +uint8_t scanCheckNeedDriverRoaming( + struct ADAPTER *prAdapter, uint8_t ucBssIndex); +uint8_t scanBeaconTimeoutFilterPolicyForAis(struct ADAPTER *prAdapter, + uint8_t ucBssIndex); +u_int8_t scanApOverload(uint16_t status, uint16_t reason); + +#endif + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/assoc.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/assoc.h new file mode 100644 index 0000000000000..8457f5d8547a7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/assoc.h @@ -0,0 +1,157 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + + +#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 */ +/*----------------------------------------------------------------------------*/ +uint32_t assocSendReAssocReqFrame(IN struct ADAPTER + *prAdapter, IN struct STA_RECORD *prStaRec); + +uint32_t assocCheckTxReAssocReqFrame(IN struct ADAPTER + *prAdapter, IN struct MSDU_INFO *prMsduInfo); + +uint32_t assocCheckTxReAssocRespFrame(IN struct ADAPTER + *prAdapter, IN struct MSDU_INFO *prMsduInfo); + +uint32_t +assocCheckRxReAssocRspFrameStatus(IN struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfb, + OUT uint16_t *pu2StatusCode); + +uint32_t assocSendDisAssocFrame(IN struct ADAPTER + *prAdapter, IN struct STA_RECORD *prStaRec, + IN uint16_t u2ReasonCode); + +uint32_t +assocProcessRxDisassocFrame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint8_t aucBSSID[], + OUT uint16_t *pu2ReasonCode); + +uint32_t assocProcessRxAssocReqFrame(IN struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfb, + OUT uint16_t *pu2StatusCode); + +uint32_t assocSendReAssocRespFrame(IN struct ADAPTER + *prAdapter, IN struct STA_RECORD *prStaRec); + +uint16_t assocBuildCapabilityInfo(IN struct ADAPTER + *prAdapter, IN struct STA_RECORD *prStaRec); + +uint16_t assoc_get_nonwfa_vend_ie_len(struct ADAPTER *prAdapter, + uint8_t ucBssIndex); + +void assoc_build_nonwfa_vend_ie(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void assocGenerateMDIE(IN struct ADAPTER *prAdapter, + IN OUT struct MSDU_INFO *prMsduInfo); + +uint32_t assocCalculateConnIELen(struct ADAPTER *prAdapter, uint8_t ucBssIdx, + struct STA_RECORD *prStaRec); + +void assocGenerateConnIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +#endif /* _ASSOC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/auth.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/auth.h new file mode 100644 index 0000000000000..e318d605a99ac --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/auth.h @@ -0,0 +1,182 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + + +#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 struct ADAPTER *prAdapter, + IN OUT struct MSDU_INFO *prMsduInfo); + +#if !CFG_SUPPORT_AAA +uint32_t authSendAuthFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN uint16_t u2TransactionSeqNum); +#else +uint32_t +authSendAuthFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN uint8_t uBssIndex, + IN struct SW_RFB *prFalseAuthSwRfb, + IN uint16_t u2TransactionSeqNum, + IN uint16_t u2StatusCode); +#endif /* CFG_SUPPORT_AAA */ + +uint32_t authCheckTxAuthFrame(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN uint16_t u2TransactionSeqNum); + +uint32_t authCheckRxAuthFrameTransSeq(IN struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfb); + +uint32_t +authCheckRxAuthFrameStatus(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint16_t u2TransactionSeqNum, + OUT uint16_t *pu2StatusCode); + +void authHandleIEChallengeText(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb, struct IE_HDR *prIEHdr); + +uint32_t authProcessRxAuth2_Auth4Frame(IN struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfb); + +uint32_t +authSendDeauthFrame(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct STA_RECORD *prStaRec, + IN struct SW_RFB *prClassErrSwRfb, IN uint16_t u2ReasonCode, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler); + +uint32_t authProcessRxDeauthFrame(IN struct SW_RFB *prSwRfb, + IN uint8_t aucBSSID[], OUT uint16_t *pu2ReasonCode); + +uint32_t +authProcessRxAuth1Frame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint8_t aucExpectedBSSID[], + IN uint16_t u2ExpectedAuthAlgNum, + IN uint16_t u2ExpectedTransSeqNum, + OUT uint16_t *pu2ReturnStatusCode); +uint32_t +authProcessRxAuthFrame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN struct BSS_INFO *prBssInfo, + OUT uint16_t *pu2ReturnStatusCode); + +void authAddMDIE(IN struct ADAPTER *prAdapter, + IN OUT struct MSDU_INFO *prMsduInfo); + +uint32_t authCalculateRSNIELen(struct ADAPTER *prAdapter, uint8_t ucBssIdx, + struct STA_RECORD *prStaRec); + +void authAddRSNIE(IN struct ADAPTER *prAdapter, + IN OUT struct MSDU_INFO *prMsduInfo); + +uint32_t authAddRSNIE_impl(IN struct ADAPTER *prAdapter, + IN OUT struct MSDU_INFO *prMsduInfo); + +void authHandleFtIEs(struct ADAPTER *prAdapter, struct SW_RFB *prSwRfb, + struct IE_HDR *prIEHdr); + +#endif /* _AUTH_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/bow_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/bow_fsm.h new file mode 100644 index 0000000000000..51c5ff6987969 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/bow_fsm.h @@ -0,0 +1,189 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +#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 +******************************************************************************** +*/ + +enum ENUM_BOW_STATE { + 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 +}; + +struct BOW_FSM_INFO { + /* Channel Privilege */ + u_int8_t fgIsChannelRequested; + u_int8_t fgIsChannelGranted; + uint32_t u4ChGrantedInterval; + + uint8_t ucPrimaryChannel; + enum ENUM_BAND eBand; + uint16_t u2BeaconInterval; + + struct STA_RECORD *prTargetStaRec; + struct BSS_DESC *prTargetBssDesc; /* For destination */ + + uint8_t aucPeerAddress[6]; + uint8_t ucBssIndex; /* Assume there is only 1 BSS for BOW */ + uint8_t ucRole; /* Initiator or responder */ + uint8_t ucAvailableAuthTypes; /* Used for AUTH_MODE_AUTO_SWITCH */ + + u_int8_t fgSupportQoS; + + /* Sequence number of requested message. */ + uint8_t ucSeqNumOfChReq; + uint8_t ucSeqNumOfReqMsg; + uint8_t ucSeqNumOfScnMsg; + uint8_t ucSeqNumOfScanReq; + uint8_t ucSeqNumOfCancelMsg; + + /* Timer */ + struct TIMER rStartingBeaconTimer; /* For device discovery time of each discovery request from user. */ + struct TIMER rChGrantedTimer; + + /* can be deleted? */ + struct TIMER rIndicationOfDisconnectTimer; + +}; + +/******************************************************************************* +* P U B 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(_prBssInfo, _eNewMediaState) \ + (_prBssInfo->eConnectionState = (_eNewMediaState)) + /* (_prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX].eConnectionState = (_eNewMediaState)); */ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/bss.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/bss.h new file mode 100644 index 0000000000000..f82f15dbda326 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/bss.h @@ -0,0 +1,300 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/*! \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. + */ + + +#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 + ******************************************************************************* + */ +#include "wlan_def.h" +extern const uint8_t *apucNetworkType[NETWORK_TYPE_NUM]; + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define BSS_DEFAULT_NUM KAL_BSS_NUM + +/* Define how many concurrent operation networks. */ +#define BSS_P2P_NUM KAL_P2P_NUM + +#if (BSS_P2P_NUM > MAX_BSSID_NUM) +#error Exceed HW capability (KAL_BSS_NUM or KAL_P2P_NUM)!! +#endif + +/* 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) + +#define MAX_BSS_INDEX HW_BSSID_NUM +#define P2P_DEV_BSS_INDEX MAX_BSS_INDEX + +#define IS_BSS_ALIVE(_prAdapter, _prBssInfo) \ + (_prBssInfo->fgIsInUse && \ + _prBssInfo->fgIsNetActive && \ + (_prBssInfo->eConnectionState == MEDIA_STATE_CONNECTED || \ + (_prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT && \ + IS_NET_PWR_STATE_ACTIVE(_prAdapter, \ + _prBssInfo->ucBssIndex)))) + +#define IS_BSS_NOT_ALIVE(_prAdapter, _prBssInfo) \ + (!IS_BSS_ALIVE(_prAdapter, _prBssInfo)) + +/******************************************************************************* + * 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 IS_BSS_INDEX_VALID(_ucBssIndex) ((_ucBssIndex) <= P2P_DEV_BSS_INDEX) + +#define GET_BSS_INFO_BY_INDEX(_prAdapter, _ucBssIndex) \ + ((_prAdapter)->aprBssInfo[(_ucBssIndex)]) + +#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 */ +/*----------------------------------------------------------------------------*/ +struct STA_RECORD * +bssCreateStaRecFromBssDesc(IN struct ADAPTER *prAdapter, + IN enum ENUM_STA_TYPE eStaType, IN uint8_t uBssIndex, + IN struct BSS_DESC *prBssDesc); + +void bssComposeNullFrame(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuffer, IN struct STA_RECORD *prStaRec); + +void +bssComposeQoSNullFrame(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuffer, IN struct STA_RECORD *prStaRec, + IN uint8_t ucUP, IN u_int8_t fgSetEOSP); + +uint32_t +bssSendNullFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler); + +uint32_t +bssSendQoSNullFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, IN uint8_t ucUP, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler); + +void bssDumpBssInfo(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +void bssDetermineApBssInfoPhyTypeSet(IN struct ADAPTER + *prAdapter, IN u_int8_t fgIsPureAp, + OUT struct BSS_INFO *prBssInfo); +int8_t bssGetRxNss(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc); +#if CFG_SUPPORT_IOT_AP_BLACKLIST +uint32_t bssGetIotApAction(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc); +#endif +/*----------------------------------------------------------------------------*/ +/* Routines for both IBSS(AdHoc) and BSS(AP) */ +/*----------------------------------------------------------------------------*/ +void bssGenerateExtSuppRate_IE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +void +bssBuildBeaconProbeRespFrameCommonIEs(IN struct MSDU_INFO + *prMsduInfo, + IN struct BSS_INFO *prBssInfo, + IN uint8_t *pucDestAddr); + +void +bssComposeBeaconProbeRespFrameHeaderAndFF( + IN uint8_t *pucBuffer, + IN uint8_t *pucDestAddr, + IN uint8_t *pucOwnMACAddress, + IN uint8_t *pucBSSID, IN uint16_t u2BeaconInterval, + IN uint16_t u2CapInfo); + +uint32_t +bssSendBeaconProbeResponse(IN struct ADAPTER *prAdapter, + IN uint8_t uBssIndex, IN uint8_t *pucDestAddr, + IN uint32_t u4ControlFlags); + +uint32_t bssProcessProbeRequest(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +void bssInitializeClientList(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo); + +void bssAddClient(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct STA_RECORD *prStaRec); + +u_int8_t bssRemoveClient(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct STA_RECORD *prStaRec); + +struct STA_RECORD *bssRemoveClientByMac(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN uint8_t *pucMac); + +struct STA_RECORD *bssGetClientByMac(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN uint8_t *pucMac); + +struct STA_RECORD *bssRemoveHeadClient(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo); + +uint32_t bssGetClientCount(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo); + +void bssDumpClientList(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo); + +void bssCheckClientList(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo); + +/*----------------------------------------------------------------------------*/ +/* Routines for IBSS(AdHoc) only */ +/*----------------------------------------------------------------------------*/ +void +ibssProcessMatchedBeacon(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct BSS_DESC *prBssDesc, IN uint8_t ucRCPI); + +uint32_t ibssCheckCapabilityForAdHocMode( + IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc, + IN uint8_t uBssIndex); + +void ibssInitForAdHoc(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo); + +uint32_t bssUpdateBeaconContent(IN struct ADAPTER + *prAdapter, IN uint8_t uBssIndex); + +/*----------------------------------------------------------------------------*/ +/* Routines for BSS(AP) only */ +/*----------------------------------------------------------------------------*/ +void bssInitForAP(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, IN u_int8_t fgIsRateUpdate); + +void bssUpdateDTIMCount(IN struct ADAPTER *prAdapter, + IN uint8_t uBssIndex); + +void bssSetTIMBitmap(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, IN uint16_t u2AssocId); + +/*link function to p2p module for txBcnIETable*/ + +/* WMM-2.2.2 WMM ACI to AC coding */ +enum ENUM_ACI { + ACI_BE = 0, + ACI_BK = 1, + ACI_VI = 2, + ACI_VO = 3, + ACI_NUM +}; + +enum ENUM_AC_PRIORITY { + AC_BK_PRIORITY = 0, + AC_BE_PRIORITY, + AC_VI_PRIORITY, + AC_VO_PRIORITY +}; + +#if (CFG_SUPPORT_HE_ER == 1) +struct EVENT_ER_TX_MODE { + uint8_t ucBssInfoIdx; + uint8_t ucErMode; +}; + +void bssProcessErTxModeEvent(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +#endif + +#endif /* _BSS_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/cnm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/cnm.h new file mode 100644 index 0000000000000..aa9401e0fa3b3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/cnm.h @@ -0,0 +1,417 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3 + * /include/mgmt/cnm.h#1 + */ + +/*! \file "cnm.h" + * \brief + */ + + +#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 + ******************************************************************************* + */ +#include "nic_cmd_event.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#if CFG_SUPPORT_DBDC +#define DBDC_5G_WMM_INDEX 0 +#define DBDC_2G_WMM_INDEX 1 +#endif +#define HW_WMM_NUM (prAdapter->ucWmmSetNum) +#define MAX_HW_WMM_INDEX (HW_WMM_NUM - 1) +#define DEFAULT_HW_WMM_INDEX MAX_HW_WMM_INDEX +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +#if (CFG_SUPPORT_IDC_CH_SWITCH == 1) +enum ENUM_CH_SWITCH_TYPE { + CH_SWITCH_2G, /* Default */ + CH_SWITCH_5G, + CH_SWITCH_NUM +}; +#endif + +struct MSG_CH_REQ { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucBssIndex; + uint8_t ucTokenID; + uint8_t ucPrimaryChannel; + enum ENUM_CHNL_EXT eRfSco; + enum ENUM_BAND eRfBand; + + /* To support 80/160MHz bandwidth */ + enum ENUM_CHANNEL_WIDTH eRfChannelWidth; + + uint8_t ucRfCenterFreqSeg1; /* To support 80/160MHz bandwidth */ + uint8_t ucRfCenterFreqSeg2; /* To support 80/160MHz bandwidth */ + enum ENUM_CH_REQ_TYPE eReqType; + uint32_t u4MaxInterval; /* In unit of ms */ + enum ENUM_DBDC_BN eDBDCBand; +}; + +struct MSG_CH_ABORT { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucBssIndex; + uint8_t ucTokenID; + enum ENUM_DBDC_BN eDBDCBand; +}; + +struct MSG_CH_GRANT { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucBssIndex; + uint8_t ucTokenID; + uint8_t ucPrimaryChannel; + enum ENUM_CHNL_EXT eRfSco; + enum ENUM_BAND eRfBand; + + /* To support 80/160MHz bandwidth */ + enum ENUM_CHANNEL_WIDTH eRfChannelWidth; + + uint8_t ucRfCenterFreqSeg1; /* To support 80/160MHz bandwidth */ + uint8_t ucRfCenterFreqSeg2; /* To support 80/160MHz bandwidth */ + enum ENUM_CH_REQ_TYPE eReqType; + uint32_t u4GrantInterval; /* In unit of ms */ + enum ENUM_DBDC_BN eDBDCBand; +}; + +struct MSG_CH_REOCVER { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucBssIndex; + uint8_t ucTokenID; + uint8_t ucPrimaryChannel; + enum ENUM_CHNL_EXT eRfSco; + enum ENUM_BAND eRfBand; + + /* To support 80/160MHz bandwidth */ + enum ENUM_CHANNEL_WIDTH eRfChannelWidth; + + uint8_t ucRfCenterFreqSeg1; /* To support 80/160MHz bandwidth */ + uint8_t ucRfCenterFreqSeg2; /* To support 80/160MHz bandwidth */ + enum ENUM_CH_REQ_TYPE eReqType; +}; + +struct CNM_INFO { + u_int8_t fgChGranted; + uint8_t ucBssIndex; + uint8_t ucTokenID; +}; + +#if CFG_ENABLE_WIFI_DIRECT +/* Moved from p2p_fsm.h */ +struct DEVICE_TYPE { + uint16_t u2CategoryId; /* Category ID */ + uint8_t aucOui[4]; /* OUI */ + uint16_t u2SubCategoryId; /* Sub Category ID */ +} __KAL_ATTRIB_PACKED__; +#endif + +#if CFG_SUPPORT_DBDC +enum ENUM_CNM_DBDC_MODE { + /* A/G traffic separate by WMM, but both + * TRX on band 0, CANNOT enable DBDC + */ + ENUM_DBDC_MODE_DISABLED, + + /* A/G traffic separate by WMM, WMM0/1 + * TRX on band 0/1, CANNOT disable DBDC + */ + ENUM_DBDC_MODE_STATIC, + + /* Automatically enable/disable DBDC, + * setting just like static/disable mode + */ + ENUM_DBDC_MODE_DYNAMIC, + + ENUM_DBDC_MODE_NUM +}; + +enum ENUM_CNM_DBDC_SWITCH_MECHANISM { /* When DBDC available in dynamic DBDC */ + /* Switch to DBDC when available (less latency) */ + ENUM_DBDC_SWITCH_MECHANISM_LATENCY_MODE, + + /* Switch to DBDC when DBDC T-put > MCC T-put */ + ENUM_DBDC_SWITCH_MECHANISM_THROUGHPUT_MODE, + + ENUM_DBDC_SWITCH_MECHANISM_NUM +}; +#endif /* CFG_SUPPORT_DBDC */ + +enum ENUM_CNM_NETWORK_TYPE_T { + ENUM_CNM_NETWORK_TYPE_OTHER, + ENUM_CNM_NETWORK_TYPE_AIS, + ENUM_CNM_NETWORK_TYPE_P2P_GC, + ENUM_CNM_NETWORK_TYPE_P2P_GO, + ENUM_CNM_NETWORK_TYPE_NUM +}; + +/******************************************************************************* + * P U B 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 CNM_CH_GRANTED_FOR_BSS(_prAdapter, _ucBssIndex) \ + ((_prAdapter)->rCnmInfo.fgChGranted && \ + (_prAdapter)->rCnmInfo.ucBssIndex == (_ucBssIndex)) + +/* True if our TxNss > 1 && peer support 2ss rate && peer no Rx limit. */ +#define IS_CONNECTION_NSS2(prBssInfo, prStaRec) \ + ((((prBssInfo)->ucOpTxNss > 1) && \ + ((prStaRec)->aucRxMcsBitmask[1] != 0x00) \ + && (((prStaRec)->u2HtCapInfo & HT_CAP_INFO_SM_POWER_SAVE) != 0)) || \ + (((prBssInfo)->ucOpTxNss > 1) && ((((prStaRec)->u2VhtRxMcsMap \ + & BITS(2, 3)) >> 2) != BITS(0, 1)) && ((((prStaRec)->ucVhtOpMode \ + & VHT_OP_MODE_RX_NSS) >> VHT_OP_MODE_RX_NSS_OFFSET) > 0))) + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +void cnmInit(struct ADAPTER *prAdapter); + +void cnmUninit(struct ADAPTER *prAdapter); + +void cnmChMngrRequestPrivilege(struct ADAPTER *prAdapter, + struct MSG_HDR *prMsgHdr); + +void cnmChMngrAbortPrivilege(struct ADAPTER *prAdapter, + struct MSG_HDR *prMsgHdr); + +void cnmChMngrHandleChEvent(struct ADAPTER *prAdapter, + struct WIFI_EVENT *prEvent); + +#if (CFG_SUPPORT_DFS_MASTER == 1) +void cnmRadarDetectEvent(struct ADAPTER *prAdapter, + struct WIFI_EVENT *prEvent); + +void cnmCsaDoneEvent(struct ADAPTER *prAdapter, + struct WIFI_EVENT *prEvent); + +#if (CFG_SUPPORT_IDC_CH_SWITCH == 1) +uint8_t cnmIdcCsaReq(IN struct ADAPTER *prAdapter, + IN uint8_t ch_num, IN uint8_t ucRoleIdx); + +void cnmIdcDetectHandler(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +#endif +#endif + +uint8_t cnmSapChannelSwitchReq(IN struct ADAPTER *prAdapter, + IN struct RF_CHANNEL_INFO *prRfChannelInfo, + IN uint8_t ucRoleIdx); + +u_int8_t cnmPreferredChannel(struct ADAPTER *prAdapter, enum ENUM_BAND *prBand, + uint8_t *pucPrimaryChannel, enum ENUM_CHNL_EXT *prBssSCO); + +u_int8_t cnmAisInfraChannelFixed(struct ADAPTER *prAdapter, + enum ENUM_BAND *prBand, uint8_t *pucPrimaryChannel); + +void cnmAisInfraConnectNotify(struct ADAPTER *prAdapter); + +u_int8_t cnmAisIbssIsPermitted(struct ADAPTER *prAdapter); + +u_int8_t cnmP2PIsPermitted(struct ADAPTER *prAdapter); + +u_int8_t cnmBowIsPermitted(struct ADAPTER *prAdapter); + +u_int8_t cnmBss40mBwPermitted(struct ADAPTER *prAdapter, uint8_t ucBssIndex); + +u_int8_t cnmBss80mBwPermitted(struct ADAPTER *prAdapter, uint8_t ucBssIndex); + +uint8_t cnmGetBssMaxBw(struct ADAPTER *prAdapter, uint8_t ucBssIndex); + +uint8_t cnmGetBssMaxBwToChnlBW(struct ADAPTER *prAdapter, uint8_t ucBssIndex); + +struct BSS_INFO *cnmGetBssInfoAndInit(struct ADAPTER *prAdapter, + enum ENUM_NETWORK_TYPE eNetworkType, u_int8_t fgIsP2pDevice); + +void cnmFreeBssInfo(struct ADAPTER *prAdapter, struct BSS_INFO *prBssInfo); +#if CFG_SUPPORT_CHNL_CONFLICT_REVISE +u_int8_t cnmAisDetectP2PChannel(struct ADAPTER *prAdapter, + enum ENUM_BAND *prBand, uint8_t *pucPrimaryChannel); +#endif + +u_int8_t cnmWmmIndexDecision(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo); +void cnmFreeWmmIndex(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo); + +#if CFG_SUPPORT_DBDC +void cnmInitDbdcSetting(IN struct ADAPTER *prAdapter); + +uint32_t cnmUpdateDbdcSetting(IN struct ADAPTER *prAdapter, + IN u_int8_t fgDbdcEn); + +uint8_t cnmGetDbdcBwCapability( + struct ADAPTER *prAdapter, + uint8_t ucBssIndex +); + +void cnmDbdcPreConnectionEnableDecision( + IN struct ADAPTER *prAdapter, + IN uint8_t ucChangedBssIndex, + IN enum ENUM_BAND eRfBand, + IN uint8_t ucPrimaryChannel, + IN uint8_t ucWmmQueIdx +); + +void cnmDbdcRuntimeCheckDecision(IN struct ADAPTER *prAdapter, + IN uint8_t ucChangedBssIndex); +void cnmDbdcGuardTimerCallback(IN struct ADAPTER *prAdapter, + IN unsigned long plParamPtr); +void cnmDbdcEventHwSwitchDone(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +u_int8_t cnmDBDCIsReqPeivilegeLock(void); +#endif /*CFG_SUPPORT_DBDC*/ + +enum ENUM_CNM_NETWORK_TYPE_T cnmGetBssNetworkType(struct BSS_INFO *prBssInfo); + +u_int8_t cnmSapIsActive(IN struct ADAPTER *prAdapter); + +u_int8_t cnmSapIsConcurrent(IN struct ADAPTER *prAdapter); + +struct BSS_INFO *cnmGetSapBssInfo(IN struct ADAPTER *prAdapter); + +void cnmOpModeGetTRxNss( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + OUT uint8_t *pucOpRxNss, + OUT uint8_t *pucOpTxNss +); +#if CFG_SUPPORT_SMART_GEAR +void cnmEventSGStatus( + IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent +); +#endif + +void cnmOpmodeEventHandler( + IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent +); + +u_int8_t cnmP2pIsActive(IN struct ADAPTER *prAdapter); + +struct BSS_INFO *cnmGetP2pBssInfo(IN struct ADAPTER *prAdapter); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#ifndef _lint +/* We don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + * We'll need this to guarantee the same member order in different structures + * to simply handling effort in some functions. + */ +static __KAL_INLINE__ void cnmMsgDataTypeCheck(void) +{ + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSG_CH_GRANT, rMsgHdr) + == 0); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSG_CH_GRANT, rMsgHdr) + == OFFSET_OF(struct MSG_CH_REOCVER, rMsgHdr)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSG_CH_GRANT, ucBssIndex) + == OFFSET_OF(struct MSG_CH_REOCVER, ucBssIndex)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSG_CH_GRANT, ucTokenID) + == OFFSET_OF(struct MSG_CH_REOCVER, ucTokenID)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSG_CH_GRANT, ucPrimaryChannel) + == OFFSET_OF(struct MSG_CH_REOCVER, ucPrimaryChannel)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSG_CH_GRANT, eRfSco) + == OFFSET_OF(struct MSG_CH_REOCVER, eRfSco)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSG_CH_GRANT, eRfBand) + == OFFSET_OF(struct MSG_CH_REOCVER, eRfBand)); + + DATA_STRUCT_INSPECTING_ASSERT( + OFFSET_OF(struct MSG_CH_GRANT, eReqType) + == OFFSET_OF(struct MSG_CH_REOCVER, eReqType)); +} +#endif /* _lint */ + +#endif /* _CNM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/cnm_mem.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/cnm_mem.h new file mode 100644 index 0000000000000..fe06b10fa694f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/cnm_mem.h @@ -0,0 +1,1213 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + + +#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 + ******************************************************************************* + */ +#include "qosmap.h" +/******************************************************************************* + * 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 */ +/* 7 to the power of 2 = 128 */ +#define MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2 7 + +/* 5 to the power of 2 = 32 */ +#define MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2 5 + +/* 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) \ + ((uint32_t)(n) << MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2) +#define MSG_BUF_BLOCKS_SIZE(n) \ + ((uint32_t)(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 + +/* Number of SW queues in each STA_REC: AC0~AC4 */ +#define STA_WAIT_QUEUE_NUM 5 + +/* Number of SC caches in each STA_REC: AC0~AC4 */ +#define SC_CACHE_INDEX_NUM 5 + +/* P2P related definitions */ +#if CFG_ENABLE_WIFI_DIRECT +/* Moved from p2p_fsm.h */ +#define WPS_ATTRI_MAX_LEN_DEVICE_NAME 32 /* 0x1011 */ + +/* NOTE(Kevin): Shall <= 16 */ +#define P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT 8 +#endif + +/* Define the argument of cnmStaFreeAllStaByNetwork when all station records + * will be free. No one will be free + */ +#define STA_REC_EXCLUDE_NONE CFG_STA_REC_NUM + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +/* Use 32 bits to represent buffur bitmap in BUF_INFO, i.e., the variable + * rFreeBlocksBitmap in BUF_INFO structure. + */ +#if (MAX_NUM_OF_BUF_BLOCKS != 32) +#error > #define MAX_NUM_OF_MGT_BUF_BLOCKS should be 32 ! +#endif /* MAX_NUM_OF_MGT_BUF_BLOCKS */ + +/* Control variable of TX management memory pool */ +struct BUF_INFO { + uint8_t *pucBuf; + +#if CFG_DBG_MGT_BUF + uint32_t u4AllocCount; + uint32_t u4FreeCount; + uint32_t u4AllocNullCount; +#endif /* CFG_DBG_MGT_BUF */ + + uint32_t rFreeBlocksBitmap; + uint8_t aucAllocatedBlockNum[MAX_NUM_OF_BUF_BLOCKS]; +}; + +/* Wi-Fi divides RAM into three types + * MSG: Mailbox message (Small size) + * BUF: HW DMA buffers (HIF/MAC) + */ +enum ENUM_RAM_TYPE { + RAM_TYPE_MSG = 0, + RAM_TYPE_BUF +}; + +enum ENUM_BUFFER_SOURCE { + BUFFER_SOURCE_HIF_TX0 = 0, + BUFFER_SOURCE_HIF_TX1, + BUFFER_SOURCE_MAC_RX, + BUFFER_SOURCE_MNG, + BUFFER_SOURCE_BCN, + BUFFER_SOURCE_NUM +}; + +enum ENUM_SEC_STATE { + 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 +}; + +struct TSPEC_ENTRY { + uint8_t ucStatus; + uint8_t ucToken; /* Dialog Token in ADDTS_REQ or ADDTS_RSP */ + uint16_t u2MediumTime; + uint32_t u4TsInfo; + /* PARAM_QOS_TS_INFO rParamTsInfo; */ + /* Add other retained QoS parameters below */ +}; + +#if 0 +struct SEC_INFO { + + enum ENUM_SEC_STATE ePreviousState; + enum ENUM_SEC_STATE eCurrentState; + + u_int8_t fg2nd1xSend; + u_int8_t fgKeyStored; + + uint8_t aucStoredKey[64]; + + u_int8_t fgAllowOnly1x; +}; +#endif + +#define MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS 3 + +#define UPDATE_BSS_RSSI_INTERVAL_SEC 3 /* Seconds */ + +/* Fragment information structure */ +struct FRAG_INFO { + uint16_t u2NextFragSeqCtrl; + uint8_t *pucNextFragStart; + struct SW_RFB *pr1stFrag; + + /* The receive time of 1st fragment */ + OS_SYSTIME rReceiveLifetimeLimit; +}; + +#if CFG_SUPPORT_802_11W +/* AP PMF */ +struct AP_PMF_CFG { + u_int8_t fgMfpc; + u_int8_t fgMfpr; + u_int8_t fgSha256; + u_int8_t fgAPApplyPmfReq; + u_int8_t fgBipKeyInstalled; +}; + +struct STA_PMF_CFG { + u_int8_t fgMfpc; + u_int8_t fgMfpr; + u_int8_t fgSha256; + u_int8_t fgSaeRequireMfp; + u_int8_t fgApplyPmf; + u_int8_t fgBipKeyInstalled; + + /* for certification 4.3.3.1, 4.3.3.2 TX unprotected deauth */ + u_int8_t fgRxDeauthResp; + + /* For PMF SA query TX request retry a timer */ + /* record the start time of 1st SAQ request */ + uint32_t u4SAQueryStart; + + uint32_t u4SAQueryCount; + uint8_t ucSAQueryTimedOut; /* retry more than 1000ms */ + struct TIMER rSAQueryTimer; + uint16_t u2TransactionID; +}; +#endif + +/* Define STA record structure */ +struct STA_RECORD { + struct LINK_ENTRY rLinkEntry; + uint8_t ucIndex; /* Not modify it except initializing */ + uint8_t ucWlanIndex; /* WLAN table index */ + +#if 0 /* TODO: Remove this */ + /* The BSS STA Rx WLAN index, IBSS Rx BC WLAN table + * index, work at IBSS Open and WEP + */ + uint8_t ucBMCWlanIndex; +#endif + + u_int8_t fgIsInUse; /* Indicate if this entry is in use or not */ + uint8_t aucMacAddr[MAC_ADDR_LEN]; /* MAC address */ + + /* SAA/AAA */ + /* Store STATE Value used in SAA/AAA */ + enum ENUM_AA_STATE eAuthAssocState; + + uint8_t ucAuthAssocReqSeqNum; + + /* Indicate the role of this STA in the network (for example, P2P GO) */ + enum ENUM_STA_TYPE eStaType; + + uint8_t ucBssIndex; /* BSS_INFO_I index */ + + uint8_t ucStaState; /* STATE_1,2,3 */ + + /* Available PHY Type Set of this peer (may deduced from + * received struct BSS_DESC) + */ + uint8_t ucPhyTypeSet; + + /* record from bcn or probe response */ + uint8_t ucVhtCapNumSoundingDimensions; + + /* The match result by AND operation of peer's PhyTypeSet and ours. */ + uint8_t ucDesiredPhyTypeSet; + + /* A flag to indicate a Basic Phy Type which is used to generate some + * Phy Attribute IE (e.g. capability, MIB) during association. + */ + u_int8_t fgHasBasicPhyType; + + /* The Basic Phy Type chosen among the ucDesiredPhyTypeSet. */ + uint8_t ucNonHTBasicPhyType; + + uint16_t u2HwDefaultFixedRateCode; + + /* For Infra Mode, to store Capability Info. from Association Resp(SAA). + * For AP Mode, to store Capability Info. from Association Req(AAA). + */ + uint16_t u2CapInfo; + + /* For Infra Mode, to store AID from Association Resp(SAA). + * For AP Mode, to store the Assigned AID(AAA). + */ + uint16_t u2AssocId; + + uint16_t u2ListenInterval; /* Listen Interval from STA(AAA) */ + + /* Our Current Desired Rate Set after match + * with STA's Operational Rate Set + */ + uint16_t u2DesiredNonHTRateSet; + + uint16_t u2OperationalRateSet; /* Operational Rate Set of peer BSS */ + uint16_t u2BSSBasicRateSet; /* Basic Rate Set of peer BSS */ + + /* For IBSS Mode, to indicate that Merge is ongoing */ + u_int8_t fgIsMerging; + + /* For Infra/AP Mode, to diagnose the Connection with this peer + * by sending ProbeReq/Null frame + */ + u_int8_t fgDiagnoseConnection; + + /*---------------------------------------------------------------------- + * 802.11n HT capabilities when (prStaRec->ucPhyTypeSet & + * PHY_TYPE_BIT_HT) is true. They have the same definition with fields + * of information element + *---------------------------------------------------------------------- + */ + uint8_t ucMcsSet; /* MCS0~7 rate set of peer BSS */ + u_int8_t fgSupMcs32; /* MCS32 is supported by peer BSS */ + uint8_t aucRxMcsBitmask[SUP_MCS_RX_BITMASK_OCTET_NUM]; + uint16_t u2RxHighestSupportedRate; + uint32_t u4TxRateInfo; + uint16_t u2HtCapInfo; /* HT cap info field by HT cap IE */ + uint8_t ucAmpduParam; /* Field A-MPDU Parameters in HT cap IE */ + uint16_t u2HtExtendedCap; /* HT extended cap field by HT cap IE */ + + /* TX beamforming cap field by HT cap IE */ + uint32_t u4TxBeamformingCap; + + uint8_t ucAselCap; /* ASEL cap field by HT cap IE */ + +#if 1 /* CFG_SUPPORT_802_11AC */ + /*---------------------------------------------------------------------- + * 802.11ac VHT capabilities when (prStaRec->ucPhyTypeSet & + * PHY_TYPE_BIT_VHT) is true. They have the same definition with fields + * of information element + *---------------------------------------------------------------------- + */ + uint32_t u4VhtCapInfo; + uint16_t u2VhtRxMcsMap; + uint16_t u2VhtRxMcsMapAssoc; + uint16_t u2VhtRxHighestSupportedDataRate; + uint16_t u2VhtTxMcsMap; + uint16_t u2VhtTxHighestSupportedDataRate; + uint8_t ucVhtOpMode; +#endif + +#if (CFG_SUPPORT_802_11AX == 1) + /*--------------------------------------------------------------------*/ + /* HE capability if (prStaRec->ucPhyTypeSet & PHY_TYPE_BIT_HE) is set */ + /* They have the same definition with fields of information element */ + /*--------------------------------------------------------------------*/ + uint8_t ucHeMacCapInfo[HE_MAC_CAP_BYTE_NUM]; + uint8_t ucHePhyCapInfo[HE_PHY_CAP_BYTE_NUM]; + + uint16_t u2HeRxMcsMapBW80; + uint16_t u2HeTxMcsMapBW80; + uint16_t u2HeRxMcsMapBW160; + uint16_t u2HeTxMcsMapBW160; + uint16_t u2HeRxMcsMapBW80P80; + uint16_t u2HeTxMcsMapBW80P80; +#endif + + /*---------------------------------------------------------------------- + * 802.11ac HT operation info when (prStaRec->ucPhyTypeSet & + * PHY_TYPE_BIT_HT) is true. They have the same definition with fields + * of information element + *---------------------------------------------------------------------- + */ + uint8_t ucHtPeerOpInfo1; /* Backup peer HT OP Info */ + + /*---------------------------------------------------------------------- + * 802.11ac VHT operation info when (prStaRec->ucPhyTypeSet & + * PHY_TYPE_BIT_VHT) is true. They have the same definition with fields + * of information element + *---------------------------------------------------------------------- + */ + /* Backup peer VHT Op Info */ + uint8_t ucVhtOpChannelWidth; + uint8_t ucVhtOpChannelFrequencyS1; + uint8_t ucVhtOpChannelFrequencyS2; + + + uint8_t ucRCPI; /* RCPI of peer */ + + /* Target BSS's DTIM Period, we use this value for + * setup Listen Interval + * TODO(Kevin): TBD + */ + uint8_t ucDTIMPeriod; + + /* For Infra/AP Mode, the Auth Algorithm Num used + * in Authentication(SAA/AAA) + */ + uint8_t ucAuthAlgNum; + uint8_t ucAuthTranNum; /* For Infra/AP Mode, the Auth Transaction Number + */ + + /* For Infra/AP Mode, to indicate ReAssoc Frame was in used(SAA/AAA) */ + u_int8_t fgIsReAssoc; + + /* For Infra Mode, the Retry Count of TX Auth/Assod Frame(SAA) */ + uint8_t ucTxAuthAssocRetryCount; + + /* For Infra Mode, the Retry Limit of TX Auth/Assod Frame(SAA) */ + uint8_t ucTxAuthAssocRetryLimit; + + uint16_t u2StatusCode; /* Status of Auth/Assoc Req */ + uint16_t u2ReasonCode; /* Reason that been Deauth/Disassoc */ + + /* Point to an allocated buffer for storing Challenge */ + /* Text for Shared Key Authentication */ + struct IE_CHALLENGE_TEXT *prChallengeText; + + /* For Infra Mode, a timer used to send a timeout event + * while waiting for TX request done or RX response. + */ + struct TIMER rTxReqDoneOrRxRespTimer; + + /* For Infra Mode, a timer used to avoid the Deauth frame + * not be sent + */ + struct TIMER rDeauthTxDoneTimer; + + /*---------------------------------------------------------------------- + * Power Management related fields (for STA/ AP/ P2P/ BOW power saving + * mode) + *---------------------------------------------------------------------- + */ + /* For Infra Mode, to indicate that outgoing frame need + * toggle the Pwr Mgt Bit in its Frame Control Field. + */ + u_int8_t fgSetPwrMgtBit; + + /* For AP Mode, to indicate the client PS state(PM). + * TRUE: In PS Mode; FALSE: In Active Mode. + */ + u_int8_t fgIsInPS; + + /* For Infra Mode, to indicate we've sent a PS POLL to AP + * and start the PS_POLL Service Period(LP) + */ + u_int8_t fgIsInPsPollSP; + + /* For Infra Mode, to indicate we've sent a Trigger Frame + * to AP and start the Delivery Service Period(LP) + */ + u_int8_t fgIsInTriggerSP; + + uint8_t ucBmpDeliveryAC; /* 0: AC0, 1: AC1, 2: AC2, 3: AC3 */ + + uint8_t ucBmpTriggerAC; /* 0: AC0, 1: AC1, 2: AC2, 3: AC3 */ + + uint8_t ucUapsdSp; /* Max SP length */ + + /*--------------------------------------------------------------------*/ + + u_int8_t fgIsRtsEnabled; + + /* (4) System Timestamp of Successful TX and RX */ + uint32_t rUpdateTime; + + /* (4) System Timestamp of latest JOIN process */ + uint32_t rLastJoinTime; + + uint8_t ucJoinFailureCount; /* Retry Count of JOIN process */ + + /* For TXM to defer pkt forwarding to MAC TX DMA */ + struct LINK arStaWaitQueue[STA_WAIT_QUEUE_NUM]; + + /* Duplicate removal for HT STA on a + * per-TID basis ("+1" is for MMPDU and non-QoS) + */ + uint16_t au2CachedSeqCtrl[TID_NUM + 1]; + + u_int8_t afgIsIgnoreAmsduDuplicate[TID_NUM + 1]; + +#if 0 + /* RXM */ + struct RX_BA_ENTRY *aprRxBaTable[TID_NUM]; + + /* TXM */ + P_TX_BA_ENTRY_T aprTxBaTable[TID_NUM]; +#endif + + struct FRAG_INFO rFragInfo[MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS]; + +#if 0 /* TODO: Remove this */ + struct SEC_INFO rSecInfo; /* The security state machine */ +#endif + +#if CFG_SUPPORT_ADHOC + /* Ad-hoc RSN Rx BC key exist flag, only reserved two + * entry for each peer + */ + u_int8_t fgAdhocRsnBcKeyExist[2]; + + /* Ad-hoc RSN Rx BC wlan index */ + uint8_t ucAdhocRsnBcWlanIndex[2]; +#endif + + u_int8_t fgPortBlock; /* The 802.1x Port Control flag */ + + u_int8_t fgTransmitKeyExist; /* Unicast key exist for this STA */ + + u_int8_t fgTxAmpduEn; /* Enable TX AMPDU for this Peer */ + u_int8_t fgRxAmpduEn; /* Enable RX AMPDU for this Peer */ + + uint8_t *pucAssocReqIe; + uint16_t u2AssocReqIeLen; + + /* link layer satatistics */ + struct WIFI_WMM_AC_STAT arLinkStatistics[WMM_AC_INDEX_NUM]; + + /*---------------------------------------------------------------------- + * WMM/QoS related fields + *---------------------------------------------------------------------- + */ + /* If the STA is associated as a QSTA or QAP (for TX/RX) */ + u_int8_t fgIsQoS; + + /* If the peer supports WMM, set to TRUE (for association) */ + u_int8_t fgIsWmmSupported; + + /* Set according to the scan result (for association) */ + u_int8_t fgIsUapsdSupported; + + u_int8_t afgAcmRequired[ACI_NUM]; + +#if (CFG_SUPPORT_802_11AX == 1) + /* If the peer supports MU EDCA, set to TRUE (for association)*/ + u_int8_t fgIsMuEdcaSupported; +#endif + + /*---------------------------------------------------------------------- + * P2P related fields + *---------------------------------------------------------------------- + */ +#if CFG_ENABLE_WIFI_DIRECT + uint8_t u2DevNameLen; + uint8_t aucDevName[WPS_ATTRI_MAX_LEN_DEVICE_NAME]; + + uint8_t aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ + + uint16_t u2ConfigMethods; + + uint8_t ucDeviceCap; + + uint8_t ucSecondaryDevTypeCount; + + struct DEVICE_TYPE rPrimaryDevTypeBE; + + struct DEVICE_TYPE arSecondaryDevTypeBE[ + P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT]; +#endif /* CFG_SUPPORT_P2P */ + + /*---------------------------------------------------------------------- + * QM related fields + *---------------------------------------------------------------------- + */ + /* Per Sta flow controal. Valid when fgIsInPS is TRUE. + * Change it for per Queue flow control + */ + uint8_t ucFreeQuota; + +#if 0 /* TODO: Remove this */ + /* used in future */ + uint8_t aucFreeQuotaPerQueue[NUM_OF_PER_STA_TX_QUEUES]; +#endif + uint8_t ucFreeQuotaForDelivery; + uint8_t ucFreeQuotaForNonDelivery; + + /*---------------------------------------------------------------------- + * TXM related fields + *---------------------------------------------------------------------- + */ + void *aprTxDescTemplate[TX_DESC_TID_NUM]; + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE && CFG_ENABLE_PER_STA_STATISTICS + uint32_t u4TotalTxPktsNumber; + uint32_t u4TotalTxPktsTime; + uint32_t u4TotalTxPktsHifTxTime; + + uint32_t u4TotalRxPktsNumber; + uint32_t u4MaxTxPktsTime; + uint32_t u4MaxTxPktsHifTime; + + uint32_t u4ThresholdCounter; + uint32_t u4EnqueueCounter; + uint32_t u4DeqeueuCounter; +#endif + +#if 1 + /*---------------------------------------------------------------------- + * To be removed, this is to make que_mgt compilation success only + *---------------------------------------------------------------------- + */ + /* When this STA_REC is in use, set to TRUE. */ + u_int8_t fgIsValid; + + /* TX key is ready */ + u_int8_t fgIsTxKeyReady; + + /* When the STA is connected or TX key is ready */ + u_int8_t fgIsTxAllowed; + + /* Per-STA Queues: [0] AC0, [1] AC1, [2] AC2, [3] AC3 */ + struct QUE arTxQueue[NUM_OF_PER_STA_TX_QUEUES]; + + /* Per-STA Pending Queues: [0] AC0, [1] AC1, [2] AC2, [3] AC3 */ + /* This queue is for Tx packet in protected BSS before key is set */ + struct QUE arPendingTxQueue[NUM_OF_PER_STA_TX_QUEUES]; + + /* Tx packet target queue pointer. Select between arTxQueue & + * arPendingTxQueue + */ + struct QUE *aprTargetQueue[NUM_OF_PER_STA_TX_QUEUES]; + + /* Reorder Parameter reference table */ + struct RX_BA_ENTRY *aprRxReorderParamRefTbl[CFG_RX_MAX_BA_TID_NUM]; +#endif + +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT + struct TIMINGMSMT_PARAM rWNMTimingMsmt; +#endif + uint8_t ucTrafficDataType; /* 0: auto 1: data 2: video 3: voice */ + + /* 0: auto 1:Force enable 2: Force disable 3: enable by peer */ + uint8_t ucTxGfMode; + + /* 0: auto 1:Force enable 2: Force disable 3: enable by peer */ + uint8_t ucTxSgiMode; + + /* 0: auto 1:Force enable 2: Force disable 3: enable by peer */ + uint8_t ucTxStbcMode; + + uint32_t u4FixedPhyRate; + uint16_t u2MaxLinkSpeed; /* unit is 0.5 Mbps */ + uint16_t u2MinLinkSpeed; + uint32_t u4Flags; /* reserved for MTK Synergies */ + +#if CFG_SUPPORT_TDLS + u_int8_t fgTdlsIsProhibited; /* TRUE: AP prohibits TDLS links */ + + /* TRUE: AP prohibits TDLS chan switch */ + u_int8_t fgTdlsIsChSwProhibited; + + u_int8_t flgTdlsIsInitiator; /* TRUE: the peer is the initiator */ + + /* temp to queue HT capability element */ + struct IE_HT_CAP rTdlsHtCap; + + struct PARAM_KEY rTdlsKeyTemp; /* temp to queue the key information */ + uint8_t ucTdlsIndex; +#endif /* CFG_SUPPORT_TDLS */ +#if CFG_SUPPORT_TX_BF + struct TXBF_PFMU_STA_INFO rTxBfPfmuStaInfo; +#endif +#if CFG_SUPPORT_MSP + uint32_t u4RxVector0; + uint32_t u4RxVector1; + uint32_t u4RxVector2; + uint32_t u4RxVector3; + uint32_t u4RxVector4; +#endif + uint8_t ucSmDialogToken; /* Spectrum Mngt Dialog Token */ + uint8_t ucSmMsmtRequestMode; /* Measurement Request Mode */ + uint8_t ucSmMsmtToken; /* Measurement Request Token */ + + /* Element for AMSDU */ + uint8_t ucAmsduEnBitmap; /* Tid bit mask of AMSDU enable */ + uint8_t ucMaxMpduCount; + uint32_t u4MaxMpduLen; + uint32_t u4MinMpduLen; +#if CFG_SUPPORT_802_11W + /* AP PMF */ + struct STA_PMF_CFG rPmfCfg; +#endif +#if DSCP_SUPPORT + uint8_t qosMapSet[64]; +#endif +#if (CFG_SUPPORT_TWT == 1) + /* TWT Requester state */ + enum _ENUM_TWT_REQUESTER_STATE_T aeTWTReqState; + struct _TWT_FLOW_T arTWTFlow[TWT_MAX_FLOW_NUM]; +#endif +#if (CFG_SUPPORT_802_11AX == 1) + struct HE_A_CTRL_OM_T arHeACtrlOm; +#endif + + u_int8_t fgSupportBTM; /* Indicates whether to support BTM */ + + /* + * Flag used to record the connected status of upper layer. + * Indicate connected status only when disconnected, and only + * indicate disconnected status only when connected. + */ + u_int8_t fgIsConnected; +#if CFG_SUPPORT_HE_ER + u_int8_t fgIsExtendedRange; +#endif +}; + +#if 0 +/* use nic_tx.h instead */ +/* MSDU_INFO and SW_RFB structure */ +struct MSDU_INFO { + + /* 4 ----------------MSDU_INFO and SW_RFB Common Fields-------------- */ + + struct LINK_ENTRY rLinkEntry; + uint8_t *pucBuffer; /* Pointer to the associated buffer */ + + uint8_t ucBufferSource; /* HIF TX0, HIF TX1, MAC RX, or MNG Pool */ + + /* Network type index that this TX packet is assocaited with */ + uint8_t ucNetworkTypeIndex; + + /* 0 to 5 (used by HIF TX to increment the corresponding TC counter) */ + uint8_t ucTC; + + uint8_t ucTID; /* Traffic Identification */ + + u_int8_t fgIs802_11Frame; /* Set to TRUE for 802.11 frame */ + uint8_t ucMacHeaderLength; + uint16_t u2PayloadLength; + uint8_t *pucMacHeader; /* 802.11 header */ + uint8_t *pucPayload; /* 802.11 payload */ + + OS_SYSTIME rArrivalTime; /* System Timestamp (4) */ + struct STA_RECORD *prStaRec; + +#if CFG_PROFILE_BUFFER_TRACING + ENUM_BUFFER_ACTIVITY_TYPE_T eActivity[2]; + uint32_t rActivityTime[2]; +#endif +#if DBG && CFG_BUFFER_FREE_CHK + u_int8_t fgBufferInSource; +#endif + + /* For specify some Control Flags, e.g. Basic Rate */ + uint8_t ucControlFlag; + + /* 4 -----------------------Non-Common ------------------------- */ + /* TODO: move flags to ucControlFlag */ + + u_int8_t fgIs1xFrame; /* Set to TRUE for 802.1x frame */ + + /* TXM: For TX Done handling, callback function & parameter (5) */ + u_int8_t fgIsTxFailed; /* Set to TRUE if transmission failure */ + + PFN_TX_DONE_HANDLER pfTxDoneHandler; + + uint64_t u8TimeStamp; /* record the TX timestamp */ + + /* TXM: For PS forwarding control (per-STA flow control) */ + /* Delivery-enabled, non-delivery-enabled, non-PS */ + uint8_t ucPsForwardingType; + + /* The Power Save session id for PS forwarding control */ + uint8_t ucPsSessionID; + + /* TXM: For MAC TX DMA operations */ + uint8_t ucMacTxQueIdx; /* MAC TX queue: AC0-AC6, BCM, or BCN */ + + /* Set to true if Ack is not required for this packet */ + u_int8_t fgNoAck; + + u_int8_t fgBIP; /* Set to true if BIP is used for this packet */ + uint8_t ucFragTotalCount; + uint8_t ucFragFinishedCount; + + /* Fragmentation threshold without WLAN Header & FCS */ + uint16_t u2FragThreshold; + + u_int8_t fgFixedRate; /* If a fixed rate is used, set to TRUE. */ + + /* The rate code copied to MAC TX Desc */ + uint8_t ucFixedRateCode; + + /* The retry limit when a fixed rate is used */ + uint8_t ucFixedRateRetryLimit; + + /* Set to true if this packet is the end of BMC */ + u_int8_t fgIsBmcQueueEnd; + + /* TXM: For flushing ACL frames */ + uint16_t u2PalLLH; /* 802.11 PAL LLH */ + /* UINT_16 u2LLH; */ + uint16_t u2ACLSeq; /* u2LLH+u2ACLSeq for AM HCI flush ACL frame */ + + /* TXM for retransmitting a flushed packet */ + u_int8_t fgIsSnAssigned; + + /* To remember the Sequence Control field of this MPDU */ + uint16_t u2SequenceNumber; +}; +#endif + +#if 0 +/* nic_rx.h */ +struct SW_RFB { + + /* 4 ----------------MSDU_INFO and SW_RFB Common Fields-------------- */ + + struct LINK_ENTRY rLinkEntry; + uint8_t *pucBuffer; /* Pointer to the associated buffer */ + + uint8_t ucBufferSource; /* HIF TX0, HIF TX1, MAC RX, or MNG Pool */ + + /* Network type index that this TX packet is assocaited with */ + uint8_t ucNetworkTypeIndex; + + /* 0 to 5 (used by HIF TX to increment the corresponding TC counter) */ + uint8_t ucTC; + + uint8_t ucTID; /* Traffic Identification */ + + u_int8_t fgIs802_11Frame; /* Set to TRUE for 802.11 frame */ + uint8_t ucMacHeaderLength; + uint16_t u2PayloadLength; + uint8_t *pucMacHeader; /* 802.11 header */ + uint8_t *pucPayload; /* 802.11 payload */ + + OS_SYSTIME rArrivalTime; /* System Timestamp (4) */ + struct STA_RECORD *prStaRec; + +#if CFG_PROFILE_BUFFER_TRACING + ENUM_BUFFER_ACTIVITY_TYPE_T eActivity[2]; + uint32_t rActivityTime[2]; +#endif +#if DBG && CFG_BUFFER_FREE_CHK + u_int8_t fgBufferInSource; +#endif + + /* For specify some Control Flags, e.g. Basic Rate */ + uint8_t ucControlFlag; + + /* 4 -----------------------Non-Common ------------------------- */ + + /* For composing the HIF RX Header (TODO: move flags to + * ucControlFlag) + */ + /* Pointer to the Response packet to * HIF RX0 or RX1 */ + uint8_t *pucHifRxPacket; + + uint16_t u2HifRxPacketLength; + uint8_t ucHeaderOffset; + uint8_t ucHifRxPortIndex; + + uint16_t u2SequenceControl; + + /* (For MAC RX packet parsing) set to TRUE if 4 addresses are present */ + u_int8_t fgIsA4Frame; + + u_int8_t fgIsBAR; + u_int8_t fgIsQoSData; + u_int8_t fgIsAmsduSubframe; /* Set to TRUE for A-MSDU Subframe */ + + /* For HIF RX DMA Desc */ + u_int8_t fgTUChecksumCheckRequired; + u_int8_t fgIPChecksumCheckRequired; + uint8_t ucEtherTypeOffset; + +}; +#endif + +enum ENUM_STA_REC_CMD_ACTION { + STA_REC_CMD_ACTION_STA = 0, + STA_REC_CMD_ACTION_BSS = 1, + STA_REC_CMD_ACTION_BSS_EXCLUDE_STA = 2 +}; + +#if CFG_SUPPORT_TDLS + +/* TDLS FSM */ +struct CMD_PEER_ADD { + + uint8_t aucPeerMac[6]; + enum ENUM_STA_TYPE eStaType; + uint8_t ucBssIdx; +}; + +struct CMD_PEER_UPDATE_HT_CAP_MCS_INFO { + uint8_t arRxMask[SUP_MCS_RX_BITMASK_OCTET_NUM]; + uint16_t u2RxHighest; + uint8_t ucTxParams; + uint8_t Reserved[3]; +}; + +struct CMD_PEER_UPDATE_VHT_CAP_MCS_INFO { + uint8_t arRxMask[SUP_MCS_RX_BITMASK_OCTET_NUM]; +}; + +struct CMD_PEER_UPDATE_HT_CAP { + uint16_t u2CapInfo; + uint8_t ucAmpduParamsInfo; + + /* 16 bytes MCS information */ + struct CMD_PEER_UPDATE_HT_CAP_MCS_INFO rMCS; + + uint16_t u2ExtHtCapInfo; + uint32_t u4TxBfCapInfo; + uint8_t ucAntennaSelInfo; +}; + +struct CMD_PEER_UPDATE_VHT_CAP { + uint16_t u2CapInfo; + /* 16 bytes MCS information */ + struct CMD_PEER_UPDATE_VHT_CAP_MCS_INFO rVMCS; + +}; + +struct CMD_PEER_UPDATE { + + uint8_t aucPeerMac[6]; + +#define CMD_PEER_UPDATE_SUP_CHAN_MAX 50 + uint8_t aucSupChan[CMD_PEER_UPDATE_SUP_CHAN_MAX]; + + uint16_t u2StatusCode; + +#define CMD_PEER_UPDATE_SUP_RATE_MAX 50 + uint8_t aucSupRate[CMD_PEER_UPDATE_SUP_RATE_MAX]; + uint16_t u2SupRateLen; + + uint8_t UapsdBitmap; + uint8_t UapsdMaxSp; /* MAX_SP */ + + uint16_t u2Capability; +#define CMD_PEER_UPDATE_EXT_CAP_MAXLEN 5 + uint8_t aucExtCap[CMD_PEER_UPDATE_EXT_CAP_MAXLEN]; + uint16_t u2ExtCapLen; + + struct CMD_PEER_UPDATE_HT_CAP rHtCap; + struct CMD_PEER_UPDATE_VHT_CAP rVHtCap; + + u_int8_t fgIsSupHt; + enum ENUM_STA_TYPE eStaType; + uint8_t ucBssIdx; + + /* TODO */ + /* So far, TDLS only a few of the parameters, the rest will be added + * in the future requiements + */ + /* kernel 3.10 station paramenters */ +#if 0 + struct station_parameters { + const u8 *supported_rates; + struct net_device *vlan; + u32 sta_flags_mask, sta_flags_set; + u32 sta_modify_mask; + int listen_interval; + u16 aid; + u8 supported_rates_len; + u8 plink_action; + u8 plink_state; + const struct ieee80211_ht_cap *ht_capa; + const struct ieee80211_vht_cap *vht_capa; + u8 uapsd_queues; + u8 max_sp; + enum nl80211_mesh_power_mode local_pm; + u16 capability; + const u8 *ext_capab; + u8 ext_capab_len; + const u8 *supported_channels; + u8 supported_channels_len; + const u8 *supported_oper_classes; + u8 supported_oper_classes_len; + }; +#endif + +}; + +#endif + +#if CFG_DBG_MGT_BUF +struct MEM_TRACK { + struct LINK_ENTRY rLinkEntry; + uint16_t u2CmdIdAndWhere; + uint8_t *pucFileAndLine; +}; +#endif +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +#define STRL(x) #x +#define STRLINE(x) STRL(x) + +#if CFG_DBG_MGT_BUF +#define cnmMgtPktAlloc(_prAdapter, _u4Length) \ + cnmPktAllocWrapper((_prAdapter), (_u4Length), (uint8_t *)__func__) + +#define cnmMgtPktFree(_prAdapter, _prMsduInfo) \ + cnmPktFreeWrapper((_prAdapter), (_prMsduInfo), (uint8_t *)__func__) + +#define cnmMemAlloc(_prAdapter, eRameType, u4Length) \ + cnmMemAllocX(_prAdapter, eRameType, u4Length, \ + __FILE__ ":" STRLINE(__LINE__)) + +#define IS_FROM_BUF(_prAdapter, pucInfoBuffer) \ + (((uint8_t *)(pucInfoBuffer) >= \ + (uint8_t *)_prAdapter->rMgtBufInfo.pucBuf) && \ + ((uint8_t *)(pucInfoBuffer) < \ + (uint8_t *)_prAdapter->rMgtBufInfo.pucBuf + MGT_BUFFER_SIZE)) +#else +#define cnmMgtPktAlloc cnmPktAlloc +#define cnmMgtPktFree cnmPktFree +#endif + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +struct MSDU_INFO *cnmPktAllocWrapper(IN struct ADAPTER *prAdapter, + IN uint32_t u4Length, IN uint8_t *pucStr); + +void cnmPktFreeWrapper(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN uint8_t *pucStr); + +struct MSDU_INFO *cnmPktAlloc(IN struct ADAPTER *prAdapter, + IN uint32_t u4Length); + +void cnmPktFree(IN struct ADAPTER *prAdapter, IN struct MSDU_INFO *prMsduInfo); + +void cnmMemInit(IN struct ADAPTER *prAdapter); + +#if CFG_DBG_MGT_BUF +void *cnmMemAllocX(IN struct ADAPTER *prAdapter, + IN enum ENUM_RAM_TYPE eRamType, IN uint32_t u4Length, + uint8_t *fileAndLine); +#else +void *cnmMemAlloc(IN struct ADAPTER *prAdapter, IN enum ENUM_RAM_TYPE eRamType, + IN uint32_t u4Length); +#endif + +void cnmMemFree(IN struct ADAPTER *prAdapter, IN void *pvMemory); + +void cnmStaRecInit(IN struct ADAPTER *prAdapter); + +struct STA_RECORD * +cnmStaRecAlloc(IN struct ADAPTER *prAdapter, IN enum ENUM_STA_TYPE eStaType, + IN uint8_t ucBssIndex, IN uint8_t *pucMacAddr); + +void cnmStaRecFree(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +void cnmStaFreeAllStaByNetwork(struct ADAPTER *prAdapter, uint8_t ucBssIndex, + uint8_t ucStaRecIndexExcluded); + +struct STA_RECORD *cnmGetStaRecByIndex(IN struct ADAPTER *prAdapter, + IN uint8_t ucIndex); + +struct STA_RECORD *cnmGetStaRecByAddress(struct ADAPTER *prAdapter, + uint8_t ucBssIndex, uint8_t aucPeerMACAddress[]); + +void cnmStaRecChangeState(IN struct ADAPTER *prAdapter, + IN OUT struct STA_RECORD *prStaRec, IN uint8_t ucNewState); + +void cnmDumpStaRec(IN struct ADAPTER *prAdapter, IN uint8_t ucStaRecIdx); + +uint32_t cnmDumpMemoryStatus(IN struct ADAPTER *prAdapter, IN uint8_t *pucBuf, + IN uint32_t u4Max); + +#if CFG_SUPPORT_TDLS +uint32_t /* TDLS_STATUS */ +cnmPeerAdd(struct ADAPTER *prAdapter, void *pvSetBuffer, + uint32_t u4SetBufferLen, uint32_t *pu4SetInfoLen); + +uint32_t /* TDLS_STATUS */ +cnmPeerUpdate(struct ADAPTER *prAdapter, void *pvSetBuffer, + uint32_t u4SetBufferLen, uint32_t *pu4SetInfoLen); + +struct STA_RECORD *cnmGetTdlsPeerByAddress(struct ADAPTER *prAdapter, + uint8_t ucBssIndex, uint8_t aucPeerMACAddress[]); +#endif + +void cnmStaSendUpdateCmd(struct ADAPTER *prAdapter, struct STA_RECORD *prStaRec, + struct TXBF_PFMU_STA_INFO *prTxBfPfmuStaInfo, u_int8_t fgNeedResp); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#ifndef _lint +/* Kevin: we don't have to call following function to inspect the data + * structure. It will check automatically while at compile time. + * We'll need this for porting driver to different RTOS. + */ +static __KAL_INLINE__ void cnmMemDataTypeCheck(void) +{ +#if 0 + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, rLinkEntry) + == 0); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, rLinkEntry) + == OFFSET_OF(struct SW_RFB, rLinkEntry)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, pucBuffer) + == OFFSET_OF(struct SW_RFB, pucBuffer)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, ucBufferSource) + == OFFSET_OF(struct SW_RFB, ucBufferSource)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, pucMacHeader) + == OFFSET_OF(struct SW_RFB, pucMacHeader)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, ucMacHeaderLength) + == OFFSET_OF(struct SW_RFB, ucMacHeaderLength)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, pucPayload) + == OFFSET_OF(struct SW_RFB, pucPayload)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, u2PayloadLength) + == OFFSET_OF(struct SW_RFB, u2PayloadLength)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, prStaRec) + == OFFSET_OF(struct SW_RFB, prStaRec)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, ucNetworkTypeIndex) + == OFFSET_OF(struct SW_RFB, ucNetworkTypeIndex)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, ucTID) + == OFFSET_OF(struct SW_RFB, ucTID)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, fgIs802_11Frame) + == OFFSET_OF(struct SW_RFB, fgIs802_11Frame)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, ucControlFlag) + == OFFSET_OF(struct SW_RFB, ucControlFlag)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, rArrivalTime) + == OFFSET_OF(struct SW_RFB, rArrivalTime)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, ucTC) + == OFFSET_OF(struct SW_RFB, ucTC)); + +#if CFG_PROFILE_BUFFER_TRACING + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, eActivity[0]) + == OFFSET_OF(struct SW_RFB, eActivity[0])); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, rActivityTime[0]) + == OFFSET_OF(struct SW_RFB, rActivityTime[0])); +#endif + +#if DBG && CFG_BUFFER_FREE_CHK + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, fgBufferInSource) + == OFFSET_OF(struct SW_RFB, fgBufferInSource)); +#endif + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct STA_RECORD, rLinkEntry) + == 0); + + return; +#endif +} +#endif /* _lint */ + +#endif /* _CNM_MEM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/cnm_scan.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/cnm_scan.h new file mode 100644 index 0000000000000..46babe311422c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/cnm_scan.h @@ -0,0 +1,164 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: @(#) + */ + +/*! \file "cnm_scan.h" + * \brief + * + */ + + +#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 + +/* Used by partial scan */ +#define SCN_INTERLACED_CHANNEL_GROUPS_NUM 3 + +#define SCN_PARTIAL_SCAN_NUM 3 + +#define SCN_PARTIAL_SCAN_IDLE_MSEC 100 + +#define SCN_P2P_FULL_SCAN_PARAM 0 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +/* The type of Scan Source */ +enum ENUM_SCN_REQ_SOURCE { + 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 ENUM_SCAN_PROFILE { + SCAN_PROFILE_FULL = 0, + SCAN_PROFILE_PARTIAL, + SCAN_PROFILE_VOIP, + SCAN_PROFILE_FULL_2G4, + SCAN_PROFILE_NUM +}; + +/******************************************************************************* + * P U B 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 struct MSG_HDR *prMsgHdr); + +u_int8_t cnmScanRunEventScanAbort(IN struct MSG_HDR *prMsgHdr); + +void cnmScanProfileSelection(void); + +void cnmScanProcessStart(void); + +void cnmScanProcessStop(void); + +void cnmScanRunEventReqAISAbsDone(IN struct MSG_HDR *prMsgHdr); + +void cnmScanRunEventCancelAISAbsDone(IN struct MSG_HDR *prMsgHdr); + +void cnmScanPartialScanTimeout(uint32_t u4Param); + +void cnmScanRunEventScnFsmComplete(IN struct MSG_HDR *prMsgHdr); +#endif + +#endif /* _CNM_SCAN_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/cnm_timer.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/cnm_timer.h new file mode 100644 index 0000000000000..dab829534ccbb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/cnm_timer.h @@ -0,0 +1,260 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + + +#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 +#undef USEC_PER_SEC +#define USEC_PER_SEC 1000000 + +#define USEC_PER_TU 1024 /* microsecond */ + +#define MSEC_PER_MIN (60 * MSEC_PER_SEC) + +#define MGMT_MAX_TIMEOUT_INTERVAL ((uint32_t)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 + +enum ENUM_TIMER_WAKELOCK_TYPE_T { + TIMER_WAKELOCK_AUTO, + TIMER_WAKELOCK_NONE, + TIMER_WAKELOCK_REQUEST, + TIMER_WAKELOCK_NUM +}; + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +typedef void(*PFN_MGMT_TIMEOUT_FUNC) (struct ADAPTER *, unsigned long); + +struct TIMER { + struct LINK_ENTRY rLinkEntry; + OS_SYSTIME rExpiredSysTime; + uint16_t u2Minutes; + uint16_t u2Reserved; + unsigned long ulDataPtr; + PFN_MGMT_TIMEOUT_FUNC pfMgmtTimeOutFunc; + enum ENUM_TIMER_WAKELOCK_TYPE_T eType; +}; + +/******************************************************************************* + * P U B 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) \ + ((uint32_t)((uint32_t)(a) - (uint32_t)(b)) > 0x7fffffff) + +/* #define TIME_BEFORE(a,b) ((int32_t)((int32_t)(b) - (int32_t)(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) ((uint32_t)(_sec) * MSEC_PER_SEC) +#define SEC_TO_USEC(_sec) ((uint32_t)(_sec) * USEC_PER_SEC) + +/* The macros to convert millisecond & microsecond */ +#define USEC_TO_MSEC(_usec) ((_usec) / USEC_PER_MSEC) +#define MSEC_TO_USEC(_msec) ((uint32_t)(_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) * USEC_PER_SEC) / KAL_HZ) + +/* 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) \ + (((uint32_t)(_currentTime) - (uint32_t)(_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), (uint32_t)(_callbackFunc)) + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +void cnmTimerInitialize(IN struct ADAPTER *prAdapter); + +void cnmTimerDestroy(IN struct ADAPTER *prAdapter); + +void cnmTimerInitTimerOption(IN struct ADAPTER *prAdapter, + IN struct TIMER *prTimer, + IN PFN_MGMT_TIMEOUT_FUNC pfFunc, + IN unsigned long ulDataPtr, + IN enum ENUM_TIMER_WAKELOCK_TYPE_T eType); + +void cnmTimerStopTimer(IN struct ADAPTER *prAdapter, IN struct TIMER *prTimer); + +void cnmTimerStartTimer(IN struct ADAPTER *prAdapter, IN struct TIMER *prTimer, + IN uint32_t u4TimeoutMs); + +void cnmTimerDoTimeOutCheck(IN struct ADAPTER *prAdapter); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +static __KAL_INLINE__ int32_t timerPendingTimer(IN struct TIMER *prTimer) +{ + ASSERT(prTimer); + + return prTimer->rLinkEntry.prNext != NULL; +} + +static __KAL_INLINE__ void cnmTimerInitTimer(IN struct ADAPTER *prAdapter, + IN struct TIMER *prTimer, + IN PFN_MGMT_TIMEOUT_FUNC pfFunc, + IN unsigned long ulDataPtr) +{ + cnmTimerInitTimerOption(prAdapter, prTimer, pfFunc, ulDataPtr, + TIMER_WAKELOCK_AUTO); +} + + +#endif /* _CNM_TIMER_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/he_ie.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/he_ie.h new file mode 100644 index 0000000000000..4c26e2da81845 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/he_ie.h @@ -0,0 +1,733 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#ifndef _HE_IE_H +#define _HE_IE_H + +#if (CFG_SUPPORT_802_11AX == 1) + +/* HE Capabilities */ +#define ELEM_EXT_ID_HE_CAP 35 +/* HE Operation */ +#define ELEM_EXT_ID_HE_OP 36 +/* UL OFDMA-based Random Access (UORA) Parameter Set element */ +#define ELEM_EXT_ID_UORA_PARAM 37 +/* MU EDCA Parameter Set element */ +#define ELEM_EXT_ID_MU_EDCA_PARAM 38 +/* Spatial Reuse Parameter Set element */ +#define ELEM_EXT_ID_SR_PARAM 39 + +#define ELEM_EXT_CAP_TWT_REQUESTER_SUPP_BIT 77 +#define ELEM_EXT_CAP_TWT_RESPONDER_SUPP_BIT 78 + +#define HE_PHY_CAP_INFO_LEN 9 + +/* HE CAP - HE MAC Capabilities Information field */ +#define HE_MAC_CAP_BYTE_NUM 6 + +/* HE MAC Capablilites byte0 */ +#define HE_MAC_CAP0_HTC_HE BIT(0) +#define HE_MAC_CAP0_HTC_HE_SHFT 0 +#define HE_MAC_CAP0_TWT_REQ BIT(1) +#define HE_MAC_CAP0_TWT_REQ_SHFT 1 +#define HE_MAC_CAP0_TWT_RSP BIT(2) +#define HE_MAC_CAP0_TWT_RSP_SHFT 2 +#define HE_MAC_CAP0_FRAGMENTATION_SHFT 3 +#define HE_MAC_CAP0_MAX_NUM_OF_FRAGMENTATION_SHFT 5 + +/* HE MAC Capablilites byte1 */ +#define HE_MAC_CAP1_MIN_FRAGMENT_SIZE_SHFT 0 +#define HE_MAC_CAP1_TRIGGER_PAD_DURATION_MASK BITS(2, 3) +#define HE_MAC_CAP1_TRIGGER_PAD_DURATION_SHFT 2 +#define HE_MAC_CAP1_MULTI_TID_AGG_RX_SHFT 4 +#define HE_MAC_CAP1_LINK_ADP_SHFT 7 + +/* HE MAC Capablilites byte2 */ +#define HE_MAC_CAP2_LINK_ADP_SHFT 0 +#define HE_MAC_CAP2_ALL_ACK_SHFT 1 +#define HE_MAC_CAP2_TRS_SHFT 2 +#define HE_MAC_CAP2_BSR_SHFT 3 +#define HE_MAC_CAP2_BTWT_SHFT 4 +#define HE_MAC_CAP2_32BIT_BA_BITMAP_SHFT 5 +#define HE_MAC_CAP2_MU_CASCAD_SHFT 6 +#define HE_MAC_CAP2_ACK_ENABLED_AGG_SHFT 7 + +/* HE MAC Capablilites byte3 */ +#define HE_MAC_CAP3_RESERVED 0 +#define HE_MAC_CAP3_OM_CTRL BIT(1) +#define HE_MAC_CAP3_OM_CTRL_SHFT 1 +#define HE_MAC_CAP3_OFDMA_RA_SHFT 2 +#define HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_SHFT 3 +#define HE_MAC_CAP3_AMSDU_FRAGMENT_SHFT 5 +#define HE_MAC_CAP3_FLEXIBLE_TWT_SHDL BIT(6) +#define HE_MAC_CAP3_FLEXIBLE_TWT_SHDL_SHFT 6 +#define HE_MAC_CAP3_RX_CTRL_TO_MUTI_BSS_SHFT 7 + +/* HE MAC Capablilites byte4 */ +#define HE_MAC_CAP4_BSRP_BQRP_AMPDU_AGG_SHFT 0 +#define HE_MAC_CAP4_QTP_SHFT 1 +#define HE_MAC_CAP4_BQR_SHFT 2 +#define HE_MAC_CAP4_SRP_RSP_SHFT 3 +#define HE_MAC_CAP4_NDP_FEEDBACK_REPORT_SHFT 4 +#define HE_MAC_CAP4_OPS_SHFT 5 +#define HE_MAC_CAP4_AMSDU_IN_AMDU BIT(6) +#define HE_MAC_CAP4_AMSDU_IN_AMDU_SHFT 6 +#define HE_MAC_CAP4_MULTI_TID_AGG_TX 7 + +/* HE MAC Capablilites byte5 */ +#define HE_MAC_CAP5_MULTI_TID_AGG_TX_MASK BITS(0, 1) +#define HE_MAC_CAP5_MULTI_TID_AGG_TX_SHFT 0 +#define HE_MAC_CAP5_SUBCHANNEL_SEL_TX_SHFT 2 +#define HE_MAC_CAP5_UL_2X996TONE_RU_SHFT 3 +#define HE_MAC_CAP5_OM_CNTL_ULMUDATE_DISABLE_RX_SHFT 4 + +/* HE CAP - HE PHY Capabilities Information field */ +#define HE_PHY_CAP_BYTE_NUM 11 + +/* HE PHY Capablilites byte0 */ +#define HE_PHY_CAP0_RESERVED 0 +#define HE_PHY_CAP0_CHAN_WIDTH_SET_BW40_2G BIT(1) +#define HE_PHY_CAP0_CHAN_WIDTH_SET_BW40_BW80_5G BIT(2) +#define HE_PHY_CAP0_CHAN_WIDTH_SET_BW160_5G BIT(3) +#define HE_PHY_CAP0_CHAN_WIDTH_SET_BW80P80_5G BIT(4) +#define HE_PHY_CAP0_CHAN_WIDTH_SET_242TONE_2G BIT(5) +#define HE_PHY_CAP0_CHAN_WIDTH_SET_242TONE_5G BIT(6) +#define HE_PHY_CAP0_CHAN_WIDTH_SET_MASK BITS(1, 7) +#define HE_PHY_CAP0_CHAN_WIDTH_SET_SHFT 1 + +/* HE PHY Capablilites byte1 */ +#define HE_PHY_CAP1_PUNCTURED_PREAMBLE_RX_SHFT 0 +#define HE_PHY_CAP1_DEVICE_CALSS_SHFT 4 +#define HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD BIT(5) +#define HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD_SHFT 5 +#define HE_PHY_CAP1_1X_HE_LTF_SHFT 6 +#define HE_PHY_CAP1_MIDAMBLE_TXRX_MAX_NSTS_SHFT 7 + + +/* HE PHY Capablilites byte2 */ +#define HE_PHY_CAP2_MIDAMBLE_TXRX_MAX_NSTS_SHFT 0 +#define HE_PHY_CAP2_NDP_4X_HE_LTF_SHFT 1 +#define HE_PHY_CAP2_STBC_TX_LT_OR_EQ_80M BIT(2) +#define HE_PHY_CAP2_STBC_TX_LT_OR_EQ_80M_SHFT 2 +#define HE_PHY_CAP2_STBC_RX_LT_OR_EQ_80M BIT(3) +#define HE_PHY_CAP2_STBC_RX_LT_OR_EQ_80M_SHFT 3 +#define HE_PHY_CAP2_DOPPLER_TX_SHFT 4 +#define HE_PHY_CAP2_DOPPLER_RX_SHFT 5 +#define HE_PHY_CAP2_FULL_BW_UL_MU_MIMO BIT(6) +#define HE_PHY_CAP2_FULL_BW_UL_MU_MIMO_SHFT 6 +#define HE_PHY_CAP2_PARTIAL_BW_UL_MU_MIMO BIT(7) +#define HE_PHY_CAP2_PARTIAL_BW_UL_MU_MIMO_SHFT 7 + +/* HE PHY Capablilites byte3 */ +#define HE_PHY_CAP3_DCM_MAX_CONSTELLATION_TX_SHFT 0 +#define HE_PHY_CAP3_DCM_MAX_CONSTELLATION_TX_MASK BITS(0, 1) +#define HE_PHY_CAP3_DCM_MAX_NSS_TX_SHFT 2 +#define HE_PHY_CAP3_DCM_MAX_CONSTELLATION_RX_SHFT 3 +#define HE_PHY_CAP3_DCM_MAX_CONSTELLATION_RX_MASK BITS(3, 4) +#define HE_PHY_CAP3_DCM_MAX_NSS_RX_SHFT 5 +#define HE_PHY_CAP3_UL_HE_MU_PPDU_SHFT 6 +#define HE_PHY_CAP3_SU_BFMER BIT(7) +#define HE_PHY_CAP3_SU_BFMER_SHFT 7 + +/* HE PHY Capablilites byte4 */ +#define HE_PHY_CAP4_SU_BFMEE BIT(0) +#define HE_PHY_CAP4_SU_BFMEE_SHFT 0 +#define HE_PHY_CAP4_MU_BFMER BIT(1) +#define HE_PHY_CAP4_MU_BFMER_SHFT 1 +#define HE_PHY_CAP4_BFMEE_STS_LT_OR_EQ_80M_MASK BITS(2, 4) +#define HE_PHY_CAP4_BFMEE_STS_LT_OR_EQ_80M_SHFT 2 +#define HE_PHY_CAP4_BFMEE_STS_GT_80M_SHFT 5 + +/* HE PHY Capablilites byte5 */ +#define HE_PHY_CAP5_NUM_OF_SND_DIM_LT_OR_EQ_80M_SHFT 0 +#define HE_PHY_CAP5_NUM_OF_SND_DIM_GT_80M_SHFT 3 +#define HE_PHY_CAP5_NG_16_SU_FB BIT(6) +#define HE_PHY_CAP5_NG_16_SU_FB_SHFT 6 +#define HE_PHY_CAP5_NG_16_MU_FB BIT(7) +#define HE_PHY_CAP5_NG_16_MU_FB_SHFT 7 + +/* HE PHY Capablilites byte6 */ +#define HE_PHY_CAP6_CODE_BOOK_4_2_SU_FB BIT(0) +#define HE_PHY_CAP6_CODE_BOOK_4_2_SU_FB_SHFT 0 +#define HE_PHY_CAP6_CODE_BOOK_7_5_MU_FB BIT(1) +#define HE_PHY_CAP6_CODE_BOOK_7_5_MU_FB_SHFT 1 +#define HE_PHY_CAP6_TRIG_SU_BF_FB BIT(2) +#define HE_PHY_CAP6_TRIG_SU_BF_FB_SHFT 2 +#define HE_PHY_CAP6_TRIG_MU_BF_PARTIAL_BW_FB BIT(3) +#define HE_PHY_CAP6_TRIG_MU_BF_PARTIAL_BW_FB_SHFT 3 +#define HE_PHY_CAP6_TRIG_CQI_FB_SHFT 4 +#define HE_PHY_CAP6_PARTIAL_BW_EXTENDED_RANGE BIT(5) +#define HE_PHY_CAP6_PARTIAL_BW_EXTENDED_RANGE_SHFT 5 +#define HE_PHY_CAP6_PARTIAL_BW_DL_MU_MIMO_SHFT 6 +#define HE_PHY_CAP6_PPE_THRESHOLD BIT(7) +#define HE_PHY_CAP6_PPE_THRESHOLD_SHFT 7 + +/* HE PHY Capablilites byte7 */ +#define HE_PHY_CAP7_SRP_BASED_SR_SHFT 0 +#define HE_PHY_CAP7_POWER_BOOST_FACTOR_SHFT 1 +#define HE_PHY_CAP7_SU_MU_4X_HE_LTF_SHFT 2 +#define HE_PHY_CAP7_MAX_NC_MASK BITS(3, 5) +#define HE_PHY_CAP7_MAX_NC_SHFT 3 +#define HE_PHY_CAP7_STBC_TX_GT_80M BIT(6) +#define HE_PHY_CAP7_STBC_TX_GT_80M_SHFT 6 +#define HE_PHY_CAP7_STBC_RX_GT_80M BIT(7) +#define HE_PHY_CAP7_STBC_RX_GT_80M_SHFT 7 + +/* HE PHY Capablilites byte8 */ +#define HE_PHY_CAP8_ER_SU_4X_HE_LTF BIT(0) +#define HE_PHY_CAP8_ER_SU_4X_HE_LTF_SHFT 0 +#define HE_PHY_CAP8_20M_IN_40M_HE_PPDU_2G_SHFT 1 +#define HE_PHY_CAP8_20M_IN_160M_HE_PPDU_SHFT 2 +#define HE_PHY_CAP8_80M_IN_160M_HE_PPDU_SHFT 3 +#define HE_PHY_CAP8_ER_SU_PPDU_1X_HE_LTF BIT(4) +#define HE_PHY_CAP8_ER_SU_PPDU_1X_HE_LTF_SHFT 4 +#define HE_PHY_CAP8_MIDAMBLE_RX_2X_1X_HE_LTF_SHFT 5 +#define HE_PHY_CAP8_DCM_MAX_BW_SHFT 6 + +/* HE PHY Capablilites byte9 */ +#define HE_PHY_CAP9_LT_16_SIGB_OFDM_SYMBOL_SHFT 0 +#define HE_PHY_CAP9_NON_TRIGGER_CQI_FB_SHFT 1 +#define HE_PHY_CAP9_TX_1024_QAM_LESS_242_RU_SHFT 2 +#define HE_PHY_CAP9_RX_1024_QAM_LESS_242_RU_SHFT 3 +#define HE_PHY_CAP9_RX_FULL_BW_COMPRESS_SIGB_SHFT 4 +#define HE_PHY_CAP9_RX_FULL_BW_NONCOMPRESS_SIGB_SHFT 5 + +/* HE PHY Capablilites byte10 */ +/* ALL reserved */ + +/* Trigger Frame MAC Padding Duration */ +#define HE_CAP_TRIGGER_PAD_DURATION_0 0 +#define HE_CAP_TRIGGER_PAD_DURATION_8 1 +#define HE_CAP_TRIGGER_PAD_DURATION_16 2 + +#define HE_CAP_INFO_MCS_MAP_MCS7 0 +#define HE_CAP_INFO_MCS_MAP_MCS9 1 +#define HE_CAP_INFO_MCS_MAP_MCS11 2 +#define HE_CAP_INFO_MCS_NOT_SUPPORTED 3 + +/* PPE Threshold Field */ +#define HE_CAP_PPE_NSS BITS(0, 2) +#define HE_CAP_PPE_NSS_SHFT 0 +#define HE_CAP_PPE_RU_IDX_BMP BITS(3, 6) +#define HE_CAP_PPE_RU_IDX_BMP_SHFT 3 +#define HE_CAP_PPE_PPET16_NSS1_RU0 BITS(7, 9) +#define HE_CAP_PPE_PPET16_NSS1_RU0_SHFT 7 +#define HE_CAP_PPE_PPET8_NSS1_RU0 BITS(10, 12) +#define HE_CAP_PPE_PPET8_NSS1_RU0_SHFT 10 + +#define HE_CAP_PPE_242_RU_IDX BIT(3) +#define HE_CAP_PPE_484_RU_IDX BITS(3, 4) +#define HE_CAP_PPE_996_RU_IDX BITS(3, 5) +#define HE_CAP_PPE_996X2_RU_IDX BITS(3, 6) + +#define CONSTELL_IDX_BPSK 0 +#define CONSTELL_IDX_QPSK 1 +#define CONSTELL_IDX_16QAM 2 +#define CONSTELL_IDX_64QAM 3 +#define CONSTELL_IDX_256QAM 4 +#define CONSTELL_IDX_1024QAM 5 +#define CONSTELL_IDX_RESERVED 6 +#define CONSTELL_IDX_NONE 7 + +/* HE Operation element - HE Operation Parameters field */ +#define HE_OP_BYTE_NUM 3 + +/* HE Operation Parameters - byte0 */ +#define HE_OP_PARAM0_DEFAULT_PE_DUR_MASK BITS(0, 2) +#define HE_OP_PARAM0_DEFAULT_PE_DUR_SHFT 0 +#define HE_OP_PARAM0_TWT_REQUIRED_SHFT 3 +#define HE_OP_PARAM0_TXOP_DUR_RTS_THRESHOLD_MASK BITS(4, 7) +#define HE_OP_PARAM0_TXOP_DUR_RTS_THRESHOLD_SHFT 4 + +/* HE Operation Parameters - byte1 */ +#define HE_OP_PARAM1_TXOP_DUR_RTS_THRESHOLD_MASK BITS(0, 5) +#define HE_OP_PARAM1_TXOP_DUR_RTS_THRESHOLD_SHFT 0 +#define HE_OP_PARAM1_VHT_OP_INFO_PRESENT BIT(6) +#define HE_OP_PARAM1_VHT_OP_INFO_PRESENT_SHFT 6 +#define HE_OP_PARAM1_CO_LOCATED_BSS_SHFT 7 + +/* HE Operation Parameters - byte2 */ +#define HE_OP_PARAM2_ER_SU_DISABLE_MASK BIT(0) +#define HE_OP_PARAM2_ER_SU_DISABLE_SHFT 0 + +/* HE Operation element - BSS Color Information */ +#define HE_OP_BSSCOLOR_BSS_COLOR_SHFT 0 +#define HE_OP_BSSCOLOR_PARTIAL_BSS_COLOR_SHFT 6 +#define HE_OP_BSSCOLOR_BSS_COLOR_DISABLE_SHFT 7 + +/* Spatial Reuse Parameter Set element - SR Control field */ +#define SR_PARAM_SRP_DISALLOWED BIT(0) +#define SR_PARAM_SRP_DISALLOWED_SHFT 0 +#define SR_PARAM_NON_SRG_OBSS_PD_SR_DISALLOWED BIT(1) +#define SR_PARAM_NON_SRG_OBSS_PD_SR_DISALLOWED_SHFT 1 +#define SR_PARAM_NON_SRG_OFFSET_PRESENT BIT(2) +#define SR_PARAM_NON_SRG_OFFSET_PRESENT_SHFT 2 +#define SR_PARAM_SRG_INFO_PRESENT BIT(3) +#define SR_PARAM_SRG_INFO_PRESENT_SHFT 3 +#define SR_PARAM_HESIGA_SR_VALUE15_ALLOWED BIT(4) +#define SR_PARAM_HESIGA_SR_VALUE15_SHFT 4 + +/* 11ax_D3.0 9.2.4.6 HT Control field */ +#define HTC_HE_VARIANT BITS(0, 1) +/* 11ax_D3.0 9.2.4.6.4 A-Control */ +#define HTC_HE_A_CTRL_TRS 0 +#define HTC_HE_A_CTRL_OM 1 +#define HTC_HE_A_CTRL_HLA 2 +#define HTC_HE_A_CTRL_BSR 3 +#define HTC_HE_A_CTRL_UPH 4 +#define HTC_HE_A_CTRL_BQR 5 +#define HTC_HE_A_CTRL_CAS 6 + +/* 1st - OM_Ctrl, 2nd - UPH_Ctrl */ +#define HTC_HE_1ST_A_CTRL_ID BITS(2, 5) +#define HTC_HE_1ST_A_CTRL_ID_SHIFT 2 + +/* 11ax_D3.0 9.2.4.6a.2 OM Control */ +#define HTC_HE_OM_RX_NSS BITS(6, 8) +#define HTC_HE_OM_RX_NSS_SHFT 6 +#define HTC_HE_OM_CH_WIDTH BITS(9, 10) +#define HTC_HE_OM_CH_WIDTH_SHFT 9 +#define HTC_HE_OM_UL_MU_DISABLE BIT(11) +#define HTC_HE_OM_UL_MU_DISABLE_SHFT 11 +#define HTC_HE_OM_TX_NSTS BITS(12, 14) +#define HTC_HE_OM_TX_NSTS_SHFT 12 +#define HTC_HE_OM_ER_SU_DISABLE BIT(15) +#define HTC_HE_OM_ER_SU_DISABLE_SHFT 15 +#define HTC_HE_OM_DL_MUMIMO_RESND_RECMD BIT(16) +#define HTC_HE_OM_DL_MUMIMO_RESND_RECMD_SHFT 16 +#define HTC_HE_OM_UL_MU_DATA_DISABLE BIT(17) +#define HTC_HE_OM_UL_MU_DATA_DISABLE_SHFT 17 + +/* 1st - OM_CTRL, 2nd - UPH_CTRL */ +#define HTC_HE_2ND_A_CTRL_ID BITS(18, 21) +#define HTC_HE_2ND_A_CTRL_ID_SHIFT 18 + +/* 11ax_D3.0 9.2.4.6a.5 UPH Control */ +#define HTC_HE_UPH_UL_PWR_HEADROOM BITS(22, 27) +#define HTC_HE_UPH_UL_PWR_HEADROOM_SHIFT 22 +#define HTC_HE_UPH_MIN_TX_PWR_FLAG BIT(28) +#define HTC_HE_UPH_MIN_TX_PWR_FLAG_SHIFT 28 + +enum ENUM_HTC_HE_OM_CH_WIDTH { + CH_BW_20 = 0, + CH_BW_40 = 1, + CH_BW_80 = 2, + CH_BW_160 = 3, +}; + +/* 11ax_D3.0 9.3.1.9 BlockAck frame format */ +#define HE_BA_TYPE BITS(1, 4) +#define HE_BA_TYPE_SHFT 1 +enum ENUM_HEBA_TYPE { + HE_BA_TYPE_BASIC = 0, /* 0 Basic */ + HE_BA_TYPE_EXT_COMPRESSED = 1, /* 1 Extended Compressed */ + HE_BA_TYPE_COMPRESSED = 2, /* 2 Compressed */ + HE_BA_TYPE_MULTI_TID = 3, /* 3 Multi-TID */ + /* 4-5 Reserved */ + HE_BA_TYPE_GCR = 6, /* 6 GCR */ + /* 7-9 Reserved */ + HE_BA_TYPE_GLK_GCR = 10, /* 10 GLK-GCR */ + HE_BA_TYPE_MULTI_STA = 11, /* 11 Multi-STA */ + /* 12-15 Reserved */ +}; + +/* should use macro to access field of HE MAC CAP*/ +#define HE_SET_MAC_CAP_HTC_HE(_aucHeMacCapInfo) \ + (_aucHeMacCapInfo[0] |= HE_MAC_CAP0_HTC_HE) + +#define HE_SET_MAC_CAP_TWT_REQ(_aucHeMacCapInfo) \ + (_aucHeMacCapInfo[0] |= HE_MAC_CAP0_TWT_REQ) + +#define HE_IS_MAC_CAP_TWT_RSP(_aucHeMacCapInfo) \ + (_aucHeMacCapInfo[0] & HE_MAC_CAP0_TWT_RSP) + +#define HE_SET_MAC_CAP_TRIGGER_PAD_DURATION(_aucHeMacCapInfo, _ucDur) \ +{ \ + _aucHeMacCapInfo[1] &= ~(HE_MAC_CAP1_TRIGGER_PAD_DURATION_MASK); \ + _aucHeMacCapInfo[1] |= \ + ((_ucDur << HE_MAC_CAP1_TRIGGER_PAD_DURATION_SHFT) \ + & HE_MAC_CAP1_TRIGGER_PAD_DURATION_MASK); \ +} + +#define HE_IS_MAC_CAP_FLEXIBLE_TWT_SHDL(_aucHeMacCapInfo) \ + (_aucHeMacCapInfo[3] & HE_MAC_CAP3_FLEXIBLE_TWT_SHDL) + + +#define HE_SET_MAC_CAP_OM_CTRL(_aucHeMacCapInfo) \ + (_aucHeMacCapInfo[3] |= HE_MAC_CAP3_OM_CTRL) + +/* should use macro to access field of HE PHY CAP*/ +#define HE_SET_PHY_CAP_CHAN_WIDTH_SET_BW40_2G(_aucHePhyCapInfo) \ + (_aucHePhyCapInfo[0] |= HE_PHY_CAP0_CHAN_WIDTH_SET_BW40_2G) + +#define HE_SET_PHY_CAP_CHAN_WIDTH_SET_BW40_BW80_5G(_aucHePhyCapInfo) \ + (_aucHePhyCapInfo[0] |= HE_PHY_CAP0_CHAN_WIDTH_SET_BW40_BW80_5G) + +#define HE_IS_PHY_CAP_CHAN_WIDTH_SET_BW160_5G(_aucHePhyCapInfo) \ + (_aucHePhyCapInfo[0] & HE_PHY_CAP0_CHAN_WIDTH_SET_BW160_5G) + +#define HE_SET_PHY_CAP_CHAN_WIDTH_SET_BW160_5G(_aucHePhyCapInfo) \ + (_aucHePhyCapInfo[0] |= HE_PHY_CAP0_CHAN_WIDTH_SET_BW160_5G) + +#define HE_IS_PHY_CAP_CHAN_WIDTH_SET_BW80P80_5G(_aucHePhyCapInfo) \ + (_aucHePhyCapInfo[0] & HE_PHY_CAP0_CHAN_WIDTH_SET_BW80P80_5G) + +#define HE_SET_PHY_CAP_CHAN_WIDTH_SET_BW80P80_5G(_aucHePhyCapInfo) \ + (_aucHePhyCapInfo[0] |= HE_PHY_CAP0_CHAN_WIDTH_SET_BW80P80_5G) + +#define HE_SET_PHY_CAP_LDPC_CODING_IN_PAYLOAD(_aucHePhyCapInfo) \ + (_aucHePhyCapInfo[1] |= HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD) + +#define HE_SET_PHY_CAP_STBC_TX_LT_OR_EQ_80M(_aucHePhyCapInfo) \ + (_aucHePhyCapInfo[2] |= HE_PHY_CAP2_STBC_TX_LT_OR_EQ_80M) + +#define HE_SET_PHY_CAP_STBC_RX_LT_OR_EQ_80M(_aucHePhyCapInfo) \ + (_aucHePhyCapInfo[2] |= HE_PHY_CAP2_STBC_RX_LT_OR_EQ_80M) + +#define HE_UNSET_PHY_CAP_SU_BFMER(_aucHePhyCapInfo) \ + (_aucHePhyCapInfo[3] &= ~HE_PHY_CAP3_SU_BFMER) + +/* set to 0 if DCM is not supported */ +/* set to 1 for BPSK */ +/* set to 2 for QPSK */ +/* set to 3 for 16-QAM */ +#define HE_SET_PHY_CAP_DCM_MAX_CONSTELLATION_TX(_aucHePhyCapInfo, _ucVal) \ +{ \ + _aucHePhyCapInfo[3] &= ~(HE_PHY_CAP3_DCM_MAX_CONSTELLATION_TX_MASK); \ + _aucHePhyCapInfo[3] |= \ + ((_ucVal << HE_PHY_CAP3_DCM_MAX_CONSTELLATION_TX_SHFT) \ + & HE_PHY_CAP3_DCM_MAX_CONSTELLATION_TX_MASK); \ +} + +/* set to 0 if DCM is not supported */ +/* set to 1 for BPSK */ +/* set to 2 for QPSK */ +/* set to 3 for 16-QAM */ +#define HE_SET_PHY_CAP_DCM_MAX_CONSTELLATION_RX(_aucHePhyCapInfo, _ucVal) \ +{ \ + _aucHePhyCapInfo[3] &= ~(HE_PHY_CAP3_DCM_MAX_CONSTELLATION_RX_MASK); \ + _aucHePhyCapInfo[3] |= \ + ((_ucVal << HE_PHY_CAP3_DCM_MAX_CONSTELLATION_RX_SHFT) \ + & HE_PHY_CAP3_DCM_MAX_CONSTELLATION_RX_MASK); \ +} + +#define HE_GET_PHY_CAP_DCM_MAX_CONSTELLATION_TX(_aucHePhyCapInfo) \ + ((_aucHePhyCapInfo[3] & HE_PHY_CAP3_DCM_MAX_CONSTELLATION_TX_MASK) \ + >> HE_PHY_CAP3_DCM_MAX_CONSTELLATION_TX_SHFT) + +#define HE_GET_PHY_CAP_DCM_MAX_CONSTELLATION_RX(_aucHePhyCapInfo) \ + ((_aucHePhyCapInfo[3] & HE_PHY_CAP3_DCM_MAX_CONSTELLATION_RX_MASK) \ + >> HE_PHY_CAP3_DCM_MAX_CONSTELLATION_RX_SHFT) + +#define HE_SET_PHY_CAP_SU_BFMEE(_aucHePhyCapInfo) \ + (_aucHePhyCapInfo[4] |= HE_PHY_CAP4_SU_BFMEE) + +#define HE_UNSET_PHY_CAP_MU_BFMER(_aucHePhyCapInfo) \ + (_aucHePhyCapInfo[4] &= ~HE_PHY_CAP4_MU_BFMER) + +#define HE_SET_PHY_CAP_BFMEE_STS_LT_OR_EQ_80M(_aucHePhyCapInfo, _ucSts) \ +{ \ + _aucHePhyCapInfo[4] &= ~(HE_PHY_CAP4_BFMEE_STS_LT_OR_EQ_80M_MASK); \ + _aucHePhyCapInfo[4] |= \ + ((_ucSts << HE_PHY_CAP4_BFMEE_STS_LT_OR_EQ_80M_SHFT) \ + & HE_PHY_CAP4_BFMEE_STS_LT_OR_EQ_80M_MASK); \ +} + +#define HE_SET_PHY_CAP_NG_16_SU_FB(_aucHePhyCapInfo) \ + (_aucHePhyCapInfo[5] |= HE_PHY_CAP5_NG_16_SU_FB) + +#define HE_SET_PHY_CAP_NG_16_MU_FB(_aucHePhyCapInfo) \ + (_aucHePhyCapInfo[5] |= HE_PHY_CAP5_NG_16_MU_FB) + +#define HE_SET_PHY_CAP_CODE_BOOK_4_2_SU_FB(_aucHePhyCapInfo) \ + (_aucHePhyCapInfo[6] |= HE_PHY_CAP6_CODE_BOOK_4_2_SU_FB) + +#define HE_SET_PHY_CAP_CODE_BOOK_7_5_MU_FB(_aucHePhyCapInfo) \ + (_aucHePhyCapInfo[6] |= HE_PHY_CAP6_CODE_BOOK_7_5_MU_FB) + +#define HE_SET_PHY_CAP_TRIG_SU_BF_FB(_aucHePhyCapInfo) \ + (_aucHePhyCapInfo[6] |= HE_PHY_CAP6_TRIG_SU_BF_FB) + +#define HE_SET_PHY_CAP_TRIG_MU_BF_PARTIAL_BW_FB(_aucHePhyCapInfo) \ + (_aucHePhyCapInfo[6] |= HE_PHY_CAP6_TRIG_MU_BF_PARTIAL_BW_FB) + +#define HE_SET_PHY_CAP_HE_PHY_CAP6_TRIG_MU_BF_PARTIAL_BW_FB(_aucHePhyCapInfo) \ + (_aucHePhyCapInfo[6] |= HE_PHY_CAP6_TRIG_MU_BF_PARTIAL_BW_FB) + +#define HE_SET_PHY_CAP_PARTIAL_BW_EXTENDED_RANGE(_aucHePhyCapInfo) \ + (_aucHePhyCapInfo[6] |= HE_PHY_CAP6_PARTIAL_BW_EXTENDED_RANGE) + +#define HE_GET_PHY_CAP_PARTIAL_BW_EXTENDED_RANGE(_aucHePhyCapInfo) \ + ((_aucHePhyCapInfo[6] & HE_PHY_CAP6_PARTIAL_BW_EXTENDED_RANGE) \ + >> HE_PHY_CAP6_PARTIAL_BW_EXTENDED_RANGE_SHFT) + +#define HE_IS_PHY_CAP_PPE_THRESHOLD(_aucHePhyCapInfo) \ + (_aucHePhyCapInfo[6] & HE_PHY_CAP6_PPE_THRESHOLD) + +#define HE_SET_PHY_CAP_MAX_NC(_aucHePhyCapInfo, _ucMaxNc) \ +{ \ + _aucHePhyCapInfo[7] &= ~(HE_PHY_CAP7_MAX_NC_MASK); \ + _aucHePhyCapInfo[7] |= ((_ucMaxNc << HE_PHY_CAP7_MAX_NC_SHFT) \ + & HE_PHY_CAP7_MAX_NC_MASK); \ +} + +#define HE_SET_PHY_CAP_STBC_TX_GT_80M(_aucHePhyCapInfo) \ + (_aucHePhyCapInfo[7] |= HE_PHY_CAP7_STBC_TX_GT_80M) + +#define HE_SET_PHY_CAP_STBC_RX_GT_80M(_aucHePhyCapInfo) \ + (_aucHePhyCapInfo[7] |= HE_PHY_CAP7_STBC_RX_GT_80M) + +#define HE_SET_PHY_CAP_ER_SU_4X_HE_LTF(_aucHePhyCapInfo) \ + (_aucHePhyCapInfo[8] |= HE_PHY_CAP8_ER_SU_4X_HE_LTF) + +#define HE_GET_PHY_CAP_ER_SU_4X_HE_LTF(_aucHePhyCapInfo) \ + ((_aucHePhyCapInfo[8] & HE_PHY_CAP8_ER_SU_4X_HE_LTF) \ + >> HE_PHY_CAP8_ER_SU_4X_HE_LTF_SHFT) + +#define HE_SET_PHY_CAP_ER_SU_PPDU_1X_HE_LTF(_aucHePhyCapInfo) \ + (_aucHePhyCapInfo[8] |= HE_PHY_CAP8_ER_SU_PPDU_1X_HE_LTF) + +#define HE_GET_PHY_CAP_ER_SU_PPDU_1X_HE_LTF(_aucHePhyCapInfo) \ + ((_aucHePhyCapInfo[8] & HE_PHY_CAP8_ER_SU_PPDU_1X_HE_LTF) \ + >> HE_PHY_CAP8_ER_SU_PPDU_1X_HE_LTF_SHFT) + +/* should use macro to access field of HE OP*/ +#define HE_IS_VHT_OP_INFO_PRESENT(_aucHeOpParams) \ + (_aucHeOpParams[1] |= HE_OP_PARAM1_VHT_OP_INFO_PRESENT) + + +#define HE_IS_HTC_HE_VARIANT(_u4HTC) \ + (_u4HTC & HTC_HE_VARIANT == HTC_HE_VARIANT) +#define HE_SET_HTC_HE_VARIANT(_u4HTC) \ + (_u4HTC |= HTC_HE_VARIANT) + +/* Control ID */ +#define HE_SET_HTC_1ST_A_CTRL_ID(_u4HTC, _ctrl_id) \ +{\ +(_u4HTC) &= ~(HTC_HE_1ST_A_CTRL_ID); \ +(_u4HTC) |= (((_ctrl_id) << (HTC_HE_1ST_A_CTRL_ID_SHIFT)) \ + & (HTC_HE_1ST_A_CTRL_ID)); \ +} +#define HE_GET_HTC_1ST_A_CTRL_ID(_u4HTC) \ + ((_u4HTC & HTC_HE_1ST_A_CTRL_ID) >> HTC_HE_1ST_A_CTRL_ID_SHIFT) + +#define HE_SET_HTC_2ND_A_CTRL_ID(_u4HTC, _ctrl_id) \ +{\ + (_u4HTC) &= ~(HTC_HE_2ND_A_CTRL_ID); \ + (_u4HTC) |= (((_ctrl_id) << (HTC_HE_2ND_A_CTRL_ID_SHIFT)) \ + & (HTC_HE_2ND_A_CTRL_ID)); \ +} +#define HE_GET_HTC_2ND_A_CTRL_ID(_u4HTC) \ + ((_u4HTC & HTC_HE_2ND_A_CTRL_ID) >> HTC_HE_2ND_A_CTRL_ID_SHIFT) + +/* OM - RX NSS */ +#define HE_SET_HTC_HE_OM_RX_NSS(_u4HTC, _rx_nss) \ +{\ +(_u4HTC) &= ~(HTC_HE_OM_RX_NSS); \ +(_u4HTC) |= (((_rx_nss) << (HTC_HE_OM_RX_NSS_SHFT)) & (HTC_HE_OM_RX_NSS)); \ +} +#define HE_GET_HTC_HE_OM_RX_NSS(_u4HTC) \ + ((_u4HTC & HTC_HE_OM_RX_NSS) >> HTC_HE_OM_RX_NSS_SHFT) + +/* OM - TX NSTS */ +#define HE_SET_HTC_HE_OM_TX_NSTS(_u4HTC, _tx_nsts) \ +{\ +(_u4HTC) &= ~(HTC_HE_OM_TX_NSTS); \ +(_u4HTC) |= (((_tx_nsts) << (HTC_HE_OM_TX_NSTS_SHFT)) & (HTC_HE_OM_TX_NSTS)); \ +} +#define HE_GET_HTC_HE_OM_TX_NSTS(_u4HTC) \ + ((_u4HTC & HTC_HE_OM_TX_NSTS) >> HTC_HE_OM_TX_NSTS_SHFT) + +/* OM - Channel Width */ +#define HE_SET_HTC_HE_OM_CH_WIDTH(_u4HTC, _bw) \ +{\ +(_u4HTC) &= ~(HTC_HE_OM_CH_WIDTH); \ +(_u4HTC) |= (((_bw) << (HTC_HE_OM_CH_WIDTH_SHFT)) & (HTC_HE_OM_CH_WIDTH)); \ +} +#define HE_GET_HTC_HE_OM_CH_WIDTH(_u4HTC) \ + ((_u4HTC & HTC_HE_OM_CH_WIDTH) >> HTC_HE_OM_CH_WIDTH_SHFT) + +/* OM - ER SU Disable */ +#define HE_SET_HTC_HE_OM_ER_SU_DISABLE(_u4HTC, _er_dis) \ +{\ +(_u4HTC) &= ~(HTC_HE_OM_ER_SU_DISABLE); \ +(_u4HTC) |= (((_er_dis) << (HTC_HE_OM_ER_SU_DISABLE_SHFT)) \ + & (HTC_HE_OM_ER_SU_DISABLE)); \ +} +#define HE_GET_HTC_HE_OM_ER_SU_DISABLE(_u4HTC) \ + ((_u4HTC & HTC_HE_OM_ER_SU_DISABLE) >> HTC_HE_OM_ER_SU_DISABLE_SHFT) + +/* OM - UL MU Disable */ +#define HE_SET_HTC_HE_OM_UL_MU_DISABLE(_u4HTC, _ul_dis) \ +{\ +(_u4HTC) &= ~(HTC_HE_OM_UL_MU_DISABLE); \ +(_u4HTC) |= (((_ul_dis) << (HTC_HE_OM_UL_MU_DISABLE_SHFT)) \ + & (HTC_HE_OM_UL_MU_DISABLE)); \ +} +#define HE_GET_HTC_HE_OM_UL_MU_DISABLE(_u4HTC) \ + ((_u4HTC & HTC_HE_OM_UL_MU_DISABLE) >> HTC_HE_OM_UL_MU_DISABLE_SHFT) + +/* OM - UL MU Data Disable */ +#define HE_SET_HTC_HE_OM_UL_MU_DATA_DISABLE(_u4HTC, _ul_data_dis) \ +{\ +(_u4HTC) &= ~(HTC_HE_OM_UL_MU_DATA_DISABLE); \ +(_u4HTC) |= (((_ul_data_dis) << (HTC_HE_OM_UL_MU_DATA_DISABLE_SHFT)) \ + & (HTC_HE_OM_UL_MU_DATA_DISABLE)); \ +} +#define HE_GET_HTC_HE_OM_UL_MU_DATA_DISABLE(_u4HTC) \ + ((_u4HTC & HTC_HE_OM_UL_MU_DATA_DISABLE) \ + >> HTC_HE_OM_UL_MU_DATA_DISABLE_SHFT) + +/* UPH - UL PWR HEADROOM */ +#define HE_SET_HTC_HE_UPH(_u4HTC, _uph) \ +{\ +(_u4HTC) &= ~(HTC_HE_UPH_UL_PWR_HEADROOM); \ +(_u4HTC) |= (((_uph) << (HTC_HE_UPH_UL_PWR_HEADROOM_SHIFT)) \ + & (HTC_HE_UPH_UL_PWR_HEADROOM)); \ +} +#define HE_GET_HTC_HE_UPH(_u4HTC) \ + ((_u4HTC & HTC_HE_UPH_UL_PWR_HEADROOM) \ + >> HTC_HE_UPH_UL_PWR_HEADROOM_SHIFT) + +/* UPH - MIN TX PWR FLAG */ +#define HE_SET_HTC_HE_UPH_MIN_TX_PWR_FLAG(_u4HTC, _flag) \ +{\ +(_u4HTC) &= ~(HTC_HE_UPH_MIN_TX_PWR_FLAG); \ +(_u4HTC) |= (((_flag) << (HTC_HE_UPH_MIN_TX_PWR_FLAG_SHIFT)) \ + & (HTC_HE_UPH_MIN_TX_PWR_FLAG)); \ +} +#define HE_GET_HTC_HE_UPH_MIN_TX_PWR_FLAG(_u4HTC) \ + ((_u4HTC & HTC_HE_UPH_MIN_TX_PWR_FLAG) \ + >> HTC_HE_UPH_MIN_TX_PWR_FLAG_SHIFT) + +/* should use macro to access field of HE OP*/ +#define HE_RESET_HE_OP(_aucHeOpInfo) \ + memset(_aucHeOpInfo, 0, HE_OP_BYTE_NUM) + +#define HE_SET_OP_PARAM_ER_SU_DISABLE(_aucHeOpParams) \ + (_aucHeOpParams[2] |= HE_OP_PARAM2_ER_SU_DISABLE_MASK) + +#define HE_IS_ER_SU_DISABLE(_aucHeOpParams) \ + (_aucHeOpParams[2] & HE_OP_PARAM2_ER_SU_DISABLE_MASK) + +struct _IE_HE_CAP_T { + u_int8_t ucId; + u_int8_t ucLength; + u_int8_t ucExtId; + u_int8_t ucHeMacCap[HE_MAC_CAP_BYTE_NUM]; /* BIT0 ~ BIT47 */ + u_int8_t ucHePhyCap[HE_PHY_CAP_BYTE_NUM]; /* BIT0 ~ BIT87 */ + u_int8_t aucVarInfo[0]; +} __KAL_ATTRIB_PACKED__; + +struct _IE_HE_OP_T { + u_int8_t ucId; + u_int8_t ucLength; + u_int8_t ucExtId; + u_int8_t ucHeOpParams[HE_OP_BYTE_NUM]; + u_int8_t ucBssColorInfo; + u_int16_t u2HeBasicMcsSet; + u_int8_t aucVarInfo[0]; +} __KAL_ATTRIB_PACKED__; + +struct _HE_SUPPORTED_MCS_FIELD { + u_int16_t u2RxMcsMap; + u_int16_t u2TxMcsMap; +} __KAL_ATTRIB_PACKED__; + +struct _PPE_THRESHOLD_FIELD { + /* 128-bit space can support 4 NSS */ + u_int64_t u8Space0; + u_int64_t u8Space1; +} __KAL_ATTRIB_PACKED__; + +struct _VHT_OP_INFO_T { + u_int8_t ucVhtOperation[3]; +} __KAL_ATTRIB_PACKED__; + +struct _HE_MAX_BSSID_IND_T { + u_int8_t ucMaxBSSIDIndicator; +} __KAL_ATTRIB_PACKED__; + +struct _MU_AC_PARAM_RECORD_T { + u_int8_t ucAciAifsn; + u_int8_t ucEcw; + u_int8_t ucMUEdcaTimer; +} __KAL_ATTRIB_PACKED__; + +struct _IE_MU_EDCA_PARAM_T { + u_int8_t ucId; + u_int8_t ucLength; + u_int8_t ucExtId; + u_int8_t ucMUQosInfo; + struct _MU_AC_PARAM_RECORD_T arMUAcParam[4]; +} __KAL_ATTRIB_PACKED__; + +struct _SRG_SR_INFO_T { + u_int8_t ucObssPdMinOffset; + u_int8_t ucObssPdMaxOffset; + u_int64_t u8BSSColorBitmap; + u_int64_t u8PartialBSSIDBitmap; +} __KAL_ATTRIB_PACKED__; + +struct _NON_SRG_SR_INFO_T { + u_int8_t ucObssPdMaxOffset; +} __KAL_ATTRIB_PACKED__; + +struct _IE_SR_PARAM_T { + u_int8_t ucId; + u_int8_t ucLength; + u_int8_t ucExtId; + u_int8_t ucSRControl; + u_int8_t aucVarInfo[1]; +} __KAL_ATTRIB_PACKED__; + +#endif /* CFG_SUPPORT_802_11AX == 1 */ +#endif /* !_HE_IE_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/he_rlm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/he_rlm.h new file mode 100644 index 0000000000000..f657ca4a4d90d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/he_rlm.h @@ -0,0 +1,187 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/*! \file "rlm.h" + * \brief + */ + +#ifndef _HE_RLM_H +#define _HE_RLM_H + +#if (CFG_SUPPORT_802_11AX == 1) + +/****************************************************************************** + * C O M P I L E R F L A G S + ****************************************************************************** + */ + +/****************************************************************************** + * E X T E R N A L R E F E R E N C E S + ****************************************************************************** + */ + +/****************************************************************************** + * C O N S T A N T S + ****************************************************************************** + */ + +#define HE_PHY_CAP2_INFO_DEFAULT_VAL (HE_PHY_CAP2_FULL_BW_UL_MU_MIMO | \ + HE_PHY_CAP2_PARTIAL_BW_UL_MU_MIMO) +#define HE_PHY_CAP6_INFO_DEFAULT_VAL (HE_PHY_CAP6_PPE_THRESHOLD) + +#define PPE_RU_IDX_SIZE 4 +#define PPE_SUBFIELD_BITS_NUM 6 + +/****************************************************************************** + * M A C R O S + ****************************************************************************** + */ +#define HE_RESET_MAC_CAP(_aucHeMacCapInfo) \ + (memset(_aucHeMacCapInfo, 0, HE_MAC_CAP_BYTE_NUM)) + +#define HE_RESET_PHY_CAP(_aucHePhyCapInfo) \ +{ \ + memset(_aucHePhyCapInfo, 0, HE_PHY_CAP_BYTE_NUM); \ + _aucHePhyCapInfo[2] = (u_int8_t)HE_PHY_CAP2_INFO_DEFAULT_VAL; \ + _aucHePhyCapInfo[6] = (u_int8_t)HE_PHY_CAP6_INFO_DEFAULT_VAL; \ +} + +/****************************************************************************** + * D A T A T Y P E S + ****************************************************************************** + */ +struct __HE_TWT_INFO_T { + u_int8_t ucFlowType; + u_int8_t ucFlowID; + u_int8_t ucIntervalExp; + u_int8_t ucProtection; +}; + +struct __HE_CFG_INFO_T { + u_int8_t fgHeSupport; /* HE Support */ + u_int8_t fgHeEnable; /* HE Enable/Disable Control */ + u_int8_t fgTwtRequesterEnable; /* HW TWT Requester Control */ + u_int8_t fgTwtResponderEnable; /* HW TWT Responder Control */ + u_int8_t fgHtcHe; /* +HTC HE Support */ + u_int8_t fgFragment; /* Fragmentation Support */ + u_int8_t fgMultiTidAgg; /* Multi-TID Aggregation Support */ + u_int8_t fgAmsduFragment; /* A-MSDU Fragmentation Support */ + u_int8_t fg32bitBaBitmap; /* 32-bit BA Bitmap Support */ +}; + +struct HE_A_CTRL_OM_T { + u_int8_t ucRxNss; + u_int8_t ucTxNsts; + u_int8_t ucBW; + u_int8_t fgDisMuUL; + u_int8_t fgDisMuULData; +}; + + +/****************************************************************************** + * 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 + ****************************************************************************** + */ + +u_int32_t heRlmCalculateHeCapIELen( + struct ADAPTER *prAdapter, + u_int8_t ucBssIndex, + struct STA_RECORD *prStaRec); +u_int32_t heRlmCalculateHeOpIELen( + struct ADAPTER *prAdapter, + u_int8_t ucBssIndex, + struct STA_RECORD *prStaRec); +void heRlmReqGenerateHeCapIE( + struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); +void heRlmRspGenerateHeCapIE( + struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); +void heRlmRspGenerateHeOpIE( + struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); +void heRlmRecHeCapInfo( + struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + u_int8_t *pucIE); +void heRlmRecHeOperation( + struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + u_int8_t *pucIE); +u_int8_t heRlmRecHeSRParams( + struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct SW_RFB *prSwRfb, + u_int8_t *pucIE, + u_int16_t u2IELength); +void heRlmInitHeHtcACtrlOMAndUPH( + struct ADAPTER *prAdapter); +void heRlmParseHeHtcACtrlOM( + uint32_t u4Htc, + struct HE_A_CTRL_OM_T *prHeActrlOM); +uint32_t heRlmSendHtcNullFrame( + IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN uint8_t ucUP, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler); +#endif /* CFG_SUPPORT_802_11AX == 1 */ +#endif /* !_HE_RLM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/hem_mbox.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/hem_mbox.h new file mode 100644 index 0000000000000..d1e105bfc41b1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/hem_mbox.h @@ -0,0 +1,452 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: include/mgmt/hem_mbox.h + */ + +/*! \file hem_mbox.h + * \brief + * + */ + +#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 */ +enum ENUM_MSG_ID { + /* MANY notify CNM to obtain channel privilege */ + MID_MNY_CNM_CH_REQ, + /* MANY notify CNM to abort/release channel privilege */ + MID_MNY_CNM_CH_ABORT, + + /* CNM notify AIS for indicating channel granted */ + MID_CNM_AIS_CH_GRANT, + /* CNM notify P2P for indicating channel granted */ + MID_CNM_P2P_CH_GRANT, + /* CNM notify BOW for indicating channel granted */ + MID_CNM_BOW_CH_GRANT, + +#if (CFG_SUPPORT_DFS_MASTER == 1) + MID_CNM_P2P_RADAR_DETECT, + MID_CNM_P2P_CSA_DONE, +#endif + /*--------------------------------------------------*/ + /* SCN Module Mailbox Messages */ + /*--------------------------------------------------*/ + /* AIS notify SCN for starting scan */ + MID_AIS_SCN_SCAN_REQ, + /* AIS notify SCN for starting scan with multiple SSID support */ + MID_AIS_SCN_SCAN_REQ_V2, + /* AIS notify SCN for cancelling scan */ + MID_AIS_SCN_SCAN_CANCEL, + /* P2P notify SCN for starting scan */ + MID_P2P_SCN_SCAN_REQ, + /* P2P notify SCN for starting scan with multiple SSID support */ + MID_P2P_SCN_SCAN_REQ_V2, + /* P2P notify SCN for cancelling scan */ + MID_P2P_SCN_SCAN_CANCEL, + /* BOW notify SCN for starting scan */ + MID_BOW_SCN_SCAN_REQ, + /* BOW notify SCN for starting scan with multiple SSID support */ + MID_BOW_SCN_SCAN_REQ_V2, + /* BOW notify SCN for cancelling scan */ + MID_BOW_SCN_SCAN_CANCEL, + /* RLM notify SCN for starting scan (OBSS-SCAN) */ + MID_RLM_SCN_SCAN_REQ, + /* RLM notify SCN for starting scan (OBSS-SCAN) + * with multiple SSID support + */ + MID_RLM_SCN_SCAN_REQ_V2, + /* RLM notify SCN for cancelling scan (OBSS-SCAN) */ + MID_RLM_SCN_SCAN_CANCEL, + /* SCN notify AIS for scan completion */ + MID_SCN_AIS_SCAN_DONE, + /* SCN notify P2P for scan completion */ + MID_SCN_P2P_SCAN_DONE, + /* SCN notify BOW for scan completion */ + MID_SCN_BOW_SCAN_DONE, + /* SCN notify RLM for scan completion (OBSS-SCAN) */ + MID_SCN_RLM_SCAN_DONE, + + /*--------------------------------------------------*/ + /* AIS Module Mailbox Messages */ + /*--------------------------------------------------*/ + /* OID/IOCTL notify AIS for join */ + MID_OID_AIS_FSM_JOIN_REQ, + /* OID/IOCTL notify AIS for abort */ + MID_OID_AIS_FSM_ABORT, + /* AIS notify SAA for Starting authentication/association fsm */ + MID_AIS_SAA_FSM_START, + /* OID notify SAA to continue to do authentication/association fsm for + ** FT + */ + MID_OID_SAA_FSM_CONTINUE, + /* OID notify SAA to continue SAE authentication/association fsm */ + MID_OID_SAA_FSM_EXTERNAL_AUTH, + /* AIS notify SAA for Aborting authentication/association fsm */ + MID_AIS_SAA_FSM_ABORT, + /* SAA notify AIS for indicating join complete */ + MID_SAA_AIS_JOIN_COMPLETE, + +#if CFG_ENABLE_BT_OVER_WIFI + /*--------------------------------------------------*/ + /* BOW Module Mailbox Messages */ + /*--------------------------------------------------*/ + /* BOW notify SAA for Starting authentication/association fsm */ + MID_BOW_SAA_FSM_START, + /* BOW notify SAA for Aborting authentication/association fsm */ + MID_BOW_SAA_FSM_ABORT, + /* SAA notify BOW for indicating join complete */ + MID_SAA_BOW_JOIN_COMPLETE, +#endif + +#if CFG_ENABLE_WIFI_DIRECT + /*--------------------------------------------------*/ + /* P2P Module Mailbox Messages */ + /*--------------------------------------------------*/ + /* P2P notify SAA for Starting authentication/association fsm */ + MID_P2P_SAA_FSM_START, + /* P2P notify SAA for Aborting authentication/association fsm */ + MID_P2P_SAA_FSM_ABORT, + /* SAA notify P2P for indicating join complete */ + MID_SAA_P2P_JOIN_COMPLETE, + + MID_MNY_P2P_FUN_SWITCH, /* Enable P2P FSM. */ + /* Start device discovery. */ + MID_MNY_P2P_DEVICE_DISCOVERY, + /* Connection request. */ + MID_MNY_P2P_CONNECTION_REQ, + /* Abort connection request, P2P FSM return to IDLE. */ + MID_MNY_P2P_CONNECTION_ABORT, + 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_MGMT_TX_CANCEL_WAIT, + 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_DEL_IFACE, + MID_MNY_P2P_MGMT_FRAME_UPDATE, +#if (CFG_SUPPORT_DFS_MASTER == 1) + MID_MNY_P2P_DFS_CAC, + MID_MNY_P2P_SET_NEW_CHANNEL, +#endif +#if CFG_SUPPORT_WFD + MID_MNY_P2P_WFD_CFG_UPDATE, +#endif + MID_MNY_P2P_ACTIVE_BSS, +#endif + +#if CFG_SUPPORT_ADHOC + /* SCN notify AIS that an IBSS Peer has been found + * and can merge into + */ + MID_SCN_AIS_FOUND_IBSS, +#endif /* CFG_SUPPORT_ADHOC */ + + /* SAA notify AIS for indicating deauthentication/disassociation */ + MID_SAA_AIS_FSM_ABORT, + + /*--------------------------------------------------*/ + /* AIS MGMT-TX Support */ + /*--------------------------------------------------*/ + MID_MNY_AIS_REMAIN_ON_CHANNEL, + MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL, + MID_MNY_AIS_MGMT_TX, + MID_MNY_AIS_MGMT_TX_CANCEL_WAIT, + MID_WNM_AIS_BSS_TRANSITION, + MID_OID_WMM_TSPEC_OPERATE, + MID_RRM_REQ_SCHEDULE, +#if CFG_SUPPORT_NCHO + MID_MNY_AIS_NCHO_ACTION_FRAME, +#endif + MID_MNY_P2P_ACS, +#if (CFG_SUPPORT_TWT == 1) + /*--------------------------------------------------*/ + /* TWT Requester Support */ + /*--------------------------------------------------*/ + MID_TWT_REQ_FSM_START, + MID_TWT_REQ_FSM_TEARDOWN, + MID_TWT_REQ_FSM_SUSPEND, + MID_TWT_REQ_FSM_RESUME, + MID_TWT_REQ_IND_RESULT, + MID_TWT_REQ_IND_SUSPEND_DONE, + MID_TWT_REQ_IND_RESUME_DONE, + MID_TWT_REQ_IND_TEARDOWN_DONE, + MID_TWT_REQ_IND_INFOFRM, + MID_TWT_PARAMS_SET, +#endif + MID_TOTAL_NUM +}; + +/* Message header of inter-components */ +struct MSG_HDR { + struct LINK_ENTRY rLinkEntry; + enum ENUM_MSG_ID eMsgId; +}; + +typedef void(*PFN_MSG_HNDL_FUNC) (struct ADAPTER *, + struct MSG_HDR *); + +struct MSG_HNDL_ENTRY { + enum ENUM_MSG_ID eMsgId; + PFN_MSG_HNDL_FUNC pfMsgHndl; +}; + +enum EUNM_MSG_SEND_METHOD { + /* Message is put in the queue and will be */ + MSG_SEND_METHOD_BUF = 0, + /*executed when mailbox is checked. */ + /* The handler function is called immediately */ + MSG_SEND_METHOD_UNBUF + /* in the same context of the sender */ +}; + +enum ENUM_MBOX_ID { + MBOX_ID_0 = 0, + MBOX_ID_TOTAL_NUM +}; + +/* Define Mailbox structure */ +struct MBOX { + struct LINK rLinkHead; +}; + +struct MSG_SAA_FSM_START { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucSeqNum; + struct STA_RECORD *prStaRec; +}; + +struct MSG_SAA_FSM_COMP { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucSeqNum; + uint32_t rJoinStatus; + struct STA_RECORD *prStaRec; + struct SW_RFB *prSwRfb; +}; + +struct MSG_SAA_FSM_ABORT { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucSeqNum; + struct STA_RECORD *prStaRec; +}; + +struct MSG_CONNECTION_ABORT { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucNetTypeIndex; +}; + +struct MSG_REMAIN_ON_CHANNEL { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + enum ENUM_BAND eBand; + enum ENUM_CHNL_EXT eSco; + uint8_t ucChannelNum; + uint32_t u4DurationMs; + uint64_t u8Cookie; + enum ENUM_CH_REQ_TYPE eReqType; + uint8_t ucBssIdx; +}; + +struct MSG_CANCEL_REMAIN_ON_CHANNEL { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint64_t u8Cookie; + uint8_t ucBssIdx; +}; + +struct MSG_MGMT_TX_REQUEST { + struct MSG_HDR rMsgHdr; + uint8_t ucBssIdx; + struct MSDU_INFO *prMgmtMsduInfo; + uint64_t u8Cookie; /* For indication. */ + u_int8_t fgNoneCckRate; + u_int8_t fgIsOffChannel; + struct RF_CHANNEL_INFO rChannelInfo; + enum ENUM_CHNL_EXT eChnlExt; + u_int8_t fgIsWaitRsp; + uint32_t u4Duration; +}; + +#if (CFG_SUPPORT_TWT == 1) +struct _MSG_TWT_REQFSM_START_T { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + struct STA_RECORD *prStaRec; + u_int8_t ucTWTFlowId; +}; + +struct _MSG_TWT_REQFSM_IND_RESULT_T { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + struct STA_RECORD *prStaRec; + u_int8_t ucTWTFlowId; +}; + +struct _MSG_TWT_REQFSM_TEARDOWN_T { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + struct STA_RECORD *prStaRec; + u_int8_t ucTWTFlowId; +}; + +struct _MSG_TWT_REQFSM_SUSPEND_T { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + struct STA_RECORD *prStaRec; + u_int8_t ucTWTFlowId; +}; + +struct _MSG_TWT_REQFSM_RESUME_T { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + struct STA_RECORD *prStaRec; + u_int8_t ucTWTFlowId; + u_int8_t ucNextTWTSize; + u_int64_t u8NextTWT; +}; + +struct _MSG_TWT_REQFSM_IND_INFOFRM_T { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + struct STA_RECORD *prStaRec; + u_int8_t ucTWTFlowId; + struct _NEXT_TWT_INFO_T rNextTWTInfo; +}; + +struct _MSG_TWT_PARAMS_SET_T { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + struct _TWT_CTRL_T rTWTCtrl; +}; +#endif + +struct MSG_CANCEL_TX_WAIT_REQUEST { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint64_t u8Cookie; + uint8_t ucBssIdx; +}; + +struct MSG_SAA_FT_CONTINUE { + struct MSG_HDR rMsgHdr; + struct STA_RECORD *prStaRec; + /* if fgFTRicRequest is TRUE, then will do FT Resource + ** Request Protocol + */ + u_int8_t fgFTRicRequest; +}; + +struct MSG_SAA_EXTERNAL_AUTH_DONE { + struct MSG_HDR rMsgHdr; + struct STA_RECORD *prStaRec; + uint16_t status; +}; + +/* specific message data types */ + +/******************************************************************************* + * P U B 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 struct ADAPTER *prAdapter, + IN enum ENUM_MBOX_ID eMboxId); + +void +mboxSendMsg(IN struct ADAPTER *prAdapter, + IN enum ENUM_MBOX_ID eMboxId, IN struct MSG_HDR *prMsg, + IN enum EUNM_MSG_SEND_METHOD eMethod); + +void mboxRcvAllMsg(IN struct ADAPTER *prAdapter, + IN enum ENUM_MBOX_ID eMboxId); + +void mboxInitialize(IN struct ADAPTER *prAdapter); + +void mboxDestroy(IN struct ADAPTER *prAdapter); + +void mboxDummy(IN struct ADAPTER *prAdapter, + struct MSG_HDR *prMsgHdr); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _HEM_MBOX_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/hs20.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/hs20.h new file mode 100644 index 0000000000000..b3ca798dd4a59 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/hs20.h @@ -0,0 +1,200 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/*! \file hs20.h + * \brief This file contains the function declaration for hs20.c. + */ + +#ifndef _HS20_H +#define _HS20_H + +#if CFG_SUPPORT_PASSPOINT +/****************************************************************************** + * C O M P I L E R F L A G S + ****************************************************************************** + */ + +/****************************************************************************** + * E X T E R N A L R E F E R E N C E S + ****************************************************************************** + */ + +/****************************************************************************** + * C O N S T A N T S + ****************************************************************************** + */ +#define BSSID_POOL_MAX_SIZE 8 +#define HS20_SIGMA_SCAN_RESULT_TIMEOUT 30 /* sec */ + +/****************************************************************************** + * D A T A T Y P E S + ****************************************************************************** + */ + +#if CFG_ENABLE_GTK_FRAME_FILTER +/*For GTK Frame Filter*/ +struct IPV4_NETWORK_ADDRESS_LIST { + uint8_t ucAddrCount; + struct CMD_IPV4_NETWORK_ADDRESS arNetAddr[1]; +}; +#endif + +/* Entry of BSSID Pool - For SIGMA Test */ +struct BSSID_ENTRY { + uint8_t aucBSSID[MAC_ADDR_LEN]; +}; + +struct HS20_INFO { + /*Hotspot 2.0 Information */ + uint8_t aucHESSID[MAC_ADDR_LEN]; + uint8_t ucAccessNetworkOptions; + uint8_t ucVenueGroup; /* VenueInfo - Group */ + uint8_t ucVenueType; + uint8_t ucHotspotConfig; + + /*Roaming Consortium Information */ + /* PARAM_HS20_ROAMING_CONSORTIUM_INFO rRCInfo; */ + + /*Hotspot 2.0 dummy AP Info */ + + /*Time Advertisement Information */ + /* UINT_32 u4UTCOffsetTime; */ + /* UINT_8 aucTimeZone[ELEM_MAX_LEN_TIME_ZONE]; */ + /* UINT_8 ucLenTimeZone; */ + + /* For SIGMA Test */ + /* BSSID Pool */ + struct BSSID_ENTRY arBssidPool[BSSID_POOL_MAX_SIZE]; + uint8_t ucNumBssidPoolEntry; + u_int8_t fgIsHS2SigmaMode; + + uint8_t ucHotspotConfig; + u_int8_t fgConnectHS20AP; + +}; + +/****************************************************************************** + * P U B L I C D A T A + ****************************************************************************** + */ + +/****************************************************************************** + * P R I V A T E D A T A + ****************************************************************************** + */ + +/****************************************************************************** + * M A C R O S + ****************************************************************************** + */ + +/*For GTK Frame Filter*/ +#if DBG +#define FREE_IPV4_NETWORK_ADDR_LIST(_prAddrList) \ + { \ + uint32_t u4Size = \ + OFFSET_OF(struct IPV4_NETWORK_ADDRESS_LIST, \ + arNetAddr) + \ + (((_prAddrList)->ucAddrCount) * \ + sizeof(struct CMD_IPV4_NETWORK_ADDRESS)); \ + kalMemFree((_prAddrList), VIR_MEM_TYPE, u4Size); \ + (_prAddrList) = NULL; \ + } +#else +#define FREE_IPV4_NETWORK_ADDR_LIST(_prAddrList) \ + { \ + kalMemFree((_prAddrList), VIR_MEM_TYPE, 0); \ + (_prAddrList) = NULL; \ + } +#endif + +/****************************************************************************** + * F U N C T I O N S + ****************************************************************************** + */ + +void hs20FillExtCapIE(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, struct MSDU_INFO *prMsduInfo); + +void hs20FillProreqExtCapIE(IN struct ADAPTER *prAdapter, OUT uint8_t *pucIE); + +void hs20FillHS20IE(IN struct ADAPTER *prAdapter, OUT uint8_t *pucIE); + +uint32_t hs20CalculateHS20RelatedIEForProbeReq(IN struct ADAPTER *prAdapter, + IN uint8_t *pucTargetBSSID); + +uint32_t hs20GenerateHS20RelatedIEForProbeReq(IN struct ADAPTER *prAdapter, + IN uint8_t *pucTargetBSSID, OUT uint8_t *prIE); + +u_int8_t hs20IsGratuitousArp(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prCurrSwRfb); + +u_int8_t hs20IsUnsolicitedNeighborAdv(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prCurrSwRfb); + +#if CFG_ENABLE_GTK_FRAME_FILTER +u_int8_t hs20IsForgedGTKFrame(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, IN struct SW_RFB *prCurrSwRfb); +#endif + +u_int8_t hs20IsUnsecuredFrame(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, IN struct SW_RFB *prCurrSwRfb); + +u_int8_t hs20IsFrameFilterEnabled(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo); + +uint32_t hs20SetBssidPool(IN struct ADAPTER *prAdapter, + IN void *pvBuffer, + IN uint8_t ucBssIndex); + +#endif /* CFG_SUPPORT_PASSPOINT */ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/mddp.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/mddp.h new file mode 100644 index 0000000000000..9f262e31ac176 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/mddp.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ +/* + ** Id: //Department/DaVinci/BRANCHES/ + * MT6620_WIFI_DRIVER_V2_3/include/mgmt/mddp.h#1 + */ + +/*! \file "mddp.h" + * \brief The declaration of nic functions + * + * Detail description. + */ + + +#ifndef _MDDP_H +#define _MDDP_H + +#if CFG_MTK_MCIF_WIFI_SUPPORT + +/******************************************************************************* + * 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 + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "mddp_export.h" +#include "mddp.h" +/******************************************************************************* + * P U B 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 mddpInit(void); +int32_t mddpMdNotifyInfo(struct mddpw_md_notify_info_t *prMdInfo); +int32_t mddpChangeState(enum mddp_state_e event, void *buf, uint32_t *buf_len); +int32_t mddpGetMdStats(IN struct net_device *prDev); +int32_t mddpSetTxDescTemplate(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN uint8_t fgActivate); +void mddpUpdateReorderQueParm(struct ADAPTER *prAdapter, + struct RX_BA_ENTRY *prReorderQueParm, + struct SW_RFB *prSwRfb); +int32_t mddpNotifyDrvMac(IN struct ADAPTER *prAdapter); +int32_t mddpNotifyDrvTxd(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN uint8_t fgActivate); +int32_t mddpNotifyStaTxd(IN struct ADAPTER *prAdapter); +void mddpNotifyWifiOnStart(void); +int32_t mddpNotifyWifiOnEnd(void); +void mddpNotifyWifiOffStart(void); +void mddpNotifyWifiOffEnd(void); +void setMddpSupportRegister(IN struct ADAPTER *prAdapter); + +#endif +#endif /* _MDDP_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/mib.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/mib.h new file mode 100644 index 0000000000000..9c7b5513fc58e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/mib.h @@ -0,0 +1,189 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + + +#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 + */ +struct DOT11_AUTHENTICATION_ALGORITHMS_ENTRY { + /* dot11AuthenticationAlgorithmsEntry 3 */ + u_int8_t dot11AuthenticationAlgorithmsEnable; +}; + +/* Entry in SMT dot11RSNAConfigPairwiseCiphersTalbe Table: + * dot11RSNAConfigPairwiseCiphersEntry + */ +struct DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY { + /* dot11RSNAConfigPairwiseCiphersEntry 2 */ + uint32_t dot11RSNAConfigPairwiseCipher; + /* dot11RSNAConfigPairwiseCiphersEntry 3 */ + u_int8_t dot11RSNAConfigPairwiseCipherEnabled; +}; + +/* Entry in SMT dot11RSNAConfigAuthenticationSuitesTalbe Table: + * dot11RSNAConfigAuthenticationSuitesEntry + */ +struct DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY { + /* dot11RSNAConfigAuthenticationSuitesEntry 2 */ + uint32_t dot11RSNAConfigAuthenticationSuite; + /* dot11RSNAConfigAuthenticationSuitesEntry 3 */ + u_int8_t dot11RSNAConfigAuthenticationSuiteEnabled; +}; + +/* ----- IEEE 802.11 MIB Major sections ----- */ +struct IEEE_802_11_MIB { + /* dot11PrivacyTable (dot11smt 5) */ + uint8_t dot11WEPDefaultKeyID; /* dot11PrivacyEntry 2 */ + u_int8_t dot11TranmitKeyAvailable; + uint32_t dot11WEPICVErrorCount; /* dot11PrivacyEntry 5 */ + uint32_t dot11WEPExcludedCount; /* dot11PrivacyEntry 6 */ + + /* dot11RSNAConfigTable (dot11smt 8) */ + uint32_t dot11RSNAConfigGroupCipher; /* dot11RSNAConfigEntry 4 */ + + /* dot11RSNAConfigPairwiseCiphersTable (dot11smt 9) */ + struct DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY + dot11RSNAConfigPairwiseCiphersTable[MAX_NUM_SUPPORTED_CIPHER_SUITES]; + + /* dot11RSNAConfigAuthenticationSuitesTable (dot11smt 10) */ + struct DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY + dot11RSNAConfigAuthenticationSuitesTable[MAX_NUM_SUPPORTED_AKM_SUITES]; + +#if 0 /* SUPPORT_WAPI */ + u_int8_t fgWapiKeyInstalled; + struct PARAM_WPI_KEY rWapiPairwiseKey[2]; + u_int8_t fgPairwiseKeyUsed[2]; + uint8_t ucWpiActivedPWKey; /* Must be 0 or 1, by wapi spec */ + struct PARAM_WPI_KEY rWapiGroupKey[2]; + u_int8_t fgGroupKeyUsed[2]; +#endif +}; + +/* ------------------ IEEE 802.11 non HT PHY characteristics ---------------- */ +struct NON_HT_PHY_ATTRIBUTE { + uint16_t u2SupportedRateSet; + + u_int8_t fgIsShortPreambleOptionImplemented; + + u_int8_t fgIsShortSlotTimeOptionImplemented; +}; + +struct NON_HT_ATTRIBUTE { + enum ENUM_PHY_TYPE_INDEX ePhyTypeIndex; + + uint16_t u2BSSBasicRateSet; +}; + + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +extern const struct NON_HT_PHY_ATTRIBUTE + rNonHTPhyAttributes[]; +extern const struct NON_HT_ATTRIBUTE + rNonHTAdHocModeAttributes[]; +extern const struct NON_HT_ATTRIBUTE + rNonHTApModeAttributes[]; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _MIB_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_assoc.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_assoc.h new file mode 100644 index 0000000000000..da5c3286538bd --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_assoc.h @@ -0,0 +1,104 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/*! \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 + ****************************************************************************** + */ + +uint8_t *p2pBuildReAssocReqFrameCommonIEs(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN uint8_t *pucBuffer); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_bss.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_bss.h new file mode 100644 index 0000000000000..75704fc7d9266 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_bss.h @@ -0,0 +1,109 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 + ****************************************************************************** + */ + +uint32_t p2pGetTxProbRspIeTableSize(void); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_dev.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_dev.h new file mode 100644 index 0000000000000..260640ad0fe22 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_dev.h @@ -0,0 +1,270 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +enum ENUM_P2P_DEV_STATE { + P2P_DEV_STATE_IDLE = 0, + P2P_DEV_STATE_SCAN, + P2P_DEV_STATE_REQING_CHANNEL, + P2P_DEV_STATE_CHNL_ON_HAND, + P2P_DEV_STATE_OFF_CHNL_TX, + /* Requesting Channel to Send Specific Frame. */ + P2P_DEV_STATE_NUM +}; + +/*-------------------- EVENT MESSAGE ---------------------*/ +struct MSG_P2P_SCAN_REQUEST { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucBssIdx; + enum ENUM_SCAN_TYPE eScanType; + struct P2P_SSID_STRUCT *prSSID; + int32_t i4SsidNum; + uint32_t u4NumChannel; + uint8_t *pucIEBuf; + uint32_t u4IELen; + u_int8_t fgIsAbort; + enum ENUM_SCAN_REASON eScanReason; + struct RF_CHANNEL_INFO arChannelListInfo[1]; +}; + +struct MSG_P2P_CHNL_REQUEST { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint64_t u8Cookie; + uint32_t u4Duration; + enum ENUM_CHNL_EXT eChnlSco; + struct RF_CHANNEL_INFO rChannelInfo; + enum ENUM_CH_REQ_TYPE eChnlReqType; +}; + +#define P2P_DEV_EXTEND_CHAN_TIME 500 + +#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 { + uint32_t u4WfdCmdType; + uint8_t ucWfdEnable; + uint8_t ucWfdCoupleSinkStatus; + uint8_t ucWfdSessionAvailable; /* 0: NA 1:Set 2:Clear */ + uint8_t ucWfdSigmaMode; + uint16_t u2WfdDevInfo; + uint16_t u2WfdControlPort; + uint16_t u2WfdMaximumTp; + uint16_t u2WfdExtendCap; + uint8_t aucWfdCoupleSinkAddress[MAC_ADDR_LEN]; + uint8_t aucWfdAssociatedBssid[MAC_ADDR_LEN]; + uint8_t aucWfdVideoIp[4]; + uint8_t aucWfdAudioIp[4]; + uint16_t u2WfdVideoPort; + uint16_t u2WfdAudioPort; + uint32_t u4WfdFlag; + uint32_t u4WfdPolicy; + uint32_t u4WfdState; + uint8_t aucWfdSessionInformationIE[24 * 8]; + uint16_t u2WfdSessionInformationIELen; + uint8_t aucReserved1[2]; + uint8_t aucWfdPrimarySinkMac[MAC_ADDR_LEN]; + uint8_t aucWfdSecondarySinkMac[MAC_ADDR_LEN]; + uint32_t u4WfdAdvancedFlag; + /* Group 1 64 bytes */ + uint8_t aucWfdLocalIp[4]; + uint16_t u2WfdLifetimeAc2; /* Unit is 2 TU */ + uint16_t u2WfdLifetimeAc3; /* Unit is 2 TU */ + uint16_t u2WfdCounterThreshold; /* Unit is ms */ + uint8_t aucReverved2[54]; + /* Group 2 64 bytes */ + uint8_t aucReverved3[64]; + /* Group 3 64 bytes */ + uint8_t aucReverved4[64]; + uint32_t u4LinkScore; +}; + +#endif + +struct MSG_P2P_ACTIVE_DEV_BSS { + struct MSG_HDR rMsgHdr; +}; + +/*-------------------- P2P FSM ACTION STRUCT ---------------------*/ + +struct P2P_OFF_CHNL_TX_REQ_INFO { + struct LINK_ENTRY rLinkEntry; + struct MSDU_INFO *prMgmtTxMsdu; + u_int8_t fgNoneCckRate; + struct RF_CHANNEL_INFO rChannelInfo; /* Off channel TX. */ + enum ENUM_CHNL_EXT eChnlExt; + /* See if driver should keep at the same channel. */ + u_int8_t fgIsWaitRsp; + uint64_t u8Cookie; /* cookie used to match with supplicant */ + uint32_t u4Duration; /* wait time for tx request */ + uint8_t ucBssIndex; +}; + +struct P2P_DEV_FSM_INFO { + uint8_t ucBssIndex; + /* State related. */ + enum ENUM_P2P_DEV_STATE eCurrentState; + + /* Channel related. */ + struct P2P_CHNL_REQ_INFO rChnlReqInfo; + + /* Scan related. */ + struct P2P_SCAN_REQ_INFO rScanReqInfo; + + /* Mgmt tx related. */ + struct P2P_MGMT_TX_REQ_INFO rMgmtTxInfo; + + /* FSM Timer */ + struct TIMER rP2pFsmTimeoutTimer; + + /* Packet filter for P2P module. */ + uint32_t u4P2pPacketFilter; + + /* Queued p2p action frame */ + struct P2P_QUEUED_ACTION_FRAME rQueuedActionFrame; +}; + +struct MSG_P2P_NETDEV_REGISTER { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + u_int8_t fgIsEnable; + uint8_t ucMode; +}; + +#if CFG_SUPPORT_WFD +struct MSG_WFD_CONFIG_SETTINGS_CHANGED { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + struct WFD_CFG_SETTINGS *prWfdCfgSettings; +}; +#endif + +struct MSG_P2P_ACS_REQUEST { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucRoleIdx; + u_int8_t fgIsHtEnable; + u_int8_t fgIsHt40Enable; + u_int8_t fgIsVhtEnable; + enum ENUM_MAX_BANDWIDTH_SETTING eChnlBw; + enum P2P_VENDOR_ACS_HW_MODE eHwMode; + uint32_t u4NumChannel; + struct RF_CHANNEL_INFO arChannelListInfo[1]; +}; + +/*========================= Initial ============================*/ + +uint8_t p2pDevFsmInit(IN struct ADAPTER *prAdapter); + +void p2pDevFsmUninit(IN struct ADAPTER *prAdapter); + +/*========================= FUNCTIONs ============================*/ + +void +p2pDevFsmStateTransition(IN struct ADAPTER *prAdapter, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo, + IN enum ENUM_P2P_DEV_STATE eNextState); + +void p2pDevFsmRunEventAbort(IN struct ADAPTER *prAdapter, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo); + +void p2pDevFsmRunEventTimeout(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr); + +/*================ Message Event =================*/ +void p2pDevFsmRunEventScanRequest(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); +void p2pDevFsmRunEventScanAbort(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void +p2pDevFsmRunEventScanDone(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo); + +void p2pDevFsmRunEventChannelRequest(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pDevFsmRunEventChannelAbort(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void +p2pDevFsmRunEventChnlGrant(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo); + +void p2pDevFsmRunEventMgmtTx(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +uint32_t +p2pDevFsmRunEventMgmtFrameTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +void p2pDevFsmRunEventMgmtFrameRegister(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +/* /////////////////////////////// */ + +void p2pDevFsmRunEventActiveDevBss(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void +p2pDevFsmNotifyP2pRx(IN struct ADAPTER *prAdapter, uint8_t p2pFrameType, + u_int8_t *prFgBufferFrame); + +void p2pDevFsmRunEventTxCancelWait(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_dev_state.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_dev_state.h new file mode 100644 index 0000000000000..868e5d3fec75c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_dev_state.h @@ -0,0 +1,107 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#ifndef _P2P_DEV_STATE_H +#define _P2P_DEV_STATE_H + +u_int8_t +p2pDevStateInit_IDLE(IN struct ADAPTER *prAdapter, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + OUT enum ENUM_P2P_DEV_STATE *peNextState); + +void p2pDevStateAbort_IDLE(IN struct ADAPTER *prAdapter); + +u_int8_t +p2pDevStateInit_REQING_CHANNEL(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + OUT enum ENUM_P2P_DEV_STATE *peNextState); + +void +p2pDevStateAbort_REQING_CHANNEL(IN struct ADAPTER *prAdapter, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN enum ENUM_P2P_DEV_STATE eNextState); + +void +p2pDevStateInit_CHNL_ON_HAND(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo); + +void +p2pDevStateAbort_CHNL_ON_HAND(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN enum ENUM_P2P_DEV_STATE eNextState); + +void p2pDevStateInit_SCAN(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct P2P_SCAN_REQ_INFO *prScanReqInfo); + +void p2pDevStateAbort_SCAN(IN struct ADAPTER *prAdapter, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo); + +u_int8_t +p2pDevStateInit_OFF_CHNL_TX(IN struct ADAPTER *prAdapter, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN struct P2P_MGMT_TX_REQ_INFO *prP2pMgmtTxInfo, + OUT enum ENUM_P2P_DEV_STATE *peNextState); + +void +p2pDevStateAbort_OFF_CHNL_TX(IN struct ADAPTER *prAdapter, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo, + IN struct P2P_MGMT_TX_REQ_INFO *prP2pMgmtTxInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN enum ENUM_P2P_DEV_STATE eNextState); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_fsm.h new file mode 100644 index 0000000000000..8b8b091a29906 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_fsm.h @@ -0,0 +1,92 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + + +#ifndef _P2P_FSM_H +#define _P2P_FSM_H + +void p2pFsmRunEventScanRequest(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pFsmRunEventChGrant(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pFsmRunEventNetDeviceRegister(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pFsmRunEventUpdateMgmtFrame(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +#if CFG_SUPPORT_WFD +void p2pFsmRunEventWfdSettingUpdate(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); +#endif + +void p2pFsmRunEventScanDone(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pFsmRunEventMgmtFrameTx(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pFsmRunEventTxCancelWait(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +#endif /* _P2P_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_func.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_func.h new file mode 100644 index 0000000000000..78f75f2caf736 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_func.h @@ -0,0 +1,485 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#ifndef _P2P_FUNC_H +#define _P2P_FUNC_H + +#define P2P_OFF_CHNL_TX_DEFAULT_TIME_MS 1000 + +#if (CFG_SUPPORT_DFS_MASTER == 1) +extern struct P2P_RADAR_INFO g_rP2pRadarInfo; + +enum _ENUM_DFS_STATE_T { + DFS_STATE_INACTIVE = 0, + DFS_STATE_CHECKING, + DFS_STATE_ACTIVE, + DFS_STATE_DETECTED, + DFS_STATE_NUM +}; +#endif + +/****************************************************************************** + * M A C R O S + ****************************************************************************** + */ +#define ATTRI_ID(_fp) (((struct P2P_ATTRIBUTE *)_fp)->ucId) +#define ATTRI_LEN(_fp) \ +(((uint16_t)((uint8_t *)&((struct P2P_ATTRIBUTE *)_fp)->u2Length)[0]) | \ +((uint16_t)((uint8_t *)&((struct P2P_ATTRIBUTE *)_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) ((struct IE_P2P *)_fp) + +#define WSC_ATTRI_ID(_fp) \ +(((uint16_t)((uint8_t *)&((struct WSC_ATTRIBUTE *)_fp)->u2Id)[0] << 8) | \ +((uint16_t)((uint8_t *)&((struct WSC_ATTRIBUTE *)_fp)->u2Id)[1])) + +#define WSC_ATTRI_LEN(_fp) \ +(((uint16_t)((uint8_t *)&((struct WSC_ATTRIBUTE *)_fp)->u2Length)[0] << 8) | \ +((uint16_t)((uint8_t *)&((struct WSC_ATTRIBUTE *)_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) ((struct IE_P2P *)_fp) + +#define WFD_ATTRI_SIZE(_fp) (P2P_ATTRI_HDR_LEN + WSC_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))) + +/****************************************************************************** + * F U N C T I O N D E C L A R A T I O N S + ****************************************************************************** + */ + +void p2pFuncRequestScan(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct P2P_SCAN_REQ_INFO *prScanReqInfo); + +void p2pFuncCancelScan(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct P2P_SCAN_REQ_INFO *prScanReqInfo); + +void +p2pFuncUpdateBssInfoForJOIN(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc, + IN struct STA_RECORD *prStaRec, + IN struct BSS_INFO *prP2pBssInfo, + IN struct SW_RFB *prAssocRspSwRfb); + +void p2pFuncAcquireCh(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo); + +void +p2pFuncDisconnect(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN struct STA_RECORD *prStaRec, + IN u_int8_t fgSendDeauth, + IN uint16_t u2ReasonCode); + +struct BSS_INFO *p2pFuncBSSIDFindBssInfo(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBSSID); + +void p2pFuncGCJoin(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN struct P2P_JOIN_INFO *prP2pJoinInfo); + +void p2pFuncStopComplete(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo); + +void +p2pFuncStartGO(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct P2P_CONNECTION_REQ_INFO *prP2pConnReqInfo, + IN struct P2P_CHNL_REQ_INFO *prP2pChnlReqInfo); + +void p2pFuncStopGO(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo); + +uint32_t p2pFuncRoleToBssIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucRoleIdx, + OUT uint8_t *pucBssIdx); + +struct P2P_ROLE_FSM_INFO *p2pFuncGetRoleByBssIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +void +p2pFuncSwitchOPMode(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN enum ENUM_OP_MODE eOpMode, + IN u_int8_t fgSyncToFW); + +void p2pFuncReleaseCh(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo); + +#if (CFG_SUPPORT_DFS_MASTER == 1) +void p2pFuncStartRdd(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIdx); + +void p2pFuncStopRdd(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIdx); + +void p2pFuncDfsSwitchCh(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct P2P_CHNL_REQ_INFO rP2pChnlReqInfo); + +u_int8_t p2pFuncCheckWeatherRadarBand( + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo); + +int32_t p2pFuncSetDriverCacTime(IN uint32_t u4CacTime); + +void p2pFuncEnableManualCac(void); + +uint32_t p2pFuncGetDriverCacTime(void); + +u_int8_t p2pFuncIsManualCac(void); + +void p2pFuncRadarInfoInit(void); + +void p2pFuncShowRadarInfo(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIdx); + +void p2pFuncGetRadarInfo(IN struct P2P_RADAR_INFO *prP2pRadarInfo); + +uint8_t *p2pFuncJpW53RadarType(void); + +uint8_t *p2pFuncJpW56RadarType(void); + +void p2pFuncSetRadarDetectMode(IN uint8_t ucRadarDetectMode); + +uint8_t p2pFuncGetRadarDetectMode(void); + +void p2pFuncSetDfsState(IN uint8_t ucDfsState); + +uint8_t p2pFuncGetDfsState(void); + +uint8_t *p2pFuncShowDfsState(void); + +void p2pFuncRecordCacStartBootTime(void); + +uint32_t p2pFuncGetCacRemainingTime(void); +#endif + +void p2pFuncSetChannel(IN struct ADAPTER *prAdapter, + IN uint8_t ucRoleIdx, + IN struct RF_CHANNEL_INFO *prRfChannelInfo); + +u_int8_t p2pFuncRetryJOIN(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct P2P_JOIN_INFO *prJoinInfo); + +uint32_t +p2pFuncTxMgmtFrame(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct MSDU_INFO *prMgmtTxMsdu, + IN u_int8_t fgNonCckRate); + +uint32_t +p2pFuncBeaconUpdate(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN struct P2P_BEACON_UPDATE_INFO *prBcnUpdateInfo, + IN uint8_t *pucNewBcnHdr, + IN uint32_t u4NewHdrLen, + IN uint8_t *pucNewBcnBody, + IN uint32_t u4NewBodyLen); + +uint32_t +p2pFuncAssocRespUpdate(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN uint8_t *AssocRespIE, + IN uint32_t u4AssocRespLen); + +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP +uint32_t +p2pFuncProbeRespUpdate(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN uint8_t *ProbeRespIE, IN uint32_t u4ProbeRespLen); +#endif + +u_int8_t +p2pFuncValidateAuth(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, IN struct SW_RFB *prSwRfb, + IN struct STA_RECORD **pprStaRec, OUT uint16_t *pu2StatusCode); + +u_int8_t p2pFuncValidateAssocReq(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, OUT uint16_t *pu2StatusCode); + +void p2pFuncResetStaRecStatus(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +void +p2pFuncInitConnectionSettings(IN struct ADAPTER *prAdapter, + IN struct P2P_CONNECTION_SETTINGS *prP2PConnSettings, + IN u_int8_t fgIsApMode); + +u_int8_t p2pFuncParseCheckForP2PInfoElem(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, OUT uint8_t *pucOuiType); + +u_int8_t p2pFuncParseCheckForTKIPInfoElem(IN uint8_t *pucBuf); + +u_int8_t +p2pFuncValidateProbeReq(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, OUT uint32_t *pu4ControlFlags, + IN u_int8_t fgIsDevInterface, IN uint8_t ucRoleIdx); + +void p2pFuncValidateRxActionFrame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN u_int8_t fgIsDevInterface, IN uint8_t ucRoleIdx); + +u_int8_t p2pFuncIsAPMode(IN struct P2P_CONNECTION_SETTINGS *prP2pConnSettings); + +void +p2pFuncParseBeaconContent(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN uint8_t *pucIEInfo, IN uint32_t u4IELen); + +struct BSS_DESC * +p2pFuncKeepOnConnection(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct P2P_CONNECTION_REQ_INFO *prConnReqInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN struct P2P_SCAN_REQ_INFO *prScanReqInfo); + +void p2pFuncStoreAssocRspIEBuffer(IN struct ADAPTER *prAdapter, + IN struct P2P_JOIN_INFO *prP2pJoinInfo, + IN struct SW_RFB *prSwRfb); + +void +p2pFuncMgmtFrameRegister(IN struct ADAPTER *prAdapter, + IN uint16_t u2FrameType, + IN u_int8_t fgIsRegistered, + OUT uint32_t *pu4P2pPacketFilter); + +void p2pFuncUpdateMgmtFrameRegister(IN struct ADAPTER *prAdapter, + IN uint32_t u4OsFilter); + +void p2pFuncGetStationInfo(IN struct ADAPTER *prAdapter, + IN uint8_t *pucMacAddr, + OUT struct P2P_STATION_INFO *prStaInfo); + +struct MSDU_INFO *p2pFuncProcessP2pProbeRsp(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, IN struct MSDU_INFO *prMgmtTxMsdu); + +#if 0 /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */ +uint32_t +p2pFuncCalculateExtra_IELenForBeacon(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN struct STA_RECORD *prStaRec); + +void p2pFuncGenerateExtra_IEForBeacon(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +#else +uint32_t p2pFuncCalculateP2p_IELenForBeacon(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN struct STA_RECORD *prStaRec); + +void p2pFuncGenerateP2p_IEForBeacon(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +uint32_t p2pFuncCalculateWSC_IELenForBeacon(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN struct STA_RECORD *prStaRec); + +void p2pFuncGenerateWSC_IEForBeacon(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); +#endif +uint32_t +p2pFuncCalculateP2p_IELenForAssocRsp(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN struct STA_RECORD *prStaRec); + +void p2pFuncGenerateP2p_IEForAssocRsp(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +uint32_t +p2pFuncCalculateP2P_IELen(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct STA_RECORD *prStaRec, + IN struct APPEND_VAR_ATTRI_ENTRY arAppendAttriTable[], + IN uint32_t u4AttriTableSize); + +void +p2pFuncGenerateP2P_IE(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN u_int8_t fgIsAssocFrame, + IN uint16_t *pu2Offset, + IN uint8_t *pucBuf, + IN uint16_t u2BufSize, + IN struct APPEND_VAR_ATTRI_ENTRY arAppendAttriTable[], + IN uint32_t u4AttriTableSize); + +uint32_t +p2pFuncAppendAttriStatusForAssocRsp(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN u_int8_t fgIsAssocFrame, + IN uint16_t *pu2Offset, + IN uint8_t *pucBuf, + IN uint16_t u2BufSize); + +uint32_t +p2pFuncAppendAttriExtListenTiming(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN u_int8_t fgIsAssocFrame, + IN uint16_t *pu2Offset, + IN uint8_t *pucBuf, + IN uint16_t u2BufSize); + +void +p2pFuncDissolve(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN u_int8_t fgSendDeauth, + IN uint16_t u2ReasonCode); + +struct IE_HDR * +p2pFuncGetSpecIE(IN struct ADAPTER *prAdapter, + IN uint8_t *pucIEBuf, + IN uint16_t u2BufferLen, + IN uint8_t ucElemID, + IN u_int8_t *pfgIsMore); + +struct P2P_ATTRIBUTE * +p2pFuncGetSpecAttri(IN struct ADAPTER *prAdapter, + IN uint8_t ucOuiType, + IN uint8_t *pucIEBuf, + IN uint16_t u2BufferLen, + IN uint8_t ucAttriID); + +uint32_t wfdFuncCalculateWfdIELenForAssocRsp(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN struct STA_RECORD *prStaRec); + +void wfdFuncGenerateWfdIEForAssocRsp(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +uint32_t p2pFuncCalculateP2P_IE_NoA(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, IN struct STA_RECORD *prStaRec); + +void p2pFuncGenerateP2P_IE_NoA(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +void p2pFunCleanQueuedMgmtFrame(IN struct ADAPTER *prAdapter, + IN struct P2P_QUEUED_ACTION_FRAME *prFrame); + +void p2pFuncSwitchSapChannel(IN struct ADAPTER *prAdapter); + +uint32_t p2pFunGetPreferredFreqList(IN struct ADAPTER *prAdapter, + IN enum ENUM_IFTYPE eIftype, OUT uint32_t *freq_list, + OUT uint32_t *num_freq_list); + +enum ENUM_P2P_CONNECT_STATE +p2pFuncGetP2pActionFrameType(IN struct MSDU_INFO *prMgmtMsdu); + +u_int8_t +p2pFuncCheckOnRocChnl(IN struct RF_CHANNEL_INFO *prTxChnl, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo); + +u_int8_t +p2pFuncNeedWaitRsp(IN struct ADAPTER *prAdapter, + IN enum ENUM_P2P_CONNECT_STATE eConnState); + +void +p2pFunClearAllTxReq(IN struct ADAPTER *prAdapter, + IN struct P2P_MGMT_TX_REQ_INFO *prP2pMgmtTxInfo); + +uint8_t p2pFunGetAcsBestCh(IN struct ADAPTER *prAdapter, + IN enum ENUM_BAND eBand, + IN enum ENUM_MAX_BANDWIDTH_SETTING eChnlBw, + IN uint32_t u4LteSafeChnMask_2G, + IN uint32_t u4LteSafeChnMask_5G_1, + IN uint32_t u4LteSafeChnMask_5G_2); +#if (CFG_SUPPORT_P2PGO_ACS == 1) + +void p2pFunGetAcsBestChList(IN struct ADAPTER *prAdapter, + IN uint8_t eBand, + IN enum ENUM_MAX_BANDWIDTH_SETTING eChnlBw, + IN uint32_t u4LteSafeChnMask_2G, + IN uint32_t u4LteSafeChnMask_5G_1, + IN uint32_t u4LteSafeChnMask_5G_2, + OUT uint8_t *pucSortChannelNumber, + OUT struct RF_CHANNEL_INFO *paucSortChannelList); +#endif +void p2pFunProcessAcsReport(IN struct ADAPTER *prAdapter, + IN uint8_t ucRoleIndex, + IN struct PARAM_GET_CHN_INFO *prLteSafeChnInfo, + IN struct P2P_ACS_REQ_INFO *prAcsReqInfo); + +void p2pFunIndicateAcsResult(IN struct GLUE_INFO *prGlueInfo, + IN struct P2P_ACS_REQ_INFO *prAcsReqInfo); + +void p2pFunCalAcsChnScores(IN struct ADAPTER *prAdapter); + +enum ENUM_CHNL_SWITCH_POLICY +p2pFunDetermineChnlSwitchPolicy(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct RF_CHANNEL_INFO *prNewChannelInfo); + +void +p2pFunNotifyChnlSwitch(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + enum ENUM_CHNL_SWITCH_POLICY ePolicy, + IN struct RF_CHANNEL_INFO *prNewChannelInfo); + +void +p2pFunChnlSwitchNotifyDone(IN struct ADAPTER *prAdapter); + +uint8_t p2pFuncIsBufferableMMPDU(IN struct ADAPTER *prAdapter, + IN enum ENUM_P2P_CONNECT_STATE eConnState, + IN struct MSDU_INFO *prMgmtTxMsdu); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_ie.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_ie.h new file mode 100644 index 0000000000000..cd287743cdd15 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_ie.h @@ -0,0 +1,102 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#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 + +/* == OFFSET_OF(IE_P2P_T,*/ +/*aucP2PAttributes[0]) */ +#define WFD_IE_OUI_HDR (ELEM_HDR_LEN + WFD_OUI_TYPE_LEN) + +/* 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 */ + +struct WFD_DEVICE_INFORMATION_IE { + uint8_t ucElemID; + uint16_t u2Length; + uint16_t u2WfdDevInfo; + uint16_t u2SessionMgmtCtrlPort; + uint16_t u2WfdDevMaxSpeed; +} __KAL_ATTRIB_PACKED__; + +#endif + +uint32_t p2pCalculate_IEForAssocReq(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN struct STA_RECORD *prStaRec); + +void p2pGenerate_IEForAssocReq(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_rlm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_rlm.h new file mode 100644 index 0000000000000..ebb91946eeceb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_rlm.h @@ -0,0 +1,136 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/*! \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 + ****************************************************************************** + */ + +#define CHANNEL_SPAN_20 20 + +/****************************************************************************** + * 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(struct ADAPTER *prAdapter, struct BSS_INFO *prBssInfo); + +u_int8_t rlmUpdateBwByChListForAP(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo); + +void rlmUpdateParamsForAP(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, u_int8_t fgUpdateBeacon); + +void rlmFuncInitialChannelList(IN struct ADAPTER *prAdapter); + +void +rlmFuncCommonChannelList(IN struct ADAPTER *prAdapter, + IN struct CHANNEL_ENTRY_FIELD *prChannelEntryII, + IN uint8_t ucChannelListSize); + +uint8_t rlmFuncFindOperatingClass(IN struct ADAPTER *prAdapter, + IN uint8_t ucChannelNum); + +u_int8_t +rlmFuncFindAvailableChannel(IN struct ADAPTER *prAdapter, + IN uint8_t ucCheckChnl, + IN uint8_t *pucSuggestChannel, + IN u_int8_t fgIsSocialChannel, IN u_int8_t fgIsDefaultChannel); + +enum ENUM_CHNL_EXT rlmDecideScoForAP(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo); + +enum ENUM_CHNL_EXT rlmGetScoForAP(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo); + +uint8_t rlmGetVhtS1ForAP(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo); + + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_rlm_obss.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_rlm_obss.h new file mode 100644 index 0000000000000..ba340c9a99c2e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_rlm_obss.h @@ -0,0 +1,118 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rlmProcessPublicAction(struct ADAPTER *prAdapter, struct SW_RFB *prSwRfb); + +void rlmHandleObssStatusEventPkt(struct ADAPTER *prAdapter, + struct EVENT_AP_OBSS_STATUS *prObssStatus); + +uint8_t rlmObssChnlLevel(struct BSS_INFO *prBssInfo, + enum ENUM_BAND eBand, uint8_t ucPriChannel, + enum ENUM_CHNL_EXT eExtend); + +void rlmObssScanExemptionRsp(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, struct SW_RFB *prSwRfb); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_role.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_role.h new file mode 100644 index 0000000000000..47e8ea0e97fa5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_role.h @@ -0,0 +1,501 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#ifndef _P2P_ROLE_H +#define _P2P_ROLE_H + +#define P2P_ROLE_GET_STATISTICS_TIME 5000 + +enum ENUM_BUFFER_TYPE { + 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 ENUM_HIDDEN_SSID_TYPE { + ENUM_HIDDEN_SSID_NONE, + ENUM_HIDDEN_SSID_ZERO_LEN, + ENUM_HIDDEN_SSID_ZERO_CONTENT, + ENUM_HIDDEN_SSID_NUM +}; + +struct P2P_BEACON_UPDATE_INFO { + uint8_t *pucBcnHdr; + uint32_t u4BcnHdrLen; + uint8_t *pucBcnBody; + uint32_t u4BcnBodyLen; +}; + +struct P2P_PROBE_RSP_UPDATE_INFO { + struct MSDU_INFO *prProbeRspMsduTemplate; +}; + +struct P2P_ASSOC_RSP_UPDATE_INFO { + uint8_t *pucAssocRspExtIE; + uint16_t u2AssocIELen; +}; + +struct AP_CRYPTO_SETTINGS { + uint32_t u4WpaVersion; + uint32_t u4CipherGroup; + int32_t i4NumOfCiphers; + uint32_t aucCiphersPairwise[5]; + int32_t i4NumOfAkmSuites; + uint32_t aucAkmSuites[2]; + u_int8_t fgIsControlPort; + uint16_t u2ControlPortBE; + u_int8_t fgIsControlPortEncrypt; +}; + +/* ////////////////////////// Message ////////////////////////////////// */ + +struct MSG_P2P_BEACON_UPDATE { + struct MSG_HDR rMsgHdr; + uint8_t ucRoleIndex; + uint32_t u4BcnHdrLen; + uint32_t u4BcnBodyLen; + uint32_t u4AssocRespLen; +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP + uint32_t u4ProbeRespLen; +#endif + uint8_t *pucBcnHdr; + uint8_t *pucBcnBody; + uint8_t *pucAssocRespIE; +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP + uint8_t *pucProbeRespIE; +#endif + u_int8_t fgIsWepCipher; + uint8_t aucBuffer[1]; /* Header & Body & Extra IEs are put here. */ +}; + +struct MSG_P2P_MGMT_FRAME_UPDATE { + struct MSG_HDR rMsgHdr; + enum ENUM_BUFFER_TYPE eBufferType; + uint32_t u4BufferLen; + uint8_t aucBuffer[1]; +}; + +struct MSG_P2P_SWITCH_OP_MODE { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + enum ENUM_OP_MODE eOpMode; + uint8_t ucRoleIdx; + enum ENUM_IFTYPE eIftype; +}; + +struct MSG_P2P_MGMT_FRAME_REGISTER { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint16_t u2FrameType; + u_int8_t fgIsRegister; +}; + +struct MSG_P2P_CHNL_ABORT { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint64_t u8Cookie; +}; + +struct MSG_P2P_CONNECTION_REQUEST { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucRoleIdx; + struct P2P_SSID_STRUCT rSsid; + uint8_t aucBssid[MAC_ADDR_LEN]; + uint8_t aucSrcMacAddr[MAC_ADDR_LEN]; + enum ENUM_CHNL_EXT eChnlSco; + struct RF_CHANNEL_INFO rChannelInfo; + uint32_t u4IELen; + uint8_t aucIEBuf[1]; + /* TODO: Auth Type, OPEN, SHARED, FT, EAP... */ +}; + +struct MSG_P2P_CONNECTION_ABORT { + struct MSG_HDR rMsgHdr; /* Must be the first member. */ + uint8_t ucRoleIdx; + uint8_t aucTargetID[MAC_ADDR_LEN]; + uint16_t u2ReasonCode; + u_int8_t fgSendDeauth; +}; + +struct MSG_P2P_START_AP { + struct MSG_HDR rMsgHdr; + uint32_t u4DtimPeriod; + uint32_t u4BcnInterval; + uint8_t aucSsid[32]; + uint16_t u2SsidLen; + uint8_t ucHiddenSsidType; + u_int8_t fgIsPrivacy; + uint8_t ucRoleIdx; + struct AP_CRYPTO_SETTINGS rEncryptionSettings; + int32_t i4InactiveTimeout; +}; + +struct MSG_P2P_STOP_AP { + struct MSG_HDR rMsgHdr; + uint8_t ucRoleIdx; +}; + +#if (CFG_SUPPORT_DFS_MASTER == 1) +struct MSG_P2P_DFS_CAC { + struct MSG_HDR rMsgHdr; + enum ENUM_CHANNEL_WIDTH eChannelWidth; + uint8_t ucRoleIdx; +}; + +struct MSG_P2P_RADAR_DETECT { + struct MSG_HDR rMsgHdr; + uint8_t ucBssIndex; +}; + +struct P2P_RADAR_INFO { + uint8_t ucRadarReportMode; + /*0: Only report radar detected; 1: Add parameter reports*/ + uint8_t ucRddIdx; + uint8_t ucLongDetected; + uint8_t ucPeriodicDetected; + uint8_t ucLPBNum; + uint8_t ucPPBNum; + uint8_t ucLPBPeriodValid; + uint8_t ucLPBWidthValid; + uint8_t ucPRICountM1; + uint8_t ucPRICountM1TH; + uint8_t ucPRICountM2; + uint8_t ucPRICountM2TH; + uint32_t u4PRI1stUs; + struct LONG_PULSE_BUFFER arLpbContent[32]; + struct PERIODIC_PULSE_BUFFER arPpbContent[32]; +}; + +struct MSG_P2P_SET_NEW_CHANNEL { + struct MSG_HDR rMsgHdr; + enum ENUM_CHANNEL_WIDTH eChannelWidth; + uint8_t ucRoleIdx; + uint8_t ucBssIndex; +}; + +struct MSG_P2P_CSA_DONE { + struct MSG_HDR rMsgHdr; + uint8_t ucBssIndex; +}; +#endif + +struct MSG_P2P_DEL_IFACE { + struct MSG_HDR rMsgHdr; + uint8_t ucRoleIdx; +}; + +struct P2P_STATION_INFO { + uint32_t u4InactiveTime; + uint32_t u4RxBytes; /* TODO: */ + uint32_t u4TxBytes; /* TODO: */ + uint32_t u4RxPackets; /* TODO: */ + uint32_t u4TxPackets; /* TODO: */ + /* TODO: Add more for requirement. */ +}; + +/* 3 --------------- WFA P2P Attributes Handler prototype --------------- */ +typedef uint32_t(*PFN_APPEND_ATTRI_FUNC) (struct ADAPTER *, + uint8_t, u_int8_t, uint16_t *, uint8_t *, uint16_t); + +typedef uint32_t(*PFN_CALCULATE_VAR_ATTRI_LEN_FUNC) (struct ADAPTER *, + struct STA_RECORD *); + +struct APPEND_VAR_ATTRI_ENTRY { + uint16_t u2EstimatedFixedAttriLen; /* For fixed length */ + PFN_CALCULATE_VAR_ATTRI_LEN_FUNC pfnCalculateVariableAttriLen; + PFN_APPEND_ATTRI_FUNC pfnAppendAttri; +}; + +/* //////////////////////////////////////////////////////////////// */ + +enum ENUM_P2P_ROLE_STATE { + P2P_ROLE_STATE_IDLE = 0, + P2P_ROLE_STATE_SCAN, + P2P_ROLE_STATE_REQING_CHANNEL, + P2P_ROLE_STATE_AP_CHNL_DETECTION, + /* Requesting Channel to Send Specific Frame. */ + P2P_ROLE_STATE_GC_JOIN, + P2P_ROLE_STATE_OFF_CHNL_TX, +#if (CFG_SUPPORT_DFS_MASTER == 1) + P2P_ROLE_STATE_DFS_CAC, + P2P_ROLE_STATE_SWITCH_CHANNEL, +#endif + P2P_ROLE_STATE_NUM +}; + +enum ENUM_P2P_CONNECTION_TYPE { + P2P_CONNECTION_TYPE_IDLE = 0, + P2P_CONNECTION_TYPE_GO, + P2P_CONNECTION_TYPE_GC, + P2P_CONNECTION_TYPE_PURE_AP, + P2P_CONNECTION_TYPE_NUM +}; + +struct P2P_JOIN_INFO { + uint8_t ucSeqNumOfReqMsg; + uint8_t ucAvailableAuthTypes; + struct STA_RECORD *prTargetStaRec; + struct BSS_DESC *prTargetBssDesc; + u_int8_t fgIsJoinComplete; + /* For ASSOC Rsp. */ + uint32_t u4BufLength; + uint8_t aucIEBuf[MAX_IE_LENGTH]; +}; + +/* For STA & AP mode. */ +struct P2P_CONNECTION_REQ_INFO { + enum ENUM_P2P_CONNECTION_TYPE eConnRequest; + struct P2P_SSID_STRUCT rSsidStruct; + uint8_t aucBssid[MAC_ADDR_LEN]; + + /* AP preferred channel. */ + struct RF_CHANNEL_INFO rChannelInfo; + enum ENUM_CHNL_EXT eChnlExt; + + /* To record channel bandwidth from CFG80211 */ + enum ENUM_MAX_BANDWIDTH_SETTING eChnlBw; + + /* To record primary channel frequency (MHz) from CFG80211 */ + uint16_t u2PriChnlFreq; + + /* To record Channel Center Frequency Segment 0 (MHz) from CFG80211 */ + uint32_t u4CenterFreq1; + + /* To record Channel Center Frequency Segment 1 (MHz) from CFG80211 */ + uint32_t u4CenterFreq2; + + /* For ASSOC Req. */ + uint32_t u4BufLength; + uint8_t aucIEBuf[MAX_IE_LENGTH]; +}; + +#define P2P_ROLE_INDEX_2_ROLE_FSM_INFO(_prAdapter, _RoleIndex) \ + ((_prAdapter)->rWifiVar.aprP2pRoleFsmInfo[_RoleIndex]) + +struct P2P_ROLE_FSM_INFO { + uint8_t ucRoleIndex; + + uint8_t ucBssIndex; + + /* State related. */ + enum ENUM_P2P_ROLE_STATE eCurrentState; + + /* Channel related. */ + struct P2P_CHNL_REQ_INFO rChnlReqInfo; + + /* Scan related. */ + struct P2P_SCAN_REQ_INFO rScanReqInfo; + + /* Mgmt tx related. */ + struct P2P_MGMT_TX_REQ_INFO rMgmtTxInfo; + + /* Auto channel selection related. */ + struct P2P_ACS_REQ_INFO rAcsReqInfo; + + /* FSM Timer */ + struct TIMER rP2pRoleFsmTimeoutTimer; + +#if CFG_ENABLE_PER_STA_STATISTICS_LOG + /* Get statistics Timer */ + struct TIMER rP2pRoleFsmGetStatisticsTimer; +#endif + +#if (CFG_SUPPORT_DFS_MASTER == 1) + struct TIMER rDfsShutDownTimer; +#endif + + /* Packet filter for P2P module. */ + uint32_t u4P2pPacketFilter; + + /* GC Join related. */ + struct P2P_JOIN_INFO rJoinInfo; + + /* Connection related. */ + struct P2P_CONNECTION_REQ_INFO rConnReqInfo; + + /* Beacon Information. */ + struct P2P_BEACON_UPDATE_INFO rBeaconUpdateInfo; +}; + +/*========================= Initial ============================*/ + +uint8_t p2pRoleFsmInit(IN struct ADAPTER *prAdapter, IN uint8_t ucRoleIdx); + +void p2pRoleFsmUninit(IN struct ADAPTER *prAdapter, IN uint8_t ucRoleIdx); + +/*================== Message Event ==================*/ + +void p2pRoleFsmRunEventAbort(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo); + +void p2pRoleFsmRunEventStartAP(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pRoleFsmRunEventDelIface(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pRoleFsmRunEventStopAP(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +#if (CFG_SUPPORT_DFS_MASTER == 1) +void p2pRoleFsmRunEventDfsCac(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pRoleFsmRunEventRadarDet(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pRoleFsmRunEventSetNewChannel(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pRoleFsmRunEventCsaDone(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pRoleFsmRunEventDfsShutDownTimeout(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr); +#endif + +void p2pRoleFsmRunEventScanRequest(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void +p2pRoleFsmRunEventScanDone(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo); + +void p2pRoleFsmRunEventJoinComplete(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pRoleFsmRunEventTimeout(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr); + +void p2pRoleFsmDeauthTimeout(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr); + +void p2pRoleFsmRunEventBeaconTimeout(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo); + +void p2pRoleUpdateACLEntry(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx); + +u_int8_t p2pRoleProcessACLInspection(IN struct ADAPTER *prAdapter, + IN uint8_t *pMacAddr, IN uint8_t ucBssIdx); + +uint32_t +p2pRoleFsmRunEventAAAComplete(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct BSS_INFO *prP2pBssInfo); + +uint32_t +p2pRoleFsmRunEventAAASuccess(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct BSS_INFO *prP2pBssInfo); + +void p2pRoleFsmRunEventAAATxFail(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct BSS_INFO *prP2pBssInfo); + +void p2pRoleFsmRunEventConnectionRequest(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pRoleFsmRunEventConnectionAbort(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void +p2pRoleFsmRunEventChnlGrant(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo); + +uint32_t +p2pRoleFsmRunEventDeauthTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +void p2pRoleFsmRunEventRxDeauthentication(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, IN struct SW_RFB *prSwRfb); + +void p2pRoleFsmRunEventRxDisassociation(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, IN struct SW_RFB *prSwRfb); + +/* //////////////////////// TO BE REFINE ///////////////////// */ +void p2pRoleFsmRunEventSwitchOPMode(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pRoleFsmRunEventBeaconUpdate(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pRoleFsmRunEventDissolve(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void +p2pProcessEvent_UpdateNOAParam(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct EVENT_UPDATE_NOA_PARAMS *prEventUpdateNoaParam); + +#if CFG_ENABLE_PER_STA_STATISTICS_LOG +void p2pRoleFsmGetStaStatistics(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr); +#endif + +void p2pRoleFsmNotifyEapolTxStatus(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN enum ENUM_EAPOL_KEY_TYPE_T rEapolKeyType, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +void p2pRoleFsmRunEventMgmtTx(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pRoleFsmRunEventTxCancelWait(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pRoleFsmRunEventAcs(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_role_state.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_role_state.h new file mode 100644 index 0000000000000..3ad21d1dadc1b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_role_state.h @@ -0,0 +1,160 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#ifndef _P2P_ROLE_STATE_H +#define _P2P_ROLE_STATE_H + +void +p2pRoleStateInit_IDLE(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN struct BSS_INFO *prP2pBssInfo); + +void +p2pRoleStateAbort_IDLE(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN struct P2P_CHNL_REQ_INFO *prP2pChnlReqInfo); + +void p2pRoleStateInit_SCAN(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct P2P_SCAN_REQ_INFO *prScanReqInfo); + +void p2pRoleStateAbort_SCAN(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo); + +void +p2pRoleStateInit_REQING_CHANNEL(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo); + +void +p2pRoleStateAbort_REQING_CHANNEL(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pRoleBssInfo, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN enum ENUM_P2P_ROLE_STATE eNextState); + +void +p2pRoleStateInit_AP_CHNL_DETECTION(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct P2P_SCAN_REQ_INFO *prScanReqInfo, + IN struct P2P_CONNECTION_REQ_INFO *prConnReqInfo); + +void +p2pRoleStateAbort_AP_CHNL_DETECTION(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct P2P_CONNECTION_REQ_INFO *prP2pConnReqInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN struct P2P_SCAN_REQ_INFO *prP2pScanReqInfo, + IN enum ENUM_P2P_ROLE_STATE eNextState); + +void +p2pRoleStateInit_GC_JOIN(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo); + +void +p2pRoleStateAbort_GC_JOIN(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN struct P2P_JOIN_INFO *prJoinInfo, + IN enum ENUM_P2P_ROLE_STATE eNextState); + +#if (CFG_SUPPORT_DFS_MASTER == 1) +void +p2pRoleStateInit_DFS_CAC(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo); + +void +p2pRoleStateAbort_DFS_CAC(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pRoleBssInfo, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN enum ENUM_P2P_ROLE_STATE eNextState); + +void +p2pRoleStateInit_SWITCH_CHANNEL(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo); + +void +p2pRoleStateAbort_SWITCH_CHANNEL(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pRoleBssInfo, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN enum ENUM_P2P_ROLE_STATE eNextState); + +void +p2pRoleStatePrepare_To_DFS_CAC_STATE(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN enum ENUM_CHANNEL_WIDTH rChannelWidth, + IN struct P2P_CONNECTION_REQ_INFO *prConnReqInfo, + OUT struct P2P_CHNL_REQ_INFO *prChnlReqInfo); + +#endif + +void +p2pRoleStatePrepare_To_REQING_CHANNEL_STATE(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct P2P_CONNECTION_REQ_INFO *prConnReqInfo, + OUT struct P2P_CHNL_REQ_INFO *prChnlReqInfo); + +u_int8_t +p2pRoleStateInit_OFF_CHNL_TX(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN struct P2P_MGMT_TX_REQ_INFO *prP2pMgmtTxInfo, + OUT enum ENUM_P2P_ROLE_STATE *peNextState); + +void +p2pRoleStateAbort_OFF_CHNL_TX(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN struct P2P_MGMT_TX_REQ_INFO *prP2pMgmtTxInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN enum ENUM_P2P_ROLE_STATE eNextState); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_scan.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_scan.h new file mode 100644 index 0000000000000..e33ff64f25e7d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/p2p_scan.h @@ -0,0 +1,125 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 + ****************************************************************************** + */ + +void scnEventReturnChannel(IN struct ADAPTER *prAdapter, + IN uint8_t ucScnSeqNum); + +u_int8_t scanUpdateP2pDeviceDesc(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc); + +void +scanP2pProcessBeaconAndProbeResp(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint32_t *prStatus, + IN struct BSS_DESC *prBssDesc, + IN struct WLAN_BEACON_FRAME *prWlanBeaconFrame); + +void scanRemoveAllP2pBssDesc(struct ADAPTER *prAdapter); + +void scanRemoveP2pBssDesc(struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc); + +struct BSS_DESC *scanP2pSearchDesc(IN struct ADAPTER *prAdapter, + IN struct P2P_CONNECTION_REQ_INFO *prConnReqInfo); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/privacy.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/privacy.h new file mode 100644 index 0000000000000..8742b4bc4c9f7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/privacy.h @@ -0,0 +1,295 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: include/mgmt/privacy.h#1 + */ + +/*! \file privacy.h + * \brief This file contains the function declaration for privacy.c. + */ + + +#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 WEP_128_LEN 16 +#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) + +/* WTBL cipher selector, sync with HAL RX from hal_hw_def_rom.h */ +#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 CIPHER_SUITE_CCMP_W_CCX 9 /* CCMP-128 for DFP or CCX MFP */ +#define CIPHER_SUITE_CCMP_256 10 +#define CIPHER_SUITE_GCMP_128 11 +#define CIPHER_SUITE_GCMP_256 12 +#define CIPHER_SUITE_GCM_WPI_128 13 + +/* Todo:: Move to register */ +#if defined(MT6630) +#define WTBL_RESERVED_ENTRY 255 +#else +#define WTBL_RESERVED_ENTRY 255 +#endif +/* Todo:: By chip capability */ +/* Max wlan table size, the max+1 used for probe request,... mgmt frame */ +/*sending use basic rate and no security */ +#define WTBL_SIZE 32 + +#define WTBL_ALLOC_FAIL WTBL_RESERVED_ENTRY +#define WTBL_DEFAULT_ENTRY 0 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +struct IEEE_802_1X_HDR { + uint8_t ucVersion; + uint8_t ucType; + uint16_t u2Length; + /* followed by length octets of data */ +}; + +struct EAPOL_KEY { + uint8_t ucType; + /* Note: key_info, key_length, and key_data_length are unaligned */ + uint8_t aucKeyInfo[2]; /* big endian */ + uint8_t aucKeyLength[2]; /* big endian */ + uint8_t aucReplayCounter[8]; + uint8_t aucKeyNonce[16]; + uint8_t aucKeyIv[16]; + uint8_t aucKeyRsc[8]; + uint8_t aucKeyId[8]; /* Reserved in IEEE 802.11i/RSN */ + uint8_t aucKeyMic[16]; + uint8_t aucKeyDataLength[2]; /* big endian */ + /* followed by key_data_length bytes of key_data */ +}; + +/* WPA2 PMKID candicate structure */ +struct PMKID_CANDICATE { + uint8_t aucBssid[MAC_ADDR_LEN]; + uint32_t u4PreAuthFlags; +}; + +#if 0 +/* WPA2 PMKID cache structure */ +struct PMKID_ENTRY { + struct PARAM_BSSID_INFO rBssidInfo; + u_int8_t fgPmkidExist; +}; +#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 struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +void secSetPortBlocked(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prSta, IN u_int8_t fgPort); + +u_int8_t secCheckClassError(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN struct STA_RECORD *prStaRec); + +u_int8_t secTxPortControlCheck(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN struct STA_RECORD *prStaRec); + +u_int8_t secRxPortControlCheck(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSWRfb); + +void secSetCipherSuite(IN struct ADAPTER *prAdapter, + IN uint32_t u4CipherSuitesFlags, + IN uint8_t ucBssIndex); + +u_int8_t secIsProtectedFrame(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsdu, + IN struct STA_RECORD *prStaRec); + +u_int8_t secRsnKeyHandshakeEnabled(IN struct ADAPTER + *prAdapter); + +uint8_t secGetBmcWlanIndex(IN struct ADAPTER *prAdapter, + IN enum ENUM_NETWORK_TYPE eNetType, + IN struct STA_RECORD *prStaRec); + +u_int8_t secTransmitKeyExist(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prSta); + +u_int8_t secEnabledInAis(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +u_int8_t secPrivacySeekForEntry(IN struct ADAPTER + *prAdapter, IN struct STA_RECORD *prSta); + +void secPrivacyFreeForEntry(IN struct ADAPTER *prAdapter, + IN uint8_t ucEntry); + +void secPrivacyFreeSta(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +void secRemoveBssBcEntry(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, IN u_int8_t fgRoam); + +uint8_t +secPrivacySeekForBcEntry(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN uint8_t *pucAddr, IN uint8_t ucStaIdx, + IN uint8_t ucAlg, IN uint8_t ucKeyId); + +uint8_t secGetStaIdxByWlanIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucWlanIdx); + +uint8_t secGetBssIdxByWlanIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucWlanIdx); + +uint8_t secGetBssIdxByRfb(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +uint8_t secLookupStaRecIndexFromTA(struct ADAPTER + *prAdapter, uint8_t *pucMacAddress); + +void secPrivacyDumpWTBL(IN struct ADAPTER *prAdapter); + +u_int8_t secCheckWTBLAssign(IN struct ADAPTER *prAdapter); + +u_int8_t secIsProtected1xFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +u_int8_t secIsProtectedBss(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo); + +u_int8_t secIsRobustActionFrame(IN struct ADAPTER *prAdapter, + IN void *prPacket); + +u_int8_t secIsRobustMgmtFrame(IN struct ADAPTER *prAdapter, + IN void *prPacket); + +u_int8_t secIsWepBss(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo); + +u_int8_t tkipMicDecapsulate(IN struct SW_RFB *prSwRfb, + IN uint8_t *pucMicKey); + +u_int8_t tkipMicDecapsulateInRxHdrTransMode( + IN struct SW_RFB *prSwRfb, IN uint8_t *pucMicKey); + +void secPostUpdateAddr(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo); + +enum ENUM_EAPOL_KEY_TYPE_T secGetEapolKeyType( + uint8_t *pucPacket); + +void secHandleNoWtbl(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _PRIVACY_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/qosmap.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/qosmap.h new file mode 100644 index 0000000000000..1cb46d2a3d04e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/qosmap.h @@ -0,0 +1,122 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "qosmap.h" + * \brief This file including the qosmap related function. + * + * This file provided the macros and functions library support for the + * protocol layer qosmap related function. + * + */ + +#ifndef _QOSMAP_H +#define _QOSMAP_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 + ******************************************************************************* + */ +#define DSCP_SUPPORT 1 +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +void handleQosMapConf(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +int qosHandleQosMapConfigure(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +void qosMapSetInit(IN struct STA_RECORD *prStaRec); + +void qosParseQosMapSet(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, IN uint8_t *qosMapSet); + +uint8_t getUpFromDscp(IN struct GLUE_INFO *prGlueInfo, + IN int type, IN int dscp); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _QOSMAP_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rate.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rate.h new file mode 100644 index 0000000000000..555ec7c414036 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rate.h @@ -0,0 +1,133 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + +#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 + ******************************************************************************* + */ +extern const uint8_t aucDataRate[]; + +/******************************************************************************* + * 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 struct IE_SUPPORTED_RATE_IOT + *prIeSupportedRate, + IN struct IE_EXT_SUPPORTED_RATE *prIeExtSupportedRate, OUT + uint16_t *pu2OperationalRateSet, + OUT uint16_t *pu2BSSBasicRateSet, + OUT u_int8_t *pfgIsUnknownBSSBasicRate); + +void +rateGetDataRatesFromRateSet(IN uint16_t + u2OperationalRateSet, IN uint16_t u2BSSBasicRateSet, + OUT uint8_t *pucDataRates, OUT + uint8_t *pucDataRatesLen); + +u_int8_t rateGetHighestRateIndexFromRateSet( + IN uint16_t u2RateSet, OUT uint8_t *pucHighestRateIndex); + +u_int8_t rateGetLowestRateIndexFromRateSet( + IN uint16_t u2RateSet, OUT uint8_t *pucLowestRateIndex); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _RATE_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rlm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rlm.h new file mode 100644 index 0000000000000..5e3a760e3f597 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rlm.h @@ -0,0 +1,512 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/ + * include/mgmt/rlm.h#2 + */ + +/*! \file "rlm.h" + * \brief + */ + + +#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 + ******************************************************************************* + */ +extern u_int8_t g_bIcapEnable; +extern u_int8_t g_bCaptureDone; +extern uint16_t g_u2DumpIndex; +#if CFG_SUPPORT_QA_TOOL +extern uint32_t g_au4Offset[2][2]; +extern uint32_t g_au4IQData[256]; +#endif + +/******************************************************************************* + * 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 | HT_CAP_INFO_DSSS_CCK_IN_40M \ + | HT_CAP_INFO_SM_POWER_SAVE) + +#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 + +#if CFG_SUPPORT_BFEE +#define TX_BEAMFORMING_CAP_BFEE \ + (TXBF_RX_NDP_CAPABLE | \ + TXBF_EXPLICIT_COMPRESSED_FEEDBACK_IMMEDIATE_CAPABLE | \ + TXBF_MINIMAL_GROUPING_1_2_3_CAPABLE | \ + TXBF_COMPRESSED_TX_ANTENNANUM_4_SUPPORTED | \ + TXBF_CHANNEL_ESTIMATION_4STS_CAPABILITY) +#else +#define TX_BEAMFORMING_CAP_BFEE 0 +#endif + +#if CFG_SUPPORT_BFER +#define TX_BEAMFORMING_CAP_BFER \ + (TXBF_TX_NDP_CAPABLE | \ + TXBF_EXPLICIT_COMPRESSED_TX_CAPAB) +#else +#define TX_BEAMFORMING_CAP_BFER 0 +#endif + +#define ASEL_CAP_DEFAULT_VAL 0 + +/* Define bandwidth from user setting */ +#define CONFIG_BW_20_40M 0 +#define CONFIG_BW_20M 1 /* 20MHz only */ + +#define RLM_INVALID_POWER_LIMIT -127 /* dbm */ + +#define RLM_MAX_TX_PWR 20 /* dbm */ +#define RLM_MIN_TX_PWR 8 /* dbm */ + +#if CFG_SUPPORT_802_11AC +#if CFG_SUPPORT_BFEE +#define FIELD_VHT_CAP_INFO_BFEE \ + (VHT_CAP_INFO_SU_BEAMFORMEE_CAPABLE) +#define VHT_CAP_INFO_BEAMFORMEE_STS_CAP_MAX 3 +#else +#define FIELD_VHT_CAP_INFO_BFEE 0 +#endif + +#if CFG_SUPPORT_BFER +#define FIELD_VHT_CAP_INFO_BFER \ + (VHT_CAP_INFO_SU_BEAMFORMER_CAPABLE| \ + VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS_2_SUPPORTED) +#else +#define FIELD_VHT_CAP_INFO_BFER 0 +#endif + +#define VHT_CAP_INFO_DEFAULT_VAL \ + (VHT_CAP_INFO_MAX_MPDU_LEN_3K | \ + (AMPDU_PARAM_MAX_AMPDU_LEN_1024K \ + << VHT_CAP_INFO_MAX_AMPDU_LENGTH_OFFSET)) + +#define VHT_CAP_INFO_DEFAULT_HIGHEST_DATA_RATE 0 +#endif +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +struct RLM_CAL_RESULT_ALL_V2 { + /* Used for checking the Cal Data is damaged */ + uint32_t u4MagicNum1; + + /* Thermal Value when do these Calibration */ + uint32_t u4ThermalInfo; + + /* Total Rom Data Length Backup in Host Side */ + uint32_t u4ValidRomCalDataLength; + + /* Total Ram Data Length Backup in Host Side */ + uint32_t u4ValidRamCalDataLength; + + /* All Rom Cal Data Dumpped by FW */ + uint32_t au4RomCalData[10000]; + + /* All Ram Cal Data Dumpped by FW */ + uint32_t au4RamCalData[10000]; + + /* Used for checking the Cal Data is damaged */ + uint32_t u4MagicNum2; +}; +extern struct RLM_CAL_RESULT_ALL_V2 g_rBackupCalDataAllV2; +#endif + +typedef void (*PFN_OPMODE_NOTIFY_DONE_FUNC)( + struct ADAPTER *, uint8_t, bool); + +enum ENUM_OP_NOTIFY_TYPE_T { + OP_NOTIFY_TYPE_VHT_NSS_BW = 0, + OP_NOTIFY_TYPE_HT_NSS, + OP_NOTIFY_TYPE_HT_BW, + OP_NOTIFY_TYPE_NUM +}; + +enum ENUM_OP_CHANGE_STATUS_T { + OP_CHANGE_STATUS_INVALID = 0, /* input invalid */ + /* input valid, but no need to change */ + OP_CHANGE_STATUS_VALID_NO_CHANGE, + /* process callback done before function return */ + OP_CHANGE_STATUS_VALID_CHANGE_CALLBACK_DONE, + /* wait next INT to call callback */ + OP_CHANGE_STATUS_VALID_CHANGE_CALLBACK_WAIT, + OP_CHANGE_STATUS_NUM +}; + +struct SUB_ELEMENT_LIST { + struct SUB_ELEMENT_LIST *prNext; + struct SUB_ELEMENT rSubIE; +}; + +/******************************************************************************* + * P U B 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 == MEDIA_STATE_CONNECTED || \ + (_prBssInfo)->eCurrentOPMode == OP_MODE_ACCESS_POINT || \ + (_prBssInfo)->eCurrentOPMode == OP_MODE_IBSS || \ + IS_BSS_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) + +#if CFG_SUPPORT_802_11AC +#define RLM_NET_IS_11AC(_prBssInfo) \ + ((_prBssInfo)->ucPhyTypeSet & PHY_TYPE_SET_802_11AC) +#endif +#if (CFG_SUPPORT_802_11AX == 1) +#define RLM_NET_IS_11AX(_prBssInfo) \ + ((_prBssInfo)->ucPhyTypeSet & PHY_TYPE_SET_802_11AX) +#endif + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +void rlmFsmEventInit(struct ADAPTER *prAdapter); + +void rlmFsmEventUninit(struct ADAPTER *prAdapter); + +void rlmReqGenerateHtCapIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rlmReqGeneratePowerCapIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rlmReqGenerateSupportedChIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rlmReqGenerateExtCapIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rlmRspGenerateHtCapIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rlmRspGenerateExtCapIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rlmRspGenerateHtOpIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rlmRspGenerateErpIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rlmGenerateMTKOuiIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +u_int8_t rlmParseCheckMTKOuiIE(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, IN uint32_t *pu4Cap); + +void rlmGenerateCsaIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rlmProcessBcn(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb, uint8_t *pucIE, + uint16_t u2IELength); + +void rlmProcessAssocRsp(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb, uint8_t *pucIE, + uint16_t u2IELength); + +void rlmProcessHtAction(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); + +#if CFG_SUPPORT_802_11AC +void rlmProcessVhtAction(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); +#endif + +void rlmFillSyncCmdParam(struct CMD_SET_BSS_RLM_PARAM + *prCmdBody, struct BSS_INFO *prBssInfo); + +void rlmSyncOperationParams(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo); + +void rlmBssInitForAPandIbss(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo); + +void rlmProcessAssocReq(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb, uint8_t *pucIE, + uint16_t u2IELength); + +void rlmBssAborted(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo); + +#if CFG_SUPPORT_TDLS +uint32_t +rlmFillHtCapIEByParams(u_int8_t fg40mAllowed, + u_int8_t fgShortGIDisabled, + uint8_t u8SupportRxSgi20, + uint8_t u8SupportRxSgi40, uint8_t u8SupportRxGf, + enum ENUM_OP_MODE eCurrentOPMode, uint8_t *pOutBuf); + +uint32_t rlmFillHtCapIEByAdapter(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, uint8_t *pOutBuf); + +uint32_t rlmFillVhtCapIEByAdapter(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, uint8_t *pOutBuf); + +#endif + +#if CFG_SUPPORT_802_11AC +void rlmReqGenerateVhtCapIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rlmRspGenerateVhtCapIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rlmRspGenerateVhtOpIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rlmFillVhtOpIE(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, struct MSDU_INFO *prMsduInfo); + +void rlmRspGenerateVhtOpNotificationIE(struct ADAPTER + *prAdapter, struct MSDU_INFO *prMsduInfo); +void rlmReqGenerateVhtOpNotificationIE(struct ADAPTER + *prAdapter, struct MSDU_INFO *prMsduInfo); + + + + +#endif + +void rlmGenerateCountryIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +#if CFG_SUPPORT_DFS +void rlmProcessSpecMgtAction(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); +#endif + +uint32_t +rlmSendOpModeNotificationFrame(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t ucChannelWidth, uint8_t ucNss); + +uint32_t +rlmSendSmPowerSaveFrame(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, uint8_t ucNss); + +void rlmSendChannelSwitchFrame(struct ADAPTER *prAdapter, + uint8_t ucBssIndex); + +uint32_t +rlmNotifyVhtOpModeTxDone(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +uint32_t +rlmSmPowerSaveTxDone(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +uint32_t +rlmNotifyChannelWidthtTxDone(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +uint8_t +rlmGetBssOpBwByVhtAndHtOpInfo(struct BSS_INFO *prBssInfo); + +uint8_t +rlmGetVhtOpBwByBssOpBw(uint8_t ucBssOpBw); + +void +rlmFillVhtOpInfoByBssOpBw(struct BSS_INFO *prBssInfo, + uint8_t ucChannelWidth); + +enum ENUM_OP_CHANGE_STATUS_T +rlmChangeOperationMode( + struct ADAPTER *prAdapter, + uint8_t ucBssIndex, + uint8_t ucChannelWidth, + uint8_t ucOpRxNss, + uint8_t ucOpTxNss, + #if CFG_SUPPORT_SMART_GEAR + uint8_t eNewReq, + #endif + PFN_OPMODE_NOTIFY_DONE_FUNC pfOpChangeHandler +); + +void +rlmDummyChangeOpHandler(struct ADAPTER *prAdapter, + uint8_t ucBssIndex, bool fgIsChangeSuccess); + + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +uint32_t rlmCalBackup( + struct ADAPTER *prAdapter, + uint8_t ucReason, + uint8_t ucAction, + uint8_t ucRomRam +); + +uint32_t rlmTriggerCalBackup( + struct ADAPTER *prAdapter, + u_int8_t fgIsCalDataBackuped +); +#endif + +void rlmModifyVhtBwPara(uint8_t *pucVhtChannelFrequencyS1, + uint8_t *pucVhtChannelFrequencyS2, + uint8_t *pucVhtChannelWidth); + +void rlmReviseMaxBw( + struct ADAPTER *prAdapter, + uint8_t ucBssIndex, + enum ENUM_CHNL_EXT *peExtend, + enum ENUM_CHANNEL_WIDTH *peChannelWidth, + uint8_t *pucS1, + uint8_t *pucPrimaryCh); + +void rlmSetMaxTxPwrLimit(IN struct ADAPTER *prAdapter, int8_t cLimit, + uint8_t ucEnable); + +void rlmSyncExtCapIEwithSupplicant(uint8_t *aucCapabilities, + const uint8_t *supExtCapIEs, size_t IElen); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#ifndef _lint +static __KAL_INLINE__ void rlmDataTypeCheck(void) +{ +} +#endif /* _lint */ + +#endif /* _RLM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rlm_domain.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rlm_domain.h new file mode 100644 index 0000000000000..dc9dc2a8303e4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rlm_domain.h @@ -0,0 +1,1147 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/ + * include/mgmt/rlm_domain.h#1 + */ + +/*! \file "rlm_domain.h" + * \brief + */ + + +#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 + ******************************************************************************* + */ + #include "wsys_cmd_handler_fw.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define MAX_SUBBAND_NUM 6 +#define MAX_SUBBAND_NUM_5G 8 + +#define COUNTRY_CODE_NULL ((uint16_t)0x0) + +/* ISO/IEC 3166-1 two-character country codes */ + +/* Andorra */ +#define COUNTRY_CODE_AD (((uint16_t) 'A' << 8) | (uint16_t) 'D') +/* UAE */ +#define COUNTRY_CODE_AE (((uint16_t) 'A' << 8) | (uint16_t) 'E') +/* Afghanistan */ +#define COUNTRY_CODE_AF (((uint16_t) 'A' << 8) | (uint16_t) 'F') +/* Antigua & Barbuda */ +#define COUNTRY_CODE_AG (((uint16_t) 'A' << 8) | (uint16_t) 'G') +/* Anguilla */ +#define COUNTRY_CODE_AI (((uint16_t) 'A' << 8) | (uint16_t) 'I') +/* Albania */ +#define COUNTRY_CODE_AL (((uint16_t) 'A' << 8) | (uint16_t) 'L') +/* Armenia */ +#define COUNTRY_CODE_AM (((uint16_t) 'A' << 8) | (uint16_t) 'M') +/* Netherlands Antilles */ +#define COUNTRY_CODE_AN (((uint16_t) 'A' << 8) | (uint16_t) 'N') +/* Angola */ +#define COUNTRY_CODE_AO (((uint16_t) 'A' << 8) | (uint16_t) 'O') +/* Argentina */ +#define COUNTRY_CODE_AR (((uint16_t) 'A' << 8) | (uint16_t) 'R') +/* American Samoa (USA) */ +#define COUNTRY_CODE_AS (((uint16_t) 'A' << 8) | (uint16_t) 'S') +/* Austria */ +#define COUNTRY_CODE_AT (((uint16_t) 'A' << 8) | (uint16_t) 'T') +/* Australia */ +#define COUNTRY_CODE_AU (((uint16_t) 'A' << 8) | (uint16_t) 'U') +/* Aruba */ +#define COUNTRY_CODE_AW (((uint16_t) 'A' << 8) | (uint16_t) 'W') +/* Azerbaijan */ +#define COUNTRY_CODE_AZ (((uint16_t) 'A' << 8) | (uint16_t) 'Z') +/* Bosnia and Herzegovina */ +#define COUNTRY_CODE_BA (((uint16_t) 'B' << 8) | (uint16_t) 'A') +/* Barbados */ +#define COUNTRY_CODE_BB (((uint16_t) 'B' << 8) | (uint16_t) 'B') +/* Bangladesh */ +#define COUNTRY_CODE_BD (((uint16_t) 'B' << 8) | (uint16_t) 'D') +/* Belgium */ +#define COUNTRY_CODE_BE (((uint16_t) 'B' << 8) | (uint16_t) 'E') +/* Burkina Faso */ +#define COUNTRY_CODE_BF (((uint16_t) 'B' << 8) | (uint16_t) 'F') +/* Bulgaria */ +#define COUNTRY_CODE_BG (((uint16_t) 'B' << 8) | (uint16_t) 'G') +/* Bahrain */ +#define COUNTRY_CODE_BH (((uint16_t) 'B' << 8) | (uint16_t) 'H') +/* Burundi */ +#define COUNTRY_CODE_BI (((uint16_t) 'B' << 8) | (uint16_t) 'I') +/* Benin */ +#define COUNTRY_CODE_BJ (((uint16_t) 'B' << 8) | (uint16_t) 'J') +/* Bermuda */ +#define COUNTRY_CODE_BM (((uint16_t) 'B' << 8) | (uint16_t) 'M') +/* Brunei */ +#define COUNTRY_CODE_BN (((uint16_t) 'B' << 8) | (uint16_t) 'N') +/* Bolivia */ +#define COUNTRY_CODE_BO (((uint16_t) 'B' << 8) | (uint16_t) 'O') +/* Brazil */ +#define COUNTRY_CODE_BR (((uint16_t) 'B' << 8) | (uint16_t) 'R') +/* Bahamas */ +#define COUNTRY_CODE_BS (((uint16_t) 'B' << 8) | (uint16_t) 'S') +/* Bhutan */ +#define COUNTRY_CODE_BT (((uint16_t) 'B' << 8) | (uint16_t) 'T') +/* Botswana */ +#define COUNTRY_CODE_BW (((uint16_t) 'B' << 8) | (uint16_t) 'W') +/* Belarus */ +#define COUNTRY_CODE_BY (((uint16_t) 'B' << 8) | (uint16_t) 'Y') +/* Belize */ +#define COUNTRY_CODE_BZ (((uint16_t) 'B' << 8) | (uint16_t) 'Z') +/* Canada */ +#define COUNTRY_CODE_CA (((uint16_t) 'C' << 8) | (uint16_t) 'A') +/* Democratic Republic of the Congo */ +#define COUNTRY_CODE_CD (((uint16_t) 'C' << 8) | (uint16_t) 'D') +/* Central African Republic */ +#define COUNTRY_CODE_CF (((uint16_t) 'C' << 8) | (uint16_t) 'F') +/* Republic of the Congo */ +#define COUNTRY_CODE_CG (((uint16_t) 'C' << 8) | (uint16_t) 'G') +/* Switzerland */ +#define COUNTRY_CODE_CH (((uint16_t) 'C' << 8) | (uint16_t) 'H') +/* Cote d'lvoire */ +#define COUNTRY_CODE_CI (((uint16_t) 'C' << 8) | (uint16_t) 'I') +/* Cook Island */ +#define COUNTRY_CODE_CK (((uint16_t) 'C' << 8) | (uint16_t) 'K') +/* Chile */ +#define COUNTRY_CODE_CL (((uint16_t) 'C' << 8) | (uint16_t) 'L') +/* Cameroon */ +#define COUNTRY_CODE_CM (((uint16_t) 'C' << 8) | (uint16_t) 'M') +/* China */ +#define COUNTRY_CODE_CN (((uint16_t) 'C' << 8) | (uint16_t) 'N') +/* Columbia */ +#define COUNTRY_CODE_CO (((uint16_t) 'C' << 8) | (uint16_t) 'O') +/* Costa Rica */ +#define COUNTRY_CODE_CR (((uint16_t) 'C' << 8) | (uint16_t) 'R') +/* Cuba */ +#define COUNTRY_CODE_CU (((uint16_t) 'C' << 8) | (uint16_t) 'U') +/* Cape Verde */ +#define COUNTRY_CODE_CV (((uint16_t) 'C' << 8) | (uint16_t) 'V') +/* "Christmas Island(Australia) */ +#define COUNTRY_CODE_CX (((uint16_t) 'C' << 8) | (uint16_t) 'X') +/* Cyprus */ +#define COUNTRY_CODE_CY (((uint16_t) 'C' << 8) | (uint16_t) 'Y') +/* Czech */ +#define COUNTRY_CODE_CZ (((uint16_t) 'C' << 8) | (uint16_t) 'Z') +/* Germany */ +#define COUNTRY_CODE_DE (((uint16_t) 'D' << 8) | (uint16_t) 'E') +/* Djibouti */ +#define COUNTRY_CODE_DJ (((uint16_t) 'D' << 8) | (uint16_t) 'J') +/* Denmark */ +#define COUNTRY_CODE_DK (((uint16_t) 'D' << 8) | (uint16_t) 'K') +/* Dominica */ +#define COUNTRY_CODE_DM (((uint16_t) 'D' << 8) | (uint16_t) 'M') +/* Dominican Republic */ +#define COUNTRY_CODE_DO (((uint16_t) 'D' << 8) | (uint16_t) 'O') +/* Algeria */ +#define COUNTRY_CODE_DZ (((uint16_t) 'D' << 8) | (uint16_t) 'Z') +/* Ecuador */ +#define COUNTRY_CODE_EC (((uint16_t) 'E' << 8) | (uint16_t) 'C') +/* Estonia */ +#define COUNTRY_CODE_EE (((uint16_t) 'E' << 8) | (uint16_t) 'E') +/* Egypt */ +#define COUNTRY_CODE_EG (((uint16_t) 'E' << 8) | (uint16_t) 'G') +/* Western Sahara (Morocco) */ +#define COUNTRY_CODE_EH (((uint16_t) 'E' << 8) | (uint16_t) 'H') +/* Eritrea */ +#define COUNTRY_CODE_ER (((uint16_t) 'E' << 8) | (uint16_t) 'R') +/* Spain */ +#define COUNTRY_CODE_ES (((uint16_t) 'E' << 8) | (uint16_t) 'S') +/* Ethiopia */ +#define COUNTRY_CODE_ET (((uint16_t) 'E' << 8) | (uint16_t) 'T') +/* Europe */ +#define COUNTRY_CODE_EU (((uint16_t) 'E' << 8) | (uint16_t) 'U') +/* Finland */ +#define COUNTRY_CODE_FI (((uint16_t) 'F' << 8) | (uint16_t) 'I') +/* Fiji */ +#define COUNTRY_CODE_FJ (((uint16_t) 'F' << 8) | (uint16_t) 'J') +/* Falkland Island */ +#define COUNTRY_CODE_FK (((uint16_t) 'F' << 8) | (uint16_t) 'K') +/* Micronesia */ +#define COUNTRY_CODE_FM (((uint16_t) 'F' << 8) | (uint16_t) 'M') +/* Faroe Island */ +#define COUNTRY_CODE_FO (((uint16_t) 'F' << 8) | (uint16_t) 'O') +/* France */ +#define COUNTRY_CODE_FR (((uint16_t) 'F' << 8) | (uint16_t) 'R') +/* Wallis and Futuna (France) */ +#define COUNTRY_CODE_FR (((uint16_t) 'F' << 8) | (uint16_t) 'R') +/* Gabon */ +#define COUNTRY_CODE_GA (((uint16_t) 'G' << 8) | (uint16_t) 'A') +/* United Kingdom */ +#define COUNTRY_CODE_GB (((uint16_t) 'G' << 8) | (uint16_t) 'B') +/* Grenada */ +#define COUNTRY_CODE_GD (((uint16_t) 'G' << 8) | (uint16_t) 'D') +/* Georgia */ +#define COUNTRY_CODE_GE (((uint16_t) 'G' << 8) | (uint16_t) 'E') +/* French Guiana */ +#define COUNTRY_CODE_GF (((uint16_t) 'G' << 8) | (uint16_t) 'F') +/* Guernsey */ +#define COUNTRY_CODE_GG (((uint16_t) 'G' << 8) | (uint16_t) 'G') +/* Ghana */ +#define COUNTRY_CODE_GH (((uint16_t) 'G' << 8) | (uint16_t) 'H') +/* Gibraltar */ +#define COUNTRY_CODE_GI (((uint16_t) 'G' << 8) | (uint16_t) 'I') +/* Gambia */ +#define COUNTRY_CODE_GM (((uint16_t) 'G' << 8) | (uint16_t) 'M') +/* Guinea */ +#define COUNTRY_CODE_GN (((uint16_t) 'G' << 8) | (uint16_t) 'N') +/* Guadeloupe */ +#define COUNTRY_CODE_GP (((uint16_t) 'G' << 8) | (uint16_t) 'P') +/* Equatorial Guinea */ +#define COUNTRY_CODE_GQ (((uint16_t) 'G' << 8) | (uint16_t) 'Q') +/* Greece */ +#define COUNTRY_CODE_GR (((uint16_t) 'G' << 8) | (uint16_t) 'R') +/* Guatemala */ +#define COUNTRY_CODE_GT (((uint16_t) 'G' << 8) | (uint16_t) 'T') +/* Guam */ +#define COUNTRY_CODE_GU (((uint16_t) 'G' << 8) | (uint16_t) 'U') +/* Guinea-Bissau */ +#define COUNTRY_CODE_GW (((uint16_t) 'G' << 8) | (uint16_t) 'W') +/* Guyana */ +#define COUNTRY_CODE_GY (((uint16_t) 'G' << 8) | (uint16_t) 'Y') +/* Hong Kong */ +#define COUNTRY_CODE_HK (((uint16_t) 'H' << 8) | (uint16_t) 'K') +/* Honduras */ +#define COUNTRY_CODE_HN (((uint16_t) 'H' << 8) | (uint16_t) 'N') +/* Croatia */ +#define COUNTRY_CODE_HR (((uint16_t) 'H' << 8) | (uint16_t) 'R') +/* Haiti */ +#define COUNTRY_CODE_HT (((uint16_t) 'H' << 8) | (uint16_t) 'T') +/* Hungary */ +#define COUNTRY_CODE_HU (((uint16_t) 'H' << 8) | (uint16_t) 'U') +/* Indonesia */ +#define COUNTRY_CODE_ID (((uint16_t) 'I' << 8) | (uint16_t) 'D') +/* Ireland */ +#define COUNTRY_CODE_IE (((uint16_t) 'I' << 8) | (uint16_t) 'E') +/* Israel */ +#define COUNTRY_CODE_IL (((uint16_t) 'I' << 8) | (uint16_t) 'L') +/* Isle of Man */ +#define COUNTRY_CODE_IM (((uint16_t) 'I' << 8) | (uint16_t) 'M') +/* India */ +#define COUNTRY_CODE_IN (((uint16_t) 'I' << 8) | (uint16_t) 'N') +/* Iraq */ +#define COUNTRY_CODE_IQ (((uint16_t) 'I' << 8) | (uint16_t) 'Q') +/* Iran */ +#define COUNTRY_CODE_IR (((uint16_t) 'I' << 8) | (uint16_t) 'R') +/* Iceland */ +#define COUNTRY_CODE_IS (((uint16_t) 'I' << 8) | (uint16_t) 'S') +/* Italy */ +#define COUNTRY_CODE_IT (((uint16_t) 'I' << 8) | (uint16_t) 'T') +/* Jersey */ +#define COUNTRY_CODE_JE (((uint16_t) 'J' << 8) | (uint16_t) 'E') +/* Jameica */ +#define COUNTRY_CODE_JM (((uint16_t) 'J' << 8) | (uint16_t) 'M') +/* Jordan */ +#define COUNTRY_CODE_JO (((uint16_t) 'J' << 8) | (uint16_t) 'O') +/* Japan */ +#define COUNTRY_CODE_JP (((uint16_t) 'J' << 8) | (uint16_t) 'P') +/* Kenya */ +#define COUNTRY_CODE_KE (((uint16_t) 'K' << 8) | (uint16_t) 'E') +/* Kyrgyzstan */ +#define COUNTRY_CODE_KG (((uint16_t) 'K' << 8) | (uint16_t) 'G') +/* Cambodia */ +#define COUNTRY_CODE_KH (((uint16_t) 'K' << 8) | (uint16_t) 'H') +/* Kiribati */ +#define COUNTRY_CODE_KI (((uint16_t) 'K' << 8) | (uint16_t) 'I') +/* Comoros */ +#define COUNTRY_CODE_KM (((uint16_t) 'K' << 8) | (uint16_t) 'M') +/* Saint Kitts and Nevis */ +#define COUNTRY_CODE_KN (((uint16_t) 'K' << 8) | (uint16_t) 'N') +/* North Korea */ +#define COUNTRY_CODE_KP (((uint16_t) 'K' << 8) | (uint16_t) 'P') +/* South Korea */ +#define COUNTRY_CODE_KR (((uint16_t) 'K' << 8) | (uint16_t) 'R') +/* Kuwait */ +#define COUNTRY_CODE_KW (((uint16_t) 'K' << 8) | (uint16_t) 'W') +/* Cayman Islands */ +#define COUNTRY_CODE_KY (((uint16_t) 'K' << 8) | (uint16_t) 'Y') +/* Kazakhstan */ +#define COUNTRY_CODE_KZ (((uint16_t) 'K' << 8) | (uint16_t) 'Z') +/* Laos */ +#define COUNTRY_CODE_LA (((uint16_t) 'L' << 8) | (uint16_t) 'A') +/* Lebanon */ +#define COUNTRY_CODE_LB (((uint16_t) 'L' << 8) | (uint16_t) 'B') +/* Saint Lucia */ +#define COUNTRY_CODE_LC (((uint16_t) 'L' << 8) | (uint16_t) 'C') +/* Liechtenstein */ +#define COUNTRY_CODE_LI (((uint16_t) 'L' << 8) | (uint16_t) 'I') +/* Sri Lanka */ +#define COUNTRY_CODE_LK (((uint16_t) 'L' << 8) | (uint16_t) 'K') +/* Liberia */ +#define COUNTRY_CODE_LR (((uint16_t) 'L' << 8) | (uint16_t) 'R') +/* Lesotho */ +#define COUNTRY_CODE_LS (((uint16_t) 'L' << 8) | (uint16_t) 'S') +/* Lithuania */ +#define COUNTRY_CODE_LT (((uint16_t) 'L' << 8) | (uint16_t) 'T') +/* Luxemburg */ +#define COUNTRY_CODE_LU (((uint16_t) 'L' << 8) | (uint16_t) 'U') +/* Latvia */ +#define COUNTRY_CODE_LV (((uint16_t) 'L' << 8) | (uint16_t) 'V') +/* Libya */ +#define COUNTRY_CODE_LY (((uint16_t) 'L' << 8) | (uint16_t) 'Y') +/* Morocco */ +#define COUNTRY_CODE_MA (((uint16_t) 'M' << 8) | (uint16_t) 'A') +/* Monaco */ +#define COUNTRY_CODE_MC (((uint16_t) 'M' << 8) | (uint16_t) 'C') +/* Moldova */ +#define COUNTRY_CODE_MD (((uint16_t) 'M' << 8) | (uint16_t) 'D') +/* Montenegro */ +#define COUNTRY_CODE_ME (((uint16_t) 'M' << 8) | (uint16_t) 'E') +/* Saint Martin / Sint Marteen (Added on window's list) */ +#define COUNTRY_CODE_MF (((uint16_t) 'M' << 8) | (uint16_t) 'F') +/* Madagascar */ +#define COUNTRY_CODE_MG (((uint16_t) 'M' << 8) | (uint16_t) 'G') +/* Marshall Islands */ +#define COUNTRY_CODE_MH (((uint16_t) 'M' << 8) | (uint16_t) 'H') +/* Macedonia */ +#define COUNTRY_CODE_MK (((uint16_t) 'M' << 8) | (uint16_t) 'K') +/* Mali */ +#define COUNTRY_CODE_ML (((uint16_t) 'M' << 8) | (uint16_t) 'L') +/* Myanmar */ +#define COUNTRY_CODE_MM (((uint16_t) 'M' << 8) | (uint16_t) 'M') +/* Mongolia */ +#define COUNTRY_CODE_MN (((uint16_t) 'M' << 8) | (uint16_t) 'N') +/* Macao */ +#define COUNTRY_CODE_MO (((uint16_t) 'M' << 8) | (uint16_t) 'O') +/* Northern Mariana Islands (Rota Island Saipan and Tinian Island) */ +#define COUNTRY_CODE_MP (((uint16_t) 'M' << 8) | (uint16_t) 'P') +/* Martinique (France) */ +#define COUNTRY_CODE_MQ (((uint16_t) 'M' << 8) | (uint16_t) 'Q') +/* Mauritania */ +#define COUNTRY_CODE_MR (((uint16_t) 'M' << 8) | (uint16_t) 'R') +/* Montserrat (UK) */ +#define COUNTRY_CODE_MS (((uint16_t) 'M' << 8) | (uint16_t) 'S') +/* Malta */ +#define COUNTRY_CODE_MT (((uint16_t) 'M' << 8) | (uint16_t) 'T') +/* Mauritius */ +#define COUNTRY_CODE_MU (((uint16_t) 'M' << 8) | (uint16_t) 'U') +/* Maldives */ +#define COUNTRY_CODE_MV (((uint16_t) 'M' << 8) | (uint16_t) 'V') +/* Malawi */ +#define COUNTRY_CODE_MW (((uint16_t) 'M' << 8) | (uint16_t) 'W') +/* Mexico */ +#define COUNTRY_CODE_MX (((uint16_t) 'M' << 8) | (uint16_t) 'X') +/* Malaysia */ +#define COUNTRY_CODE_MY (((uint16_t) 'M' << 8) | (uint16_t) 'Y') +/* Mozambique */ +#define COUNTRY_CODE_MZ (((uint16_t) 'M' << 8) | (uint16_t) 'Z') +/* Namibia */ +#define COUNTRY_CODE_NA (((uint16_t) 'N' << 8) | (uint16_t) 'A') +/* New Caledonia */ +#define COUNTRY_CODE_NC (((uint16_t) 'N' << 8) | (uint16_t) 'C') +/* Niger */ +#define COUNTRY_CODE_NE (((uint16_t) 'N' << 8) | (uint16_t) 'E') +/* Norfolk Island */ +#define COUNTRY_CODE_NF (((uint16_t) 'N' << 8) | (uint16_t) 'F') +/* Nigeria */ +#define COUNTRY_CODE_NG (((uint16_t) 'N' << 8) | (uint16_t) 'G') +/* Nicaragua */ +#define COUNTRY_CODE_NI (((uint16_t) 'N' << 8) | (uint16_t) 'I') +/* Netherlands */ +#define COUNTRY_CODE_NL (((uint16_t) 'N' << 8) | (uint16_t) 'L') +/* Norway */ +#define COUNTRY_CODE_NO (((uint16_t) 'N' << 8) | (uint16_t) 'O') +/* Nepal */ +#define COUNTRY_CODE_NP (((uint16_t) 'N' << 8) | (uint16_t) 'P') +/* Nauru */ +#define COUNTRY_CODE_NR (((uint16_t) 'N' << 8) | (uint16_t) 'R') +/* Niue */ +#define COUNTRY_CODE_NU (((uint16_t) 'N' << 8) | (uint16_t) 'U') +/* New Zealand */ +#define COUNTRY_CODE_NZ (((uint16_t) 'N' << 8) | (uint16_t) 'Z') +/* Oman */ +#define COUNTRY_CODE_OM (((uint16_t) 'O' << 8) | (uint16_t) 'M') +/* Panama */ +#define COUNTRY_CODE_PA (((uint16_t) 'P' << 8) | (uint16_t) 'A') +/* Peru */ +#define COUNTRY_CODE_PE (((uint16_t) 'P' << 8) | (uint16_t) 'E') +/* "French Polynesia */ +#define COUNTRY_CODE_PF (((uint16_t) 'P' << 8) | (uint16_t) 'F') +/* Papua New Guinea */ +#define COUNTRY_CODE_PG (((uint16_t) 'P' << 8) | (uint16_t) 'G') +/* Philippines */ +#define COUNTRY_CODE_PH (((uint16_t) 'P' << 8) | (uint16_t) 'H') +/* Pakistan */ +#define COUNTRY_CODE_PK (((uint16_t) 'P' << 8) | (uint16_t) 'K') +/* Poland */ +#define COUNTRY_CODE_PL (((uint16_t) 'P' << 8) | (uint16_t) 'L') +/* Saint Pierre and Miquelon */ +#define COUNTRY_CODE_PM (((uint16_t) 'P' << 8) | (uint16_t) 'M') +/* Pitcairn Islands */ +#define COUNTRY_CODE_PN (((uint16_t) 'P' << 8) | (uint16_t) 'N') +/* Puerto Rico (USA) */ +#define COUNTRY_CODE_PR (((uint16_t) 'P' << 8) | (uint16_t) 'R') +/* Palestinian Authority */ +#define COUNTRY_CODE_PS (((uint16_t) 'P' << 8) | (uint16_t) 'S') +/* Portugal */ +#define COUNTRY_CODE_PT (((uint16_t) 'P' << 8) | (uint16_t) 'T') +/* Palau */ +#define COUNTRY_CODE_PW (((uint16_t) 'P' << 8) | (uint16_t) 'W') +/* Paraguay */ +#define COUNTRY_CODE_PY (((uint16_t) 'P' << 8) | (uint16_t) 'Y') +/* Qatar */ +#define COUNTRY_CODE_QA (((uint16_t) 'Q' << 8) | (uint16_t) 'A') +/* Reunion (France) */ +#define COUNTRY_CODE_RE (((uint16_t) 'R' << 8) | (uint16_t) 'E') +/* Kosvo (Added on window's list) */ +#define COUNTRY_CODE_RKS (((uint16_t) 'R' << 8) | (uint16_t) 'K') +/* Romania */ +#define COUNTRY_CODE_RO (((uint16_t) 'R' << 8) | (uint16_t) 'O') +/* Serbia */ +#define COUNTRY_CODE_RS (((uint16_t) 'R' << 8) | (uint16_t) 'S') +/* Russia */ +#define COUNTRY_CODE_RU (((uint16_t) 'R' << 8) | (uint16_t) 'U') +/* Rwanda */ +#define COUNTRY_CODE_RW (((uint16_t) 'R' << 8) | (uint16_t) 'W') +/* Saudi Arabia */ +#define COUNTRY_CODE_SA (((uint16_t) 'S' << 8) | (uint16_t) 'A') +/* Solomon Islands */ +#define COUNTRY_CODE_SB (((uint16_t) 'S' << 8) | (uint16_t) 'B') +/* Seychelles */ +#define COUNTRY_CODE_SC (((uint16_t) 'S' << 8) | (uint16_t) 'C') +/* Sudan */ +#define COUNTRY_CODE_SD (((uint16_t) 'S' << 8) | (uint16_t) 'D') +/* Sweden */ +#define COUNTRY_CODE_SE (((uint16_t) 'S' << 8) | (uint16_t) 'E') +/* Singapole */ +#define COUNTRY_CODE_SG (((uint16_t) 'S' << 8) | (uint16_t) 'G') +/* Slovenia */ +#define COUNTRY_CODE_SI (((uint16_t) 'S' << 8) | (uint16_t) 'I') +/* Slovakia */ +#define COUNTRY_CODE_SK (((uint16_t) 'S' << 8) | (uint16_t) 'K') +/* Sierra Leone */ +#define COUNTRY_CODE_SL (((uint16_t) 'S' << 8) | (uint16_t) 'L') +/* San Marino */ +#define COUNTRY_CODE_SM (((uint16_t) 'S' << 8) | (uint16_t) 'M') +/* Senegal */ +#define COUNTRY_CODE_SN (((uint16_t) 'S' << 8) | (uint16_t) 'N') +/* Somalia */ +#define COUNTRY_CODE_SO (((uint16_t) 'S' << 8) | (uint16_t) 'O') +/* Suriname */ +#define COUNTRY_CODE_SR (((uint16_t) 'S' << 8) | (uint16_t) 'R') +/* South_Sudan */ +#define COUNTRY_CODE_SS (((uint16_t) 'S' << 8) | (uint16_t) 'S') +/* Sao Tome and Principe */ +#define COUNTRY_CODE_ST (((uint16_t) 'S' << 8) | (uint16_t) 'T') +/* El Salvador */ +#define COUNTRY_CODE_SV (((uint16_t) 'S' << 8) | (uint16_t) 'V') +/* Syria */ +#define COUNTRY_CODE_SY (((uint16_t) 'S' << 8) | (uint16_t) 'Y') +/* Swaziland */ +#define COUNTRY_CODE_SZ (((uint16_t) 'S' << 8) | (uint16_t) 'Z') +/* Turks and Caicos Islands (UK) */ +#define COUNTRY_CODE_TC (((uint16_t) 'T' << 8) | (uint16_t) 'C') +/* Chad */ +#define COUNTRY_CODE_TD (((uint16_t) 'T' << 8) | (uint16_t) 'D') +/* French Southern and Antarctic Lands */ +#define COUNTRY_CODE_TF (((uint16_t) 'T' << 8) | (uint16_t) 'F') +/* Togo */ +#define COUNTRY_CODE_TG (((uint16_t) 'T' << 8) | (uint16_t) 'G') +/* Thailand */ +#define COUNTRY_CODE_TH (((uint16_t) 'T' << 8) | (uint16_t) 'H') +/* Tajikistan */ +#define COUNTRY_CODE_TJ (((uint16_t) 'T' << 8) | (uint16_t) 'J') +/* East Timor */ +#define COUNTRY_CODE_TL (((uint16_t) 'T' << 8) | (uint16_t) 'L') +/* Turkmenistan */ +#define COUNTRY_CODE_TM (((uint16_t) 'T' << 8) | (uint16_t) 'M') +/* Tunisia */ +#define COUNTRY_CODE_TN (((uint16_t) 'T' << 8) | (uint16_t) 'N') +/* Tonga */ +#define COUNTRY_CODE_TO (((uint16_t) 'T' << 8) | (uint16_t) 'O') +/* Turkey */ +#define COUNTRY_CODE_TR (((uint16_t) 'T' << 8) | (uint16_t) 'R') +/* Trinidad and Tobago */ +#define COUNTRY_CODE_TT (((uint16_t) 'T' << 8) | (uint16_t) 'T') +/* Tuvalu */ +#define COUNTRY_CODE_TV (((uint16_t) 'T' << 8) | (uint16_t) 'V') +/* Taiwan */ +#define COUNTRY_CODE_TW (((uint16_t) 'T' << 8) | (uint16_t) 'W') +/* Tanzania */ +#define COUNTRY_CODE_TZ (((uint16_t) 'T' << 8) | (uint16_t) 'Z') +/* Ukraine */ +#define COUNTRY_CODE_UA (((uint16_t) 'U' << 8) | (uint16_t) 'A') +/* Ugnada */ +#define COUNTRY_CODE_UG (((uint16_t) 'U' << 8) | (uint16_t) 'G') +/* US */ +#define COUNTRY_CODE_US (((uint16_t) 'U' << 8) | (uint16_t) 'S') +/* Uruguay */ +#define COUNTRY_CODE_UY (((uint16_t) 'U' << 8) | (uint16_t) 'Y') +/* Uzbekistan */ +#define COUNTRY_CODE_UZ (((uint16_t) 'U' << 8) | (uint16_t) 'Z') +/* Vatican (Holy See) */ +#define COUNTRY_CODE_VA (((uint16_t) 'V' << 8) | (uint16_t) 'A') +/* Saint Vincent and the Grenadines */ +#define COUNTRY_CODE_VC (((uint16_t) 'V' << 8) | (uint16_t) 'C') +/* Venezuela */ +#define COUNTRY_CODE_VE (((uint16_t) 'V' << 8) | (uint16_t) 'E') +/* British Virgin Islands */ +#define COUNTRY_CODE_VG (((uint16_t) 'V' << 8) | (uint16_t) 'G') +/* US Virgin Islands */ +#define COUNTRY_CODE_VI (((uint16_t) 'V' << 8) | (uint16_t) 'I') +/* Vietnam */ +#define COUNTRY_CODE_VN (((uint16_t) 'V' << 8) | (uint16_t) 'N') +/* Vanuatu */ +#define COUNTRY_CODE_VU (((uint16_t) 'V' << 8) | (uint16_t) 'U') +/* Samoa */ +#define COUNTRY_CODE_WS (((uint16_t) 'W' << 8) | (uint16_t) 'S') +/* Yemen */ +#define COUNTRY_CODE_YE (((uint16_t) 'Y' << 8) | (uint16_t) 'E') +/* Mayotte (France) */ +#define COUNTRY_CODE_YT (((uint16_t) 'Y' << 8) | (uint16_t) 'T') +/* South Africa */ +#define COUNTRY_CODE_ZA (((uint16_t) 'Z' << 8) | (uint16_t) 'A') +/* Zambia */ +#define COUNTRY_CODE_ZM (((uint16_t) 'Z' << 8) | (uint16_t) 'M') +/* Zimbabwe */ +#define COUNTRY_CODE_ZW (((uint16_t) 'Z' << 8) | (uint16_t) 'W') +/* Default country domain */ +#define COUNTRY_CODE_DF (((uint16_t) 'D' << 8) | (uint16_t) 'F') +/* World Wide */ +#define COUNTRY_CODE_WW (((uint16_t) '0' << 8) | (uint16_t) '0') + + +/* dot11RegDomainsSupportValue */ +#define MIB_REG_DOMAIN_FCC 0x10 /* FCC (US) */ +#define MIB_REG_DOMAIN_IC 0x20 /* IC or DOC (Canada) */ +#define MIB_REG_DOMAIN_ETSI 0x30 /* ETSI (Europe) */ +#define MIB_REG_DOMAIN_SPAIN 0x31 /* Spain */ +#define MIB_REG_DOMAIN_FRANCE 0x32 /* France */ +#define MIB_REG_DOMAIN_JAPAN 0x40 /* MPHPT (Japan) */ +#define MIB_REG_DOMAIN_OTHER 0x00 /* other */ + +/*2.4G*/ +#define BAND_2G4_LOWER_BOUND 1 +#define BAND_2G4_UPPER_BOUND 14 +/*5G SubBand FCC spec*/ +#define UNII1_LOWER_BOUND 36 +#define UNII1_UPPER_BOUND 48 +#define UNII2A_LOWER_BOUND 52 +#define UNII2A_UPPER_BOUND 64 +#define UNII2C_LOWER_BOUND 100 +#define UNII2C_UPPER_BOUND 144 +#define UNII3_LOWER_BOUND 149 +#define UNII3_UPPER_BOUND 165 + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY +#define POWER_LIMIT_TABLE_NULL 0xFFFF +#define MAX_TX_POWER 63 +#define MIN_TX_POWER -64 +/*align Frimware Max Power Limit CH Num*/ +#define MAX_CMD_SUPPORT_CHANNEL_NUM 64 +#endif + +#if (CFG_SUPPORT_SINGLE_SKU == 1) +/* ARRAY_SIZE(mtk_2ghz_channels) + ARRAY_SIZE(mtk_5ghz_channels) */ +#define MAX_SUPPORTED_CH_COUNT (MAX_CHN_NUM) +#define REG_RULE_LIGHT(start, end, bw, reg_flags) \ + REG_RULE(start, end, bw, 0, 0, reg_flags) +#endif + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +/* Define Tx Power Control Channel Type */ +#define MAX_TX_PWR_CTRL_ELEMENT_NAME_SIZE 16 +#define PWR_CTRL_CHNL_TYPE_KEY_ALL "ALL" +#define PWR_CTRL_CHNL_TYPE_KEY_2G4 "2G4" +#define PWR_CTRL_CHNL_TYPE_KEY_5G "5G" +#define PWR_CTRL_CHNL_TYPE_KEY_BANDEDGE_2G4 "BANDEDGE2G4" +#define PWR_CTRL_CHNL_TYPE_KEY_BANDEDGE_5G "BANDEDGE5G" +#define PWR_CTRL_CHNL_TYPE_KEY_5G_BAND1 "5GBAND1" +#define PWR_CTRL_CHNL_TYPE_KEY_5G_BAND2 "5GBAND2" +#define PWR_CTRL_CHNL_TYPE_KEY_5G_BAND3 "5GBAND3" +#define PWR_CTRL_CHNL_TYPE_KEY_5G_BAND4 "5GBAND4" + +#define PWR_CFG_PRAM_NUM_ALL_RATE 1 + +#define PWR_CFG_PRAM_NUM_AX 18 +#if (CFG_SUPPORT_DYNA_TX_PWR_CTRL_OFDM_SETTING == 1) +#define PWR_CFG_PRAM_NUM_AC 11 +#else +#define PWR_CFG_PRAM_NUM_AC 9 +#endif /* CFG_SUPPORT_DYNA_TX_PWR_CTRL_OFDM_SETTING */ + +enum ENUM_TX_POWER_CTRL_LIST_TYPE { + PWR_CTRL_TYPE_DEFAULT_LIST = 0, + PWR_CTRL_TYPE_DYNAMIC_LIST, + PWR_CTRL_TYPE_ALL_LIST, +}; + +enum ENUM_TX_POWER_CTRL_APPLIED_WAY { + PWR_CTRL_TYPE_APPLIED_WAY_WIFION = 1, + PWR_CTRL_TYPE_APPLIED_WAY_IOCTL, +}; + +enum ENUM_TX_POWER_CTRL_OPERATION { + PWR_CTRL_TYPE_OPERATION_POWER_LEVEL = 1, + PWR_CTRL_TYPE_OPERATION_POWER_OFFSET, +}; + +enum ENUM_TX_POWER_CTRL_TYPE { + PWR_CTRL_TYPE_WIFION_POWER_LEVEL = 1, + PWR_CTRL_TYPE_WIFION_POWER_OFFSET, + PWR_CTRL_TYPE_IOCTL_POWER_LEVEL, + PWR_CTRL_TYPE_IOCTL_POWER_OFFSET, +}; + +enum ENUM_TX_POWER_CTRL_VALUE_SIGN { + PWR_CTRL_TYPE_NO_ACTION = 0, + PWR_CTRL_TYPE_POSITIVE, + PWR_CTRL_TYPE_NEGATIVE, +}; + +enum ENUM_TX_POWER_CTRL_CHANNEL_TYPE { + PWR_CTRL_CHNL_TYPE_NORMAL = 0, + PWR_CTRL_CHNL_TYPE_ALL, + PWR_CTRL_CHNL_TYPE_RANGE, + PWR_CTRL_CHNL_TYPE_2G4, + PWR_CTRL_CHNL_TYPE_5G, + PWR_CTRL_CHNL_TYPE_BANDEDGE_2G4, + PWR_CTRL_CHNL_TYPE_BANDEDGE_5G, + PWR_CTRL_CHNL_TYPE_5G_BAND1, + PWR_CTRL_CHNL_TYPE_5G_BAND2, + PWR_CTRL_CHNL_TYPE_5G_BAND3, + PWR_CTRL_CHNL_TYPE_5G_BAND4, +}; + +enum ENUM_POWER_LIMIT { + PWR_LIMIT_CCK, +#if (CFG_SUPPORT_DYNA_TX_PWR_CTRL_OFDM_SETTING == 1) + PWR_LIMIT_OFDM_L, + PWR_LIMIT_OFDM_H, +#endif /* CFG_SUPPORT_DYNA_TX_PWR_CTRL_OFDM_SETTING */ + PWR_LIMIT_20M_L, + PWR_LIMIT_20M_H, + PWR_LIMIT_40M_L, + PWR_LIMIT_40M_H, + PWR_LIMIT_80M_L, + PWR_LIMIT_80M_H, + PWR_LIMIT_160M_L, + PWR_LIMIT_160M_H, + PWR_LIMIT_NUM +}; +enum ENUM_POWER_LIMIT_HE { + PWR_LIMIT_RU26_L, /* MCS0~4 */ + PWR_LIMIT_RU26_H, /* MCS5~9 */ + PWR_LIMIT_RU26_U, /* MCS10~11 */ + + PWR_LIMIT_RU52_L, /* MCS0~4 */ + PWR_LIMIT_RU52_H, /* MCS5~9 */ + PWR_LIMIT_RU52_U, /* MCS10~11 */ + + PWR_LIMIT_RU106_L, /* MCS0~4 */ + PWR_LIMIT_RU106_H, /* MCS5~9 */ + PWR_LIMIT_RU106_U, /* MCS10~11 */ + + PWR_LIMIT_RU242_L, /* MCS0~4 */ + PWR_LIMIT_RU242_H, /* MCS5~9 */ + PWR_LIMIT_RU242_U, /* MCS10~11 */ + + PWR_LIMIT_RU484_L, /* MCS0~4 */ + PWR_LIMIT_RU484_H, /* MCS5~9 */ + PWR_LIMIT_RU484_U, /* MCS10~11 */ + + PWR_LIMIT_RU996_L, /* MCS0~4 */ + PWR_LIMIT_RU996_H, /* MCS5~9 */ + PWR_LIMIT_RU996_U, /* MCS10~11 */ + PWR_LIMIT_HE_NUM +}; + +struct TX_PWR_CTRL_CHANNEL_SETTING { + enum ENUM_TX_POWER_CTRL_CHANNEL_TYPE eChnlType; + uint8_t channelParam[2]; + + enum ENUM_TX_POWER_CTRL_VALUE_SIGN op[PWR_LIMIT_NUM]; + int8_t i8PwrLimit[PWR_LIMIT_NUM]; + + enum ENUM_TX_POWER_CTRL_VALUE_SIGN opHE[PWR_LIMIT_HE_NUM]; + int8_t i8PwrLimitHE[PWR_LIMIT_HE_NUM]; +}; + +struct TX_PWR_CTRL_ELEMENT { + struct LINK_ENTRY node; + u_int8_t fgApplied; + char name[MAX_TX_PWR_CTRL_ELEMENT_NAME_SIZE]; /* scenario name */ + uint8_t index; /* scenario index */ + enum ENUM_TX_POWER_CTRL_TYPE eCtrlType; + uint8_t settingCount; + struct TX_PWR_CTRL_CHANNEL_SETTING rChlSettingList[1]; +}; + +struct PARAM_TX_PWR_CTRL_IOCTL { + u_int8_t fgApplied; + uint8_t *name; + uint8_t index; + uint8_t *newSetting; +}; + +#endif + +enum ENUM_POWER_LIMIT_SUBBAND { + POWER_LIMIT_2G4 = 0, + POWER_LIMIT_UNII1 = 1, + POWER_LIMIT_UNII2A = 2, + POWER_LIMIT_UNII2C = 3, + POWER_LIMIT_UNII3 = 4, + POWER_LIMIT_SUBAND_NUM +}; + +/* Define channel offset in unit of 5MHz bandwidth */ +enum ENUM_CHNL_SPAN { + CHNL_SPAN_5 = 1, + CHNL_SPAN_10 = 2, + CHNL_SPAN_20 = 4, + CHNL_SPAN_40 = 8 +}; + +/* Define BSS operating bandwidth */ +enum ENUM_CHNL_BW { + CHNL_BW_20, + CHNL_BW_20_40, + CHNL_BW_10, + CHNL_BW_5 +}; + +#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. + */ +struct DOMAIN_SUBBAND_INFO { + uint8_t ucRegClass; + enum ENUM_BAND eBand; + enum ENUM_CHNL_SPAN eChannelSpan; + uint8_t ucFirstChannelNum; + uint8_t ucNumChannels; + enum ENUM_CHNL_BW eChannelBw; + u_int8_t fgDfsNeeded; + u_int8_t fgIbssProhibited; +}; + +/* Use it as all available channel list for STA */ +struct DOMAIN_INFO_ENTRY { + uint16_t u2CountryCode; + uint16_t u2MibRegDomainValue; + + /* If different attributes, put them into different rSubBands. + * For example, DFS shall be used or not. + */ + struct DOMAIN_SUBBAND_INFO rSubBand[MAX_SUBBAND_NUM]; +}; + +#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. + */ +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. + */ + uint8_t ucRegClass; /* Regulation class for 20MHz */ + uint8_t ucBand; /* Type: ENUM_BAND_T */ + uint8_t ucChannelSpan; /* Type: ENUM_CHNL_SPAN_T */ + uint8_t ucFirstChannelNum; + uint8_t ucNumChannels; + uint8_t fgDfs; /* Type: BOOLEAN*/ +}; + +/* Use it as all available channel list for STA */ +struct DOMAIN_INFO_ENTRY { + uint16_t *pu2CountryGroup; + uint32_t u4CountryNum; + + /* If different attributes, put them into different rSubBands. + * For example, DFS shall be used or not. + */ + struct DOMAIN_SUBBAND_INFO rSubBand[MAX_SUBBAND_NUM]; +}; +#endif + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +#if (CFG_SUPPORT_SINGLE_SKU == 1) +/* + * MT_TxPwrLimit.dat format + */ +#define SECTION_PREFIX (0x23232323) +#define ELEMENT_PREFIX (0xffff) +#define VERSION (0x00000001) +#define SIZE_OF_VERSION 4 +#define WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE 204800 + +struct tx_pwr_element { + uint16_t prefix; + uint8_t channel_num; + uint8_t reserved; + + /*the followings are in unit: 0.5 dbm*/ + + uint8_t tx_pwr_dsss_cck; + uint8_t tx_pwr_dsss_bpsk; + + uint8_t tx_pwr_ofdm_bpsk; /* 6M, 9M */ + uint8_t tx_pwr_ofdm_qpsk; /* 12M, 18M */ + uint8_t tx_pwr_ofdm_16qam; /* 24M, 36M */ + uint8_t tx_pwr_ofdm_48m; + uint8_t tx_pwr_ofdm_54m; + + uint8_t tx_pwr_ht20_bpsk; /* MCS0*/ + uint8_t tx_pwr_ht20_qpsk; /* MCS1, MCS2*/ + uint8_t tx_pwr_ht20_16qam; /* MCS3, MCS4*/ + uint8_t tx_pwr_ht20_mcs5; /* MCS5*/ + uint8_t tx_pwr_ht20_mcs6; /* MCS6*/ + uint8_t tx_pwr_ht20_mcs7; /* MCS7*/ + + uint8_t tx_pwr_ht40_bpsk; /* MCS0*/ + uint8_t tx_pwr_ht40_qpsk; /* MCS1, MCS2*/ + uint8_t tx_pwr_ht40_16qam; /* MCS3, MCS4*/ + uint8_t tx_pwr_ht40_mcs5; /* MCS5*/ + uint8_t tx_pwr_ht40_mcs6; /* MCS6*/ + uint8_t tx_pwr_ht40_mcs7; /* MCS7*/ + + uint8_t tx_pwr_vht20_bpsk; /* MCS0*/ + uint8_t tx_pwr_vht20_qpsk; /* MCS1, MCS2*/ + uint8_t tx_pwr_vht20_16qam; /* MCS3, MCS4*/ + uint8_t tx_pwr_vht20_64qam; /* MCS5, MCS6*/ + uint8_t tx_pwr_vht20_mcs7; + uint8_t tx_pwr_vht20_mcs8; + uint8_t tx_pwr_vht20_mcs9; + + uint8_t tx_pwr_vht_40; + uint8_t tx_pwr_vht_80; + uint8_t tx_pwr_vht_160nc; + uint8_t tx_pwr_lg_40; + uint8_t tx_pwr_lg_80; + + uint8_t tx_pwr_1ss_delta; + uint8_t reserved_3[3]; +}; + +struct tx_pwr_section { + uint32_t prefix; + uint32_t country_code; +}; +#endif /*#if (CFG_SUPPORT_SINGLE_SKU == 1)*/ + +struct COUNTRY_POWER_LIMIT_TABLE_DEFAULT { + uint8_t aucCountryCode[2]; + /* 0: ch 1 ~14 + * 1: ch 36 ~48 + * 2: ch 52 ~64 + * 3: ch 100 ~144 + * 4: ch 149 ~165 + */ + int8_t aucPwrLimitSubBand[POWER_LIMIT_SUBAND_NUM]; + /* bit0: cPwrLimit2G4, bit1: cPwrLimitUnii1; bit2: cPwrLimitUnii2A;*/ + /* bit3: cPwrLimitUnii2C; bit4: cPwrLimitUnii3; mW: 0, mW\MHz : 1 */ + uint8_t ucPwrUnit; +}; + +struct COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION { + uint8_t aucCountryCode[2]; + uint8_t ucCentralCh; + /* Note: this array doesn't include cPwrLimitOFDM_L & cPwrLimitOFDM_H */ + int8_t aucPwrLimit[PWR_LIMIT_NUM]; +}; + +struct COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION_HE { + uint8_t aucCountryCode[2]; + uint8_t ucCentralCh; + int8_t aucPwrLimit[PWR_LIMIT_HE_NUM]; +}; + + +struct SUBBAND_CHANNEL { + uint8_t ucStartCh; + uint8_t ucEndCh; + uint8_t ucInterval; + uint8_t ucReserved; +}; + +#endif /* CFG_SUPPORT_PWR_LIMIT_COUNTRY */ + +#if (CFG_SUPPORT_SINGLE_SKU == 1) +/* + * Event from chip for single sku + */ +struct SINGLE_SKU_INFO { + uint32_t u4EfuseCountryCode; + uint8_t isEfuseValid; + uint8_t ucReserved[7]; +}; + +/* + * single sku control structure + */ +enum regd_state { + REGD_STATE_UNDEFINED, + REGD_STATE_INIT, + REGD_STATE_SET_WW_CORE, + REGD_STATE_SET_COUNTRY_USER, + REGD_STATE_SET_COUNTRY_DRIVER, + REGD_STATE_SET_COUNTRY_IE, + REGD_STATE_INVALID +}; + +enum regd_control_flag { + REGD_CTRL_FLAG_SUPPORT_LOCAL_REGD_DB = (0x1 << 0) +}; + +struct mtk_regd_control { + u_int8_t en; + u_int8_t isEfuseCountryCodeUsed; + enum regd_state state; + u32 alpha2; + u32 tmp_alpha2; /*store country code set by iwpriv "country XX"*/ + u32 flag; /*enum regd_control_flag*/ + struct GLUE_INFO *pGlueInfo; /*wlan GlueInfo*/ + u8 n_channel_active_2g; + u8 n_channel_active_5g; + struct CMD_DOMAIN_CHANNEL channels[MAX_SUPPORTED_CH_COUNT]; + enum nl80211_dfs_regions dfs_region; +}; + +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) +struct mtk_regdomain { + char country_code[4]; + const struct ieee80211_regdomain *prRegdRules; +}; +#endif + +#endif +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +#define CAL_CH_OFFSET_80M(_PRIMARY_CH, _CENTRAL_CH) \ + (((_PRIMARY_CH - _CENTRAL_CH) + 6) >> 2) + +#define CAL_CH_OFFSET_160M(_PRIMARY_CH, _CENTRAL_CH) \ + (((_PRIMARY_CH - _CENTRAL_CH) + 14) >> 2) + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +struct DOMAIN_INFO_ENTRY *rlmDomainGetDomainInfo( + struct ADAPTER *prAdapter); + +u_int8_t rlmIsValidChnl(struct ADAPTER *prAdapter, uint8_t ucNumOfChannel, + enum ENUM_BAND eBand); + +void +rlmDomainGetChnlList(struct ADAPTER *prAdapter, + enum ENUM_BAND eSpecificBand, u_int8_t fgNoDfs, + uint8_t ucMaxChannelNum, uint8_t *pucNumOfChannel, + struct RF_CHANNEL_INFO *paucChannelList); + +void rlmDomainGetDfsChnls(struct ADAPTER *prAdapter, + uint8_t ucMaxChannelNum, uint8_t *pucNumOfChannel, + struct RF_CHANNEL_INFO *paucChannelList); + +void rlmDomainSendCmd(struct ADAPTER *prAdapter); + +void rlmDomainSendDomainInfoCmd(struct ADAPTER *prAdapter); + +void rlmDomainSendPassiveScanInfoCmd(struct ADAPTER + *prAdapter); + +uint32_t rlmDomainSupOperatingClassIeFill(uint8_t *pBuf); + +u_int8_t rlmDomainCheckChannelEntryValid(struct ADAPTER + *prAdapter, uint8_t ucCentralCh); + +uint8_t rlmDomainGetCenterChannel(enum ENUM_BAND eBand, + uint8_t ucPriChannel, + enum ENUM_CHNL_EXT eExtend); + +u_int8_t rlmDomainIsValidRfSetting(struct ADAPTER *prAdapter, + enum ENUM_BAND eBand, uint8_t ucPriChannel, + enum ENUM_CHNL_EXT eExtend, + enum ENUM_CHANNEL_WIDTH eChannelWidth, + uint8_t ucChannelS1, uint8_t ucChannelS2); + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +u_int8_t +rlmDomainCheckPowerLimitValid(struct ADAPTER *prAdapter, + struct COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION + rPowerLimitTableConfiguration, + uint8_t ucPwrLimitNum); + +void rlmDomainCheckCountryPowerLimitTable( + struct ADAPTER *prAdapter); + +uint16_t rlmDomainPwrLimitDefaultTableDecision( + struct ADAPTER *prAdapter, uint16_t u2CountryCode); + +void rlmDomainSendPwrLimitCmd(struct ADAPTER *prAdapter); +#endif + +#if (CFG_SUPPORT_SINGLE_SKU == 1) +extern struct ieee80211_supported_band mtk_band_2ghz; +extern struct ieee80211_supported_band mtk_band_5ghz; + +u_int8_t rlmDomainIsCtrlStateEqualTo(enum regd_state state); +u_int8_t rlmDomainIsUsingLocalRegDomainDataBase(void); +enum regd_state rlmDomainStateTransition(enum regd_state + request_state, struct regulatory_request *pRequest); +void rlmDomainSetCountryCode(char *alpha2, + u8 size_of_alpha2); +void rlmDomainSetDfsRegion(enum nl80211_dfs_regions + dfs_region); +enum nl80211_dfs_regions rlmDomainGetDfsRegion(void); +void rlmDomainResetCtrlInfo(u_int8_t force); +void rlmDomainAddActiveChannel(u8 band); +u8 rlmDomainGetActiveChannelCount(u8 band); +void rlmDomainParsingChannel(IN struct wiphy *pWiphy); +struct CMD_DOMAIN_CHANNEL *rlmDomainGetActiveChannels(void); +void rlmExtractChannelInfo(u32 max_ch_count, + struct CMD_DOMAIN_ACTIVE_CHANNEL_LIST *prBuff); +void regd_set_using_local_regdomain_db(void); +void rlmDomainSetDefaultCountryCode(void); +enum regd_state rlmDomainGetCtrlState(void); +bool rlmDomainIsSameCountryCode(char *alpha2, + u8 size_of_alpha2); +const struct ieee80211_regdomain +*rlmDomainSearchRegdomainFromLocalDataBase(char *alpha2); +struct GLUE_INFO *rlmDomainGetGlueInfo(void); +bool rlmDomainIsEfuseUsed(void); +uint8_t rlmDomainGetChannelBw(uint8_t channelNum); + +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) +extern const struct mtk_regdomain *g_prRegRuleTable[]; +#endif + +#endif + +const struct ieee80211_regdomain +*rlmDomainGetLocalDefaultRegd(void); +void rlmDomainSendInfoToFirmware(IN struct ADAPTER + *prAdapter); +uint32_t rlmDomainExtractSingleSkuInfoFromFirmware( + IN struct ADAPTER *prAdapter, IN uint8_t *pucEventBuf); +u_int8_t regd_is_single_sku_en(void); +u_int8_t rlmDomainIsLegalChannel(struct ADAPTER *prAdapter, + enum ENUM_BAND eBand, uint8_t ucChannel); +u_int8_t rlmDomainIsLegalDfsChannel(struct ADAPTER *prAdapter, + enum ENUM_BAND eBand, uint8_t ucChannel); +enum ENUM_CHNL_EXT rlmSelectSecondaryChannelType( + struct ADAPTER *prAdapter, enum ENUM_BAND band, + u8 primary_ch); +void rlmDomainOidSetCountry(IN struct ADAPTER *prAdapter, + char *country, u8 size_of_country); +u32 rlmDomainGetCountryCode(void); +u32 rlmDomainGetTempCountryCode(void); +void rlmDomainAssert(u_int8_t cond); + +#if CFG_SUPPORT_DYNAMIC_PWR_LIMIT +/* dynamic tx power control */ +void txPwrCtrlInit(struct ADAPTER *prAdapter); +void txPwrCtrlLoadConfig(struct ADAPTER *prAdapter); +void txPwrCtrlUninit(struct ADAPTER *prAdapter); +void txPwrCtrlShowList(struct ADAPTER *prAdapter, + uint8_t filterType, + char *message); +void txPwrCtrlDeleteElement(struct ADAPTER *prAdapter, + uint8_t *name, uint32_t index, + enum ENUM_TX_POWER_CTRL_LIST_TYPE eListType); +struct TX_PWR_CTRL_ELEMENT *txPwrCtrlStringToStruct(char *pcContent, + u_int8_t fgSkipHeader); +struct TX_PWR_CTRL_ELEMENT *txPwrCtrlFindElement( + struct ADAPTER *prAdapter, + uint8_t *name, + uint32_t index, + u_int8_t fgCheckIsApplied, + enum ENUM_TX_POWER_CTRL_LIST_TYPE eListType); +void txPwrCtrlAddElement(struct ADAPTER *prAdapter, + struct TX_PWR_CTRL_ELEMENT *prElement); +#endif +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _RLM_DOMAIN_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rlm_obss.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rlm_obss.h new file mode 100644 index 0000000000000..40f60b92fd327 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rlm_obss.h @@ -0,0 +1,148 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/ + * include/mgmt/rlm_obss.h#1 + */ + +/*! \file "rlm_obss.h" + * \brief + */ + + +#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 */ +enum ENUM_SYS_PCO_PHASE { + SYS_PCO_PHASE_DISABLED = 0, + SYS_PCO_PHASE_20M, + SYS_PCO_PHASE_40M +}; + +/******************************************************************************* + * P U B 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(struct ADAPTER *prAdapter); + +void rlmObssScanDone(struct ADAPTER *prAdapter, + struct MSG_HDR *prMsgHdr); + +void rlmObssTriggerScan(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _RLM_OBSS_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rlm_protection.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rlm_protection.h new file mode 100644 index 0000000000000..ed542da978e76 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rlm_protection.h @@ -0,0 +1,142 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/ + * include/mgmt/rlm_protection.h#1 + */ + +/*! \file "rlm_protection.h" + * \brief + */ + +#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 + ******************************************************************************* + */ +enum ENUM_SYS_PROTECT_MODE { + 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 +}; + +/* This definition follows HT Protection field of HT Operation IE */ +enum ENUM_HT_PROTECT_MODE { + HT_PROTECT_MODE_NONE = 0, + HT_PROTECT_MODE_NON_MEMBER, + HT_PROTECT_MODE_20M, + HT_PROTECT_MODE_NON_HT, + + HT_PROTECT_MODE_NUM +}; + +enum ENUM_GF_MODE { + GF_MODE_NORMAL = 0, + GF_MODE_PROTECT, + GF_MODE_DISALLOWED, + + GF_MODE_NUM +}; + +enum ENUM_RIFS_MODE { + RIFS_MODE_NORMAL = 0, + RIFS_MODE_DISALLOWED, + + RIFS_MODE_NUM +}; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _RLM_PROTECTION_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rlm_txpwr_init.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rlm_txpwr_init.h new file mode 100644 index 0000000000000..81586148f7ca4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rlm_txpwr_init.h @@ -0,0 +1,1609 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/ + * include/mgmt/rlm_txpwr_init.h#1 + */ + +/*! \file "rlm_txpwr_init.h" + * \brief + */ + +#ifndef _RLM_TXPWR_INIT_H +#define _RLM_TXPWR_INIT_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +/*Support Tx Power Range : 63~ -64 (unit : 0.5dBm)*/ + +#define PWR_LIMIT_2G4_IN_MW_MHZ BIT(0) +#define PWR_LIMIT_UNII1_IN_MW_MHZ BIT(1) +#define PWR_LIMIT_UNII2A_IN_MW_MHZ BIT(2) +#define PWR_LIMIT_UNII2C_IN_MW_MHZ BIT(3) +#define PWR_LIMIT_UNII3_IN_MW_MHZ BIT(4) + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY +/*Set to MAX_TX_PWR = 63dBm if larger than it*/ +struct COUNTRY_POWER_LIMIT_TABLE_DEFAULT + g_rRlmPowerLimitDefault[] = { + + { {'A', 'R'} + , {60, 34, 48, 48, 60} + , 0 + } + , + { {'A', 'U'} + , {63, 46, 46, 60, 63} + , 0 + } + , + { {'N', 'Z'} + , {63, 46, 46, 60, 63} + , 0 + } + , + { {'A', 'T'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'B', 'E'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'B', 'R'} + , {63, 46, 46, 60, 63} + , 0 + } + , + { {'B', 'G'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'C', 'A'} + , {60, 46, 48, 48, 60} + , 0 + } + , + { {'C', 'L'} + , {43, 43, 43, 63, 43} + , 0 + } + , + { {'C', 'N'} + , {40, 46, 46, 63, 63} + , 0 + } + , + { {'H', 'R'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'C', 'Z'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'D', 'K'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'D', 'M'} + , {60, 34, 46, 46, 60} + , 0 + } + , + { {'E', 'C'} + , {60, 34, 48, 48, 60} + , 0 + } + , + { {'E', 'G'} + , {40, 46, 46, 63, 46} + , 0 + } + , + { {'S', 'V'} + , {60, 34, 46, 46, 60} + , 0 + } + , + { {'F', 'I'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'F', 'R'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'G', 'R'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'H', 'N'} + , {60, 60, 48, 48, 60} + , 0 + } + , + { {'H', 'K'} + , {63, 46, 46, 60, 63} + , 0 + } + , + { {'H', 'U'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'I', 'S'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'I', 'N'} + , {63, 46, 46, 63, 46} + , 0 + } + , + { {'I', 'D'} + , {46, 63, 63, 63, 46} + , 0 + } + , + { {'I', 'E'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'I', 'L'} + , {40, 46, 46, 63, 63} + , 0 + } + , + { {'I', 'T'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'J', 'P'} + , {46, 46, 46, 46, 63} + , 0 + } + , + { {'K', 'R'} + , {46, 34, 46, 46, 46} + , 0 + } + , + { {'L', 'U'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'M', 'Y'} + , {54, 60, 60, 63, 60} + , 0 + } + , + { {'M', 'X'} + , {60, 46, 48, 63, 60} + , 0 + } + , + { {'N', 'L'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'N', 'O'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'O', 'M'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'P', 'K'} + , {40, 63, 63, 63, 40} + , 0 + } + , + { {'P', 'Y'} + , {60, 46, 46, 48, 60} + , 0 + } + , + { {'P', 'E'} + , {54, 46, 48, 42, 48} + , 0 + } + , + { {'P', 'H'} + , {48, 48, 48, 48, 48} + , 0 + } + , + { {'P', 'L'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'P', 'T'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'Q', 'A'} + , {40, 63, 63, 63, 40} + , 0 + } + , + { {'R', 'O'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'R', 'U'} + , {48, 40, 40, 60, 60} + , 0 + } + , + { {'S', 'A'} + , {40, 46, 46, 46, 46} + , 0 + } + , + { {'S', 'G'} + , {46, 40, 40, 60, 60} + , 0 + } + , + { {'S', 'K'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'S', 'I'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'Z', 'A'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'E', 'S'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'S', 'E'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'C', 'H'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'T', 'W'} + , {60, 48, 48, 48, 60} + , 0 + } + , + { {'T', 'H'} + , {40, 46, 46, 60, 60} + , 0 + } + , + { {'A', 'E'} + , {40, 46, 46, 60, 60} + , 0 + } + , + { {'G', 'B'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'U', 'Y'} + , {60, 34, 46, 46, 60} + , 0 + } + , + { {'U', 'S'} + , {60, 48, 48, 48, 60} + , 0 + } + , + { {'V', 'E'} + , {60, 46, 46, 63, 46} + , 0 + } + , + { {'V', 'N'} + , {40, 46, 46, 60, 34} + , 0 + } + , + { {'A', 'O'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'B', 'Z'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'B', 'J'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'B', 'T'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'B', 'O'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'B', 'I'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'C', 'M'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'C', 'F'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'T', 'D'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'K', 'M'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'C', 'D'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'C', 'G'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'C', 'I'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'D', 'J'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'G', 'Q'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'E', 'R'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'F', 'J'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'G', 'A'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'G', 'M'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'G', 'N'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'G', 'W'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'R', 'K'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'K', 'G'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'L', 'Y'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'M', 'G'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'M', 'L'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'N', 'R'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'N', 'C'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'S', 'T'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'S', 'C'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'S', 'L'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'S', 'B'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'S', 'O'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'S', 'R'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'S', 'Z'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'T', 'J'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'T', 'G'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'T', 'O'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'T', 'M'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'T', 'V'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'V', 'U'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'Y', 'E'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'A', 'S'} + , {60, 34, 46, 48, 60} + , 0 + } + , + { {'A', 'I'} + , {60, 34, 48, 60, 60} + , 0 + } + , + { {'B', 'M'} + , {60, 34, 48, 48, 60} + , 0 + } + , + { {'K', 'Y'} + , {60, 34, 48, 60, 60} + , 0 + } + , + { {'G', 'U'} + , {60, 34, 48, 48, 60} + , 0 + } + , + { {'F', 'M'} + , {60, 34, 48, 48, 60} + , 0 + } + , + { {'P', 'R'} + , {60, 34, 46, 48, 60} + , 0 + } + , + { {'V', 'I'} + , {60, 34, 48, 48, 60} + , 0 + } + , + { {'A', 'Z'} + , {40, 34, 48, 60, 60} + , 0 + } + , + { {'B', 'W'} + , {40, 46, 46, 60, 60} + , 0 + } + , + { {'K', 'H'} + , {40, 46, 46, 48, 60} + , 0 + } + , + { {'C', 'X'} + , {63, 46, 46, 60, 63} + , 0 + } + , + { {'C', 'O'} + , {60, 34, 48, 48, 60} + , 0 + } + , + { {'C', 'R'} + , {60, 34, 48, 48, 60} + , 0 + } + , + { {'G', 'D'} + , {40, 46, 46, 60, 60} + , 0 + } + , + { {'G', 'T'} + , {40, 34, 48, 48, 60} + , 0 + } + , + { {'K', 'I'} + , {63, 46, 46, 60, 63} + , 0 + } + , + { {'L', 'B'} + , {40, 46, 46, 46, 46} + , 0 + } + , + { {'L', 'R'} + , {60, 46, 60, 63, 63} + , 0 + } + , + { {'M', 'N'} + , {46, 32, 46, 46, 58} + , 0 + } + , + { {'A', 'N'} + , {60, 34, 48, 48, 60} + , 0 + } + , + { {'N', 'I'} + , {60, 34, 48, 48, 60} + , 0 + } + , + { {'P', 'W'} + , {60, 60, 60, 60, 60} + , 0 + } + , + { {'W', 'S'} + , {40, 40, 40, 40, 60} + , 0 + } + , + { {'L', 'K'} + , {46, 46, 46, 46, 46} + , 0 + } + , + { {'T', 'T'} + , {60, 46, 46, 60, 60} + , 0 + } + , + { {'A', 'W'} + , {60, 46, 60, 60, 63} + , 0 + } + , + { {'L', 'A'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'U', 'G'} + , {40, 46, 46, 48, 60} + , 0 + } + , + { {'M', 'M'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'A', 'L'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'D', 'Z'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'A', 'D'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'B', 'Y'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'B', 'A'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'V', 'G'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'C', 'V'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'C', 'Y'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'E', 'E'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'E', 'T'} + , {40, 40, 40, 40, 28} + , 0 + } + , + { {'G', 'F'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'P', 'F'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'T', 'F'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'G', 'E'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'D', 'E'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'G', 'H'} + , {40, 34, 48, 60, 28} + , 0 + } + , + { {'G', 'P'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'I', 'Q'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'K', 'E'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'L', 'V'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'L', 'S'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'L', 'I'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'L', 'T'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'M', 'K'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'M', 'T'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'M', 'Q'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'M', 'R'} + , {40, 46, 46, 46, 28} + , 0 + } + , + { {'M', 'U'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'Y', 'T'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'M', 'D'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'M', 'C'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'M', 'E'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'M', 'S'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'R', 'E'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'M', 'F'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'S', 'M'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'S', 'N'} + , {40, 40, 40, 60, 28} + , 0 + } + , + { {'R', 'S'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'T', 'R'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'T', 'C'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'V', 'A'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'A', 'M'} + , {40, 40, 40, 63, 63} + , 0 + } + , + { {'K', 'W'} + , {40, 46, 46, 63, 63} + , 0 + } + , + { {'M', 'A'} + , {40, 46, 46, 63, 63} + , 0 + } + , + { {'N', 'E'} + , {40, 46, 46, 63, 63} + , 0 + } + , + { {'T', 'N'} + , {40, 46, 46, 63, 63} + , 0 + } + , + { {'N', 'P'} + , {60, 46, 46, 63, 60} + , 0 + } + , + { {'A', 'F'} + , {40, 46, 63, 63, 63} + , 0 + } + , + { {'A', 'G'} + , {40, 46, 48, 63, 54} + , 0 + } + , + { {'B', 'S'} + , {63, 46, 60, 63, 63} + , 0 + } + , + { {'B', 'H'} + , {40, 46, 46, 63, 63} + , 0 + } + , + { {'B', 'B'} + , {40, 46, 48, 63, 54} + , 0 + } + , + { {'B', 'N'} + , {46, 46, 46, 63, 60} + , 0 + } + , + { {'M', 'V'} + , {40, 46, 46, 63, 40} + , 0 + } + , + { {'P', 'A'} + , {60, 34, 48, 63, 60} + , 0 + } + , + { {'Z', 'M'} + , {60, 46, 46, 63, 60} + , 0 + } + , + { {'J', 'O'} + , {40, 46, 63, 63, 46} + , 0 + } + , + { {'P', 'G'} + , {40, 46, 63, 63, 60} + , 0 + } + , + { {'B', 'F'} + , {40, 63, 63, 63, 60} + , 0 + } + , + { {'G', 'Y'} + , {60, 63, 63, 63, 60} + , 0 + } + , + { {'H', 'T'} + , {40, 63, 63, 63, 60} + , 0 + } + , + { {'J', 'M'} + , {54, 63, 63, 63, 57} + , 0 + } + , + { {'M', 'O'} + , {40, 63, 63, 63, 40} + , 0 + } + , + { {'M', 'W'} + , {60, 63, 63, 63, 60} + , 0 + } + , + { {'R', 'W'} + , {40, 63, 63, 63, 60} + , 0 + } + , + { {'K', 'N'} + , {40, 63, 63, 63, 60} + , 0 + } + , + { {'T', 'Z'} + , {40, 63, 63, 63, 40} + , 0 + } + , + { {'N', 'G'} + , {40, 63, 46, 63, 60} + , 0 + } + , + { {'B', 'D'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'D', 'O'} + , {63, 46, 46, 60, 63} + , 0 + } + , + { {'F', 'K'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'K', 'Z'} + , {40, 34, 48, 60, 60} + , 0 + } + , + { {'M', 'Z'} + , {40, 34, 46, 48, 60} + , 0 + } + , + { {'N', 'A'} + , {40, 34, 46, 48, 60} + , 0 + } + , + { {'L', 'C'} + , {40, 34, 48, 48, 60} + , 0 + } + , + { {'V', 'C'} + , {40, 34, 46, 48, 60} + , 0 + } + , + { {'U', 'A'} + , {40, 46, 46, 46, 48} + , 0 + } + , + { {'U', 'Z'} + , {40, 48, 48, 48, 60} + , 0 + } + , + { {'Z', 'W'} + , {40, 34, 46, 48, 60} + , 0 + } + , + { {'M', 'P'} + , {60, 34, 46, 48, 60} + , 0 + } + , + { {'C', 'K'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'C', 'U'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'T', 'L'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'F', 'O'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'G', 'I'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'I', 'R'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'I', 'M'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'J', 'E'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'K', 'P'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'M', 'H'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'N', 'U'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'N', 'F'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'P', 'S'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'P', 'N'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'P', 'M'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'S', 'S'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'S', 'D'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'S', 'Y'} + , {63, 63, 63, 63, 63} + , 0 + } + , +#if 1 /* Temp define as 6630 */ + { {'E', 'H'} + , {40, 46, 46, 63, 63} + , 0 + } + , + { {'G', 'G'} + , {63, 63, 63, 63, 63} + , 0 + } + , +#endif + + /*Default*/ + { {0, 0} + , {63, 63, 63, 63, 63} + , 0 + } +}; + +struct COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION_HE + g_rRlmPowerLimitConfigurationHE[] = { + /*Default*/ + { {0, 0} + , 36, + {64, 64, 64, /* RU26 L,H,U */ + 64, 64, 64, /* RU52 L,H,U*/ + 64, 64, 64, /* RU106 L,H,U*/ + 64, 64, 64, /* RU242 L,H,U*/ + 64, 64, 64, /* RU484 L,H,U*/ + 64, 64, 64} /* RU996 L,H,U*/ + } +}; + +struct COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION + g_rRlmPowerLimitConfiguration[] = { + + { {'A', 'I'} + , 144, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'A', 'Z'} + , 144, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'B', 'W'} + , 144, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'G', 'D'} + , 144, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'L', 'B'} + , 144, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'L', 'R'} + , 144, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'W', 'S'} + , 165, {40, 40, 40, 40, 40, 40, 40, 40, 40} + } + , + { {'U', 'S'} + , 1, {39, 34, 32, 60, 60, 60, 60, 60, 60} + } + , + { {'U', 'S'} + , 6, {60, 60, 60, 60, 60, 60, 60, 60, 60} + } + , + { {'U', 'S'} + , 11, {39, 33, 32, 60, 60, 60, 60, 60, 60} + } + , + { {'U', 'S'} + , 3, {60, 60, 60, 31, 30, 60, 60, 60, 60} + } + , + { {'U', 'S'} + , 9, {60, 60, 60, 31, 30, 60, 60, 60, 60} + } + , + { {'U', 'S'} + , 36, {48, 36, 36, 48, 48, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 40, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 48, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 52, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 60, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 64, {48, 36, 36, 48, 48, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 100, {48, 37, 37, 48, 48, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 116, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 140, {48, 42, 42, 48, 48, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 149, {60, 41, 41, 60, 60, 60, 60, 60, 60} + } + , + { {'U', 'S'} + , 157, {60, 60, 60, 60, 60, 60, 60, 60, 60} + } + , + { {'U', 'S'} + , 165, {60, 42, 42, 60, 60, 60, 60, 60, 60} + } + , + { {'U', 'S'} + , 38, {48, 48, 48, 27, 27, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 46, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 54, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 62, {48, 48, 48, 28, 28, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 102, {48, 48, 48, 29, 29, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 110, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 134, {48, 48, 48, 41, 41, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 151, {60, 60, 60, 36, 36, 60, 60, 60, 60} + } + , + { {'U', 'S'} + , 159, {60, 60, 60, 60, 60, 60, 60, 60, 60} + } + , + { {'U', 'S'} + , 42, {48, 48, 48, 48, 48, 24, 24, 48, 48} + } + , + { {'U', 'S'} + , 58, {48, 48, 48, 48, 48, 26, 26, 48, 48} + } + , + { {'U', 'S'} + , 106, {48, 48, 48, 48, 48, 25, 25, 48, 48} + } + , + { {'U', 'S'} + , 122, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 155, {60, 60, 60, 60, 60, 36, 36, 60, 60} + } + , + { {'U', 'S'} + , 50, {48, 48, 48, 48, 48, 48, 48, 24, 24} + } + , + { {'U', 'S'} + , 114, {48, 48, 48, 48, 48, 48, 48, 24, 24} + } + , + { {'T', 'W'} + , 1, {39, 34, 32, 60, 60, 60, 60, 60, 60} + } + , + { {'T', 'W'} + , 6, {60, 60, 60, 60, 60, 60, 60, 60, 60} + } + , + { {'T', 'W'} + , 11, {39, 33, 32, 60, 60, 60, 60, 60, 60} + } + , + { {'T', 'W'} + , 3, {60, 60, 60, 31, 30, 60, 60, 60, 60} + } + , + { {'T', 'W'} + , 9, {60, 60, 60, 31, 30, 60, 60, 60, 60} + } + , + { {'T', 'W'} + , 36, {48, 36, 36, 48, 48, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 40, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 48, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 52, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 60, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 64, {48, 36, 36, 48, 48, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 100, {48, 37, 37, 48, 48, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 116, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 140, {48, 42, 42, 48, 48, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 149, {60, 41, 41, 60, 60, 60, 60, 60, 60} + } + , + { {'T', 'W'} + , 157, {60, 60, 60, 60, 60, 60, 60, 60, 60} + } + , + { {'T', 'W'} + , 165, {60, 42, 42, 60, 60, 60, 60, 60, 60} + } + , + { {'T', 'W'} + , 38, {48, 48, 48, 27, 27, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 46, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 54, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 62, {48, 48, 48, 28, 28, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 102, {48, 48, 48, 29, 29, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 110, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 134, {48, 48, 48, 41, 41, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 151, {60, 60, 60, 36, 36, 60, 60, 60, 60} + } + , + { {'T', 'W'} + , 159, {60, 60, 60, 60, 60, 60, 60, 60, 60} + } + , + { {'T', 'W'} + , 42, {48, 48, 48, 48, 48, 24, 24, 48, 48} + } + , + { {'T', 'W'} + , 58, {48, 48, 48, 48, 48, 26, 26, 48, 48} + } + , + { {'T', 'W'} + , 106, {48, 48, 48, 48, 48, 25, 25, 48, 48} + } + , + { {'T', 'W'} + , 122, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 155, {60, 60, 60, 60, 60, 36, 36, 60, 60} + } + , + { {'T', 'W'} + , 50, {48, 48, 48, 48, 48, 48, 48, 24, 24} + } + , + { {'T', 'W'} + , 114, {48, 48, 48, 48, 48, 48, 48, 24, 24} + } + , + + /*Default*/ + { {0, 0} + , 165, {63, 63, 63, 63, 63, 63, 63, 63, 63} + } +}; + +#endif + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +#endif /* _RLM_TXPWR_INIT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/roaming_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/roaming_fsm.h new file mode 100644 index 0000000000000..921f64d91427c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/roaming_fsm.h @@ -0,0 +1,232 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: + */ + +/*! \file "roaming_fsm.h" + * \brief This file defines the FSM for Roaming MODULE. + * + * This file defines the FSM for Roaming MODULE. + */ + + +#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_DISCOVER_TIMEOUT_SEC 10 /* Seconds. */ +#define ROAMING_INACTIVE_TIMEOUT_SEC 10 /* Seconds. */ +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP +#define ROAMING_ONE_AP_SKIP_TIMES 3 +#endif + +/* #define ROAMING_NO_SWING_RCPI_STEP 5 //rcpi */ +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +enum ENUM_ROAMING_FAIL_REASON { + ROAMING_FAIL_REASON_CONNLIMIT = 0, + ROAMING_FAIL_REASON_NOCANDIDATE, + ROAMING_FAIL_REASON_NUM +}; + +/* events of roaming between driver and firmware */ +enum ENUM_ROAMING_EVENT { + ROAMING_EVENT_START = 0, + ROAMING_EVENT_DISCOVERY, + ROAMING_EVENT_ROAM, + ROAMING_EVENT_FAIL, + ROAMING_EVENT_ABORT, + ROAMING_EVENT_THRESHOLD_UPDATE, + ROAMING_EVENT_NUM +}; + +enum ENUM_ROAMING_REASON { + ROAMING_REASON_POOR_RCPI = 0, + ROAMING_REASON_TX_ERR, /*Lowest rate, high PER*/ + ROAMING_REASON_RETRY, + ROAMING_REASON_IDLE, + ROAMING_REASON_BEACON_TIMEOUT, + ROAMING_REASON_INACTIVE, + ROAMING_REASON_SAA_FAIL, + ROAMING_REASON_NUM +}; + +struct CMD_ROAMING_TRANSIT { + uint16_t u2Event; + uint16_t u2Data; + uint16_t u2RcpiLowThreshold; + uint8_t ucIsSupport11B; + uint8_t ucBssidx; + enum ENUM_ROAMING_REASON eReason; + uint32_t u4RoamingTriggerTime; /*sec in mcu*/ + uint16_t u2RcpiHighThreshold; + uint8_t aucReserved2[6]; +}; + + +struct CMD_ROAMING_CTRL { + uint8_t fgEnable; + uint8_t ucRcpiAdjustStep; + uint16_t u2RcpiLowThr; + uint8_t ucRoamingRetryLimit; + uint8_t ucRoamingStableTimeout; + uint8_t aucReserved[2]; +}; + +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP +struct CMD_ROAMING_SKIP_ONE_AP { + uint8_t fgIsRoamingSkipOneAP; + uint8_t aucReserved[3]; + uint8_t aucReserved2[8]; +}; +#endif + +enum ENUM_ROAMING_STATE { + ROAMING_STATE_IDLE = 0, + ROAMING_STATE_DECISION, + ROAMING_STATE_DISCOVERY, + ROAMING_STATE_REQ_CAND_LIST, + ROAMING_STATE_ROAM, + ROAMING_STATE_NUM +}; + +struct ROAMING_INFO { + u_int8_t fgIsEnableRoaming; + + enum ENUM_ROAMING_STATE eCurrentState; + + OS_SYSTIME rRoamingDiscoveryUpdateTime; +#if CFG_SUPPORT_DRIVER_ROAMING + OS_SYSTIME rRoamingLastDecisionTime; +#endif + + u_int8_t fgDrvRoamingAllow; + struct TIMER rWaitCandidateTimer; + enum ENUM_ROAMING_REASON eReason; + uint8_t ucPER; + uint8_t ucRcpi; + uint8_t ucThreshold; +}; + +/******************************************************************************* + * P U B 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 roamingFsmInit(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +void roamingFsmUninit(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +void roamingFsmSendCmd(IN struct ADAPTER *prAdapter, + IN struct CMD_ROAMING_TRANSIT *prTransit); + +void roamingFsmScanResultsUpdate(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +void roamingFsmSteps(IN struct ADAPTER *prAdapter, + IN enum ENUM_ROAMING_STATE eNextState, + IN uint8_t ucBssIndex); + +void roamingFsmRunEventStart(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +void roamingFsmRunEventDiscovery(IN struct ADAPTER *prAdapter, + IN struct CMD_ROAMING_TRANSIT *prTransit); + +void roamingFsmRunEventRoam(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +void roamingFsmRunEventFail(IN struct ADAPTER *prAdapter, + IN uint32_t u4Reason, + IN uint8_t ucBssIndex); + +void roamingFsmRunEventAbort(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +uint32_t roamingFsmProcessEvent(IN struct ADAPTER *prAdapter, + IN struct CMD_ROAMING_TRANSIT *prTransit); + +#endif /* _ROAMING_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rrm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rrm.h new file mode 100644 index 0000000000000..f30e7d7ba436e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rrm.h @@ -0,0 +1,201 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#ifndef _RRM_H +#define _RRM_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 + ******************************************************************************* + */ + +/* Radio Measurement Request Mode definition */ +#define RM_REQ_MODE_PARALLEL_BIT BIT(0) +#define RM_REQ_MODE_ENABLE_BIT BIT(1) +#define RM_REQ_MODE_REQUEST_BIT BIT(2) +#define RM_REQ_MODE_REPORT_BIT BIT(3) +#define RM_REQ_MODE_DURATION_MANDATORY_BIT BIT(4) +#define RM_REP_MODE_LATE BIT(0) +#define RM_REP_MODE_INCAPABLE BIT(1) +#define RM_REP_MODE_REFUSED BIT(2) + +/* Radio Measurement Report Frame Max Length */ +#define RM_REPORT_FRAME_MAX_LENGTH (1600 - NIC_TX_DESC_AND_PADDING_LENGTH) +/* beacon request mode definition */ +#define RM_BCN_REQ_PASSIVE_MODE 0 +#define RM_BCN_REQ_ACTIVE_MODE 1 +#define RM_BCN_REQ_TABLE_MODE 2 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +enum BCN_RM_STATE { + RM_NO_REQUEST, + RM_ON_GOING, + RM_WAITING, /*waiting normal scan done */ +}; + +enum RM_REQ_PRIORITY { + RM_PRI_BROADCAST, + RM_PRI_MULTICAST, + RM_PRI_UNICAST +}; + +struct NORMAL_SCAN_PARAMS { + struct PARAM_SCAN_REQUEST_ADV rScanRequest; + uint8_t aucScanIEBuf[MAX_IE_LENGTH]; + u_int8_t fgExist; +}; + +/* Beacon RM related parameters */ +struct BCN_RM_PARAMS { + enum BCN_RM_STATE eState; + struct NORMAL_SCAN_PARAMS rNormalScan; + + uint8_t token; + uint8_t lastIndication; + u8 ssid[ELEM_MAX_LEN_SSID]; + size_t ssidLen; + enum BEACON_REPORT_DETAIL reportDetail; + uint8_t *reportIeIds; + uint8_t reportIeIdsLen; + uint8_t *apChannels; + uint8_t apChannelsLen; +}; + +struct RM_BEACON_REPORT_PARAMS { + uint8_t ucChannel; + uint8_t ucRCPI; + uint8_t ucRSNI; + uint8_t ucAntennaID; + uint8_t ucFrameInfo; + uint8_t aucBcnFixedField[12]; +}; + +struct RM_MEASURE_REPORT_ENTRY { + struct LINK_ENTRY rLinkEntry; + uint8_t aucBSSID[MAC_ADDR_LEN]; + uint16_t u2MeasReportLen; + uint8_t *pucMeasReport; +}; + +struct RADIO_MEASUREMENT_REQ_PARAMS { + /* Remain Request Elements Length, started at prMeasElem. if it is 0, + * means RM is done + */ + uint16_t u2RemainReqLen; + uint16_t u2ReqIeBufLen; + struct IE_MEASUREMENT_REQ *prCurrMeasElem; + OS_SYSTIME rStartTime; + uint16_t u2Repetitions; + uint8_t *pucReqIeBuf; + enum RM_REQ_PRIORITY ePriority; + u_int8_t fgRmIsOngoing; + u_int8_t fgInitialLoop; + OS_SYSTIME rScanStartTime; + + struct BCN_RM_PARAMS rBcnRmParam; +}; + +struct RADIO_MEASUREMENT_REPORT_PARAMS { + /* the total length of Measurement Report elements */ + uint16_t u2ReportFrameLen; + uint8_t *pucReportFrameBuff; + /* Variables to collect report */ + struct LINK rReportLink; /* a link to save received report entry */ +}; + +/******************************************************************************* + * P U B 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 rrmParamInit(struct ADAPTER *prAdapter, uint8_t ucBssIndex); + +void rrmParamUninit(struct ADAPTER *prAdapter, uint8_t ucBssIndex); + +void rrmProcessNeighborReportResonse(struct ADAPTER *prAdapter, + struct WLAN_ACTION_FRAME *prAction, + struct SW_RFB *prSwRfb); + +void rrmTxNeighborReportRequest(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + struct SUB_ELEMENT_LIST *prSubIEs); + +void rrmGenerateRRMEnabledCapIE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +void rrmProcessRadioMeasurementRequest(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); + +void rrmProcessLinkMeasurementRequest(struct ADAPTER *prAdapter, + struct WLAN_ACTION_FRAME *prAction); + +void rrmFillRrmCapa(uint8_t *pucCapa); + +void rrmStartNextMeasurement(struct ADAPTER *prAdapter, u_int8_t fgNewStarted, + uint8_t ucBssIndex); + + +u_int8_t rrmFillScanMsg(struct ADAPTER *prAdapter, + struct MSG_SCN_SCAN_REQ_V2 *prMsg); + +void rrmDoBeaconMeasurement(struct ADAPTER *prAdapter, unsigned long ulParam); + +void rrmTxNeighborReportRequest(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + struct SUB_ELEMENT_LIST *prSubIEs); + +void rrmTxRadioMeasurementReport(struct ADAPTER *prAdapter, + uint8_t ucBssIndex); + +void rrmFreeMeasurementResources(struct ADAPTER *prAdapter, + uint8_t ucBssIndex); + +enum RM_REQ_PRIORITY rrmGetRmRequestPriority(uint8_t *pucDestAddr); + +void rrmRunEventProcessNextRm(struct ADAPTER *prAdapter, + struct MSG_HDR *prMsgHdr); + +void rrmScheduleNextRm(struct ADAPTER *prAdapter, + uint8_t ucBssIndex); + +void rrmUpdateBssTimeTsf(struct ADAPTER *prAdapter, struct BSS_DESC *prBssDesc); + +void rrmCollectBeaconReport(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc, IN uint8_t ucBssIndex); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _RRM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rsn.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rsn.h new file mode 100644 index 0000000000000..3f28eacc79896 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/rsn.h @@ -0,0 +1,343 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: include/mgmt/rsn.h#1 + */ + +/*! \file rsn.h + * \brief The wpa/rsn related define, macro and structure are described here. + */ + +#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 RSN_CIPHER_SUITE_GROUP_NOT_USED 0x07AC0F00 +#define RSN_CIPHER_SUITE_GCMP 0x08AC0F00 +#define RSN_CIPHER_SUITE_GCMP_256 0x09AC0F00 +#define RSN_CIPHER_SUITE_CCMP_256 0x0AAC0F00 +#define RSN_CIPHER_SUITE_BIP_GMAC_128 0x0BAC0F00 +#define RSN_CIPHER_SUITE_BIP_GMAC_256 0x0CAC0F00 +#define RSN_CIPHER_SUITE_BIP_CMAC_256 0x0DAC0F00 + +#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 +#define RSN_AKM_SUITE_FT_802_1X 0x03AC0F00 +#define RSN_AKM_SUITE_FT_PSK 0x04AC0F00 +#if KERNEL_VERSION(4, 12, 0) > CFG80211_VERSION_CODE +#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03 +#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04 +#endif +/* Add AKM SUITE for OWE since kernel haven't defined it. */ +#define WLAN_AKM_SUITE_OWE 0x000FAC12 +#if CFG_SUPPORT_802_11W +#define RSN_AKM_SUITE_802_1X_SHA256 0x05AC0F00 +#define RSN_AKM_SUITE_PSK_SHA256 0x06AC0F00 +#endif + +#define RSN_AKM_SUITE_TDLS 0x07AC0F00 +#define RSN_AKM_SUITE_SAE 0x08AC0F00 +#define RSN_AKM_SUITE_FT_OVER_SAE 0x09AC0F00 +#define RSN_AKM_SUITE_8021X_SUITE_B 0x0BAC0F00 +#define RSN_AKM_SUITE_8021X_SUITE_B_192 0x0CAC0F00 +#define RSN_AKM_SUITE_FILS_SHA256 0x0EAC0F00 +#define RSN_AKM_SUITE_FILS_SHA384 0x0FAC0F00 +#define RSN_AKM_SUITE_FT_FILS_SHA256 0x10AC0F00 +#define RSN_AKM_SUITE_FT_FILS_SHA384 0x11AC0F00 +#define RSN_AKM_SUITE_OWE 0x12AC0F00 + +#define WPA_AKM_SUITE_NONE 0x00F25000 +#define WPA_AKM_SUITE_802_1X 0x01F25000 +#define WPA_AKM_SUITE_PSK 0x02F25000 + +#define WFA_AKM_SUITE_OSEN 0x019A6F50 +/* this define should be in ieee80211.h, but kernel didn't update it. + * so we define here temporary + */ +#define WLAN_AKM_SUITE_OSEN 0x506f9a01 +#define WLAN_CIPHER_SUITE_NO_GROUP_ADDR 0x000fac07 + +/* The RSN IE len for associate request */ +#define ELEM_ID_RSN_LEN_FIXED 20 + +/* The WPA IE len for associate request */ +#define ELEM_ID_WPA_LEN_FIXED 22 + +#define MASK_RSNIE_CAP_PREAUTH BIT(0) + +#define GET_SELECTOR_TYPE(x) ((uint8_t)(((x) >> 24) & 0x000000FF)) +#define SET_SELECTOR_TYPE(x, y) (x = (((x) & 0x00FFFFFF) | \ + (((uint32_t)(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 3 */ +#define CIPHER_FLAG_WEP104 0x00000010 /* BIT 4 */ +#define CIPHER_FLAG_WEP128 0x00000020 /* BIT 5 */ +#define CIPHER_FLAG_GCMP256 0x00000080 /* BIT 7 */ + +#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) ((struct RSN_INFO_ELEM *) fp) +#define WPA_IE(fp) ((struct WPA_INFO_ELEM *) fp) + +#define ELEM_MAX_LEN_ASSOC_RSP_WSC_IE (32 - ELEM_HDR_LEN) +#define ELEM_MAX_LEN_TIMEOUT_IE (5) + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +u_int8_t rsnParseRsnIE(IN struct ADAPTER *prAdapter, + IN struct RSN_INFO_ELEM *prInfoElem, + OUT struct RSN_INFO *prRsnInfo); + +u_int8_t rsnParseWpaIE(IN struct ADAPTER *prAdapter, + IN struct WPA_INFO_ELEM *prInfoElem, + OUT struct RSN_INFO *prWpaInfo); + +u_int8_t rsnSearchSupportedCipher(IN struct ADAPTER + *prAdapter, + IN uint32_t u4Cipher, OUT uint32_t *pu4Index, + IN uint8_t ucBssIndex); + +u_int8_t rsnIsSuitableBSS(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBss, + IN struct RSN_INFO *prBssRsnInfo, + IN uint8_t ucBssIndex); + +u_int8_t rsnSearchAKMSuite(IN struct ADAPTER *prAdapter, + IN uint32_t u4AkmSuite, OUT uint32_t *pu4Index, + IN uint8_t ucBssIndex); + +u_int8_t rsnPerformPolicySelection(IN struct ADAPTER + *prAdapter, + IN struct BSS_DESC *prBss, + IN uint8_t ucBssIndex); + +void rsnGenerateWpaNoneIE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +void rsnGenerateWPAIE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +void rsnGenerateRSNIE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +u_int8_t +rsnParseCheckForWFAInfoElem(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, OUT uint8_t *pucOuiType, + OUT uint16_t *pu2SubTypeVersion); + +#if CFG_SUPPORT_AAA +void rsnParserCheckForRSNCCMPPSK(struct ADAPTER *prAdapter, + struct RSN_INFO_ELEM *prIe, + struct STA_RECORD *prStaRec, + uint16_t *pu2StatusCode); +#endif + +void rsnTkipHandleMICFailure(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prSta, + IN u_int8_t fgErrorKeyType); + +struct PMKID_ENTRY *rsnSearchPmkidEntry(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBssid, + IN uint8_t ucBssIndex); + +void rsnCheckPmkidCache(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBss, + IN uint8_t ucBssIndex); + +void rsnGeneratePmkidIndication(IN struct ADAPTER *prAdapter, + IN struct PARAM_PMKID_CANDIDATE *prCandi, + IN uint8_t ucBssIndex); + +uint32_t rsnSetPmkid(IN struct ADAPTER *prAdapter, + IN struct PARAM_PMKID *prPmkid); + +uint32_t rsnDelPmkid(IN struct ADAPTER *prAdapter, + IN struct PARAM_PMKID *prPmkid); + +uint32_t rsnFlushPmkid(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +#if CFG_SUPPORT_802_11W +uint32_t rsnCheckBipKeyInstalled(IN struct ADAPTER + *prAdapter, IN struct STA_RECORD *prStaRec); + +uint8_t rsnCheckSaQueryTimeout( + IN struct ADAPTER *prAdapter, IN uint8_t ucBssIdx); + +void rsnStartSaQueryTimer(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr); + +void rsnStartSaQuery(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx); + +void rsnStopSaQuery(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx); + +void rsnSaQueryRequest(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +void rsnSaQueryAction(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +uint16_t rsnPmfCapableValidation(IN struct ADAPTER + *prAdapter, IN struct BSS_INFO *prBssInfo, + IN struct STA_RECORD *prStaRec); + +void rsnPmfGenerateTimeoutIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rsnApStartSaQuery(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +void rsnApSaQueryAction(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +#endif /* CFG_SUPPORT_802_11W */ + +#if CFG_SUPPORT_AAA +void rsnGenerateWSCIEForAssocRsp(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); +#endif + +u_int8_t rsnParseOsenIE(struct ADAPTER *prAdapter, + struct IE_WFA_OSEN *prInfoElem, + struct RSN_INFO *prOsenInfo); + +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE +u_int8_t rsnCheckSecurityModeChanged(struct ADAPTER + *prAdapter, struct BSS_INFO *prBssInfo, + struct BSS_DESC *prBssDesc); +#endif + +uint32_t rsnCalculateFTIELen(struct ADAPTER *prAdapter, uint8_t ucBssIdx, + struct STA_RECORD *prStaRec); + +void rsnGenerateFTIE(IN struct ADAPTER *prAdapter, + IN OUT struct MSDU_INFO *prMsduInfo); + +u_int8_t rsnIsFtOverTheAir(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, IN uint8_t ucStaRecIdx); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _RSN_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/scan.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/scan.h new file mode 100644 index 0000000000000..fd3d77b8fffde --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/scan.h @@ -0,0 +1,940 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: @(#) + */ + +/*! \file "scan.h" + * \brief + * + */ + + +#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(struct BSS_DESC))) + +/* Remove SCAN result except the connected one. */ +#define SCN_RM_POLICY_EXCLUDE_CONNECTED BIT(0) + +/* Remove the timeout one */ +#define SCN_RM_POLICY_TIMEOUT BIT(1) + +/* Remove the oldest one with hidden ssid */ +#define SCN_RM_POLICY_OLDEST_HIDDEN BIT(2) + +/* 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_SMART_WEAKEST BIT(3) + +/* Remove entire SCAN result */ +#define SCN_RM_POLICY_ENTIRE BIT(4) + +/* Remove SCAN result except the specific one. */ +#define SCN_RM_POLICY_EXCLUDE_SPECIFIC_SSID BIT(5) + +/* This is used by POLICY SMART WEAKEST, If exceed this value, remove weakest + * struct BSS_DESC with same SSID first in large network. + */ +#define SCN_BSS_DESC_SAME_SSID_THRESHOLD 20 + +#define SCN_BSS_DESC_STALE_SEC 20 /* Scan Request Timeout */ + +/* For WFD scan need about 15s. */ +#define SCN_BSS_DESC_STALE_SEC_WFD 30 + +#define SCN_PROBE_DELAY_MSEC 0 + +#define SCN_ADHOC_BSS_DESC_TIMEOUT_SEC 5 /* Second. */ +#if CFG_ENABLE_WIFI_DIRECT +#if CFG_SUPPORT_WFD + /* Second. For WFD scan timeout. */ +#define SCN_ADHOC_BSS_DESC_TIMEOUT_SEC_WFD 20 +#endif +#endif + +#define SCAN_DONE_DIFFERENCE 3 + +/* Full2Partial */ +/* Define a full scan as scan channel number larger than this number */ +#define SCAN_FULL2PARTIAL_CHANNEL_NUM (20) +#define SCAN_CHANNEL_BITMAP_ARRAY_LEN (8) +#define BITS_OF_UINT (32) +#define BITS_OF_BYTE (8) + +/* dwell time setting, should align FW setting */ +#define SCAN_CHANNEL_DWELL_TIME_MIN_MSEC (42) + +/* dwell time setting, reduce APP trigger scan dwell time to 20 */ +#define SCAN_CHANNEL_MIN_DWELL_TIME_MSEC_APP (20) +#define SCAN_CHANNEL_DWELL_TIME_MSEC_APP (40) + +/*----------------------------------------------------------------------------*/ +/* 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) /* two probe req will be sent, wildcard and specified */ +#define SCAN_REQ_SSID_SPECIFIED_ONLY \ + BIT(3) /* only a specified ssid probe request will be sent */ + +/*----------------------------------------------------------------------------*/ +/* Support Multiple SSID SCAN */ +/*----------------------------------------------------------------------------*/ +#define SCN_SSID_MAX_NUM CFG_SCAN_SSID_MAX_NUM +#define SCN_SSID_MATCH_MAX_NUM CFG_SCAN_SSID_MATCH_MAX_NUM + +#if CFG_SUPPORT_AGPS_ASSIST +#define SCN_AGPS_AP_LIST_MAX_NUM 32 +#endif + +#define SCN_BSS_JOIN_FAIL_CNT_RESET_SEC 15 +#define SCN_BSS_JOIN_FAIL_RESET_STEP 2 + +#if CFG_SUPPORT_BATCH_SCAN +/*----------------------------------------------------------------------------*/ +/* SCAN_BATCH_REQ */ +/*----------------------------------------------------------------------------*/ +#define SCAN_BATCH_REQ_START BIT(0) +#define SCAN_BATCH_REQ_STOP BIT(1) +#define SCAN_BATCH_REQ_RESULT BIT(2) +#endif + +/* Support AP Setection */ +#define SCN_BSS_JOIN_FAIL_THRESOLD 4 + +#define SCN_CTRL_SCAN_CHANNEL_LISTEN_TIME_ENABLE BIT(1) +#define SCN_CTRL_IGNORE_AIS_FIX_CHANNEL BIT(1) +#define SCN_CTRL_ENABLE BIT(0) + +#define SCN_CTRL_DEFAULT_SCAN_CTRL SCN_CTRL_IGNORE_AIS_FIX_CHANNEL + +#define SCN_SCAN_DONE_PRINT_BUFFER_LENGTH 300 +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +enum ENUM_SCAN_TYPE { + SCAN_TYPE_PASSIVE_SCAN = 0, + SCAN_TYPE_ACTIVE_SCAN, + SCAN_TYPE_NUM +}; + +enum ENUM_SCAN_STATE { + SCAN_STATE_IDLE = 0, + SCAN_STATE_SCANNING, + SCAN_STATE_NUM +}; + +enum ENUM_FW_SCAN_STATE { + FW_SCAN_STATE_IDLE = 0, /* 0 */ + FW_SCAN_STATE_SCAN_START, /* 1 */ + FW_SCAN_STATE_REQ_CHANNEL, /* 2 */ + FW_SCAN_STATE_SET_CHANNEL, /* 3 */ + FW_SCAN_STATE_DELAYED_ACTIVE_PROB_REQ, /* 4 */ + FW_SCAN_STATE_ACTIVE_PROB_REQ, /* 5 */ + FW_SCAN_STATE_LISTEN, /* 6 */ + FW_SCAN_STATE_SCAN_DONE, /* 7 */ + FW_SCAN_STATE_NLO_START, /* 8 */ + FW_SCAN_STATE_NLO_HIT_CHECK, /* 9 */ + FW_SCAN_STATE_NLO_STOP, /* 10 */ + FW_SCAN_STATE_BATCH_START, /* 11 */ + FW_SCAN_STATE_BATCH_CHECK, /* 12 */ + FW_SCAN_STATE_BATCH_STOP, /* 13 */ + FW_SCAN_STATE_NUM /* 14 */ +}; + +enum ENUM_SCAN_CHANNEL { + SCAN_CHANNEL_FULL = 0, + SCAN_CHANNEL_2G4, + SCAN_CHANNEL_5G, + SCAN_CHANNEL_P2P_SOCIAL, + SCAN_CHANNEL_SPECIFIED, + SCAN_CHANNEL_NUM +}; + +struct MSG_SCN_FSM { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint32_t u4Dummy; +}; + +enum ENUM_SCHED_SCAN_ACT { + SCHED_SCAN_ACT_ENABLE = 0, + SCHED_SCAN_ACT_DISABLE, +}; + +#define SCAN_LOG_PREFIX_MAX_LEN (16) +#define SCAN_LOG_MSG_MAX_LEN (500) +#define SCAN_LOG_BUFF_SIZE (200) +#define SCAN_LOG_DYN_ALLOC_MEM (0) + +enum ENUM_SCAN_LOG_PREFIX { + /* Scan */ + LOG_SCAN_REQ_K2D = 0, /* 0 */ + LOG_SCAN_REQ_D2F, + LOG_SCAN_RESULT_F2D, + LOG_SCAN_RESULT_D2K, + LOG_SCAN_DONE_F2D, + LOG_SCAN_DONE_D2K, /* 5 */ + + /* Sched scan */ + LOG_SCHED_SCAN_REQ_START_K2D, + LOG_SCHED_SCAN_REQ_START_D2F, + LOG_SCHED_SCAN_REQ_STOP_K2D, + LOG_SCHED_SCAN_REQ_STOP_D2F, + LOG_SCHED_SCAN_DONE_F2D, /* 10 */ + LOG_SCHED_SCAN_DONE_D2K, + + /* Scan abort */ + LOG_SCAN_ABORT_REQ_K2D, + LOG_SCAN_ABORT_REQ_D2F, + LOG_SCAN_ABORT_DONE_D2K, + + /* Driver only */ + LOG_SCAN_D2D, + + /* Last one */ + LOG_SCAN_MAX +}; + +/*----------------------------------------------------------------------------*/ +/* BSS Descriptors */ +/*----------------------------------------------------------------------------*/ +struct BSS_DESC { + struct LINK_ENTRY rLinkEntry; + /* Support AP Selection*/ + struct LINK_ENTRY rLinkEntryEss[KAL_AIS_NUM]; + + uint8_t aucBSSID[MAC_ADDR_LEN]; + + /* For IBSS, the SrcAddr is different from BSSID */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; + + /* If we are going to connect to this BSS (JOIN or ROAMING to another + * BSS), don't remove this record from BSS List. + */ + u_int8_t fgIsConnecting; + + /* If we have connected to this BSS (NORMAL_TR), don't removed + * this record from BSS list. + */ + u_int8_t fgIsConnected; + + /* When this flag is TRUE, means the SSID of this + * BSS is not known yet. + */ + u_int8_t fgIsHiddenSSID; + + uint8_t ucSSIDLen; + uint8_t aucSSID[ELEM_MAX_LEN_SSID]; + + OS_SYSTIME rUpdateTime; + + enum ENUM_BSS_TYPE eBSSType; + + uint16_t u2CapInfo; + + uint16_t u2BeaconInterval; + uint16_t u2ATIMWindow; + + uint16_t u2OperationalRateSet; + uint16_t u2BSSBasicRateSet; + u_int8_t fgIsUnknownBssBasicRate; + + u_int8_t fgIsERPPresent; + u_int8_t fgIsHTPresent; + u_int8_t fgIsVHTPresent; +#if (CFG_SUPPORT_802_11AX == 1) + u_int8_t fgIsHEPresent; +#endif + +#if (CFG_SUPPORT_802_11V_MBSSID == 1) + /* Max BSSID indicator. Range from 1 to 8. + * 0 means MBSSID function is disabled + */ + u_int8_t ucMaxBSSIDIndicator; + /* MBSSID index which DUT connected for this BSS. + * 0 means DUT connect to transmitted BSSID + */ + u_int8_t ucMBSSIDIndex; +#endif + + uint8_t ucPhyTypeSet; /* Available PHY Type Set of this BSS */ + + /* record from bcn or probe response */ + uint8_t ucVhtCapNumSoundingDimensions; + + uint8_t ucChannelNum; + + /* Record bandwidth for association process. Some AP will + * send association resp by 40MHz BW + */ + enum ENUM_CHNL_EXT eSco; + + enum ENUM_CHANNEL_WIDTH eChannelWidth; /* VHT operation ie */ + uint8_t ucCenterFreqS1; + uint8_t ucCenterFreqS2; + enum ENUM_BAND eBand; + + uint8_t ucDTIMPeriod; + u_int8_t fgTIMPresent; + + /* This BSS's TimeStamp is larger than us(TCL == 1 in RX_STATUS_T) */ + u_int8_t fgIsLargerTSF; + + uint8_t ucRCPI; + + /* A flag to indicate this BSS's WMM capability */ + uint8_t ucWmmFlag; + + /*! \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 + */ + uint32_t u4RsnSelectedGroupCipher; + uint32_t u4RsnSelectedPairwiseCipher; + uint32_t u4RsnSelectedAKMSuite; + + uint16_t u2RsnCap; + + struct RSN_INFO rRSNInfo; + struct RSN_INFO rWPAInfo; +#if 1 /* CFG_SUPPORT_WAPI */ + struct WAPI_INFO rIEWAPI; + u_int8_t fgIEWAPI; +#endif + u_int8_t fgIERSN; + u_int8_t fgIEWPA; + u_int8_t fgIEOsen; + + /*! \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 + */ + uint8_t ucEncLevel; + +#if CFG_ENABLE_WIFI_DIRECT + u_int8_t fgIsP2PPresent; + u_int8_t fgIsP2PReport; /* TRUE: report to upper layer */ + struct P2P_DEVICE_DESC *prP2pDesc; + + /* For IBSS, the SrcAddr is different from BSSID */ + uint8_t aucIntendIfAddr[MAC_ADDR_LEN]; + +#if 0 /* TODO: Remove this */ + /* Device Capability Attribute. (P2P_DEV_CAPABILITY_XXXX) */ + uint8_t ucDevCapabilityBitmap; + + /* Group Capability Attribute. (P2P_GROUP_CAPABILITY_XXXX) */ + uint8_t ucGroupCapabilityBitmap; +#endif + + struct LINK 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 + + /* the beacon doesn't advertise the FT AKM but will + * use FT when supported clients connect + */ + uint8_t ucIsAdaptive11r; + + /* The received IE length exceed the maximum IE buffer size */ + u_int8_t fgIsIEOverflow; + + uint16_t u2RawLength; /* The byte count of aucRawBuf[] */ + uint16_t u2IELength; /* The byte count of aucIEBuf[] */ + + /* Place u8TimeStamp before aucIEBuf[1] to force DW align */ + union ULARGE_INTEGER u8TimeStamp; + + uint8_t aucRawBuf[CFG_RAW_BUFFER_SIZE]; + uint8_t aucIEBuf[CFG_IE_BUFFER_SIZE]; + uint16_t u2JoinStatus; + OS_SYSTIME rJoinFailTime; + + /* Support AP Selection */ + struct AIS_BLACKLIST_ITEM *prBlack; +#if CFG_SUPPORT_MBO + uint8_t fgIsDisallowed; +#endif + uint16_t u2StaCnt; + uint16_t u2AvaliableAC; /* Available Admission Capacity */ + uint8_t ucJoinFailureCount; + uint8_t ucChnlUtilization; + uint8_t ucSNR; + u_int8_t fgSeenProbeResp; + u_int8_t fgExsitBssLoadIE; + u_int8_t fgMultiAnttenaAndSTBC; + uint32_t u4UpdateIdx; + uint8_t fgIotApActionValid; + uint8_t ucIotApAct; +#if CFG_SUPPORT_RSN_SCORE + u_int8_t fgIsRSNSuitableBss; +#endif + /* end Support AP Selection */ + int8_t cPowerLimit; + uint8_t aucRrmCap[5]; +#if CFG_SUPPORT_HE_ER + uint8_t fgIsERSUDisable; + uint8_t ucDCMMaxConRx; +#endif +}; + +struct SCAN_PARAM { /* Used by SCAN FSM */ + /* Active or Passive */ + enum ENUM_SCAN_TYPE eScanType; + + /* Network Type */ + uint8_t ucBssIndex; + + /* Specified SSID Type */ + uint8_t ucSSIDType; + uint8_t ucSSIDNum; + + /* Length of Specified SSID */ + uint8_t ucSpecifiedSSIDLen[SCN_SSID_MAX_NUM]; + + /* Specified SSID */ + uint8_t aucSpecifiedSSID[SCN_SSID_MAX_NUM][ELEM_MAX_LEN_SSID]; + +#if CFG_ENABLE_WIFI_DIRECT + u_int8_t fgFindSpecificDev; /* P2P: Discovery Protocol */ + uint8_t aucDiscoverDevAddr[MAC_ADDR_LEN]; + u_int8_t fgIsDevType; + struct P2P_DEVICE_TYPE rDiscoverDevType; + + /* TODO: Find Specific Device Type. */ +#endif /* CFG_ENABLE_WIFI_DIRECT */ + + uint16_t u2ChannelDwellTime; + uint16_t u2ChannelMinDwellTime; + uint16_t u2TimeoutValue; + + uint8_t aucBSSID[MAC_ADDR_LEN]; + + enum ENUM_MSG_ID eMsgId; + u_int8_t fgIsScanV2; + + /* Run time flags */ + uint16_t u2ProbeDelayTime; + + /* channel information */ + enum ENUM_SCAN_CHANNEL eScanChannel; + uint8_t ucChannelListNum; + struct RF_CHANNEL_INFO arChnlInfoList[MAXIMUM_OPERATION_CHANNEL_LIST]; + + /* random mac */ + uint8_t ucScnFuncMask; + uint8_t aucRandomMac[MAC_ADDR_LEN]; + + /* Feedback information */ + uint8_t ucSeqNum; + + /* Information Element */ + uint16_t u2IELen; + uint8_t aucIE[MAX_IE_LENGTH]; + +}; + +struct SCHED_SCAN_PARAM { /* Used by SCAN FSM */ + uint8_t ucSeqNum; + uint8_t ucBssIndex; /* Network Type */ + u_int8_t fgStopAfterIndication; /* always FALSE */ + uint8_t ucMatchSSIDNum; /* Match SSID */ + struct BSS_DESC *aprPendingBssDescToInd[SCN_SSID_MATCH_MAX_NUM]; +}; + +struct SCAN_LOG_ELEM_BSS { + struct LINK_ENTRY rLinkEntry; + + uint8_t aucBSSID[MAC_ADDR_LEN]; + uint16_t u2SeqCtrl; +}; + +struct SCAN_LOG_CACHE { + struct LINK rBSSListFW; + struct LINK rBSSListCFG; + + struct SCAN_LOG_ELEM_BSS arBSSListBufFW[SCAN_LOG_BUFF_SIZE]; + struct SCAN_LOG_ELEM_BSS arBSSListBufCFG[SCAN_LOG_BUFF_SIZE]; +}; + +struct SCAN_INFO { + /* Store the STATE variable of SCAN FSM */ + enum ENUM_SCAN_STATE eCurrentState; + + OS_SYSTIME rLastScanCompletedTime; + + struct SCAN_PARAM rScanParam; + struct SCHED_SCAN_PARAM rSchedScanParam; + + uint32_t u4NumOfBssDesc; + + uint8_t aucScanBuffer[SCN_MAX_BUFFER_SIZE]; + + struct LINK rBSSDescList; + + struct LINK rFreeBSSDescList; + + struct LINK rPendingMsgList; + + /* Sparse Channel Detection */ + u_int8_t fgIsSparseChannelValid; + struct RF_CHANNEL_INFO rSparseChannel; + + /* Sched scan state tracking */ + u_int8_t fgSchedScanning; + + /* Full2Partial */ + OS_SYSTIME u4LastFullScanTime; + u_int8_t fgIsScanForFull2Partial; + u_int8_t ucFull2PartialSeq; + uint32_t au4ChannelBitMap[SCAN_CHANNEL_BITMAP_ARRAY_LEN]; + + /*channel idle count # Mike */ + uint8_t ucSparseChannelArrayValidNum; + uint8_t aucReserved[3]; + uint8_t aucChannelNum[64]; + uint16_t au2ChannelIdleTime[64]; + /* Mdrdy Count in each Channel */ + uint8_t aucChannelMDRDYCnt[64]; + /* Beacon and Probe Response Count in each Channel */ + uint8_t aucChannelBAndPCnt[64]; + uint16_t au2ChannelScanTime[64]; + /* Support AP Selection */ + uint32_t u4ScanUpdateIdx; + + /* Scan log cache */ + struct SCAN_LOG_CACHE rScanLogCache; +}; + +/* Incoming Mailbox Messages */ +struct MSG_SCN_SCAN_REQ { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucSeqNum; + uint8_t ucBssIndex; + enum ENUM_SCAN_TYPE eScanType; + + /* BIT(0) wildcard / BIT(1) P2P-wildcard / BIT(2) specific */ + uint8_t ucSSIDType; + + uint8_t ucSSIDLength; + uint8_t aucSSID[PARAM_MAX_LEN_SSID]; + uint16_t u2ChannelDwellTime; /* ms unit */ + uint16_t u2TimeoutValue; /* ms unit */ + enum ENUM_SCAN_CHANNEL eScanChannel; + uint8_t ucChannelListNum; + struct RF_CHANNEL_INFO arChnlInfoList[MAXIMUM_OPERATION_CHANNEL_LIST]; + uint16_t u2IELen; + uint8_t aucIE[MAX_IE_LENGTH]; +}; + +struct MSG_SCN_SCAN_REQ_V2 { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucSeqNum; + uint8_t ucBssIndex; + enum ENUM_SCAN_TYPE eScanType; + + /* BIT(0) wildcard / BIT(1) P2P-wildcard / BIT(2) specific */ + uint8_t ucSSIDType; + + uint8_t ucSSIDNum; + struct PARAM_SSID *prSsid; + uint16_t u2ProbeDelay; + uint16_t u2ChannelDwellTime; /* In TU. 1024us. */ + uint16_t u2ChannelMinDwellTime; /* In TU. 1024us. */ + uint16_t u2TimeoutValue; /* ms unit */ + + uint8_t aucBSSID[MAC_ADDR_LEN]; + enum ENUM_SCAN_CHANNEL eScanChannel; + uint8_t ucChannelListNum; + struct RF_CHANNEL_INFO arChnlInfoList[MAXIMUM_OPERATION_CHANNEL_LIST]; + uint8_t ucScnFuncMask; + uint8_t aucRandomMac[MAC_ADDR_LEN]; /* random mac */ + uint16_t u2IELen; + uint8_t aucIE[MAX_IE_LENGTH]; +}; + +struct MSG_SCN_SCAN_CANCEL { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucSeqNum; + uint8_t ucBssIndex; + u_int8_t fgIsChannelExt; + u_int8_t fgIsOidRequest; +}; + +/* Outgoing Mailbox Messages */ +enum ENUM_SCAN_STATUS { + SCAN_STATUS_DONE = 0, + SCAN_STATUS_CANCELLED, + SCAN_STATUS_FAIL, + SCAN_STATUS_BUSY, + SCAN_STATUS_NUM +}; + +struct MSG_SCN_SCAN_DONE { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucSeqNum; + uint8_t ucBssIndex; + enum ENUM_SCAN_STATUS eScanStatus; +}; + +#if CFG_SUPPORT_AGPS_ASSIST +enum AP_PHY_TYPE { + AGPS_PHY_A, + AGPS_PHY_B, + AGPS_PHY_G, +}; + +struct AGPS_AP_INFO { + uint8_t aucBSSID[MAC_ADDR_LEN]; + int16_t i2ApRssi; /* -127..128 */ + uint16_t u2Channel; /* 0..256 */ + enum AP_PHY_TYPE ePhyType; +}; + +struct AGPS_AP_LIST { + uint8_t ucNum; + struct AGPS_AP_INFO arApInfo[SCN_AGPS_AP_LIST_MAX_NUM]; +}; +#endif +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +extern const char aucScanLogPrefix[][SCAN_LOG_PREFIX_MAX_LEN]; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +#if DBG_DISABLE_ALL_LOG +#define scanlog_dbg(prefix, _Clz, _Fmt, ...) +#else /* DBG_DISABLE_ALL_LOG */ +#define scanlog_dbg(prefix, _Clz, _Fmt, ...) \ + do { \ + if ((aucDebugModule[DBG_SCN_IDX] & \ + DBG_CLASS_##_Clz) == 0) \ + break; \ + LOG_FUNC("[%u]SCANLOG:(SCN " #_Clz ") %s " _Fmt, \ + KAL_GET_CURRENT_THREAD_ID(), \ + aucScanLogPrefix[prefix], ##__VA_ARGS__); \ + } while (0) +#endif /* DBG_DISABLE_ALL_LOG */ + + +/******************************************************************************* + * 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 struct ADAPTER *prAdapter); + +void scnUninit(IN struct ADAPTER *prAdapter); + +/* Scan utilities */ +uint32_t scanCountBits(IN uint32_t bitMap[], IN uint32_t bitMapSize); + +void scanSetRequestChannel(IN struct ADAPTER *prAdapter, + IN uint32_t u4ScanChannelNum, + IN struct RF_CHANNEL_INFO arChannel[], + IN uint32_t u4ScanFlags, + IN uint8_t fgIsOnlineScan, + OUT struct MSG_SCN_SCAN_REQ_V2 *prScanReqMsg); + +/* BSS-DESC Search */ +struct BSS_DESC *scanSearchBssDescByBssid(IN struct ADAPTER *prAdapter, + IN uint8_t aucBSSID[]); + +struct BSS_DESC * +scanSearchBssDescByBssidAndSsid(IN struct ADAPTER *prAdapter, + IN uint8_t aucBSSID[], + IN u_int8_t fgCheckSsid, + IN struct PARAM_SSID *prSsid); + +struct BSS_DESC *scanSearchBssDescByTA(IN struct ADAPTER *prAdapter, + IN uint8_t aucSrcAddr[]); + +struct BSS_DESC * +scanSearchBssDescByTAAndSsid(IN struct ADAPTER *prAdapter, + IN uint8_t aucSrcAddr[], + IN u_int8_t fgCheckSsid, + IN struct PARAM_SSID *prSsid); + +/* BSS-DESC Search - Alternative */ +struct BSS_DESC * +scanSearchExistingBssDesc(IN struct ADAPTER *prAdapter, + IN enum ENUM_BSS_TYPE eBSSType, + IN uint8_t aucBSSID[], + IN uint8_t aucSrcAddr[]); + +struct BSS_DESC * +scanSearchExistingBssDescWithSsid(IN struct ADAPTER *prAdapter, + IN enum ENUM_BSS_TYPE eBSSType, + IN uint8_t aucBSSID[], + IN uint8_t aucSrcAddr[], + IN u_int8_t fgCheckSsid, + IN struct PARAM_SSID *prSsid); + +/* BSS-DESC Allocation */ +struct BSS_DESC *scanAllocateBssDesc(IN struct ADAPTER *prAdapter); + +/* BSS-DESC Removal */ +void scanRemoveBssDescsByPolicy(IN struct ADAPTER *prAdapter, + IN uint32_t u4RemovePolicy); + +void scanRemoveBssDescByBssid(IN struct ADAPTER *prAdapter, + IN uint8_t aucBSSID[]); + +void scanRemoveBssDescByBandAndNetwork( + IN struct ADAPTER *prAdapter, + IN enum ENUM_BAND eBand, + IN uint8_t ucBssIndex); + +/* BSS-DESC State Change */ +void scanRemoveConnFlagOfBssDescByBssid(IN struct ADAPTER *prAdapter, + IN uint8_t aucBSSID[]); + +/* BSS-DESC Insertion - ALTERNATIVE */ +struct BSS_DESC *scanAddToBssDesc(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +uint32_t scanProcessBeaconAndProbeResp(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSWRfb); + +void +scanBuildProbeReqFrameCommonIEs(IN struct MSDU_INFO *prMsduInfo, + IN uint8_t *pucDesiredSsid, + IN uint32_t u4DesiredSsidLen, + IN uint16_t u2SupportedRateSet); + +uint32_t scanSendProbeReqFrames(IN struct ADAPTER *prAdapter, + IN struct SCAN_PARAM *prScanParam); + +void scanUpdateBssDescForSearch(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc); + +struct BSS_DESC *scanSearchBssDescByPolicy(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +uint32_t scanAddScanResult(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc, + IN struct SW_RFB *prSwRfb); + +void scanReportBss2Cfg80211(IN struct ADAPTER *prAdapter, + IN enum ENUM_BSS_TYPE eBSSType, + IN struct BSS_DESC *SpecificprBssDesc); + +/*----------------------------------------------------------------------------*/ +/* Routines in scan_fsm.c */ +/*----------------------------------------------------------------------------*/ +void scnFsmSteps(IN struct ADAPTER *prAdapter, + IN enum ENUM_SCAN_STATE eNextState); + +/*----------------------------------------------------------------------------*/ +/* Command Routines */ +/*----------------------------------------------------------------------------*/ +void scnSendScanReq(IN struct ADAPTER *prAdapter); + +void scnSendScanReqV2(IN struct ADAPTER *prAdapter); + +/*----------------------------------------------------------------------------*/ +/* RX Event Handling */ +/*----------------------------------------------------------------------------*/ +void scnEventScanDone(IN struct ADAPTER *prAdapter, + IN struct EVENT_SCAN_DONE *prScanDone, + u_int8_t fgIsNewVersion); + +void scnEventSchedScanDone(IN struct ADAPTER *prAdapter, + IN struct EVENT_SCHED_SCAN_DONE *prSchedScanDone); + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Handling */ +/*----------------------------------------------------------------------------*/ +void scnFsmMsgStart(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void scnFsmMsgAbort(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void scnFsmHandleScanMsg(IN struct ADAPTER *prAdapter, + IN struct MSG_SCN_SCAN_REQ *prScanReqMsg); + +void scnFsmHandleScanMsgV2(IN struct ADAPTER *prAdapter, + IN struct MSG_SCN_SCAN_REQ_V2 *prScanReqMsg); + +void scnFsmRemovePendingMsg(IN struct ADAPTER *prAdapter, + IN uint8_t ucSeqNum, + IN uint8_t ucBssIndex); + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Generation */ +/*----------------------------------------------------------------------------*/ +void +scnFsmGenerateScanDoneMsg(IN struct ADAPTER *prAdapter, + IN enum ENUM_MSG_ID eMsgId, + IN uint8_t ucSeqNum, + IN uint8_t ucBssIndex, + IN enum ENUM_SCAN_STATUS eScanStatus); + +/*----------------------------------------------------------------------------*/ +/* Query for sparse channel */ +/*----------------------------------------------------------------------------*/ +u_int8_t scnQuerySparseChannel(IN struct ADAPTER *prAdapter, + enum ENUM_BAND *prSparseBand, + uint8_t *pucSparseChannel); + +/*----------------------------------------------------------------------------*/ +/* OID/IOCTL Handling */ +/*----------------------------------------------------------------------------*/ +#if CFG_SUPPORT_PASSPOINT +struct BSS_DESC *scanSearchBssDescByBssidAndLatestUpdateTime( + IN struct ADAPTER *prAdapter, + IN uint8_t aucBSSID[]); +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_AGPS_ASSIST +void scanReportScanResultToAgps(struct ADAPTER *prAdapter); +#endif + +#if CFG_SUPPORT_SCHED_SCAN +u_int8_t scnFsmSchedScanRequest(IN struct ADAPTER *prAdapter, + IN struct PARAM_SCHED_SCAN_REQUEST *prSchedScanRequest); + +u_int8_t scnFsmSchedScanStopRequest(IN struct ADAPTER *prAdapter); + +u_int8_t scnFsmSchedScanSetAction(IN struct ADAPTER *prAdapter, + IN enum ENUM_SCHED_SCAN_ACT ucSchedScanAct); + +u_int8_t scnFsmSchedScanSetCmd(IN struct ADAPTER *prAdapter, + IN struct CMD_SCHED_SCAN_REQ *prSchedScanCmd); + +void scnSetSchedScanPlan(IN struct ADAPTER *prAdapter, + IN struct CMD_SCHED_SCAN_REQ *prSchedScanCmd); + +#endif /* CFG_SUPPORT_SCHED_SCAN */ + +void scanLogEssResult(struct ADAPTER *prAdapter); +void scanInitEssResult(struct ADAPTER *prAdapter); +#if CFG_SUPPORT_SCAN_CACHE_RESULT +/*----------------------------------------------------------------------------*/ +/* Routines in scan_cache.c */ +/*----------------------------------------------------------------------------*/ +u_int8_t isScanCacheDone(struct GL_SCAN_CACHE_INFO *prScanCache); +#endif /* CFG_SUPPORT_SCAN_CACHE_RESULT */ + +void scanReqLog(struct CMD_SCAN_REQ_V2 *prCmdScanReq); +void scanResultLog(struct ADAPTER *prAdapter, struct SW_RFB *prSwRfb); +void scanLogCacheAddBSS(struct LINK *prList, + struct SCAN_LOG_ELEM_BSS *prListBuf, + enum ENUM_SCAN_LOG_PREFIX prefix, + uint8_t bssId[], uint16_t seq); +void scanLogCacheFlushBSS(struct LINK *prList, + enum ENUM_SCAN_LOG_PREFIX prefix); +void scanLogCacheFlushAll(struct ADAPTER *prAdapter, + struct SCAN_LOG_CACHE *prScanLogCache, + enum ENUM_SCAN_LOG_PREFIX prefix); + +void scanRemoveBssDescFromList(IN struct LINK *prBSSDescList, + IN struct BSS_DESC *prBssDesc, + IN struct ADAPTER *prAdapter); +void scanInsertBssDescToList(IN struct LINK *prBSSDescList, + IN struct BSS_DESC *prBssDesc, + IN u_int8_t init); +void scanResetBssDesc(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc); + +/* Check if VHT IE filled in Epigram IE */ +void scanCheckEpigramVhtIE(IN uint8_t *pucBuf, IN struct BSS_DESC *prBssDesc); +void scanParseVHTCapIE(IN uint8_t *pucIE, IN struct BSS_DESC *prBssDesc); +void scanParseVHTOpIE(IN uint8_t *pucIE, IN struct BSS_DESC *prBssDesc); + +void scanCheckAdaptive11rIE(IN uint8_t *pucBuf, IN struct BSS_DESC *prBssDesc); + +#endif /* _SCAN_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/stats.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/stats.h new file mode 100644 index 0000000000000..358dd38340848 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/stats.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. + * If not, see . + */ + +/******************************************************************************* + * C O M P I L E 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 + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O D E C L A R A T I O N S + ******************************************************************************* + */ + +#if (CFG_SUPPORT_STATISTICS == 1) +#define STATS_RX_PKT_INFO_DISPLAY StatsRxPktInfoDisplay +#define STATS_TX_PKT_INFO_DISPLAY StatsTxPktInfoDisplay +#else +#define STATS_RX_PKT_INFO_DISPLAY +#define STATS_TX_PKT_INFO_DISPLAY +#endif /* CFG_SUPPORT_STATISTICS */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E F U N C T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C F U N C T I O N S + ******************************************************************************* + */ + +#define STATS_TX_TIME_ARRIVE(__Skb__) \ +do { \ + uint64_t __SysTime; \ + __SysTime = StatsEnvTimeGet(); /* us */ \ + GLUE_SET_PKT_XTIME(__Skb__, __SysTime); \ +} while (FALSE) + +uint64_t StatsEnvTimeGet(void); + +void StatsEnvTxTime2Hif(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +void StatsEnvRxTime2Host(IN struct ADAPTER *prAdapter, + struct sk_buff *prSkb); + +void StatsRxPktInfoDisplay(struct SW_RFB *prSwRfb); + +void StatsTxPktInfoDisplay(struct sk_buff *prSkb); + +void StatsResetTxRx(void); + +void StatsEnvSetPktDelay(IN uint8_t ucTxOrRx, + IN uint8_t ucIpProto, IN uint16_t u2UdpPort, + uint32_t u4DelayThreshold); + +void StatsEnvGetPktDelay(OUT uint8_t *pucTxRxFlag, + OUT uint8_t *pucTxIpProto, OUT uint16_t *pu2TxUdpPort, + OUT uint32_t *pu4TxDelayThreshold, + OUT uint8_t *pucRxIpProto, + OUT uint16_t *pu2RxUdpPort, + OUT uint32_t *pu4RxDelayThreshold); +/* End of stats.h */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/swcr.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/swcr.h new file mode 100644 index 0000000000000..c1467c6e25d74 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/swcr.h @@ -0,0 +1,269 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/ + * MT6620_WIFI_DRIVER_V2_3/include/mgmt/swcr.h#1 + */ + +/*! \file "swcr.h" + * \brief + */ + +/* + * + */ + +#ifndef _SWCR_H +#define _SWCR_H + +#include "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 TEST_PS 1 + +#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) (ARRAY_SIZE(x)) + +#define SWCR_CR_NUM 7 + +#define SWCR_GET_RW_INDEX(action, rw, index) \ +do { \ + index = action & 0x7F; \ + rw = action >> 7; \ +} while (0) + +extern uint32_t g_au4SwCr[]; /*: 0: command other: data */ + +typedef void(*PFN_SWCR_RW_T) (struct ADAPTER *prAdapter, + uint8_t ucRead, uint16_t u2Addr, uint32_t *pu4Data); +typedef void(*PFN_CMD_RW_T) (struct ADAPTER *prAdapter, + uint8_t ucCate, uint8_t ucAction, uint8_t ucOpt0, + uint8_t ucOpt1); + +struct SWCR_MAP_ENTRY { + uint16_t u2Type; + void *u4Addr; +}; + +struct SWCR_MOD_MAP_ENTRY { + uint8_t ucMapNum; + struct SWCR_MAP_ENTRY *prSwCrMap; +}; + +enum ENUM_SWCR_DBG_TYPE { + SWCR_DBG_TYPE_ALL = 0, + SWCR_DBG_TYPE_TXRX, + SWCR_DBG_TYPE_RX_RATES, + SWCR_DBG_TYPE_PS, + SWCR_DBG_TYPE_NUM +}; + +enum ENUM_SWCR_DBG_ALL { + 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 +}; + +/******************************************************************************* + * 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(struct ADAPTER *prAdapter, + uint8_t ucRead, uint16_t u2Addr, uint32_t *pu4Data); + +/* Debug Support */ +void swCrFrameCheckEnable(struct ADAPTER *prAdapter, + uint32_t u4DumpType); +void swCrDebugInit(struct ADAPTER *prAdapter); +void swCrDebugCheckEnable(struct ADAPTER *prAdapter, + u_int8_t fgIsEnable, uint8_t ucType, uint32_t u4Timeout); +void swCrDebugUninit(struct ADAPTER *prAdapter); + +#if CFG_SUPPORT_SWCR +void swCtrlCmdCategory0(struct ADAPTER *prAdapter, + uint8_t ucCate, uint8_t ucAction, uint8_t ucOpt0, + uint8_t ucOpt1); +void swCtrlCmdCategory1(struct ADAPTER *prAdapter, + uint8_t ucCate, uint8_t ucAction, uint8_t ucOpt0, + uint8_t ucOpt1); +#if TEST_PS +void testPsCmdCategory0(struct ADAPTER *prAdapter, + uint8_t ucCate, uint8_t ucAction, uint8_t ucOpt0, + uint8_t ucOpt1); +void testPsCmdCategory1(struct ADAPTER *prAdapter, + uint8_t ucCate, uint8_t ucAction, uint8_t ucOpt0, + uint8_t ucOpt1); +#endif +#if CFG_SUPPORT_802_11V +#if (CFG_SUPPORT_802_11V_TIMING_MEASUREMENT == 1) && (WNM_UNIT_TEST == 1) +void testWNMCmdCategory0(struct ADAPTER *prAdapter, + uint8_t ucCate, uint8_t ucAction, uint8_t ucOpt0, + uint8_t ucOpt1); +#endif +#endif +void swCtrlSwCr(struct ADAPTER *prAdapter, uint8_t ucRead, + uint16_t u2Addr, uint32_t *pu4Data); + +/* Support Debug */ +void swCrDebugCheck(struct ADAPTER *prAdapter, + struct CMD_SW_DBG_CTRL *prCmdSwCtrl); +void swCrDebugCheckTimeout(IN struct ADAPTER *prAdapter, + unsigned long ulParamPtr); +void swCrDebugQuery(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); +void swCrDebugQueryTimeout(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo); +#endif + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/tdls.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/tdls.h new file mode 100644 index 0000000000000..ec39932967eb6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/tdls.h @@ -0,0 +1,485 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: include/tdls.h#1 + */ + +/*! \file "tdls.h" + * \brief This file contains the internal used in TDLS modules + * for MediaTek Inc. 802.11 Wireless LAN Adapters. + */ + + +#ifndef _TDLS_H +#define _TDLS_H + +#if CFG_SUPPORT_TDLS + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ +#define TDLS_CFG_CMD_TEST + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/* assign station record idx for the packet */ +#define TDLSEX_STA_REC_IDX_GET(__prAdapter__, __MsduInfo__) \ +{ \ + struct STA_RECORD *__StaRec__; \ + __MsduInfo__->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; \ + __StaRec__ = cnmGetStaRecByAddress(__prAdapter__, \ + (uint8_t) NETWORK_TYPE_AIS_INDEX, \ + __MsduInfo__->aucEthDestAddr); \ + if ((__StaRec__ != NULL) && (IS_DLS_STA(__StaRec__))) \ + __MsduInfo__->ucStaRecIndex = __StaRec__->ucIndex; \ +} + +/* fill wiphy flag */ +#define TDLSEX_WIPHY_FLAGS_INIT(__fgFlag__) \ +{ \ + __fgFlag__ |= (WIPHY_FLAG_SUPPORTS_TDLS | \ + WIPHY_FLAG_TDLS_EXTERNAL_SETUP); \ +} + +#define LR_TDLS_FME_FIELD_FILL(__Len) \ +{ \ + pPkt += __Len; \ + u4PktLen += __Len; \ +} + +/******************************************************************************* + * 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 + ******************************************************************************* + */ + +/* Status code */ +#define TDLS_STATUS uint32_t + +#define TDLS_STATUS_SUCCESS WLAN_STATUS_SUCCESS +#define TDLS_STATUS_FAIL WLAN_STATUS_FAILURE +#define TDLS_STATUS_INVALID_LENGTH WLAN_STATUS_INVALID_LENGTH +#define TDLS_STATUS_RESOURCES WLAN_STATUS_RESOURCES +#define TDLS_STATUS_PENDING WLAN_STATUS_PENDING + +#define TDLS_FME_MAC_ADDR_LEN 6 +#define TDLS_EX_CAP_PEER_UAPSD BIT(0) +#define TDLS_EX_CAP_CHAN_SWITCH BIT(1) +#define TDLS_EX_CAP_TDLS BIT(2) +#define TDLS_CMD_PEER_UPDATE_EXT_CAP_MAXLEN 5 +#define TDLS_CMD_PEER_UPDATE_SUP_RATE_MAX 50 +#define TDLS_CMD_PEER_UPDATE_SUP_CHAN_MAX 50 +#define TDLS_SEC_BUF_LENGTH 600 + +#define MAXNUM_TDLS_PEER 4 + +/* command */ +enum TDLS_CMD_ID { + TDLS_CMD_TEST_TX_FRAME = 0x00, + TDLS_CMD_TEST_RCV_FRAME, + TDLS_CMD_TEST_PEER_ADD, + TDLS_CMD_TEST_PEER_UPDATE, + TDLS_CMD_TEST_DATA_FRAME, + TDLS_CMD_TEST_RCV_NULL +}; + +/* protocol */ +#define TDLS_FRM_PROT_TYPE 0x890d + +/* payload specific type in the LLC/SNAP header */ +#define TDLS_FRM_PAYLOAD_TYPE 2 + +#define TDLS_FRM_CATEGORY 12 + +enum TDLS_FRM_ACTION_ID { + TDLS_FRM_ACTION_SETUP_REQ = 0x00, + TDLS_FRM_ACTION_SETUP_RSP, + TDLS_FRM_ACTION_CONFIRM, + TDLS_FRM_ACTION_TEARDOWN, + TDLS_FRM_ACTION_PTI, + TDLS_FRM_ACTION_CHAN_SWITCH_REQ, + TDLS_FRM_ACTION_CHAN_SWITCH_RSP, + TDLS_FRM_ACTION_PEER_PSM_REQ, + TDLS_FRM_ACTION_PEER_PSM_RSP, + TDLS_FRM_ACTION_PTI_RSP, + TDLS_FRM_ACTION_DISCOVERY_REQ, + TDLS_FRM_ACTION_DISCOVERY_RSP = 0x0e, + TDLS_FRM_ACTION_EVENT_TEAR_DOWN_TO_SUPPLICANT = 0x30 +}; + +/* 7.3.2.62 Link Identifier element */ +#define ELEM_ID_LINK_IDENTIFIER 101 + +struct IE_LINK_IDENTIFIER { + uint8_t ucId; + uint8_t ucLength; + uint8_t aBSSID[6]; + uint8_t aInitiator[6]; + uint8_t aResponder[6]; +} __KAL_ATTRIB_PACKED__; + +#define TDLS_LINK_IDENTIFIER_IE(__ie__) ((struct IE_LINK_IDENTIFIER *)(__ie__)) + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +struct STATION_PRARAMETERS { + const u8 *supported_rates; + struct net_device *vlan; + u32 sta_flags_mask, sta_flags_set; + u32 sta_modify_mask; + int listen_interval; + u16 aid; + u8 supported_rates_len; + u8 plink_action; + u8 plink_state; + u8 uapsd_queues; + u8 max_sp; + /* enum nl80211_mesh_power_mode local_pm; */ + u16 capability; + const u8 *ext_capab; + u8 ext_capab_len; +}; + +/* test command use */ +struct PARAM_CUSTOM_TDLS_CMD_STRUCT { + + uint8_t ucFmeType; /* TDLS_FRM_ACTION_ID */ + + uint8_t ucToken; + uint8_t ucCap; + + /* bit0: TDLS, bit1: Peer U-APSD Buffer, bit2: Channel Switching */ + + uint8_t ucExCap; + + uint8_t arSupRate[4]; + uint8_t arSupChan[4]; + + uint32_t u4Timeout; + + uint8_t arRspAddr[TDLS_FME_MAC_ADDR_LEN]; + uint8_t arBssid[TDLS_FME_MAC_ADDR_LEN]; + + /* Linux Kernel-3.10 */ + + /* struct */ + struct STATION_PRARAMETERS rPeerInfo; + +}; + +enum ENUM_TDLS_LINK_OPER { + TDLS_DISCOVERY_REQ, + TDLS_SETUP, + TDLS_TEARDOWN, + TDLS_ENABLE_LINK, + TDLS_DISABLE_LINK +}; + +struct TDLS_CMD_LINK_OPER { + + uint8_t aucPeerMac[6]; + enum ENUM_TDLS_LINK_OPER oper; + uint8_t ucBssIdx; +}; + +struct TDLS_CMD_LINK_MGT { + + uint8_t aucPeer[6]; + uint8_t ucActionCode; + uint8_t ucDialogToken; + uint16_t u2StatusCode; + uint32_t u4SecBufLen; + uint8_t aucSecBuf[TDLS_SEC_BUF_LENGTH]; + uint8_t ucBssIdx; +}; + +struct TDLS_CMD_PEER_ADD { + + uint8_t aucPeerMac[6]; + enum ENUM_STA_TYPE eStaType; +}; + +struct TDLS_CMD_PEER_UPDATE_HT_CAP_MCS_INFO { + uint8_t arRxMask[SUP_MCS_RX_BITMASK_OCTET_NUM]; + uint16_t u2RxHighest; + uint8_t ucTxParams; + uint8_t Reserved[3]; +}; + +struct TDLS_CMD_PEER_UPDATE_VHT_CAP_MCS_INFO { + uint8_t arRxMask[SUP_MCS_RX_BITMASK_OCTET_NUM]; +}; + +struct TDLS_CMD_PEER_UPDATE_HT_CAP { + uint16_t u2CapInfo; + uint8_t ucAmpduParamsInfo; + + /* 16 bytes MCS information */ + struct TDLS_CMD_PEER_UPDATE_HT_CAP_MCS_INFO rMCS; + + uint16_t u2ExtHtCapInfo; + uint32_t u4TxBfCapInfo; + uint8_t ucAntennaSelInfo; +}; + +struct TDLS_CMD_PEER_UPDATE_VHT_CAP { + uint16_t u2CapInfo; + /* 16 bytes MCS information */ + struct TDLS_CMD_PEER_UPDATE_VHT_CAP_MCS_INFO rVMCS; + +}; + +struct TDLS_CMD_PEER_UPDATE { + + uint8_t aucPeerMac[6]; + + uint8_t aucSupChan[TDLS_CMD_PEER_UPDATE_SUP_CHAN_MAX]; + + uint16_t u2StatusCode; + + uint8_t aucSupRate[TDLS_CMD_PEER_UPDATE_SUP_RATE_MAX]; + uint16_t u2SupRateLen; + + uint8_t UapsdBitmap; + uint8_t UapsdMaxSp; /* MAX_SP */ + + uint16_t u2Capability; + + uint8_t aucExtCap[TDLS_CMD_PEER_UPDATE_EXT_CAP_MAXLEN]; + uint16_t u2ExtCapLen; + + struct TDLS_CMD_PEER_UPDATE_HT_CAP rHtCap; + struct TDLS_CMD_PEER_UPDATE_VHT_CAP rVHtCap; + + u_int8_t fgIsSupHt; + enum ENUM_STA_TYPE eStaType; + +}; + +/* Command to TDLS core module */ +enum TDLS_CMD_CORE_ID { + TDLS_CORE_CMD_TEST_NULL_RCV = 0x00 +}; + +struct TDLS_CMD_CORE_TEST_NULL_RCV { + + uint32_t u4PM; +}; + +struct TDLS_CMD_CORE { + + uint32_t u4Command; + + uint8_t aucPeerMac[6]; + +#define TDLS_CMD_CORE_RESERVED_SIZE 50 + union { + struct TDLS_CMD_CORE_TEST_NULL_RCV rCmdNullRcv; + uint8_t Reserved[TDLS_CMD_CORE_RESERVED_SIZE]; + } Content; +}; + +enum TDLS_EVENT_HOST_ID { + TDLS_HOST_EVENT_TEAR_DOWN = 0x00, + TDLS_HOST_EVENT_TX_DONE +}; + +enum TDLS_EVENT_HOST_SUBID_TEAR_DOWN { + TDLS_HOST_EVENT_TD_PTI_TIMEOUT = 0x00, + TDLS_HOST_EVENT_TD_AGE_TIMEOUT, + TDLS_HOST_EVENT_TD_PTI_SEND_FAIL, + TDLS_HOST_EVENT_TD_PTI_SEND_MAX_FAIL, + TDLS_HOST_EVENT_TD_WRONG_NETWORK_IDX, + TDLS_HOST_EVENT_TD_NON_STATE3, + TDLS_HOST_EVENT_TD_LOST_TEAR_DOWN +}; + +enum TDLS_REASON_CODE { + TDLS_REASON_CODE_NONE = 0, + + TDLS_REASON_CODE_UNREACHABLE = 25, + TDLS_REASON_CODE_UNSPECIFIED = 26, + + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_UNKNOWN = 0x80, /*128*/ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_WIFI_OFF = 0x81, /*129*/ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_ROAMING = 0x82, /*130*/ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_TIMEOUT = 0x83, /*131*/ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_AGE_TIMEOUT = 0x84, /*132*/ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_REKEY = 0x85, /*133*/ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_SEND_FAIL = 0x86, /*134*/ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_SEND_MAX_FAIL = 0x87,/*135*/ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_WRONG_NETWORK_IDX = 0x88,/*136*/ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_NON_STATE3 = 0x89, /*137*/ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_TX_QUOTA_EMPTY = 0x8a, /*138*/ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_LOST_TEAR_DOWN = 0x8b /*139*/ +}; + +/******************************************************************************* + * P U B 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 + ******************************************************************************* + */ +uint32_t TdlsFrameGeneralIeAppend(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, uint8_t *pPkt); + +uint32_t /* TDLS_STATUS */ + +TdlsDataFrameSend_TearDown(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t *pPeerMac, + uint8_t ucActionCode, + uint8_t ucDialogToken, uint16_t u2StatusCode, + uint8_t *pAppendIe, uint32_t AppendIeLen); + +uint32_t /* TDLS_STATUS */ + +TdlsDataFrameSend_CONFIRM(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t *pPeerMac, + uint8_t ucActionCode, + uint8_t ucDialogToken, uint16_t u2StatusCode, + uint8_t *pAppendIe, uint32_t AppendIeLen); + +uint32_t /* TDLS_STATUS */ + +TdlsDataFrameSend_SETUP_REQ(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t *pPeerMac, + uint8_t ucActionCode, + uint8_t ucDialogToken, uint16_t u2StatusCode, + uint8_t *pAppendIe, uint32_t AppendIeLen); + +uint32_t /* TDLS_STATUS */ + +TdlsDataFrameSend_DISCOVERY_REQ(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t *pPeerMac, + uint8_t ucActionCode, + uint8_t ucDialogToken, uint16_t u2StatusCode, + uint8_t *pAppendIe, uint32_t AppendIeLen); + +uint32_t /* TDLS_STATUS */ + +TdlsDataFrameSend_SETUP_RSP(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t *pPeerMac, + uint8_t ucActionCode, + uint8_t ucDialogToken, uint16_t u2StatusCode, + uint8_t *pAppendIe, uint32_t AppendIeLen); + +uint32_t /* TDLS_STATUS */ + +TdlsDataFrameSend_DISCOVERY_RSP(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t *pPeerMac, + uint8_t ucActionCode, + uint8_t ucDialogToken, uint16_t u2StatusCode, + uint8_t *pAppendIe, uint32_t AppendIeLen); + +uint32_t TdlsexLinkOper(struct ADAPTER *prAdapter, + void *pvSetBuffer, uint32_t u4SetBufferLen, + uint32_t *pu4SetInfoLen); + +uint32_t TdlsexLinkMgt(struct ADAPTER *prAdapter, + void *pvSetBuffer, uint32_t u4SetBufferLen, + uint32_t *pu4SetInfoLen); + +void TdlsexEventHandle(struct GLUE_INFO *prGlueInfo, + uint8_t *prInBuf, uint32_t u4InBufLen); + +void TdlsEventTearDown(struct GLUE_INFO *prGlueInfo, + uint8_t *prInBuf, uint32_t u4InBufLen); + +void TdlsBssExtCapParse(struct STA_RECORD *prStaRec, + uint8_t *pucIE); + +uint32_t +TdlsSendChSwControlCmd(struct ADAPTER *prAdapter, + void *pvSetBuffer, uint32_t u4SetBufferLen, + uint32_t *pu4SetInfoLen); + +void TdlsHandleTxDoneStatus(struct ADAPTER *prAdapter, + enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* CFG_SUPPORT_TDLS */ + +#endif /* _TDLS_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/twt.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/twt.h new file mode 100644 index 0000000000000..afcdee8edab5c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/twt.h @@ -0,0 +1,246 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2017 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2017 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#ifndef _TWT_H +#define _TWT_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 TWT_MAX_FLOW_NUM 8 +#define TWT_MAX_WAKE_INTVAL_EXP (TWT_REQ_TYPE_TWT_WAKE_INTVAL_EXP >> \ + TWT_REQ_TYPE_TWT_WAKE_INTVAL_EXP_OFFSET) + +/******************************************************************************* +* 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 setting request type bit fields in TWT IE */ +#define SET_TWT_RT_REQUEST(fgReq) \ + (((fgReq) << TWT_REQ_TYPE_TWT_REQUEST_OFFSET) & \ + TWT_REQ_TYPE_TWT_REQUEST) + +#define SET_TWT_RT_SETUP_CMD(ucSetupCmd) \ + (((ucSetupCmd) << TWT_REQ_TYPE_TWT_SETUP_COMMAND_OFFSET) & \ + TWT_REQ_TYPE_TWT_SETUP_COMMAND) + +#define SET_TWT_RT_TRIGGER(fgTrigger) \ + (((fgTrigger) << TWT_REQ_TYPE_TRIGGER_OFFSET) & TWT_REQ_TYPE_TRIGGER) + +#define SET_TWT_RT_FLOW_TYPE(fgUnannounced) \ + (((fgUnannounced) << TWT_REQ_TYPE_FLOWTYPE_OFFSET) & \ + TWT_REQ_TYPE_FLOWTYPE) + +#define SET_TWT_RT_FLOW_ID(ucTWTFlowId) \ + (((ucTWTFlowId) << TWT_REQ_TYPE_TWT_FLOW_IDENTIFIER_OFFSET) & \ + TWT_REQ_TYPE_TWT_FLOW_IDENTIFIER) + +#define SET_TWT_RT_WAKE_INTVAL_EXP(ucWakeIntvlExponent) \ + (((ucWakeIntvlExponent) << TWT_REQ_TYPE_TWT_WAKE_INTVAL_EXP_OFFSET) & \ + TWT_REQ_TYPE_TWT_WAKE_INTVAL_EXP) + +#define SET_TWT_RT_PROTECTION(fgProtect) \ + (((fgProtect) << TWT_REQ_TYPE_TWT_PROTECTION_OFFSET) & \ + TWT_REQ_TYPE_TWT_PROTECTION) + +/* Macros for getting request type bit fields in TWT IE */ +#define GET_TWT_RT_REQUEST(u2ReqType) \ + (((u2ReqType) & TWT_REQ_TYPE_TWT_REQUEST) >> \ + TWT_REQ_TYPE_TWT_REQUEST_OFFSET) + +#define GET_TWT_RT_SETUP_CMD(u2ReqType) \ + (((u2ReqType) & TWT_REQ_TYPE_TWT_SETUP_COMMAND) >> \ + TWT_REQ_TYPE_TWT_SETUP_COMMAND_OFFSET) + +#define GET_TWT_RT_TRIGGER(u2ReqType) \ + (((u2ReqType) & TWT_REQ_TYPE_TRIGGER) >> TWT_REQ_TYPE_TRIGGER_OFFSET) + +#define GET_TWT_RT_FLOW_TYPE(u2ReqType) \ + (((u2ReqType) & TWT_REQ_TYPE_FLOWTYPE) >> TWT_REQ_TYPE_FLOWTYPE_OFFSET) + +#define GET_TWT_RT_FLOW_ID(u2ReqType) \ + (((u2ReqType) & TWT_REQ_TYPE_TWT_FLOW_IDENTIFIER) >> \ + TWT_REQ_TYPE_TWT_FLOW_IDENTIFIER_OFFSET) + +#define GET_TWT_RT_WAKE_INTVAL_EXP(u2ReqType) \ + (((u2ReqType) & TWT_REQ_TYPE_TWT_WAKE_INTVAL_EXP) >> \ + TWT_REQ_TYPE_TWT_WAKE_INTVAL_EXP_OFFSET) + +#define GET_TWT_RT_PROTECTION(u2ReqType) \ + (((u2ReqType) & TWT_REQ_TYPE_TWT_PROTECTION) >> \ + TWT_REQ_TYPE_TWT_PROTECTION_OFFSET) + +/* Macros to set TWT info field */ +#define SET_TWT_INFO_FLOW_ID(ucNextTWTCtrl) \ + (((ucNextTWTCtrl) << TWT_INFO_FLOW_ID_OFFSET) & TWT_INFO_FLOW_ID) + +#define SET_TWT_INFO_RESP_REQUESTED(ucNextTWTCtrl) \ + (((ucNextTWTCtrl) << TWT_INFO_RESP_REQUESTED_OFFSET) & \ + TWT_INFO_RESP_REQUESTED) + +#define SET_TWT_INFO_NEXT_TWT_REQ(ucNextTWTCtrl) \ + (((ucNextTWTCtrl) << TWT_INFO_NEXT_TWT_REQ_OFFSET) & \ + TWT_INFO_NEXT_TWT_REQ) + +#define SET_TWT_INFO_NEXT_TWT_SIZE(ucNextTWTCtrl) \ + (((ucNextTWTCtrl) << TWT_INFO_NEXT_TWT_SIZE_OFFSET) & \ + TWT_INFO_NEXT_TWT_SIZE) + +#define SET_TWT_INFO_BCAST_RESCHED(ucNextTWTCtrl) \ + (((ucNextTWTCtrl) << TWT_INFO_BCAST_RESCHED_OFFSET) & \ + TWT_INFO_BCAST_RESCHED) + +/* Macros to get TWT info field */ +#define GET_TWT_INFO_FLOW_ID(ucNextTWTCtrl) \ + (((ucNextTWTCtrl) & TWT_INFO_FLOW_ID) >> TWT_INFO_FLOW_ID_OFFSET) + +#define GET_TWT_INFO_RESP_REQUESTED(ucNextTWTCtrl) \ + (((ucNextTWTCtrl) & TWT_INFO_RESP_REQUESTED) >> \ + TWT_INFO_RESP_REQUESTED_OFFSET) + +#define GET_TWT_INFO_NEXT_TWT_REQ(ucNextTWTCtrl) \ + (((ucNextTWTCtrl) & TWT_INFO_NEXT_TWT_REQ) >> \ + TWT_INFO_NEXT_TWT_REQ_OFFSET) + +#define GET_TWT_INFO_NEXT_TWT_SIZE(ucNextTWTCtrl) \ + (((ucNextTWTCtrl) & TWT_INFO_NEXT_TWT_SIZE) >> \ + TWT_INFO_NEXT_TWT_SIZE_OFFSET) + +#define GET_TWT_INFO_BCAST_RESCHED(ucNextTWTCtrl) \ + (((ucNextTWTCtrl) & TWT_INFO_BCAST_RESCHED) >> \ + TWT_INFO_BCAST_RESCHED_OFFSET) + +/* Next TWT from the packet should be little endian */ +#define GET_48_BITS_NEXT_TWT_FROM_PKT(pMem) \ + ((u_int64_t)(*((u_int8_t *)(pMem))) | \ + ((u_int64_t)(*(((u_int8_t *)(pMem)) + 1)) >> 8) | \ + ((u_int64_t)(*(((u_int8_t *)(pMem)) + 2)) >> 16) | \ + ((u_int64_t)(*(((u_int8_t *)(pMem)) + 3)) >> 24) | \ + ((u_int64_t)(*(((u_int8_t *)(pMem)) + 4)) >> 32) | \ + ((u_int64_t)(*(((u_int8_t *)(pMem)) + 5)) >> 40)) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +void twtProcessS1GAction( + struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); + +uint32_t twtSendSetupFrame( + struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + u_int8_t ucTWTFlowId, + struct _TWT_PARAMS_T *prTWTParams, + PFN_TX_DONE_HANDLER pfTxDoneHandler); + +uint32_t twtSendTeardownFrame( + struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + u_int8_t ucTWTFlowId, + PFN_TX_DONE_HANDLER pfTxDoneHandler); + +uint32_t twtSendInfoFrame( + struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + u_int8_t ucTWTFlowId, + struct _NEXT_TWT_INFO_T *prNextTWTInfo, + PFN_TX_DONE_HANDLER pfTxDoneHandler); + +u_int8_t twtGetTxSetupFlowId( + struct MSDU_INFO *prMsduInfo); + +u_int8_t twtGetTxTeardownFlowId( + struct MSDU_INFO *prMsduInfo); + +uint8_t twtGetTxInfoFlowId( + struct MSDU_INFO *prMsduInfo); + +static inline u_int8_t twtGetNextTWTByteCnt(u_int8_t ucNextTWTSize) +{ + return (ucNextTWTSize == NEXT_TWT_SUBFIELD_64_BITS) ? 8 : + ((ucNextTWTSize == NEXT_TWT_SUBFIELD_32_BITS) ? 4 : + ((ucNextTWTSize == NEXT_TWT_SUBFIELD_48_BITS) ? 6 : 0)); +} +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _TWT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/twt_planner.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/twt_planner.h new file mode 100644 index 0000000000000..deb543eb78349 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/twt_planner.h @@ -0,0 +1,177 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2017 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2017 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#ifndef _TWT_PLANNER_H +#define _TWT_PLANNER_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 +******************************************************************************** +*/ + +struct _TWT_FLOW_T { + struct _TWT_PARAMS_T rTWTParams; + struct _TWT_PARAMS_T rTWTPeerParams; + u_int64_t u8NextTWT; +}; + +struct _TWT_AGRT_T { + u_int8_t fgValid; + u_int8_t ucAgrtTblIdx; + u_int8_t ucBssIdx; + u_int8_t ucFlowId; + struct _TWT_PARAMS_T rTWTAgrt; +}; + +struct _TWT_PLANNER_T { + struct _TWT_AGRT_T arTWTAgrtTbl[TWT_AGRT_MAX_NUM]; +}; + +/******************************************************************************* +* P U B 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 TSF_OFFSET_FOR_EMU (1 * 1000 * 1000) /* after 1 sec */ +#define TSF_OFFSET_FOR_AGRT_ADD (5 * 1000 * 1000) /* after 5 sec */ +#define TSF_OFFSET_FOR_AGRT_RESUME (5 * 1000 * 1000) /* after 5 sec */ + +/* Definitions for action control of TWT params */ +enum { + TWT_PARAM_ACTION_NONE = 0, + TWT_PARAM_ACTION_ADD_BYPASS = 1, /* bypass nego & add an agrt */ + TWT_PARAM_ACTION_DEL_BYPASS = 2, /* bypass proto & del an agrt */ + TWT_PARAM_ACTION_MOD_BYPASS = 3, /* bypass proto & modify an agrt */ + TWT_PARAM_ACTION_ADD = 4, + TWT_PARAM_ACTION_DEL = 5, + TWT_PARAM_ACTION_SUSPEND = 6, + TWT_PARAM_ACTION_RESUME = 7, + TWT_PARAM_ACTION_MAX +}; + +#define IS_TWT_PARAM_ACTION_ADD_BYPASS(ucCtrlAction) \ + ((ucCtrlAction) == TWT_PARAM_ACTION_ADD_BYPASS) +#define IS_TWT_PARAM_ACTION_DEL_BYPASS(ucCtrlAction) \ + ((ucCtrlAction) == TWT_PARAM_ACTION_DEL_BYPASS) +#define IS_TWT_PARAM_ACTION_MOD_BYPASS(ucCtrlAction) \ + ((ucCtrlAction) == TWT_PARAM_ACTION_MOD_BYPASS) +#define IS_TWT_PARAM_ACTION_ADD(ucCtrlAction) \ + ((ucCtrlAction) == TWT_PARAM_ACTION_ADD) +#define IS_TWT_PARAM_ACTION_DEL(ucCtrlAction) \ + ((ucCtrlAction) == TWT_PARAM_ACTION_DEL) +#define IS_TWT_PARAM_ACTION_SUSPEND(ucCtrlAction) \ + ((ucCtrlAction) == TWT_PARAM_ACTION_SUSPEND) +#define IS_TWT_PARAM_ACTION_RESUME(ucCtrlAction) \ + ((ucCtrlAction) == TWT_PARAM_ACTION_RESUME) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +void twtPlannerSetParams( + struct ADAPTER *prAdapter, + struct MSG_HDR *prMsgHdr); + +uint32_t twtPlannerReset( + struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo); + +void twtPlannerRxNegoResult( + struct ADAPTER *prAdapter, + struct MSG_HDR *prMsgHdr); + +void twtPlannerSuspendDone( + struct ADAPTER *prAdapter, + struct MSG_HDR *prMsgHdr); + +void twtPlannerTeardownDone( + struct ADAPTER *prAdapter, + struct MSG_HDR *prMsgHdr); + +void twtPlannerResumeDone( + struct ADAPTER *prAdapter, + struct MSG_HDR *prMsgHdr); + +void twtPlannerRxInfoFrm( + struct ADAPTER *prAdapter, + struct MSG_HDR *prMsgHdr); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _TWT_PLANNER_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/twt_req_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/twt_req_fsm.h new file mode 100644 index 0000000000000..d39a9908191d1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/twt_req_fsm.h @@ -0,0 +1,154 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2017 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2017 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#ifndef _TWT_REQ_FSM_H +#define _TWT_REQ_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 +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +enum _ENUM_TWT_REQUESTER_STATE_T { + TWT_REQ_STATE_IDLE = 0, + TWT_REQ_STATE_REQTX, + TWT_REQ_STATE_WAIT_RSP, + TWT_REQ_STATE_SUSPENDING, + TWT_REQ_STATE_SUSPENDED, + TWT_REQ_STATE_RESUMING, + TWT_REQ_STATE_TEARING_DOWN, + TWT_REQ_STATE_RX_TEARDOWN, + TWT_REQ_STATE_RX_INFOFRM, + TWT_REQ_STATE_NUM +}; + +/******************************************************************************* +* P U B 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 +******************************************************************************** +*/ + +u_int32_t +twtReqFsmRunEventTxDone( + struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +void twtReqFsmRunEventRxSetup( + struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb, + struct STA_RECORD *prStaRec, + u_int8_t ucTWTFlowId); + +void twtReqFsmRunEventRxTeardown( + struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb, + struct STA_RECORD *prStaRec, + u_int8_t ucTWTFlowId); + +void twtReqFsmRunEventRxInfoFrm( + struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb, + struct STA_RECORD *prStaRec, + u_int8_t ucTWTFlowId, + struct _NEXT_TWT_INFO_T *prNextTWTInfo); + +void twtReqFsmRunEventStart( + struct ADAPTER *prAdapter, + struct MSG_HDR *prMsgHdr); + +void twtReqFsmRunEventTeardown( + struct ADAPTER *prAdapter, + struct MSG_HDR *prMsgHdr); + +void twtReqFsmRunEventSuspend( + struct ADAPTER *prAdapter, + struct MSG_HDR *prMsgHdr); + +void twtReqFsmRunEventResume( + struct ADAPTER *prAdapter, + struct MSG_HDR *prMsgHdr); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _TWT_REQ_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/wapi.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/wapi.h new file mode 100644 index 0000000000000..f1526409dcd87 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/wapi.h @@ -0,0 +1,133 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + + +#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) ((struct WAPI_INFO_ELEM *) fp) + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +u_int8_t wapiParseWapiIE(IN struct WAPI_INFO_ELEM + *prInfoElem, OUT struct WAPI_INFO *prWapiInfo); + +u_int8_t wapiPerformPolicySelection( + IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBss, + IN uint8_t ucBssIndex); + +/* BOOLEAN */ +/* wapiUpdateTxKeyIdx ( */ +/* IN P_STA_RECORD_T prStaRec, */ +/* IN UINT_8 ucWlanIdx */ +/* ); */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#endif +#endif /* _WAPI_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/wlan_typedef.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/wlan_typedef.h new file mode 100644 index 0000000000000..99ab88227616d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/wlan_typedef.h @@ -0,0 +1,156 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + + +#ifndef _WLAN_TYPEDEF_H +#define _WLAN_TYPEDEF_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ +#define NIC_TX_ENABLE_SECOND_HW_QUEUE 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 + ******************************************************************************* + */ +/* Type definition for BSS_INFO structure, to describe the + * attributes used in a common BSS. + */ +struct BSS_INFO; /* declare BSS_INFO_T */ +struct BSS_INFO; /* declare P2P_DEV_INFO_T */ + + +struct AIS_SPECIFIC_BSS_INFO; /* declare AIS_SPECIFIC_BSS_INFO_T */ +struct P2P_SPECIFIC_BSS_INFO; /* declare P2P_SPECIFIC_BSS_INFO_T */ +struct BOW_SPECIFIC_BSS_INFO; /* declare BOW_SPECIFIC_BSS_INFO_T */ +/* CFG_SUPPORT_WFD */ +struct WFD_CFG_SETTINGS; /* declare WFD_CFG_SETTINGS_T */ + +/* BSS related structures */ +/* Type definition for BSS_DESC structure, to describe parameter + * sets of a particular BSS + */ +struct BSS_DESC; /* declare BSS_DESC */ + +#if CFG_SUPPORT_PASSPOINT +struct HS20_INFO; /* declare HS20_INFO_T */ +#endif /* CFG_SUPPORT_PASSPOINT */ + +/* Tc Resource index */ +enum ENUM_TRAFFIC_CLASS_INDEX { + /*First HW queue */ + TC0_INDEX = 0, /* HIF TX: AC0 packets */ + TC1_INDEX, /* HIF TX: AC1 packets */ + TC2_INDEX, /* HIF TX: AC2 packets */ + TC3_INDEX, /* HIF TX: AC3 packets */ + TC4_INDEX, /* HIF TX: CPU packets */ + +#if NIC_TX_ENABLE_SECOND_HW_QUEUE + /* Second HW queue */ + TC5_INDEX, /* HIF TX: AC10 packets */ + TC6_INDEX, /* HIF TX: AC11 packets */ + TC7_INDEX, /* HIF TX: AC12 packets */ + TC8_INDEX, /* HIF TX: AC13 packets */ +#endif + + TC_NUM /* Maximum number of Traffic Classes. */ +}; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#endif /* _WLAN_TYPEDEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/wmm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/wmm.h new file mode 100644 index 0000000000000..b31b86f4c232f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/wmm.h @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. + * If not, see . + */ + +#ifndef WMM_HDR_H +#define WMM_HDR_H + +#define VENDOR_OUI_TYPE_TSRS 8 +#define VENDOR_OUI_TYPE_TSM 7 +#define VENDOR_OUI_TYPE_EDCALIFE 9 +#define WLAN_MAC_ACTION_ADDTS_LEN (WLAN_MAC_MGMT_HEADER_HTC_LEN + 66) +#define WLAN_MAC_ACTION_DELTS_LEN (WLAN_MAC_MGMT_HEADER_HTC_LEN + 7) +#define TSPEC_POLICY_CHECK_INTERVAL 2500 /* unit ms */ + +#define WMM_TS_STATUS_ADMISSION_ACCEPTED 0 +#define WMM_TS_STATUS_ADDTS_INVALID_PARAM 1 +#define WMM_TS_STATUS_ADDTS_REFUSED 3 +#define WMM_TS_STATUS_ASSOC_QOS_FAILED 0xc8 +#define WMM_TS_STATUS_POLICY_CONFIG_REFUSED 0xc9 +#define WMM_TS_STATUS_ASSOC_INSUFFICIENT_BANDWIDTH 0xca +#define WMM_TS_STATUS_ASSOC_INVALID_PARAM 0xcb + +#define CFG_SUPPORT_SOFT_ACM 1 /* do Admission Control in driver */ +/* + * In WMM, TSs are identified with TIDs values 0 through 7. Any TID may + * map onto any UP and thus onto any AC, however for each AC used between + * an RA and TA, only the following combinations are valid: + * No TS, One uplink TS, one Download link TS, one uplink and one uplink + * TS, one bi-directional TS. + * so maximum 8 TSs are allowed in a RA & TA context. + */ +#define WMM_TSPEC_ID_NUM 8 + +/*WMM-2.2.11 WMM TSPEC IE*/ +#define ELEM_MAX_LEN_WMM_TSPEC 61 + +enum WMM_ADDTS_STATUS { + ADDTS_ACCEPTED = 0, + ADDTS_INVALID_PARAMS = 1, + ADDTS_REFUSED = 2 +}; + +enum TSPEC_OP_CODE { + TX_ADDTS_REQ, + RX_ADDTS_RSP, + TX_DELTS_REQ, + RX_DELTS_REQ, + DISC_DELTS_REQ, + UPDATE_TS_REQ +}; + +enum QOS_TS_STATE { + QOS_TS_INACTIVE, + QOS_TS_ACTIVE, + QOS_TS_SETUPING, + QOS_TS_STATE_MAX +}; + +enum TSPEC_DIR { + UPLINK_TS = 0, + DOWNLINK_TS = 1, + BI_DIR_TS = 3 +}; + +struct TSPEC_INFO { + struct TIMER rAddTsTimer; + uint8_t ucToken; + u_int8_t fgUapsd; + enum ENUM_ACI eAC:8; + enum TSPEC_DIR eDir:8; + enum QOS_TS_STATE eState:8; + /* debug information */ + uint16_t u2MediumTime; + uint32_t u4PhyRate; + uint8_t ucTid; +}; + +struct TSM_TRIGGER_COND { + uint8_t ucCondition; + uint8_t ucAvgErrThreshold; + uint8_t ucConsecutiveErr; + uint8_t ucDelayThreshold; + uint8_t ucMeasureCount; + /* In this time frame, for one condition, only once report is allowed */ + uint8_t ucTriggerTimeout; +}; + +struct RM_TSM_REQ { + uint16_t u2Duration; /* unit: TUs */ + uint8_t aucPeerAddr[MAC_ADDR_LEN]; + uint8_t ucToken; + uint8_t ucTID; + uint8_t ucACI; + uint8_t ucB0Range; /* 2^(i-1)*ucB0Range =< delay < 2^i * ucB0Range */ + struct TSM_TRIGGER_COND rTriggerCond; +}; + +struct ACTIVE_RM_TSM_REQ { + struct LINK_ENTRY rLinkEntry; + struct RM_TSM_REQ *prTsmReq; + struct TIMER rTsmTimer; + uint8_t ucBssIdx; +}; + +#if CFG_SUPPORT_SOFT_ACM +struct SOFT_ACM_CTRL { + uint32_t u4RemainTime; + uint32_t u4AdmittedTime; + uint32_t u4IntervalEndSec; + uint16_t u2DeqNum; +}; +#endif + +struct WMM_INFO { + /* A TS is identified uniquely by its TID value within the context of + ** the RA and TA + ** the index is TID for this array + */ + struct TSPEC_INFO arTsInfo[WMM_TSPEC_ID_NUM]; + struct LINK rActiveTsmReq; + OS_SYSTIME rTriggeredTsmRptTime; + struct TIMER rTsmTimer; +#if CFG_SUPPORT_SOFT_ACM + struct TIMER rAcmDeqTimer; + struct SOFT_ACM_CTRL arAcmCtrl[ACI_NUM]; /* 0 ~ 3, BE, BK, VI, VO */ +#endif +}; + +struct WMM_ADDTS_RSP_STEP_PARAM { + uint8_t ucDlgToken; + uint8_t ucStatusCode; + uint8_t ucApsd; + enum TSPEC_DIR eDir:8; + uint16_t u2EdcaLifeTime; + uint16_t u2MediumTime; + uint32_t u4PhyRate; +}; + +struct MSG_TS_OPERATE { + struct MSG_HDR rMsgHdr; + enum TSPEC_OP_CODE eOpCode; + uint8_t ucTid; + struct PARAM_QOS_TSPEC rTspecParam; + uint8_t ucBssIdx; +}; + +#define WMM_TSINFO_TRAFFIC_TYPE(tsinfo) (tsinfo & BIT(0)) +#define WMM_TSINFO_TSID(tsinfo) ((tsinfo & BITS(1, 4)) >> 1) +#define WMM_TSINFO_DIR(tsinfo) ((tsinfo & BITS(5, 6)) >> 5) +#define WMM_TSINFO_AC(tsinfo) ((tsinfo & BITS(7, 8)) >> 7) +#define WMM_TSINFO_PSB(tsinfo) ((tsinfo & BIT(10)) >> 10) +#define WMM_TSINFO_UP(tsinfo) ((tsinfo & BITS(11, 13)) >> 11) + +#define TSM_TRIGGER_CONDITION_ALL BITS(0, 2) +#define TSM_TRIGGER_AVG BIT(0) +#define TSM_TRIGGER_CONSECUTIVE BIT(1) +#define TSM_TIRGGER_DELAY BIT(2) + +extern uint8_t const aucUp2ACIMap[8]; +void wmmFillTsinfo(struct PARAM_QOS_TSINFO *prTsInfo, uint8_t *pucTsInfo); +void wmmSetupTspecTimeOut(struct ADAPTER *prAdapter, unsigned long ulParam); +void wmmStartTsmMeasurement(struct ADAPTER *prAdapter, unsigned long ulParam, + uint8_t ucBssIndex); +void wmmRunEventTSOperate(struct ADAPTER *prAdapter, struct MSG_HDR *prMsgHdr); +u_int8_t wmmParseQosAction(struct ADAPTER *prAdapter, struct SW_RFB *prSwRfb); +u_int8_t wmmParseTspecIE(struct ADAPTER *prAdapter, uint8_t *pucIE, + struct PARAM_QOS_TSPEC *prTspec); +void wmmTspecSteps(struct ADAPTER *prAdapter, uint8_t ucTid, + enum TSPEC_OP_CODE eOpCode, void *prStepParams, uint8_t ucBssIndex); +uint8_t wmmHasActiveTspec(struct WMM_INFO *prWmmInfo); +void wmmNotifyDisconnected(struct ADAPTER *prAdapter, uint8_t ucBssIndex); +void wmmComposeTsmRpt(struct ADAPTER *prAdapter, struct CMD_INFO *prCmdInfo, + uint8_t *pucEventBuf); +void wmmInit(IN struct ADAPTER *prAdapter); +void wmmUnInit(IN struct ADAPTER *prAdapter); +u_int8_t wmmTsmIsOngoing(struct ADAPTER *prAdapter, uint8_t ucBssIndex); +void wmmRemoveAllTsmMeasurement(struct ADAPTER *prAdapter, + u_int8_t fgOnlyTriggered, uint8_t ucBssIndex); +uint8_t wmmCalculateUapsdSetting(struct ADAPTER *prAdapter, + uint8_t ucBssIndex); +uint32_t wmmDumpActiveTspecs(struct ADAPTER *prAdapter, uint8_t *pucBuffer, + uint16_t u2BufferLenu, uint8_t ucBssIndex); +#if CFG_SUPPORT_SOFT_ACM +u_int8_t wmmAcmCanDequeue(struct ADAPTER *prAdapter, uint8_t ucAc, + uint32_t u4PktTxTime, uint8_t ucBssIndex); +void wmmAcmTxStatistic(struct ADAPTER *prAdapter, uint8_t ucAc, + uint32_t u4Remain, uint16_t u2DeqNum); + +uint32_t wmmCalculatePktUsedTime(struct BSS_INFO *prBssInfo, + struct STA_RECORD *prStaRec, + uint16_t u2PktLen); +void wmmPrepareFastUsedTimeCal(struct ADAPTER *prAdapter); +uint32_t wmmFastCalPktUsedTime(struct WMM_INFO *prWmmInfo, uint8_t ucAc, + uint16_t u2PktLen); +#endif /* CFG_SUPPORT_SOFT_ACM */ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/wnm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/wnm.h new file mode 100644 index 0000000000000..0f71de00afa7e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4m/include/mgmt/wnm.h @@ -0,0 +1,184 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + + +#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 + ******************************************************************************* + */ + +struct TIMINGMSMT_PARAM { + u_int8_t fgInitiator; + uint8_t ucTrigger; + uint8_t ucDialogToken; /* Dialog Token */ + uint8_t ucFollowUpDialogToken; /* Follow Up Dialog Token */ + uint32_t u4ToD; /* Timestamp of Departure [10ns] */ + uint32_t u4ToA; /* Timestamp of Arrival [10ns] */ +}; + +struct BSS_TRANSITION_MGT_PARAM_T { + /* for Query */ + uint8_t ucDialogToken; + uint8_t ucQueryReason; + /* for Request */ + uint8_t ucRequestMode; + uint16_t u2DisassocTimer; + uint16_t u2TermDuration; + uint8_t aucTermTsf[8]; + uint8_t ucSessionURLLen; + uint8_t aucSessionURL[255]; + /* for Respone */ + u_int8_t fgPendingResponse:1; + u_int8_t fgUnsolicitedReq:1; + u_int8_t fgReserved:6; + uint8_t ucStatusCode; + uint8_t ucTermDelay; + uint8_t aucTargetBssid[MAC_ADDR_LEN]; + uint8_t *pucOurNeighborBss; + uint16_t u2OurNeighborBssLen; +}; + +/******************************************************************************* + * P U B 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 BTM_REQ_MODE_CAND_INCLUDED_BIT BIT(0) +#define BTM_REQ_MODE_ABRIDGED BIT(1) +#define BTM_REQ_MODE_DISC_IMM BIT(2) +#define BTM_REQ_MODE_BSS_TERM_INCLUDE BIT(3) +#define BTM_REQ_MODE_ESS_DISC_IMM BIT(4) + +#define BSS_TRANSITION_MGT_STATUS_ACCEPT 0 +#define BSS_TRANSITION_MGT_STATUS_UNSPECIFIED 1 +#define BSS_TRANSITION_MGT_STATUS_NEED_SCAN 2 +#define BSS_TRANSITION_MGT_STATUS_CAND_NO_CAPACITY 3 +#define BSS_TRANSITION_MGT_STATUS_TERM_UNDESIRED 4 +#define BSS_TRANSITION_MGT_STATUS_TERM_DELAY_REQUESTED 5 +#define BSS_TRANSITION_MGT_STATUS_CAND_LIST_PROVIDED 6 +#define BSS_TRANSITION_MGT_STATUS_CAND_NO_CANDIDATES 7 +#define BSS_TRANSITION_MGT_STATUS_LEAVING_ESS 8 + +/* 802.11v: define Transtion and Transition Query reasons */ +#define BSS_TRANSITION_BETTER_AP_FOUND 6 +#define BSS_TRANSITION_LOW_RSSI 16 +#define BSS_TRANSITION_INCLUDE_PREFER_CAND_LIST 19 +#define BSS_TRANSITION_LEAVING_ESS 20 + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +void wnmWNMAction(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +void wnmReportTimingMeas(IN struct ADAPTER *prAdapter, + IN uint8_t ucStaRecIndex, IN uint32_t u4ToD, + IN uint32_t u4ToA); + +#if WNM_UNIT_TEST +void wnmTimingMeasUnitTest1(struct ADAPTER *prAdapter, + uint8_t ucStaRecIndex); +#endif + +void wnmRecvBTMRequest(IN struct ADAPTER *prAdapter, IN struct SW_RFB *prSwRfb); + +void wnmSendBTMQueryFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +void wnmSendBTMResponseFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +uint8_t wnmGetBtmToken(void); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _WNM_H */ From 1215d8cf029fddd54292bcf2f4a820feb9f395ee Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 22:17:38 +0800 Subject: [PATCH 26/32] Add files via upload --- .../wlan/core/gen4-mt7663/Android.mk | 91 + .../wlan/core/gen4-mt7663/Makefile | 515 + .../wlan/core/gen4-mt7663/Makefile.ce | 312 + .../wlan/core/gen4-mt7663/Makefile.x86 | 227 + .../chips/common/cmm_asic_connac.c | 1141 + .../core/gen4-mt7663/chips/common/fw_dl.c | 2070 ++ .../core/gen4-mt7663/chips/connac/connac.c | 315 + .../gen4-mt7663/chips/connac2x2/connac2x2.c | 315 + .../core/gen4-mt7663/chips/mt6632/mt6632.c | 437 + .../core/gen4-mt7663/chips/mt7663/mt7663.c | 327 + .../core/gen4-mt7663/chips/mt7668/mt7668.c | 513 + .../wlan/core/gen4-mt7663/common/debug.c | 555 + .../wlan/core/gen4-mt7663/common/dump.c | 463 + .../wlan/core/gen4-mt7663/common/wlan_bow.c | 3218 +++ .../wlan/core/gen4-mt7663/common/wlan_lib.c | 10702 +++++++++ .../wlan/core/gen4-mt7663/common/wlan_oid.c | 17391 ++++++++++++++ .../wlan/core/gen4-mt7663/common/wlan_p2p.c | 1740 ++ .../core/gen4-mt7663/init.wlan_mt7663_drv.rc | 3 + .../wlan/core/gen4-mt7663/nic/cmd_buf.c | 322 + .../wlan/core/gen4-mt7663/nic/nic.c | 4870 ++++ .../wlan/core/gen4-mt7663/nic/nic_cmd_event.c | 5950 +++++ .../wlan/core/gen4-mt7663/nic/nic_pwr_mgt.c | 424 + .../wlan/core/gen4-mt7663/nic/nic_rate.c | 459 + .../wlan/core/gen4-mt7663/nic/nic_rx.c | 4597 ++++ .../wlan/core/gen4-mt7663/nic/nic_tx.c | 5369 +++++ .../wlan/core/gen4-mt7663/nic/nic_umac.c | 464 + .../wlan/core/gen4-mt7663/nic/p2p_nic.c | 277 + .../wlan/core/gen4-mt7663/nic/que_mgt.c | 8135 +++++++ .../core/gen4-mt7663/os/linux/gl_ate_agent.c | 2562 +++ .../wlan/core/gen4-mt7663/os/linux/gl_bow.c | 1173 + .../core/gen4-mt7663/os/linux/gl_cfg80211.c | 7584 +++++++ .../core/gen4-mt7663/os/linux/gl_custom.c | 309 + .../core/gen4-mt7663/os/linux/gl_hook_api.c | 4153 ++++ .../wlan/core/gen4-mt7663/os/linux/gl_init.c | 4277 ++++ .../wlan/core/gen4-mt7663/os/linux/gl_kal.c | 8508 +++++++ .../wlan/core/gen4-mt7663/os/linux/gl_p2p.c | 2120 ++ .../gen4-mt7663/os/linux/gl_p2p_cfg80211.c | 4565 ++++ .../core/gen4-mt7663/os/linux/gl_p2p_init.c | 275 + .../core/gen4-mt7663/os/linux/gl_p2p_kal.c | 2017 ++ .../wlan/core/gen4-mt7663/os/linux/gl_proc.c | 3033 +++ .../core/gen4-mt7663/os/linux/gl_qa_agent.c | 8999 ++++++++ .../wlan/core/gen4-mt7663/os/linux/gl_rst.c | 529 + .../core/gen4-mt7663/os/linux/gl_sec.o.new | Bin 0 -> 19504 bytes .../core/gen4-mt7663/os/linux/gl_vendor.c | 1407 ++ .../wlan/core/gen4-mt7663/os/linux/gl_wext.c | 5001 ++++ .../core/gen4-mt7663/os/linux/gl_wext_priv.c | 18893 ++++++++++++++++ .../core/gen4-mt7663/os/linux/hif/axi/axi.c | 1318 ++ .../os/linux/hif/axi/include/hif.h | 308 + .../os/linux/hif/common/dbg_pdma.c | 1597 ++ .../os/linux/hif/common/hal_pdma.c | 2537 +++ .../os/linux/hif/common/include/hif_pdma.h | 473 + .../os/linux/hif/common/kal_pdma.c | 942 + .../core/gen4-mt7663/os/linux/hif/ehpi/arm.c | 539 + .../gen4-mt7663/os/linux/hif/ehpi/colibri.c | 541 + .../core/gen4-mt7663/os/linux/hif/ehpi/ehpi.c | 414 + .../os/linux/hif/ehpi/include/colibri.h | 190 + .../os/linux/hif/ehpi/include/hif.h | 142 + .../os/linux/hif/pcie/include/hif.h | 285 + .../core/gen4-mt7663/os/linux/hif/pcie/pcie.c | 1216 + .../core/gen4-mt7663/os/linux/hif/sdio/arm.c | 62 + .../gen4-mt7663/os/linux/hif/sdio/hal_api.c | 3082 +++ .../os/linux/hif/sdio/include/hif.h | 453 + .../os/linux/hif/sdio/include/hif_sdio.h | 267 + .../os/linux/hif/sdio/include/mtk_porting.h | 89 + .../os/linux/hif/sdio/include/sdio_ring.h | 107 + .../hif/sdio/include/test_driver_sdio_ops.h | 48 + .../core/gen4-mt7663/os/linux/hif/sdio/sdio.c | 1979 ++ .../gen4-mt7663/os/linux/hif/sdio/sdio_ring.c | 368 + .../os/linux/hif/sdio/sdio_test_driver_core.c | 448 + .../os/linux/hif/sdio/sdio_test_driver_ops.c | 194 + .../core/gen4-mt7663/os/linux/hif/sdio/x86.c | 62 + .../gen4-mt7663/os/linux/hif/usb/hal_api.c | 1927 ++ .../os/linux/hif/usb/include/cust_usb_id.h | 127 + .../os/linux/hif/usb/include/hif.h | 459 + .../os/linux/hif/usb/include/hif_usb.h | 131 + .../core/gen4-mt7663/os/linux/hif/usb/usb.c | 1670 ++ .../os/linux/include/gl_ate_agent.h | 288 + .../os/linux/include/gl_cfg80211.h | 754 + .../os/linux/include/gl_hook_api.h | 335 + .../gen4-mt7663/os/linux/include/gl_kal.h | 1591 ++ .../core/gen4-mt7663/os/linux/include/gl_os.h | 1327 ++ .../os/linux/include/gl_p2p_ioctl.h | 877 + .../gen4-mt7663/os/linux/include/gl_p2p_kal.h | 376 + .../gen4-mt7663/os/linux/include/gl_p2p_os.h | 371 + .../os/linux/include/gl_qa_agent.h | 356 + .../gen4-mt7663/os/linux/include/gl_rst.h | 298 + .../gen4-mt7663/os/linux/include/gl_sec.h | 79 + .../gen4-mt7663/os/linux/include/gl_typedef.h | 272 + .../gen4-mt7663/os/linux/include/gl_vendor.h | 709 + .../gen4-mt7663/os/linux/include/gl_wext.h | 399 + .../os/linux/include/gl_wext_priv.h | 599 + .../wlan/core/gen4-mt7663/os/linux/platform.c | 558 + .../wlan/core/gen4-mt7663/os/version.h | 138 + .../gen4-mt7663/prealloc/include/prealloc.h | 120 + .../wlan/core/gen4-mt7663/prealloc/prealloc.c | 314 + 95 files changed, 178343 insertions(+) create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/Android.mk create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/Makefile create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/Makefile.ce create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/Makefile.x86 create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/common/cmm_asic_connac.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/common/fw_dl.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/connac/connac.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/connac2x2/connac2x2.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/mt6632/mt6632.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/mt7663/mt7663.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/mt7668/mt7668.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/common/debug.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/common/dump.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/common/wlan_bow.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/common/wlan_lib.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/common/wlan_oid.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/common/wlan_p2p.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/init.wlan_mt7663_drv.rc create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/cmd_buf.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic_cmd_event.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic_pwr_mgt.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic_rate.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic_rx.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic_tx.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic_umac.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/p2p_nic.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/que_mgt.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_ate_agent.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_bow.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_cfg80211.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_custom.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_hook_api.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_init.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_kal.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_p2p.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_p2p_cfg80211.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_p2p_init.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_p2p_kal.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_proc.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_qa_agent.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_rst.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_sec.o.new create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_vendor.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_wext.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_wext_priv.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/axi/axi.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/axi/include/hif.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/common/dbg_pdma.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/common/hal_pdma.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/common/include/hif_pdma.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/common/kal_pdma.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/ehpi/arm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/ehpi/colibri.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/ehpi/ehpi.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/ehpi/include/colibri.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/ehpi/include/hif.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/pcie/include/hif.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/pcie/pcie.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/arm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/hal_api.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/include/hif.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/include/hif_sdio.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/include/mtk_porting.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/include/sdio_ring.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/include/test_driver_sdio_ops.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/sdio.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/sdio_ring.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/sdio_test_driver_core.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/sdio_test_driver_ops.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/x86.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/usb/hal_api.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/usb/include/cust_usb_id.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/usb/include/hif.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/usb/include/hif_usb.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/usb/usb.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_ate_agent.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_cfg80211.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_hook_api.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_kal.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_os.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_p2p_ioctl.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_p2p_kal.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_p2p_os.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_qa_agent.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_rst.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_sec.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_typedef.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_vendor.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_wext.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_wext_priv.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/platform.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/version.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/prealloc/include/prealloc.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/prealloc/prealloc.c diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/Android.mk b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/Android.mk new file mode 100644 index 0000000000000..68c851dc4e889 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/Android.mk @@ -0,0 +1,91 @@ +# 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) 2017. 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. +############################################################################### +# Generally Android.mk can not get KConfig setting +# we can use this way to get +# include the final KConfig +# but there is no $(AUTO_CONF) at the first time (no out folder) when make +# +#ifneq (,$(wildcard $(AUTO_CONF))) +#include $(AUTO_CONF) +#include $(CLEAR_VARS) +#endif + +############################################################################### +############################################################################### +# Generally Android.mk can not get KConfig setting # +# # +# do not have any KConfig checking in Android.mk # +# do not have any KConfig checking in Android.mk # +# do not have any KConfig checking in Android.mk # +# # +# e.g. ifeq ($(CONFIG_MTK_COMBO_WIFI), m) # +# xxxx # +# endif # +# # +# e.g. ifneq ($(filter "MT6632",$(CONFIG_MTK_COMBO_CHIP)),) # +# xxxx # +# endif # +# # +# All the KConfig checking should move to Makefile for each module # +# All the KConfig checking should move to Makefile for each module # +# All the KConfig checking should move to Makefile for each module # +# # +############################################################################### +############################################################################### + +LOCAL_PATH := $(call my-dir) +ifeq ($(MTK_WLAN_SUPPORT), yes) +ifneq (true,$(strip $(TARGET_NO_KERNEL))) +ifeq (MT7663,$(strip $(MTK_COMBO_CHIP))) +include $(CLEAR_VARS) +LOCAL_MODULE := wlan_drv_gen4_mt7663_prealloc.ko +LOCAL_PROPRIETARY_MODULE := true +LOCAL_MODULE_OWNER := mtk +LOCAL_INIT_RC := init.wlan_mt7663_drv.rc +LOCAL_SRC_FILES := $(patsubst $(LOCAL_PATH)/%,%,$(shell find $(LOCAL_PATH) -type f -name '*.[cho]')) Makefile + +include $(MTK_KERNEL_MODULE) + +include $(CLEAR_VARS) +LOCAL_MODULE := wlan_drv_gen4_mt7663.ko +LOCAL_PROPRIETARY_MODULE := true +LOCAL_MODULE_OWNER := mtk +LOCAL_INIT_RC := init.wlan_mt7663_drv.rc +LOCAL_SRC_FILES := $(patsubst $(LOCAL_PATH)/%,%,$(shell find $(LOCAL_PATH) -type f -name '*.[cho]')) Makefile + +include $(MTK_KERNEL_MODULE) +endif +endif +endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/Makefile b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/Makefile new file mode 100644 index 0000000000000..c25556ed4c090 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/Makefile @@ -0,0 +1,515 @@ +# --------------------------------------------------- +# ALPS Setting +# --------------------------------------------------- +ifneq ($(KERNEL_OUT),) + ccflags-y += -imacros $(KERNEL_OUT)/include/generated/autoconf.h +endif + +ifeq ($(KBUILD_MODPOST_FAIL_ON_WARNINGS),) + # Force build fail on modpost warning + KBUILD_MODPOST_FAIL_ON_WARNINGS=y +endif + +DRIVER_BUILD_DATE=$(shell date +%Y%m%d%H%M%S) +ccflags-y += -DDRIVER_BUILD_DATE='"$(DRIVER_BUILD_DATE)"' + +# --------------------------------------------------- +# Compile Options +# --------------------------------------------------- +WLAN_CHIP_LIST:=-UMT6620 -UMT6628 -UMT5931 -UMT6630 -UMT6632 -UMT7663 -UCONNAC -UCONNAC2X2 +# '-D' and '-U' options are processed in the order they are given on the command line. +# All '-imacros file' and '-include file' options are processed after all '-D' and '-U' options. +ccflags-y += $(WLAN_CHIP_LIST) + +############################################################## +# Common settings +############################################################## +export MTK_COMBO_CHIP=MT7663 +export CONFIG_MTK_COMBO_WIFI=m +export HIF=sdio +export CONFIG_MTK_COMBO_COMM_SDIO=y +export CONFIG_MTK_PREALLOC_MEMORY=y +ifeq ($(MTK_COMBO_CHIP),) +MTK_COMBO_CHIP = MT6632 +endif +export CONFIG_MTK_COMBO_WIFI_HIF=$(HIF) + +$(info $$MTK_PLATFORM is [${MTK_PLATFORM}]) +$(info $$WLAN_CHIP_ID is [${WLAN_CHIP_ID}]) + +ifeq ($(WLAN_CHIP_ID),) + WLAN_CHIP_ID := MT7663 +endif + +ccflags-y += -DCFG_SUPPORT_DEBUG_FS=0 +ccflags-y += -DWLAN_INCLUDE_PROC +ccflags-y += -DCFG_SUPPORT_AGPS_ASSIST=1 +ccflags-y += -DCFG_SUPPORT_TSF_USING_BOOTTIME=1 +ccflags-y += -DARP_MONITER_ENABLE=1 +ccflags-y += -Werror +#ccflags-y:=$(filter-out -U$(WLAN_CHIP_ID),$(ccflags-y)) +#ccflags-y += -DLINUX -D$(WLAN_CHIP_ID) +ccflags-y += -DLINUX + +ifneq ($(filter MT6632,$(MTK_COMBO_CHIP)),) +ccflags-y:=$(filter-out -UMT6632,$(ccflags-y)) +ccflags-y += -DMT6632 +endif + +ifneq ($(filter MT7668,$(MTK_COMBO_CHIP)),) +ccflags-y:=$(filter-out -UMT7668,$(ccflags-y)) +ccflags-y += -DMT7668 +endif + +ifneq ($(filter MT7663,$(MTK_COMBO_CHIP)),) +ccflags-y:=$(filter-out -UMT7663,$(ccflags-y)) +ccflags-y += -DMT7663 +endif + +ifneq ($(filter CONNAC,$(MTK_COMBO_CHIP)),) +ccflags-y:=$(filter-out -UCONNAC,$(ccflags-y)) +ccflags-y += -DCONNAC +endif + +ifneq ($(filter CONNAC2X2,$(MTK_COMBO_CHIP)),) +ccflags-y:=$(filter-out -UCONNAC2X2,$(ccflags-y)) +ccflags-y += -DCONNAC2X2 +endif + +ifeq ($(WIFI_ENABLE_GCOV), y) +GCOV_PROFILE := y +endif + +ifeq ($(MTK_ANDROID_WMT), y) + ccflags-y += -DCFG_MTK_ANDROID_WMT=1 +else ifneq ($(filter MT6632,$(MTK_COMBO_CHIP)),) + ccflags-y += -DCFG_MTK_ANDROID_WMT=1 +else + ccflags-y += -DCFG_MTK_ANDROID_WMT=0 +endif + +ifeq ($(MTK_ANDROID_EMI), y) + ccflags-y += -DCFG_MTK_ANDROID_EMI=1 +else + ccflags-y += -DCFG_MTK_ANDROID_EMI=0 +endif + +ifneq ($(filter MT7663 MT7668,$(MTK_COMBO_CHIP)),) + ccflags-y += -DCFG_MTK_EMI=0 +else + ccflags-y += -DCFG_MTK_EMI=DCONFIG_MTK_EMI +endif + +ifneq ($(filter MTK_WCN_REMOVE_KERNEL_MODULE,$(KBUILD_SUBDIR_CCFLAGS)),) + ccflags-y += -DCFG_BUILT_IN_DRIVER=1 +else + ccflags-y += -DCFG_BUILT_IN_DRIVER=0 +endif + +CONFIG_MTK_WIFI_MCC_SUPPORT=y +ifeq ($(CONFIG_MTK_WIFI_MCC_SUPPORT), y) + ccflags-y += -DCFG_SUPPORT_CHNL_CONFLICT_REVISE=0 +else + ccflags-y += -DCFG_SUPPORT_CHNL_CONFLICT_REVISE=1 +endif + +ifeq ($(CONFIG_MTK_AEE_FEATURE), y) + ccflags-y += -DCFG_SUPPORT_AEE=1 +else + ccflags-y += -DCFG_SUPPORT_AEE=0 +endif + +ifeq ($(CONFIG_MTK_WPA3_SUPPORT), y) + ccflags-y += -DCFG_SUPPORT_CFG80211_AUTH=1 + ccflags-y += -DCFG_SUPPORT_SAE=1 + ccflags-y += -DCFG_SUPPORT_OWE=1 + ccflags-y += -DCFG_SUPPORT_SUITB=1 +else + ccflags-y += -DCFG_SUPPORT_CFG80211_AUTH=0 + ccflags-y += -DCFG_SUPPORT_SAE=0 + ccflags-y += -DCFG_SUPPORT_OWE=0 + ccflags-y += -DCFG_SUPPORT_SUITB=0 +endif + +# Disable ASSERT() for user load, enable for others +ifneq ($(TARGET_BUILD_VARIANT),user) + ccflags-y += -DBUILD_QA_DBG=1 +else + ccflags-y += -DBUILD_QA_DBG=0 +endif + +ifeq ($(CONFIG_MTK_COMBO_WIFI),y) + ccflags-y += -DCFG_WPS_DISCONNECT=1 +endif + +ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), sdio) + ccflags-y += -D_HIF_SDIO=1 +ifeq ($(CONFIG_SDIO_AGG_THREAD), y) + ccflags-y += -D_SDIO_RING=1 +endif +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), pcie) + ccflags-y += -D_HIF_PCIE=1 +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), usb) + ccflags-y += -D_HIF_USB=1 +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), axi) + ccflags-y += -D_HIF_AXI=1 +else + $(error Unsuppoted HIF=$(CONFIG_MTK_COMBO_WIFI_HIF)!!) +endif + +CONFIG_IPI_2CHAIN_SUPPORT=y +ifeq ($(CONFIG_IPI_2CHAIN_SUPPORT),n) + ccflags-y += -DCFG_IPI_2CHAIN_SUPPORT=0 +else + ccflags-y += -DCFG_IPI_2CHAIN_SUPPORT=1 +endif + +CFG_GET_TEMPURATURE=y +ifeq ($(CFG_GET_TEMPURATURE),y) +ccflags-y += -DCFG_GET_TEMPURATURE +endif + +# For Thermal module API +# 1: enable, 0: disable +ccflags-y += -DCFG_THERMAL_API_SUPPORT=1 +ifeq ($(CFG_ENABLE_1RPD_MMPS_CTRL), y) + ccflags-y += -DCFG_ENABLE_1RPD_MMPS_CTRL=1 +endif + +ifneq ($(CFG_CFG80211_VERSION),) +VERSION_STR = $(subst \",,$(subst ., , $(subst -, ,$(subst v,,$(CFG_CFG80211_VERSION))))) +$(info VERSION_STR=$(VERSION_STR)) +X = $(firstword $(VERSION_STR)) +Y = $(word 2 ,$(VERSION_STR)) +Z = $(word 3 ,$(VERSION_STR)) +VERSION := $(shell echo "$$(( $X * 65536 + $Y * 256 + $Z))" ) +ccflags-y += -DCFG_CFG80211_VERSION=$(VERSION) +$(info DCFG_CFG80211_VERSION=$(VERSION)) +endif + + +ifeq ($(CONFIG_MTK_PASSPOINT_R2_SUPPORT), y) + ccflags-y += -DCFG_SUPPORT_PASSPOINT=1 + ccflags-y += -DCFG_HS20_DEBUG=1 + ccflags-y += -DCFG_ENABLE_GTK_FRAME_FILTER=1 +else + ccflags-y += -DCFG_SUPPORT_PASSPOINT=0 + ccflags-y += -DCFG_HS20_DEBUG=0 + ccflags-y += -DCFG_ENABLE_GTK_FRAME_FILTER=0 +endif + +MTK_MET_PROFILING_SUPPORT = yes +ifeq ($(MTK_MET_PROFILING_SUPPORT), yes) + ccflags-y += -DCFG_MET_PACKET_TRACE_SUPPORT=1 +else + ccflags-y += -DCFG_MET_PACKET_TRACE_SUPPORT=0 +endif + +MTK_MET_TAG_SUPPORT = no +ifeq ($(MTK_MET_TAG_SUPPORT), yes) + ccflags-y += -DMET_USER_EVENT_SUPPORT + ccflags-y += -DCFG_MET_TAG_SUPPORT=1 +else + ccflags-y += -DCFG_MET_TAG_SUPPORT=0 +endif + +ifeq ($(CONFIG_MTK_TC10_FEATURE), y) + ccflags-y += -DCFG_TC10_FEATURE=1 +else + ccflags-y += -DCFG_TC10_FEATURE=0 +endif + +ifeq ($(CONFIG_MTK_TC1_FEATURE), y) + ccflags-y += -DCFG_TC1_FEATURE=1 +else + ccflags-y += -DCFG_TC1_FEATURE=0 +endif + +# RX NAPI +ifneq ($(CFG_RX_NAPI_SUPPORT),) + ccflags-y += -DCFG_RX_NAPI_SUPPORT=$(CFG_RX_NAPI_SUPPORT) +endif +#ifeq ($(MODULE_NAME),) +# MODULE_NAME := wlan_$(shell echo $(strip $(WLAN_CHIP_ID)) | tr A-Z a-z)_$(CONFIG_MTK_COMBO_WIFI_HIF) +#endif + +ccflags-y += -DDBG=0 +ccflags-y += -I$(src)/os -I$(src)/os/linux/include +ccflags-y += -I$(src)/include -I$(src)/include/nic -I$(src)/include/mgmt -I$(src)/include/chips +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/performance/include/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/emi/$(MTK_PLATFORM) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/emi/submodule +ccflags-y += -I$(srctree)/drivers/devfreq/ +ccflags-y += -I$(srctree)/net +ccflags-y += -I$(srctree)/drivers/misc/mediatek/thermal/common/inc + +ifeq ($(MTK_CPU_SCHED),y) +ccflags-y += -DCFG_SUPPORT_MTK_CPU_SCHED=1 +ccflags-y += -Werror -I$(srctree)/drivers/misc/mediatek/sched/mtk_cpu_affinity +else +ccflags-y += -DCFG_SUPPORT_MTK_CPU_SCHED=0 +endif + +ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), sdio) +ccflags-y += -I$(src)/os/linux/hif/sdio/include +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), pcie) +ccflags-y += -I$(src)/os/linux/hif/common/include +ccflags-y += -I$(src)/os/linux/hif/pcie/include +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), axi) +ccflags-y += -I$(src)/os/linux/hif/common/include +ccflags-y += -I$(src)/os/linux/hif/axi/include +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), usb) +ccflags-y += -I$(src)/os/linux/hif/usb/include +endif + +ifneq ($(PLATFORM_FLAGS), ) + ccflags-y += $(PLATFORM_FLAGS) +endif + +#ifeq ($(CONFIG_MTK_WIFI_ONLY),$(filter $(CONFIG_MTK_WIFI_ONLY),m y)) +#obj-$(CONFIG_MTK_WIFI_ONLY) += $(MODULE_NAME).o +#else +#obj-$(CONFIG_MTK_COMBO_WIFI) += $(MODULE_NAME).o +#obj-y += $(MODULE_NAME).o +#endif +MODULE_NAME := wlan_drv_gen4_mt7663 +obj-m += $(MODULE_NAME).o + +# --------------------------------------------------- +# Directory List +# --------------------------------------------------- +COMMON_DIR := common/ +OS_DIR := os/linux/ +HIF_COMMON_DIR := $(OS_DIR)hif/common/ +ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), sdio) +HIF_DIR := os/linux/hif/sdio/ +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), pcie) +HIF_DIR := os/linux/hif/pcie/ +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), axi) +HIF_DIR := os/linux/hif/axi/ +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), usb) +HIF_DIR := os/linux/hif/usb/ +endif +NIC_DIR := nic/ +MGMT_DIR := mgmt/ +CHIPS := chips/ +CHIPS_CMM := $(CHIPS)common/ + +ifneq ($(MTK_PLATFORM),) +PLAT_DIR := os/linux/plat/$(MTK_PLATFORM)/ +endif + +# --------------------------------------------------- +# Objects List +# --------------------------------------------------- + +COMMON_OBJS := $(COMMON_DIR)dump.o \ + $(COMMON_DIR)wlan_lib.o \ + $(COMMON_DIR)wlan_oid.o \ + $(COMMON_DIR)wlan_bow.o \ + $(COMMON_DIR)debug.o + +NIC_OBJS := $(NIC_DIR)nic.o \ + $(NIC_DIR)nic_tx.o \ + $(NIC_DIR)nic_rx.o \ + $(NIC_DIR)nic_pwr_mgt.o \ + $(NIC_DIR)nic_rate.o \ + $(NIC_DIR)cmd_buf.o \ + $(NIC_DIR)que_mgt.o \ + $(NIC_DIR)nic_cmd_event.o \ + $(NIC_DIR)nic_umac.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_ate_agent.o \ + $(OS_DIR)gl_qa_agent.o \ + $(OS_DIR)gl_hook_api.o \ + $(OS_DIR)gl_rst.o \ + $(OS_DIR)gl_cfg80211.o \ + $(OS_DIR)gl_proc.o \ + $(OS_DIR)gl_vendor.o \ + $(OS_DIR)gl_custom.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)reg_rule.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)scan_cache.o \ + $(MGMT_DIR)swcr.o \ + $(MGMT_DIR)roaming_fsm.o \ + $(MGMT_DIR)tkip_mic.o \ + $(MGMT_DIR)hs20.o \ + $(MGMT_DIR)tdls.o \ + $(MGMT_DIR)wnm.o \ + $(MGMT_DIR)qosmap.o \ + $(MGMT_DIR)ap_selection.o \ + $(MGMT_DIR)wmm.o + +# --------------------------------------------------- +# Chips Objects List +# --------------------------------------------------- +MGMT_OBJS += $(MGMT_DIR)stats.o + + +CHIPS_OBJS += $(CHIPS_CMM)cmm_asic_connac.o +CHIPS_OBJS += $(CHIPS_CMM)fw_dl.o + +ifneq ($(filter MT6632,$(MTK_COMBO_CHIP)),) +CHIPS_OBJS += $(CHIPS)mt6632/mt6632.o +endif +ifneq ($(filter MT7668,$(MTK_COMBO_CHIP)),) +CHIPS_OBJS += $(CHIPS)mt7668/mt7668.o +endif +ifneq ($(filter MT7663,$(MTK_COMBO_CHIP)),) +CHIPS_OBJS += $(CHIPS)mt7663/mt7663.o +endif +ifneq ($(filter CONNAC,$(MTK_COMBO_CHIP)),) +CHIPS_OBJS += $(CHIPS)connac/connac.o +endif +ifneq ($(filter CONNAC2X2,$(MTK_COMBO_CHIP)),) +CHIPS_OBJS += $(CHIPS)connac2x2/connac2x2.o +endif + +# --------------------------------------------------- +# 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_dev_fsm.o\ + $(MGMT_DIR)p2p_dev_state.o\ + $(MGMT_DIR)p2p_role_fsm.o\ + $(MGMT_DIR)p2p_role_state.o\ + $(MGMT_DIR)p2p_func.o\ + $(MGMT_DIR)p2p_scan.o\ + $(MGMT_DIR)p2p_ie.o\ + $(MGMT_DIR)p2p_rlm.o\ + $(MGMT_DIR)p2p_assoc.o\ + $(MGMT_DIR)p2p_bss.o\ + $(MGMT_DIR)p2p_rlm_obss.o\ + $(MGMT_DIR)p2p_fsm.o + +MGMT_OBJS += $(MGMT_DIR)wapi.o + +ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), sdio) +HIF_OBJS := $(HIF_DIR)arm.o \ + $(HIF_DIR)sdio.o \ + $(HIF_DIR)hal_api.o \ + $(HIF_DIR)sdio_test_driver_core.o \ + $(HIF_DIR)sdio_test_driver_ops.o +ifeq ($(CONFIG_SDIO_AGG_THREAD), y) +HIF_OBJS += $(HIF_DIR)sdio_ring.o +endif +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), pcie) +HIF_OBJS := $(HIF_COMMON_DIR)hal_pdma.o \ + $(HIF_COMMON_DIR)kal_pdma.o \ + $(HIF_COMMON_DIR)dbg_pdma.o \ + $(HIF_DIR)pcie.o +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), axi) +HIF_OBJS := $(HIF_COMMON_DIR)hal_pdma.o \ + $(HIF_COMMON_DIR)kal_pdma.o \ + $(HIF_COMMON_DIR)dbg_pdma.o \ + $(HIF_DIR)axi.o +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), usb) +HIF_OBJS := $(HIF_DIR)usb.o \ + $(HIF_DIR)hal_api.o +endif + +# --------------------------------------------------- +# Platform Objects List +# --------------------------------------------------- +ifneq ($(MTK_PLATFORM),) + +PLAT_PRIV_C = $(src)/$(PLAT_DIR)plat_priv.c + +# search path (out of kernel tree) +IS_EXIST_PLAT_PRIV_C := $(wildcard $(PLAT_PRIV_C)) +# search path (build-in kernel tree) +IS_EXIST_PLAT_PRIV_C += $(wildcard $(srctree)/$(PLAT_PRIV_C)) + +ifneq ($(strip $(IS_EXIST_PLAT_PRIV_C)),) +PLAT_OBJS := $(PLAT_DIR)plat_priv.o +$(MODULE_NAME)-objs += $(PLAT_OBJS) +endif +endif + +# --------------------------------------------------- + +$(MODULE_NAME)-objs += $(COMMON_OBJS) +$(MODULE_NAME)-objs += $(NIC_OBJS) +$(MODULE_NAME)-objs += $(OS_OBJS) +$(MODULE_NAME)-objs += $(HIF_OBJS) +$(MODULE_NAME)-objs += $(MGMT_OBJS) +$(MODULE_NAME)-objs += $(CHIPS_OBJS) + +# +# mtprealloc +# +ifeq ($(CONFIG_MTK_PREALLOC_MEMORY), y) +ccflags-y += -DCFG_PREALLOC_MEMORY +ccflags-y += -I$(src)/prealloc/include +MODULE_NAME_PREALLOC = $(MODULE_NAME)_prealloc +PREALLOC_OBJS := prealloc/prealloc.o +$(MODULE_NAME_PREALLOC)-objs += $(PREALLOC_OBJS) +obj-m += $(MODULE_NAME_PREALLOC).o +endif + +ccflags-y += -DCFG_SUPPORT_WOW_EINT=1 + +# Define maximum different channels supported for ieee80211_iface_combination setting. +ccflags-y += -DCFG_NUM_DIFFERENT_CHANNELS_STA=1 +ccflags-y += -DCFG_NUM_DIFFERENT_CHANNELS_P2P=1 + +# Define initial driver running mode. +# 0=RUNNING_P2P_MODE, 1=RUNNING_AP_MODE, 2=RUNNING_DUAL_AP_MODE, 3=RUNNING_P2P_AP_MODE +ccflags-y += -DCFG_DRIVER_INITIAL_RUNNING_MODE=3 + +# Define to enable Android wake_lock +ccflags-y += -DCFG_ENABLE_WAKE_LOCK=1 + + +ccflags-y += -DCFG_ENABLE_EFUSE_MAC_ADDR=1 + +# Report all bss networks to cfg80211 when do p2p scan +ccflags-y += -DCFG_P2P_SCAN_REPORT_ALL_BSS=0 + +# Support to change sta, p2p, ap interface names +# y: enable, n: disable +# eg. insmod wlan_mt76x8_usb.ko sta=wlan p2p=p2p ap=ap + +# 1: Enable SDIO RX Work Queue De-Aggregation +# 0: Disable (default) +ccflags-y += -DCFG_SDIO_RX_AGG_WORKQUE=0 + +#Support mobile private cmd, need change cmd size to 512 +ccflags-y += -DCFG_ALPS_ANDROID_AOSP_PRIV_CMD diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/Makefile.ce b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/Makefile.ce new file mode 100644 index 0000000000000..14b060f5362dd --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/Makefile.ce @@ -0,0 +1,312 @@ +# Makefile for MT76x8 combo driver + +############################################################## +# Common settings +############################################################## +export MTK_COMBO_CHIP=MT6632 +export HIF=usb +export CONFIG_MTK_WIFI_ONLY=m +export CONFIG_MTK_COMBO=m +export CONFIG_MTK_COMBO_WIFI=m +export CONFIG_MTK_COMBO_COMM=m +export CONFIG_MTK_COMBO_COMM_UART=m +export CONFIG_MTK_COMBO_COMM_SDIO=m +export CONFIG_MT_WIFI_CHRDEV=m +export MTK_CPU_SCHED=n + +WIFI_TARGET := mt76x8 + +ifeq ($(HIF),) + HIF=usb +endif + +export CONFIG_MTK_COMBO_WIFI_HIF=$(HIF) +MODULE_NAME := wlan_$(WIFI_TARGET)_$(HIF) + +export CONFIG_MTK_PREALLOC_MEMORY=n + +############################################################## +# Platform specific +############################################################## +# Set default platform +PLATFORM = MT53XX + +ifeq ($(PLATFORM),) +PLATFORM = MT53XX +endif + +#- - - - -- - - - - - - - - - +# MT53XX start +#- - - - -- - - - - - - - - - +ifeq ($(PLATFORM),MT53XX) + +# Sets DRIVER_PARTIAL_BUILD to y to compile driver only, otherwise set to n +DRIVER_PARTIAL_BUILD=n +# Set if 64 bit platform +64BIT_MODE=true +export WIFI_TARGET +TARGET = LINUX + +ifeq ($(DRIVER_PARTIAL_BUILD),y) +# *****For driver partial build***** +LINUX_ROOT ?= $(word 1, $(subst /apollo/,/apollo /, $(shell pwd -L))) +# Modify the build parameters below to fit your build +SYSBUILD_NAME=m-base +RELEASE_NAME=mediatek/mt5891_eu_64 +KERNEL_VER=3.18 +KERNEL_CONFIG=mt5891_android_smp_mod_defconfig +ifeq ($(64BIT_MODE),true) +export 64BIT_MODE=true +export KERNEL_64BIT=true +export TOOL_CHAIN_64BIT=4.9.3 +endif +# +LINUX_SRC=$(LINUX_ROOT)/../android/$(SYSBUILD_NAME)/out/mediatek_linux/output/$(RELEASE_NAME)/rel/obj/kernel/linux_core/kernel/linux-$(KERNEL_VER)/$(KERNEL_CONFIG)_modules +OBJ_ROOT ?= $(LINUX_ROOT)/../android/$(SYSBUILD_NAME)/out/mediatek_linux/output/$(RELEASE_NAME)/rel/obj +export KERNEL_OBJ_ROOT=$(LINUX_SRC)/../.. +else +# *****For system auto build***** +LINUX_SRC=$(KERNEL_OBJ_ROOT)/$(KERNEL_VER)/$(KERNEL_CONFIG)_modules +# overwrite $(OUT_STA_KO) for MT53XX platform +OUT_STA_KO = $(OBJ_ROOT)/third_party/source/wlan/mtk/$(WIFI_TARGET)/$(MODULE_NAME).ko +endif + +include $(LINUX_ROOT)/linux_mts/mak/toolchain.mak +ifeq ($(CROSS_COMPILE),) +CROSS_COMPILE=/mtkoss/gnuarm/vfp_4.5.1_2.6.27_cortex-a9-rhel4/i686/bin/armv7a-mediatek451_001_vfp-linux-gnueabi- +endif +ifeq "$(CC)" "gcc" +CC ?= $(CROSS_COMPILE)gcc +endif +$(warning =============================================) +$(warning wifi driver LINUX_SRC=$(LINUX_SRC)) +$(warning CROSS_COMPILE=$(CROSS_COMPILE)) +$(warning =============================================) + +DRIVER_DIR=$(LINUX_ROOT)/third_party/source/wlan/mtk/$(WIFI_TARGET) + +endif +#- - - - -- - - - - - - - - - +# MT53XX end +#- - - - -- - - - - - - - - - + + +############################################################## +# Compile options +############################################################## +#/***** Common part ******/ + +# Define maximum different channels supported for ieee80211_iface_combination setting. +CFG_NUM_DIFFERENT_CHANNELS_STA=1 +CFG_NUM_DIFFERENT_CHANNELS_P2P=1 + +# Define initial driver running mode. +# 0=RUNNING_P2P_MODE, 1=RUNNING_AP_MODE, 2=RUNNING_DUAL_AP_MODE, 3=RUNNING_P2P_AP_MODE +CFG_DRIVER_INITIAL_RUNNING_MODE=3 + +# Define to enable Android wake_lock +CFG_ENABLE_WAKE_LOCK=0 + +CFG_DEFAULT_DBG_LEVEL=0xF + +CFG_TX_DIRECT_USB=1 + +CFG_RX_DIRECT_USB=1 + +CFG_USB_REQ_TX_DATA_FFA_CNT=6 + +CFG_USB_REQ_TX_DATA_CNT=2 + +CFG_USB_REQ_RX_DATA_CNT=4 + +CFG_ENABLE_EFUSE_MAC_ADDR=1 + +# Report all bss networks to cfg80211 when do p2p scan +CFG_P2P_SCAN_REPORT_ALL_BSS=0 + +# Support to change sta, p2p, ap interface names +# y: enable, n: disable +# eg. insmod wlan_mt76x8_usb.ko sta=wlan p2p=p2p ap=ap +CFG_DRIVER_INF_NAME_CHANGE=n + +# 1: Enable SDIO RX Work Queue De-Aggregation +# 0: Disable (default) +CFG_SDIO_RX_AGG_WORKQUE=0 + +#CFG_SUPPORT_SINGLE_SKU_LOCAL_DB=0 + +#/***** Platform dependent part ******/ +ifeq ($(PLATFORM),MT53XX) +CFG_SUPPORT_ROAMING=0 +endif + +ifeq ($(PLATFORM),MT8518) +CFG_SUPPORT_WOW_EINT=1 +CFG_SUPPORT_MAGIC_PKT_VENDOR_EVENT=1 +endif + +# For wpa_supplicant w/o MTK priv lib +# y: enable, n: disable +CFG_ANDROID_AOSP_PRIV_CMD=n + +# For Driver to load a specific file name as wifi.cfg +#CFG_FILE_NAME=\\\"wifi_XXX.cfg\\\" + +# For USB to switch resume method: reset_resume(resume) or disconnect +CFG_DISABLE_USB_RESET_RESUME=n + +#/***** Manage configs into compile options ******/ +ifeq ($(CFG_DISABLE_USB_RESET_RESUME),y) +PLATFORM_FLAGS += -DCFG_DISABLE_USB_RESET_RESUME +endif + +ifneq ($(CFG_FILE_NAME),) +PLATFORM_FLAGS += -DCFG_FILE_NAME=$(CFG_FILE_NAME) +endif + +ifneq ($(CFG_NUM_DIFFERENT_CHANNELS_STA),) +PLATFORM_FLAGS += -DCFG_NUM_DIFFERENT_CHANNELS_STA=$(CFG_NUM_DIFFERENT_CHANNELS_STA) +endif + +ifneq ($(CFG_NUM_DIFFERENT_CHANNELS_P2P),) +PLATFORM_FLAGS += -DCFG_NUM_DIFFERENT_CHANNELS_P2P=$(CFG_NUM_DIFFERENT_CHANNELS_P2P) +endif + +ifneq ($(CFG_DRIVER_INITIAL_RUNNING_MODE),) +PLATFORM_FLAGS += -DCFG_DRIVER_INITIAL_RUNNING_MODE=$(CFG_DRIVER_INITIAL_RUNNING_MODE) +endif + +ifneq ($(CFG_ENABLE_WAKE_LOCK),) +PLATFORM_FLAGS += -DCFG_ENABLE_WAKE_LOCK=$(CFG_ENABLE_WAKE_LOCK) +endif + +ifneq ($(CFG_DEFAULT_DBG_LEVEL),) +PLATFORM_FLAGS += -DCFG_DEFAULT_DBG_LEVEL=$(CFG_DEFAULT_DBG_LEVEL) +endif + +ifneq ($(CFG_TX_DIRECT_USB),) +PLATFORM_FLAGS += -DCFG_TX_DIRECT_USB=$(CFG_TX_DIRECT_USB) +endif + +ifneq ($(CFG_RX_DIRECT_USB),) +PLATFORM_FLAGS += -DCFG_RX_DIRECT_USB=$(CFG_RX_DIRECT_USB) +endif + +ifneq ($(CFG_USB_REQ_TX_DATA_FFA_CNT),) +PLATFORM_FLAGS += -DCFG_USB_REQ_TX_DATA_FFA_CNT=$(CFG_USB_REQ_TX_DATA_FFA_CNT) +endif + +ifneq ($(CFG_USB_REQ_TX_DATA_CNT),) +PLATFORM_FLAGS += -DCFG_USB_REQ_TX_DATA_CNT=$(CFG_USB_REQ_TX_DATA_CNT) +endif + +ifneq ($(CFG_USB_REQ_RX_DATA_CNT),) +PLATFORM_FLAGS += -DCFG_USB_REQ_RX_DATA_CNT=$(CFG_USB_REQ_RX_DATA_CNT) +endif + +ifneq ($(CFG_ENABLE_EFUSE_MAC_ADDR),) +PLATFORM_FLAGS += -DCFG_ENABLE_EFUSE_MAC_ADDR=$(CFG_ENABLE_EFUSE_MAC_ADDR) +endif + +ifeq ($(CFG_DRIVER_INF_NAME_CHANGE), y) +PLATFORM_FLAGS += -DCFG_DRIVER_INF_NAME_CHANGE +endif + +ifneq ($(CFG_P2P_SCAN_REPORT_ALL_BSS),) +PLATFORM_FLAGS += -DCFG_P2P_SCAN_REPORT_ALL_BSS=$(CFG_P2P_SCAN_REPORT_ALL_BSS) +endif + +ifneq ($(CFG_SUPPORT_ROAMING),) +PLATFORM_FLAGS += -DCFG_SUPPORT_ROAMING=$(CFG_SUPPORT_ROAMING) +endif + +ifeq ($(CFG_ANDROID_AOSP_PRIV_CMD), y) +PLATFORM_FLAGS += -DCFG_ANDROID_AOSP_PRIV_CMD +endif + +ifneq ($(CFG_SDIO_RX_AGG_WORKQUE),) +PLATFORM_FLAGS += -DCFG_SDIO_RX_AGG_WORKQUE=$(CFG_SDIO_RX_AGG_WORKQUE) +endif + +ifneq ($(CFG_SUPPORT_WOW_EINT),) +PLATFORM_FLAGS += -DCFG_SUPPORT_WOW_EINT=$(CFG_SUPPORT_WOW_EINT) +endif + +ifneq ($(CFG_SUPPORT_MAGIC_PKT_VENDOR_EVENT),) +PLATFORM_FLAGS += -DCFG_SUPPORT_MAGIC_PKT_VENDOR_EVENT=$(CFG_SUPPORT_MAGIC_PKT_VENDOR_EVENT) +endif + +#For adjust channel request interval when ais join net work +ifeq ($(CFG_SUPPORT_ADJUST_JOIN_CH_REQ_INTERVAL),y) +PLATFORM_FLAGS += -DCFG_SUPPORT_ADJUST_JOIN_CH_REQ_INTERVAL +endif + +ifeq ($(CFG_SUPPORT_P2P_GO_11B_RATE),y) +PLATFORM_FLAGS += -DCFG_SUPPORT_P2P_GO_11B_RATE +endif + +ifeq ($(CFG_SUPPORT_P2P_OPEN_SECURITY),y) +PLATFORM_FLAGS += -DCFG_SUPPORT_P2P_OPEN_SECURITY +endif + +############################################################## +# Compile settings +############################################################## + +all: driver + +driver: + +cd $(DRIVER_DIR) && make -C $(LINUX_SRC) M=$(DRIVER_DIR) MODULE_NAME=$(MODULE_NAME) PLATFORM_FLAGS="$(PLATFORM_FLAGS)" modules +ifeq ($(PLATFORM),MT53XX) +ifeq ($(DRIVER_PARTIAL_BUILD), y) + @cd $(DRIVER_DIR) && $(CROSS_COMPILE)strip --strip-unneeded $(MODULE_NAME).ko +else +ifneq ($(ANDROID),true) + if [ ! -d $(THIRDPARTY_LIB_ROOT)/wlan/$(KERNEL_VER_FOR_3RD)/mtk/$(WIFI_TARGET) ]; then \ + mkdir -p $(THIRDPARTY_LIB_ROOT)/wlan/$(KERNEL_VER_FOR_3RD)/mtk/$(WIFI_TARGET)/; \ + fi + cp -f $(OUT_STA_KO) $(THIRDPARTY_LIB_ROOT)/wlan/$(KERNEL_VER_FOR_3RD)/mtk/$(WIFI_TARGET)/$(MODULE_NAME).ko +else +ifeq "$(BUILD_CFG)" "debug" + echo "ANDROID_VERSION=$(ANDROID_VERSION)" + if [ ! -d $(LINUX_ROOT)/../android/$(ANDROID_VERSION)/vendor/mediatek/open/hardware/prebuilt/wifi/$(ANDROID_IC_SETTING)/dbg ]; then \ + mkdir -p $(LINUX_ROOT)/../android/$(ANDROID_VERSION)/vendor/mediatek/open/hardware/prebuilt/wifi/$(ANDROID_IC_SETTING)/dbg; \ + fi + cp -f $(OUT_STA_KO) $(LINUX_ROOT)/../android/$(ANDROID_VERSION)/vendor/mediatek/open/hardware/prebuilt/wifi/$(ANDROID_IC_SETTING)/dbg/$(MODULE_NAME).ko + + if [ -d $(OUTPUT_ROOT)/basic/modules ]; then \ + cp -f $(OUT_STA_KO) $(OUTPUT_ROOT)/basic/modules/wlan.ko; \ + fi +else + if [ ! -d $(LINUX_ROOT)/../android/$(ANDROID_VERSION)/vendor/mediatek/open/hardware/prebuilt/wifi/$(ANDROID_IC_SETTING) ]; then \ + mkdir -p $(LINUX_ROOT)/../android/$(ANDROID_VERSION)/vendor/mediatek/open/hardware/prebuilt/wifi/$(ANDROID_IC_SETTING); \ + fi + cp -f $(OUT_STA_KO) $(LINUX_ROOT)/../android/$(ANDROID_VERSION)/vendor/mediatek/open/hardware/prebuilt/wifi/$(ANDROID_IC_SETTING)/$(MODULE_NAME).ko + + if [ -d $(OUTPUT_ROOT)/basic/modules ]; then \ + cp -f $(OUT_STA_KO) $(OUTPUT_ROOT)/basic/modules/wlan.ko; \ + fi +endif +endif +endif +endif +# @cd $(DRIVER_DIR) && cp $(MODULES_NAME)_$(HIF).ko $(MODULES_NAME).ko + +#common: +# +cd $(COMMON_DIR) && make -C $(LINUX_SRC) M=$(COMMON_DIR) modules +# @cat $(COMMON_DIR)/Module.symvers >> $(LINUX_SRC)/Module.symvers + +clean: driver_clean + +#symvers_clean: driver_clean +# @cp $(LINUX_SRC)/Module.symvers.original $(LINUX_SRC)/Module.symvers + +driver_clean: + cd $(DRIVER_DIR) && make -C $(LINUX_SRC) M=$(DRIVER_DIR) MODULE_NAME=$(MODULE_NAME) clean + if [ -e $(DRIVER_DIR)/$(MODULE_NAME).ko ]; then rm $(DRIVER_DIR)/$(MODULE_NAME).ko; fi; + +#common_clean: +# cd $(COMMON_DIR) && make -C $(LINUX_SRC) M=$(COMMON_DIR) clean + +.PHONY: all clean driver driver_clean + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/Makefile.x86 b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/Makefile.x86 new file mode 100644 index 0000000000000..34db322c9b1be --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/Makefile.x86 @@ -0,0 +1,227 @@ +# Makefile.x86: Makefile for Linux PC +# You can build specific .ko name by assiging the "MTK_COMBO_CHIP" and "hif" parameters +# hif = pcie or sdio or usb +# Examples: +# - Default=wlan_mt6632_pcie.ko: +# make -f Makefile.x86 +# - wlan_mt7663_usb.ko: +# make -f Makefile.x86 MTK_COMBO_CHIP=MT7663 hif=usb +# Note: Chip ID must be uppercase. E.g., MT7663 + +LINUX_SRC=/lib/modules/$(shell uname -r)/build + +export CONFIG_MTK_COMBO_PLATFORM=x86 +export MTK_COMBO_CHIP=MT6632 + +PWD=$(shell pwd) +DRIVER_DIR=$(PWD) + +export CONFIG_MTK_WIFI_ONLY=m +export CONFIG_MTK_COMBO=m +export CONFIG_MTK_COMBO_WIFI=m +export CONFIG_MTK_COMBO_COMM=m +export CONFIG_MTK_COMBO_COMM_UART=m +export CONFIG_MTK_COMBO_COMM_SDIO=m +export CONFIG_MT_WIFI_CHRDEV=m + +ifneq ($(BACKPORTED_KERNEL_VERSION),) +export CFG_CFG80211_VERSION ?= $(BACKPORTED_KERNEL_VERSION) +endif + +# pcie | sdio | usb +ifeq ($(hif),) + hif=pcie +endif + +MODULES_NAME := wlan_$(shell echo $(word 1, $(MTK_COMBO_CHIP)) | tr A-Z a-z) + +export CONFIG_MTK_COMBO_WIFI_HIF=$(hif) + +export CONFIG_MTK_COMBO_PLAT_PATH=x86 + +export CONFIG_MTK_PREALLOC_MEMORY=n + +############################################################## +# Compile options +############################################################## +#/***** Common part ******/ + +# Define maximum different channels supported for ieee80211_iface_combination setting. +#CFG_NUM_DIFFERENT_CHANNELS_STA=1 +#CFG_NUM_DIFFERENT_CHANNELS_P2P=1 + +# Define initial driver running mode. +# 0=RUNNING_P2P_MODE, 1=RUNNING_AP_MODE, 2=RUNNING_DUAL_AP_MODE, 3=RUNNING_P2P_AP_MODE +#CFG_DRIVER_INITIAL_RUNNING_MODE=3 + +# Define to enable Android wake_lock +#CFG_ENABLE_WAKE_LOCK=0 + +# For wpa_supplicant w/o MTK priv lib +# y: enable, n: disable +CFG_ANDROID_AOSP_PRIV_CMD=n + +#CFG_DEFAULT_DBG_LEVEL=0xF + +CFG_TX_DIRECT_USB=1 + +CFG_RX_DIRECT_USB=1 + +CFG_USB_REQ_TX_DATA_FFA_CNT=10 + +CFG_USB_REQ_TX_DATA_CNT=2 + +CFG_USB_REQ_RX_DATA_CNT=2 + +#CFG_SUPPORT_DFS_MASTER=1 + +#CFG_SUPPORT_SINGLE_SKU_LOCAL_DB=0 + +# Report all bss networks to cfg80211 when do p2p scan +CFG_P2P_SCAN_REPORT_ALL_BSS=0 + +# Support to change sta, p2p, ap interface names +# y: enable, n: disable +# eg. insmod wlan_mt76x8_usb.ko sta=wlan p2p=p2p ap=ap +CFG_DRIVER_INF_NAME_CHANGE=n + +# Support firmware auto roaming +#CFG_SUPPORT_ROAMING=0 + +ifeq ($(CFG_ANDROID_AOSP_PRIV_CMD), y) +PLATFORM_FLAGS += -DCFG_ANDROID_AOSP_PRIV_CMD +endif + +# 1: Enable SDIO RX Work Queue De-Aggregation +# 0: Disable (default) +CFG_SDIO_RX_AGG_WORKQUE=0 + +# For Driver to load a specific file name as wifi.cfg +#CFG_FILE_NAME=\\\"wifi_XXX.cfg\\\" + +CFG_SUPPORT_SER=1 + +ifeq ($(c), ccn6) +CFG_SUPPORT_P2P_GO_11B_RATE=y +CFG_SUPPORT_P2P_OPEN_SECURITY=y +CFG_SUPPORT_ADJUST_JOIN_CH_REQ_INTERVAL=y +CFG_SUPPORT_GET_MCS_INFO=y +CFG_SUPPORT_WAPI=0 +endif + +CFG_SUPPORT_TIME_MEASURE=y + +#/***** Manage configs into compile options ******/ +ifneq ($(CFG_FILE_NAME),) +PLATFORM_FLAGS += -DCFG_FILE_NAME=$(CFG_FILE_NAME) +endif + +ifneq ($(CFG_DFS_CHSW_FORCE_BW20),) +PLATFORM_FLAGS += -DCFG_DFS_CHSW_FORCE_BW20=$(CFG_DFS_CHSW_FORCE_BW20) +endif + +ifneq ($(CFG_NUM_DIFFERENT_CHANNELS_STA),) +PLATFORM_FLAGS += -DCFG_NUM_DIFFERENT_CHANNELS_STA=$(CFG_NUM_DIFFERENT_CHANNELS_STA) +endif + +ifneq ($(CFG_NUM_DIFFERENT_CHANNELS_P2P),) +PLATFORM_FLAGS += -DCFG_NUM_DIFFERENT_CHANNELS_P2P=$(CFG_NUM_DIFFERENT_CHANNELS_P2P) +endif + +ifneq ($(CFG_DRIVER_INITIAL_RUNNING_MODE),) +PLATFORM_FLAGS += -DCFG_DRIVER_INITIAL_RUNNING_MODE=$(CFG_DRIVER_INITIAL_RUNNING_MODE) +endif + +ifneq ($(CFG_ENABLE_WAKE_LOCK),) +PLATFORM_FLAGS += -DCFG_ENABLE_WAKE_LOCK=$(CFG_ENABLE_WAKE_LOCK) +endif + +ifneq ($(CFG_DEFAULT_DBG_LEVEL),) +PLATFORM_FLAGS += -DCFG_DEFAULT_DBG_LEVEL=$(CFG_DEFAULT_DBG_LEVEL) +endif + +ifneq ($(CFG_TX_DIRECT_USB),) +PLATFORM_FLAGS += -DCFG_TX_DIRECT_USB=$(CFG_TX_DIRECT_USB) +endif + +ifneq ($(CFG_RX_DIRECT_USB),) +PLATFORM_FLAGS += -DCFG_RX_DIRECT_USB=$(CFG_RX_DIRECT_USB) +endif + +ifneq ($(CFG_USB_REQ_TX_DATA_FFA_CNT),) +PLATFORM_FLAGS += -DCFG_USB_REQ_TX_DATA_FFA_CNT=$(CFG_USB_REQ_TX_DATA_FFA_CNT) +endif + +ifneq ($(CFG_USB_REQ_TX_DATA_CNT),) +PLATFORM_FLAGS += -DCFG_USB_REQ_TX_DATA_CNT=$(CFG_USB_REQ_TX_DATA_CNT) +endif + +ifneq ($(CFG_USB_REQ_RX_DATA_CNT),) +PLATFORM_FLAGS += -DCFG_USB_REQ_RX_DATA_CNT=$(CFG_USB_REQ_RX_DATA_CNT) +endif + +ifneq ($(CFG_SUPPORT_ROAMING),) +PLATFORM_FLAGS += -DCFG_SUPPORT_ROAMING=$(CFG_SUPPORT_ROAMING) +endif + +ifneq ($(CFG_SUPPORT_DFS_MASTER),) +PLATFORM_FLAGS += -DCFG_SUPPORT_DFS_MASTER=$(CFG_SUPPORT_DFS_MASTER) +endif + +ifneq ($(CFG_SUPPORT_SINGLE_SKU_LOCAL_DB),) +PLATFORM_FLAGS += -DCFG_SUPPORT_SINGLE_SKU_LOCAL_DB=$(CFG_SUPPORT_SINGLE_SKU_LOCAL_DB) +endif + +ifeq ($(CFG_DRIVER_INF_NAME_CHANGE), y) +PLATFORM_FLAGS += -DCFG_DRIVER_INF_NAME_CHANGE +endif + +ifneq ($(CFG_P2P_SCAN_REPORT_ALL_BSS),) +PLATFORM_FLAGS += -DCFG_P2P_SCAN_REPORT_ALL_BSS=$(CFG_P2P_SCAN_REPORT_ALL_BSS) +endif + +ifneq ($(CFG_SDIO_RX_AGG_WORKQUE),) +PLATFORM_FLAGS += -DCFG_SDIO_RX_AGG_WORKQUE=$(CFG_SDIO_RX_AGG_WORKQUE) +endif + +#For adjust channel request interval when ais join net work +ifeq ($(CFG_SUPPORT_ADJUST_JOIN_CH_REQ_INTERVAL),y) +PLATFORM_FLAGS += -DCFG_SUPPORT_ADJUST_JOIN_CH_REQ_INTERVAL +endif + +ifeq ($(CFG_SUPPORT_P2P_GO_11B_RATE),y) +PLATFORM_FLAGS += -DCFG_SUPPORT_P2P_GO_11B_RATE +endif + +ifeq ($(CFG_SUPPORT_P2P_OPEN_SECURITY),y) +PLATFORM_FLAGS += -DCFG_SUPPORT_P2P_OPEN_SECURITY +endif + +ifneq ($(CFG_SUPPORT_SER),) +PLATFORM_FLAGS += -DCFG_SUPPORT_SER=$(CFG_SUPPORT_SER) +endif + +ifeq ($(CFG_SUPPORT_GET_MCS_INFO), y) +PLATFORM_FLAGS += -DCFG_SUPPORT_GET_MCS_INFO +endif + +ifeq ($(CFG_SUPPORT_TIME_MEASURE),y) +PLATFORM_FLAGS += -DCFG_SUPPORT_TIME_MEASURE +endif + +ifneq ($(CFG_SUPPORT_WAPI),) +PLATFORM_FLAGS += -DCFG_SUPPORT_WAPI=$(CFG_SUPPORT_WAPI) +endif + +all: driver + +driver: + +cd $(DRIVER_DIR) && make -C $(LINUX_SRC) M=$(DRIVER_DIR) PLATFORM_FLAGS="$(PLATFORM_FLAGS)" modules + @cd $(DRIVER_DIR) && cp $(MODULES_NAME)_$(hif).ko $(MODULES_NAME).ko + +clean: driver_clean + +driver_clean: + cd $(DRIVER_DIR) && make -C $(LINUX_SRC) M=$(DRIVER_DIR) clean + +.PHONY: all clean driver driver_clean diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/common/cmm_asic_connac.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/common/cmm_asic_connac.c new file mode 100644 index 0000000000000..659b0cce6941d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/common/cmm_asic_connac.c @@ -0,0 +1,1141 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file connac.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. + */ + +/******************************************************************************* + * C O M P I L E 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 + ******************************************************************************* + */ + + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +#if defined(_HIF_USB) +/* + * USB Endpoint OUT/DMA Scheduler Group Mapping (HW Define) + * EP#4 / Group0 (DATA) + * EP#5 / Group1 (DATA) + * EP#6 / Group2 (DATA) + * EP#7 / Group3 (DATA) + * EP#9 / Group4 (DATA) + * EP#8 / Group15 (CMD) + */ +uint8_t arAcQIdx2GroupId[MAC_TXQ_NUM] = { + GROUP0_INDEX, /* MAC_TXQ_AC0_INDEX */ + GROUP1_INDEX, /* MAC_TXQ_AC1_INDEX */ + GROUP2_INDEX, /* MAC_TXQ_AC2_INDEX */ + GROUP3_INDEX, /* MAC_TXQ_AC3_INDEX */ + + GROUP4_INDEX, /* MAC_TXQ_AC10_INDEX */ + GROUP4_INDEX, /* MAC_TXQ_AC11_INDEX */ + GROUP4_INDEX, /* MAC_TXQ_AC12_INDEX */ + GROUP4_INDEX, /* MAC_TXQ_AC13_INDEX */ + + GROUP4_INDEX, /* MAC_TXQ_AC20_INDEX */ + GROUP4_INDEX, /* MAC_TXQ_AC21_INDEX */ + GROUP4_INDEX, /* MAC_TXQ_AC22_INDEX */ + GROUP4_INDEX, /* MAC_TXQ_AC23_INDEX */ + + GROUP4_INDEX, /* MAC_TXQ_AC30_INDEX */ + GROUP4_INDEX, /* MAC_TXQ_AC31_INDEX */ + GROUP4_INDEX, /* MAC_TXQ_AC32_INDEX */ + GROUP4_INDEX, /* MAC_TXQ_AC33_INDEX */ + + GROUP4_INDEX, /* MAC_TXQ_ALTX_0_INDEX */ + GROUP4_INDEX, /* MAC_TXQ_BMC_0_INDEX */ + GROUP4_INDEX, /* MAC_TXQ_BCN_0_INDEX */ + GROUP4_INDEX, /* MAC_TXQ_PSMP_0_INDEX */ + + GROUP5_INDEX, /* Reserved */ + GROUP5_INDEX, /* Reserved */ + GROUP5_INDEX, /* Reserved */ + GROUP5_INDEX, /* Reserved */ + + GROUP5_INDEX, /* Reserved */ + GROUP5_INDEX, /* Reserved */ +}; +#endif /* _HIF_USB */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +#if defined(_HIF_USB) +#define USB_DMA_SHDL_GROUP_DEF_SEQUENCE_ORDER 0xFFFEFFFF +#define USB_DMA_SHDL_GROUP_DEF_MIN_QUOTA 0x3 +#define USB_DMA_SHDL_GROUP_DEF_MAX_QUOTA 0x1FF +#define USB_ACCESS_RETRY_LIMIT 1 +#endif /* _HIF_USB */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +void asicCapInit(IN struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + prChipInfo = prAdapter->chip_info; + + prChipInfo->u2HifTxdSize = 0; + prChipInfo->u2TxInitCmdPort = 0; + prChipInfo->u2TxFwDlPort = 0; + prChipInfo->fillHifTxDesc = NULL; + prChipInfo->u4ExtraTxByteCount = 0; + + switch (prGlueInfo->u4InfType) { +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + case MT_DEV_INF_PCIE: + case MT_DEV_INF_AXI: + prChipInfo->u2TxInitCmdPort = TX_RING_FWDL_IDX_3; + prChipInfo->u2TxFwDlPort = TX_RING_FWDL_IDX_3; + prChipInfo->ucPacketFormat = TXD_PKT_FORMAT_TXD; + prChipInfo->u4HifDmaShdlBaseAddr = PCIE_HIF_DMASHDL_BASE; + + HAL_MCR_WR(prAdapter, CONN_HIF_ON_IRQ_ENA, BIT(0)); + break; +#endif /* _HIF_PCIE */ +#if defined(_HIF_USB) + case MT_DEV_INF_USB: + prChipInfo->u2HifTxdSize = USB_HIF_TXD_LEN; + prChipInfo->fillHifTxDesc = fillUsbHifTxDesc; + prChipInfo->u2TxInitCmdPort = USB_DATA_BULK_OUT_EP8; + prChipInfo->u2TxFwDlPort = USB_DATA_BULK_OUT_EP4; + prChipInfo->ucPacketFormat = TXD_PKT_FORMAT_TXD_PAYLOAD; + prChipInfo->u4ExtraTxByteCount = + EXTRA_TXD_SIZE_FOR_TX_BYTE_COUNT; + prChipInfo->u4HifDmaShdlBaseAddr = USB_HIF_DMASHDL_BASE; + asicUsbDmaShdlInit(prAdapter); + asicUdmaTxTimeoutEnable(prAdapter); + asicUdmaRxFlush(prAdapter, FALSE); + asicPdmaHifReset(prAdapter, TRUE); + break; +#endif /* _HIF_USB */ +#if defined(_HIF_SDIO) + case MT_DEV_INF_SDIO: + prChipInfo->ucPacketFormat = TXD_PKT_FORMAT_TXD_PAYLOAD; + prChipInfo->u4ExtraTxByteCount = + EXTRA_TXD_SIZE_FOR_TX_BYTE_COUNT; + break; +#endif /* _HIF_SDIO */ + default: + break; + } +} + +uint32_t asicGetFwDlInfo(struct ADAPTER *prAdapter, + char *pcBuf, int i4TotalLen) +{ + struct TAILER_COMMON_FORMAT_T *prComTailer; + uint32_t u4Offset = 0; + uint8_t aucBuf[32]; + + prComTailer = &prAdapter->rVerInfo.rCommonTailer; + + kalMemZero(aucBuf, 32); + kalMemCopy(aucBuf, prComTailer->aucRamVersion, 10); + u4Offset += snprintf(pcBuf + u4Offset, i4TotalLen - u4Offset, + "Tailer Ver[%u:%u] %s (%s) info %u:E%u\n", + prComTailer->ucFormatVer, + prComTailer->ucFormatFlag, + aucBuf, + prComTailer->aucRamBuiltDate, + prComTailer->ucChipInfo, + prComTailer->ucEcoCode + 1); + + if (prComTailer->ucFormatFlag) { + u4Offset += snprintf(pcBuf + u4Offset, i4TotalLen - u4Offset, + "Release manifest: %s\n", + prAdapter->rVerInfo.aucReleaseManifest); + } + return u4Offset; +} + +uint32_t asicGetChipID(struct ADAPTER *prAdapter) +{ + struct mt66xx_chip_info *prChipInfo; + uint32_t u4ChipID = 0; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + ASSERT(prChipInfo); + + /* Compose chipID from chip ip version + * + * BIT(30, 31) : Coding type, 00: compact, 01: index table + * BIT(24, 29) : IP config (6 bits) + * BIT(8, 23) : IP version + * BIT(0, 7) : A die info + */ + + u4ChipID = (0x0 << 30) | + ((prChipInfo->u4ChipIpConfig & 0x3F) << 24) | + ((prChipInfo->u4ChipIpVersion & 0xF0000000) >> 8) | + ((prChipInfo->u4ChipIpVersion & 0x000F0000) >> 0) | + ((prChipInfo->u4ChipIpVersion & 0x00000F00) << 4) | + ((prChipInfo->u4ChipIpVersion & 0x0000000F) << 8) | + CONNAC_CHIP_ADIE_INFO; + + log_dbg(HAL, INFO, "ChipID = [0x%08x]\n", u4ChipID); + return u4ChipID; +} + +void asicEnableFWDownload(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnable) +{ + struct GLUE_INFO *prGlueInfo; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + + switch (prGlueInfo->u4InfType) { +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + case MT_DEV_INF_PCIE: + case MT_DEV_INF_AXI: + { + union WPDMA_GLO_CFG_STRUCT GloCfg; + + kalDevRegRead(prGlueInfo, WPDMA_GLO_CFG, &GloCfg.word); + + GloCfg.field_conn.bypass_dmashdl_txring3 = fgEnable; + + kalDevRegWrite(prGlueInfo, WPDMA_GLO_CFG, GloCfg.word); + } + break; +#endif /* _HIF_PCIE */ + +#if defined(_HIF_USB) + case MT_DEV_INF_USB: + { + uint32_t u4Value = 0; + + ASSERT(prAdapter); + + HAL_MCR_RD(prAdapter, CONNAC_UDMA_TX_QSEL, &u4Value); + + if (fgEnable) + u4Value |= FW_DL_EN; + else + u4Value &= ~FW_DL_EN; + + HAL_MCR_WR(prAdapter, CONNAC_UDMA_TX_QSEL, u4Value); + } + break; +#endif /* _HIF_USB */ + + default: + break; + } +} + +void fillNicTxDescAppend(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + OUT uint8_t *prTxDescBuffer) +{ + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + union HW_MAC_TX_DESC_APPEND *prHwTxDescAppend; + + /* Fill TxD append */ + prHwTxDescAppend = (union HW_MAC_TX_DESC_APPEND *) + prTxDescBuffer; + kalMemZero(prHwTxDescAppend, prChipInfo->txd_append_size); +} + +void fillNicTxDescAppendWithCR4(IN struct ADAPTER + *prAdapter, IN struct MSDU_INFO *prMsduInfo, + OUT uint8_t *prTxDescBuffer) +{ + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + union HW_MAC_TX_DESC_APPEND *prHwTxDescAppend; + + /* Fill TxD append */ + prHwTxDescAppend = (union HW_MAC_TX_DESC_APPEND *) + prTxDescBuffer; + kalMemZero(prHwTxDescAppend, prChipInfo->txd_append_size); + prHwTxDescAppend->CR4_APPEND.u2PktFlags = + HIT_PKT_FLAGS_CT_WITH_TXD; + prHwTxDescAppend->CR4_APPEND.ucBssIndex = + prMsduInfo->ucBssIndex; +} + +void fillTxDescAppendByHost(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN uint16_t u4MsduId, + IN phys_addr_t rDmaAddr, IN uint32_t u4Idx, + IN u_int8_t fgIsLast, + OUT uint8_t *pucBuffer) +{ + union HW_MAC_TX_DESC_APPEND *prHwTxDescAppend; + struct TXD_PTR_LEN *prPtrLen; + + prHwTxDescAppend = (union HW_MAC_TX_DESC_APPEND *) ( + pucBuffer + NIC_TX_DESC_LONG_FORMAT_LENGTH); + prHwTxDescAppend->CONNAC_APPEND.au2MsduId[u4Idx] = + u4MsduId | TXD_MSDU_ID_VLD; + prPtrLen = &prHwTxDescAppend->CONNAC_APPEND.arPtrLen[u4Idx >> 1]; + if ((u4Idx & 1) == 0) { + prPtrLen->u4Ptr0 = rDmaAddr; + prPtrLen->u2Len0 = prMsduInfo->u2FrameLength | TXD_LEN_ML; + if (fgIsLast) + prPtrLen->u2Len0 |= TXD_LEN_AL; + } else { + prPtrLen->u4Ptr1 = rDmaAddr; + prPtrLen->u2Len1 = prMsduInfo->u2FrameLength | TXD_LEN_ML; + if (fgIsLast) + prPtrLen->u2Len1 |= TXD_LEN_AL; + } +} + +void fillTxDescAppendByHostV2(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN uint16_t u4MsduId, + IN phys_addr_t rDmaAddr, IN uint32_t u4Idx, + IN u_int8_t fgIsLast, + OUT uint8_t *pucBuffer) +{ + union HW_MAC_TX_DESC_APPEND *prHwTxDescAppend; + struct TXD_PTR_LEN *prPtrLen; + uint64_t u8Addr = (uint64_t)rDmaAddr; + + prHwTxDescAppend = (union HW_MAC_TX_DESC_APPEND *) + (pucBuffer + NIC_TX_DESC_LONG_FORMAT_LENGTH); + prHwTxDescAppend->CONNAC_APPEND.au2MsduId[u4Idx] = + u4MsduId | TXD_MSDU_ID_VLD; + prPtrLen = &prHwTxDescAppend->CONNAC_APPEND.arPtrLen[u4Idx >> 1]; + + if ((u4Idx & 1) == 0) { + prPtrLen->u4Ptr0 = (uint32_t)u8Addr; + prPtrLen->u2Len0 = + (prMsduInfo->u2FrameLength & TXD_LEN_MASK_V2) | + ((u8Addr >> TXD_ADDR2_OFFSET) & TXD_ADDR2_MASK); + prPtrLen->u2Len0 |= TXD_LEN_ML_V2; + } else { + prPtrLen->u4Ptr1 = (uint32_t)u8Addr; + prPtrLen->u2Len1 = + (prMsduInfo->u2FrameLength & TXD_LEN_MASK_V2) | + ((u8Addr >> TXD_ADDR2_OFFSET) & TXD_ADDR2_MASK); + prPtrLen->u2Len1 |= TXD_LEN_ML_V2; + } +} + +void fillTxDescAppendByCR4(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN uint16_t u4MsduId, + IN phys_addr_t rDmaAddr, IN uint32_t u4Idx, + IN u_int8_t fgIsLast, + OUT uint8_t *pucBuffer) +{ + union HW_MAC_TX_DESC_APPEND *prHwTxDescAppend; + + prHwTxDescAppend = (union HW_MAC_TX_DESC_APPEND *) + (pucBuffer + NIC_TX_DESC_LONG_FORMAT_LENGTH); + prHwTxDescAppend->CR4_APPEND.u2MsduToken = u4MsduId; + prHwTxDescAppend->CR4_APPEND.ucBufNum = u4Idx + 1; + prHwTxDescAppend->CR4_APPEND.au4BufPtr[u4Idx] = rDmaAddr; + prHwTxDescAppend->CR4_APPEND.au2BufLen[u4Idx] = + prMsduInfo->u2FrameLength; +} + +void fillTxDescTxByteCount(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + struct HW_MAC_TX_DESC *prTxDesc) +{ + struct mt66xx_chip_info *prChipInfo; + uint32_t u4TxByteCount = NIC_TX_DESC_LONG_FORMAT_LENGTH; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + ASSERT(prTxDesc); + + prChipInfo = prAdapter->chip_info; + u4TxByteCount += prMsduInfo->u2FrameLength; + + if (prMsduInfo->ucPacketType == TX_PACKET_TYPE_DATA) + u4TxByteCount += prChipInfo->u4ExtraTxByteCount; + + /* Calculate Tx byte count */ + HAL_MAC_TX_DESC_SET_TX_BYTE_COUNT(prTxDesc, u4TxByteCount); +} + +void fillTxDescTxByteCountWithCR4(IN struct ADAPTER + *prAdapter, IN struct MSDU_INFO *prMsduInfo, + struct HW_MAC_TX_DESC *prTxDesc) +{ + struct mt66xx_chip_info *prChipInfo; + uint32_t u4TxByteCount = NIC_TX_DESC_LONG_FORMAT_LENGTH; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + ASSERT(prTxDesc); + + prChipInfo = prAdapter->chip_info; + u4TxByteCount += prMsduInfo->u2FrameLength; + + if (prMsduInfo->ucPacketType == TX_PACKET_TYPE_DATA) + u4TxByteCount += prChipInfo->txd_append_size; + + /* Calculate Tx byte count */ + HAL_MAC_TX_DESC_SET_TX_BYTE_COUNT(prTxDesc, u4TxByteCount); +} + +#if defined(_HIF_PCIE) || defined(_HIF_AXI) +void asicPcieDmaShdlInit(IN struct ADAPTER *prAdapter) +{ + uint32_t u4BaseAddr, u4MacVal; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + + prChipInfo = prAdapter->chip_info; + u4BaseAddr = prChipInfo->u4HifDmaShdlBaseAddr; + + HAL_MCR_RD(prAdapter, + CONN_HIF_DMASHDL_PACKET_MAX_SIZE(u4BaseAddr), &u4MacVal); + u4MacVal &= ~(PLE_PKT_MAX_SIZE_MASK | PSE_PKT_MAX_SIZE_MASK); + u4MacVal |= PLE_PKT_MAX_SIZE_NUM(0x1); + u4MacVal |= PSE_PKT_MAX_SIZE_NUM(0x18); /* 0x18 * 128 = 3K */ + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_PACKET_MAX_SIZE(u4BaseAddr), u4MacVal); + + u4MacVal = + (CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP1_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP2_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP3_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP4_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP5_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP6_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP7_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP8_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP9_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP10_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP11_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP12_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP13_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP14_REFILL_DISABLE_MASK | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP15_REFILL_DISABLE_MASK); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_REFILL_CONTROL(u4BaseAddr), u4MacVal); + + u4MacVal = DMASHDL_MIN_QUOTA_NUM(0x3); + u4MacVal |= DMASHDL_MAX_QUOTA_NUM(0xfff); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP0_CTRL(u4BaseAddr), u4MacVal); + + u4MacVal = 0; + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP1_CTRL(u4BaseAddr), u4MacVal); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP2_CTRL(u4BaseAddr), u4MacVal); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP3_CTRL(u4BaseAddr), u4MacVal); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP4_CTRL(u4BaseAddr), u4MacVal); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP5_CTRL(u4BaseAddr), u4MacVal); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP6_CTRL(u4BaseAddr), u4MacVal); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP7_CTRL(u4BaseAddr), u4MacVal); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP8_CTRL(u4BaseAddr), u4MacVal); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP9_CTRL(u4BaseAddr), u4MacVal); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP10_CTRL(u4BaseAddr), u4MacVal); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP11_CTRL(u4BaseAddr), u4MacVal); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP12_CTRL(u4BaseAddr), u4MacVal); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP13_CTRL(u4BaseAddr), u4MacVal); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP14_CTRL(u4BaseAddr), u4MacVal); +} + +void asicPdmaLoopBackConfig(struct GLUE_INFO *prGlueInfo, u_int8_t fgEnable) +{ + union WPDMA_GLO_CFG_STRUCT GloCfg; + uint32_t word = 1; + + kalDevRegRead(prGlueInfo, WPDMA_GLO_CFG, &GloCfg.word); + + GloCfg.field_conn.bypass_dmashdl_txring3 = 1; + GloCfg.field_conn.pdma_addr_ext_en = 0; + GloCfg.field_conn.omit_rx_info = 1; + GloCfg.field_conn.omit_tx_info = 1; + GloCfg.field_conn.multi_dma_en = 0; + GloCfg.field_conn.pdma_addr_ext_en = 0; + GloCfg.field_conn.tx_dma_en = 1; + GloCfg.field_conn.rx_dma_en = 1; + GloCfg.field_conn.multi_dma_en = 0; + + kalDevRegWrite(prGlueInfo, WPDMA_FIFO_TEST_MOD, word); + kalDevRegWrite(prGlueInfo, WPDMA_GLO_CFG, GloCfg.word); +} +#if CFG_SUPPORT_PCIE_L2 +void asicPdmaStop( + struct GLUE_INFO *prGlueInfo, + u_int8_t enable) +{ + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + union WPDMA_GLO_CFG_STRUCT GloCfg; + + HAL_MCR_RD(prAdapter, WPDMA_GLO_CFG, &GloCfg.word); + + if (enable == TRUE) { + GloCfg.field_conn.tx_dma_en = 0; + GloCfg.field_conn.rx_dma_en = 0; + } else { + GloCfg.field_conn.tx_dma_en = 1; + GloCfg.field_conn.rx_dma_en = 1; + } + + HAL_MCR_WR(prAdapter, WPDMA_GLO_CFG, GloCfg.word); + +} +#endif +void asicPdmaConfig(struct GLUE_INFO *prGlueInfo, u_int8_t fgEnable) +{ + struct BUS_INFO *prBusInfo = + prGlueInfo->prAdapter->chip_info->bus_info; + union WPDMA_GLO_CFG_STRUCT GloCfg; + union WPDMA_INT_MASK IntMask; + + kalDevRegRead(prGlueInfo, WPDMA_GLO_CFG, &GloCfg.word); + kalDevRegRead(prGlueInfo, WPDMA_INT_MSK, &IntMask.word); + + if (fgEnable == TRUE) { + GloCfg.field_conn.tx_dma_en = 1; + GloCfg.field_conn.rx_dma_en = 1; + GloCfg.field_conn.pdma_bt_size = 3; + GloCfg.field_conn.pdma_addr_ext_en = + (prBusInfo->u4DmaMask > 32) ? 1 : 0; + GloCfg.field_conn.tx_wb_ddone = 1; + GloCfg.field_conn.multi_dma_en = 2; + GloCfg.field_conn.fifo_little_endian = 1; + GloCfg.field_conn.clk_gate_dis = 1; + + IntMask.field.rx_done_0 = 1; + IntMask.field.rx_done_1 = 1; + IntMask.field.tx_done = + BIT(prBusInfo->tx_ring_fwdl_idx) | + BIT(prBusInfo->tx_ring_cmd_idx) | + BIT(prBusInfo->tx_ring_data_idx); + IntMask.field_conn.tx_coherent = 0; + IntMask.field_conn.rx_coherent = 0; + IntMask.field_conn.tx_dly_int = 0; + IntMask.field_conn.rx_dly_int = 0; + IntMask.field_conn.mcu2host_sw_int_ena = 1; + } else { + GloCfg.field_conn.tx_dma_en = 0; + GloCfg.field_conn.rx_dma_en = 0; + + IntMask.field_conn.rx_done_0 = 0; + IntMask.field_conn.rx_done_1 = 0; + IntMask.field_conn.tx_done = 0; + IntMask.field_conn.tx_coherent = 0; + IntMask.field_conn.rx_coherent = 0; + IntMask.field_conn.tx_dly_int = 0; + IntMask.field_conn.rx_dly_int = 0; + IntMask.field_conn.mcu2host_sw_int_ena = 0; + } + + kalDevRegWrite(prGlueInfo, WPDMA_INT_MSK, IntMask.word); + kalDevRegWrite(prGlueInfo, WPDMA_GLO_CFG, GloCfg.word); + kalDevRegWrite(prGlueInfo, MCU2HOST_SW_INT_ENA, + ERROR_DETECT_MASK); +} + +void asicEnableInterrupt(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + + ASSERT(prAdapter); + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + enable_irq(prHifInfo->u4IrqId); +} + +void asicDisableInterrupt(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + + ASSERT(prAdapter); + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + disable_irq_nosync(prHifInfo->u4IrqId); +} + +void asicLowPowerOwnRead(IN struct ADAPTER *prAdapter, + OUT u_int8_t *pfgResult) +{ + uint32_t u4RegValue; + + HAL_MCR_RD(prAdapter, CONN_HIF_ON_LPCTL, &u4RegValue); + *pfgResult = (u4RegValue & PCIE_LPCR_HOST_SET_OWN) == 0 ? + TRUE : FALSE; +} + +void asicLowPowerOwnSet(IN struct ADAPTER *prAdapter, + OUT u_int8_t *pfgResult) +{ + uint32_t u4RegValue; + + HAL_MCR_WR(prAdapter, CONN_HIF_ON_LPCTL, + PCIE_LPCR_HOST_SET_OWN); + HAL_MCR_RD(prAdapter, CONN_HIF_ON_LPCTL, &u4RegValue); + *pfgResult = (u4RegValue & PCIE_LPCR_HOST_SET_OWN) == 1; +} + +void asicLowPowerOwnClear(IN struct ADAPTER *prAdapter, + OUT u_int8_t *pfgResult) +{ + uint32_t u4RegValue; + + HAL_MCR_WR(prAdapter, CONN_HIF_ON_LPCTL, + PCIE_LPCR_HOST_CLR_OWN); + HAL_MCR_RD(prAdapter, CONN_HIF_ON_LPCTL, &u4RegValue); + *pfgResult = (u4RegValue & PCIE_LPCR_HOST_SET_OWN) == 0; +} + +#if defined(_HIF_PCIE) +void asicLowPowerOwnClearPCIe(IN struct ADAPTER *prAdapter, + OUT u_int8_t *pfgResult) +{ + struct GLUE_INFO *prGlueInfo; + struct GL_HIF_INFO *prHif = NULL; + + prGlueInfo = prAdapter->prGlueInfo; + prHif = &prGlueInfo->rHifInfo; + + pci_write_config_byte(prHif->pdev, + PCIE_DOORBELL_PUSH, + CR_PCIE_CFG_CLEAR_OWN); +} +#endif + +void asicWakeUpWiFi(IN struct ADAPTER *prAdapter) +{ + u_int8_t fgResult; + + ASSERT(prAdapter); + + HAL_LP_OWN_RD(prAdapter, &fgResult); + + if (fgResult) + prAdapter->fgIsFwOwn = FALSE; + else + HAL_LP_OWN_CLR(prAdapter, &fgResult); +} + +bool asicIsValidRegAccess(IN struct ADAPTER *prAdapter, IN uint32_t u4Register) +{ + uint32_t au4ExcludeRegs[] = { CONN_HIF_ON_LPCTL }; + uint32_t u4Idx, u4Size = sizeof(au4ExcludeRegs) / sizeof(uint32_t); + + if (wlanIsChipNoAck(prAdapter)) + return false; + + /* driver can access all consys registers on driver own */ + if (!prAdapter->fgIsFwOwn) + return true; + + /* only own control register can be accessed on fw own */ + for (u4Idx = 0; u4Idx < u4Size; u4Idx++) { + if (u4Register == au4ExcludeRegs[u4Idx]) + return true; + } + + return false; +} + +void asicGetMailboxStatus(IN struct ADAPTER *prAdapter, + OUT uint32_t *pu4Val) +{ + uint32_t u4RegValue; + + HAL_MCR_RD(prAdapter, + CONN_MCU_CONFG_ON_HOST_MAILBOX_WF_ADDR, &u4RegValue); + *pu4Val = u4RegValue; +} + +void asicSetDummyReg(struct GLUE_INFO *prGlueInfo) +{ + kalDevRegWrite(prGlueInfo, CONN_DUMMY_CR, PDMA_DUMMY_MAGIC_NUM); +} + +void asicCheckDummyReg(struct GLUE_INFO *prGlueInfo) +{ + struct GL_HIF_INFO *prHifInfo; + uint32_t u4Value = 0; + uint32_t u4Idx; + + prHifInfo = &prGlueInfo->rHifInfo; + kalDevRegRead(prGlueInfo, CONN_DUMMY_CR, &u4Value); + DBGLOG(HAL, TRACE, "Check sleep mode DummyReg[0x%x]\n", u4Value); + if (u4Value != PDMA_DUMMY_RESET_VALUE) + return; + + for (u4Idx = 0; u4Idx < NUM_OF_TX_RING; u4Idx++) + prHifInfo->TxRing[u4Idx].TxSwUsedIdx = 0; + DBGLOG(HAL, INFO, "Weakup from sleep mode\n"); + + /* Write sleep mode magic num to dummy reg */ + asicSetDummyReg(prGlueInfo); +} +#endif /* _HIF_PCIE || _HIF_AXI */ + +#if defined(_HIF_USB) +/* DMS Scheduler Init */ +void asicUsbDmaShdlGroupInit(IN struct ADAPTER *prAdapter, + uint32_t u4RefillGroup) +{ + uint32_t u4BaseAddr, u4MacVal = 0; + struct mt66xx_chip_info *prChipInfo; + uint32_t u4CfgVal = 0; + + ASSERT(prAdapter); + + prChipInfo = prAdapter->chip_info; + u4BaseAddr = prChipInfo->u4HifDmaShdlBaseAddr; + + HAL_MCR_RD(prAdapter, + CONN_HIF_DMASHDL_PACKET_MAX_SIZE(u4BaseAddr), &u4MacVal); + u4MacVal &= ~(PLE_PKT_MAX_SIZE_MASK | PSE_PKT_MAX_SIZE_MASK); + u4MacVal |= PLE_PKT_MAX_SIZE_NUM(0x1); + /* page size = 128 bytes */ + u4MacVal |= PSE_PKT_MAX_SIZE_NUM(DIV_ROUND_UP(USB_TX_CMD_BUF_SIZE, + 128)); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_PACKET_MAX_SIZE(u4BaseAddr), u4MacVal); + + u4RefillGroup |= + (CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP2_REFILL_PRIORITY_MASK + | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP3_REFILL_PRIORITY_MASK); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_REFILL_CONTROL(u4BaseAddr), u4RefillGroup); + + /* Use "User program group sequence order" by default.[16]1'b0 */ + HAL_MCR_RD(prAdapter, + CONN_HIF_DMASHDL_PAGE_SETTING(u4BaseAddr), &u4MacVal); + u4MacVal &= USB_DMA_SHDL_GROUP_DEF_SEQUENCE_ORDER; + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_PAGE_SETTING(u4BaseAddr), u4MacVal); + +#if CFG_SUPPORT_CFG_FILE + u4CfgVal = wlanCfgGetUint32(prAdapter, + "DmaShdlGroup1MinQuota", + USB_DMA_SHDL_GROUP_DEF_MIN_QUOTA); + u4MacVal = DMASHDL_MIN_QUOTA_NUM(u4CfgVal); + u4CfgVal = wlanCfgGetUint32(prAdapter, + "DmaShdlGroup1MaxQuota", + USB_DMA_SHDL_GROUP_DEF_MAX_QUOTA); + u4MacVal |= DMASHDL_MAX_QUOTA_NUM(u4CfgVal); +#else /* CFG_SUPPORT_CFG_FILE */ + u4MacVal = DMASHDL_MIN_QUOTA_NUM( + USB_DMA_SHDL_GROUP_DEF_MIN_QUOTA); + u4MacVal |= DMASHDL_MAX_QUOTA_NUM( + USB_DMA_SHDL_GROUP_DEF_MAX_QUOTA); +#endif /* !CFG_SUPPORT_CFG_FILE */ + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP1_CTRL(u4BaseAddr), u4MacVal); + +#if CFG_SUPPORT_CFG_FILE + u4CfgVal = wlanCfgGetUint32(prAdapter, + "DmaShdlGroup0MinQuota", + USB_DMA_SHDL_GROUP_DEF_MIN_QUOTA); + u4MacVal = DMASHDL_MIN_QUOTA_NUM(u4CfgVal); + u4CfgVal = wlanCfgGetUint32(prAdapter, + "DmaShdlGroup0MaxQuota", + USB_DMA_SHDL_GROUP_DEF_MAX_QUOTA); + u4MacVal |= DMASHDL_MAX_QUOTA_NUM(u4CfgVal); +#else /* CFG_SUPPORT_CFG_FILE */ + u4MacVal = DMASHDL_MIN_QUOTA_NUM( + USB_DMA_SHDL_GROUP_DEF_MIN_QUOTA); + u4MacVal |= DMASHDL_MAX_QUOTA_NUM( + USB_DMA_SHDL_GROUP_DEF_MAX_QUOTA); +#endif /* !CFG_SUPPORT_CFG_FILE */ + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP0_CTRL(u4BaseAddr), u4MacVal); + +#if CFG_SUPPORT_CFG_FILE + u4CfgVal = wlanCfgGetUint32(prAdapter, + "DmaShdlGroup2MinQuota", + USB_DMA_SHDL_GROUP_DEF_MIN_QUOTA); + u4MacVal = DMASHDL_MIN_QUOTA_NUM(u4CfgVal); + u4CfgVal = wlanCfgGetUint32(prAdapter, + "DmaShdlGroup2MaxQuota", + USB_DMA_SHDL_GROUP_DEF_MAX_QUOTA); + u4MacVal |= DMASHDL_MAX_QUOTA_NUM(u4CfgVal); +#else /* CFG_SUPPORT_CFG_FILE */ + u4MacVal = DMASHDL_MIN_QUOTA_NUM( + USB_DMA_SHDL_GROUP_DEF_MIN_QUOTA); + u4MacVal |= DMASHDL_MAX_QUOTA_NUM( + USB_DMA_SHDL_GROUP_DEF_MAX_QUOTA); +#endif /* !CFG_SUPPORT_CFG_FILE */ + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP2_CTRL(u4BaseAddr), u4MacVal); + +#if CFG_SUPPORT_CFG_FILE + u4CfgVal = wlanCfgGetUint32(prAdapter, + "DmaShdlGroup3MinQuota", + USB_DMA_SHDL_GROUP_DEF_MIN_QUOTA); + u4MacVal = DMASHDL_MIN_QUOTA_NUM(u4CfgVal); + u4CfgVal = wlanCfgGetUint32(prAdapter, + "DmaShdlGroup3MaxQuota", + USB_DMA_SHDL_GROUP_DEF_MAX_QUOTA); + u4MacVal |= DMASHDL_MAX_QUOTA_NUM(u4CfgVal); +#else /* CFG_SUPPORT_CFG_FILE */ + u4MacVal = DMASHDL_MIN_QUOTA_NUM( + USB_DMA_SHDL_GROUP_DEF_MIN_QUOTA); + u4MacVal |= DMASHDL_MAX_QUOTA_NUM( + USB_DMA_SHDL_GROUP_DEF_MAX_QUOTA); +#endif /* !CFG_SUPPORT_CFG_FILE */ + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP3_CTRL(u4BaseAddr), u4MacVal); + +#if CFG_SUPPORT_CFG_FILE + u4CfgVal = wlanCfgGetUint32(prAdapter, + "DmaShdlGroup4MinQuota", + USB_DMA_SHDL_GROUP_DEF_MIN_QUOTA); + u4MacVal = DMASHDL_MIN_QUOTA_NUM(u4CfgVal); + u4CfgVal = wlanCfgGetUint32(prAdapter, + "DmaShdlGroup4MaxQuota", + USB_DMA_SHDL_GROUP_DEF_MAX_QUOTA); + u4MacVal |= DMASHDL_MAX_QUOTA_NUM(u4CfgVal); +#else /* CFG_SUPPORT_CFG_FILE */ + u4MacVal = DMASHDL_MIN_QUOTA_NUM( + USB_DMA_SHDL_GROUP_DEF_MIN_QUOTA); + u4MacVal |= DMASHDL_MAX_QUOTA_NUM( + USB_DMA_SHDL_GROUP_DEF_MAX_QUOTA); +#endif /* !CFG_SUPPORT_CFG_FILE */ + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_GROUP4_CTRL(u4BaseAddr), u4MacVal); + + u4MacVal = ((arAcQIdx2GroupId[MAC_TXQ_AC0_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE0_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC1_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE1_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC2_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE2_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC3_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE3_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC10_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE4_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC11_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE5_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC12_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE6_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC13_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE7_MAPPING)); + HAL_MCR_WR(prAdapter, CONN_HIF_DMASHDL_Q_MAP0(u4BaseAddr), + u4MacVal); + + u4MacVal = ((arAcQIdx2GroupId[MAC_TXQ_AC20_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE8_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC21_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE9_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC22_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE10_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC23_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE11_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC30_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE12_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC31_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE13_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC32_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE14_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_AC33_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE15_MAPPING)); + HAL_MCR_WR(prAdapter, CONN_HIF_DMASHDL_Q_MAP1(u4BaseAddr), + u4MacVal); + + u4MacVal = ((arAcQIdx2GroupId[MAC_TXQ_ALTX_0_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE16_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_BMC_0_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE17_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_BCN_0_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE18_MAPPING) | + (arAcQIdx2GroupId[MAC_TXQ_PSMP_0_INDEX] << + CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE19_MAPPING)); + HAL_MCR_WR(prAdapter, CONN_HIF_DMASHDL_Q_MAP2(u4BaseAddr), + u4MacVal); +} + +void asicUsbDmaShdlInit(IN struct ADAPTER *prAdapter) +{ + uint32_t u4BaseAddr, u4MacVal; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + + prChipInfo = prAdapter->chip_info; + u4BaseAddr = prChipInfo->u4HifDmaShdlBaseAddr; + + /* + * Enable refill control group 0, 1, 2, 3, 4. + * Keep all group low refill priority to prevent low + * group starvation if we have high group. + */ + u4MacVal = + (CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP5_REFILL_DISABLE_MASK + | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP6_REFILL_DISABLE_MASK + | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP7_REFILL_DISABLE_MASK + | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP8_REFILL_DISABLE_MASK + | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP9_REFILL_DISABLE_MASK + | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP10_REFILL_DISABLE_MASK + | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP11_REFILL_DISABLE_MASK + | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP12_REFILL_DISABLE_MASK + | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP13_REFILL_DISABLE_MASK + | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP14_REFILL_DISABLE_MASK + | + CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP15_REFILL_DISABLE_MASK); + + asicUsbDmaShdlGroupInit(prAdapter, u4MacVal); + + /* + * HIF Scheduler Setting + * Group15(CMD) is highest priority. + */ + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_SHDL_SET0(u4BaseAddr), 0x6501234f); + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_SHDL_SET1(u4BaseAddr), 0xedcba987); + + HAL_MCR_WR(prAdapter, + CONN_HIF_DMASHDL_OPTIONAL_CONTROL(u4BaseAddr), 0x7004801c); +} + +u_int8_t asicUsbSuspend(IN struct ADAPTER *prAdapter, + IN struct GLUE_INFO *prGlueInfo) +{ + uint32_t u4Value; + int32_t ret = 0; + struct BUS_INFO *prBusInfo; + + DBGLOG(HAL, INFO, "%s ---->\n", __func__); + prBusInfo = prAdapter->chip_info->bus_info; + + + prGlueInfo->rHifInfo.state = USB_STATE_SUSPEND; + halDisableInterrupt(prGlueInfo->prAdapter); + halTxCancelAllSending(prGlueInfo->prAdapter); + + ret = usb_control_msg(prGlueInfo->rHifInfo.udev, + usb_sndctrlpipe(prGlueInfo->rHifInfo.udev, 0), + VND_REQ_FEATURE_SET, + DEVICE_VENDOR_REQUEST_OUT, + FEATURE_SET_WVALUE_SUSPEND, 0, + NULL, 0, + VENDOR_TIMEOUT_MS); + if (ret) { + DBGLOG(HAL, ERROR, + "%s:: VendorRequest FeatureSetResume ERROR: %x, enable PDMA TX again.\n", + __func__, (unsigned int)ret); + /* Enable PDMA TX again */ + HAL_MCR_RD(prAdapter, PDMA_IF_MISC, &u4Value); + u4Value |= PDMA_IF_MISC_TX_ENABLE_MASK; + HAL_MCR_WR(prAdapter, PDMA_IF_MISC, u4Value); + DBGLOG(HAL, INFO, "%s <----\n", __func__); + return FALSE; + } + DBGLOG(HAL, INFO, "%s <----\n", __func__); + return TRUE; +} + +uint8_t asicUsbEventEpDetected(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + int32_t ret = 0; + uint8_t ucRetryCount = 0; + u_int8_t ucEp5Disable = FALSE; + + ASSERT(FALSE == 0); + prGlueInfo = prAdapter->prGlueInfo; + prHifInfo = &prGlueInfo->rHifInfo; + + if (prHifInfo->fgEventEpDetected == FALSE) { + prHifInfo->fgEventEpDetected = TRUE; + do { + ret = mtk_usb_vendor_request(prGlueInfo, 0, + DEVICE_VENDOR_REQUEST_IN, + VND_REQ_EP5_IN_INFO, + 0, 0, &ucEp5Disable, + sizeof(ucEp5Disable)); + if (ret || ucRetryCount) + DBGLOG(HAL, ERROR, + "usb_control_msg() status: %x retry: %u\n", + (unsigned int)ret, ucRetryCount); + ucRetryCount++; + if (ucRetryCount > USB_ACCESS_RETRY_LIMIT) + break; + } while (ret); + + if (ret) { + kalSendAeeWarning(HIF_USB_ERR_TITLE_STR, + HIF_USB_ERR_DESC_STR + "USB() reports error: %x retry: %u", + ret, ucRetryCount); + DBGLOG(HAL, ERROR, + "usb_readl() reports error: %x retry: %u\n", ret, + ucRetryCount); + } else { + DBGLOG(HAL, INFO, + "%s: Get ucEp5Disable = %d\n", __func__, + ucEp5Disable); + if (ucEp5Disable) + prHifInfo->eEventEpType = EVENT_EP_TYPE_DATA_EP; + } + } + if (prHifInfo->eEventEpType == EVENT_EP_TYPE_DATA_EP) + return USB_DATA_EP_IN; + else + return USB_EVENT_EP_IN; +} + +void asicUdmaTxTimeoutEnable(IN struct ADAPTER *prAdapter) +{ + struct BUS_INFO *prBusInfo; + uint32_t u4Value; + + prBusInfo = prAdapter->chip_info->bus_info; + HAL_MCR_RD(prAdapter, prBusInfo->u4UdmaWlCfg_1_Addr, + &u4Value); + u4Value &= ~UDMA_WLCFG_1_TX_TIMEOUT_LIMIT_MASK; + u4Value |= UDMA_WLCFG_1_TX_TIMEOUT_LIMIT( + prBusInfo->u4UdmaTxTimeout); + HAL_MCR_WR(prAdapter, prBusInfo->u4UdmaWlCfg_1_Addr, + u4Value); + + HAL_MCR_RD(prAdapter, prBusInfo->u4UdmaWlCfg_0_Addr, + &u4Value); + u4Value |= UDMA_WLCFG_0_TX_TIMEOUT_EN_MASK; + HAL_MCR_WR(prAdapter, prBusInfo->u4UdmaWlCfg_0_Addr, + u4Value); +} + +void asicUdmaRxFlush(IN struct ADAPTER *prAdapter, + IN u_int8_t bEnable) +{ + struct BUS_INFO *prBusInfo; + uint32_t u4Value; + + prBusInfo = prAdapter->chip_info->bus_info; + + HAL_MCR_RD(prAdapter, prBusInfo->u4UdmaWlCfg_0_Addr, + &u4Value); + if (bEnable) + u4Value |= UDMA_WLCFG_0_RX_FLUSH_MASK; + else + u4Value &= ~UDMA_WLCFG_0_RX_FLUSH_MASK; + HAL_MCR_WR(prAdapter, prBusInfo->u4UdmaWlCfg_0_Addr, + u4Value); +} + +void asicPdmaHifReset(IN struct ADAPTER *prAdapter, + IN u_int8_t bRelease) +{ + uint32_t u4Value; + + HAL_MCR_RD(prAdapter, PDMA_HIF_RESET, &u4Value); + if (bRelease) + u4Value |= DPMA_HIF_LOGIC_RESET_MASK; + else + u4Value &= ~DPMA_HIF_LOGIC_RESET_MASK; + HAL_MCR_WR(prAdapter, PDMA_HIF_RESET, u4Value); +} + +void fillUsbHifTxDesc(IN uint8_t **pDest, + IN uint16_t *pInfoBufLen) +{ + /*USB TX Descriptor (4 bytes)*/ + /* BIT[15:0] - TX Bytes Count + * (Not including USB TX Descriptor and 4-bytes zero padding. + */ + kalMemZero((void *)*pDest, sizeof(uint32_t)); + kalMemCopy((void *)*pDest, (void *) pInfoBufLen, + sizeof(uint16_t)); +} +#endif /* _HIF_USB */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/common/fw_dl.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/common/fw_dl.c new file mode 100644 index 0000000000000..cc1c73b13399d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/common/fw_dl.c @@ -0,0 +1,2070 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file fw_dl.c + */ + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" + +/******************************************************************************* + * C O N S T A N T 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 S + ******************************************************************************* + */ + +#if CFG_ENABLE_FW_DOWNLOAD +uint32_t wlanGetDataMode(IN struct ADAPTER *prAdapter, + IN enum ENUM_IMG_DL_IDX_T eDlIdx, IN uint8_t ucFeatureSet) +{ + uint32_t u4DataMode = 0; + + if (ucFeatureSet & DOWNLOAD_CONFIG_ENCRYPTION_MODE) { + u4DataMode |= DOWNLOAD_CONFIG_RESET_OPTION; + u4DataMode |= (ucFeatureSet & + DOWNLOAD_CONFIG_KEY_INDEX_MASK); + u4DataMode |= DOWNLOAD_CONFIG_ENCRYPTION_MODE; + } + + if (eDlIdx == IMG_DL_IDX_CR4_FW) + u4DataMode |= DOWNLOAD_CONFIG_WORKING_PDA_OPTION; + +#if CFG_ENABLE_FW_DOWNLOAD_ACK + u4DataMode |= DOWNLOAD_CONFIG_ACK_OPTION; /* ACK needed */ +#endif + return u4DataMode; +} + +void wlanGetHarvardFwInfo(IN struct ADAPTER *prAdapter, + IN uint8_t u4SecIdx, IN enum ENUM_IMG_DL_IDX_T eDlIdx, + OUT uint32_t *pu4Addr, OUT uint32_t *pu4Len, + OUT uint32_t *pu4DataMode, OUT u_int8_t *pfgIsEMIDownload) +{ + struct TAILER_FORMAT_T *prTailer; + + if (eDlIdx == IMG_DL_IDX_N9_FW) + prTailer = &prAdapter->rVerInfo.rN9tailer[u4SecIdx]; + else + prTailer = &prAdapter->rVerInfo.rCR4tailer[u4SecIdx]; + + *pu4Addr = prTailer->addr; + *pu4Len = (prTailer->len + LEN_4_BYTE_CRC); + *pu4DataMode = wlanGetDataMode(prAdapter, eDlIdx, + prTailer->feature_set); + *pfgIsEMIDownload = FALSE; +} + +void wlanGetConnacFwInfo(IN struct ADAPTER *prAdapter, + IN uint8_t u4SecIdx, IN enum ENUM_IMG_DL_IDX_T eDlIdx, + OUT uint32_t *pu4Addr, OUT uint32_t *pu4Len, + OUT uint32_t *pu4DataMode, OUT u_int8_t *pfgIsEMIDownload) +{ + struct TAILER_REGION_FORMAT_T *prTailer = + &prAdapter->rVerInfo.rRegionTailers[u4SecIdx]; + + *pu4Addr = prTailer->u4Addr; + *pu4Len = prTailer->u4Len; + *pu4DataMode = wlanGetDataMode(prAdapter, eDlIdx, + prTailer->ucFeatureSet); + *pfgIsEMIDownload = prTailer->ucFeatureSet & + DOWNLOAD_CONFIG_EMI; +} + +#if CFG_SUPPORT_COMPRESSION_FW_OPTION +void wlanImageSectionGetCompressFwInfo(IN struct ADAPTER + *prAdapter, IN void *pvFwImageMapFile, + IN uint32_t u4FwImageFileLength, IN uint8_t ucTotSecNum, + IN uint8_t ucCurSecNum, IN enum ENUM_IMG_DL_IDX_T eDlIdx, + OUT uint32_t *pu4Addr, OUT uint32_t *pu4Len, + OUT uint32_t *pu4DataMode, OUT uint32_t *pu4BlockSize, + OUT uint32_t *pu4CRC, OUT uint32_t *pu4UncompressedLength) +{ + struct FW_IMAGE_TAILER_T_2 *prFwHead; + struct TAILER_FORMAT_T_2 *prTailer; + uint8_t aucBuf[32]; + + prFwHead = (struct FW_IMAGE_TAILER_T_2 *) + (pvFwImageMapFile + u4FwImageFileLength - sizeof( + struct FW_IMAGE_TAILER_T_2)); + if (ucTotSecNum == 1) + prTailer = &prFwHead->dlm_info; + else + prTailer = &prFwHead->ilm_info; + + prTailer = &prTailer[ucCurSecNum]; + + *pu4Addr = prTailer->addr; + *pu4Len = (prTailer->len); + *pu4BlockSize = (prTailer->block_size); + *pu4CRC = (prTailer->crc); + *pu4UncompressedLength = (prTailer->real_size); + *pu4DataMode = wlanGetDataMode(prAdapter, eDlIdx, + prTailer->feature_set); + + /* Dump image information */ + if (ucCurSecNum == 0) { + DBGLOG(INIT, INFO, + "%s INFO: chip_info[%u:E%u] feature[0x%02X]\n", + (eDlIdx == IMG_DL_IDX_N9_FW) ? "N9" : "CR4", + prTailer->chip_info, + prTailer->eco_code, prTailer->feature_set); + kalMemZero(aucBuf, 32); + kalStrnCpy(aucBuf, prTailer->ram_version, + sizeof(prTailer->ram_version)); + DBGLOG(INIT, INFO, "date[%s] version[%s]\n", + prTailer->ram_built_date, aucBuf); + } + /* Backup to FW version info */ + if (eDlIdx == IMG_DL_IDX_N9_FW) { + kalMemCopy(&prAdapter->rVerInfo.rN9Compressedtailer, + prTailer, sizeof(struct TAILER_FORMAT_T_2)); + prAdapter->rVerInfo.fgIsN9CompressedFW = TRUE; + } else { + kalMemCopy(&prAdapter->rVerInfo.rCR4Compressedtailer, + prTailer, sizeof(struct TAILER_FORMAT_T_2)); + prAdapter->rVerInfo.fgIsCR4CompressedFW = TRUE; + } +} +#endif + +void wlanImageSectionGetPatchInfo(IN struct ADAPTER + *prAdapter, + IN void *pvFwImageMapFile, IN uint32_t u4FwImageFileLength, + OUT uint32_t *pu4StartOffset, OUT uint32_t *pu4Addr, + OUT uint32_t *pu4Len, + OUT uint32_t *pu4DataMode) +{ + struct PATCH_FORMAT_T *prPatchFormat; + uint8_t aucBuffer[32]; + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + + prPatchFormat = (struct PATCH_FORMAT_T *) pvFwImageMapFile; + + *pu4StartOffset = offsetof(struct PATCH_FORMAT_T, + ucPatchImage); + *pu4Addr = prChipInfo->patch_addr; + *pu4Len = u4FwImageFileLength - offsetof(struct + PATCH_FORMAT_T, ucPatchImage); + *pu4DataMode = wlanGetDataMode(prAdapter, IMG_DL_IDX_PATCH, + 0); + + /* Dump image information */ + kalMemZero(aucBuffer, 32); + kalStrnCpy(aucBuffer, prPatchFormat->aucPlatform, 4); + DBGLOG(INIT, INFO, + "PATCH INFO: platform[%s] HW/SW ver[0x%04X] ver[0x%04X]\n", + aucBuffer, prPatchFormat->u4SwHwVersion, + prPatchFormat->u4PatchVersion); + + kalStrnCpy(aucBuffer, prPatchFormat->aucBuildDate, 16); + DBGLOG(INIT, INFO, "date[%s]\n", aucBuffer); + + /* Backup to FW version info */ + kalMemCopy(&prAdapter->rVerInfo.rPatchHeader, prPatchFormat, + sizeof(struct PATCH_FORMAT_T)); +} + +uint32_t wlanDownloadSection(IN struct ADAPTER *prAdapter, + IN uint32_t u4Addr, IN uint32_t u4Len, + IN uint32_t u4DataMode, IN uint8_t *pucStartPtr, + IN enum ENUM_IMG_DL_IDX_T eDlIdx) +{ + uint32_t u4ImgSecSize, u4Offset; + uint8_t *pucSecBuf; + + if (wlanImageSectionConfig(prAdapter, u4Addr, u4Len, + u4DataMode, eDlIdx) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "Firmware download configuration failed!\n"); + return WLAN_STATUS_FAILURE; + } + + for (u4Offset = 0; u4Offset < u4Len; + u4Offset += CMD_PKT_SIZE_FOR_IMAGE) { + if (u4Offset + CMD_PKT_SIZE_FOR_IMAGE < u4Len) + u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; + else + u4ImgSecSize = u4Len - u4Offset; + + pucSecBuf = (uint8_t *) pucStartPtr + u4Offset; + if (wlanImageSectionDownload(prAdapter, u4ImgSecSize, + pucSecBuf) != + WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "Firmware scatter download failed!\n"); + return WLAN_STATUS_FAILURE; + } + } + + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanDownloadEMISection(IN struct ADAPTER + *prAdapter, IN uint32_t u4DestAddr, + IN uint32_t u4Len, IN uint8_t *pucStartPtr) +{ +#if CFG_MTK_ANDROID_EMI + uint8_t __iomem *pucEmiBaseAddr = NULL; + uint32_t u4Offset = u4DestAddr & WIFI_EMI_ADDR_MASK; + + if (!gConEmiPhyBase) { + DBGLOG(INIT, ERROR, + "Consys emi memory address gConEmiPhyBase invalid\n"); + return WLAN_STATUS_FAILURE; + } + + request_mem_region(gConEmiPhyBase, gConEmiSize, "WIFI-EMI"); + kalSetEmiMpuProtection(gConEmiPhyBase, WIFI_EMI_MEM_OFFSET, + WIFI_EMI_MEM_SIZE, false); + pucEmiBaseAddr = ioremap_nocache(gConEmiPhyBase, gConEmiSize); + DBGLOG(INIT, INFO, + "EmiPhyBase:0x%llx offset:0x%x, ioremap region 0x%lX @ 0x%lX\n", + (uint64_t)gConEmiPhyBase, u4Offset, gConEmiSize, pucEmiBaseAddr); + if (!pucEmiBaseAddr) { + DBGLOG(INIT, ERROR, "ioremap failed\n"); + return WLAN_STATUS_FAILURE; + } + + kalMemCopy((pucEmiBaseAddr + u4Offset), pucStartPtr, u4Len); + + kalSetEmiMpuProtection(gConEmiPhyBase, WIFI_EMI_MEM_OFFSET, + WIFI_EMI_MEM_SIZE, true); + iounmap(pucEmiBaseAddr); + release_mem_region(gConEmiPhyBase, gConEmiSize); +#endif /* CFG_MTK_ANDROID_EMI */ + return WLAN_STATUS_SUCCESS; +} + +#if CFG_SUPPORT_COMPRESSION_FW_OPTION +u_int8_t wlanImageSectionCheckFwCompressInfo( + IN struct ADAPTER *prAdapter, + IN void *pvFwImageMapFile, IN uint32_t u4FwImageFileLength, + IN enum ENUM_IMG_DL_IDX_T eDlIdx) +{ + uint8_t ucCompression; + struct FW_IMAGE_TAILER_CHECK *prCheckInfo; + + if (eDlIdx == IMG_DL_IDX_PATCH) + return FALSE; + + prCheckInfo = (struct FW_IMAGE_TAILER_CHECK *) + (pvFwImageMapFile + u4FwImageFileLength - sizeof( + struct FW_IMAGE_TAILER_CHECK)); + DBGLOG(INIT, INFO, "feature_set %d\n", + prCheckInfo->feature_set); + ucCompression = (uint8_t)((prCheckInfo->feature_set & + COMPRESSION_OPTION_MASK) + >> COMPRESSION_OPTION_OFFSET); + DBGLOG(INIT, INFO, "Compressed Check INFORMATION %d\n", + ucCompression); + if (ucCompression == 1) { + DBGLOG(INIT, INFO, "Compressed FW\n"); + return TRUE; + } + return FALSE; +} + +uint32_t wlanCompressedImageSectionDownloadStage( + IN struct ADAPTER *prAdapter, IN void *pvFwImageMapFile, + IN uint32_t u4FwImageFileLength, IN uint8_t ucSectionNumber, + IN enum ENUM_IMG_DL_IDX_T eDlIdx, + OUT uint8_t *pucIsCompressed, + OUT struct INIT_CMD_WIFI_DECOMPRESSION_START *prFwImageInFo) +{ + uint32_t i; + int32_t i4TotalLen; + uint32_t u4FileOffset = 0; + uint32_t u4StartOffset = 0; + uint32_t u4DataMode = 0; + uint32_t u4Addr, u4Len, u4BlockSize, u4CRC; + uint32_t u4UnCompressedLength; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + uint8_t *pucStartPtr; + uint32_t u4offset = 0, u4ChunkSize; + /* 3a. parse file header for decision of + * divided firmware download or not + */ + if (wlanImageSectionCheckFwCompressInfo(prAdapter, + pvFwImageMapFile, + u4FwImageFileLength, + eDlIdx) == TRUE) { + for (i = 0; i < ucSectionNumber; ++i) { + wlanImageSectionGetCompressFwInfo(prAdapter, + pvFwImageMapFile, + u4FwImageFileLength, ucSectionNumber, i, eDlIdx, + &u4Addr, &u4Len, &u4DataMode, + &u4BlockSize, &u4CRC, &u4UnCompressedLength); + u4offset = 0; + if (i == 0) { + prFwImageInFo->u4BlockSize = u4BlockSize; + prFwImageInFo->u4Region1Address = u4Addr; + prFwImageInFo->u4Region1CRC = u4CRC; + prFwImageInFo->u4Region1length = + u4UnCompressedLength; + } else { + prFwImageInFo->u4Region2Address = u4Addr; + prFwImageInFo->u4Region2CRC = u4CRC; + prFwImageInFo->u4Region2length = + u4UnCompressedLength; + } + i4TotalLen = u4Len; + DBGLOG(INIT, INFO, + "DL Offset[%u] addr[0x%08x] len[%u] datamode[0x%08x]\n", + u4FileOffset, u4Addr, u4Len, u4DataMode); + DBGLOG(INIT, INFO, "DL BLOCK[%u] COMlen[%u] CRC[%u]\n", + u4BlockSize, u4UnCompressedLength, u4CRC); + pucStartPtr = + (uint8_t *) pvFwImageMapFile + u4StartOffset; + while (i4TotalLen) { + u4ChunkSize = *((unsigned int *)(pucStartPtr + + u4FileOffset)); + u4FileOffset += 4; + DBGLOG(INIT, INFO, + "Downloaded Length %d! Addr %x\n", + i4TotalLen, u4Addr + u4offset); + DBGLOG(INIT, INFO, + "u4ChunkSize Length %d!\n", + u4ChunkSize); + + u4Status = wlanDownloadSection(prAdapter, + u4Addr + u4offset, + u4ChunkSize, + u4DataMode, + pvFwImageMapFile + u4FileOffset, + eDlIdx); + /* escape from loop if any + * pending error occurs + */ + if (u4Status == WLAN_STATUS_FAILURE) + break; + + i4TotalLen -= u4ChunkSize; + u4offset += u4BlockSize; + u4FileOffset += u4ChunkSize; + if (i4TotalLen < 0) { + DBGLOG(INIT, ERROR, + "Firmware scatter download failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } + } + } + *pucIsCompressed = TRUE; + } else { + u4Status = wlanImageSectionDownloadStage(prAdapter, + pvFwImageMapFile, u4FwImageFileLength, + ucSectionNumber, eDlIdx); + *pucIsCompressed = FALSE; + } + return u4Status; +} +#endif + +uint32_t wlanImageSectionDownloadStage( + IN struct ADAPTER *prAdapter, IN void *pvFwImageMapFile, + IN uint32_t u4FwImageFileLength, IN uint8_t ucSectionNumber, + IN enum ENUM_IMG_DL_IDX_T eDlIdx) +{ + uint32_t u4SecIdx, u4Offset = 0; + uint32_t u4Addr, u4Len, u4DataMode = 0; + u_int8_t fgIsEMIDownload = FALSE; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + + /* 3a. parse file header for decision of + * divided firmware download or not + */ + if (eDlIdx == IMG_DL_IDX_PATCH) { + wlanImageSectionGetPatchInfo(prAdapter, pvFwImageMapFile, + u4FwImageFileLength, + &u4Offset, &u4Addr, + &u4Len, &u4DataMode); + + DBGLOG(INIT, INFO, + "DL Offset[%u] addr[0x%08x] len[%u] datamode[0x%08x]\n", + u4Offset, u4Addr, u4Len, u4DataMode); + + u4Status = wlanDownloadSection(prAdapter, u4Addr, u4Len, + u4DataMode, + pvFwImageMapFile + u4Offset, + eDlIdx); + } else { + for (u4SecIdx = 0; u4SecIdx < ucSectionNumber; + u4SecIdx++, u4Offset += u4Len) { + prChipInfo->fw_dl_ops->getFwInfo(prAdapter, u4SecIdx, + eDlIdx, &u4Addr, + &u4Len, &u4DataMode, &fgIsEMIDownload); + + DBGLOG(INIT, INFO, + "DL Offset[%u] addr[0x%08x] len[%u] datamode[0x%08x]\n", + u4Offset, u4Addr, u4Len, u4DataMode); + + if (fgIsEMIDownload) + u4Status = wlanDownloadEMISection(prAdapter, + u4Addr, u4Len, + pvFwImageMapFile + u4Offset); + else + u4Status = wlanDownloadSection(prAdapter, + u4Addr, u4Len, + u4DataMode, + pvFwImageMapFile + u4Offset, eDlIdx); + + /* escape from loop if any pending error occurs */ + if (u4Status == WLAN_STATUS_FAILURE) + break; + } + } + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to confirm the status of + * previously patch semaphore control + * + * @param prAdapter Pointer to the Adapter structure. + * ucCmdSeqNum Sequence number of previous firmware scatter + * + * @return WLAN_STATUS_SUCCESS + * WLAN_STATUS_FAILURE + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanPatchRecvSemaResp(IN struct ADAPTER *prAdapter, + IN uint8_t ucCmdSeqNum, OUT uint8_t *pucPatchStatus) +{ + struct mt66xx_chip_info *prChipInfo; + uint8_t *aucBuffer; + uint32_t u4EventSize; + struct INIT_WIFI_EVENT *prInitEvent; + struct INIT_EVENT_CMD_RESULT *prEventCmdResult; + uint32_t u4RxPktLength; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) + return WLAN_STATUS_FAILURE; + + u4EventSize = prChipInfo->rxd_size + prChipInfo->init_event_size + + sizeof(struct INIT_EVENT_CMD_RESULT); + aucBuffer = kalMemAlloc(u4EventSize, PHY_MEM_TYPE); + + if (nicRxWaitResponse(prAdapter, 0, aucBuffer, u4EventSize, + &u4RxPktLength) != WLAN_STATUS_SUCCESS) { + + DBGLOG(INIT, WARN, "Wait patch semaphore response fail\n"); + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + return WLAN_STATUS_FAILURE; + } + + prInitEvent = (struct INIT_WIFI_EVENT *) + (aucBuffer + prChipInfo->rxd_size); + if (prInitEvent->ucEID != INIT_EVENT_ID_PATCH_SEMA_CTRL) { + DBGLOG(INIT, WARN, "Unexpected EVENT ID, get 0x%0x\n", + prInitEvent->ucEID); + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + return WLAN_STATUS_FAILURE; + } + + if (prInitEvent->ucSeqNum != ucCmdSeqNum) { + DBGLOG(INIT, WARN, "Unexpected SeqNum %d, %d\n", + ucCmdSeqNum, prInitEvent->ucSeqNum); + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + return WLAN_STATUS_FAILURE; + } + + prEventCmdResult = (struct INIT_EVENT_CMD_RESULT *) + prInitEvent->aucBuffer; + + *pucPatchStatus = prEventCmdResult->ucStatus; + + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to check the patch semaphore control. + * + * @param prAdapter Pointer to the Adapter structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanPatchSendSemaControl(IN struct ADAPTER + *prAdapter, OUT uint8_t *pucSeqNum) +{ + struct mt66xx_chip_info *prChipInfo; + struct CMD_INFO *prCmdInfo; + struct INIT_HIF_TX_HEADER *prInitHifTxHeader; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + struct INIT_CMD_PATCH_SEMA_CONTROL *prPatchSemaControl; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + DEBUGFUNC("wlanImagePatchSemaphoreCheck"); + + /* 1. Allocate CMD Info Packet and its Buffer. */ + prCmdInfo = + cmdBufAllocateCmdInfo(prAdapter, + sizeof(struct INIT_HIF_TX_HEADER) + sizeof( + struct INIT_CMD_PATCH_SEMA_CONTROL)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prCmdInfo->u2InfoBufLen = sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_CMD_PATCH_SEMA_CONTROL); + + /* 2. Setup common CMD Info Packet */ + prInitHifTxHeader = (struct INIT_HIF_TX_HEADER *) ( + prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prInitHifTxHeader->u2PQ_ID = INIT_CMD_PQ_ID; + prInitHifTxHeader->ucHeaderFormat = INIT_CMD_PACKET_TYPE_ID; + prInitHifTxHeader->ucPktFt = INIT_PKT_FT_CMD; + + prInitHifTxHeader->rInitWifiCmd.ucCID = + INIT_CMD_ID_PATCH_SEMAPHORE_CONTROL; + prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = + INIT_CMD_PDA_PACKET_TYPE_ID; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = + nicIncreaseCmdSeqNum(prAdapter); + + *pucSeqNum = prInitHifTxHeader->rInitWifiCmd.ucSeqNum; + + /* 3. Setup DOWNLOAD_BUF */ + prPatchSemaControl = (struct INIT_CMD_PATCH_SEMA_CONTROL *) + prInitHifTxHeader->rInitWifiCmd.aucBuffer; + kalMemZero(prPatchSemaControl, + sizeof(struct INIT_CMD_PATCH_SEMA_CONTROL)); + prPatchSemaControl->ucGetSemaphore = PATCH_GET_SEMA_CONTROL; + + /* 4. Send FW_Download command */ + if (nicTxInitCmd(prAdapter, prCmdInfo, + prChipInfo->u2TxInitCmdPort) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "Fail to transmit image download command\n"); + } + /* 5. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + +u_int8_t wlanPatchIsDownloaded(IN struct ADAPTER *prAdapter) +{ + uint8_t ucSeqNum, ucPatchStatus; + uint32_t rStatus; + uint32_t u4Count; + + ucPatchStatus = PATCH_STATUS_NO_SEMA_NEED_PATCH; + u4Count = 0; + + while (ucPatchStatus == PATCH_STATUS_NO_SEMA_NEED_PATCH) { + if (u4Count) + kalMdelay(100); + + rStatus = wlanPatchSendSemaControl(prAdapter, &ucSeqNum); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, WARN, + "Send patch SEMA control CMD failed!!\n"); + break; + } + + rStatus = wlanPatchRecvSemaResp(prAdapter, ucSeqNum, + &ucPatchStatus); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, WARN, + "Recv patch SEMA control EVT failed!!\n"); + break; + } + + u4Count++; + + if (u4Count > 50) { + DBGLOG(INIT, WARN, "Patch status check timeout!!\n"); + break; + } + } + + if (ucPatchStatus == PATCH_STATUS_NO_NEED_TO_PATCH) + return TRUE; + else + return FALSE; +} + +uint32_t wlanPatchSendComplete(IN struct ADAPTER *prAdapter) +{ + struct CMD_INFO *prCmdInfo; + struct INIT_HIF_TX_HEADER *prInitHifTxHeader; + uint8_t ucTC, ucCmdSeqNum; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + struct mt66xx_chip_info *prChipInfo; + struct INIT_CMD_PATCH_FINISH *prPatchFinish; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + /* 1. Allocate CMD Info Packet and its Buffer. */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + sizeof(struct INIT_HIF_TX_HEADER) + sizeof( + struct INIT_CMD_PATCH_FINISH)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + kalMemZero(prCmdInfo->pucInfoBuffer, + sizeof(struct INIT_HIF_TX_HEADER) + sizeof( + struct INIT_CMD_PATCH_FINISH)); + prCmdInfo->u2InfoBufLen = sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_CMD_PATCH_FINISH); + +#if (CFG_USE_TC4_RESOURCE_FOR_INIT_CMD == 1) + /* 2. Always use TC4 (TC4 as CPU) */ + ucTC = TC4_INDEX; +#else + /* 2. Use TC0's resource to send patch finish command. + * Only TC0 is allowed because SDIO HW always reports + * MCU's TXQ_CNT at TXQ0_CNT in CR4 architecutre) + */ + ucTC = TC0_INDEX; +#endif + + /* 3. increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* 4. Setup common CMD Info Packet */ + prInitHifTxHeader = (struct INIT_HIF_TX_HEADER *) ( + prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prInitHifTxHeader->u2PQ_ID = INIT_CMD_PQ_ID; + prInitHifTxHeader->ucPktFt = INIT_PKT_FT_CMD; + + prInitHifTxHeader->rInitWifiCmd.ucCID = + INIT_CMD_ID_PATCH_FINISH; + prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = + INIT_CMD_PACKET_TYPE_ID; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + prPatchFinish = (struct INIT_CMD_PATCH_FINISH *) + prInitHifTxHeader->rInitWifiCmd.aucBuffer; + prPatchFinish->ucCheckCrc = 0; + + /* 5. Seend WIFI start command */ + while (1) { + /* 5.1 Acquire TX Resource */ + if (nicTxAcquireResource(prAdapter, ucTC, + nicTxGetPageCount(prAdapter, + prCmdInfo->u2InfoBufLen, TRUE), + TRUE) == 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"); + goto exit; + } + continue; + } + /* 5.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo, + prChipInfo->u2TxInitCmdPort) != + WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "Fail to transmit WIFI start command\n"); + goto exit; + } + + break; + }; + + DBGLOG(INIT, INFO, + "PATCH FINISH CMD send, waiting for RSP\n"); + + /* kalMdelay(10000); */ + + u4Status = wlanConfigWifiFuncStatus(prAdapter, ucCmdSeqNum); + + if (u4Status != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "PATCH FINISH EVT failed\n"); + else + DBGLOG(INIT, INFO, "PATCH FINISH EVT success!!\n"); + +exit: + /* 6. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to configure FWDL parameters + * + * @param prAdapter Pointer to the Adapter structure. + * u4DestAddr Address of destination address + * u4ImgSecSize Length of the firmware block + * fgReset should be set to TRUE if this is the 1st configuration + * + * @return WLAN_STATUS_SUCCESS + * WLAN_STATUS_FAILURE + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanImageSectionConfig( + IN struct ADAPTER *prAdapter, + IN uint32_t u4DestAddr, IN uint32_t u4ImgSecSize, + IN uint32_t u4DataMode, + IN enum ENUM_IMG_DL_IDX_T eDlIdx) +{ + struct CMD_INFO *prCmdInfo; + struct INIT_HIF_TX_HEADER *prInitHifTxHeader; + struct INIT_CMD_DOWNLOAD_CONFIG *prInitCmdDownloadConfig; + uint8_t ucTC, ucCmdSeqNum; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + DEBUGFUNC("wlanImageSectionConfig"); + + if (u4ImgSecSize == 0) + return WLAN_STATUS_SUCCESS; + /* 1. Allocate CMD Info Packet and its Buffer. */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + sizeof(struct INIT_HIF_TX_HEADER) + sizeof( + struct INIT_CMD_DOWNLOAD_CONFIG)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prCmdInfo->u2InfoBufLen = sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_CMD_DOWNLOAD_CONFIG); + +#if (CFG_USE_TC4_RESOURCE_FOR_INIT_CMD == 1) + /* 2. Use TC4's resource to download image. (TC4 as CPU) */ + ucTC = TC4_INDEX; +#else + /* 2. Use TC0's resource to send init_cmd. + * Only TC0 is allowed because SDIO HW always reports + * MCU's TXQ_CNT at TXQ0_CNT in CR4 architecutre) + */ + ucTC = TC0_INDEX; +#endif + + /* 3. increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* 4. Setup common CMD Info Packet */ + prInitHifTxHeader = (struct INIT_HIF_TX_HEADER *) ( + prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prInitHifTxHeader->u2PQ_ID = INIT_CMD_PQ_ID; + prInitHifTxHeader->ucHeaderFormat = INIT_CMD_PACKET_TYPE_ID; + prInitHifTxHeader->ucPktFt = INIT_PKT_FT_CMD; + + if (eDlIdx == IMG_DL_IDX_PATCH) + prInitHifTxHeader->rInitWifiCmd.ucCID = + INIT_CMD_ID_PATCH_START; + else + prInitHifTxHeader->rInitWifiCmd.ucCID = + INIT_CMD_ID_DOWNLOAD_CONFIG; + + + prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = + INIT_CMD_PACKET_TYPE_ID; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + /* 5. Setup CMD_DOWNLOAD_CONFIG */ + prInitCmdDownloadConfig = + (struct INIT_CMD_DOWNLOAD_CONFIG *) + (prInitHifTxHeader->rInitWifiCmd.aucBuffer); + prInitCmdDownloadConfig->u4Address = u4DestAddr; + prInitCmdDownloadConfig->u4Length = u4ImgSecSize; + prInitCmdDownloadConfig->u4DataMode = u4DataMode; + + /* 6. Send FW_Download command */ + while (1) { + /* 6.1 Acquire TX Resource */ + if (nicTxAcquireResource(prAdapter, ucTC, + nicTxGetPageCount(prAdapter, + prCmdInfo->u2InfoBufLen, TRUE), + TRUE) == 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"); + goto exit; + } + continue; + } + /* 6.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo, + prChipInfo->u2TxInitCmdPort) != + WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "Fail to transmit image download command\n"); + goto exit; + } + + break; + }; + +#if CFG_ENABLE_FW_DOWNLOAD_ACK + /* 7. Wait for INIT_EVENT_ID_CMD_RESULT */ + u4Status = wlanConfigWifiFuncStatus(prAdapter, ucCmdSeqNum); +#endif + +exit: + /* 8. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to download FW image. + * + * @param prAdapter Pointer to the Adapter structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanImageSectionDownload(IN struct ADAPTER + *prAdapter, IN uint32_t u4ImgSecSize, + IN uint8_t *pucImgSecBuf) +{ + struct CMD_INFO *prCmdInfo; + struct INIT_HIF_TX_HEADER *prInitHifTxHeader; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + ASSERT(pucImgSecBuf); + ASSERT(u4ImgSecSize <= CMD_PKT_SIZE_FOR_IMAGE); + + DEBUGFUNC("wlanImageSectionDownload"); + + prChipInfo = prAdapter->chip_info; + + if (u4ImgSecSize == 0) + return WLAN_STATUS_SUCCESS; + /* 1. Allocate CMD Info Packet and its Buffer. */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + sizeof(struct INIT_HIF_TX_HEADER) + + u4ImgSecSize); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prCmdInfo->u2InfoBufLen = sizeof(struct INIT_HIF_TX_HEADER) + + (uint16_t) u4ImgSecSize; + + /* 2. Setup common CMD Info Packet */ + prInitHifTxHeader = (struct INIT_HIF_TX_HEADER *) ( + prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prInitHifTxHeader->u2PQ_ID = INIT_CMD_PDA_PQ_ID; + prInitHifTxHeader->ucHeaderFormat = + INIT_CMD_PDA_PACKET_TYPE_ID; + prInitHifTxHeader->ucPktFt = INIT_PKT_FT_PDA_FWDL; + + prInitHifTxHeader->rInitWifiCmd.ucCID = 0; + prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = + INIT_CMD_PDA_PACKET_TYPE_ID; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = 0; + + /* 3. Setup DOWNLOAD_BUF */ + kalMemCopy(prInitHifTxHeader->rInitWifiCmd.aucBuffer, + pucImgSecBuf, u4ImgSecSize); + + /* 4. Send FW_Download command */ + if (nicTxInitCmd(prAdapter, prCmdInfo, + prChipInfo->u2TxFwDlPort) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "Fail to transmit image download command\n"); + } + /* 5. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to confirm previously firmware + * download is done without error + * + * @param prAdapter Pointer to the Adapter structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanImageQueryStatus(IN struct ADAPTER *prAdapter) +{ + struct mt66xx_chip_info *prChipInfo; + struct CMD_INFO *prCmdInfo; + struct INIT_HIF_TX_HEADER *prInitHifTxHeader; + uint8_t *aucBuffer; + uint32_t u4EventSize; + uint32_t u4RxPktLength; + struct INIT_WIFI_EVENT *prInitEvent; + struct INIT_EVENT_CMD_RESULT *prEventPendingError; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + uint8_t ucTC, ucCmdSeqNum; + struct HW_MAC_RX_DESC *prRxStatus; + uint8_t ucUnexpectCnt = 0; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + DEBUGFUNC("wlanImageQueryStatus"); + + /* 1. Allocate CMD Info Packet and it Buffer. */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + sizeof(struct INIT_HIF_TX_HEADER)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + u4EventSize = prChipInfo->rxd_size + prChipInfo->init_event_size + + sizeof(struct INIT_EVENT_CMD_RESULT); + aucBuffer = kalMemAlloc(u4EventSize, PHY_MEM_TYPE); + + kalMemZero(prCmdInfo->pucInfoBuffer, + sizeof(struct INIT_HIF_TX_HEADER)); + prCmdInfo->u2InfoBufLen = sizeof(struct INIT_HIF_TX_HEADER); + +#if (CFG_USE_TC4_RESOURCE_FOR_INIT_CMD == 1) + /* 2. Always use TC4 */ + ucTC = TC4_INDEX; +#else + /* 2. Use TC0's resource to send init_cmd + * Only TC0 is allowed because SDIO HW always reports + * CPU's TXQ_CNT at TXQ0_CNT in CR4 architecutre) + */ + ucTC = TC0_INDEX; +#endif + + /* 3. increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* 4. Setup common CMD Info Packet */ + prInitHifTxHeader = (struct INIT_HIF_TX_HEADER *) ( + prCmdInfo->pucInfoBuffer); + + prInitHifTxHeader->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prInitHifTxHeader->u2PQ_ID = INIT_CMD_PQ_ID; + + prInitHifTxHeader->rInitWifiCmd.ucCID = + INIT_CMD_ID_QUERY_PENDING_ERROR; + prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = + INIT_CMD_PACKET_TYPE_ID; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + /* 5. Send command */ + while (1) { + /* 5.1 Acquire TX Resource */ + if (nicTxAcquireResource(prAdapter, ucTC, + nicTxGetPageCount(prAdapter, + prCmdInfo->u2InfoBufLen, TRUE), + TRUE) == WLAN_STATUS_RESOURCES) { + if (nicTxPollingResource(prAdapter, + ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "Fail to get TX resource return within timeout\n"); + break; + } + continue; + + } + /* 5.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo, + prChipInfo->u2TxInitCmdPort) != + 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 */ + while (TRUE) { + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + break; + } else if (nicRxWaitResponse(prAdapter, 0, + aucBuffer, u4EventSize, + &u4RxPktLength) != + WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + break; + } else { + /* header checking .. */ + prRxStatus = (struct HW_MAC_RX_DESC *) aucBuffer; + if (prRxStatus->u2PktTYpe != + RXM_RXD_PKT_TYPE_SW_EVENT) { + DBGLOG(INIT, ERROR, + "%s: skip unexpected Rx pkt type[0x%04x]\n", + __func__, prRxStatus->u2PktTYpe); + + ucUnexpectCnt++; + + if (ucUnexpectCnt > 5) { + DBGLOG(INIT, WARN, + "%s: break since ucUnexpectCnt > %d\n", + __func__, ucUnexpectCnt); + u4Status = WLAN_STATUS_FAILURE; + break; + } + continue; + } + + prInitEvent = (struct INIT_WIFI_EVENT *) + (aucBuffer + prChipInfo->rxd_size); + + /* EID / SeqNum check */ + if (prInitEvent->ucEID != INIT_EVENT_ID_PENDING_ERROR) { + u4Status = WLAN_STATUS_FAILURE; + break; + } else if (prInitEvent->ucSeqNum != ucCmdSeqNum) { + u4Status = WLAN_STATUS_FAILURE; + break; + } + prEventPendingError = + (struct INIT_EVENT_CMD_RESULT *) + prInitEvent->aucBuffer; + /* 0 for download success */ + if (prEventPendingError->ucStatus != 0) { + u4Status = WLAN_STATUS_FAILURE; + break; + } + u4Status = WLAN_STATUS_SUCCESS; + break; + } + } + + /* 7. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanConfigWifiFuncStatus(IN struct ADAPTER + *prAdapter, IN uint8_t ucCmdSeqNum) +{ + struct mt66xx_chip_info *prChipInfo; + uint8_t *aucBuffer; + uint32_t u4EventSize; + struct INIT_WIFI_EVENT *prInitEvent; + struct INIT_EVENT_CMD_RESULT *prEventCmdResult; + uint32_t u4RxPktLength; + uint32_t u4Status; + uint8_t ucPortIdx = IMG_DL_STATUS_PORT_IDX; + struct HW_MAC_RX_DESC *prRxStatus; + uint8_t ucUnexpectCnt = 0; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + u4EventSize = prChipInfo->rxd_size + prChipInfo->init_event_size + + sizeof(struct INIT_EVENT_CMD_RESULT); + aucBuffer = kalMemAlloc(u4EventSize, PHY_MEM_TYPE); + + while (TRUE) { + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + break; + } else if (nicRxWaitResponse(prAdapter, ucPortIdx, + aucBuffer, u4EventSize, + &u4RxPktLength) != + WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + break; + } else { + /* header checking .. */ + prRxStatus = (struct HW_MAC_RX_DESC *) aucBuffer; + if (prRxStatus->u2PktTYpe != + RXM_RXD_PKT_TYPE_SW_EVENT) { + DBGLOG(INIT, ERROR, + "%s: skip unexpected Rx pkt type[0x%04x]\n", + __func__, prRxStatus->u2PktTYpe); + + ucUnexpectCnt++; + + if (ucUnexpectCnt > 5) { + DBGLOG(INIT, WARN, + "%s: break since ucUnexpectCnt > %d\n", + __func__, ucUnexpectCnt); + u4Status = WLAN_STATUS_FAILURE; + break; + } + continue; + } + + prInitEvent = (struct INIT_WIFI_EVENT *) + (aucBuffer + prChipInfo->rxd_size); + + /* EID / SeqNum check */ + if (prInitEvent->ucEID != INIT_EVENT_ID_CMD_RESULT) { + u4Status = WLAN_STATUS_FAILURE; + break; + } else if (prInitEvent->ucSeqNum != ucCmdSeqNum) { + u4Status = WLAN_STATUS_FAILURE; + break; + } + prEventCmdResult = + (struct INIT_EVENT_CMD_RESULT *) + prInitEvent->aucBuffer; + + /* 0 for download success */ + if (prEventCmdResult->ucStatus != 0) { + DBGLOG(INIT, ERROR, + "Start CMD failed, status[%u]\n", + prEventCmdResult->ucStatus); +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + if (prEventCmdResult->ucStatus == + WIFI_FW_DECOMPRESSION_FAILED) + DBGLOG(INIT, ERROR, + "Start Decompression CMD failed, status[%u]\n", + prEventCmdResult->ucStatus); +#endif + u4Status = WLAN_STATUS_FAILURE; + break; + } + u4Status = WLAN_STATUS_SUCCESS; + break; + } + } + + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + + return u4Status; +} + +uint32_t wlanConfigWifiFunc(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnable, IN uint32_t u4StartAddress, + IN uint8_t ucPDA) +{ + struct CMD_INFO *prCmdInfo; + struct INIT_HIF_TX_HEADER *prInitHifTxHeader; + struct INIT_CMD_WIFI_START *prInitCmdWifiStart; + uint8_t ucTC, ucCmdSeqNum; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + DEBUGFUNC("wlanConfigWifiFunc"); + + /* 1. Allocate CMD Info Packet and its Buffer. */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + sizeof(struct INIT_HIF_TX_HEADER) + + sizeof( + struct INIT_CMD_WIFI_START)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + kalMemZero(prCmdInfo->pucInfoBuffer, + sizeof(struct INIT_HIF_TX_HEADER) + sizeof( + struct INIT_CMD_WIFI_START)); + prCmdInfo->u2InfoBufLen = sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_CMD_WIFI_START); + +#if (CFG_USE_TC4_RESOURCE_FOR_INIT_CMD == 1) + /* 2. Always use TC4 (TC4 as CPU) */ + ucTC = TC4_INDEX; +#else + /* 2. Use TC0's resource to send init_cmd. + * Only TC0 is allowed because SDIO HW always reports + * CPU's TXQ_CNT at TXQ0_CNT in CR4 architecutre) + */ + ucTC = TC0_INDEX; +#endif + + /* 3. increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* 4. Setup common CMD Info Packet */ + prInitHifTxHeader = (struct INIT_HIF_TX_HEADER *) ( + prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prInitHifTxHeader->u2PQ_ID = INIT_CMD_PQ_ID; + prInitHifTxHeader->ucPktFt = INIT_PKT_FT_CMD; + + prInitHifTxHeader->rInitWifiCmd.ucCID = + INIT_CMD_ID_WIFI_START; + prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = + INIT_CMD_PACKET_TYPE_ID; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + prInitCmdWifiStart = (struct INIT_CMD_WIFI_START *) ( + prInitHifTxHeader->rInitWifiCmd.aucBuffer); + prInitCmdWifiStart->u4Override = 0; + if (fgEnable) + prInitCmdWifiStart->u4Override |= + START_OVERRIDE_START_ADDRESS; + + /* 5G cal until send efuse buffer mode CMD */ +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1) + if (prAdapter->fgIsSupportDelayCal == TRUE) + prInitCmdWifiStart->u4Override |= START_DELAY_CALIBRATION; +#endif + + if (ucPDA == PDA_CR4) + prInitCmdWifiStart->u4Override |= START_WORKING_PDA_OPTION; + + prInitCmdWifiStart->u4Address = u4StartAddress; + + /* 5. Seend WIFI start command */ + while (1) { + /* 5.1 Acquire TX Resource */ + if (nicTxAcquireResource(prAdapter, ucTC, + nicTxGetPageCount(prAdapter, + prCmdInfo->u2InfoBufLen, TRUE), + TRUE) == 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"); + goto exit; + } + continue; + } + /* 5.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo, + prChipInfo->u2TxInitCmdPort) + != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "Fail to transmit WIFI start command\n"); + goto exit; + } + + break; + }; + + DBGLOG(INIT, INFO, "FW_START CMD send, waiting for RSP\n"); + + u4Status = wlanConfigWifiFuncStatus(prAdapter, ucCmdSeqNum); + + if (u4Status != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "FW_START EVT failed\n"); + else + DBGLOG(INIT, INFO, "FW_START EVT success!!\n"); + +exit: + /* 6. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} +#if CFG_SUPPORT_COMPRESSION_FW_OPTION +uint32_t +wlanCompressedFWConfigWifiFunc(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnable, + IN uint32_t u4StartAddress, IN uint8_t ucPDA, + IN struct INIT_CMD_WIFI_DECOMPRESSION_START *prFwImageInFo) +{ + struct CMD_INFO *prCmdInfo; + struct INIT_HIF_TX_HEADER *prInitHifTxHeader; + struct INIT_CMD_WIFI_DECOMPRESSION_START + *prInitCmdWifiStart; + uint8_t ucTC, ucCmdSeqNum; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + DEBUGFUNC("wlanConfigWifiFunc"); + /* 1. Allocate CMD Info Packet and its Buffer. */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + sizeof(struct INIT_HIF_TX_HEADER) + + sizeof(struct INIT_CMD_WIFI_DECOMPRESSION_START)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + kalMemZero(prCmdInfo->pucInfoBuffer, + sizeof(struct INIT_HIF_TX_HEADER) + sizeof( + struct INIT_CMD_WIFI_DECOMPRESSION_START)); + prCmdInfo->u2InfoBufLen = + sizeof(struct INIT_HIF_TX_HEADER) + sizeof( + struct INIT_CMD_WIFI_DECOMPRESSION_START); + + /* 2. Always use TC0 */ + ucTC = TC0_INDEX; + + /* 3. increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* 4. Setup common CMD Info Packet */ + prInitHifTxHeader = (struct INIT_HIF_TX_HEADER *) ( + prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prInitHifTxHeader->u2PQ_ID = INIT_CMD_PQ_ID; + prInitHifTxHeader->ucPktFt = INIT_PKT_FT_CMD; + prInitHifTxHeader->rInitWifiCmd.ucCID = + INIT_CMD_ID_DECOMPRESSED_WIFI_START; + prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = + INIT_CMD_PACKET_TYPE_ID; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + prInitCmdWifiStart = (struct + INIT_CMD_WIFI_DECOMPRESSION_START *) ( + prInitHifTxHeader->rInitWifiCmd.aucBuffer); + prInitCmdWifiStart->u4Override = 0; + if (fgEnable) + prInitCmdWifiStart->u4Override |= + START_OVERRIDE_START_ADDRESS; + + /* 5G cal until send efuse buffer mode CMD */ +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1) + if (prAdapter->fgIsSupportDelayCal == TRUE) + prInitCmdWifiStart->u4Override |= START_DELAY_CALIBRATION; +#endif + if (ucPDA == PDA_CR4) + prInitCmdWifiStart->u4Override |= START_WORKING_PDA_OPTION; + +#if CFG_COMPRESSION_DEBUG + prInitCmdWifiStart->u4Override |= START_CRC_CHECK; +#endif +#if CFG_DECOMPRESSION_TMP_ADDRESS + prInitCmdWifiStart->u4Override |= + CHANGE_DECOMPRESSION_TMP_ADDRESS; + prInitCmdWifiStart->u4DecompressTmpAddress = 0xE6000; +#endif + prInitCmdWifiStart->u4Address = u4StartAddress; + prInitCmdWifiStart->u4Region1Address = + prFwImageInFo->u4Region1Address; + prInitCmdWifiStart->u4Region1CRC = + prFwImageInFo->u4Region1CRC; + prInitCmdWifiStart->u4BlockSize = + prFwImageInFo->u4BlockSize; + prInitCmdWifiStart->u4Region1length = + prFwImageInFo->u4Region1length; + prInitCmdWifiStart->u4Region2Address = + prFwImageInFo->u4Region2Address; + prInitCmdWifiStart->u4Region2CRC = + prFwImageInFo->u4Region2CRC; + prInitCmdWifiStart->u4Region2length = + prFwImageInFo->u4Region2length; + + while (1) { + /* 5.1 Acquire TX Resource */ + if (nicTxAcquireResource(prAdapter, ucTC, + nicTxGetPageCount(prAdapter, + prCmdInfo->u2InfoBufLen, TRUE), + TRUE) == WLAN_STATUS_RESOURCES) { + if (nicTxPollingResource(prAdapter, + ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "Fail to get TX resource return within timeout\n"); + break; + } + continue; + + } + /* 5.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo, + prChipInfo->u2TxInitCmdPort) + != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "Fail to transmit WIFI start command\n"); + } + + break; + }; + + DBGLOG(INIT, INFO, "FW_START CMD send, waiting for RSP\n"); + + u4Status = wlanConfigWifiFuncStatus(prAdapter, ucCmdSeqNum); + + if (u4Status != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "FW_START EVT failed\n"); + else + DBGLOG(INIT, INFO, "FW_START EVT success!!\n"); + + + /* 6. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} +#endif +#if 0 +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is used to generate CRC32 checksum + * + * @param buf Pointer to the data. + * @param len data length + * + * @return crc32 value + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanCRC32(uint8_t *buf, uint32_t len) +{ + uint32_t i, crc32 = 0xFFFFFFFF; + const uint32_t 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 + +uint32_t wlanGetHarvardTailerInfo(IN struct ADAPTER + *prAdapter, IN void *prFwBuffer, IN uint32_t u4FwSize, + IN uint32_t ucTotSecNum, IN enum ENUM_IMG_DL_IDX_T eDlIdx) +{ + struct TAILER_FORMAT_T *prTailers; + uint8_t *pucStartPtr; + uint32_t u4SecIdx; + uint8_t aucBuf[32]; + + pucStartPtr = prFwBuffer + u4FwSize - sizeof( + struct TAILER_FORMAT_T) * ucTotSecNum; + if (eDlIdx == IMG_DL_IDX_N9_FW) { + kalMemCopy(&prAdapter->rVerInfo.rN9tailer, pucStartPtr, + sizeof(struct TAILER_FORMAT_T) * ucTotSecNum); + prTailers = prAdapter->rVerInfo.rN9tailer; + } else { + kalMemCopy(&prAdapter->rVerInfo.rCR4tailer, pucStartPtr, + sizeof(struct TAILER_FORMAT_T) * ucTotSecNum); + prTailers = prAdapter->rVerInfo.rCR4tailer; + } + + for (u4SecIdx = 0; u4SecIdx < ucTotSecNum; u4SecIdx++) { + /* Dump image information */ + DBGLOG(INIT, INFO, + "%s Section[%d]: chip_info[%u:E%u] feature[0x%02X]\n", + (eDlIdx == IMG_DL_IDX_N9_FW) ? "N9" : "CR4", u4SecIdx, + prTailers[u4SecIdx].chip_info, + prTailers[u4SecIdx].eco_code + 1, + prTailers[u4SecIdx].feature_set); + + kalMemZero(aucBuf, 32); + kalMemCopy(aucBuf, prTailers[u4SecIdx].ram_version, + sizeof(prTailers[u4SecIdx].ram_version)); + DBGLOG(INIT, INFO, "date[%s] version[%s]\n", + prTailers[u4SecIdx].ram_built_date, aucBuf); + } + + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanGetConnacTailerInfo(IN struct ADAPTER + *prAdapter, IN void *prFwBuffer, + IN uint32_t u4FwSize, IN enum ENUM_IMG_DL_IDX_T eDlIdx) +{ + struct WIFI_VER_INFO *prVerInfo = &prAdapter->rVerInfo; + struct TAILER_COMMON_FORMAT_T *prComTailer; + struct TAILER_REGION_FORMAT_T *prRegTailer; + uint8_t *pucImgPtr; + uint8_t *pucTailertPtr; + uint8_t *pucStartPtr; + uint32_t u4SecIdx; + uint8_t aucBuf[32]; + + pucImgPtr = prFwBuffer; + pucStartPtr = prFwBuffer + u4FwSize - + sizeof(struct TAILER_COMMON_FORMAT_T); + prComTailer = (struct TAILER_COMMON_FORMAT_T *) pucStartPtr; + kalMemCopy(&prVerInfo->rCommonTailer, prComTailer, + sizeof(struct TAILER_COMMON_FORMAT_T)); + + /* Dump image information */ + DBGLOG(INIT, INFO, + "%s INFO: chip_info[%u:E%u] region_num[%d]\n", + (eDlIdx == IMG_DL_IDX_N9_FW) ? "N9" : "CR4", + prComTailer->ucChipInfo, + prComTailer->ucEcoCode + 1, prComTailer->ucRegionNum); + + kalMemZero(aucBuf, 32); + kalMemCopy(aucBuf, prComTailer->aucRamVersion, + sizeof(prComTailer->aucRamVersion)); + DBGLOG(INIT, INFO, "date[%s] version[%s]\n", + prComTailer->aucRamBuiltDate, aucBuf); + + if (prComTailer->ucRegionNum > MAX_FWDL_SECTION_NUM) { + DBGLOG(INIT, INFO, + "Regions number[%d] > max section number[%d]\n", + prComTailer->ucRegionNum, MAX_FWDL_SECTION_NUM); + return WLAN_STATUS_FAILURE; + } + + pucStartPtr -= (prComTailer->ucRegionNum * + sizeof(struct TAILER_REGION_FORMAT_T)); + pucTailertPtr = pucStartPtr; + for (u4SecIdx = 0; u4SecIdx < prComTailer->ucRegionNum; u4SecIdx++) { + prRegTailer = (struct TAILER_REGION_FORMAT_T *) pucStartPtr; + kalMemCopy(&prVerInfo->rRegionTailers[u4SecIdx], + prRegTailer, sizeof(struct TAILER_REGION_FORMAT_T)); + + /* Dump image information */ + DBGLOG(INIT, TRACE, + "Region[%d]: addr[0x%08X] feature[0x%02X] size[%u]\n", + u4SecIdx, prRegTailer->u4Addr, + prRegTailer->ucFeatureSet, prRegTailer->u4Len); + DBGLOG(INIT, TRACE, + "uncompress_crc[0x%08X] uncompress_size[0x%08X] block_size[0x%08X]\n", + prRegTailer->u4CRC, prRegTailer->u4RealSize, + prRegTailer->u4BlockSize); + pucImgPtr += prRegTailer->u4Len; + pucStartPtr += sizeof(struct TAILER_REGION_FORMAT_T); + } + + if (prComTailer->ucFormatFlag && pucImgPtr < pucTailertPtr) + fwDlGetReleaseInfoSection(prAdapter, pucImgPtr); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is used to extract the wifi ram code start address + * + * @param prVerInfo Pointer to the P_WIFI_VER_INFO_T structure. + * + * @return addr The ram code entry address. + * 0: use firmware defaut setting + * others: use it as the start address + */ +/*----------------------------------------------------------------------------*/ + +uint32_t wlanDetectRamEntry(IN struct WIFI_VER_INFO + *prVerInfo) +{ + uint32_t addr = 0; + uint32_t u4SecIdx; + struct TAILER_COMMON_FORMAT_T *prComTailer = + &prVerInfo->rCommonTailer; + struct TAILER_REGION_FORMAT_T *prRegTailer; + + for (u4SecIdx = 0; u4SecIdx < prComTailer->ucRegionNum; + u4SecIdx++) { + prRegTailer = &(prVerInfo->rRegionTailers[u4SecIdx]); + + if (prRegTailer->ucFeatureSet & + DOWNLOAD_CONFIG_VALID_RAM_ENTRY) { + addr = prRegTailer->u4Addr; + break; + } + } + + return addr; +} + +uint32_t wlanHarvardFormatDownload(IN struct ADAPTER + *prAdapter, IN enum ENUM_IMG_DL_IDX_T eDlIdx) +{ + uint32_t u4FwSize = 0; + void *prFwBuffer = NULL; + uint32_t rDlStatus = 0; + uint32_t rCfgStatus = 0; + uint32_t ucTotSecNum; + uint8_t ucPDA; +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + u_int8_t fgIsCompressed = FALSE; + struct INIT_CMD_WIFI_DECOMPRESSION_START rFwImageInFo; +#endif + + if (eDlIdx == IMG_DL_IDX_N9_FW) { + ucTotSecNum = N9_FWDL_SECTION_NUM; + ucPDA = PDA_N9; + } else { + ucTotSecNum = CR4_FWDL_SECTION_NUM; + ucPDA = PDA_CR4; + } + + kalFirmwareImageMapping(prAdapter->prGlueInfo, &prFwBuffer, + &u4FwSize, eDlIdx); + if (prFwBuffer == NULL) { + DBGLOG(INIT, WARN, "FW[%u] load error!\n", eDlIdx); + return WLAN_STATUS_FAILURE; + } + + wlanGetHarvardTailerInfo(prAdapter, prFwBuffer, u4FwSize, + ucTotSecNum, eDlIdx); +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + rDlStatus = wlanCompressedImageSectionDownloadStage( + prAdapter, prFwBuffer, u4FwSize, ucTotSecNum, + eDlIdx, &fgIsCompressed, &rFwImageInFo); + if (eDlIdx == IMG_DL_IDX_CR4_FW) + prAdapter->fgIsCr4FwDownloaded = TRUE; + if (fgIsCompressed == TRUE) + rCfgStatus = wlanCompressedFWConfigWifiFunc(prAdapter, + FALSE, 0, ucPDA, &rFwImageInFo); + else + rCfgStatus = wlanConfigWifiFunc(prAdapter, FALSE, 0, ucPDA); +#else + rDlStatus = wlanImageSectionDownloadStage(prAdapter, + prFwBuffer, u4FwSize, ucTotSecNum, eDlIdx); + if (eDlIdx == IMG_DL_IDX_CR4_FW) + prAdapter->fgIsCr4FwDownloaded = TRUE; + rCfgStatus = wlanConfigWifiFunc(prAdapter, FALSE, 0, ucPDA); +#endif + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, NULL, + prFwBuffer); + + if ((rDlStatus != WLAN_STATUS_SUCCESS) + || (rCfgStatus != WLAN_STATUS_SUCCESS)) + return WLAN_STATUS_FAILURE; + + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanConnacFormatDownload(IN struct ADAPTER + *prAdapter, IN enum ENUM_IMG_DL_IDX_T eDlIdx) +{ + void *prFwBuffer = NULL; + uint32_t u4FwSize = 0; + uint32_t ram_entry = 0; + uint32_t rDlStatus = 0; + uint32_t rCfgStatus = 0; + uint8_t ucRegionNum; + uint8_t ucPDA; + + kalFirmwareImageMapping(prAdapter->prGlueInfo, &prFwBuffer, + &u4FwSize, eDlIdx); + if (prFwBuffer == NULL) { + DBGLOG(INIT, WARN, "FW[%u] load error!\n", eDlIdx); + return WLAN_STATUS_FAILURE; + } + + if (wlanGetConnacTailerInfo(prAdapter, prFwBuffer, u4FwSize, + eDlIdx) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, WARN, "Get tailer info error!\n"); + return WLAN_STATUS_FAILURE; + } + + ucRegionNum = prAdapter->rVerInfo.rCommonTailer.ucRegionNum; + ucPDA = (eDlIdx == IMG_DL_IDX_N9_FW) ? PDA_N9 : PDA_CR4; + + rDlStatus = wlanImageSectionDownloadStage(prAdapter, + prFwBuffer, u4FwSize, ucRegionNum, eDlIdx); + + ram_entry = wlanDetectRamEntry(&prAdapter->rVerInfo); + rCfgStatus = wlanConfigWifiFunc(prAdapter, + (ram_entry == 0) ? FALSE : TRUE, + ram_entry, ucPDA); + + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, NULL, + prFwBuffer); + + if ((rDlStatus != WLAN_STATUS_SUCCESS) + || (rCfgStatus != WLAN_STATUS_SUCCESS)) + return WLAN_STATUS_FAILURE; + + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanDownloadFW(IN struct ADAPTER *prAdapter) +{ + uint32_t rStatus = 0; + u_int8_t fgReady; + struct mt66xx_chip_info *prChipInfo; + struct FWDL_OPS_T *prFwDlOps; + + if (!prAdapter) + return WLAN_STATUS_FAILURE; + + prChipInfo = prAdapter->chip_info; + prFwDlOps = prChipInfo->fw_dl_ops; + + DBGLOG(INIT, INFO, + "wlanDownloadFW:: Check ready_bits(=0x%x)\n", + prChipInfo->sw_ready_bits); + HAL_WIFI_FUNC_READY_CHECK(prAdapter, + prChipInfo->sw_ready_bits, &fgReady); + + if (fgReady) { + DBGLOG(INIT, INFO, + "Wi-Fi is already ON!, turn off before FW DL!\n"); + + if (wlanPowerOffWifi(prAdapter) != WLAN_STATUS_SUCCESS) + return WLAN_STATUS_FAILURE; + + nicpmWakeUpWiFi(prAdapter); + HAL_HIF_INIT(prAdapter); + } + + HAL_ENABLE_FWDL(prAdapter, TRUE); + + if (prFwDlOps->downloadPatch) + prFwDlOps->downloadPatch(prAdapter); + + DBGLOG(INIT, INFO, "FW download Start\n"); + + if (prFwDlOps->downloadFirmware) { + rStatus = prFwDlOps->downloadFirmware(prAdapter, + IMG_DL_IDX_N9_FW); + if (prChipInfo->is_support_cr4 + && rStatus == WLAN_STATUS_SUCCESS) + rStatus = prFwDlOps->downloadFirmware(prAdapter, + IMG_DL_IDX_CR4_FW); + } else + DBGLOG(INIT, WARN, "Without downlaod firmware Ops\n"); + + DBGLOG(INIT, INFO, "FW download End\n"); + + HAL_ENABLE_FWDL(prAdapter, FALSE); + + return rStatus; +} + +uint32_t wlanDownloadPatch(IN struct ADAPTER *prAdapter) +{ + uint32_t u4FwSize = 0; + void *prFwBuffer = NULL; +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + uint8_t ucIsCompressed; +#endif + if (!prAdapter) + return WLAN_STATUS_FAILURE; + + + DBGLOG(INIT, INFO, "Patch download start\n"); + + prAdapter->rVerInfo.fgPatchIsDlByDrv = FALSE; + + kalFirmwareImageMapping(prAdapter->prGlueInfo, &prFwBuffer, + &u4FwSize, IMG_DL_IDX_PATCH); + if (prFwBuffer == NULL) { + DBGLOG(INIT, WARN, "FW[%u] load error!\n", + IMG_DL_IDX_PATCH); + return WLAN_STATUS_FAILURE; + } + + if (wlanPatchIsDownloaded(prAdapter)) { + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, NULL, + prFwBuffer); + DBGLOG(INIT, INFO, "No need to download patch\n"); + return WLAN_STATUS_SUCCESS; + } + + /* Patch DL */ + do { +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + wlanCompressedImageSectionDownloadStage(prAdapter, + prFwBuffer, u4FwSize, 1, + IMG_DL_IDX_PATCH, + &ucIsCompressed, NULL); +#else + wlanImageSectionDownloadStage(prAdapter, prFwBuffer, + u4FwSize, 1, IMG_DL_IDX_PATCH); +#endif + wlanPatchSendComplete(prAdapter); + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, NULL, + prFwBuffer); + + prAdapter->rVerInfo.fgPatchIsDlByDrv = TRUE; + } while (0); + + DBGLOG(INIT, INFO, "Patch download end\n"); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanGetPatchInfo(IN struct ADAPTER *prAdapter) +{ + uint32_t u4FwSize = 0; + void *prFwBuffer = NULL; + uint32_t u4StartOffset, u4Addr, u4Len, u4DataMode; + + if (!prAdapter) + return WLAN_STATUS_FAILURE; + + kalFirmwareImageMapping(prAdapter->prGlueInfo, &prFwBuffer, + &u4FwSize, IMG_DL_IDX_PATCH); + if (prFwBuffer == NULL) { + DBGLOG(INIT, WARN, "FW[%u] load error!\n", + IMG_DL_IDX_PATCH); + return WLAN_STATUS_FAILURE; + } + + wlanImageSectionGetPatchInfo(prAdapter, prFwBuffer, + u4FwSize, &u4StartOffset, + &u4Addr, &u4Len, &u4DataMode); + + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, NULL, + prFwBuffer); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t fwDlGetFwdlInfo(struct ADAPTER *prAdapter, + char *pcBuf, int i4TotalLen) +{ + struct WIFI_VER_INFO *prVerInfo = &prAdapter->rVerInfo; + struct FWDL_OPS_T *prFwDlOps; + uint32_t u4Offset = 0; + uint8_t aucBuf[32], aucDate[32]; + + prFwDlOps = prAdapter->chip_info->fw_dl_ops; + + kalMemZero(aucBuf, 32); + kalStrnCpy(aucBuf, prVerInfo->aucFwBranchInfo, 4); + kalMemZero(aucDate, 32); + kalStrnCpy(aucDate, prVerInfo->aucFwDateCode, 16); + + u4Offset += snprintf(pcBuf + u4Offset, + i4TotalLen - u4Offset, + "\nN9 FW version %s-%u.%u.%u[DEC] (%s)\n", + aucBuf, + (uint32_t)(prVerInfo->u2FwOwnVersion >> 8), + (uint32_t)(prVerInfo->u2FwOwnVersion & BITS(0, 7)), + prVerInfo->ucFwBuildNumber, aucDate); + + if (prFwDlOps->getFwDlInfo) + u4Offset += prFwDlOps->getFwDlInfo(prAdapter, + pcBuf + u4Offset, + i4TotalLen - u4Offset); + + if (!prVerInfo->fgPatchIsDlByDrv) { + u4Offset += snprintf(pcBuf + u4Offset, + i4TotalLen - u4Offset, + "MCU patch is not downloaded by wlan driver, read patch info\n"); + wlanGetPatchInfo(prAdapter); + } + + kalMemZero(aucBuf, 32); + kalMemZero(aucDate, 32); + kalStrnCpy(aucBuf, prVerInfo->rPatchHeader.aucPlatform, 12); + kalStrnCpy(aucDate, prVerInfo->rPatchHeader.aucBuildDate, + 16); + u4Offset += snprintf(pcBuf + u4Offset, + i4TotalLen - u4Offset, + "Patch platform %s. Date %s\n", + aucBuf, aucDate); + + u4Offset += snprintf(pcBuf + u4Offset, i4TotalLen - u4Offset, + "Drv version %u.%u[DEC]\n", + (uint32_t)(prVerInfo->u2FwPeerVersion >> 8), + (uint32_t)(prVerInfo->u2FwPeerVersion & BITS(0, 7))); + return u4Offset; +} + +void fwDlGetReleaseInfoSection(struct ADAPTER *prAdapter, uint8_t *pucStartPtr) +{ + struct HEADER_RELEASE_INFO *prFirstInfo; + struct HEADER_RELEASE_INFO *prRelInfo; + uint8_t *pucCurPtr = pucStartPtr + RELEASE_INFO_SEPARATOR_LEN; + uint16_t u2Len = 0, u2Offset = 0; + + prFirstInfo = (struct HEADER_RELEASE_INFO *)pucCurPtr; + DBGLOG(INIT, INFO, "Release info tag[%u] len[%u]\n", + prFirstInfo->ucTag, prFirstInfo->u2Len); + + pucCurPtr += sizeof(struct HEADER_RELEASE_INFO); + while (u2Offset < prFirstInfo->u2Len) { + prRelInfo = (struct HEADER_RELEASE_INFO *)pucCurPtr; + DBGLOG(INIT, INFO, "Release info tag[%u] len[%u] padding[%u]\n", + prRelInfo->ucTag, prRelInfo->u2Len, + prRelInfo->ucPaddingLen); + + pucCurPtr += sizeof(struct HEADER_RELEASE_INFO); + switch (prRelInfo->ucTag) { + case 0x01: + fwDlGetReleaseManifest(prAdapter, prRelInfo, pucCurPtr); + break; + default: + DBGLOG(INIT, WARN, "Not support release info tag[%u]\n", + prRelInfo->ucTag); + } + + u2Len = prRelInfo->u2Len + prRelInfo->ucPaddingLen; + pucCurPtr += u2Len; + u2Offset += u2Len + sizeof(struct HEADER_RELEASE_INFO); + } +} + +void fwDlGetReleaseManifest(struct ADAPTER *prAdapter, + struct HEADER_RELEASE_INFO *prRelInfo, + uint8_t *pucStartPtr) +{ + kalMemZero(&prAdapter->rVerInfo.aucReleaseManifest, + sizeof(prAdapter->rVerInfo.aucReleaseManifest)); + kalMemCopy(&prAdapter->rVerInfo.aucReleaseManifest, + pucStartPtr, prRelInfo->u2Len); + DBGLOG(INIT, INFO, "Release manifest: %s\n", + prAdapter->rVerInfo.aucReleaseManifest); +} + +#endif /* CFG_ENABLE_FW_DOWNLOAD */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/connac/connac.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/connac/connac.c new file mode 100644 index 0000000000000..a5273457da6c0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/connac/connac.c @@ -0,0 +1,315 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file connac.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. + */ + +#ifdef CONNAC + +/******************************************************************************* + * C O M P I L E 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 "connac.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +uint8_t *apucConnacFwName[] = { + (uint8_t *) CFG_FW_FILENAME "_soc1_0", + NULL +}; + +struct ECO_INFO connac_eco_table[] = { + /* HW version, ROM version, Factory version */ + {0x00, 0x00, 0xA, 0x1}, /* E1 */ + {0x00, 0x00, 0x0, 0x0} /* End of table */ +}; + +#if defined(_HIF_PCIE) || defined(_HIF_AXI) +struct PCIE_CHIP_CR_MAPPING connac_bus2chip_cr_mapping[] = { + /* chip addr, bus addr, range */ + {0x80000000, 0x00002000, 0x00001000}, /* MCU_CFG */ + + {0x50000000, 0x00004000, 0x00004000}, /* CONN_HIF (PDMA) */ + {0x50002000, 0x00005000, 0x00001000}, /* CONN_HIF (Reserved) */ + {0x5000A000, 0x00006000, 0x00001000}, /* CONN_HIF (DMASHDL) */ + {0x000E0000, 0x00007000, 0x00001000}, /* CONN_HIF_ON (HOST_CSR) */ + + {0x82060000, 0x00008000, 0x00004000}, /* WF_UMAC_TOP (PLE) */ + {0x82068000, 0x0000C000, 0x00002000}, /* WF_UMAC_TOP (PSE) */ + {0x8206C000, 0x0000E000, 0x00002000}, /* WF_UMAC_TOP (PP) */ + {0x82070000, 0x00010000, 0x00010000}, /* WF_PHY */ + {0x820F0000, 0x00020000, 0x00010000}, /* WF_LMAC_TOP */ + {0x820E0000, 0x00030000, 0x00010000}, /* WF_LMAC_TOP (WF_WTBL) */ + + {0x81000000, 0x00050000, 0x00010000}, /* BTSYS_OFF */ + {0x80070000, 0x00060000, 0x00010000}, /* GPSSYS */ + {0x40000000, 0x00070000, 0x00010000}, /* WF_SYSRAM */ + {0x00300000, 0x00080000, 0x00010000}, /* MCU_SYSRAM */ + + {0x80010000, 0x000A1000, 0x00001000}, /* CONN_MCU_DMA */ + {0x80030000, 0x000A2000, 0x00001000}, /* CONN_MCU_BTIF0 */ + {0x81030000, 0x000A3000, 0x00001000}, /* CONN_MCU_CFG_ON */ + {0x80050000, 0x000A4000, 0x00001000}, /* CONN_UART_PTA */ + {0x81040000, 0x000A5000, 0x00001000}, /* CONN_MCU_CIRQ */ + {0x81050000, 0x000A6000, 0x00001000}, /* CONN_MCU_GPT */ + {0x81060000, 0x000A7000, 0x00001000}, /* CONN_PTA */ + {0x81080000, 0x000A8000, 0x00001000}, /* CONN_MCU_WDT */ + {0x81090000, 0x000A9000, 0x00001000}, /* CONN_MCU_PDA */ + {0x810A0000, 0x000AA000, 0x00001000}, /* CONN_RDD_AHB_WRAP0 */ + {0x810B0000, 0x000AB000, 0x00001000}, /* BTSYS_ON */ + {0x810C0000, 0x000AC000, 0x00001000}, /* CONN_RBIST_TOP */ + {0x810D0000, 0x000AD000, 0x00001000}, /* CONN_RDD_AHB_WRAP0 */ + {0x820D0000, 0x000AE000, 0x00001000}, /* WFSYS_ON */ + {0x60000000, 0x000AF000, 0x00001000}, /* CONN_MCU_PDA */ + + {0x80020000, 0x000B0000, 0x00010000}, /* CONN_TOP_MISC_OFF */ + {0x81020000, 0x000C0000, 0x00010000}, /* CONN_TOP_MISC_ON */ + + {0x0, 0x0, 0x0} +}; +#endif /* _HIF_PCIE || _HIF_AXI */ + +int connacGetIpSetVersion(struct GLUE_INFO *prGlueInfo) +{ + return 1; +} + +void connacConstructFirmwarePrio(struct GLUE_INFO *prGlueInfo, + uint8_t **apucNameTable, uint8_t **apucName, + uint8_t *pucNameIdx, uint8_t ucMaxNameIdx) +{ + uint8_t ucIdx = 0; + + for (ucIdx = 0; apucConnacFwName[ucIdx]; ucIdx++) { + if ((*pucNameIdx + 3) < ucMaxNameIdx) { + /* Type 1. WIFI_RAM_CODE_soc1_0_1_1 */ + snprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s_%u_%u", + apucConnacFwName[ucIdx], + connacGetIpSetVersion(prGlueInfo), + wlanGetEcoVersion( + prGlueInfo->prAdapter)); + (*pucNameIdx) += 1; + + /* Type 2. WIFI_RAM_CODE_soc1_0_1_1.bin */ + snprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s_%u_%u.bin", + apucConnacFwName[ucIdx], + connacGetIpSetVersion(prGlueInfo), + wlanGetEcoVersion( + prGlueInfo->prAdapter)); + (*pucNameIdx) += 1; + + /* Type 3. WIFI_RAM_CODE_soc1_0 */ + snprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s", + apucConnacFwName[ucIdx]); + (*pucNameIdx) += 1; + + /* Type 4. WIFI_RAM_CODE_soc1_0.bin */ + snprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s.bin", + apucConnacFwName[ucIdx]); + (*pucNameIdx) += 1; + } else { + /* the table is not large enough */ + DBGLOG(INIT, ERROR, + "kalFirmwareImageMapping >> file name array is not enough.\n"); + ASSERT(0); + } + } +} + +void connacConstructPatchName(struct GLUE_INFO *prGlueInfo, + uint8_t **apucName, uint8_t *pucNameIdx) +{ + snprintf(apucName[(*pucNameIdx)], + CFG_FW_NAME_MAX_LEN, "mtsoc1_0_patch_e%x_hdr.bin", + wlanGetEcoVersion(prGlueInfo->prAdapter)); +} + +struct BUS_INFO connac_bus_info = { +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + .top_cfg_base = CONNAC_TOP_CFG_BASE, + .bus2chip = connac_bus2chip_cr_mapping, + .tx_ring_fwdl_idx = 3, + .tx_ring_cmd_idx = 15, + .tx_ring_data_idx = 0, + .fgCheckDriverOwnInt = FALSE, + .fgInitPCIeInt = FALSE, + .u4DmaMask = 36, + + .pdmaSetup = asicPdmaConfig, + .enableInterrupt = asicEnableInterrupt, + .disableInterrupt = asicDisableInterrupt, + .lowPowerOwnRead = asicLowPowerOwnRead, + .lowPowerOwnSet = asicLowPowerOwnSet, + .lowPowerOwnClear = asicLowPowerOwnClear, + .wakeUpWiFi = asicWakeUpWiFi, + .isValidRegAccess = asicIsValidRegAccess, + .getMailboxStatus = asicGetMailboxStatus, + .setDummyReg = asicSetDummyReg, + .checkDummyReg = asicCheckDummyReg, +#endif /* _HIF_PCIE || _HIF_AXI */ +#if defined(_HIF_USB) + .u4UdmaWlCfg_0_Addr = CONNAC_UDMA_WLCFG_0, + .u4UdmaWlCfg_1_Addr = CONNAC_UDMA_WLCFG_1, + .u4UdmaWlCfg_0 = + (UDMA_WLCFG_0_TX_EN(1) | + UDMA_WLCFG_0_RX_EN(1) | + UDMA_WLCFG_0_RX_MPSZ_PAD0(1) | + UDMA_WLCFG_0_1US_TIMER_EN(1)), +#endif /* _HIF_USB */ +}; + +struct FWDL_OPS_T connac_fw_dl_ops = { + .constructFirmwarePrio = connacConstructFirmwarePrio, + .constructPatchName = connacConstructPatchName, +#if !CFG_MTK_ANDROID_WMT + .downloadPatch = wlanDownloadPatch, +#endif + .downloadFirmware = wlanConnacFormatDownload, + .getFwInfo = wlanGetConnacFwInfo, + .getFwDlInfo = asicGetFwDlInfo, +}; + +struct TX_DESC_OPS_T connacTxDescOps = { + .fillNicAppend = fillNicTxDescAppend, + .fillHifAppend = fillTxDescAppendByHostV2, + .fillTxByteCount = fillTxDescTxByteCount, +}; + +#if CFG_SUPPORT_QA_TOOL +struct ATE_OPS_T connacAteOps = { + .setICapStart = connacSetICapStart, + .getICapStatus = connacGetICapStatus, + .getICapIQData = connacGetICapIQData, + .getRbistDataDumpEvent = nicExtEventICapIQData, +}; +#endif + +struct CHIP_DBG_OPS connac_debug_ops = { +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + .showPdmaInfo = halShowPdmaInfo, + .showPseInfo = halShowPseInfo, + .showPleInfo = halShowPleInfo, + .showCsrInfo = halShowHostCsrInfo, + .showDmaschInfo = halShowDmaschInfo, +#else + .showPdmaInfo = NULL, + .showPseInfo = NULL, + .showPleInfo = NULL, + .showCsrInfo = NULL, + .showDmaschInfo = NULL, +#endif +}; + +struct mt66xx_chip_info mt66xx_chip_info_connac = { + .bus_info = &connac_bus_info, + .fw_dl_ops = &connac_fw_dl_ops, + .prTxDescOps = &connacTxDescOps, +#if CFG_SUPPORT_QA_TOOL + .prAteOps = &connacAteOps, +#endif + .prDebugOps = &connac_debug_ops, + + .chip_id = CONNAC_CHIP_ID, + .should_verify_chip_id = FALSE, + .sw_sync0 = CONNAC_SW_SYNC0, + .sw_ready_bits = WIFI_FUNC_NO_CR4_READY_BITS, + .sw_ready_bit_offset = CONNAC_SW_SYNC0_RDY_OFFSET, + .patch_addr = CONNAC_PATCH_START_ADDR, + .is_support_cr4 = FALSE, + .txd_append_size = CONNAC_TX_DESC_APPEND_LENGTH, + .rxd_size = CONNAC_RX_DESC_LENGTH, + .init_event_size = CONNAC_RX_INIT_EVENT_LENGTH, + .event_hdr_size = CONNAC_RX_EVENT_HDR_LENGTH, + .eco_info = connac_eco_table, + .isNicCapV1 = FALSE, + .is_support_efuse = FALSE, + + /* IP info, should be overwrite by getNicCapabalityV2 */ + .u4ChipIpVersion = CONNAC_CHIP_IP_VERSION, + .u4ChipIpConfig = CONNAC_CHIP_IP_CONFIG, + .asicCapInit = asicCapInit, + .asicEnableFWDownload = asicEnableFWDownload, + .asicGetChipID = asicGetChipID, + .downloadBufferBin = NULL, +#if CFG_MTK_ANDROID_WMT + .showTaskStack = connectivity_export_show_stack, +#else + .showTaskStack = NULL, +#endif + .is_support_hw_amsdu = FALSE, + .ucMaxSwAmsduNum = 4, + .workAround = 0, +}; + +struct mt66xx_hif_driver_data mt66xx_driver_data_connac = { + .chip_info = &mt66xx_chip_info_connac, +}; + +#endif /* CONNAC */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/connac2x2/connac2x2.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/connac2x2/connac2x2.c new file mode 100644 index 0000000000000..f0e99dfb56b63 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/connac2x2/connac2x2.c @@ -0,0 +1,315 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file connac.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. + */ + +#ifdef CONNAC2X2 + +/******************************************************************************* + * C O M P I L E 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 "connac2x2.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +uint8_t *apucConnac2x2FwName[] = { + (uint8_t *) CFG_FW_FILENAME "_soc2_0", + NULL +}; + +struct ECO_INFO connac2x2_eco_table[] = { + /* HW version, ROM version, Factory version */ + {0x00, 0x00, 0xA, 0x1}, /* E1 */ + {0x00, 0x00, 0x0, 0x0} /* End of table */ +}; + +#if defined(_HIF_PCIE) || defined(_HIF_AXI) +struct PCIE_CHIP_CR_MAPPING connac2x2_bus2chip_cr_mapping[] = { + /* chip addr, bus addr, range */ + {0x80000000, 0x00002000, 0x00001000}, /* MCU_CFG */ + + {0x50000000, 0x00004000, 0x00004000}, /* CONN_HIF (PDMA) */ + {0x50002000, 0x00005000, 0x00001000}, /* CONN_HIF (Reserved) */ + {0x5000A000, 0x00006000, 0x00001000}, /* CONN_HIF (DMASHDL) */ + {0x000E0000, 0x00007000, 0x00001000}, /* CONN_HIF_ON (HOST_CSR) */ + + {0x82060000, 0x00008000, 0x00004000}, /* WF_UMAC_TOP (PLE) */ + {0x82068000, 0x0000C000, 0x00002000}, /* WF_UMAC_TOP (PSE) */ + {0x8206C000, 0x0000E000, 0x00002000}, /* WF_UMAC_TOP (PP) */ + {0x82070000, 0x00010000, 0x00010000}, /* WF_PHY */ + {0x820F0000, 0x00020000, 0x00010000}, /* WF_LMAC_TOP */ + {0x820E0000, 0x00030000, 0x00010000}, /* WF_LMAC_TOP (WF_WTBL) */ + + {0x81000000, 0x00050000, 0x00010000}, /* BTSYS_OFF */ + {0x80070000, 0x00060000, 0x00010000}, /* GPSSYS */ + {0x40000000, 0x00070000, 0x00010000}, /* WF_SYSRAM */ + {0x00300000, 0x00080000, 0x00010000}, /* MCU_SYSRAM */ + + {0x80010000, 0x000A1000, 0x00001000}, /* CONN_MCU_DMA */ + {0x80030000, 0x000A2000, 0x00001000}, /* CONN_MCU_BTIF0 */ + {0x81030000, 0x000A3000, 0x00001000}, /* CONN_MCU_CFG_ON */ + {0x80050000, 0x000A4000, 0x00001000}, /* CONN_UART_PTA */ + {0x81040000, 0x000A5000, 0x00001000}, /* CONN_MCU_CIRQ */ + {0x81050000, 0x000A6000, 0x00001000}, /* CONN_MCU_GPT */ + {0x81060000, 0x000A7000, 0x00001000}, /* CONN_PTA */ + {0x81080000, 0x000A8000, 0x00001000}, /* CONN_MCU_WDT */ + {0x81090000, 0x000A9000, 0x00001000}, /* CONN_MCU_PDA */ + {0x810A0000, 0x000AA000, 0x00001000}, /* CONN_RDD_AHB_WRAP0 */ + {0x810B0000, 0x000AB000, 0x00001000}, /* BTSYS_ON */ + {0x810C0000, 0x000AC000, 0x00001000}, /* CONN_RBIST_TOP */ + {0x810D0000, 0x000AD000, 0x00001000}, /* CONN_RDD_AHB_WRAP0 */ + {0x820D0000, 0x000AE000, 0x00001000}, /* WFSYS_ON */ + {0x60000000, 0x000AF000, 0x00001000}, /* CONN_MCU_PDA */ + + {0x80020000, 0x000B0000, 0x00010000}, /* CONN_TOP_MISC_OFF */ + {0x81020000, 0x000C0000, 0x00010000}, /* CONN_TOP_MISC_ON */ + + {0x0, 0x0, 0x0} +}; +#endif /* _HIF_PCIE || _HIF_AXI */ + +int connac2x2GetIpSetVersion(struct GLUE_INFO *prGlueInfo) +{ + return 1; +} + +void connac2x2ConstructFirmwarePrio(struct GLUE_INFO *prGlueInfo, + uint8_t **apucNameTable, uint8_t **apucName, + uint8_t *pucNameIdx, uint8_t ucMaxNameIdx) +{ + uint8_t ucIdx = 0; + + for (ucIdx = 0; apucConnac2x2FwName[ucIdx]; ucIdx++) { + if ((*pucNameIdx + 3) < ucMaxNameIdx) { + /* Type 1. WIFI_RAM_CODE_soc1_0_1_1 */ + snprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s_%u_%u", + apucConnac2x2FwName[ucIdx], + connac2x2GetIpSetVersion(prGlueInfo), + wlanGetEcoVersion( + prGlueInfo->prAdapter)); + (*pucNameIdx) += 1; + + /* Type 2. WIFI_RAM_CODE_soc1_0_1_1.bin */ + snprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s_%u_%u.bin", + apucConnac2x2FwName[ucIdx], + connac2x2GetIpSetVersion(prGlueInfo), + wlanGetEcoVersion( + prGlueInfo->prAdapter)); + (*pucNameIdx) += 1; + + /* Type 3. WIFI_RAM_CODE_soc1_0 */ + snprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s", + apucConnac2x2FwName[ucIdx]); + (*pucNameIdx) += 1; + + /* Type 4. WIFI_RAM_CODE_soc1_0.bin */ + snprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s.bin", + apucConnac2x2FwName[ucIdx]); + (*pucNameIdx) += 1; + } else { + /* the table is not large enough */ + DBGLOG(INIT, ERROR, + "kalFirmwareImageMapping >> file name array is not enough.\n"); + ASSERT(0); + } + } +} + +void connac2x2ConstructPatchName(struct GLUE_INFO *prGlueInfo, + uint8_t **apucName, uint8_t *pucNameIdx) +{ + snprintf(apucName[(*pucNameIdx)], + CFG_FW_NAME_MAX_LEN, "mtsoc1_0_patch_e%x_hdr.bin", + wlanGetEcoVersion(prGlueInfo->prAdapter)); +} + +struct BUS_INFO connac2x2_bus_info = { +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + .top_cfg_base = CONNAC2X2_TOP_CFG_BASE, + .bus2chip = connac2x2_bus2chip_cr_mapping, + .tx_ring_fwdl_idx = 3, + .tx_ring_cmd_idx = 15, + .tx_ring_data_idx = 0, + .fgCheckDriverOwnInt = FALSE, + .fgInitPCIeInt = FALSE, + .u4DmaMask = 36, + + .pdmaSetup = asicPdmaConfig, + .enableInterrupt = asicEnableInterrupt, + .disableInterrupt = asicDisableInterrupt, + .lowPowerOwnRead = asicLowPowerOwnRead, + .lowPowerOwnSet = asicLowPowerOwnSet, + .lowPowerOwnClear = asicLowPowerOwnClear, + .wakeUpWiFi = asicWakeUpWiFi, + .isValidRegAccess = asicIsValidRegAccess, + .getMailboxStatus = asicGetMailboxStatus, + .setDummyReg = asicSetDummyReg, + .checkDummyReg = asicCheckDummyReg, +#endif /* _HIF_PCIE || _HIF_AXI */ +#if defined(_HIF_USB) + .u4UdmaWlCfg_0_Addr = CONNAC_UDMA_WLCFG_0, + .u4UdmaWlCfg_1_Addr = CONNAC_UDMA_WLCFG_1, + .u4UdmaWlCfg_0 = + (UDMA_WLCFG_0_TX_EN(1) | + UDMA_WLCFG_0_RX_EN(1) | + UDMA_WLCFG_0_RX_MPSZ_PAD0(1) | + UDMA_WLCFG_0_1US_TIMER_EN(1)), +#endif /* _HIF_USB */ +}; + +struct FWDL_OPS_T connac2x2_fw_dl_ops = { + .constructFirmwarePrio = connac2x2ConstructFirmwarePrio, + .constructPatchName = connac2x2ConstructPatchName, +#if !CFG_MTK_ANDROID_WMT + .downloadPatch = wlanDownloadPatch, +#endif + .downloadFirmware = wlanConnacFormatDownload, + .getFwInfo = wlanGetConnacFwInfo, + .getFwDlInfo = asicGetFwDlInfo, +}; + +struct TX_DESC_OPS_T connac2x2TxDescOps = { + .fillNicAppend = fillNicTxDescAppend, + .fillHifAppend = fillTxDescAppendByHostV2, + .fillTxByteCount = fillTxDescTxByteCount, +}; + +#if CFG_SUPPORT_QA_TOOL +struct ATE_OPS_T connac2x2AteOps = { + .setICapStart = connacSetICapStart, + .getICapStatus = connacGetICapStatus, + .getICapIQData = connacGetICapIQData, + .getRbistDataDumpEvent = nicExtEventICapIQData, +}; +#endif + +struct CHIP_DBG_OPS connac2x2_debug_ops = { +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + .showPdmaInfo = halShowPdmaInfo, + .showPseInfo = halShowPseInfo, + .showPleInfo = halShowPleInfo, + .showCsrInfo = halShowHostCsrInfo, + .showDmaschInfo = halShowDmaschInfo, +#else + .showPdmaInfo = NULL, + .showPseInfo = NULL, + .showPleInfo = NULL, + .showCsrInfo = NULL, + .showDmaschInfo = NULL, +#endif +}; + +struct mt66xx_chip_info mt66xx_chip_info_connac2x2 = { + .bus_info = &connac2x2_bus_info, + .fw_dl_ops = &connac2x2_fw_dl_ops, + .prTxDescOps = &connac2x2TxDescOps, +#if CFG_SUPPORT_QA_TOOL + .prAteOps = &connac2x2AteOps, +#endif + .prDebugOps = &connac2x2_debug_ops, + + .chip_id = CONNAC2X2_CHIP_ID, + .should_verify_chip_id = FALSE, + .sw_sync0 = CONNAC2X2_SW_SYNC0, + .sw_ready_bits = WIFI_FUNC_NO_CR4_READY_BITS, + .sw_ready_bit_offset = CONNAC2X2_SW_SYNC0_RDY_OFFSET, + .patch_addr = CONNAC2X2_PATCH_START_ADDR, + .is_support_cr4 = FALSE, + .txd_append_size = CONNAC2X2_TX_DESC_APPEND_LENGTH, + .rxd_size = CONNAC2X2_RX_DESC_LENGTH, + .init_event_size = CONNAC2X2_RX_INIT_EVENT_LENGTH, + .event_hdr_size = CONNAC2X2_RX_EVENT_HDR_LENGTH, + .eco_info = connac2x2_eco_table, + .isNicCapV1 = FALSE, + .is_support_efuse = FALSE, + + /* IP info, should be overwrite by getNicCapabalityV2 */ + .u4ChipIpVersion = CONNAC_CHIP_IP_VERSION, + .u4ChipIpConfig = CONNAC_CHIP_IP_CONFIG, + .asicCapInit = asicCapInit, + .asicEnableFWDownload = asicEnableFWDownload, + .asicGetChipID = asicGetChipID, + .downloadBufferBin = NULL, +#if CFG_MTK_ANDROID_WMT + .showTaskStack = connectivity_export_show_stack, +#else + .showTaskStack = NULL, +#endif + .is_support_hw_amsdu = TRUE, + .ucMaxSwAmsduNum = 0, + .workAround = 0, +}; + +struct mt66xx_hif_driver_data mt66xx_driver_data_connac2x2 = { + .chip_info = &mt66xx_chip_info_connac2x2, +}; + +#endif /* CONNAC2X2 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/mt6632/mt6632.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/mt6632/mt6632.c new file mode 100644 index 0000000000000..e060a7c6a120f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/mt6632/mt6632.c @@ -0,0 +1,437 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file mt6632.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. + */ + +/******************************************************************************* + * C O M P I L E 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 "mt6632.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +struct ECO_INFO mt6632_eco_table[] = { + /* HW version, ROM version, Factory version, Eco version */ + {0x00, 0x00, 0xA, 0x1}, /* E1 */ + {0x00, 0x00, 0xA, 0x2}, /* E2 */ + {0x10, 0x10, 0xA, 0x3}, /* E3 */ + + {0x00, 0x00, 0x0, 0x0} /* End of table */ +}; + +#if defined(_HIF_PCIE) +struct PCIE_CHIP_CR_MAPPING mt6632_bus2chip_cr_mapping[] = { + /* chip addr, bus addr, range */ + {0x82060000, 0x00008000, 0x00000450}, /* WF_PLE */ + {0x82068000, 0x0000c000, 0x00000450}, /* WF_PSE */ + {0x8206c000, 0x0000e000, 0x00000300}, /* PP */ + {0x820d0000, 0x00020000, 0x00000200}, /* WF_AON */ + {0x820f0000, 0x00020200, 0x00000400}, /* WF_CFG */ + {0x820f0800, 0x00020600, 0x00000200}, /* WF_CFGOFF */ + {0x820f1000, 0x00020800, 0x00000200}, /* WF_TRB */ + {0x820f2000, 0x00020a00, 0x00000200}, /* WF_AGG */ + {0x820f3000, 0x00020c00, 0x00000400}, /* WF_ARB */ + {0x820f4000, 0x00021000, 0x00000200}, /* WF_TMAC */ + {0x820f5000, 0x00021200, 0x00000400}, /* WF_RMAC */ + {0x820f6000, 0x00021600, 0x00000200}, /* WF_SEC */ + {0x820f7000, 0x00021800, 0x00000200}, /* WF_DMA */ + + {0x820f8000, 0x00022000, 0x00001000}, /* WF_PF */ + {0x820f9000, 0x00023000, 0x00000400}, /* WF_WTBLON */ + {0x820f9800, 0x00023400, 0x00000200}, /* WF_WTBLOFF */ + + {0x820fa000, 0x00024000, 0x00000200}, /* WF_ETBF */ + {0x820fb000, 0x00024200, 0x00000400}, /* WF_LPON */ + {0x820fc000, 0x00024600, 0x00000200}, /* WF_INT */ + {0x820fd000, 0x00024800, 0x00000400}, /* WF_MIB */ + + {0x820fe000, 0x00025000, 0x00002000}, /* WF_MU */ + + {0x820e0000, 0x00030000, 0x00010000}, /* WF_WTBL */ + + {0x80020000, 0x00000000, 0x00002000}, /* TOP_CFG */ + {0x80000000, 0x00002000, 0x00002000}, /* MCU_CFG */ + {0x50000000, 0x00004000, 0x00004000}, /* PDMA_CFG */ + {0xA0000000, 0x00008000, 0x00008000}, /* PSE_CFG */ + {0x82070000, 0x00010000, 0x00010000}, /* WF_PHY */ + + {0x0, 0x0, 0x0} +}; +#endif /* _HIF_PCIE */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +void mt6632CapInit(IN struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + prChipInfo = prAdapter->chip_info; + + prChipInfo->u2HifTxdSize = 0; + prChipInfo->u2TxInitCmdPort = 0; + prChipInfo->u2TxFwDlPort = 0; + prChipInfo->fillHifTxDesc = NULL; + prChipInfo->ucPacketFormat = TXD_PKT_FORMAT_TXD; + prChipInfo->u4ExtraTxByteCount = 0; + + switch (prGlueInfo->u4InfType) { +#if defined(_HIF_PCIE) + case MT_DEV_INF_PCIE: + prChipInfo->u2TxInitCmdPort = TX_RING_FWDL_IDX_3; + prChipInfo->u2TxFwDlPort = TX_RING_FWDL_IDX_3; + break; +#endif /* _HIF_PCIE */ +#if defined(_HIF_USB) + case MT_DEV_INF_USB: + prChipInfo->u2TxInitCmdPort = USB_DATA_BULK_OUT_EP8; + prChipInfo->u2TxFwDlPort = USB_DATA_BULK_OUT_EP8; + break; +#endif /* _HIF_USB */ + default: + break; + } +} + +uint32_t mt6632GetFwDlInfo(struct ADAPTER *prAdapter, + char *pcBuf, int i4TotalLen) +{ + struct WIFI_VER_INFO *prVerInfo = &prAdapter->rVerInfo; +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + struct TAILER_FORMAT_T_2 *prTailer; +#else + struct TAILER_FORMAT_T *prTailer; +#endif + uint32_t u4Offset = 0; + uint8_t aucBuf[32]; + +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + prTailer = &prVerInfo->rN9Compressedtailer; +#else + prTailer = &prVerInfo->rN9tailer[0]; +#endif + kalMemZero(aucBuf, 32); + kalMemCopy(aucBuf, prTailer->ram_version, 10); + u4Offset += snprintf(pcBuf + u4Offset, i4TotalLen - u4Offset, + "N9 tailer version %s (%s) info %u:E%u\n", + aucBuf, prTailer->ram_built_date, prTailer->chip_info, + prTailer->eco_code + 1); + +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + prTailer = &prVerInfo->rCR4Compressedtailer; +#else + prTailer = &prVerInfo->rCR4tailer[0]; +#endif + kalMemZero(aucBuf, 32); + kalMemCopy(aucBuf, prTailer->ram_version, 10); + u4Offset += snprintf(pcBuf + u4Offset, i4TotalLen - u4Offset, + "CR4 tailer version %s (%s) info %u:E%u\n", + aucBuf, prTailer->ram_built_date, prTailer->chip_info, + prTailer->eco_code + 1); + + return u4Offset; +} + +#if defined(_HIF_PCIE) + +void mt6632PdmaConfig(struct GLUE_INFO *prGlueInfo, u_int8_t enable) +{ + struct BUS_INFO *prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + union WPDMA_GLO_CFG_STRUCT GloCfg; + union WPDMA_INT_MASK IntMask; + + kalDevRegRead(prGlueInfo, WPDMA_GLO_CFG, &GloCfg.word); + + kalDevRegRead(prGlueInfo, WPDMA_INT_MSK, &IntMask.word); + + if (enable == TRUE) { + GloCfg.field.EnableTxDMA = 1; + GloCfg.field.EnableRxDMA = 1; + GloCfg.field.EnTXWriteBackDDONE = 1; + GloCfg.field.WPDMABurstSIZE = 3; + GloCfg.field.omit_tx_info = 1; + GloCfg.field.fifo_little_endian = 1; + GloCfg.field.multi_dma_en = 3; + GloCfg.field.clk_gate_dis = 1; + + IntMask.field.rx_done_0 = 1; + IntMask.field.rx_done_1 = 1; + IntMask.field.tx_done = BIT(prBusInfo->tx_ring_fwdl_idx) | + BIT(prBusInfo->tx_ring_cmd_idx) | + BIT(prBusInfo->tx_ring_data_idx); + } else { + GloCfg.field.EnableRxDMA = 0; + GloCfg.field.EnableTxDMA = 0; + GloCfg.field.multi_dma_en = 2; + + IntMask.field.rx_done_0 = 0; + IntMask.field.rx_done_1 = 0; + IntMask.field.tx_done = 0; + } + + kalDevRegWrite(prGlueInfo, WPDMA_INT_MSK, IntMask.word); + + kalDevRegWrite(prGlueInfo, WPDMA_GLO_CFG, GloCfg.word); +} + +void mt6632LowPowerOwnRead(IN struct ADAPTER *prAdapter, + OUT u_int8_t *pfgResult) +{ + uint32_t u4RegValue; + + HAL_MCR_RD(prAdapter, WPDMA_INT_STA, &u4RegValue); + *pfgResult = ((u4RegValue & WPDMA_FW_CLR_OWN_INT) ? TRUE : FALSE); +} + +void mt6632LowPowerOwnSet(IN struct ADAPTER *prAdapter, OUT u_int8_t *pfgResult) +{ + uint32_t u4RegValue; + + HAL_MCR_WR(prAdapter, CFG_PCIE_LPCR_HOST, PCIE_LPCR_HOST_SET_OWN); + HAL_MCR_RD(prAdapter, CFG_PCIE_LPCR_HOST, &u4RegValue); + *pfgResult = (u4RegValue == 0); +} + +void mt6632LowPowerOwnClear(IN struct ADAPTER *prAdapter, + OUT u_int8_t *pfgResult) +{ + uint32_t u4RegValue; + + HAL_MCR_WR(prAdapter, CFG_PCIE_LPCR_HOST, PCIE_LPCR_HOST_CLR_OWN); + HAL_MCR_RD(prAdapter, CFG_PCIE_LPCR_HOST, &u4RegValue); + *pfgResult = (u4RegValue == 0); +} + +void mt6632EnableInterrupt(IN struct ADAPTER *prAdapter) +{ + struct BUS_INFO *prBusInfo = prAdapter->chip_info->bus_info; + union WPDMA_INT_MASK IntMask; + + HAL_MCR_RD(prAdapter, WPDMA_INT_MSK, &IntMask.word); + + IntMask.field.rx_done_0 = 1; + IntMask.field.rx_done_1 = 1; + IntMask.field.tx_done = BIT(prBusInfo->tx_ring_fwdl_idx) | + BIT(prBusInfo->tx_ring_cmd_idx) | + BIT(prBusInfo->tx_ring_data_idx); + IntMask.field.tx_coherent = 0; + IntMask.field.rx_coherent = 0; + IntMask.field.tx_dly_int = 0; + IntMask.field.rx_dly_int = 0; + IntMask.field.fw_clr_own = 1; + + HAL_MCR_WR(prAdapter, WPDMA_INT_MSK, IntMask.word); + + DBGLOG(HAL, TRACE, "%s [0x%08x]\n", __func__, IntMask.word); +} + +void mt6632DisableInterrupt(IN struct ADAPTER *prAdapter) +{ + union WPDMA_INT_MASK IntMask; + + ASSERT(prAdapter); + + IntMask.word = 0; + + HAL_MCR_WR(prAdapter, WPDMA_INT_MSK, IntMask.word); + HAL_MCR_RD(prAdapter, WPDMA_INT_MSK, &IntMask.word); + + DBGLOG(HAL, TRACE, "%s\n", __func__); +} + +void mt6632WakeUpWiFi(IN struct ADAPTER *prAdapter) +{ + u_int8_t fgResult; + + ASSERT(prAdapter); + + HAL_LP_OWN_RD(prAdapter, &fgResult); + + if (fgResult) + prAdapter->fgIsFwOwn = FALSE; + else + HAL_LP_OWN_CLR(prAdapter, &fgResult); +} +#endif /* _HIF_PCIE */ + +struct BUS_INFO mt6632_bus_info = { +#if defined(_HIF_PCIE) + .top_cfg_base = MT6632_TOP_CFG_BASE, + .bus2chip = mt6632_bus2chip_cr_mapping, + .tx_ring_fwdl_idx = 3, + .tx_ring_cmd_idx = 2, + .tx_ring_data_idx = 0, + .fgCheckDriverOwnInt = TRUE, + .fgInitPCIeInt = FALSE, + .u4DmaMask = 32, + + .pdmaSetup = mt6632PdmaConfig, + .enableInterrupt = mt6632EnableInterrupt, + .disableInterrupt = mt6632DisableInterrupt, + .lowPowerOwnRead = mt6632LowPowerOwnRead, + .lowPowerOwnSet = mt6632LowPowerOwnSet, + .lowPowerOwnClear = mt6632LowPowerOwnClear, + .wakeUpWiFi = mt6632WakeUpWiFi, + .isValidRegAccess = NULL, + .getMailboxStatus = NULL, + .setDummyReg = NULL, + .checkDummyReg = NULL, +#endif /* _HIF_PCIE */ +#if defined(_HIF_USB) + .u4UdmaWlCfg_0_Addr = UDMA_WLCFG_0, + .u4UdmaWlCfg_1_Addr = UDMA_WLCFG_1, + .u4UdmaWlCfg_0 = + (UDMA_WLCFG_0_TX_EN(1) | UDMA_WLCFG_0_RX_EN(1) | + UDMA_WLCFG_0_RX_MPSZ_PAD0(1)), + .asicUsbSuspend = NULL, + .asicUsbEventEpDetected = NULL, +#endif /* _HIF_USB */ +#if defined(_HIF_SDIO) + .halTxGetFreeResource = NULL, + .halTxReturnFreeResource = NULL, + .halRestoreTxResource = NULL, + .halUpdateTxDonePendingCount = NULL, +#endif /* _HIF_SDIO */ +}; + +struct FWDL_OPS_T mt6632_fw_dl_ops = { + .constructFirmwarePrio = NULL, + .downloadPatch = NULL, + .downloadFirmware = wlanHarvardFormatDownload, + .getFwInfo = wlanGetHarvardFwInfo, + .getFwDlInfo = mt6632GetFwDlInfo, +}; + +struct TX_DESC_OPS_T mt6632TxDescOps = { + .fillNicAppend = fillNicTxDescAppendWithCR4, + .fillHifAppend = fillTxDescAppendByCR4, + .fillTxByteCount = fillTxDescTxByteCountWithCR4, +}; + +#if CFG_SUPPORT_QA_TOOL +struct ATE_OPS_T mt6632AteOps = { + .setICapStart = mt6632SetICapStart, + .getICapStatus = mt6632GetICapStatus, + .getICapIQData = commonGetICapIQData, + .getRbistDataDumpEvent = nicExtEventQueryMemDump, +}; +#endif + +struct CHIP_DBG_OPS mt6632_debug_ops = { + .showPdmaInfo = NULL, + .showPseInfo = NULL, + .showPleInfo = NULL, + .showCsrInfo = NULL, + .showDmaschInfo = NULL, +}; + +/* Litien code refine to support multi chip */ +struct mt66xx_chip_info mt66xx_chip_info_mt6632 = { + .bus_info = &mt6632_bus_info, + .fw_dl_ops = &mt6632_fw_dl_ops, + .prTxDescOps = &mt6632TxDescOps, +#if CFG_SUPPORT_QA_TOOL + .prAteOps = &mt6632AteOps, +#endif + .prDebugOps = &mt6632_debug_ops, + + .chip_id = MT6632_CHIP_ID, + .should_verify_chip_id = TRUE, + .sw_sync0 = MT6632_SW_SYNC0, + .sw_ready_bits = WIFI_FUNC_READY_BITS, + .sw_ready_bit_offset = MT6632_SW_SYNC0_RDY_OFFSET, + .patch_addr = MT6632_PATCH_START_ADDR, + .is_support_cr4 = TRUE, + .txd_append_size = MT6632_TX_DESC_APPEND_LENGTH, + .rxd_size = MT6632_RX_DESC_LENGTH, + .init_event_size = MT6632_RX_INIT_EVENT_LENGTH, + .event_hdr_size = MT6632_RX_EVENT_HDR_LENGTH, + .eco_info = mt6632_eco_table, + .isNicCapV1 = TRUE, + .is_support_efuse = TRUE, + + .asicCapInit = mt6632CapInit, + .asicEnableFWDownload = NULL, + .asicGetChipID = NULL, + .downloadBufferBin = wlanDownloadBufferBin, + .showTaskStack = NULL, + .features = 0, + .is_support_hw_amsdu = FALSE, + .ucMaxSwAmsduNum = 0, + .workAround = 0, +}; + +struct mt66xx_hif_driver_data mt66xx_driver_data_mt6632 = { + .chip_info = &mt66xx_chip_info_mt6632, +}; diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/mt7663/mt7663.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/mt7663/mt7663.c new file mode 100644 index 0000000000000..556b5c77d36e1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/mt7663/mt7663.c @@ -0,0 +1,327 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file mt7663.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. + */ + +#ifdef MT7663 + +/******************************************************************************* + * C O M P I L E 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 "mt7663.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +struct ECO_INFO mt7663_eco_table[] = { + /* HW version, ROM version, Factory version */ + {0x00, 0x00, 0x0A, 0x01}, /* E1 */ + {0x10, 0x01, 0x0A, 0x02}, /* E2 */ + {0x00, 0x00, 0x00, 0x00} /* End of table */ +}; + +#if defined(_HIF_PCIE) +struct PCIE_CHIP_CR_MAPPING mt7663_bus2chip_cr_mapping[] = { + /* chip addr, bus addr, range */ + {0x80000000, 0x00002000, 0x00001000}, /* MCU_CFG */ + + {0x50000000, 0x00004000, 0x00004000}, /* CONN_HIF (PDMA) */ + {0x50002000, 0x00005000, 0x00001000}, /* CONN_HIF (Reserved) */ + {0x5000A000, 0x00006000, 0x00001000}, /* CONN_HIF (DMASHDL) */ + {0x000E0000, 0x00007000, 0x00001000}, /* CONN_HIF_ON (HOST_CSR) */ + + {0x82060000, 0x00008000, 0x00004000}, /* WF_UMAC_TOP (PLE) */ + {0x82068000, 0x0000C000, 0x00002000}, /* WF_UMAC_TOP (PSE) */ + {0x8206C000, 0x0000E000, 0x00002000}, /* WF_UMAC_TOP (PP) */ + {0x82070000, 0x00010000, 0x00010000}, /* WF_PHY */ + {0x820F0000, 0x00020000, 0x00010000}, /* WF_LMAC_TOP */ + {0x820E0000, 0x00030000, 0x00010000}, /* WF_LMAC_TOP (WF_WTBL) */ + + {0x81000000, 0x00050000, 0x00010000}, /* BTSYS_OFF */ + {0x80070000, 0x00060000, 0x00010000}, /* GPSSYS */ + {0x40000000, 0x00070000, 0x00010000}, /* WF_SYSRAM */ + {0x00300000, 0x00080000, 0x00010000}, /* MCU_SYSRAM */ + + {0x80010000, 0x000A1000, 0x00001000}, /* CONN_MCU_DMA */ + {0x80030000, 0x000A2000, 0x00001000}, /* CONN_MCU_BTIF0 */ + {0x81030000, 0x000A3000, 0x00001000}, /* CONN_MCU_CFG_ON */ + {0x80050000, 0x000A4000, 0x00001000}, /* CONN_UART_PTA */ + {0x81040000, 0x000A5000, 0x00001000}, /* CONN_MCU_CIRQ */ + {0x81050000, 0x000A6000, 0x00001000}, /* CONN_MCU_GPT */ + {0x81060000, 0x000A7000, 0x00001000}, /* CONN_PTA */ + {0x81080000, 0x000A8000, 0x00001000}, /* CONN_MCU_WDT */ + {0x81090000, 0x000A9000, 0x00001000}, /* CONN_MCU_PDA */ + {0x810A0000, 0x000AA000, 0x00001000}, /* CONN_RDD_AHB_WRAP0 */ + {0x810B0000, 0x000AB000, 0x00001000}, /* BTSYS_ON */ + {0x810C0000, 0x000AC000, 0x00001000}, /* CONN_RBIST_TOP */ + {0x810D0000, 0x000AD000, 0x00001000}, /* CONN_RDD_AHB_WRAP0 */ + {0x820D0000, 0x000AE000, 0x00001000}, /* WFSYS_ON */ + {0x60000000, 0x000AF000, 0x00001000}, /* CONN_MCU_PDA */ + + {0x80020000, 0x000B0000, 0x00010000}, /* CONN_TOP_MISC_OFF */ + {0x81020000, 0x000C0000, 0x00010000}, /* CONN_TOP_MISC_ON */ + {0x7c030000, 0x000F0000, 0x00010000}, /* CONN_TOP_MISC_ON */ + + {0x0, 0x0, 0x0} +}; +#endif /* _HIF_PCIE */ + +void +mt7663ConstructFirmwarePrio(struct GLUE_INFO *prGlueInfo, + uint8_t **apucNameTable, uint8_t **apucName, + uint8_t *pucNameIdx, uint8_t ucMaxNameIdx) +{ + struct mt66xx_chip_info *prChipInfo = prGlueInfo->prAdapter->chip_info; + uint32_t chip_id = prChipInfo->chip_id; + uint8_t sub_idx = 0; + + for (sub_idx = 0; apucNameTable[sub_idx]; sub_idx++) { + if (((*pucNameIdx) + 3) < ucMaxNameIdx) { + /* Type 1. WIFI_RAM_CODE_MTxxxx.bin */ + snprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s%x.bin", + apucNameTable[sub_idx], chip_id); + (*pucNameIdx) += 1; + + /* Type 2. WIFI_RAM_CODE_MTxxxx */ + snprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s%x", + apucNameTable[sub_idx], chip_id); + (*pucNameIdx) += 1; + + /* Type 3. WIFI_RAM_CODE_MTxxxx_Ex.bin */ + snprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s%x_E%u.bin", + apucNameTable[sub_idx], chip_id, + wlanGetEcoVersion( + prGlueInfo->prAdapter)); + (*pucNameIdx) += 1; + + /* Type 4. WIFI_RAM_CODE_MTxxxx_Ex */ + snprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s%x_E%u", + apucNameTable[sub_idx], chip_id, + wlanGetEcoVersion( + prGlueInfo->prAdapter)); + (*pucNameIdx) += 1; + } else { + /* the table is not large enough */ + DBGLOG(INIT, ERROR, + "kalFirmwareImageMapping >> file name array is not enough.\n"); + ASSERT(0); + } + } +} + + +struct BUS_INFO mt7663_bus_info = { +#if defined(_HIF_PCIE) + .top_cfg_base = MT7663_TOP_CFG_BASE, + .bus2chip = mt7663_bus2chip_cr_mapping, + .tx_ring_fwdl_idx = 3, + .tx_ring_cmd_idx = 15, + .tx_ring_data_idx = 0, + .fgCheckDriverOwnInt = FALSE, + .fgInitPCIeInt = TRUE, + .u4DmaMask = 36, + + .pdmaSetup = asicPdmaConfig, +#if CFG_SUPPORT_PCIE_L2 + .pdmaStop = asicPdmaStop, +#endif + .enableInterrupt = asicEnableInterrupt, + .disableInterrupt = asicDisableInterrupt, + .lowPowerOwnRead = asicLowPowerOwnRead, + .lowPowerOwnSet = asicLowPowerOwnSet, + .lowPowerOwnClear = asicLowPowerOwnClearPCIe, + .wakeUpWiFi = asicWakeUpWiFi, + .isValidRegAccess = NULL, + .getMailboxStatus = asicGetMailboxStatus, + .setDummyReg = asicSetDummyReg, + .checkDummyReg = asicCheckDummyReg, +#endif /* _HIF_PCIE */ +#if defined(_HIF_USB) + .u4UdmaWlCfg_0_Addr = CONNAC_UDMA_WLCFG_0, + .u4UdmaWlCfg_1_Addr = CONNAC_UDMA_WLCFG_1, + .u4UdmaWlCfg_0 = + (UDMA_WLCFG_0_TX_EN(1) | + UDMA_WLCFG_0_RX_EN(1) | + UDMA_WLCFG_0_RX_MPSZ_PAD0(1) | + UDMA_WLCFG_0_1US_TIMER_EN(1)), + .u4UdmaTxTimeout = UDMA_TX_TIMEOUT_LIMIT, + .asicUsbSuspend = asicUsbSuspend, + .asicUsbEventEpDetected = asicUsbEventEpDetected, +#endif /* _HIF_USB */ +#if defined(_HIF_SDIO) + .halTxGetFreeResource = halTxGetFreeResource_v1, + .halTxReturnFreeResource = halTxReturnFreeResource_v1, + .halRestoreTxResource = halRestoreTxResource_v1, + .halUpdateTxDonePendingCount = halUpdateTxDonePendingCount_v1, +#endif /* _HIF_SDIO */ +}; + +struct FWDL_OPS_T mt7663_fw_dl_ops = { + .constructFirmwarePrio = mt7663ConstructFirmwarePrio, + .downloadPatch = wlanDownloadPatch, + .downloadFirmware = wlanConnacFormatDownload, + .getFwInfo = wlanGetConnacFwInfo, + .getFwDlInfo = asicGetFwDlInfo, +}; + +struct TX_DESC_OPS_T mt7663TxDescOps = { + .fillNicAppend = fillNicTxDescAppend, + .fillHifAppend = fillTxDescAppendByHostV2, + .fillTxByteCount = fillTxDescTxByteCount, +}; + +#if CFG_SUPPORT_QA_TOOL +struct ATE_OPS_T mt7663AteOps = { + .setICapStart = connacSetICapStart, + .getICapStatus = connacGetICapStatus, + .getICapIQData = connacGetICapIQData, + .getRbistDataDumpEvent = nicExtEventICapIQData, +}; +#endif + +struct CHIP_DBG_OPS mt7663_debug_ops = { +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + .showPdmaInfo = halShowPdmaInfo, + .showPseInfo = halShowPseInfo, + .showPleInfo = halShowPleInfo, + .showCsrInfo = halShowHostCsrInfo, + .showDmaschInfo = halShowDmaschInfo, +#else + .showPdmaInfo = NULL, + .showPseInfo = NULL, + .showPleInfo = NULL, + .showCsrInfo = NULL, + .showDmaschInfo = NULL, +#endif +}; + +/* Litien code refine to support multi chip */ +struct mt66xx_chip_info mt66xx_chip_info_mt7663 = { + .bus_info = &mt7663_bus_info, + .fw_dl_ops = &mt7663_fw_dl_ops, + .prTxDescOps = &mt7663TxDescOps, +#if CFG_SUPPORT_QA_TOOL + .prAteOps = &mt7663AteOps, +#endif + .prDebugOps = &mt7663_debug_ops, + + .chip_id = MT7663_CHIP_ID, + .should_verify_chip_id = FALSE, + .sw_sync0 = MT7663_SW_SYNC0, + .sw_ready_bits = WIFI_FUNC_NO_CR4_READY_BITS, + .sw_ready_bit_offset = MT7663_SW_SYNC0_RDY_OFFSET, + .patch_addr = MT7663_PATCH_START_ADDR, + .is_support_cr4 = FALSE, + .txd_append_size = MT7663_TX_DESC_APPEND_LENGTH, + .rxd_size = MT7663_RX_DESC_LENGTH, + .init_event_size = MT7663_RX_INIT_EVENT_LENGTH, + .event_hdr_size = MT7663_RX_EVENT_HDR_LENGTH, + .eco_info = mt7663_eco_table, + .isNicCapV1 = FALSE, + .is_support_efuse = TRUE, + + .asicCapInit = asicCapInit, + .asicEnableFWDownload = asicEnableFWDownload, + .asicGetChipID = NULL, + .downloadBufferBin = wlanConnacDownloadBufferBin, + .showTaskStack = NULL, + .is_support_hw_amsdu = TRUE, + .ucMaxSwAmsduNum = 0, + .workAround = 0, + .prTxPwrLimitFile = "TxPwrLimit_MT76x3.dat", + .ucTxPwrLimitBatchSize = 16, +}; + +struct mt66xx_hif_driver_data mt66xx_driver_data_mt7663 = { + .chip_info = &mt66xx_chip_info_mt7663, +}; + +#endif /* MT7663 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/mt7668/mt7668.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/mt7668/mt7668.c new file mode 100644 index 0000000000000..77c7d35fa0d22 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/chips/mt7668/mt7668.c @@ -0,0 +1,513 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file mt7668.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. + */ + +/******************************************************************************* + * C O M P I L E 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 "mt7668.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +struct ECO_INFO mt7668_eco_table[] = { + /* HW version, ROM version, Factory version, Eco version */ + {0x00, 0x00, 0xA, 0x1}, /* E1 */ + {0x10, 0x01, 0xB, 0x2}, /* E2 */ + {0x11, 0x01, 0xB, 0x2}, /* E2 */ + {0x00, 0x00, 0x0, 0x0} /* End of table */ +}; + +#if defined(_HIF_PCIE) +struct PCIE_CHIP_CR_MAPPING mt7668_bus2chip_cr_mapping[] = { + /* chip addr, bus addr, range */ + {0x82060000, 0x00008000, 0x00000450}, /* WF_PLE */ + {0x82068000, 0x0000c000, 0x00000450}, /* WF_PSE */ + {0x8206c000, 0x0000e000, 0x00000300}, /* PP */ + {0x820d0000, 0x00020000, 0x00000200}, /* WF_AON */ + {0x820f0000, 0x00020200, 0x00000400}, /* WF_CFG */ + {0x820f0800, 0x00020600, 0x00000200}, /* WF_CFGOFF */ + {0x820f1000, 0x00020800, 0x00000200}, /* WF_TRB */ + {0x820f2000, 0x00020a00, 0x00000200}, /* WF_AGG */ + {0x820f3000, 0x00020c00, 0x00000400}, /* WF_ARB */ + {0x820f4000, 0x00021000, 0x00000200}, /* WF_TMAC */ + {0x820f5000, 0x00021200, 0x00000400}, /* WF_RMAC */ + {0x820f6000, 0x00021600, 0x00000200}, /* WF_SEC */ + {0x820f7000, 0x00021800, 0x00000200}, /* WF_DMA */ + + {0x820f8000, 0x00022000, 0x00001000}, /* WF_PF */ + {0x820f9000, 0x00023000, 0x00000400}, /* WF_WTBLON */ + {0x820f9800, 0x00023400, 0x00000200}, /* WF_WTBLOFF */ + + {0x820fa000, 0x00024000, 0x00000200}, /* WF_ETBF */ + {0x820fb000, 0x00024200, 0x00000400}, /* WF_LPON */ + {0x820fc000, 0x00024600, 0x00000200}, /* WF_INT */ + {0x820fd000, 0x00024800, 0x00000400}, /* WF_MIB */ + + {0x820fe000, 0x00025000, 0x00002000}, /* WF_MU */ + + {0x820e0000, 0x00030000, 0x00010000}, /* WF_WTBL */ + + {0x80020000, 0x00000000, 0x00002000}, /* TOP_CFG */ + {0x80000000, 0x00002000, 0x00002000}, /* MCU_CFG */ + {0x50000000, 0x00004000, 0x00004000}, /* PDMA_CFG */ + {0xA0000000, 0x00008000, 0x00008000}, /* PSE_CFG */ + {0x82070000, 0x00010000, 0x00010000}, /* WF_PHY */ + + {0x0, 0x0, 0x0} +}; +#endif /* _HIF_PCIE */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +void +mt7668ConstructFirmwarePrio(struct GLUE_INFO *prGlueInfo, + uint8_t **apucNameTable, uint8_t **apucName, + uint8_t *pucNameIdx, uint8_t ucMaxNameIdx) +{ + struct mt66xx_chip_info *prChipInfo = prGlueInfo->prAdapter->chip_info; + uint32_t chip_id = prChipInfo->chip_id; + uint8_t sub_idx = 0; + + for (sub_idx = 0; apucNameTable[sub_idx]; sub_idx++) { + if (((*pucNameIdx) + 3) < ucMaxNameIdx) { + /* Type 1. WIFI_RAM_CODE_MTxxxx.bin */ + snprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s%x.bin", + apucNameTable[sub_idx], chip_id); + (*pucNameIdx) += 1; + + /* Type 2. WIFI_RAM_CODE_MTxxxx */ + snprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s%x", + apucNameTable[sub_idx], chip_id); + (*pucNameIdx) += 1; + + /* Type 3. WIFI_RAM_CODE_MTxxxx_Ex.bin */ + snprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s%x_E%u.bin", + apucNameTable[sub_idx], chip_id, + wlanGetEcoVersion( + prGlueInfo->prAdapter)); + (*pucNameIdx) += 1; + + /* Type 4. WIFI_RAM_CODE_MTxxxx_Ex */ + snprintf(*(apucName + (*pucNameIdx)), + CFG_FW_NAME_MAX_LEN, "%s%x_E%u", + apucNameTable[sub_idx], chip_id, + wlanGetEcoVersion( + prGlueInfo->prAdapter)); + (*pucNameIdx) += 1; + } else { + /* the table is not large enough */ + DBGLOG(INIT, ERROR, + "kalFirmwareImageMapping >> file name array is not enough.\n"); + ASSERT(0); + } + } +} + +void mt7668CapInit(IN struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + prChipInfo = prAdapter->chip_info; + + prChipInfo->u2HifTxdSize = 0; + prChipInfo->u2TxInitCmdPort = 0; + prChipInfo->u2TxFwDlPort = 0; + prChipInfo->fillHifTxDesc = NULL; + prChipInfo->ucPacketFormat = TXD_PKT_FORMAT_TXD; + prChipInfo->u4ExtraTxByteCount = 0; + + switch (prGlueInfo->u4InfType) { +#if defined(_HIF_PCIE) + case MT_DEV_INF_PCIE: + prChipInfo->u2TxInitCmdPort = TX_RING_FWDL_IDX_3; + prChipInfo->u2TxFwDlPort = TX_RING_FWDL_IDX_3; + break; +#endif /* _HIF_PCIE */ +#if defined(_HIF_USB) + case MT_DEV_INF_USB: + prChipInfo->u2TxInitCmdPort = USB_DATA_BULK_OUT_EP8; + prChipInfo->u2TxFwDlPort = USB_DATA_BULK_OUT_EP8; + break; +#endif /* _HIF_USB */ + default: + break; + } +} + +uint32_t mt7668GetFwDlInfo(struct ADAPTER *prAdapter, + char *pcBuf, int i4TotalLen) +{ + struct WIFI_VER_INFO *prVerInfo = &prAdapter->rVerInfo; +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + struct TAILER_FORMAT_T_2 *prTailer; +#else + struct TAILER_FORMAT_T *prTailer; +#endif + uint32_t u4Offset = 0; + uint8_t aucBuf[32]; + +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + prTailer = &prVerInfo->rN9Compressedtailer; +#else + prTailer = &prVerInfo->rN9tailer[0]; +#endif + kalMemZero(aucBuf, 32); + kalMemCopy(aucBuf, prTailer->ram_version, 10); + u4Offset += snprintf(pcBuf + u4Offset, i4TotalLen - u4Offset, + "N9 tailer version %s (%s) info %u:E%u\n", + aucBuf, prTailer->ram_built_date, prTailer->chip_info, + prTailer->eco_code + 1); + +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + prTailer = &prVerInfo->rCR4Compressedtailer; +#else + prTailer = &prVerInfo->rCR4tailer[0]; +#endif + kalMemZero(aucBuf, 32); + kalMemCopy(aucBuf, prTailer->ram_version, 10); + u4Offset += snprintf(pcBuf + u4Offset, i4TotalLen - u4Offset, + "CR4 tailer version %s (%s) info %u:E%u\n", + aucBuf, prTailer->ram_built_date, prTailer->chip_info, + prTailer->eco_code + 1); + + return u4Offset; +} + +#if defined(_HIF_PCIE) + +void mt7668PdmaConfig(struct GLUE_INFO *prGlueInfo, u_int8_t enable) +{ + struct BUS_INFO *prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + union WPDMA_GLO_CFG_STRUCT GloCfg; + union WPDMA_INT_MASK IntMask; + + kalDevRegRead(prGlueInfo, WPDMA_GLO_CFG, &GloCfg.word); + + kalDevRegRead(prGlueInfo, WPDMA_INT_MSK, &IntMask.word); + + if (enable == TRUE) { + /*0x4208 = 5440_1E70*/ + GloCfg.field_1.EnableTxDMA = 1; + GloCfg.field_1.EnableRxDMA = 1; + + GloCfg.field_1.WPDMABurstSIZE = 3; + GloCfg.field_1.EnTXWriteBackDDONE = 1; + + GloCfg.field_1.tx_bt_size = 1; + GloCfg.field_1.multi_dma_en = 3; + GloCfg.field_1.fifo_little_endian = 1; + + GloCfg.field_1.tx_bt_size_bit21 = 1; + GloCfg.field_1.first_token = 1; + GloCfg.field_1.omit_tx_info = 1; + GloCfg.field_1.reserve_30 = 1; + + IntMask.field.rx_done_0 = 1; + IntMask.field.rx_done_1 = 1; + IntMask.field.tx_done = BIT(prBusInfo->tx_ring_fwdl_idx) | + BIT(prBusInfo->tx_ring_cmd_idx) | + BIT(prBusInfo->tx_ring_data_idx); + IntMask.field.tx_dly_int = 0; + } else { + GloCfg.field_1.EnableRxDMA = 0; + GloCfg.field_1.EnableTxDMA = 0; + + IntMask.field.rx_done_0 = 0; + IntMask.field.rx_done_1 = 0; + IntMask.field.tx_done = 0; + IntMask.field.tx_dly_int = 0; + } + + kalDevRegWrite(prGlueInfo, WPDMA_INT_MSK, IntMask.word); + kalDevRegWrite(prGlueInfo, WPDMA_GLO_CFG, GloCfg.word); + + + /* new PDMA */ + /* 0x4260 = 0000_0005 */ + kalDevRegWrite(prGlueInfo, MT_WPDMA_PAUSE_RX_Q, 0x5); + + /* 0x4500 = 0000_0001*/ + kalDevRegWrite(prGlueInfo, MT_WPDMA_GLO_CFG_1, 0x1); + + /* 0x4510 = 000F_0000*/ + kalDevRegWrite(prGlueInfo, MT_WPDMA_TX_PRE_CFG, 0xF0000); + + /* 0x4520 = 0F7F_0000 */ + kalDevRegWrite(prGlueInfo, MT_WPDMA_RX_PRE_CFG, 0xF7F0000); + + /* 0x4530 = 0EA6_0026 */ + kalDevRegWrite(prGlueInfo, MT_WPDMA_ABT_CFG, 0x0EA60026); + + /* 0x4534 = E4E4_E4E4*/ + kalDevRegWrite(prGlueInfo, MT_WPDMA_ABT_CFG1, 0xE4E4E4E4); + +} + +void mt7668LowPowerOwnRead(IN struct ADAPTER *prAdapter, + OUT u_int8_t *pfgResult) +{ + uint32_t u4RegValue; + + HAL_MCR_RD(prAdapter, WPDMA_INT_STA, &u4RegValue); + *pfgResult = ((u4RegValue & WPDMA_FW_CLR_OWN_INT) ? TRUE : FALSE); +} + +void mt7668LowPowerOwnSet(IN struct ADAPTER *prAdapter, OUT u_int8_t *pfgResult) +{ + uint32_t u4RegValue; + + HAL_MCR_WR(prAdapter, CFG_PCIE_LPCR_HOST, PCIE_LPCR_HOST_SET_OWN); + HAL_MCR_RD(prAdapter, CFG_PCIE_LPCR_HOST, &u4RegValue); + *pfgResult = (u4RegValue == 0); +} + +void mt7668LowPowerOwnClear(IN struct ADAPTER *prAdapter, + OUT u_int8_t *pfgResult) +{ + uint32_t u4RegValue; + + HAL_MCR_WR(prAdapter, CFG_PCIE_LPCR_HOST, PCIE_LPCR_HOST_CLR_OWN); + HAL_MCR_RD(prAdapter, CFG_PCIE_LPCR_HOST, &u4RegValue); + *pfgResult = (u4RegValue == 0); +} +void mt7668EnableInterrupt(IN struct ADAPTER *prAdapter) +{ + struct BUS_INFO *prBusInfo = prAdapter->chip_info->bus_info; + union WPDMA_INT_MASK IntMask; + + HAL_MCR_RD(prAdapter, WPDMA_INT_MSK, &IntMask.word); + + IntMask.field.rx_done_0 = 1; + IntMask.field.rx_done_1 = 1; + IntMask.field.tx_done = BIT(prBusInfo->tx_ring_fwdl_idx) | + BIT(prBusInfo->tx_ring_cmd_idx) | + BIT(prBusInfo->tx_ring_data_idx); + IntMask.field.tx_coherent = 0; + IntMask.field.rx_coherent = 0; + IntMask.field.tx_dly_int = 0; + IntMask.field.rx_dly_int = 0; + IntMask.field.fw_clr_own = 1; + + HAL_MCR_WR(prAdapter, WPDMA_INT_MSK, IntMask.word); + + DBGLOG(HAL, TRACE, "%s [0x%08x]\n", __func__, IntMask.word); +} + +void mt7668DisableInterrupt(IN struct ADAPTER *prAdapter) +{ + union WPDMA_INT_MASK IntMask; + + ASSERT(prAdapter); + + IntMask.word = 0; + + HAL_MCR_WR(prAdapter, WPDMA_INT_MSK, IntMask.word); + HAL_MCR_RD(prAdapter, WPDMA_INT_MSK, &IntMask.word); + + DBGLOG(HAL, TRACE, "%s\n", __func__); +} + +void mt7668WakeUpWiFi(IN struct ADAPTER *prAdapter) +{ + u_int8_t fgResult; + + ASSERT(prAdapter); + + HAL_LP_OWN_RD(prAdapter, &fgResult); + + if (fgResult) + prAdapter->fgIsFwOwn = FALSE; + else + HAL_LP_OWN_CLR(prAdapter, &fgResult); +} +#endif /* _HIF_PCIE */ + +struct BUS_INFO mt7668_bus_info = { +#if defined(_HIF_PCIE) + .top_cfg_base = MT7668_TOP_CFG_BASE, + .bus2chip = mt7668_bus2chip_cr_mapping, + .tx_ring_fwdl_idx = 3, + .tx_ring_cmd_idx = 2, + .tx_ring_data_idx = 0, + .fgCheckDriverOwnInt = FALSE, + .fgInitPCIeInt = FALSE, + .u4DmaMask = 32, + + .pdmaSetup = mt7668PdmaConfig, + .enableInterrupt = mt7668EnableInterrupt, + .disableInterrupt = mt7668DisableInterrupt, + .lowPowerOwnRead = mt7668LowPowerOwnRead, + .lowPowerOwnSet = mt7668LowPowerOwnSet, + .lowPowerOwnClear = mt7668LowPowerOwnClear, + .wakeUpWiFi = mt7668WakeUpWiFi, + .isValidRegAccess = NULL, + .getMailboxStatus = NULL, + .setDummyReg = NULL, + .checkDummyReg = NULL, +#endif /* _HIF_PCIE */ +#if defined(_HIF_USB) + .u4UdmaWlCfg_0_Addr = UDMA_WLCFG_0, + .u4UdmaWlCfg_1_Addr = UDMA_WLCFG_1, + .u4UdmaWlCfg_0 = + (UDMA_WLCFG_0_TX_EN(1) | UDMA_WLCFG_0_RX_EN(1) | + UDMA_WLCFG_0_RX_MPSZ_PAD0(1)), + .asicUsbSuspend = NULL, + .asicUsbEventEpDetected = NULL, +#endif /* _HIF_USB */ +#if defined(_HIF_SDIO) + .halTxGetFreeResource = NULL, + .halTxReturnFreeResource = NULL, + .halRestoreTxResource = NULL, + .halUpdateTxDonePendingCount = NULL, +#endif /* _HIF_SDIO */ +}; + +struct FWDL_OPS_T mt7668_fw_dl_ops = { + .constructFirmwarePrio = mt7668ConstructFirmwarePrio, + .downloadPatch = wlanDownloadPatch, + .downloadFirmware = wlanHarvardFormatDownload, + .getFwInfo = wlanGetHarvardFwInfo, + .getFwDlInfo = mt7668GetFwDlInfo, +}; + +struct TX_DESC_OPS_T mt7668TxDescOps = { + .fillNicAppend = fillNicTxDescAppendWithCR4, + .fillHifAppend = fillTxDescAppendByCR4, + .fillTxByteCount = fillTxDescTxByteCountWithCR4, +}; + +#if CFG_SUPPORT_QA_TOOL +struct ATE_OPS_T mt7668AteOps = { + .setICapStart = mt6632SetICapStart, + .getICapStatus = mt6632GetICapStatus, + .getICapIQData = commonGetICapIQData, + .getRbistDataDumpEvent = nicExtEventQueryMemDump, +}; +#endif + +struct CHIP_DBG_OPS mt7668_debug_ops = { + .showPdmaInfo = NULL, + .showPseInfo = NULL, + .showPleInfo = NULL, + .showCsrInfo = NULL, + .showDmaschInfo = NULL, +}; + +/* Litien code refine to support multi chip */ +struct mt66xx_chip_info mt66xx_chip_info_mt7668 = { + .bus_info = &mt7668_bus_info, + .fw_dl_ops = &mt7668_fw_dl_ops, + .prTxDescOps = &mt7668TxDescOps, +#if CFG_SUPPORT_QA_TOOL + .prAteOps = &mt7668AteOps, +#endif + .prDebugOps = &mt7668_debug_ops, + + .chip_id = MT7668_CHIP_ID, + .should_verify_chip_id = TRUE, + .sw_sync0 = MT7668_SW_SYNC0, + .sw_ready_bits = WIFI_FUNC_READY_BITS, + .sw_ready_bit_offset = MT7668_SW_SYNC0_RDY_OFFSET, + .patch_addr = MT7668_PATCH_START_ADDR, + .is_support_cr4 = TRUE, + .txd_append_size = MT7668_TX_DESC_APPEND_LENGTH, + .rxd_size = MT7668_RX_DESC_LENGTH, + .init_event_size = MT7668_RX_INIT_EVENT_LENGTH, + .event_hdr_size = MT7668_RX_EVENT_HDR_LENGTH, + .eco_info = mt7668_eco_table, + .isNicCapV1 = TRUE, + .is_support_efuse = TRUE, + + .asicCapInit = mt7668CapInit, + .asicEnableFWDownload = NULL, + .asicGetChipID = NULL, + .downloadBufferBin = wlanDownloadBufferBin, + .showTaskStack = NULL, + .features = 0, + .is_support_hw_amsdu = FALSE, + .ucMaxSwAmsduNum = 0, + .workAround = 0, + .prTxPwrLimitFile = "TxPwrLimit_MT76x8.dat", + .ucTxPwrLimitBatchSize = 32, +}; + +struct mt66xx_hif_driver_data mt66xx_driver_data_mt7668 = { + .chip_info = &mt66xx_chip_info_mt7668, +}; + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/common/debug.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/common/debug.c new file mode 100644 index 0000000000000..70819504e5852 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/common/debug.c @@ -0,0 +1,555 @@ +#include "precomp.h" + +#if (CFG_SUPPORT_TRACE_TC4 == 1) +struct COMMAND { + uint8_t ucCID; + u_int8_t fgSetQuery; + u_int8_t fgNeedResp; + uint8_t ucCmdSeqNum; +}; + +struct SECURITY_FRAME { + uint16_t u2EthType; + uint16_t u2Reserved; +}; + +struct MGMT_FRAME { + uint16_t u2FrameCtl; + uint16_t u2DurationID; +}; + +struct TC_RES_RELEASE_ENTRY { + uint64_t u8RelaseTime; + uint32_t u4RelCID; + uint32_t u4Tc4RelCnt; + uint32_t u4AvailableTc4; +}; + +struct CMD_TRACE_ENTRY { + uint64_t u8TxTime; + enum COMMAND_TYPE eCmdType; + union { + struct COMMAND rCmd; + struct SECURITY_FRAME rSecFrame; + struct MGMT_FRAME rMgmtFrame; + } u; +}; + +#define TC_RELEASE_TRACE_BUF_MAX_NUM 100 +#define TXED_CMD_TRACE_BUF_MAX_NUM 100 + +static struct TC_RES_RELEASE_ENTRY *gprTcReleaseTraceBuffer; +static struct CMD_TRACE_ENTRY *gprCmdTraceEntry; +void wlanDebugTC4Init(void) +{ + /* debug for command/tc4 resource begin */ + gprTcReleaseTraceBuffer = + kalMemAlloc(TC_RELEASE_TRACE_BUF_MAX_NUM * sizeof( + struct TC_RES_RELEASE_ENTRY), PHY_MEM_TYPE); + kalMemZero(gprTcReleaseTraceBuffer, + TC_RELEASE_TRACE_BUF_MAX_NUM * sizeof(struct + TC_RES_RELEASE_ENTRY)); + gprCmdTraceEntry = kalMemAlloc(TXED_CMD_TRACE_BUF_MAX_NUM * + sizeof(struct CMD_TRACE_ENTRY), + PHY_MEM_TYPE); + kalMemZero(gprCmdTraceEntry, + TXED_CMD_TRACE_BUF_MAX_NUM * sizeof(struct + CMD_TRACE_ENTRY)); + /* debug for command/tc4 resource end */ +} + +void wlanDebugTC4Uninit(void) +{ + /* debug for command/tc4 resource begin */ + kalMemFree(gprTcReleaseTraceBuffer, PHY_MEM_TYPE, + TC_RELEASE_TRACE_BUF_MAX_NUM * sizeof(struct + TC_RES_RELEASE_ENTRY)); + kalMemFree(gprCmdTraceEntry, PHY_MEM_TYPE, + TXED_CMD_TRACE_BUF_MAX_NUM * sizeof(struct + CMD_TRACE_ENTRY)); + /* debug for command/tc4 resource end */ +} + +void wlanTraceTxCmd(struct CMD_INFO *prCmd) +{ + static uint16_t u2CurEntry; + struct CMD_TRACE_ENTRY *prCurCmd = + &gprCmdTraceEntry[u2CurEntry]; + + prCurCmd->u8TxTime = sched_clock(); + prCurCmd->eCmdType = prCmd->eCmdType; + if (prCmd->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) { + struct WLAN_MAC_MGMT_HEADER *prMgmt = (struct + WLAN_MAC_MGMT_HEADER *)prCmd->prMsduInfo->prPacket; + + prCurCmd->u.rMgmtFrame.u2FrameCtl = prMgmt->u2FrameCtrl; + prCurCmd->u.rMgmtFrame.u2DurationID = prMgmt->u2Duration; + } else if (prCmd->eCmdType == COMMAND_TYPE_SECURITY_FRAME) { + uint8_t *pucPkt = (uint8_t *)((struct sk_buff *) + prCmd->prPacket)->data; + + prCurCmd->u.rSecFrame.u2EthType = + (pucPkt[ETH_TYPE_LEN_OFFSET] << 8) | + (pucPkt[ETH_TYPE_LEN_OFFSET + 1]); + } else { + prCurCmd->u.rCmd.ucCID = prCmd->ucCID; + prCurCmd->u.rCmd.ucCmdSeqNum = prCmd->ucCmdSeqNum; + prCurCmd->u.rCmd.fgNeedResp = prCmd->fgNeedResp; + prCurCmd->u.rCmd.fgSetQuery = prCmd->fgSetQuery; + } + u2CurEntry++; + if (u2CurEntry == TC_RELEASE_TRACE_BUF_MAX_NUM) + u2CurEntry = 0; +} + +void wlanTraceReleaseTcRes(struct ADAPTER *prAdapter, + uint32_t u4TxRlsCnt, uint32_t u4Available) +{ + static uint16_t u2CurEntry; + struct TC_RES_RELEASE_ENTRY *prCurBuf = + &gprTcReleaseTraceBuffer[u2CurEntry]; + + prCurBuf->u8RelaseTime = sched_clock(); + prCurBuf->u4Tc4RelCnt = u4TxRlsCnt; + prCurBuf->u4AvailableTc4 = u4Available; + u2CurEntry++; + if (u2CurEntry == TXED_CMD_TRACE_BUF_MAX_NUM) + u2CurEntry = 0; +} + +void wlanDumpTcResAndTxedCmd(uint8_t *pucBuf, + uint32_t maxLen) +{ + uint16_t i = 0; + struct TC_RES_RELEASE_ENTRY *prTcRel = + gprTcReleaseTraceBuffer; + struct CMD_TRACE_ENTRY *prCmd = gprCmdTraceEntry; + + if (pucBuf) { + int bufLen = 0; + + for (; i < TXED_CMD_TRACE_BUF_MAX_NUM / 2; i++) { + bufLen = snprintf(pucBuf, maxLen, + "%d: Time %llu, Type %d, Content %08x; %d: Time %llu, Type %d, Content %08x\n", + i * 2, prCmd[i * 2].u8TxTime, + prCmd[i * 2].eCmdType, + *(uint32_t *) + (&prCmd[i * 2].u.rCmd.ucCID), + i * 2 + 1, + prCmd[i * 2 + 1].u8TxTime, + prCmd[i * 2 + 1].eCmdType, + *(uint32_t *) + (&prCmd[i * 2 + 1].u.rCmd.ucCID)); + if (bufLen <= 0) + break; + pucBuf += bufLen; + maxLen -= bufLen; + } + for (i = 0; i < TC_RELEASE_TRACE_BUF_MAX_NUM / 2; i++) { + bufLen = snprintf(pucBuf, maxLen, + "%d: Time %llu, Tc4Cnt %d, Free %d, CID %08x; %d: Time %llu, Tc4Cnt %d, Free %d CID %08x\n", + i * 2, prTcRel[i * 2].u8RelaseTime, + prTcRel[i * 2].u4Tc4RelCnt, + prTcRel[i * 2].u4AvailableTc4, + prTcRel[i * 2].u4RelCID, + i * 2 + 1, + prTcRel[i * 2 + 1].u8RelaseTime, + prTcRel[i * 2 + 1].u4Tc4RelCnt, + prTcRel[i * 2 + 1].u4AvailableTc4, + prTcRel[i * 2 + 1].u4RelCID); + if (bufLen <= 0) + break; + pucBuf += bufLen; + maxLen -= bufLen; + } + } else { + for (; i < TXED_CMD_TRACE_BUF_MAX_NUM / 4; i++) { + LOG_FUNC( + "%d: Time %llu, Type %d, Content %08x; %d: Time %llu, Type %d, Content %08x; ", + i * 4, prCmd[i * 4].u8TxTime, + prCmd[i * 4].eCmdType, + *(uint32_t *)(&prCmd[i * 4].u.rCmd.ucCID), + i * 4 + 1, prCmd[i * 4 + 1].u8TxTime, + prCmd[i * 4 + 1].eCmdType, + *(uint32_t *)(&prCmd[i * 4 + 1].u.rCmd.ucCID)); + LOG_FUNC( + "%d: Time %llu, Type %d, Content %08x; %d: Time %llu, Type %d, Content %08x\n", + i * 4 + 2, prCmd[i * 4 + 2].u8TxTime, + prCmd[i * 4 + 2].eCmdType, + *(uint32_t *)(&prCmd[i * 4 + 2].u.rCmd.ucCID), + i * 4 + 3, prCmd[i * 4 + 3].u8TxTime, + prCmd[i * 4 + 3].eCmdType, + *(uint32_t *)(&prCmd[i * 4 + 3].u.rCmd.ucCID)); + } + for (i = 0; i < TC_RELEASE_TRACE_BUF_MAX_NUM / 4; i++) { + LOG_FUNC( + "%d: Time %llu, Tc4Cnt %d, Free %d, CID %08x; %d: Time %llu, Tc4Cnt %d, Free %d, CID %08x;", + i * 4, prTcRel[i * 4].u8RelaseTime, + prTcRel[i * 4].u4Tc4RelCnt, + prTcRel[i * 4].u4AvailableTc4, + prTcRel[i * 4].u4RelCID, + i * 4 + 1, prTcRel[i * 4 + 1].u8RelaseTime, + prTcRel[i * 4 + 1].u4Tc4RelCnt, + prTcRel[i * 4 + 1].u4AvailableTc4, + prTcRel[i * 4 + 1].u4RelCID); + LOG_FUNC( + "%d: Time %llu, Tc4Cnt %d, Free %d, CID %08x; %d: Time %llu, Tc4Cnt %d, Free %d, CID %08x\n", + i * 4 + 2, prTcRel[i * 4 + 2].u8RelaseTime, + prTcRel[i * 4 + 2].u4Tc4RelCnt, + prTcRel[i * 4 + 2].u4AvailableTc4, + prTcRel[i * 4 + 2].u4RelCID, + i * 4 + 3, prTcRel[i * 4 + 3].u8RelaseTime, + prTcRel[i * 4 + 3].u4Tc4RelCnt, + prTcRel[i * 4 + 3].u4AvailableTc4, + prTcRel[i * 4 + 3].u4RelCID); + } + } +} +#endif + +uint32_t wlanSetDriverDbgLevel(IN uint32_t u4DbgIdx, IN uint32_t u4DbgMask) +{ + uint32_t u4Idx; + uint32_t fgStatus = WLAN_STATUS_SUCCESS; + + if (u4DbgIdx == DBG_ALL_MODULE_IDX) { + for (u4Idx = 0; u4Idx < DBG_MODULE_NUM; u4Idx++) + aucDebugModule[u4Idx] = (uint8_t) u4DbgMask; + LOG_FUNC("Set ALL DBG module log level to [0x%02x]\n", + u4DbgMask); + } else if (u4DbgIdx < DBG_MODULE_NUM) { + aucDebugModule[u4DbgIdx] = (uint8_t) u4DbgMask; + LOG_FUNC("Set DBG module[%u] log level to [0x%02x]\n", + u4DbgIdx, u4DbgMask); + } else { + fgStatus = WLAN_STATUS_FAILURE; + } + + if (fgStatus == WLAN_STATUS_SUCCESS) + wlanDriverDbgLevelSync(); + + return fgStatus; +} + +uint32_t wlanGetDriverDbgLevel(IN uint32_t u4DbgIdx, OUT uint32_t *pu4DbgMask) +{ + if (u4DbgIdx < DBG_MODULE_NUM) { + *pu4DbgMask = aucDebugModule[u4DbgIdx]; + return WLAN_STATUS_SUCCESS; + } + + return WLAN_STATUS_FAILURE; +} + +uint32_t wlanDbgLevelUiSupport(IN struct ADAPTER *prAdapter, uint32_t u4Version, + uint32_t ucModule) +{ + uint32_t u4Enable = ENUM_WIFI_LOG_LEVEL_SUPPORT_DISABLE; + + switch (u4Version) { + case ENUM_WIFI_LOG_LEVEL_VERSION_V1: + switch (ucModule) { + case ENUM_WIFI_LOG_MODULE_DRIVER: + u4Enable = ENUM_WIFI_LOG_LEVEL_SUPPORT_ENABLE; + break; + case ENUM_WIFI_LOG_MODULE_FW: + u4Enable = ENUM_WIFI_LOG_LEVEL_SUPPORT_ENABLE; + break; + } + break; + default: + break; + } + + return u4Enable; +} + +uint32_t wlanDbgGetLogLevelImpl(IN struct ADAPTER *prAdapter, + uint32_t u4Version, uint32_t ucModule) +{ + uint32_t u4Level = ENUM_WIFI_LOG_LEVEL_DEFAULT; + + switch (u4Version) { + case ENUM_WIFI_LOG_LEVEL_VERSION_V1: + wlanDbgGetGlobalLogLevel(ucModule, &u4Level); + break; + default: + break; + } + + return u4Level; +} + +void wlanDbgSetLogLevelImpl(IN struct ADAPTER *prAdapter, + uint32_t u4Version, uint32_t u4Module, uint32_t u4level) +{ + uint32_t u4DriverLevel = ENUM_WIFI_LOG_LEVEL_DEFAULT; + uint32_t u4FwLevel = ENUM_WIFI_LOG_LEVEL_DEFAULT; + + if (u4level >= ENUM_WIFI_LOG_LEVEL_NUM) + return; + + switch (u4Version) { + case ENUM_WIFI_LOG_LEVEL_VERSION_V1: + wlanDbgSetGlobalLogLevel(u4Module, u4level); + switch (u4Module) { + case ENUM_WIFI_LOG_MODULE_DRIVER: + { + uint32_t u4DriverLogMask; + + if (u4level == ENUM_WIFI_LOG_LEVEL_DEFAULT) + u4DriverLogMask = DBG_LOG_LEVEL_DEFAULT; + else if (u4level == ENUM_WIFI_LOG_LEVEL_MORE) + u4DriverLogMask = DBG_LOG_LEVEL_MORE; + else + u4DriverLogMask = DBG_LOG_LEVEL_EXTREME; + + wlanSetDriverDbgLevel(DBG_ALL_MODULE_IDX, + (u4DriverLogMask & DBG_CLASS_MASK)); + } + break; + case ENUM_WIFI_LOG_MODULE_FW: + { + struct CMD_EVENT_LOG_UI_INFO cmd; + + kalMemZero(&cmd, + sizeof(struct CMD_EVENT_LOG_UI_INFO)); + cmd.u4Version = u4Version; + cmd.u4LogLevel = u4level; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_LOG_UI_INFO, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_EVENT_LOG_UI_INFO), + (uint8_t *)&cmd, + NULL, + 0); + } + break; + default: + break; + } + break; + default: + break; + } + + wlanDbgGetGlobalLogLevel(ENUM_WIFI_LOG_MODULE_DRIVER, &u4DriverLevel); + wlanDbgGetGlobalLogLevel(ENUM_WIFI_LOG_MODULE_FW, &u4FwLevel); +#if (CFG_BUILT_IN_DRIVER == 0) && (CFG_MTK_ANDROID_WMT == 1) + /* + * The function definition of get_logtoomuch_enable() and + * set_logtoomuch_enable of Android O0 or lower version are different + * from that of Android O1 or higher version. Wlan driver supports .ko + * module from Android O1. Use CFG_BUILT_IN_DRIVER to distinguish + * Android version higher than O1 instead. + */ + if ((u4DriverLevel > ENUM_WIFI_LOG_LEVEL_DEFAULT || + u4FwLevel > ENUM_WIFI_LOG_LEVEL_DEFAULT) && + get_logtoomuch_enable()) { + DBGLOG(OID, TRACE, + "Disable print log too much. driver: %d, fw: %d\n", + u4DriverLevel, + u4FwLevel); + set_logtoomuch_enable(0); + } +#endif +} + +u_int8_t wlanDbgGetGlobalLogLevel(uint32_t u4Module, uint32_t *pu4Level) +{ + if (u4Module != ENUM_WIFI_LOG_MODULE_DRIVER && + u4Module != ENUM_WIFI_LOG_MODULE_FW) + return FALSE; + + *pu4Level = au4LogLevel[u4Module]; + return TRUE; +} + +u_int8_t wlanDbgSetGlobalLogLevel(uint32_t u4Module, uint32_t u4Level) +{ + if (u4Module != ENUM_WIFI_LOG_MODULE_DRIVER && + u4Module != ENUM_WIFI_LOG_MODULE_FW) + return FALSE; + + au4LogLevel[u4Module] = u4Level; + return TRUE; +} + +void wlanDriverDbgLevelSync(void) +{ + uint8_t i = 0; + uint32_t u4Mask = DBG_CLASS_MASK; + uint32_t u4DriverLogLevel = ENUM_WIFI_LOG_LEVEL_DEFAULT; + + /* get the lowest level as module's level */ + for (i = 0; i < DBG_MODULE_NUM; i++) + u4Mask &= aucDebugModule[i]; + + if ((u4Mask & DBG_LOG_LEVEL_EXTREME) == DBG_LOG_LEVEL_EXTREME) + u4DriverLogLevel = ENUM_WIFI_LOG_LEVEL_EXTREME; + else if ((u4Mask & DBG_LOG_LEVEL_MORE) == DBG_LOG_LEVEL_MORE) + u4DriverLogLevel = ENUM_WIFI_LOG_LEVEL_MORE; + else + u4DriverLogLevel = ENUM_WIFI_LOG_LEVEL_DEFAULT; + + wlanDbgSetGlobalLogLevel(ENUM_WIFI_LOG_MODULE_DRIVER, u4DriverLogLevel); +} + +static void +firmwareHexDump(const uint8_t *pucPreFix, + int32_t i4PreFixType, + int32_t i4RowSize, int32_t i4GroupSize, + const void *pvBuf, size_t len, u_int8_t fgAscii) +{ +#define OLD_KBUILD_MODNAME KBUILD_MODNAME +#undef KBUILD_MODNAME +#define KBUILD_MODNAME "wlan_mt6632_fw" + + const uint8_t *pucPtr = pvBuf; + int32_t i, i4LineLen, i4Remaining = len; + uint8_t ucLineBuf[32 * 3 + 2 + 32 + 1]; + + if (i4RowSize != 16 && i4RowSize != 32) + i4RowSize = 16; + + for (i = 0; i < len; i += i4RowSize) { + i4LineLen = min(i4Remaining, i4RowSize); + i4Remaining -= i4RowSize; + + /* use kernel API */ + hex_dump_to_buffer(pucPtr + i, i4LineLen, i4RowSize, + i4GroupSize, + ucLineBuf, sizeof(ucLineBuf), fgAscii); + + switch (i4PreFixType) { + case DUMP_PREFIX_ADDRESS: + pr_info("%s%p: %s\n", + pucPreFix, pucPtr + i, ucLineBuf); + break; + case DUMP_PREFIX_OFFSET: + pr_info("%s%.8x: %s\n", pucPreFix, i, ucLineBuf); + break; + default: + pr_info("%s%s\n", pucPreFix, ucLineBuf); + break; + } + } +#undef KBUILD_MODNAME +#define KBUILD_MODNAME OLD_KBUILD_MODNAME +} + +void wlanPrintFwLog(uint8_t *pucLogContent, + uint16_t u2MsgSize, uint8_t ucMsgType, + const uint8_t *pucFmt, ...) +{ +#define OLD_KBUILD_MODNAME KBUILD_MODNAME +#define OLD_LOG_FUNC LOG_FUNC +#undef KBUILD_MODNAME +#undef LOG_FUNC +#define KBUILD_MODNAME "wlan_mt6632_fw" +#define LOG_FUNC pr_info +#define DBG_LOG_BUF_SIZE 128 + + int8_t aucLogBuffer[DBG_LOG_BUF_SIZE]; + va_list args; + + if (u2MsgSize > DEBUG_MSG_SIZE_MAX - 1) { + LOG_FUNC("Firmware Log Size(%d) is too large, type %d\n", + u2MsgSize, ucMsgType); + return; + } + switch (ucMsgType) { + case DEBUG_MSG_TYPE_ASCII: { + uint8_t *pucChr; + + pucLogContent[u2MsgSize] = '\0'; + + /* skip newline */ + pucChr = kalStrChr(pucLogContent, '\0'); + if (*(pucChr - 1) == '\n') + *(pucChr - 1) = '\0'; + + LOG_FUNC("%s\n", pucLogContent); + } + break; + case DEBUG_MSG_TYPE_DRIVER: + /* Only 128 Bytes is available to print in driver */ + va_start(args, pucFmt); + vsnprintf(aucLogBuffer, sizeof(aucLogBuffer) - 1, pucFmt, + args); + va_end(args); + aucLogBuffer[DBG_LOG_BUF_SIZE - 1] = '\0'; + LOG_FUNC("%s\n", aucLogBuffer); + break; + case DEBUG_MSG_TYPE_MEM8: + firmwareHexDump("fw data:", DUMP_PREFIX_ADDRESS, + 16, 1, pucLogContent, u2MsgSize, true); + break; + default: + firmwareHexDump("fw data:", DUMP_PREFIX_ADDRESS, + 16, 4, pucLogContent, u2MsgSize, true); + break; + } + +#undef KBUILD_MODNAME +#undef LOG_FUNC +#define KBUILD_MODNAME OLD_KBUILD_MODNAME +#define LOG_FUNC OLD_LOG_FUNC +#undef OLD_KBUILD_MODNAME +#undef OLD_LOG_FUNC +} + +/* Begin: Functions used to breakdown packet jitter, for test case VoE 5.7 */ +static void wlanSetBE32(uint32_t u4Val, uint8_t *pucBuf) +{ + uint8_t *littleEn = (uint8_t *)&u4Val; + + pucBuf[0] = littleEn[3]; + pucBuf[1] = littleEn[2]; + pucBuf[2] = littleEn[1]; + pucBuf[3] = littleEn[0]; +} + +void wlanFillTimestamp(struct ADAPTER *prAdapter, void *pvPacket, + uint8_t ucPhase) +{ + struct sk_buff *skb = (struct sk_buff *)pvPacket; + uint8_t *pucEth = NULL; + uint32_t u4Length = 0; + uint8_t *pucUdp = NULL; + struct timeval tval; + + if (!prAdapter || !prAdapter->rDebugInfo.fgVoE5_7Test || !skb) + return; + pucEth = skb->data; + u4Length = skb->len; + if (u4Length < 200 || + ((pucEth[ETH_TYPE_LEN_OFFSET] << 8) | + (pucEth[ETH_TYPE_LEN_OFFSET + 1])) != ETH_P_IPV4) + return; + if (pucEth[ETH_HLEN+9] != IP_PRO_UDP) + return; + pucUdp = &pucEth[ETH_HLEN+28]; + if (kalStrnCmp(pucUdp, "1345678", 7)) + return; + do_gettimeofday(&tval); + switch (ucPhase) { + case PHASE_XMIT_RCV: /* xmit */ + pucUdp += 20; + break; + case PHASE_ENQ_QM: /* enq */ + pucUdp += 28; + break; + case PHASE_HIF_TX: /* tx */ + pucUdp += 36; + break; + } + wlanSetBE32(tval.tv_sec, pucUdp); + wlanSetBE32(tval.tv_usec, pucUdp+4); +} +/* End: Functions used to breakdown packet jitter, for test case VoE 5.7 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/common/dump.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/common/dump.c new file mode 100644 index 0000000000000..f642b7ff89821 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/common/dump.c @@ -0,0 +1,463 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: common/dump.c + */ + +/*! \file "dump.c" + * \brief Provide memory dump function for debugging. + * + * Provide memory dump function for debugging. + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to dump a segment of memory in bytes. + * + * \param[in] pucStartAddr Pointer to the starting address of the memory + * to be dumped. + * \param[in] u4Length Length of the memory to be dumped. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void dumpMemory8(IN uint8_t *pucStartAddr, + IN uint32_t u4Length) +{ + ASSERT(pucStartAddr); + + LOG_FUNC("DUMP8 ADDRESS: %p, Length: %d\n", pucStartAddr, + u4Length); + +#define case16 "(%p) %02x %02x %02x %02x %02x %02x %02x %02x" \ + " - %02x %02x %02x %02x %02x %02x %02x %02x\n" + +#define case07 "(%p) %02x %02x %02x %02x %02x %02x %02x\n" + +#define case08 "(%p) %02x %02x %02x %02x %02x %02x %02x %02x\n" + +#define case09 "(%p) %02x %02x %02x %02x %02x %02x %02x %02x" \ + " - %02x\n" + +#define case10 "(%p) %02x %02x %02x %02x %02x %02x %02x %02x" \ + " - %02x %02x\n" + +#define case11 "(%p) %02x %02x %02x %02x %02x %02x %02x %02x" \ + " - %02x %02x %02x\n" + +#define case12 "(%p) %02x %02x %02x %02x %02x %02x %02x %02x" \ + " - %02x %02x %02x %02x\n" + +#define case13 "(%p) %02x %02x %02x %02x %02x %02x %02x %02x" \ + " - %02x %02x %02x %02x %02x\n" + +#define case14 "(%p) %02x %02x %02x %02x %02x %02x %02x %02x" \ + " - %02x %02x %02x %02x %02x %02x\n" + +#define case15 "(%p) %02x %02x %02x %02x %02x %02x %02x %02x" \ + " - %02x %02x %02x %02x %02x %02x %02x\n" + + while (u4Length > 0) { + if (u4Length >= 16) { + LOG_FUNC + (case16, + pucStartAddr, pucStartAddr[0], pucStartAddr[1], + pucStartAddr[2], pucStartAddr[3], pucStartAddr[4], + pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8], pucStartAddr[9], pucStartAddr[10], + pucStartAddr[11], pucStartAddr[12], + pucStartAddr[13], pucStartAddr[14], + pucStartAddr[15]); + u4Length -= 16; + pucStartAddr += 16; + } else { + switch (u4Length) { + case 1: + LOG_FUNC("(%p) %02x\n", pucStartAddr, + pucStartAddr[0]); + break; + case 2: + LOG_FUNC("(%p) %02x %02x\n", pucStartAddr, + pucStartAddr[0], pucStartAddr[1]); + break; + case 3: + LOG_FUNC("(%p) %02x %02x %02x\n", + pucStartAddr, pucStartAddr[0], + pucStartAddr[1], pucStartAddr[2]); + break; + case 4: + LOG_FUNC("(%p) %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], + pucStartAddr[2], pucStartAddr[3]); + break; + case 5: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], + pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4]); + break; + case 6: + LOG_FUNC + ("(%p) %02x %02x %02x %02x %02x %02x\n", + pucStartAddr, pucStartAddr[0], + pucStartAddr[1], pucStartAddr[2], + pucStartAddr[3], pucStartAddr[4], + pucStartAddr[5]); + break; + case 7: + LOG_FUNC + (case07, + pucStartAddr, pucStartAddr[0], + pucStartAddr[1], pucStartAddr[2], + pucStartAddr[3], pucStartAddr[4], + pucStartAddr[5], pucStartAddr[6]); + break; + case 8: + LOG_FUNC + (case08, + pucStartAddr, pucStartAddr[0], + pucStartAddr[1], pucStartAddr[2], + pucStartAddr[3], pucStartAddr[4], + pucStartAddr[5], pucStartAddr[6], + pucStartAddr[7]); + break; + case 9: + LOG_FUNC + (case09, + pucStartAddr, pucStartAddr[0], + pucStartAddr[1], pucStartAddr[2], + pucStartAddr[3], pucStartAddr[4], + pucStartAddr[5], pucStartAddr[6], + pucStartAddr[7], pucStartAddr[8]); + break; + case 10: + LOG_FUNC + (case10, + 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 + (case11, + 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 + (case12, + 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 + (case13, + 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 + (case14, + 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: + default: + LOG_FUNC + (case15, + 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; + } + u4Length = 0; + } + } + + LOG_FUNC("\n"); +} /* end of dumpMemory8() */ + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to dump a segment of memory in double words. + * + * \param[in] pucStartAddr Pointer to the starting address of the memory + * to be dumped. + * \param[in] u4Length Length of the memory to be dumped. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void dumpMemory32(IN uint32_t *pu4StartAddr, + IN uint32_t u4Length) +{ + uint8_t *pucAddr; + + ASSERT(pu4StartAddr); + + LOG_FUNC("DUMP32 ADDRESS: %p, Length: %d\n", pu4StartAddr, + u4Length); + + if (IS_NOT_ALIGN_4((unsigned long)pu4StartAddr)) { + uint32_t u4ProtrudeLen = + sizeof(uint32_t) - ((unsigned long)pu4StartAddr % 4); + + u4ProtrudeLen = + ((u4Length < u4ProtrudeLen) ? u4Length : u4ProtrudeLen); + LOG_FUNC("pu4StartAddr is not at DW boundary.\n"); + pucAddr = (uint8_t *) &pu4StartAddr[0]; + + switch (u4ProtrudeLen) { + case 1: + LOG_FUNC("(%p) %02x------\n", pu4StartAddr, pucAddr[0]); + break; + case 2: + LOG_FUNC("(%p) %02x%02x----\n", pu4StartAddr, + pucAddr[1], pucAddr[0]); + break; + case 3: + LOG_FUNC("(%p) %02x%02x%02x--\n", pu4StartAddr, + pucAddr[2], pucAddr[1], pucAddr[0]); + break; + default: + break; + } + + u4Length -= u4ProtrudeLen; + pu4StartAddr = (uint32_t *) + ((unsigned long)pu4StartAddr + u4ProtrudeLen); + } + + while (u4Length > 0) { + if (u4Length >= 16) { + LOG_FUNC("(%p) %08x %08x %08x %08x\n", + pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], + pu4StartAddr[2], pu4StartAddr[3]); + pu4StartAddr += 4; + u4Length -= 16; + } else { + switch (u4Length) { + case 1: + pucAddr = (uint8_t *) &pu4StartAddr[0]; + LOG_FUNC("(%p) ------%02x\n", + pu4StartAddr, pucAddr[0]); + break; + case 2: + pucAddr = (uint8_t *) &pu4StartAddr[0]; + LOG_FUNC("(%p) ----%02x%02x\n", pu4StartAddr, + pucAddr[1], pucAddr[0]); + break; + case 3: + pucAddr = (uint8_t *) &pu4StartAddr[0]; + LOG_FUNC("(%p) --%02x%02x%02x\n", pu4StartAddr, + pucAddr[2], pucAddr[1], pucAddr[0]); + break; + case 4: + LOG_FUNC("(%p) %08x\n", pu4StartAddr, + pu4StartAddr[0]); + break; + case 5: + pucAddr = (uint8_t *) &pu4StartAddr[1]; + LOG_FUNC("(%p) %08x ------%02x\n", pu4StartAddr, + pu4StartAddr[0], pucAddr[0]); + break; + case 6: + pucAddr = (uint8_t *) &pu4StartAddr[1]; + LOG_FUNC("(%p) %08x ----%02x%02x\n", + pu4StartAddr, pu4StartAddr[0], + pucAddr[1], pucAddr[0]); + break; + case 7: + pucAddr = (uint8_t *) &pu4StartAddr[1]; + LOG_FUNC("(%p) %08x --%02x%02x%02x\n", + pu4StartAddr, pu4StartAddr[0], + pucAddr[2], pucAddr[1], pucAddr[0]); + break; + case 8: + LOG_FUNC("(%p) %08x %08x\n", pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1]); + break; + case 9: + pucAddr = (uint8_t *) &pu4StartAddr[2]; + LOG_FUNC("(%p) %08x %08x ------%02x\n", + pu4StartAddr, pu4StartAddr[0], + pu4StartAddr[1], pucAddr[0]); + break; + case 10: + pucAddr = (uint8_t *) &pu4StartAddr[2]; + LOG_FUNC("(%p) %08x %08x ----%02x%02x\n", + pu4StartAddr, pu4StartAddr[0], + pu4StartAddr[1], pucAddr[1], + pucAddr[0]); + break; + case 11: + pucAddr = (uint8_t *) &pu4StartAddr[2]; + LOG_FUNC("(%p) %08x %08x --%02x%02x%02x\n", + pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], + pucAddr[2], pucAddr[1], pucAddr[0]); + break; + case 12: + LOG_FUNC("(%p) %08x %08x %08x\n", + pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], + pu4StartAddr[2]); + break; + case 13: + pucAddr = (uint8_t *) &pu4StartAddr[3]; + LOG_FUNC("(%p) %08x %08x %08x ------%02x\n", + pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], + pu4StartAddr[2], pucAddr[0]); + break; + case 14: + pucAddr = (uint8_t *) &pu4StartAddr[3]; + LOG_FUNC("(%p) %08x %08x %08x ----%02x%02x\n", + pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], + pu4StartAddr[2], + pucAddr[1], pucAddr[0]); + break; + case 15: + default: + pucAddr = (uint8_t *) &pu4StartAddr[3]; + LOG_FUNC("(%p) %08x %08x %08x --%02x%02x%02x\n", + pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], + pu4StartAddr[2], + pucAddr[2], pucAddr[1], pucAddr[0]); + break; + } + u4Length = 0; + } + } +} /* end of dumpMemory32() */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/common/wlan_bow.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/common/wlan_bow.c new file mode 100644 index 0000000000000..2fa9374e76fec --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/common/wlan_bow.c @@ -0,0 +1,3218 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + +/****************************************************************************** +* C O M P I L E R F L A G S +******************************************************************************* +*/ + +/****************************************************************************** +* E X T E R N A L R E F E R E N C E S +******************************************************************************* +*/ +#include "precomp.h" + +#if CFG_ENABLE_BT_OVER_WIFI + +/****************************************************************************** +* C O N S T A N T S +******************************************************************************* +*/ + +/****************************************************************************** +* D A T A T Y P E S +******************************************************************************* +*/ + +/****************************************************************************** +* P U B L I C D A T A +******************************************************************************* +*/ + +#if 1 /* Marked for MT6630 */ +static uint32_t g_u4LinkCount; +static uint32_t g_u4Beaconing; +static struct BOW_TABLE arBowTable[CFG_BOW_PHYSICAL_LINK_NUM]; +#endif + +/****************************************************************************** +* P R I V A T E D A T A +******************************************************************************* +*/ + +const struct BOW_CMD 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 +******************************************************************************* +*/ + +#if 1 /* Marked for MT6630 */ +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSendSetQueryBowCmd(IN struct ADAPTER *prAdapter, + IN uint8_t ucCID, + IN uint8_t ucBssIdx, + IN u_int8_t fgSetQuery, + IN u_int8_t fgNeedResp, + IN PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + IN PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + IN uint32_t u4SetQueryInfoLen, IN uint8_t *pucInfoBuffer, IN uint8_t ucSeqNumber) +{ + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + struct WIFI_CMD *prWifiCmd; + uint8_t 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->u2InfoBufLen = (uint16_t) (CMD_HDR_SIZE + u4SetQueryInfoLen); + prCmdInfo->pfCmdDoneHandler = pfCmdDoneHandler; + prCmdInfo->pfCmdTimeoutHandler = pfCmdTimeoutHandler; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = ucCID; + prCmdInfo->fgSetQuery = fgSetQuery; + prCmdInfo->fgNeedResp = fgNeedResp; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u4SetQueryInfoLen; + prCmdInfo->pvInformationBuffer = NULL; + prCmdInfo->u4InformationBufferLength = 0; + prCmdInfo->u4PrivateData = (uint32_t) ucSeqNumber; + + /* Setup WIFI_CMD_T (no payload) */ + prWifiCmd = (struct WIFI_CMD *) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = 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, (struct QUE_ENTRY *) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + return WLAN_STATUS_PENDING; +} + +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +uint32_t wlanbowHandleCommand(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd) +{ +#if 1 /* Marked for MT6630 */ + uint32_t retval = WLAN_STATUS_FAILURE; + uint16_t i; + + ASSERT(prAdapter); + + for (i = 0; i < sizeof(arBowCmdTable) / sizeof(struct BOW_CMD); i++) { + if ((arBowCmdTable[i].uCmdID == prCmd->rHeader.ucCommandId) && arBowCmdTable[i].pfCmdHandle) { + retval = arBowCmdTable[i].pfCmdHandle(prAdapter, prCmd); + break; + } + } + + return retval; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +uint32_t bowCmdGetMacStatus(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd) +{ +#if 1 /* Marked for MT6630 */ + struct BT_OVER_WIFI_EVENT *prEvent; + struct BOW_MAC_STATUS *prMacStatus; + uint8_t idx = 0; + uint8_t ucPrimaryChannel; + enum ENUM_BAND eBand; + enum ENUM_CHNL_EXT eBssSCO; + uint8_t ucNumOfChannel = 0; /* MAX_BOW_NUMBER_OF_CHANNEL; */ + + struct RF_CHANNEL_INFO 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 = (struct BT_OVER_WIFI_EVENT *) kalMemAlloc((sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct BOW_MAC_STATUS)), VIR_MEM_TYPE); + + prEvent->rHeader.ucEventId = BOW_EVENT_ID_MAC_STATUS; + prEvent->rHeader.ucSeqNumber = prCmd->rHeader.ucSeqNumber; + prEvent->rHeader.u2PayloadLength = sizeof(struct BOW_MAC_STATUS); + + /* fill event body */ + prMacStatus = (struct BOW_MAC_STATUS *) (prEvent->aucPayload); + kalMemZero(prMacStatus, sizeof(struct 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)) { + DBGLOG(BOW, EVENT, "bowCmdGetMacStatus, Get preferred channel.\n"); + + prMacStatus->ucNumOfChannel = 1; + prMacStatus->arChannelList[0].ucChannelBand = eBand; + prMacStatus->arChannelList[0].ucChannelNum = ucPrimaryChannel; + } else { + DBGLOG(BOW, EVENT, + "bowCmdGetMacStatus, Get channel list. Current number of channel, %d.\n", ucNumOfChannel); + + rlmDomainGetChnlList(prAdapter, BAND_2G4, FALSE, 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, FALSE, + 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; + + } + } + + 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, %x, %x.\n", + prMacStatus->ucNumOfChannel, prMacStatus->arChannelList[0].ucChannelBand); + DBGLOG(BOW, EVENT, + "prMacStatus->arChannelList, %x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x.\n", + prMacStatus->arChannelList[0].ucChannelNum, + prMacStatus->arChannelList[1].ucChannelNum, + prMacStatus->arChannelList[2].ucChannelNum, + prMacStatus->arChannelList[3].ucChannelNum, + prMacStatus->arChannelList[4].ucChannelNum, + prMacStatus->arChannelList[5].ucChannelNum, + prMacStatus->arChannelList[6].ucChannelNum, + prMacStatus->arChannelList[7].ucChannelNum, + prMacStatus->arChannelList[8].ucChannelNum, + prMacStatus->arChannelList[9].ucChannelNum, + prMacStatus->arChannelList[10].ucChannelNum, + prMacStatus->arChannelList[11].ucChannelNum, + prMacStatus->arChannelList[12].ucChannelNum, + prMacStatus->arChannelList[13].ucChannelNum, + prMacStatus->arChannelList[14].ucChannelNum, + prMacStatus->arChannelList[15].ucChannelNum, + prMacStatus->arChannelList[16].ucChannelNum, prMacStatus->arChannelList[17].ucChannelNum); + + DBGLOG(BOW, 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]); + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct BOW_MAC_STATUS))); + + return WLAN_STATUS_SUCCESS; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +uint32_t bowCmdSetupConnection(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd) +{ +#if 1 /* Marked for MT6630 */ + struct BOW_SETUP_CONNECTION *prBowSetupConnection; + struct CMD_BT_OVER_WIFI rCmdBtOverWifi; + struct BOW_FSM_INFO *prBowFsmInfo; + struct BOW_TABLE rBowTable; + + uint8_t ucBowTableIdx = 0; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowSetupConnection = (struct BOW_SETUP_CONNECTION *) &(prCmd->aucPayload[0]); + + /* parameter size check */ + if (prCmd->rHeader.u2PayloadLength != sizeof(struct 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; + + 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); + + /* 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.eState = BOW_DEVICE_STATE_NUM; /* Just initiate */ + 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); + + DBGLOG(BOW, EVENT, "bowStarting, g_u4LinkCount, %x.\n", g_u4LinkCount); + + if (g_u4LinkCount == 1) { + DBGLOG(BOW, EVENT, "bowStarting, cnmTimerInitTimer.\n"); + DBGLOG(BOW, EVENT, "prBowFsmInfo->u2BeaconInterval, %d.\n", prBowFsmInfo->u2BeaconInterval); + + cnmTimerInitTimer(prAdapter, + &prBowFsmInfo->rStartingBeaconTimer, + (PFN_MGMT_TIMEOUT_FUNC) bowSendBeacon, (unsigned long) NULL); + + cnmTimerInitTimer(prAdapter, + &prBowFsmInfo->rChGrantedTimer, + (PFN_MGMT_TIMEOUT_FUNC) bowChGrantedTimeout, (unsigned long) NULL); + + /* Reset Global Variable */ + g_u4Beaconing = 0; + + DBGLOG(BOW, EVENT, "bowCmdSetupConnection, g_u4LinkCount, %x.\n", g_u4LinkCount); + DBGLOG(BOW, EVENT, "kalInitBowDevice, bow0\n"); + +#if CFG_BOW_SEPARATE_DATA_PATH + kalInitBowDevice(prAdapter->prGlueInfo, BOWDEVNAME); +#endif + + /*Active BoW Network */ + SET_NET_ACTIVE(prAdapter, prBowFsmInfo->ucBssIndex); + SET_NET_PWR_STATE_ACTIVE(prAdapter, prBowFsmInfo->ucBssIndex); + nicActivateNetwork(prAdapter, prBowFsmInfo->ucBssIndex); + + } + + 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; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +uint32_t bowCmdDestroyConnection(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd) +{ +#if 1 /* Marked for MT6630 */ + struct BOW_DESTROY_CONNECTION *prBowDestroyConnection; + struct CMD_BT_OVER_WIFI rCmdBtOverWifi; + struct BOW_FSM_INFO *prBowFsmInfo; + + uint8_t ucIdx; + + 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(struct 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 = (struct BOW_DESTROY_CONNECTION *) &(prCmd->aucPayload[0]); + + if (!bowCheckBowTableIfVaild(prAdapter, prBowDestroyConnection->aucPeerAddress)) { + DBGLOG(BOW, EVENT, "bowCmdDestroyConnection, bowCheckIfVaild, not accepted.\n"); + return WLAN_STATUS_NOT_ACCEPTED; + } + + 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]); + + /* fill CMD_BT_OVER_WIFI */ + rCmdBtOverWifi.ucAction = 2; + COPY_MAC_ADDR(rCmdBtOverWifi.rPeerAddr, prBowDestroyConnection->aucPeerAddress); + COPY_MAC_ADDR(prBowFsmInfo->aucPeerAddress, prBowDestroyConnection->aucPeerAddress); + + 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]); + + 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]); + } + + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_SUCCESS); + + return wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + prBowFsmInfo->ucBssIndex, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, + sizeof(struct CMD_BT_OVER_WIFI), + (uint8_t *)&rCmdBtOverWifi, prCmd->rHeader.ucSeqNumber); + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +uint32_t bowCmdSetPTK(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd) +{ +#if 1 /* Marked for MT6630 */ + struct BOW_SET_PTK *prBowSetPTK; + struct CMD_802_11_KEY rCmdKey; + struct BOW_FSM_INFO *prBowFsmInfo; + struct STA_RECORD *prStaRec = NULL; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + /* parameter size check */ + if (prCmd->rHeader.u2PayloadLength != sizeof(struct BOW_SET_PTK)) + return WLAN_STATUS_INVALID_LENGTH; + + prBowSetPTK = (struct BOW_SET_PTK *) &(prCmd->aucPayload[0]); + + 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)); + + 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.ucBssIdx = prBowFsmInfo->ucBssIndex; /* BT Over Wi-Fi */ + rCmdKey.ucAlgorithmId = CIPHER_SUITE_CCMP; /* AES */ + rCmdKey.ucKeyId = 0; + rCmdKey.ucKeyLen = 16; /* AES = 128bit */ + kalMemCopy(rCmdKey.aucKeyMaterial, prBowSetPTK->aucTemporalKey, 16); + + /* BT Over Wi-Fi */ + prStaRec = cnmGetStaRecByAddress(prAdapter, prBowFsmInfo->ucBssIndex, prBowSetPTK->aucPeerAddress); + rCmdKey.ucWlanIndex = prStaRec->ucWlanIndex; + + 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]); + + return wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_ADD_REMOVE_KEY, + prBowFsmInfo->ucBssIndex, + TRUE, + FALSE, + wlanbowCmdEventSetCommon, + wlanbowCmdTimeoutHandler, + sizeof(struct CMD_802_11_KEY), (uint8_t *)&rCmdKey, prCmd->rHeader.ucSeqNumber); +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +uint32_t bowCmdReadRSSI(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd) +{ +#if 1 /* Marked for MT6630 */ + struct BOW_READ_RSSI *prBowReadRSSI; + struct BOW_FSM_INFO *prBowFsmInfo; + + ASSERT(prAdapter); + + if (prAdapter->fgIsEnableLpdvt) + return WLAN_STATUS_NOT_SUPPORTED; + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + /* parameter size check */ + if (prCmd->rHeader.u2PayloadLength != sizeof(struct BOW_READ_RSSI)) + return WLAN_STATUS_INVALID_LENGTH; + + prBowReadRSSI = (struct BOW_READ_RSSI *) &(prCmd->aucPayload[0]); + + return wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + prBowFsmInfo->ucBssIndex, + FALSE, + TRUE, + wlanbowCmdEventReadRssi, + wlanbowCmdTimeoutHandler, 0, NULL, prCmd->rHeader.ucSeqNumber); + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +uint32_t bowCmdReadLinkQuality(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd) +{ +#if 1 /* Marked for MT6630 */ + struct BOW_READ_LINK_QUALITY *prBowReadLinkQuality; + struct BOW_FSM_INFO *prBowFsmInfo; + + ASSERT(prAdapter); + + if (prAdapter->fgIsEnableLpdvt) + return WLAN_STATUS_NOT_SUPPORTED; + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + /* parameter size check */ + if (prCmd->rHeader.u2PayloadLength != sizeof(struct BOW_READ_LINK_QUALITY *)) + return WLAN_STATUS_INVALID_LENGTH; + + prBowReadLinkQuality = (struct BOW_READ_LINK_QUALITY *) &(prCmd->aucPayload[0]); + + return wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + prBowFsmInfo->ucBssIndex, + FALSE, + TRUE, + wlanbowCmdEventReadLinkQuality, + wlanbowCmdTimeoutHandler, 0, NULL, prCmd->rHeader.ucSeqNumber); + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +uint32_t bowCmdShortRangeMode(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd) +{ +#if 1 /* Marked for MT6630 */ + struct BOW_SHORT_RANGE_MODE *prBowShortRangeMode; + struct CMD_TX_PWR rTxPwrParam; + + ASSERT(prAdapter); + + DBGLOG(BOW, EVENT, "bowCmdShortRangeMode.\n"); + + prBowShortRangeMode = (struct BOW_SHORT_RANGE_MODE *) &(prCmd->aucPayload[0]); + + /* parameter size check */ + if (prCmd->rHeader.u2PayloadLength != sizeof(struct 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; + } + + 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]); + + 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) { + DBGLOG(BOW, EVENT, "bowCmdShortRangeMode, %x.\n", WLAN_STATUS_SUCCESS); + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_SUCCESS); + return WLAN_STATUS_SUCCESS; + } + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_FAILURE); + return WLAN_STATUS_FAILURE; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +uint32_t bowCmdGetChannelList(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd) +{ + ASSERT(prAdapter); + + /* not supported yet */ + return WLAN_STATUS_FAILURE; +} + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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 struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd, IN uint8_t ucEventBuf) +{ + struct BT_OVER_WIFI_EVENT *prEvent; + struct BOW_COMMAND_STATUS *prBowCmdStatus; + + ASSERT(prAdapter); + + /* fill event header */ + prEvent = (struct BT_OVER_WIFI_EVENT *) kalMemAlloc((sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct BOW_COMMAND_STATUS)), VIR_MEM_TYPE); + prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; + prEvent->rHeader.ucSeqNumber = prCmd->rHeader.ucSeqNumber; + prEvent->rHeader.u2PayloadLength = sizeof(struct BOW_COMMAND_STATUS); + + /* fill event body */ + prBowCmdStatus = (struct BOW_COMMAND_STATUS *) (prEvent->aucPayload); + kalMemZero(prBowCmdStatus, sizeof(struct BOW_COMMAND_STATUS)); + + prBowCmdStatus->ucStatus = ucEventBuf; + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct 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 struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct BT_OVER_WIFI_EVENT *prEvent; + struct BOW_COMMAND_STATUS *prBowCmdStatus; + + ASSERT(prAdapter); + + /* fill event header */ + prEvent = (struct BT_OVER_WIFI_EVENT *) kalMemAlloc((sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct BOW_COMMAND_STATUS)), VIR_MEM_TYPE); + prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; + prEvent->rHeader.ucSeqNumber = (uint8_t) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(struct BOW_COMMAND_STATUS); + + /* fill event body */ + prBowCmdStatus = (struct BOW_COMMAND_STATUS *) (prEvent->aucPayload); + kalMemZero(prBowCmdStatus, sizeof(struct BOW_COMMAND_STATUS)); + + prBowCmdStatus->ucStatus = BOWCMD_STATUS_SUCCESS; + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct 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 struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct BT_OVER_WIFI_EVENT *prEvent; + struct BOW_LINK_CONNECTED *prBowLinkConnected; + struct BOW_FSM_INFO *prBowFsmInfo; + struct BSS_INFO *prBssInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + /* fill event header */ + prEvent = (struct BT_OVER_WIFI_EVENT *) kalMemAlloc((sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct BOW_LINK_CONNECTED)), VIR_MEM_TYPE); + prEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_CONNECTED; + prEvent->rHeader.ucSeqNumber = (uint8_t) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(struct BOW_LINK_CONNECTED); + + /* fill event body */ + prBowLinkConnected = (struct BOW_LINK_CONNECTED *) (prEvent->aucPayload); + kalMemZero(prBowLinkConnected, sizeof(struct BOW_LINK_CONNECTED)); + prBowLinkConnected->rChannel.ucChannelNum = prBssInfo->ucPrimaryChannel; + prBowLinkConnected->rChannel.ucChannelBand = prBssInfo->eBand; + COPY_MAC_ADDR(prBowLinkConnected->aucPeerAddress, prBowFsmInfo->aucPeerAddress); + + 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); + + /*Indicate Event to PAL */ + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct 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 struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct BT_OVER_WIFI_EVENT *prEvent; + struct BOW_LINK_DISCONNECTED *prBowLinkDisconnected; + struct BOW_FSM_INFO *prBowFsmInfo; + struct BOW_TABLE rBowTable; + uint8_t ucBowTableIdx; + enum ENUM_BOW_DEVICE_STATE eFsmState; + u_int8_t 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 = (struct BT_OVER_WIFI_EVENT *) kalMemAlloc((sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct BOW_LINK_DISCONNECTED)), VIR_MEM_TYPE); + prEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_DISCONNECTED; + if ((prCmdInfo->u4PrivateData)) + prEvent->rHeader.ucSeqNumber = (uint8_t) prCmdInfo->u4PrivateData; + else + prEvent->rHeader.ucSeqNumber = 0; + + prEvent->rHeader.u2PayloadLength = sizeof(struct BOW_LINK_DISCONNECTED); + + /* fill event body */ + prBowLinkDisconnected = (struct BOW_LINK_DISCONNECTED *) (prEvent->aucPayload); + kalMemZero(prBowLinkDisconnected, sizeof(struct BOW_LINK_DISCONNECTED)); + prBowLinkDisconnected->ucReason = 0x0; + COPY_MAC_ADDR(prBowLinkDisconnected->aucPeerAddress, prBowFsmInfo->aucPeerAddress); + + 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); + + /*Indicate BoW event to PAL */ +#if 0 + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct BOW_LINK_DISCONNECTED))); +#endif + + /* set to disconnected status */ + prBowFsmInfo->prTargetStaRec = + cnmGetStaRecByAddress(prAdapter, prBowFsmInfo->ucBssIndex, 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; + DBGLOG(BOW, EVENT, + "wlanbowCmdEventLinkDisconnected, bowGetBowTableState, %x.\n", + bowGetBowTableState(prAdapter, prBowLinkDisconnected->aucPeerAddress)); + authSendDeauthFrame(prAdapter, NULL, prBowFsmInfo->prTargetStaRec, + (struct SW_RFB *) 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; + rBowTable.ucAcquireID = 0; /* Just initiate */ + bowSetBowTableContent(prAdapter, ucBowTableIdx, &rBowTable); + + /*Indicate BoW event to PAL */ + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct 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 struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct BT_OVER_WIFI_EVENT *prEvent; + struct BOW_COMMAND_STATUS *prBowCmdStatus; + struct WIFI_CMD *prWifiCmd; + struct CMD_BT_OVER_WIFI *prCmdBtOverWifi; + struct BOW_FSM_INFO *prBowFsmInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + /* restore original command for rPeerAddr */ + prWifiCmd = (struct WIFI_CMD *) (prCmdInfo->pucInfoBuffer); + prCmdBtOverWifi = (struct CMD_BT_OVER_WIFI *) (prWifiCmd->aucBuffer); + + /* fill event header */ + prEvent = (struct BT_OVER_WIFI_EVENT *) kalMemAlloc((sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct BOW_COMMAND_STATUS)), VIR_MEM_TYPE); + prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; + prEvent->rHeader.ucSeqNumber = (uint8_t) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(struct BOW_COMMAND_STATUS); + + /* fill event body */ + prBowCmdStatus = (struct BOW_COMMAND_STATUS *) (prEvent->aucPayload); + kalMemZero(prBowCmdStatus, sizeof(struct BOW_COMMAND_STATUS)); + prBowCmdStatus->ucStatus = BOWCMD_STATUS_SUCCESS; + + /*Indicate BoW event to PAL */ + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct 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 struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct EVENT_LINK_QUALITY *prLinkQuality; + struct BT_OVER_WIFI_EVENT *prEvent; + struct BOW_LINK_QUALITY *prBowLinkQuality; + + ASSERT(prAdapter); + + prLinkQuality = (struct EVENT_LINK_QUALITY *) pucEventBuf; + + /* fill event header */ + prEvent = (struct BT_OVER_WIFI_EVENT *) kalMemAlloc((sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct BOW_LINK_QUALITY)), VIR_MEM_TYPE); + prEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_QUALITY; + prEvent->rHeader.ucSeqNumber = (uint8_t) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(struct BOW_LINK_QUALITY); + + /* fill event body */ + prBowLinkQuality = (struct BOW_LINK_QUALITY *) (prEvent->aucPayload); + kalMemZero(prBowLinkQuality, sizeof(struct BOW_LINK_QUALITY)); + prBowLinkQuality->ucLinkQuality = (uint8_t) prLinkQuality->cLinkQuality; + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct 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 struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct EVENT_LINK_QUALITY *prLinkQuality; + struct BT_OVER_WIFI_EVENT *prEvent; + struct BOW_RSSI *prBowRssi; + + ASSERT(prAdapter); + + prLinkQuality = (struct EVENT_LINK_QUALITY *) pucEventBuf; + + /* fill event header */ + prEvent = (struct BT_OVER_WIFI_EVENT *) kalMemAlloc((sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct BOW_LINK_QUALITY)), VIR_MEM_TYPE); + prEvent->rHeader.ucEventId = BOW_EVENT_ID_RSSI; + prEvent->rHeader.ucSeqNumber = (uint8_t) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(struct BOW_RSSI); + + /* fill event body */ + prBowRssi = (struct BOW_RSSI *) (prEvent->aucPayload); + kalMemZero(prBowRssi, sizeof(struct BOW_RSSI)); + prBowRssi->cRssi = (int8_t) prLinkQuality->cRssi; + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct 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 struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo) +{ + struct BT_OVER_WIFI_EVENT *prEvent; + struct BOW_COMMAND_STATUS *prBowCmdStatus; + + ASSERT(prAdapter); + + /* fill event header */ + prEvent = (struct BT_OVER_WIFI_EVENT *) kalMemAlloc((sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct BOW_COMMAND_STATUS)), VIR_MEM_TYPE); + prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; + prEvent->rHeader.ucSeqNumber = (uint8_t) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(struct BOW_COMMAND_STATUS); + + /* fill event body */ + prBowCmdStatus = (struct BOW_COMMAND_STATUS *) (prEvent->aucPayload); + kalMemZero(prBowCmdStatus, sizeof(struct BOW_COMMAND_STATUS)); + + prBowCmdStatus->ucStatus = BOWCMD_STATUS_TIMEOUT; /* timeout */ + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(struct BT_OVER_WIFI_EVENT) + sizeof(struct BOW_COMMAND_STATUS))); + +} + +/* Bruce, 20140224 */ +uint8_t bowInit(IN struct ADAPTER *prAdapter) +{ + struct BSS_INFO *prBowBssInfo; + struct BOW_FSM_INFO *prBowFsmInfo; + + ASSERT(prAdapter); + + prBowBssInfo = cnmGetBssInfoAndInit(prAdapter, NETWORK_TYPE_BOW, TRUE); + + /*Initiate BSS_INFO_T - common part -move from bowstarting */ + BSS_INFO_INIT(prAdapter, prBowBssInfo); + + prBowBssInfo->eCurrentOPMode = OP_MODE_BOW; + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowFsmInfo->ucBssIndex = prBowBssInfo->ucBssIndex; + + /* Setup Own MAC & BSSID */ + COPY_MAC_ADDR(prBowBssInfo->aucOwnMacAddr, prAdapter->rWifiVar.aucDeviceAddress); + COPY_MAC_ADDR(prBowBssInfo->aucBSSID, prAdapter->rWifiVar.aucDeviceAddress); + + return prBowBssInfo->ucBssIndex; +} + +/* Bruce, 20140224 */ +void bowUninit(IN struct ADAPTER *prAdapter) +{ + struct BSS_INFO *prBowBssInfo; + struct BOW_FSM_INFO *prBowFsmInfo; + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + cnmFreeBssInfo(prAdapter, prBowBssInfo); +} + +void bowStopping(IN struct ADAPTER *prAdapter) +{ + struct BOW_FSM_INFO *prBowFsmInfo; + struct BSS_INFO *prBowBssInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + 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]); + DBGLOG(BOW, EVENT, "BoW Stoping,[%d,%d]\n", g_u4LinkCount, g_u4Beaconing); + + if (g_u4LinkCount == 0) { + /*Stop beaconing */ + GLUE_DEC_REF_CNT(g_u4Beaconing); + + /*Deactive BoW network */ + /* prBowBssInfo->fgIsNetActive = FALSE; */ + /* prBowBssInfo->fgIsBeaconActivated = FALSE; */ + nicPmIndicateBssAbort(prAdapter, prBowBssInfo->ucBssIndex); + bowChangeMediaState(prBowBssInfo, PARAM_MEDIA_STATE_DISCONNECTED); + nicUpdateBss(prAdapter, prBowBssInfo->ucBssIndex); + /*temp solution for FW hal_pwr_mgt.c#3037 ASSERT */ + nicDeactivateNetwork(prAdapter, prBowBssInfo->ucBssIndex); + SET_NET_PWR_STATE_IDLE(prAdapter, prBowBssInfo->ucBssIndex); + UNSET_NET_ACTIVE(prAdapter, prBowBssInfo->ucBssIndex); + + } + +} + +void bowStarting(IN struct ADAPTER *prAdapter) +{ + struct BOW_FSM_INFO *prBowFsmInfo; + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if (g_u4LinkCount == 1) { + DBGLOG(BOW, EVENT, "BoW Starting.\n"); + DBGLOG(BOW, EVENT, "BoW channel granted.\n"); + + /* 3 <1> Update BSS_INFO_T per Network Basis */ + /* 4 <1.1> Setup Operation Mode */ + + /* Bruce, 20140224 */ + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + /* 4 <1.2> Setup SSID */ + prBssInfo->ucSSIDLen = BOW_SSID_LEN; + bowAssignSsid(prBssInfo->aucSSID, prBssInfo->aucOwnMacAddr); + + 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]); + + /* 4 <1.3> Clear current AP's STA_RECORD_T and current AID */ + prBssInfo->prStaRecOfAP = (struct STA_RECORD *) NULL; + prBssInfo->u2AssocId = 0; + + /* 4 <1.4> Setup Channel, Band and Phy Attributes */ + prBssInfo->ucPrimaryChannel = prBowFsmInfo->ucPrimaryChannel; + if (prBowFsmInfo->eBand == BAND_2G4) + prBssInfo->eBand = BAND_2G4; + else + prBssInfo->eBand = BAND_5G; + +#if CFG_BOW_SUPPORT_11N + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11BGN; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; + + prBssInfo->ucNonHTBasicPhyType = (uint8_t) + rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].ePhyTypeIndex; + prBssInfo->u2BSSBasicRateSet = rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].u2BSSBasicRateSet; + + prBssInfo->u2OperationalRateSet = + rNonHTPhyAttributes[prBssInfo->ucNonHTBasicPhyType].u2SupportedRateSet; + + rateGetDataRatesFromRateSet(prBssInfo->u2OperationalRateSet, + prBssInfo->u2BSSBasicRateSet, + prBssInfo->aucAllSupportedRates, &prBssInfo->ucAllSupportedRatesLen); + +#else + if (prBssInfo->eBand == BAND_2G4) { + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11BG; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; + + /* RATE_SET_ERP; */ + prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_ERP; + prBssInfo->u2OperationalRateSet = RATE_SET_ERP; + prBssInfo->ucNonHTBasicPhyType = PHY_TYPE_ERP_INDEX; + } else { + /* Depend on eBand */ + /* prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11BG; */ + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + /* prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; */ + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11A; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_11A; + + /* RATE_SET_ERP; */ + /* prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_ERP; */ + /* prBssInfo->u2OperationalRateSet = RATE_SET_ERP; */ + + /* RATE_SET_ERP; */ + prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_OFDM; + prBssInfo->u2OperationalRateSet = RATE_SET_OFDM; + prBssInfo->ucNonHTBasicPhyType = PHY_TYPE_OFDM_INDEX; + } + +#endif + prBssInfo->fgErpProtectMode = FALSE; + + /* 4 <1.5> Setup MIB for current BSS */ + prBssInfo->u2BeaconInterval = prBowFsmInfo->u2BeaconInterval; + prBssInfo->ucDTIMPeriod = DOT11_DTIM_PERIOD_DEFAULT; + prBssInfo->u2ATIMWindow = 0; + prBssInfo->ucBeaconTimeoutCount = 0; + if (prBowFsmInfo->fgSupportQoS) { + prAdapter->rWifiVar.ucQoS = TRUE; + prBssInfo->fgIsQBSS = TRUE; + } + + /* 3 <2> Update BSS_INFO_T common part */ +#if CFG_SUPPORT_AAA + bssInitForAP(prAdapter, prBssInfo, TRUE); + nicQmUpdateWmmParms(prAdapter, prBssInfo->ucBssIndex); +#endif /* CFG_SUPPORT_AAA */ + prBssInfo->fgIsNetActive = TRUE; + prBssInfo->fgIsBeaconActivated = TRUE; + + /* 3 <3> Set MAC HW */ + + 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]); + + /* 4 <3.1> use command packets to inform firmware */ + rlmBssInitForAPandIbss(prAdapter, prBssInfo); + nicUpdateBss(prAdapter, prBssInfo->ucBssIndex); + + /* 4 <3.2> Update AdHoc PM parameter */ + nicPmIndicateBssCreated(prAdapter, prBssInfo->ucBssIndex); + + /* 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 + { + uint32_t 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); + + DBGLOG(BOW, EVENT, "BoW Starting,[%d,%d]\n", g_u4LinkCount, g_u4Beaconing); + DBGLOG(BOW, EVENT, "bowStarting, g_u4LinkCount, %x.\n", g_u4LinkCount); + + /*Start beaconing */ + if (g_u4Beaconing < 1) { + GLUE_INC_REF_CNT(g_u4Beaconing); + bssSendBeaconProbeResponse(prAdapter, prBssInfo->ucBssIndex, NULL, 0); + cnmTimerStartTimer(prAdapter, &prBowFsmInfo->rStartingBeaconTimer, prBowFsmInfo->u2BeaconInterval); + } +#if 0 + /*Responder: Start to scan Initiator */ + if (prBowFsmInfo->ucRole == BOW_RESPONDER) { + DBGLOG(BOW, EVENT, "bowStarting responder, start scan result searching.\n"); + cnmTimerStopTimer(prAdapter, &prBowFsmInfo->rChGrantedTimer); + bowReleaseCh(prAdapter); + bowResponderScan(prAdapter); + } + /*Initiator: Request channel, wait for responder */ + /* else + * bowRequestCh(prAdapter); + */ +#endif + + /* wlanBindBssIdxToNetInterface(prAdapter->prGlueInfo, NET_DEV_BOW_IDX, prBssInfo->ucBssIndex); */ + +} + +void bowAssignSsid(IN uint8_t *pucSsid, IN uint8_t *puOwnMacAddr) +{ + uint8_t i; + uint8_t 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; + } + +} + +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t bowValidateProbeReq(IN struct ADAPTER *prAdapter, IN struct SW_RFB *prSwRfb, OUT uint32_t *pu4ControlFlags) +{ +#if 1 /* Marked for MT6630 */ + + struct WLAN_MAC_MGMT_HEADER *prMgtHdr; + struct BOW_FSM_INFO *prBowFsmInfo; + struct BSS_INFO *prBssInfo; + struct IE_SSID *prIeSsid = (struct IE_SSID *) NULL; + uint8_t *pucIE; + uint16_t u2IELength; + uint16_t u2Offset = 0; + u_int8_t fgReplyProbeResp = FALSE; + + ASSERT(prSwRfb); + ASSERT(pu4ControlFlags); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + +#if 0 + DBGLOG(BOW, EVENT, "bowValidateProbeReq.\n"); +#endif + + /* 4 <1> Parse Probe Req IE and Get IE ptr (SSID, Supported Rate IE, ...) */ + prMgtHdr = (struct WLAN_MAC_MGMT_HEADER *) prSwRfb->pvHeader; + + u2IELength = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen; + pucIE = (uint8_t *) (((unsigned long) prSwRfb->pvHeader) + prSwRfb->u2HeaderLen); + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (IE_ID(pucIE) == ELEM_ID_SSID) { + if ((!prIeSsid) && (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) + prIeSsid = (struct IE_SSID *) pucIE; + break; + } + } /* end of IE_FOR_EACH */ + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (IE_ID(pucIE) == ELEM_ID_SSID) { + if ((!prIeSsid) && (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) + prIeSsid = (struct IE_SSID *) 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; +#else + return 0; +#endif +} + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Media Disconnect" to HOST +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void bowSendBeacon(IN struct ADAPTER *prAdapter, IN unsigned long ulParamPtr) +{ + struct BOW_FSM_INFO *prBowFsmInfo; + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if ((g_u4Beaconing != 0) && (g_u4LinkCount > 0) + && (g_u4LinkCount < CFG_BOW_PHYSICAL_LINK_NUM)) { + /* Send beacon */ + bssSendBeaconProbeResponse(prAdapter, prBowFsmInfo->ucBssIndex, NULL, 0); + cnmTimerStartTimer(prAdapter, &prBowFsmInfo->rStartingBeaconTimer, prBowFsmInfo->u2BeaconInterval); + } else { + DBGLOG(BOW, EVENT, "BoW Send Beacon,[%d,%d]\n", g_u4LinkCount, g_u4Beaconing); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Media Disconnect" to HOST +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void bowResponderScan(IN struct ADAPTER *prAdapter) +{ + struct BOW_FSM_INFO *prBowFsmInfo; + struct MSG_SCN_SCAN_REQ *prScanReqMsg; + struct BSS_INFO *prBssInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + DBGLOG(BOW, EVENT, "bowResponderScan.\n"); + DBGLOG(BOW, EVENT, "BOW SCAN [REQ:%d]\n", prBowFsmInfo->ucSeqNumOfScanReq + 1); + + prScanReqMsg = (struct MSG_SCN_SCAN_REQ *) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(struct 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->ucBssIndex = prBowFsmInfo->ucBssIndex; + 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, (struct MSG_HDR *) 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 */ + +} + +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +void bowResponderScanDone(IN struct ADAPTER *prAdapter, IN struct MSG_HDR *prMsgHdr) +{ +#if 1 /* Marked for MT6630 */ + struct MSG_SCN_SCAN_DONE *prScanDoneMsg; + struct BOW_FSM_INFO *prBowFsmInfo; + struct BSS_DESC *prBssDesc; + uint8_t ucSeqNumOfCompMsg; + struct CONNECTION_SETTINGS *prConnSettings; + enum ENUM_BOW_DEVICE_STATE eFsmState; + enum ENUM_SCAN_STATUS eScanStatus; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prScanDoneMsg = (struct MSG_SCN_SCAN_DONE *) prMsgHdr; + eFsmState = bowGetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress); + + ucSeqNumOfCompMsg = prScanDoneMsg->ucSeqNum; + eScanStatus = prScanDoneMsg->eScanStatus; + + cnmMemFree(prAdapter, prMsgHdr); + + DBGLOG(BOW, EVENT, "bowResponderScanDone.\n"); + DBGLOG(BOW, EVENT, "BOW SCAN [DONE:%d]\n", ucSeqNumOfCompMsg); + + if (eScanStatus == SCAN_STATUS_CANCELLED) { + DBGLOG(BOW, EVENT, "BOW SCAN [CANCELLED:%d]\n", ucSeqNumOfCompMsg); + if (eFsmState == BOW_DEVICE_STATE_DISCONNECTING) { + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + prBowFsmInfo->ucBssIndex, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, 0, NULL, 0); + } + return; + } else if (eFsmState == BOW_DEVICE_STATE_DISCONNECTED) { + /* bowDisconnectLink(prAdapter, NULL, TX_RESULT_SUCCESS); */ + return; + } else if (ucSeqNumOfCompMsg != prBowFsmInfo->ucSeqNumOfScanReq) { + DBGLOG(BOW, EVENT, "Sequence no. of BOW Responder scan done is not matched.\n"); + return; + } + prConnSettings->fgIsScanReqIssued = FALSE; + prBssDesc = scanSearchBssDescByBssid(prAdapter, prBowFsmInfo->aucPeerAddress); + DBGLOG(BOW, EVENT, "End scan result searching.\n"); + DBGLOG(BOW, EVENT, "prBowFsmInfo->aucPeerAddress: [" MACSTR "]\n", MAC2STR(prBowFsmInfo->aucPeerAddress)); + + /*Initiator is FOUND */ + if (prBssDesc != NULL) { /* (prBssDesc->aucBSSID != NULL)) */ + 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"); + + /*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; +#endif /* Marked for MT6630 */ +} + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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 struct ADAPTER *prAdapter, IN u_int8_t fgIsChannelExtention) +{ + + struct MSG_SCN_SCAN_CANCEL *prScanCancel = (struct MSG_SCN_SCAN_CANCEL *) NULL; + struct BOW_FSM_INFO *prBowFsmInfo = (struct BOW_FSM_INFO *) NULL; + + DEBUGFUNC("bowResponderCancelScan()"); + + do { + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if (TRUE) { + DBGLOG(BOW, EVENT, "BOW SCAN [CANCEL:%d]\n", prBowFsmInfo->ucSeqNumOfScanReq); + + /* There is a channel privilege on hand. */ + + DBGLOG(BOW, TRACE, "BOW Cancel Scan\n"); + + prScanCancel = + (struct MSG_SCN_SCAN_CANCEL *) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(struct MSG_SCN_SCAN_CANCEL)); + if (!prScanCancel) { + /* Buffer not enough, can not cancel scan request. */ + DBGLOG(BOW, TRACE, "Buffer not enough, can not cancel scan.\n"); + ASSERT(FALSE); + break; + } + + prScanCancel->rMsgHdr.eMsgId = MID_BOW_SCN_SCAN_CANCEL; + prScanCancel->ucBssIndex = prBowFsmInfo->ucBssIndex; + prScanCancel->ucSeqNum = prBowFsmInfo->ucSeqNumOfScanReq; +#if CFG_ENABLE_WIFI_DIRECT + prScanCancel->fgIsChannelExt = fgIsChannelExtention; +#endif + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *) 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 struct ADAPTER *prAdapter, IN struct BSS_DESC *prBssDesc) +{ + struct BOW_FSM_INFO *prBowFsmInfo; + struct BSS_INFO *prBssInfo; + struct CONNECTION_SETTINGS *prConnSettings; + struct STA_RECORD *prStaRec; + struct MSG_SAA_FSM_START *prJoinReqMsg; + + ASSERT(prBssDesc); + ASSERT(prAdapter); + + DBGLOG(BOW, EVENT, "Starting bowResponderJoin.\n"); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + 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, prBssInfo->ucBssIndex, prBssDesc); + + prBowFsmInfo->prTargetStaRec = prStaRec; + + /* 4 <3> Update ucAvailableAuthTypes which we can choice during SAA */ + prStaRec->fgIsReAssoc = FALSE; + prBowFsmInfo->ucAvailableAuthTypes = (uint8_t) 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 & (uint8_t) AUTH_TYPE_OPEN_SYSTEM) { + + DBGLOG(BOW, LOUD, "JOIN INIT: Try to do Authentication with AuthType == OPEN_SYSTEM.\n"); + prBowFsmInfo->ucAvailableAuthTypes &= ~(uint8_t) AUTH_TYPE_OPEN_SYSTEM; + + prStaRec->ucAuthAlgNum = (uint8_t) 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); + DBGLOG(BOW, EVENT, "bowResponderJoin, SSID %s.\n", prBssDesc->aucSSID); + DBGLOG(BOW, EVENT, "bowResponderJoin, SSID %s.\n", prConnSettings->aucSSID); + } + /* 4 <6> Send a Msg to trigger SAA to start JOIN process. */ + prJoinReqMsg = (struct MSG_SAA_FSM_START *) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(struct MSG_SAA_FSM_START)); + 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; + + DBGLOG(BOW, EVENT, "prStaRec->eStaType, %x.\n", prStaRec->eStaType); + DBGLOG(BOW, EVENT, "BoW trigger SAA [" MACSTR "]\n", MAC2STR(prStaRec->aucMacAddr)); + + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *) prJoinReqMsg, MSG_SEND_METHOD_BUF); + +} + +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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 struct ADAPTER *prAdapter, IN struct MSG_HDR *prMsgHdr) +{ +#if 1 /* Marked for MT6630 */ + + struct MSG_SAA_FSM_COMP *prJoinCompMsg; + struct BOW_FSM_INFO *prBowFsmInfo; + struct STA_RECORD *prStaRec; + struct SW_RFB *prAssocRspSwRfb; + struct WLAN_ASSOC_RSP_FRAME *prAssocRspFrame = (struct WLAN_ASSOC_RSP_FRAME *) NULL; + uint16_t u2IELength; + uint8_t *pucIE; + struct BSS_INFO *prBowBssInfo; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + prJoinCompMsg = (struct MSG_SAA_FSM_COMP *) prMsgHdr; + prStaRec = prJoinCompMsg->prStaRec; + + 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); + + 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 = (struct WLAN_ASSOC_RSP_FRAME *) prAssocRspSwRfb->pvHeader; + + u2IELength = + (uint16_t) ((prAssocRspSwRfb->u2PacketLen - + prAssocRspSwRfb->u2HeaderLen) - + (OFFSET_OF(struct WLAN_ASSOC_RSP_FRAME, aucInfoElem[0]) - WLAN_MAC_MGMT_HEADER_LEN)); + pucIE = prAssocRspFrame->aucInfoElem; + + prStaRec->eStaType = STA_TYPE_BOW_AP; + prStaRec->u2DesiredNonHTRateSet &= prBowBssInfo->u2OperationalRateSet; + prStaRec->ucDesiredPhyTypeSet = prStaRec->ucPhyTypeSet & prBowBssInfo->ucPhyTypeSet; +#if CFG_BOW_RATE_LIMITATION + /* 4 <1.2>Update Rate Set */ + /*Limit Rate Set to 24M, 48M, 54M */ + prStaRec->u2DesiredNonHTRateSet &= (RATE_SET_BIT_24M | RATE_SET_BIT_48M | RATE_SET_BIT_54M); + /*If peer cannot support the above rate set, fix on the available highest rate */ + if (prStaRec->u2DesiredNonHTRateSet == 0) { + uint8_t ucHighestRateIndex; + + if (rateGetHighestRateIndexFromRateSet + (prBowBssInfo->u2OperationalRateSet, &ucHighestRateIndex)) { + prStaRec->u2DesiredNonHTRateSet = BIT(ucHighestRateIndex); + } + } +#endif + + /* 4 <1.1> Change FW's Media State immediately. */ + bowChangeMediaState(prBowBssInfo, 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, prBowBssInfo->ucBssIndex); + DBGLOG(BOW, EVENT, "Finish bowUpdateBssInfoForJOIN.\n"); + + /* 4 <1.4> Activate current AP's STA_RECORD_T in Driver. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + DBGLOG(BOW, EVENT, "bowFsmRunEventJoinComplete, qmActivateStaRec.\n"); + + /* 4 <1.7> Set the Next State of BOW FSM */ + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + prBowFsmInfo->ucBssIndex, + 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 + DBGLOG(BOW, EVENT, "Start bowfsmRunEventJoinComplete -- Join failed.\n"); + DBGLOG(BOW, EVENT, "BoW trigger SAA REJOIN\n"); + } + } + + cnmMemFree(prAdapter, prMsgHdr); + +#endif /* Marked for MT6630 */ +} + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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 struct ADAPTER *prAdapter, + IN enum ENUM_PARAM_MEDIA_STATE eConnectionState, IN u_int8_t fgDelayIndication) +{ + struct EVENT_CONNECTION_STATUS rEventConnStatus; + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_INFO *prBssInfo; + struct BOW_FSM_INFO *prBowFsmInfo; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + /* 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 = (uint8_t) eConnectionState; + + if (eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + rEventConnStatus.ucReasonOfDisconnect = DISCONNECT_REASON_CODE_RESERVED; + + if (prBssInfo->eCurrentOPMode == OP_MODE_BOW) { + rEventConnStatus.ucInfraMode = (uint8_t) NET_TYPE_INFRA; + rEventConnStatus.u2AID = prBssInfo->u2AssocId; + rEventConnStatus.u2ATIMWindow = 0; + } else if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + rEventConnStatus.ucInfraMode = (uint8_t) 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 = (uint8_t) PARAM_NETWORK_TYPE_DS; + break; + + case PHY_TYPE_ERP_INDEX: + rEventConnStatus.ucNetworkType = (uint8_t) PARAM_NETWORK_TYPE_OFDM24; + break; + + case PHY_TYPE_OFDM_INDEX: + rEventConnStatus.ucNetworkType = (uint8_t) PARAM_NETWORK_TYPE_OFDM5; + break; + + default: + ASSERT(0); + rEventConnStatus.ucNetworkType = (uint8_t) PARAM_NETWORK_TYPE_DS; + break; + } + } else { + + rEventConnStatus.ucReasonOfDisconnect = prBssInfo->ucReasonOfDisconnect; + + } + + /* 4 <2> Indication */ + nicMediaStateChange(prAdapter, prBssInfo->ucBssIndex, &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)); + } + +} + +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Event of Tx Fail of AAA Module. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void bowRunEventAAATxFail(IN struct ADAPTER *prAdapter, IN struct STA_RECORD *prStaRec) +{ +#if 1 /* Marked for MT6630 */ + struct BSS_INFO *prBssInfo; + struct BOW_FSM_INFO *prBowFsmInfo; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + DBGLOG(BOW, EVENT, "bowRunEventAAATxFail , bssRemoveStaRecFromClientList.\n"); + DBGLOG(BOW, EVENT, "BoW AAA TxFail, target state %d\n", prStaRec->ucStaState + 1); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + bssRemoveClient(prAdapter, prBssInfo, prStaRec); + + return; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Event of Successful Completion of AAA Module. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +uint32_t bowRunEventAAAComplete(IN struct ADAPTER *prAdapter, IN struct STA_RECORD *prStaRec) +{ +#if 1 /* Marked for MT6630 */ + struct BSS_INFO *prBssInfo; + struct BOW_FSM_INFO *prBowFsmInfo; + + ASSERT(prStaRec); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + DBGLOG(BOW, STATE, "bowRunEventAAAComplete, cnmStaRecChangeState, STA_STATE_3.\n"); + DBGLOG(BOW, EVENT, "BoW AAA complete [" MACSTR "]\n", MAC2STR(prStaRec->aucMacAddr)); + + /*Update BssInfo to connected */ + bowChangeMediaState(prBssInfo, PARAM_MEDIA_STATE_CONNECTED); + nicUpdateBss(prAdapter, prBowFsmInfo->ucBssIndex); + + /*Update StaRec to State3 */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + /*Connected */ + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + prBowFsmInfo->ucBssIndex, + TRUE, FALSE, wlanbowCmdEventLinkConnected, wlanbowCmdTimeoutHandler, 0, NULL, 0); + + return WLAN_STATUS_SUCCESS; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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) +*/ +/*----------------------------------------------------------------------------*/ + +uint32_t bowRunEventRxDeAuth(IN struct ADAPTER *prAdapter, IN struct STA_RECORD *prStaRec, IN struct SW_RFB *prSwRfb) +{ +#if 1 /* Marked for MT6630 */ + struct BSS_INFO *prBowBssInfo; + struct BOW_FSM_INFO *prBowFsmInfo; + enum ENUM_BOW_DEVICE_STATE eFsmState; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + if (!IS_STA_BOW_TYPE(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 (prStaRec->ucStaState == STA_STATE_3) { + /* 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, + prBowFsmInfo->ucBssIndex, + TRUE, + FALSE, wlanbowCmdEventLinkDisconnected, wlanbowCmdTimeoutHandler, 0, NULL, 0); + + return WLAN_STATUS_SUCCESS; + } + + return WLAN_STATUS_NOT_ACCEPTED; + +#else + return 0; +#endif +} + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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 struct ADAPTER *prAdapter, IN struct MSDU_INFO *prMsduInfo, IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + struct BOW_FSM_INFO *prBowFsmInfo; + struct STA_RECORD *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); */ + 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 + if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) + wlanLoadManufactureData(prAdapter, kalGetConfiguration(prAdapter->prGlueInfo)); + else + DBGLOG(REQ, WARN, "%s: load manufacture data fail\n", __func__); + +#endif + /*Uninit BoW Interface */ +#if CFG_BOW_SEPARATE_DATA_PATH + kalUninitBowDevice(prAdapter->prGlueInfo); +#endif + } +} + +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t bowValidateAssocReq(IN struct ADAPTER *prAdapter, IN struct SW_RFB *prSwRfb, OUT uint16_t *pu2StatusCode) +{ +#if 1 /* Marked for MT6630 */ + + u_int8_t fgReplyAssocResp = FALSE; + struct BSS_INFO *prBowBssInfo; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + struct BOW_FSM_INFO *prBowFsmInfo; + struct WLAN_ASSOC_REQ_FRAME *prAssocReqFrame = (struct WLAN_ASSOC_REQ_FRAME *) NULL; + OS_SYSTIME rCurrentTime; + static OS_SYSTIME rLastRejectAssocTime; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + prAssocReqFrame = (struct WLAN_ASSOC_REQ_FRAME *) prSwRfb->pvHeader; + *pu2StatusCode = STATUS_CODE_REQ_DECLINED; + + 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]); + + /*Assoc Accept */ + while (EQUAL_MAC_ADDR(prAssocReqFrame->aucSrcAddr, prBowFsmInfo->aucPeerAddress)) { + DBGLOG(BOW, EVENT, "bowValidateAssocReq, return wlanbowCmdEventLinkConnected.\n"); + + /*Update StaRec */ + prStaRec = cnmGetStaRecByAddress(prAdapter, prBowFsmInfo->ucBssIndex, 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 available highest rate */ + if (prStaRec->u2DesiredNonHTRateSet == 0) { + uint8_t ucHighestRateIndex; + + if (rateGetHighestRateIndexFromRateSet(prBowBssInfo->u2OperationalRateSet, &ucHighestRateIndex)) + prStaRec->u2DesiredNonHTRateSet = BIT(ucHighestRateIndex); + else { + /*If no available rate is found, DECLINE the association */ + *pu2StatusCode = STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED; + break; + } + } +#endif + + /*Update BssInfo to FW */ + bowChangeMediaState(prBowBssInfo, PARAM_MEDIA_STATE_CONNECTED); + nicUpdateBss(prAdapter, prStaRec->ucBssIndex); + + /*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; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t +bowValidateAuth(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, IN struct STA_RECORD **pprStaRec, OUT uint16_t *pu2StatusCode) +{ +#if 1 /* Marked for MT6630 */ + u_int8_t fgReplyAuth = FALSE; + struct BSS_INFO *prBowBssInfo; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + struct BOW_FSM_INFO *prBowFsmInfo; + struct WLAN_AUTH_FRAME *prAuthFrame = (struct WLAN_AUTH_FRAME *) NULL; + OS_SYSTIME rCurrentTime; + static OS_SYSTIME rLastRejectAuthTime; + + /* TODO(Kevin): Call BoW functions to check .. + * 1. Check we are BoW now. + * 2. Check we can accept connection from thsi peer + * 3. Check Black List here. + */ + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + prAuthFrame = (struct WLAN_AUTH_FRAME *) prSwRfb->pvHeader; + + 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]); + + prStaRec = cnmGetStaRecByAddress(prAdapter, prBowFsmInfo->ucBssIndex, prAuthFrame->aucSrcAddr); + if (!prStaRec) { + DBGLOG(BOW, EVENT, "bowValidateAuth, cnmStaRecAlloc.\n"); + prStaRec = cnmStaRecAlloc(prAdapter, + STA_TYPE_BOW_CLIENT, prBowFsmInfo->ucBssIndex, prAuthFrame->aucSrcAddr); + + /* TODO(Kevin): Error handling of allocation of struct STA_RECORD for + * exhausted case and do removal of unused struct STA_RECORD. + */ + 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); + DBGLOG(BOW, EVENT, "bowValidateAuth, cnmStaRecChangeState.\n"); + } else { + prSwRfb->ucStaRecIdx = prStaRec->ucIndex; + DBGLOG(BOW, EVENT, "bowValidateAuth, prStaRec->ucIndex, %x.\n", prStaRec->ucIndex); + bssRemoveClient(prAdapter, prBowBssInfo, prStaRec); + } + + if (EQUAL_MAC_ADDR(prAuthFrame->aucSrcAddr, prBowFsmInfo->aucPeerAddress)) { + DBGLOG(BOW, EVENT, "bowValidateAuth, prStaRec->eStaType, %x.\n", prStaRec->eStaType); + DBGLOG(BOW, EVENT, "bowValidateAuth, prStaRec->ucBssIndex, %x.\n", prStaRec->ucBssIndex); + + /* 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); + *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; + } + } + + DBGLOG(BOW, EVENT, "bowValidateAuth, fgReplyAuth, %x.\n", fgReplyAuth); + return fgReplyAuth; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is invoked when CNM granted channel privilege +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +void bowRunEventChGrant(IN struct ADAPTER *prAdapter, IN struct MSG_HDR *prMsgHdr) +{ +#if 1 /* Marked for MT6630 */ + struct BSS_INFO *prBowBssInfo; + struct BOW_FSM_INFO *prBowFsmInfo; + struct MSG_CH_GRANT *prMsgChGrant; + uint8_t ucTokenID; + uint32_t u4GrantInterval; + enum ENUM_BOW_DEVICE_STATE eFsmState; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + prMsgChGrant = (struct MSG_CH_GRANT *) prMsgHdr; + ucTokenID = prMsgChGrant->ucTokenID; + u4GrantInterval = prMsgChGrant->u4GrantInterval; + + /* 1. free message */ + cnmMemFree(prAdapter, prMsgHdr); + prBowFsmInfo->fgIsChannelGranted = TRUE; + + DBGLOG(BOW, EVENT, "Entering bowRunEventChGrant.\n"); + + eFsmState = bowGetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress); + + /*Release channel */ + if ((!prBowFsmInfo->fgIsChannelRequested) || + (prBowFsmInfo->ucSeqNumOfChReq != ucTokenID) || + (eFsmState == BOW_DEVICE_STATE_DISCONNECTED) || (eFsmState == BOW_DEVICE_STATE_DISCONNECTING)) { + DBGLOG(BOW, EVENT, "BoW Channel [GIVE UP:%d]\n", ucTokenID); + DBGLOG(BOW, EVENT, "[Requested:%d][ucSeqNumOfChReq:%d][eFsmState:%d]\n", + prBowFsmInfo->fgIsChannelRequested, prBowFsmInfo->ucSeqNumOfChReq, eFsmState); + 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 */ + + DBGLOG(BOW, EVENT, "BoW Channel [GRANTED:%d].\n", ucTokenID); + + 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, prBowFsmInfo->ucBssIndex); + bowReleaseCh(prAdapter); + } + + return; +#endif /* Marked for MT6630 */ +} /* end of aisFsmRunEventChGrant() */ + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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 struct ADAPTER *prAdapter) +{ + struct BOW_FSM_INFO *prBowFsmInfo; + struct MSG_CH_REQ *prMsgChReq; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if (prBowFsmInfo->fgIsChannelGranted == FALSE) { + + DBGLOG(BOW, EVENT, "BoW channel [REQUEST:%d], %d, %d.\n", + prBowFsmInfo->ucSeqNumOfChReq + 1, prBowFsmInfo->ucPrimaryChannel, prBowFsmInfo->eBand); + + prMsgChReq = (struct MSG_CH_REQ *) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(struct MSG_CH_REQ)); + + if (!prMsgChReq) { + ASSERT(0); /* Can't indicate CNM for channel acquiring */ + return; + } + + prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; + prMsgChReq->ucBssIndex = prBowFsmInfo->ucBssIndex; + prMsgChReq->ucTokenID = ++prBowFsmInfo->ucSeqNumOfChReq; + prMsgChReq->eReqType = CH_REQ_TYPE_JOIN; +#if 0 + prMsgChReq->u4MaxInterval = BOW_JOIN_CH_REQUEST_INTERVAL; +#else + prMsgChReq->u4MaxInterval = 1; +#endif + /* prBowFsmInfo->prTargetBssDesc->ucChannelNum; */ + prMsgChReq->ucPrimaryChannel = prBowFsmInfo->ucPrimaryChannel; + /* prBowFsmInfo->prTargetBssDesc->eSco; */ + prMsgChReq->eRfSco = CHNL_EXT_SCN; + /* prBowFsmInfo->prTargetBssDesc->eBand; */ + prMsgChReq->eRfBand = prBowFsmInfo->eBand; + + /* FIXME : where to call cnmGetDbdcCapability in BOW? */ + /*prMsgChReq->eDBDCBand = (prAdapter->aprBssInfo[prMsgChReq->ucBssIndex])->eDBDCBand;*/ + prMsgChReq->eDBDCBand = ENUM_BAND_AUTO; + + /* To do: check if 80/160MHz bandwidth is needed here */ + prMsgChReq->eRfChannelWidth = 0; + prMsgChReq->ucRfCenterFreqSeg1 = 0; + prMsgChReq->ucRfCenterFreqSeg2 = 0; + + prBowFsmInfo->fgIsChannelRequested = TRUE; + + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *) 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 struct ADAPTER *prAdapter) +{ + struct BOW_FSM_INFO *prBowFsmInfo; + struct MSG_CH_ABORT *prMsgChAbort; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if (prBowFsmInfo->fgIsChannelGranted != FALSE || prBowFsmInfo->fgIsChannelRequested != FALSE) { + DBGLOG(BOW, EVENT, + "BoW channel [RELEASE:%d] %d, %d.\n", prBowFsmInfo->ucSeqNumOfChReq, + prBowFsmInfo->ucPrimaryChannel, prBowFsmInfo->eBand); + + prBowFsmInfo->fgIsChannelRequested = FALSE; + prBowFsmInfo->fgIsChannelGranted = FALSE; + + /* 1. return channel privilege to CNM immediately */ + prMsgChAbort = (struct MSG_CH_ABORT *) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(struct MSG_CH_ABORT)); + if (!prMsgChAbort) { + ASSERT(0); /* Can't release Channel to CNM */ + return; + } + + prMsgChAbort->rMsgHdr.eMsgId = MID_MNY_CNM_CH_ABORT; + prMsgChAbort->ucBssIndex = prBowFsmInfo->ucBssIndex; + prMsgChAbort->ucTokenID = prBowFsmInfo->ucSeqNumOfChReq; + + /* FIXME : where to call cnmGetDbdcCapability in BOW? */ + /*prMsgChAbort->eDBDCBand = (prAdapter->aprBssInfo[prMsgChAbort->ucBssIndex])->eDBDCBand;*/ + prMsgChAbort->eDBDCBand = ENUM_BAND_AUTO; + + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *) prMsgChAbort, MSG_SEND_METHOD_BUF); + } + +} /* end of aisFsmReleaseCh() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Media Disconnect" to HOST +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void bowChGrantedTimeout(IN struct ADAPTER *prAdapter, IN unsigned long ulParamPtr) +{ + struct BOW_FSM_INFO *prBowFsmInfo; + enum ENUM_BOW_DEVICE_STATE eFsmState; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + DBGLOG(BOW, EVENT, "BoW Channel [TIMEOUT]\n"); + +#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 +} + +#endif /* Marked for MT6630 */ + +u_int8_t bowNotifyAllLinkDisconnected(IN struct ADAPTER *prAdapter) +{ +#if 1 /* Marked for MT6630 */ + + uint8_t ucBowTableIdx = 0; + struct CMD_INFO rCmdInfo; + struct BOW_FSM_INFO *prBowFsmInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + kalMemZero(&rCmdInfo, sizeof(struct CMD_INFO)); + + while (ucBowTableIdx < CFG_BOW_PHYSICAL_LINK_NUM) { + if (arBowTable[ucBowTableIdx].fgIsValid) { + COPY_MAC_ADDR(prAdapter->rWifiVar.rBowFsmInfo.aucPeerAddress, + arBowTable[ucBowTableIdx].aucPeerAddress); + 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); +#if 1 + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + prBowFsmInfo->ucBssIndex, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, 0, NULL, 0); +#else + wlanbowCmdEventLinkDisconnected(prAdapter, &rCmdInfo, NULL); +#endif + } + + ucBowTableIdx += 1; + } + + return TRUE; + +#else + return 0; +#endif +} + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Bluetooth-over-Wi-Fi state from glue layer +* +* \param[in] +* prGlueInfo +* rPeerAddr +* \return +* ENUM_BOW_DEVICE_STATE +*/ +/*----------------------------------------------------------------------------*/ + +u_int8_t bowCheckBowTableIfVaild(IN struct ADAPTER *prAdapter, IN uint8_t aucPeerAddress[6]) +{ + uint8_t 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)) { + + 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); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + return TRUE; + } + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + return FALSE; +} + +u_int8_t bowGetBowTableContent(IN struct ADAPTER *prAdapter, IN uint8_t ucBowTableIdx, OUT struct BOW_TABLE *prBowTable) +{ + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + if (arBowTable[ucBowTableIdx].fgIsValid) { + + DBGLOG(BOW, EVENT, + "bowGetBowTableContent, arBowTable[idx].fgIsValid, %x, %x.\n", + ucBowTableIdx, arBowTable[ucBowTableIdx].fgIsValid); + DBGLOG(BOW, EVENT, "GET State [%d]\n", arBowTable[ucBowTableIdx].eState); + 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; +} + +u_int8_t bowSetBowTableContent(IN struct ADAPTER *prAdapter, IN uint8_t ucBowTableIdx, IN struct BOW_TABLE *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); */ + + DBGLOG(BOW, EVENT, "SET State [%d]\n", arBowTable[ucBowTableIdx].eState); + DBGLOG(BOW, EVENT, + "kalCheckBowifVaild, arBowTable[ucBowTableIdx].fgIsValid, %x, %x.\n", ucBowTableIdx, + arBowTable[ucBowTableIdx].fgIsValid); + + return TRUE; + +} + +u_int8_t +bowGetBowTableEntryByPeerAddress(IN struct ADAPTER *prAdapter, IN uint8_t aucPeerAddress[6], OUT uint8_t *pucBowTableIdx) +{ + uint8_t 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)) { + + 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); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + *pucBowTableIdx = idx; + + return TRUE; + } + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + return FALSE; +} + +u_int8_t bowGetBowTableFreeEntry(IN struct ADAPTER *prAdapter, OUT uint8_t *pucBowTableIdx) +{ + uint8_t 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) { + DBGLOG(BOW, EVENT, + "bowGetBowTableFreeEntry, arBowTable[idx].fgIsValid, %x, %x.\n", + idx, arBowTable[idx].fgIsValid); + *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 ENUM_BOW_DEVICE_STATE bowGetBowTableState(IN struct ADAPTER *prAdapter, IN uint8_t aucPeerAddress[6]) +{ + uint8_t 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)) { + DBGLOG(BOW, EVENT, + "bowGetState, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, + aucPeerAddress[0], aucPeerAddress[1], aucPeerAddress[2], + aucPeerAddress[3], aucPeerAddress[4], aucPeerAddress[5]); + DBGLOG(BOW, EVENT, + "bowGetState, arBowTable[idx].aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", + idx, arBowTable[idx].aucPeerAddress[0], + arBowTable[idx].aucPeerAddress[1], + arBowTable[idx].aucPeerAddress[2], + arBowTable[idx].aucPeerAddress[3], + arBowTable[idx].aucPeerAddress[4], arBowTable[idx].aucPeerAddress[5]); + DBGLOG(BOW, EVENT, + "bowGetState, arBowTable[idx].fgIsValid, %x, %x.\n", idx, arBowTable[idx].fgIsValid); + DBGLOG(BOW, EVENT, + "bowGetState, arBowTable[idx].eState;, %x, %x.\n", idx, arBowTable[idx].eState); + DBGLOG(BOW, EVENT, "GET State [%d]\n", arBowTable[idx].eState); + + 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; +} + +u_int8_t bowSetBowTableState(IN struct ADAPTER *prAdapter, IN uint8_t aucPeerAddress[6], IN enum ENUM_BOW_DEVICE_STATE eState) +{ + uint8_t ucBowTableIdx; + + if (bowGetBowTableEntryByPeerAddress(prAdapter, aucPeerAddress, &ucBowTableIdx)) { + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + arBowTable[ucBowTableIdx].eState = eState; + DBGLOG(BOW, EVENT, "SET State [%d]\n", eState); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + kalSetBowState(prAdapter->prGlueInfo, eState, aucPeerAddress); + return TRUE; + } + return FALSE; +} + +#endif + +#endif /* Marked for MT6630 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/common/wlan_lib.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/common/wlan_lib.c new file mode 100644 index 0000000000000..e4a6ccd01db41 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/common/wlan_lib.c @@ -0,0 +1,10702 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/*! \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. + */ + + +/******************************************************************************* + * C O M P I L E 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 uint8_t aucPriorityParam2TC[] = { + TC1_INDEX, + TC0_INDEX, + TC0_INDEX, + TC1_INDEX, + TC2_INDEX, + TC2_INDEX, + TC3_INDEX, + TC3_INDEX +}; + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +struct CODE_MAPPING { + uint32_t u4RegisterValue; + int32_t u4TxpowerOffset; +}; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +u_int8_t fgIsBusAccessFailed = FALSE; +struct MIB_INFO_STAT g_arMibInfo[ENUM_BAND_NUM]; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +#if CFG_RCPI_COMPENSATION +static u_int8_t RxFELoss[MAX_ANTENNA_NUM][FELOSS_CH_GROUP_NUM]; + +static const u_int16_t FELossOffset[MAX_ANTENNA_NUM][FELOSS_CH_GROUP_NUM] = { + {G_BAND_WF0_FELOSS, A_BAND_WF0_LB_FELOSS, + A_BAND_WF0_MB_FELOSS, A_BAND_WF0_HB_FELOSS}, + {G_BAND_WF1_FELOSS, A_BAND_WF1_LB_FELOSS, + A_BAND_WF1_MB_FELOSS, A_BAND_WF1_HB_FELOSS} +}; +#endif + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +/* HIF suspend should wait for cfg80211 suspend done */ +#define HIF_SUSPEND_MAX_WAIT_TIME 50 /* unit: 5ms */ + +#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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wlanIsHandlerNeedHwAccess(IN PFN_OID_HANDLER_FUNC + pfnOidHandler, IN u_int8_t fgSetInfo) +{ + PFN_OID_HANDLER_FUNC *apfnOidHandlerWOHwAccess; + uint32_t i; + uint32_t 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 struct ADAPTER *prAdapter) +{ + DEBUGFUNC("wlanCardEjected"); + /* INITLOG(("\n")); */ + + ASSERT(prAdapter); + + /* mark that the card is being ejected, NDIS will shut us down soon */ + nicTxRelease(prAdapter, FALSE); + +} /* wlanCardEjected */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to check driver ready state + * + * \param[in] prGlueInfo Pointer to the GlueInfo structure. + * + * \retval TRUE Driver is ready for kernel access + * \retval FALSE Driver is not ready + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wlanIsDriverReady(IN struct GLUE_INFO *prGlueInfo) +{ + return prGlueInfo && prGlueInfo->u4ReadyFlag && !kalIsResetting(); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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. + */ +/*----------------------------------------------------------------------------*/ +struct ADAPTER *wlanAdapterCreate(IN struct GLUE_INFO + *prGlueInfo) +{ + struct ADAPTER *prAdpater = (struct ADAPTER *) NULL; + + DEBUGFUNC("wlanAdapterCreate"); + + do { + prAdpater = (struct ADAPTER *) kalMemAlloc(sizeof( + struct ADAPTER), 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(struct ADAPTER)); + 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 struct ADAPTER *prAdapter) +{ + if (!prAdapter) + return; + + scanLogCacheFlushAll(&(prAdapter->rWifiVar.rScanInfo.rScanLogCache), + LOG_SCAN_D2D, SCAN_LOG_MSG_MAX_LEN); + + kalMemFree(prAdapter, VIR_MEM_TYPE, sizeof(struct ADAPTER)); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanAdapterStart(IN struct ADAPTER *prAdapter, + IN struct REG_INFO *prRegInfo) +{ + uint32_t u4Status = WLAN_STATUS_SUCCESS; + uint32_t i; + enum ENUM_ADAPTER_START_FAIL_REASON { + ALLOC_ADAPTER_MEM_FAIL, + DRIVER_OWN_FAIL, + INIT_ADAPTER_FAIL, + INIT_HIFINFO_FAIL, + RAM_CODE_DOWNLOAD_FAIL, + WAIT_FIRMWARE_READY_FAIL, + FAIL_REASON_MAX + } eFailReason; + + ASSERT(prAdapter); + + DEBUGFUNC("wlanAdapterStart"); + + eFailReason = FAIL_REASON_MAX; + /* 4 <0> Reset variables in ADAPTER_T */ + /* prAdapter->fgIsFwOwn = TRUE; */ + prAdapter->fgIsEnterD3ReqIssued = FALSE; + + prAdapter->u4OwnFailedCount = 0; + prAdapter->u4OwnFailedLogCount = 0; + prAdapter->ucHwBssIdNum = BSS_DEFAULT_NUM; + prAdapter->ucWmmSetNum = BSS_DEFAULT_NUM; + prAdapter->ucP2PDevBssIdx = BSS_DEFAULT_NUM; + prAdapter->ucWtblEntryNum = WTBL_SIZE; + prAdapter->ucTxDefaultWlanIndex = prAdapter->ucWtblEntryNum - 1; + prAdapter->ucSerState = SER_IDLE_DONE; + + prAdapter->fgEnHifDbgInfo = true; + prAdapter->u4HifDbgFlag = 0; + prAdapter->u4HifChkFlag = 0; + + QUEUE_INITIALIZE(&(prAdapter->rPendingCmdQueue)); +#if CFG_SUPPORT_MULTITHREAD + QUEUE_INITIALIZE(&prAdapter->rTxCmdQueue); + QUEUE_INITIALIZE(&prAdapter->rTxCmdDoneQueue); +#if CFG_FIX_2_TX_PORT + QUEUE_INITIALIZE(&prAdapter->rTxP0Queue); + QUEUE_INITIALIZE(&prAdapter->rTxP1Queue); +#else + for (i = 0; i < TX_PORT_NUM; i++) + QUEUE_INITIALIZE(&prAdapter->rTxPQueue[i]); +#endif + QUEUE_INITIALIZE(&prAdapter->rRxQueue); + QUEUE_INITIALIZE(&prAdapter->rTxDataDoneQueue); +#endif + + /* Initialize rWlanInfo */ + kalMemSet(&(prAdapter->rWlanInfo), 0, + sizeof(struct WLAN_INFO)); + + /* Initialize aprBssInfo[]. + * Important: index shall be same when mapping between aprBssInfo[] + * and arBssInfoPool[]. rP2pDevInfo is indexed to final one. + */ + for (i = 0; i < MAX_BSSID_NUM; i++) + prAdapter->aprBssInfo[i] = + &prAdapter->rWifiVar.arBssInfoPool[i]; + prAdapter->aprBssInfo[prAdapter->ucP2PDevBssIdx] = + &prAdapter->rWifiVar.rP2pDevInfo; + + /* 4 <0.1> reset fgIsBusAccessFailed */ + fgIsBusAccessFailed = FALSE; + + do { + u4Status = nicAllocateAdapterMemory(prAdapter); + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "nicAllocateAdapterMemory Error!\n"); + u4Status = WLAN_STATUS_FAILURE; + eFailReason = ALLOC_ADAPTER_MEM_FAIL; +#if CFG_ENABLE_KEYWORD_EXCEPTION_MECHANISM + mtk_wcn_wmt_assert_keyword(WMTDRV_TYPE_WIFI, + "[Wi-Fi On] nicAllocateAdapterMemory Error!"); +#endif + break; + } + + prAdapter->u4OsPacketFilter = PARAM_PACKET_FILTER_SUPPORTED; + + DBGLOG(INIT, INFO, + "wlanAdapterStart(): Acquiring LP-OWN\n"); + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + DBGLOG(INIT, INFO, + "wlanAdapterStart(): Acquiring LP-OWN-end\n"); + +#if (CFG_ENABLE_FULL_PM == 0) + nicpmSetDriverOwn(prAdapter); + + if (prAdapter->fgIsFwOwn == TRUE) { + DBGLOG(INIT, ERROR, "nicpmSetDriverOwn() failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + eFailReason = DRIVER_OWN_FAIL; +#if CFG_ENABLE_KEYWORD_EXCEPTION_MECHANISM + mtk_wcn_wmt_assert_keyword(WMTDRV_TYPE_WIFI, + "[Wi-Fi On] nicpmSetDriverOwn() failed!"); +#endif + break; + } +#endif + + /* 4 <1> Initialize the Adapter */ + u4Status = nicInitializeAdapter(prAdapter); + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "nicInitializeAdapter failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + eFailReason = INIT_ADAPTER_FAIL; + break; + } + + /* 4 <2.1> Initialize System Service (MGMT Memory pool and + * STA_REC) + */ + nicInitSystemService(prAdapter); + + /* 4 <2.2> Initialize Feature Options */ + wlanInitFeatureOption(prAdapter); +#if CFG_SUPPORT_MTK_SYNERGY + if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) { + if (prRegInfo->prNvramSettings->u2FeatureReserved & + BIT(MTK_FEATURE_2G_256QAM_DISABLED)) + prAdapter->rWifiVar.aucMtkFeature[0] &= + ~(MTK_SYNERGY_CAP_SUPPORT_24G_MCS89); + } +#endif + + /* 4 <2.3> Overwrite debug level settings */ + wlanCfgSetDebugLevel(prAdapter); + + /* 4 <3> Initialize Tx */ + nicTxInitialize(prAdapter); + wlanDefTxPowerCfg(prAdapter); + + /* 4 <4> Initialize Rx */ + nicRxInitialize(prAdapter); + + /* 4 <5> HIF SW info initialize */ + if (!halHifSwInfoInit(prAdapter)) { + DBGLOG(INIT, ERROR, "halHifSwInfoInit failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + eFailReason = INIT_HIFINFO_FAIL; + break; + } + + u4Status = wlanWakeUpWiFi(prAdapter); + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "wlanWakeUpWiFi failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } + + /* 4 <6> Enable HIF cut-through to N9 mode, not visiting CR4 */ + HAL_ENABLE_FWDL(prAdapter, TRUE); + + /* 4 <7> Get ECO Version */ + u4Status = wlanSetChipEcoInfo(prAdapter); + + if (u4Status != WLAN_STATUS_SUCCESS) + break; + + +#if CFG_ENABLE_FW_DOWNLOAD + /* 4 <8> FW/patch download */ + + /* 1. disable interrupt, download is done by polling mode only + */ + nicDisableInterrupt(prAdapter); + + /* 2. Initialize Tx Resource to fw download state */ + nicTxInitResetResource(prAdapter); + + u4Status = wlanDownloadFW(prAdapter); + + if (u4Status != WLAN_STATUS_SUCCESS) { + eFailReason = RAM_CODE_DOWNLOAD_FAIL; + break; + } +#endif + + DBGLOG(INIT, INFO, "Waiting for Ready bit..\n"); + + /* 4 <9> check Wi-Fi FW asserts ready bit */ + u4Status = wlanCheckWifiFunc(prAdapter, TRUE); + + if (u4Status == WLAN_STATUS_SUCCESS) { +#if defined(_HIF_SDIO) + uint32_t *pu4WHISR = NULL; + uint16_t au2TxCount[16]; + + pu4WHISR = (uint32_t *)kalMemAlloc(sizeof(uint32_t), + PHY_MEM_TYPE); + if (!pu4WHISR) { + DBGLOG(INIT, ERROR, + "Allocate pu4WHISR fail\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } + /* 1. reset interrupt status */ + HAL_READ_INTR_STATUS(prAdapter, sizeof(uint32_t), + (uint8_t *)pu4WHISR); + if (HAL_IS_TX_DONE_INTR(*pu4WHISR)) + HAL_READ_TX_RELEASED_COUNT(prAdapter, + au2TxCount); + + if (pu4WHISR) + kalMemFree(pu4WHISR, PHY_MEM_TYPE, + sizeof(uint32_t)); +#endif + /* Set FW download success flag */ + prAdapter->fgIsFwDownloaded = TRUE; + + /* 2. query & reset TX Resource for normal operation */ + wlanQueryNicResourceInformation(prAdapter); + +#if (CFG_SUPPORT_NIC_CAPABILITY == 1) + + /* 2.9 Workaround for Capability CMD packet lost issue + */ + wlanSendDummyCmd(prAdapter, TRUE); + + /* 3. query for NIC capability */ + if (prAdapter->chip_info->isNicCapV1) + wlanQueryNicCapability(prAdapter); + + /* 4. query for NIC capability V2 */ + wlanQueryNicCapabilityV2(prAdapter); + + /* 5. reset TX Resource for normal operation + * based on the information reported from + * CMD_NicCapabilityV2 + */ + wlanUpdateNicResourceInformation(prAdapter); + + wlanPrintVersion(prAdapter); +#endif + + /* 6. update basic configuration */ + wlanUpdateBasicConfig(prAdapter); + + /* 7. Override network address */ + wlanUpdateNetworkAddress(prAdapter); + + /* 8. Apply Network Address */ + nicApplyNetworkAddress(prAdapter); + + /* 9. indicate disconnection as default status */ + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + } + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + + if (u4Status != WLAN_STATUS_SUCCESS) { + eFailReason = WAIT_FIRMWARE_READY_FAIL; + break; + } + + /* OID timeout timer initialize */ + cnmTimerInitTimer(prAdapter, + &prAdapter->rOidTimeoutTimer, + (PFN_MGMT_TIMEOUT_FUNC) wlanReleasePendingOid, + (unsigned long) NULL); + + prAdapter->ucOidTimeoutCount = 0; + + prAdapter->fgIsChipNoAck = FALSE; + + /* Return Indicated Rfb list timer */ + cnmTimerInitTimer(prAdapter, + &prAdapter->rPacketDelaySetupTimer, + (PFN_MGMT_TIMEOUT_FUNC) + wlanReturnPacketDelaySetupTimeout, + (unsigned long) NULL); + + /* Power state initialization */ + prAdapter->fgWiFiInSleepyState = FALSE; + prAdapter->rAcpiState = ACPI_STATE_D0; + +#if 0 + /* 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; +#else + if (prAdapter->rWifiVar.fgDisOnlineScan == 0) + prAdapter->fgEnOnlineScan = TRUE; + else + prAdapter->fgEnOnlineScan = FALSE; + + /* Beacon lost detection option */ + if (prAdapter->rWifiVar.fgDisBcnLostDetection != 0) + prAdapter->fgDisBcnLostDetection = TRUE; +#endif + + /* 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->u4PsCurrentMeasureEn = + prRegInfo->u4PsCurrentMeasureEn; +#if 0 + prAdapter->fgEnArpFilter = prRegInfo->fgEnArpFilter; + prAdapter->u4UapsdAcBmp = prRegInfo->u4UapsdAcBmp; + prAdapter->u4MaxSpLen = prRegInfo->u4MaxSpLen; +#else + prAdapter->fgEnArpFilter = + prAdapter->rWifiVar.fgEnArpFilter; + prAdapter->u4UapsdAcBmp = prAdapter->rWifiVar.u4UapsdAcBmp; + prAdapter->u4MaxSpLen = prAdapter->rWifiVar.u4MaxSpLen; +#endif + DBGLOG(INIT, TRACE, + "[1] fgEnArpFilter:0x%x, u4UapsdAcBmp:0x%x, u4MaxSpLen:0x%x", + prAdapter->fgEnArpFilter, prAdapter->u4UapsdAcBmp, + prAdapter->u4MaxSpLen); + + prAdapter->fgEnCtiaPowerMode = FALSE; + +#endif + /* QA_TOOL and ICAP info struct */ + prAdapter->rIcapInfo.fgCaptureDone = FALSE; + prAdapter->rIcapInfo.fgIcapEnable = FALSE; + prAdapter->rIcapInfo.u2DumpIndex = 0; + prAdapter->rIcapInfo.u4CapNode = 0; + + /* MGMT Initialization */ + nicInitMGMT(prAdapter, prRegInfo); + /* NCHO Initialization */ +#if CFG_SUPPORT_NCHO + prAdapter->rNchoInfo.fgECHOEnabled = FALSE; + prAdapter->rNchoInfo.eBand = NCHO_BAND_AUTO; + prAdapter->rNchoInfo.fgChGranted = FALSE; + prAdapter->rNchoInfo.fgIsSendingAF = FALSE; + prAdapter->rNchoInfo.u4RoamScanControl = FALSE; + prAdapter->rNchoInfo.rRoamScnChnl.ucChannelListNum = 0; + prAdapter->rNchoInfo.rRoamScnChnl.arChnlInfoList[0].eBand = + BAND_2G4; + prAdapter->rNchoInfo.rRoamScnChnl.arChnlInfoList[0].ucChannelNum + = 1; + prAdapter->rNchoInfo.eDFSScnMode = NCHO_DFS_SCN_ENABLE1; + prAdapter->rNchoInfo.i4RoamTrigger = -70; + prAdapter->rNchoInfo.i4RoamDelta = 5; + prAdapter->rNchoInfo.u4RoamScanPeriod = + ROAMING_DISCOVERY_TIMEOUT_SEC; + prAdapter->rNchoInfo.u4ScanChannelTime = 50; + prAdapter->rNchoInfo.u4ScanHomeTime = 120; + prAdapter->rNchoInfo.u4ScanHomeawayTime = 120; + prAdapter->rNchoInfo.u4ScanNProbes = 2; + prAdapter->rNchoInfo.u4WesMode = 0; +#endif + + /* Enable WZC Disassociation */ + prAdapter->rWifiVar.fgSupportWZCDisassociation = TRUE; + + /* Apply Rate Setting */ + if ((enum ENUM_REGISTRY_FIXED_RATE) (prRegInfo->u4FixedRate) + < FIXED_RATE_NUM) + prAdapter->rWifiVar.eRateSetting = + (enum ENUM_REGISTRY_FIXED_RATE) + (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 0 /* Marked for MT6630 */ +#if 1 /* set PM parameters */ + { +#if CFG_SUPPORT_PWR_MGT + prAdapter->u4PowerMode = prRegInfo->u4PowerMode; +#if CFG_ENABLE_WIFI_DIRECT + prAdapter->rWlanInfo. + arPowerSaveMode[NETWORK_TYPE_P2P_INDEX].ucNetTypeIndex + = NETWORK_TYPE_P2P_INDEX; + prAdapter->rWlanInfo. + arPowerSaveMode[NETWORK_TYPE_P2P_INDEX].ucPsProfile + = ENUM_PSP_FAST_SWITCH; +#endif +#else + prAdapter->u4PowerMode = ENUM_PSP_CONTINUOUS_ACTIVE; +#endif + + nicConfigPowerSaveProfile(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, + prAdapter->u4PowerMode, FALSE); + } + +#endif +#endif + + /* Check hardware 5g band support */ + if (prAdapter->fgIsHw5GBandDisabled) + prAdapter->fgEnable5GBand = FALSE; + else + prAdapter->fgEnable5GBand = TRUE; + +#if CFG_SUPPORT_NVRAM + /* load manufacture data */ + if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) + wlanLoadManufactureData(prAdapter, prRegInfo); + else + DBGLOG(INIT, WARN, "%s: load manufacture data fail\n", + __func__); +#endif + +#if 0 + /* Update Auto rate parameters in FW */ + nicRlmArUpdateParms(prAdapter, prRegInfo->u4ArSysParam0, + prRegInfo->u4ArSysParam1, + prRegInfo->u4ArSysParam2, + prRegInfo->u4ArSysParam3); +#endif + + /* Default QM RX BA timeout */ + prAdapter->u4QmRxBaMissTimeout = + QM_RX_BA_ENTRY_MISS_TIMEOUT_MS; + +#if CFG_SUPPORT_LOWLATENCY_MODE + wlanAdapterStartForLowLatency(prAdapter); +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + +#if (CFG_SUPPORT_GET_MCS_INFO == 1) + prAdapter->fgIsMcsInfoValid = 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); + +#if CFG_SUPPORT_SER +#if defined(_HIF_USB) + cnmTimerInitTimer(prAdapter, + &prAdapter->rSerSyncTimer, + (PFN_MGMT_TIMEOUT_FUNC) nicSerSyncTimerHandler, + (unsigned long) NULL); + cnmTimerStartTimer(prAdapter, + &prAdapter->rSerSyncTimer, + WIFI_SER_SYNC_TIMER_TIMEOUT_IN_MS); +#endif /* _HIF_USB */ +#endif /* CFG_SUPPORT_SER */ + } else { + prAdapter->u4HifDbgFlag |= DEG_HIF_DEFAULT_DUMP; + halPrintHifDbgInfo(prAdapter); + DBGLOG(INIT, WARN, "Fail reason: %d\n", eFailReason); + /* release allocated memory */ + switch (eFailReason) { + case WAIT_FIRMWARE_READY_FAIL: + case RAM_CODE_DOWNLOAD_FAIL: + case INIT_HIFINFO_FAIL: + nicRxUninitialize(prAdapter); + nicTxRelease(prAdapter, FALSE); + /* System Service Uninitialization */ + nicUninitSystemService(prAdapter); + /* fallthrough */ + case INIT_ADAPTER_FAIL: + /* fallthrough */ + case DRIVER_OWN_FAIL: + nicReleaseAdapterMemory(prAdapter); + break; + case ALLOC_ADAPTER_MEM_FAIL: + default: + break; + } + } +#if CFG_SUPPORT_CUSTOM_NETLINK + glCustomGenlInit(); +#endif + + return u4Status; +} /* wlanAdapterStart */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Uninitialize the adapter + * + * \param prAdapter Pointer of Adapter Data Structure + * + * \retval WLAN_STATUS_SUCCESS: Success + * \retval WLAN_STATUS_FAILURE: Failed + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanAdapterStop(IN struct ADAPTER *prAdapter) +{ + uint32_t u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + + /* Release all CMD/MGMT/SEC frame in command queue */ + kalClearCommandQueue(prAdapter->prGlueInfo); + +#if CFG_SUPPORT_MULTITHREAD + + /* Flush all items in queues for multi-thread */ + wlanClearTxCommandQueue(prAdapter); + + wlanClearTxCommandDoneQueue(prAdapter); + + wlanClearDataQueue(prAdapter); + + wlanClearRxToOsQueue(prAdapter); + +#endif + /* Hif power off wifi */ + + if (prAdapter->rAcpiState == ACPI_STATE_D0 && + !wlanIsChipNoAck(prAdapter) + && !kalIsCardRemoved(prAdapter->prGlueInfo)) { + wlanPowerOffWifi(prAdapter); + } + + nicRxUninitialize(prAdapter); + + nicTxRelease(prAdapter, FALSE); + + /* MGMT - unitialization */ + nicUninitMGMT(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 + +#if CFG_SUPPORT_CUSTOM_NETLINK + glCustomGenlDeinit(); +#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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wlanISR(IN struct ADAPTER *prAdapter, + IN u_int8_t 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 struct ADAPTER *prAdapter) +{ + uint32_t u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + if (prAdapter->fgIsFwOwn == FALSE) { + u4Status = nicProcessIST(prAdapter); + if (u4Status != WLAN_STATUS_SUCCESS && + (u4Status != WLAN_STATUS_NOT_INDICATING)) + DBGLOG(REQ, INFO, "Fail: nicProcessIST! status [%d]\n", + u4Status); + +#if CFG_ENABLE_WAKE_LOCK + if (KAL_WAKE_LOCK_ACTIVE(prAdapter, + &prAdapter->prGlueInfo->rIntrWakeLock)) + KAL_WAKE_UNLOCK(prAdapter, + &prAdapter->prGlueInfo->rIntrWakeLock); +#endif + } + + nicEnableInterrupt(prAdapter); + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + + +} + +void wlanClearPendingInterrupt(IN struct ADAPTER *prAdapter) +{ + uint32_t i; + + i = 0; + while (i < CFG_IST_LOOP_COUNT + && nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) { + i++; + }; +} + +uint32_t wlanCheckWifiFunc(IN struct ADAPTER *prAdapter, + IN u_int8_t fgRdyChk) +{ + u_int8_t fgResult, fgTimeout; + uint32_t u4Result, u4Status, u4StartTime, u4CurTime; + const uint32_t ready_bits = + prAdapter->chip_info->sw_ready_bits; + + u4StartTime = kalGetTimeTick(); + fgTimeout = FALSE; + +#if defined(_HIF_USB) + if (prAdapter->prGlueInfo->rHifInfo.state == + USB_STATE_LINK_DOWN) + return WLAN_STATUS_FAILURE; +#endif + + while (TRUE) { + DBGLOG(INIT, INFO, "Check ready_bits(=0x%x)\n", ready_bits); + if (fgRdyChk) + HAL_WIFI_FUNC_READY_CHECK(prAdapter, + ready_bits /* WIFI_FUNC_READY_BITS */, + &fgResult); + else { + HAL_WIFI_FUNC_OFF_CHECK(prAdapter, + ready_bits /* WIFI_FUNC_READY_BITS */, + &fgResult); +#if defined(_HIF_USB) || defined(_HIF_SDIO) + if (nicProcessIST(prAdapter) != + WLAN_STATUS_NOT_INDICATING) + DBGLOG(INIT, INFO, + "Handle pending interrupt\n"); +#endif /* _HIF_USB or _HIF_SDIO */ + } + u4CurTime = kalGetTimeTick(); + + if (CHECK_FOR_TIMEOUT(u4CurTime, u4StartTime, + CFG_RESPONSE_POLLING_TIMEOUT * + CFG_RESPONSE_POLLING_DELAY)) { + + fgTimeout = TRUE; + } + + if (fgResult) { + if (fgRdyChk) + DBGLOG(INIT, INFO, "Ready bit asserted\n"); + else + DBGLOG(INIT, INFO, "Wi-Fi power off done!\n"); + + u4Status = WLAN_STATUS_SUCCESS; + + break; + } else if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + + break; + } else if (fgTimeout) { + HAL_WIFI_FUNC_GET_STATUS(prAdapter, u4Result); + DBGLOG(INIT, ERROR, + "Waiting for %s: Timeout, Status=0x%08x\n", + fgRdyChk ? "ready bit" : "power off", u4Result); +#if CFG_ENABLE_KEYWORD_EXCEPTION_MECHANISM + mtk_wcn_wmt_assert_keyword(WMTDRV_TYPE_WIFI, + "[Wi-Fi] [Read WCIR_WLAN_READY fail!]"); +#else + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP | + RST_FLAG_PREVENT_POWER_OFF); +#endif + u4Status = WLAN_STATUS_FAILURE; + break; + } + kalMsleep(CFG_RESPONSE_POLLING_DELAY); + + } + + return u4Status; +} + +uint32_t wlanPowerOffWifi(IN struct ADAPTER *prAdapter) +{ + uint32_t rStatus; + /* Hif power off wifi */ + rStatus = halHifPowerOffWifi(prAdapter); + prAdapter->fgIsCr4FwDownloaded = FALSE; + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanProcessCommandQueue(IN struct ADAPTER + *prAdapter, IN struct QUE *prCmdQue) +{ + uint32_t rStatus; + struct QUE rTempCmdQue, rMergeCmdQue, rStandInCmdQue; + struct QUE *prTempCmdQue, *prMergeCmdQue, *prStandInCmdQue; + struct QUE_ENTRY *prQueueEntry; + struct CMD_INFO *prCmdInfo; + struct MSDU_INFO *prMsduInfo; + enum ENUM_FRAME_ACTION 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, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + + switch (prCmdInfo->eCmdType) { + case COMMAND_TYPE_NETWORK_IOCTL: { + struct WIFI_CMD *prWifiCmd = (struct WIFI_CMD *) NULL; + struct CMD_802_11_KEY *prKey = (struct CMD_802_11_KEY *) + NULL; + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + + eFrameAction = FRAME_ACTION_TX_PKT; + do { + prWifiCmd = (struct WIFI_CMD *) + (prCmdInfo->pucInfoBuffer); + prKey = (struct CMD_802_11_KEY *) + (prWifiCmd->aucBuffer); + prBssInfo = + prAdapter->aprBssInfo[prKey->ucBssIdx]; + + if ((prCmdInfo->ucCID != CMD_ID_ADD_REMOVE_KEY) + || !prKey->ucTxKey + || !prKey->ucAddRemove + || ( + prKey->ucAlgorithmId != CIPHER_SUITE_TKIP && + prKey->ucAlgorithmId != CIPHER_SUITE_CCMP)) + break; + switch (prBssInfo->eKeyAction) { + case SEC_DROP_KEY_COMMAND: + eFrameAction = FRAME_ACTION_DROP_PKT; + break; + case SEC_QUEUE_KEY_COMMAND: + eFrameAction = FRAME_ACTION_QUEUE_PKT; + break; + case SEC_TX_KEY_COMMAND: + default: + eFrameAction = FRAME_ACTION_TX_PKT; + break; + } + } while (FALSE); + break; + } + case COMMAND_TYPE_GENERAL_IOCTL: + /* command packet will be always sent */ + eFrameAction = FRAME_ACTION_TX_PKT; + break; + + case COMMAND_TYPE_SECURITY_FRAME: + /* inquire with QM */ + prMsduInfo = prCmdInfo->prMsduInfo; + + eFrameAction = qmGetFrameAction(prAdapter, + prMsduInfo->ucBssIndex, + prMsduInfo->ucStaRecIndex, + NULL, FRAME_TYPE_802_1X, + prCmdInfo->u2InfoBufLen); + break; + + case COMMAND_TYPE_MANAGEMENT_FRAME: + /* inquire with QM */ + prMsduInfo = prCmdInfo->prMsduInfo; + + eFrameAction = qmGetFrameAction(prAdapter, + prMsduInfo->ucBssIndex, + prMsduInfo->ucStaRecIndex, + prMsduInfo, FRAME_TYPE_MMPDU, + prMsduInfo->u2FrameLength); + break; + + default: + ASSERT(0); + break; + } + + /* 4 <3> handling upon dequeue result */ + if (eFrameAction == FRAME_ACTION_DROP_PKT) { + DBGLOG(INIT, INFO, + "DROP CMD TYPE[%u] ID[0x%02X] SEQ[%u]\n", + prCmdInfo->eCmdType, prCmdInfo->ucCID, + prCmdInfo->ucCmdSeqNum); + wlanReleaseCommand(prAdapter, prCmdInfo, + TX_RESULT_DROPPED_IN_DRIVER); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } else if (eFrameAction == FRAME_ACTION_QUEUE_PKT) { + DBGLOG(INIT, TRACE, + "QUE back CMD TYPE[%u] ID[0x%02X] SEQ[%u]\n", + prCmdInfo->eCmdType, prCmdInfo->ucCID, + prCmdInfo->ucCmdSeqNum); + + QUEUE_INSERT_TAIL(prMergeCmdQue, prQueueEntry); + } else if (eFrameAction == FRAME_ACTION_TX_PKT) { + /* 4 <4> Send the command */ +#if CFG_SUPPORT_MULTITHREAD + rStatus = wlanSendCommandMthread(prAdapter, prCmdInfo); + + if (rStatus == WLAN_STATUS_RESOURCES) { + /* no more TC4 resource for further + * transmission + */ + DBGLOG(INIT, WARN, + "NO Res CMD TYPE[%u] ID[0x%02X] SEQ[%u]\n", + prCmdInfo->eCmdType, prCmdInfo->ucCID, + prCmdInfo->ucCmdSeqNum); + + prAdapter->u4HifDbgFlag |= DEG_HIF_ALL; + kalSetHifDbgEvent(prAdapter->prGlueInfo); + + QUEUE_INSERT_TAIL(prMergeCmdQue, prQueueEntry); + + /* + * We reserve one TC4 resource for CMD + * specially, only break checking the left tx + * request if no resource for true CMD. + */ + if ((prCmdInfo->eCmdType != + COMMAND_TYPE_SECURITY_FRAME) && + (prCmdInfo->eCmdType != + COMMAND_TYPE_MANAGEMENT_FRAME)) + break; + } else if (rStatus == WLAN_STATUS_PENDING) { + /* Do nothing */ + /* Do nothing */ + } else if (rStatus == WLAN_STATUS_SUCCESS) { + /* Do nothing */ + /* Do nothing */ + } else { + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) + prQueueEntry; + + if (prCmdInfo->fgIsOid) { + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4SetInfoLen, + rStatus); + } + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + +#else + rStatus = wlanSendCommand(prAdapter, prCmdInfo); + + if (rStatus == WLAN_STATUS_RESOURCES) { + /* no more TC4 resource for further + * transmission + */ + + DBGLOG(INIT, WARN, + "NO Resource for CMD TYPE[%u] ID[0x%02X] SEQ[%u]\n", + prCmdInfo->eCmdType, prCmdInfo->ucCID, + prCmdInfo->ucCmdSeqNum); + + 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 { + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) + 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); + } +#endif + } else { + ASSERT(0); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + + /* 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); + +#if CFG_SUPPORT_MULTITHREAD + kalSetTxCmdEvent2Hif(prAdapter->prGlueInfo); +#endif + + return WLAN_STATUS_SUCCESS; +} /* end of wlanProcessCommandQueue() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will take CMD_INFO_T which carry some information of + * incoming OID and notify the NIC_TX to send CMD. + * + * \param prAdapter Pointer of Adapter Data Structure + * \param prCmdInfo Pointer of P_CMD_INFO_T + * + * \retval WLAN_STATUS_SUCCESS : CMD was written to HIF and be freed(CMD Done) + * immediately. + * \retval WLAN_STATUS_RESOURCE : No resource for current command, need to wait + * for previous + * frame finishing their transmission. + * \retval WLAN_STATUS_FAILURE : Get failure while access HIF or been + * rejected. + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanSendCommand(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo) +{ + struct TX_CTRL *prTxCtrl; + uint8_t ucTC; /* "Traffic Class" SW(Driver) resource + * classification + */ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + prTxCtrl = &prAdapter->rTxCtrl; + + do { + /* <0> card removal check */ + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + rStatus = WLAN_STATUS_FAILURE; + break; + } + + /* <1.1> Assign Traffic Class(TC) */ + ucTC = nicTxGetCmdResourceType(prCmdInfo); + + /* <1.2> Check if pending packet or resource was exhausted */ + rStatus = nicTxAcquireResource(prAdapter, ucTC, + nicTxGetCmdPageCount(prAdapter, prCmdInfo), + TRUE); + if (rStatus == WLAN_STATUS_RESOURCES) { + DBGLOG(INIT, INFO, "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; + } + + } while (FALSE); + + return rStatus; +} /* end of wlanSendCommand() */ + +#if CFG_SUPPORT_MULTITHREAD + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will take CMD_INFO_T which carry some information of + * incoming OID and notify the NIC_TX to send CMD. + * + * \param prAdapter Pointer of Adapter Data Structure + * \param prCmdInfo Pointer of P_CMD_INFO_T + * + * \retval WLAN_STATUS_SUCCESS : CMD was written to HIF and be freed(CMD Done) + * immediately. + * \retval WLAN_STATUS_RESOURCE : No resource for current command, need to wait + * for previous + * frame finishing their transmission. + * \retval WLAN_STATUS_FAILURE : Get failure while access HIF or been + * rejected. + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanSendCommandMthread(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo) +{ + struct TX_CTRL *prTxCtrl; + uint8_t ucTC; /* "Traffic Class" SW(Driver) resource + * classification + */ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + prTxCtrl = &prAdapter->rTxCtrl; + + prTempCmdQue = &rTempCmdQue; + QUEUE_INITIALIZE(prTempCmdQue); + + do { + /* <0> card removal check */ + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + rStatus = WLAN_STATUS_FAILURE; + break; + } + /* <1> Normal case of sending CMD Packet */ + /* <1.1> Assign Traffic Class(TC) */ + ucTC = nicTxGetCmdResourceType(prCmdInfo); + + /* <1.2> Check if pending packet or resource was exhausted */ + rStatus = nicTxAcquireResource(prAdapter, ucTC, + nicTxGetCmdPageCount(prAdapter, prCmdInfo), + TRUE); + if (rStatus == WLAN_STATUS_RESOURCES) { +#if 0 + DBGLOG(INIT, WARN, + "%s: NO Resource for CMD TYPE[%u] ID[0x%02X] SEQ[%u] TC[%u]\n", + __func__, prCmdInfo->eCmdType, prCmdInfo->ucCID, + prCmdInfo->ucCmdSeqNum, ucTC); +#endif + break; + } + + /* Process to pending command queue firest */ + if ((!prCmdInfo->fgSetQuery) || (prCmdInfo->fgNeedResp)) { + /* command packet which needs further handling upon + * response + */ + /* + * KAL_ACQUIRE_SPIN_LOCK(prAdapter, + * SPIN_LOCK_CMD_PENDING); + * QUEUE_INSERT_TAIL(&(prAdapter->rPendingCmdQueue), + * (struct QUE_ENTRY *)prCmdInfo); + * KAL_RELEASE_SPIN_LOCK(prAdapter, + * SPIN_LOCK_CMD_PENDING); + */ + } + QUEUE_INSERT_TAIL(prTempCmdQue, + (struct QUE_ENTRY *) prCmdInfo); + + /* <1.4> Set Pending in response to Query Command/Need Response + */ + if (rStatus == WLAN_STATUS_SUCCESS) { + if ((!prCmdInfo->fgSetQuery) || + (prCmdInfo->fgNeedResp) || + (prCmdInfo->eCmdType == + COMMAND_TYPE_SECURITY_FRAME)) { + rStatus = WLAN_STATUS_PENDING; + } + } + } while (FALSE); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); + QUEUE_CONCATENATE_QUEUES(&(prAdapter->rTxCmdQueue), + prTempCmdQue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); + + return rStatus; +} /* end of wlanSendCommandMthread() */ + +void wlanTxCmdDoneCb(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo) +{ + + KAL_SPIN_LOCK_DECLARATION(); + + if ((!prCmdInfo->fgSetQuery) || (prCmdInfo->fgNeedResp)) { +#if 0 + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + QUEUE_INSERT_TAIL(&prAdapter->rPendingCmdQueue, + (struct QUE_ENTRY *) prCmdInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); +#endif + } else { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); + QUEUE_INSERT_TAIL(&prAdapter->rTxCmdDoneQueue, + (struct QUE_ENTRY *) prCmdInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); + } + + /* call tx thread to work */ + set_bit(GLUE_FLAG_TX_CMD_DONE_BIT, + &prAdapter->prGlueInfo->ulFlag); + wake_up_interruptible(&prAdapter->prGlueInfo->waitq); +} + +uint32_t wlanTxCmdMthread(IN struct ADAPTER *prAdapter) +{ + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue; + struct QUE rTempCmdDoneQue; + struct QUE *prTempCmdDoneQue; + struct QUE_ENTRY *prQueueEntry; + struct CMD_INFO *prCmdInfo; + /* P_CMD_ACCESS_REG prCmdAccessReg; + * P_CMD_ACCESS_REG prEventAccessReg; + * UINT_32 u4Address; + */ + uint32_t u4TxDoneQueueSize; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + if (halIsHifStateSuspend(prAdapter)) { + DBGLOG(TX, WARN, "Suspend TxCmdMthread\n"); + return WLAN_STATUS_SUCCESS; + } + + prTempCmdQue = &rTempCmdQue; + QUEUE_INITIALIZE(prTempCmdQue); + + prTempCmdDoneQue = &rTempCmdDoneQue; + QUEUE_INITIALIZE(prTempCmdDoneQue); + + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_TX_CMD_CLEAR); + + /* TX Command Queue */ + /* 4 <1> Move whole list of CMD_INFO to temp queue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, &prAdapter->rTxCmdQueue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); + + /* 4 <2> Dequeue from head and check it is able to be sent */ + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + prCmdInfo->pfHifTxCmdDoneCb = wlanTxCmdDoneCb; + + if ((!prCmdInfo->fgSetQuery) || (prCmdInfo->fgNeedResp)) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + QUEUE_INSERT_TAIL(&(prAdapter->rPendingCmdQueue), + (struct QUE_ENTRY *) prCmdInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + } else { + QUEUE_INSERT_TAIL(prTempCmdDoneQue, prQueueEntry); + } + + nicTxCmd(prAdapter, prCmdInfo, TC4_INDEX); + + /* DBGLOG(INIT, INFO, "==> TX CMD QID: %d (Q:%d)\n", + * prCmdInfo->ucCID, prTempCmdQue->u4NumElem)); + */ + + GLUE_DEC_REF_CNT(prAdapter->prGlueInfo->i4TxPendingCmdNum); + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); + QUEUE_CONCATENATE_QUEUES(&prAdapter->rTxCmdDoneQueue, + prTempCmdDoneQue); + u4TxDoneQueueSize = prAdapter->rTxCmdDoneQueue.u4NumElem; + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); + + KAL_RELEASE_MUTEX(prAdapter, MUTEX_TX_CMD_CLEAR); + + if (u4TxDoneQueueSize > 0) { + /* call tx thread to work */ + set_bit(GLUE_FLAG_TX_CMD_DONE_BIT, + &prAdapter->prGlueInfo->ulFlag); + wake_up_interruptible(&prAdapter->prGlueInfo->waitq); + } + + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanTxCmdDoneMthread(IN struct ADAPTER *prAdapter) +{ + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue; + struct QUE_ENTRY *prQueueEntry; + struct CMD_INFO *prCmdInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + if (halIsHifStateSuspend(prAdapter)) { + DBGLOG(TX, WARN, "Suspend TxCmdDoneMthread\n"); + return WLAN_STATUS_SUCCESS; + } + + prTempCmdQue = &rTempCmdQue; + QUEUE_INITIALIZE(prTempCmdQue); + + /* 4 <1> Move whole list of CMD_INFO to temp queue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, &prAdapter->rTxCmdDoneQueue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); + + /* 4 <2> Dequeue from head and check it is able to be sent */ + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + + if (prCmdInfo->pfCmdDoneHandler) + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, + prCmdInfo->pucInfoBuffer); + /* Not pending cmd, free it after TX succeed! */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to clear all commands in TX command queue + * \param prAdapter Pointer of Adapter Data Structure + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +void wlanClearTxCommandQueue(IN struct ADAPTER *prAdapter) +{ + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue = &rTempCmdQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + QUEUE_INITIALIZE(prTempCmdQue); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, &prAdapter->rTxCmdQueue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + + if (prCmdInfo->pfCmdTimeoutHandler) + prCmdInfo->pfCmdTimeoutHandler(prAdapter, prCmdInfo); + else + wlanReleaseCommand(prAdapter, prCmdInfo, + TX_RESULT_QUEUE_CLEARANCE); + + /* Release Tx resource for CMD which resource is allocated but + * not used + */ + nicTxReleaseResource_PSE(prAdapter, + nicTxGetCmdResourceType(prCmdInfo), + nicTxGetCmdPageCount(prAdapter, prCmdInfo), TRUE); + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to clear OID commands in TX command queue + * \param prAdapter Pointer of Adapter Data Structure + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +void wlanClearTxOidCommand(IN struct ADAPTER *prAdapter) +{ + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue = &rTempCmdQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + QUEUE_INITIALIZE(prTempCmdQue); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); + + QUEUE_MOVE_ALL(prTempCmdQue, &prAdapter->rTxCmdQueue); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + + if (prCmdInfo->fgIsOid) { + + if (prCmdInfo->pfCmdTimeoutHandler) + prCmdInfo->pfCmdTimeoutHandler(prAdapter, + prCmdInfo); + else + wlanReleaseCommand(prAdapter, prCmdInfo, + TX_RESULT_QUEUE_CLEARANCE); + + /* Release Tx resource for CMD which resource is + * allocated but not used + */ + nicTxReleaseResource_PSE(prAdapter, + nicTxGetCmdResourceType(prCmdInfo), + nicTxGetCmdPageCount(prAdapter, prCmdInfo), + TRUE); + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + } else { + QUEUE_INSERT_TAIL(&prAdapter->rTxCmdQueue, + prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to clear all commands in TX command done queue + * \param prAdapter Pointer of Adapter Data Structure + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +void wlanClearTxCommandDoneQueue(IN struct ADAPTER + *prAdapter) +{ + struct QUE rTempCmdDoneQue; + struct QUE *prTempCmdDoneQue = &rTempCmdDoneQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + QUEUE_INITIALIZE(prTempCmdDoneQue); + + /* 4 <1> Move whole list of CMD_INFO to temp queue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); + QUEUE_MOVE_ALL(prTempCmdDoneQue, + &prAdapter->rTxCmdDoneQueue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); + + /* 4 <2> Dequeue from head and check it is able to be sent */ + QUEUE_REMOVE_HEAD(prTempCmdDoneQue, prQueueEntry, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + + if (prCmdInfo->pfCmdDoneHandler) + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, + prCmdInfo->pucInfoBuffer); + /* Not pending cmd, free it after TX succeed! */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + QUEUE_REMOVE_HEAD(prTempCmdDoneQue, prQueueEntry, + struct QUE_ENTRY *); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to clear all buffer in port 0/1 queue + * \param prAdapter Pointer of Adapter Data Structure + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +void wlanClearDataQueue(IN struct ADAPTER *prAdapter) +{ + if (HAL_IS_TX_DIRECT()) + nicTxDirectClearHifQ(prAdapter); + else { +#if CFG_FIX_2_TX_PORT + struct QUE qDataPort0, qDataPort1; + struct QUE *prDataPort0, *prDataPort1; + struct MSDU_INFO *prMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + prDataPort0 = &qDataPort0; + prDataPort1 = &qDataPort1; + + QUEUE_INITIALIZE(prDataPort0); + QUEUE_INITIALIZE(prDataPort1); + + /* <1> Move whole list of CMD_INFO to temp queue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + QUEUE_MOVE_ALL(prDataPort0, &prAdapter->rTxP0Queue); + QUEUE_MOVE_ALL(prDataPort1, &prAdapter->rTxP1Queue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + + /* <2> Release Tx resource */ + nicTxReleaseMsduResource(prAdapter, + (struct MSDU_INFO *) QUEUE_GET_HEAD(prDataPort0)); + nicTxReleaseMsduResource(prAdapter, + (struct MSDU_INFO *) QUEUE_GET_HEAD(prDataPort1)); + + /* <3> Return sk buffer */ + nicTxReturnMsduInfo(prAdapter, (struct MSDU_INFO *) + QUEUE_GET_HEAD(prDataPort0)); + nicTxReturnMsduInfo(prAdapter, (struct MSDU_INFO *) + QUEUE_GET_HEAD(prDataPort1)); + + /* <4> Clear pending MSDU info in data done queue */ + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); + while (QUEUE_IS_NOT_EMPTY(&prAdapter->rTxDataDoneQueue)) { + QUEUE_REMOVE_HEAD(&prAdapter->rTxDataDoneQueue, + prMsduInfo, struct MSDU_INFO *); + + nicTxFreePacket(prAdapter, prMsduInfo, FALSE); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } + KAL_RELEASE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); +#else + + struct QUE qDataPort[TX_PORT_NUM]; + struct QUE *prDataPort[TX_PORT_NUM]; + struct MSDU_INFO *prMsduInfo; + int32_t i; + + KAL_SPIN_LOCK_DECLARATION(); + + for (i = 0; i < TX_PORT_NUM; i++) { + prDataPort[i] = &qDataPort[i]; + QUEUE_INITIALIZE(prDataPort[i]); + } + + /* <1> Move whole list of CMD_INFO to temp queue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + for (i = 0; i < TX_PORT_NUM; i++) + QUEUE_MOVE_ALL(prDataPort[i], &prAdapter->rTxPQueue[i]); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + + /* <2> Return sk buffer */ + for (i = 0; i < TX_PORT_NUM; i++) { + nicTxReleaseMsduResource(prAdapter, (struct MSDU_INFO *) + QUEUE_GET_HEAD(prDataPort[i])); + nicTxReturnMsduInfo(prAdapter, (struct MSDU_INFO *) + QUEUE_GET_HEAD(prDataPort[i])); + } + + /* <3> Clear pending MSDU info in data done queue */ + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); + while (QUEUE_IS_NOT_EMPTY(&prAdapter->rTxDataDoneQueue)) { + QUEUE_REMOVE_HEAD(&prAdapter->rTxDataDoneQueue, + prMsduInfo, struct MSDU_INFO *); + + nicTxFreePacket(prAdapter, prMsduInfo, FALSE); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } + KAL_RELEASE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); +#endif + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to clear all buffer in port 0/1 queue + * \param prAdapter Pointer of Adapter Data Structure + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +void wlanClearRxToOsQueue(IN struct ADAPTER *prAdapter) +{ + struct QUE rTempRxQue; + struct QUE *prTempRxQue = &rTempRxQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + QUEUE_INITIALIZE(prTempRxQue); + + /* 4 <1> Move whole list of CMD_INFO to temp queue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); + QUEUE_MOVE_ALL(prTempRxQue, &prAdapter->rRxQueue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); + + /* 4 <2> Remove all skbuf */ + QUEUE_REMOVE_HEAD(prTempRxQue, prQueueEntry, + struct QUE_ENTRY *); + while (prQueueEntry) { + kalRxIndicateOnePkt(prAdapter->prGlueInfo, + (void *) GLUE_GET_PKT_DESCRIPTOR(prQueueEntry)); + QUEUE_REMOVE_HEAD(prTempRxQue, prQueueEntry, + struct QUE_ENTRY *); + } + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + * \param rTxDoneStatus Tx done status + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void wlanReleaseCommand(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + struct TX_CTRL *prTxCtrl; + struct MSDU_INFO *prMsduInfo; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prTxCtrl = &prAdapter->rTxCtrl; + + switch (prCmdInfo->eCmdType) { + case COMMAND_TYPE_GENERAL_IOCTL: + case COMMAND_TYPE_NETWORK_IOCTL: + DBGLOG(INIT, INFO, + "Free CMD: ID[0x%x] SeqNum[%u] OID[%u]\n", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum, + prCmdInfo->fgIsOid); + + if (prCmdInfo->fgIsOid) { + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4SetInfoLen, + WLAN_STATUS_FAILURE); + } + break; + + case COMMAND_TYPE_SECURITY_FRAME: + case COMMAND_TYPE_MANAGEMENT_FRAME: + prMsduInfo = prCmdInfo->prMsduInfo; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) { + kalSecurityFrameSendComplete(prAdapter->prGlueInfo, + prCmdInfo->prPacket, + WLAN_STATUS_FAILURE); + /* Avoid skb multiple free */ + prMsduInfo->prPacket = NULL; + } + + DBGLOG(INIT, INFO, + "Free %s Frame: BSS[%u] WIDX:PID[%u:%u] SEQ[%u] STA[%u] RSP[%u] CMDSeq[%u]\n", + prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME ? + "SEC" : "MGMT", + prMsduInfo->ucBssIndex, + prMsduInfo->ucWlanIndex, + prMsduInfo->ucPID, + prMsduInfo->ucTxSeqNum, + prMsduInfo->ucStaRecIndex, + prMsduInfo->pfTxDoneHandler ? TRUE : FALSE, + prCmdInfo->ucCmdSeqNum); + + /* invoke callbacks */ + if (prMsduInfo->pfTxDoneHandler != NULL) + prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, + rTxDoneStatus); + + if (prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) + GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum); + + cnmMgtPktFree(prAdapter, prMsduInfo); + break; + + default: + ASSERT(0); + break; + } + +} /* 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 struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr) +{ + struct QUE *prCmdQue; + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue = &rTempCmdQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("wlanReleasePendingOid"); + + ASSERT(prAdapter); + + do { + if (ulParamPtr == 1) + break; + + prAdapter->ucOidTimeoutCount++; + if (prAdapter->ucOidTimeoutCount >= + WLAN_OID_NO_ACK_THRESHOLD) { + if (!prAdapter->fgIsChipNoAck) { + DBGLOG(INIT, WARN, + "No response from chip for %u times, set NoAck flag!\n", + prAdapter->ucOidTimeoutCount); +#if 0 + glGetRstReason(RST_OID_TIMEOUT); + GL_RESET_TRIGGER(prAdapter, + RST_FLAG_CHIP_RESET); +#endif + } + + if (prAdapter->ucOidTimeoutCount >= + WLAN_OID_NO_ACK_THRESHOLD) { + if (!prAdapter->fgIsChipNoAck) { + DBGLOG(INIT, WARN, + "No response from chip for %u times, set NoAck flag!\n", + prAdapter->ucOidTimeoutCount); + } + + prAdapter->fgIsChipNoAck = TRUE; + } + + prAdapter->u4HifDbgFlag |= DEG_HIF_ALL; + kalSetHifDbgEvent(prAdapter->prGlueInfo); + } + } while (FALSE); + + do { +#if CFG_SUPPORT_MULTITHREAD + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_TX_CMD_CLEAR); +#endif + /* 1: Clear pending OID in glue layer command queue */ + kalOidCmdClearance(prAdapter->prGlueInfo); + +#if CFG_SUPPORT_MULTITHREAD + /* Clear pending OID in main_thread to hif_thread command queue + */ + wlanClearTxOidCommand(prAdapter); +#endif + + /* 2: 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, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + + if (prCmdInfo->fgIsOid) { + DBGLOG(OID, INFO, + "Clear pending OID CMD ID[0x%02X] SEQ[%u] buf[0x%p]\n", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum, + prCmdInfo->pucInfoBuffer); + + if (prCmdInfo->pfCmdTimeoutHandler) { + prCmdInfo->pfCmdTimeoutHandler( + prAdapter, prCmdInfo); + } else { + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + 0, WLAN_STATUS_FAILURE); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_CMD_PENDING); + nicTxCancelSendingCmd(prAdapter, prCmdInfo); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, + SPIN_LOCK_CMD_PENDING); + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } else { + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + + /* 3: Clear pending OID queued in pvOidEntry with REQ_FLAG_OID + * set + */ + kalOidClearance(prAdapter->prGlueInfo); + +#if CFG_SUPPORT_MULTITHREAD + KAL_RELEASE_MUTEX(prAdapter, MUTEX_TX_CMD_CLEAR); +#endif + } while (FALSE); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will search the CMD Queue to look for the pending + * CMD/OID for specific + * NETWORK TYPE and compelete it immediately when system request a reset. + * + * \param prAdapter ointer of Adapter Data Structure + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void wlanReleasePendingCMDbyBssIdx(IN struct ADAPTER + *prAdapter, IN uint8_t ucBssIndex) +{ +#if 0 + struct QUE *prCmdQue; + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue = &rTempCmdQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) 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, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + + DBGLOG(P2P, TRACE, "Pending CMD for BSS:%d\n", + prCmdInfo->ucBssIndex); + + if (prCmdInfo->ucBssIndex == ucBssIndex) { + if (prCmdInfo->pfCmdTimeoutHandler) { + prCmdInfo->pfCmdTimeoutHandler( + prAdapter, prCmdInfo); + } else if (prCmdInfo->fgIsOid) { + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + 0, WLAN_STATUS_FAILURE); + } + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } else { + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + + } while (FALSE); +#endif + + +} /* wlanReleasePendingCMDbyBssIdx */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Return the indicated packet buffer and reallocate one to the RFB + * + * \param prAdapter Pointer of Adapter Data Structure + * \param pvPacket Pointer of returned packet + * + * \retval WLAN_STATUS_SUCCESS: Success + * \retval WLAN_STATUS_FAILURE: Failed + */ +/*----------------------------------------------------------------------------*/ +void wlanReturnPacketDelaySetupTimeout(IN struct ADAPTER + *prAdapter, IN unsigned long ulParamPtr) +{ + struct RX_CTRL *prRxCtrl; + struct SW_RFB *prSwRfb = NULL; + + KAL_SPIN_LOCK_DECLARATION(); + uint32_t status = WLAN_STATUS_SUCCESS; + struct QUE *prQueList; + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + prQueList = &prRxCtrl->rIndicatedRfbList; + DBGLOG(RX, WARN, "%s: IndicatedRfbList num = %u\n", + __func__, prQueList->u4NumElem); + + while (QUEUE_IS_NOT_EMPTY(&prRxCtrl->rIndicatedRfbList)) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rIndicatedRfbList, prSwRfb, + struct SW_RFB *); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + status = nicRxSetupRFB(prAdapter, prSwRfb); + nicRxReturnRFB(prAdapter, prSwRfb); + + if (status != WLAN_STATUS_SUCCESS) + break; + } + + if (status != WLAN_STATUS_SUCCESS) { + DBGLOG(RX, WARN, "Restart ReturnIndicatedRfb Timer (%u)\n", + RX_RETURN_INDICATED_RFB_TIMEOUT_SEC); + /* restart timer */ + cnmTimerStartTimer(prAdapter, + &prAdapter->rPacketDelaySetupTimer, + SEC_TO_MSEC(RX_RETURN_INDICATED_RFB_TIMEOUT_SEC)); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct ADAPTER *prAdapter, + IN void *pvPacket) +{ + struct RX_CTRL *prRxCtrl; + struct SW_RFB *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)) { + /*Todo:: nothing */ + /*Todo:: nothing */ + } +#endif + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rIndicatedRfbList, prSwRfb, + struct SW_RFB *); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + if (!prSwRfb) { + DBGLOG(RX, WARN, "No free SwRfb!\n"); + return; + } + + if (nicRxSetupRFB(prAdapter, prSwRfb)) { + DBGLOG(RX, WARN, + "Cannot allocate packet buffer for SwRfb!\n"); + if (!timerPendingTimer( + &prAdapter->rPacketDelaySetupTimer)) { + DBGLOG(RX, WARN, + "Start ReturnIndicatedRfb Timer (%u)\n", + RX_RETURN_INDICATED_RFB_TIMEOUT_SEC); + cnmTimerStartTimer(prAdapter, + &prAdapter->rPacketDelaySetupTimer, + SEC_TO_MSEC(RX_RETURN_INDICATED_RFB_TIMEOUT_SEC)); + } + } + 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. + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanQueryInformation(IN struct ADAPTER *prAdapter, + IN PFN_OID_HANDLER_FUNC pfnOidQryHandler, + IN void *pvInfoBuf, IN uint32_t u4InfoBufLen, + OUT uint32_t *pu4QryInfoLen) +{ + uint32_t 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)) { + /* note: return WLAN_STATUS_FAILURE or + * WLAN_STATUS_SUCCESS for blocking OIDs during current + * measurement ?? + */ + return WLAN_STATUS_SUCCESS; + } +#if 1 + /* most OID handler will just queue a command packet */ + status = pfnOidQryHandler(prAdapter, pvInfoBuf, + u4InfoBufLen, pu4QryInfoLen); +#else + if (wlanIsHandlerNeedHwAccess(pfnOidQryHandler, FALSE)) { + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + /* Reset sleepy state */ + if (prAdapter->fgWiFiInSleepyState == TRUE) + prAdapter->fgWiFiInSleepyState = FALSE; + + status = pfnOidQryHandler(prAdapter, pvInfoBuf, + u4InfoBufLen, pu4QryInfoLen); + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + } else + status = pfnOidQryHandler(prAdapter, pvInfoBuf, + u4InfoBufLen, pu4QryInfoLen); +#endif + + return status; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is a required function that allows bound protocol + * drivers, or NDIS, to request changes in the state information that + * the miniport maintains for particular object identifiers, such as + * changes in multicast addresses. + * + * \param[IN] prAdapter Pointer to the Glue info structure. + * \param[IN] pfnOidSetHandler Points to the OID set handlers. + * \param[IN] pvInfoBuf Points to a buffer containing the OID-specific data + * for the set. + * \param[IN] u4InfoBufLen Specifies the number of bytes at prSetBuffer. + * \param[OUT] pu4SetInfoLen Points to the number of bytes it read or is needed. + * + * \retval WLAN_STATUS_xxx Different WLAN_STATUS code returned by different + * handlers. + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanSetInformation(IN struct ADAPTER *prAdapter, + IN PFN_OID_HANDLER_FUNC pfnOidSetHandler, + IN void *pvInfoBuf, IN uint32_t u4InfoBufLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t 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)) { + /* note: return WLAN_STATUS_FAILURE or WLAN_STATUS_SUCCESS + * for blocking OIDs during current measurement ?? + */ + return WLAN_STATUS_SUCCESS; + } +#if 1 + /* most OID handler will just queue a command packet + * for power state transition OIDs, handler will acquire power control + * by itself + */ + status = pfnOidSetHandler(prAdapter, pvInfoBuf, + u4InfoBufLen, pu4SetInfoLen); +#else + if (wlanIsHandlerNeedHwAccess(pfnOidSetHandler, TRUE)) { + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + /* Reset sleepy state */ + if (prAdapter->fgWiFiInSleepyState == TRUE) + prAdapter->fgWiFiInSleepyState = FALSE; + + status = pfnOidSetHandler(prAdapter, pvInfoBuf, + u4InfoBufLen, pu4SetInfoLen); + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + } else { + status = pfnOidSetHandler(prAdapter, pvInfoBuf, + u4InfoBufLen, pu4SetInfoLen); + } +#endif + + return status; +} + +#if CFG_SUPPORT_WAPI +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is a used to query driver's config wapi mode or not + * + * \param[IN] prAdapter Pointer to the Glue info structure. + * + * \retval TRUE for use wapi mode + * + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wlanQueryWapiMode(IN struct ADAPTER *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 struct ADAPTER *prAdapter, + IN u_int8_t 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 struct ADAPTER *prAdapter, + IN u_int8_t fgEnableBroadcast) +{ + ASSERT(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is called to send out CMD_ID_DUMMY command packet + * + * \param[IN] prAdapter Pointer to the Adapter structure. + * + * \return WLAN_STATUS_SUCCESS + * \return WLAN_STATUS_FAILURE + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanSendDummyCmd(IN struct ADAPTER *prAdapter, + IN u_int8_t fgIsReqTxRsrc) +{ + uint32_t status = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + struct WIFI_CMD *prWifiCmd; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = (uint16_t) CMD_HDR_SIZE; + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->pfCmdTimeoutHandler = NULL; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_DUMMY_RSV; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->ucCmdSeqNum = 0; + prCmdInfo->u4SetInfoLen = 0; + + prWifiCmd = (struct WIFI_CMD *) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + if (fgIsReqTxRsrc) { + if (wlanSendCommand(prAdapter, + prCmdInfo) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "Fail to transmit CMD_ID_DUMMY command\n"); + status = WLAN_STATUS_FAILURE; + } + } else { + if (nicTxCmd(prAdapter, prCmdInfo, + TC4_INDEX) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "Fail to transmit CMD_ID_DUMMY command\n"); + status = WLAN_STATUS_FAILURE; + } + } + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanSendNicPowerCtrlCmd(IN struct ADAPTER + *prAdapter, IN uint8_t ucPowerMode) +{ + uint32_t status = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + struct WIFI_CMD *prWifiCmd; + uint8_t ucTC, ucCmdSeqNum; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + + /* 1. Prepare CMD */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + + sizeof(struct CMD_NIC_POWER_CTRL))); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); +#if CFG_ENABLE_KEYWORD_EXCEPTION_MECHANISM + mtk_wcn_wmt_assert_keyword(WMTDRV_TYPE_WIFI, + "[Wi-Fi Off] Allocate CMD_INFO_T ==> FAILED."); +#endif + 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 = (uint16_t) (CMD_HDR_SIZE + sizeof( + struct CMD_NIC_POWER_CTRL)); + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->pfCmdTimeoutHandler = NULL; + prCmdInfo->fgIsOid = g_fgIsOid; + prCmdInfo->ucCID = CMD_ID_NIC_POWER_CTRL; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(struct CMD_NIC_POWER_CTRL); + + /* 2.3 Setup WIFI_CMD_T */ + prWifiCmd = (struct WIFI_CMD *) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + kalMemZero(prWifiCmd->aucBuffer, + sizeof(struct CMD_NIC_POWER_CTRL)); + ((struct 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, + nicTxGetCmdPageCount(prAdapter, prCmdInfo), TRUE) + == 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; + prAdapter->fgIsChipNoAck = TRUE; + break; + } + continue; + } + break; + }; + + /* 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"); +#if CFG_ENABLE_KEYWORD_EXCEPTION_MECHANISM + mtk_wcn_wmt_assert_keyword(WMTDRV_TYPE_WIFI, + "[Wi-Fi Off] Fail to transmit CMD_NIC_POWER_CTRL command"); +#endif + status = WLAN_STATUS_FAILURE; + } + + /* 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) + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wlanIsHandlerAllowedInRFTest(IN PFN_OID_HANDLER_FUNC pfnOidHandler, + IN u_int8_t fgSetInfo) +{ + PFN_OID_HANDLER_FUNC *apfnOidHandlerAllowedInRFTest; + uint32_t i; + uint32_t 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; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to get the chip information + * + * @param prAdapter Pointer to the Adapter structure. + * + * @return + */ +/*----------------------------------------------------------------------------*/ + +uint32_t wlanSetChipEcoInfo(IN struct ADAPTER *prAdapter) +{ + uint32_t hw_version, sw_version = 0; + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + uint32_t chip_id = prChipInfo->chip_id; + /* WLAN_STATUS status; */ + uint32_t u4Status = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanSetChipEcoInfo.\n"); + + if (wlanAccessRegister(prAdapter, TOP_HVR, &hw_version, 0, 0) != + WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "wlanSetChipEcoInfo >> get TOP_HVR failed.\n"); + u4Status = WLAN_STATUS_FAILURE; + } else if (wlanAccessRegister(prAdapter, TOP_FVR, &sw_version, 0, 0) != + WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "wlanSetChipEcoInfo >> get TOP_FVR failed.\n"); + u4Status = WLAN_STATUS_FAILURE; + } else { + /* success */ + nicSetChipHwVer((uint8_t)(GET_HW_VER(hw_version) & 0xFF)); + nicSetChipFactoryVer((uint8_t)((GET_HW_VER(hw_version) >> 8) & + 0xF)); + nicSetChipSwVer((uint8_t)GET_FW_VER(sw_version)); + + /* Assign current chip version */ + prAdapter->chip_info->eco_ver = nicGetChipEcoVer(prAdapter); + } + + DBGLOG(INIT, INFO, + "Chip ID[%04X] Version[E%u] HW[0x%08x] SW[0x%08x]\n", + chip_id, prAdapter->chip_info->eco_ver, hw_version, + sw_version); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to read/write a certain N9 + * register by inband command in blocking mode in ROM code stage + * + * @param prAdapter Pointer to the Adapter structure. + * u4DestAddr Address of destination address + * u4ImgSecSize Length of the firmware block + * fgReset should be set to TRUE if this is the 1st configuration + * + * @return WLAN_STATUS_SUCCESS + * WLAN_STATUS_FAILURE + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanAccessRegister(IN struct ADAPTER *prAdapter, + IN uint32_t u4Addr, IN uint32_t *pru4Result, + IN uint32_t u4Data, + IN uint8_t ucSetQuery) +{ + struct mt66xx_chip_info *prChipInfo; + struct CMD_INFO *prCmdInfo; + struct INIT_HIF_TX_HEADER *prInitHifTxHeader; + struct INIT_WIFI_EVENT *prInitEvent; + struct INIT_CMD_ACCESS_REG *prInitCmdAccessReg; + struct INIT_EVENT_ACCESS_REG *prInitEventAccessReg; + uint8_t ucTC, ucCmdSeqNum; + uint16_t cmd_size; + uint8_t *aucBuffer; + uint32_t u4EventSize; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + DEBUGFUNC("wlanAccessRegister"); + + /* 1. Allocate CMD Info Packet and its Buffer. */ + cmd_size = sizeof(struct INIT_HIF_TX_HEADER) + sizeof( + struct INIT_CMD_ACCESS_REG); + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, cmd_size); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + u4EventSize = prChipInfo->rxd_size + prChipInfo->init_event_size + + sizeof(struct INIT_EVENT_ACCESS_REG); + aucBuffer = kalMemAlloc(u4EventSize, PHY_MEM_TYPE); + + prCmdInfo->u2InfoBufLen = cmd_size; + +#if (CFG_USE_TC4_RESOURCE_FOR_INIT_CMD == 1) + /* 2. Use TC4's resource to download image. (TC4 as CPU) */ + ucTC = TC4_INDEX; +#else + /* 2. Use TC0's resource to download image. + * Only TC0 is allowed because SDIO HW always reports + * MCU's TXQ_CNT at TXQ0_CNT in CR4 architecutre) + */ + ucTC = TC0_INDEX; +#endif + + /* 3. increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* 4. Setup common CMD Info Packet */ + prInitHifTxHeader = (struct INIT_HIF_TX_HEADER *) ( + prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prInitHifTxHeader->u2PQ_ID = INIT_CMD_PQ_ID; + prInitHifTxHeader->ucHeaderFormat = INIT_CMD_PACKET_TYPE_ID; + prInitHifTxHeader->ucPktFt = INIT_PKT_FT_CMD; + + prInitHifTxHeader->rInitWifiCmd.ucCID = + INIT_CMD_ID_ACCESS_REG; + + prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = + INIT_CMD_PACKET_TYPE_ID; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + /* 5. Setup CMD_ACCESS_REG */ + prInitCmdAccessReg = (struct INIT_CMD_ACCESS_REG *) ( + prInitHifTxHeader->rInitWifiCmd.aucBuffer); + prInitCmdAccessReg->ucSetQuery = ucSetQuery; + prInitCmdAccessReg->u4Address = u4Addr; + prInitCmdAccessReg->u4Data = u4Data; + + /* 6. Send CMD_ACCESS_REG command */ + while (1) { + /* 6.1 Acquire TX Resource */ + if (nicTxAcquireResource + (prAdapter, ucTC, nicTxGetPageCount(prAdapter, + prCmdInfo->u2InfoBufLen, TRUE), TRUE) + == 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"); + goto exit; + } + continue; + } + + /* 6.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo, + prChipInfo->u2TxInitCmdPort) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "Fail to transmit image download command\n"); + goto exit; + } + + break; + }; + + /* 7. Wait for INIT_EVENT_ID_CMD_RESULT */ + u4Status = wlanAccessRegisterStatus(prAdapter, ucCmdSeqNum, ucSetQuery, + aucBuffer, u4EventSize); + if (ucSetQuery == 0) { + prInitEvent = (struct INIT_WIFI_EVENT *) + (aucBuffer + prChipInfo->rxd_size); + prInitEventAccessReg = (struct INIT_EVENT_ACCESS_REG *) + prInitEvent->aucBuffer; + + if (prInitEventAccessReg->u4Address != u4Addr) { + DBGLOG(INIT, ERROR, + "Event reports address incorrect. 0x%08x, 0x%08x.\n", + u4Addr, prInitEventAccessReg->u4Address); + u4Status = WLAN_STATUS_FAILURE; + } + *pru4Result = prInitEventAccessReg->u4Data; + } + +exit: + /* 8. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to get the response of INIT_CMD_ACCESS_REG +* +* @param prAdapter Pointer to the Adapter structure. +* ucCmdSeqNum Sequence number of previous firmware scatter +* ucSetQuery Read or write +* prEvent the pointer of buffer to store the response +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +uint32_t wlanAccessRegisterStatus(IN struct ADAPTER *prAdapter, + IN uint8_t ucCmdSeqNum, + IN uint8_t ucSetQuery, IN void *prEvent, + IN uint32_t u4EventLen) +{ + struct mt66xx_chip_info *prChipInfo; + struct INIT_WIFI_EVENT *prInitEvent; + uint32_t u4RxPktLength; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + uint8_t ucPortIdx = IMG_DL_STATUS_PORT_IDX; + struct HW_MAC_RX_DESC *prRxStatus; + uint8_t ucUnexpectCnt = 0; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + while (TRUE) { + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + break; + } else if (nicRxWaitResponse(prAdapter, ucPortIdx, prEvent, + u4EventLen, &u4RxPktLength) != WLAN_STATUS_SUCCESS) { + GL_RESET_TRIGGER(prAdapter, + RST_FLAG_DO_CORE_DUMP | + RST_FLAG_PREVENT_POWER_OFF); + u4Status = WLAN_STATUS_FAILURE; + break; + } else { + /* header checking .. */ + prRxStatus = (struct HW_MAC_RX_DESC *) prEvent; + if (prRxStatus->u2PktTYpe != + RXM_RXD_PKT_TYPE_SW_EVENT) { + DBGLOG(INIT, ERROR, + "%s: skip unexpected Rx pkt type[0x%04x]\n", + __func__, prRxStatus->u2PktTYpe); + + ucUnexpectCnt++; + + if (ucUnexpectCnt > 5) { + DBGLOG(INIT, WARN, + "%s: break since ucUnexpectCnt > %d\n", + __func__, ucUnexpectCnt); + u4Status = WLAN_STATUS_FAILURE; + break; + } + continue; + } + + prInitEvent = (struct INIT_WIFI_EVENT *) + (prEvent + prChipInfo->rxd_size); + + /* EID / SeqNum check */ + if (((prInitEvent->ucEID != INIT_EVENT_ID_CMD_RESULT) && + (ucSetQuery == 1)) || + ((prInitEvent->ucEID != INIT_EVENT_ID_ACCESS_REG) + && (ucSetQuery == 0))) { + GL_RESET_TRIGGER(prAdapter, + RST_FLAG_DO_CORE_DUMP | + RST_FLAG_PREVENT_POWER_OFF); + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "wlanAccessRegisterStatus: incorrect ucEID. ucSetQuery = 0x%x\n", + ucSetQuery); + break; + } else if (prInitEvent->ucSeqNum != ucCmdSeqNum) { + u4Status = WLAN_STATUS_FAILURE; + GL_RESET_TRIGGER(prAdapter, + RST_FLAG_DO_CORE_DUMP | + RST_FLAG_PREVENT_POWER_OFF); + DBGLOG(INIT, ERROR, + "wlanAccessRegisterStatus: incorrect ucCmdSeqNum. = 0x%x\n", + ucCmdSeqNum); + break; + } else { + break; + } + } + } + + return u4Status; +} +/*----------------------------------------------------------------------------*/ +/*! + * @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) + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanProcessQueuedSwRfb(IN struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfbListHead) +{ + struct SW_RFB *prSwRfb, *prNextSwRfb; + struct TX_CTRL *prTxCtrl; + struct RX_CTRL *prRxCtrl; + struct STA_RECORD *prStaRec; + + ASSERT(prAdapter); + ASSERT(prSwRfbListHead); + + prTxCtrl = &prAdapter->rTxCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + + prSwRfb = prSwRfbListHead; + + do { + /* save next first */ + prNextSwRfb = (struct SW_RFB *) QUEUE_GET_NEXT_ENTRY(( + struct QUE_ENTRY *) prSwRfb); + + switch (prSwRfb->eDst) { + case RX_PKT_DESTINATION_HOST: + prStaRec = cnmGetStaRecByIndex(prAdapter, + prSwRfb->ucStaRecIdx); + if (prStaRec && IS_STA_IN_AIS(prStaRec)) { +#if ARP_MONITER_ENABLE + qmHandleRxArpPackets(prAdapter, prSwRfb); +#endif + } + + 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) + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanProcessQueuedMsduInfo(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wlanoidTimeoutCheck(IN struct ADAPTER *prAdapter, + IN PFN_OID_HANDLER_FUNC pfnOidHandler) +{ + PFN_OID_HANDLER_FUNC *apfnOidHandlerWOTimeoutCheck; + uint32_t i; + uint32_t u4NumOfElem; + uint32_t u4OidTimeout; + + apfnOidHandlerWOTimeoutCheck = apfnOidWOTimeoutCheck; + u4NumOfElem = sizeof(apfnOidWOTimeoutCheck) / sizeof( + PFN_OID_HANDLER_FUNC); + + for (i = 0; i < u4NumOfElem; i++) { + if (apfnOidHandlerWOTimeoutCheck[i] == pfnOidHandler) + return FALSE; + } + + /* Decrease OID timeout threshold if chip NoAck/resetting */ + if (wlanIsChipNoAck(prAdapter)) { + u4OidTimeout = WLAN_OID_TIMEOUT_THRESHOLD_IN_RESETTING; + DBGLOG(INIT, INFO, + "Decrease OID timeout to %ums due to NoACK/CHIP-RESET\n", + u4OidTimeout); + } else { + u4OidTimeout = WLAN_OID_TIMEOUT_THRESHOLD; + } + + /* Set OID timer for timeout check */ + cnmTimerStartTimer(prAdapter, + &(prAdapter->rOidTimeoutTimer), u4OidTimeout); + + 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 struct ADAPTER *prAdapter) +{ + ASSERT(prAdapter); + + cnmTimerStopTimer(prAdapter, &(prAdapter->rOidTimeoutTimer)); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to override network address + * if NVRAM has a valid value + * + * @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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanUpdateNetworkAddress(IN struct ADAPTER + *prAdapter) +{ + const uint8_t aucZeroMacAddr[] = NULL_MAC_ADDR; + uint8_t rMacAddr[PARAM_MAC_ADDR_LEN]; + uint32_t u4SysTime; + + DEBUGFUNC("wlanUpdateNetworkAddress"); + + ASSERT(prAdapter); + + if (kalRetrieveNetworkAddress(prAdapter->prGlueInfo, + rMacAddr) == FALSE + || IS_BMCAST_MAC_ADDR(rMacAddr) + || EQUAL_MAC_ADDR(aucZeroMacAddr, rMacAddr)) { + /* eFUSE has a valid address, don't do anything */ + if (prAdapter->fgIsEmbbededMacAddrValid == TRUE) { +#if CFG_SHOW_MACADDR_SOURCE + DBGLOG(INIT, INFO, "Using embedded MAC address"); +#endif + return WLAN_STATUS_SUCCESS; + } +#if CFG_SHOW_MACADDR_SOURCE + DBGLOG(INIT, INFO, + "Using dynamically generated MAC address"); +#endif + /* dynamic generate */ + u4SysTime = (uint32_t) 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 + } + + COPY_MAC_ADDR(prAdapter->rWifiVar.aucMacAddress, rMacAddr); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to update basic configuration into 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanUpdateBasicConfig(IN struct ADAPTER *prAdapter) +{ + uint8_t ucCmdSeqNum; + struct CMD_INFO *prCmdInfo; + struct WIFI_CMD *prWifiCmd; + struct CMD_BASIC_CONFIG *prCmdBasicConfig; + struct PSE_CMD_HDR *prPseCmdHdr; + uint32_t rResult; + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; + + DEBUGFUNC("wlanUpdateBasicConfig"); + + ASSERT(prAdapter); + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + CMD_HDR_SIZE + sizeof(struct 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( + struct 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->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(struct CMD_BASIC_CONFIG); + + /* Setup WIFI_CMD_T */ + prWifiCmd = (struct WIFI_CMD *) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prPseCmdHdr = (struct PSE_CMD_HDR *) ( + prCmdInfo->pucInfoBuffer); + prPseCmdHdr->u2Qidx = TXD_Q_IDX_MCU_RQ0; + prPseCmdHdr->u2Pidx = TXD_P_IDX_MCU; + prPseCmdHdr->u2Hf = TXD_HF_CMD; + prPseCmdHdr->u2Ft = TXD_FT_LONG_FORMAT; + prPseCmdHdr->u2PktFt = TXD_PKT_FT_CMD; + + prWifiCmd->u2Length = prWifiCmd->u2TxByteCount - sizeof( + struct PSE_CMD_HDR); + + /* configure CMD_BASIC_CONFIG */ + + prCmdBasicConfig = (struct CMD_BASIC_CONFIG *) ( + prWifiCmd->aucBuffer); + kalMemZero(prCmdBasicConfig, + sizeof(struct CMD_BASIC_CONFIG)); + prCmdBasicConfig->ucNative80211 = 0; + prCmdBasicConfig->rCsumOffload.u2RxChecksum = 0; + prCmdBasicConfig->rCsumOffload.u2TxChecksum = 0; + prCmdBasicConfig->ucCtrlFlagAssertPath = + prWifiVar->ucCtrlFlagAssertPath; + prCmdBasicConfig->ucCtrlFlagDebugLevel = + prWifiVar->ucCtrlFlagDebugLevel; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + if (prAdapter->fgIsSupportCsumOffload) { + 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 + + rResult = wlanSendCommand(prAdapter, prCmdInfo); + + if (rResult != WLAN_STATUS_SUCCESS) { + kalEnqueueCommand(prAdapter->prGlueInfo, + (struct QUE_ENTRY *) prCmdInfo); + + return WLAN_STATUS_PENDING; + } + 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wlanQueryTestMode(IN struct ADAPTER *prAdapter) +{ + ASSERT(prAdapter); + + return prAdapter->fgTestMode; +} + +u_int8_t wlanProcessTxFrame(IN struct ADAPTER *prAdapter, + IN void *prPacket) +{ + uint32_t u4SysTime; + uint8_t ucMacHeaderLen; + struct TX_PACKET_INFO rTxPacketInfo; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + ASSERT(prPacket); + prChipInfo = prAdapter->chip_info; + + if (kalQoSFrameClassifierAndPacketInfo( + prAdapter->prGlueInfo, prPacket, &rTxPacketInfo)) { + + /* Save the value of Priority Parameter */ + GLUE_SET_PKT_TID(prPacket, rTxPacketInfo.ucPriorityParam); + + if (rTxPacketInfo.u2Flag) { + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_1X)) { + struct STA_RECORD *prStaRec; + + DBGLOG(RSN, INFO, "T1X len=%d\n", + rTxPacketInfo.u4PacketLen); + + prStaRec = cnmGetStaRecByAddress(prAdapter, + GLUE_GET_PKT_BSS_IDX(prPacket), + rTxPacketInfo.aucEthDestAddr); + + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_1X); + /* + * if (secIsProtected1xFrame(prAdapter, + * prStaRec) && + * !kalIs24Of4Packet(prPacket)) + * GLUE_SET_PKT_FLAG(prPacket, + * ENUM_PKT_PROTECTED_1X); + */ + } + + if (rTxPacketInfo.u2Flag & + BIT(ENUM_PKT_NON_PROTECTED_1X)) + GLUE_SET_PKT_FLAG(prPacket, + ENUM_PKT_NON_PROTECTED_1X); + + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_802_3)) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_802_3); + + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_VLAN_EXIST) + && FEAT_SUP_LLC_VLAN_TX(prChipInfo)) + GLUE_SET_PKT_FLAG(prPacket, + ENUM_PKT_VLAN_EXIST); + + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_DHCP)) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_DHCP); + + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_ARP)) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_ARP); + + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_ICMP)) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_ICMP); + + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_TDLS)) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_TDLS); + + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_DNS)) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_DNS); + + } + + ucMacHeaderLen = ETHER_HEADER_LEN; + + /* 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, + (uint16_t) rTxPacketInfo.u4PacketLen); + + /* Save the value of Arrival Time */ + u4SysTime = (OS_SYSTIME) kalGetTimeTick(); + GLUE_SET_PKT_ARRIVAL_TIME(prPacket, u4SysTime); + + return TRUE; + } + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wlanProcessSecurityFrame(IN struct ADAPTER + *prAdapter, IN void *prPacket) +{ + struct CMD_INFO *prCmdInfo; + struct STA_RECORD *prStaRec; + uint8_t ucBssIndex; + uint32_t u4PacketLen; + uint8_t aucEthDestAddr[PARAM_MAC_ADDR_LEN]; + struct MSDU_INFO *prMsduInfo; + uint8_t ucStaRecIndex; + + ASSERT(prAdapter); + ASSERT(prPacket); + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, 0); + + /* Get MSDU_INFO for TxDone */ + prMsduInfo = cnmPktAlloc(prAdapter, 0); + + u4PacketLen = (uint32_t) GLUE_GET_PKT_FRAME_LEN(prPacket); + + if (prCmdInfo && prMsduInfo) { + ucBssIndex = GLUE_GET_PKT_BSS_IDX(prPacket); + + kalGetEthDestAddr(prAdapter->prGlueInfo, prPacket, + aucEthDestAddr); + + prStaRec = cnmGetStaRecByAddress(prAdapter, ucBssIndex, + aucEthDestAddr); + + prCmdInfo->eCmdType = COMMAND_TYPE_SECURITY_FRAME; + prCmdInfo->u2InfoBufLen = (uint16_t) u4PacketLen; + prCmdInfo->prPacket = prPacket; + prCmdInfo->prMsduInfo = prMsduInfo; + prCmdInfo->pfCmdDoneHandler = wlanSecurityFrameTxDone; + prCmdInfo->pfCmdTimeoutHandler = wlanSecurityFrameTxTimeout; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + + if (prStaRec) + ucStaRecIndex = prStaRec->ucIndex; + else + ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; + + /* Fill-up MSDU_INFO */ + nicTxSetDataPacket(prAdapter, prMsduInfo, ucBssIndex, + ucStaRecIndex, 0, u4PacketLen, + nicTxDummyTxDone, MSDU_RATE_MODE_AUTO, + TX_PACKET_OS, 0, FALSE, TRUE); + + prMsduInfo->prPacket = prPacket; + /* No Tx descriptor template for MMPDU */ + prMsduInfo->fgIsTXDTemplateValid = FALSE; + + if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_PROTECTED_1X)) + nicTxConfigPktOption(prMsduInfo, + MSDU_OPT_PROTECTED_FRAME, TRUE); +#if CFG_SUPPORT_MULTITHREAD + nicTxComposeSecurityFrameDesc(prAdapter, prCmdInfo, + prMsduInfo->aucTxDescBuffer, NULL); +#endif + + kalEnqueueCommand(prAdapter->prGlueInfo, + (struct QUE_ENTRY *) prCmdInfo); + + GLUE_SET_EVENT(prAdapter->prGlueInfo); + + return TRUE; + } + DBGLOG(RSN, INFO, + "Failed to alloc CMD/MGMT INFO for 1X frame!!\n"); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + cnmPktFree(prAdapter, prMsduInfo); + + + 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 struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + struct MSDU_INFO *prMsduInfo = prCmdInfo->prMsduInfo; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (GET_BSS_INFO_BY_INDEX(prAdapter, + prMsduInfo->ucBssIndex)->eNetworkType == + NETWORK_TYPE_AIS + && prAdapter->rWifiVar.rAisSpecificBssInfo.fgCounterMeasure) { + struct STA_RECORD *prSta = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucBssIndex); + + if (prSta) { + kalMsleep(10); + if (authSendDeauthFrame(prAdapter, + GET_BSS_INFO_BY_INDEX(prAdapter, + prMsduInfo->ucBssIndex), prSta, + (struct SW_RFB *) NULL, + REASON_CODE_MIC_FAILURE, + (PFN_TX_DONE_HANDLER) NULL + /* secFsmEventDeauthTxDone left upper + * layer handle the 60 timer + */ + ) != WLAN_STATUS_SUCCESS) { + ASSERT(FALSE); + } + /* 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 struct ADAPTER + *prAdapter, IN struct CMD_INFO *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 struct ADAPTER *prAdapter) +{ + u_int8_t fgKeepCurrOne = FALSE; + uint32_t i; + struct WLAN_INFO *prWlanInfo; + + ASSERT(prAdapter); + prWlanInfo = &(prAdapter->rWlanInfo); + + /* clear scanning result */ + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == + PARAM_MEDIA_STATE_CONNECTED) { + + for (i = 0; i < prWlanInfo->u4ScanResultNum; i++) { + + if (EQUAL_MAC_ADDR( + prWlanInfo->rCurrBssId.arMacAddress, + prWlanInfo->arScanResult[i].arMacAddress)) { + fgKeepCurrOne = TRUE; + + if (i != 0) { + /* copy structure */ + kalMemCopy( + &(prWlanInfo->arScanResult[0]), + &(prWlanInfo->arScanResult[i]), + OFFSET_OF(struct PARAM_BSSID_EX, + aucIEs)); + } + + if (prWlanInfo->arScanResult[i].u4IELength > 0) { + if (prWlanInfo->apucScanResultIEs[i] != + &(prWlanInfo->aucScanIEBuf[0])) { + + /* move IEs to head */ + kalMemCopy(prWlanInfo->aucScanIEBuf, + prWlanInfo->apucScanResultIEs[i], + prWlanInfo->arScanResult[i] + .u4IELength); + } + + /* modify IE pointer */ + prWlanInfo->apucScanResultIEs[0] = + &(prWlanInfo->aucScanIEBuf[0]); + + } else { + prWlanInfo->apucScanResultIEs[0] = NULL; + } + + break; + } /* if */ + } /* for */ + } + + if (fgKeepCurrOne == TRUE) { + prWlanInfo->u4ScanResultNum = 1; + prWlanInfo->u4ScanIEBufferUsage = + ALIGN_4(prWlanInfo->arScanResult[0].u4IELength); + } else { + prWlanInfo->u4ScanResultNum = 0; + prWlanInfo->u4ScanIEBufferUsage = 0; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called when AIS received a beacon timeout event + * + * @param prAdapter Pointer of Adapter Data Structure + * @param arBSSID MAC address of the specified BSS + * + * @return none + */ +/*----------------------------------------------------------------------------*/ +void wlanClearBssInScanningResult(IN struct ADAPTER + *prAdapter, IN uint8_t *arBSSID) +{ + uint32_t i, j, u4IELength = 0, u4IEMoveLength; + uint8_t *pucIEPtr; + struct WLAN_INFO *prWlanInfo; + + ASSERT(prAdapter); + prWlanInfo = &(prAdapter->rWlanInfo); + + /* clear scanning result */ + i = 0; + while (1) { + if (i >= prWlanInfo->u4ScanResultNum) + break; + + if (EQUAL_MAC_ADDR(arBSSID, + prWlanInfo->arScanResult[i].arMacAddress)) { + /* backup current IE length */ + u4IELength = + ALIGN_4(prWlanInfo->arScanResult[i].u4IELength); + pucIEPtr = prWlanInfo->apucScanResultIEs[i]; + + /* removed from middle */ + for (j = i + 1; j < prWlanInfo->u4ScanResultNum; j++) { + kalMemCopy(&(prWlanInfo->arScanResult[j - 1]), + &(prWlanInfo->arScanResult[j]), + OFFSET_OF(struct PARAM_BSSID_EX, + aucIEs)); + + prWlanInfo->apucScanResultIEs[j - 1] = + prWlanInfo->apucScanResultIEs[j]; + } + + prWlanInfo->u4ScanResultNum--; + + /* remove IE buffer if needed := move rest of IE buffer + */ + if (u4IELength > 0) { + u4IEMoveLength = prWlanInfo->u4ScanIEBufferUsage + - (((unsigned long) pucIEPtr) + + u4IELength + - ((unsigned long) + (&(prWlanInfo->aucScanIEBuf[0])))); + + kalMemCopy(pucIEPtr, + (uint8_t *) (((unsigned long) + pucIEPtr) + u4IELength), + u4IEMoveLength); + + prWlanInfo->u4ScanIEBufferUsage -= + u4IELength; + + /* correction of pointers to IE buffer */ + for (j = 0; j < prWlanInfo->u4ScanResultNum; + j++) { + if (prWlanInfo->apucScanResultIEs[j] > + pucIEPtr) { + prWlanInfo->apucScanResultIEs[j] = + (uint8_t *)((unsigned long) + (prWlanInfo->apucScanResultIEs[j]) - + u4IELength); + } + } + } + } + + i++; + } +} + +#if CFG_TEST_WIFI_DIRECT_GO +void wlanEnableP2pFunction(IN struct ADAPTER *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, + (struct MSG_HDR *) prMsgFuncSwitch, MSG_SEND_METHOD_BUF); +#endif + +} + +void wlanEnableATGO(IN struct ADAPTER *prAdapter) +{ + + struct MSG_P2P_CONNECTION_REQUEST *prMsgConnReq = + (struct MSG_P2P_CONNECTION_REQUEST *) NULL; + uint8_t aucTargetDeviceID[MAC_ADDR_LEN] = { 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF }; + + prMsgConnReq = + (struct MSG_P2P_CONNECTION_REQUEST *) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(struct MSG_P2P_CONNECTION_REQUEST)); + 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, + (struct MSG_HDR *) prMsgConnReq, MSG_SEND_METHOD_BUF); + +} +#endif + +void wlanPrintVersion(IN struct ADAPTER *prAdapter) +{ + uint8_t aucBuf[512]; + + kalMemZero(aucBuf, 512); + +#if CFG_ENABLE_FW_DOWNLOAD + fwDlGetFwdlInfo(prAdapter, aucBuf, 512); +#endif + DBGLOG(SW4, INFO, "%s", aucBuf); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanQueryNicCapability(IN struct ADAPTER + *prAdapter) +{ + struct mt66xx_chip_info *prChipInfo; + uint8_t aucZeroMacAddr[] = NULL_MAC_ADDR; + uint8_t ucCmdSeqNum; + struct CMD_INFO *prCmdInfo; + struct WIFI_CMD *prWifiCmd; + uint32_t u4RxPktLength; + uint8_t *aucBuffer; + uint32_t u4EventSize; + struct HW_MAC_RX_DESC *prRxStatus; + struct WIFI_EVENT *prEvent; + struct EVENT_NIC_CAPABILITY *prEventNicCapability; + struct PSE_CMD_HDR *prPseCmdHdr; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + DEBUGFUNC("wlanQueryNicCapability"); + + /* 1. Allocate CMD Info Packet and its Buffer */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + CMD_HDR_SIZE + sizeof(struct EVENT_NIC_CAPABILITY)); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + u4EventSize = prChipInfo->rxd_size + prChipInfo->event_hdr_size + + sizeof(struct EVENT_NIC_CAPABILITY); + aucBuffer = kalMemAlloc(u4EventSize, PHY_MEM_TYPE); + + /* 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( + struct EVENT_NIC_CAPABILITY); + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_GET_NIC_CAPABILITY; + prCmdInfo->fgSetQuery = FALSE; + prCmdInfo->fgNeedResp = TRUE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = 0; + + /* Setup WIFI_CMD_T */ + prWifiCmd = (struct WIFI_CMD *) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prPseCmdHdr = (struct PSE_CMD_HDR *) ( + prCmdInfo->pucInfoBuffer); + prPseCmdHdr->u2Qidx = TXD_Q_IDX_MCU_RQ0; + prPseCmdHdr->u2Pidx = TXD_P_IDX_MCU; + prPseCmdHdr->u2Hf = TXD_HF_CMD; + prPseCmdHdr->u2Ft = TXD_FT_LONG_FORMAT; + prPseCmdHdr->u2PktFt = TXD_PKT_FT_CMD; + + prWifiCmd->u2Length = prWifiCmd->u2TxByteCount - sizeof( + struct PSE_CMD_HDR); + + wlanSendCommand(prAdapter, prCmdInfo); + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + while (TRUE) { + if (nicRxWaitResponse(prAdapter, 1, aucBuffer, u4EventSize, + &u4RxPktLength) != WLAN_STATUS_SUCCESS) { + + DBGLOG(INIT, WARN, "%s: wait for event failed!\n", + __func__); + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + return WLAN_STATUS_FAILURE; + } + /* header checking .. */ + prRxStatus = (struct HW_MAC_RX_DESC *) aucBuffer; + if (prRxStatus->u2PktTYpe != RXM_RXD_PKT_TYPE_SW_EVENT) { + DBGLOG(INIT, WARN, + "%s: skip unexpected Rx pkt type[0x%04x]\n", + __func__, prRxStatus->u2PktTYpe); + continue; + } + + prEvent = (struct WIFI_EVENT *) + (aucBuffer + prChipInfo->rxd_size); + prEventNicCapability = + (struct EVENT_NIC_CAPABILITY *)prEvent->aucBuffer; + + if (prEvent->ucEID != EVENT_ID_NIC_CAPABILITY) { + DBGLOG(INIT, WARN, + "%s: skip unexpected event ID[0x%02x]\n", + __func__, prEvent->ucEID); + continue; + } else { + break; + } + } + + prEventNicCapability = (struct EVENT_NIC_CAPABILITY *) ( + prEvent->aucBuffer); + + prAdapter->rVerInfo.u2FwProductID = + prEventNicCapability->u2ProductID; + kalMemCopy(prAdapter->rVerInfo.aucFwBranchInfo, + prEventNicCapability->aucBranchInfo, 4); + prAdapter->rVerInfo.u2FwOwnVersion = + prEventNicCapability->u2FwVersion; + prAdapter->rVerInfo.ucFwBuildNumber = + prEventNicCapability->ucFwBuildNumber; + kalMemCopy(prAdapter->rVerInfo.aucFwDateCode, + prEventNicCapability->aucDateCode, 16); + prAdapter->rVerInfo.u2FwPeerVersion = + prEventNicCapability->u2DriverVersion; + prAdapter->fgIsHw5GBandDisabled = + (u_int8_t)prEventNicCapability->ucHw5GBandDisabled; + prAdapter->fgIsEepromUsed = + (u_int8_t)prEventNicCapability->ucEepromUsed; + prAdapter->fgIsEmbbededMacAddrValid = + (u_int8_t)(!IS_BMCAST_MAC_ADDR( + prEventNicCapability->aucMacAddr) && + !EQUAL_MAC_ADDR(aucZeroMacAddr, + prEventNicCapability->aucMacAddr)); + + COPY_MAC_ADDR(prAdapter->rWifiVar.aucPermanentAddress, + prEventNicCapability->aucMacAddr); + COPY_MAC_ADDR(prAdapter->rWifiVar.aucMacAddress, + prEventNicCapability->aucMacAddr); + + prAdapter->rWifiVar.ucStaVht &= + (!(prEventNicCapability->ucHwNotSupportAC)); + prAdapter->rWifiVar.ucApVht &= + (!(prEventNicCapability->ucHwNotSupportAC)); + prAdapter->rWifiVar.ucP2pGoVht &= + (!(prEventNicCapability->ucHwNotSupportAC)); + prAdapter->rWifiVar.ucP2pGcVht &= + (!(prEventNicCapability->ucHwNotSupportAC)); + prAdapter->rWifiVar.ucHwNotSupportAC = + prEventNicCapability->ucHwNotSupportAC; + + prAdapter->u4FwCompileFlag0 = + prEventNicCapability->u4CompileFlag0; + prAdapter->u4FwCompileFlag1 = + prEventNicCapability->u4CompileFlag1; + prAdapter->u4FwFeatureFlag0 = + prEventNicCapability->u4FeatureFlag0; + prAdapter->u4FwFeatureFlag1 = + prEventNicCapability->u4FeatureFlag1; + + if (prEventNicCapability->ucHwSetNss1x1) + prAdapter->rWifiVar.ucNSS = 1; + +#if CFG_SUPPORT_DBDC + if (prEventNicCapability->ucHwNotSupportDBDC) + prAdapter->rWifiVar.eDbdcMode = ENUM_DBDC_MODE_DISABLED; +#endif + if (prEventNicCapability->ucHwBssIdNum > 0 + && prEventNicCapability->ucHwBssIdNum <= MAX_BSSID_NUM) { + prAdapter->ucHwBssIdNum = + prEventNicCapability->ucHwBssIdNum; + prAdapter->ucP2PDevBssIdx = prAdapter->ucHwBssIdNum; + /* v1 event does not report WmmSetNum, + * Assume it is the same as HwBssNum + */ + prAdapter->ucWmmSetNum = + prEventNicCapability->ucHwBssIdNum; + prAdapter->aprBssInfo[prAdapter->ucP2PDevBssIdx] = + &prAdapter->rWifiVar.rP2pDevInfo; + } + +#if CFG_ENABLE_CAL_LOG + DBGLOG(INIT, TRACE, + "RF CAL FAIL = (%d),BB CAL FAIL = (%d)\n", + prEventNicCapability->ucRfCalFail, + prEventNicCapability->ucBbCalFail); +#endif + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + + return WLAN_STATUS_SUCCESS; +} + +#if TXPWR_USE_PDSLOPE + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param prAdapter Pointer of Adapter Data Structure + * + * @return WLAN_STATUS_SUCCESS + * WLAN_STATUS_FAILURE + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanQueryPdMcr(IN struct ADAPTER *prAdapter, + struct PARAM_MCR_RW_STRUCT *prMcrRdInfo) +{ + struct mt66xx_chip_info *prChipInfo; + uint8_t ucCmdSeqNum; + struct CMD_INFO *prCmdInfo; + struct WIFI_CMD *prWifiCmd; + uint32_t u4RxPktLength; + uint8_t *aucBuffer; + uint32_t u4EventSize; + struct HW_MAC_RX_DESC *prRxStatus; + struct WIFI_EVENT *prEvent; + struct CMD_ACCESS_REG *prCmdMcrQuery; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + /* 1. Allocate CMD Info Packet and its Buffer */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + CMD_HDR_SIZE + sizeof(struct CMD_ACCESS_REG)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + u4EventSize = prChipInfo->rxd_size + prChipInfo->event_hdr_size + + struct CMD_ACCESS_REG; + aucBuffer = kalMemAlloc(u4EventSize, PHY_MEM_TYPE); + + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_BUILD_CONNECTION cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = (uint16_t) (CMD_HDR_SIZE + sizeof( + struct 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->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(struct CMD_ACCESS_REG); + + /* Setup WIFI_CMD_T */ + prWifiCmd = (struct WIFI_CMD *) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + kalMemCopy(prWifiCmd->aucBuffer, prMcrRdInfo, + sizeof(struct CMD_ACCESS_REG)); + + wlanSendCommand(prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + if (nicRxWaitResponse(prAdapter, 1, aucBuffer, u4EventSize, + &u4RxPktLength) != WLAN_STATUS_SUCCESS) { + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + return WLAN_STATUS_FAILURE; + } + /* header checking .. */ + prRxStatus = (struct HW_MAC_RX_DESC *) aucBuffer; + if (prRxStatus->u2PktTYpe != RXM_RXD_PKT_TYPE_SW_EVENT) { + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + return WLAN_STATUS_FAILURE; + } + + prEvent = (struct WIFI_EVENT *) + (aucBuffer + prChipInfo->rxd_size); + if (prEvent->ucEID != EVENT_ID_ACCESS_REG) { + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + return WLAN_STATUS_FAILURE; + } + + prCmdMcrQuery = (struct CMD_ACCESS_REG *) ( + prEvent->aucBuffer); + prMcrRdInfo->u4McrOffset = prCmdMcrQuery->u4Address; + prMcrRdInfo->u4McrData = prCmdMcrQuery->u4Data; + + kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); + + return WLAN_STATUS_SUCCESS; +} + +static int32_t wlanIntRound(int32_t 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 int32_t wlanCal6628EfuseForm(IN struct ADAPTER + *prAdapter, int32_t au4Input) +{ + + struct PARAM_MCR_RW_STRUCT rMcrRdInfo; + int32_t au4PdSlope, au4TxPwrOffset, au4TxPwrOffset_Round; + int8_t 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_t) au4TxPwrOffset_Round; + + return au4TxPwrOffset_Round; +} + +#endif + +#if CFG_SUPPORT_NVRAM_5G +uint32_t wlanLoadManufactureData_5G(IN struct ADAPTER + *prAdapter, IN struct REG_INFO *prRegInfo) +{ + + struct BANDEDGE_5G *pr5GBandEdge; + + ASSERT(prAdapter); + + pr5GBandEdge = + &prRegInfo->prOldEfuseMapping->r5GBandEdgePwr; + + /* 1. set band edge tx power if available */ + if (pr5GBandEdge->uc5GBandEdgePwrUsed != 0) { + struct CMD_EDGE_TXPWR_LIMIT rCmdEdgeTxPwrLimit; + + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrCCK = 0; + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM20 = + pr5GBandEdge->c5GBandEdgeMaxPwrOFDM20; + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM40 = + pr5GBandEdge->c5GBandEdgeMaxPwrOFDM40; + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM80 = + pr5GBandEdge->c5GBandEdgeMaxPwrOFDM80; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_EDGE_TXPWR_LIMIT_5G, + TRUE, + FALSE, + FALSE, + NULL, + NULL, sizeof(struct CMD_EDGE_TXPWR_LIMIT), + (uint8_t *) &rCmdEdgeTxPwrLimit, NULL, 0); + + /* dumpMemory8(&rCmdEdgeTxPwrLimit,4); */ + } + + /*2.set channel offset for 8 sub-band */ + if (prRegInfo->prOldEfuseMapping->uc5GChannelOffsetVaild) { + struct CMD_POWER_OFFSET rCmdPowerOffset; + uint8_t i; + + rCmdPowerOffset.ucBand = BAND_5G; + for (i = 0; i < MAX_SUBBAND_NUM_5G; i++) + rCmdPowerOffset.ucSubBandOffset[i] = + prRegInfo->prOldEfuseMapping->auc5GChOffset[i]; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_CHANNEL_PWR_OFFSET, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(rCmdPowerOffset), + (uint8_t *) &rCmdPowerOffset, NULL, 0); + /* dumpMemory8(&rCmdPowerOffset,9); */ + } + + /*3.set 5G AC power */ + if (prRegInfo->prOldEfuseMapping->uc11AcTxPwrValid) { + + struct CMD_TX_AC_PWR rCmdAcPwr; + + kalMemCopy(&rCmdAcPwr.rAcPwr, + &prRegInfo->prOldEfuseMapping->r11AcTxPwr, + sizeof(struct AC_PWR_SETTING_STRUCT)); + rCmdAcPwr.ucBand = BAND_5G; + + wlanSendSetQueryCmd(prAdapter, CMD_ID_SET_80211AC_TX_PWR, + TRUE, FALSE, FALSE, NULL, NULL, + sizeof(struct CMD_TX_AC_PWR), + (uint8_t *) &rCmdAcPwr, NULL, 0); + /* dumpMemory8(&rCmdAcPwr,9); */ + } + + return WLAN_STATUS_SUCCESS; +} +#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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanLoadManufactureData(IN struct ADAPTER + *prAdapter, IN struct REG_INFO *prRegInfo) +{ +#if CFG_SUPPORT_RDD_TEST_MODE + struct CMD_RDD_CH rRddParam; +#endif + struct CMD_NVRAM_SETTING rCmdNvramSettings; + + ASSERT(prAdapter); + + /* 1. Version Check */ + if (prAdapter->prGlueInfo->fgNvramAvailable == TRUE) { + prAdapter->rVerInfo.u2Part1CfgOwnVersion = + prRegInfo->prNvramSettings->u2Part1OwnVersion; + prAdapter->rVerInfo.u2Part1CfgPeerVersion = + prRegInfo->prNvramSettings->u2Part1PeerVersion; + prAdapter->rVerInfo.u2Part2CfgOwnVersion = + prRegInfo->prNvramSettings->u2Part2OwnVersion; + prAdapter->rVerInfo.u2Part2CfgPeerVersion = + prRegInfo->prNvramSettings->u2Part2PeerVersion; + } + +#if (CFG_SW_NVRAM_VERSION_CHECK == 1) + if (prAdapter->rVerInfo.u2Part1CfgPeerVersion > + CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part2CfgPeerVersion > + CFG_DRV_OWN_VERSION + || 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, + (struct CMD_TX_PWR *) (&(prRegInfo->rTxPwr))); + } + } + + /* Todo : Temp Open 20150806 Sam */ + prRegInfo->ucEnable5GBand = 1; + prRegInfo->ucSupport5GBand = 1; + + /* 3. Check if needs to support 5GHz */ + if (prRegInfo->ucEnable5GBand) { +#if CFG_SUPPORT_NVRAM_5G + wlanLoadManufactureData_5G(prAdapter, prRegInfo); +#endif + /* 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 CFG_SUPPORT_NVRAM_5G + /* If NvRAM read failed, this pointer will be NULL */ + if (prRegInfo->prOldEfuseMapping) { + /*2.set channel offset for 3 sub-band */ + if (prRegInfo->prOldEfuseMapping->ucChannelOffsetVaild) { + struct CMD_POWER_OFFSET rCmdPowerOffset; + uint8_t i; + + rCmdPowerOffset.ucBand = BAND_2G4; + for (i = 0; i < 3; i++) + rCmdPowerOffset.ucSubBandOffset[i] = + prRegInfo->prOldEfuseMapping + ->aucChOffset[i]; + rCmdPowerOffset.ucSubBandOffset[i] = + prRegInfo->prOldEfuseMapping + ->acAllChannelOffset; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_CHANNEL_PWR_OFFSET, + TRUE, FALSE, FALSE, NULL, NULL, + sizeof(rCmdPowerOffset), + (uint8_t *) &rCmdPowerOffset, NULL, + 0); + /* dumpMemory8(&rCmdPowerOffset,9); */ + } + } +#else + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_PHY_PARAM, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(struct CMD_PHY_PARAM), + (uint8_t *) (prRegInfo->aucEFUSE), NULL, 0); + +#endif + /*RSSI path compasation */ + if (prRegInfo->ucRssiPathCompasationUsed) { + struct CMD_RSSI_PATH_COMPASATION rCmdRssiPathCompasation; + + rCmdRssiPathCompasation.c2GRssiCompensation = + prRegInfo->rRssiPathCompasation.c2GRssiCompensation; + rCmdRssiPathCompasation.c5GRssiCompensation = + prRegInfo->rRssiPathCompasation.c5GRssiCompensation; + + wlanSendSetQueryCmd(prAdapter, CMD_ID_SET_PATH_COMPASATION, + TRUE, FALSE, FALSE, NULL, NULL, + sizeof(rCmdRssiPathCompasation), + (uint8_t *) &rCmdRssiPathCompasation, + NULL, 0); + } +#if CFG_SUPPORT_RDD_TEST_MODE + rRddParam.ucRddTestMode = (uint8_t) + prRegInfo->u4RddTestMode; + rRddParam.ucRddShutCh = (uint8_t) prRegInfo->u4RddShutFreq; + rRddParam.ucRddStartCh = (uint8_t) nicFreq2ChannelNum( + prRegInfo->u4RddStartFreq); + rRddParam.ucRddStopCh = (uint8_t) nicFreq2ChannelNum( + prRegInfo->u4RddStopFreq); + rRddParam.ucRddDfs = (uint8_t) prRegInfo->u4RddDfs; + prAdapter->ucRddStatus = 0; + nicUpdateRddTestMode(prAdapter, + (struct CMD_RDD_CH *) (&rRddParam)); +#endif + + /* 5. Get 16-bits Country Code and Bandwidth */ + prAdapter->rWifiVar.rConnSettings.u2CountryCode = + (((uint16_t) prRegInfo->au2CountryCode[0]) << 8) | ((( + uint16_t) 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); + + /* Update supported channel list in channel table */ + wlanUpdateChannelTable(prAdapter->prGlueInfo); + + + /* 7. set band edge tx power if available */ + if (prRegInfo->fg2G4BandEdgePwrUsed) { + struct CMD_EDGE_TXPWR_LIMIT 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(struct CMD_EDGE_TXPWR_LIMIT), + (uint8_t *) &rCmdEdgeTxPwrLimit, NULL, 0); + } + /*8. Set 2.4G AC power */ + if (prRegInfo->prOldEfuseMapping + && prRegInfo->prOldEfuseMapping->uc11AcTxPwrValid2G) { + + struct CMD_TX_AC_PWR rCmdAcPwr; + + kalMemCopy(&rCmdAcPwr.rAcPwr, + &prRegInfo->prOldEfuseMapping->r11AcTxPwr2G, + sizeof(struct AC_PWR_SETTING_STRUCT)); + rCmdAcPwr.ucBand = BAND_2G4; + + wlanSendSetQueryCmd(prAdapter, CMD_ID_SET_80211AC_TX_PWR, + TRUE, FALSE, FALSE, NULL, NULL, + sizeof(struct CMD_TX_AC_PWR), + (uint8_t *) &rCmdAcPwr, NULL, 0); + /* dumpMemory8(&rCmdAcPwr,9); */ + } + /* 9. Send the full Parameters of NVRAM to FW */ + + kalMemCopy(&rCmdNvramSettings.rNvramSettings, + &prRegInfo->prNvramSettings->u2Part1OwnVersion, + sizeof(struct WIFI_CFG_PARAM_STRUCT)); + ASSERT(sizeof(struct WIFI_CFG_PARAM_STRUCT) == 512); + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_NVRAM_SETTINGS, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(rCmdNvramSettings), + (uint8_t *) &rCmdNvramSettings, 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wlanResetMediaStreamMode(IN struct ADAPTER + *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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanTimerTimeoutCheck(IN struct ADAPTER *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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanProcessMboxMessage(IN struct ADAPTER + *prAdapter) +{ + uint32_t i; + + ASSERT(prAdapter); + + for (i = 0; i < MBOX_ID_TOTAL_NUM; i++) + mboxRcvAllMsg(prAdapter, (enum ENUM_MBOX_ID) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanEnqueueTxPacket(IN struct ADAPTER *prAdapter, + IN void *prNativePacket) +{ + struct TX_CTRL *prTxCtrl; + struct MSDU_INFO *prMsduInfo; + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + + prMsduInfo = cnmPktAlloc(prAdapter, 0); + + if (!prMsduInfo) + return WLAN_STATUS_RESOURCES; + + if (nicTxFillMsduInfo(prAdapter, prMsduInfo, + prNativePacket)) { + /* prMsduInfo->eSrc = TX_PACKET_OS; */ + + /* Tx profiling */ + wlanTxProfilingTagMsdu(prAdapter, prMsduInfo, + TX_PROF_TAG_DRV_ENQUE); + + /* enqueue to QM */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; + } + kalSendComplete(prAdapter->prGlueInfo, prNativePacket, + WLAN_STATUS_INVALID_PACKET); + + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + + return WLAN_STATUS_INVALID_PACKET; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to flush pending TX packets in CORE + * + * @param prAdapter Pointer of Adapter Data Structure + * + * @return WLAN_STATUS_SUCCESS + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanFlushTxPendingPackets(IN struct ADAPTER *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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanTxPendingPackets(IN struct ADAPTER *prAdapter, + IN OUT u_int8_t *pfgHwAccess) +{ + struct TX_CTRL *prTxCtrl; + struct MSDU_INFO *prMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + +#if !CFG_SUPPORT_MULTITHREAD + ASSERT(pfgHwAccess); +#endif + + /* <1> dequeue packet by txDequeuTxPackets() */ +#if CFG_SUPPORT_MULTITHREAD + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + prMsduInfo = qmDequeueTxPacketsMthread(prAdapter, + &prTxCtrl->rTc); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); +#else + 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); +#endif + if (prMsduInfo != NULL) { + if (kalIsCardRemoved(prAdapter->prGlueInfo) == FALSE) { +#if !CFG_SUPPORT_MULTITHREAD + /* <2> Acquire LP-OWN if necessary */ + if (*pfgHwAccess == FALSE) { + *pfgHwAccess = TRUE; + + wlanAcquirePowerControl(prAdapter); + } +#endif + /* <3> send packets */ +#if CFG_SUPPORT_MULTITHREAD + nicTxMsduInfoListMthread(prAdapter, prMsduInfo); +#else + nicTxMsduInfoList(prAdapter, prMsduInfo); +#endif + /* <4> update TC by txAdjustTcQuotas() */ + nicTxAdjustTcq(prAdapter); + } else + wlanProcessQueuedMsduInfo(prAdapter, prMsduInfo); + } + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanAcquirePowerControl(IN struct ADAPTER *prAdapter) +{ + ASSERT(prAdapter); + + /* DBGLOG(INIT, INFO, ("Acquire Power Ctrl\n")); */ + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanReleasePowerControl(IN struct ADAPTER *prAdapter) +{ + ASSERT(prAdapter); + + /* DBGLOG(INIT, INFO, ("Release Power Ctrl\n")); */ + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanGetTxPendingFrameCount(IN struct ADAPTER *prAdapter) +{ + struct TX_CTRL *prTxCtrl; + uint32_t u4Num; + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + u4Num = kalGetTxPendingFrameCount(prAdapter->prGlueInfo) + + (uint32_t) GLUE_GET_REF_CNT( + 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 ENUM_ACPI_STATE wlanGetAcpiState(IN struct ADAPTER *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 struct ADAPTER *prAdapter, + IN enum ENUM_ACPI_STATE ePowerState) +{ + ASSERT(prAdapter); + ASSERT(ePowerState <= ACPI_STATE_D3); + + prAdapter->rAcpiState = ePowerState; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is to query ECO version from HIFSYS CR + * + * @param prAdapter Pointer of Adapter Data Structure + * + * @return zero Unable to retrieve ECO version information + * non-zero ECO version (1-based) + */ +/*----------------------------------------------------------------------------*/ +uint8_t wlanGetEcoVersion(IN struct ADAPTER *prAdapter) +{ + uint8_t ucEcoVersion; + + ASSERT(prAdapter); + +#if CFG_MULTI_ECOVER_SUPPORT + ucEcoVersion = nicGetChipEcoVer(prAdapter); + DBGLOG(INIT, TRACE, "%s: %u\n", __func__, ucEcoVersion); + return ucEcoVersion; +#else + if (nicVerifyChipID(prAdapter) == TRUE) + return prAdapter->ucRevID + 1; + else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is to query ROM version from HIFSYS CR + * + * @param prAdapter Pointer of Adapter Data Structure + * + * @return zero Unable to retrieve ROM version information + * non-zero ROM version (1-based) + */ +/*----------------------------------------------------------------------------*/ +uint8_t wlanGetRomVersion(IN struct ADAPTER *prAdapter) +{ + uint8_t ucRomVersion; + + ASSERT(prAdapter); + + ucRomVersion = nicGetChipSwVer(); + DBGLOG(INIT, TRACE, "%s: %u\n", __func__, ucRomVersion); + return ucRomVersion; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter) +{ + uint8_t i; + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct SET_TXPWR_CTRL *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 ucBssIndex BSS Info Index + * + * @return none + */ +/*----------------------------------------------------------------------------*/ +void wlanSetPreferBandByNetwork(IN struct ADAPTER *prAdapter, + IN enum ENUM_BAND eBand, IN uint8_t ucBssIndex) +{ + ASSERT(prAdapter); + ASSERT(eBand <= BAND_NUM); + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + + /* 1. set prefer band according to network type */ + prAdapter->aePreferBand[ucBssIndex] = eBand; + + /* 2. remove buffered BSS descriptors correspondingly */ + if (eBand == BAND_2G4) + scanRemoveBssDescByBandAndNetwork(prAdapter, BAND_5G, + ucBssIndex); + else if (eBand == BAND_5G) + scanRemoveBssDescByBandAndNetwork(prAdapter, BAND_2G4, + ucBssIndex); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is to + * get channel information corresponding to specified network type + * + * @param prAdapter Pointer of Adapter Data Structure + * @param ucBssIndex BSS Info Index + * + * @return channel number + */ +/*----------------------------------------------------------------------------*/ +uint8_t wlanGetChannelNumberByNetwork(IN struct ADAPTER + *prAdapter, IN uint8_t ucBssIndex) +{ + struct BSS_INFO *prBssInfo; + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + return prBssInfo->ucPrimaryChannel; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanCheckSystemConfiguration(IN struct ADAPTER + *prAdapter) +{ +#if (CFG_NVRAM_EXISTENCE_CHECK == 1) || (CFG_SW_NVRAM_VERSION_CHECK == 1) + const uint8_t aucZeroMacAddr[] = NULL_MAC_ADDR; + u_int8_t fgIsConfExist = TRUE; + u_int8_t fgGenErrMsg = FALSE; + struct REG_INFO *prRegInfo = NULL; +#if 0 + const uint8_t aucBCAddr[] = BC_MAC_ADDR; + struct WLAN_BEACON_FRAME *prBeacon = NULL; + struct IE_SSID *prSsid = NULL; + uint32_t u4ErrCode = 0; + uint8_t aucErrMsg[32]; + struct PARAM_SSID rSsid; + struct PARAM_802_11_CONFIG rConfiguration; + uint8_t rSupportedRates[PARAM_MAX_LEN_RATES_EX]; +#endif +#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 (CFG_SUPPORT_PWR_LIMIT_COUNTRY == 1) + if (fgIsConfExist == TRUE + && (prAdapter->rVerInfo.u2Part1CfgPeerVersion > + CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part2CfgPeerVersion > + CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part1CfgOwnVersion < + CFG_DRV_PEER_VERSION + || prAdapter->rVerInfo.u2Part2CfgOwnVersion < + CFG_DRV_PEER_VERSION/* NVRAM */ + || prAdapter->rVerInfo.u2FwPeerVersion > CFG_DRV_OWN_VERSION + || 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 + || prAdapter->fgIsPowerLimitTableValid == FALSE)) + fgGenErrMsg = TRUE; +#else + if (fgIsConfExist == TRUE + && (prAdapter->rVerInfo.u2Part1CfgPeerVersion > + CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part2CfgPeerVersion > + CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part1CfgOwnVersion < + CFG_DRV_PEER_VERSION + || prAdapter->rVerInfo.u2Part2CfgOwnVersion < + CFG_DRV_PEER_VERSION/* NVRAM */ + || prAdapter->rVerInfo.u2FwPeerVersion > CFG_DRV_OWN_VERSION + || 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 +#endif +#if 0/* remove NVRAM WARNING in scan result */ + if (fgGenErrMsg == TRUE) { + prBeacon = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, + sizeof(struct WLAN_BEACON_FRAME) + + sizeof(struct IE_SSID)); + + /* initialization */ + kalMemZero(prBeacon, sizeof(struct WLAN_BEACON_FRAME) + + sizeof(struct IE_SSID)); + + /* 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 = (struct IE_SSID *) (&prBeacon->aucInfoElem[0]); + prSsid->ucId = ELEM_ID_SSID; + + /* rConfiguration initialization */ + rConfiguration.u4Length = sizeof(struct + PARAM_802_11_CONFIG); + rConfiguration.u4BeaconPeriod = 100; + rConfiguration.u4ATIMWindow = 1; + rConfiguration.u4DSConfig = 2412; + rConfiguration.rFHConfig.u4Length = sizeof( + struct PARAM_802_11_CONFIG_FH); + + /* rSupportedRates initialization */ + kalMemZero(rSupportedRates, + (sizeof(uint8_t) * PARAM_MAX_LEN_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, + (uint8_t) (strlen(NVRAM_ERR_MSG))); + + kalIndicateBssInfo(prAdapter->prGlueInfo, + (uint8_t *) prBeacon, + OFFSET_OF(struct WLAN_BEACON_FRAME, + aucInfoElem) + OFFSET_OF( + struct IE_SSID, 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(struct WLAN_BEACON_FRAME, + aucInfoElem) + OFFSET_OF( + struct IE_SSID, aucSSID) + + prSsid->ucLength - + WLAN_MAC_MGMT_HEADER_LEN, + (uint8_t *) ((unsigned long) (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 ((prAdapter->rVerInfo.u2Part1CfgPeerVersion > + CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part2CfgPeerVersion > + CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part1CfgOwnVersion < + CFG_DRV_PEER_VERSION + || prAdapter->rVerInfo.u2Part2CfgOwnVersion < + CFG_DRV_PEER_VERSION /* NVRAM */ + || prAdapter->rVerInfo.u2FwPeerVersion > + CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2FwOwnVersion < + CFG_DRV_PEER_VERSION)) + u4ErrCode |= NVRAM_ERROR_VERSION_MISMATCH; + + if (prRegInfo->ucTxPwrValid == 0) + u4ErrCode |= NVRAM_ERROR_INVALID_TXPWR; + + if (prAdapter->fgIsEmbbededMacAddrValid == FALSE + && (IS_BMCAST_MAC_ADDR(prRegInfo->aucMacAddr) + || EQUAL_MAC_ADDR(aucZeroMacAddr, + prRegInfo->aucMacAddr))) { + u4ErrCode |= NVRAM_ERROR_INVALID_MAC_ADDR; + } +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + if (prAdapter->fgIsPowerLimitTableValid == FALSE) + u4ErrCode |= NVRAM_POWER_LIMIT_TABLE_INVALID; +#endif + if (u4ErrCode != 0) { + sprintf(aucErrMsg, VER_ERR_MSG, + (unsigned int)u4ErrCode); + COPY_SSID(prSsid->aucSSID, prSsid->ucLength, aucErrMsg, + (uint8_t) (strlen(aucErrMsg))); + + kalIndicateBssInfo(prAdapter->prGlueInfo, + (uint8_t *) prBeacon, + OFFSET_OF(struct WLAN_BEACON_FRAME, + aucInfoElem) + OFFSET_OF( + struct IE_SSID, 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(struct WLAN_BEACON_FRAME, + aucInfoElem) + + OFFSET_OF(struct IE_SSID, + aucSSID) + prSsid->ucLength - + WLAN_MAC_MGMT_HEADER_LEN, + (uint8_t *) ((unsigned long) (prBeacon) + + WLAN_MAC_MGMT_HEADER_LEN)); + } + } +#endif + + if (fgGenErrMsg == TRUE) + cnmMemFree(prAdapter, prBeacon); +#endif + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidQueryBssStatistics(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + struct PARAM_GET_BSS_STATISTICS *prQueryBssStatistics; + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint32_t rResult = WLAN_STATUS_FAILURE; + uint8_t ucBssIndex; + enum ENUM_WMM_ACI eAci; + + DEBUGFUNC("wlanoidQueryBssStatistics"); + + do { + ASSERT(pvQueryBuffer); + + /* 4 1. Sanity test */ + if ((prAdapter == NULL) || (pu4QueryInfoLen == NULL)) + break; + + if ((u4QueryBufferLen) && (pvQueryBuffer == NULL)) + break; + + if (u4QueryBufferLen < + sizeof(struct PARAM_GET_BSS_STATISTICS *)) { + *pu4QueryInfoLen = + sizeof(struct PARAM_GET_BSS_STATISTICS *); + rResult = WLAN_STATUS_BUFFER_TOO_SHORT; + break; + } + + prQueryBssStatistics = (struct PARAM_GET_BSS_STATISTICS *) + pvQueryBuffer; + *pu4QueryInfoLen = sizeof(struct PARAM_GET_BSS_STATISTICS); + + ucBssIndex = prQueryBssStatistics->ucBssIndex; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (prBssInfo) { /*AIS*/ + if (prBssInfo->eCurrentOPMode == + OP_MODE_INFRASTRUCTURE) { + struct WIFI_WMM_AC_STAT *prQueryLss = NULL; + struct WIFI_WMM_AC_STAT *prStaLss = NULL; + struct WIFI_WMM_AC_STAT *prBssLss = NULL; + + prQueryLss = prQueryBssStatistics->arLinkStatistics; + prBssLss = prBssInfo->arLinkStatistics; + prStaRec = prBssInfo->prStaRecOfAP; + if (prStaRec) { + prStaLss = prStaRec->arLinkStatistics; + for (eAci = 0; + eAci < WMM_AC_INDEX_NUM; eAci++) { + prQueryLss[eAci].u4TxMsdu = + prStaLss[eAci].u4TxMsdu; + prQueryLss[eAci].u4RxMsdu = + prStaLss[eAci].u4RxMsdu; + prQueryLss[eAci].u4TxDropMsdu = + prStaLss[eAci].u4TxDropMsdu + + prBssLss[eAci].u4TxDropMsdu; + prQueryLss[eAci].u4TxFailMsdu = + prStaLss[eAci].u4TxFailMsdu; + prQueryLss[eAci].u4TxRetryMsdu = + prStaLss[eAci].u4TxRetryMsdu; + } + } + } + rResult = WLAN_STATUS_SUCCESS; + + /*P2P */ + /* TODO */ + + /*BOW*/ + /* TODO */ + } + + } while (FALSE); + + return rResult; + +} + +void wlanDumpBssStatistics(IN struct ADAPTER *prAdapter, + uint8_t ucBssIdx) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + enum ENUM_WMM_ACI eAci; + struct WIFI_WMM_AC_STAT arLLStats[WMM_AC_INDEX_NUM]; + uint8_t ucIdx; + + if (ucBssIdx > prAdapter->ucHwBssIdNum) { + DBGLOG(SW4, INFO, "Invalid BssInfo index[%u], skip dump!\n", + ucBssIdx); + return; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + if (!prBssInfo) { + DBGLOG(SW4, INFO, "Invalid BssInfo index[%u], skip dump!\n", + ucBssIdx); + return; + } + /* <1> fill per-BSS statistics */ +#if 0 + /*AIS*/ if (prBssInfo->eCurrentOPMode == + OP_MODE_INFRASTRUCTURE) { + prStaRec = prBssInfo->prStaRecOfAP; + if (prStaRec) { + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prBssInfo->arLinkStatistics[eAci].u4TxMsdu + = prStaRec->arLinkStatistics[eAci] + .u4TxMsdu; + prBssInfo->arLinkStatistics[eAci].u4RxMsdu + = prStaRec->arLinkStatistics[eAci] + .u4RxMsdu; + prBssInfo->arLinkStatistics[eAci].u4TxDropMsdu + += prStaRec->arLinkStatistics[eAci] + .u4TxDropMsdu; + prBssInfo->arLinkStatistics[eAci].u4TxFailMsdu + = prStaRec->arLinkStatistics[eAci] + .u4TxFailMsdu; + prBssInfo->arLinkStatistics[eAci].u4TxRetryMsdu + = prStaRec->arLinkStatistics[eAci] + .u4TxRetryMsdu; + } + } + } +#else + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + arLLStats[eAci].u4TxMsdu = + prBssInfo->arLinkStatistics[eAci].u4TxMsdu; + arLLStats[eAci].u4RxMsdu = + prBssInfo->arLinkStatistics[eAci].u4RxMsdu; + arLLStats[eAci].u4TxDropMsdu = + prBssInfo->arLinkStatistics[eAci].u4TxDropMsdu; + arLLStats[eAci].u4TxFailMsdu = + prBssInfo->arLinkStatistics[eAci].u4TxFailMsdu; + arLLStats[eAci].u4TxRetryMsdu = + prBssInfo->arLinkStatistics[eAci].u4TxRetryMsdu; + } + + for (ucIdx = 0; ucIdx < CFG_STA_REC_NUM; ucIdx++) { + prStaRec = cnmGetStaRecByIndex(prAdapter, ucIdx); + if (!prStaRec) + continue; + if (prStaRec->ucBssIndex != ucBssIdx) + continue; + /* now the valid sta_rec is valid */ + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + arLLStats[eAci].u4TxMsdu += + prStaRec->arLinkStatistics[eAci].u4TxMsdu; + arLLStats[eAci].u4RxMsdu += + prStaRec->arLinkStatistics[eAci].u4RxMsdu; + arLLStats[eAci].u4TxDropMsdu += + prStaRec->arLinkStatistics[eAci].u4TxDropMsdu; + arLLStats[eAci].u4TxFailMsdu += + prStaRec->arLinkStatistics[eAci].u4TxFailMsdu; + arLLStats[eAci].u4TxRetryMsdu += + prStaRec->arLinkStatistics[eAci].u4TxRetryMsdu; + } + } +#endif + + /* <2>Dump BSS statistics */ + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + DBGLOG(SW4, INFO, + "LLS BSS[%u] %s: T[%06u] R[%06u] T_D[%06u] T_F[%06u]\n", + prBssInfo->ucBssIndex, apucACI2Str[eAci], + arLLStats[eAci].u4TxMsdu, + arLLStats[eAci].u4RxMsdu, arLLStats[eAci].u4TxDropMsdu, + arLLStats[eAci].u4TxFailMsdu); + } +} + +void wlanDumpAllBssStatistics(IN struct ADAPTER *prAdapter) +{ + struct BSS_INFO *prBssInfo; + /* ENUM_WMM_ACI_T eAci; */ + uint32_t ucIdx; + + /* wlanUpdateAllBssStatistics(prAdapter); */ + + for (ucIdx = 0; ucIdx < prAdapter->ucHwBssIdNum; ucIdx++) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucIdx); + if (!IS_BSS_ACTIVE(prBssInfo)) { + DBGLOG(SW4, TRACE, + "Invalid BssInfo index[%u], skip dump!\n", + ucIdx); + continue; + } + + wlanDumpBssStatistics(prAdapter, ucIdx); + } +} + +uint32_t +wlanoidQueryStaStatistics(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + return wlanQueryStaStatistics(prAdapter, pvQueryBuffer, + u4QueryBufferLen, + pu4QueryInfoLen, + g_fgIsOid); +} + +uint32_t +wlanQueryStaStatistics(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen, + u_int8_t fgIsOid) +{ + uint32_t rResult = WLAN_STATUS_FAILURE; + struct STA_RECORD *prStaRec, *prTempStaRec; + struct PARAM_GET_STA_STATISTICS *prQueryStaStatistics; + uint8_t ucStaRecIdx; + struct QUE_MGT *prQM; + struct CMD_GET_STA_STATISTICS rQueryCmdStaStatistics; + uint8_t ucIdx; + enum ENUM_WMM_ACI eAci; + + DEBUGFUNC("wlanoidQueryStaStatistics"); + + if (prAdapter == NULL) + return WLAN_STATUS_FAILURE; + prQM = &prAdapter->rQM; + + if (prAdapter->fgIsEnableLpdvt) + return WLAN_STATUS_NOT_SUPPORTED; + + do { + ASSERT(pvQueryBuffer); + + /* 4 1. Sanity test */ + if (pu4QueryInfoLen == NULL) + break; + + if ((u4QueryBufferLen) && (pvQueryBuffer == NULL)) + break; + + if (u4QueryBufferLen < + sizeof(struct PARAM_GET_STA_STATISTICS)) { + *pu4QueryInfoLen = + sizeof(struct PARAM_GET_STA_STATISTICS); + rResult = WLAN_STATUS_BUFFER_TOO_SHORT; + break; + } + + prQueryStaStatistics = (struct PARAM_GET_STA_STATISTICS *) + pvQueryBuffer; + *pu4QueryInfoLen = sizeof(struct PARAM_GET_STA_STATISTICS); + + /* 4 5. Get driver global QM counter */ +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + for (ucIdx = TC0_INDEX; ucIdx <= TC3_INDEX; ucIdx++) { + prQueryStaStatistics->au4TcAverageQueLen[ucIdx] = + prQM->au4AverageQueLen[ucIdx]; + prQueryStaStatistics->au4TcCurrentQueLen[ucIdx] = + prQM->au4CurrentTcResource[ucIdx]; + } +#endif + + /* 4 2. Get StaRec by MAC address */ + prStaRec = NULL; + + for (ucStaRecIdx = 0; ucStaRecIdx < CFG_STA_REC_NUM; + ucStaRecIdx++) { + prTempStaRec = &(prAdapter->arStaRec[ucStaRecIdx]); + if (prTempStaRec->fgIsValid && + prTempStaRec->fgIsInUse) { + if (EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, + prQueryStaStatistics->aucMacAddr)) { + prStaRec = prTempStaRec; + break; + } + } + } + + if (!prStaRec) { + rResult = WLAN_STATUS_INVALID_DATA; + break; + } + + prQueryStaStatistics->u4Flag |= BIT(0); + +#if CFG_ENABLE_PER_STA_STATISTICS + /* 4 3. Get driver statistics */ + prQueryStaStatistics->u4TxTotalCount = + prStaRec->u4TotalTxPktsNumber; + prQueryStaStatistics->u4RxTotalCount = + prStaRec->u4TotalRxPktsNumber; + prQueryStaStatistics->u4TxExceedThresholdCount = + prStaRec->u4ThresholdCounter; + prQueryStaStatistics->u4TxMaxTime = + prStaRec->u4MaxTxPktsTime; + prQueryStaStatistics->u4TxMaxHifTime = + prStaRec->u4MaxTxPktsHifTime; + + if (prStaRec->u4TotalTxPktsNumber) { + prQueryStaStatistics->u4TxAverageProcessTime = + (prStaRec->u4TotalTxPktsTime / + prStaRec->u4TotalTxPktsNumber); + prQueryStaStatistics->u4TxAverageHifTime = + prStaRec->u4TotalTxPktsHifTxTime / + prStaRec->u4TotalTxPktsNumber; + } else + prQueryStaStatistics->u4TxAverageProcessTime = 0; + + /*link layer statistics */ + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prQueryStaStatistics->arLinkStatistics[eAci].u4TxMsdu = + prStaRec->arLinkStatistics[eAci].u4TxMsdu; + prQueryStaStatistics->arLinkStatistics[eAci].u4RxMsdu = + prStaRec->arLinkStatistics[eAci].u4RxMsdu; + prQueryStaStatistics->arLinkStatistics[ + eAci].u4TxDropMsdu = + prStaRec->arLinkStatistics[eAci].u4TxDropMsdu; + } + + for (ucIdx = TC0_INDEX; ucIdx <= TC3_INDEX; ucIdx++) { + prQueryStaStatistics->au4TcResourceEmptyCount[ucIdx] = + prQM->au4QmTcResourceEmptyCounter[ + prStaRec->ucBssIndex][ucIdx]; + /* Reset */ + prQM->au4QmTcResourceEmptyCounter[ + prStaRec->ucBssIndex][ucIdx] = 0; + prQueryStaStatistics->au4TcResourceBackCount[ucIdx] = + prQM->au4QmTcResourceBackCounter[ucIdx]; + prQM->au4QmTcResourceBackCounter[ucIdx] = 0; + prQueryStaStatistics->au4DequeueNoTcResource[ucIdx] + = prQM->au4DequeueNoTcResourceCounter[ucIdx]; + prQM->au4DequeueNoTcResourceCounter[ucIdx] = 0; + prQueryStaStatistics->au4TcResourceUsedPageCount[ucIdx] + = prQM->au4QmTcUsedPageCounter[ucIdx]; + prQM->au4QmTcUsedPageCounter[ucIdx] = 0; + prQueryStaStatistics->au4TcResourceWantedPageCount[ + ucIdx] = prQM->au4QmTcWantedPageCounter[ucIdx]; + prQM->au4QmTcWantedPageCounter[ucIdx] = 0; + } + + prQueryStaStatistics->u4EnqueueCounter = + prQM->u4EnqueueCounter; + prQueryStaStatistics->u4EnqueueStaCounter = + prStaRec->u4EnqueueCounter; + + prQueryStaStatistics->u4DequeueCounter = + prQM->u4DequeueCounter; + prQueryStaStatistics->u4DequeueStaCounter = + prStaRec->u4DeqeueuCounter; + + prQueryStaStatistics->IsrCnt = + prAdapter->prGlueInfo->IsrCnt; + prQueryStaStatistics->IsrPassCnt = + prAdapter->prGlueInfo->IsrPassCnt; + prQueryStaStatistics->TaskIsrCnt = + prAdapter->prGlueInfo->TaskIsrCnt; + + prQueryStaStatistics->IsrAbnormalCnt = + prAdapter->prGlueInfo->IsrAbnormalCnt; + prQueryStaStatistics->IsrSoftWareCnt = + prAdapter->prGlueInfo->IsrSoftWareCnt; + prQueryStaStatistics->IsrRxCnt = + prAdapter->prGlueInfo->IsrRxCnt; + prQueryStaStatistics->IsrTxCnt = + prAdapter->prGlueInfo->IsrTxCnt; + + /* 4 4.1 Reset statistics */ + if (prQueryStaStatistics->ucReadClear) { + prStaRec->u4ThresholdCounter = 0; + prStaRec->u4TotalTxPktsNumber = 0; + prStaRec->u4TotalTxPktsHifTxTime = 0; + + prStaRec->u4TotalTxPktsTime = 0; + prStaRec->u4TotalRxPktsNumber = 0; + prStaRec->u4MaxTxPktsTime = 0; + prStaRec->u4MaxTxPktsHifTime = 0; + prQM->u4EnqueueCounter = 0; + prQM->u4DequeueCounter = 0; + prStaRec->u4EnqueueCounter = 0; + prStaRec->u4DeqeueuCounter = 0; + + prAdapter->prGlueInfo->IsrCnt = 0; + prAdapter->prGlueInfo->IsrPassCnt = 0; + prAdapter->prGlueInfo->TaskIsrCnt = 0; + + prAdapter->prGlueInfo->IsrAbnormalCnt = 0; + prAdapter->prGlueInfo->IsrSoftWareCnt = 0; + prAdapter->prGlueInfo->IsrRxCnt = 0; + prAdapter->prGlueInfo->IsrTxCnt = 0; + } + /*link layer statistics */ + if (prQueryStaStatistics->ucLlsReadClear) { + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prStaRec->arLinkStatistics[eAci].u4TxMsdu = 0; + prStaRec->arLinkStatistics[eAci].u4RxMsdu = 0; + prStaRec->arLinkStatistics[eAci].u4TxDropMsdu + = 0; + } + } +#endif + + for (ucIdx = TC0_INDEX; ucIdx <= TC3_INDEX; ucIdx++) + prQueryStaStatistics->au4TcQueLen[ucIdx] = + prStaRec->aprTargetQueue[ucIdx]->u4NumElem; + + rResult = WLAN_STATUS_SUCCESS; + + /* 4 6. Ensure FW supports get station link status */ + rQueryCmdStaStatistics.ucIndex = prStaRec->ucIndex; + COPY_MAC_ADDR(rQueryCmdStaStatistics.aucMacAddr, + prQueryStaStatistics->aucMacAddr); + rQueryCmdStaStatistics.ucReadClear = + prQueryStaStatistics->ucReadClear; + rQueryCmdStaStatistics.ucLlsReadClear = + prQueryStaStatistics->ucLlsReadClear; + rQueryCmdStaStatistics.ucResetCounter = + prQueryStaStatistics->ucResetCounter; + + rResult = wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STA_STATISTICS, + FALSE, + TRUE, + fgIsOid, + nicCmdEventQueryStaStatistics, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_GET_STA_STATISTICS), + (uint8_t *)&rQueryCmdStaStatistics, + pvQueryBuffer, u4QueryBufferLen); + + if ((!fgIsOid) && (rResult == WLAN_STATUS_PENDING)) + rResult = WLAN_STATUS_SUCCESS; + + prQueryStaStatistics->u4Flag |= BIT(1); + + } while (FALSE); + + return rResult; +} /* wlanoidQueryP2pVersion */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is to query Nic resource information + * + * @param prAdapter Pointer of Adapter Data Structure + * + * @return WLAN_STATUS_SUCCESS + */ +/*----------------------------------------------------------------------------*/ +void wlanQueryNicResourceInformation(IN struct ADAPTER *prAdapter) +{ + /* 3 1. Get Nic resource information from FW */ + + /* 3 2. Setup resource parameter */ + + /* 3 3. Reset Tx resource */ + nicTxResetResource(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is to query Nic resource information + * + * @param prAdapter Pointer of Adapter Data Structure + * + * @return WLAN_STATUS_SUCCESS + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanQueryNicCapabilityV2(IN struct ADAPTER *prAdapter) +{ + uint8_t ucCmdSeqNum; + struct CMD_INFO *prCmdInfo; + struct WIFI_CMD *prWifiCmd; + uint32_t u4RxPktLength; + uint8_t *prEventBuff; + struct HW_MAC_RX_DESC *prRxStatus; + struct WIFI_EVENT *prEvent; + struct mt66xx_chip_info *prChipInfo; + uint32_t chip_id; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + chip_id = prChipInfo->chip_id; + + ASSERT(prAdapter); + + /* Get Nic resource information from FW */ + if (!prChipInfo->isNicCapV1 + || (prAdapter->u4FwFeatureFlag0 & + FEATURE_FLAG0_NIC_CAPABILITY_V2)) { + + DBGLOG(INIT, INFO, "Support NIC_CAPABILITY_V2 feature\n"); + + /* + * send NIC_CAPABILITY_V2 query cmd + */ + + /* 1. Allocate CMD Info Packet and its Buffer */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, + "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_BUILD_CONNECTION cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE; + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_GET_NIC_CAPABILITY_V2; + prCmdInfo->fgSetQuery = FALSE; + prCmdInfo->fgNeedResp = TRUE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = 0; + + /* Setup WIFI_CMD_T */ + prWifiCmd = (struct WIFI_CMD *) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prWifiCmd->u2Length = prCmdInfo->u2InfoBufLen - + (uint16_t) OFFSET_OF(struct WIFI_CMD, u2Length); + + wlanSendCommand(prAdapter, prCmdInfo); + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + /* + * receive nic_capability_v2 event + */ + + /* allocate event buffer */ + prEventBuff = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, + CFG_RX_MAX_PKT_SIZE); + if (!prEventBuff) { + DBGLOG(INIT, WARN, "%s: event buffer alloc failed!\n", + __func__); + return WLAN_STATUS_FAILURE; + } + + /* get event */ + while (TRUE) { + if (nicRxWaitResponse(prAdapter, + 1, + prEventBuff, + CFG_RX_MAX_PKT_SIZE, + &u4RxPktLength) + != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, WARN, + "%s: wait for event failed!\n", + __func__); + + /* free event buffer */ + cnmMemFree(prAdapter, prEventBuff); + + return WLAN_STATUS_FAILURE; + } + + /* header checking .. */ + prRxStatus = (struct HW_MAC_RX_DESC *) prEventBuff; + if ((prRxStatus->u2PktTYpe & + RXM_RXD_PKT_TYPE_SW_BITMAP) != + RXM_RXD_PKT_TYPE_SW_EVENT) { + DBGLOG(INIT, WARN, + "%s: skip unexpected Rx pkt type[0x%04x]\n", + __func__, prRxStatus->u2PktTYpe); + + continue; + } + + prEvent = (struct WIFI_EVENT *) + (prEventBuff + prChipInfo->rxd_size); + if (prEvent->ucEID != EVENT_ID_NIC_CAPABILITY_V2) { + DBGLOG(INIT, WARN, + "%s: skip unexpected event ID[0x%02x]\n", + __func__, prEvent->ucEID); + + continue; + } else { + /* hit */ + break; + } + } + + /* + * parsing elemens + */ + + nicCmdEventQueryNicCapabilityV2(prAdapter, + prEvent->aucBuffer); + + /* + * free event buffer + */ + cnmMemFree(prAdapter, prEventBuff); + } + + /* Fill capability for different Chip version */ + if (chip_id == HQA_CHIP_ID_6632) { + /* 6632 only */ + prAdapter->fgIsSupportBufferBinSize16Byte = TRUE; + prAdapter->fgIsSupportDelayCal = FALSE; + prAdapter->fgIsSupportGetFreeEfuseBlockCount = FALSE; + prAdapter->fgIsSupportQAAccessEfuse = FALSE; + prAdapter->fgIsSupportPowerOnSendBufferModeCMD = FALSE; + prAdapter->fgIsSupportGetTxPower = FALSE; + } else { + prAdapter->fgIsSupportBufferBinSize16Byte = FALSE; + prAdapter->fgIsSupportDelayCal = TRUE; + prAdapter->fgIsSupportGetFreeEfuseBlockCount = TRUE; + prAdapter->fgIsSupportQAAccessEfuse = TRUE; + prAdapter->fgIsSupportPowerOnSendBufferModeCMD = TRUE; + prAdapter->fgIsSupportGetTxPower = TRUE; + } + + return WLAN_STATUS_SUCCESS; +} + +void wlanSetNicResourceParameters(IN struct ADAPTER + *prAdapter) +{ + uint8_t string[128], idx; + uint32_t u4share; + uint32_t u4MaxPageCntPerFrame = + prAdapter->rTxCtrl.u4MaxPageCntPerFrame; + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + struct QUE_MGT *prQM = &prAdapter->rQM; +#endif + + /* + * Use the settings in config file first, + * else, use the settings reported from firmware. + */ + + + /* + * 1. assign free page count for each TC + */ + + /* 1 1. update free page count in TC control: MCU and LMAC */ + prWifiVar->au4TcPageCount[TC4_INDEX] = + prAdapter->nicTxReousrce.u4CmdTotalResource * + u4MaxPageCntPerFrame; /* MCU */ + + u4share = prAdapter->nicTxReousrce.u4DataTotalResource / + (TC_NUM - 1); /* LMAC. Except TC_4, which is MCU */ + for (idx = TC0_INDEX; idx < TC_NUM; idx++) { + if (idx != TC4_INDEX) + prWifiVar->au4TcPageCount[idx] = u4share * + u4MaxPageCntPerFrame; + } + + /* 1 2. if there is remaings, give them to TC_3, which is VO */ + prWifiVar->au4TcPageCount[TC3_INDEX] += + (prAdapter->nicTxReousrce.u4DataTotalResource % + (TC_NUM - 1)) * u4MaxPageCntPerFrame; + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + /* + * 2. assign guaranteed page count for each TC + */ + + /* 2 1. update guaranteed page count in QM */ + for (idx = 0; idx < TC_NUM; idx++) + prQM->au4GuaranteedTcResource[idx] = + prWifiVar->au4TcPageCount[idx]; +#endif + + +#if CFG_SUPPORT_CFG_FILE + /* + * 3. Use the settings in config file first, + * else, use the settings reported from firmware. + */ + + /* 3 1. update for free page count */ + for (idx = 0; idx < TC_NUM; idx++) { + + /* construct prefix: Tc0Page, Tc1Page... */ + memset(string, 0, sizeof(string) / sizeof(uint8_t)); + snprintf(string, sizeof(string) / sizeof(uint8_t), + "Tc%xPage", idx); + + /* update the final value */ + prWifiVar->au4TcPageCount[idx] = + (uint32_t) wlanCfgGetUint32(prAdapter, string, + prWifiVar->au4TcPageCount[idx]); + } + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + /* 3 2. update for guaranteed page count */ + for (idx = 0; idx < TC_NUM; idx++) { + + /* construct prefix: Tc0Grt, Tc1Grt... */ + memset(string, 0, sizeof(string) / sizeof(uint8_t)); + snprintf(string, sizeof(string) / sizeof(uint8_t), + "Tc%xGrt", idx); + + /* update the final value */ + prQM->au4GuaranteedTcResource[idx] = + (uint32_t) wlanCfgGetUint32(prAdapter, string, + prQM->au4GuaranteedTcResource[idx]); + } +#endif /* end of #if QM_ADAPTIVE_TC_RESOURCE_CTRL */ + +#endif /* end of #if CFG_SUPPORT_CFG_FILE */ +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is to re-assign tx resource based on firmware's report + * + * @param prAdapter Pointer of Adapter Data Structure + * + * @return WLAN_STATUS_SUCCESS + */ +/*----------------------------------------------------------------------------*/ +void wlanUpdateNicResourceInformation(IN struct ADAPTER + *prAdapter) +{ + /* + * 3 1. Query TX resource + */ + + /* information is not got from firmware, use default value */ + if (prAdapter->fgIsNicTxReousrceValid != TRUE) + return; + + /* 3 2. Setup resource parameters */ + if (prAdapter->nicTxReousrce.txResourceInit) + prAdapter->nicTxReousrce.txResourceInit(prAdapter); + else + wlanSetNicResourceParameters(prAdapter);/* 6632, 7668 ways*/ + + /* 3 3. Reset Tx resource */ + nicTxResetResource(prAdapter); + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + /* 3 4. Reset QM resource */ + qmResetTcControlResource( + prAdapter); /*CHIAHSUAN, TBD, NO PLE YET*/ +#endif + + halTxResourceResetHwTQCounter(prAdapter); +} + + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is to SET network interface index for a network + * interface. + * A network interface is a TX/RX data port hooked to OS. + * + * @param prGlueInfo Pointer of prGlueInfo Data Structure + * @param ucNetInterfaceIndex Index of network interface + * @param ucBssIndex Index of BSS + * + * @return VOID + */ +/*----------------------------------------------------------------------------*/ +void wlanBindNetInterface(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucNetInterfaceIndex, + IN void *pvNetInterface) +{ + struct NET_INTERFACE_INFO *prNetIfInfo; + + prNetIfInfo = + &prGlueInfo->arNetInterfaceInfo[ucNetInterfaceIndex]; + + prNetIfInfo->pvNetInterface = pvNetInterface; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is to SET BSS index for a network interface. + * A network interface is a TX/RX data port hooked to OS. + * + * @param prGlueInfo Pointer of prGlueInfo Data Structure + * @param ucNetInterfaceIndex Index of network interface + * @param ucBssIndex Index of BSS + * + * @return VOID + */ +/*----------------------------------------------------------------------------*/ +void wlanBindBssIdxToNetInterface(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucBssIndex, + IN void *pvNetInterface) +{ + struct NET_INTERFACE_INFO *prNetIfInfo; + + if (ucBssIndex >= prGlueInfo->prAdapter->ucHwBssIdNum) { + DBGLOG(INIT, ERROR, + "Array index out of bound, ucBssIndex=%u\n", ucBssIndex); + return; + } + + prNetIfInfo = &prGlueInfo->arNetInterfaceInfo[ucBssIndex]; + + prNetIfInfo->ucBssIndex = ucBssIndex; + prNetIfInfo->pvNetInterface = pvNetInterface; + /* prGlueInfo->aprBssIdxToNetInterfaceInfo[ucBssIndex] = prNetIfInfo; */ +} + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is to GET BSS index for a network interface. + * A network interface is a TX/RX data port hooked to OS. + * + * @param prGlueInfo Pointer of prGlueInfo Data Structure + * @param ucNetInterfaceIndex Index of network interface + * + * @return UINT_8 Index of BSS + */ +/*----------------------------------------------------------------------------*/ +uint8_t wlanGetBssIdxByNetInterface(IN struct GLUE_INFO + *prGlueInfo, IN void *pvNetInterface) +{ + uint8_t ucIdx = 0; + + ASSERT(prGlueInfo); + + for (ucIdx = 0; ucIdx < prGlueInfo->prAdapter->ucHwBssIdNum; + ucIdx++) { + if (prGlueInfo->arNetInterfaceInfo[ucIdx].pvNetInterface == + pvNetInterface) + break; + } + + return ucIdx; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is to GET network interface for a BSS. + * A network interface is a TX/RX data port hooked to OS. + * + * @param prGlueInfo Pointer of prGlueInfo Data Structure + * @param ucBssIndex Index of BSS + * + * @return PVOID pointer of network interface structure + */ +/*----------------------------------------------------------------------------*/ +void *wlanGetNetInterfaceByBssIdx(IN struct GLUE_INFO + *prGlueInfo, IN uint8_t ucBssIndex) +{ + return prGlueInfo->arNetInterfaceInfo[ucBssIndex].pvNetInterface; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is to get BSS-INDEX for AIS network. + * + * @param prAdapter Pointer of ADAPTER_T + * + * @return value, as corresponding index of BSS + */ +/*----------------------------------------------------------------------------*/ +uint8_t wlanGetAisBssIndex(IN struct ADAPTER *prAdapter) +{ + ASSERT(prAdapter); + ASSERT(prAdapter->prAisBssInfo); + + return prAdapter->prAisBssInfo->ucBssIndex; +} +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is to initialize WLAN feature options + * + * @param prAdapter Pointer of ADAPTER_T + * + * @return none + */ +/*----------------------------------------------------------------------------*/ +void wlanInitFeatureOption(IN struct ADAPTER *prAdapter) +{ + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + struct QUE_MGT *prQM = &prAdapter->rQM; +#endif + + /* Feature options will be filled by config file */ + + prWifiVar->ucQoS = (uint8_t) wlanCfgGetUint32(prAdapter, "Qos", + FEATURE_ENABLED); + + prWifiVar->ucStaHt = (uint8_t) wlanCfgGetUint32(prAdapter, "StaHT", + FEATURE_ENABLED); + prWifiVar->ucStaVht = (uint8_t) wlanCfgGetUint32(prAdapter, "StaVHT", + FEATURE_ENABLED); + + prWifiVar->ucApHt = (uint8_t) wlanCfgGetUint32(prAdapter, "ApHT", + FEATURE_ENABLED); + prWifiVar->ucApVht = (uint8_t) wlanCfgGetUint32(prAdapter, "ApVHT", + FEATURE_ENABLED); + + prWifiVar->ucP2pGoHt = (uint8_t) wlanCfgGetUint32(prAdapter, "P2pGoHT", + FEATURE_ENABLED); + prWifiVar->ucP2pGoVht = (uint8_t) wlanCfgGetUint32(prAdapter, + "P2pGoVHT", FEATURE_ENABLED); + + prWifiVar->ucP2pGcHt = (uint8_t) wlanCfgGetUint32(prAdapter, "P2pGcHT", + FEATURE_ENABLED); + prWifiVar->ucP2pGcVht = (uint8_t) wlanCfgGetUint32(prAdapter, + "P2pGcVHT", FEATURE_ENABLED); + + prWifiVar->ucAmpduRx = (uint8_t) wlanCfgGetUint32(prAdapter, "AmpduRx", + FEATURE_ENABLED); + prWifiVar->ucAmpduTx = (uint8_t) wlanCfgGetUint32(prAdapter, "AmpduTx", + FEATURE_ENABLED); + + prWifiVar->ucAmsduInAmpduRx = (uint8_t) wlanCfgGetUint32(prAdapter, + "AmsduInAmpduRx", FEATURE_ENABLED); + prWifiVar->ucAmsduInAmpduTx = (uint8_t) wlanCfgGetUint32(prAdapter, + "AmsduInAmpduTx", FEATURE_ENABLED); + prWifiVar->ucHtAmsduInAmpduRx = (uint8_t) wlanCfgGetUint32(prAdapter, + "HtAmsduInAmpduRx", FEATURE_DISABLED); + prWifiVar->ucHtAmsduInAmpduTx = (uint8_t) wlanCfgGetUint32(prAdapter, + "HtAmsduInAmpduTx", FEATURE_DISABLED); + prWifiVar->ucVhtAmsduInAmpduRx = (uint8_t) wlanCfgGetUint32(prAdapter, + "VhtAmsduInAmpduRx", FEATURE_ENABLED); + prWifiVar->ucVhtAmsduInAmpduTx = (uint8_t) wlanCfgGetUint32(prAdapter, + "VhtAmsduInAmpduTx", FEATURE_ENABLED); + + prWifiVar->ucTspec = (uint8_t) wlanCfgGetUint32(prAdapter, "Tspec", + FEATURE_DISABLED); + + prWifiVar->ucUapsd = (uint8_t) wlanCfgGetUint32(prAdapter, "Uapsd", + FEATURE_ENABLED); + prWifiVar->ucStaUapsd = (uint8_t) wlanCfgGetUint32(prAdapter, + "StaUapsd", FEATURE_DISABLED); + prWifiVar->ucApUapsd = (uint8_t) wlanCfgGetUint32(prAdapter, + "ApUapsd", FEATURE_DISABLED); + prWifiVar->ucP2pUapsd = (uint8_t) wlanCfgGetUint32(prAdapter, + "P2pUapsd", FEATURE_ENABLED); + prWifiVar->u4RegP2pIfAtProbe = (uint8_t) wlanCfgGetUint32(prAdapter, + "RegP2pIfAtProbe", FEATURE_DISABLED); + prWifiVar->ucP2pShareMacAddr = (uint8_t) wlanCfgGetUint32(prAdapter, + "P2pShareMacAddr", FEATURE_DISABLED); + + prWifiVar->ucTxShortGI = (uint8_t) wlanCfgGetUint32(prAdapter, "SgiTx", + FEATURE_ENABLED); + prWifiVar->ucRxShortGI = (uint8_t) wlanCfgGetUint32(prAdapter, "SgiRx", + FEATURE_ENABLED); + + prWifiVar->ucTxLdpc = (uint8_t) wlanCfgGetUint32(prAdapter, "LdpcTx", + FEATURE_ENABLED); + prWifiVar->ucRxLdpc = (uint8_t) wlanCfgGetUint32(prAdapter, "LdpcRx", + FEATURE_ENABLED); + + prWifiVar->ucTxStbc = (uint8_t) wlanCfgGetUint32(prAdapter, "StbcTx", + FEATURE_ENABLED); + prWifiVar->ucRxStbc = (uint8_t) wlanCfgGetUint32(prAdapter, "StbcRx", + FEATURE_ENABLED); + prWifiVar->ucRxStbcNss = (uint8_t) wlanCfgGetUint32(prAdapter, + "StbcRxNss", 1); + + prWifiVar->ucTxGf = (uint8_t) wlanCfgGetUint32(prAdapter, "GfTx", + FEATURE_ENABLED); + prWifiVar->ucRxGf = (uint8_t) wlanCfgGetUint32(prAdapter, "GfRx", + FEATURE_ENABLED); + + prWifiVar->ucMCS32 = (uint8_t) wlanCfgGetUint32(prAdapter, "MCS32", + FEATURE_DISABLED); + + prWifiVar->ucSigTaRts = (uint8_t) wlanCfgGetUint32(prAdapter, + "SigTaRts", FEATURE_DISABLED); + prWifiVar->ucDynBwRts = (uint8_t) wlanCfgGetUint32(prAdapter, + "DynBwRts", FEATURE_DISABLED); + prWifiVar->ucTxopPsTx = (uint8_t) wlanCfgGetUint32(prAdapter, + "TxopPsTx", FEATURE_DISABLED); + + prWifiVar->ucStaHtBfee = (uint8_t) wlanCfgGetUint32(prAdapter, + "StaHTBfee", FEATURE_DISABLED); + prWifiVar->ucStaVhtBfee = (uint8_t) wlanCfgGetUint32(prAdapter, + "StaVHTBfee", FEATURE_ENABLED); + prWifiVar->ucStaVhtMuBfee = (uint8_t)wlanCfgGetUint32(prAdapter, + "StaVHTMuBfee", FEATURE_ENABLED); + prWifiVar->ucStaHtBfer = (uint8_t) wlanCfgGetUint32(prAdapter, + "StaHTBfer", FEATURE_DISABLED); + prWifiVar->ucStaVhtBfer = (uint8_t) wlanCfgGetUint32(prAdapter, + "StaVHTBfer", FEATURE_DISABLED); + + /* 0: disabled + * 1: Tx done event to driver + * 2: Tx status to FW only + */ + prWifiVar->ucDataTxDone = (uint8_t) wlanCfgGetUint32( + prAdapter, "DataTxDone", 0); + prWifiVar->ucDataTxRateMode = (uint8_t) wlanCfgGetUint32( + prAdapter, "DataTxRateMode", + DATA_RATE_MODE_AUTO); + prWifiVar->u4DataTxRateCode = wlanCfgGetUint32( + prAdapter, "DataTxRateCode", 0x0); + + prWifiVar->ucApWpsMode = (uint8_t) wlanCfgGetUint32( + prAdapter, "ApWpsMode", 0); + DBGLOG(INIT, TRACE, "ucApWpsMode = %u\n", prWifiVar->ucApWpsMode); + + prWifiVar->ucThreadScheduling = (uint8_t) wlanCfgGetUint32( + prAdapter, "ThreadSched", 0); + prWifiVar->ucThreadPriority = (uint8_t) wlanCfgGetUint32( + prAdapter, "ThreadPriority", + WLAN_THREAD_TASK_PRIORITY); + prWifiVar->cThreadNice = (int8_t) wlanCfgGetInt32( + prAdapter, "ThreadNice", + WLAN_THREAD_TASK_NICE); + + prAdapter->rQM.u4MaxForwardBufferCount = (uint32_t) wlanCfgGetUint32( + prAdapter, "ApForwardBufferCnt", + QM_FWD_PKT_QUE_THRESHOLD); + + /* AP channel setting + * 0: auto + */ + prWifiVar->ucApChannel = (uint8_t) wlanCfgGetUint32( + prAdapter, "ApChannel", 0); + + /* + * 0: SCN + * 1: SCA + * 2: RES + * 3: SCB + */ + prWifiVar->ucApSco = (uint8_t) wlanCfgGetUint32( + prAdapter, "ApSco", 0); + prWifiVar->ucP2pGoSco = (uint8_t) wlanCfgGetUint32( + prAdapter, "P2pGoSco", 0); + + /* Max bandwidth setting + * 0: 20Mhz + * 1: 40Mhz + * 2: 80Mhz + * 3: 160Mhz + * 4: 80+80Mhz + * Note: For VHT STA, BW 80Mhz is a must! + */ + prWifiVar->ucStaBandwidth = (uint8_t) wlanCfgGetUint32( + prAdapter, "StaBw", MAX_BW_160MHZ); + prWifiVar->ucSta2gBandwidth = (uint8_t) wlanCfgGetUint32( + prAdapter, "Sta2gBw", MAX_BW_20MHZ); + prWifiVar->ucSta5gBandwidth = (uint8_t) wlanCfgGetUint32( + prAdapter, "Sta5gBw", MAX_BW_80MHZ); + /* GC,GO */ + prWifiVar->ucP2p2gBandwidth = (uint8_t) wlanCfgGetUint32( + prAdapter, "P2p2gBw", MAX_BW_20MHZ); + prWifiVar->ucP2p5gBandwidth = (uint8_t) wlanCfgGetUint32( + prAdapter, "P2p5gBw", MAX_BW_80MHZ); + prWifiVar->ucApBandwidth = (uint8_t) wlanCfgGetUint32( + prAdapter, "ApBw", MAX_BW_160MHZ); + prWifiVar->ucAp2gBandwidth = (uint8_t) wlanCfgGetUint32( + prAdapter, "Ap2gBw", MAX_BW_20MHZ); + prWifiVar->ucAp5gBandwidth = (uint8_t) wlanCfgGetUint32( + prAdapter, "Ap5gBw", MAX_BW_80MHZ); + prWifiVar->ucApChnlDefFromCfg = (uint8_t) wlanCfgGetUint32( + prAdapter, "ApChnlDefFromCfg", FEATURE_ENABLED); + prWifiVar->ucApAllowHtVhtTkip = (uint8_t) wlanCfgGetUint32( + prAdapter, "ApAllowHtVhtTkip", + FEATURE_DISABLED); + + prWifiVar->ucNSS = (uint8_t) wlanCfgGetUint32(prAdapter, "Nss", 2); + + /* Max Rx MPDU length setting + * 0: 3k + * 1: 8k + * 2: 11k + */ + prWifiVar->ucRxMaxMpduLen = (uint8_t) wlanCfgGetUint32( + prAdapter, "RxMaxMpduLen", + VHT_CAP_INFO_MAX_MPDU_LEN_3K); + /* Max Tx AMSDU in AMPDU length *in BYTES* */ + prWifiVar->u4TxMaxAmsduInAmpduLen = wlanCfgGetUint32( + prAdapter, "TxMaxAmsduInAmpduLen", + 4096); + + prWifiVar->ucTcRestrict = (uint8_t) wlanCfgGetUint32( + prAdapter, "TcRestrict", 0xFF); + /* Max Tx dequeue limit: 0 => auto */ + prWifiVar->u4MaxTxDeQLimit = (uint32_t) wlanCfgGetUint32( + prAdapter, "MaxTxDeQLimit", 0x0); + prWifiVar->ucAlwaysResetUsedRes = (uint32_t) wlanCfgGetUint32( + prAdapter, "AlwaysResetUsedRes", 0x0); + + prWifiVar->u4BeaconTimoutFilterDurationMs = + wlanCfgGetUint32(prAdapter, + "BeaconTimoutFilterDurationMs", + CFG_BEACON_TIMEOUT_FILTER_DURATION_DEFAULT_VALUE); + +#if CFG_SUPPORT_MTK_SYNERGY + prWifiVar->ucMtkOui = (uint8_t) wlanCfgGetUint32( + prAdapter, "MtkOui", FEATURE_ENABLED); + prWifiVar->u4MtkOuiCap = (uint32_t) wlanCfgGetUint32( + prAdapter, "MtkOuiCap", 0); + prWifiVar->aucMtkFeature[0] = 0xff; + prWifiVar->aucMtkFeature[1] = 0xff; + prWifiVar->aucMtkFeature[2] = 0xff; + prWifiVar->aucMtkFeature[3] = 0xff; + prWifiVar->ucGbandProbe256QAM = (uint8_t) wlanCfgGetUint32( + prAdapter, "Probe256QAM", + FEATURE_DISABLED); +#endif +#if CFG_SUPPORT_VHT_IE_IN_2G + prWifiVar->ucVhtIeIn2g = + (uint8_t) wlanCfgGetUint32(prAdapter, "VhtIeIn2G", + FEATURE_DISABLED); +#endif + prWifiVar->ucCmdRsvResource = (uint8_t) wlanCfgGetUint32( + prAdapter, "TxCmdRsv", + QM_CMD_RESERVED_THRESHOLD); + prWifiVar->u4MgmtQueueDelayTimeout = + (uint32_t) wlanCfgGetUint32(prAdapter, "TxMgmtQueTO", + QM_MGMT_QUEUED_TIMEOUT); /* ms */ + + /* Performance related */ + prWifiVar->u4HifIstLoopCount = (uint32_t) wlanCfgGetUint32( + prAdapter, "IstLoop", + CFG_IST_LOOP_COUNT); + prWifiVar->u4Rx2OsLoopCount = (uint32_t) wlanCfgGetUint32( + prAdapter, "Rx2OsLoop", 4); + prWifiVar->u4HifTxloopCount = (uint32_t) wlanCfgGetUint32( + prAdapter, "HifTxLoop", 1); + prWifiVar->u4TxFromOsLoopCount = (uint32_t) wlanCfgGetUint32( + prAdapter, "OsTxLoop", 1); + prWifiVar->u4TxRxLoopCount = (uint32_t) wlanCfgGetUint32( + prAdapter, "Rx2ReorderLoop", 1); + prWifiVar->u4TxIntThCount = (uint32_t) wlanCfgGetUint32( + prAdapter, "IstTxTh", + HIF_IST_TX_THRESHOLD); + + prWifiVar->u4NetifStopTh = (uint32_t) wlanCfgGetUint32( + prAdapter, "NetifStopTh", + CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD); + prWifiVar->u4NetifStartTh = (uint32_t) wlanCfgGetUint32( + prAdapter, "NetifStartTh", + CFG_TX_START_NETIF_PER_QUEUE_THRESHOLD); + prWifiVar->ucTxBaSize = (uint8_t) wlanCfgGetUint32( + prAdapter, "TxBaSize", 64); + prWifiVar->ucRxHtBaSize = (uint8_t) wlanCfgGetUint32( + prAdapter, "RxHtBaSize", 64); + prWifiVar->ucRxVhtBaSize = (uint8_t) wlanCfgGetUint32( + prAdapter, "RxVhtBaSize", 64); + + /* Tx Buffer Management */ + prWifiVar->ucExtraTxDone = (uint32_t) wlanCfgGetUint32( + prAdapter, "ExtraTxDone", 1); + prWifiVar->ucTxDbg = (uint32_t) wlanCfgGetUint32(prAdapter, "TxDbg", 0); + + kalMemZero(prWifiVar->au4TcPageCount, + sizeof(prWifiVar->au4TcPageCount)); + + prWifiVar->au4TcPageCount[TC0_INDEX] = (uint32_t) wlanCfgGetUint32( + prAdapter, "Tc0Page", + NIC_TX_PAGE_COUNT_TC0); + prWifiVar->au4TcPageCount[TC1_INDEX] = (uint32_t) wlanCfgGetUint32( + prAdapter, "Tc1Page", + NIC_TX_PAGE_COUNT_TC1); + prWifiVar->au4TcPageCount[TC2_INDEX] = (uint32_t) wlanCfgGetUint32( + prAdapter, "Tc2Page", + NIC_TX_PAGE_COUNT_TC2); + prWifiVar->au4TcPageCount[TC3_INDEX] = (uint32_t) wlanCfgGetUint32( + prAdapter, "Tc3Page", + NIC_TX_PAGE_COUNT_TC3); + prWifiVar->au4TcPageCount[TC4_INDEX] = (uint32_t) wlanCfgGetUint32( + prAdapter, "Tc4Page", + NIC_TX_PAGE_COUNT_TC4); + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + prQM->au4MinReservedTcResource[TC0_INDEX] = (uint32_t) wlanCfgGetUint32( + prAdapter, "Tc0MinRsv", + QM_MIN_RESERVED_TC0_RESOURCE); + prQM->au4MinReservedTcResource[TC1_INDEX] = (uint32_t) wlanCfgGetUint32( + prAdapter, "Tc1MinRsv", + QM_MIN_RESERVED_TC1_RESOURCE); + prQM->au4MinReservedTcResource[TC2_INDEX] = (uint32_t) wlanCfgGetUint32( + prAdapter, "Tc2MinRsv", + QM_MIN_RESERVED_TC2_RESOURCE); + prQM->au4MinReservedTcResource[TC3_INDEX] = (uint32_t) wlanCfgGetUint32( + prAdapter, "Tc3MinRsv", + QM_MIN_RESERVED_TC3_RESOURCE); + prQM->au4MinReservedTcResource[TC4_INDEX] = (uint32_t) wlanCfgGetUint32( + prAdapter, "Tc4MinRsv", + QM_MIN_RESERVED_TC4_RESOURCE); + + prQM->au4GuaranteedTcResource[TC0_INDEX] = (uint32_t) wlanCfgGetUint32( + prAdapter, "Tc0Grt", + QM_GUARANTEED_TC0_RESOURCE); + prQM->au4GuaranteedTcResource[TC1_INDEX] = + (uint32_t) wlanCfgGetUint32(prAdapter, "Tc1Grt", + QM_GUARANTEED_TC1_RESOURCE); + prQM->au4GuaranteedTcResource[TC2_INDEX] = + (uint32_t) wlanCfgGetUint32(prAdapter, "Tc2Grt", + QM_GUARANTEED_TC2_RESOURCE); + prQM->au4GuaranteedTcResource[TC3_INDEX] = (uint32_t) wlanCfgGetUint32( + prAdapter, "Tc3Grt", + QM_GUARANTEED_TC3_RESOURCE); + prQM->au4GuaranteedTcResource[TC4_INDEX] = (uint32_t) wlanCfgGetUint32( + prAdapter, "Tc4Grt", + QM_GUARANTEED_TC4_RESOURCE); + + prQM->u4TimeToAdjustTcResource = (uint32_t) wlanCfgGetUint32( + prAdapter, "TcAdjustTime", + QM_INIT_TIME_TO_ADJUST_TC_RSC); + prQM->u4TimeToUpdateQueLen = (uint32_t) wlanCfgGetUint32( + prAdapter, "QueLenUpdateTime", + QM_INIT_TIME_TO_UPDATE_QUE_LEN); + prQM->u4QueLenMovingAverage = (uint32_t) wlanCfgGetUint32( + prAdapter, "QueLenMovingAvg", + QM_QUE_LEN_MOVING_AVE_FACTOR); + prQM->u4ExtraReservedTcResource = (uint32_t) wlanCfgGetUint32( + prAdapter, "TcExtraRsv", + QM_EXTRA_RESERVED_RESOURCE_WHEN_BUSY); +#endif + + /* Stats log */ + prWifiVar->u4StatsLogTimeout = (uint32_t) wlanCfgGetUint32( + prAdapter, "StatsLogTO", + WLAN_TX_STATS_LOG_TIMEOUT); + prWifiVar->u4StatsLogDuration = (uint32_t) wlanCfgGetUint32( + prAdapter, "StatsLogDur", + WLAN_TX_STATS_LOG_DURATION); + + prWifiVar->ucDhcpTxDone = (uint8_t) wlanCfgGetUint32( + prAdapter, "DhcpTxDone", 1); + prWifiVar->ucArpTxDone = (uint8_t) wlanCfgGetUint32( + prAdapter, "ArpTxDone", 1); + + prWifiVar->ucMacAddrOverride = (uint8_t) wlanCfgGetInt32( + prAdapter, "MacOverride", 0); + if (wlanCfgGet(prAdapter, "MacAddr", prWifiVar->aucMacAddrStr, + "00:0c:e7:66:32:e1", 0)) + DBGLOG(INIT, ERROR, "get MacAddr fail, use defaul\n"); + + prWifiVar->ucCtiaMode = (uint8_t) wlanCfgGetUint32( + prAdapter, "CtiaMode", 0); + + /* Combine ucTpTestMode and ucSigmaTestMode in one flag */ + /* ucTpTestMode == 0, for normal driver */ + /* ucTpTestMode == 1, for pure throughput test mode (ex: RvR) */ + /* ucTpTestMode == 2, for sigma TGn/TGac/PMF */ + /* ucTpTestMode == 3, for sigma WMM PS */ + prWifiVar->ucTpTestMode = (uint8_t) wlanCfgGetUint32( + prAdapter, "TpTestMode", 0); + +#if IS_ENABLED(CFG_RX_NAPI_SUPPORT) + prWifiVar->ucRxNapiEnable = (uint8_t) wlanCfgGetUint32( + prAdapter, "RxNapi", 0); + prWifiVar->ucRxNapiPktChk = (uint8_t) wlanCfgGetUint32( + prAdapter, "RxNapiPktChk", 1); + prWifiVar->ucRxNapiThread = (uint8_t) wlanCfgGetUint32( + prAdapter, "RxNapiThread", 0); + prWifiVar->ucRxNapiNoTx = (uint8_t) wlanCfgGetUint32( + prAdapter, "RxNapiNoTx", 1); + prWifiVar->ucRxNapiThreshold = (uint8_t) wlanCfgGetUint32( + prAdapter, "RxNapiThreshold", 50); +#endif /* CFG_RX_NAPI_SUPPORT */ + +#if 0 + prWifiVar->ucSigmaTestMode = (uint8_t) wlanCfgGetUint32( + prAdapter, "SigmaTestMode", 0); +#endif + +#if CFG_SUPPORT_DBDC + prWifiVar->eDbdcMode = (uint8_t) wlanCfgGetUint32( + prAdapter, "DbdcMode", + ENUM_DBDC_MODE_DISABLED); +#endif /*CFG_SUPPORT_DBDC*/ +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1) + prWifiVar->ucEfuseBufferModeCal = (uint8_t) wlanCfgGetUint32( + prAdapter, "EfuseBufferModeCal", 0); +#endif + prWifiVar->ucCalTimingCtrl = (uint8_t) wlanCfgGetUint32( + prAdapter, "CalTimingCtrl", + 0 /* power on full cal */); + prWifiVar->ucWow = (uint8_t) wlanCfgGetUint32( + prAdapter, "Wow", FEATURE_DISABLED); + prWifiVar->ucOffload = (uint8_t) wlanCfgGetUint32( + prAdapter, "Offload", FEATURE_DISABLED); + prWifiVar->ucAdvPws = (uint8_t) wlanCfgGetUint32( + prAdapter, "AdvPws", FEATURE_DISABLED); + prWifiVar->ucWowOnMdtim = (uint8_t) wlanCfgGetUint32( + prAdapter, "WowOnMdtim", 1); + prWifiVar->ucWowOffMdtim = (uint8_t) wlanCfgGetUint32( + prAdapter, "WowOffMdtim", 3); + prWifiVar->ucWowPwsMode = (uint8_t) wlanCfgGetUint32( + prAdapter, "WowPsMode", Param_PowerModeFast_PSP); + prWifiVar->ucListenDtimInterval = + (uint8_t) wlanCfgGetUint32(prAdapter, "ListenDtimInt", + DEFAULT_LISTEN_INTERVAL_BY_DTIM_PERIOD); + prWifiVar->ucEapolOffload = (uint8_t) wlanCfgGetUint32( +#if CFG_SUPPORT_REPLAY_DETECTION + prAdapter, "EapolOffload", FEATURE_DISABLED); +#else + prAdapter, "EapolOffload", FEATURE_ENABLED); +#endif + prWifiVar->ucEnforcePSMode = (uint8_t) wlanCfgGetUint32( + prAdapter, "EnforcePSMode", Param_PowerModeMax); +#if CFG_SUPPORT_REPLAY_DETECTION + prWifiVar->ucRpyDetectOffload = (uint8_t) wlanCfgGetUint32( + prAdapter, "rpydetectoffload", + FEATURE_ENABLED); +#endif + + +#if CFG_WOW_SUPPORT + prAdapter->rWowCtrl.fgWowEnable = (uint8_t) wlanCfgGetUint32( + prAdapter, "WowEnable", + FEATURE_ENABLED); + prAdapter->rWowCtrl.ucScenarioId = (uint8_t) wlanCfgGetUint32( + prAdapter, "WowScenarioId", 0); + prAdapter->rWowCtrl.ucBlockCount = (uint8_t) wlanCfgGetUint32( + prAdapter, "WowPinCnt", 1); + prAdapter->rWowCtrl.astWakeHif[0].ucWakeupHif = + (uint8_t) wlanCfgGetUint32( + prAdapter, "WowHif", + ENUM_HIF_TYPE_GPIO); + prAdapter->rWowCtrl.astWakeHif[0].ucGpioPin = + (uint8_t) wlanCfgGetUint32(prAdapter, "WowGpioPin", 0xFF); + prAdapter->rWowCtrl.astWakeHif[0].ucTriggerLvl = + (uint8_t) wlanCfgGetUint32(prAdapter, "WowTriigerLevel", 3); + prAdapter->rWowCtrl.astWakeHif[0].u4GpioInterval = + wlanCfgGetUint32(prAdapter, "GpioInterval", 0); +#endif + + /* SW Test Mode: Mainly used for Sigma */ + prWifiVar->u4SwTestMode = (uint8_t) wlanCfgGetUint32( + prAdapter, "Sigma", + ENUM_SW_TEST_MODE_NONE); + prWifiVar->ucCtrlFlagAssertPath = (uint8_t) wlanCfgGetUint32( + prAdapter, "AssertPath", + DBG_ASSERT_PATH_DEFAULT); + prWifiVar->ucCtrlFlagDebugLevel = (uint8_t) wlanCfgGetUint32( + prAdapter, "AssertLevel", + DBG_ASSERT_CTRL_LEVEL_DEFAULT); + prWifiVar->u4ScanCtrl = (uint8_t) wlanCfgGetUint32( + prAdapter, "ScanCtrl", + SCN_CTRL_DEFAULT_SCAN_CTRL); + prWifiVar->ucScanChannelListenTime = (uint8_t) wlanCfgGetUint32( + prAdapter, "ScnChListenTime", 0); + + /* Wake lock related configuration */ + prWifiVar->u4WakeLockRxTimeout = wlanCfgGetUint32( + prAdapter, "WakeLockRxTO", + WAKE_LOCK_RX_TIMEOUT); + prWifiVar->u4WakeLockThreadWakeup = wlanCfgGetUint32( + prAdapter, "WakeLockThreadTO", + WAKE_LOCK_THREAD_WAKEUP_TIMEOUT); + + prWifiVar->ucSmartRTS = (uint8_t) wlanCfgGetUint32( + prAdapter, "SmartRTS", 0); + prWifiVar->ePowerMode = (enum PARAM_POWER_MODE) wlanCfgGetUint32( + prAdapter, "PowerSave", + Param_PowerModeMax); + + prWifiVar->fgActiveModeCam = (uint8_t) wlanCfgGetUint32( + prAdapter, "ActiveModeCam", + FEATURE_DISABLED); + +#if 1 + /* add more cfg from RegInfo */ + prWifiVar->u4UapsdAcBmp = (uint32_t) wlanCfgGetUint32( + prAdapter, "UapsdAcBmp", 0); + prWifiVar->u4MaxSpLen = (uint32_t) wlanCfgGetUint32( + prAdapter, "MaxSpLen", 0); + prWifiVar->fgDisOnlineScan = (uint32_t) wlanCfgGetUint32( + prAdapter, "DisOnlineScan", 0); + prWifiVar->fgDisBcnLostDetection = (uint32_t) wlanCfgGetUint32( + prAdapter, "DisBcnLostDetection", 0); + prWifiVar->fgDisRoaming = (uint32_t) wlanCfgGetUint32( + prAdapter, "DisRoaming", 0); + prWifiVar->fgEnArpFilter = (uint32_t) wlanCfgGetUint32( + prAdapter, "EnArpFilter", + FEATURE_ENABLED); +#endif + + /* Driver Flow Control Dequeue Quota. Now is only used by DBDC */ + prWifiVar->uDeQuePercentEnable = + (uint8_t) wlanCfgGetUint32(prAdapter, "DeQuePercentEnable", 1); + prWifiVar->u4DeQuePercentVHT80Nss1 = + (uint32_t) wlanCfgGetUint32(prAdapter, "DeQuePercentVHT80NSS1", + QM_DEQUE_PERCENT_VHT80_NSS1); + prWifiVar->u4DeQuePercentVHT40Nss1 = + (uint32_t) wlanCfgGetUint32(prAdapter, "DeQuePercentVHT40NSS1", + QM_DEQUE_PERCENT_VHT40_NSS1); + prWifiVar->u4DeQuePercentVHT20Nss1 = + (uint32_t) wlanCfgGetUint32(prAdapter, "DeQuePercentVHT20NSS1", + QM_DEQUE_PERCENT_VHT20_NSS1); + prWifiVar->u4DeQuePercentHT40Nss1 = + (uint32_t) wlanCfgGetUint32(prAdapter, "DeQuePercentHT40NSS1", + QM_DEQUE_PERCENT_HT40_NSS1); + prWifiVar->u4DeQuePercentHT20Nss1 = + (uint32_t) wlanCfgGetUint32(prAdapter, "DeQuePercentHT20NSS1", + QM_DEQUE_PERCENT_HT20_NSS1); + + /* Support TDLS 5.5.4.2 optional case */ + prWifiVar->fgTdlsBufferSTASleep = (u_int8_t) wlanCfgGetUint32(prAdapter, + "TdlsBufferSTASleep", FEATURE_DISABLED); + /* Support USB Whole chip reset recover */ + prWifiVar->fgChipResetRecover = (u_int8_t) wlanCfgGetUint32(prAdapter, + "ChipResetRecover", FEATURE_DISABLED); + + prWifiVar->u4PerfMonUpdatePeriod = + (uint32_t) wlanCfgGetUint32(prAdapter, "PerfMonPeriod", + PERF_MON_UPDATE_INTERVAL); + + prWifiVar->u4PerfMonTpTh[0] = + (uint32_t) wlanCfgGetUint32(prAdapter, "PerfMonLv1", 20); + prWifiVar->u4PerfMonTpTh[1] = + (uint32_t) wlanCfgGetUint32(prAdapter, "PerfMonLv2", 50); + prWifiVar->u4PerfMonTpTh[2] = + (uint32_t) wlanCfgGetUint32(prAdapter, "PerfMonLv3", 135); + prWifiVar->u4PerfMonTpTh[3] = + (uint32_t) wlanCfgGetUint32(prAdapter, "PerfMonLv4", 180); + prWifiVar->u4PerfMonTpTh[4] = + (uint32_t) wlanCfgGetUint32(prAdapter, "PerfMonLv5", 250); + prWifiVar->u4PerfMonTpTh[5] = + (uint32_t) wlanCfgGetUint32(prAdapter, "PerfMonLv6", 300); + prWifiVar->u4PerfMonTpTh[6] = + (uint32_t) wlanCfgGetUint32(prAdapter, "PerfMonLv7", 400); + prWifiVar->u4PerfMonTpTh[7] = + (uint32_t) wlanCfgGetUint32(prAdapter, "PerfMonLv8", 500); + prWifiVar->u4PerfMonTpTh[8] = + (uint32_t) wlanCfgGetUint32(prAdapter, "PerfMonLv9", 600); + prWifiVar->u4PerfMonTpTh[9] = + (uint32_t) wlanCfgGetUint32(prAdapter, "PerfMonLv10", 700); + prWifiVar->u4BoostCpuTh = + (uint32_t) wlanCfgGetUint32(prAdapter, "BoostCpuTh", 1); + + /* + * For Certification purpose,forcibly set + * "Compressed Steering Number of Beamformer Antennas Supported" to our + * own capability. + */ + prWifiVar->fgForceSTSNum = (uint8_t)wlanCfgGetUint32( + prAdapter, "ForceSTSNum", 0); + +#if CFG_SUPPORT_SPE_IDX_CONTROL + prWifiVar->ucSpeIdxCtrl = (uint8_t) wlanCfgGetUint32( + prAdapter, "SpeIdxCtrl", 2); +#if CFG_SUPPORT_COEX_NON_COTX + prWifiVar->ucSpeIdxCtrl2g = (uint8_t) wlanCfgGetUint32( + prAdapter, "SpeIdxCtrl2g", 2); + prWifiVar->fgCoexNonCoTx = (uint8_t) wlanCfgGetUint32( + prAdapter, "CoexNonCoTx", FEATURE_DISABLED); +#endif +#endif + +#if CFG_SUPPORT_LOWLATENCY_MODE + prWifiVar->ucLowLatencyModeScan = (uint32_t) wlanCfgGetUint32( + prAdapter, "LowLatencyModeScan", FEATURE_ENABLED); + prWifiVar->ucLowLatencyModeReOrder = (uint32_t) wlanCfgGetUint32( + prAdapter, "LowLatencyModeReOrder", FEATURE_ENABLED); + prWifiVar->ucLowLatencyModePower = (uint32_t) wlanCfgGetUint32( + prAdapter, "LowLatencyModePower", FEATURE_ENABLED); +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + +#ifdef CFG_SUPPORT_ADJUST_JOIN_CH_REQ_INTERVAL + prWifiVar->u4AisJoinChReqIntervel = + (uint32_t) wlanCfgGetUint32(prAdapter, "AisJoinChReqIntervel", + AIS_JOIN_CH_REQUEST_INTERVAL); + if (AIS_JOIN_CH_REQUEST_MAX_INTERVAL < + prWifiVar->u4AisJoinChReqIntervel) + prWifiVar->u4AisJoinChReqIntervel = + AIS_JOIN_CH_REQUEST_MAX_INTERVAL; +#endif + prWifiVar->ucEd2GNonEU = (int32_t) wlanCfgGetInt32(prAdapter, + "Ed2GNonEU", ED_CCA_BW20_2G_DEFAULT); + prWifiVar->ucEd5GNonEU = (int32_t) wlanCfgGetInt32(prAdapter, + "Ed5GNonEU", ED_CCA_BW20_5G_DEFAULT); + prWifiVar->ucEd2GEU = (int32_t) wlanCfgGetInt32(prAdapter, + "Ed2GEU", ED_CCA_BW20_2G_DEFAULT); + prWifiVar->ucEd5GEU = (int32_t) wlanCfgGetInt32(prAdapter, + "Ed5GEU", ED_CCA_BW20_5G_DEFAULT); + prWifiVar->ucEnforceCAM2G = + (uint8_t) wlanCfgGetUint32(prAdapter, "EnforceCAM2G", 0); + +} + +void wlanCfgSetSwCtrl(IN struct ADAPTER *prAdapter) +{ + uint32_t i = 0; + int8_t aucKey[WLAN_CFG_VALUE_LEN_MAX]; + int8_t aucValue[WLAN_CFG_VALUE_LEN_MAX]; + + const int8_t acDelim[] = " "; + int8_t *pcPtr = NULL; + int8_t *pcDupValue = NULL; + uint32_t au4Values[2]; + uint32_t u4TokenCount = 0; + uint32_t u4BufLen = 0; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + int32_t u4Ret = 0; + + for (i = 0; i < WLAN_CFG_SET_SW_CTRL_LEN_MAX; i++) { + kalMemZero(aucValue, WLAN_CFG_VALUE_LEN_MAX); + kalMemZero(aucKey, WLAN_CFG_VALUE_LEN_MAX); + kalSnprintf(aucKey, sizeof(aucKey), "SwCtrl%d", i); + + /* get nothing */ + if (wlanCfgGet(prAdapter, aucKey, aucValue, "", + 0) != WLAN_STATUS_SUCCESS) + continue; + if (!kalStrCmp(aucValue, "")) + continue; + + pcDupValue = aucValue; + u4TokenCount = 0; + + while ((pcPtr = kalStrSep((char **)(&pcDupValue), acDelim)) + != NULL) { + + if (!kalStrCmp(pcPtr, "")) + continue; + + /* au4Values[u4TokenCount] = kalStrtoul(pcPtr, NULL, 0); + */ + u4Ret = kalkStrtou32(pcPtr, 0, + &(au4Values[u4TokenCount])); + if (u4Ret) + DBGLOG(INIT, LOUD, + "parse au4Values error u4Ret=%d\n", + u4Ret); + u4TokenCount++; + + /* Only need 2 tokens */ + if (u4TokenCount >= 2) + break; + } + + if (u4TokenCount != 2) + continue; + + rSwCtrlInfo.u4Id = au4Values[0]; + rSwCtrlInfo.u4Data = au4Values[1]; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + } +} + +void wlanCfgSetChip(IN struct ADAPTER *prAdapter) +{ + uint32_t i = 0; + int8_t aucKey[WLAN_CFG_VALUE_LEN_MAX]; + int8_t aucValue[WLAN_CFG_VALUE_LEN_MAX]; + + uint32_t u4BufLen = 0; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct PARAM_CUSTOM_CHIP_CONFIG_STRUCT rChipConfigInfo; + + for (i = 0; i < WLAN_CFG_SET_CHIP_LEN_MAX; i++) { + kalMemZero(aucValue, WLAN_CFG_VALUE_LEN_MAX); + kalMemZero(aucKey, WLAN_CFG_VALUE_LEN_MAX); + kalSnprintf(aucKey, sizeof(aucKey), "SetChip%d", i); + + /* get nothing */ + if (wlanCfgGet(prAdapter, aucKey, aucValue, "", + 0) != WLAN_STATUS_SUCCESS) + continue; + if (!kalStrCmp(aucValue, "")) + continue; + + kalMemZero(&rChipConfigInfo, sizeof(rChipConfigInfo)); + + rChipConfigInfo.ucType = CHIP_CONFIG_TYPE_WO_RESPONSE; + rChipConfigInfo.u2MsgSize = kalStrnLen(aucValue, + WLAN_CFG_VALUE_LEN_MAX); + kalStrnCpy(rChipConfigInfo.aucCmd, aucValue, + CHIP_CONFIG_RESP_SIZE); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetChipConfig, + &rChipConfigInfo, sizeof(rChipConfigInfo), + FALSE, FALSE, TRUE, &u4BufLen); + } + +} + +void wlanCfgSetDebugLevel(IN struct ADAPTER *prAdapter) +{ + uint32_t i = 0; + int8_t aucKey[WLAN_CFG_VALUE_LEN_MAX]; + int8_t aucValue[WLAN_CFG_VALUE_LEN_MAX]; + const int8_t acDelim[] = " "; + int8_t *pcDupValue; + int8_t *pcPtr = NULL; + + uint32_t au4Values[2]; + uint32_t u4TokenCount = 0; + uint32_t u4DbgIdx = 0; + uint32_t u4DbgMask = 0; + int32_t u4Ret = 0; + + for (i = 0; i < WLAN_CFG_SET_DEBUG_LEVEL_LEN_MAX; i++) { + kalMemZero(aucValue, WLAN_CFG_VALUE_LEN_MAX); + kalMemZero(aucKey, WLAN_CFG_VALUE_LEN_MAX); + kalSnprintf(aucKey, sizeof(aucKey), "DbgLevel%d", i); + + /* get nothing */ + if (wlanCfgGet(prAdapter, aucKey, aucValue, "", + 0) != WLAN_STATUS_SUCCESS) + continue; + if (!kalStrCmp(aucValue, "")) + continue; + + pcDupValue = aucValue; + u4TokenCount = 0; + + while ((pcPtr = kalStrSep((char **)(&pcDupValue), + acDelim)) != NULL) { + + if (!kalStrCmp(pcPtr, "")) + continue; + + /* au4Values[u4TokenCount] = + * kalStrtoul(pcPtr, NULL, 0); + */ + u4Ret = kalkStrtou32(pcPtr, 0, + &(au4Values[u4TokenCount])); + if (u4Ret) + DBGLOG(INIT, LOUD, + "parse au4Values error u4Ret=%d\n", + u4Ret); + u4TokenCount++; + + /* Only need 2 tokens */ + if (u4TokenCount >= 2) + break; + } + + if (u4TokenCount != 2) + continue; + + u4DbgIdx = au4Values[0]; + u4DbgMask = au4Values[1]; + + /* DBG level special control */ + if (u4DbgIdx == 0xFFFFFFFF) { + wlanSetDriverDbgLevel(DBG_ALL_MODULE_IDX, u4DbgMask); + DBGLOG(INIT, INFO, + "Set ALL DBG module log level to [0x%02x]!", + (uint8_t) u4DbgMask); + } else if (u4DbgIdx == 0xFFFFFFFE) { + wlanDebugInit(); + DBGLOG(INIT, INFO, + "Reset ALL DBG module log level to DEFAULT!"); + } else if (u4DbgIdx < DBG_MODULE_NUM) { + wlanSetDriverDbgLevel(u4DbgIdx, u4DbgMask); + DBGLOG(INIT, INFO, + "Set DBG module[%u] log level to [0x%02x]!", + u4DbgIdx, (uint8_t) u4DbgMask); + } + } +} + +void wlanCfgSetCountryCode(IN struct ADAPTER *prAdapter) +{ + int8_t aucValue[WLAN_CFG_VALUE_LEN_MAX]; + + /* Apply COUNTRY Config */ + if (wlanCfgGet(prAdapter, "Country", aucValue, "", + 0) == WLAN_STATUS_SUCCESS) { + prAdapter->rWifiVar.rConnSettings.u2CountryCode = + (((uint16_t) aucValue[0]) << 8) | + ((uint16_t) aucValue[1]); + + DBGLOG(INIT, INFO, "u2CountryCode=0x%04x\n", + prAdapter->rWifiVar.rConnSettings.u2CountryCode); + + if (regd_is_single_sku_en()) { + rlmDomainOidSetCountry(prAdapter, aucValue, 2); + return; + } + + /* Force to re-search country code in regulatory domains */ + prAdapter->prDomainInfo = NULL; + rlmDomainSendCmd(prAdapter); + + /* Update supported channel list in channel table based on + * current country domain + */ + wlanUpdateChannelTable(prAdapter->prGlueInfo); + } +} + +#if CFG_SUPPORT_CFG_FILE + +struct WLAN_CFG_ENTRY *wlanCfgGetEntry(IN struct ADAPTER *prAdapter, + const int8_t *pucKey, + u_int8_t fgGetCfgRec) +{ + + struct WLAN_CFG_ENTRY *prWlanCfgEntry; + struct WLAN_CFG *prWlanCfg = NULL; + struct WLAN_CFG_REC *prWlanCfgRec = NULL; + uint32_t i, u32MaxNum; + + if (fgGetCfgRec) { + prWlanCfgRec = prAdapter->prWlanCfgRec; + u32MaxNum = WLAN_CFG_REC_ENTRY_NUM_MAX; + ASSERT(prWlanCfgRec); + } else { + prWlanCfg = prAdapter->prWlanCfg; + u32MaxNum = WLAN_CFG_ENTRY_NUM_MAX; + ASSERT(prWlanCfg); + } + + + ASSERT(pucKey); + + prWlanCfgEntry = NULL; + + for (i = 0; i < u32MaxNum; i++) { + if (fgGetCfgRec) + prWlanCfgEntry = &prWlanCfgRec->arWlanCfgBuf[i]; + else + prWlanCfgEntry = &prWlanCfg->arWlanCfgBuf[i]; + + if (prWlanCfgEntry->aucKey[0] != '\0') { + if (kalStrnCmp(pucKey, prWlanCfgEntry->aucKey, + WLAN_CFG_KEY_LEN_MAX - 1) == 0) + return prWlanCfgEntry; + } + } + + return NULL; + +} + + +struct WLAN_CFG_ENTRY *wlanCfgGetEntryByIndex( + IN struct ADAPTER *prAdapter, const uint8_t ucIdx, + uint32_t flag) +{ + + struct WLAN_CFG_ENTRY *prWlanCfgEntry; + struct WLAN_CFG *prWlanCfg; + struct WLAN_CFG_REC *prWlanCfgRec; + + + prWlanCfg = prAdapter->prWlanCfg; + prWlanCfgRec = prAdapter->prWlanCfgRec; + + ASSERT(prWlanCfg); + ASSERT(prWlanCfgRec); + + + prWlanCfgEntry = NULL; + + if (flag & WLAN_CFG_REC_FLAG_BIT) + prWlanCfgEntry = &prWlanCfgRec->arWlanCfgBuf[ucIdx]; + else + prWlanCfgEntry = &prWlanCfg->arWlanCfgBuf[ucIdx]; + + if (prWlanCfgEntry->aucKey[0] != '\0') { + DBGLOG(INIT, LOUD, "get Index(%d) saved key %s\n", ucIdx, + prWlanCfgEntry->aucKey); + return prWlanCfgEntry; + } + + DBGLOG(INIT, TRACE, + "wifi config there is no entry at index(%d)\n", ucIdx); + return NULL; + +} + + + +uint32_t wlanCfgGet(IN struct ADAPTER *prAdapter, + const int8_t *pucKey, int8_t *pucValue, int8_t *pucValueDef, + uint32_t u4Flags) +{ + + struct WLAN_CFG_ENTRY *prWlanCfgEntry; + struct WLAN_CFG *prWlanCfg; + + prWlanCfg = prAdapter->prWlanCfg; + + ASSERT(prWlanCfg); + ASSERT(pucValue); + + /* Find the exist */ + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey, FALSE); + + if (prWlanCfgEntry) { + kalMemCopy(pucValue, prWlanCfgEntry->aucValue, + WLAN_CFG_VALUE_LEN_MAX - 1); + return WLAN_STATUS_SUCCESS; + } + if (pucValueDef) + kalMemCopy(pucValue, pucValueDef, + WLAN_CFG_VALUE_LEN_MAX - 1); + return WLAN_STATUS_FAILURE; + + +} + +void wlanCfgRecordValue(IN struct ADAPTER *prAdapter, + const int8_t *pucKey, uint32_t u4Value) +{ + struct WLAN_CFG_ENTRY *prWlanCfgEntry; + uint8_t aucBuf[WLAN_CFG_VALUE_LEN_MAX]; + + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey, TRUE); + + kalMemZero(aucBuf, sizeof(aucBuf)); + + kalSnprintf(aucBuf, WLAN_CFG_VALUE_LEN_MAX, "0x%x", + (unsigned int)u4Value); + + wlanCfgSet(prAdapter, pucKey, aucBuf, 1); +} + + + +uint32_t wlanCfgGetUint32(IN struct ADAPTER *prAdapter, + const int8_t *pucKey, uint32_t u4ValueDef) +{ + struct WLAN_CFG_ENTRY *prWlanCfgEntry; + struct WLAN_CFG *prWlanCfg; + uint32_t u4Value; + int32_t u4Ret; + + prWlanCfg = prAdapter->prWlanCfg; + + ASSERT(prWlanCfg); + + u4Value = u4ValueDef; + /* Find the exist */ + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey, FALSE); + + if (prWlanCfgEntry) { + /* u4Ret = kalStrtoul(prWlanCfgEntry->aucValue, NULL, 0); */ + u4Ret = kalkStrtou32(prWlanCfgEntry->aucValue, 0, &u4Value); + if (u4Ret) + DBGLOG(INIT, LOUD, "parse aucValue error u4Ret=%d\n", + u4Ret); + } + + wlanCfgRecordValue(prAdapter, pucKey, u4Value); + + return u4Value; +} + +int32_t wlanCfgGetInt32(IN struct ADAPTER *prAdapter, + const int8_t *pucKey, int32_t i4ValueDef) +{ + struct WLAN_CFG_ENTRY *prWlanCfgEntry; + struct WLAN_CFG *prWlanCfg; + int32_t i4Value = 0; + int32_t i4Ret = 0; + + prWlanCfg = prAdapter->prWlanCfg; + + ASSERT(prWlanCfg); + + i4Value = i4ValueDef; + /* Find the exist */ + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey, FALSE); + + if (prWlanCfgEntry) { + /* i4Ret = kalStrtol(prWlanCfgEntry->aucValue, NULL, 0); */ + i4Ret = kalkStrtos32(prWlanCfgEntry->aucValue, 0, &i4Value); + if (i4Ret) + DBGLOG(INIT, LOUD, "parse aucValue error i4Ret=%d\n", + i4Ret); + } + + wlanCfgRecordValue(prAdapter, pucKey, (uint32_t)i4Value); + + return i4Value; +} + +uint32_t wlanCfgSet(IN struct ADAPTER *prAdapter, + const int8_t *pucKey, int8_t *pucValue, uint32_t u4Flags) +{ + + struct WLAN_CFG_ENTRY *prWlanCfgEntry; + struct WLAN_CFG *prWlanCfg = NULL; + struct WLAN_CFG_REC *prWlanCfgRec = NULL; + uint32_t u4EntryIndex; + uint32_t i; + uint8_t ucExist; + u_int8_t fgGetCfgRec = FALSE; + + + fgGetCfgRec = u4Flags & WLAN_CFG_REC_FLAG_BIT; + + ASSERT(pucKey); + + /* Find the exist */ + ucExist = 0; + if (fgGetCfgRec) { + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey, TRUE); + prWlanCfgRec = prAdapter->prWlanCfgRec; + ASSERT(prWlanCfgRec); + } else { + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey, FALSE); + prWlanCfg = prAdapter->prWlanCfg; + ASSERT(prWlanCfg); + } + + if (!prWlanCfgEntry) { + /* Find the empty */ + for (i = 0; i < WLAN_CFG_ENTRY_NUM_MAX; i++) { + if (fgGetCfgRec) + prWlanCfgEntry = &prWlanCfgRec->arWlanCfgBuf[i]; + else + prWlanCfgEntry = &prWlanCfg->arWlanCfgBuf[i]; + if (prWlanCfgEntry->aucKey[0] == '\0') + break; + } + + u4EntryIndex = i; + if (u4EntryIndex < WLAN_CFG_ENTRY_NUM_MAX) { + if (fgGetCfgRec) + prWlanCfgEntry = + &prWlanCfgRec->arWlanCfgBuf[u4EntryIndex]; + else + prWlanCfgEntry = + &prWlanCfg->arWlanCfgBuf[u4EntryIndex]; + kalMemZero(prWlanCfgEntry, + sizeof(struct WLAN_CFG_ENTRY)); + } else { + prWlanCfgEntry = NULL; + DBGLOG(INIT, ERROR, + "wifi config there is no empty entry\n"); + } + } /* !prWlanCfgEntry */ + else + ucExist = 1; + + if (prWlanCfgEntry) { + if (ucExist == 0) { + kalStrnCpy(prWlanCfgEntry->aucKey, pucKey, + WLAN_CFG_KEY_LEN_MAX - 1); + prWlanCfgEntry->aucKey[WLAN_CFG_KEY_LEN_MAX - 1] = '\0'; + } + + if (pucValue && pucValue[0] != '\0') { + kalStrnCpy(prWlanCfgEntry->aucValue, pucValue, + WLAN_CFG_VALUE_LEN_MAX - 1); + prWlanCfgEntry->aucValue[WLAN_CFG_VALUE_LEN_MAX - 1] = + '\0'; + + if (ucExist) { + if (prWlanCfgEntry->pfSetCb) + prWlanCfgEntry->pfSetCb(prAdapter, + prWlanCfgEntry->aucKey, + prWlanCfgEntry->aucValue, + prWlanCfgEntry->pPrivate, 0); + } + } else { + /* Call the pfSetCb if value is empty ? */ + /* remove the entry if value is empty */ + kalMemZero(prWlanCfgEntry, + sizeof(struct WLAN_CFG_ENTRY)); + } + + } + /* prWlanCfgEntry */ + if (prWlanCfgEntry) { + return WLAN_STATUS_SUCCESS; + } + if (pucKey) + DBGLOG(INIT, ERROR, "Set wifi config error key \'%s\'\n", + pucKey); + + if (pucValue) + DBGLOG(INIT, ERROR, "Set wifi config error value \'%s\'\n", + pucValue); + + return WLAN_STATUS_FAILURE; + + +} + +uint32_t +wlanCfgSetCb(IN struct ADAPTER *prAdapter, + const int8_t *pucKey, WLAN_CFG_SET_CB pfSetCb, + void *pPrivate, uint32_t u4Flags) +{ + + struct WLAN_CFG_ENTRY *prWlanCfgEntry; + struct WLAN_CFG *prWlanCfg; + + prWlanCfg = prAdapter->prWlanCfg; + ASSERT(prWlanCfg); + + /* Find the exist */ + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey, FALSE); + + if (prWlanCfgEntry) { + prWlanCfgEntry->pfSetCb = pfSetCb; + prWlanCfgEntry->pPrivate = pPrivate; + } + + if (prWlanCfgEntry) + return WLAN_STATUS_SUCCESS; + else + return WLAN_STATUS_FAILURE; + +} + +uint32_t wlanCfgSetUint32(IN struct ADAPTER *prAdapter, + const int8_t *pucKey, uint32_t u4Value) +{ + + struct WLAN_CFG *prWlanCfg; + uint8_t aucBuf[WLAN_CFG_VALUE_LEN_MAX]; + + prWlanCfg = prAdapter->prWlanCfg; + + ASSERT(prWlanCfg); + + kalMemZero(aucBuf, sizeof(aucBuf)); + + kalSnprintf(aucBuf, WLAN_CFG_VALUE_LEN_MAX, "0x%x", + (unsigned int)u4Value); + + return wlanCfgSet(prAdapter, pucKey, aucBuf, 0); +} + +enum { + STATE_EOF = 0, + STATE_TEXT = 1, + STATE_NEWLINE = 2 +}; + +struct WLAN_CFG_PARSE_STATE_S { + int8_t *ptr; + int8_t *text; +#if CFG_SUPPORT_EASY_DEBUG + uint32_t textsize; +#endif + int32_t nexttoken; + uint32_t maxSize; +}; + +int32_t wlanCfgFindNextToken(struct WLAN_CFG_PARSE_STATE_S + *state) +{ + int8_t *x = state->ptr; + int8_t *s; + + if (state->nexttoken) { + int32_t t = state->nexttoken; + + state->nexttoken = 0; + return t; + } + + for (;;) { + switch (*x) { + case 0: + state->ptr = x; + return STATE_EOF; + case '\n': + x++; + state->ptr = x; + return STATE_NEWLINE; + case ' ': + case ',': + /*case ':': should not including : , mac addr would be fail*/ + case '\t': + case '\r': + x++; + continue; + case '#': + while (*x && (*x != '\n')) + x++; + if (*x == '\n') { + state->ptr = x + 1; + return STATE_NEWLINE; + } + state->ptr = x; + return STATE_EOF; + + default: + goto text; + } + } + +textdone: + state->ptr = x; + *s = 0; + return STATE_TEXT; +text: + state->text = s = x; +textresume: + for (;;) { + switch (*x) { + case 0: + goto textdone; + case ' ': + case ',': + /* case ':': */ + case '\t': + case '\r': + x++; + goto textdone; + case '\n': + state->nexttoken = STATE_NEWLINE; + x++; + goto textdone; + case '"': + x++; + for (;;) { + switch (*x) { + case 0: + /* unterminated quoted thing */ + state->ptr = x; + return STATE_EOF; + case '"': + x++; + goto textresume; + default: + *s++ = *x++; + } + } + break; + case '\\': + x++; + switch (*x) { + case 0: + goto textdone; + case 'n': + *s++ = '\n'; + break; + case 'r': + *s++ = '\r'; + break; + case 't': + *s++ = '\t'; + break; + case '\\': + *s++ = '\\'; + break; + case '\r': + /* \ -> line continuation */ + if (x[1] != '\n') { + x++; + continue; + } + case '\n': + /* \ -> line continuation */ + x++; + /* eat any extra whitespace */ + while ((*x == ' ') || (*x == '\t')) + x++; + continue; + default: + /* unknown escape -- just copy */ + *s++ = *x++; + } + continue; + default: + *s++ = *x++; +#if CFG_SUPPORT_EASY_DEBUG + state->textsize++; +#endif + } + } + return STATE_EOF; +} + +uint32_t wlanCfgParseArgument(int8_t *cmdLine, + int32_t *argc, int8_t *argv[]) +{ + struct WLAN_CFG_PARSE_STATE_S state; + int8_t **args; + int32_t nargs; + + if (cmdLine == NULL || argc == NULL || argv == NULL) { + DBGLOG(INIT, ERROR, "parameter is NULL: %p, %p, %p\n", + cmdLine, argc, argv); + return WLAN_STATUS_FAILURE; + } + args = argv; + nargs = 0; + state.ptr = cmdLine; + state.nexttoken = 0; + state.maxSize = 0; +#if CFG_SUPPORT_EASY_DEBUG + state.textsize = 0; +#endif + + if (kalStrnLen(cmdLine, 512) >= 512) { + DBGLOG(INIT, ERROR, "cmdLine >= 512\n"); + return WLAN_STATUS_FAILURE; + } + + for (;;) { + switch (wlanCfgFindNextToken(&state)) { + case STATE_EOF: + goto exit; + case STATE_NEWLINE: + goto exit; + case STATE_TEXT: + if (nargs < WLAN_CFG_ARGV_MAX) + args[nargs++] = state.text; + break; + } + } + +exit: + *argc = nargs; + return WLAN_STATUS_SUCCESS; +} + +#if CFG_WOW_SUPPORT +uint32_t wlanCfgParseArgumentLong(int8_t *cmdLine, + int32_t *argc, int8_t *argv[]) +{ + struct WLAN_CFG_PARSE_STATE_S state; + int8_t **args; + int32_t nargs; + + if (cmdLine == NULL || argc == NULL || argv == NULL) { + DBGLOG(INIT, ERROR, "parameter is NULL: %p, %p, %p\n", + cmdLine, argc, argv); + return WLAN_STATUS_FAILURE; + } + args = argv; + nargs = 0; + state.ptr = cmdLine; + state.nexttoken = 0; + state.maxSize = 0; +#if CFG_SUPPORT_EASY_DEBUG + state.textsize = 0; +#endif + + if (kalStrnLen(cmdLine, 512) >= 512) { + DBGLOG(INIT, ERROR, "cmdLine >= 512\n"); + return WLAN_STATUS_FAILURE; + } + + for (;;) { + switch (wlanCfgFindNextToken(&state)) { + case STATE_EOF: + goto exit; + case STATE_NEWLINE: + goto exit; + case STATE_TEXT: + if (nargs < WLAN_CFG_ARGV_MAX_LONG) + args[nargs++] = state.text; + break; + } + } + +exit: + *argc = nargs; + return WLAN_STATUS_SUCCESS; +} +#endif + +uint32_t +wlanCfgParseAddEntry(IN struct ADAPTER *prAdapter, + uint8_t *pucKeyHead, uint8_t *pucKeyTail, + uint8_t *pucValueHead, uint8_t *pucValueTail) +{ + + uint8_t aucKey[WLAN_CFG_KEY_LEN_MAX]; + uint8_t aucValue[WLAN_CFG_VALUE_LEN_MAX]; + uint32_t u4Len; + + kalMemZero(aucKey, sizeof(aucKey)); + kalMemZero(aucValue, sizeof(aucValue)); + + if ((pucKeyHead == NULL) + || (pucValueHead == NULL) + ) + return WLAN_STATUS_FAILURE; + + if (pucKeyTail) { + if (pucKeyHead > pucKeyTail) + return WLAN_STATUS_FAILURE; + u4Len = pucKeyTail - pucKeyHead + 1; + } else + u4Len = kalStrnLen(pucKeyHead, WLAN_CFG_KEY_LEN_MAX - 1); + + if (u4Len >= WLAN_CFG_KEY_LEN_MAX) + u4Len = WLAN_CFG_KEY_LEN_MAX - 1; + + kalStrnCpy(aucKey, pucKeyHead, u4Len); + + if (pucValueTail) { + if (pucValueHead > pucValueTail) + return WLAN_STATUS_FAILURE; + u4Len = pucValueTail - pucValueHead + 1; + } else + u4Len = kalStrnLen(pucValueHead, + WLAN_CFG_VALUE_LEN_MAX - 1); + + if (u4Len >= WLAN_CFG_VALUE_LEN_MAX) + u4Len = WLAN_CFG_VALUE_LEN_MAX - 1; + + kalStrnCpy(aucValue, pucValueHead, u4Len); + + return wlanCfgSet(prAdapter, aucKey, aucValue, 0); +} + +enum { + WAIT_KEY_HEAD = 0, + WAIT_KEY_TAIL, + WAIT_VALUE_HEAD, + WAIT_VALUE_TAIL, + WAIT_COMMENT_TAIL +}; + +#if CFG_SUPPORT_EASY_DEBUG + +int8_t atoi(uint8_t ch) +{ + if (ch >= 'a' && ch <= 'f') + return ch - 87; + else if (ch >= 'A' && ch <= 'F') + return ch - 55; + else if (ch >= '0' && ch <= '9') + return ch - 48; + + return 0; +} + +uint32_t wlanCfgParseToFW(int8_t **args, int8_t *args_size, + uint8_t nargs, int8_t *buffer, uint8_t times) +{ + uint8_t *data = NULL; + char ch; + int32_t i = 0, j = 0; + uint32_t bufferindex = 0, base = 0; + uint32_t sum = 0, startOffset = 0; + struct CMD_FORMAT_V1 cmd_v1; + + memset(&cmd_v1, 0, sizeof(struct CMD_FORMAT_V1)); + +#if 0 + cmd_v1.itemType = atoi(*args[ED_ITEMTYPE_SITE]); +#else + cmd_v1.itemType = ITEM_TYPE_DEC; +#endif + if (buffer == NULL || + args_size[ED_STRING_SITE] == 0 || + args_size[ED_VALUE_SITE] == 0 || + (cmd_v1.itemType < ITEM_TYPE_DEC + || cmd_v1.itemType > ITEM_TYPE_STR)) { + DBGLOG(INIT, ERROR, "cfg args wrong\n"); + return WLAN_STATUS_FAILURE; + } + + cmd_v1.itemStringLength = args_size[ED_STRING_SITE]; + strncpy(cmd_v1.itemString, args[ED_STRING_SITE], + cmd_v1.itemStringLength); + DBGLOG(INIT, INFO, "itemString:"); + for (i = 0; i < cmd_v1.itemStringLength; i++) + DBGLOG(INIT, INFO, "%c", cmd_v1.itemString[i]); + DBGLOG(INIT, INFO, "\n"); + + DBGLOG(INIT, INFO, "cmd_v1.itemType = %d\n", + cmd_v1.itemType); + if (cmd_v1.itemType == ITEM_TYPE_DEC + || cmd_v1.itemType == ITEM_TYPE_HEX) { + data = args[ED_VALUE_SITE]; + + switch (cmd_v1.itemType) { + case ITEM_TYPE_DEC: + base = 10; + startOffset = 0; + break; + case ITEM_TYPE_HEX: + ch = *data; + if (args_size[ED_VALUE_SITE] < 3 || ch != '0') { + DBGLOG(INIT, WARN, + "Hex args must have prefix '0x'\n"); + return WLAN_STATUS_FAILURE; + } + + data++; + ch = *data; + if (ch != 'x' && ch != 'X') { + DBGLOG(INIT, WARN, + "Hex args must have prefix '0x'\n"); + return WLAN_STATUS_FAILURE; + } + data++; + base = 16; + startOffset = 2; + break; + } + + for (j = args_size[ED_VALUE_SITE] - 1 - startOffset; j >= 0; + j--) { + sum = sum * base + atoi(*data); + DBGLOG(INIT, WARN, "size:%d data[%d]=%u, sum=%u\n", + args_size[ED_VALUE_SITE], j, atoi(*data), sum); + + data++; + } + + bufferindex = 0; + do { + cmd_v1.itemValue[bufferindex++] = sum & 0xFF; + sum = sum >> 8; + } while (sum > 0); + cmd_v1.itemValueLength = bufferindex; + } else if (cmd_v1.itemType == ITEM_TYPE_STR) { + cmd_v1.itemValueLength = args_size[ED_VALUE_SITE]; + strncpy(cmd_v1.itemValue, args[ED_VALUE_SITE], + cmd_v1.itemValueLength); + } + + DBGLOG(INIT, INFO, "Length = %d itemValue:", + cmd_v1.itemValueLength); + for (i = cmd_v1.itemValueLength - 1; i >= 0; i--) + DBGLOG(INIT, ERROR, "%d,", cmd_v1.itemValue[i]); + DBGLOG(INIT, INFO, "\n"); + memcpy(((struct CMD_FORMAT_V1 *)buffer) + times, &cmd_v1, + sizeof(struct CMD_FORMAT_V1)); + + return WLAN_STATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is to send WLAN feature options to firmware + * + * @param prAdapter Pointer of ADAPTER_T + * + * @return none + */ +/*----------------------------------------------------------------------------*/ +void wlanFeatureToFw(IN struct ADAPTER *prAdapter) +{ + + struct WLAN_CFG_ENTRY *prWlanCfgEntry; + uint32_t i; + struct CMD_HEADER rCmdV1Header; + uint32_t rStatus; + struct CMD_FORMAT_V1 rCmd_v1; + uint8_t ucTimes = 0; + + + + rCmdV1Header.cmdType = CMD_TYPE_SET; + rCmdV1Header.cmdVersion = CMD_VER_1; + rCmdV1Header.cmdBufferLen = 0; + rCmdV1Header.itemNum = 0; + + kalMemSet(rCmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); + kalMemSet(&rCmd_v1, 0, sizeof(struct CMD_FORMAT_V1)); + + + prWlanCfgEntry = NULL; + + for (i = 0; i < WLAN_CFG_ENTRY_NUM_MAX; i++) { + + prWlanCfgEntry = wlanCfgGetEntryByIndex(prAdapter, i, 0); + + if (prWlanCfgEntry) { + + rCmd_v1.itemType = ITEM_TYPE_STR; + + + /*send string format to firmware */ + rCmd_v1.itemStringLength = kalStrLen( + prWlanCfgEntry->aucKey); + kalMemZero(rCmd_v1.itemString, MAX_CMD_NAME_MAX_LENGTH); + kalMemCopy(rCmd_v1.itemString, prWlanCfgEntry->aucKey, + rCmd_v1.itemStringLength); + + + rCmd_v1.itemValueLength = kalStrLen( + prWlanCfgEntry->aucValue); + kalMemZero(rCmd_v1.itemValue, MAX_CMD_VALUE_MAX_LENGTH); + kalMemCopy(rCmd_v1.itemValue, prWlanCfgEntry->aucValue, + rCmd_v1.itemValueLength); + + + + DBGLOG(INIT, WARN, + "Send key word (%s) WITH (%s) to firmware\n", + rCmd_v1.itemString, rCmd_v1.itemValue); + + kalMemCopy(((struct CMD_FORMAT_V1 *)rCmdV1Header.buffer) + + ucTimes, + &rCmd_v1, sizeof(struct CMD_FORMAT_V1)); + + + ucTimes++; + rCmdV1Header.cmdBufferLen += + sizeof(struct CMD_FORMAT_V1); + rCmdV1Header.itemNum += ucTimes; + + if (ucTimes == MAX_CMD_ITEM_MAX) { + /* Send to FW */ + rCmdV1Header.itemNum = ucTimes; + + rStatus = wlanSendSetQueryCmd( + /* prAdapter */ + prAdapter, + /* 0x70 */ + CMD_ID_GET_SET_CUSTOMER_CFG, + /* fgSetQuery */ + TRUE, + /* fgNeedResp */ + FALSE, + /* fgIsOid */ + FALSE, + /* pfCmdDoneHandler*/ + NULL, + /* pfCmdTimeoutHandler */ + NULL, + /* u4SetQueryInfoLen */ + sizeof(struct CMD_HEADER), + /* pucInfoBuffer */ + (uint8_t *)&rCmdV1Header, + /* pvSetQueryBuffer */ + NULL, + /* u4SetQueryBufferLen */ + 0); + + if (rStatus == WLAN_STATUS_FAILURE) + DBGLOG(INIT, INFO, + "[Fail]kalIoctl wifiSefCFG fail 0x%x\n", + rStatus); + + DBGLOG(INIT, INFO, + "kalIoctl wifiSefCFG num:%d\n", ucTimes); + kalMemSet(rCmdV1Header.buffer, 0, + MAX_CMD_BUFFER_LENGTH); + rCmdV1Header.cmdBufferLen = 0; + ucTimes = 0; + } + + + } else { + break; + } + } + + + if (ucTimes != 0) { + /* Send to FW */ + rCmdV1Header.itemNum = ucTimes; + + DBGLOG(INIT, INFO, "cmdV1Header.itemNum:%d\n", + rCmdV1Header.itemNum); + + rStatus = wlanSendSetQueryCmd( + prAdapter, /* prAdapter */ + CMD_ID_GET_SET_CUSTOMER_CFG, /* 0x70 */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler*/ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct CMD_HEADER), /* u4SetQueryInfoLen */ + (uint8_t *)&rCmdV1Header,/* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0); /* u4SetQueryBufferLen */ + + if (rStatus == WLAN_STATUS_FAILURE) + DBGLOG(INIT, INFO, + "[Fail]kalIoctl wifiSefCFG fail 0x%x\n", + rStatus); + + DBGLOG(INIT, INFO, "kalIoctl wifiSefCFG num:%d\n", ucTimes); + kalMemSet(rCmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); + rCmdV1Header.cmdBufferLen = 0; + ucTimes = 0; + } + +} + + + +uint32_t wlanCfgParse(IN struct ADAPTER *prAdapter, + uint8_t *pucConfigBuf, uint32_t u4ConfigBufLen, + u_int8_t isFwConfig) +{ + struct WLAN_CFG_PARSE_STATE_S state; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int8_t **ppcArgs; + int32_t i4Nargs; + int8_t arcArgv_size[WLAN_CFG_ARGV_MAX]; + uint8_t ucTimes = 0; + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER rCmdV1Header; + int8_t ucTmp[WLAN_CFG_VALUE_LEN_MAX]; + uint8_t i; + + uint8_t *pucCurrBuf = ucTmp; + uint32_t u4CurrSize = ARRAY_SIZE(ucTmp); + uint32_t u4RetSize = 0; + + rCmdV1Header.cmdType = CMD_TYPE_SET; + rCmdV1Header.cmdVersion = CMD_VER_1; + rCmdV1Header.cmdBufferLen = 0; + kalMemSet(rCmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); + + if (pucConfigBuf == NULL) { + DBGLOG(INIT, ERROR, "pucConfigBuf is NULL\n"); + return WLAN_STATUS_FAILURE; + } + if (kalStrnLen(pucConfigBuf, 4000) >= 4000) { + DBGLOG(INIT, ERROR, "pucConfigBuf >= 4000\n"); + return WLAN_STATUS_FAILURE; + } + if (u4ConfigBufLen == 0) + return WLAN_STATUS_FAILURE; + + ppcArgs = apcArgv; + i4Nargs = 0; + state.ptr = pucConfigBuf; + state.nexttoken = 0; + state.textsize = 0; + state.maxSize = u4ConfigBufLen; + DBGLOG(INIT, INFO, "wlanCfgParse()\n"); + + for (;;) { + switch (wlanCfgFindNextToken(&state)) { + case STATE_EOF: + if (i4Nargs < 2) + goto exit; + + DBGLOG(INIT, INFO, "STATE_EOF\n"); + + /* 3 parmeter mode transforation */ + if (i4Nargs == 3 && !isFwConfig && + arcArgv_size[0] == 1) { + + /* parsing and transfer the format + * Format 1:Dec 2.Hex 3.String + */ + + kalMemZero(ucTmp, WLAN_CFG_VALUE_LEN_MAX); + pucCurrBuf = ucTmp; + u4CurrSize = ARRAY_SIZE(ucTmp); + + if ((*ppcArgs[0] == '2') && + (*(ppcArgs[2]) != '0') && + (*(ppcArgs[2] + 1) != 'x')) { + DBGLOG(INIT, WARN, + "config file got a hex format\n" + ); + kalSnprintf(pucCurrBuf, u4CurrSize, + "0x%s", ppcArgs[2]); + } else { + kalSnprintf(pucCurrBuf, u4CurrSize, + "%s", ppcArgs[2]); + } + DBGLOG(INIT, WARN, + "[3 parameter mode][%s],[%s],[%s]\n", + ppcArgs[0], ppcArgs[1], ucTmp); + wlanCfgParseAddEntry(prAdapter, ppcArgs[1], + NULL, ucTmp, NULL); + kalMemSet(arcArgv_size, 0, WLAN_CFG_ARGV_MAX); + kalMemSet(apcArgv, 0, + WLAN_CFG_ARGV_MAX * sizeof(int8_t *)); + i4Nargs = 0; + goto exit; + + } + + wlanCfgParseAddEntry(prAdapter, ppcArgs[0], NULL, + ppcArgs[1], NULL); + + if (isFwConfig) { + uint32_t ret; + + ret = wlanCfgParseToFW(ppcArgs, arcArgv_size, + i4Nargs, + rCmdV1Header.buffer, + ucTimes); + if (ret == WLAN_STATUS_SUCCESS) { + ucTimes++; + rCmdV1Header.cmdBufferLen += + sizeof(struct CMD_FORMAT_V1); + } + } + + goto exit; + + + case STATE_NEWLINE: + if (i4Nargs < 2) + break; + + DBGLOG(INIT, INFO, "STATE_NEWLINE\n"); +#if 1 + /* 3 parmeter mode transforation */ + if (i4Nargs == 3 && !isFwConfig && + arcArgv_size[0] == 1) { + /* parsing and transfer the format + * Format 1:Dec 2.Hex 3.String + */ + kalMemZero(ucTmp, WLAN_CFG_VALUE_LEN_MAX); + pucCurrBuf = ucTmp; + u4CurrSize = ARRAY_SIZE(ucTmp); + + if ((*ppcArgs[0] == '2') && + (*(ppcArgs[2]) != '0') && + (*(ppcArgs[2] + 1) != 'x')) { + DBGLOG(INIT, WARN, + "config file got a hex format\n"); + kalSnprintf(pucCurrBuf, u4CurrSize, + "0x%s", ppcArgs[2]); + + } else { + kalSnprintf(pucCurrBuf, u4CurrSize, + "%s", ppcArgs[2]); + } + + + DBGLOG(INIT, WARN, + "[3 parameter mode][%s],[%s],[%s]\n", + ppcArgs[0], ppcArgs[1], ucTmp); + wlanCfgParseAddEntry(prAdapter, ppcArgs[1], + NULL, ucTmp, NULL); + kalMemSet(arcArgv_size, 0, WLAN_CFG_ARGV_MAX); + kalMemSet(apcArgv, 0, + WLAN_CFG_ARGV_MAX * sizeof(int8_t *)); + i4Nargs = 0; + break; + + } +#if 1 + /*combine the argument to save in temp*/ + pucCurrBuf = ucTmp; + u4CurrSize = ARRAY_SIZE(ucTmp); + + kalMemZero(ucTmp, WLAN_CFG_VALUE_LEN_MAX); + + if (i4Nargs == 2) { + /* no space for it, driver can't accept space in + * the end of the line + */ + /* ToDo: skip the space when parsing */ + kalSnprintf(pucCurrBuf, u4CurrSize, "%s", + ppcArgs[1]); + } else { + for (i = 1; i < i4Nargs; i++) { + if (u4CurrSize <= 1) { + DBGLOG(INIT, ERROR, + "write to pucCurrBuf out of bound, i=%d\n", + i); + break; + } + u4RetSize = scnprintf(pucCurrBuf, + u4CurrSize, "%s ", + ppcArgs[i]); + pucCurrBuf += u4RetSize; + u4CurrSize -= u4RetSize; + } + } + + DBGLOG(INIT, WARN, + "Save to driver temp buffer as [%s]\n", + ucTmp); + wlanCfgParseAddEntry(prAdapter, ppcArgs[0], NULL, ucTmp, + NULL); +#else + wlanCfgParseAddEntry(prAdapter, ppcArgs[0], NULL, + ppcArgs[1], NULL); +#endif + + if (isFwConfig) { + + uint32_t ret; + + ret = wlanCfgParseToFW(ppcArgs, arcArgv_size, + i4Nargs, rCmdV1Header.buffer, ucTimes); + if (ret == WLAN_STATUS_SUCCESS) { + ucTimes++; + rCmdV1Header.cmdBufferLen += + sizeof(struct CMD_FORMAT_V1); + } + + if (ucTimes == MAX_CMD_ITEM_MAX) { + /* Send to FW */ + rCmdV1Header.itemNum = ucTimes; + rStatus = wlanSendSetQueryCmd( + /* prAdapter */ + prAdapter, + /* 0x70 */ + CMD_ID_GET_SET_CUSTOMER_CFG, + /* fgSetQuery */ + TRUE, + /* fgNeedResp */ + FALSE, + /* fgIsOid */ + FALSE, + /* pfCmdDoneHandler*/ + NULL, + /* pfCmdTimeoutHandler */ + NULL, + /* u4SetQueryInfoLen */ + sizeof(struct CMD_HEADER), + /* pucInfoBuffer */ + (uint8_t *) &rCmdV1Header, + /* pvSetQueryBuffer */ + NULL, + /* u4SetQueryBufferLen */ + 0); + + if (rStatus == WLAN_STATUS_FAILURE) + DBGLOG(INIT, INFO, + "kalIoctl wifiSefCFG fail 0x%x\n", + rStatus); + DBGLOG(INIT, INFO, + "kalIoctl wifiSefCFG num:%d X\n", + ucTimes); + kalMemSet(rCmdV1Header.buffer, 0, + MAX_CMD_BUFFER_LENGTH); + rCmdV1Header.cmdBufferLen = 0; + ucTimes = 0; + } + + } + +#endif + kalMemSet(arcArgv_size, 0, WLAN_CFG_ARGV_MAX); + kalMemSet(apcArgv, 0, + WLAN_CFG_ARGV_MAX * sizeof(int8_t *)); + i4Nargs = 0; + break; + + case STATE_TEXT: + if (i4Nargs < WLAN_CFG_ARGV_MAX) { + ppcArgs[i4Nargs++] = state.text; + arcArgv_size[i4Nargs - 1] = state.textsize; + state.textsize = 0; + DBGLOG(INIT, INFO, + " nargs= %d STATE_TEXT = %s, SIZE = %d\n", + i4Nargs - 1, ppcArgs[i4Nargs - 1], + arcArgv_size[i4Nargs - 1]); + } + break; + } + } + +exit: + if (ucTimes != 0 && isFwConfig) { + /* Send to FW */ + rCmdV1Header.itemNum = ucTimes; + + DBGLOG(INIT, INFO, "cmdV1Header.itemNum:%d\n", + rCmdV1Header.itemNum); + rStatus = wlanSendSetQueryCmd( + prAdapter, /* prAdapter */ + CMD_ID_GET_SET_CUSTOMER_CFG, /* 0x70 */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler*/ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct CMD_HEADER), /* u4SetQueryInfoLen */ + (uint8_t *) &rCmdV1Header, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus == WLAN_STATUS_FAILURE) + DBGLOG(INIT, WARN, "kalIoctl wifiSefCFG fail 0x%x\n", + rStatus); + + DBGLOG(INIT, WARN, "kalIoctl wifiSefCFG num:%d X\n", + ucTimes); + kalMemSet(rCmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); + rCmdV1Header.cmdBufferLen = 0; + ucTimes = 0; + } + return WLAN_STATUS_SUCCESS; +} + +#else +uint32_t wlanCfgParse(IN struct ADAPTER *prAdapter, + uint8_t *pucConfigBuf, uint32_t u4ConfigBufLen) +{ + + struct WLAN_CFG_PARSE_STATE_S state; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int8_t **args; + int32_t nargs; + + if (pucConfigBuf == NULL) { + DBGLOG(INIT, ERROR, "pucConfigBuf is NULL\n"); + return WLAN_STATUS_FAILURE; + } + if (kalStrnLen(pucConfigBuf, 4000) >= 4000) { + DBGLOG(INIT, ERROR, "pucConfigBuf >= 4000\n"); + return WLAN_STATUS_FAILURE; + } + if (u4ConfigBufLen == 0) + return WLAN_STATUS_FAILURE; + args = apcArgv; + nargs = 0; + state.ptr = pucConfigBuf; + state.nexttoken = 0; + state.maxSize = u4ConfigBufLen; + + for (;;) { + switch (wlanCfgFindNextToken(&state)) { + case STATE_EOF: + if (nargs > 1) + wlanCfgParseAddEntry(prAdapter, args[0], NULL, + args[1], NULL); + goto exit; + case STATE_NEWLINE: + if (nargs > 1) + wlanCfgParseAddEntry(prAdapter, args[0], NULL, + args[1], NULL); + /*args[0] is parameter, args[1] is the value*/ + nargs = 0; + break; + case STATE_TEXT: + if (nargs < WLAN_CFG_ARGV_MAX) + args[nargs++] = state.text; + break; + } + } + +exit: + return WLAN_STATUS_SUCCESS; + +#if 0 + /* Old version */ + uint32_t i; + uint8_t c; + uint8_t *pbuf; + uint8_t ucState; + uint8_t *pucKeyTail = NULL; + uint8_t *pucKeyHead = NULL; + uint8_t *pucValueHead = NULL; + uint8_t *pucValueTail = NULL; + + ucState = WAIT_KEY_HEAD; + pbuf = pucConfigBuf; + + for (i = 0; i < u4ConfigBufLen; i++) { + c = pbuf[i]; + if (c == '\r' || c == '\n') { + + if (ucState == WAIT_VALUE_TAIL) { + /* Entry found */ + if (pucValueHead) + wlanCfgParseAddEntry(prAdapter, + pucKeyHead, pucKeyTail, + pucValueHead, pucValueTail); + } + ucState = WAIT_KEY_HEAD; + pucKeyTail = NULL; + pucKeyHead = NULL; + pucValueHead = NULL; + pucValueTail = NULL; + + } else if (c == '=') { + if (ucState == WAIT_KEY_TAIL) { + pucKeyTail = &pbuf[i - 1]; + ucState = WAIT_VALUE_HEAD; + } + } else if (c == ' ' || c == '\t') { + if (ucState == WAIT_KEY_TAIL) { + pucKeyTail = &pbuf[i - 1]; + ucState = WAIT_VALUE_HEAD; + } + } else { + + if (c == '#') { + /* comments */ + if (ucState == WAIT_KEY_HEAD) + ucState = WAIT_COMMENT_TAIL; + else if (ucState == WAIT_VALUE_TAIL) + pucValueTail = &pbuf[i]; + + } else { + if (ucState == WAIT_KEY_HEAD) { + pucKeyHead = &pbuf[i]; + pucKeyTail = &pbuf[i]; + ucState = WAIT_KEY_TAIL; + } else if (ucState == WAIT_VALUE_HEAD) { + pucValueHead = &pbuf[i]; + pucValueTail = &pbuf[i]; + ucState = WAIT_VALUE_TAIL; + } else if (ucState == WAIT_VALUE_TAIL) + pucValueTail = &pbuf[i]; + } + } + + } /* for */ + + if (ucState == WAIT_VALUE_TAIL) { + /* Entry found */ + if (pucValueTail) + wlanCfgParseAddEntry(prAdapter, pucKeyHead, pucKeyTail, + pucValueHead, pucValueTail); + } +#endif + + return WLAN_STATUS_SUCCESS; +} +#endif + + +uint32_t wlanCfgInit(IN struct ADAPTER *prAdapter, + uint8_t *pucConfigBuf, uint32_t u4ConfigBufLen, + uint32_t u4Flags) +{ + struct WLAN_CFG *prWlanCfg; + struct WLAN_CFG_REC *prWlanCfgRec; + /* P_WLAN_CFG_ENTRY_T prWlanCfgEntry; */ + prAdapter->prWlanCfg = &prAdapter->rWlanCfg; + prWlanCfg = prAdapter->prWlanCfg; + + prAdapter->prWlanCfgRec = &prAdapter->rWlanCfgRec; + prWlanCfgRec = prAdapter->prWlanCfgRec; + + kalMemZero(prWlanCfg, sizeof(struct WLAN_CFG)); + ASSERT(prWlanCfg); + prWlanCfg->u4WlanCfgEntryNumMax = WLAN_CFG_ENTRY_NUM_MAX; + prWlanCfg->u4WlanCfgKeyLenMax = WLAN_CFG_KEY_LEN_MAX; + prWlanCfg->u4WlanCfgValueLenMax = WLAN_CFG_VALUE_LEN_MAX; + + prWlanCfgRec->u4WlanCfgEntryNumMax = + WLAN_CFG_REC_ENTRY_NUM_MAX; + prWlanCfgRec->u4WlanCfgKeyLenMax = + WLAN_CFG_KEY_LEN_MAX; + prWlanCfgRec->u4WlanCfgValueLenMax = + WLAN_CFG_VALUE_LEN_MAX; + + DBGLOG(INIT, INFO, "Init wifi config len %u max entry %u\n", + u4ConfigBufLen, prWlanCfg->u4WlanCfgEntryNumMax); +#if DBG + /* self test */ + wlanCfgSet(prAdapter, "ConfigValid", "0x123", 0); + if (wlanCfgGetUint32(prAdapter, "ConfigValid", 0) != 0x123) + DBGLOG(INIT, INFO, "wifi config error %u\n", __LINE__); + + wlanCfgSet(prAdapter, "ConfigValid", "1", 0); + if (wlanCfgGetUint32(prAdapter, "ConfigValid", 0) != 1) + DBGLOG(INIT, INFO, "wifi config error %u\n", __LINE__); + +#endif + /*load default value because kalMemZero in this function*/ + wlanLoadDefaultCustomerSetting(prAdapter); + + /* Parse the pucConfigBuf */ + if (pucConfigBuf && (u4ConfigBufLen > 0)) +#if CFG_SUPPORT_EASY_DEBUG + wlanCfgParse(prAdapter, pucConfigBuf, u4ConfigBufLen, + FALSE); +#else + wlanCfgParse(prAdapter, pucConfigBuf, u4ConfigBufLen); +#endif + return WLAN_STATUS_SUCCESS; +} + +#endif /* CFG_SUPPORT_CFG_FILE */ + +int32_t wlanHexToNum(int8_t c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; +} + +int32_t wlanHexToByte(int8_t *hex) +{ + int32_t a, b; + + a = wlanHexToNum(*hex++); + if (a < 0) + return -1; + b = wlanHexToNum(*hex++); + if (b < 0) + return -1; + return (a << 4) | b; +} + +int32_t wlanHwAddrToBin(int8_t *txt, uint8_t *addr) +{ + int32_t i; + int8_t *pos = txt; + + for (i = 0; i < 6; i++) { + int32_t a, b; + + while (*pos == ':' || *pos == '.' || *pos == '-') + pos++; + + a = wlanHexToNum(*pos++); + if (a < 0) + return -1; + b = wlanHexToNum(*pos++); + if (b < 0) + return -1; + *addr++ = (a << 4) | b; + } + + return pos - txt; +} + +u_int8_t wlanIsChipNoAck(IN struct ADAPTER *prAdapter) +{ + u_int8_t fgIsNoAck; + + fgIsNoAck = prAdapter->fgIsChipNoAck +#if CFG_CHIP_RESET_SUPPORT + || kalIsResetting() +#endif + || fgIsBusAccessFailed; + + return fgIsNoAck; +} + +u_int8_t wlanIsChipRstRecEnabled(IN struct ADAPTER + *prAdapter) +{ + return prAdapter->rWifiVar.fgChipResetRecover; +} + +u_int8_t wlanIsChipAssert(IN struct ADAPTER *prAdapter) +{ + return prAdapter->rWifiVar.fgChipResetRecover + && prAdapter->fgIsChipAssert; +} + +void wlanChipRstPreAct(IN struct ADAPTER *prAdapter) +{ + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + int32_t i4BssIdx; + uint32_t u4ClientCount = 0; + struct STA_RECORD *prCurrStaRec = (struct STA_RECORD *) + NULL; + struct STA_RECORD *prNextCurrStaRec = (struct STA_RECORD *) + NULL; + struct LINK *prClientList; + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_CHIP_RST); + if (prAdapter->fgIsChipAssert) { + KAL_RELEASE_MUTEX(prAdapter, MUTEX_CHIP_RST); + return; + } + prAdapter->fgIsChipAssert = TRUE; + KAL_RELEASE_MUTEX(prAdapter, MUTEX_CHIP_RST); + + for (i4BssIdx = 0; i4BssIdx < prAdapter->ucHwBssIdNum; + i4BssIdx++) { + prBssInfo = prAdapter->aprBssInfo[i4BssIdx]; + + if (!prBssInfo->fgIsInUse) + continue; + + if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) { + + if (prGlueInfo->eParamMediaStateIndicated == + PARAM_MEDIA_STATE_CONNECTED) + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + } else if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) { + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + u4ClientCount = bssGetClientCount(prAdapter, + prBssInfo); + if (u4ClientCount == 0) + continue; + + prClientList = &prBssInfo->rStaRecOfClientList; + LINK_FOR_EACH_ENTRY_SAFE(prCurrStaRec, + prNextCurrStaRec, prClientList, + rLinkEntry, struct STA_RECORD) { + kalP2PGOStationUpdate( + prAdapter->prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData, + prCurrStaRec, FALSE); + LINK_REMOVE_KNOWN_ENTRY(prClientList, + &prCurrStaRec->rLinkEntry); + } + } else if (prBssInfo->eCurrentOPMode == + OP_MODE_INFRASTRUCTURE) { + if (prBssInfo->prStaRecOfAP == NULL) + continue; +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) + kalP2PGCIndicateConnectionStatus(prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData, + NULL, NULL, 0, 0, + WLAN_STATUS_MEDIA_DISCONNECT); +#else + kalP2PGCIndicateConnectionStatus(prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData, + NULL, NULL, 0, 0); +#endif + prBssInfo->prStaRecOfAP = NULL; + + } + } + } +} + +#if CFG_ENABLE_PER_STA_STATISTICS +void wlanTxLifetimeUpdateStaStats(IN struct ADAPTER + *prAdapter, IN struct MSDU_INFO *prMsduInfo) +{ + struct STA_RECORD *prStaRec; + uint32_t u4DeltaTime; + uint32_t u4DeltaHifTxTime; + struct PKT_PROFILE *prPktProfile = &prMsduInfo->rPktProfile; +#if 0 + struct QUE_MGT *prQM = &prAdapter->rQM; + uint32_t u4PktPrintPeriod = 0; +#endif + + prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + + if (prStaRec) { + u4DeltaTime = (uint32_t) (prPktProfile->rHifTxDoneTimestamp - + prPktProfile->rHardXmitArrivalTimestamp); + u4DeltaHifTxTime = (uint32_t) ( + prPktProfile->rHifTxDoneTimestamp - + prPktProfile->rDequeueTimestamp); + + /* Update StaRec statistics */ + prStaRec->u4TotalTxPktsNumber++; + prStaRec->u4TotalTxPktsTime += u4DeltaTime; + prStaRec->u4TotalTxPktsHifTxTime += u4DeltaHifTxTime; + + if (u4DeltaTime > prStaRec->u4MaxTxPktsTime) + prStaRec->u4MaxTxPktsTime = u4DeltaTime; + + if (u4DeltaHifTxTime > prStaRec->u4MaxTxPktsHifTime) + prStaRec->u4MaxTxPktsHifTime = u4DeltaHifTxTime; + + if (u4DeltaTime >= NIC_TX_TIME_THRESHOLD) + prStaRec->u4ThresholdCounter++; + +#if 0 + if (u4PktPrintPeriod && + (prStaRec->u4TotalTxPktsNumber >= u4PktPrintPeriod)) { + DBGLOG(TX, INFO, "[%u]N[%u]A[%u]M[%u]T[%u]E[%4u]\n", + prStaRec->ucIndex, + prStaRec->u4TotalTxPktsNumber, + prStaRec->u4TotalTxPktsTime, + prStaRec->u4MaxTxPktsTime, + prStaRec->u4ThresholdCounter, + prQM->au4QmTcResourceEmptyCounter[ + prStaRec->ucBssIndex][TC2_INDEX]); + + prStaRec->u4TotalTxPktsNumber = 0; + prStaRec->u4TotalTxPktsTime = 0; + prStaRec->u4MaxTxPktsTime = 0; + prStaRec->u4ThresholdCounter = 0; + prQM->au4QmTcResourceEmptyCounter[ + prStaRec->ucBssIndex][TC2_INDEX] = 0; + } +#endif + } +} +#endif + +u_int8_t wlanTxLifetimeIsProfilingEnabled( + IN struct ADAPTER *prAdapter) +{ + u_int8_t fgEnabled = TRUE; +#if CFG_SUPPORT_WFD + struct WFD_CFG_SETTINGS *prWfdCfgSettings = + (struct WFD_CFG_SETTINGS *) NULL; + + prWfdCfgSettings = + &prAdapter->rWifiVar.rWfdConfigureSettings; + + if (prWfdCfgSettings->ucWfdEnable > 0) + fgEnabled = TRUE; +#endif + + return fgEnabled; +} + +u_int8_t wlanTxLifetimeIsTargetMsdu(IN struct ADAPTER + *prAdapter, IN struct MSDU_INFO *prMsduInfo) +{ + u_int8_t fgResult = TRUE; + +#if 0 + switch (prMsduInfo->ucTID) { + /* BK */ + case 1: + case 2: + + /* BE */ + case 0: + case 3: + fgResult = FALSE; + break; + /* VI */ + case 4: + case 5: + + /* VO */ + case 6: + case 7: + fgResult = TRUE; + break; + default: + break; + } +#endif + return fgResult; +} + +void wlanTxLifetimeTagPacket(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_PROFILING_TAG eTag) +{ + struct PKT_PROFILE *prPktProfile = &prMsduInfo->rPktProfile; + + if (!wlanTxLifetimeIsProfilingEnabled(prAdapter)) + return; + + switch (eTag) { + case TX_PROF_TAG_OS_TO_DRV: + /* arrival time is tagged in wlanProcessTxFrame */ + break; + + case TX_PROF_TAG_DRV_ENQUE: + /* Reset packet profile */ + prPktProfile->fgIsValid = FALSE; + if (wlanTxLifetimeIsTargetMsdu(prAdapter, prMsduInfo)) { + /* Enable packet lifetime profiling */ + prPktProfile->fgIsValid = TRUE; + + /* Packet arrival time at kernel Hard Xmit */ + prPktProfile->rHardXmitArrivalTimestamp = + GLUE_GET_PKT_ARRIVAL_TIME(prMsduInfo->prPacket); + + /* Packet enqueue time */ + prPktProfile->rEnqueueTimestamp = (OS_SYSTIME) + kalGetTimeTick(); + } + break; + + case TX_PROF_TAG_DRV_DEQUE: + if (prPktProfile->fgIsValid) + prPktProfile->rDequeueTimestamp = (OS_SYSTIME) + kalGetTimeTick(); + break; + + case TX_PROF_TAG_DRV_TX_DONE: + if (prPktProfile->fgIsValid) { + prPktProfile->rHifTxDoneTimestamp = (OS_SYSTIME) + kalGetTimeTick(); +#if CFG_ENABLE_PER_STA_STATISTICS + wlanTxLifetimeUpdateStaStats(prAdapter, prMsduInfo); +#endif + } + break; + + case TX_PROF_TAG_MAC_TX_DONE: + break; + + default: + break; + } +} + +void wlanTxProfilingTagPacket(IN struct ADAPTER *prAdapter, + IN void *prPacket, + IN enum ENUM_TX_PROFILING_TAG eTag) +{ +#if CFG_MET_PACKET_TRACE_SUPPORT + kalMetTagPacket(prAdapter->prGlueInfo, prPacket, eTag); +#endif +} + +void wlanTxProfilingTagMsdu(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_PROFILING_TAG eTag) +{ + wlanTxLifetimeTagPacket(prAdapter, prMsduInfo, eTag); + + wlanTxProfilingTagPacket(prAdapter, prMsduInfo->prPacket, + eTag); +} + +void wlanUpdateTxStatistics(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN u_int8_t fgTxDrop) +{ + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + enum ENUM_WMM_ACI eAci = WMM_AC_BE_INDEX; + struct QUE_MGT *prQM = &prAdapter->rQM; + OS_SYSTIME rCurTime; + + eAci = aucTid2ACI[prMsduInfo->ucUserPriority]; + + prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + + if (prStaRec) { + if (fgTxDrop) + prStaRec->arLinkStatistics[eAci].u4TxDropMsdu++; + else + prStaRec->arLinkStatistics[eAci].u4TxMsdu++; + } else { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prMsduInfo->ucBssIndex); + + if (fgTxDrop) + prBssInfo->arLinkStatistics[eAci].u4TxDropMsdu++; + else + prBssInfo->arLinkStatistics[eAci].u4TxMsdu++; + } + + /* Trigger FW stats log every 20s */ + rCurTime = (OS_SYSTIME) kalGetTimeTick(); + + DBGLOG(INIT, LOUD, "CUR[%u] LAST[%u] TO[%u]\n", rCurTime, + prQM->rLastTxPktDumpTime, + CHECK_FOR_TIMEOUT(rCurTime, prQM->rLastTxPktDumpTime, + MSEC_TO_SYSTIME( + prAdapter->rWifiVar.u4StatsLogTimeout))); + + if (CHECK_FOR_TIMEOUT(rCurTime, prQM->rLastTxPktDumpTime, + MSEC_TO_SYSTIME( + prAdapter->rWifiVar.u4StatsLogTimeout))) { + + wlanTriggerStatsLog(prAdapter, + prAdapter->rWifiVar.u4StatsLogDuration); + wlanDumpAllBssStatistics(prAdapter); + + prQM->rLastTxPktDumpTime = rCurTime; + } +} + +void wlanUpdateRxStatistics(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct STA_RECORD *prStaRec; + enum ENUM_WMM_ACI eAci = WMM_AC_BE_INDEX; + + eAci = aucTid2ACI[prSwRfb->ucTid]; + + prStaRec = cnmGetStaRecByIndex(prAdapter, + prSwRfb->ucStaRecIdx); + if (prStaRec) + prStaRec->arLinkStatistics[eAci].u4RxMsdu++; +} + +uint32_t wlanTriggerStatsLog(IN struct ADAPTER *prAdapter, + IN uint32_t u4DurationInMs) +{ + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanPktTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + OS_SYSTIME rCurrent = kalGetTimeTick(); + struct PKT_PROFILE *prPktProfile = &prMsduInfo->rPktProfile; + + uint8_t *apucPktType[ENUM_PKT_FLAG_NUM] = { + (uint8_t *) DISP_STRING("INVALID"), + (uint8_t *) DISP_STRING("802_3"), + (uint8_t *) DISP_STRING("1X"), + (uint8_t *) DISP_STRING("PROTECTED_1X"), + (uint8_t *) DISP_STRING("NON_PROTECTED_1X"), + (uint8_t *) DISP_STRING("VLAN_EXIST"), + (uint8_t *) DISP_STRING("DHCP"), + (uint8_t *) DISP_STRING("ARP"), + (uint8_t *) DISP_STRING("ICMP"), + (uint8_t *) DISP_STRING("TDLS"), + (uint8_t *) DISP_STRING("DNS") + }; + if (prMsduInfo->ucPktType >= ENUM_PKT_FLAG_NUM) + prMsduInfo->ucPktType = 0; + + if (prPktProfile->fgIsValid && + ((prMsduInfo->ucPktType == ENUM_PKT_ARP) || + (prMsduInfo->ucPktType == ENUM_PKT_DHCP))) { + if (rCurrent - prPktProfile->rHardXmitArrivalTimestamp > 2000) { + DBGLOG(TX, INFO, + "valid %d; ArriveDrv %u, Enq %u, Deq %u, LeaveDrv %u, TxDone %u\n", + prPktProfile->fgIsValid, + prPktProfile->rHardXmitArrivalTimestamp, + prPktProfile->rEnqueueTimestamp, + prPktProfile->rDequeueTimestamp, + prPktProfile->rHifTxDoneTimestamp, rCurrent); + + if (prMsduInfo->ucPktType == ENUM_PKT_ARP) + prAdapter->prGlueInfo->fgTxDoneDelayIsARP = + TRUE; + prAdapter->prGlueInfo->u4ArriveDrvTick = + prPktProfile->rHardXmitArrivalTimestamp; + prAdapter->prGlueInfo->u4EnQueTick = + prPktProfile->rEnqueueTimestamp; + prAdapter->prGlueInfo->u4DeQueTick = + prPktProfile->rDequeueTimestamp; + prAdapter->prGlueInfo->u4LeaveDrvTick = + prPktProfile->rHifTxDoneTimestamp; + prAdapter->prGlueInfo->u4CurrTick = rCurrent; + prAdapter->prGlueInfo->u8CurrTime = sched_clock(); + } + } + + DBGLOG_LIMITED(TX, INFO, + "TX DONE, Type[%s] Tag[0x%08x] WIDX:PID[%u:%u] Status[%u], SeqNo: %d\n", + apucPktType[prMsduInfo->ucPktType], prMsduInfo->u4TxDoneTag, + prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, rTxDoneStatus, + prMsduInfo->ucTxSeqNum); + + if (prMsduInfo->ucPktType == ENUM_PKT_1X) { + p2pRoleFsmNotifyEapolTxStatus(prAdapter, + prMsduInfo->ucBssIndex, + prMsduInfo->eEapolKeyType, + rTxDoneStatus); + secHandleEapolTxStatus(prAdapter, prMsduInfo, + rTxDoneStatus); + } + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_ASSERT_DUMP +void wlanCorDumpTimerInit(IN struct ADAPTER *prAdapter, + u_int8_t fgIsResetN9) +{ + if (fgIsResetN9) { + cnmTimerInitTimer(prAdapter, + &prAdapter->rN9CorDumpTimer, + (PFN_MGMT_TIMEOUT_FUNC) wlanN9CorDumpTimeOut, + (unsigned long) NULL); + + } else { + cnmTimerInitTimer(prAdapter, + &prAdapter->rCr4CorDumpTimer, + (PFN_MGMT_TIMEOUT_FUNC) wlanCr4CorDumpTimeOut, + (unsigned long) NULL); + } +} + +void wlanCorDumpTimerReset(IN struct ADAPTER *prAdapter, + u_int8_t fgIsResetN9) +{ + if (prAdapter->fgN9AssertDumpOngoing + || prAdapter->fgCr4AssertDumpOngoing) { + + if (fgIsResetN9) { + cnmTimerStopTimer(prAdapter, + &prAdapter->rN9CorDumpTimer); + cnmTimerStartTimer(prAdapter, + &prAdapter->rN9CorDumpTimer, 5000); + } else { + cnmTimerStopTimer(prAdapter, + &prAdapter->rCr4CorDumpTimer); + cnmTimerStartTimer(prAdapter, + &prAdapter->rCr4CorDumpTimer, 5000); + } + } else { + DBGLOG(INIT, INFO, + "Cr4, N9 CorDump Is not ongoing, ignore timer reset\n"); + } +} + +void wlanN9CorDumpTimeOut(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr) +{ + if (prAdapter->fgN9CorDumpFileOpend) { + DBGLOG(INIT, STATE, "\n[DUMP_N9]====N9 ASSERT_END====\n"); + prAdapter->fgN9AssertDumpOngoing = FALSE; + kalCloseCorDumpFile(TRUE); + prAdapter->fgN9CorDumpFileOpend = FALSE; + +#if CFG_CHIP_RESET_SUPPORT +#ifdef CFG_SUPPORT_CONNAC2X +#else + /* Trigger RESET */ + glGetRstReason(RST_FW_ASSERT); + DBGLOG(INIT, STATE, "eResetReason = %d\n", eResetReason); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_CHIP_RESET); +#endif +#endif + + } +} + +void wlanCr4CorDumpTimeOut(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr) +{ + if (prAdapter->fgCr4CorDumpFileOpend) { + DBGLOG(INIT, STATE, "\n[DUMP_Cr4]====Cr4 ASSERT_END====\n"); + prAdapter->fgCr4AssertDumpOngoing = FALSE; + kalCloseCorDumpFile(FALSE); + prAdapter->fgCr4CorDumpFileOpend = FALSE; +#if CFG_CHIP_RESET_SUPPORT +#ifdef CFG_SUPPORT_CONNAC2X +#else + /* Trigger RESET */ + glGetRstReason(RST_FW_ASSERT); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_CHIP_RESET); +#endif +#endif + } +} +#endif + +u_int8_t +wlanGetWlanIdxByAddress(IN struct ADAPTER *prAdapter, + IN uint8_t *pucAddr, OUT uint8_t *pucIndex) +{ + uint8_t ucStaRecIdx; + struct STA_RECORD *prTempStaRec; + + for (ucStaRecIdx = 0; ucStaRecIdx < CFG_STA_REC_NUM; + ucStaRecIdx++) { + prTempStaRec = &(prAdapter->arStaRec[ucStaRecIdx]); + if (pucAddr) { + if (prTempStaRec->fgIsInUse && + EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, + pucAddr)) { + *pucIndex = prTempStaRec->ucWlanIndex; + return TRUE; + } + } else { + if (prTempStaRec->fgIsInUse + && prTempStaRec->ucStaState == STA_STATE_3) { + *pucIndex = prTempStaRec->ucWlanIndex; + return TRUE; + } + } + } + return FALSE; +} + + +uint8_t * +wlanGetStaAddrByWlanIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucIndex) +{ + struct WLAN_TABLE *prWtbl; + + if (!prAdapter || ucIndex >= WTBL_SIZE) + return NULL; + + prWtbl = prAdapter->rWifiVar.arWtbl; + if (prWtbl[ucIndex].ucUsed && prWtbl[ucIndex].ucPairwise) + return &prWtbl[ucIndex].aucMacAddr[0]; + + return NULL; +} + +void +wlanNotifyFwSuspend(struct GLUE_INFO *prGlueInfo, + struct net_device *prDev, u_int8_t fgSuspend) +{ + uint32_t rStatus; + uint32_t u4SetInfoLen; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = + (struct NETDEV_PRIVATE_GLUE_INFO *) NULL; + struct CMD_SUSPEND_MODE_SETTING rSuspendCmd; + + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prDev); + + if (prNetDevPrivate->prGlueInfo != prGlueInfo) + DBGLOG(REQ, WARN, "%s: unexpected prGlueInfo(0x%p)!\n", + __func__, prNetDevPrivate->prGlueInfo); + + rSuspendCmd.ucBssIndex = prNetDevPrivate->ucBssIdx; + rSuspendCmd.ucEnableSuspendMode = fgSuspend; + + if (prGlueInfo->prAdapter->rWifiVar.ucWow + && prGlueInfo->prAdapter->rWowCtrl.fgWowEnable) { + /* cfg enable + wow enable => Wow On mdtim*/ + rSuspendCmd.ucMdtim = + prGlueInfo->prAdapter->rWifiVar.ucWowOnMdtim; + rSuspendCmd.ucWowSuspend = 1; + DBGLOG(REQ, INFO, "mdtim [1]\n"); + } else if (prGlueInfo->prAdapter->rWifiVar.ucWow + && !prGlueInfo->prAdapter->rWowCtrl.fgWowEnable + && (prGlueInfo->prAdapter->rWifiVar.ucAdvPws)) { + /* cfg enable + wow disable + adv pws enable + * => Wow Off mdtim + */ + rSuspendCmd.ucMdtim = + prGlueInfo->prAdapter->rWifiVar.ucWowOffMdtim; + rSuspendCmd.ucWowSuspend = 1; + DBGLOG(REQ, INFO, "mdtim [2]\n"); + } else if (prGlueInfo->prAdapter->rWifiVar.ucWow + && !prGlueInfo->prAdapter->rWowCtrl.fgWowEnable + && (!prGlueInfo->prAdapter->rWifiVar.ucAdvPws)) { + /* cfg enable + wow disable + adv pws disable + * => Wow Off mdtim + * => for android screen on/off case. + */ + rSuspendCmd.ucMdtim = + prGlueInfo->prAdapter->rWifiVar.ucWowOffMdtim; + rSuspendCmd.ucWowSuspend = 0; + DBGLOG(REQ, INFO, "mdtim [2B]\n"); + } else if (!prGlueInfo->prAdapter->rWifiVar.ucWow) { + /* cfg disable => MT6632 case + * => Wow Off mdtim + */ + rSuspendCmd.ucMdtim = + prGlueInfo->prAdapter->rWifiVar.ucWowOffMdtim; + rSuspendCmd.ucWowSuspend = 0; + DBGLOG(REQ, INFO, "mdtim [3]\n"); + } + + /* When FW receive command, it check connection state to decide apply + * setting or not + */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidNotifyFwSuspend, + (void *)&rSuspendCmd, + sizeof(rSuspendCmd), + FALSE, + FALSE, + TRUE, + &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, INFO, "wlanNotifyFwSuspend fail\n"); +} + +uint32_t +wlanGetStaIdxByWlanIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucIndex, OUT uint8_t *pucStaIdx) +{ + struct WLAN_TABLE *prWtbl; + + if (!prAdapter || ucIndex >= WTBL_SIZE) + return WLAN_STATUS_FAILURE; + + prWtbl = prAdapter->rWifiVar.arWtbl; + + if (prWtbl[ucIndex].ucUsed && prWtbl[ucIndex].ucPairwise) { + *pucStaIdx = prWtbl[ucIndex].ucStaIndex; + return WLAN_STATUS_SUCCESS; + } + + return WLAN_STATUS_FAILURE; +} + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to query LTE safe channels. + * + * \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_PENDING + * \retval WLAN_STATUS_FAILURE + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryLteSafeChannel(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + uint32_t rResult = WLAN_STATUS_FAILURE; + struct CMD_GET_LTE_SAFE_CHN rQuery_LTE_SAFE_CHN; + + do { + /* Sanity test */ + if ((prAdapter == NULL) || (pu4QueryInfoLen == NULL)) + break; + if ((pvQueryBuffer == NULL) || (u4QueryBufferLen == 0)) + break; + + /* Get LTE safe channel list */ + rResult = wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LTE_CHN, + FALSE, + TRUE, + g_fgIsOid, /* Query ID */ + nicCmdEventQueryLteSafeChn, /* The handler to receive + * firmware notification + */ + nicOidCmdTimeoutCommon, + sizeof(struct CMD_GET_LTE_SAFE_CHN), + (uint8_t *)&rQuery_LTE_SAFE_CHN, + pvQueryBuffer, + u4QueryBufferLen); + DBGLOG(P2P, INFO, "[ACS] Get safe LTE Channels\n"); + } while (FALSE); + + return rResult; +} /* wlanoidQueryLteSafeChannel */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Add dirtiness to neighbor channels of a BSS to estimate channel + * quality. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] prBssDesc Pointer to the BSS description. + * \param[in] u4Dirtiness Expected dirtiness value. + * \param[in] ucCentralChannel Central channel of the given BSS. + * \param[in] ucCoveredRange With ucCoveredRange and ucCentralChannel, + * all the affected channels can be enumerated. + */ +/*----------------------------------------------------------------------------*/ +static void +wlanAddDirtinessToAffectedChannels(struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc, + uint32_t u4Dirtiness, + uint8_t ucCentralChannel, + uint8_t ucCoveredRange) +{ + uint8_t ucIdx, ucStart, ucEnd; + u_int8_t bIs5GChl = ucCentralChannel > 14; + uint8_t ucLeftNeighborChannel, ucRightNeighborChannel, + ucLeftNeighborChannel2 = 0, ucRightNeighborChannel2 = 0, + ucLeftestCoveredChannel, ucRightestCoveredChannel; + struct PARAM_GET_CHN_INFO *prGetChnLoad = & + (prAdapter->rWifiVar.rChnLoadInfo); + + ucLeftestCoveredChannel = ucCentralChannel > ucCoveredRange + ? + ucCentralChannel - ucCoveredRange : 1; + + ucLeftNeighborChannel = ucLeftestCoveredChannel ? + ucLeftestCoveredChannel - 1 : 0; + + /* align leftest covered ch and left neighbor ch to valid 5g ch */ + if (bIs5GChl) { + ucLeftestCoveredChannel += 2; + ucLeftNeighborChannel -= 1; + } else { + /* we select the nearest 2 ch to the leftest covered ch as left + * neighbor chs + */ + ucLeftNeighborChannel2 = ucLeftNeighborChannel > 1 ? + ucLeftNeighborChannel - 1 : 0; + } + + /* handle corner cases of 5g ch*/ + if (ucLeftestCoveredChannel > 14 + && ucLeftestCoveredChannel <= 36) { + ucLeftestCoveredChannel = 36; + ucLeftNeighborChannel = 0; + } else if (ucLeftestCoveredChannel > 64 + && ucLeftestCoveredChannel <= 100) { + ucLeftestCoveredChannel = 100; + ucLeftNeighborChannel = 0; + } else if (ucLeftestCoveredChannel > 144 && + ucLeftestCoveredChannel <= 149) { + ucLeftestCoveredChannel = 149; + ucLeftNeighborChannel = 0; + } + + /* + * because ch 14 is 12MHz away to ch13, we must shift the leftest + * covered ch and left neighbor ch when central ch is ch 14 + */ + if (ucCentralChannel == 14) { + ucLeftestCoveredChannel = 13; + ucLeftNeighborChannel = 12; + ucLeftNeighborChannel2 = 11; + } + + ucRightestCoveredChannel = ucCentralChannel + + ucCoveredRange; + ucRightNeighborChannel = ucRightestCoveredChannel + 1; + + /* align rightest covered ch and right neighbor ch to valid 5g ch */ + if (bIs5GChl) { + ucRightestCoveredChannel -= 2; + ucRightNeighborChannel += 1; + } else { + /* we select the nearest 2 ch to the rightest covered ch as + * right neighbor ch + */ + ucRightNeighborChannel2 = ucRightNeighborChannel < 13 ? + ucRightNeighborChannel + 1 : 0; + } + + /* handle corner cases */ + if (ucRightestCoveredChannel >= 14 + && ucRightestCoveredChannel < 36) { + if (ucRightestCoveredChannel == 14) { + ucRightestCoveredChannel = 13; + ucRightNeighborChannel = 14; + } else { + ucRightestCoveredChannel = 14; + ucRightNeighborChannel = 0; + } + + ucRightNeighborChannel2 = 0; + } else if (ucRightestCoveredChannel >= 64 + && ucRightestCoveredChannel < 100) { + ucRightestCoveredChannel = 64; + ucRightNeighborChannel = 0; + } else if (ucRightestCoveredChannel >= 144 && + ucRightestCoveredChannel < 149) { + ucRightestCoveredChannel = 144; + ucRightNeighborChannel = 0; + } else if (ucRightestCoveredChannel >= 165) { + ucRightestCoveredChannel = 165; + ucRightNeighborChannel = 0; + } + + DBGLOG(SCN, TEMP, "central ch %u\n", ucCentralChannel); + + ucStart = wlanGetChannelIndex(ucLeftestCoveredChannel); + ucEnd = wlanGetChannelIndex(ucRightestCoveredChannel); + if (ucStart >= MAX_CHN_NUM || ucEnd >= MAX_CHN_NUM) { + DBGLOG(SCN, ERROR, "Invalid ch idx of start %u, or end %u\n", + ucStart, ucEnd); + return; + } + + for (ucIdx = ucStart; ucIdx <= ucEnd; ucIdx++) { + prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtiness += + u4Dirtiness; + DBGLOG(SCN, TEMP, "Add dirtiness %d, to covered ch %d\n", + u4Dirtiness, + prGetChnLoad->rEachChnLoad[ucIdx].ucChannel); + } + + if (ucLeftNeighborChannel != 0) { + ucIdx = wlanGetChannelIndex(ucLeftNeighborChannel); + if (ucIdx < MAX_CHN_NUM) { + prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtiness += + (u4Dirtiness >> 1); + DBGLOG(SCN, TEMP, + "Add dirtiness %d, to neighbor ch %d\n", + u4Dirtiness >> 1, + prGetChnLoad->rEachChnLoad[ucIdx].ucChannel); + } + } + + if (ucRightNeighborChannel != 0) { + ucIdx = wlanGetChannelIndex(ucRightNeighborChannel); + if (ucIdx < MAX_CHN_NUM) { + prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtiness += + (u4Dirtiness >> 1); + DBGLOG(SCN, TEMP, + "Add dirtiness %d, to neighbor ch %d\n", + u4Dirtiness >> 1, + prGetChnLoad->rEachChnLoad[ucIdx].ucChannel); + } + } + + if (bIs5GChl) + return; + + /* Only necesaary for 2.5G */ + if (ucLeftNeighborChannel2 != 0) { + ucIdx = wlanGetChannelIndex(ucLeftNeighborChannel2); + if (ucIdx < MAX_CHN_NUM) { + prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtiness += + (u4Dirtiness >> 1); + DBGLOG(SCN, TEMP, + "Add dirtiness %d, to neighbor ch %d\n", + u4Dirtiness >> 1, + prGetChnLoad->rEachChnLoad[ucIdx].ucChannel); + } + } + + if (ucRightNeighborChannel2 != 0) { + ucIdx = wlanGetChannelIndex(ucRightNeighborChannel2); + if (ucIdx < MAX_CHN_NUM) { + prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtiness += + (u4Dirtiness >> 1); + DBGLOG(SCN, TEMP, + "Add dirtiness %d, to neighbor ch %d\n", + u4Dirtiness >> 1, + prGetChnLoad->rEachChnLoad[ucIdx].ucChannel); + } + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief For a scanned BSS, add dirtiness to the channels 1)around its primary + * channels and 2) in its working BW to represent the quality degrade. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] prBssDesc Pointer to the BSS description. + * \param[in] u4Dirtiness Expected dirtiness value. + * \param[in] bIsIndexOne True means index 1, False means index 2. + */ +/*----------------------------------------------------------------------------*/ +static void +wlanCalculateChannelDirtiness(IN struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc, uint32_t u4Dirtiness, + u_int8_t bIsIndexOne) +{ + uint8_t ucCoveredRange = 0, ucCentralChannel = 0, + ucCentralChannel2 = 0; + + if (bIsIndexOne) { + DBGLOG(SCN, TEMP, "Process dirtiness index 1\n"); + ucCentralChannel = prBssDesc->ucChannelNum; + ucCoveredRange = 2; + } else { + DBGLOG(SCN, TEMP, "Process dirtiness index 2, "); + switch (prBssDesc->eChannelWidth) { + case CW_20_40MHZ: + if (prBssDesc->eSco == CHNL_EXT_SCA) { + DBGLOG(SCN, TEMP, "BW40\n"); + ucCentralChannel = prBssDesc->ucChannelNum + 2; + ucCoveredRange = 4; + } else if (prBssDesc->eSco == CHNL_EXT_SCB) { + DBGLOG(SCN, TEMP, "BW40\n"); + ucCentralChannel = prBssDesc->ucChannelNum - 2; + ucCoveredRange = 4; + } else { + DBGLOG(SCN, TEMP, "BW20\n"); + ucCentralChannel = prBssDesc->ucChannelNum; + ucCoveredRange = 2; + } + break; + case CW_80MHZ: + DBGLOG(SCN, TEMP, "BW80\n"); + ucCentralChannel = prBssDesc->ucCenterFreqS1; + ucCoveredRange = 8; + break; + case CW_160MHZ: + DBGLOG(SCN, TEMP, "BW160\n"); + ucCentralChannel = prBssDesc->ucCenterFreqS1; + ucCoveredRange = 16; + break; + case CW_80P80MHZ: + DBGLOG(SCN, TEMP, "BW8080\n"); + ucCentralChannel = prBssDesc->ucCenterFreqS1; + ucCentralChannel2 = prBssDesc->ucCenterFreqS2; + ucCoveredRange = 8; + break; + default: + ucCentralChannel = prBssDesc->ucChannelNum; + ucCoveredRange = 2; + break; + }; + } + + wlanAddDirtinessToAffectedChannels(prAdapter, prBssDesc, + u4Dirtiness, + ucCentralChannel, ucCoveredRange); + + /* 80 + 80 secondary 80 case */ + if (bIsIndexOne || ucCentralChannel2 == 0) + return; + + wlanAddDirtinessToAffectedChannels(prAdapter, prBssDesc, + u4Dirtiness, + ucCentralChannel2, ucCoveredRange); +} + +void +wlanInitChnLoadInfoChannelList(IN struct ADAPTER *prAdapter) +{ + uint8_t ucIdx = 0; + struct PARAM_GET_CHN_INFO *prGetChnLoad = & + (prAdapter->rWifiVar.rChnLoadInfo); + + for (ucIdx = 0; ucIdx < MAX_CHN_NUM; ucIdx++) + prGetChnLoad->rEachChnLoad[ucIdx].ucChannel = + wlanGetChannelNumFromIndex(ucIdx); +} + +uint32_t +wlanCalculateAllChannelDirtiness(IN struct ADAPTER + *prAdapter) +{ + uint32_t rResult = WLAN_STATUS_SUCCESS; + int32_t i4Rssi = 0; + struct BSS_DESC *prBssDesc = NULL; + uint32_t u4Dirtiness = 0; + struct LINK *prBSSDescList = + &(prAdapter->rWifiVar.rScanInfo.rBSSDescList); + + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, + struct BSS_DESC) { + i4Rssi = RCPI_TO_dBm(prBssDesc->ucRCPI); + + if (i4Rssi >= ACS_AP_RSSI_LEVEL_HIGH) + u4Dirtiness = ACS_DIRTINESS_LEVEL_HIGH; + else if (i4Rssi >= ACS_AP_RSSI_LEVEL_LOW) + u4Dirtiness = ACS_DIRTINESS_LEVEL_MID; + else + u4Dirtiness = ACS_DIRTINESS_LEVEL_LOW; + + DBGLOG(SCN, TEMP, "Found an AP(%s), primary ch %d\n", + prBssDesc->aucSSID, prBssDesc->ucChannelNum); + + /* dirtiness index1 */ + wlanCalculateChannelDirtiness(prAdapter, prBssDesc, + u4Dirtiness, TRUE); + + /* dirtiness index2 */ + wlanCalculateChannelDirtiness(prAdapter, prBssDesc, + u4Dirtiness >> 1, FALSE); + } + + return rResult; +} + +uint8_t +wlanGetChannelIndex(IN uint8_t channel) +{ + uint8_t ucIdx = MAX_CHN_NUM; + + if (channel <= 14) + ucIdx = channel - 1; + else if (channel >= 36 && channel <= 64) + ucIdx = 14 + (channel - 36) / 4; + else if (channel >= 100 && channel <= 144) + ucIdx = 14 + 8 + (channel - 100) / 4; + else if (channel >= 149 && channel <= 165) + ucIdx = 14 + 8 + 12 + (channel - 149) / 4; + + return ucIdx; +} + +/*---------------------------------------------------------------------*/ +/*! + * \brief Get ch index by the given ch num; the reverse function of + * wlanGetChannelIndex + * + * \param[in] ucIdx Channel index + * \param[out] ucChannel Channel number + */ +/*---------------------------------------------------------------------*/ + +uint8_t +wlanGetChannelNumFromIndex(IN uint8_t ucIdx) +{ + uint8_t ucChannel = 0; + + if (ucIdx >= 34) + ucChannel = ((ucIdx - 34) << 2) + 149; + else if (ucIdx >= 22) + ucChannel = ((ucIdx - 22) << 2) + 100; + else if (ucIdx >= 14) + ucChannel = ((ucIdx - 14) << 2) + 36; + else + ucChannel = ucIdx + 1; + + return ucChannel; +} + +void +wlanSortChannel(IN struct ADAPTER *prAdapter) +{ + struct PARAM_GET_CHN_INFO *prChnLoadInfo = & + (prAdapter->rWifiVar.rChnLoadInfo); + int8_t ucIdx = 0, ucRoot = 0, ucChild = 0; + struct PARAM_CHN_RANK_INFO rChnRankInfo; + + /* prepare unsorted ch rank list */ + for (ucIdx = 0; ucIdx < MAX_CHN_NUM; ++ucIdx) { + prChnLoadInfo->rChnRankList[ucIdx].ucChannel = + prChnLoadInfo->rEachChnLoad[ucIdx].ucChannel; + prChnLoadInfo->rChnRankList[ucIdx].u4Dirtiness = + prChnLoadInfo->rEachChnLoad[ucIdx].u4Dirtiness; + } + + /* heapify ch rank list */ + for (ucIdx = MAX_CHN_NUM / 2 - 1; ucIdx >= 0; --ucIdx) { + for (ucRoot = ucIdx; ucRoot * 2 + 1 < MAX_CHN_NUM; + ucRoot = ucChild) { + + ucChild = ucRoot * 2 + 1; + if (ucChild < MAX_CHN_NUM - 1 && prChnLoadInfo-> + rChnRankList[ucChild + 1].u4Dirtiness > + prChnLoadInfo->rChnRankList[ucChild].u4Dirtiness) + ucChild += 1; + + if (prChnLoadInfo->rChnRankList[ucChild].u4Dirtiness <= + prChnLoadInfo->rChnRankList[ucRoot].u4Dirtiness) + break; + + rChnRankInfo = prChnLoadInfo->rChnRankList[ucChild]; + prChnLoadInfo->rChnRankList[ucChild] = + prChnLoadInfo->rChnRankList[ucRoot]; + prChnLoadInfo->rChnRankList[ucRoot] = rChnRankInfo; + } + } + + /* sort ch rank list */ + for (ucIdx = MAX_CHN_NUM - 1; ucIdx > 0; ucIdx--) { + rChnRankInfo = prChnLoadInfo->rChnRankList[0]; + prChnLoadInfo->rChnRankList[0] = + prChnLoadInfo->rChnRankList[ucIdx]; + prChnLoadInfo->rChnRankList[ucIdx] = rChnRankInfo; + + for (ucRoot = 0; ucRoot * 2 + 1 < ucIdx; ucRoot = ucChild) { + ucChild = ucRoot * 2 + 1; + if (ucChild < ucIdx - 1 && prChnLoadInfo-> + rChnRankList[ucChild + 1].u4Dirtiness > + prChnLoadInfo->rChnRankList[ucChild].u4Dirtiness) + ucChild += 1; + + if (prChnLoadInfo->rChnRankList[ucChild].u4Dirtiness <= + prChnLoadInfo->rChnRankList[ucRoot].u4Dirtiness) + break; + + rChnRankInfo = prChnLoadInfo->rChnRankList[ucChild]; + prChnLoadInfo->rChnRankList[ucChild] = + prChnLoadInfo->rChnRankList[ucRoot]; + prChnLoadInfo->rChnRankList[ucRoot] = rChnRankInfo; + } + } + + for (ucIdx = 0; ucIdx < MAX_CHN_NUM; ++ucIdx) + log_dbg(P2P, TEMP, "[ACS]channel=%d, dirtiness=%d\n", + prChnLoadInfo->rChnRankList[ucIdx].ucChannel, + prChnLoadInfo->rChnRankList[ucIdx].u4Dirtiness); + +} +#endif + +#if ((CFG_SISO_SW_DEVELOP == 1) || (CFG_SUPPORT_SPE_IDX_CONTROL == 1)) +uint8_t +wlanGetAntPathType(IN struct ADAPTER *prAdapter, + IN enum ENUM_WF_PATH_FAVOR_T eWfPathFavor, + IN uint8_t ucBssIndex) +{ + uint8_t ucFianlWfPathType = eWfPathFavor; +#if (CFG_SUPPORT_SPE_IDX_CONTROL == 1) + uint8_t ucNss = prAdapter->rWifiVar.ucNSS; + uint8_t ucSpeIdxCtrl = GET_SPE_IDX_CTRL(prAdapter); +#if CFG_SUPPORT_COEX_NON_COTX + enum ENUM_BAND eBand; + struct BSS_INFO *prBssInfo; + + if (GET_COEX_NON_COTX(prAdapter) && + ucNss == 2) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + if (prBssInfo->fgIsGranted) + eBand = prBssInfo->eBandGranted; + else + eBand = prBssInfo->eBand; + if (eBand == BAND_2G4 && + prAdapter->rWifiVar.ucSpeIdxCtrl2g != 2) + ucSpeIdxCtrl = prAdapter->rWifiVar.ucSpeIdxCtrl2g; + } +#endif + if (ucNss <= 2) { + if (ucSpeIdxCtrl == 0) + ucFianlWfPathType = ENUM_WF_0_ONE_STREAM_PATH_FAVOR; + else if (ucSpeIdxCtrl == 1) + ucFianlWfPathType = ENUM_WF_1_ONE_STREAM_PATH_FAVOR; + else if (ucSpeIdxCtrl == 2) { + if (ucNss > 1) + ucFianlWfPathType = + ENUM_WF_0_1_DUP_STREAM_PATH_FAVOR; + else + ucFianlWfPathType = ENUM_WF_NON_FAVOR; + } else + ucFianlWfPathType = ENUM_WF_NON_FAVOR; + } + DBGLOG(TX, INFO, "WfPathType:%d, SpeIdxCtrl=%d\n", + ucFianlWfPathType, ucSpeIdxCtrl); +#endif + return ucFianlWfPathType; +} + +uint8_t +wlanAntPathFavorSelect(IN struct ADAPTER *prAdapter, + IN enum ENUM_WF_PATH_FAVOR_T eWfPathFavor) +{ + uint8_t ucRetValSpeIdx = 0x18; +#if (CFG_SUPPORT_SPE_IDX_CONTROL == 1) + uint8_t ucNss = prAdapter->rWifiVar.ucNSS; + + if (ucNss <= 2) { + if ((eWfPathFavor == ENUM_WF_NON_FAVOR) || + (eWfPathFavor == ENUM_WF_0_ONE_STREAM_PATH_FAVOR) || + (eWfPathFavor == ENUM_WF_0_1_TWO_STREAM_PATH_FAVOR)) + ucRetValSpeIdx = ANTENNA_WF0; + else if (eWfPathFavor == ENUM_WF_0_1_DUP_STREAM_PATH_FAVOR) + ucRetValSpeIdx = 0x18; + else if (eWfPathFavor == ENUM_WF_1_ONE_STREAM_PATH_FAVOR) + ucRetValSpeIdx = ANTENNA_WF1; + else + ucRetValSpeIdx = ANTENNA_WF0; + } +#endif + return ucRetValSpeIdx; +} +#endif + +uint8_t +wlanGetSpeIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN enum ENUM_WF_PATH_FAVOR_T eWfPathFavor) +{ + uint8_t ucRetValSpeIdx = 0; +#if ((CFG_SISO_SW_DEVELOP == 1) || (CFG_SUPPORT_SPE_IDX_CONTROL == 1)) + struct BSS_INFO *prBssInfo; + enum ENUM_BAND eBand = BAND_NULL; + + if (ucBssIndex > prAdapter->ucHwBssIdNum) { + DBGLOG(SW4, ERROR, "Invalid BssInfo index[%u], skip dump!\n", + ucBssIndex); + return ucRetValSpeIdx; + } + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + /* + * if DBDC enable return 0, else depend 2.4G/5G & support WF path + * retrun accurate value + */ + if (!prAdapter->rWifiVar.fgDbDcModeEn) { + if (prBssInfo->fgIsGranted) + eBand = prBssInfo->eBandGranted; + else + eBand = prBssInfo->eBand; + + if (eBand == BAND_2G4) { + if (IS_WIFI_2G4_SISO(prAdapter)) { + if (IS_WIFI_2G4_WF0_SUPPORT(prAdapter)) + ucRetValSpeIdx = ANTENNA_WF0; + else + ucRetValSpeIdx = ANTENNA_WF1; + } else { + if (IS_WIFI_SMART_GEAR_SUPPORT_WF0_SISO( + prAdapter)) + ucRetValSpeIdx = ANTENNA_WF0; + else if (IS_WIFI_SMART_GEAR_SUPPORT_WF1_SISO( + prAdapter)) + ucRetValSpeIdx = ANTENNA_WF1; + else + ucRetValSpeIdx = wlanAntPathFavorSelect( + prAdapter, eWfPathFavor); + } + } else if (eBand == BAND_5G) { + if (IS_WIFI_5G_SISO(prAdapter)) { + if (IS_WIFI_5G_WF0_SUPPORT(prAdapter)) + ucRetValSpeIdx = ANTENNA_WF0; + else + ucRetValSpeIdx = ANTENNA_WF1; + } else { + if (IS_WIFI_SMART_GEAR_SUPPORT_WF0_SISO( + prAdapter)) + ucRetValSpeIdx = ANTENNA_WF0; + else if (IS_WIFI_SMART_GEAR_SUPPORT_WF1_SISO( + prAdapter)) + ucRetValSpeIdx = ANTENNA_WF1; + else + ucRetValSpeIdx = wlanAntPathFavorSelect( + prAdapter, eWfPathFavor); + } + } else + ucRetValSpeIdx = wlanAntPathFavorSelect(prAdapter, + eWfPathFavor); + } + DBGLOG(INIT, INFO, "SpeIdx:%d,D:%d,G=%d,B=%d,Bss=%d\n", + ucRetValSpeIdx, prAdapter->rWifiVar.fgDbDcModeEn, + prBssInfo->fgIsGranted, eBand, ucBssIndex); +#endif + return ucRetValSpeIdx; +} + +uint8_t +wlanGetSupportNss(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + uint8_t ucRetValNss = prAdapter->rWifiVar.ucNSS; +#if CFG_SISO_SW_DEVELOP + struct BSS_INFO *prBssInfo; + enum ENUM_BAND eBand = BAND_NULL; + + if (ucBssIndex > prAdapter->ucHwBssIdNum) { + DBGLOG(SW4, ERROR, "Invalid BssInfo index[%u], skip dump!\n", + ucBssIndex); + return ucRetValNss; + } + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + /* + * depend 2.4G/5G support SISO/MIMO + * retrun accurate value + */ + if (prBssInfo->fgIsGranted) + eBand = prBssInfo->eBandGranted; + else + eBand = prBssInfo->eBand; + + if ((eBand == BAND_2G4) && IS_WIFI_2G4_SISO(prAdapter)) + ucRetValNss = 1; + else if ((eBand == BAND_5G) && IS_WIFI_5G_SISO(prAdapter)) + ucRetValNss = 1; + DBGLOG(INIT, INFO, "Nss=%d,G=%d,B=%d,Bss=%d\n", + ucRetValNss, prBssInfo->fgIsGranted, eBand, ucBssIndex); +#endif + return ucRetValNss; +} + +#if CFG_SUPPORT_LOWLATENCY_MODE +/*----------------------------------------------------------------------------*/ +/*! + * \brief This is a private routine, which is used to initialize the variables + * for low latency mode. + * + * \param prAdapter Pointer of Adapter Data Structure + * + * \retval WLAN_STATUS_SUCCESS: Success + * \retval WLAN_STATUS_FAILURE: Failed + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanAdapterStartForLowLatency(IN struct ADAPTER *prAdapter) +{ + uint32_t u4Status = WLAN_STATUS_SUCCESS; + + /* Default disable low latency mode */ + prAdapter->fgEnLowLatencyMode = FALSE; + + /* Default enable scan */ + prAdapter->fgEnCfg80211Scan = TRUE; + + return u4Status; +} +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ +int32_t wlanGetFileContent(struct ADAPTER *prAdapter, + const uint8_t *pcFileName, uint8_t *pucBuf, + uint32_t u4MaxFileLen, uint32_t *pu4ReadFileLen, u_int8_t bReqFw) +{ + if (bReqFw) + return kalRequestFirmware(pcFileName, pucBuf, + u4MaxFileLen, pu4ReadFileLen, + prAdapter->prGlueInfo->prDev); + + return kalReadToFile(pcFileName, pucBuf, + u4MaxFileLen, pu4ReadFileLen); +} + +void wlanReleasePendingCmdById(struct ADAPTER *prAdapter, uint8_t ucCid) +{ + struct QUE *prCmdQue; + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue = &rTempCmdQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + DBGLOG(OID, INFO, "Remove pending Cmd: CID %d\n", ucCid); + + /* 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, struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + if (prCmdInfo->ucCID != ucCid) { + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + continue; + } + + if (prCmdInfo->pfCmdTimeoutHandler) { + prCmdInfo->pfCmdTimeoutHandler(prAdapter, prCmdInfo); + } else if (prCmdInfo->fgIsOid) { + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, 0, + WLAN_STATUS_FAILURE); + } + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This is a routine, which is used to release tx cmd after bus suspend + * + * \param prAdapter Pointer of Adapter Data Structure + */ +/*----------------------------------------------------------------------------*/ +void wlanReleaseAllTxCmdQueue(struct ADAPTER *prAdapter) +{ + struct QUE *prCmdQue; + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue = &rTempCmdQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + /* dump queue info before release for debug */ + cmdBufDumpCmdQueue(&prAdapter->rPendingCmdQueue, + "waiting response CMD queue"); + cmdBufDumpCmdQueue(&prAdapter->rTxCmdQueue, + "Tx CMD queue"); + + DBGLOG(OID, INFO, "Remove all pending Cmd\n"); + /* 1: Clear Pending OID */ + wlanReleasePendingOid(prAdapter, 1); + + /* 2: Clear other pending cmd 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, struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + + if (prCmdInfo->pfCmdTimeoutHandler) { + prCmdInfo->pfCmdTimeoutHandler(prAdapter, prCmdInfo); + } else if (prCmdInfo->fgIsOid) { + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, 0, + WLAN_STATUS_FAILURE); + } + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + + /* 3. clear tx cmd queue*/ + wlanClearTxCommandQueue(prAdapter); + + /* 4. clear tx cmd done queue*/ + wlanClearTxCommandDoneQueue(prAdapter); + +} + +void +wlanWaitCfg80211SuspendDone(struct GLUE_INFO *prGlueInfo) +{ + uint8_t u1Count = 0; + + while (!(test_bit(SUSPEND_FLAG_CLEAR_WHEN_RESUME, + &prGlueInfo->prAdapter->ulSuspendFlag))) { + if (u1Count > HIF_SUSPEND_MAX_WAIT_TIME) { + DBGLOG(HAL, ERROR, "cfg80211 not suspend\n"); + break; + } + usleep_range(5000, 6000); + u1Count++; + } +} + +/* Translate Decimals string to Hex +** The result will be put in a 2bytes variable. +** Integer part will occupy the left most 3 bits, and decimal part is in the +** left 13 bits +** Integer part can be parsed by kstrtou16, decimal part should be translated by +** mutiplying +** 16 and then pick integer part. +** For example +*/ +uint32_t wlanDecimalStr2Hexadecimals(uint8_t *pucDecimalStr, uint16_t *pu2Out) +{ + uint8_t aucDecimalStr[32] = {0,}; + uint8_t *pucDecimalPart = NULL; + uint8_t *tmp = NULL; + uint32_t u4Result = 0; + uint32_t u4Ret = 0; + uint32_t u4Degree = 0; + uint32_t u4Remain = 0; + uint8_t ucAccuracy = 4; /* Hex decimals accuarcy is 4 bytes */ + uint32_t u4Base = 1; + + if (!pu2Out || !pucDecimalStr) + return 1; + + while (*pucDecimalStr == '0') + pucDecimalStr++; + kalStrnCpy(aucDecimalStr, pucDecimalStr, sizeof(aucDecimalStr) - 1); + pucDecimalPart = strchr(aucDecimalStr, '.'); + if (!pucDecimalPart) { + DBGLOG(INIT, INFO, "No decimal part, ori str %s\n", + pucDecimalStr); + goto integer_part; + } + *pucDecimalPart++ = 0; + /* get decimal degree */ + tmp = pucDecimalPart + strlen(pucDecimalPart); + do { + if (tmp == pucDecimalPart) { + DBGLOG(INIT, INFO, + "Decimal part are all 0, ori str %s\n", + pucDecimalStr); + goto integer_part; + } + tmp--; + } while (*tmp == '0'); + + *(++tmp) = 0; + u4Degree = (uint32_t)(tmp - pucDecimalPart); + /* if decimal part is not 0, translate it to hexadecimal decimals */ + /* Power(10, degree) */ + for (; u4Remain < u4Degree; u4Remain++) + u4Base *= 10; + + while (*pucDecimalPart == '0') + pucDecimalPart++; + + u4Ret = kstrtou32(pucDecimalPart, 0, &u4Remain); + if (u4Ret) { + DBGLOG(INIT, ERROR, "Parse decimal str %s error, degree %u\n", + pucDecimalPart, u4Degree); + return u4Ret; + } + + do { + u4Remain *= 16; + u4Result |= (u4Remain / u4Base) << ((ucAccuracy-1) * 4); + u4Remain %= u4Base; + ucAccuracy--; + } while (u4Remain && ucAccuracy > 0); + /* Each Hex Decimal byte was left shift more than 3 bits, so need + ** right shift 3 bits at last + ** For example, mmmnnnnnnnnnnnnn. + ** mmm is integer part, n represents decimals part. + ** the left most 4 n are shift 9 bits. But in for loop, we shift 12 bits + **/ + u4Result >>= 3; + u4Remain = 0; + +integer_part: + u4Ret = kstrtou32(aucDecimalStr, 0, &u4Remain); + u4Result |= u4Remain << 13; + + if (u4Ret) + DBGLOG(INIT, ERROR, "Parse integer str %s error\n", + aucDecimalStr); + else { + *pu2Out = u4Result & 0xffff; + DBGLOG(INIT, TRACE, "Result 0x%04x\n", *pu2Out); + } + return u4Ret; +} + +uint32_t wlanGetSupportedFeatureSet(IN struct GLUE_INFO *prGlueInfo) +{ + uint32_t u4FeatureSet = WIFI_HAL_FEATURE_SET; + struct REG_INFO *prRegInfo; + + prRegInfo = kalGetConfiguration(prGlueInfo); + if ((prRegInfo != NULL) && (prRegInfo->ucSupport5GBand)) + u4FeatureSet |= WIFI_FEATURE_INFRA_5G; + + return u4FeatureSet; +} + +uint32_t wlanSetEd(IN struct ADAPTER *prAdapter, int32_t u4EdVal2G, + int32_t u4EdVal5G, uint32_t u4Sel) +{ + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + + rSwCtrlInfo.u4Id = CMD_SW_DBGCTL_ADVCTL_SET_ID + CMD_ADVCTL_ED_ID; + rSwCtrlInfo.u4Data = ((u4EdVal2G & 0xFF) | + ((u4EdVal5G & 0xFF)<<16) | (u4Sel << 31)); + DBGLOG(REQ, INFO, "rSwCtrlInfo.u4Data=0x%x,\n", rSwCtrlInfo.u4Data); + return kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, &rSwCtrlInfo, + sizeof(rSwCtrlInfo), FALSE, FALSE, TRUE, &u4BufLen); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is a wrapper to send eapol offload (rekey) command +* with PN sync consideration +* +* @param prGlueInfo Pointer of prGlueInfo Data Structure +* +* @return VOID +*/ +/*----------------------------------------------------------------------------*/ +int wlanSuspendRekeyOffload(struct GLUE_INFO *prGlueInfo, uint8_t ucRekeyMode) +{ + uint32_t u4BufLen; + struct PARAM_GTK_REKEY_DATA *prGtkData; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + int32_t i4Rslt = -EINVAL; +#if CFG_SUPPORT_REPLAY_DETECTION + struct GL_DETECT_REPLAY_INFO *prDetRplyInfo = NULL; + uint8_t ucCurKeyId; + uint8_t ucRpyOffload; +#endif + + ASSERT(prGlueInfo); + +#if CFG_SUPPORT_REPLAY_DETECTION + ucRpyOffload = prGlueInfo->prAdapter->rWifiVar.ucRpyDetectOffload; + + if ((ucRekeyMode == GTK_REKEY_CMD_MODE_SET_BCMC_PN) && + (ucRpyOffload == FALSE)) { + DBGLOG(RSN, INFO, + "Set PN to fw, but feature off. no action\n"); + return WLAN_STATUS_SUCCESS; + } + + if ((ucRekeyMode == GTK_REKEY_CMD_MODE_GET_BCMC_PN) && + (ucRpyOffload == FALSE)) { + DBGLOG(RSN, INFO, + "Get PN from fw, but feature off. no action\n"); + return WLAN_STATUS_SUCCESS; + } +#endif + + prGtkData = + (struct PARAM_GTK_REKEY_DATA *) kalMemAlloc(sizeof( + struct PARAM_GTK_REKEY_DATA), VIR_MEM_TYPE); + + if (!prGtkData) + return WLAN_STATUS_SUCCESS; + + kalMemZero(prGtkData, sizeof(struct PARAM_GTK_REKEY_DATA)); + + /* if enable, FW rekey offload. if disable, rekey back to supplicant */ + prGtkData->ucRekeyMode = ucRekeyMode; + DBGLOG(RSN, INFO, "GTK Rekey ucRekeyMode = %d\n", ucRekeyMode); + + if (ucRekeyMode == GTK_REKEY_CMD_MODE_OFFLOAD_ON) { + DBGLOG(RSN, INFO, "kek\n"); + DBGLOG_MEM8(RSN, INFO, (uint8_t *)prGlueInfo->rWpaInfo.aucKek, + NL80211_KEK_LEN); + DBGLOG(RSN, INFO, "kck\n"); + DBGLOG_MEM8(RSN, INFO, (uint8_t *)prGlueInfo->rWpaInfo.aucKck, + NL80211_KCK_LEN); + DBGLOG(RSN, INFO, "replay count\n"); + DBGLOG_MEM8(RSN, INFO, + (uint8_t *)prGlueInfo->rWpaInfo.aucReplayCtr, + NL80211_REPLAY_CTR_LEN); + + kalMemCopy(prGtkData->aucKek, prGlueInfo->rWpaInfo.aucKek, + NL80211_KEK_LEN); + kalMemCopy(prGtkData->aucKck, prGlueInfo->rWpaInfo.aucKck, + NL80211_KCK_LEN); + kalMemCopy(prGtkData->aucReplayCtr, + prGlueInfo->rWpaInfo.aucReplayCtr, + NL80211_REPLAY_CTR_LEN); + + prGtkData->ucBssIndex = + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + + prGtkData->u4Proto = NL80211_WPA_VERSION_2; + if (prGlueInfo->rWpaInfo.u4WpaVersion == + IW_AUTH_WPA_VERSION_WPA) + prGtkData->u4Proto = NL80211_WPA_VERSION_1; + + if (prGlueInfo->rWpaInfo.u4CipherPairwise == + IW_AUTH_CIPHER_TKIP) + prGtkData->u4PairwiseCipher = BIT(3); + else if (prGlueInfo->rWpaInfo.u4CipherPairwise == + IW_AUTH_CIPHER_CCMP) + prGtkData->u4PairwiseCipher = BIT(4); + else { + kalMemFree(prGtkData, VIR_MEM_TYPE, + sizeof(PARAM_GTK_REKEY_DATA)); + return WLAN_STATUS_SUCCESS; + } + + if (prGlueInfo->rWpaInfo.u4CipherGroup == + IW_AUTH_CIPHER_TKIP) + prGtkData->u4GroupCipher = BIT(3); + else if (prGlueInfo->rWpaInfo.u4CipherGroup == + IW_AUTH_CIPHER_CCMP) + prGtkData->u4GroupCipher = BIT(4); + else { + kalMemFree(prGtkData, VIR_MEM_TYPE, + sizeof(PARAM_GTK_REKEY_DATA)); + return WLAN_STATUS_SUCCESS; + } + + prGtkData->u4KeyMgmt = prGlueInfo->rWpaInfo.u4KeyMgmt; + prGtkData->u4MgmtGroupCipher = 0; + + } + + if (ucRekeyMode == GTK_REKEY_CMD_MODE_OFLOAD_OFF) { + /* inform FW disable EAPOL offload */ + DBGLOG(RSN, INFO, "Disable EAPOL offload\n"); + } + +#if CFG_SUPPORT_REPLAY_DETECTION + if (ucRekeyMode == GTK_REKEY_CMD_MODE_RPY_OFFLOAD_ON) + DBGLOG(RSN, INFO, + "ucRekeyMode(rpy rekey offload on): %d\n", + ucRekeyMode); + + if (ucRekeyMode == GTK_REKEY_CMD_MODE_RPY_OFFLOAD_OFF) + DBGLOG(RSN, INFO, + "ucRekeyMode(rpy rekey offload off): %d\n", + ucRekeyMode); + + if ((ucRekeyMode == GTK_REKEY_CMD_MODE_SET_BCMC_PN) && + (ucRpyOffload == TRUE)) { + + prDetRplyInfo = &prGlueInfo->prDetRplyInfo; + ucCurKeyId = prDetRplyInfo->ucCurKeyId; + prGtkData->ucCurKeyId = ucCurKeyId; + DBGLOG_MEM8(RSN, INFO, + (uint8_t *)prGtkData->aucReplayCtr, + NL80211_REPLAY_CTR_LEN); + kalMemCopy(prGtkData->aucReplayCtr, + prDetRplyInfo->arReplayPNInfo[ucCurKeyId].auPN, + NL80211_REPLAY_CTR_LEN); + + /* set bc/mc PN zero before suspend */ + kalMemZero(prDetRplyInfo->arReplayPNInfo[ucCurKeyId].auPN, + NL80211_REPLAY_CTR_LEN); + } + + if ((ucRekeyMode == GTK_REKEY_CMD_MODE_GET_BCMC_PN) && + (ucRpyOffload == TRUE)) { + prGtkData->ucBssIndex = + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + } +#endif + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetGtkRekeyData, + prGtkData, sizeof(struct PARAM_GTK_REKEY_DATA), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, ERROR, "Suspend rekey data err:%x\n", rStatus); + else + i4Rslt = 0; + + kalMemFree(prGtkData, VIR_MEM_TYPE, sizeof(PARAM_GTK_REKEY_DATA)); + + return i4Rslt; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is a wrapper to send power-saving mode command +* when AIS enter wow, and send WOW command +* Also let GC/GO/AP enter deactivate state to enter TOP sleep +* +* @param prGlueInfo Pointer of prGlueInfo Data Structure +* +* @return VOID +*/ +/*----------------------------------------------------------------------------*/ +void wlanSuspendPmHandle(struct GLUE_INFO *prGlueInfo) +{ + uint8_t idx; + enum PARAM_POWER_MODE ePwrMode; + /* struct BSS_INFO *prBssInfo; */ + uint8_t ucKekZeroCnt = 0; + uint8_t ucKckZeroCnt = 0; + uint8_t ucGtkOffload = TRUE; + uint8_t i = 0; +#if CFG_SUPPORT_REPLAY_DETECTION + struct GL_DETECT_REPLAY_INFO *prDetRplyInfo = NULL; + uint8_t ucKeyIdx = 0; + uint8_t ucRpyOffload = 0; +#endif + struct STA_RECORD *prStaRec; + struct RX_BA_ENTRY *prRxBaEntry; + +#if CFG_SUPPORT_ADVANCE_CONTROL + if (prGlueInfo->prAdapter->u4IsKeepFullPwrBitmap) + wlanKeepFullPwr(prGlueInfo->prAdapter, FALSE); +#endif + /* if cfg EAPOL offload is 0, we set rekey offload when enter wow */ + if (!prGlueInfo->prAdapter->rWifiVar.ucEapolOffload) { + + /* + * check if KCK, KEK not sync from supplicant. + * if no these info updated from supplicant, + * disable GTK offload feature. + */ + for (i = 0; i < NL80211_KEK_LEN; i++) { + if (prGlueInfo->rWpaInfo.aucKek[i] == 0x00) + ucKekZeroCnt++; + } + + for (i = 0; i < NL80211_KCK_LEN; i++) { + if (prGlueInfo->rWpaInfo.aucKck[i] == 0x00) + ucKckZeroCnt++; + } + + if ((ucKekZeroCnt == NL80211_KCK_LEN) || + (ucKckZeroCnt == NL80211_KCK_LEN)) { + DBGLOG(RSN, INFO, "no offload, no KCK/KEK from cfg\n"); + + ucGtkOffload = FALSE; + /* set bc/mc replay detection off to fw */ + wlanSuspendRekeyOffload(prGlueInfo, + GTK_REKEY_CMD_MODE_RPY_OFFLOAD_OFF); + } + +#if CFG_SUPPORT_REPLAY_DETECTION + ucRpyOffload = + prGlueInfo->prAdapter->rWifiVar.ucRpyDetectOffload; + + if (ucRpyOffload && ucGtkOffload) + wlanSuspendRekeyOffload(prGlueInfo, + GTK_REKEY_CMD_MODE_SET_BCMC_PN); +#endif + + if (ucGtkOffload) + wlanSuspendRekeyOffload(prGlueInfo, + GTK_REKEY_CMD_MODE_OFFLOAD_ON); + +#if CFG_SUPPORT_REPLAY_DETECTION + prDetRplyInfo = &prGlueInfo->prDetRplyInfo; + for (ucKeyIdx = 0; ucKeyIdx < 4; ucKeyIdx++) { + kalMemZero(prDetRplyInfo->arReplayPNInfo[ucKeyIdx].auPN, + NL80211_KEYRSC_LEN); + } +#endif + + DBGLOG(HAL, STATE, "Suspend rekey offload\n"); + } + + /* Pending Timer related to CNM need to check and + * perform corresponding timeout handler. Without it, + * Might happen CNM abnormal after resume or during suspend. + */ + cnmCheckPendingTimer(prGlueInfo->prAdapter); + + /* 1) wifi cfg "Wow" is true, 2) wow or AdvPws is enable + * 3) WIfI connected => execute WOW flow + * Send power-saving cmd when enter wow, even w/o cfg80211 support + */ + if (prGlueInfo->prAdapter->rWifiVar.ucWow && + (prGlueInfo->prAdapter->rWowCtrl.fgWowEnable || + prGlueInfo->prAdapter->rWifiVar.ucAdvPws)) { + if (kalGetMediaStateIndicated(prGlueInfo) == + PARAM_MEDIA_STATE_CONNECTED) { + /* AIS bss enter wow power mode, default fast pws */ + ePwrMode = prGlueInfo->prAdapter->rWifiVar.ucWowPwsMode; + idx = prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + nicConfigPowerSaveWowProfile(prGlueInfo->prAdapter, idx, + ePwrMode, FALSE, TRUE); + DBGLOG(HAL, STATE, "Wow AIS_idx:%d, pwr mode:%d\n", + idx, ePwrMode); + + DBGLOG(HAL, STATE, "enter WOW flow\n"); + kalWowProcess(prGlueInfo, TRUE); + } + } + + /* After resuming, WinStart will unsync with AP's SN. + * Set fgFirstSnToWinStart for all valid BA entry before suspend. + */ + for (idx = 0; idx < CFG_STA_REC_NUM; idx++) { + prStaRec = cnmGetStaRecByIndex(prGlueInfo->prAdapter, idx); + if (!prStaRec) + continue; + + for (i = 0; i < CFG_RX_MAX_BA_TID_NUM; i++) { + prRxBaEntry = prStaRec->aprRxReorderParamRefTbl[i]; + if (!prRxBaEntry || !(prRxBaEntry->fgIsValid)) + continue; + + prRxBaEntry->fgFirstSnToWinStart = TRUE; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to restore power-saving mode command when leave wow +* But ignore GC/GO/AP role +* +* @param prGlueInfo Pointer of prGlueInfo Data Structure +* +* @return VOID +*/ +/*----------------------------------------------------------------------------*/ +void wlanResumePmHandle(struct GLUE_INFO *prGlueInfo) +{ +#if 1 + enum PARAM_POWER_MODE ePwrMode = Param_PowerModeCAM; + uint8_t ucKekZeroCnt = 0; + uint8_t ucKckZeroCnt = 0; + uint8_t ucGtkOffload = TRUE; + uint8_t i = 0; + struct ADAPTER *prAdapter; +#if CFG_SUPPORT_REPLAY_DETECTION + struct GL_DETECT_REPLAY_INFO *prDetRplyInfo = NULL; + uint8_t ucKeyIdx = 0; + uint8_t ucRpyOffload = 0; +#endif + + prAdapter = prGlueInfo->prAdapter; + + /* if cfg EAPOL offload disble, we disable offload when leave wow */ + if (!prGlueInfo->prAdapter->rWifiVar.ucEapolOffload) { + + /* + * check if KCK, KEK not sync from supplicant. + * if no these info updated from supplicant, + *disable GTK offload feature. + */ + for (i = 0; i < NL80211_KEK_LEN; i++) { + if (prGlueInfo->rWpaInfo.aucKek[i] == 0x00) + ucKekZeroCnt++; + } + + for (i = 0; i < NL80211_KCK_LEN; i++) { + if (prGlueInfo->rWpaInfo.aucKck[i] == 0x00) + ucKckZeroCnt++; + } + + if ((ucKekZeroCnt == NL80211_KCK_LEN) || + (ucKckZeroCnt == NL80211_KCK_LEN)) { + + DBGLOG(RSN, INFO, "no offload, no KCK/KEK from cfg\n"); + + ucGtkOffload = FALSE; + /* set bc/mc replay detection off to fw */ + wlanSuspendRekeyOffload(prGlueInfo, + GTK_REKEY_CMD_MODE_RPY_OFFLOAD_OFF); + } + +#if CFG_SUPPORT_REPLAY_DETECTION + prDetRplyInfo = &prGlueInfo->prDetRplyInfo; + + /* Reset BC/MC KeyRSC to prevent incorrect replay detection. */ + for (ucKeyIdx = 0; ucKeyIdx < 4; ucKeyIdx++) { + kalMemZero(prDetRplyInfo->arReplayPNInfo[ucKeyIdx].auPN, + NL80211_KEYRSC_LEN); + } + + ucRpyOffload = + prGlueInfo->prAdapter->rWifiVar.ucRpyDetectOffload; + + /* sync BC/MC PN */ + if (ucRpyOffload && ucGtkOffload) + wlanSuspendRekeyOffload(prGlueInfo, + GTK_REKEY_CMD_MODE_GET_BCMC_PN); +#endif + + if (ucGtkOffload) { + wlanSuspendRekeyOffload(prGlueInfo, + GTK_REKEY_CMD_MODE_OFLOAD_OFF); + + DBGLOG(HAL, STATE, "Resume rekey offload disable\n"); + } + } + + if (prGlueInfo->prAdapter->rWifiVar.ucWow && + (prGlueInfo->prAdapter->rWowCtrl.fgWowEnable || + prGlueInfo->prAdapter->rWifiVar.ucAdvPws)) { + if (kalGetMediaStateIndicated(prGlueInfo) == + PARAM_MEDIA_STATE_CONNECTED) { + DBGLOG(HAL, STATE, "leave WOW. AIS BssIdx:%d\n", + prAdapter->prAisBssInfo->ucBssIndex); + kalWowProcess(prGlueInfo, FALSE); + + /* Restore AIS pws when leave wow, ignore ePwrMode */ + nicConfigPowerSaveWowProfile(prGlueInfo->prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, + ePwrMode, FALSE, FALSE); + } + } +#endif +#if CFG_SUPPORT_ADVANCE_CONTROL + if (prGlueInfo->prAdapter->u4IsKeepFullPwrBitmap) + wlanKeepFullPwr(prGlueInfo->prAdapter, TRUE); +#endif + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to wake up WiFi +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +uint32_t wlanWakeUpWiFi(IN struct ADAPTER *prAdapter) +{ + u_int8_t fgReady; + + if (!prAdapter) + return WLAN_STATUS_FAILURE; + + HAL_WIFI_FUNC_READY_CHECK(prAdapter, prChipInfo->sw_ready_bits, + &fgReady); + + if (fgReady) { + DBGLOG(INIT, INFO, + "Wi-Fi is already ON!, turn off before FW DL!\n"); +#if defined(_HIF_USB) + wlanSendDummyCmd(prAdapter, FALSE); /* for deep sleep mode */ + nicEnableInterrupt(prAdapter); /* clear USB EPIN FIFO */ +#endif + + if (wlanPowerOffWifi(prAdapter) != WLAN_STATUS_SUCCESS) + return WLAN_STATUS_FAILURE; + + } + + nicpmWakeUpWiFi(prAdapter); + HAL_HIF_INIT(prAdapter); + + return WLAN_STATUS_SUCCESS; +} + +void disconnect_sta(struct ADAPTER *prAdapter, struct STA_RECORD *sta_rec) +{ + struct GLUE_INFO *glue_info; + struct MSG_AIS_ABORT *ais_abort_msg = NULL; + struct MSG_P2P_CONNECTION_ABORT *p2p_abot_msg = NULL; + struct BSS_INFO *p2p_bss_info = NULL; + uint8_t role_idx = 0; + + + if (!prAdapter) { + DBGLOG(MEM, ERROR, "prAdapter is NULL\n"); + return; + } + if (!sta_rec) { + DBGLOG(MEM, ERROR, "sta_rec is NULL\n"); + return; + } + + glue_info = prAdapter->prGlueInfo; + + switch (sta_rec->eStaType) { + case STA_TYPE_LEGACY_AP: + if (prAdapter->rAcpiState == ACPI_STATE_D3) + return; + /* prepare message to AIS */ + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = FALSE; + /* Send AIS Abort Message */ + ais_abort_msg = + (struct MSG_AIS_ABORT *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_AIS_ABORT)); + if (ais_abort_msg) { + ais_abort_msg->rMsgHdr.eMsgId = + MID_OID_AIS_FSM_JOIN_REQ; + ais_abort_msg->ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_DISASSOCIATED; + ais_abort_msg->fgDelayIndication = FALSE; + + DBGLOG(AIS, INFO, + "Disconnect STA["MACSTR"] type:0x%x\n", + MAC2STR(sta_rec->aucMacAddr), sta_rec->eStaType); + + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *) ais_abort_msg, + MSG_SEND_METHOD_UNBUF); +#define DISCONNECT_STATUS WLAN_STATUS_MEDIA_DISCONNECT + /* indicate for disconnection */ + if (kalGetMediaStateIndicated(glue_info) == + PARAM_MEDIA_STATE_CONNECTED) { + kalIndicateStatusAndComplete(glue_info, + DISCONNECT_STATUS, + NULL, + 0); + } +#undef DISCONNECT_STATUS + } + break; + case STA_TYPE_LEGACY_CLIENT: + case STA_TYPE_P2P_GC: + case STA_TYPE_P2P_GO: + p2p_abot_msg = + (struct MSG_P2P_CONNECTION_ABORT *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_P2P_CONNECTION_ABORT)); + + if (p2p_abot_msg) { + p2p_bss_info = + GET_BSS_INFO_BY_INDEX(prAdapter, + sta_rec->ucBssIndex); + role_idx = p2p_bss_info->u4PrivateData; + p2p_abot_msg->rMsgHdr.eMsgId = + MID_MNY_P2P_CONNECTION_ABORT; + COPY_MAC_ADDR(p2p_abot_msg->aucTargetID, + sta_rec->aucMacAddr); + + p2p_abot_msg->u2ReasonCode = REASON_CODE_UNSPECIFIED; + p2p_abot_msg->ucRoleIdx = role_idx; + p2p_abot_msg->fgSendDeauth = FALSE; + + DBGLOG(P2P, INFO, + "Disconnect STA["MACSTR"] type:0x%x\n", + MAC2STR(sta_rec->aucMacAddr), sta_rec->eStaType); + + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *)p2p_abot_msg, + MSG_SEND_METHOD_UNBUF); + } + break; + default: + break; + } +} + +uint32_t wlanData2RateInMs(uint32_t data, uint32_t interval) +{ + /* interval in millisecond + * TODO : 32/64 bits overflow problem + * + * Max $data in 32bits system is 2^12 * 2^20 = 4096M + * Consider this basic Data2Rate formula : data*MSEC_PER_SEC/interval. + * We should reserve 10-bits for multiplication to avoid data overflow, + * and the formula becomes 4M * MSEC_PER_SEC + * If $data is over 4M, the result would be overflow in this case. + * + * Calculation optimized to avoid data overflow + */ + uint32_t rate; + + if (interval == MSEC_PER_SEC) + rate = data; + else if (data > interval) + rate = (data / interval) * MSEC_PER_SEC; + else + rate = (data * MSEC_PER_SEC) / interval; + return rate; +} + +#if CFG_RCPI_COMPENSATION +void wlanLoadEfuseRxFELoss(struct ADAPTER *prAdapter) +{ + uint32_t u4Efuse_addr = 0, u4Index; + uint8_t ucGroup, ucAnt; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + struct PARAM_CUSTOM_ACCESS_EFUSE *prAccessEfuseInfo = NULL; + + prGlueInfo = prAdapter->prGlueInfo; + + + /* allocate memory for Access Efuse Info */ + prAccessEfuseInfo = (struct PARAM_CUSTOM_ACCESS_EFUSE *) + kalMemAlloc(sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), + VIR_MEM_TYPE); + if (prAccessEfuseInfo == NULL) + goto label_exit; + + kalMemZero(prAccessEfuseInfo, sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + + for (ucAnt = 0; ucAnt < MAX_ANTENNA_NUM; ucAnt++) { + for (ucGroup = 0; ucGroup < FELOSS_CH_GROUP_NUM; ucGroup++) { + u4Efuse_addr = FELossOffset[ucAnt][ucGroup]; + prAccessEfuseInfo->u4Address = + (u4Efuse_addr / EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + u4Index = u4Efuse_addr % EFUSE_BLOCK_SIZE; + + if (u4Index == 0) { + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + prAccessEfuseInfo, sizeof( + struct PARAM_CUSTOM_ACCESS_EFUSE), + TRUE, TRUE, TRUE, &u4BufLen); + } + + RxFELoss[ucAnt][ucGroup] = + (prAdapter->aucEepromVaule[u4Index] & RX_FELOSS_MASK) + >> RX_FELOSS_OFFSET; + + DBGLOG(REQ, LOUD, "Ant[%d] Gruoup[%d] FEloss[%d]", + ucAnt, ucGroup, RxFELoss[ucAnt][ucGroup]); + } + } +label_exit: + if (prAccessEfuseInfo != NULL) + kalMemFree(prAccessEfuseInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); +} + +void wlanLoadBufferbinRxFELoss(struct ADAPTER *prAdapter) +{ + uint32_t u4Efuse_addr = 0; + uint8_t ucGroup, ucAnt; + + for (ucGroup = 0; ucGroup < FELOSS_CH_GROUP_NUM; ucGroup++) { + for (ucAnt = 0; ucAnt < MAX_ANTENNA_NUM; ucAnt++) { + u4Efuse_addr = FELossOffset[ucAnt][ucGroup]; + RxFELoss[ucAnt][ucGroup] = + (uacEEPROMImage[u4Efuse_addr] & RX_FELOSS_MASK) + >> RX_FELOSS_OFFSET; + DBGLOG(REQ, LOUD, "Ant[%d] Gruoup[%d] FEloss[%d]", + ucAnt, ucGroup, RxFELoss[ucAnt][ucGroup]); + } + } +} + +void wlanUpdateRxFELoss(IN struct SW_RFB *prSwRfb) +{ + struct HW_MAC_RX_DESC *prRxStatus; + struct HW_MAC_RX_STS_GROUP_3 *prRxStatusGroup3; + uint8_t ucChanNum, ucGroupIdx = 0; + uint8_t ucRcpi0, ucRcpi1; + uint8_t ucRxFELoss0, ucRxFELoss1; + + prRxStatus = prSwRfb->prRxStatus; + prRxStatusGroup3 = prSwRfb->prRxStatusGroup3; + ucChanNum = HAL_RX_STATUS_GET_CHNL_NUM(prRxStatus); + + /* Check channel group */ + if (HAL_RX_STATUS_GET_RF_BAND(prRxStatus) == BAND_2G4) { + ucGroupIdx = 0; + } else { + /* cyclic ch group process for high ch in group 0 */ + if (ucChanNum > A_BAND_FELOSS_BOUND_2) + ucGroupIdx = 1; + else if (ucChanNum > A_BAND_FELOSS_BOUND_1) + ucGroupIdx = 3; /* BOUND_2 ~ BOUND_1 */ + else if (ucChanNum > A_BAND_FELOSS_BOUND_0) + ucGroupIdx = 2; /* BOUND_1 ~ BOUND_0 */ + else + ucGroupIdx = 1; /* BOUND_0 ~ */ + } + ucRxFELoss0 = RxFELoss[ANTENNA_WF0][ucGroupIdx]; + ucRxFELoss1 = RxFELoss[ANTENNA_WF1][ucGroupIdx]; + + DBGLOG(REQ, LOUD, + "ucChanNum = %d, Group=%d ucRxFELoss0 = %d ucRxFELoss1 = %d\n", + ucChanNum, ucGroupIdx, ucRxFELoss0, ucRxFELoss1); + + /* Do the compensation */ + ucRcpi0 = HAL_RX_STATUS_GET_RCPI0(prRxStatusGroup3); + if (ucRcpi0 < RCPI_MEASUREMENT_NOT_AVAILABLE) + HAL_RX_STATUS_SET_RCPI0(prRxStatusGroup3, + (ucRcpi0 + ucRxFELoss0)); + + ucRcpi1 = HAL_RX_STATUS_GET_RCPI1(prRxStatusGroup3); + if (ucRcpi1 < RCPI_MEASUREMENT_NOT_AVAILABLE) + HAL_RX_STATUS_SET_RCPI1(prRxStatusGroup3, + (ucRcpi1 + ucRxFELoss1)); +} + +uint8_t wlanGetCurrChRxFELoss(struct ADAPTER *prAdapter, + uint8_t ucStaIdx, uint8_t ucAnt) +{ + uint8_t ucChanNum = 0, ucGroupIdx = 0, ucRxFELoss = 0; + struct STA_RECORD *prStaRec; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaIdx); + + if (prStaRec == NULL) + return ucRxFELoss; + + if (IS_STA_IN_AIS(prStaRec)) { + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == + PARAM_MEDIA_STATE_CONNECTED) + ucChanNum = prAdapter->prAisBssInfo->ucPrimaryChannel; + } else if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { + ucChanNum = prAdapter->rWifiVar.ucApChannel; + } else { + DBGLOG(REQ, WARN, "Cannot Get Channel\n"); + } + + if (ucChanNum <= HW_CHNL_NUM_MAX_2G4) { + ucGroupIdx = 0; + } else { + /* cyclic ch group process for high ch in group 0 */ + if (ucChanNum > A_BAND_FELOSS_BOUND_2) + ucGroupIdx = 1; + else if (ucChanNum > A_BAND_FELOSS_BOUND_1) + ucGroupIdx = 3; /* BOUND_2 ~ BOUND_1 */ + else if (ucChanNum > A_BAND_FELOSS_BOUND_0) + ucGroupIdx = 2; /* BOUND_1 ~ BOUND_0 */ + else + ucGroupIdx = 1; /* BOUND_0 ~ */ + } + ucRxFELoss = RxFELoss[ucAnt][ucGroupIdx]; + + return ucRxFELoss; +} +#endif /* CFG_RCPI_COMPENSATION */ +#if CFG_SUPPORT_HW_1T2R +void wlanLoadEfuse1T2R(struct ADAPTER *prAdapter) +{ + uint32_t u4Efuse_addr = 0, u4Index; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + struct PARAM_CUSTOM_ACCESS_EFUSE *prAccessEfuseInfo = NULL; + + prGlueInfo = prAdapter->prGlueInfo; + + + /* allocate memory for Access Efuse Info */ + prAccessEfuseInfo = (struct PARAM_CUSTOM_ACCESS_EFUSE *) + kalMemAlloc(sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), + VIR_MEM_TYPE); + if (prAccessEfuseInfo == NULL) + goto label_exit; + + kalMemZero(prAccessEfuseInfo, sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + u4Efuse_addr = EFUSE_1T2R_ADDR; + prAccessEfuseInfo->u4Address = + (u4Efuse_addr / EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + u4Index = u4Efuse_addr % EFUSE_BLOCK_SIZE; + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + prAccessEfuseInfo, sizeof( + struct PARAM_CUSTOM_ACCESS_EFUSE), + TRUE, TRUE, TRUE, &u4BufLen); + if (rStatus == WLAN_STATUS_SUCCESS) { + prAdapter->fgIsHW1T2R = + ((prAdapter->aucEepromVaule[u4Index] + >> EFUSE_1T2R_OFFSET) & 0x1); + } else + prAdapter->fgIsHW1T2R = FALSE; + DBGLOG(REQ, INFO, + "%s IsHW1T2R = %d\n", + __func__, prAdapter->fgIsHW1T2R); + +label_exit: + if (prAccessEfuseInfo != NULL) + kalMemFree(prAccessEfuseInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); +} +void wlanLoadBufferbin1T2R(struct ADAPTER *prAdapter) +{ + prAdapter->fgIsHW1T2R = + ((uacEEPROMImage[EFUSE_1T2R_ADDR] + >> EFUSE_1T2R_OFFSET) & 0x1); + DBGLOG(REQ, INFO, + "%s IsHW1T2R = %d\n", + __func__, prAdapter->fgIsHW1T2R); +} +#endif + +#if CFG_SUPPORT_ADVANCE_CONTROL +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to set g_fgKeepFullPwr flag in firmware +* +* \param[IN] prAdapter Pointer to the Adapter structure. +* \param[IN] fgEnable Boolean of enable +* +* \return WLAN_STATUS_SUCCESS +* \return WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +uint32_t wlanKeepFullPwr(struct ADAPTER *prAdapter, uint8_t fgEnable) +{ + + struct CMD_KEEP_FULL_PWR rCmdKeepFullPwr; + + ASSERT(prAdapter); + + rCmdKeepFullPwr.ucEnable = fgEnable; + DBGLOG(HAL, STATE, "KeepFullPwr: %d\n", rCmdKeepFullPwr.ucEnable); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_KEEP_FULL_PWR, + TRUE, + FALSE, + FALSE, NULL, NULL, + sizeof(struct CMD_KEEP_FULL_PWR), + (uint8_t *)&rCmdKeepFullPwr, NULL, 0); +} +#endif + +#if CFG_SUPPORT_GET_MCS_INFO +void wlanRxMcsInfoMonitor(struct ADAPTER *prAdapter, + unsigned long ulParamPtr) +{ + static uint8_t ucSmapleCnt; + uint8_t ucStaIdx = 0; + struct STA_RECORD *prStaRec; + + if (prAdapter->prAisBssInfo->prStaRecOfAP == NULL) + goto out; + + ucStaIdx = prAdapter->prAisBssInfo->prStaRecOfAP->ucIndex; + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaIdx); + + if (!prStaRec) + goto out; + + if (prStaRec->fgIsValid && prStaRec->fgIsInUse) { + prStaRec->au4RxV0[ucSmapleCnt] = prStaRec->u4RxVector0; + prStaRec->au4RxV1[ucSmapleCnt] = prStaRec->u4RxVector1; + + ucSmapleCnt = (ucSmapleCnt + 1) % MCS_INFO_SAMPLE_CNT; + } + +out: + cnmTimerStartTimer(prAdapter, &prAdapter->rRxMcsInfoTimer, + MCS_INFO_SAMPLE_PERIOD); +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/common/wlan_oid.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/common/wlan_oid.c new file mode 100644 index 0000000000000..51a225618e89a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/common/wlan_oid.c @@ -0,0 +1,17391 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/common + * /wlan_oid.c#11 + */ + +/*! \file wlanoid.c + * \brief This file contains the WLAN OID processing routines of Windows + * 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" +#include "mgmt/rsn.h" +#include "gl_wext.h" +#include "debug.h" +#include + +/****************************************************************************** + * C O N S T A N T S + ****************************************************************************** + */ + +/****************************************************************************** + * D A T A T Y P E S + ****************************************************************************** + */ + +/****************************************************************************** + * P U B L I C D A T A + ****************************************************************************** + */ +struct PARAM_CUSTOM_KEY_CFG_STRUCT g_rDefaulteSetting[] = { + /*format : + *: {"firmware config parameter", "firmware config value"} + */ + {"AdapScan", "0x0"} +}; + + +/****************************************************************************** + * P R I V A T E D A T A + ****************************************************************************** + */ + +/****************************************************************************** + * M A C R O S + ****************************************************************************** + */ + +/****************************************************************************** + * F U N C T I O N D E C L A R A T I O N S + ****************************************************************************** + */ +#if DBG && 0 +static void SetRCID(u_int8_t fgOneTb3, u_int8_t *fgRCID); +#endif + +#if CFG_SLT_SUPPORT +static void SetTestChannel(uint8_t *pucPrimaryChannel); +#endif + +/****************************************************************************** + * F U N C T I O N S + ****************************************************************************** + */ +static void setApUapsdEnable(struct ADAPTER *prAdapter, + u_int8_t enable) +{ + struct PARAM_CUSTOM_UAPSD_PARAM_STRUCT rUapsdParams; + uint32_t u4SetInfoLen = 0; + uint8_t ucBssIdx; + + /* FIX ME: Add p2p role index selection */ + if (p2pFuncRoleToBssIdx( + prAdapter, 0, &ucBssIdx) != WLAN_STATUS_SUCCESS) + return; + + DBGLOG(OID, INFO, "setApUapsdEnable: %d, ucBssIdx: %d\n", + enable, ucBssIdx); + + rUapsdParams.ucBssIdx = ucBssIdx; + + if (enable) { + prAdapter->rWifiVar.ucApUapsd = TRUE; + rUapsdParams.fgEnAPSD = 1; + rUapsdParams.fgEnAPSD_AcBe = 1; + rUapsdParams.fgEnAPSD_AcBk = 1; + rUapsdParams.fgEnAPSD_AcVi = 1; + rUapsdParams.fgEnAPSD_AcVo = 1; + /* default: 0, do not limit delivery pkt number */ + rUapsdParams.ucMaxSpLen = 0; + } else { + prAdapter->rWifiVar.ucApUapsd = FALSE; + rUapsdParams.fgEnAPSD = 0; + rUapsdParams.fgEnAPSD_AcBe = 0; + rUapsdParams.fgEnAPSD_AcBk = 0; + rUapsdParams.fgEnAPSD_AcVi = 0; + rUapsdParams.fgEnAPSD_AcVo = 0; + /* default: 0, do not limit delivery pkt number */ + rUapsdParams.ucMaxSpLen = 0; + } + wlanoidSetUApsdParam(prAdapter, + &rUapsdParams, + sizeof(struct PARAM_CUSTOM_UAPSD_PARAM_STRUCT), + &u4SetInfoLen); +} + +#if CFG_ENABLE_STATISTICS_BUFFERING +static u_int8_t IsBufferedStatisticsUsable( + struct ADAPTER *prAdapter) +{ + ASSERT(prAdapter); + + if (prAdapter->fgIsStatValid == TRUE && + (kalGetTimeTick() - prAdapter->rStatUpdateTime) <= + CFG_STATISTICS_VALID_CYCLE) + return TRUE; + else + return FALSE; +} +#endif + +#if DBG && 0 +static void SetRCID(u_int8_t fgOneTb3, u_int8_t *fgRCID) +{ + if (fgOneTb3) + *fgRCID = 0; + else + *fgRCID = 1; +} +#endif + +#if CFG_SLT_SUPPORT +static void SetTestChannel(uint8_t *pucPrimaryChannel) +{ + if (*pucPrimaryChannel < 5) + *pucPrimaryChannel = 8; + else if (*pucPrimaryChannel > 10) + *pucPrimaryChannel = 3; +} +#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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryNetworkTypesSupported(IN struct ADAPTER + *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + uint32_t u4NumItem = 0; + enum ENUM_PARAM_NETWORK_TYPE + eSupportedNetworks[PARAM_NETWORK_TYPE_NUM]; + struct PARAM_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 = + (uint32_t) OFFSET_OF(struct PARAM_NETWORK_TYPE_LIST, + eNetworkType) + + (u4NumItem * sizeof(enum ENUM_PARAM_NETWORK_TYPE)); + + if (u4QueryBufferLen < *pu4QueryInfoLen) + return WLAN_STATUS_INVALID_LENGTH; + + prSupported = (struct PARAM_NETWORK_TYPE_LIST *) + pvQueryBuffer; + prSupported->NumberOfItems = u4NumItem; + kalMemCopy(prSupported->eNetworkType, eSupportedNetworks, + u4NumItem * sizeof(enum ENUM_PARAM_NETWORK_TYPE)); + + DBGLOG(REQ, TRACE, "NDIS supported network type list: %u\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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryNetworkTypeInUse(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + /* TODO: need to check the OID handler content again!! */ + + enum ENUM_PARAM_NETWORK_TYPE rCurrentNetworkTypeInUse = + PARAM_NETWORK_TYPE_OFDM24; + + DEBUGFUNC("wlanoidQueryNetworkTypeInUse"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(enum + ENUM_PARAM_NETWORK_TYPE)) { + *pu4QueryInfoLen = sizeof(enum ENUM_PARAM_NETWORK_TYPE); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == + PARAM_MEDIA_STATE_CONNECTED) + rCurrentNetworkTypeInUse = (enum ENUM_PARAM_NETWORK_TYPE) ( + prAdapter->rWlanInfo.ucNetworkType); + else + rCurrentNetworkTypeInUse = (enum ENUM_PARAM_NETWORK_TYPE) ( + prAdapter->rWlanInfo.ucNetworkTypeInUse); + + *(enum ENUM_PARAM_NETWORK_TYPE *) pvQueryBuffer = + rCurrentNetworkTypeInUse; + *pu4QueryInfoLen = sizeof(enum ENUM_PARAM_NETWORK_TYPE); + + 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetNetworkTypeInUse(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + /* TODO: need to check the OID handler content again!! */ + + enum ENUM_PARAM_NETWORK_TYPE eNewNetworkType; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidSetNetworkTypeInUse"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(enum ENUM_PARAM_NETWORK_TYPE)) { + *pu4SetInfoLen = sizeof(enum ENUM_PARAM_NETWORK_TYPE); + return WLAN_STATUS_INVALID_LENGTH; + } + + eNewNetworkType = *(enum ENUM_PARAM_NETWORK_TYPE *) + pvSetBuffer; + *pu4SetInfoLen = sizeof(enum ENUM_PARAM_NETWORK_TYPE); + + DBGLOG(REQ, INFO, "New network type: %d mode\n", + eNewNetworkType); + + switch (eNewNetworkType) { + + case PARAM_NETWORK_TYPE_DS: + prAdapter->rWlanInfo.ucNetworkTypeInUse = + (uint8_t) PARAM_NETWORK_TYPE_DS; + break; + + case PARAM_NETWORK_TYPE_OFDM5: + prAdapter->rWlanInfo.ucNetworkTypeInUse = + (uint8_t) PARAM_NETWORK_TYPE_OFDM5; + break; + + case PARAM_NETWORK_TYPE_OFDM24: + prAdapter->rWlanInfo.ucNetworkTypeInUse = + (uint8_t) PARAM_NETWORK_TYPE_OFDM24; + break; + + case PARAM_NETWORK_TYPE_AUTOMODE: + prAdapter->rWlanInfo.ucNetworkTypeInUse = + (uint8_t) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryBssid(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + uint32_t 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) { + uint8_t aucTemp[PARAM_MAC_ADDR_LEN]; /*!< 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryBssidList(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + struct GLUE_INFO *prGlueInfo; + uint32_t i, u4BssidListExLen; + struct PARAM_BSSID_LIST_EX *prList; + struct PARAM_BSSID_EX *prBssidEx; + uint8_t *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(struct PARAM_BSSID_LIST_EX); + + *pu4QueryInfoLen = u4BssidListExLen; + + if (u4QueryBufferLen < *pu4QueryInfoLen) + return WLAN_STATUS_INVALID_LENGTH; + + /* Clear the buffer */ + kalMemZero(pvQueryBuffer, u4BssidListExLen); + + prList = (struct PARAM_BSSID_LIST_EX *) pvQueryBuffer; + cp = (uint8_t *) &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 = (struct PARAM_BSSID_EX *) cp; + + /* copy structure */ + kalMemCopy(prBssidEx, + &(prAdapter->rWlanInfo.arScanResult[i]), + OFFSET_OF(struct PARAM_BSSID_EX, 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetBssidListScan(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct PARAM_SSID *prSsid; + struct PARAM_SSID rSsid; + + DEBUGFUNC("wlanoidSetBssidListScan()"); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in set BSSID list scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (prAdapter->fgTestMode) { + DBGLOG(OID, WARN, "didn't support Scan in test mode\n"); + return WLAN_STATUS_FAILURE; + } + + ASSERT(pu4SetInfoLen); + *pu4SetInfoLen = 0; + + if (prAdapter->fgIsRadioOff) { + DBGLOG(OID, WARN, + "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + 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 + return WLAN_STATUS_FAILURE; + } else + return WLAN_STATUS_FAILURE; + } else +#endif + { + if (prAdapter->fgEnOnlineScan == TRUE) + aisFsmScanRequest(prAdapter, prSsid, NULL, 0); + else if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != + PARAM_MEDIA_STATE_CONNECTED) + aisFsmScanRequest(prAdapter, prSsid, NULL, 0); + else + return WLAN_STATUS_FAILURE; + } + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetBssidListScanExt(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct PARAM_SCAN_REQUEST_EXT *prScanRequest; + struct PARAM_SSID *prSsid; + uint8_t *pucIe; + uint32_t u4IeLength; + + DEBUGFUNC("wlanoidSetBssidListScanExt()"); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in set BSSID list scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (prAdapter->fgTestMode) { + DBGLOG(OID, WARN, "didn't support Scan in test mode\n"); + return WLAN_STATUS_FAILURE; + } + + ASSERT(pu4SetInfoLen); + *pu4SetInfoLen = 0; + + if (u4SetBufferLen != sizeof(struct PARAM_SCAN_REQUEST_EXT)) + return WLAN_STATUS_INVALID_LENGTH; + + if (prAdapter->fgIsRadioOff) { + DBGLOG(OID, WARN, + "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + DBGLOG(OID, TRACE, "ScanEX\n"); + if (pvSetBuffer != NULL && u4SetBufferLen != 0) { + prScanRequest = (struct PARAM_SCAN_REQUEST_EXT *) + 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 + return WLAN_STATUS_FAILURE; + } else + return WLAN_STATUS_FAILURE; + } else +#endif + { + if (prAdapter->fgEnOnlineScan == TRUE) + aisFsmScanRequest(prAdapter, prSsid, pucIe, u4IeLength); + else if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != + PARAM_MEDIA_STATE_CONNECTED) + aisFsmScanRequest(prAdapter, prSsid, pucIe, u4IeLength); + else + return WLAN_STATUS_FAILURE; + } + + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetBssidListScanWithIE */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to request the driver to perform + * scanning with attaching information elements(IEs) specified from user + * space and multiple SSID + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetBssidListScanAdv(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct PARAM_SCAN_REQUEST_ADV *prScanRequest; + + DEBUGFUNC("wlanoidSetBssidListScanAdv()"); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in set BSSID list scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (prAdapter->fgTestMode) { + DBGLOG(OID, WARN, "didn't support Scan in test mode\n"); + return WLAN_STATUS_FAILURE; + } + + ASSERT(pu4SetInfoLen); + *pu4SetInfoLen = 0; + + if (u4SetBufferLen != sizeof(struct PARAM_SCAN_REQUEST_ADV)) + return WLAN_STATUS_INVALID_LENGTH; + else if (pvSetBuffer == NULL) + return WLAN_STATUS_INVALID_DATA; + + if (prAdapter->fgIsRadioOff) { + DBGLOG(OID, WARN, + "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + prScanRequest = (struct PARAM_SCAN_REQUEST_ADV *) + pvSetBuffer; + +#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) { + aisFsmScanRequestAdv(prAdapter, prScanRequest); + } else + return WLAN_STATUS_FAILURE; + } else + return WLAN_STATUS_FAILURE; + } else +#endif + { + if (prAdapter->fgEnOnlineScan == TRUE) { + aisFsmScanRequestAdv(prAdapter, prScanRequest); + } else if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) + != PARAM_MEDIA_STATE_CONNECTED) { + aisFsmScanRequestAdv(prAdapter, prScanRequest); + } else + return WLAN_STATUS_FAILURE; + } + cnmTimerStartTimer(prAdapter, + &prAdapter->rWifiVar.rAisFsmInfo.rScanDoneTimer, + SEC_TO_MSEC(AIS_SCN_DONE_TIMEOUT_SEC)); + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetBssidListScanAdv */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetBssid(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct GLUE_INFO *prGlueInfo; + uint8_t *pAddr; + uint32_t i; + int32_t i4Idx = -1; + struct MSG_AIS_ABORT *prAisAbortMsg; + uint8_t ucReasonOfDisconnect; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = MAC_ADDR_LEN; + if (u4SetBufferLen != MAC_ADDR_LEN) { + *pu4SetInfoLen = MAC_ADDR_LEN; + return WLAN_STATUS_INVALID_LENGTH; + } else if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(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 = (uint8_t *) pvSetBuffer; + + /* re-association check */ + if (kalGetMediaStateIndicated(prGlueInfo) == + PARAM_MEDIA_STATE_CONNECTED) { + if (EQUAL_MAC_ADDR( + prAdapter->rWlanInfo.rCurrBssId.arMacAddress, pAddr)) { + kalSetMediaStateIndicated(prGlueInfo, + PARAM_MEDIA_STATE_TO_BE_INDICATED); + ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_REASSOCIATION; + } else { + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_NEW_CONNECTION; + } + } else { + ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_NEW_CONNECTION; + } + + /* check if any scanned result matchs with the BSSID */ + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + if (EQUAL_MAC_ADDR( + prAdapter->rWlanInfo.arScanResult[i].arMacAddress, pAddr)) { + i4Idx = (int32_t) 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 = (struct MSG_AIS_ABORT *) cnmMemAlloc( + prAdapter, RAM_TYPE_MSG, sizeof(struct MSG_AIS_ABORT)); + if (!prAisAbortMsg) { + DBGLOG(REQ, ERROR, "Fail in allocating AisAbortMsg.\n"); + return WLAN_STATUS_FAILURE; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; + prAisAbortMsg->ucReasonOfDisconnect = ucReasonOfDisconnect; + + /* Update the information to CONNECTION_SETTINGS_T */ + prAdapter->rWifiVar.rConnSettings.ucSSIDLen = 0; + prAdapter->rWifiVar.rConnSettings.aucSSID[0] = '\0'; + COPY_MAC_ADDR(prAdapter->rWifiVar.rConnSettings.aucBSSID, + pAddr); + + if (EQUAL_MAC_ADDR( + prAdapter->rWlanInfo.rCurrBssId.arMacAddress, pAddr)) + prAisAbortMsg->fgDelayIndication = TRUE; + else + prAisAbortMsg->fgDelayIndication = FALSE; + +#if CFG_DISCONN_DEBUG_FEATURE + /* used to disconnect debug capability */ + g_rDisconnInfoTemp.ucTrigger = DISCONNECT_TRIGGER_ACTIVE; +#endif + + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetSsid(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct GLUE_INFO *prGlueInfo; + struct PARAM_SSID *pParamSsid; + uint32_t i; + int32_t i4Idx = -1, i4MaxRSSI = INT_MIN; + struct MSG_AIS_ABORT *prAisAbortMsg; + u_int8_t 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(struct PARAM_SSID) + || u4SetBufferLen > sizeof(struct PARAM_SSID)) + 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 = (struct PARAM_SSID *) 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++) { + uint8_t *aucSsid = + prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid; + uint8_t ucSsidLength = (uint8_t) + prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen; + int32_t i4RSSI = prAdapter->rWlanInfo.arScanResult[i].rRssi; + + if (EQUAL_SSID(aucSsid, ucSsidLength, pParamSsid->aucSsid, + pParamSsid->u4SsidLen) && + i4RSSI >= i4MaxRSSI) { + i4Idx = (int32_t) 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 (!((pParamSsid->aucSsid[i] > 0) + && (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 = (struct MSG_AIS_ABORT *) cnmMemAlloc( + prAdapter, RAM_TYPE_MSG, sizeof(struct MSG_AIS_ABORT)); + if (!prAisAbortMsg) { + DBGLOG(REQ, ERROR, "Fail in allocating AisAbortMsg.\n"); + return WLAN_STATUS_FAILURE; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; + prAisAbortMsg->ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_NEW_CONNECTION; + COPY_SSID(prAdapter->rWifiVar.rConnSettings.aucSSID, + prAdapter->rWifiVar.rConnSettings.ucSSIDLen, + pParamSsid->aucSsid, (uint8_t) pParamSsid->u4SsidLen); + + if (EQUAL_SSID( + prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, + prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen, + pParamSsid->aucSsid, pParamSsid->u4SsidLen)) { + prAisAbortMsg->fgDelayIndication = TRUE; + } else { + /* Update the information to CONNECTION_SETTINGS_T */ + prAisAbortMsg->fgDelayIndication = FALSE; + } + DBGLOG(SCN, INFO, "SSID %s\n", + prAdapter->rWifiVar.rConnSettings.aucSSID); + +#if CFG_DISCONN_DEBUG_FEATURE + /* used to disconnect debug capability */ + g_rDisconnInfoTemp.ucTrigger = DISCONNECT_TRIGGER_ACTIVE; +#endif + + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prAisAbortMsg, MSG_SEND_METHOD_BUF); + + return WLAN_STATUS_SUCCESS; + +} /* end of wlanoidSetSsid() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine will initiate the join procedure to attempt + * to associate with the new BSS, base on given SSID, BSSID, and + * freqency. + * If the target connecting BSS is in the same ESS as current connected + * BSS, roaming will be performed. + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetConnect(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct GLUE_INFO *prGlueInfo; + struct PARAM_CONNECT *pParamConn; + struct CONNECTION_SETTINGS *prConnSettings; + uint32_t i; + struct MSG_AIS_ABORT *prAisAbortMsg; + u_int8_t fgIsValidSsid = TRUE; + u_int8_t fgEqualSsid = FALSE; + u_int8_t fgEqualBssid = FALSE; + const uint8_t aucZeroMacAddr[] = NULL_MAC_ADDR; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* MSDN: + * Powering on the radio if the radio is powered off through a setting + * of OID_802_11_DISASSOCIATE + */ + if (prAdapter->fgIsRadioOff == TRUE) + prAdapter->fgIsRadioOff = FALSE; + + if (u4SetBufferLen != sizeof(struct PARAM_CONNECT)) + 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; + } + prAisAbortMsg = (struct MSG_AIS_ABORT *) cnmMemAlloc( + prAdapter, RAM_TYPE_MSG, sizeof(struct MSG_AIS_ABORT)); + if (!prAisAbortMsg) { + DBGLOG(REQ, ERROR, "Fail in allocating AisAbortMsg.\n"); + return WLAN_STATUS_FAILURE; + } + prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; + + pParamConn = (struct PARAM_CONNECT *) pvSetBuffer; + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + + if (pParamConn->u4SsidLen > 32) { + cnmMemFree(prAdapter, prAisAbortMsg); + DBGLOG(OID, WARN, "SsidLen [%d] is invalid!\n", + pParamConn->u4SsidLen); + return WLAN_STATUS_INVALID_LENGTH; + } else if (!pParamConn->pucBssid && !pParamConn->pucSsid) { + cnmMemFree(prAdapter, prAisAbortMsg); + DBGLOG(OID, WARN, "Bssid or ssid is invalid!\n"); + return WLAN_STATUS_INVALID_LENGTH; + } + + prGlueInfo = prAdapter->prGlueInfo; + kalMemZero(prConnSettings->aucSSID, + sizeof(prConnSettings->aucSSID)); + prConnSettings->ucSSIDLen = 0; + kalMemZero(prConnSettings->aucBSSID, + sizeof(prConnSettings->aucBSSID)); + kalMemZero(prConnSettings->aucBSSIDHint, + sizeof(prConnSettings->aucBSSIDHint)); + prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_ANY; + prConnSettings->fgIsConnByBssidIssued = FALSE; + + if (pParamConn->pucSsid) { + prConnSettings->eConnectionPolicy = + CONNECT_BY_SSID_BEST_RSSI; + prConnSettings->ucSSIDLen = pParamConn->u4SsidLen; + COPY_SSID(prConnSettings->aucSSID, + prConnSettings->ucSSIDLen, pParamConn->pucSsid, + (uint8_t) pParamConn->u4SsidLen); + if (EQUAL_SSID( + prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, + prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen, + pParamConn->pucSsid, pParamConn->u4SsidLen)) + fgEqualSsid = TRUE; + } + if (pParamConn->pucBssid) { + if (!EQUAL_MAC_ADDR(aucZeroMacAddr, pParamConn->pucBssid) + && IS_UCAST_MAC_ADDR(pParamConn->pucBssid)) { + prConnSettings->eConnectionPolicy = CONNECT_BY_BSSID; + prConnSettings->fgIsConnByBssidIssued = TRUE; + COPY_MAC_ADDR(prConnSettings->aucBSSID, + pParamConn->pucBssid); + if (EQUAL_MAC_ADDR( + prAdapter->rWlanInfo.rCurrBssId.arMacAddress, + pParamConn->pucBssid)) + fgEqualBssid = TRUE; + } else + DBGLOG(INIT, INFO, "wrong bssid " MACSTR "to connect\n", + MAC2STR(pParamConn->pucBssid)); + } else if (pParamConn->pucBssidHint) { + if (!EQUAL_MAC_ADDR(aucZeroMacAddr, pParamConn->pucBssidHint) + && IS_UCAST_MAC_ADDR(pParamConn->pucBssidHint)) { + prConnSettings->eConnectionPolicy = + CONNECT_BY_BSSID_HINT; + COPY_MAC_ADDR(prConnSettings->aucBSSIDHint, + pParamConn->pucBssidHint); + if (EQUAL_MAC_ADDR( + prAdapter->rWlanInfo.rCurrBssId.arMacAddress, + pParamConn->pucBssidHint)) + fgEqualBssid = TRUE; + } + } else + DBGLOG(INIT, INFO, "No Bssid set\n"); + prConnSettings->u4FreqInKHz = pParamConn->u4CenterFreq; + + /* prepare for CMD_BUILD_CONNECTION & CMD_GET_CONNECTION_STATUS */ + /* re-association check */ + if (kalGetMediaStateIndicated(prGlueInfo) == + PARAM_MEDIA_STATE_CONNECTED) { + if (fgEqualSsid) { + prAisAbortMsg->ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_ROAMING; + if (fgEqualBssid) { + kalSetMediaStateIndicated(prGlueInfo, + PARAM_MEDIA_STATE_TO_BE_INDICATED); + prAisAbortMsg->ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_REASSOCIATION; + } + } else { + DBGLOG(INIT, INFO, "DisBySsid\n"); + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + prAisAbortMsg->ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_NEW_CONNECTION; + } + } else + prAisAbortMsg->ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_NEW_CONNECTION; +#if 0 + /* check if any scanned result matchs with the SSID */ + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + uint8_t *aucSsid = + prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid; + uint8_t ucSsidLength = (uint8_t) + prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen; + int32_t i4RSSI = prAdapter->rWlanInfo.arScanResult[i].rRssi; + + if (EQUAL_SSID(aucSsid, ucSsidLength, pParamConn->pucSsid, + pParamConn->u4SsidLen) && + i4RSSI >= i4MaxRSSI) { + i4Idx = (int32_t) i; + i4MaxRSSI = i4RSSI; + } + if (EQUAL_MAC_ADDR( + prAdapter->rWlanInfo.arScanResult[i].arMacAddress, pAddr)) { + i4Idx = (int32_t) i; + break; + } + } +#endif + /* prepare message to AIS */ + if (prConnSettings->eOPMode == NET_TYPE_IBSS + || prConnSettings->eOPMode == NET_TYPE_DEDICATED_IBSS) { + /* IBSS *//* beacon period */ + prConnSettings->u2BeaconPeriod = + prAdapter->rWlanInfo.u2BeaconPeriod; + prConnSettings->u2AtimWindow = + prAdapter->rWlanInfo.u2AtimWindow; + } + + if (prAdapter->rWifiVar.fgSupportWZCDisassociation) { + if (pParamConn->u4SsidLen == ELEM_MAX_LEN_SSID) { + fgIsValidSsid = FALSE; + + if (pParamConn->pucSsid) { + for (i = 0; i < ELEM_MAX_LEN_SSID; i++) { + if (!((pParamConn->pucSsid[i] > 0) && + (pParamConn->pucSsid[i] <= 0x1F))) { + fgIsValidSsid = TRUE; + break; + } + } + } else { + DBGLOG(INIT, ERROR, + "pParamConn->pucSsid is NULL\n"); + } + } + } + + /* Set Connection Request Issued Flag */ + if (fgIsValidSsid) + prConnSettings->fgIsConnReqIssued = TRUE; + else { + prConnSettings->eReConnectLevel = RECONNECT_LEVEL_USER_SET; + prConnSettings->fgIsConnReqIssued = FALSE; + } + + if (fgEqualSsid || fgEqualBssid) + prAisAbortMsg->fgDelayIndication = TRUE; + else + /* Update the information to CONNECTION_SETTINGS_T */ + prAisAbortMsg->fgDelayIndication = FALSE; + +#if CFG_DISCONN_DEBUG_FEATURE + /* used to disconnect debug capability */ + g_rDisconnInfoTemp.ucTrigger = DISCONNECT_TRIGGER_ACTIVE; +#endif + + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prAisAbortMsg, MSG_SEND_METHOD_BUF); + + DBGLOG(INIT, INFO, "ssid %s, bssid " MACSTR + ", bssid_hint " MACSTR ", conn policy %d, disc reason %d\n", + prConnSettings->aucSSID, MAC2STR(prConnSettings->aucBSSID), + MAC2STR(prConnSettings->aucBSSIDHint), + prConnSettings->eConnectionPolicy, + prAisAbortMsg->ucReasonOfDisconnect); + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetConnect */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQuerySsid(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + struct PARAM_SSID *prAssociatedSsid; + + DEBUGFUNC("wlanoidQuerySsid"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct PARAM_SSID); + + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prAssociatedSsid = (struct PARAM_SSID *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryInfrastructureMode(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryInfrastructureMode"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(enum ENUM_PARAM_OP_MODE); + + if (u4QueryBufferLen < sizeof(enum ENUM_PARAM_OP_MODE)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *(enum ENUM_PARAM_OP_MODE *) 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 (*(enum ENUM_PARAM_OP_MODE *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetInfrastructureMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct GLUE_INFO *prGlueInfo; + enum ENUM_PARAM_OP_MODE eOpMode; + /* P_WLAN_TABLE_T prWlanTable; */ +#if CFG_SUPPORT_802_11W + /* P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; */ +#endif + /* P_BSS_INFO_T prBssInfo; */ + /* UINT_8 i; */ + + DEBUGFUNC("wlanoidSetInfrastructureMode"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prGlueInfo = prAdapter->prGlueInfo; + + if (u4SetBufferLen < sizeof(enum ENUM_PARAM_OP_MODE)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + *pu4SetInfoLen = sizeof(enum ENUM_PARAM_OP_MODE); + + 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 = *(enum ENUM_PARAM_OP_MODE *) 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; + + 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 + +#if 0 /* STA record remove at AIS_ABORT nicUpdateBss and DISCONNECT */ + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) + cnmStaFreeAllStaByNetwork(prAdapter, + prBssInfo->ucBssIndex, 0); + } +#endif + + /* Clean up the Tx key flag */ + if (prAdapter->prAisBssInfo != NULL) { + prAdapter->prAisBssInfo->fgBcDefaultKeyExist = FALSE; + prAdapter->prAisBssInfo->ucBcDefaultKeyIdx = 0xFF; + } + + /* prWlanTable = prAdapter->rWifiVar.arWtbl; */ + /* prWlanTable[prAdapter->prAisBssInfo->ucBMCWlanIndex].ucKeyId = 0; */ + +#if DBG + DBGLOG(RSN, TRACE, "wlanoidSetInfrastructureMode\n"); +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_INFRASTRUCTURE, + TRUE, + FALSE, + g_fgIsOid, + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryAuthMode(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryAuthMode"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(enum ENUM_PARAM_AUTH_MODE); + + if (u4QueryBufferLen < sizeof(enum ENUM_PARAM_AUTH_MODE)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + *(enum ENUM_PARAM_AUTH_MODE *) pvQueryBuffer = + prAdapter->rWifiVar.rConnSettings.eAuthMode; + +#if DBG + switch (*(enum ENUM_PARAM_AUTH_MODE *) 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; + +#if CFG_SUPPORT_CFG80211_AUTH + case AUTH_MODE_WPA2_SAE: + DBGLOG(REQ, INFO, "Current auth mode: SAE\n"); + break; +#endif + + default: + DBGLOG(REQ, INFO, "Current auth mode: %d\n", + *(enum ENUM_PARAM_AUTH_MODE *) pvQueryBuffer); + break; + } +#endif + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryAuthMode */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set the IEEE 802.11 authentication mode + * to the driver. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. + * \param[in] u4SetBufferLen The length of the set buffer. + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed + * due to invalid length of the set buffer, returns + * the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_DATA + * \retval WLAN_STATUS_INVALID_LENGTH + * \retval WLAN_STATUS_ADAPTER_NOT_READY + * \retval WLAN_STATUS_NOT_ACCEPTED + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetAuthMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct GLUE_INFO *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 ENUM_PARAM_AUTH_MODE); + + if (u4SetBufferLen < sizeof(enum ENUM_PARAM_AUTH_MODE)) + 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 (*(enum ENUM_PARAM_AUTH_MODE *) pvSetBuffer >= + AUTH_MODE_NUM) { + DBGLOG(REQ, TRACE, "Invalid auth mode %d\n", + *(enum ENUM_PARAM_AUTH_MODE *) pvSetBuffer); + return WLAN_STATUS_INVALID_DATA; + } + + switch (*(enum ENUM_PARAM_AUTH_MODE *) pvSetBuffer) { + case AUTH_MODE_WPA: + case AUTH_MODE_WPA_PSK: + case AUTH_MODE_WPA2: + case AUTH_MODE_WPA2_PSK: + case AUTH_MODE_WPA2_FT: + case AUTH_MODE_WPA2_FT_PSK: + /* infrastructure mode only */ + if (prAdapter->rWifiVar.rConnSettings.eOPMode != + NET_TYPE_INFRA) + return WLAN_STATUS_NOT_ACCEPTED; + break; + + case AUTH_MODE_WPA_NONE: + /* ad hoc mode only */ + if (prAdapter->rWifiVar.rConnSettings.eOPMode != + NET_TYPE_IBSS) + return WLAN_STATUS_NOT_ACCEPTED; + break; + + default: + break; + } + + /* Save the new authentication mode. */ + prAdapter->rWifiVar.rConnSettings.eAuthMode = * + (enum ENUM_PARAM_AUTH_MODE *) pvSetBuffer; + +#if 1 /* 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; + +#if CFG_SUPPORT_SAE + case AUTH_MODE_WPA2_SAE: + DBGLOG(RSN, INFO, "New auth mode: SAE\n"); + break; +#endif + + default: + DBGLOG(RSN, TRACE, "New auth mode: unknown (%d)\n", + prAdapter->rWifiVar.rConnSettings.eAuthMode); + } +#endif + +#if 0 + 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 + } +#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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryPrivacyFilter(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryPrivacyFilter"); + + ASSERT(prAdapter); + + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(enum ENUM_PARAM_PRIVACY_FILTER); + + if (u4QueryBufferLen < sizeof(enum + ENUM_PARAM_PRIVACY_FILTER)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + *(enum ENUM_PARAM_PRIVACY_FILTER *) pvQueryBuffer = + prAdapter->rWlanInfo.ePrivacyFilter; + +#if DBG + switch (*(enum ENUM_PARAM_PRIVACY_FILTER *) 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", + *(enum ENUM_PARAM_AUTH_MODE *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetPrivacyFilter(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct GLUE_INFO *prGlueInfo; + + DEBUGFUNC("wlanoidSetPrivacyFilter"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + prGlueInfo = prAdapter->prGlueInfo; + + *pu4SetInfoLen = sizeof(enum ENUM_PARAM_PRIVACY_FILTER); + + if (u4SetBufferLen < sizeof(enum ENUM_PARAM_PRIVACY_FILTER)) + 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 (*(enum ENUM_PARAM_PRIVACY_FILTER *) pvSetBuffer >= + PRIVACY_FILTER_NUM) { + DBGLOG(REQ, TRACE, "Invalid privacy filter %d\n", + *(enum ENUM_PARAM_PRIVACY_FILTER *) pvSetBuffer); + return WLAN_STATUS_INVALID_DATA; + } + + switch (*(enum ENUM_PARAM_PRIVACY_FILTER *) pvSetBuffer) { + default: + break; + } + + /* Save the new authentication mode. */ + prAdapter->rWlanInfo.ePrivacyFilter = + *(enum ENUM_PARAM_PRIVACY_FILTER) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetReloadDefaults(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + enum ENUM_PARAM_NETWORK_TYPE eNetworkType; + uint32_t u4Len; + uint8_t ucCmdSeqNum; + + DEBUGFUNC("wlanoidSetReloadDefaults"); + + ASSERT(prAdapter); + + ASSERT(pu4SetInfoLen); + *pu4SetInfoLen = sizeof(enum ENUM_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 (*(enum ENUM_RELOAD_DEFAULTS *) pvSetBuffer) { + case ENUM_RELOAD_WEP_KEYS: + /* Reload available default WEP keys from the permanent + * storage. + */ + prAdapter->rWifiVar.rConnSettings.eAuthMode = + AUTH_MODE_OPEN; + /* ENUM_ENCRYPTION_DISABLED; */ + prAdapter->rWifiVar.rConnSettings.eEncStatus = + ENUM_ENCRYPTION1_KEY_ABSENT; + { + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + struct WIFI_CMD *prWifiCmd; + struct CMD_802_11_KEY *prCmdKey; + uint8_t aucBCAddr[] = BC_MAC_ADDR; + + prGlueInfo = prAdapter->prGlueInfo; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + (CMD_HDR_SIZE + sizeof(struct 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->u2InfoBufLen = CMD_HDR_SIZE + + sizeof(struct CMD_802_11_KEY); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = g_fgIsOid; + prCmdInfo->ucCID = CMD_ID_ADD_REMOVE_KEY; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = + sizeof(struct PARAM_REMOVE_KEY); + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + + /* Setup WIFI_CMD_T */ + prWifiCmd = + (struct WIFI_CMD *) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prCmdKey = + (struct CMD_802_11_KEY *)(prWifiCmd->aucBuffer); + + kalMemZero((uint8_t *) prCmdKey, + sizeof(struct 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, + (struct QUE_ENTRY *) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; + } + + break; + + default: + DBGLOG(REQ, TRACE, "Invalid reload option %d\n", + *(enum ENUM_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 +uint8_t keyBuffer[sizeof(struct PARAM_KEY) + + 16 /* LEGACY_KEY_MAX_LEN */]; +uint8_t aucBCAddr[] = BC_MAC_ADDR; +#endif +uint32_t +wlanoidSetAddWep(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ +#ifndef LINUX + uint8_t keyBuffer[sizeof(struct PARAM_KEY) + + 16 /* LEGACY_KEY_MAX_LEN */]; + uint8_t aucBCAddr[] = BC_MAC_ADDR; +#endif + struct PARAM_WEP *prNewWepKey; + struct PARAM_KEY *prParamKey = (struct PARAM_KEY *) + keyBuffer; + uint32_t u4KeyId, u4SetLen; + + DEBUGFUNC("wlanoidSetAddWep"); + + ASSERT(prAdapter); + + *pu4SetInfoLen = OFFSET_OF(struct PARAM_WEP, + aucKeyMaterial); + + if (u4SetBufferLen < OFFSET_OF(struct PARAM_WEP, + 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 = (struct PARAM_WEP *) pvSetBuffer; + + /* Verify the total buffer for minimum length. */ + if (u4SetBufferLen < OFFSET_OF(struct PARAM_WEP, + aucKeyMaterial) + prNewWepKey->u4KeyLength) { + DBGLOG(REQ, WARN, + "Invalid total buffer length (%d) than minimum length (%d)\n", + (uint8_t) u4SetBufferLen, + (uint8_t) OFFSET_OF(struct PARAM_WEP, aucKeyMaterial)); + + *pu4SetInfoLen = OFFSET_OF(struct PARAM_WEP, + 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", + (uint8_t) prNewWepKey->u4Length, + (uint8_t) 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", + (uint8_t) 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", + (uint8_t) 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->ucBssIdx = prAdapter->prAisBssInfo->ucBssIndex; + + if (prParamKey->u4KeyLength == WEP_40_LEN) + prParamKey->ucCipher = CIPHER_SUITE_WEP40; + else if (prParamKey->u4KeyLength == WEP_104_LEN) + prParamKey->ucCipher = CIPHER_SUITE_WEP104; + else if (prParamKey->u4KeyLength == WEP_128_LEN) + prParamKey->ucCipher = CIPHER_SUITE_WEP128; + + prParamKey->u4Length = OFFSET_OF( + struct PARAM_KEY, aucKeyMaterial) + prNewWepKey->u4KeyLength; + + wlanoidSetAddKey(prAdapter, (void *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetRemoveWep(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t u4KeyId, u4SetLen; + struct PARAM_REMOVE_KEY rRemoveKey; + uint8_t aucBCAddr[] = BC_MAC_ADDR; + + DEBUGFUNC("wlanoidSetRemoveWep"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + u4KeyId = *(uint32_t *) pvSetBuffer; + + /* Dump PARAM_WEP content. */ + DBGLOG(REQ, INFO, "Set: Dump PARAM_KEY_INDEX content\n"); + DBGLOG(REQ, INFO, "Index : %u\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: %u\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 %u\n", u4KeyId); + return WLAN_STATUS_INVALID_DATA; + } + + rRemoveKey.u4Length = sizeof(struct PARAM_REMOVE_KEY); + rRemoveKey.u4KeyIndex = *(uint32_t *) pvSetBuffer; + + kalMemCopy(rRemoveKey.arBSSID, aucBCAddr, MAC_ADDR_LEN); + + wlanoidSetRemoveKey(prAdapter, (void *)&rRemoveKey, + sizeof(struct PARAM_REMOVE_KEY), &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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetAddKey(IN struct ADAPTER *prAdapter, IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, OUT uint32_t *pu4SetInfoLen) +{ + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + struct WIFI_CMD *prWifiCmd; + struct PARAM_KEY *prNewKey; + struct CMD_802_11_KEY *prCmdKey; + uint8_t ucCmdSeqNum; + struct BSS_INFO *prBssInfo; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecBssInfo; + struct STA_RECORD *prStaRec = NULL; + u_int8_t fgNoHandshakeSec = FALSE; +#if CFG_SUPPORT_TDLS + struct STA_RECORD *prTmpStaRec; +#endif + DEBUGFUNC("wlanoidSetAddKey"); + DBGLOG(REQ, LOUD, "\n"); + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + DBGLOG(RSN, TRACE, "wlanoidSetAddKey\n"); + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(RSN, 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 = (struct PARAM_KEY *) pvSetBuffer; + /* Verify the key structure length. */ + if (prNewKey->u4Length > u4SetBufferLen) { + DBGLOG(RSN, WARN, + "Invalid key structure length (%d) greater than total buffer length (%d)\n", + (uint8_t) prNewKey->u4Length, (uint8_t) u4SetBufferLen); + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_INVALID_LENGTH; + } + /* Verify the key material length for key material buffer */ + if (prNewKey->u4KeyLength > prNewKey->u4Length - + OFFSET_OF(struct PARAM_KEY, aucKeyMaterial)) { + DBGLOG(RSN, WARN, "Invalid key material length (%d)\n", + (uint8_t) 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(RSN, TRACE, "Set: Dump PARAM_KEY content, Len: 0x%08x, BSSID: " + MACSTR + ", KeyIdx: 0x%08x, KeyLen: 0x%08x, Cipher: %d, Material:\n", + prNewKey->u4Length, MAC2STR(prNewKey->arBSSID), + prNewKey->u4KeyIndex, prNewKey->u4KeyLength, + prNewKey->ucCipher); + DBGLOG_MEM8(RSN, TRACE, prNewKey->aucKeyMaterial, + prNewKey->u4KeyLength); + DBGLOG(RSN, TRACE, "Key RSC:\n"); + DBGLOG_MEM8(RSN, TRACE, &prNewKey->rKeyRSC, sizeof(uint64_t)); + + prGlueInfo = prAdapter->prGlueInfo; + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prNewKey->ucBssIdx); + if (!prBssInfo) { + DBGLOG(REQ, INFO, "BSS Info not exist !!\n"); + return WLAN_STATUS_SUCCESS; + } + /* Tx Rx KeyType addr + * STA, GC: + * case1: 1 1 0 BC addr (no sta record of AP at this moment) WEP, + * notice: tx at default key setting WEP key now save to BSS_INFO + * case2: 0 1 0 BSSID (sta record of AP) RSN BC key + * case3: 1 1 1 AP addr (sta record of AP) RSN STA key + * + * GO: + * case1: 1 1 0 BSSID (no sta record) WEP -- Not support + * case2: 1 0 0 BSSID (no sta record) RSN BC key + * case3: 1 1 1 STA addr STA key + */ + if (prNewKey->ucCipher == CIPHER_SUITE_WEP40 || + prNewKey->ucCipher == CIPHER_SUITE_WEP104 || + prNewKey->ucCipher == CIPHER_SUITE_WEP128) { + /* check if the key no need handshake, then save to bss wep key + * for global usage + */ + fgNoHandshakeSec = TRUE; + } + if (fgNoHandshakeSec) { +#if DBG + if (IS_BSS_AIS(prBssInfo)) { + if (prAdapter->rWifiVar.rConnSettings.eAuthMode + >= AUTH_MODE_WPA && + prAdapter->rWifiVar.rConnSettings.eAuthMode != + AUTH_MODE_WPA_NONE) { + DBGLOG(RSN, WARN, + "Set wep at not open/shared setting\n"); + return WLAN_STATUS_SUCCESS; + } + } +#endif + } + if ((prNewKey->u4KeyIndex & IS_UNICAST_KEY) == IS_UNICAST_KEY) { + prStaRec = cnmGetStaRecByAddress(prAdapter, + prBssInfo->ucBssIndex, prNewKey->arBSSID); + if (!prStaRec) { /* Already disconnected ? */ + DBGLOG(REQ, INFO, + "[wlan] Not set the peer key while disconnect\n"); + return WLAN_STATUS_SUCCESS; + } + } + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + (CMD_HDR_SIZE + sizeof(struct 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(RSN, TRACE, "ucCmdSeqNum = %d\n", ucCmdSeqNum); + /* compose CMD_802_11_KEY cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(struct CMD_802_11_KEY); +#if CFG_SUPPORT_REPLAY_DETECTION + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetAddKey; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutSetAddKey; +#else + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; +#endif + prCmdInfo->fgIsOid = g_fgIsOid; + prCmdInfo->ucCID = CMD_ID_ADD_REMOVE_KEY; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u4SetBufferLen; + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + /* Setup WIFI_CMD_T */ + prWifiCmd = (struct WIFI_CMD *) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + prCmdKey = (struct CMD_802_11_KEY *) (prWifiCmd->aucBuffer); + kalMemZero(prCmdKey, sizeof(struct 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; + /* Copy the addr of the key */ + if ((prNewKey->u4KeyIndex & IS_UNICAST_KEY) == IS_UNICAST_KEY) { + if (prStaRec) { + /* Overwrite the fgNoHandshakeSec in case */ + fgNoHandshakeSec = FALSE; /* Legacy 802.1x wep case ? */ + /* ASSERT(FALSE); */ + } + } else { + if (!IS_BSS_ACTIVE(prBssInfo)) + DBGLOG(REQ, INFO, + "[wlan] BSS info (%d) not active yet!", + prNewKey->ucBssIdx); + } + prCmdKey->ucBssIdx = prBssInfo->ucBssIndex; + prCmdKey->ucKeyId = (uint8_t) (prNewKey->u4KeyIndex & 0xff); + /* Note: the key length may not correct for WPA-None */ + prCmdKey->ucKeyLen = (uint8_t) prNewKey->u4KeyLength; + kalMemCopy(prCmdKey->aucKeyMaterial, + (uint8_t *)prNewKey->aucKeyMaterial, prCmdKey->ucKeyLen); + if (prNewKey->ucCipher) { + prCmdKey->ucAlgorithmId = prNewKey->ucCipher; + if (IS_BSS_AIS(prBssInfo)) { +#if CFG_SUPPORT_802_11W + if (prCmdKey->ucAlgorithmId == CIPHER_SUITE_BIP) { + if (prCmdKey->ucKeyId >= 4) { + struct AIS_SPECIFIC_BSS_INFO + *prAisSpecBssInfo; + + prAisSpecBssInfo = + &prAdapter->rWifiVar + .rAisSpecificBssInfo; + prAisSpecBssInfo->fgBipKeyInstalled = + TRUE; + } + } +#endif + if ((prCmdKey->ucAlgorithmId == CIPHER_SUITE_CCMP) && + rsnCheckPmkidCandicate(prAdapter)) { + 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)); + } + + if (prCmdKey->ucAlgorithmId == CIPHER_SUITE_TKIP) { + /* Todo:: Support AP mode defragment */ + /* for pairwise key only */ + if ((prNewKey->u4KeyIndex & BITS(30, 31)) == + ((IS_UNICAST_KEY) | (IS_TRANSMIT_KEY))) { + kalMemCopy( + prAdapter->rWifiVar + .rAisSpecificBssInfo.aucRxMicKey, + &prCmdKey->aucKeyMaterial[16], + MIC_KEY_LEN); + kalMemCopy( + prAdapter->rWifiVar + .rAisSpecificBssInfo.aucTxMicKey, + &prCmdKey->aucKeyMaterial[24], + MIC_KEY_LEN); + } + } + } else { +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if ((prCmdKey->ucKeyId >= 4 && prCmdKey->ucKeyId <= 5) + && (prCmdKey->ucAlgorithmId == CIPHER_SUITE_BIP)) { + DBGLOG(RSN, INFO, "AP mode set BIP\n"); + prBssInfo->rApPmfCfg.fgBipKeyInstalled = TRUE; + } +#endif + } + } else { /* Legacy windows NDIS no cipher info */ +#if 0 + 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 (IS_BSS_AIS(prBssInfo)) { +#if CFG_SUPPORT_802_11W + if (prCmdKey->ucKeyId >= 4) { + struct AIS_SPECIFIC_BSS_INFO + *prAisSpecBssInfo; + + prCmdKey->ucAlgorithmId = + CIPHER_SUITE_BIP; + prAisSpecBssInfo = + &prAdapter->rWifiVar + .rAisSpecificBssInfo; + prAisSpecBssInfo + ->fgBipKeyInstalled = + TRUE; + } else +#endif + { + prCmdKey->ucAlgorithmId = CIPHER_SUITE_CCMP; + if (rsnCheckPmkidCandicate(prAdapter)) { + DBGLOG(RSN, TRACE, + "Add key: Prepare a timer to indicate candidate PMKID\n"); + cnmTimerStopTimer(prAdapter, + &prAisSpecBssInfo + ->rPreauthenticationTimer); + cnmTimerStartTimer(prAdapter, + &prAisSpecBssInfo + ->rPreauthenticationTimer, + SEC_TO_MSEC( + WAIT_TIME_IND_PMKID_CANDICATE_SEC)); + } + } + } + } + } else if (prNewKey->u4KeyLength == 32) { + if (IS_BSS_AIS(prBssInfo)) { + if (prAdapter->rWifiVar.rConnSettings.eAuthMode + == AUTH_MODE_WPA_NONE) { + if (prAdapter->rWifiVar.rConnSettings + .eEncStatus == + ENUM_ENCRYPTION2_ENABLED) { + prCmdKey->ucAlgorithmId = + CIPHER_SUITE_TKIP; + } else if (prAdapter->rWifiVar + .rConnSettings.eEncStatus == + ENUM_ENCRYPTION3_ENABLED) { + prCmdKey->ucAlgorithmId = + CIPHER_SUITE_CCMP; + prCmdKey->ucKeyLen = + CCMP_KEY_LEN; + } + } else { + prCmdKey->ucAlgorithmId = + CIPHER_SUITE_TKIP; + kalMemCopy( + prAdapter->rWifiVar + .rAisSpecificBssInfo + .aucRxMicKey, + &prCmdKey->aucKeyMaterial[16], + MIC_KEY_LEN); + kalMemCopy( + prAdapter->rWifiVar + .rAisSpecificBssInfo + .aucTxMicKey, + &prCmdKey->aucKeyMaterial[24], + MIC_KEY_LEN); + if (0 /* Todo::GCMP & GCMP-BIP ? */) { + if (rsnCheckPmkidCandicate(prAdapter)) { + DBGLOG(RSN, TRACE, + "Add key: Prepare a timer to indicate candidate PMKID\n"); + cnmTimerStopTimer(prAdapter, + &prAisSpecBssInfo-> + rPreauthenticationTimer); + cnmTimerStartTimer(prAdapter, + &prAisSpecBssInfo-> + rPreauthenticationTimer, + SEC_TO_MSEC( + WAIT_TIME_IND_PMKID_CANDICATE_SEC)); + } + } else { + prCmdKey->ucAlgorithmId = CIPHER_SUITE_TKIP; + } + } +} +#endif + } + { +#if CFG_SUPPORT_TDLS + prTmpStaRec = cnmGetStaRecByAddress(prAdapter, + prBssInfo->ucBssIndex, prNewKey->arBSSID); + if (prTmpStaRec) { + if (IS_DLS_STA(prTmpStaRec)) { + prStaRec = prTmpStaRec; + + /*128 ,TODO GCMP 256 */ + prCmdKey->ucAlgorithmId = CIPHER_SUITE_CCMP; + + kalMemCopy(prCmdKey->aucPeerAddr, + prStaRec->aucMacAddr, MAC_ADDR_LEN); + } + } +#endif + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if (prCmdKey->ucAlgorithmId == CIPHER_SUITE_BIP) { + if (prCmdKey->ucIsAuthenticator) { + DBGLOG(RSN, INFO, + "Authenticator BIP bssid:%d\n", + prBssInfo->ucBssIndex); + + prCmdKey->ucWlanIndex = + secPrivacySeekForBcEntry(prAdapter, + prBssInfo->ucBssIndex, + prBssInfo->aucOwnMacAddr, + STA_REC_INDEX_NOT_FOUND, + prCmdKey->ucAlgorithmId, + prCmdKey->ucKeyId); + } else { + prCmdKey->ucWlanIndex = + secPrivacySeekForBcEntry(prAdapter, + prBssInfo->ucBssIndex, + prBssInfo->prStaRecOfAP->aucMacAddr, + prBssInfo->prStaRecOfAP->ucIndex, + prCmdKey->ucAlgorithmId, + prCmdKey->ucKeyId); + } + + DBGLOG(RSN, INFO, "BIP BC wtbl index:%d\n", + prCmdKey->ucWlanIndex); + } else +#endif + if (1) { + if (prStaRec) { + if (prCmdKey->ucKeyType) { /* RSN STA */ + struct WLAN_TABLE *prWtbl; + + prWtbl = prAdapter->rWifiVar.arWtbl; + prWtbl[prStaRec->ucWlanIndex].ucKeyId = + prCmdKey->ucKeyId; + prCmdKey->ucWlanIndex = + prStaRec->ucWlanIndex; + + /* wait for CMD Done ? */ + prStaRec->fgTransmitKeyExist = TRUE; + + kalMemCopy(prCmdKey->aucPeerAddr, + prNewKey->arBSSID, + MAC_ADDR_LEN); +#if CFG_SUPPORT_802_11W + /* AP PMF */ + DBGLOG(RSN, INFO, + "Assign client PMF flag = %d\n", + prStaRec->rPmfCfg.fgApplyPmf); + prCmdKey->ucMgmtProtection = + prStaRec->rPmfCfg.fgApplyPmf; +#endif + } else { + ASSERT(FALSE); + } + } else { /* Overwrite the old one for AP and STA WEP */ + if (prBssInfo->prStaRecOfAP) { + DBGLOG(RSN, INFO, "AP REC\n"); + prCmdKey->ucWlanIndex = + secPrivacySeekForBcEntry( + prAdapter, + prBssInfo->ucBssIndex, + prBssInfo->prStaRecOfAP + ->aucMacAddr, + prBssInfo->prStaRecOfAP + ->ucIndex, + prCmdKey->ucAlgorithmId, + prCmdKey->ucKeyId); + kalMemCopy(prCmdKey->aucPeerAddr, + prBssInfo->prStaRecOfAP + ->aucMacAddr, + MAC_ADDR_LEN); + } else { + DBGLOG(RSN, INFO, "!AP && !STA REC\n"); + prCmdKey->ucWlanIndex = + secPrivacySeekForBcEntry( + prAdapter, + prBssInfo->ucBssIndex, + prBssInfo->aucOwnMacAddr, + STA_REC_INDEX_NOT_FOUND, + prCmdKey->ucAlgorithmId, + prCmdKey->ucKeyId); + kalMemCopy(prCmdKey->aucPeerAddr, + prBssInfo->aucOwnMacAddr, + MAC_ADDR_LEN); + } + if (prCmdKey->ucKeyId >= MAX_KEY_NUM) { + DBGLOG(RSN, ERROR, + "prCmdKey->ucKeyId [%u] overrun\n", + prCmdKey->ucKeyId); + return WLAN_STATUS_FAILURE; + } + if (fgNoHandshakeSec) { + /* WEP: STA and AP */ + prBssInfo->wepkeyWlanIdx = + prCmdKey->ucWlanIndex; + prBssInfo->wepkeyUsed[ + prCmdKey->ucKeyId] = TRUE; + } else if (!prBssInfo->prStaRecOfAP) { + /* AP WPA/RSN */ + prBssInfo->ucBMCWlanIndexS[ + prCmdKey->ucKeyId] = + prCmdKey->ucWlanIndex; + prBssInfo->ucBMCWlanIndexSUsed[ + prCmdKey->ucKeyId] = TRUE; + } else { + /* STA WPA/RSN, should not have tx but + * no sta record + */ + prBssInfo->ucBMCWlanIndexS[ + prCmdKey->ucKeyId] = + prCmdKey->ucWlanIndex; + prBssInfo->ucBMCWlanIndexSUsed[ + prCmdKey->ucKeyId] = TRUE; + DBGLOG(RSN, INFO, + "BMCWlanIndex kid = %d, index = %d\n", + prCmdKey->ucKeyId, + prCmdKey->ucWlanIndex); + } + if (prCmdKey->ucTxKey) { /* */ + prBssInfo->fgBcDefaultKeyExist = TRUE; + prBssInfo->ucBcDefaultKeyIdx = + prCmdKey->ucKeyId; + } + } + } + } +#if 1 + DBGLOG(RSN, INFO, "Add key cmd to wlan index %d:", + prCmdKey->ucWlanIndex); + DBGLOG(RSN, INFO, "(BSS = %d) " MACSTR "\n", prCmdKey->ucBssIdx, + MAC2STR(prCmdKey->aucPeerAddr)); + DBGLOG(RSN, INFO, "Tx = %d type = %d Auth = %d\n", prCmdKey->ucTxKey, + prCmdKey->ucKeyType, + prCmdKey->ucIsAuthenticator); + DBGLOG(RSN, INFO, "cipher = %d keyid = %d keylen = %d\n", + prCmdKey->ucAlgorithmId, prCmdKey->ucKeyId, + prCmdKey->ucKeyLen); + DBGLOG_MEM8(RSN, INFO, prCmdKey->aucKeyMaterial, prCmdKey->ucKeyLen); + if (prCmdKey->ucKeyId < MAX_KEY_NUM) { + DBGLOG(RSN, INFO, "wepkeyUsed = %d\n", + prBssInfo->wepkeyUsed[prCmdKey->ucKeyId]); + DBGLOG(RSN, INFO, "wepkeyWlanIdx = %d:", + prBssInfo->wepkeyWlanIdx); + DBGLOG(RSN, INFO, "ucBMCWlanIndexSUsed = %d\n", + prBssInfo->ucBMCWlanIndexSUsed[prCmdKey->ucKeyId]); + DBGLOG(RSN, INFO, "ucBMCWlanIndexS = %d:", + prBssInfo->ucBMCWlanIndexS[prCmdKey->ucKeyId]); + } else + DBGLOG(RSN, WARN, "invalid prCmdKey->ucKeyId(%d)\n", + prCmdKey->ucKeyId); +#endif + prAdapter->rWifiVar.rAisSpecificBssInfo.ucKeyAlgorithmId = + prCmdKey->ucAlgorithmId; + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (struct QUE_ENTRY *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetRemoveKey(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + struct WIFI_CMD *prWifiCmd; + struct PARAM_REMOVE_KEY *prRemovedKey; + struct CMD_802_11_KEY *prCmdKey; + uint8_t ucCmdSeqNum; + struct WLAN_TABLE *prWlanTable; + struct STA_RECORD *prStaRec = NULL; + struct BSS_INFO *prBssInfo; + /* UINT_8 i = 0; */ + u_int8_t fgRemoveWepKey = FALSE; + u_int8_t fgRemoveBCKey = FALSE; + uint32_t ucRemoveBCKeyAtIdx = WTBL_RESERVED_ENTRY; + uint32_t u4KeyIndex; + + DEBUGFUNC("wlanoidSetRemoveKey"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + DBGLOG(RSN, INFO, "wlanoidSetRemoveKey\n"); + + prWlanTable = prAdapter->rWifiVar.arWtbl; + *pu4SetInfoLen = sizeof(struct PARAM_REMOVE_KEY); + + if (u4SetBufferLen < sizeof(struct PARAM_REMOVE_KEY)) + 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 = (struct PARAM_REMOVE_KEY *) pvSetBuffer; + + /* Dump PARAM_REMOVE_KEY content. */ + DBGLOG(RSN, INFO, "Set: Dump PARAM_REMOVE_KEY content\n"); + DBGLOG(RSN, INFO, "Length : 0x%08x\n", + prRemovedKey->u4Length); + DBGLOG(RSN, INFO, "Key Index : 0x%08x\n", + prRemovedKey->u4KeyIndex); + DBGLOG(RSN, INFO, "BSS_INDEX : %d\n", + prRemovedKey->ucBssIdx); + DBGLOG(RSN, INFO, "BSSID:\n"); + DBGLOG_MEM8(RSN, INFO, prRemovedKey->arBSSID, MAC_ADDR_LEN); + + prGlueInfo = prAdapter->prGlueInfo; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prRemovedKey->ucBssIdx); + ASSERT(prBssInfo); + + u4KeyIndex = prRemovedKey->u4KeyIndex & 0x000000FF; +#if CFG_SUPPORT_802_11W + ASSERT(u4KeyIndex < MAX_KEY_NUM + 2); +#else + /* ASSERT(prCmdKey->ucKeyId < MAX_KEY_NUM); */ +#endif + + if (u4KeyIndex >= 4) { + DBGLOG(RSN, INFO, "Remove bip key Index : 0x%08x\n", + u4KeyIndex); + return WLAN_STATUS_SUCCESS; + } + + /* Clean up the Tx key flag */ + if (prRemovedKey->u4KeyIndex & IS_UNICAST_KEY) { + prStaRec = cnmGetStaRecByAddress(prAdapter, + prRemovedKey->ucBssIdx, prRemovedKey->arBSSID); + if (!prStaRec) + return WLAN_STATUS_SUCCESS; + } else { + if (u4KeyIndex == prBssInfo->ucBcDefaultKeyIdx) + prBssInfo->fgBcDefaultKeyExist = FALSE; + } + + if (!prStaRec) { + if (prBssInfo->wepkeyUsed[u4KeyIndex] == TRUE) + fgRemoveWepKey = TRUE; + + if (fgRemoveWepKey) { + DBGLOG(RSN, INFO, "Remove wep key id = %d", u4KeyIndex); + prBssInfo->wepkeyUsed[u4KeyIndex] = FALSE; + if (prBssInfo->fgBcDefaultKeyExist && + prBssInfo->ucBcDefaultKeyIdx == u4KeyIndex) { + prBssInfo->fgBcDefaultKeyExist = FALSE; + prBssInfo->ucBcDefaultKeyIdx = 0xff; + } + ASSERT(prBssInfo->wepkeyWlanIdx < WTBL_SIZE); + ucRemoveBCKeyAtIdx = prBssInfo->wepkeyWlanIdx; + fgRemoveBCKey = TRUE; + } else { + DBGLOG(RSN, INFO, "Remove group key id = %d", + u4KeyIndex); + + if (prBssInfo->ucBMCWlanIndexSUsed[u4KeyIndex]) { + if (prBssInfo->fgBcDefaultKeyExist && + prBssInfo->ucBcDefaultKeyIdx == + u4KeyIndex) { + prBssInfo->fgBcDefaultKeyExist = FALSE; + prBssInfo->ucBcDefaultKeyIdx = 0xff; + } + if (u4KeyIndex != 0) + ASSERT(prBssInfo->ucBMCWlanIndexS[ + u4KeyIndex] < WTBL_SIZE); + ucRemoveBCKeyAtIdx = + prBssInfo->ucBMCWlanIndexS[u4KeyIndex]; + prBssInfo->ucBMCWlanIndexSUsed[u4KeyIndex] = + FALSE; + prBssInfo->ucBMCWlanIndexS[u4KeyIndex] = + WTBL_RESERVED_ENTRY; + fgRemoveBCKey = TRUE; + } + } + + /* Change the wtbl to not used state */ + if (fgRemoveBCKey) + prWlanTable[ucRemoveBCKeyAtIdx].ucUsed = FALSE; + + DBGLOG(RSN, INFO, "ucRemoveBCKeyAtIdx = %d", + ucRemoveBCKeyAtIdx); + + if (ucRemoveBCKeyAtIdx >= WTBL_SIZE) + return WLAN_STATUS_SUCCESS; + } + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + (CMD_HDR_SIZE + sizeof(struct CMD_802_11_KEY))); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prRemovedKey->ucBssIdx); + + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_802_11_KEY cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + /* prCmdInfo->ucBssIndex = prRemovedKey->ucBssIdx; */ + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof( + struct CMD_802_11_KEY); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = g_fgIsOid; + prCmdInfo->ucCID = CMD_ID_ADD_REMOVE_KEY; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + /* prCmdInfo->fgDriverDomainMCR = FALSE; */ + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(struct PARAM_REMOVE_KEY); + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + + /* Setup WIFI_CMD_T */ + prWifiCmd = (struct WIFI_CMD *) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prCmdKey = (struct CMD_802_11_KEY *) (prWifiCmd->aucBuffer); + + kalMemZero((uint8_t *) prCmdKey, + sizeof(struct CMD_802_11_KEY)); + + prCmdKey->ucAddRemove = 0; /* Remove */ + prCmdKey->ucKeyId = (uint8_t) u4KeyIndex; + kalMemCopy(prCmdKey->aucPeerAddr, + (uint8_t *) prRemovedKey->arBSSID, MAC_ADDR_LEN); + prCmdKey->ucBssIdx = prRemovedKey->ucBssIdx; + + if (prStaRec) { + prCmdKey->ucKeyType = 1; + prCmdKey->ucWlanIndex = prStaRec->ucWlanIndex; + prStaRec->fgTransmitKeyExist = FALSE; + } else if (ucRemoveBCKeyAtIdx < WTBL_SIZE) { + prCmdKey->ucWlanIndex = ucRemoveBCKeyAtIdx; + } else { + ASSERT(FALSE); + } + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, + (struct QUE_ENTRY *) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; +} /* wlanoidSetRemoveKey */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set the default key + * + * \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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetDefaultKey(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + struct WIFI_CMD *prWifiCmd; + struct PARAM_DEFAULT_KEY *prDefaultKey; + struct CMD_DEFAULT_KEY *prCmdDefaultKey; + uint8_t ucCmdSeqNum; + struct BSS_INFO *prBssInfo; + u_int8_t fgSetWepKey = FALSE; + uint8_t ucWlanIndex = WTBL_RESERVED_ENTRY; + + DEBUGFUNC("wlanoidSetDefaultKey"); + + 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; + } + + prDefaultKey = (struct PARAM_DEFAULT_KEY *) pvSetBuffer; + + *pu4SetInfoLen = u4SetBufferLen; + + /* Dump PARAM_DEFAULT_KEY_T content. */ + DBGLOG(RSN, INFO, + "Key Index : %d, Unicast Key : %d, Multicast Key : %d\n", + prDefaultKey->ucKeyID, prDefaultKey->ucUnicast, + prDefaultKey->ucMulticast); + + /* prWlanTable = prAdapter->rWifiVar.arWtbl; */ + prGlueInfo = prAdapter->prGlueInfo; + + if (prDefaultKey->ucBssIdx > HW_BSSID_NUM) + return WLAN_STATUS_FAILURE; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prDefaultKey->ucBssIdx); + + DBGLOG(RSN, INFO, "WlanIdx = %d\n", + prBssInfo->wepkeyWlanIdx); + + if (prDefaultKey->ucMulticast) { + if (prBssInfo->prStaRecOfAP) { /* Actually GC not have wep */ + if (prBssInfo->wepkeyUsed[prDefaultKey->ucKeyID]) { + prBssInfo->ucBcDefaultKeyIdx = + prDefaultKey->ucKeyID; + prBssInfo->fgBcDefaultKeyExist = TRUE; + ucWlanIndex = prBssInfo->wepkeyWlanIdx; + } else { + if (prDefaultKey->ucUnicast) { + DBGLOG(RSN, ERROR, + "Set STA Unicast default key"); + return WLAN_STATUS_SUCCESS; + } + ASSERT(FALSE); + } + } else { /* For AP mode only */ + + if (prBssInfo->wepkeyUsed[prDefaultKey->ucKeyID] + == TRUE) + fgSetWepKey = TRUE; + + if (fgSetWepKey) { + ucWlanIndex = prBssInfo->wepkeyWlanIdx; + } else { + if (!prBssInfo->ucBMCWlanIndexSUsed[ + prDefaultKey->ucKeyID]) { + DBGLOG(RSN, ERROR, + "Set AP wep default but key not exist!"); + return WLAN_STATUS_SUCCESS; + } + ucWlanIndex = prBssInfo->ucBMCWlanIndexS[ + prDefaultKey->ucKeyID]; + } + prBssInfo->ucBcDefaultKeyIdx = prDefaultKey->ucKeyID; + prBssInfo->fgBcDefaultKeyExist = TRUE; + } + if (ucWlanIndex > WTBL_SIZE) + ASSERT(FALSE); + + } else { + DBGLOG(RSN, ERROR, + "Check the case set unicast default key!"); + ASSERT(FALSE); + } + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + (CMD_HDR_SIZE + sizeof(struct CMD_DEFAULT_KEY))); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + DBGLOG(RSN, TRACE, + "ucCmdSeqNum = %d, CMD_ID_DEFAULT_KEY_ID (%d) with wlan idx = %d\n", + ucCmdSeqNum, prDefaultKey->ucKeyID, ucWlanIndex); + + /* compose CMD_802_11_KEY cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof( + struct CMD_DEFAULT_KEY); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = g_fgIsOid; + prCmdInfo->ucCID = CMD_ID_DEFAULT_KEY_ID; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u4SetBufferLen; + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + + /* Setup WIFI_CMD_T */ + prWifiCmd = (struct WIFI_CMD *) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prCmdDefaultKey = (struct CMD_DEFAULT_KEY *) ( + prWifiCmd->aucBuffer); + + kalMemZero(prCmdDefaultKey, sizeof(struct CMD_DEFAULT_KEY)); + + prCmdDefaultKey->ucBssIdx = prDefaultKey->ucBssIdx; + prCmdDefaultKey->ucKeyId = prDefaultKey->ucKeyID; + prCmdDefaultKey->ucWlanIndex = ucWlanIndex; + prCmdDefaultKey->ucMulticast = prDefaultKey->ucMulticast; + + DBGLOG(RSN, INFO, + "CMD_ID_DEFAULT_KEY_ID (%d) with wlan idx = %d\n", + prDefaultKey->ucKeyID, ucWlanIndex); + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, + (struct QUE_ENTRY *) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; +} /* wlanoidSetDefaultKey */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryEncryptionStatus(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + u_int8_t fgTransmitKeyAvailable = TRUE; + enum ENUM_WEP_STATUS eEncStatus = 0; + + DEBUGFUNC("wlanoidQueryEncryptionStatus"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(enum ENUM_WEP_STATUS); + + fgTransmitKeyAvailable = + prAdapter->prAisBssInfo->fgBcDefaultKeyExist; + + switch (prAdapter->rWifiVar.rConnSettings.eEncStatus) { + case ENUM_ENCRYPTION3_ENABLED: + if (fgTransmitKeyAvailable) + eEncStatus = ENUM_ENCRYPTION3_ENABLED; + else + eEncStatus = ENUM_ENCRYPTION3_KEY_ABSENT; + break; + + case ENUM_ENCRYPTION2_ENABLED: + if (fgTransmitKeyAvailable) { + eEncStatus = ENUM_ENCRYPTION2_ENABLED; + break; + } + eEncStatus = ENUM_ENCRYPTION2_KEY_ABSENT; + break; + + case ENUM_ENCRYPTION1_ENABLED: + if (fgTransmitKeyAvailable) + eEncStatus = ENUM_ENCRYPTION1_ENABLED; + else + eEncStatus = ENUM_ENCRYPTION1_KEY_ABSENT; + break; + + case ENUM_ENCRYPTION_DISABLED: + eEncStatus = ENUM_ENCRYPTION_DISABLED; + break; + + default: + DBGLOG(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 + + *(enum ENUM_WEP_STATUS *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetEncryptionStatus(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct GLUE_INFO *prGlueInfo; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + enum ENUM_WEP_STATUS eEewEncrypt; + + DEBUGFUNC("wlanoidSetEncryptionStatus"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prGlueInfo = prAdapter->prGlueInfo; + + *pu4SetInfoLen = sizeof(enum ENUM_WEP_STATUS); + + /* 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 = *(enum ENUM_WEP_STATUS *) pvSetBuffer; + DBGLOG(REQ, INFO, "ENCRYPTION_STATUS %d\n", eEewEncrypt); + + switch (eEewEncrypt) { + case ENUM_ENCRYPTION_DISABLED: /* Disable WEP, TKIP, AES */ + DBGLOG(RSN, INFO, "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, INFO, "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, INFO, "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, INFO, "Enable Encryption3\n"); + break; + +#if CFG_SUPPORT_SUITB + case ENUM_ENCRYPTION4_ENABLED: /* Eanble GCMP256 */ + secSetCipherSuite(prAdapter, CIPHER_FLAG_GCMP256); + DBGLOG(RSN, INFO, "Enable Encryption4\n"); + break; +#endif + + default: + DBGLOG(RSN, INFO, "Unacceptible encryption status: %d\n", + *(enum ENUM_WEP_STATUS *) pvSetBuffer); + + rStatus = WLAN_STATUS_NOT_SUPPORTED; + } + + if (rStatus == WLAN_STATUS_SUCCESS) { + /* Save the new encryption status. */ + prAdapter->rWifiVar.rConnSettings.eEncStatus = * + (enum ENUM_WEP_STATUS *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetTest(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_802_11_TEST *prTest; + void *pvTestData; + void *pvStatusBuffer; + uint32_t u4StatusBufferSize; + + DEBUGFUNC("wlanoidSetTest"); + + ASSERT(prAdapter); + + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = u4SetBufferLen; + + prTest = (struct PARAM_802_11_TEST *) pvSetBuffer; + + DBGLOG(REQ, TRACE, "Test - Type %u\n", prTest->u4Type); + + switch (prTest->u4Type) { + case 1: /* Type 1: generate an authentication event */ + pvTestData = (void *) &prTest->u.AuthenticationEvent; + pvStatusBuffer = (void *) + prAdapter->aucIndicationEventBuffer; + u4StatusBufferSize = prTest->u4Length - 8; + if (u4StatusBufferSize > sizeof( + prTest->u.AuthenticationEvent)) + return WLAN_STATUS_INVALID_LENGTH; + break; + + case 2: /* Type 2: generate an RSSI status indication */ + pvTestData = (void *) &prTest->u.RssiTrigger; + pvStatusBuffer = (void *) + &prAdapter->rWlanInfo.rCurrBssId.rRssi; + u4StatusBufferSize = sizeof(int32_t); + break; + + default: + return WLAN_STATUS_INVALID_DATA; + } + + /* 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryCapability(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_CAPABILITY *prCap; + struct PARAM_AUTH_ENCRYPTION + *prAuthenticationEncryptionSupported; + + DEBUGFUNC("wlanoidQueryCapability"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = 4 * sizeof(uint32_t) + 14 * sizeof( + struct PARAM_AUTH_ENCRYPTION); + + if (u4QueryBufferLen < *pu4QueryInfoLen) + return WLAN_STATUS_INVALID_LENGTH; + + prCap = (struct PARAM_CAPABILITY *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryPmkid(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t i; + struct PARAM_PMKID *prPmkid; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecBssInfo; + + DEBUGFUNC("wlanoidQueryPmkid"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + *pu4QueryInfoLen = OFFSET_OF(struct PARAM_PMKID, + arBSSIDInfo) + + prAisSpecBssInfo->u4PmkidCacheCount * sizeof( + struct PARAM_BSSID_INFO); + + if (u4QueryBufferLen < *pu4QueryInfoLen) + return WLAN_STATUS_INVALID_LENGTH; + + prPmkid = (struct PARAM_PMKID *) 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(uint8_t) * PARAM_MAC_ADDR_LEN)); + kalMemCopy(prPmkid->arBSSIDInfo[i].arPMKID, + prAisSpecBssInfo->arPmkidCache[i].rBssidInfo.arPMKID, + (sizeof(uint8_t) * 16)); + } + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetPmkid(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t i, j; + struct PARAM_PMKID *prPmkid; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecBssInfo; + + DEBUGFUNC("wlanoidSetPmkid"); + + DBGLOG(REQ, INFO, "wlanoidSetPmkid\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = u4SetBufferLen; + + /* It's possibble BSSIDInfoCount is zero, because OS wishes to clean + * PMKID + */ + if (u4SetBufferLen < OFFSET_OF(struct PARAM_PMKID, + arBSSIDInfo)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + ASSERT(pvSetBuffer); + prPmkid = (struct PARAM_PMKID *) pvSetBuffer; + + if (u4SetBufferLen < + ((prPmkid->u4BSSIDInfoCount * sizeof(struct + PARAM_BSSID_INFO)) + OFFSET_OF(struct PARAM_PMKID, + arBSSIDInfo))) + return WLAN_STATUS_INVALID_DATA; + + if (prPmkid->u4BSSIDInfoCount > CFG_MAX_PMKID_CACHE) + return WLAN_STATUS_INVALID_DATA; + + DBGLOG(REQ, INFO, "Count %u\n", prPmkid->u4BSSIDInfoCount); + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + /* This OID replace everything in the PMKID cache. */ + if (prPmkid->u4BSSIDInfoCount == 0) { + prAisSpecBssInfo->u4PmkidCacheCount = 0; + kalMemZero(prAisSpecBssInfo->arPmkidCache, + sizeof(struct PMKID_ENTRY) * CFG_MAX_PMKID_CACHE); + } + if ((prAisSpecBssInfo->u4PmkidCacheCount + + prPmkid->u4BSSIDInfoCount > CFG_MAX_PMKID_CACHE)) { + prAisSpecBssInfo->u4PmkidCacheCount = 0; + kalMemZero(prAisSpecBssInfo->arPmkidCache, + sizeof(struct PMKID_ENTRY) * 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. + */ + for (i = 0; i < prPmkid->u4BSSIDInfoCount; i++) { + /* Search for desired BSSID. If desired BSSID is found, + * then set the PMKID + */ + if (!rsnSearchPmkidEntry(prAdapter, + (uint8_t *) 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(uint8_t) * PARAM_MAC_ADDR_LEN)); + 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(uint8_t) * 16)); + DBGLOG(RSN, TRACE, + "Add BSSID " MACSTR " idx=%u PMKID value " MACSTR + "\n", + MAC2STR(prAisSpecBssInfo->arPmkidCache[j] + .rBssidInfo.arBSSID), + j, + MAC2STR(prAisSpecBssInfo->arPmkidCache[j] + .rBssidInfo.arPMKID)); + prAisSpecBssInfo->arPmkidCache[j].fgPmkidExist = TRUE; + } + } + + if (prAdapter->rWifiVar.rConnSettings.fgOkcEnabled) { + struct BSS_DESC *prBssDesc = + prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc; + uint8_t *pucPmkID = NULL; + + if ((prPmkid->u4Length & BIT(31)) || + (prBssDesc && EQUAL_MAC_ADDR( + prPmkid->arBSSIDInfo[0].arBSSID, prBssDesc->aucBSSID))) { + if (j == CFG_MAX_PMKID_CACHE) { + j = 0; + kalMemCopy( + prAisSpecBssInfo->arPmkidCache[0] + .rBssidInfo.arBSSID, + prPmkid->arBSSIDInfo[0].arBSSID, + (sizeof(uint8_t) * PARAM_MAC_ADDR_LEN)); + kalMemCopy( + prAisSpecBssInfo->arPmkidCache[0] + .rBssidInfo.arPMKID, + prPmkid->arBSSIDInfo[0].arPMKID, + (sizeof(uint8_t) * 16)); + prAisSpecBssInfo->arPmkidCache[0].fgPmkidExist + = TRUE; + } + pucPmkID = prAisSpecBssInfo->arPmkidCache[j].rBssidInfo + .arPMKID; + log_dbg(RSN, INFO, MACSTR " OKC PMKID %02x%02x%02x%02x%02x%02x%02x%02x...\n", + MAC2STR(prAisSpecBssInfo-> + arPmkidCache[j].rBssidInfo.arBSSID), + pucPmkID[0], pucPmkID[1], + pucPmkID[2], pucPmkID[3], + pucPmkID[4], pucPmkID[5], + pucPmkID[6], pucPmkID[7]); + } + aisFsmRunEventSetOkcPmk(prAdapter); + } + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQuerySupportedRates(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint8_t eRate[PARAM_MAX_LEN_RATES] = { + /* 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(uint8_t) * + PARAM_MAX_LEN_RATES_EX); + + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + kalMemCopy(pvQueryBuffer, (void *) &eRate, + (sizeof(uint8_t) * PARAM_MAX_LEN_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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryDesiredRates(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + DEBUGFUNC("wlanoidQueryDesiredRates"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = (sizeof(uint8_t) * + PARAM_MAX_LEN_RATES_EX); + + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + kalMemCopy(pvQueryBuffer, + (void *) &(prAdapter->rWlanInfo.eDesiredRates), + (sizeof(uint8_t) * PARAM_MAX_LEN_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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetDesiredRates(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t i; + + DEBUGFUNC("wlanoidSetDesiredRates"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < (sizeof(uint8_t) * + PARAM_MAX_LEN_RATES)) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = (sizeof(uint8_t) * PARAM_MAX_LEN_RATES); + + if (u4SetBufferLen < (sizeof(uint8_t) * + PARAM_MAX_LEN_RATES)) + return WLAN_STATUS_INVALID_LENGTH; + + kalMemCopy((void *) &(prAdapter->rWlanInfo.eDesiredRates), + pvSetBuffer, (sizeof(uint8_t) * PARAM_MAX_LEN_RATES)); + + prAdapter->rWlanInfo.eLinkAttr.ucDesiredRateLen = + PARAM_MAX_LEN_RATES; + for (i = 0; i < PARAM_MAX_LEN_RATES; i++) + prAdapter->rWlanInfo.eLinkAttr.u2DesiredRate[i] = + (uint16_t) (prAdapter->rWlanInfo.eDesiredRates[i]); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_LINK_ATTRIB, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_LINK_ATTRIB), + (uint8_t *) &(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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryMaxFrameSize(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + DEBUGFUNC("wlanoidQueryMaxFrameSize"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(uint32_t)) { + *pu4QueryInfoLen = sizeof(uint32_t); + return WLAN_STATUS_INVALID_LENGTH; + } + + *(uint32_t *) pvQueryBuffer = ETHERNET_MAX_PKT_SZ - + ETHERNET_HEADER_SZ; + *pu4QueryInfoLen = sizeof(uint32_t); + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryMaxTotalSize(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + DEBUGFUNC("wlanoidQueryMaxTotalSize"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(uint32_t)) { + *pu4QueryInfoLen = sizeof(uint32_t); + return WLAN_STATUS_INVALID_LENGTH; + } + + *(uint32_t *) pvQueryBuffer = ETHERNET_MAX_PKT_SZ; + *pu4QueryInfoLen = sizeof(uint32_t); + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryVendorId(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { +#if DBG + uint8_t *cp; +#endif + DEBUGFUNC("wlanoidQueryVendorId"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(uint32_t)) { + *pu4QueryInfoLen = sizeof(uint32_t); + return WLAN_STATUS_INVALID_LENGTH; + } + + kalMemCopy(pvQueryBuffer, prAdapter->aucMacAddress, 3); + *((uint8_t *) pvQueryBuffer + 3) = 1; + *pu4QueryInfoLen = sizeof(uint32_t); + +#if DBG + cp = (uint8_t *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryRssi(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + + return wlanQueryRssi(prAdapter, + pvQueryBuffer, + u4QueryBufferLen, + pu4QueryInfoLen, + g_fgIsOid); +} + +uint32_t +wlanQueryRssi(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen, + IN uint8_t fgIsOid) { + + DEBUGFUNC("wlanoidQueryRssi"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (prAdapter->fgIsEnableLpdvt) + return WLAN_STATUS_NOT_SUPPORTED; + + *pu4QueryInfoLen = sizeof(int32_t); + + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(REQ, WARN, "Too short length %u\n", + u4QueryBufferLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == + PARAM_MEDIA_STATE_DISCONNECTED) { + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (prAdapter->fgIsLinkQualityValid == TRUE && + (kalGetTimeTick() - prAdapter->rLinkQualityUpdateTime) <= + CFG_LINK_QUALITY_VALID_PERIOD) { + int32_t rRssi; + + /* ranged from (-128 ~ 30) in unit of dBm */ + rRssi = (int32_t) prAdapter->rLinkQuality.cRssi; + + 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(int32_t)); + return WLAN_STATUS_SUCCESS; + } +#ifdef LINUX + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + fgIsOid, + nicCmdEventQueryLinkQuality, + nicOidCmdTimeoutCommon, + *pu4QueryInfoLen, pvQueryBuffer, + pvQueryBuffer, + u4QueryBufferLen); +#else + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + fgIsOid, + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryRssiTrigger(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *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(int32_t); + + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(REQ, WARN, "Too short length %u\n", + u4QueryBufferLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + *(int32_t *) pvQueryBuffer = + prAdapter->rWlanInfo.rRssiTriggerValue; + DBGLOG(REQ, INFO, "RSSI trigger: %d dBm\n", + *(int32_t *) 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 + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetRssiTrigger(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + int32_t rRssiTriggerValue; + + DEBUGFUNC("wlanoidSetRssiTrigger"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(int32_t); + rRssiTriggerValue = *(int32_t *) 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 == (int32_t) ( + prAdapter->rLinkQuality.cRssi)) { + prAdapter->rWlanInfo.eRssiTriggerType = + ENUM_RSSI_TRIGGER_TRIGGERED; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (void *) &prAdapter->rWlanInfo.rRssiTriggerValue, + sizeof(int32_t)); + } else if (rRssiTriggerValue < (int32_t) ( + prAdapter->rLinkQuality.cRssi)) + prAdapter->rWlanInfo.eRssiTriggerType = + ENUM_RSSI_TRIGGER_GREATER; + else if (rRssiTriggerValue > (int32_t) ( + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetCurrentLookahead(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + DEBUGFUNC("wlanoidSetCurrentLookahead"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(uint32_t)) { + *pu4SetInfoLen = sizeof(uint32_t); + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = sizeof(uint32_t); + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryRcvError(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *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(uint32_t); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(uint32_t) + || (u4QueryBufferLen > sizeof(uint32_t) + && u4QueryBufferLen < sizeof(uint64_t))) { + *pu4QueryInfoLen = sizeof(uint64_t); + 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(uint32_t)) { + *pu4QueryInfoLen = sizeof(uint32_t); + *(uint32_t *) pvQueryBuffer = (uint32_t) + prAdapter->rStatStruct.rFCSErrorCount.QuadPart; + } else { + *pu4QueryInfoLen = sizeof(uint64_t); + *(uint64_t *) pvQueryBuffer = (uint64_t) + prAdapter->rStatStruct.rFCSErrorCount.QuadPart; + } + + return WLAN_STATUS_SUCCESS; + } +#endif + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryRecvError, + nicOidCmdTimeoutCommon, 0, NULL, + pvQueryBuffer, + u4QueryBufferLen); + +} /* wlanoidQueryRcvError */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the number of frames that the NIC + * cannot receive due to lack of NIC receive buffer space. + * + * \param[in] pvAdapter Pointer to the Adapter structure + * \param[in] pvQueryBuf A pointer to the buffer that holds the result of the + * query buffer + * \param[in] u4QueryBufLen The length of the query buffer + * \param[out] pu4QueryInfoLen If the call is successful, returns the number of + * bytes written into the query buffer. If the call + * failed due to invalid length of the query buffer, + * returns the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS If success; + * \retval WLAN_STATUS_INVALID_LENGTH + * \retval WLAN_STATUS_ADAPTER_NOT_READY + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryRcvNoBuffer(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *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(uint32_t); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(uint32_t) + || (u4QueryBufferLen > sizeof(uint32_t) + && u4QueryBufferLen < sizeof(uint64_t))) { + *pu4QueryInfoLen = sizeof(uint64_t); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(uint32_t)) { + *pu4QueryInfoLen = sizeof(uint32_t); + *(uint32_t *) pvQueryBuffer = (uint32_t) 0; /* @FIXME */ + } else { + *pu4QueryInfoLen = sizeof(uint64_t); + *(uint64_t *) pvQueryBuffer = (uint64_t) 0; /* @FIXME */ + } + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryRecvNoBuffer, + nicOidCmdTimeoutCommon, 0, NULL, + pvQueryBuffer, + u4QueryBufferLen); + +} /* wlanoidQueryRcvNoBuffer */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the number of frames that the NIC + * received and it is CRC error. + * + * \param[in] pvAdapter Pointer to the Adapter structure + * \param[in] pvQueryBuf A pointer to the buffer that holds the result of the + * query buffer + * \param[in] u4QueryBufLen The length of the query buffer + * \param[out] pu4QueryInfoLen If the call is successful, returns the number of + * bytes written into the query buffer. If the call + * failed due to invalid length of the query buffer, + * returns the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS If success; + * \retval WLAN_STATUS_INVALID_LENGTH + * \retval WLAN_STATUS_ADAPTER_NOT_READY + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryRcvCrcError(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *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(uint32_t); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(uint32_t) + || (u4QueryBufferLen > sizeof(uint32_t) + && u4QueryBufferLen < sizeof(uint64_t))) { + *pu4QueryInfoLen = sizeof(uint64_t); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(uint32_t)) { + *pu4QueryInfoLen = sizeof(uint32_t); + *(uint32_t *) pvQueryBuffer = (uint32_t) + prAdapter->rStatStruct.rFCSErrorCount.QuadPart; + } else { + *pu4QueryInfoLen = sizeof(uint64_t); + *(uint64_t *) pvQueryBuffer = (uint64_t) + prAdapter->rStatStruct.rFCSErrorCount.QuadPart; + } + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryRecvCrcError, + nicOidCmdTimeoutCommon, 0, NULL, + pvQueryBuffer, + u4QueryBufferLen); + +} /* wlanoidQueryRcvCrcError */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the current 802.11 statistics. + * + * \param[in] pvAdapter Pointer to the Adapter structure + * \param[in] pvQueryBuf A pointer to the buffer that holds the result of the + * query buffer + * \param[in] u4QueryBufLen The length of the query buffer + * \param[out] pu4QueryInfoLen If the call is successful, returns the number of + * bytes written into the query buffer. If the call + * failed due to invalid length of the query buffer, + * returns the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryStatistics(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_802_11_STATISTICS_STRUCT rStatistics; + + DEBUGFUNC("wlanoidQueryStatistics"); + DBGLOG(REQ, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(struct + PARAM_802_11_STATISTICS_STRUCT); + + 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(uint32_t); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(struct + PARAM_802_11_STATISTICS_STRUCT)) { + DBGLOG(REQ, WARN, "Too short length %u\n", + u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + struct PARAM_802_11_STATISTICS_STRUCT *prStatistics; + + *pu4QueryInfoLen = sizeof(struct + PARAM_802_11_STATISTICS_STRUCT); + prStatistics = (struct PARAM_802_11_STATISTICS_STRUCT *) + pvQueryBuffer; + + prStatistics->u4Length = sizeof(struct + PARAM_802_11_STATISTICS_STRUCT); + prStatistics->rTransmittedFragmentCount = + prAdapter->rStatStruct.rTransmittedFragmentCount; + prStatistics->rMulticastTransmittedFrameCount = + prAdapter->rStatStruct.rMulticastTransmittedFrameCount; + prStatistics->rFailedCount = + prAdapter->rStatStruct.rFailedCount; + prStatistics->rRetryCount = + prAdapter->rStatStruct.rRetryCount; + prStatistics->rMultipleRetryCount = + prAdapter->rStatStruct.rMultipleRetryCount; + prStatistics->rRTSSuccessCount = + prAdapter->rStatStruct.rRTSSuccessCount; + prStatistics->rRTSFailureCount = + prAdapter->rStatStruct.rRTSFailureCount; + prStatistics->rACKFailureCount = + prAdapter->rStatStruct.rACKFailureCount; + prStatistics->rFrameDuplicateCount = + prAdapter->rStatStruct.rFrameDuplicateCount; + prStatistics->rReceivedFragmentCount = + prAdapter->rStatStruct.rReceivedFragmentCount; + prStatistics->rMulticastReceivedFrameCount = + prAdapter->rStatStruct.rMulticastReceivedFrameCount; + prStatistics->rFCSErrorCount = + prAdapter->rStatStruct.rFCSErrorCount; + prStatistics->rTKIPLocalMICFailures.QuadPart = 0; + prStatistics->rTKIPICVErrors.QuadPart = 0; + prStatistics->rTKIPCounterMeasuresInvoked.QuadPart = 0; + prStatistics->rTKIPReplays.QuadPart = 0; + prStatistics->rCCMPFormatErrors.QuadPart = 0; + prStatistics->rCCMPReplays.QuadPart = 0; + prStatistics->rCCMPDecryptErrors.QuadPart = 0; + prStatistics->rFourWayHandshakeFailures.QuadPart = 0; + prStatistics->rWEPUndecryptableCount.QuadPart = 0; + prStatistics->rWEPICVErrorCount.QuadPart = 0; + prStatistics->rDecryptSuccessCount.QuadPart = 0; + prStatistics->rDecryptFailureCount.QuadPart = 0; + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventQueryStatistics, + nicOidCmdTimeoutCommon, + sizeof(struct PARAM_802_11_STATISTICS_STRUCT), + (uint8_t *)&rStatistics, + pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryStatistics */ + +uint32_t +wlanoidQueryBugReport(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + DEBUGFUNC("wlanoidQueryBugReport"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(struct _EVENT_BUG_REPORT_T); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, + "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(uint32_t); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(struct + _EVENT_BUG_REPORT_T)) { + DBGLOG(OID, WARN, "Too short length %u\n", + u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_BUG_REPORT, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventQueryBugReport, + nicOidCmdTimeoutCommon, + 0, NULL, pvQueryBuffer, u4QueryBufferLen); +} /* wlanoidQueryBugReport */ + +/*----------------------------------------------------------------------------*/ +/*! \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryMediaStreamMode(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + DEBUGFUNC("wlanoidQueryMediaStreamMode"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(enum ENUM_MEDIA_STREAM_MODE); + + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + *(enum 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetMediaStreamMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + enum ENUM_MEDIA_STREAM_MODE eStreamMode; + + DEBUGFUNC("wlanoidSetMediaStreamMode"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(enum ENUM_MEDIA_STREAM_MODE)) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = sizeof(enum ENUM_MEDIA_STREAM_MODE); + + eStreamMode = *(enum 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(struct CMD_LINK_ATTRIB), + (uint8_t *) &(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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryPermanentAddr(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryCurrentAddr(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + 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; + + COPY_MAC_ADDR(pvQueryBuffer, + prAdapter->rWifiVar.aucMacAddress); + *pu4QueryInfoLen = MAC_ADDR_LEN; + + return WLAN_STATUS_SUCCESS; +} /* 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 + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryLinkSpeed(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + DEBUGFUNC("wlanoidQueryLinkSpeed"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (prAdapter->fgIsEnableLpdvt) + return WLAN_STATUS_NOT_SUPPORTED; + + *pu4QueryInfoLen = sizeof(uint32_t); + + if (u4QueryBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != + PARAM_MEDIA_STATE_CONNECTED) { + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (prAdapter->fgIsLinkRateValid == TRUE && + (kalGetTimeTick() - prAdapter->rLinkRateUpdateTime) <= + CFG_LINK_QUALITY_VALID_PERIOD) { + *(uint32_t *) 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, + g_fgIsOid, + nicCmdEventQueryLinkSpeed, + nicOidCmdTimeoutCommon, 0, NULL, + pvQueryBuffer, u4QueryBufferLen); + } +} /* end of wlanoidQueryLinkSpeed() */ + +#if CFG_SUPPORT_QA_TOOL +#if CFG_SUPPORT_BUFFER_MODE +uint32_t +wlanoidSetEfusBufferMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE + *prSetEfuseBufModeInfo; + struct CMD_EFUSE_BUFFER_MODE *prCmdSetEfuseBufModeInfo = + NULL; + PFN_CMD_DONE_HANDLER pfCmdDoneHandler; + uint32_t u4EfuseContentSize, u4QueryInfoLen; + u_int8_t fgSetQuery, fgNeedResp; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidSetEfusBufferMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + /* get the buffer mode info */ + prSetEfuseBufModeInfo = + (struct PARAM_CUSTOM_EFUSE_BUFFER_MODE *) pvSetBuffer; + + /* copy command header */ + prCmdSetEfuseBufModeInfo = (struct CMD_EFUSE_BUFFER_MODE *) + kalMemAlloc(sizeof(struct CMD_EFUSE_BUFFER_MODE), + VIR_MEM_TYPE); + if (prCmdSetEfuseBufModeInfo == NULL) + return WLAN_STATUS_FAILURE; + kalMemZero(prCmdSetEfuseBufModeInfo, + sizeof(struct CMD_EFUSE_BUFFER_MODE)); + prCmdSetEfuseBufModeInfo->ucSourceMode = + prSetEfuseBufModeInfo->ucSourceMode; + prCmdSetEfuseBufModeInfo->ucCount = + prSetEfuseBufModeInfo->ucCount; + prCmdSetEfuseBufModeInfo->ucCmdType = + prSetEfuseBufModeInfo->ucCmdType; + prCmdSetEfuseBufModeInfo->ucReserved = + prSetEfuseBufModeInfo->ucReserved; + + /* decide content size and SetQuery / NeedResp flag */ + if (prAdapter->fgIsSupportBufferBinSize16Byte == TRUE) { + u4EfuseContentSize = sizeof(struct BIN_CONTENT) * + EFUSE_CONTENT_SIZE; + pfCmdDoneHandler = nicCmdEventSetCommon; + fgSetQuery = TRUE; + fgNeedResp = FALSE; + } else { +#if (CFG_FW_Report_Efuse_Address == 1) + u4EfuseContentSize = (prAdapter->u4EfuseEndAddress) - + (prAdapter->u4EfuseStartAddress) + 1; +#else + u4EfuseContentSize = EFUSE_CONTENT_BUFFER_SIZE; +#endif + pfCmdDoneHandler = NULL; + fgSetQuery = FALSE; + fgNeedResp = TRUE; + } + + u4QueryInfoLen = OFFSET_OF(struct CMD_EFUSE_BUFFER_MODE, + aBinContent) + u4EfuseContentSize; + + if (u4SetBufferLen < u4QueryInfoLen) { + kalMemFree(prCmdSetEfuseBufModeInfo, VIR_MEM_TYPE, + sizeof(struct CMD_EFUSE_BUFFER_MODE)); + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = u4QueryInfoLen; + kalMemCopy(prCmdSetEfuseBufModeInfo->aBinContent, + prSetEfuseBufModeInfo->aBinContent, + u4EfuseContentSize); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_EFUSE_BUFFER_MODE, + fgSetQuery, + fgNeedResp, + g_fgIsOid, + pfCmdDoneHandler, + nicOidCmdTimeoutCommon, + u4QueryInfoLen, + (uint8_t *) (prCmdSetEfuseBufModeInfo), + pvSetBuffer, u4SetBufferLen); + + kalMemFree(prCmdSetEfuseBufModeInfo, VIR_MEM_TYPE, + sizeof(struct CMD_EFUSE_BUFFER_MODE)); + + return rWlanStatus; +} + +uint32_t +wlanoidConnacSetEfusBufferMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE_CONNAC_T + *prSetEfuseBufModeInfo; + struct CMD_EFUSE_BUFFER_MODE_CONNAC_T + *prCmdSetEfuseBufModeInfo = NULL; + uint32_t u4EfuseContentSize, u4QueryInfoLen; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidSetEfusBufferMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + DBGLOG(OID, INFO, "u4SetBufferLen = %d\n", u4SetBufferLen); + /* get the buffer mode info */ + prSetEfuseBufModeInfo = + (struct PARAM_CUSTOM_EFUSE_BUFFER_MODE_CONNAC_T *) pvSetBuffer; + + /* copy command header */ + prCmdSetEfuseBufModeInfo = (struct CMD_EFUSE_BUFFER_MODE_CONNAC_T *) + kalMemAlloc(sizeof(struct CMD_EFUSE_BUFFER_MODE_CONNAC_T), + VIR_MEM_TYPE); + if (prCmdSetEfuseBufModeInfo == NULL) + return WLAN_STATUS_FAILURE; + kalMemZero(prCmdSetEfuseBufModeInfo, + sizeof(struct CMD_EFUSE_BUFFER_MODE_CONNAC_T)); + prCmdSetEfuseBufModeInfo->ucSourceMode = + prSetEfuseBufModeInfo->ucSourceMode; + prCmdSetEfuseBufModeInfo->ucContentFormat = + prSetEfuseBufModeInfo->ucContentFormat; + prCmdSetEfuseBufModeInfo->u2Count = + prSetEfuseBufModeInfo->u2Count; + + u4EfuseContentSize = prCmdSetEfuseBufModeInfo->u2Count; + + u4QueryInfoLen = OFFSET_OF(struct + CMD_EFUSE_BUFFER_MODE_CONNAC_T, + aBinContent) + u4EfuseContentSize; + + if (u4SetBufferLen < u4QueryInfoLen) { + kalMemFree(prCmdSetEfuseBufModeInfo, VIR_MEM_TYPE, + sizeof(struct CMD_EFUSE_BUFFER_MODE_CONNAC_T)); + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = u4QueryInfoLen; + kalMemCopy(prCmdSetEfuseBufModeInfo->aBinContent, + prSetEfuseBufModeInfo->aBinContent, + u4EfuseContentSize); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_EFUSE_BUFFER_MODE, + FALSE, + TRUE, + g_fgIsOid, + NULL, + nicOidCmdTimeoutCommon, + u4QueryInfoLen, + (uint8_t *) (prCmdSetEfuseBufModeInfo), + pvSetBuffer, u4SetBufferLen); + + kalMemFree(prCmdSetEfuseBufModeInfo, VIR_MEM_TYPE, + sizeof(struct CMD_EFUSE_BUFFER_MODE_CONNAC_T)); + + return rWlanStatus; +} + +/*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to read efuse content. + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryProcessAccessEfuseRead(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_ACCESS_EFUSE *prSetAccessEfuseInfo; + struct CMD_ACCESS_EFUSE rCmdSetAccessEfuse; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryProcessAccessEfuseRead"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_ACCESS_EFUSE)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prSetAccessEfuseInfo = (struct PARAM_CUSTOM_ACCESS_EFUSE *) + pvSetBuffer; + + kalMemSet(&rCmdSetAccessEfuse, 0, + sizeof(struct CMD_ACCESS_EFUSE)); + + rCmdSetAccessEfuse.u4Address = + prSetAccessEfuseInfo->u4Address; + rCmdSetAccessEfuse.u4Valid = prSetAccessEfuseInfo->u4Valid; + + + DBGLOG(INIT, INFO, + "MT6632 : wlanoidQueryProcessAccessEfuseRead, address=%d\n", + rCmdSetAccessEfuse.u4Address); + + kalMemCopy(rCmdSetAccessEfuse.aucData, + prSetAccessEfuseInfo->aucData, + sizeof(uint8_t) * 16); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_EFUSE_ACCESS, + FALSE, /* Query Bit: True->write False->read */ + TRUE, + g_fgIsOid, + NULL, /* No Tx done function wait until fw ack */ + nicOidCmdTimeoutCommon, + sizeof(struct CMD_ACCESS_EFUSE), + (uint8_t *) (&rCmdSetAccessEfuse), pvSetBuffer, + u4SetBufferLen); + + return rWlanStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to write efuse content. + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryProcessAccessEfuseWrite(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_ACCESS_EFUSE *prSetAccessEfuseInfo; + struct CMD_ACCESS_EFUSE rCmdSetAccessEfuse; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryProcessAccessEfuseWrite"); + DBGLOG(INIT, INFO, + "MT6632 : wlanoidQueryProcessAccessEfuseWrite\n"); + + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_ACCESS_EFUSE)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prSetAccessEfuseInfo = (struct PARAM_CUSTOM_ACCESS_EFUSE *) + pvSetBuffer; + + kalMemSet(&rCmdSetAccessEfuse, 0, + sizeof(struct CMD_ACCESS_EFUSE)); + + rCmdSetAccessEfuse.u4Address = + prSetAccessEfuseInfo->u4Address; + rCmdSetAccessEfuse.u4Valid = prSetAccessEfuseInfo->u4Valid; + + DBGLOG(INIT, INFO, + "MT6632 : wlanoidQueryProcessAccessEfuseWrite, address=%d\n", + rCmdSetAccessEfuse.u4Address); + + + kalMemCopy(rCmdSetAccessEfuse.aucData, + prSetAccessEfuseInfo->aucData, + sizeof(uint8_t) * 16); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_EFUSE_ACCESS, + TRUE, /* Query Bit: True->write False->read*/ + TRUE, + g_fgIsOid, + NULL, /* No Tx done function wait until fw ack */ + nicOidCmdTimeoutCommon, + sizeof(struct CMD_ACCESS_EFUSE), + (uint8_t *) (&rCmdSetAccessEfuse), pvSetBuffer, + u4SetBufferLen); + + return rWlanStatus; +} + + + + +uint32_t +wlanoidQueryEfuseFreeBlock(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_EFUSE_FREE_BLOCK + *prGetEfuseFreeBlockInfo; + struct CMD_EFUSE_FREE_BLOCK rCmdGetEfuseFreeBlock; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryEfuseFreeBlock"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct + PARAM_CUSTOM_EFUSE_FREE_BLOCK); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_EFUSE_FREE_BLOCK)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prGetEfuseFreeBlockInfo = (struct + PARAM_CUSTOM_EFUSE_FREE_BLOCK *) pvSetBuffer; + + kalMemSet(&rCmdGetEfuseFreeBlock, 0, + sizeof(struct CMD_EFUSE_FREE_BLOCK)); + + rCmdGetEfuseFreeBlock.ucVersion = 1;/*1:new version, 0:old version*/ + rCmdGetEfuseFreeBlock.ucDieIndex = 0;/*0:D Die, 1: A die */ + + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_EFUSE_FREE_BLOCK, + FALSE, /* Query Bit: True->write False->read */ + TRUE, + g_fgIsOid, + NULL, /* No Tx done function wait until fw ack */ + nicOidCmdTimeoutCommon, + sizeof(struct CMD_EFUSE_FREE_BLOCK), + (uint8_t *) (&rCmdGetEfuseFreeBlock), pvSetBuffer, + u4SetBufferLen); + + return rWlanStatus; +} + +uint32_t +wlanoidQueryGetTxPower(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_GET_TX_POWER *prGetTxPowerInfo; + struct CMD_GET_TX_POWER rCmdGetTxPower; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryGetTxPower"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CUSTOM_GET_TX_POWER *); + + if (u4SetBufferLen < sizeof(struct PARAM_CUSTOM_GET_TX_POWER + *)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prGetTxPowerInfo = (struct PARAM_CUSTOM_GET_TX_POWER *) + pvSetBuffer; + + kalMemSet(&rCmdGetTxPower, 0, + sizeof(struct CMD_GET_TX_POWER)); + + rCmdGetTxPower.ucTxPwrType = EXT_EVENT_TARGET_TX_POWER; + rCmdGetTxPower.ucCenterChannel = + prGetTxPowerInfo->ucCenterChannel; + rCmdGetTxPower.ucDbdcIdx = prGetTxPowerInfo->ucDbdcIdx; + rCmdGetTxPower.ucBand = prGetTxPowerInfo->ucBand; + + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_GET_TX_POWER, + FALSE, /* Query Bit: True->write False->read*/ + TRUE, + g_fgIsOid, + NULL, /* No Tx done function wait until fw ack */ + nicOidCmdTimeoutCommon, + sizeof(struct CMD_GET_TX_POWER), + (uint8_t *) (&rCmdGetTxPower), + pvSetBuffer, u4SetBufferLen); + + return rWlanStatus; +} + + +/*#endif*/ + +#endif /* CFG_SUPPORT_BUFFER_MODE */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to query RX statistics. + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryRxStatistics(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_CUSTOM_ACCESS_RX_STAT *prRxStatistics; + struct CMD_ACCESS_RX_STAT *prCmdAccessRxStat; + struct CMD_ACCESS_RX_STAT rCmdAccessRxStat; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + /* UINT_32 u4MemSize = PARAM_MEM_DUMP_MAX_SIZE; */ + uint32_t u4SeqNum = 0; + uint32_t u4TotalNum = 0; + + prCmdAccessRxStat = &rCmdAccessRxStat; + + DEBUGFUNC("wlanoidQueryRxStatistics"); + DBGLOG(INIT, LOUD, "\n"); + + DBGLOG(INIT, ERROR, "MT6632 : wlanoidQueryRxStatistics\n"); + + prRxStatistics = (struct PARAM_CUSTOM_ACCESS_RX_STAT *) + pvQueryBuffer; + + *pu4QueryInfoLen = 8 + prRxStatistics->u4TotalNum; + + u4SeqNum = prRxStatistics->u4SeqNum; + u4TotalNum = prRxStatistics->u4TotalNum; + + do { + prCmdAccessRxStat->u4SeqNum = u4SeqNum; + prCmdAccessRxStat->u4TotalNum = u4TotalNum; + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_RX_STAT, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventQueryRxStatistics, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_ACCESS_RX_STAT), + (uint8_t *) prCmdAccessRxStat, pvQueryBuffer, + u4QueryBufferLen); + } while (FALSE); + + return rStatus; +} + +#if CFG_SUPPORT_TX_BF + +uint32_t +wlanoidStaRecUpdate(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct CMD_STAREC_UPDATE *prStaRecUpdateInfo; + struct STAREC_COMMON *prStaRecCmm; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidStaRecUpdate"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct STAREC_COMMON); + if (u4SetBufferLen < sizeof(struct STAREC_COMMON)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prStaRecUpdateInfo = + (struct CMD_STAREC_UPDATE *) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, (CMD_STAREC_UPDATE_HDR_SIZE + + u4SetBufferLen)); + if (!prStaRecUpdateInfo) { + DBGLOG(INIT, ERROR, + "Allocate P_CMD_DEV_INFO_UPDATE_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* fix me: configurable ucBssIndex */ + prStaRecCmm = (struct STAREC_COMMON *) pvSetBuffer; + prStaRecUpdateInfo->ucBssIndex = 0; + prStaRecUpdateInfo->ucWlanIdx = prStaRecCmm->u2Reserve1; + prStaRecUpdateInfo->u2TotalElementNum = 1; + kalMemCopy(prStaRecUpdateInfo->aucBuffer, pvSetBuffer, + u4SetBufferLen); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_STAREC_UPDATE, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + (CMD_STAREC_UPDATE_HDR_SIZE + u4SetBufferLen), + (uint8_t *) prStaRecUpdateInfo, NULL, 0); + + cnmMemFree(prAdapter, prStaRecUpdateInfo); + + return rWlanStatus; +} + +uint32_t +wlanoidStaRecBFUpdate(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct CMD_STAREC_UPDATE *prStaRecUpdateInfo; + struct CMD_STAREC_BF *prStaRecBF; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidStaRecBFUpdate"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct CMD_STAREC_BF); + if (u4SetBufferLen < sizeof(struct CMD_STAREC_BF)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prStaRecUpdateInfo = + (struct CMD_STAREC_UPDATE *) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, (CMD_STAREC_UPDATE_HDR_SIZE + + u4SetBufferLen)); + if (!prStaRecUpdateInfo) { + DBGLOG(INIT, ERROR, + "Allocate P_CMD_DEV_INFO_UPDATE_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* fix me: configurable ucBssIndex */ + prStaRecBF = (struct CMD_STAREC_BF *) pvSetBuffer; + prStaRecUpdateInfo->ucBssIndex = prStaRecBF->ucReserved[0]; + prStaRecUpdateInfo->ucWlanIdx = prStaRecBF->ucReserved[1]; + prStaRecUpdateInfo->u2TotalElementNum = 1; + kalMemCopy(prStaRecUpdateInfo->aucBuffer, pvSetBuffer, + u4SetBufferLen); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_STAREC_UPDATE, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + (CMD_STAREC_UPDATE_HDR_SIZE + u4SetBufferLen), + (uint8_t *) prStaRecUpdateInfo, NULL, 0); + + cnmMemFree(prAdapter, prStaRecUpdateInfo); + + return rWlanStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief extend command packet generation utility + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] ucCID Command ID + * \param[in] ucExtCID Extend 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanSendSetQueryExtCmd(IN struct ADAPTER *prAdapter, + uint8_t ucCID, + uint8_t ucExtCID, + u_int8_t fgSetQuery, + u_int8_t fgNeedResp, + u_int8_t fgIsOid, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + uint32_t u4SetQueryInfoLen, + uint8_t *pucInfoBuffer, OUT void *pvSetQueryBuffer, + IN uint32_t u4SetQueryBufferLen) { + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + struct WIFI_CMD *prWifiCmd; + uint8_t 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->u2InfoBufLen = (uint16_t) (CMD_HDR_SIZE + + u4SetQueryInfoLen); + prCmdInfo->pfCmdDoneHandler = pfCmdDoneHandler; + prCmdInfo->pfCmdTimeoutHandler = pfCmdTimeoutHandler; + prCmdInfo->fgIsOid = fgIsOid; + prCmdInfo->ucCID = ucCID; + prCmdInfo->fgSetQuery = fgSetQuery; + prCmdInfo->fgNeedResp = fgNeedResp; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u4SetQueryInfoLen; + prCmdInfo->pvInformationBuffer = pvSetQueryBuffer; + prCmdInfo->u4InformationBufferLength = u4SetQueryBufferLen; + + /* Setup WIFI_CMD_T (no payload) */ + prWifiCmd = (struct WIFI_CMD *) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->u2Length = prCmdInfo->u2InfoBufLen - + (uint16_t) OFFSET_OF(struct WIFI_CMD, u2Length); + prWifiCmd->u2PqId = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucExtenCID = ucExtCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + if (u4SetQueryInfoLen > 0 && pucInfoBuffer != NULL) + kalMemCopy(prWifiCmd->aucBuffer, pucInfoBuffer, + u4SetQueryInfoLen); + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, + (struct QUE_ENTRY *) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + return WLAN_STATUS_PENDING; +} + +uint32_t +wlanoidBssInfoBasic(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct CMD_BSS_INFO_UPDATE *prBssInfoUpdateBasic; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidManualAssoc"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct BSSINFO_BASIC); + if (u4SetBufferLen < sizeof(struct BSSINFO_BASIC)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prBssInfoUpdateBasic = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + (CMD_BSSINFO_UPDATE_HDR_SIZE + u4SetBufferLen)); + if (!prBssInfoUpdateBasic) { + DBGLOG(INIT, ERROR, + "Allocate P_CMD_DEV_INFO_UPDATE_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* fix me: configurable ucBssIndex */ + prBssInfoUpdateBasic->ucBssIndex = 0; + prBssInfoUpdateBasic->u2TotalElementNum = 1; + kalMemCopy(prBssInfoUpdateBasic->aucBuffer, pvSetBuffer, + u4SetBufferLen); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_BSSINFO_UPDATE, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + (CMD_BSSINFO_UPDATE_HDR_SIZE + u4SetBufferLen), + (uint8_t *) prBssInfoUpdateBasic, NULL, 0); + + cnmMemFree(prAdapter, prBssInfoUpdateBasic); + + return rWlanStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to do Coex Isolation Detection. + +* \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, +* eturns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryCoexIso(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + struct PARAM_COEX_HANDLER *prParaCoexHandler; + struct PARAM_COEX_ISO_DETECT *prParaCoexIsoDetect; + struct CMD_COEX_HANDLER rCmdCoexHandler; + struct CMD_COEX_ISO_DETECT rCmdCoexIsoDetect; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct PARAM_COEX_HANDLER); + + if (u4QueryBufferLen < sizeof(struct PARAM_COEX_HANDLER)) + return WLAN_STATUS_INVALID_LENGTH; + + prParaCoexHandler = + (struct PARAM_COEX_HANDLER *) pvQueryBuffer; + prParaCoexIsoDetect = + (struct PARAM_COEX_ISO_DETECT *) &prParaCoexHandler->aucBuffer[0]; + + rCmdCoexIsoDetect.u4Channel = prParaCoexIsoDetect->u4Channel; + rCmdCoexIsoDetect.u4IsoPath = prParaCoexIsoDetect->u4IsoPath; + rCmdCoexIsoDetect.u4Isolation = prParaCoexIsoDetect->u4Isolation; + + rCmdCoexHandler.u4SubCmd = prParaCoexHandler->u4SubCmd; + + /* Copy Memory */ + kalMemCopy(rCmdCoexHandler.aucBuffer, + &rCmdCoexIsoDetect, + sizeof(rCmdCoexIsoDetect)); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_COEX_CTRL, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryCoexIso, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_COEX_HANDLER), + (unsigned char *) &rCmdCoexHandler, + pvQueryBuffer, + u4QueryBufferLen); + +} + +uint32_t +wlanoidQueryCoexGetInfo(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + struct PARAM_COEX_HANDLER *prParaCoexHandler; + struct PARAM_COEX_GET_INFO *prParaCoexGetInfo; + struct CMD_COEX_HANDLER rCmdCoexHandler; + struct CMD_COEX_GET_INFO rCmdCoexGetInfo; + + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct PARAM_COEX_HANDLER); + + if (u4QueryBufferLen < sizeof(struct PARAM_COEX_HANDLER)) + return WLAN_STATUS_INVALID_LENGTH; + + prParaCoexHandler = + (struct PARAM_COEX_HANDLER *)pvQueryBuffer; + prParaCoexGetInfo = + (struct PARAM_COEX_GET_INFO *)&prParaCoexHandler->aucBuffer[0]; + + kalMemZero(rCmdCoexGetInfo.ucCoexInfo, + sizeof(rCmdCoexGetInfo.ucCoexInfo)); + + rCmdCoexHandler.u4SubCmd = prParaCoexHandler->u4SubCmd; + + /* Copy Memory */ + kalMemCopy(rCmdCoexHandler.aucBuffer, + &rCmdCoexGetInfo, + sizeof(struct CMD_COEX_GET_INFO)); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_COEX_CTRL, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventQueryCoexGetInfo, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_COEX_HANDLER), + (unsigned char *) &rCmdCoexHandler, + pvQueryBuffer, + u4QueryBufferLen); +} + +uint32_t +wlanoidDevInfoActive(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct CMD_DEV_INFO_UPDATE *prDevInfoUpdateActive; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidManualAssoc"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct CMD_DEVINFO_ACTIVE); + if (u4SetBufferLen < sizeof(struct CMD_DEVINFO_ACTIVE)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prDevInfoUpdateActive = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + (CMD_DEVINFO_UPDATE_HDR_SIZE + u4SetBufferLen)); + if (!prDevInfoUpdateActive) { + DBGLOG(INIT, ERROR, + "Allocate P_CMD_DEV_INFO_UPDATE_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* fix me: configurable ucOwnMacIdx */ + prDevInfoUpdateActive->ucOwnMacIdx = 0; + prDevInfoUpdateActive->ucAppendCmdTLV = 0; + prDevInfoUpdateActive->u2TotalElementNum = 1; + kalMemCopy(prDevInfoUpdateActive->aucBuffer, pvSetBuffer, + u4SetBufferLen); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_DEVINFO_UPDATE, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + (CMD_DEVINFO_UPDATE_HDR_SIZE + u4SetBufferLen), + (uint8_t *) prDevInfoUpdateActive, NULL, 0); + + cnmMemFree(prAdapter, prDevInfoUpdateActive); + + return rWlanStatus; +} + +uint32_t +wlanoidManualAssoc(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct CMD_STAREC_UPDATE *prStaRecManualAssoc; + struct CMD_MANUAL_ASSOC_STRUCT *prManualAssoc; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidManualAssoc"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct CMD_STAREC_UPDATE); + if (u4SetBufferLen < sizeof(struct CMD_STAREC_UPDATE)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prStaRecManualAssoc = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + (CMD_STAREC_UPDATE_HDR_SIZE + u4SetBufferLen)); + if (!prStaRecManualAssoc) { + DBGLOG(INIT, ERROR, + "Allocate P_CMD_STAREC_UPDATE_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prManualAssoc = (struct CMD_MANUAL_ASSOC_STRUCT *) + pvSetBuffer; + prStaRecManualAssoc->ucWlanIdx = prManualAssoc->ucWtbl; + prStaRecManualAssoc->ucBssIndex = prManualAssoc->ucOwnmac; + prStaRecManualAssoc->u2TotalElementNum = 1; + kalMemCopy(prStaRecManualAssoc->aucBuffer, pvSetBuffer, + u4SetBufferLen); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_STAREC_UPDATE, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + (CMD_STAREC_UPDATE_HDR_SIZE + u4SetBufferLen), + (uint8_t *) prStaRecManualAssoc, NULL, 0); + + cnmMemFree(prAdapter, prStaRecManualAssoc); + + return rWlanStatus; +} + +struct TXBF_CMD_DONE_HANDLER { + uint32_t u4TxBfCmdId; + void (*pFunc)(struct ADAPTER *, struct CMD_INFO *, + uint8_t *); +}; + +struct TXBF_CMD_DONE_HANDLER rTxBfCmdDoneHandler[] = { + {BF_SOUNDING_OFF, nicCmdEventSetCommon}, + {BF_SOUNDING_ON, nicCmdEventSetCommon}, + {BF_DATA_PACKET_APPLY, nicCmdEventSetCommon}, + {BF_PFMU_MEM_ALLOCATE, nicCmdEventSetCommon}, + {BF_PFMU_MEM_RELEASE, nicCmdEventSetCommon}, + {BF_PFMU_TAG_READ, nicCmdEventPfmuTagRead}, + {BF_PFMU_TAG_WRITE, nicCmdEventSetCommon}, + {BF_PROFILE_READ, nicCmdEventPfmuDataRead}, + {BF_PROFILE_WRITE, nicCmdEventSetCommon}, + {BF_PN_READ, nicCmdEventSetCommon}, + {BF_PN_WRITE, nicCmdEventSetCommon}, + {BF_PFMU_MEM_ALLOC_MAP_READ, nicCmdEventSetCommon}, +#if CFG_SUPPORT_TX_BF_FPGA + {BF_PFMU_SW_TAG_WRITE, nicCmdEventSetCommon} +#endif +}; + +uint32_t +wlanoidTxBfAction(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + union PARAM_CUSTOM_TXBF_ACTION_STRUCT *prTxBfActionInfo; + union CMD_TXBF_ACTION rCmdTxBfActionInfo; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + u_int8_t fgSetQuery, fgNeedResp; + uint32_t u4TxBfCmdId; + uint8_t ucIdx; + + DEBUGFUNC("wlanoidTxBfAction"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(union + PARAM_CUSTOM_TXBF_ACTION_STRUCT); + + if (u4SetBufferLen < sizeof(union + PARAM_CUSTOM_TXBF_ACTION_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prTxBfActionInfo = (union PARAM_CUSTOM_TXBF_ACTION_STRUCT *) + pvSetBuffer; + + memcpy(&rCmdTxBfActionInfo, prTxBfActionInfo, + sizeof(union CMD_TXBF_ACTION)); + + u4TxBfCmdId = + rCmdTxBfActionInfo.rProfileTagRead.ucTxBfCategory; + if (TXBF_CMD_NEED_TO_RESPONSE(u4TxBfCmdId) == + 0) { /* don't need response */ + fgSetQuery = TRUE; + fgNeedResp = FALSE; + } else { + fgSetQuery = FALSE; + fgNeedResp = TRUE; + } + + for (ucIdx = 0; ucIdx < ARRAY_SIZE(rTxBfCmdDoneHandler); + ucIdx++) { + if (u4TxBfCmdId == rTxBfCmdDoneHandler[ucIdx].u4TxBfCmdId) + break; + } + + if (ucIdx == ARRAY_SIZE(rTxBfCmdDoneHandler)) { + DBGLOG(RFTEST, ERROR, + "ucIdx [%d] overrun of rTxBfCmdDoneHandler\n", ucIdx); + return WLAN_STATUS_NOT_SUPPORTED; + } + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_BF_ACTION, + fgSetQuery, + fgNeedResp, + g_fgIsOid, + rTxBfCmdDoneHandler[ucIdx].pFunc, + nicOidCmdTimeoutCommon, + sizeof(union CMD_TXBF_ACTION), + (uint8_t *) &rCmdTxBfActionInfo, + pvSetBuffer, + u4SetBufferLen); + + return rWlanStatus; +} + +#if CFG_SUPPORT_MU_MIMO +uint32_t +wlanoidMuMimoAction(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT + *prMuMimoActionInfo; + union CMD_MUMIMO_ACTION rCmdMuMimoActionInfo; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + u_int8_t fgSetQuery, fgNeedResp; + uint32_t u4MuMimoCmdId; + void (*pFunc)(struct ADAPTER *, struct CMD_INFO *, + uint8_t *); + + DEBUGFUNC("wlanoidMuMimoAction"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prMuMimoActionInfo = (struct + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT *) pvSetBuffer; + + memcpy(&rCmdMuMimoActionInfo, prMuMimoActionInfo, + sizeof(union CMD_MUMIMO_ACTION)); + + u4MuMimoCmdId = rCmdMuMimoActionInfo.ucMuMimoCategory; + if (MU_CMD_NEED_TO_RESPONSE(u4MuMimoCmdId) == 0) { + fgSetQuery = TRUE; + fgNeedResp = FALSE; + } else { + fgSetQuery = FALSE; + fgNeedResp = TRUE; + } + + pFunc = nicCmdEventSetCommon; + if (u4MuMimoCmdId == MU_HQA_GET_QD) + pFunc = nicCmdEventGetQd; + else if (u4MuMimoCmdId == MU_HQA_GET_CALC_LQ) + pFunc = nicCmdEventGetCalcLq; + else if (u4MuMimoCmdId == MU_GET_CALC_INIT_MCS) + pFunc = nicCmdEventGetCalcInitMcs; + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_MU_CTRL, + fgSetQuery, + fgNeedResp, + g_fgIsOid, + pFunc, + nicOidCmdTimeoutCommon, + sizeof(union CMD_MUMIMO_ACTION), + (uint8_t *) &rCmdMuMimoActionInfo, + pvSetBuffer, + u4SetBufferLen); + + return rWlanStatus; +} +#endif /* CFG_SUPPORT_MU_MIMO */ +#endif /* CFG_SUPPORT_TX_BF */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Trigger FW Cal for Backup Cal Data to Host + * Side. + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetCalBackup(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct PARAM_CAL_BACKUP_STRUCT_V2 *prCalBackupDataV2Info; + + DBGLOG(RFTEST, INFO, "%s\n", __func__); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CAL_BACKUP_STRUCT_V2); + + if (u4SetBufferLen < sizeof(struct + PARAM_CAL_BACKUP_STRUCT_V2)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prCalBackupDataV2Info = (struct PARAM_CAL_BACKUP_STRUCT_V2 + *) pvSetBuffer; + + if (prCalBackupDataV2Info->ucReason == 1 + && prCalBackupDataV2Info->ucAction == 2) { + /* Trigger All Cal Function */ + return wlanoidSendCalBackupV2Cmd(prAdapter, pvSetBuffer, + u4SetBufferLen); + } else if (prCalBackupDataV2Info->ucReason == 4 + && prCalBackupDataV2Info->ucAction == 6) { + /* For Debug Use, Tell FW Print Cal Data (Rom or Ram) */ + return wlanoidSendCalBackupV2Cmd(prAdapter, pvSetBuffer, + u4SetBufferLen); + } else if (prCalBackupDataV2Info->ucReason == 3 + && prCalBackupDataV2Info->ucAction == 5) { + /* Send Cal Data to FW */ + if (prCalBackupDataV2Info->ucRomRam == 0) + prCalBackupDataV2Info->u4RemainLength = + g_rBackupCalDataAllV2.u4ValidRomCalDataLength; + else if (prCalBackupDataV2Info->ucRomRam == 1) + prCalBackupDataV2Info->u4RemainLength = + g_rBackupCalDataAllV2.u4ValidRamCalDataLength; + + return wlanoidSendCalBackupV2Cmd(prAdapter, pvSetBuffer, + u4SetBufferLen); + } + + return rWlanStatus; +} + +uint32_t wlanoidSendCalBackupV2Cmd(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen) { + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct PARAM_CAL_BACKUP_STRUCT_V2 *prCalBackupDataV2Info; + struct CMD_CAL_BACKUP_STRUCT_V2 *prCmdCalBackupDataV2; + uint8_t ucReason, ucAction, ucNeedResp, ucFragNum, ucRomRam; + uint32_t u4DumpMaxSize = PARAM_CAL_DATA_DUMP_MAX_SIZE; + uint32_t u4RemainLength, u4CurrAddr, u4CurrLen; + + DBGLOG(RFTEST, INFO, "%s\n", __func__); + + prCmdCalBackupDataV2 = (struct CMD_CAL_BACKUP_STRUCT_V2 *) + kalMemAlloc(sizeof(struct CMD_CAL_BACKUP_STRUCT_V2), + VIR_MEM_TYPE); + + prCalBackupDataV2Info = (struct PARAM_CAL_BACKUP_STRUCT_V2 *) + pvQueryBuffer; + + ucReason = prCalBackupDataV2Info->ucReason; + ucAction = prCalBackupDataV2Info->ucAction; + ucNeedResp = prCalBackupDataV2Info->ucNeedResp; + ucRomRam = prCalBackupDataV2Info->ucRomRam; + + if (ucAction == 2) { + /* Trigger All Cal Function */ + prCmdCalBackupDataV2->ucReason = ucReason; + prCmdCalBackupDataV2->ucAction = ucAction; + prCmdCalBackupDataV2->ucNeedResp = ucNeedResp; + prCmdCalBackupDataV2->ucFragNum = + prCalBackupDataV2Info->ucFragNum; + prCmdCalBackupDataV2->ucRomRam = ucRomRam; + prCmdCalBackupDataV2->u4ThermalValue = + prCalBackupDataV2Info->u4ThermalValue; + prCmdCalBackupDataV2->u4Address = + prCalBackupDataV2Info->u4Address; + prCmdCalBackupDataV2->u4Length = + prCalBackupDataV2Info->u4Length; + prCmdCalBackupDataV2->u4RemainLength = + prCalBackupDataV2Info->u4RemainLength; +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST_DBGLOG + DBGLOG(RFTEST, INFO, + "=========== Driver Send Query CMD#0 or CMD#1 (Info) ===========\n"); + DBGLOG(RFTEST, INFO, "Reason = %d\n", + prCmdCalBackupDataV2->ucReason); + DBGLOG(RFTEST, INFO, "Action = %d\n", + prCmdCalBackupDataV2->ucAction); + DBGLOG(RFTEST, INFO, "NeedResp = %d\n", + prCmdCalBackupDataV2->ucNeedResp); + DBGLOG(RFTEST, INFO, "FragNum = %d\n", + prCmdCalBackupDataV2->ucFragNum); + DBGLOG(RFTEST, INFO, "RomRam = %d\n", + prCmdCalBackupDataV2->ucRomRam); + DBGLOG(RFTEST, INFO, "ThermalValue = %d\n", + prCmdCalBackupDataV2->u4ThermalValue); + DBGLOG(RFTEST, INFO, "Address = 0x%08x\n", + prCmdCalBackupDataV2->u4Address); + DBGLOG(RFTEST, INFO, "Length = %d\n", + prCmdCalBackupDataV2->u4Length); + DBGLOG(RFTEST, INFO, "RemainLength = %d\n", + prCmdCalBackupDataV2->u4RemainLength); + DBGLOG(RFTEST, INFO, + "================================================================\n"); +#endif + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_CAL_BACKUP_IN_HOST_V2, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + NULL, + sizeof(struct CMD_CAL_BACKUP_STRUCT_V2), + (uint8_t *) prCmdCalBackupDataV2, + pvQueryBuffer, + u4QueryBufferLen); + + kalMemFree(prCmdCalBackupDataV2, VIR_MEM_TYPE, + sizeof(struct CMD_CAL_BACKUP_STRUCT_V2)); + } else if (ucAction == 0 || ucAction == 1 + || ucAction == 6) { + /* Query CMD#0 and CMD#1. */ + /* For Thermal Value and Total Cal Data Length. */ + prCmdCalBackupDataV2->ucReason = ucReason; + prCmdCalBackupDataV2->ucAction = ucAction; + prCmdCalBackupDataV2->ucNeedResp = ucNeedResp; + prCmdCalBackupDataV2->ucFragNum = + prCalBackupDataV2Info->ucFragNum; + prCmdCalBackupDataV2->ucRomRam = ucRomRam; + prCmdCalBackupDataV2->u4ThermalValue = + prCalBackupDataV2Info->u4ThermalValue; + prCmdCalBackupDataV2->u4Address = + prCalBackupDataV2Info->u4Address; + prCmdCalBackupDataV2->u4Length = + prCalBackupDataV2Info->u4Length; + prCmdCalBackupDataV2->u4RemainLength = + prCalBackupDataV2Info->u4RemainLength; +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST_DBGLOG + DBGLOG(RFTEST, INFO, + "=========== Driver Send Query CMD#0 or CMD#1 (Info) ===========\n"); + DBGLOG(RFTEST, INFO, "Reason = %d\n", + prCmdCalBackupDataV2->ucReason); + DBGLOG(RFTEST, INFO, "Action = %d\n", + prCmdCalBackupDataV2->ucAction); + DBGLOG(RFTEST, INFO, "NeedResp = %d\n", + prCmdCalBackupDataV2->ucNeedResp); + DBGLOG(RFTEST, INFO, "FragNum = %d\n", + prCmdCalBackupDataV2->ucFragNum); + DBGLOG(RFTEST, INFO, "RomRam = %d\n", + prCmdCalBackupDataV2->ucRomRam); + DBGLOG(RFTEST, INFO, "ThermalValue = %d\n", + prCmdCalBackupDataV2->u4ThermalValue); + DBGLOG(RFTEST, INFO, "Address = 0x%08x\n", + prCmdCalBackupDataV2->u4Address); + DBGLOG(RFTEST, INFO, "Length = %d\n", + prCmdCalBackupDataV2->u4Length); + DBGLOG(RFTEST, INFO, "RemainLength = %d\n", + prCmdCalBackupDataV2->u4RemainLength); + DBGLOG(RFTEST, INFO, + "================================================================\n"); +#endif + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_CAL_BACKUP_IN_HOST_V2, + FALSE, + TRUE, + FALSE, + nicCmdEventQueryCalBackupV2, + NULL, + sizeof(struct CMD_CAL_BACKUP_STRUCT_V2), + (uint8_t *) prCmdCalBackupDataV2, + pvQueryBuffer, + u4QueryBufferLen); + + kalMemFree(prCmdCalBackupDataV2, VIR_MEM_TYPE, + sizeof(struct CMD_CAL_BACKUP_STRUCT_V2)); + } else if (ucAction == 4) { + /* Query All Cal Data from FW (Rom or Ram). */ + u4RemainLength = prCalBackupDataV2Info->u4RemainLength; + u4CurrAddr = prCalBackupDataV2Info->u4Address + + prCalBackupDataV2Info->u4Length; + ucFragNum = prCalBackupDataV2Info->ucFragNum + 1; + + if (u4RemainLength > u4DumpMaxSize) { + u4CurrLen = u4DumpMaxSize; + u4RemainLength -= u4DumpMaxSize; + } else { + u4CurrLen = u4RemainLength; + u4RemainLength = 0; + } + + prCmdCalBackupDataV2->ucReason = ucReason; + prCmdCalBackupDataV2->ucAction = ucAction; + prCmdCalBackupDataV2->ucNeedResp = ucNeedResp; + prCmdCalBackupDataV2->ucFragNum = ucFragNum; + prCmdCalBackupDataV2->ucRomRam = ucRomRam; + prCmdCalBackupDataV2->u4ThermalValue = + prCalBackupDataV2Info->u4ThermalValue; + prCmdCalBackupDataV2->u4Address = u4CurrAddr; + prCmdCalBackupDataV2->u4Length = u4CurrLen; + prCmdCalBackupDataV2->u4RemainLength = u4RemainLength; +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST_DBGLOG + DBGLOG(RFTEST, INFO, + "========= Driver Send Query All Cal Data from FW (Info) =========\n"); + DBGLOG(RFTEST, INFO, "Reason = %d\n", + prCmdCalBackupDataV2->ucReason); + DBGLOG(RFTEST, INFO, "Action = %d\n", + prCmdCalBackupDataV2->ucAction); + DBGLOG(RFTEST, INFO, "NeedResp = %d\n", + prCmdCalBackupDataV2->ucNeedResp); + DBGLOG(RFTEST, INFO, "FragNum = %d\n", + prCmdCalBackupDataV2->ucFragNum); + DBGLOG(RFTEST, INFO, "RomRam = %d\n", + prCmdCalBackupDataV2->ucRomRam); + DBGLOG(RFTEST, INFO, "ThermalValue = %d\n", + prCmdCalBackupDataV2->u4ThermalValue); + DBGLOG(RFTEST, INFO, "Address = 0x%08x\n", + prCmdCalBackupDataV2->u4Address); + DBGLOG(RFTEST, INFO, "Length = %d\n", + prCmdCalBackupDataV2->u4Length); + DBGLOG(RFTEST, INFO, "RemainLength = %d\n", + prCmdCalBackupDataV2->u4RemainLength); + DBGLOG(RFTEST, INFO, + "=================================================================\n"); +#endif + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_CAL_BACKUP_IN_HOST_V2, + FALSE, + TRUE, + FALSE, + nicCmdEventQueryCalBackupV2, + NULL, + sizeof(struct CMD_CAL_BACKUP_STRUCT_V2), + (uint8_t *) prCmdCalBackupDataV2, + pvQueryBuffer, + u4QueryBufferLen); + + kalMemFree(prCmdCalBackupDataV2, VIR_MEM_TYPE, + sizeof(struct CMD_CAL_BACKUP_STRUCT_V2)); + } else if (ucAction == 5) { + /* Send All Cal Data to FW (Rom or Ram). */ + u4RemainLength = prCalBackupDataV2Info->u4RemainLength; + u4CurrAddr = prCalBackupDataV2Info->u4Address + + prCalBackupDataV2Info->u4Length; + ucFragNum = prCalBackupDataV2Info->ucFragNum + 1; + + if (u4RemainLength > u4DumpMaxSize) { + u4CurrLen = u4DumpMaxSize; + u4RemainLength -= u4DumpMaxSize; + } else { + u4CurrLen = u4RemainLength; + u4RemainLength = 0; + } + + prCmdCalBackupDataV2->ucReason = ucReason; + prCmdCalBackupDataV2->ucAction = ucAction; + prCmdCalBackupDataV2->ucNeedResp = ucNeedResp; + prCmdCalBackupDataV2->ucFragNum = ucFragNum; + prCmdCalBackupDataV2->ucRomRam = ucRomRam; + prCmdCalBackupDataV2->u4ThermalValue = + prCalBackupDataV2Info->u4ThermalValue; + prCmdCalBackupDataV2->u4Address = u4CurrAddr; + prCmdCalBackupDataV2->u4Length = u4CurrLen; + prCmdCalBackupDataV2->u4RemainLength = u4RemainLength; +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST_DBGLOG + DBGLOG(RFTEST, INFO, + "========= Driver Send All Cal Data to FW (Info) =========\n"); + DBGLOG(RFTEST, INFO, "Reason = %d\n", + prCmdCalBackupDataV2->ucReason); + DBGLOG(RFTEST, INFO, "Action = %d\n", + prCmdCalBackupDataV2->ucAction); + DBGLOG(RFTEST, INFO, "NeedResp = %d\n", + prCmdCalBackupDataV2->ucNeedResp); + DBGLOG(RFTEST, INFO, "FragNum = %d\n", + prCmdCalBackupDataV2->ucFragNum); + DBGLOG(RFTEST, INFO, "RomRam = %d\n", + prCmdCalBackupDataV2->ucRomRam); + DBGLOG(RFTEST, INFO, "ThermalValue = %d\n", + prCmdCalBackupDataV2->u4ThermalValue); + DBGLOG(RFTEST, INFO, "Address = 0x%08x\n", + prCmdCalBackupDataV2->u4Address); + DBGLOG(RFTEST, INFO, "Length = %d\n", + prCmdCalBackupDataV2->u4Length); + DBGLOG(RFTEST, INFO, "RemainLength = %d\n", + prCmdCalBackupDataV2->u4RemainLength); +#endif + /* Copy Cal Data From Driver to FW */ + if (prCmdCalBackupDataV2->ucRomRam == 0) + kalMemCopy( + (uint8_t *)(prCmdCalBackupDataV2->au4Buffer), + (uint8_t *)(g_rBackupCalDataAllV2.au4RomCalData) + + prCmdCalBackupDataV2->u4Address, + prCmdCalBackupDataV2->u4Length); + else if (prCmdCalBackupDataV2->ucRomRam == 1) + kalMemCopy( + (uint8_t *)(prCmdCalBackupDataV2->au4Buffer), + (uint8_t *)(g_rBackupCalDataAllV2.au4RamCalData) + + prCmdCalBackupDataV2->u4Address, + prCmdCalBackupDataV2->u4Length); +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST_DBGLOG + DBGLOG(RFTEST, INFO, + "Check some of elements (0x%08x), (0x%08x), (0x%08x), (0x%08x), (0x%08x)\n", + prCmdCalBackupDataV2->au4Buffer[0], + prCmdCalBackupDataV2->au4Buffer[1], + prCmdCalBackupDataV2->au4Buffer[2], + prCmdCalBackupDataV2->au4Buffer[3], + prCmdCalBackupDataV2->au4Buffer[4]); + DBGLOG(RFTEST, INFO, + "Check some of elements (0x%08x), (0x%08x), (0x%08x), (0x%08x), (0x%08x)\n", + prCmdCalBackupDataV2->au4Buffer[( + prCmdCalBackupDataV2->u4Length + / sizeof(uint32_t)) - 5], + prCmdCalBackupDataV2->au4Buffer[( + prCmdCalBackupDataV2->u4Length + / sizeof(uint32_t)) - 4], + prCmdCalBackupDataV2->au4Buffer[( + prCmdCalBackupDataV2->u4Length + / sizeof(uint32_t)) - 3], + prCmdCalBackupDataV2->au4Buffer[( + prCmdCalBackupDataV2->u4Length + / sizeof(uint32_t)) - 2], + prCmdCalBackupDataV2->au4Buffer[( + prCmdCalBackupDataV2->u4Length + / sizeof(uint32_t)) - 1]); + + DBGLOG(RFTEST, INFO, + "=================================================================\n"); +#endif + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_CAL_BACKUP_IN_HOST_V2, + FALSE, + TRUE, + FALSE, + nicCmdEventQueryCalBackupV2, + NULL, + sizeof(struct CMD_CAL_BACKUP_STRUCT_V2), + (uint8_t *) prCmdCalBackupDataV2, + pvQueryBuffer, + u4QueryBufferLen); + + kalMemFree(prCmdCalBackupDataV2, VIR_MEM_TYPE, + sizeof(struct CMD_CAL_BACKUP_STRUCT_V2)); + } + + return rWlanStatus; +} + +uint32_t +wlanoidQueryCalBackupV2(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct PARAM_CAL_BACKUP_STRUCT_V2 *prCalBackupDataV2Info; + + DBGLOG(RFTEST, INFO, "%s\n", __func__); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct CMD_CAL_BACKUP_STRUCT_V2); + + prCalBackupDataV2Info = (struct PARAM_CAL_BACKUP_STRUCT_V2 + *) pvQueryBuffer; + + if (prCalBackupDataV2Info->ucReason == 0 + && prCalBackupDataV2Info->ucAction == 0) { + /* Get Thermal Temp from FW */ + return wlanoidSendCalBackupV2Cmd(prAdapter, pvQueryBuffer, + u4QueryBufferLen); + } else if (prCalBackupDataV2Info->ucReason == 0 + && prCalBackupDataV2Info->ucAction == 1) { + /* Get Cal Data Size from FW */ + return wlanoidSendCalBackupV2Cmd(prAdapter, pvQueryBuffer, + u4QueryBufferLen); + } else if (prCalBackupDataV2Info->ucReason == 2 + && prCalBackupDataV2Info->ucAction == 4) { + /* Get Cal Data from FW */ + if (prCalBackupDataV2Info->ucRomRam == 0) + prCalBackupDataV2Info->u4RemainLength = + g_rBackupCalDataAllV2.u4ValidRomCalDataLength; + else if (prCalBackupDataV2Info->ucRomRam == 1) + prCalBackupDataV2Info->u4RemainLength = + g_rBackupCalDataAllV2.u4ValidRamCalDataLength; + + return wlanoidSendCalBackupV2Cmd(prAdapter, pvQueryBuffer, + u4QueryBufferLen); + } else { + return rWlanStatus; + } +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryMcrRead(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_CUSTOM_MCR_RW_STRUCT *prMcrRdInfo; + struct CMD_ACCESS_REG rCmdAccessReg; + + DEBUGFUNC("wlanoidQueryMcrRead"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct + PARAM_CUSTOM_MCR_RW_STRUCT); + + if (u4QueryBufferLen < sizeof(struct + PARAM_CUSTOM_MCR_RW_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + prMcrRdInfo = (struct PARAM_CUSTOM_MCR_RW_STRUCT *) + pvQueryBuffer; + + /* 0x9000 - 0x9EFF reserved for FW */ +#if CFG_SUPPORT_SWCR + if ((prMcrRdInfo->u4McrOffset >> 16) == 0x9F00) { + swCrReadWriteCmd(prAdapter, SWCR_READ, + (uint16_t) (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, + g_fgIsOid, + nicCmdEventQueryMcrRead, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_ACCESS_REG), + (uint8_t *) &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 = %#08x, Data = %#08x\n", + prMcrRdInfo->u4McrOffset, prMcrRdInfo->u4McrData); + return WLAN_STATUS_SUCCESS; + } +} /* end of wlanoidQueryMcrRead() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to write MCR and enable specific function. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. + * \param[in] u4SetBufferLen The length of the set buffer. + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed + * due to invalid length of the set buffer, returns + * the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetMcrWrite(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_MCR_RW_STRUCT *prMcrWrInfo; + struct CMD_ACCESS_REG rCmdAccessReg; + +#if CFG_STRESS_TEST_SUPPORT + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prBssInfo = prAdapter->prAisBssInfo; + struct STA_RECORD *prStaRec = prBssInfo->prStaRecOfAP; + uint32_t u4McrOffset, u4McrData; +#endif + + DEBUGFUNC("wlanoidSetMcrWrite"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CUSTOM_MCR_RW_STRUCT); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_MCR_RW_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prMcrWrInfo = (struct PARAM_CUSTOM_MCR_RW_STRUCT *) + 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 ENUM_REGISTRY_FIXED_RATE) + (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 */ + } + } + + 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, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_ACCESS_REG), + (uint8_t *) &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, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_ACCESS_REG), + (uint8_t *) &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, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_ACCESS_REG), + (uint8_t *) &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, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_ACCESS_REG), + (uint8_t *) &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, + (uint16_t)(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) { + uint32_t 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, + (uint32_t) 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, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_ACCESS_REG), + (uint8_t *) &rCmdAccessReg, + pvSetBuffer, u4SetBufferLen); + } +#endif + +#if 1 + /* low power test special command */ + if (prMcrWrInfo->u4McrOffset == 0x11111110) { + uint32_t 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, + (uint32_t) 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, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_ACCESS_REG), + (uint8_t *) &rCmdAccessReg, + pvSetBuffer, u4SetBufferLen); + } +#endif + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN + if (prMcrWrInfo->u4McrOffset == 0x22220000) { + /* read test mode */ + kalSetSdioTestPattern(prAdapter->prGlueInfo, + TRUE, TRUE); + + return WLAN_STATUS_SUCCESS; + } + + if (prMcrWrInfo->u4McrOffset == 0x22220001) { + /* write test mode */ + kalSetSdioTestPattern(prAdapter->prGlueInfo, + TRUE, FALSE); + + return WLAN_STATUS_SUCCESS; + } + + if (prMcrWrInfo->u4McrOffset == 0x22220002) { + /* leave from test mode */ + kalSetSdioTestPattern(prAdapter->prGlueInfo, + FALSE, FALSE); + + return WLAN_STATUS_SUCCESS; + } +#endif + + /* fill command */ + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_ACCESS_REG), + (uint8_t *) &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 = %#08x, Data = %#08x\n", + prMcrWrInfo->u4McrOffset, + prMcrWrInfo->u4McrData); + + return WLAN_STATUS_SUCCESS; + } +} /* wlanoidSetMcrWrite */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to query driver 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryDrvMcrRead(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_CUSTOM_MCR_RW_STRUCT *prMcrRdInfo; + /* CMD_ACCESS_REG rCmdAccessReg; */ + + DEBUGFUNC("wlanoidQueryMcrRead"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct + PARAM_CUSTOM_MCR_RW_STRUCT); + + if (u4QueryBufferLen < sizeof(struct + PARAM_CUSTOM_MCR_RW_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + prMcrRdInfo = (struct PARAM_CUSTOM_MCR_RW_STRUCT *) + pvQueryBuffer; + + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + HAL_MCR_RD(prAdapter, (prMcrRdInfo->u4McrOffset & BITS(2, + 31)), &prMcrRdInfo->u4McrData); + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + + DBGLOG(INIT, TRACE, + "DRV MCR Read: Offset = %#08x, Data = %#08x\n", + prMcrRdInfo->u4McrOffset, prMcrRdInfo->u4McrData); + + return WLAN_STATUS_SUCCESS; + +} /* end of wlanoidQueryMcrRead() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to write MCR and enable specific function. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. + * \param[in] u4SetBufferLen The length of the set buffer. + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed + * due to invalid length of the set buffer, returns + * the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetDrvMcrWrite(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_MCR_RW_STRUCT *prMcrWrInfo; + /* CMD_ACCESS_REG rCmdAccessReg; */ + + DEBUGFUNC("wlanoidSetMcrWrite"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CUSTOM_MCR_RW_STRUCT); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_MCR_RW_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prMcrWrInfo = (struct PARAM_CUSTOM_MCR_RW_STRUCT *) + pvSetBuffer; + + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + HAL_MCR_WR(prAdapter, (prMcrWrInfo->u4McrOffset & BITS(2, + 31)), prMcrWrInfo->u4McrData); + + DBGLOG(INIT, TRACE, + "DRV MCR Write: Offset = %#08x, Data = %#08x\n", + prMcrWrInfo->u4McrOffset, prMcrWrInfo->u4McrData); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetMcrWrite */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to query SW CTRL + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[out] pvQueryBuf A pointer to the buffer that holds the result of + * the query. + * \param[in] u4QueryBufLen The length of the query buffer. + * \param[out] pu4QueryInfoLen If the call is successful, returns the number of + * bytes written into the query buffer. If the call + * failed due to invalid length of the query buffer, + * returns the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQuerySwCtrlRead(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_CUSTOM_SW_CTRL_STRUCT *prSwCtrlInfo; + uint32_t rWlanStatus; + uint16_t u2Id, u2SubId; + uint32_t u4Data; + + struct CMD_SW_DBG_CTRL rCmdSwCtrl; + + DEBUGFUNC("wlanoidQuerySwCtrlRead"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct + PARAM_CUSTOM_SW_CTRL_STRUCT); + + if (u4QueryBufferLen < sizeof(struct + PARAM_CUSTOM_SW_CTRL_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + prSwCtrlInfo = (struct PARAM_CUSTOM_SW_CTRL_STRUCT *) + pvQueryBuffer; + + u2Id = (uint16_t) (prSwCtrlInfo->u4Id >> 16); + u2SubId = (uint16_t) (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 */, + (uint16_t) u2SubId, &u4Data); + break; +#endif /* CFG_SUPPORT_SWCR */ + + case 0xFFFF: { + u4Data = 0x5AA56620; + } + break; + + case 0xBABA: + switch ((u2SubId >> 8) & BITS(0, 7)) { + case 0x00: + /* Dump Tx resource and queue status */ + qmDumpQueueStatus(prAdapter, NULL, 0); + cnmDumpMemoryStatus(prAdapter, NULL, 0); + break; + + case 0x01: + /* Dump StaRec info by index */ + cnmDumpStaRec(prAdapter, + (uint8_t) (u2SubId & BITS(0, 7))); + break; + + case 0x02: + /* Dump BSS info by index */ + bssDumpBssInfo(prAdapter, + (uint8_t) (u2SubId & BITS(0, 7))); + break; + + case 0x03: + /*Dump BSS statistics by index */ + wlanDumpBssStatistics(prAdapter, + (uint8_t) (u2SubId & BITS(0, 7))); + break; + + case 0x04: + halDumpHifStatus(prAdapter, NULL, 0); + break; + + default: + break; + } + + u4Data = 0xBABABABA; + break; + + case 0x9000: + default: { + rCmdSwCtrl.u4Id = prSwCtrlInfo->u4Id; + rCmdSwCtrl.u4Data = 0; + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventQuerySwCtrlRead, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_SW_DBG_CTRL), + (uint8_t *) &rCmdSwCtrl, + pvQueryBuffer, u4QueryBufferLen); + return rWlanStatus; + } + } /* 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetSwCtrlWrite(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_SW_CTRL_STRUCT *prSwCtrlInfo; + struct CMD_SW_DBG_CTRL rCmdSwCtrl; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + uint16_t u2Id, u2SubId; + uint32_t u4Data; + uint8_t ucNss; + uint8_t ucChannelWidth; + uint8_t ucBssIndex; + + DEBUGFUNC("wlanoidSetSwCtrlWrite"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CUSTOM_SW_CTRL_STRUCT); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_SW_CTRL_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prSwCtrlInfo = (struct PARAM_CUSTOM_SW_CTRL_STRUCT *) + pvSetBuffer; + + u2Id = (uint16_t) (prSwCtrlInfo->u4Id >> 16); + u2SubId = (uint16_t) (prSwCtrlInfo->u4Id & BITS(0, 15)); + u4Data = prSwCtrlInfo->u4Data; + + switch (u2Id) { + + /* 0x9000 - 0x9EFF reserved for FW */ + /* 0xFFFE reserved for FW */ + +#if CFG_SUPPORT_SWCR + case 0x9F00: + swCrReadWriteCmd(prAdapter, SWCR_WRITE, (uint16_t) u2SubId, + &u4Data); + break; +#endif /* CFG_SUPPORT_SWCR */ + + case 0x2222: + ucNss = (uint8_t)(u4Data & BITS(0, 3)); + ucChannelWidth = (uint8_t)((u4Data & BITS(4, 7)) >> 4); + ucBssIndex = (uint8_t) u2SubId; + + if ((u2SubId & BITS(8, 15)) != 0) { /* Debug OP change + * parameters + */ + DBGLOG(RLM, INFO, + "[UT_OP] BSS[%d] IsBwChange[%d] BW[%d] IsNssChange[%d] Nss[%d]\n", + ucBssIndex, + prAdapter->aprBssInfo[ucBssIndex]-> + fgIsOpChangeChannelWidth, + prAdapter->aprBssInfo[ucBssIndex]-> + ucOpChangeChannelWidth, + prAdapter->aprBssInfo[ucBssIndex]-> + fgIsOpChangeNss, + prAdapter->aprBssInfo[ucBssIndex]-> + ucOpChangeNss); + + DBGLOG(RLM, INFO, + "[UT_OP] current OP mode: w[%d] s1[%d] s2[%d] sco[%d] Nss[%d]\n", + prAdapter->aprBssInfo[ucBssIndex]-> + ucVhtChannelWidth, + prAdapter->aprBssInfo[ucBssIndex]-> + ucVhtChannelFrequencyS1, + prAdapter->aprBssInfo[ucBssIndex]-> + ucVhtChannelFrequencyS2, + prAdapter->aprBssInfo[ucBssIndex]-> + eBssSCO, + prAdapter->aprBssInfo[ucBssIndex]-> + ucNss); + } else { + /* ucChannelWidth 0:20MHz, 1:40MHz, 2:80MHz, 3:160MHz + * 4:80+80MHz + */ + DBGLOG(RLM, INFO, + "[UT_OP] Change BSS[%d] OpMode to BW[%d] Nss[%d]\n", + ucBssIndex, ucChannelWidth, ucNss); + rlmChangeOperationMode(prAdapter, ucBssIndex, + ucChannelWidth, ucNss, rlmDummyChangeOpHandler); + } + break; + + case 0x1000: + if (u2SubId == 0x8000) { + /* CTIA power save mode setting (code: 0x10008000) */ + prAdapter->u4CtiaPowerMode = u4Data; + prAdapter->fgEnCtiaPowerMode = TRUE; + + /* */ + { + enum PARAM_POWER_MODE ePowerMode; + + if (prAdapter->u4CtiaPowerMode == 0) + /* force to keep in CAM mode */ + ePowerMode = Param_PowerModeCAM; + else if (prAdapter->u4CtiaPowerMode == 1) + ePowerMode = Param_PowerModeMAX_PSP; + else + ePowerMode = Param_PowerModeFast_PSP; + + rWlanStatus = nicConfigPowerSaveProfile( + prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, + ePowerMode, g_fgIsOid, + PS_CALLER_SW_WRITE); + } + } + break; + case 0x1001: + if (u2SubId == 0x0) + prAdapter->fgEnOnlineScan = (u_int8_t) u4Data; + else if (u2SubId == 0x1) + prAdapter->fgDisBcnLostDetection = (u_int8_t) u4Data; + else if (u2SubId == 0x2) + prAdapter->rWifiVar.ucUapsd = (u_int8_t) u4Data; + else if (u2SubId == 0x3) { + prAdapter->u4UapsdAcBmp = u4Data & BITS(0, 15); + GET_BSS_INFO_BY_INDEX(prAdapter, + u4Data >> 16)->rPmProfSetupInfo.ucBmpDeliveryAC = + (uint8_t) prAdapter->u4UapsdAcBmp; + GET_BSS_INFO_BY_INDEX(prAdapter, + u4Data >> 16)->rPmProfSetupInfo.ucBmpTriggerAC = + (uint8_t) prAdapter->u4UapsdAcBmp; + } else if (u2SubId == 0x4) + prAdapter->fgDisStaAgingTimeoutDetection = + (u_int8_t) u4Data; + else if (u2SubId == 0x5) + prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode = + (uint8_t) u4Data; + else if (u2SubId == 0x0100) { + if (u4Data == 2) + prAdapter->rWifiVar.ucRxGf = FEATURE_DISABLED; + else + prAdapter->rWifiVar.ucRxGf = FEATURE_ENABLED; + } else if (u2SubId == 0x0101) + prAdapter->rWifiVar.ucRxShortGI = (uint8_t) u4Data; + else if (u2SubId == 0x0103) { /* AP Mode WMMPS */ + DBGLOG(OID, INFO, + "ApUapsd 0x10010103 cmd received: %d\n", + u4Data); + setApUapsdEnable(prAdapter, (u_int8_t) u4Data); + } else if (u2SubId == 0x0110) { + prAdapter->fgIsEnableLpdvt = (u_int8_t) u4Data; + prAdapter->fgEnOnlineScan = (u_int8_t) u4Data; + DBGLOG(INIT, INFO, "--- Enable LPDVT [%d] ---\n", + prAdapter->fgIsEnableLpdvt); + } + + break; + +#if CFG_SUPPORT_SWCR + case 0x1002: +#if CFG_RX_PKTS_DUMP + if (u2SubId == 0x0) { + if (u4Data) + u4Data = BIT(HIF_RX_PKT_TYPE_MANAGEMENT); + swCrFrameCheckEnable(prAdapter, u4Data); + } +#endif + if (u2SubId == 0x1) { + u_int8_t fgIsEnable; + uint8_t ucType; + uint32_t u4Timeout; + + fgIsEnable = (u_int8_t) (u4Data & 0xff); + ucType = 0; /* ((u4Data>>4) & 0xf); */ + u4Timeout = ((u4Data >> 8) & 0xff); + swCrDebugCheckEnable(prAdapter, fgIsEnable, ucType, + u4Timeout); + } + break; +#endif + case 0x1003: /* for debug switches */ + switch (u2SubId) { + case 1: + DBGLOG(OID, INFO, + "Enable VoE 5.7 Packet Jitter test\n"); + prAdapter->rDebugInfo.fgVoE5_7Test = !!u4Data; + break; + case 0x0002: + { + struct CMD_TX_AMPDU rTxAmpdu; + uint32_t rStatus; + + rTxAmpdu.fgEnable = !!u4Data; + + rStatus = wlanSendSetQueryCmd( + prAdapter, CMD_ID_TX_AMPDU, TRUE, FALSE, FALSE, + NULL, NULL, sizeof(struct CMD_TX_AMPDU), + (uint8_t *)&rTxAmpdu, NULL, 0); + DBGLOG(OID, INFO, "disable tx ampdu status %u\n", + rStatus); + break; + } + default: + break; + } + break; + +#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) { + struct BSS_INFO *prBssInfo = prAdapter->prAisBssInfo; + + authSendDeauthFrame(prAdapter, prBssInfo, + 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: %u\n", u4Data); + + if ((enum ENUM_REGISTRY_FIXED_RATE) (u4Data) < + FIXED_RATE_NUM) + prAdapter->rWifiVar.eRateSetting = + (enum ENUM_REGISTRY_FIXED_RATE)(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 */ + /* 3. Disable FIFO FULL no ack */ + /* 4. Disable Roaming */ + /* Disalbe auto tx power */ + /* 2. Keep at CAM mode */ + /* 5. Disable Beacon Timeout Detection */ + rWlanStatus = nicEnterCtiaMode(prAdapter, + TRUE, g_fgIsOid); + } else if (u2SubId == 0x1235) { + /* 1. Enaable On-Lin Scan */ + /* 3. Enable FIFO FULL no ack */ + /* 4. Enable Roaming */ + /* Enable auto tx power */ + /* 2. Keep at Fast PS */ + /* 5. Enable Beacon Timeout Detection */ + rWlanStatus = nicEnterCtiaMode(prAdapter, + FALSE, g_fgIsOid); + } else if (u2SubId == 0x1260) { + /* Disable On-Line Scan */ + rWlanStatus = nicEnterCtiaModeOfScan(prAdapter, + TRUE, TRUE); + } else if (u2SubId == 0x1261) { + /* Enable On-Line Scan */ + rWlanStatus = nicEnterCtiaModeOfScan(prAdapter, + FALSE, TRUE); + } else if (u2SubId == 0x1262) { + /* Disable Roaming */ + rWlanStatus = nicEnterCtiaModeOfRoaming(prAdapter, + TRUE, TRUE); + } else if (u2SubId == 0x1263) { + /* Enable Roaming */ + rWlanStatus = nicEnterCtiaModeOfRoaming(prAdapter, + FALSE, TRUE); + } else if (u2SubId == 0x1264) { + /* Keep at CAM mode */ + rWlanStatus = nicEnterCtiaModeOfCAM(prAdapter, + TRUE, g_fgIsOid); + } else if (u2SubId == 0x1265) { + /* Keep at Fast PS */ + rWlanStatus = nicEnterCtiaModeOfCAM(prAdapter, + FALSE, g_fgIsOid); + } else if (u2SubId == 0x1266) { + /* Disable Beacon Timeout Detection */ + rWlanStatus = nicEnterCtiaModeOfBCNTimeout(prAdapter, + TRUE, TRUE); + } else if (u2SubId == 0x1267) { + /* Enable Beacon Timeout Detection */ + rWlanStatus = nicEnterCtiaModeOfBCNTimeout(prAdapter, + FALSE, TRUE); + } else if (u2SubId == 0x1268) { + /* Disalbe auto tx power */ + rWlanStatus = nicEnterCtiaModeOfAutoTxPower(prAdapter, + TRUE, TRUE); + } else if (u2SubId == 0x1269) { + /* Enable auto tx power */ + rWlanStatus = nicEnterCtiaModeOfAutoTxPower(prAdapter, + FALSE, TRUE); + } else if (u2SubId == 0x1270) { + /* Disalbe FIFO FULL no ack */ + rWlanStatus = nicEnterCtiaModeOfFIFOFullNoAck(prAdapter, + TRUE, TRUE); + } else if (u2SubId == 0x1271) { + /* Enable FIFO FULL no ack */ + rWlanStatus = nicEnterCtiaModeOfFIFOFullNoAck(prAdapter, + FALSE, TRUE); + } +#endif +#if CFG_MTK_STAGE_SCAN + else if (u2SubId == 0x1250) + prAdapter->aePreferBand[KAL_NETWORK_TYPE_AIS_INDEX] = + BAND_NULL; + else if (u2SubId == 0x1251) + prAdapter->aePreferBand[KAL_NETWORK_TYPE_AIS_INDEX] = + BAND_2G4; + else if (u2SubId == 0x1252) { + if (prAdapter->fgEnable5GBand) + prAdapter->aePreferBand + [KAL_NETWORK_TYPE_AIS_INDEX] = BAND_5G; + else + /* Skip this setting if 5G band is disabled */ + DBGLOG(SCN, INFO, + "Skip 5G stage scan request due to 5G is disabled\n"); + } +#endif + } + break; + + case 0x9000: + default: { + rCmdSwCtrl.u4Id = prSwCtrlInfo->u4Id; + rCmdSwCtrl.u4Data = prSwCtrlInfo->u4Data; + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_SW_DBG_CTRL), + (uint8_t *) &rCmdSwCtrl, + pvSetBuffer, u4SetBufferLen); + } + } /* switch(u2Id) */ + + return rWlanStatus; +} /* wlanoidSetSwCtrlWrite */ + +uint32_t +wlanoidQueryChipConfig(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_CUSTOM_CHIP_CONFIG_STRUCT *prChipConfigInfo; + struct CMD_CHIP_CONFIG rCmdChipConfig; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQuerySwCtrlRead"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct + PARAM_CUSTOM_CHIP_CONFIG_STRUCT); + + if (u4QueryBufferLen < sizeof(struct + PARAM_CUSTOM_CHIP_CONFIG_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + prChipConfigInfo = (struct PARAM_CUSTOM_CHIP_CONFIG_STRUCT + *) pvQueryBuffer; + kalMemZero(&rCmdChipConfig, sizeof(rCmdChipConfig)); + + rCmdChipConfig.u2Id = prChipConfigInfo->u2Id; + rCmdChipConfig.ucType = prChipConfigInfo->ucType; + rCmdChipConfig.ucRespType = prChipConfigInfo->ucRespType; + rCmdChipConfig.u2MsgSize = prChipConfigInfo->u2MsgSize; + if (rCmdChipConfig.u2MsgSize > CHIP_CONFIG_RESP_SIZE) { + DBGLOG(REQ, INFO, + "Chip config Msg Size %u is not valid (query)\n", + rCmdChipConfig.u2MsgSize); + rCmdChipConfig.u2MsgSize = CHIP_CONFIG_RESP_SIZE; + } + kalMemCopy(rCmdChipConfig.aucCmd, prChipConfigInfo->aucCmd, + rCmdChipConfig.u2MsgSize); + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_CHIP_CONFIG, FALSE, + TRUE, g_fgIsOid, + /*nicCmdEventQuerySwCtrlRead, */ + nicCmdEventQueryChipConfig, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_CHIP_CONFIG), + (uint8_t *) &rCmdChipConfig, + pvQueryBuffer, + u4QueryBufferLen); + + return rWlanStatus; + +} + +/* end of wlanoidQueryChipConfig() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set chip + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. + * \param[in] u4SetBufferLen The length of the set buffer. + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed + * due to invalid length of the set buffer, returns + * the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetChipConfig(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_CHIP_CONFIG_STRUCT *prChipConfigInfo; + struct CMD_CHIP_CONFIG rCmdChipConfig; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DATA_STRUCT_INSPECTING_ASSERT( + sizeof(prChipConfigInfo->aucCmd) == CHIP_CONFIG_RESP_SIZE); + DEBUGFUNC("wlanoidSetChipConfig"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct + PARAM_CUSTOM_CHIP_CONFIG_STRUCT); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_CHIP_CONFIG_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prChipConfigInfo = (struct PARAM_CUSTOM_CHIP_CONFIG_STRUCT + *) pvSetBuffer; + kalMemZero(&rCmdChipConfig, sizeof(rCmdChipConfig)); + + rCmdChipConfig.u2Id = prChipConfigInfo->u2Id; + rCmdChipConfig.ucType = prChipConfigInfo->ucType; + rCmdChipConfig.ucRespType = prChipConfigInfo->ucRespType; + rCmdChipConfig.u2MsgSize = prChipConfigInfo->u2MsgSize; + if (rCmdChipConfig.u2MsgSize > CHIP_CONFIG_RESP_SIZE) { + DBGLOG(REQ, INFO, + "Chip config Msg Size %u is not valid (set)\n", + rCmdChipConfig.u2MsgSize); + rCmdChipConfig.u2MsgSize = CHIP_CONFIG_RESP_SIZE; + } + kalMemCopy(rCmdChipConfig.aucCmd, prChipConfigInfo->aucCmd, + rCmdChipConfig.u2MsgSize); + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_CHIP_CONFIG, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_CHIP_CONFIG), + (uint8_t *) &rCmdChipConfig, + pvSetBuffer, u4SetBufferLen); + + return rWlanStatus; +} /* wlanoidSetChipConfig */ + +void +wlanLoadDefaultCustomerSetting(IN struct ADAPTER * + prAdapter) { + + uint8_t ucItemNum, i; + + + ucItemNum = (sizeof(g_rDefaulteSetting) / sizeof( + struct PARAM_CUSTOM_KEY_CFG_STRUCT)); + DBGLOG(INIT, TRACE, "Default firmware setting %d item\n", + ucItemNum); + + + for (i = 0; i < ucItemNum; i++) { + wlanCfgSet(prAdapter, g_rDefaulteSetting[i].aucKey, + g_rDefaulteSetting[i].aucValue, 0); + DBGLOG(INIT, TRACE, "%s with %s\n", + g_rDefaulteSetting[i].aucKey, + g_rDefaulteSetting[i].aucValue); + } + +#if 1 + /*If need to re-parsing , included wlanInitFeatureOption*/ + wlanInitFeatureOption(prAdapter); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set cfg and callback + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetKeyCfg(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct PARAM_CUSTOM_KEY_CFG_STRUCT *prKeyCfgInfo; + + DEBUGFUNC("wlanoidSetKeyCfg"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CUSTOM_KEY_CFG_STRUCT); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_KEY_CFG_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + prKeyCfgInfo = (struct PARAM_CUSTOM_KEY_CFG_STRUCT *) + pvSetBuffer; + + if (kalMemCmp(prKeyCfgInfo->aucKey, "reload", 6) == 0) + wlanGetConfig(prAdapter); /* Reload config file */ + else + wlanCfgSet(prAdapter, prKeyCfgInfo->aucKey, + prKeyCfgInfo->aucValue, 0); + + wlanInitFeatureOption(prAdapter); +#if CFG_SUPPORT_EASY_DEBUG + wlanFeatureToFw(prAdapter); +#endif + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryEepromRead(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_CUSTOM_EEPROM_RW_STRUCT *prEepromRwInfo; + struct CMD_ACCESS_EEPROM rCmdAccessEeprom; + + DEBUGFUNC("wlanoidQueryEepromRead"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct + PARAM_CUSTOM_EEPROM_RW_STRUCT); + + if (u4QueryBufferLen < sizeof(struct + PARAM_CUSTOM_EEPROM_RW_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + prEepromRwInfo = (struct PARAM_CUSTOM_EEPROM_RW_STRUCT *) + pvQueryBuffer; + + kalMemZero(&rCmdAccessEeprom, + sizeof(struct CMD_ACCESS_EEPROM)); + rCmdAccessEeprom.u2Offset = prEepromRwInfo->ucEepromIndex; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_EEPROM, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventQueryEepromRead, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_ACCESS_EEPROM), + (uint8_t *) &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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetEepromWrite(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_EEPROM_RW_STRUCT *prEepromRwInfo; + struct CMD_ACCESS_EEPROM rCmdAccessEeprom; + + DEBUGFUNC("wlanoidSetEepromWrite"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct + PARAM_CUSTOM_EEPROM_RW_STRUCT); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_EEPROM_RW_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prEepromRwInfo = (struct PARAM_CUSTOM_EEPROM_RW_STRUCT *) + pvSetBuffer; + + kalMemZero(&rCmdAccessEeprom, + sizeof(struct CMD_ACCESS_EEPROM)); + rCmdAccessEeprom.u2Offset = prEepromRwInfo->ucEepromIndex; + rCmdAccessEeprom.u2Data = prEepromRwInfo->u2EepromData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_EEPROM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_ACCESS_EEPROM), + (uint8_t *) &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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryXmitOk(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *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(uint32_t); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(uint32_t) + || (u4QueryBufferLen > sizeof(uint32_t) + && u4QueryBufferLen < sizeof(uint64_t))) { + *pu4QueryInfoLen = sizeof(uint64_t); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(uint32_t)) { + *pu4QueryInfoLen = sizeof(uint32_t); + *(uint32_t *) pvQueryBuffer = (uint32_t) + prAdapter->rStatStruct + .rTransmittedFragmentCount.QuadPart; + } else { + *pu4QueryInfoLen = sizeof(uint64_t); + *(uint64_t *) pvQueryBuffer = (uint64_t) + prAdapter->rStatStruct + .rTransmittedFragmentCount.QuadPart; + } + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryXmitOk, + nicOidCmdTimeoutCommon, 0, NULL, + pvQueryBuffer, + u4QueryBufferLen); + +} /* wlanoidQueryXmitOk */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to query the number of the successfully + * received packets. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[out] pvQueryBuf A pointer to the buffer that holds the result of + * the query. + * \param[in] u4QueryBufLen The length of the query buffer. + * \param[out] pu4QueryInfoLen If the call is successful, returns the number of + * bytes written into the query buffer. If the call + * failed due to invalid length of the query buffer, + * returns the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryRcvOk(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *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(uint32_t); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(uint32_t) + || (u4QueryBufferLen > sizeof(uint32_t) + && u4QueryBufferLen < sizeof(uint64_t))) { + *pu4QueryInfoLen = sizeof(uint64_t); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(uint32_t)) { + *pu4QueryInfoLen = sizeof(uint32_t); + *(uint32_t *) pvQueryBuffer = (uint32_t) + prAdapter->rStatStruct.rReceivedFragmentCount + .QuadPart; + } else { + *pu4QueryInfoLen = sizeof(uint64_t); + *(uint64_t *) pvQueryBuffer = (uint64_t) + prAdapter->rStatStruct.rReceivedFragmentCount + .QuadPart; + } + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryRecvOk, + nicOidCmdTimeoutCommon, 0, NULL, + pvQueryBuffer, + u4QueryBufferLen); + +} /* wlanoidQueryRcvOk */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to query the number of frames that the driver + * fails to transmit. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[out] pvQueryBuf A pointer to the buffer that holds the result of + * the query. + * \param[in] u4QueryBufLen The length of the query buffer. + * \param[out] pu4QueryInfoLen If the call is successful, returns the number of + * bytes written into the query buffer. If the call + * failed due to invalid length of the query buffer, + * returns the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryXmitError(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *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(uint32_t); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(uint32_t) + || (u4QueryBufferLen > sizeof(uint32_t) + && u4QueryBufferLen < sizeof(uint64_t))) { + *pu4QueryInfoLen = sizeof(uint64_t); + return WLAN_STATUS_INVALID_LENGTH; + } + +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(uint32_t)) { + *pu4QueryInfoLen = sizeof(uint32_t); + *(uint32_t *) pvQueryBuffer = (uint32_t) + prAdapter->rStatStruct.rFailedCount.QuadPart; + } else { + *pu4QueryInfoLen = sizeof(uint64_t); + *(uint64_t *) pvQueryBuffer = (uint64_t) + prAdapter->rStatStruct.rFailedCount.QuadPart; + } + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryXmitError, + nicOidCmdTimeoutCommon, 0, NULL, + pvQueryBuffer, + u4QueryBufferLen); + +} /* wlanoidQueryXmitError */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to query the number of frames successfully + * transmitted after exactly one collision. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[out] pvQueryBuf A pointer to the buffer that holds the result of + * the query. + * \param[in] u4QueryBufLen The length of the query buffer. + * \param[out] pu4QueryInfoLen If the call is successful, returns the number of + * bytes written into the query buffer. If the call + * failed due to invalid length of the query buffer, + * returns the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryXmitOneCollision(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *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(uint32_t); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(uint32_t) + || (u4QueryBufferLen > sizeof(uint32_t) + && u4QueryBufferLen < sizeof(uint64_t))) { + *pu4QueryInfoLen = sizeof(uint64_t); + return WLAN_STATUS_INVALID_LENGTH; + } + +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(uint32_t)) { + *pu4QueryInfoLen = sizeof(uint32_t); + *(uint32_t *) pvQueryBuffer = (uint32_t) + (prAdapter->rStatStruct.rMultipleRetryCount + .QuadPart - + prAdapter->rStatStruct.rRetryCount.QuadPart); + } else { + *pu4QueryInfoLen = sizeof(uint64_t); + *(uint64_t *) pvQueryBuffer = (uint64_t) + (prAdapter->rStatStruct.rMultipleRetryCount + .QuadPart - + prAdapter->rStatStruct.rRetryCount.QuadPart); + } + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryXmitOneCollision, + nicOidCmdTimeoutCommon, 0, NULL, + pvQueryBuffer, + u4QueryBufferLen); + +} /* wlanoidQueryXmitOneCollision */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to query the number of frames successfully + * transmitted after more than one collision. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[out] pvQueryBuf A pointer to the buffer that holds the result of + * the query. + * \param[in] u4QueryBufLen The length of the query buffer. + * \param[out] pu4QueryInfoLen If the call is successful, returns the number of + * bytes written into the query buffer. If the call + * failed due to invalid length of the query buffer, + * returns the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryXmitMoreCollisions(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *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(uint32_t); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(uint32_t) + || (u4QueryBufferLen > sizeof(uint32_t) + && u4QueryBufferLen < sizeof(uint64_t))) { + *pu4QueryInfoLen = sizeof(uint64_t); + return WLAN_STATUS_INVALID_LENGTH; + } + +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(uint32_t)) { + *pu4QueryInfoLen = sizeof(uint32_t); + *(uint32_t *) pvQueryBuffer = (uint32_t) ( + prAdapter->rStatStruct.rMultipleRetryCount + .QuadPart); + } else { + *pu4QueryInfoLen = sizeof(uint64_t); + *(uint64_t *) pvQueryBuffer = (uint64_t) ( + prAdapter->rStatStruct.rMultipleRetryCount + .QuadPart); + } + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryXmitMoreCollisions, + nicOidCmdTimeoutCommon, 0, NULL, + pvQueryBuffer, + u4QueryBufferLen); + +} /* wlanoidQueryXmitMoreCollisions */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to query the number of frames + * not transmitted due to excessive collisions. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] pvQueryBuffer Pointer to the buffer that holds the result of + * the query. + * \param[in] u4QueryBufferLen The length of the query buffer. + * \param[out] pu4QueryInfoLen If the call is successful, returns the number + * of bytes written into the query buffer. If the + * call failed due to invalid length of the query + * buffer, returns the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryXmitMaxCollisions(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *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(uint32_t); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(uint32_t) + || (u4QueryBufferLen > sizeof(uint32_t) + && u4QueryBufferLen < sizeof(uint64_t))) { + *pu4QueryInfoLen = sizeof(uint64_t); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(uint32_t)) { + *pu4QueryInfoLen = sizeof(uint32_t); + *(uint32_t *) pvQueryBuffer = (uint32_t) + prAdapter->rStatStruct.rFailedCount.QuadPart; + } else { + *pu4QueryInfoLen = sizeof(uint64_t); + *(uint64_t *) pvQueryBuffer = (uint64_t) + prAdapter->rStatStruct.rFailedCount.QuadPart; + } + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryXmitMaxCollisions, + nicOidCmdTimeoutCommon, 0, + NULL, pvQueryBuffer, + u4QueryBufferLen); + +} /* wlanoidQueryXmitMaxCollisions */ + +#define MTK_CUSTOM_OID_INTERFACE_VERSION 0x00006620 /* for WPDWifi DLL */ +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to query current the OID interface version, + * which is the interface between the application and driver. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] pvQueryBuffer Pointer to the buffer that holds the result of + * the query. + * \param[in] u4QueryBufferLen The length of the query buffer. + * \param[out] pu4QueryInfoLen If the call is successful, returns the number + * of bytes written into the query buffer. If the + * call failed due to invalid length of the query + * buffer, returns the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryOidInterfaceVersion(IN struct ADAPTER * + prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + DEBUGFUNC("wlanoidQueryOidInterfaceVersion"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *(uint32_t *) pvQueryBuffer = + MTK_CUSTOM_OID_INTERFACE_VERSION; + *pu4QueryInfoLen = sizeof(uint32_t); + + DBGLOG(REQ, WARN, "Custom OID interface version: %#08X\n", + *(uint32_t *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryMulticastList(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetMulticastList(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct CMD_MAC_MCAST_ADDR rCmdMacMcastAddr; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* The data must be a multiple of the Ethernet address size. */ + if ((u4SetBufferLen % MAC_ADDR_LEN)) { + DBGLOG(REQ, WARN, "Invalid MC list length %u\n", + u4SetBufferLen); + + *pu4SetInfoLen = (((u4SetBufferLen + MAC_ADDR_LEN) - 1) / + MAC_ADDR_LEN) * MAC_ADDR_LEN; + + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = u4SetBufferLen; + + /* Verify if we can support so many multicast addresses. */ + if (u4SetBufferLen > MAX_NUM_GROUP_ADDR * MAC_ADDR_LEN) { + 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.ucBssIndex = + prAdapter->prAisBssInfo->ucBssIndex; + kalMemCopy(rCmdMacMcastAddr.arAddress, pvSetBuffer, + u4SetBufferLen); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_MAC_MCAST_ADDR, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_MAC_MCAST_ADDR), + (uint8_t *) &rCmdMacMcastAddr, + pvSetBuffer, u4SetBufferLen); +} /* end of wlanoidSetMulticastList() */ + +uint32_t +wlanoidRssiMonitor(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_RSSI_MONITOR_T rRssi; + int8_t orig_max_rssi_value; + int8_t orig_min_rssi_value; + uint32_t rStatus1 = WLAN_STATUS_SUCCESS; + uint32_t rStatus2; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct PARAM_RSSI_MONITOR_T); + + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(OID, WARN, "Too short length %u\n", + u4QueryBufferLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == + PARAM_MEDIA_STATE_DISCONNECTED) + rStatus1 = WLAN_STATUS_ADAPTER_NOT_READY; + + kalMemZero(&rRssi, sizeof(struct PARAM_RSSI_MONITOR_T)); + + orig_max_rssi_value = rRssi.max_rssi_value; + orig_min_rssi_value = rRssi.min_rssi_value; + + kalMemCopy(&rRssi, pvQueryBuffer, + sizeof(struct PARAM_RSSI_MONITOR_T)); + if (rRssi.enable) { + if (rRssi.max_rssi_value > PARAM_WHQL_RSSI_MAX_DBM) + rRssi.max_rssi_value = PARAM_WHQL_RSSI_MAX_DBM; + if (rRssi.min_rssi_value < -120) + rRssi.min_rssi_value = -120; + } else { + rRssi.max_rssi_value = 0; + rRssi.min_rssi_value = 0; + } + + DBGLOG(OID, INFO, + "enable=%d, max_rssi_value=%d, min_rssi_value=%d, orig_max_rssi_value=%d, orig_min_rssi_value=%d\n", + rRssi.enable, rRssi.max_rssi_value, rRssi.min_rssi_value, + orig_max_rssi_value, orig_min_rssi_value); + + rStatus2 = wlanSendSetQueryCmd(prAdapter, + CMD_ID_RSSI_MONITOR, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct PARAM_RSSI_MONITOR_T), + (uint8_t *)&rRssi, NULL, 0); + + return (rStatus1 == WLAN_STATUS_ADAPTER_NOT_READY) ? + rStatus1 : rStatus2; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetCurrentPacketFilter(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t u4NewPacketFilter; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t rResult = WLAN_STATUS_FAILURE; + struct CMD_RX_PACKET_FILTER rSetRxPacketFilter; + + DBGLOG(REQ, INFO, "wlanoidSetCurrentPacketFilter"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(uint32_t)) { + *pu4SetInfoLen = sizeof(uint32_t); + return WLAN_STATUS_INVALID_LENGTH; + } + ASSERT(pvSetBuffer); + + /* Set the new packet filter. */ + u4NewPacketFilter = *(uint32_t *) pvSetBuffer; + + DBGLOG(REQ, TRACE, "New packet filter: %#08x\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; + DBGLOG(REQ, WARN, "some flags we don't support\n"); + 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 + + prAdapter->fgAllMulicastFilter = FALSE; + if (u4NewPacketFilter & PARAM_PACKET_FILTER_ALL_MULTICAST) + prAdapter->fgAllMulicastFilter = TRUE; + } while (FALSE); + + if (rStatus == WLAN_STATUS_SUCCESS) { + /* Store the packet filter */ + + prAdapter->u4OsPacketFilter &= PARAM_PACKET_FILTER_P2P_MASK; + prAdapter->u4OsPacketFilter |= u4NewPacketFilter; + + kalMemZero(&rSetRxPacketFilter, sizeof(rSetRxPacketFilter)); + rSetRxPacketFilter.u4RxPacketFilter = + prAdapter->u4OsPacketFilter; + rResult = wlanoidSetPacketFilter(prAdapter, + &rSetRxPacketFilter, + g_fgIsOid, pvSetBuffer, + u4SetBufferLen); + DBGLOG(OID, TRACE, "[MC debug] u4OsPacketFilter=%x\n", + prAdapter->u4OsPacketFilter); + return rResult; + } else { + return rStatus; + } +} /* wlanoidSetCurrentPacketFilter */ + +uint32_t wlanoidSetPacketFilter(struct ADAPTER *prAdapter, + void *pvPacketFiltr, + u_int8_t fgIsOid, void *pvSetBuffer, + uint32_t u4SetBufferLen) { + struct CMD_RX_PACKET_FILTER *prSetRxPacketFilter = NULL; + + prSetRxPacketFilter = (struct CMD_RX_PACKET_FILTER *) + pvPacketFiltr; +#if CFG_SUPPORT_DROP_MC_PACKET + if (prAdapter->prGlueInfo->fgIsInSuspendMode) + prSetRxPacketFilter->u4RxPacketFilter &= + ~(PARAM_PACKET_FILTER_MULTICAST | + PARAM_PACKET_FILTER_ALL_MULTICAST); +#endif + DBGLOG(OID, INFO, + "[MC debug] u4PacketFilter=%x, IsSuspend=%d\n", + prSetRxPacketFilter->u4RxPacketFilter, + prAdapter->prGlueInfo->fgIsInSuspendMode); + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RX_FILTER, + TRUE, + FALSE, + fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_RX_PACKET_FILTER), + (uint8_t *)prSetRxPacketFilter, + pvSetBuffer, u4SetBufferLen); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryCurrentPacketFilter(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + DEBUGFUNC("wlanoidQueryCurrentPacketFilter"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(uint32_t); + + if (u4QueryBufferLen >= sizeof(uint32_t)) { + ASSERT(pvQueryBuffer); + *(uint32_t *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryAcpiDevicePowerState(IN struct ADAPTER * + prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { +#if DBG + enum PARAM_DEVICE_POWER_STATE *prPowerState; +#endif + + DEBUGFUNC("wlanoidQueryAcpiDevicePowerState"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(enum PARAM_DEVICE_POWER_STATE); + +#if DBG + prPowerState = (enum PARAM_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 + */ + *(enum PARAM_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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetAcpiDevicePowerState(IN struct ADAPTER * + prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + enum PARAM_DEVICE_POWER_STATE *prPowerState; + u_int8_t fgRetValue = TRUE; + + DEBUGFUNC("wlanoidSetAcpiDevicePowerState"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(enum PARAM_DEVICE_POWER_STATE); + + ASSERT(pvSetBuffer); + prPowerState = (enum PARAM_DEVICE_POWER_STATE *) + pvSetBuffer; + switch (*prPowerState) { + case ParamDeviceStateD0: + DBGLOG(REQ, INFO, "Set Power State: D0\n"); + kalDevSetPowerState(prAdapter->prGlueInfo, + (uint32_t) 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, + (uint32_t) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryFragThreshold(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetFragThreshold(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryRtsThreshold(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + DEBUGFUNC("wlanoidQueryRtsThreshold"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + DBGLOG(REQ, LOUD, "\n"); + + if (u4QueryBufferLen < sizeof(uint32_t)) { + *pu4QueryInfoLen = sizeof(uint32_t); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + *((uint32_t *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetRtsThreshold(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *prRtsThreshold; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(uint32_t); + if (u4SetBufferLen < sizeof(uint32_t)) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prRtsThreshold = (uint32_t *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetDisassociate(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct MSG_AIS_ABORT *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; + prAdapter->rWifiVar.rConnSettings.eReConnectLevel = + RECONNECT_LEVEL_USER_SET; + + /* Send AIS Abort Message */ + prAisAbortMsg = (struct MSG_AIS_ABORT *) cnmMemAlloc( + prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_AIS_ABORT)); + if (!prAisAbortMsg) { + DBGLOG(REQ, ERROR, "Fail in creating AisAbortMsg.\n"); + return WLAN_STATUS_FAILURE; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; + prAisAbortMsg->ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_NEW_CONNECTION; + prAisAbortMsg->fgDelayIndication = FALSE; + +#if CFG_DISCONN_DEBUG_FEATURE + /* used to disconnect debug capability */ + g_rDisconnInfoTemp.ucTrigger = DISCONNECT_TRIGGER_ACTIVE; +#endif + + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prAisAbortMsg, MSG_SEND_METHOD_BUF); + + /* indicate for disconnection */ + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == + PARAM_MEDIA_STATE_CONNECTED) + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY, NULL, 0); +#if !defined(LINUX) + prAdapter->fgIsRadioOff = TRUE; +#endif + + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetDisassociate */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to query the power save profile. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[out] pvQueryBuf A pointer to the buffer that holds the result of + * the query. + * \param[in] u4QueryBufLen The length of the query buffer. + * \param[out] pu4QueryInfoLen If the call is successful, returns the number of + * bytes written into the query buffer. If the call + * failed due to invalid length of the query buffer, + * returns the amount of storage needed. + * + * \return WLAN_STATUS_SUCCESS + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQuery802dot11PowerSaveProfile(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + DEBUGFUNC("wlanoidQuery802dot11PowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen != 0) { + ASSERT(pvQueryBuffer); + + /* *(PPARAM_POWER_MODE) pvQueryBuffer = (PARAM_POWER_MODE) + * (prAdapter->rWlanInfo.ePowerSaveMode.ucPsProfile); + */ + *(enum PARAM_POWER_MODE *) pvQueryBuffer = + (enum PARAM_POWER_MODE) ( + prAdapter->rWlanInfo.arPowerSaveMode[ + prAdapter->prAisBssInfo->ucBssIndex].ucPsProfile); + *pu4QueryInfoLen = sizeof(enum 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) + */ + *(enum PARAM_POWER_MODE *) pvQueryBuffer = + (enum 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSet802dot11PowerSaveProfile(IN struct ADAPTER * + prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t status; + struct PARAM_POWER_MODE_ *prPowerMode; + struct BSS_INFO *prBssInfo; + + const uint8_t *apucPsMode[Param_PowerModeMax] = { + (uint8_t *) "CAM", + (uint8_t *) "MAX PS", + (uint8_t *) "FAST PS" + }; + + DEBUGFUNC("wlanoidSet802dot11PowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_POWER_MODE_); + prPowerMode = (struct PARAM_POWER_MODE_ *) pvSetBuffer; + + if (u4SetBufferLen < sizeof(struct PARAM_POWER_MODE_)) { + DBGLOG(REQ, WARN, + "Set power mode error: Invalid length %u\n", + u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } else if (prPowerMode->ePowerMode >= Param_PowerModeMax) { + DBGLOG(REQ, WARN, + "Set power mode error: Invalid power mode(%u)\n", + prPowerMode->ePowerMode); + return WLAN_STATUS_INVALID_DATA; + } else if (prPowerMode->ucBssIdx >= + prAdapter->ucHwBssIdNum) { + DBGLOG(REQ, WARN, + "Set power mode error: Invalid BSS index(%u)\n", + prPowerMode->ucBssIdx); + return WLAN_STATUS_INVALID_DATA; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prPowerMode->ucBssIdx); + + if (prAdapter->fgEnCtiaPowerMode) { + if (prPowerMode->ePowerMode != Param_PowerModeCAM) { + /* User setting to PS mode (Param_PowerModeMAX_PSP or + * Param_PowerModeFast_PSP) + */ + + if (prAdapter->u4CtiaPowerMode == 0) + /* force to keep in CAM mode */ + prPowerMode->ePowerMode = Param_PowerModeCAM; + else if (prAdapter->u4CtiaPowerMode == 1) + prPowerMode->ePowerMode = + Param_PowerModeMAX_PSP; + else if (prAdapter->u4CtiaPowerMode == 2) + prPowerMode->ePowerMode = + Param_PowerModeFast_PSP; + } + } + + /* only CAM mode allowed when TP/Sigma on */ + if ((prAdapter->rWifiVar.ucTpTestMode == + ENUM_TP_TEST_MODE_THROUGHPUT) || + (prAdapter->rWifiVar.ucTpTestMode == + ENUM_TP_TEST_MODE_SIGMA_AC_N_PMF)) + prPowerMode->ePowerMode = Param_PowerModeCAM; + else if (prAdapter->rWifiVar.ePowerMode != + Param_PowerModeMax) + prPowerMode->ePowerMode = prAdapter->rWifiVar.ePowerMode; + + /* for WMM PS Sigma certification, keep WiFi in ps mode continuously */ + /* force PS == Param_PowerModeMAX_PSP */ + if ((prAdapter->rWifiVar.ucTpTestMode == + ENUM_TP_TEST_MODE_SIGMA_WMM_PS) && + (prPowerMode->ePowerMode >= Param_PowerModeMAX_PSP)) + prPowerMode->ePowerMode = Param_PowerModeMAX_PSP; + + status = nicConfigPowerSaveProfile(prAdapter, prPowerMode->ucBssIdx, + prPowerMode->ePowerMode, + g_fgIsOid, PS_CALLER_COMMON); + + if (prPowerMode->ePowerMode < Param_PowerModeMax) { + DBGLOG(INIT, TRACE, + "Set %s Network BSS(%u) PS mode to %s (%d)\n", + apucNetworkType[prBssInfo->eNetworkType], + prPowerMode->ucBssIdx, + apucPsMode[prPowerMode->ePowerMode], + prPowerMode->ePowerMode); + } else { + DBGLOG(INIT, TRACE, + "Invalid PS mode setting (%d) for %s Network BSS(%u)\n", + prPowerMode->ePowerMode, + apucNetworkType[prBssInfo->eNetworkType], + prPowerMode->ucBssIdx); + } + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryAdHocMode(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetAdHocMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryFrequency(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + DEBUGFUNC("wlanoidQueryFrequency"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rWifiVar.rConnSettings.eOPMode == + NET_TYPE_INFRA) { + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == + PARAM_MEDIA_STATE_CONNECTED) + *(uint32_t *) pvQueryBuffer = nicChannelNum2Freq( + prAdapter->prAisBssInfo->ucPrimaryChannel); + else + *(uint32_t *) pvQueryBuffer = 0; + } else + *(uint32_t *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetFrequency(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pu4FreqInKHz; + + DEBUGFUNC("wlanoidSetFrequency"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + pu4FreqInKHz = (uint32_t *) pvSetBuffer; + + prAdapter->rWifiVar.rConnSettings.ucAdHocChannelNum = + (uint8_t) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetChannel(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryBeaconInterval(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + DEBUGFUNC("wlanoidQueryBeaconInterval"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(uint32_t); + + if (u4QueryBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == + PARAM_MEDIA_STATE_CONNECTED) { + if (prAdapter->rWifiVar.rConnSettings.eOPMode == + NET_TYPE_INFRA) + *(uint32_t *) pvQueryBuffer = + prAdapter->rWlanInfo.rCurrBssId.rConfiguration + .u4BeaconPeriod; + else + *(uint32_t *) pvQueryBuffer = + (uint32_t)prAdapter->rWlanInfo.u2BeaconPeriod; + } else { + if (prAdapter->rWifiVar.rConnSettings.eOPMode == + NET_TYPE_INFRA) + *(uint32_t *) pvQueryBuffer = 0; + else + *(uint32_t *) pvQueryBuffer = + (uint32_t)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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetBeaconInterval(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pu4BeaconInterval; + + DEBUGFUNC("wlanoidSetBeaconInterval"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(uint32_t); + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + pu4BeaconInterval = (uint32_t *) pvSetBuffer; + + if ((*pu4BeaconInterval < DOT11_BEACON_PERIOD_MIN) + || (*pu4BeaconInterval > DOT11_BEACON_PERIOD_MAX)) { + DBGLOG(REQ, TRACE, "Invalid Beacon Interval = %u\n", + *pu4BeaconInterval); + return WLAN_STATUS_INVALID_DATA; + } + + prAdapter->rWlanInfo.u2BeaconPeriod = (uint16_t) * + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryAtimWindow(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + DEBUGFUNC("wlanoidQueryAtimWindow"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(uint32_t); + + if (u4QueryBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rWifiVar.rConnSettings.eOPMode == + NET_TYPE_INFRA) + *(uint32_t *) pvQueryBuffer = 0; + else + *(uint32_t *) pvQueryBuffer = (uint32_t) + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetAtimWindow(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pu4AtimWindow; + + DEBUGFUNC("wlanoidSetAtimWindow"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + pu4AtimWindow = (uint32_t *) pvSetBuffer; + + prAdapter->rWlanInfo.u2AtimWindow = (uint16_t) * + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetCurrentAddr(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetCSUMOffload(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t u4CSUMFlags; + struct CMD_BASIC_CONFIG rCmdBasicConfig; + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; + + DEBUGFUNC("wlanoidSetCSUMOffload"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + u4CSUMFlags = *(uint32_t *) pvSetBuffer; + + kalMemZero(&rCmdBasicConfig, + sizeof(struct CMD_BASIC_CONFIG)); + + 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; + rCmdBasicConfig.ucCtrlFlagAssertPath = + prWifiVar->ucCtrlFlagAssertPath; + rCmdBasicConfig.ucCtrlFlagDebugLevel = + prWifiVar->ucCtrlFlagDebugLevel; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_BASIC_CONFIG, + TRUE, + FALSE, + g_fgIsOid, + NULL, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_BASIC_CONFIG), + (uint8_t *) &rCmdBasicConfig, + pvSetBuffer, u4SetBufferLen); + + return WLAN_STATUS_SUCCESS; +} +#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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetNetworkAddress(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t i, u4IPv4AddrIdx; + struct CMD_SET_NETWORK_ADDRESS_LIST + *prCmdNetworkAddressList; + struct PARAM_NETWORK_ADDRESS_LIST *prNetworkAddressList = + (struct PARAM_NETWORK_ADDRESS_LIST *) pvSetBuffer; + struct PARAM_NETWORK_ADDRESS *prNetworkAddress; + uint32_t u4IPv4AddrCount, u4CmdSize; +#if CFG_ENABLE_GTK_FRAME_FILTER + uint32_t u4IpV4AddrListSize; + struct BSS_INFO *prBssInfo = + &prAdapter->rWifiVar.arBssInfoPool[KAL_NETWORK_TYPE_AIS_INDEX]; +#endif + + DEBUGFUNC("wlanoidSetNetworkAddress"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 4; + + if (u4SetBufferLen < OFFSET_OF(struct + PARAM_NETWORK_ADDRESS_LIST, arAddress)) + return WLAN_STATUS_INVALID_DATA; + + *pu4SetInfoLen = 0; + u4IPv4AddrCount = 0; + + /* 4 <1.1> Get IPv4 address count */ + /* We only suppot IPv4 address setting */ + prNetworkAddress = prNetworkAddressList->arAddress; + for (i = 0; i < prNetworkAddressList->u4AddressCount; i++) { + if ((prNetworkAddress->u2AddressType == + PARAM_PROTOCOL_ID_TCP_IP) && + (prNetworkAddress->u2AddressLength == IPV4_ADDR_LEN)) { + u4IPv4AddrCount++; + } + + prNetworkAddress = (struct PARAM_NETWORK_ADDRESS *) + ((unsigned long) prNetworkAddress + + (unsigned long) (prNetworkAddress->u2AddressLength + + OFFSET_OF(struct PARAM_NETWORK_ADDRESS, aucAddress))); + } + + /* 4 <2> Calculate command buffer size */ + /* construct payload of command packet */ + if (u4IPv4AddrCount == 0) + u4CmdSize = sizeof(struct CMD_SET_NETWORK_ADDRESS_LIST); + else + u4CmdSize = + OFFSET_OF(struct CMD_SET_NETWORK_ADDRESS_LIST, + arNetAddress) + + (sizeof(struct IPV4_NETWORK_ADDRESS) * + u4IPv4AddrCount); + + /* 4 <3> Allocate command buffer */ + prCmdNetworkAddressList = (struct CMD_SET_NETWORK_ADDRESS_LIST *) + kalMemAlloc(u4CmdSize, VIR_MEM_TYPE); + + if (prCmdNetworkAddressList == NULL) + return WLAN_STATUS_FAILURE; + +#if CFG_ENABLE_GTK_FRAME_FILTER + u4IpV4AddrListSize = + OFFSET_OF(struct IPV4_NETWORK_ADDRESS_LIST, arNetAddr) + + (u4IPv4AddrCount * sizeof(struct IPV4_NETWORK_ADDRESS)); + if (prBssInfo->prIpV4NetAddrList) + FREE_IPV4_NETWORK_ADDR_LIST(prBssInfo->prIpV4NetAddrList); + prBssInfo->prIpV4NetAddrList = + (struct IPV4_NETWORK_ADDRESS_LIST *) + kalMemAlloc(u4IpV4AddrListSize, + VIR_MEM_TYPE); + prBssInfo->prIpV4NetAddrList->ucAddrCount = + (uint8_t) u4IPv4AddrCount; +#endif + + /* 4 <4> Fill P_CMD_SET_NETWORK_ADDRESS_LIST */ + prCmdNetworkAddressList->ucBssIndex = + prNetworkAddressList->ucBssIdx; + + /* only to set IP address to FW once ARP filter is enabled */ + if (prAdapter->fgEnArpFilter) { + prCmdNetworkAddressList->ucAddressCount = + (uint8_t) u4IPv4AddrCount; + prNetworkAddress = prNetworkAddressList->arAddress; + + /* DBGLOG(INIT, INFO, ("%s: u4IPv4AddrCount (%lu)\n", + * __FUNCTION__, u4IPv4AddrCount)); + */ + + for (i = 0, u4IPv4AddrIdx = 0; + i < prNetworkAddressList->u4AddressCount; i++) { + if (prNetworkAddress->u2AddressType == + PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == + IPV4_ADDR_LEN) { + + kalMemCopy(prCmdNetworkAddressList-> + arNetAddress[u4IPv4AddrIdx].aucIpAddr, + prNetworkAddress->aucAddress, + sizeof(uint32_t)); + +#if CFG_ENABLE_GTK_FRAME_FILTER + kalMemCopy(prBssInfo->prIpV4NetAddrList-> + arNetAddr[u4IPv4AddrIdx].aucIpAddr, + prNetworkAddress->aucAddress, + sizeof(uint32_t)); +#endif + + DBGLOG(INIT, INFO, + "%s: IPv4 Addr [%u][" IPV4STR "]\n", + __func__, u4IPv4AddrIdx, + IPV4TOSTR(prNetworkAddress->aucAddress)); + + u4IPv4AddrIdx++; + } + + prNetworkAddress = (struct PARAM_NETWORK_ADDRESS *) + ((unsigned long)prNetworkAddress + + (unsigned long)(prNetworkAddress->u2AddressLength + + OFFSET_OF(struct PARAM_NETWORK_ADDRESS, + aucAddress))); + } + + } else { + prCmdNetworkAddressList->ucAddressCount = 0; + } + + DBGLOG(INIT, INFO, + "%s: Set %u IPv4 address for BSS[%u]\n", __func__, + u4IPv4AddrCount, + prCmdNetworkAddressList->ucBssIndex); + + /* 4 <5> Send command */ + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_IP_ADDRESS, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetIpAddress, + nicOidCmdTimeoutCommon, + u4CmdSize, + (uint8_t *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidRftestSetTestMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t rStatus; + struct CMD_TEST_CTRL rCmdTestCtrl; + + DEBUGFUNC("wlanoidRftestSetTestMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 0; + + if (u4SetBufferLen == 0) { + if ((prAdapter->fgTestMode == FALSE) + || (prAdapter->fgIcapMode == TRUE)) { + /* switch to RF Test mode */ + rCmdTestCtrl.ucAction = 0; /* Switch mode */ + rCmdTestCtrl.u.u4OpMode = 1; /* RF test mode */ + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_TEST_CTRL, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventEnterRfTest, + nicOidCmdEnterRFTestTimeout, + sizeof(struct CMD_TEST_CTRL), + (uint8_t *) &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 RF test ICAP 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidRftestSetTestIcapMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t rStatus; + struct CMD_TEST_CTRL rCmdTestCtrl; + + DEBUGFUNC("wlanoidRftestSetTestIcapMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 0; + + if (u4SetBufferLen == 0) { + if (prAdapter->fgIcapMode == FALSE) { + /* switch to RF Test mode */ + rCmdTestCtrl.ucAction = 0; /* Switch mode */ + rCmdTestCtrl.u.u4OpMode = 2; /* RF test mode */ + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_TEST_CTRL, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventEnterRfTest, + nicOidCmdEnterRFTestTimeout, + sizeof(struct CMD_TEST_CTRL), + (uint8_t *) &rCmdTestCtrl, + pvSetBuffer, u4SetBufferLen); + } else { + /* already in ICAP 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidRftestSetAbortTestMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t rStatus; + struct CMD_TEST_CTRL rCmdTestCtrl; + + DEBUGFUNC("wlanoidRftestSetAbortTestMode"); + + ASSERT(prAdapter); + 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_CTRL, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventLeaveRfTest, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_TEST_CTRL), + (uint8_t *) &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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidRftestQueryAutoTest(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_MTK_WIFI_TEST_STRUCT *prRfATInfo; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidRftestQueryAutoTest"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(struct + PARAM_MTK_WIFI_TEST_STRUCT); + +#if 0 /* PeiHsuan Temp Remove this check for workaround Gen2/Gen3 EM Mode + * Modification + */ + if (u4QueryBufferLen != sizeof(struct PARAM_MTK_WIFI_TEST_STRUCT)) { + DBGLOG(REQ, ERROR, "Invalid data. QueryBufferLen: %ld.\n", + u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } +#endif + + prRfATInfo = (struct PARAM_MTK_WIFI_TEST_STRUCT *) + pvQueryBuffer; + + DBGLOG(RFTEST, INFO, + "Get AT_CMD BufferLen = %d, AT Index = %d, Data = %d\n", + u4QueryBufferLen, + prRfATInfo->u4FuncIndex, + prRfATInfo->u4FuncData); + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidRftestSetAutoTest(IN struct ADAPTER *prAdapter, + OUT void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_MTK_WIFI_TEST_STRUCT *prRfATInfo; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidRftestSetAutoTest"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_MTK_WIFI_TEST_STRUCT); + +#if 0 /* PeiHsuan Temp Remove this check for workaround Gen2/Gen3 EM Mode + * Modification + */ + if (u4SetBufferLen != sizeof(struct + PARAM_MTK_WIFI_TEST_STRUCT)) { + DBGLOG(REQ, ERROR, "Invalid data. SetBufferLen: %ld.\n", + u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } +#endif + + prRfATInfo = (struct PARAM_MTK_WIFI_TEST_STRUCT *) + pvSetBuffer; + + DBGLOG(RFTEST, INFO, + "Set AT_CMD BufferLen = %d, AT Index = %d, Data = %d\n", + u4SetBufferLen, + prRfATInfo->u4FuncIndex, + prRfATInfo->u4FuncData); + + rStatus = rftestSetATInfo(prAdapter, + prRfATInfo->u4FuncIndex, prRfATInfo->u4FuncData); + + return rStatus; +} + +/* RF test OID set handler */ +uint32_t rftestSetATInfo(IN struct ADAPTER *prAdapter, + uint32_t u4FuncIndex, uint32_t u4FuncData) { + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + struct WIFI_CMD *prWifiCmd; + struct CMD_TEST_CTRL *pCmdTestCtrl; + uint8_t ucCmdSeqNum; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + (CMD_HDR_SIZE + sizeof(struct CMD_TEST_CTRL))); + + 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( + struct CMD_TEST_CTRL); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = g_fgIsOid; + prCmdInfo->ucCID = CMD_ID_TEST_CTRL; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(struct CMD_TEST_CTRL); + prCmdInfo->pvInformationBuffer = NULL; + prCmdInfo->u4InformationBufferLength = 0; + + /* Setup WIFI_CMD_T (payload = CMD_TEST_CTRL_T) */ + prWifiCmd = (struct WIFI_CMD *) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + pCmdTestCtrl = (struct CMD_TEST_CTRL *) ( + prWifiCmd->aucBuffer); + pCmdTestCtrl->ucAction = 1; /* Set ATInfo */ + pCmdTestCtrl->u.rRfATInfo.u4FuncIndex = u4FuncIndex; + pCmdTestCtrl->u.rRfATInfo.u4FuncData = u4FuncData; + + if ((u4FuncIndex == RF_AT_FUNCID_COMMAND) + && (u4FuncData == RF_AT_COMMAND_ICAP)) { + prAdapter->rIcapInfo.fgIcapEnable = TRUE; + prAdapter->rIcapInfo.fgCaptureDone = FALSE; + } + /* ICAP dump name Reset */ + if ((u4FuncIndex == RF_AT_FUNCID_COMMAND) + && (u4FuncData == RF_AT_COMMAND_RESET_DUMP_NAME)) + prAdapter->rIcapInfo.u2DumpIndex = 0; + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, + (struct QUE_ENTRY *) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prAdapter->prGlueInfo); + + return WLAN_STATUS_PENDING; +} + +uint32_t wlanoidExtRfTestICapStart(IN struct ADAPTER *prAdapter, + OUT void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct CMD_TEST_CTRL_EXT_T rCmdTestCtrl; + struct RBIST_CAP_START_T *prCmdICapInfo; + struct PARAM_MTK_WIFI_TEST_STRUCT_EXT_T *prRfATInfo; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidExtRfTestICapStart"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct + PARAM_MTK_WIFI_TEST_STRUCT_EXT_T); + + prRfATInfo = (struct PARAM_MTK_WIFI_TEST_STRUCT_EXT_T *) + pvSetBuffer; + + DBGLOG(RFTEST, INFO, + "Set AT_CMD BufferLen = %d, AT Index = %d\n", + u4SetBufferLen, + prRfATInfo->u4FuncIndex); + + rCmdTestCtrl.ucAction = ACTION_IN_RFTEST; + rCmdTestCtrl.u.rRfATInfo.u4FuncIndex = + SET_ICAP_CAPTURE_START; + + prCmdICapInfo = &(rCmdTestCtrl.u.rRfATInfo.Data.rICapInfo); + kalMemCopy(prCmdICapInfo, &(prRfATInfo->Data.rICapInfo), + sizeof(struct RBIST_CAP_START_T)); + + prAdapter->rIcapInfo.fgIcapEnable = TRUE; + prAdapter->rIcapInfo.fgCaptureDone = FALSE; + + rStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_RF_TEST, + TRUE, /* Query Bit: True->write False->read */ + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_TEST_CTRL_EXT_T), + (uint8_t *)&rCmdTestCtrl, pvSetBuffer, + u4SetBufferLen); + return rStatus; +} + +uint32_t wlanoidExtRfTestICapStatus(IN struct ADAPTER *prAdapter, + OUT void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct CMD_TEST_CTRL_EXT_T rCmdTestCtrl; + struct RBIST_CAP_START_T *prCmdICapInfo; + struct PARAM_MTK_WIFI_TEST_STRUCT_EXT_T *prRfATInfo; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidExtRfTestICapStatus"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct + PARAM_MTK_WIFI_TEST_STRUCT_EXT_T); + + prRfATInfo = (struct PARAM_MTK_WIFI_TEST_STRUCT_EXT_T *) + pvSetBuffer; + + DBGLOG(RFTEST, INFO, + "Set AT_CMD BufferLen = %d, AT Index = %d\n", + u4SetBufferLen, + prRfATInfo->u4FuncIndex); + + rCmdTestCtrl.ucAction = ACTION_IN_RFTEST; + rCmdTestCtrl.u.rRfATInfo.u4FuncIndex = + GET_ICAP_CAPTURE_STATUS; + + prCmdICapInfo = &(rCmdTestCtrl.u.rRfATInfo.Data.rICapInfo); + kalMemCopy(prCmdICapInfo, &(prRfATInfo->Data.rICapInfo), + sizeof(struct RBIST_CAP_START_T)); + + rStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_RF_TEST, + FALSE, /* Query Bit: True->write False->read */ + TRUE, + g_fgIsOid, + NULL, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_TEST_CTRL_EXT_T), + (uint8_t *)(&rCmdTestCtrl), pvSetBuffer, + u4SetBufferLen); + return rStatus; +} + +void wlanoidRfTestICapRawDataProc(IN struct ADAPTER * + prAdapter, uint32_t u4CapStartAddr, + uint32_t u4TotalBufferSize) { + struct CMD_TEST_CTRL_EXT_T rCmdTestCtrl; + struct PARAM_MTK_WIFI_TEST_STRUCT_EXT_T *prRfATInfo; + uint32_t u4SetBufferLen = 0; + void *pvSetBuffer = NULL; + int32_t rStatus; + + ASSERT(prAdapter); + + prRfATInfo = &(rCmdTestCtrl.u.rRfATInfo); + + rCmdTestCtrl.ucAction = ACTION_IN_RFTEST; + prRfATInfo->u4FuncIndex = GET_ICAP_RAW_DATA; + prRfATInfo->Data.rICapDump.u4Address = u4CapStartAddr; + prRfATInfo->Data.rICapDump.u4AddrOffset = 0x04; + prRfATInfo->Data.rICapDump.u4Bank = 1; + prRfATInfo->Data.rICapDump.u4BankSize = u4TotalBufferSize; + + rStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_RF_TEST, + TRUE, /* Query Bit: True->write False->read */ + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_TEST_CTRL_EXT_T), + (uint8_t *)(&rCmdTestCtrl), + pvSetBuffer, u4SetBufferLen); +} + +uint32_t +rftestQueryATInfo(IN struct ADAPTER *prAdapter, + uint32_t u4FuncIndex, uint32_t u4FuncData, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen) { + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + struct WIFI_CMD *prWifiCmd; + struct CMD_TEST_CTRL *pCmdTestCtrl; + uint8_t ucCmdSeqNum; + union EVENT_TEST_STATUS *prTestStatus; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + + if (u4FuncIndex == RF_AT_FUNCID_FW_INFO) { + /* driver implementation */ + prTestStatus = (union EVENT_TEST_STATUS *) pvQueryBuffer; + + prTestStatus->rATInfo.u4FuncData = + (prAdapter->rVerInfo.u2FwProductID << 16) | + (prAdapter->rVerInfo.u2FwOwnVersion); + u4QueryBufferLen = sizeof(union EVENT_TEST_STATUS); + + return WLAN_STATUS_SUCCESS; + } else if (u4FuncIndex == RF_AT_FUNCID_DRV_INFO) { + /* driver implementation */ + prTestStatus = (union EVENT_TEST_STATUS *) pvQueryBuffer; + + prTestStatus->rATInfo.u4FuncData = CFG_DRV_OWN_VERSION; + u4QueryBufferLen = sizeof(union EVENT_TEST_STATUS); + + return WLAN_STATUS_SUCCESS; + } else if (u4FuncIndex == + RF_AT_FUNCID_QUERY_ICAP_DUMP_FILE) { + /* driver implementation */ + prTestStatus = (union EVENT_TEST_STATUS *) pvQueryBuffer; + + prTestStatus->rATInfo.u4FuncData = + prAdapter->rIcapInfo.u2DumpIndex; + u4QueryBufferLen = sizeof(union EVENT_TEST_STATUS); + + return WLAN_STATUS_SUCCESS; + } + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + (CMD_HDR_SIZE + sizeof(struct CMD_TEST_CTRL))); + + 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( + struct CMD_TEST_CTRL); + prCmdInfo->pfCmdDoneHandler = nicCmdEventQueryRfTestATInfo; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = g_fgIsOid; + prCmdInfo->ucCID = CMD_ID_TEST_CTRL; + prCmdInfo->fgSetQuery = FALSE; + prCmdInfo->fgNeedResp = TRUE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(struct CMD_TEST_CTRL); + prCmdInfo->pvInformationBuffer = pvQueryBuffer; + prCmdInfo->u4InformationBufferLength = u4QueryBufferLen; + + /* Setup WIFI_CMD_T (payload = CMD_TEST_CTRL_T) */ + prWifiCmd = (struct WIFI_CMD *) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + pCmdTestCtrl = (struct CMD_TEST_CTRL *) ( + prWifiCmd->aucBuffer); + pCmdTestCtrl->ucAction = 2; /* Get ATInfo */ + pCmdTestCtrl->u.rRfATInfo.u4FuncIndex = u4FuncIndex; + pCmdTestCtrl->u.rRfATInfo.u4FuncData = u4FuncData; + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, + (struct QUE_ENTRY *) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prAdapter->prGlueInfo); + + return WLAN_STATUS_PENDING; + +} + +uint32_t rftestSetFrequency(IN struct ADAPTER *prAdapter, + IN uint32_t u4FreqInKHz, + IN uint32_t *pu4SetInfoLen) { + struct CMD_TEST_CTRL rCmdTestCtrl; + + ASSERT(prAdapter); + + rCmdTestCtrl.ucAction = 5; /* Set Channel Frequency */ + rCmdTestCtrl.u.u4ChannelFreq = u4FreqInKHz; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_TEST_CTRL, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_TEST_CTRL), + (uint8_t *) &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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanSendSetQueryCmd(IN struct ADAPTER *prAdapter, + uint8_t ucCID, + u_int8_t fgSetQuery, + u_int8_t fgNeedResp, + u_int8_t fgIsOid, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + uint32_t u4SetQueryInfoLen, + uint8_t *pucInfoBuffer, OUT void *pvSetQueryBuffer, + IN uint32_t u4SetQueryBufferLen) { + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + struct WIFI_CMD *prWifiCmd; + uint8_t ucCmdSeqNum; + + if (kalIsResetting()) { + DBGLOG(INIT, WARN, "Chip resetting, skip\n"); + return WLAN_STATUS_FAILURE; + } + + 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->u2InfoBufLen = (uint16_t) (CMD_HDR_SIZE + + u4SetQueryInfoLen); + prCmdInfo->pfCmdDoneHandler = pfCmdDoneHandler; + prCmdInfo->pfCmdTimeoutHandler = pfCmdTimeoutHandler; + prCmdInfo->fgIsOid = fgIsOid; + prCmdInfo->ucCID = ucCID; + prCmdInfo->fgSetQuery = fgSetQuery; + prCmdInfo->fgNeedResp = fgNeedResp; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u4SetQueryInfoLen; + prCmdInfo->pvInformationBuffer = pvSetQueryBuffer; + prCmdInfo->u4InformationBufferLength = u4SetQueryBufferLen; + + /* Setup WIFI_CMD_T (no payload) */ + prWifiCmd = (struct WIFI_CMD *) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->u2Length = prCmdInfo->u2InfoBufLen - + (uint16_t) OFFSET_OF(struct WIFI_CMD, u2Length); + prWifiCmd->u2PqId = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + 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, + (struct QUE_ENTRY *) 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 + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetWapiMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *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 (*(uint32_t *) 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->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + 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 = (struct WIFI_CMD *) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + cp = (uint8_t *) (prWifiCmd->aucBuffer); + + kalMemCopy(cp, (uint8_t *) pvSetBuffer, 4); + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, + (struct QUE_ENTRY *) 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 + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetWapiAssocInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct WAPI_INFO_ELEM *prWapiInfo; + uint8_t *cp; + uint16_t u2AuthSuiteCount = 0; + uint16_t u2PairSuiteCount = 0; + uint32_t u4AuthKeyMgtSuite = 0; + uint32_t u4PairSuite = 0; + uint32_t u4GroupSuite = 0; + uint16_t u2IeLength = 0; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + DEBUGFUNC("wlanoidSetWapiAssocInfo"); + DBGLOG(REQ, LOUD, "\r\n"); + + prAdapter->rWifiVar.rConnSettings.fgWapiMode = FALSE; + + if (u4SetBufferLen < 20 /* From EID to Group cipher */) + return WLAN_STATUS_INVALID_LENGTH; + + if (!wextSrchDesiredWAPIIE((uint8_t *) pvSetBuffer, + u4SetBufferLen, (uint8_t **) &prWapiInfo)) + return WLAN_STATUS_INVALID_LENGTH; + + if (!prWapiInfo || prWapiInfo->ucLength < 18 + || prWapiInfo->ucLength > 40) + return WLAN_STATUS_INVALID_LENGTH; + + u2IeLength = prWapiInfo->ucLength + 2; + + /* Skip Version check */ + cp = (uint8_t *) &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, + (uint8_t) (u4AuthKeyMgtSuite & 0x000000FF), + (uint8_t) ((u4AuthKeyMgtSuite >> 8) & 0x000000FF), + (uint8_t) ((u4AuthKeyMgtSuite >> 16) & 0x000000FF), + (uint8_t) ((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, + (uint8_t) (u4PairSuite & 0x000000FF), + (uint8_t) ((u4PairSuite >> 8) & 0x000000FF), + (uint8_t) ((u4PairSuite >> 16) & 0x000000FF), + (uint8_t) ((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", + (uint8_t) (u4GroupSuite & 0x000000FF), + (uint8_t) ((u4GroupSuite >> 8) & 0x000000FF), + (uint8_t) ((u4GroupSuite >> 16) & 0x000000FF), + (uint8_t) ((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, + prWapiInfo, u2IeLength); + prAdapter->prGlueInfo->u2WapiAssocInfoIESz = u2IeLength; + DBGLOG(SEC, TRACE, "Assoc Info IE sz %u\n", u2IeLength); + + prAdapter->rWifiVar.rConnSettings.fgWapiMode = TRUE; + + 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetWapiKey(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + struct WIFI_CMD *prWifiCmd; + struct PARAM_WPI_KEY *prNewKey; + struct CMD_802_11_KEY *prCmdKey; + uint8_t *pc; + uint8_t ucCmdSeqNum; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + + 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 = (struct PARAM_WPI_KEY *) pvSetBuffer; + + DBGLOG_MEM8(REQ, TRACE, (uint8_t *) pvSetBuffer, 560); + pc = (uint8_t *) pvSetBuffer; + + *pu4SetInfoLen = u4SetBufferLen; + + /* Todo:: WAPI AP mode !!!!! */ + prBssInfo = prAdapter->prAisBssInfo; + + prNewKey->ucKeyID = prNewKey->ucKeyID & BIT(0); + + /* 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, (uint8_t *) prNewKey->aucWPIEK, + (uint8_t) prNewKey->u4LenWPIEK); + prNewKey->u4LenWPICK = 16; + + DBGLOG(REQ, TRACE, "CK Key(%d):\r\n", + (uint8_t) prNewKey->u4LenWPICK); + DBGLOG_MEM8(REQ, TRACE, (uint8_t *) prNewKey->aucWPICK, + (uint8_t) 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, (uint8_t *) 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->u2InfoBufLen = CMD_HDR_SIZE + sizeof( + struct CMD_802_11_KEY); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = g_fgIsOid; + prCmdInfo->ucCID = CMD_ID_ADD_REMOVE_KEY; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u4SetBufferLen; + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + + /* Setup WIFI_CMD_T */ + prWifiCmd = (struct WIFI_CMD *) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prCmdKey = (struct CMD_802_11_KEY *) (prWifiCmd->aucBuffer); + + kalMemZero(prCmdKey, sizeof(struct CMD_802_11_KEY)); + + prCmdKey->ucAddRemove = 1; /* Add */ + + if (prNewKey->eKeyType == ENUM_WPI_PAIRWISE_KEY) { + prCmdKey->ucTxKey = 1; + prCmdKey->ucKeyType = 1; + } + kalMemCopy(prCmdKey->aucPeerAddr, + (uint8_t *) prNewKey->aucAddrIndex, MAC_ADDR_LEN); + if ((prCmdKey->aucPeerAddr[0] & prCmdKey->aucPeerAddr[1] & + prCmdKey->aucPeerAddr[2] & + prCmdKey->aucPeerAddr[3] & prCmdKey->aucPeerAddr[4] & + prCmdKey->aucPeerAddr[5]) == 0xFF) { + prStaRec = cnmGetStaRecByAddress(prAdapter, + prBssInfo->ucBssIndex, prBssInfo->aucBSSID); + ASSERT(prStaRec); /* AIS RSN Group key, addr is BC addr */ + kalMemCopy(prCmdKey->aucPeerAddr, prStaRec->aucMacAddr, + MAC_ADDR_LEN); + } else { + prStaRec = cnmGetStaRecByAddress(prAdapter, + prBssInfo->ucBssIndex, prCmdKey->aucPeerAddr); + } + + prCmdKey->ucBssIdx = + prAdapter->prAisBssInfo->ucBssIndex; /* AIS */ + + prCmdKey->ucKeyId = prNewKey->ucKeyID; + + prCmdKey->ucKeyLen = 32; + + prCmdKey->ucAlgorithmId = CIPHER_SUITE_WPI; + + kalMemCopy(prCmdKey->aucKeyMaterial, + (uint8_t *) prNewKey->aucWPIEK, 16); + + kalMemCopy(prCmdKey->aucKeyMaterial + 16, + (uint8_t *) prNewKey->aucWPICK, 16); + + kalMemCopy(prCmdKey->aucKeyRsc, (uint8_t *) prNewKey->aucPN, + 16); + + if (prCmdKey->ucTxKey) { + if (prStaRec) { + if (prCmdKey->ucKeyType) { /* AIS RSN STA */ + prCmdKey->ucWlanIndex = prStaRec->ucWlanIndex; + prStaRec->fgTransmitKeyExist = + TRUE; /* wait for CMD Done ? */ + } else { + ASSERT(FALSE); + } + } +#if 0 + if (fgAddTxBcKey || !prStaRec) { + + if ((prCmdKey->aucPeerAddr[0] + & prCmdKey->aucPeerAddr[1] + & prCmdKey->aucPeerAddr[2] + & prCmdKey->aucPeerAddr[3] + & prCmdKey->aucPeerAddr[4] + & prCmdKey->aucPeerAddr[5]) == 0xFF) { + prCmdKey->ucWlanIndex = + 255; /* AIS WEP Tx key */ + } else { /* Exist this case ? */ + ASSERT(FALSE); + /* prCmdKey->ucWlanIndex = */ + /* secPrivacySeekForBcEntry(prAdapter, */ + /* prBssInfo->ucBssIndex, */ + /* NETWORK_TYPE_AIS, */ + /* prCmdKey->aucPeerAddr, */ + /* prCmdKey->ucAlgorithmId, */ + /* prCmdKey->ucKeyId, */ + } + + prBssInfo->fgBcDefaultKeyExist = TRUE; + prBssInfo->ucBMCWlanIndex = + prCmdKey->ucWlanIndex; /* Saved for AIS WEP */ + prBssInfo->ucTxBcDefaultIdx = prCmdKey->ucKeyId; + } +#endif + } else { + /* Including IBSS RSN Rx BC key ? */ + if ((prCmdKey->aucPeerAddr[0] & prCmdKey->aucPeerAddr[1] & + prCmdKey->aucPeerAddr[2] & prCmdKey->aucPeerAddr[3] & + prCmdKey->aucPeerAddr[4] & prCmdKey->aucPeerAddr[5]) == + 0xFF) { + prCmdKey->ucWlanIndex = + WTBL_RESERVED_ENTRY; /* AIS WEP, should not have + * this case!! + */ + } else { + if (prStaRec) { /* AIS RSN Group key but addr is BSSID + */ + /* ASSERT(prStaRec->ucBMCWlanIndex < WTBL_SIZE) + */ + prCmdKey->ucWlanIndex = + secPrivacySeekForBcEntry(prAdapter, + prStaRec->ucBssIndex, + prStaRec->aucMacAddr, + prStaRec->ucIndex, + prCmdKey->ucAlgorithmId, + prCmdKey->ucKeyId); + prStaRec->ucWlanIndex = prCmdKey->ucWlanIndex; + } else { /* Exist this case ? */ + ASSERT(FALSE); + /* prCmdKey->ucWlanIndex = */ + /* secPrivacySeekForBcEntry(prAdapter, */ + /* prBssInfo->ucBssIndex, */ + /* NETWORK_TYPE_AIS, */ + /* prCmdKey->aucPeerAddr, */ + /* prCmdKey->ucAlgorithmId, */ + /* prCmdKey->ucKeyId, */ + } + } + } + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, + (struct QUE_ENTRY *) 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 + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetWSCAssocInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *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 = + (uint16_t) u4SetBufferLen; + DBGLOG(SEC, TRACE, "Assoc Info IE sz %d\n", u4SetBufferLen); + + return WLAN_STATUS_SUCCESS; + +} +#endif + +#if CFG_ENABLE_WAKEUP_ON_LAN +uint32_t +wlanoidSetAddWakeupPattern(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_PM_PACKET_PATTERN *prPacketPattern; + + DEBUGFUNC("wlanoidSetAddWakeupPattern"); + DBGLOG(REQ, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_PM_PACKET_PATTERN); + + if (u4SetBufferLen < sizeof(struct PARAM_PM_PACKET_PATTERN)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prPacketPattern = (struct PARAM_PM_PACKET_PATTERN *) + pvSetBuffer; + + /* FIXME: Send the struct to firmware */ + + return WLAN_STATUS_FAILURE; +} + +uint32_t +wlanoidSetRemoveWakeupPattern(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_PM_PACKET_PATTERN *prPacketPattern; + + DEBUGFUNC("wlanoidSetAddWakeupPattern"); + DBGLOG(REQ, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_PM_PACKET_PATTERN); + + if (u4SetBufferLen < sizeof(struct PARAM_PM_PACKET_PATTERN)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prPacketPattern = (struct PARAM_PM_PACKET_PATTERN *) + pvSetBuffer; + + /* FIXME: Send the struct to firmware */ + + return WLAN_STATUS_FAILURE; +} + +uint32_t +wlanoidQueryEnableWakeup(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t *pu4WakeupEventEnable; + + DEBUGFUNC("wlanoidQueryEnableWakeup"); + DBGLOG(REQ, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(uint32_t); + + if (u4QueryBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + pu4WakeupEventEnable = (uint32_t *) pvQueryBuffer; + + *pu4WakeupEventEnable = prAdapter->u4WakeupEventEnable; + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidSetEnableWakeup(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pu4WakeupEventEnable; + + DEBUGFUNC("wlanoidSetEnableWakup"); + DBGLOG(REQ, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + pu4WakeupEventEnable = (uint32_t *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetWiFiWmmPsTest(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_WMM_PS_TEST_STRUCT *prWmmPsTestInfo; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct CMD_SET_WMM_PS_TEST_STRUCT rSetWmmPsTestParam; + uint16_t u2CmdBufLen; + struct PM_PROFILE_SETUP_INFO *prPmProfSetupInfo; + struct BSS_INFO *prBssInfo; + + DEBUGFUNC("wlanoidSetWiFiWmmPsTest"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct + PARAM_CUSTOM_WMM_PS_TEST_STRUCT); + + prWmmPsTestInfo = (struct PARAM_CUSTOM_WMM_PS_TEST_STRUCT *) + pvSetBuffer; + + rSetWmmPsTestParam.ucBssIndex = + prAdapter->prAisBssInfo->ucBssIndex; + rSetWmmPsTestParam.bmfgApsdEnAc = + prWmmPsTestInfo->bmfgApsdEnAc; + rSetWmmPsTestParam.ucIsEnterPsAtOnce = + prWmmPsTestInfo->ucIsEnterPsAtOnce; + rSetWmmPsTestParam.ucIsDisableUcTrigger = + prWmmPsTestInfo->ucIsDisableUcTrigger; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + rSetWmmPsTestParam.ucBssIndex); + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + prPmProfSetupInfo->ucBmpDeliveryAC = + (rSetWmmPsTestParam.bmfgApsdEnAc >> 4) & BITS(0, 3); + prPmProfSetupInfo->ucBmpTriggerAC = + rSetWmmPsTestParam.bmfgApsdEnAc & BITS(0, 3); + + u2CmdBufLen = sizeof(struct CMD_SET_WMM_PS_TEST_STRUCT); + +#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, g_fgIsOid, + nicCmdEventSetCommon,/* TODO? */ + nicCmdTimeoutCommon, u2CmdBufLen, + (uint8_t *) &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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetTxAmpdu(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct CMD_TX_AMPDU rTxAmpdu; + uint16_t u2CmdBufLen; + u_int8_t *pfgEnable; + + DEBUGFUNC("wlanoidSetTxAmpdu"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(u_int8_t); + + pfgEnable = (u_int8_t *) pvSetBuffer; + + rTxAmpdu.fgEnable = *pfgEnable; + + u2CmdBufLen = sizeof(struct CMD_TX_AMPDU); + + rStatus = wlanSendSetQueryCmd(prAdapter, CMD_ID_TX_AMPDU, + TRUE, FALSE, TRUE, NULL, NULL, + u2CmdBufLen, + (uint8_t *) &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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetAddbaReject(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct CMD_ADDBA_REJECT rAddbaReject; + uint16_t u2CmdBufLen; + u_int8_t *pfgEnable; + + DEBUGFUNC("wlanoidSetAddbaReject"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(u_int8_t); + + pfgEnable = (u_int8_t *) pvSetBuffer; + + rAddbaReject.fgEnable = *pfgEnable; + + u2CmdBufLen = sizeof(struct CMD_ADDBA_REJECT); + + rStatus = wlanSendSetQueryCmd(prAdapter, CMD_ID_ADDBA_REJECT, + TRUE, FALSE, TRUE, NULL, NULL, + u2CmdBufLen, + (uint8_t *) &rAddbaReject, NULL, 0); + + return rStatus; +} /* wlanoidSetAddbaReject */ + +#if CFG_SLT_SUPPORT + +uint32_t +wlanoidQuerySLTStatus(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct PARAM_MTK_SLT_TEST_STRUCT *prMtkSltInfo = + (struct PARAM_MTK_SLT_TEST_STRUCT *) NULL; + struct SLT_INFO *prSltInfo = (struct SLT_INFO *) NULL; + + DEBUGFUNC("wlanoidQuerySLTStatus"); + DBGLOG(REQ, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(struct PARAM_MTK_SLT_TEST_STRUCT); + + if (u4QueryBufferLen < sizeof(struct + PARAM_MTK_SLT_TEST_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvQueryBuffer); + + prMtkSltInfo = (struct PARAM_MTK_SLT_TEST_STRUCT *) + pvQueryBuffer; + + prSltInfo = &(prAdapter->rWifiVar.rSltInfo); + + switch (prMtkSltInfo->rSltFuncIdx) { + case ENUM_MTK_SLT_FUNC_LP_SET: { + struct PARAM_MTK_SLT_LP_TEST_STRUCT *prLpSetting = + (struct PARAM_MTK_SLT_LP_TEST_STRUCT *) NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof( + struct PARAM_MTK_SLT_LP_TEST_STRUCT)); + + prLpSetting = (struct PARAM_MTK_SLT_LP_TEST_STRUCT *) + &prMtkSltInfo->unFuncInfoContent; + + prLpSetting->u4BcnRcvNum = prSltInfo->u4BeaconReceiveCnt; + } + break; + default: + /* TBD... */ + break; + } + + return rWlanStatus; +} /* wlanoidQuerySLTStatus */ + +uint32_t +wlanoidUpdateSLTMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct PARAM_MTK_SLT_TEST_STRUCT *prMtkSltInfo = + (struct PARAM_MTK_SLT_TEST_STRUCT *) NULL; + struct SLT_INFO *prSltInfo = (struct SLT_INFO *) NULL; + struct BSS_DESC *prBssDesc = (struct BSS_DESC *) NULL; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) 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(struct PARAM_MTK_SLT_TEST_STRUCT); + + if (u4SetBufferLen < sizeof(struct + PARAM_MTK_SLT_TEST_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prMtkSltInfo = (struct PARAM_MTK_SLT_TEST_STRUCT *) + pvSetBuffer; + + prSltInfo = &(prAdapter->rWifiVar.rSltInfo); + prBssInfo = prAdapter->prAisBssInfo; + + switch (prMtkSltInfo->rSltFuncIdx) { + case ENUM_MTK_SLT_FUNC_INITIAL: { /* Initialize */ + struct PARAM_MTK_SLT_INITIAL_STRUCT *prMtkSltInit = + (struct PARAM_MTK_SLT_INITIAL_STRUCT *) NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof( + struct PARAM_MTK_SLT_INITIAL_STRUCT)); + + prMtkSltInit = (struct PARAM_MTK_SLT_INITIAL_STRUCT *) + &prMtkSltInfo->unFuncInfoContent; + + if (prSltInfo->prPseudoStaRec != NULL) { + /* The driver has been initialized. */ + prSltInfo->prPseudoStaRec = NULL; + } + + prSltInfo->prPseudoBssDesc = scanSearchExistingBssDesc( + prAdapter, BSS_TYPE_IBSS, + prMtkSltInit->aucTargetMacAddr, + prMtkSltInit->aucTargetMacAddr); + + prSltInfo->u2SiteID = prMtkSltInit->u2SiteID; + + /* Bandwidth 2.4G: Channel 1~14 + * Bandwidth 5G: *36, 40, 44, 48, 52, 56, 60, 64, + * *100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, + * 149, 153, *157, 161, + * 184, 188, 192, 196, 200, 204, 208, 212, *216 + */ + prSltInfo->ucChannel2G4 = 1 + (prSltInfo->u2SiteID % 4) * 5; + + switch (prSltInfo->ucChannel2G4) { + case 1: + prSltInfo->ucChannel5G = 36; + break; + case 6: + prSltInfo->ucChannel5G = 52; + break; + case 11: + prSltInfo->ucChannel5G = 104; + break; + case 16: + prSltInfo->ucChannel2G4 = 14; + prSltInfo->ucChannel5G = 161; + break; + default: + ASSERT(FALSE); + } + + if (prSltInfo->prPseudoBssDesc == NULL) { + do { + prSltInfo->prPseudoBssDesc = + scanAllocateBssDesc(prAdapter); + + if (prSltInfo->prPseudoBssDesc == NULL) { + rWlanStatus = WLAN_STATUS_FAILURE; + break; + } + prBssDesc = prSltInfo->prPseudoBssDesc; + + } while (FALSE); + } else { + prBssDesc = prSltInfo->prPseudoBssDesc; + } + + if (prBssDesc) { + prBssDesc->eBSSType = BSS_TYPE_IBSS; + + COPY_MAC_ADDR(prBssDesc->aucSrcAddr, + prMtkSltInit->aucTargetMacAddr); + COPY_MAC_ADDR(prBssDesc->aucBSSID, + prBssInfo->aucOwnMacAddr); + + prBssDesc->u2BeaconInterval = 100; + prBssDesc->u2ATIMWindow = 0; + prBssDesc->ucDTIMPeriod = 1; + + prBssDesc->u2IELength = 0; + + prBssDesc->fgIsERPPresent = TRUE; + prBssDesc->fgIsHTPresent = TRUE; + + prBssDesc->u2OperationalRateSet = BIT(RATE_36M_INDEX); + prBssDesc->u2BSSBasicRateSet = BIT(RATE_36M_INDEX); + prBssDesc->fgIsUnknownBssBasicRate = FALSE; + + prBssDesc->fgIsLargerTSF = TRUE; + + prBssDesc->eBand = BAND_2G4; + + prBssDesc->ucChannelNum = prSltInfo->ucChannel2G4; + + prBssDesc->ucPhyTypeSet = PHY_TYPE_SET_802_11ABGN; + + GET_CURRENT_SYSTIME(&prBssDesc->rUpdateTime); + } + } + break; + case ENUM_MTK_SLT_FUNC_RATE_SET: /* Update RF Settings. */ + if (prSltInfo->prPseudoStaRec == NULL) { + rWlanStatus = WLAN_STATUS_FAILURE; + } else { + struct PARAM_MTK_SLT_TR_TEST_STRUCT *prTRSetting = + (struct PARAM_MTK_SLT_TR_TEST_STRUCT *) NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof( + struct PARAM_MTK_SLT_TR_TEST_STRUCT)); + + prStaRec = prSltInfo->prPseudoStaRec; + prTRSetting = (struct PARAM_MTK_SLT_TR_TEST_STRUCT *) + &prMtkSltInfo->unFuncInfoContent; + + if (prTRSetting->rNetworkType == + PARAM_NETWORK_TYPE_OFDM5) { + prBssInfo->eBand = BAND_5G; + prBssInfo->ucPrimaryChannel = + prSltInfo->ucChannel5G; + } + if (prTRSetting->rNetworkType == + PARAM_NETWORK_TYPE_OFDM24) { + prBssInfo->eBand = BAND_2G4; + prBssInfo->ucPrimaryChannel = + prSltInfo->ucChannel2G4; + } + + if ((prTRSetting->u4FixedRate & FIXED_BW_DL40) != 0) { + /* RF 40 */ + /* It would controls RFBW capability in WTBL. */ + prStaRec->u2HtCapInfo |= + HT_CAP_INFO_SUP_CHNL_WIDTH; + /* This controls RF BW, RF BW would be 40 + * only if + * 1. PHY_TYPE_BIT_HT is TRUE. + * 2. SCO is SCA/SCB. + */ + prStaRec->ucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + + /* U20/L20 Control. */ + switch (prTRSetting->u4FixedRate & 0xC000) { + case FIXED_EXT_CHNL_U20: + prBssInfo->eBssSCO = + CHNL_EXT_SCB; /* +2 */ + if (prTRSetting->rNetworkType == + PARAM_NETWORK_TYPE_OFDM5) { + prBssInfo->ucPrimaryChannel + += 2; + } else { + /* For channel 1, testing L20 at + * channel 8. AOSP + */ + SetTestChannel( + &prBssInfo->ucPrimaryChannel); + } + break; + case FIXED_EXT_CHNL_L20: + default: /* 40M */ + prBssInfo->eBssSCO = + CHNL_EXT_SCA; /* -2 */ + if (prTRSetting->rNetworkType == + PARAM_NETWORK_TYPE_OFDM5) { + prBssInfo->ucPrimaryChannel + -= 2; + } else { + /* For channel 11 / 14. testing + * U20 at channel 3. AOSP + */ + SetTestChannel( + &prBssInfo->ucPrimaryChannel); + } + 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_SW_INDEX); + break; + case RATE_OFDM_48M: + prStaRec->u2DesiredNonHTRateSet = + BIT(RATE_48M_SW_INDEX); + break; + case RATE_OFDM_36M: + prStaRec->u2DesiredNonHTRateSet = + BIT(RATE_36M_SW_INDEX); + break; + case RATE_OFDM_24M: + prStaRec->u2DesiredNonHTRateSet = + BIT(RATE_24M_SW_INDEX); + break; + case RATE_OFDM_6M: + prStaRec->u2DesiredNonHTRateSet = + BIT(RATE_6M_SW_INDEX); + break; + case RATE_CCK_11M_LONG: + prStaRec->u2DesiredNonHTRateSet = + BIT(RATE_11M_SW_INDEX); + break; + case RATE_CCK_1M_LONG: + prStaRec->u2DesiredNonHTRateSet = + BIT(RATE_1M_SW_INDEX); + break; + case RATE_GF_MCS_0: + prStaRec->u2DesiredNonHTRateSet = + BIT(RATE_HT_PHY_SW_INDEX); + prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + break; + case RATE_MM_MCS_7: + prStaRec->u2DesiredNonHTRateSet = + BIT(RATE_HT_PHY_SW_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_SW_INDEX); + prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + break; + default: + prStaRec->u2DesiredNonHTRateSet = + BIT(RATE_36M_SW_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. */ + struct PARAM_MTK_SLT_LP_TEST_STRUCT *prLpSetting = + (struct PARAM_MTK_SLT_LP_TEST_STRUCT *) NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof( + struct PARAM_MTK_SLT_LP_TEST_STRUCT)); + + prLpSetting = (struct PARAM_MTK_SLT_LP_TEST_STRUCT *) + &prMtkSltInfo->unFuncInfoContent; + + if (prSltInfo->prPseudoBssDesc == NULL) { + /* Please initial SLT Mode first. */ + break; + } + prBssDesc = prSltInfo->prPseudoBssDesc; + + switch (prLpSetting->rLpTestMode) { + case ENUM_MTK_LP_TEST_NORMAL: + /* In normal mode, we would use target MAC address to be + * the BSSID. + */ + COPY_MAC_ADDR(prBssDesc->aucBSSID, + prBssInfo->aucOwnMacAddr); + prSltInfo->fgIsDUT = FALSE; + break; + case ENUM_MTK_LP_TEST_GOLDEN_SAMPLE: + /* 1. Lower AIFS of BCN queue. + * 2. Fixed Random Number tobe 0. + */ + prSltInfo->fgIsDUT = FALSE; + /* In LP test mode, we would use MAC address of Golden + * Sample to be the BSSID. + */ + COPY_MAC_ADDR(prBssDesc->aucBSSID, + prBssInfo->aucOwnMacAddr); + break; + case ENUM_MTK_LP_TEST_DUT: + /* 1. Enter Sleep Mode. + * 2. Fix random number a large value & enlarge AIFN of + * BCN queue. + */ + COPY_MAC_ADDR(prBssDesc->aucBSSID, + prBssDesc->aucSrcAddr); + prSltInfo->u4BeaconReceiveCnt = 0; + prSltInfo->fgIsDUT = TRUE; + break; + } + + } + + break; + default: + break; + } + + return WLAN_STATUS_FAILURE; + + return rWlanStatus; +} /* wlanoidUpdateSLTMode */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to query NVRAM value. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[out] pvQueryBuf A pointer to the buffer that holds the result of + * the query. + * \param[in] u4QueryBufLen The length of the query buffer. + * \param[out] pu4QueryInfoLen If the call is successful, returns the number of + * bytes written into the query buffer. If the call + * failed due to invalid length of the query buffer, + * returns the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_FAILURE + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryNvramRead(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_CUSTOM_EEPROM_RW_STRUCT *prNvramRwInfo; + uint16_t u2Data; + u_int8_t fgStatus; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryNvramRead"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct + PARAM_CUSTOM_EEPROM_RW_STRUCT); + + if (u4QueryBufferLen < sizeof(struct + PARAM_CUSTOM_EEPROM_RW_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + prNvramRwInfo = (struct PARAM_CUSTOM_EEPROM_RW_STRUCT *) + 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(struct + PARAM_CUSTOM_EEPROM_RW_STRUCT); + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetNvramWrite(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_EEPROM_RW_STRUCT *prNvramRwInfo; + u_int8_t fgStatus; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidSetNvramWrite"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct + PARAM_CUSTOM_EEPROM_RW_STRUCT); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_EEPROM_RW_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prNvramRwInfo = (struct PARAM_CUSTOM_EEPROM_RW_STRUCT *) + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryCfgSrcType(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + ASSERT(prAdapter); + + *pu4QueryInfoLen = sizeof(enum ENUM_CFG_SRC_TYPE); + + if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) + *(enum ENUM_CFG_SRC_TYPE *) pvQueryBuffer = + CFG_SRC_TYPE_NVRAM; + else + *(enum ENUM_CFG_SRC_TYPE *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryEepromType(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + ASSERT(prAdapter); + + *pu4QueryInfoLen = sizeof(enum ENUM_EEPROM_TYPE *); + +#if CFG_SUPPORT_NIC_CAPABILITY + if (prAdapter->fgIsEepromUsed == TRUE) + *(enum ENUM_EEPROM_TYPE *) pvQueryBuffer = + EEPROM_TYPE_PRESENT; + else + *(enum ENUM_EEPROM_TYPE *) pvQueryBuffer = EEPROM_TYPE_NO; +#else + *(enum ENUM_EEPROM_TYPE *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetCountryCode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint8_t *pucCountry; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + + if (regd_is_single_sku_en()) { + rlmDomainOidSetCountry(prAdapter, pvSetBuffer, + u4SetBufferLen); + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_SUCCESS; + } + + ASSERT(u4SetBufferLen == 2); + + *pu4SetInfoLen = 2; + + pucCountry = pvSetBuffer; + + prAdapter->rWifiVar.rConnSettings.u2CountryCode = + (((uint16_t) pucCountry[0]) << 8) | ((uint16_t) pucCountry[1]); + + /* Force to re-search country code in regulatory domains */ + prAdapter->prDomainInfo = NULL; + rlmDomainSendCmd(prAdapter); + + /* Update supported channel list in channel table based on current + * country domain + */ + wlanUpdateChannelTable(prAdapter->prGlueInfo); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidSetScanMacOui(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct PARAM_BSS_MAC_OUI *prParamMacOui; + struct BSS_INFO *prBssInfo; + + ASSERT(prAdapter); + ASSERT(prAdapter->prGlueInfo); + ASSERT(pvSetBuffer); + ASSERT(u4SetBufferLen == sizeof(struct PARAM_BSS_MAC_OUI)); + + prParamMacOui = (struct PARAM_BSS_MAC_OUI *)pvSetBuffer; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prParamMacOui->ucBssIndex); + if (!prBssInfo) { + log_dbg(REQ, ERROR, "Invalid bss info (ind=%u)\n", + prParamMacOui->ucBssIndex); + return WLAN_STATUS_FAILURE; + } + + kalMemCopy(prBssInfo->ucScanOui, prParamMacOui->ucMacOui, MAC_OUI_LEN); + prBssInfo->fgIsScanOuiSet = TRUE; + *pu4SetInfoLen = MAC_OUI_LEN; + + return WLAN_STATUS_SUCCESS; +} + +#if 0 +uint32_t +wlanoidSetNoaParam(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_NOA_PARAM_STRUCT *prNoaParam; + struct CMD_CUSTOM_NOA_PARAM_STRUCT rCmdNoaParam; + + DEBUGFUNC("wlanoidSetNoaParam"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct + PARAM_CUSTOM_NOA_PARAM_STRUCT); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_NOA_PARAM_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prNoaParam = (struct PARAM_CUSTOM_NOA_PARAM_STRUCT *) + pvSetBuffer; + + kalMemZero(&rCmdNoaParam, + sizeof(struct CMD_CUSTOM_NOA_PARAM_STRUCT)); + 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(struct CMD_CUSTOM_NOA_PARAM_STRUCT), + (uint8_t *) &rCmdNoaParam, pvSetBuffer, + u4SetBufferLen); +} + +uint32_t +wlanoidSetOppPsParam(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_OPPPS_PARAM_STRUCT *prOppPsParam; + struct CMD_CUSTOM_OPPPS_PARAM_STRUCT rCmdOppPsParam; + + DEBUGFUNC("wlanoidSetOppPsParam"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct + PARAM_CUSTOM_OPPPS_PARAM_STRUCT); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_OPPPS_PARAM_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prOppPsParam = (struct PARAM_CUSTOM_OPPPS_PARAM_STRUCT *) + pvSetBuffer; + + kalMemZero(&rCmdOppPsParam, + sizeof(struct CMD_CUSTOM_OPPPS_PARAM_STRUCT)); + rCmdOppPsParam.u4CTwindowMs = prOppPsParam->u4CTwindowMs; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_OPPPS_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_CUSTOM_OPPPS_PARAM_STRUCT), + (uint8_t *) &rCmdOppPsParam, pvSetBuffer, + u4SetBufferLen); +} + +uint32_t +wlanoidSetUApsdParam(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_UAPSD_PARAM_STRUCT *prUapsdParam; + struct CMD_CUSTOM_UAPSD_PARAM_STRUCT rCmdUapsdParam; + struct PM_PROFILE_SETUP_INFO *prPmProfSetupInfo; + struct BSS_INFO *prBssInfo; + + DEBUGFUNC("wlanoidSetUApsdParam"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct + PARAM_CUSTOM_UAPSD_PARAM_STRUCT); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_UAPSD_PARAM_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prBssInfo = & + (prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + + prUapsdParam = (struct PARAM_CUSTOM_UAPSD_PARAM_STRUCT *) + pvSetBuffer; + + kalMemZero(&rCmdUapsdParam, + sizeof(struct CMD_CUSTOM_OPPPS_PARAM_STRUCT)); + 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(struct CMD_CUSTOM_OPPPS_PARAM_STRUCT), + (uint8_t *)&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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetBT(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + + struct PTA_IPC *prPtaIpc; + + DEBUGFUNC("wlanoidSetBT.\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PTA_IPC); + if (u4SetBufferLen != sizeof(struct PTA_IPC)) { + /* 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 = (struct PTA_IPC *) pvSetBuffer; + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS && CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(INIT, INFO, + "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]); + + DBGLOG(INIT, INFO, + "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(struct PTA_IPC), + (uint8_t *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryBT(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + /* P_PARAM_PTA_IPC_T prPtaIpc; */ + /* UINT_32 u4QueryBuffLen; */ + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct PTA_IPC); + + /* Check for query buffer length */ + if (u4QueryBufferLen != sizeof(struct PTA_IPC)) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvQueryBuffer); + /* prPtaIpc = (P_PTA_IPC_T)pvQueryBuffer; */ + /* prPtaIpc->ucCmd = BT_CMD_PROFILE; */ + /* prPtaIpc->ucLen = sizeof(prPtaIpc->u); */ + /* nicPtaGetProfile(prAdapter, (PUINT_8)&prPtaIpc->u, &u4QueryBuffLen); + */ + + return WLAN_STATUS_SUCCESS; +} + +#if 0 +uint32_t +wlanoidQueryBtSingleAntenna(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + P_PTA_INFO_T prPtaInfo; + uint32_t *pu4SingleAntenna; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(uint32_t); + + /* Check for query buffer length */ + if (u4QueryBufferLen != sizeof(uint32_t)) { + DBGLOG(REQ, WARN, "Invalid length %lu\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvQueryBuffer); + + prPtaInfo = &prAdapter->rPtaInfo; + pu4SingleAntenna = (uint32_t *) pvQueryBuffer; + + if (prPtaInfo->fgSingleAntenna) { + /* DBGLOG(INIT, INFO, (KERN_WARNING DRV_NAME + * "Q Single Ant = 1\r\n")); + */ + *pu4SingleAntenna = 1; + } else { + /* DBGLOG(INIT, INFO, (KERN_WARNING DRV_NAME + * "Q Single Ant = 0\r\n")); + */ + *pu4SingleAntenna = 0; + } + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidSetBtSingleAntenna(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + + uint32_t *pu4SingleAntenna; + uint32_t u4SingleAntenna; + P_PTA_INFO_T prPtaInfo; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + prPtaInfo = &prAdapter->rPtaInfo; + + *pu4SetInfoLen = sizeof(uint32_t); + if (u4SetBufferLen != sizeof(uint32_t)) + 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 = (uint32_t *) pvSetBuffer; + u4SingleAntenna = *pu4SingleAntenna; + + if (u4SingleAntenna == 0) { + /* DBGLOG(INIT, INFO, (KERN_WARNING DRV_NAME + * "Set Single Ant = 0\r\n")); + */ + prPtaInfo->fgSingleAntenna = FALSE; + } else { + /* DBGLOG(INIT, INFO, (KERN_WARNING DRV_NAME + * "Set Single Ant = 1\r\n")); + */ + prPtaInfo->fgSingleAntenna = TRUE; + } + ptaFsmRunEventSetConfig(prAdapter, &prPtaInfo->rPtaParam); + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS +uint32_t +wlanoidQueryPta(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + P_PTA_INFO_T prPtaInfo; + uint32_t *pu4Pta; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(uint32_t); + + /* Check for query buffer length */ + if (u4QueryBufferLen != sizeof(uint32_t)) { + DBGLOG(REQ, WARN, "Invalid length %lu\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvQueryBuffer); + + prPtaInfo = &prAdapter->rPtaInfo; + pu4Pta = (uint32_t *) pvQueryBuffer; + + if (prPtaInfo->fgEnabled) { + /* DBGLOG(INIT, INFO, (KERN_WARNING DRV_NAME"PTA = 1\r\n")); */ + *pu4Pta = 1; + } else { + /* DBGLOG(INIT, INFO, (KERN_WARNING DRV_NAME"PTA = 0\r\n")); */ + *pu4Pta = 0; + } + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidSetPta(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pu4PtaCtrl; + uint32_t u4PtaCtrl; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(uint32_t); + if (u4SetBufferLen != sizeof(uint32_t)) + 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 = (uint32_t *) pvSetBuffer; + u4PtaCtrl = *pu4PtaCtrl; + + if (u4PtaCtrl == 0) { + /* DBGLOG(INIT, INFO, (KERN_WARNING DRV_NAME"Set Pta= 0\r\n")); + */ + nicPtaSetFunc(prAdapter, FALSE); + } else { + /* DBGLOG(INIT, INFO, (KERN_WARNING DRV_NAME"Set Pta= 1\r\n")); + */ + nicPtaSetFunc(prAdapter, TRUE); + } + + return WLAN_STATUS_SUCCESS; +} +#endif + +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set Tx power profile. + * + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. + * \param[in] u4SetBufferLen The length of the set buffer. + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed + * due to invalid length of the set buffer, returns + * the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetTxPower(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct SET_TXPWR_CTRL *pTxPwr = (struct SET_TXPWR_CTRL *) + pvSetBuffer; + struct SET_TXPWR_CTRL *prCmd; + uint32_t i; + uint32_t rStatus; + + DEBUGFUNC("wlanoidSetTxPower"); + DBGLOG(REQ, LOUD, "\r\n"); + + prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, + sizeof(struct SET_TXPWR_CTRL)); + kalMemZero(prCmd, sizeof(struct SET_TXPWR_CTRL)); + prCmd->c2GLegacyStaPwrOffset = + pTxPwr->c2GLegacyStaPwrOffset; + prCmd->c2GHotspotPwrOffset = pTxPwr->c2GHotspotPwrOffset; + prCmd->c2GP2pPwrOffset = pTxPwr->c2GP2pPwrOffset; + prCmd->c2GBowPwrOffset = pTxPwr->c2GBowPwrOffset; + prCmd->c5GLegacyStaPwrOffset = + pTxPwr->c5GLegacyStaPwrOffset; + prCmd->c5GHotspotPwrOffset = pTxPwr->c5GHotspotPwrOffset; + prCmd->c5GP2pPwrOffset = pTxPwr->c5GP2pPwrOffset; + prCmd->c5GBowPwrOffset = pTxPwr->c5GBowPwrOffset; + prCmd->ucConcurrencePolicy = pTxPwr->ucConcurrencePolicy; + for (i = 0; i < 14; i++) + prCmd->acTxPwrLimit2G[i] = pTxPwr->acTxPwrLimit2G[i]; + + for (i = 0; i < 4; i++) + prCmd->acTxPwrLimit5G[i] = pTxPwr->acTxPwrLimit5G[i]; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + +#if 0 + DBGLOG(INIT, INFO, "c2GLegacyStaPwrOffset=%d\n", + pTxPwr->c2GLegacyStaPwrOffset); + DBGLOG(INIT, INFO, "c2GHotspotPwrOffset=%d\n", + pTxPwr->c2GHotspotPwrOffset); + DBGLOG(INIT, INFO, "c2GP2pPwrOffset=%d\n", + pTxPwr->c2GP2pPwrOffset); + DBGLOG(INIT, INFO, "c2GBowPwrOffset=%d\n", + pTxPwr->c2GBowPwrOffset); + DBGLOG(INIT, INFO, "c5GLegacyStaPwrOffset=%d\n", + pTxPwr->c5GLegacyStaPwrOffset); + DBGLOG(INIT, INFO, "c5GHotspotPwrOffset=%d\n", + pTxPwr->c5GHotspotPwrOffset); + DBGLOG(INIT, INFO, "c5GP2pPwrOffset=%d\n", + pTxPwr->c5GP2pPwrOffset); + DBGLOG(INIT, INFO, "c5GBowPwrOffset=%d\n", + pTxPwr->c5GBowPwrOffset); + DBGLOG(INIT, INFO, "ucConcurrencePolicy=%d\n", + pTxPwr->ucConcurrencePolicy); + + for (i = 0; i < 14; i++) + DBGLOG(INIT, INFO, "acTxPwrLimit2G[%d]=%d\n", i, + pTxPwr->acTxPwrLimit2G[i]); + + for (i = 0; i < 4; i++) + DBGLOG(INIT, INFO, "acTxPwrLimit5G[%d]=%d\n", i, + pTxPwr->acTxPwrLimit5G[i]); +#endif + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_TXPWR_CTRL, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + g_fgIsOid, /* fgIsOid */ + nicCmdEventSetCommon, nicOidCmdTimeoutCommon, + sizeof(struct SET_TXPWR_CTRL), /* u4SetQueryInfoLen */ + (uint8_t *) prCmd, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + /* ASSERT(rStatus == WLAN_STATUS_PENDING); */ + cnmMemFree(prAdapter, prCmd); + + return rStatus; + +} + +uint32_t wlanSendMemDumpCmd(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen) { + struct PARAM_CUSTOM_MEM_DUMP_STRUCT *prMemDumpInfo; + struct CMD_DUMP_MEM *prCmdDumpMem; + struct CMD_DUMP_MEM rCmdDumpMem; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4MemSize = PARAM_MEM_DUMP_MAX_SIZE; + + uint32_t u4RemainLeng = 0; + uint32_t u4CurAddr = 0; + uint8_t ucFragNum = 0; + + prCmdDumpMem = &rCmdDumpMem; + prMemDumpInfo = (struct PARAM_CUSTOM_MEM_DUMP_STRUCT *) + 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 { + uint32_t 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; +#if CFG_SUPPORT_QA_TOOL + prCmdDumpMem->u4IcapContent = prMemDumpInfo->u4IcapContent; +#endif /* CFG_SUPPORT_QA_TOOL */ + + DBGLOG(REQ, TRACE, "[%d] 0x%X, len %u, remain len %u\n", + ucFragNum, prCmdDumpMem->u4Address, + prCmdDumpMem->u4Length, prCmdDumpMem->u4RemainLength); + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_DUMP_MEM, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryMemDump, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_DUMP_MEM), + (uint8_t *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryMemDump(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_CUSTOM_MEM_DUMP_STRUCT *prMemDumpInfo; + + DEBUGFUNC("wlanoidQueryMemDump"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(uint32_t); + + prMemDumpInfo = (struct PARAM_CUSTOM_MEM_DUMP_STRUCT *) + pvQueryBuffer; + DBGLOG(REQ, TRACE, "Dump 0x%X, len %u\n", + prMemDumpInfo->u4Address, prMemDumpInfo->u4Length); + + prMemDumpInfo->u4RemainLength = prMemDumpInfo->u4Length; + prMemDumpInfo->u4Length = 0; + prMemDumpInfo->ucFragNum = 0; + + return wlanSendMemDumpCmd(prAdapter, pvQueryBuffer, + u4QueryBufferLen); + +} /* end of wlanoidQueryMcrRead() */ + +#if CFG_ENABLE_WIFI_DIRECT +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to set the p2p mode. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. + * \param[in] u4SetBufferLen The length of the set buffer. + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed + * due to invalid length of the set buffer, returns + * the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetP2pMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t status = WLAN_STATUS_SUCCESS; + struct PARAM_CUSTOM_P2P_SET_STRUCT *prSetP2P = + (struct PARAM_CUSTOM_P2P_SET_STRUCT *) NULL; + /* P_MSG_P2P_NETDEV_REGISTER_T prP2pNetdevRegMsg = + * P_MSG_P2P_NETDEV_REGISTER_T)NULL; + */ + DEBUGFUNC("wlanoidSetP2pMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CUSTOM_P2P_SET_STRUCT); + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_P2P_SET_STRUCT)) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prSetP2P = (struct PARAM_CUSTOM_P2P_SET_STRUCT *) + pvSetBuffer; + + DBGLOG(P2P, TRACE, "Set P2P enable[%d] mode[%d]\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 + * enable = 1, mode = 2 => init dual Soft AP network + * enable = 1, mode = 3 => init AP+P2P network + */ + + + DBGLOG(P2P, INFO, "P2P Compile as (%d)p2p-like interface\n", + KAL_P2P_NUM); + + if (prSetP2P->u4Mode >= RUNNING_P2P_MODE_NUM) { + DBGLOG(P2P, ERROR, "P2P interface mode(%d) is wrong\n", + prSetP2P->u4Mode); + ASSERT(0); + } + + if (prSetP2P->u4Enable) { + p2pSetMode(prSetP2P->u4Mode); + + if (p2pLaunch(prAdapter->prGlueInfo)) { + /* ToDo:: ASSERT */ + ASSERT(prAdapter->fgIsP2PRegistered); + if (prAdapter->rWifiVar.ucApUapsd + && (prSetP2P->u4Mode != RUNNING_P2P_MODE)) { + DBGLOG(OID, INFO, + "wlanoidSetP2pMode Default enable ApUapsd\n"); + setApUapsdEnable(prAdapter, TRUE); + } + } else { + DBGLOG(P2P, ERROR, "P2P Launch Failed\n"); + status = WLAN_STATUS_FAILURE; + } + + } else { + if (prAdapter->fgIsP2PRegistered) + p2pRemove(prAdapter->prGlueInfo); + + } + +#if 0 + prP2pNetdevRegMsg = (struct MSG_P2P_NETDEV_REGISTER *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + (sizeof(struct MSG_P2P_NETDEV_REGISTER))); + + 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 = (uint8_t) prSetP2P->u4Mode; + + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prP2pNetdevRegMsg, MSG_SEND_METHOD_BUF); +#endif + + return status; + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set the GTK rekey data + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetGtkRekeyData(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + struct WIFI_CMD *prWifiCmd; + uint8_t ucCmdSeqNum; + struct BSS_INFO *prBssInfo; + + DBGLOG(REQ, INFO, "wlanoidSetGtkRekeyData\n"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(RSN, WARN, + "Fail in set rekey! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + prBssInfo = prAdapter->prAisBssInfo; + + *pu4SetInfoLen = u4SetBufferLen; + + prGlueInfo = prAdapter->prGlueInfo; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + (CMD_HDR_SIZE + sizeof(struct PARAM_GTK_REKEY_DATA))); + + 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 PARAM_GTK_REKEY_DATA cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof( + struct PARAM_GTK_REKEY_DATA); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = g_fgIsOid; + prCmdInfo->ucCID = CMD_ID_SET_GTK_REKEY_DATA; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u4SetBufferLen; + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + + /* Setup WIFI_CMD_T */ + prWifiCmd = (struct WIFI_CMD *) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + if (u4SetBufferLen > 0 && pvSetBuffer != NULL) + kalMemCopy(prWifiCmd->aucBuffer, (uint8_t *) pvSetBuffer, + u4SetBufferLen); + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, + (struct QUE_ENTRY *) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; + +} /* wlanoidSetGtkRekeyData */ + +#if CFG_SUPPORT_SCHED_SCAN +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to request starting of schedule scan + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. + * \param[in] u4SetBufferLen The length of the set buffer. + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed + * due to invalid length of the set buffer, returns + * the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_ADAPTER_NOT_READY + * \retval WLAN_STATUS_INVALID_LENGTH + * \retval WLAN_STATUS_INVALID_DATA + * + * \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetStartSchedScan(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_SCHED_SCAN_REQUEST *prSchedScanRequest; + + DEBUGFUNC("wlanoidSetStartSchedScan()"); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, + "Fail in set scheduled scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pu4SetInfoLen); + *pu4SetInfoLen = 0; + + if (u4SetBufferLen != sizeof(struct + PARAM_SCHED_SCAN_REQUEST)) + return WLAN_STATUS_INVALID_LENGTH; + else if (pvSetBuffer == NULL) + return WLAN_STATUS_INVALID_DATA; + else if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == + PARAM_MEDIA_STATE_CONNECTED + && prAdapter->fgEnOnlineScan == FALSE) + return WLAN_STATUS_FAILURE; + + if (prAdapter->fgIsRadioOff) { + DBGLOG(REQ, WARN, + "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + prSchedScanRequest = (struct PARAM_SCHED_SCAN_REQUEST *) + pvSetBuffer; + + if (scnFsmSchedScanRequest(prAdapter, + prSchedScanRequest) == TRUE) + return WLAN_STATUS_SUCCESS; + else + return WLAN_STATUS_FAILURE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to request termination of schedule scan + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. + * \param[in] u4SetBufferLen The length of the set buffer. + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed + * due to invalid length of the set buffer, returns + * the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_ADAPTER_NOT_READY + * \retval WLAN_STATUS_INVALID_LENGTH + * \retval WLAN_STATUS_INVALID_DATA + * + * \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetStopSchedScan(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t ret; + + ASSERT(prAdapter); + + /* ask SCN module to stop scan request */ + if (scnFsmSchedScanStopRequest(prAdapter) == TRUE) + ret = WLAN_STATUS_SUCCESS; + else { + DBGLOG(REQ, WARN, "scnFsmSchedScanStopRequest failed.\n"); + ret = WLAN_STATUS_FAILURE; + } + return ret; +} +#endif /* CFG_SUPPORT_SCHED_SCAN */ + +#if CFG_M0VE_BA_TO_DRIVER +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to reset BA scoreboard. + * + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanoidResetBAScoreboard(IN struct ADAPTER * + prAdapter, IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen) { + uint32_t rStatus; + + DEBUGFUNC("wlanoidResetBAScoreboard"); + DBGLOG(REQ, WARN, "[Puff]wlanoidResetBAScoreboard\n"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_RESET_BA_SCOREBOARD, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + TRUE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + u4SetBufferLen, /* u4SetQueryInfoLen */ + (uint8_t *) pvSetBuffer, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + /* ASSERT(rStatus == WLAN_STATUS_PENDING); */ + + return rStatus; + +} + +#endif + +#if CFG_SUPPORT_BATCH_SCAN + +#define CMD_WLS_BATCHING "WLS_BATCHING" + +#define BATCHING_SET "SET" +#define BATCHING_GET "GET" +#define BATCHING_STOP "STOP" + +#define PARAM_SCANFREQ "SCANFREQ" +#define PARAM_MSCAN "MSCAN" +#define PARAM_BESTN "BESTN" +#define PARAM_CHANNEL "CHANNEL" +#define PARAM_RTT "RTT" + +uint32_t +batchSetCmd(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4WritenLen) { + struct CHANNEL_INFO *prRfChannelInfo; + struct CMD_BATCH_REQ rCmdBatchReq; + + uint32_t rStatus = WLAN_STATUS_SUCCESS; + int8_t *head, *p, *p2; + uint32_t tokens; + int32_t scanfreq, mscan, bestn, rtt; + char *pcTemp; + /* CHAR c_scanfreq[4], c_mscan[4], c_bestn[4], c_rtt[4], c_channel[100]; + */ + /* INT_32 ch_type; */ + uint32_t u4Value = 0; + int32_t i4Ret = 0; + + DBGLOG(SCN, TRACE, "[BATCH] command=%s, len=%u\n", + (char *)pvSetBuffer, u4SetBufferLen); + + if (!pu4WritenLen) + return -EINVAL; + *pu4WritenLen = 0; + + if (u4SetBufferLen < kalStrLen(CMD_WLS_BATCHING)) { + DBGLOG(SCN, TRACE, "[BATCH] invalid len %d\n", + u4SetBufferLen); + return -EINVAL; + } + + head = pvSetBuffer + kalStrLen(CMD_WLS_BATCHING) + 1; + kalMemSet(&rCmdBatchReq, 0, sizeof(struct CMD_BATCH_REQ)); + + if (!kalStrnCmp(head, BATCHING_SET, + kalStrLen(BATCHING_SET))) { + + DBGLOG(SCN, TRACE, "XXX Start Batch Scan XXX\n"); + + head += kalStrLen(BATCHING_SET) + 1; + + /* SCANFREQ, MSCAN, BESTN */ + tokens = sscanf(head, "SCANFREQ=%d MSCAN=%d BESTN=%d", + &scanfreq, &mscan, &bestn); + if (tokens != 3) { + DBGLOG(SCN, TRACE, + "[BATCH] Parse fail: tokens=%d, SCANFREQ=%d MSCAN=%d BESTN=%d\n", + tokens, scanfreq, mscan, bestn); + return -EINVAL; + } + /* RTT */ + p = kalStrStr(head, PARAM_RTT); + if (!p) { + DBGLOG(SCN, TRACE, "[BATCH] Parse RTT fail. head=%s\n", + head); + return -EINVAL; + } + tokens = sscanf(p, "RTT=%d", &rtt); + if (tokens != 1) { + DBGLOG(SCN, TRACE, + "[BATCH] Parse fail: tokens=%d, rtt=%d\n", + tokens, rtt); + return -EINVAL; + } + /* CHANNEL */ + p = kalStrStr(head, PARAM_CHANNEL); + if (!p) { + DBGLOG(SCN, TRACE, "[BATCH] Parse CHANNEL fail(1)\n"); + return -EINVAL; + } + head = p; + p = kalStrChr(head, '>'); + if (!p) { + DBGLOG(SCN, TRACE, "[BATCH] Parse CHANNEL fail(2)\n"); + return -EINVAL; + } + /* else { + * p = '.'; // remove '>' because sscanf can not parse <%s> + * } + */ + /* tokens = sscanf(head, "CHANNEL=<%s", c_channel); + * if (tokens != 1) { + * DBGLOG(SCN, TRACE, "[BATCH] Parse fail: tokens=%d, + * CHANNEL=<%s>\n", tokens, c_channel); + * return -EINVAL; + * } + */ + rCmdBatchReq.ucChannelType = SCAN_CHANNEL_SPECIFIED; + rCmdBatchReq.ucChannelListNum = 0; + prRfChannelInfo = &rCmdBatchReq.arChannelList[0]; + p = head + kalStrLen(PARAM_CHANNEL) + 2; /* c_channel; */ + pcTemp = (char *)p; + while ((p2 = kalStrSep(&pcTemp, ",")) != NULL) { + if (p2 == NULL || *p2 == 0) + break; + if (*p2 == '\0') + continue; + if (*p2 == 'A') { + rCmdBatchReq.ucChannelType = + rCmdBatchReq.ucChannelType == + SCAN_CHANNEL_2G4 ? + SCAN_CHANNEL_FULL : SCAN_CHANNEL_5G; + } else if (*p2 == 'B') { + rCmdBatchReq.ucChannelType = + rCmdBatchReq.ucChannelType == + SCAN_CHANNEL_5G ? + SCAN_CHANNEL_FULL : SCAN_CHANNEL_2G4; + } else { + + /* Translate Freq from MHz to channel number. */ + /* prRfChannelInfo->ucChannelNum = + * kalStrtol(p2, NULL, 0); + */ + i4Ret = kalkStrtou32(p2, 0, &u4Value); + if (i4Ret) + DBGLOG(SCN, TRACE, + "parse ucChannelNum error i4Ret=%d\n", + i4Ret); + prRfChannelInfo->ucChannelNum = + (uint8_t) u4Value; + DBGLOG(SCN, TRACE, + "Scanning Channel:%d, freq: %d\n", + prRfChannelInfo->ucChannelNum, + nicChannelNum2Freq( + prRfChannelInfo->ucChannelNum)); + prRfChannelInfo->ucBand = + prRfChannelInfo->ucChannelNum < 15 + ? BAND_2G4 : BAND_5G; + + rCmdBatchReq.ucChannelListNum++; + if (rCmdBatchReq.ucChannelListNum >= 32) + break; + prRfChannelInfo++; + } + } + + /* set channel for test */ +#if 0 + rCmdBatchReq.ucChannelType = + 4; /* SCAN_CHANNEL_SPECIFIED; */ + rCmdBatchReq.ucChannelListNum = 0; + prRfChannelInfo = &rCmdBatchReq.arChannelList[0]; + for (i = 1; i <= 14; i++) { + + /* filter out some */ + if (i == 1 || i == 5 || i == 11) + continue; + + /* Translate Freq from MHz to channel number. */ + prRfChannelInfo->ucChannelNum = i; + DBGLOG(SCN, TRACE, "Scanning Channel:%d, freq: %d\n", + prRfChannelInfo->ucChannelNum, + nicChannelNum2Freq( + prRfChannelInfo->ucChannelNum)); + prRfChannelInfo->ucBand = BAND_2G4; + + rCmdBatchReq.ucChannelListNum++; + prRfChannelInfo++; + } +#endif +#if 0 + rCmdBatchReq.ucChannelType = 0; /* SCAN_CHANNEL_FULL; */ +#endif + + rCmdBatchReq.u4Scanfreq = scanfreq; + rCmdBatchReq.ucMScan = mscan > CFG_BATCH_MAX_MSCAN ? + CFG_BATCH_MAX_MSCAN : mscan; + rCmdBatchReq.ucBestn = bestn; + rCmdBatchReq.ucRtt = rtt; + DBGLOG(SCN, TRACE, + "[BATCH] SCANFREQ=%d MSCAN=%d BESTN=%d RTT=%d\n", + rCmdBatchReq.u4Scanfreq, rCmdBatchReq.ucMScan, + rCmdBatchReq.ucBestn, rCmdBatchReq.ucRtt); + + if (rCmdBatchReq.ucChannelType != SCAN_CHANNEL_SPECIFIED) { + DBGLOG(SCN, TRACE, "[BATCH] CHANNELS = %s\n", + rCmdBatchReq.ucChannelType == SCAN_CHANNEL_FULL ? + "FULL" : rCmdBatchReq.ucChannelType == + SCAN_CHANNEL_2G4 ? "2.4G all" : "5G all"); + } else { + DBGLOG(SCN, TRACE, "[BATCH] CHANNEL list\n"); + prRfChannelInfo = &rCmdBatchReq.arChannelList[0]; + for (tokens = 0; tokens < rCmdBatchReq.ucChannelListNum; + tokens++) { + DBGLOG(SCN, TRACE, "[BATCH] %s, %d\n", + prRfChannelInfo->ucBand + == BAND_2G4 ? "2.4G" : "5G", + prRfChannelInfo->ucChannelNum); + prRfChannelInfo++; + } + } + + rCmdBatchReq.ucSeqNum = 1; + rCmdBatchReq.ucNetTypeIndex = KAL_NETWORK_TYPE_AIS_INDEX; + rCmdBatchReq.ucCmd = SCAN_BATCH_REQ_START; + + *pu4WritenLen = kalSnprintf(pvSetBuffer, 3, "%d", + rCmdBatchReq.ucMScan); + + } else if (!kalStrnCmp(head, BATCHING_STOP, + kalStrLen(BATCHING_STOP))) { + + DBGLOG(SCN, TRACE, "XXX Stop Batch Scan XXX\n"); + + rCmdBatchReq.ucSeqNum = 1; + rCmdBatchReq.ucNetTypeIndex = KAL_NETWORK_TYPE_AIS_INDEX; + rCmdBatchReq.ucCmd = SCAN_BATCH_REQ_STOP; + } else { + return -EINVAL; + } + + rStatus = wlanSendSetQueryCmd(prAdapter, CMD_ID_SET_BATCH_REQ, + TRUE, FALSE, g_fgIsOid, NULL, NULL, + sizeof(struct CMD_BATCH_REQ), + (uint8_t *) &rCmdBatchReq, NULL, 0); + + /* kalMemSet(pvSetBuffer, 0, u4SetBufferLen); */ + /* rStatus = kalSnprintf(pvSetBuffer, 2, "%s", "OK"); */ + + /* exit: */ + return rStatus; +} + +uint32_t +batchGetCmd(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct CMD_BATCH_REQ rCmdBatchReq; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct EVENT_BATCH_RESULT *prEventBatchResult; + /* UINT_32 i; */ + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + prEventBatchResult = (struct EVENT_BATCH_RESULT *) + pvQueryBuffer; + + DBGLOG(SCN, TRACE, "XXX Get Batch Scan Result (%d) XXX\n", + prEventBatchResult->ucScanCount); + + *pu4QueryInfoLen = sizeof(struct EVENT_BATCH_RESULT); + + rCmdBatchReq.ucSeqNum = 2; + rCmdBatchReq.ucCmd = SCAN_BATCH_REQ_RESULT; + rCmdBatchReq.ucMScan = + prEventBatchResult->ucScanCount; /* Get which round result */ + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_BATCH_REQ, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventBatchScanResult, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_BATCH_REQ), + (uint8_t *) &rCmdBatchReq, + (void *) pvQueryBuffer, + u4QueryBufferLen); + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] prAdapter Pointer to the Adapter structure + * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set + * \param[in] u4SetBufferLen The length of the set buffer + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed due to invalid length of + * the set buffer, returns the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. + * \retval WLAN_STATUS_INVALID_LENGTH + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetBatchScanReq(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + return batchSetCmd(prAdapter, pvSetBuffer, u4SetBufferLen, + pu4SetInfoLen); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[out] pvQueryBuffer A pointer to the buffer that holds the result of + * the query. + * \param[in] u4QueryBufferLen The length of the query buffer. + * \param[out] pu4QueryInfoLen If the call is successful, returns the number of + * bytes written into the query buffer. If the call + * failed due to invalid length of the query buffer, + * returns the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryBatchScanResult(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + return batchGetCmd(prAdapter, pvQueryBuffer, + u4QueryBufferLen, pu4QueryInfoLen); + +} /* end of wlanoidQueryBatchScanResult() */ + +#endif /* CFG_SUPPORT_BATCH_SCAN */ + +#if CFG_SUPPORT_PASSPOINT +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called by HS2.0 to set the assoc info, which is needed + * to add to Association request frame while join HS2.0 AP. + * + * \param[in] prAdapter Pointer to the Adapter structure + * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set + * \param[in] u4SetBufferLen The length of the set buffer + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed due to invalid length of + * the set buffer, returns the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. + * \retval WLAN_STATUS_INVALID_LENGTH + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetHS20Info(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct IE_HS20_INDICATION *prHS20IndicationIe; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + DEBUGFUNC("wlanoidSetHS20AssocInfo"); + DBGLOG(OID, LOUD, "\r\n"); + + if (u4SetBufferLen == 0) + return WLAN_STATUS_INVALID_LENGTH; + + *pu4SetInfoLen = u4SetBufferLen; + + prHS20IndicationIe = (struct IE_HS20_INDICATION *) + pvSetBuffer; + + prAdapter->prGlueInfo->ucHotspotConfig = + prHS20IndicationIe->ucHotspotConfig; + prAdapter->prGlueInfo->fgConnectHS20AP = TRUE; + + DBGLOG(SEC, TRACE, "HS20 IE sz %u\n", u4SetBufferLen); + + kalMemCopy(prAdapter->prGlueInfo->aucHS20AssocInfoIE, + pvSetBuffer, u4SetBufferLen); + prAdapter->prGlueInfo->u2HS20AssocInfoIELen = + (uint16_t) u4SetBufferLen; + DBGLOG(SEC, TRACE, "HS20 Assoc Info IE sz %u\n", + u4SetBufferLen); + + return WLAN_STATUS_SUCCESS; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called by WSC to set the assoc info, which is needed + * to add to Association request frame while join WPS AP. + * + * \param[in] prAdapter Pointer to the Adapter structure + * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set + * \param[in] u4SetBufferLen The length of the set buffer + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed due to invalid length of + * the set buffer, returns the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. + * \retval WLAN_STATUS_INVALID_LENGTH + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetInterworkingInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called by WSC to set the Roaming Consortium IE info, + * which is needed to add to Association request frame while join WPS AP. + * + * \param[in] prAdapter Pointer to the Adapter structure + * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set + * \param[in] u4SetBufferLen The length of the set buffer + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed due to invalid length of + * the set buffer, returns the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. + * \retval WLAN_STATUS_INVALID_LENGTH + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetRoamingConsortiumIEInfo(IN struct ADAPTER * + prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set_bssid_pool + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] pvSetBuffer Pointer to the buffer that holds the data to be + * set. + * \param[in] u4SetBufferLen The length of the set buffer. + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed + * due to invalid length of the set buffer, returns + * the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + * \retval WLAN_STATUS_ADAPTER_NOT_READY + * \retval WLAN_STATUS_MULTICAST_FULL + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetHS20BssidPool(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (u4SetBufferLen < sizeof(struct + PARAM_HS20_SET_BSSID_POOL)) { + *pu4SetInfoLen = sizeof(struct PARAM_HS20_SET_BSSID_POOL); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + rWlanStatus = hs20SetBssidPool(prAdapter, pvSetBuffer, + KAL_NETWORK_TYPE_AIS_INDEX); + + return rWlanStatus; +} /* end of wlanoidSendHS20GASRequest() */ + +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_SNIFFER +uint32_t +wlanoidSetMonitor(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_MONITOR_SET_STRUCT *prMonitorSetInfo; + struct CMD_MONITOR_SET_INFO rCmdMonitorSetInfo; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidSetMonitor"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct + PARAM_CUSTOM_MONITOR_SET_STRUCT); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_MONITOR_SET_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prMonitorSetInfo = (struct PARAM_CUSTOM_MONITOR_SET_STRUCT + *) pvSetBuffer; + + rCmdMonitorSetInfo.ucEnable = prMonitorSetInfo->ucEnable; + rCmdMonitorSetInfo.ucBand = prMonitorSetInfo->ucBand; + rCmdMonitorSetInfo.ucPriChannel = + prMonitorSetInfo->ucPriChannel; + rCmdMonitorSetInfo.ucSco = prMonitorSetInfo->ucSco; + rCmdMonitorSetInfo.ucChannelWidth = + prMonitorSetInfo->ucChannelWidth; + rCmdMonitorSetInfo.ucChannelS1 = + prMonitorSetInfo->ucChannelS1; + rCmdMonitorSetInfo.ucChannelS2 = + prMonitorSetInfo->ucChannelS2; + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_MONITOR, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_MONITOR_SET_INFO), + (uint8_t *) &rCmdMonitorSetInfo, + pvSetBuffer, + u4SetBufferLen); +#if CFG_SUPPORT_TX_BEACON_STA_MODE + if (rCmdMonitorSetInfo.ucEnable != 0) + nicActivateNetwork(prAdapter, 0); + else + nicDeactivateNetwork(prAdapter, 0); +#endif + return rWlanStatus; +} +#endif + + +#if CFG_SUPPORT_ADVANCE_CONTROL +uint32_t +wlanoidAdvCtrl(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + return wlanAdvCtrl(prAdapter, + pvQueryBuffer, + u4QueryBufferLen, + pu4QueryInfoLen, + g_fgIsOid); +} + +uint32_t +wlanAdvCtrl(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen, + IN uint8_t fgIsOid) +{ + struct CMD_ADV_CONFIG_HEADER *cmd; + uint16_t type = 0; + uint32_t len; + u_int8_t fgSetQuery = FALSE; + u_int8_t fgNeedResp = TRUE; + + DEBUGFUNC("wlanoidAdvCtrl"); + + 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(uint32_t); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(*cmd)) { + DBGLOG(REQ, WARN, "Too short length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + cmd = (struct CMD_ADV_CONFIG_HEADER *)pvQueryBuffer; + + if (cmd->u2Type & CMD_ADV_CONTROL_SET) { + fgSetQuery = TRUE; + fgNeedResp = FALSE; + } + + type = cmd->u2Type; + type &= ~CMD_ADV_CONTROL_SET; + DBGLOG(RSN, INFO, "%s cmd type %d\n", __func__, cmd->u2Type); + switch (type) { + case CMD_PTA_CONFIG_TYPE: + *pu4QueryInfoLen = sizeof(struct CMD_PTA_CONFIG); + len = sizeof(struct CMD_PTA_CONFIG); + break; +#ifdef CFG_SUPPORT_EXT_PTA_DEBUG_COMMAND + case CMD_EXT_PTA_CONFIG_TYPE: + *pu4QueryInfoLen = sizeof(CMD_PTA_CONFIG_T); + len = sizeof(CMD_PTA_CONFIG_T); + break; +#endif + case CMD_GET_REPORT_TYPE: + *pu4QueryInfoLen = sizeof(struct CMD_GET_TRAFFIC_REPORT); + len = sizeof(struct CMD_GET_TRAFFIC_REPORT); + break; + case CMD_NOISE_HISTOGRAM_TYPE: +#if CFG_IPI_2CHAIN_SUPPORT + case CMD_NOISE_HISTOGRAM_TYPE2: +#endif + *pu4QueryInfoLen = sizeof(struct CMD_NOISE_HISTOGRAM_REPORT); + len = sizeof(struct CMD_NOISE_HISTOGRAM_REPORT); + break; +#ifdef CFG_SUPPORT_ADMINCTRL + case CMD_ADMINCTRL_CONFIG_TYPE: + *pu4QueryInfoLen = sizeof(struct CMD_ADMIN_CTRL_CONFIG); + len = sizeof(struct CMD_ADMIN_CTRL_CONFIG); + break; +#endif + default: + return WLAN_STATUS_INVALID_LENGTH; + } + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ADV_CONTROL, + fgSetQuery, + fgNeedResp, + fgIsOid, + nicCmdEventQueryAdvCtrl, + nicOidCmdTimeoutCommon, + len, (uint8_t *)cmd, + pvQueryBuffer, u4QueryBufferLen); +} +#endif + + +#if CFG_SUPPORT_MSP +uint32_t +wlanoidQueryWlanInfo(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + + return wlanQueryWlanInfo(prAdapter, + pvQueryBuffer, + u4QueryBufferLen, + pu4QueryInfoLen, + g_fgIsOid); +} + +uint32_t +wlanQueryWlanInfo(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen, + IN uint8_t fgIsOid) { + struct PARAM_HW_WLAN_INFO *prHwWlanInfo; + + DEBUGFUNC("wlanoidQueryWlanInfo"); + DBGLOG(REQ, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(struct PARAM_HW_WLAN_INFO); + + 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(uint32_t); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(struct PARAM_HW_WLAN_INFO)) { + DBGLOG(REQ, WARN, "Too short length %u\n", + u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prHwWlanInfo = (struct PARAM_HW_WLAN_INFO *)pvQueryBuffer; + DBGLOG(RSN, INFO, + "MT6632 : wlanoidQueryWlanInfo index = %d\n", + prHwWlanInfo->u4Index); + + /* *pu4QueryInfoLen = 8 + prRxStatistics->u4TotalNum; */ + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_WLAN_INFO, + FALSE, + TRUE, + fgIsOid, + nicCmdEventQueryWlanInfo, + nicOidCmdTimeoutCommon, + sizeof(struct PARAM_HW_WLAN_INFO), + (uint8_t *)prHwWlanInfo, + pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryWlanInfo */ + + +uint32_t +wlanoidQueryMibInfo(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_HW_MIB_INFO *prHwMibInfo; + + DEBUGFUNC("wlanoidQueryMibInfo"); + DBGLOG(REQ, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(struct PARAM_HW_MIB_INFO); + + 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(uint32_t); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(struct + PARAM_HW_MIB_INFO)) { + DBGLOG(REQ, WARN, "Too short length %u\n", + u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prHwMibInfo = (struct PARAM_HW_MIB_INFO *)pvQueryBuffer; + DBGLOG(RSN, INFO, + "MT6632 : wlanoidQueryMibInfo index = %d\n", + prHwMibInfo->u4Index); + + /* *pu4QueryInfoLen = 8 + prRxStatistics->u4TotalNum; */ + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_MIB_INFO, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventQueryMibInfo, + nicOidCmdTimeoutCommon, + sizeof(struct PARAM_HW_MIB_INFO), + (uint8_t *)prHwMibInfo, + pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryMibInfo */ +#endif + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set FW log to Host. + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetFwLog2Host( + IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct CMD_FW_LOG_2_HOST_CTRL *prFwLog2HostCtrl; + + DEBUGFUNC("wlanoidSetFwLog2Host"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct CMD_FW_LOG_2_HOST_CTRL); + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, + "Fail in set FW log to Host! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4SetBufferLen < sizeof(struct + CMD_FW_LOG_2_HOST_CTRL)) { + DBGLOG(REQ, WARN, "Too short length %d\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prFwLog2HostCtrl = (struct CMD_FW_LOG_2_HOST_CTRL *) + pvSetBuffer; + + DBGLOG(REQ, INFO, "McuDest %d, LogType %d\n", + prFwLog2HostCtrl->ucMcuDest, + prFwLog2HostCtrl->ucFwLog2HostCtrl); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_FW_LOG_2_HOST, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_FW_LOG_2_HOST_CTRL), + (uint8_t *)prFwLog2HostCtrl, + pvSetBuffer, u4SetBufferLen); +} + +uint32_t +wlanoidNotifyFwSuspend( + IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct CMD_SUSPEND_MODE_SETTING *prSuspendCmd; + + if (!prAdapter || !pvSetBuffer) + return WLAN_STATUS_INVALID_DATA; + + prSuspendCmd = (struct CMD_SUSPEND_MODE_SETTING *) + pvSetBuffer; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_SUSPEND_MODE, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_SUSPEND_MODE_SETTING), + (uint8_t *)prSuspendCmd, + NULL, + 0); +} + +uint32_t +wlanoidQueryCnm( + IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_GET_CNM_T *prCnmInfo = NULL; + + DEBUGFUNC("wlanoidQueryLinkSpeed"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (prAdapter->fgIsEnableLpdvt) + return WLAN_STATUS_NOT_SUPPORTED; + + *pu4QueryInfoLen = sizeof(struct PARAM_GET_CNM_T); + + if (u4QueryBufferLen < sizeof(struct PARAM_GET_CNM_T)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + prCnmInfo = (struct PARAM_GET_CNM_T *)pvQueryBuffer; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_CNM, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventQueryCnmInfo, + nicOidCmdTimeoutCommon, + sizeof(struct PARAM_GET_CNM_T), + (uint8_t *)prCnmInfo, + pvQueryBuffer, u4QueryBufferLen); +} + +uint32_t +wlanoidPacketKeepAlive(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct PARAM_PACKET_KEEPALIVE_T *prPacket; + + DEBUGFUNC("wlanoidPacketKeepAlive"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(struct PARAM_PACKET_KEEPALIVE_T); + + /* Check for query buffer length */ + if (u4SetBufferLen < *pu4SetInfoLen) { + DBGLOG(OID, WARN, "Too short length %u\n", u4SetBufferLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + prPacket = (struct PARAM_PACKET_KEEPALIVE_T *) + kalMemAlloc(sizeof(struct PARAM_PACKET_KEEPALIVE_T), + VIR_MEM_TYPE); + if (!prPacket) { + DBGLOG(OID, ERROR, + "Can not alloc memory for struct PARAM_PACKET_KEEPALIVE_T\n"); + return -ENOMEM; + } + kalMemCopy(prPacket, pvSetBuffer, + sizeof(struct PARAM_PACKET_KEEPALIVE_T)); + + DBGLOG(OID, INFO, "enable=%d, index=%d\r\n", + prPacket->enable, prPacket->index); + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_WFC_KEEP_ALIVE, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct PARAM_PACKET_KEEPALIVE_T), + (uint8_t *)prPacket, NULL, 0); + kalMemFree(prPacket, VIR_MEM_TYPE, + sizeof(struct PARAM_PACKET_KEEPALIVE_T)); + return rStatus; +} + +#if CFG_SUPPORT_DBDC +uint32_t +wlanoidSetDbdcEnable( + IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint8_t ucDBDCEnable; + + if (!prAdapter || !pvSetBuffer) + return WLAN_STATUS_INVALID_DATA; + + kalMemCopy(&ucDBDCEnable, pvSetBuffer, 1); + cnmUpdateDbdcSetting(prAdapter, ucDBDCEnable); + + return WLAN_STATUS_SUCCESS; +} +#endif /*#if CFG_SUPPORT_DBDC*/ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set tx target power base. + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQuerySetTxTargetPower(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_SET_TX_TARGET_POWER + *prSetTxTargetPowerInfo; + struct CMD_SET_TX_TARGET_POWER rCmdSetTxTargetPower; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQuerySetTxTargetPower"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct + PARAM_CUSTOM_SET_TX_TARGET_POWER *); + + if (u4SetBufferLen < sizeof(struct + PARAM_CUSTOM_SET_TX_TARGET_POWER *)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prSetTxTargetPowerInfo = + (struct PARAM_CUSTOM_SET_TX_TARGET_POWER *) pvSetBuffer; + + kalMemSet(&rCmdSetTxTargetPower, 0, + sizeof(struct CMD_SET_TX_TARGET_POWER)); + + rCmdSetTxTargetPower.ucTxTargetPwr = + prSetTxTargetPowerInfo->ucTxTargetPwr; + + DBGLOG(INIT, INFO, + "MT6632 : wlanoidQuerySetTxTargetPower =%x dbm\n", + rCmdSetTxTargetPower.ucTxTargetPwr); + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_TX_PWR, + TRUE, /* fgSetQuery Bit: True->write False->read */ + FALSE, /* fgNeedResp */ + g_fgIsOid, /* fgIsOid*/ + nicCmdEventSetCommon, /* REF: wlanoidSetDbdcEnable */ + nicOidCmdTimeoutCommon, + sizeof(struct CMD_ACCESS_EFUSE), + (uint8_t *) (&rCmdSetTxTargetPower), pvSetBuffer, + u4SetBufferLen); + + return rWlanStatus; +} + +#if (CFG_SUPPORT_DFS_MASTER == 1) +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set rdd report. + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQuerySetRddReport(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_SET_RDD_REPORT *prSetRddReport; + struct CMD_RDD_ON_OFF_CTRL *prCmdRddOnOffCtrl; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQuerySetRddReport"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CUSTOM_SET_RDD_REPORT + *); + + ASSERT(pvSetBuffer); + + prSetRddReport = (struct PARAM_CUSTOM_SET_RDD_REPORT *) + pvSetBuffer; + + prCmdRddOnOffCtrl = (struct CMD_RDD_ON_OFF_CTRL *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(*prCmdRddOnOffCtrl)); + + ASSERT(prCmdRddOnOffCtrl); + if (prCmdRddOnOffCtrl == NULL) { + DBGLOG(INIT, ERROR, "prCmdRddOnOffCtrl is NULL"); + return WLAN_STATUS_FAILURE; + } + + prCmdRddOnOffCtrl->ucDfsCtrl = RDD_RADAR_EMULATE; + + prCmdRddOnOffCtrl->ucRddIdx = prSetRddReport->ucDbdcIdx; + + if (prCmdRddOnOffCtrl->ucRddIdx) + prCmdRddOnOffCtrl->ucRddRxSel = RDD_IN_SEL_1; + else + prCmdRddOnOffCtrl->ucRddRxSel = RDD_IN_SEL_0; + + DBGLOG(INIT, INFO, + "MT6632 : wlanoidQuerySetRddReport - DFS ctrl: %.d, RDD index: %d\n", + prCmdRddOnOffCtrl->ucDfsCtrl, prCmdRddOnOffCtrl->ucRddIdx); + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_RDD_ON_OFF_CTRL, + TRUE, /* fgSetQuery Bit: True->write False->read */ + FALSE, /* fgNeedResp */ + g_fgIsOid, /* fgIsOid*/ + nicCmdEventSetCommon, /* REF: wlanoidSetDbdcEnable */ + nicOidCmdTimeoutCommon, + sizeof(*prCmdRddOnOffCtrl), + (uint8_t *) (prCmdRddOnOffCtrl), pvSetBuffer, + u4SetBufferLen); + + cnmMemFree(prAdapter, prCmdRddOnOffCtrl); + + return rWlanStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set rdd report. + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQuerySetRadarDetectMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_CUSTOM_SET_RADAR_DETECT_MODE + *prSetRadarDetectMode; + struct CMD_RDD_ON_OFF_CTRL *prCmdRddOnOffCtrl; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQuerySetRadarDetectMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = + sizeof(struct PARAM_CUSTOM_SET_RADAR_DETECT_MODE *); + + ASSERT(pvSetBuffer); + + prSetRadarDetectMode = + (struct PARAM_CUSTOM_SET_RADAR_DETECT_MODE *) pvSetBuffer; + + prCmdRddOnOffCtrl = (struct CMD_RDD_ON_OFF_CTRL *)cnmMemAlloc( + prAdapter, RAM_TYPE_MSG, + sizeof(*prCmdRddOnOffCtrl)); + + ASSERT(prCmdRddOnOffCtrl); + if (prCmdRddOnOffCtrl == NULL) { + DBGLOG(INIT, ERROR, "prCmdRddOnOffCtrl is NULL"); + return WLAN_STATUS_FAILURE; + } + + prCmdRddOnOffCtrl->ucDfsCtrl = RDD_DET_MODE; + + prCmdRddOnOffCtrl->ucSetVal = + prSetRadarDetectMode->ucRadarDetectMode; + + DBGLOG(INIT, INFO, + "MT6632 : wlanoidQuerySetRadarDetectMode - DFS ctrl: %.d, Radar Detect Mode: %d\n", + prCmdRddOnOffCtrl->ucDfsCtrl, prCmdRddOnOffCtrl->ucSetVal); + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_RDD_ON_OFF_CTRL, + TRUE, /* fgSetQuery Bit: True->write False->read */ + FALSE, /* fgNeedResp */ + g_fgIsOid, /* fgIsOid*/ + nicCmdEventSetCommon, /* REF: wlanoidSetDbdcEnable */ + nicOidCmdTimeoutCommon, + sizeof(*prCmdRddOnOffCtrl), + (uint8_t *) (prCmdRddOnOffCtrl), + pvSetBuffer, + u4SetBufferLen); + + cnmMemFree(prAdapter, prCmdRddOnOffCtrl); + + return rWlanStatus; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidLinkDown(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + DEBUGFUNC("wlanoidSetDisassociate"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 0; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, + "Fail in set link down! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + aisBssLinkDown(prAdapter); + + prAdapter->prGlueInfo->u4LinkDownPendFlag = TRUE; + + return WLAN_STATUS_PENDING; +} /* wlanoidSetDisassociate */ + +uint32_t +wlanoidGetTxPwrTbl(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + struct CMD_GET_TXPWR_TBL CmdPwrTbl; + struct PARAM_CMD_GET_TXPWR_TBL *prPwrTbl = NULL; + + DEBUGFUNC("wlanoidGetTxPwrTbl"); + DBGLOG(REQ, LOUD, "\n"); + + if (!prAdapter || (!pvQueryBuffer && u4QueryBufferLen) || + !pu4QueryInfoLen) + return WLAN_STATUS_INVALID_DATA; + + *pu4QueryInfoLen = sizeof(struct PARAM_CMD_GET_TXPWR_TBL); + + 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(uint32_t); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(struct PARAM_CMD_GET_TXPWR_TBL)) { + DBGLOG(REQ, WARN, "Too short length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prPwrTbl = (struct PARAM_CMD_GET_TXPWR_TBL *)pvQueryBuffer; + + CmdPwrTbl.ucCmdVer = 0x01; + CmdPwrTbl.u2CmdLen = sizeof(struct CMD_GET_TXPWR_TBL); + CmdPwrTbl.ucDbdcIdx = prPwrTbl->ucDbdcIdx; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_TXPWR_TBL, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventGetTxPwrTbl, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_GET_TXPWR_TBL), + (uint8_t *)&CmdPwrTbl, + pvQueryBuffer, + u4QueryBufferLen); + +} + +#if CFG_SUPPORT_NCHO +#define FW_CFG_KEY_NCHO_ENABLE "NCHOEnable" +#define FW_CFG_KEY_NCHO_ROAM_RCPI "RoamingRCPIValue" +#define FW_CFG_KEY_NCHO_SCN_CHANNEL_TIME "NCHOScnChannelTime" +#define FW_CFG_KEY_NCHO_SCN_HOME_TIME "NCHOScnHomeTime" +#define FW_CFG_KEY_NCHO_SCN_HOME_AWAY_TIME "NCHOScnHomeAwayTime" +#define FW_CFG_KEY_NCHO_SCN_NPROBES "NCHOScnNumProbs" +#define FW_CFG_KEY_NCHO_WES_MODE "NCHOWesMode" +#define FW_CFG_KEY_NCHO_SCAN_DFS_MODE "NCHOScnDfsMode" + +uint32_t +wlanoidSetNchoHeader(struct CMD_HEADER *prCmdHeader, + struct CMD_FORMAT_V1 *pr_cmd_v1, + char *pStr, uint32_t u4Len) { + prCmdHeader->cmdVersion = CMD_VER_1_EXT; + prCmdHeader->cmdType = CMD_TYPE_QUERY; + prCmdHeader->itemNum = 1; + prCmdHeader->cmdBufferLen = sizeof(struct CMD_FORMAT_V1); + kalMemSet(prCmdHeader->buffer, 0, MAX_CMD_BUFFER_LENGTH); + + if (!prCmdHeader || !pStr || u4Len == 0) + return WLAN_STATUS_FAILURE; + + pr_cmd_v1->itemStringLength = u4Len; + kalMemCopy(pr_cmd_v1->itemString, pStr, u4Len); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidSetNchoRoamTrigger(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + int32_t *pi4Param = NULL; + char acCmd[NCHO_CMD_MAX_LENGTH] = {0}; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoRoamTrigger"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(int32_t); + + if (u4SetBufferLen < sizeof(int32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + pi4Param = (int32_t *) pvSetBuffer; + *pi4Param = dBm_TO_RCPI(*pi4Param); /* DB to RCPI */ + if (*pi4Param < RCPI_LOW_BOUND + || *pi4Param > RCPI_HIGH_BOUND) { + DBGLOG(INIT, ERROR, "NCHO roam trigger invalid %d\n", + *pi4Param); + return WLAN_STATUS_INVALID_DATA; + } + + kalSprintf(acCmd, "%s %d", FW_CFG_KEY_NCHO_ROAM_RCPI, + *pi4Param); + rStatus = wlanFwCfgParse(prAdapter, acCmd); + if (rStatus == WLAN_STATUS_SUCCESS) { + prAdapter->rNchoInfo.i4RoamTrigger = RCPI_TO_dBm(*pi4Param); + DBGLOG(INIT, TRACE, "NCHO roam trigger is %d\n", + prAdapter->rNchoInfo.i4RoamTrigger); + } + + return rStatus; +} + +uint32_t +wlanoidQueryNchoRoamTrigger(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER cmdV1Header; + struct CMD_HEADER *prCmdV1Header = (struct CMD_HEADER *) + pvQueryBuffer; + struct CMD_FORMAT_V1 *prCmdV1 = NULL; + + DEBUGFUNC("wlanoidQueryNchoRoamTrigger"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct CMD_HEADER); + + if (u4QueryBufferLen < sizeof(struct CMD_HEADER)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgECHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + prCmdV1 = (struct CMD_FORMAT_V1 *) prCmdV1Header->buffer; + rStatus = wlanoidSetNchoHeader(prCmdV1Header, + prCmdV1, + FW_CFG_KEY_NCHO_ROAM_RCPI, + kalStrLen(FW_CFG_KEY_NCHO_ROAM_RCPI)); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "NCHO no enough memory\n"); + return rStatus; + } + kalMemCopy(&cmdV1Header, prCmdV1Header, + sizeof(struct CMD_HEADER)); + rStatus = wlanSendSetQueryCmd( + prAdapter, + CMD_ID_GET_SET_CUSTOMER_CFG, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventQueryCfgRead, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_HEADER), + (uint8_t *)&cmdV1Header, + pvQueryBuffer, + u4QueryBufferLen); + return rStatus; +} + +uint32_t +wlanoidSetNchoRoamDelta(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + int32_t *pi4Param = NULL; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoRoamDelta"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(int32_t); + + if (u4SetBufferLen < sizeof(int32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + pi4Param = (int32_t *) pvSetBuffer; + if (*pi4Param > 100) { + DBGLOG(INIT, ERROR, "NCHO roam delta invalid %d\n", + *pi4Param); + return WLAN_STATUS_INVALID_DATA; + } + + prAdapter->rNchoInfo.i4RoamDelta = *pi4Param; + DBGLOG(INIT, TRACE, "NCHO roam delta is %d\n", *pi4Param); + rStatus = WLAN_STATUS_SUCCESS; + + return rStatus; +} + +uint32_t +wlanoidQueryNchoRoamDelta(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + int32_t *pParam = NULL; + + DEBUGFUNC("wlanoidQueryNchoRoamDelta"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(int32_t *)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgECHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + pParam = (int32_t *) pvQueryBuffer; + *pParam = prAdapter->rNchoInfo.i4RoamDelta; + DBGLOG(INIT, TRACE, "NCHO roam delta is %d\n", *pParam); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidSetNchoRoamScnPeriod(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pParam = NULL; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoRoamScnPeriod"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (uint32_t *) pvSetBuffer; + + prAdapter->rNchoInfo.u4RoamScanPeriod = *pParam; + DBGLOG(INIT, TRACE, "NCHO roam scan period is %d\n", + *pParam); + rStatus = WLAN_STATUS_SUCCESS; + + return rStatus; +} + +uint32_t +wlanoidQueryNchoRoamScnPeriod(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t *pParam = NULL; + + DEBUGFUNC("wlanoidQueryNchoRoamScnPeriod"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgECHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + pParam = (uint32_t *) pvQueryBuffer; + *pParam = prAdapter->rNchoInfo.u4RoamScanPeriod; + DBGLOG(INIT, TRACE, "NCHO roam scan period is %d\n", + *pParam); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidSetNchoRoamScnChnl(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct _CFG_NCHO_SCAN_CHNL_T *prRoamScnChnl = NULL; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoRoamScnChnl"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(struct _CFG_NCHO_SCAN_CHNL_T); + + if (u4SetBufferLen < sizeof(struct _CFG_NCHO_SCAN_CHNL_T)) + return WLAN_STATUS_INVALID_LENGTH; + + prRoamScnChnl = (struct _CFG_NCHO_SCAN_CHNL_T *) + pvSetBuffer; + + kalMemCopy(&prAdapter->rNchoInfo.rRoamScnChnl, + prRoamScnChnl, *pu4SetInfoLen); + prAdapter->rNchoInfo.u4RoamScanControl = TRUE; + DBGLOG(INIT, TRACE, + "NCHO set roam scan channel num is %d\n", + prRoamScnChnl->ucChannelListNum); + rStatus = WLAN_STATUS_SUCCESS; + + + return rStatus; +} + +uint32_t +wlanoidQueryNchoRoamScnChnl(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct _CFG_NCHO_SCAN_CHNL_T *prRoamScnChnl = NULL; + + DEBUGFUNC("wlanoidQueryNchoRoamScnChnl"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(struct _CFG_NCHO_SCAN_CHNL_T)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgECHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + prRoamScnChnl = (struct _CFG_NCHO_SCAN_CHNL_T *) + pvQueryBuffer; + kalMemCopy(prRoamScnChnl, + &prAdapter->rNchoInfo.rRoamScnChnl, u4QueryBufferLen); + DBGLOG(INIT, TRACE, "NCHO roam scan channel num is %d\n", + prRoamScnChnl->ucChannelListNum); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidSetNchoRoamScnCtrl(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pParam = NULL; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoRoamScnChnl"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (uint32_t *) pvSetBuffer; + if (*pParam != TRUE && *pParam != FALSE) { + DBGLOG(INIT, ERROR, "NCHO roam scan control invalid %d\n", + *pParam); + return WLAN_STATUS_INVALID_DATA; + } + + prAdapter->rNchoInfo.u4RoamScanControl = *pParam; + DBGLOG(INIT, TRACE, "NCHO roam scan control is %d\n", + *pParam); + rStatus = WLAN_STATUS_SUCCESS; + + return rStatus; +} + +uint32_t +wlanoidQueryNchoRoamScnCtrl(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t *pParam = NULL; + + DEBUGFUNC("wlanoidQueryNchoRoamScnCtrl"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgECHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + pParam = (uint32_t *) pvQueryBuffer; + *pParam = prAdapter->rNchoInfo.u4RoamScanControl; + DBGLOG(INIT, TRACE, "NCHO roam scan control is %d\n", + *pParam); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidSetNchoScnChnlTime(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pParam = NULL; + char acCmd[NCHO_CMD_MAX_LENGTH] = {0}; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoScnChnlTime"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (uint32_t *) pvSetBuffer; + if (*pParam < 10 && *pParam > 1000) { + DBGLOG(INIT, ERROR, "NCHO scan channel time invalid %d\n", + *pParam); + return WLAN_STATUS_INVALID_DATA; + } + + kalSprintf(acCmd, "%s %d", FW_CFG_KEY_NCHO_SCN_CHANNEL_TIME, + *pParam); + rStatus = wlanFwCfgParse(prAdapter, acCmd); + if (rStatus == WLAN_STATUS_SUCCESS) { + prAdapter->rNchoInfo.u4ScanChannelTime = *pParam; + DBGLOG(INIT, TRACE, "NCHO scan channel time is %d\n", + *pParam); + } + + return rStatus; +} + +uint32_t +wlanoidQueryNchoScnChnlTime(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER cmdV1Header; + struct CMD_HEADER *prCmdV1Header = (struct CMD_HEADER *) + pvQueryBuffer; + struct CMD_FORMAT_V1 *prCmdV1 = NULL; + + DEBUGFUNC("wlanoidQueryNchoScnChnlTime"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct CMD_HEADER); + + if (u4QueryBufferLen < sizeof(struct CMD_HEADER)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgECHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + prCmdV1 = (struct CMD_FORMAT_V1 *) prCmdV1Header->buffer; + rStatus = wlanoidSetNchoHeader(prCmdV1Header, prCmdV1, + FW_CFG_KEY_NCHO_SCN_CHANNEL_TIME, + kalStrLen(FW_CFG_KEY_NCHO_SCN_CHANNEL_TIME)); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "NCHO no enough memory\n"); + return rStatus; + } + kalMemCopy(&cmdV1Header, prCmdV1Header, + sizeof(struct CMD_HEADER)); + rStatus = wlanSendSetQueryCmd( + prAdapter, + CMD_ID_GET_SET_CUSTOMER_CFG, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventQueryCfgRead, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_HEADER), + (uint8_t *)&cmdV1Header, + pvQueryBuffer, + u4QueryBufferLen); + return rStatus; +} + +uint32_t +wlanoidSetNchoScnHomeTime(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pParam = NULL; + char acCmd[NCHO_CMD_MAX_LENGTH] = {0}; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoScnHomeTime"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (uint32_t *) pvSetBuffer; + if (*pParam < 10 && *pParam > 1000) { + DBGLOG(INIT, ERROR, "NCHO scan home time invalid %d\n", + *pParam); + return WLAN_STATUS_INVALID_DATA; + } + + kalSprintf(acCmd, "%s %d", FW_CFG_KEY_NCHO_SCN_HOME_TIME, + *pParam); + DBGLOG(REQ, TRACE, "NCHO cmd is %s\n", acCmd); + rStatus = wlanFwCfgParse(prAdapter, acCmd); + if (rStatus == WLAN_STATUS_SUCCESS) { + prAdapter->rNchoInfo.u4ScanHomeTime = *pParam; + DBGLOG(INIT, TRACE, "NCHO scan home time is %d\n", *pParam); + } + + return rStatus; +} + +uint32_t +wlanoidQueryNchoScnHomeTime(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER cmdV1Header; + struct CMD_HEADER *prCmdV1Header = (struct CMD_HEADER *) + pvQueryBuffer; + struct CMD_FORMAT_V1 *prCmdV1 = NULL; + + DEBUGFUNC("wlanoidQueryNchoScnHomeTime"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct CMD_HEADER); + + if (u4QueryBufferLen < sizeof(struct CMD_HEADER)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgECHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + prCmdV1 = (struct CMD_FORMAT_V1 *) prCmdV1Header->buffer; + rStatus = wlanoidSetNchoHeader(prCmdV1Header, prCmdV1, + FW_CFG_KEY_NCHO_SCN_HOME_TIME, + kalStrLen(FW_CFG_KEY_NCHO_SCN_HOME_TIME)); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "NCHO no enough memory\n"); + return rStatus; + } + kalMemCopy(&cmdV1Header, prCmdV1Header, + sizeof(struct CMD_HEADER)); + rStatus = wlanSendSetQueryCmd( + prAdapter, + CMD_ID_GET_SET_CUSTOMER_CFG, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventQueryCfgRead, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_HEADER), + (uint8_t *)&cmdV1Header, + pvQueryBuffer, + u4QueryBufferLen); + return rStatus; +} + +uint32_t +wlanoidSetNchoScnHomeAwayTime(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pParam = NULL; + char acCmd[NCHO_CMD_MAX_LENGTH] = {0}; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoScnHomeAwayTime"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (uint32_t *) pvSetBuffer; + if (*pParam < 10 && *pParam > 1000) { + DBGLOG(INIT, ERROR, "NCHO scan home away time invalid %d\n", + *pParam); + return WLAN_STATUS_INVALID_DATA; + } + + + kalSprintf(acCmd, "%s %d", + FW_CFG_KEY_NCHO_SCN_HOME_AWAY_TIME, *pParam); + DBGLOG(REQ, TRACE, "NCHO cmd is %s\n", acCmd); + rStatus = wlanFwCfgParse(prAdapter, acCmd); + if (rStatus == WLAN_STATUS_SUCCESS) { + prAdapter->rNchoInfo.u4ScanHomeawayTime = *pParam; + DBGLOG(INIT, TRACE, "NCHO scan home away is %d\n", *pParam); + } + + return rStatus; +} + +uint32_t +wlanoidQueryNchoScnHomeAwayTime(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER cmdV1Header; + struct CMD_HEADER *prCmdV1Header = (struct CMD_HEADER *) + pvQueryBuffer; + struct CMD_FORMAT_V1 *prCmdV1 = NULL; + + DEBUGFUNC("wlanoidQueryNchoScnHomeTime"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct CMD_HEADER); + + if (u4QueryBufferLen < sizeof(struct CMD_HEADER)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgECHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + prCmdV1 = (struct CMD_FORMAT_V1 *) prCmdV1Header->buffer; + rStatus = wlanoidSetNchoHeader(prCmdV1Header, prCmdV1, + FW_CFG_KEY_NCHO_SCN_HOME_AWAY_TIME, + kalStrLen(FW_CFG_KEY_NCHO_SCN_HOME_AWAY_TIME)); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "NCHO no enough memory\n"); + return rStatus; + } + kalMemCopy(&cmdV1Header, prCmdV1Header, + sizeof(struct CMD_HEADER)); + rStatus = wlanSendSetQueryCmd( + prAdapter, + CMD_ID_GET_SET_CUSTOMER_CFG, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventQueryCfgRead, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_HEADER), + (uint8_t *)&cmdV1Header, + pvQueryBuffer, + u4QueryBufferLen); + return rStatus; +} + +uint32_t +wlanoidSetNchoScnNprobes(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pParam = NULL; + char acCmd[NCHO_CMD_MAX_LENGTH] = {0}; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoScnNprobes"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (uint32_t *) pvSetBuffer; + if (*pParam > 16) { + DBGLOG(INIT, ERROR, "NCHO scan Nprobes invalid %d\n", + *pParam); + return WLAN_STATUS_INVALID_DATA; + } + + + kalSprintf(acCmd, "%s %d", FW_CFG_KEY_NCHO_SCN_NPROBES, + *pParam); + rStatus = wlanFwCfgParse(prAdapter, acCmd); + if (rStatus == WLAN_STATUS_SUCCESS) { + prAdapter->rNchoInfo.u4ScanNProbes = *pParam; + DBGLOG(INIT, TRACE, "NCHO Nprobes is %d\n", *pParam); + } + return rStatus; +} + +uint32_t +wlanoidQueryNchoScnNprobes(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER cmdV1Header; + struct CMD_HEADER *prCmdV1Header = (struct CMD_HEADER *) + pvQueryBuffer; + struct CMD_FORMAT_V1 *prCmdV1 = NULL; + + DEBUGFUNC("wlanoidQueryNchoScnNprobes"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct CMD_HEADER); + + if (u4QueryBufferLen < sizeof(struct CMD_HEADER)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgECHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + prCmdV1 = (struct CMD_FORMAT_V1 *) prCmdV1Header->buffer; + rStatus = wlanoidSetNchoHeader(prCmdV1Header, + prCmdV1, + FW_CFG_KEY_NCHO_SCN_NPROBES, + kalStrLen(FW_CFG_KEY_NCHO_SCN_NPROBES)); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "NCHO no enough memory\n"); + return rStatus; + } + kalMemCopy(&cmdV1Header, prCmdV1Header, + sizeof(struct CMD_HEADER)); + rStatus = wlanSendSetQueryCmd( + prAdapter, + CMD_ID_GET_SET_CUSTOMER_CFG, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventQueryCfgRead, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_HEADER), + (uint8_t *)&cmdV1Header, + pvQueryBuffer, + u4QueryBufferLen); + return rStatus; +} + +uint32_t +wlanoidGetNchoReassocInfo(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct BSS_DESC *prBssDesc = NULL; + struct PARAM_CONNECT *prParamConn; + + DEBUGFUNC("wlanoidGetNchoReassocInfo"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + ASSERT(pvQueryBuffer); + + prParamConn = (struct PARAM_CONNECT *)pvQueryBuffer; + if (prAdapter->rNchoInfo.fgECHOEnabled == TRUE) { + prBssDesc = scanSearchBssDescByBssid(prAdapter, + prParamConn->pucBssid); + if (prBssDesc != NULL) { + prParamConn->u4SsidLen = prBssDesc->ucSSIDLen; + COPY_SSID(prParamConn->pucSsid, + prParamConn->u4SsidLen, + prBssDesc->aucSSID, + prBssDesc->ucSSIDLen); + rStatus = WLAN_STATUS_SUCCESS; + } + } + return rStatus; +} + +uint32_t +wlanoidSendNchoActionFrameStart(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct _NCHO_INFO_T *prNchoInfo = NULL; + struct _NCHO_ACTION_FRAME_PARAMS_T *prParamActionFrame = + NULL; + + DEBUGFUNC("wlanoidSendNchoActionFrameStart"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + + prNchoInfo = &prAdapter->rNchoInfo; + prParamActionFrame = (struct _NCHO_ACTION_FRAME_PARAMS_T *) + pvSetBuffer; + prNchoInfo->fgIsSendingAF = TRUE; + prNchoInfo->fgChGranted = FALSE; + COPY_MAC_ADDR(prNchoInfo->rParamActionFrame.aucBssid, + prParamActionFrame->aucBssid); + prNchoInfo->rParamActionFrame.i4channel = + prParamActionFrame->i4channel; + prNchoInfo->rParamActionFrame.i4DwellTime = + prParamActionFrame->i4DwellTime; + prNchoInfo->rParamActionFrame.i4len = + prParamActionFrame->i4len; + kalMemCopy(prNchoInfo->rParamActionFrame.aucData, + prParamActionFrame->aucData, + prParamActionFrame->i4len); + DBGLOG(INIT, TRACE, "NCHO send ncho action frame start\n"); + rStatus = WLAN_STATUS_SUCCESS; + + return rStatus; +} + +uint32_t +wlanoidSendNchoActionFrameEnd(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSendNchoActionFrameEnd"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + prAdapter->rNchoInfo.fgIsSendingAF = FALSE; + prAdapter->rNchoInfo.fgChGranted = TRUE; + DBGLOG(INIT, TRACE, "NCHO send action frame end\n"); + rStatus = WLAN_STATUS_SUCCESS; + + return rStatus; +} + +uint32_t +wlanoidSetNchoWesMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pParam = NULL; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoWesMode"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (uint32_t *) pvSetBuffer; + if (*pParam != TRUE && *pParam != FALSE) { + DBGLOG(INIT, ERROR, "NCHO wes mode invalid %d\n", *pParam); + return WLAN_STATUS_INVALID_DATA; + } + + + prAdapter->rNchoInfo.u4WesMode = *pParam; + DBGLOG(INIT, TRACE, "NCHO WES mode is %d\n", *pParam); + rStatus = WLAN_STATUS_SUCCESS; + + return rStatus; +} + +uint32_t +wlanoidQueryNchoWesMode(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t *pParam = NULL; + + DEBUGFUNC("wlanoidQueryNchoWesMode"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgECHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + pParam = (uint32_t *) pvQueryBuffer; + *pParam = prAdapter->rNchoInfo.u4WesMode; + DBGLOG(INIT, TRACE, "NCHO Wes mode is %d\n", *pParam); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidSetNchoBand(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pParam = NULL; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoBand"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (uint32_t *) pvSetBuffer; + + switch (*pParam) { + case NCHO_BAND_AUTO: + prAdapter->aePreferBand[NETWORK_TYPE_AIS] = BAND_NULL; + prAdapter->rNchoInfo.eBand = NCHO_BAND_AUTO; + rStatus = WLAN_STATUS_SUCCESS; + break; + case NCHO_BAND_2G4: + prAdapter->aePreferBand[NETWORK_TYPE_AIS] = BAND_2G4; + prAdapter->rNchoInfo.eBand = NCHO_BAND_2G4; + rStatus = WLAN_STATUS_SUCCESS; + break; + case NCHO_BAND_5G: + prAdapter->aePreferBand[NETWORK_TYPE_AIS] = BAND_5G; + prAdapter->rNchoInfo.eBand = NCHO_BAND_5G; + rStatus = WLAN_STATUS_SUCCESS; + break; + default: + DBGLOG(INIT, ERROR, "NCHO wes mode invalid %d\n", *pParam); + rStatus = WLAN_STATUS_INVALID_DATA; + break; + } + + DBGLOG(INIT, INFO, "NCHO enabled:%d ,band:%d,status:%d\n" + , prAdapter->rNchoInfo.fgECHOEnabled, *pParam, rStatus); + + + return rStatus; +} + +uint32_t +wlanoidQueryNchoBand(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t *pParam = NULL; + + DEBUGFUNC("wlanoidQueryNchoBand"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgECHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + pParam = (uint32_t *) pvQueryBuffer; + *pParam = prAdapter->rNchoInfo.eBand; + DBGLOG(INIT, TRACE, "NCHO band is %d\n", *pParam); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidSetNchoDfsScnMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pParam = NULL; + char acCmd[NCHO_CMD_MAX_LENGTH] = {0}; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoDfsScnMode"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (uint32_t *) pvSetBuffer; + if (*pParam >= NCHO_DFS_SCN_NUM) { + DBGLOG(INIT, ERROR, "NCHO DFS scan mode invalid %d\n", + *pParam); + return WLAN_STATUS_INVALID_DATA; + } + + + kalSprintf(acCmd, "%s %d", FW_CFG_KEY_NCHO_SCAN_DFS_MODE, + *pParam); + rStatus = wlanFwCfgParse(prAdapter, acCmd); + if (rStatus == WLAN_STATUS_SUCCESS) { + prAdapter->rNchoInfo.eDFSScnMode = *pParam; + DBGLOG(INIT, TRACE, "NCHO DFS scan mode is %d\n", *pParam); + } + + return rStatus; +} + +uint32_t +wlanoidQueryNchoDfsScnMode(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER cmdV1Header; + struct CMD_HEADER *prCmdV1Header = (struct CMD_HEADER *) + pvQueryBuffer; + struct CMD_FORMAT_V1 *prCmdV1 = NULL; + + DEBUGFUNC("wlanoidQueryNchoDfsScnMode"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct CMD_HEADER); + + if (u4QueryBufferLen < sizeof(struct CMD_HEADER)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rNchoInfo.fgECHOEnabled == FALSE) + return WLAN_STATUS_INVALID_DATA; + + prCmdV1 = (struct CMD_FORMAT_V1 *) prCmdV1Header->buffer; + rStatus = wlanoidSetNchoHeader(prCmdV1Header, prCmdV1, + FW_CFG_KEY_NCHO_SCAN_DFS_MODE, + kalStrLen(FW_CFG_KEY_NCHO_SCAN_DFS_MODE)); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "NCHO no enough memory\n"); + return rStatus; + } + kalMemCopy(&cmdV1Header, prCmdV1Header, + sizeof(struct CMD_HEADER)); + rStatus = wlanSendSetQueryCmd( + prAdapter, + CMD_ID_GET_SET_CUSTOMER_CFG, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventQueryCfgRead, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_HEADER), + (uint8_t *)&cmdV1Header, + pvQueryBuffer, + u4QueryBufferLen); + return rStatus; +} + +uint32_t +wlanoidSetNchoEnable(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t *pParam = NULL; + char acCmd[NCHO_CMD_MAX_LENGTH] = { 0 }; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DEBUGFUNC("wlanoidSetNchoEnable"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = sizeof(uint32_t); + + if (u4SetBufferLen < sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + pParam = (uint32_t *) pvSetBuffer; + if (*pParam != 0 && *pParam != 1) { + DBGLOG(INIT, ERROR, "NCHO DFS scan mode invalid %d\n", + *pParam); + return WLAN_STATUS_INVALID_DATA; + } + + kalSprintf(acCmd, "%s %d", FW_CFG_KEY_NCHO_ENABLE, *pParam); + rStatus = wlanFwCfgParse(prAdapter, acCmd); + if (rStatus == WLAN_STATUS_SUCCESS) { + prAdapter->rNchoInfo.fgECHOEnabled = *pParam; + DBGLOG(INIT, INFO, "NCHO enable is %d\n", *pParam); + } + + return rStatus; +} + +uint32_t +wlanoidQueryNchoEnable(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER cmdV1Header; + struct CMD_HEADER *prCmdV1Header = (struct CMD_HEADER *) + pvQueryBuffer; + struct CMD_FORMAT_V1 *prCmdV1 = NULL; + + DEBUGFUNC("wlanoidQueryNchoRoamTrigger"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct CMD_HEADER); + + if (u4QueryBufferLen < sizeof(struct CMD_HEADER)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + prCmdV1 = (struct CMD_FORMAT_V1 *) prCmdV1Header->buffer; + rStatus = wlanoidSetNchoHeader(prCmdV1Header, + prCmdV1, + FW_CFG_KEY_NCHO_ENABLE, + kalStrLen(FW_CFG_KEY_NCHO_ENABLE)); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "NCHO no enough memory\n"); + return rStatus; + } + kalMemCopy(&cmdV1Header, prCmdV1Header, + sizeof(struct CMD_HEADER)); + rStatus = wlanSendSetQueryCmd( + prAdapter, + CMD_ID_GET_SET_CUSTOMER_CFG, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventQueryCfgRead, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_HEADER), + (uint8_t *)&cmdV1Header, + pvQueryBuffer, + u4QueryBufferLen); + return rStatus; +} +#endif /* CFG_SUPPORT_NCHO */ + +uint32_t +wlanoidAbortScan(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + + struct AIS_FSM_INFO *prAisFsmInfo = NULL; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + if (prAisFsmInfo->eCurrentState == AIS_STATE_SCAN || + prAisFsmInfo->eCurrentState == AIS_STATE_ONLINE_SCAN) { + DBGLOG(OID, INFO, "wlanoidAbortScan\n"); + prAisFsmInfo->fgIsScanOidAborted = TRUE; + aisFsmStateAbort_SCAN(prAdapter); + } + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidDisableTdlsPs(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct CMD_TDLS_PS_T rTdlsPs; + + if (!prAdapter || !pvSetBuffer) + return WLAN_STATUS_INVALID_DATA; + + rTdlsPs.ucIsEnablePs = *(uint8_t *)pvSetBuffer - '0'; + DBGLOG(OID, INFO, "enable tdls ps %d\n", + rTdlsPs.ucIsEnablePs); + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_TDLS_PS, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(rTdlsPs), + (uint8_t *)&rTdlsPs, + NULL, + 0); +} + +uint32_t wlanoidSetSer(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t u4CmdId; + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (u4SetBufferLen != sizeof(uint32_t)) + return WLAN_STATUS_INVALID_LENGTH; + + u4CmdId = *((uint32_t *)pvSetBuffer); + + DBGLOG(OID, INFO, "Set SER CMD[%d]\n", u4CmdId); + + switch (u4CmdId) { + case SER_USER_CMD_DISABLE: + wlanoidSerExtCmd(prAdapter, SER_ACTION_SET, + SER_SET_DISABLE, 0); + break; + + case SER_USER_CMD_ENABLE: + wlanoidSerExtCmd(prAdapter, SER_ACTION_SET, SER_SET_ENABLE, 0); + break; + + case SER_USER_CMD_QUERY: + wlanoidSerExtCmd(prAdapter, SER_ACTION_QUERY, 0, 0); + break; + + case SER_USER_CMD_ENABLE_MASK_TRACKING_ONLY: + wlanoidSerExtCmd(prAdapter, SER_ACTION_SET_ENABLE_MASK, + SER_ENABLE_TRACKING, 0); + break; + + case SER_USER_CMD_ENABLE_MASK_L1_RECOVER_ONLY: + wlanoidSerExtCmd(prAdapter, SER_ACTION_SET_ENABLE_MASK, + SER_ENABLE_TRACKING | SER_ENABLE_L1_RECOVER, + 0); + break; + + case SER_USER_CMD_ENABLE_MASK_L2_RECOVER_ONLY: + wlanoidSerExtCmd(prAdapter, SER_ACTION_SET_ENABLE_MASK, + SER_ENABLE_TRACKING | SER_ENABLE_L2_RECOVER, + 0); + break; + + case SER_USER_CMD_ENABLE_MASK_L3_RX_ABORT_ONLY: + wlanoidSerExtCmd(prAdapter, SER_ACTION_SET_ENABLE_MASK, + SER_ENABLE_TRACKING | SER_ENABLE_L3_RX_ABORT, + 0); + break; + + case SER_USER_CMD_ENABLE_MASK_L3_TX_ABORT_ONLY: + wlanoidSerExtCmd(prAdapter, SER_ACTION_SET_ENABLE_MASK, + SER_ENABLE_TRACKING | SER_ENABLE_L3_TX_ABORT, + 0); + break; + + case SER_USER_CMD_ENABLE_MASK_L3_TX_DISABLE_ONLY: + wlanoidSerExtCmd(prAdapter, SER_ACTION_SET_ENABLE_MASK, + SER_ENABLE_TRACKING | + SER_ENABLE_L3_TX_DISABLE, 0); + break; + + case SER_USER_CMD_ENABLE_MASK_L3_BFRECOVER_ONLY: + wlanoidSerExtCmd(prAdapter, SER_ACTION_SET_ENABLE_MASK, + SER_ENABLE_TRACKING | + SER_ENABLE_L3_BF_RECOVER, 0); + break; + + case SER_USER_CMD_ENABLE_MASK_RECOVER_ALL: + wlanoidSerExtCmd(prAdapter, SER_ACTION_SET_ENABLE_MASK, + (SER_ENABLE_TRACKING | + SER_ENABLE_L1_RECOVER | + SER_ENABLE_L2_RECOVER | + SER_ENABLE_L3_RX_ABORT | + SER_ENABLE_L3_TX_ABORT | + SER_ENABLE_L3_TX_DISABLE | + SER_ENABLE_L3_BF_RECOVER), 0); + break; + + case SER_USER_CMD_L0_RECOVER: + wlanoidSerExtCmd(prAdapter, SER_ACTION_RECOVER, + SER_SET_L0_RECOVER, 0); + break; + + case SER_USER_CMD_L1_RECOVER: + wlanoidSerExtCmd(prAdapter, SER_ACTION_RECOVER, + SER_SET_L1_RECOVER, 0); + break; + + case SER_USER_CMD_L2_BN0_RECOVER: + wlanoidSerExtCmd(prAdapter, SER_ACTION_RECOVER, + SER_SET_L2_RECOVER, ENUM_BAND_0); + break; + + case SER_USER_CMD_L2_BN1_RECOVER: + wlanoidSerExtCmd(prAdapter, SER_ACTION_RECOVER, + SER_SET_L2_RECOVER, ENUM_BAND_1); + break; + + case SER_USER_CMD_L3_RX0_ABORT: + wlanoidSerExtCmd(prAdapter, SER_ACTION_RECOVER, + SER_SET_L3_RX_ABORT, ENUM_BAND_0); + break; + + case SER_USER_CMD_L3_RX1_ABORT: + wlanoidSerExtCmd(prAdapter, SER_ACTION_RECOVER, + SER_SET_L3_RX_ABORT, ENUM_BAND_1); + break; + + case SER_USER_CMD_L3_TX0_ABORT: + wlanoidSerExtCmd(prAdapter, SER_ACTION_RECOVER, + SER_SET_L3_TX_ABORT, ENUM_BAND_0); + break; + + case SER_USER_CMD_L3_TX1_ABORT: + wlanoidSerExtCmd(prAdapter, SER_ACTION_RECOVER, + SER_SET_L3_TX_ABORT, ENUM_BAND_1); + break; + + case SER_USER_CMD_L3_TX0_DISABLE: + wlanoidSerExtCmd(prAdapter, SER_ACTION_RECOVER, + SER_SET_L3_TX_DISABLE, ENUM_BAND_0); + break; + + case SER_USER_CMD_L3_TX1_DISABLE: + wlanoidSerExtCmd(prAdapter, SER_ACTION_RECOVER, + SER_SET_L3_TX_DISABLE, ENUM_BAND_1); + break; + + case SER_USER_CMD_L3_BF_RECOVER: + wlanoidSerExtCmd(prAdapter, SER_ACTION_RECOVER, + SER_SET_L3_BF_RECOVER, 0); + break; + + default: + DBGLOG(OID, ERROR, "Error SER CMD\n"); + } + + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanoidSerExtCmd(IN struct ADAPTER *prAdapter, uint8_t ucAction, + uint8_t ucSerSet, uint8_t ucDbdcIdx) { + struct EXT_CMD_SER_T rCmdSer = {0}; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + rCmdSer.ucAction = ucAction; + rCmdSer.ucSerSet = ucSerSet; + rCmdSer.ucDbdcIdx = ucDbdcIdx; + + rStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_SER, + TRUE, + FALSE, + g_fgIsOid, + NULL, + nicOidCmdTimeoutCommon, + sizeof(struct EXT_CMD_SER_T), + (uint8_t *)&rCmdSer, NULL, 0); + return rStatus; +} + +#if (CFG_SUPPORT_TXPOWER_INFO == 1) +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set rdd report. + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryTxPowerInfo(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T *prTxPowerInfo = + NULL; + struct CMD_TX_POWER_SHOW_INFO_T rCmdTxPowerShowInfo; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + if (!prAdapter) + return WLAN_STATUS_FAILURE; + if (!pvQueryBuffer) + return WLAN_STATUS_FAILURE; + if (!pu4QueryInfoLen) + return WLAN_STATUS_FAILURE; + + if (u4QueryBufferLen < + sizeof(struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T)) { + *pu4QueryInfoLen = sizeof(struct + PARAM_TXPOWER_ALL_RATE_POWER_INFO_T); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + *pu4QueryInfoLen = sizeof(struct + PARAM_TXPOWER_ALL_RATE_POWER_INFO_T); + + prTxPowerInfo = (struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T + *) pvQueryBuffer; + + kalMemSet(&rCmdTxPowerShowInfo, 0, + sizeof(struct CMD_TX_POWER_SHOW_INFO_T)); + + rCmdTxPowerShowInfo.ucPowerCtrlFormatId = + TX_POWER_SHOW_INFO; + rCmdTxPowerShowInfo.ucTxPowerInfoCatg = + prTxPowerInfo->ucTxPowerCategory; + rCmdTxPowerShowInfo.ucBandIdx = prTxPowerInfo->ucBandIdx; + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_TX_POWER_FEATURE_CTRL, + FALSE, /* Query Bit: True->write False->read */ + TRUE, + g_fgIsOid, + nicCmdEventQueryTxPowerInfo, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_TX_POWER_SHOW_INFO_T), + (uint8_t *) (&rCmdTxPowerShowInfo), + pvQueryBuffer, + u4QueryBufferLen); + + return rWlanStatus; +} +#endif + +uint32_t +wlanoidSetDrvRoamingPolicy(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + uint32_t u4RoamingPoily = 0; + struct ROAMING_INFO *prRoamingFsmInfo; + struct CONNECTION_SETTINGS *prConnSettings; + uint32_t u4CurConPolicy; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + + u4RoamingPoily = *(uint32_t *)pvSetBuffer; + + prRoamingFsmInfo = (struct ROAMING_INFO *) & + (prAdapter->rWifiVar.rRoamingInfo); + + prConnSettings = (struct CONNECTION_SETTINGS *) + &prAdapter->rWifiVar.rConnSettings; + u4CurConPolicy = prConnSettings->eConnectionPolicy; + + if (u4RoamingPoily == 1) { + if (((prAdapter->rWifiVar.rAisFsmInfo.eCurrentState == + AIS_STATE_NORMAL_TR) + || (prAdapter->rWifiVar.rAisFsmInfo.eCurrentState == + AIS_STATE_ONLINE_SCAN)) + && (prRoamingFsmInfo->eCurrentState == ROAMING_STATE_IDLE)) + roamingFsmRunEventStart(prAdapter); + + /* Change Connect by any , avoid to connect by BSSID on roaming + * or beacon timeout! + */ + prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_ANY; + + } else { + if (prRoamingFsmInfo->eCurrentState != ROAMING_STATE_IDLE) + roamingFsmRunEventAbort(prAdapter); + } + prRoamingFsmInfo->fgDrvRoamingAllow = (u_int8_t) + u4RoamingPoily; + + DBGLOG(REQ, INFO, + "wlanoidSetDrvRoamingPolicy, RoamingPoily= %d, conn policy= [%d] -> [%d]\n", + u4RoamingPoily, u4CurConPolicy, + prRoamingFsmInfo->fgDrvRoamingAllow); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanoidUpdateFtIes(struct ADAPTER *prAdapter, void *pvSetBuffer, + uint32_t u4SetBufferLen, uint32_t *pu4SetInfoLen) +{ + struct FT_IES *prFtIes = NULL; + uint32_t u4IeLen = 0; + uint8_t *pucIEStart = NULL; + struct STA_RECORD *prStaRec = NULL; +#if CFG_SUPPORT_CFG80211_AUTH + uint16_t u2Offset = 0; +#else + struct MSG_SAA_FT_CONTINUE *prFtContinueMsg = NULL; + struct cfg80211_update_ft_ies_params *ftie = NULL; +#endif + + if (!pvSetBuffer || u4SetBufferLen == 0) { + DBGLOG(OID, ERROR, + "FT: pvSetBuffer is Null %d, Buffer Len %u\n", + !pvSetBuffer, u4SetBufferLen); + return WLAN_STATUS_INVALID_DATA; + } + prStaRec = prAdapter->rWifiVar.rAisFsmInfo.prTargetStaRec; + prFtIes = &prAdapter->prGlueInfo->rFtIeForTx; +#if CFG_SUPPORT_CFG80211_AUTH + pucIEStart = (uint8_t *)pvSetBuffer; + u4IeLen = u4SetBufferLen; + DBGLOG(OID, INFO, "u4IeLen %d\n", u4IeLen); +#else + ftie = (struct cfg80211_update_ft_ies_params *)pvSetBuffer; + + if (ftie->ie_len == 0) { + DBGLOG(OID, WARN, "FT: FT Ies length is 0\n"); + return WLAN_STATUS_SUCCESS; + } + if (prFtIes->u4IeLength != ftie->ie_len) { + kalMemFree(prFtIes->pucIEBuf, VIR_MEM_TYPE, + prFtIes->u4IeLength); + prFtIes->pucIEBuf = kalMemAlloc(ftie->ie_len, VIR_MEM_TYPE); + prFtIes->u4IeLength = ftie->ie_len; + } + pucIEStart = prFtIes->pucIEBuf; + u4IeLen = prFtIes->u4IeLength; + prFtIes->u2MDID = ftie->md; +#endif + prFtIes->prFTIE = NULL; + prFtIes->prMDIE = NULL; + prFtIes->prRsnIE = NULL; + prFtIes->prTIE = NULL; +#if CFG_SUPPORT_CFG80211_AUTH + IE_FOR_EACH(pucIEStart, u4IeLen, u2Offset) { + switch (IE_ID(pucIEStart)) { + case ELEM_ID_MOBILITY_DOMAIN: + if (prFtIes->prMDIE == NULL) + prFtIes->prMDIE = kalMemAlloc( + IE_SIZE(pucIEStart), VIR_MEM_TYPE); + COPY_IE((unsigned long)(prFtIes->prMDIE), pucIEStart); + prFtIes->u4IeLength += IE_SIZE(pucIEStart); + break; + case ELEM_ID_FAST_TRANSITION: + if (prFtIes->prFTIE == NULL) + prFtIes->prFTIE = kalMemAlloc(IE_SIZE( + pucIEStart), VIR_MEM_TYPE); + COPY_IE((unsigned long)(prFtIes->prFTIE), pucIEStart); + prFtIes->u4IeLength += IE_SIZE(pucIEStart); + break; + case ELEM_ID_RESOURCE_INFO_CONTAINER: + break; + case ELEM_ID_TIMEOUT_INTERVAL: + if (prFtIes->prTIE == NULL) + prFtIes->prTIE = kalMemAlloc( + IE_SIZE(pucIEStart), VIR_MEM_TYPE); + COPY_IE((unsigned long)(prFtIes->prTIE), pucIEStart); + prFtIes->u4IeLength += IE_SIZE(pucIEStart); + break; + case ELEM_ID_RSN: + if (prFtIes->prRsnIE == NULL) + prFtIes->prRsnIE = kalMemAlloc( + IE_SIZE(pucIEStart), VIR_MEM_TYPE); + COPY_IE((unsigned long)(prFtIes->prRsnIE), pucIEStart); + prFtIes->u4IeLength += IE_SIZE(pucIEStart); + break; + } + } + DBGLOG(OID, INFO, + "FT: IesLen %u, MDIE %d FTIE %d RSN %d TIE %d\n", + prFtIes->u4IeLength, !!prFtIes->prMDIE, + !!prFtIes->prFTIE, !!prFtIes->prRsnIE, + !!prFtIes->prTIE); + +#else + if (u4IeLen) + kalMemCopy(pucIEStart, ftie->ie, u4IeLen); + while (u4IeLen >= 2) { + uint32_t u4InfoElemLen = IE_SIZE(pucIEStart); + + if (u4InfoElemLen > u4IeLen) + break; + switch (pucIEStart[0]) { + case ELEM_ID_MOBILITY_DOMAIN: + prFtIes->prMDIE = + (struct IE_MOBILITY_DOMAIN *)pucIEStart; + break; + case ELEM_ID_FAST_TRANSITION: + prFtIes->prFTIE = + (struct IE_FAST_TRANSITION *)pucIEStart; + break; + case ELEM_ID_RESOURCE_INFO_CONTAINER: + break; + case ELEM_ID_TIMEOUT_INTERVAL: + prFtIes->prTIE = + (struct IE_TIMEOUT_INTERVAL *)pucIEStart; + break; + case ELEM_ID_RSN: + prFtIes->prRsnIE = (struct RSN_INFO_ELEM *)pucIEStart; + break; + } + u4IeLen -= u4InfoElemLen; + pucIEStart += u4InfoElemLen; + } + DBGLOG(OID, INFO, + "FT: MdId %d IesLen %u, MDIE %d FTIE %d RSN %d TIE %d\n", + ftie->md, prFtIes->u4IeLength, !!prFtIes->prMDIE, + !!prFtIes->prFTIE, !!prFtIes->prRsnIE, !!prFtIes->prTIE); +#endif + +#if !CFG_SUPPORT_CFG80211_AUTH + /* check if SAA is waiting to send Reassoc req */ + if (!prStaRec || prStaRec->ucAuthTranNum != AUTH_TRANSACTION_SEQ_2 || + !prStaRec->fgIsReAssoc || prStaRec->ucStaState != STA_STATE_1) + return WLAN_STATUS_SUCCESS; + + prFtContinueMsg = (struct MSG_SAA_FT_CONTINUE *)cnmMemAlloc( + prAdapter, RAM_TYPE_MSG, sizeof(struct MSG_SAA_FT_CONTINUE)); + if (!prFtContinueMsg) { + DBGLOG(OID, WARN, "FT: failed to allocate Join Req Msg\n"); + return WLAN_STATUS_FAILURE; + } + prFtContinueMsg->rMsgHdr.eMsgId = MID_OID_SAA_FSM_CONTINUE; + prFtContinueMsg->prStaRec = prStaRec; + /* ToDo: for Resource Request Protocol, we need to check if RIC request + ** is included. + */ + if (prFtIes->prMDIE && (prFtIes->prMDIE->ucBitMap & BIT(1))) + prFtContinueMsg->fgFTRicRequest = TRUE; + else + prFtContinueMsg->fgFTRicRequest = FALSE; + DBGLOG(OID, INFO, "FT: continue to do auth/assoc, Ft Request %d\n", + prFtContinueMsg->fgFTRicRequest); + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *)prFtContinueMsg, + MSG_SEND_METHOD_BUF); +#endif + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanoidSendNeighborRequest(struct ADAPTER *prAdapter, + void *pvSetBuffer, uint32_t u4SetBufferLen, + uint32_t *pu4SetInfoLen) +{ + struct SUB_ELEMENT_LIST *prSSIDIE = NULL; + struct BSS_INFO *prAisBssInfo = NULL; + uint8_t ucSSIDIELen = 0; + uint8_t *pucSSID = (uint8_t *)pvSetBuffer; + + if (!prAdapter || !prAdapter->prAisBssInfo) + return WLAN_STATUS_INVALID_DATA; + prAisBssInfo = prAdapter->prAisBssInfo; + if (prAisBssInfo->eConnectionState != PARAM_MEDIA_STATE_CONNECTED) { + DBGLOG(OID, ERROR, "didn't connected any Access Point\n"); + return WLAN_STATUS_FAILURE; + } + if (u4SetBufferLen == 0 || !pucSSID) { + rlmTxNeighborReportRequest(prAdapter, + prAisBssInfo->prStaRecOfAP, NULL); + return WLAN_STATUS_SUCCESS; + } + + ucSSIDIELen = (uint8_t)(u4SetBufferLen + sizeof(*prSSIDIE)); + prSSIDIE = kalMemAlloc(ucSSIDIELen, PHY_MEM_TYPE); + if (!prSSIDIE) { + DBGLOG(OID, ERROR, "No Memory\n"); + return WLAN_STATUS_FAILURE; + } + prSSIDIE->prNext = NULL; + prSSIDIE->rSubIE.ucSubID = ELEM_ID_SSID; + prSSIDIE->rSubIE.ucLength = (uint8_t)u4SetBufferLen; + kalMemCopy(&prSSIDIE->rSubIE.aucOptInfo[0], pucSSID, + (uint8_t)u4SetBufferLen); + DBGLOG(OID, INFO, "Send Neighbor Request, SSID=%s\n", pucSSID); + rlmTxNeighborReportRequest(prAdapter, prAisBssInfo->prStaRecOfAP, + prSSIDIE); + kalMemFree(prSSIDIE, PHY_MEM_TYPE, ucSSIDIELen); + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanoidSync11kCapabilities(struct ADAPTER *prAdapter, + void *pvSetBuffer, uint32_t u4SetBufferLen, + uint32_t *pu4SetInfoLen) +{ + struct CMD_SET_RRM_CAPABILITY rCmdRrmCapa; + + kalMemZero(&rCmdRrmCapa, sizeof(rCmdRrmCapa)); + rCmdRrmCapa.ucCmdVer = 0x1; + rCmdRrmCapa.ucRrmEnable = 1; + rlmFillRrmCapa(&rCmdRrmCapa.ucCapabilities[0]); + return wlanSendSetQueryCmd( + prAdapter, CMD_ID_SET_RRM_CAPABILITY, TRUE, FALSE, g_fgIsOid, + nicCmdEventSetCommon, nicOidCmdTimeoutCommon, + sizeof(struct CMD_SET_RRM_CAPABILITY), (uint8_t *)&rCmdRrmCapa, + pvSetBuffer, u4SetBufferLen); +} + +static uint8_t pow_r(uint8_t x, uint8_t y) +{ + uint8_t result = 0; + uint8_t tmp = 0; + + if (y == 0) + return 1; + if (y == 1) + return x; + tmp = pow_r(x, y/2); + if ((y & 1) != 0) + result = x * tmp * tmp; + else + result = tmp * tmp; + return result; + +} + +uint32_t wlanoidSendBTMQuery(struct ADAPTER *prAdapter, void *pvSetBuffer, + uint32_t u4SetBufferLen, uint32_t *pu4SetInfoLen) +{ + struct STA_RECORD *prStaRec = NULL; + struct BSS_TRANSITION_MGT_PARAM_T *prBtmMgt = NULL; + uint8_t i = 0; + uint8_t uReason = 0; + + if (!prAdapter->prAisBssInfo || + prAdapter->prAisBssInfo->eConnectionState != + PARAM_MEDIA_STATE_CONNECTED) { + DBGLOG(OID, INFO, "Not connected yet\n"); + return WLAN_STATUS_FAILURE; + } + prStaRec = prAdapter->prAisBssInfo->prStaRecOfAP; + if (!prStaRec || !prStaRec->fgSupportBTM) { + DBGLOG(OID, INFO, + "Target BSS(%p) didn't support Bss Transition Management\n", + prStaRec); + return WLAN_STATUS_FAILURE; + } + + if (pvSetBuffer != NULL) { + for (i = 0; i < strlen(pvSetBuffer); i++) { + uReason += ((*(uint8_t *)(pvSetBuffer + i) - '0') + * pow_r(10, (strlen(pvSetBuffer) - i - 1))); + } + } + prBtmMgt = &prAdapter->rWifiVar.rAisSpecificBssInfo.rBTMParam; + prBtmMgt->ucDialogToken = wnmGetBtmToken(); + prBtmMgt->ucQueryReason = pvSetBuffer ? uReason + : BSS_TRANSITION_LOW_RSSI; + DBGLOG(OID, INFO, "Send BssTransitionManagementQuery, Reason %d\n", + prBtmMgt->ucQueryReason); + wnmSendBTMQueryFrame(prAdapter, prStaRec); + return WLAN_STATUS_SUCCESS; +} + +/* + * This func is mainly from bionic's strtok.c + */ +static int8_t *strtok_r(int8_t *s, const int8_t *delim, int8_t **last) +{ + char *spanp; + int c, sc; + char *tok; + + + if (s == NULL) { + s = *last; + if (s == 0) + return NULL; + } +cont: + c = *s++; + for (spanp = (char *)delim; (sc = *spanp++) != 0;) { + if (c == sc) + goto cont; + } + + if (c == 0) { /* no non-delimiter characters */ + *last = NULL; + return NULL; + } + tok = s - 1; + + for (;;) { + c = *s++; + spanp = (char *)delim; + do { + sc = *spanp++; + if (sc == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + *last = s; + return tok; + } + } while (sc != 0); + } +} + +uint32_t wlanoidTspecOperation(struct ADAPTER *prAdapter, void *pvBuffer, + uint32_t u4BufferLen, uint32_t *pu4InfoLen) +{ + struct PARAM_QOS_TSPEC *prTspecParam = NULL; + struct MSG_TS_OPERATE *prMsgTsOperate = NULL; + uint8_t *pucCmd = (uint8_t *)pvBuffer; + uint8_t *pucSavedPtr = NULL; + uint8_t *pucItem = NULL; + uint32_t u4Ret = 1; + uint8_t ucApsdSetting = 2; /* 0: legacy; 1: u-apsd; 2: not set yet */ + enum TSPEC_OP_CODE eTsOp; + +#if !CFG_SUPPORT_WMM_AC + DBGLOG(OID, INFO, "WMM AC is not supported\n"); + return WLAN_STATUS_FAILURE; +#endif + if (kalStrniCmp(pucCmd, "dumpts", 6) == 0) { + *pu4InfoLen = kalSnprintf(pucCmd, u4BufferLen, "%s", + "\nAll Active Tspecs:\n"); + u4BufferLen -= *pu4InfoLen; + pucCmd += *pu4InfoLen; + *pu4InfoLen += + wmmDumpActiveTspecs(prAdapter, pucCmd, u4BufferLen); + return WLAN_STATUS_SUCCESS; + } + + if (kalStrniCmp(pucCmd, "addts", 5) == 0) + eTsOp = TX_ADDTS_REQ; + else if (kalStrniCmp(pucCmd, "delts", 5) == 0) + eTsOp = TX_DELTS_REQ; + else { + DBGLOG(OID, INFO, "wrong operation %s\n", pucCmd); + return WLAN_STATUS_FAILURE; + } + /* addts token n,tid n,dir n,psb n,up n,fixed n,size n,maxsize + ** n,maxsrvint n, minsrvint n, + ** inact n, suspension n, srvstarttime n, minrate n,meanrate n,peakrate + ** n,burst n,delaybound n, + ** phyrate n,SBA n,mediumtime n + */ + prMsgTsOperate = (struct MSG_TS_OPERATE *)cnmMemAlloc( + prAdapter, RAM_TYPE_MSG, sizeof(struct MSG_TS_OPERATE)); + if (!prMsgTsOperate) + return WLAN_STATUS_FAILURE; + + kalMemZero(prMsgTsOperate, sizeof(struct MSG_TS_OPERATE)); + prMsgTsOperate->rMsgHdr.eMsgId = MID_OID_WMM_TSPEC_OPERATE; + prMsgTsOperate->eOpCode = eTsOp; + prTspecParam = &prMsgTsOperate->rTspecParam; + pucCmd += 6; + pucItem = (uint8_t *)strtok_r((int8_t *)pucCmd, ",", + (int8_t **)&pucSavedPtr); + while (pucItem) { + if (kalStrniCmp(pucItem, "token ", 6) == 0) + u4Ret = kstrtou8(pucItem + 6, 0, + &prTspecParam->ucDialogToken); + else if (kalStrniCmp(pucItem, "tid ", 4) == 0) { + u4Ret = kstrtou8(pucItem + 4, 0, + &prMsgTsOperate->ucTid); + prTspecParam->rTsInfo.ucTid = prMsgTsOperate->ucTid; + } else if (kalStrniCmp(pucItem, "dir ", 4) == 0) + u4Ret = kstrtou8(pucItem + 4, 0, + &prTspecParam->rTsInfo.ucDirection); + else if (kalStrniCmp(pucItem, "psb ", 4) == 0) + u4Ret = kstrtou8(pucItem+4, 0, &ucApsdSetting); + else if (kalStrniCmp(pucItem, "up ", 3) == 0) + u4Ret = kstrtou8(pucItem + 3, 0, + &prTspecParam->rTsInfo.ucuserPriority); + else if (kalStrniCmp(pucItem, "size ", 5) == 0) { + uint16_t u2Size = 0; + + u4Ret = kstrtou16(pucItem+5, 0, &u2Size); + prTspecParam->u2NominalMSDUSize |= u2Size; + } else if (kalStrniCmp(pucItem, "fixed ", 6) == 0) { + uint8_t ucFixed = 0; + + u4Ret = kstrtou8(pucItem+6, 0, &ucFixed); + if (ucFixed) + prTspecParam->u2NominalMSDUSize |= BIT(15); + } else if (kalStrniCmp(pucItem, "maxsize ", 8) == 0) + u4Ret = kstrtou16(pucItem + 8, 0, + &prTspecParam->u2MaxMSDUsize); + else if (kalStrniCmp(pucItem, "maxsrvint ", 10) == 0) + u4Ret = kalkStrtou32(pucItem + 10, 0, + &prTspecParam->u4MaxSvcIntv); + else if (kalStrniCmp(pucItem, "minsrvint ", 10) == 0) + u4Ret = kalkStrtou32(pucItem + 10, 0, + &prTspecParam->u4MinSvcIntv); + else if (kalStrniCmp(pucItem, "inact ", 6) == 0) + u4Ret = kalkStrtou32(pucItem + 6, 0, + &prTspecParam->u4InactIntv); + else if (kalStrniCmp(pucItem, "suspension ", 11) == 0) + u4Ret = kalkStrtou32(pucItem + 11, 0, + &prTspecParam->u4SpsIntv); + else if (kalStrniCmp(pucItem, "srvstarttime ", 13) == 0) + u4Ret = kalkStrtou32(pucItem + 13, 0, + &prTspecParam->u4SvcStartTime); + else if (kalStrniCmp(pucItem, "minrate ", 8) == 0) + u4Ret = kalkStrtou32(pucItem + 8, 0, + &prTspecParam->u4MinDataRate); + else if (kalStrniCmp(pucItem, "meanrate ", 9) == 0) + u4Ret = kalkStrtou32(pucItem + 9, 0, + &prTspecParam->u4MeanDataRate); + else if (kalStrniCmp(pucItem, "peakrate ", 9) == 0) + u4Ret = kalkStrtou32(pucItem + 9, 0, + &prTspecParam->u4PeakDataRate); + else if (kalStrniCmp(pucItem, "burst ", 6) == 0) + u4Ret = kalkStrtou32(pucItem + 6, 0, + &prTspecParam->u4MaxBurstSize); + else if (kalStrniCmp(pucItem, "delaybound ", 11) == 0) + u4Ret = kalkStrtou32(pucItem + 11, 0, + &prTspecParam->u4DelayBound); + else if (kalStrniCmp(pucItem, "phyrate ", 8) == 0) + u4Ret = kalkStrtou32(pucItem + 8, 0, + &prTspecParam->u4MinPHYRate); + else if (kalStrniCmp(pucItem, "sba ", 4) == 0) + u4Ret = wlanDecimalStr2Hexadecimals( + pucItem + 4, &prTspecParam->u2Sba); + else if (kalStrniCmp(pucItem, "mediumtime ", 11) == 0) + u4Ret = kstrtou16(pucItem + 11, 0, + &prTspecParam->u2MediumTime); + + if (u4Ret) { + DBGLOG(OID, ERROR, "Parse %s error\n", pucItem); + cnmMemFree(prAdapter, prMsgTsOperate); + return WLAN_STATUS_FAILURE; + } + pucItem = + (uint8_t *)strtok_r(NULL, ",", (int8_t **)&pucSavedPtr); + } + /* if APSD is not set in addts request, use global wmmps settings */ + if (!prAdapter->prAisBssInfo) + DBGLOG(OID, ERROR, "AisBssInfo is NULL!\n"); + else if (ucApsdSetting == 2) { + struct PM_PROFILE_SETUP_INFO *prPmProf = NULL; + enum ENUM_ACI eAc = + aucUp2ACIMap[prTspecParam->rTsInfo.ucuserPriority]; + + prPmProf = &prAdapter->prAisBssInfo->rPmProfSetupInfo; + switch (prTspecParam->rTsInfo.ucDirection) { + case UPLINK_TS: /* UpLink*/ + if (prPmProf->ucBmpTriggerAC & BIT(eAc)) + prTspecParam->rTsInfo.ucApsd = 1; + break; + case DOWNLINK_TS:/* DownLink */ + if (prPmProf->ucBmpDeliveryAC & BIT(eAc)) + prTspecParam->rTsInfo.ucApsd = 1; + break; + case BI_DIR_TS: /* Bi-directional */ + if ((prPmProf->ucBmpTriggerAC & BIT(eAc)) && + (prPmProf->ucBmpDeliveryAC & BIT(eAc))) + prTspecParam->rTsInfo.ucApsd = 1; + break; + } + } else + prTspecParam->rTsInfo.ucApsd = ucApsdSetting; + *(--pucCmd) = 0; + pucCmd -= 5; + DBGLOG(OID, INFO, + "%s %d %d %d %d %d %d %d %u %u %u %u %u %u %u %u %u %u %u 0x%04x %d\n", + pucCmd, prTspecParam->ucDialogToken, prTspecParam->rTsInfo.ucTid, + prTspecParam->rTsInfo.ucDirection, prTspecParam->rTsInfo.ucApsd, + prTspecParam->rTsInfo.ucuserPriority, + prTspecParam->u2NominalMSDUSize, prTspecParam->u2MaxMSDUsize, + prTspecParam->u4MaxSvcIntv, prTspecParam->u4MinSvcIntv, + prTspecParam->u4InactIntv, prTspecParam->u4SpsIntv, + prTspecParam->u4SvcStartTime, prTspecParam->u4MinDataRate, + prTspecParam->u4MeanDataRate, prTspecParam->u4PeakDataRate, + prTspecParam->u4MaxBurstSize, prTspecParam->u4DelayBound, + prTspecParam->u4MinPHYRate, prTspecParam->u2Sba, + prTspecParam->u2MediumTime); + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *)prMsgTsOperate, + MSG_SEND_METHOD_BUF); + return WLAN_STATUS_SUCCESS; +} + +/* It's a Integretion Test function for RadioMeasurement. If you found errors +** during doing Radio Measurement, +** you can run this IT function with iwpriv wlan0 driver \"RM-IT +** xx,xx,xx, xx\" +** xx,xx,xx,xx is the RM request frame data +*/ +uint32_t wlanoidPktProcessIT(struct ADAPTER *prAdapter, void *pvBuffer, + uint32_t u4BufferLen, uint32_t *pu4InfoLen) +{ + struct SW_RFB rSwRfb; + static uint8_t aucPacket[200] = {0,}; + uint8_t *pucSavedPtr = (int8_t *)pvBuffer; + uint8_t *pucItem = NULL; + uint8_t j = 0; + int8_t i = 0; + uint8_t ucByte; + u_int8_t fgBTMReq = FALSE; + void (*process_func)(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); + + if (!pvBuffer) { + DBGLOG(OID, ERROR, "pvBuffer is NULL\n"); + return WLAN_STATUS_FAILURE; + } + + if (!kalStrniCmp(pucSavedPtr, "RM-IT ", 6)) { + process_func = rlmProcessRadioMeasurementRequest; + pucSavedPtr += 6; + } else if (!kalStrniCmp(pucSavedPtr, "BTM-IT ", 7)) { + process_func = wnmRecvBTMRequest; + pucSavedPtr += 7; + fgBTMReq = TRUE; + } else { + pucSavedPtr[10] = 0; + DBGLOG(OID, ERROR, "IT type %s is not supported\n", + pucSavedPtr); + return WLAN_STATUS_NOT_SUPPORTED; + } + kalMemZero(aucPacket, sizeof(aucPacket)); + pucItem = strtok_r(pucSavedPtr, ",", (int8_t **)&pucSavedPtr); + while (pucItem) { + ucByte = *pucItem; + i = 0; + while (ucByte) { + if (i > 1) { + DBGLOG(OID, ERROR, + "more than 2 char for one byte\n"); + return WLAN_STATUS_FAILURE; + } else if (i == 1) + aucPacket[j] <<= 4; + if (ucByte >= '0' && ucByte <= '9') + aucPacket[j] |= ucByte - '0'; + else if (ucByte >= 'a' && ucByte <= 'f') + aucPacket[j] |= ucByte - 'a' + 10; + else if (ucByte >= 'A' && ucByte <= 'F') + aucPacket[j] |= ucByte - 'A' + 10; + else { + DBGLOG(OID, ERROR, "not a hex char %c\n", + ucByte); + return WLAN_STATUS_FAILURE; + } + ucByte = *(++pucItem); + i++; + } + j++; + pucItem = strtok_r(NULL, ",", (int8_t **)&pucSavedPtr); + } + DBGLOG(OID, INFO, "Dump IT packet, len %d\n", j); + dumpMemory8(aucPacket, j); + if (j < WLAN_MAC_MGMT_HEADER_LEN) { + DBGLOG(OID, ERROR, "packet length %d less than mac header 24\n", + j); + return WLAN_STATUS_FAILURE; + } + rSwRfb.pvHeader = (void *)&aucPacket[0]; + rSwRfb.u2PacketLen = j; + rSwRfb.u2HeaderLen = WLAN_MAC_MGMT_HEADER_LEN; + rSwRfb.ucStaRecIdx = KAL_NETWORK_TYPE_AIS_INDEX; + if (fgBTMReq) { + struct HW_MAC_RX_DESC rRxStatus; + + rSwRfb.prRxStatus = (struct HW_MAC_RX_DESC *)&rRxStatus; + rSwRfb.prRxStatus->ucChanFreq = 6; + wnmWNMAction(prAdapter, &rSwRfb); + } else { + process_func(prAdapter, &rSwRfb); + } + + return WLAN_STATUS_SUCCESS; +} + +/* Firmware Integration Test functions +** This function receives commands that are input by a firmware IT test script +** By using IT test script, RD no need to run IT with a real Access Point +** For example: iwpriv wlan0 driver \"Fw-Event Roaming ....\" +*/ +uint32_t wlanoidFwEventIT(struct ADAPTER *prAdapter, void *pvBuffer, + uint32_t u4BufferLen, uint32_t *pu4InfoLen) +{ + uint8_t *pucCmd = (int8_t *)pvBuffer; + + /* Firmware roaming Integration Test case */ + if (!kalStrniCmp(pucCmd, "Roaming", 7)) { + uint8_t ucRCPI = 0; + uint8_t ucFrameType = 0; + uint32_t i = 0; + struct CMD_INFO *prCmdInfo; + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct WLAN_ACTION_FRAME *prAction = NULL; + struct QUE_ENTRY *prEntry = NULL; + struct QUE_ENTRY *prPreEntry = NULL; + struct CMD_ROAMING_TRANSIT rTransit = {0}; + + GLUE_SPIN_LOCK_DECLARATION(); + + if (prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc) + rTransit.u2Data = prAdapter->rWifiVar.rAisFsmInfo + .prTargetBssDesc->ucRCPI; + rTransit.u2Event = ROAMING_EVENT_DISCOVERY; + rTransit.eReason = ROAMING_REASON_POOR_RCPI; + roamingFsmRunEventDiscovery(prAdapter, &rTransit); + /* Try to find the BTM query frame which is sent by + ** roamingFsmRunEventDiscovery + */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + for (prEntry = QUEUE_GET_HEAD(&prGlueInfo->rCmdQueue); + prEntry != NULL; prPreEntry = prEntry, + prEntry = QUEUE_GET_NEXT_ENTRY(&prCmdInfo->rQueEntry)) { + prCmdInfo = (struct CMD_INFO *)prEntry; + if (!prCmdInfo->prMsduInfo || + prCmdInfo->prMsduInfo->eSrc != TX_PACKET_MGMT || + !prCmdInfo->prMsduInfo->prPacket) + continue; + prAction = (struct WLAN_ACTION_FRAME *) + prCmdInfo->prMsduInfo->prPacket; + if (prAction->u2FrameCtrl != MAC_FRAME_ACTION) + continue; + if (prAction->ucCategory == CATEGORY_RM_ACTION && + prAction->ucAction == + ACTION_NEIGHBOR_REPORT_REQ) { + ucFrameType = 1; + break; + } + if (prAction->ucCategory == CATEGORY_WNM_ACTION && + prAction->ucAction == + ACTION_WNM_BSS_TRANSITION_MANAGEMENT_QUERY) { + ucFrameType = 2; + break; + } + } + if (prEntry) { + if (prPreEntry) { + prPreEntry->prNext = prEntry->prNext; + prGlueInfo->rCmdQueue.u4NumElem--; + } else + QUEUE_INITIALIZE(&prGlueInfo->rCmdQueue); + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + /* roamingFsmRunEventDiscovery has sent a btm query frame */ + if (ucFrameType == 2) { + struct ACTION_BTM_QUERY_FRAME *prBtmQuery = + (struct ACTION_BTM_QUERY_FRAME *)prAction; + + /* IT string may be "Roaming ", to reuse btm it function, + ** we need to replace Roaming with BTM-IT. Length of + ** Roaming is 7 bytes, so pucCmd + ** need to self add 1, and buffer length need to self + ** minus 1, and copy BTM-IT to pucCmd. + */ + pucCmd++; + u4BufferLen--; + kalMemCopy(pucCmd, "BTM-IT", 6); + + /* Find the diaglogToken string in , it follows "BTM-IT ", whose length is 7 + */ + for (ucRCPI = 0, i = 7; i < u4BufferLen; i++) { + if (pucCmd[i] == ',') + ucRCPI++; + if (ucRCPI == + OFFSET_OF(struct ACTION_BTM_QUERY_FRAME, + ucDialogToken)) + break; + } + /* Replace diaglog token string with the token that is + ** in query frame + */ + ucRCPI = prBtmQuery->ucDialogToken; + ucFrameType = (ucRCPI >> 4) & 0xf; + if (ucFrameType > 9) + pucCmd[++i] = ucFrameType + 'a' - 10; + else + pucCmd[++i] = ucFrameType + '0'; + ucFrameType = ucRCPI & 0xf; + if (ucFrameType > 9) + pucCmd[++i] = ucFrameType + 'a' - 10; + else + pucCmd[++i] = ucFrameType + '0'; + wlanoidPktProcessIT(prAdapter, (void *)pucCmd, + u4BufferLen, pu4InfoLen); + } else if (ucFrameType == 1) { + /* Not support neighbor ap report request IT now */ + } + } else { + DBGLOG(OID, ERROR, "Not supported Fw Event IT type %s\n", + pucCmd); + return WLAN_STATUS_FAILURE; + } + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanoidDumpUapsdSetting(struct ADAPTER *prAdapter, void *pvBuffer, + uint32_t u4BufferLen, uint32_t *pu4InfoLen) +{ + uint8_t *pucCmd = (uint8_t *)pvBuffer; + uint8_t ucFinalSetting = 0; + uint8_t ucStaticSetting = 0; + struct PM_PROFILE_SETUP_INFO *prPmProf = NULL; + + if (!pvBuffer) { + DBGLOG(OID, ERROR, "pvBuffer is NULL\n"); + return WLAN_STATUS_FAILURE; + } + if (!prAdapter->prAisBssInfo) + return WLAN_STATUS_FAILURE; + prPmProf = &prAdapter->prAisBssInfo->rPmProfSetupInfo; + ucStaticSetting = + (prPmProf->ucBmpDeliveryAC << 4) | prPmProf->ucBmpTriggerAC; + ucFinalSetting = wmmCalculateUapsdSetting(prAdapter); + *pu4InfoLen = kalSnprintf( + pucCmd, u4BufferLen, + "\nStatic Uapsd Setting:0x%02x\nFinal Uapsd Setting:0x%02x", + ucStaticSetting, ucFinalSetting); + return WLAN_STATUS_SUCCESS; +} + +#if CFG_SUPPORT_OSHARE +uint32_t +wlanoidSetOshareMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + if (!prAdapter || !pvSetBuffer) + return WLAN_STATUS_INVALID_DATA; + + DBGLOG(OID, TRACE, "wlanoidSetOshareMode\n"); + + return wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_OSHARE_MODE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + g_fgIsOid, /* fgIsOid */ + nicCmdEventSetCommon, /* pfCmdDoneHandler*/ + nicOidCmdTimeoutCommon, /* pfCmdTimeoutHandler */ + u4SetBufferLen, /* u4SetQueryInfoLen */ + (uint8_t *) pvSetBuffer,/* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0); /* u4SetQueryBufferLen */ +} +#endif + +uint32_t +wlanoidQueryWifiLogLevelSupport(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_WIFI_LOG_LEVEL_UI *pparam; + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + pparam = (struct PARAM_WIFI_LOG_LEVEL_UI *) pvQueryBuffer; + pparam->u4Enable = wlanDbgLevelUiSupport(prAdapter, + pparam->u4Version, pparam->u4Module); + + DBGLOG(OID, INFO, "version: %d, module: %d, enable: %d\n", + pparam->u4Version, + pparam->u4Module, + pparam->u4Enable); + + *pu4QueryInfoLen = sizeof(struct PARAM_WIFI_LOG_LEVEL_UI); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidQueryWifiLogLevel(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + struct PARAM_WIFI_LOG_LEVEL *pparam; + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + pparam = (struct PARAM_WIFI_LOG_LEVEL *) pvQueryBuffer; + pparam->u4Level = wlanDbgGetLogLevelImpl(prAdapter, + pparam->u4Version, + pparam->u4Module); + + DBGLOG(OID, INFO, "version: %d, module: %d, level: %d\n", + pparam->u4Version, + pparam->u4Module, + pparam->u4Level); + + *pu4QueryInfoLen = sizeof(struct PARAM_WIFI_LOG_LEVEL_UI); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +wlanoidSetWifiLogLevel(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + struct PARAM_WIFI_LOG_LEVEL *pparam; + + ASSERT(prAdapter); + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + pparam = (struct PARAM_WIFI_LOG_LEVEL *) pvSetBuffer; + + DBGLOG(OID, INFO, "version: %d, module: %d, level: %d\n", + pparam->u4Version, + pparam->u4Module, + pparam->u4Level); + + wlanDbgSetLogLevelImpl(prAdapter, + pparam->u4Version, + pparam->u4Module, + pparam->u4Level); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t wlanoidSetDrvSer(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + ASSERT(prAdapter); + + prAdapter->u4HifChkFlag |= HIF_DRV_SER; + kalSetHifDbgEvent(prAdapter->prGlueInfo); + + return 0; +} + +uint32_t wlanoidSetAmsduNum(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct mt66xx_chip_info *prChipInfo = NULL; + + ASSERT(prAdapter); + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prChipInfo = prAdapter->chip_info; + prChipInfo->ucMaxSwAmsduNum = (uint8_t)*((uint32_t *)pvSetBuffer); + DBGLOG(OID, INFO, "Set SW AMSDU Num: %d\n", + prChipInfo->ucMaxSwAmsduNum); + return 0; +} + +uint32_t wlanoidSetAmsduSize(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct mt66xx_chip_info *prChipInfo = NULL; + struct WIFI_VAR *prWifiVar = NULL; + + ASSERT(prAdapter); + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prChipInfo = prAdapter->chip_info; + prWifiVar = &prAdapter->rWifiVar; + prWifiVar->u4TxMaxAmsduInAmpduLen = *((uint32_t *)pvSetBuffer); + DBGLOG(OID, INFO, "Set SW AMSDU max Size: %d\n", + prWifiVar->u4TxMaxAmsduInAmpduLen); + return 0; +} + +uint32_t +wlanoidShowPdmaInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + prAdapter->u4HifDbgFlag |= DEG_HIF_PDMA; + kalSetHifDbgEvent(prAdapter->prGlueInfo); + + return 0; +} + +uint32_t +wlanoidShowPseInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + prAdapter->u4HifDbgFlag |= DEG_HIF_PSE; + kalSetHifDbgEvent(prAdapter->prGlueInfo); + + return 0; +} + +uint32_t +wlanoidShowPleInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + prAdapter->u4HifDbgFlag |= DEG_HIF_PLE; + kalSetHifDbgEvent(prAdapter->prGlueInfo); + + return 0; +} + +uint32_t +wlanoidShowCsrInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + prAdapter->u4HifDbgFlag |= DEG_HIF_HOST_CSR; + kalSetHifDbgEvent(prAdapter->prGlueInfo); + + return 0; +} + +uint32_t +wlanoidShowDmaschInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + prAdapter->u4HifDbgFlag |= DEG_HIF_DMASCH; + kalSetHifDbgEvent(prAdapter->prGlueInfo); + + return 0; +} + +#if CFG_SUPPORT_LOWLATENCY_MODE +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to enable/disable low latency mode + * + * \param[in] prAdapter A pointer to the Adapter structure. + * \param[in] pvSetBuffer A pointer to the buffer that holds the + * OID-specific data to be set. + * \param[in] u4SetBufferLen The number of bytes the set buffer. + * \param[out] pu4SetInfoLen Points to the number of bytes it read or is + * needed + * \retval WLAN_STATUS_SUCCESS + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanoidSetLowLatencyMode( + IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) { + u_int8_t fgEnMode = FALSE; /* Low Latency Mode */ + u_int8_t fgEnScan = FALSE; /* Scan management */ + u_int8_t fgEnPM = FALSE; /* Power management */ + uint32_t u4Events; + uint32_t u4PowerFlag; + struct PARAM_POWER_MODE_ rPowerMode; + struct WIFI_VAR *prWifiVar = NULL; + + DEBUGFUNC("wlanoidSetLowLatencyMode"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + if (u4SetBufferLen != sizeof(uint32_t)) { + *pu4SetInfoLen = sizeof(uint32_t); + return WLAN_STATUS_INVALID_LENGTH; + } + ASSERT(pu4SetInfoLen); + + /* Initialize */ + prWifiVar = &prAdapter->rWifiVar; + kalMemCopy(&u4Events, pvSetBuffer, u4SetBufferLen); + DBGLOG(OID, INFO, + "LowLatency(gaming) event - gas:0x%x, net:0x%x, whitelist:0x%x, scan=%u, reorder=%u, power=%u\n", + (u4Events & GED_EVENT_GAS), + (u4Events & GED_EVENT_NETWORK), + (u4Events & GED_EVENT_DOPT_WIFI_SCAN), + (uint32_t)prWifiVar->ucLowLatencyModeScan, + (uint32_t)prWifiVar->ucLowLatencyModeReOrder, + (uint32_t)prWifiVar->ucLowLatencyModePower); + rPowerMode.ucBssIdx = prAdapter->prAisBssInfo->ucBssIndex; + u4PowerFlag = + prAdapter->rWlanInfo.u4PowerSaveFlag[rPowerMode.ucBssIdx]; + + /* Enable/disable low latency mode decision: + * + * Enable if it's GAS and network event + * and the Glue media state is connected. + */ + if ((u4Events & GED_EVENT_GAS) != 0 + && (u4Events & GED_EVENT_NETWORK) != 0 + && PARAM_MEDIA_STATE_CONNECTED + == kalGetMediaStateIndicated(prAdapter->prGlueInfo)) + fgEnMode = TRUE; /* It will enable low latency mode */ + + /* Enable/disable scan management decision: + * + * Enable if it will enable low latency mode. + * Or, enable if it is a white list event. + */ + if (fgEnMode != TRUE + || (u4Events & GED_EVENT_DOPT_WIFI_SCAN) != 0) + fgEnScan = TRUE; /* It will enable scan management */ + + /* Enable/disable power management decision: + */ + if (BIT(PS_CALLER_GPU) & u4PowerFlag) + fgEnPM = TRUE; + else + fgEnPM = FALSE; + + /* Debug log for the actions */ + if (fgEnMode != prAdapter->fgEnLowLatencyMode + || fgEnScan != prAdapter->fgEnCfg80211Scan + || fgEnPM != fgEnMode) { + DBGLOG(OID, INFO, + "LowLatency(gaming) change (m:%d,s:%d,PM:%d,F:0x%x)\n", + fgEnMode, fgEnScan, fgEnPM, u4PowerFlag); + } + + /* Scan management: + * + * Disable/enable scan + */ + if ((prWifiVar->ucLowLatencyModeScan == FEATURE_ENABLED) && + (fgEnScan != prAdapter->fgEnCfg80211Scan)) + prAdapter->fgEnCfg80211Scan = fgEnScan; + + if ((prWifiVar->ucLowLatencyModeReOrder == FEATURE_ENABLED) && + (fgEnMode != prAdapter->fgEnLowLatencyMode)) { + prAdapter->fgEnLowLatencyMode = fgEnMode; + + /* Queue management: + * + * Change QM RX BA timeout if the gaming mode state changed + */ + if (fgEnMode) { + prAdapter->u4QmRxBaMissTimeout + = QM_RX_BA_ENTRY_MISS_TIMEOUT_MS_SHORT; + } else { + prAdapter->u4QmRxBaMissTimeout + = QM_RX_BA_ENTRY_MISS_TIMEOUT_MS; + } + } + + /* Power management: + * + * Set power saving mode profile to FW + * + * Do if 1. the power saving caller including GPU + * and 2. it will disable low latency mode. + * Or, do if 1. the power saving caller is not including GPU + * and 2. it will enable low latency mode. + */ + if ((prWifiVar->ucLowLatencyModePower == FEATURE_ENABLED) && + (fgEnPM != fgEnMode)) { + if (fgEnMode == TRUE) + rPowerMode.ePowerMode = Param_PowerModeCAM; + else + rPowerMode.ePowerMode = Param_PowerModeFast_PSP; + + nicConfigPowerSaveProfile(prAdapter, rPowerMode.ucBssIdx, + rPowerMode.ePowerMode, FALSE, PS_CALLER_GPU); + } + + *pu4SetInfoLen = 0; /* We do not need to read */ + + return WLAN_STATUS_SUCCESS; +} +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + +uint32_t +wlanoidGetIpiInfo(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + + struct PARAM_GET_IPI_INFO_T *prCmdGetIpiInfo; + + *pu4QueryInfoLen = sizeof(struct PARAM_GET_IPI_INFO_T); + + if (u4QueryBufferLen < sizeof(struct PARAM_GET_IPI_INFO_T)) { + DBGLOG(REQ, WARN, "Too short length %u\n", + u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prCmdGetIpiInfo = (struct PARAM_GET_IPI_INFO_T *)pvQueryBuffer; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_IPI_INFO, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct PARAM_GET_IPI_INFO_T), + (uint8_t *) prCmdGetIpiInfo, + pvQueryBuffer, u4QueryBufferLen); +} + +#ifdef CFG_GET_TEMPURATURE + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to get die temperature. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[out] pvQueryBuf A pointer to the buffer that holds the result of + * the query (temperature) + * \param[in] u4QueryBufLen The length of the query buffer (integer: 4 bytes) + * \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 + */ +/*----------------------------------------------------------------------------*/ + +uint32_t +wlanoidGetTemperature(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + struct CMD_THERMAL_SENSOR_INFO rThermalInfo; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + if (!prAdapter || !pvQueryBuffer || !pu4QueryInfoLen) + return WLAN_STATUS_INVALID_DATA; + + 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(uint32_t); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(int)) { + DBGLOG(REQ, WARN, "Too short length %ld\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } else if (prAdapter->fgTestMode == TRUE) { + /*DBGLOG(REQ, WARN, "Not supported in Test Mode\n");*/ + return WLAN_STATUS_NOT_SUPPORTED; + } + kalMemSet(&rThermalInfo, 0, + sizeof(struct CMD_THERMAL_SENSOR_INFO)); + + rThermalInfo.u1ThermalCtrlFormatId = THERMAL_SENSOR_INFO_GET; + rThermalInfo.u1ActionIdx = THERMAL_SENSOR_INFO_TEMPERATURE; + + + /* Not necessary to use : CMD_ID_GET_TEMPERATURE * + * Use new THERMAL SENSOR service instead * + */ + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_GET_SENSOR_RESULT, + FALSE, /* Query Bit: True->write False->read */ + TRUE, + g_fgIsOid, + nicCmdEventGetTemperature, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_THERMAL_SENSOR_INFO), + (uint8_t *) (&rThermalInfo), + pvQueryBuffer, + u4QueryBufferLen); + + return rWlanStatus; +} +#endif + + +#if CFG_SUPPORT_ANT_DIV +/*----------------------------------------------------------------------------*/ +/*! +* \brief antenna diversity config +* +* \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 +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidAntDivCfg(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct CMD_ANT_DIV_CTRL *prAntDivInfo; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + u_int8_t fgSetQuery = TRUE; + u_int8_t fgNeedResp = FALSE; + + DEBUGFUNC("wlanoidSetAntDiv"); + if (prAdapter == NULL) + return -EFAULT; + if (pu4SetInfoLen == NULL) + return -EFAULT; + if (pvSetBuffer == NULL) + return -EFAULT; + + *pu4SetInfoLen = sizeof(struct CMD_ANT_DIV_CTRL); + if (u4SetBufferLen < sizeof(struct CMD_ANT_DIV_CTRL)) + return WLAN_STATUS_INVALID_LENGTH; + + prAntDivInfo = (struct CMD_ANT_DIV_CTRL *) pvSetBuffer; + + /* GET need to wait for response from FW module */ + switch (prAntDivInfo->ucAction) { + case ANT_DIV_CMD_GET_ANT: + case ANT_DIV_CMD_DETC: + fgSetQuery = FALSE; + fgNeedResp = TRUE; + break; + case ANT_DIV_CMD_SWH: + fgSetQuery = TRUE; + fgNeedResp = TRUE; + break; + case ANT_DIV_CMD_SET_ANT: + fgSetQuery = TRUE; + fgNeedResp = FALSE; + break; + default: + DBGLOG(REQ, WARN, "don't support action = %d\n", + prAntDivInfo->ucAction); + return WLAN_STATUS_INVALID_DATA; + break; + } + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_ANT_DIV_CTRL, + fgSetQuery, + fgNeedResp, + g_fgIsOid, + nicCmdEventAntDiv, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_ANT_DIV_CTRL), + (uint8_t *) prAntDivInfo, + pvSetBuffer, u4SetBufferLen); + + return rWlanStatus; +} +#endif +#if (CFG_SUPPORT_GET_MCS_INFO == 1) +uint32_t +wlanoidTxQueryMcsInfo(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + struct PARAM_TX_MCS_INFO *prMcsInfo; + + DEBUGFUNC("wlanoidQueryWlanInfo"); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, + "Adapter not ready. ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(uint32_t); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(int)) { + DBGLOG(REQ, WARN, "Too short length %ld\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } else if (prAdapter->fgTestMode == TRUE) { + /*DBGLOG(REQ, WARN, "Not supported in Test Mode\n");*/ + return WLAN_STATUS_NOT_SUPPORTED; + } + + if (prAdapter->prAisBssInfo->prStaRecOfAP == NULL) + return WLAN_STATUS_FAILURE; + + prMcsInfo = (struct PARAM_TX_MCS_INFO *)pvQueryBuffer; + prMcsInfo->ucStaIndex = prAdapter->prAisBssInfo->prStaRecOfAP->ucIndex; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_TX_MCS_INFO, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventQueryTxMcsInfo, + nicOidCmdTimeoutCommon, + sizeof(struct PARAM_TX_MCS_INFO), + (uint8_t *) prMcsInfo, + pvQueryBuffer, u4QueryBufferLen); +} +#endif + +#ifdef CFG_SUPPORT_TIME_MEASURE +uint32_t wlanoidQueryStartFtm( + IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen + ) +{ + struct CMD_TM_ACTION_T rCmdTmAction; + struct PARAM_TM_T *prTmrParam; + uint8_t fgNeedResp = FALSE; + + DEBUGFUNC("wlanoidQueryStartFtm"); + + if (prAdapter == NULL) + return -EFAULT; + if (pu4QueryInfoLen == NULL) + return -EFAULT; + if ((u4QueryBufferLen > 0) && (pvQueryBuffer == NULL)) + return -EFAULT; + + *pu4QueryInfoLen = sizeof(struct CMD_TM_ACTION_T); + prTmrParam = (struct PARAM_TM_T *)pvQueryBuffer; + + rCmdTmAction.ucTmCategory = TM_ACTION_START_FTM; + rCmdTmAction.ucCmdVer = TM_CMD_EVENT_VER; + rCmdTmAction.u2CmdLen = CMD_TM_ACTION_START_FTM_LEN; + if (prTmrParam->ucFTMNum != 0 && prTmrParam->ucMinDeltaIn100US != 0 && + prTmrParam->ucFTMBandwidth != 0) { + COPY_MAC_ADDR(rCmdTmAction.aucRttPeerAddr, + prTmrParam->aucRttPeerAddr); + rCmdTmAction.ucFTMNum = prTmrParam->ucFTMNum; + rCmdTmAction.ucMinDeltaIn100US = prTmrParam->ucMinDeltaIn100US; + rCmdTmAction.ucFTMBandwidth = prTmrParam->ucFTMBandwidth; + fgNeedResp = (prTmrParam->u4DistanceCm == 0); + } + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_TMR_ACTION, + TRUE, + fgNeedResp, + TRUE, + nicCmdEventGetTmReport, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_TM_ACTION_T), + (uint8_t *)&rCmdTmAction, + pvQueryBuffer, u4QueryBufferLen); +} + +uint32_t wlanoidQueryFtm( + IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen + ) +{ + struct CMD_TM_ACTION_T rCmdTmAction; + struct PARAM_TM_T *prTmrParam; + struct timespec Ftmtv_raw; + + DEBUGFUNC("wlanoidQueryStartFtm"); + + if (prAdapter == NULL) + return -EFAULT; + if (pu4QueryInfoLen == NULL) + return -EFAULT; + if ((u4QueryBufferLen > 0) && (pvQueryBuffer == NULL)) + return -EFAULT; + + *pu4QueryInfoLen = sizeof(struct CMD_TM_ACTION_T); + prTmrParam = (struct PARAM_TM_T *)pvQueryBuffer; + + rCmdTmAction.ucTmCategory = prTmrParam->ucTmCategory; + rCmdTmAction.ucCmdVer = TM_CMD_EVENT_VER; + rCmdTmAction.u2CmdLen = CMD_TM_ACTION_QUERY_LEN; + + getrawmonotonic(&Ftmtv_raw); + /* gpio_set_value(A1, 1); */ + /* gpio_set_value(A1, 0); */ + g_u8LastSysClkps = g_u8SysClkps; + g_u8SysClkps = (uint64_t)(Ftmtv_raw.tv_sec * 1000000000LL + + Ftmtv_raw.tv_nsec) * 1000; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_TMR_ACTION, + TRUE, + TRUE, + TRUE, + nicCmdEventGetTmReport, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_TM_ACTION_T), + (uint8_t *)&rCmdTmAction, + pvQueryBuffer, u4QueryBufferLen); +} + +uint32_t wlanoidSetEnableTmr( + IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen + ) +{ + struct CMD_TM_ACTION_T rCmdTmAction; + struct PARAM_TM_T *prTmrParam; + + DEBUGFUNC("wlanoidSetEnableTmr"); + + if (prAdapter == NULL) + return -EFAULT; + if (pu4SetInfoLen == NULL) + return -EFAULT; + if ((u4SetBufferLen > 0) && (pvSetBuffer == NULL)) + return -EFAULT; + + *pu4SetInfoLen = sizeof(struct CMD_TM_ACTION_T); + prTmrParam = (struct PARAM_TM_T *)pvSetBuffer; + + rCmdTmAction.ucTmCategory = TM_ACTION_TMR_ENABLE; + rCmdTmAction.ucCmdVer = TM_CMD_EVENT_VER; + rCmdTmAction.u2CmdLen = CMD_TM_ACTION_START_FTM_LEN; + rCmdTmAction.fgFtmEnable = prTmrParam->fgFtmEnable; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_TMR_ACTION, + TRUE, + FALSE, + TRUE, + nicCmdEventGetTmReport, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_TM_ACTION_T), + (uint8_t *)&rCmdTmAction, + pvSetBuffer, u4SetBufferLen); +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/common/wlan_p2p.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/common/wlan_p2p.c new file mode 100644 index 0000000000000..83b2469c46f96 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/common/wlan_p2p.c @@ -0,0 +1,1740 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + + +/****************************************************************************** + * C O M P I L E R F L A G S + ****************************************************************************** + */ + +/****************************************************************************** + * E X T E R N A L R E F E R E N C E S + ****************************************************************************** + */ +#include "precomp.h" +#include "gl_p2p_ioctl.h" + +/****************************************************************************** + * C O N S T A N T S + ******************************************************************************* + */ + +/****************************************************************************** + * D A T A T Y P E S + ******************************************************************************* + */ + +/****************************************************************************** + * P U B L I C D A T A + ******************************************************************************* + */ + +/****************************************************************************** + * P R I V A T E D A T A + ******************************************************************************* + */ + +/****************************************************************************** + * M A C R O S + ******************************************************************************* + */ + +/****************************************************************************** + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/****************************************************************************** + * F U N C T I O N S + ****************************************************************************** + */ +/*---------------------------------------------------------------------------*/ +/*! + * \brief command packet generation utility + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] ucCID Command ID + * \param[in] fgSetQuery Set or Query + * \param[in] fgNeedResp Need for response + * \param[in] pfCmdDoneHandler Function pointer when command is done + * \param[in] u4SetQueryInfoLen The length of the set/query buffer + * \param[in] pucInfoBuffer Pointer to set/query buffer + * + * + * \retval WLAN_STATUS_PENDING + * \retval WLAN_STATUS_FAILURE + */ +/*---------------------------------------------------------------------------*/ +uint32_t +wlanoidSendSetQueryP2PCmd(IN struct ADAPTER *prAdapter, + IN uint8_t ucCID, + IN uint8_t ucBssIdx, + IN u_int8_t fgSetQuery, + IN u_int8_t fgNeedResp, + IN u_int8_t fgIsOid, + IN PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + IN PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + IN uint32_t u4SetQueryInfoLen, + IN uint8_t *pucInfoBuffer, + OUT void *pvSetQueryBuffer, + IN uint32_t u4SetQueryBufferLen) +{ + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + struct WIFI_CMD *prWifiCmd; + uint8_t 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->u2InfoBufLen = (uint16_t) (CMD_HDR_SIZE + u4SetQueryInfoLen); + prCmdInfo->pfCmdDoneHandler = pfCmdDoneHandler; + prCmdInfo->pfCmdTimeoutHandler = pfCmdTimeoutHandler; + prCmdInfo->fgIsOid = fgIsOid; + prCmdInfo->ucCID = ucCID; + prCmdInfo->fgSetQuery = fgSetQuery; + prCmdInfo->fgNeedResp = fgNeedResp; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u4SetQueryInfoLen; + prCmdInfo->pvInformationBuffer = pvSetQueryBuffer; + prCmdInfo->u4InformationBufferLength = u4SetQueryBufferLen; + + /* Setup WIFI_CMD_T (no payload) */ + prWifiCmd = (struct WIFI_CMD *) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->u2Length = prCmdInfo->u2InfoBufLen - + (uint16_t) OFFSET_OF(struct WIFI_CMD, u2Length); + prWifiCmd->u2PqId = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + 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, (struct QUE_ENTRY *) 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 + */ +/*---------------------------------------------------------------------------*/ +#if 0 +uint32_t +wlanoidSetAddP2PKey(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct CMD_802_11_KEY rCmdKey; + struct PARAM_KEY *prNewKey; + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + + DEBUGFUNC("wlanoidSetAddP2PKey"); + DBGLOG(REQ, INFO, "\n"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prNewKey = (struct PARAM_KEY *) pvSetBuffer; + + /* Verify the key structure length. */ + if (prNewKey->u4Length > u4SetBufferLen) { + log_dbg(REQ, WARN, + "Invalid key structure length (%d) greater than total buffer length (%d)\n", + (uint8_t) prNewKey->u4Length, (uint8_t) 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(struct PARAM_KEY, aucKeyMaterial)) { + log_dbg(REQ, WARN, + "Invalid key material length (%d)\n", + (uint8_t) 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; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prNewKey->ucBssIdx); + ASSERT(prBssInfo); +#if 0 + if (prBssInfo->ucBMCWlanIndex >= WTBL_SIZE) { + prBssInfo->ucBMCWlanIndex = + secPrivacySeekForBcEntry(prAdapter, + prBssInfo->ucBssIndex, prBssInfo->aucBSSID, + 0xff, CIPHER_SUITE_NONE, 0xff); + } +#endif + /* fill CMD_802_11_KEY */ + kalMemZero(&rCmdKey, sizeof(struct 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 0 + /* group client */ + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { +#else + /* group client */ + if (kalP2PGetRole(prAdapter->prGlueInfo) == 1) { +#endif + + rCmdKey.ucIsAuthenticator = 0; + } else { /* group owner */ + rCmdKey.ucIsAuthenticator = 1; + /* Force to set GO/AP Tx */ + rCmdKey.ucTxKey = 1; + } + + COPY_MAC_ADDR(rCmdKey.aucPeerAddr, prNewKey->arBSSID); + rCmdKey.ucBssIdx = prNewKey->ucBssIdx; + 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 */ + else if (prNewKey->u4KeyLength == WEP_40_LEN) + rCmdKey.ucAlgorithmId = CIPHER_SUITE_WEP40; /* WEP 40 */ + else if (prNewKey->u4KeyLength == WEP_104_LEN) + rCmdKey.ucAlgorithmId = CIPHER_SUITE_WEP104; /* WEP 104 */ + else + ASSERT(FALSE); + rCmdKey.ucKeyId = (uint8_t) (prNewKey->u4KeyIndex & 0xff); + rCmdKey.ucKeyLen = (uint8_t) prNewKey->u4KeyLength; + kalMemCopy(rCmdKey.aucKeyMaterial, + (uint8_t *) prNewKey->aucKeyMaterial, rCmdKey.ucKeyLen); + + if ((rCmdKey.aucPeerAddr[0] & + rCmdKey.aucPeerAddr[1] & rCmdKey.aucPeerAddr[2] & + rCmdKey.aucPeerAddr[3] & rCmdKey.aucPeerAddr[4] & + rCmdKey.aucPeerAddr[5]) == 0xFF) { + kalMemCopy(rCmdKey.aucPeerAddr, + prBssInfo->aucBSSID, MAC_ADDR_LEN); + if (!rCmdKey.ucIsAuthenticator) { + prStaRec = cnmGetStaRecByAddress(prAdapter, + rCmdKey.ucBssIdx, rCmdKey.aucPeerAddr); + if (!prStaRec) + ASSERT(FALSE); + } + } else { + prStaRec = cnmGetStaRecByAddress(prAdapter, + rCmdKey.ucBssIdx, rCmdKey.aucPeerAddr); + } + + if (rCmdKey.ucTxKey) { + if (prStaRec) { + if (rCmdKey.ucKeyType) { /* RSN STA */ + ASSERT(prStaRec->ucWlanIndex < WTBL_SIZE); + rCmdKey.ucWlanIndex = prStaRec->ucWlanIndex; + /* wait for CMD Done ? */ + prStaRec->fgTransmitKeyExist = TRUE; + } else { + ASSERT(FALSE); + } + } else { + if (prBssInfo) { /* GO/AP Tx BC */ + ASSERT(prBssInfo->ucBMCWlanIndex < WTBL_SIZE); + rCmdKey.ucWlanIndex = prBssInfo->ucBMCWlanIndex; + prBssInfo->fgBcDefaultKeyExist = TRUE; + prBssInfo->ucTxDefaultKeyID = rCmdKey.ucKeyId; + } else { + /* GC WEP Tx key ? */ + rCmdKey.ucWlanIndex = 255; + ASSERT(FALSE); + } + } + } else { + if (((rCmdKey.aucPeerAddr[0] & rCmdKey.aucPeerAddr[1] & + rCmdKey.aucPeerAddr[2] & rCmdKey.aucPeerAddr[3] & + rCmdKey.aucPeerAddr[4] & + rCmdKey.aucPeerAddr[5]) == 0xFF) || + ((rCmdKey.aucPeerAddr[0] | rCmdKey.aucPeerAddr[1] | + rCmdKey.aucPeerAddr[2] | rCmdKey.aucPeerAddr[3] | + rCmdKey.aucPeerAddr[4] | rCmdKey.aucPeerAddr[5]) == 0x00)) { + rCmdKey.ucWlanIndex = 255; /* GC WEP ? */ + ASSERT(FALSE); + } else { + if (prStaRec) { /* GC Rx RSN Group key */ + rCmdKey.ucWlanIndex = + secPrivacySeekForBcEntry(prAdapter, + prStaRec->ucBssIndex, + prStaRec->aucMacAddr, + prStaRec->ucIndex, + rCmdKey.ucAlgorithmId, + rCmdKey.ucKeyId); + prStaRec->ucBMCWlanIndex = rCmdKey.ucWlanIndex; + ASSERT(prStaRec->ucBMCWlanIndex < WTBL_SIZE); + } else { /* Exist this case ? */ + ASSERT(FALSE); + } + } + } + + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_ADD_REMOVE_KEY, + prNewKey->ucBssIdx, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + NULL, + sizeof(struct CMD_802_11_KEY), + (uint8_t *)&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 + */ +/*---------------------------------------------------------------------------*/ +uint32_t +wlanoidSetRemoveP2PKey(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct CMD_802_11_KEY rCmdKey; + struct PARAM_REMOVE_KEY *prRemovedKey; + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + + DEBUGFUNC("wlanoidSetRemoveP2PKey"); + ASSERT(prAdapter); + + if (u4SetBufferLen < sizeof(struct PARAM_REMOVE_KEY)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + prRemovedKey = (struct PARAM_REMOVE_KEY *) 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; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prRemovedKey->ucBssIdx); + + kalMemZero((uint8_t *)&rCmdKey, sizeof(struct CMD_802_11_KEY)); + + rCmdKey.ucAddRemove = 0; /* remove */ + /* group client */ + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + rCmdKey.ucIsAuthenticator = 0; + } else { /* group owner */ + rCmdKey.ucIsAuthenticator = 1; + } + kalMemCopy(rCmdKey.aucPeerAddr, + (uint8_t *) prRemovedKey->arBSSID, MAC_ADDR_LEN); + rCmdKey.ucBssIdx = prRemovedKey->ucBssIdx; + rCmdKey.ucKeyId = (uint8_t) (prRemovedKey->u4KeyIndex & 0x000000ff); + + /* Clean up the Tx key flag */ + prStaRec = cnmGetStaRecByAddress(prAdapter, + prRemovedKey->ucBssIdx, prRemovedKey->arBSSID); + + /* mark for MR1 to avoid remove-key, + * but remove the wlan_tbl0 at the same time + */ + if (1 /*prRemovedKey->u4KeyIndex & IS_UNICAST_KEY */) { + if (prStaRec) { + rCmdKey.ucKeyType = 1; + rCmdKey.ucWlanIndex = prStaRec->ucWlanIndex; + prStaRec->fgTransmitKeyExist = FALSE; + } else if (rCmdKey.ucIsAuthenticator) + prBssInfo->fgBcDefaultKeyExist = FALSE; + } else { + if (rCmdKey.ucIsAuthenticator) + prBssInfo->fgBcDefaultKeyExist = FALSE; + } + + if (!prStaRec) { + if (prAdapter->rWifiVar.rConnSettings.eAuthMode < AUTH_MODE_WPA + && prAdapter->rWifiVar.rConnSettings.eEncStatus + != ENUM_ENCRYPTION_DISABLED) { + rCmdKey.ucWlanIndex = prBssInfo->ucBMCWlanIndex; + } else { + rCmdKey.ucWlanIndex = WTBL_RESERVED_ENTRY; + return WLAN_STATUS_SUCCESS; + } + } + + /* mark for MR1 to avoid remove-key, + * but remove the wlan_tbl0 at the same time + */ + /* secPrivacyFreeForEntry(prAdapter, rCmdKey.ucWlanIndex); */ + + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_ADD_REMOVE_KEY, + prRemovedKey->ucBssIdx, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + NULL, + sizeof(struct CMD_802_11_KEY), + (uint8_t *)&rCmdKey, + pvSetBuffer, + u4SetBufferLen); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetP2pNetworkAddress(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t i, j; + struct CMD_SET_NETWORK_ADDRESS_LIST *prCmdNWAddrList; + struct PARAM_NETWORK_ADDRESS_LIST *prNWAddrList = + (struct PARAM_NETWORK_ADDRESS_LIST *) pvSetBuffer; + struct PARAM_NETWORK_ADDRESS *prNWAddress; + struct PARAM_NETWORK_ADDRESS_IP *prNetAddrIp; + uint32_t u4IpAddressCount, u4CmdSize; + + DEBUGFUNC("wlanoidSetP2pNetworkAddress"); + DBGLOG(INIT, TRACE, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 4; + + if (u4SetBufferLen < sizeof(struct PARAM_NETWORK_ADDRESS_LIST)) + return WLAN_STATUS_INVALID_DATA; + + *pu4SetInfoLen = 0; + u4IpAddressCount = 0; + + prNWAddress = prNWAddrList->arAddress; + for (i = 0; i < prNWAddrList->u4AddressCount; i++) { + if (prNWAddress->u2AddressType + == PARAM_PROTOCOL_ID_TCP_IP && + prNWAddress->u2AddressLength + == sizeof(struct PARAM_NETWORK_ADDRESS_IP)) { + u4IpAddressCount++; + } + + prNWAddress = (struct PARAM_NETWORK_ADDRESS *) + ((unsigned long) prNWAddress + + (unsigned long) (prNWAddress->u2AddressLength + + OFFSET_OF(struct PARAM_NETWORK_ADDRESS, aucAddress))); + } + + /* construct payload of command packet */ + u4CmdSize = + OFFSET_OF(struct CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress) + + sizeof(struct IPV4_NETWORK_ADDRESS) * u4IpAddressCount; + + prCmdNWAddrList = (struct CMD_SET_NETWORK_ADDRESS_LIST *) + kalMemAlloc(u4CmdSize, VIR_MEM_TYPE); + + if (prCmdNWAddrList == NULL) + return WLAN_STATUS_FAILURE; + + /* fill P_CMD_SET_NETWORK_ADDRESS_LIST */ + prCmdNWAddrList->ucBssIndex = prNWAddrList->ucBssIdx; + prCmdNWAddrList->ucAddressCount = (uint8_t) u4IpAddressCount; + prNWAddress = prNWAddrList->arAddress; + for (i = 0, j = 0; i < prNWAddrList->u4AddressCount; i++) { + if (prNWAddress->u2AddressType + == PARAM_PROTOCOL_ID_TCP_IP && + prNWAddress->u2AddressLength + == sizeof(struct PARAM_NETWORK_ADDRESS_IP)) { + prNetAddrIp = (struct PARAM_NETWORK_ADDRESS_IP *) + prNWAddress->aucAddress; + + kalMemCopy( + prCmdNWAddrList->arNetAddress[j].aucIpAddr, + &(prNetAddrIp->in_addr), sizeof(uint32_t)); + + j++; + } + + prNWAddress = (struct PARAM_NETWORK_ADDRESS *) + ((unsigned long) prNWAddress + + (unsigned long) (prNWAddress->u2AddressLength + + OFFSET_OF(struct PARAM_NETWORK_ADDRESS, aucAddress))); + } + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_IP_ADDRESS, + TRUE, + FALSE, + TRUE, + nicCmdEventSetIpAddress, + nicOidCmdTimeoutCommon, + u4CmdSize, + (uint8_t *) prCmdNWAddrList, + pvSetBuffer, + u4SetBufferLen); + + kalMemFree(prCmdNWAddrList, 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryP2pPowerSaveProfile(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryP2pPowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen != 0) { + ASSERT(pvQueryBuffer); + /* TODO: FIXME */ + /* *(enum PARAM_POWER_MODE *) pvQueryBuffer = + * (enum PARAM_POWER_MODE) + *(prAdapter->rWlanInfo. + * arPowerSaveMode[prAdapter->ucP2PDevBssIdx].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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetP2pPowerSaveProfile(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t status; + enum PARAM_POWER_MODE ePowerMode; + + DEBUGFUNC("wlanoidSetP2pPowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(enum PARAM_POWER_MODE); + if (u4SetBufferLen < sizeof(enum PARAM_POWER_MODE)) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } else if (*(enum PARAM_POWER_MODE *) + pvSetBuffer >= Param_PowerModeMax) { + DBGLOG(REQ, WARN, "Invalid power mode %d\n", + *(enum PARAM_POWER_MODE *) pvSetBuffer); + return WLAN_STATUS_INVALID_DATA; + } + + ePowerMode = *(enum PARAM_POWER_MODE *) pvSetBuffer; + + if (prAdapter->fgEnCtiaPowerMode) { + if (ePowerMode == Param_PowerModeCAM) { + /*Todo:: Nothing */ + /*Todo:: Nothing */ + } else { + /* User setting to PS mode + *(Param_PowerModeMAX_PSP or Param_PowerModeFast_PSP) + */ + + if (prAdapter->u4CtiaPowerMode == 0) { + /* force to keep in CAM mode */ + ePowerMode = Param_PowerModeCAM; + } else if (prAdapter->u4CtiaPowerMode == 1) { + ePowerMode = Param_PowerModeMAX_PSP; + } else if (prAdapter->u4CtiaPowerMode == 2) { + ePowerMode = Param_PowerModeFast_PSP; + } + } + } + + /* TODO: FIXME */ + status = nicConfigPowerSaveProfile(prAdapter, prAdapter->ucP2PDevBssIdx, + ePowerMode, g_fgIsOid, PS_CALLER_P2P); + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetP2pSetNetworkAddress(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t i, j; + struct CMD_SET_NETWORK_ADDRESS_LIST *prCmdNWAddrList; + struct PARAM_NETWORK_ADDRESS_LIST *prNWAddrList = + (struct PARAM_NETWORK_ADDRESS_LIST *) pvSetBuffer; + struct PARAM_NETWORK_ADDRESS *prNWAddress; + struct PARAM_NETWORK_ADDRESS_IP *prNetAddrIp; + uint32_t u4IpAddressCount, u4CmdSize; + uint8_t *pucBuf = (uint8_t *) pvSetBuffer; + + DEBUGFUNC("wlanoidSetP2pSetNetworkAddress"); + DBGLOG(INIT, TRACE, "\n"); + DBGLOG(INIT, INFO, "wlanoidSetP2pSetNetworkAddress (%d)\n", + (int16_t) u4SetBufferLen); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 4; + + if (u4SetBufferLen < sizeof(struct PARAM_NETWORK_ADDRESS_LIST)) + return WLAN_STATUS_INVALID_DATA; + + *pu4SetInfoLen = 0; + u4IpAddressCount = 0; + + prNWAddress = prNWAddrList->arAddress; + for (i = 0; i < prNWAddrList->u4AddressCount; i++) { + if (prNWAddress->u2AddressType + == PARAM_PROTOCOL_ID_TCP_IP && + prNWAddress->u2AddressLength + == sizeof(struct PARAM_NETWORK_ADDRESS_IP)) { + u4IpAddressCount++; + } + + prNWAddress = (struct PARAM_NETWORK_ADDRESS *) + ((unsigned long) prNWAddress + + (unsigned long) (prNWAddress->u2AddressLength + + OFFSET_OF(struct PARAM_NETWORK_ADDRESS, aucAddress))); + } + + /* construct payload of command packet */ + u4CmdSize = + OFFSET_OF(struct CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress) + + sizeof(struct IPV4_NETWORK_ADDRESS) * u4IpAddressCount; + + if (u4IpAddressCount == 0) + u4CmdSize = sizeof(struct CMD_SET_NETWORK_ADDRESS_LIST); + + prCmdNWAddrList = (struct CMD_SET_NETWORK_ADDRESS_LIST *) + kalMemAlloc(u4CmdSize, VIR_MEM_TYPE); + + if (prCmdNWAddrList == NULL) + return WLAN_STATUS_FAILURE; + + /* fill P_CMD_SET_NETWORK_ADDRESS_LIST */ + prCmdNWAddrList->ucBssIndex = prNWAddrList->ucBssIdx; + + /* only to set IP address to FW once ARP filter is enabled */ + if (prAdapter->fgEnArpFilter) { + prCmdNWAddrList->ucAddressCount = + (uint8_t) u4IpAddressCount; + prNWAddress = prNWAddrList->arAddress; + + DBGLOG(INIT, INFO, "u4IpAddressCount (%u)\n", + (int32_t) u4IpAddressCount); + + for (i = 0, j = 0; i < prNWAddrList->u4AddressCount; i++) { + if (prNWAddress->u2AddressType + == PARAM_PROTOCOL_ID_TCP_IP && + prNWAddress->u2AddressLength + == sizeof(struct PARAM_NETWORK_ADDRESS_IP)) { + + prNetAddrIp = + (struct PARAM_NETWORK_ADDRESS_IP *) + prNWAddress->aucAddress; + + kalMemCopy( + prCmdNWAddrList->arNetAddress[j] + .aucIpAddr, + &(prNetAddrIp->in_addr), + sizeof(uint32_t)); + + j++; + + pucBuf = (uint8_t *) &prNetAddrIp->in_addr; + DBGLOG(INIT, INFO, + "prNetAddrIp->in_addr:%d:%d:%d:%d\n", + (uint8_t) pucBuf[0], + (uint8_t) pucBuf[1], + (uint8_t) pucBuf[2], + (uint8_t) pucBuf[3]); + } + + prNWAddress = (struct PARAM_NETWORK_ADDRESS *) + ((unsigned long) prNWAddress + + (unsigned long) (prNWAddress->u2AddressLength + + OFFSET_OF(struct PARAM_NETWORK_ADDRESS, + aucAddress))); + } + + } else { + prCmdNWAddrList->ucAddressCount = 0; + } + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_IP_ADDRESS, + TRUE, + FALSE, + TRUE, + nicCmdEventSetIpAddress, + nicOidCmdTimeoutCommon, + u4CmdSize, + (uint8_t *) prCmdNWAddrList, + pvSetBuffer, + u4SetBufferLen); + + kalMemFree(prCmdNWAddrList, 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetP2PMulticastList(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct CMD_MAC_MCAST_ADDR rCmdMacMcastAddr; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* The data must be a multiple of the Ethernet address size. */ + if ((u4SetBufferLen % MAC_ADDR_LEN)) { + DBGLOG(REQ, WARN, "Invalid MC list length %u\n", + u4SetBufferLen); + + *pu4SetInfoLen = + (((u4SetBufferLen + MAC_ADDR_LEN) - 1) + / MAC_ADDR_LEN) * MAC_ADDR_LEN; + + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = u4SetBufferLen; + + /* Verify if we can support so many multicast addresses. */ + if (u4SetBufferLen > MAX_NUM_GROUP_ADDR * MAC_ADDR_LEN) { + 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; + /* TODO: */ + rCmdMacMcastAddr.ucBssIndex = prAdapter->ucP2PDevBssIdx; + kalMemCopy(rCmdMacMcastAddr.arAddress, pvSetBuffer, u4SetBufferLen); + + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_MAC_MCAST_ADDR, + prAdapter->ucP2PDevBssIdx, + /* TODO: */ + /* This CMD response is no need + * to complete the OID. + * Or the event would unsync. + */ + TRUE, FALSE, FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_MAC_MCAST_ADDR), + (uint8_t *) &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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSendP2PSDRequest(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (u4SetBufferLen < sizeof(struct PARAM_P2P_SEND_SD_REQUEST)) { + *pu4SetInfoLen = sizeof(struct 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSendP2PSDResponse(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (u4SetBufferLen < sizeof(struct PARAM_P2P_SEND_SD_RESPONSE)) { + *pu4SetInfoLen = sizeof(struct 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidGetP2PSDRequest(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; +/* PUINT_8 pucChannelNum = NULL; */ +/* UINT_8 ucChannelNum = 0, ucSeqNum = 0; */ + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(struct PARAM_P2P_GET_SD_REQUEST)) { + *pu4QueryInfoLen = sizeof(struct PARAM_P2P_GET_SD_REQUEST); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + DBGLOG(P2P, TRACE, "Get Service Discovery Request\n"); + + *pu4QueryInfoLen = 0; + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidGetP2PSDResponse(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + /* UINT_8 ucSeqNum = 0, */ + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(struct PARAM_P2P_GET_SD_RESPONSE)) { + *pu4QueryInfoLen = sizeof(struct PARAM_P2P_GET_SD_RESPONSE); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + DBGLOG(P2P, TRACE, "Get Service Discovery Response\n"); + + *pu4QueryInfoLen = 0; + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetP2PTerminateSDPhase(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct PARAM_P2P_TERMINATE_SD_PHASE *prP2pTerminateSD = + (struct PARAM_P2P_TERMINATE_SD_PHASE *) NULL; + uint8_t aucNullAddr[] = NULL_MAC_ADDR; + + do { + if ((prAdapter == NULL) || (pu4SetInfoLen == NULL)) + break; + + if ((u4SetBufferLen) && (pvSetBuffer == NULL)) + break; + + if (u4SetBufferLen + < sizeof(struct PARAM_P2P_TERMINATE_SD_PHASE)) { + + *pu4SetInfoLen = + sizeof(struct PARAM_P2P_TERMINATE_SD_PHASE); + rWlanStatus = WLAN_STATUS_BUFFER_TOO_SHORT; + break; + } + + prP2pTerminateSD = + (struct 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetSecCheckRequest(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + +#if 0 /* Comment it because CMD_ID_SEC_CHECK is not defined */ + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SEC_CHECK, + prAdapter->ucP2PDevBssIdx, + FALSE, + TRUE, + TRUE, + NULL, + nicOidCmdTimeoutCommon, + u4SetBufferLen, + (uint8_t *) pvSetBuffer, + pvSetBuffer, + u4SetBufferLen); +#else + return WLAN_STATUS_NOT_SUPPORTED; +#endif +} /* end of wlanoidSetSecCheckRequest() */ + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidGetSecCheckResponse(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + /* P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T)NULL; */ + struct GLUE_INFO *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[0]->aucSecCheckRsp, + u4QueryBufferLen); +#endif + kalMemCopy((uint8_t *) + (pvQueryBuffer + + OFFSET_OF(struct iw_p2p_transport_struct, aucBuffer)), + prGlueInfo->prP2PInfo[0]->aucSecCheckRsp, + u4QueryBufferLen); + + return rWlanStatus; +} /* end of wlanoidGetSecCheckResponse() */ +#endif +#endif + +uint32_t +wlanoidSetNoaParam(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct PARAM_CUSTOM_NOA_PARAM_STRUCT *prNoaParam; + struct CMD_CUSTOM_NOA_PARAM_STRUCT rCmdNoaParam; + + DEBUGFUNC("wlanoidSetNoaParam"); + DBGLOG(INIT, TRACE, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CUSTOM_NOA_PARAM_STRUCT); + + if (u4SetBufferLen < sizeof(struct PARAM_CUSTOM_NOA_PARAM_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prNoaParam = (struct PARAM_CUSTOM_NOA_PARAM_STRUCT *) pvSetBuffer; + + kalMemZero(&rCmdNoaParam, sizeof(struct CMD_CUSTOM_NOA_PARAM_STRUCT)); + rCmdNoaParam.u4NoaDurationMs = prNoaParam->u4NoaDurationMs; + rCmdNoaParam.u4NoaIntervalMs = prNoaParam->u4NoaIntervalMs; + rCmdNoaParam.u4NoaCount = prNoaParam->u4NoaCount; + rCmdNoaParam.ucBssIdx = prNoaParam->ucBssIdx; + +#if 0 + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_NOA_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_CUSTOM_NOA_PARAM_STRUCT), + (uint8_t *) &rCmdNoaParam, + pvSetBuffer, + u4SetBufferLen); +#else + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_NOA_PARAM, + prNoaParam->ucBssIdx, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_CUSTOM_NOA_PARAM_STRUCT), + (uint8_t *) &rCmdNoaParam, + pvSetBuffer, + u4SetBufferLen); + +#endif + +} + +uint32_t +wlanoidSetOppPsParam(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct PARAM_CUSTOM_OPPPS_PARAM_STRUCT *prOppPsParam; + struct CMD_CUSTOM_OPPPS_PARAM_STRUCT rCmdOppPsParam; + + DEBUGFUNC("wlanoidSetOppPsParam"); + DBGLOG(INIT, TRACE, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CUSTOM_OPPPS_PARAM_STRUCT); + + if (u4SetBufferLen < sizeof(struct PARAM_CUSTOM_OPPPS_PARAM_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prOppPsParam = (struct PARAM_CUSTOM_OPPPS_PARAM_STRUCT *) pvSetBuffer; + + kalMemZero(&rCmdOppPsParam, + sizeof(struct CMD_CUSTOM_OPPPS_PARAM_STRUCT)); + rCmdOppPsParam.u4CTwindowMs = prOppPsParam->u4CTwindowMs; + rCmdOppPsParam.ucBssIdx = prOppPsParam->ucBssIdx; + +#if 0 + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_OPPPS_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_CUSTOM_OPPPS_PARAM_STRUCT), + (uint8_t *) &rCmdOppPsParam, + pvSetBuffer, + u4SetBufferLen); +#else + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_OPPPS_PARAM, + prOppPsParam->ucBssIdx, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_CUSTOM_OPPPS_PARAM_STRUCT), + (uint8_t *) &rCmdOppPsParam, + pvSetBuffer, + u4SetBufferLen); + +#endif + +} + +uint32_t +wlanoidSetUApsdParam(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + struct PARAM_CUSTOM_UAPSD_PARAM_STRUCT *prUapsdParam; + struct CMD_CUSTOM_UAPSD_PARAM_STRUCT rCmdUapsdParam; + struct PM_PROFILE_SETUP_INFO *prPmProfSetupInfo; + struct BSS_INFO *prBssInfo; + + DEBUGFUNC("wlanoidSetUApsdParam"); + DBGLOG(INIT, TRACE, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CUSTOM_UAPSD_PARAM_STRUCT); + + if (u4SetBufferLen < sizeof(struct PARAM_CUSTOM_UAPSD_PARAM_STRUCT)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prUapsdParam = (struct PARAM_CUSTOM_UAPSD_PARAM_STRUCT *) pvSetBuffer; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prUapsdParam->ucBssIdx); + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + + kalMemZero(&rCmdUapsdParam, + sizeof(struct CMD_CUSTOM_UAPSD_PARAM_STRUCT)); + + rCmdUapsdParam.fgEnAPSD = 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(struct CMD_CUSTOM_UAPSD_PARAM_STRUCT), + (uint8_t *) &rCmdUapsdParam, + pvSetBuffer, + u4SetBufferLen); +#else + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_UAPSD_PARAM, + prBssInfo->ucBssIndex, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_CUSTOM_UAPSD_PARAM_STRUCT), + (uint8_t *) &rCmdUapsdParam, + pvSetBuffer, + u4SetBufferLen); + +#endif +} + +uint32_t +wlanoidQueryP2pVersion(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + uint32_t 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(uint8_t)) { + *pu4QueryInfoLen = sizeof(uint8_t); + rResult = WLAN_STATUS_BUFFER_TOO_SHORT; + break; + } + + } while (FALSE); + + return rResult; +} /* wlanoidQueryP2pVersion */ + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to set the WPS mode. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. + * \param[in] u4SetBufferLen The length of the set buffer. + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed + * due to invalid length of the set buffer, returns + * the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetP2pWPSmode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t status; + uint32_t u4IsWPSmode = 0; + int i = 0; + + DEBUGFUNC("wlanoidSetP2pWPSmode"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (pvSetBuffer) + u4IsWPSmode = *(uint32_t *) pvSetBuffer; + else + u4IsWPSmode = 0; + + /* set all Role to the same value */ + for (i = 0; i < KAL_P2P_NUM; i++) + if (u4IsWPSmode) + prAdapter->rWifiVar.prP2PConnSettings[i]->fgIsWPSMode + = 1; + else + prAdapter->rWifiVar.prP2PConnSettings[i]->fgIsWPSMode + = 0; + + status = nicUpdateBss(prAdapter, prAdapter->ucP2PDevBssIdx); + + return status; +} /* end of wlanoidSetP2pWPSmode() */ + +#endif + +uint32_t +wlanoidSetP2pSupplicantVersion(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t rResult = WLAN_STATUS_FAILURE; + uint8_t 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(uint8_t); + + if (u4SetBufferLen < sizeof(uint8_t)) { + rResult = WLAN_STATUS_INVALID_LENGTH; + break; + } + + ucVersionNum = *((uint8_t *) pvSetBuffer); + + rResult = WLAN_STATUS_SUCCESS; + } while (FALSE); + + return rResult; +} /* wlanoidSetP2pSupplicantVersion */ + +#if CFG_SUPPORT_P2P_RSSI_QUERY +uint32_t +wlanoidQueryP2pRssi(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryP2pRssi"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (prAdapter->fgIsEnableLpdvt) + return WLAN_STATUS_NOT_SUPPORTED; + + *pu4QueryInfoLen = sizeof(int32_t); + + /* 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) { + + int32_t rRssi; + + /* ranged from (-128 ~ 30) in unit of dBm */ + rRssi = (int32_t) prAdapter->rP2pLinkQuality.cRssi; + + 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(int32_t)); + 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 + +uint32_t +wlanoidAbortP2pScan(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) { + + DBGLOG(P2P, INFO, "wlanoidAbortP2pScan\n"); + + ASSERT(prAdapter); + + p2pDevFsmRunEventScanAbort(prAdapter, NULL); + + return WLAN_STATUS_SUCCESS; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/init.wlan_mt7663_drv.rc b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/init.wlan_mt7663_drv.rc new file mode 100644 index 0000000000000..90f779d14c008 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/init.wlan_mt7663_drv.rc @@ -0,0 +1,3 @@ +on boot + insmod /vendor/lib/modules/wlan_drv_gen4_mt7663_prealloc.ko +# insmod /vendor/lib/modules/wlan_drv_gen4_mt7663.ko diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/cmd_buf.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/cmd_buf.c new file mode 100644 index 0000000000000..cf569819ab449 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/cmd_buf.c @@ -0,0 +1,322 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + + +/******************************************************************************* + * C O M P I L E 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 + ******************************************************************************* + */ +u_int8_t fgCmdDumpIsDone = FALSE; +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is used to initial the MGMT memory pool for CMD Packet. + * + * @param prAdapter Pointer to the Adapter structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void cmdBufInitialize(IN struct ADAPTER *prAdapter) +{ + struct CMD_INFO *prCmdInfo; + uint32_t 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 dump CMD queue and print to trace, for debug use only + * @param[in] prQueue Pointer to the command Queue to be dumped + * @param[in] quename Name of the queue + */ +/*----------------------------------------------------------------------------*/ +void cmdBufDumpCmdQueue(struct QUE *prQueue, + int8_t *queName) +{ + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) + QUEUE_GET_HEAD(prQueue); + + DBGLOG(NIC, INFO, "Dump CMD info for %s, Elem number:%u\n", + queName, prQueue->u4NumElem); + while (prCmdInfo) { + struct CMD_INFO *prCmdInfo1, *prCmdInfo2, *prCmdInfo3; + + prCmdInfo1 = (struct CMD_INFO *)QUEUE_GET_NEXT_ENTRY(( + struct QUE_ENTRY *)prCmdInfo); + if (!prCmdInfo1) { + DBGLOG(NIC, INFO, "CID:%d SEQ:%d\n", prCmdInfo->ucCID, + prCmdInfo->ucCmdSeqNum); + break; + } + prCmdInfo2 = (struct CMD_INFO *)QUEUE_GET_NEXT_ENTRY(( + struct QUE_ENTRY *)prCmdInfo1); + if (!prCmdInfo2) { + DBGLOG(NIC, INFO, "CID:%d, SEQ:%d; CID:%d, SEQ:%d\n", + prCmdInfo->ucCID, + prCmdInfo->ucCmdSeqNum, prCmdInfo1->ucCID, + prCmdInfo1->ucCmdSeqNum); + break; + } + prCmdInfo3 = (struct CMD_INFO *)QUEUE_GET_NEXT_ENTRY(( + struct QUE_ENTRY *)prCmdInfo2); + if (!prCmdInfo3) { + DBGLOG(NIC, INFO, + "CID:%d, SEQ:%d; CID:%d, SEQ:%d; CID:%d, SEQ:%d\n", + prCmdInfo->ucCID, + prCmdInfo->ucCmdSeqNum, prCmdInfo1->ucCID, + prCmdInfo1->ucCmdSeqNum, + prCmdInfo2->ucCID, prCmdInfo2->ucCmdSeqNum); + break; + } + DBGLOG(NIC, INFO, + "CID:%d, SEQ:%d; CID:%d, SEQ:%d; CID:%d, SEQ:%d; CID:%d, SEQ:%d\n", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum, + prCmdInfo1->ucCID, prCmdInfo1->ucCmdSeqNum, + prCmdInfo2->ucCID, prCmdInfo2->ucCmdSeqNum, + prCmdInfo3->ucCID, prCmdInfo3->ucCmdSeqNum); + prCmdInfo = (struct CMD_INFO *)QUEUE_GET_NEXT_ENTRY(( + struct QUE_ENTRY *)prCmdInfo3); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Allocate CMD_INFO_T from a free list and MGMT memory pool. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] u4Length Length of the frame buffer to allocate. + * + * @retval NULL Pointer to the valid CMD Packet handler + * @retval !NULL Fail to allocat CMD Packet + */ +/*----------------------------------------------------------------------------*/ +struct CMD_INFO *cmdBufAllocateCmdInfo(IN struct ADAPTER + *prAdapter, IN uint32_t u4Length) +{ + struct CMD_INFO *prCmdInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("cmdBufAllocateCmdInfo"); + + ASSERT(prAdapter); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + QUEUE_REMOVE_HEAD(&prAdapter->rFreeCmdList, prCmdInfo, + struct CMD_INFO *); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + + if (prCmdInfo) { + /* Setup initial value in CMD_INFO_T */ + prCmdInfo->u2InfoBufLen = 0; + prCmdInfo->fgIsOid = FALSE; + + if (u4Length) { + /* Start address of allocated memory */ + u4Length = TFCB_FRAME_PAD_TO_DW(u4Length); + + 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 { + kalMemZero(prCmdInfo->pucInfoBuffer, u4Length); + } + } else { + prCmdInfo->pucInfoBuffer = NULL; + } + fgCmdDumpIsDone = FALSE; + } else if (!fgCmdDumpIsDone) { + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct QUE *prCmdQue = &prGlueInfo->rCmdQueue; + struct QUE *prPendingCmdQue = &prAdapter->rPendingCmdQueue; + struct TX_TCQ_STATUS *prTc = &prAdapter->rTxCtrl.rTc; + + fgCmdDumpIsDone = TRUE; + cmdBufDumpCmdQueue(prCmdQue, "waiting Tx CMD queue"); + cmdBufDumpCmdQueue(prPendingCmdQue, + "waiting response CMD queue"); + DBGLOG(NIC, INFO, "Tc4 number:%d\n", + prTc->au4FreeBufferCount[TC4_INDEX]); + } + + if (prCmdInfo) { + DBGLOG(MEM, LOUD, + "CMD[0x%p] allocated! LEN[%04u], Rest[%u]\n", + prCmdInfo, u4Length, prAdapter->rFreeCmdList.u4NumElem); + } else { + DBGLOG(MEM, WARN, + "CMD allocation failed! LEN[%04u], Rest[%u]\n", + u4Length, prAdapter->rFreeCmdList.u4NumElem); + } + + 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 struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo) +{ + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("cmdBufFreeCmdInfo"); + + ASSERT(prAdapter); + + if (prCmdInfo) { + if (prCmdInfo->pucInfoBuffer) { + cnmMemFree(prAdapter, prCmdInfo->pucInfoBuffer); + prCmdInfo->pucInfoBuffer = NULL; + } + + prCmdInfo->fgIsOid = FALSE; + + 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); + } + + if (prCmdInfo) + DBGLOG(MEM, LOUD, "CMD[0x%p] freed! Rest[%u]\n", prCmdInfo, + prAdapter->rFreeCmdList.u4NumElem); + + return; + +} /* end of cmdBufFreeCmdPacket() */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic.c new file mode 100644 index 0000000000000..0c6ef6d1f43fd --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic.c @@ -0,0 +1,4870 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic.c#4 + */ + +/*! \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. + */ + + +/******************************************************************************* + * C O M P I L E 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 uint8_t 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 */ + PHY_TYPE_SET_802_11AC, + PHY_TYPE_SET_802_11ANAC, + PHY_TYPE_SET_802_11ABGNAC +}; + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +static struct INT_EVENT_MAP 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 uint8_t ucIntEventMapSize = (sizeof( + arIntEventMapTable) / sizeof(struct INT_EVENT_MAP)); + +static IST_EVENT_FUNCTION apfnEventFuncTable[] = { + nicProcessAbnormalInterrupt, /*!< INT_EVENT_ABNORMAL */ + nicProcessSoftwareInterrupt, /*!< INT_EVENT_SW_INT */ + nicProcessTxInterrupt, /*!< INT_EVENT_TX */ + nicProcessRxInterrupt, /*!< INT_EVENT_RX */ +}; + +struct ECO_INFO g_eco_info = {0xFF}; + +#ifdef CFG_SUPPORT_TIME_MEASURE +/* 11mc Audio Sync */ +uint64_t g_u8SysClkps; +uint64_t g_u8LastSysClkps; +int64_t g_i8HostClkRateDiff; +uint64_t g_u8NicCnt; +int64_t g_i8ClockOffset; +int64_t g_i8ClkRateDiff; +uint64_t g_u8LastToA; +#endif + +/******************************************************************************* + * 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) \ +{ \ + pucMem = (uint8_t *)kalMemAlloc(u4Size, eMemType); \ + if (pucMem == (uint8_t *)NULL) { \ + DBGLOG(INIT, ERROR, \ + "Could not allocate %u bytes for %s.\n", \ + u4Size, (char *) pucComment); \ + break; \ + } \ + ASSERT(((unsigned long)pucMem % 4) == 0); \ + DBGLOG(INIT, TRACE, "Alloc %u bytes, addr = 0x%p for %s.\n", \ + u4Size, (void *) pucMem, (char *) 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicAllocateAdapterMemory(IN struct ADAPTER + *prAdapter) +{ + uint32_t status = WLAN_STATUS_RESOURCES; + struct RX_CTRL *prRxCtrl; + struct TX_CTRL *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 = (uint8_t *) NULL; + prRxCtrl->pucRxCached = (uint8_t *) NULL; + + /* 4 <1> Memory for Management Memory Pool and CMD_INFO_T */ + /* Allocate memory for the struct CMD_INFO + * and its MGMT memory pool. + */ + prAdapter->u4MgtBufCachedSize = MGT_BUFFER_SIZE; + +#ifdef CFG_PREALLOC_MEMORY + prAdapter->pucMgtBufCached = preallocGetMem(MEM_ID_NIC_ADAPTER); +#else + LOCAL_NIC_ALLOCATE_MEMORY(prAdapter->pucMgtBufCached, + prAdapter->u4MgtBufCachedSize, PHY_MEM_TYPE, + "COMMON MGMT MEMORY POOL"); +#endif + + /* 4 <2> Memory for RX Descriptor */ + /* Initialize the number of rx buffers + * we will have in our queue. + */ + /* We may setup ucRxPacketDescriptors by GLUE Layer, + * and using this variable directly. + */ + /* Allocate memory for the SW receive structures. */ + prRxCtrl->u4RxCachedSize = CFG_RX_MAX_PKT_NUM * ALIGN_4( + sizeof(struct SW_RFB)); + + LOCAL_NIC_ALLOCATE_MEMORY(prRxCtrl->pucRxCached, + prRxCtrl->u4RxCachedSize, + VIR_MEM_TYPE, "struct SW_RFB"); + + /* 4 <3> Memory for TX DEscriptor */ + prTxCtrl->u4TxCachedSize = CFG_TX_MAX_PKT_NUM * ALIGN_4( + sizeof(struct MSDU_INFO)); + + LOCAL_NIC_ALLOCATE_MEMORY(prTxCtrl->pucTxCached, + prTxCtrl->u4TxCachedSize, + VIR_MEM_TYPE, "struct MSDU_INFO"); + + /* 4 <4> Memory for Common Coalescing Buffer */ + + /* Get valid buffer size based on config & host capability */ + prAdapter->u4CoalescingBufCachedSize = + halGetValidCoalescingBufSize(prAdapter); + + /* Allocate memory for the common coalescing buffer. */ +#ifdef CFG_PREALLOC_MEMORY + prAdapter->pucCoalescingBufCached = + preallocGetMem(MEM_ID_IO_BUFFER); +#else + prAdapter->pucCoalescingBufCached = kalAllocateIOBuffer( + prAdapter->u4CoalescingBufCachedSize); +#endif + + if (prAdapter->pucCoalescingBufCached == NULL) { + DBGLOG(INIT, ERROR, + "Could not allocate %u bytes for coalescing buffer.\n", + prAdapter->u4CoalescingBufCachedSize); + break; + } + + /* <5> Memory for HIF */ + if (halAllocateIOBuffer(prAdapter) != WLAN_STATUS_SUCCESS) + 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 struct ADAPTER *prAdapter) +{ + struct TX_CTRL *prTxCtrl; + struct RX_CTRL *prRxCtrl; + uint32_t u4Idx; + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + + /* 4 <5> Memory for HIF */ + halReleaseIOBuffer(prAdapter); + + /* 4 <4> Memory for Common Coalescing Buffer */ + if (prAdapter->pucCoalescingBufCached) { +#ifndef CFG_PREALLOC_MEMORY + kalReleaseIOBuffer((void *) + prAdapter->pucCoalescingBufCached, + prAdapter->u4CoalescingBufCachedSize); +#endif + prAdapter->pucCoalescingBufCached = (uint8_t *) NULL; + } + + /* 4 <3> Memory for TX Descriptor */ + if (prTxCtrl->pucTxCached) { + kalMemFree(prTxCtrl->pucTxCached, VIR_MEM_TYPE, + prTxCtrl->u4TxCachedSize); + prTxCtrl->pucTxCached = (uint8_t *) NULL; + } + /* 4 <2> Memory for RX Descriptor */ + if (prRxCtrl->pucRxCached) { + kalMemFree(prRxCtrl->pucRxCached, VIR_MEM_TYPE, + prRxCtrl->u4RxCachedSize); + prRxCtrl->pucRxCached = (uint8_t *) NULL; + } + /* 4 <1> Memory for Management Memory Pool */ + if (prAdapter->pucMgtBufCached) { +#ifndef CFG_PREALLOC_MEMORY + kalMemFree(prAdapter->pucMgtBufCached, + PHY_MEM_TYPE, prAdapter->u4MgtBufCachedSize); +#endif + prAdapter->pucMgtBufCached = (uint8_t *) NULL; + } + + /* Memory for TX Desc Template */ + for (u4Idx = 0; u4Idx < CFG_STA_REC_NUM; u4Idx++) + nicTxFreeDescTemplate(prAdapter, + &prAdapter->arStaRec[u4Idx]); + +#if CFG_DBG_MGT_BUF + do { + u_int8_t fgUnfreedMem = FALSE; + struct BUF_INFO *prBufInfo; + + /* Dynamic allocated memory from OS */ + if (prAdapter->u4MemFreeDynamicCount != + prAdapter->u4MemAllocDynamicCount) + fgUnfreedMem = TRUE; + + /* MSG buffer */ + prBufInfo = &prAdapter->rMsgBufInfo; + if (prBufInfo->u4AllocCount != (prBufInfo->u4FreeCount + + prBufInfo->u4AllocNullCount)) + fgUnfreedMem = TRUE; + + /* MGT buffer */ + prBufInfo = &prAdapter->rMgtBufInfo; + if (prBufInfo->u4AllocCount != (prBufInfo->u4FreeCount + + prBufInfo->u4AllocNullCount)) + fgUnfreedMem = TRUE; + + /* Check if all allocated memories are free */ + if (fgUnfreedMem) { + DBGLOG(MEM, ERROR, + "Unequal memory alloc/free count!\n"); + + qmDumpQueueStatus(prAdapter, NULL, 0); + cnmDumpMemoryStatus(prAdapter, NULL, 0); + } + + if (!wlanIsChipNoAck(prAdapter)) { + /* Skip this ASSERT if chip is no ACK */ + ASSERT(prAdapter->u4MemFreeDynamicCount == + prAdapter->u4MemAllocDynamicCount); + } + } while (FALSE); +#endif + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief disable global interrupt + * + * @param prAdapter pointer to the Adapter handler + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicDisableInterrupt(IN struct ADAPTER *prAdapter) +{ + halDisableInterrupt(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief enable global interrupt + * + * @param prAdapter pointer to the Adapter handler + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicEnableInterrupt(IN struct ADAPTER *prAdapter) +{ + halEnableInterrupt(prAdapter); + +} /* end of nicEnableInterrupt() */ + +#if 0 /* CFG_SDIO_INTR_ENHANCE */ +/*----------------------------------------------------------------------------*/ +/*! + * @brief Read interrupt status from hardware + * + * @param prAdapter pointer to the Adapter handler + * @param the interrupts + * + * @return N/A + * + */ +/*----------------------------------------------------------------------------*/ +void nicSDIOReadIntStatus(IN struct ADAPTER *prAdapter, + OUT uint32_t *pu4IntStatus) +{ + struct ENHANCE_MODE_DATA_STRUCT *prSDIOCtrl; + + DEBUGFUNC("nicSDIOReadIntStatus"); + + ASSERT(prAdapter); + ASSERT(pu4IntStatus); + + prSDIOCtrl = prAdapter->prSDIOCtrl; + ASSERT(prSDIOCtrl); + + HAL_PORT_RD(prAdapter, + MCR_WHISR, + sizeof(struct ENHANCE_MODE_DATA_STRUCT), + (uint8_t *) prSDIOCtrl, + sizeof(struct ENHANCE_MODE_DATA_STRUCT)); + + 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->rTxInfo.au4WTSR[2] + | prSDIOCtrl->rTxInfo.au4WTSR[3] + | prSDIOCtrl->rTxInfo.au4WTSR[4] + | prSDIOCtrl->rTxInfo.au4WTSR[5] + | prSDIOCtrl->rTxInfo.au4WTSR[6] + | prSDIOCtrl->rTxInfo.au4WTSR[7])) { + prSDIOCtrl->u4WHISR |= WHISR_TX_DONE_INT; + } + + if ((prSDIOCtrl->u4WHISR & BIT(31)) == 0 && + HAL_GET_MAILBOX_READ_CLEAR(prAdapter) == TRUE && + (prSDIOCtrl->u4RcvMailbox0 != 0 + || prSDIOCtrl->u4RcvMailbox1 != 0)) { + prSDIOCtrl->u4WHISR |= BIT(31); + } + + *pu4IntStatus = prSDIOCtrl->u4WHISR; + +} /* end of nicSDIOReadIntStatus() */ +#endif + +#if 0 /*defined(_HIF_PCIE) */ +void nicPCIEReadIntStatus(IN struct ADAPTER *prAdapter, + OUT uint32_t *pu4IntStatus) +{ + uint32_t u4RegValue; + + *pu4IntStatus = 0; + + HAL_MCR_RD(prAdapter, WPDMA_INT_STA, &u4RegValue); + + if (HAL_IS_RX_DONE_INTR(u4RegValue)) + *pu4IntStatus |= WHISR_RX0_DONE_INT; + + if (HAL_IS_TX_DONE_INTR(u4RegValue)) + *pu4IntStatus |= WHISR_TX_DONE_INT; + + /* clear interrupt */ + HAL_MCR_WR(prAdapter, WPDMA_INT_STA, u4RegValue); + +} +#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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicProcessIST(IN struct ADAPTER *prAdapter) +{ + uint32_t u4Status = WLAN_STATUS_SUCCESS; + uint32_t u4IntStatus = 0; + uint32_t i; + + 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; + } + + for (i = 0; i < prAdapter->rWifiVar.u4HifIstLoopCount; + i++) { + + HAL_READ_INT_STATUS(prAdapter, &u4IntStatus); + /* DBGLOG(INIT, TRACE, ("u4IntStatus: 0x%x\n", u4IntStatus)); */ + + if (u4IntStatus == 0) { + if (i == 0) + u4Status = WLAN_STATUS_NOT_INDICATING; + break; + } + + nicProcessIST_impl(prAdapter, u4IntStatus); + + /* Have to TX now. Skip RX polling ASAP */ + if (test_bit(GLUE_FLAG_HIF_TX_CMD_BIT, + &prAdapter->prGlueInfo->ulFlag) + || test_bit(GLUE_FLAG_HIF_TX_BIT, + &prAdapter->prGlueInfo->ulFlag)) { + i *= 2; + } + } + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicProcessIST_impl(IN struct ADAPTER *prAdapter, + IN uint32_t u4IntStatus) +{ + uint32_t u4IntCount = 0; + struct INT_EVENT_MAP *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 (0) { + /* ignore */ + } else if (apfnEventFuncTable[prIntEventMap->u4Event] != + NULL) { + apfnEventFuncTable[ + prIntEventMap->u4Event] (prAdapter); + } else { + DBGLOG(INTR, WARN, + "Empty INTR handler! ISAR bit#: %u, event:%u, func: 0x%p\n", + prIntEventMap->u4Int, + prIntEventMap->u4Event, + apfnEventFuncTable[prIntEventMap->u4Event]); + + /* to trap any NULL interrupt handler */ + ASSERT(0); + } + 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t nicVerifyChipID(IN struct ADAPTER *prAdapter) +{ + return halVerifyChipID(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter) +{ + + ASSERT(prAdapter); + + /* 4 <0> Initial value */ +} + +void nicHifInit(IN struct ADAPTER *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) + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicInitializeAdapter(IN struct ADAPTER *prAdapter) +{ + uint32_t u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + + prAdapter->fgIsIntEnableWithLPOwnSet = FALSE; + prAdapter->fgIsReadRevID = FALSE; + + do { + if (!nicVerifyChipID(prAdapter)) { + u4Status = WLAN_STATUS_FAILURE; + break; + } + /* 4 <1> MCR init */ + nicMCRInit(prAdapter); + + HAL_HIF_INIT(prAdapter); + + /* 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 struct ADAPTER *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 struct ADAPTER + *prAdapter) +{ + if (halIsHifStateSuspend(prAdapter)) + DBGLOG(RX, WARN, "suspend Abnormal\n"); + + prAdapter->prGlueInfo->IsrAbnormalCnt++; + + halProcessAbnormalInterrupt(prAdapter); + glGetRstReason(RST_PROCESS_ABNORMAL_INT); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief . + * + * @param prAdapter Pointer to the Adapter structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicProcessFwOwnBackInterrupt(IN struct ADAPTER + *prAdapter) +{ + +} /* end of nicProcessFwOwnBackInterrupt() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief . + * + * @param prAdapter Pointer to the Adapter structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicProcessSoftwareInterrupt(IN struct ADAPTER + *prAdapter) +{ + if (halIsHifStateSuspend(prAdapter)) + DBGLOG(RX, WARN, "suspend SW INT\n"); + + prAdapter->prGlueInfo->IsrSoftWareCnt++; + halProcessSoftwareInterrupt(prAdapter); +} /* end of nicProcessSoftwareInterrupt() */ + +void nicSetSwIntr(IN struct ADAPTER *prAdapter, + IN uint32_t u4SwIntrBitmap) +{ + /* NOTE: + * SW interrupt in HW bit 16 is mapping to SW bit 0 + * (shift 16bit in HW transparancy) + * SW interrupt valid from b0~b15 + */ + ASSERT((u4SwIntrBitmap & BITS(0, 15)) == 0); + /* DBGLOG(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 + */ +/*----------------------------------------------------------------------------*/ +struct CMD_INFO *nicGetPendingCmdInfo(IN struct ADAPTER + *prAdapter, IN uint8_t ucSeqNum) +{ + struct QUE *prCmdQue; + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue = &rTempCmdQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) 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, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + + if (prCmdInfo->ucCmdSeqNum == ucSeqNum) + break; + + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + + prCmdInfo = NULL; + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + 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 + */ +/*----------------------------------------------------------------------------*/ +struct MSDU_INFO *nicGetPendingTxMsduInfo( + IN struct ADAPTER *prAdapter, IN uint8_t ucWlanIndex, + IN uint8_t ucPID) +{ + struct QUE *prTxingQue; + struct QUE rTempQue; + struct QUE *prTempQue = &rTempQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct MSDU_INFO *prMsduInfo = (struct MSDU_INFO *) 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, + struct QUE_ENTRY *); + while (prQueueEntry) { + prMsduInfo = (struct MSDU_INFO *) prQueueEntry; + + if ((prMsduInfo->ucPID == ucPID) + && (prMsduInfo->ucWlanIndex == ucWlanIndex)) + break; + + QUEUE_INSERT_TAIL(prTxingQue, prQueueEntry); + + prMsduInfo = NULL; + + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, + struct QUE_ENTRY *); + } + QUEUE_CONCATENATE_QUEUES(prTxingQue, prTempQue); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + if (prMsduInfo) { + DBGLOG(TX, TRACE, + "Get Msdu WIDX:PID[%u:%u] SEQ[%u] from Pending Q\n", + prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, + prMsduInfo->ucTxSeqNum); + } else { + DBGLOG(TX, WARN, + "Cannot get Target Msdu WIDX:PID[%u:%u] from Pending Q\n", + ucWlanIndex, ucPID); + } + + return prMsduInfo; +} + +void nicFreePendingTxMsduInfo(IN struct ADAPTER *prAdapter, + IN uint8_t ucIndex, IN enum ENUM_REMOVE_BY_MSDU_TPYE ucFreeType) +{ + struct QUE *prTxingQue; + struct QUE rTempQue; + struct QUE *prTempQue = &rTempQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct MSDU_INFO *prMsduInfoListHead = (struct MSDU_INFO *) + NULL; + struct MSDU_INFO *prMsduInfoListTail = (struct MSDU_INFO *) + NULL; + struct MSDU_INFO *prMsduInfo = (struct MSDU_INFO *) NULL; + uint8_t ucRemoveByIndex; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + if (ucFreeType >= ENUM_REMOVE_BY_MSDU_TPYE_NUM) { + DBGLOG(TX, WARN, "Wrong remove type: %d\n", ucFreeType); + return; + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + prTxingQue = &(prAdapter->rTxCtrl.rTxMgmtTxingQueue); + QUEUE_MOVE_ALL(prTempQue, prTxingQue); + + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, + struct QUE_ENTRY *); + + while (prQueueEntry) { + prMsduInfo = (struct MSDU_INFO *) prQueueEntry; + + switch (ucFreeType) { + case MSDU_REMOVE_BY_WLAN_INDEX: + ucRemoveByIndex = prMsduInfo->ucWlanIndex; + break; + case MSDU_REMOVE_BY_BSS_INDEX: + default: + ucRemoveByIndex = prMsduInfo->ucBssIndex; + break; + } + if (ucRemoveByIndex == ucIndex) { + DBGLOG(TX, TRACE, + "%s: Get Msdu WIDX:PID[%u:%u] SEQ[%u] from Pending Q\n", + __func__, prMsduInfo->ucWlanIndex, + prMsduInfo->ucPID, + prMsduInfo->ucTxSeqNum); + + 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, + struct QUE_ENTRY *); + } + QUEUE_CONCATENATE_QUEUES(prTxingQue, prTempQue); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + /* free */ + if (prMsduInfoListHead) { + nicTxFreeMsduInfoPacket(prAdapter, prMsduInfoListHead); + nicTxReturnMsduInfo(prAdapter, prMsduInfoListHead); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This procedure is used to retrieve a CMD sequence number atomically + * + * @param prAdapter Pointer of ADAPTER_T + * + * @retval - UINT_8 + */ +/*----------------------------------------------------------------------------*/ +uint8_t nicIncreaseCmdSeqNum(IN struct ADAPTER *prAdapter) +{ + uint8_t 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 + */ +/*----------------------------------------------------------------------------*/ +uint8_t nicIncreaseTxSeqNum(IN struct ADAPTER *prAdapter) +{ + uint8_t ucRetval; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_SEQ_NUM); + + ucRetval = prAdapter->ucTxSeqNum; + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +nicMediaStateChange(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct EVENT_CONNECTION_STATUS *prConnectionStatus) +{ + struct GLUE_INFO *prGlueInfo; + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prAisBssInfo; + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = prAdapter->prAisBssInfo; + + switch (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType) { + case NETWORK_TYPE_AIS: + if (prConnectionStatus->ucMediaStatus == + PARAM_MEDIA_STATE_DISCONNECTED) { /* disconnected */ + if (kalGetMediaStateIndicated(prGlueInfo) != + PARAM_MEDIA_STATE_DISCONNECTED || + prAisFsmInfo->eCurrentState == AIS_STATE_JOIN) { + + 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 ENUM_PARAM_OP_MODE) + 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: + break; +#endif + +#if CFG_ENABLE_WIFI_DIRECT + case NETWORK_TYPE_P2P: + break; +#endif + default: + ASSERT(0); + } + + return WLAN_STATUS_SUCCESS; +} /* nicMediaStateChange */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This utility function is used to generate a join failure event to OS + * + * @param + * + * @retval + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicMediaJoinFailure(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN uint32_t rStatus) +{ + struct GLUE_INFO *prGlueInfo; + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + + switch (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType) { + case NETWORK_TYPE_AIS: + kalIndicateStatusAndComplete(prGlueInfo, rStatus, NULL, 0); + + break; + + case NETWORK_TYPE_BOW: + case NETWORK_TYPE_P2P: + default: + break; + } + + return WLAN_STATUS_SUCCESS; +} /* end of nicMediaJoinFailure() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicChannelNum2Freq(uint32_t u4ChannelNum) +{ + uint32_t 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 <= 181) + || (u4ChannelNum == 16)) + u4ChannelInMHz = 5000 + u4ChannelNum * 5; + else if (u4ChannelNum >= 182 && u4ChannelNum <= 196) + u4ChannelInMHz = 4000 + u4ChannelNum * 5; + else if (u4ChannelNum == 201) + u4ChannelInMHz = 2730; + else if (u4ChannelNum == 202) + u4ChannelInMHz = 2498; + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicFreq2ChannelNum(uint32_t 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 5310000: + return 62; + case 5320000: + return 64; + case 5500000: + return 100; + case 5510000: + return 102; + case 5520000: + return 104; + case 5530000: + return 106; + case 5540000: + return 108; + case 5550000: + return 110; + case 5560000: + return 112; + case 5570000: + return 114; + case 5580000: + return 116; + case 5590000: + return 118; + case 5600000: + return 120; + case 5610000: + return 122; + case 5620000: + return 124; + case 5630000: + return 126; + case 5640000: + return 128; + case 5660000: + return 132; + case 5670000: + return 134; + case 5680000: + return 136; + case 5690000: + return 138; + case 5700000: + return 140; + case 5710000: + return 142; + case 5720000: + return 144; + case 5745000: + return 149; + case 5755000: + return 151; + case 5765000: + return 153; + case 5775000: + return 155; + case 5785000: + return 157; + case 5795000: + return 159; + case 5805000: + return 161; + case 5825000: + return 165; + case 5845000: + return 169; + case 5865000: + return 173; + default: + DBGLOG(BSS, INFO, "Return Invalid Channelnum = 0.\n"); + return 0; + } +} + +uint8_t nicGetVhtS1(uint8_t ucPrimaryChannel, + uint8_t ucBandwidth) +{ + /* find S1 (central channel 42, 58, 106, 122, and 155) */ + + if ((ucBandwidth == VHT_OP_CHANNEL_WIDTH_80) + || (ucBandwidth == VHT_OP_CHANNEL_WIDTH_80P80)) { + + if (ucPrimaryChannel >= 36 && ucPrimaryChannel <= 48) + return 42; + else if (ucPrimaryChannel >= 52 && ucPrimaryChannel <= 64) + return 58; + else if (ucPrimaryChannel >= 100 && ucPrimaryChannel <= 112) + return 106; + else if (ucPrimaryChannel >= 116 && ucPrimaryChannel <= 128) + return 122; + else if (ucPrimaryChannel >= 132 && ucPrimaryChannel <= 144) + return 138; + else if (ucPrimaryChannel >= 149 && ucPrimaryChannel <= 161) + return 155; + + } else if (ucBandwidth == VHT_OP_CHANNEL_WIDTH_160) { + + if (ucPrimaryChannel >= 36 && ucPrimaryChannel <= 64) + return 50; + else if (ucPrimaryChannel >= 100 && ucPrimaryChannel <= 128) + return 114; + + } else { + + return 0; + } + + 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 - + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicActivateNetwork(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + struct CMD_BSS_ACTIVATE_CTRL rCmdActivateCtrl; + struct BSS_INFO *prBssInfo; + /* const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; */ + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + prBssInfo->fg40mBwAllowed = FALSE; + prBssInfo->fgAssoc40mBwAllowed = FALSE; + + rCmdActivateCtrl.ucBssIndex = ucBssIndex; + rCmdActivateCtrl.ucActive = 1; + rCmdActivateCtrl.ucNetworkType = (uint8_t) + prBssInfo->eNetworkType; + rCmdActivateCtrl.ucOwnMacAddrIndex = + prBssInfo->ucOwnMacIndex; + COPY_MAC_ADDR(rCmdActivateCtrl.aucBssMacAddr, + prBssInfo->aucOwnMacAddr); + + prBssInfo->ucBMCWlanIndex = + secPrivacySeekForBcEntry(prAdapter, prBssInfo->ucBssIndex, + prBssInfo->aucOwnMacAddr, + STA_REC_INDEX_NOT_FOUND, + CIPHER_SUITE_NONE, 0xFF); + rCmdActivateCtrl.ucBMCWlanIndex = prBssInfo->ucBMCWlanIndex; + + kalMemZero(&rCmdActivateCtrl.ucReserved, + sizeof(rCmdActivateCtrl.ucReserved)); + +#if 1 /* DBG */ + DBGLOG(RSN, INFO, + "[wlan index]=%d OwnMac=" MACSTR " BSSID=" MACSTR + " BMCIndex = %d NetType=%d\n", + ucBssIndex, + MAC2STR(prBssInfo->aucOwnMacAddr), + MAC2STR(prBssInfo->aucBSSID), + prBssInfo->ucBMCWlanIndex, prBssInfo->eNetworkType); +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_BSS_ACTIVATE_CTRL, + TRUE, + FALSE, + FALSE, + NULL, NULL, + sizeof(struct CMD_BSS_ACTIVATE_CTRL), + (uint8_t *)&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 - + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicDeactivateNetwork(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + uint32_t u4Status; + struct CMD_BSS_ACTIVATE_CTRL rCmdActivateCtrl; + struct BSS_INFO *prBssInfo; + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + kalMemZero(&rCmdActivateCtrl, + sizeof(struct CMD_BSS_ACTIVATE_CTRL)); + + rCmdActivateCtrl.ucBssIndex = ucBssIndex; + rCmdActivateCtrl.ucActive = 0; + rCmdActivateCtrl.ucNetworkType = + (uint8_t)prBssInfo->eNetworkType; + rCmdActivateCtrl.ucOwnMacAddrIndex = + prBssInfo->ucOwnMacIndex; + rCmdActivateCtrl.ucBMCWlanIndex = + prBssInfo->ucBMCWlanIndex; + + DBGLOG(RSN, INFO, + "[wlan index]=%d OwnMac=" MACSTR " BSSID=" MACSTR + " BMCIndex = %d NetType=%d\n", + ucBssIndex, + MAC2STR(prBssInfo->aucOwnMacAddr), + MAC2STR(prBssInfo->aucBSSID), + prBssInfo->ucBMCWlanIndex, prBssInfo->eNetworkType); + + u4Status = wlanSendSetQueryCmd(prAdapter, + CMD_ID_BSS_ACTIVATE_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_BSS_ACTIVATE_CTRL), + (uint8_t *)&rCmdActivateCtrl, NULL, 0); + + secRemoveBssBcEntry(prAdapter, prBssInfo, FALSE); + + /* StaRec in BSS client list also need to be removed from list */ + bssInitializeClientList(prAdapter, prBssInfo); + + /* free all correlated station records */ + cnmStaFreeAllStaByNetwork(prAdapter, ucBssIndex, + STA_REC_EXCLUDE_NONE); + if (HAL_IS_TX_DIRECT(prAdapter)) + nicTxDirectClearBssAbsentQ(prAdapter, ucBssIndex); + else + qmFreeAllByBssIdx(prAdapter, ucBssIndex); + nicFreePendingTxMsduInfo(prAdapter, ucBssIndex, + MSDU_REMOVE_BY_BSS_INDEX); + kalClearSecurityFramesByBssIdx(prAdapter->prGlueInfo, + ucBssIndex); + cnmFreeWmmIndex(prAdapter, prBssInfo); + + 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 + * ucBssIndex Index of BSS-INFO + * + * @retval - + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicUpdateBss(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + uint32_t u4Status = WLAN_STATUS_NOT_ACCEPTED; + struct BSS_INFO *prBssInfo; + struct CMD_SET_BSS_INFO rCmdSetBssInfo; + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + + kalMemZero(&rCmdSetBssInfo, + sizeof(struct CMD_SET_BSS_INFO)); + + rCmdSetBssInfo.ucBssIndex = ucBssIndex; + rCmdSetBssInfo.ucConnectionState = (uint8_t) + prBssInfo->eConnectionState; + rCmdSetBssInfo.ucCurrentOPMode = (uint8_t) + prBssInfo->eCurrentOPMode; + rCmdSetBssInfo.ucSSIDLen = (uint8_t) prBssInfo->ucSSIDLen; + kalMemCopy(rCmdSetBssInfo.aucSSID, prBssInfo->aucSSID, + prBssInfo->ucSSIDLen); + COPY_MAC_ADDR(rCmdSetBssInfo.aucBSSID, prBssInfo->aucBSSID); + rCmdSetBssInfo.ucIsQBSS = (uint8_t) prBssInfo->fgIsQBSS; + rCmdSetBssInfo.ucNonHTBasicPhyType = + prBssInfo->ucNonHTBasicPhyType; + rCmdSetBssInfo.u2OperationalRateSet = + prBssInfo->u2OperationalRateSet; + rCmdSetBssInfo.u2BSSBasicRateSet = + prBssInfo->u2BSSBasicRateSet; + rCmdSetBssInfo.u2HwDefaultFixedRateCode = + prBssInfo->u2HwDefaultFixedRateCode; + rCmdSetBssInfo.ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + rCmdSetBssInfo.u4PrivateData = prBssInfo->u4PrivateData; +#if CFG_SUPPORT_DBDC + /* + *To do: In fact, this is not used anymore and could be removed now. + *But command structure change has driver and firmware dependency. + *So currently using ENUM_BAND_AUTO is a temporary solution. + */ + rCmdSetBssInfo.ucDBDCBand = ENUM_BAND_AUTO; +#endif + rCmdSetBssInfo.ucWmmSet = prBssInfo->ucWmmQueSet; + rCmdSetBssInfo.ucNss = prBssInfo->ucNss; + + if (prBssInfo->fgBcDefaultKeyExist) { + if (prBssInfo->wepkeyWlanIdx < + prAdapter->ucTxDefaultWlanIndex) + rCmdSetBssInfo.ucBMCWlanIndex = + prBssInfo->wepkeyWlanIdx; + else if (prBssInfo->ucBMCWlanIndexSUsed[ + prBssInfo->ucBcDefaultKeyIdx]) + rCmdSetBssInfo.ucBMCWlanIndex = + prBssInfo->ucBMCWlanIndexS[ + prBssInfo->ucBcDefaultKeyIdx]; + } else + rCmdSetBssInfo.ucBMCWlanIndex = prBssInfo->ucBMCWlanIndex; + + DBGLOG(RSN, TRACE, "Update BSS BMC WlanIdx %u\n", + rCmdSetBssInfo.ucBMCWlanIndex); + +#if CFG_ENABLE_WIFI_DIRECT + rCmdSetBssInfo.ucHiddenSsidMode = + prBssInfo->eHiddenSsidType; +#endif + rlmFillSyncCmdParam(&rCmdSetBssInfo.rBssRlmParam, + prBssInfo); + + rCmdSetBssInfo.ucWapiMode = (uint8_t) FALSE; + + if ((prAdapter->prAisBssInfo != NULL) && + (rCmdSetBssInfo.ucBssIndex == + prAdapter->prAisBssInfo->ucBssIndex)) { + struct CONNECTION_SETTINGS *prConnSettings = & + (prAdapter->rWifiVar.rConnSettings); +#if CFG_SUPPORT_PASSPOINT + /* mapping OSEN to WPA2, + * due to firmware no need to know current is OSEN + */ + if (prConnSettings->eAuthMode == AUTH_MODE_WPA_OSEN) + rCmdSetBssInfo.ucAuthMode = AUTH_MODE_WPA2; + else +#endif + rCmdSetBssInfo.ucAuthMode = (uint8_t) prConnSettings->eAuthMode; + rCmdSetBssInfo.ucEncStatus = (uint8_t) + prConnSettings->eEncStatus; + rCmdSetBssInfo.ucWapiMode = (uint8_t) + prConnSettings->fgWapiMode; + } +#if CFG_ENABLE_BT_OVER_WIFI + else if (IS_BSS_BOW(prBssInfo)) { + rCmdSetBssInfo.ucAuthMode = (uint8_t) AUTH_MODE_WPA2_PSK; + rCmdSetBssInfo.ucEncStatus = (uint8_t) + ENUM_ENCRYPTION3_KEY_ABSENT; + } +#endif + else { +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { +#if CFG_SUPPORT_SUITB + if (kalP2PGetGcmp256Cipher(prAdapter->prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData)) { + rCmdSetBssInfo.ucAuthMode = + (uint8_t) AUTH_MODE_WPA2_PSK; + rCmdSetBssInfo.ucEncStatus = + (uint8_t) ENUM_ENCRYPTION4_ENABLED; + } else +#endif + if (kalP2PGetCcmpCipher(prAdapter->prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData)) { + rCmdSetBssInfo.ucAuthMode = + (uint8_t) AUTH_MODE_WPA2_PSK; + rCmdSetBssInfo.ucEncStatus = + (uint8_t) + ENUM_ENCRYPTION3_ENABLED; + } else if (kalP2PGetTkipCipher(prAdapter->prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData)) { + rCmdSetBssInfo.ucAuthMode = + (uint8_t) AUTH_MODE_WPA_PSK; + rCmdSetBssInfo.ucEncStatus = + (uint8_t) ENUM_ENCRYPTION2_ENABLED; + } else if (kalP2PGetWepCipher(prAdapter->prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData)) { + rCmdSetBssInfo.ucAuthMode = + (uint8_t) AUTH_MODE_OPEN; + rCmdSetBssInfo.ucEncStatus = + (uint8_t) ENUM_ENCRYPTION1_ENABLED; + } else { + rCmdSetBssInfo.ucAuthMode = + (uint8_t) AUTH_MODE_OPEN; + rCmdSetBssInfo.ucEncStatus = + (uint8_t) ENUM_ENCRYPTION_DISABLED; + } + /* Need the probe response to detect the PBC overlap */ + rCmdSetBssInfo.ucIsApMode = + p2pFuncIsAPMode( + prAdapter->rWifiVar.prP2PConnSettings[ + prBssInfo->u4PrivateData]); + + } +#else + rCmdSetBssInfo.ucAuthMode = (uint8_t) AUTH_MODE_WPA2_PSK; + rCmdSetBssInfo.ucEncStatus = (uint8_t) + ENUM_ENCRYPTION3_KEY_ABSENT; +#endif + } + /* Firmware didn't define AUTH_MODE_NON_RSN_FT, so AUTH_MODE_OPEN is + ** zero in firmware, + ** but it is 1 in driver. so we need to minus 1 for all authmode except + ** AUTH_MODE_NON_RSN_FT, + ** because AUTH_MODE_NON_RSN_FT will be same as AUTH_MODE_OPEN in + ** firmware + **/ + if (rCmdSetBssInfo.ucAuthMode != AUTH_MODE_NON_RSN_FT) + rCmdSetBssInfo.ucAuthMode -= 1; + + rCmdSetBssInfo.ucDisconnectDetectTh = 0; + + if ((prAdapter->prAisBssInfo != NULL) && + (ucBssIndex == prAdapter->prAisBssInfo->ucBssIndex) && + (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) && + (prBssInfo->prStaRecOfAP != NULL)) { + rCmdSetBssInfo.ucStaRecIdxOfAP = + prBssInfo->prStaRecOfAP->ucIndex; + + cnmAisInfraConnectNotify(prAdapter); + } +#if CFG_ENABLE_WIFI_DIRECT + else if ((prAdapter->fgIsP2PRegistered) && + (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) && + (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) + && (prBssInfo->prStaRecOfAP != NULL)) { + rCmdSetBssInfo.ucStaRecIdxOfAP = + prBssInfo->prStaRecOfAP->ucIndex; + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI +/* disabled for BOW to finish ucBssIndex migration */ + else if (prBssInfo->eNetworkType == NETWORK_TYPE_BOW && + prBssInfo->eCurrentOPMode == OP_MODE_BOW + && prBssInfo->prStaRecOfAP != NULL) { + rCmdSetBssInfo.ucStaRecIdxOfAP = + prBssInfo->prStaRecOfAP->ucIndex; + } +#endif + else + rCmdSetBssInfo.ucStaRecIdxOfAP = STA_REC_INDEX_NOT_FOUND; + + DBGLOG(BSS, INFO, + "Update Bss[%u] ConnState[%u] OPmode[%u] BSSID[" MACSTR + "] AuthMode[%u] EncStatus[%u]\n", ucBssIndex, + prBssInfo->eConnectionState, + prBssInfo->eCurrentOPMode, MAC2STR(prBssInfo->aucBSSID), + rCmdSetBssInfo.ucAuthMode, + rCmdSetBssInfo.ucEncStatus); + + u4Status = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_BSS_INFO, + TRUE, + FALSE, + FALSE, + NULL, NULL, + sizeof(struct CMD_SET_BSS_INFO), + (uint8_t *)&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 */ + bssInitializeClientList(prAdapter, prBssInfo); + +#if DBG + DBGLOG(BSS, TRACE, "nicUpdateBss for disconnect state\n"); +#endif + /* free all correlated station records */ + cnmStaFreeAllStaByNetwork(prAdapter, ucBssIndex, + STA_REC_EXCLUDE_NONE); + if (HAL_IS_TX_DIRECT(prAdapter)) + nicTxDirectClearBssAbsentQ(prAdapter, ucBssIndex); + else + qmFreeAllByBssIdx(prAdapter, ucBssIndex); + kalClearSecurityFramesByBssIdx(prAdapter->prGlueInfo, + ucBssIndex); +#if CFG_ENABLE_GTK_FRAME_FILTER + if (prBssInfo->prIpV4NetAddrList) + FREE_IPV4_NETWORK_ADDR_LIST( + prBssInfo->prIpV4NetAddrList); +#endif +#if CFG_SUPPORT_DBDC + cnmDbdcDisableDecision(prAdapter, ucBssIndex); +#endif + } + + return u4Status; +} + +/* BSS-INFO Indication (PM) */ +/*----------------------------------------------------------------------------*/ +/*! + * @brief This utility function is used to indicate PM that + * a BSS has been created. (for AdHoc / P2P-GO) + * + * @param prAdapter Pointer of ADAPTER_T + * ucBssIndex Index of BSS-INFO + * + * @retval - + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicPmIndicateBssCreated(IN struct ADAPTER + *prAdapter, IN uint8_t ucBssIndex) +{ + struct BSS_INFO *prBssInfo; + struct CMD_INDICATE_PM_BSS_CREATED rCmdIndicatePmBssCreated; + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + rCmdIndicatePmBssCreated.ucBssIndex = ucBssIndex; + 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(struct CMD_INDICATE_PM_BSS_CREATED), + (uint8_t *)&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 - + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicPmIndicateBssConnected(IN struct ADAPTER + *prAdapter, IN uint8_t ucBssIndex) +{ + struct BSS_INFO *prBssInfo; + struct CMD_INDICATE_PM_BSS_CONNECTED + rCmdIndicatePmBssConnected; + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + rCmdIndicatePmBssConnected.ucBssIndex = ucBssIndex; + 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; + + /* rCmdIndicatePmBssConnected.ucBmpDeliveryAC, */ + /* rCmdIndicatePmBssConnected.ucBmpTriggerAC); */ + + if ((GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType == NETWORK_TYPE_AIS) +#if CFG_ENABLE_WIFI_DIRECT + || ((GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType == NETWORK_TYPE_P2P) + && (prAdapter->fgIsP2PRegistered)) +#endif + ) { + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE && + prBssInfo->prStaRecOfAP) { + uint8_t ucUapsd = wmmCalculateUapsdSetting(prAdapter); + + /* should sync Tspec uapsd settings */ + rCmdIndicatePmBssConnected.ucBmpDeliveryAC = + (ucUapsd >> 4) & 0xf; + rCmdIndicatePmBssConnected.ucBmpTriggerAC = + ucUapsd & 0xf; + rCmdIndicatePmBssConnected.fgIsUapsdConnection = + (uint8_t) 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(struct CMD_INDICATE_PM_BSS_CONNECTED), + (uint8_t *)&rCmdIndicatePmBssConnected, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This utility function is used to indicate PM that + * a BSS has been disconnected + * + * @param prAdapter Pointer of ADAPTER_T + * ucBssIndex Index of BSS-INFO + * + * @retval - + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicPmIndicateBssAbort(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + struct CMD_INDICATE_PM_BSS_ABORT rCmdIndicatePmBssAbort; + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + rCmdIndicatePmBssAbort.ucBssIndex = ucBssIndex; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_INDICATE_PM_BSS_ABORT, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_INDICATE_PM_BSS_ABORT), + (uint8_t *)&rCmdIndicatePmBssAbort, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This utility function is used to set power save bit map + * + * + * @param prAdapter Pointer of ADAPTER_T + * ucBssIndex Index of BSS-INFO + * ucSet enter power save or not(1 PS, 0 not PS) + * ucCaller index of bit map for caller + * @retval - + */ +/*----------------------------------------------------------------------------*/ +void +nicPowerSaveInfoMap(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN enum PARAM_POWER_MODE ePowerMode, + IN enum POWER_SAVE_CALLER ucCaller) +{ + uint32_t u4Flag; + + /* max caller is 24 */ + if (ucCaller >= PS_CALLER_MAX_NUM) + ASSERT(0); + + u4Flag = prAdapter->rWlanInfo.u4PowerSaveFlag[ucBssIndex]; + + /* set send command flag */ + if (ePowerMode != Param_PowerModeCAM) { + u4Flag &= ~BIT(ucCaller); + if (u4Flag == 0) + u4Flag |= PS_SYNC_WITH_FW; + } else { + if (u4Flag == 0) + u4Flag |= PS_SYNC_WITH_FW; + u4Flag |= BIT(ucCaller); + } + + DBGLOG(NIC, INFO, + "Flag=0x%04x, Caller=%d, PM=%d, PSFlag[%d]=0x%04x\n", + u4Flag, ucCaller, ePowerMode, ucBssIndex, + prAdapter->rWlanInfo.u4PowerSaveFlag[ucBssIndex]); + + prAdapter->rWlanInfo.u4PowerSaveFlag[ucBssIndex] = u4Flag; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This utility function is used to set power save profile + * + * + * @param prAdapter Pointer of ADAPTER_T + * ucBssIndex Index of BSS-INFO + * ucSet enter power save or not(1 PS, 0 not PS) + * fgEnCmdEvent Enable the functions when command done and timeout + * ucCaller index of bit map for caller + * + * @retval WLAN_STATUS_SUCCESS + * @retval WLAN_STATUS_PENDING + * @retval WLAN_STATUS_FAILURE + * @retval WLAN_STATUS_NOT_SUPPORTED + */ +/*----------------------------------------------------------------------------*/ +uint32_t +nicConfigPowerSaveProfile(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN enum PARAM_POWER_MODE ePwrMode, + IN u_int8_t fgEnCmdEvent, + IN enum POWER_SAVE_CALLER ucCaller) +{ + DEBUGFUNC("nicConfigPowerSaveProfile"); + DBGLOG(INIT, TRACE, + "ucBssIndex:%d, ePwrMode:%d, fgEnCmdEvent:%d\n", + ucBssIndex, ePwrMode, fgEnCmdEvent); + + ASSERT(prAdapter); + + if (ucBssIndex >= prAdapter->ucHwBssIdNum) { + ASSERT(0); + return WLAN_STATUS_NOT_SUPPORTED; + } + + nicPowerSaveInfoMap(prAdapter, ucBssIndex, ePwrMode, ucCaller); + + prAdapter->rWlanInfo.arPowerSaveMode[ucBssIndex].ucBssIndex + = ucBssIndex; + prAdapter->rWlanInfo.arPowerSaveMode[ucBssIndex].ucPsProfile + = (uint8_t) ePwrMode; + + if (PS_SYNC_WITH_FW + & prAdapter->rWlanInfo.u4PowerSaveFlag[ucBssIndex]) { + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + prAdapter->rWlanInfo.u4PowerSaveFlag[ucBssIndex] + &= ~PS_SYNC_WITH_FW; + + DBGLOG(NIC, TRACE, + "SYNC_WITH_FW u4PowerSaveFlag[%d]=0x%04x\n", + ucBssIndex, + prAdapter->rWlanInfo.u4PowerSaveFlag[ucBssIndex]); + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_POWER_SAVE_MODE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + fgEnCmdEvent, /* fgIsOid */ + + /* pfCmdDoneHandler */ + (fgEnCmdEvent ? nicCmdEventSetCommon : NULL), + + /* pfCmdTimeoutHandler */ + (fgEnCmdEvent ? nicOidCmdTimeoutCommon : NULL), + + /* u4SetQueryInfoLen */ + sizeof(struct CMD_PS_PROFILE), + + /* pucInfoBuffer */ + (uint8_t *) &(prAdapter->rWlanInfo + .arPowerSaveMode[ucBssIndex]), + + /* pvSetQueryBuffer */ + NULL, + + /* u4SetQueryBufferLen */ + 0 + ); + + if (fgEnCmdEvent) + return rWlanStatus; + } + return WLAN_STATUS_SUCCESS; +} /* end of nicConfigPowerSaveProfile */ + +uint32_t +nicConfigProcSetCamCfgWrite(IN struct ADAPTER *prAdapter, + IN u_int8_t enabled) +{ + enum PARAM_POWER_MODE ePowerMode; + uint8_t ucBssIndex; + struct CMD_PS_PROFILE rPowerSaveMode; + + if ((!prAdapter) || (!prAdapter->prAisBssInfo)) + return WLAN_STATUS_FAILURE; + + ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + if (ucBssIndex >= BSS_DEFAULT_NUM) + return WLAN_STATUS_FAILURE; + rPowerSaveMode.ucBssIndex = ucBssIndex; + + if (enabled) { + prAdapter->rWlanInfo.fgEnSpecPwrMgt = TRUE; + ePowerMode = Param_PowerModeCAM; + rPowerSaveMode.ucPsProfile = (uint8_t) ePowerMode; + DBGLOG(INIT, INFO, "Enable CAM BssIndex:%d, PowerMode:%d\n", + ucBssIndex, rPowerSaveMode.ucPsProfile); + } else { + prAdapter->rWlanInfo.fgEnSpecPwrMgt = FALSE; + rPowerSaveMode.ucPsProfile = + prAdapter->rWlanInfo.arPowerSaveMode[ucBssIndex]. + ucPsProfile; + DBGLOG(INIT, INFO, + "Disable CAM BssIndex:%d, PowerMode:%d\n", + ucBssIndex, rPowerSaveMode.ucPsProfile); + } + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_POWER_SAVE_MODE, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_PS_PROFILE), + (uint8_t *) &rPowerSaveMode, + NULL, 0); +} + +uint32_t +nicConfigPowerSaveWowProfile(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN enum PARAM_POWER_MODE ePwrMode, + IN u_int8_t fgEnCmdEvent, + IN u_int8_t fgSuspend) +{ + struct WLAN_INFO *prWlanInfo; + uint8_t ucCurrBssIndex; + enum PARAM_POWER_MODE eCurrPwrMode; + uint32_t ret; + + prWlanInfo = &prAdapter->rWlanInfo; + + if (fgSuspend) { + + /* store current to wow profile */ + prWlanInfo->arPowerSaveWowMode[ucBssIndex].ucBssIndex = + prWlanInfo->arPowerSaveMode[ucBssIndex].ucBssIndex; + + prWlanInfo->arPowerSaveWowMode[ucBssIndex].ucPsProfile = + prWlanInfo->arPowerSaveMode[ucBssIndex].ucPsProfile; + + /* confgiure suspend power mode profile */ + ret = nicConfigPowerSaveProfile(prAdapter, ucBssIndex, + ePwrMode, fgEnCmdEvent, PS_CALLER_COMMON); + + } else { + /* if resume, restore power save profile */ + ucCurrBssIndex = + prWlanInfo->arPowerSaveWowMode[ucBssIndex].ucBssIndex; + + eCurrPwrMode = + prWlanInfo->arPowerSaveWowMode[ucBssIndex].ucPsProfile; + + /* confgiure resume power mode profile */ + ret = nicConfigPowerSaveProfile(prAdapter, ucCurrBssIndex, + eCurrPwrMode, fgEnCmdEvent, PS_CALLER_COMMON); + + DBGLOG(PF, INFO, "Resume wow power mode idx:%d, mode:%d\n", + ucCurrBssIndex, eCurrPwrMode); + } + + return ret; +} + +uint32_t nicEnterCtiaMode(IN struct ADAPTER *prAdapter, + u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent) +{ + struct CMD_SW_DBG_CTRL rCmdSwCtrl; + /* CMD_ACCESS_REG rCmdAccessReg; */ + uint32_t rWlanStatus; + + DEBUGFUNC("nicEnterCtiaMode"); + DBGLOG(INIT, TRACE, "nicEnterCtiaMode: %d\n", fgEnterCtia); + + ASSERT(prAdapter); + + rWlanStatus = WLAN_STATUS_SUCCESS; + + if (fgEnterCtia) { + /* 1. Disable On-Lin Scan */ + prAdapter->fgEnOnlineScan = FALSE; + + /* 2. Disable FIFO FULL no ack */ + /* 3. Disable Roaming */ + /* 4. Disalbe auto tx power */ + rCmdSwCtrl.u4Id = 0xa0100003; + rCmdSwCtrl.u4Data = 0x0; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, NULL, NULL, + sizeof(struct CMD_SW_DBG_CTRL), + (uint8_t *)&rCmdSwCtrl, NULL, 0); + + /* 2. Keep at CAM mode */ + { + enum PARAM_POWER_MODE ePowerMode; + + prAdapter->u4CtiaPowerMode = 0; + prAdapter->fgEnCtiaPowerMode = TRUE; + + ePowerMode = Param_PowerModeCAM; + rWlanStatus = nicConfigPowerSaveProfile(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, + ePowerMode, fgEnCmdEvent, PS_CALLER_CTIA); + } + + /* 5. Disable Beacon Timeout Detection */ + prAdapter->fgDisBcnLostDetection = TRUE; + } else { + /* 1. Enaable On-Lin Scan */ + prAdapter->fgEnOnlineScan = TRUE; + + /* 2. Enable FIFO FULL no ack */ + /* 3. Enable Roaming */ + /* 4. Enable auto tx power */ + /* */ + + rCmdSwCtrl.u4Id = 0xa0100003; + rCmdSwCtrl.u4Data = 0x1; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, NULL, NULL, + sizeof(struct CMD_SW_DBG_CTRL), + (uint8_t *)&rCmdSwCtrl, NULL, 0); + + /* 2. Keep at Fast PS */ + { + enum PARAM_POWER_MODE ePowerMode; + + prAdapter->u4CtiaPowerMode = 2; + prAdapter->fgEnCtiaPowerMode = TRUE; + + ePowerMode = Param_PowerModeFast_PSP; + rWlanStatus = nicConfigPowerSaveProfile(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, + ePowerMode, fgEnCmdEvent, PS_CALLER_CTIA); + } + + /* 5. Enable Beacon Timeout Detection */ + prAdapter->fgDisBcnLostDetection = FALSE; + + } + + return rWlanStatus; +} /* end of nicEnterCtiaMode() */ + +uint32_t nicEnterCtiaModeOfScan(IN struct ADAPTER + *prAdapter, u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent) +{ + uint32_t rWlanStatus; + + ASSERT(prAdapter); + DBGLOG(INIT, INFO, "nicEnterCtiaModeOfScan: %d\n", + fgEnterCtia); + + rWlanStatus = WLAN_STATUS_SUCCESS; + + if (fgEnterCtia) { + /* Disable On-Line Scan */ + prAdapter->fgEnOnlineScan = FALSE; + } else { + /* Enable On-Line Scan */ + prAdapter->fgEnOnlineScan = TRUE; + } + + return rWlanStatus; +} + +uint32_t nicEnterCtiaModeOfRoaming(IN struct ADAPTER + *prAdapter, u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent) +{ + struct CMD_SW_DBG_CTRL rCmdSwCtrl; + uint32_t rWlanStatus; + + ASSERT(prAdapter); + DBGLOG(INIT, INFO, "nicEnterCtiaModeOfRoaming: %d\n", + fgEnterCtia); + + rWlanStatus = WLAN_STATUS_SUCCESS; + + if (fgEnterCtia) { + /* Disable Roaming */ + rCmdSwCtrl.u4Id = 0x55660000; + rCmdSwCtrl.u4Data = 0x0; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, NULL, NULL, + sizeof(struct CMD_SW_DBG_CTRL), + (uint8_t *) &rCmdSwCtrl, NULL, 0); + } else { + /* Enable Roaming */ + rCmdSwCtrl.u4Id = 0x55660000; + rCmdSwCtrl.u4Data = 0x1; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, NULL, NULL, + sizeof(struct CMD_SW_DBG_CTRL), + (uint8_t *) &rCmdSwCtrl, NULL, 0); + } + + return rWlanStatus; +} + +uint32_t nicEnterCtiaModeOfCAM(IN struct ADAPTER *prAdapter, + u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent) +{ + uint32_t rWlanStatus; + + ASSERT(prAdapter); + DBGLOG(INIT, INFO, "nicEnterCtiaModeOfCAM: %d\n", + fgEnterCtia); + + rWlanStatus = WLAN_STATUS_SUCCESS; + + if (fgEnterCtia) { + /* Keep at CAM mode */ + { + enum PARAM_POWER_MODE ePowerMode; + + prAdapter->u4CtiaPowerMode = 0; + prAdapter->fgEnCtiaPowerMode = TRUE; + + ePowerMode = Param_PowerModeCAM; + rWlanStatus = nicConfigPowerSaveProfile(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, + ePowerMode, fgEnCmdEvent, PS_CALLER_CTIA_CAM); + } + } else { + /* Keep at Fast PS */ + { + enum PARAM_POWER_MODE ePowerMode; + + prAdapter->u4CtiaPowerMode = 2; + prAdapter->fgEnCtiaPowerMode = TRUE; + + ePowerMode = Param_PowerModeFast_PSP; + rWlanStatus = nicConfigPowerSaveProfile(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, + ePowerMode, fgEnCmdEvent, PS_CALLER_CTIA_CAM); + } + } + + return rWlanStatus; +} + +uint32_t nicEnterCtiaModeOfBCNTimeout(IN struct ADAPTER + *prAdapter, u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent) +{ + uint32_t rWlanStatus; + + ASSERT(prAdapter); + DBGLOG(INIT, INFO, "nicEnterCtiaModeOfBCNTimeout: %d\n", + fgEnterCtia); + + rWlanStatus = WLAN_STATUS_SUCCESS; + + if (fgEnterCtia) { + /* Disable Beacon Timeout Detection */ + prAdapter->fgDisBcnLostDetection = TRUE; + } else { + /* Enable Beacon Timeout Detection */ + prAdapter->fgDisBcnLostDetection = FALSE; + } + + return rWlanStatus; +} + +uint32_t nicEnterCtiaModeOfAutoTxPower(IN struct ADAPTER + *prAdapter, u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent) +{ + struct CMD_SW_DBG_CTRL rCmdSwCtrl; + uint32_t rWlanStatus; + + ASSERT(prAdapter); + DBGLOG(INIT, INFO, "nicEnterCtiaModeOfAutoTxPower: %d\n", + fgEnterCtia); + + rWlanStatus = WLAN_STATUS_SUCCESS; + + if (fgEnterCtia) { + /* Disalbe auto tx power */ + rCmdSwCtrl.u4Id = 0x55670003; + rCmdSwCtrl.u4Data = 0x0; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_SW_DBG_CTRL), + (uint8_t *) &rCmdSwCtrl, + NULL, 0); + } else { + /* Enable auto tx power */ + rCmdSwCtrl.u4Id = 0x55670003; + rCmdSwCtrl.u4Data = 0x1; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_SW_DBG_CTRL), + (uint8_t *) &rCmdSwCtrl, + NULL, 0); + } + + return rWlanStatus; +} + +uint32_t nicEnterCtiaModeOfFIFOFullNoAck(IN struct ADAPTER + *prAdapter, u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent) +{ + struct CMD_SW_DBG_CTRL rCmdSwCtrl; + uint32_t rWlanStatus; + + ASSERT(prAdapter); + DBGLOG(INIT, INFO, "nicEnterCtiaModeOfFIFOFullNoAck: %d\n", + fgEnterCtia); + + rWlanStatus = WLAN_STATUS_SUCCESS; + + if (fgEnterCtia) { + /* Disable FIFO FULL no ack */ + rCmdSwCtrl.u4Id = 0x55680000; + rCmdSwCtrl.u4Data = 0x0; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_SW_DBG_CTRL), + (uint8_t *) &rCmdSwCtrl, + NULL, 0); + } else { + /* Enable FIFO FULL no ack */ + rCmdSwCtrl.u4Id = 0x55680000; + rCmdSwCtrl.u4Data = 0x1; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_SW_DBG_CTRL), + (uint8_t *) &rCmdSwCtrl, + NULL, 0); + } + + return rWlanStatus; +} + +uint32_t nicEnterTPTestMode(IN struct ADAPTER *prAdapter, + IN uint8_t ucFuncMask) +{ + struct CMD_SW_DBG_CTRL rCmdSwCtrl; + uint32_t rWlanStatus; + uint8_t ucBssIdx; + struct BSS_INFO *prBssInfo; + + ASSERT(prAdapter); + + rWlanStatus = WLAN_STATUS_SUCCESS; + + if (ucFuncMask) { + /* 1. Disable On-Lin Scan */ + if (ucFuncMask & TEST_MODE_DISABLE_ONLINE_SCAN) + prAdapter->fgEnOnlineScan = FALSE; + + /* 2. Disable Roaming */ + if (ucFuncMask & TEST_MODE_DISABLE_ROAMING) { + rCmdSwCtrl.u4Id = 0xa0210000; + rCmdSwCtrl.u4Data = 0x0; + wlanSendSetQueryCmd(prAdapter, CMD_ID_SW_DBG_CTRL, TRUE, + FALSE, FALSE, + NULL, NULL, sizeof(struct CMD_SW_DBG_CTRL), + (uint8_t *)&rCmdSwCtrl, NULL, 0); + } + /* 3. Keep at CAM mode */ + if (ucFuncMask & TEST_MODE_FIXED_CAM_MODE) + for (ucBssIdx = 0; ucBssIdx < prAdapter->ucHwBssIdNum; + ucBssIdx++) { + prBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIdx); + if (prBssInfo->fgIsInUse + && (prBssInfo->eCurrentOPMode + == OP_MODE_INFRASTRUCTURE)) + nicConfigPowerSaveProfile(prAdapter, + ucBssIdx, Param_PowerModeCAM, + FALSE, PS_CALLER_TP); + } + + /* 4. Disable Beacon Timeout Detection */ + if (ucFuncMask & TEST_MODE_DISABLE_BCN_LOST_DET) + prAdapter->fgDisBcnLostDetection = TRUE; + } else { + /* 1. Enaable On-Lin Scan */ + prAdapter->fgEnOnlineScan = TRUE; + + /* 2. Enable Roaming */ + rCmdSwCtrl.u4Id = 0xa0210000; + rCmdSwCtrl.u4Data = 0x1; + wlanSendSetQueryCmd(prAdapter, CMD_ID_SW_DBG_CTRL, TRUE, + FALSE, FALSE, + NULL, NULL, sizeof(struct CMD_SW_DBG_CTRL), + (uint8_t *)&rCmdSwCtrl, NULL, 0); + + /* 3. Keep at Fast PS */ + for (ucBssIdx = 0; ucBssIdx < prAdapter->ucHwBssIdNum; + ucBssIdx++) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + if (prBssInfo->fgIsInUse + && (prBssInfo->eCurrentOPMode + == OP_MODE_INFRASTRUCTURE)) + nicConfigPowerSaveProfile(prAdapter, ucBssIdx, + Param_PowerModeFast_PSP, + FALSE, PS_CALLER_TP); + } + + /* 4. Enable Beacon Timeout Detection */ + prAdapter->fgDisBcnLostDetection = FALSE; + } + + return rWlanStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This utility function is used to indicate firmware domain + * for beacon generation parameters + * + * @param prAdapter Pointer of ADAPTER_T + * eIeUpdMethod, Update Method + * ucBssIndex Index of BSS-INFO + * 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +nicUpdateBeaconIETemplate(IN struct ADAPTER *prAdapter, + IN enum ENUM_IE_UPD_METHOD eIeUpdMethod, + IN uint8_t ucBssIndex, IN uint16_t u2Capability, + IN uint8_t *aucIe, IN uint16_t u2IELen) +{ + struct CMD_BEACON_TEMPLATE_UPDATE *prCmdBcnUpdate; + uint16_t u2CmdBufLen = 0; + struct GLUE_INFO *prGlueInfo; + struct CMD_INFO *prCmdInfo; + struct WIFI_CMD *prWifiCmd; + uint8_t ucCmdSeqNum; + + DEBUGFUNC("wlanUpdateBeaconIETemplate"); + DBGLOG(INIT, LOUD, "\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(struct CMD_BEACON_TEMPLATE_UPDATE, + aucIE) + u2IELen; + } else if (eIeUpdMethod == IE_UPD_METHOD_DELETE_ALL) { + u2CmdBufLen = OFFSET_OF(struct CMD_BEACON_TEMPLATE_UPDATE, + u2IELen); +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP + } else if (eIeUpdMethod == IE_UPD_METHOD_UPDATE_PROBE_RSP) { + u2CmdBufLen = OFFSET_OF(struct CMD_BEACON_TEMPLATE_UPDATE, + aucIE) + u2IELen; + DBGLOG(NIC, INFO, + "update for probe response offload to firmware\n"); +#endif + } else { + DBGLOG(INIT, ERROR, "Unknown IeUpdMethod.\n"); + 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"); + 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->u2InfoBufLen = (uint16_t) (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->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u2CmdBufLen; + prCmdInfo->pvInformationBuffer = NULL; + prCmdInfo->u4InformationBufferLength = 0; + + /* Setup WIFI_CMD_T (no payload) */ + prWifiCmd = (struct WIFI_CMD *) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prCmdBcnUpdate = (struct CMD_BEACON_TEMPLATE_UPDATE *) ( + prWifiCmd->aucBuffer); + + /* fill beacon updating command */ + prCmdBcnUpdate->ucUpdateMethod = (uint8_t) eIeUpdMethod; + prCmdBcnUpdate->ucBssIndex = ucBssIndex; + prCmdBcnUpdate->u2Capability = u2Capability; + prCmdBcnUpdate->u2IELen = u2IELen; + if (u2IELen > 0) + kalMemCopy(prCmdBcnUpdate->aucIE, aucIe, u2IELen); + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, + (struct QUE_ENTRY *) 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 struct ADAPTER *prAdapter) +{ + struct CONNECTION_SETTINGS *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 + prAdapter->rWifiVar.eNonHTBasicPhyType2G4 = + PHY_TYPE_HR_DSSS_INDEX; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This utility function is used to update WMM Parms + * + * @param prAdapter Pointer of ADAPTER_T + * ucBssIndex Index of BSS-INFO + * + * @retval - + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicQmUpdateWmmParms(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + struct BSS_INFO *prBssInfo; + struct CMD_UPDATE_WMM_PARMS rCmdUpdateWmmParms; + + ASSERT(prAdapter); + + DBGLOG(QM, INFO, "Update WMM parameters for BSS[%u]\n", + ucBssIndex); + + DBGLOG(QM, EVENT, "sizeof(struct AC_QUE_PARMS): %zu\n", + sizeof(struct AC_QUE_PARMS)); + DBGLOG(QM, EVENT, "sizeof(CMD_UPDATE_WMM_PARMS): %zu\n", + sizeof(struct CMD_UPDATE_WMM_PARMS)); + DBGLOG(QM, EVENT, "sizeof(struct WIFI_CMD): %zu\n", + sizeof(struct WIFI_CMD)); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + rCmdUpdateWmmParms.ucBssIndex = (uint8_t) ucBssIndex; + kalMemCopy(&rCmdUpdateWmmParms.arACQueParms[0], + &prBssInfo->arACQueParms[0], + (sizeof(struct AC_QUE_PARMS) * AC_NUM)); + + rCmdUpdateWmmParms.fgIsQBSS = prBssInfo->fgIsQBSS; + rCmdUpdateWmmParms.ucWmmSet = (uint8_t) + prBssInfo->ucWmmQueSet; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_UPDATE_WMM_PARMS, + TRUE, + FALSE, + FALSE, + NULL, NULL, + sizeof(struct CMD_UPDATE_WMM_PARMS), + (uint8_t *)&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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicUpdateTxPower(IN struct ADAPTER *prAdapter, + IN struct CMD_TX_PWR *prTxPwrParam) +{ + DEBUGFUNC("nicUpdateTxPower"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_TX_PWR, + TRUE, + FALSE, FALSE, NULL, NULL, + sizeof(struct CMD_TX_PWR), + (uint8_t *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicSetAutoTxPower(IN struct ADAPTER *prAdapter, + IN struct CMD_AUTO_POWER_PARAM *prAutoPwrParam) +{ + DEBUGFUNC("nicSetAutoTxPower"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_AUTOPWR_CTRL, + TRUE, + FALSE, + FALSE, + NULL, NULL, + sizeof(struct CMD_AUTO_POWER_PARAM), + (uint8_t *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicSetAutoTxPowerControl(IN struct ADAPTER + *prAdapter, IN struct CMD_TX_PWR *prTxPwrParam) +{ + DEBUGFUNC("nicUpdateTxPower"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_TX_PWR, + TRUE, + FALSE, FALSE, NULL, NULL, + sizeof(struct CMD_TX_PWR), + (uint8_t *) 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicUpdate5GOffset(IN struct ADAPTER *prAdapter, + IN struct CMD_5G_PWR_OFFSET *pr5GPwrOffset) +{ +#if 0 /* It is not needed anymore */ + DEBUGFUNC("nicUpdate5GOffset"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_5G_PWR_OFFSET, + TRUE, + FALSE, + FALSE, NULL, NULL, + sizeof(struct CMD_5G_PWR_OFFSET), + (uint8_t *) pr5GPwrOffset, NULL, 0); +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicUpdateDPD(IN struct ADAPTER *prAdapter, + IN struct CMD_PWR_PARAM *prDpdCalResult) +{ + DEBUGFUNC("nicUpdateDPD"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_PWR_PARAM, + TRUE, + FALSE, + FALSE, NULL, NULL, + sizeof(struct CMD_PWR_PARAM), + (uint8_t *) 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 struct ADAPTER *prAdapter) +{ + ASSERT(prAdapter); + + /* <1> Initialize MGMT Memory pool and STA_REC */ + cnmMemInit(prAdapter); + cnmStaRecInit(prAdapter); + cmdBufInitialize(prAdapter); + + /* <2> Mailbox Initialization */ + mboxInitialize(prAdapter); + + /* <3> Timer Initialization */ + cnmTimerInitialize(prAdapter); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This utility function reset some specific system service, + * such as STA-REC + * + * @param prAdapter Pointer of ADAPTER_T + * + * @retval none + */ +/*----------------------------------------------------------------------------*/ +void nicResetSystemService(IN struct ADAPTER *prAdapter) +{ + ASSERT(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This utility function is used to update WMM Parms + * + * @param prAdapter Pointer of ADAPTER_T + * + * @retval none + */ +/*----------------------------------------------------------------------------*/ +void nicUninitSystemService(IN struct ADAPTER *prAdapter) +{ + ASSERT(prAdapter); + + /* Timer Destruction */ + cnmTimerDestroy(prAdapter); + + /* Mailbox Destruction */ + mboxDestroy(prAdapter); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This utility function is used to update WMM Parms + * + * @param prAdapter Pointer of ADAPTER_T + * + * @retval none + */ +/*----------------------------------------------------------------------------*/ +void nicInitMGMT(IN struct ADAPTER *prAdapter, + IN struct REG_INFO *prRegInfo) +{ + ASSERT(prAdapter); + + /* CNM Module - initialization */ + cnmInit(prAdapter); + + wmmInit(prAdapter); + + /* RLM Module - initialization */ + rlmFsmEventInit(prAdapter); + + /* SCN Module - initialization */ + scnInit(prAdapter); + + /* AIS Module - intiailization */ + aisFsmInit(prAdapter); + aisInitializeConnectionSettings(prAdapter, prRegInfo); + +#if CFG_SUPPORT_ROAMING + /* Roaming Module - intiailization */ + roamingFsmInit(prAdapter); +#endif /* CFG_SUPPORT_ROAMING */ + +#if CFG_SUPPORT_SWCR + swCrDebugInit(prAdapter); +#endif /* CFG_SUPPORT_SWCR */ + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This utility function is used to update WMM Parms + * + * @param prAdapter Pointer of ADAPTER_T + * + * @retval none + */ +/*----------------------------------------------------------------------------*/ +void nicUninitMGMT(IN struct ADAPTER *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); + + wmmUnInit(prAdapter); + + /* RLM Module - uninitialization */ + rlmFsmEventUninit(prAdapter); + + /* CNM Module - uninitialization */ + cnmUninit(prAdapter); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 u2CapInfo Capability settings + * @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 struct ADAPTER *prAdapter, + IN uint8_t rMacAddr[PARAM_MAC_ADDR_LEN], + IN struct PARAM_SSID *prSsid, + IN uint16_t u2CapInfo, + IN int32_t rRssi, + IN enum ENUM_PARAM_NETWORK_TYPE eNetworkType, + IN struct PARAM_802_11_CONFIG *prConfiguration, + IN enum ENUM_PARAM_OP_MODE eOpMode, + IN uint8_t rSupportedRates[PARAM_MAX_LEN_RATES_EX], + IN uint16_t u2IELength, IN uint8_t *pucIEBuf) +{ + u_int8_t bReplace; + uint32_t i; + uint32_t u4IdxWeakest = 0; + int32_t rWeakestRssi; + uint32_t u4BufferSize; + /* Privicy setting 0: Open / 1: WEP/WPA/WPA2 enabled */ + uint32_t u4Privacy = u2CapInfo & CAP_INFO_PRIVACY ? 1 : 0; + + ASSERT(prAdapter); + + rWeakestRssi = (int32_t) INT_MAX; + u4BufferSize = ARRAY_SIZE( + prAdapter->rWlanInfo.aucScanIEBuf); + + 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(struct PARAM_BSSID_EX, aucIEs)); + + /* then fill buffer */ + prAdapter->rWlanInfo.arScanResult[i].u4Length = + OFFSET_OF(struct PARAM_BSSID_EX, 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(struct PARAM_802_11_CONFIG)); + prAdapter->rWlanInfo.arScanResult[i].eOpMode = eOpMode; + kalMemCopy(( + prAdapter->rWlanInfo. + arScanResult[i].rSupportedRates), + rSupportedRates, (sizeof(uint8_t) * + PARAM_MAX_LEN_RATES_EX)); + prAdapter->rWlanInfo.arScanResult[i].u4IELength = + (uint32_t) 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(struct PARAM_BSSID_EX, aucIEs)); + + /* then fill buffer */ + prAdapter->rWlanInfo.arScanResult[i].u4Length = + OFFSET_OF(struct PARAM_BSSID_EX, 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(struct PARAM_802_11_CONFIG)); + prAdapter->rWlanInfo.arScanResult[i].eOpMode = eOpMode; + kalMemCopy(( + prAdapter->rWlanInfo.arScanResult[i]. + rSupportedRates), + rSupportedRates, (sizeof(uint8_t) * + PARAM_MAX_LEN_RATES_EX)); + prAdapter->rWlanInfo.arScanResult[i].u4IELength = + (uint32_t) 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 != (int32_t) INT_MAX) { + /* replace weakest one */ + i = u4IdxWeakest; + + /* free IE buffer then zero */ + nicFreeScanResultIE(prAdapter, i); + kalMemZero(&(prAdapter->rWlanInfo.arScanResult[i]), + OFFSET_OF(struct PARAM_BSSID_EX, aucIEs)); + + /* then fill buffer */ + prAdapter->rWlanInfo.arScanResult[i].u4Length = + OFFSET_OF(struct PARAM_BSSID_EX, 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(struct PARAM_802_11_CONFIG)); + prAdapter->rWlanInfo.arScanResult[i].eOpMode = eOpMode; + kalMemCopy(( + prAdapter->rWlanInfo.arScanResult[i]. + rSupportedRates), + rSupportedRates, (sizeof(uint8_t) * + PARAM_MAX_LEN_RATES_EX)); + prAdapter->rWlanInfo.arScanResult[i].u4IELength = + (uint32_t) 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 struct ADAPTER *prAdapter, + IN uint32_t u4Idx) +{ + uint32_t i; + uint8_t *pucPivot, *pucMovePivot; + uint32_t 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 = (uint8_t *) ((unsigned long) ( + prAdapter->rWlanInfo.apucScanResultIEs[u4Idx]) + + u4FreeSize); + + u4ReserveSize = ((unsigned long) pucPivot) - + (unsigned long) (&(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] = + (uint8_t *) ((unsigned long) ( + prAdapter->rWlanInfo. + apucScanResultIEs[i]) + - u4FreeSize); + } + } + } + + /* 1.2 reset the freed one */ + prAdapter->rWlanInfo.arScanResult[u4Idx].u4IELength = 0; + prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; + + /* 2. reduce IE buffer usage */ + prAdapter->rWlanInfo.u4ScanIEBufferUsage -= u4FreeSize; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is to hack parameters for WLAN TABLE for + * fixed rate settings + * + * @param prAdapter Pointer to the Adapter structure. + * @param eRateSetting + * @param pu2DesiredNonHTRateSet, + * @param pu2BSSBasicRateSet, + * @param pucMcsSet + * @param pucSupMcs32 + * @param pu2HtCapInfo + * + * @return WLAN_STATUS_SUCCESS + */ +/*----------------------------------------------------------------------------*/ +uint32_t +nicUpdateRateParams(IN struct ADAPTER *prAdapter, + IN enum ENUM_REGISTRY_FIXED_RATE eRateSetting, + IN uint8_t *pucDesiredPhyTypeSet, + IN uint16_t *pu2DesiredNonHTRateSet, + IN uint16_t *pu2BSSBasicRateSet, + IN uint8_t *pucMcsSet, IN uint8_t *pucSupMcs32, + IN uint16_t *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 = BIT(HT_RATE_MCS0_INDEX - 1); + *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 = BIT(HT_RATE_MCS1_INDEX - 1); + *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 = BIT(HT_RATE_MCS2_INDEX - 1); + *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 = BIT(HT_RATE_MCS3_INDEX - 1); + *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 = BIT(HT_RATE_MCS4_INDEX - 1); + *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 = BIT(HT_RATE_MCS5_INDEX - 1); + *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 = BIT(HT_RATE_MCS6_INDEX - 1); + *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 = BIT(HT_RATE_MCS7_INDEX - 1); + *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 = BIT(HT_RATE_MCS0_INDEX - 1); + *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 = BIT(HT_RATE_MCS1_INDEX - 1); + *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 = BIT(HT_RATE_MCS2_INDEX - 1); + *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 = BIT(HT_RATE_MCS3_INDEX - 1); + *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 = BIT(HT_RATE_MCS4_INDEX - 1); + *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 = BIT(HT_RATE_MCS5_INDEX - 1); + *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 = BIT(HT_RATE_MCS6_INDEX - 1); + *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 = BIT(HT_RATE_MCS7_INDEX - 1); + *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 = BIT(HT_RATE_MCS0_INDEX - 1); + *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 = BIT(HT_RATE_MCS1_INDEX - 1); + *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 = BIT(HT_RATE_MCS2_INDEX - 1); + *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 = BIT(HT_RATE_MCS3_INDEX - 1); + *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 = BIT(HT_RATE_MCS4_INDEX - 1); + *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 = BIT(HT_RATE_MCS5_INDEX - 1); + *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 = BIT(HT_RATE_MCS6_INDEX - 1); + *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 = BIT(HT_RATE_MCS7_INDEX - 1); + *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 = 0; + *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 = BIT(HT_RATE_MCS0_INDEX - 1); + *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 = BIT(HT_RATE_MCS1_INDEX - 1); + *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 = BIT(HT_RATE_MCS2_INDEX - 1); + *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 = BIT(HT_RATE_MCS3_INDEX - 1); + *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 = BIT(HT_RATE_MCS4_INDEX - 1); + *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 = BIT(HT_RATE_MCS5_INDEX - 1); + *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 = BIT(HT_RATE_MCS6_INDEX - 1); + *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 = BIT(HT_RATE_MCS7_INDEX - 1); + *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 = 0; + *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 + */ +/*----------------------------------------------------------------------------*/ + +uint32_t nicWriteMcr(IN struct ADAPTER *prAdapter, + IN uint32_t u4Address, IN uint32_t u4Value) +{ + struct CMD_ACCESS_REG rCmdAccessReg; + + rCmdAccessReg.u4Address = u4Address; + rCmdAccessReg.u4Data = u4Value; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + TRUE, + FALSE, + FALSE, NULL, NULL, + sizeof(struct CMD_ACCESS_REG), + (uint8_t *) &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 + */ +/*----------------------------------------------------------------------------*/ + +uint32_t +nicRlmArUpdateParms(IN struct ADAPTER *prAdapter, + IN uint32_t u4ArSysParam0, + IN uint32_t u4ArSysParam1, IN uint32_t u4ArSysParam2, + IN uint32_t u4ArSysParam3) +{ + uint8_t ucArVer, ucAbwVer, ucAgiVer; + uint16_t u2HtClrMask; + uint16_t u2LegacyClrMask; + uint8_t ucArCheckWindow; + uint8_t ucArPerL; + uint8_t ucArPerH; + uint8_t ucArPerForceRateDownPer; + + ucArVer = (uint8_t) (u4ArSysParam0 & BITS(0, 3)); + ucAbwVer = (uint8_t) ((u4ArSysParam0 & BITS(4, 5)) >> 4); + ucAgiVer = (uint8_t) ((u4ArSysParam0 & BITS(6, 7)) >> 6); + u2HtClrMask = (uint16_t) ((u4ArSysParam0 & BITS(8, + 15)) >> 8); + u2LegacyClrMask = (uint16_t) ((u4ArSysParam0 & BITS(16, + 31)) >> 16); + +#if 0 + ucArCheckWindow = (uint8_t) (u4ArSysParam1 & BITS(0, 7)); + ucArPerH = (uint8_t) ((u4ArSysParam1 & BITS(16, 23)) >> 16); + ucArPerL = (uint8_t) ((u4ArSysParam1 & BITS(24, 31)) >> 24); +#endif + + ucArCheckWindow = (uint8_t) (u4ArSysParam1 & BITS(0, 7)); + ucArPerForceRateDownPer = (uint8_t) (((u4ArSysParam1 >> 8) & + BITS(0, 7))); + ucArPerH = (uint8_t) (((u4ArSysParam1 >> 16) & BITS(0, 7))); + ucArPerL = (uint8_t) (((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 + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicRoamingUpdateParams(IN struct ADAPTER + *prAdapter, IN uint32_t u4EnableRoaming) +{ + struct CONNECTION_SETTINGS *prConnSettings; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prConnSettings->fgIsEnableRoaming = ((u4EnableRoaming > 0) + ? (TRUE) : (FALSE)); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to update Link Quality information + * + * @param prAdapter Pointer of Adapter Data Structure + * ucBssIndex + * prEventLinkQuality + * cRssi + * cLinkQuality + * + * @return none + */ +/*----------------------------------------------------------------------------*/ +void nicUpdateLinkQuality(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct EVENT_LINK_QUALITY_V2 *prEventLinkQuality) +{ + int8_t cRssi; + uint16_t u2AdjustRssi = 10; + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + ASSERT(prEventLinkQuality); + + switch (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType) { + case NETWORK_TYPE_AIS: + if (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->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) { + /* ranged from (-128 ~ 30) in unit of dBm */ + cRssi = + prEventLinkQuality->rLq[ucBssIndex]. + cRssi; + cRssi = + (int8_t) (((int16_t) + (cRssi) * u2AdjustRssi) / 10); + DBGLOG(RLM, INFO, + "Rssi=%d, NewRssi=%d\n", + prEventLinkQuality->rLq[ucBssIndex]. + cRssi, + cRssi); + nicUpdateRSSI(prAdapter, ucBssIndex, cRssi, + prEventLinkQuality->rLq[ucBssIndex]. + cLinkQuality); + } + + if (prAdapter->fgIsLinkRateValid == FALSE + || (kalGetTimeTick() - + prAdapter->rLinkRateUpdateTime) + > CFG_LINK_QUALITY_VALID_PERIOD) { + nicUpdateLinkSpeed(prAdapter, ucBssIndex, + prEventLinkQuality->rLq[ucBssIndex]. + u2LinkSpeed); + } + + } + break; + +#if 0 +/* #if CFG_ENABLE_WIFI_DIRECT && CFG_SUPPORT_P2P_RSSI_QUERY */ + case NETWORK_TYPE_P2P: + if (prAdapter->fgIsP2pLinkQualityValid == FALSE + || (kalGetTimeTick() - prAdapter->rP2pLinkQualityUpdateTime) + > CFG_LINK_QUALITY_VALID_PERIOD) { + struct EVENT_LINK_QUALITY_EX *prEventLQEx = + (struct EVENT_LINK_QUALITY_EX *) + prEventLinkQuality; + + nicUpdateRSSI(prAdapter, ucBssIndex, + prEventLQEx->cRssiP2P, + prEventLQEx->cLinkQualityP2P); + } + break; +#endif + default: + break; + + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to update RSSI and Link Quality information + * + * @param prAdapter Pointer of Adapter Data Structure + * ucBssIndex + * cRssi + * cLinkQuality + * + * @return none + */ +/*----------------------------------------------------------------------------*/ +void nicUpdateRSSI(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN int8_t cRssi, + IN int8_t cLinkQuality) +{ + ASSERT(prAdapter); + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + switch (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType) { + case NETWORK_TYPE_AIS: + if (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->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 && CFG_SUPPORT_P2P_RSSI_QUERY + case NETWORK_TYPE_P2P: + 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 + default: + break; + + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to update Link Quality information + * + * @param prAdapter Pointer of Adapter Data Structure + * ucBssIndex + * prEventLinkQuality + * cRssi + * cLinkQuality + * + * @return none + */ +/*----------------------------------------------------------------------------*/ +void nicUpdateLinkSpeed(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN uint16_t u2LinkSpeed) +{ + ASSERT(prAdapter); + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + switch (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType) { + case NETWORK_TYPE_AIS: + if (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eConnectionState == + PARAM_MEDIA_STATE_CONNECTED) { + /* buffer statistics for further query */ + prAdapter->fgIsLinkRateValid = TRUE; + prAdapter->rLinkRateUpdateTime = kalGetTimeTick(); + + prAdapter->rLinkQuality.u2LinkSpeed = u2LinkSpeed; + } + break; + + default: + break; + + } + +} + +#if CFG_SUPPORT_RDD_TEST_MODE +uint32_t nicUpdateRddTestMode(IN struct ADAPTER *prAdapter, + IN struct CMD_RDD_CH *prRddChParam) +{ + DEBUGFUNC("nicUpdateRddTestMode.\n"); + + ASSERT(prAdapter); + + /* aisFsmScanRequest(prAdapter, NULL); */ + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RDD_CH, + TRUE, + FALSE, FALSE, NULL, NULL, + sizeof(struct CMD_RDD_CH), + (uint8_t *) prRddChParam, NULL, 0); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to apply network address setting to + * both OS side and firmware domain + * + * @param prAdapter Pointer of Adapter Data Structure + * + * @return none + */ +/*----------------------------------------------------------------------------*/ + +uint32_t nicApplyNetworkAddress(IN struct ADAPTER + *prAdapter) +{ + uint32_t i; + + ASSERT(prAdapter); + + /* copy to adapter */ + COPY_MAC_ADDR(prAdapter->rMyMacAddr, + prAdapter->rWifiVar.aucMacAddress); + + /* 4 <3> Update new MAC address to all 3 networks */ + 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; + +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + if (prAdapter->rWifiVar.arBssInfoPool[i].eNetworkType == + NETWORK_TYPE_P2P) { + COPY_MAC_ADDR( + prAdapter->rWifiVar.arBssInfoPool[i]. + aucOwnMacAddr, + prAdapter->rWifiVar.aucDeviceAddress); + } + } + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + if (prAdapter->rWifiVar.arBssInfoPool[i].eNetworkType == + NETWORK_TYPE_BOW) { + COPY_MAC_ADDR( + prAdapter->rWifiVar.arBssInfoPool[i]. + 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 WLAN_STATUS_SUCCESS; +} + +#if 1 +uint8_t nicGetChipHwVer(void) +{ + return g_eco_info.ucHwVer; +} + +uint8_t nicGetChipSwVer(void) +{ + return g_eco_info.ucRomVer; +} + +uint8_t nicGetChipFactoryVer(void) +{ + return g_eco_info.ucFactoryVer; +} + +uint8_t nicSetChipHwVer(uint8_t value) +{ + g_eco_info.ucHwVer = value; + return 0; +} + +uint8_t nicSetChipSwVer(uint8_t value) +{ + g_eco_info.ucRomVer = value; + return 0; +} + +uint8_t nicSetChipFactoryVer(uint8_t value) +{ + g_eco_info.ucFactoryVer = value; + return 0; +} + +#else +uint8_t nicGetChipHwVer(void) +{ + return mtk_wcn_wmt_ic_info_get(WMTCHIN_HWVER) & BITS(0, 7); +} + +uint8_t nicGetChipSwVer(void) +{ + return mtk_wcn_wmt_ic_info_get(WMTCHIN_FWVER) & BITS(0, 7); +} + +uint8_t nicGetChipFactoryVer(void) +{ + return (mtk_wcn_wmt_ic_info_get(WMTCHIN_FWVER) & BITS(8, + 11)) >> 8; +} +#endif + +uint8_t nicGetChipEcoVer(IN struct ADAPTER *prAdapter) +{ + struct ECO_INFO *prEcoInfo; + uint8_t ucEcoVer; + uint8_t ucCurSwVer, ucCurHwVer, ucCurFactoryVer; + + ucCurSwVer = nicGetChipSwVer(); + ucCurHwVer = nicGetChipHwVer(); + ucCurFactoryVer = nicGetChipFactoryVer(); + + ucEcoVer = 0; + + while (TRUE) { + /* Get ECO info from table */ + prEcoInfo = (struct ECO_INFO *) & + (prAdapter->chip_info->eco_info[ucEcoVer]); + + if ((prEcoInfo->ucRomVer == 0) && + (prEcoInfo->ucHwVer == 0) && + (prEcoInfo->ucFactoryVer == 0)) { + + /* last ECO info */ + if (ucEcoVer > 0) + ucEcoVer--; + + /* End of table */ + break; + } + + if ((prEcoInfo->ucRomVer == ucCurSwVer) && + (prEcoInfo->ucHwVer == ucCurHwVer) && + (prEcoInfo->ucFactoryVer == ucCurFactoryVer)) { + break; + } + + ucEcoVer++; + } + +#if 0 + DBGLOG(INIT, INFO, + "Cannot get ECO version for SwVer[0x%02x]HwVer[0x%02x]FactoryVer[0x%1x],recognize as latest version[E%u]\n", + ucCurSwVer, ucCurHwVer, ucCurFactoryVer, + prAdapter->chip_info->eco_info[ucEcoVer].ucEcoVer); +#endif + return prAdapter->chip_info->eco_info[ucEcoVer].ucEcoVer; +} + +u_int8_t nicIsEcoVerEqualTo(IN struct ADAPTER *prAdapter, + uint8_t ucEcoVer) +{ + if (ucEcoVer == prAdapter->chip_info->eco_ver) + return TRUE; + else + return FALSE; +} + +u_int8_t nicIsEcoVerEqualOrLaterTo(IN struct ADAPTER + *prAdapter, uint8_t ucEcoVer) +{ + if (ucEcoVer <= prAdapter->chip_info->eco_ver) + return TRUE; + else + return FALSE; +} + +#if CFG_SUPPORT_SER +void nicSerStopTxRx(IN struct ADAPTER *prAdapter) +{ +#if defined(_HIF_USB) + struct GL_HIF_INFO *prHifInfo; + unsigned long ulFlags_1, ulFlags_2; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + /* 1. Make sure ucSerState is accessed sequentially. + * 2. Two scenarios: + * - When hif_thread is doing usb_submit_urb, SER occurs. + * hif_thread acquires the lock first, so nicSerSyncTimerHandler + * must wait hif_thread until it completes current usb_submit_urb. + * Then, nicSerSyncTimerHandler acquires the lock, change + * ucSerState to prevent subsequent usb_submit_urb and cancel ALL + * TX BULK OUT URB. + * - When SER is triggered and executed, hif_thread is prepared to do + * usb_submit_urb. nicSerSyncTimerHandler acquires the lock first, + * which guarantees ucSerState is accessed sequentially. Then, + * hif_thread acquires the lock, knows that SER is ongoing, and + * bypass usb_submit_urb. + * 3. The purpose of using two spinlocks (i.e. rTxDataQLock & + * rTxCmdQLock) is making both TX data and TX cmd are independent + * with each other. + */ + spin_lock_irqsave(&prHifInfo->rTxDataQLock, ulFlags_1); + spin_lock_irqsave(&prHifInfo->rTxCmdQLock, ulFlags_2); +#endif + DBGLOG(INIT, WARN, "[SER][L1] host set STOP_TRX\n"); + prAdapter->ucSerState = SER_STOP_HOST_TX_RX; + + /* Force own to FW as ACK and stop HIF */ + prAdapter->fgWiFiInSleepyState = TRUE; + +#if defined(_HIF_USB) + spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, ulFlags_2); + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, ulFlags_1); +#endif +} + +void nicSerStopTx(IN struct ADAPTER *prAdapter) +{ +#if defined(_HIF_USB) + struct GL_HIF_INFO *prHifInfo; + unsigned long ulFlags_1, ulFlags_2; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + spin_lock_irqsave(&prHifInfo->rTxDataQLock, ulFlags_1); + spin_lock_irqsave(&prHifInfo->rTxCmdQLock, ulFlags_2); +#endif + + prAdapter->ucSerState = SER_STOP_HOST_TX; + +#if defined(_HIF_USB) + spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, ulFlags_2); + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, ulFlags_1); +#endif +} + +void nicSerStartTxRx(IN struct ADAPTER *prAdapter) +{ +#if defined(_HIF_USB) + struct GL_HIF_INFO *prHifInfo; + unsigned long ulFlags_1, ulFlags_2; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + spin_lock_irqsave(&prHifInfo->rTxDataQLock, ulFlags_1); + spin_lock_irqsave(&prHifInfo->rTxCmdQLock, ulFlags_2); +#endif + + DBGLOG(INIT, WARN, "[SER][L1] host recovery TRX\n"); + halSerHifReset(prAdapter); + prAdapter->ucSerState = SER_IDLE_DONE; + +#if defined(_HIF_USB) + spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, ulFlags_2); + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, ulFlags_1); +#endif +} + +u_int8_t nicSerIsWaitingReset(IN struct ADAPTER *prAdapter) +{ + if (prAdapter->ucSerState == SER_STOP_HOST_TX_RX) + return TRUE; + else + return FALSE; +} + +u_int8_t nicSerIsTxStop(IN struct ADAPTER *prAdapter) +{ + switch (prAdapter->ucSerState) { + case SER_STOP_HOST_TX: + case SER_STOP_HOST_TX_RX: + case SER_REINIT_HIF: + return TRUE; + + case SER_IDLE_DONE: + default: + return FALSE; + } +} + +u_int8_t nicSerIsRxStop(IN struct ADAPTER *prAdapter) +{ + switch (prAdapter->ucSerState) { + case SER_STOP_HOST_TX_RX: + case SER_REINIT_HIF: + return TRUE; + + case SER_STOP_HOST_TX: + case SER_IDLE_DONE: + default: + return FALSE; + } +} + +void nicSerReInitBeaconFrame(IN struct ADAPTER *prAdapter) +{ + struct P2P_ROLE_FSM_INFO *prRoleP2pFsmInfo; + + prRoleP2pFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + 0); + if (prRoleP2pFsmInfo != NULL) { + bssUpdateBeaconContent(prAdapter, + prRoleP2pFsmInfo->ucBssIndex); + DBGLOG(NIC, INFO, "SER beacon frame is updated\n"); + } +} + +#if defined(_HIF_USB) +void nicSerSyncTimerHandler(IN struct ADAPTER *prAdapter, + IN unsigned long ulParam) +{ + int ret = 0; + uint16_t u2SerState; + + /* get N9 SER state */ + ret = HAL_WIFI_FUNC_GET_SER_STATE(prAdapter, &u2SerState); + + if (ret) + goto bypass; + + switch (u2SerState) { + case ENUM_SER_STATE_IDLE: + /* do nothing */ + break; + + case ENUM_SER_STATE_ERR_DET: + + /* Stop upper layers calling the device hard_start_xmit + * routine. + */ + netif_tx_stop_all_queues(prAdapter->prGlueInfo->prDevHandler); + + /* stop TX/RX */ + nicSerStopTxRx(prAdapter); + + halTxCancelAllSending(prAdapter); + + halDisableInterrupt(prAdapter); + + /* Send Host stops TX/RX done response to N9 */ + HAL_WIFI_FUNC_SET_SER_STATE(prAdapter, + (uint16_t) ENUM_SER_STATE_HIF_TRX_SUSPEND); + + DBGLOG(NIC, WARN, "SER: Stop HIF Tx/Rx!\n"); + + break; + + case ENUM_SER_STATE_HIF_TRX_SUSPEND: + /* do nothing */ + break; + + case ENUM_SER_STATE_RESET_DONE: + + HAL_WIFI_FUNC_SET_SER_STATE(prAdapter, + (uint16_t) ENUM_SER_STATE_HIF_TRX_RESUME); + + /* resume TX/RX */ + nicSerStartTxRx(prAdapter); + + nicEnableInterrupt(prAdapter); + + /* Allow upper layers to call the device hard_start_xmit + * routine. + */ + netif_tx_start_all_queues(prAdapter->prGlueInfo->prDevHandler); + + DBGLOG(NIC, WARN, "SER: Start HIF Tx/Rx!\n"); + + break; + + case ENUM_SER_STATE_HIF_TRX_RESUME: + /* do nothing */ + break; + + default: + DBGLOG(NIC, ERROR, "SER state undefined(%d)\n", u2SerState); + break; + } + +bypass: + /* TODO SER error handling? */ + + cnmTimerStartTimer(prAdapter, &prAdapter->rSerSyncTimer, + WIFI_SER_SYNC_TIMER_TIMEOUT_IN_MS); +} +#endif /* _HIF_USB */ +#endif /* CFG_SUPPORT_SER */ + +#ifdef CFG_SUPPORT_TIME_MEASURE +uint64_t nicCalcTime( + uint64_t u8Time, + int64_t i8ClkOffset, + int64_t i8ClkRateDiff, + uint64_t u8LastTime) +{ + uint64_t u8DeltaTime; + int64_t i8TotalClkRateDiff; + + if (u8Time < u8LastTime) + u8Time = u8Time + BIT64(48); + + if (i8ClkOffset == 0 && u8LastTime == 0) { + u8Time = u8Time & BITS64(0, 47); + return u8Time; + } + + u8DeltaTime = u8Time - u8LastTime; + + { + /* i8TotalClkRateDiff = i8ClkRateDiff * + ** (INT_64)u8DeltaTime / 10000000000LL + */ + uint64_t u8LowBits = 0; + uint64_t u8CODCalcInterval_Shifted = + AUDIO_SYNC_CLK_RATE_DIFF_DIVISOR; + uint8_t ucRightShift = 0; + + while (u8DeltaTime > BIT64(44)) { + u8CODCalcInterval_Shifted >>= 1; + u8LowBits |= ((u8DeltaTime&BIT64(0))<>= 1; + ucRightShift++; + } + if (u8CODCalcInterval_Shifted > 0) { + i8TotalClkRateDiff = div64_s64( + (i8ClkRateDiff * (int64_t)u8DeltaTime), + (int64_t)u8CODCalcInterval_Shifted + ); + } else { + i8TotalClkRateDiff = 0; + } + i8TotalClkRateDiff += div64_s64( + (i8ClkRateDiff * (int64_t)u8LowBits), + (int64_t)AUDIO_SYNC_CLK_RATE_DIFF_DIVISOR); + } + + u8Time = (int64_t)u8Time + i8ClkOffset + i8TotalClkRateDiff; + + u8Time = u8Time & BITS64(0, 47); + + return u8Time; +} + +uint64_t nicFtmRAWASCtrl(uint64_t u8SysTime) +{ + uint64_t u8NicCnt; /* ps */ + + /* T = (INT_64)u8NicCnt + + ** g_i8ClockOffset + + ** (u8NicCnt - g_u8LastToA) * g_i8COD / 100000000000LLl; + */ + + if (g_u8NicCnt < g_u8LastToA) + g_u8NicCnt = g_u8NicCnt + BIT64(48); + + DBGLOG(NIC, INFO, "[%s] Clk drift: %lld\n", __func__ + , g_i8HostClkRateDiff); + u8SysTime = u8SysTime * 1000; + + u8NicCnt = nicCalcTime(u8SysTime, + ((int64_t)g_u8NicCnt - (int64_t)g_u8SysClkps), + g_i8HostClkRateDiff, g_u8SysClkps); + + u8NicCnt = nicCalcTime(u8NicCnt, g_i8ClockOffset, + g_i8ClkRateDiff, g_u8LastToA); + + return u8NicCnt; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic_cmd_event.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic_cmd_event.c new file mode 100644 index 0000000000000..0892d6868cd55 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic_cmd_event.c @@ -0,0 +1,5950 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/ + * MT6620_WIFI_DRIVER_V2_3/nic/nic_cmd_event.c#3 + */ + +/*! \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. + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" +#include "gl_ate_agent.h" +#include "gl_vendor.h" + + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +const struct NIC_CAPABILITY_V2_REF_TABLE + gNicCapabilityV2InfoTable[] = { +#if defined(_HIF_SDIO) + {TAG_CAP_TX_RESOURCE, nicEventQueryTxResourceEntry}, +#endif + {TAG_CAP_TX_EFUSEADDRESS, nicCmdEventQueryNicEfuseAddr}, + {TAG_CAP_COEX_FEATURE, nicCmdEventQueryNicCoexFeature}, + {TAG_CAP_SINGLE_SKU, rlmDomainExtractSingleSkuInfoFromFirmware}, +#if CFG_TCP_IP_CHKSUM_OFFLOAD + {TAG_CAP_CSUM_OFFLOAD, nicCmdEventQueryNicCsumOffload}, +#endif + {TAG_CAP_HW_VERSION, nicCfgChipCapHwVersion}, + {TAG_CAP_SW_VERSION, nicCfgChipCapSwVersion}, + {TAG_CAP_MAC_ADDR, nicCfgChipCapMacAddr}, + {TAG_CAP_PHY_CAP, nicCfgChipCapPhyCap}, + {TAG_CAP_MAC_CAP, nicCfgChipCapMacCap}, + {TAG_CAP_FRAME_BUF_CAP, nicCfgChipCapFrameBufCap}, + {TAG_CAP_BEAMFORM_CAP, nicCfgChipCapBeamformCap}, + {TAG_CAP_LOCATION_CAP, nicCfgChipCapLocationCap}, + {TAG_CAP_MUMIMO_CAP, nicCfgChipCapMuMimoCap}, + {TAG_CAP_BUFFER_MODE_INFO, nicCfgChipCapBufferModeInfo}, +}; + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D A T A + ******************************************************************************* + */ +void nicCmdEventQueryMcrRead(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct PARAM_CUSTOM_MCR_RW_STRUCT *prMcrRdInfo; + struct GLUE_INFO *prGlueInfo; + struct CMD_ACCESS_REG *prCmdAccessReg; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prCmdAccessReg = (struct CMD_ACCESS_REG *) (pucEventBuf); + + u4QueryInfoLen = sizeof(struct PARAM_CUSTOM_MCR_RW_STRUCT); + + prMcrRdInfo = (struct PARAM_CUSTOM_MCR_RW_STRUCT *) + prCmdInfo->pvInformationBuffer; + prMcrRdInfo->u4McrOffset = prCmdAccessReg->u4Address; + prMcrRdInfo->u4McrData = prCmdAccessReg->u4Data; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + + return; + +} + +void nicCmdEventQueryCoexIso(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct GLUE_INFO *prGlueInfo; + + struct CMD_COEX_HANDLER *prCmdCoexHandler; + struct CMD_COEX_ISO_DETECT *prCmdCoexIsoDetect; + struct PARAM_COEX_HANDLER *prParaCoexHandler; + struct PARAM_COEX_ISO_DETECT *prCoexIsoDetect; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prCmdCoexHandler = (struct CMD_COEX_HANDLER *) (pucEventBuf); + u4QueryInfoLen = sizeof(struct PARAM_COEX_HANDLER); + prCmdCoexIsoDetect = + (struct CMD_COEX_ISO_DETECT *) &prCmdCoexHandler->aucBuffer[0]; + + prParaCoexHandler = + (struct PARAM_COEX_HANDLER *) prCmdInfo->pvInformationBuffer; + prCoexIsoDetect = + (struct PARAM_COEX_ISO_DETECT *) &prParaCoexHandler->aucBuffer[0]; + prCoexIsoDetect->u4IsoPath = prCmdCoexIsoDetect->u4IsoPath; + prCoexIsoDetect->u4Channel = prCmdCoexIsoDetect->u4Channel; + prCoexIsoDetect->u4Isolation = prCmdCoexIsoDetect->u4Isolation; + + kalOidComplete(prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + } + +} + +void nicCmdEventQueryCoexGetInfo(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct GLUE_INFO *prGlueInfo; + + struct CMD_COEX_HANDLER *prCmdCoexHandler; + struct CMD_COEX_GET_INFO *prCmdCoexGetInfo; + struct PARAM_COEX_HANDLER *prParaCoexHandler; + struct PARAM_COEX_GET_INFO *prParaCoexGetInfo; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (!prCmdInfo->fgIsOid) + return; + + prGlueInfo = prAdapter->prGlueInfo; + prCmdCoexHandler = (struct CMD_COEX_HANDLER *) (pucEventBuf); + u4QueryInfoLen = sizeof(struct PARAM_COEX_HANDLER); + + prCmdCoexGetInfo = + (struct CMD_COEX_GET_INFO *)&prCmdCoexHandler->aucBuffer[0]; + + prParaCoexHandler = + (struct PARAM_COEX_HANDLER *)prCmdInfo->pvInformationBuffer; + + prParaCoexGetInfo = + (struct PARAM_COEX_GET_INFO *)&prParaCoexHandler->aucBuffer[0]; + + kalMemCopy(prParaCoexGetInfo->ucCoexInfo, + prCmdCoexGetInfo->ucCoexInfo, + sizeof(prCmdCoexGetInfo->ucCoexInfo)); + + kalOidComplete(prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); +} + +#if CFG_SUPPORT_QA_TOOL +void nicCmdEventQueryRxStatistics(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + struct PARAM_CUSTOM_ACCESS_RX_STAT *prRxStatistics; + struct EVENT_ACCESS_RX_STAT *prEventAccessRxStat; + uint32_t u4QueryInfoLen, i; + struct GLUE_INFO *prGlueInfo; + uint32_t *prElement; + uint32_t u4Temp; + /* P_CMD_ACCESS_RX_STAT prCmdRxStat, prRxStat; */ + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventAccessRxStat = (struct EVENT_ACCESS_RX_STAT *) ( + pucEventBuf); + + prRxStatistics = (struct PARAM_CUSTOM_ACCESS_RX_STAT *) + prCmdInfo->pvInformationBuffer; + prRxStatistics->u4SeqNum = prEventAccessRxStat->u4SeqNum; + prRxStatistics->u4TotalNum = + prEventAccessRxStat->u4TotalNum; + + u4QueryInfoLen = sizeof(struct CMD_ACCESS_RX_STAT); + + if (prRxStatistics->u4SeqNum == u4RxStatSeqNum) { + prElement = &g_HqaRxStat.MAC_FCS_Err; + for (i = 0; i < HQA_RX_STATISTIC_NUM; i++) { + u4Temp = ntohl( + prEventAccessRxStat->au4Buffer[i]); + kalMemCopy(prElement, &u4Temp, 4); + + if (i < (HQA_RX_STATISTIC_NUM - 1)) + prElement++; + } + + g_HqaRxStat.AllMacMdrdy0 = ntohl( + prEventAccessRxStat->au4Buffer[i]); + i++; + g_HqaRxStat.AllMacMdrdy1 = ntohl( + prEventAccessRxStat->au4Buffer[i]); + /* i++; */ + /* g_HqaRxStat.AllFCSErr0 = + * ntohl(prEventAccessRxStat->au4Buffer[i]); + */ + /* i++; */ + /* g_HqaRxStat.AllFCSErr1 = + * ntohl(prEventAccessRxStat->au4Buffer[i]); + */ + } + + DBGLOG(INIT, ERROR, + "MT6632 : RX Statistics Test SeqNum = %d, TotalNum = %d\n", + (unsigned int)prEventAccessRxStat->u4SeqNum, + (unsigned int)prEventAccessRxStat->u4TotalNum); + + DBGLOG(INIT, ERROR, + "MAC_FCS_ERR = %d, MAC_MDRDY = %d, MU_RX_CNT = %d, RX_FIFO_FULL = %d\n", + (unsigned int)prEventAccessRxStat->au4Buffer[0], + (unsigned int)prEventAccessRxStat->au4Buffer[1], + (unsigned int)prEventAccessRxStat->au4Buffer[65], + (unsigned int)prEventAccessRxStat->au4Buffer[22]); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} + +#if CFG_SUPPORT_TX_BF +void nicCmdEventPfmuDataRead(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct GLUE_INFO *prGlueInfo; + union PFMU_DATA *prEventPfmuDataRead = NULL; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventPfmuDataRead = (union PFMU_DATA *) (pucEventBuf); + + u4QueryInfoLen = sizeof(union PFMU_DATA); + + g_rPfmuData = *prEventPfmuDataRead; + } + + DBGLOG(INIT, INFO, "=========== Before ===========\n"); + if (prEventPfmuDataRead != NULL) { + DBGLOG(INIT, INFO, "u2Phi11 = 0x%x\n", + prEventPfmuDataRead->rField.u2Phi11); + DBGLOG(INIT, INFO, "ucPsi21 = 0x%x\n", + prEventPfmuDataRead->rField.ucPsi21); + DBGLOG(INIT, INFO, "u2Phi21 = 0x%x\n", + prEventPfmuDataRead->rField.u2Phi21); + DBGLOG(INIT, INFO, "ucPsi31 = 0x%x\n", + prEventPfmuDataRead->rField.ucPsi31); + DBGLOG(INIT, INFO, "u2Phi31 = 0x%x\n", + prEventPfmuDataRead->rField.u2Phi31); + DBGLOG(INIT, INFO, "ucPsi41 = 0x%x\n", + prEventPfmuDataRead->rField.ucPsi41); + DBGLOG(INIT, INFO, "u2Phi22 = 0x%x\n", + prEventPfmuDataRead->rField.u2Phi22); + DBGLOG(INIT, INFO, "ucPsi32 = 0x%x\n", + prEventPfmuDataRead->rField.ucPsi32); + DBGLOG(INIT, INFO, "u2Phi32 = 0x%x\n", + prEventPfmuDataRead->rField.u2Phi32); + DBGLOG(INIT, INFO, "ucPsi42 = 0x%x\n", + prEventPfmuDataRead->rField.ucPsi42); + DBGLOG(INIT, INFO, "u2Phi33 = 0x%x\n", + prEventPfmuDataRead->rField.u2Phi33); + DBGLOG(INIT, INFO, "ucPsi43 = 0x%x\n", + prEventPfmuDataRead->rField.ucPsi43); + DBGLOG(INIT, INFO, "u2dSNR00 = 0x%x\n", + prEventPfmuDataRead->rField.u2dSNR00); + DBGLOG(INIT, INFO, "u2dSNR01 = 0x%x\n", + prEventPfmuDataRead->rField.u2dSNR01); + DBGLOG(INIT, INFO, "u2dSNR02 = 0x%x\n", + prEventPfmuDataRead->rField.u2dSNR02); + DBGLOG(INIT, INFO, "u2dSNR03 = 0x%x\n", + prEventPfmuDataRead->rField.u2dSNR03); + } +} + +void nicCmdEventPfmuTagRead(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct GLUE_INFO *prGlueInfo; + struct EVENT_PFMU_TAG_READ *prEventPfmuTagRead = NULL; + struct PARAM_CUSTOM_PFMU_TAG_READ_STRUCT *prPfumTagRead = + NULL; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + if (!pucEventBuf) { + DBGLOG(INIT, ERROR, "pucEventBuf is NULL.\n"); + return; + } + if (!prCmdInfo->pvInformationBuffer) { + DBGLOG(INIT, ERROR, + "prCmdInfo->pvInformationBuffer is NULL.\n"); + return; + } + /* 4 <2> Update information of OID */ + if (!prCmdInfo->fgIsOid) { + DBGLOG(INIT, ERROR, "cmd %u seq #%u not oid!", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + return; + } + prGlueInfo = prAdapter->prGlueInfo; + prEventPfmuTagRead = (struct EVENT_PFMU_TAG_READ *) ( + pucEventBuf); + + prPfumTagRead = (struct PARAM_CUSTOM_PFMU_TAG_READ_STRUCT *) + prCmdInfo->pvInformationBuffer; + + kalMemCopy(prPfumTagRead, prEventPfmuTagRead, + sizeof(struct EVENT_PFMU_TAG_READ)); + + u4QueryInfoLen = sizeof(union CMD_TXBF_ACTION); + + g_rPfmuTag1 = prPfumTagRead->ru4TxBfPFMUTag1; + g_rPfmuTag2 = prPfumTagRead->ru4TxBfPFMUTag2; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + + DBGLOG(INIT, INFO, + "========================== (R)Tag1 info ==========================\n"); + + DBGLOG(INIT, INFO, + " Row data0 : %x, Row data1 : %x, Row data2 : %x, Row data3 : %x\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.au4RawData[0], + prEventPfmuTagRead->ru4TxBfPFMUTag1.au4RawData[1], + prEventPfmuTagRead->ru4TxBfPFMUTag1.au4RawData[2], + prEventPfmuTagRead->ru4TxBfPFMUTag1.au4RawData[3]); + DBGLOG(INIT, INFO, "ProfileID = %d Invalid status = %d\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucProfileID, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucInvalidProf); + DBGLOG(INIT, INFO, "0:iBF / 1:eBF = %d\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucTxBf); + DBGLOG(INIT, INFO, "0:SU / 1:MU = %d\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucSU_MU); + DBGLOG(INIT, INFO, "DBW(0/1/2/3 BW20/40/80/160NC) = %d\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucDBW); + DBGLOG(INIT, INFO, "RMSD = %d\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucRMSD); + DBGLOG(INIT, INFO, + "Nrow = %d, Ncol = %d, Ng = %d, LM = %d\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucNrow, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucNcol, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucNgroup, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucLM); + DBGLOG(INIT, INFO, + "Mem1(%d, %d), Mem2(%d, %d), Mem3(%d, %d), Mem4(%d, %d)\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr1ColIdx, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr1RowIdx, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr2ColIdx, + (prEventPfmuTagRead->ru4TxBfPFMUTag1. + rField.ucMemAddr2RowIdx | + (prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr2RowIdxMsb + << 5)), + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr3ColIdx, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr3RowIdx, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr4ColIdx, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr4RowIdx); + DBGLOG(INIT, INFO, + "SNR STS0=0x%x, SNR STS1=0x%x, SNR STS2=0x%x, SNR STS3=0x%x\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucSNR_STS0, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucSNR_STS1, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucSNR_STS2, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucSNR_STS3); + DBGLOG(INIT, INFO, + "===============================================================\n"); + + DBGLOG(INIT, INFO, + "========================== (R)Tag2 info ==========================\n"); + DBGLOG(INIT, INFO, + " Row data0 : %x, Row data1 : %x, Row data2 : %x\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.au4RawData[0], + prEventPfmuTagRead->ru4TxBfPFMUTag2.au4RawData[1], + prEventPfmuTagRead->ru4TxBfPFMUTag2.au4RawData[2]); + DBGLOG(INIT, INFO, "Smart Ant Cfg = %d\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.u2SmartAnt); + DBGLOG(INIT, INFO, "SE index = %d\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucSEIdx); + DBGLOG(INIT, INFO, "RMSD Threshold = %d\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucRMSDThd); + DBGLOG(INIT, INFO, + "MCS TH L1SS = %d, S1SS = %d, L2SS = %d, S2SS = %d\n" + "L3SS = %d, S3SS = %d\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucMCSThL1SS, + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucMCSThS1SS, + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucMCSThL2SS, + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucMCSThS2SS, + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucMCSThL3SS, + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucMCSThS3SS); + DBGLOG(INIT, INFO, "iBF lifetime limit(unit:4ms) = 0x%x\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.uciBfTimeOut); + DBGLOG(INIT, INFO, + "iBF desired DBW = %d\n 0/1/2/3 : BW20/40/80/160NC\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.uciBfDBW); + DBGLOG(INIT, INFO, + "iBF desired Ncol = %d\n 0/1/2 : Ncol = 1 ~ 3\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.uciBfNcol); + DBGLOG(INIT, INFO, + "iBF desired Nrow = %d\n 0/1/2/3 : Nrow = 1 ~ 4\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.uciBfNrow); + DBGLOG(INIT, INFO, + "===============================================================\n"); + +} + +#endif /* CFG_SUPPORT_TX_BF */ +#if CFG_SUPPORT_MU_MIMO +void nicCmdEventGetQd(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct GLUE_INFO *prGlueInfo; + struct EVENT_HQA_GET_QD *prEventHqaGetQd; + uint32_t i; + + struct PARAM_CUSTOM_GET_QD_STRUCT *prGetQd = NULL; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + if (!pucEventBuf) { + DBGLOG(INIT, ERROR, "pucEventBuf is NULL.\n"); + return; + } + if (!prCmdInfo->pvInformationBuffer) { + DBGLOG(INIT, ERROR, + "prCmdInfo->pvInformationBuffer is NULL.\n"); + return; + } + /* 4 <2> Update information of OID */ + if (!prCmdInfo->fgIsOid) { + DBGLOG(INIT, ERROR, "cmd %u seq #%u not oid!\n", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + return; + } + prGlueInfo = prAdapter->prGlueInfo; + prEventHqaGetQd = (struct EVENT_HQA_GET_QD *) (pucEventBuf); + + prGetQd = (struct PARAM_CUSTOM_GET_QD_STRUCT *) + prCmdInfo->pvInformationBuffer; + + kalMemCopy(prGetQd, prEventHqaGetQd, + sizeof(struct EVENT_HQA_GET_QD)); + + u4QueryInfoLen = sizeof(union CMD_MUMIMO_ACTION); + + /* g_rPfmuTag1 = prPfumTagRead->ru4TxBfPFMUTag1; */ + /* g_rPfmuTag2 = prPfumTagRead->ru4TxBfPFMUTag2; */ + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + + DBGLOG(INIT, INFO, " event id : %x\n", prGetQd->u4EventId); + for (i = 0; i < 14; i++) + DBGLOG(INIT, INFO, "au4RawData[%d]: %x\n", i, + prGetQd->au4RawData[i]); + +} + +void nicCmdEventGetCalcLq(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct GLUE_INFO *prGlueInfo; + struct EVENT_HQA_GET_MU_CALC_LQ *prEventHqaGetMuCalcLq; + uint32_t i, j; + + struct PARAM_CUSTOM_GET_MU_CALC_LQ_STRUCT *prGetMuCalcLq = + NULL; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + if (!pucEventBuf) { + DBGLOG(INIT, ERROR, "pucEventBuf is NULL.\n"); + return; + } + if (!prCmdInfo->pvInformationBuffer) { + DBGLOG(INIT, ERROR, + "prCmdInfo->pvInformationBuffer is NULL.\n"); + return; + } + /* 4 <2> Update information of OID */ + if (!prCmdInfo->fgIsOid) { + DBGLOG(INIT, ERROR, "cmd %u seq #%u not oid!\n", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + return; + } + prGlueInfo = prAdapter->prGlueInfo; + prEventHqaGetMuCalcLq = (struct EVENT_HQA_GET_MU_CALC_LQ *) + (pucEventBuf); + + prGetMuCalcLq = (struct PARAM_CUSTOM_GET_MU_CALC_LQ_STRUCT + *) prCmdInfo->pvInformationBuffer; + + kalMemCopy(prGetMuCalcLq, prEventHqaGetMuCalcLq, + sizeof(struct EVENT_HQA_GET_MU_CALC_LQ)); + + u4QueryInfoLen = sizeof(union CMD_MUMIMO_ACTION); + + /* g_rPfmuTag1 = prPfumTagRead->ru4TxBfPFMUTag1; */ + /* g_rPfmuTag2 = prPfumTagRead->ru4TxBfPFMUTag2; */ + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + + + DBGLOG(INIT, INFO, " event id : %x\n", + prGetMuCalcLq->u4EventId); + for (i = 0; i < NUM_OF_USER; i++) + for (j = 0; j < NUM_OF_MODUL; j++) + DBGLOG(INIT, INFO, " lq_report[%d][%d]: %x\n", i, j, + prGetMuCalcLq->rEntry.lq_report[i][j]); + +} + +void nicCmdEventGetCalcInitMcs(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct GLUE_INFO *prGlueInfo; + struct EVENT_SHOW_GROUP_TBL_ENTRY *prEventShowGroupTblEntry + = NULL; + + struct PARAM_CUSTOM_SHOW_GROUP_TBL_ENTRY_STRUCT + *prShowGroupTbl; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + if (!pucEventBuf) { + DBGLOG(INIT, ERROR, "pucEventBuf is NULL.\n"); + return; + } + if (!prCmdInfo->pvInformationBuffer) { + DBGLOG(INIT, ERROR, + "prCmdInfo->pvInformationBuffer is NULL.\n"); + return; + } + /* 4 <2> Update information of OID */ + if (!prCmdInfo->fgIsOid) { + DBGLOG(INIT, ERROR, "cmd %u seq #%u not oid!\n", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + return; + } + prGlueInfo = prAdapter->prGlueInfo; + prEventShowGroupTblEntry = (struct + EVENT_SHOW_GROUP_TBL_ENTRY *) (pucEventBuf); + + prShowGroupTbl = (struct + PARAM_CUSTOM_SHOW_GROUP_TBL_ENTRY_STRUCT *) + prCmdInfo->pvInformationBuffer; + + kalMemCopy(prShowGroupTbl, prEventShowGroupTblEntry, + sizeof(struct EVENT_SHOW_GROUP_TBL_ENTRY)); + + u4QueryInfoLen = sizeof(union CMD_MUMIMO_ACTION); + + /* g_rPfmuTag1 = prPfumTagRead->ru4TxBfPFMUTag1; */ + /* g_rPfmuTag2 = prPfumTagRead->ru4TxBfPFMUTag2; */ + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + + + DBGLOG(INIT, INFO, + "========================== (R)Group table info ==========================\n"); + DBGLOG(INIT, INFO, " event id : %x\n", + prEventShowGroupTblEntry->u4EventId); + DBGLOG(INIT, INFO, "index = %x numUser = %x\n", + prEventShowGroupTblEntry->index, + prEventShowGroupTblEntry->numUser); + DBGLOG(INIT, INFO, "BW = %x NS0/1/ = %x/%x\n", + prEventShowGroupTblEntry->BW, prEventShowGroupTblEntry->NS0, + prEventShowGroupTblEntry->NS1); + DBGLOG(INIT, INFO, "PFIDUser0/1 = %x/%x\n", + prEventShowGroupTblEntry->PFIDUser0, + prEventShowGroupTblEntry->PFIDUser1); + DBGLOG(INIT, INFO, + "fgIsShortGI = %x, fgIsUsed = %x, fgIsDisable = %x\n", + prEventShowGroupTblEntry->fgIsShortGI, + prEventShowGroupTblEntry->fgIsUsed, + prEventShowGroupTblEntry->fgIsDisable); + DBGLOG(INIT, INFO, "initMcsUser0/1 = %x/%x\n", + prEventShowGroupTblEntry->initMcsUser0, + prEventShowGroupTblEntry->initMcsUser1); + DBGLOG(INIT, INFO, "dMcsUser0: 0/1/ = %x/%x\n", + prEventShowGroupTblEntry->dMcsUser0, + prEventShowGroupTblEntry->dMcsUser1); + +} +#endif /* CFG_SUPPORT_MU_MIMO */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +void nicCmdEventQuerySwCtrlRead(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct PARAM_CUSTOM_SW_CTRL_STRUCT *prSwCtrlInfo; + struct GLUE_INFO *prGlueInfo; + struct CMD_SW_DBG_CTRL *prCmdSwCtrl; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prCmdSwCtrl = (struct CMD_SW_DBG_CTRL *) (pucEventBuf); + + u4QueryInfoLen = sizeof(struct PARAM_CUSTOM_SW_CTRL_STRUCT); + + prSwCtrlInfo = (struct PARAM_CUSTOM_SW_CTRL_STRUCT *) + prCmdInfo->pvInformationBuffer; + prSwCtrlInfo->u4Id = prCmdSwCtrl->u4Id; + prSwCtrlInfo->u4Data = prCmdSwCtrl->u4Data; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} + +void nicCmdEventQueryChipConfig(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct PARAM_CUSTOM_CHIP_CONFIG_STRUCT *prChipConfigInfo; + struct GLUE_INFO *prGlueInfo; + struct CMD_CHIP_CONFIG *prCmdChipConfig; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prCmdChipConfig = (struct CMD_CHIP_CONFIG *) (pucEventBuf); + + u4QueryInfoLen = sizeof(struct + PARAM_CUSTOM_CHIP_CONFIG_STRUCT); + + if (prCmdInfo->u4InformationBufferLength < sizeof( + struct PARAM_CUSTOM_CHIP_CONFIG_STRUCT)) { + DBGLOG(REQ, INFO, + "Chip config u4InformationBufferLength %u is not valid (event)\n", + prCmdInfo->u4InformationBufferLength); + } + prChipConfigInfo = (struct PARAM_CUSTOM_CHIP_CONFIG_STRUCT + *) prCmdInfo->pvInformationBuffer; + prChipConfigInfo->ucRespType = prCmdChipConfig->ucRespType; + prChipConfigInfo->u2MsgSize = prCmdChipConfig->u2MsgSize; + DBGLOG(REQ, INFO, "%s: RespTyep %u\n", __func__, + prChipConfigInfo->ucRespType); + DBGLOG(REQ, INFO, "%s: u2MsgSize %u\n", __func__, + prChipConfigInfo->u2MsgSize); + + if (prChipConfigInfo->u2MsgSize > CHIP_CONFIG_RESP_SIZE) { + DBGLOG(REQ, WARN, + "Chip config Msg Size %u is not valid (event)\n", + prChipConfigInfo->u2MsgSize); + prChipConfigInfo->u2MsgSize = CHIP_CONFIG_RESP_SIZE; + } + + kalMemCopy(prChipConfigInfo->aucCmd, + prCmdChipConfig->aucCmd, prChipConfigInfo->u2MsgSize); + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} + +void nicCmdEventSetCommon(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, + prCmdInfo->u4InformationBufferLength, WLAN_STATUS_SUCCESS); + } + +} + +void nicCmdEventSetDisassociate(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information 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 + +} + +void nicCmdEventSetIpAddress(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + uint32_t u4Count; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + u4Count = (prCmdInfo->u4SetInfoLen - OFFSET_OF( + struct CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress)) + / sizeof(struct IPV4_NETWORK_ADDRESS); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + OFFSET_OF(struct PARAM_NETWORK_ADDRESS_LIST, + arAddress) + u4Count * + (OFFSET_OF(struct PARAM_NETWORK_ADDRESS, aucAddress) + + sizeof(struct PARAM_NETWORK_ADDRESS_IP)), + WLAN_STATUS_SUCCESS); + } + +} + +void nicCmdEventQueryRfTestATInfo(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + union EVENT_TEST_STATUS *prTestStatus, *prQueryBuffer; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prTestStatus = (union EVENT_TEST_STATUS *) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prQueryBuffer = (union EVENT_TEST_STATUS *) + prCmdInfo->pvInformationBuffer; + + /* Memory copy length is depended on upper-layer */ + kalMemCopy(prQueryBuffer, prTestStatus, + prCmdInfo->u4InformationBufferLength); + + u4QueryInfoLen = sizeof(union EVENT_TEST_STATUS); + + /* Update Query Information Length */ + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} + +void nicCmdEventQueryLinkQuality(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + int32_t rRssi, *prRssi; + struct EVENT_LINK_QUALITY *prLinkQuality; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prLinkQuality = (struct EVENT_LINK_QUALITY *) pucEventBuf; + + /* ranged from (-128 ~ 30) in unit of dBm */ + rRssi = (int32_t) prLinkQuality->cRssi; + + if (prAdapter->prAisBssInfo->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; + } + + prGlueInfo = prAdapter->prGlueInfo; + prRssi = (int32_t *) prCmdInfo->pvInformationBuffer; + + kalMemCopy(prRssi, &rRssi, sizeof(int32_t)); + u4QueryInfoLen = sizeof(int32_t); + + if (prCmdInfo->fgIsOid) { + 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 struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct EVENT_LINK_QUALITY *prLinkQuality; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; + uint32_t *pu4LinkSpeed; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prLinkQuality = (struct EVENT_LINK_QUALITY *) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + pu4LinkSpeed = (uint32_t *) ( + prCmdInfo->pvInformationBuffer); + + *pu4LinkSpeed = prLinkQuality->u2LinkSpeed * 5000; + + u4QueryInfoLen = sizeof(uint32_t); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +void nicCmdEventQueryStatistics(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + struct PARAM_802_11_STATISTICS_STRUCT *prStatistics; + struct EVENT_STATISTICS *prEventStatistics; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (struct EVENT_STATISTICS *) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + u4QueryInfoLen = sizeof(struct + PARAM_802_11_STATISTICS_STRUCT); + prStatistics = (struct PARAM_802_11_STATISTICS_STRUCT *) + prCmdInfo->pvInformationBuffer; + + prStatistics->rTransmittedFragmentCount = + prEventStatistics->rTransmittedFragmentCount; + prStatistics->rFailedCount = + prEventStatistics->rFailedCount; + prStatistics->rRetryCount = prEventStatistics->rRetryCount; + prStatistics->rMultipleRetryCount = + prEventStatistics->rMultipleRetryCount; + prStatistics->rACKFailureCount = + prEventStatistics->rACKFailureCount; + prStatistics->rReceivedFragmentCount = + prEventStatistics->rReceivedFragmentCount; + prStatistics->rFCSErrorCount = + prEventStatistics->rFCSErrorCount; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +void nicCmdEventQueryBugReport(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ +#define BUG_REPORT_VERSION 1 + + struct _EVENT_BUG_REPORT_T *prStatistics; + struct _EVENT_BUG_REPORT_T *prEventStatistics; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (struct _EVENT_BUG_REPORT_T *) + pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + u4QueryInfoLen = sizeof(struct _EVENT_BUG_REPORT_T); + if (prEventStatistics->u4BugReportVersion == + BUG_REPORT_VERSION) { + prStatistics = (struct _EVENT_BUG_REPORT_T *) + prCmdInfo->pvInformationBuffer; + kalMemCopy(prStatistics, + prEventStatistics, u4QueryInfoLen); + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +void nicCmdEventEnterRfTest(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + /* [driver-land] */ + /* prAdapter->fgTestMode = TRUE; */ + if (prAdapter->fgTestMode) + prAdapter->fgTestMode = FALSE; + else + 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, TRUE); + + /* 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); + + /* Block til firmware completed entering into RF test mode */ + kalMsleep(500); + +#if defined(_HIF_SDIO) && 0 + /* 3. Disable Interrupt */ + HAL_INTR_DISABLE(prAdapter); + + /* 4. Block til firmware completed entering into RF test mode */ + kalMsleep(500); + while (1) { + uint32_t u4Value; + + 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 Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4SetInfoLen, + WLAN_STATUS_NOT_SUPPORTED); + + } + return; + } + kalMsleep(10); + } + + /* 5. Clear Interrupt Status */ + { + uint32_t u4WHISR = 0; + uint16_t au2TxCount[16]; + + HAL_READ_INTR_STATUS(prAdapter, 4, (uint8_t *)&u4WHISR); + if (HAL_IS_TX_DONE_INTR(u4WHISR)) + HAL_READ_TX_RELEASED_COUNT(prAdapter, au2TxCount); + } + /* 6. Reset TX Counter */ + nicTxResetResource(prAdapter); + + /* 7. Re-enable Interrupt */ + HAL_INTR_ENABLE(prAdapter); +#endif + + /* 8. completion indication */ + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, + WLAN_STATUS_SUCCESS); + } +#if CFG_SUPPORT_NVRAM + /* 9. load manufacture data */ + if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) + wlanLoadManufactureData(prAdapter, + kalGetConfiguration(prAdapter->prGlueInfo)); + else + DBGLOG(REQ, WARN, "%s: load manufacture data fail\n", + __func__); +#endif + +} + +void nicCmdEventLeaveRfTest(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + /* Block until firmware completed leaving from RF test mode */ + kalMsleep(500); + +#if defined(_HIF_SDIO) && 0 + uint32_t u4WHISR = 0; + uint16_t au2TxCount[16]; + uint32_t u4Value; + + /* 1. Disable Interrupt */ + HAL_INTR_DISABLE(prAdapter); + + /* 2. Block until 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 Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4SetInfoLen, + WLAN_STATUS_NOT_SUPPORTED); + + } + return; + } + kalMsleep(10); + } + /* 3. Clear Interrupt Status */ + HAL_READ_INTR_STATUS(prAdapter, 4, (uint8_t *)&u4WHISR); + if (HAL_IS_TX_DONE_INTR(u4WHISR)) + HAL_READ_TX_RELEASED_COUNT(prAdapter, au2TxCount); + /* 4. Reset TX Counter */ + nicTxResetResource(prAdapter); + + /* 5. Re-enable Interrupt */ + HAL_INTR_ENABLE(prAdapter); +#endif + + /* 6. set driver-land variable */ + prAdapter->fgTestMode = FALSE; + prAdapter->fgIcapMode = FALSE; + + /* 7. completion indication */ + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, + WLAN_STATUS_SUCCESS); + } + + /* 8. Indicate as disconnected */ + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != + PARAM_MEDIA_STATE_DISCONNECTED) { + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + + prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); + } +#if CFG_SUPPORT_NVRAM + /* 9. load manufacture data */ + if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) + wlanLoadManufactureData(prAdapter, + kalGetConfiguration(prAdapter->prGlueInfo)); + else + DBGLOG(REQ, WARN, "%s: load manufacture data fail\n", + __func__); +#endif + + /* 10. Override network address */ + wlanUpdateNetworkAddress(prAdapter); + +} + +void nicCmdEventQueryMcastAddr(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct GLUE_INFO *prGlueInfo; + struct CMD_MAC_MCAST_ADDR *prEventMacMcastAddr; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventMacMcastAddr = (struct CMD_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 struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct PARAM_CUSTOM_EEPROM_RW_STRUCT *prEepromRdInfo; + struct GLUE_INFO *prGlueInfo; + struct CMD_ACCESS_EEPROM *prEventAccessEeprom; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventAccessEeprom = (struct CMD_ACCESS_EEPROM *) ( + pucEventBuf); + + u4QueryInfoLen = sizeof(struct + PARAM_CUSTOM_EEPROM_RW_STRUCT); + + prEepromRdInfo = (struct PARAM_CUSTOM_EEPROM_RW_STRUCT *) + prCmdInfo->pvInformationBuffer; + prEepromRdInfo->ucEepromIndex = (uint8_t) ( + prEventAccessEeprom->u2Offset); + prEepromRdInfo->u2EepromData = prEventAccessEeprom->u2Data; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} + +void nicCmdEventSetMediaStreamMode(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + struct PARAM_MEDIA_STREAMING_INDICATION + rParamMediaStreamIndication; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, + WLAN_STATUS_SUCCESS); + } + + rParamMediaStreamIndication.rStatus.eStatusType = + ENUM_STATUS_TYPE_MEDIA_STREAM_MODE; + rParamMediaStreamIndication.eMediaStreamMode = + prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode == 0 ? + ENUM_MEDIA_STREAM_OFF : ENUM_MEDIA_STREAM_ON; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (void *)&rParamMediaStreamIndication, + sizeof(struct PARAM_MEDIA_STREAMING_INDICATION)); +} + +void nicCmdEventSetStopSchedScan(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + /* + * DBGLOG(SCN, INFO, "--->nicCmdEventSetStopSchedScan\n" )); + */ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + /* + * DBGLOG(SCN, INFO, "<--kalSchedScanStopped\n" ); + */ + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4InformationBufferLength, + WLAN_STATUS_SUCCESS); + } + + DBGLOG(SCN, INFO, + "nicCmdEventSetStopSchedScan OID done, release lock and send event to uplayer\n"); + /* Due to dead lock issue, need to release the IO + * control before calling kernel APIs + */ + kalSchedScanStopped(prAdapter->prGlueInfo, + !prCmdInfo->fgIsOid); + +} + +/* Statistics responder */ +void nicCmdEventQueryXmitOk(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct EVENT_STATISTICS *prEventStatistics; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; + uint32_t *pu4Data; + uint64_t *pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (struct EVENT_STATISTICS *) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof( + uint32_t)) { + u4QueryInfoLen = sizeof(uint32_t); + + pu4Data = (uint32_t *) prCmdInfo->pvInformationBuffer; + *pu4Data = (uint32_t) + prEventStatistics-> + rTransmittedFragmentCount.QuadPart; + } else { + u4QueryInfoLen = sizeof(uint64_t); + + pu8Data = (uint64_t *) prCmdInfo->pvInformationBuffer; + *pu8Data = + prEventStatistics-> + rTransmittedFragmentCount.QuadPart; + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +void nicCmdEventQueryRecvOk(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct EVENT_STATISTICS *prEventStatistics; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; + uint32_t *pu4Data; + uint64_t *pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (struct EVENT_STATISTICS *) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof( + uint32_t)) { + u4QueryInfoLen = sizeof(uint32_t); + + pu4Data = (uint32_t *) prCmdInfo->pvInformationBuffer; + *pu4Data = (uint32_t) + prEventStatistics-> + rReceivedFragmentCount.QuadPart; + } else { + u4QueryInfoLen = sizeof(uint64_t); + + pu8Data = (uint64_t *) prCmdInfo->pvInformationBuffer; + *pu8Data = + prEventStatistics-> + rReceivedFragmentCount.QuadPart; + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +void nicCmdEventQueryXmitError(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct EVENT_STATISTICS *prEventStatistics; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; + uint32_t *pu4Data; + uint64_t *pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (struct EVENT_STATISTICS *) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof( + uint32_t)) { + u4QueryInfoLen = sizeof(uint32_t); + + pu4Data = (uint32_t *) prCmdInfo->pvInformationBuffer; + *pu4Data = (uint32_t) + prEventStatistics->rFailedCount.QuadPart; + } else { + u4QueryInfoLen = sizeof(uint64_t); + + pu8Data = (uint64_t *) prCmdInfo->pvInformationBuffer; + *pu8Data = (uint64_t) + prEventStatistics->rFailedCount.QuadPart; + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +void nicCmdEventQueryRecvError(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct EVENT_STATISTICS *prEventStatistics; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; + uint32_t *pu4Data; + uint64_t *pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (struct EVENT_STATISTICS *) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof( + uint32_t)) { + u4QueryInfoLen = sizeof(uint32_t); + + pu4Data = (uint32_t *) prCmdInfo->pvInformationBuffer; + *pu4Data = (uint32_t) + prEventStatistics->rFCSErrorCount.QuadPart; + /* @FIXME, RX_ERROR_DROP_COUNT/RX_FIFO_FULL_DROP_COUNT + * is not calculated + */ + } else { + u4QueryInfoLen = sizeof(uint64_t); + + pu8Data = (uint64_t *) 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 struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + struct EVENT_STATISTICS *prEventStatistics; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; + uint32_t *pu4Data; + uint64_t *pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (struct EVENT_STATISTICS *) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof( + uint32_t)) { + u4QueryInfoLen = sizeof(uint32_t); + + pu4Data = (uint32_t *) prCmdInfo->pvInformationBuffer; + *pu4Data = 0; /* @FIXME? */ + } else { + u4QueryInfoLen = sizeof(uint64_t); + + pu8Data = (uint64_t *) prCmdInfo->pvInformationBuffer; + *pu8Data = 0; /* @FIXME? */ + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +void nicCmdEventQueryRecvCrcError(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + struct EVENT_STATISTICS *prEventStatistics; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; + uint32_t *pu4Data; + uint64_t *pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (struct EVENT_STATISTICS *) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof( + uint32_t)) { + u4QueryInfoLen = sizeof(uint32_t); + + pu4Data = (uint32_t *) prCmdInfo->pvInformationBuffer; + *pu4Data = (uint32_t) + prEventStatistics->rFCSErrorCount.QuadPart; + } else { + u4QueryInfoLen = sizeof(uint64_t); + + pu8Data = (uint64_t *) prCmdInfo->pvInformationBuffer; + *pu8Data = prEventStatistics->rFCSErrorCount.QuadPart; + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +void nicCmdEventQueryRecvErrorAlignment(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + struct EVENT_STATISTICS *prEventStatistics; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; + uint32_t *pu4Data; + uint64_t *pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (struct EVENT_STATISTICS *) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof( + uint32_t)) { + u4QueryInfoLen = sizeof(uint32_t); + + pu4Data = (uint32_t *) prCmdInfo->pvInformationBuffer; + *pu4Data = (uint32_t) 0; /* @FIXME */ + } else { + u4QueryInfoLen = sizeof(uint64_t); + + pu8Data = (uint64_t *) prCmdInfo->pvInformationBuffer; + *pu8Data = 0; /* @FIXME */ + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +void nicCmdEventQueryXmitOneCollision(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + struct EVENT_STATISTICS *prEventStatistics; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; + uint32_t *pu4Data; + uint64_t *pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (struct EVENT_STATISTICS *) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof( + uint32_t)) { + u4QueryInfoLen = sizeof(uint32_t); + + pu4Data = (uint32_t *) prCmdInfo->pvInformationBuffer; + *pu4Data = + (uint32_t) + (prEventStatistics->rMultipleRetryCount.QuadPart + - prEventStatistics->rRetryCount.QuadPart); + } else { + u4QueryInfoLen = sizeof(uint64_t); + + pu8Data = (uint64_t *) prCmdInfo->pvInformationBuffer; + *pu8Data = + (uint64_t) + (prEventStatistics->rMultipleRetryCount.QuadPart + - prEventStatistics->rRetryCount.QuadPart); + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +void nicCmdEventQueryXmitMoreCollisions(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + struct EVENT_STATISTICS *prEventStatistics; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; + uint32_t *pu4Data; + uint64_t *pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (struct EVENT_STATISTICS *) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof( + uint32_t)) { + u4QueryInfoLen = sizeof(uint32_t); + + pu4Data = (uint32_t *) prCmdInfo->pvInformationBuffer; + *pu4Data = (uint32_t) + prEventStatistics->rMultipleRetryCount.QuadPart; + } else { + u4QueryInfoLen = sizeof(uint64_t); + + pu8Data = (uint64_t *) prCmdInfo->pvInformationBuffer; + *pu8Data = (uint64_t) + prEventStatistics->rMultipleRetryCount.QuadPart; + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +void nicCmdEventQueryXmitMaxCollisions(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + struct EVENT_STATISTICS *prEventStatistics; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; + uint32_t *pu4Data; + uint64_t *pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (struct EVENT_STATISTICS *) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof( + uint32_t)) { + u4QueryInfoLen = sizeof(uint32_t); + + pu4Data = (uint32_t *) prCmdInfo->pvInformationBuffer; + *pu4Data = (uint32_t) + prEventStatistics->rFailedCount.QuadPart; + } else { + u4QueryInfoLen = sizeof(uint64_t); + + pu8Data = (uint64_t *) prCmdInfo->pvInformationBuffer; + *pu8Data = (uint64_t) + 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 struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo) +{ + ASSERT(prAdapter); + + if (prCmdInfo->fgIsOid) + 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 struct ADAPTER *prAdapter, + IN struct CMD_INFO *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 struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo) +{ + ASSERT(prAdapter); + + /* 1. Remove pending TX frames */ + nicTxRelease(prAdapter, TRUE); + + /* 1.1 clear pending Security / Management Frames */ + kalClearSecurityFrames(prAdapter->prGlueInfo); + kalClearMgmtFrames(prAdapter->prGlueInfo); + + /* 1.2 clear pending TX packet queued in glue layer */ + kalFlushPendingTxPackets(prAdapter->prGlueInfo); + + /* 2. indicate for OID failure */ + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, + 0, WLAN_STATUS_FAILURE); +} + +#if CFG_SUPPORT_QA_TOOL +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called when received dump memory event packet. + * transfer the memory data to the IQ format data and write into file + * + * @param prIQAry Pointer to the array store I or Q data. + * prDataLen The return data length - bytes + * u4IQ 0: get I data + * 1 : get Q data + * + * @return -1: open file error + * + */ +/*----------------------------------------------------------------------------*/ +int32_t GetIQData(struct ADAPTER *prAdapter, + int32_t **prIQAry, uint32_t *prDataLen, uint32_t u4IQ, + uint32_t u4GetWf1) +{ + uint8_t aucPath[50]; /* the path for iq data dump out */ + uint8_t aucData[50]; /* iq data in string format */ + uint32_t i = 0, j = 0, count = 0; + int32_t ret = -1; + int32_t rv; + struct file *file = NULL; + + *prIQAry = prAdapter->rIcapInfo.au4IQData; + + /* sprintf(aucPath, "/pattern.txt"); // CSD's Pattern */ + snprintf(aucPath, + sizeof(aucPath), "/tmp/dump_out_%05hu_WF%u.txt", + prAdapter->rIcapInfo.u2DumpIndex - 1, u4GetWf1); + if (kalCheckPath(aucPath) == -1) { + snprintf(aucPath, sizeof(aucPath), + "/data/dump_out_%05hu_WF%u.txt", + prAdapter->rIcapInfo.u2DumpIndex - 1, u4GetWf1); + } + + DBGLOG(INIT, INFO, + "iCap Read Dump File dump_out_%05hu_WF%u.txt\n", + prAdapter->rIcapInfo.u2DumpIndex - 1, u4GetWf1); + + file = kalFileOpen(aucPath, O_RDONLY, 0); + + if ((file != NULL) && !IS_ERR(file)) { + /* read 1K data per time */ + for (i = 0; i < RTN_IQ_DATA_LEN / sizeof(uint32_t); + i++, prAdapter->rIcapInfo.au4Offset[u4GetWf1][u4IQ] += + IQ_FILE_LINE_OFFSET) { + if (kalFileRead(file, + prAdapter->rIcapInfo.au4Offset[u4GetWf1][u4IQ], + aucData, IQ_FILE_IQ_STR_LEN) == 0) + break; + + count = 0; + + for (j = 0; j < 8; j++) { + if (aucData[j] != ' ') + aucData[count++] = aucData[j]; + } + + aucData[count] = '\0'; + + /* transfer data format (string to int) */ + rv = kstrtoint(aucData, 0, + &prAdapter->rIcapInfo.au4IQData[i]); + } + *prDataLen = i * sizeof(uint32_t); + kalFileClose(file); + ret = 0; + } + + DBGLOG(INIT, INFO, + "MT6632 : QA_AGENT GetIQData prDataLen = %d\n", *prDataLen); + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT GetIQData i = %d\n", + i); + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called when received dump memory event packet. + * transfer the memory data to the IQ format data and write into file + * + * @param prEventDumpMem Pointer to the event dump memory structure. + * + * @return 0: SUCCESS, -1: FAIL + * + */ +/*----------------------------------------------------------------------------*/ + +uint32_t nicTsfRawData2IqFmt(struct EVENT_DUMP_MEM + *prEventDumpMem, struct ICAP_INFO_T *prIcap) +{ + static uint8_t + aucPathWF0[40]; /* the path for iq data dump out */ + static uint8_t + aucPathWF1[40]; /* the path for iq data dump out */ + static uint8_t + aucPathRAWWF0[40]; /* the path for iq data dump out */ + static uint8_t + aucPathRAWWF1[40]; /* the path for iq data dump out */ + uint8_t *pucDataWF0 = NULL; /* the data write into file */ + uint8_t *pucDataWF1 = NULL; /* the data write into file */ + uint8_t *pucDataRAWWF0 = + NULL; /* the data write into file */ + uint8_t *pucDataRAWWF1 = + NULL; /* the data write into file */ + uint32_t u4SrcOffset; /* record the buffer offset */ + uint32_t u4FmtLen = 0; /* bus format length */ + uint32_t u4CpyLen = 0; + uint32_t u4RemainByte; + uint32_t u4DataWBufSize = 150; + uint32_t u4DataRAWWBufSize = 150; + uint32_t u4DataWLenF0 = 0; + uint32_t u4DataWLenF1 = 0; + uint32_t u4DataRAWWLenF0 = 0; + uint32_t u4DataRAWWLenF1 = 0; + + u_int8_t fgAppend; + int32_t u4Iqc160WF0Q0, u4Iqc160WF1I1; + + static uint8_t + ucDstOffset; /* for alignment. bcs we send 2KB data per packet,*/ + /*the data will not align in 12 bytes case. */ + static uint32_t u4CurTimeTick; + + static union ICAP_BUS_FMT icapBusData; + uint32_t *ptr; + + pucDataWF0 = kmalloc(u4DataWBufSize, GFP_KERNEL); + pucDataWF1 = kmalloc(u4DataWBufSize, GFP_KERNEL); + pucDataRAWWF0 = kmalloc(u4DataRAWWBufSize, GFP_KERNEL); + pucDataRAWWF1 = kmalloc(u4DataRAWWBufSize, GFP_KERNEL); + + + if ((!pucDataWF0) || (!pucDataWF1) || (!pucDataRAWWF0) + || (!pucDataRAWWF1)) { + DBGLOG(INIT, ERROR, "kmalloc failed.\n"); + kfree(pucDataWF0); + kfree(pucDataWF1); + kfree(pucDataRAWWF0); + kfree(pucDataRAWWF1); + ASSERT(-1); + return -1; + } + + fgAppend = TRUE; + if (prEventDumpMem->ucFragNum == 1) { + + u4CurTimeTick = kalGetTimeTick(); + /* Store memory dump into sdcard, + * path /sdcard/dump__ + * _.hex + */ +#if defined(LINUX) + + /* if blbist mkdir undre /data/blbist, + * the dump files wouls put on it + */ + scnprintf(aucPathWF0, sizeof(aucPathWF0), + "/tmp/dump_out_%05hu_WF0.txt", prIcap->u2DumpIndex); + scnprintf(aucPathWF1, sizeof(aucPathWF1), + "/tmp/dump_out_%05hu_WF1.txt", prIcap->u2DumpIndex); + if (kalCheckPath(aucPathWF0) == -1) { + kalMemSet(aucPathWF0, 0x00, sizeof(aucPathWF0)); + scnprintf(aucPathWF0, sizeof(aucPathWF0), + "/data/dump_out_%05hu_WF0.txt", + prIcap->u2DumpIndex); + } else + kalTrunkPath(aucPathWF0); + + if (kalCheckPath(aucPathWF1) == -1) { + kalMemSet(aucPathWF1, 0x00, sizeof(aucPathWF1)); + scnprintf(aucPathWF1, sizeof(aucPathWF1), + "/data/dump_out_%05hu_WF1.txt", + prIcap->u2DumpIndex); + } else + kalTrunkPath(aucPathWF1); + + scnprintf(aucPathRAWWF0, sizeof(aucPathRAWWF0), + "/dump_RAW_%hu_WF0.txt", prIcap->u2DumpIndex); + scnprintf(aucPathRAWWF1, sizeof(aucPathRAWWF1), + "/dump_RAW_%hu_WF1.txt", prIcap->u2DumpIndex); + if (kalCheckPath(aucPathRAWWF0) == -1) { + kalMemSet(aucPathRAWWF0, 0x00, sizeof(aucPathRAWWF0)); + scnprintf(aucPathRAWWF0, sizeof(aucPathRAWWF0), + "/data/dump_RAW_%05hu_WF0.txt", + prIcap->u2DumpIndex); + } else + kalTrunkPath(aucPathRAWWF0); + + if (kalCheckPath(aucPathRAWWF1) == -1) { + kalMemSet(aucPathRAWWF1, 0x00, sizeof(aucPathRAWWF1)); + scnprintf(aucPathRAWWF1, sizeof(aucPathRAWWF1), + "/data/dump_RAW_%05hu_WF1.txt", + prIcap->u2DumpIndex); + } else + kalTrunkPath(aucPathRAWWF1); + +#else + kal_sprintf_ddk(aucPathWF0, sizeof(aucPathWF0), + u4CurTimeTick, prEventDumpMem->u4Address, + prEventDumpMem->u4Length + + prEventDumpMem->u4RemainLength); + kal_sprintf_ddk(aucPathWF1, sizeof(aucPathWF1), + u4CurTimeTick, prEventDumpMem->u4Address, + prEventDumpMem->u4Length + + prEventDumpMem->u4RemainLength); +#endif + /* fgAppend = FALSE; */ + } + + ptr = (uint32_t *)(&prEventDumpMem->aucBuffer[0]); + + for (u4SrcOffset = 0, + u4RemainByte = prEventDumpMem->u4Length; u4RemainByte > 0; + ) { + u4FmtLen = + (prEventDumpMem->eIcapContent + == ICAP_CONTENT_SPECTRUM) ? + sizeof(struct SPECTRUM_BUS_FMT) : sizeof(union + ICAP_BUS_FMT); + /* 4 bytes : 12 bytes */ + u4CpyLen = (u4RemainByte - u4FmtLen >= 0) ? u4FmtLen : + u4RemainByte; + + if ((ucDstOffset + u4CpyLen) > sizeof(icapBusData)) { + DBGLOG(INIT, ERROR, + "ucDstOffset(%u) + u4CpyLen(%u) exceed bound of icapBusData\n", + ucDstOffset, u4CpyLen); + kfree(pucDataWF0); + kfree(pucDataWF1); + kfree(pucDataRAWWF0); + kfree(pucDataRAWWF1); + ASSERT(-1); + return -1; + } + memcpy((uint8_t *)&icapBusData + ucDstOffset, + &prEventDumpMem->aucBuffer[0] + u4SrcOffset, u4CpyLen); +#if 0 + if (prEventDumpMem->eIcapContent == ICAP_CONTENT_ADC) { + sprintf(aucDataWF0, "%8d,%8d\n", + icapBusData.rAdcBusData.u4Dcoc0I, + icapBusData.rAdcBusData.u4Dcoc0Q); + sprintf(aucDataWF1, "%8d,%8d\n", + icapBusData.rAdcBusData.u4Dcoc1I, + icapBusData.rAdcBusData.u4Dcoc1Q); + } +#endif + if (prEventDumpMem->eIcapContent == ICAP_CONTENT_FIIQ || + prEventDumpMem->eIcapContent == ICAP_CONTENT_FDIQ) { + u4DataWLenF0 = scnprintf(pucDataWF0, u4DataWBufSize, + "%8d,%8d\n", + icapBusData.rIqcBusData.u4Iqc0I, + icapBusData.rIqcBusData.u4Iqc0Q); + u4DataWLenF1 = scnprintf(pucDataWF1, u4DataWBufSize, + "%8d,%8d\n", + icapBusData.rIqcBusData.u4Iqc1I, + icapBusData.rIqcBusData.u4Iqc1Q); + } else if (prEventDumpMem->eIcapContent - 1000 == + ICAP_CONTENT_FIIQ + || prEventDumpMem->eIcapContent - 1000 == + ICAP_CONTENT_FDIQ) { + u4Iqc160WF0Q0 = + icapBusData.rIqc160BusData.u4Iqc0Q0P1 | + (icapBusData.rIqc160BusData.u4Iqc0Q0P2 << 8); + u4Iqc160WF1I1 = + icapBusData.rIqc160BusData.u4Iqc1I1P1 | + (icapBusData.rIqc160BusData.u4Iqc1I1P2 << 4); + + u4DataWLenF0 = scnprintf(pucDataWF0, u4DataWBufSize, + "%8d,%8d\n%8d,%8d\n", + icapBusData.rIqc160BusData.u4Iqc0I0, + u4Iqc160WF0Q0, + icapBusData.rIqc160BusData.u4Iqc0I1, + icapBusData.rIqc160BusData.u4Iqc0Q1); + + u4DataWLenF1 = scnprintf(pucDataWF1, u4DataWBufSize, + "%8d,%8d\n%8d,%8d\n", + icapBusData.rIqc160BusData.u4Iqc1I0, + icapBusData.rIqc160BusData.u4Iqc1Q0, + u4Iqc160WF1I1, + icapBusData.rIqc160BusData.u4Iqc1Q1); + + } else if (prEventDumpMem->eIcapContent == + ICAP_CONTENT_SPECTRUM) { + u4DataWLenF0 = scnprintf(pucDataWF0, u4DataWBufSize, + "%8d,%8d\n", + icapBusData.rSpectrumBusData.u4DcocI, + icapBusData.rSpectrumBusData.u4DcocQ); + } else if (prEventDumpMem->eIcapContent == + ICAP_CONTENT_ADC) { + u4DataWLenF0 = scnprintf(pucDataWF0, u4DataWBufSize, + "%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n", + icapBusData.rPackedAdcBusData.u4AdcI0T0, + icapBusData.rPackedAdcBusData.u4AdcQ0T0, + icapBusData.rPackedAdcBusData.u4AdcI0T1, + icapBusData.rPackedAdcBusData.u4AdcQ0T1, + icapBusData.rPackedAdcBusData.u4AdcI0T2, + icapBusData.rPackedAdcBusData.u4AdcQ0T2, + icapBusData.rPackedAdcBusData.u4AdcI0T3, + icapBusData.rPackedAdcBusData.u4AdcQ0T3, + icapBusData.rPackedAdcBusData.u4AdcI0T4, + icapBusData.rPackedAdcBusData.u4AdcQ0T4, + icapBusData.rPackedAdcBusData.u4AdcI0T5, + icapBusData.rPackedAdcBusData.u4AdcQ0T5); + + u4DataWLenF1 = scnprintf(pucDataWF1, u4DataWBufSize, + "%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n", + icapBusData.rPackedAdcBusData.u4AdcI1T0, + icapBusData.rPackedAdcBusData.u4AdcQ1T0, + icapBusData.rPackedAdcBusData.u4AdcI1T1, + icapBusData.rPackedAdcBusData.u4AdcQ1T1, + icapBusData.rPackedAdcBusData.u4AdcI1T2, + icapBusData.rPackedAdcBusData.u4AdcQ1T2, + icapBusData.rPackedAdcBusData.u4AdcI1T3, + icapBusData.rPackedAdcBusData.u4AdcQ1T3, + icapBusData.rPackedAdcBusData.u4AdcI1T4, + icapBusData.rPackedAdcBusData.u4AdcQ1T4, + icapBusData.rPackedAdcBusData.u4AdcI1T5, + icapBusData.rPackedAdcBusData.u4AdcQ1T5); + } else if (prEventDumpMem->eIcapContent - 2000 == + ICAP_CONTENT_ADC) { + u4DataWLenF0 = scnprintf(pucDataWF0, u4DataWBufSize, + "%8d,%8d\n%8d,%8d\n%8d,%8d\n", + icapBusData.rPackedAdcBusData.u4AdcI0T0, + icapBusData.rPackedAdcBusData.u4AdcQ0T0, + icapBusData.rPackedAdcBusData.u4AdcI0T1, + icapBusData.rPackedAdcBusData.u4AdcQ0T1, + icapBusData.rPackedAdcBusData.u4AdcI0T2, + icapBusData.rPackedAdcBusData.u4AdcQ0T2); + + u4DataWLenF1 = scnprintf(pucDataWF1, u4DataWBufSize, + "%8d,%8d\n%8d,%8d\n%8d,%8d\n", + icapBusData.rPackedAdcBusData.u4AdcI1T0, + icapBusData.rPackedAdcBusData.u4AdcQ1T0, + icapBusData.rPackedAdcBusData.u4AdcI1T1, + icapBusData.rPackedAdcBusData.u4AdcQ1T1, + icapBusData.rPackedAdcBusData.u4AdcI1T2, + icapBusData.rPackedAdcBusData.u4AdcQ1T2); + } else if (prEventDumpMem->eIcapContent == + ICAP_CONTENT_TOAE) { + /* actually, this is DCOC. we take TOAE as DCOC */ + u4DataWLenF0 = scnprintf(pucDataWF0, u4DataWBufSize, + "%8d,%8d\n", + icapBusData.rAdcBusData.u4Dcoc0I, + icapBusData.rAdcBusData.u4Dcoc0Q); + u4DataWLenF1 = scnprintf(pucDataWF1, u4DataWBufSize, + "%8d,%8d\n", + icapBusData.rAdcBusData.u4Dcoc1I, + icapBusData.rAdcBusData.u4Dcoc1Q); + } + if (u4CpyLen == + u4FmtLen) { /* the data format is complete */ + kalWriteToFile(aucPathWF0, fgAppend, pucDataWF0, + u4DataWLenF0); + kalWriteToFile(aucPathWF1, fgAppend, pucDataWF1, + u4DataWLenF1); + } + ptr = (uint32_t *)(&prEventDumpMem->aucBuffer[0] + + u4SrcOffset); + u4DataRAWWLenF0 = scnprintf(pucDataRAWWF0, u4DataWBufSize, + "%08x%08x%08x\n", + *(ptr + 2), *(ptr + 1), *ptr); + kalWriteToFile(aucPathRAWWF0, fgAppend, pucDataRAWWF0, + u4DataRAWWLenF0); + kalWriteToFile(aucPathRAWWF1, fgAppend, pucDataRAWWF1, + u4DataRAWWLenF1); + + u4RemainByte -= u4CpyLen; + u4SrcOffset += u4CpyLen; /* shift offset */ + /* only use ucDstOffset at first packet for align 2KB */ + ucDstOffset = 0; + } + /* if this is a last packet, we can't transfer the remain data. + * bcs we can't guarantee the data is complete align data format + */ + /* the data format is complete */ + if (u4CpyLen != u4FmtLen) { + /* not align 2KB, keep the data + * and next packet data will append it + */ + ucDstOffset = u4CpyLen; + } + + kfree(pucDataWF0); + kfree(pucDataWF1); + kfree(pucDataRAWWF0); + kfree(pucDataRAWWF1); + + if (u4RemainByte < 0) { + ASSERT(-1); + return -1; + } + + return 0; +} +#endif /* CFG_SUPPORT_QA_TOOL */ + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +void nicCmdEventQueryCalBackupV2(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + struct PARAM_CAL_BACKUP_STRUCT_V2 *prCalBackupDataV2Info; + struct CMD_CAL_BACKUP_STRUCT_V2 *prEventCalBackupDataV2; + uint32_t u4QueryInfoLen, u4QueryInfo, u4TempAddress; + struct GLUE_INFO *prGlueInfo; + + DBGLOG(RFTEST, INFO, "%s\n", __func__); + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + + prGlueInfo = prAdapter->prGlueInfo; + prEventCalBackupDataV2 = (struct CMD_CAL_BACKUP_STRUCT_V2 *) + (pucEventBuf); + + u4QueryInfoLen = sizeof(struct CMD_CAL_BACKUP_STRUCT_V2); + + prCalBackupDataV2Info = (struct PARAM_CAL_BACKUP_STRUCT_V2 + *) prCmdInfo->pvInformationBuffer; +#if 0 + DBGLOG(RFTEST, INFO, + "============ Receive a Cal Data EVENT (Info) ============\n"); + DBGLOG(RFTEST, INFO, "Reason = %d\n", + prEventCalBackupDataV2->ucReason); + DBGLOG(RFTEST, INFO, "Action = %d\n", + prEventCalBackupDataV2->ucAction); + DBGLOG(RFTEST, INFO, "NeedResp = %d\n", + prEventCalBackupDataV2->ucNeedResp); + DBGLOG(RFTEST, INFO, "FragNum = %d\n", + prEventCalBackupDataV2->ucFragNum); + DBGLOG(RFTEST, INFO, "RomRam = %d\n", + prEventCalBackupDataV2->ucRomRam); + DBGLOG(RFTEST, INFO, "ThermalValue = %d\n", + prEventCalBackupDataV2->u4ThermalValue); + DBGLOG(RFTEST, INFO, "Address = 0x%08x\n", + prEventCalBackupDataV2->u4Address); + DBGLOG(RFTEST, INFO, "Length = %d\n", + prEventCalBackupDataV2->u4Length); + DBGLOG(RFTEST, INFO, "RemainLength = %d\n", + prEventCalBackupDataV2->u4RemainLength); + DBGLOG(RFTEST, INFO, + "=========================================================\n"); +#endif + + if (prEventCalBackupDataV2->ucReason == 0 + && prEventCalBackupDataV2->ucAction == 0) { + DBGLOG(RFTEST, INFO, + "Received an EVENT for Query Thermal Temp.\n"); + prCalBackupDataV2Info->u4ThermalValue = + prEventCalBackupDataV2->u4ThermalValue; + g_rBackupCalDataAllV2.u4ThermalInfo = + prEventCalBackupDataV2->u4ThermalValue; + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } else if (prEventCalBackupDataV2->ucReason == 0 + && prEventCalBackupDataV2->ucAction == 1) { + DBGLOG(RFTEST, INFO, + "Received an EVENT for Query Total Cal Data Length.\n"); + prCalBackupDataV2Info->u4Length = + prEventCalBackupDataV2->u4Length; + + if (prEventCalBackupDataV2->ucRomRam == 0) + g_rBackupCalDataAllV2.u4ValidRomCalDataLength = + prEventCalBackupDataV2->u4Length; + else if (prEventCalBackupDataV2->ucRomRam == 1) + g_rBackupCalDataAllV2.u4ValidRamCalDataLength = + prEventCalBackupDataV2->u4Length; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } else if (prEventCalBackupDataV2->ucReason == 2 + && prEventCalBackupDataV2->ucAction == 4) { + DBGLOG(RFTEST, INFO, + "Received an EVENT for Query All Cal (%s) Data. FragNum = %d\n", + prCalBackupDataV2Info->ucRomRam == 0 ? "ROM" : "RAM", + prEventCalBackupDataV2->ucFragNum); + prCalBackupDataV2Info->u4Address = + prEventCalBackupDataV2->u4Address; + prCalBackupDataV2Info->u4Length = + prEventCalBackupDataV2->u4Length; + prCalBackupDataV2Info->u4RemainLength = + prEventCalBackupDataV2->u4RemainLength; + prCalBackupDataV2Info->ucFragNum = + prEventCalBackupDataV2->ucFragNum; + + /* Copy Cal Data From FW to Driver Array */ + if (prEventCalBackupDataV2->ucRomRam == 0) { + u4TempAddress = prEventCalBackupDataV2->u4Address; + kalMemCopy( + (uint8_t *)(g_rBackupCalDataAllV2.au4RomCalData) + + u4TempAddress, + (uint8_t *)(prEventCalBackupDataV2->au4Buffer), + prEventCalBackupDataV2->u4Length); + } else if (prEventCalBackupDataV2->ucRomRam == 1) { + u4TempAddress = prEventCalBackupDataV2->u4Address; + kalMemCopy( + (uint8_t *)(g_rBackupCalDataAllV2.au4RamCalData) + + u4TempAddress, + (uint8_t *)(prEventCalBackupDataV2->au4Buffer), + prEventCalBackupDataV2->u4Length); + } + + if (prEventCalBackupDataV2->u4Address == 0xFFFFFFFF) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Address Error!!!!!!!!!!!\n"); + } else if (prEventCalBackupDataV2->u4RemainLength == 0 + && prEventCalBackupDataV2->ucRomRam == 1) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Get Cal Data from FW (%s). Finish!!!!!!!!!!!\n", + prCalBackupDataV2Info->ucRomRam == 0 ? "ROM" : "RAM"); + } else if (prEventCalBackupDataV2->u4RemainLength == 0 + && prEventCalBackupDataV2->ucRomRam == 0) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Get Cal Data from FW (%s). Finish!!!!!!!!!!!\n", + prCalBackupDataV2Info->ucRomRam == 0 ? "ROM" : "RAM"); + prCalBackupDataV2Info->ucFragNum = 0; + prCalBackupDataV2Info->ucRomRam = 1; + prCalBackupDataV2Info->u4ThermalValue = 0; + prCalBackupDataV2Info->u4Address = 0; + prCalBackupDataV2Info->u4Length = 0; + prCalBackupDataV2Info->u4RemainLength = 0; + DBGLOG(RFTEST, INFO, + "RLM CMD : Get Cal Data from FW (%s). Start!!!!!!!!!!!!!!!!\n", + prCalBackupDataV2Info->ucRomRam == 0 ? "ROM" : "RAM"); + DBGLOG(RFTEST, INFO, "Thermal Temp = %d\n", + g_rBackupCalDataAllV2.u4ThermalInfo); + wlanoidQueryCalBackupV2(prAdapter, + prCalBackupDataV2Info, + sizeof(struct PARAM_CAL_BACKUP_STRUCT_V2), + &u4QueryInfo); + } else { + wlanoidSendCalBackupV2Cmd(prAdapter, + prCmdInfo->pvInformationBuffer, + prCmdInfo->u4InformationBufferLength); + } + } else if (prEventCalBackupDataV2->ucReason == 3 + && prEventCalBackupDataV2->ucAction == 5) { + DBGLOG(RFTEST, INFO, + "Received an EVENT for Send All Cal Data. FragNum = %d\n", + prEventCalBackupDataV2->ucFragNum); + prCalBackupDataV2Info->u4Address = + prEventCalBackupDataV2->u4Address; + prCalBackupDataV2Info->u4Length = + prEventCalBackupDataV2->u4Length; + prCalBackupDataV2Info->u4RemainLength = + prEventCalBackupDataV2->u4RemainLength; + prCalBackupDataV2Info->ucFragNum = + prEventCalBackupDataV2->ucFragNum; + + if (prEventCalBackupDataV2->u4RemainLength == 0 + || prEventCalBackupDataV2->u4Address == 0xFFFFFFFF) { + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } else { + wlanoidSendCalBackupV2Cmd(prAdapter, + prCmdInfo->pvInformationBuffer, + prCmdInfo->u4InformationBufferLength); + } + } else { + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called to handle dump burst event + * + * @param prAdapter Pointer to the Adapter structure. + * @param prCmdInfo Pointer to the command information + * @param pucEventBuf Pointer to event buffer + * + * @return none + * + */ +/*----------------------------------------------------------------------------*/ +void nicEventQueryMemDump(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct EVENT_DUMP_MEM *prEventDumpMem; + static uint8_t aucPath[256]; + static uint8_t aucPath_done[300]; + static uint32_t u4CurTimeTick; + + ASSERT(prAdapter); + ASSERT(pucEventBuf); + + snprintf(aucPath, sizeof(aucPath), "/dump_%05hu.hex", + prAdapter->rIcapInfo.u2DumpIndex); + + prEventDumpMem = (struct EVENT_DUMP_MEM *) (pucEventBuf); + + if (kalCheckPath(aucPath) == -1) { + kalMemSet(aucPath, 0x00, 256); + snprintf(aucPath, sizeof(aucPath), "/data/dump_%05hu.hex", + prAdapter->rIcapInfo.u2DumpIndex); + } + + if (prEventDumpMem->ucFragNum == 1) { + /* Store memory dump into sdcard, + * path /sdcard/dump__ + * _.hex + */ + u4CurTimeTick = kalGetTimeTick(); +#if defined(LINUX) + + /* if blbist mkdir undre /data/blbist, + * the dump files wouls put on it + */ + snprintf(aucPath, sizeof(aucPath), "/dump_%05hu.hex", + prAdapter->rIcapInfo.u2DumpIndex); + if (kalCheckPath(aucPath) == -1) { + kalMemSet(aucPath, 0x00, 256); + snprintf(aucPath, + sizeof(aucPath), "/data/dump_%05hu.hex", + prAdapter->rIcapInfo.u2DumpIndex); + } +#else + kal_sprintf_ddk(aucPath, sizeof(aucPath), + u4CurTimeTick, + prEventDumpMem->u4Address, + prEventDumpMem->u4Length + + prEventDumpMem->u4RemainLength); +#endif + 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 CFG_SUPPORT_QA_TOOL + nicTsfRawData2IqFmt(prEventDumpMem, &prAdapter->rIcapInfo); +#endif /* CFG_SUPPORT_QA_TOOL */ + DBGLOG(INIT, INFO, + "iCap : ==> (u4RemainLength = %x, u4Address=%x )\n", + prEventDumpMem->u4RemainLength, + prEventDumpMem->u4Address); + + if (prEventDumpMem->u4RemainLength == 0 + || prEventDumpMem->u4Address == 0xFFFFFFFF) { + + /* The request is finished or firmware response a error */ + /* Reply time tick to iwpriv */ + + prAdapter->rIcapInfo.fgIcapEnable = FALSE; + prAdapter->rIcapInfo.fgCaptureDone = TRUE; + + snprintf(aucPath_done, + sizeof(aucPath_done), "/file_dump_done.txt"); + if (kalCheckPath(aucPath_done) == -1) { + kalMemSet(aucPath_done, 0x00, 256); + snprintf(aucPath_done, + sizeof(aucPath_done), + "/data/file_dump_done.txt"); + } + DBGLOG(INIT, INFO, ": ==> gen done_file\n"); + kalWriteToFile(aucPath_done, FALSE, aucPath_done, + sizeof(aucPath_done)); +#if CFG_SUPPORT_QA_TOOL + prAdapter->rIcapInfo.au4Offset[0][0] = 0; + prAdapter->rIcapInfo.au4Offset[0][1] = 9; + prAdapter->rIcapInfo.au4Offset[1][0] = 0; + prAdapter->rIcapInfo.au4Offset[1][1] = 9; +#endif /* CFG_SUPPORT_QA_TOOL */ + + prAdapter->rIcapInfo.u2DumpIndex++; + + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct GLUE_INFO *prGlueInfo; + struct EVENT_DUMP_MEM *prEventDumpMem; + static uint8_t aucPath[256]; + /* static UINT_8 aucPath_done[300]; */ + static uint32_t u4CurTimeTick; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (1) { + prGlueInfo = prAdapter->prGlueInfo; + prEventDumpMem = (struct EVENT_DUMP_MEM *) (pucEventBuf); + + u4QueryInfoLen = sizeof(struct PARAM_CUSTOM_MEM_DUMP_STRUCT + *); + + if (prEventDumpMem->ucFragNum == 1) { + /* Store memory dump into sdcard, + * path /sdcard/dump__ + * _.hex + */ + u4CurTimeTick = kalGetTimeTick(); +#if defined(LINUX) + + /* PeiHsuan add for avoiding out of memory 20160801 */ + if (prAdapter->rIcapInfo.u2DumpIndex >= 20) + prAdapter->rIcapInfo.u2DumpIndex = 0; + + /* if blbist mkdir undre /data/blbist, + * the dump files wouls put on it + */ + snprintf(aucPath, sizeof(aucPath), "/dump_%05hu.hex", + prAdapter->rIcapInfo.u2DumpIndex); + if (kalCheckPath(aucPath) == -1) { + kalMemSet(aucPath, 0x00, 256); + sprintf(aucPath, "/data/dump_%05hu.hex", + prAdapter->rIcapInfo.u2DumpIndex); + } else + kalTrunkPath(aucPath); + + DBGLOG(INIT, INFO, + "iCap Create New Dump File dump_%05hu.hex\n", + prAdapter->rIcapInfo.u2DumpIndex); +#else + kal_sprintf_ddk(aucPath, sizeof(aucPath), + u4CurTimeTick, + prEventDumpMem->u4Address, + prEventDumpMem->u4Length + + prEventDumpMem->u4RemainLength); + /* strcpy(aucPath, "dump.hex"); */ +#endif + 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 CFG_SUPPORT_QA_TOOL + nicTsfRawData2IqFmt(prEventDumpMem, &prAdapter->rIcapInfo); +#endif /* CFG_SUPPORT_QA_TOOL */ + if (prEventDumpMem->u4RemainLength == 0 + || prEventDumpMem->u4Address == 0xFFFFFFFF) { + /* The request is finished or firmware response + * a error + */ + /* Reply time tick to iwpriv */ + if (prCmdInfo->fgIsOid) { + + /* the oid would be complete only in oid-trigger + * mode, that is no need to if the event-trigger + */ + if (prAdapter->rIcapInfo.fgIcapEnable + == FALSE) { + *((uint32_t *) + prCmdInfo->pvInformationBuffer) + = u4CurTimeTick; + kalOidComplete(prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + } + } + prAdapter->rIcapInfo.fgIcapEnable = FALSE; + prAdapter->rIcapInfo.fgCaptureDone = TRUE; +#if defined(LINUX) + + prAdapter->rIcapInfo.u2DumpIndex++; + +#else + kal_sprintf_done_ddk(aucPath_done, + sizeof(aucPath_done)); + kalWriteToFile(aucPath_done, FALSE, aucPath_done, + sizeof(aucPath_done)); +#endif + } else { +#if defined(LINUX) + +#else /* 2013/05/26 fw would try to send the buffer successfully */ + /* The memory dump request is not finished, + * Send next command + */ + wlanSendMemDumpCmd(prAdapter, + prCmdInfo->pvInformationBuffer, + prCmdInfo->u4InformationBufferLength); +#endif + } + } + + return; + +} + +#if CFG_SUPPORT_BATCH_SCAN +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called when event for SUPPORT_BATCH_SCAN + * + * @param prAdapter Pointer to the Adapter structure. + * @param prCmdInfo Pointer to the command information + * @param pucEventBuf Pointer to the event buffer + * + * @return none + * + */ +/*----------------------------------------------------------------------------*/ +void nicCmdEventBatchScanResult(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct EVENT_BATCH_RESULT *prEventBatchResult; + struct GLUE_INFO *prGlueInfo; + + DBGLOG(SCN, TRACE, "nicCmdEventBatchScanResult"); + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventBatchResult = (struct EVENT_BATCH_RESULT *) + pucEventBuf; + + u4QueryInfoLen = sizeof(struct EVENT_BATCH_RESULT); + kalMemCopy(prCmdInfo->pvInformationBuffer, + prEventBatchResult, sizeof(struct EVENT_BATCH_RESULT)); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} +#endif + +void nicEventHifCtrl(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct EVENT_HIF_CTRL *prEventHifCtrl; + struct GL_HIF_INFO *prHifInfo; + + prEventHifCtrl = (struct EVENT_HIF_CTRL *) ( + prEvent->aucBuffer); + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + DBGLOG(HAL, STATE, "%s: EVENT_ID_HIF_CTRL\n", __func__); + DBGLOG(HAL, STATE, "prEventHifCtrl->HifType = %hhu, HifSuspend = %d\n", + prEventHifCtrl->ucHifType, prEventHifCtrl->ucHifSuspend); + DBGLOG(HAL, INFO, "prEventHifCtrl->ucHifTxTrafficStatus = %hhu, ", + prEventHifCtrl->ucHifTxTrafficStatus); + DBGLOG(HAL, INFO, "prEventHifCtrl->ucHifRxTrafficStatus = %hhu\n", + prEventHifCtrl->ucHifRxTrafficStatus); + +#if defined(_HIF_USB) + /* if USB suspend, polling sequence */ + if (prEventHifCtrl->ucHifSuspend) { + if (prEventHifCtrl->ucHifTxTrafficStatus == + ENUM_HIF_TRAFFIC_IDLE && + prEventHifCtrl->ucHifRxTrafficStatus == + ENUM_HIF_TRAFFIC_IDLE) { + /* success */ + halUSBPreSuspendDone( + prAdapter, NULL, prEvent->aucBuffer); + } else { + /* busy */ + /* invalid */ + halUSBPreSuspendTimeout(prAdapter, NULL); + } + } else { + /* if USB get resume event, change to LINK_UP */ + glUsbSetState(prHifInfo, USB_STATE_LINK_UP); + } +#endif + +#if defined(_HIF_SDIO) + if (prEventHifCtrl->ucHifSuspend) { + /* if SDIO get suspend event, change to PRE_SUSPEND_DONE */ + glSdioSetState(prHifInfo, SDIO_STATE_PRE_SUSPEND_DONE); + } else { + /* if SDIO get resume event, change to LINK_UP */ + glSdioSetState(prHifInfo, SDIO_STATE_LINK_UP); + } +#endif + +#if CFG_SUPPORT_PCIE_L2 +#if defined(_HIF_PCIE) + if (prEventHifCtrl->ucHifSuspend) { + /* if PCIE get suspend event, change to PRE_SUSPEND_DONE */ + glPCIeSetState(prHifInfo, PCIE_STATE_PRE_SUSPEND_DONE); + } else { + /* if PCIE get resume event, change to LINK_UP */ + glPCIeSetState(prHifInfo, PCIE_STATE_LINK_UP); + } +#endif + +#endif + +} + +#if CFG_SUPPORT_BUILD_DATE_CODE +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called when event for build date code information + * has been retrieved + * + * @param prAdapter Pointer to the Adapter structure. + * @param prCmdInfo Pointer to the command information + * @param pucEventBuf Pointer to the event buffer + * + * @return none + * + */ +/*----------------------------------------------------------------------------*/ +void nicCmdEventBuildDateCode(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct EVENT_BUILD_DATE_CODE *prEvent; + struct GLUE_INFO *prGlueInfo; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEvent = (struct EVENT_BUILD_DATE_CODE *) pucEventBuf; + + u4QueryInfoLen = sizeof(uint8_t) * 16; + kalMemCopy(prCmdInfo->pvInformationBuffer, + prEvent->aucDateCode, sizeof(uint8_t) * 16); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called when event for query STA link status + * has been retrieved + * + * @param prAdapter Pointer to the Adapter structure. + * @param prCmdInfo Pointer to the command information + * @param pucEventBuf Pointer to the event buffer + * + * @return none + * + */ +/*----------------------------------------------------------------------------*/ +void nicCmdEventQueryStaStatistics(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct EVENT_STA_STATISTICS *prEvent; + struct GLUE_INFO *prGlueInfo; + struct PARAM_GET_STA_STATISTICS *prStaStatistics; + enum ENUM_WMM_ACI eAci; + struct STA_RECORD *prStaRec; + uint8_t ucDbdcIdx; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + ASSERT(prCmdInfo->pvInformationBuffer); + + prGlueInfo = prAdapter->prGlueInfo; + prEvent = (struct EVENT_STA_STATISTICS *) pucEventBuf; + prStaStatistics = (struct PARAM_GET_STA_STATISTICS *) + prCmdInfo->pvInformationBuffer; + + u4QueryInfoLen = sizeof(struct PARAM_GET_STA_STATISTICS); + + /* Statistics from FW is valid */ + if (prEvent->u4Flags & BIT(0)) { + prStaStatistics->ucPer = prEvent->ucPer; + prStaStatistics->ucRcpi = prEvent->ucRcpi; + prStaStatistics->u4PhyMode = prEvent->u4PhyMode; + prStaStatistics->u2LinkSpeed = prEvent->u2LinkSpeed; + + prStaStatistics->u4TxFailCount = prEvent->u4TxFailCount; + prStaStatistics->u4TxLifeTimeoutCount = + prEvent->u4TxLifeTimeoutCount; + prStaStatistics->u4TransmitCount = + prEvent->u4TransmitCount; + prStaStatistics->u4TransmitFailCount = + prEvent->u4TransmitFailCount; + prStaStatistics->u4Rate1TxCnt = prEvent->u4Rate1TxCnt; + prStaStatistics->u4Rate1FailCnt = + prEvent->u4Rate1FailCnt; + + prStaStatistics->ucTemperature = prEvent->ucTemperature; + prStaStatistics->ucSkipAr = prEvent->ucSkipAr; + prStaStatistics->ucArTableIdx = prEvent->ucArTableIdx; + prStaStatistics->ucRateEntryIdx = + prEvent->ucRateEntryIdx; + prStaStatistics->ucRateEntryIdxPrev = + prEvent->ucRateEntryIdxPrev; + prStaStatistics->ucTxSgiDetectPassCnt = + prEvent->ucTxSgiDetectPassCnt; + prStaStatistics->ucAvePer = prEvent->ucAvePer; +#if (CFG_SUPPORT_RA_GEN == 0) + kalMemCopy(prStaStatistics->aucArRatePer, + prEvent->aucArRatePer, + sizeof(prEvent->aucArRatePer)); + kalMemCopy(prStaStatistics->aucRateEntryIndex, + prEvent->aucRateEntryIndex, + sizeof(prEvent->aucRateEntryIndex)); +#else + prStaStatistics->u4AggRangeCtrl_0 = + prEvent->u4AggRangeCtrl_0; + prStaStatistics->u4AggRangeCtrl_1 = + prEvent->u4AggRangeCtrl_1; + prStaStatistics->ucRangeType = prEvent->ucRangeType; + kalMemCopy(prStaStatistics->aucReserved5, + prEvent->aucReserved5, + sizeof(prEvent->aucReserved5)); +#endif + prStaStatistics->ucArStateCurr = prEvent->ucArStateCurr; + prStaStatistics->ucArStatePrev = prEvent->ucArStatePrev; + prStaStatistics->ucArActionType = + prEvent->ucArActionType; + prStaStatistics->ucHighestRateCnt = + prEvent->ucHighestRateCnt; + prStaStatistics->ucLowestRateCnt = + prEvent->ucLowestRateCnt; + prStaStatistics->u2TrainUp = prEvent->u2TrainUp; + prStaStatistics->u2TrainDown = prEvent->u2TrainDown; + kalMemCopy(&prStaStatistics->rTxVector, + &prEvent->rTxVector, + sizeof(prEvent->rTxVector)); + kalMemCopy(&prStaStatistics->rMibInfo, + &prEvent->rMibInfo, + sizeof(prEvent->rMibInfo)); + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; ucDbdcIdx++) { + g_arMibInfo[ucDbdcIdx].u4RxMpduCnt += + prStaStatistics->rMibInfo[ucDbdcIdx]. + u4RxMpduCnt; + g_arMibInfo[ucDbdcIdx].u4FcsError += + prStaStatistics->rMibInfo[ucDbdcIdx]. + u4FcsError; + g_arMibInfo[ucDbdcIdx].u4RxFifoFull += + prStaStatistics->rMibInfo[ucDbdcIdx]. + u4RxFifoFull; + g_arMibInfo[ucDbdcIdx].u4AmpduTxSfCnt += + prStaStatistics->rMibInfo[ucDbdcIdx]. + u4AmpduTxSfCnt; + g_arMibInfo[ucDbdcIdx].u4AmpduTxAckSfCnt += + prStaStatistics->rMibInfo[ucDbdcIdx]. + u4AmpduTxAckSfCnt; + g_arMibInfo[ucDbdcIdx].u2TxRange1AmpduCnt += + prStaStatistics->rMibInfo[ucDbdcIdx]. + u2TxRange1AmpduCnt; + g_arMibInfo[ucDbdcIdx].u2TxRange2AmpduCnt += + prStaStatistics->rMibInfo[ucDbdcIdx]. + u2TxRange2AmpduCnt; + g_arMibInfo[ucDbdcIdx].u2TxRange3AmpduCnt += + prStaStatistics->rMibInfo[ucDbdcIdx]. + u2TxRange3AmpduCnt; + g_arMibInfo[ucDbdcIdx].u2TxRange4AmpduCnt += + prStaStatistics->rMibInfo[ucDbdcIdx]. + u2TxRange4AmpduCnt; + g_arMibInfo[ucDbdcIdx].u2TxRange5AmpduCnt += + prStaStatistics->rMibInfo[ucDbdcIdx]. + u2TxRange5AmpduCnt; + g_arMibInfo[ucDbdcIdx].u2TxRange6AmpduCnt += + prStaStatistics->rMibInfo[ucDbdcIdx]. + u2TxRange6AmpduCnt; + g_arMibInfo[ucDbdcIdx].u2TxRange7AmpduCnt += + prStaStatistics->rMibInfo[ucDbdcIdx]. + u2TxRange7AmpduCnt; + g_arMibInfo[ucDbdcIdx].u2TxRange8AmpduCnt += + prStaStatistics->rMibInfo[ucDbdcIdx]. + u2TxRange8AmpduCnt; + } + prStaStatistics->fgIsForceTxStream = + prEvent->fgIsForceTxStream; + prStaStatistics->fgIsForceSeOff = + prEvent->fgIsForceSeOff; +#if (CFG_SUPPORT_RA_GEN == 0) + kalMemCopy(prStaStatistics->aucReserved6, + prEvent->aucReserved6, + sizeof(prEvent->aucReserved6)); +#else + prStaStatistics->u2RaRunningCnt = + prEvent->u2RaRunningCnt; + prStaStatistics->ucRaStatus = prEvent->ucRaStatus; + prStaStatistics->ucFlag = prEvent->ucFlag; + kalMemCopy(&prStaStatistics->aucTxQuality, + &prEvent->aucTxQuality, + sizeof(prEvent->aucTxQuality)); + prStaStatistics->ucTxRateUpPenalty = + prEvent->ucTxRateUpPenalty; + prStaStatistics->ucLowTrafficMode = + prEvent->ucLowTrafficMode; + prStaStatistics->ucLowTrafficCount = + prEvent->ucLowTrafficCount; + prStaStatistics->ucLowTrafficDashBoard = + prEvent->ucLowTrafficDashBoard; + prStaStatistics->ucDynamicSGIState = + prEvent->ucDynamicSGIState; + prStaStatistics->ucDynamicSGIScore = + prEvent->ucDynamicSGIScore; + prStaStatistics->ucDynamicBWState = + prEvent->ucDynamicBWState; + prStaStatistics->ucDynamicGband256QAMState = + prEvent->ucDynamicGband256QAMState; + prStaStatistics->ucVhtNonSpRateState = + prEvent->ucVhtNonSpRateState; +#endif + prStaRec = cnmGetStaRecByIndex(prAdapter, + prEvent->ucStaRecIdx); + + if (prStaRec) { + /*link layer statistics */ + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; + eAci++) { + prStaStatistics->arLinkStatistics[eAci]. + u4TxFailMsdu = + prEvent->arLinkStatistics[eAci]. + u4TxFailMsdu; + prStaStatistics->arLinkStatistics[eAci]. + u4TxRetryMsdu = + prEvent->arLinkStatistics[eAci]. + u4TxRetryMsdu; + + /*for dump bss statistics */ + prStaRec->arLinkStatistics[eAci]. + u4TxFailMsdu = + prEvent->arLinkStatistics[eAci]. + u4TxFailMsdu; + prStaRec->arLinkStatistics[eAci]. + u4TxRetryMsdu = + prEvent->arLinkStatistics[eAci]. + u4TxRetryMsdu; + } + } + if (prEvent->u4TxCount) { + uint32_t u4TxDoneAirTimeMs = + USEC_TO_MSEC(prEvent->u4TxDoneAirTime * + 32); + + prStaStatistics->u4TxAverageAirTime = + (u4TxDoneAirTimeMs / + prEvent->u4TxCount); + } else { + prStaStatistics->u4TxAverageAirTime = 0; + } + +#if CFG_ENABLE_PER_STA_STATISTICS_LOG +#if CFG_SUPPORT_WFD + /* dump statistics for WFD */ + if (prAdapter->rWifiVar + .rWfdConfigureSettings.ucWfdEnable == 1) { + uint32_t u4LinkScore = 0; + uint32_t u4TotalError = + prStaStatistics->u4TxFailCount + + prStaStatistics->u4TxLifeTimeoutCount; + uint32_t u4TxExceedThresholdCount = + prStaStatistics->u4TxExceedThresholdCount; + uint32_t u4TxTotalCount = + prStaStatistics->u4TxTotalCount; + + /* Calcute Link Score + * u4LinkScore 10~100 , + * ExceedThreshold ratio 0~90 only + * u4LinkScore 0~9 + * Drop packet ratio 0~9 and + * all packets exceed threshold + */ + if (u4TxTotalCount) { + if (u4TxExceedThresholdCount <= u4TxTotalCount) + u4LinkScore = (90 - + ((u4TxExceedThresholdCount * 90) + / u4TxTotalCount)); + else + u4LinkScore = 0; + } else + u4LinkScore = 90; + + u4LinkScore += 10; + if (u4LinkScore == 10) { + if (u4TotalError <= u4TxTotalCount) + u4LinkScore = (10 - + ((u4TotalError * 10) / + u4TxTotalCount)); + else + u4LinkScore = 0; + } + + if (u4LinkScore > 100) + u4LinkScore = 100; + + log_dbg(P2P, INFO, + "[%u][%u] link_score=%u, rssi=%u, rate=%u, threshold_cnt=%u, fail_cnt=%u\n", + prEvent->ucNetworkTypeIndex, + prEvent->ucStaRecIdx, + u4LinkScore, + prStaStatistics->ucRcpi, + prStaStatistics->u2LinkSpeed, + prStaStatistics->u4TxExceedThresholdCount, + prStaStatistics->u4TxFailCount); + log_dbg(P2P, INFO, "timeout_cnt=%u, apt=%u, aat=%u, total_cnt=%u\n", + prStaStatistics->u4TxLifeTimeoutCount, + prStaStatistics->u4TxAverageProcessTime, + prStaStatistics->u4TxAverageAirTime, + prStaStatistics->u4TxTotalCount); + } +#endif +#endif + } + + if (prCmdInfo->fgIsOid) + kalOidComplete(prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + +} + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is called when event for query LTE safe channels + * has been retrieved + * + * @param prAdapter Pointer to the Adapter structure. + * @param prCmdInfo Pointer to the command information + * @param pucEventBuf Pointer to the event buffer + * + * @return none + */ +/*----------------------------------------------------------------------------*/ +void nicCmdEventQueryLteSafeChn(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct EVENT_LTE_SAFE_CHN *prEvent; + struct GLUE_INFO *prGlueInfo; + struct PARAM_GET_CHN_INFO *prLteSafeChnInfo; + uint8_t ucIdx = 0; + + if ((prAdapter == NULL) + || (prCmdInfo == NULL) + || (pucEventBuf == NULL) + || (prCmdInfo->pvInformationBuffer == NULL)) { + ASSERT(FALSE); + return; + } + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEvent = (struct EVENT_LTE_SAFE_CHN *) + pucEventBuf; /* FW responsed data */ + + prLteSafeChnInfo = (struct PARAM_GET_CHN_INFO *) + prCmdInfo->pvInformationBuffer; + + u4QueryInfoLen = sizeof(struct PARAM_GET_CHN_INFO); + + /* Statistics from FW is valid */ + if (prEvent->u4Flags & BIT(0)) { + for (ucIdx = 0; + ucIdx < NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_MAX; + ucIdx++) { + prLteSafeChnInfo->rLteSafeChnList. + au4SafeChannelBitmask[ucIdx] + = prEvent->rLteSafeChn. + au4SafeChannelBitmask[ucIdx]; + + DBGLOG(P2P, TRACE, + "[ACS]LTE safe channels[%d]=0x%08x\n", + ucIdx, + prLteSafeChnInfo->rLteSafeChnList. + au4SafeChannelBitmask[ucIdx]); + } + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} +#endif + +#if CFG_SUPPORT_ADVANCE_CONTROL +void nicCmdEventQueryAdvCtrl(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + uint8_t *query; + struct GLUE_INFO *prGlueInfo; + uint32_t query_len; + struct CMD_ADV_CONFIG_HEADER *hdr; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (!pucEventBuf) { + DBGLOG(REQ, ERROR, "pucEventBuf is null.\n"); + return; + } + hdr = (struct CMD_ADV_CONFIG_HEADER *)pucEventBuf; + DBGLOG(REQ, LOUD, "%s type %x len %d>\n", __func__ + , hdr->u2Type, hdr->u2Len); + + prGlueInfo = prAdapter->prGlueInfo; + query_len = hdr->u2Len; + query = prCmdInfo->pvInformationBuffer; + if (query && + (query_len == prCmdInfo->u4InformationBufferLength)) + kalMemCopy(query, hdr, query_len); + else + DBGLOG(REQ, LOUD, "%s type %x, len %d != buflen %d>\n" + , __func__, hdr->u2Type, hdr->u2Len, + prCmdInfo->u4InformationBufferLength); + + if (prCmdInfo->fgIsOid) { + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + query_len, WLAN_STATUS_SUCCESS); + } +} +#endif + + +void nicEventRddPulseDump(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + uint16_t u2Idx, u2PulseCnt; + struct EVENT_WIFI_RDD_TEST *prRddPulseEvent; + + ASSERT(prAdapter); + ASSERT(pucEventBuf); + + prRddPulseEvent = (struct EVENT_WIFI_RDD_TEST *) ( + pucEventBuf); + + u2PulseCnt = (prRddPulseEvent->u4FuncLength - + RDD_EVENT_HDR_SIZE) / RDD_ONEPLUSE_SIZE; + + DBGLOG(INIT, INFO, "[RDD]0x%08x %08d[RDD%d]\n", + prRddPulseEvent->u4Prefix + , prRddPulseEvent->u4Count, prRddPulseEvent->ucRddIdx); + + for (u2Idx = 0; u2Idx < u2PulseCnt; u2Idx++) { + DBGLOG(INIT, INFO, + "[RDD]0x%02x%02x%02x%02x %02x%02x%02x%02x[RDD%d]\n" + , prRddPulseEvent->aucBuffer[RDD_ONEPLUSE_SIZE * u2Idx + + RDD_PULSE_OFFSET3] + , prRddPulseEvent->aucBuffer[RDD_ONEPLUSE_SIZE * u2Idx + + RDD_PULSE_OFFSET2] + , prRddPulseEvent->aucBuffer[RDD_ONEPLUSE_SIZE * u2Idx + + RDD_PULSE_OFFSET1] + , prRddPulseEvent->aucBuffer[RDD_ONEPLUSE_SIZE * u2Idx + + RDD_PULSE_OFFSET0] + , prRddPulseEvent->aucBuffer[RDD_ONEPLUSE_SIZE * u2Idx + + RDD_PULSE_OFFSET7] + , prRddPulseEvent->aucBuffer[RDD_ONEPLUSE_SIZE * u2Idx + + RDD_PULSE_OFFSET6] + , prRddPulseEvent->aucBuffer[RDD_ONEPLUSE_SIZE * u2Idx + + RDD_PULSE_OFFSET5] + , prRddPulseEvent->aucBuffer[RDD_ONEPLUSE_SIZE * u2Idx + + RDD_PULSE_OFFSET4] + , prRddPulseEvent->ucRddIdx + ); + } + +} + +#if CFG_SUPPORT_MSP +void nicCmdEventQueryWlanInfo(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct PARAM_HW_WLAN_INFO *prWlanInfo; + struct EVENT_WLAN_INFO *prEventWlanInfo; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventWlanInfo = (struct EVENT_WLAN_INFO *) pucEventBuf; + + DBGLOG(RSN, INFO, "MT6632 : nicCmdEventQueryWlanInfo\n"); + + prGlueInfo = prAdapter->prGlueInfo; + + u4QueryInfoLen = sizeof(struct PARAM_HW_WLAN_INFO); + prWlanInfo = (struct PARAM_HW_WLAN_INFO *) + prCmdInfo->pvInformationBuffer; + + /* prWlanInfo->u4Length = sizeof(PARAM_HW_WLAN_INFO_T); */ + if (prEventWlanInfo && prWlanInfo) { + kalMemCopy(&prWlanInfo->rWtblTxConfig, + &prEventWlanInfo->rWtblTxConfig, + sizeof(struct PARAM_TX_CONFIG)); + kalMemCopy(&prWlanInfo->rWtblSecConfig, + &prEventWlanInfo->rWtblSecConfig, + sizeof(struct PARAM_SEC_CONFIG)); + kalMemCopy(&prWlanInfo->rWtblKeyConfig, + &prEventWlanInfo->rWtblKeyConfig, + sizeof(struct PARAM_KEY_CONFIG)); + kalMemCopy(&prWlanInfo->rWtblRateInfo, + &prEventWlanInfo->rWtblRateInfo, + sizeof(struct PARAM_PEER_RATE_INFO)); + kalMemCopy(&prWlanInfo->rWtblBaConfig, + &prEventWlanInfo->rWtblBaConfig, + sizeof(struct PARAM_PEER_BA_CONFIG)); + kalMemCopy(&prWlanInfo->rWtblPeerCap, + &prEventWlanInfo->rWtblPeerCap, + sizeof(struct PARAM_PEER_CAP)); + kalMemCopy(&prWlanInfo->rWtblRxCounter, + &prEventWlanInfo->rWtblRxCounter, + sizeof(struct PARAM_PEER_RX_COUNTER_ALL)); + kalMemCopy(&prWlanInfo->rWtblTxCounter, + &prEventWlanInfo->rWtblTxCounter, + sizeof(struct PARAM_PEER_TX_COUNTER_ALL)); + } + + if (prCmdInfo->fgIsOid) { + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + + +void nicCmdEventQueryMibInfo(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct PARAM_HW_MIB_INFO *prMibInfo; + struct EVENT_MIB_INFO *prEventMibInfo; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventMibInfo = (struct EVENT_MIB_INFO *) pucEventBuf; + + DBGLOG(RSN, INFO, "MT6632 : nicCmdEventQueryMibInfo\n"); + + prGlueInfo = prAdapter->prGlueInfo; + + u4QueryInfoLen = sizeof(struct PARAM_HW_MIB_INFO); + prMibInfo = (struct PARAM_HW_MIB_INFO *) + prCmdInfo->pvInformationBuffer; + if (prEventMibInfo && prMibInfo) { + kalMemCopy(&prMibInfo->rHwMibCnt, + &prEventMibInfo->rHwMibCnt, + sizeof(struct HW_MIB_COUNTER)); + kalMemCopy(&prMibInfo->rHwMib2Cnt, + &prEventMibInfo->rHwMib2Cnt, + sizeof(struct HW_MIB2_COUNTER)); + kalMemCopy(&prMibInfo->rHwTxAmpduMts, + &prEventMibInfo->rHwTxAmpduMts, + sizeof(struct HW_TX_AMPDU_METRICS)); + } + + if (prCmdInfo->fgIsOid) { + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} +#endif + +uint32_t nicEventQueryTxResourceEntry(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct NIC_TX_RESOURCE *prTxResource; + uint32_t version = *((uint32_t *)pucEventBuf); + + + prAdapter->fgIsNicTxReousrceValid = TRUE; + + if (version & NIC_TX_RESOURCE_REPORT_VERSION_PREFIX) + return nicEventQueryTxResource(prAdapter, pucEventBuf); + + /* 6632, 7668 ways */ + prAdapter->nicTxReousrce.txResourceInit = NULL; + + prTxResource = (struct NIC_TX_RESOURCE *)pucEventBuf; + prAdapter->nicTxReousrce.u4CmdTotalResource = + prTxResource->u4CmdTotalResource; + prAdapter->nicTxReousrce.u4CmdResourceUnit = + prTxResource->u4CmdResourceUnit; + prAdapter->nicTxReousrce.u4DataTotalResource = + prTxResource->u4DataTotalResource; + prAdapter->nicTxReousrce.u4DataResourceUnit = + prTxResource->u4DataResourceUnit; + + DBGLOG(INIT, INFO, + "nicCmdEventQueryNicTxResource: u4CmdTotalResource = %x\n", + prAdapter->nicTxReousrce.u4CmdTotalResource); + DBGLOG(INIT, INFO, + "nicCmdEventQueryNicTxResource: u4CmdResourceUnit = %x\n", + prAdapter->nicTxReousrce.u4CmdResourceUnit); + DBGLOG(INIT, INFO, + "nicCmdEventQueryNicTxResource: u4DataTotalResource = %x\n", + prAdapter->nicTxReousrce.u4DataTotalResource); + DBGLOG(INIT, INFO, + "nicCmdEventQueryNicTxResource: u4DataResourceUnit = %x\n", + prAdapter->nicTxReousrce.u4DataResourceUnit); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t nicCmdEventQueryNicEfuseAddr(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct NIC_EFUSE_ADDRESS *prTxResource = + (struct NIC_EFUSE_ADDRESS *)pucEventBuf; + + prAdapter->u4EfuseStartAddress = + prTxResource->u4EfuseStartAddress; + prAdapter->u4EfuseEndAddress = + prTxResource->u4EfuseEndAddress; + + DBGLOG(INIT, INFO, + "nicCmdEventQueryNicEfuseAddr: u4EfuseStartAddress = %x\n", + prAdapter->u4EfuseStartAddress); + DBGLOG(INIT, INFO, + "nicCmdEventQueryNicEfuseAddr: u4EfuseEndAddress = %x\n", + prAdapter->u4EfuseEndAddress); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t nicCmdEventQueryNicCoexFeature(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct NIC_COEX_FEATURE *prCoexFeature = + (struct NIC_COEX_FEATURE *)pucEventBuf; + + prAdapter->u4FddMode = prCoexFeature->u4FddMode; + + DBGLOG(INIT, INFO, + "nicCmdEventQueryNicCoexFeature: u4FddMode = %x\n", + prAdapter->u4FddMode); + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +uint32_t nicCmdEventQueryNicCsumOffload(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct NIC_CSUM_OFFLOAD *prChecksumOffload = + (struct NIC_CSUM_OFFLOAD *)pucEventBuf; + + prAdapter->fgIsSupportCsumOffload = + prChecksumOffload->ucIsSupportCsumOffload; + + DBGLOG(INIT, INFO, + "nicCmdEventQueryNicCsumOffload: ucIsSupportCsumOffload = %x\n", + prAdapter->fgIsSupportCsumOffload); + + return WLAN_STATUS_SUCCESS; +} +#endif + +uint32_t nicCfgChipCapHwVersion(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct CAP_HW_VERSION *prHwVer = + (struct CAP_HW_VERSION *)pucEventBuf; + + prAdapter->rVerInfo.u2FwProductID = prHwVer->u2ProductID; + + return WLAN_STATUS_SUCCESS; +} + +uint32_t nicCfgChipCapSwVersion(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct CAP_SW_VERSION *prSwVer = + (struct CAP_SW_VERSION *)pucEventBuf; + + prAdapter->rVerInfo.u2FwOwnVersion = prSwVer->u2FwVersion; + prAdapter->rVerInfo.ucFwBuildNumber = + prSwVer->u2FwBuildNumber; + kalMemCopy(prAdapter->rVerInfo.aucFwBranchInfo, + prSwVer->aucBranchInfo, 4); + kalMemCopy(prAdapter->rVerInfo.aucFwDateCode, + prSwVer->aucDateCode, 16); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t nicCfgChipCapMacAddr(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct CAP_MAC_ADDR *prMacAddr = (struct CAP_MAC_ADDR *)pucEventBuf; + uint8_t aucZeroMacAddr[] = NULL_MAC_ADDR; + + COPY_MAC_ADDR(prAdapter->rWifiVar.aucPermanentAddress, + prMacAddr->aucMacAddr); + COPY_MAC_ADDR(prAdapter->rWifiVar.aucMacAddress, + prMacAddr->aucMacAddr); + prAdapter->fgIsEmbbededMacAddrValid = (u_int8_t) ( + !IS_BMCAST_MAC_ADDR(prMacAddr->aucMacAddr) && + !EQUAL_MAC_ADDR(aucZeroMacAddr, prMacAddr->aucMacAddr)); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t nicCfgChipCapPhyCap(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct CAP_PHY_CAP *prPhyCap = (struct CAP_PHY_CAP *)pucEventBuf; + + prAdapter->rWifiVar.ucStaVht &= prPhyCap->ucVht; + prAdapter->rWifiVar.ucApVht &= prPhyCap->ucVht; + prAdapter->rWifiVar.ucP2pGoVht &= prPhyCap->ucVht; + prAdapter->rWifiVar.ucP2pGcVht &= prPhyCap->ucVht; + prAdapter->rWifiVar.ucHwNotSupportAC = (prPhyCap->ucVht) ? FALSE:TRUE; + prAdapter->fgIsHw5GBandDisabled = !prPhyCap->uc5gBand; + prAdapter->rWifiVar.ucNSS = (prPhyCap->ucNss > + prAdapter->rWifiVar.ucNSS) ? + (prAdapter->rWifiVar.ucNSS):(prPhyCap->ucNss); +#if CFG_SUPPORT_DBDC + if (!prPhyCap->ucDbdc) + prAdapter->rWifiVar.eDbdcMode = ENUM_DBDC_MODE_DISABLED; +#endif + prAdapter->rWifiVar.ucTxLdpc &= prPhyCap->ucTxLdpc; + prAdapter->rWifiVar.ucRxLdpc &= prPhyCap->ucRxLdpc; + prAdapter->rWifiVar.ucTxStbc &= prPhyCap->ucTxStbc; + prAdapter->rWifiVar.ucRxStbc &= prPhyCap->ucRxStbc; + + if (!prPhyCap->ucVht) { +#if CFG_SUPPORT_MTK_SYNERGY + prAdapter->rWifiVar.ucGbandProbe256QAM = FEATURE_DISABLED; +#endif +#if CFG_SUPPORT_VHT_IE_IN_2G + prAdapter->rWifiVar.ucVhtIeIn2g = FEATURE_DISABLED; +#endif + } + + prAdapter->rWifiFemCfg.u2WifiPath = (uint16_t)(prPhyCap->ucHwWifiPath); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t nicCfgChipCapMacCap(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct CAP_MAC_CAP *prMacCap = (struct CAP_MAC_CAP *)pucEventBuf; + + if (prMacCap->ucHwBssIdNum > 0 + && prMacCap->ucHwBssIdNum <= MAX_BSSID_NUM) { + prAdapter->ucHwBssIdNum = prMacCap->ucHwBssIdNum; + prAdapter->ucP2PDevBssIdx = prAdapter->ucHwBssIdNum; + prAdapter->aprBssInfo[prAdapter->ucP2PDevBssIdx] = + &prAdapter->rWifiVar.rP2pDevInfo; + } + DBGLOG(INIT, INFO, "ucHwBssIdNum: %d.\n", + prMacCap->ucHwBssIdNum); + + if (prMacCap->ucWtblEntryNum > 0 + && prMacCap->ucWtblEntryNum <= WTBL_SIZE) { + prAdapter->ucWtblEntryNum = prMacCap->ucWtblEntryNum; + prAdapter->ucTxDefaultWlanIndex = prAdapter->ucWtblEntryNum + - 1; + } + DBGLOG(INIT, INFO, "ucWtblEntryNum: %d.\n", + prMacCap->ucWtblEntryNum); + + prAdapter->ucWmmSetNum = prMacCap->ucWmmSet > 0 ? + prMacCap->ucWmmSet : 1; + DBGLOG(INIT, INFO, "ucWmmSetNum: %d.\n", + prMacCap->ucWmmSet); + + return WLAN_STATUS_SUCCESS; +} + +uint32_t nicCfgChipCapFrameBufCap(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + return WLAN_STATUS_SUCCESS; +} + +uint32_t nicCfgChipCapBeamformCap(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + return WLAN_STATUS_SUCCESS; +} + +uint32_t nicCfgChipCapLocationCap(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + return WLAN_STATUS_SUCCESS; +} + +uint32_t nicCfgChipCapMuMimoCap(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + return WLAN_STATUS_SUCCESS; +} + +uint32_t nicCfgChipCapBufferModeInfo(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct CAP_BUFFER_MODE_INFO_T *prBufferModeInfo = + (struct CAP_BUFFER_MODE_INFO_T *)pucEventBuf; + uint32_t u4Idx = 0; + + prAdapter->rBufferModeInfo = *prBufferModeInfo; + + DBGLOG(INIT, INFO, "%s: %d, %d, %d\n", __func__, + prBufferModeInfo->ucVersion, + prBufferModeInfo->ucFormatSupportBitmap, + prBufferModeInfo->u2EfuseTotalSize); + + for (u4Idx = 0; u4Idx < EFUSE_SECTION_TABLE_SIZE; ++u4Idx) { + DBGLOG(INIT, INFO, "%s: %d = %d, %d\n", __func__, + u4Idx, prBufferModeInfo->arSections[u4Idx].u2StartOffset, + prBufferModeInfo->arSections[u4Idx].u2Length); + } + + return WLAN_STATUS_SUCCESS; +} + +struct nicTxRsrcEvtHdlr nicTxRsrcEvtHdlrTbl[] = { + {NIC_TX_RESOURCE_REPORT_VERSION_1, + nicEventQueryTxResource_v1, + nicTxResourceUpdate_v1}, +}; + +uint32_t nicEventQueryTxResource(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf) +{ + uint32_t i, i_max; + uint32_t version = *((uint32_t *)(pucEventBuf)); + + i_max = sizeof(nicTxRsrcEvtHdlrTbl) / sizeof( + struct nicTxRsrcEvtHdlr); + for (i = 0; i < i_max; i += 2) { + if (version == nicTxRsrcEvtHdlrTbl[i].u4Version) { + /* assign callback to do the resource init. */ + prAdapter->nicTxReousrce.txResourceInit = + nicTxRsrcEvtHdlrTbl[i].nicTxResourceInit; + + return nicTxRsrcEvtHdlrTbl[i].nicEventTxResource( + prAdapter, pucEventBuf); + } + } + + /* invalid version, cannot find the handler */ + DBGLOG(INIT, ERROR, + "nicEventQueryTxResource(): Invaalid version.\n"); + prAdapter->nicTxReousrce.txResourceInit = NULL; + + return WLAN_STATUS_NOT_SUPPORTED; +} + +uint32_t nicEventQueryTxResource_v1(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf) +{ + struct tx_resource_report_v1 *pV1 = + (struct tx_resource_report_v1 *)pucEventBuf; + uint16_t page_size; + + /* PSE */ + page_size = pV1->u4PlePsePageSize & 0xFFFF; + prAdapter->nicTxReousrce.u4CmdTotalResource = + pV1->u4HifCmdPsePageQuota; + prAdapter->nicTxReousrce.u4CmdResourceUnit = page_size; + prAdapter->nicTxReousrce.u4DataTotalResource = + pV1->u4HifDataPsePageQuota; + prAdapter->nicTxReousrce.u4DataResourceUnit = page_size; + + /* PLE */ + page_size = (pV1->u4PlePsePageSize >> 16) & 0xFFFF; + prAdapter->nicTxReousrce.u4CmdTotalResourcePle = + pV1->u4HifCmdPlePageQuota; + prAdapter->nicTxReousrce.u4CmdResourceUnitPle = page_size; + prAdapter->nicTxReousrce.u4DataTotalResourcePle = + pV1->u4HifDataPlePageQuota; + prAdapter->nicTxReousrce.u4DataResourceUnitPle = page_size; + + /* PpTxAddCnt */ + prAdapter->nicTxReousrce.ucPpTxAddCnt = pV1->ucPpTxAddCnt; + + /* enable PLE resource control flag */ + if (!prAdapter->nicTxReousrce.u4DataTotalResourcePle) + prAdapter->rTxCtrl.rTc.fgNeedPleCtrl = FALSE; + else + prAdapter->rTxCtrl.rTc.fgNeedPleCtrl = + NIC_TX_RESOURCE_CTRL_PLE; + return WLAN_STATUS_SUCCESS; +} + +void nicCmdEventQueryNicCapabilityV2(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct EVENT_NIC_CAPABILITY_V2 *prEventNicV2 = + (struct EVENT_NIC_CAPABILITY_V2 *)pucEventBuf; + struct NIC_CAPABILITY_V2_ELEMENT *prElement; + uint32_t tag_idx, table_idx, offset; + + offset = 0; + + /* process each element */ + for (tag_idx = 0; tag_idx < prEventNicV2->u2TotalElementNum; + tag_idx++) { + + prElement = (struct NIC_CAPABILITY_V2_ELEMENT *)( + prEventNicV2->aucBuffer + offset); + + for (table_idx = 0; + table_idx < (sizeof(gNicCapabilityV2InfoTable) / sizeof( + struct NIC_CAPABILITY_V2_REF_TABLE)); + table_idx++) { + + /* find the corresponding tag's handler */ + if (gNicCapabilityV2InfoTable[table_idx].tag_type == + prElement->tag_type) { + gNicCapabilityV2InfoTable[table_idx].hdlr( + prAdapter, prElement->aucbody); + break; + } + } + + /* move to the next tag */ + offset += prElement->body_len + (uint16_t) OFFSET_OF( + struct NIC_CAPABILITY_V2_ELEMENT, aucbody); + } + +} + +#if (CFG_SUPPORT_TXPOWER_INFO == 1) +void nicCmdEventQueryTxPowerInfo(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + struct EXT_EVENT_TXPOWER_ALL_RATE_POWER_INFO_T *prEvent = + NULL; + struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T *prTxPowerInfo = + NULL; + uint32_t u4QueryInfoLen; + struct GLUE_INFO *prGlueInfo = NULL; + + if (!prAdapter) + return; + + prGlueInfo = prAdapter->prGlueInfo; + if (!prCmdInfo) + return; + if (!pucEventBuf) + return; + if (!(prCmdInfo->pvInformationBuffer)) + return; + + if (prCmdInfo->fgIsOid) { + prEvent = (struct EXT_EVENT_TXPOWER_ALL_RATE_POWER_INFO_T *) + pucEventBuf; + + if (prEvent->ucTxPowerCategory == + TXPOWER_EVENT_SHOW_ALL_RATE_TXPOWER_INFO) { + prEvent = + (struct + EXT_EVENT_TXPOWER_ALL_RATE_POWER_INFO_T *) + pucEventBuf; + prTxPowerInfo = + (struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T *) + prCmdInfo->pvInformationBuffer; + u4QueryInfoLen = + sizeof( + struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T); + + kalMemCopy(prTxPowerInfo, prEvent, + sizeof( + struct EXT_EVENT_TXPOWER_ALL_RATE_POWER_INFO_T)); + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} +#endif + +void nicEventLinkQuality(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct mt66xx_chip_info *prChipInfo = NULL; + struct CMD_INFO *prCmdInfo; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + +#if CFG_ENABLE_WIFI_DIRECT && CFG_SUPPORT_P2P_RSSI_QUERY + if (prEvent->u2PacketLen == prChipInfo->event_hdr_size + + sizeof(struct EVENT_LINK_QUALITY_EX)) { + struct EVENT_LINK_QUALITY_EX *prLqEx = + (struct EVENT_LINK_QUALITY_EX *) (prEvent->aucBuffer); + + if (prLqEx->ucIsLQ0Rdy) + nicUpdateLinkQuality(prAdapter, 0, + (struct EVENT_LINK_QUALITY *) prLqEx); + if (prLqEx->ucIsLQ1Rdy) + nicUpdateLinkQuality(prAdapter, 1, + (struct 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, 0, + (struct EVENT_LINK_QUALITY *) (prEvent->aucBuffer)); + } +#else + /*only support ais query */ + { + uint8_t ucBssIndex; + struct BSS_INFO *prBssInfo; + + for (ucBssIndex = 0; ucBssIndex < prAdapter->ucHwBssIdNum; + ucBssIndex++) { + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + + if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS + && prBssInfo->fgIsInUse) + break; + } + + if (ucBssIndex >= prAdapter->ucHwBssIdNum) + ucBssIndex = 1; + /* No hit(bss1 for default ais network) */ + nicUpdateLinkQuality(prAdapter, ucBssIndex, + (struct EVENT_LINK_QUALITY_V2 *) (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 >= (int32_t) ( + prAdapter->rLinkQuality.cRssi)) { + + prAdapter->rWlanInfo.eRssiTriggerType = + ENUM_RSSI_TRIGGER_TRIGGERED; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (void *) &(prAdapter->rWlanInfo.rRssiTriggerValue), + sizeof(int32_t)); + } else if (prAdapter->rWlanInfo.eRssiTriggerType == + ENUM_RSSI_TRIGGER_LESS && + prAdapter->rWlanInfo.rRssiTriggerValue <= (int32_t) ( + prAdapter->rLinkQuality.cRssi)) { + + prAdapter->rWlanInfo.eRssiTriggerType = + ENUM_RSSI_TRIGGER_TRIGGERED; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (void *) &(prAdapter->rWlanInfo.rRssiTriggerValue), + sizeof(int32_t)); + } +#endif +} + +uint32_t nicExtTsfRawData2IqFmt( + struct EXT_EVENT_RBIST_DUMP_DATA_T *prEventDumpMem, + struct ICAP_INFO_T *prIcap) +{ + static uint8_t + aucPathWF0[40]; /* the path for iq data dump out */ + static uint8_t + aucPathWF1[40]; /* the path for iq data dump out */ + static uint8_t + aucPathRAWWF0[40]; /* the path for iq data dump out */ + static uint8_t + aucPathRAWWF1[40]; /* the path for iq data dump out */ + uint8_t *pucDataWF0 = NULL; /* the data write into file */ + uint8_t *pucDataWF1 = NULL; /* the data write into file */ + uint8_t *pucDataRAWWF0 = + NULL; /* the data write into file */ + uint8_t *pucDataRAWWF1 = + NULL; /* the data write into file */ + uint32_t u4SrcOffset; /* record the buffer offset */ + uint32_t u4FmtLen = 0; /* bus format length */ + uint32_t u4CpyLen = 0; + uint32_t u4RemainByte; + uint32_t u4DataWBufSize = 150; + uint32_t u4DataRAWWBufSize = 150; + uint32_t u4DataWLenF0 = 0; + uint32_t u4DataWLenF1 = 0; + uint32_t u4DataRAWWLenF0 = 0; + uint32_t u4DataRAWWLenF1 = 0; + u_int8_t fgAppend; + int32_t u4Iqc160WF0Q0, u4Iqc160WF1I1; + /* for alignment. bcs we send 2KB data per packet,*/ + static uint8_t ucDstOffset; + /* the data will not align in 12 bytes case. */ + static uint32_t u4CurTimeTick; + + static union ICAP_BUS_FMT icapBusData; + uint32_t *ptr; + + pucDataWF0 = kmalloc(u4DataWBufSize, GFP_KERNEL); + pucDataWF1 = kmalloc(u4DataWBufSize, GFP_KERNEL); + pucDataRAWWF0 = kmalloc(u4DataRAWWBufSize, GFP_KERNEL); + pucDataRAWWF1 = kmalloc(u4DataRAWWBufSize, GFP_KERNEL); + + + if ((!pucDataWF0) || (!pucDataWF1) || (!pucDataRAWWF0) + || (!pucDataRAWWF1)) { + DBGLOG(INIT, ERROR, "kmalloc failed.\n"); + kfree(pucDataWF0); + kfree(pucDataWF1); + kfree(pucDataRAWWF0); + kfree(pucDataRAWWF1); + ASSERT(-1); + return -1; + } + + fgAppend = TRUE; + if (prEventDumpMem->u4PktNum == 0) { + u4CurTimeTick = kalGetTimeTick(); + /* Store memory dump into sdcard, + * path /sdcard/dump__ + * _.hex + */ +#if defined(LINUX) + + /* if blbist mkdir undre /data/blbist, + * the dump files wouls put on it + */ + scnprintf(aucPathWF0, sizeof(aucPathWF0), + "/dump_out_%05hu_WF0.txt", prIcap->u2DumpIndex); + scnprintf(aucPathWF1, sizeof(aucPathWF1), + "/dump_out_%05hu_WF1.txt", prIcap->u2DumpIndex); + if (kalCheckPath(aucPathWF0) == -1) { + kalMemSet(aucPathWF0, 0x00, sizeof(aucPathWF0)); + scnprintf(aucPathWF0, sizeof(aucPathWF0), + "/data/dump_out_%05hu_WF0.txt", + prIcap->u2DumpIndex); + } else + kalTrunkPath(aucPathWF0); + + if (kalCheckPath(aucPathWF1) == -1) { + kalMemSet(aucPathWF1, 0x00, sizeof(aucPathWF1)); + scnprintf(aucPathWF1, sizeof(aucPathWF1), + "/data/dump_out_%05hu_WF1.txt", + prIcap->u2DumpIndex); + } else + kalTrunkPath(aucPathWF1); + + scnprintf(aucPathRAWWF0, sizeof(aucPathRAWWF0), + "/dump_RAW_%05hu_WF0.txt", prIcap->u2DumpIndex); + scnprintf(aucPathRAWWF1, sizeof(aucPathRAWWF1), + "/dump_RAW_%05hu_WF1.txt", prIcap->u2DumpIndex); + if (kalCheckPath(aucPathRAWWF0) == -1) { + kalMemSet(aucPathRAWWF0, 0x00, sizeof(aucPathRAWWF0)); + scnprintf(aucPathRAWWF0, sizeof(aucPathRAWWF0), + "/data/dump_RAW_%05hu_WF0.txt", + prIcap->u2DumpIndex); + } else + kalTrunkPath(aucPathRAWWF0); + + if (kalCheckPath(aucPathRAWWF1) == -1) { + kalMemSet(aucPathRAWWF1, 0x00, sizeof(aucPathRAWWF1)); + scnprintf(aucPathRAWWF1, sizeof(aucPathRAWWF1), + "/data/dump_RAW_%hu_WF1.txt", + prIcap->u2DumpIndex); + } else + kalTrunkPath(aucPathRAWWF1); + +#else + /* TODO: check Address */ + kal_sprintf_ddk(aucPathWF0, sizeof(aucPathWF0), + u4CurTimeTick, prEventDumpMem->u4Address, + prEventDumpMem->u4Length + + prEventDumpMem->u4RemainLength); + kal_sprintf_ddk(aucPathWF1, sizeof(aucPathWF1), + u4CurTimeTick, prEventDumpMem->u4Address, + prEventDumpMem->u4Length + + prEventDumpMem->u4RemainLength); +#endif + /* fgAppend = FALSE; */ + } + + ptr = (uint32_t *)(&prEventDumpMem->u4Data); + + for (u4SrcOffset = 0, + u4RemainByte = prEventDumpMem->u4DataLength; + u4RemainByte > 0;) { + u4FmtLen = (prIcap->u4CapNode == ICAP_CONTENT_SPECTRUM) ? + sizeof(struct SPECTRUM_BUS_FMT) : sizeof(union + ICAP_BUS_FMT); + /* 4 bytes : 12 bytes */ + u4CpyLen = (u4RemainByte - u4FmtLen >= 0) ? u4FmtLen : + u4RemainByte; + if ((ucDstOffset + u4CpyLen) > sizeof(icapBusData)) { + DBGLOG(INIT, ERROR, + "ucDstOffset(%u) + u4CpyLen(%u) exceed bound of icapBusData\n", + ucDstOffset, u4CpyLen); + kfree(pucDataWF0); + kfree(pucDataWF1); + kfree(pucDataRAWWF0); + kfree(pucDataRAWWF1); + ASSERT(-1); + return -1; + } + + memcpy((uint8_t *)&icapBusData + ucDstOffset, + &prEventDumpMem->u4Data + u4SrcOffset, u4CpyLen); + if (prIcap->u4CapNode == ICAP_CONTENT_FIIQ + || prIcap->u4CapNode == ICAP_CONTENT_FDIQ) { + u4DataWLenF0 = scnprintf(pucDataWF0, u4DataWBufSize, + "%8d,%8d\n", + icapBusData.rIqcBusData.u4Iqc0I, + icapBusData.rIqcBusData.u4Iqc0Q); + u4DataWLenF1 = scnprintf(pucDataWF1, u4DataWBufSize, + "%8d,%8d\n", + icapBusData.rIqcBusData.u4Iqc1I, + icapBusData.rIqcBusData.u4Iqc1Q); + } else if (prIcap->u4CapNode - 1000 == ICAP_CONTENT_FIIQ || + prIcap->u4CapNode - 1000 == ICAP_CONTENT_FDIQ) { + u4Iqc160WF0Q0 = icapBusData.rIqc160BusData.u4Iqc0Q0P1 | + (icapBusData.rIqc160BusData.u4Iqc0Q0P2 << 8); + u4Iqc160WF1I1 = icapBusData.rIqc160BusData.u4Iqc1I1P1 | + (icapBusData.rIqc160BusData.u4Iqc1I1P2 << 4); + + u4DataWLenF0 = scnprintf(pucDataWF0, u4DataWBufSize, + "%8d,%8d\n%8d,%8d\n", + icapBusData.rIqc160BusData.u4Iqc0I0, + u4Iqc160WF0Q0, + icapBusData.rIqc160BusData.u4Iqc0I1, + icapBusData.rIqc160BusData.u4Iqc0Q1); + + u4DataWLenF1 = scnprintf(pucDataWF1, u4DataWBufSize, + "%8d,%8d\n%8d,%8d\n", + icapBusData.rIqc160BusData.u4Iqc1I0, + icapBusData.rIqc160BusData.u4Iqc1Q0, + u4Iqc160WF1I1, + icapBusData.rIqc160BusData.u4Iqc1Q1); + + } else if (prIcap->u4CapNode == ICAP_CONTENT_SPECTRUM) { + u4DataWLenF0 = scnprintf(pucDataWF0, u4DataWBufSize, + "%8d,%8d\n", + icapBusData.rSpectrumBusData.u4DcocI, + icapBusData.rSpectrumBusData.u4DcocQ); + } else if (prIcap->u4CapNode == ICAP_CONTENT_ADC) { + u4DataWLenF0 = scnprintf(pucDataWF0, u4DataWBufSize, + "%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n", + icapBusData.rPackedAdcBusData.u4AdcI0T0, + icapBusData.rPackedAdcBusData.u4AdcQ0T0, + icapBusData.rPackedAdcBusData.u4AdcI0T1, + icapBusData.rPackedAdcBusData.u4AdcQ0T1, + icapBusData.rPackedAdcBusData.u4AdcI0T2, + icapBusData.rPackedAdcBusData.u4AdcQ0T2, + icapBusData.rPackedAdcBusData.u4AdcI0T3, + icapBusData.rPackedAdcBusData.u4AdcQ0T3, + icapBusData.rPackedAdcBusData.u4AdcI0T4, + icapBusData.rPackedAdcBusData.u4AdcQ0T4, + icapBusData.rPackedAdcBusData.u4AdcI0T5, + icapBusData.rPackedAdcBusData.u4AdcQ0T5); + + u4DataWLenF1 = scnprintf(pucDataWF1, u4DataWBufSize, + "%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n", + icapBusData.rPackedAdcBusData.u4AdcI1T0, + icapBusData.rPackedAdcBusData.u4AdcQ1T0, + icapBusData.rPackedAdcBusData.u4AdcI1T1, + icapBusData.rPackedAdcBusData.u4AdcQ1T1, + icapBusData.rPackedAdcBusData.u4AdcI1T2, + icapBusData.rPackedAdcBusData.u4AdcQ1T2, + icapBusData.rPackedAdcBusData.u4AdcI1T3, + icapBusData.rPackedAdcBusData.u4AdcQ1T3, + icapBusData.rPackedAdcBusData.u4AdcI1T4, + icapBusData.rPackedAdcBusData.u4AdcQ1T4, + icapBusData.rPackedAdcBusData.u4AdcI1T5, + icapBusData.rPackedAdcBusData.u4AdcQ1T5); + } else if (prIcap->u4CapNode - 2000 == ICAP_CONTENT_ADC) { + u4DataWLenF0 = scnprintf(pucDataWF0, u4DataWBufSize, + "%8d,%8d\n%8d,%8d\n%8d,%8d\n", + icapBusData.rPackedAdcBusData.u4AdcI0T0, + icapBusData.rPackedAdcBusData.u4AdcQ0T0, + icapBusData.rPackedAdcBusData.u4AdcI0T1, + icapBusData.rPackedAdcBusData.u4AdcQ0T1, + icapBusData.rPackedAdcBusData.u4AdcI0T2, + icapBusData.rPackedAdcBusData.u4AdcQ0T2); + + u4DataWLenF1 = scnprintf(pucDataWF1, u4DataWBufSize, + "%8d,%8d\n%8d,%8d\n%8d,%8d\n", + icapBusData.rPackedAdcBusData.u4AdcI1T0, + icapBusData.rPackedAdcBusData.u4AdcQ1T0, + icapBusData.rPackedAdcBusData.u4AdcI1T1, + icapBusData.rPackedAdcBusData.u4AdcQ1T1, + icapBusData.rPackedAdcBusData.u4AdcI1T2, + icapBusData.rPackedAdcBusData.u4AdcQ1T2); + } else if (prIcap->u4CapNode == ICAP_CONTENT_TOAE) { + /* actually, this is DCOC. we take TOAE as DCOC */ + u4DataWLenF0 = scnprintf(pucDataWF0, u4DataWBufSize, + "%8d,%8d\n", + icapBusData.rAdcBusData.u4Dcoc0I, + icapBusData.rAdcBusData.u4Dcoc0Q); + u4DataWLenF1 = scnprintf(pucDataWF1, u4DataWBufSize, + "%8d,%8d\n", + icapBusData.rAdcBusData.u4Dcoc1I, + icapBusData.rAdcBusData.u4Dcoc1Q); + } + if (u4CpyLen == + u4FmtLen) { /* the data format is complete */ + kalWriteToFile(aucPathWF0, fgAppend, pucDataWF0, + u4DataWLenF0); + kalWriteToFile(aucPathWF1, fgAppend, pucDataWF1, + u4DataWLenF1); + } + ptr = (uint32_t *)(&prEventDumpMem->u4Data + u4SrcOffset); + u4DataRAWWLenF0 = scnprintf(pucDataRAWWF0, u4DataWBufSize, + "%08x%08x%08x\n", + *(ptr + 2), *(ptr + 1), *ptr); + kalWriteToFile(aucPathRAWWF0, fgAppend, pucDataRAWWF0, + u4DataRAWWLenF0); + kalWriteToFile(aucPathRAWWF1, fgAppend, pucDataRAWWF1, + u4DataRAWWLenF1); + + u4RemainByte -= u4CpyLen; + u4SrcOffset += u4CpyLen; /* shift offset */ + /* only use ucDstOffset at first packet for align 2KB */ + ucDstOffset = 0; + } + /* if this is a last packet, we can't transfer the remain data. + * bcs we can't guarantee the data is complete align data format + */ + if (u4CpyLen != + u4FmtLen) { /* the data format is complete */ + /* not align 2KB, keep the data and next packet data + * will append it + */ + ucDstOffset = u4CpyLen; + } + + kfree(pucDataWF0); + kfree(pucDataWF1); + kfree(pucDataRAWWF0); + kfree(pucDataRAWWF1); + + if (u4RemainByte < 0) { + ASSERT(-1); + return -1; + } + + return 0; +} + +void nicExtEventReCalData(IN struct ADAPTER *prAdapter, IN uint8_t *pucEventBuf) +{ + struct EXT_EVENT_RECAL_DATA_T *prReCalData = NULL; + struct RECAL_INFO_T *prReCalInfo = NULL; + struct RECAL_DATA_T *prCalArray = NULL; + uint32_t u4Idx = 0; + + ASSERT(pucEventBuf); + ASSERT(prAdapter); + prReCalInfo = &prAdapter->rReCalInfo; + if (prReCalInfo->prCalArray == NULL) { + prCalArray = (struct RECAL_DATA_T *)kalMemAlloc( + 2048 * sizeof(struct RECAL_DATA_T), VIR_MEM_TYPE); + + if (prCalArray == NULL) { + DBGLOG(RFTEST, ERROR, + "Unable to alloc memory for recal data\n"); + return; + } + prReCalInfo->prCalArray = prCalArray; + } + + if (prReCalInfo->u4Count >= 2048) { + DBGLOG(RFTEST, ERROR, + "Too many Recal packet, maximum packets will be 2048, ignore\n"); + return; + } + + prCalArray = prReCalInfo->prCalArray; + DBGLOG(RFTEST, INFO, "prCalArray[%d] address [%p]\n", + prReCalInfo->u4Count, + &prCalArray[prReCalInfo->u4Count]); + + prReCalData = (struct EXT_EVENT_RECAL_DATA_T *)pucEventBuf; + switch (prReCalData->u4Type) { + case 0: { + unsigned long ulTmpData; + + prReCalData->u.ucData[9] = '\0'; + prReCalData->u.ucData[19] = '\0'; + u4Idx = prReCalInfo->u4Count; + + if (kstrtoul(&prReCalData->u.ucData[1], 16, &ulTmpData)) + DBGLOG(RFTEST, ERROR, "convert fail: ucData[1]\n"); + else + prCalArray[u4Idx].u4CalId = (unsigned int)ulTmpData; + if (kstrtoul(&prReCalData->u.ucData[11], 16, &ulTmpData)) + DBGLOG(RFTEST, ERROR, "convert fail: ucData[11]\n"); + else + prCalArray[u4Idx].u4CalAddr = (unsigned int)ulTmpData; + if (kstrtoul(&prReCalData->u.ucData[20], 16, &ulTmpData)) + DBGLOG(RFTEST, ERROR, "convert fail: ucData[20] %s\n", + &prReCalData->u.ucData[20]); + else + prCalArray[u4Idx].u4CalValue = (unsigned int)ulTmpData; + + DBGLOG(RFTEST, TRACE, "[0x%08x][0x%08x][0x%08x]\n", + prCalArray[u4Idx].u4CalId, + prCalArray[u4Idx].u4CalAddr, + prCalArray[u4Idx].u4CalValue); + prReCalInfo->u4Count++; + break; + } + case 1: + /* Todo: for extension to handle int */ + /* data directly come from FW */ + break; + } +} + + +void nicExtEventICapIQData(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct EXT_EVENT_RBIST_DUMP_DATA_T *prICapEvent; + uint32_t Idxi = 0, Idxj = 0, Idxk = 0; + struct _RBIST_IQ_DATA_T *prIQArray = NULL; + struct ICAP_INFO_T *prIcapInfo = NULL; + + ASSERT(prAdapter); + ASSERT(pucEventBuf); + + prICapEvent = (struct EXT_EVENT_RBIST_DUMP_DATA_T *) + pucEventBuf; + prIcapInfo = &prAdapter->rIcapInfo; + prIQArray = prIcapInfo->prIQArray; + ASSERT(prIQArray); + + /* If we receive the packet which is delivered from + * last time data-capure, we need to drop it. + */ + DBGLOG(RFTEST, INFO, "prICapEvent->u4PktNum = %d\n", + prICapEvent->u4PktNum); + if (prICapEvent->u4PktNum > prIcapInfo->u4ICapEventCnt) { + if (prICapEvent->u4DataLength == 0) + prAdapter->rIcapInfo.fgCaptureDone = TRUE; + DBGLOG(RFTEST, ERROR, + "Packet out of order: Pkt num %d, EventCnt %d\n", + prICapEvent->u4PktNum, prIcapInfo->u4ICapEventCnt); + return; + } + + DBGLOG(RFTEST, INFO, + "u4SmplCnt = [%d], u4WFCnt = [%d], IQArrayIndex = [%d]\n", + prICapEvent->u4SmplCnt, + prICapEvent->u4WFCnt, + prIcapInfo->u4IQArrayIndex); + + if (prICapEvent->u4DataLength != 0 && + prICapEvent->u4SmplCnt * prICapEvent->u4WFCnt * + NUM_OF_CAP_TYPE > ICAP_EVENT_DATA_SAMPLE) { + /* Max count = Total ICAP_EVENT_DATA_SAMPLE count + * and cut into half (I/Q) + */ + prICapEvent->u4SmplCnt = ICAP_EVENT_DATA_SAMPLE / + NUM_OF_CAP_TYPE; + DBGLOG(RFTEST, WARN, + "u4SmplCnt is larger than buffer size\n"); + } + + if (prIcapInfo->u4IQArrayIndex + prICapEvent->u4SmplCnt > + MAX_ICAP_IQ_DATA_CNT) { + DBGLOG(RFTEST, ERROR, + "Too many packets from FW, skip rest of them\n"); + return; + } + + for (Idxi = 0; Idxi < prICapEvent->u4SmplCnt; Idxi++) { + for (Idxj = 0; Idxj < prICapEvent->u4WFCnt; Idxj++) { + prIQArray[prIcapInfo->u4IQArrayIndex]. + u4IQArray[Idxj][CAP_I_TYPE] = + prICapEvent->u4Data[Idxk++]; + prIQArray[prIcapInfo->u4IQArrayIndex]. + u4IQArray[Idxj][CAP_Q_TYPE] = + prICapEvent->u4Data[Idxk++]; + } + prIcapInfo->u4IQArrayIndex++; + } + + /* Print ICap data to console for debugging purpose */ + for (Idxi = 0; Idxi < prICapEvent->u4SmplCnt; Idxi++) + if (prICapEvent->u4Data[Idxi] == 0) + DBGLOG(RFTEST, WARN, "Data[%d] : %x\n", Idxi, + prICapEvent->u4Data[Idxi]); + + + /* Update ICapEventCnt */ + if (prICapEvent->u4DataLength != 0) + prIcapInfo->u4ICapEventCnt++; + + /* Check whether is the last FW event or not */ + if ((prICapEvent->u4DataLength == 0) + && (prICapEvent->u4PktNum == prIcapInfo->u4ICapEventCnt)) { + /* Reset ICapEventCnt */ + prAdapter->rIcapInfo.fgIcapEnable = FALSE; + prAdapter->rIcapInfo.fgCaptureDone = TRUE; + prIcapInfo->u4ICapEventCnt = 0; + DBGLOG(INIT, INFO, ": ==> gen done_file\n"); + } +} + +void nicExtEventQueryMemDump(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf) +{ + struct EXT_EVENT_RBIST_DUMP_DATA_T *prEventDumpMem; + static uint8_t aucPath[256]; + static uint8_t aucPath_done[300]; + static uint32_t u4CurTimeTick; + + ASSERT(prAdapter); + ASSERT(pucEventBuf); + + snprintf(aucPath, + sizeof(aucPath), "/dump_%05hu.hex", + prAdapter->rIcapInfo.u2DumpIndex); + + prEventDumpMem = (struct EXT_EVENT_RBIST_DUMP_DATA_T *) + pucEventBuf; + + if (kalCheckPath(aucPath) == -1) { + kalMemSet(aucPath, 0x00, 256); + snprintf(aucPath, + sizeof(aucPath), "/data/dump_%05hu.hex", + prAdapter->rIcapInfo.u2DumpIndex); + } + + if (prEventDumpMem->u4PktNum == 0) { + /* Store memory dump into sdcard, + * path /sdcard/dump__ + * _.hex + */ + u4CurTimeTick = kalGetTimeTick(); +#if defined(LINUX) + + /* if blbist mkdir undre /data/blbist, + * the dump files wouls put on it + */ + snprintf(aucPath, + sizeof(aucPath), "/dump_%05hu.hex", + prAdapter->rIcapInfo.u2DumpIndex); + if (kalCheckPath(aucPath) == -1) { + kalMemSet(aucPath, 0x00, 256); + snprintf(aucPath, + sizeof(aucPath), "/data/dump_%05hu.hex", + prAdapter->rIcapInfo.u2DumpIndex); + } +#else + /* TODO: check Address */ + kal_sprintf_ddk(aucPath, sizeof(aucPath), + u4CurTimeTick, prEventDumpMem->u4Address, + prEventDumpMem->u4Length + + prEventDumpMem->u4RemainLength); +#endif + kalWriteToFile(aucPath, FALSE, + (uint8_t *)prEventDumpMem->u4Data, + prEventDumpMem->u4DataLength); + } else { + /* Append current memory dump to the hex file */ + kalWriteToFile(aucPath, TRUE, + (uint8_t *)prEventDumpMem->u4Data, + prEventDumpMem->u4DataLength); + } +#if CFG_SUPPORT_QA_TOOL + nicExtTsfRawData2IqFmt(prEventDumpMem, + &prAdapter->rIcapInfo); +#endif /* CFG_SUPPORT_QA_TOOL */ + + /* TODO: check Address */ + + if (prEventDumpMem->u4DataLength == 0) { + /* The request is finished or firmware response a error */ + /* Reply time tick to iwpriv */ + + prAdapter->rIcapInfo.fgIcapEnable = FALSE; + prAdapter->rIcapInfo.fgCaptureDone = TRUE; + + snprintf(aucPath_done, + sizeof(aucPath_done), "/file_dump_done.txt"); + if (kalCheckPath(aucPath_done) == -1) { + kalMemSet(aucPath_done, 0x00, 256); + snprintf(aucPath_done, + sizeof(aucPath_done), + "/data/file_dump_done.txt"); + } + DBGLOG(INIT, INFO, ": ==> gen done_file\n"); + kalWriteToFile(aucPath_done, FALSE, aucPath_done, + sizeof(aucPath_done)); +#if CFG_SUPPORT_QA_TOOL + prAdapter->rIcapInfo.au4Offset[0][0] = 0; + prAdapter->rIcapInfo.au4Offset[0][1] = 9; + prAdapter->rIcapInfo.au4Offset[1][0] = 0; + prAdapter->rIcapInfo.au4Offset[1][1] = 9; +#endif /* CFG_SUPPORT_QA_TOOL */ + prAdapter->rIcapInfo.u2DumpIndex++; + + } +} + + +uint32_t nicRfTestEventHandler(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + uint32_t u4QueryInfoLen = 0; + struct EXT_EVENT_RF_TEST_RESULT_T *prResult; + struct EXT_EVENT_RBIST_CAP_STATUS_T *prCapStatus; + struct mt66xx_chip_info *prChipInfo = NULL; + struct ATE_OPS_T *prAteOps = NULL; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + ASSERT(prChipInfo); + prAteOps = prChipInfo->prAteOps; + ASSERT(prAteOps); + + prResult = (struct EXT_EVENT_RF_TEST_RESULT_T *) + prEvent->aucBuffer; + DBGLOG(RFTEST, INFO, "prResult->u4FuncIndex = %d\n", + prResult->u4FuncIndex); + switch (prResult->u4FuncIndex) { + case GET_ICAP_CAPTURE_STATUS: + u4QueryInfoLen = sizeof(struct + EXT_EVENT_RBIST_CAP_STATUS_T); + prCapStatus = (struct EXT_EVENT_RBIST_CAP_STATUS_T *) + prEvent->aucBuffer; + + DBGLOG(RFTEST, INFO, "prCapStatus->u4CapDone = %d\n", + prCapStatus->u4CapDone); + if (prCapStatus->u4CapDone && + !prAdapter->rIcapInfo.fgCaptureDone) + wlanoidRfTestICapRawDataProc(prAdapter, + 0 /*prCapStatus->u4CapStartAddr*/, + 0 /*prCapStatus->u4TotalBufferSize*/); + break; + + case GET_ICAP_RAW_DATA: + if (prAteOps->getRbistDataDumpEvent) { + prAteOps->getRbistDataDumpEvent(prAdapter, + prEvent->aucBuffer); +#if 0 + /* NOTE: only for FW + * defconfig CONFIG_WIFI_ICAP_DUMP_DATA_BY_SOLICITING=y + */ + if (!prAdapter->rIcapInfo.fgCaptureDone) + wlanoidRfTestICapRawDataProc(prAdapter, + 0 /*prCapStatus->u4CapStartAddr*/, + 0 /*prCapStatus->u4TotalBufferSize*/); +#endif + } + break; + + case RE_CALIBRATION: + nicExtEventReCalData(prAdapter, prEvent->aucBuffer); + break; + + default: + DBGLOG(RFTEST, WARN, "Unknown rf test event, ignore\n"); + break; + } + + return u4QueryInfoLen; +} + +void nicEventLayer0ExtMagic(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + uint32_t u4QueryInfoLen = 0; + struct CMD_INFO *prCmdInfo = NULL; + + log_dbg(NIC, TRACE, "prEvent->ucExtenEID = %x\n", prEvent->ucExtenEID); + + switch (prEvent->ucExtenEID) { + case EXT_EVENT_ID_CMD_RESULT: + u4QueryInfoLen = sizeof(struct + PARAM_CUSTOM_EFUSE_BUFFER_MODE); + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + break; + + case EXT_EVENT_ID_EFUSE_ACCESS: + { + struct EVENT_ACCESS_EFUSE *prEventEfuseAccess; + + u4QueryInfoLen = sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE); + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + prEventEfuseAccess = (struct EVENT_ACCESS_EFUSE *) ( + prEvent->aucBuffer); + + /* Efuse block size 16 */ + kalMemCopy(prAdapter->aucEepromVaule, + prEventEfuseAccess->aucData, 16); + break; + } + + case EXT_EVENT_ID_RF_TEST: + u4QueryInfoLen = nicRfTestEventHandler(prAdapter, prEvent); + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + break; + + case EXT_EVENT_ID_GET_TX_POWER: + { + struct EXT_EVENT_GET_TX_POWER *prEventGetTXPower; + + u4QueryInfoLen = sizeof(struct PARAM_CUSTOM_GET_TX_POWER); + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + prEventGetTXPower = (struct EXT_EVENT_GET_TX_POWER *) ( + prEvent->aucBuffer); + + prAdapter->u4GetTxPower = + prEventGetTXPower->ucTx0TargetPower; + break; + } + + case EXT_EVENT_ID_EFUSE_FREE_BLOCK: + { + struct EXT_EVENT_EFUSE_FREE_BLOCK *prEventGetFreeBlock; + + u4QueryInfoLen = sizeof(struct + PARAM_CUSTOM_EFUSE_FREE_BLOCK); + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + prEventGetFreeBlock = (struct EXT_EVENT_EFUSE_FREE_BLOCK *) + (prEvent->aucBuffer); + prAdapter->u4FreeBlockNum = + prEventGetFreeBlock->u2FreeBlockNum; + break; + } + + case EXT_EVENT_ID_BF_STATUS_READ: + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + if (prCmdInfo != NULL && prCmdInfo->pfCmdDoneHandler) { + struct EXT_EVENT_BF_STATUS_T *prExtBfStatus = + (struct EXT_EVENT_BF_STATUS_T *)prEvent->aucBuffer; + + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, + prExtBfStatus->aucBuf); + } + break; + + case EXT_EVENT_ID_MAX_AMSDU_LENGTH_UPDATE: + { + struct EXT_EVENT_MAX_AMSDU_LENGTH_UPDATE *prEventAmsdu; + struct STA_RECORD *prStaRec; + uint8_t ucStaRecIndex; + + prEventAmsdu = (struct EXT_EVENT_MAX_AMSDU_LENGTH_UPDATE *) + (prEvent->aucBuffer); + + ucStaRecIndex = secGetStaIdxByWlanIdx( + prAdapter, prEventAmsdu->ucWlanIdx); + if (ucStaRecIndex == STA_REC_INDEX_NOT_FOUND) + break; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIndex); + if (!prStaRec) + break; + + if (prStaRec->ucMaxMpduCount == 0 || + prStaRec->ucMaxMpduCount > prEventAmsdu->ucAmsduLen) + prStaRec->ucMaxMpduCount = prEventAmsdu->ucAmsduLen; + + DBGLOG(NIC, INFO, + "Amsdu update event ucWlanIdx[%u] ucLen[%u] ucMaxMpduCount[%u]\n", + prEventAmsdu->ucWlanIdx, prEventAmsdu->ucAmsduLen, + prStaRec->ucMaxMpduCount); + break; + } +#ifdef CFG_GET_TEMPURATURE + + case EXT_EVENT_ID_GET_SENSOR_RESULT: + { + u4QueryInfoLen = sizeof(uint32_t); + /* 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, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + break; + } +#endif /* CFG_GET_TEMPURATURE */ + + + default: + break; + } + + if (prCmdInfo != NULL) { + if ((prCmdInfo->fgIsOid) != 0) { + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + } +#if (CFG_SUPPORT_TXPOWER_INFO == 1) + else if ((prEvent->ucExtenEID) == + EXT_EVENT_ID_TX_POWER_FEATURE_CTRL) { + u4QueryInfoLen = sizeof(struct + PARAM_TXPOWER_ALL_RATE_POWER_INFO_T); + /* 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, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + } +#endif +} + +void nicEventMicErrorInfo(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct EVENT_MIC_ERR_INFO *prMicError; + /* P_PARAM_AUTH_EVENT_T prAuthEvent; */ + struct STA_RECORD *prStaRec; + + DBGLOG(RSN, EVENT, "EVENT_ID_MIC_ERR_INFO\n"); + + prMicError = (struct EVENT_MIC_ERR_INFO *) ( + prEvent->aucBuffer); + prStaRec = cnmGetStaRecByAddress(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, + prAdapter->rWlanInfo.rCurrBssId.arMacAddress); + ASSERT(prStaRec); + + if (prStaRec) + rsnTkipHandleMICFailure(prAdapter, prStaRec, + (u_int8_t) prMicError->u4Flags); + else + DBGLOG(RSN, INFO, "No STA rec!!\n"); +#if 0 + prAuthEvent = (struct PARAM_AUTH_EVENT *) + prAdapter->aucIndicationEventBuffer; + + /* Status type: Authentication Event */ + prAuthEvent->rStatus.eStatusType = + ENUM_STATUS_TYPE_AUTHENTICATION; + + /* Authentication request */ + prAuthEvent->arRequest[0].u4Length = sizeof( + struct PARAM_AUTH_REQUEST); + kalMemCopy((void *) prAuthEvent->arRequest[0].arBssid, + (void *) prAdapter->rWlanInfo.rCurrBssId.arMacAddress, + 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, + (void *) prAuthEvent, + sizeof(struct PARAM_STATUS_INDICATION) + sizeof( + struct PARAM_AUTH_REQUEST)); +#endif +} + +void nicEventScanDone(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + scnEventScanDone(prAdapter, + (struct EVENT_SCAN_DONE *) (prEvent->aucBuffer), TRUE); +} + +void nicEventSchedScanDone(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + DBGLOG(INIT, INFO, "EVENT_ID_SCHED_SCAN_DONE\n"); + scnEventSchedScanDone(prAdapter, + (struct EVENT_SCHED_SCAN_DONE *) (prEvent->aucBuffer)); +#if CFG_SUPPORT_PNO + prAdapter->prAisBssInfo->fgIsPNOEnable = FALSE; + if (prAdapter->prAisBssInfo->fgIsNetRequestInActive + && prAdapter->prAisBssInfo->fgIsPNOEnable) { + UNSET_NET_ACTIVE(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex); + DBGLOG(INIT, INFO, + "INACTIVE AIS from ACTIVE to disable PNO\n"); + /* sync with firmware */ + nicDeactivateNetwork(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex); + } +#endif +} + +void nicEventSleepyNotify(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ +#if !defined(_HIF_USB) + struct EVENT_SLEEPY_INFO *prEventSleepyNotify; + + prEventSleepyNotify = (struct EVENT_SLEEPY_INFO *) ( + prEvent->aucBuffer); + + prAdapter->fgWiFiInSleepyState = (u_int8_t) ( + prEventSleepyNotify->ucSleepyState); + +#if CFG_SUPPORT_MULTITHREAD + if (prEventSleepyNotify->ucSleepyState) + kalSetFwOwnEvent2Hif(prAdapter->prGlueInfo); +#endif +#endif +} + +void nicEventBtOverWifi(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ +#if CFG_ENABLE_BT_OVER_WIFI + uint8_t aucTmp[sizeof(struct BT_OVER_WIFI_EVENT) + sizeof( + struct BOW_LINK_DISCONNECTED)]; + struct EVENT_BT_OVER_WIFI *prEventBtOverWifi; + struct BT_OVER_WIFI_EVENT *prBowEvent; + struct BOW_LINK_CONNECTED *prBowLinkConnected; + struct BOW_LINK_DISCONNECTED *prBowLinkDisconnected; + + prEventBtOverWifi = (struct EVENT_BT_OVER_WIFI *) ( + prEvent->aucBuffer); + + /* construct event header */ + prBowEvent = (struct BT_OVER_WIFI_EVENT *) aucTmp; + + if (prEventBtOverWifi->ucLinkStatus == 0) { + /* Connection */ + prBowEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_CONNECTED; + prBowEvent->rHeader.ucSeqNumber = 0; + prBowEvent->rHeader.u2PayloadLength = sizeof( + struct BOW_LINK_CONNECTED); + + /* fill event body */ + prBowLinkConnected = (struct 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( + struct BOW_LINK_DISCONNECTED); + + /* fill event body */ + prBowLinkDisconnected = (struct BOW_LINK_DISCONNECTED *) ( + prBowEvent->aucPayload); + prBowLinkDisconnected->ucReason = 0; /* @FIXME */ + kalMemZero(prBowLinkDisconnected->aucPeerAddress, + MAC_ADDR_LEN); /* @FIXME */ + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prBowEvent); + } +#endif +} + +void nicEventStatistics(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct CMD_INFO *prCmdInfo; + + /* buffer statistics for further query */ + prAdapter->fgIsStatValid = TRUE; + prAdapter->rStatUpdateTime = kalGetTimeTick(); + kalMemCopy(&prAdapter->rStatStruct, prEvent->aucBuffer, + sizeof(struct 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); + } +} +void nicEventWlanInfo(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct CMD_INFO *prCmdInfo; + + /* buffer statistics for further query */ + prAdapter->fgIsStatValid = TRUE; + prAdapter->rStatUpdateTime = kalGetTimeTick(); + kalMemCopy(&prAdapter->rEventWlanInfo, prEvent->aucBuffer, + sizeof(struct EVENT_WLAN_INFO)); + + DBGLOG(RSN, INFO, "EVENT_ID_WLAN_INFO"); + /* 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); + } +} + +void nicEventMibInfo(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct CMD_INFO *prCmdInfo; + + + /* buffer statistics for further query */ + prAdapter->fgIsStatValid = TRUE; + prAdapter->rStatUpdateTime = kalGetTimeTick(); + + DBGLOG(RSN, INFO, "EVENT_ID_MIB_INFO"); + /* 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); + } + +} + +void nicEventIpiInfo(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct EVENT_GET_IPI_INFO_T *prEventIpiInfo; + + prEventIpiInfo = (struct EVENT_GET_IPI_INFO_T *)(prEvent->aucBuffer); + + DBGLOG(SW4, INFO, "=== Show IPI Info ===\n"); + DBGLOG(SW4, INFO, " < -92dBm: %d.%03dms (0x%08x)\n", + (prEventIpiInfo->au4IpiValue[0] << 3) / 1000, + (prEventIpiInfo->au4IpiValue[0] << 3) % 1000, + prEventIpiInfo->au4IpiValue[0]); + DBGLOG(SW4, INFO, ">= -92dBm < -89dBm: %d.%03dms (0x%08x)\n", + (prEventIpiInfo->au4IpiValue[1] << 3) / 1000, + (prEventIpiInfo->au4IpiValue[1] << 3) % 1000, + prEventIpiInfo->au4IpiValue[1]); + DBGLOG(SW4, INFO, ">= -89dBm < -86dBm: %d.%03dms (0x%08x)\n", + (prEventIpiInfo->au4IpiValue[2] << 3) / 1000, + (prEventIpiInfo->au4IpiValue[2] << 3) % 1000, + prEventIpiInfo->au4IpiValue[2]); + DBGLOG(SW4, INFO, ">= -86dBm < -83dBm: %d.%03dms (0x%08x)\n", + (prEventIpiInfo->au4IpiValue[3] << 3) / 1000, + (prEventIpiInfo->au4IpiValue[3] << 3) % 1000, + prEventIpiInfo->au4IpiValue[3]); + DBGLOG(SW4, INFO, ">= -83dBm < -80dBm: %d.%03dms (0x%08x)\n", + (prEventIpiInfo->au4IpiValue[4] << 3) / 1000, + (prEventIpiInfo->au4IpiValue[4] << 3) % 1000, + prEventIpiInfo->au4IpiValue[4]); + DBGLOG(SW4, INFO, ">= -80dBm < -75dBm: %d.%03dms (0x%08x)\n", + (prEventIpiInfo->au4IpiValue[5] << 3) / 1000, + (prEventIpiInfo->au4IpiValue[5] << 3) % 1000, + prEventIpiInfo->au4IpiValue[5]); + DBGLOG(SW4, INFO, ">= -75dBm < -70dBm: %d.%03dms (0x%08x)\n", + (prEventIpiInfo->au4IpiValue[6] << 3) / 1000, + (prEventIpiInfo->au4IpiValue[6] << 3) % 1000, + prEventIpiInfo->au4IpiValue[6]); + DBGLOG(SW4, INFO, ">= -70dBm < -65dBm: %d.%03dms (0x%08x)\n", + (prEventIpiInfo->au4IpiValue[7] << 3) / 1000, + (prEventIpiInfo->au4IpiValue[7] << 3) % 1000, + prEventIpiInfo->au4IpiValue[7]); + DBGLOG(SW4, INFO, ">= -65dBm < -60dBm: %d.%03dms (0x%08x)\n", + (prEventIpiInfo->au4IpiValue[8] << 3) / 1000, + (prEventIpiInfo->au4IpiValue[8] << 3) % 1000, + prEventIpiInfo->au4IpiValue[8]); + DBGLOG(SW4, INFO, ">= -60dBm < -55dBm: %d.%03dms (0x%08x)\n", + (prEventIpiInfo->au4IpiValue[9] << 3) / 1000, + (prEventIpiInfo->au4IpiValue[9] << 3) % 1000, + prEventIpiInfo->au4IpiValue[9]); + DBGLOG(SW4, INFO, ">= -55dBm : %d.%03dms (0x%08x)\n", + (prEventIpiInfo->au4IpiValue[10] << 3) / 1000, + (prEventIpiInfo->au4IpiValue[10] << 3) % 1000, + prEventIpiInfo->au4IpiValue[10]); + DBGLOG(SW4, INFO, "======== END ========\n"); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is to decide if the beacon time out is reasonable +* by the TRX and some known factors +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return true if the beacon timeout event is valid after policy checking +* false if the beacon timeout event needs to be ignored +*/ +/*----------------------------------------------------------------------------*/ +bool nicBeaconTimeoutFilterPolicy(IN struct ADAPTER *prAdapter) +{ + struct RX_CTRL *prRxCtrl; + struct TX_CTRL *prTxCtrl; + OS_SYSTIME u4CurrentTime; + bool bValid = true; + uint32_t u4MonitorWindow; + + ASSERT(prAdapter); + u4MonitorWindow = prAdapter->rWifiVar.u4BeaconTimoutFilterDurationMs; + if (u4MonitorWindow == 0) /* Check if disable the filter */ + return true; + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + GET_CURRENT_SYSTIME(&u4CurrentTime); + + DBGLOG(NIC, INFO, + "u4MonitorWindow: %d, u4CurrentTime: %d, u4LastRxTime: %d, u4LastTxTime: %d", + u4MonitorWindow, u4CurrentTime, + prRxCtrl->u4LastRxTime, prTxCtrl->u4LastTxTime); + + /* Policy 1, if RX in the past duration (in ms) + * Policy 2, if TX done successfully in the past duration (in ms) + * if hit, then the beacon timeout event will be ignored + */ + if (!CHECK_FOR_TIMEOUT(u4CurrentTime, prRxCtrl->u4LastRxTime, + SEC_TO_SYSTIME(MSEC_TO_SEC(u4MonitorWindow)))) { + DBGLOG(NIC, INFO, "Policy 1 hit, RX in the past duration"); + bValid = false; + } else if (!CHECK_FOR_TIMEOUT(u4CurrentTime, prTxCtrl->u4LastTxTime, + SEC_TO_SYSTIME(MSEC_TO_SEC(u4MonitorWindow)))) { + DBGLOG(NIC, INFO, + "Policy 2 hit, TX done successfully in the past duration"); + bValid = false; + } + + DBGLOG(NIC, INFO, "valid beacon time out event?: %d", bValid); + + return bValid; +} + +void nicEventBeaconTimeout(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + DBGLOG(NIC, INFO, "EVENT_ID_BSS_BEACON_TIMEOUT\n"); + + if (prAdapter->fgDisBcnLostDetection == FALSE) { + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + struct EVENT_BSS_BEACON_TIMEOUT *prEventBssBeaconTimeout; + + prEventBssBeaconTimeout = (struct EVENT_BSS_BEACON_TIMEOUT + *) (prEvent->aucBuffer); + + if (prEventBssBeaconTimeout->ucBssIndex >= + prAdapter->ucHwBssIdNum) + return; + + DBGLOG(NIC, INFO, "Reason code: %d\n", + prEventBssBeaconTimeout->ucReasonCode); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prEventBssBeaconTimeout->ucBssIndex); + + if ((prAdapter->prAisBssInfo != NULL) && + (prEventBssBeaconTimeout->ucBssIndex == + prAdapter->prAisBssInfo->ucBssIndex)) { + if (nicBeaconTimeoutFilterPolicy(prAdapter)) { +#if CFG_DISCONN_DEBUG_FEATURE + g_rDisconnInfoTemp.ucBcnTimeoutReason = + prEventBssBeaconTimeout->ucReasonCode; +#endif + aisBssBeaconTimeout(prAdapter); + } + } +#if CFG_ENABLE_WIFI_DIRECT + else if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) + p2pRoleFsmRunEventBeaconTimeout(prAdapter, prBssInfo); +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (GET_BSS_INFO_BY_INDEX(prAdapter, + prEventBssBeaconTimeout->ucBssIndex)->eNetworkType == + NETWORK_TYPE_BOW) { + /* ToDo:: Nothing */ + } +#endif + else { + DBGLOG(RX, ERROR, + "EVENT_ID_BSS_BEACON_TIMEOUT: (ucBssIndex = %d)\n", + prEventBssBeaconTimeout->ucBssIndex); + } + } + +} + +void nicEventUpdateNoaParams(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { + struct EVENT_UPDATE_NOA_PARAMS *prEventUpdateNoaParam; + + prEventUpdateNoaParam = (struct EVENT_UPDATE_NOA_PARAMS *) ( + prEvent->aucBuffer); + + if (GET_BSS_INFO_BY_INDEX(prAdapter, + prEventUpdateNoaParam->ucBssIndex)->eNetworkType + == NETWORK_TYPE_P2P) { + + p2pProcessEvent_UpdateNOAParam(prAdapter, + prEventUpdateNoaParam->ucBssIndex, + prEventUpdateNoaParam); + } else { + ASSERT(0); + } + } +#else + ASSERT(0); +#endif +} + +void nicEventStaAgingTimeout(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + if (prAdapter->fgDisStaAgingTimeoutDetection == FALSE) { + struct EVENT_STA_AGING_TIMEOUT *prEventStaAgingTimeout; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + + prEventStaAgingTimeout = (struct EVENT_STA_AGING_TIMEOUT *) + (prEvent->aucBuffer); + prStaRec = cnmGetStaRecByIndex(prAdapter, + prEventStaAgingTimeout->ucStaRecIdx); + if (prStaRec == NULL) + return; + + DBGLOG(NIC, INFO, "EVENT_ID_STA_AGING_TIMEOUT: STA[%u] " + MACSTR "\n", + prEventStaAgingTimeout->ucStaRecIdx, + MAC2STR(prStaRec->aucMacAddr)); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + bssRemoveClient(prAdapter, prBssInfo, prStaRec); + + if (prAdapter->fgIsP2PRegistered) { + p2pFuncDisconnect(prAdapter, prBssInfo, prStaRec, FALSE, + REASON_CODE_DISASSOC_INACTIVITY); + } + + } + /* gDisStaAgingTimeoutDetection */ +} + +void nicEventApObssStatus(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) + rlmHandleObssStatusEventPkt(prAdapter, + (struct EVENT_AP_OBSS_STATUS *) prEvent->aucBuffer); +#endif +} + +void nicEventRoamingStatus(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ +#if CFG_SUPPORT_ROAMING + struct CMD_ROAMING_TRANSIT *prTransit; + + prTransit = (struct CMD_ROAMING_TRANSIT *) ( + prEvent->aucBuffer); + + roamingFsmProcessEvent(prAdapter, prTransit); +#endif /* CFG_SUPPORT_ROAMING */ +} + +void nicEventSendDeauth(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct SW_RFB rSwRfb; + + DBGLOG(NIC, INFO, "%s\n", __func__); +#if DBG + struct WLAN_MAC_HEADER *prWlanMacHeader; + + prWlanMacHeader = (struct WLAN_MAC_HEADER *)prEvent->aucBuffer; + DBGLOG(RX, TRACE, "nicRx: aucAddr1: " MACSTR "\n", + MAC2STR(prWlanMacHeader->aucAddr1)); + DBGLOG(RX, TRACE, "nicRx: aucAddr2: " MACSTR "\n", + MAC2STR(prWlanMacHeader->aucAddr2)); +#endif + + /* receive packets without StaRec */ + rSwRfb.pvHeader = (struct WLAN_MAC_HEADER *)prEvent->aucBuffer; + if (authSendDeauthFrame(prAdapter, NULL, NULL, &rSwRfb, + REASON_CODE_CLASS_3_ERR, + (PFN_TX_DONE_HANDLER) NULL) == WLAN_STATUS_SUCCESS) { + + DBGLOG(RX, ERROR, "Send Deauth Error\n"); + } +} + +void nicEventUpdateRddStatus(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ +#if CFG_SUPPORT_RDD_TEST_MODE + struct EVENT_RDD_STATUS *prEventRddStatus; + + prEventRddStatus = (struct EVENT_RDD_STATUS *) ( + prEvent->aucBuffer); + + prAdapter->ucRddStatus = prEventRddStatus->ucRddStatus; +#endif +} + +void nicEventUpdateBwcsStatus(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct PTA_IPC *prEventBwcsStatus; + + prEventBwcsStatus = (struct PTA_IPC *) (prEvent->aucBuffer); + +#if CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(RSN, EVENT, "BCM BWCS Event: %02x%02x%02x%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, + (void *) prEventBwcsStatus, sizeof(struct PTA_IPC)); +} + +void nicEventUpdateBcmDebug(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct PTA_IPC *prEventBwcsStatus; + + prEventBwcsStatus = (struct PTA_IPC *) (prEvent->aucBuffer); + +#if CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(RSN, EVENT, "BCM FW status: %02x%02x%02x%02x\n", + prEventBwcsStatus->u.aucBTPParams[0], + prEventBwcsStatus->u.aucBTPParams[1], + prEventBwcsStatus->u.aucBTPParams[2], + prEventBwcsStatus->u.aucBTPParams[3]); +#endif +} + +void nicEventAddPkeyDone(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct EVENT_ADD_KEY_DONE_INFO *prKeyDone; + struct STA_RECORD *prStaRec = NULL; + uint8_t ucKeyId; + + prKeyDone = (struct EVENT_ADD_KEY_DONE_INFO *) ( + prEvent->aucBuffer); + + DBGLOG(RSN, INFO, "EVENT_ID_ADD_PKEY_DONE BSSIDX=%d " MACSTR + "\n", + prKeyDone->ucBSSIndex, MAC2STR(prKeyDone->aucStaAddr)); + + prStaRec = cnmGetStaRecByAddress(prAdapter, + prKeyDone->ucBSSIndex, + prKeyDone->aucStaAddr); + + if (!prStaRec) { + ucKeyId = prAdapter->rWifiVar. + rAisSpecificBssInfo.ucKeyAlgorithmId; + if ((ucKeyId == CIPHER_SUITE_WEP40) + || (ucKeyId == CIPHER_SUITE_WEP104)) { + DBGLOG(RX, INFO, "WEP, ucKeyAlgorithmId= %d\n", + ucKeyId); + prStaRec = cnmGetStaRecByAddress(prAdapter, + prKeyDone->ucBSSIndex, + prAdapter->rWifiVar.arBssInfoPool[ + prKeyDone->ucBSSIndex].aucBSSID); + if (!prStaRec) { + DBGLOG(RX, INFO, + "WEP, AddPKeyDone, ucBSSIndex %d, Addr " + MACSTR ", StaRec is NULL\n", + prKeyDone->ucBSSIndex, + MAC2STR(prAdapter->rWifiVar + .arBssInfoPool[prKeyDone-> + ucBSSIndex].aucBSSID)); + } + } else { + DBGLOG(RX, INFO, + "AddPKeyDone, ucBSSIndex %d, Addr " + MACSTR ", StaRec is NULL\n", + prKeyDone->ucBSSIndex, + MAC2STR(prKeyDone->aucStaAddr)); + } + } + if (prStaRec) { + DBGLOG(RSN, INFO, "STA " MACSTR " Add Key Done!!\n", + MAC2STR(prStaRec->aucMacAddr)); + prStaRec->fgIsTxKeyReady = TRUE; + qmUpdateStaRec(prAdapter, prStaRec); + } + + prAdapter->fgIsAddKeyDone = TRUE; +} + +void nicEventIcapDone(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct EVENT_ICAP_STATUS *prEventIcapStatus; + struct PARAM_CUSTOM_MEM_DUMP_STRUCT rMemDumpInfo; + uint32_t u4QueryInfo; + + prEventIcapStatus = (struct EVENT_ICAP_STATUS *) ( + prEvent->aucBuffer); + + rMemDumpInfo.u4Address = prEventIcapStatus->u4StartAddress; + rMemDumpInfo.u4Length = prEventIcapStatus->u4IcapSieze; +#if CFG_SUPPORT_QA_TOOL + rMemDumpInfo.u4IcapContent = + prEventIcapStatus->u4IcapContent; +#endif + + wlanoidQueryMemDump(prAdapter, &rMemDumpInfo, + sizeof(rMemDumpInfo), &u4QueryInfo); +} + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +struct PARAM_CAL_BACKUP_STRUCT_V2 g_rCalBackupDataV2; + +void nicEventCalAllDone(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct CMD_CAL_BACKUP_STRUCT_V2 *prEventCalBackupDataV2; + uint32_t u4QueryInfo; + + DBGLOG(RFTEST, INFO, "%s\n", __func__); + + memset(&g_rCalBackupDataV2, 0, + sizeof(struct PARAM_CAL_BACKUP_STRUCT_V2)); + + prEventCalBackupDataV2 = (struct CMD_CAL_BACKUP_STRUCT_V2 *) + (prEvent->aucBuffer); + + if (prEventCalBackupDataV2->ucReason == 1 + && prEventCalBackupDataV2->ucAction == 2) { + DBGLOG(RFTEST, INFO, + "Received an EVENT for Trigger Do All Cal Function.\n"); + + g_rCalBackupDataV2.ucReason = 2; + g_rCalBackupDataV2.ucAction = 4; + g_rCalBackupDataV2.ucNeedResp = 1; + g_rCalBackupDataV2.ucFragNum = 0; + g_rCalBackupDataV2.ucRomRam = 0; + g_rCalBackupDataV2.u4ThermalValue = 0; + g_rCalBackupDataV2.u4Address = 0; + g_rCalBackupDataV2.u4Length = 0; + g_rCalBackupDataV2.u4RemainLength = 0; + + DBGLOG(RFTEST, INFO, + "RLM CMD : Get Cal Data from FW (%s). Start!!!!!!!!!!!!!!!!\n", + g_rCalBackupDataV2.ucRomRam == 0 ? "ROM" : "RAM"); + DBGLOG(RFTEST, INFO, "Thermal Temp = %d\n", + g_rBackupCalDataAllV2.u4ThermalInfo); + wlanoidQueryCalBackupV2(prAdapter, + &g_rCalBackupDataV2, + sizeof(struct PARAM_CAL_BACKUP_STRUCT_V2), + &u4QueryInfo); + } + +} +#endif + +void nicEventDebugMsg(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct EVENT_DEBUG_MSG *prEventDebugMsg; + uint8_t ucMsgType; + uint16_t u2MsgSize; + uint8_t *pucMsg; + + prEventDebugMsg = (struct EVENT_DEBUG_MSG *)( + prEvent->aucBuffer); + ucMsgType = prEventDebugMsg->ucMsgType; + u2MsgSize = prEventDebugMsg->u2MsgSize; + pucMsg = prEventDebugMsg->aucMsg; + +#if CFG_SUPPORT_QA_TOOL + if (ucMsgType == DEBUG_MSG_TYPE_ASCII) { + if (kalStrnCmp("[RECAL DUMP START]", pucMsg, 18) == 0) { + prAdapter->rReCalInfo.fgDumped = TRUE; + return; + } else if (kalStrnCmp("[RECAL DUMP END]", pucMsg, 16) == 0) { + prAdapter->rReCalInfo.fgDumped = TRUE; + return; + } else if (prAdapter->rReCalInfo.fgDumped && + kalStrnCmp("[Recal]", pucMsg, 7) == 0) { + struct WIFI_EVENT *prTmpEvent; + struct EXT_EVENT_RECAL_DATA_T *prCalData; + uint32_t u4Size = sizeof(struct WIFI_EVENT) + + sizeof(struct EXT_EVENT_RECAL_DATA_T); + + prTmpEvent = (struct WIFI_EVENT *) + kalMemAlloc(u4Size, VIR_MEM_TYPE); + kalMemZero(prTmpEvent, u4Size); + + prCalData = (struct EXT_EVENT_RECAL_DATA_T *) + prTmpEvent->aucBuffer; + prCalData->u4FuncIndex = RE_CALIBRATION; + prCalData->u4Type = 0; + /* format: [XXXXXXXX][YYYYYYYY]ZZZZZZZZ */ + kalMemCopy(prCalData->u.ucData, pucMsg + 7, 28); + nicRfTestEventHandler(prAdapter, prTmpEvent); + kalMemFree(prTmpEvent, VIR_MEM_TYPE, u4Size); + } + } +#endif + + wlanPrintFwLog(pucMsg, u2MsgSize, ucMsgType, " "); +} + +void nicEventTdls(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ +#if CFG_SUPPORT_TDLS + TdlsexEventHandle(prAdapter->prGlueInfo, + (uint8_t *)prEvent->aucBuffer, + (uint32_t)(prEvent->u2PacketLength - 8)); +#endif +} + +void nicEventRssiMonitor(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + int32_t rssi = 0; + struct GLUE_INFO *prGlueInfo; + struct wiphy *wiphy; + + prGlueInfo = prAdapter->prGlueInfo; + wiphy = priv_to_wiphy(prGlueInfo); + + kalMemCopy(&rssi, prEvent->aucBuffer, sizeof(int32_t)); + DBGLOG(RX, TRACE, "EVENT_ID_RSSI_MONITOR value=%d\n", rssi); +#if KERNEL_VERSION(3, 16, 0) <= LINUX_VERSION_CODE + mtk_cfg80211_vendor_event_rssi_beyond_range(wiphy, + prGlueInfo->prDevHandler->ieee80211_ptr, rssi); +#endif +} + +void nicEventDumpMem(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct CMD_INFO *prCmdInfo; + + DBGLOG(SW4, INFO, "%s: EVENT_ID_DUMP_MEM\n", __func__); + + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + DBGLOG(NIC, INFO, ": ==> 1\n"); + 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); + } else { + /* Burst mode */ + DBGLOG(NIC, INFO, ": ==> 2\n"); +#if 0 + nicEventQueryMemDump(prAdapter, prEvent->aucBuffer); +#endif + } +} + +void nicEventAssertDump(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct mt66xx_chip_info *prChipInfo = NULL; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + if (wlanIsChipRstRecEnabled(prAdapter)) + wlanChipRstPreAct(prAdapter); + + if (prEvent->ucS2DIndex == S2D_INDEX_EVENT_N2H) { + if (!prAdapter->fgN9AssertDumpOngoing) { + DBGLOG(NIC, ERROR, + "%s: EVENT_ID_ASSERT_DUMP\n", __func__); + DBGLOG(NIC, ERROR, + "\n[DUMP_N9]====N9 ASSERT_DUMPSTART====\n"); + prAdapter->fgKeepPrintCoreDump = TRUE; + if (kalOpenCorDumpFile(TRUE) != WLAN_STATUS_SUCCESS) + DBGLOG(NIC, ERROR, "kalOpenCorDumpFile fail\n"); + else + prAdapter->fgN9CorDumpFileOpend = TRUE; + + prAdapter->fgN9AssertDumpOngoing = TRUE; + wlanCorDumpTimerInit(prAdapter, TRUE); + } + if (prAdapter->fgN9AssertDumpOngoing) { + + if (prAdapter->fgKeepPrintCoreDump) + DBGLOG(NIC, ERROR, "[DUMP_N9]%s:\n", + prEvent->aucBuffer); + if (!kalStrnCmp(prEvent->aucBuffer, + ";more log added here", 5) + || !kalStrnCmp(prEvent->aucBuffer, + ";[core dump start]", 5)) + prAdapter->fgKeepPrintCoreDump = FALSE; + + if (prAdapter->fgN9CorDumpFileOpend) { + if (kalWriteCorDumpFile( + prEvent->aucBuffer, + prEvent->u2PacketLength - + prChipInfo->event_hdr_size, + TRUE) != WLAN_STATUS_SUCCESS) { + DBGLOG(NIC, INFO, + "kalWriteN9CorDumpFile fail\n"); + } + } + wlanCorDumpTimerReset(prAdapter, TRUE); + } + } else { + /* prEvent->ucS2DIndex == S2D_INDEX_EVENT_C2H */ + if (!prAdapter->fgCr4AssertDumpOngoing) { + DBGLOG(NIC, ERROR, + "%s: EVENT_ID_ASSERT_DUMP\n", __func__); + DBGLOG(NIC, ERROR, + "\n[DUMP_Cr4]====CR4 ASSERT_DUMPSTART====\n"); + prAdapter->fgKeepPrintCoreDump = TRUE; + if (kalOpenCorDumpFile(FALSE) != WLAN_STATUS_SUCCESS) + DBGLOG(NIC, ERROR, "kalOpenCorDumpFile fail\n"); + else + prAdapter->fgCr4CorDumpFileOpend = TRUE; + + prAdapter->fgCr4AssertDumpOngoing = TRUE; + wlanCorDumpTimerInit(prAdapter, FALSE); + } + if (prAdapter->fgCr4AssertDumpOngoing) { + if (prAdapter->fgKeepPrintCoreDump) + DBGLOG(NIC, ERROR, "[DUMP_CR4]%s:\n", + prEvent->aucBuffer); + if (!kalStrnCmp(prEvent->aucBuffer, + ";more log added here", 5)) + prAdapter->fgKeepPrintCoreDump = FALSE; + + if (prAdapter->fgCr4CorDumpFileOpend) { + if (kalWriteCorDumpFile( + prEvent->aucBuffer, + prEvent->u2PacketLength - + prChipInfo->event_hdr_size, + FALSE) != WLAN_STATUS_SUCCESS) { + DBGLOG(NIC, ERROR, + "kalWriteN9CorDumpFile fail\n"); + } + } + wlanCorDumpTimerReset(prAdapter, FALSE); + } + } +} + +void nicEventRddSendPulse(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + DBGLOG(RLM, INFO, "%s: EVENT_ID_RDD_SEND_PULSE\n", + __func__); + + nicEventRddPulseDump(prAdapter, prEvent->aucBuffer); +} + +void nicEventUpdateCoexPhyrate(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + uint8_t i; + struct EVENT_UPDATE_COEX_PHYRATE *prEventUpdateCoexPhyrate; + + ASSERT(prAdapter); + + DBGLOG(NIC, LOUD, "%s\n", __func__); + + prEventUpdateCoexPhyrate = (struct EVENT_UPDATE_COEX_PHYRATE + *)(prEvent->aucBuffer); + + for (i = 0; i < (prAdapter->ucHwBssIdNum + 1); i++) { + prAdapter->aprBssInfo[i]->u4CoexPhyRateLimit = + prEventUpdateCoexPhyrate->au4PhyRateLimit[i]; + DBGLOG(NIC, INFO, "Coex:BSS[%d]R:%d\n", i, + prAdapter->aprBssInfo[i]->u4CoexPhyRateLimit); + } + + prAdapter->ucSmarGearSupportSisoOnly = + prEventUpdateCoexPhyrate->ucSupportSisoOnly; + prAdapter->ucSmartGearWfPathSupport = + prEventUpdateCoexPhyrate->ucWfPathSupport; + + DBGLOG(NIC, INFO, "Smart Gear SISO:%d, WF:%d\n", + prAdapter->ucSmarGearSupportSisoOnly, + prAdapter->ucSmartGearWfPathSupport); +} + +#if (CFG_WOW_SUPPORT == 1) +void nicEventWakeUpReason(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct _EVENT_WAKEUP_REASON_INFO *prWakeUpReason; + struct GLUE_INFO *prGlueInfo; +#if CFG_SUPPORT_MAGIC_PKT_VENDOR_EVENT + struct wiphy *wiphy; +#endif + + DBGLOG(NIC, INFO, "nicEventWakeUpReason\n"); + prGlueInfo = prAdapter->prGlueInfo; + + /* Driver receives EVENT_ID_WOW_WAKEUP_REASON after fw wake up host + * The possible Wakeup Reason define in FW as following + * 0: MAGIC PACKET + * 1: BITMAP + * 2: ARPNS + * 3: GTK_REKEY + * 4: COALESCING_FILTER + * 5: HW_GLOBAL_ENABLE + * 6: TCP_SYN PACKET + * 7: TDLS + * 8: DISCONNECT + * 9: IPV4_UDP PACKET + * 10: IPV4_TCP PACKET + * 11: IPV6_UDP PACKET + * 12: IPV6_TCP PACKET + */ + prWakeUpReason = + (struct _EVENT_WAKEUP_REASON_INFO *) (prEvent->aucBuffer); + prGlueInfo->prAdapter->rWowCtrl.ucReason = prWakeUpReason->reason; + DBGLOG(NIC, INFO, "nicEventWakeUpReason:%d\n", + prGlueInfo->prAdapter->rWowCtrl.ucReason); + +#if CFG_SUPPORT_MAGIC_PKT_VENDOR_EVENT + wiphy = priv_to_wiphy(prGlueInfo); + if (prWakeUpReason->reason == ENUM_PF_CMD_TYPE_MAGIC) { + DBGLOG(RX, INFO, + "EVENT ID[0x%02X] Find Magic Packet!!\n", + prEvent->ucEID); + mtk_cfg80211_vendor_event_wowlan_magic_pkt(wiphy, + prGlueInfo->prDevHandler->ieee80211_ptr, 0); + } +#endif +} +#endif + +void nicCmdEventQueryCnmInfo(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct PARAM_GET_CNM_T *prCnmInfoQuery = NULL; + struct PARAM_GET_CNM_T *prCnmInfoEvent = NULL; + struct GLUE_INFO *prGlueInfo; + uint32_t u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + if (prCmdInfo->fgIsOid) { + prCnmInfoQuery = (struct PARAM_GET_CNM_T *) + prCmdInfo->pvInformationBuffer; + prCnmInfoEvent = (struct PARAM_GET_CNM_T *)pucEventBuf; + kalMemCopy(prCnmInfoQuery, prCnmInfoEvent, + sizeof(struct PARAM_GET_CNM_T)); + + prGlueInfo = prAdapter->prGlueInfo; + u4QueryInfoLen = sizeof(struct PARAM_GET_CNM_T); + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +void nicEventCnmInfo(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct CMD_INFO *prCmdInfo; + + /* 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); + } +} + +#if CFG_SUPPORT_REPLAY_DETECTION +void nicCmdEventSetAddKey(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct WIFI_CMD *prWifiCmd = NULL; + struct CMD_802_11_KEY *prCmdKey = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct GL_DETECT_REPLAY_INFO *prDetRplyInfo = NULL; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4InformationBufferLength, + WLAN_STATUS_SUCCESS); + } + + prGlueInfo = prAdapter->prGlueInfo; + prDetRplyInfo = &prGlueInfo->prDetRplyInfo; + if (pucEventBuf) { + prWifiCmd = (struct WIFI_CMD *) (pucEventBuf); + prCmdKey = (struct CMD_802_11_KEY *) (prWifiCmd->aucBuffer); + + if (!prCmdKey->ucKeyType && + prCmdKey->ucKeyId >= 0 && prCmdKey->ucKeyId < 4) { + /* Only save data broadcast key info. + * ucKeyType == 1 means unicast key + * ucKeyId == 4 or ucKeyId == 5 means it is a PMF key + */ + + prDetRplyInfo->ucCurKeyId = prCmdKey->ucKeyId; + prDetRplyInfo->ucKeyType = prCmdKey->ucKeyType; + prDetRplyInfo->arReplayPNInfo[ + prCmdKey->ucKeyId].fgRekey = TRUE; + prDetRplyInfo->arReplayPNInfo[ + prCmdKey->ucKeyId].fgFirstPkt = TRUE; + DBGLOG(NIC, TRACE, "Keyid is %d, ucKeyType is %d\n", + prCmdKey->ucKeyId, prCmdKey->ucKeyType); + } + } +} +void nicOidCmdTimeoutSetAddKey(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo) +{ + ASSERT(prAdapter); + + DBGLOG(NIC, WARN, "Wlan setaddkey timeout.\n"); + if (prCmdInfo->fgIsOid) + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, + 0, WLAN_STATUS_FAILURE); +} +#endif + +#if CFG_SUPPORT_ANT_DIV +void nicCmdEventAntDiv(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + struct CMD_ANT_DIV_CTRL *prAntDivInfo; + uint32_t u4QueryInfoLen; + + if (prAdapter == NULL) { + DBGLOG(RSN, INFO, "prAdapter is null\n"); + return; + } + if (prCmdInfo == NULL) { + DBGLOG(RSN, INFO, "prCmdInfo is null\n"); + return; + } + + if (prCmdInfo->fgIsOid) { + u4QueryInfoLen = sizeof(struct CMD_ANT_DIV_CTRL); + prAntDivInfo = (struct CMD_ANT_DIV_CTRL *) + prCmdInfo->pvInformationBuffer; + + if (pucEventBuf && prAntDivInfo) + kalMemCopy(prAntDivInfo, pucEventBuf, u4QueryInfoLen); + + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + } +} + +void nicEventGetGtkDataSync(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct PARAM_GTK_REKEY_DATA *prGtkData = NULL; + struct GL_DETECT_REPLAY_INFO *prDetRplyInfo = NULL; + uint8_t ucCurKeyId; + + prGtkData = (struct PARAM_GTK_REKEY_DATA *) (prEvent->aucBuffer); + prDetRplyInfo = &prAdapter->prGlueInfo->prDetRplyInfo; + prDetRplyInfo->ucCurKeyId = prGtkData->ucCurKeyId; + ucCurKeyId = prDetRplyInfo->ucCurKeyId; + + /* index bounds check */ + if (ucCurKeyId >= MAX_KEY_NUM) { + DBGLOG(RSN, WARN, "Invalid KeyId of PN: %d, out of bound.\n", + ucCurKeyId); + return; + } + + kalMemZero(prDetRplyInfo->arReplayPNInfo[ucCurKeyId].auPN, + NL80211_REPLAY_CTR_LEN); + +#if 0 + /* + * if Drv alread rx a new PN value large than fw PN, + * then skip PN update. + */ + if (qmRxDetectReplay(prGtkData->aucReplayCtr, + prDetRplyInfo->arReplayPNInfo[ucCurKeyId].auPN)) + return; +#endif + + kalMemCopy(prDetRplyInfo->arReplayPNInfo[ucCurKeyId].auPN, + prGtkData->aucReplayCtr, 6); + + DBGLOG(RSN, INFO, "Get BC/MC PN update from fw.\n"); + + DBGLOG_MEM8(RSN, INFO, + (uint8_t *)prDetRplyInfo->arReplayPNInfo[ucCurKeyId].auPN, + NL80211_REPLAY_CTR_LEN); +} + +#endif + +void nicCmdEventGetTxPwrTbl(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct GLUE_INFO *prGlueInfo; + struct EVENT_GET_TXPWR_TBL *prTxPwrTblEvent = NULL; + struct PARAM_CMD_GET_TXPWR_TBL *prTxPwrTbl = NULL; + void *info_buf = NULL; + + if (!prAdapter) { + DBGLOG(NIC, ERROR, "NULL prAdapter!\n"); + return; + } + + if (!prCmdInfo) { + DBGLOG(NIC, ERROR, "NULL prCmdInfo!\n"); + return; + } + + if (!pucEventBuf || !prCmdInfo->pvInformationBuffer) { + if (prCmdInfo->fgIsOid) { + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + 0, + WLAN_STATUS_FAILURE); + } + + if (!pucEventBuf) + DBGLOG(NIC, WARN, "NULL pucEventBuf!\n"); + + if (!prCmdInfo->pvInformationBuffer) + DBGLOG(NIC, WARN, "NULL pvInformationBuffer!\n"); + + return; + } + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + info_buf = prCmdInfo->pvInformationBuffer; + prTxPwrTblEvent = (struct EVENT_GET_TXPWR_TBL *) pucEventBuf; + prTxPwrTbl = (struct PARAM_CMD_GET_TXPWR_TBL *) info_buf; + + u4QueryInfoLen = sizeof(struct PARAM_CMD_GET_TXPWR_TBL); + + prTxPwrTbl->ucCenterCh = prTxPwrTblEvent->ucCenterCh; + + kalMemCopy(prTxPwrTbl->tx_pwr_tbl, + prTxPwrTblEvent->tx_pwr_tbl, + sizeof(prTxPwrTblEvent->tx_pwr_tbl)); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +#ifdef CFG_GET_TEMPURATURE +void nicCmdEventGetTemperature(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct GLUE_INFO *prGlueInfo; + struct EVENT_GET_THERMAL_SENSOR *event_temperature = NULL; + + int *temperature = NULL; + + if (!prAdapter) { + DBGLOG(NIC, ERROR, "NULL prAdapter!\n"); + return; + } + + if (!prCmdInfo) { + DBGLOG(NIC, ERROR, "NULL prCmdInfo!\n"); + return; + } + + if (!pucEventBuf || !prCmdInfo->pvInformationBuffer) { + if (prCmdInfo->fgIsOid) { + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + 0, + WLAN_STATUS_FAILURE); + } + + if (!pucEventBuf) + DBGLOG(NIC, WARN, "NULL pucEventBuf!\n"); + + if (!prCmdInfo->pvInformationBuffer) + DBGLOG(NIC, WARN, "NULL pvInformationBuffer!\n"); + return; + } + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + event_temperature = + (struct EVENT_GET_THERMAL_SENSOR *)pucEventBuf; + temperature = (int *)prCmdInfo->pvInformationBuffer; + *temperature = (int)event_temperature->u4SensorResult; + + u4QueryInfoLen = sizeof(int); + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} +#endif +#if (CFG_SUPPORT_GET_MCS_INFO == 1) +void nicCmdEventQueryTxMcsInfo(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + uint32_t u4QueryInfoLen; + struct GLUE_INFO *prGlueInfo; + struct EVENT_TX_MCS_INFO *prTxMcsEvent; + struct PARAM_TX_MCS_INFO *prTxMcsInfo; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + ASSERT(prCmdInfo->pvInformationBuffer); + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + prTxMcsEvent = (struct EVENT_TX_MCS_INFO *) pucEventBuf; + prTxMcsInfo = (struct PARAM_TX_MCS_INFO *) + prCmdInfo->pvInformationBuffer; + + u4QueryInfoLen = sizeof(struct EVENT_TX_MCS_INFO); + + kalMemCopy(prTxMcsInfo->au2TxRateCode, + prTxMcsEvent->au2TxRateCode, + sizeof(prTxMcsEvent->au2TxRateCode)); + kalMemCopy(prTxMcsInfo->aucTxRatePer, + prTxMcsEvent->aucTxRatePer, + sizeof(prTxMcsEvent->aucTxRatePer)); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + + +} + +void nicEventTxMcsInfo(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct CMD_INFO *prCmdInfo; + + DBGLOG(RSN, INFO, "EVENT_ID_TX_MCS_INFO"); + /* 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); + } +} +#endif + +#ifdef CFG_SUPPORT_TIME_MEASURE +void nicCmdEventGetTmReport( + IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf +) +{ + uint32_t u4QueryInfoLen; + struct GLUE_INFO *prGlueInfo; + struct EVENT_TM_REPORT_T *prEvtTmRpt = NULL; + struct PARAM_TM_T *prTmrParam = NULL; + uint64_t u8TimeDiff; + uint64_t u8TimeDiff2; + + if (!prAdapter) { + DBGLOG(INIT, ERROR, "prAdapter is NULL.\n"); + return; + } + if (!pucEventBuf) { + DBGLOG(INIT, ERROR, "pucEventBuf is NULL.\n"); + return; + } + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "prCmdInfo is NULL.\n"); + return; + } + if (!prCmdInfo->pvInformationBuffer) { + DBGLOG(INIT, ERROR, "prCmdInfo->pvInformationBuffer is NULL\n"); + return; + } + if (!prCmdInfo->fgIsOid) { + DBGLOG(INIT, ERROR, "cmd %u seq #%u not oid!", + prCmdInfo->ucCID, + prCmdInfo->ucCmdSeqNum); + return; + } + prGlueInfo = prAdapter->prGlueInfo; + + prEvtTmRpt = (struct EVENT_TM_REPORT_T *) (pucEventBuf); + + u4QueryInfoLen = prEvtTmRpt->u2CmdLen; + + prTmrParam = (struct PARAM_TM_T *) prCmdInfo->pvInformationBuffer; + + prTmrParam->u2NumOfValidResult = prEvtTmRpt->u2NumOfValidResult; + prTmrParam->u4DistanceCm = prEvtTmRpt->u4DistanceCm; + prTmrParam->u8DistStdevSq = prEvtTmRpt->u8DistStdevSq; + COPY_MAC_ADDR(prTmrParam->aucRttPeerAddr, prEvtTmRpt->aucRttPeerAddr); + if (prEvtTmRpt->u2CmdLen == + OFFSET_OF(struct EVENT_TM_REPORT_T, aucPadding2[0])) { + prTmrParam->u8Tsf = prEvtTmRpt->u8Tsf; + prTmrParam->i8ClockOffset = prEvtTmRpt->i8ClockOffset; + prTmrParam->i8ClkRateDiffRatioIn10ms = + prEvtTmRpt->i8ClkRateDiffRatioIn10ms; + prTmrParam->u8LastToA = prEvtTmRpt->u8LastToA; + + u8TimeDiff = (prEvtTmRpt->u8Tsf < g_u8NicCnt) ? + (prEvtTmRpt->u8Tsf + BIT64(48) - g_u8NicCnt) : + (prEvtTmRpt->u8Tsf - g_u8NicCnt); + u8TimeDiff2 = g_u8SysClkps - g_u8LastSysClkps; + + g_i8HostClkRateDiff = div64_s64( + AUDIO_SYNC_CLK_RATE_DIFF_DIVISOR * + ((int64_t)u8TimeDiff - + (int64_t)u8TimeDiff2), + u8TimeDiff2); + g_u8NicCnt = prEvtTmRpt->u8Tsf; + g_i8ClockOffset = prEvtTmRpt->i8ClockOffset; + g_i8ClkRateDiff = prEvtTmRpt->i8ClkRateDiffRatioIn10ms; + g_u8LastToA = prEvtTmRpt->u8LastToA; + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic_pwr_mgt.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic_pwr_mgt.c new file mode 100644 index 0000000000000..48da5e3f0f296 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic_pwr_mgt.c @@ -0,0 +1,424 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + + +/******************************************************************************* + * C O M P I L E 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 + ******************************************************************************* + */ + +void nicpmWakeUpWiFi(IN struct ADAPTER *prAdapter) +{ + if (!nicVerifyChipID(prAdapter)) { + DBGLOG(INIT, ERROR, "Chip id verify error!\n"); + return; + } + HAL_WAKE_UP_WIFI(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to process the POWER ON procedure. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicpmSetFWOwn(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnableGlobalInt) +{ + halSetFWOwn(prAdapter, fgEnableGlobalInt); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to process the POWER OFF procedure. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +u_int8_t nicpmSetDriverOwn(IN struct ADAPTER *prAdapter) +{ + return halSetDriverOwn(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to set ACPI power mode to D0. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +u_int8_t nicpmSetAcpiPowerD0(IN struct ADAPTER *prAdapter) +{ + +#if 0 + uint32_t u4Status = WLAN_STATUS_SUCCESS; + uint32_t u4Value = 0, u4WHISR = 0; + uint16_t au2TxCount[16]; + uint32_t i; +#if CFG_ENABLE_FW_DOWNLOAD + uint32_t u4FwImgLength, u4FwLoadAddr, u4Cr4FwImgLength; + void *prFwMappingHandle; + void *pvFwImageMapFile = NULL; + void *pvCr4FwImageMapFile = NULL; +#if CFG_ENABLE_FW_DIVIDED_DOWNLOAD + struct FIRMWARE_DIVIDED_DOWNLOAD *prFwHead; + u_int8_t fgValidHead = TRUE; + +#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(MT6630) + /* 1. Request Ownership to enter F/W download state */ + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); +#if !CFG_ENABLE_FULL_PM + nicpmSetDriverOwn(prAdapter); +#endif + + /* 2. Initialize the Adapter */ + u4Status = nicInitializeAdapter(prAdapter); + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "nicInitializeAdapter failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } +#endif + +#if CFG_ENABLE_FW_DOWNLOAD + prFwMappingHandle = + kalFirmwareImageMapping(prAdapter->prGlueInfo, + &pvFwImageMapFile, &u4FwImgLength, + &pvCr4FwImageMapFile, &u4Cr4FwImgLength); + if (!prFwMappingHandle) { + DBGLOG(INIT, ERROR, + "Fail to load FW image from file!\n"); + pvFwImageMapFile = NULL; + } +#if defined(MT6630) + 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 = + (struct FIRMWARE_DIVIDED_DOWNLOAD *) + ((uint8_t *) + pvFwImageMapFile + u4FwImgLength - + (2 * sizeof(struct FWDL_SECTION_INFO))); +#if 0 + if (prFwHead->u4Signature == MTK_WIFI_SIGNATURE && + prFwHead->u4CRC == wlanCRC32( + (uint8_t *) pvFwImageMapFile + + u4CRCOffset, + u4FwImgLength - u4CRCOffset)) { + fgValidHead = TRUE; + } else { + fgValidHead = FALSE; + } +#endif + /* 3b. engage divided firmware downloading */ + if (fgValidHead == TRUE) { + wlanFwDvdDwnloadHandler(prAdapter, prFwHead, + pvFwImageMapFile, &u4Status); + } else +#endif + { + if (wlanImageSectionConfig(prAdapter, + u4FwLoadAddr, + u4FwImgLength, TRUE) + != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "Firmware download configuration failed!\n"); + + u4Status = WLAN_STATUS_FAILURE; + break; + } + wlanFwDwnloadHandler(prAdapter, u4FwImgLength, + pvFwImageMapFile, &u4Status); + } + /* escape to top */ + if (u4Status != WLAN_STATUS_SUCCESS) { + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, + prFwMappingHandle, pvFwImageMapFile, + pvCr4FwImageMapFile); + 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, + pvCr4FwImageMapFile); + u4Status = WLAN_STATUS_FAILURE; + break; + } +#endif + + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, + prFwMappingHandle, pvFwImageMapFile, + pvCr4FwImageMapFile); + } 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 +#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; + } + i++; + kalMsleep(10); + } + + if (u4Status == WLAN_STATUS_SUCCESS) { + /* 6.1 reset interrupt status */ + HAL_READ_INTR_STATUS(prAdapter, 4, (uint8_t *)&u4WHISR); + if (HAL_IS_TX_DONE_INTR(u4WHISR)) + HAL_READ_TX_RELEASED_COUNT(prAdapter, + au2TxCount); + + /* 6.2 reset TX Resource for normal operation */ + nicTxResetResource(prAdapter); + + /* 6.3 Enable interrupt */ + nicEnableInterrupt(prAdapter); + + /* 6.4 Update basic configuration */ + wlanUpdateBasicConfig(prAdapter); + + /* 6.5 Apply Network Address */ + nicApplyNetworkAddress(prAdapter); + + /* 6.6 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; +#else + return TRUE; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is used to set ACPI power mode to D3. + * + * @param prAdapter pointer to the Adapter handler + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +u_int8_t nicpmSetAcpiPowerD3(IN struct ADAPTER *prAdapter) +{ + /* UINT_32 i; */ + + ASSERT(prAdapter); + +#if 0 + /* 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, TRUE); + + /* 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; +#endif + return TRUE; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic_rate.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic_rate.c new file mode 100644 index 0000000000000..70d9c3f4d1ee1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic_rate.c @@ -0,0 +1,459 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/*! \file "nic_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. + */ + + +/******************************************************************************* + * C O M P I L E 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 uint16_t au2RateCCKLong[CCK_RATE_NUM] = { + 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 */ +}; + +const uint16_t au2RateCCKShort[CCK_RATE_NUM] = { + 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 */ +}; + +const uint16_t au2RateOFDM[OFDM_RATE_NUM] = { + 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 */ +}; + +const uint16_t au2RateHTMixed[HT_RATE_NUM] = { + RATE_MM_MCS_32, /* RATE_MCS32_INDEX, */ + 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, */ +}; + +const uint16_t au2RateHTGreenField[HT_RATE_NUM] = { + RATE_GF_MCS_32, /* RATE_MCS32_INDEX, */ + 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, */ +}; + +const uint16_t au2RateVHT[VHT_RATE_NUM] = { + RATE_VHT_MCS_0, /* RATE_MCS0_INDEX, */ + RATE_VHT_MCS_1, /* RATE_MCS1_INDEX, */ + RATE_VHT_MCS_2, /* RATE_MCS2_INDEX, */ + RATE_VHT_MCS_3, /* RATE_MCS3_INDEX, */ + RATE_VHT_MCS_4, /* RATE_MCS4_INDEX, */ + RATE_VHT_MCS_5, /* RATE_MCS5_INDEX, */ + RATE_VHT_MCS_6, /* RATE_MCS6_INDEX, */ + RATE_VHT_MCS_7, /* RATE_MCS7_INDEX, */ + RATE_VHT_MCS_8, /* RATE_MCS8_INDEX, */ + RATE_VHT_MCS_9 /* RATE_MCS9_INDEX, */ +}; + +/* in unit of 100kb/s */ +const struct EMU_MAC_RATE_INFO arMcsRate2PhyRate[] = { + /* Phy Rate Code, + * BW20, BW20 SGI, BW40, BW40 SGI, BW80, BW80 SGI, BW160, BW160 SGI + */ + RATE_INFO(PHY_RATE_MCS0, 65, 72, 135, 150, 293, 325, 585, 650), + RATE_INFO(PHY_RATE_MCS1, 130, 144, 270, 300, 585, 650, 1170, 1300), + RATE_INFO(PHY_RATE_MCS2, 195, 217, 405, 450, 878, 975, 1755, 1950), + RATE_INFO(PHY_RATE_MCS3, 260, 289, 540, 600, 1170, 1300, 2340, 2600), + RATE_INFO(PHY_RATE_MCS4, 390, 433, 810, 900, 1755, 1950, 3510, 3900), + RATE_INFO(PHY_RATE_MCS5, 520, 578, 1080, 1200, 2340, 2600, 4680, 5200), + RATE_INFO(PHY_RATE_MCS6, 585, 650, 1215, 1350, 2633, 2925, 5265, 5850), + RATE_INFO(PHY_RATE_MCS7, 650, 722, 1350, 1500, 2925, 3250, 5850, 6500), + RATE_INFO(PHY_RATE_MCS8, 780, 867, 1620, 1800, 3510, 3900, 7020, 7800), + RATE_INFO(PHY_RATE_MCS9, 867, 963, 1800, 2000, 3900, 4333, 7800, 8667), + RATE_INFO(PHY_RATE_MCS32, 0, 0, 60, 67, 0, 0, 0, 0) +}; + +/* in uint of 500kb/s */ +const uint8_t aucHwRate2PhyRate[] = { + RATE_1M, /*1M long */ + RATE_2M, /*2M long */ + RATE_5_5M, /*5.5M long */ + RATE_11M, /*11M long */ + RATE_1M, /*1M short invalid */ + RATE_2M, /*2M short */ + RATE_5_5M, /*5.5M short */ + RATE_11M, /*11M short */ + RATE_48M, /*48M */ + RATE_24M, /*24M */ + RATE_12M, /*12M */ + RATE_6M, /*6M */ + RATE_54M, /*54M */ + RATE_36M, /*36M */ + RATE_18M, /*18M */ + RATE_9M /*9M */ +}; +/******************************************************************************* + * 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 + ******************************************************************************* + */ +uint32_t +nicGetPhyRateByMcsRate( + IN uint8_t ucIdx, + IN uint8_t ucBw, + IN uint8_t ucGI) +{ + return arMcsRate2PhyRate[ucIdx].u4PhyRate[ucBw][ucGI]; +} + +uint32_t +nicGetHwRateByPhyRate( + IN uint8_t ucIdx) +{ + return aucHwRate2PhyRate[ucIdx]; /* uint : 500 kbps */ +} + +uint32_t +nicSwIndex2RateIndex( + IN uint8_t ucRateSwIndex, + OUT uint8_t *pucRateIndex, + OUT uint8_t *pucPreambleOption +) +{ + ASSERT(pucRateIndex); + ASSERT(pucPreambleOption); + + if (ucRateSwIndex >= RATE_6M_SW_INDEX) { + *pucRateIndex = ucRateSwIndex - RATE_6M_SW_INDEX; + *pucPreambleOption = PREAMBLE_OFDM_MODE; + } else { + *pucRateIndex = ucRateSwIndex; + *pucPreambleOption = PREAMBLE_DEFAULT_LONG_NONE; + } + return WLAN_STATUS_SUCCESS; +} + +uint32_t nicRateIndex2RateCode(IN uint8_t ucPreambleOption, + IN uint8_t ucRateIndex, OUT uint16_t *pu2RateCode) +{ + switch (ucPreambleOption) { + case PREAMBLE_DEFAULT_LONG_NONE: + if (ucRateIndex >= CCK_RATE_NUM) + return WLAN_STATUS_INVALID_DATA; + *pu2RateCode = au2RateCCKLong[ucRateIndex]; + break; + + case PREAMBLE_OPTION_SHORT: + if (ucRateIndex >= CCK_RATE_NUM) + return WLAN_STATUS_INVALID_DATA; + *pu2RateCode = au2RateCCKShort[ucRateIndex]; + break; + + case PREAMBLE_OFDM_MODE: + if (ucRateIndex >= OFDM_RATE_NUM) + return WLAN_STATUS_INVALID_DATA; + *pu2RateCode = au2RateOFDM[ucRateIndex]; + break; + + case PREAMBLE_HT_MIXED_MODE: + if (ucRateIndex >= HT_RATE_NUM) + return WLAN_STATUS_INVALID_DATA; + *pu2RateCode = au2RateHTMixed[ucRateIndex]; + break; + + case PREAMBLE_HT_GREEN_FIELD: + if (ucRateIndex >= HT_RATE_NUM) + return WLAN_STATUS_INVALID_DATA; + *pu2RateCode = au2RateHTGreenField[ucRateIndex]; + break; + + case PREAMBLE_VHT_FIELD: + if (ucRateIndex >= VHT_RATE_NUM) + return WLAN_STATUS_INVALID_DATA; + *pu2RateCode = au2RateVHT[ucRateIndex]; + break; + + default: + return WLAN_STATUS_INVALID_DATA; + } + + return WLAN_STATUS_SUCCESS; +} + +uint32_t +nicRateCode2PhyRate( + IN uint16_t u2RateCode, + IN uint8_t ucBandwidth, + IN uint8_t ucGI, + IN uint8_t ucRateNss) +{ + uint8_t ucPhyRate; + uint16_t u2TxMode; + uint32_t u4PhyRateBy1SS, u4PhyRateIn100Kbps = 0; + + ucPhyRate = RATE_CODE_GET_PHY_RATE(u2RateCode); + u2TxMode = u2RateCode & RATE_TX_MODE_MASK; + ucRateNss = ucRateNss + AR_SS_1; /* change to be base=1 */ + + if ((u2TxMode == TX_MODE_HT_GF) + || (u2TxMode == TX_MODE_HT_MM)) { + + if (ucPhyRate > PHY_RATE_MCS7) + u2RateCode = u2RateCode - HT_RATE_MCS7_INDEX; + else + ucRateNss = AR_SS_1; + + } else if ((u2TxMode == TX_MODE_OFDM) + || (u2TxMode == TX_MODE_CCK)) { + ucRateNss = AR_SS_1; + } + DBGLOG(NIC, LOUD, + "Coex:nicRateCode2PhyRate,RC:%x,B:%d,I:%d\n", + u2RateCode, ucBandwidth, ucGI); + + u4PhyRateBy1SS = nicRateCode2DataRate(u2RateCode, + ucBandwidth, ucGI); + u4PhyRateIn100Kbps = u4PhyRateBy1SS * ucRateNss; + + DBGLOG(NIC, LOUD, + "Coex:nicRateCode2PhyRate,1ss R:%d,PHY R:%d\n", + u4PhyRateBy1SS, u4PhyRateIn100Kbps); + + return u4PhyRateIn100Kbps; +} + +uint32_t +nicRateCode2DataRate( + IN uint16_t u2RateCode, + IN uint8_t ucBandwidth, + IN uint8_t ucGI) +{ + uint8_t ucPhyRate, ucIdx, ucBw = 0; + uint32_t u4PhyRateIn100Kbps = 0; + uint16_t u2TxMode; + + if ((ucBandwidth == FIX_BW_NO_FIXED) + || (ucBandwidth == FIX_BW_20)) + ucBw = MAC_BW_20; + else if (ucBandwidth == FIX_BW_40) + ucBw = MAC_BW_40; + else if (ucBandwidth == FIX_BW_80) + ucBw = MAC_BW_80; + else if (ucBandwidth == FIX_BW_160) + ucBw = MAC_BW_160; + + ucPhyRate = RATE_CODE_GET_PHY_RATE(u2RateCode); + u2TxMode = u2RateCode & RATE_TX_MODE_MASK; + /* Set MMSS parameter if HT/VHT rate */ + if ((u2TxMode == TX_MODE_HT_GF) || + (u2TxMode == TX_MODE_HT_MM) || + (u2TxMode == TX_MODE_VHT)) { + /* No SGI Greenfield for 1T */ + /* Refer to section 20.3.11.11.6 of IEEE802.11-2012 */ + if (u2TxMode == TX_MODE_HT_GF) + ucGI = MAC_GI_NORMAL; + + ucIdx = ucPhyRate; + + if (ucIdx == PHY_RATE_MCS32) + ucIdx = 10; + + u4PhyRateIn100Kbps = nicGetPhyRateByMcsRate(ucIdx, ucBw, + ucGI); + } else if ((u2TxMode == TX_MODE_OFDM) || + (u2TxMode == TX_MODE_CCK)) { + u4PhyRateIn100Kbps = (nicGetHwRateByPhyRate( + ucPhyRate & BITS(0, 3))) * 5; + } else { + ASSERT(FALSE); + } + return u4PhyRateIn100Kbps; +} + +u_int8_t +nicGetRateIndexFromRateSetWithLimit( + IN uint16_t u2RateSet, + IN uint32_t u4PhyRateLimit, + IN u_int8_t fgGetLowest, + OUT uint8_t *pucRateSwIndex) +{ + uint32_t i; + uint32_t u4CurPhyRate, u4TarPhyRate, u4HighestPhyRate, + u4LowestPhyRate; + uint8_t ucRateIndex, ucRatePreamble, ucTarRateSwIndex, + ucHighestPhyRateSwIdx, ucLowestPhyRateSwIdx; + uint16_t u2CurRateCode; + uint32_t u4Status; + + /* Set init value */ + if (fgGetLowest) { + u4TarPhyRate = 0xFFFFFFFF; + u4HighestPhyRate = 0; + ucHighestPhyRateSwIdx = RATE_NUM_SW; + } else { + u4TarPhyRate = 0; + u4LowestPhyRate = 0xFFFFFFFF; + ucLowestPhyRateSwIdx = RATE_NUM_SW; + } + + ucTarRateSwIndex = RATE_NUM_SW; + + /* Find SW rate index by limitation */ + for (i = RATE_1M_SW_INDEX; i <= RATE_54M_SW_INDEX; i++) { + if (u2RateSet & BIT(i)) { + + /* Convert SW rate index to phy rate in 100kbps */ + nicSwIndex2RateIndex(i, &ucRateIndex, &ucRatePreamble); + u4Status = nicRateIndex2RateCode(ucRatePreamble, + ucRateIndex, &u2CurRateCode); + + if (u4Status != WLAN_STATUS_SUCCESS) + continue; + + u4CurPhyRate = + nicRateCode2DataRate(u2CurRateCode, MAC_BW_20, + MAC_GI_NORMAL); + + /* Compare */ + if (fgGetLowest) { + if (u4HighestPhyRate < u4CurPhyRate) { + u4HighestPhyRate = u4CurPhyRate; + ucHighestPhyRateSwIdx = i; + } + if ((u4CurPhyRate >= u4PhyRateLimit) + && (u4CurPhyRate <= u4TarPhyRate)) { + u4TarPhyRate = u4CurPhyRate; + ucTarRateSwIndex = i; + } + } else { + if (u4LowestPhyRate > u4CurPhyRate) { + u4LowestPhyRate = u4CurPhyRate; + ucLowestPhyRateSwIdx = i; + } + if ((u4CurPhyRate <= u4PhyRateLimit) + && (u4CurPhyRate >= u4TarPhyRate)) { + u4TarPhyRate = u4CurPhyRate; + ucTarRateSwIndex = i; + } + } + } + } + + /* Return target SW rate index */ + if (ucTarRateSwIndex < RATE_NUM_SW) { + *pucRateSwIndex = ucTarRateSwIndex; + } else { + if (fgGetLowest) + *pucRateSwIndex = ucHighestPhyRateSwIdx; + else + *pucRateSwIndex = ucLowestPhyRateSwIdx; + } + return TRUE; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic_rx.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic_rx.c new file mode 100644 index 0000000000000..a531be2ff2524 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic_rx.c @@ -0,0 +1,4597 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_rx.c#5 + */ + +/*! \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. + */ + + +/******************************************************************************* + * C O M P I L E 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 "que_mgt.h" +#include "wnm.h" + +#ifndef LINUX +#include +#else +#include +#endif + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +#if CFG_MGMT_FRAME_HANDLING +static PROCESS_RX_MGT_FUNCTION +apfnProcessRxMgtFrame[MAX_NUM_OF_FC_SUBTYPES] = { +#if CFG_SUPPORT_AAA + aaaFsmRunEventRxAssoc, /* subtype 0000: Association request */ +#else + NULL, /* subtype 0000: Association request */ +#endif /* CFG_SUPPORT_AAA */ + saaFsmRunEventRxAssoc, /* subtype 0001: Association response */ +#if CFG_SUPPORT_AAA + aaaFsmRunEventRxAssoc, /* subtype 0010: Reassociation request */ +#else + NULL, /* subtype 0010: Reassociation request */ +#endif /* CFG_SUPPORT_AAA */ + saaFsmRunEventRxAssoc, /* subtype 0011: Reassociation response */ +#if CFG_SUPPORT_ADHOC || CFG_ENABLE_WIFI_DIRECT + 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 + +static struct RX_EVENT_HANDLER arEventTable[] = { + {EVENT_ID_RX_ADDBA, qmHandleEventRxAddBa}, + {EVENT_ID_DBDC_SWITCH_DONE, cnmDbdcEventHwSwitchDone}, + {EVENT_ID_RX_DELBA, qmHandleEventRxDelBa}, + {EVENT_ID_CHECK_REORDER_BUBBLE, qmHandleEventCheckReorderBubble}, + {EVENT_ID_LINK_QUALITY, nicEventLinkQuality}, + {EVENT_ID_LAYER_0_EXT_MAGIC_NUM, nicEventLayer0ExtMagic}, + {EVENT_ID_MIC_ERR_INFO, nicEventMicErrorInfo}, + {EVENT_ID_SCAN_DONE, nicEventScanDone}, + {EVENT_ID_SCHED_SCAN_DONE, nicEventSchedScanDone}, + {EVENT_ID_TX_DONE, nicTxProcessTxDoneEvent}, + {EVENT_ID_SLEEPY_INFO, nicEventSleepyNotify}, +#if CFG_ENABLE_BT_OVER_WIFI + {EVENT_ID_BT_OVER_WIFI, nicEventBtOverWifi}, +#endif + {EVENT_ID_STATISTICS, nicEventStatistics}, + {EVENT_ID_WLAN_INFO, nicEventWlanInfo}, + {EVENT_ID_MIB_INFO, nicEventMibInfo}, + {EVENT_ID_IPI_INFO, nicEventIpiInfo}, +#if (CFG_SUPPORT_GET_MCS_INFO == 1) + {EVENT_ID_TX_MCS_INFO, nicEventTxMcsInfo}, +#endif + {EVENT_ID_CH_PRIVILEGE, cnmChMngrHandleChEvent}, + {EVENT_ID_BSS_ABSENCE_PRESENCE, qmHandleEventBssAbsencePresence}, + {EVENT_ID_STA_CHANGE_PS_MODE, qmHandleEventStaChangePsMode}, + {EVENT_ID_STA_UPDATE_FREE_QUOTA, qmHandleEventStaUpdateFreeQuota}, + {EVENT_ID_BSS_BEACON_TIMEOUT, nicEventBeaconTimeout}, + {EVENT_ID_UPDATE_NOA_PARAMS, nicEventUpdateNoaParams}, + {EVENT_ID_STA_AGING_TIMEOUT, nicEventStaAgingTimeout}, + {EVENT_ID_AP_OBSS_STATUS, nicEventApObssStatus}, + {EVENT_ID_ROAMING_STATUS, nicEventRoamingStatus}, + {EVENT_ID_SEND_DEAUTH, nicEventSendDeauth}, + {EVENT_ID_UPDATE_RDD_STATUS, nicEventUpdateRddStatus}, + {EVENT_ID_UPDATE_BWCS_STATUS, nicEventUpdateBwcsStatus}, + {EVENT_ID_UPDATE_BCM_DEBUG, nicEventUpdateBcmDebug}, + {EVENT_ID_ADD_PKEY_DONE, nicEventAddPkeyDone}, + {EVENT_ID_ICAP_DONE, nicEventIcapDone}, + {EVENT_ID_DEBUG_MSG, nicEventDebugMsg}, + {EVENT_ID_TDLS, nicEventTdls}, + {EVENT_ID_RSSI_MONITOR, nicEventRssiMonitor}, + {EVENT_ID_DUMP_MEM, nicEventDumpMem}, +#if CFG_ASSERT_DUMP + {EVENT_ID_ASSERT_DUMP, nicEventAssertDump}, +#endif +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST + {EVENT_ID_CAL_ALL_DONE, nicEventCalAllDone}, +#endif + {EVENT_ID_HIF_CTRL, nicEventHifCtrl}, + {EVENT_ID_RDD_SEND_PULSE, nicEventRddSendPulse}, +#if (CFG_SUPPORT_DFS_MASTER == 1) + {EVENT_ID_UPDATE_COEX_PHYRATE, nicEventUpdateCoexPhyrate}, + {EVENT_ID_RDD_REPORT, cnmRadarDetectEvent}, + {EVENT_ID_CSA_DONE, cnmCsaDoneEvent}, +#if CFG_SUPPORT_IDC_CH_SWITCH + {EVENT_ID_LTE_IDC_REPORT, cnmIdcDetectHandler}, +#endif +#else + {EVENT_ID_UPDATE_COEX_PHYRATE, nicEventUpdateCoexPhyrate}, +#endif +#if (CFG_WOW_SUPPORT == 1) + {EVENT_ID_WOW_WAKEUP_REASON, nicEventWakeUpReason}, +#endif +#if CFG_SUPPORT_REPLAY_DETECTION + {EVENT_ID_GET_GTK_REKEY_DATA, nicEventGetGtkDataSync}, +#endif + {EVENT_ID_TX_ADDBA, qmHandleEventTxAddBa}, + {EVENT_ID_GET_CNM, nicEventCnmInfo} +}; + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +#define MAX_EAPOL_REQUE 100 +/******************************************************************************* + * 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 struct ADAPTER *prAdapter) +{ + struct RX_CTRL *prRxCtrl; + uint8_t *pucMemHandle; + struct SW_RFB *prSwRfb = (struct SW_RFB *) NULL; + uint32_t i; + + DEBUGFUNC("nicRxInitialize"); + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + + /* 4 <0> Clear allocated memory. */ + kalMemZero((void *) 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 = (struct SW_RFB *) pucMemHandle; + + if (nicRxSetupRFB(prAdapter, prSwRfb)) { + DBGLOG(RX, ERROR, + "nicRxInitialize failed: Cannot allocate packet buffer for SwRfb!\n"); + return; + } + nicRxReturnRFB(prAdapter, prSwRfb); + + pucMemHandle += ALIGN_4(sizeof(struct SW_RFB)); + } + + if (prRxCtrl->rFreeSwRfbList.u4NumElem != + CFG_RX_MAX_PKT_NUM) + ASSERT_NOMEM(); + /* Check if the memory allocation consist with this + * initialization function + */ + ASSERT((uint32_t) (pucMemHandle - prRxCtrl->pucRxCached) == + prRxCtrl->u4RxCachedSize); + + /* 4 <2> Clear all RX counters */ + RX_RESET_ALL_CNTS(prRxCtrl); + + prRxCtrl->pucRxCoalescingBufPtr = + prAdapter->pucCoalescingBufCached; + +#if CFG_HIF_STATISTICS + prRxCtrl->u4TotalRxAccessNum = 0; + prRxCtrl->u4TotalRxPacketNum = 0; +#endif + +#if CFG_HIF_RX_STARVATION_WARNING + prRxCtrl->u4QueuedCnt = 0; + prRxCtrl->u4DequeuedCnt = 0; +#endif + +} /* end of nicRxInitialize() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Uninitialize the RFBs + * + * @param prAdapter Pointer to the Adapter structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicRxUninitialize(IN struct ADAPTER *prAdapter) +{ + struct RX_CTRL *prRxCtrl; + struct SW_RFB *prSwRfb = (struct SW_RFB *) 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, + struct SW_RFB *); + 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_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, + struct SW_RFB *); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + if (prSwRfb) { + if (prSwRfb->pvPacket) + kalPacketFree(prAdapter->prGlueInfo, + prSwRfb->pvPacket); + prSwRfb->pvPacket = NULL; + } else { + break; + } + } while (TRUE); + +} /* end of nicRxUninitialize() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Fill RFB + * + * @param prAdapter pointer to the Adapter handler + * @param prSWRfb specify the RFB to receive rx data + * + * @return (none) + * + */ +/*----------------------------------------------------------------------------*/ +bool nicRxFillRFB(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb) +{ + struct mt66xx_chip_info *prChipInfo; + struct HW_MAC_RX_DESC *prRxStatus; + + uint32_t u4PktLen = 0; + /* UINT_32 u4MacHeaderLen; */ + uint32_t u4HeaderOffset; + uint16_t u2RxStatusOffset; + + DEBUGFUNC("nicRxFillRFB"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prChipInfo = prAdapter->chip_info; + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + u4PktLen = (uint32_t) HAL_RX_STATUS_GET_RX_BYTE_CNT( + prRxStatus); + if (u4PktLen < sizeof(struct HW_MAC_RX_DESC)) { + DBGLOG(RX, ERROR, + "Logic Check Error - u4PktLen(%lu) < RXD.\n", + u4PktLen); + return FALSE; + } + + u4HeaderOffset = (uint32_t) ( + HAL_RX_STATUS_GET_HEADER_OFFSET(prRxStatus)); + + u2RxStatusOffset = prChipInfo->rxd_size; + prSwRfb->ucGroupVLD = (uint8_t) HAL_RX_STATUS_GET_GROUP_VLD( + prRxStatus); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_4)) { + prSwRfb->prRxStatusGroup4 = (struct HW_MAC_RX_STS_GROUP_4 *) + ((uint8_t *) prRxStatus + u2RxStatusOffset); + u2RxStatusOffset += sizeof(struct HW_MAC_RX_STS_GROUP_4); + + } + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_1)) { + prSwRfb->prRxStatusGroup1 = (struct HW_MAC_RX_STS_GROUP_1 *) + ((uint8_t *) prRxStatus + u2RxStatusOffset); + u2RxStatusOffset += sizeof(struct HW_MAC_RX_STS_GROUP_1); + + } + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_2)) { + prSwRfb->prRxStatusGroup2 = (struct HW_MAC_RX_STS_GROUP_2 *) + ((uint8_t *) prRxStatus + u2RxStatusOffset); + u2RxStatusOffset += sizeof(struct HW_MAC_RX_STS_GROUP_2); + + } + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_3)) { + prSwRfb->prRxStatusGroup3 = (struct HW_MAC_RX_STS_GROUP_3 *) + ((uint8_t *) prRxStatus + u2RxStatusOffset); + u2RxStatusOffset += sizeof(struct HW_MAC_RX_STS_GROUP_3); + } + + if (u4PktLen < u2RxStatusOffset + u4HeaderOffset) { + DBGLOG(RX, ERROR, + "Logic Check Error - u4PktLen(%lu) < (%d + %d)\n", + u4PktLen, + u2RxStatusOffset, + u4HeaderOffset); + return FALSE; + } + prSwRfb->u2RxStatusOffst = u2RxStatusOffset; + prSwRfb->pvHeader = (uint8_t *) prRxStatus + + u2RxStatusOffset + u4HeaderOffset; + prSwRfb->u2PacketLen = (uint16_t) (u4PktLen - + (u2RxStatusOffset + u4HeaderOffset)); + prSwRfb->u2HeaderLen = (uint16_t) + HAL_RX_STATUS_GET_HEADER_LEN(prRxStatus); + + if (u4PktLen < u2RxStatusOffset + + u4HeaderOffset + prSwRfb->u2HeaderLen) { + DBGLOG(RX, ERROR, + "Logic Check Error - u4PktLen(%lu) < (%d + %d + %d)\n", + u4PktLen, + u2RxStatusOffset, + u4HeaderOffset, + prSwRfb->u2HeaderLen); + return FALSE; + } + + prSwRfb->ucWlanIdx = (uint8_t) HAL_RX_STATUS_GET_WLAN_IDX( + prRxStatus); + prSwRfb->ucStaRecIdx = secGetStaIdxByWlanIdx(prAdapter, + (uint8_t) HAL_RX_STATUS_GET_WLAN_IDX(prRxStatus)); + prSwRfb->prStaRec = cnmGetStaRecByIndex(prAdapter, + prSwRfb->ucStaRecIdx); + prSwRfb->ucTid = (uint8_t) HAL_RX_STATUS_GET_TID( + prRxStatus); + +#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 = (uint8_t) ((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 + return TRUE; +} + +#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 struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb) +{ + struct RX_CSO_REPORT_T *rReport; + uint32_t u4TcpUdpIpCksStatus; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + u4TcpUdpIpCksStatus = prSwRfb->u4TcpUdpIpCksStatus; + rReport = (struct RX_CSO_REPORT_T *) &u4TcpUdpIpCksStatus; + DBGLOG_LIMITED(RX, LOUD, + "RX_IPV4_STATUS=%d, RX_TCP_STATUS=%d, RX_UDP_STATUS=%d\n", + rReport->u4IpV4CksStatus, rReport->u4TcpCksStatus, + rReport->u4UdpCksStatus); + DBGLOG_LIMITED(RX, LOUD, + "RX_IPV4_TYPE=%d, RX_IPV6_TYPE=%d, RX_TCP_TYPE=%d, RX_UDP_TYPE=%d\n", + rReport->u4IpV4CksType, rReport->u4IpV6CksType, + rReport->u4TcpCksType, rReport->u4UdpCksType); + + 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 rxDefragMPDU() is used to defragment the incoming packets. + * + * \param[in] prSWRfb The RFB which is being processed. + * \param[in] UINT_16 u2FrameCtrl + * + * \retval NOT NULL Receive the last fragment data + * \retval NULL Receive the fragment packet which is not the last + */ +/*----------------------------------------------------------------------------*/ +struct SW_RFB *nicRxDefragMPDU(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSWRfb, OUT struct QUE *prReturnedQue) +{ + + struct SW_RFB *prOutputSwRfb = (struct SW_RFB *) NULL; +#if 1 + struct RX_CTRL *prRxCtrl; + struct FRAG_INFO *prFragInfo; + uint32_t i = 0, j; + uint16_t u2SeqCtrl, u2FrameCtrl; + uint8_t ucFragNum; + u_int8_t fgFirst = FALSE; + u_int8_t fgLast = FALSE; + OS_SYSTIME rCurrentTime; + struct WLAN_MAC_HEADER *prWlanHeader = NULL; + struct HW_MAC_RX_DESC *prRxStatus = NULL; + struct HW_MAC_RX_STS_GROUP_4 *prRxStatusGroup4 = NULL; + + DEBUGFUNC("nicRx: rxmDefragMPDU\n"); + + ASSERT(prSWRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + + prRxStatus = prSWRfb->prRxStatus; + ASSERT(prRxStatus); + + if (HAL_RX_STATUS_IS_HEADER_TRAN(prRxStatus) == FALSE) { + prWlanHeader = (struct WLAN_MAC_HEADER *) prSWRfb->pvHeader; + prSWRfb->u2SequenceControl = prWlanHeader->u2SeqCtrl; + u2FrameCtrl = prWlanHeader->u2FrameCtrl; + } else { + prRxStatusGroup4 = prSWRfb->prRxStatusGroup4; + prSWRfb->u2SequenceControl = HAL_RX_STATUS_GET_SEQFrag_NUM( + prRxStatusGroup4); + u2FrameCtrl = HAL_RX_STATUS_GET_FRAME_CTL_FIELD( + prRxStatusGroup4); + } + u2SeqCtrl = prSWRfb->u2SequenceControl; + ucFragNum = (uint8_t) (u2SeqCtrl & MASK_SC_FRAG_NUM); + prSWRfb->u2FrameCtrl = u2FrameCtrl; + + if (!(u2FrameCtrl & MASK_FC_MORE_FRAG)) { + /* The last fragment frame */ + if (ucFragNum) { + DBGLOG(RX, LOUD, + "FC %04x M %04x SQ %04x\n", u2FrameCtrl, + (uint16_t) (u2FrameCtrl & MASK_FC_MORE_FRAG), + u2SeqCtrl); + fgLast = TRUE; + } + /* Non-fragment frame */ + else + return prSWRfb; + } + /* The fragment frame except the last one */ + else { + if (ucFragNum == 0) { + DBGLOG(RX, LOUD, + "FC %04x M %04x SQ %04x\n", u2FrameCtrl, + (uint16_t) (u2FrameCtrl & MASK_FC_MORE_FRAG), + u2SeqCtrl); + fgFirst = TRUE; + } else { + DBGLOG(RX, LOUD, + "FC %04x M %04x SQ %04x\n", u2FrameCtrl, + (uint16_t) (u2FrameCtrl & MASK_FC_MORE_FRAG), + u2SeqCtrl); + } + } + + GET_CURRENT_SYSTIME(&rCurrentTime); + + for (j = 0; j < MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS; j++) { + prFragInfo = &prSWRfb->prStaRec->rFragInfo[j]; + if (prFragInfo->pr1stFrag) { + /* I. If the receive timer for the MSDU or MMPDU that + * is stored in the fragments queue exceeds + * dot11MaxReceiveLifetime, we discard the uncompleted + * fragments. + * II. If we didn't receive the last MPDU for a period, + * we use this function for remove frames. + */ + if (CHECK_FOR_EXPIRATION(rCurrentTime, + prFragInfo->rReceiveLifetimeLimit)) { + prFragInfo->pr1stFrag->eDst = + RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) + prFragInfo->pr1stFrag); + + prFragInfo->pr1stFrag = (struct SW_RFB *) NULL; + } + } + } + + for (i = 0; i < MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS; i++) { + + prFragInfo = &prSWRfb->prStaRec->rFragInfo[i]; + + if (fgFirst) { /* looking for timed-out frag buffer */ + + if (prFragInfo->pr1stFrag == (struct SW_RFB *) + NULL) /* find a free frag buffer */ + break; + } else { + /* looking for a buffer with desired next seqctrl */ + + if (prFragInfo->pr1stFrag == (struct SW_RFB *) NULL) + continue; + + if (RXM_IS_QOS_DATA_FRAME(u2FrameCtrl)) { + if (RXM_IS_QOS_DATA_FRAME( + prFragInfo->pr1stFrag->u2FrameCtrl)) { + if (u2SeqCtrl == + prFragInfo->u2NextFragSeqCtrl) + break; + } + } else { + if (!RXM_IS_QOS_DATA_FRAME( + prFragInfo->pr1stFrag->u2FrameCtrl)) { + if (u2SeqCtrl == + prFragInfo->u2NextFragSeqCtrl) + break; + } + } + } + } + + if (i >= MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS) { + + /* Can't find a proper struct FRAG_INFO. + * I. 1st Fragment MPDU, all of the FragInfo are exhausted + * II. 2nd ~ (n-1)th Fragment MPDU, can't find the right + * FragInfo for defragment. + * Because we won't process fragment frame outside this + * function, so we should free it right away. + */ + nicRxReturnRFB(prAdapter, prSWRfb); + + return (struct SW_RFB *) NULL; + } + + ASSERT(prFragInfo); + + /* retrieve Rx payload */ + prSWRfb->u2HeaderLen = HAL_RX_STATUS_GET_HEADER_LEN( + prRxStatus); + prSWRfb->pucPayload = (uint8_t *) (( + (unsigned long) prSWRfb->pvHeader) + + prSWRfb->u2HeaderLen); + prSWRfb->u2PayloadLength = + (uint16_t) (HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus) - (( + unsigned long) prSWRfb->pucPayload - + (unsigned long) prRxStatus)); + + if (fgFirst) { + DBGLOG(RX, LOUD, "rxDefragMPDU first\n"); + + SET_EXPIRATION_TIME(prFragInfo->rReceiveLifetimeLimit, + TU_TO_SYSTIME( + DOT11_RECEIVE_LIFETIME_TU_DEFAULT)); + + prFragInfo->pr1stFrag = prSWRfb; + + prFragInfo->pucNextFragStart = + (uint8_t *) prSWRfb->pucRecvBuff + + HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus); + + prFragInfo->u2NextFragSeqCtrl = u2SeqCtrl + 1; + DBGLOG(RX, LOUD, + "First: nextFragmentSeqCtrl = %04x, u2SeqCtrl = %04x\n", + prFragInfo->u2NextFragSeqCtrl, u2SeqCtrl); + + /* prSWRfb->fgFragmented = TRUE; */ + /* whsu: todo for checksum */ + } else { + prFragInfo->pr1stFrag->prRxStatus->u2RxByteCount += + prSWRfb->u2PayloadLength; + + if (prFragInfo->pr1stFrag->prRxStatus->u2RxByteCount > + CFG_RX_MAX_PKT_SIZE) { + + prFragInfo->pr1stFrag->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) + prFragInfo->pr1stFrag); + + prFragInfo->pr1stFrag = (struct SW_RFB *) NULL; + + nicRxReturnRFB(prAdapter, prSWRfb); + } else { + kalMemCopy(prFragInfo->pucNextFragStart, + prSWRfb->pucPayload, + prSWRfb->u2PayloadLength); + /* [6630] update rx byte count and packet length */ + prFragInfo->pr1stFrag->u2PacketLen += + prSWRfb->u2PayloadLength; + prFragInfo->pr1stFrag->u2PayloadLength += + prSWRfb->u2PayloadLength; + + if (fgLast) { /* The last one, free the buffer */ + DBGLOG(RX, LOUD, "Defrag: finished\n"); + + prOutputSwRfb = prFragInfo->pr1stFrag; + + prFragInfo->pr1stFrag = (struct SW_RFB *) NULL; + } else { + DBGLOG(RX, LOUD, "Defrag: mid fraged\n"); + + prFragInfo->pucNextFragStart += + prSWRfb->u2PayloadLength; + + prFragInfo->u2NextFragSeqCtrl++; + } + + nicRxReturnRFB(prAdapter, prSWRfb); + } + } + + /* DBGLOG_MEM8(RXM, INFO, */ + /* prFragInfo->pr1stFrag->pucPayload, */ + /* prFragInfo->pr1stFrag->u2PayloadLength); */ +#endif + return prOutputSwRfb; +} /* end of rxmDefragMPDU() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Do duplicate detection + * + * @param prSwRfb Pointer to the RX packet + * + * @return TRUE: a duplicate, FALSE: not a duplicate + */ +/*----------------------------------------------------------------------------*/ +u_int8_t nicRxIsDuplicateFrame(IN OUT struct SW_RFB + *prSwRfb) +{ + + /* Non-QoS Unicast Data or Unicast MMPDU: SC Cache #4; + * QoS Unicast Data: SC Cache #0~3; + * Broadcast/Multicast: RetryBit == 0 + */ + uint32_t u4SeqCtrlCacheIdx; + uint16_t u2SequenceControl, u2FrameCtrl; + u_int8_t fgIsDuplicate = FALSE, fgIsAmsduSubframe = FALSE; + struct WLAN_MAC_HEADER *prWlanHeader = NULL; + struct HW_MAC_RX_DESC *prRxStatus = NULL; + struct HW_MAC_RX_STS_GROUP_4 *prRxStatusGroup4 = NULL; + + DEBUGFUNC("nicRx: Enter rxmIsDuplicateFrame()\n"); + + ASSERT(prSwRfb); + + /* Situations in which the STC_REC is missing include: + * (1) Probe Request (2) (Re)Association Request + * (3) IBSS data frames (4) Probe Response + */ + if (!prSwRfb->prStaRec) + return FALSE; + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + fgIsAmsduSubframe = HAL_RX_STATUS_GET_PAYLOAD_FORMAT( + prRxStatus); + if (HAL_RX_STATUS_IS_HEADER_TRAN(prRxStatus) == FALSE) { + prWlanHeader = (struct WLAN_MAC_HEADER *) prSwRfb->pvHeader; + u2SequenceControl = prWlanHeader->u2SeqCtrl; + u2FrameCtrl = prWlanHeader->u2FrameCtrl; + } else { + prRxStatusGroup4 = prSwRfb->prRxStatusGroup4; + u2SequenceControl = HAL_RX_STATUS_GET_SEQFrag_NUM( + prRxStatusGroup4); + u2FrameCtrl = HAL_RX_STATUS_GET_FRAME_CTL_FIELD( + prRxStatusGroup4); + } + prSwRfb->u2SequenceControl = u2SequenceControl; + + /* Case 1: Unicast QoS data */ + if (RXM_IS_QOS_DATA_FRAME( + u2FrameCtrl)) { + /* WLAN header shall exist when doing duplicate detection */ + if (prSwRfb->prStaRec-> + aprRxReorderParamRefTbl[prSwRfb->ucTid]) { + + /* QoS data with an RX BA agreement + * Case 1: The packet is not an AMPDU subframe, + * so the RetryBit may be set to 1 (TBC). + * Case 2: The RX BA agreement was just established. + * Some enqueued packets may not be sent with + * aggregation. + */ + + DBGLOG(RX, LOUD, "RX: SC=0x%X (BA Entry present)\n", + u2SequenceControl); + + /* Update the SN cache in order to ensure the + * correctness of duplicate removal in case the + * BA agreement is deleted + */ + prSwRfb->prStaRec->au2CachedSeqCtrl[prSwRfb->ucTid] = + u2SequenceControl; + + /* debug */ +#if 0 + DBGLOG(RXM, LOUD, + "RXM: SC= 0x%X (Cache[%d] updated) with BA\n", + u2SequenceControl, prSwRfb->ucTID); + + if (g_prMqm->arRxBaTable[ + prSwRfb->prStaRec->aucRxBaTable[prSwRfb->ucTID]] + .ucStatus == BA_ENTRY_STATUS_DELETING) { + DBGLOG(RXM, LOUD, + "RXM: SC= 0x%X (Cache[%d] updated) with DELETING BA\n", + u2SequenceControl, prSwRfb->ucTID); + } +#endif + + /* HW scoreboard shall take care Case 1. + * Let the layer layer handle Case 2. + */ + return FALSE; /* Not a duplicate */ + } + + if (prSwRfb->prStaRec->ucDesiredPhyTypeSet & + (PHY_TYPE_BIT_HT | PHY_TYPE_BIT_VHT)) { + u4SeqCtrlCacheIdx = prSwRfb->ucTid; + } else { + if (prSwRfb->ucTid < 8) { /* UP = 0~7 */ + u4SeqCtrlCacheIdx = aucTid2ACI[prSwRfb->ucTid]; + } else { + DBGLOG(RX, WARN, + "RXM: (Warning) Unknown QoS Data with TID=%d\n", + prSwRfb->ucTid); + /* Ignore duplicate frame check */ + return FALSE; + } + } + } + /* Case 2: Unicast non-QoS data or MMPDUs */ + else + u4SeqCtrlCacheIdx = TID_NUM; + + /* If this is a retransmission */ + if (u2FrameCtrl & MASK_FC_RETRY) { + if (u2SequenceControl != + prSwRfb->prStaRec->au2CachedSeqCtrl[u4SeqCtrlCacheIdx]) { + prSwRfb->prStaRec->au2CachedSeqCtrl[u4SeqCtrlCacheIdx] = + u2SequenceControl; + if (fgIsAmsduSubframe == + RX_PAYLOAD_FORMAT_FIRST_SUB_AMSDU) + prSwRfb->prStaRec-> + afgIsIgnoreAmsduDuplicate[ + u4SeqCtrlCacheIdx] = TRUE; + DBGLOG(RX, LOUD, "RXM: SC= 0x%x (Cache[%u] updated)\n", + u2SequenceControl, u4SeqCtrlCacheIdx); + } else { + /* A duplicate. */ + if (prSwRfb->prStaRec-> + afgIsIgnoreAmsduDuplicate[u4SeqCtrlCacheIdx]) { + if (fgIsAmsduSubframe == + RX_PAYLOAD_FORMAT_LAST_SUB_AMSDU) + prSwRfb->prStaRec-> + afgIsIgnoreAmsduDuplicate[ + u4SeqCtrlCacheIdx] = FALSE; + } else { + fgIsDuplicate = TRUE; + DBGLOG(RX, LOUD, + "RXM: SC= 0x%x (Cache[%u] duplicate)\n", + u2SequenceControl, u4SeqCtrlCacheIdx); + } + } + } + + /* Not a retransmission */ + else { + + prSwRfb->prStaRec->au2CachedSeqCtrl[u4SeqCtrlCacheIdx] = + u2SequenceControl; + prSwRfb->prStaRec->afgIsIgnoreAmsduDuplicate[u4SeqCtrlCacheIdx] + = FALSE; + + DBGLOG(RX, LOUD, "RXM: SC= 0x%x (Cache[%u] updated)\n", + u2SequenceControl, u4SeqCtrlCacheIdx); + } + + return fgIsDuplicate; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfb) +{ + struct RX_CTRL *prRxCtrl; + struct TX_CTRL *prTxCtrl; + u_int8_t fgIsRetained = FALSE; + uint32_t u4CurrentRxBufferCount; + /* P_STA_RECORD_T prStaRec = (P_STA_RECORD_T)NULL; */ + + DEBUGFUNC("nicRxProcessPktWithoutReorder"); + /* DBGLOG(RX, TRACE, ("\n")); */ + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + u4CurrentRxBufferCount = prRxCtrl->rFreeSwRfbList.u4NumElem; + /* QM USED = $A, AVAILABLE COUNT = $B, INDICATED TO OS = $C + * TOTAL = $A + $B + $C + * + * Case #1 (Retain) + * ------------------------------------------------------- + * $A + $B < THRESHOLD := $A + $B + $C < THRESHOLD + $C + * := $TOTAL - THRESHOLD < $C + * => $C used too much, retain + * + * Case #2 (Non-Retain) + * ------------------------------------------------------- + * $A + $B > THRESHOLD := $A + $B + $C > THRESHOLD + $C + * := $TOTAL - THRESHOLD > $C + * => still available for $C to use + * + */ + +#if defined(LINUX) + fgIsRetained = FALSE; +#else + fgIsRetained = (((u4CurrentRxBufferCount + + qmGetRxReorderQueuedBufferCount(prAdapter) + + prTxCtrl->i4PendingFwdFrameCount) < + CFG_RX_RETAINED_PKT_THRESHOLD) ? TRUE : FALSE); +#endif + + /* DBGLOG(RX, INFO, ("fgIsRetained = %d\n", fgIsRetained)); */ +#if CFG_ENABLE_PER_STA_STATISTICS + if (prSwRfb->prStaRec + && (prAdapter->rWifiVar.rWfdConfigureSettings.ucWfdEnable > + 0)) + prSwRfb->prStaRec->u4TotalRxPktsNumber++; +#endif + if (kalProcessRxPacket(prAdapter->prGlueInfo, + prSwRfb->pvPacket, + prSwRfb->pvHeader, + (uint32_t) prSwRfb->u2PacketLen, fgIsRetained, + prSwRfb->aeCSUM) != WLAN_STATUS_SUCCESS) { + DBGLOG(RX, ERROR, + "kalProcessRxPacket return value != WLAN_STATUS_SUCCESS\n"); + + nicRxReturnRFB(prAdapter, prSwRfb); + return; + } + +#if CFG_SUPPORT_MULTITHREAD + if (HAL_IS_RX_DIRECT(prAdapter) || + kalRxNapiValidSkb(prAdapter->prGlueInfo, + GLUE_GET_PKT_DESCRIPTOR( + GLUE_GET_PKT_QUEUE_ENTRY(prSwRfb->pvPacket)) + )) { + kalRxIndicateOnePkt(prAdapter->prGlueInfo, + (void *) GLUE_GET_PKT_DESCRIPTOR( + GLUE_GET_PKT_QUEUE_ENTRY(prSwRfb->pvPacket))); + RX_ADD_CNT(prRxCtrl, RX_DATA_INDICATION_COUNT, 1); + if (fgIsRetained) + RX_ADD_CNT(prRxCtrl, RX_DATA_RETAINED_COUNT, 1); + } else { + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); + QUEUE_INSERT_TAIL(&(prAdapter->rRxQueue), + (struct QUE_ENTRY *) GLUE_GET_PKT_QUEUE_ENTRY( + prSwRfb->pvPacket)); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); + + prRxCtrl->ucNumIndPacket++; + kalSetTxEvent2Rx(prAdapter->prGlueInfo); + } +#else + prRxCtrl->apvIndPacket[prRxCtrl->ucNumIndPacket] = + prSwRfb->pvPacket; + prRxCtrl->ucNumIndPacket++; +#endif + +#ifndef LINUX + if (fgIsRetained) { + prRxCtrl->apvRetainedPacket[prRxCtrl->ucNumRetainedPacket] = + prSwRfb->pvPacket; + prRxCtrl->ucNumRetainedPacket++; + } else +#endif + prSwRfb->pvPacket = NULL; + + + /* Return RFB */ + if ((!timerPendingTimer(&prAdapter->rPacketDelaySetupTimer)) + && nicRxSetupRFB(prAdapter, prSwRfb)) { + DBGLOG(RX, WARN, + "Allocate buf failed, Start IndicatedRfb Timer (%u)\n", + RX_RETURN_INDICATED_RFB_TIMEOUT_SEC); + cnmTimerStartTimer(prAdapter, + &prAdapter->rPacketDelaySetupTimer, + SEC_TO_MSEC(RX_RETURN_INDICATED_RFB_TIMEOUT_SEC)); + } + 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 struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct MSDU_INFO *prMsduInfo, *prRetMsduInfoList; + struct TX_CTRL *prTxCtrl; + struct RX_CTRL *prRxCtrl; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxProcessForwardPkt"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prTxCtrl = &prAdapter->rTxCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + + prMsduInfo = cnmPktAlloc(prAdapter, 0); + + if (prMsduInfo && + kalProcessRxPacket(prAdapter->prGlueInfo, + prSwRfb->pvPacket, + prSwRfb->pvHeader, + (uint32_t) prSwRfb->u2PacketLen, + prRxCtrl->rFreeSwRfbList.u4NumElem < + CFG_RX_RETAINED_PKT_THRESHOLD ? TRUE : FALSE, + prSwRfb->aeCSUM) == WLAN_STATUS_SUCCESS) { + + /* parsing forward frame */ + wlanProcessTxFrame(prAdapter, (void *) (prSwRfb->pvPacket)); + /* pack into MSDU_INFO_T */ + nicTxFillMsduInfo(prAdapter, prMsduInfo, + (void *) (prSwRfb->pvPacket)); + + prMsduInfo->eSrc = TX_PACKET_FORWARDING; + prMsduInfo->ucBssIndex = secGetBssIdxByWlanIdx(prAdapter, + prSwRfb->ucWlanIdx); + + /* 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 */ + DBGLOG(QM, INFO, "No Tx MSDU_INFO for forwarding frames\n"); + nicRxReturnRFB(prAdapter, prSwRfb); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Process broadcast data packet for both host and forwarding + * + * @param prAdapter pointer to the Adapter handler + * @param prSWRfb the RFB to receive rx data + * + * @return (none) + * + */ +/*----------------------------------------------------------------------------*/ +void nicRxProcessGOBroadcastPkt(IN struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfb) +{ + struct SW_RFB *prSwRfbDuplicated; + struct TX_CTRL *prTxCtrl; + struct RX_CTRL *prRxCtrl; + struct HW_MAC_RX_DESC *prRxStatus; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxProcessGOBroadcastPkt"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prTxCtrl = &prAdapter->rTxCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + 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_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, + prSwRfbDuplicated, struct SW_RFB *); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + if (prSwRfbDuplicated) { + kalMemCopy(prSwRfbDuplicated->pucRecvBuff, + prSwRfb->pucRecvBuff, + ALIGN_4(prRxStatus->u2RxByteCount + + HIF_RX_HW_APPENDED_LEN)); + + prSwRfbDuplicated->ucPacketType = RX_PKT_TYPE_RX_DATA; + prSwRfbDuplicated->ucStaRecIdx = prSwRfb->ucStaRecIdx; + if (nicRxFillRFB(prAdapter, prSwRfbDuplicated) + == FALSE) { + DBGLOG(RX, ERROR, + "[%s] call nicRxFillRFB() failed\n", + __func__); + nicRxReturnRFB(prAdapter, prSwRfb); + return; + } + + /* 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); + +} + +#if CFG_SUPPORT_SNIFFER +void nicRxFillRadiotapMCS(IN OUT struct MONITOR_RADIOTAP + *prMonitorRadiotap, + IN struct HW_MAC_RX_STS_GROUP_3 *prRxStatusGroup3) +{ + uint8_t ucFrMode; + uint8_t ucShortGI; + uint8_t ucRxMode; + uint8_t ucLDPC; + uint8_t ucSTBC; + uint8_t ucNess; + + ucFrMode = (((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET); + /* VHTA1 B0-B1 */ + ucShortGI = ((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_SHORT_GI) ? 1 : 0; /* HT_shortgi */ + ucRxMode = (((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_RX_MODE_MASK) >> RX_VT_RX_MODE_OFFSET); + ucLDPC = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_LDPC) ? + 1 : 0; /* HT_adcode */ + ucSTBC = (((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_STBC_MASK) >> RX_VT_STBC_OFFSET); /* HT_stbc */ + ucNess = (((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_NESS_MASK) >> RX_VT_NESS_OFFSET); /* HT_extltf */ + + prMonitorRadiotap->ucMcsKnown = + (BITS(0, 6) | (((ucNess & BIT(1)) >> 1) << 7)); + + prMonitorRadiotap->ucMcsFlags = ((ucFrMode) | + (ucShortGI << 2) | + ((ucRxMode & BIT(0)) << 3) | + (ucLDPC << 4) | (ucSTBC << 5) | + ((ucNess & BIT(0)) << 7)); + /* Bit[6:0] for 802.11n, mcs0 ~ mcs7 */ + prMonitorRadiotap->ucMcsMcs = (( + prRxStatusGroup3)->u4RxVector[0] & RX_VT_RX_RATE_MASK); +} + +void nicRxFillRadiotapVHT(IN OUT struct MONITOR_RADIOTAP + *prMonitorRadiotap, + IN struct HW_MAC_RX_STS_GROUP_3 *prRxStatusGroup3) +{ + uint8_t ucSTBC; + uint8_t ucTxopPsNotAllow; + uint8_t ucShortGI; + uint8_t ucNsym; + uint8_t ucLdpcExtraOfdmSym; + uint8_t ucBeamFormed; + uint8_t ucFrMode; + uint8_t ucNsts; + uint8_t ucMcs; + + prMonitorRadiotap->u2VhtKnown = RADIOTAP_VHT_ALL_KNOWN; + prMonitorRadiotap->u2VhtKnown &= + ~RADIOTAP_VHT_SHORT_GI_NSYM_KNOWN; + + ucSTBC = (((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_STBC_MASK) >> + RX_VT_STBC_OFFSET); /* BIT[7]: VHTA1 B3 */ + ucTxopPsNotAllow = ((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_TXOP_PS_NOT_ALLOWED) ? 1 : 0; /* VHTA1 B22 */ + /* + * ucNsym = ((prRxStatusGroup3)->u4RxVector[0] + * & RX_VT_SHORT_GI_NSYM) ? 1 : 0; //VHTA2 B1 + */ + ucNsym = 0; /* Invalid in MT6632*/ + ucShortGI = ((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_SHORT_GI) ? 1 : 0; /* VHTA2 B0 */ + ucLdpcExtraOfdmSym = ((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_LDPC_EXTRA_OFDM_SYM) ? 1 : 0; /* VHTA2 B3 */ + ucBeamFormed = ((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_BEAMFORMED) ? 1 : 0; /* VHTA2 B8 */ + prMonitorRadiotap->ucVhtFlags = ((ucSTBC) | + (ucTxopPsNotAllow << 1) | + (ucShortGI << 2) | (ucNsym << 3) + | (ucLdpcExtraOfdmSym << 4) + | (ucBeamFormed << 5)); + + ucFrMode = (((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET); + /* VHTA1 B0-B1 */ + switch (ucFrMode) { + case RX_VT_FR_MODE_20: + prMonitorRadiotap->ucVhtBandwidth = 0; + break; + case RX_VT_FR_MODE_40: + prMonitorRadiotap->ucVhtBandwidth = 1; + break; + case RX_VT_FR_MODE_80: + prMonitorRadiotap->ucVhtBandwidth = 4; + break; + case RX_VT_FR_MODE_160: + prMonitorRadiotap->ucVhtBandwidth = 11; + break; + default: + prMonitorRadiotap->ucVhtBandwidth = 0; + } + + /* Set to 0~7 for 1~8 space time streams */ + ucNsts = (((prRxStatusGroup3)->u4RxVector[1] & + RX_VT_NSTS_MASK) >> RX_VT_NSTS_OFFSET) + 1; + /* VHTA1 B10-B12 */ + + /* Bit[3:0] for 802.11ac, mcs0 ~ mcs9 */ + ucMcs = ((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_RX_RATE_AC_MASK); + + prMonitorRadiotap->aucVhtMcsNss[0] = ((ucMcs << 4) | + (ucNsts - ucSTBC)); /* STBC = Nsts - Nss */ + + /* + * prMonitorRadiotap->ucVhtCoding = + * (((prRxStatusGroup3)->u4RxVector[0] + * & RX_VT_CODING_MASK) >> RX_VT_CODING_OFFSET); + */ + prMonitorRadiotap->ucVhtCoding = 0; /* Invalid in MT6632*/ + + /* VHTA2 B2-B3 */ + + prMonitorRadiotap->ucVhtGroupId = + (((((prRxStatusGroup3)->u4RxVector[1] & + RX_VT_GROUPID_1_MASK) >> RX_VT_GROUPID_1_OFFSET) << 2) | + (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_GROUPID_0_MASK) + >> RX_VT_GROUPID_0_OFFSET)); + /* VHTA1 B4-B9 */ + /* VHTA1 B13-B21 */ + prMonitorRadiotap->u2VhtPartialAid = (((( + prRxStatusGroup3)->u4RxVector[2] + & RX_VT_AID_1_MASK) << 4) | + (((prRxStatusGroup3)->u4RxVector[1] + & RX_VT_AID_0_MASK) >> + RX_VT_AID_0_OFFSET)); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Process HIF monitor packet + * + * @param prAdapter pointer to the Adapter handler + * @param prSWRfb the RFB to receive rx data + * + * @return (none) + * + */ +/*----------------------------------------------------------------------------*/ +void nicRxProcessMonitorPacket(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb) +{ + struct sk_buff *prSkb = NULL; + struct RX_CTRL *prRxCtrl; + struct HW_MAC_RX_DESC *prRxStatus; + struct HW_MAC_RX_STS_GROUP_2 *prRxStatusGroup2; + struct HW_MAC_RX_STS_GROUP_3 *prRxStatusGroup3; + struct MONITOR_RADIOTAP rMonitorRadiotap; + struct RADIOTAP_FIELD_VENDOR_ rRadiotapFieldVendor; + uint8_t *prVendorNsOffset; + uint32_t u4VendorNsLen; + uint32_t u4RadiotapLen; + uint32_t u4ItPresent; + uint8_t aucMtkOui[] = VENDOR_OUI_MTK; + uint8_t ucRxRate; + uint8_t ucRxMode; + uint8_t ucChanNum; + uint8_t ucMcs; + uint8_t ucFrMode; + uint8_t ucShortGI; + uint32_t u4PhyRate; + +#if CFG_SUPPORT_MULTITHREAD + KAL_SPIN_LOCK_DECLARATION(); +#endif + + DEBUGFUNC("nicRxProcessMonitorPacket"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + + if (nicRxFillRFB(prAdapter, prSwRfb) == FALSE) { + DBGLOG(RX, ERROR, "[%s] call nicRxFillRFB() failed\n", + __func__); + nicRxReturnRFB(prAdapter, prSwRfb); + return; + } + + /* can't parse radiotap info if no rx vector */ + if (((prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_2)) == 0) + || ((prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_3)) == 0)) { + nicRxReturnRFB(prAdapter, prSwRfb); + return; + } + + prRxStatus = prSwRfb->prRxStatus; + prRxStatusGroup2 = prSwRfb->prRxStatusGroup2; + prRxStatusGroup3 = prSwRfb->prRxStatusGroup3; + + /* Bit Number 30 Vendor Namespace */ + u4VendorNsLen = sizeof(struct RADIOTAP_FIELD_VENDOR_); + rRadiotapFieldVendor.aucOUI[0] = aucMtkOui[0]; + rRadiotapFieldVendor.aucOUI[1] = aucMtkOui[1]; + rRadiotapFieldVendor.aucOUI[2] = aucMtkOui[2]; + rRadiotapFieldVendor.ucSubNamespace = 0; + rRadiotapFieldVendor.u2DataLen = u4VendorNsLen - 6; + /* VHTA1 B0-B1 */ + rRadiotapFieldVendor.ucData = ((( + prRxStatusGroup3)->u4RxVector[0] + & RX_VT_FR_MODE_MASK) >> + RX_VT_FR_MODE_OFFSET); + + ucRxMode = (((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_RX_MODE_MASK) >> RX_VT_RX_MODE_OFFSET); + + if (ucRxMode == RX_VT_VHT_MODE) { + u4RadiotapLen = RADIOTAP_LEN_VHT; + u4ItPresent = RADIOTAP_FIELDS_VHT; + } else if ((ucRxMode == RX_VT_MIXED_MODE) + || (ucRxMode == RX_VT_GREEN_MODE)) { + u4RadiotapLen = RADIOTAP_LEN_HT; + u4ItPresent = RADIOTAP_FIELDS_HT; + } else { + u4RadiotapLen = RADIOTAP_LEN_LEGACY; + u4ItPresent = RADIOTAP_FIELDS_LEGACY; + } + + /* Radiotap Header & Bit Number 30 Vendor Namespace */ + prVendorNsOffset = (uint8_t *) &rMonitorRadiotap + + u4RadiotapLen; + u4RadiotapLen += u4VendorNsLen; + kalMemSet(&rMonitorRadiotap, 0, + sizeof(struct MONITOR_RADIOTAP)); + kalMemCopy(prVendorNsOffset, + (uint8_t *) &rRadiotapFieldVendor, u4VendorNsLen); + rMonitorRadiotap.u2ItLen = cpu_to_le16(u4RadiotapLen); + rMonitorRadiotap.u4ItPresent = u4ItPresent; + + /* Bit Number 0 TSFT */ + rMonitorRadiotap.u8MacTime = + (prRxStatusGroup2->u4Timestamp); + + /* Bit Number 1 FLAGS */ + if (HAL_RX_STATUS_IS_FRAG(prRxStatus) == TRUE) + rMonitorRadiotap.ucFlags |= BIT(3); + + if (HAL_RX_STATUS_IS_FCS_ERROR(prRxStatus) == TRUE) + rMonitorRadiotap.ucFlags |= BIT(6); + + /* Bit Number 2 RATE */ + if ((ucRxMode == RX_VT_LEGACY_CCK) + || (ucRxMode == RX_VT_LEGACY_OFDM)) { + /* Bit[2:0] for Legacy CCK, Bit[3:0] for Legacy OFDM */ + ucRxRate = ((prRxStatusGroup3)->u4RxVector[0] & BITS(0, 3)); + rMonitorRadiotap.ucRate = nicGetHwRateByPhyRate(ucRxRate); + } else { + ucMcs = ((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_RX_RATE_AC_MASK); + /* VHTA1 B0-B1 */ + ucFrMode = (((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET); + ucShortGI = ((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_SHORT_GI) ? 1 : 0; /* VHTA2 B0 */ + + /* ucRate(500kbs) = u4PhyRate(100kbps) / 5, max ucRate = 0xFF */ + u4PhyRate = nicGetPhyRateByMcsRate(ucMcs, ucFrMode, + ucShortGI); + if (u4PhyRate > 1275) + rMonitorRadiotap.ucRate = 0xFF; + else + rMonitorRadiotap.ucRate = u4PhyRate / 5; + } + + /* Bit Number 3 CHANNEL */ + if (ucRxMode == RX_VT_LEGACY_CCK) + rMonitorRadiotap.u2ChFlags |= BIT(5); + else /* OFDM */ + rMonitorRadiotap.u2ChFlags |= BIT(6); + + ucChanNum = HAL_RX_STATUS_GET_CHNL_NUM(prRxStatus); + if (HAL_RX_STATUS_GET_RF_BAND(prRxStatus) == BAND_2G4) { + rMonitorRadiotap.u2ChFlags |= BIT(7); + rMonitorRadiotap.u2ChFrequency = (ucChanNum * 5 + 2407); + } else { /* BAND_5G */ + rMonitorRadiotap.u2ChFlags |= BIT(8); + rMonitorRadiotap.u2ChFrequency = (ucChanNum * 5 + 5000); + } + + /* Bit Number 5 ANT SIGNAL */ + rMonitorRadiotap.ucAntennaSignal = + RCPI_TO_dBm(HAL_RX_STATUS_GET_RCPI0(prRxStatusGroup3)); + + /* Bit Number 6 ANT NOISE */ + rMonitorRadiotap.ucAntennaNoise = (((( + prRxStatusGroup3)->u4RxVector[5] + & RX_VT_NF0_MASK) >> 1) + + 128); + + /* Bit Number 11 ANT, Invalid for MT6632 and MT7615 */ + rMonitorRadiotap.ucAntenna = (( + prRxStatusGroup3)->u4RxVector[2] & RX_VT_SEL_ANT) ? 1 : 0; + + /* Bit Number 19 MCS */ + if ((u4ItPresent & RADIOTAP_FIELD_MCS)) + nicRxFillRadiotapMCS(&rMonitorRadiotap, prRxStatusGroup3); + + /* Bit Number 20 AMPDU */ + if (HAL_RX_STATUS_IS_AMPDU_SUB_FRAME(prRxStatus)) { + if (HAL_RX_STATUS_GET_RXV_SEQ_NO(prRxStatus)) + ++prRxCtrl->u4AmpduRefNum; + rMonitorRadiotap.u4AmpduRefNum = prRxCtrl->u4AmpduRefNum; + } + + /* Bit Number 21 VHT */ + if ((u4ItPresent & RADIOTAP_FIELD_VHT)) + nicRxFillRadiotapVHT(&rMonitorRadiotap, prRxStatusGroup3); + + prSwRfb->pvHeader -= u4RadiotapLen; + kalMemCopy(prSwRfb->pvHeader, &rMonitorRadiotap, + u4RadiotapLen); + + prSkb = (struct sk_buff *)(prSwRfb->pvPacket); + prSkb->data = (unsigned char *)(prSwRfb->pvHeader); + + skb_reset_tail_pointer(prSkb); + skb_trim(prSkb, 0); + skb_put(prSkb, (u4RadiotapLen + prSwRfb->u2PacketLen)); + +#if CFG_SUPPORT_MULTITHREAD + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); + QUEUE_INSERT_TAIL(&(prAdapter->rRxQueue), + (struct QUE_ENTRY *) GLUE_GET_PKT_QUEUE_ENTRY( + prSwRfb->pvPacket)); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); + + prRxCtrl->ucNumIndPacket++; + kalSetTxEvent2Rx(prAdapter->prGlueInfo); +#else + prRxCtrl->apvIndPacket[prRxCtrl->ucNumIndPacket] = + prSwRfb->pvPacket; + prRxCtrl->ucNumIndPacket++; +#endif + + prSwRfb->pvPacket = NULL; + /* Return RFB */ + if (nicRxSetupRFB(prAdapter, prSwRfb)) { + DBGLOG(RX, WARN, + "Cannot allocate packet buffer for SwRfb!\n"); + if (!timerPendingTimer( + &prAdapter->rPacketDelaySetupTimer)) { + DBGLOG(RX, WARN, + "Start ReturnIndicatedRfb Timer (%u)\n", + RX_RETURN_INDICATED_RFB_TIMEOUT_SEC); + cnmTimerStartTimer(prAdapter, + &prAdapter->rPacketDelaySetupTimer, + SEC_TO_MSEC( + RX_RETURN_INDICATED_RFB_TIMEOUT_SEC)); + } + } + nicRxReturnRFB(prAdapter, prSwRfb); +} +#else +/*----------------------------------------------------------------------------*/ +/*! + * @brief Process HIF monitor packet + * + * @param prAdapter pointer to the Adapter handler + * @param prSWRfb the RFB to receive rx data + * + * @return (none) + * + */ +/*----------------------------------------------------------------------------*/ +void nicRxProcessMonitorPacket(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb) +{ +} +#endif + +#if (CFG_SUPPORT_PERF_IND == 1) +/*----------------------------------------------------------------------------*/ +/*! + * @brief Process & Parsing RXV for traffic indicator + * + * @param prAdapter pointer to the Adapter handler + * @param prSWRfb the RFB to receive rx data + * + * @return (none) + * + */ +/*----------------------------------------------------------------------------*/ +void nicRxProcessRXV(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint8_t ucBssIndex) +{ + struct HW_MAC_RX_STS_GROUP_3 *prRxStatusGroup3; + uint8_t ucRxRate; + uint8_t ucRxMode; + uint8_t ucRCPI0 = 0, ucRCPI1 = 0; + uint8_t ucMcs; + uint8_t ucFrMode; + uint8_t ucShortGI, ucGroupid, ucMu, ucNsts = 1; + uint32_t u4PhyRate; + uint16_t u2Rate = 0; + uint8_t ucNss = 1; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + if (ucBssIndex >= BSSID_NUM) + return; + + /* can't parse radiotap info if no rx vector */ + if (((prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_2)) == 0) + || ((prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_3)) == 0)) + return; + + prRxStatusGroup3 = prSwRfb->prRxStatusGroup3; + + ucRxMode = (((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_RX_MODE_MASK) >> RX_VT_RX_MODE_OFFSET); + + /* RATE & NSS */ + if ((ucRxMode == RX_VT_LEGACY_CCK) + || (ucRxMode == RX_VT_LEGACY_OFDM)) { + /* Bit[2:0] for Legacy CCK, Bit[3:0] for Legacy OFDM */ + ucRxRate = ((prRxStatusGroup3)->u4RxVector[0] & BITS(0, 3)); + u2Rate = nicGetHwRateByPhyRate(ucRxRate); + } else { + ucNss = (((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_NUM_RX_MASK) >> RX_VT_NUM_RX_OFFSET); + ucMcs = ((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_RX_RATE_AC_MASK); + ucNsts = (((prRxStatusGroup3)->u4RxVector[1] & + RX_VT_NSTS_MASK) >> RX_VT_NSTS_OFFSET); + ucGroupid = ((prRxStatusGroup3)->u4RxVector[1] & + RX_VT_GROUP_ID_MASK) >> RX_VT_GROUP_ID_OFFSET; + + if ((ucRxMode == RX_VT_MIXED_MODE) + || (ucRxMode == RX_VT_GREEN_MODE)) { + ucMcs -= (ucNss * 8); + } + + if (ucNsts == 0) + ucNsts = 1; + + if (ucGroupid && ucGroupid != 63) { + ucMu = 1; + } else { + ucMu = 0; + ucNsts += 1; + } + + /* VHTA1 B0-B1 */ + ucFrMode = (((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET); + ucShortGI = ((prRxStatusGroup3)->u4RxVector[0] & + RX_VT_SHORT_GI) ? 1 : 0; + + if ((ucMcs > PHY_RATE_MCS9) || + (ucFrMode > RX_VT_FR_MODE_160) || + (ucShortGI > MAC_GI_SHORT)) + return; + + /* ucRate(500kbs) = u4PhyRate(100kbps) */ + u4PhyRate = nicGetPhyRateByMcsRate(ucMcs, ucFrMode, + ucShortGI); + u4PhyRate *= (ucNss + 1); + u2Rate = u4PhyRate / 5; + } + + /* RCPI */ + ucRCPI0 = ((prRxStatusGroup3)->u4RxVector[3] & + RX_VT_RCPI0_MASK) >> RX_VT_RCPI0_OFFSET; + ucRCPI1 = ((prRxStatusGroup3)->u4RxVector[3] & + RX_VT_RCPI1_MASK) >> RX_VT_RCPI1_OFFSET; + + /* Record peak rate to Traffic Indicator*/ + if (u2Rate > prAdapter->prGlueInfo + ->PerfIndCache.u2CurRxRate[ucBssIndex]) { + prAdapter->prGlueInfo->PerfIndCache. + u2CurRxRate[ucBssIndex] = u2Rate; + prAdapter->prGlueInfo->PerfIndCache. + ucCurRxNss[ucBssIndex] = ucNsts; + prAdapter->prGlueInfo->PerfIndCache. + ucCurRxRCPI0[ucBssIndex] = ucRCPI0; + prAdapter->prGlueInfo->PerfIndCache. + ucCurRxRCPI1[ucBssIndex] = ucRCPI1; + } +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb) +{ + struct RX_CTRL *prRxCtrl; + struct SW_RFB *prRetSwRfb, *prNextSwRfb; + struct HW_MAC_RX_DESC *prRxStatus; + u_int8_t fgDrop; + uint8_t ucBssIndex = 0; + struct mt66xx_chip_info *prChipInfo; + + DEBUGFUNC("nicRxProcessDataPacket"); + /* DBGLOG(INIT, TRACE, ("\n")); */ + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + fgDrop = FALSE; + + prRxStatus = prSwRfb->prRxStatus; + prRxCtrl = &prAdapter->rRxCtrl; + prChipInfo = prAdapter->chip_info; + + /* Check AMPDU_nERR_Bitmap */ + prSwRfb->fgDataFrame = TRUE; + prSwRfb->fgFragFrame = FALSE; + prSwRfb->fgReorderBuffer = FALSE; + + /* BA session */ + if ((prRxStatus->u2StatusFlag & RXS_DW2_AMPDU_nERR_BITMAP) + == RXS_DW2_AMPDU_nERR_VALUE) + prSwRfb->fgReorderBuffer = TRUE; + /* non BA session */ + else if ((prRxStatus->u2StatusFlag & RXS_DW2_RX_nERR_BITMAP) + == RXS_DW2_RX_nERR_VALUE) { + if ((prRxStatus->u2StatusFlag & RXS_DW2_RX_nDATA_BITMAP) == + RXS_DW2_RX_nDATA_VALUE) + prSwRfb->fgDataFrame = FALSE; + + if ((prRxStatus->u2StatusFlag & RXS_DW2_RX_FRAG_BITMAP) == + RXS_DW2_RX_FRAG_VALUE) + prSwRfb->fgFragFrame = TRUE; + + } else { + fgDrop = TRUE; + if (!HAL_RX_STATUS_IS_ICV_ERROR(prRxStatus) + && HAL_RX_STATUS_IS_TKIP_MIC_ERROR(prRxStatus)) { + struct STA_RECORD *prStaRec; + + prStaRec = cnmGetStaRecByAddress(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, + prAdapter->rWlanInfo.rCurrBssId.arMacAddress); + if (prStaRec) { + DBGLOG(RSN, EVENT, "MIC_ERR_PKT\n"); + rsnTkipHandleMICFailure(prAdapter, prStaRec, 0); + } + } +#if UNIFIED_MAC_RX_FORMAT + else if (HAL_RX_STATUS_IS_LLC_MIS(prRxStatus) + && !HAL_RX_STATUS_IS_ERROR(prRxStatus) + && !FEAT_SUP_LLC_VLAN_RX(prChipInfo)) { + uint16_t *pu2EtherType; + + if (nicRxFillRFB(prAdapter, prSwRfb) == FALSE) { + DBGLOG(RX, ERROR, + "[%s] call nicRxFillRFB() failed\n", + __func__); + nicRxReturnRFB(prAdapter, prSwRfb); + RX_INC_CNT(prRxCtrl, RX_CLASS_ERR_DROP_COUNT); + RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); + return; + } + + pu2EtherType = (uint16_t *) + ((uint8_t *)prSwRfb->pvHeader + + 2 * MAC_ADDR_LEN); + + /* If ethernet type is VLAN, do not drop it. + * Pass up to driver process + */ + if (prSwRfb->u2HeaderLen >= ETH_HLEN + && *pu2EtherType == NTOHS(ETH_P_VLAN)) + fgDrop = FALSE; + } +#else + else if (HAL_RX_STATUS_IS_LLC_MIS(prRxStatus)) { + DBGLOG(RSN, EVENT, ("LLC_MIS_ERR\n")); + fgDrop = TRUE; /* Drop after send de-auth */ + } +#endif + } + +#if CFG_TCP_IP_CHKSUM_OFFLOAD || CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 + if (prAdapter->fgIsSupportCsumOffload && fgDrop == FALSE) + nicRxFillChksumStatus(prAdapter, prSwRfb); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + /* if(secCheckClassError(prAdapter, prSwRfb, prStaRec) == TRUE && */ + if (prAdapter->fgTestMode == FALSE && fgDrop == FALSE) { + uint16_t *pu2EtherType; + struct STA_RECORD *prStaRec; +#if CFG_HIF_RX_STARVATION_WARNING + prRxCtrl->u4QueuedCnt++; +#endif + + if (nicRxFillRFB(prAdapter, prSwRfb) == FALSE) { + DBGLOG(RX, ERROR, "[%s] call nicRxFillRFB() failed\n", + __func__); + nicRxReturnRFB(prAdapter, prSwRfb); + RX_INC_CNT(prRxCtrl, RX_CLASS_ERR_DROP_COUNT); + RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); + return; + } + ucBssIndex = secGetBssIdxByWlanIdx(prAdapter, + prSwRfb->ucWlanIdx); + GLUE_SET_PKT_BSS_IDX(prSwRfb->pvPacket, ucBssIndex); + STATS_RX_PKT_INFO_DISPLAY(prSwRfb); + + pu2EtherType = (uint16_t *) + ((uint8_t *)prSwRfb->pvHeader + 2 * MAC_ADDR_LEN); + prStaRec = prSwRfb->prStaRec; + + /* If receive EAPOL frames of sta record != STA_STATE_3 + * Re-enqueu it of MAX_EAPOL_RE_ENQUEUE_CNT times + * Otherwise, the EAPOL frames might drop in the wpa_supp + */ + if (prSwRfb->u2HeaderLen >= ETH_HLEN + && *pu2EtherType == NTOHS(ETH_P_1X) + && prStaRec != NULL + && ((prStaRec->ucStaState != STA_STATE_3) + || (prStaRec->fgIsValid != TRUE)) + && prStaRec->eapol_re_enqueue_cnt < MAX_EAPOL_REQUE) { + KAL_SPIN_LOCK_DECLARATION(); + DBGLOG(RSN, TRACE, + "Re-enqueue EAPOL frame:State[%u], retry[%d]\n", + prStaRec->ucStaState, + prStaRec->eapol_re_enqueue_cnt); + DBGLOG(RSN, TRACE, "prStaRec->fgIsValid [%d]", + prStaRec->fgIsValid); + prStaRec->eapol_re_enqueue_cnt++; + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_INSERT_TAIL(&prAdapter->rRxCtrl.rReceivedRfbList, + &prSwRfb->rQueEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + /* Wake up Rx handling thread */ + set_bit(GLUE_FLAG_RX_BIT, + &(prAdapter->prGlueInfo->ulFlag)); + wake_up_interruptible(&(prAdapter->prGlueInfo->waitq)); + return; + } + + prRetSwRfb = qmHandleRxPackets(prAdapter, prSwRfb); + if (prRetSwRfb != NULL) { + GET_CURRENT_SYSTIME(&prRxCtrl->u4LastRxTime); + do { +#if CFG_SUPPORT_MSP + if (prRetSwRfb->ucGroupVLD + & BIT(RX_GROUP_VLD_3) && + (prRetSwRfb->ucStaRecIdx < + CFG_STA_REC_NUM)) { + struct STA_RECORD *prStaRec = NULL; +#if CFG_RCPI_COMPENSATION + wlanUpdateRxFELoss(prRetSwRfb); +#endif + prStaRec = &prAdapter->arStaRec[ + prRetSwRfb->ucStaRecIdx]; + + if (prStaRec->fgIsValid && + prStaRec->fgIsInUse) { + prStaRec->u4RxVector0 = + HAL_RX_VECTOR_GET_RX_VECTOR( + prRetSwRfb->prRxStatusGroup3, + 0); + + prStaRec->u4RxVector1 = + HAL_RX_VECTOR_GET_RX_VECTOR( + prRetSwRfb->prRxStatusGroup3, + 1); + + prStaRec->u4RxVector2 = + HAL_RX_VECTOR_GET_RX_VECTOR( + prRetSwRfb->prRxStatusGroup3, + 2); + + prStaRec->u4RxVector3 = + HAL_RX_VECTOR_GET_RX_VECTOR( + prRetSwRfb->prRxStatusGroup3, + 3); + + prStaRec->u4RxVector4 = + HAL_RX_VECTOR_GET_RX_VECTOR( + prRetSwRfb->prRxStatusGroup3, + 4); + } + } +#endif +#if (CFG_SUPPORT_PERF_IND == 1) + nicRxProcessRXV( + prAdapter, + prRetSwRfb, + ucBssIndex); +#endif + /* save next first */ + prNextSwRfb = (struct SW_RFB *) + QUEUE_GET_NEXT_ENTRY( + (struct QUE_ENTRY *) + prRetSwRfb); + + switch (prRetSwRfb->eDst) { + case RX_PKT_DESTINATION_HOST: + prStaRec = cnmGetStaRecByIndex( + prAdapter, + prRetSwRfb->ucStaRecIdx); + if (prStaRec && + IS_STA_IN_AIS(prStaRec)) { +#if ARP_MONITER_ENABLE + qmHandleRxArpPackets(prAdapter, + prRetSwRfb); + qmHandleRxDhcpPackets(prAdapter, + prRetSwRfb); +#endif + } + secHandleRxEapolPacket( + prAdapter, prRetSwRfb, + prStaRec); + 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); + } +} + +#if 1 +void nicRxProcessEventPacket(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb) +{ + struct mt66xx_chip_info *prChipInfo; + struct CMD_INFO *prCmdInfo; + struct WIFI_EVENT *prEvent; + uint32_t u4Idx, u4Size; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + prChipInfo = prAdapter->chip_info; + + prEvent = (struct WIFI_EVENT *) + (prSwRfb->pucRecvBuff + prChipInfo->rxd_size); + if (prEvent->ucEID != EVENT_ID_DEBUG_MSG + && prEvent->ucEID != EVENT_ID_ASSERT_DUMP) { + DBGLOG(NIC, TRACE, + "RX EVENT: ID[0x%02X] SEQ[%u] LEN[%u]\n", + prEvent->ucEID, prEvent->ucSeqNum, + prEvent->u2PacketLength); + } + + if (prEvent->u2PacketLength > CFG_RX_MAX_PKT_SIZE) { + DBGLOG(NIC, WARN, + "RX EVENT: ID[0x%02X] SEQ[%u], invalid LEN[%u] > %u\n", + prEvent->ucEID, prEvent->ucSeqNum, + prEvent->u2PacketLength, prSwRfb->u2PacketLen); + goto done; + } + + /* Event handler table */ + u4Size = sizeof(arEventTable) / sizeof(struct + RX_EVENT_HANDLER); + + for (u4Idx = 0; u4Idx < u4Size; u4Idx++) { + if (prEvent->ucEID == arEventTable[u4Idx].eEID) { + arEventTable[u4Idx].pfnHandler(prAdapter, prEvent); + + break; + } + } + + /* Event cannot be found in event handler table, use default action */ + if (u4Idx >= u4Size) { + 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); + } else { + DBGLOG(RX, TRACE, + "UNHANDLED RX EVENT: ID[0x%02X] SEQ[%u] LEN[%u]\n", + prEvent->ucEID, prEvent->ucSeqNum, + prEvent->u2PacketLength); + } + } + +done: + /* Reset Chip NoAck flag */ + if (prAdapter->fgIsChipNoAck) { + DBGLOG(RX, WARN, + "Got response from chip, clear NoAck flag!\n"); + WARN_ON(TRUE); + } + prAdapter->ucOidTimeoutCount = 0; + prAdapter->fgIsChipNoAck = FALSE; + + nicRxReturnRFB(prAdapter, prSwRfb); +} +#else +u_int8_t fgKeepPrintCoreDump = FALSE; +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb) +{ + struct CMD_INFO *prCmdInfo; + /* P_MSDU_INFO_T prMsduInfo; */ + struct WIFI_EVENT *prEvent; + struct GLUE_INFO *prGlueInfo; + u_int8_t fgIsNewVersion; + /*#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1)*/ + uint32_t u4QueryInfoLen; + /*#endif*/ + /*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ + struct EVENT_ACCESS_EFUSE *prEventEfuseAccess; + struct EXT_EVENT_EFUSE_FREE_BLOCK *prEventGetFreeBlock; + /*#endif*/ + DEBUGFUNC("nicRxProcessEventPacket"); + /* DBGLOG(INIT, TRACE, ("\n")); */ + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + nicRxFillRFB(prAdapter, prSwRfb); + if (prSwRfb->prRxStatusGroup3 == NULL) { + DBGLOG(RX, WARN, + "rxStatusGroup3 for MGMT frame is NULL, drop this packet, dump RXD and Packet\n"); + DBGLOG_MEM8(RX, WARN, (uint8_t *) prSwRfb->prRxStatus, + sizeof(*prSwRfb->prRxStatus)); + if (prSwRfb->pvHeader) + DBGLOG_MEM8(RX, WARN, (uint8_t *) prSwRfb->pvHeader, + prSwRfb->u2PacketLen > 32 ? + 32 : prSwRfb->u2PacketLen); + nicRxReturnRFB(prAdapter, prSwRfb); + RX_INC_CNT(&prAdapter->rRxCtrl, RX_DROP_TOTAL_COUNT); +#if 0 +#if CFG_CHIP_RESET_SUPPORT + glGetRstReason(RST_GROUP3_NULL); + glResetTrigger(prAdapter); +#endif +#endif + ) { + DBGLOG(INIT, INFO, + "RX EVENT: ID[0x%02X] SEQ[%u] LEN[%u]\n", + prEvent->ucEID, prEvent->ucSeqNum, + prEvent->u2PacketLength); + } + + /* Event Handling */ + switch (prEvent->ucEID) { +#if 0 /* It is removed now */ + case EVENT_ID_CMD_RESULT: + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + struct EVENT_CMD_RESULT *prCmdResult; + + prCmdResult = (struct EVENT_CMD_RESULT *) + ((uint8_t *) 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; +#endif + +#if 0 + case EVENT_ID_CONNECTION_STATUS: + /* OBSELETE */ + { + struct EVENT_CONNECTION_STATUS *prConnectionStatus; + + prConnectionStatus = + (struct EVENT_CONNECTION_STATUS *) + (prEvent->aucBuffer); + + DbgPrint("RX EVENT: EVENT_ID_CONNECTION_STATUS = %d\n", + prConnectionStatus->ucMediaStatus); + if (prConnectionStatus->ucMediaStatus == + PARAM_MEDIA_STATE_DISCONNECTED) { + /* disconnected */ + if (kalGetMediaStateIndicated(prGlueInfo) != + PARAM_MEDIA_STATE_DISCONNECTED) { + + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, + NULL, 0); + + prAdapter->rWlanInfo.u4SysTime = + kalGetTimeTick(); + } + } else if (prConnectionStatus->ucMediaStatus == + PARAM_MEDIA_STATE_CONNECTED) { + /* connected */ + prAdapter->rWlanInfo.u4SysTime = + kalGetTimeTick(); + + /* fill information for association result */ + prAdapter->rWlanInfo.rCurrBssId.rSsid. + u4SsidLen = prConnectionStatus->ucSsidLen; + kalMemCopy( + prAdapter->rWlanInfo.rCurrBssId. + rSsid.aucSsid, + prConnectionStatus->aucSsid, + prConnectionStatus->ucSsidLen); + + kalMemCopy( + prAdapter->rWlanInfo.rCurrBssId. + arMacAddress, + prConnectionStatus->aucBssid, + MAC_ADDR_LEN); + /* @FIXME */ + prAdapter->rWlanInfo.rCurrBssId.u4Privacy = + prConnectionStatus->ucEncryptStatus; + /* @FIXME */ + prAdapter->rWlanInfo.rCurrBssId.rRssi = 0; + /* @FIXME */ + prAdapter->rWlanInfo.rCurrBssId. + eNetworkTypeInUse = PARAM_NETWORK_TYPE_AUTOMODE; + prAdapter->rWlanInfo.rCurrBssId.rConfiguration. + u4BeaconPeriod + = prConnectionStatus->u2BeaconPeriod; + prAdapter->rWlanInfo.rCurrBssId.rConfiguration. + u4ATIMWindow + = prConnectionStatus->u2ATIMWindow; + prAdapter->rWlanInfo.rCurrBssId.rConfiguration. + u4DSConfig + = prConnectionStatus->u4FreqInKHz; + prAdapter->rWlanInfo.ucNetworkType = + prConnectionStatus->ucNetworkType; + + switch (prConnectionStatus->ucInfraMode) { + case 0: + prAdapter->rWlanInfo.rCurrBssId.eOpMode + = NET_TYPE_IBSS; + break; + case 1: + prAdapter->rWlanInfo.rCurrBssId.eOpMode + = NET_TYPE_INFRA; + break; + case 2: + default: + prAdapter->rWlanInfo.rCurrBssId.eOpMode + = NET_TYPE_AUTO_SWITCH; + break; + } + /* always indicate to OS according to MSDN + * (re-association/roaming) + */ + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_CONNECT, NULL, 0); + } + } + break; + + case EVENT_ID_SCAN_RESULT: + /* OBSELETE */ + break; +#endif + + case EVENT_ID_RX_ADDBA: + /* The FW indicates that an RX BA agreement + * will be established + */ + qmHandleEventRxAddBa(prAdapter, prEvent); + break; + + case EVENT_ID_RX_DELBA: + /* The FW indicates that an RX BA agreement + * has been deleted + */ + qmHandleEventRxDelBa(prAdapter, prEvent); + break; + + case EVENT_ID_CHECK_REORDER_BUBBLE: + qmHandleEventCheckReorderBubble(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( + struct EVENT_LINK_QUALITY_EX)) { + struct EVENT_LINK_QUALITY_EX *prLqEx = + (struct EVENT_LINK_QUALITY_EX *) + (prEvent->aucBuffer); + + if (prLqEx->ucIsLQ0Rdy) + nicUpdateLinkQuality(prAdapter, 0, + (struct EVENT_LINK_QUALITY *) + prLqEx); + if (prLqEx->ucIsLQ1Rdy) + nicUpdateLinkQuality(prAdapter, 1, + (struct 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, 0, + (struct EVENT_LINK_QUALITY *) + (prEvent->aucBuffer)); + } +#else + /*only support ais query */ + { + uint8_t ucBssIndex; + struct BSS_INFO *prBssInfo; + + for (ucBssIndex = 0; + ucBssIndex < prAdapter->ucHwBssIdNum; + ucBssIndex++) { + prBssInfo = + prAdapter->aprBssInfo[ + ucBssIndex]; + + if ((prBssInfo->eNetworkType == + NETWORK_TYPE_AIS) + && (prBssInfo->fgIsInUse)) + break; + } + + /* No hit(bss1 for default ais network) */ + if (ucBssIndex >= prAdapter->ucHwBssIdNum) + ucBssIndex = 1; + + nicUpdateLinkQuality(prAdapter, ucBssIndex, + (struct EVENT_LINK_QUALITY_V2 *) + (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 + >= (int32_t) ( + prAdapter->rLinkQuality.cRssi)) { + prAdapter->rWlanInfo.eRssiTriggerType = + ENUM_RSSI_TRIGGER_TRIGGERED; + + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (void *) + &(prAdapter->rWlanInfo. + rRssiTriggerValue), + sizeof(int32_t)); + } else if (prAdapter->rWlanInfo.eRssiTriggerType == + ENUM_RSSI_TRIGGER_LESS + && prAdapter->rWlanInfo.rRssiTriggerValue + <= (int32_t) ( + prAdapter->rLinkQuality.cRssi)) { + prAdapter->rWlanInfo.eRssiTriggerType = + ENUM_RSSI_TRIGGER_TRIGGERED; + + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (void *) + &(prAdapter->rWlanInfo. + rRssiTriggerValue), + sizeof(int32_t)); + } +#endif + + break; + + /*#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1)*/ + case EVENT_ID_LAYER_0_EXT_MAGIC_NUM: + if ((prEvent->ucExtenEID) == EXT_EVENT_ID_CMD_RESULT) { + + u4QueryInfoLen = + sizeof( + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE); + + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + if ((prCmdInfo->fgIsOid) != 0) { + kalOidComplete( + prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo( + prAdapter, prCmdInfo); + } + } + } + /*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ + + else if ((prEvent->ucExtenEID) == + EXT_EVENT_ID_CMD_EFUSE_ACCESS) { + u4QueryInfoLen = + sizeof( + struct PARAM_CUSTOM_ACCESS_EFUSE); + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + prEventEfuseAccess = + (struct EVENT_ACCESS_EFUSE *) + (prEvent->aucBuffer); + + /* Efuse block size 16 */ + kalMemCopy(prAdapter->aucEepromVaule, + prEventEfuseAccess->aucData, 16); + + if (prCmdInfo != NULL) { + if ((prCmdInfo->fgIsOid) != 0) { + kalOidComplete( + prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo( + prAdapter, prCmdInfo); + + } + } + } + + else if ((prEvent->ucExtenEID) == + EXT_EVENT_ID_EFUSE_FREE_BLOCK) { + u4QueryInfoLen = sizeof(struct + PARAM_CUSTOM_EFUSE_FREE_BLOCK); + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + prEventGetFreeBlock = + (struct EXT_EVENT_EFUSE_FREE_BLOCK *) + (prEvent->aucBuffer); + prAdapter->u4FreeBlockNum = + prEventGetFreeBlock->u2FreeBlockNum; + + if (prCmdInfo != NULL) { + if ((prCmdInfo->fgIsOid) != 0) { + kalOidComplete( + prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, + prCmdInfo); + } + } + } + /*#endif*/ + break; + /*#endif*/ + + case EVENT_ID_MIC_ERR_INFO: { + struct EVENT_MIC_ERR_INFO *prMicError; + /* P_PARAM_AUTH_EVENT_T prAuthEvent; */ + struct STA_RECORD *prStaRec; + + DBGLOG(RSN, EVENT, "EVENT_ID_MIC_ERR_INFO\n"); + + prMicError = (struct EVENT_MIC_ERR_INFO *) ( + prEvent->aucBuffer); + prStaRec = cnmGetStaRecByAddress(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, + prAdapter->rWlanInfo.rCurrBssId.arMacAddress); + ASSERT(prStaRec); + + if (prStaRec) + rsnTkipHandleMICFailure(prAdapter, prStaRec, + (u_int8_t) prMicError->u4Flags); + else + DBGLOG(RSN, INFO, "No STA rec!!\n"); +#if 0 + prAuthEvent = (struct PARAM_AUTH_EVENT *) + prAdapter->aucIndicationEventBuffer; + + /* Status type: Authentication Event */ + prAuthEvent->rStatus.eStatusType = + ENUM_STATUS_TYPE_AUTHENTICATION; + + /* Authentication request */ + prAuthEvent->arRequest[0].u4Length = sizeof( + struct PARAM_AUTH_REQUEST); + kalMemCopy((void *) prAuthEvent->arRequest[0].arBssid, + (void *) + prAdapter->rWlanInfo.rCurrBssId.arMacAddress, + 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, + (void *) prAuthEvent, + sizeof(struct PARAM_STATUS_INDICATION) + sizeof( + struct PARAM_AUTH_REQUEST)); +#endif + } + break; + +#if 0 /* Marked for MT6630 */ + case EVENT_ID_ASSOC_INFO: { + struct EVENT_ASSOC_INFO *prAssocInfo; + + prAssocInfo = (struct EVENT_ASSOC_INFO *) ( + prEvent->aucBuffer); + + kalHandleAssocInfo(prAdapter->prGlueInfo, prAssocInfo); + } + break; + + case EVENT_ID_802_11_PMKID: { + struct PARAM_AUTH_EVENT *prAuthEvent; + uint8_t *cp; + uint32_t u4LenOfUsedBuffer; + + prAuthEvent = (struct PARAM_AUTH_EVENT *) + prAdapter->aucIndicationEventBuffer; + + prAuthEvent->rStatus.eStatusType = + ENUM_STATUS_TYPE_CANDIDATE_LIST; + + u4LenOfUsedBuffer = + (uint32_t) (prEvent->u2PacketLength - 8); + + prAuthEvent->arRequest[0].u4Length = u4LenOfUsedBuffer; + + cp = (uint8_t *) &prAuthEvent->arRequest[0]; + + /* Status type: PMKID Candidatelist Event */ + kalMemCopy(cp, (struct EVENT_PMKID_CANDIDATE_LIST *) ( + prEvent->aucBuffer), + prEvent->u2PacketLength - 8); + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (void *) prAuthEvent, + sizeof(struct PARAM_STATUS_INDICATION) + + u4LenOfUsedBuffer); + } + break; +#endif + case EVENT_ID_SCAN_DONE: + fgIsNewVersion = TRUE; + scnEventScanDone(prAdapter, + (struct EVENT_SCAN_DONE *) (prEvent->aucBuffer), + fgIsNewVersion); + break; + + case EVENT_ID_NLO_DONE: + DBGLOG(INIT, INFO, "EVENT_ID_NLO_DONE\n"); + scnEventNloDone(prAdapter, + (struct EVENT_NLO_DONE *) (prEvent->aucBuffer)); +#if CFG_SUPPORT_PNO + prAdapter->prAisBssInfo->fgIsPNOEnable = FALSE; + if (prAdapter->prAisBssInfo->fgIsNetRequestInActive + && prAdapter->prAisBssInfo->fgIsPNOEnable) { + UNSET_NET_ACTIVE(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex); + DBGLOG(INIT, INFO, + "INACTIVE AIS from ACTIVEto disable PNO\n"); + /* sync with firmware */ + nicDeactivateNetwork(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex); + } +#endif + break; + + case EVENT_ID_TX_DONE: +#if 1 + nicTxProcessTxDoneEvent(prAdapter, prEvent); +#else + { + struct EVENT_TX_DONE *prTxDone; + + prTxDone = + (struct EVENT_TX_DONE *) + (prEvent->aucBuffer); + + DBGLOG(INIT, INFO, + "EVENT_ID_TX_DONE WIDX:PID[%u:%u] Status[%u] SN[%u]\n", + prTxDone->ucWlanIndex, + prTxDone->ucPacketSeq, + prTxDone->ucStatus, + prTxDone->u2SequenceNumber); + + /* call related TX Done Handler */ + prMsduInfo = nicGetPendingTxMsduInfo(prAdapter, + prTxDone->ucWlanIndex, + 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 ENUM_TX_RESULT_CODE) + (prTxDone->ucStatus)); + + if (prMsduInfo->eSrc == TX_PACKET_MGMT) + cnmMgtPktFree( + prAdapter, prMsduInfo); + else + nicTxReturnMsduInfo( + prAdapter, prMsduInfo); + } + } +#endif + break; + + case EVENT_ID_SLEEPY_INFO: +#if defined(_HIF_USB) +#else + { + struct EVENT_SLEEPY_INFO *prEventSleepyNotify; + + prEventSleepyNotify = (struct EVENT_SLEEPY_INFO *) ( + prEvent->aucBuffer); + + prAdapter->fgWiFiInSleepyState = (u_int8_t) ( + prEventSleepyNotify->ucSleepyState); + +#if CFG_SUPPORT_MULTITHREAD + if (prEventSleepyNotify->ucSleepyState) + kalSetFwOwnEvent2Hif(prGlueInfo); +#endif + } +#endif + break; + case EVENT_ID_BT_OVER_WIFI: +#if CFG_ENABLE_BT_OVER_WIFI + { + uint8_t aucTmp[sizeof(struct BT_OVER_WIFI_EVENT) + + sizeof(struct BOW_LINK_DISCONNECTED)]; + struct EVENT_BT_OVER_WIFI *prEventBtOverWifi; + struct BT_OVER_WIFI_EVENT *prBowEvent; + struct BOW_LINK_CONNECTED *prBowLinkConnected; + struct BOW_LINK_DISCONNECTED *prBowLinkDisconnected; + + prEventBtOverWifi = (struct EVENT_BT_OVER_WIFI *) ( + prEvent->aucBuffer); + + /* construct event header */ + prBowEvent = (struct BT_OVER_WIFI_EVENT *) aucTmp; + + if (prEventBtOverWifi->ucLinkStatus == 0) { + /* Connection */ + prBowEvent->rHeader.ucEventId = + BOW_EVENT_ID_LINK_CONNECTED; + prBowEvent->rHeader.ucSeqNumber = 0; + prBowEvent->rHeader.u2PayloadLength = sizeof( + struct BOW_LINK_CONNECTED); + + /* fill event body */ + prBowLinkConnected = + (struct 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( + struct BOW_LINK_DISCONNECTED); + + /* fill event body */ + prBowLinkDisconnected = + (struct BOW_LINK_DISCONNECTED *) + (prBowEvent->aucPayload); + /* @FIXME */ + prBowLinkDisconnected->ucReason = 0; + 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(struct 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; + +#if CFG_SUPPORT_MSP + case EVENT_ID_WLAN_INFO: + /* buffer statistics for further query */ + prAdapter->fgIsStatValid = TRUE; + prAdapter->rStatUpdateTime = kalGetTimeTick(); + kalMemCopy(&prAdapter->rEventWlanInfo, + prEvent->aucBuffer, + sizeof(struct EVENT_WLAN_INFO)); + + DBGLOG(RSN, INFO, "EVENT_ID_WLAN_INFO"); + /* 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_MIB_INFO: + /* buffer statistics for further query */ + prAdapter->fgIsStatValid = TRUE; + prAdapter->rStatUpdateTime = kalGetTimeTick(); + + DBGLOG(RSN, INFO, "EVENT_ID_MIB_INFO"); + /* command response handling */ + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + if (prCmdInfo->pfCmdDoneHandler) + prCmdInfo->pfCmdDoneHandler(prAdapter, + prCmdInfo, + prEvent->aucBuffer); + else if (prCmdInfo->fgIsOid) + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + 0, WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + + break; +#endif + 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) { + struct BSS_INFO *prBssInfo = + (struct BSS_INFO *) NULL; + struct EVENT_BSS_BEACON_TIMEOUT + *prEventBssBeaconTimeout; + + prEventBssBeaconTimeout = + (struct EVENT_BSS_BEACON_TIMEOUT *) + (prEvent->aucBuffer); + + if (prEventBssBeaconTimeout->ucBssIndex >= + prAdapter->ucHwBssIdNum) + break; + + DBGLOG(INIT, INFO, "Reason code: %d\n", + prEventBssBeaconTimeout->ucReasonCode); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prEventBssBeaconTimeout->ucBssIndex); + + if (prEventBssBeaconTimeout->ucBssIndex == + prAdapter->prAisBssInfo->ucBssIndex) + aisBssBeaconTimeout(prAdapter); +#if CFG_ENABLE_WIFI_DIRECT + else if (prBssInfo->eNetworkType == + NETWORK_TYPE_P2P) + p2pRoleFsmRunEventBeaconTimeout( + prAdapter, prBssInfo); +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (GET_BSS_INFO_BY_INDEX(prAdapter, + prEventBssBeaconTimeout->ucBssIndex)-> + eNetworkType == NETWORK_TYPE_BOW) { + /* ToDo:: Nothing */ + } +#endif + else { + DBGLOG(RX, ERROR, + "EVENT_ID_BSS_BEACON_TIMEOUT: (ucBssIndex = %d)\n", + prEventBssBeaconTimeout->ucBssIndex); + } + } + + break; + case EVENT_ID_UPDATE_NOA_PARAMS: +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { + struct EVENT_UPDATE_NOA_PARAMS + *prEventUpdateNoaParam; + + prEventUpdateNoaParam = + (struct EVENT_UPDATE_NOA_PARAMS *) + (prEvent->aucBuffer); + + if (GET_BSS_INFO_BY_INDEX(prAdapter, + prEventUpdateNoaParam-> + ucBssIndex)-> + eNetworkType == + NETWORK_TYPE_P2P) { + p2pProcessEvent_UpdateNOAParam( + prAdapter, + prEventUpdateNoaParam-> + ucBssIndex, + prEventUpdateNoaParam); + } else { + ASSERT(0); + } + } +#else + ASSERT(0); +#endif + break; + + case EVENT_ID_STA_AGING_TIMEOUT: +#if CFG_ENABLE_WIFI_DIRECT + { + if (prAdapter->fgDisStaAgingTimeoutDetection == FALSE) { + struct EVENT_STA_AGING_TIMEOUT + *prEventStaAgingTimeout; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo = + (struct BSS_INFO *) NULL; + + prEventStaAgingTimeout = + (struct EVENT_STA_AGING_TIMEOUT *) + (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 = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + bssRemoveClient(prAdapter, prBssInfo, prStaRec); + + /* Call False Auth */ + if (prAdapter->fgIsP2PRegistered) { + p2pFuncDisconnect(prAdapter, + prBssInfo, 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, + (struct EVENT_AP_OBSS_STATUS *) + prEvent->aucBuffer); +#endif + break; + + case EVENT_ID_ROAMING_STATUS: +#if CFG_SUPPORT_ROAMING + { + struct CMD_ROAMING_TRANSIT *prTransit; + + prTransit = (struct CMD_ROAMING_TRANSIT *) ( + prEvent->aucBuffer); + roamingFsmProcessEvent(prAdapter, prTransit); + } +#endif /* CFG_SUPPORT_ROAMING */ + break; + case EVENT_ID_SEND_DEAUTH: +#if DBG + { + struct WLAN_MAC_HEADER *prWlanMacHeader; + + prWlanMacHeader = (struct WLAN_MAC_HEADER *) + prEvent->aucBuffer; + 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 = (struct WLAN_MAC_HEADER *) + prEvent->aucBuffer; + if (authSendDeauthFrame(prAdapter, + NULL, + NULL, + prSwRfb, + REASON_CODE_CLASS_3_ERR, + (PFN_TX_DONE_HANDLER) NULL) == + WLAN_STATUS_SUCCESS) { + DBGLOG(RX, INFO, "Send Deauth Error\n"); + } + break; + +#if CFG_SUPPORT_RDD_TEST_MODE + case EVENT_ID_UPDATE_RDD_STATUS: { + struct EVENT_RDD_STATUS *prEventRddStatus; + + prEventRddStatus = (struct EVENT_RDD_STATUS *) ( + prEvent->aucBuffer); + + prAdapter->ucRddStatus = prEventRddStatus->ucRddStatus; + } + + break; +#endif + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS + case EVENT_ID_UPDATE_BWCS_STATUS: + { + struct PTA_IPC *prEventBwcsStatus; + + prEventBwcsStatus = + (struct PTA_IPC *) (prEvent->aucBuffer); + +#if CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(RSN, EVENT, "BCM BWCS Event: %02x%02x%02x%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, + (void *) prEventBwcsStatus, + sizeof(struct PTA_IPC)); + } + + break; + + case EVENT_ID_UPDATE_BCM_DEBUG: { + struct PTA_IPC *prEventBwcsStatus; + + prEventBwcsStatus = + (struct PTA_IPC *) (prEvent->aucBuffer); + +#if CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(RSN, EVENT, "BCM FW status: %02x%02x%02x%02x\n", + prEventBwcsStatus->u.aucBTPParams[0], + prEventBwcsStatus->u.aucBTPParams[1], + prEventBwcsStatus->u.aucBTPParams[2], + prEventBwcsStatus->u.aucBTPParams[3]); +#endif + } + + break; +#endif + case EVENT_ID_ADD_PKEY_DONE: { + struct EVENT_ADD_KEY_DONE_INFO *prAddKeyDone; + struct STA_RECORD *prStaRec; + + prAddKeyDone = (struct EVENT_ADD_KEY_DONE_INFO *) ( + prEvent->aucBuffer); + + DBGLOG(RSN, EVENT, + "EVENT_ID_ADD_PKEY_DONE BSSIDX=%d " MACSTR "\n", + prAddKeyDone->ucBSSIndex, + MAC2STR(prAddKeyDone->aucStaAddr)); + + prStaRec = cnmGetStaRecByAddress(prAdapter, + prAddKeyDone->ucBSSIndex, + prAddKeyDone->aucStaAddr); + + if (prStaRec) { + DBGLOG(RSN, EVENT, + "STA " MACSTR " Add Key Done!!\n", + MAC2STR(prStaRec->aucMacAddr)); + prStaRec->fgIsTxKeyReady = TRUE; + qmUpdateStaRec(prAdapter, prStaRec); + } + } + break; + case EVENT_ID_ICAP_DONE: { + struct EVENT_ICAP_STATUS *prEventIcapStatus; + struct PARAM_CUSTOM_MEM_DUMP_STRUCT rMemDumpInfo; + uint32_t u4QueryInfo; + + prEventIcapStatus = (struct EVENT_ICAP_STATUS *) ( + prEvent->aucBuffer); + + rMemDumpInfo.u4Address = + prEventIcapStatus->u4StartAddress; + rMemDumpInfo.u4Length = + prEventIcapStatus->u4IcapSieze; +#if CFG_SUPPORT_QA_TOOL + rMemDumpInfo.u4IcapContent = + prEventIcapStatus->u4IcapContent; +#endif + + wlanoidQueryMemDump(prAdapter, &rMemDumpInfo, + sizeof(rMemDumpInfo), &u4QueryInfo); + + } + + break; + case EVENT_ID_DEBUG_MSG: { + struct EVENT_DEBUG_MSG *prEventDebugMsg; + uint16_t u2DebugMsgId; + uint8_t ucMsgType; + uint8_t ucFlags; + uint32_t u4Value; + uint16_t u2MsgSize; + uint8_t *pucMsg; + + prEventDebugMsg = (struct EVENT_DEBUG_MSG *) ( + prEvent->aucBuffer); + + u2DebugMsgId = prEventDebugMsg->u2DebugMsgId; + ucMsgType = prEventDebugMsg->ucMsgType; + ucFlags = prEventDebugMsg->ucFlags; + u4Value = prEventDebugMsg->u4Value; + u2MsgSize = prEventDebugMsg->u2MsgSize; + pucMsg = prEventDebugMsg->aucMsg; + + DBGLOG(SW4, TRACE, + "DEBUG_MSG Id %u Type %u Fg 0x%x Val 0x%x Size %u\n", + u2DebugMsgId, ucMsgType, + ucFlags, u4Value, u2MsgSize); + + if (u2MsgSize <= DEBUG_MSG_SIZE_MAX) { + if (ucMsgType >= DEBUG_MSG_TYPE_END) + ucMsgType = DEBUG_MSG_TYPE_MEM32; + + if (ucMsgType == DEBUG_MSG_TYPE_ASCII) { + uint8_t *pucChr; + + pucMsg[u2MsgSize] = '\0'; + + /* skip newline */ + pucChr = kalStrChr(pucMsg, '\0'); + if (*(pucChr - 1) == '\n') + *(pucChr - 1) = '\0'; + + DBGLOG(SW4, INFO, "%s\n", pucMsg); + } else if (ucMsgType == DEBUG_MSG_TYPE_MEM8) { + DBGLOG(SW4, INFO, "Dump MEM8\n"); + DBGLOG_MEM8(SW4, INFO, + pucMsg, u2MsgSize); + } else { + DBGLOG(SW4, INFO, "Dump MEM32\n"); + DBGLOG_MEM32(SW4, INFO, pucMsg, + u2MsgSize); + } + } /* DEBUG_MSG_SIZE_MAX */ + else + DBGLOG(SW4, INFO, + "Debug msg size %u is too large.\n", + u2MsgSize); + } + break; + +#if CFG_SUPPORT_BATCH_SCAN + case EVENT_ID_BATCH_RESULT: + DBGLOG(SCN, TRACE, "Got EVENT_ID_BATCH_RESULT"); + + /* command response handling */ + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + if (prCmdInfo->pfCmdDoneHandler) + prCmdInfo->pfCmdDoneHandler(prAdapter, + prCmdInfo, + prEvent->aucBuffer); + else if (prCmdInfo->fgIsOid) + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + 0, WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + + break; +#endif /* CFG_SUPPORT_BATCH_SCAN */ + +#if CFG_SUPPORT_TDLS + case EVENT_ID_TDLS: + + TdlsexEventHandle(prAdapter->prGlueInfo, + (uint8_t *) prEvent->aucBuffer, + (uint32_t) (prEvent->u2PacketLength - 8)); + break; +#endif /* CFG_SUPPORT_TDLS */ + + case EVENT_ID_DUMP_MEM: + DBGLOG(INIT, INFO, "%s: EVENT_ID_DUMP_MEM\n", __func__); + + prCmdInfo = nicGetPendingCmdInfo(prAdapter, + prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + DBGLOG(INIT, INFO, ": ==> 1\n"); + 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); + } else { + /* Burst mode */ + DBGLOG(INIT, INFO, ": ==> 2\n"); + nicEventQueryMemDump(prAdapter, + prEvent->aucBuffer); + } + break; +#if CFG_ASSERT_DUMP + case EVENT_ID_ASSERT_DUMP: + + if (prEvent->ucS2DIndex == S2D_INDEX_EVENT_N2H) { + if (!prAdapter->fgN9AssertDumpOngoing) { + DBGLOG(INIT, INFO, + "%s: EVENT_ID_ASSERT_DUMP\n", + __func__); + DBGLOG(INIT, INFO, + "\n[DUMP_N9]====N9 ASSERT_DUMPSTART====\n"); + fgKeepPrintCoreDump = TRUE; + if (kalOpenCorDumpFile(TRUE) != + WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, + "kalOpenCorDumpFile fail\n"); + else + prAdapter->fgN9CorDumpFileOpend + = TRUE; + + prAdapter->fgN9AssertDumpOngoing = TRUE; + } else if (prAdapter->fgN9AssertDumpOngoing) { + + if (fgKeepPrintCoreDump) + DBGLOG(INIT, INFO, + "[DUMP_N9]%s:\n", + prEvent->aucBuffer); + if (!kalStrnCmp(prEvent->aucBuffer, + ";more log added here", + 5) || !kalStrnCmp( + prEvent->aucBuffer, + ";[core dump start]", + 5)) + fgKeepPrintCoreDump = FALSE; + + if (prAdapter->fgN9CorDumpFileOpend && + (kalWriteCorDumpFile( + prEvent->aucBuffer, + prEvent->u2PacketLength, + TRUE) != + WLAN_STATUS_SUCCESS)) { + DBGLOG(INIT, INFO, + "kalWriteN9CorDumpFile fail\n"); + } + wlanCorDumpTimerReset(prAdapter, TRUE); + } + } else { + /* prEvent->ucS2DIndex == S2D_INDEX_EVENT_C2H */ + if (!prAdapter->fgCr4AssertDumpOngoing) { + DBGLOG(INIT, INFO, + "%s: EVENT_ID_ASSERT_DUMP\n", + __func__); + DBGLOG(INIT, INFO, + "\n[DUMP_Cr4]====CR4 ASSERT_DUMPSTART====\n"); + fgKeepPrintCoreDump = TRUE; + if (kalOpenCorDumpFile(FALSE) != + WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, + "kalOpenCorDumpFile fail\n"); + else + prAdapter-> + fgCr4CorDumpFileOpend = TRUE; + + prAdapter->fgCr4AssertDumpOngoing = + TRUE; + } else if (prAdapter->fgCr4AssertDumpOngoing) { + if (fgKeepPrintCoreDump) + DBGLOG(INIT, INFO, + "[DUMP_CR4]%s:\n", + prEvent->aucBuffer); + if (!kalStrnCmp(prEvent->aucBuffer, + ";more log added here", + 5)) + fgKeepPrintCoreDump = FALSE; + + if (prAdapter->fgCr4CorDumpFileOpend && + (kalWriteCorDumpFile( + prEvent->aucBuffer, + prEvent->u2PacketLength, + FALSE) != + WLAN_STATUS_SUCCESS)) { + DBGLOG(INIT, INFO, + "kalWriteN9CorDumpFile fail\n"); + } + wlanCorDumpTimerReset(prAdapter, FALSE); + } + } + break; + +#endif + + case EVENT_ID_RDD_SEND_PULSE: + DBGLOG(INIT, INFO, "%s: EVENT_ID_RDD_SEND_PULSE\n", + __func__); + + nicEventRddPulseDump(prAdapter, prEvent->aucBuffer); + break; + + case EVENT_ID_ACCESS_RX_STAT: + case EVENT_ID_ACCESS_REG: + case EVENT_ID_NIC_CAPABILITY: + 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; + } + + /* Reset Chip NoAck flag */ + if (prGlueInfo->prAdapter->fgIsChipNoAck) { + DBGLOG(INIT, WARN, + "Got response from chip, clear NoAck flag!\n"); + WARN_ON(TRUE); + } + prGlueInfo->prAdapter->ucOidTimeoutCount = 0; + prGlueInfo->prAdapter->fgIsChipNoAck = FALSE; + + nicRxReturnRFB(prAdapter, prSwRfb); + } +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb) +{ + struct GLUE_INFO *prGlueInfo; + uint8_t ucSubtype; +#if CFG_SUPPORT_802_11W + /* BOOL fgMfgDrop = FALSE; */ +#endif + ASSERT(prAdapter); + ASSERT(prSwRfb); + + if (nicRxFillRFB(prAdapter, prSwRfb) == FALSE) { + DBGLOG(RX, ERROR, "[%s] call nicRxFillRFB() failed\n", + __func__); + nicRxReturnRFB(prAdapter, prSwRfb); + RX_INC_CNT(&prAdapter->rRxCtrl, RX_DROP_TOTAL_COUNT); + return; + } + + ucSubtype = (*(uint8_t *) (prSwRfb->pvHeader) & + MASK_FC_SUBTYPE) >> OFFSET_OF_FC_SUBTYPE; + +#if CFG_RX_PKTS_DUMP + { + struct WLAN_MAC_MGMT_HEADER *prWlanMgmtHeader; + uint16_t u2TxFrameCtrl; + + u2TxFrameCtrl = (*(uint8_t *) (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) { + + prWlanMgmtHeader = + (struct WLAN_MAC_MGMT_HEADER *) ( + prSwRfb->pvHeader); + + DBGLOG(SW4, INFO, + "QM RX MGT: net %u sta idx %u wlan idx %u ssn %u ptype %u subtype %u 11 %u\n", + prSwRfb->prStaRec->ucBssIndex, + prSwRfb->ucStaRecIdx, + prSwRfb->ucWlanIdx, + prWlanMgmtHeader->u2SeqCtrl, + /* The new SN of the frame */ + prSwRfb->ucPacketType, ucSubtype); + /* HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr))); */ + + DBGLOG_MEM8(SW4, TRACE, + (uint8_t *) prSwRfb->pvHeader, + prSwRfb->u2PacketLen); + } + } + } +#endif +#if CFG_SUPPORT_802_11W + if (HAL_RX_STATUS_IS_ICV_ERROR(prSwRfb->prRxStatus)) { + if (HAL_RX_STATUS_GET_SEC_MODE(prSwRfb->prRxStatus) == + CIPHER_SUITE_BIP) + DBGLOG(RSN, INFO, "[MFP] RX with BIP ICV ERROR\n"); + else + DBGLOG(RSN, INFO, "[MFP] RX with ICV ERROR\n"); + + nicRxReturnRFB(prAdapter, prSwRfb); + RX_INC_CNT(&prAdapter->rRxCtrl, RX_DROP_TOTAL_COUNT); + return; + } +#endif + + if (prAdapter->fgTestMode == FALSE) { +#if CFG_MGMT_FRAME_HANDLING + prGlueInfo = prAdapter->prGlueInfo; + if ((prGlueInfo == NULL) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(RX, WARN, + "Bypass this mgmt frame without wlanProbe done\n"); + } else 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); +} + +void nicRxProcessMsduReport(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb) +{ + halRxProcessMsduReport(prAdapter, prSwRfb); + + nicRxReturnRFB(prAdapter, prSwRfb); +} + +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG +static void nicRxCheckWakeupReason(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb) +{ + struct mt66xx_chip_info *prChipInfo; + struct WIFI_EVENT *prEvent; + uint8_t *pvHeader = NULL; + struct HW_MAC_RX_DESC *prRxStatus; + uint16_t u2PktLen = 0; + uint32_t u4HeaderOffset; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + if (!prSwRfb) + return; + + prRxStatus = prSwRfb->prRxStatus; + if (!prRxStatus) + return; + + prSwRfb->ucGroupVLD = (uint8_t) HAL_RX_STATUS_GET_GROUP_VLD(prRxStatus); + + switch (prSwRfb->ucPacketType) { + case RX_PKT_TYPE_RX_DATA: + { + uint16_t u2Temp = 0; + + u2PktLen = HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus); + u4HeaderOffset = (uint32_t) + (HAL_RX_STATUS_GET_HEADER_OFFSET(prRxStatus)); + u2Temp = prChipInfo->rxd_size; + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_4)) + u2Temp += sizeof(struct HW_MAC_RX_STS_GROUP_4); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_1)) + u2Temp += sizeof(struct HW_MAC_RX_STS_GROUP_1); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_2)) + u2Temp += sizeof(struct HW_MAC_RX_STS_GROUP_2); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_3)) + u2Temp += sizeof(struct HW_MAC_RX_STS_GROUP_3); + pvHeader = (uint8_t *)prRxStatus + u2Temp + u4HeaderOffset; + u2PktLen -= u2Temp + u4HeaderOffset; + if (!pvHeader) { + DBGLOG(RX, ERROR, + "data packet but pvHeader is NULL!\n"); + break; + } + if ((prRxStatus->u2StatusFlag & (RXS_DW2_RX_nERR_BITMAP | + RXS_DW2_RX_nDATA_BITMAP)) == RXS_DW2_RX_nDATA_VALUE) { + struct WLAN_MAC_HEADER *prWlanMacHeader = + (struct WLAN_MAC_HEADER *)pvHeader; + + if ((prWlanMacHeader->u2FrameCtrl & MASK_FRAME_TYPE) == + MAC_FRAME_BLOCK_ACK_REQ) { + DBGLOG(RX, INFO, + "BAR frame[SSN:%d, TID:%d] wakeup host\n", + prSwRfb->u2SSN, prSwRfb->ucTid); + break; + } + } + u2Temp = (pvHeader[ETH_TYPE_LEN_OFFSET] << 8) | + (pvHeader[ETH_TYPE_LEN_OFFSET + 1]); + + switch (u2Temp) { + case ETH_P_IPV4: + u2Temp = *(uint16_t *) &pvHeader[ETH_HLEN + 4]; + DBGLOG(RX, INFO, + "IP Packet from:%d.%d.%d.%d, IP ID 0x%04x wakeup host\n", + pvHeader[ETH_HLEN + 12], + pvHeader[ETH_HLEN + 13], + pvHeader[ETH_HLEN + 14], + pvHeader[ETH_HLEN + 15], u2Temp); + break; + case ETH_P_ARP: + break; + case ETH_P_1X: + case ETH_P_PRE_1X: +#if CFG_SUPPORT_WAPI + case ETH_WPI_1X: +#endif + case ETH_P_AARP: + case ETH_P_IPV6: + case ETH_P_IPX: + case 0x8100: /* VLAN */ + case 0x890d: /* TDLS */ + DBGLOG(RX, INFO, + "Data Packet, EthType 0x%04x wakeup host\n", + u2Temp); + break; + default: + DBGLOG(RX, WARN, + "abnormal packet, EthType 0x%04x wakeup host\n", + u2Temp); + DBGLOG_MEM8(RX, INFO, + pvHeader, u2PktLen > 50 ? 50:u2PktLen); + break; + } + break; + } + case RX_PKT_TYPE_SW_DEFINED: + /* HIF_RX_PKT_TYPE_EVENT */ + if ((prSwRfb->prRxStatus->u2PktTYpe & + RXM_RXD_PKT_TYPE_SW_BITMAP) == + RXM_RXD_PKT_TYPE_SW_EVENT) { + + prEvent = (struct WIFI_EVENT *) + (prSwRfb->pucRecvBuff + prChipInfo->rxd_size); + + DBGLOG(RX, INFO, "Event 0x%02x wakeup host\n", + prEvent->ucEID); + break; + + } + /* case HIF_RX_PKT_TYPE_MANAGEMENT: */ + else if ((prSwRfb->prRxStatus->u2PktTYpe & + RXM_RXD_PKT_TYPE_SW_BITMAP) == + RXM_RXD_PKT_TYPE_SW_FRAME) { + uint8_t ucSubtype; + struct WLAN_MAC_MGMT_HEADER *prWlanMgmtHeader; + uint16_t u2Temp = prChipInfo->rxd_size; + + u4HeaderOffset = (uint32_t) + (HAL_RX_STATUS_GET_HEADER_OFFSET(prRxStatus)); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_4)) + u2Temp += sizeof(struct HW_MAC_RX_STS_GROUP_4); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_1)) + u2Temp += sizeof(struct HW_MAC_RX_STS_GROUP_1); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_2)) + u2Temp += sizeof(struct HW_MAC_RX_STS_GROUP_2); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_3)) + u2Temp += sizeof(struct HW_MAC_RX_STS_GROUP_3); + pvHeader = (uint8_t *) + prRxStatus + u2Temp + u4HeaderOffset; + if (!pvHeader) { + DBGLOG(RX, ERROR, + "Mgmt Frame but pvHeader is NULL!\n"); + break; + } + prWlanMgmtHeader = + (struct WLAN_MAC_MGMT_HEADER *)pvHeader; + ucSubtype = (prWlanMgmtHeader->u2FrameCtrl & + MASK_FC_SUBTYPE) >> OFFSET_OF_FC_SUBTYPE; + DBGLOG(RX, INFO, + "MGMT frame subtype: %d SeqCtrl %d wakeup host\n", + ucSubtype, prWlanMgmtHeader->u2SeqCtrl); + } else { + DBGLOG(RX, ERROR, + "[%s]ERROR: u2PktTYpe(0x%04X) is OUT OF DEF.!!!\n", + __func__, prSwRfb->prRxStatus->u2PktTYpe); + ASSERT(0); + } + break; + default: + DBGLOG(RX, WARN, "Unknown Packet %d wakeup host\n", + prSwRfb->ucPacketType); + break; + } +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @brief nicProcessRFBs is used to process RFBs in the rReceivedRFBList queue. + * + * @param prAdapter Pointer to the Adapter structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicRxProcessRFBs(IN struct ADAPTER *prAdapter) +{ + struct RX_CTRL *prRxCtrl; + struct SW_RFB *prSwRfb = (struct SW_RFB *) NULL; + struct QUE rTempRfbList; + struct QUE *prTempRfbList = &rTempRfbList; + uint32_t u4RxLoopCount, u4Tick; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxProcessRFBs"); + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + prRxCtrl->ucNumIndPacket = 0; + prRxCtrl->ucNumRetainedPacket = 0; + u4RxLoopCount = prAdapter->rWifiVar.u4TxRxLoopCount; + u4Tick = kalGetTimeTick(); + + QUEUE_INITIALIZE(prTempRfbList); + + while (u4RxLoopCount--) { + while (QUEUE_IS_NOT_EMPTY(&prRxCtrl->rReceivedRfbList)) { + + /* check process RFB timeout */ + if ((kalGetTimeTick() - u4Tick) > RX_PROCESS_TIMEOUT) { + DBGLOG(RX, WARN, "Rx process RFBs timeout\n"); + break; + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_MOVE_ALL(prTempRfbList, + &prRxCtrl->rReceivedRfbList); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + while (QUEUE_IS_NOT_EMPTY(prTempRfbList)) { + QUEUE_REMOVE_HEAD(prTempRfbList, + prSwRfb, struct SW_RFB *); + + if (!prSwRfb) + break; +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG + if (kalIsWakeupByWlan(prAdapter)) + nicRxCheckWakeupReason(prAdapter, + prSwRfb); +#endif + + switch (prSwRfb->ucPacketType) { + case RX_PKT_TYPE_RX_DATA: + if (HAL_MON_EN(prAdapter)) { + nicRxProcessMonitorPacket( + prAdapter, prSwRfb); + break; + } + + nicRxProcessDataPacket( + prAdapter, prSwRfb); + break; + + case RX_PKT_TYPE_SW_DEFINED: + /* HIF_RX_PKT_TYPE_EVENT */ + if ((prSwRfb->prRxStatus->u2PktTYpe & + RXM_RXD_PKT_TYPE_SW_BITMAP) == + RXM_RXD_PKT_TYPE_SW_EVENT) { + nicRxProcessEventPacket( + prAdapter, + prSwRfb); + } + /* case HIF_RX_PKT_TYPE_MANAGEMENT: */ + else if ((prSwRfb->prRxStatus->u2PktTYpe + & RXM_RXD_PKT_TYPE_SW_BITMAP) == + RXM_RXD_PKT_TYPE_SW_FRAME) { + /* OFLD pkts should go data flow + * 1: EAPOL + * 2: ARP / NS + * 3: TDLS + */ + if (HAL_RX_STATUS_GET_OFLD( + prSwRfb->prRxStatus)) + nicRxProcessDataPacket( + prAdapter, prSwRfb); + else + nicRxProcessMgmtPacket( + prAdapter, prSwRfb); + } else { + DBGLOG(RX, ERROR, + "u2PktTYpe(0x%04X) is OUT OF DEF.!!!\n", + prSwRfb->prRxStatus-> + u2PktTYpe); + DBGLOG_MEM8(RX, ERROR, + prSwRfb->pucRecvBuff, + prSwRfb->prRxStatus-> + u2RxByteCount); + + /*ASSERT(0);*/ + nicRxReturnRFB(prAdapter, + prSwRfb); + RX_INC_CNT(prRxCtrl, + RX_TYPE_ERR_DROP_COUNT); + RX_INC_CNT(prRxCtrl, + RX_DROP_TOTAL_COUNT); + + } + break; + + case RX_PKT_TYPE_MSDU_REPORT: + nicRxProcessMsduReport(prAdapter, + prSwRfb); + break; + + /* case HIF_RX_PKT_TYPE_TX_LOOPBACK: */ + /* case HIF_RX_PKT_TYPE_MANAGEMENT: */ + case RX_PKT_TYPE_TX_STATUS: + case RX_PKT_TYPE_RX_VECTOR: + case RX_PKT_TYPE_TM_REPORT: + default: + nicRxReturnRFB(prAdapter, prSwRfb); + 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; + } + + } + + if (prRxCtrl->ucNumIndPacket > 0) { + RX_ADD_CNT(prRxCtrl, RX_DATA_INDICATION_COUNT, + prRxCtrl->ucNumIndPacket); + RX_ADD_CNT(prRxCtrl, RX_DATA_RETAINED_COUNT, + prRxCtrl->ucNumRetainedPacket); +#if !CFG_SUPPORT_MULTITHREAD +#if CFG_NATIVE_802_11 + kalRxIndicatePkts(prAdapter->prGlueInfo, + (uint32_t) prRxCtrl->ucNumIndPacket, + (uint32_t) + prRxCtrl->ucNumRetainedPacket); +#else + kalRxIndicatePkts(prAdapter->prGlueInfo, + prRxCtrl->apvIndPacket, + (uint32_t) prRxCtrl->ucNumIndPacket); +#endif +#endif + kalPerMonStart(prAdapter->prGlueInfo); + } + } + } +} /* end of nicRxProcessRFBs() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicRxSetupRFB(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + void *pvPacket; + uint8_t *pucRecvBuff; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + if (!prSwRfb->pvPacket) { + kalMemZero(prSwRfb, sizeof(struct SW_RFB)); + pvPacket = kalPacketAlloc(prAdapter->prGlueInfo, + CFG_RX_MAX_PKT_SIZE, &pucRecvBuff); + if (pvPacket == NULL) + return WLAN_STATUS_RESOURCES; + + prSwRfb->pvPacket = pvPacket; + prSwRfb->pucRecvBuff = (void *) pucRecvBuff; + } else { + kalMemZero(((uint8_t *) prSwRfb + OFFSET_OF(struct SW_RFB, + prRxStatus)), + (sizeof(struct SW_RFB) - OFFSET_OF(struct SW_RFB, + prRxStatus))); + } + + prSwRfb->prRxStatus = (struct HW_MAC_RX_DESC *) ( + 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 struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct RX_CTRL *prRxCtrl; + struct QUE_ENTRY *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_FREE_QUE); + + if (prSwRfb->pvPacket) { + /* QUEUE_INSERT_TAIL */ + QUEUE_INSERT_TAIL(&prRxCtrl->rFreeSwRfbList, prQueEntry); + } else { + /* QUEUE_INSERT_TAIL */ + QUEUE_INSERT_TAIL(&prRxCtrl->rIndicatedRfbList, prQueEntry); + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + /* Trigger Rx if there are free SwRfb */ + if (halIsPendingRx(prAdapter) + && (prRxCtrl->rFreeSwRfbList.u4NumElem > 0)) + kalSetIntEvent(prAdapter->prGlueInfo); +} /* 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 struct ADAPTER *prAdapter) +{ + ASSERT(prAdapter); + prAdapter->prGlueInfo->IsrRxCnt++; + + if (halIsHifStateSuspend(prAdapter)) { + DBGLOG(RX, WARN, "suspend RX INT\n"); + } + +#if CFG_SUPPORT_SER + /* SER break point */ + if (nicSerIsRxStop(prAdapter)) { + /* Skip following Rx handling */ + return; + } + +#endif /* CFG_SUPPORT_SER */ + + halProcessRxInterrupt(prAdapter); + +#if CFG_SUPPORT_MULTITHREAD + set_bit(GLUE_FLAG_RX_BIT, &(prAdapter->prGlueInfo->ulFlag)); + wake_up_interruptible(&(prAdapter->prGlueInfo->waitq)); +#else + nicRxProcessRFBs(prAdapter); +#endif + + 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 struct ADAPTER * + prAdapter, IN const enum ENUM_CSUM_RESULT aeCSUM[]) { + struct RX_CTRL *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)) { + /* count success num */ + RX_INC_CNT(prRxCtrl, RX_CSUM_IP_SUCCESS_COUNT); + } else if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_FAILED) + || (aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_FAILED)) { + RX_INC_CNT(prRxCtrl, RX_CSUM_IP_FAILED_COUNT); + } else if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_NONE) + && (aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_NONE)) { + RX_INC_CNT(prRxCtrl, RX_CSUM_UNKNOWN_L3_PKT_COUNT); + } else { + ASSERT(0); + } + + if (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_SUCCESS) { + /* count success num */ + RX_INC_CNT(prRxCtrl, RX_CSUM_TCP_SUCCESS_COUNT); + } else if (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_FAILED) { + RX_INC_CNT(prRxCtrl, RX_CSUM_TCP_FAILED_COUNT); + } else if (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_SUCCESS) { + RX_INC_CNT(prRxCtrl, RX_CSUM_UDP_SUCCESS_COUNT); + } else if (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_FAILED) { + RX_INC_CNT(prRxCtrl, RX_CSUM_UDP_FAILED_COUNT); + } else if ((aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_NONE) + && (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_NONE)) { + RX_INC_CNT(prRxCtrl, RX_CSUM_UNKNOWN_L4_PKT_COUNT); + } else { + ASSERT(0); + } + +} /* end of nicRxUpdateCSUMStatistics() */ +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is used to query current status of RX Module. + * + * @param prAdapter Pointer to the Adapter structure. + * @param pucBuffer Pointer to the message buffer. + * @param pu4Count Pointer to the buffer of message length count. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicRxQueryStatus(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuffer, OUT uint32_t *pu4Count) +{ + struct RX_CTRL *prRxCtrl; + uint8_t *pucCurrBuf = pucBuffer; + uint32_t u4CurrCount; + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + ASSERT(pu4Count); + +#define SPRINTF_RX_QSTATUS(arg) \ + { \ + u4CurrCount = \ + scnprintf(pucCurrBuf, *pu4Count, PRINTF_ARG arg); \ + pucCurrBuf += (uint8_t)u4CurrCount; \ + *pu4Count -= u4CurrCount; \ + } + + + SPRINTF_RX_QSTATUS(("\n\nRX CTRL STATUS:")); + SPRINTF_RX_QSTATUS(("\n===============")); + SPRINTF_RX_QSTATUS(("\nFREE RFB w/i BUF LIST :%9u", + prRxCtrl->rFreeSwRfbList.u4NumElem)); + SPRINTF_RX_QSTATUS(("\nFREE RFB w/o BUF LIST :%9u", + prRxCtrl->rIndicatedRfbList.u4NumElem)); + SPRINTF_RX_QSTATUS(("\nRECEIVED RFB LIST :%9u", + prRxCtrl->rReceivedRfbList.u4NumElem)); + + SPRINTF_RX_QSTATUS(("\n\n")); + + /* *pu4Count = (UINT_32)((UINT_32)pucCurrBuf - (UINT_32)pucBuffer); */ + +} /* end of nicRxQueryStatus() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Clear RX related counters + * + * @param prAdapter Pointer of Adapter Data Structure + * + * @return - (none) + */ +/*----------------------------------------------------------------------------*/ +void nicRxClearStatistics(IN struct ADAPTER *prAdapter) +{ + struct RX_CTRL *prRxCtrl; + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + RX_RESET_ALL_CNTS(prRxCtrl); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is used to query current statistics of RX Module. + * + * @param prAdapter Pointer to the Adapter structure. + * @param pucBuffer Pointer to the message buffer. + * @param pu4Count Pointer to the buffer of message length count. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicRxQueryStatistics(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuffer, OUT uint32_t *pu4Count) +{ + struct RX_CTRL *prRxCtrl; + uint8_t *pucCurrBuf = pucBuffer; + uint32_t u4CurrCount; + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + ASSERT(pu4Count); + +#define SPRINTF_RX_COUNTER(eCounter) \ + { \ + u4CurrCount = scnprintf(pucCurrBuf, *pu4Count, "%-30s : %u\n", \ + #eCounter, \ + (uint32_t)prRxCtrl->au8Statistics[eCounter]); \ + pucCurrBuf += (uint8_t)u4CurrCount; \ + *pu4Count -= u4CurrCount; \ + } + + SPRINTF_RX_COUNTER(RX_MPDU_TOTAL_COUNT); + SPRINTF_RX_COUNTER(RX_SIZE_ERR_DROP_COUNT); + SPRINTF_RX_COUNTER(RX_DATA_INDICATION_COUNT); + SPRINTF_RX_COUNTER(RX_DATA_RETURNED_COUNT); + SPRINTF_RX_COUNTER(RX_DATA_RETAINED_COUNT); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD || CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 + SPRINTF_RX_COUNTER(RX_CSUM_TCP_FAILED_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_UDP_FAILED_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_IP_FAILED_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_TCP_SUCCESS_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_UDP_SUCCESS_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_IP_SUCCESS_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_UNKNOWN_L4_PKT_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_UNKNOWN_L3_PKT_COUNT); + SPRINTF_RX_COUNTER(RX_IP_V6_PKT_CCOUNT); +#endif + + /* *pu4Count = (UINT_32)(pucCurrBuf - pucBuffer); */ + + nicRxClearStatistics(prAdapter); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Read the Response data from data port + * + * @param prAdapter pointer to the Adapter handler + * @param pucRspBuffer pointer to the Response buffer + * + * @retval WLAN_STATUS_SUCCESS: Response packet has been read + * @retval WLAN_STATUS_FAILURE: Read Response packet timeout or error occurred + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t +nicRxWaitResponse(IN struct ADAPTER *prAdapter, + IN uint8_t ucPortIdx, OUT uint8_t *pucRspBuffer, + IN uint32_t u4MaxRespBufferLen, OUT uint32_t *pu4Length) { + struct mt66xx_chip_info *prChipInfo; + struct WIFI_EVENT *prEvent; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + u4Status = halRxWaitResponse(prAdapter, ucPortIdx, + pucRspBuffer, + u4MaxRespBufferLen, pu4Length); + if (u4Status == WLAN_STATUS_SUCCESS) { + DBGLOG(RX, TRACE, + "Dump Response buffer, length = %u\n", *pu4Length); + DBGLOG_MEM8(RX, TRACE, pucRspBuffer, *pu4Length); + + prEvent = (struct WIFI_EVENT *) + (pucRspBuffer + prChipInfo->rxd_size); + + DBGLOG(INIT, TRACE, + "RX EVENT: ID[0x%02X] SEQ[%u] LEN[%u]\n", + prEvent->ucEID, prEvent->ucSeqNum, + prEvent->u2PacketLength); + } else { + prAdapter->u4HifDbgFlag |= DEG_HIF_DEFAULT_DUMP; + halPrintHifDbgInfo(prAdapter); + DBGLOG(RX, ERROR, "halRxWaitResponse fail!status %X\n", + u4Status); + } + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Set filter to enable Promiscuous Mode + * + * @param prAdapter Pointer to the Adapter structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicRxEnablePromiscuousMode(IN struct ADAPTER * + prAdapter) { + ASSERT(prAdapter); + +} /* end of nicRxEnablePromiscuousMode() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Set filter to disable Promiscuous Mode + * + * @param prAdapter Pointer to the Adapter structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicRxDisablePromiscuousMode(IN struct ADAPTER * + prAdapter) { + ASSERT(prAdapter); + +} /* end of nicRxDisablePromiscuousMode() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief this function flushes all packets queued in reordering module + * + * @param prAdapter Pointer to the Adapter structure. + * + * @retval WLAN_STATUS_SUCCESS Flushed successfully + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicRxFlush(IN struct ADAPTER *prAdapter) +{ + struct SW_RFB *prSwRfb; + + ASSERT(prAdapter); + prSwRfb = qmFlushRxQueues(prAdapter); + if (prSwRfb != NULL) { + do { + struct SW_RFB *prNextSwRfb; + + /* save next first */ + prNextSwRfb = (struct SW_RFB *) QUEUE_GET_NEXT_ENTRY(( + struct QUE_ENTRY *) prSwRfb); + + /* free */ + nicRxReturnRFB(prAdapter, prSwRfb); + + prSwRfb = prNextSwRfb; + } while (prSwRfb); + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param + * + * @retval + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicRxProcessActionFrame(IN struct ADAPTER * + prAdapter, IN struct SW_RFB *prSwRfb) { + struct WLAN_ACTION_FRAME *prActFrame; + struct BSS_INFO *prBssInfo = NULL; +#if CFG_SUPPORT_802_11W + u_int8_t fgRobustAction = FALSE; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecBssInfo; +#endif + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + DBGLOG(RSN, TRACE, "[Rx] nicRxProcessActionFrame\n"); + + if (prSwRfb->u2PacketLen < sizeof(struct WLAN_ACTION_FRAME) + - 1) + return WLAN_STATUS_INVALID_PACKET; + prActFrame = (struct WLAN_ACTION_FRAME *) prSwRfb->pvHeader; + + DBGLOG(RSN, INFO, "Action frame category=%d\n", + prActFrame->ucCategory); + +#if CFG_SUPPORT_802_11W + if ((prActFrame->ucCategory <= + CATEGORY_PROTECTED_DUAL_OF_PUBLIC_ACTION && + prActFrame->ucCategory != CATEGORY_PUBLIC_ACTION && + prActFrame->ucCategory != + CATEGORY_HT_ACTION) /* At 11W spec Code 7 is reserved */ || + (prActFrame->ucCategory == + CATEGORY_VENDOR_SPECIFIC_ACTION_PROTECTED)) { + fgRobustAction = TRUE; + } + /* DBGLOG(RSN, TRACE, ("[Rx] fgRobustAction=%d\n", fgRobustAction)); */ + + if (fgRobustAction && prSwRfb->prStaRec && + GET_BSS_INFO_BY_INDEX(prAdapter, + prSwRfb->prStaRec->ucBssIndex)->eNetworkType == + NETWORK_TYPE_AIS) { + prAisSpecBssInfo = & + (prAdapter->rWifiVar.rAisSpecificBssInfo); + + DBGLOG(RSN, INFO, + "[Rx]RobustAction %x %x %x\n", + prSwRfb->prRxStatus->u2StatusFlag, + prSwRfb->prRxStatus->ucWlanIdx, + prSwRfb->prRxStatus->ucTidSecMode); + + if (prAisSpecBssInfo->fgMgmtProtection + && (!(prActFrame->u2FrameCtrl & MASK_FC_PROTECTED_FRAME) + && (HAL_RX_STATUS_GET_SEC_MODE(prSwRfb->prRxStatus) == + CIPHER_SUITE_CCMP))) { + DBGLOG(RSN, INFO, + "[MFP] Not handle and drop un-protected robust action frame!!\n"); + return WLAN_STATUS_INVALID_PACKET; + } + } +#endif + + if (prSwRfb->prStaRec) + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prSwRfb->prStaRec->ucBssIndex); + + switch (prActFrame->ucCategory) { +#if CFG_M0VE_BA_TO_DRIVER + case CATEGORY_BLOCK_ACK_ACTION: + DBGLOG(RX, WARN, + "[Puff][%s] Rx CATEGORY_BLOCK_ACK_ACTION\n", __func__); + + if (prSwRfb->prStaRec) + mqmHandleBaActionFrame(prAdapter, prSwRfb); + + break; +#endif +#if DSCP_SUPPORT + case CATEGORY_QOS_ACTION: + DBGLOG(RX, INFO, "received dscp action frame: %d\n", + __LINE__); + handleQosMapConf(prAdapter, prSwRfb); + break; +#endif + case CATEGORY_PUBLIC_ACTION: +#if 0 /* CFG_SUPPORT_802_11W */ + /* Sigma */ +#else + if (prAdapter->prAisBssInfo && + prSwRfb->prStaRec + && prSwRfb->prStaRec->ucBssIndex == + prAdapter->prAisBssInfo->ucBssIndex) { + aisFuncValidateRxActionFrame(prAdapter, prSwRfb); + } +#endif + + if (prAdapter->prAisBssInfo + && prAdapter->prAisBssInfo->ucBssIndex == + KAL_NETWORK_TYPE_AIS_INDEX) + aisFuncValidateRxActionFrame(prAdapter, prSwRfb); +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { + rlmProcessPublicAction(prAdapter, prSwRfb); + if (prBssInfo) + p2pFuncValidateRxActionFrame(prAdapter, prSwRfb, + (prBssInfo->ucBssIndex == + prAdapter->ucP2PDevBssIdx), + (uint8_t) prBssInfo->u4PrivateData); + else + p2pFuncValidateRxActionFrame(prAdapter, + prSwRfb, TRUE, 0); + } +#endif + break; + + case CATEGORY_HT_ACTION: + rlmProcessHtAction(prAdapter, prSwRfb); + break; + case CATEGORY_VENDOR_SPECIFIC_ACTION: +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { + if (prBssInfo) + p2pFuncValidateRxActionFrame(prAdapter, prSwRfb, + (prBssInfo->ucBssIndex == + prAdapter->ucP2PDevBssIdx), + (uint8_t) prBssInfo->u4PrivateData); + else + p2pFuncValidateRxActionFrame(prAdapter, + prSwRfb, TRUE, 0); + } +#endif +#if CFG_SUPPORT_NCHO + { + struct BSS_INFO *prBssInfo; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prSwRfb->prStaRec->ucBssIndex); + if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) { + if (prAdapter->rNchoInfo.fgECHOEnabled == TRUE + && prAdapter->rNchoInfo.u4WesMode == TRUE) { + aisFuncValidateRxActionFrame(prAdapter, + prSwRfb); + DBGLOG(INIT, INFO, + "NCHO CATEGORY_VENDOR_SPECIFIC_ACTION\n"); + } + } + } +#endif + break; +#if CFG_SUPPORT_802_11W + case CATEGORY_SA_QUERY_ACTION: { + struct BSS_INFO *prBssInfo; + + if (prSwRfb->prStaRec) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prSwRfb->prStaRec->ucBssIndex); + ASSERT(prBssInfo); + if ((prBssInfo->eNetworkType == NETWORK_TYPE_AIS) && + prAdapter->rWifiVar.rAisSpecificBssInfo. + fgMgmtProtection /* Use MFP */) { + /* MFP test plan 5.3.3.4 */ + rsnSaQueryAction(prAdapter, prSwRfb); + } else if ((prBssInfo->eNetworkType == + NETWORK_TYPE_P2P) && + (prBssInfo->eCurrentOPMode == + OP_MODE_ACCESS_POINT)) { + /* AP PMF */ + DBGLOG(RSN, INFO, + "[Rx] nicRx AP PMF SAQ action\n"); + if (rsnCheckBipKeyInstalled(prAdapter, + prSwRfb->prStaRec)) { + /* MFP test plan 4.3.3.4 */ + rsnApSaQueryAction(prAdapter, prSwRfb); + } + } + } + } + break; +#endif + case CATEGORY_WNM_ACTION: { + if (prSwRfb->prStaRec && + GET_BSS_INFO_BY_INDEX(prAdapter, + prSwRfb->prStaRec->ucBssIndex) + ->eNetworkType == NETWORK_TYPE_AIS) { + DBGLOG(RX, INFO, "WNM action frame: %d\n", __LINE__); + wnmWNMAction(prAdapter, prSwRfb); + } else + DBGLOG(RX, INFO, "WNM action frame: %d\n", __LINE__); + } + break; + +#if CFG_SUPPORT_DFS + case CATEGORY_SPEC_MGT: { + if (prAdapter->fgEnable5GBand) { + DBGLOG(RLM, INFO, + "[Channel Switch]nicRxProcessActionFrame\n"); + rlmProcessSpecMgtAction(prAdapter, prSwRfb); + } + } + break; +#endif + +#if CFG_SUPPORT_802_11AC + case CATEGORY_VHT_ACTION: + rlmProcessVhtAction(prAdapter, prSwRfb); + break; +#endif + +#if CFG_SUPPORT_802_11K + case CATEGORY_RM_ACTION: + switch (prActFrame->ucAction) { + case RM_ACTION_RM_REQUEST: + rlmProcessRadioMeasurementRequest(prAdapter, prSwRfb); + break; + case RM_ACTION_REIGHBOR_RESPONSE: + rlmProcessNeighborReportResonse(prAdapter, prActFrame, + prSwRfb->u2PacketLen); + break; + } + break; +#endif + case CATEGORY_WME_MGT_NOTIFICATION: + wmmParseQosAction(prAdapter, prSwRfb); + break; + default: + break; + } /* end of switch case */ + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param + * + * @retval + */ +/*----------------------------------------------------------------------------*/ +uint8_t +nicRxGetRcpiValueFromRxv(IN uint8_t ucRcpiMode, + IN struct SW_RFB *prSwRfb) { + uint8_t ucRcpi0, ucRcpi1; + uint8_t ucRcpiValue = 0; + uint8_t ucRxNum; + + ASSERT(prSwRfb); + + if (ucRcpiMode >= RCPI_MODE_NUM) { + DBGLOG(RX, WARN, + "Rcpi Mode = %d is invalid for getting uint8_t value from RXV\n", + ucRcpiMode); + return 0; + } +#if CFG_RCPI_COMPENSATION + wlanUpdateRxFELoss(prSwRfb); +#endif + + ucRcpi0 = HAL_RX_STATUS_GET_RCPI0( + prSwRfb->prRxStatusGroup3); + ucRcpi1 = HAL_RX_STATUS_GET_RCPI1( + prSwRfb->prRxStatusGroup3); + ucRxNum = HAL_RX_STATUS_GET_RX_NUM( + prSwRfb->prRxStatusGroup3); + + if (ucRxNum == 0) + ucRcpiValue = (ucRcpi0 >= RCPI_MEASUREMENT_NOT_AVAILABLE) ? + (ucRcpi1):(ucRcpi0); + + else if (ucRxNum == 1) { + switch (ucRcpiMode) { + case RCPI_MODE_WF0: + ucRcpiValue = ucRcpi0; + break; + + case RCPI_MODE_WF1: + ucRcpiValue = ucRcpi1; + break; + + case RCPI_MODE_WF2: + case RCPI_MODE_WF3: + DBGLOG(RX, WARN, + "Rcpi Mode = %d is invalid for device with only 2 antenna, use default rcpi0\n", + ucRcpiMode); + ucRcpiValue = ucRcpi0; + break; + + case RCPI_MODE_AVG: /*Not recommended for CBW80+80*/ + ucRcpiValue = (ucRcpi0 + ucRcpi1) / 2; + break; + + case RCPI_MODE_MAX: + ucRcpiValue = + (ucRcpi0 > ucRcpi1) ? (ucRcpi0) : (ucRcpi1); + break; + + case RCPI_MODE_MIN: + ucRcpiValue = + (ucRcpi0 < ucRcpi1) ? (ucRcpi0) : (ucRcpi1); + break; + + default: + break; + } + } else { + DBGLOG(RX, WARN, + "RX_NUM = %d is invalid for getting uint8_t value from RXV\n", + ucRxNum); + return 0; + } + + return ucRcpiValue; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic_tx.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic_tx.c new file mode 100644 index 0000000000000..ca849b31f8b9a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic_tx.c @@ -0,0 +1,5369 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_tx.c#2 + */ + +/*! \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. + */ + + +/******************************************************************************* + * C O M P I L E 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 "que_mgt.h" + +#ifdef UDP_SKT_WIFI +#if (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) +#include +#else +#include +#endif +#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 + ******************************************************************************* + */ + +PFN_TX_DATA_DONE_CB g_pfTxDataDoneCb = nicTxMsduDoneCb; + +static const struct TX_RESOURCE_CONTROL + arTcResourceControl[TC_NUM] = { + /* dest port index, dest queue index, HIF TX queue index */ + /* First HW queue */ + {PORT_INDEX_LMAC, MAC_TXQ_AC0_INDEX, HIF_TX_AC0_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC1_INDEX, HIF_TX_AC1_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC2_INDEX, HIF_TX_AC2_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC3_INDEX, HIF_TX_AC3_INDEX}, + {PORT_INDEX_MCU, MCU_Q1_INDEX, HIF_TX_CPU_INDEX}, + + /* Second HW queue */ +#if NIC_TX_ENABLE_SECOND_HW_QUEUE + {PORT_INDEX_LMAC, MAC_TXQ_AC10_INDEX, HIF_TX_AC10_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC11_INDEX, HIF_TX_AC11_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC12_INDEX, HIF_TX_AC12_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC13_INDEX, HIF_TX_AC13_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC11_INDEX, HIF_TX_AC11_INDEX}, +#endif +}; + +/* Traffic settings per TC */ +static const struct TX_TC_TRAFFIC_SETTING + arTcTrafficSettings[NET_TC_NUM] = { + /* Tx desc template format, Remaining Tx time, + * Retry count + */ + /* For Data frame with StaRec, + * set Long Format to enable the following settings + */ + { + NIC_TX_DESC_LONG_FORMAT_LENGTH, NIC_TX_AC_BE_REMAINING_TX_TIME, + NIC_TX_DATA_DEFAULT_RETRY_COUNT_LIMIT + }, + { + NIC_TX_DESC_LONG_FORMAT_LENGTH, NIC_TX_AC_BK_REMAINING_TX_TIME, + NIC_TX_DATA_DEFAULT_RETRY_COUNT_LIMIT + }, + { + NIC_TX_DESC_LONG_FORMAT_LENGTH, NIC_TX_AC_VI_REMAINING_TX_TIME, + NIC_TX_DATA_DEFAULT_RETRY_COUNT_LIMIT + }, + { + NIC_TX_DESC_LONG_FORMAT_LENGTH, NIC_TX_AC_VO_REMAINING_TX_TIME, + NIC_TX_DATA_DEFAULT_RETRY_COUNT_LIMIT + }, + + /* MGMT frame */ + { + NIC_TX_DESC_LONG_FORMAT_LENGTH, NIC_TX_MGMT_REMAINING_TX_TIME, + NIC_TX_MGMT_DEFAULT_RETRY_COUNT_LIMIT + }, + + /* non-StaRec frame (BMC, etc...) */ + { + NIC_TX_DESC_LONG_FORMAT_LENGTH, TX_DESC_TX_TIME_NO_LIMIT, + NIC_TX_DATA_DEFAULT_RETRY_COUNT_LIMIT + }, +}; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +static uint8_t *apucTxResultStr[TX_RESULT_NUM] = { + (uint8_t *) DISP_STRING("SUCCESS"), /* success */ + (uint8_t *) DISP_STRING("LIFE_TO"), /* life timeout */ + (uint8_t *) DISP_STRING("RTS_ER"), /* RTS error */ + (uint8_t *) DISP_STRING("MPDU_ER"), /* MPDU error */ + (uint8_t *) DISP_STRING("AGE_TO"), /* aging timeout */ + (uint8_t *) DISP_STRING("FLUSHED"), /* flushed */ + (uint8_t *) DISP_STRING("BIP_ER"), /* BIP error */ + (uint8_t *) DISP_STRING("UNSPEC_ER"), /* unspecified error */ + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) NULL, + (uint8_t *) DISP_STRING("DP_IN_DRV"), /* drop in driver */ + (uint8_t *) DISP_STRING("DP_IN_FW"), /* drop in FW */ + (uint8_t *) DISP_STRING("QUE_CLR"), /* queue clearance */ + (uint8_t *) DISP_STRING("INACT_BSS") /* inactive BSS */ +}; + +/******************************************************************************* + * M A 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 struct ADAPTER *prAdapter) +{ + struct TX_CTRL *prTxCtrl; + uint8_t *pucMemHandle; + struct MSDU_INFO *prMsduInfo; + uint32_t i; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicTxInitialize"); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + /* 4 <1> Initialization of Traffic Class Queue Parameters */ + nicTxResetResource(prAdapter); + + prTxCtrl->pucTxCoalescingBufPtr = + prAdapter->pucCoalescingBufCached; + + prTxCtrl->u4WrIdx = 0; + + /* 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 = (struct MSDU_INFO *) pucMemHandle; + kalMemZero(prMsduInfo, sizeof(struct MSDU_INFO)); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TX_MSDU_INFO_LIST); + QUEUE_INSERT_TAIL(&prTxCtrl->rFreeMsduInfoList, + (struct QUE_ENTRY *) prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TX_MSDU_INFO_LIST); + + pucMemHandle += ALIGN_4(sizeof(struct MSDU_INFO)); + } + + ASSERT(prTxCtrl->rFreeMsduInfoList.u4NumElem == + CFG_TX_MAX_PKT_NUM); + /* Check if the memory allocation consist + * with this initialization function + */ + ASSERT((uint32_t) (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; + + /* Assign init value */ + /* Tx sequence number */ + prAdapter->ucTxSeqNum = 0; + /* PID pool */ + for (i = 0; i < WTBL_SIZE; i++) + prAdapter->aucPidPool[i] = NIC_TX_DESC_DRIVER_PID_MIN; + + /* enable/disable TX resource control */ + prTxCtrl->fgIsTxResourceCtrl = NIC_TX_RESOURCE_CTRL; + + qmInit(prAdapter, halIsTxResourceControlEn(prAdapter)); + + TX_RESET_ALL_CNTS(prTxCtrl); + +} /* end of nicTxInitialize() */ + +u_int8_t nicTxSanityCheckResource(IN struct ADAPTER + *prAdapter) +{ + struct TX_CTRL *prTxCtrl; + uint8_t ucTC; + uint32_t ucTotalMaxResource = 0; + uint32_t ucTotalFreeResource = 0; + u_int8_t fgError = FALSE; + + if (prAdapter->rWifiVar.ucTxDbg & BIT(0)) { + prTxCtrl = &prAdapter->rTxCtrl; + + for (ucTC = TC0_INDEX; ucTC < TC_NUM; ucTC++) { + ucTotalMaxResource += + prTxCtrl->rTc.au4MaxNumOfPage[ucTC]; + ucTotalFreeResource += + prTxCtrl->rTc.au4FreePageCount[ucTC]; + + if (prTxCtrl->rTc.au4FreePageCount[ucTC] > + prTxCtrl->u4TotalPageNum) { + DBGLOG(TX, ERROR, + "%s:%u\n error\n", __func__, __LINE__); + fgError = TRUE; + } + + if (prTxCtrl->rTc.au4MaxNumOfPage[ucTC] > + prTxCtrl->u4TotalPageNum) { + DBGLOG(TX, ERROR, + "%s:%u\n error\n", __func__, __LINE__); + fgError = TRUE; + } + + if (prTxCtrl->rTc.au4FreePageCount[ucTC] > + prTxCtrl->rTc.au4MaxNumOfPage[ucTC]) { + DBGLOG(TX, ERROR, + "%s:%u\n error\n", __func__, __LINE__); + fgError = TRUE; + } + } + + if (ucTotalMaxResource != prTxCtrl->u4TotalPageNum) { + DBGLOG(TX, ERROR, + "%s:%u\n error\n", __func__, __LINE__); + fgError = TRUE; + } + + if (ucTotalMaxResource < ucTotalFreeResource) { + DBGLOG(TX, ERROR, + "%s:%u\n error\n", __func__, __LINE__); + fgError = TRUE; + } + + if (ucTotalFreeResource > prTxCtrl->u4TotalPageNum) { + DBGLOG(TX, ERROR, + "%s:%u\n error\n", __func__, __LINE__); + fgError = TRUE; + } + + if (fgError) { + DBGLOG(TX, ERROR, "Total resource[%u]\n", + prTxCtrl->u4TotalPageNum); + qmDumpQueueStatus(prAdapter, NULL, 0); + } + } + + return !fgError; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Condition check if the PLE resource control is needed or not + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] ucTC Specify the resource of TC + * + * \retval FALSE Resource control is not needed. + * \retval TRUE Resource is not needed. + */ +/*----------------------------------------------------------------------------*/ + +u_int8_t nicTxResourceIsPleCtrlNeeded(IN struct ADAPTER + *prAdapter, IN uint8_t ucTC) +{ + struct TX_CTRL *prTxCtrl; + struct TX_TCQ_STATUS *prTc; + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + prTc = &prTxCtrl->rTc; + + /* no PLE resource control */ + if (!prTc->fgNeedPleCtrl) + return FALSE; + + /* CMD doesn't have PLE */ + if (ucTC == 4) + return FALSE; + + /* rom stage inbabd command use TC0. need refine a good method */ + if ((ucTC == 0) && (prAdapter->fgIsFwDownloaded == FALSE)) + return FALSE; + + return TRUE; +} + + +uint32_t nicTxResourceGetPleFreeCount(IN struct ADAPTER + *prAdapter, IN uint8_t ucTC) +{ + struct TX_CTRL *prTxCtrl; + struct TX_TCQ_STATUS *prTc; + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + prTc = &prTxCtrl->rTc; + + if (!nicTxResourceIsPleCtrlNeeded(prAdapter, ucTC)) { + /* unlimited value*/ + return 0xFFFFFFFF; + } + + return prTc->au4FreePageCount_PLE[ucTC]; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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. + */ +/*----------------------------------------------------------------------------*/ + +uint32_t nicTxAcquireResourcePLE(IN struct ADAPTER + *prAdapter, IN uint8_t ucTC) +{ + struct TX_CTRL *prTxCtrl; + struct TX_TCQ_STATUS *prTc; + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + prTc = &prTxCtrl->rTc; + + if (!nicTxResourceIsPleCtrlNeeded(prAdapter, ucTC)) + return WLAN_STATUS_SUCCESS; + + DBGLOG(INIT, TRACE, + "Acquire PLE: TC%d AcquirePageCnt[%u] FreeBufferCnt[%u] FreePageCnt[%u]\n", + ucTC, NIX_TX_PLE_PAGE_CNT_PER_FRAME, + prTc->au4FreeBufferCount_PLE[ucTC], + prTc->au4FreePageCount_PLE[ucTC]); + + + /* PLE Acquire */ + if (prTc->au4FreePageCount_PLE[ucTC] >= + NIX_TX_PLE_PAGE_CNT_PER_FRAME) { + prTc->au4FreePageCount_PLE[ucTC] -= + NIX_TX_PLE_PAGE_CNT_PER_FRAME; + + return WLAN_STATUS_SUCCESS; + } + + DBGLOG(INIT, ERROR, + "Acquire PLE FAILURE. TC%d AcquirePageCnt[%u] FreeBufferCnt[%u] FreePageCnt[%u]\n", + ucTC, NIX_TX_PLE_PAGE_CNT_PER_FRAME, + prTc->au4FreeBufferCount_PLE[ucTC], + prTc->au4FreePageCount_PLE[ucTC]); + + + return WLAN_STATUS_RESOURCES; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t u4CurrTick; +uint32_t nicTxAcquireResource(IN struct ADAPTER *prAdapter, + IN uint8_t ucTC, IN uint32_t u4PageCount, + IN u_int8_t fgReqLock) +{ +#define TC4_NO_RESOURCE_DELAY_MS 5 /* exponential of 5s */ + + struct TX_CTRL *prTxCtrl; + struct TX_TCQ_STATUS *prTc; + uint32_t u4Status = WLAN_STATUS_RESOURCES; + uint32_t u4MaxPageCntPerFrame = + prAdapter->rTxCtrl.u4MaxPageCntPerFrame; + struct QUE_MGT *prQM; + + KAL_SPIN_LOCK_DECLARATION(); + + /* enable/disable TX resource control */ + if (!prAdapter->rTxCtrl.fgIsTxResourceCtrl) + return WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + prTc = &prTxCtrl->rTc; + + if (fgReqLock) + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); +#if 1 + prQM = &prAdapter->rQM; + if (prTc->au4FreePageCount[ucTC] >= u4PageCount) { + + if (nicTxAcquireResourcePLE(prAdapter, + ucTC) != WLAN_STATUS_SUCCESS) { + if (fgReqLock) + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TX_RESOURCE); + + return WLAN_STATUS_RESOURCES; + } + + /* This update must be AFTER the PLE-resource-check */ + if (ucTC == TC4_INDEX) + u4CurrTick = 0; + prTc->au4FreePageCount[ucTC] -= u4PageCount; + prTc->au4FreeBufferCount[ucTC] = + (prTc->au4FreePageCount[ucTC] / u4MaxPageCntPerFrame); + prQM->au4QmTcUsedPageCounter[ucTC] += u4PageCount; + + DBGLOG(TX, TEMP, + "Acquire: TC%d AcquirePageCnt[%u] FreeBufferCnt[%u] FreePageCnt[%u]\n", + ucTC, u4PageCount, prTc->au4FreeBufferCount[ucTC], + prTc->au4FreePageCount[ucTC]); + + u4Status = WLAN_STATUS_SUCCESS; + } +#else + if (prTxCtrl->rTc.au4FreePageCount[ucTC] > 0) { + + prTxCtrl->rTc.au4FreePageCount[ucTC] -= 1; + + u4Status = WLAN_STATUS_SUCCESS; + } +#endif + if (fgReqLock) + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + if (ucTC == TC4_INDEX) { + if (u4CurrTick == 0) + u4CurrTick = kalGetTimeTick(); + if (CHECK_FOR_TIMEOUT(kalGetTimeTick(), u4CurrTick, + SEC_TO_SYSTIME(TC4_NO_RESOURCE_DELAY_MS))) { +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanDumpTcResAndTxedCmd(NULL, 0); +#endif + cmdBufDumpCmdQueue(&prAdapter->rPendingCmdQueue, + "waiting response CMD queue"); + } + } + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxPollingResource(IN struct ADAPTER *prAdapter, + IN uint8_t ucTC) +{ + struct TX_CTRL *prTxCtrl; + uint32_t u4Status = WLAN_STATUS_FAILURE; + int32_t i = NIC_TX_RESOURCE_POLLING_TIMEOUT; + /*UINT_32 au4WTSR[8];*/ + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + if (ucTC >= TC_NUM) + return WLAN_STATUS_FAILURE; + + if (prTxCtrl->rTc.au4FreeBufferCount[ucTC] > 0) + return WLAN_STATUS_SUCCESS; + + while (i-- > 0) { +#if 1 + u4Status = halTxPollingResource(prAdapter, ucTC); + if (u4Status == WLAN_STATUS_RESOURCES) + kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC); + else + break; +#else + HAL_READ_TX_RELEASED_COUNT(prAdapter, au4WTSR); + + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + break; + } else if (halTxReleaseResource(prAdapter, + (uint16_t *) au4WTSR)) { + if (prTxCtrl->rTc.au4FreeBufferCount[ucTC] > 0) { + u4Status = WLAN_STATUS_SUCCESS; + break; + } + kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC); + } else { + kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC); + } +#endif + } + +#if DBG + { + int32_t i4Times = NIC_TX_RESOURCE_POLLING_TIMEOUT - (i + 1); + + if (i4Times) { + DBGLOG(TX, TRACE, + "Polling MCR_WTSR delay %ld times, %ld 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. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +u_int8_t nicTxReleaseResource(IN struct ADAPTER *prAdapter, + IN uint8_t ucTc, IN uint32_t u4PageCount, + IN u_int8_t fgReqLock, IN u_int8_t fgPLE) +{ + struct TX_TCQ_STATUS *prTcqStatus; + u_int8_t bStatus = FALSE; + uint32_t u4MaxPageCntPerFrame = + prAdapter->rTxCtrl.u4MaxPageCntPerFrame; + struct QUE_MGT *prQM = NULL; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + /* enable/disable TX resource control */ + if (!prAdapter->rTxCtrl.fgIsTxResourceCtrl) + return TRUE; + + /* No need to do PLE resource control */ + if (fgPLE && !nicTxResourceIsPleCtrlNeeded(prAdapter, ucTc)) + return TRUE; + + prTcqStatus = &prAdapter->rTxCtrl.rTc; + prQM = &prAdapter->rQM; + + /* Return free Tc page count */ + if (fgReqLock) + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + if (fgPLE) { + prTcqStatus->au4FreePageCount_PLE[ucTc] += u4PageCount; + prTcqStatus->au4FreeBufferCount_PLE[ucTc] = + (prTcqStatus->au4FreePageCount_PLE[ucTc] / + NIX_TX_PLE_PAGE_CNT_PER_FRAME); + } else { + prTcqStatus->au4FreePageCount[ucTc] += u4PageCount; + prTcqStatus->au4FreeBufferCount[ucTc] = + (prTcqStatus->au4FreePageCount[ucTc] / + u4MaxPageCntPerFrame); + } + prQM->au4QmTcResourceBackCounter[ucTc] += u4PageCount; + + if (fgReqLock) + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + +#if (CFG_SUPPORT_TRACE_TC4 == 1) + if (ucTc == TC4_INDEX) + wlanTraceReleaseTcRes(prAdapter, u4PageCount, + prTcqStatus->au4FreePageCount[ucTc]); +#endif + bStatus = TRUE; + + return bStatus; +} /* end of nicTxReleaseResource() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Driver maintain a variable that is synchronous with the usage of + * individual TC Buffer Count. This function will release TC Buffer + * count for resource allocated but un-Tx MSDU_INFO + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicTxReleaseMsduResource(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfoListHead) +{ + struct MSDU_INFO *prMsduInfo = prMsduInfoListHead, + *prNextMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + while (prMsduInfo) { + prNextMsduInfo = (struct MSDU_INFO *) QUEUE_GET_NEXT_ENTRY(( + struct QUE_ENTRY *) prMsduInfo); + + nicTxReleaseResource_PSE(prAdapter, prMsduInfo->ucTC, + nicTxGetPageCount( + prAdapter, prMsduInfo->u2FrameLength, + FALSE), FALSE); + + nicTxReleaseResource_PLE(prAdapter, prMsduInfo->ucTC, + NIX_TX_PLE_PAGE_CNT_PER_FRAME, FALSE); + + prMsduInfo = prNextMsduInfo; + }; + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Reset TC Buffer Count to initialized value + * + * \param[in] prAdapter Pointer to the Adapter structure. + * + * @return WLAN_STATUS_SUCCESS + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxResetResource(IN struct ADAPTER *prAdapter) +{ + struct TX_CTRL *prTxCtrl; + uint8_t ucIdx; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicTxResetResource"); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + /* Following two lines MUST be in order. */ + prTxCtrl->u4PageSize = halGetHifTxPageSize(prAdapter); + prTxCtrl->u4MaxPageCntPerFrame = nicTxGetMaxPageCntPerFrame( + prAdapter); + + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + /* Delta page count */ + kalMemZero(prTxCtrl->rTc.au4TxDonePageCount, + sizeof(prTxCtrl->rTc.au4TxDonePageCount)); + kalMemZero(prTxCtrl->rTc.au4PreUsedPageCount, + sizeof(prTxCtrl->rTc.au4PreUsedPageCount)); + + prTxCtrl->rTc.ucNextTcIdx = TC0_INDEX; + prTxCtrl->rTc.u4AvaliablePageCount = 0; + + DBGLOG(TX, TRACE, + "Default TCQ free resource [%u %u %u %u %u]\n", + prAdapter->rWifiVar.au4TcPageCount[TC0_INDEX], + prAdapter->rWifiVar.au4TcPageCount[TC1_INDEX], + prAdapter->rWifiVar.au4TcPageCount[TC2_INDEX], + prAdapter->rWifiVar.au4TcPageCount[TC3_INDEX], + prAdapter->rWifiVar.au4TcPageCount[TC4_INDEX]); + + /* Reset counter: PSE */ + prAdapter->rTxCtrl.u4TotalPageNum = 0; + prAdapter->rTxCtrl.u4TotalTxRsvPageNum = 0; + /* Reset counter: PLE */ + prAdapter->rTxCtrl.u4TotalPageNumPle = 0; + + /* Assign resource for each TC according to prAdapter->rWifiVar */ + for (ucIdx = TC0_INDEX; ucIdx < TC_NUM; ucIdx++) { + + /* + * PSE + */ + + /* Page Count */ + prTxCtrl->rTc.au4MaxNumOfPage[ucIdx] = + prAdapter->rWifiVar.au4TcPageCount[ucIdx]; + prTxCtrl->rTc.au4FreePageCount[ucIdx] = + prAdapter->rWifiVar.au4TcPageCount[ucIdx]; + + DBGLOG(TX, TRACE, "Set TC%u Default[%u] Max[%u] Free[%u]\n", + ucIdx, + prAdapter->rWifiVar.au4TcPageCount[ucIdx], + prTxCtrl->rTc.au4MaxNumOfPage[ucIdx], + prTxCtrl->rTc.au4FreePageCount[ucIdx]); + + /* Buffer count */ + prTxCtrl->rTc.au4MaxNumOfBuffer[ucIdx] = + (prTxCtrl->rTc.au4MaxNumOfPage[ucIdx] / + (prTxCtrl->u4MaxPageCntPerFrame)); + + prTxCtrl->rTc.au4FreeBufferCount[ucIdx] = + (prTxCtrl->rTc.au4FreePageCount[ucIdx] / + (prTxCtrl->u4MaxPageCntPerFrame)); + + + DBGLOG(TX, TRACE, + "Set TC%u Default[%u] Buffer Max[%u] Free[%u]\n", + ucIdx, + prAdapter->rWifiVar.au4TcPageCount[ucIdx], + prTxCtrl->rTc.au4MaxNumOfBuffer[ucIdx], + prTxCtrl->rTc.au4FreeBufferCount[ucIdx]); + + prAdapter->rTxCtrl.u4TotalPageNum += + prTxCtrl->rTc.au4MaxNumOfPage[ucIdx]; + + + /* + * PLE + */ + if (prAdapter->rTxCtrl.rTc.fgNeedPleCtrl) { + /* Page Count */ + prTxCtrl->rTc.au4MaxNumOfPage_PLE[ucIdx] = + prAdapter->rWifiVar.au4TcPageCountPle[ucIdx]; + prTxCtrl->rTc.au4FreePageCount_PLE[ucIdx] = + prAdapter->rWifiVar.au4TcPageCountPle[ucIdx]; + + DBGLOG(TX, TRACE, + "[PLE]Set TC%u Default[%u] Max[%u] Free[%u]\n", + ucIdx, + prAdapter->rWifiVar.au4TcPageCountPle[ucIdx], + prTxCtrl->rTc.au4MaxNumOfPage_PLE[ucIdx], + prTxCtrl->rTc.au4FreePageCount_PLE[ucIdx]); + + /* Buffer count */ + prTxCtrl->rTc.au4MaxNumOfBuffer_PLE[ucIdx] = + (prTxCtrl->rTc.au4MaxNumOfPage_PLE[ucIdx] / + NIX_TX_PLE_PAGE_CNT_PER_FRAME); + + prTxCtrl->rTc.au4FreeBufferCount_PLE[ucIdx] = + (prTxCtrl->rTc.au4FreePageCount_PLE[ucIdx] / + NIX_TX_PLE_PAGE_CNT_PER_FRAME); + + + DBGLOG(TX, TRACE, + "[PLE]Set TC%u Default[%u] Buffer Max[%u] Free[%u]\n", + ucIdx, + prAdapter->rWifiVar.au4TcPageCountPle[ucIdx], + prTxCtrl->rTc.au4MaxNumOfBuffer_PLE[ucIdx], + prTxCtrl->rTc.au4FreeBufferCount_PLE[ucIdx]); + + prAdapter->rTxCtrl.u4TotalPageNumPle += + prTxCtrl->rTc.au4MaxNumOfPage_PLE[ucIdx]; + } + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + if (!prAdapter->fgIsNicTxReousrceValid)/* use default value */ + prAdapter->nicTxReousrce.ucPpTxAddCnt = + NIC_TX_LEN_ADDING_LENGTH; + DBGLOG(TX, TRACE, + "Reset TCQ free resource to Page <>:Buf [%u:%u %u:%u %u:%u %u:%u %u:%u]\n", + prTxCtrl->rTc.au4FreePageCount[TC0_INDEX], + prTxCtrl->rTc.au4FreeBufferCount[TC0_INDEX], + prTxCtrl->rTc.au4FreePageCount[TC1_INDEX], + prTxCtrl->rTc.au4FreeBufferCount[TC1_INDEX], + prTxCtrl->rTc.au4FreePageCount[TC2_INDEX], + prTxCtrl->rTc.au4FreeBufferCount[TC2_INDEX], + prTxCtrl->rTc.au4FreePageCount[TC3_INDEX], + prTxCtrl->rTc.au4FreeBufferCount[TC3_INDEX], + prTxCtrl->rTc.au4FreePageCount[TC4_INDEX], + prTxCtrl->rTc.au4FreeBufferCount[TC4_INDEX]); + + if (prAdapter->rTxCtrl.rTc.fgNeedPleCtrl) + DBGLOG(TX, TRACE, + "Reset TCQ free resource to Page <>:Buf [%u:%u %u:%u %u:%u %u:%u %u:%u]\n", + prTxCtrl->rTc.au4FreePageCount_PLE[TC0_INDEX], + prTxCtrl->rTc.au4FreeBufferCount_PLE[TC0_INDEX], + prTxCtrl->rTc.au4FreePageCount_PLE[TC1_INDEX], + prTxCtrl->rTc.au4FreeBufferCount_PLE[TC1_INDEX], + prTxCtrl->rTc.au4FreePageCount_PLE[TC2_INDEX], + prTxCtrl->rTc.au4FreeBufferCount_PLE[TC2_INDEX], + prTxCtrl->rTc.au4FreePageCount_PLE[TC3_INDEX], + prTxCtrl->rTc.au4FreeBufferCount_PLE[TC3_INDEX], + prTxCtrl->rTc.au4FreePageCount_PLE[TC4_INDEX], + prTxCtrl->rTc.au4FreeBufferCount_PLE[TC4_INDEX]); + + + DBGLOG(TX, TRACE, + "Reset TCQ MAX resource to Page <>:Buf [%u:%u %u:%u %u:%u %u:%u %u:%u]\n", + prTxCtrl->rTc.au4MaxNumOfPage[TC0_INDEX], + prTxCtrl->rTc.au4MaxNumOfBuffer[TC0_INDEX], + prTxCtrl->rTc.au4MaxNumOfPage[TC1_INDEX], + prTxCtrl->rTc.au4MaxNumOfBuffer[TC1_INDEX], + prTxCtrl->rTc.au4MaxNumOfPage[TC2_INDEX], + prTxCtrl->rTc.au4MaxNumOfBuffer[TC2_INDEX], + prTxCtrl->rTc.au4MaxNumOfPage[TC3_INDEX], + prTxCtrl->rTc.au4MaxNumOfBuffer[TC3_INDEX], + prTxCtrl->rTc.au4MaxNumOfPage[TC4_INDEX], + prTxCtrl->rTc.au4MaxNumOfBuffer[TC4_INDEX]); + + if (prAdapter->rTxCtrl.rTc.fgNeedPleCtrl) + DBGLOG(TX, TRACE, + "Reset TCQ MAX resource to Page <>:Buf [%u:%u %u:%u %u:%u %u:%u %u:%u]\n", + prTxCtrl->rTc.au4MaxNumOfPage_PLE[TC0_INDEX], + prTxCtrl->rTc.au4MaxNumOfBuffer_PLE[TC0_INDEX], + prTxCtrl->rTc.au4MaxNumOfPage_PLE[TC1_INDEX], + prTxCtrl->rTc.au4MaxNumOfBuffer_PLE[TC1_INDEX], + prTxCtrl->rTc.au4MaxNumOfPage_PLE[TC2_INDEX], + prTxCtrl->rTc.au4MaxNumOfBuffer_PLE[TC2_INDEX], + prTxCtrl->rTc.au4MaxNumOfPage_PLE[TC3_INDEX], + prTxCtrl->rTc.au4MaxNumOfBuffer_PLE[TC3_INDEX], + prTxCtrl->rTc.au4MaxNumOfPage_PLE[TC4_INDEX], + prTxCtrl->rTc.au4MaxNumOfBuffer_PLE[TC4_INDEX]); + + return WLAN_STATUS_SUCCESS; +} + +#if QM_FAST_TC_RESOURCE_CTRL +uint32_t +nicTxGetAdjustableResourceCnt(IN struct ADAPTER *prAdapter) +{ + struct TX_CTRL *prTxCtrl; + uint8_t ucIdx; + uint32_t u4TotAdjCnt = 0; + uint32_t u4AdjCnt; + struct QUE_MGT *prQM = NULL; + + prQM = &prAdapter->rQM; + prTxCtrl = &prAdapter->rTxCtrl; + + for (ucIdx = TC0_INDEX; ucIdx < TC_NUM; ucIdx++) { + if (ucIdx == TC4_INDEX) + continue; + + if (prTxCtrl->rTc.au4FreeBufferCount[ucIdx] > + prQM->au4MinReservedTcResource[ucIdx]) + u4AdjCnt = prTxCtrl->rTc.au4FreeBufferCount[ucIdx] - + prQM->au4MinReservedTcResource[ucIdx]; + else + u4AdjCnt = 0; + + u4TotAdjCnt += u4AdjCnt; + } + + /* no PLE resource control */ + if (!prAdapter->rTxCtrl.rTc.fgNeedPleCtrl) + return u4TotAdjCnt; + + /* PLE part */ + for (ucIdx = TC0_INDEX; ucIdx < TC_NUM; ucIdx++) { + if (ucIdx == TC4_INDEX) + continue; + + if (prTxCtrl->rTc.au4FreeBufferCount_PLE[ucIdx] > + prQM->au4MinReservedTcResource[ucIdx]) + u4AdjCnt = prTxCtrl->rTc.au4FreeBufferCount_PLE[ucIdx] - + prQM->au4MinReservedTcResource[ucIdx]; + else + u4AdjCnt = 0; + + u4TotAdjCnt += u4AdjCnt; + } + + return u4TotAdjCnt; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +uint16_t nicTxGetResource(IN struct ADAPTER *prAdapter, + IN uint8_t ucTC) +{ + struct TX_CTRL *prTxCtrl; + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + ASSERT(prTxCtrl); + + if (ucTC >= TC_NUM) + return 0; + else + return prTxCtrl->rTc.au4FreePageCount[ucTC]; +} + +uint8_t nicTxGetFrameResourceType(IN uint8_t eFrameType, + IN struct MSDU_INFO *prMsduInfo) +{ + uint8_t ucTC; + + switch (eFrameType) { + case FRAME_TYPE_802_1X: + ucTC = TC4_INDEX; + break; + + case FRAME_TYPE_MMPDU: + if (prMsduInfo) + ucTC = prMsduInfo->ucTC; + else + ucTC = TC4_INDEX; + break; + + default: + DBGLOG(INIT, WARN, "Undefined Frame Type(%u)\n", + eFrameType); + ucTC = TC4_INDEX; + break; + } + + return ucTC; +} + +uint8_t nicTxGetCmdResourceType(IN struct CMD_INFO + *prCmdInfo) +{ + uint8_t ucTC; + + switch (prCmdInfo->eCmdType) { + case COMMAND_TYPE_NETWORK_IOCTL: + case COMMAND_TYPE_GENERAL_IOCTL: + ucTC = TC4_INDEX; + break; + + case COMMAND_TYPE_SECURITY_FRAME: + ucTC = nicTxGetFrameResourceType(FRAME_TYPE_802_1X, NULL); + break; + + case COMMAND_TYPE_MANAGEMENT_FRAME: + ucTC = nicTxGetFrameResourceType(FRAME_TYPE_MMPDU, + prCmdInfo->prMsduInfo); + break; + + default: + DBGLOG(INIT, WARN, "Undefined CMD Type(%u)\n", + prCmdInfo->eCmdType); + ucTC = TC4_INDEX; + break; + } + + return ucTC; +} + +uint8_t nicTxGetTxQByTc(IN struct ADAPTER *prAdapter, + IN uint8_t ucTc) +{ + return arTcResourceControl[ucTc].ucHifTxQIndex; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxMsduInfoList(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfoListHead) +{ + struct MSDU_INFO *prMsduInfo, *prNextMsduInfo; + struct QUE qDataPort0, qDataPort1; + struct QUE *prDataPort0, *prDataPort1; + uint32_t status; + + ASSERT(prAdapter); + ASSERT(prMsduInfoListHead); + + prMsduInfo = prMsduInfoListHead; + + prDataPort0 = &qDataPort0; + prDataPort1 = &qDataPort1; + + QUEUE_INITIALIZE(prDataPort0); + QUEUE_INITIALIZE(prDataPort1); + + /* Separate MSDU_INFO_T lists into 2 categories: for Port#0 & Port#1 */ + while (prMsduInfo) { + prNextMsduInfo = (struct MSDU_INFO *) QUEUE_GET_NEXT_ENTRY(( + struct QUE_ENTRY *) prMsduInfo); + + switch (prMsduInfo->ucTC) { + case TC0_INDEX: + case TC1_INDEX: + case TC2_INDEX: + case TC3_INDEX: + QUEUE_GET_NEXT_ENTRY((struct QUE_ENTRY *) prMsduInfo) = + NULL; + QUEUE_INSERT_TAIL(prDataPort0, + (struct QUE_ENTRY *) prMsduInfo); + status = nicTxAcquireResource( + prAdapter, prMsduInfo->ucTC, + nicTxGetPageCount( + prAdapter, prMsduInfo->u2FrameLength, + FALSE), TRUE); + ASSERT(status == WLAN_STATUS_SUCCESS); + + break; + + case TC4_INDEX: /* Management packets */ + QUEUE_GET_NEXT_ENTRY((struct QUE_ENTRY *) prMsduInfo) = + NULL; + QUEUE_INSERT_TAIL(prDataPort1, + (struct QUE_ENTRY *) prMsduInfo); + + status = nicTxAcquireResource( + prAdapter, prMsduInfo->ucTC, + nicTxGetPageCount(prAdapter, + prMsduInfo->u2FrameLength, + FALSE), TRUE); + ASSERT(status == WLAN_STATUS_SUCCESS); + + break; + + default: + ASSERT(0); + break; + } + + prMsduInfo = prNextMsduInfo; + } + + if (prDataPort0->u4NumElem > 0) + nicTxMsduQueue(prAdapter, 0, prDataPort0); + + if (prDataPort1->u4NumElem > 0) + nicTxMsduQueue(prAdapter, 1, prDataPort1); + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_SUPPORT_MULTITHREAD +/*----------------------------------------------------------------------------*/ +/*! + * @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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxMsduInfoListMthread(IN struct ADAPTER + *prAdapter, IN struct MSDU_INFO *prMsduInfoListHead) +{ +#if CFG_FIX_2_TX_PORT + struct MSDU_INFO *prMsduInfo, *prNextMsduInfo; + struct QUE qDataPort0, qDataPort1; + struct QUE *prDataPort0, *prDataPort1; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prMsduInfoListHead); + + prMsduInfo = prMsduInfoListHead; + + prDataPort0 = &qDataPort0; + prDataPort1 = &qDataPort1; + + QUEUE_INITIALIZE(prDataPort0); + QUEUE_INITIALIZE(prDataPort1); + + /* Separate MSDU_INFO_T lists into 2 categories: for Port#0 & Port#1 */ + while (prMsduInfo) { + prNextMsduInfo = (struct MSDU_INFO *) QUEUE_GET_NEXT_ENTRY(( + struct QUE_ENTRY *) prMsduInfo); + + switch (prMsduInfo->ucTC) { + case TC0_INDEX: + case TC1_INDEX: + case TC2_INDEX: + case TC3_INDEX: + QUEUE_GET_NEXT_ENTRY((struct QUE_ENTRY *) prMsduInfo) = + NULL; + QUEUE_INSERT_TAIL(prDataPort0, + (struct QUE_ENTRY *) prMsduInfo); + break; + + case TC4_INDEX: /* Management packets */ + QUEUE_GET_NEXT_ENTRY((struct QUE_ENTRY *) prMsduInfo) = + NULL; + QUEUE_INSERT_TAIL(prDataPort1, + (struct QUE_ENTRY *) prMsduInfo); + break; + + default: + ASSERT(0); + break; + } + + nicTxFillDataDesc(prAdapter, prMsduInfo); + + prMsduInfo = prNextMsduInfo; + } + + if (prDataPort0->u4NumElem > 0 + || prDataPort1->u4NumElem > 0) { + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + QUEUE_CONCATENATE_QUEUES((&(prAdapter->rTxP0Queue)), + (prDataPort0)); + QUEUE_CONCATENATE_QUEUES((&(prAdapter->rTxP1Queue)), + (prDataPort1)); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + + kalSetTxEvent2Hif(prAdapter->prGlueInfo); + } +#else + + struct MSDU_INFO *prMsduInfo, *prNextMsduInfo; + struct QUE qDataPort[TX_PORT_NUM]; + struct QUE *prDataPort[TX_PORT_NUM]; + int32_t i; + u_int8_t fgSetTx2Hif = FALSE; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prMsduInfoListHead); + + prMsduInfo = prMsduInfoListHead; + + for (i = 0; i < TX_PORT_NUM; i++) { + prDataPort[i] = &qDataPort[i]; + QUEUE_INITIALIZE(prDataPort[i]); + } + + /* Separate MSDU_INFO_T lists into 2 categories: for Port#0 & Port#1 */ + while (prMsduInfo) { + + fgSetTx2Hif = TRUE; + prNextMsduInfo = (struct MSDU_INFO *) QUEUE_GET_NEXT_ENTRY(( + struct QUE_ENTRY *) prMsduInfo); + + if (prMsduInfo->ucWmmQueSet == DBDC_2G_WMM_INDEX) { + QUEUE_GET_NEXT_ENTRY((struct QUE_ENTRY *) prMsduInfo) = + NULL; + QUEUE_INSERT_TAIL(prDataPort[TX_2G_WMM_PORT_NUM], + (struct QUE_ENTRY *) prMsduInfo); + } else { + if (prMsduInfo->ucTC >= 0 && + prMsduInfo->ucTC < TC_NUM) { + QUEUE_GET_NEXT_ENTRY( + (struct QUE_ENTRY *) prMsduInfo) = + NULL; + QUEUE_INSERT_TAIL(prDataPort[prMsduInfo->ucTC], + (struct QUE_ENTRY *) prMsduInfo); + } else + ASSERT(0); + } + nicTxFillDataDesc(prAdapter, prMsduInfo); + + prMsduInfo = prNextMsduInfo; + } + + if (fgSetTx2Hif) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + for (i = 0; i < TX_PORT_NUM; i++) + QUEUE_CONCATENATE_QUEUES((&(prAdapter->rTxPQueue[i])), + (prDataPort[i])); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + + if (HAL_HAS_AGG_THREAD(prAdapter)) + HAL_AGG_THREAD_WAKE_UP(prAdapter); + else + kalSetTxEvent2Hif(prAdapter->prGlueInfo); + } + +#endif + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief In this function, we'll write frame(PACKET_INFO_T) into HIF + * when apply multithread. + * + * @param prAdapter Pointer to the Adapter structure. + * + * @retval WLAN_STATUS_SUCCESS Bus access ok. + * @retval WLAN_STATUS_FAILURE Bus access fail. + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxMsduQueueMthread(IN struct ADAPTER *prAdapter) +{ +#if CFG_FIX_2_TX_PORT + struct QUE qDataPort0, qDataPort1; + struct QUE *prDataPort0, *prDataPort1; + uint32_t u4TxLoopCount; + + KAL_SPIN_LOCK_DECLARATION(); + + prDataPort0 = &qDataPort0; + prDataPort1 = &qDataPort1; + + QUEUE_INITIALIZE(prDataPort0); + QUEUE_INITIALIZE(prDataPort1); + + u4TxLoopCount = prAdapter->rWifiVar.u4HifTxloopCount; + + while (u4TxLoopCount--) { + while (QUEUE_IS_NOT_EMPTY(&(prAdapter->rTxP0Queue))) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + QUEUE_MOVE_ALL(prDataPort0, &(prAdapter->rTxP0Queue)); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + + nicTxMsduQueue(prAdapter, 0, prDataPort0); + + if (QUEUE_IS_NOT_EMPTY(prDataPort0)) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TX_PORT_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD( + &(prAdapter->rTxP0Queue), + prDataPort0); + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TX_PORT_QUE); + + break; + } + } + + while (QUEUE_IS_NOT_EMPTY(&(prAdapter->rTxP1Queue))) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + QUEUE_MOVE_ALL(prDataPort1, &(prAdapter->rTxP1Queue)); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + + nicTxMsduQueue(prAdapter, 1, prDataPort1); + + if (QUEUE_IS_NOT_EMPTY(prDataPort1)) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TX_PORT_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD( + &(prAdapter->rTxP1Queue), + prDataPort1); + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TX_PORT_QUE); + + break; + } + } + } +#else + + uint32_t u4TxLoopCount; + struct QUE qDataPort[TX_PORT_NUM]; + struct QUE *prDataPort[TX_PORT_NUM]; + int32_t i; + + KAL_SPIN_LOCK_DECLARATION(); + + if (halIsHifStateSuspend(prAdapter)) { + DBGLOG(TX, WARN, "Suspend TxMsduQueueMthread\n"); + return WLAN_STATUS_SUCCESS; + } + + for (i = 0; i < TX_PORT_NUM; i++) { + prDataPort[i] = &qDataPort[i]; + QUEUE_INITIALIZE(prDataPort[i]); + } + + u4TxLoopCount = prAdapter->rWifiVar.u4HifTxloopCount; + + while (u4TxLoopCount--) { + for (i = TC_NUM; i >= 0; i--) { + while (QUEUE_IS_NOT_EMPTY(&(prAdapter->rTxPQueue[i]))) { + KAL_ACQUIRE_SPIN_LOCK( + prAdapter, SPIN_LOCK_TX_PORT_QUE); + QUEUE_MOVE_ALL( + prDataPort[i], + &(prAdapter->rTxPQueue[i])); + KAL_RELEASE_SPIN_LOCK( + prAdapter, SPIN_LOCK_TX_PORT_QUE); + + nicTxMsduQueue(prAdapter, 0, prDataPort[i]); + + if (QUEUE_IS_NOT_EMPTY(prDataPort[i])) { + KAL_ACQUIRE_SPIN_LOCK( + prAdapter, + SPIN_LOCK_TX_PORT_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD( + &(prAdapter->rTxPQueue[i]), + prDataPort[i]); + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TX_PORT_QUE); + + break; + } + } + } + } +#endif + return WLAN_STATUS_SUCCESS; +} + +uint32_t nicTxGetMsduPendingCnt(IN struct ADAPTER + *prAdapter) +{ +#if CFG_FIX_2_TX_PORT + return prAdapter->rTxP0Queue.u4NumElem + + prAdapter->rTxP1Queue.u4NumElem; +#else + int32_t i; + uint32_t retValue = 0; + + for (i = 0; i < TX_PORT_NUM; i++) + retValue += prAdapter->rTxPQueue[i].u4NumElem; + return retValue; +#endif +} + +#endif + +void nicTxComposeDescAppend(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + OUT uint8_t *prTxDescBuffer) +{ + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + + if (prChipInfo->prTxDescOps->fillNicAppend) + prChipInfo->prTxDescOps->fillNicAppend(prAdapter, + prMsduInfo, prTxDescBuffer); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief In this function, we'll compose the Tx descriptor of the MSDU. + * + * @param prAdapter Pointer to the Adapter structure. + * @param prMsduInfo Pointer to the Msdu info + * @param prTxDesc Pointer to the Tx descriptor buffer + * + * @retval VOID + */ +/*----------------------------------------------------------------------------*/ +void +nicTxComposeDesc(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN uint32_t u4TxDescLength, IN u_int8_t fgIsTemplate, + OUT uint8_t *prTxDescBuffer) +{ + struct HW_MAC_TX_DESC *prTxDesc; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + uint8_t ucEtherTypeOffsetInWord; + uint32_t u4TxDescAndPaddingLength; + uint8_t ucTarPort, ucTarQueue; +#if ((CFG_SISO_SW_DEVELOP == 1) || (CFG_SUPPORT_SPE_IDX_CONTROL == 1)) + enum ENUM_WF_PATH_FAVOR_T eWfPathFavor; +#endif + prTxDesc = (struct HW_MAC_TX_DESC *) prTxDescBuffer; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prMsduInfo->ucBssIndex); + prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + + u4TxDescAndPaddingLength = u4TxDescLength + + NIC_TX_DESC_PADDING_LENGTH; + + kalMemZero(prTxDesc, u4TxDescAndPaddingLength); + + /* Move to nicTxFillDesc */ + /* Tx byte count */ + /* HAL_MAC_TX_DESC_SET_TX_BYTE_COUNT(prTxDesc, + * ucTxDescAndPaddingLength + prMsduInfo->u2FrameLength); + */ + + /* Ether-type offset */ + if (prMsduInfo->fgIs802_11) { + ucEtherTypeOffsetInWord = + (NIC_TX_PSE_HEADER_LENGTH + + prMsduInfo->ucMacHeaderLength + + prMsduInfo->ucLlcLength) >> 1; + } else { + ucEtherTypeOffsetInWord = ((ETHER_HEADER_LEN - + ETHER_TYPE_LEN) + NIC_TX_PSE_HEADER_LENGTH) >> 1; + } + HAL_MAC_TX_DESC_SET_ETHER_TYPE_OFFSET(prTxDesc, + ucEtherTypeOffsetInWord); + + /* Port index / queue index */ + ucTarPort = + arTcResourceControl[prMsduInfo->ucTC].ucDestPortIndex; + HAL_MAC_TX_DESC_SET_PORT_INDEX(prTxDesc, ucTarPort); + + ucTarQueue = + arTcResourceControl[prMsduInfo->ucTC].ucDestQueueIndex; + if (ucTarPort == PORT_INDEX_LMAC) + ucTarQueue += (prBssInfo->ucWmmQueSet * WMM_AC_INDEX_NUM); + + HAL_MAC_TX_DESC_SET_QUEUE_INDEX(prTxDesc, ucTarQueue); + + /* BMC packet */ + if (prMsduInfo->ucStaRecIndex == STA_REC_INDEX_BMCAST) { + HAL_MAC_TX_DESC_SET_BMC(prTxDesc); + + /* Must set No ACK to mask retry bit in FC */ + HAL_MAC_TX_DESC_SET_NO_ACK(prTxDesc); + } + /* WLAN index */ + prMsduInfo->ucWlanIndex = nicTxGetWlanIdx(prAdapter, + prMsduInfo->ucBssIndex, prMsduInfo->ucStaRecIndex); + +#if 0 /* DBG */ + DBGLOG(RSN, INFO, + "Tx WlanIndex = %d eAuthMode = %d\n", + prMsduInfo->ucWlanIndex, + prAdapter->rWifiVar.rConnSettings.eAuthMode); +#endif + HAL_MAC_TX_DESC_SET_WLAN_INDEX(prTxDesc, + prMsduInfo->ucWlanIndex); + + /* Header format */ + if (prMsduInfo->fgIs802_11) { + HAL_MAC_TX_DESC_SET_HEADER_FORMAT(prTxDesc, + HEADER_FORMAT_802_11_NORMAL_MODE); + HAL_MAC_TX_DESC_SET_802_11_HEADER_LENGTH(prTxDesc, + (prMsduInfo->ucMacHeaderLength >> 1)); + } else { + HAL_MAC_TX_DESC_SET_HEADER_FORMAT(prTxDesc, + HEADER_FORMAT_NON_802_11); + HAL_MAC_TX_DESC_SET_ETHERNET_II(prTxDesc); + } + + /* Header Padding */ + HAL_MAC_TX_DESC_SET_HEADER_PADDING(prTxDesc, + NIC_TX_DESC_HEADER_PADDING_LENGTH); + + /* TID */ + HAL_MAC_TX_DESC_SET_TID(prTxDesc, + prMsduInfo->ucUserPriority); + + /* Protection */ + if (secIsProtectedFrame(prAdapter, prMsduInfo, prStaRec)) { + /* Update Packet option, + * PF bit will be set in nicTxFillDescByPktOption() + */ + if ((prStaRec && prStaRec->fgTransmitKeyExist) + || fgIsTemplate) { + nicTxConfigPktOption( + prMsduInfo, MSDU_OPT_PROTECTED_FRAME, + TRUE); + + if (prMsduInfo->fgIs802_1x_NonProtected) { + nicTxConfigPktOption( + prMsduInfo, MSDU_OPT_PROTECTED_FRAME, + FALSE); + DBGLOG(RSN, LOUD, + "Pairwise EAPoL not protect!\n"); + } + } else if (prMsduInfo->ucStaRecIndex == + STA_REC_INDEX_BMCAST) {/* BMC packet */ + nicTxConfigPktOption(prMsduInfo, + MSDU_OPT_PROTECTED_FRAME, + TRUE); + DBGLOG(RSN, LOUD, "Protect BMC frame!\n"); + } + } +#if (UNIFIED_MAC_TX_FORMAT == 1) + /* Packet Format */ + HAL_MAC_TX_DESC_SET_PKT_FORMAT(prTxDesc, + prMsduInfo->ucPacketFormat); +#endif + + /* Own MAC */ + HAL_MAC_TX_DESC_SET_OWN_MAC_INDEX(prTxDesc, + prBssInfo->ucOwnMacIndex); + + if (u4TxDescLength == NIC_TX_DESC_SHORT_FORMAT_LENGTH) { + HAL_MAC_TX_DESC_SET_SHORT_FORMAT(prTxDesc); + + /* Update Packet option */ + nicTxFillDescByPktOption(prMsduInfo, prTxDesc); + + /* Short format, Skip DW 2~6 */ + return; + } + HAL_MAC_TX_DESC_SET_LONG_FORMAT(prTxDesc); + + /* Update Packet option */ + nicTxFillDescByPktOption(prMsduInfo, prTxDesc); + + nicTxFillDescByPktControl(prMsduInfo, prTxDesc); + + /* Type */ + if (prMsduInfo->fgIs802_11) { + struct WLAN_MAC_HEADER *prWlanHeader = + (struct WLAN_MAC_HEADER *) ((unsigned long) ( + prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + HAL_MAC_TX_DESC_SET_TYPE(prTxDesc, + (prWlanHeader->u2FrameCtrl & MASK_FC_TYPE) >> 2); + HAL_MAC_TX_DESC_SET_SUB_TYPE(prTxDesc, + (prWlanHeader->u2FrameCtrl & MASK_FC_SUBTYPE) >> + OFFSET_OF_FC_SUBTYPE); + } + /* PID */ + if (prMsduInfo->pfTxDoneHandler) { + prMsduInfo->ucPID = nicTxAssignPID(prAdapter, + prMsduInfo->ucWlanIndex); + HAL_MAC_TX_DESC_SET_PID(prTxDesc, prMsduInfo->ucPID); + HAL_MAC_TX_DESC_SET_TXS_TO_MCU(prTxDesc); + } else if (prAdapter->rWifiVar.ucDataTxDone == 2) { + /* Log mode: only TxS to FW, no event to driver */ + HAL_MAC_TX_DESC_SET_PID(prTxDesc, NIC_TX_DESC_PID_RESERVED); + HAL_MAC_TX_DESC_SET_TXS_TO_MCU(prTxDesc); + } + + /* Remaining TX time */ + if (!(prMsduInfo->u4Option & MSDU_OPT_MANUAL_LIFE_TIME)) + prMsduInfo->u4RemainingLifetime = + arTcTrafficSettings[prMsduInfo->ucTC].u4RemainingTxTime; + HAL_MAC_TX_DESC_SET_REMAINING_LIFE_TIME_IN_MS(prTxDesc, + prMsduInfo->u4RemainingLifetime); + + /* Tx count limit */ + if (!(prMsduInfo->u4Option & MSDU_OPT_MANUAL_RETRY_LIMIT)) { + /* Note: BMC packet retry limit is set to unlimited */ + prMsduInfo->ucRetryLimit = + arTcTrafficSettings[prMsduInfo->ucTC].ucTxCountLimit; + } + HAL_MAC_TX_DESC_SET_REMAINING_TX_COUNT(prTxDesc, + prMsduInfo->ucRetryLimit); + + /* Power Offset */ + HAL_MAC_TX_DESC_SET_POWER_OFFSET(prTxDesc, + prMsduInfo->cPowerOffset); + + /* Fix rate */ + switch (prMsduInfo->ucRateMode) { + case MSDU_RATE_MODE_MANUAL_DESC: + HAL_MAC_TX_DESC_SET_DW(prTxDesc, 6, 1, + &prMsduInfo->u4FixedRateOption); +#if ((CFG_SISO_SW_DEVELOP == 1) || (CFG_SUPPORT_SPE_IDX_CONTROL == 1)) + /* Update spatial extension index setting */ + eWfPathFavor = wlanGetAntPathType(prAdapter, ENUM_WF_NON_FAVOR, + prBssInfo->ucBssIndex); + HAL_MAC_TX_DESC_SET_SPE_IDX(prTxDesc, + wlanGetSpeIdx(prAdapter, prBssInfo->ucBssIndex, + eWfPathFavor)); +#endif + HAL_MAC_TX_DESC_SET_FIXED_RATE_MODE_TO_DESC(prTxDesc); + HAL_MAC_TX_DESC_SET_FIXED_RATE_ENABLE(prTxDesc); + break; + + case MSDU_RATE_MODE_MANUAL_CR: + HAL_MAC_TX_DESC_SET_FIXED_RATE_MODE_TO_CR(prTxDesc); + HAL_MAC_TX_DESC_SET_FIXED_RATE_ENABLE(prTxDesc); + break; + + case MSDU_RATE_MODE_AUTO: + default: + break; + } + +} + +void +nicTxComposeSecurityFrameDesc(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, OUT uint8_t *prTxDescBuffer, + OUT uint8_t *pucTxDescLength) +{ + struct HW_MAC_TX_DESC *prTxDesc = (struct HW_MAC_TX_DESC *) + prTxDescBuffer; + uint8_t ucTxDescAndPaddingLength = + NIC_TX_DESC_LONG_FORMAT_LENGTH + NIC_TX_DESC_PADDING_LENGTH; + + struct BSS_INFO *prBssInfo; + uint8_t ucTid = 0; + uint8_t ucTempTC = TC4_INDEX; + void *prNativePacket; + uint8_t ucEtherTypeOffsetInWord; + struct MSDU_INFO *prMsduInfo; + + prMsduInfo = prCmdInfo->prMsduInfo; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prMsduInfo->ucBssIndex); + prNativePacket = prMsduInfo->prPacket; + + ASSERT(prNativePacket); + + kalMemZero(prTxDesc, ucTxDescAndPaddingLength); + + /* WLAN index */ + prMsduInfo->ucWlanIndex = nicTxGetWlanIdx(prAdapter, + prMsduInfo->ucBssIndex, prMsduInfo->ucStaRecIndex); + + /* UC to a connected peer */ + HAL_MAC_TX_DESC_SET_WLAN_INDEX(prTxDesc, + prMsduInfo->ucWlanIndex); + /* Redirect Security frame to TID0 */ + /* ucTempTC = arNetwork2TcResource[prStaRec->ucBssIndex] + * [aucTid2ACI[ucTid]]; + */ + + /* Tx byte count */ + HAL_MAC_TX_DESC_SET_TX_BYTE_COUNT(prTxDesc, + ucTxDescAndPaddingLength + prCmdInfo->u2InfoBufLen); + + /* Ether-type offset */ + ucEtherTypeOffsetInWord = ((ETHER_HEADER_LEN - + ETHER_TYPE_LEN) + NIC_TX_PSE_HEADER_LENGTH) >> 1; + HAL_MAC_TX_DESC_SET_ETHER_TYPE_OFFSET(prTxDesc, + ucEtherTypeOffsetInWord); + + /* Port index / queue index */ + HAL_MAC_TX_DESC_SET_PORT_INDEX(prTxDesc, + arTcResourceControl[ucTempTC].ucDestPortIndex); + HAL_MAC_TX_DESC_SET_QUEUE_INDEX(prTxDesc, + arTcResourceControl[ucTempTC].ucDestQueueIndex); + + /* Header format */ + HAL_MAC_TX_DESC_SET_HEADER_FORMAT(prTxDesc, + HEADER_FORMAT_NON_802_11); + + /* Long Format */ + HAL_MAC_TX_DESC_SET_LONG_FORMAT(prTxDesc); + + /* Update Packet option */ + nicTxFillDescByPktOption(prMsduInfo, prTxDesc); + + if (!GLUE_TEST_PKT_FLAG(prNativePacket, ENUM_PKT_802_3)) { + /* Set EthernetII */ + HAL_MAC_TX_DESC_SET_ETHERNET_II(prTxDesc); + } + /* Header Padding */ + HAL_MAC_TX_DESC_SET_HEADER_PADDING(prTxDesc, + NIC_TX_DESC_HEADER_PADDING_LENGTH); + + /* TID */ + HAL_MAC_TX_DESC_SET_TID(prTxDesc, ucTid); + + /* Remaining TX time */ + HAL_MAC_TX_DESC_SET_REMAINING_LIFE_TIME_IN_MS(prTxDesc, + arTcTrafficSettings[ucTempTC].u4RemainingTxTime); + + /* Tx count limit */ + HAL_MAC_TX_DESC_SET_REMAINING_TX_COUNT(prTxDesc, + arTcTrafficSettings[ucTempTC].ucTxCountLimit); + + /* Set lowest BSS basic rate */ + HAL_MAC_TX_DESC_SET_FR_RATE(prTxDesc, + prBssInfo->u2HwDefaultFixedRateCode); + HAL_MAC_TX_DESC_SET_FIXED_RATE_MODE_TO_DESC(prTxDesc); + HAL_MAC_TX_DESC_SET_FIXED_RATE_ENABLE(prTxDesc); + + /* Packet Format */ + HAL_MAC_TX_DESC_SET_PKT_FORMAT(prTxDesc, + TXD_PKT_FORMAT_COMMAND); + + /* Own MAC */ + HAL_MAC_TX_DESC_SET_OWN_MAC_INDEX(prTxDesc, + prBssInfo->ucOwnMacIndex); + + /* PID */ + if (prMsduInfo->pfTxDoneHandler) { + prMsduInfo->ucPID = nicTxAssignPID(prAdapter, + prMsduInfo->ucWlanIndex); + HAL_MAC_TX_DESC_SET_PID(prTxDesc, prMsduInfo->ucPID); + HAL_MAC_TX_DESC_SET_TXS_TO_MCU(prTxDesc); + } + + if (pucTxDescLength) + *pucTxDescLength = ucTxDescAndPaddingLength; +} + +u_int8_t nicTxIsTXDTemplateAllowed(IN struct ADAPTER + *prAdapter, IN struct MSDU_INFO *prMsduInfo, + IN struct STA_RECORD *prStaRec) +{ + if (prMsduInfo->fgIsTXDTemplateValid) { + if (prMsduInfo->fgIs802_1x) + return FALSE; + + if (prMsduInfo->ucRateMode != MSDU_RATE_MODE_AUTO) + return FALSE; + + if (!prStaRec) + return FALSE; + + if (prMsduInfo->ucControlFlag) + return FALSE; + + if (prMsduInfo->pfTxDoneHandler) + return FALSE; + + if (prAdapter->rWifiVar.ucDataTxRateMode) + return FALSE; + + return TRUE; + } + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief In this function, we'll compose the Tx descriptor of the MSDU. + * + * @param prAdapter Pointer to the Adapter structure. + * @param prMsduInfo Pointer to the Msdu info + * @param prTxDesc Pointer to the Tx descriptor buffer + * + * @retval VOID + */ +/*----------------------------------------------------------------------------*/ +void +nicTxFillDesc(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + OUT uint8_t *prTxDescBuffer, OUT uint32_t *pu4TxDescLength) +{ + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + struct HW_MAC_TX_DESC *prTxDesc = (struct HW_MAC_TX_DESC *) + prTxDescBuffer; + struct HW_MAC_TX_DESC *prTxDescTemplate = NULL; + struct STA_RECORD *prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + uint32_t u4TxDescLength; +#if CFG_TCP_IP_CHKSUM_OFFLOAD + uint8_t ucChksumFlag = 0; +#endif + + /* This is to lock the process to preventing */ + /* nicTxFreeDescTemplate while Filling it */ + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_DESC); + + /* + * ------------------------------------------------------------------- + * Fill up common fileds + * ------------------------------------------------------------------- + */ + u4TxDescLength = NIC_TX_DESC_LONG_FORMAT_LENGTH; + + /* Get TXD from pre-allocated template */ + if (nicTxIsTXDTemplateAllowed(prAdapter, prMsduInfo, + prStaRec) && + prStaRec->aprTxDescTemplate[prMsduInfo->ucUserPriority]) { + prTxDescTemplate = + prStaRec->aprTxDescTemplate[prMsduInfo->ucUserPriority]; + + if (prMsduInfo->ucPacketType == TX_PACKET_TYPE_DATA) + kalMemCopy(prTxDesc, prTxDescTemplate, + u4TxDescLength + prChipInfo->txd_append_size); + else + kalMemCopy(prTxDesc, prTxDescTemplate, u4TxDescLength); + + /* Overwrite fields for EOSP or More data */ + nicTxFillDescByPktOption(prMsduInfo, prTxDesc); + } + /* Compose TXD by Msdu info */ + else { +#if (UNIFIED_MAC_TX_FORMAT == 1) + if (prMsduInfo->eSrc == TX_PACKET_MGMT) + prMsduInfo->ucPacketFormat = TXD_PKT_FORMAT_COMMAND; + else + prMsduInfo->ucPacketFormat = prChipInfo->ucPacketFormat; +#endif /* UNIFIED_MAC_TX_FORMAT == 1 */ + nicTxComposeDesc(prAdapter, prMsduInfo, u4TxDescLength, + FALSE, prTxDescBuffer); + + /* Compose TxD append */ + if (prMsduInfo->ucPacketType == TX_PACKET_TYPE_DATA) + nicTxComposeDescAppend(prAdapter, prMsduInfo, + prTxDescBuffer + u4TxDescLength); + } + + /* + * -------------------------------------------------------------------- + * Fill up remaining parts, per-packet variant fields + * -------------------------------------------------------------------- + */ + if (prChipInfo->prTxDescOps->fillTxByteCount) + prChipInfo->prTxDescOps->fillTxByteCount(prAdapter, + prMsduInfo, prTxDesc); + + /* Checksum offload */ +#if CFG_TCP_IP_CHKSUM_OFFLOAD + if (prAdapter->fgIsSupportCsumOffload + && prMsduInfo->eSrc == TX_PACKET_OS) { + if (prAdapter->u4CSUMFlags & + (CSUM_OFFLOAD_EN_TX_TCP | CSUM_OFFLOAD_EN_TX_UDP | + CSUM_OFFLOAD_EN_TX_IP)) { + ASSERT(prMsduInfo->prPacket); + kalQueryTxChksumOffloadParam(prMsduInfo->prPacket, + &ucChksumFlag); + if ((ucChksumFlag & TX_CS_IP_GEN)) + HAL_MAC_TX_DESC_SET_IP_CHKSUM(prTxDesc); + if ((ucChksumFlag & TX_CS_TCP_UDP_GEN)) + HAL_MAC_TX_DESC_SET_TCP_UDP_CHKSUM(prTxDesc); + } + } +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + /* Set EtherType & VLAN for non 802.11 frame */ + if (!prMsduInfo->fgIs802_11) { + if (prMsduInfo->fgIs802_3) + HAL_MAC_TX_DESC_UNSET_ETHERNET_II(prTxDesc); + if (prMsduInfo->fgIsVlanExists) + HAL_MAC_TX_DESC_SET_VLAN(prTxDesc); + } + + if (pu4TxDescLength) + *pu4TxDescLength = u4TxDescLength; + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_DESC); +} + +void +nicTxFillDataDesc(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + uint8_t *pucOutputBuf; + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + + pucOutputBuf = skb_push((struct sk_buff *) + prMsduInfo->prPacket, + NIC_TX_DESC_AND_PADDING_LENGTH + + prChipInfo->txd_append_size); + + nicTxFillDesc(prAdapter, prMsduInfo, pucOutputBuf, NULL); +} + +void +nicTxCopyDesc(IN struct ADAPTER *prAdapter, + IN uint8_t *pucTarTxDesc, IN uint8_t *pucSrcTxDesc, + OUT uint8_t *pucTxDescLength) +{ + uint8_t ucTxDescLength; + + if (HAL_MAC_TX_DESC_IS_LONG_FORMAT((struct HW_MAC_TX_DESC *) + pucSrcTxDesc)) + ucTxDescLength = NIC_TX_DESC_LONG_FORMAT_LENGTH; + else + ucTxDescLength = NIC_TX_DESC_SHORT_FORMAT_LENGTH; + + kalMemCopy(pucTarTxDesc, pucSrcTxDesc, ucTxDescLength); + + if (pucTxDescLength) + *pucTxDescLength = ucTxDescLength; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief In this function, we'll generate Tx descriptor template for each TID. + * + * @param prAdapter Pointer to the Adapter structure. + * @param prStaRec Pointer to the StaRec structure. + * + * @retval VOID + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxGenerateDescTemplate(IN struct ADAPTER + *prAdapter, IN struct STA_RECORD *prStaRec) +{ + uint8_t ucTid; + uint8_t ucTc; + uint32_t u4TxDescSize, u4TxDescAppendSize; + struct HW_MAC_TX_DESC *prTxDesc; + struct MSDU_INFO *prMsduInfo; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + + /* Free previous template, first */ + /* nicTxFreeDescTemplate(prAdapter, prStaRec); */ + for (ucTid = 0; ucTid < TX_DESC_TID_NUM; ucTid++) + prStaRec->aprTxDescTemplate[ucTid] = NULL; + + prMsduInfo = cnmPktAlloc(prAdapter, 0); + + if (!prMsduInfo) + return WLAN_STATUS_RESOURCES; + + prChipInfo = prAdapter->chip_info; + + /* Fill up MsduInfo template */ + prMsduInfo->eSrc = TX_PACKET_OS; + prMsduInfo->fgIs802_11 = FALSE; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_1x_NonProtected = FALSE; + prMsduInfo->fgIs802_3 = FALSE; + prMsduInfo->fgIsVlanExists = FALSE; + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->prPacket = NULL; + prMsduInfo->u2FrameLength = 0; + prMsduInfo->u4Option = 0; + prMsduInfo->u4FixedRateOption = 0; + prMsduInfo->ucRateMode = MSDU_RATE_MODE_AUTO; + prMsduInfo->ucBssIndex = prStaRec->ucBssIndex; + prMsduInfo->ucPacketType = TX_PACKET_TYPE_DATA; + prMsduInfo->ucPacketFormat = prChipInfo->ucPacketFormat; + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucPID = NIC_TX_DESC_PID_RESERVED; + + u4TxDescSize = NIC_TX_DESC_LONG_FORMAT_LENGTH; + u4TxDescAppendSize = prChipInfo->txd_append_size; + + DBGLOG(QM, INFO, + "Generate TXD template for STA[%u] QoS[%u]\n", + prStaRec->ucIndex, prStaRec->fgIsQoS); + + /* Generate new template */ + if (prStaRec->fgIsQoS) { + /* For QoS STA, generate 8 TXD template (TID0~TID7) */ + for (ucTid = 0; ucTid < TX_DESC_TID_NUM; ucTid++) { + + if (prAdapter->rWifiVar.ucTcRestrict < TC_NUM) + ucTc = prAdapter->rWifiVar.ucTcRestrict; + else + ucTc = + arNetwork2TcResource[ + prStaRec->ucBssIndex][ + aucTid2ACI[ucTid]]; + u4TxDescSize = arTcTrafficSettings[ucTc].u4TxDescLength; + + /* Include TxD append */ + prTxDesc = kalMemAlloc( + u4TxDescSize + u4TxDescAppendSize, + VIR_MEM_TYPE); + DBGLOG(QM, TRACE, "STA[%u] TID[%u] TxDTemp[0x%p]\n", + prStaRec->ucIndex, ucTid, prTxDesc); + if (!prTxDesc) { + rStatus = WLAN_STATUS_RESOURCES; + break; + } + + /* Update MsduInfo TID & TC */ + prMsduInfo->ucUserPriority = ucTid; + prMsduInfo->ucTC = ucTc; + + /* Compose Tx desc template */ + nicTxComposeDesc( + prAdapter, prMsduInfo, u4TxDescSize, TRUE, + (uint8_t *) prTxDesc); + + /* Fill TxD append */ + nicTxComposeDescAppend(prAdapter, prMsduInfo, + ((uint8_t *)prTxDesc + u4TxDescSize)); + + prStaRec->aprTxDescTemplate[ucTid] = prTxDesc; + } + } else { + /* For non-QoS STA, generate 1 TXD template (TID0) */ + do { + if (prAdapter->rWifiVar.ucTcRestrict < TC_NUM) + ucTc = prAdapter->rWifiVar.ucTcRestrict; + else + ucTc = arNetwork2TcResource[ + prStaRec->ucBssIndex][ + NET_TC_WMM_AC_BE_INDEX]; + + /* ucTxDescSize = + * arTcTrafficSettings[ucTc].ucTxDescLength; + */ + u4TxDescSize = NIC_TX_DESC_LONG_FORMAT_LENGTH; + + prTxDesc = kalMemAlloc( + u4TxDescSize + u4TxDescAppendSize, + VIR_MEM_TYPE); + if (!prTxDesc) { + rStatus = WLAN_STATUS_RESOURCES; + break; + } + /* Update MsduInfo TID & TC */ + prMsduInfo->ucUserPriority = 0; + prMsduInfo->ucTC = ucTc; + + /* Compose Tx desc template */ + nicTxComposeDesc( + prAdapter, prMsduInfo, u4TxDescSize, TRUE, + (uint8_t *) prTxDesc); + + /* Fill TxD append */ + nicTxComposeDescAppend(prAdapter, prMsduInfo, + ((uint8_t *)prTxDesc + u4TxDescSize)); + + for (ucTid = 0; ucTid < TX_DESC_TID_NUM; ucTid++) { + prStaRec->aprTxDescTemplate[ucTid] = prTxDesc; + DBGLOG(QM, TRACE, + "TXD template: TID[%u] Ptr[0x%p]\n", + ucTid, prTxDesc); + } + } while (FALSE); + } + + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief In this function, we'll free Tx descriptor template for each TID. + * + * @param prAdapter Pointer to the Adapter structure. + * @param prStaRec Pointer to the StaRec structure. + * + * @retval VOID + */ +/*----------------------------------------------------------------------------*/ +void nicTxFreeDescTemplate(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + uint8_t ucTid; + uint8_t ucTxDescSize; + struct HW_MAC_TX_DESC *prTxDesc; + + KAL_SPIN_LOCK_DECLARATION(); + + DBGLOG(QM, TRACE, "Free TXD template for STA[%u] QoS[%u]\n", + prStaRec->ucIndex, prStaRec->fgIsQoS); + + /* This is to lock the process to preventing */ + /* nicTxFreeDescTemplate while Filling it */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_DESC); + + if (prStaRec->fgIsQoS) { + for (ucTid = 0; ucTid < TX_DESC_TID_NUM; ucTid++) { + prTxDesc = (struct HW_MAC_TX_DESC *) + prStaRec->aprTxDescTemplate[ucTid]; + + if (prTxDesc) { + if (HAL_MAC_TX_DESC_IS_LONG_FORMAT(prTxDesc)) + ucTxDescSize = + NIC_TX_DESC_LONG_FORMAT_LENGTH; + else + ucTxDescSize = + NIC_TX_DESC_SHORT_FORMAT_LENGTH; + + kalMemFree(prTxDesc, VIR_MEM_TYPE, + ucTxDescSize); + + prTxDesc = + prStaRec->aprTxDescTemplate[ucTid] = + NULL; + } + } + } else { + prTxDesc = (struct HW_MAC_TX_DESC *) + prStaRec->aprTxDescTemplate[0]; + if (prTxDesc) { + if (HAL_MAC_TX_DESC_IS_LONG_FORMAT(prTxDesc)) + ucTxDescSize = NIC_TX_DESC_LONG_FORMAT_LENGTH; + else + ucTxDescSize = NIC_TX_DESC_SHORT_FORMAT_LENGTH; + + kalMemFree(prTxDesc, VIR_MEM_TYPE, ucTxDescSize); + prTxDesc = NULL; + } + for (ucTid = 0; ucTid < TX_DESC_TID_NUM; ucTid++) + prStaRec->aprTxDescTemplate[ucTid] = NULL; + } + + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_DESC); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief In this function, we'll Update H/W AMSDU filed of TxD template. + * + * @param prAdapter Pointer to the Adapter structure. + * @param prStaRec Pointer to the StaRec structure. + * @param ucTid Select target Tid template + * @param ucSet Set or clear + * + * @retval VOID + */ +/*----------------------------------------------------------------------------*/ +void nicTxSetHwAmsduDescTemplate(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, IN uint8_t ucTid, + IN u_int8_t fgSet) +{ + struct HW_MAC_TX_DESC *prTxDesc; + + DBGLOG(QM, INFO, + "Update HW Amsdu field of TXD template for STA[%u] Tid[%u]\n", + prStaRec->ucIndex, ucTid); + + if (prStaRec->aprTxDescTemplate[ucTid]) { + prTxDesc = (struct HW_MAC_TX_DESC *) + prStaRec->aprTxDescTemplate[ucTid]; + if (fgSet) + HAL_MAC_TX_DESC_SET_HW_AMSDU(prTxDesc); + else + HAL_MAC_TX_DESC_UNSET_HW_AMSDU(prTxDesc); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Write data to device done + * + * \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. + * \param[in] prQue msdu info que to be free + * + * \retval TRUE operation success + * \retval FALSE operation fail + */ +/*----------------------------------------------------------------------------*/ +void nicTxMsduDoneCb(IN struct GLUE_INFO *prGlueInfo, + IN struct QUE *prQue) +{ + struct MSDU_INFO *prMsduInfo, *prNextMsduInfo; + struct QUE rFreeQueue; + struct QUE *prFreeQueue; + /* P_NATIVE_PACKET prNativePacket;*/ + struct TX_CTRL *prTxCtrl; + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + prFreeQueue = &rFreeQueue; + QUEUE_INITIALIZE(prFreeQueue); + + if (prQue && prQue->u4NumElem > 0) { + prMsduInfo = (struct MSDU_INFO *) QUEUE_GET_HEAD(prQue); + + while (prMsduInfo) { + prNextMsduInfo = + (struct MSDU_INFO *) QUEUE_GET_NEXT_ENTRY( + &prMsduInfo->rQueEntry); + +#if 1 + nicTxFreePacket(prAdapter, prMsduInfo, FALSE); +#else + prNativePacket = prMsduInfo->prPacket; + + /* Free MSDU_INFO */ + if (prMsduInfo->eSrc == TX_PACKET_OS) { + wlanTxProfilingTagMsdu(prAdapter, prMsduInfo, + TX_PROF_TAG_DRV_DEQUE); + kalSendComplete( + prAdapter->prGlueInfo, prNativePacket, + WLAN_STATUS_SUCCESS); + prMsduInfo->prPacket = NULL; + } else if (prMsduInfo->eSrc == TX_PACKET_FORWARDING) { + GLUE_DEC_REF_CNT( + prTxCtrl->i4PendingFwdFrameCount); + } +#endif + + if (!prMsduInfo->pfTxDoneHandler) + QUEUE_INSERT_TAIL(prFreeQueue, + (struct QUE_ENTRY *) prMsduInfo); + + prMsduInfo = prNextMsduInfo; + } + + wlanTxProfilingTagMsdu(prAdapter, + (struct MSDU_INFO *) QUEUE_GET_HEAD(&rFreeQueue), + TX_PROF_TAG_DRV_FREE_MSDU); + + nicTxReturnMsduInfo(prAdapter, + (struct MSDU_INFO *) + QUEUE_GET_HEAD(&rFreeQueue)); + } +} +/*----------------------------------------------------------------------------*/ +/*! + * @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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxMsduQueue(IN struct ADAPTER *prAdapter, + uint8_t ucPortIdx, struct QUE *prQue) +{ + struct MSDU_INFO *prMsduInfo; + struct TX_CTRL *prTxCtrl; + void *prNativePacket; + + ASSERT(prAdapter); + ASSERT(prQue); + + prTxCtrl = &prAdapter->rTxCtrl; + +#if CFG_HIF_STATISTICS + prTxCtrl->u4TotalTxAccessNum++; + prTxCtrl->u4TotalTxPacketNum += prQue->u4NumElem; +#endif + + while (QUEUE_IS_NOT_EMPTY(prQue)) { + QUEUE_REMOVE_HEAD(prQue, prMsduInfo, struct MSDU_INFO *); + + if (!halTxIsDataBufEnough(prAdapter, prMsduInfo)) { + QUEUE_INSERT_HEAD(prQue, + (struct QUE_ENTRY *) prMsduInfo); + break; + } + + prNativePacket = prMsduInfo->prPacket; + +#if !CFG_SUPPORT_MULTITHREAD + nicTxFillDataDesc(prAdapter, prMsduInfo); +#endif + + if (prMsduInfo->eSrc == TX_PACKET_OS) { + wlanTxProfilingTagMsdu(prAdapter, prMsduInfo, + TX_PROF_TAG_DRV_TX_DONE); + wlanFillTimestamp(prAdapter, prMsduInfo->prPacket, + PHASE_HIF_TX); + } + + if (prMsduInfo->pfTxDoneHandler) { +#if defined(_HIF_USB) + /* For USB, we insert data MSDU into rTxMgmtTxingQueue + * util halTxUSBSendData. The reason is, in SER, we want + * the operation of data MSDU insertion into + * rTxMgmtTxingQueue and the operation of URB submit + * are atomic. + */ +#else + KAL_SPIN_LOCK_DECLARATION(); + + /* Record native packet pointer for Tx done log */ + WLAN_GET_FIELD_32(&prMsduInfo->prPacket, + &prMsduInfo->u4TxDoneTag); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TXING_MGMT_LIST); + QUEUE_INSERT_TAIL(&(prTxCtrl->rTxMgmtTxingQueue), + (struct QUE_ENTRY *) prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TXING_MGMT_LIST); +#endif /* _HIF_USB */ + } else + wlanTxLifetimeTagPacket(prAdapter, prMsduInfo, + TX_PROF_TAG_DRV_TX_DONE); + + StatsEnvTxTime2Hif(prAdapter, prMsduInfo); + + if (HAL_HAS_AGG_THREAD(prAdapter)) { + if (kalDevWriteData(prAdapter->prGlueInfo, + prMsduInfo) == FALSE) { + QUEUE_INSERT_HEAD(prQue, + (struct QUE_ENTRY *) prMsduInfo); + break; + } + } else { + HAL_WRITE_TX_DATA(prAdapter, prMsduInfo); + } + } + + HAL_KICK_TX_DATA(prAdapter); + + 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxCmd(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t ucTC) +{ + struct WIFI_CMD *prWifiCmd; + struct MSDU_INFO *prMsduInfo; + struct TX_CTRL *prTxCtrl; + struct sk_buff *skb; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prTxCtrl = &prAdapter->rTxCtrl; +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanTraceTxCmd(prCmdInfo); +#endif + + if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) { + prMsduInfo = prCmdInfo->prMsduInfo; + + prCmdInfo->pucTxd = prMsduInfo->aucTxDescBuffer; + if (HAL_MAC_TX_DESC_IS_LONG_FORMAT((struct HW_MAC_TX_DESC *) + prMsduInfo->aucTxDescBuffer)) + prCmdInfo->u4TxdLen = NIC_TX_DESC_LONG_FORMAT_LENGTH; + else + prCmdInfo->u4TxdLen = NIC_TX_DESC_SHORT_FORMAT_LENGTH; + + skb = (struct sk_buff *)prMsduInfo->prPacket; + prCmdInfo->pucTxp = skb->data; + prCmdInfo->u4TxpLen = skb->len; + + HAL_WRITE_TX_CMD(prAdapter, prCmdInfo, ucTC); + + prMsduInfo->prPacket = NULL; + + if (prMsduInfo->pfTxDoneHandler) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TXING_MGMT_LIST); + QUEUE_INSERT_TAIL(&(prTxCtrl->rTxMgmtTxingQueue), + (struct QUE_ENTRY *) prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TXING_MGMT_LIST); + } else { + /* Only return MSDU_INFO */ + /* NativePacket will be freed at + * SEC frame CMD callback + */ + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } + + } else if (prCmdInfo->eCmdType == + COMMAND_TYPE_MANAGEMENT_FRAME) { + prMsduInfo = prCmdInfo->prMsduInfo; + + ASSERT(prMsduInfo->fgIs802_11 == TRUE); + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + + prCmdInfo->pucTxd = prMsduInfo->aucTxDescBuffer; + if (HAL_MAC_TX_DESC_IS_LONG_FORMAT((struct HW_MAC_TX_DESC *) + prMsduInfo->aucTxDescBuffer)) + prCmdInfo->u4TxdLen = NIC_TX_DESC_LONG_FORMAT_LENGTH; + else + prCmdInfo->u4TxdLen = NIC_TX_DESC_SHORT_FORMAT_LENGTH; + + prCmdInfo->pucTxp = prMsduInfo->prPacket; + prCmdInfo->u4TxpLen = prMsduInfo->u2FrameLength; + + HAL_WRITE_TX_CMD(prAdapter, prCmdInfo, ucTC); + /* <4> Management Frame Post-Processing */ + GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum); + + DBGLOG(INIT, TRACE, + "TX MGMT Frame: BSS[%u] WIDX:PID[%u:%u] SEQ[%u] STA[%u] RSP[%u]\n", + prMsduInfo->ucBssIndex, prMsduInfo->ucWlanIndex, + prMsduInfo->ucPID, + prMsduInfo->ucTxSeqNum, prMsduInfo->ucStaRecIndex, + prMsduInfo->pfTxDoneHandler ? TRUE : FALSE); + + if (prMsduInfo->pfTxDoneHandler) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TXING_MGMT_LIST); + QUEUE_INSERT_TAIL(&(prTxCtrl->rTxMgmtTxingQueue), + (struct QUE_ENTRY *) prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TXING_MGMT_LIST); + } else { + cnmMgtPktFree(prAdapter, prMsduInfo); + } + + } else { + struct PSE_CMD_HDR *prPseCmdHdr; + + prWifiCmd = (struct WIFI_CMD *) prCmdInfo->pucInfoBuffer; + + prPseCmdHdr = (struct PSE_CMD_HDR *) ( + prCmdInfo->pucInfoBuffer); + prPseCmdHdr->u2Qidx = TXD_Q_IDX_MCU_RQ0; + prPseCmdHdr->u2Pidx = TXD_P_IDX_MCU; + prPseCmdHdr->u2Hf = TXD_HF_CMD; + prPseCmdHdr->u2Ft = TXD_FT_LONG_FORMAT; + prPseCmdHdr->u2PktFt = TXD_PKT_FT_CMD; + + prWifiCmd->u2Length = prWifiCmd->u2TxByteCount - sizeof( + struct PSE_CMD_HDR); + +#if (CFG_UMAC_GENERATION >= 0x20) + /* TODO ? */ + /* prWifiCmd->prPseCmd.u2TxByteCount + * = u2OverallBufferLength; + * prWifiCmd->u2TxByteCount = u2OverallBufferLength + * - sizeof(struct PSE_CMD_HDR); + */ +#else + prWifiCmd->u2TxByteCount = + TFCB_FRAME_PAD_TO_DW((prCmdInfo->u2InfoBufLen) & + (uint16_t) HIF_TX_HDR_TX_BYTE_COUNT_MASK); +#endif + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucS2DIndex = S2D_INDEX_CMD_H2N_H2C; + prCmdInfo->pucTxd = prCmdInfo->pucInfoBuffer; + prCmdInfo->u4TxdLen = prCmdInfo->u2InfoBufLen; + prCmdInfo->pucTxp = NULL; + prCmdInfo->u4TxpLen = 0; + + HAL_WRITE_TX_CMD(prAdapter, prCmdInfo, ucTC); + + DBGLOG(INIT, TRACE, + "TX CMD: ID[0x%02X] SEQ[%u] SET[%u] LEN[%u]\n", + prWifiCmd->ucCID, prWifiCmd->ucSeqNum, + prWifiCmd->ucSetQuery, prWifiCmd->u2Length); + } + + 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 struct ADAPTER *prAdapter, + IN u_int8_t fgProcTxDoneHandler) +{ + struct TX_CTRL *prTxCtrl; + struct MSDU_INFO *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, + struct MSDU_INFO *); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + if (prMsduInfo) { + DBGLOG(TX, TRACE, + "%s: Get Msdu WIDX:PID[%u:%u] SEQ[%u] from Pending Q\n", + __func__, prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, + prMsduInfo->ucTxSeqNum); + + /* invoke done handler */ + if (prMsduInfo->pfTxDoneHandler && fgProcTxDoneHandler) + prMsduInfo->pfTxDoneHandler( + prAdapter, prMsduInfo, + TX_RESULT_DROPPED_IN_DRIVER); + + nicTxFreeMsduInfoPacket(prAdapter, prMsduInfo); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } else { + break; + } + } while (TRUE); + +} /* end of nicTxRelease() */ + +/* Just a variant of nicTxRelease(). The only difference is that this function + * holds the spinlock from the beginning to the end of execution. + */ +void nicTxReleaseSafe(IN struct ADAPTER *prAdapter, + IN u_int8_t fgProcTxDoneHandler) +{ + struct TX_CTRL *prTxCtrl; + struct MSDU_INFO *prMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + nicTxFlush(prAdapter); + + /* free MSDU_INFO_T from rTxMgmtMsduInfoList */ + do { + QUEUE_REMOVE_HEAD(&prTxCtrl->rTxMgmtTxingQueue, prMsduInfo, + struct MSDU_INFO *); + + if (prMsduInfo) { + DBGLOG(TX, TRACE, + "%s: Get Msdu WIDX:PID[%u:%u] SEQ[%u] from Pending Q\n", + __func__, prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, + prMsduInfo->ucTxSeqNum); + + /* invoke done handler */ + if (prMsduInfo->pfTxDoneHandler && fgProcTxDoneHandler) + prMsduInfo->pfTxDoneHandler( + prAdapter, prMsduInfo, + TX_RESULT_DROPPED_IN_DRIVER); + + nicTxFreeMsduInfoPacket(prAdapter, prMsduInfo); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } else { + break; + } + } while (TRUE); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); +} /* 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 struct ADAPTER *prAdapter) +{ + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; + + prAdapter->prGlueInfo->IsrTxCnt++; + halProcessTxInterrupt(prAdapter); + + if (halIsHifStateSuspend(prAdapter)) + DBGLOG(TX, WARN, "Suspend TX INT\n"); + + /* Indicate Service Thread */ + if (kalGetTxPendingCmdCount(prAdapter->prGlueInfo) > 0 + || wlanGetTxPendingFrameCount(prAdapter) > 0) { + kalSetEvent(prAdapter->prGlueInfo); + } + +#if CFG_SUPPORT_SER + + /* SER break point */ + if (nicSerIsTxStop(prAdapter)) { + /* Skip following Tx handling */ + return; + } + +#endif /* CFG_SUPPORT_SER */ + + if (!HAL_HAS_AGG_THREAD(prAdapter)) { + /* TX Commands */ + if (kalGetTxPendingCmdCount(prAdapter->prGlueInfo)) + wlanTxCmdMthread(prAdapter); + + /* Process TX data packet to HIF */ + if (nicTxGetMsduPendingCnt(prAdapter) >= + prWifiVar->u4TxIntThCount) + nicTxMsduQueueMthread(prAdapter); + } +} /* end of nicProcessTxInterrupt() */ + +void nicTxFreePacket(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN u_int8_t fgDrop) +{ + void *prNativePacket; + struct TX_CTRL *prTxCtrl; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + + prNativePacket = prMsduInfo->prPacket; + + if (fgDrop) + rStatus = WLAN_STATUS_FAILURE; + + if (prMsduInfo->eSrc == TX_PACKET_OS) { + if (prNativePacket) + kalSendComplete(prAdapter->prGlueInfo, prNativePacket, + rStatus); + if (fgDrop) + wlanUpdateTxStatistics(prAdapter, prMsduInfo, + TRUE); /*get per-AC Tx drop packets */ + } else if (prMsduInfo->eSrc == TX_PACKET_MGMT) { + if (prMsduInfo->pfTxDoneHandler) + prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, + TX_RESULT_DROPPED_IN_DRIVER); + if (prNativePacket) + cnmMemFree(prAdapter, prNativePacket); + } else if (prMsduInfo->eSrc == TX_PACKET_FORWARDING) { + GLUE_DEC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfoListHead) +{ + void *prNativePacket; + struct MSDU_INFO *prMsduInfo = prMsduInfoListHead; + struct TX_CTRL *prTxCtrl; + + ASSERT(prAdapter); + ASSERT(prMsduInfoListHead); + + prTxCtrl = &prAdapter->rTxCtrl; + + while (prMsduInfo) { + prNativePacket = prMsduInfo->prPacket; + +#if 1 + nicTxFreePacket(prAdapter, prMsduInfo, TRUE); +#else + if (prMsduInfo->eSrc == TX_PACKET_OS) { + if (prNativePacket) + kalSendComplete( + prAdapter->prGlueInfo, prNativePacket, + WLAN_STATUS_FAILURE); + /*get per-AC Tx drop packets */ + wlanUpdateTxStatistics(prAdapter, prMsduInfo, TRUE); + } else if (prMsduInfo->eSrc == TX_PACKET_MGMT) { + if (prMsduInfo->pfTxDoneHandler) + prMsduInfo->pfTxDoneHandler( + prAdapter, prMsduInfo, + TX_RESULT_DROPPED_IN_DRIVER); + if (prNativePacket) + cnmMemFree(prAdapter, prNativePacket); + } else if (prMsduInfo->eSrc == TX_PACKET_FORWARDING) { + GLUE_DEC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount); + } +#endif + prMsduInfo = (struct MSDU_INFO *) QUEUE_GET_NEXT_ENTRY(( + struct QUE_ENTRY *) prMsduInfo); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief this function returns P_MSDU_INFO_T of MsduInfoList to + * TxCtrl->rfreeMsduInfoList + * + * @param prAdapter Pointer to the Adapter structure. + * @param prMsduInfoList a link list of P_MSDU_INFO_T + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicTxReturnMsduInfo(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfoListHead) +{ + struct TX_CTRL *prTxCtrl; + struct MSDU_INFO *prMsduInfo = prMsduInfoListHead, + *prNextMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + while (prMsduInfo) { + prNextMsduInfo = (struct MSDU_INFO *) QUEUE_GET_NEXT_ENTRY(( + struct QUE_ENTRY *) prMsduInfo); + + switch (prMsduInfo->eSrc) { + case TX_PACKET_FORWARDING: + wlanReturnPacket(prAdapter, prMsduInfo->prPacket); + break; + case TX_PACKET_OS: + case TX_PACKET_OS_OID: + case TX_PACKET_MGMT: + default: + break; + } + + /* Reset MSDU_INFO fields */ + kalMemZero(prMsduInfo, sizeof(struct MSDU_INFO)); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TX_MSDU_INFO_LIST); + QUEUE_INSERT_TAIL(&prTxCtrl->rFreeMsduInfoList, + (struct QUE_ENTRY *) prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_TX_MSDU_INFO_LIST); + prMsduInfo = prNextMsduInfo; + }; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief this function fills packet information to P_MSDU_INFO_T + * + * @param prAdapter Pointer to the Adapter structure. + * @param prMsduInfo P_MSDU_INFO_T + * @param prPacket P_NATIVE_PACKET + * + * @retval TRUE Success to extract information + * @retval FALSE Fail to extract correct information + */ +/*----------------------------------------------------------------------------*/ +u_int8_t nicTxFillMsduInfo(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN void *prPacket) +{ + struct GLUE_INFO *prGlueInfo; + + ASSERT(prAdapter); + + kalMemZero(prMsduInfo, sizeof(struct MSDU_INFO)); + + prGlueInfo = prAdapter->prGlueInfo; + ASSERT(prGlueInfo); + + kalGetEthDestAddr(prAdapter->prGlueInfo, prPacket, + prMsduInfo->aucEthDestAddr); + + prMsduInfo->prPacket = prPacket; + prMsduInfo->ucBssIndex = GLUE_GET_PKT_BSS_IDX(prPacket); + prMsduInfo->ucUserPriority = GLUE_GET_PKT_TID(prPacket); + prMsduInfo->ucMacHeaderLength = GLUE_GET_PKT_HEADER_LEN( + prPacket); + prMsduInfo->u2FrameLength = (uint16_t) + GLUE_GET_PKT_FRAME_LEN(prPacket); + prMsduInfo->u4PageCount = nicTxGetPageCount(prAdapter, + prMsduInfo->u2FrameLength, FALSE); + + if (GLUE_IS_PKT_FLAG_SET(prPacket)) { + prMsduInfo->fgIs802_1x = GLUE_TEST_PKT_FLAG(prPacket, + ENUM_PKT_1X) ? TRUE : FALSE; + prMsduInfo->fgIs802_1x_NonProtected = + GLUE_TEST_PKT_FLAG(prPacket, + ENUM_PKT_NON_PROTECTED_1X) ? TRUE : FALSE; + prMsduInfo->fgIs802_3 = GLUE_TEST_PKT_FLAG(prPacket, + ENUM_PKT_802_3) ? TRUE : FALSE; + prMsduInfo->fgIsVlanExists = GLUE_TEST_PKT_FLAG(prPacket, + ENUM_PKT_VLAN_EXIST) ? TRUE : FALSE; + + if (prMsduInfo->fgIs802_1x) + prMsduInfo->eEapolKeyType = secGetEapolKeyType((( + struct sk_buff *)prPacket)->data); + + if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_DHCP) + && prAdapter->rWifiVar.ucDhcpTxDone) + prMsduInfo->ucPktType = ENUM_PKT_DHCP; + else if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_ARP) + && prAdapter->rWifiVar.ucArpTxDone) + prMsduInfo->ucPktType = ENUM_PKT_ARP; + else if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_1X)) + prMsduInfo->ucPktType = ENUM_PKT_1X; + else if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_ICMP)) + prMsduInfo->ucPktType = ENUM_PKT_ICMP; + else if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_TDLS)) + prMsduInfo->ucPktType = ENUM_PKT_TDLS; + else if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_DNS)) + prMsduInfo->ucPktType = ENUM_PKT_DNS; + + if (prMsduInfo->ucPktType != 0) { + prMsduInfo->pfTxDoneHandler = wlanPktTxDone; + prMsduInfo->ucTxSeqNum = GLUE_GET_PKT_SEQ_NO(prPacket); + } + + if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_DHCP) || + GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_ARP) || + GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_1X)) { + /* Set BSS/STA lowest basic rate */ + prMsduInfo->ucRateMode = MSDU_RATE_MODE_LOWEST_RATE; + +#if CFG_CHANGE_CRITICAL_PACKET_PRIORITY + /* Set higher priority */ + prMsduInfo->ucUserPriority = + NIC_TX_CRITICAL_DATA_TID; +#endif + } + } + + /* Add dummy Tx done */ + if ((prAdapter->rWifiVar.ucDataTxDone == 1) + && (prMsduInfo->pfTxDoneHandler == NULL)) + prMsduInfo->pfTxDoneHandler = nicTxDummyTxDone; + + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxAdjustTcq(IN struct ADAPTER *prAdapter) +{ +#if CFG_SUPPORT_MULTITHREAD + struct TX_TCQ_ADJUST rTcqAdjust; + struct TX_CTRL *prTxCtrl; + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + qmAdjustTcQuotasMthread(prAdapter, &rTcqAdjust, + &prTxCtrl->rTc); + +#else + + uint32_t u4Num; + struct TX_TCQ_ADJUST rTcqAdjust; + struct TX_CTRL *prTxCtrl; + struct TX_TCQ_STATUS *prTcqStatus; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + prTcqStatus = &prAdapter->rTxCtrl.rTc; + ASSERT(prTxCtrl); + + if (qmAdjustTcQuotas(prAdapter, &rTcqAdjust, + &prTxCtrl->rTc)) { + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + for (u4Num = 0; u4Num < TC_NUM; u4Num++) { + /* Page count */ + prTxCtrl->rTc.au4FreePageCount[u4Num] += + (rTcqAdjust.ai4Variation[u4Num] * + NIC_TX_MAX_PAGE_PER_FRAME); + prTxCtrl->rTc.au4MaxNumOfPage[u4Num] += + (rTcqAdjust.ai4Variation[u4Num] * + NIC_TX_MAX_PAGE_PER_FRAME); + + /* Buffer count */ + prTxCtrl->rTc.au4FreeBufferCount[u4Num] += + rTcqAdjust.ai4Variation[u4Num]; + prTxCtrl->rTc.au4MaxNumOfBuffer[u4Num] += + rTcqAdjust.ai4Variation[u4Num]; + + ASSERT(prTxCtrl->rTc.au4FreeBufferCount[u4Num] >= 0); + ASSERT(prTxCtrl->rTc.au4MaxNumOfBuffer[u4Num] >= 0); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); +#if 0 + DBGLOG(TX, LOUD, + "TCQ Status Free Page:Buf[%03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u]\n", + prTcqStatus->au4FreePageCount[TC0_INDEX], + prTcqStatus->au4FreeBufferCount[TC0_INDEX], + prTcqStatus->au4FreePageCount[TC1_INDEX], + prTcqStatus->au4FreeBufferCount[TC1_INDEX], + prTcqStatus->au4FreePageCount[TC2_INDEX], + prTcqStatus->au4FreeBufferCount[TC2_INDEX], + prTcqStatus->au4FreePageCount[TC3_INDEX], + prTcqStatus->au4FreeBufferCount[TC3_INDEX], + prTcqStatus->au4FreePageCount[TC4_INDEX], + prTcqStatus->au4FreeBufferCount[TC4_INDEX], + prTcqStatus->au4FreePageCount[TC5_INDEX], + prTcqStatus->au4FreeBufferCount[TC5_INDEX]); +#endif + DBGLOG(TX, LOUD, + "TCQ Status Max Page:Buf[%03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u]\n", + prTcqStatus->au4MaxNumOfPage[TC0_INDEX], + prTcqStatus->au4MaxNumOfBuffer[TC0_INDEX], + prTcqStatus->au4MaxNumOfPage[TC1_INDEX], + prTcqStatus->au4MaxNumOfBuffer[TC1_INDEX], + prTcqStatus->au4MaxNumOfPage[TC2_INDEX], + prTcqStatus->au4MaxNumOfBuffer[TC2_INDEX], + prTcqStatus->au4MaxNumOfPage[TC3_INDEX], + prTcqStatus->au4MaxNumOfBuffer[TC3_INDEX], + prTcqStatus->au4MaxNumOfPage[TC4_INDEX], + prTcqStatus->au4MaxNumOfBuffer[TC4_INDEX]); + + } +#endif + 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 + */ +/*----------------------------------------------------------------------------*/ + +uint32_t nicTxFlush(IN struct ADAPTER *prAdapter) +{ + struct MSDU_INFO *prMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + if (HAL_IS_TX_DIRECT(prAdapter)) { + nicTxDirectClearAllStaPsQ(prAdapter); + } else { + /* ask Per STA/AC queue to be fllushed + * and return all queued packets + */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + prMsduInfo = qmFlushTxQueues(prAdapter); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + + if (prMsduInfo != NULL) { + nicTxFreeMsduInfoPacket(prAdapter, prMsduInfo); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } + } + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_ENABLE_FW_DOWNLOAD +/*----------------------------------------------------------------------------*/ +/*! + * \brief In this function, we'll write Command(CMD_INFO_T) into HIF. + * However this function is used for INIT_CMD. + * + * In order to avoid further maintenance issues, these 2 functions + * are separated + * + * @param prAdapter Pointer to the Adapter structure. + * @param prPacketInfo Pointer of CMD_INFO_T + * @param ucTC Specify the resource of TC + * + * @retval WLAN_STATUS_SUCCESS Bus access ok. + * @retval WLAN_STATUS_FAILURE Bus access fail. + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxInitCmd(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint16_t u2Port) +{ + uint16_t u2OverallBufferLength; + /* Pointer to Transmit Data Structure Frame */ + uint8_t *pucOutputBuf = (uint8_t *) NULL; + struct TX_CTRL *prTxCtrl; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prChipInfo = prAdapter->chip_info; + prTxCtrl = &prAdapter->rTxCtrl; + pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; + u2OverallBufferLength = TFCB_FRAME_PAD_TO_DW(( + prCmdInfo->u2InfoBufLen + prChipInfo->u2HifTxdSize) & + (uint16_t) + HIF_TX_HDR_TX_BYTE_COUNT_MASK); + + /* <0> Copy HIF TXD if need */ + HAL_WRITE_HIF_TXD(prChipInfo, pucOutputBuf, + prCmdInfo->u2InfoBufLen); + + /* <1> Copy CMD Header to command buffer + * (by using pucCoalescingBufCached) + */ + kalMemCopy((void *)&pucOutputBuf[prChipInfo->u2HifTxdSize], + (void *) prCmdInfo->pucInfoBuffer, prCmdInfo->u2InfoBufLen); + + ASSERT(u2OverallBufferLength <= + prAdapter->u4CoalescingBufCachedSize); + + /* <2> Write frame to data port */ + HAL_WRITE_TX_PORT(prAdapter, u2Port/*NIC_TX_INIT_CMD_PORT*/, + (uint32_t) u2OverallBufferLength, + (uint8_t *) pucOutputBuf, + (uint32_t) 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxInitResetResource(IN struct ADAPTER + *prAdapter) +{ + struct TX_CTRL *prTxCtrl; + uint8_t ucIdx; + uint32_t u4MaxPageCntPerFrame = + prAdapter->rTxCtrl.u4MaxPageCntPerFrame; + + DEBUGFUNC("nicTxInitResetResource"); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + /* Delta page count */ + kalMemZero(prTxCtrl->rTc.au4TxDonePageCount, + sizeof(prTxCtrl->rTc.au4TxDonePageCount)); + kalMemZero(prTxCtrl->rTc.au4PreUsedPageCount, + sizeof(prTxCtrl->rTc.au4PreUsedPageCount)); + prTxCtrl->rTc.ucNextTcIdx = TC0_INDEX; + prTxCtrl->rTc.u4AvaliablePageCount = 0; + + /* Page count */ + prTxCtrl->rTc.au4MaxNumOfPage[TC0_INDEX] = + NIC_TX_INIT_PAGE_COUNT_TC0; + prTxCtrl->rTc.au4FreePageCount[TC0_INDEX] = + NIC_TX_INIT_PAGE_COUNT_TC0; + + prTxCtrl->rTc.au4MaxNumOfPage[TC1_INDEX] = + NIC_TX_INIT_PAGE_COUNT_TC1; + prTxCtrl->rTc.au4FreePageCount[TC1_INDEX] = + NIC_TX_INIT_PAGE_COUNT_TC1; + + prTxCtrl->rTc.au4MaxNumOfPage[TC2_INDEX] = + NIC_TX_INIT_PAGE_COUNT_TC2; + prTxCtrl->rTc.au4FreePageCount[TC2_INDEX] = + NIC_TX_INIT_PAGE_COUNT_TC2; + + prTxCtrl->rTc.au4MaxNumOfPage[TC3_INDEX] = + NIC_TX_INIT_PAGE_COUNT_TC3; + prTxCtrl->rTc.au4FreePageCount[TC3_INDEX] = + NIC_TX_INIT_PAGE_COUNT_TC3; + + prTxCtrl->rTc.au4MaxNumOfPage[TC4_INDEX] = + NIC_TX_INIT_PAGE_COUNT_TC4; + prTxCtrl->rTc.au4FreePageCount[TC4_INDEX] = + NIC_TX_INIT_PAGE_COUNT_TC4; + + /* Buffer count */ + for (ucIdx = TC0_INDEX; ucIdx < TC_NUM; ucIdx++) { + prTxCtrl->rTc.au4MaxNumOfBuffer[ucIdx] = + prTxCtrl->rTc.au4MaxNumOfPage[ucIdx] / + u4MaxPageCntPerFrame; + prTxCtrl->rTc.au4FreeBufferCount[ucIdx] = + prTxCtrl->rTc.au4FreePageCount[ucIdx] / + u4MaxPageCntPerFrame; + } + + return WLAN_STATUS_SUCCESS; + +} + +#endif + +u_int8_t nicTxProcessMngPacket(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ +#if 0 + uint16_t u2RateCode; +#endif + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + + if (prMsduInfo->eSrc != TX_PACKET_MGMT) + return FALSE; + + /* Sanity check */ + if (!prMsduInfo->prPacket) + return FALSE; + + if (!prMsduInfo->u2FrameLength) + return FALSE; + + if (!prMsduInfo->ucMacHeaderLength) + return FALSE; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prMsduInfo->ucBssIndex); + prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + + /* MMPDU: force stick to TC4 */ + prMsduInfo->ucTC = TC4_INDEX; + + /* No Tx descriptor template for MMPDU */ + prMsduInfo->fgIsTXDTemplateValid = FALSE; + + /* Fixed Rate */ + if (prMsduInfo->ucRateMode == MSDU_RATE_MODE_AUTO) { +#if 0 + prMsduInfo->ucRateMode = MSDU_RATE_MODE_MANUAL_DESC; + + if (prStaRec) + u2RateCode = prStaRec->u2HwDefaultFixedRateCode; + else + u2RateCode = prBssInfo->u2HwDefaultFixedRateCode; + + nicTxSetPktFixedRateOption(prMsduInfo, u2RateCode, + FIX_BW_NO_FIXED, FALSE, FALSE); +#else + nicTxSetPktLowestFixedRate(prAdapter, prMsduInfo); +#endif + } +#if CFG_SUPPORT_MULTITHREAD + nicTxFillDesc(prAdapter, prMsduInfo, + prMsduInfo->aucTxDescBuffer, NULL); +#endif + + return TRUE; +} + +void nicTxProcessTxDoneEvent(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct EVENT_TX_DONE *prTxDone; + struct MSDU_INFO *prMsduInfo; + struct TX_CTRL *prTxCtrl = &prAdapter->rTxCtrl; + + uint8_t *apucBandwidt[4] = { + (uint8_t *)"20", (uint8_t *)"40", + (uint8_t *)"80", (uint8_t *)"160/80+80"}; + + prTxDone = (struct EVENT_TX_DONE *) (prEvent->aucBuffer); + + if (prTxDone->ucStatus == 0) + GET_CURRENT_SYSTIME(&prTxCtrl->u4LastTxTime); + + if (prTxDone->ucFlag & BIT(TXS_WITH_ADVANCED_INFO)) { + /* Tx Done with advanced info */ + if (prTxDone->ucStatus != 0) + DBGLOG_LIMITED(NIC, INFO, + "EVENT_ID_TX_DONE WIDX:PID[%u:%u] Status[%u:%s] SN[%u] TID[%u] CNT[%u] Flush[%u]\n", + prTxDone->ucWlanIndex, prTxDone->ucPacketSeq, + prTxDone->ucStatus, + apucTxResultStr[prTxDone->ucStatus], + prTxDone->u2SequenceNumber, prTxDone->ucTid, + prTxDone->ucTxCount, prTxDone->ucFlushReason); + else + DBGLOG(NIC, TRACE, + "EVENT_ID_TX_DONE WIDX:PID[%u:%u] Status[%u:%s] SN[%u] TID[%u] CNT[%u] Flush[%u]\n", + prTxDone->ucWlanIndex, prTxDone->ucPacketSeq, + prTxDone->ucStatus, + apucTxResultStr[prTxDone->ucStatus], + prTxDone->u2SequenceNumber, prTxDone->ucTid, + prTxDone->ucTxCount, prTxDone->ucFlushReason); + + if (prTxDone->ucFlag & BIT(TXS_IS_EXIST)) { + uint8_t ucNss, ucStbc; + int8_t icTxPwr; + uint32_t *pu4RawTxs = + (uint32_t *)&prTxDone->aucRawTxS[0]; + + ucNss = (prTxDone->u2TxRate & TX_DESC_NSTS_MASK) >> + TX_DESC_NSTS_OFFSET; + ucNss += 1; + ucStbc = (prTxDone->u2TxRate & TX_DESC_STBC) ? + TRUE : FALSE; + + if (ucStbc) + ucNss /= 2; + + if (prTxDone->ucStatus != 0) + DBGLOG_LIMITED(NIC, INFO, + "||RATE[0x%04x] BW[%s] NSS[%u] ArIdx[%u] RspRate[0x%02x]\n", + prTxDone->u2TxRate, + apucBandwidt[prTxDone->ucBandwidth], + ucNss, + prTxDone->ucRateTableIdx, + prTxDone->ucRspRate); + else + DBGLOG(NIC, TRACE, + "||RATE[0x%04x] BW[%s] NSS[%u] ArIdx[%u] RspRate[0x%02x]\n", + prTxDone->u2TxRate, + apucBandwidt[prTxDone->ucBandwidth], + ucNss, + prTxDone->ucRateTableIdx, + prTxDone->ucRspRate); + icTxPwr = (int8_t)prTxDone->ucTxPower; + if (icTxPwr & BIT(6)) + icTxPwr |= BIT(7); + + if (prTxDone->ucStatus != 0) + DBGLOG_LIMITED(NIC, INFO, + "||AMPDU[%u] PS[%u] IBF[%u] EBF[%u] TxPwr[%d%sdBm] TSF[%u] TxDelay[%uus]\n", + prTxDone->u4AppliedFlag & + BIT(TX_FRAME_IN_AMPDU_FORMAT) ? + TRUE : FALSE, + prTxDone->u4AppliedFlag & + BIT(TX_FRAME_PS_BIT) ? TRUE : FALSE, + prTxDone->u4AppliedFlag & + BIT(TX_FRAME_IMP_BF) ? TRUE : FALSE, + prTxDone->u4AppliedFlag & + BIT(TX_FRAME_EXP_BF) ? TRUE : FALSE, + icTxPwr / 2, icTxPwr & BIT(0) ? + ".5" : "", + prTxDone->u4Timestamp, + prTxDone->u4TxDelay); + else + DBGLOG(NIC, TRACE, + "||AMPDU[%u] PS[%u] IBF[%u] EBF[%u] TxPwr[%d%sdBm] TSF[%u] TxDelay[%uus]\n", + prTxDone->u4AppliedFlag & + BIT(TX_FRAME_IN_AMPDU_FORMAT) ? + TRUE : FALSE, + prTxDone->u4AppliedFlag & + BIT(TX_FRAME_PS_BIT) ? TRUE : FALSE, + prTxDone->u4AppliedFlag & + BIT(TX_FRAME_IMP_BF) ? TRUE : FALSE, + prTxDone->u4AppliedFlag & + BIT(TX_FRAME_EXP_BF) ? TRUE : FALSE, + icTxPwr / 2, icTxPwr & BIT(0) ? + ".5" : "", + prTxDone->u4Timestamp, + prTxDone->u4TxDelay); + if (prTxDone->ucStatus != 0) + DBGLOG_LIMITED(NIC, INFO, + "TxS[%08x %08x %08x %08x %08x %08x %08x]\n", + *pu4RawTxs, + *(pu4RawTxs + 1), *(pu4RawTxs + 2), + *(pu4RawTxs + 3), *(pu4RawTxs + 4), + *(pu4RawTxs + 5), *(pu4RawTxs + 6)); + else + DBGLOG(NIC, TRACE, + "TxS[%08x %08x %08x %08x %08x %08x %08x]\n", + *pu4RawTxs, + *(pu4RawTxs + 1), *(pu4RawTxs + 2), + *(pu4RawTxs + 3), *(pu4RawTxs + 4), + *(pu4RawTxs + 5), *(pu4RawTxs + 6)); + } + } else { + DBGLOG(NIC, TRACE, + "EVENT_ID_TX_DONE WIDX:PID[%u:%u] Status[%u:%s] SN[%u]\n", + prTxDone->ucWlanIndex, prTxDone->ucPacketSeq, + prTxDone->ucStatus, + apucTxResultStr[prTxDone->ucStatus], + prTxDone->u2SequenceNumber); + } + + /* call related TX Done Handler */ + prMsduInfo = nicGetPendingTxMsduInfo(prAdapter, + prTxDone->ucWlanIndex, + prTxDone->ucPacketSeq); + +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT + DBGLOG(NIC, 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 ENUM_TX_RESULT_CODE) (prTxDone->ucStatus)); + + if (prMsduInfo->eSrc == TX_PACKET_MGMT) + cnmMgtPktFree(prAdapter, prMsduInfo); +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + else if (prMsduInfo->prToken) + prMsduInfo->pfTxDoneHandler = NULL; +#endif + else { + nicTxFreePacket(prAdapter, prMsduInfo, FALSE); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxEnqueueMsdu(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct TX_CTRL *prTxCtrl; + struct MSDU_INFO *prNextMsduInfo, *prRetMsduInfo, + *prMsduInfoHead; + struct QUE qDataPort0, qDataPort1; + struct QUE *prDataPort0, *prDataPort1; + struct CMD_INFO *prCmdInfo; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + prDataPort0 = &qDataPort0; + prDataPort1 = &qDataPort1; + + QUEUE_INITIALIZE(prDataPort0); + QUEUE_INITIALIZE(prDataPort1); + + /* check how many management frame are being queued */ + while (prMsduInfo) { + prNextMsduInfo = (struct MSDU_INFO *) QUEUE_GET_NEXT_ENTRY(( + struct QUE_ENTRY *) prMsduInfo); + + QUEUE_GET_NEXT_ENTRY((struct QUE_ENTRY *) prMsduInfo) = + NULL; + + if (prMsduInfo->eSrc == TX_PACKET_MGMT) { + if (nicTxProcessMngPacket(prAdapter, prMsduInfo)) { + /* Valid MGMT */ + QUEUE_INSERT_TAIL(prDataPort1, + (struct QUE_ENTRY *) + prMsduInfo); + } else { + /* Invalid MGMT */ + DBGLOG(TX, WARN, + "Invalid MGMT[0x%p] BSS[%u] STA[%u],free it\n", + prMsduInfo, prMsduInfo->ucBssIndex, + prMsduInfo->ucStaRecIndex); + + cnmMgtPktFree(prAdapter, prMsduInfo); + } + } else { + QUEUE_INSERT_TAIL(prDataPort0, + (struct QUE_ENTRY *) prMsduInfo); + } + + prMsduInfo = prNextMsduInfo; + } + + if (prDataPort0->u4NumElem) { + /* send to QM */ + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + prRetMsduInfo = qmEnqueueTxPackets(prAdapter, + (struct MSDU_INFO *) QUEUE_GET_HEAD(prDataPort0)); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + + /* post-process for dropped packets */ + if (prRetMsduInfo) { /* unable to enqueue */ + nicTxFreeMsduInfoPacket(prAdapter, prRetMsduInfo); + nicTxReturnMsduInfo(prAdapter, prRetMsduInfo); + } + } + + if (prDataPort1->u4NumElem) { + prMsduInfoHead = (struct MSDU_INFO *) QUEUE_GET_HEAD( + prDataPort1); + + if (nicTxGetFreeCmdCount(prAdapter) < + NIC_TX_CMD_INFO_RESERVED_COUNT) { + /* not enough descriptors for sending */ + u4Status = WLAN_STATUS_FAILURE; + + /* free all MSDUs */ + while (prMsduInfoHead) { + prNextMsduInfo = + (struct MSDU_INFO *) + 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 = + (struct MSDU_INFO *) + QUEUE_GET_NEXT_ENTRY( + &prMsduInfoHead->rQueEntry); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, + SPIN_LOCK_CMD_RESOURCE); + QUEUE_REMOVE_HEAD( + &prAdapter->rFreeCmdList, + prCmdInfo, + struct CMD_INFO *); + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_CMD_RESOURCE); + + if (prCmdInfo) { + GLUE_INC_REF_CNT( + prTxCtrl->i4TxMgmtPendingNum); + + kalMemZero(prCmdInfo, + sizeof(struct CMD_INFO)); + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + /* Tag MGMT enqueue time */ + GET_CURRENT_SYSTIME( + &prMsduInfoHead-> + rPktProfile.rEnqueueTimestamp); +#endif + prCmdInfo->eCmdType = + COMMAND_TYPE_MANAGEMENT_FRAME; + prCmdInfo->u2InfoBufLen = + prMsduInfoHead->u2FrameLength; + prCmdInfo->pucInfoBuffer = NULL; + prCmdInfo->prMsduInfo = prMsduInfoHead; + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->pfCmdTimeoutHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->ucCmdSeqNum = + prMsduInfoHead->ucTxSeqNum; + + DBGLOG(TX, TRACE, + "%s: EN-Q MSDU[0x%p] SEQ[%u] BSS[%u] STA[%u] to CMD Q\n", + __func__, prMsduInfoHead, + prMsduInfoHead->ucTxSeqNum, + prMsduInfoHead->ucBssIndex, + prMsduInfoHead->ucStaRecIndex); + + kalEnqueueCommand(prAdapter->prGlueInfo, + (struct QUE_ENTRY *) prCmdInfo); + } else { + /* Cmd free count is larger than + * expected, but allocation fail. + */ + u4Status = WLAN_STATUS_FAILURE; + + if (prMsduInfoHead->pfTxDoneHandler + != NULL) { + prMsduInfoHead->pfTxDoneHandler( + prAdapter, + prMsduInfoHead, + TX_RESULT_DROPPED_IN_DRIVER); + } + + 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 WLAN index + * + * @param prAdapter Pointer to the Adapter structure. + * + * @retval + */ +/*----------------------------------------------------------------------------*/ +uint8_t nicTxGetWlanIdx(struct ADAPTER *prAdapter, + uint8_t ucBssIdx, uint8_t ucStaRecIdx) +{ + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + uint8_t ucWlanIndex = prAdapter->ucTxDefaultWlanIndex; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIdx); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + + if (prStaRec) + ucWlanIndex = prStaRec->ucWlanIndex; + else if ((ucStaRecIdx == STA_REC_INDEX_BMCAST) + && prBssInfo->fgIsInUse) { + if (prBssInfo->fgBcDefaultKeyExist) { + if (prBssInfo->wepkeyUsed[prBssInfo->ucBcDefaultKeyIdx] + && prBssInfo->wepkeyWlanIdx + < prAdapter->ucTxDefaultWlanIndex) + ucWlanIndex = prBssInfo->wepkeyWlanIdx; + else if (prBssInfo->ucBMCWlanIndexSUsed[ + prBssInfo->ucBcDefaultKeyIdx]) + ucWlanIndex = + prBssInfo->ucBMCWlanIndexS[ + prBssInfo->ucBcDefaultKeyIdx]; + } else + ucWlanIndex = prBssInfo->ucBMCWlanIndex; + } + + if (ucWlanIndex >= WTBL_SIZE) { + DBGLOG(TX, WARN, + "Unexpected WIDX[%u] BSS[%u] STA[%u], set WIDX to default value[%u]\n", + ucWlanIndex, ucBssIdx, ucStaRecIdx, + prAdapter->ucTxDefaultWlanIndex); + + ucWlanIndex = prAdapter->ucTxDefaultWlanIndex; + } + + return ucWlanIndex; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * @param prAdapter Pointer to the Adapter structure. + * + * @retval + */ +/*----------------------------------------------------------------------------*/ +u_int8_t nicTxIsMgmtResourceEnough(IN struct ADAPTER + *prAdapter) +{ + if (nicTxGetFreeCmdCount(prAdapter) > + (CFG_TX_MAX_CMD_PKT_NUM / 2)) + return TRUE; + else + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief this function returns available count in command queue + * + * @param prAdapter Pointer to the Adapter structure. + * + * @retval + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxGetFreeCmdCount(IN struct ADAPTER *prAdapter) +{ + ASSERT(prAdapter); + + return prAdapter->rFreeCmdList.u4NumElem; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief this function returns page count of frame + * + * @param prAdapter Pointer to the Adapter structure. + * @param u4FrameLength frame length + * + * @retval page count of this frame + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxGetPageCount(IN struct ADAPTER *prAdapter, + IN uint32_t u4FrameLength, IN u_int8_t fgIncludeDesc) +{ + return halTxGetPageCount(prAdapter, u4FrameLength, + fgIncludeDesc); +} + +uint32_t nicTxGetCmdPageCount(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo) +{ + uint32_t u4PageCount; + + switch (prCmdInfo->eCmdType) { + case COMMAND_TYPE_NETWORK_IOCTL: + case COMMAND_TYPE_GENERAL_IOCTL: + u4PageCount = nicTxGetPageCount(prAdapter, + prCmdInfo->u2InfoBufLen, TRUE); + break; + + case COMMAND_TYPE_SECURITY_FRAME: + case COMMAND_TYPE_MANAGEMENT_FRAME: + /* No TxD append field for management packet */ + u4PageCount = nicTxGetPageCount(prAdapter, + prCmdInfo->u2InfoBufLen + + NIC_TX_DESC_LONG_FORMAT_LENGTH, + TRUE); + break; + + default: + DBGLOG(INIT, WARN, "Undefined CMD Type(%u)\n", + prCmdInfo->eCmdType); + u4PageCount = nicTxGetPageCount(prAdapter, + prCmdInfo->u2InfoBufLen, FALSE); + break; + } + + return u4PageCount; +} + +void nicTxSetMngPacket(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + uint8_t ucBssIndex, uint8_t ucStaRecIndex, + uint8_t ucMacHeaderLength, + uint16_t u2FrameLength, + PFN_TX_DONE_HANDLER pfTxDoneHandler, + uint8_t ucRateMode) +{ + ASSERT(prMsduInfo); + + prMsduInfo->ucBssIndex = ucBssIndex; + prMsduInfo->ucStaRecIndex = ucStaRecIndex; + prMsduInfo->ucMacHeaderLength = ucMacHeaderLength; + prMsduInfo->u2FrameLength = u2FrameLength; + prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; + prMsduInfo->ucRateMode = ucRateMode; + + /* Reset default value for MMPDU */ + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_1x_NonProtected = + TRUE; /*For data frame only, no sense for management frame*/ + prMsduInfo->u4FixedRateOption = 0; + prMsduInfo->cPowerOffset = 0; + prMsduInfo->u4Option = 0; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->ucPID = NIC_TX_DESC_PID_RESERVED; + prMsduInfo->ucPacketType = TX_PACKET_TYPE_MGMT; + prMsduInfo->ucUserPriority = 0; + prMsduInfo->eSrc = TX_PACKET_MGMT; +} + +void nicTxSetDataPacket(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + uint8_t ucBssIndex, uint8_t ucStaRecIndex, + uint8_t ucMacHeaderLength, + uint16_t u2FrameLength, PFN_TX_DONE_HANDLER pfTxDoneHandler, + uint8_t ucRateMode, enum ENUM_TX_PACKET_SRC eSrc, + uint8_t ucTID, + u_int8_t fgIs802_11Frame, u_int8_t fgIs1xFrame) +{ + ASSERT(prMsduInfo); + + prMsduInfo->ucBssIndex = ucBssIndex; + prMsduInfo->ucStaRecIndex = ucStaRecIndex; + prMsduInfo->ucMacHeaderLength = ucMacHeaderLength; + prMsduInfo->u2FrameLength = u2FrameLength; + prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; + prMsduInfo->ucRateMode = ucRateMode; + prMsduInfo->ucUserPriority = ucTID; + prMsduInfo->fgIs802_11 = fgIs802_11Frame; + prMsduInfo->eSrc = eSrc; + prMsduInfo->fgIs802_1x = fgIs1xFrame; + + /* Reset default value for data packet */ + prMsduInfo->u4FixedRateOption = 0; + prMsduInfo->cPowerOffset = 0; + prMsduInfo->u4Option = 0; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->ucPID = NIC_TX_DESC_PID_RESERVED; + prMsduInfo->ucPacketType = TX_PACKET_TYPE_DATA; +} + +void nicTxFillDescByPktOption(struct MSDU_INFO *prMsduInfo, + struct HW_MAC_TX_DESC *prTxDesc) +{ + uint32_t u4PktOption = prMsduInfo->u4Option; + u_int8_t fgIsLongFormat; + u_int8_t fgProtected = FALSE; + + /* Skip this function if no options is set */ + if (!u4PktOption) + return; + + fgIsLongFormat = HAL_MAC_TX_DESC_IS_LONG_FORMAT(prTxDesc); + + /* Fields in DW0 and DW1 (Short Format) */ + if (u4PktOption & MSDU_OPT_NO_ACK) + HAL_MAC_TX_DESC_SET_NO_ACK(prTxDesc); + + if (u4PktOption & MSDU_OPT_PROTECTED_FRAME) { + /* DBGLOG(RSN, INFO, "MSDU_OPT_PROTECTED_FRAME\n"); */ + HAL_MAC_TX_DESC_SET_PROTECTION(prTxDesc); + fgProtected = TRUE; + } + + switch (HAL_MAC_TX_DESC_GET_HEADER_FORMAT(prTxDesc)) { + case HEADER_FORMAT_802_11_ENHANCE_MODE: + if (u4PktOption & MSDU_OPT_EOSP) + HAL_MAC_TX_DESC_SET_EOSP(prTxDesc); + + if (u4PktOption & MSDU_OPT_AMSDU) + HAL_MAC_TX_DESC_SET_AMSDU(prTxDesc); + break; + + case HEADER_FORMAT_NON_802_11: + if (u4PktOption & MSDU_OPT_EOSP) + HAL_MAC_TX_DESC_SET_EOSP(prTxDesc); + + if (u4PktOption & MSDU_OPT_MORE_DATA) + HAL_MAC_TX_DESC_SET_MORE_DATA(prTxDesc); + + if (u4PktOption & MSDU_OPT_REMOVE_VLAN) + HAL_MAC_TX_DESC_SET_REMOVE_VLAN(prTxDesc); + break; + + case HEADER_FORMAT_802_11_NORMAL_MODE: + if (fgProtected && prMsduInfo->prPacket) { + struct WLAN_MAC_HEADER *prWlanHeader = + (struct WLAN_MAC_HEADER *) ((unsigned long) ( + prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prWlanHeader->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + } + break; + + default: + break; + } + + if (!fgIsLongFormat) + return; + + /* Fields in DW2~6 (Long Format) */ + if (u4PktOption & MSDU_OPT_NO_AGGREGATE) + HAL_MAC_TX_DESC_SET_BA_DISABLE(prTxDesc); + + if (u4PktOption & MSDU_OPT_TIMING_MEASURE) + HAL_MAC_TX_DESC_SET_TIMING_MEASUREMENT(prTxDesc); + + if (u4PktOption & MSDU_OPT_NDP) + HAL_MAC_TX_DESC_SET_NDP(prTxDesc); + + if (u4PktOption & MSDU_OPT_NDPA) + HAL_MAC_TX_DESC_SET_NDPA(prTxDesc); + + if (u4PktOption & MSDU_OPT_SOUNDING) + HAL_MAC_TX_DESC_SET_SOUNDING_FRAME(prTxDesc); + + if (u4PktOption & MSDU_OPT_FORCE_RTS) + HAL_MAC_TX_DESC_SET_FORCE_RTS_CTS(prTxDesc); + + if (u4PktOption & MSDU_OPT_BIP) + HAL_MAC_TX_DESC_SET_BIP(prTxDesc); + + /* SW field */ + if (u4PktOption & MSDU_OPT_SW_DURATION) + HAL_MAC_TX_DESC_SET_DURATION_CONTROL_BY_SW(prTxDesc); + + if (u4PktOption & MSDU_OPT_SW_PS_BIT) + HAL_MAC_TX_DESC_SET_SW_PM_CONTROL(prTxDesc); + + if (u4PktOption & MSDU_OPT_SW_HTC) + HAL_MAC_TX_DESC_SET_HTC_EXIST(prTxDesc); +#if 0 + if (u4PktOption & MSDU_OPT_SW_BAR_SN) + HAL_MAC_TX_DESC_SET_SW_BAR_SSN(prTxDesc); +#endif + if (u4PktOption & MSDU_OPT_MANUAL_SN) { + HAL_MAC_TX_DESC_SET_TXD_SN_VALID(prTxDesc); + HAL_MAC_TX_DESC_SET_SEQUENCE_NUMBER(prTxDesc, + prMsduInfo->u2SwSN); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Extra configuration for Tx packet + * + * @retval + */ +/*----------------------------------------------------------------------------*/ +void nicTxConfigPktOption(struct MSDU_INFO *prMsduInfo, + uint32_t u4OptionMask, u_int8_t fgSetOption) +{ + if (fgSetOption) + prMsduInfo->u4Option |= u4OptionMask; + else + prMsduInfo->u4Option &= ~u4OptionMask; +} + +void nicTxFillDescByPktControl(struct MSDU_INFO *prMsduInfo, + struct HW_MAC_TX_DESC *prTxDesc) +{ + uint8_t ucPktControl = prMsduInfo->ucControlFlag; + uint8_t ucSwReserved; + + /* Skip this function if no options is set */ + if (!ucPktControl) + return; + + if (HAL_MAC_TX_DESC_IS_LONG_FORMAT(prTxDesc)) { + ucSwReserved = HAL_MAC_TX_DESC_GET_SW_RESERVED(prTxDesc); + + if (ucPktControl & MSDU_CONTROL_FLAG_FORCE_TX) + ucSwReserved |= MSDU_CONTROL_FLAG_FORCE_TX; + + HAL_MAC_TX_DESC_SET_SW_RESERVED(prTxDesc, ucSwReserved); + } +} + +void nicTxConfigPktControlFlag(struct MSDU_INFO *prMsduInfo, + uint8_t ucControlFlagMask, u_int8_t fgSetFlag) +{ + /* Set control flag */ + if (fgSetFlag) + prMsduInfo->ucControlFlag |= ucControlFlagMask; + else + prMsduInfo->ucControlFlag &= + ~ucControlFlagMask; /* Clear control flag */ +} + +void nicTxSetPktLifeTime(struct MSDU_INFO *prMsduInfo, + uint32_t u4TxLifeTimeInMs) +{ + prMsduInfo->u4RemainingLifetime = u4TxLifeTimeInMs; + prMsduInfo->u4Option |= MSDU_OPT_MANUAL_LIFE_TIME; +} + +void nicTxSetPktRetryLimit(struct MSDU_INFO *prMsduInfo, + uint8_t ucRetryLimit) +{ + prMsduInfo->ucRetryLimit = ucRetryLimit; + prMsduInfo->u4Option |= MSDU_OPT_MANUAL_RETRY_LIMIT; +} + +void nicTxSetPktPowerOffset(struct MSDU_INFO *prMsduInfo, + int8_t cPowerOffset) +{ + prMsduInfo->cPowerOffset = cPowerOffset; + prMsduInfo->u4Option |= MSDU_OPT_MANUAL_POWER_OFFSET; +} + +void nicTxSetPktSequenceNumber(struct MSDU_INFO *prMsduInfo, + uint16_t u2SN) +{ + prMsduInfo->u2SwSN = u2SN; + prMsduInfo->u4Option |= MSDU_OPT_MANUAL_SN; +} + +void nicTxSetPktMacTxQue(struct MSDU_INFO *prMsduInfo, + uint8_t ucMacTxQue) +{ + uint8_t ucTcIdx; + + for (ucTcIdx = TC0_INDEX; ucTcIdx < TC_NUM; ucTcIdx++) { + if (arTcResourceControl[ucTcIdx].ucDestQueueIndex == + ucMacTxQue) + break; + } + + if (ucTcIdx < TC_NUM) { + prMsduInfo->ucTC = ucTcIdx; + prMsduInfo->u4Option |= MSDU_OPT_MANUAL_TX_QUE; + } +} + +void nicTxSetPktFixedRateOptionFull(struct MSDU_INFO + *prMsduInfo, + uint16_t u2RateCode, + uint8_t ucBandwidth, + u_int8_t fgShortGI, + u_int8_t fgLDPC, + u_int8_t fgDynamicBwRts, u_int8_t fgBeamforming, + uint8_t ucAntennaIndex) +{ + struct HW_MAC_TX_DESC rTxDesc; + struct HW_MAC_TX_DESC *prTxDesc = &rTxDesc; + + kalMemZero(prTxDesc, NIC_TX_DESC_LONG_FORMAT_LENGTH); + + /* Follow the format of Tx descriptor DW 6 */ + HAL_MAC_TX_DESC_SET_FR_RATE(prTxDesc, u2RateCode); + + if (ucBandwidth) + HAL_MAC_TX_DESC_SET_FR_BW(prTxDesc, ucBandwidth); + + if (fgBeamforming) + HAL_MAC_TX_DESC_SET_FR_BF(prTxDesc); + + if (fgShortGI) + HAL_MAC_TX_DESC_SET_FR_SHORT_GI(prTxDesc); + + if (fgLDPC) + HAL_MAC_TX_DESC_SET_FR_LDPC(prTxDesc); + + if (fgDynamicBwRts) + HAL_MAC_TX_DESC_SET_FR_DYNAMIC_BW_RTS(prTxDesc); + + HAL_MAC_TX_DESC_SET_FR_ANTENNA_ID(prTxDesc, ucAntennaIndex); + + /* Write back to RateOption of MSDU_INFO */ + HAL_MAC_TX_DESC_GET_DW(prTxDesc, 6, 1, + &prMsduInfo->u4FixedRateOption); + + prMsduInfo->ucRateMode = MSDU_RATE_MODE_MANUAL_DESC; + +} + +void nicTxSetPktFixedRateOption(struct MSDU_INFO + *prMsduInfo, + uint16_t u2RateCode, uint8_t ucBandwidth, + u_int8_t fgShortGI, u_int8_t fgDynamicBwRts) +{ + struct HW_MAC_TX_DESC rTxDesc; + struct HW_MAC_TX_DESC *prTxDesc = &rTxDesc; + + kalMemZero(prTxDesc, NIC_TX_DESC_LONG_FORMAT_LENGTH); + + /* Follow the format of Tx descriptor DW 6 */ + HAL_MAC_TX_DESC_SET_FR_RATE(prTxDesc, u2RateCode); + + if (ucBandwidth) + HAL_MAC_TX_DESC_SET_FR_BW(prTxDesc, ucBandwidth); + + if (fgShortGI) + HAL_MAC_TX_DESC_SET_FR_SHORT_GI(prTxDesc); + + if (fgDynamicBwRts) + HAL_MAC_TX_DESC_SET_FR_DYNAMIC_BW_RTS(prTxDesc); + + /* Write back to RateOption of MSDU_INFO */ + HAL_MAC_TX_DESC_GET_DW(prTxDesc, 6, 1, + &prMsduInfo->u4FixedRateOption); + + prMsduInfo->ucRateMode = MSDU_RATE_MODE_MANUAL_DESC; + +} + +void nicTxSetPktLowestFixedRate(IN struct ADAPTER + *prAdapter, IN struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo = GET_BSS_INFO_BY_INDEX( + prAdapter, prMsduInfo->ucBssIndex); + struct STA_RECORD *prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + uint8_t ucRateSwIndex, ucRateIndex, ucRatePreamble; + uint16_t u2RateCode, u2RateCodeLimit, u2OperationalRateSet; + uint32_t u4CurrentPhyRate, u4Status; + + /* Not to use TxD template for fixed rate */ + prMsduInfo->fgIsTXDTemplateValid = FALSE; + + /* Fixed Rate */ + prMsduInfo->ucRateMode = MSDU_RATE_MODE_MANUAL_DESC; + + if (prStaRec) { + u2RateCode = prStaRec->u2HwDefaultFixedRateCode; + u2OperationalRateSet = prStaRec->u2OperationalRateSet; + } else { + u2RateCode = prBssInfo->u2HwDefaultFixedRateCode; + u2OperationalRateSet = prBssInfo->u2OperationalRateSet; + } + + /* CoexPhyRateLimit is 0 means phy rate is unlimited */ + if (prBssInfo->u4CoexPhyRateLimit != 0) { + + u4CurrentPhyRate = nicRateCode2PhyRate(u2RateCode, + FIX_BW_NO_FIXED, MAC_GI_NORMAL, AR_SS_NULL); + + if (prBssInfo->u4CoexPhyRateLimit > u4CurrentPhyRate) { + nicGetRateIndexFromRateSetWithLimit( + u2OperationalRateSet, + prBssInfo->u4CoexPhyRateLimit, + TRUE, &ucRateSwIndex); + + /* Convert SW rate index to rate code */ + nicSwIndex2RateIndex(ucRateSwIndex, &ucRateIndex, + &ucRatePreamble); + u4Status = nicRateIndex2RateCode(ucRatePreamble, + ucRateIndex, &u2RateCodeLimit); + if (u4Status == WLAN_STATUS_SUCCESS) { + /* Replace by limitation rate */ + u2RateCode = u2RateCodeLimit; + DBGLOG(NIC, INFO, + "Coex RatePreamble=%d, R_SW_IDX:%d, R_CODE:0x%x\n", + ucRatePreamble, ucRateIndex, u2RateCode); + } + } + } + nicTxSetPktFixedRateOption(prMsduInfo, u2RateCode, + FIX_BW_NO_FIXED, FALSE, FALSE); +} + +void nicTxSetPktMoreData(struct MSDU_INFO + *prCurrentMsduInfo, u_int8_t fgSetMoreDataBit) +{ + struct WLAN_MAC_HEADER *prWlanMacHeader = NULL; + + if (prCurrentMsduInfo->fgIs802_11) { + prWlanMacHeader = + (struct WLAN_MAC_HEADER *) (((uint8_t *) ( + prCurrentMsduInfo->prPacket)) + MAC_TX_RESERVED_FIELD); + } + + if (fgSetMoreDataBit) { + if (!prCurrentMsduInfo->fgIs802_11) + prCurrentMsduInfo->u4Option |= MSDU_OPT_MORE_DATA; + else + prWlanMacHeader->u2FrameCtrl |= MASK_FC_MORE_DATA; + } else { + if (!prCurrentMsduInfo->fgIs802_11) + prCurrentMsduInfo->u4Option &= ~MSDU_OPT_MORE_DATA; + else + prWlanMacHeader->u2FrameCtrl &= ~MASK_FC_MORE_DATA; + } +} + +uint8_t nicTxAssignPID(IN struct ADAPTER *prAdapter, + IN uint8_t ucWlanIndex) +{ + uint8_t ucRetval; + uint8_t *pucPidPool; + + ASSERT(prAdapter); + + pucPidPool = &prAdapter->aucPidPool[ucWlanIndex]; + + ucRetval = *pucPidPool; + + /* Driver side Tx Sequence number: 1~127 */ + (*pucPidPool)++; + + if (*pucPidPool > NIC_TX_DESC_DRIVER_PID_MAX) + *pucPidPool = NIC_TX_DESC_DRIVER_PID_MIN; + + return ucRetval; +} + +void nicTxSetPktEOSP(struct MSDU_INFO *prCurrentMsduInfo, + u_int8_t fgSetEOSPBit) +{ + struct WLAN_MAC_HEADER_QOS *prWlanMacHeader = NULL; + u_int8_t fgWriteToDesc = TRUE; + + if (prCurrentMsduInfo->fgIs802_11) { + prWlanMacHeader = + (struct WLAN_MAC_HEADER_QOS *) (((uint8_t *) ( + prCurrentMsduInfo->prPacket)) + MAC_TX_RESERVED_FIELD); + fgWriteToDesc = FALSE; + } + + if (fgSetEOSPBit) { + if (fgWriteToDesc) + prCurrentMsduInfo->u4Option |= MSDU_OPT_EOSP; + else + prWlanMacHeader->u2QosCtrl |= MASK_QC_EOSP; + } else { + if (fgWriteToDesc) + prCurrentMsduInfo->u4Option &= ~MSDU_OPT_EOSP; + else + prWlanMacHeader->u2QosCtrl &= ~MASK_QC_EOSP; + } +} + +uint32_t +nicTxDummyTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + struct PERF_MONITOR_T *prPerMonitor = &prAdapter->rPerMonitor; + + if (rTxDoneStatus == 0) { + prPerMonitor->ulTotalTxSuccessCount++; + } else { + DBGLOG(TX, INFO, + "Msdu WIDX:PID[%u:%u] SEQ[%u] Tx Status[%u]\n", + prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, + prMsduInfo->ucTxSeqNum, rTxDoneStatus); + prPerMonitor->ulTotalTxFailCount++; + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Update BSS Tx Params + * + * @param prStaRec The peer + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicTxUpdateBssDefaultRate(struct BSS_INFO *prBssInfo) +{ + uint8_t ucLowestBasicRateIndex; + + prBssInfo->u2HwDefaultFixedRateCode = RATE_OFDM_6M; + + /* 4 <1> Find Lowest Basic Rate Index for default TX Rate of MMPDU */ + if (rateGetLowestRateIndexFromRateSet( + prBssInfo->u2BSSBasicRateSet, &ucLowestBasicRateIndex)) { + nicRateIndex2RateCode(PREAMBLE_DEFAULT_LONG_NONE, + ucLowestBasicRateIndex, + &prBssInfo->u2HwDefaultFixedRateCode); + } else { + switch (prBssInfo->ucNonHTBasicPhyType) { + case PHY_TYPE_ERP_INDEX: + case PHY_TYPE_OFDM_INDEX: + prBssInfo->u2HwDefaultFixedRateCode = RATE_OFDM_6M; + break; + + default: + prBssInfo->u2HwDefaultFixedRateCode = RATE_CCK_1M_LONG; + break; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Update StaRec Tx parameters + * + * @param prStaRec The peer + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void nicTxUpdateStaRecDefaultRate(struct STA_RECORD + *prStaRec) +{ + uint8_t ucLowestBasicRateIndex; + + prStaRec->u2HwDefaultFixedRateCode = RATE_OFDM_6M; + + /* 4 <1> Find Lowest Basic Rate Index for default TX Rate of MMPDU */ + if (rateGetLowestRateIndexFromRateSet( + prStaRec->u2BSSBasicRateSet, &ucLowestBasicRateIndex)) { + nicRateIndex2RateCode(PREAMBLE_DEFAULT_LONG_NONE, + ucLowestBasicRateIndex, + &prStaRec->u2HwDefaultFixedRateCode); + } else { + if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11B) + prStaRec->u2HwDefaultFixedRateCode = RATE_CCK_1M_LONG; + else if (prStaRec->ucDesiredPhyTypeSet & + PHY_TYPE_SET_802_11G) + prStaRec->u2HwDefaultFixedRateCode = RATE_OFDM_6M; + else if (prStaRec->ucDesiredPhyTypeSet & + PHY_TYPE_SET_802_11A) + prStaRec->u2HwDefaultFixedRateCode = RATE_OFDM_6M; + else if (prStaRec->ucDesiredPhyTypeSet & + PHY_TYPE_SET_802_11N) + prStaRec->u2HwDefaultFixedRateCode = RATE_MM_MCS_0; + } +} + +void nicTxCancelSendingCmd(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo) +{ + halTxCancelSendingCmd(prAdapter, prCmdInfo); +} + +uint32_t nicTxGetMaxPageCntPerFrame(IN struct ADAPTER + *prAdapter) +{ + uint32_t page_size = halGetHifTxPageSize(prAdapter); + + /* + * want to replace + * #define NIC_TX_MAX_PAGE_PER_FRAME \ + * ((NIC_TX_DESC_AND_PADDING_LENGTH + + * NIC_TX_DESC_HEADER_PADDING_LENGTH + \ + * NIC_TX_MAX_SIZE_PER_FRAME + NIC_TX_PAGE_SIZE - 1) + * / NIC_TX_PAGE_SIZE) + */ + + return ((NIC_TX_DESC_AND_PADDING_LENGTH + + NIC_TX_DESC_HEADER_PADDING_LENGTH + + NIC_TX_MAX_SIZE_PER_FRAME + page_size - 1) / page_size); +} + +/* TX Direct functions : BEGIN */ + +/*----------------------------------------------------------------------------*/ +/* + * \brief This function is to start rTxDirectHifTimer to try to + * send out packets in + * rStaPsQueue[], rBssAbsentQueue[], rTxDirectHifQueue[]. + * + * \param[in] prAdapter Pointer of Adapter + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +void nicTxDirectStartCheckQTimer(IN struct ADAPTER + *prAdapter) +{ + mod_timer(&prAdapter->rTxDirectHifTimer, jiffies + 1); +} + +void nicTxDirectClearSkbQ(IN struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct sk_buff *prSkb; + + while (TRUE) { + spin_lock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + prSkb = skb_dequeue(&prAdapter->rTxDirectSkbQueue); + spin_unlock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + if (prSkb == NULL) + break; + + kalSendComplete(prGlueInfo, prSkb, + WLAN_STATUS_NOT_ACCEPTED); + } +} + +void nicTxDirectClearHifQ(IN struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + uint8_t ucHifTc = 0; + struct QUE rNeedToFreeQue; + struct QUE *prNeedToFreeQue = &rNeedToFreeQue; + + QUEUE_INITIALIZE(prNeedToFreeQue); + + for (ucHifTc = 0; ucHifTc < TX_PORT_NUM; ucHifTc++) { + spin_lock_bh( + &prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + if (QUEUE_IS_NOT_EMPTY( + &prAdapter->rTxDirectHifQueue[ucHifTc])) { + QUEUE_MOVE_ALL(prNeedToFreeQue, + &prAdapter->rTxDirectHifQueue[ucHifTc]); + spin_unlock_bh( + &prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + + wlanProcessQueuedMsduInfo(prAdapter, + (struct MSDU_INFO *) + QUEUE_GET_HEAD(prNeedToFreeQue)); + } else { + spin_unlock_bh( + &prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + } + } +} + +void nicTxDirectClearStaPsQ(IN struct ADAPTER *prAdapter, + uint8_t ucStaRecIndex) +{ + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct QUE rNeedToFreeQue; + struct QUE *prNeedToFreeQue = &rNeedToFreeQue; + spinlock_t *prSpinLock = &prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]; + bool fgIrqDisabled = irqs_disabled(); + + QUEUE_INITIALIZE(prNeedToFreeQue); + if (fgIrqDisabled) + spin_lock(prSpinLock); + else + spin_lock_bh(prSpinLock); + if (QUEUE_IS_NOT_EMPTY( + &prAdapter->rStaPsQueue[ucStaRecIndex])) { + QUEUE_MOVE_ALL(prNeedToFreeQue, + &prAdapter->rStaPsQueue[ucStaRecIndex]); + if (fgIrqDisabled) + spin_unlock(prSpinLock); + else + spin_unlock_bh(prSpinLock); + + wlanProcessQueuedMsduInfo(prAdapter, + (struct MSDU_INFO *) QUEUE_GET_HEAD(prNeedToFreeQue)); + } else { + if (fgIrqDisabled) + spin_unlock(prSpinLock); + else + spin_unlock_bh(prSpinLock); + } +} + +void nicTxDirectClearBssAbsentQ(IN struct ADAPTER + *prAdapter, uint8_t ucBssIndex) +{ + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct QUE rNeedToFreeQue; + struct QUE *prNeedToFreeQue = &rNeedToFreeQue; + + QUEUE_INITIALIZE(prNeedToFreeQue); + spin_lock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + if (QUEUE_IS_NOT_EMPTY( + &prAdapter->rBssAbsentQueue[ucBssIndex])) { + QUEUE_MOVE_ALL(prNeedToFreeQue, + &prAdapter->rBssAbsentQueue[ucBssIndex]); + spin_unlock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + + wlanProcessQueuedMsduInfo(prAdapter, + (struct MSDU_INFO *) QUEUE_GET_HEAD(prNeedToFreeQue)); + } else { + spin_unlock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + } +} + +void nicTxDirectClearAllStaPsQ(IN struct ADAPTER *prAdapter) +{ + uint8_t ucStaRecIndex; + uint32_t u4StaPsBitmap; + + u4StaPsBitmap = prAdapter->u4StaPsBitmap; + + if (!u4StaPsBitmap) + return; + + for (ucStaRecIndex = 0; ucStaRecIndex < CFG_STA_REC_NUM; + ++ucStaRecIndex) { + if (QUEUE_IS_NOT_EMPTY( + &prAdapter->rStaPsQueue[ucStaRecIndex])) { + nicTxDirectClearStaPsQ(prAdapter, + ucStaRecIndex); + u4StaPsBitmap &= ~BIT(ucStaRecIndex); + } + if (u4StaPsBitmap == 0) + break; + } +} + +/*----------------------------------------------------------------------------*/ +/* + * \brief This function is to check the StaRec is in Ps or not, + * and store MsduInfo(s) or sent MsduInfo(s) to the next + * stage respectively. + * + * \param[in] prAdapter Pointer of Adapter + * \param[in] ucStaRecIndex Indictate which StaRec to be checked + * \param[in] prQue Pointer of MsduInfo queue which to be processed + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +static void nicTxDirectCheckStaPsQ(IN struct ADAPTER + *prAdapter, uint8_t ucStaRecIndex, struct QUE *prQue) +{ + struct STA_RECORD *prStaRec; /* The current focused STA */ + struct MSDU_INFO *prMsduInfo; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + u_int8_t fgReturnStaPsQ = FALSE; + + if (ucStaRecIndex >= CFG_STA_REC_NUM) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIndex); + + QUEUE_CONCATENATE_QUEUES( + &prAdapter->rStaPsQueue[ucStaRecIndex], prQue); + QUEUE_REMOVE_HEAD(&prAdapter->rStaPsQueue[ucStaRecIndex], + prQueueEntry, struct QUE_ENTRY *); + prMsduInfo = (struct MSDU_INFO *) prQueueEntry; + + if (prMsduInfo == NULL) { + DBGLOG(TX, INFO, "prMsduInfo empty\n"); + return; + } + + if (prStaRec == NULL) { + DBGLOG(TX, INFO, "prStaRec empty\n"); + return; + } + + if (prStaRec->fgIsInPS) { + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + DBGLOG(TX, INFO, "fgIsInPS!\n"); + while (1) { + if (prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported && + (prStaRec->ucBmpTriggerAC + & BIT(prMsduInfo->ucTC))) { + if (prStaRec->ucFreeQuotaForDelivery > 0) { + prStaRec->ucFreeQuotaForDelivery--; + QUEUE_INSERT_TAIL( + prQue, + (struct QUE_ENTRY *) + prMsduInfo); + } else { + fgReturnStaPsQ = TRUE; + break; + } + } else { + if (prStaRec->ucFreeQuotaForNonDelivery > 0) { + prStaRec->ucFreeQuotaForNonDelivery--; + QUEUE_INSERT_TAIL( + prQue, + (struct QUE_ENTRY *) + prMsduInfo); + } else { + fgReturnStaPsQ = TRUE; + break; + } + } + if (QUEUE_IS_NOT_EMPTY( + &prAdapter->rStaPsQueue[ucStaRecIndex])) { + QUEUE_REMOVE_HEAD( + &prAdapter->rStaPsQueue[ucStaRecIndex], + prQueueEntry, struct QUE_ENTRY *); + prMsduInfo = (struct MSDU_INFO *) prQueueEntry; + } else { + break; + } + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + if (fgReturnStaPsQ) { + QUEUE_INSERT_HEAD( + &prAdapter->rStaPsQueue[ucStaRecIndex], + (struct QUE_ENTRY *) prMsduInfo); + prAdapter->u4StaPsBitmap |= BIT(ucStaRecIndex); + return; + } + } else { + QUEUE_INSERT_TAIL(prQue, (struct QUE_ENTRY *) prMsduInfo); + if (QUEUE_IS_NOT_EMPTY( + &prAdapter->rStaPsQueue[ucStaRecIndex])) + QUEUE_CONCATENATE_QUEUES(prQue, + &prAdapter->rStaPsQueue[ucStaRecIndex]); + } + prAdapter->u4StaPsBitmap &= ~BIT(ucStaRecIndex); +} + +/*----------------------------------------------------------------------------*/ +/* + * \brief This function is to check the Bss is net absent or not, + * and store MsduInfo(s) or sent MsduInfo(s) to the next + * stage respectively. + * + * \param[in] prAdapter Pointer of Adapter + * \param[in] ucBssIndex Indictate which Bss to be checked + * \param[in] prQue Pointer of MsduInfo queue which to be processed + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +static void nicTxDirectCheckBssAbsentQ(IN struct ADAPTER + *prAdapter, uint8_t ucBssIndex, struct QUE *prQue) +{ + struct BSS_INFO *prBssInfo; + struct MSDU_INFO *prMsduInfo; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + u_int8_t fgReturnBssAbsentQ = FALSE; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + QUEUE_CONCATENATE_QUEUES( + &prAdapter->rBssAbsentQueue[ucBssIndex], prQue); + QUEUE_REMOVE_HEAD(&prAdapter->rBssAbsentQueue[ucBssIndex], + prQueueEntry, struct QUE_ENTRY *); + prMsduInfo = (struct MSDU_INFO *) prQueueEntry; + + if (prMsduInfo == NULL) { + DBGLOG(TX, INFO, "prMsduInfo empty\n"); + return; + } + + if (prBssInfo->fgIsNetAbsent) { + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + DBGLOG(TX, INFO, "fgIsNetAbsent!\n"); + while (1) { + if (prBssInfo->ucBssFreeQuota > 0) { + prBssInfo->ucBssFreeQuota--; + QUEUE_INSERT_TAIL( + prQue, (struct QUE_ENTRY *) prMsduInfo); + DBGLOG(TX, INFO, + "fgIsNetAbsent Quota Availalbe\n"); + } else { + fgReturnBssAbsentQ = TRUE; + DBGLOG(TX, INFO, "fgIsNetAbsent NoQuota\n"); + break; + } + if (QUEUE_IS_NOT_EMPTY( + &prAdapter->rBssAbsentQueue[ucBssIndex])) { + QUEUE_REMOVE_HEAD( + &prAdapter->rBssAbsentQueue[ucBssIndex], + prQueueEntry, struct QUE_ENTRY *); + prMsduInfo = (struct MSDU_INFO *) prQueueEntry; + } else { + break; + } + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + if (fgReturnBssAbsentQ) { + QUEUE_INSERT_HEAD( + &prAdapter->rBssAbsentQueue[ucBssIndex], + (struct QUE_ENTRY *) prMsduInfo); + prAdapter->u4BssAbsentBitmap |= BIT(ucBssIndex); + return; + } + } else { + if (prAdapter->u4BssAbsentBitmap) + DBGLOG(TX, INFO, "fgIsNetAbsent END!\n"); + QUEUE_INSERT_TAIL(prQue, (struct QUE_ENTRY *) prMsduInfo); + if (QUEUE_IS_NOT_EMPTY( + &prAdapter->rBssAbsentQueue[ucBssIndex])) + QUEUE_CONCATENATE_QUEUES(prQue, + &prAdapter->rBssAbsentQueue[ucBssIndex]); + } + prAdapter->u4BssAbsentBitmap &= ~BIT(ucBssIndex); +} + +/*----------------------------------------------------------------------------*/ +/* + * \brief Get Tc for hif port mapping. + * + * \param[in] prMsduInfo Pointer of the MsduInfo + * + * \retval Tc which maps to hif port. + */ +/*----------------------------------------------------------------------------*/ +static uint8_t nicTxDirectGetHifTc(struct MSDU_INFO + *prMsduInfo) +{ + uint8_t ucHifTc = 0; + + if (prMsduInfo->ucWmmQueSet == DBDC_2G_WMM_INDEX) { + ucHifTc = TX_2G_WMM_PORT_NUM; + } else { + if (prMsduInfo->ucTC >= 0 && prMsduInfo->ucTC < TC_NUM) + ucHifTc = prMsduInfo->ucTC; + else + ASSERT(0); + } + return ucHifTc; +} + +/*----------------------------------------------------------------------------*/ +/* + * \brief This function is called by nicTxDirectStartXmit() + * and nicTxDirectTimerCheckHifQ(). + * It is the main function to send skb out on HIF bus. + * + * \param[in] prSkb Pointer of the sk_buff to be sent + * \param[in] prMsduInfo Pointer of the MsduInfo + * \param[in] prAdapter Pointer of Adapter + * \param[in] ucCheckTc Indictate which Tc HifQ to be checked + * \param[in] ucStaRecIndex Indictate which StaPsQ to be checked + * \param[in] ucBssIndex Indictate which BssAbsentQ to be checked + * + * \retval WLAN_STATUS + */ +/*----------------------------------------------------------------------------*/ +static uint32_t nicTxDirectStartXmitMain(struct sk_buff + *prSkb, struct MSDU_INFO *prMsduInfo, + struct ADAPTER *prAdapter, + uint8_t ucCheckTc, uint8_t ucStaRecIndex, + uint8_t ucBssIndex) +{ + struct STA_RECORD *prStaRec; /* The current focused STA */ + struct BSS_INFO *prBssInfo; + uint8_t ucTC = 0, ucHifTc = 0; + struct QUE *prTxQue; + u_int8_t fgDropPacket = FALSE; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct QUE rProcessingQue; + struct QUE *prProcessingQue = &rProcessingQue; + uint8_t ucActivedTspec = 0; + + + QUEUE_INITIALIZE(prProcessingQue); + + ucActivedTspec = wmmHasActiveTspec(&prAdapter->rWifiVar.rWmmInfo); + + if (prSkb) { + nicTxFillMsduInfo(prAdapter, prMsduInfo, prSkb); + + /* Tx profiling */ + wlanTxProfilingTagMsdu(prAdapter, prMsduInfo, + TX_PROF_TAG_DRV_ENQUE); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prMsduInfo->ucBssIndex); + + if (!prBssInfo) { + /* No BSS_INFO */ + fgDropPacket = TRUE; + } else if (IS_BSS_ACTIVE(prBssInfo)) { + /* BSS active */ + fgDropPacket = FALSE; + } else { + /* BSS inactive */ + fgDropPacket = TRUE; + } + + if (fgDropPacket) { + DBGLOG(QM, TRACE, + "Drop the Packet for inactive Bss %u\n", + prMsduInfo->ucBssIndex); + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_31); + TX_INC_CNT(&prAdapter->rTxCtrl, TX_INACTIVE_BSS_DROP); + + wlanProcessQueuedMsduInfo(prAdapter, prMsduInfo); + return WLAN_STATUS_FAILURE; + } + + qmDetermineStaRecIndex(prAdapter, prMsduInfo); + + wlanUpdateTxStatistics(prAdapter, prMsduInfo, + FALSE); /*get per-AC Tx packets */ + + switch (prMsduInfo->ucStaRecIndex) { + case STA_REC_INDEX_BMCAST: + ucTC = + arNetwork2TcResource[ + prMsduInfo->ucBssIndex][ + NET_TC_BMC_INDEX]; + + /* Always set BMC packet retry limit to unlimited */ + if (!(prMsduInfo->u4Option + & MSDU_OPT_MANUAL_RETRY_LIMIT)) + nicTxSetPktRetryLimit(prMsduInfo, + TX_DESC_TX_COUNT_NO_LIMIT); + + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_23); + break; + case STA_REC_INDEX_NOT_FOUND: + /* Drop packet if no STA_REC is found */ + DBGLOG(QM, TRACE, "Drop the Packet for no STA_REC\n"); + + TX_INC_CNT(&prAdapter->rTxCtrl, TX_INACTIVE_STA_DROP); + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_24); + wlanProcessQueuedMsduInfo(prAdapter, prMsduInfo); + return WLAN_STATUS_FAILURE; + default: + prTxQue = qmDetermineStaTxQueue(prAdapter, prMsduInfo, + ucActivedTspec, &ucTC); + break; /*default */ + } /* switch (prMsduInfo->ucStaRecIndex) */ + + prMsduInfo->ucTC = ucTC; + prMsduInfo->ucWmmQueSet = + prBssInfo->ucWmmQueSet; /* to record WMM Set */ + + /* Check the Tx descriptor template is valid */ + qmSetTxPacketDescTemplate(prAdapter, prMsduInfo); + + /* Set Tx rate */ + switch (prAdapter->rWifiVar.ucDataTxRateMode) { + case DATA_RATE_MODE_BSS_LOWEST: + nicTxSetPktLowestFixedRate(prAdapter, prMsduInfo); + break; + + case DATA_RATE_MODE_MANUAL: + prMsduInfo->u4FixedRateOption = + prAdapter->rWifiVar.u4DataTxRateCode; + + prMsduInfo->ucRateMode = MSDU_RATE_MODE_MANUAL_DESC; + break; + + case DATA_RATE_MODE_AUTO: + default: + if (prMsduInfo->ucRateMode + == MSDU_RATE_MODE_LOWEST_RATE) + nicTxSetPktLowestFixedRate( + prAdapter, prMsduInfo); + break; + } + + nicTxFillDataDesc(prAdapter, prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + + QUEUE_INSERT_TAIL(prProcessingQue, + (struct QUE_ENTRY *) prMsduInfo); + + /* Power-save STA handling */ + nicTxDirectCheckStaPsQ(prAdapter, prMsduInfo->ucStaRecIndex, + prProcessingQue); + + /* Absent BSS handling */ + nicTxDirectCheckBssAbsentQ(prAdapter, + prMsduInfo->ucBssIndex, prProcessingQue); + + if (QUEUE_IS_EMPTY(prProcessingQue)) + return WLAN_STATUS_SUCCESS; + + if (prProcessingQue->u4NumElem != 1) { + while (1) { + QUEUE_REMOVE_HEAD(prProcessingQue, prQueueEntry, + struct QUE_ENTRY *); + if (prQueueEntry == NULL) + break; + prMsduInfo = (struct MSDU_INFO *) prQueueEntry; + ucHifTc = nicTxDirectGetHifTc(prMsduInfo); + QUEUE_INSERT_TAIL( + &prAdapter->rTxDirectHifQueue[ucHifTc], + (struct QUE_ENTRY *) prMsduInfo); + } + nicTxDirectStartCheckQTimer(prAdapter); + return WLAN_STATUS_SUCCESS; + } + + QUEUE_REMOVE_HEAD(prProcessingQue, prQueueEntry, + struct QUE_ENTRY *); + prMsduInfo = (struct MSDU_INFO *) prQueueEntry; + ucHifTc = nicTxDirectGetHifTc(prMsduInfo); + + if (QUEUE_IS_NOT_EMPTY( + &prAdapter->rTxDirectHifQueue[ucHifTc])) { + QUEUE_INSERT_TAIL( + &prAdapter->rTxDirectHifQueue[ucHifTc], + (struct QUE_ENTRY *) prMsduInfo); + QUEUE_REMOVE_HEAD( + &prAdapter->rTxDirectHifQueue[ucHifTc], + prQueueEntry, struct QUE_ENTRY *); + prMsduInfo = (struct MSDU_INFO *) prQueueEntry; + } + } else { + if (ucStaRecIndex != 0xff || ucBssIndex != 0xff) { + /* Power-save STA handling */ + if (ucStaRecIndex != 0xff) + nicTxDirectCheckStaPsQ(prAdapter, ucStaRecIndex, + prProcessingQue); + + /* Absent BSS handling */ + if (ucBssIndex != 0xff) + nicTxDirectCheckBssAbsentQ( + prAdapter, ucBssIndex, + prProcessingQue); + + if (QUEUE_IS_EMPTY(prProcessingQue)) + return WLAN_STATUS_SUCCESS; + + if (prProcessingQue->u4NumElem != 1) { + while (1) { + QUEUE_REMOVE_HEAD( + prProcessingQue, prQueueEntry, + struct QUE_ENTRY *); + if (prQueueEntry == NULL) + break; + prMsduInfo = + (struct MSDU_INFO *) + prQueueEntry; + ucHifTc = + nicTxDirectGetHifTc(prMsduInfo); + QUEUE_INSERT_TAIL( + &prAdapter-> + rTxDirectHifQueue[ucHifTc], + (struct QUE_ENTRY *) + prMsduInfo); + } + nicTxDirectStartCheckQTimer(prAdapter); + return WLAN_STATUS_SUCCESS; + } + + QUEUE_REMOVE_HEAD(prProcessingQue, prQueueEntry, + struct QUE_ENTRY *); + prMsduInfo = (struct MSDU_INFO *) prQueueEntry; + ucHifTc = nicTxDirectGetHifTc(prMsduInfo); + } else { + if (ucCheckTc != 0xff) + ucHifTc = ucCheckTc; + + if (QUEUE_IS_EMPTY( + &prAdapter->rTxDirectHifQueue[ucHifTc])) { + DBGLOG(TX, INFO, + "ERROR: no rTxDirectHifQueue (%u)\n", + ucHifTc); + return WLAN_STATUS_FAILURE; + } + QUEUE_REMOVE_HEAD( + &prAdapter->rTxDirectHifQueue[ucHifTc], + prQueueEntry, struct QUE_ENTRY *); + prMsduInfo = (struct MSDU_INFO *) prQueueEntry; + } + } + + while (1) { + if (!halTxIsDataBufEnough(prAdapter, prMsduInfo)) { + QUEUE_INSERT_HEAD( + &prAdapter->rTxDirectHifQueue[ucHifTc], + (struct QUE_ENTRY *) prMsduInfo); + mod_timer(&prAdapter->rTxDirectHifTimer, + jiffies + TX_DIRECT_CHECK_INTERVAL); + + return WLAN_STATUS_SUCCESS; + } + + HAL_WRITE_TX_DATA(prAdapter, prMsduInfo); + + if (QUEUE_IS_NOT_EMPTY( + &prAdapter->rTxDirectHifQueue[ucHifTc])) { + QUEUE_REMOVE_HEAD( + &prAdapter->rTxDirectHifQueue[ucHifTc], + prQueueEntry, struct QUE_ENTRY *); + prMsduInfo = (struct MSDU_INFO *) prQueueEntry; + } else { + break; + } + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/* + * \brief This function is the timeout function of timer rTxDirectSkbTimer. + * The purpose is to check if rTxDirectSkbQueue has any skb to be sent. + * + * \param[in] data Pointer of GlueInfo + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE +void nicTxDirectTimerCheckSkbQ(struct timer_list *timer) +#else +void nicTxDirectTimerCheckSkbQ(unsigned long data) +#endif +{ + +#if KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE + struct ADAPTER *prAdapter = + from_timer(prAdapter, timer, rTxDirectSkbTimer); + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; +#else + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)data; + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; +#endif + + if (skb_queue_len(&prAdapter->rTxDirectSkbQueue)) + nicTxDirectStartXmit(NULL, prGlueInfo); + else + DBGLOG(TX, INFO, "fgHasNoMsdu FALSE\n"); +} + +/*----------------------------------------------------------------------------*/ +/* + * \brief This function is the timeout function of timer rTxDirectHifTimer. + * The purpose is to check if rStaPsQueue, rBssAbsentQueue, + * and rTxDirectHifQueue has any MsduInfo to be sent. + * + * \param[in] data Pointer of GlueInfo + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE +void nicTxDirectTimerCheckHifQ(struct timer_list *timer) +#else +void nicTxDirectTimerCheckHifQ(unsigned long data) +#endif +{ + +#if KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE + struct ADAPTER *prAdapter = + from_timer(prAdapter, timer, rTxDirectHifTimer); + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; +#else + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)data; + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; +#endif + + uint8_t ucHifTc = 0; + uint32_t u4StaPsBitmap, u4BssAbsentBitmap; + uint8_t ucStaRecIndex, ucBssIndex; + + spin_lock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + + u4StaPsBitmap = prAdapter->u4StaPsBitmap; + u4BssAbsentBitmap = prAdapter->u4BssAbsentBitmap; + + if (u4StaPsBitmap) + for (ucStaRecIndex = 0; ucStaRecIndex < CFG_STA_REC_NUM; + ++ucStaRecIndex) { + if (QUEUE_IS_NOT_EMPTY( + &prAdapter->rStaPsQueue[ucStaRecIndex])) { + nicTxDirectStartXmitMain(NULL, NULL, prAdapter, + 0xff, ucStaRecIndex, 0xff); + u4StaPsBitmap &= ~BIT(ucStaRecIndex); + DBGLOG(TX, INFO, + "ucStaRecIndex: %u\n", ucStaRecIndex); + } + if (u4StaPsBitmap == 0) + break; + } + + if (u4BssAbsentBitmap) + for (ucBssIndex = 0; ucBssIndex < MAX_BSSID_NUM + 1; + ++ucBssIndex) { + if (QUEUE_IS_NOT_EMPTY( + &prAdapter->rBssAbsentQueue[ucBssIndex])) { + nicTxDirectStartXmitMain(NULL, NULL, prAdapter, + 0xff, 0xff, ucBssIndex); + u4BssAbsentBitmap &= ~BIT(ucBssIndex); + DBGLOG(TX, INFO, + "ucBssIndex: %u\n", ucBssIndex); + } + if (u4BssAbsentBitmap == 0) + break; + } + + + for (ucHifTc = 0; ucHifTc < TX_PORT_NUM; ucHifTc++) + if (QUEUE_IS_NOT_EMPTY( + &prAdapter->rTxDirectHifQueue[ucHifTc])) + nicTxDirectStartXmitMain(NULL, NULL, prAdapter, ucHifTc, + 0xff, 0xff); + + spin_unlock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); +} + +/*----------------------------------------------------------------------------*/ +/* + * \brief This function is have to called by kalHardStartXmit(). + * The purpose is to let as many as possible TX processing in softirq + * instead of in kernel thread to reduce TX CPU usage. + * NOTE: Currently only USB interface can use this function. + * + * \param[in] prSkb Pointer of the sk_buff to be sent + * \param[in] prGlueInfo Pointer of prGlueInfo + * + * \retval WLAN_STATUS + */ +/*----------------------------------------------------------------------------*/ +uint32_t nicTxDirectStartXmit(struct sk_buff *prSkb, + struct GLUE_INFO *prGlueInfo) +{ + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + struct MSDU_INFO *prMsduInfo; + uint32_t ret = WLAN_STATUS_SUCCESS; + + spin_lock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + + if (prSkb) { + prMsduInfo = cnmPktAlloc(prAdapter, 0); + + if (prMsduInfo == NULL) { + DBGLOG(TX, INFO, "cnmPktAlloc NULL\n"); + skb_queue_tail(&prAdapter->rTxDirectSkbQueue, prSkb); + + ret = WLAN_STATUS_SUCCESS; + goto end; + } + if (skb_queue_len(&prAdapter->rTxDirectSkbQueue)) { + skb_queue_tail(&prAdapter->rTxDirectSkbQueue, prSkb); + prSkb = skb_dequeue(&prAdapter->rTxDirectSkbQueue); + } + } else { + prMsduInfo = cnmPktAlloc(prAdapter, 0); + if (prMsduInfo != NULL) { + prSkb = skb_dequeue(&prAdapter->rTxDirectSkbQueue); + if (prSkb == NULL) { + DBGLOG(TX, INFO, + "ERROR: no rTxDirectSkbQueue\n"); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + ret = WLAN_STATUS_FAILURE; + goto end; + } + } else { + ret = WLAN_STATUS_FAILURE; + goto end; + } + } + + while (1) { + nicTxDirectStartXmitMain(prSkb, prMsduInfo, prAdapter, 0xff, + 0xff, 0xff); + prSkb = skb_dequeue(&prAdapter->rTxDirectSkbQueue); + if (prSkb != NULL) { + prMsduInfo = cnmPktAlloc(prAdapter, 0); + if (prMsduInfo == NULL) { + skb_queue_head(&prAdapter->rTxDirectSkbQueue, + prSkb); + break; + } + } else { + break; + } + } + +end: + if (skb_queue_len(&prAdapter->rTxDirectSkbQueue)) + mod_timer(&prAdapter->rTxDirectSkbTimer, + jiffies + TX_DIRECT_CHECK_INTERVAL); + spin_unlock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + return ret; +} +/* TX Direct functions : END */ + + +/*----------------------------------------------------------------------------*/ +/* + * \brief Assign Tc resource to prWifiVar according to firmware's report + * + * \param[in] prSkb Pointer of the sk_buff to be sent + * \param[in] prGlueInfo Pointer of prGlueInfo + * + */ +/*----------------------------------------------------------------------------*/ + +void nicTxResourceUpdate_v1(IN struct ADAPTER *prAdapter) +{ + uint8_t string[128], idx, i, tc_num; + uint32_t u4share, u4remains; + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; + uint32_t *pau4TcPageCount; +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + struct QUE_MGT *prQM = &prAdapter->rQM; +#endif + + + /* + * Use the settings in config file first, + * else, use the settings reported from firmware. + */ + + + /* + * 1. assign PSE/PLE free page count for each TC + */ + + tc_num = (TC_NUM - 1); /* except TC4_INDEX */ + for (i = 0; i < 2; i++) { + if (i == 0) { + /* PSE CMD*/ + prWifiVar->au4TcPageCount[TC4_INDEX] = + prAdapter->nicTxReousrce.u4CmdTotalResource; + + /* calculate PSE free page count for each TC, + * except TC_4 + */ + u4share = prAdapter->nicTxReousrce.u4DataTotalResource / + tc_num; + u4remains = prAdapter->nicTxReousrce. + u4DataTotalResource % tc_num; + pau4TcPageCount = prWifiVar->au4TcPageCount; + } else { + /* PLE CMD*/ + prWifiVar->au4TcPageCountPle[TC4_INDEX] = + prAdapter->nicTxReousrce.u4CmdTotalResourcePle; + + /* calculate PLE free page count for each TC, + * except TC_4 + */ + u4share = prAdapter->nicTxReousrce. + u4DataTotalResourcePle / tc_num; + u4remains = prAdapter->nicTxReousrce. + u4DataTotalResourcePle % tc_num; + pau4TcPageCount = prWifiVar->au4TcPageCountPle; + } + + /* assign free page count for each TC, except TC_4 */ + for (idx = TC0_INDEX; idx < TC_NUM; idx++) { + if (idx != TC4_INDEX) + pau4TcPageCount[idx] = u4share; + } + /* if there is remaings, give them to TC_3, which is VO */ + pau4TcPageCount[TC3_INDEX] += u4remains; + } + + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + /* + * 2. assign guaranteed page count for each TC + */ + + /* 2 1. update guaranteed page count in QM */ + for (idx = 0; idx < TC_NUM; idx++) + prQM->au4GuaranteedTcResource[idx] = + prWifiVar->au4TcPageCount[idx]; +#endif + + + +#if CFG_SUPPORT_CFG_FILE + /* + * 3. Use the settings in config file first, + * else, use the settings reported from firmware. + */ + + /* 3 1. update for free page count */ + for (idx = 0; idx < TC_NUM; idx++) { + + /* construct prefix: Tc0Page, Tc1Page... */ + memset(string, 0, sizeof(string) / sizeof(uint8_t)); + snprintf(string, sizeof(string) / sizeof(uint8_t), + "Tc%xPage", idx); + + /* update the final value */ + prWifiVar->au4TcPageCount[idx] = + (uint32_t) wlanCfgGetUint32(prAdapter, + string, prWifiVar->au4TcPageCount[idx]); + } + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + /* 3 2. update for guaranteed page count */ + for (idx = 0; idx < TC_NUM; idx++) { + + /* construct prefix: Tc0Grt, Tc1Grt... */ + memset(string, 0, sizeof(string) / sizeof(uint8_t)); + snprintf(string, sizeof(string) / sizeof(uint8_t), + "Tc%xGrt", idx); + + /* update the final value */ + prQM->au4GuaranteedTcResource[idx] = + (uint32_t) wlanCfgGetUint32(prAdapter, + string, prQM->au4GuaranteedTcResource[idx]); + } +#endif /* end of #if QM_ADAPTIVE_TC_RESOURCE_CTRL */ +#endif /* end of #if CFG_SUPPORT_CFG_FILE */ + + + + + /* + * 4. Peak throughput settings. + * Give most of the resource to TC1_INDEX. + * Reference to arNetwork2TcResource[], AC_BE uses TC1_INDEX. + */ + if (prAdapter->rWifiVar.ucTpTestMode == + ENUM_TP_TEST_MODE_THROUGHPUT) { + uint32_t u4psePageCnt, u4plePageCnt, u4pseRemain, + u4pleRemain; +#define DEFAULT_PACKET_NUM 5 + + + /* pse */ + u4pseRemain = prAdapter->nicTxReousrce.u4DataTotalResource; + u4psePageCnt = DEFAULT_PACKET_NUM * + nicTxGetMaxPageCntPerFrame(prAdapter); + + /* ple */ + u4pleRemain = + prAdapter->nicTxReousrce.u4DataTotalResourcePle; + u4plePageCnt = DEFAULT_PACKET_NUM * + NIX_TX_PLE_PAGE_CNT_PER_FRAME; + + /* equally giving to each TC */ + for (idx = 0; idx < TC_NUM; idx++) { + if (idx == TC4_INDEX) + continue; + + /* pse */ + prWifiVar->au4TcPageCount[idx] = u4psePageCnt; + u4pseRemain -= u4psePageCnt; + + /* ple */ + prWifiVar->au4TcPageCountPle[idx] = u4plePageCnt; + u4pleRemain -= u4plePageCnt; + } + + /* remaings are to TC1_INDEX */ + prWifiVar->au4TcPageCount[TC1_INDEX] += u4pseRemain; + prWifiVar->au4TcPageCountPle[TC1_INDEX] += u4pleRemain; + } +} + +void nicTxChangeDataPortByAc(struct STA_RECORD *prStaRec, uint8_t ucAci, + u_int8_t fgToMcu) +{ + uint8_t ucTid; + void **pprTxDTemplate = NULL; + + if (!prStaRec) + return; + DBGLOG(TX, INFO, "Data Packets in Aci %d will route to %s\n", ucAci, + fgToMcu ? "MCU" : "LMAC"); + pprTxDTemplate = &prStaRec->aprTxDescTemplate[0]; + for (ucTid = 0; ucTid < TX_DESC_TID_NUM; ucTid++) { + if (aucTid2ACI[ucTid] != ucAci) + continue; + HAL_MAC_TX_DESC_SET_PORT_INDEX( + (struct HW_MAC_TX_DESC *)pprTxDTemplate[ucTid], + fgToMcu ? PORT_INDEX_MCU:PORT_INDEX_LMAC); + } +} + +/* if some msdus are waiting tx done status, but now roaming done, then need to +** change wlan index of these msdus to match tx done status event +** In multi-thread solution, we also need to check if pending tx packets in +** hif_thread tx queue. +*/ +void nicTxHandleRoamingDone(struct ADAPTER *prAdapter, + struct STA_RECORD *prOldStaRec, + struct STA_RECORD *prNewStaRec) +{ + struct MSDU_INFO *prMsduInfo = NULL; + uint8_t ucOldWlanIndex = prOldStaRec->ucWlanIndex; + uint8_t ucNewWlanIndex = prNewStaRec->ucWlanIndex; + uint8_t ucIndex = 0; + + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + prMsduInfo = (struct MSDU_INFO *)QUEUE_GET_HEAD( + &prAdapter->rTxCtrl.rTxMgmtTxingQueue); + while (prMsduInfo) { + if (prMsduInfo->ucWlanIndex == ucOldWlanIndex) + prMsduInfo->ucWlanIndex = ucNewWlanIndex; + prMsduInfo = (struct MSDU_INFO *)QUEUE_GET_NEXT_ENTRY( + &prMsduInfo->rQueEntry); + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + +/* I think any time we disconnect with previous AP, rTxP0Queue and rTxP1Queue +** should be empty. +** because we have stopped dequeue when initial to connect the new roaming AP. +** It is enough time for hif_thread to send out these packets. But anyway, let's +** prepare code for that case to avoid scheduler corner case. +*/ +#if CFG_SUPPORT_MULTITHREAD + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); +#if CFG_FIX_2_TX_PORT + prMsduInfo = (struct MSDU_INFO *)QUEUE_GET_HEAD(&prAdapter->rTxP0Queue); + while (prMsduInfo) { + if (prMsduInfo->ucWlanIndex == ucOldWlanIndex) + prMsduInfo->ucWlanIndex = ucNewWlanIndex; + prMsduInfo = (struct MSDU_INFO *)QUEUE_GET_NEXT_ENTRY( + &prMsduInfo->rQueEntry); + } + prMsduInfo = (struct MSDU_INFO *)QUEUE_GET_HEAD(&prAdapter->rTxP1Queue); + while (prMsduInfo) { + if (prMsduInfo->ucWlanIndex == ucOldWlanIndex) + prMsduInfo->ucWlanIndex = ucNewWlanIndex; + prMsduInfo = (struct MSDU_INFO *)QUEUE_GET_NEXT_ENTRY( + &prMsduInfo->rQueEntry); + } +#else + for (ucIndex = 0; ucIndex < TX_PORT_NUM; ucIndex++) { + prMsduInfo = (struct MSDU_INFO *)QUEUE_GET_HEAD( + &prAdapter->rTxPQueue[ucIndex]); + while (prMsduInfo) { + if (prMsduInfo->ucWlanIndex == ucOldWlanIndex) + prMsduInfo->ucWlanIndex = ucNewWlanIndex; + prMsduInfo = (struct MSDU_INFO *)QUEUE_GET_NEXT_ENTRY( + &prMsduInfo->rQueEntry); + } + } +#endif + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); +#endif +} + + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic_umac.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic_umac.c new file mode 100644 index 0000000000000..460ff9c93b7ea --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/nic_umac.c @@ -0,0 +1,464 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_umac.c#5 + */ + +/*! \file nic_umac.c + * \brief Functions that used for debug UMAC + * + * This file includes the functions used do umac debug + * + */ + +/******************************************************************************* + * C O M P I L E 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 "que_mgt.h" + +#ifndef LINUX +#include +#else +#include +#endif + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + + + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +struct UMAC_PG_INFO_AND_RESERVE_CNT_CR_OFFSET_MAP { + uint8_t ucGroupID; + uint32_t u4PgReservePageCntRegOffset; + uint32_t u4PgInfoRegOffset; +}; + +struct UMAC_PG_MAX_MIN_QUOTA_SET { + uint8_t ucPageGroupID; + uint16_t u2MaxPageQuota; + uint16_t u2MinPageQuota; +}; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +const struct UMAC_PG_INFO_AND_RESERVE_CNT_CR_OFFSET_MAP + g_arPlePgInfoAndReserveCrOffsetMap[] = { + { + UMAC_PG_HIF0_GROUP_0, + UMAC_PG_HIF0_GROUP(UMAC_PLE_CFG_POOL_INDEX), + UMAC_HIF0_PG_INFO(UMAC_PLE_CFG_POOL_INDEX) + }, + { + UMAC_PG_HIF0_GROUP_0, + UMAC_PG_HIF0_GROUP(UMAC_PLE_CFG_POOL_INDEX), + UMAC_HIF0_PG_INFO(UMAC_PLE_CFG_POOL_INDEX) + }, + { + UMAC_PG_CPU_GROUP_2, + UMAC_PG_CPU_GROUP(UMAC_PLE_CFG_POOL_INDEX), + UMAC_CPU_PG_INFO(UMAC_PLE_CFG_POOL_INDEX) + }, +}; + +const struct UMAC_PG_INFO_AND_RESERVE_CNT_CR_OFFSET_MAP + g_arPsePgInfoAndReserveCrOffsetMap[] = { + { + UMAC_PG_HIF0_GROUP_0, + UMAC_PG_HIF0_GROUP(UMAC_PSE_CFG_POOL_INDEX), + UMAC_HIF0_PG_INFO(UMAC_PSE_CFG_POOL_INDEX) + }, + { + UMAC_PG_HIF1_GROUP_1, + UMAC_PG_HIF1_GROUP(UMAC_PSE_CFG_POOL_INDEX), + UMAC_HIF1_PG_INFO(UMAC_PSE_CFG_POOL_INDEX) + }, + { + UMAC_PG_CPU_GROUP_2, + UMAC_PG_CPU_GROUP(UMAC_PSE_CFG_POOL_INDEX), + UMAC_CPU_PG_INFO(UMAC_PSE_CFG_POOL_INDEX) + }, + { + UMAC_PG_LMAC0_GROUP_3, + UMAC_PG_LMAC0_GROUP(UMAC_PSE_CFG_POOL_INDEX), + UMAC_LMAC0_PG_INFO(UMAC_PSE_CFG_POOL_INDEX) + }, + { + UMAC_PG_LMAC1_GROUP_4, + UMAC_PG_LMAC1_GROUP(UMAC_PSE_CFG_POOL_INDEX), + UMAC_LMAC1_PG_INFO(UMAC_PSE_CFG_POOL_INDEX) + }, + { + UMAC_PG_LMAC2_GROUP_5, + UMAC_PG_LMAC2_GROUP(UMAC_PSE_CFG_POOL_INDEX), + UMAC_LMAC2_PG_INFO(UMAC_PSE_CFG_POOL_INDEX) + }, + { + UMAC_PG_PLE_GROUP_6, + UMAC_PG_PLE_GROUP(UMAC_PSE_CFG_POOL_INDEX), + UMAC_PLE_PG_INFO(UMAC_PSE_CFG_POOL_INDEX) + }, +}; + +/******************************************************************************* + * M A 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 halUmacWrapSourcePortSanityCheck: + * + * @param IN BOOLEAN fgPsePleFlag, + * IN UINT_8 ucPageGroupID + * @return TRUE/FALSE + */ +/*----------------------------------------------------------------------------*/ + +OUT u_int8_t halUmacWrapSourcePortSanityCheck( + IN u_int8_t fgPsePleFlag, IN uint8_t ucPageGroupID) +{ + + if (fgPsePleFlag == UMAC_PSE_CFG_POOL_INDEX) { + if (ucPageGroupID > UMAC_PG_PLE_GROUP_6) + return FALSE; + } else if (fgPsePleFlag == UMAC_PLE_CFG_POOL_INDEX) { + if ((ucPageGroupID != UMAC_PG_HIF0_GROUP_0) + && (ucPageGroupID != UMAC_PG_CPU_GROUP_2)) + return FALSE; + } else + return FALSE; + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief halUmacWrapRsvPgCnt: + * + * @param IN P_ADAPTER_T prAdapter + * IN BOOLEAN fgPsePleFlag, + * IN UINT_8 ucPageGroupID + * @return UINT_16 + */ +/*----------------------------------------------------------------------------*/ + +OUT uint16_t halUmacWrapRsvPgCnt(IN struct ADAPTER + *prAdapter, IN u_int8_t fgPsePleFlag, + IN uint8_t ucPageGroupID) +{ + uint32_t u4RegAddr = 0; + uint32_t u4Value = 0; + + if (halUmacWrapSourcePortSanityCheck(fgPsePleFlag, + ucPageGroupID) == FALSE) + return UMAC_FID_FAULT; + + if (fgPsePleFlag == UMAC_PSE_CFG_POOL_INDEX) + u4RegAddr = + g_arPsePgInfoAndReserveCrOffsetMap[ucPageGroupID]. + u4PgInfoRegOffset; + else if (fgPsePleFlag == UMAC_PLE_CFG_POOL_INDEX) + u4RegAddr = + g_arPlePgInfoAndReserveCrOffsetMap[ucPageGroupID]. + u4PgInfoRegOffset; + + HAL_MCR_RD(prAdapter, u4RegAddr, &u4Value); + + return (uint16_t) (u4Value & BITS(0, 11)); +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief halUmacWrapSrcPgCnt: + * + * @param IN P_ADAPTER_T prAdapter + * IN BOOLEAN fgPsePleFlag, + * IN UINT_8 ucPageGroupID + * @return UINT_16 + */ +/*----------------------------------------------------------------------------*/ + +OUT uint16_t halUmacWrapSrcPgCnt(IN struct ADAPTER + *prAdapter, IN u_int8_t fgPsePleFlag, + IN uint8_t ucPageGroupID) +{ + uint32_t u4RegAddr = 0; + uint32_t u4Value = 0; + + if (halUmacWrapSourcePortSanityCheck(fgPsePleFlag, + ucPageGroupID) == FALSE) + return UMAC_FID_FAULT; + + if (fgPsePleFlag == UMAC_PSE_CFG_POOL_INDEX) + u4RegAddr = + g_arPsePgInfoAndReserveCrOffsetMap[ucPageGroupID]. + u4PgInfoRegOffset; + else if (fgPsePleFlag == UMAC_PLE_CFG_POOL_INDEX) + u4RegAddr = + g_arPlePgInfoAndReserveCrOffsetMap[ucPageGroupID]. + u4PgInfoRegOffset; + + HAL_MCR_RD(prAdapter, u4RegAddr, &u4Value); + + return (uint16_t) ((u4Value & BITS(16, 27)) >> 16); +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief halUmacPbufCtrlTotalPageNum: + * + * @param IN P_ADAPTER_T prAdapter + * IN BOOLEAN fgPsePleFlag, + * @return UINT_16 + */ +/*----------------------------------------------------------------------------*/ + +OUT uint16_t halUmacPbufCtrlTotalPageNum(IN struct ADAPTER + *prAdapter, IN uint16_t fgPsePleFlag) +{ + uint32_t u4Value = 0; + + HAL_MCR_RD(prAdapter, UMAC_PBUF_CTRL(fgPsePleFlag), + &u4Value); + + return (uint16_t) (u4Value & + UMAC_PBUF_CTRL_TOTAL_PAGE_NUM_MASK); +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief halUmacWrapFrePageCnt: + * + * @param IN P_ADAPTER_T prAdapter + * IN BOOLEAN fgPsePleFlag, + * @return UINT_16 + */ +/*----------------------------------------------------------------------------*/ + +OUT uint16_t halUmacWrapFrePageCnt(IN struct ADAPTER + *prAdapter, IN u_int8_t fgPsePleFlag) +{ + uint32_t u4Value = 0; + + HAL_MCR_RD(prAdapter, UMAC_FREEPG_CNT(fgPsePleFlag), + &u4Value); + return (u4Value & UMAC_FREEPG_CNT_FREEPAGE_CNT_MASK) >> + UMAC_FREEPG_CNT_FREEPAGE_CNT_OFFSET; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief halUmacWrapFfaCnt: + * + * @param IN P_ADAPTER_T prAdapter + * IN BOOLEAN fgPsePleFlag, + * @return UINT_16 + */ +/*----------------------------------------------------------------------------*/ + +OUT uint16_t halUmacWrapFfaCnt(IN struct ADAPTER *prAdapter, + IN u_int8_t fgPsePleFlag) +{ + uint32_t u4Value = 0; + + HAL_MCR_RD(prAdapter, UMAC_FREEPG_CNT(fgPsePleFlag), + &u4Value); + return (u4Value & UMAC_FREEPG_CNT_FFA_CNT_MASK) >> + UMAC_FREEPG_CNT_FFA_CNT_OFFSET; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief halUmacInfoGetMiscStatus: + * + * @param IN P_ADAPTER_T prAdapter + * IN P_UMAC_STAT2_GET_T pUmacStat2Get, + * @return UINT_16 + */ +/*----------------------------------------------------------------------------*/ + + +OUT u_int8_t halUmacInfoGetMiscStatus(IN struct ADAPTER + *prAdapter, IN struct UMAC_STAT2_GET *pUmacStat2Get) +{ + pUmacStat2Get->u2PleRevPgHif0Group0 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PLE_CFG_POOL_INDEX, + UMAC_PG_HIF0_GROUP_0); + + pUmacStat2Get->u2PleRevPgCpuGroup2 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PLE_CFG_POOL_INDEX, + UMAC_PG_CPU_GROUP_2); + + pUmacStat2Get->u2PseRevPgHif0Group0 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_HIF0_GROUP_0); + + pUmacStat2Get->u2PseRevPgHif1Group1 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_HIF1_GROUP_1); + + pUmacStat2Get->u2PseRevPgCpuGroup2 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_CPU_GROUP_2); + + pUmacStat2Get->u2PseRevPgLmac0Group3 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_LMAC0_GROUP_3); + + pUmacStat2Get->u2PseRevPgLmac1Group4 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_LMAC1_GROUP_4); + + pUmacStat2Get->u2PseRevPgLmac2Group5 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_LMAC2_GROUP_5); + + pUmacStat2Get->u2PseRevPgPleGroup6 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_PLE_GROUP_6); + + pUmacStat2Get->u2PleSrvPgHif0Group0 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PLE_CFG_POOL_INDEX, + UMAC_PG_HIF0_GROUP_0); + + pUmacStat2Get->u2PleSrvPgCpuGroup2 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PLE_CFG_POOL_INDEX, + UMAC_PG_CPU_GROUP_2); + + pUmacStat2Get->u2PseSrvPgHif0Group0 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_HIF0_GROUP_0); + + pUmacStat2Get->u2PseSrvPgHif1Group1 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_HIF1_GROUP_1); + + pUmacStat2Get->u2PseSrvPgCpuGroup2 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_CPU_GROUP_2); + + pUmacStat2Get->u2PseSrvPgLmac0Group3 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_LMAC0_GROUP_3); + + pUmacStat2Get->u2PseSrvPgLmac1Group4 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_LMAC1_GROUP_4); + + pUmacStat2Get->u2PseSrvPgLmac2Group5 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_LMAC2_GROUP_5); + + pUmacStat2Get->u2PseSrvPgPleGroup6 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, + UMAC_PG_PLE_GROUP_6); + + + pUmacStat2Get->u2PleTotalPageNum = + halUmacPbufCtrlTotalPageNum(prAdapter, + UMAC_PLE_CFG_POOL_INDEX); + + pUmacStat2Get->u2PseTotalPageNum = + halUmacPbufCtrlTotalPageNum(prAdapter, + UMAC_PSE_CFG_POOL_INDEX); + + pUmacStat2Get->u2PleFreePageNum = halUmacWrapFrePageCnt( + prAdapter, UMAC_PLE_CFG_POOL_INDEX); + + pUmacStat2Get->u2PseFreePageNum = halUmacWrapFrePageCnt( + prAdapter, UMAC_PSE_CFG_POOL_INDEX); + + pUmacStat2Get->u2PleFfaNum = halUmacWrapFfaCnt(prAdapter, + UMAC_PLE_CFG_POOL_INDEX); + + pUmacStat2Get->u2PseFfaNum = halUmacWrapFfaCnt(prAdapter, + UMAC_PSE_CFG_POOL_INDEX); + + return TRUE; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/p2p_nic.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/p2p_nic.c new file mode 100644 index 0000000000000..e71e645eb7f41 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/p2p_nic.c @@ -0,0 +1,277 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 struct ADAPTER *prAdapter, + IN struct EVENT_P2P_DEV_DISCOVER_RESULT *prP2pResult, + IN uint8_t *pucRxIEBuf, + IN uint16_t u2RxIELength) +{ + struct P2P_INFO *prP2pInfo = (struct P2P_INFO *) NULL; + struct EVENT_P2P_DEV_DISCOVER_RESULT *prTargetResult = + (struct EVENT_P2P_DEV_DISCOVER_RESULT *) NULL; + uint32_t u4Idx = 0; + u_int8_t bUpdate = FALSE; + + uint8_t *pucIeBuf = (uint8_t *) NULL; + uint16_t u2IELength = 0; + uint8_t 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(struct EVENT_P2P_DEV_DISCOVER_RESULT)); + + /* then buffer */ + kalMemCopy(prTargetResult, + (void *) prP2pResult, + sizeof(struct EVENT_P2P_DEV_DISCOVER_RESULT)); + + /* 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 (((unsigned long) prP2pInfo->pucCurrIePtr + + (unsigned long) u2RxIELength) > + (unsigned long)& + prP2pInfo->aucCommIePool + [CFG_MAX_COMMON_IE_BUF_LEN]) { + + /* Common Buffer is no enough. */ + u2RxIELength = + (uint16_t) ((unsigned long) + &prP2pInfo->aucCommIePool + [CFG_MAX_COMMON_IE_BUF_LEN] - + (unsigned long) + prP2pInfo->pucCurrIePtr); + } + + /* Step to next buffer address. */ + prP2pInfo->pucCurrIePtr = + (uint8_t *) ((unsigned long) + prP2pInfo->pucCurrIePtr + + (unsigned long) u2RxIELength); + } + + /* Restore buffer pointer. */ + prTargetResult->pucIeBuf = pucIeBuf; + + if (pucRxIEBuf) { + /* If new received IE is available. + * Replace the old one & update new IE length. + */ + kalMemCopy(pucIeBuf, pucRxIEBuf, u2RxIELength); + prTargetResult->u2IELength = u2RxIELength; + } else { + /* There is no new IE information, + * keep the old one. + */ + prTargetResult->u2IELength = u2IELength; + } + } + } + + if (!bUpdate) { + /* We would flush the whole scan result + * after each scan request is issued. + * If P2P device is too many, it may over the scan list. + */ + if ((u4Idx < CFG_MAX_NUM_BSS_LIST) + && (UNEQUAL_MAC_ADDR(zeroMac, + prP2pResult->aucDeviceAddr))) { + + prTargetResult = &prP2pInfo->arP2pDiscoverResult[u4Idx]; + + /* zero */ + kalMemZero(prTargetResult, + sizeof(struct EVENT_P2P_DEV_DISCOVER_RESULT)); + + /* then buffer */ + kalMemCopy(prTargetResult, + (void *) prP2pResult, + sizeof(struct EVENT_P2P_DEV_DISCOVER_RESULT)); + + if (u2RxIELength) { + prTargetResult->pucIeBuf = + prP2pInfo->pucCurrIePtr; + + if (((unsigned long) prP2pInfo->pucCurrIePtr + + (unsigned long) u2RxIELength) > + (unsigned long) + &prP2pInfo->aucCommIePool + [CFG_MAX_COMMON_IE_BUF_LEN]) { + + /* Common Buffer is no enough. */ + u2IELength = + (uint16_t) ((unsigned long) + &prP2pInfo->aucCommIePool + [CFG_MAX_COMMON_IE_BUF_LEN] - + (unsigned long) + prP2pInfo->pucCurrIePtr); + } else { + u2IELength = u2RxIELength; + } + + prP2pInfo->pucCurrIePtr = + (uint8_t *) ((unsigned long) + prP2pInfo->pucCurrIePtr + + (unsigned long) u2IELength); + + kalMemCopy((void *) prTargetResult->pucIeBuf, + (void *) pucRxIEBuf, + (uint32_t) u2IELength); + + prTargetResult->u2IELength = u2IELength; + } else { + prTargetResult->pucIeBuf = NULL; + prTargetResult->u2IELength = 0; + } + + prP2pInfo->u4DeviceNum++; + + } else { + /* TODO: Fixme to replace an old one. (?) */ + ASSERT(FALSE); + } + } +} /* nicRxAddP2pDevice */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/que_mgt.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/que_mgt.c new file mode 100644 index 0000000000000..6994acb32faea --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/nic/que_mgt.c @@ -0,0 +1,8135 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \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. + */ + + +/******************************************************************************* + * C O M P I L E 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 "queue.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]; + +const uint8_t aucTid2ACI[TX_DESC_TID_NUM] = { + WMM_AC_BE_INDEX, /* TID0 */ + WMM_AC_BK_INDEX, /* TID1 */ + WMM_AC_BK_INDEX, /* TID2 */ + WMM_AC_BE_INDEX, /* TID3 */ + WMM_AC_VI_INDEX, /* TID4 */ + WMM_AC_VI_INDEX, /* TID5 */ + WMM_AC_VO_INDEX, /* TID6 */ + WMM_AC_VO_INDEX /* TID7 */ +}; + +const uint8_t aucACI2TxQIdx[WMM_AC_INDEX_NUM] = { + TX_QUEUE_INDEX_AC1, /* WMM_AC_BE_INDEX */ + TX_QUEUE_INDEX_AC0, /* WMM_AC_BK_INDEX */ + TX_QUEUE_INDEX_AC2, /* WMM_AC_VI_INDEX */ + TX_QUEUE_INDEX_AC3 /* WMM_AC_VO_INDEX */ +}; + +const uint8_t *apucACI2Str[WMM_AC_INDEX_NUM] = { + "BE", "BK", "VI", "VO" +}; + +const uint8_t arNetwork2TcResource[MAX_BSSID_NUM + 1][NET_TC_NUM] = { + /* HW Queue Set 1 */ + /* AC_BE, AC_BK, AC_VI, AC_VO, MGMT, BMC */ + /* AIS */ + {TC1_INDEX, TC0_INDEX, TC2_INDEX, TC3_INDEX, TC4_INDEX, BMC_TC_INDEX}, + /* P2P/BoW */ + {TC1_INDEX, TC0_INDEX, TC2_INDEX, TC3_INDEX, TC4_INDEX, BMC_TC_INDEX}, + /* P2P/BoW */ + {TC1_INDEX, TC0_INDEX, TC2_INDEX, TC3_INDEX, TC4_INDEX, BMC_TC_INDEX}, + /* P2P/BoW */ + {TC1_INDEX, TC0_INDEX, TC2_INDEX, TC3_INDEX, TC4_INDEX, BMC_TC_INDEX}, + /* P2P_DEV */ + {TC1_INDEX, TC0_INDEX, TC2_INDEX, TC3_INDEX, TC4_INDEX, BMC_TC_INDEX}, +}; + +const uint8_t aucWmmAC2TcResourceSet1[WMM_AC_INDEX_NUM] = { + TC1_INDEX, + TC0_INDEX, + TC2_INDEX, + TC3_INDEX +}; + +#if NIC_TX_ENABLE_SECOND_HW_QUEUE +const uint8_t aucWmmAC2TcResourceSet2[WMM_AC_INDEX_NUM] = { + TC7_INDEX, + TC6_INDEX, + TC8_INDEX, + TC9_INDEX +}; +#endif +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +#if ARP_MONITER_ENABLE +static uint16_t arpMoniter; +static uint8_t apIp[4]; +static uint8_t gatewayIp[4]; +#endif +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +#if CFG_RX_REORDERING_ENABLED +#define qmHandleRxPackets_AOSP_1 \ +do { \ + /* ToDo[6630]: duplicate removal */ \ + if (!fgIsBMC && nicRxIsDuplicateFrame(prCurrSwRfb) == TRUE) { \ + DBGLOG(QM, TRACE, "Duplicated packet is detected\n"); \ + RX_INC_CNT(&prAdapter->rRxCtrl, RX_DUPICATE_DROP_COUNT); \ + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; \ + } \ + /* ToDo[6630]: defragmentation */ \ + if (prCurrSwRfb->fgFragFrame) { \ + prCurrSwRfb = nicRxDefragMPDU(prAdapter, \ + prCurrSwRfb, prReturnedQue); \ + if (prCurrSwRfb) { \ + prRxStatus = prCurrSwRfb->prRxStatus; \ + DBGLOG(QM, TRACE, \ + "defragmentation RxStatus=%p\n", prRxStatus); \ + } \ + } \ + if (prCurrSwRfb) { \ + fgMicErr = FALSE; \ + if (HAL_RX_STATUS_GET_SEC_MODE(prRxStatus) == \ + CIPHER_SUITE_TKIP_WO_MIC) { \ + if (prCurrSwRfb->prStaRec) { \ + uint8_t ucBssIndex; \ + struct BSS_INFO *prBssInfo = NULL; \ + uint8_t *pucMicKey = NULL; \ + ucBssIndex = \ + prCurrSwRfb->prStaRec->ucBssIndex; \ + ASSERT(ucBssIndex < prAdapter->ucHwBssIdNum); \ + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, \ + ucBssIndex); \ + ASSERT(prBssInfo); \ + if (prBssInfo->eCurrentOPMode == \ + OP_MODE_INFRASTRUCTURE) \ + pucMicKey = \ + &(prAdapter->rWifiVar.\ + rAisSpecificBssInfo.aucRxMicKey[0]); \ + else { \ + ASSERT(FALSE); \ + } \ + /* SW TKIP MIC verify */ \ + if (pucMicKey == NULL) { \ + DBGLOG(RX, ERROR, \ + "No TKIP Mic Key\n"); \ + fgMicErr = TRUE; \ + } \ + else if (tkipMicDecapsulateInRxHdrTransMode( \ + prCurrSwRfb, pucMicKey) == FALSE) { \ + fgMicErr = TRUE; \ + } \ + } \ + if (fgMicErr) { \ + /* bypass tkip frag */ \ + if (!prCurrSwRfb->fgFragFrame) { \ + log_dbg(RX, ERROR, \ + "Mark NULL for TKIP Mic Error\n"); \ + RX_INC_CNT(&prAdapter->rRxCtrl, \ + RX_MIC_ERROR_DROP_COUNT); \ + prCurrSwRfb->eDst = \ + RX_PKT_DESTINATION_NULL; \ + } \ + } \ + } \ + QUEUE_INSERT_TAIL(prReturnedQue, \ + (struct QUE_ENTRY *)prCurrSwRfb); \ + } \ +} while (0) +#endif + +#define RX_DIRECT_REORDER_LOCK(pad, dbg) \ +do { \ + struct GLUE_INFO *_glue = pad->prGlueInfo; \ + if (!HAL_IS_RX_DIRECT(pad) || !_glue) \ + break; \ + if (dbg) \ + DBGLOG(QM, EVENT, "RX_DIRECT_REORDER_LOCK %d\n", __LINE__); \ + if (irqs_disabled()) \ + spin_lock(&_glue->rSpinLock[SPIN_LOCK_RX_DIRECT_REORDER]); \ + else \ + spin_lock_bh(&_glue->rSpinLock[SPIN_LOCK_RX_DIRECT_REORDER]); \ +} while (0) + +#define RX_DIRECT_REORDER_UNLOCK(pad, dbg) \ +do { \ + struct GLUE_INFO *_glue = pad->prGlueInfo; \ + if (!HAL_IS_RX_DIRECT(pad) || !_glue) \ + break; \ + if (dbg) \ + DBGLOG(QM, EVENT, "RX_DIRECT_REORDER_UNLOCK %u\n", __LINE__); \ + if (irqs_disabled()) \ + spin_unlock(&_glue->rSpinLock[SPIN_LOCK_RX_DIRECT_REORDER]); \ + else \ + spin_unlock_bh(&_glue->rSpinLock[SPIN_LOCK_RX_DIRECT_REORDER]);\ +} while (0) + +/******************************************************************************* + * 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 Queue Management for TX + * + * \param[in] (none) + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void qmInit(IN struct ADAPTER *prAdapter, + IN u_int8_t isTxResrouceControlEn) +{ + uint32_t u4Idx; +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + uint32_t u4TotalMinReservedTcResource = 0; + uint32_t u4TotalTcResource = 0; + uint32_t u4TotalGurantedTcResource = 0; +#endif + + struct QUE_MGT *prQM = &prAdapter->rQM; + + /* DbgPrint("QM: Enter qmInit()\n"); */ + + /* 4 <2> Initialize other TX queues (queues not in STA_RECs) */ + for (u4Idx = 0; u4Idx < NUM_OF_PER_TYPE_TX_QUEUES; u4Idx++) + QUEUE_INITIALIZE(&(prQM->arTxQueue[u4Idx])); + + /* 4 <3> Initialize the RX BA table and RX queues */ + /* Initialize the RX Reordering Parameters and Queues */ + for (u4Idx = 0; u4Idx < CFG_NUM_OF_RX_BA_AGREEMENTS; u4Idx++) { + prQM->arRxBaTable[u4Idx].fgIsValid = FALSE; + QUEUE_INITIALIZE(&(prQM->arRxBaTable[u4Idx].rReOrderQue)); + prQM->arRxBaTable[u4Idx].u2WinStart = 0xFFFF; + prQM->arRxBaTable[u4Idx].u2WinEnd = 0xFFFF; + + prQM->arRxBaTable[u4Idx].fgIsWaitingForPktWithSsn = FALSE; + prQM->arRxBaTable[u4Idx].fgHasBubble = FALSE; +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + prQM->arRxBaTable[u4Idx].u8LastAmsduSubIdx = + RX_PAYLOAD_FORMAT_MSDU; + prQM->arRxBaTable[u4Idx].fgAmsduNeedLastFrame = FALSE; + prQM->arRxBaTable[u4Idx].fgIsAmsduDuplicated = FALSE; +#endif + prQM->arRxBaTable[u4Idx].fgFirstSnToWinStart = FALSE; + cnmTimerInitTimer(prAdapter, + &(prQM->arRxBaTable[u4Idx].rReorderBubbleTimer), + (PFN_MGMT_TIMEOUT_FUNC) qmHandleReorderBubbleTimeout, + (unsigned long) (&prQM->arRxBaTable[u4Idx])); + + } + prQM->ucRxBaCount = 0; + + kalMemSet(&g_arMissTimeout, 0, sizeof(g_arMissTimeout)); + + prQM->fgIsTxResrouceControlEn = isTxResrouceControlEn; + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + /* 4 <4> Initialize TC resource control variables */ + for (u4Idx = 0; u4Idx < TC_NUM; u4Idx++) + prQM->au4AverageQueLen[u4Idx] = 0; + + ASSERT(prQM->u4TimeToAdjustTcResource + && prQM->u4TimeToUpdateQueLen); + + for (u4Idx = 0; u4Idx < TC_NUM; u4Idx++) { + prQM->au4CurrentTcResource[u4Idx] = + prAdapter->rTxCtrl.rTc.au4MaxNumOfBuffer[u4Idx]; + + if (u4Idx != TC4_INDEX) { + u4TotalTcResource += prQM->au4CurrentTcResource[u4Idx]; + u4TotalGurantedTcResource += + prQM->au4GuaranteedTcResource[u4Idx]; + u4TotalMinReservedTcResource += + prQM->au4MinReservedTcResource[u4Idx]; + } + } + + /* Sanity Check */ + if (u4TotalMinReservedTcResource > u4TotalTcResource) + kalMemZero(prQM->au4MinReservedTcResource, + sizeof(prQM->au4MinReservedTcResource)); + + if (u4TotalGurantedTcResource > u4TotalTcResource) + kalMemZero(prQM->au4GuaranteedTcResource, + sizeof(prQM->au4GuaranteedTcResource)); + + u4TotalGurantedTcResource = 0; + + /* Initialize Residual TC resource */ + for (u4Idx = 0; u4Idx < TC_NUM; u4Idx++) { + if (prQM->au4GuaranteedTcResource[u4Idx] < + prQM->au4MinReservedTcResource[u4Idx]) + prQM->au4GuaranteedTcResource[u4Idx] = + prQM->au4MinReservedTcResource[u4Idx]; + + if (u4Idx != TC4_INDEX) + u4TotalGurantedTcResource += + prQM->au4GuaranteedTcResource[u4Idx]; + } + + prQM->u4ResidualTcResource = u4TotalTcResource - + u4TotalGurantedTcResource; + + prQM->fgTcResourcePostAnnealing = FALSE; + prQM->fgForceReassign = FALSE; +#if QM_FAST_TC_RESOURCE_CTRL + prQM->fgTcResourceFastReaction = FALSE; +#endif +#endif + +#if QM_TEST_MODE + prQM->u4PktCount = 0; + +#if QM_TEST_FAIR_FORWARDING + + prQM->u4CurrentStaRecIndexToEnqueue = 0; + { + uint8_t aucMacAddr[MAC_ADDR_LEN]; + struct STA_RECORD *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->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + COPY_MAC_ADDR((prStaRec)->aucMacAddr, aucMacAddr); + + } + +#endif + +#endif + +#if QM_FORWARDING_FAIRNESS + for (u4Idx = 0; u4Idx < NUM_OF_PER_STA_TX_QUEUES; u4Idx++) { + prQM->au4ResourceUsedCount[u4Idx] = 0; + prQM->au4HeadStaRecIndex[u4Idx] = 0; + } + + prQM->u4GlobalResourceUsedCount = 0; +#endif + + prQM->u4TxAllowedStaCount = 0; + + prQM->rLastTxPktDumpTime = (OS_SYSTIME) kalGetTimeTick(); + +} + +#if QM_TEST_MODE +void qmTestCases(IN struct ADAPTER *prAdapter) +{ + struct QUE_MGT *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, &prAdapter->arStaRec[0]); + } else { + + uint8_t 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 Update a STA_REC + * + * \param[in] prAdapter Pointer to the Adapter instance + * \param[in] prStaRec The pointer of the STA_REC + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void qmUpdateStaRec(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + struct BSS_INFO *prBssInfo; + u_int8_t fgIsTxAllowed = FALSE; + + if (!prStaRec) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + ASSERT(prBssInfo); + + /* 4 <1> Ensure STA is valid */ + if (prStaRec->fgIsValid) { + /* 4 <2.1> STA/BSS is protected */ + if (secIsProtectedBss(prAdapter, prBssInfo)) { + if (prStaRec->fgIsTxKeyReady || + secIsWepBss(prAdapter, prBssInfo)) + fgIsTxAllowed = TRUE; + else + fgIsTxAllowed = FALSE; + } + /* 4 <2.2> OPEN security */ + else + fgIsTxAllowed = TRUE; + } + /* 4 Update StaRec */ + qmSetStaRecTxAllowed(prAdapter, prStaRec, fgIsTxAllowed); + +#if CFG_SUPPORT_BFER + if ((IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaVhtBfer) || + IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaHtBfer)) && + fgIsTxAllowed && (prStaRec->ucStaState == STA_STATE_3)) { + rlmBfStaRecPfmuUpdate(prAdapter, prStaRec); + rlmETxBfTriggerPeriodicSounding(prAdapter); + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Activate a STA_REC + * + * \param[in] prAdapter Pointer to the Adapter instance + * \param[in] prStaRec The pointer of the STA_REC + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void qmActivateStaRec(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + /* 4 <1> Deactivate first */ + if (!prStaRec) + return; + + if (prStaRec->fgIsValid) { /* The STA_REC has been activated */ + DBGLOG(QM, WARN, + "QM: (WARNING) Activating a STA_REC which has been activated\n"); + DBGLOG(QM, WARN, + "QM: (WARNING) Deactivating a STA_REC before re-activating\n"); + /* To flush TX/RX queues and del RX BA agreements */ + qmDeactivateStaRec(prAdapter, prStaRec); + } + /* 4 <2> Activate the STA_REC */ + /* Reset buffer count */ + prStaRec->ucFreeQuota = 0; + prStaRec->ucFreeQuotaForDelivery = 0; + prStaRec->ucFreeQuotaForNonDelivery = 0; + + /* Init the STA_REC */ + prStaRec->fgIsValid = TRUE; + prStaRec->fgIsInPS = FALSE; + + /* Default setting of TX/RX AMPDU */ + prStaRec->fgTxAmpduEn = IS_FEATURE_ENABLED( + prAdapter->rWifiVar.ucAmpduTx); + prStaRec->fgRxAmpduEn = IS_FEATURE_ENABLED( + prAdapter->rWifiVar.ucAmpduRx); + + nicTxGenerateDescTemplate(prAdapter, prStaRec); + + qmUpdateStaRec(prAdapter, prStaRec); + + /* 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[%d]\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 struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + uint32_t i; + + if (!prStaRec) + return; + /* 4 <1> Flush TX queues */ + if (HAL_IS_TX_DIRECT(prAdapter)) { + nicTxDirectClearStaPsQ(prAdapter, prStaRec->ucIndex); + } else { + struct MSDU_INFO *prFlushedTxPacketList = NULL; + + prFlushedTxPacketList = qmFlushStaTxQueues(prAdapter, + prStaRec->ucIndex); + + 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, prStaRec->ucIndex, (uint8_t) i, + FALSE); + } + + /* 4 <3> Deactivate the STA_REC */ + prStaRec->fgIsValid = FALSE; + prStaRec->fgIsInPS = FALSE; + prStaRec->fgIsTxKeyReady = FALSE; + + /* Reset buffer count */ + prStaRec->ucFreeQuota = 0; + prStaRec->ucFreeQuotaForDelivery = 0; + prStaRec->ucFreeQuotaForNonDelivery = 0; + + nicTxFreeDescTemplate(prAdapter, prStaRec); + + qmUpdateStaRec(prAdapter, prStaRec); + + DBGLOG(QM, INFO, "QM: -STA[%u]\n", prStaRec->ucIndex); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Deactivate a STA_REC + * + * \param[in] prAdapter Pointer to the Adapter instance + * \param[in] ucBssIndex The index of the BSS + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void qmFreeAllByBssIdx(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIndex) +{ + + struct QUE_MGT *prQM; + struct QUE *prQue; + struct QUE rNeedToFreeQue; + struct QUE rTempQue; + struct QUE *prNeedToFreeQue; + struct QUE *prTempQue; + struct MSDU_INFO *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, + struct MSDU_INFO *); + while (prMsduInfo) { + + if (prMsduInfo->ucBssIndex == ucBssIndex) { + /* QUEUE_INSERT_TAIL */ + QUEUE_INSERT_TAIL(prNeedToFreeQue, + (struct QUE_ENTRY *) prMsduInfo); + } else { + /* QUEUE_INSERT_TAIL */ + QUEUE_INSERT_TAIL(prQue, + (struct QUE_ENTRY *) prMsduInfo); + } + + QUEUE_REMOVE_HEAD(prTempQue, prMsduInfo, + struct MSDU_INFO *); + } + if (QUEUE_IS_NOT_EMPTY(prNeedToFreeQue)) + wlanProcessQueuedMsduInfo(prAdapter, + (struct MSDU_INFO *) + QUEUE_GET_HEAD(prNeedToFreeQue)); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Flush all TX queues + * + * \param[in] (none) + * + * \return The flushed packets (in a list of MSDU_INFOs) + */ +/*----------------------------------------------------------------------------*/ +struct MSDU_INFO *qmFlushTxQueues(IN struct ADAPTER *prAdapter) +{ + uint8_t ucStaArrayIdx; + uint8_t ucQueArrayIdx; + + struct QUE_MGT *prQM = &prAdapter->rQM; + + struct QUE rTempQue; + struct QUE *prTempQue = &rTempQue; + struct QUE *prQue; + + DBGLOG(QM, TRACE, "QM: Enter qmFlushTxQueues()\n"); + + QUEUE_INITIALIZE(prTempQue); + + /* Concatenate all MSDU_INFOs in per-STA queues */ + for (ucStaArrayIdx = 0; ucStaArrayIdx < CFG_STA_REC_NUM; + ucStaArrayIdx++) { + for (ucQueArrayIdx = 0; + ucQueArrayIdx < NUM_OF_PER_STA_TX_QUEUES; + ucQueArrayIdx++) { + prQue = &(prAdapter->arStaRec[ucStaArrayIdx]. + arPendingTxQueue[ucQueArrayIdx]); + QUEUE_CONCATENATE_QUEUES(prTempQue, prQue); + prQue = &(prAdapter->arStaRec[ucStaArrayIdx]. + arTxQueue[ucQueArrayIdx]); + QUEUE_CONCATENATE_QUEUES(prTempQue, prQue); + } + } + + /* Flush per-Type queues */ + for (ucQueArrayIdx = 0; + ucQueArrayIdx < NUM_OF_PER_TYPE_TX_QUEUES; + ucQueArrayIdx++) { + prQue = &(prQM->arTxQueue[ucQueArrayIdx]); + QUEUE_CONCATENATE_QUEUES(prTempQue, prQue); + } + + return (struct MSDU_INFO *)QUEUE_GET_HEAD(prTempQue); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Flush TX packets for a particular STA + * + * \param[in] u4StaRecIdx STA_REC index + * + * \return The flushed packets (in a list of MSDU_INFOs) + */ +/*----------------------------------------------------------------------------*/ +struct MSDU_INFO *qmFlushStaTxQueues(IN struct ADAPTER *prAdapter, + IN uint32_t u4StaRecIdx) +{ + uint8_t ucQueArrayIdx; + struct STA_RECORD *prStaRec; + struct QUE *prQue; + struct QUE rTempQue; + struct QUE *prTempQue = &rTempQue; + + DBGLOG(QM, TRACE, "QM: Enter qmFlushStaTxQueues(%u)\n", u4StaRecIdx); + + ASSERT(u4StaRecIdx < CFG_STA_REC_NUM); + + prStaRec = &prAdapter->arStaRec[u4StaRecIdx]; + ASSERT(prStaRec); + + QUEUE_INITIALIZE(prTempQue); + + /* Concatenate all MSDU_INFOs in TX queues of this STA_REC */ + for (ucQueArrayIdx = 0; + ucQueArrayIdx < NUM_OF_PER_STA_TX_QUEUES; ucQueArrayIdx++) { + prQue = &(prStaRec->arPendingTxQueue[ucQueArrayIdx]); + QUEUE_CONCATENATE_QUEUES(prTempQue, prQue); + prQue = &(prStaRec->arTxQueue[ucQueArrayIdx]); + QUEUE_CONCATENATE_QUEUES(prTempQue, prQue); + } + + return (struct MSDU_INFO *)QUEUE_GET_HEAD(prTempQue); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Flush RX packets + * + * \param[in] (none) + * + * \return The flushed packets (in a list of SW_RFBs) + */ +/*----------------------------------------------------------------------------*/ +struct SW_RFB *qmFlushRxQueues(IN struct ADAPTER *prAdapter) +{ + uint32_t i; + struct SW_RFB *prSwRfbListHead; + struct SW_RFB *prSwRfbListTail; + struct QUE_MGT *prQM = &prAdapter->rQM; + + prSwRfbListHead = prSwRfbListTail = NULL; + + DBGLOG(QM, TRACE, "QM: Enter qmFlushRxQueues()\n"); + + RX_DIRECT_REORDER_LOCK(prAdapter, 0); + 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 = (struct SW_RFB *) + QUEUE_GET_HEAD( + &(prQM->arRxBaTable[i]. + rReOrderQue)); + prSwRfbListTail = (struct SW_RFB *) + 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 = (struct SW_RFB *) + QUEUE_GET_TAIL( + &(prQM->arRxBaTable[i]. + rReOrderQue)); + } + + QUEUE_INITIALIZE(&(prQM->arRxBaTable[i].rReOrderQue)); + if (QM_RX_GET_NEXT_SW_RFB(prSwRfbListTail)) { + DBGLOG(QM, ERROR, + "QM: non-null tail->next at arRxBaTable[%u]\n", + i); + } + } else { + continue; + } + } + RX_DIRECT_REORDER_UNLOCK(prAdapter, 0); + + 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) + */ +/*----------------------------------------------------------------------------*/ +struct SW_RFB *qmFlushStaRxQueue(IN struct ADAPTER *prAdapter, + IN uint32_t u4StaRecIdx, IN uint32_t u4Tid) +{ + /* UINT_32 i; */ + struct SW_RFB *prSwRfbListHead; + struct SW_RFB *prSwRfbListTail; + struct RX_BA_ENTRY *prReorderQueParm; + struct STA_RECORD *prStaRec; + + DBGLOG(QM, TRACE, "QM: Enter qmFlushStaRxQueues(%u)\n", u4StaRecIdx); + + prSwRfbListHead = prSwRfbListTail = NULL; + + prStaRec = &prAdapter->arStaRec[u4StaRecIdx]; + ASSERT(prStaRec); + + /* No matter whether this is an activated STA_REC, do flush */ +#if 0 + if (!prStaRec->fgIsValid) + return NULL; +#endif + + /* Obtain the RX BA Entry pointer */ + prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[u4Tid]); + + /* Note: For each queued packet, + * prCurrSwRfb->eDst equals RX_PKT_DESTINATION_HOST + */ + if (prReorderQueParm) { + RX_DIRECT_REORDER_LOCK(prAdapter, 0); + if (QUEUE_IS_NOT_EMPTY(&(prReorderQueParm->rReOrderQue))) { + + prSwRfbListHead = (struct SW_RFB *) + QUEUE_GET_HEAD( + &(prReorderQueParm->rReOrderQue)); + prSwRfbListTail = (struct SW_RFB *) + QUEUE_GET_TAIL( + &(prReorderQueParm->rReOrderQue)); + + QUEUE_INITIALIZE(&(prReorderQueParm->rReOrderQue)); + } + RX_DIRECT_REORDER_UNLOCK(prAdapter, 0); + } + + if (prSwRfbListTail) { + if (QM_RX_GET_NEXT_SW_RFB(prSwRfbListTail)) { + DBGLOG(QM, ERROR, + "QM: non-empty tail->next at STA %u TID %u\n", + u4StaRecIdx, u4Tid); + } + + /* Terminate the MSDU_INFO list with a NULL pointer */ + QM_TX_SET_NEXT_SW_RFB(prSwRfbListTail, NULL); + } + return prSwRfbListHead; +} + +struct QUE *qmDetermineStaTxQueue(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN uint8_t ucActiveTs, OUT uint8_t *pucTC) +{ + struct QUE *prTxQue = NULL; + struct STA_RECORD *prStaRec; + enum ENUM_WMM_ACI eAci = WMM_AC_BE_INDEX; + u_int8_t fgCheckACMAgain; + uint8_t ucTC, ucQueIdx = WMM_AC_BE_INDEX; + struct BSS_INFO *prBssInfo; + /* BEtoBK, na, VItoBE, VOtoVI */ + uint8_t aucNextUP[WMM_AC_INDEX_NUM] = {1, 1, 0, 4}; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prMsduInfo->ucBssIndex); + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, + prMsduInfo->ucStaRecIndex); + if (prStaRec == NULL) + return prTxQue; + + if (!prStaRec) { + DBGLOG(QM, ERROR, "prStaRec is null.\n"); + return NULL; + } + if (prMsduInfo->ucUserPriority < 8) { + QM_DBG_CNT_INC(&prAdapter->rQM, + prMsduInfo->ucUserPriority + 15); + } + + eAci = WMM_AC_BE_INDEX; + do { + fgCheckACMAgain = FALSE; + if (prStaRec->fgIsQoS) { + if (prMsduInfo->ucUserPriority < TX_DESC_TID_NUM) { + eAci = aucTid2ACI[prMsduInfo->ucUserPriority]; + ucQueIdx = aucACI2TxQIdx[eAci]; + ucTC = + arNetwork2TcResource[ + prMsduInfo->ucBssIndex][eAci]; + } else { + ucQueIdx = TX_QUEUE_INDEX_AC1; + ucTC = TC1_INDEX; + eAci = WMM_AC_BE_INDEX; + DBGLOG(QM, WARN, + "Packet TID is not in [0~7]\n"); + ASSERT(0); + } + if ((prBssInfo->arACQueParms[eAci].ucIsACMSet) && + !(ucActiveTs & BIT(eAci)) && + (eAci != WMM_AC_BK_INDEX)) { + DBGLOG(WMM, TRACE, + "ucUserPriority: %d, aucNextUP[eAci]: %d", + prMsduInfo->ucUserPriority, + aucNextUP[eAci]); + prMsduInfo->ucUserPriority = aucNextUP[eAci]; + fgCheckACMAgain = TRUE; + } + } else { + ucQueIdx = TX_QUEUE_INDEX_NON_QOS; + ucTC = arNetwork2TcResource[prMsduInfo->ucBssIndex][ + NET_TC_WMM_AC_BE_INDEX]; + } + + if (prAdapter->rWifiVar.ucTcRestrict < TC_NUM) { + ucTC = prAdapter->rWifiVar.ucTcRestrict; + ucQueIdx = ucTC; + } + + } while (fgCheckACMAgain); + + if (ucQueIdx >= NUM_OF_PER_STA_TX_QUEUES) { + DBGLOG(QM, ERROR, + "ucQueIdx = %u, needs 0~3 to avoid out-of-bounds.\n", + ucQueIdx); + return NULL; + } + if (prStaRec->fgIsTxAllowed) { + /* non protected BSS or protected BSS with key set */ + prTxQue = prStaRec->aprTargetQueue[ucQueIdx]; + } else if (secIsProtectedBss(prAdapter, prBssInfo) && + prMsduInfo->fgIs802_1x && + prMsduInfo->fgIs802_1x_NonProtected) { + /* protected BSS without key set */ + /* Tx pairwise EAPOL 1x packet (non-protected frame) */ + prTxQue = &prStaRec->arTxQueue[ucQueIdx]; + } else { + /* protected BSS without key set */ + /* Enqueue protected frame into pending queue */ + prTxQue = prStaRec->aprTargetQueue[ucQueIdx]; + } + + *pucTC = ucTC; + /* + * Record how many packages enqueue this STA + * to TX during statistic intervals + */ + prStaRec->u4EnqueueCounter++; + + return prTxQue; +} + +void qmSetTxPacketDescTemplate(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct STA_RECORD *prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX( + prAdapter, prMsduInfo->ucStaRecIndex); + + /* Check the Tx descriptor template is valid */ + if (prStaRec && + prStaRec->aprTxDescTemplate[prMsduInfo->ucUserPriority]) { + prMsduInfo->fgIsTXDTemplateValid = TRUE; + } else { + if (prStaRec) { + DBGLOG(QM, TRACE, + "Cannot get TXD template for STA[%u] QoS[%u] MSDU UP[%u]\n", + prStaRec->ucIndex, prStaRec->fgIsQoS, + prMsduInfo->ucUserPriority); + } + prMsduInfo->fgIsTXDTemplateValid = FALSE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief : To StaRec, function to stop TX + * + * \param[in] : + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void qmSetStaRecTxAllowed(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, IN u_int8_t fgIsTxAllowed) +{ + uint8_t ucIdx; + struct QUE *prSrcQ, *prDstQ; + + DBGLOG(QM, INFO, "Set Sta[%u] TxAllowed from [%u] to [%u] %s TxQ\n", + prStaRec->ucIndex, + prStaRec->fgIsTxAllowed, + fgIsTxAllowed, + fgIsTxAllowed ? "normal" : "pending"); + + /* Update Tx queue when allowed state change*/ + if (prStaRec->fgIsTxAllowed != fgIsTxAllowed) { + for (ucIdx = 0; ucIdx < NUM_OF_PER_STA_TX_QUEUES; ucIdx++) { + if (fgIsTxAllowed) { + prSrcQ = &prStaRec->arPendingTxQueue[ucIdx]; + prDstQ = &prStaRec->arTxQueue[ucIdx]; + } else { + prSrcQ = &prStaRec->arTxQueue[ucIdx]; + prDstQ = &prStaRec->arPendingTxQueue[ucIdx]; + } + + QUEUE_CONCATENATE_QUEUES_HEAD(prDstQ, prSrcQ); + prStaRec->aprTargetQueue[ucIdx] = prDstQ; + } + + if (fgIsTxAllowed) + prAdapter->rQM.u4TxAllowedStaCount++; + else + prAdapter->rQM.u4TxAllowedStaCount--; + + } + prStaRec->fgIsTxAllowed = fgIsTxAllowed; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Enqueue TX packets + * + * \param[in] prMsduInfoListHead Pointer to the list of TX packets + * + * \return The freed packets, which are not enqueued + */ +/*----------------------------------------------------------------------------*/ +struct MSDU_INFO *qmEnqueueTxPackets(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfoListHead) +{ + struct MSDU_INFO *prMsduInfoReleaseList; + struct MSDU_INFO *prCurrentMsduInfo; + struct MSDU_INFO *prNextMsduInfo; + + struct QUE *prTxQue; + struct QUE rNotEnqueuedQue; + struct STA_RECORD *prStaRec; + uint8_t ucTC; + struct TX_CTRL *prTxCtrl = &prAdapter->rTxCtrl; + struct QUE_MGT *prQM = &prAdapter->rQM; + struct BSS_INFO *prBssInfo; + u_int8_t fgDropPacket; + uint8_t ucActivedTspec = 0; + + DBGLOG(QM, LOUD, "Enter qmEnqueueTxPackets\n"); + + ASSERT(prMsduInfoListHead); + + prMsduInfoReleaseList = NULL; + prCurrentMsduInfo = NULL; + QUEUE_INITIALIZE(&rNotEnqueuedQue); + prNextMsduInfo = prMsduInfoListHead; + ucActivedTspec = wmmHasActiveTspec(&prAdapter->rWifiVar.rWmmInfo); + + do { + prCurrentMsduInfo = prNextMsduInfo; + prNextMsduInfo = QM_TX_GET_NEXT_MSDU_INFO( + prCurrentMsduInfo); + ucTC = TC1_INDEX; + + /* 4 <0> Sanity check of BSS_INFO */ + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prCurrentMsduInfo->ucBssIndex); + + if (!prBssInfo) { + /* No BSS_INFO */ + fgDropPacket = TRUE; + } else if (IS_BSS_ACTIVE(prBssInfo)) { + /* BSS active */ + fgDropPacket = FALSE; + } else { + /* BSS inactive */ + fgDropPacket = TRUE; + } + + if (!fgDropPacket) { + /* 4 <1> Lookup the STA_REC index */ + /* The ucStaRecIndex will be set in this function */ + qmDetermineStaRecIndex(prAdapter, prCurrentMsduInfo); + + /*get per-AC Tx packets */ + wlanUpdateTxStatistics(prAdapter, prCurrentMsduInfo, + FALSE); + + DBGLOG(QM, LOUD, "Enqueue MSDU by StaRec[%u]!\n", + prCurrentMsduInfo->ucStaRecIndex); + + switch (prCurrentMsduInfo->ucStaRecIndex) { + case STA_REC_INDEX_BMCAST: + prTxQue = + &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST]; + ucTC = + arNetwork2TcResource[prCurrentMsduInfo-> + ucBssIndex][NET_TC_BMC_INDEX]; + + /* Always set BMC packet retry limit + * to unlimited + */ + if (!(prCurrentMsduInfo->u4Option & + MSDU_OPT_MANUAL_RETRY_LIMIT)) + nicTxSetPktRetryLimit(prCurrentMsduInfo, + TX_DESC_TX_COUNT_NO_LIMIT); + + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_23); + break; + + case STA_REC_INDEX_NOT_FOUND: + /* Drop packet if no STA_REC is found */ + DBGLOG(QM, TRACE, + "Drop the Packet for no STA_REC\n"); + + prTxQue = &rNotEnqueuedQue; + + TX_INC_CNT(&prAdapter->rTxCtrl, + TX_INACTIVE_STA_DROP); + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_24); + break; + + default: + prTxQue = qmDetermineStaTxQueue( + prAdapter, prCurrentMsduInfo, + ucActivedTspec, &ucTC); + if (!prTxQue) { + DBGLOG(QM, INFO, + "Drop the Packet for TxQue is NULL\n"); + prTxQue = &rNotEnqueuedQue; + TX_INC_CNT(&prAdapter->rTxCtrl, + TX_INACTIVE_STA_DROP); + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_24); + } +#if ARP_MONITER_ENABLE + prStaRec = + QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, + prCurrentMsduInfo-> + ucStaRecIndex); + if (prStaRec && IS_STA_IN_AIS(prStaRec) && + prCurrentMsduInfo->eSrc == TX_PACKET_OS) + qmDetectArpNoResponse(prAdapter, + prCurrentMsduInfo); +#endif + break; /*default */ + } /* switch (prCurrentMsduInfo->ucStaRecIndex) */ + + if (prCurrentMsduInfo->eSrc == TX_PACKET_FORWARDING) { + DBGLOG(QM, TRACE, + "Forward Pkt to STA[%u] BSS[%u]\n", + prCurrentMsduInfo->ucStaRecIndex, + prCurrentMsduInfo->ucBssIndex); + + if (prTxQue->u4NumElem >= + prQM->u4MaxForwardBufferCount) { + DBGLOG(QM, INFO, + "Drop the Packet for full Tx queue (forwarding) Bss %u\n", + prCurrentMsduInfo->ucBssIndex); + prTxQue = &rNotEnqueuedQue; + TX_INC_CNT(&prAdapter->rTxCtrl, + TX_FORWARD_OVERFLOW_DROP); + } + } + + } else { + DBGLOG(QM, TRACE, + "Drop the Packet for inactive Bss %u\n", + prCurrentMsduInfo->ucBssIndex); + 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 */ + /* Note that the BSS Index and STA_REC index are determined in + * qmDetermineStaRecIndex(prCurrentMsduInfo). + */ + prCurrentMsduInfo->ucTC = ucTC; + + /* Check the Tx descriptor template is valid */ + qmSetTxPacketDescTemplate(prAdapter, prCurrentMsduInfo); + + /* Set Tx rate */ + switch (prAdapter->rWifiVar.ucDataTxRateMode) { + case DATA_RATE_MODE_BSS_LOWEST: + nicTxSetPktLowestFixedRate(prAdapter, + prCurrentMsduInfo); + break; + + case DATA_RATE_MODE_MANUAL: + prCurrentMsduInfo->u4FixedRateOption = + prAdapter->rWifiVar.u4DataTxRateCode; + + prCurrentMsduInfo->ucRateMode = + MSDU_RATE_MODE_MANUAL_DESC; + break; + + case DATA_RATE_MODE_AUTO: + default: + if (prCurrentMsduInfo->ucRateMode == + MSDU_RATE_MODE_LOWEST_RATE) + nicTxSetPktLowestFixedRate(prAdapter, + prCurrentMsduInfo); + break; + } + + /* 4 <4> Enqueue the packet */ + QUEUE_INSERT_TAIL(prTxQue, + (struct QUE_ENTRY *) prCurrentMsduInfo); + wlanFillTimestamp(prAdapter, prCurrentMsduInfo->prPacket, + PHASE_ENQ_QM); + /* + * Record how many packages enqueue + * to TX during statistic intervals + */ + if (prTxQue != &rNotEnqueuedQue) { + prQM->u4EnqueueCounter++; + /* how many page count this frame wanted */ + prQM->au4QmTcWantedPageCounter[ucTC] += + prCurrentMsduInfo->u4PageCount; + } +#if QM_TC_RESOURCE_EMPTY_COUNTER + if (prCurrentMsduInfo->u4PageCount > + prTxCtrl->rTc.au4FreePageCount[ucTC]) + prQM->au4QmTcResourceEmptyCounter[ + prCurrentMsduInfo->ucBssIndex][ucTC]++; +#endif + +#if QM_FAST_TC_RESOURCE_CTRL && QM_ADAPTIVE_TC_RESOURCE_CTRL + if (prTxQue != &rNotEnqueuedQue) { + /* Check and trigger fast TC resource + * adjustment for queued packets + */ + qmCheckForFastTcResourceCtrl(prAdapter, ucTC); + } +#endif + +#if QM_TEST_MODE + if (++prQM->u4PktCount == QM_TEST_TRIGGER_TX_COUNT) { + prQM->u4PktCount = 0; + qmTestCases(prAdapter); + } +#endif + } while (prNextMsduInfo); + + if (QUEUE_IS_NOT_EMPTY(&rNotEnqueuedQue)) { + QM_TX_SET_NEXT_MSDU_INFO((struct MSDU_INFO *) + QUEUE_GET_TAIL(&rNotEnqueuedQue), NULL); + prMsduInfoReleaseList = (struct MSDU_INFO *) QUEUE_GET_HEAD( + &rNotEnqueuedQue); + } +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + /* 4 Update TC resource control related variables */ + /* Keep track of the queue length */ + qmDoAdaptiveTcResourceCtrl(prAdapter); +#endif + + return prMsduInfoReleaseList; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Determine the STA_REC index for a packet + * + * \param[in] prMsduInfo Pointer to the packet + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void qmDetermineStaRecIndex(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + uint32_t i; + + struct STA_RECORD *prTempStaRec; + struct BSS_INFO *prBssInfo; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + prTempStaRec = NULL; + + ASSERT(prMsduInfo); + + DBGLOG(QM, LOUD, + "Msdu BSS Idx[%u] OpMode[%u] StaRecOfApExist[%u]\n", + prMsduInfo->ucBssIndex, prBssInfo->eCurrentOPMode, + prBssInfo->prStaRecOfAP ? TRUE : FALSE); + + switch (prBssInfo->eCurrentOPMode) { + case OP_MODE_IBSS: + case OP_MODE_ACCESS_POINT: + /* 4 <1> DA = BMCAST */ + if (IS_BMCAST_MAC_ADDR(prMsduInfo->aucEthDestAddr)) { + prMsduInfo->ucStaRecIndex = STA_REC_INDEX_BMCAST; + DBGLOG(QM, LOUD, "TX with DA = BMCAST\n"); + return; + } + break; + + /* Infra Client/GC */ + case OP_MODE_INFRASTRUCTURE: + case OP_MODE_BOW: +#if CFG_SUPPORT_TDLS + prTempStaRec = + cnmGetTdlsPeerByAddress(prAdapter, + prBssInfo->ucBssIndex, + prMsduInfo->aucEthDestAddr); + if (IS_DLS_STA(prTempStaRec) + && prTempStaRec->ucStaState == STA_STATE_3) { + if (g_arTdlsLink[prTempStaRec->ucTdlsIndex]) { + prMsduInfo->ucStaRecIndex = + prTempStaRec->ucIndex; + return; + } + } +#endif + /* 4 <2> Check if an AP STA is present */ + prTempStaRec = prBssInfo->prStaRecOfAP; + if (prTempStaRec) { + DBGLOG(QM, LOUD, + "StaOfAp Idx[%u] WIDX[%u] Valid[%u] TxAllowed[%u] InUse[%u] Type[%u]\n", + prTempStaRec->ucIndex, + prTempStaRec->ucWlanIndex, + prTempStaRec->fgIsValid, + prTempStaRec->fgIsTxAllowed, + prTempStaRec->fgIsInUse, + prTempStaRec->eStaType); + + if (prTempStaRec->fgIsInUse) { + prMsduInfo->ucStaRecIndex = + prTempStaRec->ucIndex; + DBGLOG(QM, LOUD, "TX with AP_STA[%u]\n", + prTempStaRec->ucIndex); + return; + } + } + break; + + case OP_MODE_P2P_DEVICE: + break; + + default: + break; + } + + /* 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_STA_REC_NUM; i++) { + prTempStaRec = &(prAdapter->arStaRec[i]); + if (prTempStaRec->fgIsInUse) { + if (EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, + prMsduInfo->aucEthDestAddr)) { + prMsduInfo->ucStaRecIndex = + prTempStaRec->ucIndex; + DBGLOG(QM, LOUD, "TX with STA[%u]\n", + 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 = + (uint8_t) prQM->u4CurrentStaRecIndexToEnqueue; +#endif +} + +struct STA_RECORD *qmDetermineStaToBeDequeued( + IN struct ADAPTER *prAdapter, + IN uint32_t u4StartStaRecIndex) +{ + + return NULL; +} + +struct QUE *qmDequeueStaTxPackets(IN struct ADAPTER *prAdapter) +{ + + return NULL; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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) + */ +/*----------------------------------------------------------------------------*/ +uint32_t +qmDequeueTxPacketsFromPerStaQueues(IN struct ADAPTER *prAdapter, + OUT struct QUE *prQue, IN uint8_t ucTC, + IN uint32_t u4CurrentQuota, + IN uint32_t *prPleCurrentQuota, + IN uint32_t u4TotalQuota) +{ + uint32_t ucLoop; /* Loop for */ + + uint32_t u4CurStaIndex = 0; + uint32_t u4CurStaUsedResource = 0; + + /* The current focused STA */ + struct STA_RECORD *prStaRec; + /* The Bss for current focused STA */ + struct BSS_INFO *prBssInfo; + /* The current TX queue to dequeue */ + struct QUE *prCurrQueue; + /* The dequeued packet */ + struct MSDU_INFO *prDequeuedPkt; + + /* To remember the total forwarded packets for a STA */ + uint32_t u4CurStaForwardFrameCount; + /* The maximum number of packets a STA can forward */ + uint32_t u4MaxForwardFrameCountLimit; + uint32_t u4AvaliableResource; /* The TX resource amount */ + uint32_t u4MaxResourceLimit; + + u_int8_t fgEndThisRound; + struct QUE_MGT *prQM = &prAdapter->rQM; + + uint8_t *pucPsStaFreeQuota; +#if CFG_SUPPORT_SOFT_ACM + uint8_t ucAc; + u_int8_t fgAcmFlowCtrl = FALSE; + static const uint8_t aucTc2Ac[] = {ACI_BK, ACI_BE, ACI_VI, ACI_VO}; +#endif + + /* 4 <1> Assign init value */ + /* Post resource handling, give infinity resource*/ + if (prQM->fgTcResourcePostHandle) { + u4AvaliableResource = QM_STA_FORWARD_COUNT_UNLIMITED; + u4MaxResourceLimit = QM_STA_FORWARD_COUNT_UNLIMITED; + *prPleCurrentQuota = QM_STA_FORWARD_COUNT_UNLIMITED; + } else { + /* Sanity Check */ + if (!u4CurrentQuota) { + DBGLOG(TX, LOUD, + "(Fairness) Skip TC = %u u4CurrentQuota = %u\n", + ucTC, u4CurrentQuota); + prQM->au4DequeueNoTcResourceCounter[ucTC]++; + return u4CurrentQuota; + } + /* Check PLE resource */ + if (!(*prPleCurrentQuota)) + return u4CurrentQuota; + u4AvaliableResource = u4CurrentQuota; + u4MaxResourceLimit = u4TotalQuota; + } + +#if QM_FORWARDING_FAIRNESS + u4CurStaIndex = prQM->au4HeadStaRecIndex[ucTC]; + u4CurStaUsedResource = prQM->au4ResourceUsedCount[ucTC]; +#endif + + fgEndThisRound = FALSE; + ucLoop = 0; + u4CurStaForwardFrameCount = 0; + + DBGLOG(QM, TEMP, + "(Fairness) TC[%u] Init Head STA[%u] Resource[%u]\n", + ucTC, u4CurStaIndex, u4AvaliableResource); + + /* 4 <2> Traverse STA array from Head STA */ + /* From STA[x] to STA[x+1] to STA[x+2] to ... to STA[x] */ + while (ucLoop < CFG_STA_REC_NUM) { + prStaRec = &prAdapter->arStaRec[u4CurStaIndex]; + prCurrQueue = &prStaRec->arTxQueue[ucTC]; + + /* 4 <2.1> Find a Tx allowed STA */ + /* Only Data frame will be queued in */ + /* if (prStaRec->fgIsTxAllowed) { */ + if (QUEUE_IS_NOT_EMPTY(prCurrQueue)) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + /* prCurrQueue = &prStaRec->aprTxQueue[ucTC]; */ + prDequeuedPkt = NULL; + pucPsStaFreeQuota = NULL; + /* Set default forward count limit to unlimited */ + u4MaxForwardFrameCountLimit = + QM_STA_FORWARD_COUNT_UNLIMITED; + + /* 4 <2.2> Update forward frame/page count + * limit for this STA + */ + /* AP mode: STA in PS buffer handling */ + if (prStaRec->fgIsInPS) { + if (prStaRec->fgIsQoS && + prStaRec->fgIsUapsdSupported && + (prStaRec->ucBmpTriggerAC & + BIT(ucTC))) { + u4MaxForwardFrameCountLimit = + prStaRec-> + ucFreeQuotaForDelivery; + pucPsStaFreeQuota = + &prStaRec-> + ucFreeQuotaForDelivery; + } else { + u4MaxForwardFrameCountLimit = + prStaRec-> + ucFreeQuotaForNonDelivery; + pucPsStaFreeQuota = + &prStaRec-> + ucFreeQuotaForNonDelivery; + } + } + + /* fgIsInPS */ + /* Absent BSS handling */ + if (prBssInfo->fgIsNetAbsent) { + if (u4MaxForwardFrameCountLimit > + prBssInfo->ucBssFreeQuota) + u4MaxForwardFrameCountLimit = + prBssInfo->ucBssFreeQuota; + } +#if CFG_SUPPORT_DBDC + if (prAdapter->rWifiVar.fgDbDcModeEn) + u4MaxResourceLimit = + gmGetDequeueQuota(prAdapter, + prStaRec, prBssInfo, + u4TotalQuota); +#endif +#if CFG_SUPPORT_SOFT_ACM + if (ucTC <= TC3_INDEX && + prStaRec->afgAcmRequired[aucTc2Ac[ucTC]]) { + ucAc = aucTc2Ac[ucTC]; + DBGLOG(QM, TRACE, "AC %d Pending Pkts %u\n", + ucAc, prCurrQueue->u4NumElem); + /* Quick check remain medium time and pending + ** packets + */ + if (QUEUE_IS_EMPTY(prCurrQueue) || + !wmmAcmCanDequeue(prAdapter, ucAc, 0)) + goto skip_dequeue; + fgAcmFlowCtrl = TRUE; + } else + fgAcmFlowCtrl = FALSE; +#endif + /* 4 <2.3> Dequeue packet */ + /* Three cases to break: (1) No resource + * (2) No packets (3) Fairness + */ + while (!QUEUE_IS_EMPTY(prCurrQueue)) { + prDequeuedPkt = (struct MSDU_INFO *) + QUEUE_GET_HEAD(prCurrQueue); + + if ((u4CurStaForwardFrameCount >= + u4MaxForwardFrameCountLimit) || + (u4CurStaUsedResource >= + u4MaxResourceLimit)) { + /* Exceeds Limit */ + prQM-> + au4DequeueNoTcResourceCounter[ucTC]++; + break; + } else if (prDequeuedPkt->u4PageCount > + u4AvaliableResource) { + /* Available Resource is not enough */ + prQM-> + au4DequeueNoTcResourceCounter[ucTC]++; + if (!(prAdapter->rWifiVar. + ucAlwaysResetUsedRes & BIT(0))) + fgEndThisRound = TRUE; + break; + } else if ((*prPleCurrentQuota) < + NIX_TX_PLE_PAGE_CNT_PER_FRAME) { + if (!(prAdapter->rWifiVar. + ucAlwaysResetUsedRes & BIT(0))) + fgEndThisRound = TRUE; + break; + } else if (!prStaRec->fgIsValid) { + /* In roaming, if the sta_rec doesn't + * active by event 0x0C, it can't + * dequeue data. + */ + DBGLOG_LIMITED(QM, WARN, + "sta_rec is not valid\n"); + break; + } +#if CFG_SUPPORT_SOFT_ACM + if (fgAcmFlowCtrl) { + uint32_t u4PktTxTime = 0; + + u4PktTxTime = wmmCalculatePktUsedTime( + prBssInfo, prStaRec, + prDequeuedPkt->u2FrameLength - + ETH_HLEN); + if (!wmmAcmCanDequeue(prAdapter, ucAc, + u4PktTxTime)) + break; + } +#endif + /* Available to be Tx */ + + QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, + struct MSDU_INFO *); + + if (!QUEUE_IS_EMPTY(prCurrQueue)) { + /* XXX: check all queues for STA */ + prDequeuedPkt->ucPsForwardingType = + PS_FORWARDING_MORE_DATA_ENABLED; + } + /* to record WMM Set */ + prDequeuedPkt->ucWmmQueSet = + prBssInfo->ucWmmQueSet; + QUEUE_INSERT_TAIL(prQue, + (struct QUE_ENTRY *) + prDequeuedPkt); + prStaRec->u4DeqeueuCounter++; + prQM->u4DequeueCounter++; + + u4AvaliableResource -= + prDequeuedPkt->u4PageCount; + u4CurStaUsedResource += + prDequeuedPkt->u4PageCount; + u4CurStaForwardFrameCount++; + (*prPleCurrentQuota) -= + NIX_TX_PLE_PAGE_CNT_PER_FRAME; + } +#if CFG_SUPPORT_SOFT_ACM +skip_dequeue: +#endif + /* AP mode: Update STA in PS Free quota */ + if (prStaRec->fgIsInPS && pucPsStaFreeQuota) { + if ((*pucPsStaFreeQuota) >= + u4CurStaForwardFrameCount) + (*pucPsStaFreeQuota) -= + u4CurStaForwardFrameCount; + else + (*pucPsStaFreeQuota) = 0; + } + + if (prBssInfo->fgIsNetAbsent) { + if (prBssInfo->ucBssFreeQuota >= + u4CurStaForwardFrameCount) + prBssInfo->ucBssFreeQuota -= + u4CurStaForwardFrameCount; + else + prBssInfo->ucBssFreeQuota = 0; + } + } + + if (fgEndThisRound) { + /* End this round */ + break; + } + + /* Prepare for next STA */ + ucLoop++; + u4CurStaIndex++; + u4CurStaIndex %= CFG_STA_REC_NUM; + u4CurStaUsedResource = 0; + u4CurStaForwardFrameCount = 0; + } + + /* 4 <3> Store Head Sta information to QM */ + /* No need to count used resource if thers is only one STA */ + if ((prQM->u4TxAllowedStaCount == 1) || + (prAdapter->rWifiVar.ucAlwaysResetUsedRes & BIT(1))) + u4CurStaUsedResource = 0; + +#if QM_FORWARDING_FAIRNESS + prQM->au4HeadStaRecIndex[ucTC] = u4CurStaIndex; + prQM->au4ResourceUsedCount[ucTC] = u4CurStaUsedResource; +#endif + + DBGLOG(QM, TEMP, + "(Fairness) TC[%u] Scheduled Head STA[%u] Left Resource[%u]\n", + ucTC, u4CurStaIndex, u4AvaliableResource); + + return u4AvaliableResource; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 BMC_TC_INDEX) + * \param[in] ucMaxNum The maximum amount of available resource + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void +qmDequeueTxPacketsFromPerTypeQueues(IN struct ADAPTER *prAdapter, + OUT struct QUE *prQue, IN uint8_t ucTC, + IN uint32_t u4CurrentQuota, + IN uint32_t *prPleCurrentQuota, + IN uint32_t u4TotalQuota) +{ + uint32_t u4AvaliableResource, u4LeftResource; + uint32_t u4MaxResourceLimit; + uint32_t u4TotalUsedResource = 0; + struct QUE_MGT *prQM; + PFN_DEQUEUE_FUNCTION pfnDeQFunc[2]; + u_int8_t fgChangeDeQFunc = TRUE; + u_int8_t fgGlobalQueFirst = TRUE; + + DBGLOG(QM, TEMP, "Enter %s (TC = %d, quota = %u)\n", + __func__, ucTC, u4CurrentQuota); + + prQM = &prAdapter->rQM; + + /* Post resource handling, give infinity resource*/ + if (prQM->fgTcResourcePostHandle) { + u4AvaliableResource = QM_STA_FORWARD_COUNT_UNLIMITED; + u4MaxResourceLimit = QM_STA_FORWARD_COUNT_UNLIMITED; + *prPleCurrentQuota = QM_STA_FORWARD_COUNT_UNLIMITED; + } else { + /* Broadcast/Multicast data packets */ + if (u4CurrentQuota == 0) + return; + /* Check PLE resource */ + if (!(*prPleCurrentQuota)) + return; + u4AvaliableResource = u4CurrentQuota; + u4MaxResourceLimit = u4TotalQuota; + } + +#if QM_FORWARDING_FAIRNESS + u4TotalUsedResource = prQM->u4GlobalResourceUsedCount; + fgGlobalQueFirst = prQM->fgGlobalQFirst; +#endif + + /* Dequeue function selection */ + if (fgGlobalQueFirst) { + pfnDeQFunc[0] = qmDequeueTxPacketsFromGlobalQueue; + pfnDeQFunc[1] = qmDequeueTxPacketsFromPerStaQueues; + } else { + pfnDeQFunc[0] = qmDequeueTxPacketsFromPerStaQueues; + pfnDeQFunc[1] = qmDequeueTxPacketsFromGlobalQueue; + } + + /* 1st dequeue function */ + u4LeftResource = pfnDeQFunc[0](prAdapter, prQue, ucTC, + u4AvaliableResource, + prPleCurrentQuota, + (u4MaxResourceLimit - u4TotalUsedResource)); + + /* dequeue function comsumes no resource, change */ + if ((u4LeftResource >= u4AvaliableResource) && + (u4AvaliableResource >= + prAdapter->rTxCtrl.u4MaxPageCntPerFrame)) { + fgChangeDeQFunc = TRUE; + } else { + u4TotalUsedResource += + (u4AvaliableResource - u4LeftResource); + /* Used resource exceeds limit, change */ + if (u4TotalUsedResource >= u4MaxResourceLimit) + fgChangeDeQFunc = TRUE; + } + + if (fgChangeDeQFunc) { + fgGlobalQueFirst = !fgGlobalQueFirst; + u4TotalUsedResource = 0; + } + + /* 2nd dequeue function */ + u4LeftResource = pfnDeQFunc[1](prAdapter, prQue, ucTC, + u4LeftResource, prPleCurrentQuota, u4MaxResourceLimit); + +#if QM_FORWARDING_FAIRNESS + prQM->fgGlobalQFirst = fgGlobalQueFirst; + prQM->u4GlobalResourceUsedCount = u4TotalUsedResource; +#endif + +} /* qmDequeueTxPacketsFromPerTypeQueues */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Dequeue TX packets from a QM global Queue for a particular TC + * + * \param[out] prQue The queue to put the dequeued packets + * \param[in] ucTC The TC index(Shall always be BMC_TC_INDEX) + * \param[in] ucMaxNum The maximum amount of available resource + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +uint32_t +qmDequeueTxPacketsFromGlobalQueue(IN struct ADAPTER *prAdapter, + OUT struct QUE *prQue, + IN uint8_t ucTC, IN uint32_t u4CurrentQuota, + IN uint32_t *prPleCurrentQuota, + IN uint32_t u4TotalQuota) +{ + struct BSS_INFO *prBssInfo; + struct QUE *prCurrQueue; + uint32_t u4AvaliableResource; + struct MSDU_INFO *prDequeuedPkt; + struct MSDU_INFO *prBurstEndPkt; + struct QUE rMergeQue; + struct QUE *prMergeQue; + struct QUE_MGT *prQM; + + DBGLOG(QM, TEMP, "Enter %s (TC = %d, quota = %u)\n", + __func__, ucTC, u4CurrentQuota); + + /* Broadcast/Multicast data packets */ + if (u4CurrentQuota == 0) + return u4CurrentQuota; + /* Check PLE resource */ + if (!(*prPleCurrentQuota)) + return u4CurrentQuota; + + prQM = &prAdapter->rQM; + + /* 4 <1> Determine the queue */ + prCurrQueue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST]; + u4AvaliableResource = u4CurrentQuota; + prDequeuedPkt = NULL; + prBurstEndPkt = NULL; + + /* Post resource handling, give infinity resource*/ + if (prQM->fgTcResourcePostHandle) { + u4AvaliableResource = QM_STA_FORWARD_COUNT_UNLIMITED; + *prPleCurrentQuota = QM_STA_FORWARD_COUNT_UNLIMITED; + } + + QUEUE_INITIALIZE(&rMergeQue); + prMergeQue = &rMergeQue; + + /* 4 <2> Dequeue packets */ + while (!QUEUE_IS_EMPTY(prCurrQueue)) { + prDequeuedPkt = (struct MSDU_INFO *) QUEUE_GET_HEAD( + prCurrQueue); + if (prDequeuedPkt->u4PageCount > u4AvaliableResource) + break; + if ((*prPleCurrentQuota) < NIX_TX_PLE_PAGE_CNT_PER_FRAME) + break; + + QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, + struct MSDU_INFO *); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prDequeuedPkt->ucBssIndex); + + if (IS_BSS_ACTIVE(prBssInfo)) { + if (!prBssInfo->fgIsNetAbsent) { + /* to record WMM Set */ + prDequeuedPkt->ucWmmQueSet = + prBssInfo->ucWmmQueSet; + QUEUE_INSERT_TAIL(prQue, + (struct QUE_ENTRY *) + prDequeuedPkt); + prBurstEndPkt = prDequeuedPkt; + prQM->u4DequeueCounter++; + u4AvaliableResource -= + prDequeuedPkt->u4PageCount; + (*prPleCurrentQuota) -= + NIX_TX_PLE_PAGE_CNT_PER_FRAME; + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_26); + } else { + QUEUE_INSERT_TAIL(prMergeQue, + (struct QUE_ENTRY *) + 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((struct MSDU_INFO *) + QUEUE_GET_TAIL(prCurrQueue), NULL); + } + + return u4AvaliableResource; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +struct MSDU_INFO *qmDequeueTxPackets(IN struct ADAPTER *prAdapter, + IN struct TX_TCQ_STATUS *prTcqStatus) +{ + int32_t i; + struct MSDU_INFO *prReturnedPacketListHead; + struct QUE rReturnedQue; + uint32_t u4MaxQuotaLimit; + uint32_t u4AvailableResourcePLE; + + DBGLOG(QM, TEMP, "Enter qmDequeueTxPackets\n"); + + QUEUE_INITIALIZE(&rReturnedQue); + + prReturnedPacketListHead = NULL; + + /* TC0 to TC3: AC0~AC3 (commands packets are not handled by QM) */ + for (i = TC3_INDEX; i >= TC0_INDEX; i--) { + DBGLOG(QM, TEMP, "Dequeue packets from Per-STA queue[%u]\n", i); + + /* If only one STA is Tx allowed, + * no need to restrict Max quota + */ + if (prAdapter->rWifiVar.u4MaxTxDeQLimit) + u4MaxQuotaLimit = prAdapter->rWifiVar.u4MaxTxDeQLimit; + else if (prAdapter->rQM.u4TxAllowedStaCount == 1) + u4MaxQuotaLimit = QM_STA_FORWARD_COUNT_UNLIMITED; + else + u4MaxQuotaLimit = + (uint32_t) prTcqStatus->au4MaxNumOfPage[i]; + + u4AvailableResourcePLE = nicTxResourceGetPleFreeCount( + prAdapter, i); + + if (i == BMC_TC_INDEX) + qmDequeueTxPacketsFromPerTypeQueues(prAdapter, + &rReturnedQue, (uint8_t)i, + prTcqStatus->au4FreePageCount[i], + &u4AvailableResourcePLE, + u4MaxQuotaLimit); + else + qmDequeueTxPacketsFromPerStaQueues(prAdapter, + &rReturnedQue, + (uint8_t)i, + prTcqStatus->au4FreePageCount[i], + &u4AvailableResourcePLE, + u4MaxQuotaLimit); + + /* The aggregate number of dequeued packets */ + DBGLOG(QM, TEMP, "DQA)[%u](%u)\n", i, + rReturnedQue.u4NumElem); + } + + if (QUEUE_IS_NOT_EMPTY(&rReturnedQue)) { + prReturnedPacketListHead = (struct MSDU_INFO *) + QUEUE_GET_HEAD(&rReturnedQue); + QM_TX_SET_NEXT_MSDU_INFO((struct MSDU_INFO *) + QUEUE_GET_TAIL(&rReturnedQue), NULL); + } + + return prReturnedPacketListHead; +} + +#if CFG_SUPPORT_MULTITHREAD +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +struct MSDU_INFO *qmDequeueTxPacketsMthread( + IN struct ADAPTER *prAdapter, + IN struct TX_TCQ_STATUS *prTcqStatus) +{ + + /* INT_32 i; */ + struct MSDU_INFO *prReturnedPacketListHead; + /* QUE_T rReturnedQue; */ + /* UINT_32 u4MaxQuotaLimit; */ + struct MSDU_INFO *prMsduInfo, *prNextMsduInfo; + KAL_SPIN_LOCK_DECLARATION(); + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + if (prAdapter->rQM.fgForceReassign) + qmDoAdaptiveTcResourceCtrl(prAdapter); +#endif + + if (!prAdapter->rQM.fgTcResourcePostHandle) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + prReturnedPacketListHead = qmDequeueTxPackets(prAdapter, + prTcqStatus); + + /* require the resource first to prevent from unsync */ + prMsduInfo = prReturnedPacketListHead; + while (prMsduInfo) { + prNextMsduInfo = (struct MSDU_INFO *) + QUEUE_GET_NEXT_ENTRY + ((struct QUE_ENTRY *) prMsduInfo); + nicTxAcquireResource(prAdapter, prMsduInfo->ucTC, + nicTxGetPageCount(prAdapter, + prMsduInfo->u2FrameLength, FALSE), FALSE); + + prMsduInfo = prNextMsduInfo; + } + } else { + prReturnedPacketListHead = qmDequeueTxPackets(prAdapter, + prTcqStatus); + } + if (prReturnedPacketListHead) + wlanTxProfilingTagMsdu(prAdapter, prReturnedPacketListHead, + TX_PROF_TAG_DRV_DEQUE); + + if (!prAdapter->rQM.fgTcResourcePostHandle) + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + 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) + */ +/*----------------------------------------------------------------------------*/ +u_int8_t +qmAdjustTcQuotasMthread(IN struct ADAPTER *prAdapter, + OUT struct TX_TCQ_ADJUST *prTcqAdjust, + IN struct TX_TCQ_STATUS *prTcqStatus) +{ +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + uint32_t i; + struct QUE_MGT *prQM = &prAdapter->rQM; + + KAL_SPIN_LOCK_DECLARATION(); + + /* Must initialize */ + for (i = 0; i < QM_ACTIVE_TC_NUM; i++) + prTcqAdjust->ai4Variation[i] = 0; + + /* 4 <1> If TC resource is not just adjusted, exit directly */ + if (!prQM->fgTcResourcePostAnnealing) + return FALSE; + + /* 4 <2> Adjust TcqStatus according to + * the updated prQM->au4CurrentTcResource + */ + else { + int32_t i4TotalExtraQuota = 0; + int32_t ai4ExtraQuota[QM_ACTIVE_TC_NUM]; + u_int8_t fgResourceRedistributed = TRUE; + + /* Must initialize */ + for (i = 0; i < TC_NUM; i++) + prTcqAdjust->ai4Variation[i] = 0; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + /* Obtain the free-to-distribute resource */ + for (i = 0; i < QM_ACTIVE_TC_NUM; i++) { + ai4ExtraQuota[i] = + (int32_t) prTcqStatus->au4MaxNumOfBuffer[i] - + (int32_t) prQM->au4CurrentTcResource[i]; + + if (ai4ExtraQuota[i] > 0) { + /* The resource shall be reallocated + * to other TCs + */ + if (ai4ExtraQuota[i] > + prTcqStatus->au4FreeBufferCount[ + i]) { + ai4ExtraQuota[i] = + prTcqStatus-> + au4FreeBufferCount[i]; + fgResourceRedistributed = FALSE; + } + + i4TotalExtraQuota += ai4ExtraQuota[i]; + prTcqAdjust->ai4Variation[i] = + (-ai4ExtraQuota[i]); + } + } + + /* Distribute quotas to TCs which need extra resource + * according to prQM->au4CurrentTcResource + */ + for (i = 0; i < QM_ACTIVE_TC_NUM; i++) { + if (ai4ExtraQuota[i] < 0) { + if ((-ai4ExtraQuota[i]) > i4TotalExtraQuota) { + ai4ExtraQuota[i] = (-i4TotalExtraQuota); + fgResourceRedistributed = FALSE; + } + + i4TotalExtraQuota += ai4ExtraQuota[i]; + prTcqAdjust->ai4Variation[i] = + (-ai4ExtraQuota[i]); + } + } + + /* In case some TC is waiting for TX Done, + * continue to adjust TC quotas upon TX Done + */ + prQM->fgTcResourcePostAnnealing = (!fgResourceRedistributed); + + for (i = 0; i < TC_NUM; i++) { + prTcqStatus->au4FreePageCount[i] += + (prTcqAdjust->ai4Variation[i] * + prAdapter->rTxCtrl.u4MaxPageCntPerFrame); + prTcqStatus->au4MaxNumOfPage[i] += + (prTcqAdjust->ai4Variation[i] * + prAdapter->rTxCtrl.u4MaxPageCntPerFrame); + + prTcqStatus->au4FreeBufferCount[i] += + prTcqAdjust->ai4Variation[i]; + prTcqStatus->au4MaxNumOfBuffer[i] += + prTcqAdjust->ai4Variation[i]; + } + + + /* PLE */ + qmAdjustTcQuotaPle(prAdapter, prTcqAdjust, prTcqStatus); + + +#if QM_FAST_TC_RESOURCE_CTRL + prQM->fgTcResourceFastReaction = FALSE; +#endif + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + } + + return TRUE; +#else + return FALSE; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Adjust the TC PLE 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 qmAdjustTcQuotaPle(IN struct ADAPTER *prAdapter, + OUT struct TX_TCQ_ADJUST *prTcqAdjust, + IN struct TX_TCQ_STATUS *prTcqStatus) +{ + uint8_t i; + int32_t i4pages; + struct TX_CTRL *prTxCtrl; + struct TX_TCQ_STATUS *prTc; + int32_t i4TotalExtraQuota = 0; + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + prTc = &prTxCtrl->rTc; + + /* no PLE resource control */ + if (!prTc->fgNeedPleCtrl) + return; + + /* collect free PLE resource */ + for (i = TC0_INDEX; i < TC_NUM; i++) { + + if (!nicTxResourceIsPleCtrlNeeded(prAdapter, i)) + continue; + + /* adjust ple resource */ + i4pages = prTcqAdjust->ai4Variation[i] * + NIX_TX_PLE_PAGE_CNT_PER_FRAME; + + if (i4pages < 0) { + /* donate resource to other TC */ + if (prTcqStatus->au4FreePageCount_PLE[i] < (-i4pages)) { + /* not enough to give */ + i4pages = + -(prTcqStatus->au4FreePageCount_PLE[i]); + } + i4TotalExtraQuota += -i4pages; + + prTcqStatus->au4FreePageCount_PLE[i] += i4pages; + prTcqStatus->au4MaxNumOfPage_PLE[i] += i4pages; + + prTcqStatus->au4FreeBufferCount_PLE[i] += + (i4pages / NIX_TX_PLE_PAGE_CNT_PER_FRAME); + prTcqStatus->au4MaxNumOfBuffer_PLE[i] += + (i4pages / NIX_TX_PLE_PAGE_CNT_PER_FRAME); + } + } + + /* distribute PLE resource */ + for (i = TC0_INDEX; i < TC_NUM; i++) { + if (!nicTxResourceIsPleCtrlNeeded(prAdapter, i)) + continue; + + /* adjust ple resource */ + i4pages = prTcqAdjust->ai4Variation[i] * + NIX_TX_PLE_PAGE_CNT_PER_FRAME; + + if (i4pages > 0) { + if (i4TotalExtraQuota >= i4pages) { + i4TotalExtraQuota -= i4pages; + } else { + i4pages = i4TotalExtraQuota; + i4TotalExtraQuota = 0; + } + prTcqStatus->au4FreePageCount_PLE[i] += i4pages; + prTcqStatus->au4MaxNumOfPage_PLE[i] += i4pages; + + prTcqStatus->au4FreeBufferCount_PLE[i] = + (prTcqStatus->au4FreePageCount_PLE[i] / + NIX_TX_PLE_PAGE_CNT_PER_FRAME); + prTcqStatus->au4MaxNumOfBuffer_PLE[i] = + (prTcqStatus->au4MaxNumOfBuffer_PLE[i] / + NIX_TX_PLE_PAGE_CNT_PER_FRAME); + } + } + + /* distribute remaining PLE resource */ + while (i4TotalExtraQuota != 0) { + DBGLOG(QM, INFO, + "distribute remaining PLE resource[%u]\n", + i4TotalExtraQuota); + for (i = TC0_INDEX; i < TC_NUM; i++) { + if (!nicTxResourceIsPleCtrlNeeded(prAdapter, i)) + continue; + + if (i4TotalExtraQuota >= + NIX_TX_PLE_PAGE_CNT_PER_FRAME) { + prTcqStatus->au4FreePageCount_PLE[i] += + NIX_TX_PLE_PAGE_CNT_PER_FRAME; + prTcqStatus->au4MaxNumOfPage_PLE[i] += + NIX_TX_PLE_PAGE_CNT_PER_FRAME; + + prTcqStatus->au4FreeBufferCount_PLE[i] += 1; + prTcqStatus->au4MaxNumOfBuffer_PLE[i] += 1; + + i4TotalExtraQuota -= + NIX_TX_PLE_PAGE_CNT_PER_FRAME; + } else { + /* remaining PLE pages are + * not enough for a package + */ + prTcqStatus->au4FreePageCount_PLE[i] += + i4TotalExtraQuota; + prTcqStatus->au4MaxNumOfPage_PLE[i] += + i4TotalExtraQuota; + + prTcqStatus->au4FreeBufferCount_PLE[i] = + (prTcqStatus->au4FreePageCount_PLE[i] / + NIX_TX_PLE_PAGE_CNT_PER_FRAME); + prTcqStatus->au4MaxNumOfBuffer_PLE[i] = + (prTcqStatus->au4MaxNumOfPage_PLE[i] / + NIX_TX_PLE_PAGE_CNT_PER_FRAME); + + i4TotalExtraQuota = 0; + } + } + } + +} + +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \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) + */ +/*----------------------------------------------------------------------------*/ +u_int8_t qmAdjustTcQuotas(IN struct ADAPTER *prAdapter, + OUT struct TX_TCQ_ADJUST *prTcqAdjust, + IN struct TX_TCQ_STATUS *prTcqStatus) +{ +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + uint32_t i; + struct QUE_MGT *prQM = &prAdapter->rQM; + + /* Must initialize */ + for (i = 0; i < QM_ACTIVE_TC_NUM; i++) + prTcqAdjust->ai4Variation[i] = 0; + + /* 4 <1> If TC resource is not just adjusted, exit directly */ + if (!prQM->fgTcResourcePostAnnealing) + return FALSE; + /* 4 <2> Adjust TcqStatus according to + * the updated prQM->au4CurrentTcResource + */ + else { + int32_t i4TotalExtraQuota = 0; + int32_t ai4ExtraQuota[QM_ACTIVE_TC_NUM]; + u_int8_t fgResourceRedistributed = TRUE; + + /* Obtain the free-to-distribute resource */ + for (i = 0; i < QM_ACTIVE_TC_NUM; i++) { + ai4ExtraQuota[i] = + (int32_t) prTcqStatus->au4MaxNumOfBuffer[i] - + (int32_t) prQM->au4CurrentTcResource[i]; + + if (ai4ExtraQuota[i] > 0) { + /* The resource shall be + * reallocated to other TCs + */ + if (ai4ExtraQuota[i] > + prTcqStatus->au4FreeBufferCount[i]) { + ai4ExtraQuota[i] = + prTcqStatus-> + au4FreeBufferCount[i]; + fgResourceRedistributed = FALSE; + } + + i4TotalExtraQuota += ai4ExtraQuota[i]; + prTcqAdjust->ai4Variation[i] = + (-ai4ExtraQuota[i]); + } + } + + /* Distribute quotas to TCs which need extra resource + * according to prQM->au4CurrentTcResource + */ + for (i = 0; i < QM_ACTIVE_TC_NUM; i++) { + if (ai4ExtraQuota[i] < 0) { + if ((-ai4ExtraQuota[i]) > i4TotalExtraQuota) { + ai4ExtraQuota[i] = (-i4TotalExtraQuota); + fgResourceRedistributed = FALSE; + } + + i4TotalExtraQuota += ai4ExtraQuota[i]; + prTcqAdjust->ai4Variation[i] = + (-ai4ExtraQuota[i]); + } + } + + /* In case some TC is waiting for TX Done, + * continue to adjust TC quotas upon TX Done + */ + prQM->fgTcResourcePostAnnealing = (!fgResourceRedistributed); + +#if QM_FAST_TC_RESOURCE_CTRL + prQM->fgTcResourceFastReaction = FALSE; +#endif + +#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->au4FreeBufferCount[0], + prTcqStatus->au4FreeBufferCount[1], + prTcqStatus->au4FreeBufferCount[2], + prTcqStatus->au4FreeBufferCount[3], + prTcqStatus->au4FreeBufferCount[4], + prTcqStatus->au4FreeBufferCount[5]); +#endif + } + + return TRUE; +#else + return FALSE; +#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 struct ADAPTER *prAdapter) +{ + int32_t u4CurrQueLen, u4Tc, u4StaRecIdx; + struct STA_RECORD *prStaRec; + struct QUE_MGT *prQM = &prAdapter->rQM; + struct BSS_INFO *prBssInfo; + + /* 4 <1> Update the queue lengths for TC0 to TC3 (skip TC4) and TC5 */ + for (u4Tc = 0; u4Tc < QM_ACTIVE_TC_NUM; u4Tc++) { + u4CurrQueLen = 0; + + /* Calculate per-STA queue length */ + if (u4Tc < NUM_OF_PER_STA_TX_QUEUES) { + for (u4StaRecIdx = 0; u4StaRecIdx < CFG_STA_REC_NUM; + u4StaRecIdx++) { + prStaRec = cnmGetStaRecByIndex(prAdapter, + u4StaRecIdx); + if (prStaRec) { + prBssInfo = GET_BSS_INFO_BY_INDEX( + prAdapter, + prStaRec->ucBssIndex); + + /* If the STA is activated, + * get the queue length + */ + if ((prStaRec->fgIsValid) && + (!prBssInfo->fgIsNetAbsent)) + u4CurrQueLen += + (prStaRec-> + arTxQueue[u4Tc]. + u4NumElem); + } + } + } + + if (u4Tc == BMC_TC_INDEX) { + /* Update the queue length for (BMCAST) */ + u4CurrQueLen += prQM->arTxQueue[ + TX_QUEUE_INDEX_BMCAST].u4NumElem; + } + + if (prQM->au4AverageQueLen[u4Tc] == 0) { + prQM->au4AverageQueLen[u4Tc] = (u4CurrQueLen << + prQM->u4QueLenMovingAverage); + } else { + prQM->au4AverageQueLen[u4Tc] -= + (prQM->au4AverageQueLen[u4Tc] >> + prQM->u4QueLenMovingAverage); + prQM->au4AverageQueLen[u4Tc] += (u4CurrQueLen); + } + } +#if 0 + /* Update the queue length for TC5 (BMCAST) */ + u4CurrQueLen = + prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST].u4NumElem; + + if (prQM->au4AverageQueLen[TC5_INDEX] == 0) { + prQM->au4AverageQueLen[TC5_INDEX] = (u4CurrQueLen << + QM_QUE_LEN_MOVING_AVE_FACTOR); + } else { + prQM->au4AverageQueLen[TC5_INDEX] -= + (prQM->au4AverageQueLen[TC5_INDEX] >> + QM_QUE_LEN_MOVING_AVE_FACTOR); + prQM->au4AverageQueLen[TC5_INDEX] += (u4CurrQueLen); + } +#endif +} + +void qmAllocateResidualTcResource(IN struct ADAPTER *prAdapter, + IN int32_t *ai4TcResDemand, + IN uint32_t *pu4ResidualResource, + IN uint32_t *pu4ShareCount) +{ + struct QUE_MGT *prQM = &prAdapter->rQM; + uint32_t u4Share = 0; + uint32_t u4TcIdx; + uint8_t ucIdx; + uint32_t au4AdjTc[] = { TC3_INDEX, TC2_INDEX, TC1_INDEX, TC0_INDEX }; + uint32_t u4AdjTcSize = (sizeof(au4AdjTc) / sizeof(uint32_t)); + uint32_t u4ResidualResource = *pu4ResidualResource; + uint32_t u4ShareCount = *pu4ShareCount; + + /* If there is no resource left, exit directly */ + if (u4ResidualResource == 0) + return; + + /* This shall not happen */ + if (u4ShareCount == 0) { + prQM->au4CurrentTcResource[TC1_INDEX] += u4ResidualResource; + DBGLOG(QM, ERROR, "QM: (Error) u4ShareCount = 0\n"); + return; + } + + /* Share the residual resource evenly */ + u4Share = (u4ResidualResource / u4ShareCount); + if (u4Share) { + for (u4TcIdx = 0; u4TcIdx < QM_ACTIVE_TC_NUM; u4TcIdx++) { + /* Skip TC4 (not adjustable) */ + if (u4TcIdx == TC4_INDEX) + continue; + + if (ai4TcResDemand[u4TcIdx] > 0) { + if (ai4TcResDemand[u4TcIdx] > u4Share) { + prQM->au4CurrentTcResource[u4TcIdx] += + u4Share; + u4ResidualResource -= u4Share; + ai4TcResDemand[u4TcIdx] -= u4Share; + } else { + prQM->au4CurrentTcResource[u4TcIdx] += + ai4TcResDemand[u4TcIdx]; + u4ResidualResource -= + ai4TcResDemand[u4TcIdx]; + ai4TcResDemand[u4TcIdx] = 0; + } + } + } + } + + /* By priority, allocate the left resource + * that is not divisible by u4Share + */ + ucIdx = 0; + while (u4ResidualResource) { + u4TcIdx = au4AdjTc[ucIdx]; + + if (ai4TcResDemand[u4TcIdx]) { + prQM->au4CurrentTcResource[u4TcIdx]++; + u4ResidualResource--; + ai4TcResDemand[u4TcIdx]--; + + if (ai4TcResDemand[u4TcIdx] == 0) + u4ShareCount--; + } + + if (u4ShareCount <= 0) + break; + + ucIdx++; + ucIdx %= u4AdjTcSize; + } + + /* Allocate the left resource */ + prQM->au4CurrentTcResource[TC3_INDEX] += u4ResidualResource; + + *pu4ResidualResource = u4ResidualResource; + *pu4ShareCount = u4ShareCount; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Assign TX resource for each TC according to TX queue length and + * current assignment + * + * \param (none) + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void qmReassignTcResource(IN struct ADAPTER *prAdapter) +{ + int32_t i4TotalResourceDemand = 0; + uint32_t u4ResidualResource = 0; + uint32_t u4TcIdx; + int32_t ai4TcResDemand[QM_ACTIVE_TC_NUM]; + uint32_t u4ShareCount = 0; + uint32_t u4Share = 0; + struct QUE_MGT *prQM = &prAdapter->rQM; + uint32_t u4ActiveTcCount = 0; + uint32_t u4LastActiveTcIdx = TC3_INDEX; + + /* 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 (u4TcIdx = 0; u4TcIdx < QM_ACTIVE_TC_NUM; u4TcIdx++) { + /* Skip TC4, which is not adjustable */ + if (u4TcIdx == TC4_INDEX) + continue; + + /* Define: extra_demand = que_length + + * min_reserved_quota - current_quota + */ + ai4TcResDemand[u4TcIdx] = ((int32_t)(QM_GET_TX_QUEUE_LEN( + prAdapter, u4TcIdx) + + prQM->au4MinReservedTcResource[u4TcIdx]) - + (int32_t)prQM->au4CurrentTcResource[u4TcIdx]); + + /* If there are queued packets, allocate extra resource + * for the TC (for TCP consideration) + */ + if (QM_GET_TX_QUEUE_LEN(prAdapter, u4TcIdx)) { + ai4TcResDemand[u4TcIdx] += + prQM->u4ExtraReservedTcResource; + u4ActiveTcCount++; + } + + i4TotalResourceDemand += ai4TcResDemand[u4TcIdx]; + } + + /* 4 <2> Case 1: Demand <= Total Resource */ + if (i4TotalResourceDemand <= 0) { + + /* 4 <2.1> Calculate the residual resource evenly */ + /* excluding TC4 */ + if (u4ActiveTcCount == 0) + u4ShareCount = (QM_ACTIVE_TC_NUM - 1); + else + u4ShareCount = u4ActiveTcCount; + + u4ResidualResource = (uint32_t) (-i4TotalResourceDemand); + u4Share = (u4ResidualResource / u4ShareCount); + + /* 4 <2.2> Satisfy every TC and share + * the residual resource evenly + */ + for (u4TcIdx = 0; u4TcIdx < QM_ACTIVE_TC_NUM; u4TcIdx++) { + /* Skip TC4 (not adjustable) */ + if (u4TcIdx == TC4_INDEX) + continue; + + prQM->au4CurrentTcResource[u4TcIdx] += + ai4TcResDemand[u4TcIdx]; + + /* Every TC is fully satisfied */ + ai4TcResDemand[u4TcIdx] = 0; + + /* The left resource will be allocated */ + if (QM_GET_TX_QUEUE_LEN(prAdapter, u4TcIdx) || + (u4ActiveTcCount == 0)) { + prQM->au4CurrentTcResource[u4TcIdx] += u4Share; + u4ResidualResource -= u4Share; + u4LastActiveTcIdx = u4TcIdx; + } + } + + /* 4 <2.3> Allocate the left resource to last active TC */ + prQM->au4CurrentTcResource[u4LastActiveTcIdx] += + (u4ResidualResource); + + } + /* 4 <3> Case 2: Demand > Total Resource --> Guarantee + * a minimum amount of resource for each TC + */ + else { + u4ShareCount = 0; + u4ResidualResource = prQM->u4ResidualTcResource; + + /* 4 <3.1> Allocated resouce amount = minimum + * of (guaranteed, total demand) + */ + for (u4TcIdx = 0; u4TcIdx < QM_ACTIVE_TC_NUM; u4TcIdx++) { + /* Skip TC4 (not adjustable) */ + if (u4TcIdx == TC4_INDEX) + continue; + + /* The demand can be fulfilled with + * the guaranteed resource amount + */ + if ((prQM->au4CurrentTcResource[u4TcIdx] + + ai4TcResDemand[u4TcIdx]) <= + prQM->au4GuaranteedTcResource[u4TcIdx]) { + + prQM->au4CurrentTcResource[u4TcIdx] += + ai4TcResDemand[u4TcIdx]; + u4ResidualResource += + (prQM->au4GuaranteedTcResource[u4TcIdx] + - prQM->au4CurrentTcResource[u4TcIdx]); + ai4TcResDemand[u4TcIdx] = 0; + } + + /* The demand can not be fulfilled with + * the guaranteed resource amount + */ + else { + ai4TcResDemand[u4TcIdx] -= + (prQM->au4GuaranteedTcResource[u4TcIdx] + - prQM->au4CurrentTcResource[u4TcIdx]); + + prQM->au4CurrentTcResource[u4TcIdx] = + prQM->au4GuaranteedTcResource[u4TcIdx]; + u4ShareCount++; + } + } + + /* 4 <3.2> Allocate the residual resource */ + qmAllocateResidualTcResource(prAdapter, ai4TcResDemand, + &u4ResidualResource, &u4ShareCount); + } + + prQM->fgTcResourcePostAnnealing = TRUE; + +#if QM_PRINT_TC_RESOURCE_CTRL + /* Debug print */ + DBGLOG(QM, INFO, + "QM: TC Rsc adjust to [%03u:%03u:%03u:%03u:%03u:%03u]\n", + prQM->au4CurrentTcResource[0], + prQM->au4CurrentTcResource[1], + prQM->au4CurrentTcResource[2], + prQM->au4CurrentTcResource[3], + prQM->au4CurrentTcResource[4], + prQM->au4CurrentTcResource[5]); +#endif + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Adjust TX resource for each TC according to TX queue length and + * current assignment + * + * \param (none) + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void qmDoAdaptiveTcResourceCtrl(IN struct ADAPTER *prAdapter) +{ + struct QUE_MGT *prQM = &prAdapter->rQM; + + if (prQM->fgForceReassign) { + prQM->u4TimeToUpdateQueLen = 1; + prQM->u4TimeToAdjustTcResource = 1; + prQM->fgTcResourceFastReaction = TRUE; + + prQM->fgForceReassign = FALSE; + } + + /* 4 <0> Check to update queue length or not */ + if (--prQM->u4TimeToUpdateQueLen) + return; + /* 4 <1> Update TC queue length */ + prQM->u4TimeToUpdateQueLen = QM_INIT_TIME_TO_UPDATE_QUE_LEN; + qmUpdateAverageTxQueLen(prAdapter); + + /* 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); +#if QM_FAST_TC_RESOURCE_CTRL + if (prQM->fgTcResourceFastReaction) { + prQM->fgTcResourceFastReaction = FALSE; + nicTxAdjustTcq(prAdapter); + } +#endif + } + } + + /* Debug */ +#if QM_PRINT_TC_RESOURCE_CTRL + do { + uint32_t u4Tc; + + for (u4Tc = 0; u4Tc < QM_ACTIVE_TC_NUM; u4Tc++) { + if (QM_GET_TX_QUEUE_LEN(prAdapter, u4Tc) >= 100) { + log_dbg(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; + } + } + } while (FALSE); +#endif +} + +#if QM_FAST_TC_RESOURCE_CTRL +void qmCheckForFastTcResourceCtrl(IN struct ADAPTER *prAdapter, + IN uint8_t ucTc) +{ + struct QUE_MGT *prQM = &prAdapter->rQM; + u_int8_t fgTrigger = FALSE; + + if (!prAdapter->rTxCtrl.rTc.au4FreeBufferCount[ucTc] + || ((prAdapter->rTxCtrl.rTc.fgNeedPleCtrl) && + (!prAdapter->rTxCtrl.rTc.au4FreeBufferCount_PLE[ucTc]))) { + if (!prQM->au4CurrentTcResource[ucTc] || + nicTxGetAdjustableResourceCnt(prAdapter)) + fgTrigger = TRUE; + } + + /* Trigger TC resource adjustment + * if there is a requirement coming for a empty TC + */ + if (fgTrigger) { + prQM->fgForceReassign = TRUE; + + DBGLOG(QM, LOUD, + "Trigger TC Resource adjustment for TC[%u]\n", ucTc); + } +} +#endif + +#endif + +uint32_t gmGetDequeueQuota( + IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct BSS_INFO *prBssInfo, + IN uint32_t u4TotalQuota +) +{ + uint32_t u4Weight = 100; + uint32_t u4Quota; + + struct QUE_MGT *prQM = &prAdapter->rQM; + + if ((prAdapter->rWifiVar.uDeQuePercentEnable == FALSE) || + (prQM->fgIsTxResrouceControlEn == FALSE)) + return u4TotalQuota; + + if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_VHT) { + if (prBssInfo->ucVhtChannelWidth > + VHT_OP_CHANNEL_WIDTH_20_40) { + /* BW80 NSS1 rate: MCS9 433 Mbps */ + u4Weight = prAdapter->rWifiVar.u4DeQuePercentVHT80Nss1; + } else if (prBssInfo->eBssSCO != CHNL_EXT_SCN) { + /* BW40 NSS1 Max rate: 200 Mbps */ + u4Weight = prAdapter->rWifiVar.u4DeQuePercentVHT40Nss1; + } else { + /* BW20 NSS1 Max rate: 72.2Mbps (MCS8 86.7Mbps) */ + u4Weight = prAdapter->rWifiVar.u4DeQuePercentVHT20Nss1; + } + } else if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_HT) { + if (prBssInfo->ucHtOpInfo1 & HT_OP_INFO1_STA_CHNL_WIDTH) { + /* BW40 NSS1 Max rate: 150 Mbps (MCS9 200Mbps)*/ + u4Weight = prAdapter->rWifiVar.u4DeQuePercentHT40Nss1; + } else { + /* BW20 NSS1 Max rate: 72.2Mbps (MCS8 86.7Mbps)*/ + u4Weight = prAdapter->rWifiVar.u4DeQuePercentHT20Nss1; + } + } + + u4Quota = u4TotalQuota * u4Weight / 100; + + if (u4Quota > u4TotalQuota || u4Quota <= 0) + return u4TotalQuota; + + return u4Quota; +} + +/*----------------------------------------------------------------------------*/ +/* RX-Related Queue Management */ +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +/*! + * \brief Init Queue Management for RX + * + * \param[in] (none) + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void qmInitRxQueues(IN struct ADAPTER *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 + */ +/*----------------------------------------------------------------------------*/ +struct SW_RFB *qmHandleRxPackets(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfbListHead) +{ + +#if CFG_RX_REORDERING_ENABLED + struct SW_RFB *prCurrSwRfb; + struct SW_RFB *prNextSwRfb; + struct HW_MAC_RX_DESC *prRxStatus; + struct QUE rReturnedQue; + struct QUE *prReturnedQue; + uint8_t *pucEthDestAddr; + u_int8_t fgIsBMC, fgIsHTran; + u_int8_t fgMicErr; +#if CFG_SUPPORT_REPLAY_DETECTION + u_int8_t ucBssIndexRly = 0; + struct BSS_INFO *prBssInfoRly = NULL; +#endif + + DEBUGFUNC("qmHandleRxPackets"); + + ASSERT(prSwRfbListHead); + + prReturnedQue = &rReturnedQue; + + QUEUE_INITIALIZE(prReturnedQue); + prNextSwRfb = prSwRfbListHead; + + do { + prCurrSwRfb = prNextSwRfb; + prNextSwRfb = QM_RX_GET_NEXT_SW_RFB(prCurrSwRfb); + + prRxStatus = prCurrSwRfb->prRxStatus; + if (prRxStatus->u2RxByteCount > CFG_RX_MAX_PKT_SIZE) { + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) prCurrSwRfb); + DBGLOG(QM, ERROR, + "Drop packet when packet length is larger than CFG_RX_MAX_PKT_SIZE. Packet length=%d\n", + prRxStatus->u2RxByteCount); + continue; + } + /* 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)) { + log_dbg(SW4, INFO, "QM RX DATA: net _u sta idx %u wlan idx %u ssn _u tid %u ptype %u 11 %u\n", + prCurrSwRfb->ucStaRecIdx, prRxStatus->ucWlanIdx, + HAL_RX_STATUS_GET_TID(prRxStatus), + prCurrSwRfb->ucPacketType, + prCurrSwRfb->fgReorderBuffer); + + DBGLOG_MEM8(SW4, TRACE, + (uint8_t *) prCurrSwRfb->pvHeader, + prCurrSwRfb->u2PacketLen); + } +#endif + + fgIsBMC = HAL_RX_STATUS_IS_BC(prRxStatus) | + HAL_RX_STATUS_IS_MC(prRxStatus); + fgIsHTran = FALSE; + if (HAL_RX_STATUS_GET_HEADER_TRAN(prRxStatus) == TRUE) { + /* (!HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)){ */ + + uint8_t ucBssIndex; + struct BSS_INFO *prBssInfo; + uint8_t aucTaAddr[MAC_ADDR_LEN]; + + fgIsHTran = TRUE; + pucEthDestAddr = prCurrSwRfb->pvHeader; + if (prCurrSwRfb->prRxStatusGroup4 == NULL) { + DBGLOG(QM, ERROR, + "H/W did Header Trans but prRxStatusGroup4 is NULL !!!\n"); + DBGLOG_MEM8(QM, ERROR, prCurrSwRfb->pucRecvBuff, + HAL_RX_STATUS_GET_RX_BYTE_CNT( + prRxStatus)); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) + prCurrSwRfb); + DBGLOG(RX, WARN, + "rxStatusGroup4 for data packet is NULL, drop this packet, and dump RXD and Packet\n"); + DBGLOG_MEM8(RX, WARN, (uint8_t *) prRxStatus, + sizeof(*prRxStatus)); + if (prCurrSwRfb->pvHeader) + DBGLOG_MEM8(RX, WARN, + prCurrSwRfb->pvHeader, + prCurrSwRfb->u2PacketLen > + 32 ? 32 : + prCurrSwRfb->u2PacketLen); +#if 0 + glGetRstReason(RST_GROUP4_NULL); + GL_RESET_TRIGGER(prAdapter, + RST_FLAG_DO_CORE_DUMP); +#endif + continue; + } + + if (prCurrSwRfb->prStaRec == NULL) { + /* Workaround WTBL Issue */ + HAL_RX_STATUS_GET_TA( + prCurrSwRfb->prRxStatusGroup4, + aucTaAddr); + prCurrSwRfb->ucStaRecIdx = + secLookupStaRecIndexFromTA( + prAdapter, aucTaAddr); + if (prCurrSwRfb->ucStaRecIdx < + CFG_STA_REC_NUM) { + prCurrSwRfb->prStaRec = + cnmGetStaRecByIndex(prAdapter, + prCurrSwRfb-> + ucStaRecIdx); +#define __STR_FMT__ \ + "Re-search the staRec = %d, mac = " MACSTR ", byteCnt= %d\n" + log_dbg(QM, TRACE, + __STR_FMT__, + prCurrSwRfb->ucStaRecIdx, + MAC2STR(aucTaAddr), + prRxStatus->u2RxByteCount); +#undef __STR_FMT__ + } + + if (prCurrSwRfb->prStaRec == NULL) { + DBGLOG(QM, TRACE, + "Mark NULL the Packet for no STA_REC, wlanIdx=%d\n", + prRxStatus->ucWlanIdx); + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_NO_STA_DROP_COUNT); + prCurrSwRfb->eDst = + RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) + prCurrSwRfb); + continue; + } + + prCurrSwRfb->ucWlanIdx = + prCurrSwRfb->prStaRec->ucWlanIndex; + GLUE_SET_PKT_BSS_IDX(prCurrSwRfb->pvPacket, + secGetBssIdxByWlanIdx(prAdapter, + prCurrSwRfb->ucWlanIdx)); + } + + if (prCurrSwRfb->ucTid >= CFG_RX_MAX_BA_TID_NUM) { + log_dbg(QM, ERROR, "TID from RXD = %d, out of range !!!\n", + prCurrSwRfb->ucTid); + DBGLOG_MEM8(QM, ERROR, + prCurrSwRfb->pucRecvBuff, + HAL_RX_STATUS_GET_RX_BYTE_CNT( + prRxStatus)); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) prCurrSwRfb); + continue; + } + + if (prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem > + (CFG_RX_MAX_PKT_NUM - + CFG_NUM_OF_QM_RX_PKT_NUM) || TRUE) { + + ucBssIndex = prCurrSwRfb->prStaRec->ucBssIndex; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex); + + if (!IS_BSS_ACTIVE(prBssInfo)) { + log_dbg(QM, TRACE, "Mark NULL the Packet for inactive Bss %u\n", + ucBssIndex); + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_INACTIVE_BSS_DROP_COUNT); + prCurrSwRfb->eDst = + RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) + prCurrSwRfb); + continue; + } + + if (prBssInfo->eCurrentOPMode == + OP_MODE_ACCESS_POINT) { + if (IS_BMCAST_MAC_ADDR( + pucEthDestAddr)) { + prCurrSwRfb->eDst = + RX_PKT_DESTINATION_HOST_WITH_FORWARD; + } else if ( + secLookupStaRecIndexFromTA( + prAdapter, + pucEthDestAddr) + != + STA_REC_INDEX_NOT_FOUND) { + + prCurrSwRfb->eDst = + RX_PKT_DESTINATION_FORWARD; + } + } +#if CFG_SUPPORT_PASSPOINT + else if (hs20IsFrameFilterEnabled(prAdapter, + prBssInfo) && + hs20IsUnsecuredFrame(prAdapter, + prBssInfo, + prCurrSwRfb)) { + DBGLOG(QM, WARN, + "Mark NULL the Packet for Dropped Packet %u\n", + ucBssIndex); + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_HS20_DROP_COUNT); + prCurrSwRfb->eDst = + RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) + prCurrSwRfb); + continue; + } +#endif /* CFG_SUPPORT_PASSPOINT */ + + } else { + /* Dont not occupy other SW RFB */ + DBGLOG(QM, TRACE, + "Mark NULL the Packet for less Free Sw Rfb\n"); + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_LESS_SW_RFB_DROP_COUNT); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) prCurrSwRfb); + continue; + } + + } else { + uint16_t u2FrameCtrl = 0; + struct WLAN_MAC_HEADER *prWlanHeader = NULL; + + prWlanHeader = (struct WLAN_MAC_HEADER *) + prCurrSwRfb->pvHeader; + u2FrameCtrl = prWlanHeader->u2FrameCtrl; + if (prCurrSwRfb->prStaRec == NULL && + RXM_IS_DATA_FRAME(u2FrameCtrl) && + (prAdapter->prAisBssInfo) && + (prAdapter->prAisBssInfo->eConnectionState == + PARAM_MEDIA_STATE_CONNECTED)) { + /* rx header translation */ + log_dbg(QM, INFO, "RXD Trans: FrameCtrl=0x%02x GVLD=0x%x, StaRecIdx=%d, WlanIdx=%d PktLen=%d\n", + u2FrameCtrl, prCurrSwRfb->ucGroupVLD, + prCurrSwRfb->ucStaRecIdx, + prCurrSwRfb->ucWlanIdx, + prCurrSwRfb->u2PacketLen); + + if (prAdapter->prAisBssInfo + && prAdapter->prAisBssInfo->prStaRecOfAP) + if (EQUAL_MAC_ADDR( + prWlanHeader-> + aucAddr1, + prAdapter-> + prAisBssInfo-> + aucOwnMacAddr) + && EQUAL_MAC_ADDR( + prWlanHeader-> + aucAddr2, + prAdapter-> + prAisBssInfo-> + aucBSSID)) { + uint16_t u2MACLen = 0; + /* QoS data, VHT */ + if (RXM_IS_QOS_DATA_FRAME( + u2FrameCtrl)) + u2MACLen = sizeof( + struct WLAN_MAC_HEADER_QOS); + else + u2MACLen = sizeof( + struct + WLAN_MAC_HEADER); + u2MACLen += + ETH_LLC_LEN + + ETH_SNAP_OUI_LEN; + u2MACLen -= + ETHER_TYPE_LEN_OFFSET; + prCurrSwRfb->pvHeader += + u2MACLen; + kalMemCopy( + prCurrSwRfb->pvHeader, + prWlanHeader->aucAddr1, + MAC_ADDR_LEN); + kalMemCopy( + prCurrSwRfb->pvHeader + + MAC_ADDR_LEN, + prWlanHeader->aucAddr2, + MAC_ADDR_LEN); + prCurrSwRfb->u2PacketLen -= + u2MACLen; + + /* record StaRec related info */ + prCurrSwRfb->prStaRec = + prAdapter-> + prAisBssInfo-> + prStaRecOfAP; + prCurrSwRfb->ucStaRecIdx = + prCurrSwRfb->prStaRec-> + ucIndex; + prCurrSwRfb->ucWlanIdx = + prCurrSwRfb->prStaRec-> + ucWlanIndex; + GLUE_SET_PKT_BSS_IDX( + prCurrSwRfb->pvPacket, + secGetBssIdxByWlanIdx( + prAdapter, + prCurrSwRfb-> + ucWlanIdx)); + DBGLOG_MEM8(QM, WARN, + (uint8_t *) + prCurrSwRfb->pvHeader, + (prCurrSwRfb-> + u2PacketLen > 64) ? 64 : + prCurrSwRfb-> + u2PacketLen); + } + } + } + +#if CFG_SUPPORT_WAPI + if (prCurrSwRfb->u2PacketLen > ETHER_HEADER_LEN) { + uint8_t *pc = (uint8_t *) prCurrSwRfb->pvHeader; + uint16_t u2Etype = 0; + + u2Etype = (pc[ETHER_TYPE_LEN_OFFSET] << 8) | + (pc[ETHER_TYPE_LEN_OFFSET + 1]); + /* for wapi integrity test. WPI_1x packet should be + * always in non-encrypted mode. if we received any + * WPI(0x88b4) packet that is encrypted, drop here. + */ + if (u2Etype == ETH_WPI_1X && + HAL_RX_STATUS_GET_SEC_MODE(prRxStatus) != 0 && + HAL_RX_STATUS_IS_CIPHER_MISMATCH(prRxStatus) == 0) { + DBGLOG(QM, INFO, + "drop wpi packet with sec mode\n"); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) prCurrSwRfb); + continue; + } + } +#endif + + + /* Todo:: Move the data class error check here */ + +#if CFG_SUPPORT_REPLAY_DETECTION + if (prCurrSwRfb->prStaRec) { + ucBssIndexRly = prCurrSwRfb->prStaRec->ucBssIndex; + prBssInfoRly = GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndexRly); + if (prBssInfoRly && !IS_BSS_ACTIVE(prBssInfoRly)) { + DBGLOG(QM, INFO, + "Mark NULL the Packet for inactive Bss %u\n", + ucBssIndexRly); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) prCurrSwRfb); + continue; + } + } + if (fgIsBMC && prBssInfoRly && IS_BSS_AIS(prBssInfoRly) && + qmHandleRxReplay(prAdapter, prCurrSwRfb)) { + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) prCurrSwRfb); + continue; + } +#endif + + if (prCurrSwRfb->fgReorderBuffer && !fgIsBMC && fgIsHTran) { + /* 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, + prReturnedQue); + + } else if (prCurrSwRfb->fgDataFrame) { + /* Check Class Error */ + if (prCurrSwRfb->prStaRec && + (secCheckClassError(prAdapter, prCurrSwRfb, + prCurrSwRfb->prStaRec) == TRUE)) { + struct RX_BA_ENTRY *prReorderQueParm = NULL; + + if (!fgIsBMC && fgIsHTran && + (HAL_RX_STATUS_GET_FRAME_CTL_FIELD( + prCurrSwRfb->prRxStatusGroup4) & + MASK_FRAME_TYPE) != MAC_FRAME_DATA) { + prReorderQueParm = + ((prCurrSwRfb->prStaRec-> + aprRxReorderParamRefTbl)[ + prCurrSwRfb->ucTid]); + } + + if (prReorderQueParm && + prReorderQueParm->fgIsValid) { + /* Only QoS Data frame with BA aggrement + * shall enter reordering buffer + */ + qmProcessPktWithReordering(prAdapter, + prCurrSwRfb, + prReturnedQue); + } else + qmHandleRxPackets_AOSP_1; + } else { + DBGLOG(QM, TRACE, + "Mark NULL the Packet for class error\n"); + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_CLASS_ERR_DROP_COUNT); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) prCurrSwRfb); + } + } else { + struct WLAN_MAC_HEADER *prWlanMacHeader; + + ASSERT(prCurrSwRfb->pvHeader); + + prWlanMacHeader = (struct WLAN_MAC_HEADER *) + prCurrSwRfb->pvHeader; + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + + switch (prWlanMacHeader->u2FrameCtrl & + MASK_FRAME_TYPE) { + /* BAR frame */ + case MAC_FRAME_BLOCK_ACK_REQ: + qmProcessBarFrame(prAdapter, + prCurrSwRfb, prReturnedQue); + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_BAR_DROP_COUNT); + break; + default: + DBGLOG(QM, TRACE, + "Mark NULL the Packet for non-interesting type\n"); + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_NO_INTEREST_DROP_COUNT); + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) prCurrSwRfb); + break; + } + } + + } while (prNextSwRfb); + + /* The returned list of SW_RFBs must end with a NULL pointer */ + if (QUEUE_IS_NOT_EMPTY(prReturnedQue)) + QM_TX_SET_NEXT_MSDU_INFO((struct SW_RFB *) QUEUE_GET_TAIL( + prReturnedQue), NULL); + + return (struct SW_RFB *) QUEUE_GET_HEAD(prReturnedQue); + +#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 struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + OUT struct QUE *prReturnedQue) +{ + + struct STA_RECORD *prStaRec; + struct HW_MAC_RX_DESC *prRxStatus; + struct RX_BA_ENTRY *prReorderQueParm; + +#if CFG_SUPPORT_RX_AMSDU + uint8_t u8AmsduSubframeIdx; + uint32_t u4SeqNo; +#endif + DEBUGFUNC("qmProcessPktWithReordering"); + + ASSERT(prSwRfb); + ASSERT(prReturnedQue); + ASSERT(prSwRfb->prRxStatus); + + /* We should have STA_REC here */ + prStaRec = prSwRfb->prStaRec; + ASSERT(prStaRec); + ASSERT(prSwRfb->ucTid < CFG_RX_MAX_BA_TID_NUM); + + prRxStatus = prSwRfb->prRxStatus; + + if (prSwRfb->ucTid >= CFG_RX_MAX_BA_TID_NUM) { + DBGLOG(QM, WARN, "TID from RXD = %d, out of range!!\n", + prSwRfb->ucTid); + DBGLOG_MEM8(QM, ERROR, prSwRfb->pucRecvBuff, + HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus)); + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) prSwRfb); + return; + } + + /* Check whether the BA agreement exists */ + prReorderQueParm = (( + prStaRec->aprRxReorderParamRefTbl)[prSwRfb->ucTid]); + if (!prReorderQueParm || !(prReorderQueParm->fgIsValid)) { + DBGLOG(QM, TRACE, + "Reordering but no BA agreement for STA[%d] TID[%d]\n", + prStaRec->ucIndex, prSwRfb->ucTid); + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *) prSwRfb); + return; + } + + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_DATA_REORDER_TOTAL_COUNT); + + prSwRfb->u2SSN = HAL_RX_STATUS_GET_SEQFrag_NUM( + prSwRfb->prRxStatusGroup4) >> RX_STATUS_SEQ_NUM_OFFSET; + +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + /* QUEUE_INITIALIZE(&prSwRfb->rAmsduQue); */ + + u8AmsduSubframeIdx = HAL_RX_STATUS_GET_PAYLOAD_FORMAT(prRxStatus); + + /* prMpduSwRfb = prReorderQueParm->prMpduSwRfb; */ + u4SeqNo = (uint32_t)prSwRfb->u2SSN; + + switch (u8AmsduSubframeIdx) { + case RX_PAYLOAD_FORMAT_FIRST_SUB_AMSDU: + if (prReorderQueParm->fgAmsduNeedLastFrame) { + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_DATA_AMSDU_MISS_COUNT); + prReorderQueParm->fgAmsduNeedLastFrame = FALSE; + } + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_DATA_MSDU_IN_AMSDU_COUNT); + RX_INC_CNT(&prAdapter->rRxCtrl, RX_DATA_AMSDU_COUNT); + break; + + case RX_PAYLOAD_FORMAT_MIDDLE_SUB_AMSDU: + prReorderQueParm->fgAmsduNeedLastFrame = TRUE; + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_DATA_MSDU_IN_AMSDU_COUNT); + if (prReorderQueParm->u4SeqNo != u4SeqNo) { + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_DATA_AMSDU_MISS_COUNT); + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_DATA_AMSDU_COUNT); + } + break; + case RX_PAYLOAD_FORMAT_LAST_SUB_AMSDU: + prReorderQueParm->fgAmsduNeedLastFrame = FALSE; + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_DATA_MSDU_IN_AMSDU_COUNT); + if (prReorderQueParm->u4SeqNo != u4SeqNo) { + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_DATA_AMSDU_MISS_COUNT); + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_DATA_AMSDU_COUNT); + } + break; + + case RX_PAYLOAD_FORMAT_MSDU: + if (prReorderQueParm->fgAmsduNeedLastFrame) { + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_DATA_AMSDU_MISS_COUNT); + prReorderQueParm->fgAmsduNeedLastFrame = FALSE; + } + break; + default: + break; + } + + prReorderQueParm->u4SeqNo = u4SeqNo; +#endif + + RX_DIRECT_REORDER_LOCK(prAdapter, 0); + /* After resuming, WinStart and WinEnd are obsolete and unsync + * with AP's SN. So assign the SN of first packet to WinStart + * as "Fall Within" case. + */ + if (prReorderQueParm->fgFirstSnToWinStart) { + DBGLOG(QM, INFO, + "[%u] First resumed SN(%u) reset Window{%u,%u}\n", + prSwRfb->ucTid, prSwRfb->u2SSN, + prReorderQueParm->u2WinStart, + prReorderQueParm->u2WinEnd); + + prReorderQueParm->u2WinStart = prSwRfb->u2SSN; + prReorderQueParm->u2WinEnd = + ((prReorderQueParm->u2WinStart) + + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT; + prReorderQueParm->fgFirstSnToWinStart = FALSE; + } + + /* Insert reorder packet */ + qmInsertReorderPkt(prAdapter, prSwRfb, prReorderQueParm, + prReturnedQue); + RX_DIRECT_REORDER_UNLOCK(prAdapter, 0); +} + +void qmProcessBarFrame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, OUT struct QUE *prReturnedQue) +{ + + struct STA_RECORD *prStaRec; + struct HW_MAC_RX_DESC *prRxStatus; + struct RX_BA_ENTRY *prReorderQueParm; + struct CTRL_BAR_FRAME *prBarCtrlFrame; + + uint32_t u4SSN; + uint32_t u4WinStart; + uint32_t u4WinEnd; + + ASSERT(prSwRfb); + ASSERT(prReturnedQue); + ASSERT(prSwRfb->prRxStatus); + ASSERT(prSwRfb->pvHeader); + + prRxStatus = prSwRfb->prRxStatus; + + prBarCtrlFrame = (struct CTRL_BAR_FRAME *) prSwRfb->pvHeader; + + prSwRfb->ucTid = + (*((uint16_t *) ((uint8_t *) prBarCtrlFrame + + CTRL_BAR_BAR_CONTROL_OFFSET))) >> + BAR_CONTROL_TID_INFO_OFFSET; + prSwRfb->u2SSN = + (*((uint16_t *) ((uint8_t *) prBarCtrlFrame + + CTRL_BAR_BAR_INFORMATION_OFFSET))) >> + OFFSET_BAR_SSC_SN; + + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (struct QUE_ENTRY *) prSwRfb); + + /* Incorrect STA_REC index */ + prSwRfb->ucStaRecIdx = secLookupStaRecIndexFromTA(prAdapter, + prBarCtrlFrame->aucSrcAddr); + if (prSwRfb->ucStaRecIdx >= CFG_STA_REC_NUM) { + 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 */ + prSwRfb->prStaRec = cnmGetStaRecByIndex(prAdapter, + prSwRfb->ucStaRecIdx); + prStaRec = prSwRfb->prStaRec; + if (prStaRec == NULL) { + /* ASSERT(prStaRec); */ + return; + } +#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 index out of bound */ + if (prSwRfb->ucTid >= CFG_RX_MAX_BA_TID_NUM) { + DBGLOG(QM, WARN, + "QM: (Warning) index out of bound: ucTid = %d\n", + prSwRfb->ucTid); + /* ASSERT(0); */ + return; + } + + /* 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; + } + + RX_DIRECT_REORDER_LOCK(prAdapter, 0); + + u4SSN = (uint32_t) (prSwRfb->u2SSN); + u4WinStart = (uint32_t) (prReorderQueParm->u2WinStart); + u4WinEnd = (uint32_t) (prReorderQueParm->u2WinEnd); + + if (qmCompareSnIsLessThan(u4WinStart, u4SSN)) { + prReorderQueParm->u2WinStart = (uint16_t) u4SSN; + prReorderQueParm->u2WinEnd = + ((prReorderQueParm->u2WinStart) + + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT; +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + prReorderQueParm->u8LastAmsduSubIdx = RX_PAYLOAD_FORMAT_MSDU; +#endif + DBGLOG(QM, TRACE, + "QM:(BAR)[%d](%u){%hu,%hu}\n", + prSwRfb->ucTid, u4SSN, + prReorderQueParm->u2WinStart, + prReorderQueParm->u2WinEnd); + qmPopOutDueToFallAhead(prAdapter, prReorderQueParm, + prReturnedQue); + } else { + DBGLOG(QM, TRACE, "QM:(BAR)(%d)(%u){%u,%u}\n", + prSwRfb->ucTid, u4SSN, u4WinStart, u4WinEnd); + } + RX_DIRECT_REORDER_UNLOCK(prAdapter, 0); +} + +void qmInsertReorderPkt(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN struct RX_BA_ENTRY *prReorderQueParm, + OUT struct QUE *prReturnedQue) +{ + uint32_t u4SeqNo; + uint32_t u4WinStart; + uint32_t u4WinEnd; + + /* Start to reorder packets */ + u4SeqNo = (uint32_t) (prSwRfb->u2SSN); + u4WinStart = (uint32_t) (prReorderQueParm->u2WinStart); + u4WinEnd = (uint32_t) (prReorderQueParm->u2WinEnd); + + /* Debug */ + DBGLOG_LIMITED(QM, LOUD, "QM:(R)[%u](%u){%u,%u}\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(prAdapter, prSwRfb, + prReorderQueParm, prReturnedQue); + +#if QM_RX_WIN_SSN_AUTO_ADVANCING + if (prReorderQueParm->fgIsWaitingForPktWithSsn) { + /* Let the first received packet + * pass the reorder check + */ + DBGLOG(QM, LOUD, "QM:(A)[%d](%u){%u,%u}\n", + prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); + + prReorderQueParm->u2WinStart = (uint16_t) u4SeqNo; + prReorderQueParm->u2WinEnd = + ((prReorderQueParm->u2WinStart) + + (prReorderQueParm->u2WinSize) - 1) % + MAX_SEQ_NO_COUNT; + prReorderQueParm->fgIsWaitingForPktWithSsn = FALSE; +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + prReorderQueParm->u8LastAmsduSubIdx = + RX_PAYLOAD_FORMAT_MSDU; +#endif + } +#endif + + qmPopOutDueToFallWithin(prAdapter, 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)))) { + + uint16_t u2Delta, u2BeforeWinEnd; + uint32_t u4BeforeCount, u4MissingCount; + +#if QM_RX_WIN_SSN_AUTO_ADVANCING + if (prReorderQueParm->fgIsWaitingForPktWithSsn) + prReorderQueParm->fgIsWaitingForPktWithSsn = FALSE; +#endif + + qmInsertFallAheadReorderPkt(prAdapter, prSwRfb, + prReorderQueParm, prReturnedQue); + + u2BeforeWinEnd = prReorderQueParm->u2WinEnd; + + /* Advance the window after inserting a new tail */ + prReorderQueParm->u2WinEnd = (uint16_t) u4SeqNo; + prReorderQueParm->u2WinStart = + (((prReorderQueParm->u2WinEnd) + MAX_SEQ_NO_COUNT - + prReorderQueParm->u2WinSize + 1) % + MAX_SEQ_NO_COUNT); +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + prReorderQueParm->u8LastAmsduSubIdx = + RX_PAYLOAD_FORMAT_MSDU; +#endif + u4BeforeCount = prReorderQueParm->rReOrderQue.u4NumElem; + qmPopOutDueToFallAhead(prAdapter, prReorderQueParm, + prReturnedQue); + + if (prReorderQueParm->u2WinEnd >= u2BeforeWinEnd) + u2Delta = prReorderQueParm->u2WinEnd - u2BeforeWinEnd; + else + u2Delta = MAX_SEQ_NO_COUNT - (u2BeforeWinEnd - + prReorderQueParm->u2WinEnd); + + u4MissingCount = u2Delta - (u4BeforeCount - + prReorderQueParm->rReOrderQue.u4NumElem); + + RX_ADD_CNT(&prAdapter->rRxCtrl, RX_DATA_REORDER_MISS_COUNT, + u4MissingCount); + } + /* Case 3: Fall behind */ + else { +#if CFG_SUPPORT_LOWLATENCY_MODE || CFG_SUPPORT_OSHARE + if (qmIsNoDropPacket(prAdapter, prSwRfb)) { + DBGLOG(QM, LOUD, "QM: No drop packet:[%d](%d){%d,%d}\n", + prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); + + qmPopOutReorderPkt(prAdapter, prSwRfb, + prReturnedQue, RX_DATA_REORDER_BEHIND_COUNT); + return; + } +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + +#if QM_RX_WIN_SSN_AUTO_ADVANCING && QM_RX_INIT_FALL_BEHIND_PASS + if (prReorderQueParm->fgIsWaitingForPktWithSsn) { + DBGLOG(QM, LOUD, "QM:(P)[%u](%u){%u,%u}\n", + prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); + qmPopOutReorderPkt(prAdapter, prSwRfb, prReturnedQue, + RX_DATA_REORDER_BEHIND_COUNT); + return; + } +#endif + + /* An erroneous packet */ + DBGLOG(QM, LOUD, "QM:(D)[%u](%u){%u,%u}\n", prSwRfb->ucTid, + u4SeqNo, u4WinStart, u4WinEnd); + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + qmPopOutReorderPkt(prAdapter, prSwRfb, prReturnedQue, + RX_DATA_REORDER_BEHIND_COUNT); + return; + } +} + +void qmInsertFallWithinReorderPkt(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN struct RX_BA_ENTRY *prReorderQueParm, + OUT struct QUE *prReturnedQue) +{ + struct SW_RFB *prExaminedQueuedSwRfb; + struct QUE *prReorderQue; + struct HW_MAC_RX_DESC *prRxStatus; + uint8_t u8AmsduSubframeIdx; /* RX reorder for one MSDU in AMSDU issue */ + + ASSERT(prSwRfb); + ASSERT(prReorderQueParm); + ASSERT(prReturnedQue); + + prReorderQue = &(prReorderQueParm->rReOrderQue); + prExaminedQueuedSwRfb = (struct SW_RFB *) QUEUE_GET_HEAD( + prReorderQue); + + prRxStatus = prSwRfb->prRxStatus; + u8AmsduSubframeIdx = HAL_RX_STATUS_GET_PAYLOAD_FORMAT( + prRxStatus); + + /* There are no packets queued in the Reorder Queue */ + if (prExaminedQueuedSwRfb == NULL) { + ((struct QUE_ENTRY *) prSwRfb)->prPrev = NULL; + ((struct QUE_ENTRY *) prSwRfb)->prNext = NULL; + prReorderQue->prHead = (struct QUE_ENTRY *) prSwRfb; + prReorderQue->prTail = (struct QUE_ENTRY *) prSwRfb; + prReorderQue->u4NumElem++; + } + + /* Determine the insert position */ + else { + do { + /* Case 1: Terminate. A duplicate packet */ + if ((prExaminedQueuedSwRfb->u2SSN) == + (prSwRfb->u2SSN)) { +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + /* if middle or last and first is not + * duplicated, not a duplicat packet + */ + if (!prReorderQueParm->fgIsAmsduDuplicated && + (u8AmsduSubframeIdx == + RX_PAYLOAD_FORMAT_MIDDLE_SUB_AMSDU || + u8AmsduSubframeIdx == + RX_PAYLOAD_FORMAT_LAST_SUB_AMSDU)) { + + prExaminedQueuedSwRfb = + (struct SW_RFB *)(( + (struct QUE_ENTRY *) + prExaminedQueuedSwRfb)->prNext); + while (prExaminedQueuedSwRfb && + ((prExaminedQueuedSwRfb-> + u2SSN) == (prSwRfb->u2SSN))) + prExaminedQueuedSwRfb = + (struct SW_RFB *)(( + (struct QUE_ENTRY *) + prExaminedQueuedSwRfb)-> + prNext); + + break; + } + /* if first is duplicated, + * drop subsequent middle and last frames + */ + if (u8AmsduSubframeIdx == + RX_PAYLOAD_FORMAT_FIRST_SUB_AMSDU) + prReorderQueParm->fgIsAmsduDuplicated = + TRUE; +#endif + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + qmPopOutReorderPkt(prAdapter, + prSwRfb, prReturnedQue, + RX_DUPICATE_DROP_COUNT); + 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 = + (struct SW_RFB *) (((struct QUE_ENTRY *) + prExaminedQueuedSwRfb)->prNext); + } while (prExaminedQueuedSwRfb); +#if CFG_SUPPORT_RX_AMSDU + prReorderQueParm->fgIsAmsduDuplicated = FALSE; +#endif + /* Update the Reorder Queue Parameters according to + * the found insert position + */ + if (prExaminedQueuedSwRfb == NULL) { + /* The received packet shall be placed at the tail */ + ((struct QUE_ENTRY *) prSwRfb)->prPrev = + prReorderQue->prTail; + ((struct QUE_ENTRY *) prSwRfb)->prNext = NULL; + (prReorderQue->prTail)->prNext = + (struct QUE_ENTRY *) (prSwRfb); + prReorderQue->prTail = (struct QUE_ENTRY *) (prSwRfb); + } else { + ((struct QUE_ENTRY *) prSwRfb)->prPrev = + ((struct QUE_ENTRY *) + prExaminedQueuedSwRfb)->prPrev; + ((struct QUE_ENTRY *) prSwRfb)->prNext = + (struct QUE_ENTRY *) prExaminedQueuedSwRfb; + if (((struct QUE_ENTRY *) prExaminedQueuedSwRfb) == + (prReorderQue->prHead)) { + /* The received packet will become the head */ + prReorderQue->prHead = + (struct QUE_ENTRY *) prSwRfb; + } else { + (((struct QUE_ENTRY *) + prExaminedQueuedSwRfb)->prPrev)->prNext = + (struct QUE_ENTRY *) prSwRfb; + } + ((struct QUE_ENTRY *) prExaminedQueuedSwRfb)->prPrev = + (struct QUE_ENTRY *) prSwRfb; + } + + prReorderQue->u4NumElem++; + } + +} + +void qmInsertFallAheadReorderPkt(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN struct RX_BA_ENTRY *prReorderQueParm, + OUT struct QUE *prReturnedQue) +{ + struct QUE *prReorderQue; + + ASSERT(prSwRfb); + ASSERT(prReorderQueParm); + ASSERT(prReturnedQue); +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + prReorderQueParm->fgIsAmsduDuplicated = FALSE; +#endif + prReorderQue = &(prReorderQueParm->rReOrderQue); + /* There are no packets queued in the Reorder Queue */ + if (QUEUE_IS_EMPTY(prReorderQue)) { + ((struct QUE_ENTRY *) prSwRfb)->prPrev = NULL; + ((struct QUE_ENTRY *) prSwRfb)->prNext = NULL; + prReorderQue->prHead = (struct QUE_ENTRY *) prSwRfb; + } else { + ((struct QUE_ENTRY *) prSwRfb)->prPrev = + prReorderQue->prTail; + ((struct QUE_ENTRY *) prSwRfb)->prNext = NULL; + (prReorderQue->prTail)->prNext = (struct QUE_ENTRY *) ( + prSwRfb); + } + prReorderQue->prTail = (struct QUE_ENTRY *) prSwRfb; + prReorderQue->u4NumElem++; +} + +void qmPopOutReorderPkt(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, OUT struct QUE *prReturnedQue, + IN enum ENUM_RX_STATISTIC_COUNTER eRxCounter) +{ + uint32_t u4PktCnt = 0; + /* RX reorder for one MSDU in AMSDU issue */ +#if 0 + struct SW_RFB *prAmsduSwRfb; +#endif + +#if CFG_SUPPORT_RX_DYNAMIC_MCC_PRIORITY + struct STA_RECORD *prStaRec = NULL; + + prStaRec = &(prAdapter->arStaRec[prSwRfb->ucStaRecIdx]); + + if (prStaRec->fgIsInUse) { + if (IS_STA_IN_P2P(prStaRec)) { + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_DATA_REORDER_WITHIN_COUNT_P2P); + } else if (IS_STA_IN_AIS(prStaRec)) { + RX_INC_CNT(&prAdapter->rRxCtrl, + RX_DATA_REORDER_WITHIN_COUNT_STA); + } + } +#endif + + u4PktCnt++; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *)prSwRfb); + +#if 0 + u4PktCnt += prSwRfb->rAmsduQue.u4NumElem; + QUEUE_REMOVE_HEAD(&prSwRfb->rAmsduQue, prAmsduSwRfb, + struct SW_RFB *); + while (prAmsduSwRfb) { + /* Update MSDU destination of AMSDU */ + prAmsduSwRfb->eDst = prSwRfb->eDst; + QUEUE_INSERT_TAIL(prReturnedQue, + (struct QUE_ENTRY *)prAmsduSwRfb); + QUEUE_REMOVE_HEAD(&prSwRfb->rAmsduQue, prAmsduSwRfb, + struct SW_RFB *); + } +#endif + + RX_ADD_CNT(&prAdapter->rRxCtrl, eRxCounter, u4PktCnt); +} + +void qmPopOutDueToFallWithin(IN struct ADAPTER *prAdapter, + IN struct RX_BA_ENTRY *prReorderQueParm, + OUT struct QUE *prReturnedQue) +{ + struct SW_RFB *prReorderedSwRfb; + struct QUE *prReorderQue; + u_int8_t fgDequeuHead, fgMissing; + OS_SYSTIME rCurrentTime, *prMissTimeout; + struct HW_MAC_RX_DESC *prRxStatus; + /* RX reorder for one MSDU in AMSDU issue */ + uint8_t fgIsAmsduSubframe; + + 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 = (struct SW_RFB *) QUEUE_GET_HEAD( + prReorderQue); + fgDequeuHead = FALSE; + + /* RX reorder for one MSDU in AMSDU issue */ + prRxStatus = prReorderedSwRfb->prRxStatus; + fgIsAmsduSubframe = HAL_RX_STATUS_GET_PAYLOAD_FORMAT( + prRxStatus); +#if CFG_SUPPORT_RX_AMSDU + /* If SN + 1 come and last frame is first or middle, + * update winstart + */ + if ((qmCompareSnIsLessThan((prReorderQueParm->u2WinStart), + (prReorderedSwRfb->u2SSN))) + && (prReorderQueParm->u4SeqNo != + prReorderQueParm->u2WinStart)) { + if (prReorderQueParm->u8LastAmsduSubIdx == + RX_PAYLOAD_FORMAT_FIRST_SUB_AMSDU + || prReorderQueParm->u8LastAmsduSubIdx == + RX_PAYLOAD_FORMAT_MIDDLE_SUB_AMSDU) { + + prReorderQueParm->u2WinStart = + (((prReorderQueParm->u2WinStart) + 1) % + MAX_SEQ_NO_COUNT); + prReorderQueParm->u8LastAmsduSubIdx = + RX_PAYLOAD_FORMAT_MSDU; + } + } +#endif + /* SN == WinStart, so the head packet + * shall be indicated (advance the window) + */ + if ((prReorderedSwRfb->u2SSN) == + (prReorderQueParm->u2WinStart)) { + + fgDequeuHead = TRUE; + /* RX reorder for one MSDU in AMSDU issue */ + /* if last frame, winstart++. + * Otherwise, keep winstart + */ + if (fgIsAmsduSubframe == + RX_PAYLOAD_FORMAT_LAST_SUB_AMSDU + || fgIsAmsduSubframe == RX_PAYLOAD_FORMAT_MSDU) + prReorderQueParm->u2WinStart = + (((prReorderedSwRfb->u2SSN) + 1) % + MAX_SEQ_NO_COUNT); +#if CFG_SUPPORT_RX_AMSDU + prReorderQueParm->u8LastAmsduSubIdx = fgIsAmsduSubframe; +#endif + } + /* SN > WinStart, break to update WinEnd */ + else { + /* Start bubble timer */ + if (!prReorderQueParm->fgHasBubble) { + cnmTimerStartTimer(prAdapter, + &(prReorderQueParm->rReorderBubbleTimer), + prAdapter->u4QmRxBaMissTimeout); + prReorderQueParm->fgHasBubble = TRUE; + prReorderQueParm->u2FirstBubbleSn = + prReorderQueParm->u2WinStart; + + DBGLOG(QM, TRACE, + "QM:(Bub Timer) STA[%u] TID[%u] BubSN[%u] Win{%d, %d}\n", + prReorderQueParm->ucStaRecIdx, + prReorderedSwRfb->ucTid, + prReorderQueParm->u2FirstBubbleSn, + prReorderQueParm->u2WinStart, + prReorderQueParm->u2WinEnd); + } + + if (fgMissing && + CHECK_FOR_TIMEOUT(rCurrentTime, *prMissTimeout, + MSEC_TO_SYSTIME( + prAdapter->u4QmRxBaMissTimeout + ))) { + + 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); +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + prReorderQueParm->u8LastAmsduSubIdx = + RX_PAYLOAD_FORMAT_MSDU; +#endif + fgMissing = FALSE; + } else + break; + } + + /* Dequeue the head packet */ + if (fgDequeuHead) { + if (((struct QUE_ENTRY *) prReorderedSwRfb)->prNext == + NULL) { + prReorderQue->prHead = NULL; + prReorderQue->prTail = NULL; + } else { + prReorderQue->prHead = + ((struct QUE_ENTRY *) + prReorderedSwRfb)->prNext; + (((struct QUE_ENTRY *) + prReorderedSwRfb)->prNext)->prPrev = + NULL; + } + prReorderQue->u4NumElem--; + DBGLOG(QM, LOUD, "QM: [%d] %d (%d)\n", + prReorderQueParm->ucTid, + prReorderedSwRfb->u2PacketLen, + prReorderedSwRfb->u2SSN); + qmPopOutReorderPkt(prAdapter, prReorderedSwRfb, + prReturnedQue, RX_DATA_REORDER_WITHIN_COUNT); + } + } + + 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 struct ADAPTER *prAdapter, + IN struct RX_BA_ENTRY *prReorderQueParm, + OUT struct QUE *prReturnedQue) +{ + struct SW_RFB *prReorderedSwRfb; + struct QUE *prReorderQue; + u_int8_t fgDequeuHead; + struct HW_MAC_RX_DESC *prRxStatus; + uint8_t fgIsAmsduSubframe;/* RX reorder for one MSDU in AMSDU issue */ + + 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 = + (struct SW_RFB *) QUEUE_GET_HEAD(prReorderQue); + fgDequeuHead = FALSE; + + /* RX reorder for one MSDU in AMSDU issue */ + prRxStatus = prReorderedSwRfb->prRxStatus; + fgIsAmsduSubframe = + HAL_RX_STATUS_GET_PAYLOAD_FORMAT(prRxStatus); +#if CFG_SUPPORT_RX_AMSDU + /* If SN + 1 come and last frame is first or middle, + * update winstart + */ + if ((qmCompareSnIsLessThan((prReorderQueParm->u2WinStart), + (prReorderedSwRfb->u2SSN))) + && (prReorderQueParm->u4SeqNo != + prReorderQueParm->u2WinStart)) { + if (prReorderQueParm->u8LastAmsduSubIdx == + RX_PAYLOAD_FORMAT_FIRST_SUB_AMSDU + || prReorderQueParm->u8LastAmsduSubIdx == + RX_PAYLOAD_FORMAT_MIDDLE_SUB_AMSDU) { + + prReorderQueParm->u2WinStart = + (((prReorderQueParm->u2WinStart) + 1) % + MAX_SEQ_NO_COUNT); + prReorderQueParm->u8LastAmsduSubIdx = + RX_PAYLOAD_FORMAT_MSDU; + } + } +#endif + /* SN == WinStart, so the head packet shall be + * indicated (advance the window) + */ + if ((prReorderedSwRfb->u2SSN) == + (prReorderQueParm->u2WinStart)) { + + fgDequeuHead = TRUE; + /* RX reorder for one MSDU in AMSDU issue */ + /* if last frame, winstart++. + * Otherwise, keep winstart + */ + if (fgIsAmsduSubframe == + RX_PAYLOAD_FORMAT_LAST_SUB_AMSDU || + fgIsAmsduSubframe == RX_PAYLOAD_FORMAT_MSDU) + prReorderQueParm->u2WinStart = + (((prReorderedSwRfb->u2SSN) + 1) % + MAX_SEQ_NO_COUNT); +#if CFG_SUPPORT_RX_AMSDU + prReorderQueParm->u8LastAmsduSubIdx = fgIsAmsduSubframe; +#endif + } + + /* SN < WinStart, so the head packet shall be + * indicated (do not advance the window) + */ + else if (qmCompareSnIsLessThan((uint32_t)( + prReorderedSwRfb->u2SSN), + (uint32_t)(prReorderQueParm->u2WinStart))) + fgDequeuHead = TRUE; + + /* SN > WinStart, break to update WinEnd */ + else { + /* Start bubble timer */ + if (!prReorderQueParm->fgHasBubble) { + cnmTimerStartTimer(prAdapter, + &(prReorderQueParm-> + rReorderBubbleTimer), + prAdapter->u4QmRxBaMissTimeout); + prReorderQueParm->fgHasBubble = TRUE; + prReorderQueParm->u2FirstBubbleSn = + prReorderQueParm->u2WinStart; + + DBGLOG(QM, TRACE, + "QM:(Bub Timer) STA[%u] TID[%u] BubSN[%u] Win{%d, %d}\n", + prReorderQueParm->ucStaRecIdx, + prReorderedSwRfb->ucTid, + prReorderQueParm->u2FirstBubbleSn, + prReorderQueParm->u2WinStart, + prReorderQueParm->u2WinEnd); + } + break; + } + + /* Dequeue the head packet */ + if (fgDequeuHead) { + if (((struct QUE_ENTRY *) prReorderedSwRfb)->prNext == + NULL) { + prReorderQue->prHead = NULL; + prReorderQue->prTail = NULL; + } else { + prReorderQue->prHead = ((struct QUE_ENTRY *) + prReorderedSwRfb)->prNext; + (((struct QUE_ENTRY *) prReorderedSwRfb)-> + prNext)->prPrev = NULL; + } + prReorderQue->u4NumElem--; + DBGLOG_LIMITED(QM, TRACE, "QM: [%u] %u (%u)\n", + prReorderQueParm->ucTid, + prReorderedSwRfb->u2PacketLen, + prReorderedSwRfb->u2SSN); + + qmPopOutReorderPkt(prAdapter, prReorderedSwRfb, + prReturnedQue, RX_DATA_REORDER_AHEAD_COUNT); + } + } + + /* After WinStart has been determined, update the WinEnd */ + prReorderQueParm->u2WinEnd = + (((prReorderQueParm->u2WinStart) + + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT); + +} + +void qmHandleReorderBubbleTimeout(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr) +{ + struct mt66xx_chip_info *prChipInfo; + struct RX_BA_ENTRY *prReorderQueParm = + (struct RX_BA_ENTRY *) ulParamPtr; + struct SW_RFB *prSwRfb = (struct SW_RFB *) NULL; + struct WIFI_EVENT *prEvent; + struct EVENT_CHECK_REORDER_BUBBLE *prCheckReorderEvent; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + if (!prReorderQueParm->fgIsValid) { + DBGLOG(QM, TRACE, + "QM:(Bub Check Cancel) STA[%u] TID[%u], No Rx BA entry\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + return; + } + + if (!prReorderQueParm->fgHasBubble) { + DBGLOG(QM, TRACE, + "QM:(Bub Check Cancel) STA[%u] TID[%u], Bubble has been filled\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + return; + } + + DBGLOG(QM, TRACE, + "QM:(Bub Timeout) STA[%u] TID[%u] BubSN[%u]\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid, + prReorderQueParm->u2FirstBubbleSn); + + /* Generate a self-inited event to Rx path */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_REMOVE_HEAD(&prAdapter->rRxCtrl.rFreeSwRfbList, + prSwRfb, struct SW_RFB *); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + if (prSwRfb) { + prEvent = (struct WIFI_EVENT *) + (prSwRfb->pucRecvBuff + prChipInfo->rxd_size); + prEvent->ucEID = EVENT_ID_CHECK_REORDER_BUBBLE; + prEvent->ucSeqNum = 0; + prEvent->u2PacketLength = + prChipInfo->rxd_size + prChipInfo->event_hdr_size + + sizeof(struct EVENT_CHECK_REORDER_BUBBLE); + + prCheckReorderEvent = (struct EVENT_CHECK_REORDER_BUBBLE *) + prEvent->aucBuffer; + prCheckReorderEvent->ucStaRecIdx = + prReorderQueParm->ucStaRecIdx; + prCheckReorderEvent->ucTid = prReorderQueParm->ucTid; + + prSwRfb->ucPacketType = RX_PKT_TYPE_SW_DEFINED; + prSwRfb->prRxStatus->u2PktTYpe = RXM_RXD_PKT_TYPE_SW_EVENT; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_INSERT_TAIL(&prAdapter->rRxCtrl.rReceivedRfbList, + &prSwRfb->rQueEntry); + RX_INC_CNT(&prAdapter->rRxCtrl, RX_MPDU_TOTAL_COUNT); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + DBGLOG(QM, LOUD, + "QM:(Bub Check Event Sent) STA[%u] TID[%u]\n", + prReorderQueParm->ucStaRecIdx, + prReorderQueParm->ucTid); + + nicRxProcessRFBs(prAdapter); + + DBGLOG(QM, LOUD, + "QM:(Bub Check Event Handled) STA[%u] TID[%u]\n", + prReorderQueParm->ucStaRecIdx, + prReorderQueParm->ucTid); + } else { + DBGLOG(QM, TRACE, + "QM:(Bub Check Cancel) STA[%u] TID[%u], Bub check event alloc failed\n", + prReorderQueParm->ucStaRecIdx, + prReorderQueParm->ucTid); + + cnmTimerStartTimer(prAdapter, + &(prReorderQueParm->rReorderBubbleTimer), + prAdapter->u4QmRxBaMissTimeout); + + DBGLOG(QM, TRACE, + "QM:(Bub Timer Restart) STA[%u] TID[%u] BubSN[%u] Win{%d, %d}\n", + prReorderQueParm->ucStaRecIdx, + prReorderQueParm->ucTid, + prReorderQueParm->u2FirstBubbleSn, + prReorderQueParm->u2WinStart, + prReorderQueParm->u2WinEnd); + } + +} + +void qmHandleEventCheckReorderBubble(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct EVENT_CHECK_REORDER_BUBBLE *prCheckReorderEvent; + struct RX_BA_ENTRY *prReorderQueParm; + struct QUE *prReorderQue; + struct QUE rReturnedQue; + struct QUE *prReturnedQue = &rReturnedQue; + struct SW_RFB *prReorderedSwRfb, *prSwRfb; + OS_SYSTIME *prMissTimeout; + + prCheckReorderEvent = (struct EVENT_CHECK_REORDER_BUBBLE *) + (prEvent->aucBuffer); + + QUEUE_INITIALIZE(prReturnedQue); + + /* Get target Rx BA entry */ + prReorderQueParm = qmLookupRxBaEntry(prAdapter, + prCheckReorderEvent->ucStaRecIdx, + prCheckReorderEvent->ucTid); + + /* Sanity Check */ + if (!prReorderQueParm) { + DBGLOG(QM, TRACE, + "QM:(Bub Check Cancel) STA[%u] TID[%u], No Rx BA entry\n", + prCheckReorderEvent->ucStaRecIdx, + prCheckReorderEvent->ucTid); + return; + } + + if (!prReorderQueParm->fgIsValid) { + DBGLOG(QM, TRACE, + "QM:(Bub Check Cancel) STA[%u] TID[%u], No Rx BA entry\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + return; + } + + if (!prReorderQueParm->fgHasBubble) { + DBGLOG(QM, TRACE, + "QM:(Bub Check Cancel) STA[%u] TID[%u], Bubble has been filled\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + return; + } + + prReorderQue = &(prReorderQueParm->rReOrderQue); + + RX_DIRECT_REORDER_LOCK(prAdapter, 0); + + if (QUEUE_IS_EMPTY(prReorderQue)) { + prReorderQueParm->fgHasBubble = FALSE; + + DBGLOG(QM, TRACE, + "QM:(Bub Check Cancel) STA[%u] TID[%u], Bubble has been filled\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + + RX_DIRECT_REORDER_UNLOCK(prAdapter, 0); + return; + } + + DBGLOG(QM, TRACE, + "QM:(Bub Check Event Got) STA[%u] TID[%u]\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + + /* Expected bubble timeout => pop out packets before win_end */ + if (prReorderQueParm->u2FirstBubbleSn == + prReorderQueParm->u2WinStart) { + + prReorderedSwRfb = (struct SW_RFB *) QUEUE_GET_TAIL( + prReorderQue); + + prReorderQueParm->u2WinStart = prReorderedSwRfb->u2SSN + 1; + if (prReorderQueParm->u2WinStart >= MAX_SEQ_NO_COUNT) + prReorderQueParm->u2WinStart %= MAX_SEQ_NO_COUNT; + prReorderQueParm->u2WinEnd = + ((prReorderQueParm->u2WinStart) + + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT; +#if CFG_SUPPORT_RX_AMSDU + prReorderQueParm->u8LastAmsduSubIdx = + RX_PAYLOAD_FORMAT_MSDU; +#endif + qmPopOutDueToFallAhead(prAdapter, prReorderQueParm, + prReturnedQue); + + DBGLOG(QM, TRACE, + "QM:(Bub Flush) STA[%u] TID[%u] BubSN[%u] Win{%u, %u}\n", + prReorderQueParm->ucStaRecIdx, + prReorderQueParm->ucTid, + prReorderQueParm->u2FirstBubbleSn, + prReorderQueParm->u2WinStart, + prReorderQueParm->u2WinEnd); + + prReorderQueParm->fgHasBubble = FALSE; + RX_DIRECT_REORDER_UNLOCK(prAdapter, 0); + + /* process prReturnedQue after unlock prReturnedQue */ + if (QUEUE_IS_NOT_EMPTY(prReturnedQue)) { + QM_TX_SET_NEXT_MSDU_INFO( + (struct SW_RFB *) QUEUE_GET_TAIL( + prReturnedQue), NULL); + + prSwRfb = (struct SW_RFB *) + QUEUE_GET_HEAD(prReturnedQue); + while (prSwRfb) { + DBGLOG(QM, TRACE, + "QM:(Bub Flush) STA[%u] TID[%u] Pop Out SN[%u]\n", + prReorderQueParm->ucStaRecIdx, + prReorderQueParm->ucTid, + prSwRfb->u2SSN); + + prSwRfb = (struct SW_RFB *) + QUEUE_GET_NEXT_ENTRY( + (struct QUE_ENTRY *) prSwRfb); + } + + wlanProcessQueuedSwRfb(prAdapter, + (struct SW_RFB *) + QUEUE_GET_HEAD(prReturnedQue)); + } else { + DBGLOG(QM, TRACE, + "QM:(Bub Flush) STA[%u] TID[%u] Pop Out 0 packet\n", + prReorderQueParm->ucStaRecIdx, + prReorderQueParm->ucTid); + } + } + /* First bubble has been filled but others exist */ + else { + prReorderQueParm->u2FirstBubbleSn = + prReorderQueParm->u2WinStart; + + DBGLOG(QM, TRACE, + "QM:(Bub Timer) STA[%u] TID[%u] BubSN[%u] Win{%u, %u}\n", + prReorderQueParm->ucStaRecIdx, + prReorderQueParm->ucTid, + prReorderQueParm->u2FirstBubbleSn, + prReorderQueParm->u2WinStart, + prReorderQueParm->u2WinEnd); + RX_DIRECT_REORDER_UNLOCK(prAdapter, 0); + + cnmTimerStartTimer(prAdapter, + &(prReorderQueParm->rReorderBubbleTimer), + prAdapter->u4QmRxBaMissTimeout); + } + + prMissTimeout = &g_arMissTimeout[ + prReorderQueParm->ucStaRecIdx][prReorderQueParm->ucTid]; + if (QUEUE_IS_EMPTY(prReorderQue)) { + DBGLOG(QM, TRACE, + "QM:(Bub Check) Reset prMissTimeout to zero\n"); + *prMissTimeout = 0; + } else { + DBGLOG(QM, TRACE, + "QM:(Bub Check) Reset prMissTimeout to current time\n"); + GET_CURRENT_SYSTIME(prMissTimeout); + } +} + +u_int8_t qmCompareSnIsLessThan(IN uint32_t u4SnLess, IN uint32_t u4SnGreater) +{ + /* 0 <---> SnLess <--(gap>2048)--> SnGreater : SnLess > SnGreater */ + if ((u4SnLess + HALF_SEQ_NO_COUNT) <= u4SnGreater) + 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 struct MAILBOX_MSG prMailboxRxMsg) +{ + /* DbgPrint("QM: Enter qmHandleMailboxRxMessage()\n"); */ + /* TODO */ +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Handle ADD TX BA Event from the FW + * + * \param[in] prAdapter Adapter pointer + * \param[in] prEvent The event packet from the FW + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void qmHandleEventTxAddBa(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct mt66xx_chip_info *prChipInfo; + struct EVENT_TX_ADDBA *prEventTxAddBa; + struct STA_RECORD *prStaRec; + uint8_t ucStaRecIdx; + uint8_t ucTid; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + DBGLOG(QM, INFO, "QM:Event +TxBa\n"); + + if (!prChipInfo->is_support_hw_amsdu && + prChipInfo->ucMaxSwAmsduNum <= 1) { + DBGLOG(QM, INFO, "QM:Event +TxBa but chip is not support\n"); + return; + } + + prEventTxAddBa = (struct EVENT_TX_ADDBA *) (prEvent->aucBuffer); + ucStaRecIdx = prEventTxAddBa->ucStaRecIdx; + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, ucStaRecIdx); + if (!prStaRec) { + /* Invalid STA_REC index, discard the event packet */ + /* ASSERT(0); */ + DBGLOG(QM, INFO, + "QM: (Warning) TX ADDBA Event for a NULL STA_REC\n"); + return; + } + + for (ucTid = 0; ucTid < TX_DESC_TID_NUM; ucTid++) { + uint8_t ucStaEn = prStaRec->ucAmsduEnBitmap & BIT(ucTid); + uint8_t ucEvtEn = prEventTxAddBa->ucAmsduEnBitmap & BIT(ucTid); + + if (prChipInfo->is_support_hw_amsdu && ucStaEn != ucEvtEn) + nicTxSetHwAmsduDescTemplate(prAdapter, prStaRec, ucTid, + ucEvtEn >> ucTid); + } + + prStaRec->ucAmsduEnBitmap = prEventTxAddBa->ucAmsduEnBitmap; + prStaRec->ucMaxMpduCount = prEventTxAddBa->ucMaxMpduCount; + prStaRec->u4MaxMpduLen = prEventTxAddBa->u4MaxMpduLen; + prStaRec->u4MinMpduLen = prEventTxAddBa->u4MinMpduLen; + + DBGLOG(QM, INFO, + "QM:Event +TxBa bitmap[0x%x] count[%u] MaxLen[%u] MinLen[%u]\n", + prStaRec->ucAmsduEnBitmap, prStaRec->ucMaxMpduCount, + prStaRec->u4MaxMpduLen, prStaRec->u4MinMpduLen); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct EVENT_RX_ADDBA *prEventRxAddBa; + struct STA_RECORD *prStaRec; + uint32_t u4Tid; + uint32_t u4WinSize; + + DBGLOG(QM, INFO, "QM:Event +RxBa\n"); + + prEventRxAddBa = (struct EVENT_RX_ADDBA *) ( + prEvent->aucBuffer); + 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, + (uint8_t) u4Tid, + (prEventRxAddBa->u2BAStartSeqCtrl >> + OFFSET_BAR_SSC_SN), + (uint16_t) 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 struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct EVENT_RX_DELBA *prEventRxDelBa; + struct STA_RECORD *prStaRec; + + /* DbgPrint("QM:Event -RxBa\n"); */ + + prEventRxDelBa = (struct EVENT_RX_DELBA *) ( + prEvent->aucBuffer); + 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); + +} + +struct RX_BA_ENTRY *qmLookupRxBaEntry(IN struct ADAPTER *prAdapter, + uint8_t ucStaRecIdx, uint8_t ucTid) +{ + int i; + struct QUE_MGT *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; +} + +u_int8_t qmAddRxBaEntry(IN struct ADAPTER *prAdapter, + IN uint8_t ucStaRecIdx, IN uint8_t ucTid, + IN uint16_t u2WinStart, IN uint16_t u2WinSize) +{ + int i; + struct RX_BA_ENTRY *prRxBaEntry = NULL; + struct STA_RECORD *prStaRec; + struct QUE_MGT *prQM = &prAdapter->rQM; + + ASSERT(ucStaRecIdx < CFG_STA_REC_NUM); + + if (ucStaRecIdx >= CFG_STA_REC_NUM) { + /* 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); + + /* 4 <1> Delete before adding */ + /* Remove the BA entry for the same (STA, TID) tuple if it exists */ + /* prQM->ucRxBaCount-- */ + if (qmLookupRxBaEntry(prAdapter, ucStaRecIdx, ucTid)) + qmDelRxBaEntry(prAdapter, ucStaRecIdx, ucTid, TRUE); + /* 4 <2> Add a new BA entry */ + /* No available entry to store the BA agreement info. Retrun FALSE. */ + if (prQM->ucRxBaCount >= CFG_NUM_OF_RX_BA_AGREEMENTS) { + DBGLOG(QM, ERROR, + "QM: **failure** (limited resource, ucRxBaCount=%d)\n", + prQM->ucRxBaCount); + return FALSE; + } + /* Find the free-to-use BA entry */ + for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) { + if (!prQM->arRxBaTable[i].fgIsValid) { + prRxBaEntry = &(prQM->arRxBaTable[i]); + prQM->ucRxBaCount++; + DBGLOG(QM, LOUD, + "QM: ucRxBaCount=%d\n", prQM->ucRxBaCount); + break; + } + } + + /* If a free-to-use entry is found, + * configure it and associate it with the STA_REC + */ + u2WinSize += CFG_RX_BA_INC_SIZE; + if (prRxBaEntry) { + prRxBaEntry->ucStaRecIdx = ucStaRecIdx; + prRxBaEntry->ucTid = ucTid; + prRxBaEntry->u2WinStart = u2WinStart; + prRxBaEntry->u2WinSize = u2WinSize; + prRxBaEntry->u2WinEnd = ((u2WinStart + u2WinSize - 1) % + MAX_SEQ_NO_COUNT); +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + prRxBaEntry->u8LastAmsduSubIdx = RX_PAYLOAD_FORMAT_MSDU; + prRxBaEntry->fgAmsduNeedLastFrame = FALSE; + prRxBaEntry->fgIsAmsduDuplicated = FALSE; +#endif + prRxBaEntry->fgIsValid = TRUE; + prRxBaEntry->fgIsWaitingForPktWithSsn = TRUE; + prRxBaEntry->fgHasBubble = FALSE; + + g_arMissTimeout[ucStaRecIdx][ucTid] = 0; + + DBGLOG(QM, INFO, + "QM: +RxBA(STA=%u TID=%u WinStart=%u WinEnd=%u WinSize=%u)\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 struct ADAPTER *prAdapter, + IN uint8_t ucStaRecIdx, IN uint8_t ucTid, + IN u_int8_t fgFlushToHost) +{ + struct RX_BA_ENTRY *prRxBaEntry; + struct STA_RECORD *prStaRec; + struct SW_RFB *prFlushedPacketList = NULL; + struct QUE_MGT *prQM = &prAdapter->rQM; + + ASSERT(ucStaRecIdx < CFG_STA_REC_NUM); + + prStaRec = &prAdapter->arStaRec[ucStaRecIdx]; + ASSERT(prStaRec); + +#if 0 + if (!(prStaRec->fgIsValid)) { + DbgPrint("QM: (WARNING) Invalid STA when deleting an RX BA\n"); + return; + } +#endif + + if (ucTid >= CFG_RX_MAX_BA_TID_NUM) { + DBGLOG(QM, WARN, "QM: ucTid invalid: %d in %s)\n", + ucTid, __func__); + return; + } + + /* 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 { + + struct SW_RFB *prSwRfb; + struct SW_RFB *prNextSwRfb; + + prSwRfb = prFlushedPacketList; + + do { + prNextSwRfb = (struct SW_RFB *) + QUEUE_GET_NEXT_ENTRY( + (struct QUE_ENTRY *) prSwRfb); + nicRxReturnRFB(prAdapter, prSwRfb); + prSwRfb = prNextSwRfb; + } while (prSwRfb); + + } + + } + + if (prRxBaEntry->fgHasBubble) { + DBGLOG(QM, TRACE, + "QM:(Bub Check Cancel) STA[%u] TID[%u], DELBA\n", + prRxBaEntry->ucStaRecIdx, prRxBaEntry->ucTid); + + cnmTimerStopTimer(prAdapter, + &prRxBaEntry->rReorderBubbleTimer); + prRxBaEntry->fgHasBubble = FALSE; + } +#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 + { + struct RX_CTRL *prRxCtrl; + + prRxCtrl = &prAdapter->rRxCtrl; + DBGLOG(QM, TRACE, + "QM: (RX DEBUG) Enqueued: %d / Dequeued: %d\n", + prRxCtrl->u4QueuedCnt, prRxCtrl->u4DequeuedCnt); + } +#endif +} + +void mqmParseAssocReqWmmIe(IN struct ADAPTER *prAdapter, + IN uint8_t *pucIE, IN struct STA_RECORD *prStaRec) +{ + struct IE_WMM_INFO *prIeWmmInfo; + uint8_t ucQosInfo; + uint8_t ucQosInfoAC; + uint8_t ucBmpAC; + uint8_t aucWfaOui[] = VENDOR_OUI_WFA; + + if ((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) + && (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) { + + switch (WMM_IE_OUI_SUBTYPE(pucIE)) { + case VENDOR_OUI_SUBTYPE_WMM_INFO: + if (IE_LEN(pucIE) != 7) + break; /* WMM Info IE with a wrong length */ + + prStaRec->fgIsQoS = TRUE; + prStaRec->fgIsWmmSupported = TRUE; + + prIeWmmInfo = (struct IE_WMM_INFO *) pucIE; + ucQosInfo = prIeWmmInfo->ucQosInfo; + ucQosInfoAC = ucQosInfo & BITS(0, 3); + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucUapsd)) + prStaRec->fgIsUapsdSupported = + (ucQosInfoAC) ? TRUE : FALSE; + else + prStaRec->fgIsUapsdSupported = FALSE; + + 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; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, IN uint8_t *pucIE, + IN uint16_t u2IELength) +{ + struct STA_RECORD *prStaRec; + uint16_t u2Offset; + uint8_t *pucIEStart; + uint32_t u4Flags; + + 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 (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS)) + return; + + /* Determine whether QoS is enabled with the association */ + else { + prStaRec->u4Flags = 0; + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_VENDOR: + mqmParseAssocReqWmmIe(prAdapter, + pucIE, prStaRec); + +#if CFG_SUPPORT_MTK_SYNERGY + if (rlmParseCheckMTKOuiIE(prAdapter, + pucIE, &u4Flags)) + prStaRec->u4Flags = u4Flags; +#endif + + break; + + case ELEM_ID_HT_CAP: + /* Some client won't put the WMM IE + * if client is 802.11n + */ + if (IE_LEN(pucIE) == + (sizeof(struct IE_HT_CAP) - 2)) + prStaRec->fgIsQoS = TRUE; + break; + default: + break; + } + } + + DBGLOG(QM, TRACE, + "MQM: Assoc_Req Parsing (QoS Enabled=%d)\n", + prStaRec->fgIsQoS); + + } +} + +void mqmParseAssocRspWmmIe(IN uint8_t *pucIE, + IN struct STA_RECORD *prStaRec) +{ + uint8_t aucWfaOui[] = VENDOR_OUI_WFA; + + if ((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) + && (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) { + struct IE_WMM_PARAM *prWmmParam = (struct IE_WMM_PARAM *) pucIE; + enum ENUM_ACI eAci; + + 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; + prStaRec->fgIsUapsdSupported = + !!(prWmmParam->ucQosInfo & WMM_QOS_INFO_UAPSD); + for (eAci = ACI_BE; eAci < ACI_NUM; eAci++) + prStaRec->afgAcmRequired[eAci] = !!( + prWmmParam->arAcParam[eAci].ucAciAifsn & + WMM_ACIAIFSN_ACM); + DBGLOG(WMM, INFO, + "WMM: " MACSTR "ACM BK=%d BE=%d VI=%d VO=%d\n", + MAC2STR(prStaRec->aucMacAddr), + prStaRec->afgAcmRequired[ACI_BK], + prStaRec->afgAcmRequired[ACI_BE], + prStaRec->afgAcmRequired[ACI_VI], + prStaRec->afgAcmRequired[ACI_VO]); + 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; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, IN uint8_t *pucIE, + IN uint16_t u2IELength) +{ + struct STA_RECORD *prStaRec; + uint16_t u2Offset; + uint8_t *pucIEStart; + uint32_t u4Flags; +#if DSCP_SUPPORT + u_int8_t hasnoQosMapSetIE = TRUE; +#endif + + 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.ucQoS); + + /* If the device does not support QoS + * or if WMM is not supported by the peer, exit. + */ + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS)) + return; + + /* Determine whether QoS is enabled with the association */ + else { + prStaRec->u4Flags = 0; + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_VENDOR: + /* Process WMM related IE */ + mqmParseAssocRspWmmIe(pucIE, prStaRec); + +#if CFG_SUPPORT_MTK_SYNERGY + if (rlmParseCheckMTKOuiIE(prAdapter, + pucIE, &u4Flags)) + prStaRec->u4Flags = u4Flags; +#endif + + break; + + case ELEM_ID_HT_CAP: + /* Some AP won't put the WMM IE + * if client is 802.11n + */ + if (IE_LEN(pucIE) == + (sizeof(struct IE_HT_CAP) - 2)) + prStaRec->fgIsQoS = TRUE; + break; +#if DSCP_SUPPORT + case ELEM_ID_QOS_MAP_SET: + DBGLOG(QM, WARN, + "QM: received assoc resp qosmapset ie\n"); + prStaRec->qosMapSet = + qosParseQosMapSet(prAdapter, pucIE); + hasnoQosMapSetIE = FALSE; + break; +#endif + default: + break; + } + } +#if DSCP_SUPPORT + if (hasnoQosMapSetIE) { + DBGLOG(QM, WARN, + "QM: remove assoc resp qosmapset ie\n"); + QosMapSetRelease(prStaRec); + prStaRec->qosMapSet = NULL; + } +#endif + /* Parse AC parameters and write to HW CRs */ + if ((prStaRec->fgIsQoS) + && (prStaRec->eStaType == STA_TYPE_LEGACY_AP)) { + mqmParseEdcaParameters(prAdapter, prSwRfb, pucIEStart, + u2IELength, TRUE); +#if ARP_MONITER_ENABLE + qmResetArpDetect(); +#endif + } + DBGLOG(QM, TRACE, + "MQM: Assoc_Rsp Parsing (QoS Enabled=%d)\n", + prStaRec->fgIsQoS); + if (prStaRec->fgIsWmmSupported) + nicQmUpdateWmmParms(prAdapter, prStaRec->ucBssIndex); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void mqmProcessBcn(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, IN uint8_t *pucIE, + IN uint16_t u2IELength) +{ + struct BSS_INFO *prBssInfo; + u_int8_t fgNewParameter; + uint8_t i; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + ASSERT(pucIE); + + DBGLOG(QM, TRACE, "Enter %s\n", __func__); + + fgNewParameter = FALSE; + + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, i); + + 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, + ((struct WLAN_MAC_MGMT_HEADER *) + (prSwRfb->pvHeader))->aucBSSID)) { + + fgNewParameter = + mqmParseEdcaParameters( + prAdapter, + prSwRfb, pucIE, + u2IELength, FALSE); + } + } + + /* Appy new parameters if necessary */ + if (fgNewParameter) { + nicQmUpdateWmmParms(prAdapter, + prBssInfo->ucBssIndex); + fgNewParameter = FALSE; + } + } /* end of IS_BSS_ACTIVE() */ + } +} + +u_int8_t mqmUpdateEdcaParameters(IN struct BSS_INFO *prBssInfo, + IN uint8_t *pucIE, IN u_int8_t fgForceOverride) +{ + struct AC_QUE_PARMS *prAcQueParams; + struct IE_WMM_PARAM *prIeWmmParam; + enum ENUM_WMM_ACI eAci; + u_int8_t fgNewParameter = FALSE; + + do { + if (IE_LEN(pucIE) != 24) + break; /* WMM Param IE with a wrong length */ + + prIeWmmParam = (struct IE_WMM_PARAM *) pucIE; + + /* Check the Parameter Set Count to determine + * whether EDCA parameters have been changed + */ + if (!fgForceOverride) { + if (mqmCompareEdcaParameters(prIeWmmParam, prBssInfo)) { + fgNewParameter = FALSE; + break; + } + } + + fgNewParameter = TRUE; + /* Update Parameter Set Count */ + prBssInfo->ucWmmParamSetCount = (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); + log_dbg(QM, INFO, "BSS[%u]: eAci[%d] ACM[%d] Aifsn[%d] CWmin/max[%d/%d] TxopLimit[%d] NewParameter[%d]\n", + prBssInfo->ucBssIndex, eAci, + prAcQueParams->ucIsACMSet, + prAcQueParams->u2Aifsn, prAcQueParams->u2CWmin, + prAcQueParams->u2CWmax, + prAcQueParams->u2TxopLimit, fgNewParameter); + } + } while (FALSE); + + return fgNewParameter; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t +mqmParseEdcaParameters(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, IN uint8_t *pucIE, + IN uint16_t u2IELength, IN u_int8_t fgForceOverride) +{ + struct STA_RECORD *prStaRec; + uint16_t u2Offset; + uint8_t aucWfaOui[] = VENDOR_OUI_WFA; + struct BSS_INFO *prBssInfo; + u_int8_t fgNewParameter = FALSE; + + DEBUGFUNC("mqmParseEdcaParameters"); + + if (!prSwRfb) + return FALSE; + + if (!pucIE) + return FALSE; + + prStaRec = cnmGetStaRecByIndex(prAdapter, + prSwRfb->ucStaRecIdx); + /* ASSERT(prStaRec); */ + + if (prStaRec == NULL) + return FALSE; + + DBGLOG(QM, TRACE, "QM: (fgIsWmmSupported=%d, fgIsQoS=%d)\n", + prStaRec->fgIsWmmSupported, prStaRec->fgIsQoS); + + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS) + || (!prStaRec->fgIsWmmSupported) + || (!prStaRec->fgIsQoS)) + return FALSE; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + /* Goal: Obtain the EDCA parameters */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_WMM: + if (!((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) && + (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3)))) + break; + + switch (WMM_IE_OUI_SUBTYPE(pucIE)) { + case VENDOR_OUI_SUBTYPE_WMM_PARAM: + fgNewParameter = + mqmUpdateEdcaParameters(prBssInfo, + pucIE, fgForceOverride); + break; + + default: + /* Other WMM QoS IEs. Ignore */ + break; + } + + /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS, ... + * (not cared) + */ + break; + default: + break; + } + } + + return fgNewParameter; +} + +u_int8_t mqmCompareEdcaParameters(IN struct IE_WMM_PARAM *prIeWmmParam, + IN struct BSS_INFO *prBssInfo) +{ + struct AC_QUE_PARMS *prAcQueParams; + struct WMM_AC_PARAM *prWmmAcParams; + enum ENUM_WMM_ACI eAci; + + /* return FALSE; */ + + /* Check Set Count */ + if (prBssInfo->ucWmmParamSetCount != + (prIeWmmParam->ucQosInfo & WMM_QOS_INFO_PARAM_SET_CNT)) + return FALSE; + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prAcQueParams = &prBssInfo->arACQueParms[eAci]; + prWmmAcParams = &prIeWmmParam->arAcParam[eAci]; + + /* ACM */ + if (prAcQueParams->ucIsACMSet != ((prWmmAcParams->ucAciAifsn & + WMM_ACIAIFSN_ACM) ? TRUE : FALSE)) + return FALSE; + + /* AIFSN */ + if (prAcQueParams->u2Aifsn != (prWmmAcParams->ucAciAifsn & + WMM_ACIAIFSN_AIFSN)) + return FALSE; + + /* CW Max */ + if (prAcQueParams->u2CWmax != + (BIT((prWmmAcParams->ucEcw & WMM_ECW_WMAX_MASK) >> + WMM_ECW_WMAX_OFFSET) - 1)) + return FALSE; + + /* CW Min */ + if (prAcQueParams->u2CWmin != (BIT(prWmmAcParams->ucEcw & + WMM_ECW_WMIN_MASK) - 1)) + return FALSE; + + if (prAcQueParams->u2TxopLimit != + prWmmAcParams->u2TxopLimit) + return FALSE; + } + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct IE_WMM_PARAM *prIeWmmParam, + IN uint32_t u4AcOffset, + OUT struct AC_QUE_PARMS *prAcQueParams) +{ + struct WMM_AC_PARAM *prAcParam = + &prIeWmmParam->arAcParam[u4AcOffset]; + + prAcQueParams->ucIsACMSet = (prAcParam->ucAciAifsn & + WMM_ACIAIFSN_ACM) ? TRUE : FALSE; + + prAcQueParams->u2Aifsn = (prAcParam->ucAciAifsn & + WMM_ACIAIFSN_AIFSN); + + prAcQueParams->u2CWmax = BIT((prAcParam->ucEcw & + WMM_ECW_WMAX_MASK) >> WMM_ECW_WMAX_OFFSET) - 1; + + prAcQueParams->u2CWmin = BIT(prAcParam->ucEcw & + WMM_ECW_WMIN_MASK) - 1; + + WLAN_GET_FIELD_16(&prAcParam->u2TxopLimit, + &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 struct ADAPTER *prAdapter, + IN struct BSS_DESC *prScanResult, + OUT struct STA_RECORD *prStaRec) +{ + uint8_t *pucIE; + uint16_t u2IELength; + uint16_t u2Offset; + uint8_t aucWfaOui[] = VENDOR_OUI_WFA; + u_int8_t fgIsHtVht; + + DEBUGFUNC("mqmProcessScanResult"); + + ASSERT(prScanResult); + ASSERT(prStaRec); + + /* Reset the flag before parsing */ + prStaRec->fgIsWmmSupported = FALSE; + prStaRec->fgIsUapsdSupported = FALSE; + prStaRec->fgIsQoS = FALSE; + + fgIsHtVht = FALSE; + + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS)) + return; + + u2IELength = prScanResult->u2IELength; + pucIE = prScanResult->aucIEBuf; + + /* <1> Determine whether the peer supports WMM/QoS and UAPSDU */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + + case ELEM_ID_EXTENDED_CAP: +#if CFG_SUPPORT_TDLS + TdlsBssExtCapParse(prStaRec, pucIE); +#endif /* CFG_SUPPORT_TDLS */ +#if CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT + prStaRec->fgSupportBTM = + !!((*(uint32_t *)(pucIE + 2)) & + BIT(ELEM_EXT_CAP_BSS_TRANSITION_BIT)); +#endif + break; + + case ELEM_ID_WMM: + if ((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) && + (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) { + struct IE_WMM_PARAM *prWmmParam = + (struct IE_WMM_PARAM *)pucIE; + enum ENUM_ACI eAci; + + switch (WMM_IE_OUI_SUBTYPE(pucIE)) { + case VENDOR_OUI_SUBTYPE_WMM_PARAM: + /* WMM Param IE with a wrong length */ + if (IE_LEN(pucIE) != 24) + break; + prStaRec->fgIsWmmSupported = TRUE; + prStaRec->fgIsUapsdSupported = + !!(prWmmParam->ucQosInfo & + WMM_QOS_INFO_UAPSD); + for (eAci = ACI_BE; eAci < ACI_NUM; + eAci++) + prStaRec->afgAcmRequired + [eAci] = !!( + prWmmParam + ->arAcParam + [eAci] + .ucAciAifsn & + WMM_ACIAIFSN_ACM); + DBGLOG(WMM, INFO, + "WMM: " MACSTR + "ACM BK=%d BE=%d VI=%d VO=%d\n", + MAC2STR(prStaRec->aucMacAddr), + prStaRec->afgAcmRequired[ACI_BK], + prStaRec->afgAcmRequired[ACI_BE], + prStaRec->afgAcmRequired[ACI_VI], + prStaRec->afgAcmRequired + [ACI_VO]); + break; + + case VENDOR_OUI_SUBTYPE_WMM_INFO: + /* WMM Info IE with a wrong length */ + if (IE_LEN(pucIE) != 7) + break; + prStaRec->fgIsWmmSupported = TRUE; + prStaRec->fgIsUapsdSupported = + (((( + (struct IE_WMM_INFO *) + pucIE)->ucQosInfo) + & WMM_QOS_INFO_UAPSD) + ? TRUE : FALSE); + break; + + default: + /* A WMM QoS IE that doesn't matter. + * Ignore it. + */ + break; + } + } + break; + + default: + /* A WMM IE that doesn't matter. Ignore it. */ + break; + } + } + + /* <1> Determine QoS */ + if (prStaRec->ucDesiredPhyTypeSet & (PHY_TYPE_SET_802_11N | + PHY_TYPE_SET_802_11AC)) + fgIsHtVht = TRUE; + + if (fgIsHtVht || prStaRec->fgIsWmmSupported) + prStaRec->fgIsQoS = TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Generate the WMM Info IE by Param + * + * \param[in] prAdapter Adapter pointer + * @param prMsduInfo The TX MMPDU + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +uint32_t +mqmFillWmmInfoIE(uint8_t *pucOutBuf, + u_int8_t fgSupportUAPSD, uint8_t ucBmpDeliveryAC, + uint8_t ucBmpTriggerAC, uint8_t ucUapsdSp) +{ + struct IE_WMM_INFO *prIeWmmInfo; + uint32_t ucUapsd[] = { + WMM_QOS_INFO_BE_UAPSD, + WMM_QOS_INFO_BK_UAPSD, + WMM_QOS_INFO_VI_UAPSD, + WMM_QOS_INFO_VO_UAPSD + }; + uint8_t aucWfaOui[] = VENDOR_OUI_WFA; + + ASSERT(pucOutBuf); + + prIeWmmInfo = (struct IE_WMM_INFO *) pucOutBuf; + + prIeWmmInfo->ucId = ELEM_ID_WMM; + prIeWmmInfo->ucLength = ELEM_MAX_LEN_WMM_INFO; + + /* WMM-2.2.1 WMM Information Element Field Values */ + prIeWmmInfo->aucOui[0] = aucWfaOui[0]; + prIeWmmInfo->aucOui[1] = aucWfaOui[1]; + prIeWmmInfo->aucOui[2] = aucWfaOui[2]; + prIeWmmInfo->ucOuiType = VENDOR_OUI_TYPE_WMM; + prIeWmmInfo->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_INFO; + + prIeWmmInfo->ucVersion = VERSION_WMM; + prIeWmmInfo->ucQosInfo = 0; + + /* UAPSD initial queue configurations (delivery and trigger enabled) */ + if (fgSupportUAPSD) { + uint8_t ucQosInfo = 0; + uint8_t i; + + /* Static U-APSD setting */ + for (i = ACI_BE; i <= ACI_VO; i++) { + if (ucBmpDeliveryAC & ucBmpTriggerAC & BIT(i)) + ucQosInfo |= (uint8_t) ucUapsd[i]; + } + + if (ucBmpDeliveryAC & ucBmpTriggerAC) { + switch (ucUapsdSp) { + case WMM_MAX_SP_LENGTH_ALL: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_ALL; + break; + + case WMM_MAX_SP_LENGTH_2: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_2; + break; + + case WMM_MAX_SP_LENGTH_4: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_4; + break; + + case WMM_MAX_SP_LENGTH_6: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_6; + break; + + default: + DBGLOG(QM, 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. + */ + return IE_SIZE(prIeWmmInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Generate the WMM Info IE + * + * \param[in] prAdapter Adapter pointer + * @param prMsduInfo The TX MMPDU + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +uint32_t +mqmGenerateWmmInfoIEByStaRec(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, struct STA_RECORD *prStaRec, + uint8_t *pucOutBuf) +{ + struct PM_PROFILE_SETUP_INFO *prPmProfSetupInfo; + u_int8_t fgSupportUapsd; + + ASSERT(pucOutBuf); + + /* In case QoS is not turned off, exit directly */ + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS)) + return 0; + + if (prStaRec == NULL) + return 0; + + if (!prStaRec->fgIsQoS) + return 0; + + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + + fgSupportUapsd = (IS_FEATURE_ENABLED( + prAdapter->rWifiVar.ucUapsd) && + prStaRec->fgIsUapsdSupported); + + return mqmFillWmmInfoIE(pucOutBuf, + fgSupportUapsd, + prPmProfSetupInfo->ucBmpDeliveryAC, + prPmProfSetupInfo->ucBmpTriggerAC, + prPmProfSetupInfo->ucUapsdSp); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Generate the WMM Info IE + * + * \param[in] prAdapter Adapter pointer + * @param prMsduInfo The TX MMPDU + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void mqmGenerateWmmInfoIE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint32_t u4Length; + + DEBUGFUNC("mqmGenerateWmmInfoIE"); + + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + if (prStaRec == NULL) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + u4Length = mqmGenerateWmmInfoIEByStaRec(prAdapter, + prBssInfo, prStaRec, + ((uint8_t *) prMsduInfo->prPacket + + prMsduInfo->u2FrameLength)); + + prMsduInfo->u2FrameLength += u4Length; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Generate the WMM Param IE + * + * \param[in] prAdapter Adapter pointer + * @param prMsduInfo The TX MMPDU + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void mqmGenerateWmmParamIE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct IE_WMM_PARAM *prIeWmmParam; + + uint8_t aucWfaOui[] = VENDOR_OUI_WFA; + + uint8_t aucACI[] = { + WMM_ACI_AC_BE, + WMM_ACI_AC_BK, + WMM_ACI_AC_VI, + WMM_ACI_AC_VO + }; + + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + enum ENUM_WMM_ACI eAci; + struct WMM_AC_PARAM *prAcParam; + + DEBUGFUNC("mqmGenerateWmmParamIE"); + DBGLOG(QM, LOUD, "\n"); + + ASSERT(prMsduInfo); + + /* In case QoS is not turned off, exit directly */ + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS)) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + + if (prStaRec) { + if (!prStaRec->fgIsQoS) + return; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prMsduInfo->ucBssIndex); + + if (!prBssInfo->fgIsQBSS) + return; + + prIeWmmParam = (struct IE_WMM_PARAM *) + ((uint8_t *) 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 initial queue configurations (delivery and trigger enabled) */ + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucUapsd)) + prIeWmmParam->ucQosInfo |= WMM_QOS_INFO_UAPSD; + + /* EDCA parameter */ + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prAcParam = &prIeWmmParam->arAcParam[eAci]; + + /* ACI */ + prAcParam->ucAciAifsn = aucACI[eAci]; + /* ACM */ + if (prBssInfo->arACQueParmsForBcast[eAci].ucIsACMSet) + prAcParam->ucAciAifsn |= WMM_ACIAIFSN_ACM; + /* AIFSN */ + prAcParam->ucAciAifsn |= + (prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn & + WMM_ACIAIFSN_AIFSN); + + /* ECW Min */ + prAcParam->ucEcw = (prBssInfo->aucCWminLog2ForBcast[eAci] & + WMM_ECW_WMIN_MASK); + /* ECW Max */ + prAcParam->ucEcw |= + ((prBssInfo->aucCWmaxLog2ForBcast[eAci] << + WMM_ECW_WMAX_OFFSET) & WMM_ECW_WMAX_MASK); + + /* Txop limit */ + WLAN_SET_FIELD_16(&prAcParam->u2TxopLimit, + prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit); + + } + + /* Increment the total IE length + * for the Element ID and Length fields. + */ + prMsduInfo->u2FrameLength += IE_SIZE(prIeWmmParam); + +} + +#if CFG_SUPPORT_TDLS +/*----------------------------------------------------------------------------*/ +/*! + * @brief Generate the WMM Param IE + * + * \param[in] prAdapter Adapter pointer + * @param prMsduInfo The TX MMPDU + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +uint32_t mqmGenerateWmmParamIEByParam(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, uint8_t *pOutBuf) +{ + struct IE_WMM_PARAM *prIeWmmParam; + + uint8_t aucWfaOui[] = VENDOR_OUI_WFA; + + uint8_t aucACI[] = { + WMM_ACI_AC_BE, + WMM_ACI_AC_BK, + WMM_ACI_AC_VI, + WMM_ACI_AC_VO + }; + + struct AC_QUE_PARMS *prACQueParms; + /* BE, BK, VO, VI */ + uint8_t auCWminLog2ForBcast[WMM_AC_INDEX_NUM] = {4, 4, 3, 2}; + uint8_t auCWmaxLog2ForBcast[WMM_AC_INDEX_NUM] = {10, 10, 4, 3}; + uint8_t auAifsForBcast[WMM_AC_INDEX_NUM] = {3, 7, 2, 2}; + /* If the AP is OFDM */ + uint8_t auTxopForBcast[WMM_AC_INDEX_NUM] = {0, 0, 94, 47}; + + enum ENUM_WMM_ACI eAci; + struct WMM_AC_PARAM *prAcParam; + + DEBUGFUNC("mqmGenerateWmmParamIE"); + DBGLOG(QM, LOUD, "\n"); + + ASSERT(pOutBuf); + + /* In case QoS is not turned off, exit directly */ + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS)) + return WLAN_STATUS_SUCCESS; + + if (!prBssInfo->fgIsQBSS) + return WLAN_STATUS_SUCCESS; + + if (IS_FEATURE_ENABLED( + prAdapter->rWifiVar.fgTdlsBufferSTASleep)) { + prACQueParms = prBssInfo->arACQueParmsForBcast; + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prACQueParms[eAci].ucIsACMSet = 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]; + + /* used to send WMM IE */ + prBssInfo->aucCWminLog2ForBcast[eAci] = + auCWminLog2ForBcast[eAci]; + prBssInfo->aucCWmaxLog2ForBcast[eAci] = + auCWmaxLog2ForBcast[eAci]; + } + } + + prIeWmmParam = (struct IE_WMM_PARAM *) pOutBuf; + + prIeWmmParam->ucId = ELEM_ID_WMM; + prIeWmmParam->ucLength = ELEM_MAX_LEN_WMM_PARAM; + + /* WMM-2.2.1 WMM Information Element Field Values */ + prIeWmmParam->aucOui[0] = aucWfaOui[0]; + prIeWmmParam->aucOui[1] = aucWfaOui[1]; + prIeWmmParam->aucOui[2] = aucWfaOui[2]; + prIeWmmParam->ucOuiType = VENDOR_OUI_TYPE_WMM; + prIeWmmParam->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_PARAM; + + prIeWmmParam->ucVersion = VERSION_WMM; + /* STAUT Buffer STA, also sleeps (optional) + * The STAUT sends a TDLS Setup/Response/Confirm Frame, + * with all four AC flags set to 1 in QoS Info Field + * to STA 2, via the AP, + */ + if (IS_FEATURE_ENABLED( + prAdapter->rWifiVar.fgTdlsBufferSTASleep)) + prIeWmmParam->ucQosInfo = (0x0F & + WMM_QOS_INFO_PARAM_SET_CNT); + else + prIeWmmParam->ucQosInfo = (prBssInfo->ucWmmParamSetCount & + WMM_QOS_INFO_PARAM_SET_CNT); + + /* UAPSD initial queue configurations (delivery and trigger enabled) */ + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucUapsd)) + prIeWmmParam->ucQosInfo |= WMM_QOS_INFO_UAPSD; + + /* EDCA parameter */ + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prAcParam = &prIeWmmParam->arAcParam[eAci]; + /* ACI */ + prAcParam->ucAciAifsn = aucACI[eAci]; + /* ACM */ + if (prBssInfo->arACQueParmsForBcast[eAci].ucIsACMSet) + prAcParam->ucAciAifsn |= WMM_ACIAIFSN_ACM; + /* AIFSN */ + prAcParam->ucAciAifsn |= + (prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn & + WMM_ACIAIFSN_AIFSN); + + /* ECW Min */ + prAcParam->ucEcw = (prBssInfo->aucCWminLog2ForBcast[eAci] & + WMM_ECW_WMIN_MASK); + /* ECW Max */ + prAcParam->ucEcw |= + ((prBssInfo->aucCWmaxLog2ForBcast[eAci] << + WMM_ECW_WMAX_OFFSET) & WMM_ECW_WMAX_MASK); + + /* Txop limit */ + WLAN_SET_FIELD_16(&prAcParam->u2TxopLimit, + prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit); + + } + + /* Increment the total IE length + * for the Element ID and Length fields. + */ + return IE_SIZE(prIeWmmParam); + +} + +#endif + +u_int8_t isProbeResponse(IN struct MSDU_INFO *prMgmtTxMsdu) +{ + struct WLAN_MAC_HEADER *prWlanHdr = + (struct WLAN_MAC_HEADER *) NULL; + + prWlanHdr = + (struct WLAN_MAC_HEADER *) ((unsigned long) + prMgmtTxMsdu->prPacket + MAC_TX_RESERVED_FIELD); + + return (prWlanHdr->u2FrameCtrl & MASK_FRAME_TYPE) == + MAC_FRAME_PROBE_RSP ? TRUE : FALSE; +} + + +enum ENUM_FRAME_ACTION qmGetFrameAction(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN uint8_t ucStaRecIdx, IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_FRAME_TYPE_IN_CMD_Q eFrameType, + IN uint16_t u2FrameLength) +{ + enum ENUM_FRAME_ACTION eFrameAction = FRAME_ACTION_TX_PKT; + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint8_t ucTC = nicTxGetFrameResourceType(eFrameType, prMsduInfo); + uint16_t u2FreeResource = nicTxGetResource(prAdapter, ucTC); + uint8_t ucReqResource; + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; + + DEBUGFUNC("qmGetFrameAction"); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, ucStaRecIdx); + + do { + /* 4 <1> Tx, if FORCE_TX is set */ + if (prMsduInfo) { + if (prMsduInfo->ucControlFlag & + MSDU_CONTROL_FLAG_FORCE_TX) { + eFrameAction = FRAME_ACTION_TX_PKT; + break; + } + } + /* 4 <2> Drop, if BSS is inactive */ + if (!IS_BSS_ACTIVE(prBssInfo)) { + DBGLOG(QM, TRACE, + "Drop packets (BSS[%u] is INACTIVE)\n", + prBssInfo->ucBssIndex); + eFrameAction = FRAME_ACTION_DROP_PKT; + break; + } + + /* 4 <3> Queue, if BSS is absent, drop probe response */ + if (prBssInfo->fgIsNetAbsent) { + if (prMsduInfo && isProbeResponse(prMsduInfo)) { + DBGLOG(TX, TRACE, + "Drop probe response (BSS[%u] Absent)\n", + prBssInfo->ucBssIndex); + + eFrameAction = FRAME_ACTION_DROP_PKT; + } else { + DBGLOG(TX, TRACE, + "Queue packets (BSS[%u] Absent)\n", + prBssInfo->ucBssIndex); + eFrameAction = FRAME_ACTION_QUEUE_PKT; + } + break; + } + + /* 4 <4> Check based on StaRec */ + if (prStaRec) { + /* 4 <4.1> Drop, if StaRec is not in use */ + if (!prStaRec->fgIsInUse) { + DBGLOG(QM, TRACE, + "Drop packets (Sta[%u] not in USE)\n", + prStaRec->ucIndex); + eFrameAction = FRAME_ACTION_DROP_PKT; + break; + } + /* 4 <4.2> Sta in PS */ + if (prStaRec->fgIsInPS) { + ucReqResource = nicTxGetPageCount(prAdapter, + u2FrameLength, FALSE) + + prWifiVar->ucCmdRsvResource + + QM_MGMT_QUEUED_THRESHOLD; + + /* 4 <4.2.1> Tx, if resource is enough */ + if (u2FreeResource > ucReqResource) { + eFrameAction = FRAME_ACTION_TX_PKT; + break; + } + /* 4 <4.2.2> Queue, if resource is not enough */ + else { + DBGLOG(QM, INFO, + "Queue packets (Sta[%u] in PS)\n", + prStaRec->ucIndex); + eFrameAction = FRAME_ACTION_QUEUE_PKT; + break; + } + } + } + + } while (FALSE); + + /* <5> Resource CHECK! */ + /* <5.1> Reserve resource for CMD & 1X */ + if (eFrameType == FRAME_TYPE_MMPDU) { + ucReqResource = nicTxGetPageCount(prAdapter, u2FrameLength, + FALSE) + prWifiVar->ucCmdRsvResource; + + if (u2FreeResource < ucReqResource) { + eFrameAction = FRAME_ACTION_QUEUE_PKT; + DBGLOG(QM, INFO, + "Queue MGMT (MSDU[0x%p] Req/Rsv/Free[%u/%u/%u])\n", + prMsduInfo, + nicTxGetPageCount(prAdapter, + u2FrameLength, FALSE), + prWifiVar->ucCmdRsvResource, u2FreeResource); + } + + /* <6> Timeout check! */ +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + if ((eFrameAction == FRAME_ACTION_QUEUE_PKT) && prMsduInfo) { + OS_SYSTIME rCurrentTime, rEnqTime; + + GET_CURRENT_SYSTIME(&rCurrentTime); + rEnqTime = prMsduInfo->rPktProfile.rEnqueueTimestamp; + + if (CHECK_FOR_TIMEOUT(rCurrentTime, rEnqTime, + MSEC_TO_SYSTIME( + prWifiVar->u4MgmtQueueDelayTimeout))) { + eFrameAction = FRAME_ACTION_DROP_PKT; + log_dbg(QM, INFO, "Drop MGMT (MSDU[0x%p] timeout[%ums])\n", + prMsduInfo, + prWifiVar->u4MgmtQueueDelayTimeout); + } + } +#endif + } + + return eFrameAction; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct EVENT_BSS_ABSENCE_PRESENCE *prEventBssStatus; + struct BSS_INFO *prBssInfo; + u_int8_t fgIsNetAbsentOld; + + prEventBssStatus = (struct EVENT_BSS_ABSENCE_PRESENCE *) ( + prEvent->aucBuffer); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prEventBssStatus->ucBssIndex); + fgIsNetAbsentOld = prBssInfo->fgIsNetAbsent; + prBssInfo->fgIsNetAbsent = prEventBssStatus->ucIsAbsent; + prBssInfo->ucBssFreeQuota = prEventBssStatus->ucBssFreeQuota; + + DBGLOG(QM, INFO, "NAF=%d,%d,%d\n", + prEventBssStatus->ucBssIndex, prBssInfo->fgIsNetAbsent, + prBssInfo->ucBssFreeQuota); + + if (!prBssInfo->fgIsNetAbsent) { + /* ToDo:: QM_DBG_CNT_INC */ + QM_DBG_CNT_INC(&(prAdapter->rQM), QM_DBG_CNT_27); + } else { + /* ToDo:: QM_DBG_CNT_INC */ + QM_DBG_CNT_INC(&(prAdapter->rQM), QM_DBG_CNT_28); + } + /* From Absent to Present */ + if ((fgIsNetAbsentOld) && (!prBssInfo->fgIsNetAbsent)) { + if (HAL_IS_TX_DIRECT(prAdapter)) + nicTxDirectStartCheckQTimer(prAdapter); + else { +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + prAdapter->rQM.fgForceReassign = TRUE; +#endif + 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 struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct EVENT_STA_CHANGE_PS_MODE *prEventStaChangePsMode; + struct STA_RECORD *prStaRec; + u_int8_t fgIsInPSOld; + + /* DbgPrint("QM:Event -RxBa\n"); */ + + prEventStaChangePsMode = (struct EVENT_STA_CHANGE_PS_MODE *) + (prEvent->aucBuffer); + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, + prEventStaChangePsMode->ucStaRecIdx); + /* ASSERT(prStaRec); */ + + if (prStaRec) { + + fgIsInPSOld = prStaRec->fgIsInPS; + prStaRec->fgIsInPS = prEventStaChangePsMode->ucIsInPs; + + qmUpdateFreeQuota(prAdapter, + prStaRec, + prEventStaChangePsMode->ucUpdateMode, + prEventStaChangePsMode->ucFreeQuota); + + DBGLOG(QM, INFO, "PS=%d,%d\n", + prEventStaChangePsMode->ucStaRecIdx, + prStaRec->fgIsInPS); + + /* From PS to Awake */ + if ((fgIsInPSOld) && (!prStaRec->fgIsInPS)) { + if (HAL_IS_TX_DIRECT(prAdapter)) + nicTxDirectStartCheckQTimer(prAdapter); + else { +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + prAdapter->rQM.fgForceReassign = TRUE; +#endif + 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 struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct EVENT_STA_UPDATE_FREE_QUOTA + *prEventStaUpdateFreeQuota; + struct STA_RECORD *prStaRec; + + prEventStaUpdateFreeQuota = (struct + EVENT_STA_UPDATE_FREE_QUOTA *) (prEvent->aucBuffer); + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, + prEventStaUpdateFreeQuota->ucStaRecIdx); + /* 2013/08/30 + * Station Record possible been freed. + */ + /* ASSERT(prStaRec); */ + + if (prStaRec) { + if (prStaRec->fgIsInPS) { + qmUpdateFreeQuota(prAdapter, + prStaRec, + prEventStaUpdateFreeQuota->ucUpdateMode, + prEventStaUpdateFreeQuota->ucFreeQuota); + + if (HAL_IS_TX_DIRECT(prAdapter)) + nicTxDirectStartCheckQTimer(prAdapter); + else + kalSetEvent(prAdapter->prGlueInfo); + } + 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 struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, IN uint8_t ucUpdateMode, + IN uint8_t ucFreeQuota) +{ + + uint8_t ucFreeQuotaForNonDelivery; + uint8_t 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t qmGetRxReorderQueuedBufferCount(IN struct ADAPTER *prAdapter) +{ + uint32_t i, u4Total; + struct QUE_MGT *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; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Dump current queue status + * + * \param[in] (none) + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +uint32_t qmDumpQueueStatus(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, IN uint32_t u4Max) +{ + struct TX_CTRL *prTxCtrl; + struct QUE_MGT *prQM; + struct GLUE_INFO *prGlueInfo; + uint32_t i, u4TotalBufferCount, u4TotalPageCount; + uint32_t u4CurBufferCount, u4CurPageCount; + uint32_t u4Len = 0; + + DEBUGFUNC(("%s", __func__)); + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + prQM = &prAdapter->rQM; + prGlueInfo = prAdapter->prGlueInfo; + u4TotalBufferCount = 0; + u4TotalPageCount = 0; + u4CurBufferCount = 0; + u4CurPageCount = 0; + + LOGBUF(pucBuf, u4Max, u4Len, "\n"); + LOGBUF(pucBuf, u4Max, u4Len, + "------------\n"); + + for (i = TC0_INDEX; i < TC_NUM; i++) { + LOGBUF(pucBuf, u4Max, u4Len, + "TC%u ResCount: Max[%02u/%03u] Free[%02u/%03u] PreUsed[%03u]\n", + i, prTxCtrl->rTc.au4MaxNumOfBuffer[i], + prTxCtrl->rTc.au4MaxNumOfPage[i], + prTxCtrl->rTc.au4FreeBufferCount[i], + prTxCtrl->rTc.au4FreePageCount[i], + prTxCtrl->rTc.au4PreUsedPageCount[i]); + + u4TotalBufferCount += prTxCtrl->rTc.au4MaxNumOfBuffer[i]; + u4TotalPageCount += prTxCtrl->rTc.au4MaxNumOfPage[i]; + u4CurBufferCount += prTxCtrl->rTc.au4FreeBufferCount[i]; + u4CurPageCount += prTxCtrl->rTc.au4FreePageCount[i]; + } + + LOGBUF(pucBuf, u4Max, u4Len, + "ToT ResCount: Max[%02u/%03u] Free[%02u/%03u]\n", + u4TotalBufferCount, u4TotalPageCount, u4CurBufferCount, + u4CurPageCount); + + u4TotalBufferCount = 0; + u4TotalPageCount = 0; + u4CurBufferCount = 0; + u4CurPageCount = 0; + LOGBUF(pucBuf, u4Max, u4Len, + "------------\n"); + + for (i = TC0_INDEX; i < TC_NUM; i++) { + LOGBUF(pucBuf, u4Max, u4Len, + "TC%u ResCount: Max[%02u/%03u] Free[%02u/%03u] PreUsed[%03u]\n", + i, prTxCtrl->rTc.au4MaxNumOfBuffer_PLE[i], + prTxCtrl->rTc.au4MaxNumOfPage_PLE[i], + prTxCtrl->rTc.au4FreeBufferCount_PLE[i], + prTxCtrl->rTc.au4FreePageCount_PLE[i], + prTxCtrl->rTc.au4PreUsedPageCount[i]); + + u4TotalBufferCount += prTxCtrl->rTc.au4MaxNumOfBuffer_PLE[i]; + u4TotalPageCount += prTxCtrl->rTc.au4MaxNumOfPage_PLE[i]; + u4CurBufferCount += prTxCtrl->rTc.au4FreeBufferCount_PLE[i]; + u4CurPageCount += prTxCtrl->rTc.au4FreePageCount_PLE[i]; + } + + LOGBUF(pucBuf, u4Max, u4Len, + "ToT ResCount: Max[%02u/%03u] Free[%02u/%03u]\n", + u4TotalBufferCount, u4TotalPageCount, u4CurBufferCount, + u4CurPageCount); + + LOGBUF(pucBuf, u4Max, u4Len, + "---------------------------------\n"); +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + for (i = TC0_INDEX; i < TC_NUM; i++) { + LOGBUF(pucBuf, u4Max, u4Len, + "TC%u AvgQLen[%04u] minRsv[%02u] CurTcRes[%02u] GrtdTcRes[%02u]\n", + i, QM_GET_TX_QUEUE_LEN(prAdapter, i), + prQM->au4MinReservedTcResource[i], + prQM->au4CurrentTcResource[i], + prQM->au4GuaranteedTcResource[i]); + } + + LOGBUF(pucBuf, u4Max, u4Len, + "Resource Residual[%u] ExtraRsv[%u]\n", + prQM->u4ResidualTcResource, + prQM->u4ExtraReservedTcResource); + LOGBUF(pucBuf, u4Max, u4Len, + "QueLenMovingAvg[%u] Time2AdjResource[%u] Time2UpdateQLen[%u]\n", + prQM->u4QueLenMovingAverage, prQM->u4TimeToAdjustTcResource, + prQM->u4TimeToUpdateQueLen); +#endif + + DBGLOG(SW4, INFO, "---------------------------------\n"); + +#if QM_FORWARDING_FAIRNESS + for (i = 0; i < NUM_OF_PER_STA_TX_QUEUES; i++) { + LOGBUF(pucBuf, u4Max, u4Len, + "TC%u HeadSta[%u] ResourceUsedCount[%u]\n", + i, prQM->au4HeadStaRecIndex[i], + prQM->au4ResourceUsedCount[i]); + } +#endif + + LOGBUF(pucBuf, u4Max, u4Len, + "BMC or unknown TxQueue Len[%u]\n", + prQM->arTxQueue[0].u4NumElem); + LOGBUF(pucBuf, u4Max, u4Len, + "Pending QLen Normal[%u] Sec[%u] Cmd[%u]\n", + GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum), + GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum), + GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingCmdNum)); + +#if defined(LINUX) + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + LOGBUF(pucBuf, u4Max, u4Len, + "Pending BSS[%u] QLen[%u:%u:%u:%u]\n", i, + prGlueInfo->ai4TxPendingFrameNumPerQueue[i][0], + prGlueInfo->ai4TxPendingFrameNumPerQueue[i][1], + prGlueInfo->ai4TxPendingFrameNumPerQueue[i][2], + prGlueInfo->ai4TxPendingFrameNumPerQueue[i][3]); + } +#endif + LOGBUF(pucBuf, u4Max, u4Len, "Pending FWD CNT[%d]\n", + prTxCtrl->i4PendingFwdFrameCount); + LOGBUF(pucBuf, u4Max, u4Len, "Pending MGMT CNT[%d]\n", + prTxCtrl->i4TxMgmtPendingNum); + + LOGBUF(pucBuf, u4Max, u4Len, + "---------------------------------\n"); + + LOGBUF(pucBuf, u4Max, u4Len, "Total RFB[%u]\n", + CFG_RX_MAX_PKT_NUM); + LOGBUF(pucBuf, u4Max, u4Len, "rFreeSwRfbList[%u]\n", + prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem); + LOGBUF(pucBuf, u4Max, u4Len, "rReceivedRfbList[%u]\n", + prAdapter->rRxCtrl.rReceivedRfbList.u4NumElem); + LOGBUF(pucBuf, u4Max, u4Len, "rIndicatedRfbList[%u]\n", + prAdapter->rRxCtrl.rIndicatedRfbList.u4NumElem); + LOGBUF(pucBuf, u4Max, u4Len, "ucNumIndPacket[%u]\n", + prAdapter->rRxCtrl.ucNumIndPacket); + LOGBUF(pucBuf, u4Max, u4Len, "ucNumRetainedPacket[%u]\n", + prAdapter->rRxCtrl.ucNumRetainedPacket); + + LOGBUF(pucBuf, u4Max, u4Len, + "---------------------------------\n"); + LOGBUF(pucBuf, u4Max, u4Len, + "CMD: Free[%u/%u] PQ[%u] CQ[%u] TCQ[%u] TCDQ[%u]\n", + prAdapter->rFreeCmdList.u4NumElem, + CFG_TX_MAX_CMD_PKT_NUM, + prAdapter->rPendingCmdQueue.u4NumElem, + prGlueInfo->rCmdQueue.u4NumElem, + prAdapter->rTxCmdQueue.u4NumElem, + prAdapter->rTxCmdDoneQueue.u4NumElem); + LOGBUF(pucBuf, u4Max, u4Len, + "MSDU: Free[%u/%u] Pending[%u] Done[%u]\n", + prAdapter->rTxCtrl.rFreeMsduInfoList.u4NumElem, + CFG_TX_MAX_PKT_NUM, + prAdapter->rTxCtrl.rTxMgmtTxingQueue.u4NumElem, + prAdapter->rTxDataDoneQueue.u4NumElem); + return u4Len; +} + +#if CFG_M0VE_BA_TO_DRIVER +/*----------------------------------------------------------------------------*/ +/*! + * @brief Send DELBA Action frame + * + * @param fgIsInitiator DELBA_ROLE_INITIATOR or DELBA_ROLE_RECIPIENT + * @param prStaRec Pointer to the STA_REC of the receiving peer + * @param u4Tid TID of the BA entry + * @param u4ReasonCode The reason code carried in the Action frame + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void +mqmSendDelBaFrame(IN struct ADAPTER *prAdapter, + IN u_int8_t fgIsInitiator, IN struct STA_RECORD *prStaRec, + IN uint32_t u4Tid, IN uint32_t u4ReasonCode) +{ + + struct MSDU_INFO *prTxMsduInfo; + struct ACTION_DELBA_FRAME *prDelBaFrame; + struct BSS_INFO *prBssInfo; + + DBGLOG(QM, WARN, "[Puff]: Enter mqmSendDelBaFrame()\n"); + + ASSERT(prStaRec); + + /* 3 <1> Block the message in case of invalid STA */ + if (!prStaRec->fgIsInUse) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) sta_rec is not inuse\n", + __func__); + return; + } + /* Check HT-capabale STA */ + if (!(prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_HT)) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) sta is NOT HT-capable(0x%08X)\n", + __func__, + prStaRec->ucDesiredPhyTypeSet); + return; + } + /* 4 <2> Construct the DELBA frame */ + prTxMsduInfo = (struct MSDU_INFO *) cnmMgtPktAlloc( + prAdapter, ACTION_DELBA_FRAME_LEN); + + if (!prTxMsduInfo) { + log_dbg(QM, WARN, "[Puff][%s]: (Warning) DELBA for TID=%ld was not sent (MSDU_INFO alloc failure)\n", + __func__, u4Tid); + return; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + /* Fill the Action frame */ + prDelBaFrame = (struct ACTION_DELBA_FRAME *) + ((uint32_t) (prTxMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + prDelBaFrame->u2FrameCtrl = MAC_FRAME_ACTION; +#if CFG_SUPPORT_802_11W + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) DELBA is 80211w enabled\n", + __func__); + prDelBaFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + } +#endif + + prDelBaFrame->u2DurationID = 0; + prDelBaFrame->ucCategory = CATEGORY_BLOCK_ACK_ACTION; + prDelBaFrame->ucAction = ACTION_DELBA; + + prDelBaFrame->u2DelBaParameterSet = 0; + prDelBaFrame->u2DelBaParameterSet |= ((fgIsInitiator ? + ACTION_DELBA_INITIATOR_MASK : 0)); + prDelBaFrame->u2DelBaParameterSet |= ((u4Tid << + ACTION_DELBA_TID_OFFSET) & ACTION_DELBA_TID_MASK); + prDelBaFrame->u2ReasonCode = u4ReasonCode; + + COPY_MAC_ADDR(prDelBaFrame->aucDestAddr, + prStaRec->aucMacAddr); + COPY_MAC_ADDR(prDelBaFrame->aucSrcAddr, + prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prDelBaFrame->aucBSSID, prBssInfo->aucBSSID); + + /* 4 <3> Configure the MSDU_INFO and forward it to TXM */ + TX_SET_MMPDU(prAdapter, + prTxMsduInfo, + prStaRec->ucBssIndex, + (prStaRec != NULL) ? (prStaRec->ucIndex) : + (STA_REC_INDEX_NOT_FOUND), + WLAN_MAC_HEADER_LEN, ACTION_DELBA_FRAME_LEN, NULL, + MSDU_RATE_MODE_AUTO); + +#if CFG_SUPPORT_802_11W + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(RSN, INFO, "Set MSDU_OPT_PROTECTED_FRAME\n"); + nicTxConfigPktOption(prTxMsduInfo, MSDU_OPT_PROTECTED_FRAME, + TRUE); + } +#endif + + /* TID and fgIsInitiator are needed + * when processing TX Done of the DELBA frame + */ + prTxMsduInfo->ucTID = (uint8_t) u4Tid; + prTxMsduInfo->ucControlFlag = (fgIsInitiator ? 1 : 0); + + nicTxEnqueueMsdu(prAdapter, prTxMsduInfo); + + DBGLOG(QM, WARN, + "[Puff][%s]: Send DELBA for TID=%ld Initiator=%d\n", + __func__, u4Tid, fgIsInitiator); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Callback function for the TX Done event for an ADDBA_RSP + * + * @param prMsduInfo The TX packet + * @param rWlanStatus WLAN_STATUS_SUCCESS if TX is successful + * + * @return WLAN_STATUS_BUFFER_RETAINED is returned if the buffer shall not be + * freed by TXM + */ +/*----------------------------------------------------------------------------*/ +uint32_t +mqmCallbackAddBaRspSent(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + struct RX_BA_ENTRY *prRxBaEntry; + struct STA_RECORD *prStaRec; + struct QUE_MGT *prQM; + + uint32_t u4Tid = 0; + + /* ASSERT(prMsduInfo); */ + prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + prQM = &prAdapter->rQM; + + DBGLOG(QM, WARN, + "[Puff]: Enter mqmCallbackAddBaRspSent()\n"); + + /* 4 <0> Check STA_REC status */ + /* Check STA_REC is inuse */ + if (!prStaRec->fgIsInUse) { + DBGLOG(QM, WARN, "[Puff][%s]: (Warning) sta_rec is not inuse\n", + __func__); + return WLAN_STATUS_SUCCESS; + } + /* Check HT-capabale STA */ + if (!(prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_HT)) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) sta is NOT HT-capable(0x%08X)\n", + __func__, + prStaRec->ucDesiredPhyTypeSet); + /* To free the received ADDBA_REQ directly */ + return WLAN_STATUS_SUCCESS; + } + /* 4 <1> Find the corresponding BA entry */ + /* TID is stored in MSDU_INFO when composing the ADDBA_RSP frame */ + u4Tid = prMsduInfo->ucTID; + prRxBaEntry = &prQM->arRxBaTable[u4Tid]; + + /* Note: Due to some reason, for example, receiving a DELBA, + * the BA entry may not be in state NEGO + */ + /* 4 <2> INVALID state */ + if (!prRxBaEntry) { + log_dbg(QM, WARN, "[Puff][%s]: (RX_BA) ADDBA_RSP ---> peer (STA=%d TID=%d)(TX successful)(invalid BA)\n", + __func__, prStaRec->ucIndex, u4Tid); + } + /* 4 <3> NEGO, ACTIVE, or DELETING state */ + else { + switch (rTxDoneStatus) { + /* 4 TX Success */ + case TX_RESULT_SUCCESS: + + DBGLOG(QM, WARN, + "[Puff][%s]: (RX_BA) ADDBA_RSP ---> peer (STA=%d TID=%d)(TX successful)\n", + __func__, prStaRec->ucIndex, u4Tid); + + /* 4 NEGO or ACTIVE state */ + if (prRxBaEntry->ucStatus != BA_ENTRY_STATUS_DELETING) + mqmRxModifyBaEntryStatus(prAdapter, prRxBaEntry, + BA_ENTRY_STATUS_ACTIVE); + break; + + /* 4 TX Failure */ + default: + + log_dbg(QM, WARN, "[Puff][%s]: (RX_BA) ADDBA_RSP ---> peer (STA=%d TID=%ld Entry_Status=%d)(TX failed)\n", + __func__, prStaRec->ucIndex, + u4Tid, prRxBaEntry->ucStatus); + + /* 4 NEGO or ACTIVE state */ + /* Notify the host to delete the agreement */ + if (prRxBaEntry->ucStatus != BA_ENTRY_STATUS_DELETING) { + mqmRxModifyBaEntryStatus(prAdapter, prRxBaEntry, + BA_ENTRY_STATUS_DELETING); + + /* Send DELBA to the peer to ensure + * the BA state is synchronized + */ + mqmSendDelBaFrame(prAdapter, + DELBA_ROLE_RECIPIENT, + prStaRec, u4Tid, + STATUS_CODE_UNSPECIFIED_FAILURE); + } + break; + } + + } + + return WLAN_STATUS_SUCCESS; /* TXM shall release the packet */ + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Check if there is any idle RX BA + * + * @param u4Param (not used) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void mqmTimeoutCheckIdleRxBa(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr) +{ + int8_t i; + struct RX_BA_ENTRY *prRxBa; + uint32_t u4IdleCountThreshold = 0; + struct STA_RECORD *prStaRec; + struct QUE_MGT *prQM; + + DBGLOG(QM, WARN, + "[Puff]: Enter mqmTimeoutIdleRxBaDetection()\n"); + + prQM = &prAdapter->rQM; + + /* 4 <1> Restart the timer */ + cnmTimerStopTimer(prAdapter, + &prAdapter->rMqmIdleRxBaDetectionTimer); + cnmTimerStartTimer(prAdapter, + &prAdapter->rMqmIdleRxBaDetectionTimer, + MQM_IDLE_RX_BA_CHECK_INTERVAL); + + /* 4 <2> Increment the idle count for each idle BA */ + for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) { + + prRxBa = &prQM->arRxBaTable[i]; + + if (prRxBa->ucStatus == BA_ENTRY_STATUS_ACTIVE) { + + prStaRec = cnmGetStaRecByIndex(prAdapter, + prRxBa->ucStaRecIdx); + + if (!prStaRec->fgIsInUse) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) sta_rec is not inuse\n", + __func__); + ASSERT(0); + } + /* Check HT-capabale STA */ + if (!(prStaRec->ucDesiredPhyTypeSet & + PHY_TYPE_BIT_HT)) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) sta is NOT HT-capable(0x%08X)\n", + __func__, + prStaRec->ucDesiredPhyTypeSet); + ASSERT(0); + } + /* 4 <2.1> Idle detected, increment idle count + * and see if a DELBA should be sent + */ + if (prRxBa->u2SnapShotSN == + prStaRec->au2CachedSeqCtrl[prRxBa->ucTid]) { + + prRxBa->ucIdleCount++; + + ASSERT(prRxBa->ucTid < 8); + switch (aucTid2ACI[prRxBa->ucTid]) { + case 0: /* BK */ + u4IdleCountThreshold = + MQM_DEL_IDLE_RXBA_THRESHOLD_BK; + break; + case 1: /* BE */ + u4IdleCountThreshold = + MQM_DEL_IDLE_RXBA_THRESHOLD_BE; + break; + case 2: /* VI */ + u4IdleCountThreshold = + MQM_DEL_IDLE_RXBA_THRESHOLD_VI; + break; + case 3: /* VO */ + u4IdleCountThreshold = + MQM_DEL_IDLE_RXBA_THRESHOLD_VO; + break; + } + + if (prRxBa->ucIdleCount >= + u4IdleCountThreshold) { + mqmRxModifyBaEntryStatus(prAdapter, + prRxBa, + BA_ENTRY_STATUS_INVALID); + mqmSendDelBaFrame(prAdapter, + DELBA_ROLE_RECIPIENT, prStaRec, + (uint32_t) prRxBa->ucTid, + REASON_CODE_PEER_TIME_OUT); + qmDelRxBaEntry(prAdapter, + prStaRec->ucIndex, + prRxBa->ucTid, TRUE); + } + } + /* 4 <2.2> Activity detected */ + else { + prRxBa->u2SnapShotSN = + prStaRec->au2CachedSeqCtrl[ + prRxBa->ucTid]; + prRxBa->ucIdleCount = 0; + continue; /* check the next BA entry */ + } + } + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Do RX BA entry state transition + * + * @param prRxBaEntry The BA entry pointer + * @param eStatus The state to transition to + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void +mqmRxModifyBaEntryStatus(IN struct ADAPTER *prAdapter, + IN struct RX_BA_ENTRY *prRxBaEntry, + IN enum ENUM_BA_ENTRY_STATUS eStatus) +{ + struct STA_RECORD *prStaRec; + struct QUE_MGT *prQM; + + u_int8_t fgResetScoreBoard = FALSE; + + ASSERT(prRxBaEntry); + + prStaRec = cnmGetStaRecByIndex(prAdapter, + prRxBaEntry->ucStaRecIdx); + ASSERT(prStaRec); + prQM = &prAdapter->rQM; + + if (prRxBaEntry->ucStatus == (uint8_t) eStatus) { + DBGLOG(QM, WARN, "[Puff][%s]: eStatus are identical...\n", + __func__, prRxBaEntry->ucStatus); + return; + } + /* 4 <1> State transition from state X */ + switch (prRxBaEntry->ucStatus) { + + /* 4 <1.1> From (X = INVALID) to (ACTIVE or NEGO or DELETING) */ + case BA_ENTRY_STATUS_INVALID: + + /* Associate the BA entry with the STA_REC + * when leaving INVALID state + */ + kalMemCopy(&prQM->arRxBaTable[prRxBaEntry->ucTid], + prRxBaEntry, sizeof(struct RX_BA_ENTRY)); + + /* Increment the RX BA counter */ + prQM->ucRxBaCount++; + ASSERT(prQM->ucRxBaCount <= CFG_NUM_OF_RX_BA_AGREEMENTS); + + /* Since AMPDU may be received during INVALID state */ + fgResetScoreBoard = TRUE; + + /* Reset Idle Count since this BA entry is being activated now. + * Note: If there is no ACTIVE entry, + * the idle detection timer will not be started. + */ + prRxBaEntry->ucIdleCount = 0; + break; + + /* 4 <1.2> Other cases */ + default: + break; + } + + /* 4 <2> State trasition to state Y */ + switch (eStatus) { + + /* 4 <2.1> From (NEGO, ACTIVE, DELETING) to (Y=INVALID) */ + case BA_ENTRY_STATUS_INVALID: + + /* Disassociate the BA entry with the STA_REC */ + kalMemZero(&prQM->arRxBaTable[prRxBaEntry->ucTid], + sizeof(struct RX_BA_ENTRY)); + + /* Decrement the RX BA counter */ + prQM->ucRxBaCount--; + ASSERT(prQM->ucRxBaCount < CFG_NUM_OF_RX_BA_AGREEMENTS); + + /* (TBC) */ + fgResetScoreBoard = TRUE; + + /* If there is not any BA agreement, + * stop doing idle detection + */ + if (prQM->ucRxBaCount == 0) { + if (MQM_CHECK_FLAG(prAdapter->u4FlagBitmap, + MQM_FLAG_IDLE_RX_BA_TIMER_STARTED)) { + cnmTimerStopTimer(prAdapter, + &prAdapter->rMqmIdleRxBaDetectionTimer); + MQM_CLEAR_FLAG(prAdapter->u4FlagBitmap, + MQM_FLAG_IDLE_RX_BA_TIMER_STARTED); + } + } + + break; + + /* 4 <2.2> From (any) to (Y=ACTIVE) */ + case BA_ENTRY_STATUS_ACTIVE: + + /* If there is at least one BA going into ACTIVE, + * start idle detection + */ + if (!MQM_CHECK_FLAG(prAdapter->u4FlagBitmap, + MQM_FLAG_IDLE_RX_BA_TIMER_STARTED)) { + cnmTimerInitTimer(prAdapter, + &prAdapter->rMqmIdleRxBaDetectionTimer, + (PFN_MGMT_TIMEOUT_FUNC) mqmTimeoutCheckIdleRxBa, + (unsigned long) NULL); + /* No parameter */ + + cnmTimerStopTimer(prAdapter, + &prAdapter->rMqmIdleRxBaDetectionTimer); + +#if MQM_IDLE_RX_BA_DETECTION + cnmTimerStartTimer(prAdapter, + &prAdapter->rMqmIdleRxBaDetectionTimer, + MQM_IDLE_RX_BA_CHECK_INTERVAL); + MQM_SET_FLAG(prAdapter->u4FlagBitmap, + MQM_FLAG_IDLE_RX_BA_TIMER_STARTED); +#endif + } + + break; + + case BA_ENTRY_STATUS_NEGO: + default: + break; + } + + if (fgResetScoreBoard) { + struct CMD_RESET_BA_SCOREBOARD *prCmdBody; + + prCmdBody = (struct CMD_RESET_BA_SCOREBOARD *) + cnmMemAlloc(prAdapter, RAM_TYPE_BUF, + sizeof(struct CMD_RESET_BA_SCOREBOARD)); + ASSERT(prCmdBody); + + prCmdBody->ucflag = MAC_ADDR_TID_MATCH; + prCmdBody->ucTID = prRxBaEntry->ucTid; + kalMemCopy(prCmdBody->aucMacAddr, prStaRec->aucMacAddr, + PARAM_MAC_ADDR_LEN); + + wlanoidResetBAScoreboard(prAdapter, prCmdBody, + sizeof(struct CMD_RESET_BA_SCOREBOARD)); + + cnmMemFree(prAdapter, prCmdBody); + } + + DBGLOG(QM, WARN, + "[Puff]QM: (RX_BA) [STA=%d TID=%d] status from %d to %d\n", + prRxBaEntry->ucStaRecIdx, prRxBaEntry->ucTid, + prRxBaEntry->ucStatus, eStatus); + + prRxBaEntry->ucStatus = (uint8_t) eStatus; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void mqmHandleAddBaReq(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + struct ACTION_ADDBA_REQ_FRAME *prAddBaReq; + struct ACTION_ADDBA_REQ_BODY rAddBaReqBody; + struct ACTION_ADDBA_RSP_FRAME *prAddBaRsp; + struct ACTION_ADDBA_RSP_BODY rAddBaRspBody; + struct RX_BA_ENTRY *prRxBaEntry; + struct MSDU_INFO *prTxMsduInfo; + struct QUE_MGT *prQM; + + /* Reject or accept the ADDBA_REQ */ + u_int8_t fgIsReqAccepted = TRUE; + /* Indicator: Whether a new RX BA entry will be added */ + u_int8_t fgIsNewEntryAdded = FALSE; + + uint32_t u4Tid; + uint32_t u4StaRecIdx; + uint16_t u2WinStart; + uint16_t u2WinSize; + uint32_t u4BuffSize; + +#if CFG_SUPPORT_BCM + uint32_t u4BuffSizeBT; +#endif + + ASSERT(prSwRfb); + + prStaRec = prSwRfb->prStaRec; + prQM = &prAdapter->rQM; + + do { + + /* 4 <0> Check if this is an active HT-capable STA */ + /* Check STA_REC is inuse */ + if (!prStaRec->fgIsInUse) { + log_dbg(QM, WARN, "[Puff][%s]: (Warning) sta_rec is not inuse\n", + __func__); + break; + } + /* Check HT-capabale STA */ + if (!(prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_HT)) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) sta is NOT HT-capable(0x%08X)\n", + __func__, + prStaRec->ucDesiredPhyTypeSet); + break; /* To free the received ADDBA_REQ directly */ + } + /* 4 <1> Check user configurations and HW capabilities */ + /* Check configurations (QoS support, AMPDU RX support) */ + if ((!prAdapter->rWifiVar.fgSupportQoS) || + (!prAdapter->rWifiVar.fgSupportAmpduRx) || + (!prStaRec->fgRxAmpduEn)) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) BA ACK Policy not supported fgSupportQoS(%d)", + __func__, prAdapter->rWifiVar.fgSupportQoS); + DBGLOG(QM, WARN, + "fgSupportAmpduRx(%d), fgRxAmpduEn(%d)\n", + prAdapter->rWifiVar.fgSupportAmpduRx, + prStaRec->fgRxAmpduEn); + /* Will send an ADDBA_RSP with DECLINED */ + fgIsReqAccepted = FALSE; + } + /* Check capability */ + prAddBaReq = ((struct ACTION_ADDBA_REQ_FRAME *) ( + prSwRfb->pvHeader)); + kalMemCopy((uint8_t *) (&rAddBaReqBody), + (uint8_t *) (&(prAddBaReq->aucBAParameterSet[0])), + 6); + if ((((rAddBaReqBody.u2BAParameterSet) & + BA_PARAM_SET_ACK_POLICY_MASK) >> + BA_PARAM_SET_ACK_POLICY_MASK_OFFSET) + != BA_PARAM_SET_ACK_POLICY_IMMEDIATE_BA) { + /* Only Immediate_BA is supported */ + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) BA ACK Policy not supported (0x%08X)\n", + __func__, rAddBaReqBody.u2BAParameterSet); + /* Will send an ADDBA_RSP with DECLINED */ + fgIsReqAccepted = FALSE; + } + + /* 4 <2> Determine the RX BA entry (existing or to be added) */ + /* Note: BA entry index = (TID, STA_REC index) */ + u4Tid = (((rAddBaReqBody.u2BAParameterSet) & + BA_PARAM_SET_TID_MASK) >> + BA_PARAM_SET_TID_MASK_OFFSET); + u4StaRecIdx = prStaRec->ucIndex; + DBGLOG(QM, WARN, + "[Puff][%s]: BA entry index = [TID(%d), STA_REC index(%d)]\n", + __func__, u4Tid, u4StaRecIdx); + + u2WinStart = ((rAddBaReqBody.u2BAStartSeqCtrl) >> + OFFSET_BAR_SSC_SN); + u2WinSize = (((rAddBaReqBody.u2BAParameterSet) & + BA_PARAM_SET_BUFFER_SIZE_MASK) >> + BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET); + DBGLOG(QM, WARN, + "[Puff][%s]: BA entry info = [WinStart(%d), WinSize(%d)]\n", + __func__, u2WinStart, u2WinSize); + + if (fgIsReqAccepted) { + + prRxBaEntry = &prQM->arRxBaTable[u4Tid]; + + if (!prRxBaEntry) { + + /* 4 INVALID state && BA entry + * available --> Add a new entry and accept + */ + if (prQM->ucRxBaCount < + CFG_NUM_OF_RX_BA_AGREEMENTS) { + + fgIsNewEntryAdded = + qmAddRxBaEntry(prAdapter, + (uint8_t) u4StaRecIdx, + (uint8_t) u4Tid, u2WinStart, + u2WinSize); + + if (!fgIsNewEntryAdded) { + DBGLOG(QM, ERROR, + "[Puff][%s]: (Error) Free RX BA entry alloc failure\n"); + fgIsReqAccepted = FALSE; + } else { + log_dbg(QM, WARN, "[Puff][%s]: Create a new BA Entry\n"); + } + } + /* 4 INVALID state && BA entry + * unavailable --> Reject the ADDBA_REQ + */ + else { + log_dbg(QM, WARN, "[Puff][%s]: (Warning) Free RX BA entry unavailable(req: %d)\n", + __func__, prQM->ucRxBaCount); + /* Will send ADDBA_RSP with DECLINED */ + fgIsReqAccepted = FALSE; + } + } else { + + /* 4 NEGO or DELETING state --> + * Ignore the ADDBA_REQ + * For NEGO: do nothing. Wait for TX Done of + * ADDBA_RSP + * For DELETING: do nothing. Wait for TX Done + * of DELBA + */ + if (prRxBaEntry->ucStatus != + BA_ENTRY_STATUS_ACTIVE) { + /* Ignore the ADDBA_REQ since + * the current state is NEGO + */ + log_dbg(QM, WARN, "[Puff][%s]:(Warning)ADDBA_REQ for TID=%ld is received, status:%d)\n", + __func__, u4Tid, + prRxBaEntry->ucStatus); + break; + } + } + } + /* 4 <3> Construct the ADDBA_RSP frame */ + prTxMsduInfo = (struct MSDU_INFO *) cnmMgtPktAlloc( + prAdapter, ACTION_ADDBA_RSP_FRAME_LEN); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + if (!prTxMsduInfo) { + + /* The peer may send an ADDBA_REQ message later. + * Do nothing to the BA entry. No DELBA will be + * sent (because cnmMgtPktAlloc() may fail again). + * No BA deletion event will be sent to the host + * (because cnmMgtPktAlloc() may fail again). + */ + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) ADDBA_RSP alloc failure\n", + __func__); + + if (fgIsNewEntryAdded) { + /* If a new entry has been created due + * to this ADDBA_REQ, delete it + */ + ASSERT(prRxBaEntry); + mqmRxModifyBaEntryStatus(prAdapter, + prRxBaEntry, BA_ENTRY_STATUS_INVALID); + } + + break; /* Exit directly to free the ADDBA_REQ */ + } + + /* Fill the ADDBA_RSP message */ + prAddBaRsp = (struct ACTION_ADDBA_RSP_FRAME *) + ((uint32_t) (prTxMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + prAddBaRsp->u2FrameCtrl = MAC_FRAME_ACTION; + +#if CFG_SUPPORT_802_11W + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) ADDBA_RSP is 80211w enabled\n", + __func__); + prAddBaReq->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + } +#endif + prAddBaRsp->u2DurationID = 0; + prAddBaRsp->ucCategory = CATEGORY_BLOCK_ACK_ACTION; + prAddBaRsp->ucAction = ACTION_ADDBA_RSP; + prAddBaRsp->ucDialogToken = prAddBaReq->ucDialogToken; + + log_dbg(QM, WARN, "[Puff][%s]: (Warning) ADDBA_RSP DurationID(%d) Category(%d) Action(%d) DialogToken(%d)\n", + __func__, prAddBaRsp->u2DurationID, + prAddBaRsp->ucCategory, prAddBaRsp->ucAction, + prAddBaRsp->ucDialogToken); + + if (fgIsReqAccepted) + rAddBaRspBody.u2StatusCode = STATUS_CODE_SUCCESSFUL; + else + rAddBaRspBody.u2StatusCode = STATUS_CODE_REQ_DECLINED; + + /* WinSize = min(WinSize in ADDBA_REQ, CFG_RX_BA_MAX_WINSIZE) */ + u4BuffSize = (((rAddBaReqBody.u2BAParameterSet) & + BA_PARAM_SET_BUFFER_SIZE_MASK) >> + BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET); + + /*If ADDBA req WinSize<=0 => use default WinSize(16) */ + if ((u4BuffSize > CFG_RX_BA_MAX_WINSIZE) + || (u4BuffSize <= 0)) + u4BuffSize = CFG_RX_BA_MAX_WINSIZE; +#if CFG_SUPPORT_BCM + /* TODO: Call BT coexistence function to limit the winsize */ + u4BuffSizeBT = bcmRequestBaWinSize(); + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) bcmRequestBaWinSize(%d)\n", + __func__, u4BuffSizeBT); + + if (u4BuffSize > u4BuffSizeBT) + u4BuffSize = u4BuffSizeBT; +#endif /* CFG_SUPPORT_BCM */ + + rAddBaRspBody.u2BAParameterSet = (BA_POLICY_IMMEDIATE | + (u4Tid << BA_PARAM_SET_TID_MASK_OFFSET) | + (u4BuffSize << BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET)); + + /* TODO: Determine the BA timeout value + * according to the default preference + */ + rAddBaRspBody.u2BATimeoutValue = + rAddBaReqBody.u2BATimeoutValue; + + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) ADDBA_RSP u4BuffSize(%d) StatusCode(%d)", + __func__, u4BuffSize, rAddBaRspBody.u2StatusCode); + DBGLOG(QM, WARN, + "BAParameterSet(0x%08X) BATimeoutValue(%d)\n", + rAddBaRspBody.u2BAParameterSet, + rAddBaRspBody.u2BATimeoutValue); + kalMemCopy((uint8_t *) (&(prAddBaRsp->aucStatusCode[0])), + (uint8_t *) (&rAddBaRspBody), 6); + + COPY_MAC_ADDR(prAddBaRsp->aucDestAddr, + prStaRec->aucMacAddr); + COPY_MAC_ADDR(prAddBaRsp->aucSrcAddr, + prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prAddBaRsp->aucBSSID, prAddBaReq->aucBSSID); + + /* 4 <4> Forward the ADDBA_RSP to TXM */ + TX_SET_MMPDU(prAdapter, + prTxMsduInfo, + prStaRec->ucBssIndex, + (prStaRec != NULL) ? (prStaRec->ucIndex) : + (STA_REC_INDEX_NOT_FOUND), + WLAN_MAC_HEADER_LEN, + ACTION_ADDBA_RSP_FRAME_LEN, + mqmCallbackAddBaRspSent, + MSDU_RATE_MODE_AUTO); + +#if CFG_SUPPORT_802_11W + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(RSN, INFO, "Set MSDU_OPT_PROTECTED_FRAME\n"); + nicTxConfigPktOption(prTxMsduInfo, + MSDU_OPT_PROTECTED_FRAME, TRUE); + } +#endif + + /* Note: prTxMsduInfo->ucTID is not used for transmitting the + * ADDBA_RSP. However, when processing TX Done of this + * ADDBA_RSP, the TID value is needed, so store the TID value + * in advance to prevent parsing the ADDBA_RSP frame + */ + prTxMsduInfo->ucTID = (uint8_t) u4Tid; + + nicTxEnqueueMsdu(prAdapter, prTxMsduInfo); + + DBGLOG(QM, WARN, + "[Puff][%s]: (RX_BA) ADDBA_RSP ---> peer (STA=%d TID=%ld)\n", + __func__, + prStaRec->ucIndex, u4Tid); + +#if 0 + /* 4 <5> Notify the host to start buffer reordering */ + /* Only when a new BA entry is indeed + * added will the host be notified + */ + if (fgIsNewEntryAdded) { + ASSERT(fgIsReqAccepted); + + prSwRfbEventToHost = (struct SW_RFB *) cnmMgtPktAlloc( + EVENT_RX_ADDBA_PACKET_LEN); + + if (!prSwRfbEventToHost) { + + /* Note: DELBA will not be sent since + * cnmMgtPktAlloc() may fail again. However, + * it does not matter because upon receipt of + * AMPDUs without a RX BA agreement, + * MQM will send DELBA frames + */ + + DBGLOG(MQM, WARN, + "MQM: (Warning) EVENT packet alloc failed\n"); + + /* Ensure that host and FW are synchronized */ + mqmRxModifyBaEntryStatus(prRxBaEntry, + BA_ENTRY_STATUS_INVALID); + + break; /* Free the received ADDBA_REQ */ + } + prEventRxAddBa = (struct EVENT_RX_ADDBA *) + prSwRfbEventToHost->pucBuffer; + prEventRxAddBa->ucStaRecIdx = (uint8_t) u4StaRecIdx; + prEventRxAddBa->u2Length = EVENT_RX_ADDBA_PACKET_LEN; + prEventRxAddBa->ucEID = EVENT_ID_RX_ADDBA; + /* Unsolicited event packet */ + prEventRxAddBa->ucSeqNum = 0; + prEventRxAddBa->u2BAParameterSet = + rAddBaRspBody.u2BAParameterSet; + prEventRxAddBa->u2BAStartSeqCtrl = + rAddBaReqBody.u2BAStartSeqCtrl; + prEventRxAddBa->u2BATimeoutValue = + rAddBaReqBody.u2BATimeoutValue; + prEventRxAddBa->ucDialogToken = + prAddBaReq->ucDialogToken; + + log_dbg(MQM, INFO, "MQM: (RX_BA) Event ADDBA ---> driver (STA=%ld TID=%ld WinStart=%d)\n", + u4StaRecIdx, u4Tid, + (prEventRxAddBa->u2BAStartSeqCtrl >> 4)); + + /* Configure the SW_RFB for the Event packet */ + RXM_SET_EVENT_PACKET( + /* struct SW_RFB **/ (struct SW_RFB *) + prSwRfbEventToHost, + /* HIF RX Packet pointer */ + (uint8_t *) prEventRxAddBa, + /* HIF RX port number */ HIF_RX0_INDEX + ); + + rxmSendEventToHost(prSwRfbEventToHost); + + + } +#endif + + } while (FALSE); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void mqmHandleAddBaRsp(IN struct SW_RFB *prSwRfb) +{ + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void mqmHandleDelBa(IN struct SW_RFB *prSwRfb) +{ + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void mqmHandleBaActionFrame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct WLAN_ACTION_FRAME *prRxFrame; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxFrame = (struct WLAN_ACTION_FRAME *) prSwRfb->pvHeader; + DBGLOG(RLM, WARN, "[Puff][%s] Action(%d)\n", __func__, + prRxFrame->ucAction); + + switch (prRxFrame->ucAction) { + + case ACTION_ADDBA_REQ: + DBGLOG(RLM, WARN, + "[Puff][%s] (RX_BA) ADDBA_REQ <--- peer\n", __func__); + mqmHandleAddBaReq(prAdapter, prSwRfb); + break; + + case ACTION_ADDBA_RSP: + DBGLOG(RLM, WARN, + "[Puff][%s] (RX_BA) ADDBA_RSP <--- peer\n", __func__); + mqmHandleAddBaRsp(prSwRfb); + break; + + case ACTION_DELBA: + DBGLOG(RLM, WARN, "[Puff][%s] (RX_BA) DELBA <--- peer\n", + __func__); + mqmHandleDelBa(prSwRfb); + break; + + default: + DBGLOG(RLM, WARN, "[Puff][%s] Unknown BA Action Frame\n", + __func__); + break; + } + +} + +#endif + +#if ARP_MONITER_ENABLE +void qmDetectArpNoResponse(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct sk_buff *prSkb = NULL; + uint8_t *pucData = NULL; + uint16_t u2EtherType = 0; + int arpOpCode = 0; + + if (!prAdapter) + return; + + prSkb = (struct sk_buff *)prMsduInfo->prPacket; + + if (!prSkb || (prSkb->len <= ETHER_HEADER_LEN)) + return; + + pucData = prSkb->data; + if (!pucData) + return; + u2EtherType = (pucData[ETH_TYPE_LEN_OFFSET] << 8) | + (pucData[ETH_TYPE_LEN_OFFSET + 1]); + + if (u2EtherType != ETH_P_ARP) + return; + + /* If ARP req is neither to apIp nor to gatewayIp, ignore detection */ + if (kalMemCmp(apIp, &pucData[ETH_TYPE_LEN_OFFSET + 26], + sizeof(apIp)) && + kalMemCmp(gatewayIp, &pucData[ETH_TYPE_LEN_OFFSET + 26], + sizeof(gatewayIp))) + return; + + arpOpCode = (pucData[ETH_TYPE_LEN_OFFSET + 8] << 8) | + (pucData[ETH_TYPE_LEN_OFFSET + 8 + 1]); + + if (arpOpCode == ARP_PRO_REQ) { + arpMoniter++; + if (arpMoniter > 20) { + DBGLOG(INIT, WARN, + "IOT Critical issue, arp no resp, check AP!\n"); + if (prAdapter->prAisBssInfo) + prAdapter->prAisBssInfo->u2DeauthReason = + BEACON_TIMEOUT_DUE_2_APR_NO_RESPONSE; + aisBssBeaconTimeout(prAdapter); + arpMoniter = 0; + kalMemZero(apIp, sizeof(apIp)); + } + } +} + +void qmHandleRxArpPackets(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb) +{ + uint8_t *pucData = NULL; + uint16_t u2EtherType = 0; + int arpOpCode = 0; + + if (prSwRfb->u2PacketLen <= ETHER_HEADER_LEN) + return; + + pucData = (uint8_t *)prSwRfb->pvHeader; + if (!pucData) + return; + u2EtherType = (pucData[ETH_TYPE_LEN_OFFSET] << 8) | + (pucData[ETH_TYPE_LEN_OFFSET + 1]); + + if (u2EtherType != ETH_P_ARP) + return; + + arpOpCode = (pucData[ETH_TYPE_LEN_OFFSET + 8] << 8) | + (pucData[ETH_TYPE_LEN_OFFSET + 8 + 1]); + if (arpOpCode == ARP_PRO_RSP) { + arpMoniter = 0; + if (prAdapter->prAisBssInfo && + prAdapter->prAisBssInfo->prStaRecOfAP) { + if (EQUAL_MAC_ADDR( + &(pucData[ETH_TYPE_LEN_OFFSET + 10]), + /* source hardware address */ + prAdapter->prAisBssInfo-> + prStaRecOfAP->aucMacAddr)) { + kalMemCopy(apIp, + &(pucData[ETH_TYPE_LEN_OFFSET + 16]), + sizeof(apIp)); + DBGLOG(INIT, TRACE, + "get arp response from AP %d.%d.%d.%d\n", + apIp[0], apIp[1], apIp[2], apIp[3]); + } + } + } +} + +void qmHandleRxDhcpPackets(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb) +{ + uint8_t *pucData = NULL; + uint8_t *pucEthBody = NULL; + uint8_t *pucUdpBody = NULL; + uint32_t udpLength = 0; + uint32_t i = 0; + struct BOOTP_PROTOCOL *prBootp = NULL; + uint32_t u4DhcpMagicCode = 0; + uint8_t dhcpTypeGot = 0; + uint8_t dhcpGatewayGot = 0; + + if (prSwRfb->u2PacketLen <= ETHER_HEADER_LEN) + return; + + pucData = (uint8_t *)prSwRfb->pvHeader; + if (!pucData) + return; + if (((pucData[ETH_TYPE_LEN_OFFSET] << 8) | + pucData[ETH_TYPE_LEN_OFFSET + 1]) != ETH_P_IPV4) + return; + + pucEthBody = &pucData[ETH_HLEN]; + if (((pucEthBody[0] & IPVH_VERSION_MASK) >> + IPVH_VERSION_OFFSET) != IPVERSION) + return; + if (pucEthBody[9] != IP_PRO_UDP) + return; + + pucUdpBody = &pucEthBody[(pucEthBody[0] & 0x0F) * 4]; + if ((pucUdpBody[0] << 8 | pucUdpBody[1]) != UDP_PORT_DHCPS || + (pucUdpBody[2] << 8 | pucUdpBody[3]) != UDP_PORT_DHCPC) + return; + + udpLength = pucUdpBody[4] << 8 | pucUdpBody[5]; + + prBootp = (struct BOOTP_PROTOCOL *) &pucUdpBody[8]; + + WLAN_GET_FIELD_BE32(&prBootp->aucOptions[0], + &u4DhcpMagicCode); + if (u4DhcpMagicCode != DHCP_MAGIC_NUMBER) { + DBGLOG(INIT, WARN, + "dhcp wrong magic number, magic code: %d\n", + u4DhcpMagicCode); + return; + } + + /* 1. 248 is from udp header to the beginning of dhcp option + * 2. not sure the dhcp option always usd 255 as a end mark? + * if so, while condition should be removed? + */ + while (i < udpLength - 248) { + /* bcz of the strange struct BOOTP_PROTOCOL *, + * the dhcp magic code was count in dhcp options + * so need to [i + 4] to skip it + */ + switch (prBootp->aucOptions[i + 4]) { + case 3: + /* both dhcp ack and offer will update it */ + if (prBootp->aucOptions[i + 6] || + prBootp->aucOptions[i + 7] || + prBootp->aucOptions[i + 8] || + prBootp->aucOptions[i + 9]) { + gatewayIp[0] = prBootp->aucOptions[i + 6]; + gatewayIp[1] = prBootp->aucOptions[i + 7]; + gatewayIp[2] = prBootp->aucOptions[i + 8]; + gatewayIp[3] = prBootp->aucOptions[i + 9]; + + DBGLOG(INIT, TRACE, "Gateway ip: %d.%d.%d.%d\n", + gatewayIp[0], + gatewayIp[1], + gatewayIp[2], + gatewayIp[3]); + }; + dhcpGatewayGot = 1; + break; + case 53: + if (prBootp->aucOptions[i + 6] != 0x02 + && prBootp->aucOptions[i + 6] != 0x05) { + DBGLOG(INIT, WARN, + "wrong dhcp message type, type: %d\n", + prBootp->aucOptions[i + 6]); + if (dhcpGatewayGot) + kalMemZero(gatewayIp, + sizeof(gatewayIp)); + return; + } + dhcpTypeGot = 1; + break; + case 255: + return; + + default: + break; + } + if (dhcpGatewayGot && dhcpTypeGot) + return; + + i += prBootp->aucOptions[i + 5] + 2; + } + DBGLOG(INIT, WARN, + "can't find the dhcp option 255?, need to check the net log\n"); +} + +void qmResetArpDetect(void) +{ + arpMoniter = 0; + kalMemZero(apIp, sizeof(apIp)); + kalMemZero(gatewayIp, sizeof(gatewayIp)); +} +#endif + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL +void qmResetTcControlResource(IN struct ADAPTER *prAdapter) +{ + uint32_t u4Idx; + uint32_t u4TotalMinReservedTcResource = 0; + uint32_t u4TotalTcResource = 0; + uint32_t u4TotalGurantedTcResource = 0; + struct QUE_MGT *prQM = &prAdapter->rQM; + + /* Initialize TC resource control variables */ + for (u4Idx = 0; u4Idx < TC_NUM; u4Idx++) + prQM->au4AverageQueLen[u4Idx] = 0; + + ASSERT(prQM->u4TimeToAdjustTcResource + && prQM->u4TimeToUpdateQueLen); + + for (u4Idx = 0; u4Idx < TC_NUM; u4Idx++) { + prQM->au4CurrentTcResource[u4Idx] = + prAdapter->rTxCtrl.rTc.au4MaxNumOfBuffer[u4Idx]; + + if (u4Idx != TC4_INDEX) { + u4TotalTcResource += prQM->au4CurrentTcResource[u4Idx]; + u4TotalGurantedTcResource += + prQM->au4GuaranteedTcResource[u4Idx]; + u4TotalMinReservedTcResource += + prQM->au4MinReservedTcResource[u4Idx]; + } + } + + /* Sanity Check */ + if (u4TotalMinReservedTcResource > u4TotalTcResource) + kalMemZero(prQM->au4MinReservedTcResource, + sizeof(prQM->au4MinReservedTcResource)); + + if (u4TotalGurantedTcResource > u4TotalTcResource) + kalMemZero(prQM->au4GuaranteedTcResource, + sizeof(prQM->au4GuaranteedTcResource)); + + u4TotalGurantedTcResource = 0; + + /* Initialize Residual TC resource */ + for (u4Idx = 0; u4Idx < TC_NUM; u4Idx++) { + if (prQM->au4GuaranteedTcResource[u4Idx] < + prQM->au4MinReservedTcResource[u4Idx]) + prQM->au4GuaranteedTcResource[u4Idx] = + prQM->au4MinReservedTcResource[u4Idx]; + + if (u4Idx != TC4_INDEX) + u4TotalGurantedTcResource += + prQM->au4GuaranteedTcResource[u4Idx]; + } + + prQM->u4ResidualTcResource = u4TotalTcResource - + u4TotalGurantedTcResource; + +} +#endif + +#if CFG_SUPPORT_REPLAY_DETECTION +/* To change PN number to UINT64 */ +#define CCMPTSCPNNUM 6 +u_int8_t qmRxPNtoU64(uint8_t *pucPN, uint8_t uPNNum, + uint64_t *pu64Rets) +{ + uint8_t ucCount = 0; + uint64_t u64Data = 0; + + if (!pu64Rets) { + DBGLOG(QM, ERROR, "Please input valid pu8Rets\n"); + return FALSE; + } + + if (uPNNum > CCMPTSCPNNUM) { + DBGLOG(QM, ERROR, "Please input valid uPNNum:%d\n", uPNNum); + return FALSE; + } + + *pu64Rets = 0; + for (; ucCount < uPNNum; ucCount++) { + u64Data = ((uint64_t) pucPN[ucCount]) << (8 * ucCount); + *pu64Rets += u64Data; + } + return TRUE; +} + +/* To check PN/TSC between RxStatus and local record. + * return TRUE if PNS is not bigger than PNT + */ +u_int8_t qmRxDetectReplay(uint8_t *pucPNS, uint8_t *pucPNT) +{ + uint64_t u8RxNum = 0; + uint64_t u8LocalRec = 0; + + if (!pucPNS || !pucPNT) { + DBGLOG(QM, ERROR, "Please input valid PNS:%p and PNT:%p\n", + pucPNS, pucPNT); + return TRUE; + } + + if (!qmRxPNtoU64(pucPNS, CCMPTSCPNNUM, &u8RxNum) + || !qmRxPNtoU64(pucPNT, CCMPTSCPNNUM, &u8LocalRec)) { + DBGLOG(QM, ERROR, "PN2U64 failed\n"); + return TRUE; + } + /* PN overflow ? */ + return !(u8RxNum > u8LocalRec); +} + +/* TO filter broadcast and multicast data packet replay issue. */ +u_int8_t qmHandleRxReplay(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb) +{ + uint8_t *pucPN = NULL; + uint8_t ucKeyID = 0; /* 0~4 */ + /* CIPHER_SUITE_NONE~CIPHER_SUITE_GCMP */ + uint8_t ucSecMode = CIPHER_SUITE_NONE; + struct GLUE_INFO *prGlueInfo = NULL; + struct GL_WPA_INFO *prWpaInfo = NULL; + struct GL_DETECT_REPLAY_INFO *prDetRplyInfo = NULL; + struct HW_MAC_RX_DESC *prRxStatus = NULL; + uint8_t ucCheckZeroPN; + uint8_t i; + + if (!prAdapter) + return TRUE; + if (prSwRfb->u2PacketLen <= ETHER_HEADER_LEN) + return TRUE; + + if (!(prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_1))) { + DBGLOG_LIMITED(QM, TRACE, "Group 1 invalid\n"); + return FALSE; + } + + /* BMC only need check CCMP and TKIP Cipher suite */ + prRxStatus = prSwRfb->prRxStatus; + ucSecMode = HAL_RX_STATUS_GET_SEC_MODE(prRxStatus); + + prGlueInfo = prAdapter->prGlueInfo; + prWpaInfo = &prGlueInfo->rWpaInfo; + + DBGLOG_LIMITED(QM, TRACE, "ucSecMode = [%u], ChiperGroup = [%u]\n", + ucSecMode, prWpaInfo->u4CipherGroup); + + if (ucSecMode != CIPHER_SUITE_CCMP + && ucSecMode != CIPHER_SUITE_TKIP) { + DBGLOG_LIMITED(QM, TRACE, + "SecMode: %d and CipherGroup: %d, no need check replay\n", + ucSecMode, prWpaInfo->u4CipherGroup); + return FALSE; + } + + ucKeyID = HAL_RX_STATUS_GET_KEY_ID(prRxStatus); + if (ucKeyID >= MAX_KEY_NUM) { + DBGLOG(QM, ERROR, "KeyID: %d error\n", ucKeyID); + return TRUE; + } + + prDetRplyInfo = &prGlueInfo->prDetRplyInfo; + +#if 0 + if (prDetRplyInfo->arReplayPNInfo[ucKeyID].fgFirstPkt) { + prDetRplyInfo->arReplayPNInfo[ucKeyID].fgFirstPkt = FALSE; + HAL_RX_STATUS_GET_PN(prSwRfb->prRxStatusGroup1, + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN); + DBGLOG(QM, INFO, + "First check packet. Key ID:0x%x\n", ucKeyID); + return FALSE; + } +#endif + + pucPN = prSwRfb->prRxStatusGroup1->aucPN; + DBGLOG_LIMITED(QM, TRACE, + "BC packet 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x--0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n", + pucPN[0], pucPN[1], pucPN[2], pucPN[3], pucPN[4], pucPN[5], + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN[0], + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN[1], + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN[2], + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN[3], + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN[4], + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN[5]); + + if (prDetRplyInfo->fgKeyRscFresh == TRUE) { + + /* PN non-fresh setting */ + prDetRplyInfo->fgKeyRscFresh = FALSE; + ucCheckZeroPN = 0; + + for (i = 0; i < 8; i++) { + if (prSwRfb->prRxStatusGroup1->aucPN[i] == 0x0) + ucCheckZeroPN++; + } + + /* for AP start PN from 0, bypass PN check and update */ + if (ucCheckZeroPN == 8) { + DBGLOG(QM, WARN, "Fresh BC_PN with AP PN=0\n"); + return FALSE; + } + } + + if (qmRxDetectReplay(pucPN, + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN)) { + DBGLOG_LIMITED(QM, WARN, "Drop BC replay packet!\n"); + return TRUE; + } + + HAL_RX_STATUS_GET_PN(prSwRfb->prRxStatusGroup1, + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN); + return FALSE; +} +#endif + +#if CFG_SUPPORT_LOWLATENCY_MODE || CFG_SUPPORT_OSHARE +u_int8_t +qmIsNoDropPacket(IN struct ADAPTER *prAdapter, IN struct SW_RFB *prSwRfb) +{ + uint8_t *pucData = (uint8_t *) prSwRfb->pvHeader; + uint16_t u2Etype = (pucData[ETH_TYPE_LEN_OFFSET] << 8) + | (pucData[ETH_TYPE_LEN_OFFSET + 1]); + uint8_t ucBssIndex + = secGetBssIdxByWlanIdx(prAdapter, prSwRfb->ucWlanIdx); + u_int8_t fgCheckDrop = FALSE; + +#if CFG_SUPPORT_LOWLATENCY_MODE + if (prAdapter->fgEnLowLatencyMode) + fgCheckDrop = TRUE; +#endif + +#if CFG_SUPPORT_OSHARE + if (!fgCheckDrop && + (prAdapter->fgEnOshareMode) && + (ucBssIndex <= MAX_BSSID_NUM) && + (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType + == NETWORK_TYPE_P2P)) + fgCheckDrop = TRUE; +#endif + + if (fgCheckDrop && u2Etype == ETH_P_IP) { + uint8_t *pucEthBody = &pucData[ETH_HLEN]; + uint8_t ucIpProto = pucEthBody[IP_PROTO_HLEN]; + + if (ucIpProto == IP_PRO_UDP || ucIpProto == IP_PRO_TCP) + return TRUE; + } + return FALSE; +} +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + +void qmMoveStaTxQueue(struct STA_RECORD *prSrcStaRec, + struct STA_RECORD *prDstStaRec) +{ + uint8_t ucQueArrayIdx; + struct QUE *prSrcQue = NULL; + struct QUE *prDstQue = NULL; + struct MSDU_INFO *prMsduInfo = NULL; + uint8_t ucDstStaIndex = 0; + + ASSERT(prSrcStaRec); + ASSERT(prDstStaRec); + + prSrcQue = &prSrcStaRec->arTxQueue[0]; + prDstQue = &prDstStaRec->arTxQueue[0]; + ucDstStaIndex = prDstStaRec->ucIndex; + + DBGLOG(QM, INFO, "Pending MSDUs for TC 0~3, %u %u %u %u\n", + prSrcQue[TC0_INDEX].u4NumElem, prSrcQue[TC1_INDEX].u4NumElem, + prSrcQue[TC2_INDEX].u4NumElem, prSrcQue[TC3_INDEX].u4NumElem); + /* Concatenate all MSDU_INFOs in TX queues of this STA_REC */ + for (ucQueArrayIdx = 0; ucQueArrayIdx < TC4_INDEX; ucQueArrayIdx++) { + prMsduInfo = (struct MSDU_INFO *)QUEUE_GET_HEAD( + &prSrcQue[ucQueArrayIdx]); + while (prMsduInfo) { + prMsduInfo->ucStaRecIndex = ucDstStaIndex; + prMsduInfo = (struct MSDU_INFO *)QUEUE_GET_NEXT_ENTRY( + &prMsduInfo->rQueEntry); + } + QUEUE_CONCATENATE_QUEUES((&prDstQue[ucQueArrayIdx]), + (&prSrcQue[ucQueArrayIdx])); + } +} + +void qmHandleDelTspec(struct ADAPTER *prAdapter, struct STA_RECORD *prStaRec, + enum ENUM_ACI eAci) +{ + uint8_t aucNextUP[ACI_NUM] = {1 /* BEtoBK */, 1 /*na */, 0 /*VItoBE */, + 4 /*VOtoVI */}; + enum ENUM_ACI aeNextAci[ACI_NUM] = {ACI_BK, ACI_BK, ACI_BE, ACI_VI}; + uint8_t ucActivedTspec = 0; + uint8_t ucNewUp = 0; + struct QUE *prSrcQue = NULL; + struct QUE *prDstQue = NULL; + struct MSDU_INFO *prMsduInfo = NULL; + struct AC_QUE_PARMS *prAcQueParam = NULL; + uint8_t ucTc = 0; + + if (!prStaRec || eAci == ACI_NUM || eAci == ACI_BK || !prAdapter || + !prAdapter->prAisBssInfo) { + DBGLOG(QM, ERROR, "prSta NULL %d, eAci %d, prAdapter NULL %d\n", + !prStaRec, eAci, !prAdapter); + return; + } + prSrcQue = &prStaRec->arTxQueue[aucWmmAC2TcResourceSet1[eAci]]; + prAcQueParam = &(prAdapter->prAisBssInfo->arACQueParms[0]); + ucActivedTspec = wmmHasActiveTspec(&prAdapter->rWifiVar.rWmmInfo); + + while (prAcQueParam[eAci].ucIsACMSet && + !(ucActivedTspec & BIT(eAci)) && eAci != ACI_BK) { + eAci = aeNextAci[eAci]; + ucNewUp = aucNextUP[eAci]; + } + DBGLOG(QM, INFO, "new ACI %d, ACM %d, HasTs %d\n", eAci, + prAcQueParam[eAci].ucIsACMSet, !!(ucActivedTspec & BIT(eAci))); + ucTc = aucWmmAC2TcResourceSet1[eAci]; + prDstQue = &prStaRec->arTxQueue[ucTc]; + prMsduInfo = (struct MSDU_INFO *)QUEUE_GET_HEAD(prSrcQue); + while (prMsduInfo) { + prMsduInfo->ucUserPriority = ucNewUp; + prMsduInfo->ucTC = ucTc; + prMsduInfo = (struct MSDU_INFO *)QUEUE_GET_NEXT_ENTRY( + &prMsduInfo->rQueEntry); + } + QUEUE_CONCATENATE_QUEUES(prDstQue, prSrcQue); +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + qmUpdateAverageTxQueLen(prAdapter); + qmReassignTcResource(prAdapter); +#endif + nicTxAdjustTcq(prAdapter); + kalSetEvent(prAdapter->prGlueInfo); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_ate_agent.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_ate_agent.c new file mode 100644 index 0000000000000..897b576c6fe92 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_ate_agent.c @@ -0,0 +1,2562 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + Module Name: + gl_ate_agent.c +*/ +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ + +#include "precomp.h" +#if CFG_SUPPORT_QA_TOOL +#include "gl_wext.h" +#include "gl_cfg80211.h" +#include "gl_ate_agent.h" +#include "gl_hook_api.h" +#include "gl_qa_agent.h" +#if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE +#include +#endif + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +#if CFG_SUPPORT_TX_BF +union PFMU_PROFILE_TAG1 g_rPfmuTag1; +union PFMU_PROFILE_TAG2 g_rPfmuTag2; +union PFMU_DATA g_rPfmuData; +#endif + +struct ATE_PRIV_CMD { + uint8_t *name; + int (*set_proc)(struct net_device *prNetDev, + uint8_t *prInBuf); +}; + +struct ATE_PRIV_CMD rAtePrivCmdTable[] = { + {"ResetCounter", Set_ResetStatCounter_Proc}, + {"ATE", SetATE}, +#if 0 + {"ADCDump", SetADCDump}, + {"ATEBSSID", SetATEBssid}, +#endif + {"ATEDA", SetATEDa}, + {"ATESA", SetATESa}, + {"ATECHANNEL", SetATEChannel}, + {"ATETXPOW0", SetATETxPower0}, + {"ATETXGI", SetATETxGi}, + {"ATETXBW", SetATETxBw}, + {"ATETXLEN", SetATETxLength}, + {"ATETXCNT", SetATETxCount}, + {"ATETXMCS", SetATETxMcs}, + {"ATETXMODE", SetATETxMode}, + {"ATEIPG", SetATEIpg}, +#if CFG_SUPPORT_TX_BF + {"TxBfProfileTagHelp", Set_TxBfProfileTag_Help}, + {"TxBfProfileTagInValid", Set_TxBfProfileTag_InValid}, + {"TxBfProfileTagPfmuIdx", Set_TxBfProfileTag_PfmuIdx}, + {"TxBfProfileTagBfType", Set_TxBfProfileTag_BfType}, + {"TxBfProfileTagBw", Set_TxBfProfileTag_DBW}, + {"TxBfProfileTagSuMu", Set_TxBfProfileTag_SuMu}, + {"TxBfProfileTagMemAlloc", Set_TxBfProfileTag_Mem}, + {"TxBfProfileTagMatrix", Set_TxBfProfileTag_Matrix}, + {"TxBfProfileTagSnr", Set_TxBfProfileTag_SNR}, + {"TxBfProfileTagSmtAnt", Set_TxBfProfileTag_SmartAnt}, + {"TxBfProfileTagSeIdx", Set_TxBfProfileTag_SeIdx}, + {"TxBfProfileTagRmsdThrd", Set_TxBfProfileTag_RmsdThrd}, + {"TxBfProfileTagMcsThrd", Set_TxBfProfileTag_McsThrd}, + {"TxBfProfileTagTimeOut", Set_TxBfProfileTag_TimeOut}, + {"TxBfProfileTagDesiredBw", Set_TxBfProfileTag_DesiredBW}, + {"TxBfProfileTagDesiredNc", Set_TxBfProfileTag_DesiredNc}, + {"TxBfProfileTagDesiredNr", Set_TxBfProfileTag_DesiredNr}, + {"TxBfProfileTagRead", Set_TxBfProfileTagRead}, + {"TxBfProfileTagWrite", Set_TxBfProfileTagWrite}, + {"TxBfProfileDataRead", Set_TxBfProfileDataRead}, + {"TxBfProfileDataWrite", Set_TxBfProfileDataWrite}, + {"TxBfProfilePnRead", Set_TxBfProfilePnRead}, + {"TxBfProfilePnWrite", Set_TxBfProfilePnWrite}, + {"TxBfSounding", Set_Trigger_Sounding_Proc}, + {"TxBfSoundingStop", Set_Stop_Sounding_Proc}, + {"TxBfTxApply", Set_TxBfTxApply}, + {"TxBfManualAssoc", Set_TxBfManualAssoc}, + {"TxBfPfmuMemAlloc", Set_TxBfPfmuMemAlloc}, + {"TxBfPfmuMemRelease", Set_TxBfPfmuMemRelease}, + {"StaRecCmmUpdate", Set_StaRecCmmUpdate}, + {"StaRecBfUpdate", Set_StaRecBfUpdate}, + {"DevInfoUpdate", Set_DevInfoUpdate}, + {"BssInfoUpdate", Set_BssInfoUpdate}, +#if CFG_SUPPORT_MU_MIMO + {"MUGetInitMCS", Set_MUGetInitMCS}, + {"MUCalInitMCS", Set_MUCalInitMCS}, + {"MUCalLQ", Set_MUCalLQ}, + {"MUGetLQ", Set_MUGetLQ}, + {"MUSetSNROffset", Set_MUSetSNROffset}, + {"MUSetZeroNss", Set_MUSetZeroNss}, + {"MUSetSpeedUpLQ", Set_MUSetSpeedUpLQ}, + {"MUSetMUTable", Set_MUSetMUTable}, + {"MUSetGroup", Set_MUSetGroup}, + {"MUGetQD", Set_MUGetQD}, + {"MUSetEnable", Set_MUSetEnable}, + {"MUSetGID_UP", Set_MUSetGID_UP}, + {"MUTriggerTx", Set_MUTriggerTx}, +#endif + +#if CFG_SUPPORT_TX_BF_FPGA + {"TxBfProfileSwTagWrite", Set_TxBfProfileSwTagWrite}, +#endif + +#endif + + {"WriteEfuse", WriteEfuse}, + {"TxPower", SetTxTargetPower}, +#if (CFG_SUPPORT_DFS_MASTER == 1) + {"RDDReport", SetRddReport}, + {"ByPassCac", SetByPassCac}, + {"RadarDetectMode", SetRadarDetectMode}, +#endif + + {NULL,} +}; + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Reset RX Statistic Counters. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +int Set_ResetStatCounter_Proc(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + int32_t i4Status; + + DBGLOG(REQ, INFO, + "ATE_AGENT iwpriv Set_ResetStatCounter_Proc\n"); + + i4Status = MT_ATEResetTXRXCounter(prNetDev); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set Start Test Mode / Stop Test Mode + * / Start TX / Stop TX / Start RX / Stop RX. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATE(struct net_device *prNetDev, uint8_t *prInBuf) +{ + int32_t i4Status; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetATE\n"); + + if (!strcmp(prInBuf, "ATESTART")) { + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetATE - ATESTART\n"); + i4Status = MT_ATEStart(prNetDev, prInBuf); + } else if (!strcmp(prInBuf, "ICAPSTART")) { + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetATE - ICAPSTART\n"); + i4Status = MT_ICAPStart(prNetDev, prInBuf); + } else if (prInBuf[0] == '1' || prInBuf[0] == '2' + || prInBuf[0] == '3' || prInBuf[0] == '4') { + DBGLOG(REQ, INFO, + "ATE_AGENT iwpriv SetATE - ICAP COMMAND\n"); + i4Status = MT_ICAPCommand(prNetDev, prInBuf); + } else if (!strcmp(prInBuf, "ATESTOP")) { + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetATE - ATESTOP\n"); + i4Status = MT_ATEStop(prNetDev, prInBuf); + } else if (!strcmp(prInBuf, "TXFRAME")) { + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetATE - TXFRAME\n"); + i4Status = MT_ATEStartTX(prNetDev, prInBuf); + } else if (!strcmp(prInBuf, "TXSTOP")) { + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetATE - TXSTOP\n"); + i4Status = MT_ATEStopTX(prNetDev, prInBuf); + } else if (!strcmp(prInBuf, "RXFRAME")) { + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetATE - RXFRAME\n"); + i4Status = MT_ATEStartRX(prNetDev, prInBuf); + } else if (!strcmp(prInBuf, "RXSTOP")) { + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetATE - RXSTOP\n"); + i4Status = MT_ATEStopRX(prNetDev, prInBuf); + } else { + return -EINVAL; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set TX Destination Address. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATEDa(struct net_device *prNetDev, uint8_t *prInBuf) +{ + int32_t i4Status = 0; + uint32_t addr[MAC_ADDR_LEN]; + uint8_t addr2[MAC_ADDR_LEN]; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "ATE_AGENT iwpriv SetDa\n"); + /* xx:xx:xx:xx:xx:xx */ + rv = sscanf(prInBuf, "%x:%x:%x:%x:%x:%x", &addr[0], + &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]); + if (rv == 6) { + DBGLOG(RFTEST, ERROR, + "ATE_AGENT iwpriv SetATEDa Sa:%02x:%02x:%02x:%02x:%02x:%02x\n", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + + addr2[0] = (uint8_t) addr[0]; + addr2[1] = (uint8_t) addr[1]; + addr2[2] = (uint8_t) addr[2]; + addr2[3] = (uint8_t) addr[3]; + addr2[4] = (uint8_t) addr[4]; + addr2[5] = (uint8_t) addr[5]; + + i4Status = MT_ATESetMACAddress(prNetDev, + RF_AT_FUNCID_SET_MAC_ADDRESS, addr2); + } else { + return -EINVAL; + } + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set TX Source Address. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATESa(struct net_device *prNetDev, uint8_t *prInBuf) +{ + int32_t i4Status = 0; + uint32_t addr[MAC_ADDR_LEN]; + uint8_t addr2[MAC_ADDR_LEN]; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "ATE_AGENT iwpriv SetSa\n"); + /* xx:xx:xx:xx:xx:xx */ + rv = sscanf(prInBuf, "%x:%x:%x:%x:%x:%x", &addr[0], + &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]); + if (rv == 6) { + DBGLOG(RFTEST, ERROR, + "ATE_AGENT iwpriv SetATESa Sa:%02x:%02x:%02x:%02x:%02x:%02x\n", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + + addr2[0] = (uint8_t) addr[0]; + addr2[1] = (uint8_t) addr[1]; + addr2[2] = (uint8_t) addr[2]; + addr2[3] = (uint8_t) addr[3]; + addr2[4] = (uint8_t) addr[4]; + addr2[5] = (uint8_t) addr[5]; + + i4Status = MT_ATESetMACAddress(prNetDev, + RF_AT_FUNCID_SET_TA, addr2); + } else { + return -EINVAL; + } + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set Channel Frequency. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATEChannel(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t i4SetFreq = 0; + int32_t i4Status, i4SetChan = 0; + int32_t rv; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetChannel\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetChan); + if (rv == 0) { + i4SetFreq = nicChannelNum2Freq(i4SetChan); + i4Status = MT_ATESetChannel(prNetDev, 0, i4SetFreq); + } else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set TX WF0 Power. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATETxPower0(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t i4SetTxPower0 = 0; + int32_t i4Status; + int32_t rv; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetTxPower0\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxPower0); + if (rv == 0) + i4Status = MT_ATESetTxPower0(prNetDev, i4SetTxPower0); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set TX Guard Interval. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATETxGi(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t i4SetTxGi = 0; + int32_t i4Status; + int32_t rv; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetTxGi\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxGi); + if (rv == 0) + i4Status = MT_ATESetTxGi(prNetDev, i4SetTxGi); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set TX System Bandwidth. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATETxBw(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t i4SetSystemBW = 0; + int32_t i4Status; + int32_t rv; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetSystemBW\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetSystemBW); + if (rv == 0) + i4Status = MT_ATESetSystemBW(prNetDev, i4SetSystemBW); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set TX Mode (Preamble). + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATETxMode(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t i4SetTxMode = 0; + int32_t i4Status; + int32_t rv; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetTxMode\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxMode); + if (rv == 0) + i4Status = MT_ATESetPreamble(prNetDev, i4SetTxMode); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set TX Length. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATETxLength(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t i4SetTxLength = 0; + int32_t i4Status; + int32_t rv; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetTxLength\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxLength); + if (rv == 0) + i4Status = MT_ATESetTxLength(prNetDev, i4SetTxLength); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set TX Count. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATETxCount(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t i4SetTxCount = 0; + int32_t i4Status; + int32_t rv; + uint8_t addr[MAC_ADDR_LEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetTxCount\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxCount); + if (rv == 0) + i4Status = MT_ATESetTxCount(prNetDev, i4SetTxCount); + else + return -EINVAL; + + i4Status = MT_ATESetMACAddress(prNetDev, + RF_AT_FUNCID_SET_MAC_ADDRESS, addr); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set TX Rate. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATETxMcs(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t i4SetTxMcs = 0; + int32_t i4Status; + int32_t rv; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetTxMcs\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxMcs); + if (rv == 0) + i4Status = MT_ATESetRate(prNetDev, i4SetTxMcs); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set Inter-Packet Guard Interval. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetATEIpg(struct net_device *prNetDev, uint8_t *prInBuf) +{ + uint32_t i4SetTxIPG = 0; + int32_t i4Status; + int32_t rv; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv SetIpg\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxIPG); + if (rv == 0) + i4Status = MT_ATESetTxIPG(prNetDev, i4SetTxIPG); + else + return -EINVAL; + + return i4Status; +} + +#if CFG_SUPPORT_TX_BF +int Set_TxBfProfileTag_Help(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + DBGLOG(RFTEST, ERROR, + "========================================================================================================================\n" + "TxBfProfile Tag1 setting example :\n" + "iwpriv ra0 set TxBfProfileTagPfmuIdx =xx\n" + "iwpriv ra0 set TxBfProfileTagBfType =xx (0: iBF; 1: eBF)\n" + "iwpriv ra0 set TxBfProfileTagBw =xx (0/1/2/3 : BW20/40/80/160NC)\n" + "iwpriv ra0 set TxBfProfileTagSuMu =xx (0:SU, 1:MU)\n" + "iwpriv ra0 set TxBfProfileTagInvalid =xx (0: valid, 1: invalid)\n" + "iwpriv ra0 set TxBfProfileTagMemAlloc =xx:xx:xx:xx:xx:xx:xx:xx (mem_row, mem_col), ..\n" + "iwpriv ra0 set TxBfProfileTagMatrix =nrow:nol:ng:LM\n" + "iwpriv ra0 set TxBfProfileTagSnr =SNR_STS0:SNR_STS1:SNR_STS2:SNR_STS3\n" + "\n\n" + "TxBfProfile Tag2 setting example :\n" + "iwpriv ra0 set TxBfProfileTagSmtAnt =xx (11:0)\n" + "iwpriv ra0 set TxBfProfileTagSeIdx =xx\n" + "iwpriv ra0 set TxBfProfileTagRmsdThrd =xx\n" + "iwpriv ra0 set TxBfProfileTagMcsThrd =xx:xx:xx:xx:xx:xx (MCS TH L1SS:S1SS:L2SS:....)\n" + "iwpriv ra0 set TxBfProfileTagTimeOut =xx\n" + "iwpriv ra0 set TxBfProfileTagDesiredBw=xx (0/1/2/3 : BW20/40/80/160NC)\n" + "iwpriv ra0 set TxBfProfileTagDesiredNc=xx\n" + "iwpriv ra0 set TxBfProfileTagDesiredNr=xx\n" + "\n\n" + "Read TxBf profile Tag :\n" + "iwpriv ra0 set TxBfProfileTagRead =xx (PFMU ID)\n" + "\n" + "Write TxBf profile Tag :\n" + "iwpriv ra0 set TxBfProfileTagWrite =xx (PFMU ID)\n" + "When you use one of relative CMD to update one of tag parameters, you should call TxBfProfileTagWrite to update Tag\n" + "\n\n" + "Read TxBf profile Data :\n" + "iwpriv ra0 set TxBfProfileDataRead =xx (PFMU ID)\n" + "\n" + "Write TxBf profile Data :\n" + "iwpriv ra0 set TxBfProfileDataWrite =BW :subcarrier:phi11:psi2l:Phi21:Psi31:Phi31:Psi41:Phi22:Psi32:Phi32:Psi42:Phi33:Psi43\n" + "iwpriv ra0 set TxBfProfileDataWriteAll=Profile ID : BW (BW : 0x00 (20M) , 0x01 (40M), 0x02 (80M), 0x3 (160M)\n" + "When you use CMD TxBfProfileDataWrite to update profile data per subcarrier, you should call TxBfProfileDataWriteAll to update all of\n" + "subcarrier's profile data.\n\n" + "Read TxBf profile PN :\n" + "iwpriv ra0 set TxBfProfilePnRead =xx (PFMU ID)\n" + "\n" + "Write TxBf profile PN :\n" + "iwpriv ra0 set TxBfProfilePnWrite =Profile ID:BW:1STS_Tx0:1STS_Tx1:1STS_Tx2:1STS_Tx3:2STS_Tx0:2STS_Tx1:2STS_Tx2:2STS_Tx3:3STS_Tx1:3STS_Tx2:3STS_Tx3\n" + "========================================================================================================================\n"); + return 0; +} + +int Set_TxBfProfileTag_InValid(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t ucInValid; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_InValid\n"); + + rv = kstrtoint(prInBuf, 0, &ucInValid); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTag_InValid prInBuf = %s, ucInValid = %d\n", + prInBuf, + ucInValid); + i4Status = TxBfProfileTag_InValid(prNetDev, &g_rPfmuTag1, + ucInValid); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_PfmuIdx(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t ucProfileIdx; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_PfmuIdx\n"); + + rv = kstrtoint(prInBuf, 0, &ucProfileIdx); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTag_PfmuIdx prInBuf = %s, ucProfileIdx = %d\n", + prInBuf, + ucProfileIdx); + i4Status = TxBfProfileTag_PfmuIdx(prNetDev, &g_rPfmuTag1, + ucProfileIdx); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_BfType(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t ucBFType; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_BfType\n"); + + rv = kstrtoint(prInBuf, 0, &ucBFType); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTag_BfType prInBuf = %s, ucBFType = %d\n", + prInBuf, ucBFType); + i4Status = TxBfProfileTag_TxBfType(prNetDev, &g_rPfmuTag1, + ucBFType); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_DBW(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t ucBW; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_DBW\n"); + + rv = kstrtoint(prInBuf, 0, &ucBW); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTag_DBW prInBuf = %s, ucBW = %d\n", + prInBuf, ucBW); + i4Status = TxBfProfileTag_DBW(prNetDev, &g_rPfmuTag1, ucBW); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_SuMu(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t ucSuMu; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_SuMu\n"); + + rv = kstrtoint(prInBuf, 0, &ucSuMu); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTag_SuMu prInBuf = %s, ucSuMu = %d\n", + prInBuf, ucSuMu); + i4Status = TxBfProfileTag_SuMu(prNetDev, &g_rPfmuTag1, + ucSuMu); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_Mem(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t aucInput[8]; + int32_t i4Status = 0; + uint8_t aucMemAddrColIdx[4], aucMemAddrRowIdx[4]; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_Mem\n"); + + rv = sscanf(prInBuf, "%d:%d:%d:%d:%d:%d:%d:%d", + &aucInput[0], &aucInput[1], &aucInput[2], &aucInput[3], + &aucInput[4], &aucInput[5], &aucInput[6], + &aucInput[7]); + /* mem col0:row0:col1:row1:col2:row2:col3:row3 */ + if (rv == 8) { + DBGLOG(RFTEST, ERROR, + "ATE_AGENT iwpriv Set_TxBfProfileTag_Mem aucInput:%d:%d:%d:%d:%d:%d:%d:%d\n", + aucInput[0], aucInput[1], aucInput[2], aucInput[3], + aucInput[4], aucInput[5], aucInput[6], + aucInput[7]); + + aucMemAddrColIdx[0] = (uint8_t) aucInput[0]; + aucMemAddrRowIdx[0] = (uint8_t) aucInput[1]; + aucMemAddrColIdx[1] = (uint8_t) aucInput[2]; + aucMemAddrRowIdx[1] = (uint8_t) aucInput[3]; + aucMemAddrColIdx[2] = (uint8_t) aucInput[4]; + aucMemAddrRowIdx[2] = (uint8_t) aucInput[5]; + aucMemAddrColIdx[3] = (uint8_t) aucInput[6]; + aucMemAddrRowIdx[3] = (uint8_t) aucInput[7]; + + i4Status = TxBfProfileTag_Mem(prNetDev, &g_rPfmuTag1, + aucMemAddrColIdx, aucMemAddrRowIdx); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_Matrix(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t aucInput[6]; + uint8_t ucNrow, ucNcol, ucNgroup, ucLM, ucCodeBook, + ucHtcExist; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_Matrix\n"); + + rv = sscanf(prInBuf, "%d:%d:%d:%d:%d:%d", + &aucInput[0], &aucInput[1], &aucInput[2], &aucInput[3], + &aucInput[4], &aucInput[5]); + /* nrow:nol:ng:LM:CodeBook:HtcExist */ + if (rv == 6) { + DBGLOG(RFTEST, ERROR, + "ATE_AGENT iwpriv Set_TxBfProfileTag_Matrix aucInput:%d:%d:%d:%d:%d:%d\n", + aucInput[0], aucInput[1], aucInput[2], aucInput[3], + aucInput[4], aucInput[5]); + ucNrow = (uint8_t) aucInput[0]; + ucNcol = (uint8_t) aucInput[1]; + ucNgroup = (uint8_t) aucInput[2]; + ucLM = (uint8_t) aucInput[3]; + ucCodeBook = (uint8_t) aucInput[4]; + ucHtcExist = (uint8_t) aucInput[5]; + + i4Status = TxBfProfileTag_Matrix(prNetDev, &g_rPfmuTag1, ucNrow, + ucNcol, ucNgroup, ucLM, ucCodeBook, ucHtcExist); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_SNR(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t aucInput[4]; + uint8_t ucSNR_STS0, ucSNR_STS1, ucSNR_STS2, ucSNR_STS3; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_SNR\n"); + + rv = sscanf(prInBuf, "%d:%d:%d:%d", &aucInput[0], + &aucInput[1], &aucInput[2], &aucInput[3]); + if (rv == 4) { + DBGLOG(RFTEST, ERROR, + "ATE_AGENT iwpriv Set_TxBfProfileTag_SNR aucInput:%d:%d:%d:%d\n", + aucInput[0], aucInput[1], aucInput[2], aucInput[3]); + + ucSNR_STS0 = (uint8_t) aucInput[0]; + ucSNR_STS1 = (uint8_t) aucInput[1]; + ucSNR_STS2 = (uint8_t) aucInput[2]; + ucSNR_STS3 = (uint8_t) aucInput[3]; + + i4Status = TxBfProfileTag_SNR(prNetDev, &g_rPfmuTag1, + ucSNR_STS0, ucSNR_STS1, ucSNR_STS2, ucSNR_STS3); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_SmartAnt(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + int32_t i4Status = 0; + uint32_t ucSmartAnt; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_SmartAnt\n"); + + rv = kstrtoint(prInBuf, 0, &ucSmartAnt); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTag_SmartAnt prInBuf = %s, ucSmartAnt = %d\n", + prInBuf, + ucSmartAnt); + i4Status = TxBfProfileTag_SmtAnt(prNetDev, &g_rPfmuTag2, + ucSmartAnt); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_SeIdx(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + int32_t i4Status = 0; + uint32_t ucSeIdx; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_SeIdx\n"); + + rv = kstrtoint(prInBuf, 0, &ucSeIdx); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "TxBfProfileTag_SeIdx prInBuf = %s, ucSeIdx = %d\n", + prInBuf, ucSeIdx); + i4Status = TxBfProfileTag_SeIdx(prNetDev, &g_rPfmuTag2, + ucSeIdx); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_RmsdThrd(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + int32_t i4Status = 0; + uint32_t ucRmsdThrd; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_RmsdThrd\n"); + + rv = kstrtoint(prInBuf, 0, &ucRmsdThrd); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTag_RmsdThrd prInBuf = %s, ucRmsdThrd = %d\n", + prInBuf, + ucRmsdThrd); + i4Status = TxBfProfileTag_RmsdThd(prNetDev, &g_rPfmuTag2, + ucRmsdThrd); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_McsThrd(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t aucInput[6]; + uint8_t ucMcsLss[3], ucMcsSss[3]; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_McsThrd\n"); + + rv = sscanf(prInBuf, "%d:%d:%d:%d:%d:%d", + &aucInput[0], &aucInput[1], &aucInput[2], &aucInput[3], + &aucInput[4], &aucInput[5]); + if (rv == 6) { + DBGLOG(RFTEST, ERROR, + "ATE_AGENT iwpriv Set_TxBfProfileTag_McsThrd aucInput:%d:%d:%d:%d:%d:%d\n", + aucInput[0], aucInput[1], aucInput[2], aucInput[3], + aucInput[4], aucInput[5]); + + ucMcsLss[0] = (uint8_t) aucInput[0]; + ucMcsSss[0] = (uint8_t) aucInput[1]; + ucMcsLss[1] = (uint8_t) aucInput[2]; + ucMcsSss[1] = (uint8_t) aucInput[3]; + ucMcsLss[2] = (uint8_t) aucInput[4]; + ucMcsSss[2] = (uint8_t) aucInput[5]; + + i4Status = TxBfProfileTag_McsThd(prNetDev, &g_rPfmuTag2, + ucMcsLss, ucMcsSss); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_TimeOut(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t ucTimeOut; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_TimeOut\n"); + + rv = kstrtouint(prInBuf, 0, &ucTimeOut); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTag_TimeOut prInBuf = %s, ucTimeOut = %d\n", + prInBuf, + ucTimeOut); + i4Status = TxBfProfileTag_TimeOut(prNetDev, &g_rPfmuTag2, + ucTimeOut); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_DesiredBW(struct net_device + *prNetDev, uint8_t *prInBuf) +{ + uint32_t ucDesiredBW; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_DesiredBW\n"); + + rv = kstrtoint(prInBuf, 0, &ucDesiredBW); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTag_DesiredBW prInBuf = %s, ucDesiredBW = %d\n", + prInBuf, + ucDesiredBW); + i4Status = TxBfProfileTag_DesiredBW(prNetDev, &g_rPfmuTag2, + ucDesiredBW); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_DesiredNc(struct net_device + *prNetDev, uint8_t *prInBuf) +{ + uint32_t ucDesiredNc; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_DesiredNc\n"); + + rv = kstrtoint(prInBuf, 0, &ucDesiredNc); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTag_DesiredNc prInBuf = %s, ucDesiredNc = %d\n", + prInBuf, + ucDesiredNc); + i4Status = TxBfProfileTag_DesiredNc(prNetDev, &g_rPfmuTag2, + ucDesiredNc); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_DesiredNr(struct net_device + *prNetDev, uint8_t *prInBuf) +{ + uint32_t ucDesiredNr; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTag_DesiredNr\n"); + + rv = kstrtoint(prInBuf, 0, &ucDesiredNr); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTag_DesiredNr prInBuf = %s, ucDesiredNr = %d\n", + prInBuf, + ucDesiredNr); + i4Status = TxBfProfileTag_DesiredNr(prNetDev, &g_rPfmuTag2, + ucDesiredNr); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTagWrite(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t profileIdx; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTagWrite\n"); + + rv = kstrtoint(prInBuf, 0, &profileIdx); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTagWrite prInBuf = %s, profileIdx = %d\n", + prInBuf, + profileIdx); + i4Status = TxBfProfileTagWrite(prNetDev, &g_rPfmuTag1, + &g_rPfmuTag2, profileIdx); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTagRead(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t profileIdx, fgBFer; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileTagRead\n"); + + rv = sscanf(prInBuf, "%d:%d", &profileIdx, &fgBFer); + if (rv == 2) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileTagRead prInBuf = %s, profileIdx = %d, fgBFer = %d\n", + prInBuf, profileIdx, fgBFer); + i4Status = TxBfProfileTagRead(prNetDev, profileIdx, fgBFer); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileDataRead(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t profileIdx, fgBFer, subcarrierIdxMsb, + subcarrierIdxLsb; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileDataRead\n"); + + rv = sscanf(prInBuf, "%d:%d:%x:%x", &profileIdx, &fgBFer, + &subcarrierIdxMsb, &subcarrierIdxLsb); + if (rv == 4) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileDataRead prInBuf = %s, profileIdx = %d, fgBFer = %d, subcarrierIdxMsb:%x, subcarrierIdxLsb:%x\n", + prInBuf, profileIdx, fgBFer, subcarrierIdxMsb, + subcarrierIdxLsb); + i4Status = TxBfProfileDataRead(prNetDev, profileIdx, fgBFer, + subcarrierIdxMsb, subcarrierIdxLsb); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileDataWrite(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + + uint32_t u4ProfileIdx; + uint32_t u4SubcarrierIdx; + uint32_t au4Phi[6]; + uint32_t au4Psi[6]; + uint32_t au4DSnr[4]; + uint16_t au2Phi[6]; + uint8_t aucPsi[6]; + uint8_t aucDSnr[4]; + uint32_t i; + int32_t rv; + + int32_t i4Status = 0; + + DBGLOG(RFTEST, ERROR, "TxBfProfileDataWrite\n"); + + rv = sscanf(prInBuf, + "%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x", + &u4ProfileIdx, &u4SubcarrierIdx, &au4Phi[0], &au4Psi[0], + &au4Phi[1], &au4Psi[1], + &au4Phi[2], &au4Psi[2], &au4Phi[3], &au4Psi[3], &au4Phi[4], + &au4Psi[4], + &au4Phi[5], &au4Psi[5], + &au4DSnr[0], &au4DSnr[1], &au4DSnr[2], &au4DSnr[3]); + + if (rv == 18) { + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite prInBuf = %s, u4ProfileIdx = %x, u4SubcarrierIdx = %x, au4Phi[0]:%x, au4Phi[1]:%x, au4Phi[2]:%x, au4Phi[3]:%x, au4Phi[4]:%x, au4Phi[5]:%x, au4Psi[0]:%x, au4Psi[1]:%x, au4Psi[2]:%x, au4Psi[3]:%x, au4Psi[4]:%x, au4Psi[5]:%x,au4DSnr[0]:%x, au4DSnr[1]:%x, au4DSnr[2]:%x, au4DSnr[3]:%x\n", + prInBuf, u4ProfileIdx, u4SubcarrierIdx, + au4Phi[0], au4Phi[1], au4Phi[2], au4Phi[3], au4Phi[4], + au4Phi[5], + au4Psi[0], au4Psi[1], au4Psi[2], au4Psi[3], au4Psi[4], + au4Psi[5], + au4DSnr[0], au4DSnr[1], au4DSnr[2], au4DSnr[3]); + for (i = 0; i < 6; i++) { + au2Phi[i] = au4Phi[i]; + aucPsi[i] = au4Psi[i]; + } + for (i = 0; i < 4; i++) + aucDSnr[i] = au4DSnr[i]; + + i4Status = TxBfProfileDataWrite(prNetDev, u4ProfileIdx, + u4SubcarrierIdx, au2Phi, aucPsi, aucDSnr); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfilePnRead(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t profileIdx; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfilePnRead\n"); + + rv = kstrtoint(prInBuf, 0, &profileIdx); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfilePnRead prInBuf = %s, profileIdx = %d\n", + prInBuf, profileIdx); + i4Status = TxBfProfilePnRead(prNetDev, profileIdx); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfilePnWrite(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4ProfileIdx; + uint16_t u2bw; + uint16_t au2XSTS[12]; + int32_t rv; + + int32_t i4Status = 0; + + DBGLOG(RFTEST, ERROR, "TxBfProfilePnWrite\n"); + + rv = sscanf(prInBuf, + "%d:%hd:%hd:%hd:%hd:%hd:%hd:%hd:%hd:%hd:%hd:%hd:%hd:%hd", + &u4ProfileIdx, &u2bw, &au2XSTS[0], &au2XSTS[1], &au2XSTS[2], + &au2XSTS[3], + &au2XSTS[4], &au2XSTS[5], &au2XSTS[6], &au2XSTS[7], + &au2XSTS[8], &au2XSTS[9], &au2XSTS[10], + &au2XSTS[11]); + if (rv == 14) { + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite prInBuf = %s, ucProfileIdx = %d, u2bw = %dau2XSTS[0]:%d, au2XSTS[1]:%d, au2XSTS[2]:%d, au2XSTS[3]:%d, au2XSTS[4]:%d, au2XSTS[5]:%d, au2XSTS[6]:%d, au2XSTS[7]:%d, au2XSTS[8]:%d, au2XSTS[9]:%d, au2XSTS[10]:%d, au2XSTS[11]:%d\n", + prInBuf, u4ProfileIdx, u2bw, au2XSTS[0], + au2XSTS[1], au2XSTS[2], au2XSTS[3], au2XSTS[4], + au2XSTS[5], au2XSTS[6], au2XSTS[7], au2XSTS[8], + au2XSTS[9], au2XSTS[10], au2XSTS[11]); + + i4Status = TxBfProfilePnWrite(prNetDev, u4ProfileIdx, u2bw, + au2XSTS); + } else + return -EINVAL; + + return i4Status; +} + +/* Su_Mu:NumSta:SndInterval:WLan0:WLan1:WLan2:WLan3 */ +int Set_Trigger_Sounding_Proc(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t ucSuMu, ucNumSta, ucSndInterval, ucWLan0, ucWLan1, + ucWLan2, ucWLan3; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_Trigger_Sounding_Proc\n"); + + rv = sscanf + (prInBuf, "%x:%x:%x:%x:%x:%x:%x", &ucSuMu, &ucNumSta, + &ucSndInterval, &ucWLan0, &ucWLan1, &ucWLan2, + &ucWLan3); + if (rv == 7) { + DBGLOG(RFTEST, ERROR, + "Set_Trigger_Sounding_Proc prInBuf = %s, ucSuMu = %d, ucNumSta = %d, ucSndInterval = %d, ucWLan0 = %d, ucWLan1 = %d, ucWLan2:%d, ucWLan3:%d\n", + prInBuf, ucSuMu, ucNumSta, ucSndInterval, ucWLan0, + ucWLan1, ucWLan2, ucWLan3); + i4Status = TxBfSounding(prNetDev, ucSuMu, ucNumSta, + ucSndInterval, ucWLan0, ucWLan1, ucWLan2, ucWLan3); + } else + return -EINVAL; + + return i4Status; +} + +int Set_Stop_Sounding_Proc(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + int32_t i4Status = 0; + + DBGLOG(RFTEST, ERROR, "Set_Stop_Sounding_Proc\n"); + + i4Status = TxBfSoundingStop(prNetDev); + + return i4Status; +} + +int Set_TxBfTxApply(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4WlanId, u4ETxBf, u4ITxBf, u4MuTxBf; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "TxBfTxApply\n"); + + rv = sscanf(prInBuf, "%d:%d:%d:%d", &u4WlanId, &u4ETxBf, + &u4ITxBf, &u4MuTxBf); + if (rv == 4) { + DBGLOG(RFTEST, ERROR, + "TxBfTxApply prInBuf = %s, u4WlanId = %d, u4ETxBf = %d, u4ITxBf = %d, u4MuTxBf = %d\n", + prInBuf, u4WlanId, u4ETxBf, u4ITxBf, u4MuTxBf); + i4Status = TxBfTxApply(prNetDev, u4WlanId, u4ETxBf, u4ITxBf, + u4MuTxBf); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfManualAssoc(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + int32_t au4Mac[MAC_ADDR_LEN]; + int32_t u4Type, u4Wtbl, u4Ownmac, u4PhyMode, u4Bw, u4Nss, + u4PfmuId, u4Mode, u4Marate, u4SpeIdx, ucaid, u4Rv; + int8_t aucMac[MAC_ADDR_LEN]; + int32_t i4Status = 0; + int32_t i = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "TxBfManualAssoc\n"); + + rv = sscanf(prInBuf, + "%x:%x:%x:%x:%x:%x:%x:%d:%x:%x:%x:%x:%d:%x:%x:%x:%d:%x", + &au4Mac[0], &au4Mac[1], &au4Mac[2], &au4Mac[3], &au4Mac[4], + &au4Mac[5], + &u4Type, &u4Wtbl, &u4Ownmac, &u4PhyMode, &u4Bw, &u4Nss, + &u4PfmuId, &u4Mode, &u4Marate, &u4SpeIdx, + &ucaid, &u4Rv); + if (rv == 18) { + DBGLOG(RFTEST, ERROR, + "TxBfManualAssoc au4Mac[0] = %x, au4Mac[1] = %x, au4Mac[2] = %xau4Mac[3] = %x, au4Mac[4] = %x, au4Mac[5] = %x, u4Type = %x, u4Wtbl = %d, u4Ownmac = %x, u4PhyMode = %x u4Bw = %x, u4Nss = %x, u4PfmuId = %d, u4Mode = %x, u4Marate = %x, u4SpeIdx = %d, ucaid = %d, u4Rv = %x", + au4Mac[0], au4Mac[1], au4Mac[2], au4Mac[3], au4Mac[4], + au4Mac[5], u4Type, u4Wtbl, u4Ownmac, + u4PhyMode, u4Bw, u4Nss, u4PfmuId, u4Mode, u4Marate, + u4SpeIdx, ucaid, u4Rv); + for (i = 0; i < MAC_ADDR_LEN; i++) + aucMac[i] = au4Mac[i]; + + i4Status = + TxBfManualAssoc(prNetDev, aucMac, u4Type, u4Wtbl, + u4Ownmac, u4Mode, u4Bw, u4Nss, u4PfmuId, + u4Marate, u4SpeIdx, ucaid, u4Rv); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfPfmuMemAlloc(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t ucSuMuMode, ucWlanIdx; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "TxBfPfmuMemAlloc\n"); + + rv = sscanf(prInBuf, "%d:%d", &ucSuMuMode, &ucWlanIdx); + if (rv == 2) { + DBGLOG(RFTEST, ERROR, + "TxBfPfmuMemAlloc ucSuMuMode = %d, ucWlanIdx = %d", + ucSuMuMode, ucWlanIdx); + i4Status = TxBfPfmuMemAlloc(prNetDev, ucSuMuMode, + ucWlanIdx); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfPfmuMemRelease(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t ucWlanId; + int32_t i4Status = 0; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "TxBfPfmuMemRelease\n"); + + rv = kstrtoint(prInBuf, 0, &ucWlanId); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "TxBfPfmuMemRelease ucWlanId = %d", + ucWlanId); + i4Status = TxBfPfmuMemRelease(prNetDev, ucWlanId); + } else + return -EINVAL; + + return i4Status; +} + +int Set_DevInfoUpdate(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4OwnMacIdx, fgBand; + uint32_t OwnMacAddr[MAC_ADDR_LEN]; + uint8_t aucMacAddr[MAC_ADDR_LEN]; + int32_t i4Status = 0; + uint32_t i; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "DevInfoUpdate\n"); + + rv = sscanf + (prInBuf, "%d:%x:%x:%x:%x:%x:%x:%d", &u4OwnMacIdx, + &OwnMacAddr[0], &OwnMacAddr[1], &OwnMacAddr[2], + &OwnMacAddr[3], &OwnMacAddr[4], &OwnMacAddr[5], &fgBand); + if (rv == 8) { + DBGLOG(RFTEST, ERROR, + "DevInfoUpdate prInBuf = %s, u4OwnMacIdx = %x, fgBand = %x,OwnMacAddr[0]:%x, OwnMacAddr[1]:%x, OwnMacAddr[2]:%x, OwnMacAddr[3]:%x, OwnMacAddr[4]:%x, OwnMacAddr[5]:%x,", + prInBuf, u4OwnMacIdx, fgBand, + OwnMacAddr[0], OwnMacAddr[1], + OwnMacAddr[2], OwnMacAddr[3], + OwnMacAddr[4], OwnMacAddr[5]); + for (i = 0; i < MAC_ADDR_LEN; i++) + aucMacAddr[i] = OwnMacAddr[i]; + + i4Status = DevInfoUpdate(prNetDev, u4OwnMacIdx, fgBand, + aucMacAddr); + } else + return -EINVAL; + + return i4Status; +} + +int Set_BssInfoUpdate(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4OwnMacIdx, u4BssIdx; + uint32_t au4BssId[MAC_ADDR_LEN]; + uint8_t aucBssId[MAC_ADDR_LEN]; + int32_t i4Status = 0; + uint32_t i; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "BssInfoUpdate\n"); + + rv = sscanf + (prInBuf, "%d:%d:%x:%x:%x:%x:%x:%x", &u4OwnMacIdx, + &u4BssIdx, &au4BssId[0], &au4BssId[1], &au4BssId[2], + &au4BssId[3], &au4BssId[4], &au4BssId[5]); + if (rv == 8) { + DBGLOG(RFTEST, ERROR, + "BssInfoUpdate prInBuf = %s, u4OwnMacIdx = %x, u4BssIdx = %x,au4BssId[0]:%x, au4BssId[1]:%x, au4BssId[2]:%x, au4BssId[3]:%x, au4BssId[4]:%x, au4BssId[5]:%x,", + prInBuf, u4OwnMacIdx, u4BssIdx, au4BssId[0], au4BssId[1], + au4BssId[2], au4BssId[3], au4BssId[4], + au4BssId[5]); + for (i = 0; i < MAC_ADDR_LEN; i++) + aucBssId[i] = au4BssId[i]; + + i4Status = BssInfoUpdate(prNetDev, u4OwnMacIdx, u4BssIdx, + aucBssId); + } else + return -EINVAL; + + return i4Status; +} + +int Set_StaRecCmmUpdate(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4WlanId, u4BssId, u4Aid; + uint32_t au4MacAddr[MAC_ADDR_LEN]; + uint8_t aucMacAddr[MAC_ADDR_LEN]; + int32_t i4Status = 0; + uint32_t i; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_StaRecCmmUpdate\n"); + + rv = sscanf + (prInBuf, "%x:%x:%x:%x:%x:%x:%x:%x:%x", &u4WlanId, &u4BssId, + &u4Aid, &au4MacAddr[0], &au4MacAddr[1], + &au4MacAddr[2], &au4MacAddr[3], &au4MacAddr[4], + &au4MacAddr[5]); + if (rv == 9) { + DBGLOG(RFTEST, ERROR, + "Set_StaRecCmmUpdate prInBuf = %s, u4WlanId = %x, u4BssId = %x, u4Aid = %x,aucMacAddr[0]:%x, aucMacAddr[1]:%x, aucMacAddr[2]:%x, aucMacAddr[3]:%x, aucMacAddr[4]:%x, aucMacAddr[5]:%x,", + prInBuf, u4WlanId, u4BssId, u4Aid, au4MacAddr[0], + au4MacAddr[1], au4MacAddr[2], au4MacAddr[3], + au4MacAddr[4], au4MacAddr[5]); + for (i = 0; i < MAC_ADDR_LEN; i++) + aucMacAddr[i] = au4MacAddr[i]; + + i4Status = StaRecCmmUpdate(prNetDev, u4WlanId, u4BssId, + u4Aid, aucMacAddr); + } else + return -EINVAL; + + return i4Status; +} + +int Set_StaRecBfUpdate(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + struct STA_REC_BF_UPD_ARGUMENT rStaRecBfUpdArg; + uint8_t aucMemRow[4], aucMemCol[4]; + int32_t i4Status = 0; + uint32_t i; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_StaRecBfUpdate\n"); + + rv = sscanf(prInBuf, + "%x:%x:%x:%x:%x:%d:%d:%d:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x", + &rStaRecBfUpdArg.u4WlanId, &rStaRecBfUpdArg.u4BssId, + &rStaRecBfUpdArg.u4PfmuId, + &rStaRecBfUpdArg.u4SuMu, &rStaRecBfUpdArg.u4eTxBfCap, + &rStaRecBfUpdArg.u4NdpaRate, + &rStaRecBfUpdArg.u4NdpRate, &rStaRecBfUpdArg.u4ReptPollRate, + &rStaRecBfUpdArg.u4TxMode, + &rStaRecBfUpdArg.u4Nc, &rStaRecBfUpdArg.u4Nr, + &rStaRecBfUpdArg.u4Bw, &rStaRecBfUpdArg.u4SpeIdx, + &rStaRecBfUpdArg.u4TotalMemReq, + &rStaRecBfUpdArg.u4MemReq20M, &rStaRecBfUpdArg.au4MemRow[0], + &rStaRecBfUpdArg.au4MemCol[0], + &rStaRecBfUpdArg.au4MemRow[1], + &rStaRecBfUpdArg.au4MemCol[1], + &rStaRecBfUpdArg.au4MemRow[2], + &rStaRecBfUpdArg.au4MemCol[2], + &rStaRecBfUpdArg.au4MemRow[3], + &rStaRecBfUpdArg.au4MemCol[3]); + if (rv == 23) { + /* + *DBGLOG(RFTEST, ERROR, + *"Set_StaRecBfUpdate prInBuf = %s, u4WlanId = %x, u4BssId = %x, + * u4Aid = %x, + * aucMacAddr[0]:%x, aucMacAddr[1]:%x, aucMacAddr[2]:%x, + * aucMacAddr[3]:%x, aucMacAddr[4]:%x, aucMacAddr[5]:%x", + * prInBuf, u4OwnMacIdx, u4BssIdx, u4Aid, + * aucMacAddr[0], aucMacAddr[1], aucMacAddr[2], aucMacAddr[3], + * aucMacAddr[4], aucMacAddr[5]); + */ + for (i = 0; i < 4; i++) { + aucMemRow[i] = rStaRecBfUpdArg.au4MemRow[i]; + aucMemCol[i] = rStaRecBfUpdArg.au4MemCol[i]; + } + i4Status = StaRecBfUpdate(prNetDev, rStaRecBfUpdArg, + aucMemRow, aucMemCol); + } else + return -EINVAL; + + return i4Status; +} + +#if CFG_SUPPORT_MU_MIMO +int Set_MUGetInitMCS(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT rMuMimoActionInfo; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + + uint32_t u4groupIdx; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_MUGetInitMCS\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rv = kstrtouint(prInBuf, 0, &u4groupIdx); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "Test\n"); + DBGLOG(RFTEST, ERROR, + "Set_MUGetInitMCS prInBuf = %s, u4groupIdx = %x", + prInBuf, u4groupIdx); + + rMuMimoActionInfo.ucMuMimoCategory = MU_GET_CALC_INIT_MCS; + rMuMimoActionInfo.unMuMimoParam.rMuGetCalcInitMcs.ucgroupIdx + = u4groupIdx; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, + sizeof(rMuMimoActionInfo), + TRUE, TRUE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUCalInitMCS(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT rMuMimoActionInfo; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + + uint32_t u4NumOfUser, u4Bandwidth, u4NssOfUser0, + u4NssOfUser1, u4PfMuIdOfUser0, u4PfMuIdOfUser1, u4NumOfTxer, + u4SpeIndex, u4GroupIndex; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_MUCalInitMCS\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rv = sscanf + (prInBuf, "%x:%x:%x:%x:%x:%x:%x:%x:%x", &u4NumOfUser, + &u4Bandwidth, &u4NssOfUser0, &u4NssOfUser1, + &u4PfMuIdOfUser0, &u4PfMuIdOfUser1, &u4NumOfTxer, + &u4SpeIndex, &u4GroupIndex); + if (rv == 9) { + DBGLOG(RFTEST, ERROR, + "Set_MUCalInitMCS prInBuf = %s, u4NumOfUser = %x, u4Bandwidth = %x, u4NssOfUser0 = %x, u4NssOfUser1 = %x, u4PfMuIdOfUser0 = %x, u4PfMuIdOfUser1 = %x, u4NumOfTxer = %x, u4SpeIndex = %x, u4GroupIndex = %x", + prInBuf, u4NumOfUser, u4Bandwidth, u4NssOfUser0, + u4NssOfUser1, u4PfMuIdOfUser0, u4PfMuIdOfUser1, + u4NumOfTxer, u4SpeIndex, u4GroupIndex); + + rMuMimoActionInfo.ucMuMimoCategory = MU_SET_CALC_INIT_MCS; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucNumOfUser = + u4NumOfUser; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucBandwidth = + u4Bandwidth; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucNssOfUser0 = + u4NssOfUser0; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucNssOfUser1 = + u4NssOfUser1; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucPfMuIdOfUser0 + = u4PfMuIdOfUser0; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucPfMuIdOfUser1 + = u4PfMuIdOfUser1; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucNumOfTxer = + u4NumOfTxer; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucSpeIndex = + u4SpeIndex; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.u4GroupIndex = + u4GroupIndex; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, + sizeof(rMuMimoActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUCalLQ(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT rMuMimoActionInfo; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + + uint32_t u4NumOfUser, u4Bandwidth, u4NssOfUser0, + u4NssOfUser1, u4PfMuIdOfUser0, u4PfMuIdOfUser1, + u4NumOfTxer, u4SpeIndex, u4GroupIndex; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_MUCalLQ\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rv = sscanf + (prInBuf, "%x:%x:%x:%x:%x:%x:%x:%x:%x", &u4NumOfUser, + &u4Bandwidth, &u4NssOfUser0, &u4NssOfUser1, + &u4PfMuIdOfUser0, &u4PfMuIdOfUser1, &u4NumOfTxer, + &u4SpeIndex, &u4GroupIndex); + if (rv == 9) { + DBGLOG(RFTEST, ERROR, + "Set_MUCalLQ prInBuf = %s, u4NumOfUser = %x, u4Bandwidth = %x, u4NssOfUser0 = %x, u4NssOfUser1 = %x, u4PfMuIdOfUser0 = %x, u4PfMuIdOfUser1 = %x, u4NumOfTxer = %x, u4SpeIndex = %x, u4GroupIndex = %x", + prInBuf, u4NumOfUser, u4Bandwidth, u4NssOfUser0, + u4NssOfUser1, u4PfMuIdOfUser0, u4PfMuIdOfUser1, + u4NumOfTxer, u4SpeIndex, u4GroupIndex); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_CALC_LQ; + /* rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucType = + * u4Type; + */ + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucNumOfUser = + u4NumOfUser; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucBandwidth = + u4Bandwidth; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucNssOfUser0 = + u4NssOfUser0; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucNssOfUser1 = + u4NssOfUser1; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucPfMuIdOfUser0 + = u4PfMuIdOfUser0; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucPfMuIdOfUser1 + = u4PfMuIdOfUser1; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucNumOfTxer = + u4NumOfTxer; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucSpeIndex = + u4SpeIndex; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.u4GroupIndex = + u4GroupIndex; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, + sizeof(rMuMimoActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUGetLQ(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT rMuMimoActionInfo; + int32_t i4Status = 0; + /* UINT_32 u4Type; */ + uint32_t u4BufLen = 0; + + DBGLOG(RFTEST, ERROR, "Set_MUGetLQ\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + /* if (sscanf(prInBuf, "%x", &u4Type) == 1) + * { + * DBGLOG(RFTEST, ERROR, "Set_MUGetLQ prInBuf = %s, u4Type = %x", + * prInBuf, u4Type); + */ + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_GET_CALC_LQ; + /* rMuMimoActionInfo.unMuMimoParam.rMuGetLq.ucType = u4Type; */ + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, + sizeof(rMuMimoActionInfo), + TRUE, TRUE, TRUE, &u4BufLen); + /* } + * else + * { + * return -EINVAL; + * } + */ + + return i4Status; +} + +int Set_MUSetSNROffset(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT rMuMimoActionInfo; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + + uint32_t u4Val; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_MUSetSNROffset\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rv = kstrtoint(prInBuf, 0, &u4Val); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_MUSetSNROffset prInBuf = %s, u4Val = %x", prInBuf, + u4Val); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_SNR_OFFSET; + rMuMimoActionInfo.unMuMimoParam.rMuSetSnrOffset.ucVal = + u4Val; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, + sizeof(rMuMimoActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUSetZeroNss(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT rMuMimoActionInfo; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + + uint32_t u4Val; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_MUSetZeroNss\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rv = kstrtouint(prInBuf, 0, &u4Val); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_MUSetZeroNss prInBuf = %s, u4Val = %x", prInBuf, + u4Val); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_ZERO_NSS; + rMuMimoActionInfo.unMuMimoParam.rMuSetZeroNss.ucVal = u4Val; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, + sizeof(rMuMimoActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUSetSpeedUpLQ(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT rMuMimoActionInfo; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + + uint32_t u4Val; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_MUSetSpeedUpLQ\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rv = kstrtouint(prInBuf, 0, &u4Val); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_MUSetSpeedUpLQ prInBuf = %s, u4Val = %x", prInBuf, + u4Val); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_SPEED_UP_LQ; + rMuMimoActionInfo.unMuMimoParam.rMuSpeedUpLq.u4Val = u4Val; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, + sizeof(rMuMimoActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUSetMUTable(struct net_device *prNetDev, + uint8_t *prTable) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT rMuMimoActionInfo; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + /*uint32_t i; + *uint32_t u4Type, u4Length; + */ + + DBGLOG(RFTEST, ERROR, "Set_MUSetMUTable\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + /* if (sscanf(prInBuf, "%x:%x", &u4Type, &u4Length) == 2) */ + /* { */ + /* DBGLOG(RFTEST, ERROR, "Set_MUSetMUTable prInBuf = %s, */ + /* u4Type = %x, u4Length = %x", prInBuf, u4Type, u4Length); */ + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_MU_TABLE; + /* rMuMimoActionInfo.unMuMimoParam.rMuSetMuTable.u2Type = u4Type; */ + /* rMuMimoActionInfo.unMuMimoParam.rMuSetMuTable.u4Length = u4Length; */ + + /* for ( i = 0 ; i < NUM_MUT_NR_NUM * NUM_MUT_FEC * NUM_MUT_MCS + * * NUM_MUT_INDEX ; i++) + * { + */ + memcpy(rMuMimoActionInfo.unMuMimoParam.rMuSetMuTable.aucMetricTable, + prTable, + NUM_MUT_NR_NUM * NUM_MUT_FEC * NUM_MUT_MCS * NUM_MUT_INDEX); + /* } */ + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, + sizeof(rMuMimoActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + /* } */ + /* else */ + /* { */ + /* return -EINVAL; */ + /* } */ + + return i4Status; +} + +int Set_MUSetGroup(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT rMuMimoActionInfo; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + uint32_t i = 0; + + uint32_t aucUser0MacAddr[PARAM_MAC_ADDR_LEN], + aucUser1MacAddr[PARAM_MAC_ADDR_LEN]; + + DBGLOG(RFTEST, ERROR, "Set_MUSetGroup\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (sscanf(prInBuf, + "%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x", + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4GroupIndex, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4NumOfUser, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0Ldpc, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1Ldpc, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4ShortGI, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4Bw, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0Nss, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1Nss, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4GroupId, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0UP, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1UP, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0MuPfId, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1MuPfId, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0InitMCS, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1InitMCS, + &aucUser0MacAddr[0], + &aucUser0MacAddr[1], &aucUser0MacAddr[2], + &aucUser0MacAddr[3], &aucUser0MacAddr[4], + &aucUser0MacAddr[5], &aucUser1MacAddr[0], + &aucUser1MacAddr[1], &aucUser1MacAddr[2], + &aucUser1MacAddr[3], &aucUser1MacAddr[4], + &aucUser1MacAddr[5]) != 27) { + return -EINVAL; + } + + DBGLOG(RFTEST, ERROR, + "Set_MUSetGroup prInBuf = %s,u4GroupIndex = %d, u4NumOfUser = %d, u4User0Ldpc = %d, u4User1Ldpc = %d, u4ShortGI = %d, u4Bw = %d, u4User0Nss = %d, u4User1Nss = %d, u4GroupId = %d, u4User0UP = %d, u4User1UP = %d, u4User0MuPfId = %d, u4User1MuPfId = %d, u4User0InitMCS = %d, u4User1InitMCS = %d,aucUser0MacAddr[0] = %x, aucUser0MacAddr[1] = %x, aucUser0MacAddr[2] = %x, aucUser0MacAddr[3] = %x, aucUser0MacAddr[4] = %x, aucUser0MacAddr[5] = %x,aucUser1MacAddr[0] = %x, aucUser1MacAddr[1] = %x, aucUser1MacAddr[2] = %x, aucUser1MacAddr[3] = %x, aucUser1MacAddr[4] = %x, aucUser1MacAddr[5] = %x,", + prInBuf, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4GroupIndex, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4NumOfUser, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0Ldpc, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1Ldpc, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4ShortGI, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4Bw, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0Nss, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1Nss, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4GroupId, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0UP, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1UP, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0MuPfId, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1MuPfId, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0InitMCS, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1InitMCS, + aucUser0MacAddr[0], aucUser0MacAddr[1], + aucUser0MacAddr[2], aucUser0MacAddr[3], + aucUser0MacAddr[4], aucUser0MacAddr[5], + aucUser1MacAddr[0], aucUser1MacAddr[1], + aucUser1MacAddr[2], aucUser1MacAddr[3], + aucUser1MacAddr[4], aucUser1MacAddr[5]); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_GROUP; + for (i = 0; i < PARAM_MAC_ADDR_LEN; i++) { + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.aucUser0MacAddr[i] + = aucUser0MacAddr[i]; + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.aucUser1MacAddr[i] + = aucUser1MacAddr[i]; + } + + i4Status = kalIoctl(prGlueInfo, wlanoidMuMimoAction, &rMuMimoActionInfo, + sizeof(rMuMimoActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +int Set_MUGetQD(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT rMuMimoActionInfo; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + + uint32_t u4SubcarrierIndex, u4Length; + + DBGLOG(RFTEST, ERROR, "Set_MUGetQD\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (sscanf(prInBuf, "%x:%x", &u4SubcarrierIndex, + &u4Length) == 2) { + DBGLOG(RFTEST, ERROR, + "Set_MUGetQD prInBuf = %s, u4SubcarrierIndex = %x, u4Length = %x", + prInBuf, + u4SubcarrierIndex, u4Length); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_GET_QD; + rMuMimoActionInfo.unMuMimoParam.rMuGetQd.ucSubcarrierIndex = + u4SubcarrierIndex; + /* rMuMimoActionInfo.unMuMimoParam.rMuGetQd.u4Length = + * u4Length; + */ + /* rMuMimoActionInfo.unMuMimoParam.rMuGetQd.ucgroupIdx = + * ucgroupIdx; + */ + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, + sizeof(rMuMimoActionInfo), + TRUE, TRUE, TRUE, &u4BufLen); + } else { + return -EINVAL; + } + + return i4Status; +} + +int Set_MUSetEnable(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT rMuMimoActionInfo; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + + uint32_t u4Val; + int32_t rv; + + DBGLOG(RFTEST, ERROR, "Set_MUSetEnable\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rv = kstrtouint(prInBuf, 0, &u4Val); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, + "Set_MUSetEnable prInBuf = %s, u4Val = %x", + prInBuf, u4Val); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_ENABLE; + rMuMimoActionInfo.unMuMimoParam.rMuSetEnable.ucVal = u4Val; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, + sizeof(rMuMimoActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUSetGID_UP(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT rMuMimoActionInfo; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + + DBGLOG(RFTEST, ERROR, "Set_MUSetGID_UP\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (sscanf(prInBuf, "%x:%x:%x:%x:%x:%x", + &rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Gid[0], + &rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Gid[1], + &rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[0], + &rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[1], + &rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[2], + &rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[3]) == + 6) { + DBGLOG(RFTEST, ERROR, + "Set_MUSetGID_UP prInBuf = %s, au4Gid[0] = %x, au4Gid[1] = %x, au4Up[0] = %x, au4Up[1] = %x, au4Up[2] = %x, au4Up[3] = %x", + prInBuf, + rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Gid[0], + rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Gid[1], + rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[0], + rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[1], + rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[2], + rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[3]); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_STA_PARAM; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, + sizeof(rMuMimoActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + } else { + return -EINVAL; + } + + return i4Status; +} + +int Set_MUTriggerTx(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT rMuMimoActionInfo; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + uint32_t i, j; + + uint32_t u4IsRandomPattern, u4MsduPayloadLength0, + u4MsduPayloadLength1, u4MuPacketCount, u4NumOfSTAs; + uint32_t au4MacAddrs[2][6]; + + DBGLOG(RFTEST, ERROR, "Set_MUTriggerTx\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (sscanf(prInBuf, + "%d:%x:%x:%x:%d:%d:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x", + &u4IsRandomPattern, &u4MsduPayloadLength0, + &u4MsduPayloadLength1, &u4MuPacketCount, &u4NumOfSTAs, + &au4MacAddrs[0][0], &au4MacAddrs[0][1], &au4MacAddrs[0][2], + &au4MacAddrs[0][3], &au4MacAddrs[0][4], + &au4MacAddrs[0][5], &au4MacAddrs[1][0], &au4MacAddrs[1][1], + &au4MacAddrs[1][2], &au4MacAddrs[1][3], + &au4MacAddrs[1][4], &au4MacAddrs[1][5]) == 17) { + DBGLOG(RFTEST, ERROR, + "Set_MUTriggerTx prInBuf = %s, u4IsRandomPattern = %x, u4MsduPayloadLength0 = %x, u4MsduPayloadLength1 = %x, u4MuPacketCount = %x, u4NumOfSTAs = %x, au4MacAddrs[0][0] = %x, au4MacAddrs[0][1] = %x, au4MacAddrs[0][2] = %x, au4MacAddrs[0][3] = %x, au4MacAddrs[0][4] = %x, au4MacAddrs[0][5] = %x,au4MacAddrs[1][0] = %x, au4MacAddrs[1][1] = %x, au4MacAddrs[1][2] = %x, au4MacAddrs[1][3] = %x, au4MacAddrs[1][4] = %x, au4MacAddrs[1][5] = %x", + prInBuf, u4IsRandomPattern, u4MsduPayloadLength0, + u4MsduPayloadLength1, u4MuPacketCount, + u4NumOfSTAs, au4MacAddrs[0][0], au4MacAddrs[0][1], + au4MacAddrs[0][2], au4MacAddrs[0][3], + au4MacAddrs[0][4], au4MacAddrs[0][5], au4MacAddrs[1][0], + au4MacAddrs[1][1], au4MacAddrs[1][2], + au4MacAddrs[1][3], au4MacAddrs[1][4], au4MacAddrs[1][5]); + + rMuMimoActionInfo.ucMuMimoCategory = MU_SET_TRIGGER_MU_TX; + rMuMimoActionInfo.unMuMimoParam.rMuTriggerMuTx + .fgIsRandomPattern + = u4IsRandomPattern; + rMuMimoActionInfo.unMuMimoParam.rMuTriggerMuTx + .u4MsduPayloadLength0 + = u4MsduPayloadLength0; + rMuMimoActionInfo.unMuMimoParam.rMuTriggerMuTx + .u4MsduPayloadLength1 + = u4MsduPayloadLength1; + rMuMimoActionInfo.unMuMimoParam.rMuTriggerMuTx.u4MuPacketCount + = u4MuPacketCount; + rMuMimoActionInfo.unMuMimoParam.rMuTriggerMuTx.u4NumOfSTAs = + u4NumOfSTAs; + + for (i = 0 ; i < 2 ; i++) { + for (j = 0 ; j < PARAM_MAC_ADDR_LEN ; j++) + rMuMimoActionInfo.unMuMimoParam.rMuTriggerMuTx + .aucMacAddrs[i][j] + = au4MacAddrs[i][j]; + } + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, + sizeof(rMuMimoActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + } else { + return -EINVAL; + } + + return i4Status; +} +#endif + +#if CFG_SUPPORT_TX_BF_FPGA +int Set_TxBfProfileSwTagWrite(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + int32_t i4Status = 0; + int32_t rv; + uint32_t u4Lm, u4Nc, u4Nr, u4Bw, u4Codebook, u4Group; + + DBGLOG(RFTEST, ERROR, "Set_TxBfProfileSwTagWrite\n"); + + rv = sscanf(prInBuf, "%d-%d-%d-%d-%d-%d", &u4Lm, &u4Nr, + &u4Nc, &u4Bw, &u4Codebook, &u4Group); + + if (rv == 6) { + if ((u4Lm > 0) && (u4Group < 3) && (u4Nr < 4) && (u4Nc < 4) + && (u4Codebook < 4)) { + DBGLOG(RFTEST, ERROR, + "Set_TxBfProfileSwTagWrite prInBuf = %s, u4Lm = %d, u4Nr = %d, u4Nc = %d, u4BW = %d, u4CodeBook = %d, u4Group=%d\n", + prInBuf, u4Lm, u4Nr, u4Nc, u4Bw, u4Codebook, + u4Group); + + i4Status = TxBfPseudoTagUpdate(prNetDev, u4Lm, u4Nr, + u4Nc, u4Bw, u4Codebook, u4Group); + } else + return -EINVAL; + } else + return -EINVAL; + + return i4Status; +} +#endif +#endif + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Write Efuse. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int WriteEfuse(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + int32_t i4Status; + int32_t rv; + uint32_t addr[2]; + uint16_t addr2[2]; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv WriteEfuse, buf: %s\n", + prInBuf); + + rv = sscanf(prInBuf, "%x:%x", &addr[0], &addr[1]); + + DBGLOG(REQ, INFO, + "ATE_AGENT iwpriv WriteEfuse, prInBuf: %s\n", prInBuf); + DBGLOG(INIT, ERROR, + "ATE_AGENT iwpriv WriteEfuse :%02x:%02x\n", addr[0], + addr[1]); + + addr2[0] = (uint16_t) addr[0]; + addr2[1] = (uint16_t) addr[1]; + + if (rv == 2) + i4Status = MT_ATEWriteEfuse(prNetDev, addr2[0], addr2[1]); + else + return -EINVAL; + + return i4Status; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set Tx Power. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetTxTargetPower(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + int32_t i4Status; + int32_t rv; + int addr; + uint8_t addr2; + + DBGLOG(REQ, INFO, + "ATE_AGENT iwpriv Set Tx Target Power, buf: %s\n", prInBuf); + + /* rv = sscanf(prInBuf, "%u", &addr);*/ + rv = kstrtoint(prInBuf, 0, &addr); + + DBGLOG(REQ, INFO, + "ATE_AGENT iwpriv Set Tx Target Power, prInBuf: %s\n", + prInBuf); + DBGLOG(INIT, ERROR, + "ATE_AGENT iwpriv Set Tx Target Power :%02x\n", addr); + + addr2 = (uint8_t) addr; + + if (rv == 0) + i4Status = MT_ATESetTxTargetPower(prNetDev, addr2); + else + return -EINVAL; + + return i4Status; +} + +#if (CFG_SUPPORT_DFS_MASTER == 1) +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set RDD Report + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetRddReport(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + int32_t i4Status; + int32_t rv; + int dbdcIdx; + uint8_t ucDbdcIdx; + + DBGLOG(REQ, INFO, + "ATE_AGENT iwpriv Set RDD Report, buf: %s\n", prInBuf); + + /* rv = sscanf(prInBuf, "%u", &addr);*/ + rv = kstrtoint(prInBuf, 0, &dbdcIdx); + + DBGLOG(REQ, INFO, + "ATE_AGENT iwpriv Set RDD Report, prInBuf: %s\n", prInBuf); + DBGLOG(INIT, ERROR, + "ATE_AGENT iwpriv Set RDD Report : Band %d\n", dbdcIdx); + + if (p2pFuncGetDfsState() == DFS_STATE_INACTIVE + || p2pFuncGetDfsState() == DFS_STATE_DETECTED) { + DBGLOG(REQ, ERROR, + "RDD Report is not supported in this DFS state (inactive or deteted)\n"); + return WLAN_STATUS_NOT_SUPPORTED; + } + + if (dbdcIdx != 0 && dbdcIdx != 1) { + DBGLOG(REQ, ERROR, + "RDD index is not \"0\" or \"1\", Invalid data\n"); + return WLAN_STATUS_INVALID_DATA; + } + + ucDbdcIdx = (uint8_t) dbdcIdx; + + if (rv == 0) + i4Status = MT_ATESetRddReport(prNetDev, ucDbdcIdx); + else + return -EINVAL; + + return i4Status; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set By Pass CAC. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetByPassCac(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + int32_t i4Status; + int32_t rv; + int32_t i4ByPassCacTime; + uint32_t u4ByPassCacTime; + + DBGLOG(REQ, INFO, + "ATE_AGENT iwpriv Set By Pass Cac, buf: %s\n", prInBuf); + + rv = kstrtoint(prInBuf, 0, &i4ByPassCacTime); + + DBGLOG(REQ, INFO, + "ATE_AGENT iwpriv Set By Pass Cac, prInBuf: %s\n", prInBuf); + DBGLOG(INIT, ERROR, + "ATE_AGENT iwpriv Set By Pass Cac : %dsec\n", + i4ByPassCacTime); + + if (i4ByPassCacTime < 0) { + DBGLOG(REQ, ERROR, "Cac time < 0, Invalid data\n"); + return WLAN_STATUS_INVALID_DATA; + } + + u4ByPassCacTime = (uint32_t) i4ByPassCacTime; + + p2pFuncEnableManualCac(); + + if (rv == 0) + i4Status = p2pFuncSetDriverCacTime(u4ByPassCacTime); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to Set Radar Detect Mode. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int SetRadarDetectMode(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + int32_t i4Status; + int32_t rv; + int radarDetectMode; + uint8_t ucRadarDetectMode; + + DBGLOG(REQ, INFO, + "ATE_AGENT iwpriv Set Radar Detect Mode, buf: %s\n", + prInBuf); + + rv = kstrtoint(prInBuf, 0, &radarDetectMode); + + DBGLOG(REQ, INFO, + "ATE_AGENT iwpriv Set Radar Detect Mode, prInBuf: %s\n", + prInBuf); + DBGLOG(INIT, ERROR, + "ATE_AGENT iwpriv Set Radar Detect Mode : %d\n", + radarDetectMode); + + if (p2pFuncGetDfsState() == DFS_STATE_INACTIVE + || p2pFuncGetDfsState() == DFS_STATE_DETECTED) { + DBGLOG(REQ, ERROR, + "RDD Report is not supported in this DFS state (inactive or deteted)\n"); + return WLAN_STATUS_NOT_SUPPORTED; + } + + if (radarDetectMode != 0 && radarDetectMode != 1) { + DBGLOG(REQ, ERROR, + "Radar Detect Mode is not \"0\" or \"1\", Invalid data\n"); + return WLAN_STATUS_INVALID_DATA; + } + + ucRadarDetectMode = (uint8_t) radarDetectMode; + + p2pFuncSetRadarDetectMode(ucRadarDetectMode); + + if (rv == 0) + i4Status = MT_ATESetRadarDetectMode(prNetDev, + ucRadarDetectMode); + else + return -EINVAL; + + return i4Status; +} + +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to search the corresponding ATE agent + * function. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf A pointer to the command string buffer + * \param[in] u4InBufLen The length of the buffer + * \param[out] None + * + * \retval 0 On success. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int AteCmdSetHandle(struct net_device *prNetDev, + uint8_t *prInBuf, uint32_t u4InBufLen) +{ + uint8_t *this_char, *value; + struct ATE_PRIV_CMD *prAtePrivCmd; + int32_t i4Status = 0; + + while ((this_char = strsep((char **)&prInBuf, + ",")) != NULL) { + if (!*this_char) + continue; + DBGLOG(RFTEST, ERROR, "ATE_AGENT iwpriv this_char = %s\n", + this_char); + DBGLOG(RFTEST, INFO, "ATE_AGENT iwpriv this_char = %s\n", + this_char); + + value = strchr(this_char, '='); + if (value != NULL) + *value++ = 0; + + DBGLOG(REQ, INFO, "ATE_AGENT iwpriv cmd = %s, value = %s\n", + this_char, value); + + for (prAtePrivCmd = rAtePrivCmdTable; prAtePrivCmd->name; + prAtePrivCmd++) { + if (!strcmp(this_char, prAtePrivCmd->name)) { + /* FALSE: Set private failed then return Invalid + * argument + */ + if (prAtePrivCmd->set_proc(prNetDev, value) + != 0) + i4Status = -EINVAL; + break; /*Exit for loop. */ + } + } + + if (prAtePrivCmd->name == NULL) { /*Not found argument */ + i4Status = -EINVAL; + break; + } + } + return i4Status; +} +#endif /*CFG_SUPPORT_QA_TOOL */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_bow.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_bow.c new file mode 100644 index 0000000000000..06105b2a7a7d6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_bow.c @@ -0,0 +1,1173 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "debug.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "precomp.h" +#include +#include "bss.h" + +#if CFG_ENABLE_BT_OVER_WIFI + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* @FIXME if there is command/event with payload length > 28 */ +#define MAX_BUFFER_SIZE (64) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +uint32_t g_u4PrevSysTime; +uint32_t g_u4CurrentSysTime; +uint32_t g_arBowRevPalPacketTime[32]; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/* forward declarations */ +static ssize_t bow_ampc_read(IN struct file *filp, IN char __user *buf, IN size_t size, IN OUT loff_t *ppos); + +static ssize_t bow_ampc_write(IN struct file *filp, OUT const char __user *buf, IN size_t size, IN OUT loff_t *ppos); + +static long bow_ampc_ioctl(IN struct file *filp, IN unsigned int cmd, IN OUT unsigned long arg); + +static unsigned int bow_ampc_poll(IN struct file *filp, IN poll_table * wait); + +static int bow_ampc_open(IN struct inode *inodep, IN struct file *filp); + +static int bow_ampc_release(IN struct inode *inodep, IN struct file *filp); + +/* character file operations */ +static const struct file_operations bow_ampc_fops = { + /* .owner = THIS_MODULE, */ + .read = bow_ampc_read, + .write = bow_ampc_write, + .unlocked_ioctl = bow_ampc_ioctl, + .poll = bow_ampc_poll, + .open = bow_ampc_open, + .release = bow_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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t glRegisterAmpc(IN struct GLUE_INFO *prGlueInfo) +{ + ASSERT(prGlueInfo); + + DBGLOG(BOW, INFO, "Register for character device to communicate with 802.11 PAL.\n"); + + if (prGlueInfo->rBowInfo.fgIsRegistered == TRUE) + return FALSE; +#if 0 + /* 1. allocate major number dynamically */ + + if (alloc_chrdev_region(&(prGlueInfo->rBowInfo.u4DeviceNumber), 0, /* first minor number */ + 1, /* number */ + GLUE_BOW_DEVICE_NAME) != 0) + + return FALSE; +#endif + +#if 1 + +#if defined(CONFIG_AMPC_CDEV_NUM) + prGlueInfo->rBowInfo.u4DeviceNumber = MKDEV(CONFIG_AMPC_CDEV_NUM, 0); +#else + prGlueInfo->rBowInfo.u4DeviceNumber = MKDEV(226, 0); +#endif + + if (register_chrdev_region(prGlueInfo->rBowInfo.u4DeviceNumber, 1, /* number */ + GLUE_BOW_DEVICE_NAME) != 0) + + return FALSE; +#endif + + /* 2. spin-lock initialization */ + /* spin_lock_init(&(prGlueInfo->rBowInfo.rSpinLock)); */ + + /* 3. initialize kfifo */ +#if 0 + prGlueInfo->rBowInfo.prKfifo = kfifo_alloc(GLUE_BOW_KFIFO_DEPTH, + GFP_KERNEL, + &(prGlueInfo->rBowInfo.rSpinLock)); +#endif + 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), &bow_ampc_fops); + /* prGlueInfo->rBowInfo.cdev.owner = THIS_MODULE; */ + prGlueInfo->rBowInfo.cdev.ops = &bow_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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t glUnregisterAmpc(IN struct GLUE_INFO *prGlueInfo) +{ + ASSERT(prGlueInfo); + + DBGLOG(BOW, INFO, "Unregister character device for communicating with 802.11 PAL.\n"); + + if (prGlueInfo->rBowInfo.fgIsRegistered == FALSE) + return FALSE; + + prGlueInfo->rBowInfo.fgIsRegistered = FALSE; + + /* 1. free netdev if necessary */ +#if CFG_BOW_SEPARATE_DATA_PATH + kalUninitBowDevice(prGlueInfo); +#endif + + /* 2. removal of character device */ + cdev_del(&(prGlueInfo->rBowInfo.cdev)); + + /* 3. free kfifo */ +/* kfifo_free(prGlueInfo->rBowInfo.prKfifo); */ + kfifo_free(&(prGlueInfo->rBowInfo.rKfifo)); +/* prGlueInfo->rBowInfo.prKfifo = NULL; */ +/* prGlueInfo->rBowInfo.rKfifo = NULL; */ + + /* 4. free device number */ + unregister_chrdev_region(prGlueInfo->rBowInfo.u4DeviceNumber, 1); + + return TRUE; + +} /* end of glUnregisterAmpc */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief read handler for character device to communicate with 802.11 PAL +* +* \param[in] +* \return +* Follows Linux Character Device Interface +* +*/ +/*----------------------------------------------------------------------------*/ +static ssize_t bow_ampc_read(IN struct file *filp, IN char __user *buf, IN size_t size, IN OUT loff_t *ppos) +{ + uint8_t aucBuffer[MAX_BUFFER_SIZE]; + ssize_t retval; + + struct GLUE_INFO *prGlueInfo; + + prGlueInfo = (struct GLUE_INFO *) (filp->private_data); + + ASSERT(prGlueInfo); + + DBGLOG(BOW, INFO, "BoW EVENT read.\n"); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return -EFAULT; + /* size check */ +/* if(kfifo_len(prGlueInfo->rBowInfo.prKfifo) >= size) */ + if (kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)) >= size) + retval = size; + else + retval = kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)); +/* retval = kfifo_len(prGlueInfo->rBowInfo.prKfifo); */ + +/* kfifo_get(prGlueInfo->rBowInfo.prKfifo, aucBuffer, retval); */ +/* kfifo_out(prGlueInfo->rBowInfo.prKfifo, aucBuffer, retval); */ + if (!(kfifo_out(&(prGlueInfo->rBowInfo.rKfifo), aucBuffer, retval))) + retval = -EIO; + + 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 bow_ampc_write(IN struct file *filp, OUT const char __user *buf, IN size_t size, IN OUT loff_t *ppos) +{ + uint8_t i; + + uint8_t aucBuffer[MAX_BUFFER_SIZE]; + struct BT_OVER_WIFI_COMMAND *prCmd; + struct GLUE_INFO *prGlueInfo; + + prGlueInfo = (struct GLUE_INFO *) (filp->private_data); + ASSERT(prGlueInfo); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return -EFAULT; + + if (size > MAX_BUFFER_SIZE) + return -EINVAL; + else if (copy_from_user(aucBuffer, buf, size)) + return -EIO; + + 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"); + + prCmd = (struct BT_OVER_WIFI_COMMAND *) aucBuffer; + + DBGLOG(BOW, EVENT, "AMP write content payload length : %d.\n", prCmd->rHeader.u2PayloadLength); + + DBGLOG(BOW, EVENT, "AMP write content header length : %d.\n", sizeof(struct BT_OVER_WIFI_COMMAND_HEADER)); + + /* size check */ + if (prCmd->rHeader.u2PayloadLength + sizeof(struct BT_OVER_WIFI_COMMAND_HEADER) != size) { + DBGLOG(BOW, EVENT, "Wrong CMD total length.\n"); + + 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 bow_ampc_ioctl(IN struct file *filp, IN unsigned int cmd, IN OUT unsigned long arg) +{ + int err = 0; + struct GLUE_INFO *prGlueInfo; + + prGlueInfo = (struct GLUE_INFO *) (filp->private_data); + + ASSERT(prGlueInfo); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return -EFAULT; + /* permission check */ + if (_IOC_DIR(cmd) & _IOC_READ) + err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)); + else if (_IOC_DIR(cmd) & _IOC_WRITE) + err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)); + if (err) + return -EFAULT; + + /* no ioctl is implemented yet */ + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief ioctl handler for character device to communicate with 802.11 PAL +* +* \param[in] +* \return +* Follows Linux Character Device Interface +* +*/ +/*----------------------------------------------------------------------------*/ +static unsigned int bow_ampc_poll(IN struct file *filp, IN poll_table * wait) +{ + unsigned int retval; + struct GLUE_INFO *prGlueInfo; + + prGlueInfo = (struct GLUE_INFO *) (filp->private_data); + + ASSERT(prGlueInfo); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return -EFAULT; + + poll_wait(filp, &prGlueInfo->rBowInfo.outq, wait); + + retval = (POLLOUT | POLLWRNORM); /* always accepts incoming command packets */ + +/* DBGLOG(BOW, EVENT, ("bow_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, ("bow_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 bow_ampc_open(IN struct inode *inodep, IN struct file *filp) +{ + struct GLUE_INFO *prGlueInfo; + struct GL_BOW_INFO *prBowInfo; + + DBGLOG(BOW, INFO, "in %s\n", __func__); + + prBowInfo = container_of(inodep->i_cdev, struct GL_BOW_INFO, cdev); + ASSERT(prBowInfo); + + prGlueInfo = container_of(prBowInfo, struct GLUE_INFO, 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 bow_ampc_release(IN struct inode *inodep, IN struct file *filp) +{ + struct GLUE_INFO *prGlueInfo; + + prGlueInfo = (struct GLUE_INFO *) (filp->private_data); + + DBGLOG(BOW, INFO, "in %s\n", __func__); + + ASSERT(prGlueInfo); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to indicate event for Bluetooth over Wi-Fi +* +* \param[in] +* prGlueInfo +* prEvent +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +void kalIndicateBOWEvent(IN struct GLUE_INFO *prGlueInfo, IN struct BT_OVER_WIFI_EVENT *prEvent) +{ + size_t u4AvailSize, u4EventSize; + + ASSERT(prGlueInfo); + ASSERT(prEvent); + + /* check device */ + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return; +#if 0 + u4AvailSize = GLUE_BOW_KFIFO_DEPTH - kfifo_len(prGlueInfo->rBowInfo.prKfifo); +#endif + u4AvailSize = GLUE_BOW_KFIFO_DEPTH - kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)); + + u4EventSize = prEvent->rHeader.u2PayloadLength + sizeof(struct BT_OVER_WIFI_EVENT_HEADER); + + /* 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), (uint8_t *) prEvent, u4EventSize); + wake_up_interruptible(&(prGlueInfo->rBowInfo.outq)); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Bluetooth-over-Wi-Fi state from glue layer +* +* \param[in] +* prGlueInfo +* rPeerAddr +* \return +* ENUM_BOW_DEVICE_STATE +*/ +/*----------------------------------------------------------------------------*/ +enum ENUM_BOW_DEVICE_STATE kalGetBowState(IN struct GLUE_INFO *prGlueInfo, IN uint8_t aucPeerAddress[6]) +{ + uint8_t i; + + ASSERT(prGlueInfo); + + DBGLOG(BOW, EVENT, "kalGetBowState.\n"); + + for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { + if (EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr, aucPeerAddress) == 0) { + 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]); + + 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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalSetBowState(IN struct GLUE_INFO *prGlueInfo, IN enum ENUM_BOW_DEVICE_STATE eBowState, IN uint8_t aucPeerAddress[6]) +{ + uint8_t i; + + ASSERT(prGlueInfo); + DBGLOG(BOW, EVENT, "kalSetBowState, aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + aucPeerAddress[0], + aucPeerAddress[1], aucPeerAddress[2], aucPeerAddress[3], aucPeerAddress[4], aucPeerAddress[5]); + + for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { + if (EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr, aucPeerAddress) == 0) { + prGlueInfo->rBowInfo.aeState[i] = eBowState; + + 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]); + + 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 ENUM_BOW_DEVICE_STATE kalGetBowGlobalState(IN struct GLUE_INFO *prGlueInfo) +{ + uint32_t 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 +*/ +/*----------------------------------------------------------------------------*/ +uint32_t kalGetBowFreqInKHz(IN struct GLUE_INFO *prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->rBowInfo.u4FreqInKHz; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Bluetooth-over-Wi-Fi role +* +* \param[in] +* prGlueInfo +* +* \return +* 0: Responder +* 1: Initiator +*/ +/*----------------------------------------------------------------------------*/ +uint8_t kalGetBowRole(IN struct GLUE_INFO *prGlueInfo, IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN]) +{ + uint32_t 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 struct GLUE_INFO *prGlueInfo, IN uint8_t ucRole, IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN]) +{ + uint32_t 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) { + /* Henry, 0 : Responder, 1 : Initiator */ + prGlueInfo->rBowInfo.aucRole[i] = ucRole; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to get available Bluetooth-over-Wi-Fi physical link number +* +* \param[in] +* prGlueInfo +* \return +* UINT_32 +* how many physical links are aviailable +*/ +/*----------------------------------------------------------------------------*/ +uint8_t kalGetBowAvailablePhysicalLinkCount(IN struct GLUE_INFO *prGlueInfo) +{ + uint8_t i; + uint8_t 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 + DBGLOG(BOW, EVENT, "kalGetBowAvailablePhysicalLinkCount, ucLinkCount, %c.\n", ucLinkCount); +#endif + + return ucLinkCount; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This inline function is to extract some packet information for BoW +* +* @param prGlueInfo Pointer to the glue structure +* @param prNdisPacket Packet descriptor +* @param pfgIs1X 802.1x packet or not +* +* @retval TRUE Success to extract information +* @retval FALSE Fail to extract correct information +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalBowFrameClassifier(IN struct GLUE_INFO *prGlueInfo, IN void *prPacket, OUT u_int8_t *pfgIs1X) +{ + uint32_t u4PacketLen; + uint16_t u2EtherTypeLen; + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + uint8_t *aucLookAheadBuf = NULL; + uint8_t ucEthTypeLenOffset = ETHER_HEADER_LEN - ETHER_TYPE_LEN; + uint8_t *pucNextProtocol = NULL; + uint8_t aucLLC[] = ETH_LLC; + uint8_t aucSnapBtOui[] = ETH_SNAP_BT_SIG_OUI; + uint8_t ucMinLength = ucEthTypeLenOffset + ETHER_TYPE_LEN + ETH_LLC_LEN + ETH_SNAP_LEN; + + DEBUGFUNC("kalQoSFrameClassifierAndPacketInfo"); + + u4PacketLen = prSkb->len; + + if (u4PacketLen < ETHER_HEADER_LEN) { + DBGLOG(INIT, WARN, "Invalid Ether packet length: %lu\n", u4PacketLen); + return FALSE; + } + + aucLookAheadBuf = prSkb->data; + + *pfgIs1X = FALSE; + + /* 4 <0> Obtain Ether Type/Len */ + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[ucEthTypeLenOffset], &u2EtherTypeLen); + + /* 4 <1> Skip 802.1Q header (VLAN Tagging) */ + if (u2EtherTypeLen == ETH_P_VLAN) { + ucEthTypeLenOffset += ETH_802_1Q_HEADER_LEN; + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[ucEthTypeLenOffset], &u2EtherTypeLen); + } + /* 4 <2> Obtain next protocol pointer */ + pucNextProtocol = &aucLookAheadBuf[ucEthTypeLenOffset + ETHER_TYPE_LEN]; + + /* 4 <3> Handle ethernet format */ + if (u2EtherTypeLen > ETH_802_3_MAX_LEN) { + /* Not BoW frame */ + return FALSE; + } + /* 4 <4> Check for PAL (BT over Wi-Fi) */ + /* BoW LLC/SNAP header check */ + if (u4PacketLen >= ucMinLength && + !kalMemCmp(pucNextProtocol, aucLLC, ETH_LLC_LEN) && + !kalMemCmp(pucNextProtocol + ETH_LLC_LEN, aucSnapBtOui, ETH_SNAP_OUI_LEN)) { + uint16_t u2LocalCode; + + WLAN_GET_FIELD_BE16(pucNextProtocol + ETH_LLC_LEN + ETH_SNAP_OUI_LEN, &u2LocalCode); + + if (u2LocalCode == BOW_PROTOCOL_ID_SECURITY_FRAME) + *pfgIs1X = TRUE; + + return TRUE; + } + + return FALSE; +} /* end of kalBoWFrameClassifier() */ + +#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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + + ASSERT(prDev); + + prGlueInfo = *((struct GLUE_INFO **) 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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + + ASSERT(prDev); + + prGlueInfo = *((struct GLUE_INFO **) 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; +}; + +#if 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) +{ + struct GLUE_INFO *prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + + struct QUE_ENTRY *prQueueEntry = NULL; + struct QUE *prTxQueue = NULL; + uint16_t u2QueueIdx = 0; + uint8_t ucDSAP, ucSSAP, ucControl; + uint8_t aucOUI[3]; + uint8_t *aucLookAheadBuf = NULL; + uint8_t ucBssIndex; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prSkb); + ASSERT(prDev); + ASSERT(prGlueInfo); + + aucLookAheadBuf = prSkb->data; + + ucDSAP = *(uint8_t *) &aucLookAheadBuf[ETH_LLC_OFFSET]; + ucSSAP = *(uint8_t *) &aucLookAheadBuf[ETH_LLC_OFFSET + 1]; + ucControl = *(uint8_t *) &aucLookAheadBuf[ETH_LLC_OFFSET + 2]; + aucOUI[0] = *(uint8_t *) &aucLookAheadBuf[ETH_SNAP_OFFSET]; + aucOUI[1] = *(uint8_t *) &aucLookAheadBuf[ETH_SNAP_OFFSET + 1]; + aucOUI[2] = *(uint8_t *) &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)) { + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(BOW, TRACE, "GLUE_FLAG_HALT skip tx\n"); + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } + + GLUE_SET_PKT_FLAG_PAL(prSkb); + + ucBssIndex = wlanGetBssIdxByNetInterface(prGlueInfo, NET_DEV_BOW_IDX); + + GLUE_SET_PKT_BSS_IDX(prSkb, ucBssIndex); + + prQueueEntry = (struct QUE_ENTRY *) GLUE_GET_PKT_QUEUE_ENTRY(prSkb); + prTxQueue = &prGlueInfo->rTxQueue; + + if (wlanProcessSecurityFrame(prGlueInfo->prAdapter, (void *) 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[ucBssIndex][u2QueueIdx]); + + if (prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex][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; +} +#else +/*----------------------------------------------------------------------------*/ +/*! + * \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) +{ + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) NULL; + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t ucBssIndex; + u_int8_t fgIs1x; + + ASSERT(prSkb); + ASSERT(prDev); + +#if 1 + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) netdev_priv(prDev); + prGlueInfo = prNetDevPrivate->prGlueInfo; + ucBssIndex = prNetDevPrivate->ucBssIdx; +#else + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + + ucBssIndex = wlanGetBssIdxByNetInterface(prGlueInfo, NET_DEV_BOW_IDX); +#endif + + kalResetPacket(prGlueInfo, (void *) prSkb); + + /* Discard frames not generated by PAL */ + /* Parsing BOW frame info */ + if (!kalBowFrameClassifier(prGlueInfo, (void *) prSkb, &fgIs1x)) { + /* Cannot extract packet */ + DBGLOG(BOW, INFO, "Invalid BOW frame, skip Tx\n"); + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } + + if (fgIs1x) + GLUE_SET_PKT_FLAG(prSkb, ENUM_PKT_1X); + + if (kalHardStartXmit(prSkb, prDev, prGlueInfo, ucBssIndex) == WLAN_STATUS_SUCCESS) { + /* Successfully enqueue to Tx queue */ + /* Successfully enqueue to Tx queue */ + } + + /* For Linux, we'll always return OK FLAG, because we'll free this skb by ourself */ + return NETDEV_TX_OK; +} +#endif + +/* 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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalInitBowDevice(IN struct GLUE_INFO *prGlueInfo, IN const char *prDevName) +{ + struct ADAPTER *prAdapter; + struct GL_HIF_INFO *prHif; + uint8_t rMacAddr[PARAM_MAC_ADDR_LEN]; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPriv = (struct NETDEV_PRIVATE_GLUE_INFO *) NULL; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->rBowInfo.fgIsRegistered == TRUE); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prHif = &prGlueInfo->rHifInfo; + ASSERT(prHif); + + prChipInfo = prGlueInfo->prAdapter->chip_info; + + if (prGlueInfo->rBowInfo.fgIsNetRegistered == FALSE) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) + prGlueInfo->rBowInfo.prDevHandler = + alloc_netdev_mq(sizeof(struct GLUE_INFO *), prDevName, + NET_NAME_PREDICTABLE, ether_setup, CFG_MAX_TXQ_NUM); +#else + prGlueInfo->rBowInfo.prDevHandler = + alloc_netdev_mq(sizeof(struct GLUE_INFO *), prDevName, ether_setup, CFG_MAX_TXQ_NUM); +#endif + if (!prGlueInfo->rBowInfo.prDevHandler) + return FALSE; + + /* 1. setup netdev */ + /* 1.1 Point to shared glue structure */ + /* *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->rBowInfo.prDevHandler)) = prGlueInfo; */ + prNetDevPriv = (struct NETDEV_PRIVATE_GLUE_INFO *) netdev_priv(prGlueInfo->rBowInfo.prDevHandler); + prNetDevPriv->prGlueInfo = prGlueInfo; + + /* 1.2 fill hardware address */ + COPY_MAC_ADDR(rMacAddr, prAdapter->rMyMacAddr); + rMacAddr[0] |= 0x2; /* change to local administrated address */ + kalMemCopy(prGlueInfo->rBowInfo.prDevHandler->dev_addr, rMacAddr, ETH_ALEN); + kalMemCopy(prGlueInfo->rBowInfo.prDevHandler->perm_addr, + prGlueInfo->rBowInfo.prDevHandler->dev_addr, ETH_ALEN); + + /* 1.3 register callback functions */ + prGlueInfo->rBowInfo.prDevHandler->needed_headroom += + NIC_TX_DESC_AND_PADDING_LENGTH + prChipInfo->txd_append_size; + prGlueInfo->rBowInfo.prDevHandler->netdev_ops = &bow_netdev_ops; + +#if defined(_HIF_SDIO) && (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); + + /* 2.1 bind NetDev pointer to NetDev index */ + wlanBindBssIdxToNetInterface(prGlueInfo, bowInit(prAdapter), + (void *) prGlueInfo->rBowInfo.prDevHandler); + prNetDevPriv->ucBssIdx = prAdapter->rWifiVar.rBowFsmInfo.ucBssIndex; + /* wlanBindNetInterface(prGlueInfo, NET_DEV_BOW_IDX, */ + /* (PVOID)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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalUninitBowDevice(IN struct GLUE_INFO *prGlueInfo) +{ + struct ADAPTER *prAdapter; + + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + /* ASSERT(prGlueInfo->rBowInfo.fgIsRegistered == TRUE); */ + + if (prGlueInfo->rBowInfo.fgIsNetRegistered == TRUE) { + + prGlueInfo->rBowInfo.fgIsNetRegistered = FALSE; + + bowUninit(prAdapter); + + if (netif_carrier_ok(prGlueInfo->rBowInfo.prDevHandler)) + netif_carrier_off(prGlueInfo->rBowInfo.prDevHandler); + + netif_tx_stop_all_queues(prGlueInfo->rBowInfo.prDevHandler); + + /* netdevice unregistration & free */ + unregister_netdev(prGlueInfo->rBowInfo.prDevHandler); + free_netdev(prGlueInfo->rBowInfo.prDevHandler); + prGlueInfo->rBowInfo.prDevHandler = NULL; + + return TRUE; + + } else { + return FALSE; + } +} + +#endif /* CFG_BOW_SEPARATE_DATA_PATH */ +#endif /* CFG_ENABLE_BT_OVER_WIFI */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_cfg80211.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_cfg80211.c new file mode 100644 index 0000000000000..288388e685454 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_cfg80211.c @@ -0,0 +1,7584 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** 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. + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "gl_os.h" +#include "debug.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "precomp.h" +#include +#include +#include +#include "gl_cfg80211.h" +#include "gl_vendor.h" +#include "gl_p2p_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 + ******************************************************************************* + */ + +/******************************************************************************* + * 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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + enum ENUM_PARAM_OP_MODE eOpMode; + uint32_t u4BufLen; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, INFO, "mtk_cfg80211_change_iface\n"); + + 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, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "set infrastructure mode error:%x\n", + rStatus); + + /* reset wpa info */ + prGlueInfo->rWpaInfo.u4WpaVersion = + IW_AUTH_WPA_VERSION_DISABLED; + prGlueInfo->rWpaInfo.u4KeyMgmt = 0; + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; +#if CFG_SUPPORT_802_11W + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; + prGlueInfo->rWpaInfo.ucRSNMfpCap = 0; + prGlueInfo->rWpaInfo.u4CipherGroupMgmt = IW_AUTH_CIPHER_NONE; +#endif + + ndev->ieee80211_ptr->iftype = type; + + 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) +{ + struct PARAM_KEY rKey; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + int32_t i4Rslt = -EINVAL; + uint32_t u4BufLen = 0; + uint8_t tmp1[8], tmp2[8]; +#if CFG_SUPPORT_REPLAY_DETECTION + struct GL_DETECT_REPLAY_INFO *prDetRplyInfo = NULL; + uint8_t ucCheckZeroKey = 0; + uint8_t i = 0; +#endif + + const uint8_t aucBCAddr[] = BC_MAC_ADDR; + /* const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; */ + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(RSN, INFO, "mtk_cfg80211_add_key\n"); +#if DBG + if (mac_addr) { + DBGLOG(RSN, INFO, + "keyIdx = %d pairwise = %d mac = " MACSTR "\n", + key_index, pairwise, MAC2STR(mac_addr)); + } else { + DBGLOG(RSN, INFO, "keyIdx = %d pairwise = %d null mac\n", + key_index, pairwise); + } + DBGLOG(RSN, INFO, "Cipher = %x\n", params->cipher); + DBGLOG_MEM8(RSN, INFO, params->key, params->key_len); +#endif + + kalMemZero(&rKey, sizeof(struct PARAM_KEY)); + + rKey.u4KeyIndex = key_index; + + if (params->cipher) { + switch (params->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + rKey.ucCipher = CIPHER_SUITE_WEP40; + break; + case WLAN_CIPHER_SUITE_WEP104: + rKey.ucCipher = CIPHER_SUITE_WEP104; + break; +#if 0 + case WLAN_CIPHER_SUITE_WEP128: + rKey.ucCipher = CIPHER_SUITE_WEP128; + break; +#endif + case WLAN_CIPHER_SUITE_TKIP: + rKey.ucCipher = CIPHER_SUITE_TKIP; + break; + case WLAN_CIPHER_SUITE_CCMP: + rKey.ucCipher = CIPHER_SUITE_CCMP; + break; +#if 0 + case WLAN_CIPHER_SUITE_GCMP: + rKey.ucCipher = CIPHER_SUITE_GCMP; + break; + case WLAN_CIPHER_SUITE_CCMP_256: + rKey.ucCipher = CIPHER_SUITE_CCMP256; + break; +#endif + case WLAN_CIPHER_SUITE_SMS4: + rKey.ucCipher = CIPHER_SUITE_WPI; + break; + case WLAN_CIPHER_SUITE_AES_CMAC: + rKey.ucCipher = CIPHER_SUITE_BIP; + break; + default: + ASSERT(FALSE); + } + } + + if (pairwise) { + ASSERT(mac_addr); + rKey.u4KeyIndex |= BIT(31); + rKey.u4KeyIndex |= BIT(30); + COPY_MAC_ADDR(rKey.arBSSID, mac_addr); + + /* reset KCK, KEK, EAPOL Replay counter */ + kalMemZero(prGlueInfo->rWpaInfo.aucKek, NL80211_KEK_LEN); + kalMemZero(prGlueInfo->rWpaInfo.aucKck, NL80211_KCK_LEN); + kalMemZero(prGlueInfo->rWpaInfo.aucReplayCtr, + NL80211_REPLAY_CTR_LEN); + } else { /* Group key */ + COPY_MAC_ADDR(rKey.arBSSID, aucBCAddr); + } + + if (params->key) { + if (params->key_len > sizeof(rKey.aucKeyMaterial)) + return -EINVAL; + +#if CFG_SUPPORT_REPLAY_DETECTION + for (i = 0; i < params->key_len; i++) { + if (params->key[i] == 0x00) + ucCheckZeroKey++; + } + + if (ucCheckZeroKey == params->key_len) + return 0; +#endif + + kalMemCopy(rKey.aucKeyMaterial, params->key, + params->key_len); + if (rKey.ucCipher == CIPHER_SUITE_TKIP) { + kalMemCopy(tmp1, ¶ms->key[16], 8); + kalMemCopy(tmp2, ¶ms->key[24], 8); + kalMemCopy(&rKey.aucKeyMaterial[16], tmp2, 8); + kalMemCopy(&rKey.aucKeyMaterial[24], tmp1, 8); + } + } + + rKey.ucBssIdx = + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + + rKey.u4KeyLength = params->key_len; + rKey.u4Length = ((unsigned long) &(((struct PARAM_KEY *) + 0)->aucKeyMaterial)) + rKey.u4KeyLength; + +#if CFG_SUPPORT_REPLAY_DETECTION + prDetRplyInfo = &prGlueInfo->prDetRplyInfo; + + if ((!pairwise) && + ((params->cipher == WLAN_CIPHER_SUITE_TKIP) || + (params->cipher == WLAN_CIPHER_SUITE_CCMP))) { + + if ((prDetRplyInfo->ucCurKeyId == key_index) && + (!kalMemCmp(prDetRplyInfo->aucKeyMaterial, + params->key, params->key_len))) { + DBGLOG(RSN, TRACE, + "M3/G1, KeyID and KeyValue equal.\n"); + DBGLOG(RSN, TRACE, + "gtk reinstall, so no update BC/MC PN.\n"); + } else { + kalMemCopy( + prDetRplyInfo->arReplayPNInfo[key_index].auPN, + params->seq, params->seq_len); + prDetRplyInfo->ucCurKeyId = key_index; + prDetRplyInfo->u4KeyLength = params->key_len; + kalMemCopy(prDetRplyInfo->aucKeyMaterial, + params->key, params->key_len); + } + + prDetRplyInfo->fgKeyRscFresh = TRUE; + } +#endif + + rStatus = kalIoctl(prGlueInfo, wlanoidSetAddKey, &rKey, + rKey.u4Length, FALSE, FALSE, TRUE, &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 *) + ) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if 1 + DBGLOG(INIT, INFO, "--> %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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct PARAM_REMOVE_KEY rRemoveKey; + uint32_t u4BufLen = 0; + int32_t i4Rslt = -EINVAL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + if (g_u4HaltFlag) { + DBGLOG(RSN, WARN, "wlan is halt, skip key deletion\n"); + return WLAN_STATUS_FAILURE; + } + + DBGLOG(RSN, TRACE, "mtk_cfg80211_del_key\n"); +#if DBG + if (mac_addr) { + DBGLOG(RSN, TRACE, + "keyIdx = %d pairwise = %d mac = " MACSTR "\n", + key_index, pairwise, MAC2STR(mac_addr)); + } else { + DBGLOG(RSN, TRACE, "keyIdx = %d pairwise = %d null mac\n", + key_index, pairwise); + } +#endif + + kalMemZero(&rRemoveKey, sizeof(struct PARAM_REMOVE_KEY)); + rRemoveKey.u4KeyIndex = key_index; + rRemoveKey.u4Length = sizeof(struct PARAM_REMOVE_KEY); + if (mac_addr) { + COPY_MAC_ADDR(rRemoveKey.arBSSID, mac_addr); + rRemoveKey.u4KeyIndex |= BIT(30); + } + + if ((prGlueInfo->prAdapter == NULL) + || (prGlueInfo->prAdapter->prAisBssInfo == NULL)) + return i4Rslt; + + rRemoveKey.ucBssIdx = + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetRemoveKey, &rRemoveKey, + rRemoveKey.u4Length, FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(RSN, WARN, "remove key error:%x\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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_DEFAULT_KEY rDefaultKey; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + int32_t i4Rst = -EINVAL; + uint32_t u4BufLen = 0; + u_int8_t fgDef = FALSE, fgMgtDef = FALSE; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + /* For STA, should wep set the default key !! */ + DBGLOG(RSN, INFO, "mtk_cfg80211_set_default_key\n"); +#if DBG + DBGLOG(RSN, INFO, + "keyIdx = %d unicast = %d multicast = %d\n", key_index, + unicast, multicast); +#endif + + rDefaultKey.ucKeyID = key_index; + rDefaultKey.ucUnicast = unicast; + rDefaultKey.ucMulticast = multicast; + if (rDefaultKey.ucUnicast && !rDefaultKey.ucMulticast) + return WLAN_STATUS_SUCCESS; + + if (rDefaultKey.ucUnicast && rDefaultKey.ucMulticast) + fgDef = TRUE; + + if (!rDefaultKey.ucUnicast && rDefaultKey.ucMulticast) + fgMgtDef = TRUE; + + rDefaultKey.ucBssIdx = + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetDefaultKey, &rDefaultKey, + sizeof(struct PARAM_DEFAULT_KEY), + FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus == WLAN_STATUS_SUCCESS) + i4Rst = 0; + + return i4Rst; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for getting station information such as + * RSSI + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *ndev, const u8 *mac, + struct station_info *sinfo) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint8_t arBssid[PARAM_MAC_ADDR_LEN]; + uint32_t u4BufLen, u4Rate; + int32_t i4Rssi; + struct PARAM_GET_STA_STATISTICS rQueryStaStatistics; + uint32_t u4TotalError; + struct net_device_stats *prDevStats; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, TRACE, "mtk_cfg80211_get_station\n"); + kalMemZero(arBssid, MAC_ADDR_LEN); + wlanQueryInformation(prGlueInfo->prAdapter, wlanoidQueryBssid, + &arBssid[0], sizeof(arBssid), &u4BufLen); + + /* 1. check input MAC address */ + /* On Android O, this might be wlan0 address */ + if (UNEQUAL_MAC_ADDR(arBssid, mac) + && UNEQUAL_MAC_ADDR( + prGlueInfo->prAdapter->rWifiVar.aucMacAddress, 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 */ + if (prGlueInfo->eParamMediaStateIndicated != + PARAM_MEDIA_STATE_CONNECTED) { + /* not connected */ + DBGLOG(REQ, WARN, "not yet connected\n"); + return 0; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryLinkSpeed, &u4Rate, + sizeof(u4Rate), TRUE, FALSE, FALSE, &u4BufLen); + +#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE + sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); +#else + sinfo->filled |= STATION_INFO_TX_BITRATE; +#endif + if ((rStatus != WLAN_STATUS_SUCCESS) || (u4Rate == 0)) { + /* unable to retrieve link speed */ + DBGLOG(REQ, WARN, "last link speed\n"); + sinfo->txrate.legacy = prGlueInfo->u4LinkSpeedCache; + } else { + /* convert from 100bps to 100kbps */ + sinfo->txrate.legacy = u4Rate / 1000; + prGlueInfo->u4LinkSpeedCache = u4Rate / 1000; + } + + /* 3. fill RSSI */ + rStatus = kalIoctl(prGlueInfo, wlanoidQueryRssi, &i4Rssi, + sizeof(i4Rssi), TRUE, FALSE, FALSE, &u4BufLen); + +#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE + sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); +#else + sinfo->filled |= STATION_INFO_SIGNAL; +#endif + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, + "Query RSSI failed, use last RSSI %d\n", + prGlueInfo->i4RssiCache); + sinfo->signal = prGlueInfo->i4RssiCache ? + prGlueInfo->i4RssiCache : + PARAM_WHQL_RSSI_INITIAL_DBM; + } else if (i4Rssi == PARAM_WHQL_RSSI_MIN_DBM || + i4Rssi == PARAM_WHQL_RSSI_MAX_DBM) { + DBGLOG(REQ, WARN, + "RSSI abnormal, use last RSSI %d\n", + prGlueInfo->i4RssiCache); + sinfo->signal = prGlueInfo->i4RssiCache ? + prGlueInfo->i4RssiCache : i4Rssi; + } else { + sinfo->signal = i4Rssi; /* dBm */ + prGlueInfo->i4RssiCache = i4Rssi; + } + + /* Get statistics from net_dev */ + prDevStats = (struct net_device_stats *)kalGetStats(ndev); + + if (prDevStats) { + /* 4. fill RX_PACKETS */ +#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE + sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS); + sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES64); +#else + sinfo->filled |= STATION_INFO_RX_PACKETS; + sinfo->filled |= NL80211_STA_INFO_RX_BYTES64; +#endif + sinfo->rx_packets = prDevStats->rx_packets; + sinfo->rx_bytes = prDevStats->rx_bytes; + + /* 5. fill TX_PACKETS */ +#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE + sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS); + sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES64); +#else + sinfo->filled |= STATION_INFO_TX_PACKETS; + sinfo->filled |= NL80211_STA_INFO_TX_BYTES64; +#endif + sinfo->tx_packets = prDevStats->tx_packets; + sinfo->tx_bytes = prDevStats->tx_bytes; + + /* 6. fill TX_FAILED */ + kalMemZero(&rQueryStaStatistics, + sizeof(rQueryStaStatistics)); + COPY_MAC_ADDR(rQueryStaStatistics.aucMacAddr, arBssid); + rQueryStaStatistics.ucReadClear = TRUE; + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryStaStatistics, + &rQueryStaStatistics, + sizeof(rQueryStaStatistics), + TRUE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, + "link speed=%u, rssi=%d, unable to retrieve link speed,status=%u\n", + sinfo->txrate.legacy, sinfo->signal, rStatus); + } else { + DBGLOG(REQ, INFO, + "link speed=%u, rssi=%d, BSSID:[" MACSTR + "], TxFail=%u, TxTimeOut=%u, TxOK=%u, RxOK=%u\n", + sinfo->txrate.legacy, sinfo->signal, + MAC2STR(arBssid), + rQueryStaStatistics.u4TxFailCount, + rQueryStaStatistics.u4TxLifeTimeoutCount, + sinfo->tx_packets, sinfo->rx_packets); + + u4TotalError = rQueryStaStatistics.u4TxFailCount + + rQueryStaStatistics.u4TxLifeTimeoutCount; + prDevStats->tx_errors += u4TotalError; + } +#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE + sinfo->filled |= BIT(NL80211_STA_INFO_TX_FAILED); +#else + sinfo->filled |= STATION_INFO_TX_FAILED; +#endif + sinfo->tx_failed = prDevStats->tx_errors; + } + + return 0; +} +#else +int mtk_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac, + struct station_info *sinfo) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint8_t arBssid[PARAM_MAC_ADDR_LEN]; + uint32_t u4BufLen, u4Rate; + int32_t i4Rssi; + struct PARAM_GET_STA_STATISTICS rQueryStaStatistics; + uint32_t u4TotalError; + struct net_device_stats *prDevStats; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + DBGLOG(REQ, TRACE, "mtk_cfg80211_get_station\n"); + + 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 */ + if (prGlueInfo->eParamMediaStateIndicated != + PARAM_MEDIA_STATE_CONNECTED) { + /* not connected */ + DBGLOG(REQ, WARN, "not yet connected\n"); + } else { + rStatus = kalIoctl(prGlueInfo, wlanoidQueryLinkSpeed, &u4Rate, + sizeof(u4Rate), TRUE, FALSE, FALSE, &u4BufLen); + + sinfo->filled |= STATION_INFO_TX_BITRATE; + + if ((rStatus != WLAN_STATUS_SUCCESS) || (u4Rate == 0)) { + /* unable to retrieve link speed */ + DBGLOG(REQ, WARN, "last link speed\n"); + sinfo->txrate.legacy = prGlueInfo->u4LinkSpeedCache; + } else { + /* convert from 100bps to 100kbps */ + sinfo->txrate.legacy = u4Rate / 1000; + prGlueInfo->u4LinkSpeedCache = u4Rate / 1000; + } + } + + /* 3. fill RSSI */ + if (prGlueInfo->eParamMediaStateIndicated != + PARAM_MEDIA_STATE_CONNECTED) { + /* not connected */ + DBGLOG(REQ, WARN, "not yet connected\n"); + } else { + rStatus = kalIoctl(prGlueInfo, wlanoidQueryRssi, &i4Rssi, + sizeof(i4Rssi), TRUE, FALSE, FALSE, &u4BufLen); + + sinfo->filled |= STATION_INFO_SIGNAL; + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, + "Query RSSI failed, use last RSSI %d\n", + prGlueInfo->i4RssiCache); + sinfo->signal = prGlueInfo->i4RssiCache ? + prGlueInfo->i4RssiCache : + PARAM_WHQL_RSSI_INITIAL_DBM; + } else if (i4Rssi == PARAM_WHQL_RSSI_MIN_DBM || + i4Rssi == PARAM_WHQL_RSSI_MAX_DBM) { + DBGLOG(REQ, WARN, + "RSSI abnormal, use last RSSI %d\n", + prGlueInfo->i4RssiCache); + sinfo->signal = prGlueInfo->i4RssiCache ? + prGlueInfo->i4RssiCache : i4Rssi; + } else { + sinfo->signal = i4Rssi; /* dBm */ + prGlueInfo->i4RssiCache = i4Rssi; + } + } + + /* Get statistics from net_dev */ + prDevStats = (struct net_device_stats *)kalGetStats(ndev); + if (prDevStats) { + /* 4. fill RX_PACKETS */ + sinfo->filled |= STATION_INFO_RX_PACKETS; + sinfo->rx_packets = prDevStats->rx_packets; + + /* 5. fill TX_PACKETS */ + sinfo->filled |= STATION_INFO_TX_PACKETS; + sinfo->tx_packets = prDevStats->tx_packets; + + /* 6. fill TX_FAILED */ + kalMemZero(&rQueryStaStatistics, + sizeof(rQueryStaStatistics)); + COPY_MAC_ADDR(rQueryStaStatistics.aucMacAddr, arBssid); + rQueryStaStatistics.ucReadClear = TRUE; + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryStaStatistics, + &rQueryStaStatistics, + sizeof(rQueryStaStatistics), + TRUE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, + "link speed=%u, rssi=%d, unable to get sta statistics: status=%u\n", + sinfo->txrate.legacy, sinfo->signal, rStatus); + } else { + DBGLOG(REQ, INFO, + "link speed=%u, rssi=%d, BSSID=[" MACSTR + "], TxFailCount=%d, LifeTimeOut=%d\n", + sinfo->txrate.legacy, sinfo->signal, + MAC2STR(arBssid), + rQueryStaStatistics.u4TxFailCount, + rQueryStaStatistics.u4TxLifeTimeoutCount); + + u4TotalError = rQueryStaStatistics.u4TxFailCount + + rQueryStaStatistics.u4TxLifeTimeoutCount; + prDevStats->tx_errors += u4TotalError; + } + sinfo->filled |= STATION_INFO_TX_FAILED; + sinfo->tx_failed = prDevStats->tx_errors; + } + + return 0; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for getting statistics for Link layer + * statistics + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_get_link_statistics(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac, + struct station_info *sinfo) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint8_t arBssid[PARAM_MAC_ADDR_LEN]; + uint32_t u4BufLen; + int32_t i4Rssi; + struct PARAM_GET_STA_STATISTICS rQueryStaStatistics; + struct PARAM_GET_BSS_STATISTICS rQueryBssStatistics; + struct net_device_stats *prDevStats; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = + (struct NETDEV_PRIVATE_GLUE_INFO *) NULL; + uint8_t ucBssIndex; + + prGlueInfo = (struct GLUE_INFO *) 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 RSSI */ + if (prGlueInfo->eParamMediaStateIndicated != + PARAM_MEDIA_STATE_CONNECTED) { + /* not connected */ + DBGLOG(REQ, WARN, "not yet connected\n"); + } else { + rStatus = kalIoctl(prGlueInfo, wlanoidQueryRssi, &i4Rssi, + sizeof(i4Rssi), TRUE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "unable to retrieve rssi\n"); + } + + /* Get statistics from net_dev */ + prDevStats = (struct net_device_stats *)kalGetStats(ndev); + + /*3. get link layer statistics from Driver and FW */ + if (prDevStats) { + /* 3.1 get per-STA link statistics */ + kalMemZero(&rQueryStaStatistics, + sizeof(rQueryStaStatistics)); + COPY_MAC_ADDR(rQueryStaStatistics.aucMacAddr, arBssid); + rQueryStaStatistics.ucLlsReadClear = + FALSE; /* dont clear for get BSS statistic */ + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryStaStatistics, + &rQueryStaStatistics, + sizeof(rQueryStaStatistics), + TRUE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, + "unable to retrieve per-STA link statistics\n"); + + /*3.2 get per-BSS link statistics */ + if (rStatus == WLAN_STATUS_SUCCESS) { + /* get Bss Index from ndev */ + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(ndev); + ASSERT(prNetDevPrivate->prGlueInfo == prGlueInfo); + ucBssIndex = prNetDevPrivate->ucBssIdx; + + kalMemZero(&rQueryBssStatistics, + sizeof(rQueryBssStatistics)); + rQueryBssStatistics.ucBssIndex = ucBssIndex; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryBssStatistics, + &rQueryBssStatistics, + sizeof(rQueryBssStatistics), + TRUE, FALSE, TRUE, &u4BufLen); + } else { + DBGLOG(REQ, WARN, + "unable to retrieve per-BSS link statistics\n"); + } + + } + + 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 cfg80211_scan_request *request) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint32_t i, j, u4BufLen; + struct PARAM_SCAN_REQUEST_ADV *prScanRequest; + uint32_t num_ssid = 0; + uint32_t old_num_ssid = 0; + uint32_t u4ValidIdx = 0; + uint32_t wildcard_flag = 0; +#if (CFG_SUPPORT_QA_TOOL == 1) || (CFG_SUPPORT_LOWLATENCY_MODE == 1) + struct ADAPTER *prAdapter = NULL; +#endif + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + if (!prGlueInfo) { + DBGLOG(REQ, ERROR, "prGlueInfo is NULL"); + return -EINVAL; + } + + DBGLOG(REQ, TRACE, "mtk_cfg80211_scan\n"); +#if (CFG_SUPPORT_QA_TOOL == 1) || (CFG_SUPPORT_LOWLATENCY_MODE == 1) + prAdapter = prGlueInfo->prAdapter; + if (prGlueInfo->prAdapter == NULL) { + DBGLOG(REQ, ERROR, "prGlueInfo->prAdapter is NULL"); + return -EINVAL; + } +#endif + +#if CFG_SUPPORT_QA_TOOL + if (prAdapter->fgIcapMode) { + DBGLOG(REQ, ERROR, "prAdapter->fgIcapMode == TRUE\n"); + return -EBUSY; + } +#endif + + kalScanReqLog(request); + + /* check if there is any pending scan/sched_scan not yet finished */ + if (prGlueInfo->prScanRequest != NULL) { + DBGLOG(REQ, ERROR, "prGlueInfo->prScanRequest != NULL\n"); + return -EBUSY; + } + +#if CFG_SUPPORT_LOWLATENCY_MODE + if (!prGlueInfo->prAdapter->fgEnCfg80211Scan + && PARAM_MEDIA_STATE_CONNECTED + == kalGetMediaStateIndicated(prGlueInfo)) { + DBGLOG(REQ, INFO, + "mtk_cfg80211_scan LowLatency reject scan\n"); + return -EBUSY; + } +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + +#if CFG_SUPPORT_SCAN_CACHE_RESULT + prGlueInfo->scanCache.prGlueInfo = prGlueInfo; + prGlueInfo->scanCache.prRequest = request; + prGlueInfo->scanCache.n_channels = (uint32_t) request->n_channels; + if (isScanCacheDone(&prGlueInfo->scanCache) == TRUE) + return 0; +#endif /* CFG_SUPPORT_SCAN_CACHE_RESULT */ + + prScanRequest = kalMemAlloc(sizeof(struct PARAM_SCAN_REQUEST_ADV), + VIR_MEM_TYPE); + if (prScanRequest == NULL) { + DBGLOG(REQ, ERROR, "alloc scan request fail\n"); + return -ENOMEM; + + } + kalMemZero(prScanRequest, + sizeof(struct PARAM_SCAN_REQUEST_ADV)); + + if (request->n_ssids == 0) { + prScanRequest->u4SsidNum = 0; + prScanRequest->ucScanType = SCAN_TYPE_PASSIVE_SCAN; + } else if ((request->ssids) && (request->n_ssids > 0) + && (request->n_ssids <= (SCN_SSID_MAX_NUM + 1))) { + num_ssid = (uint32_t)request->n_ssids; + old_num_ssid = (uint32_t)request->n_ssids; + u4ValidIdx = 0; + for (i = 0; i < request->n_ssids; i++) { + if ((request->ssids[i].ssid[0] == 0) + || (request->ssids[i].ssid_len == 0)) { + /* remove if this is a wildcard scan */ + num_ssid--; + wildcard_flag |= (1 << i); + DBGLOG(REQ, TRACE, "i=%d, wildcard scan\n", i); + continue; + } + COPY_SSID(prScanRequest->rSsid[u4ValidIdx].aucSsid, + prScanRequest->rSsid[u4ValidIdx].u4SsidLen, + request->ssids[i].ssid, + request->ssids[i].ssid_len); + if (prScanRequest->rSsid[u4ValidIdx].u4SsidLen > + ELEM_MAX_LEN_SSID) { + prScanRequest->rSsid[u4ValidIdx].u4SsidLen = + ELEM_MAX_LEN_SSID; + } + DBGLOG(REQ, INFO, + "i=%d, u4ValidIdx=%d, Ssid=%s, SsidLen=%d\n", + i, u4ValidIdx, + prScanRequest->rSsid[u4ValidIdx].aucSsid, + prScanRequest->rSsid[u4ValidIdx].u4SsidLen); + + u4ValidIdx++; + if (u4ValidIdx == SCN_SSID_MAX_NUM) { + DBGLOG(REQ, TRACE, "SCN_SSID_MAX_NUM\n"); + break; + } + } + /* real SSID number to firmware */ + prScanRequest->u4SsidNum = u4ValidIdx; + prScanRequest->ucScanType = SCAN_TYPE_ACTIVE_SCAN; + } else { + DBGLOG(REQ, ERROR, "request->n_ssids:%d\n", + request->n_ssids); + kalMemFree(prScanRequest, + sizeof(struct PARAM_SCAN_REQUEST_ADV), VIR_MEM_TYPE); + return -EINVAL; + } + DBGLOG(REQ, INFO, + "mtk_cfg80211_scan(), n_ssids=%d, num_ssid=(%u->%u), wildcard=0x%X\n", + request->n_ssids, old_num_ssid, num_ssid, wildcard_flag); + + /* Set channel info */ + if (request->n_channels > MAXIMUM_OPERATION_CHANNEL_LIST) { + prScanRequest->u4ChannelNum = 0; + DBGLOG(REQ, INFO, + "Channel list %u exceed maximum support.\n", + request->n_channels); + } else { + j = 0; + for (i = 0; i < request->n_channels; i++) { + uint32_t u4channel = + nicFreq2ChannelNum(request->channels[i]->center_freq * + 1000); + if (u4channel == 0) { + DBGLOG(REQ, WARN, "Wrong Channel[%d] freq=%u\n", + i, request->channels[i]->center_freq); + continue; + } + prScanRequest->arChannel[j].ucChannelNum = u4channel; + switch ((request->channels[i])->band) { + case KAL_BAND_2GHZ: + prScanRequest->arChannel[j].eBand = BAND_2G4; + break; + case KAL_BAND_5GHZ: + prScanRequest->arChannel[j].eBand = BAND_5G; + break; + default: + DBGLOG(REQ, WARN, "UNKNOWN Band %d(chnl=%u)\n", + request->channels[i]->band, + u4channel); + prScanRequest->arChannel[j].eBand = BAND_NULL; + break; + } + j++; + } + prScanRequest->u4ChannelNum = j; + } + DBGLOG(REQ, INFO, "n_ssids(%d==>%u) n_channel(%u==>%u)\n", + request->n_ssids, num_ssid, request->n_channels, + prScanRequest->u4ChannelNum); + + if (kalScanParseRandomMac(request->wdev->netdev, + request, prScanRequest->aucRandomMac)) { + prScanRequest->ucScnFuncMask |= ENUM_SCN_RANDOM_MAC_EN; + } + + if (request->ie_len > 0) { + prScanRequest->u4IELength = request->ie_len; + prScanRequest->pucIE = (uint8_t *) (request->ie); + } + + prGlueInfo->prScanRequest = request; + rStatus = kalIoctl(prGlueInfo, wlanoidSetBssidListScanAdv, + prScanRequest, sizeof(struct PARAM_SCAN_REQUEST_ADV), + FALSE, FALSE, FALSE, &u4BufLen); + + kalMemFree(prScanRequest, + sizeof(struct PARAM_SCAN_REQUEST_ADV), VIR_MEM_TYPE); + if (rStatus != WLAN_STATUS_SUCCESS) { + prGlueInfo->prScanRequest = NULL; + DBGLOG(REQ, WARN, "scan error:%x\n", rStatus); + return -EINVAL; + } + + return 0; +} +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for abort an ongoing scan. The driver + * shall indicate the status of the scan through cfg80211_scan_done() + * + * @param wiphy - pointer of wireless hardware description + * wdev - pointer of wireless device state + * + */ +/*----------------------------------------------------------------------------*/ +void mtk_cfg80211_abort_scan(struct wiphy *wiphy, + struct wireless_dev *wdev) +{ + uint32_t u4SetInfoLen = 0; + uint32_t rStatus; + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + scanlog_dbg(LOG_SCAN_ABORT_REQ_K2D, INFO, "mtk_cfg80211_abort_scan\n"); + + rStatus = kalIoctl(prGlueInfo, + wlanoidAbortScan, + NULL, 1, FALSE, FALSE, TRUE, &u4SetInfoLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, ERROR, "wlanoidAbortScan fail 0x%x\n", rStatus); +} + +static uint8_t wepBuf[48]; +#if CFG_SUPPORT_CFG80211_AUTH +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting auth to + * the ESS with the specified parameters + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_auth(struct wiphy *wiphy, struct net_device *ndev, + struct cfg80211_auth_request *req) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint32_t u4BufLen; + struct PARAM_CONNECT rNewSsid; + enum ENUM_PARAM_OP_MODE eOpMode; + struct CONNECTION_SETTINGS *prConnSettings = NULL; +#if CFG_SUPPORT_REPLAY_DETECTION + struct GL_DETECT_REPLAY_INFO *prDetRplyInfo = NULL; +#endif + struct PARAM_WEP *prWepKey; + /*Is auth parameter needed to be updated to AIS.*/ + uint8_t fgNewAuthParam = FALSE; + struct STA_RECORD *prStaRec = NULL; +#if CFG_SUPPORT_802_11R + uint32_t u4InfoBufLen = 0; +#endif + struct cfg80211_connect_params connect; + struct cfg80211_connect_params *sme = &connect; + const struct cfg80211_bss_ies *ies; + const uint8_t *ssidie = NULL; + uint8_t ssid_len = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if KERNEL_VERSION(4, 10, 0) > CFG80211_VERSION_CODE + if (req->sae_data_len != 0) + DBGLOG(REQ, INFO, "[wlan] mtk_cfg80211_auth %p %zu\n", + req->sae_data, req->sae_data_len); +#else + if (req->auth_data_len != 0) + DBGLOG(REQ, INFO, "[wlan] mtk_cfg80211_auth %p %zu\n", + req->auth_data, req->auth_data_len); +#endif + + DBGLOG(REQ, INFO, "auth to BSS [" MACSTR "]\n", + MAC2STR((uint8_t *)req->bss->bssid)); + DBGLOG(REQ, INFO, "auth_type:%d\n", req->auth_type); + + prConnSettings = &prGlueInfo->prAdapter->rWifiVar.rConnSettings; + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + memset(&connect, 0, sizeof(connect)); + sme->bssid = req->bss->bssid; + if (mtk_Netdev_To_RoleIdx(prGlueInfo, ndev, + &prConnSettings->ucRoleIdx) < 0) + return -EINVAL; + + prConnSettings->fgIsP2pConn = TRUE; + ies = rcu_access_pointer(req->bss->ies); + if (!ies) + return false; + + ssidie = cfg80211_find_ie(WLAN_EID_SSID, ies->data, ies->len); + if (!ssidie) + return false; + + ssid_len = ssidie[1]; + sme->ssid = ssidie + 2; + sme->ssid_len = ssid_len; + COPY_SSID(prConnSettings->aucSSID, prConnSettings->ucSSIDLen, + sme->ssid, sme->ssid_len); + prConnSettings->fgIsSendAssoc = FALSE; + return mtk_p2p_cfg80211_connect(wiphy, ndev, sme); + } + + /* <1>Set OP mode */ + 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, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "wlanoidSetInfrastructureMode fail 0x%x\n", + rStatus); + return -EFAULT; + } + + /*<2> Set Auth data */ + prConnSettings->ucAuthDataLen = 0; +#if KERNEL_VERSION(4, 10, 0) > CFG80211_VERSION_CODE + if (req->sae_data_len != 0) { + if (req->sae_data_len > AUTH_DATA_MAX_LEN) { + DBGLOG(INIT, WARN, + "request auth with unexpected length:%d\n", + req->sae_data_len); + return -EFAULT; + } + + kalMemCopy(prConnSettings->aucAuthData, req->sae_data, + req->sae_data_len); + prConnSettings->ucAuthDataLen = req->sae_data_len; + + DBGLOG(INIT, INFO, + "Dump auth data in connectSettings, auth len:%d\n", + prConnSettings->ucAuthDataLen); + DBGLOG_MEM8(REQ, INFO, prConnSettings->aucAuthData, + req->sae_data_len); + } +#else + if (req->auth_data_len != 0) { + if (req->auth_data_len > AUTH_DATA_MAX_LEN) { + DBGLOG(INIT, WARN, + "request auth with unexpected length:%d\n", + req->auth_data_len); + return -EFAULT; + } + + kalMemCopy(prConnSettings->aucAuthData, req->auth_data, + req->auth_data_len); + prConnSettings->ucAuthDataLen = req->auth_data_len; + + DBGLOG(INIT, INFO, + "Dump auth data in connectSettings, auth len:%d\n", + prConnSettings->ucAuthDataLen); + DBGLOG_MEM8(REQ, INFO, prConnSettings->aucAuthData, + req->auth_data_len); + } +#endif + + /*<3> Set ChannelNum */ + if (req->bss->channel->center_freq) { + prConnSettings->ucChannelNum = + nicFreq2ChannelNum( + req->bss->channel->center_freq * 1000); + DBGLOG(RSN, INFO, + "set prConnSettings->ucChannelNum:%d\n", + prConnSettings->ucChannelNum); + } else { + prConnSettings->ucChannelNum = 0; + DBGLOG(RSN, INFO, + "req->bss->channel->center_freq is NULL.\n"); + } + +#if CFG_SUPPORT_REPLAY_DETECTION + /* reset Detect replay information */ + prDetRplyInfo = &prGlueInfo->prDetRplyInfo; + kalMemZero(prDetRplyInfo, sizeof(struct GL_DETECT_REPLAY_INFO)); +#endif + + /* Reset WPA info */ + prGlueInfo->rWpaInfo.u4AuthAlg = 0; + + switch (req->auth_type) { + case NL80211_AUTHTYPE_OPEN_SYSTEM: + if (!(prGlueInfo->rWpaInfo.u4AuthAlg & AUTH_TYPE_OPEN_SYSTEM)) + fgNewAuthParam = TRUE; + prGlueInfo->rWpaInfo.u4AuthAlg |= AUTH_TYPE_OPEN_SYSTEM; + break; + case NL80211_AUTHTYPE_SHARED_KEY: + if (!(prGlueInfo->rWpaInfo.u4AuthAlg & AUTH_TYPE_SHARED_KEY)) + fgNewAuthParam = TRUE; + prGlueInfo->rWpaInfo.u4AuthAlg |= AUTH_TYPE_SHARED_KEY; + break; + case NL80211_AUTHTYPE_SAE: + if (!(prGlueInfo->rWpaInfo.u4AuthAlg & AUTH_TYPE_SAE)) + fgNewAuthParam = TRUE; + prGlueInfo->rWpaInfo.u4AuthAlg |= AUTH_TYPE_SAE; + break; +#if CFG_SUPPORT_802_11R + case NL80211_AUTHTYPE_FT: + if (!(prGlueInfo->rWpaInfo.u4AuthAlg + & AUTH_TYPE_FAST_BSS_TRANSITION)) + fgNewAuthParam = TRUE; + prGlueInfo->rWpaInfo.u4AuthAlg |= AUTH_TYPE_FAST_BSS_TRANSITION; + break; +#endif + default: + DBGLOG(REQ, WARN, + "Auth type: %ld not support, use default OPEN system\n", + req->auth_type); + prGlueInfo->rWpaInfo.u4AuthAlg |= AUTH_TYPE_OPEN_SYSTEM; + break; + } + DBGLOG(REQ, INFO, "Auth Algorithm : %ld\n", + prGlueInfo->rWpaInfo.u4AuthAlg); + + if (req->key_len != 0) { + /* NL80211 only set the Tx wep key while connect, + * the max 4 wep key set prior via add key cmd + */ + + if (!(prGlueInfo->rWpaInfo.u4AuthAlg & AUTH_TYPE_SHARED_KEY)) + DBGLOG(REQ, WARN, "Auth Algorithm : %ld with wep key\n", + prGlueInfo->rWpaInfo.u4AuthAlg); + + prWepKey = (struct PARAM_WEP *) wepBuf; + + kalMemZero(prWepKey, sizeof(struct PARAM_WEP)); + prWepKey->u4Length = + OFFSET_OF(struct PARAM_WEP, aucKeyMaterial) + + req->key_len; + prWepKey->u4KeyLength = (uint32_t) req->key_len; + prWepKey->u4KeyIndex = (uint32_t) req->key_idx; + prWepKey->u4KeyIndex |= IS_TRANSMIT_KEY; + if (prWepKey->u4KeyLength > MAX_KEY_LEN) { + DBGLOG(REQ, WARN, "Too long key length (%u)\n", + prWepKey->u4KeyLength); + return -EINVAL; + } + kalMemCopy(prWepKey->aucKeyMaterial, req->key, + prWepKey->u4KeyLength); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetAddWep, prWepKey, + prWepKey->u4Length, FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "wlanoidSetAddWep fail 0x%x\n", + rStatus); + return -EFAULT; + } + } + kalMemZero(&rNewSsid, sizeof(struct PARAM_CONNECT)); + + if (rNewSsid.pucBssid != (uint8_t *)req->bss->bssid) { + fgNewAuthParam = TRUE; + rNewSsid.pucBssid = (uint8_t *)req->bss->bssid; + } +#if CFG_SUPPORT_802_11R + if (req->auth_type == NL80211_AUTHTYPE_FT) { + rNewSsid.pucSsid = prGlueInfo->prAdapter + ->rWlanInfo.rCurrBssId.rSsid.aucSsid; + rNewSsid.u4SsidLen = prGlueInfo->prAdapter + ->rWlanInfo.rCurrBssId.rSsid.u4SsidLen; + rStatus = kalIoctl(prGlueInfo, wlanoidUpdateFtIes, + (void *)(uint8_t *)req->ie, req->ie_len, + FALSE, FALSE, FALSE, &u4InfoBufLen); + DBGLOG(REQ, TRACE, + "wlanoidUpdateFtIes rStatus 0x%x\n", rStatus); + } +#endif + /* rNewSsid.pucSsid = (uint8_t *)sme->ssid;*/ + /* rNewSsid.u4SsidLen = sme->ssid_len;*/ + + DBGLOG(REQ, INFO, "auth to BSS [" MACSTR "],UpperReq [" MACSTR "]\n", + MAC2STR(rNewSsid.pucBssid), + MAC2STR((uint8_t *)req->bss->bssid)); + + prConnSettings->fgIsSendAssoc = FALSE; + if (!prConnSettings->fgIsConnInitialized || fgNewAuthParam) { + /* [TODO] to consider if bssid/auth_alg changed + * (need to update to AIS) + */ + if (fgNewAuthParam) + DBGLOG(REQ, WARN, "auth param update\n"); + rStatus = kalIoctl(prGlueInfo, wlanoidSetConnect, + (void *)&rNewSsid, sizeof(struct PARAM_CONNECT), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set SSID:%x\n", rStatus); + return -EINVAL; + } + } else { + /* skip join initial flow + * when it has been completed with the same auth parameters + */ + prStaRec = cnmGetStaRecByAddress(prGlueInfo->prAdapter, + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex, + rNewSsid.pucBssid); + if (prStaRec) + saaSendAuthAssoc(prGlueInfo->prAdapter, prStaRec); + else + DBGLOG(REQ, WARN, + "can't send auth since can't find StaRec\n"); + } + + return 0; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint32_t u4BufLen; + enum ENUM_WEP_STATUS eEncStatus; + enum ENUM_PARAM_AUTH_MODE eAuthMode; + uint32_t cipher; + struct PARAM_CONNECT rNewSsid; + u_int8_t fgCarryWPSIE = FALSE; + enum ENUM_PARAM_OP_MODE eOpMode; + uint32_t i, u4AkmSuite = 0; + struct DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY + *prEntry; + struct CONNECTION_SETTINGS *prConnSettings = NULL; +#if CFG_SUPPORT_REPLAY_DETECTION + struct GL_DETECT_REPLAY_INFO *prDetRplyInfo = NULL; +#endif + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, STATE, "[wlan] mtk_cfg80211_connect %p %zu %d\n", + sme->ie, sme->ie_len, sme->auth_type); + prConnSettings = + &prGlueInfo->prAdapter->rWifiVar.rConnSettings; + + 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, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, + "wlanoidSetInfrastructureMode fail 0x%x\n", rStatus); + return -EFAULT; + } + + /* after set operation mode, key table are cleared */ + +#if CFG_SUPPORT_REPLAY_DETECTION + /* reset Detect replay information */ + prDetRplyInfo = &prGlueInfo->prDetRplyInfo; + kalMemZero(prDetRplyInfo, + sizeof(struct GL_DETECT_REPLAY_INFO)); +#endif + + /* <1> 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; + prGlueInfo->rWpaInfo.fgPrivacyInvoke = FALSE; +#if CFG_SUPPORT_802_11W + prGlueInfo->rWpaInfo.u4CipherGroupMgmt = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.ucRSNMfpCap = RSN_AUTH_MFP_DISABLED; + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; + prGlueInfo->rWpaInfo.ucRSNMfpCap = RSN_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; + case NL80211_AUTHTYPE_FT: + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_FT; + break; + default: + /* NL80211 only set the Tx wep key while connect */ + if (sme->key_len != 0) + prGlueInfo->rWpaInfo.u4AuthAlg = + IW_AUTH_ALG_OPEN_SYSTEM | + IW_AUTH_ALG_SHARED_KEY; + else + prGlueInfo->rWpaInfo.u4AuthAlg = + IW_AUTH_ALG_OPEN_SYSTEM; + break; + } + + if (sme->crypto.n_ciphers_pairwise) { + DBGLOG(RSN, INFO, "[wlan] cipher pairwise (%x)\n", + sme->crypto.ciphers_pairwise[0]); + + 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; +#if CFG_SUPPORT_SUITB + case WLAN_CIPHER_SUITE_BIP_GMAC_256: + prGlueInfo->rWpaInfo.u4CipherPairwise = + IW_AUTH_CIPHER_GCMP256; + break; + case WLAN_CIPHER_SUITE_GCMP_256: + prGlueInfo->rWpaInfo.u4CipherPairwise = + IW_AUTH_CIPHER_GCMP256; + break; +#endif + 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; + case WLAN_CIPHER_SUITE_NO_GROUP_ADDR: + break; +#if CFG_SUPPORT_SUITB + case WLAN_CIPHER_SUITE_BIP_GMAC_256: + prGlueInfo->rWpaInfo.u4CipherGroup = + IW_AUTH_CIPHER_GCMP256; + break; + case WLAN_CIPHER_SUITE_GCMP_256: + prGlueInfo->rWpaInfo.u4CipherGroup = + IW_AUTH_CIPHER_GCMP256; + break; +#endif + default: + DBGLOG(REQ, WARN, "invalid cipher group (%d)\n", + sme->crypto.cipher_group); + return -EINVAL; + } + } + + /* DBGLOG(SCN, INFO, ("akm_suites=%x\n", sme->crypto.akm_suites[0])); */ + 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; + u4AkmSuite = WPA_AKM_SUITE_802_1X; + break; + case WLAN_AKM_SUITE_PSK: + eAuthMode = AUTH_MODE_WPA_PSK; + u4AkmSuite = WPA_AKM_SUITE_PSK; + break; + default: + DBGLOG(REQ, WARN, "invalid Akm Suite (%d)\n", + sme->crypto.akm_suites[0]); + 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; + u4AkmSuite = RSN_AKM_SUITE_802_1X; + break; + case WLAN_AKM_SUITE_PSK: + eAuthMode = AUTH_MODE_WPA2_PSK; + u4AkmSuite = RSN_AKM_SUITE_PSK; + break; +#if CFG_SUPPORT_802_11R + case WLAN_AKM_SUITE_FT_8021X: + eAuthMode = AUTH_MODE_WPA2_FT; + u4AkmSuite = RSN_AKM_SUITE_FT_802_1X; + break; + case WLAN_AKM_SUITE_FT_PSK: + eAuthMode = AUTH_MODE_WPA2_FT_PSK; + u4AkmSuite = RSN_AKM_SUITE_FT_PSK; + break; +#endif +#if CFG_SUPPORT_802_11W + /* Notice:: Need kernel patch!! */ + case WLAN_AKM_SUITE_8021X_SHA256: + eAuthMode = AUTH_MODE_WPA2; + u4AkmSuite = RSN_AKM_SUITE_802_1X_SHA256; + break; + case WLAN_AKM_SUITE_PSK_SHA256: + eAuthMode = AUTH_MODE_WPA2_PSK; + u4AkmSuite = RSN_AKM_SUITE_PSK_SHA256; + break; +#endif +#if CFG_SUPPORT_PASSPOINT + case WLAN_AKM_SUITE_OSEN: + eAuthMode = AUTH_MODE_WPA_OSEN; + u4AkmSuite = WFA_AKM_SUITE_OSEN; + break; +#endif +#if CFG_SUPPORT_SUITB + case WLAN_AKM_SUITE_8021X_SUITE_B: + eAuthMode = AUTH_MODE_WPA2_PSK; + u4AkmSuite = RSN_AKM_SUITE_8021X_SUITE_B_192; + break; + + case WLAN_AKM_SUITE_8021X_SUITE_B_192: + eAuthMode = AUTH_MODE_WPA2_PSK; + u4AkmSuite = RSN_AKM_SUITE_8021X_SUITE_B_192; + break; +#endif +#if CFG_SUPPORT_OWE + case WLAN_AKM_SUITE_OWE: + eAuthMode = AUTH_MODE_WPA2_PSK; + u4AkmSuite = RSN_AKM_SUITE_OWE; + break; +#endif + default: + DBGLOG(REQ, WARN, "invalid Akm Suite (%d)\n", + sme->crypto.akm_suites[0]); + return -EINVAL; + } + } + } + + if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_DISABLED) { + switch (prGlueInfo->rWpaInfo.u4AuthAlg) { + case IW_AUTH_ALG_OPEN_SYSTEM: + eAuthMode = AUTH_MODE_OPEN; + break; + case IW_AUTH_ALG_FT: + eAuthMode = AUTH_MODE_NON_RSN_FT; + break; + default: + eAuthMode = AUTH_MODE_AUTO_SWITCH; + break; + } + } + + prGlueInfo->rWpaInfo.fgPrivacyInvoke = sme->privacy; + prGlueInfo->fgWpsActive = FALSE; + +#if CFG_SUPPORT_PASSPOINT + prGlueInfo->fgConnectHS20AP = FALSE; +#endif /* CFG_SUPPORT_PASSPOINT */ + + prConnSettings->fgOkcEnabled = FALSE; + prConnSettings->fgOkcPmksaReady = FALSE; + + prGlueInfo->non_wfa_vendor_ie_len = 0; + if (sme->ie && sme->ie_len > 0) { + uint32_t rStatus; + uint32_t u4BufLen; + uint8_t *prDesiredIE = NULL; + uint8_t *pucIEStart = (uint8_t *)sme->ie; +#if CFG_SUPPORT_WAPI + rStatus = kalIoctl(prGlueInfo, wlanoidSetWapiAssocInfo, + pucIEStart, sme->ie_len, FALSE, FALSE, FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, TRACE, + "[wapi] wapi not support due to set wapi assoc info error:%x\n", + rStatus); +#endif +#if CFG_SUPPORT_WPS2 + if (wextSrchDesiredWPSIE(pucIEStart, sme->ie_len, 0xDD, + (uint8_t **) &prDesiredIE)) { + prGlueInfo->fgWpsActive = TRUE; + fgCarryWPSIE = TRUE; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetWSCAssocInfo, + prDesiredIE, IE_SIZE(prDesiredIE), + FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(SEC, WARN, + "[WSC] set WSC assoc info error:%x\n", + rStatus); + } +#endif +#if CFG_SUPPORT_PASSPOINT + if (wextSrchDesiredHS20IE(pucIEStart, sme->ie_len, + (uint8_t **) &prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, wlanoidSetHS20Info, + prDesiredIE, IE_SIZE(prDesiredIE), + FALSE, FALSE, TRUE, &u4BufLen); +#if 0 + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, + "[HS20] set HS20 assoc info error:%x\n", + rStatus); +#endif + } + if (wextSrchDesiredInterworkingIE(pucIEStart, sme->ie_len, + (uint8_t **) &prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetInterworkingInfo, prDesiredIE, + IE_SIZE(prDesiredIE), + FALSE, FALSE, TRUE, &u4BufLen); +#if 0 + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, + "[HS20] set Interworking assoc info error:%x\n" + , rStatus); +#endif + } + if (wextSrchDesiredRoamingConsortiumIE(pucIEStart, sme->ie_len, + (uint8_t **) &prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRoamingConsortiumIEInfo, prDesiredIE, + IE_SIZE(prDesiredIE), + FALSE, FALSE, TRUE, &u4BufLen); +#if 0 + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, + "[HS20] set RoamingConsortium assoc info error:%x\n", + rStatus); +#endif + } +#endif /* CFG_SUPPORT_PASSPOINT */ + if (wextSrchDesiredWPAIE(pucIEStart, sme->ie_len, 0x30, + (uint8_t **) &prDesiredIE)) { + struct RSN_INFO rRsnInfo; + + if (rsnParseRsnIE(prGlueInfo->prAdapter, + (struct RSN_INFO_ELEM *)prDesiredIE, &rRsnInfo)) { +#if CFG_SUPPORT_802_11W + if (rRsnInfo.u2RsnCap & ELEM_WPA_CAP_MFPC) { + prGlueInfo->rWpaInfo.u4CipherGroupMgmt + = rRsnInfo + .u4GroupMgmtKeyCipherSuite; + prGlueInfo->rWpaInfo.ucRSNMfpCap = + RSN_AUTH_MFP_OPTIONAL; + if (rRsnInfo.u2RsnCap & + ELEM_WPA_CAP_MFPR) + prGlueInfo->rWpaInfo + .ucRSNMfpCap = + RSN_AUTH_MFP_REQUIRED; + } else + prGlueInfo->rWpaInfo.ucRSNMfpCap = + RSN_AUTH_MFP_DISABLED; +#endif + } + } + /* Find non-wfa vendor specific ies set from upper layer */ + if (cfg80211_get_non_wfa_vendor_ie(prGlueInfo, pucIEStart, + sme->ie_len) > 0) { + DBGLOG(RSN, INFO, "Found non-wfa vendor ie (len=%u)\n", + prGlueInfo->non_wfa_vendor_ie_len); + } + + wextSrchOkcAndPMKID(pucIEStart, sme->ie_len, + (uint8_t **)&prDesiredIE, + &prConnSettings->fgOkcEnabled); + if (prConnSettings->fgOkcEnabled) { + uint16_t u2PmkIdCnt = 0; + + if (prDesiredIE) + u2PmkIdCnt = *(uint16_t *)prDesiredIE; + DBGLOG(REQ, TRACE, "u2PmkIdCnt %d\n", u2PmkIdCnt); + if (u2PmkIdCnt != 0 && sme->bssid + && !EQUAL_MAC_ADDR("\x0\x0\x0\x0\x0\x0", + sme->bssid) && IS_UCAST_MAC_ADDR(sme->bssid)) { + struct PARAM_PMKID rPmkid; + + rPmkid.u4Length = (uint32_t)(sizeof(rPmkid) + | (1 << 31)); + rPmkid.u4BSSIDInfoCount = 1; + kalMemCopy(rPmkid.arBSSIDInfo[0].arBSSID, + sme->bssid, MAC_ADDR_LEN); + kalMemCopy(rPmkid.arBSSIDInfo[0].arPMKID, + prDesiredIE + 2, IW_PMKID_LEN); + rStatus = kalIoctl(prGlueInfo, wlanoidSetPmkid, + (void *)&rPmkid, rPmkid.u4Length, + FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, + "failed to add OKC PMKID\n"); + } + } + + } + + /* clear WSC Assoc IE buffer in case WPS IE is not detected */ + if (fgCarryWPSIE == FALSE) { + kalMemZero(&prGlueInfo->aucWSCAssocInfoIE, 200); + prGlueInfo->u2WSCAssocInfoIELen = 0; + } + + /* Fill WPA info - mfp setting */ + /* Must put after paring RSNE from upper layer + * for prGlueInfo->rWpaInfo.ucRSNMfpCap assignment + */ +#if CFG_SUPPORT_802_11W + switch (sme->mfp) { + case NL80211_MFP_NO: + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; + /* Change Mfp parameter from DISABLED to OPTIONAL + * if upper layer set MFPC = 1 in RSNE + * since upper layer can't bring MFP OPTIONAL information + * to driver by sme->mfp + */ + if (prGlueInfo->rWpaInfo.ucRSNMfpCap == RSN_AUTH_MFP_OPTIONAL) + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_OPTIONAL; + else if (prGlueInfo->rWpaInfo.ucRSNMfpCap == + RSN_AUTH_MFP_REQUIRED) + DBGLOG(REQ, WARN, + "mfp parameter(DISABLED) conflict with mfp cap(REQUIRED)\n"); + break; + case NL80211_MFP_REQUIRED: + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_REQUIRED; + break; + default: + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; + break; + } + /* DBGLOG(REQ, INFO, ("MFP=%d\n", prGlueInfo->rWpaInfo.u4Mfp)); */ +#endif + + rStatus = kalIoctl(prGlueInfo, wlanoidSetAuthMode, &eAuthMode, + sizeof(eAuthMode), FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "set auth mode error:%x\n", rStatus); + + /* Enable the specific AKM suite only. */ + for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) { + prEntry = &prGlueInfo->prAdapter->rMib + .dot11RSNAConfigAuthenticationSuitesTable[i]; + + if (prEntry->dot11RSNAConfigAuthenticationSuite == + u4AkmSuite) { + prEntry->dot11RSNAConfigAuthenticationSuiteEnabled = + TRUE; + } else { + prEntry->dot11RSNAConfigAuthenticationSuiteEnabled = + FALSE; + } + } + + cipher = prGlueInfo->rWpaInfo.u4CipherGroup | + prGlueInfo->rWpaInfo.u4CipherPairwise; + + if (1 /* prGlueInfo->rWpaInfo.fgPrivacyInvoke */) { +#if CFG_SUPPORT_SUITB + if (cipher & IW_AUTH_CIPHER_GCMP256) { + eEncStatus = ENUM_ENCRYPTION4_ENABLED; + } else +#endif + 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, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "set encryption mode error:%x\n", + rStatus); + + if (sme->key_len != 0 + && prGlueInfo->rWpaInfo.u4WpaVersion == + IW_AUTH_WPA_VERSION_DISABLED) { + /* NL80211 only set the Tx wep key while connect, the max 4 wep + * key set prior via add key cmd + */ + struct PARAM_WEP *prWepKey = (struct PARAM_WEP *) wepBuf; + + kalMemZero(prWepKey, sizeof(struct PARAM_WEP)); + prWepKey->u4Length = OFFSET_OF(struct PARAM_WEP, + aucKeyMaterial) + sme->key_len; + prWepKey->u4KeyLength = (uint32_t) sme->key_len; + prWepKey->u4KeyIndex = (uint32_t) sme->key_idx; + prWepKey->u4KeyIndex |= IS_TRANSMIT_KEY; + if (prWepKey->u4KeyLength > MAX_KEY_LEN) { + 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, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "wlanoidSetAddWep fail 0x%x\n", + rStatus); + return -EFAULT; + } + } + + /* Avoid dangling pointer, set defatul all zero */ + kalMemZero(&rNewSsid, sizeof(rNewSsid)); + rNewSsid.u4CenterFreq = sme->channel ? + sme->channel->center_freq : 0; + rNewSsid.pucBssid = (uint8_t *)sme->bssid; +#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE + rNewSsid.pucBssidHint = (uint8_t *)sme->bssid_hint; +#endif + rNewSsid.pucSsid = (uint8_t *)sme->ssid; + rNewSsid.u4SsidLen = sme->ssid_len; + rStatus = kalIoctl(prGlueInfo, wlanoidSetConnect, + (void *)&rNewSsid, sizeof(struct PARAM_CONNECT), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set SSID:%x\n", rStatus); + return -EINVAL; + } +#if 0 + if (sme->bssid != NULL + && 1 /* prGlueInfo->fgIsBSSIDSet */) { + /* connect by BSSID */ + if (sme->ssid_len > 0) { + struct CONNECTION_SETTINGS *prConnSettings = NULL; + + prConnSettings = & + (prGlueInfo->prAdapter->rWifiVar.rConnSettings); + /* prGlueInfo->fgIsSSIDandBSSIDSet = TRUE; */ + COPY_SSID(prConnSettings->aucSSID, + prConnSettings->ucSSIDLen, + sme->ssid, sme->ssid_len); + } + rStatus = kalIoctl(prGlueInfo, wlanoidSetBssid, + (void *) sme->bssid, MAC_ADDR_LEN, + FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set BSSID:%x\n", rStatus); + return -EINVAL; + } + } else if (sme->ssid_len > 0) { + /* connect by SSID */ + COPY_SSID(rNewSsid.aucSsid, rNewSsid.u4SsidLen, sme->ssid, + sme->ssid_len); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetSsid, + (void *)&rNewSsid, sizeof(struct PARAM_SSID), + FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set SSID:%x\n", rStatus); + return -EINVAL; + } + } +#endif + 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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint32_t u4BufLen; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, STATE, "mtk_cfg80211_disconnect\n"); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, NULL, + 0, FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "disassociate error:%x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +#if CFG_SUPPORT_CFG80211_AUTH +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to deauth from + * currently connected ESS + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_deauth(struct wiphy *wiphy, struct net_device *ndev, + struct cfg80211_deauth_request *req) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint32_t u4BufLen; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, INFO, "mtk_cfg80211_deauth\n"); +#if CFG_SUPPORT_CFG80211_AUTH + /* The BSS from cfg80211_ops.assoc must give back to + * cfg80211_send_rx_assoc() or to cfg80211_assoc_timeout(). + * To ensure proper refcounting, new association requests + * while already associating must be rejected. + */ + if (prGlueInfo->prAdapter->rWifiVar.rConnSettings.bss) { + DBGLOG(REQ, INFO, "assoc timeout notify\n"); + /* ops caller have already hold the mutex. */ + cfg80211_assoc_timeout(ndev, + prGlueInfo->prAdapter->rWifiVar.rConnSettings.bss); + DBGLOG(REQ, INFO, "assoc timeout notify, Done\n"); + prGlueInfo->prAdapter->rWifiVar.rConnSettings.bss = NULL; + } +#endif + rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, NULL, 0, + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "disassociate error:%x\n", rStatus); + return -EFAULT; + } + + return 0; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @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) +{ + struct PARAM_SSID rNewSsid; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4ChnlFreq; /* Store channel or frequency information */ + uint32_t u4BufLen = 0, u4SsidLen = 0; + uint32_t rStatus; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, INFO, "mtk_cfg80211_join_ibss\n"); + + /* set channel */ + if (params->channel_fixed) { + u4ChnlFreq = params->chandef.center_freq1; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetFrequency, + &u4ChnlFreq, sizeof(u4ChnlFreq), + FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + /* set SSID */ + if (params->ssid_len > PARAM_MAX_LEN_SSID) + u4SsidLen = PARAM_MAX_LEN_SSID; + else + u4SsidLen = params->ssid_len; + + kalMemCopy(rNewSsid.aucSsid, params->ssid, + u4SsidLen); + rStatus = kalIoctl(prGlueInfo, wlanoidSetSsid, (void *)&rNewSsid, + sizeof(struct PARAM_SSID), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set SSID:%x\n", rStatus); + return -EFAULT; + } + + return 0; + + return -EINVAL; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to leave from IBSS group + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_leave_ibss(struct wiphy *wiphy, + struct net_device *ndev) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint32_t u4BufLen; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, INFO, "%s\n", __func__); + rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, NULL, + 0, FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "disassociate error:%x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to configure + * WLAN power managemenet + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_set_power_mgmt(struct wiphy *wiphy, + struct net_device *ndev, bool enabled, int timeout) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint32_t u4BufLen; + struct PARAM_POWER_MODE_ rPowerMode; + struct WIFI_VAR *prWifiVar; + enum PARAM_POWER_MODE eEnforcePowerMode; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + if (!prGlueInfo) + return -EFAULT; + + if (!prGlueInfo->prAdapter->prAisBssInfo) + return -EFAULT; + + prWifiVar = &prGlueInfo->prAdapter->rWifiVar; + + DBGLOG(REQ, INFO, "%s: enabled=%d, timeout=%d\n", __func__, + enabled, timeout); + + if (enabled && + ((prGlueInfo->prAdapter->prAisBssInfo->eBand == BAND_5G) || + (!prWifiVar->ucEnforceCAM2G))) { + if (timeout == -1) + rPowerMode.ePowerMode = Param_PowerModeFast_PSP; + else + rPowerMode.ePowerMode = Param_PowerModeMAX_PSP; + } else { + rPowerMode.ePowerMode = Param_PowerModeCAM; + } + + if (prWifiVar->fgActiveModeCam) + rPowerMode.ePowerMode = Param_PowerModeCAM; + + rPowerMode.ucBssIdx = + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + + if ((prGlueInfo->prAdapter->prAisBssInfo->ePowerModeFromUser + != rPowerMode.ePowerMode) && + (prGlueInfo->prAdapter->rWifiVar.ucEnforcePSMode + < Param_PowerModeMax)) { + /* + * Store user's PS mode for restoring + * when we do not enforce power mode anymore + */ + DBGLOG(INIT, STATE, "Store user's PS mode:%d\n", + rPowerMode.ePowerMode); + prGlueInfo->prAdapter->prAisBssInfo->ePowerModeFromUser = + rPowerMode.ePowerMode; + } + + eEnforcePowerMode = + (enum PARAM_POWER_MODE) + prGlueInfo->prAdapter->rWifiVar.ucEnforcePSMode; + + if (eEnforcePowerMode < Param_PowerModeMax) + rPowerMode.ePowerMode = eEnforcePowerMode; + + rStatus = kalIoctl(prGlueInfo, wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, sizeof(struct PARAM_POWER_MODE_), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set_power_mgmt error:%x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to cache + * a PMKID for a BSSID + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_set_pmksa(struct wiphy *wiphy, + struct net_device *ndev, struct cfg80211_pmksa *pmksa) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint32_t u4BufLen; + struct PARAM_PMKID *prPmkid; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + prPmkid = (struct PARAM_PMKID *) kalMemAlloc(8 + sizeof( + struct PARAM_BSSID_INFO), VIR_MEM_TYPE); + DBGLOG(REQ, INFO, "mtk_cfg80211_set_pmksa\n"); + + if (!prPmkid) { + DBGLOG(INIT, INFO, + "Can not alloc memory for IW_PMKSA_ADD\n"); + return -ENOMEM; + } + + prPmkid->u4Length = 8 + sizeof(struct PARAM_BSSID_INFO); + 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(struct PARAM_PMKID), + FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "add pmkid error:%x\n", rStatus); + kalMemFree(prPmkid, VIR_MEM_TYPE, + 8 + sizeof(struct PARAM_BSSID_INFO)); + + 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) +{ + DBGLOG(REQ, INFO, "not support now\n"); + 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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint32_t u4BufLen; + struct PARAM_PMKID *prPmkid; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + prPmkid = (struct PARAM_PMKID *) kalMemAlloc(8, + VIR_MEM_TYPE); + + DBGLOG(P2P, INFO, "mtk_cfg80211_flush_pmksa\n"); + + 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(struct PARAM_PMKID), FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "flush pmkid error:%x\n", rStatus); + kalMemFree(prPmkid, VIR_MEM_TYPE, 8); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for setting the rekey data + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_set_rekey_data(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_gtk_rekey_data *data) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4BufLen; + struct PARAM_GTK_REKEY_DATA *prGtkData; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + int32_t i4Rslt = -EINVAL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + /* if offload dis, store key data, and enable rekey offload when wow */ + if (!prGlueInfo->prAdapter->rWifiVar.ucEapolOffload) { + kalMemZero(prGlueInfo->rWpaInfo.aucKek, NL80211_KEK_LEN); + kalMemZero(prGlueInfo->rWpaInfo.aucKck, NL80211_KCK_LEN); + kalMemZero(prGlueInfo->rWpaInfo.aucReplayCtr, + NL80211_REPLAY_CTR_LEN); + kalMemCopy(prGlueInfo->rWpaInfo.aucKek, data->kek, + NL80211_KEK_LEN); + kalMemCopy(prGlueInfo->rWpaInfo.aucKck, data->kck, + NL80211_KCK_LEN); + kalMemCopy(prGlueInfo->rWpaInfo.aucReplayCtr, data->replay_ctr, + NL80211_REPLAY_CTR_LEN); + + return 0; + } + + prGtkData = + (struct PARAM_GTK_REKEY_DATA *) kalMemAlloc(sizeof( + struct PARAM_GTK_REKEY_DATA), VIR_MEM_TYPE); + + if (!prGtkData) + return WLAN_STATUS_SUCCESS; + + DBGLOG(RSN, INFO, "cfg80211_set_rekey_data size(%d)\n", + (uint32_t) sizeof(struct cfg80211_gtk_rekey_data)); + + DBGLOG(RSN, TRACE, "kek\n"); + DBGLOG_MEM8(RSN, TRACE, (uint8_t *)data->kek, + NL80211_KEK_LEN); + DBGLOG(RSN, TRACE, "kck\n"); + DBGLOG_MEM8(RSN, TRACE, (uint8_t *)data->kck, + NL80211_KCK_LEN); + DBGLOG(RSN, TRACE, "replay count\n"); + DBGLOG_MEM8(RSN, TRACE, (uint8_t *)data->replay_ctr, + NL80211_REPLAY_CTR_LEN); + + +#if 0 + kalMemCopy(prGtkData, data, sizeof(*data)); +#else + kalMemCopy(prGtkData->aucKek, data->kek, NL80211_KEK_LEN); + kalMemCopy(prGtkData->aucKck, data->kck, NL80211_KCK_LEN); + kalMemCopy(prGtkData->aucReplayCtr, data->replay_ctr, + NL80211_REPLAY_CTR_LEN); +#endif + + prGtkData->ucBssIndex = + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + + prGtkData->u4Proto = NL80211_WPA_VERSION_2; + if (prGlueInfo->rWpaInfo.u4WpaVersion == + IW_AUTH_WPA_VERSION_WPA) + prGtkData->u4Proto = NL80211_WPA_VERSION_1; + + if (prGlueInfo->rWpaInfo.u4CipherPairwise == + IW_AUTH_CIPHER_TKIP) + prGtkData->u4PairwiseCipher = BIT(3); + else if (prGlueInfo->rWpaInfo.u4CipherPairwise == + IW_AUTH_CIPHER_CCMP) + prGtkData->u4PairwiseCipher = BIT(4); + else { + kalMemFree(prGtkData, VIR_MEM_TYPE, + sizeof(struct PARAM_GTK_REKEY_DATA)); + return WLAN_STATUS_SUCCESS; + } + + if (prGlueInfo->rWpaInfo.u4CipherGroup == + IW_AUTH_CIPHER_TKIP) + prGtkData->u4GroupCipher = BIT(3); + else if (prGlueInfo->rWpaInfo.u4CipherGroup == + IW_AUTH_CIPHER_CCMP) + prGtkData->u4GroupCipher = BIT(4); + else { + kalMemFree(prGtkData, VIR_MEM_TYPE, + sizeof(struct PARAM_GTK_REKEY_DATA)); + return WLAN_STATUS_SUCCESS; + } + + prGtkData->u4KeyMgmt = prGlueInfo->rWpaInfo.u4KeyMgmt; + prGtkData->u4MgmtGroupCipher = 0; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetGtkRekeyData, prGtkData, + sizeof(struct PARAM_GTK_REKEY_DATA), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "set GTK rekey data error:%x\n", + rStatus); + else + i4Rslt = 0; + + kalMemFree(prGtkData, VIR_MEM_TYPE, + sizeof(struct PARAM_GTK_REKEY_DATA)); + + return i4Rslt; +} + +void mtk_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, + IN struct wireless_dev *wdev, + IN u16 frame_type, + IN bool reg) +{ +#if 0 + struct MSG_P2P_MGMT_FRAME_REGISTER *prMgmtFrameRegister = + (struct MSG_P2P_MGMT_FRAME_REGISTER *) NULL; +#endif + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + + do { + + DBGLOG(INIT, TRACE, "mtk_cfg80211_mgmt_frame_register\n"); + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + switch (frame_type) { + case MAC_FRAME_PROBE_REQ: + if (reg) { + prGlueInfo->u4OsMgmtFrameFilter |= + PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(INIT, TRACE, + "Open packet filer probe request\n"); + } else { + prGlueInfo->u4OsMgmtFrameFilter &= + ~PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(INIT, TRACE, + "Close packet filer probe request\n"); + } + break; + case MAC_FRAME_ACTION: + if (reg) { + prGlueInfo->u4OsMgmtFrameFilter |= + PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(INIT, TRACE, + "Open packet filer action frame.\n"); + } else { + prGlueInfo->u4OsMgmtFrameFilter &= + ~PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(INIT, TRACE, + "Close packet filer action frame.\n"); + } + break; + default: + DBGLOG(INIT, TRACE, + "Ask frog to add code for mgmt:%x\n", + frame_type); + break; + } + + if (prGlueInfo->prAdapter != NULL) { + + set_bit(GLUE_FLAG_FRAME_FILTER_AIS_BIT, + &prGlueInfo->ulFlag); + + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + + if (in_interrupt()) + DBGLOG(INIT, TRACE, + "It is in interrupt level\n"); + } +#if 0 + + prMgmtFrameRegister = + (struct MSG_P2P_MGMT_FRAME_REGISTER *) cnmMemAlloc( + prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_P2P_MGMT_FRAME_REGISTER)); + + 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, + (struct MSG_HDR *) prMgmtFrameRegister, + MSG_SEND_METHOD_BUF); + +#endif + + } while (FALSE); + +} /* mtk_cfg80211_mgmt_frame_register */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to stay on a + * specified channel + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, unsigned int duration, + u64 *cookie) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_REMAIN_ON_CHANNEL *prMsgChnlReq = + (struct MSG_REMAIN_ON_CHANNEL *) NULL; + + do { + if ((wiphy == NULL) + || (wdev == NULL) + || (chan == NULL) + || (cookie == NULL)) { + break; + } + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if 1 + DBGLOG(INIT, INFO, "--> %s()\n", __func__); +#endif + + *cookie = prGlueInfo->u8Cookie++; + + prMsgChnlReq = cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, sizeof(struct MSG_REMAIN_ON_CHANNEL)); + + if (prMsgChnlReq == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgChnlReq->rMsgHdr.eMsgId = + MID_MNY_AIS_REMAIN_ON_CHANNEL; + prMsgChnlReq->u8Cookie = *cookie; + prMsgChnlReq->u4DurationMs = duration; + + prMsgChnlReq->ucChannelNum = nicFreq2ChannelNum( + chan->center_freq * 1000); + + switch (chan->band) { + case KAL_BAND_2GHZ: + prMsgChnlReq->eBand = BAND_2G4; + break; + case KAL_BAND_5GHZ: + prMsgChnlReq->eBand = BAND_5G; + break; + default: + prMsgChnlReq->eBand = BAND_2G4; + break; + } + + prMsgChnlReq->eSco = CHNL_EXT_SCN; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prMsgChnlReq, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to cancel staying + * on a specified channel + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_cancel_remain_on_channel( + struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_CANCEL_REMAIN_ON_CHANNEL *prMsgChnlAbort = + (struct MSG_CANCEL_REMAIN_ON_CHANNEL *) NULL; + + do { + if ((wiphy == NULL) + || (wdev == NULL) + ) { + break; + } + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, INFO, + "mtk_cfg80211_cancel_remain_on_channel\n"); + + prMsgChnlAbort = + cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_CANCEL_REMAIN_ON_CHANNEL)); + + if (prMsgChnlAbort == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgChnlAbort->rMsgHdr.eMsgId = + MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL; + prMsgChnlAbort->u8Cookie = cookie; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prMsgChnlAbort, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to send a management frame + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_MGMT_TX_REQUEST *prMsgTxReq = (struct + MSG_MGMT_TX_REQUEST *) NULL; + struct MSDU_INFO *prMgmtFrame = (struct MSDU_INFO *) NULL; + uint8_t *pucFrameBuf = (uint8_t *) NULL; + + do { + if ((wiphy == NULL) || (wdev == NULL) || (params == 0) + || (cookie == NULL)) + break; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, INFO, "mtk_cfg80211_mgmt_tx\n"); + + *cookie = prGlueInfo->u8Cookie++; + + /* Channel & Channel Type & Wait time are ignored. */ + prMsgTxReq = cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_MGMT_TX_REQUEST)); + + if (prMsgTxReq == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgTxReq->fgNoneCckRate = FALSE; + prMsgTxReq->fgIsWaitRsp = TRUE; + + prMgmtFrame = cnmMgtPktAlloc(prGlueInfo->prAdapter, + (uint32_t) (params->len + + MAC_TX_RESERVED_FIELD)); + prMsgTxReq->prMgmtMsduInfo = prMgmtFrame; + if (prMsgTxReq->prMgmtMsduInfo == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgTxReq->u8Cookie = *cookie; + prMsgTxReq->rMsgHdr.eMsgId = MID_MNY_AIS_MGMT_TX; + + pucFrameBuf = (uint8_t *) ((unsigned long) + prMgmtFrame->prPacket + + MAC_TX_RESERVED_FIELD); + + kalMemCopy(pucFrameBuf, params->buf, params->len); + + prMgmtFrame->u2FrameLength = params->len; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, + (struct MSG_HDR *) 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; +} +#else +int mtk_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *channel, bool offscan, + unsigned int wait, + const u8 *buf, size_t len, bool no_cck, + bool dont_wait_for_ack, u64 *cookie) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_MGMT_TX_REQUEST *prMsgTxReq = (struct + MSG_MGMT_TX_REQUEST *) NULL; + struct MSDU_INFO *prMgmtFrame = (struct MSDU_INFO *) NULL; + uint8_t *pucFrameBuf = (uint8_t *) NULL; + + do { + if ((wiphy == NULL) + || (buf == NULL) + || (len == 0) + || (wdev == NULL) + || (cookie == NULL)) { + break; + } + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, INFO, "mtk_cfg80211_mgmt_tx\n"); + + *cookie = prGlueInfo->u8Cookie++; + + /* Channel & Channel Type & Wait time are ignored. */ + prMsgTxReq = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_MGMT_TX_REQUEST)); + + if (prMsgTxReq == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgTxReq->fgNoneCckRate = FALSE; + prMsgTxReq->fgIsWaitRsp = TRUE; + + prMgmtFrame = cnmMgtPktAlloc(prGlueInfo->prAdapter, + (uint32_t) (len + MAC_TX_RESERVED_FIELD)); + prMsgTxReq->prMgmtMsduInfo = prMgmtFrame; + if (prMsgTxReq->prMgmtMsduInfo == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgTxReq->u8Cookie = *cookie; + prMsgTxReq->rMsgHdr.eMsgId = MID_MNY_AIS_MGMT_TX; + + pucFrameBuf = (uint8_t *) ((unsigned long) + prMgmtFrame->prPacket + + MAC_TX_RESERVED_FIELD); + + kalMemCopy(pucFrameBuf, buf, len); + + prMgmtFrame->u2FrameLength = len; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, + (struct MSG_HDR *) 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; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to cancel the wait time + * from transmitting a management frame on another channel + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct wireless_dev *wdev, u64 cookie) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if 1 + DBGLOG(INIT, INFO, "--> %s()\n", __func__); +#endif + + /* not implemented */ + + return -EINVAL; +} + +#ifdef CONFIG_NL80211_TESTMODE + +#if CFG_SUPPORT_PASSPOINT +int mtk_cfg80211_testmode_hs20_cmd(IN struct wiphy *wiphy, + IN void *data, IN int len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct wpa_driver_hs20_data_s *prParams = NULL; + uint32_t rstatus = WLAN_STATUS_SUCCESS; + int fgIsValid = 0; + uint32_t u4SetInfoLen = 0; + + ASSERT(wiphy); + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + DBGLOG(REQ, INFO, "--> %s()\n", __func__); + + if (data && len) + prParams = (struct wpa_driver_hs20_data_s *)data; + + if (prParams) { + int i; + + DBGLOG(INIT, INFO, "[%s] Cmd Type (%d)\n", + __func__, prParams->CmdType); + switch (prParams->CmdType) { + case HS20_CMD_ID_SET_BSSID_POOL: + DBGLOG(REQ, TRACE, + "fgBssidPoolIsEnable=%d, ucNumBssidPool=%d\n", + prParams->hs20_set_bssid_pool.fgBssidPoolIsEnable, + prParams->hs20_set_bssid_pool.ucNumBssidPool); + for (i = 0; + i < prParams->hs20_set_bssid_pool.ucNumBssidPool; + i++) { + DBGLOG(REQ, TRACE, + "[%d][ " MACSTR " ]\n", + i, + MAC2STR(prParams-> + hs20_set_bssid_pool. + arBssidPool[i])); + } + rstatus = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC) wlanoidSetHS20BssidPool, + &prParams->hs20_set_bssid_pool, + sizeof(struct param_hs20_set_bssid_pool), + FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + break; + default: + DBGLOG(REQ, TRACE, "[%s] Unknown Cmd Type (%d)\n", + __func__, prParams->CmdType); + rstatus = WLAN_STATUS_FAILURE; + + } + + } + + if (rstatus != WLAN_STATUS_SUCCESS) + fgIsValid = -EFAULT; + + return fgIsValid; +} +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_WAPI +int mtk_cfg80211_testmode_set_key_ext(IN struct wiphy + *wiphy, IN void *data, IN int len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct NL80211_DRIVER_SET_KEY_EXTS *prParams = + (struct NL80211_DRIVER_SET_KEY_EXTS *) NULL; + struct iw_encode_exts *prIWEncExt = (struct iw_encode_exts + *)NULL; + uint32_t rstatus = WLAN_STATUS_SUCCESS; + int fgIsValid = 0; + uint32_t u4BufLen = 0; + const uint8_t aucBCAddr[] = BC_MAC_ADDR; + + struct PARAM_KEY *prWpiKey = (struct PARAM_KEY *) + keyStructBuf; + + memset(keyStructBuf, 0, sizeof(keyStructBuf)); + + ASSERT(wiphy); + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + +#if 1 + DBGLOG(INIT, INFO, "--> %s()\n", __func__); +#endif + + if (data == NULL || len == 0) { + DBGLOG(INIT, TRACE, "%s data or len is invalid\n", __func__); + return -EINVAL; + } + + prParams = (struct NL80211_DRIVER_SET_KEY_EXTS *) data; + prIWEncExt = (struct iw_encode_exts *)&prParams->ext; + + if (prIWEncExt->alg == IW_ENCODE_ALG_SMS4) { + /* KeyID */ + prWpiKey->u4KeyIndex = prParams->key_index; + prWpiKey->u4KeyIndex--; + if (prWpiKey->u4KeyIndex > 1) { + return -EINVAL; + } + + if (prIWEncExt->key_len != 32) { + return -EINVAL; + } + prWpiKey->u4KeyLength = prIWEncExt->key_len; + + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY && + !(prIWEncExt->ext_flags & IW_ENCODE_EXT_GROUP_KEY)) { + /* WAI seems set the STA group key with + * IW_ENCODE_EXT_SET_TX_KEY !!!! + * Ignore the group case + */ + prWpiKey->u4KeyIndex |= BIT(30); + prWpiKey->u4KeyIndex |= BIT(31); + /* BSSID */ + memcpy(prWpiKey->arBSSID, prIWEncExt->addr, 6); + } else { + COPY_MAC_ADDR(prWpiKey->arBSSID, aucBCAddr); + } + + /* PN */ + /* memcpy(prWpiKey->rKeyRSC, prIWEncExt->tx_seq, + * IW_ENCODE_SEQ_MAX_SIZE * 2); + */ + + memcpy(prWpiKey->aucKeyMaterial, prIWEncExt->key, 32); + + prWpiKey->u4Length = sizeof(struct PARAM_KEY); + prWpiKey->ucBssIdx = + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + prWpiKey->ucCipher = CIPHER_SUITE_WPI; + + rstatus = kalIoctl(prGlueInfo, wlanoidSetAddKey, prWpiKey, + sizeof(struct PARAM_KEY), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rstatus != WLAN_STATUS_SUCCESS) { + fgIsValid = -EFAULT; + } + + } + return fgIsValid; +} +#endif + +int +mtk_cfg80211_testmode_get_sta_statistics(IN struct wiphy + *wiphy, IN void *data, IN int len, + IN struct GLUE_INFO *prGlueInfo) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen; + uint32_t u4LinkScore; + uint32_t u4TotalError; + uint32_t u4TxExceedThresholdCount; + uint32_t u4TxTotalCount; + + struct NL80211_DRIVER_GET_STA_STATISTICS_PARAMS *prParams = + NULL; + struct PARAM_GET_STA_STATISTICS rQueryStaStatistics; + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(prGlueInfo); + + if (data && len) + prParams = (struct NL80211_DRIVER_GET_STA_STATISTICS_PARAMS + *) data; + + if (prParams == NULL) { + DBGLOG(QM, ERROR, "prParams is NULL, data=%p, len=%d\n", + data, len); + return -EINVAL; + } else if (prParams->aucMacAddr == NULL) { + DBGLOG(QM, ERROR, + "prParams->aucMacAddr is NULL, data=%p, len=%d\n", + data, len); + return -EINVAL; + } + + skb = cfg80211_testmode_alloc_reply_skb(wiphy, + sizeof(struct PARAM_GET_STA_STATISTICS) + 1); + if (!skb) { + DBGLOG(QM, ERROR, "allocate skb failed:%x\n", rStatus); + return -ENOMEM; + } + + DBGLOG(QM, TRACE, "Get [" MACSTR "] STA statistics\n", + MAC2STR(prParams->aucMacAddr)); + + kalMemZero(&rQueryStaStatistics, + sizeof(rQueryStaStatistics)); + COPY_MAC_ADDR(rQueryStaStatistics.aucMacAddr, + prParams->aucMacAddr); + rQueryStaStatistics.ucReadClear = TRUE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStaStatistics, + &rQueryStaStatistics, sizeof(rQueryStaStatistics), + TRUE, FALSE, TRUE, &u4BufLen); + + /* Calcute Link Score */ + u4TxExceedThresholdCount = + rQueryStaStatistics.u4TxExceedThresholdCount; + u4TxTotalCount = rQueryStaStatistics.u4TxTotalCount; + u4TotalError = rQueryStaStatistics.u4TxFailCount + + rQueryStaStatistics.u4TxLifeTimeoutCount; + + /* u4LinkScore 10~100 , ExceedThreshold ratio 0~90 only + * u4LinkScore 0~9 , Drop packet ratio 0~9 and all packets exceed + * threshold + */ + if (u4TxTotalCount) { + if (u4TxExceedThresholdCount <= u4TxTotalCount) + u4LinkScore = (90 - ((u4TxExceedThresholdCount * 90) + / u4TxTotalCount)); + else + u4LinkScore = 0; + } else { + u4LinkScore = 90; + } + + u4LinkScore += 10; + + if (u4LinkScore == 10) { + if (u4TotalError <= u4TxTotalCount) + u4LinkScore = (10 - ((u4TotalError * 10) + / u4TxTotalCount)); + else + u4LinkScore = 0; + + } + + if (u4LinkScore > 100) + u4LinkScore = 100; + { + u8 __tmp = 0; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_INVALID, sizeof(u8), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u8 __tmp = NL80211_DRIVER_TESTMODE_VERSION; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_VERSION, sizeof(u8), + &__tmp) < 0)) + goto nla_put_failure; + } + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_MAC, MAC_ADDR_LEN, + prParams->aucMacAddr) < 0)) + goto nla_put_failure; + { + u32 __tmp = u4LinkScore; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + + { + u32 __tmp = rQueryStaStatistics.u4Flag; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_FLAG, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4EnqueueCounter; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_ENQUEUE, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4DequeueCounter; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_DEQUEUE, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4EnqueueStaCounter; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_STA_ENQUEUE, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4DequeueStaCounter; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_STA_DEQUEUE, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.IsrCnt; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_CNT, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + + { + u32 __tmp = rQueryStaStatistics.IsrPassCnt; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_PASS_CNT, + sizeof(u32), &__tmp) < 0)) + goto nla_put_failure; + } + + { + u32 __tmp = rQueryStaStatistics.TaskIsrCnt; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_IRQ_TASK_CNT, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + + { + u32 __tmp = rQueryStaStatistics.IsrAbnormalCnt; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_IRQ_AB_CNT, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + + { + u32 __tmp = rQueryStaStatistics.IsrSoftWareCnt; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_IRQ_SW_CNT, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + + { + u32 __tmp = rQueryStaStatistics.IsrTxCnt; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_IRQ_TX_CNT, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + + { + u32 __tmp = rQueryStaStatistics.IsrRxCnt; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_IRQ_RX_CNT, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + + /* FW part STA link status */ + { + u8 __tmp = rQueryStaStatistics.ucPer; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_PER, sizeof(u8), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u8 __tmp = rQueryStaStatistics.ucRcpi; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_RSSI, sizeof(u8), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4PhyMode; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_PHY_MODE, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u16 __tmp = rQueryStaStatistics.u2LinkSpeed; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_TX_RATE, sizeof(u16), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4TxFailCount; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4TxLifeTimeoutCount; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4TxAverageAirTime; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + + /* Driver part link status */ + { + u32 __tmp = rQueryStaStatistics.u4TxTotalCount; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4TxExceedThresholdCount; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT, sizeof(u32), + &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4TxAverageProcessTime; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME, + sizeof(u32), &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4TxMaxTime; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_MAX_PROCESS_TIME, + sizeof(u32), &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4TxAverageHifTime; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_AVG_HIF_PROCESS_TIME, + sizeof(u32), &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4TxMaxHifTime; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_MAX_HIF_PROCESS_TIME, + sizeof(u32), &__tmp) < 0)) + goto nla_put_failure; + } + + /* Network counter */ + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY, + sizeof(rQueryStaStatistics.au4TcResourceEmptyCount), + rQueryStaStatistics.au4TcResourceEmptyCount) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_NO_TC_ARRAY, + sizeof(rQueryStaStatistics.au4DequeueNoTcResource), + rQueryStaStatistics.au4DequeueNoTcResource) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_RB_ARRAY, + sizeof(rQueryStaStatistics.au4TcResourceBackCount), + rQueryStaStatistics.au4TcResourceBackCount) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_USED_TC_PGCT_ARRAY, + sizeof(rQueryStaStatistics.au4TcResourceUsedPageCount), + rQueryStaStatistics.au4TcResourceUsedPageCount) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_WANTED_TC_PGCT_ARRAY, + sizeof(rQueryStaStatistics.au4TcResourceWantedPageCount), + rQueryStaStatistics.au4TcResourceWantedPageCount) < 0)) + goto nla_put_failure; + + /* Sta queue length */ + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY, + sizeof(rQueryStaStatistics.au4TcQueLen), + rQueryStaStatistics.au4TcQueLen) < 0)) + goto nla_put_failure; + + /* Global QM counter */ + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY, + sizeof(rQueryStaStatistics.au4TcAverageQueLen), + rQueryStaStatistics.au4TcAverageQueLen) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY, + sizeof(rQueryStaStatistics.au4TcCurrentQueLen), + rQueryStaStatistics.au4TcCurrentQueLen) < 0)) + goto nla_put_failure; + + /* Reserved field */ + if (unlikely(nla_put(skb, + NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY, + sizeof(rQueryStaStatistics.au4Reserved), + rQueryStaStatistics.au4Reserved) < 0)) + goto nla_put_failure; + + return cfg80211_testmode_reply(skb); + +nla_put_failure: + /* nal_put_skb_fail */ + kfree_skb(skb); + return -EFAULT; +} + +int +mtk_cfg80211_testmode_get_link_detection(IN struct wiphy + *wiphy, IN void *data, IN int len, + IN struct GLUE_INFO *prGlueInfo) +{ + + uint32_t rStatus = WLAN_STATUS_SUCCESS; + int32_t i4Status = -EINVAL; + uint32_t u4BufLen; + uint8_t u1buf = 0; + uint32_t i = 0; + uint32_t arBugReport[sizeof(struct _EVENT_BUG_REPORT_T)]; + struct PARAM_802_11_STATISTICS_STRUCT rStatistics; + struct _EVENT_BUG_REPORT_T *prBugReport; + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(prGlueInfo); + + prBugReport = (struct _EVENT_BUG_REPORT_T *) kalMemAlloc( + sizeof(struct _EVENT_BUG_REPORT_T), VIR_MEM_TYPE); + if (!prBugReport) { + DBGLOG(QM, TRACE, "%s allocate prBugReport failed\n", + __func__); + return -ENOMEM; + } + skb = cfg80211_testmode_alloc_reply_skb(wiphy, + sizeof(struct PARAM_802_11_STATISTICS_STRUCT) + + sizeof(struct _EVENT_BUG_REPORT_T) + 1); + + if (!skb) { + kalMemFree(prBugReport, VIR_MEM_TYPE, + sizeof(struct _EVENT_BUG_REPORT_T)); + DBGLOG(QM, TRACE, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + kalMemZero(&rStatistics, sizeof(rStatistics)); + kalMemZero(prBugReport, sizeof(struct _EVENT_BUG_REPORT_T)); + kalMemZero(arBugReport, + sizeof(struct _EVENT_BUG_REPORT_T) * sizeof(uint32_t)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStatistics, + &rStatistics, sizeof(rStatistics), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "query statistics error:%x\n", rStatus); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryBugReport, + prBugReport, sizeof(struct _EVENT_BUG_REPORT_T), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "query statistics error:%x\n", rStatus); + + kalMemCopy(arBugReport, prBugReport, + sizeof(struct _EVENT_BUG_REPORT_T)); + + rStatistics.u4RstReason = eResetReason; + rStatistics.u8RstTime = u8ResetTime; + rStatistics.u4RoamFailCnt = prGlueInfo->u4RoamFailCnt; + rStatistics.u8RoamFailTime = prGlueInfo->u8RoamFailTime; + rStatistics.u2TxDoneDelayIsARP = + prGlueInfo->fgTxDoneDelayIsARP; + rStatistics.u4ArriveDrvTick = prGlueInfo->u4ArriveDrvTick; + rStatistics.u4EnQueTick = prGlueInfo->u4EnQueTick; + rStatistics.u4DeQueTick = prGlueInfo->u4DeQueTick; + rStatistics.u4LeaveDrvTick = prGlueInfo->u4LeaveDrvTick; + rStatistics.u4CurrTick = prGlueInfo->u4CurrTick; + rStatistics.u8CurrTime = prGlueInfo->u8CurrTime; + + if (!NLA_PUT_U8(skb, NL80211_TESTMODE_LINK_INVALID, &u1buf)) + goto nla_put_failure; + + if (!NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_TX_FAIL_CNT, + &rStatistics.rFailedCount.QuadPart)) + goto nla_put_failure; + + if (!NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_TX_RETRY_CNT, + &rStatistics.rRetryCount.QuadPart)) + goto nla_put_failure; + + if (!NLA_PUT_U64(skb, + NL80211_TESTMODE_LINK_TX_MULTI_RETRY_CNT, + &rStatistics.rMultipleRetryCount.QuadPart)) + goto nla_put_failure; + + if (!NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_ACK_FAIL_CNT, + &rStatistics.rACKFailureCount.QuadPart)) + goto nla_put_failure; + + if (!NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_FCS_ERR_CNT, + &rStatistics.rFCSErrorCount.QuadPart)) + goto nla_put_failure; + + if (!NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_TX_CNT, + &rStatistics.rTransmittedFragmentCount.QuadPart)) + goto nla_put_failure; + + if (!NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_RX_CNT, + &rStatistics.rReceivedFragmentCount.QuadPart)) + goto nla_put_failure; + + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_LINK_RST_REASON, + &rStatistics.u4RstReason)) + goto nla_put_failure; + + if (!NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_RST_TIME, + &rStatistics.u8RstTime)) + goto nla_put_failure; + + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_LINK_ROAM_FAIL_TIMES, + &rStatistics.u4RoamFailCnt)) + goto nla_put_failure; + + if (!NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_ROAM_FAIL_TIME, + &rStatistics.u8RoamFailTime)) + goto nla_put_failure; + + if (!NLA_PUT_U8(skb, + NL80211_TESTMODE_LINK_TX_DONE_DELAY_IS_ARP, + &rStatistics.u2TxDoneDelayIsARP)) + goto nla_put_failure; + + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_LINK_ARRIVE_DRV_TICK, + &rStatistics.u4ArriveDrvTick)) + goto nla_put_failure; + + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_LINK_ENQUE_TICK, + &rStatistics.u4EnQueTick)) + goto nla_put_failure; + + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_LINK_DEQUE_TICK, + &rStatistics.u4DeQueTick)) + goto nla_put_failure; + + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_LINK_LEAVE_DRV_TICK, + &rStatistics.u4LeaveDrvTick)) + goto nla_put_failure; + + if (!NLA_PUT_U32(skb, NL80211_TESTMODE_LINK_CURR_TICK, + &rStatistics.u4CurrTick)) + goto nla_put_failure; + + if (!NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_CURR_TIME, + &rStatistics.u8CurrTime)) + goto nla_put_failure; + + for (i = 0; + i < sizeof(struct _EVENT_BUG_REPORT_T) / sizeof(uint32_t); + i++) { + if (!NLA_PUT_U32(skb, i + NL80211_TESTMODE_LINK_DETECT_NUM, + &arBugReport[i])) + goto nla_put_failure; + } + + i4Status = cfg80211_testmode_reply(skb); + kalMemFree(prBugReport, VIR_MEM_TYPE, + sizeof(struct _EVENT_BUG_REPORT_T)); + return i4Status; + +nla_put_failure: + /* nal_put_skb_fail */ + kfree_skb(skb); + kalMemFree(prBugReport, VIR_MEM_TYPE, + sizeof(struct _EVENT_BUG_REPORT_T)); + return -EFAULT; +} + +int mtk_cfg80211_testmode_sw_cmd(IN struct wiphy *wiphy, + IN void *data, IN int len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct NL80211_DRIVER_SW_CMD_PARAMS *prParams = + (struct NL80211_DRIVER_SW_CMD_PARAMS *) NULL; + uint32_t rstatus = WLAN_STATUS_SUCCESS; + int fgIsValid = 0; + uint32_t u4SetInfoLen = 0; + + ASSERT(wiphy); + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + +#if 0 + DBGLOG(INIT, INFO, "--> %s()\n", __func__); +#endif + + if (data && len) + prParams = (struct NL80211_DRIVER_SW_CMD_PARAMS *) data; + + if (prParams) { + if (prParams->set == 1) { + rstatus = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC) wlanoidSetSwCtrlWrite, + &prParams->adr, (uint32_t) 8, + FALSE, FALSE, TRUE, &u4SetInfoLen); + } + } + + if (rstatus != WLAN_STATUS_SUCCESS) + fgIsValid = -EFAULT; + + return fgIsValid; +} + +static int mtk_wlan_cfg_testmode_cmd(struct wiphy *wiphy, + void *data, int len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct NL80211_DRIVER_TEST_MODE_PARAMS *prParams = NULL; + int32_t i4Status; + + ASSERT(wiphy); + + if (!data || !len) { + DBGLOG(REQ, ERROR, "mtk_cfg80211_testmode_cmd null data\n"); + return -EINVAL; + } + + if (!wiphy) { + DBGLOG(REQ, ERROR, + "mtk_cfg80211_testmode_cmd null wiphy\n"); + return -EINVAL; + } + + prGlueInfo = (struct GLUE_INFO *)wiphy_priv(wiphy); + prParams = (struct NL80211_DRIVER_TEST_MODE_PARAMS *)data; + + /* Clear the version byte */ + prParams->index = prParams->index & ~BITS(24, 31); + DBGLOG(INIT, TRACE, "params index=%x\n", prParams->index); + + switch (prParams->index) { + case TESTMODE_CMD_ID_SW_CMD: /* SW cmd */ + i4Status = mtk_cfg80211_testmode_sw_cmd(wiphy, data, len); + break; + case TESTMODE_CMD_ID_WAPI: /* WAPI */ +#if CFG_SUPPORT_WAPI + i4Status = mtk_cfg80211_testmode_set_key_ext(wiphy, data, + len); +#endif + break; + case 0x10: + i4Status = mtk_cfg80211_testmode_get_sta_statistics(wiphy, + data, len, prGlueInfo); + break; + case 0x20: + i4Status = mtk_cfg80211_testmode_get_link_detection(wiphy, + data, len, prGlueInfo); + break; +#if CFG_SUPPORT_PASSPOINT + case TESTMODE_CMD_ID_HS20: + i4Status = mtk_cfg80211_testmode_hs20_cmd(wiphy, data, len); + break; +#endif /* CFG_SUPPORT_PASSPOINT */ + case TESTMODE_CMD_ID_STR_CMD: + i4Status = mtk_cfg80211_process_str_cmd(prGlueInfo, + (uint8_t *)(prParams + 1), len - sizeof(*prParams)); + break; + + default: + i4Status = -EINVAL; + break; + } + + if (i4Status != 0) + DBGLOG(REQ, TRACE, "prParams->index=%d, status=%d\n", + prParams->index, i4Status); + + return i4Status; +} + +#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_testmode_cmd(struct wiphy *wiphy, + struct wireless_dev *wdev, + void *data, int len) +{ + ASSERT(wdev); + return mtk_wlan_cfg_testmode_cmd(wiphy, data, len); +} +#else +int mtk_cfg80211_testmode_cmd(struct wiphy *wiphy, + void *data, int len) +{ + return mtk_wlan_cfg_testmode_cmd(wiphy, data, len); +} +#endif +#endif + +#if CFG_SUPPORT_SCHED_SCAN +int mtk_cfg80211_sched_scan_start(IN struct wiphy *wiphy, + IN struct net_device *ndev, + IN struct cfg80211_sched_scan_request *request) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint32_t i, u4BufLen; + struct PARAM_SCHED_SCAN_REQUEST *prSchedScanRequest; + uint32_t num = 0; + + if (likely(request)) { + scanlog_dbg(LOG_SCHED_SCAN_REQ_START_K2D, INFO, "ssid(%d)match(%d)ch(%u)f(%u)rssi(%d)\n", + request->n_ssids, request->n_match_sets, + request->n_channels, request->flags, +#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE + request->min_rssi_thold); +#else + request->rssi_thold); +#endif + } else + scanlog_dbg(LOG_SCHED_SCAN_REQ_START_K2D, INFO, "--> %s()\n", + __func__); + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + if (prGlueInfo->prAdapter == NULL) { + DBGLOG(REQ, ERROR, "prGlueInfo->prAdapter is NULL"); + return -EINVAL; + } + +#if CFG_SUPPORT_LOWLATENCY_MODE + if (!prGlueInfo->prAdapter->fgEnCfg80211Scan + && PARAM_MEDIA_STATE_CONNECTED + == kalGetMediaStateIndicated(prGlueInfo)) { + DBGLOG(REQ, INFO, + "sched_scan_start LowLatency reject scan\n"); + return -EBUSY; + } +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + + if (prGlueInfo->prSchedScanRequest != NULL) { + DBGLOG(SCN, ERROR, + "GlueInfo->prSchedScanRequest != NULL\n"); + return -EBUSY; + } else if (request == NULL) { + DBGLOG(SCN, ERROR, "request == NULL\n"); + return -EINVAL; + } else if (!request->n_match_sets) { + /* invalid scheduled scan request */ + DBGLOG(SCN, ERROR, + "No match sets. No need to do sched scan\n"); + return -EINVAL; + } else if (request->n_match_sets > + CFG_SCAN_SSID_MATCH_MAX_NUM) { + DBGLOG(SCN, WARN, "request->n_match_sets(%d) > %d\n", + request->n_match_sets, + CFG_SCAN_SSID_MATCH_MAX_NUM); + return -EINVAL; + } else if (request->n_ssids > + CFG_SCAN_HIDDEN_SSID_MAX_NUM) { + DBGLOG(SCN, WARN, "request->n_ssids(%d) > %d\n", + request->n_ssids, CFG_SCAN_HIDDEN_SSID_MAX_NUM); + return -EINVAL; + } + + prSchedScanRequest = (struct PARAM_SCHED_SCAN_REQUEST *) + kalMemAlloc(sizeof(struct PARAM_SCHED_SCAN_REQUEST), + VIR_MEM_TYPE); + if (prSchedScanRequest == NULL) { + DBGLOG(SCN, ERROR, "prSchedScanRequest kalMemAlloc fail\n"); + return -ENOMEM; + } + kalMemZero(prSchedScanRequest, + sizeof(struct PARAM_SCHED_SCAN_REQUEST)); + + /* passed in the probe_reqs in active scans */ + if (request->ssids) { + for (i = 0; i < request->n_ssids; i++) { + DBGLOG(SCN, TRACE, "ssids : (%d)[%s]\n", + i, request->ssids[i].ssid); + /* driver ignored the null ssid */ + if (request->ssids[i].ssid_len == 0 + || request->ssids[i].ssid[0] == 0) + DBGLOG(SCN, TRACE, "ignore null ssid(%d)\n", i); + else { + struct PARAM_SSID *prSsid; + + prSsid = &(prSchedScanRequest->arSsid[num]); + COPY_SSID(prSsid->aucSsid, prSsid->u4SsidLen, + request->ssids[i].ssid, + request->ssids[i].ssid_len); + num++; + } + } + } + prSchedScanRequest->u4SsidNum = num; +#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE + prSchedScanRequest->i4MinRssiThold = + request->min_rssi_thold; +#else + prSchedScanRequest->i4MinRssiThold = request->rssi_thold; +#endif + + num = 0; + if (request->match_sets) { + for (i = 0; i < request->n_match_sets; i++) { + DBGLOG(SCN, TRACE, "match : (%d)[%s]\n", i, + request->match_sets[i].ssid.ssid); + /* driver ignored the null ssid */ + if (request->match_sets[i].ssid.ssid_len == 0 + || request->match_sets[i].ssid.ssid[0] == 0) + DBGLOG(SCN, TRACE, "ignore null ssid(%d)\n", i); + else { + struct PARAM_SSID *prSsid = + &(prSchedScanRequest->arMatchSsid[num]); + + COPY_SSID(prSsid->aucSsid, + prSsid->u4SsidLen, + request->match_sets[i].ssid.ssid, + request->match_sets[i].ssid.ssid_len); +#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE + prSchedScanRequest->ai4RssiThold[i] = + request->match_sets[i].rssi_thold; +#else + prSchedScanRequest->ai4RssiThold[i] = + request->rssi_thold; +#endif + num++; + } + } + } + prSchedScanRequest->u4MatchSsidNum = num; + + if (kalSchedScanParseRandomMac(ndev, request, + prSchedScanRequest->aucRandomMac, + prSchedScanRequest->aucRandomMacMask)) { + prSchedScanRequest->ucScnFuncMask |= ENUM_SCN_RANDOM_MAC_EN; + } + + prSchedScanRequest->u4IELength = request->ie_len; + if (request->ie_len > 0) { + prSchedScanRequest->pucIE = + kalMemAlloc(request->ie_len, VIR_MEM_TYPE); + if (prSchedScanRequest->pucIE == NULL) { + DBGLOG(SCN, ERROR, "pucIE kalMemAlloc fail\n"); + } else { + kalMemZero(prSchedScanRequest->pucIE, request->ie_len); + kalMemCopy(prSchedScanRequest->pucIE, + (uint8_t *)request->ie, request->ie_len); + } + } + +#if KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE + prSchedScanRequest->u2ScanInterval = + (uint16_t) (request->scan_plans->interval); +#else + prSchedScanRequest->u2ScanInterval = (uint16_t) ( + request->interval); +#endif + + prSchedScanRequest->ucChnlNum = (uint8_t) + request->n_channels; + prSchedScanRequest->pucChannels = + kalMemAlloc(request->n_channels, VIR_MEM_TYPE); + if (!prSchedScanRequest->pucChannels) { + DBGLOG(SCN, ERROR, "pucChannels kalMemAlloc fail\n"); + prSchedScanRequest->ucChnlNum = 0; + } else { + for (i = 0; i < request->n_channels; i++) { + uint32_t freq = + request->channels[i]->center_freq * 1000; + + prSchedScanRequest->pucChannels[i] = + nicFreq2ChannelNum(freq); + } + } + + rStatus = kalIoctl(prGlueInfo, wlanoidSetStartSchedScan, + prSchedScanRequest, + sizeof(struct PARAM_SCHED_SCAN_REQUEST), + FALSE, FALSE, TRUE, &u4BufLen); + + kalMemFree(prSchedScanRequest->pucChannels, + VIR_MEM_TYPE, request->n_channels); + kalMemFree(prSchedScanRequest->pucIE, + VIR_MEM_TYPE, request->ie_len); + kalMemFree(prSchedScanRequest, + VIR_MEM_TYPE, sizeof(struct PARAM_SCHED_SCAN_REQUEST)); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "scheduled scan error:%x\n", rStatus); + return -EINVAL; + } + + prGlueInfo->prSchedScanRequest = request; + + return 0; +} + +int mtk_cfg80211_sched_scan_stop(IN struct wiphy *wiphy, + IN struct net_device *ndev) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint32_t u4BufLen; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + scanlog_dbg(LOG_SCHED_SCAN_REQ_STOP_K2D, INFO, "--> %s()\n", __func__); + + /* check if there is any pending scan/sched_scan not yet finished */ + if (prGlueInfo->prSchedScanRequest == NULL) + return -EPERM; /* Operation not permitted */ + + rStatus = kalIoctl(prGlueInfo, wlanoidSetStopSchedScan, + NULL, 0, + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_FAILURE) { + DBGLOG(REQ, WARN, "scheduled scan error:%x\n", rStatus); + return -EINVAL; + } + prGlueInfo->prSchedScanRequest = NULL; + + return 0; +} +#endif /* CFG_SUPPORT_SCHED_SCAN */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for handling association request + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_assoc(struct wiphy *wiphy, + struct net_device *ndev, struct cfg80211_assoc_request *req) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t arBssid[PARAM_MAC_ADDR_LEN]; +#if CFG_SUPPORT_PASSPOINT + uint8_t *prDesiredIE = NULL; +#endif /* CFG_SUPPORT_PASSPOINT */ + uint32_t rStatus; + uint32_t u4BufLen; +#if CFG_SUPPORT_CFG80211_AUTH + enum ENUM_WEP_STATUS eEncStatus; + enum ENUM_PARAM_AUTH_MODE eAuthMode; + uint32_t cipher; + uint32_t i, u4AkmSuite; + struct DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY *prEntry; + struct CONNECTION_SETTINGS *prConnSettings = NULL; + uint8_t *prDesiredIE = NULL; + uint8_t *pucIEStart = NULL; + struct RSN_INFO rRsnInfo; + struct STA_RECORD *prStaRec = NULL; +#if CFG_SUPPORT_802_11R + uint32_t u4InfoBufLen = 0; +#endif +struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; +struct P2P_CONNECTION_REQ_INFO *prConnReqInfo = + (struct P2P_CONNECTION_REQ_INFO *) NULL; +#endif + +#if CFG_SUPPORT_CFG80211_AUTH + rRsnInfo.u2PmkidCnt = 0; + kalMemZero(rRsnInfo.aucPmkidList, sizeof(rRsnInfo.aucPmkidList)); +#endif + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if CFG_SUPPORT_CFG80211_AUTH + prConnSettings = &prGlueInfo->prAdapter->rWifiVar.rConnSettings; + + /* [todo]temp use for indicate rx assoc resp, + * may need to be modified + */ + + /* The BSS from cfg80211_ops.assoc must give back to + * cfg80211_send_rx_assoc() or to cfg80211_assoc_timeout(). + * To ensure proper refcounting, new association requests + * while already associating must be rejected. + */ + if (prConnSettings->bss) + return -ENOENT; + prConnSettings->bss = req->bss; +#endif + DBGLOG(REQ, INFO, "mtk_cfg80211_assoc, media state:%d\n", + prGlueInfo->eParamMediaStateIndicated); +#if CFG_SUPPORT_CFG80211_AUTH + if (!prConnSettings->fgIsP2pConn) +#endif + { + kalMemZero(arBssid, MAC_ADDR_LEN); + if (prGlueInfo->eParamMediaStateIndicated == + PARAM_MEDIA_STATE_CONNECTED) { + wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryBssid, + &arBssid[0], + sizeof(arBssid), + &u4BufLen); +#if CFG_SUPPORT_802_11R + if (req->crypto.akm_suites[0] + != WLAN_AKM_SUITE_FT_8021X + && req->crypto.akm_suites[0] + != WLAN_AKM_SUITE_FT_PSK) +#endif + /* 1. check BSSID */ + if (UNEQUAL_MAC_ADDR(arBssid, + req->bss->bssid)) { + /* wrong MAC address */ + DBGLOG(REQ, WARN, + "incorrect BSSID: [" MACSTR + "] currently connected BSSID[" + MACSTR "]\n", + MAC2STR(req->bss->bssid), + MAC2STR(arBssid)); + return -ENOENT; + } + } + } +#if CFG_SUPPORT_CFG80211_AUTH + /* <1> 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; +#if CFG_SUPPORT_802_11W + prGlueInfo->rWpaInfo.u4CipherGroupMgmt = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; + prGlueInfo->rWpaInfo.ucRSNMfpCap = RSN_AUTH_MFP_DISABLED; +#endif + prGlueInfo->rWpaInfo.ucRsneLen = 0; + + /* 2.Fill WPA version */ + if (req->crypto.wpa_versions & NL80211_WPA_VERSION_1) + prGlueInfo->rWpaInfo.u4WpaVersion = + IW_AUTH_WPA_VERSION_WPA; + else if (req->crypto.wpa_versions & NL80211_WPA_VERSION_2) + prGlueInfo->rWpaInfo.u4WpaVersion = + IW_AUTH_WPA_VERSION_WPA2; + else + prGlueInfo->rWpaInfo.u4WpaVersion = + IW_AUTH_WPA_VERSION_DISABLED; + DBGLOG(REQ, INFO, "wpa ver=%d\n", + prGlueInfo->rWpaInfo.u4WpaVersion); + + /* 3.Fill pairwise cipher suite */ + if (req->crypto.n_ciphers_pairwise) { + DBGLOG(RSN, INFO, "[wlan] cipher pairwise (%x)\n", + req->crypto.ciphers_pairwise[0]); + + prGlueInfo->prAdapter->rWifiVar.rConnSettings.rRsnInfo + .au4PairwiseKeyCipherSuite[0] = + req->crypto.ciphers_pairwise[0]; + switch (req->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; + case WLAN_CIPHER_SUITE_BIP_GMAC_256: + prGlueInfo->rWpaInfo.u4CipherPairwise = + IW_AUTH_CIPHER_GCMP256; + break; + case WLAN_CIPHER_SUITE_GCMP_256: + prGlueInfo->rWpaInfo.u4CipherPairwise = + IW_AUTH_CIPHER_GCMP256; + break; + default: + DBGLOG(REQ, WARN, + "invalid cipher pairwise (%d)\n", + req->crypto.ciphers_pairwise[0]); + return -EINVAL; + } + } + + /* 4. Fill group cipher suite */ + if (req->crypto.cipher_group) { + DBGLOG(RSN, INFO, "[wlan] cipher group (%x)\n", + req->crypto.cipher_group); + prGlueInfo->prAdapter->rWifiVar.rConnSettings.rRsnInfo + .u4GroupKeyCipherSuite = + req->crypto.cipher_group; + switch (req->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; + case WLAN_CIPHER_SUITE_BIP_GMAC_256: + prGlueInfo->rWpaInfo.u4CipherGroup = + IW_AUTH_CIPHER_GCMP256; + break; + case WLAN_CIPHER_SUITE_GCMP_256: + prGlueInfo->rWpaInfo.u4CipherGroup = + IW_AUTH_CIPHER_GCMP256; + break; + case WLAN_CIPHER_SUITE_NO_GROUP_ADDR: + break; + default: + DBGLOG(REQ, WARN, "invalid cipher group (%d)\n", + req->crypto.cipher_group); + return -EINVAL; + } + } + + /* 5. Fill encryption status */ + cipher = prGlueInfo->rWpaInfo.u4CipherGroup | + prGlueInfo->rWpaInfo.u4CipherPairwise; + if (1 /* prGlueInfo->rWpaInfo.fgPrivacyInvoke */) { + if (cipher & IW_AUTH_CIPHER_GCMP256) { + eEncStatus = ENUM_ENCRYPTION4_ENABLED; + } else 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, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, + "set encryption mode error:%x\n", + rStatus); + + /* 6. Fill AKM suites */ + u4AkmSuite = 0; + eAuthMode = 0; + DBGLOG(REQ, INFO, "request numbers of Akm Suite:%d\n", + req->crypto.n_akm_suites); + for (i = 0; i < req->crypto.n_akm_suites; i++) + DBGLOG(REQ, INFO, "request Akm Suite[%d]:%d\n", + i, req->crypto.akm_suites[i]); + + if (req->crypto.n_akm_suites) { + prGlueInfo->prAdapter->rWifiVar.rConnSettings.rRsnInfo + .au4AuthKeyMgtSuite[0] = + req->crypto.akm_suites[0]; + DBGLOG(REQ, INFO, + "Akm Suite:%d\n", + req->crypto.akm_suites[0]); + + if (prGlueInfo->rWpaInfo.u4WpaVersion == + IW_AUTH_WPA_VERSION_WPA) { + switch (req->crypto.akm_suites[0]) { + case WLAN_AKM_SUITE_8021X: + eAuthMode = AUTH_MODE_WPA; + u4AkmSuite = WPA_AKM_SUITE_802_1X; + break; + case WLAN_AKM_SUITE_PSK: + eAuthMode = AUTH_MODE_WPA_PSK; + u4AkmSuite = WPA_AKM_SUITE_PSK; + break; + default: + DBGLOG(REQ, WARN, + "invalid Akm Suite (%08x)\n", + req->crypto.akm_suites[0]); + return -EINVAL; + } + } else if (prGlueInfo->rWpaInfo.u4WpaVersion == + IW_AUTH_WPA_VERSION_WPA2) { + switch (req->crypto.akm_suites[0]) { + case WLAN_AKM_SUITE_8021X: + eAuthMode = AUTH_MODE_WPA2; + u4AkmSuite = RSN_AKM_SUITE_802_1X; + break; + case WLAN_AKM_SUITE_PSK: + eAuthMode = AUTH_MODE_WPA2_PSK; + u4AkmSuite = RSN_AKM_SUITE_PSK; + break; +#if CFG_SUPPORT_802_11R + case WLAN_AKM_SUITE_FT_8021X: + eAuthMode = AUTH_MODE_WPA2_FT; + u4AkmSuite = RSN_AKM_SUITE_FT_802_1X; + break; + case WLAN_AKM_SUITE_FT_PSK: + eAuthMode = AUTH_MODE_WPA2_FT_PSK; + u4AkmSuite = RSN_AKM_SUITE_FT_PSK; + break; +#endif +#if CFG_SUPPORT_802_11W + /* Notice:: Need kernel patch!! */ + case WLAN_AKM_SUITE_8021X_SHA256: + eAuthMode = AUTH_MODE_WPA2; + u4AkmSuite = + RSN_AKM_SUITE_802_1X_SHA256; + break; + case WLAN_AKM_SUITE_PSK_SHA256: + eAuthMode = AUTH_MODE_WPA2_PSK; + u4AkmSuite = + RSN_AKM_SUITE_PSK_SHA256; + break; +#endif + case WLAN_AKM_SUITE_8021X_SUITE_B: + eAuthMode = AUTH_MODE_WPA2_PSK; + u4AkmSuite = + RSN_AKM_SUITE_8021X_SUITE_B_192; + break; + + case WLAN_AKM_SUITE_8021X_SUITE_B_192: + eAuthMode = AUTH_MODE_WPA2_PSK; + u4AkmSuite = + RSN_AKM_SUITE_8021X_SUITE_B_192; + break; +#if CFG_SUPPORT_SAE + /* Need to add in WPA also? */ + case WLAN_AKM_SUITE_SAE: + eAuthMode = AUTH_MODE_WPA2_SAE; + u4AkmSuite = RSN_AKM_SUITE_SAE; + break; +#endif +#if CFG_SUPPORT_OWE + case WLAN_AKM_SUITE_OWE: + eAuthMode = AUTH_MODE_WPA2_PSK; + u4AkmSuite = RSN_AKM_SUITE_OWE; + break; +#endif + default: + DBGLOG(REQ, WARN, + "invalid Akm Suite (%08x)\n", + req->crypto.akm_suites[0]); + 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; + } + + DBGLOG(REQ, INFO, "set auth mode:%d, akm suite:0x%x\n", + eAuthMode, u4AkmSuite); + + /* 6.1 Set auth mode*/ + rStatus = kalIoctl(prGlueInfo, wlanoidSetAuthMode, &eAuthMode, + sizeof(eAuthMode), FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "set auth mode error:%x\n", rStatus); + + /* 6.2 Enable the specific AKM suite only. */ + for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) { + prEntry = &prGlueInfo->prAdapter + ->rMib.dot11RSNAConfigAuthenticationSuitesTable[i]; + + if (prEntry->dot11RSNAConfigAuthenticationSuite == u4AkmSuite) { + prEntry->dot11RSNAConfigAuthenticationSuiteEnabled + = TRUE; + DBGLOG(REQ, INFO, "match AuthenticationSuite = 0x%x", + u4AkmSuite); + } else { + prEntry->dot11RSNAConfigAuthenticationSuiteEnabled + = FALSE; + } + } +#endif + + /* 7. Parsing desired ie from upper layer */ + prGlueInfo->fgWpsActive = FALSE; + + if (req->ie && req->ie_len > 0) { +#if CFG_SUPPORT_CFG80211_AUTH + pucIEStart = (uint8_t *)req->ie; +#endif +#if CFG_SUPPORT_PASSPOINT + if (wextSrchDesiredHS20IE((uint8_t *) req->ie, req->ie_len, + (uint8_t **) &prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, wlanoidSetHS20Info, + prDesiredIE, IE_SIZE(prDesiredIE), + FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + /* DBGLOG(REQ, TRACE, + * ("[HS20] set HS20 assoc info error:%x\n", + * rStatus)); + */ + } + } + + if (wextSrchDesiredInterworkingIE((uint8_t *) req->ie, + req->ie_len, (uint8_t **) &prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetInterworkingInfo, prDesiredIE, + IE_SIZE(prDesiredIE), + FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + /* DBGLOG(REQ, TRACE, + * ("[HS20] set Interworking assoc info error: + * %x\n", rStatus)); + */ + } + } + + if (wextSrchDesiredRoamingConsortiumIE((uint8_t *) req->ie, + req->ie_len, (uint8_t **) &prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRoamingConsortiumIEInfo, + prDesiredIE, IE_SIZE(prDesiredIE), + FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + /* DBGLOG(REQ, TRACE, + * ("[HS20] set RoamingConsortium assoc info + * error:%x\n", rStatus)); + */ + } + } +#endif /* CFG_SUPPORT_PASSPOINT */ +#if CFG_SUPPORT_CFG80211_AUTH + if (wextSrchDesiredWPAIE(pucIEStart, req->ie_len, 0x30, + (uint8_t **) &prDesiredIE)) { + if (rsnParseRsnIE(prGlueInfo->prAdapter, + (struct RSN_INFO_ELEM *)prDesiredIE, + &rRsnInfo)) { +#if CFG_SUPPORT_802_11W + /* Fill RSNE MFP Cap */ + if (rRsnInfo.u2RsnCap & ELEM_WPA_CAP_MFPC) { + prGlueInfo->rWpaInfo.u4CipherGroupMgmt + = rRsnInfo + .u4GroupMgmtKeyCipherSuite; + prGlueInfo->rWpaInfo.ucRSNMfpCap = + RSN_AUTH_MFP_OPTIONAL; + if (rRsnInfo.u2RsnCap & + ELEM_WPA_CAP_MFPR) + prGlueInfo->rWpaInfo.ucRSNMfpCap + = RSN_AUTH_MFP_REQUIRED; + } else + prGlueInfo->rWpaInfo.ucRSNMfpCap = + RSN_AUTH_MFP_DISABLED; +#endif + prGlueInfo->rWpaInfo.ucRsneLen = rRsnInfo.ucRsneLen; + + /* Fill RSNE PMKID Count and List */ + prConnSettings->rRsnInfo.u2PmkidCnt = + rRsnInfo.u2PmkidCnt; + if (rRsnInfo.u2PmkidCnt > 0) + kalMemCopy(prConnSettings + ->rRsnInfo.aucPmkidList, + rRsnInfo.aucPmkidList, + (rRsnInfo.u2PmkidCnt * RSN_PMKID_LEN)); + + } + } + +#if CFG_SUPPORT_OWE + /* Gen OWE IE */ + if (wextSrchDesiredWPAIE(pucIEStart, req->ie_len, 0xff, + (uint8_t **) &prDesiredIE)) { + uint8_t ucLength = (*(prDesiredIE+1)+2); + + kalMemCopy(&prGlueInfo->prAdapter + ->rWifiVar.rConnSettings.rOweInfo, + prDesiredIE, ucLength); + + DBGLOG(REQ, INFO, "DUMP OWE INFO, EID %x length %x\n", + *prDesiredIE, ucLength); + DBGLOG_MEM8(REQ, INFO, &prGlueInfo->prAdapter + ->rWifiVar.rConnSettings.rOweInfo, ucLength); + } else { + kalMemSet(&prGlueInfo->prAdapter + ->rWifiVar.rConnSettings.rOweInfo, + 0, sizeof(struct OWE_INFO_T)); + } +#endif +#if CFG_SUPPORT_802_11R + if (prGlueInfo->prAdapter->rWifiVar + .rConnSettings.eAuthMode == AUTH_MODE_WPA2_FT || + prGlueInfo->prAdapter->rWifiVar.rConnSettings.eAuthMode == + AUTH_MODE_WPA2_FT_PSK) { + rStatus = kalIoctl(prGlueInfo, wlanoidUpdateFtIes, + (void *)pucIEStart, req->ie_len, FALSE, + FALSE, FALSE, &u4InfoBufLen); + DBGLOG(REQ, TRACE, + "wlanoidUpdateFtIes rStatus 0x%x\n", rStatus); + } +#endif +#endif + } + + /* Fill WPA info - mfp setting */ + /* Must put after paring RSNE from upper layer + * for prGlueInfo->rWpaInfo.ucRSNMfpCap assignment + */ +#if CFG_SUPPORT_802_11W + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; + if (req->use_mfp) + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_REQUIRED; + else { + /* Change Mfp parameter from DISABLED to OPTIONAL + * if upper layer set MFPC = 1 in RSNE + * since upper layer can't bring MFP OPTIONAL information + * to driver by sme->mfp + */ + if (prGlueInfo->rWpaInfo.ucRSNMfpCap == + RSN_AUTH_MFP_OPTIONAL) + prGlueInfo->rWpaInfo.u4Mfp = + IW_AUTH_MFP_OPTIONAL; + else if (prGlueInfo->rWpaInfo.ucRSNMfpCap == + RSN_AUTH_MFP_REQUIRED) + DBGLOG(REQ, WARN, + "mfp parameter(DISABLED) conflict with mfp cap(REQUIRED)\n"); + } + /* DBGLOG(REQ, INFO, "MFP=%d\n", prGlueInfo->rWpaInfo.u4Mfp); */ +#endif + +#if CFG_SUPPORT_CFG80211_AUTH + /*[TODO]may to check if assoc + * parameters change as cfg80211_auth + */ + prConnSettings->fgIsSendAssoc = TRUE; + if ((!prConnSettings->fgIsConnInitialized) && + (prConnSettings->fgIsP2pConn != TRUE)) { + rStatus = kalIoctl(prGlueInfo, wlanoidSetBssid, + (void *) req->bss->bssid, MAC_ADDR_LEN, + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set BSSID:%x\n", rStatus); + return -EINVAL; + } + } else { /* skip join initial flow when it has been completed*/ + if ((mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) && + prConnSettings->fgIsP2pConn) { + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO( + prGlueInfo->prAdapter, + prConnSettings->ucRoleIdx); + prStaRec = prP2pRoleFsmInfo->rJoinInfo.prTargetStaRec; + prConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + kalMemCopy(prConnReqInfo->aucIEBuf, + req->ie, req->ie_len); + prConnReqInfo->u4BufLength = req->ie_len; + + /* set crypto */ + kalP2PSetCipher(prGlueInfo, IW_AUTH_CIPHER_NONE, + prConnSettings->ucRoleIdx); + DBGLOG(REQ, INFO, + "n_ciphers_pairwise %d, ciphers_pairwise[0] %#x\n", + req->crypto.n_ciphers_pairwise, + req->crypto.ciphers_pairwise[0]); + + if (req->crypto.n_ciphers_pairwise) { + switch (req->crypto.ciphers_pairwise[0]) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + kalP2PSetCipher(prGlueInfo, + IW_AUTH_CIPHER_WEP40, + prConnSettings->ucRoleIdx); + break; + case WLAN_CIPHER_SUITE_TKIP: + kalP2PSetCipher(prGlueInfo, + IW_AUTH_CIPHER_TKIP, + prConnSettings->ucRoleIdx); + break; + case WLAN_CIPHER_SUITE_CCMP: + case WLAN_CIPHER_SUITE_AES_CMAC: + kalP2PSetCipher(prGlueInfo, + IW_AUTH_CIPHER_CCMP, + prConnSettings->ucRoleIdx); + break; + default: + DBGLOG(REQ, WARN, + "invalid cipher pairwise (%d)\n", + req->crypto + .ciphers_pairwise[0]); + /* do cfg80211_put_bss before return */ + return -EINVAL; + } + } + /* end */ + } else { + prStaRec = cnmGetStaRecByAddress(prGlueInfo->prAdapter, + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex, + req->bss->bssid); + } + + if (prStaRec) + saaSendAuthAssoc(prGlueInfo->prAdapter, + prStaRec); + else + DBGLOG(REQ, WARN, + "can't send auth since can't find StaRec\n"); + } +#else + rStatus = kalIoctl(prGlueInfo, wlanoidSetBssid, + (void *)req->bss->bssid, MAC_ADDR_LEN, + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set BSSID:%x\n", rStatus); + return -EINVAL; + } +#endif + return 0; +} + +#if CFG_SUPPORT_NFC_BEAM_PLUS + +int mtk_cfg80211_testmode_get_scan_done(IN struct wiphy + *wiphy, IN void *data, IN int len, + IN struct GLUE_INFO *prGlueInfo) +{ + int32_t i4Status = -EINVAL; + +#ifdef CONFIG_NL80211_TESTMODE +#define NL80211_TESTMODE_P2P_SCANDONE_INVALID 0 +#define NL80211_TESTMODE_P2P_SCANDONE_STATUS 1 + + uint32_t rStatus = WLAN_STATUS_SUCCESS; + int32_t READY_TO_BEAM = 0; + + struct sk_buff *skb = NULL; + + ASSERT(wiphy); + ASSERT(prGlueInfo); + + skb = cfg80211_testmode_alloc_reply_skb(wiphy, + sizeof(uint32_t)); + + /* READY_TO_BEAM = + * (UINT_32)(prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo + * .fgIsGOInitialDone) + * &(!prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo + * .fgIsScanRequest); + */ + READY_TO_BEAM = 1; + /* DBGLOG(QM, TRACE, + * "NFC:GOInitialDone[%d] and P2PScanning[%d]\n", + * prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo + * .fgIsGOInitialDone, + * prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo + * .fgIsScanRequest)); + */ + + if (!skb) { + DBGLOG(QM, TRACE, "%s allocate skb failed:%x\n", __func__, + rStatus); + return -ENOMEM; + } + { + u8 __tmp = 0; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_P2P_SCANDONE_INVALID, + sizeof(u8), &__tmp) < 0)) { + kfree_skb(skb); + return -EINVAL; + } + } + { + u32 __tmp = READY_TO_BEAM; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_P2P_SCANDONE_STATUS, + sizeof(u32), &__tmp) < 0)) { + kfree_skb(skb); + return -EINVAL; + } + } + + i4Status = cfg80211_testmode_reply(skb); +#else + DBGLOG(QM, WARN, "CONFIG_NL80211_TESTMODE not enabled\n"); +#endif + return i4Status; +} + +#endif + +#if CFG_SUPPORT_TDLS + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for changing a station information + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int +mtk_cfg80211_change_station(struct wiphy *wiphy, + struct net_device *ndev, const u8 *mac, + struct station_parameters *params) +{ + + /* return 0; */ + + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + struct GLUE_INFO *prGlueInfo = NULL; + struct CMD_PEER_UPDATE rCmdUpdate; + uint32_t rStatus; + uint32_t u4BufLen, u4Temp; + struct ADAPTER *prAdapter; + struct BSS_INFO *prAisBssInfo; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, INFO, "mtk_cfg80211_change_station\n"); + /* make up command */ + + prAdapter = prGlueInfo->prAdapter; + prAisBssInfo = prAdapter->prAisBssInfo; + + if (params == NULL) + return 0; + else if (params->supported_rates == NULL) + return 0; + + /* init */ + kalMemZero(&rCmdUpdate, sizeof(rCmdUpdate)); + kalMemCopy(rCmdUpdate.aucPeerMac, mac, 6); + + if (params->supported_rates != NULL) { + + u4Temp = params->supported_rates_len; + if (u4Temp > CMD_PEER_UPDATE_SUP_RATE_MAX) + u4Temp = CMD_PEER_UPDATE_SUP_RATE_MAX; + kalMemCopy(rCmdUpdate.aucSupRate, params->supported_rates, + u4Temp); + rCmdUpdate.u2SupRateLen = u4Temp; + } + + /* + * In supplicant, only recognize WLAN_EID_QOS 46, not 0xDD WMM + * So force to support UAPSD here. + */ + rCmdUpdate.UapsdBitmap = 0x0F; /*params->uapsd_queues; */ + rCmdUpdate.UapsdMaxSp = 0; /*params->max_sp; */ + + rCmdUpdate.u2Capability = params->capability; + + if (params->ext_capab != NULL) { + + u4Temp = params->ext_capab_len; + if (u4Temp > CMD_PEER_UPDATE_EXT_CAP_MAXLEN) + u4Temp = CMD_PEER_UPDATE_EXT_CAP_MAXLEN; + kalMemCopy(rCmdUpdate.aucExtCap, params->ext_capab, u4Temp); + rCmdUpdate.u2ExtCapLen = u4Temp; + } + + if (params->ht_capa != NULL) { + + rCmdUpdate.rHtCap.u2CapInfo = params->ht_capa->cap_info; + rCmdUpdate.rHtCap.ucAmpduParamsInfo = + params->ht_capa->ampdu_params_info; + rCmdUpdate.rHtCap.u2ExtHtCapInfo = + params->ht_capa->extended_ht_cap_info; + rCmdUpdate.rHtCap.u4TxBfCapInfo = + params->ht_capa->tx_BF_cap_info; + rCmdUpdate.rHtCap.ucAntennaSelInfo = + params->ht_capa->antenna_selection_info; + kalMemCopy(rCmdUpdate.rHtCap.rMCS.arRxMask, + params->ht_capa->mcs.rx_mask, + sizeof(rCmdUpdate.rHtCap.rMCS.arRxMask)); + + rCmdUpdate.rHtCap.rMCS.u2RxHighest = + params->ht_capa->mcs.rx_highest; + rCmdUpdate.rHtCap.rMCS.ucTxParams = + params->ht_capa->mcs.tx_params; + rCmdUpdate.fgIsSupHt = TRUE; + } + /* vht */ + + if (params->vht_capa != NULL) { + /* rCmdUpdate.rVHtCap */ + /* rCmdUpdate.rVHtCap */ + } + + /* update a TDLS peer record */ + /* sanity check */ + if ((params->sta_flags_set & BIT( + NL80211_STA_FLAG_TDLS_PEER))) + rCmdUpdate.eStaType = STA_TYPE_DLS_PEER; + rStatus = kalIoctl(prGlueInfo, cnmPeerUpdate, &rCmdUpdate, + sizeof(struct CMD_PEER_UPDATE), FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EINVAL; + /* for Ch Sw AP prohibit case */ + if (prAisBssInfo->fgTdlsIsChSwProhibited) { + /* disable TDLS ch sw function */ + + rStatus = kalIoctl(prGlueInfo, + TdlsSendChSwControlCmd, + &TdlsSendChSwControlCmd, + sizeof(struct CMD_TDLS_CH_SW), + FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + } + + return 0; +} +#else +int +mtk_cfg80211_change_station(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac, + struct station_parameters *params) +{ + + /* return 0; */ + + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + struct GLUE_INFO *prGlueInfo = NULL; + struct CMD_PEER_UPDATE rCmdUpdate; + uint32_t rStatus; + uint32_t u4BufLen, u4Temp; + struct ADAPTER *prAdapter; + struct BSS_INFO *prAisBssInfo; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, INFO, "mtk_cfg80211_change_station\n"); + /* make up command */ + + prAdapter = prGlueInfo->prAdapter; + prAisBssInfo = prAdapter->prAisBssInfo; + + if (params == NULL) + return 0; + else if (params->supported_rates == NULL) + return 0; + + /* init */ + kalMemZero(&rCmdUpdate, sizeof(rCmdUpdate)); + kalMemCopy(rCmdUpdate.aucPeerMac, mac, 6); + + if (params->supported_rates != NULL) { + + u4Temp = params->supported_rates_len; + if (u4Temp > CMD_PEER_UPDATE_SUP_RATE_MAX) + u4Temp = CMD_PEER_UPDATE_SUP_RATE_MAX; + kalMemCopy(rCmdUpdate.aucSupRate, params->supported_rates, + u4Temp); + rCmdUpdate.u2SupRateLen = u4Temp; + } + + /* + * In supplicant, only recognize WLAN_EID_QOS 46, not 0xDD WMM + * So force to support UAPSD here. + */ + rCmdUpdate.UapsdBitmap = 0x0F; /*params->uapsd_queues; */ + rCmdUpdate.UapsdMaxSp = 0; /*params->max_sp; */ + + rCmdUpdate.u2Capability = params->capability; + + if (params->ext_capab != NULL) { + + u4Temp = params->ext_capab_len; + if (u4Temp > CMD_PEER_UPDATE_EXT_CAP_MAXLEN) + u4Temp = CMD_PEER_UPDATE_EXT_CAP_MAXLEN; + kalMemCopy(rCmdUpdate.aucExtCap, params->ext_capab, u4Temp); + rCmdUpdate.u2ExtCapLen = u4Temp; + } + + if (params->ht_capa != NULL) { + + rCmdUpdate.rHtCap.u2CapInfo = params->ht_capa->cap_info; + rCmdUpdate.rHtCap.ucAmpduParamsInfo = + params->ht_capa->ampdu_params_info; + rCmdUpdate.rHtCap.u2ExtHtCapInfo = + params->ht_capa->extended_ht_cap_info; + rCmdUpdate.rHtCap.u4TxBfCapInfo = + params->ht_capa->tx_BF_cap_info; + rCmdUpdate.rHtCap.ucAntennaSelInfo = + params->ht_capa->antenna_selection_info; + kalMemCopy(rCmdUpdate.rHtCap.rMCS.arRxMask, + params->ht_capa->mcs.rx_mask, + sizeof(rCmdUpdate.rHtCap.rMCS.arRxMask)); + + rCmdUpdate.rHtCap.rMCS.u2RxHighest = + params->ht_capa->mcs.rx_highest; + rCmdUpdate.rHtCap.rMCS.ucTxParams = + params->ht_capa->mcs.tx_params; + rCmdUpdate.fgIsSupHt = TRUE; + } + /* vht */ + + if (params->vht_capa != NULL) { + /* rCmdUpdate.rVHtCap */ + /* rCmdUpdate.rVHtCap */ + } + + /* update a TDLS peer record */ + /* sanity check */ + if ((params->sta_flags_set & BIT( + NL80211_STA_FLAG_TDLS_PEER))) + rCmdUpdate.eStaType = STA_TYPE_DLS_PEER; + rStatus = kalIoctl(prGlueInfo, cnmPeerUpdate, &rCmdUpdate, + sizeof(struct CMD_PEER_UPDATE), FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EINVAL; + /* for Ch Sw AP prohibit case */ + if (prAisBssInfo->fgTdlsIsChSwProhibited) { + /* disable TDLS ch sw function */ + + rStatus = kalIoctl(prGlueInfo, + TdlsSendChSwControlCmd, + &TdlsSendChSwControlCmd, + sizeof(struct CMD_TDLS_CH_SW), + FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + } + + return 0; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for adding a station information + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_add_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, struct station_parameters *params) +{ + /* return 0; */ + + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + struct GLUE_INFO *prGlueInfo = NULL; + struct CMD_PEER_ADD rCmdCreate; + struct ADAPTER *prAdapter; + uint32_t rStatus; + uint32_t u4BufLen; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + DBGLOG(REQ, INFO, "mtk_cfg80211_add_station\n"); + + /* make up command */ + + prAdapter = prGlueInfo->prAdapter; + + /* init */ + kalMemZero(&rCmdCreate, sizeof(rCmdCreate)); + kalMemCopy(rCmdCreate.aucPeerMac, mac, 6); + + /* create a TDLS peer record */ + if ((params->sta_flags_set & BIT( + NL80211_STA_FLAG_TDLS_PEER))) { + rCmdCreate.eStaType = STA_TYPE_DLS_PEER; + rStatus = kalIoctl(prGlueInfo, cnmPeerAdd, &rCmdCreate, + sizeof(struct CMD_PEER_ADD), + FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EINVAL; + } + + return 0; +} +#else +int mtk_cfg80211_add_station(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac, + struct station_parameters *params) +{ + /* return 0; */ + + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + struct GLUE_INFO *prGlueInfo = NULL; + struct CMD_PEER_ADD rCmdCreate; + struct ADAPTER *prAdapter; + uint32_t rStatus; + uint32_t u4BufLen; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + DBGLOG(REQ, INFO, "mtk_cfg80211_add_station\n"); + + /* make up command */ + + prAdapter = prGlueInfo->prAdapter; + + /* init */ + kalMemZero(&rCmdCreate, sizeof(rCmdCreate)); + kalMemCopy(rCmdCreate.aucPeerMac, mac, 6); + + /* create a TDLS peer record */ + if ((params->sta_flags_set & BIT( + NL80211_STA_FLAG_TDLS_PEER))) { + rCmdCreate.eStaType = STA_TYPE_DLS_PEER; + rStatus = kalIoctl(prGlueInfo, cnmPeerAdd, &rCmdCreate, + sizeof(struct CMD_PEER_ADD), + FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EINVAL; + } + + return 0; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for deleting a station information + * + * @param + * + * @retval 0: successful + * others: failure + * + * @other + * must implement if you have add_station(). + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +#if KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE +static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +int mtk_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *ndev, + struct station_del_parameters *params) +{ + /* fgIsTDLSlinkEnable = 0; */ + + /* return 0; */ + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + + const u8 *mac = params->mac ? params->mac : bcast_addr; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter; + struct STA_RECORD *prStaRec; + u8 deleteMac[MAC_ADDR_LEN]; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, INFO, "mtk_cfg80211_del_station\n"); + + prAdapter = prGlueInfo->prAdapter; + + /* For kernel 3.18 modification, we trasfer to local buff to query + * sta + */ + memset(deleteMac, 0, MAC_ADDR_LEN); + memcpy(deleteMac, mac, MAC_ADDR_LEN); + + prStaRec = cnmGetStaRecByAddress(prAdapter, + (uint8_t) prAdapter->prAisBssInfo->ucBssIndex, deleteMac); + + if (prStaRec != NULL) + cnmStaRecFree(prAdapter, prStaRec); + + return 0; +} +#else +int mtk_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *ndev, const u8 *mac) +{ + /* fgIsTDLSlinkEnable = 0; */ + + /* return 0; */ + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter; + struct STA_RECORD *prStaRec; + u8 deleteMac[MAC_ADDR_LEN]; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, INFO, "mtk_cfg80211_del_station\n"); + + prAdapter = prGlueInfo->prAdapter; + + /* For kernel 3.18 modification, we trasfer to local buff to query + * sta + */ + memset(deleteMac, 0, MAC_ADDR_LEN); + memcpy(deleteMac, mac, MAC_ADDR_LEN); + + prStaRec = cnmGetStaRecByAddress(prAdapter, + (uint8_t) prAdapter->prAisBssInfo->ucBssIndex, deleteMac); + + if (prStaRec != NULL) + cnmStaRecFree(prAdapter, prStaRec); + + return 0; +} +#endif +#else +int mtk_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac) +{ + /* fgIsTDLSlinkEnable = 0; */ + + /* return 0; */ + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter; + struct STA_RECORD *prStaRec; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, INFO, "mtk_cfg80211_del_station\n"); + + prAdapter = prGlueInfo->prAdapter; + + prStaRec = cnmGetStaRecByAddress(prAdapter, + (uint8_t) prAdapter->prAisBssInfo->ucBssIndex, mac); + + if (prStaRec != NULL) + cnmStaRecFree(prAdapter, prStaRec); + + return 0; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to transmit a TDLS data frame from nl80211. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[in] + * \param[in] + * \param[in] buf includes RSN IE + FT IE + Lifetimeout IE + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE +int +mtk_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, + bool initiator, const u8 *buf, size_t len) +{ + struct GLUE_INFO *prGlueInfo; + struct TDLS_CMD_LINK_MGT rCmdMgt; + uint32_t u4BufLen; + + DBGLOG(REQ, INFO, "mtk_cfg80211_tdls_mgmt\n"); + + /* sanity check */ + if ((wiphy == NULL) || (peer == NULL) || (buf == NULL)) + return -EINVAL; + + /* init */ + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + if (prGlueInfo == NULL) + return -EINVAL; + + kalMemZero(&rCmdMgt, sizeof(rCmdMgt)); + rCmdMgt.u2StatusCode = status_code; + rCmdMgt.u4SecBufLen = len; + rCmdMgt.ucDialogToken = dialog_token; + rCmdMgt.ucActionCode = action_code; + kalMemCopy(&(rCmdMgt.aucPeer), peer, 6); + + if (len > TDLS_SEC_BUF_LENGTH) { + DBGLOG(REQ, WARN, "%s:len > TDLS_SEC_BUF_LENGTH\n", __func__); + return -EINVAL; + } + + kalMemCopy(&(rCmdMgt.aucSecBuf), buf, len); + + kalIoctl(prGlueInfo, TdlsexLinkMgt, &rCmdMgt, + sizeof(struct TDLS_CMD_LINK_MGT), FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + return 0; + +} +#elif KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int +mtk_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, + const u8 *buf, size_t len) +{ + struct GLUE_INFO *prGlueInfo; + struct TDLS_CMD_LINK_MGT rCmdMgt; + uint32_t u4BufLen; + + DBGLOG(REQ, INFO, "mtk_cfg80211_tdls_mgmt\n"); + + /* sanity check */ + if ((wiphy == NULL) || (peer == NULL) || (buf == NULL)) + return -EINVAL; + + /* init */ + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + if (prGlueInfo == NULL) + return -EINVAL; + + kalMemZero(&rCmdMgt, sizeof(rCmdMgt)); + rCmdMgt.u2StatusCode = status_code; + rCmdMgt.u4SecBufLen = len; + rCmdMgt.ucDialogToken = dialog_token; + rCmdMgt.ucActionCode = action_code; + kalMemCopy(&(rCmdMgt.aucPeer), peer, 6); + kalMemCopy(&(rCmdMgt.aucSecBuf), buf, len); + + kalIoctl(prGlueInfo, TdlsexLinkMgt, &rCmdMgt, + sizeof(struct TDLS_CMD_LINK_MGT), FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + return 0; + +} + +#else +int +mtk_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, const u8 *buf, size_t len) +{ + struct GLUE_INFO *prGlueInfo; + struct TDLS_CMD_LINK_MGT rCmdMgt; + uint32_t u4BufLen; + + DBGLOG(REQ, INFO, "mtk_cfg80211_tdls_mgmt\n"); + + /* sanity check */ + if ((wiphy == NULL) || (peer == NULL) || (buf == NULL)) + return -EINVAL; + + /* init */ + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + if (prGlueInfo == NULL) + return -EINVAL; + + kalMemZero(&rCmdMgt, sizeof(rCmdMgt)); + rCmdMgt.u2StatusCode = status_code; + rCmdMgt.u4SecBufLen = len; + rCmdMgt.ucDialogToken = dialog_token; + rCmdMgt.ucActionCode = action_code; + kalMemCopy(&(rCmdMgt.aucPeer), peer, 6); + if (len > TDLS_SEC_BUF_LENGTH) + DBGLOG(REQ, WARN, + "In mtk_cfg80211_tdls_mgmt , len > TDLS_SEC_BUF_LENGTH, please check\n"); + else + kalMemCopy(&(rCmdMgt.aucSecBuf), buf, len); + + kalIoctl(prGlueInfo, TdlsexLinkMgt, &rCmdMgt, + sizeof(struct TDLS_CMD_LINK_MGT), FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + return 0; + +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to hadel TDLS link from nl80211. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[in] + * \param[in] + * \param[in] buf includes RSN IE + FT IE + Lifetimeout IE + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_tdls_oper(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, enum nl80211_tdls_operation oper) +{ + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4BufLen; + struct ADAPTER *prAdapter; + struct TDLS_CMD_LINK_OPER rCmdOper; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + DBGLOG(REQ, INFO, "mtk_cfg80211_tdls_oper\n"); + + ASSERT(prGlueInfo); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rCmdOper, sizeof(rCmdOper)); + kalMemCopy(rCmdOper.aucPeerMac, peer, 6); + + rCmdOper.oper = (enum ENUM_TDLS_LINK_OPER)oper; + + if (oper == NL80211_TDLS_DISABLE_LINK) { + /* [ALPS03767042] wlan: fix TDLS 5.3 test issue + * [Detail] + * Timing issue of data direct path design + * - Data sent directly through HW (new design in 6765) + * - Command sent to FW to process (original design) + * Issue occurs while + * - Tear down packet sent by wlanHardStartXmit(), + * but not real sent out + * - CMD_ID_REMOVE_STA_RECORD sent to FW to disable TDLS link + * [Solution] + * Short-term + * - Delay TDLS disable link to let tear down data package + * to send + * Long-term + * - Enhance the TDLS flow to guarantee TX can send out + * successfully + */ + DBGLOG(TDLS, INFO, "NL80211_TDLS_DISABLE_LINK, kalMsleep(20)"); + kalMsleep(20); + } + + kalIoctl(prGlueInfo, TdlsexLinkOper, &rCmdOper, + sizeof(struct TDLS_CMD_LINK_OPER), FALSE, FALSE, FALSE, + &u4BufLen); + return 0; +} +#else +int mtk_cfg80211_tdls_oper(struct wiphy *wiphy, + struct net_device *dev, u8 *peer, + enum nl80211_tdls_operation oper) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4BufLen; + struct ADAPTER *prAdapter; + struct TDLS_CMD_LINK_OPER rCmdOper; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, INFO, "mtk_cfg80211_tdls_oper\n"); + + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rCmdOper, sizeof(rCmdOper)); + kalMemCopy(rCmdOper.aucPeerMac, peer, 6); + + rCmdOper.oper = oper; + + if (oper == NL80211_TDLS_DISABLE_LINK) { + /* [ALPS03767042] wlan: fix TDLS 5.3 test issue + * [Detail] + * Timing issue of data direct path design + * - Data sent directly through HW (new design in 6765) + * - Command sent to FW to process (original design) + * Issue occurs while + * - Tear down packet sent by wlanHardStartXmit(), + * but not real sent out + * - CMD_ID_REMOVE_STA_RECORD sent to FW to disable TDLS link + * [Solution] + * Short-term + * - Delay TDLS disable link to let tear down data package + * to send + * Long-term + * - Enhance the TDLS flow to guarantee TX can send out + * successfully + */ + DBGLOG(TDLS, INFO, "NL80211_TDLS_DISABLE_LINK, kalMsleep(20)"); + kalMsleep(20); + } + + kalIoctl(prGlueInfo, TdlsexLinkOper, &rCmdOper, + sizeof(struct TDLS_CMD_LINK_OPER), FALSE, FALSE, FALSE, + &u4BufLen); + return 0; +} +#endif +#endif + +int32_t mtk_cfg80211_process_str_cmd(struct GLUE_INFO + *prGlueInfo, uint8_t *cmd, int32_t len) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4SetInfoLen = 0; + + if (strnicmp(cmd, "tdls-ps ", 8) == 0) { +#if CFG_SUPPORT_TDLS + rStatus = kalIoctl(prGlueInfo, + wlanoidDisableTdlsPs, + (void *)(cmd + 8), 1, + FALSE, FALSE, TRUE, &u4SetInfoLen); +#else + DBGLOG(REQ, WARN, "not support tdls\n"); + return -EOPNOTSUPP; +#endif + } else if (strncasecmp(cmd, "NEIGHBOR-REQUEST", 16) == 0) { + uint8_t *pucSSID = NULL; + uint32_t u4SSIDLen = 0; + + if (len > 16 && (strncasecmp(cmd+16, " SSID=", 6) == 0)) { + pucSSID = cmd + 22; + u4SSIDLen = len - 22; + DBGLOG(REQ, INFO, "cmd=%s, ssid len %u, ssid=%s\n", cmd, + u4SSIDLen, pucSSID); + } + rStatus = kalIoctl(prGlueInfo, wlanoidSendNeighborRequest, + (void *)pucSSID, u4SSIDLen, FALSE, FALSE, + TRUE, &u4SetInfoLen); + } else if (strncasecmp(cmd, "BSS-TRANSITION-QUERY", 20) == 0) { + uint8_t *pucReason = NULL; + + if (len > 20 && (strncasecmp(cmd+20, " reason=", 8) == 0)) + pucReason = cmd + 28; + rStatus = kalIoctl(prGlueInfo, wlanoidSendBTMQuery, + (void *)pucReason, 1, FALSE, FALSE, TRUE, + &u4SetInfoLen); + } else if (strnicmp(cmd, "OSHAREMOD ", 10) == 0) { +#if CFG_SUPPORT_OSHARE + struct OSHARE_MODE_T cmdBuf; + struct OSHARE_MODE_T *pCmdHeader = NULL; + struct OSHARE_MODE_SETTING_V1_T *pCmdData = NULL; + + kalMemZero(&cmdBuf, sizeof(cmdBuf)); + + pCmdHeader = &cmdBuf; + pCmdHeader->cmdVersion = OSHARE_MODE_CMD_V1; + pCmdHeader->cmdType = 1; /*1-set 0-query*/ + pCmdHeader->magicCode = OSHARE_MODE_MAGIC_CODE; + pCmdHeader->cmdBufferLen = MAX_OSHARE_MODE_LENGTH; + + pCmdData = (struct OSHARE_MODE_SETTING_V1_T *) & + (pCmdHeader->buffer[0]); + pCmdData->osharemode = *(uint8_t *)(cmd + 10) - '0'; + + DBGLOG(REQ, INFO, "cmd=%s, osharemode=%u\n", cmd, + pCmdData->osharemode); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetOshareMode, + &cmdBuf, + sizeof(struct OSHARE_MODE_T), + FALSE, + FALSE, + TRUE, + &u4SetInfoLen); + + if (rStatus == WLAN_STATUS_SUCCESS) + prGlueInfo->prAdapter->fgEnOshareMode + = pCmdData->osharemode; +#else + DBGLOG(REQ, WARN, "not support OSHAREMOD\n"); + return -EOPNOTSUPP; +#endif + } else + return -EOPNOTSUPP; + + if (rStatus == WLAN_STATUS_SUCCESS) + return 0; + + return -EINVAL; +} + +#if (CFG_SUPPORT_SINGLE_SKU == 1) + +#if (CFG_BUILT_IN_DRIVER == 1) +/* in kernel-x.x/net/wireless/reg.c */ +#else +bool is_world_regdom(const char *alpha2) +{ + if (!alpha2) + return false; + + return (alpha2[0] == '0') && (alpha2[1] == '0'); +} +#endif + +enum regd_state regd_state_machine(IN struct regulatory_request *pRequest) +{ + switch (pRequest->initiator) { + case NL80211_REGDOM_SET_BY_USER: + DBGLOG(RLM, INFO, "regd_state_machine: SET_BY_USER\n"); + + return rlmDomainStateTransition(REGD_STATE_SET_COUNTRY_USER, + pRequest); + + case NL80211_REGDOM_SET_BY_DRIVER: + DBGLOG(RLM, INFO, "regd_state_machine: SET_BY_DRIVER\n"); + + return rlmDomainStateTransition( + REGD_STATE_SET_COUNTRY_DRIVER, pRequest); + + case NL80211_REGDOM_SET_BY_CORE: + DBGLOG(RLM, INFO, + "regd_state_machine: NL80211_REGDOM_SET_BY_CORE\n"); + + return rlmDomainStateTransition(REGD_STATE_SET_WW_CORE, + pRequest); + + case NL80211_REGDOM_SET_BY_COUNTRY_IE: + DBGLOG(RLM, WARN, + "============== WARNING ==============\n"); + DBGLOG(RLM, WARN, + "regd_state_machine: SET_BY_COUNTRY_IE\n"); + DBGLOG(RLM, WARN, "Regulatory rule is updated by IE.\n"); + DBGLOG(RLM, WARN, + "============== WARNING ==============\n"); + + return rlmDomainStateTransition(REGD_STATE_SET_COUNTRY_IE, + pRequest); + + default: + return rlmDomainStateTransition(REGD_STATE_INVALID, + pRequest); + } +} + + +void +mtk_apply_custom_regulatory(IN struct wiphy *pWiphy, + IN const struct ieee80211_regdomain *pRegdom) +{ + u32 band_idx, ch_idx; + struct ieee80211_supported_band *sband; + struct ieee80211_channel *chan; + + DBGLOG(RLM, INFO, "%s()\n", __func__); + + /* to reset cha->flags*/ + for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { + sband = pWiphy->bands[band_idx]; + if (!sband) + continue; + + for (ch_idx = 0; ch_idx < sband->n_channels; ch_idx++) { + chan = &sband->channels[ch_idx]; + + /*reset chan->flags*/ + chan->flags = 0; + } + + } + + /* update to kernel */ + wiphy_apply_custom_regulatory(pWiphy, pRegdom); +} + +void +mtk_reg_notify(IN struct wiphy *pWiphy, + IN struct regulatory_request *pRequest) +{ + struct GLUE_INFO *prGlueInfo; + struct ADAPTER *prAdapter; + enum regd_state old_state; + + if (g_u4HaltFlag) { + DBGLOG(RLM, WARN, "wlan is halt, skip reg callback\n"); + return; + } + + if (!pWiphy) { + DBGLOG(RLM, ERROR, "pWiphy = NULL!\n"); + return; + } + + /* + * Awlays use wlan0's base wiphy pointer to update reg notifier. + * Because only one reg state machine is handled. + */ + if (gprWdev && (pWiphy != gprWdev->wiphy)) { + pWiphy = gprWdev->wiphy; + DBGLOG(RLM, ERROR, "Use base wiphy to update (p=%p)\n", + gprWdev->wiphy); + } + + old_state = rlmDomainGetCtrlState(); + + /* + * Magic flow for driver to send inband command after kernel's calling + * reg_notifier callback + */ + if (!pRequest) { + /*triggered by our driver in wlan initial process.*/ + + if (old_state == REGD_STATE_INIT) { + if (rlmDomainIsUsingLocalRegDomainDataBase()) { + DBGLOG(RLM, WARN, + "County Code is not assigned. Use default WW.\n"); + goto DOMAIN_SEND_CMD; + + } else { + DBGLOG(RLM, ERROR, + "Invalid REG state happened. state = 0x%x\n", + old_state); + return; + } + } else if ((old_state == REGD_STATE_SET_WW_CORE) || + (old_state == REGD_STATE_SET_COUNTRY_USER) || + (old_state == REGD_STATE_SET_COUNTRY_DRIVER)) { + goto DOMAIN_SEND_CMD; + } else { + DBGLOG(RLM, ERROR, + "Invalid REG state happened. state = 0x%x\n", + old_state); + return; + } + } + + /* + * Ignore the CORE's WW setting when using local data base of regulatory + * rules + */ + if ((pRequest->initiator == NL80211_REGDOM_SET_BY_CORE) && +#if KERNEL_VERSION(3, 14, 0) > CFG80211_VERSION_CODE + (pWiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY)) +#else + (pWiphy->regulatory_flags & REGULATORY_CUSTOM_REG)) +#endif + return;/*Ignore the CORE's WW setting*/ + + /* + * State machine transition + */ + DBGLOG(RLM, INFO, + "request->alpha2=%s, initiator=%x, intersect=%d\n", + pRequest->alpha2, pRequest->initiator, pRequest->intersect); + + regd_state_machine(pRequest); + + if (rlmDomainGetCtrlState() == old_state) { + if (((old_state == REGD_STATE_SET_COUNTRY_USER) + || (old_state == REGD_STATE_SET_COUNTRY_DRIVER)) + && (!(rlmDomainIsSameCountryCode(pRequest->alpha2, + sizeof(pRequest->alpha2))))) + DBGLOG(RLM, INFO, "Set by user to NEW country code\n"); + else + /* Change to same state or same country, ignore */ + return; + } else if (rlmDomainIsCtrlStateEqualTo(REGD_STATE_INVALID)) { + DBGLOG(RLM, ERROR, + "\n%s():\n---> WARNING. Transit to invalid state.\n", + __func__); + DBGLOG(RLM, ERROR, "---> WARNING.\n "); + rlmDomainAssert(0); + } + + /* + * Set country code + */ + if (pRequest->initiator != NL80211_REGDOM_SET_BY_DRIVER) { + rlmDomainSetCountryCode(pRequest->alpha2, + sizeof(pRequest->alpha2)); + } else { + /*SET_BY_DRIVER*/ + + if (rlmDomainIsEfuseUsed()) { + if (!rlmDomainIsUsingLocalRegDomainDataBase()) + DBGLOG(RLM, WARN, + "[WARNING!!!] Local DB must be used if country code from efuse.\n"); + } else { + /* iwpriv case */ + if (rlmDomainIsUsingLocalRegDomainDataBase() && + (!rlmDomainIsEfuseUsed())) { + /*iwpriv set country but local data base*/ + u32 country_code = + rlmDomainGetTempCountryCode(); + + rlmDomainSetCountryCode((char *)&country_code, + sizeof(country_code)); + } else { + /*iwpriv set country but query CRDA*/ + rlmDomainSetCountryCode(pRequest->alpha2, + sizeof(pRequest->alpha2)); + } + } + } + + rlmDomainSetDfsRegion(pRequest->dfs_region); + + +DOMAIN_SEND_CMD: + DBGLOG(RLM, INFO, "g_mtk_regd_control.alpha2 = 0x%x\n", + rlmDomainGetCountryCode()); + + /* + * Check if using customized regulatory rule + */ + if (rlmDomainIsUsingLocalRegDomainDataBase()) { + const struct ieee80211_regdomain *pRegdom; + u32 country_code = rlmDomainGetCountryCode(); + char alpha2[4]; + + /*fetch regulatory rules from local data base*/ + alpha2[0] = country_code & 0xFF; + alpha2[1] = (country_code >> 8) & 0xFF; + alpha2[2] = (country_code >> 16) & 0xFF; + alpha2[3] = (country_code >> 24) & 0xFF; + + pRegdom = rlmDomainSearchRegdomainFromLocalDataBase(alpha2); + if (!pRegdom) { + DBGLOG(RLM, ERROR, + "%s(): Error, Cannot find the correct RegDomain. country = %u\n", + __func__, rlmDomainGetCountryCode()); + + rlmDomainAssert(0); + return; + } + + mtk_apply_custom_regulatory(pWiphy, pRegdom); + } + + /* + * Parsing channels + */ + rlmDomainParsingChannel(pWiphy); /*real regd update*/ + + /* + * Check if firmawre support single sku. + * no need to send information to FW due to FW is not supported. + */ + if (!regd_is_single_sku_en()) + return; + + /* + * Always use the wlan GlueInfo as parameter. + */ + prGlueInfo = rlmDomainGetGlueInfo(); + if (!prGlueInfo) { + DBGLOG(RLM, ERROR, "prGlueInfo is NULL!\n"); + return; /*interface is not up yet.*/ + } + + prAdapter = prGlueInfo->prAdapter; + if (!prAdapter) { + DBGLOG(RLM, ERROR, "prAdapter is NULL!\n"); + return; /*interface is not up yet.*/ + } + + if (test_bit(SUSPEND_FLAG_CLEAR_WHEN_RESUME, + &prAdapter->ulSuspendFlag)) { + DBGLOG(RLM, STATE, + "[%s] Suspend is ongoing\n", __func__); + return; + } + + /* + * Send commands to firmware + */ + prAdapter->rWifiVar.rConnSettings.u2CountryCode = + (uint16_t)rlmDomainGetCountryCode(); + rlmDomainSendCmd(prAdapter); +} + +void +cfg80211_regd_set_wiphy(IN struct wiphy *prWiphy) +{ + /* + * register callback + */ + prWiphy->reg_notifier = mtk_reg_notify; + + + /* + * clear REGULATORY_CUSTOM_REG flag + */ +#if KERNEL_VERSION(3, 14, 0) > CFG80211_VERSION_CODE + /*tells kernel that assign WW as default*/ + prWiphy->flags &= ~(WIPHY_FLAG_CUSTOM_REGULATORY); +#else + prWiphy->regulatory_flags &= ~(REGULATORY_CUSTOM_REG); + + /*ignore the hint from IE*/ + prWiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE; + +#ifdef CFG_SUPPORT_DISABLE_BCN_HINTS + /*disable beacon hint to avoid channel flag be changed*/ + prWiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS; +#endif +#endif + + + /* + * set REGULATORY_CUSTOM_REG flag + */ +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) +#if KERNEL_VERSION(3, 14, 0) > CFG80211_VERSION_CODE + /*tells kernel that assign WW as default*/ + prWiphy->flags |= (WIPHY_FLAG_CUSTOM_REGULATORY); +#else + prWiphy->regulatory_flags |= (REGULATORY_CUSTOM_REG); +#endif + /* assigned a defautl one */ + if (rlmDomainGetLocalDefaultRegd()) + wiphy_apply_custom_regulatory(prWiphy, + rlmDomainGetLocalDefaultRegd()); +#endif + + + /* + * Initialize regd control information + */ + rlmDomainResetCtrlInfo(FALSE); +} + +#else +void +cfg80211_regd_set_wiphy(IN struct wiphy *prWiphy) +{ +} +#endif + +int mtk_cfg80211_suspend(struct wiphy *wiphy, + struct cfg80211_wowlan *wow) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + DBGLOG(REQ, STATE, "mtk_cfg80211_suspend\n"); + + if (!wiphy) + return 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!prGlueInfo) + return 0; +#if !CFG_ENABLE_WAKE_LOCK + /* AIS flow: disassociation if wow_en=0 */ + /* cancel scan report done event */ + aisPreSuspendFlow(prGlueInfo); + + /* In current design, only support AIS connection during suspend only. + * It need to add flow to deactive P2P (GC/GO) link during suspend flow. + * Otherwise, MT7668 would fail to enter deep sleep. + */ + p2pProcessPreSuspendFlow(prGlueInfo->prAdapter); +#endif + if (kalHaltTryLock()) + return 0; + + if (kalIsHalted() || !wiphy) + goto end; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (prGlueInfo && prGlueInfo->prAdapter) { + set_bit(SUSPEND_FLAG_FOR_WAKEUP_REASON, + &prGlueInfo->prAdapter->ulSuspendFlag); + set_bit(SUSPEND_FLAG_CLEAR_WHEN_RESUME, + &prGlueInfo->prAdapter->ulSuspendFlag); + } +end: + kalHaltUnlock(); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief cfg80211 resume callback, will be invoked in wiphy_resume. + * + * @param wiphy: pointer to wiphy + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_resume(struct wiphy *wiphy) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct BSS_DESC **pprBssDesc = NULL; + struct ADAPTER *prAdapter = NULL; + uint8_t i = 0; + + DBGLOG(REQ, STATE, "mtk_cfg80211_resume\n"); + + if (kalHaltTryLock()) + return 0; + + if (kalIsHalted() || !wiphy) + goto end; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + if (prGlueInfo) + prAdapter = prGlueInfo->prAdapter; + if (prAdapter == NULL) + goto end; + + clear_bit(SUSPEND_FLAG_CLEAR_WHEN_RESUME, + &prAdapter->ulSuspendFlag); + pprBssDesc = &prAdapter->rWifiVar.rScanInfo.rSchedScanParam. + aprPendingBssDescToInd[0]; + for (; i < SCN_SSID_MATCH_MAX_NUM; i++) { + if (pprBssDesc[i] == NULL) + break; + if (pprBssDesc[i]->u2RawLength == 0) + continue; + kalIndicateBssInfo(prGlueInfo, + (uint8_t *) pprBssDesc[i]->aucRawBuf, + pprBssDesc[i]->u2RawLength, + pprBssDesc[i]->ucChannelNum, + RCPI_TO_dBm(pprBssDesc[i]->ucRCPI)); + } + DBGLOG(SCN, INFO, "pending %d sched scan results\n", i); + if (i > 0) + kalMemZero(&pprBssDesc[0], i * sizeof(struct BSS_DESC *)); + +end: + kalHaltUnlock(); + + return 0; +} + +#if CFG_ENABLE_UNIFY_WIPHY +/*----------------------------------------------------------------------------*/ +/*! + * @brief Check the net device is P2P net device (P2P GO/GC, AP), or not. + * + * @param prGlueInfo : the driver private data + * ndev : the net device + * + * @retval 0: AIS device (STA/IBSS) + * 1: P2P GO/GC, AP + */ +/*----------------------------------------------------------------------------*/ +int mtk_IsP2PNetDevice(struct GLUE_INFO *prGlueInfo, + struct net_device *ndev) +{ + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = NULL; + int iftype = 0; + int ret = 1; + + if (ndev == NULL) { + DBGLOG(REQ, WARN, "ndev is NULL\n"); + return -1; + } + + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(ndev); + iftype = ndev->ieee80211_ptr->iftype; + + /* P2P device/GO/GC always return 1 */ + if (prNetDevPrivate->ucIsP2p == TRUE) + ret = 1; + else if (iftype == NL80211_IFTYPE_STATION) + ret = 0; + else if (iftype == NL80211_IFTYPE_ADHOC) + ret = 0; + + DBGLOG(REQ, LOUD, + "ucIsP2p = %d\n", + ret); + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Initialize the AIS related FSM and data. + * + * @param prGlueInfo : the driver private data + * ndev : the net device + * ucBssIdx : the AIS BSS index adssigned by the driver (wlanProbe) + * + * @retval 0 + * + */ +/*----------------------------------------------------------------------------*/ +int mtk_init_sta_role(struct ADAPTER *prAdapter, + struct net_device *ndev) +{ + struct NETDEV_PRIVATE_GLUE_INFO *prNdevPriv = NULL; + + if ((prAdapter == NULL) || (ndev == NULL)) + return -1; + + /* init AIS FSM */ + aisFsmInit(prAdapter); + +#if CFG_SUPPORT_ROAMING + /* Roaming Module - intiailization */ + roamingFsmInit(prAdapter); +#endif /* CFG_SUPPORT_ROAMING */ + + ndev->netdev_ops = wlanGetNdevOps(); + ndev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; + + /* set the ndev's ucBssIdx to the AIS BSS index */ + prNdevPriv = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(ndev); + prNdevPriv->ucBssIdx = prAdapter->prAisBssInfo->ucBssIndex; + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Uninitialize the AIS related FSM and data. + * + * @param prAdapter : the driver private data + * + * @retval 0 + * + */ +/*----------------------------------------------------------------------------*/ +int mtk_uninit_sta_role(struct ADAPTER *prAdapter, + struct net_device *ndev) +{ + struct NETDEV_PRIVATE_GLUE_INFO *prNdevPriv = NULL; + + if ((prAdapter == NULL) || (ndev == NULL)) + return -1; + +#if CFG_SUPPORT_ROAMING + /* Roaming Module - unintiailization */ + roamingFsmUninit(prAdapter); +#endif /* CFG_SUPPORT_ROAMING */ + + /* uninit AIS FSM */ + aisFsmUninit(prAdapter); + + /* set the ucBssIdx to the illegal value */ + prNdevPriv = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(ndev); + prNdevPriv->ucBssIdx = 0xff; + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Initialize the AP (P2P) related FSM and data. + * + * @param prGlueInfo : the driver private data + * ndev : net device + * + * @retval 0 : success + * others : can't alloc and setup the AP FSM & data + * + */ +/*----------------------------------------------------------------------------*/ +int mtk_init_ap_role(struct GLUE_INFO *prGlueInfo, + struct net_device *ndev) +{ + int u4Idx = 0; + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + + for (u4Idx = 0; u4Idx < KAL_P2P_NUM; u4Idx++) { + if (gprP2pRoleWdev[u4Idx] == NULL) + break; + } + + if (u4Idx >= KAL_P2P_NUM) { + DBGLOG(INIT, ERROR, "There is no free gprP2pRoleWdev.\n"); + return -ENOMEM; + } + + if ((u4Idx == 0) || + (prAdapter == NULL) || + (prAdapter->rP2PNetRegState != + ENUM_NET_REG_STATE_REGISTERED)) { + DBGLOG(INIT, ERROR, + "The wlan0 can't set to AP without p2p0\n"); + /* System will crash, if p2p0 isn't existing. */ + return -EFAULT; + } + + /* reference from the glRegisterP2P() */ + gprP2pRoleWdev[u4Idx] = ndev->ieee80211_ptr; + if (glSetupP2P(prGlueInfo, gprP2pRoleWdev[u4Idx], ndev, + u4Idx, TRUE)) { + gprP2pRoleWdev[u4Idx] = NULL; + return -EFAULT; + } + + prGlueInfo->prAdapter->prP2pInfo->u4DeviceNum++; + + /* reference from p2pNetRegister() */ + /* The ndev doesn't need register_netdev, only reassign the gPrP2pDev.*/ + gPrP2pDev[u4Idx] = ndev; + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Unnitialize the AP (P2P) related FSM and data. + * + * @param prGlueInfo : the driver private data + * ndev : net device + * + * @retval 0 : success + * others : can't find the AP information by the ndev + * + */ +/*----------------------------------------------------------------------------*/ +int mtk_uninit_ap_role(struct GLUE_INFO *prGlueInfo, + struct net_device *ndev) +{ + unsigned char u4Idx; + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, ndev, &u4Idx) != 0) { + DBGLOG(INIT, WARN, + "can't find the matched dev to uninit AP\n"); + return -EFAULT; + } + + glUnregisterP2P(prGlueInfo, u4Idx); + + gPrP2pDev[u4Idx] = NULL; + gprP2pRoleWdev[u4Idx] = NULL; + + return 0; +} + + +#if (CFG_SUPPORT_DFS_MASTER == 1) +#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_start_radar_detection(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef, + unsigned int cac_time_ms) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, dev) <= 0) { + DBGLOG(REQ, WARN, "STA doesn't support this function\n"); + return -EFAULT; + } + + return mtk_p2p_cfg80211_start_radar_detection(wiphy, + dev, chandef, cac_time_ms); +} +#else +int mtk_cfg_start_radar_detection(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, dev) <= 0) { + DBGLOG(REQ, WARN, "STA doesn't support this function\n"); + return -EFAULT; + } + + return mtk_p2p_cfg80211_start_radar_detection(wiphy, dev, chandef); +} +#endif + +#if KERNEL_VERSION(3, 13, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_channel_switch(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_csa_settings *params) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, dev) <= 0) { + DBGLOG(REQ, WARN, "STA doesn't support this function\n"); + return -EFAULT; + } + + return mtk_p2p_cfg80211_channel_switch(wiphy, dev, params); +} +#endif +#endif + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +struct wireless_dev *mtk_cfg_add_iface(struct wiphy *wiphy, + const char *name, + unsigned char name_assign_type, + enum nl80211_iftype type, + struct vif_params *params) +#elif KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE +struct wireless_dev *mtk_cfg_add_iface(struct wiphy *wiphy, + const char *name, + unsigned char name_assign_type, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params) +#else +struct wireless_dev *mtk_cfg_add_iface(struct wiphy *wiphy, + const char *name, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params) +#endif +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return ERR_PTR(-EFAULT); + } + + /* TODO: error handele for the non-P2P interface */ + +#if (CFG_ENABLE_WIFI_DIRECT_CFG_80211 == 0) + DBGLOG(REQ, WARN, "P2P is not supported\n"); + return ERR_PTR(-EINVAL); +#else /* CFG_ENABLE_WIFI_DIRECT_CFG_80211 */ +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE + return mtk_p2p_cfg80211_add_iface(wiphy, name, + name_assign_type, type, params); +#elif KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE + return mtk_p2p_cfg80211_add_iface(wiphy, name, + name_assign_type, type, + flags, params); +#else /* KERNEL_VERSION > (4, 1, 0) */ + return mtk_p2p_cfg80211_add_iface(wiphy, name, type, flags, + params); +#endif /* KERNEL_VERSION */ +#endif /* CFG_ENABLE_WIFI_DIRECT_CFG_80211 */ +} + +int mtk_cfg_del_iface(struct wiphy *wiphy, + struct wireless_dev *wdev) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + /* TODO: error handele for the non-P2P interface */ +#if (CFG_ENABLE_WIFI_DIRECT_CFG_80211 == 0) + DBGLOG(REQ, WARN, "P2P is not supported\n"); + return -EINVAL; +#else /* CFG_ENABLE_WIFI_DIRECT_CFG_80211 */ + return mtk_p2p_cfg80211_del_iface(wiphy, wdev); +#endif /* CFG_ENABLE_WIFI_DIRECT_CFG_80211 */ +} + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_change_iface(struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type, + struct vif_params *params) +#else +int mtk_cfg_change_iface(struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params) +#endif +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct NETDEV_PRIVATE_GLUE_INFO *prNetdevPriv = NULL; + struct P2P_INFO *prP2pInfo = NULL; + uint8_t state = 0; + + GLUE_SPIN_LOCK_DECLARATION(); + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(P2P, INFO, "ndev=%p, new type=%d\n", ndev, type); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (!ndev) { + DBGLOG(REQ, WARN, "ndev is NULL\n"); + return -EINVAL; + } + + prNetdevPriv = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(ndev); + +#if (CFG_ENABLE_WIFI_DIRECT_CFG_80211) + /* for p2p0(GO/GC) & ap0(SAP): mtk_p2p_cfg80211_change_iface + * for wlan0 (STA/SAP): the following mtk_cfg_change_iface process + */ + if (ndev != prGlueInfo->prDevHandler) { +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE + return mtk_p2p_cfg80211_change_iface(wiphy, ndev, type, + NULL, params); +#else + return mtk_p2p_cfg80211_change_iface(wiphy, ndev, type, + flags, params); +#endif + } +#endif /* CFG_ENABLE_WIFI_DIRECT_CFG_80211 */ + + prAdapter = prGlueInfo->prAdapter; + + if (ndev->ieee80211_ptr->iftype == type) { + DBGLOG(REQ, INFO, "ndev type is not changed (%d)\n", type); + return 0; + } + + netif_carrier_off(ndev); + /* stop ap will stop all queue, and kalIndicateStatusAndComplete only do + * netif_carrier_on. So that, the following STA can't send 4-way M2 to + * AP. + */ + netif_tx_start_all_queues(ndev); + + /* flush scan */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if ((prGlueInfo->prScanRequest != NULL) && + (prGlueInfo->prScanRequest->wdev == ndev->ieee80211_ptr)) { + kalCfg80211ScanDone(prGlueInfo->prScanRequest, TRUE); + prGlueInfo->prScanRequest = NULL; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + /* expect that only AP & STA will be handled here (excluding IBSS) */ + + if (type == NL80211_IFTYPE_AP) { + /* STA mode change to AP mode */ + prP2pInfo = prAdapter->prP2pInfo; + + if (prP2pInfo == NULL) { + DBGLOG(INIT, ERROR, "prP2pInfo is NULL\n"); + return -EFAULT; + } + + if (prP2pInfo->u4DeviceNum >= KAL_P2P_NUM) { + DBGLOG(INIT, ERROR, "resource invalid, u4DeviceNum=%d\n" + , prP2pInfo->u4DeviceNum); + return -EFAULT; + } + + mtk_uninit_sta_role(prAdapter, ndev); + + if (mtk_init_ap_role(prGlueInfo, ndev) != 0) { + DBGLOG(INIT, ERROR, "mtk_init_ap_role FAILED\n"); + + /* Only AP/P2P resource has the failure case. */ + /* So, just re-init AIS. */ + mtk_init_sta_role(prAdapter, ndev); + return -EFAULT; + } + } else { + /* AP mode change to STA mode */ + if (mtk_uninit_ap_role(prGlueInfo, ndev) != 0) { + DBGLOG(INIT, ERROR, "mtk_uninit_ap_role FAILED\n"); + return -EFAULT; + } + + mtk_init_sta_role(prAdapter, ndev); + + /* continue the mtk_cfg80211_change_iface() process */ +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE + mtk_cfg80211_change_iface(wiphy, ndev, type, NULL, params); +#else + mtk_cfg80211_change_iface(wiphy, ndev, type, flags, params); +#endif + } + + return 0; +} + +int mtk_cfg_add_key(struct wiphy *wiphy, + struct net_device *ndev, u8 key_index, + bool pairwise, const u8 *mac_addr, + struct key_params *params) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + return mtk_p2p_cfg80211_add_key(wiphy, ndev, key_index, + pairwise, mac_addr, params); + } + /* STA Mode */ + return mtk_cfg80211_add_key(wiphy, ndev, key_index, + pairwise, + mac_addr, params); +} + +int mtk_cfg_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 *)) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + return mtk_p2p_cfg80211_get_key(wiphy, ndev, key_index, + pairwise, mac_addr, cookie, callback); + } + /* STA Mode */ + return mtk_cfg80211_get_key(wiphy, ndev, key_index, + pairwise, mac_addr, cookie, callback); +} + +int mtk_cfg_del_key(struct wiphy *wiphy, + struct net_device *ndev, u8 key_index, + bool pairwise, const u8 *mac_addr) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + return mtk_p2p_cfg80211_del_key(wiphy, ndev, key_index, + pairwise, mac_addr); + } + /* STA Mode */ + return mtk_cfg80211_del_key(wiphy, ndev, key_index, + pairwise, mac_addr); +} + +int mtk_cfg_set_default_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, bool unicast, bool multicast) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + return mtk_p2p_cfg80211_set_default_key(wiphy, ndev, + key_index, unicast, multicast); + } + /* STA Mode */ + return mtk_cfg80211_set_default_key(wiphy, ndev, + key_index, unicast, multicast); +} + +int mtk_cfg_set_default_mgmt_key(struct wiphy *wiphy, + struct net_device *ndev, u8 key_index) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) + return mtk_p2p_cfg80211_set_mgmt_key(wiphy, ndev, key_index); + /* STA Mode */ + DBGLOG(REQ, WARN, "STA don't support this function\n"); + return -EFAULT; +} + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_get_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, struct station_info *sinfo) +#else +int mtk_cfg_get_station(struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, struct station_info *sinfo) +#endif +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) + return mtk_p2p_cfg80211_get_station(wiphy, ndev, mac, + sinfo); + /* STA Mode */ + return mtk_cfg80211_get_station(wiphy, ndev, mac, sinfo); +} + +#if CFG_SUPPORT_TDLS +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_change_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, struct station_parameters *params) +#else +int mtk_cfg_change_station(struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, struct station_parameters *params) +#endif +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + DBGLOG(REQ, WARN, "P2P/AP don't support this function\n"); + return -EFAULT; + } + /* STA Mode */ + return mtk_cfg80211_change_station(wiphy, ndev, mac, + params); +} + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_add_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, struct station_parameters *params) +#else +int mtk_cfg_add_station(struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, struct station_parameters *params) +#endif +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + DBGLOG(REQ, WARN, "P2P/AP don't support this function\n"); + return -EFAULT; + } + /* STA Mode */ + return mtk_cfg80211_add_station(wiphy, ndev, mac, params); +} + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_tdls_oper(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *peer, enum nl80211_tdls_operation oper) +#else +int mtk_cfg_tdls_oper(struct wiphy *wiphy, + struct net_device *ndev, + u8 *peer, enum nl80211_tdls_operation oper) +#endif +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + DBGLOG(REQ, WARN, "P2P/AP don't support this function\n"); + return -EFAULT; + } + /* STA Mode */ + return mtk_cfg80211_tdls_oper(wiphy, ndev, peer, oper); +} + +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, + bool initiator, const u8 *buf, size_t len) +#elif KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, + const u8 *buf, size_t len) +#else +int mtk_cfg_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, + const u8 *buf, size_t len) +#endif +{ + struct GLUE_INFO *prGlueInfo; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, dev) > 0) { + DBGLOG(REQ, WARN, "P2P/AP don't support this function\n"); + return -EFAULT; + } + +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE + return mtk_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code, + dialog_token, status_code, peer_capability, initiator, + buf, len); +#elif KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE + return mtk_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code, + dialog_token, status_code, peer_capability, + buf, len); +#else + return mtk_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code, + dialog_token, status_code, + buf, len); +#endif +} +#endif /* CFG_SUPPORT_TDLS */ + +#if KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_del_station(struct wiphy *wiphy, + struct net_device *ndev, + struct station_del_parameters *params) +#elif KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_del_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac) +#else +int mtk_cfg_del_station(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac) +#endif +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { +#if KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE + return mtk_p2p_cfg80211_del_station(wiphy, ndev, params); +#else + return mtk_p2p_cfg80211_del_station(wiphy, ndev, mac); +#endif + } + /* STA Mode */ +#if CFG_SUPPORT_TDLS +#if KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE + return mtk_cfg80211_del_station(wiphy, ndev, params); +#else /* CFG80211_VERSION_CODE > KERNEL_VERSION(3, 19, 0) */ + return mtk_cfg80211_del_station(wiphy, ndev, mac); +#endif /* CFG80211_VERSION_CODE */ +#else /* CFG_SUPPORT_TDLS == 0 */ + /* AIS only support this function when CFG_SUPPORT_TDLS */ + return -EFAULT; +#endif /* CFG_SUPPORT_TDLS */ +} + +int mtk_cfg_scan(struct wiphy *wiphy, + struct cfg80211_scan_request *request) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, + request->wdev->netdev) > 0) + return mtk_p2p_cfg80211_scan(wiphy, request); + /* STA Mode */ + return mtk_cfg80211_scan(wiphy, request); +} + +#if KERNEL_VERSION(4, 5, 0) <= CFG80211_VERSION_CODE +void mtk_cfg_abort_scan(struct wiphy *wiphy, + struct wireless_dev *wdev) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, wdev->netdev) > 0) + mtk_p2p_cfg80211_abort_scan(wiphy, wdev); + else /* STA Mode */ + mtk_cfg80211_abort_scan(wiphy, wdev); +} +#endif + +#if CFG_SUPPORT_SCHED_SCAN +int mtk_cfg_sched_scan_start(IN struct wiphy *wiphy, + IN struct net_device *ndev, + IN struct cfg80211_sched_scan_request *request) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + DBGLOG(REQ, WARN, "P2P/AP don't support this function\n"); + return -EFAULT; + } + + return mtk_cfg80211_sched_scan_start(wiphy, ndev, request); + +} + +int mtk_cfg_sched_scan_stop(IN struct wiphy *wiphy, + IN struct net_device *ndev) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + DBGLOG(REQ, WARN, "P2P/AP don't support this function\n"); + return -EFAULT; + } + + return mtk_cfg80211_sched_scan_stop(wiphy, ndev); +} +#endif /* CFG_SUPPORT_SCHED_SCAN */ + +int mtk_cfg_connect(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_connect_params *sme) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) + return mtk_p2p_cfg80211_connect(wiphy, ndev, sme); + /* STA Mode */ + return mtk_cfg80211_connect(wiphy, ndev, sme); +} + +int mtk_cfg_disconnect(struct wiphy *wiphy, + struct net_device *ndev, + u16 reason_code) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) + return mtk_p2p_cfg80211_disconnect(wiphy, ndev, + reason_code); + /* STA Mode */ + return mtk_cfg80211_disconnect(wiphy, ndev, reason_code); +} + +int mtk_cfg_join_ibss(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_ibss_params *params) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) + return mtk_p2p_cfg80211_join_ibss(wiphy, ndev, params); + /* STA Mode */ + return mtk_cfg80211_join_ibss(wiphy, ndev, params); +} + +int mtk_cfg_leave_ibss(struct wiphy *wiphy, + struct net_device *ndev) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) + return mtk_p2p_cfg80211_leave_ibss(wiphy, ndev); + /* STA Mode */ + return mtk_cfg80211_leave_ibss(wiphy, ndev); +} + +int mtk_cfg_set_power_mgmt(struct wiphy *wiphy, + struct net_device *ndev, + bool enabled, int timeout) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + return mtk_p2p_cfg80211_set_power_mgmt(wiphy, ndev, + enabled, timeout); + } + /* STA Mode */ + return mtk_cfg80211_set_power_mgmt(wiphy, ndev, enabled, + timeout); +} + +int mtk_cfg_set_pmksa(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_pmksa *pmksa) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + DBGLOG(REQ, WARN, "P2P/AP don't support this function\n"); + return -EFAULT; + } + + return mtk_cfg80211_set_pmksa(wiphy, ndev, pmksa); +} + +int mtk_cfg_del_pmksa(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_pmksa *pmksa) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + DBGLOG(REQ, WARN, "P2P/AP don't support this function\n"); + return -EFAULT; + } + + return mtk_cfg80211_del_pmksa(wiphy, ndev, pmksa); +} + +int mtk_cfg_flush_pmksa(struct wiphy *wiphy, + struct net_device *ndev) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + DBGLOG(REQ, WARN, "P2P/AP don't support this function\n"); + return -EFAULT; + } + + return mtk_cfg80211_flush_pmksa(wiphy, ndev); +} + +#if CONFIG_SUPPORT_GTK_REKEY +int mtk_cfg_set_rekey_data(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_gtk_rekey_data *data) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, dev) > 0) { + DBGLOG(REQ, WARN, "P2P/AP don't support this function\n"); + return -EFAULT; + } + + return mtk_cfg80211_set_rekey_data(wiphy, dev, data); +} +#endif /* CONFIG_SUPPORT_GTK_REKEY */ + +int mtk_cfg_suspend(struct wiphy *wiphy, + struct cfg80211_wowlan *wow) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return 0; + } + + /* TODO: AP/P2P do not support this function, should take that case. */ + return mtk_cfg80211_suspend(wiphy, wow); +} + +int mtk_cfg_resume(struct wiphy *wiphy) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return 0; + } + + /* TODO: AP/P2P do not support this function, should take that case. */ + return mtk_cfg80211_resume(wiphy); +} + +int mtk_cfg_assoc(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_assoc_request *req) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + +#if !CFG_SUPPORT_CFG80211_AUTH + if (mtk_IsP2PNetDevice(prGlueInfo, ndev) > 0) { + DBGLOG(REQ, WARN, "P2P/AP don't support this function\n"); + return -EFAULT; + } +#endif + /* STA Mode */ + return mtk_cfg80211_assoc(wiphy, ndev, req); +} + +int mtk_cfg_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, + unsigned int duration, u64 *cookie) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, wdev->netdev) > 0) { + return mtk_p2p_cfg80211_remain_on_channel(wiphy, wdev, chan, + duration, cookie); + } + /* STA Mode */ + return mtk_cfg80211_remain_on_channel(wiphy, wdev, chan, + duration, cookie); +} + +int mtk_cfg_cancel_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, u64 cookie) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, wdev->netdev) > 0) { + return mtk_p2p_cfg80211_cancel_remain_on_channel(wiphy, + wdev, + cookie); + } + /* STA Mode */ + return mtk_cfg80211_cancel_remain_on_channel(wiphy, wdev, + cookie); +} + +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, u64 *cookie) +#else +int mtk_cfg_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *channel, bool offscan, + unsigned int wait, const u8 *buf, size_t len, bool no_cck, + bool dont_wait_for_ack, u64 *cookie) +#endif +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE + if (mtk_IsP2PNetDevice(prGlueInfo, wdev->netdev) > 0) + return mtk_p2p_cfg80211_mgmt_tx(wiphy, wdev, params, + cookie); + /* STA Mode */ + return mtk_cfg80211_mgmt_tx(wiphy, wdev, params, cookie); +#else /* KERNEL_VERSION(3, 14, 0) > CFG80211_VERSION_CODE */ + if (mtk_IsP2PNetDevice(prGlueInfo, wdev->netdev) > 0) { + return mtk_p2p_cfg80211_mgmt_tx(wiphy, wdev, channel, offscan, + wait, buf, len, no_cck, dont_wait_for_ack, cookie); + } + /* STA Mode */ + return mtk_cfg80211_mgmt_tx(wiphy, wdev, channel, offscan, wait, buf, + len, no_cck, dont_wait_for_ack, cookie); +#endif +} + +void mtk_cfg_mgmt_frame_register(struct wiphy *wiphy, + struct wireless_dev *wdev, + u16 frame_type, bool reg) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, wdev->netdev) > 0) { + mtk_p2p_cfg80211_mgmt_frame_register(wiphy, wdev, + frame_type, + reg); + } else { + mtk_cfg80211_mgmt_frame_register(wiphy, wdev, frame_type, + reg); + } +} + +#ifdef CONFIG_NL80211_TESTMODE +#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_testmode_cmd(struct wiphy *wiphy, + struct wireless_dev *wdev, + void *data, int len) +#else +int mtk_cfg_testmode_cmd(struct wiphy *wiphy, void *data, + int len) +#endif +{ +#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, wdev->netdev) > 0) { + return mtk_p2p_cfg80211_testmode_cmd(wiphy, wdev, data, + len); + } + + return mtk_cfg80211_testmode_cmd(wiphy, wdev, data, len); +#else + /* XXX: no information can to check the mtk_IsP2PNetDevice */ + /* return mtk_p2p_cfg80211_testmode_cmd(wiphy, data, len); */ + return mtk_cfg80211_testmode_cmd(wiphy, data, len); +#endif +} +#endif /* CONFIG_NL80211_TESTMODE */ + +#if (CFG_ENABLE_WIFI_DIRECT_CFG_80211 != 0) +int mtk_cfg_change_bss(struct wiphy *wiphy, + struct net_device *dev, + struct bss_parameters *params) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, dev) <= 0) { + DBGLOG(REQ, WARN, "STA doesn't support this function\n"); + return -EFAULT; + } + + return mtk_p2p_cfg80211_change_bss(wiphy, dev, params); +} + +int mtk_cfg_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, wdev->netdev) <= 0) { + DBGLOG(REQ, WARN, "STA doesn't support this function\n"); + return -EFAULT; + } + + return mtk_p2p_cfg80211_mgmt_tx_cancel_wait(wiphy, wdev, + cookie); +} + +int mtk_cfg_deauth(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_deauth_request *req) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + int ret = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, dev) > 0) + ret = mtk_p2p_cfg80211_deauth(wiphy, dev, req); +#if CFG_SUPPORT_CFG80211_AUTH + else + ret = mtk_cfg80211_deauth(wiphy, dev, req); +#endif + return ret; +} + +int mtk_cfg_disassoc(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_disassoc_request *req) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, dev) <= 0) { + DBGLOG(REQ, WARN, "STA doesn't support this function\n"); + return -EFAULT; + } + + return mtk_p2p_cfg80211_disassoc(wiphy, dev, req); +} + +int mtk_cfg_start_ap(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ap_settings *settings) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, dev) <= 0) { + DBGLOG(REQ, WARN, "STA doesn't support this function\n"); + return -EFAULT; + } + + return mtk_p2p_cfg80211_start_ap(wiphy, dev, settings); +} + +int mtk_cfg_change_beacon(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_beacon_data *info) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, dev) <= 0) { + DBGLOG(REQ, WARN, "STA doesn't support this function\n"); + return -EFAULT; + } + + return mtk_p2p_cfg80211_change_beacon(wiphy, dev, info); +} + +int mtk_cfg_stop_ap(struct wiphy *wiphy, + struct net_device *dev) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, dev) <= 0) { + DBGLOG(REQ, WARN, "STA doesn't support this function\n"); + return -EFAULT; + } + + return mtk_p2p_cfg80211_stop_ap(wiphy, dev); +} + +int mtk_cfg_set_wiphy_params(struct wiphy *wiphy, + u32 changed) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + /* TODO: AIS not support this function */ + return mtk_p2p_cfg80211_set_wiphy_params(wiphy, changed); +} + +int mtk_cfg_set_bitrate_mask(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, + const struct cfg80211_bitrate_mask *mask) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, dev) <= 0) { + DBGLOG(REQ, WARN, "STA doesn't support this function\n"); + return -EFAULT; + } + + return mtk_p2p_cfg80211_set_bitrate_mask(wiphy, dev, peer, + mask); +} + +int mtk_cfg_set_txpower(struct wiphy *wiphy, + struct wireless_dev *wdev, + enum nl80211_tx_power_setting type, int mbm) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, wdev->netdev) <= 0) { + DBGLOG(REQ, WARN, "STA doesn't support this function\n"); + return -EFAULT; + } + + return mtk_p2p_cfg80211_set_txpower(wiphy, wdev, type, mbm); +} + +int mtk_cfg_get_txpower(struct wiphy *wiphy, + struct wireless_dev *wdev, + int *dbm) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t state = 0; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + if (!halIsHifStateReady(prGlueInfo->prAdapter, &state)) { + DBGLOG(REQ, WARN, "driver is not ready, state:%d\n", state); + return -EFAULT; + } + + if (mtk_IsP2PNetDevice(prGlueInfo, wdev->netdev) <= 0) { + DBGLOG_LIMITED(REQ, WARN, + "STA doesn't support this function\n"); + return -EFAULT; + } + + return mtk_p2p_cfg80211_get_txpower(wiphy, wdev, dbm); +} +#endif /* (CFG_ENABLE_WIFI_DIRECT_CFG_80211 != 0) */ +#endif /* CFG_ENABLE_UNIFY_WIPHY */ + +/*-----------------------------------------------------------------------*/ +/*! + * @brief This function goes through the provided ies buffer, and + * collects those non-wfa vendor specific ies into driver's + * internal buffer (non_wfa_vendor_ie_buf), to be sent in + * AssocReq in AIS mode. + * The non-wfa vendor specific ies are those with ie_id = 0xdd + * and ouis are different from wfa's oui. (i.e., it could be + * customer's vendor ie ...etc. + * + * @param prGlueInfo driver's private glueinfo + * ies ie buffer + * len length of ie + * + * @retval length of the non_wfa vendor ie + */ +/*-----------------------------------------------------------------------*/ +uint16_t cfg80211_get_non_wfa_vendor_ie(struct GLUE_INFO *prGlueInfo, + uint8_t *ies, int32_t len) +{ + const uint8_t *pos = ies, *end = ies+len; + struct ieee80211_vendor_ie *ie; + int32_t ie_oui = 0; + uint16_t *ret_len, max_len; + uint8_t *w_pos; + + if (!prGlueInfo || !ies || !len) + return 0; + w_pos = prGlueInfo->non_wfa_vendor_ie_buf; + ret_len = &prGlueInfo->non_wfa_vendor_ie_len; + max_len = (uint16_t)sizeof(prGlueInfo->non_wfa_vendor_ie_buf); + + while (pos < end) { + pos = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, pos, + end - pos); + if (!pos) + break; + + ie = (struct ieee80211_vendor_ie *)pos; + + /* Make sure we can access ie->len */ + BUILD_BUG_ON(offsetof(struct ieee80211_vendor_ie, len) != 1); + + if (ie->len < sizeof(*ie)) + goto cont; + + ie_oui = ie->oui[0] << 16 | ie->oui[1] << 8 | ie->oui[2]; + /* + * If oui is other than: 0x0050f2 & 0x506f9a, + * we consider it is non-wfa oui. + */ + if (ie_oui != WLAN_OUI_MICROSOFT && ie_oui != WLAN_OUI_WFA) { + /* + * If remaining buf len is capable, we copy + * this ie to the buf. + */ + if (max_len-(*ret_len) >= ie->len+2) { + DBGLOG(AIS, TRACE, + "vendor ie(len=%d, oui=0x%06x)\n", + ie->len, ie_oui); + memcpy(w_pos, pos, ie->len+2); + w_pos += (ie->len+2); + (*ret_len) += ie->len+2; + } else { + /* Otherwise we give an error msg + * and return. + */ + DBGLOG(AIS, ERROR, + "Insufficient buf for vendor ie, exit!\n"); + break; + } + } +cont: + pos += 2 + ie->len; + } + return *ret_len; +} + +int mtk_cfg80211_update_ft_ies(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_update_ft_ies_params *ftie) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4InfoBufLen = 0; + uint32_t rStatus = WLAN_STATUS_FAILURE; + +#if !CFG_SUPPORT_802_11R + DBGLOG(OID, INFO, "FT: 802.11R is not enabled\n"); + return 0; +#endif + if (!wiphy) + return -1; + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + rStatus = kalIoctl(prGlueInfo, wlanoidUpdateFtIes, (void *)ftie, + sizeof(*ftie), FALSE, FALSE, FALSE, &u4InfoBufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(OID, INFO, "FT: update Ft IE failed\n"); + return 0; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_custom.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_custom.c new file mode 100644 index 0000000000000..c8f25e46b461b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_custom.c @@ -0,0 +1,309 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#include +#include +#include "precomp.h" + +#if CFG_SUPPORT_CUSTOM_NETLINK + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define MAX_BIND_PROCESS (1) +#define GL_CUSTOM_FAMILY_NAME "WIFI_NL_CUSTOM" +#define MAX_CUSTOM_PKT_LENGTH (2048) +enum { + __GL_CUSTOM_ATTR_INVALID, + GL_CUSTOM_ATTR_MSG, /* message */ + __GL_CUSTOM_ATTR_MAX, +}; +#define GL_CUSTOM_ATTR_MAX (__GL_CUSTOM_ATTR_MAX - 1) + +enum { + __GL_CUSTOM_COMMAND_INVALID, + GL_CUSTOM_COMMAND_BIND, /* bind */ + GL_CUSTOM_COMMAND_SEND, /* user -> kernel */ + GL_CUSTOM_COMMAND_RECV, /* kernel -> user */ + __GL_CUSTOM_COMMAND_MAX, +}; +#define GL_CUSTOM_COMMAND_MAX (__GL_CUSTOM_COMMAND_MAX - 1) + +#if CFG_SUPPORT_TX_BEACON_STA_MODE +#define CUSTOM_BEACON_TYPE (0x80) +#endif +/******************************************************************************* +* P U B L I C 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 int32_t glCustomGenlBind( + struct sk_buff *skb, struct genl_info *info); +static int32_t glCustomRecvFromUplayer( + struct sk_buff *skb, struct genl_info *info); + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static struct genl_family glCustomGenlFamily = { + .id = GENL_ID_GENERATE, + .hdrsize = 0, + .name = GL_CUSTOM_FAMILY_NAME, + .version = 1, + .maxattr = GL_CUSTOM_ATTR_MAX, +}; + +/* attribute policy */ +static struct nla_policy glCustomGenlPolicy[GL_CUSTOM_ATTR_MAX + 1] = { + [GL_CUSTOM_ATTR_MSG] = {.type = NLA_NUL_STRING}, +}; + +/* operation definition */ +static struct genl_ops glCustomGenlOpsArray[] = { + { + .cmd = GL_CUSTOM_COMMAND_BIND, + .flags = 0, + .policy = glCustomGenlPolicy, + .doit = glCustomGenlBind, + .dumpit = NULL, + }, + { + .cmd = GL_CUSTOM_COMMAND_SEND, + .flags = 0, + .policy = glCustomGenlPolicy, + .doit = glCustomRecvFromUplayer, + .dumpit = NULL, + }, +}; + +int32_t gBindProcessNum; +pid_t gBindPid; + +uint8_t gScanIEBuf[MAX_IE_LENGTH]; +uint32_t gScanIELen; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +void glCustomGenlInit(void) +{ + if (genl_register_family_with_ops(&glCustomGenlFamily, + glCustomGenlOpsArray) != 0) + DBGLOG(INIT, ERROR, + "%s(): GE_NELINK family registration fail\n", + __func__); +} + +void glCustomGenlDeinit(void) +{ + genl_unregister_family(&glCustomGenlFamily); +} + +static int32_t glCustomGenlBind(struct sk_buff *skb, struct genl_info *info) +{ + struct nlattr *na; + int8_t *pData = NULL; + + DBGLOG(INIT, ERROR, "%s(): ->\n", __func__); + if (info == NULL) + return -1; + + na = info->attrs[GL_CUSTOM_ATTR_MSG]; + if (na) + pData = (int8_t *) nla_data(na); + + if (strcmp(pData, "BIND") == 0) { + if (gBindProcessNum < MAX_BIND_PROCESS) { + gBindPid = info->snd_portid; + gBindProcessNum++; + DBGLOG(INIT, ERROR, + "%s():-> pid = %d\n", + __func__, info->snd_portid); + } else { + gBindPid = info->snd_portid; + DBGLOG(INIT, ERROR, + "%s(): exceeding binding limit %d\n", + __func__, MAX_BIND_PROCESS); + } + } else if (strcmp(pData, "UNBIND") == 0) { + if (gBindProcessNum == 1) { + gBindPid = 0; + gBindProcessNum--; + DBGLOG(INIT, ERROR, + "%s():-> pid = %d unbind\n", + __func__, info->snd_portid); + } else { + DBGLOG(INIT, ERROR, + "%s(): unbinding error %d\n", + __func__, gBindProcessNum); + } + } else { + DBGLOG(INIT, ERROR, + "%s(): Unknown cmd %s\n", + __func__, pData); + } + + return 0; +} + +#if CFG_SUPPORT_TX_BEACON_STA_MODE +static uint32_t glCustomBeaconTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + DBGLOG(TX, WARN, + "glCustomBeaconTxDone: Status: %d, seq NO. %d\n", + rTxDoneStatus, prMsduInfo->ucTxSeqNum); + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; +} + +static uint32_t glCustomSendBeacon(void *probe_resp, uint32_t resp_len) +{ + struct ADAPTER *prAdapter; + struct MSDU_INFO *prMsduInfo; + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = wlanGetGlueInfo(); + + if (!prGlueInfo) { + DBGLOG(INIT, ERROR, "No glue info\n"); + return WLAN_STATUS_FAILURE; + } + + prAdapter = prGlueInfo->prAdapter; + + /* 4 <1> Allocate a PKT_INFO_T for Probe Response Frame */ + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, resp_len); + if (prMsduInfo == NULL) { + DBGLOG(BSS, WARN, "No PKT_INFO_T for sending Custom Frame\n"); + return WLAN_STATUS_RESOURCES; + } + + /* 4 <2> Compose Probe Response frame header */ + /* and fixed fields in MSDU_INfO_T. */ + /* Compose Header and Fixed Field */ + memcpy((int8_t *)prMsduInfo->prPacket, (int8_t *)probe_resp, resp_len); + + /* 4 <3> Update information of MSDU_INFO_T */ + nicTxSetMngPacket(prAdapter, prMsduInfo, 0, + 0xFF, WLAN_MAC_MGMT_HEADER_LEN, + resp_len, glCustomBeaconTxDone, + MSDU_RATE_MODE_LOWEST_RATE); + nicTxConfigPktControlFlag(prMsduInfo, + MSDU_CONTROL_FLAG_FORCE_TX, TRUE); + + DBGLOG(TX, WARN, "glCustomSendBeacon seq NO %d\n", + prMsduInfo->ucTxSeqNum); + + /* 4 <6> Inform TXM to send this Beacon /Probe Response frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; +} +#endif + +static int32_t glCustomRecvFromUplayer( + struct sk_buff *skb, struct genl_info *info) +{ + struct nlattr *na; + int8_t *pData = NULL; + int32_t u4DataLen = 0; + + if (info == NULL) + goto out; + + na = info->attrs[GL_CUSTOM_ATTR_MSG]; + + if (na) { + pData = (int8_t *) nla_data(na); + u4DataLen = nla_len(na); + } + + DBGLOG(INIT, TRACE, "glCustomRecvFromUplayer len=%d, data[0]=0x%2x\n", + u4DataLen, (uint8_t)pData[0]); + + +#if CFG_SUPPORT_TX_BEACON_STA_MODE + if ((uint8_t)pData[0] == CUSTOM_BEACON_TYPE) + glCustomSendBeacon(pData, u4DataLen); +#endif + +out: + return 0; +} +#endif /* CFG_CUSTOM_NETLINK_SUPPORT */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_hook_api.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_hook_api.c new file mode 100644 index 0000000000000..032dc2c17505b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_hook_api.c @@ -0,0 +1,4153 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + Module Name: + gl_hook_api.c +*/ +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" +#if CFG_SUPPORT_QA_TOOL +#include "gl_wext.h" +#include "gl_cfg80211.h" +#include "gl_ate_agent.h" +#include "gl_qa_agent.h" +#if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE +#include +#endif +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +enum { + ATE_LOG_RXV = 1, + ATE_LOG_RDD, + ATE_LOG_RE_CAL, + ATE_LOG_TYPE_NUM, + ATE_LOG_RXINFO, + ATE_LOG_TXDUMP, + ATE_LOG_TEST, +}; + +enum { + ATE_LOG_OFF, + ATE_LOG_ON, + ATE_LOG_DUMP, + ATE_LOG_CTRL_NUM, +}; + +/* Maximum rxv vectors under 2048-2 bytes */ +#define MAX_RXV_DUMP_COUNT (56) +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Enter Test Mode. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEStart(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetTestMode, /* pfnOidHandler */ + NULL, /* pvInfoBuf */ + 0, /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Enter ICAP Mode. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ICAPStart(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetTestIcapMode, /* pfnOidHandler */ + NULL, /* pvInfoBuf */ + 0, /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Enter ICAP Mode. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ICAPCommand(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct mt66xx_chip_info *prChipInfo = NULL; + struct ATE_OPS_T *prAteOps = NULL; + uint32_t *buf = NULL; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prChipInfo = prGlueInfo->prAdapter->chip_info; + ASSERT(prChipInfo); + prAteOps = prChipInfo->prAteOps; + ASSERT(prAteOps); + + if (prInBuf[0] == '1') { + if (prAteOps->setICapStart) + i4Status = prAteOps->setICapStart(prGlueInfo, + 1, + 0, + 0, + 0x10000006, + 0, + 10, + 0, + 0x2000, + 0xefefefef, + 0x0001efef, + 0); + else + i4Status = 1; + } else if (prInBuf[0] == '2') { + if (prAteOps->getICapStatus) + i4Status = prAteOps->getICapStatus(prGlueInfo); + else + i4Status = 1; + } else if (prInBuf[0] == '3') { + if (prAteOps->getICapIQData) { + buf = kalMemAlloc(1024, VIR_MEM_TYPE); + i4Status = prAteOps->getICapIQData(prGlueInfo, + (uint8_t *) buf, CAP_I_TYPE, 0); + dumpMemory32((uint32_t *)buf, i4Status); + kalMemFree(buf, VIR_MEM_TYPE, 1024); + } else + i4Status = 1; + } else if (prInBuf[0] == '4') { + if (prAteOps->getICapIQData) { + buf = (uint32_t *) kalMemAlloc(1024, VIR_MEM_TYPE); + i4Status = prAteOps->getICapIQData(prGlueInfo, + (uint8_t *) buf, CAP_Q_TYPE, 0); + dumpMemory32((uint32_t *)buf, i4Status); + kalMemFree(buf, VIR_MEM_TYPE, 1024); + } else + i4Status = 1; + } + + return i4Status; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Abort Test Mode. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEStop(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAbortTestMode, /* pfnOidHandler */ + NULL, /* pvInfoBuf */ + 0, /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Start auto Tx test in packet format and the driver will + * enter auto Tx test mode. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEStartTX(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_STARTTX; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Stop TX/RX test action if the driver is in any test + * mode. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEStopTX(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_STOPTEST; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Start auto Rx test and the driver will enter auto Rx + * test mode. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEStartRX(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_STARTRX; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Stop TX/RX test action if the driver is in any test + * mode. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prInBuf + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEStopRX(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_STOPTEST; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Channel Frequency. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4SetFreq Center frequency in unit of KHz + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetChannel(struct net_device *prNetDev, + uint32_t u4SXIdx, uint32_t u4SetFreq) +{ + uint32_t u4BufLen = 0; + uint32_t i4SetChan; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + i4SetChan = nicFreq2ChannelNum(u4SetFreq); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetChannel=%d, Freq=%d\n", + i4SetChan, u4SetFreq); + + if (u4SetFreq == 0) + return -EINVAL; + + if (u4SXIdx == 0) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_CHNL_FREQ; + rRfATInfo.u4FuncData = u4SetFreq; + } else { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_CHNL_FREQ | BIT(16); + rRfATInfo.u4FuncData = u4SetFreq; + } + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Preamble. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4Mode depends on Rate. 0--> normal, + * 1--> CCK short preamble, + * 2: 11n MM, + * 3: 11n GF + * 4: 11ac VHT + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetPreamble(struct net_device *prNetDev, + uint32_t u4Mode) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetPreamble=%d\n", + u4Mode); + + if (u4Mode > 4) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_PREAMBLE; + rRfATInfo.u4FuncData = u4Mode; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Channel Bandwidth. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4BW Choose Channel Bandwidth + * 0: 20 / 1: 40 / 2: 80 / 3: 160 + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetSystemBW(struct net_device *prNetDev, + uint32_t u4BW) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t u4BWMapping = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetSystemBW=%d\n", u4BW); + + if (u4BW > 6) + return -EINVAL; + + /* BW Mapping in QA Tool + * 0: BW20 + * 1: BW40 + * 2: BW80 + * 3: BW10 + * 4: BW5 + * 5: BW160C + * 6: BW160NC + */ + /* BW Mapping in FW + * 0: BW20 + * 1: BW40 + * 2: BW80 + * 3: BW160C + * 4: BW160NC + * 5: BW5 + * 6: BW10 + */ + if (u4BW == 0) + u4BWMapping = 0; + else if (u4BW == 1) + u4BWMapping = 1; + else if (u4BW == 2) + u4BWMapping = 2; + else if (u4BW == 3) + u4BWMapping = 6; + else if (u4BW == 4) + u4BWMapping = 5; + else if (u4BW == 5) + u4BWMapping = 3; + else if (u4BW == 6) + u4BWMapping = 4; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_CBW; + rRfATInfo.u4FuncData = u4BWMapping; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set TX Length. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4TxLength Packet length (MPDU) + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetTxLength(struct net_device *prNetDev, + uint32_t u4TxLength) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetTxLength=%d\n", + u4TxLength); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_PKTLEN; + rRfATInfo.u4FuncData = u4TxLength; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set TX Count. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4TxCount Total packet count to send. 0 : unlimited, + * until stopped + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetTxCount(struct net_device *prNetDev, + uint32_t u4TxCount) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetTxCount=%d\n", + u4TxCount); + + if (u4TxCount < 0) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_PKTCNT; + rRfATInfo.u4FuncData = u4TxCount; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set TX Inter-Packet Guard. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4TxIPG In unit of us. The min value is 19us and max + * value is 2314us. + * \ It will be round-up to (19+9n) us. + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetTxIPG(struct net_device *prNetDev, + uint32_t u4TxIPG) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetTxIPG=%d\n", u4TxIPG); + + if (u4TxIPG > 2314 || u4TxIPG < 19) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_PKTINTERVAL; + rRfATInfo.u4FuncData = u4TxIPG; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set WF0 TX Power. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4TxPower0 Tx Gain of RF. The value is signed absolute + * power + * (2's complement representation) in unit of 0.5 dBm. + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetTxPower0(struct net_device *prNetDev, + uint32_t u4TxPower0) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetTxPower0=0x%02x\n", + u4TxPower0); + + if (u4TxPower0 > 0x3F) { + u4TxPower0 += 128; + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK Negative Power =0x%02x\n", + u4TxPower0); + } + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_POWER; + rRfATInfo.u4FuncData = u4TxPower0; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Per Packet BW. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4BW 0: 20 / 1: 40 / 2: 80 / 3: 160 + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetPerPacketBW(struct net_device *prNetDev, + uint32_t u4BW) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t u4BWMapping = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetPerPacketBW=%d\n", + u4BW); + + if (u4BW > 6) + return -EINVAL; + + /* BW Mapping in QA Tool + * 0: BW20 + * 1: BW40 + * 2: BW80 + * 3: BW10 + * 4: BW5 + * 5: BW160C + * 6: BW160NC + */ + /* BW Mapping in FW + * 0: BW20 + * 1: BW40 + * 2: BW80 + * 3: BW160C + * 4: BW160NC + * 5: BW5 + * 6: BW10 + */ + if (u4BW == 0) + u4BWMapping = 0; + else if (u4BW == 1) + u4BWMapping = 1; + else if (u4BW == 2) + u4BWMapping = 2; + else if (u4BW == 3) + u4BWMapping = 6; + else if (u4BW == 4) + u4BWMapping = 5; + else if (u4BW == 5) + u4BWMapping = 3; + else if (u4BW == 6) + u4BWMapping = 4; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_DBW; + rRfATInfo.u4FuncData = u4BWMapping; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Primary Channel Setting. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4PrimaryCh The range is from 0~7 + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEPrimarySetting(struct net_device *prNetDev, + uint32_t u4PrimaryCh) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK PrimarySetting=%d\n", + u4PrimaryCh); + + if (u4PrimaryCh > 7) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_PRIMARY_CH; + rRfATInfo.u4FuncData = u4PrimaryCh; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set TX Guard Interval. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4SetTxGi 0: Normal GI, 1: Short GI + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetTxGi(struct net_device *prNetDev, + uint32_t u4SetTxGi) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetTxGi=%d\n", u4SetTxGi); + + if (u4SetTxGi != 0 && u4SetTxGi != 1) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_GI; + rRfATInfo.u4FuncData = u4SetTxGi; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set TX Path. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4Tx_path 0: All Tx, 1: WF0, 2: WF1, 3: WF0+WF1 + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetTxPath(struct net_device *prNetDev, + uint32_t u4Tx_path) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK u4Tx_path=%d\n", + u4Tx_path); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TX_PATH; + rRfATInfo.u4FuncData = u4Tx_path; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set TX Payload Fix/Random. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4Stbc 0: Disable , 1 : Enable + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetTxPayLoad(struct net_device *prNetDev, + uint32_t u4Gen_payload_rule, uint8_t ucPayload) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK rule=%d, len =0x%x\n", + u4Gen_payload_rule, ucPayload); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_PAYLOAD; + rRfATInfo.u4FuncData = ((u4Gen_payload_rule << 16) | + ucPayload); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set TX STBC. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4Stbc 0: Disable , 1 : Enable + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetTxSTBC(struct net_device *prNetDev, + uint32_t u4Stbc) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK u4Stbc=%d\n", u4Stbc); + + if (u4Stbc > 1) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_STBC; + rRfATInfo.u4FuncData = u4Stbc; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set TX Nss. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4Nss 1/2 + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetTxVhtNss(struct net_device *prNetDev, + uint32_t u4VhtNss) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK u4Nss=%d\n", u4VhtNss); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_NSS; + rRfATInfo.u4FuncData = u4VhtNss; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Rate. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4Rate Rate + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetRate(struct net_device *prNetDev, + uint32_t u4Rate) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetRate=0x%08x\n", + u4Rate); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_RATE; + rRfATInfo.u4FuncData = u4Rate; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Encode Mode. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4Ldpc 0: BCC / 1: LDPC + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetEncodeMode(struct net_device *prNetDev, + uint32_t u4Ldpc) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetEncodeMode=%d\n", + u4Ldpc); + + if (u4Ldpc != 0 && u4Ldpc != 1) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ENCODE_MODE; + rRfATInfo.u4FuncData = u4Ldpc; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set iBF Enable. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4iBF 0: disable / 1: enable + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetiBFEnable(struct net_device *prNetDev, + uint32_t u4iBF) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetiBFEnable=%d\n", + u4iBF); + + if (u4iBF != 0 && u4iBF != 1) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_IBF_ENABLE; + rRfATInfo.u4FuncData = u4iBF; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set eBF Enable. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4eBF 0: disable / 1: enable + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESeteBFEnable(struct net_device *prNetDev, + uint32_t u4eBF) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SeteBFEnable=%d\n", + u4eBF); + + if (u4eBF != 0 && u4eBF != 1) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_EBF_ENABLE; + rRfATInfo.u4FuncData = u4eBF; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set MAC Address. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4Type Address type + * \param[in] ucAddr Address ready to set + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetMACAddress(struct net_device *prNetDev, + uint32_t u4Type, uint8_t *ucAddr) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, ERROR, + "QA_ATE_HOOK SetMACAddress Type = %d, Addr = %02x:%02x:%02x:%02x:%02x:%02x\n", + u4Type, ucAddr[0], ucAddr[1], ucAddr[2], ucAddr[3], + ucAddr[4], ucAddr[5]); + +#if 1 + rRfATInfo.u4FuncIndex = u4Type; + memcpy(&rRfATInfo.u4FuncData, ucAddr, 4); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; +#endif + rRfATInfo.u4FuncIndex = u4Type | BIT(18); + memset(&rRfATInfo.u4FuncData, 0, + sizeof(rRfATInfo.u4FuncData)); + memcpy(&rRfATInfo.u4FuncData, ucAddr + 4, 2); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for RX Vector Dump. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4Type + * \param[in] u4On_off + * \param[in] u4Size + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATELogOnOff(struct net_device *prNetDev, + uint32_t u4Type, uint32_t u4On_off, uint32_t u4Size) +{ + int32_t i4Status = 0, i, i4TargetLength = 0, + i4MaxDumpRXVCnt = 500; + uint32_t u4BufLen = 0, rxv; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATELogOnOff\n"); + + switch (u4Type) { + case ATE_LOG_RXV: + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATELogOnOff : ATE_LOG_RXV\n\n"); + break; + case ATE_LOG_RDD: + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATELogOnOff : ATE_LOG_RDD\n\n"); + break; + case ATE_LOG_RE_CAL: + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATELogOnOff : ATE_LOG_RE_CAL\n\n"); + break; + case ATE_LOG_RXINFO: + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATELogOnOff : ATE_LOG_RXINFO\n\n"); + break; + case ATE_LOG_TXDUMP: + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATELogOnOff : ATE_LOG_TXDUMP\n\n"); + break; + case ATE_LOG_TEST: + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATELogOnOff : ATE_LOG_TEST\n\n"); + break; + default: + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK log type %d not supported\n\n", u4Type); + } + + if ((u4On_off == ATE_LOG_DUMP) && (u4Type == ATE_LOG_RXV)) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_RESULT_INFO; + rRfATInfo.u4FuncData = RF_AT_FUNCID_RXV_DUMP; + + i4Status = kalIoctl(prGlueInfo, wlanoidRftestQueryAutoTest, + &rRfATInfo, sizeof(rRfATInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + i4TargetLength = rRfATInfo.u4FuncData * 36; + DBGLOG(RFTEST, ERROR, + "QA_ATE_HOOK Get RX Vector Total size = %d\n", + i4TargetLength); + + if (i4TargetLength >= (i4MaxDumpRXVCnt * 36)) + i4TargetLength = (i4MaxDumpRXVCnt * 36); + } else { + DBGLOG(RFTEST, ERROR, + "QA_ATE_HOOK Get RX Vector Total Size Error!!!!\n\n"); + } + + TOOL_PRINTLOG(RFTEST, ERROR, "[LOG DUMP START]\n"); + + for (i = 0; i < i4TargetLength; i += 4) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_RXV_DUMP; + rRfATInfo.u4FuncData = i; + + i4Status = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, + &rRfATInfo, sizeof(rRfATInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + rxv = rRfATInfo.u4FuncData; + + if (i % 36 == 0) + TOOL_PRINTLOG(RFTEST, ERROR, + "%%[RXV DUMP START][%d]\n", + (i / 36) + 1); + + TOOL_PRINTLOG(RFTEST, ERROR, "[RXVD%d]%08x\n", + ((i % 36) / 4) + 1, rxv); + + if (((i % 36) / 4) + 1 == 9) + TOOL_PRINTLOG(RFTEST, ERROR, + "[RXV DUMP END]\n"); + } + } + + TOOL_PRINTLOG(RFTEST, ERROR, "[LOG DUMP END]\n"); + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Get RX Vector Dump. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[out] pucData Pointer to the output data buffer +* \param[out] pCount Pointer to the length of data +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEGetDumpRXV(struct net_device *prNetDev, + uint8_t *pucData, + int32_t *pCount) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t i = 0, u4BufLen = 0, u4Value = 0; + uint32_t u4RespLen = 2, i4TargetLength = 0; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_RESULT_INFO; + rRfATInfo.u4FuncData = RF_AT_FUNCID_RXV_DUMP; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + + i4Status = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, + &rRfATInfo, + sizeof(rRfATInfo), + TRUE, + TRUE, + TRUE, + &u4BufLen); + + if (i4Status == 0) { + DBGLOG(RFTEST, INFO, "Get RX Vector Total count = %d\n", + rRfATInfo.u4FuncData); + if (rRfATInfo.u4FuncData > MAX_RXV_DUMP_COUNT) + rRfATInfo.u4FuncData = MAX_RXV_DUMP_COUNT; + + i4TargetLength = rRfATInfo.u4FuncData * 36; + u4Value = ntohl(rRfATInfo.u4FuncData); + kalMemCopy(pucData + u4RespLen, + (uint8_t *)&u4Value, + sizeof(u4Value)); + u4RespLen += sizeof(u4Value); + } else { + DBGLOG(RFTEST, ERROR, "Get RX Vector Total Size Error!!\n"); + return -EFAULT; + } + + for (i = 0; i < i4TargetLength; i += 4) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_RXV_DUMP; + rRfATInfo.u4FuncData = i; + + i4Status = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, + &rRfATInfo, + sizeof(rRfATInfo), + TRUE, + TRUE, + TRUE, + &u4BufLen); + + if (i4Status == 0) { + u4Value = ntohl(rRfATInfo.u4FuncData); + kalMemCopy(pucData + u4RespLen, + (uint8_t *)&u4Value, + sizeof(u4Value)); + u4RespLen += sizeof(u4Value); + } else { + DBGLOG(RFTEST, ERROR, + "Error getting index[%d]'s RXV dump data!!\n", i); + return -EFAULT; + } + } + + *pCount = i4TargetLength; + /* dumpMemory32((PUINT_32)pucData, i4TargetLength + 8); */ + + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Reset Counter. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEResetTXRXCounter(struct net_device *prNetDev) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATEResetTXRXCounter\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_RESETTXRXCOUNTER; + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set DBDC Band Index. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4BandIdx Band Index Number ready to set + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetDBDCBandIndex(struct net_device *prNetDev, + uint32_t u4BandIdx) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATESetDBDCBandIndex\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_DBDC_BAND_IDX; + rRfATInfo.u4FuncData = u4BandIdx; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Band. (2G or 5G) + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] i4Band Band to set + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetBand(struct net_device *prNetDev, + int32_t i4Band) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATESetBand\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_BAND; + rRfATInfo.u4FuncData = i4Band; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Tx Tone Type. (2G or 5G) + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] i4ToneType Set Single or Two Tone. + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetTxToneType(struct net_device *prNetDev, + int32_t i4ToneType) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATESetTxToneType\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TONE_TYPE; + rRfATInfo.u4FuncData = i4ToneType; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Tx Tone Frequency. (DC/5M/10M/20M/40M) + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] i4ToneFreq Set Tx Tone Frequency. + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetTxToneBW(struct net_device *prNetDev, + int32_t i4ToneFreq) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATESetTxToneBW\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TONE_BW; + rRfATInfo.u4FuncData = i4ToneFreq; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Tx Tone DC Offset. (DC Offset I / DC Offset Q) + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] i4DcOffsetI Set Tx Tone DC Offset I. + * \param[in] i4DcOffsetQ Set Tx Tone DC Offset Q. + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetTxToneDCOffset(struct net_device *prNetDev, + int32_t i4DcOffsetI, int32_t i4DcOffsetQ) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATESetTxToneDCOffset\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TONE_DC_OFFSET; + rRfATInfo.u4FuncData = i4DcOffsetQ << 16 | i4DcOffsetI; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Tx Tone Power. (RF and Digital) + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] i4AntIndex + * \param[in] i4RF_Power + * \param[in] i4Digi_Power + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetDBDCTxTonePower(struct net_device *prNetDev, + int32_t i4AntIndex, int32_t i4RF_Power, int32_t i4Digi_Power) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATESetDBDCTxTonePower\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TONE_RF_GAIN; + rRfATInfo.u4FuncData = i4AntIndex << 16 | i4RF_Power; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TONE_DIGITAL_GAIN; + rRfATInfo.u4FuncData = i4AntIndex << 16 | i4Digi_Power; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Start Tx Tone. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] i4Control Start or Stop TX Tone. + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEDBDCTxTone(struct net_device *prNetDev, + int32_t i4Control) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATEDBDCTxTone\n"); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (i4Control) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_SINGLE_TONE; + } else { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_STOPTEST; + } + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set TX Mac Header. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u4BandIdx Band Index Number ready to set + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetMacHeader(struct net_device *prNetDev, + uint32_t u4FrameCtrl, uint32_t u4DurationID, + uint32_t u4SeqCtrl) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATESetMacHeader\n"); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MAC_HEADER; + rRfATInfo.u4FuncData = u4FrameCtrl || (u4DurationID << 16); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_SEQ_CTRL; + rRfATInfo.u4FuncData = u4SeqCtrl; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for IRR Set ADC. (RF_AT_FUNCID_SET_ADC) + * + * \param[in] prNetDev Pointer to the Net Device + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATE_IRRSetADC(struct net_device *prNetDev, + uint32_t u4WFIdx, + uint32_t u4ChFreq, + uint32_t u4BW, uint32_t u4Sx, uint32_t u4Band, + uint32_t u4RunType, uint32_t u4FType) +{ + uint32_t u4BufLen = 0, i = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t au4Param[7]; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATE_IRRSetADC\n"); + + if (u4BW == 3 || u4BW == 4 || u4BW > 5) + return -EINVAL; + + if (u4BW == 5) /* For BW160, UI will pass "5" */ + u4BW = 3; + + au4Param[0] = u4ChFreq; + au4Param[1] = u4WFIdx; + au4Param[2] = u4BW; + au4Param[3] = u4Sx; + au4Param[4] = u4Band; + au4Param[5] = u4RunType; + au4Param[6] = u4FType; + + for (i = 0; i < 8; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ADC | (i << 16); + if (i < 7) + rRfATInfo.u4FuncData = au4Param[i]; + else + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for IRR Set RX Gain. (RF_AT_FUNCID_SET_RX_GAIN) + * + * \param[in] prNetDev Pointer to the Net Device + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATE_IRRSetRxGain(struct net_device *prNetDev, + uint32_t u4PgaLpfg, uint32_t u4Lna, uint32_t u4Band, + uint32_t u4WF_inx, uint32_t u4Rfdgc) +{ + uint32_t u4BufLen = 0, i = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t au4Param[5]; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATE_IRRSetRxGain\n"); + + au4Param[0] = u4PgaLpfg; + au4Param[1] = u4Lna; + au4Param[2] = u4Band; + au4Param[3] = u4WF_inx; + au4Param[4] = u4Rfdgc; + + for (i = 0; i < 6; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_RX_GAIN | + (i << 16); + if (i < 5) + rRfATInfo.u4FuncData = au4Param[i]; + else + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for IRR Set TTG. (RF_AT_FUNCID_SET_TTG) + * + * \param[in] prNetDev Pointer to the Net Device + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATE_IRRSetTTG(struct net_device *prNetDev, + uint32_t u4TTGPwrIdx, uint32_t u4ChFreq, + uint32_t u4FIToneFreq, uint32_t u4Band) +{ + uint32_t u4BufLen = 0, i = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t au4Param[4]; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATE_IRRSetTTG\n"); + + au4Param[0] = u4ChFreq; + au4Param[1] = u4FIToneFreq; + au4Param[2] = u4TTGPwrIdx; + au4Param[3] = u4Band; + + for (i = 0; i < 5; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TTG | (i << 16); + if (i < 4) + rRfATInfo.u4FuncData = au4Param[i]; + else + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for IRR Set TTG On/Off. (RF_AT_FUNCID_TTG_ON_OFF) + * + * \param[in] prNetDev Pointer to the Net Device + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATE_IRRSetTrunOnTTG(struct net_device *prNetDev, + uint32_t u4TTGOnOff, uint32_t u4Band, uint32_t u4WF_inx) +{ + uint32_t u4BufLen = 0, i = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t au4Param[3]; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATE_IRRSetTrunOnTTG\n"); + + au4Param[0] = u4TTGOnOff; + au4Param[1] = u4Band; + au4Param[2] = u4WF_inx; + + for (i = 0; i < 4; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_TTG_ON_OFF | (i << 16); + if (i < 3) + rRfATInfo.u4FuncData = au4Param[i]; + else + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for IRR Set TTG On/Off. + * + * \param[in] prNetDev Pointer to the Net Device + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATE_TMRSetting(struct net_device *prNetDev, uint32_t u4Setting, + uint32_t u4Version, uint32_t u4MPThres, uint32_t u4MPIter) +{ + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATE_TMRSetting\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TMR_ROLE; + rRfATInfo.u4FuncData = u4Setting; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TMR_MODULE; + rRfATInfo.u4FuncData = u4Version; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TMR_DBM; + rRfATInfo.u4FuncData = u4MPThres; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TMR_ITER; + rRfATInfo.u4FuncData = u4MPIter; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for MPS Setting. (Set Seq Data) + * + * \param[in] prNetDev Pointer to the Net Device + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEMPSSetSeqData(struct net_device *prNetDev, + uint32_t u4TestNum, uint32_t *pu4Phy, uint32_t u4Band) +{ + uint32_t u4BufLen = 0, i; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATEMPSSetSeqData\n"); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_SIZE; + rRfATInfo.u4FuncData = u4TestNum; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + for (i = 0 ; i < u4TestNum ; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_SEQ_DATA | + (i << 16); + rRfATInfo.u4FuncData = pu4Phy[i]; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for MPS Setting. (Set Payload Length) + * + * \param[in] prNetDev Pointer to the Net Device + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEMPSSetPayloadLength(struct net_device *prNetDev, + uint32_t u4TestNum, uint32_t *pu4Length, uint32_t u4Band) +{ + uint32_t u4BufLen = 0, i; + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATEMPSSetPayloadLength\n"); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + for (i = 0 ; i < u4TestNum ; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_PAYLOAD_LEN | + (i << 16); + rRfATInfo.u4FuncData = pu4Length[i]; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for MPS Setting. (Set Packet Count) + * + * \param[in] prNetDev Pointer to the Net Device + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEMPSSetPacketCount(struct net_device *prNetDev, + uint32_t u4TestNum, uint32_t *pu4PktCnt, uint32_t u4Band) +{ + uint32_t u4BufLen = 0, i; + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATEMPSSetPacketCount\n"); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + for (i = 0 ; i < u4TestNum ; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_PKT_CNT | + (i << 16); + rRfATInfo.u4FuncData = pu4PktCnt[i]; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for MPS Setting. (Set Power Gain) + * + * \param[in] prNetDev Pointer to the Net Device + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEMPSSetPowerGain(struct net_device *prNetDev, + uint32_t u4TestNum, uint32_t *pu4PwrGain, uint32_t u4Band) +{ + uint32_t u4BufLen = 0, i; + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATEMPSSetPowerGain\n"); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + for (i = 0 ; i < u4TestNum ; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_PWR_GAIN | + (i << 16); + rRfATInfo.u4FuncData = pu4PwrGain[i]; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for MPS Setting. (Set NSS) + * + * \param[in] prNetDev Pointer to the Net Device + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEMPSSetNss(struct net_device *prNetDev, + uint32_t u4TestNum, uint32_t *pu4Nss, uint32_t u4Band) +{ + uint32_t u4BufLen = 0, i; + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK MT_ATEMPSSetNss\n"); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + for (i = 0 ; i < u4TestNum ; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_NSS | + (i << 16); + rRfATInfo.u4FuncData = pu4Nss[i]; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for MPS Setting. (Set NSS) + * + * \param[in] prNetDev Pointer to the Net Device + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEMPSSetPerpacketBW(struct net_device *prNetDev, + uint32_t u4TestNum, uint32_t *pu4PerPktBW, uint32_t u4Band) +{ + uint32_t u4BufLen = 0, i; + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + DBGLOG(RFTEST, INFO, + "QA_ATE_HOOK MT_ATEMPSSetPerpacketBW\n"); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + for (i = 0 ; i < u4TestNum ; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_PACKAGE_BW | + (i << 16); + rRfATInfo.u4FuncData = pu4PerPktBW[i]; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Start RDD. + * + * \param[in] prNetDev Pointer to the Net Device + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATERDDStart(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4BufLen = 0; + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_RDD; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Stop RDD. + * + * \param[in] prNetDev Pointer to the Net Device + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATERDDStop(struct net_device *prNetDev, + uint8_t *prInBuf) +{ + uint32_t u4BufLen = 0; + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_ATE_HOOK SetATE = %s\n", prInBuf); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_RDD_OFF; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; + +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Write Efuse. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u2Offset Efuse offset + * \param[in] u2Content Efuse content + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATEWriteEfuse(struct net_device *prNetDev, + uint16_t u2Offset, uint16_t u2Content) +{ + uint32_t u4BufLen = 0; + struct PARAM_CUSTOM_ACCESS_EFUSE rAccessEfuseInfoRead, + rAccessEfuseInfoWrite; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t i4Status = WLAN_STATUS_SUCCESS; + uint8_t u4Index = 0, u4Loop = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + kalMemSet(&rAccessEfuseInfoRead, 0, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + kalMemSet(&rAccessEfuseInfoWrite, 0, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + + + + /* Read */ + DBGLOG(INIT, INFO, "QA_AGENT HQA_WriteBulkEEPROM Read\n"); + kalMemSet(&rAccessEfuseInfoRead, 0, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + rAccessEfuseInfoRead.u4Address = (u2Offset / + EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + i4Status = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfoRead, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), + TRUE, TRUE, TRUE, &u4BufLen); + + + /* Write */ + kalMemSet(&rAccessEfuseInfoWrite, 0, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + u4Index = u2Offset % EFUSE_BLOCK_SIZE; + + if (u4Index >= EFUSE_BLOCK_SIZE - 1) { + DBGLOG(INIT, INFO, "u4Index [%d] overrun\n", u4Index); + return -EFAULT; + } + + prGlueInfo->prAdapter->aucEepromVaule[u4Index] = u2Content; + prGlueInfo->prAdapter->aucEepromVaule[u4Index + 1] = + u2Content >> 8 & 0xff; + + kalMemCopy(rAccessEfuseInfoWrite.aucData, + prGlueInfo->prAdapter->aucEepromVaule, 16); + + for (u4Loop = 0; u4Loop < (EFUSE_BLOCK_SIZE); u4Loop++) { + DBGLOG(INIT, INFO, + "QA_AGENT aucEepromVaule u4Loop=%d u4Value=%x\n", + u4Loop, prGlueInfo->prAdapter->aucEepromVaule[u4Loop]); + + DBGLOG(INIT, INFO, + "QA_AGENT rAccessEfuseInfoWrite.aucData u4Loop=%d u4Value=%x\n", + u4Loop, rAccessEfuseInfoWrite.aucData[u4Loop]); + } + + rAccessEfuseInfoWrite.u4Address = (u2Offset / + EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + + i4Status = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseWrite, + &rAccessEfuseInfoWrite, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), + FALSE, TRUE, TRUE, &u4BufLen); + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Tx Target Power. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] u2TxTargetPower TxTarget Power + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetTxTargetPower(struct net_device *prNetDev, + uint8_t ucTxTargetPower) +{ + uint32_t u4BufLen = 0; + struct PARAM_CUSTOM_SET_TX_TARGET_POWER rSetTxTargetPwr; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t i4Status = WLAN_STATUS_SUCCESS; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + kalMemSet(&rSetTxTargetPwr, 0, + sizeof(struct PARAM_CUSTOM_SET_TX_TARGET_POWER)); + + + /* Set Target Power Base */ + DBGLOG(INIT, INFO, "QA_AGENT Set Tx Target Power= %x dbm\n", + ucTxTargetPower); + rSetTxTargetPwr.ucTxTargetPwr = ucTxTargetPower; + + i4Status = kalIoctl(prGlueInfo, + wlanoidQuerySetTxTargetPower, + &rSetTxTargetPwr, + sizeof(struct PARAM_CUSTOM_SET_TX_TARGET_POWER), + FALSE, FALSE, TRUE, &u4BufLen); + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +#if (CFG_SUPPORT_DFS_MASTER == 1) +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Rdd Report. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] ucDbdcIdx Dbdc Index + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetRddReport(struct net_device *prNetDev, + uint8_t ucDbdcIdx) +{ + uint32_t u4BufLen = 0; + struct PARAM_CUSTOM_SET_RDD_REPORT rSetRddReport; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t i4Status = WLAN_STATUS_SUCCESS; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + kalMemSet(&rSetRddReport, 0, + sizeof(struct PARAM_CUSTOM_SET_RDD_REPORT)); + + /* Set Rdd Report */ + DBGLOG(INIT, INFO, "QA_AGENT Set RDD Report - Band: %d\n", + ucDbdcIdx); + rSetRddReport.ucDbdcIdx = ucDbdcIdx; + + i4Status = kalIoctl(prGlueInfo, + wlanoidQuerySetRddReport, + &rSetRddReport, + sizeof(struct PARAM_CUSTOM_SET_RDD_REPORT), + FALSE, FALSE, TRUE, &u4BufLen); + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Hook API for Set Radar Detect Mode. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] ucRadarDetectMode Radar Detect Mode + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If kalIoctl return nonzero. + * \retval -EINVAL If invalid argument. + */ +/*----------------------------------------------------------------------------*/ +int32_t MT_ATESetRadarDetectMode(struct net_device + *prNetDev, uint8_t ucRadarDetectMode) +{ + uint32_t u4BufLen = 0; + struct PARAM_CUSTOM_SET_RADAR_DETECT_MODE + rSetRadarDetectMode; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t i4Status = WLAN_STATUS_SUCCESS; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + kalMemSet(&rSetRadarDetectMode, 0, + sizeof(struct PARAM_CUSTOM_SET_RADAR_DETECT_MODE)); + + /* Set Rdd Report */ + DBGLOG(INIT, INFO, "QA_AGENT Set Radar Detect Mode: %d\n", + ucRadarDetectMode); + rSetRadarDetectMode.ucRadarDetectMode = ucRadarDetectMode; + + i4Status = kalIoctl(prGlueInfo, + wlanoidQuerySetRadarDetectMode, + &rSetRadarDetectMode, + sizeof(struct PARAM_CUSTOM_SET_RADAR_DETECT_MODE), + FALSE, FALSE, TRUE, &u4BufLen); + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +#endif + +#if CFG_SUPPORT_TX_BF +int32_t TxBfProfileTag_InValid(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + uint8_t ucInValid) +{ + int32_t i4Status = 0; + + prPfmuTag1->rField.ucInvalidProf = ucInValid; + + return i4Status; +} + +int32_t TxBfProfileTag_PfmuIdx(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + uint8_t ucProfileIdx) +{ + int32_t i4Status = 0; + + prPfmuTag1->rField.ucProfileID = ucProfileIdx; + + return i4Status; +} + +int32_t TxBfProfileTag_TxBfType(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + uint8_t ucBFType) +{ + int32_t i4Status = 0; + + prPfmuTag1->rField.ucTxBf = ucBFType; + + return i4Status; +} + +int32_t TxBfProfileTag_DBW(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, uint8_t ucBW) +{ + int32_t i4Status = 0; + + prPfmuTag1->rField.ucDBW = ucBW; + + return i4Status; +} + +int32_t TxBfProfileTag_SuMu(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, uint8_t ucSuMu) +{ + int32_t i4Status = 0; + + prPfmuTag1->rField.ucSU_MU = ucSuMu; + + return i4Status; +} + +int32_t TxBfProfileTag_Mem(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + uint8_t *aucMemAddrColIdx, uint8_t *aucMemAddrRowIdx) +{ + int32_t i4Status = 0; + + prPfmuTag1->rField.ucMemAddr1ColIdx = aucMemAddrColIdx[0]; + prPfmuTag1->rField.ucMemAddr1RowIdx = aucMemAddrRowIdx[0]; + prPfmuTag1->rField.ucMemAddr2ColIdx = aucMemAddrColIdx[1]; + prPfmuTag1->rField.ucMemAddr2RowIdx = aucMemAddrRowIdx[1] & + 0x1F; + prPfmuTag1->rField.ucMemAddr2RowIdxMsb = aucMemAddrRowIdx[1] + >> 5; + prPfmuTag1->rField.ucMemAddr3ColIdx = aucMemAddrColIdx[2]; + prPfmuTag1->rField.ucMemAddr3RowIdx = aucMemAddrRowIdx[2]; + prPfmuTag1->rField.ucMemAddr4ColIdx = aucMemAddrColIdx[3]; + prPfmuTag1->rField.ucMemAddr4RowIdx = aucMemAddrRowIdx[3]; + + return i4Status; +} + +int32_t TxBfProfileTag_Matrix(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + uint8_t ucNrow, + uint8_t ucNcol, uint8_t ucNgroup, uint8_t ucLM, + uint8_t ucCodeBook, uint8_t ucHtcExist) +{ + int32_t i4Status = 0; + + prPfmuTag1->rField.ucNrow = ucNrow; + prPfmuTag1->rField.ucNcol = ucNcol; + prPfmuTag1->rField.ucNgroup = ucNgroup; + prPfmuTag1->rField.ucLM = ucLM; + prPfmuTag1->rField.ucCodeBook = ucCodeBook; + prPfmuTag1->rField.ucHtcExist = ucHtcExist; + + return i4Status; +} + +int32_t TxBfProfileTag_SNR(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + uint8_t ucSNR_STS0, uint8_t ucSNR_STS1, + uint8_t ucSNR_STS2, uint8_t ucSNR_STS3) +{ + int32_t i4Status = 0; + + prPfmuTag1->rField.ucSNR_STS0 = ucSNR_STS0; + prPfmuTag1->rField.ucSNR_STS1 = ucSNR_STS1; + prPfmuTag1->rField.ucSNR_STS2 = ucSNR_STS2; + prPfmuTag1->rField.ucSNR_STS3 = ucSNR_STS3; + + return i4Status; +} + +int32_t TxBfProfileTag_SmtAnt(struct net_device *prNetDev, + union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t ucSmartAnt) +{ + int32_t i4Status = 0; + + prPfmuTag2->rField.u2SmartAnt = ucSmartAnt; + + return i4Status; +} + +int32_t TxBfProfileTag_SeIdx(struct net_device *prNetDev, + union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t ucSeIdx) +{ + int32_t i4Status = 0; + + prPfmuTag2->rField.ucSEIdx = ucSeIdx; + + return i4Status; +} + +int32_t TxBfProfileTag_RmsdThd(struct net_device *prNetDev, + union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t ucRmsdThrd) +{ + int32_t i4Status = 0; + + prPfmuTag2->rField.ucRMSDThd = ucRmsdThrd; + + return i4Status; +} + +int32_t TxBfProfileTag_McsThd(struct net_device *prNetDev, + union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t *pMCSThLSS, uint8_t *pMCSThSSS) +{ + int32_t i4Status = 0; + + prPfmuTag2->rField.ucMCSThL1SS = pMCSThLSS[0]; + prPfmuTag2->rField.ucMCSThS1SS = pMCSThSSS[0]; + prPfmuTag2->rField.ucMCSThL2SS = pMCSThLSS[1]; + prPfmuTag2->rField.ucMCSThS2SS = pMCSThSSS[1]; + prPfmuTag2->rField.ucMCSThL3SS = pMCSThLSS[2]; + prPfmuTag2->rField.ucMCSThS3SS = pMCSThSSS[2]; + + return i4Status; +} + +int32_t TxBfProfileTag_TimeOut(struct net_device *prNetDev, + union PFMU_PROFILE_TAG2 *prPfmuTag2, uint8_t ucTimeOut) +{ + int32_t i4Status = 0; + + prPfmuTag2->rField.uciBfTimeOut = ucTimeOut; + + return i4Status; +} + +int32_t TxBfProfileTag_DesiredBW(struct net_device + *prNetDev, union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t ucDesiredBW) +{ + int32_t i4Status = 0; + + prPfmuTag2->rField.uciBfDBW = ucDesiredBW; + + return i4Status; +} + +int32_t TxBfProfileTag_DesiredNc(struct net_device + *prNetDev, union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t ucDesiredNc) +{ + int32_t i4Status = 0; + + prPfmuTag2->rField.uciBfNcol = ucDesiredNc; + + return i4Status; +} + +int32_t TxBfProfileTag_DesiredNr(struct net_device + *prNetDev, union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t ucDesiredNr) +{ + int32_t i4Status = 0; + + prPfmuTag2->rField.uciBfNrow = ucDesiredNr; + + return i4Status; +} + +int32_t TxBfProfileTagWrite(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t profileIdx) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : au4RawData[0] = 0x%08x\n", + prPfmuTag1->au4RawData[0]); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : au4RawData[1] = 0x%08x\n", + prPfmuTag1->au4RawData[1]); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : au4RawData[2] = 0x%08x\n", + prPfmuTag1->au4RawData[2]); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : au4RawData[3] = 0x%08x\n", + prPfmuTag1->au4RawData[3]); + + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : au4RawData[0] = 0x%08x\n", + prPfmuTag2->au4RawData[0]); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : au4RawData[1] = 0x%08x\n", + prPfmuTag2->au4RawData[1]); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : au4RawData[2] = 0x%08x\n", + prPfmuTag2->au4RawData[2]); + + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucProfileID= %d\n", + prPfmuTag1->rField.ucProfileID); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucTxBf= %d\n", + prPfmuTag1->rField.ucTxBf); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucDBW= %d\n", + prPfmuTag1->rField.ucDBW); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucSU_MU= %d\n", + prPfmuTag1->rField.ucSU_MU); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucInvalidProf= %d\n", + prPfmuTag1->rField.ucInvalidProf); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucRMSD= %d\n", + prPfmuTag1->rField.ucRMSD); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr1ColIdx= %d\n", + prPfmuTag1->rField.ucMemAddr1ColIdx); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr1RowIdx= %d\n", + prPfmuTag1->rField.ucMemAddr1RowIdx); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr2ColIdx= %d\n", + prPfmuTag1->rField.ucMemAddr2ColIdx); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr2RowIdx= %d\n", + prPfmuTag1->rField.ucMemAddr2RowIdx); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr2RowIdxMsb= %d\n", + prPfmuTag1->rField.ucMemAddr2RowIdxMsb); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr3ColIdx= %d\n", + prPfmuTag1->rField.ucMemAddr3ColIdx); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr3RowIdx= %d\n", + prPfmuTag1->rField.ucMemAddr3RowIdx); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr4ColIdx= %d\n", + prPfmuTag1->rField.ucMemAddr4ColIdx); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucMemAddr4RowIdx= %d\n", + prPfmuTag1->rField.ucMemAddr4RowIdx); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucReserved= %d\n", + prPfmuTag1->rField.ucReserved); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucNrow= %d\n", + prPfmuTag1->rField.ucNrow); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucNcol= %d\n", + prPfmuTag1->rField.ucNcol); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucNgroup= %d\n", + prPfmuTag1->rField.ucNgroup); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucLM= %d\n", + prPfmuTag1->rField.ucLM); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucCodeBook= %d\n", + prPfmuTag1->rField.ucCodeBook); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucHtcExist= %d\n", + prPfmuTag1->rField.ucHtcExist); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucReserved1= %d\n", + prPfmuTag1->rField.ucReserved1); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucSNR_STS0= %d\n", + prPfmuTag1->rField.ucSNR_STS0); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucSNR_STS1= %d\n", + prPfmuTag1->rField.ucSNR_STS1); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucSNR_STS2= %d\n", + prPfmuTag1->rField.ucSNR_STS2); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucSNR_STS3= %d\n", + prPfmuTag1->rField.ucSNR_STS3); + DBGLOG(RFTEST, ERROR, + "prPfmuTag1 : prPfmuTag1->rField.ucIBfLnaIdx= %d\n", + prPfmuTag1->rField.ucIBfLnaIdx); + + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.u2SmartAnt = %d\n", + prPfmuTag2->rField.u2SmartAnt); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucReserved0 = %d\n", + prPfmuTag2->rField.ucReserved0); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucSEIdx = %d\n", + prPfmuTag2->rField.ucSEIdx); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucRMSDThd = %d\n", + prPfmuTag2->rField.ucRMSDThd); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucReserved1 = %d\n", + prPfmuTag2->rField.ucReserved1); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucMCSThL1SS = %d\n", + prPfmuTag2->rField.ucMCSThL1SS); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucMCSThS1SS = %d\n", + prPfmuTag2->rField.ucMCSThS1SS); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucMCSThL2SS = %d\n", + prPfmuTag2->rField.ucMCSThL2SS); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucMCSThS2SS = %d\n", + prPfmuTag2->rField.ucMCSThS2SS); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucMCSThL3SS = %d\n", + prPfmuTag2->rField.ucMCSThL3SS); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucMCSThS3SS = %d\n", + prPfmuTag2->rField.ucMCSThS3SS); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.uciBfTimeOut = %d\n", + prPfmuTag2->rField.uciBfTimeOut); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucReserved2 = %d\n", + prPfmuTag2->rField.ucReserved2); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucReserved3 = %d\n", + prPfmuTag2->rField.ucReserved3); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.ucReserved4 = %d\n", + prPfmuTag2->rField.ucReserved4); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.uciBfDBW = %d\n", + prPfmuTag2->rField.uciBfDBW); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.uciBfNcol = %d\n", + prPfmuTag2->rField.uciBfNcol); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.uciBfNrow = %d\n", + prPfmuTag2->rField.uciBfNrow); + DBGLOG(RFTEST, ERROR, + "prPfmuTag2 : prPfmuTag2->rField.u2Reserved5 = %d\n", + prPfmuTag2->rField.u2Reserved5); + + rTxBfActionInfo.rProfileTagWrite.ucTxBfCategory = + BF_PFMU_TAG_WRITE; + rTxBfActionInfo.rProfileTagWrite.ucPfmuId = profileIdx; + memcpy(&rTxBfActionInfo.rProfileTagWrite.ucBuffer, + prPfmuTag1, sizeof(union PFMU_PROFILE_TAG1)); + memcpy(&rTxBfActionInfo.rProfileTagWrite.ucBuffer[16], + prPfmuTag2, sizeof(union PFMU_PROFILE_TAG2)); + + i4Status = kalIoctl(prGlueInfo, wlanoidTxBfAction, &rTxBfActionInfo, + sizeof(rTxBfActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +int32_t TxBfProfileTagRead(struct net_device *prNetDev, + uint8_t profileIdx, uint8_t fgBFer) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, + "TxBfProfileTagRead : profileIdx = 0x%08x\n", profileIdx); + DBGLOG(RFTEST, ERROR, + "TxBfProfileTagRead : fgBFer = 0x%08x\n", fgBFer); + + rTxBfActionInfo.rProfileTagRead.ucTxBfCategory = + BF_PFMU_TAG_READ; + rTxBfActionInfo.rProfileTagRead.ucProfileIdx = profileIdx; + rTxBfActionInfo.rProfileTagRead.fgBfer = fgBFer; + + i4Status = kalIoctl(prGlueInfo, wlanoidTxBfAction, &rTxBfActionInfo, + sizeof(rTxBfActionInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + return i4Status; +} + +int32_t StaRecCmmUpdate(struct net_device *prNetDev, + uint8_t ucWlanId, uint8_t ucBssId, uint8_t u4Aid, + uint8_t aucMacAddr[MAC_ADDR_LEN] + ) +{ + struct STAREC_COMMON rStaRecCmm; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + int32_t i4Status = 0; + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rStaRecCmm, sizeof(struct STAREC_COMMON)); + /* Tag assignment */ + rStaRecCmm.u2Tag = STA_REC_BASIC; + rStaRecCmm.u2Length = sizeof(struct STAREC_COMMON); + + /* content */ + kalMemCopy(rStaRecCmm.aucPeerMacAddr, aucMacAddr, + MAC_ADDR_LEN); + rStaRecCmm.ucConnectionState = TRUE; + rStaRecCmm.u2AID = u4Aid; + rStaRecCmm.u2Reserve1 = ucWlanId; + + DBGLOG(RFTEST, ERROR, "ucWlanId = 0x%08x\n", ucWlanId); + + i4Status = kalIoctl(prGlueInfo, wlanoidStaRecUpdate, &rStaRecCmm, + sizeof(struct STAREC_COMMON), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +int32_t StaRecBfUpdate(struct net_device *prNetDev, + struct STA_REC_BF_UPD_ARGUMENT rStaRecBfUpdArg, + uint8_t aucMemRow[4], uint8_t aucMemCol[4] + ) +{ + struct CMD_STAREC_BF rStaRecBF; + /* PARAM_CUSTOM_STA_REC_UPD_STRUCT_T rStaRecUpdateInfo = {0}; */ + /* P_STA_RECORD_T prStaRec; */ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + int32_t i4Status = 0; + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rStaRecBF, sizeof(struct CMD_STAREC_BF)); + /* Tag assignment */ + rStaRecBF.u2Tag = STA_REC_BF; + rStaRecBF.u2Length = sizeof(struct CMD_STAREC_BF); + rStaRecBF.ucReserved[0] = rStaRecBfUpdArg.u4BssId; + rStaRecBF.ucReserved[1] = rStaRecBfUpdArg.u4WlanId; + /* content */ + rStaRecBF.rTxBfPfmuInfo.u2PfmuId = rStaRecBfUpdArg.u4PfmuId; + rStaRecBF.rTxBfPfmuInfo.ucTotMemRequire = + rStaRecBfUpdArg.u4TotalMemReq; + rStaRecBF.rTxBfPfmuInfo.ucMemRequire20M = + rStaRecBfUpdArg.u4MemReq20M; + rStaRecBF.rTxBfPfmuInfo.ucMemRow0 = aucMemRow[0]; + rStaRecBF.rTxBfPfmuInfo.ucMemCol0 = aucMemCol[0]; + rStaRecBF.rTxBfPfmuInfo.ucMemRow1 = aucMemRow[1]; + rStaRecBF.rTxBfPfmuInfo.ucMemCol1 = aucMemCol[1]; + rStaRecBF.rTxBfPfmuInfo.ucMemRow2 = aucMemRow[2]; + rStaRecBF.rTxBfPfmuInfo.ucMemCol2 = aucMemCol[2]; + rStaRecBF.rTxBfPfmuInfo.ucMemRow3 = aucMemRow[3]; + rStaRecBF.rTxBfPfmuInfo.ucMemCol3 = aucMemCol[3]; + /* 0 : SU, 1 : MU */ + rStaRecBF.rTxBfPfmuInfo.fgSU_MU = rStaRecBfUpdArg.u4SuMu; + /* 0: iBF, 1: eBF */ + rStaRecBF.rTxBfPfmuInfo.fgETxBfCap = + rStaRecBfUpdArg.u4eTxBfCap; + /* 0: legacy, 1: OFDM, 2: HT, 4: VHT */ + rStaRecBF.rTxBfPfmuInfo.ucSoundingPhy = 1; + rStaRecBF.rTxBfPfmuInfo.ucNdpaRate = + rStaRecBfUpdArg.u4NdpaRate; + rStaRecBF.rTxBfPfmuInfo.ucNdpRate = + rStaRecBfUpdArg.u4NdpRate; + rStaRecBF.rTxBfPfmuInfo.ucReptPollRate = + rStaRecBfUpdArg.u4ReptPollRate; + /* 0: legacy, 1: OFDM, 2: HT, 4: VHT */ + rStaRecBF.rTxBfPfmuInfo.ucTxMode = rStaRecBfUpdArg.u4TxMode; + rStaRecBF.rTxBfPfmuInfo.ucNc = rStaRecBfUpdArg.u4Nc; + rStaRecBF.rTxBfPfmuInfo.ucNr = rStaRecBfUpdArg.u4Nr; + /* 0 : 20M, 1 : 40M, 2 : 80M, 3 : 80 + 80M */ + rStaRecBF.rTxBfPfmuInfo.ucCBW = rStaRecBfUpdArg.u4Bw; + rStaRecBF.rTxBfPfmuInfo.ucSEIdx = rStaRecBfUpdArg.u4SpeIdx; + /* Default setting */ + rStaRecBF.rTxBfPfmuInfo.u2SmartAnt = 0; + rStaRecBF.rTxBfPfmuInfo.uciBfTimeOut = 0; + rStaRecBF.rTxBfPfmuInfo.uciBfDBW = 0; + rStaRecBF.rTxBfPfmuInfo.uciBfNcol = 0; + rStaRecBF.rTxBfPfmuInfo.uciBfNrow = 0; + + i4Status = kalIoctl(prGlueInfo, + wlanoidStaRecBFUpdate, &rStaRecBF, + sizeof(struct CMD_STAREC_BF), FALSE, FALSE, TRUE, + &u4BufLen); + + return i4Status; +} + +int32_t DevInfoUpdate(struct net_device *prNetDev, + uint8_t ucOwnMacIdx, uint8_t fgBand, + uint8_t aucMacAddr[MAC_ADDR_LEN]) +{ + struct CMD_DEVINFO_ACTIVE rDevInfo; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + int32_t i4Status = 0; + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rDevInfo, sizeof(struct CMD_DEVINFO_ACTIVE)); + /* Tag assignment */ + rDevInfo.u2Tag = DEV_INFO_ACTIVE; + rDevInfo.u2Length = sizeof(struct CMD_DEVINFO_ACTIVE); + /* content */ + kalMemCopy(rDevInfo.aucOwnMacAddr, aucMacAddr, + MAC_ADDR_LEN); + rDevInfo.ucActive = TRUE; + rDevInfo.ucBandNum = 0; + rDevInfo.aucReserve[0] = ucOwnMacIdx; + + i4Status = kalIoctl(prGlueInfo, wlanoidDevInfoActive, &rDevInfo, + sizeof(struct CMD_DEVINFO_ACTIVE), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +int32_t BssInfoUpdate(struct net_device *prNetDev, + uint8_t ucOwnMacIdx, uint8_t ucBssIdx, + uint8_t ucBssId[MAC_ADDR_LEN]) +{ + struct BSSINFO_BASIC rBssInfo; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + int32_t i4Status = 0; + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rBssInfo, sizeof(struct BSSINFO_BASIC)); + /* Tag assignment */ + rBssInfo.u2Tag = BSS_INFO_BASIC; + rBssInfo.u2Length = sizeof(struct BSSINFO_BASIC); + /* content */ + kalMemCopy(rBssInfo.aucBSSID, ucBssId, MAC_ADDR_LEN); + rBssInfo.ucBcMcWlanidx = ucBssIdx; + rBssInfo.ucActive = TRUE; + rBssInfo.u4NetworkType = NETWORK_TYPE_AIS; + rBssInfo.u2BcnInterval = 100; + rBssInfo.ucDtimPeriod = 1; + + i4Status = kalIoctl(prGlueInfo, + wlanoidBssInfoBasic, &rBssInfo, + sizeof(struct BSSINFO_BASIC), FALSE, FALSE, TRUE, + &u4BufLen); + + return i4Status; +} + +int32_t TxBfProfileDataRead(struct net_device *prNetDev, + uint8_t profileIdx, uint8_t fgBFer, + uint8_t ucSubCarrIdxMsb, uint8_t ucSubCarrIdxLsb) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataRead : ucPfmuIdx = 0x%08x\n", profileIdx); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataRead : fgBFer = 0x%08x\n", fgBFer); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataRead : ucSubCarrIdxMsb = 0x%08x\n", + ucSubCarrIdxMsb); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataRead : ucSubCarrIdxLsb = 0x%08x\n", + ucSubCarrIdxLsb); + + rTxBfActionInfo.rProfileDataRead.ucTxBfCategory = + BF_PROFILE_READ; + rTxBfActionInfo.rProfileDataRead.ucPfmuIdx = profileIdx; + rTxBfActionInfo.rProfileDataRead.fgBFer = fgBFer; + rTxBfActionInfo.rProfileDataRead.ucSubCarrIdxMsb = + ucSubCarrIdxMsb; + rTxBfActionInfo.rProfileDataRead.ucSubCarrIdxLsb = + ucSubCarrIdxLsb; + + i4Status = kalIoctl(prGlueInfo, wlanoidTxBfAction, &rTxBfActionInfo, + sizeof(rTxBfActionInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + return i4Status; +} + +int32_t TxBfProfileDataWrite(struct net_device *prNetDev, + uint8_t profileIdx, + uint16_t u2SubCarrIdx, uint16_t au2Phi[6], + uint8_t aucPsi[6], uint8_t aucDSnr[4] + ) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : ucPfmuIdx = 0x%08x\n", profileIdx); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : u2SubCarrIdx = 0x%08x\n", + u2SubCarrIdx); + + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : au2Phi[0] = 0x%08x\n", au2Phi[0]); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : au2Phi[1] = 0x%08x\n", au2Phi[1]); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : au2Phi[2] = 0x%08x\n", au2Phi[2]); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : au2Phi[3] = 0x%08x\n", au2Phi[3]); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : au2Phi[4] = 0x%08x\n", au2Phi[4]); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : au2Phi[5] = 0x%08x\n", au2Phi[5]); + + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : aucPsi[0] = 0x%08x\n", aucPsi[0]); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : aucPsi[1] = 0x%08x\n", aucPsi[1]); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : aucPsi[2] = 0x%08x\n", aucPsi[2]); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : aucPsi[3] = 0x%08x\n", aucPsi[3]); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : aucPsi[4] = 0x%08x\n", aucPsi[4]); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : aucPsi[5] = 0x%08x\n", aucPsi[5]); + + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : aucDSnr[0] = 0x%x\n", aucDSnr[0]); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : aucDSnr[1] = 0x%x\n", aucDSnr[1]); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : aucDSnr[2] = 0x%x\n", aucDSnr[2]); + DBGLOG(RFTEST, ERROR, + "TxBfProfileDataWrite : aucDSnr[3] = 0x%x\n", aucDSnr[3]); + + rTxBfActionInfo.rProfileDataWrite.ucTxBfCategory = + BF_PROFILE_WRITE; + rTxBfActionInfo.rProfileDataWrite.ucPfmuIdx = profileIdx; + rTxBfActionInfo.rProfileDataWrite.u2SubCarrIdxLsb = + u2SubCarrIdx; + rTxBfActionInfo.rProfileDataWrite.u2SubCarrIdxMsb = + u2SubCarrIdx >> 8; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2Phi11 + = au2Phi[0]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2Phi21 + = au2Phi[1]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2Phi31 + = au2Phi[2]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2Phi22 + = au2Phi[3]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2Phi32 + = au2Phi[4]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2Phi33 + = au2Phi[5]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.ucPsi21 + = aucPsi[0]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.ucPsi31 + = aucPsi[1]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.ucPsi41 + = aucPsi[2]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.ucPsi32 + = aucPsi[3]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.ucPsi42 + = aucPsi[4]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.ucPsi43 + = aucPsi[5]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2dSNR00 + = aucDSnr[0]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2dSNR01 + = aucDSnr[1]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2dSNR02 + = aucDSnr[2]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2dSNR03 + = aucDSnr[3]; + + i4Status = kalIoctl(prGlueInfo, wlanoidTxBfAction, &rTxBfActionInfo, + sizeof(rTxBfActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +int32_t TxBfProfilePnRead(struct net_device *prNetDev, + uint8_t profileIdx) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnRead : ucPfmuIdx = 0x%08x\n", profileIdx); + + rTxBfActionInfo.rProfilePnRead.ucTxBfCategory = BF_PN_READ; + rTxBfActionInfo.rProfilePnRead.ucPfmuIdx = profileIdx; + + i4Status = kalIoctl(prGlueInfo, wlanoidTxBfAction, &rTxBfActionInfo, + sizeof(rTxBfActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +int32_t TxBfProfilePnWrite(struct net_device *prNetDev, + uint8_t profileIdx, uint16_t u2bw, uint16_t au2XSTS[12]) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : ucPfmuIdx = 0x%08x\n", profileIdx); + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : u2bw = 0x%08x\n", u2bw); + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : au2XSTS[0] = 0x%08x\n", au2XSTS[0]); + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : au2XSTS[1] = 0x%08x\n", au2XSTS[1]); + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : au2XSTS[2] = 0x%08x\n", au2XSTS[2]); + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : au2XSTS[3] = 0x%08x\n", au2XSTS[3]); + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : au2XSTS[4] = 0x%08x\n", au2XSTS[4]); + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : au2XSTS[5] = 0x%08x\n", au2XSTS[5]); + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : au2XSTS[6] = 0x%08x\n", au2XSTS[6]); + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : au2XSTS[7] = 0x%08x\n", au2XSTS[7]); + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : au2XSTS[8] = 0x%08x\n", au2XSTS[8]); + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : au2XSTS[9] = 0x%08x\n", au2XSTS[9]); + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : au2XSTS[10] = 0x%08x\n", au2XSTS[10]); + DBGLOG(RFTEST, ERROR, + "TxBfProfilePnWrite : au2XSTS[11] = 0x%08x\n", au2XSTS[11]); + + rTxBfActionInfo.rProfilePnWrite.ucTxBfCategory = + BF_PN_WRITE; + rTxBfActionInfo.rProfilePnWrite.ucPfmuIdx = profileIdx; + rTxBfActionInfo.rProfilePnWrite.u2bw = u2bw; + memcpy(&rTxBfActionInfo.rProfilePnWrite.ucBuf[0], &au2XSTS[0], + sizeof(uint16_t) * 12); + + i4Status = kalIoctl(prGlueInfo, wlanoidTxBfAction, &rTxBfActionInfo, + sizeof(rTxBfActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +int32_t TxBfSounding(struct net_device *prNetDev, + uint8_t ucSuMu, /* 0/1/2/3 */ + uint8_t ucNumSta, /* 00~04 */ + uint8_t ucSndInterval, /* 00~FF */ + uint8_t ucWLan0, /* 00~7F */ + uint8_t ucWLan1, /* 00~7F */ + uint8_t ucWLan2, /* 00~7F */ + + uint8_t ucWLan3 /* 00~7F */ + ) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, "TxBfSounding : ucSuMu = 0x%08x\n", + ucSuMu); + DBGLOG(RFTEST, ERROR, "TxBfSounding : ucNumSta = 0x%08x\n", + ucNumSta); + DBGLOG(RFTEST, ERROR, + "TxBfSounding : ucSndInterval = 0x%08x\n", ucSndInterval); + DBGLOG(RFTEST, ERROR, "TxBfSounding : ucWLan0 = 0x%08x\n", + ucWLan0); + DBGLOG(RFTEST, ERROR, "TxBfSounding : ucWLan1 = 0x%08x\n", + ucWLan1); + DBGLOG(RFTEST, ERROR, "TxBfSounding : ucWLan2 = 0x%08x\n", + ucWLan2); + DBGLOG(RFTEST, ERROR, "TxBfSounding : ucWLan3 = 0x%08x\n", + ucWLan3); + + switch (ucSuMu) { + case MU_SOUNDING: + + case MU_PERIODIC_SOUNDING: + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding + .rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucCmdCategoryID = + BF_SOUNDING_ON; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding + .rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucSuMuSndMode = ucSuMu; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding + .rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucStaNum = ucNumSta; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding + .rExtCmdExtBfMuSndPeriodicTriggerCtrl.u4SoundingInterval = + ucSndInterval; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding + .rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucWlanId[0] = ucWLan0; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding + .rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucWlanId[1] = ucWLan1; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding + .rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucWlanId[2] = ucWLan2; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding + .rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucWlanId[3] = ucWLan3; + break; + + case SU_SOUNDING: + case SU_PERIODIC_SOUNDING: + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding + .rExtCmdExtBfSndPeriodicTriggerCtrl.ucCmdCategoryID = + BF_SOUNDING_ON; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding + .rExtCmdExtBfSndPeriodicTriggerCtrl.ucSuMuSndMode = ucSuMu; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding + .rExtCmdExtBfSndPeriodicTriggerCtrl.u4SoundingInterval = + ucSndInterval; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding + .rExtCmdExtBfSndPeriodicTriggerCtrl.ucWlanIdx = ucWLan0; + break; + default: + break; + } + + i4Status = kalIoctl(prGlueInfo, wlanoidTxBfAction, &rTxBfActionInfo, + sizeof(rTxBfActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +int32_t TxBfSoundingStop(struct net_device *prNetDev) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, "TxBfSoundingStop\n"); + + rTxBfActionInfo.rTxBfSoundingStop.ucTxBfCategory = + BF_SOUNDING_OFF; + rTxBfActionInfo.rTxBfSoundingStop.ucSndgStop = 1; + + i4Status = kalIoctl(prGlueInfo, wlanoidTxBfAction, &rTxBfActionInfo, + sizeof(rTxBfActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +int32_t TxBfTxApply(struct net_device *prNetDev, + uint8_t ucWlanId, uint8_t fgETxBf, uint8_t fgITxBf, + uint8_t fgMuTxBf) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, + "TxBfTxApply : ucWlanId = 0x%08x, fgETxBf = 0x%08x,fgITxBf = 0x%08x,fgMuTxBf = 0x%08x\n", + ucWlanId, fgETxBf, fgITxBf, fgMuTxBf); + + rTxBfActionInfo.rTxBfTxApply.ucTxBfCategory = + BF_DATA_PACKET_APPLY; + rTxBfActionInfo.rTxBfTxApply.ucWlanId = ucWlanId; + rTxBfActionInfo.rTxBfTxApply.fgETxBf = fgETxBf; + rTxBfActionInfo.rTxBfTxApply.fgITxBf = fgITxBf; + rTxBfActionInfo.rTxBfTxApply.fgMuTxBf = fgMuTxBf; + + i4Status = kalIoctl(prGlueInfo, wlanoidTxBfAction, &rTxBfActionInfo, + sizeof(rTxBfActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +int32_t TxBfPfmuMemAlloc(struct net_device *prNetDev, + uint8_t ucSuMuMode, uint8_t ucWlanIdx) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, + "TxBfPfmuMemAlloc : ucSuMuMode = 0x%08x, ucWlanIdx = 0x%08x\n", + ucSuMuMode, ucWlanIdx); + + rTxBfActionInfo.rTxBfPfmuMemAlloc.ucTxBfCategory = + BF_PFMU_MEM_ALLOCATE; + rTxBfActionInfo.rTxBfPfmuMemAlloc.ucSuMuMode = ucSuMuMode; + rTxBfActionInfo.rTxBfPfmuMemAlloc.ucWlanIdx = ucWlanIdx; + + i4Status = kalIoctl(prGlueInfo, wlanoidTxBfAction, &rTxBfActionInfo, + sizeof(rTxBfActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +int32_t TxBfPfmuMemRelease(struct net_device *prNetDev, + uint8_t ucWlanId) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, + "TxBfPfmuMemRelease : ucWlanId = 0x%08x\n", ucWlanId); + + rTxBfActionInfo.rTxBfPfmuMemRls.ucTxBfCategory = + BF_PFMU_MEM_RELEASE; + rTxBfActionInfo.rTxBfPfmuMemRls.ucWlanId = ucWlanId; + + i4Status = kalIoctl(prGlueInfo, wlanoidTxBfAction, &rTxBfActionInfo, + sizeof(rTxBfActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +int32_t TxBfBssInfoUpdate(struct net_device *prNetDev, + uint8_t ucOwnMacIdx, uint8_t ucBssIdx, + uint8_t ucBssId[MAC_ADDR_LEN]) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + /* UINT_32 u4BufLen = 0; */ + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + struct BSS_INFO *prBssInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, + "TxBfBssInfoUpdate : ucOwnMacIdx = 0x%08x\n", ucOwnMacIdx); + DBGLOG(RFTEST, ERROR, + "TxBfBssInfoUpdate : ucBssIdx = 0x%08x\n", ucBssIdx); + DBGLOG(RFTEST, ERROR, + "TxBfBssInfoUpdate : ucBssId[0] = 0x%08x\n", ucBssId[0]); + DBGLOG(RFTEST, ERROR, + "TxBfBssInfoUpdate : ucBssId[1] = 0x%08x\n", ucBssId[1]); + DBGLOG(RFTEST, ERROR, + "TxBfBssInfoUpdate : ucBssId[2] = 0x%08x\n", ucBssId[2]); + DBGLOG(RFTEST, ERROR, + "TxBfBssInfoUpdate : ucBssId[3] = 0x%08x\n", ucBssId[3]); + DBGLOG(RFTEST, ERROR, + "TxBfBssInfoUpdate : ucBssId[4] = 0x%08x\n", ucBssId[4]); + DBGLOG(RFTEST, ERROR, + "TxBfBssInfoUpdate : ucBssId[5] = 0x%08x\n", ucBssId[5]); + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + if (!prBssInfo) + return WLAN_STATUS_FAILURE; + prBssInfo->ucOwnMacIndex = ucOwnMacIdx; + kalMemCopy(prBssInfo->aucBSSID, ucBssId, MAC_ADDR_LEN); + + nicUpdateBss(prAdapter, prBssInfo->ucBssIndex); + + return i4Status; +} + +/* iwpriv ra0 set assoc=[mac:hh:hh:hh:hh:hh:hh]-[wtbl:dd]- + * [ownmac:dd]-[type:xx]-[mode:mmm]-[bw:dd]-[nss:ss]-[maxrate:kkk_dd] + */ +int32_t TxBfManualAssoc(struct net_device *prNetDev, + uint8_t aucMac[MAC_ADDR_LEN], + uint8_t ucType, /* no use */ + uint8_t ucWtbl, + uint8_t ucOwnmac, + uint8_t ucMode, + uint8_t ucBw, + uint8_t ucNss, uint8_t ucPfmuId, uint8_t ucMarate, + uint8_t ucSpeIdx, uint8_t ucRca2, uint8_t ucRv) +{ + struct CMD_MANUAL_ASSOC_STRUCT rManualAssoc; + /* P_STA_RECORD_T prStaRec; */ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + int32_t i4Status = 0; + /* uint8_t ucNsts; + * uint32_t i; + */ + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rManualAssoc, + sizeof(struct CMD_MANUAL_ASSOC_STRUCT)); + /* Tag assignment */ + rManualAssoc.u2Tag = STA_REC_MAUNAL_ASSOC; + rManualAssoc.u2Length = sizeof(struct + CMD_MANUAL_ASSOC_STRUCT); + /* content */ + kalMemCopy(rManualAssoc.aucMac, aucMac, MAC_ADDR_LEN); + rManualAssoc.ucType = ucType; + rManualAssoc.ucWtbl = ucWtbl; + rManualAssoc.ucOwnmac = ucOwnmac; + rManualAssoc.ucMode = ucMode; + rManualAssoc.ucBw = ucBw; + rManualAssoc.ucNss = ucNss; + rManualAssoc.ucPfmuId = ucPfmuId; + rManualAssoc.ucMarate = ucMarate; + rManualAssoc.ucSpeIdx = ucSpeIdx; + rManualAssoc.ucaid = ucRca2; + +#if 0 + switch (ucMode) { + case 0: /* abggnanac */ + prStaRec->ucDesiredPhyTypeSet = + aucPhyCfg2PhyTypeSet[PHY_TYPE_SET_802_11ABGNAC]; + break; + case 1: /* bggnan */ + prStaRec->ucDesiredPhyTypeSet = + aucPhyCfg2PhyTypeSet[PHY_TYPE_SET_802_11ABGN]; + break; + case 2: /* aanac */ + prStaRec->ucDesiredPhyTypeSet = + aucPhyCfg2PhyTypeSet[PHY_TYPE_SET_802_11ANAC]; + break; + default: + prStaRec->ucDesiredPhyTypeSet = + aucPhyCfg2PhyTypeSet[PHY_TYPE_SET_802_11ABGNAC]; + break; + } + + prStaRec->rTxBfPfmuStaInfo.u2PfmuId = ucPfmuId; + + memcpy(prStaRec->aucMacAddr, aucMac, MAC_ADDR_LEN); + + i4Status = kalIoctl(prGlueInfo, wlanoidStaRecUpdate, &rStaRecUpdateInfo, + sizeof(struct PARAM_CUSTOM_STA_REC_UPD_STRUCT), + FALSE, FALSE, TRUE, &u4BufLen); +#endif + + i4Status = kalIoctl(prGlueInfo, wlanoidManualAssoc, &rManualAssoc, + sizeof(struct CMD_MANUAL_ASSOC_STRUCT), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +#if CFG_SUPPORT_TX_BF_FPGA +int32_t TxBfPseudoTagUpdate(struct net_device *prNetDev, + uint8_t ucLm, uint8_t ucNr, + uint8_t ucNc, uint8_t ucBw, uint8_t ucCodeBook, + uint8_t ucGroup) +{ + int32_t i4Status = 0; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4BufLen = 0; + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, ERROR, + "TxBfPseudoTagUpdate : ucLm = 0x%08x, ucNr = 0x%08x, ucNc = 0x%08x, ucBw = 0x%08x, ucCodeBook = 0x%08x, ucGroup = 0x%08x\n", + ucLm, ucNr, ucNc, ucBw, ucCodeBook, ucGroup); + + rTxBfActionInfo.rTxBfProfileSwTagWrite.ucTxBfCategory = + BF_PFMU_SW_TAG_WRITE; + rTxBfActionInfo.rTxBfProfileSwTagWrite.ucLm = ucLm; + rTxBfActionInfo.rTxBfProfileSwTagWrite.ucNr = ucNr; + rTxBfActionInfo.rTxBfProfileSwTagWrite.ucNc = ucNc; + rTxBfActionInfo.rTxBfProfileSwTagWrite.ucBw = ucBw; + rTxBfActionInfo.rTxBfProfileSwTagWrite.ucCodebook = + ucCodeBook; + rTxBfActionInfo.rTxBfProfileSwTagWrite.ucgroup = ucGroup; + + i4Status = kalIoctl(prGlueInfo, wlanoidTxBfAction, &rTxBfActionInfo, + sizeof(rTxBfActionInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} +#endif + +#endif +#endif /*CFG_SUPPORT_QA_TOOL */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_init.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_init.c new file mode 100644 index 0000000000000..03e0332968840 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_init.c @@ -0,0 +1,4277 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux + * /gl_init.c#11 + */ + +/*! \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. + */ + + +/******************************************************************************* + * C O M P I L E 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" +#if CFG_SUPPORT_AGPS_ASSIST +#include "gl_kal.h" +#endif +#include "gl_vendor.h" +#if CFG_THERMAL_API_SUPPORT +#include "mtk_ts_wmt.h" +#endif + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +/* #define MAX_IOREQ_NUM 10 */ +struct semaphore g_halt_sem; +int g_u4HaltFlag; + +struct wireless_dev *gprWdev; +#if CFG_THERMAL_API_SUPPORT +u_int8_t g_fgIsWifiEnabled = FALSE; +static int mtk_wcn_temp_query_ctrl(void); +#endif + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +/* Tasklet mechanism is like buttom-half in Linux. We just want to + * send a signal to OS for interrupt defer processing. All resources + * are NOT allowed reentry, so txPacket, ISR-DPC and ioctl must avoid preempty. + */ +struct WLANDEV_INFO { + struct net_device *prDev; +}; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +MODULE_AUTHOR(NIC_AUTHOR); +MODULE_DESCRIPTION(NIC_DESC); +MODULE_SUPPORTED_DEVICE(NIC_NAME); + +/* MODULE_LICENSE("MTK Propietary"); */ +MODULE_LICENSE("Dual BSD/GPL"); + +#ifdef CFG_DRIVER_INF_NAME_CHANGE +char *gprifnamesta = ""; +char *gprifnamep2p = ""; +char *gprifnameap = ""; +module_param_named(sta, gprifnamesta, charp, 0000); +module_param_named(p2p, gprifnamep2p, charp, 0000); +module_param_named(ap, gprifnameap, charp, 0000); +#endif /* CFG_DRIVER_INF_NAME_CHANGE */ + +/* NIC interface name */ +#define NIC_INF_NAME "wlan%d" + +#ifdef CFG_DRIVER_INF_NAME_CHANGE +/* Kernel IFNAMESIZ is 16, we use 5 in case some protocol might auto gen + * interface name, + */ +/* in that case, the interface name might have risk of over kernel's IFNAMESIZ + */ +#define CUSTOM_IFNAMESIZ 5 +#endif /* CFG_DRIVER_INF_NAME_CHANGE */ + +#if CFG_SUPPORT_SNIFFER +#define NIC_MONITOR_INF_NAME "radiotap%d" +#endif + +uint8_t aucDebugModule[DBG_MODULE_NUM]; +uint32_t au4LogLevel[ENUM_WIFI_LOG_MODULE_NUM] = {ENUM_WIFI_LOG_LEVEL_DEFAULT}; + +/* 4 2007/06/26, mikewu, now we don't use this, we just fix the number of wlan + * device to 1 + */ +static struct WLANDEV_INFO + arWlanDevInfo[CFG_MAX_WLAN_DEVICES] = { {0} }; + +static uint32_t +u4WlanDevNum; /* How many NICs coexist now */ + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +u_int8_t g_fgIsCalDataBackuped = FALSE; +#endif + +/* 20150205 added work queue for sched_scan to avoid cfg80211 stop schedule scan + * dead loack + */ +struct delayed_work sched_workq; + +#define CFG_EEPRM_FILENAME "EEPROM" +#define FILE_NAME_MAX 64 + +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1) +static uint8_t *apucEepromName[] = { + (uint8_t *) CFG_EEPRM_FILENAME "_MT", + NULL +}; +#endif + +int CFG80211_Suspend(struct wiphy *wiphy, + struct cfg80211_wowlan *wow) +{ + DBGLOG(INIT, INFO, "CFG80211 suspend CB\n"); + + return 0; +} + +int CFG80211_Resume(struct wiphy *wiphy) +{ + DBGLOG(INIT, INFO, "CFG80211 resume CB\n"); + + return 0; +} + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +#define CHAN2G(_channel, _freq, _flags) \ +{ \ + .band = KAL_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 = KAL_BAND_5GHZ, \ + .center_freq = \ + (((_channel >= 182) && (_channel <= 196)) ? \ + (4000 + (5 * (_channel))) : (5000 + (5 * (_channel)))), \ + .hw_value = (_channel), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} +static struct ieee80211_channel mtk_5ghz_channels[] = { + CHAN5G(36, 0), CHAN5G(40, 0), + CHAN5G(44, 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(144, 0), + CHAN5G(149, 0), CHAN5G(153, 0), + CHAN5G(157, 0), CHAN5G(161, 0), + CHAN5G(165, 0), + +}; + +#define RATETAB_ENT(_rate, _rateid, _flags) \ +{ \ + .bitrate = (_rate), \ + .hw_value = (_rateid), \ + .flags = (_flags), \ +} + +/* for cfg80211 - rate table */ +static struct ieee80211_rate mtk_rates[] = { + RATETAB_ENT(10, 0x1000, 0), + RATETAB_ENT(20, 0x1001, 0), + RATETAB_ENT(55, 0x1002, 0), + RATETAB_ENT(110, 0x1003, 0), /* 802.11b */ + RATETAB_ENT(60, 0x2000, 0), + RATETAB_ENT(90, 0x2001, 0), + RATETAB_ENT(120, 0x2002, 0), + RATETAB_ENT(180, 0x2003, 0), + RATETAB_ENT(240, 0x2004, 0), + RATETAB_ENT(360, 0x2005, 0), + RATETAB_ENT(480, 0x2006, 0), + RATETAB_ENT(540, 0x2007, 0), /* 802.11a/g */ +}; + +#define mtk_a_rates (mtk_rates + 4) +#define mtk_a_rates_size (ARRAY_SIZE(mtk_rates) - 4) +#define mtk_g_rates (mtk_rates + 0) +#define mtk_g_rates_size (ARRAY_SIZE(mtk_rates) - 0) + +#define WLAN_MCS_INFO \ +{ \ + .rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \ + .rx_highest = 0, \ + .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ +} + +#define WLAN_VHT_MCS_INFO \ +{ \ + .rx_mcs_map = 0xFFFA, \ + .rx_highest = cpu_to_le16(867), \ + .tx_mcs_map = 0xFFFA, \ + .tx_highest = cpu_to_le16(867), \ +} + + +#define WLAN_HT_CAP \ +{ \ + .ht_supported = true, \ + .cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 \ + | IEEE80211_HT_CAP_SM_PS \ + | IEEE80211_HT_CAP_GRN_FLD \ + | IEEE80211_HT_CAP_SGI_20 \ + | IEEE80211_HT_CAP_SGI_40, \ + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, \ + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE, \ + .mcs = WLAN_MCS_INFO, \ +} + +#define WLAN_VHT_CAP \ +{ \ + .vht_supported = true, \ + .cap = IEEE80211_VHT_CAP_RXLDPC \ + | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK \ + | IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 \ + | IEEE80211_VHT_CAP_RXLDPC \ + | IEEE80211_VHT_CAP_SHORT_GI_80 \ + | IEEE80211_VHT_CAP_TXSTBC \ + | IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE \ + | IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE, \ + .vht_mcs = WLAN_VHT_MCS_INFO, \ +} + +/* public for both Legacy Wi-Fi / P2P access */ +struct ieee80211_supported_band mtk_band_2ghz = { + .band = KAL_BAND_2GHZ, + .channels = mtk_2ghz_channels, + .n_channels = ARRAY_SIZE(mtk_2ghz_channels), + .bitrates = mtk_g_rates, + .n_bitrates = mtk_g_rates_size, + .ht_cap = WLAN_HT_CAP, +}; + +/* public for both Legacy Wi-Fi / P2P access */ +struct ieee80211_supported_band mtk_band_5ghz = { + .band = KAL_BAND_5GHZ, + .channels = mtk_5ghz_channels, + .n_channels = ARRAY_SIZE(mtk_5ghz_channels), + .bitrates = mtk_a_rates, + .n_bitrates = mtk_a_rates_size, + .ht_cap = WLAN_HT_CAP, + .vht_cap = WLAN_VHT_CAP, +}; + +const uint32_t 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, + WLAN_CIPHER_SUITE_NO_GROUP_ADDR +}; + +#if (CFG_ENABLE_UNIFY_WIPHY == 0) +static struct cfg80211_ops mtk_wlan_ops = { + .suspend = mtk_cfg80211_suspend, + .resume = mtk_cfg80211_resume, + .change_virtual_intf = mtk_cfg80211_change_iface, + .add_key = mtk_cfg80211_add_key, + .get_key = mtk_cfg80211_get_key, + .del_key = mtk_cfg80211_del_key, + .set_default_key = mtk_cfg80211_set_default_key, + .get_station = mtk_cfg80211_get_station, +#if CFG_SUPPORT_TDLS + .change_station = mtk_cfg80211_change_station, + .add_station = mtk_cfg80211_add_station, + .del_station = mtk_cfg80211_del_station, +#endif + .scan = mtk_cfg80211_scan, +#if KERNEL_VERSION(4, 5, 0) <= CFG80211_VERSION_CODE + .abort_scan = mtk_cfg80211_abort_scan, +#endif + .connect = mtk_cfg80211_connect, +#if CFG_SUPPORT_CFG80211_AUTH + .deauth = mtk_cfg80211_deauth, +#endif + .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, +#if CONFIG_SUPPORT_GTK_REKEY + .set_rekey_data = mtk_cfg80211_set_rekey_data, +#endif +#if CFG_SUPPORT_CFG80211_AUTH + .auth = mtk_cfg80211_auth, +#endif + .assoc = mtk_cfg80211_assoc, + + /* Action Frame TX/RX */ + .remain_on_channel = mtk_cfg80211_remain_on_channel, + .cancel_remain_on_channel = mtk_cfg80211_cancel_remain_on_channel, + .mgmt_tx = mtk_cfg80211_mgmt_tx, + /* .mgmt_tx_cancel_wait = mtk_cfg80211_mgmt_tx_cancel_wait, */ + .mgmt_frame_register = mtk_cfg80211_mgmt_frame_register, + +#ifdef CONFIG_NL80211_TESTMODE + .testmode_cmd = mtk_cfg80211_testmode_cmd, +#endif +#if CFG_SUPPORT_SCHED_SCAN + .sched_scan_start = mtk_cfg80211_sched_scan_start, + .sched_scan_stop = mtk_cfg80211_sched_scan_stop, +#endif /* CFG_SUPPORT_SCHED_SCAN */ +#if CFG_SUPPORT_TDLS + .tdls_oper = mtk_cfg80211_tdls_oper, + .tdls_mgmt = mtk_cfg80211_tdls_mgmt, +#endif + .update_ft_ies = mtk_cfg80211_update_ft_ies, +}; +#else /* CFG_ENABLE_UNIFY_WIPHY */ +static struct cfg80211_ops mtk_cfg_ops = { + .add_virtual_intf = mtk_cfg_add_iface, + .del_virtual_intf = mtk_cfg_del_iface, + .change_virtual_intf = mtk_cfg_change_iface, + .add_key = mtk_cfg_add_key, + .get_key = mtk_cfg_get_key, + .del_key = mtk_cfg_del_key, + .set_default_mgmt_key = mtk_cfg_set_default_mgmt_key, + .set_default_key = mtk_cfg_set_default_key, + .get_station = mtk_cfg_get_station, +#if CFG_SUPPORT_TDLS + .change_station = mtk_cfg_change_station, + .add_station = mtk_cfg_add_station, + .tdls_oper = mtk_cfg_tdls_oper, + .tdls_mgmt = mtk_cfg_tdls_mgmt, +#endif + .del_station = mtk_cfg_del_station, /* AP/P2P use this function */ + .scan = mtk_cfg_scan, +#if KERNEL_VERSION(4, 5, 0) <= CFG80211_VERSION_CODE + .abort_scan = mtk_cfg_abort_scan, +#endif +#if CFG_SUPPORT_SCHED_SCAN + .sched_scan_start = mtk_cfg_sched_scan_start, + .sched_scan_stop = mtk_cfg_sched_scan_stop, +#endif /* CFG_SUPPORT_SCHED_SCAN */ + + .connect = mtk_cfg_connect, +#if CFG_SUPPORT_CFG80211_AUTH + .deauth = mtk_cfg_deauth, +#endif + .disconnect = mtk_cfg_disconnect, + .join_ibss = mtk_cfg_join_ibss, + .leave_ibss = mtk_cfg_leave_ibss, + .set_power_mgmt = mtk_cfg_set_power_mgmt, + .set_pmksa = mtk_cfg_set_pmksa, + .del_pmksa = mtk_cfg_del_pmksa, + .flush_pmksa = mtk_cfg_flush_pmksa, +#if CONFIG_SUPPORT_GTK_REKEY + .set_rekey_data = mtk_cfg_set_rekey_data, +#endif + .suspend = mtk_cfg_suspend, + .resume = mtk_cfg_resume, +#if CFG_SUPPORT_CFG80211_AUTH + .auth = mtk_cfg80211_auth, +#endif + .assoc = mtk_cfg_assoc, + + /* Action Frame TX/RX */ + .remain_on_channel = mtk_cfg_remain_on_channel, + .cancel_remain_on_channel = mtk_cfg_cancel_remain_on_channel, + .mgmt_tx = mtk_cfg_mgmt_tx, + /* .mgmt_tx_cancel_wait = mtk_cfg80211_mgmt_tx_cancel_wait, */ + .mgmt_frame_register = mtk_cfg_mgmt_frame_register, + +#ifdef CONFIG_NL80211_TESTMODE + .testmode_cmd = mtk_cfg_testmode_cmd, +#endif + +#if (CFG_SUPPORT_DFS_MASTER == 1) + .start_radar_detection = mtk_cfg_start_radar_detection, +#if KERNEL_VERSION(3, 13, 0) <= CFG80211_VERSION_CODE + .channel_switch = mtk_cfg_channel_switch, +#endif +#endif + +#if (CFG_ENABLE_WIFI_DIRECT_CFG_80211 != 0) + .change_bss = mtk_cfg_change_bss, + .mgmt_tx_cancel_wait = mtk_cfg_mgmt_tx_cancel_wait, + .deauth = mtk_cfg_deauth, + .disassoc = mtk_cfg_disassoc, + .start_ap = mtk_cfg_start_ap, + .change_beacon = mtk_cfg_change_beacon, + .stop_ap = mtk_cfg_stop_ap, + .set_wiphy_params = mtk_cfg_set_wiphy_params, + .set_bitrate_mask = mtk_cfg_set_bitrate_mask, + .set_tx_power = mtk_cfg_set_txpower, + .get_tx_power = mtk_cfg_get_txpower, +#endif + .update_ft_ies = mtk_cfg80211_update_ft_ies, +}; +#endif /* CFG_ENABLE_UNIFY_WIPHY */ + +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE + +static const struct wiphy_vendor_command + mtk_wlan_vendor_ops[] = { + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_GET_CHANNEL_LIST + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_channel_list + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_SET_COUNTRY_CODE + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_country_code + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV + | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_scan_mac_oui + }, + { + { + .vendor_id = OUI_QCA, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_band + }, + { + { + .vendor_id = OUI_QCA, + .subcmd = WIFI_SUBCMD_SET_ROAMING + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_roaming_policy + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_GET_ROAMING_CAPABILITIES + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_roaming_capabilities + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_CONFIG_ROAMING + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_config_roaming + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_ENABLE_ROAMING + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_enable_roaming + }, + /* RTT */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = RTT_SUBCMD_GETCAPABILITY + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_rtt_capabilities + }, + /* Link Layer Statistics */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = LSTATS_SUBCMD_GET_INFO + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_llstats_get_info + }, + /* RSSI Monitoring */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_SET_RSSI_MONITOR + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_rssi_monitoring + }, + /* Packet Keep Alive */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_OFFLOAD_START_MKEEP_ALIVE + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_packet_keep_alive_start + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_OFFLOAD_STOP_MKEEP_ALIVE + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_packet_keep_alive_stop + }, + /* Get Driver Version or Firmware Version */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = LOGGER_GET_VER + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_version + }, + /* Get Supported Feature Set */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_GET_FEATURE_SET + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_supported_feature_set + }, + /* Set Tx Power Scenario */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_SELECT_TX_POWER_SCENARIO + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_tx_power_scenario + }, +#if CFG_SUPPORT_P2P_PREFERRED_FREQ_LIST + /* P2P get preferred freq list */ + { + { + .vendor_id = OUI_QCA, + .subcmd = NL80211_VENDOR_SUBCMD_GET_PREFER_FREQ_LIST + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV + | WIPHY_VENDOR_CMD_NEED_NETDEV + | WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = mtk_cfg80211_vendor_get_preferred_freq_list + }, +#endif /* CFG_SUPPORT_P2P_PREFERRED_FREQ_LIST */ +}; + +static const struct nl80211_vendor_cmd_info + mtk_wlan_vendor_events[] = { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_HOTLIST_RESULTS_FOUND + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_SCAN_RESULTS_AVAILABLE + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_FULL_SCAN_RESULTS + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = RTT_EVENT_COMPLETE + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_COMPLETE_SCAN + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_HOTLIST_RESULTS_LOST + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_EVENT_RSSI_MONITOR + }, +#if CFG_SUPPORT_MAGIC_PKT_VENDOR_EVENT + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_EVENT_MAGIC_PACKET_RECEIVED + } +#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_ais_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { + [NL80211_IFTYPE_ADHOC] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) + }, + [NL80211_IFTYPE_STATION] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_BEACON >> 4) + }, + [NL80211_IFTYPE_AP] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_ACTION >> 4) + }, + [NL80211_IFTYPE_AP_VLAN] = { + /* copy AP */ + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) | + BIT(IEEE80211_STYPE_ACTION >> 4) + }, + [NL80211_IFTYPE_P2P_CLIENT] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + }, + [NL80211_IFTYPE_P2P_GO] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_ACTION >> 4) + } +}; + +#ifdef CONFIG_PM +static const struct wiphy_wowlan_support mtk_wlan_wowlan_support = { + .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT | + WIPHY_WOWLAN_ANY, +}; +#endif + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! + * \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; +} +#endif + +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE +u16 wlanSelectQueue(struct net_device *dev, + struct sk_buff *skb, + struct net_device *sb_dev, select_queue_fallback_t fallback) +{ + return mtk_wlan_ndev_select_queue(skb); +} +#elif KERNEL_VERSION(3, 14, 0) <= LINUX_VERSION_CODE +u16 wlanSelectQueue(struct net_device *dev, + struct sk_buff *skb, + void *accel_priv, select_queue_fallback_t fallback) +{ + return mtk_wlan_ndev_select_queue(skb); +} +#elif KERNEL_VERSION(3, 13, 0) <= LINUX_VERSION_CODE +u16 wlanSelectQueue(struct net_device *dev, + struct sk_buff *skb, + void *accel_priv) +{ + return mtk_wlan_ndev_select_queue(skb); +} +#else +u16 wlanSelectQueue(struct net_device *dev, + struct sk_buff *skb) +{ + return mtk_wlan_ndev_select_queue(skb); +} +#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 struct GLUE_INFO *prGlueInfo, + OUT struct REG_INFO *prRegInfo) +{ + ASSERT(prGlueInfo); + ASSERT(prRegInfo); + DBGLOG(INIT, INFO, "glLoadNvram start\n"); + if ((!prGlueInfo) || (!prRegInfo)) + return; + + /* load full NVRAM */ + prGlueInfo->fgNvramAvailable = FALSE; + if (kalCfgDataRead(prGlueInfo, 0, + sizeof(prRegInfo->aucNvram), + (uint16_t *)prRegInfo->aucNvram) == TRUE) { + + struct WIFI_CFG_PARAM_STRUCT *prNvramSettings; + + if (sizeof(struct WIFI_CFG_PARAM_STRUCT) > + sizeof(prRegInfo->aucNvram)) { + DBGLOG(INIT, ERROR, + "Size WIFI_CFG_PARAM_STRUCT %zu > size aucNvram %zu\n" + , sizeof(struct WIFI_CFG_PARAM_STRUCT), + sizeof(prRegInfo->aucNvram)); + return; + } +#if CFG_SUPPORT_NVRAM_5G + if (sizeof(struct NEW_EFUSE_MAPPING2NVRAM) > + sizeof(prRegInfo->aucEFUSE)) { + DBGLOG(INIT, ERROR, + "Size NEW_EFUSE_MAPPING2NVRAM %zu >size aucEFUSE %zu\n" + , sizeof(struct NEW_EFUSE_MAPPING2NVRAM), + sizeof(prRegInfo->aucEFUSE)); + return; + } +#endif + + prRegInfo->prNvramSettings = + (struct WIFI_CFG_PARAM_STRUCT *)&prRegInfo->aucNvram; + prNvramSettings = prRegInfo->prNvramSettings; + +#if CFG_SUPPORT_NVRAM_5G + /* load EFUSE overriding part */ + kalMemCopy(prRegInfo->aucEFUSE, + prNvramSettings->EfuseMapping.aucEFUSE, + sizeof(prRegInfo->aucEFUSE)); + prRegInfo->prOldEfuseMapping = + (struct NEW_EFUSE_MAPPING2NVRAM *)&prRegInfo->aucEFUSE; +#else + /* load EFUSE overriding part */ + kalMemCopy(prRegInfo->aucEFUSE, prNvramSettings->aucEFUSE, + sizeof(prRegInfo->aucEFUSE)); +#endif + + /* load MAC Address */ + kalMemCopy(prRegInfo->aucMacAddr, + prNvramSettings->aucMacAddress, + PARAM_MAC_ADDR_LEN * sizeof(uint8_t)); + + /* load country code */ + /* cast to wide characters */ + prRegInfo->au2CountryCode[0] = + (uint16_t) prNvramSettings->aucCountryCode[0]; + prRegInfo->au2CountryCode[1] = + (uint16_t) prNvramSettings->aucCountryCode[1]; + + /* load default normal TX power */ + kalMemCopy(&prRegInfo->rTxPwr, &prNvramSettings->rTxPwr, + sizeof(struct TX_PWR_PARAM)); + + /* load feature flags */ + prRegInfo->ucTxPwrValid = prNvramSettings->ucTxPwrValid; + + prRegInfo->ucSupport5GBand = + prNvramSettings->ucSupport5GBand; + + prRegInfo->uc2G4BwFixed20M = + prNvramSettings->uc2G4BwFixed20M; + + prRegInfo->uc5GBwFixed20M = prNvramSettings->uc5GBwFixed20M; + + prRegInfo->ucEnable5GBand = prNvramSettings->ucEnable5GBand; + + prRegInfo->ucRxDiversity = prNvramSettings->ucRxDiversity; + + prRegInfo->ucRssiPathCompasationUsed = + prNvramSettings->fgRssiCompensationVaildbit; + + prRegInfo->ucGpsDesense = prNvramSettings->ucGpsDesense; + + /* load band edge tx power control */ + prRegInfo->fg2G4BandEdgePwrUsed = + prNvramSettings->fg2G4BandEdgePwrUsed; + + if (prRegInfo->prNvramSettings->fg2G4BandEdgePwrUsed) { + prRegInfo->cBandEdgeMaxPwrCCK = + prNvramSettings->cBandEdgeMaxPwrCCK; + + prRegInfo->cBandEdgeMaxPwrOFDM20 = + prNvramSettings->cBandEdgeMaxPwrOFDM20; + + prRegInfo->cBandEdgeMaxPwrOFDM40 = + prNvramSettings->cBandEdgeMaxPwrOFDM40; + } + + /* load regulation subbands */ + prRegInfo->eRegChannelListMap = + (enum ENUM_REG_CH_MAP) + prNvramSettings->ucRegChannelListMap; + prRegInfo->ucRegChannelListIndex = + prNvramSettings->ucRegChannelListIndex; + + if (prRegInfo->eRegChannelListMap == + REG_CH_MAP_CUSTOMIZED) { + kalMemCopy(prRegInfo->rDomainInfo.rSubBand, + prNvramSettings->aucRegSubbandInfo, + MAX_SUBBAND_NUM * sizeof(uint8_t)); + } + + /* load rssiPathCompensation */ + kalMemCopy(&prRegInfo->rRssiPathCompasation, + &prNvramSettings->rRssiPathCompensation, + sizeof(struct RSSI_PATH_COMPASATION)); + + prGlueInfo->fgNvramAvailable = TRUE; + DBGLOG(INIT, INFO, "glLoadNvram end\n"); + } else { + DBGLOG(INIT, INFO, "glLoadNvram fail\n"); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Release prDev from wlandev_array and free tasklet object related to + * it. + * + * \param[in] prDev Pointer to struct net_device + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static void wlanClearDevIdx(struct net_device *prDev) +{ + int i; + + ASSERT(prDev); + + for (i = 0; i < CFG_MAX_WLAN_DEVICES; i++) { + if (arWlanDevInfo[i].prDev == prDev) { + arWlanDevInfo[i].prDev = NULL; + u4WlanDevNum--; + } + } + +} /* end of wlanClearDevIdx() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Allocate an unique interface index, net_device::ifindex member for + * this wlan device. Store the net_device in wlandev_array, and + * initialize tasklet object related to it. + * + * \param[in] prDev Pointer to struct net_device + * + * \retval >= 0 The device number. + * \retval -1 Fail to get index. + */ +/*----------------------------------------------------------------------------*/ +static int wlanGetDevIdx(struct net_device *prDev) +{ + int i; + + ASSERT(prDev); + + for (i = 0; i < CFG_MAX_WLAN_DEVICES; i++) { + if (arWlanDevInfo[i].prDev == (struct net_device *)NULL) { + /* Reserve 2 bytes space to store one digit of + * device number and NULL terminator. + */ + arWlanDevInfo[i].prDev = prDev; + u4WlanDevNum++; + return i; + } + } + + return -1; +} /* end of wlanGetDevIdx() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief A method of struct net_device, a primary SOCKET interface to configure + * the interface lively. Handle an ioctl call on one of our devices. + * Everything Linux ioctl specific is done here. Then we pass the + * contents of the ifr->data to the request message handler. + * + * \param[in] prDev Linux kernel netdevice + * + * \param[in] prIFReq Our private ioctl request structure, typed for the + * generic + * struct ifreq so we can use ptr to function + * + * \param[in] cmd Command ID + * + * \retval 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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int ret = 0; + + /* Verify input parameters for the following functions */ + ASSERT(prDev && prIfReq); + if (!prDev || !prIfReq) { + DBGLOG(INIT, ERROR, "Invalid input data\n"); + return -EINVAL; + } + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + if (!prGlueInfo) { + DBGLOG(INIT, ERROR, "prGlueInfo is NULL\n"); + return -EFAULT; + } + + if (prGlueInfo->u4ReadyFlag == 0) { + DBGLOG(INIT, ERROR, "Adapter is not ready\n"); + return -EINVAL; + } + + if ((i4Cmd >= SIOCIWFIRST) && (i4Cmd < SIOCIWFIRSTPRIV)) { + /* 0x8B00 ~ 0x8BDF, wireless extension region */ + ret = wext_support_ioctl(prDev, prIfReq, i4Cmd); + } else if ((i4Cmd >= SIOCIWFIRSTPRIV) + && (i4Cmd < SIOCIWLASTPRIV)) { + /* 0x8BE0 ~ 0x8BFF, private ioctl region */ + ret = priv_support_ioctl(prDev, prIfReq, i4Cmd); + } else if (i4Cmd == SIOCDEVPRIVATE + 1) { +#ifdef CFG_ANDROID_AOSP_PRIV_CMD + ret = android_private_support_driver_cmd(prDev, prIfReq, i4Cmd); +#else + ret = priv_support_driver_cmd(prDev, prIfReq, i4Cmd); +#endif /* CFG_ANDROID_AOSP_PRIV_CMD */ + } else { + DBGLOG(INIT, WARN, "Unexpected ioctl command: 0x%04x\n", + i4Cmd); + ret = -EOPNOTSUPP; + } + + return ret; +} /* end of wlanDoIOCTL() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*---------------------------------------------------------------------------*/ +struct GLUE_INFO *wlanGetGlueInfo(void) +{ + struct net_device *prDev = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + + if (u4WlanDevNum == 0) + return NULL; + + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + if (prDev == NULL) + return NULL; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + + return prGlueInfo; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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; +struct net_device *gPrDev; + +static void wlanSetMulticastList(struct net_device *prDev) +{ + /* Allow to receive all multicast for WOW */ + DBGLOG(INIT, TRACE, "wlanSetMulticastList\n"); + prDev->flags |= (IFF_MULTICAST | IFF_ALLMULTI); + 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 + * main_thread, so we can't let tx_thread to do this + */ + +static void wlanSetMulticastListWorkQueue( + struct work_struct *work) +{ + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4PacketFilter = 0; + uint32_t u4SetInfoLen; + struct net_device *prDev = gPrDev; + + down(&g_halt_sem); + if (g_u4HaltFlag) { + up(&g_halt_sem); + return; + } + + prGlueInfo = (prDev != NULL) ? *((struct GLUE_INFO **) + 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; + } + + DBGLOG(INIT, INFO, + "wlanSetMulticastListWorkQueue prDev->flags:0x%x\n", + prDev->flags); + + if (prDev->flags & IFF_PROMISC) + u4PacketFilter |= PARAM_PACKET_FILTER_PROMISCUOUS; + + if (prDev->flags & IFF_BROADCAST) + u4PacketFilter |= PARAM_PACKET_FILTER_BROADCAST; + + if (prDev->flags & IFF_MULTICAST) { + if ((prDev->flags & IFF_ALLMULTI) + || (netdev_mc_count(prDev) > MAX_NUM_GROUP_ADDR)) + u4PacketFilter |= PARAM_PACKET_FILTER_ALL_MULTICAST; + else + u4PacketFilter |= PARAM_PACKET_FILTER_MULTICAST; + } + + up(&g_halt_sem); + + if (kalIoctl(prGlueInfo, + wlanoidSetCurrentPacketFilter, + &u4PacketFilter, + sizeof(u4PacketFilter), FALSE, FALSE, TRUE, + &u4SetInfoLen) != WLAN_STATUS_SUCCESS) { + return; + } + + if (u4PacketFilter & PARAM_PACKET_FILTER_MULTICAST) { + /* Prepare multicast address list */ + struct netdev_hw_addr *ha; + uint8_t *prMCAddrList = NULL; + uint32_t 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 (!prMCAddrList) { + DBGLOG(INIT, WARN, "prMCAddrList memory alloc fail!\n"); + return; + } + + netdev_for_each_mc_addr(ha, prDev) { + if (i < MAX_NUM_GROUP_ADDR) { + kalMemCopy((prMCAddrList + i * ETH_ALEN), + GET_ADDR(ha), ETH_ALEN); + i++; + } + } + + up(&g_halt_sem); + + kalIoctl(prGlueInfo, + wlanoidSetMulticastList, prMCAddrList, (i * ETH_ALEN), + FALSE, FALSE, TRUE, &u4SetInfoLen); + + kalMemFree(prMCAddrList, VIR_MEM_TYPE, + MAX_NUM_GROUP_ADDR * ETH_ALEN); + } + +} /* end of wlanSetMulticastList() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To indicate scheduled scan has been stopped + * + * \param[in] + * prGlueInfo + * + * \return + * None + */ +/*----------------------------------------------------------------------------*/ +void wlanSchedScanStoppedWorkQueue(struct work_struct *work) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct net_device *prDev = gPrDev; + + DBGLOG(SCN, INFO, "wlanSchedScanStoppedWorkQueue\n"); + prGlueInfo = (prDev != NULL) ? *((struct GLUE_INFO **) + netdev_priv(prDev)) : NULL; + if (!prGlueInfo) { + DBGLOG(SCN, INFO, "prGlueInfo == NULL unexpected\n"); + return; + } + + /* 2. indication to cfg80211 */ + /* 20150205 change cfg80211_sched_scan_stopped to work queue due to + * sched_scan_mtx dead lock issue + */ +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE + cfg80211_sched_scan_stopped(priv_to_wiphy(prGlueInfo), 0); +#else + cfg80211_sched_scan_stopped(priv_to_wiphy(prGlueInfo)); +#endif + DBGLOG(SCN, INFO, + "cfg80211_sched_scan_stopped event send done WorkQueue thread return from wlanSchedScanStoppedWorkQueue\n"); + return; + +} + +/* FIXME: Since we cannot sleep in the wlanSetMulticastList, we arrange + * another workqueue for sleeping. We don't want to block + * main_thread, so we can't let tx_thread to do this + */ + +void p2pSetMulticastListWorkQueueWrapper(struct GLUE_INFO + *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 + +} /* 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) +{ + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = + (struct NETDEV_PRIVATE_GLUE_INFO *) NULL; + struct GLUE_INFO *prGlueInfo = *((struct GLUE_INFO **) + netdev_priv(prDev)); + uint8_t ucBssIndex; + + ASSERT(prSkb); + ASSERT(prDev); + ASSERT(prGlueInfo); + + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prDev); + ASSERT(prNetDevPrivate->prGlueInfo == prGlueInfo); + ucBssIndex = prNetDevPrivate->ucBssIdx; + +#if CFG_SUPPORT_PASSPOINT + if (prGlueInfo->fgIsDad) { + /* kalPrint("[Passpoint R2] Due to ipv4_dad...TX is forbidden\n" + * ); + */ + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } + if (prGlueInfo->fgIs6Dad) { + /* kalPrint("[Passpoint R2] Due to ipv6_dad...TX is forbidden\n" + * ); + */ + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_CHIP_RESET_SUPPORT + if (!wlanIsDriverReady(prGlueInfo)) { + DBGLOG(INIT, WARN, + "u4ReadyFlag:%u, kalIsResetting():%d, dropping the packet\n", + prGlueInfo->u4ReadyFlag, kalIsResetting()); + + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } +#endif + + + kalResetPacket(prGlueInfo, (void *) prSkb); + + STATS_TX_TIME_ARRIVE(prSkb); + + if (kalHardStartXmit(prSkb, prDev, prGlueInfo, + ucBssIndex) == WLAN_STATUS_SUCCESS) { + /* Successfully enqueue to Tx queue */ + /* Successfully enqueue to Tx queue */ + if (netif_carrier_ok(prDev)) + kalPerMonStart(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) +{ + return (struct net_device_stats *)kalGetStats(prDev); +} /* end of wlanGetStats() */ + +void wlanDebugInit(void) +{ + /* Set the initial debug level of each module */ +#if DBG + /* enable all */ + wlanSetDriverDbgLevel(DBG_ALL_MODULE_IDX, DBG_CLASS_MASK); +#else +#ifdef CFG_DEFAULT_DBG_LEVEL + wlanSetDriverDbgLevel(DBG_ALL_MODULE_IDX, + CFG_DEFAULT_DBG_LEVEL); +#else + wlanSetDriverDbgLevel(DBG_ALL_MODULE_IDX, + DBG_LOG_LEVEL_DEFAULT); +#endif +#endif /* DBG */ + + LOG_FUNC("Reset ALL DBG module log level to DEFAULT!"); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + if (!prDev) + return -ENXIO; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + INIT_DELAYED_WORK(&workq, wlanSetMulticastListWorkQueue); + + /* 20150205 work queue for sched_scan */ + INIT_DELAYED_WORK(&sched_workq, + wlanSchedScanStoppedWorkQueue); + + /* 20161024 init wow port setting */ +#if CFG_WOW_SUPPORT + kalWowInit(prGlueInfo); +#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) +{ +} /* end of wlanUninit() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief A method of struct net_device, to set the randomized mac address + * + * This method is called before Wifi Framework requests a new conenction with + * enabled feature "Connected Random Mac". + * + * \param[in] ndev Pointer to struct net_device. + * \param[in] addr Randomized Mac address passed from WIFI framework. + * + * \return int. + */ +/*----------------------------------------------------------------------------*/ +static int wlanSetMacAddress(struct net_device *ndev, void *addr) +{ + struct ADAPTER *prAdapter = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct sockaddr *sa = NULL; + + /********************************************************************** + * Check if kernel passes valid data to us * + ********************************************************************** + */ + if (!ndev || !addr) { + DBGLOG(INIT, ERROR, "Set macaddr with ndev(%d) and addr(%d)\n", + (ndev == NULL) ? 0 : 1, (addr == NULL) ? 0 : 1); + return WLAN_STATUS_INVALID_DATA; + } + + /********************************************************************** + * 1. Change OwnMacAddr which will be updated to FW through * + * rlmActivateNetwork later. * + * 2. Change dev_addr stored in kernel to notify framework that the * + * mac addr has been changed and what the new value is. * + ********************************************************************** + */ + sa = (struct sockaddr *)addr; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(ndev)); + prAdapter = prGlueInfo->prAdapter; + + COPY_MAC_ADDR(prAdapter->prAisBssInfo->aucOwnMacAddr, sa->sa_data); + COPY_MAC_ADDR(prGlueInfo->prDevHandler->dev_addr, sa->sa_data); + DBGLOG(INIT, INFO, "Set connect random macaddr to " MACSTR ".\n", + MAC2STR(prAdapter->prAisBssInfo->aucOwnMacAddr)); + + return WLAN_STATUS_SUCCESS; +} /* end of wlanSetMacAddr() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + ASSERT(prDev); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); +#if IS_ENABLED(CFG_RX_NAPI_SUPPORT) + napi_enable(&prGlueInfo->rNapi); +#endif /* CFG_RX_NAPI_SUPPORT */ + + netif_tx_start_all_queues(prDev); + + return 0; /* success */ +} /* end of wlanOpen() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief A function for prDev->stop + * + * \param[in] prDev Pointer to struct net_device. + * + * \retval 0 The execution of wlanStop succeeds. + * \retval < 0 The execution of wlanStop failed. + */ +/*----------------------------------------------------------------------------*/ +static int wlanStop(struct net_device *prDev) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prDev); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + + /* CFG80211 down */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if (prGlueInfo->prScanRequest) { + kalCfg80211ScanDone(prGlueInfo->prScanRequest, TRUE); + prGlueInfo->prScanRequest = NULL; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + /* zero clear old acs information */ + kalMemZero(&(prGlueInfo->prAdapter->rWifiVar.rChnLoadInfo), + sizeof(prGlueInfo->prAdapter->rWifiVar.rChnLoadInfo)); + wlanInitChnLoadInfoChannelList(prGlueInfo->prAdapter); +#endif + + netif_tx_stop_all_queues(prDev); + +#if IS_ENABLED(CFG_RX_NAPI_SUPPORT) + if (skb_queue_len(&prGlueInfo->rRxNapiSkbQ)) { + + struct sk_buff *skb; + + DBGLOG(INIT, WARN, "NAPI Remain pkts %d\n", + skb_queue_len(&prGlueInfo->rRxNapiSkbQ)); + + while ((skb = skb_dequeue(&prGlueInfo->rRxNapiSkbQ)) != NULL) + kfree_skb(skb); + } + napi_disable(&prGlueInfo->rNapi); +#endif /* CFG_RX_NAPI_SUPPORT */ + + return 0; /* success */ +} /* end of wlanStop() */ + +#if CFG_SUPPORT_SNIFFER +static int wlanMonOpen(struct net_device *prDev) +{ + ASSERT(prDev); + + netif_tx_start_all_queues(prDev); + + return 0; /* success */ +} + +static int wlanMonStop(struct net_device *prDev) +{ + ASSERT(prDev); + + netif_tx_stop_all_queues(prDev); + + return 0; /* success */ +} + +static const struct net_device_ops wlan_mon_netdev_ops = { + .ndo_open = wlanMonOpen, + .ndo_stop = wlanMonStop, +}; + +void wlanMonWorkHandler(struct work_struct *work) +{ + struct GLUE_INFO *prGlueInfo; + + prGlueInfo = container_of(work, struct GLUE_INFO, monWork); + + if (prGlueInfo->fgIsEnableMon) { + if (prGlueInfo->prMonDevHandler) + return; +#if KERNEL_VERSION(3, 18, 0) <= LINUX_VERSION_CODE + prGlueInfo->prMonDevHandler = + alloc_netdev_mq(sizeof(struct NETDEV_PRIVATE_GLUE_INFO), + NIC_MONITOR_INF_NAME, + NET_NAME_PREDICTABLE, ether_setup, + CFG_MAX_TXQ_NUM); +#else + prGlueInfo->prMonDevHandler = + alloc_netdev_mq(sizeof(struct NETDEV_PRIVATE_GLUE_INFO), + NIC_MONITOR_INF_NAME, + ether_setup, CFG_MAX_TXQ_NUM); +#endif + if (prGlueInfo->prMonDevHandler == NULL) { + DBGLOG(INIT, ERROR, + "wlanMonWorkHandler: Allocated prMonDevHandler context FAIL.\n"); + return; + } + + ((struct NETDEV_PRIVATE_GLUE_INFO *) netdev_priv( + prGlueInfo->prMonDevHandler))->prGlueInfo = prGlueInfo; + prGlueInfo->prMonDevHandler->type = + ARPHRD_IEEE80211_RADIOTAP; + prGlueInfo->prMonDevHandler->netdev_ops = + &wlan_mon_netdev_ops; + netif_carrier_off(prGlueInfo->prMonDevHandler); + netif_tx_stop_all_queues(prGlueInfo->prMonDevHandler); + kalResetStats(prGlueInfo->prMonDevHandler); + + if (register_netdev(prGlueInfo->prMonDevHandler) < 0) { + DBGLOG(INIT, ERROR, + "wlanMonWorkHandler: Registered prMonDevHandler context FAIL.\n"); + free_netdev(prGlueInfo->prMonDevHandler); + prGlueInfo->prMonDevHandler = NULL; + } + DBGLOG(INIT, INFO, + "wlanMonWorkHandler: Registered prMonDevHandler context DONE.\n"); + } else { + if (prGlueInfo->prMonDevHandler) { + unregister_netdev(prGlueInfo->prMonDevHandler); + prGlueInfo->prMonDevHandler = NULL; + DBGLOG(INIT, INFO, + "wlanMonWorkHandler: unRegistered prMonDevHandler context DONE.\n"); + } + } +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \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(struct GLUE_INFO *prGlueInfo) +{ + uint8_t i, j; + uint8_t ucNumOfChannel; + struct RF_CHANNEL_INFO aucChannelList[ARRAY_SIZE( + mtk_2ghz_channels) + ARRAY_SIZE(mtk_5ghz_channels)]; + + /* 1. Disable all channels */ + for (i = 0; i < ARRAY_SIZE(mtk_2ghz_channels); i++) { + mtk_2ghz_channels[i].flags |= IEEE80211_CHAN_DISABLED; + mtk_2ghz_channels[i].orig_flags |= IEEE80211_CHAN_DISABLED; + } + + for (i = 0; i < ARRAY_SIZE(mtk_5ghz_channels); i++) { + mtk_5ghz_channels[i].flags |= IEEE80211_CHAN_DISABLED; + mtk_5ghz_channels[i].orig_flags |= IEEE80211_CHAN_DISABLED; + } + + /* 2. Get current domain channel list */ + rlmDomainGetChnlList(prGlueInfo->prAdapter, + BAND_NULL, FALSE, + ARRAY_SIZE(mtk_2ghz_channels) + ARRAY_SIZE( + mtk_5ghz_channels), + &ucNumOfChannel, aucChannelList); + + /* 3. Enable specific channel based on domain channel list */ + for (i = 0; i < ucNumOfChannel; i++) { + switch (aucChannelList[i].eBand) { + case BAND_2G4: + for (j = 0; j < ARRAY_SIZE(mtk_2ghz_channels); j++) { + if (mtk_2ghz_channels[j].hw_value == + aucChannelList[i].ucChannelNum) { + mtk_2ghz_channels[j].flags &= + ~IEEE80211_CHAN_DISABLED; + mtk_2ghz_channels[j].orig_flags &= + ~IEEE80211_CHAN_DISABLED; + break; + } + } + break; + + case BAND_5G: + for (j = 0; j < ARRAY_SIZE(mtk_5ghz_channels); j++) { + if (mtk_5ghz_channels[j].hw_value == + aucChannelList[i].ucChannelNum) { + mtk_5ghz_channels[j].flags &= + ~IEEE80211_CHAN_DISABLED; + mtk_5ghz_channels[j].orig_flags &= + ~IEEE80211_CHAN_DISABLED; + break; + } + } + break; + + default: + DBGLOG(INIT, WARN, "Unknown band %d\n", + aucChannelList[i].eBand); + break; + } + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Register the device to the kernel and return the index. + * + * \param[in] prDev Pointer to struct net_device. + * + * \retval 0 The execution of wlanNetRegister succeeds. + * \retval < 0 The execution of wlanNetRegister failed. + */ +/*----------------------------------------------------------------------------*/ +static int32_t wlanNetRegister(struct wireless_dev *prWdev) +{ + struct GLUE_INFO *prGlueInfo; + int32_t i4DevIdx = -1; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = + (struct NETDEV_PRIVATE_GLUE_INFO *) NULL; + struct ADAPTER *prAdapter = NULL; + + ASSERT(prWdev); + + do { + if (!prWdev) + break; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(prWdev->wiphy); + prAdapter = prGlueInfo->prAdapter; + i4DevIdx = wlanGetDevIdx(prWdev->netdev); + if (i4DevIdx < 0) { + DBGLOG(INIT, ERROR, "net_device number exceeds!\n"); + break; + } + + if (prAdapter && prAdapter->rWifiVar.ucWow) + kalInitDevWakeup(prGlueInfo->prAdapter, + wiphy_dev(prWdev->wiphy)); + + if (register_netdev(prWdev->netdev) < 0) { + DBGLOG(INIT, ERROR, "Register net_device failed\n"); + wlanClearDevIdx(prWdev->netdev); + i4DevIdx = -1; + } + +#if IS_ENABLED(CFG_RX_NAPI_SUPPORT) +#if IS_ENABLED(CFG_GRO_SUPPORT) + /* Register GRO function to kernel */ + prWdev->netdev->features |= NETIF_F_GRO; + prWdev->netdev->hw_features |= NETIF_F_GRO; +#endif /* CFG_GRO_SUPPORT */ + netif_napi_add(prWdev->netdev, &prGlueInfo->rNapi, + kalRxNapiPoll, NAPI_POLL_WEIGHT); + skb_queue_head_init(&prGlueInfo->rRxNapiSkbQ); + if (prGlueInfo->prAdapter->rWifiVar.ucRxNapiEnable) + kalRxNapiSetEnable(prGlueInfo, TRUE); +#endif /* CFG_RX_NAPI_SUPPORT */ + +#if 1 + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prGlueInfo->prDevHandler); + ASSERT(prNetDevPrivate->prGlueInfo == prGlueInfo); + prNetDevPrivate->ucBssIdx = + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; +#if CFG_ENABLE_UNIFY_WIPHY + prNetDevPrivate->ucIsP2p = FALSE; +#endif + wlanBindBssIdxToNetInterface(prGlueInfo, + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex, + (void *) prWdev->netdev); +#else + wlanBindBssIdxToNetInterface(prGlueInfo, + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex, + (void *) prWdev->netdev); + /* wlanBindNetInterface(prGlueInfo, NET_DEV_WLAN_IDX, + * (PVOID)prWdev->netdev); + */ +#endif + if (i4DevIdx != -1) + prGlueInfo->fgIsRegistered = TRUE; + } while (FALSE); + + return i4DevIdx; /* success */ +} /* end of wlanNetRegister() */ + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Unregister the device from the kernel + * + * \param[in] prWdev Pointer to struct net_device. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static void wlanNetUnregister(struct wireless_dev *prWdev) +{ + struct GLUE_INFO *prGlueInfo; + + if (!prWdev) { + DBGLOG(INIT, ERROR, "The device context is NULL\n"); + return; + } + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(prWdev->wiphy); + +#if IS_ENABLED(CFG_RX_NAPI_SUPPORT) + kalRxNapiSetEnable(prGlueInfo, FALSE); + netif_napi_del(&prGlueInfo->rNapi); +#endif /* CFG_RX_NAPI_SUPPORT */ + + wlanClearDevIdx(prWdev->netdev); + unregister_netdev(prWdev->netdev); + + prGlueInfo->fgIsRegistered = FALSE; + +#if CFG_SUPPORT_SNIFFER + if (prGlueInfo->prMonDevHandler) { + unregister_netdev(prGlueInfo->prMonDevHandler); + /* FIXME: Why not free_netdev()? */ + prGlueInfo->prMonDevHandler = NULL; + } + prGlueInfo->fgIsEnableMon = FALSE; +#endif + +} /* end of wlanNetUnregister() */ + +static const struct net_device_ops wlan_netdev_ops = { + .ndo_open = wlanOpen, + .ndo_stop = wlanStop, + .ndo_set_rx_mode = wlanSetMulticastList, + .ndo_get_stats = wlanGetStats, + .ndo_do_ioctl = wlanDoIOCTL, + .ndo_start_xmit = wlanHardStartXmit, + .ndo_init = wlanInit, + .ndo_uninit = wlanUninit, + .ndo_select_queue = wlanSelectQueue, + .ndo_set_mac_address = wlanSetMacAddress, +}; + +#if CFG_ENABLE_UNIFY_WIPHY +const struct net_device_ops *wlanGetNdevOps(void) +{ + return &wlan_netdev_ops; +} +#endif + +static void wlanCreateWirelessDevice(void) +{ + struct wiphy *prWiphy = NULL; + struct wireless_dev *prWdev = NULL; + unsigned int u4SupportSchedScanFlag = 0; + + /* 4 <1.1> Create wireless_dev */ + prWdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (!prWdev) { + DBGLOG(INIT, ERROR, + "Allocating memory to wireless_dev context failed\n"); + return; + } + /* 4 <1.2> Create wiphy */ +#if CFG_ENABLE_UNIFY_WIPHY + prWiphy = wiphy_new(&mtk_cfg_ops, sizeof(struct GLUE_INFO)); +#else + prWiphy = wiphy_new(&mtk_wlan_ops, + sizeof(struct GLUE_INFO)); +#endif + + if (!prWiphy) { + DBGLOG(INIT, ERROR, + "Allocating memory to wiphy device failed\n"); + goto free_wdev; + } + + /* 4 <1.3> configure wireless_dev & wiphy */ + prWdev->iftype = NL80211_IFTYPE_STATION; + prWiphy->iface_combinations = p_mtk_iface_combinations_sta; + prWiphy->n_iface_combinations = + mtk_iface_combinations_sta_num; + prWiphy->max_scan_ssids = SCN_SSID_MAX_NUM + + 1; /* include one wildcard ssid */ + prWiphy->max_scan_ie_len = 512; +#if CFG_SUPPORT_SCHED_SCAN + prWiphy->max_sched_scan_ssids = + CFG_SCAN_HIDDEN_SSID_MAX_NUM; + prWiphy->max_match_sets = + CFG_SCAN_SSID_MATCH_MAX_NUM; + prWiphy->max_sched_scan_ie_len = CFG_CFG80211_IE_BUF_LEN; + u4SupportSchedScanFlag = + WIPHY_FLAG_SUPPORTS_SCHED_SCAN; +#endif /* CFG_SUPPORT_SCHED_SCAN */ + prWiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); + prWiphy->bands[KAL_BAND_2GHZ] = &mtk_band_2ghz; + /* always assign 5Ghz bands here, if the chip is not support 5Ghz, + * bands[KAL_BAND_5GHZ] will be assign to NULL + */ + prWiphy->bands[KAL_BAND_5GHZ] = &mtk_band_5ghz; + prWiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + prWiphy->cipher_suites = (const u32 *)mtk_cipher_suites; + prWiphy->n_cipher_suites = ARRAY_SIZE(mtk_cipher_suites); + prWiphy->flags = WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL + | u4SupportSchedScanFlag; + +#if CFG_SUPPORT_802_11R && CFG_SUPPORT_CFG80211_AUTH + prWiphy->features |= NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES; + prWiphy->features |= NL80211_FEATURE_QUIET; + prWiphy->features |= NL80211_FEATURE_TX_POWER_INSERTION; +#endif /* CFG_SUPPORT_ROAMING */ + +#if (CFG_SUPPORT_ROAMING == 1) + prWiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; +#endif /* CFG_SUPPORT_ROAMING */ + +#if KERNEL_VERSION(3, 14, 0) > CFG80211_VERSION_CODE + prWiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; +#else + prWiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; +#if (CFG_SUPPORT_DFS_MASTER == 1) + prWiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE + prWiphy->max_num_csa_counters = 2; +#endif +#endif /* CFG_SUPPORT_DFS_MASTER */ +#endif +#if (CFG_SUPPORT_SAE == 1) + prWiphy->features |= NL80211_FEATURE_SAE; +#endif /* CFG_SUPPORT_DFS_MASTER */ + + cfg80211_regd_set_wiphy(prWiphy); + +#if (CFG_SUPPORT_TDLS == 1) + TDLSEX_WIPHY_FLAGS_INIT(prWiphy->flags); +#endif /* CFG_SUPPORT_TDLS */ + prWiphy->max_remain_on_channel_duration = 5000; + prWiphy->mgmt_stypes = mtk_cfg80211_ais_default_mgmt_stypes; + +#if (CFG_SUPPORT_SCAN_RANDOM_MAC && \ + (KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE)) + prWiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; + prWiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR; +#endif + +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE + prWiphy->vendor_commands = mtk_wlan_vendor_ops; + prWiphy->n_vendor_commands = sizeof(mtk_wlan_vendor_ops) / + sizeof(struct wiphy_vendor_command); + prWiphy->vendor_events = mtk_wlan_vendor_events; + prWiphy->n_vendor_events = ARRAY_SIZE( + mtk_wlan_vendor_events); +#endif + /* 4 <1.4> wowlan support */ +#ifdef CONFIG_PM +#if KERNEL_VERSION(3, 11, 0) <= CFG80211_VERSION_CODE + prWiphy->wowlan = &mtk_wlan_wowlan_support; +#else + kalMemCopy(&prWiphy->wowlan, &mtk_wlan_wowlan_support, + sizeof(struct wiphy_wowlan_support)); +#endif +#endif + +#ifdef CONFIG_CFG80211_WEXT + /* 4 <1.5> Use wireless extension to replace IOCTL */ + +#if CFG_ENABLE_UNIFY_WIPHY + prWiphy->wext = NULL; +#else + prWiphy->wext = &wext_handler_def; +#endif +#endif + /* initialize semaphore for halt control */ + sema_init(&g_halt_sem, 1); + +#if CFG_ENABLE_UNIFY_WIPHY + prWiphy->iface_combinations = p_mtk_iface_combinations_p2p; + prWiphy->n_iface_combinations = + mtk_iface_combinations_p2p_num; + + prWiphy->interface_modes |= BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_P2P_CLIENT) | + BIT(NL80211_IFTYPE_P2P_GO) | + BIT(NL80211_IFTYPE_STATION); + prWiphy->software_iftypes |= BIT(NL80211_IFTYPE_P2P_DEVICE); + prWiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | + WIPHY_FLAG_HAVE_AP_SME; + prWiphy->ap_sme_capa = 1; +#endif + if (wiphy_register(prWiphy) < 0) { + DBGLOG(INIT, ERROR, "wiphy_register error\n"); + goto free_wiphy; + } + prWdev->wiphy = prWiphy; + gprWdev = prWdev; + DBGLOG(INIT, INFO, "Create wireless device success\n"); + return; + +free_wiphy: + wiphy_free(prWiphy); +free_wdev: + kfree(prWdev); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Destroy all wdev (including the P2P device), and unregister wiphy + * + * \param (none) + * + * \return (none) + * + */ +/*----------------------------------------------------------------------------*/ +static void wlanDestroyAllWdev(void) +{ +#if CFG_ENABLE_UNIFY_WIPHY + /* There is only one wiphy, avoid that double free the wiphy */ + struct wiphy *wiphy = NULL; +#endif +#if CFG_ENABLE_WIFI_DIRECT + int i = 0; +#endif + +#if CFG_ENABLE_WIFI_DIRECT + /* free P2P wdev */ + for (i = 0; i < KAL_P2P_NUM; i++) { + if (gprP2pRoleWdev[i] == NULL) + continue; +#if CFG_ENABLE_UNIFY_WIPHY + if (gprP2pRoleWdev[i] == gprWdev) { + /* This is AIS/AP Interface */ + gprP2pRoleWdev[i] = NULL; + continue; + } +#endif + /* Do wiphy_unregister here. Take care the case that the + * gprP2pRoleWdev[i] is created by the cfg80211 add iface ops, + * And the base P2P dev is in the gprP2pWdev. + * Expect that new created gprP2pRoleWdev[i] is freed in + * unregister_netdev/mtk_vif_destructor. And gprP2pRoleWdev[i] + * is reset as gprP2pWdev in mtk_vif_destructor. + */ + if (gprP2pRoleWdev[i] == gprP2pWdev) + gprP2pWdev = NULL; + +#if CFG_ENABLE_UNIFY_WIPHY + wiphy = gprP2pRoleWdev[i]->wiphy; +#else + set_wiphy_dev(gprP2pRoleWdev[i]->wiphy, NULL); + wiphy_unregister(gprP2pRoleWdev[i]->wiphy); + wiphy_free(gprP2pRoleWdev[i]->wiphy); +#endif + + kfree(gprP2pRoleWdev[i]); + gprP2pRoleWdev[i] = NULL; + } + + if (gprP2pWdev != NULL) { + /* This case is that gprP2pWdev isn't equal to gprP2pRoleWdev[0] + * . The gprP2pRoleWdev[0] is created in the p2p cfg80211 add + * iface ops. The two wdev use the same wiphy. Don't double + * free the same wiphy. + * This part isn't expect occur. Because p2pNetUnregister should + * unregister_netdev the new created wdev, and gprP2pRoleWdev[0] + * is reset as gprP2pWdev. + */ +#if CFG_ENABLE_UNIFY_WIPHY + wiphy = gprP2pWdev->wiphy; +#endif + + kfree(gprP2pWdev); + gprP2pWdev = NULL; + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + + /* free AIS wdev */ + if (gprWdev) { +#if CFG_ENABLE_UNIFY_WIPHY + wiphy = gprWdev->wiphy; +#else + /* trunk doesn't do set_wiphy_dev, but trunk-ce1 does. */ + /* set_wiphy_dev(gprWdev->wiphy, NULL); */ + wiphy_unregister(gprWdev->wiphy); + wiphy_free(gprWdev->wiphy); +#endif + kfree(gprWdev); + gprWdev = NULL; + } + +#if CFG_ENABLE_UNIFY_WIPHY + /* unregister & free wiphy */ + if (wiphy) { + /* set_wiphy_dev(wiphy, NULL): set the wiphy->dev->parent = NULL + * The trunk-ce1 does this, but the trunk seems not. + */ + /* set_wiphy_dev(wiphy, NULL); */ + wiphy_unregister(wiphy); + wiphy_free(wiphy); + } +#endif +} + +void wlanWakeLockInit(struct GLUE_INFO *prGlueInfo) +{ +#ifdef CONFIG_ANDROID + KAL_WAKE_LOCK_INIT(NULL, &prGlueInfo->rIntrWakeLock, + "WLAN interrupt"); + KAL_WAKE_LOCK_INIT(NULL, &prGlueInfo->rTimeoutWakeLock, + "WLAN timeout"); +#endif +} + +void wlanWakeLockUninit(struct GLUE_INFO *prGlueInfo) +{ +#if CFG_ENABLE_WAKE_LOCK + if (KAL_WAKE_LOCK_ACTIVE(NULL, &prGlueInfo->rIntrWakeLock)) + KAL_WAKE_UNLOCK(NULL, &prGlueInfo->rIntrWakeLock); + KAL_WAKE_LOCK_DESTROY(NULL, &prGlueInfo->rIntrWakeLock); + + if (KAL_WAKE_LOCK_ACTIVE(NULL, + &prGlueInfo->rTimeoutWakeLock)) + KAL_WAKE_UNLOCK(NULL, &prGlueInfo->rTimeoutWakeLock); + KAL_WAKE_LOCK_DESTROY(NULL, &prGlueInfo->rTimeoutWakeLock); +#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(void *pvData, + void *pvDriverData) +{ + struct wireless_dev *prWdev = gprWdev; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t i; + struct device *prDev; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = + (struct NETDEV_PRIVATE_GLUE_INFO *) NULL; + struct mt66xx_chip_info *prChipInfo; +#if CFG_ENABLE_UNIFY_WIPHY + struct wiphy *prWiphy = NULL; +#endif + + uint8_t *prInfName = NULL; + + if (prWdev == NULL) { + DBGLOG(INIT, ERROR, + "No wireless dev exist, abort power on\n"); + return NULL; + } + +#if CFG_ENABLE_UNIFY_WIPHY + /* The gprWdev is created at initWlan() and isn't reset when the + * disconnection occur. That cause some issue. + */ + prWiphy = prWdev->wiphy; + memset(prWdev, 0, sizeof(struct wireless_dev)); + prWdev->wiphy = prWiphy; + prWdev->iftype = NL80211_IFTYPE_STATION; +#if (CFG_SUPPORT_SINGLE_SKU == 1) + /* XXX: ref from cfg80211_regd_set_wiphy(). + * The error case: Sometimes after unplug/plug usb, the wlan0 STA can't + * scan correctly (FW doesn't do scan). The usb_probe message: + * "mtk_reg_notify:(RLM ERROR) Invalid REG state happened. state = 0x6". + */ + if (rlmDomainGetCtrlState() == REGD_STATE_INVALID) + rlmDomainResetCtrlInfo(TRUE); +#endif +#endif /* CFG_ENABLE_UNIFY_WIPHY */ + + /* 4 <1.3> co-relate wiphy & prDev */ + glGetDev(pvData, &prDev); + if (!prDev) { + DBGLOG(INIT, ERROR, "unable to get struct dev for wlan\n"); + return NULL; + } + /* Some kernel API (ex: cfg80211_get_drvinfo) will use wiphy_dev(). + * Without set_wiphy_dev(prWdev->wiphy, prDev), those API will crash. + */ + set_wiphy_dev(prWdev->wiphy, prDev); + + /* 4 <2> Create Glue structure */ + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(prWdev->wiphy); + kalMemZero(prGlueInfo, sizeof(struct GLUE_INFO)); + + /* 4 <2.1> Create Adapter structure */ + prAdapter = (struct ADAPTER *) wlanAdapterCreate( + prGlueInfo); + + if (!prAdapter) { + DBGLOG(INIT, ERROR, + "Allocating memory to adapter failed\n"); + glClearHifInfo(prGlueInfo); + goto netcreate_err; + } + + prChipInfo = ((struct mt66xx_hif_driver_data *) + pvDriverData)->chip_info; + prAdapter->chip_info = prChipInfo; + prGlueInfo->prAdapter = prAdapter; + + /* 4 <3> Initialize Glue structure */ + /* 4 <3.1> Create net device */ + +#ifdef CFG_DRIVER_INF_NAME_CHANGE + + if (kalStrLen(gprifnamesta) > 0) { + prInfName = kalStrCat(gprifnamesta, "%d"); + DBGLOG(INIT, WARN, "Station ifname customized, use %s\n", + prInfName); + } else +#endif /* CFG_DRIVER_INF_NAME_CHANGE */ + prInfName = NIC_INF_NAME; + +#if KERNEL_VERSION(3, 18, 0) <= LINUX_VERSION_CODE + prGlueInfo->prDevHandler = + alloc_netdev_mq(sizeof(struct NETDEV_PRIVATE_GLUE_INFO), + prInfName, NET_NAME_PREDICTABLE, ether_setup, + CFG_MAX_TXQ_NUM); +#else + prGlueInfo->prDevHandler = + alloc_netdev_mq(sizeof(struct NETDEV_PRIVATE_GLUE_INFO), + prInfName, + ether_setup, CFG_MAX_TXQ_NUM); +#endif + + if (!prGlueInfo->prDevHandler) { + DBGLOG(INIT, ERROR, + "Allocating memory to net_device context failed\n"); + goto netcreate_err; + } + DBGLOG(INIT, INFO, "net_device prDev(0x%p) allocated\n", + prGlueInfo->prDevHandler); + + /* Device can help us to save at most 3000 packets, after we stopped + ** queue + */ + prGlueInfo->prDevHandler->tx_queue_len = 3000; + + /* 4 <3.1.1> Initialize net device varaiables */ +#if 1 + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prGlueInfo->prDevHandler); + prNetDevPrivate->prGlueInfo = prGlueInfo; +#else + *((struct GLUE_INFO **) netdev_priv( + prGlueInfo->prDevHandler)) = prGlueInfo; +#endif + prGlueInfo->prDevHandler->needed_headroom += + NIC_TX_HEAD_ROOM; +/* + NIC_TX_DESC_AND_PADDING_LENGTH + + prChipInfo->txd_append_size; +*/ + 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); + kalResetStats(prGlueInfo->prDevHandler); + +#if CFG_SUPPORT_SNIFFER + INIT_WORK(&(prGlueInfo->monWork), wlanMonWorkHandler); +#endif + + /* 4 <3.1.2> co-relate with wiphy bi-directionally */ + prGlueInfo->prDevHandler->ieee80211_ptr = prWdev; + + prWdev->netdev = prGlueInfo->prDevHandler; + + /* 4 <3.1.3> co-relate net device & prDev */ + SET_NETDEV_DEV(prGlueInfo->prDevHandler, + wiphy_dev(prWdev->wiphy)); + + /* 4 <3.1.4> set device to glue */ + prGlueInfo->prDev = prDev; + + /* 4 <3.2> Initialize glue variables */ + prGlueInfo->eParamMediaStateIndicated = + PARAM_MEDIA_STATE_DISCONNECTED; + prGlueInfo->ePowerState = ParamDeviceStateD0; + prGlueInfo->fgIsRegistered = FALSE; + prGlueInfo->prScanRequest = NULL; + prGlueInfo->prSchedScanRequest = NULL; + + +#if CFG_SUPPORT_PASSPOINT + /* Init DAD */ + prGlueInfo->fgIsDad = FALSE; + prGlueInfo->fgIs6Dad = FALSE; + kalMemZero(prGlueInfo->aucDADipv4, 4); + kalMemZero(prGlueInfo->aucDADipv6, 16); +#endif /* CFG_SUPPORT_PASSPOINT */ + + init_completion(&prGlueInfo->rScanComp); + init_completion(&prGlueInfo->rHaltComp); + init_completion(&prGlueInfo->rPendComp); + +#if CFG_SUPPORT_MULTITHREAD + init_completion(&prGlueInfo->rHifHaltComp); + init_completion(&prGlueInfo->rRxHaltComp); +#endif + +#if CFG_SUPPORT_NCHO + init_completion(&prGlueInfo->rAisChGrntComp); +#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]); + } + + for (i = 0; i < MUTEX_NUM; i++) { + mutex_init(&prGlueInfo->arMutex[i]); + lockdep_set_subclass(&prGlueInfo->arMutex[i], i); + } + + /* initialize semaphore for ioctl */ + sema_init(&prGlueInfo->ioctl_sem, 1); + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN + /* initialize SDIO read-write pattern control */ + prGlueInfo->fgEnSdioTestPattern = FALSE; + prGlueInfo->fgIsSdioTestInitialized = FALSE; +#endif + + /* 4 <8> Init Queues */ + init_waitqueue_head(&prGlueInfo->waitq); + QUEUE_INITIALIZE(&prGlueInfo->rCmdQueue); + prGlueInfo->i4TxPendingCmdNum = 0; + QUEUE_INITIALIZE(&prGlueInfo->rTxQueue); + glSetHifInfo(prGlueInfo, (unsigned long) pvData); + + /* Init wakelock */ + wlanWakeLockInit(prGlueInfo); + + /* main thread is created in this function */ +#if CFG_SUPPORT_MULTITHREAD + init_waitqueue_head(&prGlueInfo->waitq_rx); + init_waitqueue_head(&prGlueInfo->waitq_hif); + + prGlueInfo->u4TxThreadPid = 0xffffffff; + prGlueInfo->u4RxThreadPid = 0xffffffff; + prGlueInfo->u4HifThreadPid = 0xffffffff; +#endif + + return prWdev; + +netcreate_err: + if (prAdapter != NULL) { + wlanAdapterDestroy(prAdapter); + prAdapter = NULL; + } + + if (prGlueInfo->prDevHandler != NULL) { + free_netdev(prGlueInfo->prDevHandler); + prGlueInfo->prDevHandler = NULL; + } + + return NULL; +} /* 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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + ASSERT(prWdev); + + if (!prWdev) { + DBGLOG(INIT, ERROR, "The device context is NULL\n"); + return; + } + + /* prGlueInfo is allocated with net_device */ + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(prWdev->wiphy); + ASSERT(prGlueInfo); + + /* prWdev: base AIS dev + * Because the interface dev (ex: usb_device) would be free + * after un-plug event. Should set the wiphy->dev->parent which + * pointer to the interface dev to NULL. Otherwise, the corresponding + * system operation (poweroff, suspend) might reference it. + * set_wiphy_dev(wiphy, NULL): set the wiphy->dev->parent = NULL + * The set_wiphy_dev(prWdev->wiphy, prDev) is done in wlanNetCreate. + * But that is after wiphy_register, and will cause exception in + * wiphy_unregister(), if do not set_wiphy_dev(wiphy, NULL). + */ + set_wiphy_dev(prWdev->wiphy, NULL); + + /* 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); + + /* gPrDev is assigned by prGlueInfo->prDevHandler, + * set NULL to this global variable. + */ + gPrDev = NULL; + +} /* end of wlanNetDestroy() */ + +void wlanSetSuspendMode(struct GLUE_INFO *prGlueInfo, + u_int8_t fgEnable) +{ + struct net_device *prDev = NULL; +#if CFG_SUPPORT_DROP_MC_PACKET + uint32_t u4PacketFilter = 0; + uint32_t u4SetInfoLen = 0; +#endif + + if (!prGlueInfo) + return; + + prDev = prGlueInfo->prDevHandler; + if (!prDev) + return; + +#if CFG_SUPPORT_DROP_MC_PACKET + /* new filter should not include p2p mask */ +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + u4PacketFilter = prGlueInfo->prAdapter->u4OsPacketFilter & + (~PARAM_PACKET_FILTER_P2P_MASK); +#endif + if (kalIoctl(prGlueInfo, + wlanoidSetCurrentPacketFilter, + &u4PacketFilter, + sizeof(u4PacketFilter), FALSE, FALSE, TRUE, + &u4SetInfoLen) != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, ERROR, "set packet filter failed.\n"); +#endif + kalSetNetAddressFromInterface(prGlueInfo, prDev, fgEnable); + wlanNotifyFwSuspend(prGlueInfo, prDev, fgEnable); +} + +#if CFG_ENABLE_EARLY_SUSPEND +static struct early_suspend wlan_early_suspend_desc = { + .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN, +}; + +static void wlan_early_suspend(struct early_suspend *h) +{ + struct net_device *prDev = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + + /* 4 <1> Sanity Check */ + if ((u4WlanDevNum == 0) + && (u4WlanDevNum > CFG_MAX_WLAN_DEVICES)) { + DBGLOG(INIT, ERROR, + "wlanLateResume u4WlanDevNum==0 invalid!!\n"); + return; + } + + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + if (!prDev) + return; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + if (!prGlueInfo) + return; + + DBGLOG(INIT, INFO, "********<%s>********\n", __func__); + + if (prGlueInfo->fgIsInSuspendMode == TRUE) { + DBGLOG(INIT, INFO, "%s: Already in suspend mode, SKIP!\n", + __func__); + return; + } + + prGlueInfo->fgIsInSuspendMode = TRUE; + + wlanSetSuspendMode(prGlueInfo, TRUE); + p2pSetSuspendMode(prGlueInfo, TRUE); +} + +static void wlan_late_resume(struct early_suspend *h) +{ + struct net_device *prDev = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + + /* 4 <1> Sanity Check */ + if ((u4WlanDevNum == 0) + && (u4WlanDevNum > CFG_MAX_WLAN_DEVICES)) { + DBGLOG(INIT, ERROR, + "wlanLateResume u4WlanDevNum==0 invalid!!\n"); + return; + } + + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + if (!prDev) + return; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + if (!prGlueInfo) + return; + + DBGLOG(INIT, INFO, "********<%s>********\n", __func__); + + if (prGlueInfo->fgIsInSuspendMode == FALSE) { + DBGLOG(INIT, INFO, "%s: Not in suspend mode, SKIP!\n", + __func__); + return; + } + + prGlueInfo->fgIsInSuspendMode = FALSE; + + /* 4 <2> Set suspend mode for each network */ + wlanSetSuspendMode(prGlueInfo, FALSE); + p2pSetSuspendMode(prGlueInfo, FALSE); +} +#endif + +#if (CFG_MTK_ANDROID_WMT || WLAN_INCLUDE_PROC) + +int set_p2p_mode_handler(struct net_device *netdev, + struct PARAM_CUSTOM_P2P_SET_STRUCT p2pmode) +{ + struct GLUE_INFO *prGlueInfo = *((struct GLUE_INFO **) + netdev_priv(netdev)); + struct PARAM_CUSTOM_P2P_SET_STRUCT rSetP2P; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + if (!prGlueInfo) + return -1; + +#if (CFG_MTK_ANDROID_WMT) + if (prGlueInfo->u4ReadyFlag == 0) { + DBGLOG(INIT, ERROR, "adapter is not ready\n"); + return -1; + } +#endif /*CFG_MTK_ANDROID_WMT*/ + + rSetP2P.u4Enable = p2pmode.u4Enable; + rSetP2P.u4Mode = p2pmode.u4Mode; + + if ((!rSetP2P.u4Enable) && (kalIsResetting() == FALSE)) + p2pNetUnregister(prGlueInfo, FALSE); + + rWlanStatus = kalIoctl(prGlueInfo, wlanoidSetP2pMode, + (void *) &rSetP2P, + sizeof(struct PARAM_CUSTOM_P2P_SET_STRUCT), + FALSE, FALSE, TRUE, &u4BufLen); + + DBGLOG(INIT, INFO, "set_p2p_mode_handler ret = 0x%08x\n", + (uint32_t) rWlanStatus); + + + /* Need to check fgIsP2PRegistered, in case of whole chip reset. + * in this case, kalIOCTL return success always, + * and prGlueInfo->prP2PInfo[0] may be NULL + */ + if ((rSetP2P.u4Enable) + && (prGlueInfo->prAdapter->fgIsP2PRegistered) + && (kalIsResetting() == FALSE)) + p2pNetRegister(prGlueInfo, FALSE); + + return 0; +} + +#endif + +#if CFG_SUPPORT_EASY_DEBUG +/*----------------------------------------------------------------------------*/ +/*! + * \brief parse config from wifi.cfg + * + * \param[in] prAdapter + * + * \retval VOID + */ +/*----------------------------------------------------------------------------*/ +void wlanGetParseConfig(struct ADAPTER *prAdapter) +{ + uint8_t *pucConfigBuf; + uint32_t u4ConfigReadLen; + + wlanCfgInit(prAdapter, NULL, 0, 0); + pucConfigBuf = (uint8_t *) kalMemAlloc( + WLAN_CFG_FILE_BUF_SIZE, VIR_MEM_TYPE); + kalMemZero(pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE); + u4ConfigReadLen = 0; + if (pucConfigBuf) { + if (kalRequestFirmware("wifi.cfg", pucConfigBuf, + WLAN_CFG_FILE_BUF_SIZE, &u4ConfigReadLen, + prAdapter->prGlueInfo->prDev) == 0) { + /* ToDo:: Nothing */ + } else if (kalReadToFile("/data/misc/wifi.cfg", + pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE, + &u4ConfigReadLen) == 0) { + /* ToDo:: Nothing */ + } else if (kalReadToFile("/data/misc/wifi/wifi.cfg", + pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE, + &u4ConfigReadLen) == 0) { + /* ToDo:: Nothing */ + } else if (kalReadToFile("/storage/sdcard0/wifi.cfg", + pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE, + &u4ConfigReadLen) == 0) { + /* ToDo:: Nothing */ + } + + if (pucConfigBuf[0] != '\0' && u4ConfigReadLen > 0) + wlanCfgParse(prAdapter, pucConfigBuf, u4ConfigReadLen, + TRUE); + + kalMemFree(pucConfigBuf, VIR_MEM_TYPE, + WLAN_CFG_FILE_BUF_SIZE); + } /* pucConfigBuf */ +} + + +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief get config from wifi.cfg + * + * \param[in] prAdapter + * + * \retval VOID + */ +/*----------------------------------------------------------------------------*/ +void wlanGetConfig(struct ADAPTER *prAdapter) +{ + uint8_t *pucConfigBuf; + uint32_t u4ConfigReadLen; + + wlanCfgInit(prAdapter, NULL, 0, 0); + pucConfigBuf = (uint8_t *) kalMemAlloc( + WLAN_CFG_FILE_BUF_SIZE, VIR_MEM_TYPE); + kalMemZero(pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE); + u4ConfigReadLen = 0; + if (pucConfigBuf) { +#ifdef CFG_FILE_NAME + if (kalRequestFirmware(CFG_FILE_NAME, pucConfigBuf, + WLAN_CFG_FILE_BUF_SIZE, &u4ConfigReadLen, + prAdapter->prGlueInfo->prDev) == 0) { + } else +#endif + if (kalRequestFirmware("wifi.cfg", pucConfigBuf, + WLAN_CFG_FILE_BUF_SIZE, &u4ConfigReadLen, + prAdapter->prGlueInfo->prDev) == 0) { + /* ToDo:: Nothing */ + } else if (kalReadToFile("/data/misc/wifi/wifi.cfg", + pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE, + &u4ConfigReadLen) == 0) { + /* ToDo:: Nothing */ + } else if (kalReadToFile("/storage/sdcard0/wifi.cfg", + pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE, + &u4ConfigReadLen) == 0) { + /* ToDo:: Nothing */ + } + + if (pucConfigBuf[0] != '\0' && u4ConfigReadLen > 0) + wlanCfgInit(prAdapter, + pucConfigBuf, u4ConfigReadLen, 0); + + kalMemFree(pucConfigBuf, VIR_MEM_TYPE, + WLAN_CFG_FILE_BUF_SIZE); + } /* pucConfigBuf */ +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief this function send buffer bin EEPROB_MTxxxx.bin to FW. + * + * \param[in] prAdapter + * + * \retval WLAN_STATUS_SUCCESS Success + * \retval WLAN_STATUS_FAILURE Failed + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanDownloadBufferBin(struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo = NULL; +#if (CFG_FW_Report_Efuse_Address) + uint16_t u2InitAddr = prAdapter->u4EfuseStartAddress; +#else + uint16_t u2InitAddr = EFUSE_CONTENT_BUFFER_START; +#endif + uint32_t u4BufLen = 0; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE *prSetEfuseBufModeInfo + = NULL; + uint32_t u4ContentLen; + uint8_t *pucConfigBuf = NULL; + struct mt66xx_chip_info *prChipInfo; + uint32_t chip_id; + uint8_t aucEeprom[32]; + uint32_t retWlanStat = WLAN_STATUS_FAILURE; + +#if CFG_EFUSE_AUTO_MODE_SUPPORT + uint32_t u4Efuse_addr = 0; + struct PARAM_CUSTOM_ACCESS_EFUSE *prAccessEfuseInfo + = NULL; +#endif + + if (prAdapter->fgIsSupportPowerOnSendBufferModeCMD == + TRUE) { + DBGLOG(INIT, INFO, "Start Efuse Buffer Mode ..\n"); + DBGLOG(INIT, INFO, "ucEfuseBUfferModeCal is %x\n", + prAdapter->rWifiVar.ucEfuseBufferModeCal); + + prChipInfo = prAdapter->chip_info; + chip_id = prChipInfo->chip_id; + prGlueInfo = prAdapter->prGlueInfo; + + if (prGlueInfo == NULL || prGlueInfo->prDev == NULL) + goto label_exit; + + /* allocate memory for buffer mode info */ + prSetEfuseBufModeInfo = + (struct PARAM_CUSTOM_EFUSE_BUFFER_MODE *) + kalMemAlloc(sizeof( + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE), + VIR_MEM_TYPE); + if (prSetEfuseBufModeInfo == NULL) + goto label_exit; + kalMemZero(prSetEfuseBufModeInfo, + sizeof(struct PARAM_CUSTOM_EFUSE_BUFFER_MODE)); + +#if CFG_EFUSE_AUTO_MODE_SUPPORT + /* allocate memory for Access Efuse Info */ + prAccessEfuseInfo = + (struct PARAM_CUSTOM_ACCESS_EFUSE *) + kalMemAlloc(sizeof( + struct PARAM_CUSTOM_ACCESS_EFUSE), + VIR_MEM_TYPE); + if (prAccessEfuseInfo == NULL) + goto label_exit; + kalMemZero(prAccessEfuseInfo, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + + if (prAdapter->rWifiVar.ucEfuseBufferModeCal == LOAD_AUTO) { + prAccessEfuseInfo->u4Address = (u4Efuse_addr / + EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + prAccessEfuseInfo, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), + TRUE, TRUE, TRUE, &u4BufLen); + if (prGlueInfo->prAdapter->aucEepromVaule[1] + == (chip_id>>8)) { + prAdapter->rWifiVar.ucEfuseBufferModeCal + = LOAD_EFUSE; + DBGLOG(INIT, STATE, + "[EFUSE AUTO] EFUSE Mode\n"); + } else { + prAdapter->rWifiVar.ucEfuseBufferModeCal + = LOAD_EEPROM_BIN; + DBGLOG(INIT, STATE, + "[EFUSE AUTO] Buffer Mode\n"); + } + } +#endif + + if (prAdapter->rWifiVar.ucEfuseBufferModeCal + == LOAD_EEPROM_BIN) { + /* Buffer mode */ + /* Only in buffer mode need to access bin file */ + /* 1 <1> Load bin file*/ + pucConfigBuf = (uint8_t *) kalMemAlloc( + MAX_EEPROM_BUFFER_SIZE, VIR_MEM_TYPE); + if (pucConfigBuf == NULL) + goto label_exit; + + kalMemZero(pucConfigBuf, MAX_EEPROM_BUFFER_SIZE); + + /* 1 <2> Construct EEPROM binary name */ + kalMemZero(aucEeprom, sizeof(aucEeprom)); + + snprintf(aucEeprom, 32, "%s%x.bin", + apucEepromName[0], chip_id); + + /* 1 <3> Request buffer bin */ + if (kalRequestFirmware(aucEeprom, pucConfigBuf, + MAX_EEPROM_BUFFER_SIZE, &u4ContentLen, + prGlueInfo->prDev) == 0) { + DBGLOG(INIT, INFO, "request file done\n"); + } else { + DBGLOG(INIT, INFO, "can't find file\n"); + goto label_exit; + } + + /* 1 <4> Send CMD with bin file content */ + prGlueInfo = prAdapter->prGlueInfo; + + /* Update contents in local table */ + kalMemCopy(uacEEPROMImage, pucConfigBuf, + MAX_EEPROM_BUFFER_SIZE); + + /* copy to the command buffer */ +#if (CFG_FW_Report_Efuse_Address) + u4ContentLen = (prAdapter->u4EfuseEndAddress) - + (prAdapter->u4EfuseStartAddress) + 1; +#else + u4ContentLen = EFUSE_CONTENT_BUFFER_SIZE; +#endif + if (u4ContentLen > MAX_EEPROM_BUFFER_SIZE) + goto label_exit; + kalMemCopy(prSetEfuseBufModeInfo->aBinContent, + &pucConfigBuf[u2InitAddr], u4ContentLen); + + prSetEfuseBufModeInfo->ucSourceMode = 1; + } else { + /* eFuse mode */ + /* Only need to tell FW the content from, contents are + * directly from efuse + */ + prSetEfuseBufModeInfo->ucSourceMode = 0; + } + prSetEfuseBufModeInfo->ucCmdType = 0x1 | + (prAdapter->rWifiVar.ucCalTimingCtrl << 4); + prSetEfuseBufModeInfo->ucCount = + 0xFF; /* ucCmdType 1 don't care the ucCount */ + + rStatus = kalIoctl(prGlueInfo, wlanoidSetEfusBufferMode, + (void *)prSetEfuseBufModeInfo, + sizeof(struct PARAM_CUSTOM_EFUSE_BUFFER_MODE), + FALSE, TRUE, TRUE, &u4BufLen); + } + + retWlanStat = WLAN_STATUS_SUCCESS; + +label_exit: + + /* free memory */ + if (prSetEfuseBufModeInfo != NULL) + kalMemFree(prSetEfuseBufModeInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_CUSTOM_EFUSE_BUFFER_MODE)); + + if (pucConfigBuf != NULL) + kalMemFree(pucConfigBuf, VIR_MEM_TYPE, + MAX_EEPROM_BUFFER_SIZE); + +#if CFG_EFUSE_AUTO_MODE_SUPPORT + if (prAccessEfuseInfo != NULL) + kalMemFree(prAccessEfuseInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); +#endif + + return retWlanStat; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief this function send buffer bin EEPROB_MTxxxx.bin to FW. + * + * \param[in] prAdapter + * + * \retval WLAN_STATUS_SUCCESS Success + * \retval WLAN_STATUS_FAILURE Failed + */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanConnacDownloadBufferBin(struct ADAPTER + *prAdapter) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4BufLen = 0; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE_CONNAC_T + *prSetEfuseBufModeInfo = NULL; + uint32_t u4ContentLen; + uint8_t *pucConfigBuf = NULL; + struct mt66xx_chip_info *prChipInfo; + uint32_t chip_id; + uint8_t aucEeprom[32]; + uint32_t retWlanStat = WLAN_STATUS_FAILURE; + struct CAP_BUFFER_MODE_INFO_T *prBufferModeInfo = NULL; + +#if CFG_EFUSE_AUTO_MODE_SUPPORT + uint32_t u4Efuse_addr = 0; + struct PARAM_CUSTOM_ACCESS_EFUSE *prAccessEfuseInfo + = NULL; +#endif + + if (prAdapter->fgIsSupportPowerOnSendBufferModeCMD == FALSE) + return WLAN_STATUS_SUCCESS; + + DBGLOG(INIT, INFO, "Start Efuse Buffer Mode ..\n"); + DBGLOG(INIT, INFO, "ucEfuseBUfferModeCal is %x\n", + prAdapter->rWifiVar.ucEfuseBufferModeCal); + + prChipInfo = prAdapter->chip_info; + chip_id = prChipInfo->chip_id; + prGlueInfo = prAdapter->prGlueInfo; + prBufferModeInfo = &prAdapter->rBufferModeInfo; + + if (prGlueInfo == NULL || prGlueInfo->prDev == NULL) + goto label_exit; + + /* allocate memory for buffer mode info */ + prSetEfuseBufModeInfo = + (struct PARAM_CUSTOM_EFUSE_BUFFER_MODE_CONNAC_T *) + kalMemAlloc(sizeof( + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE_CONNAC_T), + VIR_MEM_TYPE); + if (prSetEfuseBufModeInfo == NULL) + goto label_exit; + kalMemZero(prSetEfuseBufModeInfo, + sizeof(struct PARAM_CUSTOM_EFUSE_BUFFER_MODE_CONNAC_T)); + +#if CFG_EFUSE_AUTO_MODE_SUPPORT + /* allocate memory for Access Efuse Info */ + prAccessEfuseInfo = + (struct PARAM_CUSTOM_ACCESS_EFUSE *) + kalMemAlloc(sizeof( + struct PARAM_CUSTOM_ACCESS_EFUSE), + VIR_MEM_TYPE); + if (prAccessEfuseInfo == NULL) + goto label_exit; + kalMemZero(prAccessEfuseInfo, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + + if (prAdapter->rWifiVar.ucEfuseBufferModeCal == LOAD_AUTO) { + prAccessEfuseInfo->u4Address = (u4Efuse_addr / + EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + prAccessEfuseInfo, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), + TRUE, TRUE, TRUE, &u4BufLen); + if (prGlueInfo->prAdapter->aucEepromVaule[1] + == (chip_id>>8)) { + prAdapter->rWifiVar.ucEfuseBufferModeCal + = LOAD_EFUSE; + DBGLOG(INIT, STATE, + "[EFUSE AUTO] EFUSE Mode\n"); + } else { + prAdapter->rWifiVar.ucEfuseBufferModeCal + = LOAD_EEPROM_BIN; + DBGLOG(INIT, STATE, + "[EFUSE AUTO] Buffer Mode\n"); + } + } +#endif + + if (prAdapter->rWifiVar.ucEfuseBufferModeCal == LOAD_EEPROM_BIN) { + /* Buffer mode */ + /* Only in buffer mode need to access bin file */ + /* 1 <1> Load bin file*/ + pucConfigBuf = (uint8_t *) kalMemAlloc( + MAX_EEPROM_BUFFER_SIZE, VIR_MEM_TYPE); + if (pucConfigBuf == NULL) + goto label_exit; + + kalMemZero(pucConfigBuf, MAX_EEPROM_BUFFER_SIZE); + + /* 1 <2> Construct EEPROM binary name */ + kalMemZero(aucEeprom, sizeof(aucEeprom)); + + snprintf(aucEeprom, 32, "%s%x.bin", + apucEepromName[0], chip_id); + + /* 1 <3> Request buffer bin */ + if (kalRequestFirmware(aucEeprom, pucConfigBuf, + MAX_EEPROM_BUFFER_SIZE, &u4ContentLen, prGlueInfo->prDev) + == 0) { + DBGLOG(INIT, INFO, "request file done\n"); + } else { + DBGLOG(INIT, INFO, "can't find file\n"); + goto label_exit; + } + DBGLOG(INIT, INFO, "u4ContentLen = %d\n", u4ContentLen); + + if (u4ContentLen > MAX_EEPROM_BUFFER_SIZE) { + DBGLOG(INIT, ERROR, "u4ContentLen: %d > %d\n", + u4ContentLen, MAX_EEPROM_BUFFER_SIZE); + goto label_exit; + } + + /* Update contents in local table */ + kalMemCopy(uacEEPROMImage, pucConfigBuf, + u4ContentLen); + + /* 1 <4> Send CMD with bin file content */ + if (prBufferModeInfo->ucVersion != 0x02) { + DBGLOG(INIT, ERROR, "Not support version\n"); + goto label_exit; + } + + if (prBufferModeInfo->ucFormatSupportBitmap & + BIT(CONTENT_FORMAT_WHOLE_CONTENT)) { + if (u4ContentLen > prBufferModeInfo->u2EfuseTotalSize) { + DBGLOG(INIT, ERROR, "u4ContentLen: %d > %d\n", + u4ContentLen, + prBufferModeInfo->u2EfuseTotalSize); + goto label_exit; + } + + kalMemCopy(prSetEfuseBufModeInfo->aBinContent, + pucConfigBuf, u4ContentLen); + } else if (prBufferModeInfo->ucFormatSupportBitmap & + BIT(CONTENT_FORMAT_MULTIPLE_SECTIONS)) { + /* TODO */ + DBGLOG(INIT, ERROR, "Not support yet!\n"); + goto label_exit; + } else { + DBGLOG(INIT, ERROR, + "Not support legacy BIN_CONTENT mode\n"); + goto label_exit; + } + + prSetEfuseBufModeInfo->ucSourceMode = SOURCE_MODE_BUFFER_MODE; +#if CFG_RCPI_COMPENSATION + wlanLoadBufferbinRxFELoss(prAdapter); +#endif +#if CFG_SUPPORT_HW_1T2R + wlanLoadBufferbin1T2R(prAdapter); +#endif + } else { + /* eFuse mode */ + /* Only need to tell FW the content from, contents are directly + * from efuse + */ + prSetEfuseBufModeInfo->ucSourceMode = SOURCE_MODE_EFUSE; + u4ContentLen = 0; +#if CFG_RCPI_COMPENSATION + wlanLoadEfuseRxFELoss(prAdapter); +#endif +#if CFG_SUPPORT_HW_1T2R + wlanLoadEfuse1T2R(prAdapter); +#endif + } + prSetEfuseBufModeInfo->ucContentFormat = CONTENT_FORMAT_WHOLE_CONTENT | + (prAdapter->rWifiVar.ucCalTimingCtrl << + CMD_TYPE_CAL_TIME_REDUCTION_SHFT); + prSetEfuseBufModeInfo->u2Count = u4ContentLen; + + rStatus = kalIoctl(prGlueInfo, wlanoidConnacSetEfusBufferMode, + (void *)prSetEfuseBufModeInfo, + OFFSET_OF(struct PARAM_CUSTOM_EFUSE_BUFFER_MODE_CONNAC_T, + aBinContent) + u4ContentLen, + FALSE, TRUE, TRUE, &u4BufLen); + + retWlanStat = WLAN_STATUS_SUCCESS; + +label_exit: + + /* free memory */ + if (prSetEfuseBufModeInfo != NULL) + kalMemFree(prSetEfuseBufModeInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_CUSTOM_EFUSE_BUFFER_MODE_CONNAC_T)); + + if (pucConfigBuf != NULL) + kalMemFree(pucConfigBuf, VIR_MEM_TYPE, + MAX_EEPROM_BUFFER_SIZE); + +#if CFG_EFUSE_AUTO_MODE_SUPPORT + if (prAccessEfuseInfo != NULL) + kalMemFree(prAccessEfuseInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); +#endif + + return retWlanStat; +} + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + +#define FW_LOG_CMD_ON_OFF 0 +#define FW_LOG_CMD_SET_LEVEL 1 +static uint32_t u4LogOnOffCache = -1; + +static void consys_log_event_notification(int cmd, int value) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct net_device *prDev = gPrDev; + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER rCmdV1Header; + struct CMD_FORMAT_V1 rCmd_v1; + + DBGLOG(INIT, INFO, "gPrDev=%p, cmd=%d, value=%d\n", + gPrDev, cmd, value); + + if (kalIsHalted()) { /* power-off */ + u4LogOnOffCache = value; + DBGLOG(INIT, INFO, + "Power off return, u4LogOnOffCache=%d\n", + u4LogOnOffCache); + return; + } + + prGlueInfo = (prDev != NULL) ? + *((struct GLUE_INFO **) netdev_priv(prDev)) : NULL; + DBGLOG(INIT, TRACE, "prGlueInfo=%p\n", prGlueInfo); + if (!prGlueInfo) { + u4LogOnOffCache = value; + DBGLOG(INIT, INFO, + "prGlueInfo == NULL return, u4LogOnOffCache=%d\n", + u4LogOnOffCache); + return; + } + prAdapter = prGlueInfo->prAdapter; + DBGLOG(INIT, TRACE, "prAdapter=%p\n", prAdapter); + if (!prAdapter) { + u4LogOnOffCache = value; + DBGLOG(INIT, INFO, + "prAdapter == NULL return, u4LogOnOffCache=%d\n", + u4LogOnOffCache); + return; + } + + if (cmd == FW_LOG_CMD_ON_OFF) { + + /*EvtDrvnLogEn 0/1*/ + uint8_t onoff[1] = {'0'}; + + DBGLOG(INIT, TRACE, "FW_LOG_CMD_ON_OFF\n"); + + rCmdV1Header.cmdType = CMD_TYPE_SET; + rCmdV1Header.cmdVersion = CMD_VER_1; + rCmdV1Header.cmdBufferLen = 0; + rCmdV1Header.itemNum = 0; + + kalMemSet(rCmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); + kalMemSet(&rCmd_v1, 0, sizeof(struct CMD_FORMAT_V1)); + + rCmd_v1.itemType = ITEM_TYPE_STR; + + /*send string format to firmware */ + rCmd_v1.itemStringLength = kalStrLen("EnableDbgLog"); + kalMemZero(rCmd_v1.itemString, MAX_CMD_NAME_MAX_LENGTH); + kalMemCopy(rCmd_v1.itemString, "EnableDbgLog", + rCmd_v1.itemStringLength); + + if (value == 1) /* other cases, send 'OFF=0' */ + onoff[0] = '1'; + rCmd_v1.itemValueLength = 1; + kalMemZero(rCmd_v1.itemValue, MAX_CMD_VALUE_MAX_LENGTH); + kalMemCopy(rCmd_v1.itemValue, &onoff, 1); + + DBGLOG(INIT, INFO, "Send key word (%s) WITH (%s) to firmware\n", + rCmd_v1.itemString, rCmd_v1.itemValue); + + kalMemCopy(((struct CMD_FORMAT_V1 *)rCmdV1Header.buffer), + &rCmd_v1, sizeof(struct CMD_FORMAT_V1)); + + rCmdV1Header.cmdBufferLen += sizeof(struct CMD_FORMAT_V1); + rCmdV1Header.itemNum = 1; + + rStatus = wlanSendSetQueryCmd( + prAdapter, /* prAdapter */ + CMD_ID_GET_SET_CUSTOMER_CFG, /* 0x70 */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler*/ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct CMD_HEADER), + (uint8_t *)&rCmdV1Header, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus == WLAN_STATUS_FAILURE) + DBGLOG(INIT, INFO, + "[Fail]kalIoctl wifiSefCFG fail 0x%x\n", + rStatus); + + /* keep in cache */ + u4LogOnOffCache = value; + } else if (cmd == FW_LOG_CMD_SET_LEVEL) { + /*ENG_LOAD_OFFSET 1*/ + /*USERDEBUG_LOAD_OFFSET 2 */ + /*USER_LOAD_OFFSET 3 */ + DBGLOG(INIT, INFO, "FW_LOG_CMD_SET_LEVEL\n"); + } else { + DBGLOG(INIT, INFO, "command can not parse\n"); + } +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \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 int32_t wlanProbe(void *pvData, void *pvDriverData) +{ + struct wireless_dev *prWdev = NULL; + enum ENUM_PROBE_FAIL_REASON { + BUS_INIT_FAIL, + NET_CREATE_FAIL, + BUS_SET_IRQ_FAIL, + ADAPTER_START_FAIL, + NET_REGISTER_FAIL, + PROC_INIT_FAIL, + FAIL_MET_INIT_PROCFS, + FAIL_REASON_NUM + } eFailReason; + struct WLANDEV_INFO *prWlandevInfo = NULL; + int32_t i4DevIdx = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + int32_t i4Status = 0; + u_int8_t bRet = FALSE; + u_int8_t i = 0; + struct REG_INFO *prRegInfo; + struct mt66xx_chip_info *prChipInfo; +#if CFG_SUPPORT_REPLAY_DETECTION + u_int8_t ucRpyDetectOffload; +#endif + +#if CFG_THERMAL_API_SUPPORT + struct wcn_platform_bridge pbridge; +#endif + +#if (MTK_WCN_HIF_SDIO && CFG_WMT_WIFI_PATH_SUPPORT) + int32_t i4RetVal = 0; +#endif + int32_t u4LogLevel = ENUM_WIFI_LOG_LEVEL_DEFAULT; + +#if 0 + uint8_t *pucConfigBuf = NULL, pucCfgBuf = NULL; + uint32_t u4ConfigReadLen = 0; +#endif + eFailReason = FAIL_REASON_NUM; + do { + /* 4 <1> Initialize the IO port of the interface */ + /* GeorgeKuo: pData has different meaning for _HIF_XXX: + * _HIF_EHPI: pointer to memory base variable, which will be + * initialized by glBusInit(). + * _HIF_SDIO: bus driver handle + */ + + DBGLOG(INIT, STATE, "enter wlanProbe\n"); + + bRet = glBusInit(pvData); + +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanDebugTC4Init(); +#endif + /* Cannot get IO address from interface */ + if (bRet == FALSE) { + DBGLOG(INIT, ERROR, "wlanProbe: glBusInit() fail\n"); + i4Status = -EIO; + eFailReason = BUS_INIT_FAIL; + break; + } + /* 4 <2> Create network device, Adapter, KalInfo, + * prDevHandler(netdev) + */ + prWdev = wlanNetCreate(pvData, pvDriverData); + if (prWdev == NULL) { + DBGLOG(INIT, ERROR, + "wlanProbe: No memory for dev and its private\n"); + i4Status = -ENOMEM; + eFailReason = NET_CREATE_FAIL; + break; + } + /* 4 <2.5> Set the ioaddr to HIF Info */ + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(prWdev->wiphy); + if (prGlueInfo == NULL) { + DBGLOG(INIT, ERROR, + "wlanProbe: get wiphy_priv() fail\n"); + i4Status = -EFAULT; + break; + } + + gPrDev = prGlueInfo->prDevHandler; + + /* 4 <4> Setup IRQ */ + prWlandevInfo = &arWlanDevInfo[i4DevIdx]; + + i4Status = glBusSetIrq(prWdev->netdev, NULL, prGlueInfo); + + if (i4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "wlanProbe: Set IRQ error\n"); + eFailReason = BUS_SET_IRQ_FAIL; + break; + } + + prGlueInfo->i4DevIdx = i4DevIdx; + + prAdapter = prGlueInfo->prAdapter; + + prGlueInfo->u4ReadyFlag = 0; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + prAdapter->fgIsSupportCsumOffload = FALSE; + prAdapter->u4CSUMFlags = CSUM_OFFLOAD_EN_ALL; +#endif + +#if CFG_SUPPORT_CFG_FILE + wlanGetConfig(prAdapter); +#endif + + /* Init Chip Capability */ + prChipInfo = prAdapter->chip_info; + if (prChipInfo->asicCapInit) + prChipInfo->asicCapInit(prAdapter); + + + /* Default support 2.4/5G MIMO */ + prAdapter->rWifiFemCfg.u2WifiPath = ( + WLAN_FLAG_2G4_WF0 | WLAN_FLAG_5G_WF0 | + WLAN_FLAG_2G4_WF1 | WLAN_FLAG_5G_WF1); + +#if (MTK_WCN_HIF_SDIO && CFG_WMT_WIFI_PATH_SUPPORT) + i4RetVal = mtk_wcn_wmt_wifi_fem_cfg_report(( + void *)&prAdapter->rWifiFemCfg); + if (i4RetVal) + DBGLOG(INIT, ERROR, "Get WifiPath from WMT drv fail\n"); + else + DBGLOG(INIT, INFO, + "Get WifiPath from WMT drv success, WifiPath=0x%x\n", + prAdapter->rWifiFemCfg.u2WifiPath); +#endif + /* 4 <5> Start Device */ + prRegInfo = &prGlueInfo->rRegInfo; + + /* P_REG_INFO_T prRegInfo = (P_REG_INFO_T) kmalloc( + * sizeof(REG_INFO_T), GFP_KERNEL); + */ + kalMemSet(prRegInfo, 0, sizeof(struct REG_INFO)); + + /* Trigger the action of switching Pwr state to drv_own */ + prAdapter->fgIsFwOwn = TRUE; + + /* 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; +#if 0 + prRegInfo->fgEnArpFilter = TRUE; +#endif + /* The Init value of u4WpaVersion/u4AuthAlg shall be + * DISABLE/OPEN, not zero! + */ + /* The Init value of u4CipherGroup/u4CipherPairwise shall be + * NONE, not zero! + */ + prGlueInfo->rWpaInfo.u4WpaVersion = + IW_AUTH_WPA_VERSION_DISABLED; + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE; + + tasklet_init(&prGlueInfo->rRxTask, halRxTasklet, + (unsigned long)prGlueInfo); + tasklet_init(&prGlueInfo->rTxCompleteTask, + halTxCompleteTasklet, (unsigned long)prGlueInfo); + + if (wlanAdapterStart(prAdapter, + prRegInfo) != WLAN_STATUS_SUCCESS) + i4Status = -EIO; + + if (HAL_IS_TX_DIRECT(prAdapter)) { + if (!prAdapter->fgTxDirectInited) { + skb_queue_head_init( + &prAdapter->rTxDirectSkbQueue); + +#if KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE + timer_setup(&prAdapter->rTxDirectSkbTimer, + nicTxDirectTimerCheckSkbQ, 0); + + timer_setup(&prAdapter->rTxDirectHifTimer, + nicTxDirectTimerCheckHifQ, 0); +#else + init_timer(&prAdapter->rTxDirectSkbTimer); + prAdapter->rTxDirectSkbTimer.data = + (unsigned long)prGlueInfo; + prAdapter->rTxDirectSkbTimer.function = + nicTxDirectTimerCheckSkbQ; + + init_timer(&prAdapter->rTxDirectHifTimer); + prAdapter->rTxDirectHifTimer.data = + (unsigned long)prGlueInfo; + prAdapter->rTxDirectHifTimer.function = + nicTxDirectTimerCheckHifQ; +#endif + prAdapter->fgTxDirectInited = TRUE; + } + } + + /* kfree(prRegInfo); */ + + if (i4Status < 0) { + eFailReason = ADAPTER_START_FAIL; + break; + } + + INIT_WORK(&prGlueInfo->rTxMsduFreeWork, kalFreeTxMsduWorker); + + INIT_DELAYED_WORK(&prGlueInfo->rRxPktDeAggWork, + halDeAggRxPktWorker); + + + prGlueInfo->main_thread = kthread_run(main_thread, + prGlueInfo->prDevHandler, "main_thread"); +#if CFG_SUPPORT_MULTITHREAD + prGlueInfo->hif_thread = kthread_run(hif_thread, + prGlueInfo->prDevHandler, "hif_thread"); + prGlueInfo->rx_thread = kthread_run(rx_thread, + prGlueInfo->prDevHandler, "rx_thread"); + HAL_AGG_THREAD(prGlueInfo->prAdapter); +#endif + + + /* TODO the change schedule API shall be provided by OS glue + * layer + */ + /* Switch the Wi-Fi task priority to higher priority and change + * the scheduling method + */ + if (prGlueInfo->prAdapter->rWifiVar.ucThreadPriority > 0) { + struct sched_param param = { + .sched_priority = prGlueInfo->prAdapter + ->rWifiVar.ucThreadPriority + }; + sched_setscheduler(prGlueInfo->main_thread, + prGlueInfo->prAdapter->rWifiVar + .ucThreadScheduling, ¶m); +#if CFG_SUPPORT_MULTITHREAD + sched_setscheduler(prGlueInfo->hif_thread, + prGlueInfo->prAdapter->rWifiVar + .ucThreadScheduling, ¶m); + sched_setscheduler(prGlueInfo->rx_thread, + prGlueInfo->prAdapter->rWifiVar + .ucThreadScheduling, ¶m); +#endif + DBGLOG(INIT, INFO, + "Set pri = %d, sched = %d\n", + prGlueInfo->prAdapter->rWifiVar.ucThreadPriority, + prGlueInfo->prAdapter->rWifiVar + .ucThreadScheduling); + } + + g_u4HaltFlag = 0; + +#if CFG_SUPPORT_BUFFER_MODE +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1) + if (prChipInfo->downloadBufferBin) { + if (prChipInfo->downloadBufferBin(prAdapter) != + WLAN_STATUS_SUCCESS){ + DBGLOG(INIT, ERROR, + "wlanProbe: downloadBufferBin fail\n"); + return -1; + } + } +#endif +#endif + +#if CFG_SUPPORT_DBDC + /* Update DBDC default setting */ + cnmInitDbdcSetting(prAdapter); +#endif /*CFG_SUPPORT_DBDC*/ + + /* send regulatory information to firmware */ + rlmDomainSendInfoToFirmware(prAdapter); + + /* set MAC address */ + { + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct sockaddr MacAddr; + uint32_t u4SetInfoLen = 0; + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryCurrentAddr, + &MacAddr.sa_data, PARAM_MAC_ADDR_LEN, + TRUE, TRUE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, WARN, "set MAC addr fail 0x%x\n", + rStatus); + } else { + kalMemCopy(prGlueInfo->prDevHandler->dev_addr, + &MacAddr.sa_data, ETH_ALEN); + kalMemCopy(prGlueInfo->prDevHandler->perm_addr, + prGlueInfo->prDevHandler->dev_addr, + ETH_ALEN); + +#if CFG_SHOW_MACADDR_SOURCE + DBGLOG(INIT, INFO, "MAC address: " MACSTR, + MAC2STR(prAdapter->rWifiVar.aucMacAddress)); +#endif + } + } + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + /* set HW checksum offload */ + if (prAdapter->fgIsSupportCsumOffload) { + uint32_t rStatus = WLAN_STATUS_FAILURE; + uint32_t u4CSUMFlags = CSUM_OFFLOAD_EN_ALL; + uint32_t u4SetInfoLen = 0; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetCSUMOffload, + (void *) &u4CSUMFlags, + sizeof(uint32_t), + FALSE, FALSE, TRUE, &u4SetInfoLen); + + if (rStatus == WLAN_STATUS_SUCCESS) { + prGlueInfo->prDevHandler->features = + NETIF_F_IP_CSUM | + NETIF_F_IPV6_CSUM | + NETIF_F_RXCSUM; + } else { + DBGLOG(INIT, WARN, + "set HW checksum offload fail 0x%x\n", + rStatus); + prAdapter->fgIsSupportCsumOffload = FALSE; + } + } +#endif +#if CFG_SUPPORT_802_11K + { + uint32_t rStatus = WLAN_STATUS_FAILURE; + uint32_t u4SetInfoLen = 0; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSync11kCapabilities, NULL, 0, + FALSE, FALSE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, WARN, + "RRM: Set 11k Capabilities fail 0x%x\n", + rStatus); + } +#endif + + /* 4 <3> Register the card */ + i4DevIdx = wlanNetRegister(prWdev); + if (i4DevIdx < 0) { + i4Status = -ENXIO; + DBGLOG(INIT, ERROR, + "wlanProbe: Cannot register the net_device context to the kernel\n"); + eFailReason = NET_REGISTER_FAIL; + break; + } + /* 4 <4> Register early suspend callback */ +#if CFG_ENABLE_EARLY_SUSPEND + glRegisterEarlySuspend(&wlan_early_suspend_desc, + wlan_early_suspend, wlan_late_resume); +#endif + + /* 4 <5> Register Notifier callback */ + wlanRegisterNotifier(); + + /* 4 <6> Initialize /proc filesystem */ +#if WLAN_INCLUDE_PROC + i4Status = procCreateFsEntry(prGlueInfo); + if (i4Status < 0) { + DBGLOG(INIT, ERROR, "wlanProbe: init procfs failed\n"); + eFailReason = PROC_INIT_FAIL; + break; + } +#endif /* WLAN_INCLUDE_PROC */ + +#if CFG_MET_PACKET_TRACE_SUPPORT + kalMetInit(prGlueInfo); +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + prGlueInfo->rBowInfo.fgIsNetRegistered = FALSE; + prGlueInfo->rBowInfo.fgIsRegistered = FALSE; + glRegisterAmpc(prGlueInfo); +#endif + +#if (CFG_ENABLE_WIFI_DIRECT && CFG_MTK_ANDROID_WMT) + register_set_p2p_mode_handler(set_p2p_mode_handler); +#elif (CFG_ENABLE_WIFI_DIRECT) + if (prAdapter->rWifiVar.u4RegP2pIfAtProbe) { + struct PARAM_CUSTOM_P2P_SET_STRUCT rSetP2P; + + rSetP2P.u4Enable = 1; + +#ifdef CFG_DRIVER_INITIAL_RUNNING_MODE + rSetP2P.u4Mode = CFG_DRIVER_INITIAL_RUNNING_MODE; +#else + rSetP2P.u4Mode = RUNNING_P2P_MODE; +#endif /* CFG_DRIVER_RUNNING_MODE */ + if (set_p2p_mode_handler(prWdev->netdev, rSetP2P) == 0) + DBGLOG(INIT, INFO, + "%s: p2p device registered\n", + __func__); + else + DBGLOG(INIT, ERROR, + "%s: Failed to register p2p device\n", + __func__); + } +#endif +#if (CFG_MET_PACKET_TRACE_SUPPORT == 1) + DBGLOG(INIT, TRACE, "init MET procfs...\n"); + i4Status = kalMetInitProcfs(prGlueInfo); + if (i4Status < 0) { + DBGLOG(INIT, ERROR, + "wlanProbe: init MET procfs failed\n"); + eFailReason = FAIL_MET_INIT_PROCFS; + break; + } +#endif + kalMemZero(&prGlueInfo->rFtIeForTx, + sizeof(prGlueInfo->rFtIeForTx)); + + /* Configure 5G band for registered wiphy */ + if (prAdapter->fgEnable5GBand) + prWdev->wiphy->bands[KAL_BAND_5GHZ] = &mtk_band_5ghz; + else + prWdev->wiphy->bands[KAL_BAND_5GHZ] = NULL; + + for (i = 0 ; i < KAL_P2P_NUM; i++) { + if (gprP2pRoleWdev[i] == NULL) + continue; + + if (prAdapter->fgEnable5GBand) + gprP2pRoleWdev[i]->wiphy->bands[KAL_BAND_5GHZ] = + &mtk_band_5ghz; + else + gprP2pRoleWdev[i]->wiphy->bands[KAL_BAND_5GHZ] = + NULL; + } + } while (FALSE); + + if (i4Status == 0) { +#if CFG_SUPPORT_AGPS_ASSIST + kalIndicateAgpsNotify(prAdapter, AGPS_EVENT_WLAN_ON, NULL, + 0); +#endif +#if CFG_SUPPORT_EASY_DEBUG + /* move before reading file + * wlanLoadDefaultCustomerSetting(prAdapter); + */ + wlanFeatureToFw(prGlueInfo->prAdapter); +#endif + wlanCfgSetSwCtrl(prGlueInfo->prAdapter); + wlanCfgSetChip(prGlueInfo->prAdapter); + wlanCfgSetCountryCode(prGlueInfo->prAdapter); + kalPerMonInit(prGlueInfo); +#if CFG_MET_TAG_SUPPORT + if (met_tag_init() != 0) + DBGLOG(INIT, ERROR, "MET_TAG_INIT error!\n"); +#endif + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST + /* Calibration Backup Flow */ + if (!g_fgIsCalDataBackuped) { + if (rlmTriggerCalBackup(prGlueInfo->prAdapter, + g_fgIsCalDataBackuped) == WLAN_STATUS_FAILURE) { + DBGLOG(RFTEST, INFO, + "Error : Boot Time Wi-Fi Enable Fail........\n"); + return -1; + } + + g_fgIsCalDataBackuped = TRUE; + } else { + if (rlmTriggerCalBackup(prGlueInfo->prAdapter, + g_fgIsCalDataBackuped) == WLAN_STATUS_FAILURE) { + DBGLOG(RFTEST, INFO, + "Error : Normal Wi-Fi Enable Fail........\n"); + return -1; + } + } +#endif + +#if CFG_SUPPORT_REPLAY_DETECTION + ucRpyDetectOffload = prAdapter->rWifiVar.ucRpyDetectOffload; + + if (ucRpyDetectOffload == FEATURE_ENABLED) { + DBGLOG(INIT, INFO, + "Send CMD to enable Replay Detection offload feature\n"); + wlanSuspendRekeyOffload(prAdapter->prGlueInfo, + GTK_REKEY_CMD_MODE_RPY_OFFLOAD_ON); + } else { + DBGLOG(INIT, INFO, + "Send CMD to disable Replay Detection offload feature\n"); + wlanSuspendRekeyOffload(prAdapter->prGlueInfo, + GTK_REKEY_CMD_MODE_RPY_OFFLOAD_OFF); + } +#endif + + /* card is ready */ + prGlueInfo->u4ReadyFlag = 1; + + kalSetHalted(FALSE); + wlanDbgGetGlobalLogLevel(ENUM_WIFI_LOG_MODULE_FW, + &u4LogLevel); + if (u4LogLevel > ENUM_WIFI_LOG_LEVEL_DEFAULT) + wlanDbgSetLogLevelImpl(prAdapter, + ENUM_WIFI_LOG_LEVEL_VERSION_V1, + ENUM_WIFI_LOG_MODULE_FW, + u4LogLevel); + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + /* sync log status with firmware */ + if (u4LogOnOffCache != -1) /* -1: connsysD does not set */ + consys_log_event_notification((int)FW_LOG_CMD_ON_OFF, + u4LogOnOffCache); +#endif + DBGLOG(INIT, STATE, "wlanProbe: probe success\n"); +#if CFG_CHIP_RESET_HANG + if (fgIsResetHangState == SER_L0_HANG_RST_TRGING) { + DBGLOG(INIT, STATE, "[SER][L0] SET SQC hang!\n"); + fgIsResetHangState = SER_L0_HANG_RST_HANG; + fgIsResetting = TRUE; + } +#endif + + } else { + DBGLOG(INIT, ERROR, "wlanProbe: probe failed, reason:%d\n", + eFailReason); + switch (eFailReason) { + case FAIL_MET_INIT_PROCFS: + kalMetRemoveProcfs(); + case PROC_INIT_FAIL: + wlanNetUnregister(prWdev); + case NET_REGISTER_FAIL: + set_bit(GLUE_FLAG_HALT_BIT, &prGlueInfo->ulFlag); + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + /* wait main thread stops */ + wait_for_completion_interruptible( + &prGlueInfo->rHaltComp); + wlanAdapterStop(prAdapter); + /* fallthrough */ + case ADAPTER_START_FAIL: + glBusFreeIrq(prWdev->netdev, + *((struct GLUE_INFO **) + netdev_priv(prWdev->netdev))); + /* fallthrough */ + case BUS_SET_IRQ_FAIL: + wlanWakeLockUninit(prGlueInfo); + wlanNetDestroy(prWdev); + /* prGlueInfo->prAdapter is released in + * wlanNetDestroy + */ + /* Set NULL value for local prAdapter as well */ + prAdapter = NULL; + break; + case NET_CREATE_FAIL: + break; + case BUS_INIT_FAIL: + break; + default: + break; + } + } +#if CFG_THERMAL_API_SUPPORT + if (i4Status == 0) + g_fgIsWifiEnabled = TRUE; + + pbridge.thermal_query_cb = mtk_wcn_temp_query_ctrl; + wcn_export_platform_bridge_register(&pbridge); +#endif + + 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; + struct WLANDEV_INFO *prWlandevInfo = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + u_int8_t fgResult = FALSE; + + DBGLOG(INIT, STATE, "Remove wlan!\n"); + + kalSetHalted(TRUE); + + /* 4 <0> Sanity check */ + ASSERT(u4WlanDevNum <= CFG_MAX_WLAN_DEVICES); + if (u4WlanDevNum == 0) { + DBGLOG(INIT, ERROR, "u4WlanDevNum = 0\n"); + return; + } +#if (CFG_ENABLE_WIFI_DIRECT && CFG_MTK_ANDROID_WMT) + register_set_p2p_mode_handler(NULL); +#endif + if (u4WlanDevNum > 0 + && u4WlanDevNum <= CFG_MAX_WLAN_DEVICES) { + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + prWlandevInfo = &arWlanDevInfo[u4WlanDevNum - 1]; + } + + ASSERT(prDev); + if (prDev == NULL) { + DBGLOG(INIT, ERROR, "prDev is NULL\n"); + return; + } + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + ASSERT(prGlueInfo); + if (prGlueInfo == NULL) { + DBGLOG(INIT, STATE, "prGlueInfo is NULL\n"); + free_netdev(prDev); + return; + } + + /* to avoid that wpa_supplicant/hostapd triogger new cfg80211 command */ + prGlueInfo->u4ReadyFlag = 0; + + /* Have tried to do scan done here, but the exception occurs for */ + /* the P2P scan. Keep the original design that scan done in the */ + /* p2pStop/wlanStop. */ + +#if WLAN_INCLUDE_PROC + procRemoveProcfs(); +#endif /* WLAN_INCLUDE_PROC */ + + prAdapter = prGlueInfo->prAdapter; + kalPerMonDestroy(prGlueInfo); + +#if CFG_SUPPORT_SER +#if defined(_HIF_USB) + cnmTimerStopTimer(prAdapter, &prAdapter->rSerSyncTimer); +#endif /* _HIF_USB */ +#endif /* CFG_SUPPORT_SER */ + + /* complete possible pending oid, which may block wlanRemove some time + * and then whole chip reset may failed + */ + if (kalIsResetting()) + wlanReleasePendingOid(prGlueInfo->prAdapter, 1); + +#if CFG_ENABLE_BT_OVER_WIFI + if (prGlueInfo->rBowInfo.fgIsNetRegistered) { + bowNotifyAllLinkDisconnected(prGlueInfo->prAdapter); + /* wait 300ms for BoW module to send deauth */ + kalMsleep(300); + } +#endif + + if (prGlueInfo->eParamMediaStateIndicated == + PARAM_MEDIA_STATE_CONNECTED) { + +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 2, 0) <= CFG80211_VERSION_CODE) + cfg80211_disconnected(prGlueInfo->prDevHandler, 0, NULL, 0, + TRUE, GFP_KERNEL); +#else + cfg80211_disconnected(prGlueInfo->prDevHandler, 0, NULL, 0, + GFP_KERNEL); +#endif + kalMsleep(500); + } + + flush_delayed_work(&workq); + + /* 20150205 work queue for sched_scan */ + + flush_delayed_work(&sched_workq); + + down(&g_halt_sem); + g_u4HaltFlag = 1; + up(&g_halt_sem); + + /* 4 <2> Mark HALT, notify main thread to stop, and clean up queued + * requests + */ + set_bit(GLUE_FLAG_HALT_BIT, &prGlueInfo->ulFlag); + + /* Stop works */ + flush_work(&prGlueInfo->rTxMsduFreeWork); + cancel_delayed_work_sync(&prGlueInfo->rRxPktDeAggWork); + +#if CFG_SUPPORT_MULTITHREAD + wake_up_interruptible(&prGlueInfo->waitq_hif); + wait_for_completion_interruptible( + &prGlueInfo->rHifHaltComp); + HAL_AGG_THREAD_WAKE_UP(prGlueInfo->prAdapter); + wake_up_interruptible(&prGlueInfo->waitq_rx); + wait_for_completion_interruptible(&prGlueInfo->rRxHaltComp); +#endif + + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + /* wait main thread stops */ + wait_for_completion_interruptible(&prGlueInfo->rHaltComp); + + DBGLOG(INIT, INFO, "wlan thread stopped\n"); + + /* prGlueInfo->rHifInfo.main_thread = NULL; */ + prGlueInfo->main_thread = NULL; +#if CFG_SUPPORT_MULTITHREAD + prGlueInfo->hif_thread = NULL; + prGlueInfo->rx_thread = NULL; + + prGlueInfo->u4TxThreadPid = 0xffffffff; + prGlueInfo->u4HifThreadPid = 0xffffffff; +#endif + + if (HAL_IS_TX_DIRECT(prAdapter)) { + if (prAdapter->fgTxDirectInited) { + del_timer_sync(&prAdapter->rTxDirectSkbTimer); + del_timer_sync(&prAdapter->rTxDirectHifTimer); + } + } + + /* Destroy wakelock */ + wlanWakeLockUninit(prGlueInfo); + + kalMemSet(&(prGlueInfo->prAdapter->rWlanInfo), 0, + sizeof(struct WLAN_INFO)); + +#if CFG_ENABLE_WIFI_DIRECT + if (prGlueInfo->prAdapter->fgIsP2PRegistered) { + DBGLOG(INIT, INFO, "p2pNetUnregister...\n"); + p2pNetUnregister(prGlueInfo, FALSE); + DBGLOG(INIT, INFO, "p2pRemove...\n"); + /*p2pRemove must before wlanAdapterStop */ + p2pRemove(prGlueInfo); + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + if (prGlueInfo->rBowInfo.fgIsRegistered) + glUnregisterAmpc(prGlueInfo); +#endif + +#if (CFG_MET_PACKET_TRACE_SUPPORT == 1) + kalMetRemoveProcfs(); +#endif + +#if CFG_MET_TAG_SUPPORT + if (GL_MET_TAG_UNINIT() != 0) + DBGLOG(INIT, ERROR, "MET_TAG_UNINIT error!\n"); +#endif + + /* 4 <4> wlanAdapterStop */ +#if CFG_SUPPORT_AGPS_ASSIST + kalIndicateAgpsNotify(prAdapter, AGPS_EVENT_WLAN_OFF, NULL, + 0); +#endif + + wlanAdapterStop(prAdapter); + + HAL_LP_OWN_SET(prAdapter, &fgResult); + DBGLOG(INIT, INFO, "HAL_LP_OWN_SET(%d)\n", + (uint32_t) fgResult); + + /* 4 Stopping handling interrupt and free IRQ */ + glBusFreeIrq(prDev, prGlueInfo); + + /* 4 <5> Release the Bus */ + glBusRelease(prDev); + +#if (CFG_SUPPORT_TRACE_TC4 == 1) + wlanDebugTC4Uninit(); +#endif + /* 4 <6> Unregister the card */ + wlanNetUnregister(prDev->ieee80211_ptr); + + /* 4 <7> Destroy the device */ + wlanNetDestroy(prDev->ieee80211_ptr); + prDev = NULL; + + tasklet_kill(&prGlueInfo->rTxCompleteTask); + tasklet_kill(&prGlueInfo->rRxTask); + + /* 4 <8> Unregister early suspend callback */ +#if CFG_ENABLE_EARLY_SUSPEND + glUnregisterEarlySuspend(&wlan_early_suspend_desc); +#endif + + gprWdev->netdev = NULL; + + /* 4 <9> Unregister notifier callback */ + wlanUnregisterNotifier(); + +#if CFG_CHIP_RESET_SUPPORT & !CFG_WMT_RESET_API_SUPPORT + fgIsResetting = FALSE; +#endif +#if CFG_THERMAL_API_SUPPORT + g_fgIsWifiEnabled = FALSE; + wcn_export_platform_bridge_unregister(); +#endif + + DBGLOG(INIT, STATE, "end\n"); + +} /* end of wlanRemove() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Driver entry point when the driver is configured as a Linux Module, + * and is called once at module load time, by the user-level modutils + * application: insmod or modprobe. + * + * \retval 0 Success + */ +/*----------------------------------------------------------------------------*/ +/* 1 Module Entry Point */ +static int initWlan(void) +{ + int ret = 0; + struct GLUE_INFO *prGlueInfo = NULL; + + DBGLOG(INIT, INFO, "initWlan\n"); + +#ifdef CFG_DRIVER_INF_NAME_CHANGE + + if (kalStrLen(gprifnamesta) > CUSTOM_IFNAMESIZ || + kalStrLen(gprifnamep2p) > CUSTOM_IFNAMESIZ || + kalStrLen(gprifnameap) > CUSTOM_IFNAMESIZ) { + DBGLOG(INIT, ERROR, "custom infname len illegal > %d\n", + CUSTOM_IFNAMESIZ); + return -EINVAL; + } + +#endif /* CFG_DRIVER_INF_NAME_CHANGE */ + + wlanDebugInit(); + + /* memory pre-allocation */ +#if CFG_PRE_ALLOCATION_IO_BUFFER + kalInitIOBuffer(TRUE); +#else + kalInitIOBuffer(FALSE); +#endif + + +#if WLAN_INCLUDE_PROC + procInitFs(); +#endif + + wlanCreateWirelessDevice(); + if (gprWdev == NULL) + return -ENOMEM; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv( + gprWdev->wiphy); + if (gprWdev) { + /* P2PDev and P2PRole[0] share the same Wdev */ + if (glP2pCreateWirelessDevice(prGlueInfo) == TRUE) + gprP2pWdev = gprP2pRoleWdev[0]; + } + gPrDev = NULL; + + ret = ((glRegisterBus(wlanProbe, + wlanRemove) == WLAN_STATUS_SUCCESS) ? 0 : -EIO); + + if (ret == -EIO) { + kalUninitIOBuffer(); + return ret; + } +#if (CFG_CHIP_RESET_SUPPORT) + glResetInit(prGlueInfo); +#endif + kalFbNotifierReg((struct GLUE_INFO *) wiphy_priv( + gprWdev->wiphy)); + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH + wifi_fwlog_event_func_register(consys_log_event_notification); +#endif + +#if CFG_MTK_ANDROID_EMI + /* Set WIFI EMI protection to consys permitted on system boot up */ + kalSetEmiMpuProtection(gConEmiPhyBase, WIFI_EMI_MEM_OFFSET, + WIFI_EMI_MEM_SIZE, true); +#endif + return ret; +} /* end of initWlan() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Driver exit point when the driver as a Linux Module is removed. Called + * at module unload time, by the user level modutils application: rmmod. + * This is our last chance to clean up after ourselves. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +/* 1 Module Leave Point */ +static void exitWlan(void) +{ + kalFbNotifierUnReg(); +#if CFG_CHIP_RESET_SUPPORT + glResetUninit(); +#endif + + glUnregisterBus(wlanRemove); + + /* free pre-allocated memory */ + kalUninitIOBuffer(); + + /* For single wiphy case, it's hardly to free wdev & wiphy in 2 func. + * So that, use wlanDestroyAllWdev to replace wlanDestroyWirelessDevice + * and glP2pDestroyWirelessDevice. + */ + wlanDestroyAllWdev(); + +#if WLAN_INCLUDE_PROC + procUninitProcFs(); +#endif + DBGLOG(INIT, INFO, "exitWlan\n"); + +} /* end of exitWlan() */ + +#if CFG_THERMAL_API_SUPPORT + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief export API for thermal +* +* \retval >0 Success +* \retval -1000 invalid +*/ +/*----------------------------------------------------------------------------*/ +static int mtk_wcn_temp_query_ctrl(void) +{ + struct net_device *prDev = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + int i4Temperature = 0; +#ifdef CFG_GET_TEMPURATURE + uint32_t u4BufLen; + uint32_t rStatus = WLAN_STATUS_SUCCESS; +#endif + /* 1. check if wifi is enabled */ + if (!g_fgIsWifiEnabled) + return -1000; + + ASSERT(u4WlanDevNum <= CFG_MAX_WLAN_DEVICES); + if (u4WlanDevNum == 0) { + DBGLOG(INIT, INFO, "0 == u4WlanDevNum\n"); + return -1000; + } + + if (u4WlanDevNum > 0 && u4WlanDevNum <= CFG_MAX_WLAN_DEVICES) + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + + ASSERT(prDev); + if (prDev == NULL) { + DBGLOG(INIT, INFO, "NULL == prDev\n"); + return -1000; + } + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + ASSERT(prGlueInfo); + if (prGlueInfo == NULL) { + DBGLOG(INIT, INFO, "NULL == prGlueInfo\n"); + return -1000; + } + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); +#ifdef CFG_GET_TEMPURATURE + rStatus = kalIoctl(prGlueInfo, + wlanoidGetTemperature, + &i4Temperature, + sizeof(i4Temperature), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "Query ucTemperature failed!\n"); + return -1000; + } +#else + return -1000; +#endif + return i4Temperature; + +} +#endif + +#if ((MTK_WCN_HIF_SDIO == 1) && (CFG_BUILT_IN_DRIVER == 1)) || \ + ((MTK_WCN_HIF_AXI == 1) && (CFG_BUILT_IN_DRIVER == 1)) + +int mtk_wcn_wlan_gen4_init(void) +{ + return initWlan(); +} +EXPORT_SYMBOL(mtk_wcn_wlan_gen4_init); + +void mtk_wcn_wlan_gen4_exit(void) +{ + return exitWlan(); +} +EXPORT_SYMBOL(mtk_wcn_wlan_gen4_exit); + +#elif ((MTK_WCN_HIF_SDIO == 0) && (CFG_BUILT_IN_DRIVER == 1)) + +device_initcall(initWlan); + +#else + +module_init(initWlan); +module_exit(exitWlan); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_kal.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_kal.c new file mode 100644 index 0000000000000..c39af683a13d6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_kal.c @@ -0,0 +1,8508 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux + * /gl_kal.c#10 + */ + +/*! \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. + */ + + +/******************************************************************************* + * C O M P I L E 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 "gl_wext.h" +#include "precomp.h" +#if CFG_SUPPORT_AGPS_ASSIST +#include +#endif +#if CFG_SUPPORT_MTK_CPU_SCHED +#include +#include +#endif +#ifdef CONFIG_IDME +#include +#endif + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +/* the maximum length of a file name */ +#define FILE_NAME_MAX CFG_FW_NAME_MAX_LEN + +/* the maximum number of all possible file name */ +#define FILE_NAME_TOTAL 8 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +#if DBG +int allocatedMemSize; +#endif + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +static void *pvIoBuffer; +static uint32_t pvIoBufferSize; +static uint32_t pvIoBufferUsage; + +static struct KAL_HALT_CTRL_T rHaltCtrl = { + .lock = __SEMAPHORE_INITIALIZER(rHaltCtrl.lock, 1), + .owner = NULL, + .fgHalt = TRUE, + .fgHeldByKalIoctl = FALSE, + .u4HoldStart = 0, +}; +/* framebuffer callback related variable and status flag */ +u_int8_t wlan_fb_power_down = FALSE; + +#if CFG_FORCE_ENABLE_PERF_MONITOR +u_int8_t wlan_perf_monitor_force_enable = TRUE; +#else +u_int8_t wlan_perf_monitor_force_enable = FALSE; +#endif + +#if CFG_ENABLE_WAKE_LOCK +static KAL_WAKE_LOCK_T rRxThreadWakeLock; +static KAL_WAKE_LOCK_T rHifThreadWakeLock; +static KAL_WAKE_LOCK_T rTxThreadWakeLock; +#endif + +static struct notifier_block wlan_fb_notifier; +void *wlan_fb_notifier_priv_data; +u_int8_t g_fgIsOid = TRUE; +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#if CFG_ENABLE_FW_DOWNLOAD + +#if (defined(CONFIG_UIDGID_STRICT_TYPE_CHECKS) || \ + (KERNEL_VERSION(3, 14, 0) <= LINUX_VERSION_CODE)) +#define KUIDT_VALUE(v) (v.val) +#define KGIDT_VALUE(v) (v.val) +#else +#define KUIDT_VALUE(v) v +#define KGIDT_VALUE(v) v +#endif + +const struct firmware *fw_entry; + +/* Default */ +static uint8_t *apucFwName[] = { + (uint8_t *) CFG_FW_FILENAME "_MT", + NULL +}; + +static uint8_t *apucCr4FwName[] = { + (uint8_t *) CFG_CR4_FW_FILENAME "_" HIF_NAME "_MT", + (uint8_t *) CFG_CR4_FW_FILENAME "_MT", + NULL +}; + +#if CFG_ASSERT_DUMP +/* Core dump debug usage */ +#if MTK_WCN_HIF_SDIO +uint8_t *apucCorDumpN9FileName = + "/data/misc/wifi/FW_DUMP_N9"; +uint8_t *apucCorDumpCr4FileName = + "/data/misc/wifi/FW_DUMP_Cr4"; +#else +uint8_t *apucCorDumpN9FileName = "/tmp/FW_DUMP_N9"; +uint8_t *apucCorDumpCr4FileName = "/tmp/FW_DUMP_Cr4"; +#endif +#endif +/*----------------------------------------------------------------------------*/ +/*! + * \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. + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t kalFirmwareOpen(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t **apucNameTable) +{ + uint8_t ucNameIdx; + /* PPUINT_8 apucNameTable; */ + uint8_t ucCurEcoVer = wlanGetEcoVersion( + prGlueInfo->prAdapter); + u_int8_t fgResult = FALSE; + int ret; + + /* Try to open FW binary */ + for (ucNameIdx = 0; apucNameTable[ucNameIdx]; ucNameIdx++) { + /* + * Driver support request_firmware() to get files + * Android path: "/etc/firmware", "/vendor/firmware", + * "/firmware/image" + * Linux path: "/lib/firmware", "/lib/firmware/update" + */ + ret = request_firmware(&fw_entry, apucNameTable[ucNameIdx], + prGlueInfo->prDev); + + if (ret) { + DBGLOG(INIT, ERROR, + "Request FW image: %s failed, errno[%d]\n", + apucNameTable[ucNameIdx], fgResult); + continue; + } else { + DBGLOG(INIT, TRACE, "Request FW image: %s done\n", + apucNameTable[ucNameIdx]); + fgResult = TRUE; + break; + } + } + + + /* Check result */ + if (!fgResult) + goto error_open; + + + return WLAN_STATUS_SUCCESS; + +error_open: + DBGLOG(INIT, ERROR, + "Request FW image failed! Cur ECO Ver[E%u]\n", + ucCurEcoVer); + + 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. + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t kalFirmwareClose(IN struct GLUE_INFO *prGlueInfo) +{ + release_firmware(fw_entry); + + 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. + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t kalFirmwareLoad(IN struct GLUE_INFO *prGlueInfo, + OUT void *prBuf, IN uint32_t u4Offset, + OUT uint32_t *pu4Size) +{ + ASSERT(prGlueInfo); + ASSERT(pu4Size); + ASSERT(prBuf); + + if ((fw_entry == NULL) || (fw_entry->size == 0) + || (fw_entry->data == NULL)) { + goto error_read; + } else { + memcpy(prBuf, fw_entry->data, fw_entry->size); + *pu4Size = fw_entry->size; + } + + 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. + * + */ +/*----------------------------------------------------------------------------*/ + +uint32_t kalFirmwareSize(IN struct GLUE_INFO *prGlueInfo, + OUT uint32_t *pu4Size) +{ + ASSERT(prGlueInfo); + ASSERT(pu4Size); + + *pu4Size = fw_entry->size; + + return WLAN_STATUS_SUCCESS; +} + +void +kalConstructDefaultFirmwarePrio(struct GLUE_INFO + *prGlueInfo, uint8_t **apucNameTable, + uint8_t **apucName, uint8_t *pucNameIdx, + uint8_t ucMaxNameIdx) +{ + struct mt66xx_chip_info *prChipInfo = + prGlueInfo->prAdapter->chip_info; + uint32_t chip_id = prChipInfo->chip_id; + uint8_t sub_idx = 0; + + for (sub_idx = 0; apucNameTable[sub_idx]; sub_idx++) { + if ((*pucNameIdx + 3) < ucMaxNameIdx) { + /* Type 1. WIFI_RAM_CODE_MTxxxx */ + snprintf(*(apucName + (*pucNameIdx)), FILE_NAME_MAX, + "%s%x", apucNameTable[sub_idx], chip_id); + (*pucNameIdx) += 1; + + /* Type 2. WIFI_RAM_CODE_MTxxxx.bin */ + snprintf(*(apucName + (*pucNameIdx)), FILE_NAME_MAX, + "%s%x.bin", + apucNameTable[sub_idx], chip_id); + (*pucNameIdx) += 1; + + /* Type 3. WIFI_RAM_CODE_MTxxxx_Ex */ + snprintf(*(apucName + (*pucNameIdx)), FILE_NAME_MAX, + "%s%x_E%u", + apucNameTable[sub_idx], chip_id, + wlanGetEcoVersion(prGlueInfo->prAdapter)); + (*pucNameIdx) += 1; + + /* Type 4. WIFI_RAM_CODE_MTxxxx_Ex.bin */ + snprintf(*(apucName + (*pucNameIdx)), FILE_NAME_MAX, + "%s%x_E%u.bin", + apucNameTable[sub_idx], chip_id, + wlanGetEcoVersion(prGlueInfo->prAdapter)); + (*pucNameIdx) += 1; + } else { + /* the table is not large enough */ + DBGLOG(INIT, ERROR, + "kalFirmwareImageMapping >> file name array is not enough.\n"); + ASSERT(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 + */ +/*----------------------------------------------------------------------------*/ + +void * +kalFirmwareImageMapping(IN struct GLUE_INFO *prGlueInfo, + OUT void **ppvMapFileBuf, OUT uint32_t *pu4FileLength, + IN enum ENUM_IMG_DL_IDX_T eDlIdx) +{ + uint8_t **apucNameTable = NULL; + uint8_t *apucName[FILE_NAME_TOTAL + + 1]; /* extra +1, for the purpose of + * detecting the end of the array + */ + uint8_t idx = 0, max_idx, ucRomVer = 0, + aucNameBody[FILE_NAME_TOTAL][FILE_NAME_MAX], sub_idx = 0; + struct mt66xx_chip_info *prChipInfo = + prGlueInfo->prAdapter->chip_info; + uint32_t chip_id = prChipInfo->chip_id; + + DEBUGFUNC("kalFirmwareImageMapping"); + + ASSERT(prGlueInfo); + ASSERT(ppvMapFileBuf); + ASSERT(pu4FileLength); + + *ppvMapFileBuf = NULL; + *pu4FileLength = 0; + + do { + /* <0.0> Get FW name prefix table */ + switch (eDlIdx) { + case IMG_DL_IDX_N9_FW: + apucNameTable = apucFwName; + break; + + case IMG_DL_IDX_CR4_FW: + apucNameTable = apucCr4FwName; + break; + + case IMG_DL_IDX_PATCH: + break; + + default: + ASSERT(0); + break; + } + + /* <0.2> Construct FW name */ + memset(apucName, 0, sizeof(apucName)); + + /* magic number 1: reservation for detection + * of the end of the array + */ + max_idx = (sizeof(apucName) / sizeof(uint8_t *)) - 1; + + idx = 0; + apucName[idx] = (uint8_t *)(aucNameBody + idx); + + if (eDlIdx == IMG_DL_IDX_PATCH) { + /* construct the file name for patch */ + + /* mtxxxx_patch_ex_hdr.bin*/ + if (prChipInfo->fw_dl_ops->constructPatchName) + prChipInfo->fw_dl_ops->constructPatchName( + prGlueInfo, apucName, &idx); + else { + ucRomVer = wlanGetRomVersion( + prGlueInfo->prAdapter) + 1; + snprintf(apucName[idx], FILE_NAME_MAX, + "mt%x_patch_e%u_hdr.bin", chip_id, + ucRomVer); + } + idx += 1; + } else { + for (sub_idx = 0; sub_idx < max_idx; sub_idx++) + apucName[sub_idx] = + (uint8_t *)(aucNameBody + sub_idx); + + if (prChipInfo->fw_dl_ops->constructFirmwarePrio) + prChipInfo->fw_dl_ops->constructFirmwarePrio( + prGlueInfo, apucNameTable, apucName, + &idx, max_idx); + else + kalConstructDefaultFirmwarePrio( + prGlueInfo, apucNameTable, apucName, + &idx, max_idx); + } + + /* let the last pointer point to NULL + * so that we can detect the end of the array in + * kalFirmwareOpen(). + */ + apucName[idx] = NULL; + + apucNameTable = apucName; + + /* <1> Open firmware */ + if (kalFirmwareOpen(prGlueInfo, + apucNameTable) != WLAN_STATUS_SUCCESS) + break; + { + uint32_t u4FwSize = 0; + void *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 struct GLUE_INFO + *prGlueInfo, IN void *prFwHandle, IN void *pvMapFileBuf) +{ + DEBUGFUNC("kalFirmwareImageUnmapping"); + + ASSERT(prGlueInfo); + + /* pvMapFileBuf might be NULL when file doesn't exist */ + if (pvMapFileBuf) + vfree(pvMapFileBuf); + + kalFirmwareClose(prGlueInfo); +} +#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 struct GLUE_INFO *prGlueInfo, + IN enum ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, + OUT unsigned long *plFlags) +{ + unsigned long ulFlags = 0; + + ASSERT(prGlueInfo); + ASSERT(plFlags); + + if (rLockCategory < SPIN_LOCK_NUM) { + DBGLOG(INIT, LOUD, "SPIN_LOCK[%u] Try to acquire\n", + rLockCategory); +#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], + ulFlags); +#endif /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + + *plFlags = ulFlags; + + DBGLOG(INIT, LOUD, "SPIN_LOCK[%u] Acquired\n", + rLockCategory); + } + +} /* end of kalAcquireSpinLock() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is provided by GLUE Layer for internal driver stack to + * release OS SPIN_LOCK. + * + * \param[in] prGlueInfo Pointer of GLUE Data Structure + * \param[in] rLockCategory Specify which SPIN_LOCK + * \param[in] u4Flags Saved IRQ flags + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void kalReleaseSpinLock(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, + IN unsigned long ulFlags) +{ + 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], ulFlags); +#endif /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + DBGLOG(INIT, LOUD, "SPIN_UNLOCK[%u]\n", rLockCategory); + } + +} /* end of kalReleaseSpinLock() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is provided by GLUE Layer for internal driver stack to + * acquire OS MUTEX. + * + * \param[in] prGlueInfo Pointer of GLUE Data Structure + * \param[in] rMutexCategory Specify which MUTEX + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void kalAcquireMutex(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_MUTEX_CATEGORY_E rMutexCategory) +{ + ASSERT(prGlueInfo); + + if (rMutexCategory < MUTEX_NUM) { + DBGLOG(INIT, TEMP, + "MUTEX_LOCK[%u] Try to acquire\n", rMutexCategory); + mutex_lock(&prGlueInfo->arMutex[rMutexCategory]); + DBGLOG(INIT, TEMP, "MUTEX_LOCK[%u] Acquired\n", rMutexCategory); + } + +} /* end of kalAcquireMutex() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is provided by GLUE Layer for internal driver stack to + * release OS MUTEX. + * + * \param[in] prGlueInfo Pointer of GLUE Data Structure + * \param[in] rMutexCategory Specify which MUTEX + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void kalReleaseMutex(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_MUTEX_CATEGORY_E rMutexCategory) +{ + ASSERT(prGlueInfo); + + if (rMutexCategory < MUTEX_NUM) { + mutex_unlock(&prGlueInfo->arMutex[rMutexCategory]); + DBGLOG(INIT, TEMP, "MUTEX_UNLOCK[%u]\n", rMutexCategory); + } + +} /* end of kalReleaseMutex() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucMacAddr) +{ + ASSERT(prGlueInfo); + ASSERT(pucMacAddr); + + if (UNEQUAL_MAC_ADDR(prGlueInfo->prDevHandler->dev_addr, + pucMacAddr)) + memcpy(prGlueInfo->prDevHandler->dev_addr, pucMacAddr, + PARAM_MAC_ADDR_LEN); + +} + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +/*----------------------------------------------------------------------------*/ +/*! + * \brief To query the packet information for offload related parameters. + * + * \param[in] pvPacket Pointer to the packet descriptor. + * \param[in] pucFlag Points to the offload related parameter. + * + * \return (none) + * + */ +/*----------------------------------------------------------------------------*/ +void kalQueryTxChksumOffloadParam(IN void *pvPacket, + OUT uint8_t *pucFlag) +{ + struct sk_buff *skb = (struct sk_buff *)pvPacket; + uint8_t ucFlag = 0; + + ASSERT(pvPacket); + ASSERT(pucFlag); + + if (skb->ip_summed == CHECKSUM_PARTIAL) { +#if DBG + /* Kevin: do double check, we can remove this part in Normal + * Driver. + * Because we register NIC feature with NETIF_F_IP_CSUM for + * MT5912B MAC, so we'll process IP packet only. + */ + if (skb->protocol != htons(ETH_P_IP)) { + + } else +#endif + ucFlag |= (TX_CS_IP_GEN | TX_CS_TCP_UDP_GEN); + } + + *pucFlag = ucFlag; + +} /* kalQueryChksumOffloadParam */ + +/* 4 2007/10/8, mikewu, this is rewritten by Mike */ +/*----------------------------------------------------------------------------*/ +/*! + * \brief To update the checksum offload status to the packet to be indicated to + * OS. + * + * \param[in] pvPacket Pointer to the packet descriptor. + * \param[in] pucFlag Points to the offload related parameter. + * + * \return (none) + * + */ +/*----------------------------------------------------------------------------*/ +void kalUpdateRxCSUMOffloadParam(IN void *pvPacket, + IN enum ENUM_CSUM_RESULT 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"); + +#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 struct GLUE_INFO *prGlueInfo, + IN void *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 + */ +/*----------------------------------------------------------------------------*/ +void *kalPacketAlloc(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Size, OUT uint8_t **ppucData) +{ + struct mt66xx_chip_info *prChipInfo; + struct sk_buff *prSkb; + uint32_t u4TxHeadRoomSize; + uint32_t u4flag = 0; + + prChipInfo = prGlueInfo->prAdapter->chip_info; + u4TxHeadRoomSize = NIC_TX_DESC_AND_PADDING_LENGTH + + prChipInfo->txd_append_size; + + /* Enable __GFP_NORETRY to prevent oom issue when WiFi traffic */ + /* Only Disable __GFP_NORETRY for nicRxInitialize */ + if (prGlueInfo->prAdapter->fgIsFwDownloaded) + u4flag = __GFP_NORETRY; + + if (in_interrupt()) + prSkb = __dev_alloc_skb(u4Size + u4TxHeadRoomSize, + GFP_ATOMIC | __GFP_NOWARN | + u4flag); + else + prSkb = __dev_alloc_skb(u4Size + u4TxHeadRoomSize, + GFP_KERNEL | u4flag); + + if (prSkb) { + skb_reserve(prSkb, u4TxHeadRoomSize); + + *ppucData = (uint8_t *) (prSkb->data); + + kalResetPacket(prGlueInfo, (void *) prSkb); + } +#if DBG + { + uint32_t *pu4Head = (uint32_t *) &prSkb->cb[0]; + *pu4Head = (uint32_t) prSkb->head; + DBGLOG(RX, TRACE, "prSkb->head = %#lx, prSkb->cb = %#lx\n", + (uint32_t) prSkb->head, *pu4Head); + } +#endif + return (void *) prSkb; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +void *kalPacketAllocWithHeadroom(IN struct GLUE_INFO + *prGlueInfo, IN uint32_t u4Size, OUT uint8_t **ppucData) +{ + struct sk_buff *prSkb = dev_alloc_skb(u4Size); + + if (!prSkb) { + DBGLOG(TX, WARN, "alloc skb failed\n"); + return NULL; + } + + /* + * Reserve NIC_TX_HEAD_ROOM as this skb + * is allocated by driver instead of kernel. + */ + skb_reserve(prSkb, NIC_TX_HEAD_ROOM); + + *ppucData = (uint8_t *) (prSkb->data); + + kalResetPacket(prGlueInfo, (void *) prSkb); +#if DBG + { + uint32_t *pu4Head = (uint32_t *) &prSkb->cb[0]; + *pu4Head = (uint32_t) prSkb->head; + DBGLOG(RX, TRACE, "prSkb->head = %#lx, prSkb->cb = %#lx\n", + (uint32_t) prSkb->head, *pu4Head); + } +#endif + return (void *) 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. + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t +kalProcessRxPacket(IN struct GLUE_INFO *prGlueInfo, + IN void *pvPacket, IN uint8_t *pucPacketStart, + IN uint32_t u4PacketLen, + /* IN PBOOLEAN pfgIsRetain, */ + IN u_int8_t fgIsRetain, IN enum ENUM_CSUM_RESULT aerCSUM[]) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct sk_buff *skb = (struct sk_buff *)pvPacket; + + skb->data = (unsigned char *)pucPacketStart; + + /* Reset skb */ + skb_reset_tail_pointer(skb); + skb_trim(skb, 0); + + if (skb->tail > skb->end) { + DBGLOG(RX, ERROR, +#ifdef NET_SKBUFF_DATA_USES_OFFSET + "[skb:0x%p][skb->len:%d][skb->protocol:0x%02X] tail:%u, end:%u, data:%p\n", +#else + "[skb:0x%p][skb->len:%d][skb->protocol:0x%02X] tail:%p, end:%p, data:%p\n", +#endif + (uint8_t *) skb, + skb->len, + skb->protocol, + skb->tail, + skb->end, + skb->data); + DBGLOG_MEM32(RX, ERROR, (uint32_t *) skb->data, skb->len); + return WLAN_STATUS_FAILURE; + } + + /* Put data */ + skb_put(skb, u4PacketLen); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + if (prGlueInfo->prAdapter->fgIsSupportCsumOffload) + 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. + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t kalRxIndicatePkts(IN struct GLUE_INFO *prGlueInfo, + IN void *apvPkts[], IN uint8_t ucPktNum) +{ + uint8_t ucIdx = 0; + + ASSERT(prGlueInfo); + ASSERT(apvPkts); + + for (ucIdx = 0; ucIdx < ucPktNum; ucIdx++) + kalRxIndicateOnePkt(prGlueInfo, apvPkts[ucIdx]); + + KAL_WAKE_LOCK_TIMEOUT(prGlueInfo->prAdapter, + &prGlueInfo->rTimeoutWakeLock, MSEC_TO_JIFFIES( + prGlueInfo->prAdapter->rWifiVar.u4WakeLockRxTimeout)); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To indicate one received packets is available for higher + * level protocol uses. + * + * \param[in] prGlueInfo Pointer to the Adapter structure. + * \param[in] pvPkt The packet to be indicated + * + * \retval TRUE Success. + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t kalRxIndicateOnePkt(IN struct GLUE_INFO + *prGlueInfo, IN void *pvPkt) +{ + struct net_device *prNetDev = prGlueInfo->prDevHandler; + struct sk_buff *prSkb = NULL; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prGlueInfo); + ASSERT(pvPkt); + + prSkb = pvPkt; + prChipInfo = prGlueInfo->prAdapter->chip_info; +#if DBG && 0 + do { + uint8_t *pu4Head = (uint8_t *) &prSkb->cb[0]; + uint32_t 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 1 + + prNetDev = (struct net_device *)wlanGetNetInterfaceByBssIdx( + prGlueInfo, GLUE_GET_PKT_BSS_IDX(prSkb)); + if (!prNetDev) + prNetDev = prGlueInfo->prDevHandler; +#if CFG_SUPPORT_SNIFFER + if (prGlueInfo->fgIsEnableMon) + prNetDev = prGlueInfo->prMonDevHandler; +#endif + if (prNetDev->dev_addr == NULL) { + DBGLOG(RX, WARN, "dev_addr == NULL\n"); + return WLAN_STATUS_FAILURE; + } + + prNetDev->stats.rx_bytes += prSkb->len; + prNetDev->stats.rx_packets++; +#if (CFG_SUPPORT_PERF_IND == 1) + if (GLUE_GET_PKT_BSS_IDX(prSkb) < BSS_DEFAULT_NUM) { + /* update Performance Indicator statistics*/ + prGlueInfo->PerfIndCache.u4CurRxBytes + [GLUE_GET_PKT_BSS_IDX(prSkb)] += prSkb->len; + } +#endif +#else + 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[0]->rNetDevStats.rx_bytes += + prSkb->len; + prGlueInfo->prP2PInfo[0]->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++; + + } +#endif + + StatsEnvRxTime2Host(prGlueInfo->prAdapter, prSkb); + +#if KERNEL_VERSION(4, 11, 0) <= CFG80211_VERSION_CODE + /* ToDo jiffies assignment */ +#else + prNetDev->last_rx = jiffies; +#endif + +#if CFG_SUPPORT_SNIFFER + if (prGlueInfo->fgIsEnableMon) { + skb_reset_mac_header(prSkb); + prSkb->ip_summed = CHECKSUM_UNNECESSARY; + prSkb->pkt_type = PACKET_OTHERHOST; + prSkb->protocol = htons(ETH_P_802_2); + } else { + prSkb->protocol = eth_type_trans(prSkb, prNetDev); + } +#else + prSkb->protocol = eth_type_trans(prSkb, prNetDev); +#endif + prSkb->dev = prNetDev; + /* DBGLOG_MEM32(RX, TRACE, (PUINT_32)prSkb->data, prSkb->len); */ + /* DBGLOG(RX, EVENT, ("kalRxIndicatePkts len = %d\n", prSkb->len)); */ + if (prSkb->tail > prSkb->end) { + DBGLOG(RX, ERROR, +#ifdef NET_SKBUFF_DATA_USES_OFFSET + "kalRxIndicateOnePkt [prSkb = 0x%p][prSkb->len = %d][prSkb->protocol = 0x%02x] %u,%u\n", +#else + "kalRxIndicateOnePkt [prSkb = 0x%p][prSkb->len = %d][prSkb->protocol = 0x%02x] %p,%p\n", +#endif + prSkb, prSkb->len, prSkb->protocol, prSkb->tail, + prSkb->end); + DBGLOG_MEM32(RX, ERROR, (uint32_t *) prSkb->data, + prSkb->len); + } + + if (prSkb->protocol == NTOHS(ETH_P_8021Q) + && !FEAT_SUP_LLC_VLAN_RX(prChipInfo)) { + /* + * DA-MAC + SA-MAC + 0x8100 was removed in eth_type_trans() + * pkt format here is + * TCI(2-bytes) + Len(2-btyes) + payload-type(2-bytes) + payload + * Remove "Len" field inserted by RX VLAN header translation + * Note: TCI+payload-type is a standard 8021Q header + * + * This format update is based on RX VLAN HW header translation. + * If the setting was changed, you may need to change rules here + * as well. + */ + const uint8_t vlan_skb_mem_move = 2; + + /* Remove "Len" and shift data pointer 2 bytes */ + kalMemCopy(prSkb->data + vlan_skb_mem_move, prSkb->data, + vlan_skb_mem_move); + skb_pull_rcsum(prSkb, vlan_skb_mem_move); + + /* Have to update MAC header properly. Otherwise, wrong MACs + * woud be passed up + */ + kalMemMove(prSkb->data - ETH_HLEN, + prSkb->data - ETH_HLEN - vlan_skb_mem_move, + ETH_HLEN); + prSkb->mac_header += vlan_skb_mem_move; + + skb_reset_network_header(prSkb); + skb_reset_transport_header(prSkb); + kal_skb_reset_mac_len(prSkb); + } + + if (prSkb->protocol == HTONS(ETH_P_1X)) + DBGLOG(RX, INFO, "Rx EAPOL Frame [Len: %d]\n", prSkb->len); + +#if IS_ENABLED(CFG_RX_NAPI_SUPPORT) + if (kalRxNapiValidSkb(prGlueInfo, prSkb)) { + skb_queue_tail(&prGlueInfo->rRxNapiSkbQ, prSkb); + napi_schedule(&prGlueInfo->rNapi); + return WLAN_STATUS_SUCCESS; + } +#endif /* CFG_RX_NAPI_SUPPORT */ + + if (!in_interrupt()) + netif_rx_ni(prSkb); /* only in non-interrupt context */ + else + netif_rx(prSkb); + + 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 struct GLUE_INFO + *prGlueInfo, IN uint32_t eStatus, IN void *pvBuf, + IN uint32_t u4BufLen) +{ + + uint32_t bufLen; + struct PARAM_STATUS_INDICATION *pStatus; + struct PARAM_AUTH_EVENT *pAuth; + struct PARAM_PMKID_CANDIDATE_LIST *pPmkid; + uint8_t arBssid[PARAM_MAC_ADDR_LEN]; + struct PARAM_SSID ssid; + struct ieee80211_channel *prChannel = NULL; + struct cfg80211_bss *bss = NULL; + uint8_t ucChannelNum; + struct BSS_DESC *prBssDesc = NULL; + uint8_t fgScanAborted = FALSE; + struct wiphy *wiphy = NULL; + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE + struct cfg80211_roam_info rRoamInfo = { 0 }; +#endif + + GLUE_SPIN_LOCK_DECLARATION(); + + kalMemZero(arBssid, MAC_ADDR_LEN); + + ASSERT(prGlueInfo); + + wiphy = priv_to_wiphy(prGlueInfo); + + pStatus = (struct PARAM_STATUS_INDICATION *)pvBuf; + pAuth = (struct PARAM_AUTH_EVENT *)pStatus; + pPmkid = (struct PARAM_PMKID_CANDIDATE_LIST *)(pStatus + 1); + + 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); +#if CFG_SUPPORT_CFG80211_AUTH /* Report RX association response frame */ + DBGLOG(INIT, INFO, + "Skip report CONNECTED when using supplicant SME\n"); +#if CFG_SUPPORT_802_11R + kalMemFree(prGlueInfo->rFtIeForTx.prMDIE, VIR_MEM_TYPE, + IE_SIZE(prGlueInfo->rFtIeForTx.prMDIE)); + kalMemFree(prGlueInfo->rFtIeForTx.prFTIE, VIR_MEM_TYPE, + IE_SIZE(prGlueInfo->rFtIeForTx.prFTIE)); + kalMemFree(prGlueInfo->rFtIeForTx.prRsnIE, VIR_MEM_TYPE, + IE_SIZE(prGlueInfo->rFtIeForTx.prRsnIE)); + kalMemFree(prGlueInfo->rFtIeForTx.prTIE, VIR_MEM_TYPE, + IE_SIZE(prGlueInfo->rFtIeForTx.prTIE)); + kalMemZero(&prGlueInfo->rFtIeForTx, + sizeof(prGlueInfo->rFtIeForTx)); +#endif + return; +#endif + + 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 + "], Mac:" MACSTR "\n", + prGlueInfo->prDevHandler->name, ssid.aucSsid, + MAC2STR(arBssid), + MAC2STR( + prGlueInfo->prAdapter->rWifiVar.aucMacAddress)); + } while (0); + + if (prGlueInfo->fgIsRegistered == TRUE) { + struct cfg80211_bss *bss_others = NULL; + uint8_t ucLoopCnt = + 15; /* only loop 15 times to avoid dead loop */ + + /* retrieve channel */ + ucChannelNum = + wlanGetChannelNumberByNetwork( + prGlueInfo->prAdapter, + prGlueInfo->prAdapter->prAisBssInfo-> + ucBssIndex); + if (ucChannelNum <= 14) { + prChannel = + ieee80211_get_channel( + wiphy, + ieee80211_channel_to_frequency + (ucChannelNum, KAL_BAND_2GHZ)); + } else { + prChannel = + ieee80211_get_channel( + wiphy, + ieee80211_channel_to_frequency + (ucChannelNum, KAL_BAND_5GHZ)); + } + + if (!prChannel) { + DBGLOG(SCN, ERROR, + "prChannel is NULL and ucChannelNum is %d\n", + ucChannelNum); + break; + } + + /* ensure BSS exists */ +#if KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE + bss = cfg80211_get_bss( + wiphy, prChannel, arBssid, + ssid.aucSsid, ssid.u4SsidLen, + IEEE80211_BSS_TYPE_ESS, + IEEE80211_PRIVACY_ANY); +#else + bss = cfg80211_get_bss( + wiphy, prChannel, arBssid, + ssid.aucSsid, ssid.u4SsidLen, + WLAN_CAPABILITY_ESS, + WLAN_CAPABILITY_ESS); +#endif + if (bss == NULL) { + /* create BSS on-the-fly */ + prBssDesc = ((struct AIS_FSM_INFO *) + (&(prGlueInfo->prAdapter-> + rWifiVar.rAisFsmInfo)))-> + prTargetBssDesc; + + if (prBssDesc != NULL) { +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE + bss = cfg80211_inform_bss( + wiphy, + prChannel, + CFG80211_BSS_FTYPE_PRESP, + arBssid, + 0, /* TSF */ + WLAN_CAPABILITY_ESS, + prBssDesc->u2BeaconInterval, /* beacon interval */ + prBssDesc->aucIEBuf, /* IE */ + prBssDesc->u2IELength, /* IE Length */ + RCPI_TO_dBm(prBssDesc->ucRCPI) * 100, /* MBM */ + GFP_KERNEL); +#else + bss = cfg80211_inform_bss( + wiphy, + 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); +#endif + } + } + + StatsResetTxRx(); + + /* remove all bsses that before and only channel + * different with the current connected one + * if without this patch, UI will show channel A is + * connected even if AP has change channel from A to B + */ + while (ucLoopCnt--) { +#if KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE + bss_others = cfg80211_get_bss( + wiphy, + NULL, arBssid, ssid.aucSsid, + ssid.u4SsidLen, + IEEE80211_BSS_TYPE_ESS, + IEEE80211_PRIVACY_ANY); +#else + bss_others = cfg80211_get_bss( + wiphy, + NULL, arBssid, ssid.aucSsid, + ssid.u4SsidLen, + WLAN_CAPABILITY_ESS, + WLAN_CAPABILITY_ESS); +#endif + if (bss && bss_others && bss_others != bss) { + DBGLOG(SCN, INFO, + "remove BSSes that only channel different\n"); + cfg80211_unlink_bss( + wiphy, + bss_others); + + cfg80211_put_bss(wiphy, bss_others); + } else { + if (bss_others) { + cfg80211_put_bss(wiphy, + bss_others); + } + break; + } + } + + /* CFG80211 Indication */ + if (eStatus == WLAN_STATUS_ROAM_OUT_FIND_BEST) { +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE + rRoamInfo.bss = bss; + rRoamInfo.req_ie = prGlueInfo->aucReqIe; + rRoamInfo.req_ie_len = + prGlueInfo->u4ReqIeLength; + rRoamInfo.resp_ie = prGlueInfo->aucRspIe; + rRoamInfo.resp_ie_len = + prGlueInfo->u4RspIeLength; + + cfg80211_roamed(prGlueInfo->prDevHandler, + &rRoamInfo, GFP_KERNEL); +#else + cfg80211_roamed_bss( + prGlueInfo->prDevHandler, + bss, + prGlueInfo->aucReqIe, + prGlueInfo->u4ReqIeLength, + prGlueInfo->aucRspIe, + prGlueInfo->u4RspIeLength, + GFP_KERNEL); +#endif + } else { + cfg80211_connect_result( + prGlueInfo->prDevHandler, + arBssid, + prGlueInfo->aucReqIe, + prGlueInfo->u4ReqIeLength, + prGlueInfo->aucRspIe, + prGlueInfo->u4RspIeLength, + WLAN_STATUS_SUCCESS, + GFP_KERNEL); + if (bss) + cfg80211_put_bss(wiphy, bss); + } + } + + break; + + case WLAN_STATUS_MEDIA_DISCONNECT: + case WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY: + /* indicate disassoc event */ + wext_indicate_wext_event(prGlueInfo, SIOCGIWAP, NULL, 0); + /* For CR 90 and CR99, While supplicant do reassociate, driver + * will do netif_carrier_off first, + * after associated success, at joinComplete(), + * do netif_carier_on, + * but for unknown reason, the supplicant 1x pkt will not + * called the driver hardStartXmit, for template workaround + * these bugs, add this compiling flag + */ + /* switch netif off */ + +#if 1 /* CONSOLE_MESSAGE */ + DBGLOG(INIT, INFO, "[wifi] %s netif_carrier_off\n", + prGlueInfo->prDevHandler->name); +#endif + + netif_carrier_off(prGlueInfo->prDevHandler); +#if CFG_SUPPORT_CFG80211_AUTH + /* Report T/RX deauth/disassociation frame */ + DBGLOG(INIT, INFO, + "Skip report DISCONNECTED when using supplicant SME\n"); +#else + /* Full2Partial: reset */ + if (prGlueInfo->prAdapter) { + struct SCAN_INFO *prScanInfo = + &(prGlueInfo->prAdapter->rWifiVar.rScanInfo); + prScanInfo->fgIsScanForFull2Partial = FALSE; + prScanInfo->u4LastFullScanTime = 0; + } + + if (prGlueInfo->fgIsRegistered == TRUE) { + struct BSS_INFO *prBssInfo = + prGlueInfo->prAdapter->prAisBssInfo; + uint16_t u2DeauthReason = 0; +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) + + if (prBssInfo) + u2DeauthReason = prBssInfo->u2DeauthReason; + /* CFG80211 Indication */ + DBGLOG(INIT, INFO, + "[wifi]Indicate disconnection: Reason=%d Locally[%d]\n", + u2DeauthReason, + (eStatus == + WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY)); + cfg80211_disconnected(prGlueInfo->prDevHandler, + u2DeauthReason, NULL, 0, + eStatus == WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY, + GFP_KERNEL); + +#else + +#ifdef CONFIG_ANDROID +#if KERNEL_VERSION(3, 10, 0) == LINUX_VERSION_CODE + /* Don't indicate disconnection to upper layer for + * ANDROID kernel 3.10 + */ + /* since cfg80211 will indicate disconnection to + * wpa_supplicant for this kernel + */ + if (eStatus == WLAN_STATUS_MEDIA_DISCONNECT) +#endif +#endif + { + + + if (prBssInfo) + u2DeauthReason = + prBssInfo->u2DeauthReason; + /* CFG80211 Indication */ + cfg80211_disconnected(prGlueInfo->prDevHandler, + u2DeauthReason, NULL, 0, + GFP_KERNEL); + } + + +#endif + } +#endif + kalMemFree(prGlueInfo->rFtIeForTx.pucIEBuf, VIR_MEM_TYPE, + prGlueInfo->rFtIeForTx.u4IeLength); +#if CFG_SUPPORT_CFG80211_AUTH + kalMemFree(prGlueInfo->rFtIeForTx.prMDIE, VIR_MEM_TYPE, + IE_SIZE(prGlueInfo->rFtIeForTx.prMDIE)); + kalMemFree(prGlueInfo->rFtIeForTx.prFTIE, VIR_MEM_TYPE, + IE_SIZE(prGlueInfo->rFtIeForTx.prFTIE)); + kalMemFree(prGlueInfo->rFtIeForTx.prRsnIE, VIR_MEM_TYPE, + IE_SIZE(prGlueInfo->rFtIeForTx.prRsnIE)); + kalMemFree(prGlueInfo->rFtIeForTx.prTIE, VIR_MEM_TYPE, + IE_SIZE(prGlueInfo->rFtIeForTx.prTIE)); +#endif + kalMemZero(&prGlueInfo->rFtIeForTx, + sizeof(prGlueInfo->rFtIeForTx)); + + prGlueInfo->eParamMediaStateIndicated = + PARAM_MEDIA_STATE_DISCONNECTED; + + break; + + case WLAN_STATUS_SCAN_COMPLETE: + if (pvBuf && u4BufLen == sizeof(uint8_t)) + fgScanAborted = *(uint8_t *)pvBuf; + + /* indicate scan complete event */ + wext_indicate_wext_event(prGlueInfo, SIOCGIWSCAN, NULL, 0); + + if (fgScanAborted == FALSE) { + kalScanLogCacheFlushBSS(prGlueInfo->prAdapter, + SCAN_LOG_MSG_MAX_LEN); + scanlog_dbg(LOG_SCAN_DONE_D2K, INFO, "Call cfg80211_scan_done (aborted=%u)\n", + fgScanAborted); + } else { + scanlog_dbg(LOG_SCAN_ABORT_DONE_D2K, INFO, "Call cfg80211_scan_done (aborted=%u)\n", + fgScanAborted); + } + + /* 1. reset first for newly incoming request */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if (prGlueInfo->prScanRequest != NULL) { + kalCfg80211ScanDone(prGlueInfo->prScanRequest, + fgScanAborted); + prGlueInfo->prScanRequest = NULL; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + 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: + /* 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: + { + uint32_t i = 0; + + struct PARAM_PMKID_CANDIDATE + *prPmkidCand = + (struct PARAM_PMKID_CANDIDATE *) + &pPmkid->arCandidateList[0]; + + for (i = 0; i < pPmkid->u4NumCandidates; i++) { + cfg80211_pmksa_candidate_notify( + prGlueInfo->prDevHandler, + 1000, + prPmkidCand[i].arBSSID, + prPmkidCand[i].u4Flags, + GFP_KERNEL); + + wext_indicate_wext_event( + prGlueInfo, + IWEVPMKIDCAND, + (unsigned char *) + &pPmkid->arCandidateList[i], + pPmkid->u4NumCandidates); + } + } + break; + case ENUM_STATUS_TYPE_FT_AUTH_STATUS: + cfg80211_ft_event(prGlueInfo->prDevHandler, + &prGlueInfo->rFtEventParam); + break; + + default: + /* case ENUM_STATUS_TYPE_MEDIA_STREAM_MODE */ + break; + } + } else { + + } + break; + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS + case WLAN_STATUS_BWCS_UPDATE: { + wext_indicate_wext_event(prGlueInfo, IWEVCUSTOM, pvBuf, + sizeof(struct PTA_IPC)); + } + + break; + +#endif + case WLAN_STATUS_JOIN_FAILURE: { + struct BSS_DESC *prBssDesc = prGlueInfo->prAdapter->rWifiVar + .rAisFsmInfo.prTargetBssDesc; + if (prBssDesc) { + DBGLOG(INIT, INFO, "JOIN Failure: u2JoinStatus=%d", + prBssDesc->u2JoinStatus); + COPY_MAC_ADDR(arBssid, prBssDesc->aucBSSID); + } else { + DBGLOG(INIT, INFO, "JOIN Failure: No TargetBssDesc"); + COPY_MAC_ADDR(arBssid, + prGlueInfo->prAdapter->rWifiVar.rConnSettings + .aucBSSID); + } + if (prBssDesc && prBssDesc->u2JoinStatus + && prBssDesc->u2JoinStatus != STATUS_CODE_AUTH_TIMEOUT + && prBssDesc->u2JoinStatus != STATUS_CODE_ASSOC_TIMEOUT) + cfg80211_connect_result(prGlueInfo->prDevHandler, + arBssid, + prGlueInfo->aucReqIe, + prGlueInfo->u4ReqIeLength, + prGlueInfo->aucRspIe, + prGlueInfo->u4RspIeLength, + prBssDesc->u2JoinStatus, + GFP_KERNEL); + else + cfg80211_connect_result(prGlueInfo->prDevHandler, + arBssid, + prGlueInfo->aucReqIe, + prGlueInfo->u4ReqIeLength, + prGlueInfo->aucRspIe, + prGlueInfo->u4RspIeLength, + WLAN_STATUS_AUTH_TIMEOUT, + GFP_KERNEL); + prGlueInfo->eParamMediaStateIndicated = + PARAM_MEDIA_STATE_DISCONNECTED; + break; + } + default: + 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 struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucFrameBody, IN uint32_t u4FrameBodyLen, + IN u_int8_t fgReassocRequest) +{ + uint8_t *cp; + + ASSERT(prGlueInfo); + + /* reset */ + prGlueInfo->u4ReqIeLength = 0; + + if (fgReassocRequest) { + if (u4FrameBodyLen < 15) { + return; + } + } else { + if (u4FrameBodyLen < 9) { + return; + } + } + + cp = pucFrameBody; + + if (fgReassocRequest) { + /* Capability information field 2 */ + /* Listen interval field 2 */ + /* Current AP address 6 */ + cp += 10; + u4FrameBodyLen -= 10; + } else { + /* Capability information field 2 */ + /* Listen interval field 2 */ + cp += 4; + u4FrameBodyLen -= 4; + } + + wext_indicate_wext_event(prGlueInfo, IWEVASSOCREQIE, cp, + u4FrameBodyLen); + + if (u4FrameBodyLen <= CFG_CFG80211_IE_BUF_LEN) { + prGlueInfo->u4ReqIeLength = u4FrameBodyLen; + kalMemCopy(prGlueInfo->aucReqIe, cp, u4FrameBodyLen); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is called to update the (re)association + * response information to the structure used to reply with + * cfg80211_connect_result + * + * @param prGlueInfo Pointer to adapter descriptor + * @param pucFrameBody Pointer to the frame body of the last (Re)Association + * Response frame from the AP + * @param u4FrameBodyLen The length of the frame body of the last + * (Re)Association Response frame + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void kalUpdateReAssocRspInfo(IN struct GLUE_INFO + *prGlueInfo, IN uint8_t *pucFrameBody, + IN uint32_t u4FrameBodyLen) +{ + uint32_t u4IEOffset = + 6; /* cap_info, status_code & assoc_id */ + uint32_t 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 */ + +void kalResetPacket(IN struct GLUE_INFO *prGlueInfo, + IN void *prPacket) +{ + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + + /* Reset cb */ + kalMemZero(prSkb->cb, sizeof(prSkb->cb)); +} + +/*----------------------------------------------------------------------------*/ +/* + * \brief This function is to check the pairwise eapol and wapi 1x. + * + * \param[in] prPacket Pointer to struct net_device + * + * \retval WLAN_STATUS + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalIsPairwiseEapolPacket(IN void *prPacket) +{ + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + uint8_t *pucPacket = (uint8_t *)prSkb->data; + uint16_t u2EthType = 0; + uint16_t u2KeyInfo = 0; + + WLAN_GET_FIELD_BE16(&pucPacket[ETHER_HEADER_LEN - ETHER_TYPE_LEN], + &u2EthType); +#if CFG_SUPPORT_WAPI + /* prBssInfo && prBssInfo->eNetworkType == NETWORK_TYPE_AIS && + * wlanQueryWapiMode(prAdapter) + */ + if (u2EthType == ETH_WPI_1X) + return TRUE; +#endif + if (u2EthType != ETH_P_1X) + return FALSE; + u2KeyInfo = pucPacket[5 + ETHER_HEADER_LEN] << 8 | + pucPacket[6 + ETHER_HEADER_LEN]; +#if 1 + /* BIT3 is pairwise key bit, and check SM is 0. it means this is 4-way + * handshake frame + */ + DBGLOG(RSN, INFO, "u2KeyInfo=%d\n", u2KeyInfo); + if ((u2KeyInfo & BIT(3)) && !(u2KeyInfo & BIT(13))) + return TRUE; +#else + /* BIT3 is pairwise key bit, bit 8 is key mic bit. + * only the two bits are set, it means this is 4-way handshake 4/4 or + * 2/4 frame + */ + DBGLOG(RSN, INFO, "u2KeyInfo=%d\n", u2KeyInfo); + if ((u2KeyInfo & (BIT(3) | BIT(8))) == (BIT(3) | BIT(8))) + return TRUE; +#endif + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/* + * \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 + * \param[in] prGlueInfo Pointer of prGlueInfo + * \param[in] ucBssIndex BSS index of this net device + * + * \retval WLAN_STATUS + */ +/*----------------------------------------------------------------------------*/ +uint32_t +kalHardStartXmit(struct sk_buff *prOrgSkb, + IN struct net_device *prDev, struct GLUE_INFO *prGlueInfo, + uint8_t ucBssIndex) +{ + struct QUE_ENTRY *prQueueEntry = NULL; + struct QUE *prTxQueue = NULL; + uint16_t u2QueueIdx = 0; + struct sk_buff *prSkbNew = NULL; + struct sk_buff *prSkb = NULL; + uint32_t u4SkbLen = 0; + + ASSERT(prOrgSkb); + ASSERT(prGlueInfo); + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(INIT, INFO, "GLUE_FLAG_HALT skip tx\n"); + dev_kfree_skb(prOrgSkb); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + if (prGlueInfo->prAdapter->fgIsEnableLpdvt) { + DBGLOG(INIT, INFO, "LPDVT enable, skip this frame\n"); + dev_kfree_skb(prOrgSkb); + return WLAN_STATUS_NOT_ACCEPTED; + } + + if (skb_headroom(prOrgSkb) < NIC_TX_HEAD_ROOM) { + /* + * Should not happen + * kernel crash may happen as skb shared info + * channged. + * offer an change for lucky anyway + */ + prSkbNew = skb_realloc_headroom(prOrgSkb, NIC_TX_HEAD_ROOM); + ASSERT(prSkbNew); + dev_kfree_skb(prOrgSkb); + prSkb = prSkbNew; + } else + prSkb = prOrgSkb; + + prQueueEntry = (struct QUE_ENTRY *) + GLUE_GET_PKT_QUEUE_ENTRY(prSkb); + prTxQueue = &prGlueInfo->rTxQueue; + + GLUE_SET_PKT_BSS_IDX(prSkb, ucBssIndex); + + /* Parsing frame info */ + if (!wlanProcessTxFrame(prGlueInfo->prAdapter, + (void *) prSkb)) { + /* Cannot extract packet */ + DBGLOG(INIT, INFO, + "Cannot extract content, skip this frame\n"); + dev_kfree_skb(prSkb); + return WLAN_STATUS_INVALID_PACKET; + } + + /* Tx profiling */ + wlanTxProfilingTagPacket(prGlueInfo->prAdapter, + (void *) prSkb, TX_PROF_TAG_OS_TO_DRV); + + /* Handle normal data frame */ + u2QueueIdx = skb_get_queue_mapping(prSkb); + u4SkbLen = prSkb->len; + + if (u2QueueIdx >= CFG_MAX_TXQ_NUM) { + DBGLOG(INIT, INFO, + "Incorrect queue index, skip this frame\n"); + dev_kfree_skb(prSkb); + return WLAN_STATUS_INVALID_PACKET; + } + + if (!HAL_IS_TX_DIRECT(prGlueInfo->prAdapter)) { + GLUE_SPIN_LOCK_DECLARATION(); + + 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[ucBssIndex] + [u2QueueIdx]); + + if (GLUE_GET_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue + [ucBssIndex][u2QueueIdx]) >= + prGlueInfo->prAdapter->rWifiVar.u4NetifStopTh) { + netif_stop_subqueue(prDev, u2QueueIdx); + + DBGLOG(TX, INFO, + "Stop subqueue for BSS[%u] QIDX[%u] PKT_LEN[%u] TOT_CNT[%d] PER-Q_CNT[%d]\n", + ucBssIndex, u2QueueIdx, u4SkbLen, + GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum), + GLUE_GET_REF_CNT( + prGlueInfo->ai4TxPendingFrameNumPerQueue + [ucBssIndex][u2QueueIdx])); + } + + /* Update NetDev statisitcs */ + prDev->stats.tx_bytes += u4SkbLen; + prDev->stats.tx_packets++; + +#if (CFG_SUPPORT_PERF_IND == 1) + /* update Performance Indicator statistics*/ + prGlueInfo->PerfIndCache.u4CurTxBytes[ucBssIndex] += u4SkbLen; +#endif + + DBGLOG(TX, LOUD, + "Enqueue frame for BSS[%u] QIDX[%u] PKT_LEN[%u] TOT_CNT[%d] PER-Q_CNT[%d]\n", + ucBssIndex, u2QueueIdx, u4SkbLen, + GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum), + GLUE_GET_REF_CNT( + prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex] + [u2QueueIdx])); + + if (HAL_IS_TX_DIRECT(prGlueInfo->prAdapter)) + return nicTxDirectStartXmit(prSkb, prGlueInfo); + + kalSetEvent(prGlueInfo); + + return WLAN_STATUS_SUCCESS; +} /* end of kalHardStartXmit() */ + +uint32_t kalResetStats(IN struct net_device *prDev) +{ + DBGLOG(QM, LOUD, "Reset NetDev[0x%p] statistics\n", prDev); + + kalMemZero(kalGetStats(prDev), + sizeof(struct net_device_stats)); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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. + */ +/*----------------------------------------------------------------------------*/ +void *kalGetStats(IN struct net_device *prDev) +{ + return (void *) &prDev->stats; +} /* end of wlanGetStats() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct GLUE_INFO + *prGlueInfo, IN void *pvPacket) +{ + struct net_device *prDev = NULL; + struct sk_buff *prSkb = NULL; + uint16_t u2QueueIdx = 0; + uint8_t ucBssIndex = 0; + u_int8_t fgIsValidDevice = TRUE; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(pvPacket); + /* ASSERT(prGlueInfo->i4TxPendingFrameNum); */ + + prSkb = (struct sk_buff *)pvPacket; + u2QueueIdx = skb_get_queue_mapping(prSkb); + ASSERT(u2QueueIdx < CFG_MAX_TXQ_NUM); + + ucBssIndex = GLUE_GET_PKT_BSS_IDX(pvPacket); + +#if 0 + if ((GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum) <= + 0)) { + uint8_t ucBssIdx; + uint16_t u2QIdx; + + DBGLOG(INIT, INFO, "TxPendingFrameNum[%u] CurFrameId[%u]\n", + prGlueInfo->i4TxPendingFrameNum, + GLUE_GET_PKT_ARRIVAL_TIME(pvPacket)); + + for (ucBssIdx = 0; ucBssIdx < prAdapter->ucHwBssIdNum; + ucBssIdx++) { + for (u2QIdx = 0; u2QIdx < CFG_MAX_TXQ_NUM; u2QIdx++) { + DBGLOG(INIT, INFO, + "BSS[%u] Q[%u] TxPendingFrameNum[%u]\n", + ucBssIdx, u2QIdx, + prGlueInfo->ai4TxPendingFrameNumPerQueue + [ucBssIdx][u2QIdx]); + } + } + } + + ASSERT((GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum) > + 0)); +#endif + + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingFrameNum); + GLUE_DEC_REF_CNT( + prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex] + [u2QueueIdx]); + + DBGLOG(TX, LOUD, + "Release frame for BSS[%u] QIDX[%u] PKT_LEN[%u] TOT_CNT[%d] PER-Q_CNT[%d]\n", + ucBssIndex, u2QueueIdx, prSkb->len, + GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum), + GLUE_GET_REF_CNT( + prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex] + [u2QueueIdx])); + + prDev = prSkb->dev; + + ASSERT(prDev); + +#if CFG_ENABLE_WIFI_DIRECT + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + { + struct BSS_INFO *prBssInfo = GET_BSS_INFO_BY_INDEX( + prGlueInfo->prAdapter, ucBssIndex); + struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) + NULL; + struct net_device *prNetdevice = NULL; + + /* in case packet was sent after P2P device is unregistered or + * the net_device was be free + */ + if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) { + if (prGlueInfo->prAdapter->fgIsP2PRegistered == FALSE) + fgIsValidDevice = FALSE; + else { + ASSERT(prBssInfo->u4PrivateData < KAL_P2P_NUM); + prGlueP2pInfo = + prGlueInfo->prP2PInfo[ + prBssInfo->u4PrivateData]; + if (prGlueP2pInfo) { + prNetdevice = + prGlueP2pInfo->aprRoleHandler; + /* The net_device may be free */ + if ((prDev != prNetdevice) + && (prDev != + prGlueP2pInfo->prDevHandler)) { + fgIsValidDevice = FALSE; + DBGLOG(TX, LOUD, + "kalSendCompleteAndAwakeQueue net device deleted! ucBssIndex = %u\n", + ucBssIndex); + } + } + } + } + } +#endif + + if (fgIsValidDevice == TRUE) { + uint32_t u4StartTh = + prGlueInfo->prAdapter->rWifiVar.u4NetifStartTh; + + if (netif_subqueue_stopped(prDev, prSkb) && + prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex] + [u2QueueIdx] <= u4StartTh) { + netif_wake_subqueue(prDev, u2QueueIdx); + DBGLOG(TX, TRACE, + "WakeUp Queue BSS[%u] QIDX[%u] PKT_LEN[%u] TOT_CNT[%d] PER-Q_CNT[%d]\n", + ucBssIndex, u2QueueIdx, prSkb->len, + GLUE_GET_REF_CNT( + prGlueInfo->i4TxPendingFrameNum), + GLUE_GET_REF_CNT( + prGlueInfo-> + ai4TxPendingFrameNumPerQueue + [ucBssIndex][u2QueueIdx])); + } + } + +#if CFG_ENABLE_WIFI_DIRECT + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); +#endif + + dev_kfree_skb_any((struct sk_buff *)pvPacket); + + DBGLOG(TX, LOUD, "----- pending frame %d -----\n", + prGlueInfo->i4TxPendingFrameNum); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Copy Mac Address setting from registry. It's All Zeros in Linux. + * + * \param[in] prAdapter Pointer to the Adapter structure + * + * \param[out] paucMacAddr Pointer to the Mac Address buffer + * + * \retval WLAN_STATUS_SUCCESS + * + * \note + */ +/*----------------------------------------------------------------------------*/ +void kalQueryRegistryMacAddr(IN struct GLUE_INFO + *prGlueInfo, OUT uint8_t *paucMacAddr) +{ + uint8_t aucZeroMac[MAC_ADDR_LEN] = { 0, 0, 0, 0, 0, 0 } + + DEBUGFUNC("kalQueryRegistryMacAddr"); + + ASSERT(prGlueInfo); + ASSERT(paucMacAddr); + + kalMemCopy((void *) paucMacAddr, (void *) aucZeroMac, + MAC_ADDR_LEN); + +} /* end of kalQueryRegistryMacAddr() */ + +#if CFG_SUPPORT_EXT_CONFIG +/*----------------------------------------------------------------------------*/ +/*! + * \brief Read external configuration, ex. NVRAM or file + * + * \param[in] prGlueInfo Pointer of GLUE Data Structure + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +uint32_t kalReadExtCfg(IN struct GLUE_INFO *prGlueInfo) +{ + ASSERT(prGlueInfo); + + /* External data is given from user space by ioctl or /proc, not read by + * driver. + */ + if (prGlueInfo->u4ExtCfgLength != 0) + DBGLOG(INIT, TRACE, + "Read external configuration data -- OK\n"); + else + DBGLOG(INIT, TRACE, + "Read external configuration data -- fail\n"); + + return prGlueInfo->u4ExtCfgLength; +} +#endif + +u_int8_t +kalIPv4FrameClassifier(IN struct GLUE_INFO *prGlueInfo, + IN void *prPacket, IN uint8_t *pucIpHdr, + OUT struct TX_PACKET_INFO *prTxPktInfo) +{ + uint8_t ucIpVersion, ucIcmpType; + uint8_t ucIpProto; + uint8_t ucSeqNo; + uint8_t *pucUdpHdr, *pucIcmp; + uint16_t u2DstPort, u2IcmpId, u2IcmpSeq; + struct BOOTP_PROTOCOL *prBootp; + uint32_t u4DhcpMagicCode; + + /* IPv4 version check */ + ucIpVersion = (pucIpHdr[0] & IP_VERSION_MASK) >> + IP_VERSION_OFFSET; + if (ucIpVersion != IP_VERSION_4) { + DBGLOG(TX, WARN, "Invalid IPv4 packet version: %u\n", + ucIpVersion); + return FALSE; + } + + ucIpProto = pucIpHdr[IPV4_HDR_IP_PROTOCOL_OFFSET]; + + if (ucIpProto == IP_PRO_UDP) { + pucUdpHdr = &pucIpHdr[IPV4_HDR_LEN]; + + /* Get UDP DST port */ + WLAN_GET_FIELD_BE16(&pucUdpHdr[UDP_HDR_DST_PORT_OFFSET], + &u2DstPort); + + /* BOOTP/DHCP protocol */ + if ((u2DstPort == IP_PORT_BOOTP_SERVER) || + (u2DstPort == IP_PORT_BOOTP_CLIENT)) { + + prBootp = (struct BOOTP_PROTOCOL *) + &pucUdpHdr[UDP_HDR_LEN]; + + WLAN_GET_FIELD_BE32(&prBootp->aucOptions[0], + &u4DhcpMagicCode); + + if (u4DhcpMagicCode == DHCP_MAGIC_NUMBER) { + uint32_t u4Xid; + + WLAN_GET_FIELD_BE32(&prBootp->u4TransId, + &u4Xid); + + ucSeqNo = nicIncreaseTxSeqNum( + prGlueInfo->prAdapter); + GLUE_SET_PKT_SEQ_NO(prPacket, ucSeqNo); + + DBGLOG_LIMITED(TX, INFO, + "DHCP PKT[0x%p] XID[0x%08x] OPT[%u] TYPE[%u], SeqNo: %d\n", + prPacket, u4Xid, prBootp->aucOptions[4], + prBootp->aucOptions[6], ucSeqNo); + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_DHCP); + } + } else if (u2DstPort == UDP_PORT_DNS) { + uint16_t u2IpId = *(uint16_t *)&pucIpHdr[IPV4_ADDR_LEN]; + uint8_t *pucUdpPayload = &pucUdpHdr[UDP_HDR_LEN]; + uint16_t u2TransId = (pucUdpPayload[0] << 8) | + pucUdpPayload[1]; + + ucSeqNo = nicIncreaseTxSeqNum(prGlueInfo->prAdapter); + GLUE_SET_PKT_SEQ_NO(prPacket, ucSeqNo); + DBGLOG_LIMITED(TX, INFO, + " DNS: [0x%p] IPID[0x%02x] TransID[0x%04x] SeqNo[%d]\n", + prPacket, u2IpId, u2TransId, ucSeqNo); + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_DNS); + } else if ((u2DstPort == IP_PORT_MDNS) + || (u2DstPort == IP_PORT_MDNS)) { + uint8_t *pucMdnsHdr = NULL; + struct MDNS_RESP_INFO_T *respInfo; + + if (!prGlueInfo->prAdapter->mdns_offload_enable) + return TRUE; + + respInfo = (struct MDNS_RESP_INFO_T *)kalMemAlloc( + sizeof(struct MDNS_RESP_INFO_T), + PHY_MEM_TYPE); + if (respInfo == NULL) + return TRUE; + + kalMemZero(respInfo, sizeof(struct MDNS_RESP_INFO_T)); + pucMdnsHdr = &pucIpHdr[IPV4_HDR_LEN + UDP_HDR_LEN]; + if (kalParseMdnsRespPkt(pucMdnsHdr, respInfo) + == TRUE) { + if (respInfo->ptrInfo.ttl != 0) + kalAddMdnsCache(respInfo); + else + kalDelMdnsCache(respInfo); + } + kalMemFree(respInfo, PHY_MEM_TYPE, + sizeof(struct MDNS_RESP_INFO_T)); + } + } else if (ucIpProto == IP_PRO_ICMP) { + /* the number of ICMP packets is seldom so we print log here */ + uint16_t u2IpId = + (pucIpHdr[IPV4_ADDR_LEN] << 8) | + pucIpHdr[IPV4_ADDR_LEN + 1]; + pucIcmp = &pucIpHdr[20]; + + ucIcmpType = pucIcmp[0]; + if (ucIcmpType == + 3) /* don't log network unreachable packet */ + return FALSE; + u2IcmpId = *(uint16_t *) &pucIcmp[4]; + u2IcmpSeq = *(uint16_t *) &pucIcmp[6]; + + ucSeqNo = nicIncreaseTxSeqNum(prGlueInfo->prAdapter); + GLUE_SET_PKT_SEQ_NO(prPacket, ucSeqNo); + DBGLOG_LIMITED(TX, INFO, + " ICMP: IPID[0x%04x] Type %d, Id 0x%04x, Seq BE 0x%04x, SeqNo: %d\n", + u2IpId, ucIcmpType, u2IcmpId, u2IcmpSeq, ucSeqNo); + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_ICMP); + } + return TRUE; +} + + +u_int8_t +kalArpFrameClassifier(IN struct GLUE_INFO *prGlueInfo, + IN void *prPacket, IN uint8_t *pucIpHdr, + OUT struct TX_PACKET_INFO *prTxPktInfo) +{ + uint16_t u2ArpOp; + uint8_t ucSeqNo; + + ucSeqNo = nicIncreaseTxSeqNum(prGlueInfo->prAdapter); + WLAN_GET_FIELD_BE16(&pucIpHdr[ARP_OPERATION_OFFSET], + &u2ArpOp); + + DBGLOG(TX, INFO, "ARP %s PKT[0x%p] TAR MAC/IP[" MACSTR "]/[" + IPV4STR "], SeqNo: %d\n", + u2ArpOp == ARP_OPERATION_REQUEST ? "REQ" : "RSP", + prPacket, MAC2STR(&pucIpHdr[ARP_TARGET_MAC_OFFSET]), + IPV4TOSTR(&pucIpHdr[ARP_TARGET_IP_OFFSET]), ucSeqNo); + + GLUE_SET_PKT_SEQ_NO(prPacket, ucSeqNo); + + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_ARP); + return TRUE; +} + +u_int8_t +kalTdlsFrameClassifier(IN struct GLUE_INFO *prGlueInfo, + IN void *prPacket, IN uint8_t *pucIpHdr, + OUT struct TX_PACKET_INFO *prTxPktInfo) +{ + uint8_t ucSeqNo; + uint8_t ucActionCode; + + ucActionCode = pucIpHdr[TDLS_ACTION_CODE_OFFSET]; + + DBGLOG(TX, INFO, "TDLS action code: %d\n", ucActionCode); + + ucSeqNo = nicIncreaseTxSeqNum(prGlueInfo->prAdapter); + + GLUE_SET_PKT_SEQ_NO(prPacket, ucSeqNo); + + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_TDLS); + + return TRUE; +} + +u_int8_t +kalSecurityFrameClassifier(IN struct GLUE_INFO *prGlueInfo, + IN void *prPacket, IN uint8_t *pucIpHdr, + IN uint16_t u2EthType, IN uint8_t *aucLookAheadBuf, + OUT struct TX_PACKET_INFO *prTxPktInfo) +{ + uint8_t *pucEapol; + uint8_t ucEapolType; + uint8_t ucSeqNo; +#if CFG_SUPPORT_WAPI + uint8_t ucSubType; /* sub type filed*/ + uint16_t u2Length; + uint16_t u2Seq; +#endif + uint8_t ucEAPoLKey = 0; + uint8_t ucEapOffset = ETHER_HEADER_LEN; + uint16_t u2KeyInfo = 0; + + pucEapol = pucIpHdr; + + if (u2EthType == ETH_P_1X) { + + ucEapolType = pucEapol[1]; + + /* Leave EAP to check */ + ucEAPoLKey = aucLookAheadBuf[1 + ucEapOffset]; + if (ucEAPoLKey != ETH_EAPOL_KEY) + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_NON_PROTECTED_1X); + else { + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[5 + ucEapOffset], + &u2KeyInfo); + /* BIT3 is pairwise key bit */ + DBGLOG(TX, INFO, "u2KeyInfo=%d\n", u2KeyInfo); + if (u2KeyInfo & BIT(3)) + prTxPktInfo->u2Flag |= + BIT(ENUM_PKT_NON_PROTECTED_1X); + } + + + switch (ucEapolType) { + case 0: /* eap packet */ + + ucSeqNo = nicIncreaseTxSeqNum(prGlueInfo->prAdapter); + GLUE_SET_PKT_SEQ_NO(prPacket, ucSeqNo); + + DBGLOG(TX, INFO, + " EAP Packet: code %d, id %d, type %d, PKT[0x%p], SeqNo: %d\n", + pucEapol[4], pucEapol[5], pucEapol[7], prPacket, + ucSeqNo); + break; + case 1: /* eapol start */ + ucSeqNo = nicIncreaseTxSeqNum(prGlueInfo->prAdapter); + GLUE_SET_PKT_SEQ_NO(prPacket, ucSeqNo); + + DBGLOG(TX, INFO, + " EAPOL: start, PKT[0x%p], SeqNo: %d\n", + prPacket, ucSeqNo); + break; + case 3: /* key */ + + ucSeqNo = nicIncreaseTxSeqNum(prGlueInfo->prAdapter); + GLUE_SET_PKT_SEQ_NO(prPacket, ucSeqNo); + + DBGLOG(TX, INFO, + " EAPOL: key, KeyInfo 0x%04x, PKT[0x%p], SeqNo: %d\n", + *((uint16_t *)(&pucEapol[5])), prPacket, + ucSeqNo); + break; + } +#if CFG_SUPPORT_WAPI + } else if (u2EthType == ETH_WPI_1X) { + + ucSubType = pucEapol[3]; /* sub type filed*/ + u2Length = *(uint16_t *)&pucEapol[6]; + u2Seq = *(uint16_t *)&pucEapol[8]; + ucSeqNo = nicIncreaseTxSeqNum(prGlueInfo->prAdapter); + GLUE_SET_PKT_SEQ_NO(prPacket, ucSeqNo); + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_NON_PROTECTED_1X); + + DBGLOG(TX, INFO, + " WAPI: subType %d, Len %d, Seq %d, PKT[0x%p], SeqNo: %d\n", + ucSubType, u2Length, u2Seq, prPacket, ucSeqNo); +#endif + } + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_1X); + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 prPacket Packet descriptor + * @param prTxPktInfo Extracted packet info + * + * @retval TRUE Success to extract information + * @retval FALSE Fail to extract correct information + */ +/*----------------------------------------------------------------------------*/ +u_int8_t +kalQoSFrameClassifierAndPacketInfo(IN struct GLUE_INFO *prGlueInfo, + IN void *prPacket, OUT struct TX_PACKET_INFO *prTxPktInfo) +{ + uint32_t u4PacketLen; + uint16_t u2EtherTypeLen; + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + uint8_t *aucLookAheadBuf = NULL; + uint8_t ucEthTypeLenOffset = ETHER_HEADER_LEN - + ETHER_TYPE_LEN; + uint8_t *pucNextProtocol = NULL; +#if DSCP_SUPPORT + uint8_t ucUserPriority; +#endif + + u4PacketLen = prSkb->len; + + if (u4PacketLen < ETHER_HEADER_LEN) { + DBGLOG(INIT, WARN, "Invalid Ether packet length: %u\n", + u4PacketLen); + return FALSE; + } + + aucLookAheadBuf = prSkb->data; + + /* Reset Packet Info */ + kalMemZero(prTxPktInfo, sizeof(struct TX_PACKET_INFO)); + + /* 4 <0> Obtain Ether Type/Len */ + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[ucEthTypeLenOffset], + &u2EtherTypeLen); + + /* 4 <1> Skip 802.1Q header (VLAN Tagging) */ + if (u2EtherTypeLen == ETH_P_VLAN) { + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_VLAN_EXIST); + ucEthTypeLenOffset += ETH_802_1Q_HEADER_LEN; + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[ucEthTypeLenOffset], + &u2EtherTypeLen); + } + /* 4 <2> Obtain next protocol pointer */ + pucNextProtocol = &aucLookAheadBuf[ucEthTypeLenOffset + + ETHER_TYPE_LEN]; + + /* 4 <3> Handle ethernet format */ + switch (u2EtherTypeLen) { + case ETH_P_IPV4: + /* IPv4 header length check */ + if (u4PacketLen < (ucEthTypeLenOffset + ETHER_TYPE_LEN + + IPV4_HDR_LEN)) { + DBGLOG(INIT, WARN, "Invalid IPv4 packet length: %u\n", + u4PacketLen); + break; + } +#if DSCP_SUPPORT + if (GLUE_GET_PKT_BSS_IDX(prSkb) != P2P_DEV_BSS_INDEX) { + ucUserPriority = getUpFromDscp(prGlueInfo, + GLUE_GET_PKT_BSS_IDX(prSkb), + (pucNextProtocol[1] & 0xFC) >> 2); + if (ucUserPriority != 0xFF) + prSkb->priority = ucUserPriority; + } +#endif + kalIPv4FrameClassifier(prGlueInfo, prPacket, + pucNextProtocol, prTxPktInfo); + break; + + case ETH_P_ARP: + kalArpFrameClassifier(prGlueInfo, prPacket, pucNextProtocol, + prTxPktInfo); + break; + + case ETH_P_1X: + case ETH_P_PRE_1X: +#if CFG_SUPPORT_WAPI + case ETH_WPI_1X: +#endif + kalSecurityFrameClassifier(prGlueInfo, prPacket, + pucNextProtocol, u2EtherTypeLen, aucLookAheadBuf, + prTxPktInfo); + break; + + case ETH_PRO_TDLS: + kalTdlsFrameClassifier(prGlueInfo, prPacket, + pucNextProtocol, prTxPktInfo); + break; + default: + /* 4 <4> Handle 802.3 format if LEN <= 1500 */ + if (u2EtherTypeLen <= ETH_802_3_MAX_LEN) + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_802_3); + break; + } + + /* 4 <4.1> Check for PAL (BT over Wi-Fi) */ + /* Move to kalBowFrameClassifier */ + + /* 4 <5> Return the value of Priority Parameter. */ + /* prSkb->priority is assigned by Linux wireless utility + * function(cfg80211_classify8021d) + */ + /* at net_dev selection callback (ndo_select_queue) */ + prTxPktInfo->ucPriorityParam = prSkb->priority; + + /* 4 <6> Retrieve Packet Information - DA */ + /* Packet Length/ Destination Address */ + prTxPktInfo->u4PacketLen = u4PacketLen; + + kalMemCopy(prTxPktInfo->aucEthDestAddr, aucLookAheadBuf, + PARAM_MAC_ADDR_LEN); + + return TRUE; +} /* end of kalQoSFrameClassifier() */ + +u_int8_t kalGetEthDestAddr(IN struct GLUE_INFO *prGlueInfo, + IN void *prPacket, OUT uint8_t *pucEthDestAddr) +{ + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + uint8_t *aucLookAheadBuf = NULL; + + /* Sanity Check */ + if (!prPacket || !prGlueInfo) + return FALSE; + + aucLookAheadBuf = prSkb->data; + + kalMemCopy(pucEthDestAddr, aucLookAheadBuf, + PARAM_MAC_ADDR_LEN); + + return TRUE; +} + +void +kalOidComplete(IN struct GLUE_INFO *prGlueInfo, + IN u_int8_t fgSetQuery, IN uint32_t u4SetQueryInfoLen, + IN uint32_t rOidStatus) +{ + + ASSERT(prGlueInfo); + /* remove timeout check timer */ + wlanoidClearTimeoutCheck(prGlueInfo->prAdapter); + + prGlueInfo->rPendStatus = rOidStatus; + + prGlueInfo->u4OidCompleteFlag = 1; + /* complete ONLY if there are waiters */ + if (!completion_done(&prGlueInfo->rPendComp)) { + complete(&prGlueInfo->rPendComp); + } else { + DBGLOG(INIT, WARN, "SKIP multiple OID complete!\n"); + } + + if (rOidStatus == WLAN_STATUS_SUCCESS) + DBGLOG(INIT, TRACE, "Complete OID, status:success\n"); + else + DBGLOG(INIT, WARN, "Complete OID, status:0x%08x\n", + rOidStatus); + + /* else let it timeout on kalIoctl entry */ +} + +void kalOidClearance(IN struct GLUE_INFO *prGlueInfo) +{ + +} + +void kalGetLocalTime(unsigned long long *sec, unsigned long *nsec) +{ + if (sec != NULL && nsec != NULL) { + *sec = local_clock(); + *nsec = do_div(*sec, 1000000000)/1000; + } else + DBGLOG(INIT, ERROR, + "The input parameters error when get local time\n"); +} + +/* + * kalThreadSchedRetrieve + * Retrieve thread's current scheduling statistics and + * stored in output "sched". + * Return value: + * 0 : Schedstats successfully retrieved + * -1 : Kernel's schedstats feature not enabled + * -2 : pThread not yet initialized or sched is a NULL pointer + */ +static int32_t kalThreadSchedRetrieve(struct task_struct *pThread, + struct KAL_THREAD_SCHEDSTATS *pSched) +{ +#ifdef CONFIG_SCHEDSTATS + struct sched_entity se; + unsigned long long sec; + unsigned long usec; + + if (!pSched) + return -2; + + /* always clear sched to simplify error handling at caller side */ + memset(pSched, 0, sizeof(struct KAL_THREAD_SCHEDSTATS)); + + if (!pThread) + return -2; + + memcpy(&se, &pThread->se, sizeof(struct sched_entity)); + kalGetLocalTime(&sec, &usec); + + pSched->time = sec*1000 + usec/1000; + pSched->exec = se.sum_exec_runtime; + pSched->runnable = se.statistics.wait_sum; + pSched->iowait = se.statistics.iowait_sum; + + return 0; +#else + /* always clear sched to simplify error handling at caller side */ + if (pSched) + memset(pSched, 0, sizeof(struct KAL_THREAD_SCHEDSTATS)); + return -1; +#endif +} + +/* + * kalThreadSchedMark + * Record the thread's current schedstats and stored in + * output "schedstats" parameter for profiling at later time. + * Return value: + * 0 : Schedstats successfully recorded + * -1 : Kernel's schedstats feature not enabled + * -2 : pThread not yet initialized or invalid parameters + */ +int32_t kalThreadSchedMark(struct task_struct *pThread, + struct KAL_THREAD_SCHEDSTATS *pSchedstats) +{ + return kalThreadSchedRetrieve(pThread, pSchedstats); +} + +/* + * kalThreadSchedUnmark + * Calculate scheduling statistics against the previously marked point. + * The result will be filled back into the schedstats output parameter. + * Return value: + * 0 : Schedstats successfully calculated + * -1 : Kernel's schedstats feature not enabled + * -2 : pThread not yet initialized or invalid parameters + */ +int32_t kalThreadSchedUnmark(struct task_struct *pThread, + struct KAL_THREAD_SCHEDSTATS *pSchedstats) +{ + int32_t ret; + struct KAL_THREAD_SCHEDSTATS sched_now; + + if (unlikely(!pSchedstats)) { + ret = -2; + } else { + ret = kalThreadSchedRetrieve(pThread, &sched_now); + if (ret == 0) { + pSchedstats->time = + sched_now.time - pSchedstats->time; + pSchedstats->exec = + sched_now.exec - pSchedstats->exec; + pSchedstats->runnable = + sched_now.runnable - pSchedstats->runnable; + pSchedstats->iowait = + sched_now.iowait - pSchedstats->iowait; + } + } + return ret; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @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; */ + +uint32_t +kalIoctl(IN struct GLUE_INFO *prGlueInfo, + IN PFN_OID_HANDLER_FUNC pfnOidHandler, + IN void *pvInfoBuf, + IN uint32_t u4InfoBufLen, IN u_int8_t fgRead, + IN u_int8_t fgWaitResp, IN u_int8_t fgCmd, + OUT uint32_t *pu4QryInfoLen) +{ + struct GL_IO_REQ *prIoReq = NULL; + struct KAL_THREAD_SCHEDSTATS schedstats; + uint32_t ret = WLAN_STATUS_SUCCESS; + uint32_t waitRet = 0; + +#if CFG_CHIP_RESET_SUPPORT + if (kalIsResetting()) + return WLAN_STATUS_SUCCESS; +#endif + + if (wlanIsChipAssert(prGlueInfo->prAdapter)) + return WLAN_STATUS_SUCCESS; + + /* GLUE_SPIN_LOCK_DECLARATION(); */ + ASSERT(prGlueInfo); + + /* Just direct function call if already + * in main_thread or interrupt context + */ + if (prGlueInfo->u4TxThreadPid == KAL_GET_CURRENT_THREAD_ID() + || in_interrupt()) { + if (pfnOidHandler) { + g_fgIsOid = FALSE; + ret = pfnOidHandler(prGlueInfo->prAdapter, pvInfoBuf, + u4InfoBufLen, pu4QryInfoLen); + } + return ret; + } + + /* <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; + + /* <5> Reset the status of pending OID */ + prGlueInfo->rPendStatus = WLAN_STATUS_FAILURE; + /* prGlueInfo->u4TimeoutFlag = 0; */ + prGlueInfo->u4OidCompleteFlag = 0; + + /* <6> Check if we use the command queue */ + prIoReq->u4Flag = fgCmd; + + /* <7> schedule the OID bit */ + set_bit(GLUE_FLAG_OID_BIT, &prGlueInfo->ulFlag); + + /* <7.1> Hold wakelock to ensure OS won't be suspended */ + KAL_WAKE_LOCK_TIMEOUT(prGlueInfo->prAdapter, + &prGlueInfo->rTimeoutWakeLock, MSEC_TO_JIFFIES( + prGlueInfo->prAdapter->rWifiVar.u4WakeLockThreadWakeup)); + + /* <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 30 secs + */ + kalThreadSchedMark(prGlueInfo->main_thread, &schedstats); + waitRet = wait_for_completion_timeout(&prGlueInfo->rPendComp, + MSEC_TO_JIFFIES(30*1000)); + kalThreadSchedUnmark(prGlueInfo->main_thread, &schedstats); + + if (waitRet > 0) { + /* 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 (ret != WLAN_STATUS_SUCCESS) + DBGLOG(OID, WARN, "kalIoctl: ret ErrCode: 0x%X\n", ret); + } else { + +#if 0 + /* Case 2: timeout */ + /* clear pending OID's cmd in CMD queue */ + if (fgCmd) { + prGlueInfo->u4TimeoutFlag = 1; + wlanReleasePendingOid(prGlueInfo->prAdapter, 0); + } +#endif + DBGLOG(OID, WARN, + "duration:%llums, sched(x%llu/r%llu/i%llu)\n", + schedstats.time, schedstats.exec, + schedstats.runnable, schedstats.iowait); + DBGLOG(OID, ERROR, + "wait main_thread timeout, show backtrace:\n"); + + kal_show_stack(prGlueInfo->prAdapter, + prGlueInfo->main_thread, NULL); + ret = WLAN_STATUS_FAILURE; + } + + /* <10> Clear bit for error handling */ + clear_bit(GLUE_FLAG_OID_BIT, &prGlueInfo->ulFlag); + + 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 struct GLUE_INFO *prGlueInfo) +{ + struct QUE *prCmdQue; + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue = &rTempCmdQue; + struct QUE rReturnCmdQue; + struct QUE *prReturnCmdQue = &rReturnCmdQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + QUEUE_INITIALIZE(prReturnCmdQue); + /* Clear pending security frames in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) { + if (prCmdInfo->pfCmdTimeoutHandler) + prCmdInfo->pfCmdTimeoutHandler( + prGlueInfo->prAdapter, prCmdInfo); + else + wlanReleaseCommand(prGlueInfo->prAdapter, + prCmdInfo, TX_RESULT_QUEUE_CLEARANCE); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingCmdNum); + } else { + QUEUE_INSERT_TAIL(prReturnCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(prCmdQue, prReturnCmdQue); + 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 kalClearSecurityFramesByBssIdx(IN struct GLUE_INFO + *prGlueInfo, IN uint8_t ucBssIndex) +{ + struct QUE *prCmdQue; + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue = &rTempCmdQue; + struct QUE rReturnCmdQue; + struct QUE *prReturnCmdQue = &rReturnCmdQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) NULL; + struct MSDU_INFO *prMsduInfo; + u_int8_t fgFree; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + QUEUE_INITIALIZE(prReturnCmdQue); + /* Clear pending security frames in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + prMsduInfo = prCmdInfo->prMsduInfo; + fgFree = FALSE; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME + && prMsduInfo) { + if (prMsduInfo->ucBssIndex == ucBssIndex) + fgFree = TRUE; + } + + if (fgFree) { + if (prCmdInfo->pfCmdTimeoutHandler) + prCmdInfo->pfCmdTimeoutHandler( + prGlueInfo->prAdapter, prCmdInfo); + else + wlanReleaseCommand(prGlueInfo->prAdapter, + prCmdInfo, TX_RESULT_QUEUE_CLEARANCE); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingCmdNum); + } else + QUEUE_INSERT_TAIL(prReturnCmdQue, prQueueEntry); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(prCmdQue, prReturnCmdQue); + 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 struct GLUE_INFO *prGlueInfo) +{ + struct QUE *prCmdQue; + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue = &rTempCmdQue; + struct QUE rReturnCmdQue; + struct QUE *prReturnCmdQue = &rReturnCmdQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + QUEUE_INITIALIZE(prReturnCmdQue); + /* Clear pending management frames in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) { + wlanReleaseCommand(prGlueInfo->prAdapter, prCmdInfo, + TX_RESULT_QUEUE_CLEARANCE); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingCmdNum); + } else { + QUEUE_INSERT_TAIL(prReturnCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(prCmdQue, prReturnCmdQue); + 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 kalClearMgmtFramesByBssIdx(IN struct GLUE_INFO + *prGlueInfo, IN uint8_t ucBssIndex) +{ + struct QUE *prCmdQue; + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue = &rTempCmdQue; + struct QUE rReturnCmdQue; + struct QUE *prReturnCmdQue = &rReturnCmdQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) NULL; + struct MSDU_INFO *prMsduInfo; + u_int8_t fgFree; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + QUEUE_INITIALIZE(prReturnCmdQue); + /* Clear pending management frames in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + prMsduInfo = prCmdInfo->prMsduInfo; + fgFree = FALSE; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME + && prMsduInfo) { + if (prMsduInfo->ucBssIndex == ucBssIndex) + fgFree = TRUE; + } + + if (fgFree) { + wlanReleaseCommand(prGlueInfo->prAdapter, prCmdInfo, + TX_RESULT_QUEUE_CLEARANCE); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingCmdNum); + } else { + QUEUE_INSERT_TAIL(prReturnCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(prCmdQue, prReturnCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); +} /* kalClearMgmtFramesByBssIdx */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to clear all commands in command queue + * \param prGlueInfo Pointer of GLUE Data Structure + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +void kalClearCommandQueue(IN struct GLUE_INFO *prGlueInfo) +{ + struct QUE *prCmdQue; + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue = &rTempCmdQue; + struct QUE rReturnCmdQue; + struct QUE *prReturnCmdQue = &rReturnCmdQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + QUEUE_INITIALIZE(prReturnCmdQue); + + /* Clear ALL in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + while (prQueueEntry) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + + if (prCmdInfo->pfCmdTimeoutHandler) + prCmdInfo->pfCmdTimeoutHandler(prGlueInfo->prAdapter, + prCmdInfo); + else + wlanReleaseCommand(prGlueInfo->prAdapter, prCmdInfo, + TX_RESULT_QUEUE_CLEARANCE); + + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingCmdNum); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } +} + +uint32_t kalProcessTxPacket(struct GLUE_INFO *prGlueInfo, + struct sk_buff *prSkb) +{ + uint32_t u4Status = WLAN_STATUS_SUCCESS; + + if (prSkb == NULL) { + DBGLOG(INIT, WARN, "prSkb == NULL in tx\n"); + return u4Status; + } + + /* Handle security frame */ + if (0 /* GLUE_TEST_PKT_FLAG(prSkb, ENUM_PKT_1X) */ + /* No more sending via cmd */) { + if (wlanProcessSecurityFrame(prGlueInfo->prAdapter, + (void *) prSkb)) { + u4Status = WLAN_STATUS_SUCCESS; + GLUE_INC_REF_CNT( + prGlueInfo->i4TxPendingSecurityFrameNum); + } else { + u4Status = WLAN_STATUS_RESOURCES; + } + } + /* Handle normal frame */ + else + u4Status = wlanEnqueueTxPacket(prGlueInfo->prAdapter, + (void *) prSkb); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to process Tx request to main_thread + * + * \param prGlueInfo Pointer of GLUE Data Structure + * + * \retval none + */ +/*----------------------------------------------------------------------------*/ +void kalProcessTxReq(struct GLUE_INFO *prGlueInfo, + u_int8_t *pfgNeedHwAccess) +{ + struct QUE *prCmdQue = NULL; + struct QUE *prTxQueue = NULL; + struct QUE rTempQue; + struct QUE *prTempQue = &rTempQue; + struct QUE rTempReturnQue; + struct QUE *prTempReturnQue = &rTempReturnQue; + struct QUE_ENTRY *prQueueEntry = NULL; + /* struct sk_buff *prSkb = NULL; */ + uint32_t u4Status; +#if CFG_SUPPORT_MULTITHREAD + uint32_t u4CmdCount = 0; +#endif + uint32_t u4TxLoopCount; + + /* for spin lock acquire and release */ + GLUE_SPIN_LOCK_DECLARATION(); + + prTxQueue = &prGlueInfo->rTxQueue; + prCmdQue = &prGlueInfo->rCmdQueue; + + QUEUE_INITIALIZE(prTempQue); + QUEUE_INITIALIZE(prTempReturnQue); + + u4TxLoopCount = + prGlueInfo->prAdapter->rWifiVar.u4TxFromOsLoopCount; + + /* Process Mailbox Messages */ + wlanProcessMboxMessage(prGlueInfo->prAdapter); + + /* Process CMD request */ +#if CFG_SUPPORT_MULTITHREAD + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + u4CmdCount = prCmdQue->u4NumElem; + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + if (u4CmdCount > 0) + wlanProcessCommandQueue(prGlueInfo->prAdapter, prCmdQue); + +#else + if (prCmdQue->u4NumElem > 0) { + if (*pfgNeedHwAccess == FALSE) { + *pfgNeedHwAccess = TRUE; + + wlanAcquirePowerControl(prGlueInfo->prAdapter); + } + wlanProcessCommandQueue(prGlueInfo->prAdapter, prCmdQue); + } +#endif + + while (u4TxLoopCount--) { + while (QUEUE_IS_NOT_EMPTY(prTxQueue)) { + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_MOVE_ALL(prTempQue, prTxQueue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + + /* Handle Packet Tx */ + while (QUEUE_IS_NOT_EMPTY(prTempQue)) { + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, + struct QUE_ENTRY *); + + if (prQueueEntry == NULL) + break; + + u4Status = kalProcessTxPacket(prGlueInfo, + (struct sk_buff *) + GLUE_GET_PKT_DESCRIPTOR( + prQueueEntry)); +#if 0 + prSkb = (struct sk_buff *) + GLUE_GET_PKT_DESCRIPTOR(prQueueEntry); + ASSERT(prSkb); + if (prSkb == NULL) { + DBGLOG(INIT, WARN, + "prSkb == NULL in tx\n"); + continue; + } + + /* Handle security frame */ + if (GLUE_GET_PKT_IS_1X(prSkb)) { + if (wlanProcessSecurityFrame( + prGlueInfo->prAdapter, + (void *)prSkb)) { + u4Status = WLAN_STATUS_SUCCESS; + GLUE_INC_REF_CNT(prGlueInfo-> + i4TxPendingSecurityFrameNum); + } else { + u4Status = + WLAN_STATUS_RESOURCES; + } + } + /* Handle normal frame */ + else + u4Status = wlanEnqueueTxPacket( + prGlueInfo->prAdapter, + (void *) prSkb); +#endif + /* Enqueue packet back into TxQueue if resource + * is not enough + */ + if (u4Status == WLAN_STATUS_RESOURCES) { + QUEUE_INSERT_TAIL(prTempReturnQue, + prQueueEntry); + break; + } + } + + if (wlanGetTxPendingFrameCount( + prGlueInfo->prAdapter) > 0) + wlanTxPendingPackets(prGlueInfo->prAdapter, + pfgNeedHwAccess); + + /* Enqueue packet back into TxQueue if resource is not + * enough + */ + if (QUEUE_IS_NOT_EMPTY(prTempReturnQue)) { + QUEUE_CONCATENATE_QUEUES(prTempReturnQue, + prTempQue); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, + SPIN_LOCK_TX_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(prTxQueue, + prTempReturnQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, + SPIN_LOCK_TX_QUE); + + break; + } + } + + if (wlanGetTxPendingFrameCount(prGlueInfo->prAdapter) > 0) + wlanTxPendingPackets(prGlueInfo->prAdapter, + pfgNeedHwAccess); + } + +} + +#if CFG_SUPPORT_MULTITHREAD +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param data data pointer to private data of hif_thread + * + * @retval If the function succeeds, the return value is 0. + * Otherwise, an error code is returned. + * + */ +/*----------------------------------------------------------------------------*/ +int hif_thread(void *data) +{ + struct net_device *dev = data; + struct GLUE_INFO *prGlueInfo = *((struct GLUE_INFO **) + netdev_priv(dev)); + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + int ret = 0; + + KAL_WAKE_LOCK_INIT(prAdapter, &rHifThreadWakeLock, "WLAN hif_thread"); + KAL_WAKE_LOCK(prAdapter, &rHifThreadWakeLock); + + DBGLOG(INIT, INFO, "%s:%u starts running...\n", + KAL_GET_CURRENT_THREAD_NAME(), KAL_GET_CURRENT_THREAD_ID()); + + prGlueInfo->u4HifThreadPid = KAL_GET_CURRENT_THREAD_ID(); + + set_user_nice(current, prAdapter->rWifiVar.cThreadNice); + + while (TRUE) { + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT +#if CFG_CHIP_RESET_SUPPORT + || kalIsResetting() +#endif + ) { + DBGLOG(INIT, INFO, "hif_thread should stop now...\n"); + break; + } + + /* Unlock wakelock if hif_thread going to idle */ + if (!(prGlueInfo->ulFlag & GLUE_FLAG_HIF_PROCESS)) + KAL_WAKE_UNLOCK(prAdapter, &rHifThreadWakeLock); + + /* + * 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 + * + */ + do { + ret = wait_event_interruptible(prGlueInfo->waitq_hif, + ((prGlueInfo->ulFlag & GLUE_FLAG_HIF_PROCESS) + != 0)); + } while (ret != 0); +#if CFG_ENABLE_WAKE_LOCK + if (!KAL_WAKE_LOCK_ACTIVE(prAdapter, &rHifThreadWakeLock)) + KAL_WAKE_LOCK(prAdapter, &rHifThreadWakeLock); +#endif + if (prAdapter->fgIsFwOwn + && (prGlueInfo->ulFlag == GLUE_FLAG_HIF_FW_OWN)) { + DBGLOG(INIT, INFO, + "Only FW OWN request, but now already done FW OWN\n"); + clear_bit(GLUE_FLAG_HIF_FW_OWN_BIT, + &prGlueInfo->ulFlag); + continue; + } + wlanAcquirePowerControl(prAdapter); + + /* Handle Interrupt */ + if (test_and_clear_bit(GLUE_FLAG_INT_BIT, + &prGlueInfo->ulFlag)) { + /* the Wi-Fi interrupt is already disabled in mmc + * thread, so we set the flag only to enable the + * interrupt later + */ + prAdapter->fgIsIntEnable = FALSE; + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT +#if CFG_CHIP_RESET_SUPPORT + || kalIsResetting() +#endif + ) { + /* Should stop now... skip pending interrupt */ + DBGLOG(INIT, INFO, + "ignore pending interrupt\n"); + } else { + /* DBGLOG(INIT, INFO, ("HIF Interrupt!\n")); */ + prGlueInfo->TaskIsrCnt++; + wlanIST(prAdapter); + } + } + +#if CFG_SUPPORT_SER + + /* Skip Tx request if SER is operating */ + if ((prAdapter->fgIsFwOwn == FALSE) && + !nicSerIsTxStop(prAdapter)) { + +#else /* !CFG_SUPPORT_SER */ + + if (prAdapter->fgIsFwOwn == FALSE) { + +#endif /* CFG_SUPPORT_SER */ + /* TX Commands */ + if (test_and_clear_bit(GLUE_FLAG_HIF_TX_CMD_BIT, + &prGlueInfo->ulFlag)) + wlanTxCmdMthread(prAdapter); + + /* Process TX data packet to HIF */ + if (test_and_clear_bit(GLUE_FLAG_HIF_TX_BIT, + &prGlueInfo->ulFlag)) { + if (HAL_HAS_AGG_THREAD(prGlueInfo->prAdapter)) { + HAL_AGG_KICK_DATA + (prGlueInfo->prAdapter); + } else { + nicTxMsduQueueMthread + (prAdapter); + } + } + } + + /* Read chip status when chip no response */ + if (test_and_clear_bit(GLUE_FLAG_HIF_PRT_HIF_DBG_INFO_BIT, + &prGlueInfo->ulFlag)) + halPrintHifDbgInfo(prAdapter); + + /* Set FW own */ + if (test_and_clear_bit(GLUE_FLAG_HIF_FW_OWN_BIT, + &prGlueInfo->ulFlag)) + prAdapter->fgWiFiInSleepyState = TRUE; + + /* Release to FW own */ + wlanReleasePowerControl(prAdapter); + } + + complete(&prGlueInfo->rHifHaltComp); +#if CFG_ENABLE_WAKE_LOCK + if (KAL_WAKE_LOCK_ACTIVE(prAdapter, &rHifThreadWakeLock)) + KAL_WAKE_UNLOCK(prAdapter, &rHifThreadWakeLock); + KAL_WAKE_LOCK_DESTROY(prAdapter, &rHifThreadWakeLock); +#endif + + DBGLOG(INIT, TRACE, "%s:%u stopped!\n", + KAL_GET_CURRENT_THREAD_NAME(), KAL_GET_CURRENT_THREAD_ID()); + +#if CFG_CHIP_RESET_HANG + while (fgIsResetHangState == SER_L0_HANG_RST_HANG) { + kalMsleep(SER_L0_HANG_LOG_TIME_INTERVAL); + DBGLOG(INIT, STATE, "[SER][L0] SQC hang!\n"); + } +#endif + + return 0; +} + +int rx_thread(void *data) +{ + struct net_device *dev = data; + struct GLUE_INFO *prGlueInfo = *((struct GLUE_INFO **) + netdev_priv(dev)); + + struct QUE rTempRxQue; + struct QUE *prTempRxQue = NULL; + struct QUE_ENTRY *prQueueEntry = NULL; +#if CFG_SUPPORT_MTK_CPU_SCHED + struct cpumask *mask = ¤t->cpus_allowed; +#endif + + int ret = 0; + + uint32_t u4LoopCount; + + /* for spin lock acquire and release */ + KAL_SPIN_LOCK_DECLARATION(); + + KAL_WAKE_LOCK_INIT(prGlueInfo->prAdapter, + &rRxThreadWakeLock, "WLAN rx_thread"); + KAL_WAKE_LOCK(prGlueInfo->prAdapter, &rRxThreadWakeLock); + + DBGLOG(INIT, INFO, "%s:%u starts running...\n", + KAL_GET_CURRENT_THREAD_NAME(), KAL_GET_CURRENT_THREAD_ID()); + + prGlueInfo->u4RxThreadPid = KAL_GET_CURRENT_THREAD_ID(); + + set_user_nice(current, + prGlueInfo->prAdapter->rWifiVar.cThreadNice); +#if CFG_SUPPORT_MTK_CPU_SCHED + cpumask_clear_cpu(0, mask); + cpumask_set_cpu(1, mask); + cpumask_set_cpu(2, mask); + cpumask_set_cpu(3, mask); + mt_sched_setaffinity(0, mask); +#endif + prTempRxQue = &rTempRxQue; + + while (TRUE) { + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT +#if CFG_CHIP_RESET_SUPPORT + || kalIsResetting() +#endif + ) { + DBGLOG(INIT, INFO, "rx_thread should stop now...\n"); + break; + } + + /* Unlock wakelock if rx_thread going to idle */ + if (!(prGlueInfo->ulFlag & GLUE_FLAG_RX_PROCESS)) + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, + &rRxThreadWakeLock); + + /* + * sleep on waitqueue if no events occurred. + */ + do { + ret = wait_event_interruptible(prGlueInfo->waitq_rx, + ((prGlueInfo->ulFlag & GLUE_FLAG_RX_PROCESS) != 0)); + } while (ret != 0); +#if CFG_ENABLE_WAKE_LOCK + if (!KAL_WAKE_LOCK_ACTIVE(prGlueInfo->prAdapter, + &rRxThreadWakeLock)) + KAL_WAKE_LOCK(prGlueInfo->prAdapter, + &rRxThreadWakeLock); +#endif + if (test_and_clear_bit(GLUE_FLAG_RX_TO_OS_BIT, + &prGlueInfo->ulFlag)) { + u4LoopCount = + prGlueInfo->prAdapter->rWifiVar.u4Rx2OsLoopCount; + + while (u4LoopCount--) { + while (QUEUE_IS_NOT_EMPTY( + &prGlueInfo->prAdapter->rRxQueue)) { + QUEUE_INITIALIZE(prTempRxQue); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, + SPIN_LOCK_RX_TO_OS_QUE); + QUEUE_MOVE_ALL(prTempRxQue, + &prGlueInfo->prAdapter->rRxQueue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, + SPIN_LOCK_RX_TO_OS_QUE); + + while (QUEUE_IS_NOT_EMPTY( + prTempRxQue)) { + QUEUE_REMOVE_HEAD(prTempRxQue, + prQueueEntry, + struct QUE_ENTRY *); + kalRxIndicateOnePkt(prGlueInfo, + (void *) + GLUE_GET_PKT_DESCRIPTOR( + prQueueEntry)); + } + + KAL_WAKE_LOCK_TIMEOUT(prGlueInfo->prAdapter, + &prGlueInfo->rTimeoutWakeLock, + MSEC_TO_JIFFIES(prGlueInfo->prAdapter + ->rWifiVar.u4WakeLockRxTimeout)); + } + } + } + } + + complete(&prGlueInfo->rRxHaltComp); +#if CFG_ENABLE_WAKE_LOCK + if (KAL_WAKE_LOCK_ACTIVE(prGlueInfo->prAdapter, + &rRxThreadWakeLock)) + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, &rRxThreadWakeLock); + KAL_WAKE_LOCK_DESTROY(prGlueInfo->prAdapter, + &rRxThreadWakeLock); +#endif + + DBGLOG(INIT, TRACE, "%s:%u stopped!\n", + KAL_GET_CURRENT_THREAD_NAME(), KAL_GET_CURRENT_THREAD_ID()); + +#if CFG_CHIP_RESET_HANG + while (fgIsResetHangState == SER_L0_HANG_RST_HANG) { + kalMsleep(SER_L0_HANG_LOG_TIME_INTERVAL); + DBGLOG(INIT, STATE, "[SER][L0] SQC hang!\n"); + } +#endif + + return 0; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @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 main_thread + * + * @retval If the function succeeds, the return value is 0. + * Otherwise, an error code is returned. + * + */ +/*----------------------------------------------------------------------------*/ + +int main_thread(void *data) +{ + struct net_device *dev = data; + struct GLUE_INFO *prGlueInfo = *((struct GLUE_INFO **) + netdev_priv(dev)); + struct GL_IO_REQ *prIoReq = NULL; + int ret = 0; + u_int8_t fgNeedHwAccess = FALSE; + +#if CFG_SUPPORT_MULTITHREAD + prGlueInfo->u4TxThreadPid = KAL_GET_CURRENT_THREAD_ID(); +#endif + + current->flags |= PF_NOFREEZE; + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prAdapter); + set_user_nice(current, + prGlueInfo->prAdapter->rWifiVar.cThreadNice); + + KAL_WAKE_LOCK_INIT(prGlueInfo->prAdapter, + &rTxThreadWakeLock, "WLAN main_thread"); + KAL_WAKE_LOCK(prGlueInfo->prAdapter, &rTxThreadWakeLock); + + DBGLOG(INIT, INFO, "%s:%u starts running...\n", + KAL_GET_CURRENT_THREAD_NAME(), KAL_GET_CURRENT_THREAD_ID()); + + while (TRUE) { + +#if CFG_ENABLE_WIFI_DIRECT + /*run p2p multicast list work. */ + if (test_and_clear_bit(GLUE_FLAG_SUB_MOD_MULTICAST_BIT, + &prGlueInfo->ulFlag)) + p2pSetMulticastListWorkQueueWrapper(prGlueInfo); +#endif + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT || kalIsResetting()) { + DBGLOG(INIT, INFO, "%s should stop now...\n", + KAL_GET_CURRENT_THREAD_NAME()); + break; + } + + /* Unlock wakelock if main_thread going to idle */ + if (!(prGlueInfo->ulFlag & GLUE_FLAG_MAIN_PROCESS)) + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, + &rTxThreadWakeLock); + + /* + * 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 + */ + do { + ret = wait_event_interruptible(prGlueInfo->waitq, + ((prGlueInfo->ulFlag & GLUE_FLAG_MAIN_PROCESS) + != 0)); + } while (ret != 0); +#if CFG_ENABLE_WAKE_LOCK + if (!KAL_WAKE_LOCK_ACTIVE(prGlueInfo->prAdapter, + &rTxThreadWakeLock)) + KAL_WAKE_LOCK(prGlueInfo->prAdapter, + &rTxThreadWakeLock); +#endif + +#if CFG_ENABLE_WIFI_DIRECT + /*run p2p multicast list work. */ + if (test_and_clear_bit(GLUE_FLAG_SUB_MOD_MULTICAST_BIT, + &prGlueInfo->ulFlag)) + p2pSetMulticastListWorkQueueWrapper(prGlueInfo); + + if (test_and_clear_bit(GLUE_FLAG_FRAME_FILTER_BIT, + &prGlueInfo->ulFlag)) { + p2pFuncUpdateMgmtFrameRegister(prGlueInfo->prAdapter, + prGlueInfo->prP2PDevInfo->u4OsMgmtFrameFilter); + } +#endif + if (test_and_clear_bit(GLUE_FLAG_FRAME_FILTER_AIS_BIT, + &prGlueInfo->ulFlag)) { + aisFuncUpdateMgmtFrameRegister(prGlueInfo->prAdapter, + prGlueInfo->u4OsMgmtFrameFilter); + } + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT || kalIsResetting()) { + DBGLOG(INIT, INFO, "%s should stop now...\n", + KAL_GET_CURRENT_THREAD_NAME()); + break; + } + + fgNeedHwAccess = FALSE; + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN + if (prGlueInfo->fgEnSdioTestPattern == TRUE) { + if (fgNeedHwAccess == FALSE) { + fgNeedHwAccess = TRUE; + + wlanAcquirePowerControl(prGlueInfo->prAdapter); + } + + if (prGlueInfo->fgIsSdioTestInitialized == FALSE) { + /* enable PRBS mode */ + kalDevRegWrite(prGlueInfo, MCR_WTMCR, + 0x00080002); + prGlueInfo->fgIsSdioTestInitialized = TRUE; + } + + if (prGlueInfo->fgSdioReadWriteMode == TRUE) { + /* read test */ + kalDevPortRead(prGlueInfo, MCR_WTMDR, 256, + prGlueInfo->aucSdioTestBuffer, + sizeof(prGlueInfo->aucSdioTestBuffer)); + } else { + /* write test */ + kalDevPortWrite(prGlueInfo, MCR_WTMDR, 172, + prGlueInfo->aucSdioTestBuffer, + sizeof(prGlueInfo->aucSdioTestBuffer)); + } + } +#endif +#if CFG_SUPPORT_MULTITHREAD +#else + /* Handle Interrupt */ + if (test_and_clear_bit(GLUE_FLAG_INT_BIT, + &prGlueInfo->ulFlag)) { + + if (fgNeedHwAccess == FALSE) { + fgNeedHwAccess = TRUE; + + wlanAcquirePowerControl(prGlueInfo->prAdapter); + } + + /* the Wi-Fi interrupt is already disabled in mmc + * thread, so we set the flag only to enable the + * interrupt later + */ + prGlueInfo->prAdapter->fgIsIntEnable = FALSE; + /* wlanISR(prGlueInfo->prAdapter, TRUE); */ + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT || + kalIsResetting()) { + /* Should stop now... skip pending interrupt */ + DBGLOG(INIT, INFO, + "ignore pending interrupt\n"); + } else { + prGlueInfo->TaskIsrCnt++; + wlanIST(prGlueInfo->prAdapter); + } + } +#endif + /* transfer ioctl to OID request */ + + do { + if (test_and_clear_bit(GLUE_FLAG_OID_BIT, + &prGlueInfo->ulFlag)) { + g_fgIsOid = TRUE; + /* get current prIoReq */ + prIoReq = &(prGlueInfo->OidEntry); + if (prIoReq->fgRead == FALSE) { + 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 ONLY if there are waiters */ + if (!completion_done( + &prGlueInfo->rPendComp)) + complete( + &prGlueInfo->rPendComp); + else + DBGLOG(INIT, WARN, + "SKIP multiple OID complete!\n" + ); + } 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 (test_and_clear_bit(GLUE_FLAG_TXREQ_BIT, + &prGlueInfo->ulFlag)) + kalProcessTxReq(prGlueInfo, &fgNeedHwAccess); +#if CFG_SUPPORT_MULTITHREAD + /* Process RX */ + if (test_and_clear_bit(GLUE_FLAG_RX_BIT, + &prGlueInfo->ulFlag)) + nicRxProcessRFBs(prGlueInfo->prAdapter); + if (test_and_clear_bit(GLUE_FLAG_TX_CMD_DONE_BIT, + &prGlueInfo->ulFlag)) + wlanTxCmdDoneMthread(prGlueInfo->prAdapter); +#endif + + /* 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 CFG_SUPPORT_MULTITHREAD +#else + if (fgNeedHwAccess == TRUE) + wlanReleasePowerControl(prGlueInfo->prAdapter); +#endif + /* handle cnmTimer time out */ + if (test_and_clear_bit(GLUE_FLAG_TIMEOUT_BIT, + &prGlueInfo->ulFlag)) + wlanTimerTimeoutCheck(prGlueInfo->prAdapter); +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN + if (prGlueInfo->fgEnSdioTestPattern == TRUE) + kalSetEvent(prGlueInfo); +#endif + } + +#if 0 + if (fgNeedHwAccess == TRUE) + wlanReleasePowerControl(prGlueInfo->prAdapter); +#endif + + /* flush the pending TX packets */ + if (GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum) > 0) + kalFlushPendingTxPackets(prGlueInfo); + + /* flush pending security frames */ + if (GLUE_GET_REF_CNT( + prGlueInfo->i4TxPendingSecurityFrameNum) > 0) + kalClearSecurityFrames(prGlueInfo); + + /* remove pending oid */ + wlanReleasePendingOid(prGlueInfo->prAdapter, 0); + + complete(&prGlueInfo->rHaltComp); +#if CFG_ENABLE_WAKE_LOCK + if (KAL_WAKE_LOCK_ACTIVE(prGlueInfo->prAdapter, + &rTxThreadWakeLock)) + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, &rTxThreadWakeLock); + KAL_WAKE_LOCK_DESTROY(prGlueInfo->prAdapter, + &rTxThreadWakeLock); +#endif + + DBGLOG(INIT, TRACE, "%s:%u stopped!\n", + KAL_GET_CURRENT_THREAD_NAME(), KAL_GET_CURRENT_THREAD_ID()); + +#if CFG_CHIP_RESET_HANG + while (fgIsResetHangState == SER_L0_HANG_RST_HANG) { + kalMsleep(SER_L0_HANG_LOG_TIME_INTERVAL); + DBGLOG(INIT, STATE, "[SER][L0] SQC hang!\n"); + } +#endif + + 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalIsCardRemoved(IN struct GLUE_INFO *prGlueInfo) +{ + ASSERT(prGlueInfo); + + return FALSE; + /* Linux MMC doesn't have removal notification yet */ +} +#ifdef CONFIG_IDME +#ifdef CFG_SUPPORT_DUAL_CARD_DUAL_DRIVER +/* Support dual NIC in IDME mode */ +#define IDME_MACADDR "/proc/idme/mac_addr2" +#else +#define IDME_MACADDR "/proc/idme/mac_addr" +#endif +static int idme_get_mac_addr(unsigned char *mac_addr, size_t addr_len) +{ + unsigned char buf[IFHWADDRLEN * 2 + 1] = {""}, str[3] = {""}; + int i, mac[IFHWADDRLEN]; + struct file *f; + size_t len; + + if (!mac_addr || addr_len < IFHWADDRLEN) { + DBGLOG(INIT, ERROR, "invalid mac_addr ptr or buf\n"); + return -1; + } + + f = filp_open(IDME_MACADDR, O_RDONLY, 0); + if (IS_ERR(f)) { + DBGLOG(INIT, ERROR, "can't open mac addr file\n"); + return -1; + } + + kalFileRead(f, f->f_pos, buf, IFHWADDRLEN * 2); + + if (strlen(buf) != IFHWADDRLEN * 2) + goto bailout; + + for (i = 0; i < IFHWADDRLEN; i++) { + str[0] = buf[i * 2]; + str[1] = buf[i * 2 + 1]; + if (!isxdigit(str[0]) || !isxdigit(str[1])) + goto bailout; + len = sscanf(str, "%02x", &mac[i]); + if (len != 1) + goto bailout; + } + for (i = 0; i < IFHWADDRLEN; i++) + mac_addr[i] = (unsigned char)mac[i]; + return 0; +bailout: + DBGLOG(INIT, ERROR, "wrong mac addr %02x %02x\n", buf[0], buf[1]); + return -1; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to send command to firmware for overriding + * netweork address + * + * \param pvGlueInfo Pointer of GLUE Data Structure + * + * \retval TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalRetrieveNetworkAddress(IN struct GLUE_INFO *prGlueInfo, + IN OUT uint8_t *prMacAddr) +{ + ASSERT(prGlueInfo); + + /* Get MAC address override from wlan feature option */ + prGlueInfo->fgIsMacAddrOverride = + prGlueInfo->prAdapter->rWifiVar.ucMacAddrOverride; + + wlanHwAddrToBin( + prGlueInfo->prAdapter->rWifiVar.aucMacAddrStr, + prGlueInfo->rMacAddrOverride); + +#ifdef CONFIG_IDME + if (prMacAddr && 0 == idme_get_mac_addr((unsigned char *)prMacAddr, + (sizeof(uint8_t) * PARAM_MAC_ADDR_LEN))) { + DBGLOG(INIT, INFO, "use IDME mac addr\n"); + return TRUE; + } +#endif + + if (prGlueInfo->fgIsMacAddrOverride == FALSE) { + +#ifdef CFG_ENABLE_EFUSE_MAC_ADDR + if (prGlueInfo->prAdapter->fgIsEmbbededMacAddrValid) { + COPY_MAC_ADDR(prMacAddr, + prGlueInfo->prAdapter->rWifiVar.aucMacAddress); + return TRUE; + } else { + return FALSE; + } +#else + if (prGlueInfo->fgNvramAvailable == FALSE) { + DBGLOG(INIT, INFO, "glLoadNvram fail\n"); + return FALSE; + } + kalMemCopy(prMacAddr, prGlueInfo->rRegInfo.aucMacAddr, + PARAM_MAC_ADDR_LEN * sizeof(uint8_t)); + return TRUE; +#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 struct GLUE_INFO + *prGlueInfo) +{ + struct QUE *prTxQue; + struct QUE_ENTRY *prQueueEntry; + void *prPacket; + + ASSERT(prGlueInfo); + + prTxQue = &(prGlueInfo->rTxQueue); + + if (GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum) == 0) + return; + + if (HAL_IS_TX_DIRECT()) { + nicTxDirectClearSkbQ(prGlueInfo->prAdapter); + } else { + GLUE_SPIN_LOCK_DECLARATION(); + + while (TRUE) { + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_REMOVE_HEAD(prTxQue, prQueueEntry, + struct QUE_ENTRY *); + 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 ENUM_PARAM_MEDIA_STATE kalGetMediaStateIndicated( + IN struct GLUE_INFO *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 struct GLUE_INFO + *prGlueInfo, IN enum ENUM_PARAM_MEDIA_STATE + 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 struct GLUE_INFO *prGlueInfo) +{ + struct QUE *prCmdQue; + struct QUE rTempCmdQue; + struct QUE *prTempCmdQue = &rTempCmdQue; + struct QUE rReturnCmdQue; + struct QUE *prReturnCmdQue = &rReturnCmdQue; + struct QUE_ENTRY *prQueueEntry = (struct QUE_ENTRY *) NULL; + struct CMD_INFO *prCmdInfo = (struct CMD_INFO *) NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + QUEUE_INITIALIZE(prReturnCmdQue); + + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + while (prQueueEntry) { + + if (((struct CMD_INFO *) prQueueEntry)->fgIsOid) { + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + break; + } + QUEUE_INSERT_TAIL(prReturnCmdQue, prQueueEntry); + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, + struct QUE_ENTRY *); + } + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(prCmdQue, prReturnCmdQue); + QUEUE_CONCATENATE_QUEUES_HEAD(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); + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingCmdNum); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct GLUE_INFO *prGlueInfo, + IN struct QUE_ENTRY *prQueueEntry) +{ + struct QUE *prCmdQue; + struct CMD_INFO *prCmdInfo; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + ASSERT(prQueueEntry); + + prCmdQue = &prGlueInfo->rCmdQueue; + + prCmdInfo = (struct CMD_INFO *) prQueueEntry; + + DBGLOG(INIT, INFO, + "EN-Q CMD TYPE[%u] ID[0x%02X] SEQ[%u] to CMD Q\n", + prCmdInfo->eCmdType, prCmdInfo->ucCID, + prCmdInfo->ucCmdSeqNum); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingCmdNum); + 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 struct GLUE_INFO *prGlueInfo, + IN struct EVENT_ASSOC_INFO *prAssocInfo) +{ + /* to do */ +} + +/*----------------------------------------------------------------------------*/ +/*! + * * @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 struct GLUE_INFO + *prGlueInfo, IN void *pvPacket, IN uint32_t rStatus) +{ + ASSERT(pvPacket); + + /* dev_kfree_skb((struct sk_buff *) pvPacket); */ + kalSendCompleteAndAwakeQueue(prGlueInfo, pvPacket); + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum); +} + +uint32_t kalGetTxPendingFrameCount(IN struct GLUE_INFO + *prGlueInfo) +{ + ASSERT(prGlueInfo); + + return (uint32_t) (GLUE_GET_REF_CNT( + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t kalGetTxPendingCmdCount(IN struct GLUE_INFO + *prGlueInfo) +{ + ASSERT(prGlueInfo); + + return (uint32_t)GLUE_GET_REF_CNT( + prGlueInfo->i4TxPendingCmdNum); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct GLUE_INFO *prGlueInfo, + IN void *prTimerHandler) +{ + + ASSERT(prGlueInfo); +#if KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE + timer_setup(&(prGlueInfo->tickfn), prTimerHandler, 0); +#else + init_timer(&(prGlueInfo->tickfn)); + prGlueInfo->tickfn.function = prTimerHandler; + prGlueInfo->tickfn.data = (unsigned long)prGlueInfo; +#endif +} + +/* 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. + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalSetTimer(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Interval) +{ + ASSERT(prGlueInfo); + + if (HAL_IS_RX_DIRECT(prGlueInfo->prAdapter)) { + mod_timer(&prGlueInfo->tickfn, + jiffies + u4Interval * HZ / MSEC_PER_SEC); + } else { + 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalCancelTimer(IN struct GLUE_INFO *prGlueInfo) +{ + ASSERT(prGlueInfo); + + clear_bit(GLUE_FLAG_TIMEOUT_BIT, &prGlueInfo->ulFlag); + + if (del_timer_sync(&(prGlueInfo->tickfn)) >= 0) + return TRUE; + else + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is a callback function for scanning done + * + * \param[in] prGlueInfo Pointer to GLUE Data Structure + * + * \retval none + * + */ +/*----------------------------------------------------------------------------*/ +void kalScanDone(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_KAL_NETWORK_TYPE_INDEX eNetTypeIdx, + IN uint32_t status) +{ + uint8_t fgAborted = (status != WLAN_STATUS_SUCCESS) ? TRUE : FALSE; + ASSERT(prGlueInfo); + + scanLogEssResult(prGlueInfo->prAdapter); + + scanReportBss2Cfg80211(prGlueInfo->prAdapter, + BSS_TYPE_INFRASTRUCTURE, NULL); + + /* check for system configuration for generating error message on scan + * list + */ + wlanCheckSystemConfiguration(prGlueInfo->prAdapter); + + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_SCAN_COMPLETE, + &fgAborted, sizeof(fgAborted)); +} + +#if CFG_SUPPORT_SCAN_CACHE_RESULT +/*----------------------------------------------------------------------------*/ +/*! + * @brief update timestamp information of bss cache in kernel + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @return status 0 if success, error code otherwise + */ +/*----------------------------------------------------------------------------*/ +uint8_t kalUpdateBssTimestamp(IN struct GLUE_INFO *prGlueInfo) +{ + struct wiphy *wiphy; + struct cfg80211_registered_device *rdev; + struct cfg80211_internal_bss *bss = NULL; + struct cfg80211_bss_ies *ies; + uint64_t new_timestamp = kalGetBootTime(); + + ASSERT(prGlueInfo); + wiphy = priv_to_wiphy(prGlueInfo); + if (!wiphy) { + log_dbg(REQ, ERROR, "wiphy is null\n"); + return 1; + } + rdev = container_of(wiphy, struct cfg80211_registered_device, wiphy); + + log_dbg(REQ, INFO, "Update scan timestamp: %llu (%llu)\n", + new_timestamp, le64_to_cpu(new_timestamp)); + + /* add 1 ms to prevent scan time too short */ + new_timestamp += 1000; + + spin_lock_bh(&rdev->bss_lock); + list_for_each_entry(bss, &rdev->bss_list, list) { + const struct cfg80211_bss_ies *old; + + ies = kzalloc(sizeof(*ies) + bss->pub.ies->len, GFP_ATOMIC); + if (!ies) + continue; + ies->len = bss->pub.ies->len; + ies->tsf = le64_to_cpu(new_timestamp); + ies->from_beacon = bss->pub.ies->from_beacon; + memcpy(ies->data, bss->pub.ies->data, bss->pub.ies->len); + if (ies->from_beacon) { + old = rcu_access_pointer(bss->pub.beacon_ies); + rcu_assign_pointer(bss->pub.beacon_ies, ies); + } else { /* proberesp */ + old = rcu_access_pointer(bss->pub.proberesp_ies); + rcu_assign_pointer(bss->pub.proberesp_ies, ies); + } + rcu_assign_pointer(bss->pub.ies, ies); + if (old) + kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head); + } + spin_unlock_bh(&rdev->bss_lock); + + return 0; +} +#endif /* CFG_SUPPORT_SCAN_CACHE_RESULT */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to generate a random number + * + * \param none + * + * \retval UINT_32 + */ +/*----------------------------------------------------------------------------*/ +uint32_t kalRandomNumber(void) +{ + uint32_t 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) + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE +void kalTimeoutHandler(struct timer_list *timer) +#else +void kalTimeoutHandler(unsigned long arg) +#endif +{ + +#if KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE + struct GLUE_INFO *prGlueInfo = + from_timer(prGlueInfo, timer, tickfn); +#else + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) arg; +#endif + + ASSERT(prGlueInfo); + + /* Notify tx thread for timeout event */ + set_bit(GLUE_FLAG_TIMEOUT_BIT, &prGlueInfo->ulFlag); + wake_up_interruptible(&prGlueInfo->waitq); + +} + +void kalSetEvent(struct GLUE_INFO *pr) +{ + set_bit(GLUE_FLAG_TXREQ_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq); +} + +void kalSetIntEvent(struct GLUE_INFO *pr) +{ + KAL_WAKE_LOCK(pr->prAdapter, &pr->rIntrWakeLock); + + set_bit(GLUE_FLAG_INT_BIT, &pr->ulFlag); + + /* when we got interrupt, we wake up servie thread */ +#if CFG_SUPPORT_MULTITHREAD + wake_up_interruptible(&pr->waitq_hif); +#else + wake_up_interruptible(&pr->waitq); +#endif +} + +void kalSetHifDbgEvent(struct GLUE_INFO *pr) +{ + set_bit(GLUE_FLAG_HIF_PRT_HIF_DBG_INFO_BIT, &(pr->ulFlag)); +#if CFG_SUPPORT_MULTITHREAD + wake_up_interruptible(&pr->waitq_hif); +#endif +} + +#if CFG_SUPPORT_MULTITHREAD +void kalSetTxEvent2Hif(struct GLUE_INFO *pr) +{ + if (!pr->hif_thread) + return; + + KAL_WAKE_LOCK_TIMEOUT(pr->prAdapter, &pr->rTimeoutWakeLock, + MSEC_TO_JIFFIES( + pr->prAdapter->rWifiVar.u4WakeLockThreadWakeup)); + set_bit(GLUE_FLAG_HIF_TX_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq_hif); +} + +void kalSetFwOwnEvent2Hif(struct GLUE_INFO *pr) +{ + if (!pr->hif_thread) + return; + + KAL_WAKE_LOCK_TIMEOUT(pr->prAdapter, &pr->rTimeoutWakeLock, + MSEC_TO_JIFFIES( + pr->prAdapter->rWifiVar.u4WakeLockThreadWakeup)); + + set_bit(GLUE_FLAG_HIF_FW_OWN_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq_hif); +} + +void kalSetTxEvent2Rx(struct GLUE_INFO *pr) +{ + if (!pr->rx_thread) + return; + + KAL_WAKE_LOCK_TIMEOUT(pr->prAdapter, &pr->rTimeoutWakeLock, + MSEC_TO_JIFFIES( + pr->prAdapter->rWifiVar.u4WakeLockThreadWakeup)); + + set_bit(GLUE_FLAG_RX_TO_OS_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq_rx); +} + +void kalSetTxCmdEvent2Hif(struct GLUE_INFO *pr) +{ + if (!pr->hif_thread) + return; + + KAL_WAKE_LOCK_TIMEOUT(pr->prAdapter, &pr->rTimeoutWakeLock, + MSEC_TO_JIFFIES( + pr->prAdapter->rWifiVar.u4WakeLockThreadWakeup)); + + set_bit(GLUE_FLAG_HIF_TX_CMD_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq_hif); +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * \brief to check if configuration file (NVRAM/Registry) exists + * + * \param[in] + * prGlueInfo + * + * \return + * TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalIsConfigurationExist(IN struct GLUE_INFO + *prGlueInfo) +{ +#if !defined(CONFIG_X86) + ASSERT(prGlueInfo); + + return prGlueInfo->fgNvramAvailable; +#else + /* there is no configuration data for x86-linux */ + /*return FALSE;*/ + + + /*Modify for Linux PC support NVRAM Setting*/ + return prGlueInfo->fgNvramAvailable; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief to retrieve Registry information + * + * \param[in] + * prGlueInfo + * + * \return + * Pointer of REG_INFO_T + */ +/*----------------------------------------------------------------------------*/ +struct REG_INFO *kalGetConfiguration(IN struct GLUE_INFO + *prGlueInfo) +{ + ASSERT(prGlueInfo); + + return &(prGlueInfo->rRegInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief to check if the WPS is active or not + * + * \param[in] + * prGlueInfo + * + * \return + * TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalWSCGetActiveState(IN struct GLUE_INFO + *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 struct GLUE_INFO *prGlueInfo, + IN enum ENUM_KAL_NETWORK_TYPE_INDEX eNetTypeIdx, + IN int8_t cRssi, IN int8_t 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; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Pre-allocate I/O buffer + * + * \param[in] + * none + * + * \return + * TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalInitIOBuffer(u_int8_t is_pre_alloc) +{ + uint32_t u4Size; + + /* not pre-allocation for all memory usage */ + if (!is_pre_alloc) { + pvIoBuffer = NULL; + return FALSE; + } + + /* pre-allocation for all memory usage */ + if (HIF_TX_COALESCING_BUFFER_SIZE > + HIF_RX_COALESCING_BUFFER_SIZE) + u4Size = HIF_TX_COALESCING_BUFFER_SIZE; + else + u4Size = HIF_RX_COALESCING_BUFFER_SIZE; + + u4Size += HIF_EXTRA_IO_BUFFER_SIZE; + + 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) +{ + kfree(pvIoBuffer); + + pvIoBuffer = (void *) NULL; + pvIoBufferSize = 0; + pvIoBufferUsage = 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Dispatch pre-allocated I/O buffer + * + * \param[in] + * u4AllocSize + * + * \return + * PVOID for pointer of pre-allocated I/O buffer + */ +/*----------------------------------------------------------------------------*/ +void *kalAllocateIOBuffer(IN uint32_t u4AllocSize) +{ + void *ret = (void *) NULL; + + if (pvIoBuffer) { + if (u4AllocSize <= (pvIoBufferSize - pvIoBufferUsage)) { + ret = (void *) + &(((uint8_t *) (pvIoBuffer))[pvIoBufferUsage]); + pvIoBufferUsage += u4AllocSize; + } + } else { + /* fault tolerance */ + ret = (void *) kalMemAlloc(u4AllocSize, PHY_MEM_TYPE); + } + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Release all dispatched I/O buffer + * + * \param[in] + * none + * + * \return + * none + */ +/*----------------------------------------------------------------------------*/ +void kalReleaseIOBuffer(IN void *pvAddr, IN uint32_t 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 struct GLUE_INFO *prGlueInfo, + IN enum ENUM_BAND eSpecificBand, + IN uint8_t ucMaxChannelNum, IN uint8_t *pucNumOfChannel, + IN struct RF_CHANNEL_INFO *paucChannelList) +{ + rlmDomainGetChnlList(prGlueInfo->prAdapter, eSpecificBand, + FALSE, + ucMaxChannelNum, pucNumOfChannel, paucChannelList); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] prAdapter Pointer of ADAPTER_T + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalIsAPmode(IN struct GLUE_INFO *prGlueInfo) +{ +#if 0 /* Marked for MT6630 (New ucBssIndex) */ +#if CFG_ENABLE_WIFI_DIRECT + if (IS_NET_ACTIVE(prGlueInfo->prAdapter, + NETWORK_TYPE_P2P_INDEX) && + p2pFuncIsAPMode( + prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo)) + return TRUE; +#endif +#endif + + return FALSE; +} + +#if CFG_SUPPORT_802_11W +/*----------------------------------------------------------------------------*/ +/*! + * \brief to check if the MFP is DISABLD/OPTIONAL/REQUIRED + * + * \param[in] + * prGlueInfo + * + * \return + * RSN_AUTH_MFP_DISABLED + * RSN_AUTH_MFP_OPTIONAL + * RSN_AUTH_MFP_DISABLED + */ +/*----------------------------------------------------------------------------*/ +uint32_t kalGetMfpSetting(IN struct GLUE_INFO *prGlueInfo) +{ + uint32_t u4RsnMfp = RSN_AUTH_MFP_DISABLED; + + ASSERT(prGlueInfo); + + switch (prGlueInfo->rWpaInfo.u4Mfp) { + case IW_AUTH_MFP_DISABLED: + u4RsnMfp = RSN_AUTH_MFP_DISABLED; + break; + case IW_AUTH_MFP_OPTIONAL: + u4RsnMfp = RSN_AUTH_MFP_OPTIONAL; + break; + case IW_AUTH_MFP_REQUIRED: + u4RsnMfp = RSN_AUTH_MFP_REQUIRED; + break; + default: + u4RsnMfp = RSN_AUTH_MFP_DISABLED; + break; + } + + return u4RsnMfp; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief to check if the RSN IE CAP setting from supplicant + * + * \param[in] + * prGlueInfo + * + * \return + * TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +uint8_t kalGetRsnIeMfpCap(IN struct GLUE_INFO *prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->rWpaInfo.ucRSNMfpCap; +} +#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); +} + +uint32_t 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()); + +#if KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE + ret = kernel_read(file, data, size, &offset); +#else + ret = vfs_read(file, data, size, &offset); +#endif + + set_fs(oldfs); + return ret; +} + +uint32_t 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()); + +#if KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE + ret = kernel_write(file, data, size, &offset); +#else + ret = vfs_write(file, data, size, &offset); +#endif + + set_fs(oldfs); + return ret; +} + +uint32_t kalWriteToFile(const uint8_t *pucPath, + u_int8_t fgDoAppend, uint8_t *pucData, uint32_t u4Size) +{ + struct file *file = NULL; + int32_t ret = -1; + uint32_t u4Flags = 0; + + if (fgDoAppend) + u4Flags = O_APPEND; + + file = kalFileOpen(pucPath, O_WRONLY | O_CREAT | u4Flags, 0700); + if (file != NULL) { + kalFileWrite(file, 0, pucData, u4Size); + kalFileClose(file); + ret = 0; + } + return ret; +} + +int32_t kalReadToFile(const uint8_t *pucPath, + uint8_t *pucData, uint32_t u4Size, uint32_t *pu4ReadSize) +{ + struct file *file = NULL; + int32_t ret = -1; + uint32_t u4ReadSize = 0; + + DBGLOG(INIT, INFO, "kalReadToFile() path %s\n", pucPath); + + file = kalFileOpen(pucPath, O_RDONLY, 0); + + if ((file != NULL) && !IS_ERR(file)) { + u4ReadSize = kalFileRead(file, 0, pucData, u4Size); + kalFileClose(file); + if (pu4ReadSize) + *pu4ReadSize = u4ReadSize; + ret = 0; + } + return ret; +} + +uint32_t kalCheckPath(const uint8_t *pucPath) +{ + struct file *file = NULL; + uint32_t u4Flags = 0; + + file = kalFileOpen(pucPath, O_WRONLY | O_CREAT | u4Flags, 0700); + if (!file) + return -1; + + kalFileClose(file); + return 1; +} + +uint32_t kalTrunkPath(const uint8_t *pucPath) +{ + struct file *file = NULL; + uint32_t u4Flags = O_TRUNC; + + file = kalFileOpen(pucPath, O_WRONLY | O_CREAT | u4Flags, 0700); + if (!file) + return -1; + + kalFileClose(file); + return 1; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief read request firmware file binary to pucData + * + * \param[in] pucPath file name + * \param[out] pucData Request file output buffer + * \param[in] u4Size read size + * \param[out] pu4ReadSize real read size + * \param[in] dev + * + * \return + * 0 success + * >0 fail + */ +/*----------------------------------------------------------------------------*/ +int32_t kalRequestFirmware(const uint8_t *pucPath, + uint8_t *pucData, uint32_t u4Size, + uint32_t *pu4ReadSize, struct device *dev) +{ + const struct firmware *fw; + int ret = 0; + + /* + * Driver support request_firmware() to get files + * Android path: "/etc/firmware", "/vendor/firmware", "/firmware/image" + * Linux path: "/lib/firmware", "/lib/firmware/update" + */ + ret = request_firmware(&fw, pucPath, dev); + + if (ret != 0) { + DBGLOG(INIT, INFO, "kalRequestFirmware %s Fail, errno[%d]!!\n", + pucPath, ret); + pucData = NULL; + *pu4ReadSize = 0; + return ret; + } + + DBGLOG(INIT, INFO, "kalRequestFirmware(): %s OK\n", + pucPath); + + if (fw->size < u4Size) + u4Size = fw->size; + + memcpy(pucData, fw->data, u4Size); + if (pu4ReadSize) + *pu4ReadSize = u4Size; + + release_firmware(fw); + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To indicate BSS-INFO to NL80211 as scanning result + * + * \param[in] + * prGlueInfo + * pucBeaconProbeResp + * u4FrameLen + * + * + * + * \return + * none + */ +/*----------------------------------------------------------------------------*/ +void +kalIndicateBssInfo(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucBeaconProbeResp, + IN uint32_t u4FrameLen, IN uint8_t ucChannelNum, + IN int32_t 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, + KAL_BAND_2GHZ)); + } else { + prChannel = ieee80211_get_channel(wiphy, + ieee80211_channel_to_frequency(ucChannelNum, + KAL_BAND_5GHZ)); + } + + if (prChannel != NULL + && prGlueInfo->fgIsRegistered == TRUE) { + struct cfg80211_bss *bss; +#if CFG_SUPPORT_TSF_USING_BOOTTIME + struct ieee80211_mgmt *prMgmtFrame = (struct ieee80211_mgmt + *)pucBeaconProbeResp; + + prMgmtFrame->u.beacon.timestamp = kalGetBootTime(); +#endif + + kalScanResultLog(prGlueInfo->prAdapter, + (struct ieee80211_mgmt *)pucBeaconProbeResp); + + /* indicate to NL80211 subsystem */ + bss = cfg80211_inform_bss_frame(wiphy, prChannel, + (struct ieee80211_mgmt *)pucBeaconProbeResp, + u4FrameLen, i4SignalStrength * 100, GFP_KERNEL); + + if (!bss) { + /* ToDo:: DBGLOG */ + DBGLOG(REQ, WARN, + "cfg80211_inform_bss_frame() returned with NULL\n"); + } else + cfg80211_put_bss(wiphy, bss); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To indicate channel ready + * + * \param[in] + * prGlueInfo + * + * \return + * none + */ +/*----------------------------------------------------------------------------*/ +void +kalReadyOnChannel(IN struct GLUE_INFO *prGlueInfo, + IN uint64_t u8Cookie, + IN enum ENUM_BAND eBand, IN enum ENUM_CHNL_EXT eSco, + IN uint8_t ucChannelNum, IN uint32_t u4DurationMs) +{ + struct ieee80211_channel *prChannel = NULL; + enum nl80211_channel_type rChannelType; + + /* ucChannelNum = wlanGetChannelNumberByNetwork(prGlueInfo->prAdapter, + * NETWORK_TYPE_AIS_INDEX); + */ + + if (prGlueInfo->fgIsRegistered == TRUE) { + if (ucChannelNum <= 14) { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, + KAL_BAND_2GHZ)); + } else { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, + KAL_BAND_5GHZ)); + } + + if (prChannel == NULL) { + DBGLOG(AIS, WARN, + "prChannel is null"); + return; + } + + switch (eSco) { + case CHNL_EXT_SCN: + rChannelType = NL80211_CHAN_NO_HT; + break; + + case CHNL_EXT_SCA: + rChannelType = NL80211_CHAN_HT40MINUS; + break; + + case CHNL_EXT_SCB: + rChannelType = NL80211_CHAN_HT40PLUS; + break; + + case CHNL_EXT_RES: + default: + rChannelType = NL80211_CHAN_HT20; + break; + } + + cfg80211_ready_on_channel( + prGlueInfo->prDevHandler->ieee80211_ptr, + u8Cookie, prChannel, u4DurationMs, GFP_KERNEL); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To indicate channel expiration + * + * \param[in] + * prGlueInfo + * + * \return + * none + */ +/*----------------------------------------------------------------------------*/ +void +kalRemainOnChannelExpired(IN struct GLUE_INFO *prGlueInfo, + IN uint64_t u8Cookie, IN enum ENUM_BAND eBand, + IN enum ENUM_CHNL_EXT eSco, IN uint8_t ucChannelNum) +{ + struct ieee80211_channel *prChannel = NULL; + enum nl80211_channel_type rChannelType; + + ucChannelNum = + wlanGetChannelNumberByNetwork(prGlueInfo->prAdapter, + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex); + + if (prGlueInfo->fgIsRegistered == TRUE) { + if (ucChannelNum <= 14) { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, + KAL_BAND_2GHZ)); + } else { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, + KAL_BAND_5GHZ)); + } + + if (prChannel == NULL) { + DBGLOG(AIS, WARN, + "prChannel is null"); + return; + } + + switch (eSco) { + case CHNL_EXT_SCN: + rChannelType = NL80211_CHAN_NO_HT; + break; + + case CHNL_EXT_SCA: + rChannelType = NL80211_CHAN_HT40MINUS; + break; + + case CHNL_EXT_SCB: + rChannelType = NL80211_CHAN_HT40PLUS; + break; + + case CHNL_EXT_RES: + default: + rChannelType = NL80211_CHAN_HT20; + break; + } + + cfg80211_remain_on_channel_expired( + prGlueInfo->prDevHandler->ieee80211_ptr, + u8Cookie, prChannel, GFP_KERNEL); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To indicate Mgmt tx status + * + * \param[in] + * prGlueInfo + * + * \return + * none + */ +/*----------------------------------------------------------------------------*/ +void +kalIndicateMgmtTxStatus(IN struct GLUE_INFO *prGlueInfo, + IN uint64_t u8Cookie, IN u_int8_t fgIsAck, + IN uint8_t *pucFrameBuf, IN uint32_t u4FrameLen) +{ + + do { + if ((prGlueInfo == NULL) + || (pucFrameBuf == NULL) + || (u4FrameLen == 0)) { + DBGLOG(AIS, TRACE, + "Unexpected pointer PARAM. 0x%lx, 0x%lx, %d.", + prGlueInfo, pucFrameBuf, u4FrameLen); + ASSERT(FALSE); + break; + } + + cfg80211_mgmt_tx_status( + prGlueInfo->prDevHandler->ieee80211_ptr, + u8Cookie, pucFrameBuf, u4FrameLen, fgIsAck, GFP_KERNEL); + + } while (FALSE); + +} /* kalIndicateMgmtTxStatus */ + +void kalIndicateRxMgmtFrame(IN struct GLUE_INFO *prGlueInfo, + IN struct SW_RFB *prSwRfb) +{ + int32_t i4Freq = 0; + uint8_t ucChnlNum = 0; + + do { + if ((prGlueInfo == NULL) || (prSwRfb == NULL)) { + ASSERT(FALSE); + break; + } + + ucChnlNum = (uint8_t) HAL_RX_STATUS_GET_CHNL_NUM( + prSwRfb->prRxStatus); + + i4Freq = nicChannelNum2Freq(ucChnlNum) / 1000; + + if (prGlueInfo->prDevHandler->ieee80211_ptr == NULL) { + DBGLOG(AIS, WARN, + "ieee80211_ptr is NULL!\n"); + break; + } + + if (prGlueInfo->u4OsMgmtFrameFilter == 0) { + DBGLOG(AIS, WARN, + "The cfg80211 hasn't do mgmt register!\n"); + break; + } + +#if (KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE) + cfg80211_rx_mgmt(prGlueInfo->prDevHandler->ieee80211_ptr, + i4Freq, /* in MHz */ + RCPI_TO_dBm((uint8_t) nicRxGetRcpiValueFromRxv( + RCPI_MODE_MAX, prSwRfb)), + prSwRfb->pvHeader, prSwRfb->u2PacketLen, + NL80211_RXMGMT_FLAG_ANSWERED); + +#elif (KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE) + cfg80211_rx_mgmt(prGlueInfo->prDevHandler->ieee80211_ptr, + i4Freq, /* in MHz */ + RCPI_TO_dBm((uint8_t) + nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0, prSwRfb)), + prSwRfb->pvHeader, prSwRfb->u2PacketLen, + NL80211_RXMGMT_FLAG_ANSWERED, + GFP_ATOMIC); +#else + cfg80211_rx_mgmt(prGlueInfo->prDevHandler->ieee80211_ptr, + i4Freq, /* in MHz */ + RCPI_TO_dBm((uint8_t) + nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0, prSwRfb)), + prSwRfb->pvHeader, prSwRfb->u2PacketLen, + GFP_ATOMIC); +#endif + + } while (FALSE); + +} /* kalIndicateRxMgmtFrame */ + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN +/*----------------------------------------------------------------------------*/ +/*! + * \brief To configure SDIO test pattern mode + * + * \param[in] + * prGlueInfo + * fgEn + * fgRead + * + * \return + * TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalSetSdioTestPattern(IN struct GLUE_INFO + *prGlueInfo, IN u_int8_t fgEn, IN u_int8_t fgRead) +{ + const uint8_t aucPattern[] = { + 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, + 0xaa, 0x55, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x80, + 0x80, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, + 0x40, 0x40, 0x40, 0xbf, 0x40, 0x40, 0x40, 0xbf, + 0xbf, 0xbf, 0x40, 0xbf, 0xbf, 0xbf, 0x20, 0x20, + 0x20, 0xdf, 0x20, 0x20, 0x20, 0xdf, 0xdf, 0xdf, + 0x20, 0xdf, 0xdf, 0xdf, 0x10, 0x10, 0x10, 0xef, + 0x10, 0x10, 0x10, 0xef, 0xef, 0xef, 0x10, 0xef, + 0xef, 0xef, 0x08, 0x08, 0x08, 0xf7, 0x08, 0x08, + 0x08, 0xf7, 0xf7, 0xf7, 0x08, 0xf7, 0xf7, 0xf7, + 0x04, 0x04, 0x04, 0xfb, 0x04, 0x04, 0x04, 0xfb, + 0xfb, 0xfb, 0x04, 0xfb, 0xfb, 0xfb, 0x02, 0x02, + 0x02, 0xfd, 0x02, 0x02, 0x02, 0xfd, 0xfd, 0xfd, + 0x02, 0xfd, 0xfd, 0xfd, 0x01, 0x01, 0x01, 0xfe, + 0x01, 0x01, 0x01, 0xfe, 0xfe, 0xfe, 0x01, 0xfe, + 0xfe, 0xfe, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff + }; + uint32_t i; + + ASSERT(prGlueInfo); + + /* access to MCR_WTMCR to engage PRBS mode */ + prGlueInfo->fgEnSdioTestPattern = fgEn; + prGlueInfo->fgSdioReadWriteMode = fgRead; + + if (fgRead == FALSE) { + /* fill buffer for data to be written */ + for (i = 0; i < sizeof(aucPattern); i++) + prGlueInfo->aucSdioTestBuffer[i] = aucPattern[i]; + } + + return TRUE; +} +#endif + +#if (CFG_MET_PACKET_TRACE_SUPPORT == 1) +#define PROC_MET_PROF_CTRL "met_ctrl" +#define PROC_MET_PROF_PORT "met_port" + +struct proc_dir_entry *pMetProcDir; +void *pMetGlobalData; + +#endif +/*----------------------------------------------------------------------------*/ +/*! + * \brief To indicate scheduled scan results are avilable + * + * \param[in] + * prGlueInfo + * + * \return + * None + */ +/*----------------------------------------------------------------------------*/ +void kalSchedScanResults(IN struct GLUE_INFO *prGlueInfo) +{ + ASSERT(prGlueInfo); + scanReportBss2Cfg80211(prGlueInfo->prAdapter, + BSS_TYPE_INFRASTRUCTURE, NULL); + + scanlog_dbg(LOG_SCHED_SCAN_DONE_D2K, INFO, "Call cfg80211_sched_scan_results\n"); +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE + cfg80211_sched_scan_results(priv_to_wiphy(prGlueInfo), 0); +#else + cfg80211_sched_scan_results(priv_to_wiphy(prGlueInfo)); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To indicate scheduled scan has been stopped + * + * \param[in] + * prGlueInfo + * + * \return + * None + */ +/*----------------------------------------------------------------------------*/ +void kalSchedScanStopped(IN struct GLUE_INFO *prGlueInfo, + u_int8_t fgDriverTriggerd) +{ + /* DBGLOG(SCN, INFO, ("-->kalSchedScanStopped\n" )); */ + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + +#if 1 + /* 1. reset first for newly incoming request */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if (prGlueInfo->prSchedScanRequest != NULL) + prGlueInfo->prSchedScanRequest = NULL; + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); +#endif + DBGLOG(SCN, INFO, "Driver triggerd %d\n", fgDriverTriggerd); + + /* 2. indication to cfg80211 */ + /* 20150205 change cfg80211_sched_scan_stopped to work queue to use K + * thread to send event instead of Tx thread + * due to sched_scan_mtx dead lock issue by Tx thread serves oid cmds + * and send event in the same time + */ + if (fgDriverTriggerd) { + DBGLOG(SCN, INFO, "start work queue to send event\n"); + schedule_delayed_work(&sched_workq, 0); + DBGLOG(SCN, INFO, "main_thread return from %s\n", __func__); + } +} + +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG +/*----------------------------------------------------------------------------*/ +/*! + * \brief To check if device if wake up by wlan + * + * \param[in] + * prAdapter + * + * \return + * TRUE: wake up by wlan; otherwise, FALSE + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalIsWakeupByWlan(struct ADAPTER *prAdapter) +{ + /* + * SUSPEND_FLAG_FOR_WAKEUP_REASON is set means system has suspended, + * but may be failed duo to some driver suspend failed. so we need + * help of function slp_get_wake_reason + */ + if (test_and_clear_bit(SUSPEND_FLAG_FOR_WAKEUP_REASON, + &prAdapter->ulSuspendFlag) == 0) + return FALSE; + + return TRUE; +} +#endif + + + +u_int8_t +kalGetIPv4Address(IN struct net_device *prDev, + IN uint32_t u4MaxNumOfAddr, OUT uint8_t *pucIpv4Addrs, + OUT uint32_t *pu4NumOfIpv4Addr) +{ + uint32_t u4NumIPv4 = 0; + uint32_t u4AddrLen = IPV4_ADDR_LEN; + struct in_ifaddr *prIfa; + + /* 4 <1> Sanity check of netDevice */ + if (!prDev || !(prDev->ip_ptr) + || !((struct in_device *)(prDev->ip_ptr))->ifa_list) { + DBGLOG(INIT, INFO, + "IPv4 address is not available for dev(0x%p)\n", prDev); + + *pu4NumOfIpv4Addr = 0; + return FALSE; + } + + prIfa = ((struct in_device *)(prDev->ip_ptr))->ifa_list; + + /* 4 <2> copy the IPv4 address */ + while ((u4NumIPv4 < u4MaxNumOfAddr) && prIfa) { + kalMemCopy(&pucIpv4Addrs[u4NumIPv4 * u4AddrLen], + &prIfa->ifa_local, u4AddrLen); + prIfa = prIfa->ifa_next; + + DBGLOG(INIT, INFO, + "IPv4 addr [%u][" IPV4STR "]\n", u4NumIPv4, + IPV4TOSTR(&pucIpv4Addrs[u4NumIPv4 * u4AddrLen])); + + u4NumIPv4++; + } + + *pu4NumOfIpv4Addr = u4NumIPv4; + + return TRUE; +} + +#if IS_ENABLED(CONFIG_IPV6) +u_int8_t +kalGetIPv6Address(IN struct net_device *prDev, + IN uint32_t u4MaxNumOfAddr, OUT uint8_t *pucIpv6Addrs, + OUT uint32_t *pu4NumOfIpv6Addr) +{ + uint32_t u4NumIPv6 = 0; + uint32_t u4AddrLen = IPV6_ADDR_LEN; + struct inet6_ifaddr *prIfa; + + /* 4 <1> Sanity check of netDevice */ + if (!prDev || !(prDev->ip6_ptr)) { + DBGLOG(INIT, INFO, + "IPv6 address is not available for dev(0x%p)\n", prDev); + + *pu4NumOfIpv6Addr = 0; + return FALSE; + } + + + /* 4 <2> copy the IPv6 address */ + LIST_FOR_EACH_IPV6_ADDR(prIfa, prDev->ip6_ptr) { + kalMemCopy(&pucIpv6Addrs[u4NumIPv6 * u4AddrLen], + &prIfa->addr, u4AddrLen); + + DBGLOG(INIT, INFO, + "IPv6 addr [%u][" IPV6STR "]\n", u4NumIPv6, + IPV6TOSTR(&pucIpv6Addrs[u4NumIPv6 * u4AddrLen])); + + if ((u4NumIPv6 + 1) >= u4MaxNumOfAddr) + break; + u4NumIPv6++; + } + + *pu4NumOfIpv6Addr = u4NumIPv6; + + return TRUE; +} +#endif /* IS_ENABLED(CONFIG_IPV6) */ + +void +kalSetNetAddress(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucBssIdx, + IN uint8_t *pucIPv4Addr, IN uint32_t u4NumIPv4Addr, + IN uint8_t *pucIPv6Addr, IN uint32_t u4NumIPv6Addr) +{ + uint32_t rStatus = WLAN_STATUS_FAILURE; + uint32_t u4SetInfoLen = 0; + uint32_t u4Len = OFFSET_OF(struct + PARAM_NETWORK_ADDRESS_LIST, arAddress); + struct PARAM_NETWORK_ADDRESS_LIST *prParamNetAddrList; + struct PARAM_NETWORK_ADDRESS *prParamNetAddr; + uint32_t i, u4AddrLen; + + /* 4 <1> Calculate buffer size */ + /* IPv4 */ + u4Len += (((sizeof(struct PARAM_NETWORK_ADDRESS) - 1) + + IPV4_ADDR_LEN) * u4NumIPv4Addr); + /* IPv6 */ + u4Len += (((sizeof(struct PARAM_NETWORK_ADDRESS) - 1) + + IPV6_ADDR_LEN) * u4NumIPv6Addr); + + /* 4 <2> Allocate buffer */ + prParamNetAddrList = (struct PARAM_NETWORK_ADDRESS_LIST *) + kalMemAlloc(u4Len, VIR_MEM_TYPE); + + if (!prParamNetAddrList) { + DBGLOG(INIT, WARN, + "Fail to alloc buffer for setting BSS[%u] network address!\n", + ucBssIdx); + return; + } + /* 4 <3> Fill up network address */ + prParamNetAddrList->u2AddressType = + PARAM_PROTOCOL_ID_TCP_IP; + prParamNetAddrList->u4AddressCount = 0; + prParamNetAddrList->ucBssIdx = ucBssIdx; + + /* 4 <3.1> Fill up IPv4 address */ + u4AddrLen = IPV4_ADDR_LEN; + prParamNetAddr = prParamNetAddrList->arAddress; + for (i = 0; i < u4NumIPv4Addr; i++) { + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + prParamNetAddr->u2AddressLength = u4AddrLen; + kalMemCopy(prParamNetAddr->aucAddress, + &pucIPv4Addr[i * u4AddrLen], u4AddrLen); + + prParamNetAddr = (struct PARAM_NETWORK_ADDRESS *) (( + unsigned long) prParamNetAddr + (unsigned long) ( + u4AddrLen + OFFSET_OF( + struct PARAM_NETWORK_ADDRESS, aucAddress))); + } + prParamNetAddrList->u4AddressCount += u4NumIPv4Addr; + + /* 4 <3.2> Fill up IPv6 address */ + u4AddrLen = IPV6_ADDR_LEN; + for (i = 0; i < u4NumIPv6Addr; i++) { + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + prParamNetAddr->u2AddressLength = u4AddrLen; + kalMemCopy(prParamNetAddr->aucAddress, + &pucIPv6Addr[i * u4AddrLen], u4AddrLen); + + prParamNetAddr = (struct PARAM_NETWORK_ADDRESS *) (( + unsigned long) prParamNetAddr + (unsigned long) ( + u4AddrLen + OFFSET_OF( + struct PARAM_NETWORK_ADDRESS, aucAddress))); + } + prParamNetAddrList->u4AddressCount += u4NumIPv6Addr; + + /* 4 <4> IOCTL to main_thread */ + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNetworkAddress, + (void *) prParamNetAddrList, u4Len, + FALSE, FALSE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "%s: Fail to set network address\n", + __func__); + + kalMemFree(prParamNetAddrList, VIR_MEM_TYPE, u4Len); + +} + +void kalSetNetAddressFromInterface(IN struct GLUE_INFO + *prGlueInfo, IN struct net_device *prDev, IN u_int8_t fgSet) +{ + uint32_t u4NumIPv4, u4NumIPv6; + uint8_t pucIPv4Addr[IPV4_ADDR_LEN * CFG_PF_ARP_NS_MAX_NUM], + pucIPv6Addr[IPV6_ADDR_LEN * CFG_PF_ARP_NS_MAX_NUM]; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = + (struct NETDEV_PRIVATE_GLUE_INFO *) NULL; + + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prDev); + + if (prNetDevPrivate->prGlueInfo != prGlueInfo) + DBGLOG(REQ, WARN, "%s: unexpected prGlueInfo(0x%p)!\n", + __func__, prNetDevPrivate->prGlueInfo); + + u4NumIPv4 = 0; + u4NumIPv6 = 0; + + if (fgSet) { + kalGetIPv4Address(prDev, CFG_PF_ARP_NS_MAX_NUM, pucIPv4Addr, + &u4NumIPv4); + kalGetIPv6Address(prDev, CFG_PF_ARP_NS_MAX_NUM, pucIPv6Addr, + &u4NumIPv6); + } + + if (u4NumIPv4 + u4NumIPv6 > CFG_PF_ARP_NS_MAX_NUM) { + if (u4NumIPv4 >= CFG_PF_ARP_NS_MAX_NUM) { + u4NumIPv4 = CFG_PF_ARP_NS_MAX_NUM; + u4NumIPv6 = 0; + } else { + u4NumIPv6 = CFG_PF_ARP_NS_MAX_NUM - u4NumIPv4; + } + } + + kalSetNetAddress(prGlueInfo, prNetDevPrivate->ucBssIdx, + pucIPv4Addr, u4NumIPv4, pucIPv6Addr, u4NumIPv6); +} + +#if CFG_MET_PACKET_TRACE_SUPPORT + +u_int8_t kalMetCheckProfilingPacket(IN struct GLUE_INFO + *prGlueInfo, IN void *prPacket) +{ + uint32_t u4PacketLen; + uint16_t u2EtherTypeLen; + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + uint8_t *aucLookAheadBuf = NULL; + uint8_t ucEthTypeLenOffset = ETHER_HEADER_LEN - + ETHER_TYPE_LEN; + uint8_t *pucNextProtocol = NULL; + + u4PacketLen = prSkb->len; + + if (u4PacketLen < ETHER_HEADER_LEN) { + DBGLOG(INIT, WARN, "Invalid Ether packet length: %u\n", + u4PacketLen); + return FALSE; + } + + aucLookAheadBuf = prSkb->data; + + /* 4 <0> Obtain Ether Type/Len */ + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[ucEthTypeLenOffset], + &u2EtherTypeLen); + + /* 4 <1> Skip 802.1Q header (VLAN Tagging) */ + if (u2EtherTypeLen == ETH_P_VLAN) { + ucEthTypeLenOffset += ETH_802_1Q_HEADER_LEN; + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[ucEthTypeLenOffset], + &u2EtherTypeLen); + } + /* 4 <2> Obtain next protocol pointer */ + pucNextProtocol = &aucLookAheadBuf[ucEthTypeLenOffset + + ETHER_TYPE_LEN]; + + /* 4 <3> Handle ethernet format */ + switch (u2EtherTypeLen) { + + /* IPv4 */ + case ETH_P_IPV4: { + uint8_t *pucIpHdr = pucNextProtocol; + uint8_t ucIpVersion; + + /* IPv4 header length check */ + if (u4PacketLen < (ucEthTypeLenOffset + ETHER_TYPE_LEN + + IPV4_HDR_LEN)) { + DBGLOG(INIT, WARN, "Invalid IPv4 packet length: %u\n", + u4PacketLen); + return FALSE; + } + + /* IPv4 version check */ + ucIpVersion = (pucIpHdr[0] & IP_VERSION_MASK) >> + IP_VERSION_OFFSET; + if (ucIpVersion != IP_VERSION_4) { + DBGLOG(INIT, WARN, "Invalid IPv4 packet version: %u\n", + ucIpVersion); + return FALSE; + } + + if (pucIpHdr[IPV4_HDR_IP_PROTOCOL_OFFSET] == IP_PRO_UDP) { + uint8_t *pucUdpHdr = &pucIpHdr[IPV4_HDR_LEN]; + uint16_t u2UdpDstPort; + uint16_t u2UdpSrcPort; + + /* Get UDP DST port */ + WLAN_GET_FIELD_BE16(&pucUdpHdr[UDP_HDR_DST_PORT_OFFSET], + &u2UdpDstPort); + + /* Get UDP SRC port */ + WLAN_GET_FIELD_BE16(&pucUdpHdr[UDP_HDR_SRC_PORT_OFFSET], + &u2UdpSrcPort); + + if (u2UdpSrcPort == prGlueInfo->u2MetUdpPort) { + uint16_t u2IpId; + + /* Store IP ID for Tag */ + WLAN_GET_FIELD_BE16( + &pucIpHdr[IPV4_HDR_IP_IDENTIFICATION_OFFSET], + &u2IpId); +#if 0 + DBGLOG(INIT, INFO, + "TX PKT PROTOCOL[0x%x] UDP DST port[%u] IP_ID[%u]\n", + pucIpHdr[IPV4_HDR_IP_PROTOCOL_OFFSET], + u2UdpDstPort, + u2IpId); +#endif + GLUE_SET_PKT_IP_ID(prPacket, u2IpId); + + return TRUE; + } + } + } + break; + + default: + break; + } + + return FALSE; +} + +static unsigned long __read_mostly tracing_mark_write_addr; + +static int __mt_find_tracing_mark_write_symbol_fn( + void *prData, const char *pcNameBuf, + struct module *prModule, unsigned long ulAddress) +{ + if (strcmp(pcNameBuf, "tracing_mark_write") == 0) { + tracing_mark_write_addr = ulAddress; + return 1; + } + return 0; +} + +static inline void __mt_update_tracing_mark_write_addr(void) +{ + if (unlikely(tracing_mark_write_addr == 0)) + kallsyms_on_each_symbol( + __mt_find_tracing_mark_write_symbol_fn, NULL); +} + +void kalMetTagPacket(IN struct GLUE_INFO *prGlueInfo, + IN void *prPacket, IN enum ENUM_TX_PROFILING_TAG eTag) +{ + if (!prGlueInfo->fgMetProfilingEn) + return; + + switch (eTag) { + case TX_PROF_TAG_OS_TO_DRV: + if (kalMetCheckProfilingPacket(prGlueInfo, prPacket)) { + /* trace_printk("S|%d|%s|%d\n", current->pid, + * "WIFI-CHIP", GLUE_GET_PKT_IP_ID(prPacket)); + */ + __mt_update_tracing_mark_write_addr(); +#if 0 /* #ifdef CONFIG_TRACING */ /* #if CFG_MET_PACKET_TRACE_SUPPORT */ + event_trace_printk(tracing_mark_write_addr, + "S|%d|%s|%d\n", + current->tgid, "WIFI-CHIP", + GLUE_GET_PKT_IP_ID(prPacket)); +#endif + GLUE_SET_PKT_FLAG_PROF_MET(prPacket); + } + break; + + case TX_PROF_TAG_DRV_TX_DONE: + if (GLUE_GET_PKT_IS_PROF_MET(prPacket)) { + /* trace_printk("F|%d|%s|%d\n", current->pid, + * "WIFI-CHIP", GLUE_GET_PKT_IP_ID(prPacket)); + */ + __mt_update_tracing_mark_write_addr(); +#if 0 /* #ifdef CONFIG_TRACING */ /* #if CFG_MET_PACKET_TRACE_SUPPORT */ + event_trace_printk(tracing_mark_write_addr, + "F|%d|%s|%d\n", + current->tgid, "WIFI-CHIP", + GLUE_GET_PKT_IP_ID(prPacket)); +#endif + } + break; + + case TX_PROF_TAG_MAC_TX_DONE: + break; + + default: + break; + } +} + +void kalMetInit(IN struct GLUE_INFO *prGlueInfo) +{ + prGlueInfo->fgMetProfilingEn = FALSE; + prGlueInfo->u2MetUdpPort = 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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. + */ +/*----------------------------------------------------------------------------*/ +#if 0 +static ssize_t kalMetWriteProcfs(struct file *file, + const char __user *buffer, size_t count, loff_t *off) +{ + char acBuf[128 + 1]; /* + 1 for "\0" */ + uint32_t u4CopySize; + int u16MetUdpPort; + int u8MetProfEnable; + + IN struct GLUE_INFO *prGlueInfo; + ssize_t result; + + u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : + (sizeof(acBuf) - 1); + result = copy_from_user(acBuf, buffer, u4CopySize); + acBuf[u4CopySize] = '\0'; + + if (sscanf(acBuf, " %d %d", &u8MetProfEnable, + &u16MetUdpPort) == 2) + DBGLOG(INIT, INFO, + "MET_PROF: Write MET PROC Enable=%d UDP_PORT=%d\n", + u8MetProfEnable, u16MetUdpPort); + if (pMetGlobalData != NULL) { + prGlueInfo = (struct GLUE_INFO *) pMetGlobalData; + prGlueInfo->fgMetProfilingEn = (u_int8_t) u8MetProfEnable; + prGlueInfo->u2MetUdpPort = (uint16_t) u16MetUdpPort; + } + return count; +} +#endif +static ssize_t kalMetCtrlWriteProcfs(struct file *file, + const char __user *buffer, size_t count, loff_t *off) +{ + char acBuf[128 + 1]; /* + 1 for "\0" */ + uint32_t u4CopySize; + int u8MetProfEnable; + ssize_t result; + + IN struct GLUE_INFO *prGlueInfo; + + u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : + (sizeof(acBuf) - 1); + result = copy_from_user(acBuf, buffer, u4CopySize); + acBuf[u4CopySize] = '\0'; + + if (sscanf(acBuf, " %d", &u8MetProfEnable) == 1) + DBGLOG(INIT, INFO, "MET_PROF: Write MET PROC Enable=%d\n", + u8MetProfEnable); + if (pMetGlobalData != NULL) { + prGlueInfo = (struct GLUE_INFO *) pMetGlobalData; + prGlueInfo->fgMetProfilingEn = (uint8_t) u8MetProfEnable; + } + return count; +} + +static ssize_t kalMetPortWriteProcfs(struct file *file, + const char __user *buffer, size_t count, loff_t *off) +{ + char acBuf[128 + 1]; /* + 1 for "\0" */ + uint32_t u4CopySize; + int u16MetUdpPort; + ssize_t result; + + IN struct GLUE_INFO *prGlueInfo; + + u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : + (sizeof(acBuf) - 1); + result = copy_from_user(acBuf, buffer, u4CopySize); + acBuf[u4CopySize] = '\0'; + + if (sscanf(acBuf, " %d", &u16MetUdpPort) == 1) + DBGLOG(INIT, INFO, "MET_PROF: Write MET PROC UDP_PORT=%d\n", + u16MetUdpPort); + if (pMetGlobalData != NULL) { + prGlueInfo = (struct GLUE_INFO *) pMetGlobalData; + prGlueInfo->u2MetUdpPort = (uint16_t) u16MetUdpPort; + } + return count; +} + +#if 0 +const struct file_operations rMetProcFops = { + .write = kalMetWriteProcfs +}; +#endif +const struct file_operations rMetProcCtrlFops = { + .write = kalMetCtrlWriteProcfs +}; + +const struct file_operations rMetProcPortFops = { + .write = kalMetPortWriteProcfs +}; + +int kalMetInitProcfs(IN struct GLUE_INFO *prGlueInfo) +{ + /* struct proc_dir_entry *pMetProcDir; */ + if (init_net.proc_net == (struct proc_dir_entry *)NULL) { + DBGLOG(INIT, INFO, "init proc fs fail: proc_net == NULL\n"); + return -ENOENT; + } + /* + * Directory: Root (/proc/net/wlan0) + */ + pMetProcDir = proc_mkdir("wlan0", init_net.proc_net); + if (pMetProcDir == NULL) + return -ENOENT; + /* + * /proc/net/wlan0 + * |-- met_ctrl (PROC_MET_PROF_CTRL) + */ + /* proc_create(PROC_MET_PROF_CTRL, 0x0644, pMetProcDir, &rMetProcFops); + */ + proc_create(PROC_MET_PROF_CTRL, 0000, pMetProcDir, + &rMetProcCtrlFops); + proc_create(PROC_MET_PROF_PORT, 0000, pMetProcDir, + &rMetProcPortFops); + + pMetGlobalData = (void *)prGlueInfo; + + return 0; +} + +int kalMetRemoveProcfs(void) +{ + + if (init_net.proc_net == (struct proc_dir_entry *)NULL) { + DBGLOG(INIT, WARN, + "remove proc fs fail: proc_net == NULL\n"); + return -ENOENT; + } + remove_proc_entry(PROC_MET_PROF_CTRL, pMetProcDir); + remove_proc_entry(PROC_MET_PROF_PORT, pMetProcDir); + /* remove root directory (proc/net/wlan0) */ + remove_proc_entry("wlan0", init_net.proc_net); + /* clear MetGlobalData */ + pMetGlobalData = NULL; + + return 0; +} + +#endif +#if CFG_SUPPORT_AGPS_ASSIST +u_int8_t kalIndicateAgpsNotify(struct ADAPTER *prAdapter, + uint8_t cmd, uint8_t *data, uint16_t dataLen) +{ +#ifdef CONFIG_NL80211_TESTMODE + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct sk_buff *skb = NULL; + + skb = cfg80211_testmode_alloc_event_skb(priv_to_wiphy( + prGlueInfo), + dataLen, GFP_KERNEL); + + /* DBGLOG(CCX, INFO, ("WLAN_STATUS_AGPS_NOTIFY, cmd=%d\n", cmd)); */ + if (unlikely(nla_put(skb, MTK_ATTR_AGPS_CMD, sizeof(cmd), + &cmd) < 0)) + goto nla_put_failure; + if (dataLen > 0 && data + && unlikely(nla_put(skb, MTK_ATTR_AGPS_DATA, dataLen, + data) < 0)) + goto nla_put_failure; + if (unlikely(nla_put(skb, MTK_ATTR_AGPS_IFINDEX, + sizeof(uint32_t), &prGlueInfo->prDevHandler->ifindex) < 0)) + goto nla_put_failure; + /* currently, the ifname maybe wlan0, p2p0, so the maximum name length + * will be 5 bytes + */ + if (unlikely(nla_put(skb, MTK_ATTR_AGPS_IFNAME, 5, + prGlueInfo->prDevHandler->name) < 0)) + goto nla_put_failure; + + cfg80211_testmode_event(skb, GFP_KERNEL); + return TRUE; +nla_put_failure: + kfree_skb(skb); +#else + DBGLOG(INIT, WARN, "CONFIG_NL80211_TESTMODE not enabled\n"); +#endif + return FALSE; +} +#endif + +uint64_t kalGetBootTime(void) +{ + struct timespec ts; + uint64_t bootTime = 0; + +#if KERNEL_VERSION(2, 6, 39) <= LINUX_VERSION_CODE + get_monotonic_boottime(&ts); +#else + ts = ktime_to_timespec(ktime_get()); +#endif + + bootTime = ts.tv_sec; + bootTime *= USEC_PER_SEC; + bootTime += ts.tv_nsec / NSEC_PER_USEC; + return bootTime; +} + +#if CFG_ASSERT_DUMP +uint32_t kalOpenCorDumpFile(u_int8_t fgIsN9) +{ + /* Move open-op to kalWriteCorDumpFile(). Empty files only */ + uint32_t ret; + uint8_t *apucFileName; + + if (fgIsN9) + apucFileName = apucCorDumpN9FileName; + else + apucFileName = apucCorDumpCr4FileName; + + ret = kalTrunkPath(apucFileName); + + return (ret >= 0)?WLAN_STATUS_SUCCESS:WLAN_STATUS_FAILURE; +} + +uint32_t kalWriteCorDumpFile(uint8_t *pucBuffer, + uint16_t u2Size, u_int8_t fgIsN9) +{ + uint32_t ret; + uint8_t *apucFileName; + + if (fgIsN9) + apucFileName = apucCorDumpN9FileName; + else + apucFileName = apucCorDumpCr4FileName; + + ret = kalWriteToFile(apucFileName, TRUE, pucBuffer, u2Size); + + return (ret >= 0)?WLAN_STATUS_SUCCESS:WLAN_STATUS_FAILURE; +} + +uint32_t kalCloseCorDumpFile(u_int8_t fgIsN9) +{ + /* Move close-op to kalWriteCorDumpFile(). Do nothing here */ + + return WLAN_STATUS_SUCCESS; +} +#endif + +#if CFG_WOW_SUPPORT +void kalWowInit(IN struct GLUE_INFO *prGlueInfo) +{ + kalMemZero(&prGlueInfo->prAdapter->rWowCtrl.stWowPort, + sizeof(struct WOW_PORT)); + prGlueInfo->prAdapter->rWowCtrl.ucReason = INVALID_WOW_WAKE_UP_REASON; + + prGlueInfo->prAdapter->mdns_offload_enable = FALSE; +} + +void kalWowCmdEventSetCb(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo,IN uint8_t *pucEventBuf) +{ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + + if (prCmdInfo->ucCID == CMD_ID_SET_PF_CAPABILITY) { + DBGLOG(INIT, STATE, "CMD_ID_SET_PF_CAPABILITY cmd done\n"); + prAdapter->fgSetPfCapabilityDone = TRUE; + } + + if (prCmdInfo->ucCID == CMD_ID_SET_WOWLAN) { + DBGLOG(INIT, STATE, "CMD_ID_SET_WOWLAN cmd done\n"); + prAdapter->fgSetWowDone = TRUE; + } + +} + +void kalWowProcess(IN struct GLUE_INFO *prGlueInfo, + uint8_t enable) +{ + struct CMD_WOWLAN_PARAM rCmdWowlanParam; + struct CMD_PACKET_FILTER_CAP rCmdPacket_Filter_Cap; + struct WOW_CTRL *pWOW_CTRL = + &prGlueInfo->prAdapter->rWowCtrl; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t ii, wait = 0; + bool bWake = TRUE; /* to wake up host or just keep connection */ + + kalMemZero(&rCmdWowlanParam, + sizeof(struct CMD_WOWLAN_PARAM)); + + kalMemZero(&rCmdPacket_Filter_Cap, + sizeof(struct CMD_PACKET_FILTER_CAP)); + + prGlueInfo->prAdapter->fgSetPfCapabilityDone = FALSE; + prGlueInfo->prAdapter->fgSetWowDone = FALSE; + + if (prGlueInfo->prAdapter->rWifiVar.ucAdvPws == 1 + && prGlueInfo->prAdapter->rWowCtrl.fgWowEnable == 0) + bWake = FALSE; + + /* add mdns offload */ + if (enable) + DBGLOG(PF, STATE, "Suspend: mDNS flag:%d\n", + prGlueInfo->prAdapter->mdns_offload_enable); + + if (enable && prGlueInfo->prAdapter->mdns_offload_enable) { + kalSendDelMdnsCacheToFw(prGlueInfo); + kalSendAddMdnsCacheToFw(prGlueInfo); + } + + DBGLOG(PF, INFO, + "PF, pAd ucBssIndex=%d, ucOwnMacIndex=%d\n", + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex, + prGlueInfo->prAdapter->prAisBssInfo->ucOwnMacIndex); + + DBGLOG(PF, INFO, "profile wow=%d, bWake=%d, GpioInterval=%d\n", + prGlueInfo->prAdapter->rWifiVar.ucWow, bWake, + prGlueInfo->prAdapter->rWowCtrl.astWakeHif[0].u4GpioInterval); + +/* Add this step in 0x4A wow command, then we can save 0x59 command */ +#if 0 + rCmdPacket_Filter_Cap.packet_cap_type |= + PACKETF_CAP_TYPE_MAGIC; + /* 20160627 Bennett: if receive BMC magic, PF search by bssid index, + * which is different with OM index + */ + /* After discussion, enable all bssid bits */ + /* rCmdPacket_Filter_Cap.ucBssid |= + * BIT(prGlueInfo->prAdapter->prAisBssInfo->ucOwnMacIndex); + */ + rCmdPacket_Filter_Cap.ucBssid |= BITS(0, 3); + + if (enable && bWake) + rCmdPacket_Filter_Cap.usEnableBits |= + PACKETF_CAP_TYPE_MAGIC; + else + rCmdPacket_Filter_Cap.usEnableBits &= + ~PACKETF_CAP_TYPE_MAGIC; + + rStatus = wlanSendSetQueryCmd(prGlueInfo->prAdapter, + CMD_ID_SET_PF_CAPABILITY, + TRUE, + FALSE, + FALSE, + kalWowCmdEventSetCb, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_PACKET_FILTER_CAP), + (uint8_t *)&rCmdPacket_Filter_Cap, + NULL, + 0); +#endif + + /* Set bssid bits in wowlan cmd to replace CMD_ID_SET_PF_CAPABILITY */ + /* After discussion, enable all bssid bits */ + rCmdWowlanParam.ucBssid |= BITS(0, 3); + + /* Let WOW enable/disable as last command, so we can back/restore DMA + * classify filter in FW + */ + rCmdWowlanParam.ucScenarioID = pWOW_CTRL->ucScenarioId; + rCmdWowlanParam.ucBlockCount = pWOW_CTRL->ucBlockCount; + rCmdWowlanParam.astWakeHif[0].ucWakeupHif = + pWOW_CTRL->astWakeHif[0].ucWakeupHif; + rCmdWowlanParam.astWakeHif[0].ucGpioPin = + pWOW_CTRL->astWakeHif[0].ucGpioPin; + rCmdWowlanParam.astWakeHif[0].ucTriggerLvl = + pWOW_CTRL->astWakeHif[0].ucTriggerLvl; + rCmdWowlanParam.astWakeHif[0].u4GpioInterval = + pWOW_CTRL->astWakeHif[0].u4GpioInterval; + + DBGLOG(PF, INFO, + "Test XX source: IPV4/UDP=%d, IPV4/TCP=%d, IPV6/UDP=%d, IPV6/TCP=%d\n", + pWOW_CTRL->stWowPort.ucIPv4UdpPortCnt, + pWOW_CTRL->stWowPort.ucIPv4TcpPortCnt, + pWOW_CTRL->stWowPort.ucIPv6UdpPortCnt, + pWOW_CTRL->stWowPort.ucIPv6TcpPortCnt); + + /* copy UDP/TCP port setting */ + if (bWake) + kalMemCopy(&rCmdWowlanParam.stWowPort, + &prGlueInfo->prAdapter->rWowCtrl.stWowPort, + sizeof(struct WOW_PORT)); + else + kalMemZero(&prGlueInfo->prAdapter->rWowCtrl.stWowPort, + sizeof(struct WOW_PORT)); + + DBGLOG(PF, INFO, + "Cmd: IPV4/UDP=%d, IPV4/TCP=%d, IPV6/UDP=%d, IPV6/TCP=%d\n", + rCmdWowlanParam.stWowPort.ucIPv4UdpPortCnt, + rCmdWowlanParam.stWowPort.ucIPv4TcpPortCnt, + rCmdWowlanParam.stWowPort.ucIPv6UdpPortCnt, + rCmdWowlanParam.stWowPort.ucIPv6TcpPortCnt); + + for (ii = 0; + ii < rCmdWowlanParam.stWowPort.ucIPv4UdpPortCnt; ii++) + DBGLOG(PF, INFO, "IPV4/UDP port[%d]=%d\n", ii, + rCmdWowlanParam.stWowPort.ausIPv4UdpPort[ii]); + + for (ii = 0; + ii < rCmdWowlanParam.stWowPort.ucIPv4TcpPortCnt; ii++) + DBGLOG(PF, INFO, "IPV4/TCP port[%d]=%d\n", ii, + rCmdWowlanParam.stWowPort.ausIPv4TcpPort[ii]); + + for (ii = 0; + ii < rCmdWowlanParam.stWowPort.ucIPv6UdpPortCnt; ii++) + DBGLOG(PF, INFO, "IPV6/UDP port[%d]=%d\n", ii, + rCmdWowlanParam.stWowPort.ausIPv6UdpPort[ii]); + + for (ii = 0; + ii < rCmdWowlanParam.stWowPort.ucIPv6TcpPortCnt; ii++) + DBGLOG(PF, INFO, "IPV6/TCP port[%d]=%d\n", ii, + rCmdWowlanParam.stWowPort.ausIPv6TcpPort[ii]); + + + /* GPIO parameter is necessary in suspend/resume */ + if (enable == 1) { + rCmdWowlanParam.ucCmd = PM_WOWLAN_REQ_START; + rCmdWowlanParam.ucDetectType = WOWLAN_DETECT_TYPE_MAGIC; + rCmdWowlanParam.u2FilterFlag = WOWLAN_FF_DROP_ALL | + WOWLAN_FF_SEND_MAGIC_TO_HOST | + WOWLAN_FF_ALLOW_1X | + WOWLAN_FF_ALLOW_ARP_REQ2ME; + if (!bWake) + rCmdWowlanParam.ucDetectType = WOWLAN_DETECT_TYPE_NONE; + + } else { + rCmdWowlanParam.ucCmd = PM_WOWLAN_REQ_STOP; + } + + rStatus = wlanSendSetQueryCmd(prGlueInfo->prAdapter, + CMD_ID_SET_WOWLAN, + TRUE, + FALSE, + FALSE, + kalWowCmdEventSetCb, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_WOWLAN_PARAM), + (uint8_t *)&rCmdWowlanParam, + NULL, + 0); + + + while (1) { + kalUdelay(200); + schedule(); + + if (wait > 2500) { + DBGLOG(INIT, ERROR, "WoW process timeout.PF:%d. WoW:%d\n", + prGlueInfo->prAdapter->fgSetPfCapabilityDone, + prGlueInfo->prAdapter->fgSetWowDone); + break; + } + if (prGlueInfo->prAdapter->fgSetWowDone == TRUE) { + DBGLOG(INIT, STATE, "WoW process done\n"); + break; + } + + wait++; + } + + /* ARP offload. move to last command */ + wlanSetSuspendMode(prGlueInfo, enable); + + wlanSendDummyCmd(prGlueInfo->prAdapter, TRUE); + +} + +struct MDNS_Template_Record gRspCacheRecord[MAX_MDNS_CACHE_NUM]; + +uint8_t gOldestIndex; + +uint16_t kalMdsnParseName(uint8_t *pucMdnsHdr, uint16_t offset, + uint8_t *name, uint16_t *name_len) +{ + uint16_t pos = 0; + uint16_t i = 0; + bool compress = FALSE; + uint8_t len = 0; + uint8_t limit = MDNS_NAME_MAX_LEN - 1; + + /* parse compress name */ + /* there may be compress name contain compress name */ + pos = offset; + while (pucMdnsHdr[offset] != 0) { + len = pucMdnsHdr[offset]; + switch (len & 0xc0) { + case 0x00: + /* uncompress code */ + if ((*name_len + len) > limit) { + *name_len = 0; + return 0; + } + + for (i = 0; i <= len; i++) { + name[*name_len] = pucMdnsHdr[offset + i]; + *name_len += 1; + } + offset += len + 1; + if (compress == FALSE) + pos = offset; + break; + + case 0x40: + case 0x80: + *name_len = 0; + return 0; + + case 0xc0: + if (compress == FALSE) { + pos = offset; + compress = TRUE; + } + DBGLOG(PF, LOUD, "0x%02x 0x%02x.\n", + pucMdnsHdr[offset], pucMdnsHdr[offset + 1]); + offset = ((pucMdnsHdr[offset] & 0x3f) << 8) + | pucMdnsHdr[offset + 1]; + break; + } + } + + /* for compress, c0xx 2byes, for uncompress 0 as the end of the name */ + if (compress == TRUE) + pos += 2; + else + pos += 1; + + *name_len += 1; + + return pos; +} + +bool kalParseMdnsRespPkt(uint8_t *pucMdnsHdr, + struct MDNS_RESP_INFO_T *resp) +{ + uint16_t pos; + uint8_t *ip; + + pos = 0; + resp->usMdnsId = NTOHS(*(uint16_t *)(pucMdnsHdr + pos)); + + pos += 2; + resp->usMdnsFlags = NTOHS(*(uint16_t *)(pucMdnsHdr + pos)); + + pos += 2; + resp->usQuestionCnt = NTOHS(*(uint16_t *)(pucMdnsHdr + pos)); + + pos += 2; + resp->usAnswerCnt = NTOHS(*(uint16_t *)(pucMdnsHdr + pos)); + + pos += 2; + resp->usAuthCnt = NTOHS(*(uint16_t *)(pucMdnsHdr + pos)); + + pos += 2; + resp->usAddtionCnt = NTOHS(*(uint16_t *)(pucMdnsHdr + pos)); + + DBGLOG(SW4, LOUD, "MDNS PKT[ID %d] flags[0x%x]\n", + resp->usMdnsId, resp->usMdnsFlags); + DBGLOG(SW4, LOUD, "questionCnt[%d] answerCnt[%d]\n", + resp->usQuestionCnt, resp->usAnswerCnt); + DBGLOG(SW4, LOUD, "authcnt[%d] addCnt[%d]\n", + resp->usAuthCnt, resp->usAddtionCnt); + + if ((resp->usMdnsFlags & 0x8000) == 0) { + DBGLOG(SW4, LOUD, "MDNS is query packet\n"); + return FALSE; + } + + if ((resp->usAnswerCnt == 1 && resp->usAddtionCnt == 3) + || (resp->usAnswerCnt == 4 && resp->usAddtionCnt == 0)) { + DBGLOG(SW4, LOUD, "MDNS ans %d add %d\n", + resp->usAnswerCnt, resp->usAddtionCnt); + } else { + DBGLOG(SW4, LOUD, "MDNS ans %d add %d\n", + resp->usAnswerCnt, resp->usAddtionCnt); + return FALSE; + } + + /* parse ptr info */ + pos += 2; + pos = kalMdsnParseName(pucMdnsHdr, pos, + resp->ptrInfo.queryName, + &resp->ptrInfo.queryNameLen); + + DBGLOG(SW4, LOUD, "qurey name: %s\n", + resp->ptrInfo.queryName); + DBGLOG(SW4, LOUD, "qurey name len: %d pos %d\n", + resp->ptrInfo.queryNameLen, pos); + + resp->ptrInfo.type = NTOHS(*(uint16_t *)(pucMdnsHdr + pos)); + if (resp->ptrInfo.type != 12) { + DBGLOG(SW4, LOUD, "not ptr type %d\n", + resp->ptrInfo.type); + return FALSE; + } + + pos += 2; + resp->ptrInfo.cl = NTOHS(*(uint16_t *)(pucMdnsHdr + pos)); + + pos += 2; + resp->ptrInfo.ttl = NTOHL(*(uint32_t *)(pucMdnsHdr + pos)); + + pos += 4; + resp->ptrInfo.dataLen = NTOHS(*(uint16_t *)(pucMdnsHdr + pos)); + + DBGLOG(SW4, LOUD, "ptr type %d class %d ttl %d datalen %d\n", + resp->ptrInfo.type, resp->ptrInfo.cl, + resp->ptrInfo.ttl, resp->ptrInfo.dataLen); + + pos += 2; + pos = kalMdsnParseName(pucMdnsHdr, pos, + resp->ptrInfo.domName, + &resp->ptrInfo.domNameLen); + + DBGLOG(SW4, LOUD, "ptr domain name: %s\n", resp->ptrInfo.domName); + + /* parse compress name, need update the datalen */ + resp->ptrInfo.dataLen = resp->ptrInfo.domNameLen; + + /* parse txt info */ + pos = kalMdsnParseName(pucMdnsHdr, pos, resp->txtInfo.domName, + &resp->txtInfo.domNameLen); + + DBGLOG(SW4, LOUD, "txt domain name: %s\n", resp->txtInfo.domName); + + resp->txtInfo.type = NTOHS(*(uint16_t *)(pucMdnsHdr + pos)); + if (resp->txtInfo.type != 16) { + DBGLOG(SW4, LOUD, "not txt type %d\n", resp->txtInfo.type); + return FALSE; + } + + pos += 2; + resp->txtInfo.cl = NTOHS(*(uint16_t *)(pucMdnsHdr + pos)); + + pos += 2; + resp->txtInfo.ttl = NTOHL(*(uint32_t *)(pucMdnsHdr + pos)); + + pos += 4; + resp->txtInfo.dataLen = NTOHS(*(uint16_t *)(pucMdnsHdr + pos)); + + DBGLOG(SW4, LOUD, "txt type %d class %d ttl %d datalen %d\n", + resp->txtInfo.type, resp->txtInfo.cl, + resp->txtInfo.ttl, resp->txtInfo.dataLen); + + pos += 2; + kalMemCopy(resp->txtInfo.text, + pucMdnsHdr + pos, + resp->txtInfo.dataLen); + + DBGLOG(SW4, LOUD, "txt text: %s\n", resp->txtInfo.text); + + /* parse srv info */ + pos += resp->txtInfo.dataLen; + pos = kalMdsnParseName(pucMdnsHdr, pos, resp->srvInfo.domName, + &resp->srvInfo.domNameLen); + + DBGLOG(SW4, LOUD, "srv domain name: %s\n", resp->srvInfo.domName); + + resp->srvInfo.type = NTOHS(*(uint16_t *)(pucMdnsHdr + pos)); + if (resp->srvInfo.type != 33) { + DBGLOG(SW4, LOUD, "not srv type %d\n", resp->srvInfo.type); + return FALSE; + } + + pos += 2; + resp->srvInfo.cl = NTOHS(*(uint16_t *)(pucMdnsHdr + pos)); + + pos += 2; + resp->srvInfo.ttl = NTOHL(*(uint32_t *)(pucMdnsHdr + pos)); + + pos += 4; + resp->srvInfo.dataLen = NTOHS(*(uint16_t *)(pucMdnsHdr + pos)); + + pos += 2; + resp->srvInfo.priority = NTOHS(*(uint16_t *)(pucMdnsHdr + pos)); + + pos += 2; + resp->srvInfo.weight = NTOHS(*(uint16_t *)(pucMdnsHdr + pos)); + + pos += 2; + resp->srvInfo.port = NTOHS(*(uint16_t *)(pucMdnsHdr + pos)); + + DBGLOG(SW4, LOUD, "srv type %d class %d ttl %d datalen %d.\n", + resp->srvInfo.type, resp->srvInfo.cl, + resp->srvInfo.ttl, resp->srvInfo.dataLen); + + DBGLOG(SW4, LOUD, "srv pri %d weight %d port %d.\n", + resp->srvInfo.priority, resp->srvInfo.weight, + resp->srvInfo.port); + + pos += 2; + pos = kalMdsnParseName(pucMdnsHdr, pos, resp->srvInfo.target, + &resp->srvInfo.targetLen); + + DBGLOG(SW4, LOUD, "srv target name: %s\n", resp->srvInfo.target); + + /* parse compress name, need update the datalen */ + resp->srvInfo.dataLen = 6 + resp->srvInfo.targetLen; + + /* parse a info */ + pos = kalMdsnParseName(pucMdnsHdr, pos, resp->aInfo.domName, + &resp->aInfo.domNameLen); + + DBGLOG(SW4, LOUD, "a domain name: %s.\n", resp->aInfo.domName); + + resp->aInfo.type = NTOHS(*(uint16_t *)(pucMdnsHdr + pos)); + if (resp->aInfo.type != 1) { + DBGLOG(SW4, LOUD, "not a type %d.\n", resp->aInfo.type); + return FALSE; + } + + pos += 2; + resp->aInfo.cl = NTOHS(*(uint16_t *)(pucMdnsHdr + pos)); + + pos += 2; + resp->aInfo.ttl = NTOHL(*(uint32_t *)(pucMdnsHdr + pos)); + + pos += 4; + resp->aInfo.dataLen = NTOHS(*(uint16_t *)(pucMdnsHdr + pos)); + + pos += 2; + resp->aInfo.ipAddr = NTOHL(*(uint32_t *)(pucMdnsHdr + pos)); + + DBGLOG(SW4, LOUD, "a type %d class %d ttl %d datalen %d.\n", + resp->aInfo.type, resp->aInfo.cl, + resp->aInfo.ttl, resp->aInfo.dataLen); + + ip = (uint8_t *)&(resp->aInfo.ipAddr); + DBGLOG(SW4, LOUD, "a host ip [%d.%d.%d.%d].\n", + ip[0], ip[1], ip[2], ip[3]); + + return TRUE; +} + +void kalPickMdnsParamFromResp(struct MDNS_RESP_INFO_T *respInfo, + struct MDNS_Template_Record *respTemplate) +{ + uint16_t offset; + struct MDNS_ANSWER_RR *prMdnsAnswerR = NULL; + struct MDNS_TXT_RR *prMdnsTxtR = NULL; + struct MDNS_SRV_RR *prMdnsSrvR = NULL; + struct MDNS_QUESTION *prMdnsQuestion = NULL; + struct MDNS_A_RR *prMdnsAR = NULL; + + prMdnsQuestion = &respTemplate->mdnsQuestionTemplate; + + /* store query info */ + kalMemCopy(prMdnsQuestion->name, + respInfo->ptrInfo.queryName, + MDNS_NAME_MAX_LEN); + prMdnsQuestion->name_length = respInfo->ptrInfo.queryNameLen; + prMdnsQuestion->type = respInfo->ptrInfo.type; + prMdnsQuestion->class = respInfo->ptrInfo.cl; + + /* store answer RR */ + prMdnsAnswerR = &respTemplate->mdnsResponseRecord; + offset = 0; + kalMemCopy(&prMdnsAnswerR->data[offset], + respInfo->ptrInfo.queryName, + respInfo->ptrInfo.queryNameLen); + + offset += respInfo->ptrInfo.queryNameLen; + *(uint16_t *)(&prMdnsAnswerR->data[offset]) + = HTONS(respInfo->ptrInfo.type); + + offset += sizeof(uint16_t); + *(uint16_t *)(&prMdnsAnswerR->data[offset]) + = HTONS(respInfo->ptrInfo.cl); + + offset += sizeof(uint16_t); + *(uint32_t *)(&prMdnsAnswerR->data[offset]) + = HTONL(respInfo->ptrInfo.ttl); + + offset += sizeof(uint32_t); + *(uint16_t *)(&prMdnsAnswerR->data[offset]) + = HTONS(respInfo->ptrInfo.dataLen); + + offset += sizeof(uint16_t); + kalMemCopy(&prMdnsAnswerR->data[offset], + respInfo->ptrInfo.domName, + respInfo->ptrInfo.domNameLen); + offset += respInfo->ptrInfo.domNameLen; + prMdnsAnswerR->data_length = offset; + + /* store server name (domain name) */ + kalMemCopy(respTemplate->ucServiceName, + respInfo->ptrInfo.domName, + respInfo->ptrInfo.domNameLen); + respTemplate->ServiceNameLen = respInfo->ptrInfo.domNameLen; + + /* store SRV info */ + offset = 0; + prMdnsSrvR = &respTemplate->mdnsSrvRecord; + *(uint16_t *)(&prMdnsSrvR->data[offset]) + = HTONS(respInfo->srvInfo.type); + + offset += sizeof(uint16_t); + *(uint16_t *)(&prMdnsSrvR->data[offset]) = HTONS(respInfo->srvInfo.cl); + + offset += sizeof(uint16_t); + *(uint32_t *)(&prMdnsSrvR->data[offset]) = HTONL(respInfo->srvInfo.ttl); + + offset += sizeof(uint32_t); + /* use target */ + *(uint16_t *)(&prMdnsSrvR->data[offset]) + = HTONS(respInfo->srvInfo.targetLen + 6); + + offset += sizeof(uint16_t); + *(uint16_t *)(&prMdnsSrvR->data[offset]) + = HTONS(respInfo->srvInfo.priority); + + offset += sizeof(uint16_t); + *(uint16_t *)(&prMdnsSrvR->data[offset]) + = HTONS(respInfo->srvInfo.weight); + + offset += sizeof(uint16_t); + *(uint16_t *)(&prMdnsSrvR->data[offset]) + = HTONS(respInfo->srvInfo.port); + + offset += sizeof(uint16_t); + prMdnsSrvR->data_length = offset; + + /* store TXT info */ + offset = 0; + prMdnsTxtR = &respTemplate->mdnsTxtRecord; + *(uint16_t *)(&prMdnsTxtR->data[offset]) + = HTONS(respInfo->txtInfo.type); + + offset += sizeof(uint16_t); + *(uint16_t *)(&prMdnsTxtR->data[offset]) = HTONS(respInfo->txtInfo.cl); + + offset += sizeof(uint16_t); + *(uint32_t *)(&prMdnsTxtR->data[offset]) = HTONL(respInfo->txtInfo.ttl); + + offset += sizeof(uint32_t); + *(uint16_t *)(&prMdnsTxtR->data[offset]) + = HTONS(respInfo->txtInfo.dataLen); + + offset += sizeof(uint16_t); + kalMemCopy(&prMdnsTxtR->data[offset], + respInfo->txtInfo.text, + respInfo->txtInfo.dataLen); + offset += respInfo->txtInfo.dataLen; + prMdnsTxtR->data_length = offset; + + /* store target name */ + kalMemCopy(respTemplate->ucTargetName, + respInfo->srvInfo.target, + respInfo->srvInfo.targetLen); + respTemplate->TargetNameLen = respInfo->srvInfo.targetLen; + + /* store A info */ + offset = 0; + prMdnsAR = &respTemplate->mdnsARecord; + + *(uint16_t *)(&prMdnsAR->data[offset]) + = HTONS(respInfo->aInfo.type); + + offset += sizeof(uint16_t); + *(uint16_t *)(&prMdnsAR->data[offset]) = HTONS(respInfo->aInfo.cl); + + offset += sizeof(uint16_t); + *(uint32_t *)(&prMdnsAR->data[offset]) = HTONL(respInfo->aInfo.ttl); + + offset += sizeof(uint32_t); + *(uint16_t *)(&prMdnsAR->data[offset]) + = HTONS(respInfo->aInfo.dataLen); + + offset += sizeof(uint16_t); + *(uint32_t *)(&prMdnsAR->data[offset]) = HTONL(respInfo->aInfo.ipAddr); + offset += respInfo->aInfo.dataLen; + prMdnsAR->data_length = offset; +} + +void kalSendMdnsEventCb(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + + if (prCmdInfo->ucCID == CMD_ID_SET_MDNS_RECORD) { + DBGLOG(INIT, LOUD, "CMD_ID_SET_MDNS_RECORD cmd submitted\n"); + prAdapter->fgSetMdnsDone = TRUE; + } +} + +void kalSendDelMdnsCacheToFw(struct GLUE_INFO *prGlueInfo) +{ + struct CMD_MDNS_PARAM_T *cmdMdnsParam; + uint8_t i; + uint32_t wait; + + cmdMdnsParam = (struct CMD_MDNS_PARAM_T *)kalMemAlloc( + sizeof(struct CMD_MDNS_PARAM_T), VIR_MEM_TYPE); + if (!cmdMdnsParam) + return; + + for (i = 0; i < MAX_MDNS_CACHE_NUM; i++) { + kalMemZero(cmdMdnsParam, sizeof(struct CMD_MDNS_PARAM_T)); + + cmdMdnsParam->ucCmd = MDNS_CMD_DEL_RECORD; + cmdMdnsParam->u4RecordId = i; + + prGlueInfo->prAdapter->fgSetMdnsDone = FALSE; + + wlanSendSetQueryCmd(prGlueInfo->prAdapter, + CMD_ID_SET_MDNS_RECORD, + TRUE, + FALSE, + FALSE, + kalSendMdnsEventCb, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_MDNS_PARAM_T), + (uint8_t *)cmdMdnsParam, + NULL, + 0); + + wait = 0; + while (1) { + kalMsleep(2); + + if (wait > 100) { + DBGLOG(INIT, ERROR, "WoW process timeout\n\n"); + break; + } + if (prGlueInfo->prAdapter->fgSetMdnsDone == TRUE) { + DBGLOG(INIT, LOUD, + "send mdns record [%d] done\n", i); + break; + } + wait++; + } + } + + kalMemFree(cmdMdnsParam, VIR_MEM_TYPE, + sizeof(struct CMD_MDNS_PARAM_T)); +} + +void kalSendAddMdnsCacheToFw(struct GLUE_INFO *prGlueInfo) +{ + struct CMD_MDNS_PARAM_T *cmdMdnsParam; + uint8_t i; + uint32_t wait; + + cmdMdnsParam = (struct CMD_MDNS_PARAM_T *)kalMemAlloc( + sizeof(struct CMD_MDNS_PARAM_T), VIR_MEM_TYPE); + if (!cmdMdnsParam) + return; + + for (i = 0; i < MAX_MDNS_CACHE_NUM; i++) { + if (gRspCacheRecord[i].bIsUsed == 0) { + DBGLOG(SW4, LOUD, "null cache, don't send to fw.\n"); + continue; + } + + kalMemZero(cmdMdnsParam, sizeof(struct CMD_MDNS_PARAM_T)); + + prGlueInfo->prAdapter->fgSetMdnsDone = FALSE; + + cmdMdnsParam->ucCmd = MDNS_CMD_ADD_RECORD; + cmdMdnsParam->u4RecordId = gRspCacheRecord[i].u4RecordId; + kalMemCopy(&cmdMdnsParam->mdnsQueryRespTemplate, + &gRspCacheRecord[i], + sizeof(struct MDNS_Template_Record)); + DBGLOG(SW4, STATE, "mDNS cache: %d, recordid %d %s.\n", + i, gRspCacheRecord[i].u4RecordId, + gRspCacheRecord[i].mdnsQuestionTemplate.name); + + wlanSendSetQueryCmd(prGlueInfo->prAdapter, + CMD_ID_SET_MDNS_RECORD, + TRUE, + FALSE, + FALSE, + kalSendMdnsEventCb, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_MDNS_PARAM_T), + (uint8_t *)cmdMdnsParam, + NULL, + 0); + + wait = 0; + while (1) { + kalMsleep(2); + + if (wait > 100) { + DBGLOG(INIT, ERROR, + "WoW process timeout\n\n"); + break; + } + if (prGlueInfo->prAdapter->fgSetMdnsDone == TRUE) { + DBGLOG(INIT, LOUD, + "send mdns record [%d] done\n", i); + break; + } + wait++; + } + } + + kalMemFree(cmdMdnsParam, VIR_MEM_TYPE, + sizeof(struct CMD_MDNS_PARAM_T)); +} + +void kalShowMdnsCache(void) +{ + uint8_t i; + + for (i = 0; i < MAX_MDNS_CACHE_NUM; i++) { + DBGLOG(SW4, STATE, "mDNS cache: %d, %d [%s] [%s].\n", + i, gRspCacheRecord[i].u4RecordId, + gRspCacheRecord[i].mdnsQuestionTemplate.name, + gRspCacheRecord[i].ucServiceName); + } +} + +void kalSendMdnsEnableToFw(struct GLUE_INFO *prGlueInfo) +{ + struct CMD_MDNS_PARAM_T *cmdMdnsParam; + uint8_t *pucMdnsARecord; + struct WLAN_MAC_HEADER_QoS_T *prMacHeader; + uint8_t *pucIPHeader; + uint8_t *pucUDPHeader; + + cmdMdnsParam = (struct CMD_MDNS_PARAM_T *)kalMemAlloc( + sizeof(struct CMD_MDNS_PARAM_T), VIR_MEM_TYPE); + if (!cmdMdnsParam) + return; + + kalMemZero(cmdMdnsParam, sizeof(struct CMD_MDNS_PARAM_T)); + + cmdMdnsParam->ucCmd = MDNS_CMD_ENABLE; + + DBGLOG(SW4, ERROR, "mDNS Enable.\n"); + /* Store 802.11 MAC header.*/ + + prMacHeader = &cmdMdnsParam->aucMdnsMacHdr; + prMacHeader->u2FrameCtrl = MAC_FRAME_QOS_DATA; + prMacHeader->u2FrameCtrl |= MASK_FC_TO_DS; + prMacHeader->u2FrameCtrl |= MASK_FC_PWR_MGT; + + /* SA, DA.*/ + COPY_MAC_ADDR(prMacHeader->aucAddr2, + prGlueInfo->prDevHandler->dev_addr); + prMacHeader->aucAddr3[0] = 1; + prMacHeader->aucAddr3[1] = 0; + prMacHeader->aucAddr3[2] = 0x5E; + prMacHeader->aucAddr3[3] = 0; + prMacHeader->aucAddr3[4] = 0; + prMacHeader->aucAddr3[5] = 0xFB; + + prMacHeader->u2SeqCtrl = 0; + + prMacHeader->u2QosCtrl = 0; + prMacHeader->u2QosCtrl |= + (ACK_POLICY_NORMAL_ACK_IMPLICIT_BA_REQ + << MASK_QC_ACK_POLICY_OFFSET); + + /* IPv4 header.*/ + pucIPHeader = &cmdMdnsParam->aucMdnsIPHdr[0]; + /* Version: 4, Length:(5*4) */ + pucIPHeader[0] = 4<<4 | 5; + /* Diff.Services */ + pucIPHeader[1] = 0; + /* IP length: + *(IPV4_HEADER_LENGTH + UDP_HEADER_LENGTH + u4MdnsLen) + */ + pucIPHeader[2] = 0; + pucIPHeader[3] = 0; + /* Identifier.*/ + pucIPHeader[4] = 0; + pucIPHeader[5] = 0; + /* Fragmentation Flags, Mask 0xE0.*/ + pucIPHeader[6] = 0; + pucIPHeader[6] = 1 << 6; + /* Fragment Offset, [6,7]Mask 0x1FFF.*/ + pucIPHeader[7] = 0; + /* TTL.*/ + pucIPHeader[8] = 255; + /* Protocol, UDP.*/ + pucIPHeader[9] = 17; + /* Header Checksum.*/ + pucIPHeader[10] = 0; + pucIPHeader[11] = 0; + /* Source IP: FW could check and update SIP again.*/ + pucIPHeader[12] = 0; + pucIPHeader[13] = 0; + pucIPHeader[14] = 0; + pucIPHeader[15] = 0; + /* DIP:MC IP(224.0.0.251) */ + pucIPHeader[16] = 224; + pucIPHeader[17] = 0; + pucIPHeader[18] = 0; + pucIPHeader[19] = 251; + + /*UDP header*/ + pucUDPHeader = &cmdMdnsParam->aucMdnsUdpHdr[0]; + /* Source port: 5353 */ + pucUDPHeader[0] = (5353 & 0xff00) >> 8; + pucUDPHeader[1] = 5353 & 0x00ff; + /* Destination port: 5353 */ + pucUDPHeader[2] = (5353 & 0xff00) >> 8; + pucUDPHeader[3] = 5353 & 0x00ff; + /* UDP length: Calculate by FW*/ + pucUDPHeader[4] = 0; + pucUDPHeader[5] = 0; + /* UDP CheckSum: Calculate by FW*/ + pucUDPHeader[6] = 0; + pucUDPHeader[7] = 0; + + /* Store A RR.*/ + pucMdnsARecord = &cmdMdnsParam->mdnsARecord[0]; + /* Type.*/ + pucMdnsARecord[0] = 0; + pucMdnsARecord[1] = 1; + /* Class.*/ + pucMdnsARecord[2] = (32769 & 0xff00) >> 8; + pucMdnsARecord[3] = 32769 & 0x00ff; + /* TTL.*/ + pucMdnsARecord[4] = 0; + pucMdnsARecord[5] = 0; + pucMdnsARecord[6] = (4500 & 0xff00) >> 8; + pucMdnsARecord[7] = 4500 & 0x00ff; + /* Data Length.*/ + pucMdnsARecord[8] = 0; + pucMdnsARecord[9] = 4; + /* SIP Address.*/ + pucMdnsARecord[10] = 0; + pucMdnsARecord[11] = 0; + pucMdnsARecord[12] = 0; + pucMdnsARecord[13] = 0; + + wlanSendSetQueryCmd(prGlueInfo->prAdapter, + CMD_ID_SET_MDNS_RECORD, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_MDNS_PARAM_T), + (uint8_t *)cmdMdnsParam, + NULL, + 0); + + kalMemFree(cmdMdnsParam, VIR_MEM_TYPE, + sizeof(struct CMD_MDNS_PARAM_T)); +} + +void kalSendMdnsDisableToFw(struct GLUE_INFO *prGlueInfo) +{ + struct CMD_MDNS_PARAM_T *cmdMdnsParam; + + cmdMdnsParam = (struct CMD_MDNS_PARAM_T *)kalMemAlloc( + sizeof(struct CMD_MDNS_PARAM_T), VIR_MEM_TYPE); + + if (!cmdMdnsParam) + return; + + kalMemZero(cmdMdnsParam, sizeof(struct CMD_MDNS_PARAM_T)); + + cmdMdnsParam->ucCmd = MDNS_CMD_DISABLE; + + DBGLOG(SW4, ERROR, "mDNS Disable.\n"); + + wlanSendSetQueryCmd(prGlueInfo->prAdapter, + CMD_ID_SET_MDNS_RECORD, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_MDNS_PARAM_T), + (uint8_t *)cmdMdnsParam, + NULL, + 0); + + kalMemFree(cmdMdnsParam, VIR_MEM_TYPE, + sizeof(struct CMD_MDNS_PARAM_T)); +} + +uint8_t kalAddMdnsCache(struct MDNS_RESP_INFO_T *respInfo) +{ + uint8_t i; + bool flag = FALSE; + struct MDNS_Template_Record *respTemplate; + + respTemplate = (struct MDNS_Template_Record *)kalMemAlloc( + sizeof(struct MDNS_Template_Record), PHY_MEM_TYPE); + + if (respTemplate == NULL) { + DBGLOG(SW4, ERROR, "kmalloc failed.\n"); + return 1; + } + + kalMemZero(respTemplate, sizeof(struct MDNS_Template_Record)); + kalPickMdnsParamFromResp(respInfo, respTemplate); + + for (i = 0; i < MAX_MDNS_CACHE_NUM; i++) { + /* if query name is same, newer one replace the older */ + if (kalMemCmp(&respTemplate->mdnsQuestionTemplate, + &gRspCacheRecord[i].mdnsQuestionTemplate, + sizeof(struct MDNS_QUESTION)) == 0 && + kalMemCmp(&respTemplate->mdnsResponseRecord, + &gRspCacheRecord[i].mdnsResponseRecord, + sizeof(struct MDNS_ANSWER_RR)) == 0 && + kalMemCmp(&respTemplate->mdnsTxtRecord, + &gRspCacheRecord[i].mdnsTxtRecord, + sizeof(struct MDNS_TXT_RR)) == 0 && + kalMemCmp(&respTemplate->mdnsSrvRecord, + &gRspCacheRecord[i].mdnsSrvRecord, + sizeof(struct MDNS_SRV_RR)) == 0) { + respTemplate->bIsUsed = TRUE; + respTemplate->u4RecordId = i; + kalMemCopy(&gRspCacheRecord[i], + respTemplate, + sizeof(struct MDNS_Template_Record)); + flag = TRUE; + break; + } + } + + if (flag == TRUE) { + DBGLOG(SW4, LOUD, "already in the table, record %d.\n", i); + goto exit; + } + + for (i = 0; i < MAX_MDNS_CACHE_NUM; i++) { + /* find a unused one */ + if (gRspCacheRecord[i].bIsUsed == FALSE) { + respTemplate->u4RecordId = i; + respTemplate->bIsUsed = TRUE; + kalMemCopy(&gRspCacheRecord[i], + respTemplate, + sizeof(struct MDNS_Template_Record)); + flag = TRUE; + break; + } + } + + if (flag == TRUE) { + DBGLOG(SW4, LOUD, "find a unused record %d.\n", i); + goto exit; + } + + DBGLOG(SW4, LOUD, "cache full, replace the oldest index %d.\n", + gOldestIndex); + + respTemplate->u4RecordId = gOldestIndex; + kalMemCopy(&gRspCacheRecord[gOldestIndex], + respTemplate, + sizeof(struct MDNS_Template_Record)); + gOldestIndex = (gOldestIndex + 1) % MAX_MDNS_CACHE_NUM; + +exit: + kalMemFree(respTemplate, PHY_MEM_TYPE, + sizeof(struct MDNS_Template_Record)); + + return 0; +} + +void kalDelMdnsCache(struct MDNS_RESP_INFO_T *respInfo) +{ + uint8_t i, j; + + for (i = 0; i < MAX_MDNS_CACHE_NUM; i++) { + if (kalMemCmp(respInfo->ptrInfo.queryName, + gRspCacheRecord[i].mdnsQuestionTemplate.name, + MDNS_QUESTION_NAME_MAX_LEN) == 0 && + kalMemCmp(respInfo->ptrInfo.domName, + gRspCacheRecord[i].ucServiceName, + MDNS_SERVICE_NAME_MAX_LEN) == 0) { + DBGLOG(SW4, LOUD, "goodbye packet, delete %d.\n", i); + kalMemZero(&gRspCacheRecord[i], + sizeof(struct MDNS_Template_Record)); + break; + } + } + + /* move the other to fill the one */ + for (j = i + 1; j < MAX_MDNS_CACHE_NUM; j++) { + if (gRspCacheRecord[j].bIsUsed == 0) + continue; + + gRspCacheRecord[j].u4RecordId -= 1; + kalMemCopy(&gRspCacheRecord[j - 1], &gRspCacheRecord[j], + sizeof(struct MDNS_Template_Record)); + + } + + kalMemZero(&gRspCacheRecord[MAX_MDNS_CACHE_NUM - 1], + sizeof(struct MDNS_Template_Record)); +} + +void kalInitMdnsCache(void) +{ + kalMemZero(&gRspCacheRecord, + sizeof(struct MDNS_Template_Record) * MAX_MDNS_CACHE_NUM); +} + +#endif + +void kalFreeTxMsduWorker(struct work_struct *work) +{ + struct GLUE_INFO *prGlueInfo; + struct ADAPTER *prAdapter; + struct QUE rTmpQue; + struct QUE *prTmpQue = &rTmpQue; + struct MSDU_INFO *prMsduInfo; + + if (g_u4HaltFlag) + return; + + prGlueInfo = ENTRY_OF(work, struct GLUE_INFO, + rTxMsduFreeWork); + prAdapter = prGlueInfo->prAdapter; + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) + return; + + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); + QUEUE_MOVE_ALL(prTmpQue, &prAdapter->rTxDataDoneQueue); + KAL_RELEASE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); + + while (QUEUE_IS_NOT_EMPTY(prTmpQue)) { + QUEUE_REMOVE_HEAD(prTmpQue, prMsduInfo, struct MSDU_INFO *); + + wlanTxProfilingTagMsdu(prAdapter, prMsduInfo, + TX_PROF_TAG_DRV_FREE_MSDU); + + nicTxFreePacket(prAdapter, prMsduInfo, FALSE); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } +} + +void kalFreeTxMsdu(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); + QUEUE_INSERT_TAIL(&prAdapter->rTxDataDoneQueue, + (struct QUE_ENTRY *) prMsduInfo); + KAL_RELEASE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); + + schedule_work(&prAdapter->prGlueInfo->rTxMsduFreeWork); +} + +int32_t kalHaltLock(uint32_t waitMs) +{ + int32_t i4Ret = 0; + struct GLUE_INFO *prGlueInfo = NULL; + if (waitMs) { + i4Ret = down_timeout(&rHaltCtrl.lock, + MSEC_TO_JIFFIES(waitMs)); + if (!i4Ret) + goto success; + if (i4Ret != -ETIME) + return i4Ret; + + prGlueInfo = wlanGetGlueInfo(); + if (rHaltCtrl.fgHeldByKalIoctl) { + DBGLOG(INIT, ERROR, + "kalIoctl was executed longer than %u ms, show backtrace of tx_thread!\n", + kalGetTimeTick() - rHaltCtrl.u4HoldStart); + if (prGlueInfo) + kal_show_stack(prGlueInfo->prAdapter, + prGlueInfo->main_thread, NULL); + } else { + DBGLOG(INIT, ERROR, + "halt lock held by %s pid %d longer than %u ms!\n", + rHaltCtrl.owner->comm, rHaltCtrl.owner->pid, + kalGetTimeTick() - rHaltCtrl.u4HoldStart); + if (prGlueInfo) + kal_show_stack(prGlueInfo->prAdapter, + rHaltCtrl.owner, NULL); + } + return i4Ret; + } + down(&rHaltCtrl.lock); +success: + rHaltCtrl.owner = current; + rHaltCtrl.u4HoldStart = kalGetTimeTick(); + return 0; +} + +int32_t kalHaltTryLock(void) +{ + int32_t i4Ret = 0; + + i4Ret = down_trylock(&rHaltCtrl.lock); + if (i4Ret) + return i4Ret; + rHaltCtrl.owner = current; + rHaltCtrl.u4HoldStart = kalGetTimeTick(); + return 0; +} + +void kalHaltUnlock(void) +{ + if (kalGetTimeTick() - rHaltCtrl.u4HoldStart > + WLAN_OID_TIMEOUT_THRESHOLD * 2 && + rHaltCtrl.owner) + DBGLOG(INIT, ERROR, + "process %s pid %d hold halt lock longer than 4s!\n", + rHaltCtrl.owner->comm, rHaltCtrl.owner->pid); + rHaltCtrl.owner = NULL; + up(&rHaltCtrl.lock); +} + +void kalSetHalted(u_int8_t fgHalt) +{ + rHaltCtrl.fgHalt = fgHalt; +} + +u_int8_t kalIsHalted(void) +{ + return rHaltCtrl.fgHalt; +} + + +#if 0 +void kalPerMonDump(IN struct GLUE_INFO *prGlueInfo) +{ + struct PERF_MONITOR_T *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + DBGLOG(SW4, WARN, "ulPerfMonFlag:0x%lx\n", + prPerMonitor->ulPerfMonFlag); + DBGLOG(SW4, WARN, "ulLastTxBytes:%d\n", + prPerMonitor->ulLastTxBytes); + DBGLOG(SW4, WARN, "ulLastRxBytes:%d\n", + prPerMonitor->ulLastRxBytes); + DBGLOG(SW4, WARN, "ulP2PLastTxBytes:%d\n", + prPerMonitor->ulP2PLastTxBytes); + DBGLOG(SW4, WARN, "ulP2PLastRxBytes:%d\n", + prPerMonitor->ulP2PLastRxBytes); + DBGLOG(SW4, WARN, "ulThroughput:%d\n", + prPerMonitor->ulThroughput); + DBGLOG(SW4, WARN, "u4UpdatePeriod:%d\n", + prPerMonitor->u4UpdatePeriod); + DBGLOG(SW4, WARN, "u4TarPerfLevel:%d\n", + prPerMonitor->u4TarPerfLevel); + DBGLOG(SW4, WARN, "u4CurrPerfLevel:%d\n", + prPerMonitor->u4CurrPerfLevel); + DBGLOG(SW4, WARN, "netStats tx_bytes:%d\n", + prGlueInfo->prDevHandler->stats.tx_bytes); + DBGLOG(SW4, WARN, "netStats tx_bytes:%d\n", + prGlueInfo->prDevHandler->stats.rx_bytes); + DBGLOG(SW4, WARN, "p2p netStats tx_bytes:%d\n", + prGlueInfo->prP2PInfo->prDevHandler->stats.tx_bytes); + DBGLOG(SW4, WARN, "p2p netStats tx_bytes:%d\n", + prGlueInfo->prP2PInfo->prDevHandler->stats.rx_bytes); +} +#endif + +#if (CFG_SUPPORT_PERF_IND == 1) +#define PERF_UPDATE_PERIOD 1000 /* ms */ +void kalPerfIndReset(IN struct ADAPTER *prAdapter) +{ + uint8_t ucIdx; + + for (ucIdx = 0; ucIdx < BSSID_NUM; ucIdx++) { + prAdapter->prGlueInfo->PerfIndCache.u4CurTxBytes[ucIdx] = 0; + prAdapter->prGlueInfo->PerfIndCache.u4CurRxBytes[ucIdx] = 0; + prAdapter->prGlueInfo->PerfIndCache.u2CurRxRate[ucIdx] = 0; + prAdapter->prGlueInfo->PerfIndCache.ucCurRxRCPI0[ucIdx] = 0; + prAdapter->prGlueInfo->PerfIndCache.ucCurRxRCPI1[ucIdx] = 0; + } +} + +uint32_t kalPerfDisableDataRssiUpdate(IN struct ADAPTER *prAdapter) +{ + struct CMD_COEX_HANDLER rCmdCoexHandler; + bool fgPerfDisableDataRssiUpdate = TRUE; + + ASSERT(prAdapter); + + rCmdCoexHandler.u4SubCmd = + (enum ENUM_COEX_CMD_CTRL) COEX_CMD_SET_DISABLE_DATA_RSSI_UPDATE; + + kalMemCopy(&rCmdCoexHandler.aucBuffer, + &fgPerfDisableDataRssiUpdate, + sizeof(bool)); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_COEX_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_COEX_HANDLER), + (uint8_t *) &rCmdCoexHandler, + NULL, + 0); +} + +void kalSetPerfReport(IN struct ADAPTER *prAdapter) +{ + struct CMD_PERF_IND *prCmdPerfReport; + uint8_t i; + uint32_t u4CurrentTp = 0; + + prCmdPerfReport = (struct CMD_PERF_IND *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct CMD_PERF_IND)); + + if (!prCmdPerfReport) + return; + + kalMemZero(prCmdPerfReport, sizeof(struct CMD_PERF_IND)); + + prCmdPerfReport->ucCmdVer = 0; + prCmdPerfReport->u2CmdLen = sizeof(struct CMD_PERF_IND); + + prCmdPerfReport->u4VaildPeriod = PERF_UPDATE_PERIOD; + + for (i = 0; i < BSS_DEFAULT_NUM; i++) { + prCmdPerfReport->ulCurTxBytes[i] = + prAdapter->prGlueInfo->PerfIndCache.u4CurTxBytes[i]; + prCmdPerfReport->ulCurRxBytes[i] = + prAdapter->prGlueInfo->PerfIndCache.u4CurRxBytes[i]; + prCmdPerfReport->u2CurRxRate[i] = + prAdapter->prGlueInfo->PerfIndCache.u2CurRxRate[i]; + prCmdPerfReport->ucCurRxRCPI0[i] = + prAdapter->prGlueInfo->PerfIndCache.ucCurRxRCPI0[i]; + prCmdPerfReport->ucCurRxRCPI1[i] = + prAdapter->prGlueInfo->PerfIndCache.ucCurRxRCPI1[i]; + prCmdPerfReport->ucCurRxNss[i] = + prAdapter->prGlueInfo->PerfIndCache.ucCurRxNss[i]; + u4CurrentTp += (prCmdPerfReport->ulCurTxBytes[i] + + prCmdPerfReport->ulCurRxBytes[i]); + } + + if (u4CurrentTp != 0) { + DBGLOG(SW4, INFO, + "Total TP[%d] TX-Byte[%d][%d][%d][%d],RX-Byte[%d][%d][%d][%d]\n", + u4CurrentTp, + prCmdPerfReport->ulCurTxBytes[0], + prCmdPerfReport->ulCurTxBytes[1], + prCmdPerfReport->ulCurTxBytes[2], + prCmdPerfReport->ulCurTxBytes[3], + prCmdPerfReport->ulCurRxBytes[0], + prCmdPerfReport->ulCurRxBytes[1], + prCmdPerfReport->ulCurRxBytes[2], + prCmdPerfReport->ulCurRxBytes[3]); + DBGLOG(SW4, INFO, + "Rate[%d][%d][%d][%d] RCPI[%d][%d][%d][%d]\n", + prCmdPerfReport->u2CurRxRate[0], + prCmdPerfReport->u2CurRxRate[1], + prCmdPerfReport->u2CurRxRate[2], + prCmdPerfReport->u2CurRxRate[3], + prCmdPerfReport->ucCurRxRCPI0[0], + prCmdPerfReport->ucCurRxRCPI0[1], + prCmdPerfReport->ucCurRxRCPI0[2], + prCmdPerfReport->ucCurRxRCPI0[3]); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_PERF_IND, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_PERF_IND), + (uint8_t *) prCmdPerfReport, + NULL, + 0); + } + cnmMemFree(prAdapter, prCmdPerfReport); +} +#endif + +inline int32_t kalPerMonInit(IN struct GLUE_INFO + *prGlueInfo) +{ + struct PERF_MONITOR_T *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + DBGLOG(SW4, TRACE, "enter %s\n", __func__); + if (KAL_TEST_BIT(PERF_MON_RUNNING_BIT, + prPerMonitor->ulPerfMonFlag)) + DBGLOG(SW4, WARN, + "abnormal, perf monitor already running\n"); + KAL_CLR_BIT(PERF_MON_RUNNING_BIT, + prPerMonitor->ulPerfMonFlag); + KAL_CLR_BIT(PERF_MON_DISABLE_BIT, + prPerMonitor->ulPerfMonFlag); + KAL_SET_BIT(PERF_MON_STOP_BIT, prPerMonitor->ulPerfMonFlag); + prPerMonitor->u4UpdatePeriod = + prGlueInfo->prAdapter->rWifiVar.u4PerfMonUpdatePeriod; + cnmTimerInitTimerOption(prGlueInfo->prAdapter, + &prPerMonitor->rPerfMonTimer, + (PFN_MGMT_TIMEOUT_FUNC) kalPerMonHandler, + (unsigned long) NULL, + TIMER_WAKELOCK_NONE); +#if (CFG_SUPPORT_PERF_IND == 1) + kalPerfIndReset(prGlueInfo->prAdapter); +#endif + DBGLOG(SW4, TRACE, "exit %s\n", __func__); + return 0; +} + +inline int32_t kalPerMonDisable(IN struct GLUE_INFO + *prGlueInfo) +{ + struct PERF_MONITOR_T *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + + DBGLOG(SW4, INFO, "enter %s\n", __func__); + if (KAL_TEST_BIT(PERF_MON_RUNNING_BIT, + prPerMonitor->ulPerfMonFlag)) { + DBGLOG(SW4, TRACE, "need to stop before disable\n"); + kalPerMonStop(prGlueInfo); + } + KAL_SET_BIT(PERF_MON_DISABLE_BIT, + prPerMonitor->ulPerfMonFlag); + DBGLOG(SW4, TRACE, "exit %s\n", __func__); + return 0; +} + +inline int32_t kalPerMonEnable(IN struct GLUE_INFO + *prGlueInfo) +{ + struct PERF_MONITOR_T *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + + DBGLOG(SW4, INFO, "enter %s\n", __func__); + KAL_CLR_BIT(PERF_MON_DISABLE_BIT, + prPerMonitor->ulPerfMonFlag); + DBGLOG(SW4, TRACE, "exit %s\n", __func__); + return 0; +} + +inline int32_t kalPerMonStart(IN struct GLUE_INFO + *prGlueInfo) +{ + struct PERF_MONITOR_T *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + DBGLOG(SW4, TEMP, "enter %s\n", __func__); + + if (!wlan_perf_monitor_force_enable && + (wlan_fb_power_down || prGlueInfo->fgIsInSuspendMode)) + return 0; + + if (KAL_TEST_BIT(PERF_MON_DISABLE_BIT, + prPerMonitor->ulPerfMonFlag) || + KAL_TEST_BIT(PERF_MON_RUNNING_BIT, + prPerMonitor->ulPerfMonFlag)) + return 0; + + prPerMonitor->ulLastRxBytes = 0; + prPerMonitor->ulLastTxBytes = 0; + prPerMonitor->ulP2PLastRxBytes = 0; + prPerMonitor->ulP2PLastTxBytes = 0; + prPerMonitor->ulThroughput = 0; + prPerMonitor->u4CurrPerfLevel = 0; + prPerMonitor->u4TarPerfLevel = 0; + + prPerMonitor->u4UpdatePeriod = + prGlueInfo->prAdapter->rWifiVar.u4PerfMonUpdatePeriod; + cnmTimerStartTimer(prGlueInfo->prAdapter, + &prPerMonitor->rPerfMonTimer, prPerMonitor->u4UpdatePeriod); + KAL_SET_BIT(PERF_MON_RUNNING_BIT, + prPerMonitor->ulPerfMonFlag); + KAL_CLR_BIT(PERF_MON_STOP_BIT, prPerMonitor->ulPerfMonFlag); + DBGLOG(SW4, INFO, "perf monitor started\n"); + return 0; +} + +inline int32_t kalPerMonStop(IN struct GLUE_INFO + *prGlueInfo) +{ + struct PERF_MONITOR_T *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + DBGLOG(SW4, TRACE, "enter %s\n", __func__); + + if (KAL_TEST_BIT(PERF_MON_DISABLE_BIT, + prPerMonitor->ulPerfMonFlag)) { + DBGLOG(SW4, TRACE, "perf monitor disabled\n"); + return 0; + } + + if (KAL_TEST_BIT(PERF_MON_STOP_BIT, + prPerMonitor->ulPerfMonFlag)) { + DBGLOG(SW4, TRACE, "perf monitor already stopped\n"); + return 0; + } + + KAL_SET_BIT(PERF_MON_STOP_BIT, prPerMonitor->ulPerfMonFlag); + if (KAL_TEST_BIT(PERF_MON_RUNNING_BIT, + prPerMonitor->ulPerfMonFlag)) { + cnmTimerStopTimer(prGlueInfo->prAdapter, + &prPerMonitor->rPerfMonTimer); + KAL_CLR_BIT(PERF_MON_RUNNING_BIT, + prPerMonitor->ulPerfMonFlag); + prPerMonitor->ulLastRxBytes = 0; + prPerMonitor->ulLastTxBytes = 0; + prPerMonitor->ulP2PLastRxBytes = 0; + prPerMonitor->ulP2PLastTxBytes = 0; + prPerMonitor->ulThroughput = 0; + prPerMonitor->ulWlanTxTp = 0; + prPerMonitor->ulWlanRxTp = 0; + prPerMonitor->ulP2PTxTp = 0; + prPerMonitor->ulP2PRxTp = 0; + prPerMonitor->u4CurrPerfLevel = 0; + prPerMonitor->u4TarPerfLevel = 0; + /*Cancel CPU performance mode request*/ + kalBoostCpu(prGlueInfo->prAdapter, + prPerMonitor->u4TarPerfLevel, + prGlueInfo->prAdapter->rWifiVar.u4BoostCpuTh); + } + DBGLOG(SW4, TRACE, "exit %s\n", __func__); + return 0; +} + +inline int32_t kalPerMonDestroy(IN struct GLUE_INFO + *prGlueInfo) +{ + kalPerMonDisable(prGlueInfo); + return 0; +} + +void kalPerMonHandler(IN struct ADAPTER *prAdapter, + unsigned long ulParam) +{ + /*Calculate current throughput*/ + struct PERF_MONITOR_T *prPerMonitor; + struct net_device *prNetDev = NULL; + uint32_t u4Idx = 0; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + uint8_t i = + 0; /*currently i will always be 0 because we only regist 0*/ + u_int8_t fgIsP2PNoneUsed = FALSE; + + signed long latestTxBytes, latestRxBytes, txDiffBytes, + rxDiffBytes; + signed long p2pLatestTxBytes, p2pLatestRxBytes, + p2pTxDiffBytes, p2pRxDiffBytes; + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; +#if (CFG_SUPPORT_PERF_IND == 1) + uint8_t ucIdx; + uint32_t u4CurrentTp = 0; + /* TBD */ + /* struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; */ +#endif + + if ((prGlueInfo->ulFlag & GLUE_FLAG_HALT) + || (!prAdapter->fgIsP2PRegistered)) + return; + + for (u4Idx = 0; u4Idx < BSS_DEFAULT_NUM; u4Idx++) { + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + (uint8_t) u4Idx); + if (prP2pBssInfo->eNetworkType == NETWORK_TYPE_P2P) + break; + } + prNetDev = prGlueInfo->prDevHandler; + + prPerMonitor = &prAdapter->rPerMonitor; + DBGLOG(SW4, TRACE, "enter kalPerMonHandler\n"); +#if (CFG_SUPPORT_PERF_IND == 1) + /* TBD ==> if (prWifiVar->fgPerfIndicatorEn) */ + kalSetPerfReport(prAdapter); + for (ucIdx = 0; ucIdx < BSS_DEFAULT_NUM; ucIdx++) { + u4CurrentTp += + (prAdapter->prGlueInfo->PerfIndCache.u4CurTxBytes[ucIdx] + + prAdapter->prGlueInfo->PerfIndCache.u4CurRxBytes[ucIdx]); + } + kalPerfIndReset(prAdapter); +#endif + + latestTxBytes = prGlueInfo->prDevHandler->stats.tx_bytes; + latestRxBytes = prGlueInfo->prDevHandler->stats.rx_bytes; + if (prGlueInfo->prP2PInfo[i]) { + if (prGlueInfo->prP2PInfo[i]->prDevHandler) { + p2pLatestTxBytes = + prGlueInfo->prP2PInfo[i]->prDevHandler->stats.tx_bytes; + p2pLatestRxBytes = + prGlueInfo->prP2PInfo[i]->prDevHandler->stats.rx_bytes; + } else { + fgIsP2PNoneUsed = TRUE; + p2pLatestTxBytes = 0; + p2pLatestRxBytes = 0; + } + } else { + fgIsP2PNoneUsed = TRUE; + p2pLatestTxBytes = 0; + p2pLatestRxBytes = 0; + } + + if (prPerMonitor->ulLastRxBytes == 0 && + prPerMonitor->ulLastTxBytes == 0 && + prPerMonitor->ulP2PLastRxBytes == 0 && + prPerMonitor->ulP2PLastTxBytes == 0) { + prPerMonitor->ulThroughput = 0; + prPerMonitor->ulWlanTxTp = 0; + prPerMonitor->ulWlanRxTp = 0; + prPerMonitor->ulP2PTxTp = 0; + prPerMonitor->ulP2PRxTp = 0; + } else { + txDiffBytes = latestTxBytes - prPerMonitor->ulLastTxBytes; + rxDiffBytes = latestRxBytes - prPerMonitor->ulLastRxBytes; + if (txDiffBytes < 0) + txDiffBytes = -(txDiffBytes); + if (rxDiffBytes < 0) + rxDiffBytes = -(rxDiffBytes); + + if (!fgIsP2PNoneUsed) { + p2pTxDiffBytes = p2pLatestTxBytes - + prPerMonitor->ulP2PLastTxBytes; + p2pRxDiffBytes = p2pLatestRxBytes - + prPerMonitor->ulP2PLastRxBytes; + if (p2pTxDiffBytes < 0) + p2pTxDiffBytes = -(p2pTxDiffBytes); + if (p2pRxDiffBytes < 0) + p2pRxDiffBytes = -(p2pRxDiffBytes); + } else { + p2pTxDiffBytes = 0; + p2pRxDiffBytes = 0; + } + prPerMonitor->ulThroughput = txDiffBytes + rxDiffBytes + + p2pTxDiffBytes + p2pRxDiffBytes; + prPerMonitor->ulThroughput = + wlanData2RateInMs(prPerMonitor->ulThroughput, + prPerMonitor->u4UpdatePeriod); + prPerMonitor->ulThroughput <<= 3; + + if (txDiffBytes) + prPerMonitor->ulWlanTxTp = + wlanData2RateInMs(txDiffBytes, + prPerMonitor->u4UpdatePeriod); + + if (rxDiffBytes) + prPerMonitor->ulWlanRxTp = + wlanData2RateInMs(rxDiffBytes, + prPerMonitor->u4UpdatePeriod); + + if (p2pTxDiffBytes) + prPerMonitor->ulP2PTxTp = + wlanData2RateInMs(p2pTxDiffBytes, + prPerMonitor->u4UpdatePeriod); + + if (p2pRxDiffBytes) + prPerMonitor->ulP2PRxTp = + wlanData2RateInMs(p2pRxDiffBytes, + prPerMonitor->u4UpdatePeriod); + DBGLOG(SW4, INFO, + "Tput: %ld > [%ld][%ld] [%ld][%ld], Pending[%d], Used[%d] PER[%ld %ld]\n", + prPerMonitor->ulThroughput, + txDiffBytes, rxDiffBytes, + p2pTxDiffBytes, p2pRxDiffBytes, + GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum), + GLUE_GET_REF_CNT(prPerMonitor->u4UsedCnt), + prPerMonitor->ulTotalTxSuccessCount, + prPerMonitor->ulTotalTxFailCount); + } + + prPerMonitor->ulLastTxBytes = latestTxBytes; + prPerMonitor->ulLastRxBytes = latestRxBytes; + prPerMonitor->ulP2PLastTxBytes = p2pLatestTxBytes; + prPerMonitor->ulP2PLastRxBytes = p2pLatestRxBytes; + + prPerMonitor->u4TarPerfLevel = PERF_MON_TP_MAX_THRESHOLD; + for (u4Idx = 0; u4Idx < PERF_MON_TP_MAX_THRESHOLD; + u4Idx++) { + if ((prPerMonitor->ulThroughput >> 20) < + prAdapter->rWifiVar.u4PerfMonTpTh[u4Idx]) { + prPerMonitor->u4TarPerfLevel = u4Idx; + break; + } + } + + if (!wlan_perf_monitor_force_enable && + (wlan_fb_power_down || + prGlueInfo->fgIsInSuspendMode || + !(netif_carrier_ok(prNetDev) || + (prP2pBssInfo->eConnectionState == + PARAM_MEDIA_STATE_CONNECTED) || + (prP2pBssInfo->rStaRecOfClientList.u4NumElem > 0)))) + kalPerMonStop(prGlueInfo); + else { + if ((prPerMonitor->u4TarPerfLevel != + prPerMonitor->u4CurrPerfLevel) && + (prAdapter->rWifiVar.u4BoostCpuTh < + PERF_MON_TP_MAX_THRESHOLD)) { + + DBGLOG(SW4, INFO, + "PerfMon total:%3lu.%03lu mbps lv:%u th:%u fg:0x%lx\n", + (unsigned long) (prPerMonitor->ulThroughput >> 20), + (unsigned long) ((prPerMonitor->ulThroughput >> 10) + & BITS(0, 9)), + prPerMonitor->u4TarPerfLevel, + prAdapter->rWifiVar.u4BoostCpuTh, + prPerMonitor->ulPerfMonFlag); + + kalBoostCpu(prAdapter, prPerMonitor->u4TarPerfLevel, + prAdapter->rWifiVar.u4BoostCpuTh); + } + prPerMonitor->u4UpdatePeriod = + prAdapter->rWifiVar.u4PerfMonUpdatePeriod; +#if (CFG_SUPPORT_PERF_IND == 1) + /* Only routine start timer when Tput exist*/ + if (u4CurrentTp > 0) { + cnmTimerStartTimer(prGlueInfo->prAdapter, + &prPerMonitor->rPerfMonTimer, + prPerMonitor->u4UpdatePeriod); + } else { + KAL_CLR_BIT(PERF_MON_RUNNING_BIT, + prPerMonitor->ulPerfMonFlag); + kalPerfDisableDataRssiUpdate(prAdapter); + } +#else + cnmTimerStartTimer(prGlueInfo->prAdapter, + &prPerMonitor->rPerfMonTimer, + prPerMonitor->u4UpdatePeriod); +#endif + } + prPerMonitor->u4CurrPerfLevel = + prPerMonitor->u4TarPerfLevel; + + /* check tx hang */ + prAdapter->u4HifChkFlag |= HIF_CHK_TX_HANG; + kalSetHifDbgEvent(prAdapter->prGlueInfo); + + DBGLOG(SW4, TRACE, "exit kalPerMonHandler\n"); +} + +uint32_t kalPerMonGetInfo(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, IN uint32_t u4Max) +{ + struct PERF_MONITOR_T *prPerMonitor; + uint32_t u4Len = 0; + unsigned long ulWlanTxTpInBits, ulWlanRxTpInBits, + ulP2PTxTpInBits, ulP2PRxTpInBits; + + prPerMonitor = &prAdapter->rPerMonitor; + + ulWlanTxTpInBits = prPerMonitor->ulWlanTxTp << 3; + ulWlanRxTpInBits = prPerMonitor->ulWlanRxTp << 3; + ulP2PTxTpInBits = prPerMonitor->ulP2PTxTp << 3; + ulP2PRxTpInBits = prPerMonitor->ulP2PRxTp << 3; + + LOGBUF(pucBuf, u4Max, u4Len, + "\nWi-Fi Throughput (update period %ums):\n", + prPerMonitor->u4UpdatePeriod); + + LOGBUF(pucBuf, u4Max, u4Len, + "wlan Tx: %3lu.%03lu mbps, Rx %3lu.%03lu mbps\n", + (ulWlanTxTpInBits >> 20), + ((ulWlanTxTpInBits >> 10) & BITS(0, 9)), + (ulWlanRxTpInBits >> 20), + ((ulWlanRxTpInBits >> 10) & BITS(0, 9))); + + LOGBUF(pucBuf, u4Max, u4Len, + "p2p Tx: %3lu.%03lu mbps, Rx %3lu.%03lu mbps\n", + (ulP2PTxTpInBits >> 20), ((ulP2PTxTpInBits >> 10) & BITS(0, + 9)), + (ulP2PRxTpInBits >> 20), ((ulP2PRxTpInBits >> 10) & BITS(0, + 9))); + + LOGBUF(pucBuf, u4Max, u4Len, "Total: %3lu.%03lu mbps\n", + (prPerMonitor->ulThroughput >> 20), + ((prPerMonitor->ulThroughput >> 10) & BITS(0, 9))); + + LOGBUF(pucBuf, u4Max, u4Len, + "Performance level: %u threshold: %u flag: 0x%lx\n", + prPerMonitor->u4CurrPerfLevel, + prAdapter->rWifiVar.u4BoostCpuTh, + prPerMonitor->ulPerfMonFlag); + + return u4Len; +} + +int32_t __weak kalBoostCpu(IN struct ADAPTER *prAdapter, + IN uint32_t u4TarPerfLevel, IN uint32_t u4BoostCpuTh) +{ + DBGLOG(SW4, INFO, "enter kalBoostCpu\n"); + return 0; +} + +int32_t __weak kalSetCpuNumFreq(uint32_t u4CoreNum, + uint32_t u4Freq) +{ + DBGLOG(SW4, INFO, + "enter weak kalSetCpuNumFreq, u4CoreNum:%d, urFreq:%d\n", + u4CoreNum, u4Freq); + return 0; +} + +void __weak kalSetEmiMpuProtection(phys_addr_t emiPhyBase, uint32_t offset, + uint32_t size, bool enable) +{ + DBGLOG(SW4, WARN, "EMI MPU function is not defined\n"); +} + +void __weak kalSetDrvEmiMpuProtection(phys_addr_t emiPhyBase, uint32_t offset, + uint32_t size) +{ + DBGLOG(SW4, WARN, "DRV EMI MPU function is not defined\n"); +} + +int32_t kalPerMonSetForceEnableFlag(uint8_t uFlag) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) + wlan_fb_notifier_priv_data; + + wlan_perf_monitor_force_enable = uFlag == 0 ? FALSE : TRUE; + DBGLOG(SW4, INFO, + "uFlag:%d, wlan_perf_monitor_ctrl_flag:%d\n", uFlag, + wlan_perf_monitor_force_enable); + + if (wlan_perf_monitor_force_enable && prGlueInfo + && !kalIsHalted()) + kalPerMonEnable(prGlueInfo); + + return 0; +} + +static int wlan_fb_notifier_callback(struct notifier_block + *self, unsigned long event, void *data) +{ + struct fb_event *evdata = data; + int32_t blank = 0; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) + wlan_fb_notifier_priv_data; + + /* If we aren't interested in this event, skip it immediately ... */ + if ((event != FB_EVENT_BLANK) || !prGlueInfo) + return 0; + + if (kalHaltTryLock()) + return 0; + + if (kalIsHalted()) { + kalHaltUnlock(); + return 0; + } + + blank = *(int32_t *)evdata->data; + + switch (blank) { + case FB_BLANK_UNBLANK: + kalPerMonEnable(prGlueInfo); + wlan_fb_power_down = FALSE; + break; + case FB_BLANK_POWERDOWN: + wlan_fb_power_down = TRUE; + if (!wlan_perf_monitor_force_enable) + kalPerMonDisable(prGlueInfo); + break; + default: + break; + } + + kalHaltUnlock(); + return 0; +} + +int32_t kalFbNotifierReg(IN struct GLUE_INFO *prGlueInfo) +{ + int32_t i4Ret; + + wlan_fb_notifier_priv_data = prGlueInfo; + wlan_fb_notifier.notifier_call = wlan_fb_notifier_callback; + + i4Ret = fb_register_client(&wlan_fb_notifier); + if (i4Ret) + DBGLOG(SW4, WARN, "Register wlan_fb_notifier failed:%d\n", + i4Ret); + else + DBGLOG(SW4, TRACE, "Register wlan_fb_notifier succeed\n"); + return i4Ret; +} + +void kalFbNotifierUnReg(void) +{ + fb_unregister_client(&wlan_fb_notifier); + wlan_fb_notifier_priv_data = NULL; +} + +#if CFG_SUPPORT_DFS +void kalIndicateChannelSwitch(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_CHNL_EXT eSco, + IN uint8_t ucChannelNum) +{ + struct cfg80211_chan_def chandef; + struct ieee80211_channel *prChannel = NULL; + enum nl80211_channel_type rChannelType; + + if (ucChannelNum <= 14) { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, + KAL_BAND_2GHZ)); + } else { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, + KAL_BAND_5GHZ)); + } + + if (!prChannel) { + DBGLOG(REQ, ERROR, "ieee80211_get_channel fail!\n"); + return; + } + + switch (eSco) { + case CHNL_EXT_SCN: + rChannelType = NL80211_CHAN_NO_HT; + break; + + case CHNL_EXT_SCA: + rChannelType = NL80211_CHAN_HT40MINUS; + break; + + case CHNL_EXT_SCB: + rChannelType = NL80211_CHAN_HT40PLUS; + break; + + case CHNL_EXT_RES: + default: + rChannelType = NL80211_CHAN_HT20; + break; + } + + DBGLOG(REQ, STATE, "DFS channel switch to %d\n", ucChannelNum); + + cfg80211_chandef_create(&chandef, prChannel, rChannelType); + cfg80211_ch_switch_notify(prGlueInfo->prDevHandler, &chandef); +} +#endif + +void kalInitDevWakeup(struct ADAPTER *prAdapter, struct device *prDev) +{ + /* + * The remote wakeup function will be disabled after + * first time resume, we need to call device_init_wakeup() + * to notify usbcore that we support wakeup function, + * so usbcore will re-enable our remote wakeup function + * before entering suspend. + */ + if (prAdapter->rWifiVar.ucWow) + device_init_wakeup(prDev, TRUE); +} + +u_int8_t kalIsOuiMask(const uint8_t pucMacAddrMask[MAC_ADDR_LEN]) +{ + return (pucMacAddrMask[0] == 0xFF && + pucMacAddrMask[1] == 0xFF && + pucMacAddrMask[2] == 0xFF); +} + +u_int8_t kalIsValidMacAddr(const uint8_t *addr) +{ + return (addr != NULL) && is_valid_ether_addr(addr); +} + +#if (KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE) +u_int8_t kalParseRandomMac(const struct net_device *ndev, + uint8_t *pucMacAddr, uint8_t *pucMacAddrMask, + uint8_t *pucRandomMac) +{ + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = NULL; + struct ADAPTER *prAdapter = NULL; + uint8_t ucBssIndex; + struct BSS_INFO *prBssInfo; + uint8_t ucMacAddr[MAC_ADDR_LEN]; + + if (!ndev) { + log_dbg(SCN, ERROR, "Invalid net device\n"); + return FALSE; + } + + prNetDevPrivate = + (struct NETDEV_PRIVATE_GLUE_INFO *) netdev_priv(ndev); + + if (!prNetDevPrivate || !(prNetDevPrivate->prGlueInfo) + || !(prNetDevPrivate->prGlueInfo->prAdapter)) { + log_dbg(SCN, ERROR, "Invalid private param\n"); + return FALSE; + } + + prAdapter = prNetDevPrivate->prGlueInfo->prAdapter; + ucBssIndex = prNetDevPrivate->ucBssIdx; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (!prBssInfo) { + log_dbg(SCN, WARN, "Invalid bss info (ind=%u)\n", ucBssIndex); + return FALSE; + } + + if (!kalIsOuiMask(pucMacAddrMask) && !prBssInfo->fgIsScanOuiSet) { + eth_zero_addr(pucRandomMac); + eth_zero_addr(pucMacAddrMask); + log_dbg(SCN, INFO, "random mac enabled.\n"); + return TRUE; + } + + if (pucMacAddr) + COPY_MAC_ADDR(ucMacAddr, pucMacAddr); + else + eth_zero_addr(ucMacAddr); + + if (prBssInfo->fgIsScanOuiSet) { + kalMemCopy(ucMacAddr, prBssInfo->ucScanOui, MAC_OUI_LEN); + kalMemSet(pucMacAddrMask, 0xFF, MAC_OUI_LEN); + } + get_random_mask_addr(pucRandomMac, ucMacAddr, pucMacAddrMask); + log_dbg(SCN, INFO, "random mac=" MACSTR ", mac_addr=" MACSTR + ", mac_addr_mask=%pM\n", MAC2STR(pucRandomMac), + MAC2STR(ucMacAddr), pucMacAddrMask); + + return TRUE; +} + +u_int8_t kalScanParseRandomMac(const struct net_device *ndev, + const struct cfg80211_scan_request *request, uint8_t *pucRandomMac) +{ + uint8_t ucMacAddr[MAC_ADDR_LEN]; + uint8_t ucMacAddrMask[MAC_ADDR_LEN]; + + ASSERT(request); + ASSERT(pucRandomMac); + + if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) { + log_dbg(SCN, TRACE, "Scan random mac is not set\n"); + return FALSE; + } +#if KERNEL_VERSION(4, 10, 0) <= CFG80211_VERSION_CODE + { + if (kalIsValidMacAddr(request->bssid)) { + COPY_MAC_ADDR(pucRandomMac, request->bssid); + log_dbg(SCN, INFO, "random mac=" MACSTR "\n", + pucRandomMac); + return TRUE; + } + } +#endif + COPY_MAC_ADDR(ucMacAddr, request->mac_addr); + COPY_MAC_ADDR(ucMacAddrMask, request->mac_addr_mask); + + return kalParseRandomMac(ndev, ucMacAddr, ucMacAddrMask, pucRandomMac); +} + +u_int8_t kalSchedScanParseRandomMac(const struct net_device *ndev, + const struct cfg80211_sched_scan_request *request, + uint8_t *pucRandomMac, uint8_t *pucRandomMacMask) +{ + uint8_t ucMacAddr[MAC_ADDR_LEN]; + + ASSERT(request); + ASSERT(pucRandomMac); + ASSERT(pucRandomMacMask); + + if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) { + log_dbg(SCN, TRACE, "Scan random mac is not set\n"); + return FALSE; + } + COPY_MAC_ADDR(ucMacAddr, request->mac_addr); + COPY_MAC_ADDR(pucRandomMacMask, request->mac_addr_mask); + + return kalParseRandomMac(ndev, ucMacAddr, + pucRandomMacMask, pucRandomMac); +} +#else /* if (KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE) */ +u_int8_t kalScanParseRandomMac(const struct net_device *ndev, + const struct cfg80211_scan_request *request, uint8_t *pucRandomMac) +{ + return FALSE; +} + +u_int8_t kalSchedScanParseRandomMac(const struct net_device *ndev, + const struct cfg80211_sched_scan_request *request, + uint8_t *pucRandomMac, uint8_t *pucRandomMacMask) +{ + return FALSE; +} +#endif + +void kalScanReqLog(struct cfg80211_scan_request *request) +{ +#if (KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE) + scanlog_dbg(LOG_SCAN_REQ_K2D, INFO, "Scan flags=0x%x [mac]addr=" + MACSTR " mask=" MACSTR "\n", + request->flags, + MAC2STR(request->mac_addr), + MAC2STR(request->mac_addr_mask)); +#else + scanlog_dbg(LOG_SCAN_REQ_K2D, INFO, "Scan flags=0x%x\n", + request->flags); +#endif + kalScanSsidLog(request, SCAN_LOG_MSG_MAX_LEN); + kalScanChannelLog(request, SCAN_LOG_MSG_MAX_LEN); +} + +void kalScanChannelLog(struct cfg80211_scan_request *request, + const uint16_t logBufLen) +{ + char logBuf[logBufLen]; + uint32_t idx = 0; + int i = 0; + /* the decimal value could be 0 ~ 65535 */ + const uint8_t dataLen = 6; + + /* The maximum characters of int32_t could be 10. Thus, the + * length should be 10+14 for the format "n_channels=%u: ". + */ + idx += kalSnprintf(logBuf, 24, "n_channels=%u: ", request->n_channels); + + for (i = 0; i < request->n_channels; ++i) { + if (dataLen+1 > logBufLen) { + scanlog_dbg(LOG_SCAN_REQ_K2D, INFO, "Need buffer size %u for log\n", + dataLen+1); + break; + } else if (idx+dataLen+1 > logBufLen) { + logBuf[idx] = 0; /* terminating null byte */ + scanlog_dbg(LOG_SCAN_REQ_K2D, INFO, "%s\n", + logBuf); + idx = 0; + } + + /* number + terminating null byte + a space */ + idx += kalSnprintf(logBuf+idx, dataLen+1, "%u ", + request->channels[i]->hw_value); + } + if (idx != 0) { + logBuf[idx] = 0; /* terminating null byte */ + scanlog_dbg(LOG_SCAN_REQ_K2D, INFO, "%s\n", + logBuf); + idx = 0; + } +} + +void kalScanSsidLog(struct cfg80211_scan_request *request, + const uint16_t logBufLen) +{ + char logBuf[logBufLen]; + uint32_t idx = 0; + int i = 0; + + /* The maximum characters of uint32_t could be 10. Thus, the + * length should be 10+11 for the format "n_ssids=%d: ". + */ + idx += kalSnprintf(logBuf, 21, "n_ssids=%d: ", request->n_ssids); + + for (i = 0; i < request->n_ssids; ++i) { + uint8_t len = request->ssids[i].ssid_len; + + if (len == 0) { + continue; + } else if (len+1+1 > logBufLen) { + scanlog_dbg(LOG_SCAN_REQ_K2D, INFO, "Need buffer size %u for log\n", + len+1+1); + break; + } else if (idx+len+1+1 > logBufLen) { + logBuf[idx] = 0; /* terminating null byte */ + scanlog_dbg(LOG_SCAN_REQ_K2D, INFO, "%s\n", + logBuf); + idx = 0; + } + + /* SSID without terminating null byte */ + kalStrnCpy(logBuf+idx, request->ssids[i].ssid, len); + idx = idx + len; + + kalMemCopy(logBuf+idx, " ", 1); + idx = idx + 1; + } + if (idx != 0) { + logBuf[idx] = 0; /* terminating null byte */ + scanlog_dbg(LOG_SCAN_REQ_K2D, INFO, "%s\n", + logBuf); + idx = 0; + } +} + +void kalScanResultLog(struct ADAPTER *prAdapter, struct ieee80211_mgmt *mgmt) +{ + scanLogCacheAddBSS( + &(prAdapter->rWifiVar.rScanInfo.rScanLogCache.rBSSListCFG), + prAdapter->rWifiVar.rScanInfo.rScanLogCache.arBSSListBufCFG, + LOG_SCAN_RESULT_D2K, + mgmt->bssid, + mgmt->seq_ctrl); +} + +void kalScanLogCacheFlushBSS(struct ADAPTER *prAdapter, + const uint16_t logBufLen) +{ + scanLogCacheFlushBSS( + &(prAdapter->rWifiVar.rScanInfo.rScanLogCache.rBSSListCFG), + LOG_SCAN_DONE_D2K, logBufLen); +} + +void kalRxNapiSetEnable( + IN struct GLUE_INFO *prGlueInfo, + IN uint8_t enable) +{ +#if IS_ENABLED(CFG_RX_NAPI_SUPPORT) + DBGLOG(RX, STATE, "RX NAPI %s\n", (enable?"Enable":"Disable")); + prGlueInfo->ucRxNapiEnable = enable; +#endif +} + +uint8_t kalRxNapiIsEnable(IN struct GLUE_INFO *prGlueInfo) +{ +#if IS_ENABLED(CFG_RX_NAPI_SUPPORT) + return prGlueInfo->ucRxNapiEnable; +#else + return FALSE; +#endif +} + +uint8_t kalRxNapiValidSkb(struct GLUE_INFO *prGlueInfo, + struct sk_buff *prSkb) +{ +#if IS_ENABLED(CFG_RX_NAPI_SUPPORT) + struct WIFI_VAR *prWifiVar = &prGlueInfo->prAdapter->rWifiVar; + struct PERF_MONITOR_T *prPerMonitor = + &prGlueInfo->prAdapter->rPerMonitor; + struct net_device *prNetDev = prGlueInfo->prDevHandler; + + uint8_t *pucMacHdr; + uint8_t ucIpProto; + uint16_t u2EtherType; + +#if CFG_SUPPORT_SNIFFER + if (prGlueInfo->fgIsEnableMon) + return FALSE; +#endif + prNetDev = (struct net_device *)wlanGetNetInterfaceByBssIdx( + prGlueInfo, GLUE_GET_PKT_BSS_IDX(prSkb)); + if (!prNetDev) + prNetDev = prGlueInfo->prDevHandler; + /*ap/p2p not support yet*/ + if (NL80211_IFTYPE_STATION != + prNetDev->ieee80211_ptr->iftype) + return FALSE; + if (!kalRxNapiIsEnable(prGlueInfo)) + return FALSE; + + /* Tput condition check, if PerfMon running */ + if (KAL_TEST_BIT(PERF_MON_RUNNING_BIT, prPerMonitor->ulPerfMonFlag)) { + /* Skip NAPI if Tput too low */ + uint16_t u2TputMbps = 0; + + if (prWifiVar->ucRxNapiNoTx) { + u2TputMbps += prPerMonitor->ulWlanRxTp >> 17; + u2TputMbps += prPerMonitor->ulP2PRxTp >> 17; + } else + u2TputMbps = prPerMonitor->ulThroughput >> 20; + + if (u2TputMbps < prWifiVar->ucRxNapiThreshold) + return FALSE; + } + + /* Get mac_hdr to check caller */ + if (!skb_mac_header_was_set(prSkb)) + skb_reset_mac_header(prSkb); + pucMacHdr = skb_mac_header(prSkb); + + /* If in main thread, check settings */ + if (prSkb->data == pucMacHdr) { + /* If we need RxThread mode, return FALSE here. */ + if (prWifiVar->ucRxNapiThread) + return FALSE; + } + + /* Need to check IP protocol? */ + if (!prWifiVar->ucRxNapiPktChk) + return TRUE; + + WLAN_GET_FIELD_BE16(&pucMacHdr[ETHER_TYPE_LEN_OFFSET], &u2EtherType); + + /* Check if pkt-len is valid or not */ + if (u2EtherType != ETH_P_IPV4 || + prSkb->len <= ETH_HLEN+IPV4_HDR_LEN) + return TRUE; + + /* Check type of IP-pkt */ + ucIpProto = pucMacHdr[ETH_HLEN+IPV4_HDR_IP_PROTOCOL_OFFSET]; + /* NAPI may drop UDP */ + if (ucIpProto == IP_PRO_UDP) + return FALSE; + + return TRUE; +#else + return FALSE; +#endif +} + +int kalRxNapiPoll(struct napi_struct *napi, int budget) +{ +#if IS_ENABLED(CFG_RX_NAPI_SUPPORT) + uint32_t work_done = 0; + struct sk_buff *prSkb = NULL; + struct GLUE_INFO *prGlueInfo = + container_of(napi, struct GLUE_INFO, rNapi); + + while ((work_done < budget) && + (!skb_queue_empty(&prGlueInfo->rRxNapiSkbQ))) { + uint8_t ucAccept = TRUE; + + prSkb = skb_dequeue(&prGlueInfo->rRxNapiSkbQ); + if (!prSkb) + break; + +#if IS_ENABLED(CFG_GRO_SUPPORT) + if (napi_gro_receive(napi, prSkb) == GRO_DROP) +#else + if (netif_receive_skb(prSkb) != NET_RX_SUCCESS) +#endif /* CFG_GRO_SUPPORT */ + ucAccept = FALSE; + + if (ucAccept) + work_done++; + } + if (work_done < budget) { + if (!skb_queue_empty(&prGlueInfo->rRxNapiSkbQ)) + napi_schedule(napi); + else + napi_complete(napi); + } + return work_done; +#else + return 0; +#endif +} + +unsigned long kal_kallsyms_lookup_name(const char *name) +{ + unsigned long ret = 0; + + ret = kallsyms_lookup_name(name); + if (ret) { +#ifdef CONFIG_ARM +#ifdef CONFIG_THUMB2_KERNEL + /*set bit 0 in address for thumb mode*/ + ret |= 1; +#endif +#endif + } + return ret; +} + + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_p2p.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_p2p.c new file mode 100644 index 0000000000000..dc4de82a785ac --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_p2p.c @@ -0,0 +1,2120 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + + +/****************************************************************************** + * C O M P I L E R F L A G S + ****************************************************************************** + */ + +/****************************************************************************** + * E X T E R N A L R E F E R E N C E S + ****************************************************************************** + */ + +#include + +#include + + +#include "gl_os.h" +#include "debug.h" +#include "wlan_lib.h" +#include "gl_wext.h" + +/* #include */ +#include "gl_p2p_ioctl.h" + +#include "precomp.h" +#include "gl_vendor.h" +#include "gl_cfg80211.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) + +#if 0 +#define RUNNING_P2P_MODE 0 +#define RUNNING_AP_MODE 1 +#define RUNNING_DUAL_AP_MODE 2 +#endif +/****************************************************************************** + * 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 + ****************************************************************************** + */ + +struct net_device *g_P2pPrDev; +struct wireless_dev *gprP2pWdev; +struct wireless_dev *gprP2pRoleWdev[KAL_P2P_NUM]; +struct net_device *gPrP2pDev[KAL_P2P_NUM]; + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#if (CFG_ENABLE_UNIFY_WIPHY == 0) +static struct cfg80211_ops mtk_p2p_ops = { +#if (CFG_ENABLE_WIFI_DIRECT_CFG_80211 != 0) + /* Froyo */ + .add_virtual_intf = mtk_p2p_cfg80211_add_iface, + .change_virtual_intf = mtk_p2p_cfg80211_change_iface, /* 1 st */ + .del_virtual_intf = mtk_p2p_cfg80211_del_iface, + .change_bss = mtk_p2p_cfg80211_change_bss, + .scan = mtk_p2p_cfg80211_scan, +#if KERNEL_VERSION(4, 5, 0) <= CFG80211_VERSION_CODE + .abort_scan = mtk_p2p_cfg80211_abort_scan, +#endif + .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, + .mgmt_tx_cancel_wait = mtk_p2p_cfg80211_mgmt_tx_cancel_wait, + .connect = mtk_p2p_cfg80211_connect, + .disconnect = mtk_p2p_cfg80211_disconnect, + .deauth = mtk_p2p_cfg80211_deauth, + .disassoc = mtk_p2p_cfg80211_disassoc, + .start_ap = mtk_p2p_cfg80211_start_ap, + .change_beacon = mtk_p2p_cfg80211_change_beacon, + .stop_ap = mtk_p2p_cfg80211_stop_ap, + .set_wiphy_params = mtk_p2p_cfg80211_set_wiphy_params, + .del_station = mtk_p2p_cfg80211_del_station, + .set_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, + .set_default_mgmt_key = mtk_p2p_cfg80211_set_mgmt_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, +#if (CFG_SUPPORT_DFS_MASTER == 1) + .start_radar_detection = mtk_p2p_cfg80211_start_radar_detection, +#if KERNEL_VERSION(3, 13, 0) <= CFG80211_VERSION_CODE + .channel_switch = mtk_p2p_cfg80211_channel_switch, +#endif +#endif +#ifdef CONFIG_NL80211_TESTMODE + .testmode_cmd = mtk_p2p_cfg80211_testmode_cmd, +#endif +#endif +}; +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE + +static const struct wiphy_vendor_command mtk_p2p_vendor_ops[] = { + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_GET_CHANNEL_LIST + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV + | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_channel_list + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_SET_COUNTRY_CODE + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV + | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_country_code + }, +#if CFG_SUPPORT_P2P_PREFERRED_FREQ_LIST + /* P2P get preferred freq list */ + { + { + .vendor_id = OUI_QCA, + .subcmd = NL80211_VENDOR_SUBCMD_GET_PREFER_FREQ_LIST + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV + | WIPHY_VENDOR_CMD_NEED_NETDEV + | WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = mtk_cfg80211_vendor_get_preferred_freq_list + }, +#endif /* CFG_SUPPORT_P2P_PREFERRED_FREQ_LIST */ +}; + +#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 +#endif + +static const struct iw_priv_args rP2PIwPrivTable[] = { + { + .cmd = IOC_P2P_CFG_DEVICE, + .set_args = IW_PRIV_TYPE_BYTE + | (__u16) sizeof(struct 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(struct 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(struct 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(struct 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(struct 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(struct 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"} +}; + +#if 0 +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 +}; +#endif + +#ifdef CONFIG_PM +static const struct wiphy_wowlan_support mtk_p2p_wowlan_support = { + .flags = WIPHY_WOWLAN_DISCONNECT | WIPHY_WOWLAN_ANY, +}; +#endif + +static const struct ieee80211_iface_limit mtk_p2p_sta_go_limits[] = { + { + .max = 3, + .types = BIT(NL80211_IFTYPE_STATION), + }, + + { + .max = 1, + .types = BIT(NL80211_IFTYPE_P2P_GO) + | BIT(NL80211_IFTYPE_P2P_CLIENT), + }, +}; + +#if (CFG_SUPPORT_DFS_MASTER == 1) +#if (KERNEL_VERSION(3, 17, 0) > CFG80211_VERSION_CODE) + +static const struct ieee80211_iface_limit mtk_ap_limits[] = { + { + .max = 1, + .types = BIT(NL80211_IFTYPE_AP), + }, +}; +#endif +#endif + +static const struct ieee80211_iface_combination +mtk_iface_combinations_sta[] = { + { +#ifdef CFG_NUM_DIFFERENT_CHANNELS_STA + .num_different_channels = CFG_NUM_DIFFERENT_CHANNELS_STA, +#else + .num_different_channels = 2, +#endif /* CFG_NUM_DIFFERENT_CHANNELS_STA */ + .max_interfaces = 3, + /*.beacon_int_infra_match = true,*/ + .limits = mtk_p2p_sta_go_limits, + .n_limits = 1, /* include p2p */ + }, +}; + +static const struct ieee80211_iface_combination +mtk_iface_combinations_p2p[] = { + { +#if CFG_ENABLE_UNIFY_WIPHY + /* The 2 MCC channels case has been verified */ + .num_different_channels = 2, +#elif defined(CFG_NUM_DIFFERENT_CHANNELS_P2P) + .num_different_channels = CFG_NUM_DIFFERENT_CHANNELS_P2P, +#else + .num_different_channels = 2, +#endif /* CFG_NUM_DIFFERENT_CHANNELS_P2P */ + .max_interfaces = 3, + /*.beacon_int_infra_match = true,*/ + .limits = mtk_p2p_sta_go_limits, + .n_limits = ARRAY_SIZE(mtk_p2p_sta_go_limits), /* include p2p */ + }, +#if (CFG_SUPPORT_DFS_MASTER == 1) +#if (KERNEL_VERSION(3, 17, 0) > CFG80211_VERSION_CODE) + /* ONLY for passing checks in cfg80211_can_use_iftype_chan + * before linux-3.17.0 + */ + { + .num_different_channels = 1, + .max_interfaces = 1, + .limits = mtk_ap_limits, + .n_limits = ARRAY_SIZE(mtk_ap_limits), + .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | + BIT(NL80211_CHAN_WIDTH_20) | + BIT(NL80211_CHAN_WIDTH_40) | + BIT(NL80211_CHAN_WIDTH_80) | + BIT(NL80211_CHAN_WIDTH_80P80), + }, +#endif +#endif +}; + + +const struct ieee80211_iface_combination + *p_mtk_iface_combinations_sta = mtk_iface_combinations_sta; +const int32_t mtk_iface_combinations_sta_num = + ARRAY_SIZE(mtk_iface_combinations_sta); + +const struct ieee80211_iface_combination + *p_mtk_iface_combinations_p2p = mtk_iface_combinations_p2p; +const int32_t mtk_iface_combinations_p2p_num = + ARRAY_SIZE(mtk_iface_combinations_p2p); + +/****************************************************************************** + * M A C R O S + ****************************************************************************** + */ + +/****************************************************************************** + * F U N C T I O N D E C L A R A T I O N S + ****************************************************************************** + */ + +/* 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 p2pSetMACAddress(IN struct net_device *prDev, void *addr); + +static int p2pDoIOCTL(struct net_device *prDev, + struct ifreq *prIFReq, + int i4Cmd); + + +/*---------------------------------------------------------------------------*/ +/*! + * \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) +{ +} /* end of p2pUninit() */ + +const struct net_device_ops p2p_netdev_ops = { + .ndo_open = p2pOpen, + .ndo_stop = p2pStop, + .ndo_set_mac_address = p2pSetMACAddress, + .ndo_set_rx_mode = p2pSetMulticastList, + .ndo_get_stats = p2pGetStats, + .ndo_do_ioctl = p2pDoIOCTL, + .ndo_start_xmit = p2pHardStartXmit, + /* .ndo_select_queue = p2pSelectQueue, */ + .ndo_select_queue = wlanSelectQueue, + .ndo_init = p2pInit, + .ndo_uninit = p2pUninit, +}; + +/****************************************************************************** + * F U N C T I O N S + ****************************************************************************** + */ + +/*---------------------------------------------------------------------------*/ +/*! + * \brief Allocate memory for P2P_INFO, GL_P2P_INFO, P2P_CONNECTION_SETTINGS + * P2P_SPECIFIC_BSS_INFO, P2P_FSM_INFO + * + * \param[in] prGlueInfo Pointer to glue info + * + * \return TRUE + * FALSE + */ +/*---------------------------------------------------------------------------*/ +u_int8_t p2PAllocInfo(IN struct GLUE_INFO *prGlueInfo, IN uint8_t ucIdex) +{ + struct ADAPTER *prAdapter = NULL; + struct WIFI_VAR *prWifiVar = NULL; + /* UINT_32 u4Idx = 0; */ + + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + prWifiVar = &(prAdapter->rWifiVar); + + ASSERT(prAdapter); + ASSERT(prWifiVar); + + do { + if (prGlueInfo->prP2PInfo[ucIdex] == NULL) { + /*alloc memory for p2p info */ + prGlueInfo->prP2PInfo[ucIdex] = + kalMemAlloc(sizeof(struct GL_P2P_INFO), + VIR_MEM_TYPE); + + if (prGlueInfo->prP2PDevInfo == NULL) { + prGlueInfo->prP2PDevInfo = + kalMemAlloc( + sizeof(struct GL_P2P_DEV_INFO), + VIR_MEM_TYPE); + if (prGlueInfo->prP2PDevInfo) { + kalMemZero(prGlueInfo->prP2PDevInfo, + sizeof(struct GL_P2P_DEV_INFO)); + } + } + + if (prAdapter->prP2pInfo == NULL) { + prAdapter->prP2pInfo = + kalMemAlloc(sizeof(struct P2P_INFO), + VIR_MEM_TYPE); + if (prAdapter->prP2pInfo) { + kalMemZero(prAdapter->prP2pInfo, + sizeof(struct P2P_INFO)); + } + } + + if (prWifiVar->prP2pDevFsmInfo == NULL) { + /* Don't only create P2P device for ucIdex 0. + * Avoid the exception that mtk_init_ap_role + * called without p2p0. + */ + prWifiVar->prP2pDevFsmInfo = + kalMemAlloc( + sizeof(struct P2P_DEV_FSM_INFO), + VIR_MEM_TYPE); + if (prWifiVar->prP2pDevFsmInfo) { + kalMemZero(prWifiVar->prP2pDevFsmInfo, + sizeof(struct + P2P_DEV_FSM_INFO)); + } + } + + prWifiVar->prP2PConnSettings[ucIdex] = + kalMemAlloc( + sizeof(struct P2P_CONNECTION_SETTINGS), + VIR_MEM_TYPE); + prWifiVar->prP2pSpecificBssInfo[ucIdex] = + kalMemAlloc( + sizeof(struct P2P_SPECIFIC_BSS_INFO), + VIR_MEM_TYPE); +#if CFG_ENABLE_PER_STA_STATISTICS_LOG + prWifiVar->prP2pQueryStaStatistics[ucIdex] = + kalMemAlloc( + sizeof(struct PARAM_GET_STA_STATISTICS), + VIR_MEM_TYPE); +#endif + /* TODO: It can be moved + * to the interface been created. + */ +#if 0 + for (u4Idx = 0; u4Idx < BSS_P2P_NUM; u4Idx++) { + prWifiVar->aprP2pRoleFsmInfo[u4Idx] = + kalMemAlloc(sizeof(struct P2P_ROLE_FSM_INFO), + VIR_MEM_TYPE); + } +#endif + } else { + ASSERT(prAdapter->prP2pInfo != NULL); + ASSERT(prWifiVar->prP2PConnSettings[ucIdex] != NULL); + /* ASSERT(prWifiVar->prP2pFsmInfo != NULL); */ + ASSERT(prWifiVar->prP2pSpecificBssInfo[ucIdex] != NULL); + } + /*MUST set memory to 0 */ + kalMemZero(prGlueInfo->prP2PInfo[ucIdex], + sizeof(struct GL_P2P_INFO)); + kalMemZero(prWifiVar->prP2PConnSettings[ucIdex], + sizeof(struct P2P_CONNECTION_SETTINGS)); +/* kalMemZero(prWifiVar->prP2pFsmInfo, sizeof(P2P_FSM_INFO_T)); */ + kalMemZero(prWifiVar->prP2pSpecificBssInfo[ucIdex], + sizeof(struct P2P_SPECIFIC_BSS_INFO)); +#if CFG_ENABLE_PER_STA_STATISTICS_LOG + if (prWifiVar->prP2pQueryStaStatistics[ucIdex]) + kalMemZero(prWifiVar->prP2pQueryStaStatistics[ucIdex], + sizeof(struct PARAM_GET_STA_STATISTICS)); +#endif + } while (FALSE); + + if (!prGlueInfo->prP2PDevInfo) + DBGLOG(P2P, ERROR, "prP2PDevInfo error\n"); + else + DBGLOG(P2P, TRACE, "prP2PDevInfo ok\n"); + + if (!prGlueInfo->prP2PInfo[ucIdex]) + DBGLOG(P2P, ERROR, "prP2PInfo error\n"); + else + DBGLOG(P2P, TRACE, "prP2PInfo ok\n"); + + + + /* chk if alloc successful or not */ + if (prGlueInfo->prP2PInfo[ucIdex] && + prGlueInfo->prP2PDevInfo && + prAdapter->prP2pInfo && + prWifiVar->prP2PConnSettings[ucIdex] && +/* prWifiVar->prP2pFsmInfo && */ + prWifiVar->prP2pSpecificBssInfo[ucIdex]) + return TRUE; + + + DBGLOG(P2P, ERROR, "[fail!]p2PAllocInfo :fail\n"); + + if (prWifiVar->prP2pSpecificBssInfo[ucIdex]) { + kalMemFree(prWifiVar->prP2pSpecificBssInfo[ucIdex], + VIR_MEM_TYPE, + sizeof(struct P2P_SPECIFIC_BSS_INFO)); + + prWifiVar->prP2pSpecificBssInfo[ucIdex] = NULL; + } + +#if CFG_ENABLE_PER_STA_STATISTICS_LOG + if (prWifiVar->prP2pQueryStaStatistics[ucIdex]) { + kalMemFree(prWifiVar->prP2pQueryStaStatistics[ucIdex], + VIR_MEM_TYPE, + sizeof(struct PARAM_GET_STA_STATISTICS)); + prWifiVar->prP2pQueryStaStatistics[ucIdex] = NULL; + } +#endif + +/* if (prWifiVar->prP2pFsmInfo) { */ +/* kalMemFree(prWifiVar->prP2pFsmInfo, + * VIR_MEM_TYPE, sizeof(P2P_FSM_INFO_T)); + */ + +/* prWifiVar->prP2pFsmInfo = NULL; */ +/* } */ + if (prWifiVar->prP2PConnSettings[ucIdex]) { + kalMemFree(prWifiVar->prP2PConnSettings[ucIdex], + VIR_MEM_TYPE, sizeof(struct P2P_CONNECTION_SETTINGS)); + + prWifiVar->prP2PConnSettings[ucIdex] = NULL; + } + if (prGlueInfo->prP2PDevInfo) { + kalMemFree(prGlueInfo->prP2PDevInfo, + VIR_MEM_TYPE, sizeof(struct GL_P2P_DEV_INFO)); + + prGlueInfo->prP2PDevInfo = NULL; + } + if (prGlueInfo->prP2PInfo[ucIdex]) { + kalMemFree(prGlueInfo->prP2PInfo[ucIdex], + VIR_MEM_TYPE, sizeof(struct GL_P2P_INFO)); + + prGlueInfo->prP2PInfo[ucIdex] = NULL; + } + if (prAdapter->prP2pInfo) { + kalMemFree(prAdapter->prP2pInfo, + VIR_MEM_TYPE, sizeof(struct P2P_INFO)); + + 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 + * [in] ucIdx The BSS with the idx will be freed. + * "ucIdx == 0xff" will free all BSSs. + * Only has meaning for "CFG_ENABLE_UNIFY_WIPHY == 1" + * + * \return TRUE + * FALSE + */ +/*---------------------------------------------------------------------------*/ +u_int8_t p2PFreeInfo(struct GLUE_INFO *prGlueInfo, uint8_t ucIdx) +{ + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + + ASSERT(prGlueInfo); + ASSERT(prAdapter); + + if (ucIdx >= KAL_P2P_NUM) { + DBGLOG(P2P, ERROR, "ucIdx=%d is invalid\n", ucIdx); + return FALSE; + } + + /* Expect that prAdapter->prP2pInfo must be existing. */ + if (prAdapter->prP2pInfo == NULL) { + DBGLOG(P2P, ERROR, "prAdapter->prP2pInfo is NULL\n"); + return FALSE; + } + + /* TODO: how can I sure that the specific P2P device can be freed? + * The original check is that prGlueInfo->prAdapter->fgIsP2PRegistered. + * For one wiphy feature, this func may be called without + * (fgIsP2PRegistered == FALSE) condition. + */ + + if (prGlueInfo->prP2PInfo[ucIdx] != NULL) { + kalMemFree(prAdapter->rWifiVar.prP2PConnSettings[ucIdx], + VIR_MEM_TYPE, + sizeof(struct P2P_CONNECTION_SETTINGS)); + prAdapter->rWifiVar.prP2PConnSettings[ucIdx] = NULL; + + kalMemFree(prAdapter->rWifiVar.prP2pSpecificBssInfo[ucIdx], + VIR_MEM_TYPE, + sizeof(struct P2P_SPECIFIC_BSS_INFO)); + prAdapter->rWifiVar.prP2pSpecificBssInfo[ucIdx] = NULL; + +#if CFG_ENABLE_PER_STA_STATISTICS_LOG + kalMemFree(prAdapter->rWifiVar.prP2pQueryStaStatistics[ucIdx], + VIR_MEM_TYPE, + sizeof(struct PARAM_GET_STA_STATISTICS)); + prAdapter->rWifiVar.prP2pQueryStaStatistics[ucIdx] = NULL; +#endif + +#if (CFG_SUPPORT_DFS_MASTER == 1) + if (prGlueInfo->prP2PInfo[ucIdx]->chandef) { + if (prGlueInfo->prP2PInfo[ucIdx]->chandef->chan) { + cnmMemFree(prGlueInfo->prAdapter, + prGlueInfo->prP2PInfo[ucIdx] + ->chandef->chan); + prGlueInfo->prP2PInfo[ucIdx] + ->chandef->chan = NULL; + } + cnmMemFree(prGlueInfo->prAdapter, + prGlueInfo->prP2PInfo[ucIdx]->chandef); + prGlueInfo->prP2PInfo[ucIdx]->chandef = NULL; + } +#endif + kalMemFree(prGlueInfo->prP2PInfo[ucIdx], + VIR_MEM_TYPE, + sizeof(struct GL_P2P_INFO)); + prGlueInfo->prP2PInfo[ucIdx] = NULL; + + prAdapter->prP2pInfo->u4DeviceNum--; + } + + if (prAdapter->prP2pInfo->u4DeviceNum == 0) { + /* all prP2PInfo are freed, and free the general part now */ + + kalMemFree(prAdapter->prP2pInfo, VIR_MEM_TYPE, + sizeof(struct P2P_INFO)); + prAdapter->prP2pInfo = NULL; + + if (prGlueInfo->prP2PDevInfo) { + kalMemFree(prGlueInfo->prP2PDevInfo, VIR_MEM_TYPE, + sizeof(struct GL_P2P_DEV_INFO)); + prGlueInfo->prP2PDevInfo = NULL; + } + if (prAdapter->rWifiVar.prP2pDevFsmInfo) { + kalMemFree(prAdapter->rWifiVar.prP2pDevFsmInfo, + VIR_MEM_TYPE, sizeof(struct P2P_DEV_FSM_INFO)); + prAdapter->rWifiVar.prP2pDevFsmInfo = NULL; + } + + /* Reomve p2p bss scan list */ + scanRemoveAllP2pBssDesc(prAdapter); + } + + return TRUE; +} + +u_int8_t p2pNetRegister(struct GLUE_INFO *prGlueInfo, + u_int8_t fgIsRtnlLockAcquired) +{ + u_int8_t fgDoRegister = FALSE; + u_int8_t fgRollbackRtnlLock = FALSE; + u_int8_t 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(); + } + + /* net device initialize */ + netif_carrier_off(prGlueInfo->prP2PInfo[0]->prDevHandler); + netif_tx_stop_all_queues(prGlueInfo->prP2PInfo[0]->prDevHandler); + + /* register for net device */ + if (register_netdev(prGlueInfo->prP2PInfo[0]->prDevHandler) < 0) { + DBGLOG(INIT, WARN, "unable to register netdevice for p2p\n"); + /* free dev in glUnregisterP2P() */ + /* free_netdev(prGlueInfo->prP2PInfo[0]->prDevHandler); */ + ret = FALSE; + } else { + prGlueInfo->prAdapter->rP2PNetRegState = + ENUM_NET_REG_STATE_REGISTERED; + gPrP2pDev[0] = prGlueInfo->prP2PInfo[0]->prDevHandler; + ret = TRUE; + } + + if (prGlueInfo->prAdapter->prP2pInfo->u4DeviceNum == KAL_P2P_NUM) { + /* net device initialize */ + netif_carrier_off(prGlueInfo->prP2PInfo[1]->prDevHandler); + netif_tx_stop_all_queues( + prGlueInfo->prP2PInfo[1]->prDevHandler); + + /* register for net device */ + if (register_netdev( + prGlueInfo->prP2PInfo[1]->prDevHandler) < 0) { + + DBGLOG(INIT, WARN, + "unable to register netdevice for p2p\n"); + + free_netdev(prGlueInfo->prP2PInfo[1]->prDevHandler); + + ret = FALSE; + } else { + prGlueInfo->prAdapter->rP2PNetRegState = + ENUM_NET_REG_STATE_REGISTERED; + gPrP2pDev[1] = prGlueInfo->prP2PInfo[1]->prDevHandler; + ret = TRUE; + } + + + DBGLOG(P2P, INFO, "P2P 2nd interface work\n"); + } + if (fgRollbackRtnlLock) + rtnl_lock(); + + return ret; +} + +u_int8_t p2pNetUnregister(struct GLUE_INFO *prGlueInfo, + u_int8_t fgIsRtnlLockAcquired) +{ + u_int8_t fgDoUnregister = FALSE; + u_int8_t fgRollbackRtnlLock = FALSE; + uint8_t ucRoleIdx; + struct ADAPTER *prAdapter = NULL; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPriv = NULL; + struct GL_P2P_INFO *prP2PInfo = NULL; + struct BSS_INFO *prP2pBssInfo = NULL; + int iftype = 0; + struct net_device *prRoleDev = NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + prAdapter = prGlueInfo->prAdapter; + + ASSERT(prGlueInfo); + ASSERT(prAdapter); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if (prAdapter->rP2PNetRegState == ENUM_NET_REG_STATE_REGISTERED) { + prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_UNREGISTERING; + fgDoUnregister = TRUE; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + if (!fgDoUnregister) + return TRUE; + + if (fgIsRtnlLockAcquired && rtnl_is_locked()) + fgRollbackRtnlLock = TRUE; + + for (ucRoleIdx = 0; ucRoleIdx < KAL_P2P_NUM; ucRoleIdx++) { + prP2PInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + if (prP2PInfo == NULL) + continue; + +#if CFG_ENABLE_UNIFY_WIPHY + /* don't unregister the dev that share with the AIS */ + if (prP2PInfo->prDevHandler == gprWdev->netdev) + continue; +#endif + + prRoleDev = prP2PInfo->aprRoleHandler; + if (prRoleDev != NULL) { + /* info cfg80211 disconnect */ + prNetDevPriv = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prRoleDev); + iftype = prRoleDev->ieee80211_ptr->iftype; + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prNetDevPriv->ucBssIdx); + + /* FIXME: The p2pRoleFsmUninit may call the + * cfg80211_disconnected. + * p2pRemove()->glUnregisterP2P->p2pRoleFsmUninit(), + * it may be too late. + */ + if ((prP2pBssInfo != NULL) && + (prP2pBssInfo->eConnectionState == + PARAM_MEDIA_STATE_CONNECTED) && + ((iftype == NL80211_IFTYPE_P2P_CLIENT) || + (iftype == NL80211_IFTYPE_STATION))) { +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 2, 0) <= CFG80211_VERSION_CODE) + cfg80211_disconnected(prRoleDev, 0, NULL, 0, + TRUE, GFP_KERNEL); +#else + cfg80211_disconnected(prRoleDev, 0, NULL, 0, + GFP_KERNEL); +#endif + } + + if (prRoleDev != prP2PInfo->prDevHandler) { + if (netif_carrier_ok(prRoleDev)) + netif_carrier_off(prRoleDev); + + netif_tx_stop_all_queues(prRoleDev); + } + } + + if (netif_carrier_ok(prP2PInfo->prDevHandler)) + netif_carrier_off(prP2PInfo->prDevHandler); + + netif_tx_stop_all_queues(prP2PInfo->prDevHandler); + + if (fgRollbackRtnlLock) + rtnl_unlock(); + + /* Here are the functions which need rtnl_lock */ + if ((prRoleDev) && (prP2PInfo->prDevHandler != prRoleDev)) { + DBGLOG(INIT, INFO, "unregister p2p[%d]\n", ucRoleIdx); + unregister_netdev(prRoleDev); + + /* This ndev is created in mtk_p2p_cfg80211_add_iface(), + * and unregister_netdev will also free the ndev. + */ + } + + DBGLOG(INIT, INFO, "unregister p2pdev[%d]\n", ucRoleIdx); + unregister_netdev(prP2PInfo->prDevHandler); + + if (fgRollbackRtnlLock) + rtnl_lock(); + } + + prGlueInfo->prAdapter->rP2PNetRegState = + ENUM_NET_REG_STATE_UNREGISTERED; + + return TRUE; +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief Setup the P2P device information + * + * \param[in] prGlueInfo Pointer to glue info + * [in] prP2pWdev Pointer to the wireless device + * [in] prP2pDev Pointer to the net device + * [in] u4Idx The P2P Role index (max : (KAL_P2P_NUM-1)) + * [in] fgIsApMode Indicate that this device is AP Role or not + * + * \return 0 Success + * -1 Failure + */ +/*---------------------------------------------------------------------------*/ +int glSetupP2P(struct GLUE_INFO *prGlueInfo, struct wireless_dev *prP2pWdev, + struct net_device *prP2pDev, int u4Idx, u_int8_t fgIsApMode) +{ + struct ADAPTER *prAdapter = NULL; + struct GL_P2P_INFO *prP2PInfo = NULL; + struct GL_HIF_INFO *prHif = NULL; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPriv = NULL; + struct mt66xx_chip_info *prChipInfo = NULL; + + DBGLOG(INIT, INFO, "setup the p2p dev\n"); + + if ((prGlueInfo == NULL) || + (prP2pWdev == NULL) || + (prP2pWdev->wiphy == NULL) || + (prP2pDev == NULL)) { + DBGLOG(INIT, ERROR, "parameter is NULL!!\n"); + return -1; + } + + prHif = &prGlueInfo->rHifInfo; + prAdapter = prGlueInfo->prAdapter; + + if ((prAdapter == NULL) || + (prHif == NULL)) { + DBGLOG(INIT, ERROR, "prAdapter/prHif is NULL!!\n"); + return -1; + } + + /* FIXME: check KAL_P2P_NUM in trunk? */ + if (u4Idx >= KAL_P2P_NUM) { + DBGLOG(INIT, ERROR, "u4Idx(%d) is out of range!!\n", u4Idx); + return -1; + } + + prChipInfo = prAdapter->chip_info; + + /*0. allocate p2pinfo */ + if (p2PAllocInfo(prGlueInfo, u4Idx) != TRUE) { + DBGLOG(INIT, WARN, "Allocate memory for p2p FAILED\n"); + ASSERT(0); + return -1; + } + + prP2PInfo = prGlueInfo->prP2PInfo[u4Idx]; + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + /* fill wiphy parameters */ + + prP2PInfo->prWdev = prP2pWdev; + + if (!prAdapter->fgEnable5GBand) + prP2pWdev->wiphy->bands[BAND_5G] = NULL; + +#endif /* CFG_ENABLE_WIFI_DIRECT_CFG_80211 */ + + /* setup netdev */ + /* Point to shared glue structure */ + prNetDevPriv = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prP2pDev); + prNetDevPriv->prGlueInfo = prGlueInfo; + + /* set ucIsP2p for P2P function device */ + if (fgIsApMode == TRUE) { + prP2pWdev->iftype = NL80211_IFTYPE_AP; +#if CFG_ENABLE_UNIFY_WIPHY + prNetDevPriv->ucIsP2p = FALSE; +#endif + } else { + prP2pWdev->iftype = NL80211_IFTYPE_P2P_CLIENT; +#if CFG_ENABLE_UNIFY_WIPHY + prNetDevPriv->ucIsP2p = TRUE; +#endif + } + + /* register callback functions */ + prP2pDev->needed_headroom += + NIC_TX_DESC_AND_PADDING_LENGTH + prChipInfo->txd_append_size; + prP2pDev->netdev_ops = &p2p_netdev_ops; +#ifdef CONFIG_WIRELESS_EXT + prP2pDev->wireless_handlers = &wext_handler_def; +#endif + +#if defined(_HIF_SDIO) +#if (MTK_WCN_HIF_SDIO == 0) + SET_NETDEV_DEV(prP2pDev, &(prHif->func->dev)); +#endif +#endif + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + prP2pDev->ieee80211_ptr = prP2pWdev; + prP2pWdev->netdev = prP2pDev; +#endif + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + /* set HW checksum offload */ + if (prAdapter->fgIsSupportCsumOffload) { + prP2pDev->features = NETIF_F_IP_CSUM | + NETIF_F_IPV6_CSUM | + NETIF_F_RXCSUM; + } +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + kalResetStats(prP2pDev); + + /* finish */ + /* bind netdev pointer to netdev index */ + prP2PInfo->prDevHandler = prP2pDev; + + /* XXX: All the P2P/AP devices do p2pDevFsmInit in the original code */ + wlanBindBssIdxToNetInterface(prGlueInfo, p2pDevFsmInit(prAdapter), + (void *) prP2PInfo->prDevHandler); + + prP2PInfo->aprRoleHandler = prP2PInfo->prDevHandler; + + DBGLOG(P2P, INFO, + "check prDevHandler = %p, aprRoleHandler = %p\n", + prP2PInfo->prDevHandler, prP2PInfo->aprRoleHandler); + + prNetDevPriv->ucBssIdx = p2pRoleFsmInit(prAdapter, u4Idx); + /* Currently wpasupplicant can't support create interface. */ + /* so initial the corresponding data structure here. */ + wlanBindBssIdxToNetInterface(prGlueInfo, prNetDevPriv->ucBssIdx, + (void *) prP2PInfo->aprRoleHandler); + + /* bind netdev pointer to netdev index */ +#if 0 + wlanBindNetInterface(prGlueInfo, NET_DEV_P2P_IDX, + (void *)prGlueInfo->prP2PInfo->prDevHandler); +#endif + + /* setup running mode */ + p2pFuncInitConnectionSettings(prAdapter, + prAdapter->rWifiVar.prP2PConnSettings[u4Idx], fgIsApMode); + + return 0; +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief Register for cfg80211 for Wi-Fi Direct + * + * \param[in] prGlueInfo Pointer to glue info + * + * \return TRUE + * FALSE + */ +/*---------------------------------------------------------------------------*/ +u_int8_t glRegisterP2P(struct GLUE_INFO *prGlueInfo, const char *prDevName, + const char *prDevName2, uint8_t ucApMode) +{ + struct ADAPTER *prAdapter = NULL; + uint8_t rMacAddr[PARAM_MAC_ADDR_LEN]; + u_int8_t fgIsApMode = FALSE; + uint8_t ucRegisterNum = 1, i = 0; + struct wireless_dev *prP2pWdev = NULL; + struct net_device *prP2pDev = NULL; + struct wiphy *prWiphy = NULL; + const char *prSetDevName; +#if (CFG_ENABLE_UNIFY_WIPHY == 0) + struct GL_HIF_INFO *prHif = NULL; + struct device *prDev; +#endif + + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + if ((ucApMode == RUNNING_DUAL_AP_MODE) || + (ucApMode == RUNNING_P2P_AP_MODE)) { + ucRegisterNum = 2; + glP2pCreateWirelessDevice(prGlueInfo); + } + + do { + if (ucApMode == RUNNING_P2P_AP_MODE) { + if (i == 0) { + prSetDevName = prDevName; + fgIsApMode = FALSE; + } else { + prSetDevName = prDevName2; + fgIsApMode = TRUE; + } + } else { + /* RUNNING_AP_MODE + * RUNNING_DUAL_AP_MODE + * RUNNING_P2P_MODE + */ + prSetDevName = prDevName; + + if (ucApMode == RUNNING_P2P_MODE) + fgIsApMode = FALSE; + else + fgIsApMode = TRUE; + } + + if (!gprP2pRoleWdev[i]) { + DBGLOG(P2P, ERROR, "gprP2pRoleWdev[%d] is NULL\n", i); + return FALSE; + } + + prP2pWdev = gprP2pRoleWdev[i]; + DBGLOG(INIT, INFO, "glRegisterP2P(%d)\n", i); + + /* Reset prP2pWdev for the issue that the prP2pWdev doesn't + * reset when the usb unplug/plug. + */ + prWiphy = prP2pWdev->wiphy; + memset(prP2pWdev, 0, sizeof(struct wireless_dev)); + prP2pWdev->wiphy = prWiphy; + + /* allocate netdev */ +#if KERNEL_VERSION(3, 17, 0) <= CFG80211_VERSION_CODE + prP2pDev = alloc_netdev_mq( + sizeof(struct NETDEV_PRIVATE_GLUE_INFO), + prSetDevName, NET_NAME_PREDICTABLE, + ether_setup, CFG_MAX_TXQ_NUM); +#else + prP2pDev = alloc_netdev_mq( + sizeof(struct NETDEV_PRIVATE_GLUE_INFO), + prSetDevName, + ether_setup, CFG_MAX_TXQ_NUM); +#endif + if (!prP2pDev) { + DBGLOG(INIT, WARN, "unable to allocate ndev for p2p\n"); + goto err_alloc_netdev; + } + + /* fill hardware address */ + COPY_MAC_ADDR(rMacAddr, prAdapter->rMyMacAddr); + rMacAddr[0] |= 0x2; + /* change to local administrated address */ + rMacAddr[0] ^= i << 2; + kalMemCopy(prP2pDev->dev_addr, rMacAddr, ETH_ALEN); + kalMemCopy(prP2pDev->perm_addr, prP2pDev->dev_addr, ETH_ALEN); + + if (glSetupP2P(prGlueInfo, prP2pWdev, prP2pDev, i, fgIsApMode) + != 0) { + DBGLOG(INIT, WARN, "glSetupP2P FAILED\n"); + free_netdev(prP2pDev); + return FALSE; + } + +#if (CFG_ENABLE_UNIFY_WIPHY == 0) + prHif = &prGlueInfo->rHifInfo; + glGetHifDev(prHif, &prDev); + if (!prDev) + DBGLOG(INIT, ERROR, "P2P[%d] parent dev is NULL\n", i); + set_wiphy_dev(prWiphy, prDev); +#endif + + i++; + /* prP2pInfo is alloc at glSetupP2P()->p2PAllocInfo() */ + prAdapter->prP2pInfo->u4DeviceNum++; + + /* set p2p net device register state */ + /* p2pNetRegister() will check prAdapter->rP2PNetRegState. */ + prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_UNREGISTERED; + } while (i < ucRegisterNum); + + return TRUE; +#if 0 +err_reg_netdev: + free_netdev(prGlueInfo->prP2PInfo->prDevHandler); +#endif +err_alloc_netdev: + return FALSE; +} /* end of glRegisterP2P() */ + +#if CFG_ENABLE_UNIFY_WIPHY +u_int8_t glP2pCreateWirelessDevice(struct GLUE_INFO *prGlueInfo) +{ + struct wiphy *prWiphy = gprWdev->wiphy; + struct wireless_dev *prWdev = NULL; + uint8_t i = 0; + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + if (!prWiphy) { + DBGLOG(P2P, ERROR, "unable to allocate wiphy for p2p\n"); + return FALSE; + } + + for (i = 0 ; i < KAL_P2P_NUM; i++) { + if (!gprP2pRoleWdev[i]) + break; + } + + if (i >= KAL_P2P_NUM) { + DBGLOG(INIT, WARN, "fail to register wiphy to driver\n"); + return FALSE; + } + + prWdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (!prWdev) { + DBGLOG(P2P, ERROR, "allocate p2p wdev fail, no memory\n"); + return FALSE; + } + + /* set priv as pointer to glue structure */ + prWdev->wiphy = prWiphy; + + gprP2pRoleWdev[i] = prWdev; + DBGLOG(INIT, INFO, "glP2pCreateWirelessDevice (%p)\n", + gprP2pRoleWdev[i]->wiphy); + + return TRUE; +#else + return FALSE; +#endif +} +#else /* (CFG_ENABLE_UNIFY_WIPHY == 0) */ +u_int8_t glP2pCreateWirelessDevice(struct GLUE_INFO *prGlueInfo) +{ + struct wiphy *prWiphy = NULL; + struct wireless_dev *prWdev = NULL; + uint8_t i = 0; +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + prWdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (!prWdev) { + DBGLOG(P2P, ERROR, + "allocate p2p wireless device fail, no memory\n"); + return FALSE; + } + /* 1. allocate WIPHY */ + prWiphy = wiphy_new(&mtk_p2p_ops, sizeof(struct GLUE_INFO *)); + if (!prWiphy) { + DBGLOG(P2P, ERROR, "unable to allocate wiphy for p2p\n"); + goto free_wdev; + } + + prWiphy->interface_modes = BIT(NL80211_IFTYPE_AP) + | BIT(NL80211_IFTYPE_P2P_CLIENT) + | BIT(NL80211_IFTYPE_P2P_GO) + | BIT(NL80211_IFTYPE_STATION); + + prWiphy->software_iftypes |= BIT(NL80211_IFTYPE_P2P_DEVICE); + + prWiphy->iface_combinations = p_mtk_iface_combinations_p2p; + prWiphy->n_iface_combinations = mtk_iface_combinations_p2p_num; + + prWiphy->bands[KAL_BAND_2GHZ] = &mtk_band_2ghz; + prWiphy->bands[KAL_BAND_5GHZ] = &mtk_band_5ghz; + + prWiphy->mgmt_stypes = mtk_cfg80211_default_mgmt_stypes; + prWiphy->max_remain_on_channel_duration = 5000; + prWiphy->n_cipher_suites = 5; + prWiphy->cipher_suites = mtk_cipher_suites; +#if KERNEL_VERSION(3, 14, 0) > CFG80211_VERSION_CODE + prWiphy->flags = WIPHY_FLAG_CUSTOM_REGULATORY + | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL + | WIPHY_FLAG_HAVE_AP_SME; +#else +#if (CFG_SUPPORT_DFS_MASTER == 1) + prWiphy->flags = WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL + | WIPHY_FLAG_HAVE_AP_SME + | WIPHY_FLAG_HAS_CHANNEL_SWITCH; + prWiphy->max_num_csa_counters = 2; +#else + prWiphy->flags = WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL + | WIPHY_FLAG_HAVE_AP_SME; +#endif + prWiphy->regulatory_flags = REGULATORY_CUSTOM_REG; +#endif + prWiphy->ap_sme_capa = 1; + + prWiphy->max_scan_ssids = MAX_SCAN_LIST_NUM; + prWiphy->max_scan_ie_len = MAX_SCAN_IE_LEN; + prWiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE + prWiphy->vendor_commands = mtk_p2p_vendor_ops; + prWiphy->n_vendor_commands = sizeof(mtk_p2p_vendor_ops) + / sizeof(struct wiphy_vendor_command); +#endif + +#ifdef CONFIG_PM +#if KERNEL_VERSION(3, 9, 0) > CFG80211_VERSION_CODE + prWiphy->wowlan = &mtk_p2p_wowlan_support; +#endif +#endif + + cfg80211_regd_set_wiphy(prWiphy); + + /* 2.1 set priv as pointer to glue structure */ + *((struct GLUE_INFO **) wiphy_priv(prWiphy)) = prGlueInfo; + /* Here are functions which need rtnl_lock */ + if (wiphy_register(prWiphy) < 0) { + DBGLOG(INIT, WARN, "fail to register wiphy for p2p\n"); + goto free_wiphy; + } + prWdev->wiphy = prWiphy; + + for (i = 0 ; i < KAL_P2P_NUM; i++) { + if (!gprP2pRoleWdev[i]) { + gprP2pRoleWdev[i] = prWdev; + DBGLOG(INIT, INFO, + "glP2pCreateWirelessDevice (%x)\n", + gprP2pRoleWdev[i]->wiphy); + break; + } + } + + if (i == KAL_P2P_NUM) + DBGLOG(INIT, WARN, "fail to register wiphy to driver\n"); + + return TRUE; + +free_wiphy: + wiphy_free(prWiphy); +free_wdev: + kfree(prWdev); +#endif + return FALSE; +} +#endif /* CFG_ENABLE_UNIFY_WIPHY */ + +/*---------------------------------------------------------------------------*/ +/*! + * \brief Unregister Net Device for Wi-Fi Direct + * + * \param[in] prGlueInfo Pointer to glue info + * [in] ucIdx The BSS with the idx will be freed. + * "ucIdx == 0xff" will free all BSSs. + * Only has meaning for "CFG_ENABLE_UNIFY_WIPHY == 1" + * + * \return TRUE + * FALSE + */ +/*---------------------------------------------------------------------------*/ +u_int8_t glUnregisterP2P(struct GLUE_INFO *prGlueInfo, uint8_t ucIdx) +{ + uint8_t ucRoleIdx; + struct ADAPTER *prAdapter; + struct GL_P2P_INFO *prP2PInfo = NULL; + int i4Start = 0, i4End = 0; + + ASSERT(prGlueInfo); + + if (ucIdx == 0xff) { + i4Start = 0; + i4End = BSS_P2P_NUM; + } else if (ucIdx < BSS_P2P_NUM) { + i4Start = ucIdx; + i4End = ucIdx + 1; + } else { + DBGLOG(INIT, WARN, "The ucIdx (%d) is a wrong value\n", ucIdx); + return FALSE; + } + + prAdapter = prGlueInfo->prAdapter; + + /* 4 <1> Uninit P2P dev FSM */ + /* Uninit P2P device FSM */ + /* only do p2pDevFsmUninit, when unregister all P2P device */ + if (ucIdx == 0xff) + p2pDevFsmUninit(prAdapter); + + /* 4 <2> Uninit P2P role FSM */ + for (ucRoleIdx = i4Start; ucRoleIdx < i4End; ucRoleIdx++) { + if (P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, ucRoleIdx)) { + /* FIXME: The cfg80211_XXX() is following the + * p2pRoleFsmUninit() sub-progress. + * ex: The cfg80211_del_sta() is called in the + * kalP2PGOStationUpdate(). + * But the netdev had be unregistered at + * p2pNetUnregister(). EXCEPTION!! + */ + p2pRoleFsmUninit(prGlueInfo->prAdapter, ucRoleIdx); + } + } + + /* 4 <3> Free Wiphy & netdev */ + for (ucRoleIdx = i4Start; ucRoleIdx < i4End; ucRoleIdx++) { + prP2PInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + + if (prP2PInfo == NULL) + continue; + /* For P2P interfaces, prDevHandler points to the net_device of + * p2p0 interface. And aprRoleHandler points to the net_device + * of p2p virtual interface (i.e., p2p1) when it was created. + * And when p2p virtual interface is deleted, aprRoleHandler + * will change to point to prDevHandler. Hence, when + * aprRoleHandler & prDevHandler are pointing to different + * addresses, it means vif p2p1 exists. Otherwise it means p2p1 + * was already deleted. + */ + if ((prP2PInfo->aprRoleHandler != NULL) && + (prP2PInfo->aprRoleHandler != prP2PInfo->prDevHandler)) { + /* This device is added by the P2P, and use + * ndev->destructor to free. The p2pDevFsmUninit() use + * prP2PInfo->aprRoleHandler to do some check. + */ + prP2PInfo->aprRoleHandler = NULL; + DBGLOG(P2P, INFO, "aprRoleHandler idx %d set NULL\n", + ucRoleIdx); + + /* Expect that gprP2pRoleWdev[ucRoleIdx] has been reset + * as gprP2pWdev or NULL in p2pNetUnregister + * (unregister_netdev). + */ + } + + if (prP2PInfo->prDevHandler) { + /* don't free the dev that share with the AIS */ + if (prP2PInfo->prDevHandler == gprWdev->netdev) + gprP2pRoleWdev[ucRoleIdx] = NULL; + else + free_netdev(prP2PInfo->prDevHandler); + prP2PInfo->prDevHandler = NULL; + } + + /* 4 <4> Free P2P internal memory */ + if (!p2PFreeInfo(prGlueInfo, ucRoleIdx)) { + /* FALSE: (fgIsP2PRegistered!=FALSE)||(ucRoleIdx err) */ + DBGLOG(INIT, ERROR, "p2PFreeInfo FAILED\n"); + ASSERT(0); + return FALSE; + } + } + + return TRUE; +} /* end of glUnregisterP2P() */ + +/* 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 = *((struct GLUE_INFO **) 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, + (struct MSG_HDR *) prFuncSwitch, + MSG_SEND_METHOD_BUF); +#endif + + /* 2. carrier on & start TX queue */ + /*DFS todo 20161220_DFS*/ +#if (CFG_SUPPORT_DFS_MASTER == 1) + if (prDev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) { + /*netif_carrier_on(prDev);*/ + netif_tx_start_all_queues(prDev); + } +#else + /*netif_carrier_on(prDev);*/ + netif_tx_start_all_queues(prDev); +#endif + + 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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct GL_P2P_DEV_INFO *prP2pGlueDevInfo = NULL; +/* P_MSG_P2P_FUNCTION_SWITCH_T prFuncSwitch; */ + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prDev); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + /* XXX: The p2pStop may be triggered after the wlanRemove. */ + /* And prGlueInfo->prP2PDevInfo is freed in p2PFreeInfo. */ + if (!prAdapter->fgIsP2PRegistered) + return -EFAULT; + + prP2pGlueDevInfo = prGlueInfo->prP2PDevInfo; + ASSERT(prP2pGlueDevInfo); + + /* 0. Do the scan done and set parameter to abort if the scan pending */ + /*DBGLOG(INIT, INFO, "p2pStop and ucRoleIdx = %u\n", ucRoleIdx);*/ + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if ((prP2pGlueDevInfo->prScanRequest != NULL) && + (prP2pGlueDevInfo->prScanRequest->wdev == prDev->ieee80211_ptr)) { + DBGLOG(INIT, INFO, "p2pStop and abort scan!!\n"); + kalCfg80211ScanDone(prP2pGlueDevInfo->prScanRequest, TRUE); + prP2pGlueDevInfo->prScanRequest = NULL; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + /* 1. stop TX queue */ + netif_tx_stop_all_queues(prDev); +#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 */ + 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, + (struct MSG_HDR *) prFuncSwitch, + MSG_SEND_METHOD_BUF); +#endif + /* 3. stop queue and turn off carrier */ + /* TH3 multiple P2P */ + /*prGlueInfo->prP2PInfo[0]->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) +{ + return (struct net_device_stats *)kalGetStats(prDev); +} /* end of p2pGetStats() */ + +static void p2pSetMulticastList(IN struct net_device *prDev) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + + prGlueInfo = (prDev != NULL) + ? *((struct GLUE_INFO **) 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); + return; + } + + g_P2pPrDev = prDev; + + /* 4 Mark HALT, notify main thread to finish current job */ + set_bit(GLUE_FLAG_SUB_MOD_MULTICAST_BIT, &prGlueInfo->ulFlag); + /* 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(struct GLUE_INFO *prGlueInfo) +{ + uint32_t u4SetInfoLen = 0; + uint32_t u4McCount; + struct net_device *prDev = g_P2pPrDev; + + prGlueInfo = (prDev != NULL) + ? *((struct GLUE_INFO **) netdev_priv(prDev)) + : NULL; + + ASSERT(prDev); + ASSERT(prGlueInfo); + if (!prDev || !prGlueInfo || !prGlueInfo->prP2PDevInfo) { + DBGLOG(INIT, WARN, + " abnormal dev or skb: prDev(0x%p), prGlueInfo(0x%p)\n", + prDev, prGlueInfo); + return; + } + + if (prDev->flags & IFF_PROMISC) + prGlueInfo->prP2PDevInfo->u4PacketFilter + |= PARAM_PACKET_FILTER_PROMISCUOUS; + + if (prDev->flags & IFF_BROADCAST) + prGlueInfo->prP2PDevInfo->u4PacketFilter + |= PARAM_PACKET_FILTER_BROADCAST; + u4McCount = netdev_mc_count(prDev); + + if (prDev->flags & IFF_MULTICAST) { + if ((prDev->flags & IFF_ALLMULTI) + || (u4McCount > MAX_NUM_GROUP_ADDR)) + prGlueInfo->prP2PDevInfo->u4PacketFilter + |= PARAM_PACKET_FILTER_ALL_MULTICAST; + else + prGlueInfo->prP2PDevInfo->u4PacketFilter + |= PARAM_PACKET_FILTER_MULTICAST; + } + + if (prGlueInfo->prP2PDevInfo->u4PacketFilter + & PARAM_PACKET_FILTER_MULTICAST) { + /* Prepare multicast address list */ + struct netdev_hw_addr *ha; + uint32_t i = 0; + + /* Avoid race condition with kernel net subsystem */ + netif_addr_lock_bh(prDev); + + netdev_for_each_mc_addr(ha, prDev) { + /* If ha is null, it will break the loop. */ + /* Check mc count before accessing to ha to + * prevent from kernel crash. + */ + if (i == u4McCount || !ha) + break; + if (i < MAX_NUM_GROUP_ADDR) { + COPY_MAC_ADDR( + &(prGlueInfo->prP2PDevInfo + ->aucMCAddrList[i]), + GET_ADDR(ha)); + i++; + } + } + + netif_addr_unlock_bh(prDev); + + DBGLOG(P2P, TRACE, "SEt Multicast Address List\n"); + + if (i >= MAX_NUM_GROUP_ADDR) + return; + wlanoidSetP2PMulticastList(prGlueInfo->prAdapter, + &(prGlueInfo->prP2PDevInfo->aucMCAddrList[0]), + (i * ETH_ALEN), &u4SetInfoLen); + + } + +} /* 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) +{ + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = + (struct NETDEV_PRIVATE_GLUE_INFO *) NULL; + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t ucBssIndex; + struct BSS_INFO *prP2pBssInfo = NULL; + + ASSERT(prSkb); + ASSERT(prDev); + + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prDev); + prGlueInfo = prNetDevPrivate->prGlueInfo; + ucBssIndex = prNetDevPrivate->ucBssIdx; + + kalResetPacket(prGlueInfo, (void *) prSkb); + + kalHardStartXmit(prSkb, prDev, prGlueInfo, ucBssIndex); + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, ucBssIndex); + if ((prP2pBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) || + (prP2pBssInfo->rStaRecOfClientList.u4NumElem > 0)) + kalPerMonStart(prGlueInfo); + + return NETDEV_TX_OK; +} /* end of p2pHardStartXmit() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief A method of struct net_device, a primary SOCKET interface to configure + * the interface lively. Handle an ioctl call on one of our devices. + * Everything Linux ioctl specific is done here. + * Then we pass the contents + * of the ifr->data to the request message handler. + * + * \param[in] prDev Linux kernel netdevice + * + * \param[in] prIFReq Our private ioctl request structure, + * typed for the generic struct ifreq + * so we can use ptr to function + * + * \param[in] cmd Command ID + * + * \retval 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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int ret = 0; + /* char *prExtraBuf = NULL; */ + /* UINT_32 u4ExtraSize = 0; */ + /* struct iwreq *prIwReq = (struct iwreq *)prIfReq; */ + /* struct iw_request_info rIwReqInfo; */ + + ASSERT(prDev && prIfReq); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + if (!prGlueInfo) { + DBGLOG(P2P, ERROR, "prGlueInfo is NULL\n"); + return -EFAULT; + } + + if (prGlueInfo->u4ReadyFlag == 0) { + DBGLOG(P2P, ERROR, "Adapter is not ready\n"); + return -EINVAL; + } + + if (i4Cmd == SIOCGIWPRIV) { + ret = wext_support_ioctl(prDev, prIfReq, i4Cmd); + } else if ((i4Cmd >= SIOCIWFIRSTPRIV) && (i4Cmd < SIOCIWLASTPRIV)) { + /* 0x8BE0 ~ 0x8BFF, private ioctl region */ + ret = priv_support_ioctl(prDev, prIfReq, i4Cmd); + } else if (i4Cmd == SIOCDEVPRIVATE + 1) { +#ifdef CFG_ANDROID_AOSP_PRIV_CMD + ret = android_private_support_driver_cmd(prDev, prIfReq, i4Cmd); +#else + ret = priv_support_driver_cmd(prDev, prIfReq, i4Cmd); +#endif /* CFG_ANDROID_AOSP_PRIV_CMD */ + } else { + DBGLOG(INIT, WARN, "Unexpected ioctl command: 0x%04x\n", i4Cmd); + ret = -1; + } + +#if 0 + /* 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)) { + DBGLOG(INIT, 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: +#if 0 + ret = rP2PIwPrivHandler[i4Cmd - SIOCIWFIRSTPRIV](prDev, + &rIwReqInfo, + &(prIwReq->u), + (char *)&(prIwReq->u)); +#endif + 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; + } +#endif /* 0 */ + + return ret; +} /* end of p2pDoIOCTL() */ + + +/*---------------------------------------------------------------------------*/ +/*! + * \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) +{ + struct ADAPTER *prAdapter = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct sockaddr *sa = NULL; + struct BSS_INFO *prBssInfo = NULL; + struct BSS_INFO *prDevBssInfo = NULL; + uint8_t ucRoleIdx = 0, ucBssIdx = 0; + struct GL_P2P_INFO *prP2pInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + if (!prDev || !addr) { + DBGLOG(INIT, ERROR, "Set macaddr with ndev(%d) and addr(%d)\n", + (prDev == NULL) ? 0 : 1, (addr == NULL) ? 0 : 1); + return WLAN_STATUS_INVALID_DATA; + } + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prDev, &ucRoleIdx) != 0) { + DBGLOG(INIT, ERROR, "can't find the matched dev"); + return WLAN_STATUS_INVALID_DATA; + } + + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, + ucRoleIdx, &ucBssIdx) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "can't find the matched bss"); + return WLAN_STATUS_INVALID_DATA; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + if (!prBssInfo) { + DBGLOG(INIT, ERROR, "bss is not active\n"); + return WLAN_STATUS_INVALID_DATA; + } + + prDevBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + P2P_DEV_BSS_INDEX); + if (!prDevBssInfo) { + DBGLOG(INIT, ERROR, "dev bss is not active\n"); + return WLAN_STATUS_INVALID_DATA; + } + + prP2pInfo = prGlueInfo->prP2PInfo[0]; + if (!prP2pInfo) { + DBGLOG(INIT, ERROR, "p2p info is null\n"); + return WLAN_STATUS_INVALID_DATA; + } + + sa = (struct sockaddr *)addr; + + COPY_MAC_ADDR(prBssInfo->aucOwnMacAddr, sa->sa_data); + COPY_MAC_ADDR(prDev->dev_addr, sa->sa_data); + + if ((prP2pInfo->prDevHandler == prDev) + && mtk_IsP2PNetDevice(prGlueInfo, prDev)) { + COPY_MAC_ADDR(prAdapter->rWifiVar.aucDeviceAddress, + sa->sa_data); + COPY_MAC_ADDR(prDevBssInfo->aucOwnMacAddr, sa->sa_data); + DBGLOG(INIT, INFO, + "[%d][%d] Set random macaddr to " MACSTR ".\n", + ucBssIdx, + prDevBssInfo->ucBssIndex, + MAC2STR(prDevBssInfo->aucOwnMacAddr)); + } else { + DBGLOG(INIT, INFO, + "[%d] Set random macaddr to " MACSTR ".\n", + ucBssIdx, + MAC2STR(prBssInfo->aucOwnMacAddr)); + } + + return WLAN_STATUS_SUCCESS; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_p2p_cfg80211.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_p2p_cfg80211.c new file mode 100644 index 0000000000000..b945a9f0729cc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_p2p_cfg80211.c @@ -0,0 +1,4565 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 + ****************************************************************************** + */ + +#include "config.h" + +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#include +#include +#include +#include +#include + +#include "precomp.h" +#include "gl_cfg80211.h" +#include "gl_p2p_os.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 + ****************************************************************************** + */ + +#if CFG_ENABLE_UNIFY_WIPHY +#define P2P_WIPHY_PRIV(_wiphy, _priv) \ + (_priv = (struct GLUE_INFO *) wiphy_priv(_wiphy)) +#else +#define P2P_WIPHY_PRIV(_wiphy, _priv) \ + (_priv = *((struct GLUE_INFO **) wiphy_priv(_wiphy))) +#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 + ****************************************************************************** + */ + +u_int8_t +mtk_p2p_cfg80211func_channel_sco_switch( + IN enum nl80211_channel_type channel_type, + IN enum ENUM_CHNL_EXT *prChnlSco) +{ + u_int8_t fgIsValid = FALSE; + + do { + 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; +} + +u_int8_t +mtk_p2p_cfg80211func_channel_format_switch( + IN struct cfg80211_chan_def *channel_def, + IN struct ieee80211_channel *channel, + IN struct RF_CHANNEL_INFO *prRfChnlInfo) +{ + u_int8_t fgIsValid = FALSE; + + do { + if (channel == NULL) + break; + + DBGLOG(P2P, INFO, + "switch channel band: %d, freq: %d\n", + channel->band, channel->center_freq); + + if (prRfChnlInfo) { + prRfChnlInfo->ucChannelNum = + nicFreq2ChannelNum(channel->center_freq * 1000); + + switch (channel->band) { + case KAL_BAND_2GHZ: + prRfChnlInfo->eBand = BAND_2G4; + break; + case KAL_BAND_5GHZ: + prRfChnlInfo->eBand = BAND_5G; + break; + default: + prRfChnlInfo->eBand = BAND_2G4; + break; + } + + } + + if (channel_def && prRfChnlInfo) { + + switch (channel_def->width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + prRfChnlInfo->ucChnlBw = MAX_BW_20MHZ; + break; + case NL80211_CHAN_WIDTH_40: + prRfChnlInfo->ucChnlBw = MAX_BW_40MHZ; + break; + case NL80211_CHAN_WIDTH_80: + prRfChnlInfo->ucChnlBw = MAX_BW_80MHZ; + break; + case NL80211_CHAN_WIDTH_80P80: + prRfChnlInfo->ucChnlBw = MAX_BW_80_80_MHZ; + break; + case NL80211_CHAN_WIDTH_160: + prRfChnlInfo->ucChnlBw = MAX_BW_160MHZ; + break; + default: + prRfChnlInfo->ucChnlBw = MAX_BW_20MHZ; + break; + } + prRfChnlInfo->u2PriChnlFreq = channel->center_freq; + prRfChnlInfo->u4CenterFreq1 = channel_def->center_freq1; + prRfChnlInfo->u4CenterFreq2 = channel_def->center_freq2; + } + + fgIsValid = TRUE; + + } while (FALSE); + + return fgIsValid; +} + +/* mtk_p2p_cfg80211func_channel_format_switch */ + +int32_t mtk_Netdev_To_RoleIdx(struct GLUE_INFO *prGlueInfo, + struct net_device *ndev, uint8_t *pucRoleIdx) +{ + int32_t i4Ret = -1; + uint32_t u4Idx = 0; + + if ((pucRoleIdx == NULL) || (ndev == NULL)) + return i4Ret; +#if 0 + for (u4Idx = 0; u4Idx < KAL_P2P_NUM; u4Idx++) { + if (prGlP2pInfo->aprRoleHandler[u4Idx] == ndev) { + *pucRoleIdx = (uint8_t) u4Idx; + i4Ret = 0; + } + } +#if 1 + i4Ret = 0; + *pucRoleIdx = 0; +#endif +#else + /* The prP2PInfo[0] may be removed and prP2PInfo[1] is existing + * under cfg80211 operation. So that check all KAL_P2P_NUM not only + * prGlueInfo->prAdapter->prP2pInfo->u4DeviceNum. + */ + for (u4Idx = 0; u4Idx < KAL_P2P_NUM; u4Idx++) { + if ((prGlueInfo->prP2PInfo[u4Idx] != NULL) && + (prGlueInfo->prP2PInfo[u4Idx]->aprRoleHandler != NULL) && + (prGlueInfo->prP2PInfo[u4Idx]->aprRoleHandler == ndev)) { + *pucRoleIdx = (uint8_t) u4Idx; + i4Ret = 0; + } + } +#endif + + return i4Ret; + +} /* mtk_Netdev_To_RoleIdx */ + +static void mtk_vif_destructor(struct net_device *dev) +{ + struct wireless_dev *prWdev = ERR_PTR(-ENOMEM); + uint32_t u4Idx = 0; + + DBGLOG(P2P, INFO, "mtk_vif_destructor\n"); + if (dev) { + prWdev = dev->ieee80211_ptr; + free_netdev(dev); + /* Expect that the gprP2pWdev isn't freed here */ + if ((prWdev) && (prWdev != gprP2pWdev)) { + /* Role[i] and Dev share the same wdev by default */ + for (u4Idx = 0; u4Idx < KAL_P2P_NUM; u4Idx++) { + if (prWdev != gprP2pRoleWdev[u4Idx]) + continue; + /* In the initWlan gprP2pRoleWdev[0] is equal to + * gprP2pWdev. And other gprP2pRoleWdev[] should + * be NULL, if the 2nd P2P dev isn't created. + */ + if (u4Idx == 0) + gprP2pRoleWdev[u4Idx] = gprP2pWdev; + else + gprP2pRoleWdev[u4Idx] = NULL; + break; + } + kfree(prWdev); + } + } +} + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +struct wireless_dev *mtk_p2p_cfg80211_add_iface(struct wiphy *wiphy, + const char *name, unsigned char name_assign_type, + enum nl80211_iftype type, struct vif_params *params) +#elif KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE +struct wireless_dev *mtk_p2p_cfg80211_add_iface(struct wiphy *wiphy, + const char *name, unsigned char name_assign_type, + enum nl80211_iftype type, u32 *flags, struct vif_params *params) +#else +struct wireless_dev *mtk_p2p_cfg80211_add_iface(struct wiphy *wiphy, + const char *name, + enum nl80211_iftype type, u32 *flags, struct vif_params *params) +#endif +{ + /* 2 TODO: Fit kernel 3.10 modification */ + struct ADAPTER *prAdapter; + struct GLUE_INFO *prGlueInfo = NULL; + struct net_device *prNewNetDevice = NULL; + uint32_t u4Idx = 0; + struct GL_P2P_INFO *prP2pInfo = NULL; + struct GL_HIF_INFO *prHif = NULL; + struct MSG_P2P_SWITCH_OP_MODE *prSwitchModeMsg = NULL; + struct wireless_dev *prWdev = NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = NULL; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPriv = NULL; + uint8_t rMacAddr[PARAM_MAC_ADDR_LEN]; + struct MSG_P2P_ACTIVE_DEV_BSS *prMsgActiveBss = NULL; + struct mt66xx_chip_info *prChipInfo; + struct wireless_dev *prOrigWdev = NULL; + + do { + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (prGlueInfo == NULL) + return ERR_PTR(-EINVAL); + + prAdapter = prGlueInfo->prAdapter; + prChipInfo = prAdapter->chip_info; + + for (u4Idx = 0; u4Idx < KAL_P2P_NUM; u4Idx++) { + prP2pInfo = prGlueInfo->prP2PInfo[u4Idx]; + /* Expect that only create the new dev with the p2p0 */ + if (prP2pInfo == NULL) + continue; + if (prP2pInfo->aprRoleHandler == + prP2pInfo->prDevHandler) + break; + if (prP2pInfo->aprRoleHandler == NULL) { + p2pRoleFsmInit(prGlueInfo->prAdapter, u4Idx); + break; + } + } + + /*u4Idx = 0;*/ + DBGLOG(P2P, TRACE, "%s: u4Idx=%d\n", __func__, u4Idx); + + if (u4Idx == KAL_P2P_NUM) { + /* Role port full. */ + return ERR_PTR(-EINVAL); + } + + prP2pInfo = prGlueInfo->prP2PInfo[u4Idx]; + + /* Alloc all resource here to avoid do unregister_netdev for + * error case (kernel exception). + */ +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE + prNewNetDevice = alloc_netdev_mq( + sizeof(struct NETDEV_PRIVATE_GLUE_INFO), name, + NET_NAME_PREDICTABLE, ether_setup, CFG_MAX_TXQ_NUM); +#else + prNewNetDevice = alloc_netdev_mq( + sizeof(struct NETDEV_PRIVATE_GLUE_INFO), name, + ether_setup, CFG_MAX_TXQ_NUM); +#endif + + if (prNewNetDevice == NULL) { + DBGLOG(P2P, ERROR, "can't alloc prNewNetDevice\n"); + break; + } + + prWdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (prWdev == NULL) { + DBGLOG(P2P, ERROR, "can't alloc prWdev\n"); + break; + } + + prSwitchModeMsg = (struct MSG_P2P_SWITCH_OP_MODE *) cnmMemAlloc( + prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_P2P_SWITCH_OP_MODE)); + if (prSwitchModeMsg == NULL) { + DBGLOG(P2P, ERROR, "can't alloc prSwitchModeMsg\n"); + break; + } + + prMsgActiveBss = (struct MSG_P2P_ACTIVE_DEV_BSS *) cnmMemAlloc( + prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_P2P_ACTIVE_DEV_BSS)); + + if (prMsgActiveBss == NULL) { + DBGLOG(P2P, ERROR, "can't alloc prMsgActiveBss\n"); + break; + } + + DBGLOG(P2P, INFO, "type: %d, name = %s, netdev: 0x%p\n", + type, name, prNewNetDevice); + + prP2pInfo->aprRoleHandler = prNewNetDevice; + *((struct GLUE_INFO **) netdev_priv(prNewNetDevice)) = + prGlueInfo; + prNewNetDevice->needed_headroom += + NIC_TX_DESC_AND_PADDING_LENGTH + + prChipInfo->txd_append_size; + prNewNetDevice->netdev_ops = &p2p_netdev_ops; + + prHif = &prGlueInfo->rHifInfo; + ASSERT(prHif); + +#if defined(_HIF_SDIO) +#if (MTK_WCN_HIF_SDIO == 0) + SET_NETDEV_DEV(prNewNetDevice, &(prHif->func->dev)); +#endif +#endif + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + kalMemCopy(prWdev, gprP2pWdev, sizeof(struct wireless_dev)); + prWdev->netdev = prNewNetDevice; + prWdev->iftype = type; + prNewNetDevice->ieee80211_ptr = prWdev; + /* register destructor function for virtual interface */ +#if KERNEL_VERSION(4, 14, 0) <= CFG80211_VERSION_CODE + prNewNetDevice->priv_destructor = mtk_vif_destructor; +#else + prNewNetDevice->destructor = mtk_vif_destructor; +#endif + + /* The prOrigWdev is used to do error handle. If return fail, + * set the gprP2pRoleWdev[u4Idx] to original value. + * Expect that the gprP2pRoleWdev[0] = gprP2pWdev, and the + * other is NULL. + */ + prOrigWdev = gprP2pRoleWdev[u4Idx]; + gprP2pRoleWdev[u4Idx] = prWdev; + /*prP2pInfo->prRoleWdev[0] = prWdev;*//* TH3 multiple P2P */ +#endif + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + /* set HW checksum offload */ + if (prAdapter->fgIsSupportCsumOffload) + prNewNetDevice->features = NETIF_F_IP_CSUM + | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + kalResetStats(prNewNetDevice); + /* net device initialize */ + + /* register for net device */ + if (register_netdevice(prP2pInfo->aprRoleHandler) < 0) { + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_add_iface 456\n"); + DBGLOG(INIT, WARN, + "unable to register netdevice for p2p\n"); + break; + + } else { + DBGLOG(P2P, TRACE, "register_netdev OK\n"); + prGlueInfo->prAdapter->rP2PNetRegState = + ENUM_NET_REG_STATE_REGISTERED; + + netif_carrier_off(prP2pInfo->aprRoleHandler); + netif_tx_stop_all_queues(prP2pInfo->aprRoleHandler); + } + prP2pRoleFsmInfo = prAdapter->rWifiVar.aprP2pRoleFsmInfo[u4Idx]; + + /* 13. bind netdev pointer to netdev index */ + wlanBindBssIdxToNetInterface(prGlueInfo, + prP2pRoleFsmInfo->ucBssIndex, + (void *) prP2pInfo->aprRoleHandler); + prNetDevPriv = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prP2pInfo->aprRoleHandler); + prNetDevPriv->prGlueInfo = prGlueInfo; + prNetDevPriv->ucBssIdx = prP2pRoleFsmInfo->ucBssIndex; +#if CFG_ENABLE_UNIFY_WIPHY + /* Expect that only P2P device uses the cfg80211_add_iface */ + prNetDevPriv->ucIsP2p = TRUE; +#endif + + /* 4.2 fill hardware address */ + COPY_MAC_ADDR(rMacAddr, prAdapter->rMyMacAddr); + if (prGlueInfo->prAdapter->rWifiVar.ucP2pShareMacAddr && + (type == NL80211_IFTYPE_P2P_CLIENT + || type == NL80211_IFTYPE_P2P_GO)) { + rMacAddr[0] = gPrP2pDev[0]->dev_addr[0]; + } else { + /* change to local administrated address */ + rMacAddr[0] |= 0x2; + if (u4Idx > 0) + rMacAddr[0] ^= u4Idx << 2; + else + rMacAddr[0] ^= + prGlueInfo->prAdapter + ->prP2pInfo->u4DeviceNum << 2; + } + kalMemCopy(prNewNetDevice->dev_addr, rMacAddr, ETH_ALEN); + kalMemCopy(prNewNetDevice->perm_addr, rMacAddr, ETH_ALEN); + + DBGLOG(P2P, TRACE, + "mtk_p2p_cfg80211_add_iface ucBssIdx=%d\n", + prNetDevPriv->ucBssIdx); + + /* Switch OP MOde. */ + prSwitchModeMsg->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; + prSwitchModeMsg->ucRoleIdx = 0; + switch (type) { + case NL80211_IFTYPE_P2P_CLIENT: + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_P2P_CLIENT.\n"); + prSwitchModeMsg->eOpMode = OP_MODE_INFRASTRUCTURE; + kalP2PSetRole(prGlueInfo, 1, u4Idx); + break; + case NL80211_IFTYPE_STATION: + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_STATION.\n"); + prSwitchModeMsg->eOpMode = OP_MODE_INFRASTRUCTURE; + kalP2PSetRole(prGlueInfo, 1, u4Idx); + break; + case NL80211_IFTYPE_AP: + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_AP.\n"); + prSwitchModeMsg->eOpMode = OP_MODE_ACCESS_POINT; + kalP2PSetRole(prGlueInfo, 2, u4Idx); + break; + case NL80211_IFTYPE_P2P_GO: + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_P2P_GO not AP.\n"); + prSwitchModeMsg->eOpMode = OP_MODE_ACCESS_POINT; + kalP2PSetRole(prGlueInfo, 2, u4Idx); + break; + default: + DBGLOG(P2P, TRACE, "Other type :%d .\n", type); + prSwitchModeMsg->eOpMode = OP_MODE_P2P_DEVICE; + kalP2PSetRole(prGlueInfo, 0, u4Idx); + break; + } + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prSwitchModeMsg, + MSG_SEND_METHOD_BUF); + + /* Send Msg to DevFsm and active P2P dev BSS */ + prMsgActiveBss->rMsgHdr.eMsgId = MID_MNY_P2P_ACTIVE_BSS; + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prMsgActiveBss, MSG_SEND_METHOD_BUF); + /* Success */ + return prWdev; + } while (FALSE); + + /* Start Error Handle */ + + if (prNewNetDevice != NULL) { + free_netdev(prNewNetDevice); + prP2pInfo->aprRoleHandler = NULL; + } + + if (prWdev != NULL) { + kfree(prWdev); + + if ((gprP2pRoleWdev[u4Idx] != NULL) && + (gprP2pRoleWdev[u4Idx] != gprP2pWdev)) { + gprP2pRoleWdev[u4Idx] = prOrigWdev; + } + } + + if (prSwitchModeMsg != NULL) + cnmMemFree(prAdapter, prSwitchModeMsg); + + if (prMsgActiveBss != NULL) + cnmMemFree(prAdapter, prMsgActiveBss); + + return ERR_PTR(-ENOMEM); +} /* mtk_p2p_cfg80211_add_iface */ + +int mtk_p2p_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev) +{ +#if 0 + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + struct MSG_P2P_DEL_IFACE *prP2pDelIfaceMsg = + (struct MSG_P2P_DEL_IFACE *) NULL; + struct MSG_P2P_ACTIVE_DEV_BSS *prMsgActiveBss = + (struct MSG_P2P_ACTIVE_DEV_BSS *) NULL; + + prGlueInfo = *((struct GLUE_INFO **) wiphy_priv(wiphy)); + if (prGlueInfo == NULL) + return -EINVAL; + + prP2pDelIfaceMsg = (struct MSG_P2P_DEL_IFACE *) + cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_P2P_DEL_IFACE)); + + if (prP2pDelIfaceMsg == NULL) { + ASSERT(FALSE); + DBGLOG(INIT, WARN, "unable to alloc msg\n"); + } else { + prP2pDelIfaceMsg->rMsgHdr.eMsgId = MID_MNY_P2P_DEL_IFACE; + prP2pDelIfaceMsg->ucRoleIdx = 0; + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prP2pDelIfaceMsg, + MSG_SEND_METHOD_BUF); + + /* Send Msg to DevFsm and Deactive P2P dev BSS */ + prMsgActiveBss = cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_P2P_ACTIVE_DEV_BSS)); + prMsgActiveBss->rMsgHdr.eMsgId = MID_MNY_P2P_ACTIVE_BSS; + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prMsgActiveBss, + MSG_SEND_METHOD_BUF); + } + +#else + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + struct MSG_P2P_DEL_IFACE *prP2pDelIfaceMsg = + (struct MSG_P2P_DEL_IFACE *) NULL; + struct ADAPTER *prAdapter; + struct GL_P2P_INFO *prP2pInfo = (struct GL_P2P_INFO *) NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct GL_P2P_DEV_INFO *prP2pGlueDevInfo = + (struct GL_P2P_DEV_INFO *) NULL; + struct net_device *UnregRoleHander = (struct net_device *)NULL; + unsigned char ucBssIdx = 0; + struct BSS_INFO *prP2pBssInfo = NULL; +#if 1 + struct cfg80211_scan_request *prScanRequest = NULL; +#endif + + GLUE_SPIN_LOCK_DECLARATION(); + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_del_iface\n"); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (prGlueInfo == NULL) + return -EINVAL; + + prAdapter = prGlueInfo->prAdapter; + prP2pInfo = prGlueInfo->prP2PInfo[0]; + prP2pGlueDevInfo = prGlueInfo->prP2PDevInfo; + + if ((prP2pInfo == NULL) || + (prP2pInfo->aprRoleHandler == NULL) || + (prP2pInfo->aprRoleHandler == prP2pInfo->prDevHandler)) { + /* This iface isn't added. */ + return -EINVAL; + } + + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_DEL_INF); + + prP2pRoleFsmInfo = prAdapter->rWifiVar.aprP2pRoleFsmInfo[0]; + if (prP2pRoleFsmInfo == NULL) { + KAL_RELEASE_MUTEX(prAdapter, MUTEX_DEL_INF); + return -EINVAL; + } + + ucBssIdx = prP2pRoleFsmInfo->ucBssIndex; + wlanBindBssIdxToNetInterface(prGlueInfo, ucBssIdx, + (void *) prGlueInfo->prP2PInfo[0]->prDevHandler); + + UnregRoleHander = prP2pInfo->aprRoleHandler; + + /* fix that the kernel warning occures when the GC is connected */ + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + if ((prP2pBssInfo != NULL) && + (prP2pBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) && + (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) { +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 2, 0) <= CFG80211_VERSION_CODE) + cfg80211_disconnected(UnregRoleHander, 0, NULL, 0, TRUE, + GFP_KERNEL); +#else + cfg80211_disconnected(UnregRoleHander, 0, NULL, 0, GFP_KERNEL); +#endif + } + + /* Wait for kalSendCompleteAndAwakeQueue() complete */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + prP2pInfo->aprRoleHandler = prP2pInfo->prDevHandler; +#if 1 + prScanRequest = prP2pGlueDevInfo->prScanRequest; + if ((prScanRequest != NULL) && + (prScanRequest->wdev == UnregRoleHander->ieee80211_ptr)) { + kalCfg80211ScanDone(prScanRequest, TRUE); + prP2pGlueDevInfo->prScanRequest = NULL; + } +#else + /* 2017/12/18: This part is for error case that p2p-p2p0-0 which is + * deleted when doing scan causes some exception for scan done action. + * The newest driver doesn't observed this error case, so just do the + * normal scan done process (use prP2pGlueDevInfo->prScanRequest, not + * prP2pGlueDevInfo->rBackupScanRequest). Keep this part for the + * reference, if the exception case occurs again. + * Can reference the related part in the mtk_p2p_cfg80211_scan. + */ + if (prP2pGlueDevInfo->prScanRequest != NULL) { + /* Check the wdev with backup scan req due to */ + /* the kernel will free this request by error handling */ + if (prP2pGlueDevInfo->rBackupScanRequest.wdev + == UnregRoleHander->ieee80211_ptr) { + kalCfg80211ScanDone( + &(prP2pGlueDevInfo->rBackupScanRequest), TRUE); + /* clear the request to avoid the Role FSM + * calls the scan_done again + */ + prP2pGlueDevInfo->prScanRequest = NULL; + } + } +#endif + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + /* prepare for removal */ + if (netif_carrier_ok(UnregRoleHander)) + netif_carrier_off(UnregRoleHander); + + netif_tx_stop_all_queues(UnregRoleHander); + + /* Here are functions which need rtnl_lock */ + unregister_netdevice(UnregRoleHander); + /* free is called at destructor */ + /* free_netdev(UnregRoleHander); */ + + KAL_RELEASE_MUTEX(prAdapter, MUTEX_DEL_INF); + + prP2pDelIfaceMsg = (struct MSG_P2P_DEL_IFACE *) + cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_P2P_DEL_IFACE)); + + if (prP2pDelIfaceMsg == NULL) { + ASSERT(FALSE); + DBGLOG(INIT, WARN, "unable to alloc msg\n"); + } else { + prP2pDelIfaceMsg->rMsgHdr.eMsgId = MID_MNY_P2P_DEL_IFACE; + prP2pDelIfaceMsg->ucRoleIdx = 0; + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prP2pDelIfaceMsg, + MSG_SEND_METHOD_BUF); + } +#endif + return 0; +} /* mtk_p2p_cfg80211_del_iface */ + +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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Rslt = -EINVAL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + struct P2P_PARAM_KEY rKey; + uint8_t ucRoleIdx = 0; + const uint8_t aucBCAddr[] = BC_MAC_ADDR; + /* const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; */ + uint8_t ucLoopCnt = 0; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + prGlueInfo->prAdapter->fgIsAddKeyDone = FALSE; + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, ndev, &ucRoleIdx) != 0) + return -EINVAL; + + DBGLOG(RSN, TRACE, "mtk_p2p_cfg80211_add_key\n"); +#if DBG + if (mac_addr) { + DBGLOG(RSN, INFO, + "keyIdx = %d pairwise = %d mac = " MACSTR "\n", + key_index, pairwise, MAC2STR(mac_addr)); + } else { + DBGLOG(RSN, INFO, + "keyIdx = %d pairwise = %d null mac\n", + key_index, pairwise); + } + DBGLOG(RSN, TRACE, "Cipher = %x\n", params->cipher); + DBGLOG_MEM8(RSN, TRACE, params->key, params->key_len); +#endif + + /* Todo:: By Cipher to set the key */ + + kalMemZero(&rKey, sizeof(struct P2P_PARAM_KEY)); + + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, + ucRoleIdx, &rKey.ucBssIdx) != WLAN_STATUS_SUCCESS) + return -EINVAL; + + rKey.u4KeyIndex = key_index; + + if (params->cipher) { + switch (params->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + rKey.ucCipher = CIPHER_SUITE_WEP40; + break; + case WLAN_CIPHER_SUITE_WEP104: + rKey.ucCipher = CIPHER_SUITE_WEP104; + break; +#if 0 + case WLAN_CIPHER_SUITE_WEP128: + rKey.ucCipher = CIPHER_SUITE_WEP128; + break; +#endif + case WLAN_CIPHER_SUITE_TKIP: + rKey.ucCipher = CIPHER_SUITE_TKIP; + break; + case WLAN_CIPHER_SUITE_CCMP: + rKey.ucCipher = CIPHER_SUITE_CCMP; + break; +#if 0 + case WLAN_CIPHER_SUITE_GCMP: + rKey.ucCipher = CIPHER_SUITE_GCMP; + break; + case WLAN_CIPHER_SUITE_CCMP_256: + rKey.ucCipher = CIPHER_SUITE_CCMP256; + break; +#endif + case WLAN_CIPHER_SUITE_SMS4: + rKey.ucCipher = CIPHER_SUITE_WPI; + break; + case WLAN_CIPHER_SUITE_AES_CMAC: + rKey.ucCipher = CIPHER_SUITE_BIP; + break; + default: + ASSERT(FALSE); + } + } + + /* For BC addr case: ex: AP mode, + * driver_nl80211 will not have mac_addr + */ + if (pairwise) { + rKey.u4KeyIndex |= BIT(31); /* Tx */ + rKey.u4KeyIndex |= BIT(30); /* Pairwise */ + COPY_MAC_ADDR(rKey.arBSSID, mac_addr); + } else { + COPY_MAC_ADDR(rKey.arBSSID, aucBCAddr); + } + + /* Check if add key under AP mode */ + if (kalP2PGetRole(prGlueInfo, ucRoleIdx) == 2) + rKey.u4KeyIndex |= BIT(28); /* authenticator */ + + + if (params->key) + kalMemCopy(rKey.aucKeyMaterial, params->key, params->key_len); + rKey.u4KeyLength = params->key_len; + rKey.u4Length = ((unsigned long) + &(((struct P2P_PARAM_KEY *) 0)->aucKeyMaterial)) + + rKey.u4KeyLength; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAddKey, + &rKey, rKey.u4Length, FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_SUCCESS) + i4Rslt = 0; + + while (!prGlueInfo->prAdapter->fgIsAddKeyDone) { + if (ucLoopCnt > 100) { + DBGLOG(P2P, ERROR, + "wait AddKeyDone timeout\n"); + break; + } + + ucLoopCnt++; + kalMsleep(1); + } + 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 *)) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + /* not implemented yet */ + DBGLOG(RSN, INFO, "not support this func\n"); + + return -EINVAL; +} + +int mtk_p2p_cfg80211_del_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, bool pairwise, const u8 *mac_addr) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_REMOVE_KEY rRemoveKey; + int32_t i4Rslt = -EINVAL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + uint8_t ucRoleIdx = 0; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + DBGLOG(RSN, TRACE, "mtk_p2p_cfg80211_del_key\n"); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, ndev, &ucRoleIdx) < 0) + return -EINVAL; +#if DBG + if (mac_addr) { + DBGLOG(RSN, TRACE, + "keyIdx = %d pairwise = %d mac = " MACSTR "\n", + key_index, pairwise, MAC2STR(mac_addr)); + } else { + DBGLOG(RSN, TRACE, + "keyIdx = %d pairwise = %d null mac\n", + key_index, pairwise); + } +#endif + + kalMemZero(&rRemoveKey, sizeof(struct PARAM_REMOVE_KEY)); + + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, + ucRoleIdx, &rRemoveKey.ucBssIdx) != WLAN_STATUS_SUCCESS) + return -EINVAL; + + if (mac_addr) + COPY_MAC_ADDR(rRemoveKey.arBSSID, mac_addr); + rRemoveKey.u4KeyIndex = key_index; + rRemoveKey.u4Length = sizeof(struct PARAM_REMOVE_KEY); + if (mac_addr) { + COPY_MAC_ADDR(rRemoveKey.arBSSID, mac_addr); + rRemoveKey.u4KeyIndex |= BIT(30); + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRemoveKey, + &rRemoveKey, rRemoveKey.u4Length, + FALSE, FALSE, 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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_DEFAULT_KEY rDefaultKey; + uint8_t ucRoleIdx = 0; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + int32_t i4Rst = -EINVAL; + uint32_t u4BufLen = 0; + u_int8_t fgDef = FALSE, fgMgtDef = FALSE; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + DBGLOG(RSN, TRACE, "mtk_p2p_cfg80211_set_default_key\n"); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, netdev, &ucRoleIdx) != 0) + return -EINVAL; +#if DBG + DBGLOG(RSN, TRACE, + "keyIdx = %d unicast = %d multicast = %d\n", + key_index, unicast, multicast); +#endif + + + /* For wep case, this set the key for tx */ + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, + ucRoleIdx, &rDefaultKey.ucBssIdx) != WLAN_STATUS_SUCCESS) + return -EINVAL; + + + rDefaultKey.ucKeyID = key_index; + rDefaultKey.ucUnicast = unicast; + rDefaultKey.ucMulticast = multicast; + if (rDefaultKey.ucUnicast && !rDefaultKey.ucMulticast) + return WLAN_STATUS_SUCCESS; + + if (rDefaultKey.ucUnicast && rDefaultKey.ucMulticast) + fgDef = TRUE; + + if (!rDefaultKey.ucUnicast && rDefaultKey.ucMulticast) + fgMgtDef = TRUE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetDefaultKey, + &rDefaultKey, + sizeof(struct PARAM_DEFAULT_KEY), + FALSE, FALSE, TRUE, &u4BufLen); + + + if (rStatus == WLAN_STATUS_SUCCESS) + i4Rst = 0; + + + return i4Rst; +} + +/*---------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for setting the default mgmt key index + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*---------------------------------------------------------------------------*/ +int mtk_p2p_cfg80211_set_mgmt_key(struct wiphy *wiphy, + struct net_device *dev, u8 key_index) +{ + DBGLOG(RSN, INFO, "mtk_p2p_cfg80211_set_mgmt_key, kid:%d\n", key_index); + + return 0; +} + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, struct station_info *sinfo) +#else +int mtk_p2p_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, struct station_info *sinfo) +#endif +{ + int32_t i4RetRslt = -EINVAL; + int32_t i4Rssi = 0; + uint8_t ucRoleIdx = 0; + uint8_t ucBssIdx = 0; + uint32_t u4Rate = 0; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + struct GL_P2P_INFO *prP2pGlueInfo = (struct GL_P2P_INFO *) NULL; + struct P2P_STATION_INFO rP2pStaInfo; + struct BSS_INFO *prBssInfo; + struct PARAM_GET_STA_STATISTICS *prQuery; + + ASSERT(wiphy); + + do { + if ((wiphy == NULL) || (ndev == NULL) + || (sinfo == NULL) || (mac == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_get_station\n"); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, ndev, &ucRoleIdx) != 0) + return -EINVAL; + + prP2pGlueInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + + /* Get station information. */ + /* 1. Inactive time? */ + p2pFuncGetStationInfo(prGlueInfo->prAdapter, + (uint8_t *)mac, &rP2pStaInfo); + + /* Inactive time. */ +#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE + sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME); +#else + sinfo->filled |= STATION_INFO_INACTIVE_TIME; +#endif + sinfo->inactive_time = rP2pStaInfo.u4InactiveTime; + sinfo->generation = prP2pGlueInfo->i4Generation; + + /* 2. fill TX rate */ + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, + ucRoleIdx, &ucBssIdx) != WLAN_STATUS_SUCCESS) + return -EINVAL; + prBssInfo = + GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, ucBssIdx); + if (!prBssInfo) { + DBGLOG(P2P, WARN, "bss is not active\n"); + return -EINVAL; + } + if (prBssInfo->eConnectionState + != PARAM_MEDIA_STATE_CONNECTED) { + /* not connected */ + DBGLOG(P2P, WARN, "not yet connected\n"); + return 0; + } + + prQuery = + prGlueInfo->prAdapter->rWifiVar + .prP2pQueryStaStatistics[ucRoleIdx]; + if (prQuery) { + u4Rate = prQuery->u2LinkSpeed * 5000; + i4Rssi = RCPI_TO_dBm(prQuery->ucRcpi); + } + + sinfo->txrate.legacy = u4Rate / 1000; + sinfo->signal = i4Rssi; + + DBGLOG(P2P, INFO, + "ucRoleIdx = %d, rate = %u, signal = %d\n", + ucRoleIdx, + sinfo->txrate.legacy, + sinfo->signal); + +#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE + sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); + sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); +#else + sinfo->filled |= STATION_INFO_TX_BITRATE; + sinfo->filled |= STATION_INFO_SIGNAL; +#endif + + i4RetRslt = 0; + } while (FALSE); + + return i4RetRslt; +} + +int mtk_p2p_cfg80211_scan(struct wiphy *wiphy, + struct cfg80211_scan_request *request) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + struct GL_P2P_INFO *prP2pGlueInfo = (struct GL_P2P_INFO *) NULL; + struct GL_P2P_DEV_INFO *prP2pGlueDevInfo = + (struct GL_P2P_DEV_INFO *) NULL; + struct MSG_P2P_SCAN_REQUEST *prMsgScanRequest = ( + struct MSG_P2P_SCAN_REQUEST *) NULL; + uint32_t u4MsgSize = 0, u4Idx = 0; + int32_t i4RetRslt = -EINVAL; + struct RF_CHANNEL_INFO *prRfChannelInfo = + (struct RF_CHANNEL_INFO *) NULL; + struct P2P_SSID_STRUCT *prSsidStruct = (struct P2P_SSID_STRUCT *) NULL; + struct ieee80211_channel *prChannel = NULL; + struct cfg80211_ssid *prSsid = NULL; + uint8_t ucBssIdx = 0; + u_int8_t fgIsFullChanScan = FALSE; + + /* [-----Channel-----] [-----SSID-----][-----IE-----] */ + + do { + if ((wiphy == NULL) || (request == NULL)) + break; + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (wlanIsChipAssert(prGlueInfo->prAdapter)) + break; + + prP2pGlueInfo = prGlueInfo->prP2PInfo[0]; + prP2pGlueDevInfo = prGlueInfo->prP2PDevInfo; + + if ((prP2pGlueInfo == NULL) || (prP2pGlueDevInfo == NULL)) { + ASSERT(FALSE); + break; + } + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_scan.\n"); + + if (prP2pGlueDevInfo->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; + } + + prP2pGlueDevInfo->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; + fgIsFullChanScan = TRUE; + DBGLOG(P2P, TRACE, + "Channel list exceed the maximun support.\n"); + } + /* TODO: */ + /* Find a way to distinct DEV port scan & ROLE port scan. + */ + ucBssIdx = prGlueInfo->prAdapter->ucP2PDevBssIdx; + DBGLOG(P2P, TRACE, "Device Port Scan.\n"); + + u4MsgSize = sizeof(struct MSG_P2P_SCAN_REQUEST) + + (request->n_channels * sizeof(struct RF_CHANNEL_INFO)) + + (request->n_ssids * sizeof(struct PARAM_SSID)) + + 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; + prMsgScanRequest->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prMsgScanRequest->ucBssIdx = ucBssIdx; + + DBGLOG(P2P, INFO, + "Requesting channel number:%d.\n", request->n_channels); + + for (u4Idx = 0; u4Idx < request->n_channels; u4Idx++) { + /* Translate Freq from MHz to channel number. */ + prRfChannelInfo = + &(prMsgScanRequest->arChannelListInfo[u4Idx]); + prChannel = request->channels[u4Idx]; + + prRfChannelInfo->ucChannelNum = + nicFreq2ChannelNum( + prChannel->center_freq * 1000); + + DBGLOG(P2P, TRACE, + "Scanning Channel:%d, freq: %d\n", + prRfChannelInfo->ucChannelNum, + prChannel->center_freq); + + switch (prChannel->band) { + case KAL_BAND_2GHZ: + prRfChannelInfo->eBand = BAND_2G4; + break; + case KAL_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; + if (fgIsFullChanScan) { + prMsgScanRequest->u4NumChannel = + SCN_P2P_FULL_SCAN_PARAM; + DBGLOG(P2P, INFO, + "request->n_channels = SCN_P2P_FULL_SCAN_PARAM\n"); + } + DBGLOG(P2P, TRACE, "Finish channel list.\n"); + + /* SSID */ + prSsid = request->ssids; + prSsidStruct = (struct P2P_SSID_STRUCT *) prRfChannelInfo; + if (request->n_ssids) { + ASSERT((unsigned long) prSsidStruct + == (unsigned long) + &(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 = (uint8_t *) prSsidStruct; + if (request->ie_len) { + kalMemCopy(prMsgScanRequest->pucIEBuf, + request->ie, request->ie_len); + prMsgScanRequest->u4IELen = request->ie_len; + } else { + prMsgScanRequest->u4IELen = 0; + } + + DBGLOG(P2P, TRACE, "Finish IE Buffer.\n"); + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prMsgScanRequest, + MSG_SEND_METHOD_BUF); + + /* Backup scan request structure */ + /* The purpose of this backup is due + * to the kernel free the scan req + * when the wpa supplicant down the iface before down, + * and it will free the original scan request structure + * In this case, the scan resoure could be locked by kernel, + * and driver needs this work around to clear the state + */ +#if 0 + kalMemCopy(&(prP2pGlueDevInfo->rBackupScanRequest), + prP2pGlueDevInfo->prScanRequest, + sizeof(struct cfg80211_scan_request)); +#endif + i4RetRslt = 0; + } while (FALSE); + + return i4RetRslt; +} /* mtk_p2p_cfg80211_scan */ + +void mtk_p2p_cfg80211_abort_scan(struct wiphy *wiphy, struct wireless_dev *wdev) +{ + uint32_t u4SetInfoLen = 0; + uint32_t u4Value = 0; + uint32_t rStatus; + struct GLUE_INFO *prGlueInfo = NULL; + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_abort_scan\n"); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidAbortP2pScan, + &u4Value, sizeof(u4Value), + FALSE, FALSE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, ERROR, + "mtk_p2p_cfg80211_abort_scan fail 0x%x\n", + rStatus); +} + +int mtk_p2p_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) +{ + int32_t i4Rslt = -EINVAL; + struct GLUE_INFO *prGlueInfo = NULL; + + do { + if (wiphy == NULL) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_set_wiphy_params\n"); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + 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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + DBGLOG(P2P, INFO, "not support now\n"); + /* not implemented yet */ + + return -EINVAL; +} + +int mtk_p2p_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + DBGLOG(P2P, INFO, "not support now\n"); + /* not implemented yet */ + + return -EINVAL; +} + +int mtk_p2p_cfg80211_set_txpower(struct wiphy *wiphy, + struct wireless_dev *wdev, + enum nl80211_tx_power_setting type, int mbm) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + ASSERT(wiphy); + + DBGLOG(P2P, INFO, "%s: not support now\n", __func__); + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + /* not implemented yet */ + + return -EINVAL; +} + +int mtk_p2p_cfg80211_get_txpower(struct wiphy *wiphy, + struct wireless_dev *wdev, int *dbm) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + ASSERT(wiphy); + + DBGLOG(P2P, TRACE, "%s: not support now\n", __func__); + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + /* not implemented yet */ + + return -EINVAL; +} + +int mtk_p2p_cfg80211_set_power_mgmt(struct wiphy *wiphy, + struct net_device *ndev, bool enabled, int timeout) +{ + struct GLUE_INFO *prGlueInfo = NULL; + enum PARAM_POWER_MODE ePowerMode; + struct PARAM_POWER_MODE_ rPowerMode; + uint32_t u4Leng; + uint8_t ucRoleIdx; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (enabled) + ePowerMode = Param_PowerModeFast_PSP; + else + ePowerMode = Param_PowerModeCAM; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_set_power_mgmt ps=%d.\n", enabled); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, + ndev, &ucRoleIdx) != 0) + return -EINVAL; + + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, + ucRoleIdx, &rPowerMode.ucBssIdx) != WLAN_STATUS_SUCCESS) + return -EINVAL; + + rPowerMode.ePowerMode = ePowerMode; + + /* p2p_set_power_save */ + kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, sizeof(rPowerMode), + FALSE, FALSE, TRUE, &u4Leng); + + return 0; +} + +int mtk_p2p_cfg80211_start_ap(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ap_settings *settings) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + struct ADAPTER *prAdapter = (struct ADAPTER *) NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_P2P_BEACON_UPDATE *prP2pBcnUpdateMsg = + (struct MSG_P2P_BEACON_UPDATE *) NULL; + struct MSG_P2P_START_AP *prP2pStartAPMsg = + (struct MSG_P2P_START_AP *) NULL; + uint8_t *pucBuffer = (uint8_t *) NULL; + uint8_t ucRoleIdx = 0; + struct cfg80211_chan_def *chandef; + struct RF_CHANNEL_INFO rRfChnlInfo; + uint8_t ucLoopCnt = 0; + + /* RF_CHANNEL_INFO_T rRfChnlInfo; */ +/* P_IE_SSID_T prSsidIE = (P_IE_SSID_T)NULL; */ + + do { + if ((wiphy == NULL) || (settings == NULL)) + break; + + DBGLOG(P2P, INFO, "%s\n", __func__); + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + if (prGlueInfo == NULL) { + DBGLOG(P2P, ERROR, "%s: prGlueInfo = NULL\n", __func__); + break; + } + + prAdapter = prGlueInfo->prAdapter; + if (prAdapter == NULL) { + DBGLOG(P2P, ERROR, "%s: prAdapter = NULL\n", __func__); + break; + } + + prAdapter->fgIsStartApDone = FALSE; + + /*DFS todo 20161220_DFS*/ + netif_carrier_on(dev); + netif_tx_start_all_queues(dev); + + chandef = &settings->chandef; + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + + if (chandef) { + mtk_p2p_cfg80211func_channel_format_switch(chandef, + chandef->chan, &rRfChnlInfo); + + /* Follow the channel info from wifi.cfg + * prior to hostapd.conf + */ + { + struct WIFI_VAR *prWifiVar = + (struct WIFI_VAR *)NULL; + + prWifiVar = &prAdapter->rWifiVar; + + if ((prWifiVar->ucApChannel != 0) && + (prWifiVar->ucApChnlDefFromCfg != 0) && + (prWifiVar->ucApChannel != + rRfChnlInfo.ucChannelNum)) { + rRfChnlInfo.ucChannelNum = + prWifiVar->ucApChannel; + rRfChnlInfo.eBand = + (rRfChnlInfo.ucChannelNum <= 14) + ? BAND_2G4 : BAND_5G; + /* [TODO][20160829]If we will set SCO + * by nl80211_channel_type afterward, + * to check if we need to modify SCO + * by wifi.cfg here + */ + } + } + + p2pFuncSetChannel(prAdapter, + ucRoleIdx, &rRfChnlInfo); + } else + DBGLOG(P2P, INFO, "!!! no CH def!!!\n"); + + prP2pBcnUpdateMsg = (struct MSG_P2P_BEACON_UPDATE *) + cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + (sizeof(struct MSG_P2P_BEACON_UPDATE) + + + settings->beacon.head_len + + settings->beacon.tail_len + + settings->beacon.assocresp_ies_len +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP + + settings->beacon.proberesp_ies_len +#endif + )); + + if (prP2pBcnUpdateMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prP2pBcnUpdateMsg->ucRoleIndex = ucRoleIdx; + prP2pBcnUpdateMsg->rMsgHdr.eMsgId = MID_MNY_P2P_BEACON_UPDATE; + pucBuffer = prP2pBcnUpdateMsg->aucBuffer; + +#if (CFG_SUPPORT_DFS_MASTER == 1) + if (p2pFuncGetDfsState() == DFS_STATE_DETECTED) + p2pFuncSetDfsState(DFS_STATE_INACTIVE); +#endif + 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 += settings->beacon.head_len; + } else { + prP2pBcnUpdateMsg->u4BcnHdrLen = 0; + + prP2pBcnUpdateMsg->pucBcnHdr = NULL; + } + + if (settings->beacon.tail_len != 0) { + uint8_t ucLen = settings->beacon.tail_len; + + prP2pBcnUpdateMsg->pucBcnBody = pucBuffer; + kalMemCopy(pucBuffer, + settings->beacon.tail, + settings->beacon.tail_len); + + prP2pBcnUpdateMsg->u4BcnBodyLen = ucLen; + + pucBuffer += settings->beacon.tail_len; + } else { + prP2pBcnUpdateMsg->u4BcnBodyLen = 0; + + prP2pBcnUpdateMsg->pucBcnBody = NULL; + } + + if ((settings->crypto.cipher_group == + WLAN_CIPHER_SUITE_WEP40) || + (settings->crypto.cipher_group == + WLAN_CIPHER_SUITE_WEP104)) + prP2pBcnUpdateMsg->fgIsWepCipher = TRUE; + else + prP2pBcnUpdateMsg->fgIsWepCipher = FALSE; + + if (settings->beacon.assocresp_ies_len != 0 + && settings->beacon.assocresp_ies != NULL) { + prP2pBcnUpdateMsg->pucAssocRespIE = pucBuffer; + kalMemCopy(pucBuffer, + settings->beacon.assocresp_ies, + settings->beacon.assocresp_ies_len); + prP2pBcnUpdateMsg->u4AssocRespLen = + settings->beacon.assocresp_ies_len; + } else { + prP2pBcnUpdateMsg->u4AssocRespLen = 0; + prP2pBcnUpdateMsg->pucAssocRespIE = NULL; + } + +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP + if (settings->beacon.proberesp_ies_len != 0 + && settings->beacon.proberesp_ies != NULL) { + prP2pBcnUpdateMsg->pucProbeRespIE = pucBuffer; + kalMemCopy(pucBuffer, + settings->beacon.proberesp_ies, + settings->beacon.proberesp_ies_len); + prP2pBcnUpdateMsg->u4ProbeRespLen = + settings->beacon.proberesp_ies_len; + } else { + prP2pBcnUpdateMsg->u4ProbeRespLen = 0; + prP2pBcnUpdateMsg->pucProbeRespIE = NULL; + } +#endif + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prP2pBcnUpdateMsg, + MSG_SEND_METHOD_BUF); + + prP2pStartAPMsg = (struct MSG_P2P_START_AP *) + cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(struct MSG_P2P_START_AP)); + + 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; + + prP2pStartAPMsg->ucRoleIdx = ucRoleIdx; + + kalP2PSetRole(prGlueInfo, 2, ucRoleIdx); + + COPY_SSID(prP2pStartAPMsg->aucSsid, + prP2pStartAPMsg->u2SsidLen, + settings->ssid, settings->ssid_len); + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prP2pStartAPMsg, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + + } while (FALSE); + + while (prAdapter && !prAdapter->fgIsStartApDone) { + if (ucLoopCnt > 10) { + DBGLOG(P2P, ERROR, + "wait StartApDone timeout\n"); + break; + } + + ucLoopCnt++; + kalMsleep(10); + } + + 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; */ +/* }; */ +/* ////////////////// */ +} /* mtk_p2p_cfg80211_start_ap */ + +#if (CFG_SUPPORT_DFS_MASTER == 1) + +static int mtk_p2p_cfg80211_start_radar_detection_impl(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef, + unsigned int cac_time_ms) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_P2P_DFS_CAC *prP2pDfsCacMsg = + (struct MSG_P2P_DFS_CAC *) NULL; + uint8_t ucRoleIdx = 0; + struct RF_CHANNEL_INFO rRfChnlInfo; + + do { + if ((wiphy == NULL) || (chandef == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_start_radar_detection.\n"); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->chandef == NULL) { + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef = + (struct cfg80211_chan_def *) + cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_BUF, + sizeof(struct cfg80211_chan_def)); + + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->chan = + (struct ieee80211_channel *) + cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_BUF, + sizeof(struct ieee80211_channel)); + } + + /* Copy chan def to local buffer*/ + prGlueInfo->prP2PInfo[ucRoleIdx] + ->chandef->center_freq1 = chandef->center_freq1; + prGlueInfo->prP2PInfo[ucRoleIdx] + ->chandef->center_freq2 = chandef->center_freq2; + prGlueInfo->prP2PInfo[ucRoleIdx] + ->chandef->width = chandef->width; + memcpy(prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->chan, + chandef->chan, sizeof(struct ieee80211_channel)); + prGlueInfo->prP2PInfo[ucRoleIdx]->cac_time_ms = cac_time_ms; + + if (chandef) { + mtk_p2p_cfg80211func_channel_format_switch(chandef, + chandef->chan, &rRfChnlInfo); + + p2pFuncSetChannel(prGlueInfo->prAdapter, + ucRoleIdx, &rRfChnlInfo); + } + + DBGLOG(P2P, INFO, + "mtk_p2p_cfg80211_start_radar_detection.(role %d)\n", + ucRoleIdx); + + p2pFuncSetDfsState(DFS_STATE_INACTIVE); + + prP2pDfsCacMsg = (struct MSG_P2P_DFS_CAC *) + cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, sizeof(*prP2pDfsCacMsg)); + + if (prP2pDfsCacMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prP2pDfsCacMsg->rMsgHdr.eMsgId = MID_MNY_P2P_DFS_CAC; + + switch (chandef->width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + case NL80211_CHAN_WIDTH_40: + prP2pDfsCacMsg->eChannelWidth = CW_20_40MHZ; + break; + + case NL80211_CHAN_WIDTH_80: + prP2pDfsCacMsg->eChannelWidth = CW_80MHZ; + break; + + case NL80211_CHAN_WIDTH_80P80: + prP2pDfsCacMsg->eChannelWidth = CW_80P80MHZ; + break; + + default: + DBGLOG(P2P, ERROR, + "mtk_p2p_cfg80211_start_radar_detection. !!!Bandwidth do not support!!!\n"); + ASSERT(FALSE); + break; + } + + prP2pDfsCacMsg->ucRoleIdx = ucRoleIdx; + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prP2pDfsCacMsg, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + + } while (FALSE); + + return i4Rslt; +} + +#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_start_radar_detection(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef, unsigned int cac_time_ms) +{ + return mtk_p2p_cfg80211_start_radar_detection_impl( + wiphy, dev, chandef, cac_time_ms); +} +#else +int mtk_p2p_cfg80211_start_radar_detection(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef) +{ + return mtk_p2p_cfg80211_start_radar_detection_impl( + wiphy, dev, chandef, IEEE80211_DFS_MIN_CAC_TIME_MS); +} +#endif + +#if KERNEL_VERSION(3, 13, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_channel_switch(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_csa_settings *params) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + struct ADAPTER *prAdapter = (struct ADAPTER *) NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_P2P_BEACON_UPDATE *prP2pBcnUpdateMsg = + (struct MSG_P2P_BEACON_UPDATE *) NULL; + struct MSG_P2P_SET_NEW_CHANNEL *prP2pSetNewChannelMsg = + (struct MSG_P2P_SET_NEW_CHANNEL *) NULL; + uint8_t *pucBuffer = (uint8_t *) NULL; + uint8_t ucRoleIdx = 0; + struct RF_CHANNEL_INFO rRfChnlInfo; + struct BSS_INFO *prBssInfo; + uint8_t ucBssIndex; + uint32_t u4Len = 0; + uint8_t ucLoopCnt = 0; + + do { + if ((wiphy == NULL) || (params == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_channel_switch.\n"); + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + if (prGlueInfo == NULL) { + DBGLOG(P2P, ERROR, "%s: prGlueInfo = NULL\n", __func__); + break; + } + + prAdapter = prGlueInfo->prAdapter; + if (prAdapter == NULL) { + DBGLOG(P2P, ERROR, "%s: prAdapter = NULL\n", __func__); + break; + } + + prAdapter->fgIsChSwitchDone = FALSE; + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + + /*DFS todo 20161220_DFS*/ + netif_carrier_on(dev); + netif_tx_start_all_queues(dev); + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->chandef == NULL) { + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef = + (struct cfg80211_chan_def *) + cnmMemAlloc(prAdapter, + RAM_TYPE_BUF, sizeof(struct cfg80211_chan_def)); + + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->chan = + (struct ieee80211_channel *) + cnmMemAlloc(prAdapter, + RAM_TYPE_BUF, sizeof(struct ieee80211_channel)); + } + /* Copy chan def to local buffer*/ + prGlueInfo->prP2PInfo[ucRoleIdx] + ->chandef->center_freq1 = params->chandef.center_freq1; + prGlueInfo->prP2PInfo[ucRoleIdx] + ->chandef->center_freq2 = params->chandef.center_freq2; + prGlueInfo->prP2PInfo[ucRoleIdx] + ->chandef->width = params->chandef.width; + memcpy(prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->chan, + params->chandef.chan, + sizeof(struct ieee80211_channel)); + + if (params) { + mtk_p2p_cfg80211func_channel_format_switch( + ¶ms->chandef, + params->chandef.chan, &rRfChnlInfo); + + p2pFuncSetChannel(prAdapter, + ucRoleIdx, &rRfChnlInfo); + } + + DBGLOG(P2P, INFO, + "mtk_p2p_cfg80211_channel_switch.(role %d)\n", + ucRoleIdx); + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->chan-> + dfs_state == NL80211_DFS_AVAILABLE +#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE + && prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->chan-> + dfs_cac_ms != 0 +#endif + ) + p2pFuncSetDfsState(DFS_STATE_ACTIVE); + else + p2pFuncSetDfsState(DFS_STATE_INACTIVE); + + /* Set CSA IE parameters */ + prAdapter->rWifiVar.fgCsaInProgress = TRUE; + prAdapter->rWifiVar.ucChannelSwitchMode = 1; + prAdapter->rWifiVar.ucNewChannelNumber = + nicFreq2ChannelNum( + params->chandef.chan->center_freq * 1000); + prAdapter->rWifiVar.ucChannelSwitchCount = + params->count; + + /* Set new channel parameters */ + prP2pSetNewChannelMsg = (struct MSG_P2P_SET_NEW_CHANNEL *) + cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(*prP2pSetNewChannelMsg)); + + if (prP2pSetNewChannelMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prP2pSetNewChannelMsg->rMsgHdr.eMsgId = + MID_MNY_P2P_SET_NEW_CHANNEL; + + switch (params->chandef.width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + case NL80211_CHAN_WIDTH_40: + prP2pSetNewChannelMsg->eChannelWidth = CW_20_40MHZ; + break; + + case NL80211_CHAN_WIDTH_80: + prP2pSetNewChannelMsg->eChannelWidth = CW_80MHZ; + break; + + case NL80211_CHAN_WIDTH_80P80: + prP2pSetNewChannelMsg->eChannelWidth = CW_80P80MHZ; + break; + + default: + DBGLOG(P2P, ERROR, + "mtk_p2p_cfg80211_channel_switch. !!!Bandwidth do not support!!!\n"); + ASSERT(FALSE); + break; + } + + prP2pSetNewChannelMsg->ucRoleIdx = ucRoleIdx; + + for (ucBssIndex = 0; + ucBssIndex < BSS_DEFAULT_NUM; ucBssIndex++) { + prBssInfo = GET_BSS_INFO_BY_INDEX( + prAdapter, ucBssIndex); + + if (prBssInfo && prBssInfo->fgIsDfsActive) { + prP2pSetNewChannelMsg->ucBssIndex = ucBssIndex; + break; + } + } + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prP2pSetNewChannelMsg, + MSG_SEND_METHOD_BUF); + + /* Update beacon */ + if ((params->beacon_csa.head_len != 0) + || (params->beacon_csa.tail_len != 0)) { + u4Len = (sizeof(struct MSG_P2P_BEACON_UPDATE) + + params->beacon_csa.head_len + + params->beacon_csa.tail_len); + + prP2pBcnUpdateMsg = (struct MSG_P2P_BEACON_UPDATE *) + cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + u4Len); + + if (prP2pBcnUpdateMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + kalMemZero(prP2pBcnUpdateMsg, u4Len); + + prP2pBcnUpdateMsg->ucRoleIndex = ucRoleIdx; + prP2pBcnUpdateMsg->rMsgHdr.eMsgId = + MID_MNY_P2P_BEACON_UPDATE; + pucBuffer = prP2pBcnUpdateMsg->aucBuffer; + + if (params->beacon_csa.head_len != 0) { + kalMemCopy(pucBuffer, + params->beacon_csa.head, + params->beacon_csa.head_len); + + prP2pBcnUpdateMsg->u4BcnHdrLen = + params->beacon_csa.head_len; + + prP2pBcnUpdateMsg->pucBcnHdr = pucBuffer; + + pucBuffer = (uint8_t *) ((unsigned long) + pucBuffer + + (unsigned long) + params->beacon_csa.head_len); + } else { + prP2pBcnUpdateMsg->u4BcnHdrLen = 0; + + prP2pBcnUpdateMsg->pucBcnHdr = NULL; + } + + if (params->beacon_csa.tail_len != 0) { + uint8_t ucLen = params->beacon_csa.tail_len; + + prP2pBcnUpdateMsg->pucBcnBody = pucBuffer; + kalMemCopy(pucBuffer, + params->beacon_csa.tail, + params->beacon_csa.tail_len); + + prP2pBcnUpdateMsg->u4BcnBodyLen = ucLen; + } else { + prP2pBcnUpdateMsg->u4BcnBodyLen = 0; + prP2pBcnUpdateMsg->pucBcnBody = NULL; + } + + kalP2PSetRole(prGlueInfo, 2, ucRoleIdx); + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prP2pBcnUpdateMsg, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; /* Return Success */ + } + + } while (FALSE); + + while (prAdapter && !prAdapter->fgIsChSwitchDone) { + if (ucLoopCnt > 100) { + DBGLOG(P2P, ERROR, + "wait ChSwitchDone timeout\n"); + break; + } + + ucLoopCnt++; + kalMsleep(1); + } + + return i4Rslt; +} +#endif +#endif + +#if 0 +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; +}; +#endif + +int mtk_p2p_cfg80211_change_beacon(struct wiphy *wiphy, + struct net_device *dev, struct cfg80211_beacon_data *info) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_P2P_BEACON_UPDATE *prP2pBcnUpdateMsg = + (struct MSG_P2P_BEACON_UPDATE *) NULL; + uint8_t *pucBuffer = (uint8_t *) NULL; + uint8_t ucRoleIdx = 0; + uint32_t u4Len = 0; + + do { + if ((wiphy == NULL) || (info == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_change_beacon.\n"); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + + if ((info->head_len != 0) || (info->tail_len != 0)) { + u4Len = (sizeof(struct MSG_P2P_BEACON_UPDATE) + + info->head_len + + info->tail_len + + info->assocresp_ies_len +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP + + info->proberesp_ies_len +#endif + ); + + prP2pBcnUpdateMsg = (struct MSG_P2P_BEACON_UPDATE *) + cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + u4Len); + + if (prP2pBcnUpdateMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + kalMemZero(prP2pBcnUpdateMsg, u4Len); + + prP2pBcnUpdateMsg->ucRoleIndex = ucRoleIdx; + 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 += info->head_len; + } else { + prP2pBcnUpdateMsg->u4BcnHdrLen = 0; + + prP2pBcnUpdateMsg->pucBcnHdr = NULL; + } + + if (info->tail_len != 0) { + uint8_t ucLen = info->tail_len; + + prP2pBcnUpdateMsg->pucBcnBody = pucBuffer; + kalMemCopy(pucBuffer, + info->tail, + info->tail_len); + + prP2pBcnUpdateMsg->u4BcnBodyLen = ucLen; + + pucBuffer += info->tail_len; + } else { + prP2pBcnUpdateMsg->u4BcnBodyLen = 0; + prP2pBcnUpdateMsg->pucBcnBody = NULL; + } + + if (info->assocresp_ies_len != 0 + && info->assocresp_ies != NULL) { + + prP2pBcnUpdateMsg->pucAssocRespIE = pucBuffer; + kalMemCopy(pucBuffer, + info->assocresp_ies, + info->assocresp_ies_len); + prP2pBcnUpdateMsg->u4AssocRespLen = + info->assocresp_ies_len; + } else { + prP2pBcnUpdateMsg->u4AssocRespLen = 0; + prP2pBcnUpdateMsg->pucAssocRespIE = NULL; + } + +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP + if (info->proberesp_ies_len != 0 + && info->proberesp_ies != NULL) { + + prP2pBcnUpdateMsg->pucProbeRespIE = pucBuffer; + kalMemCopy(pucBuffer, + info->proberesp_ies, + info->proberesp_ies_len); + prP2pBcnUpdateMsg->u4ProbeRespLen = + info->proberesp_ies_len; + } else { + prP2pBcnUpdateMsg->u4ProbeRespLen = 0; + prP2pBcnUpdateMsg->pucProbeRespIE = NULL; + } +#endif + + kalP2PSetRole(prGlueInfo, 2, ucRoleIdx); + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prP2pBcnUpdateMsg, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; /* Return Success */ + } + + /* TODO: Probe Rsp, Assoc Rsp, Beacon IE update. */ + +/* ////////////////////////// */ +/** + * struct cfg80211_beacon_data - beacon data + * @head: head portion of beacon (before TIM IE) + * or %NULL if not changed + * @tail: tail portion of beacon (after TIM IE) + * or %NULL if not changed + * @head_len: length of @head + * @tail_len: length of @tail + * @beacon_ies: extra information element(s) to add into Beacon frames or %NULL + * @beacon_ies_len: length of beacon_ies in octets + * @proberesp_ies: extra information element(s) to add into Probe Response + * frames or %NULL + * @proberesp_ies_len: length of proberesp_ies in octets + * @assocresp_ies: extra information element(s) to add into (Re)Association + * Response frames or %NULL + * @assocresp_ies_len: length of assocresp_ies in octets + * @probe_resp_len: length of probe response template (@probe_resp) + * @probe_resp: probe response template (AP mode only) + */ +/* struct cfg80211_beacon_data { */ +/* const u8 *head, *tail; */ +/* const u8 *beacon_ies; */ +/* const u8 *proberesp_ies; */ +/* const u8 *assocresp_ies; */ +/* const u8 *probe_resp; */ + +/* size_t head_len, tail_len; */ +/* size_t beacon_ies_len; */ +/* size_t proberesp_ies_len; */ +/* size_t assocresp_ies_len; */ +/* size_t probe_resp_len; */ +/* }; */ + +/* ////////////////////////// */ + + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_change_beacon */ + +int mtk_p2p_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + struct ADAPTER *prAdapter = (struct ADAPTER *) NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_P2P_SWITCH_OP_MODE *prP2pSwitchMode = + (struct MSG_P2P_SWITCH_OP_MODE *) NULL; + uint8_t ucRoleIdx = 0; + uint8_t ucLoopCnt = 0; + + do { + if (wiphy == NULL) + break; + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_stop_ap.\n"); + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + if (prGlueInfo == NULL) { + DBGLOG(P2P, ERROR, "%s: prGlueInfo = NULL\n", __func__); + break; + } + + prAdapter = prGlueInfo->prAdapter; + if (prAdapter == NULL) { + DBGLOG(P2P, ERROR, "%s: prAdapter = NULL\n", __func__); + break; + } + + prAdapter->fgIsStopApDone = FALSE; + +#if (CFG_SUPPORT_DFS_MASTER == 1) + if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) { + netif_carrier_off(dev); + netif_tx_stop_all_queues(dev); + } +#endif + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + /* Switch OP MOde. */ + prP2pSwitchMode = cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(struct MSG_P2P_SWITCH_OP_MODE)); + + if (prP2pSwitchMode == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prP2pSwitchMode->rMsgHdr.eMsgId = MID_MNY_P2P_STOP_AP; + prP2pSwitchMode->ucRoleIdx = ucRoleIdx; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prP2pSwitchMode, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + while (prAdapter && !prAdapter->fgIsStopApDone) { + if (ucLoopCnt > 100) { + DBGLOG(P2P, ERROR, + "wait StopApDone timeout\n"); + break; + } + + ucLoopCnt++; + kalMsleep(1); + } + + 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) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + int32_t i4Rslt = 0; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_deauth.\n"); + + i4Rslt = mtk_p2p_cfg80211_disconnect(wiphy, dev, + req->reason_code); + return i4Rslt; +} /* mtk_p2p_cfg80211_deauth */ + +/* TODO: */ +int mtk_p2p_cfg80211_disassoc(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_disassoc_request *req) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_disassoc.\n"); + + /* not implemented yet */ + + return -EINVAL; +} /* mtk_p2p_cfg80211_disassoc */ + +int mtk_p2p_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, + unsigned int duration, u64 *cookie) +{ + int32_t i4Rslt = -EINVAL; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + struct GL_P2P_DEV_INFO *prGlueP2pDevInfo = + (struct GL_P2P_DEV_INFO *) NULL; + struct MSG_P2P_CHNL_REQUEST *prMsgChnlReq = + (struct MSG_P2P_CHNL_REQUEST *) NULL; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_remain_on_channel\n"); + + do { + if ((wiphy == NULL) || + /* (dev == NULL) || */ + (chan == NULL) || (cookie == NULL)) { + break; + } + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + prGlueP2pDevInfo = prGlueInfo->prP2PDevInfo; + + *cookie = prGlueP2pDevInfo->u8Cookie++; + + prMsgChnlReq = cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, sizeof(struct MSG_P2P_CHNL_REQUEST)); + + if (prMsgChnlReq == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + DBGLOG(P2P, INFO, + "Remain on channel, cookie: 0x%llx\n", + *cookie); + + prMsgChnlReq->rMsgHdr.eMsgId = MID_MNY_P2P_CHNL_REQ; + prMsgChnlReq->u8Cookie = *cookie; + prMsgChnlReq->u4Duration = duration; + prMsgChnlReq->eChnlReqType = CH_REQ_TYPE_P2P_LISTEN; + + mtk_p2p_cfg80211func_channel_format_switch(NULL, chan, + &prMsgChnlReq->rChannelInfo); + mtk_p2p_cfg80211func_channel_sco_switch(NL80211_CHAN_NO_HT, + &prMsgChnlReq->eChnlSco); + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prMsgChnlReq, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} + +/* mtk_p2p_cfg80211_remain_on_channel */ + +int mtk_p2p_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, u64 cookie) +{ + int32_t i4Rslt = -EINVAL; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL; + struct MSG_P2P_CHNL_ABORT *prMsgChnlAbort = + (struct MSG_P2P_CHNL_ABORT *) NULL; + + do { + if (wiphy == NULL /* || (dev == NULL) */) + break; + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + prGlueP2pInfo = prGlueInfo->prP2PInfo[0]; + + prMsgChnlAbort = cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, sizeof(struct MSG_P2P_CHNL_ABORT)); + + if (prMsgChnlAbort == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + DBGLOG(P2P, INFO, + "Cancel remain on channel, cookie: 0x%llx\n", cookie); + + prMsgChnlAbort->rMsgHdr.eMsgId = MID_MNY_P2P_CHNL_ABORT; + prMsgChnlAbort->u8Cookie = cookie; + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prMsgChnlAbort, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_cancel_remain_on_channel */ +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_P2P_MGMT_TX_REQUEST *prMsgTxReq = + (struct MSG_P2P_MGMT_TX_REQUEST *) NULL; + struct MSDU_INFO *prMgmtFrame = (struct MSDU_INFO *) NULL; + uint8_t *pucFrameBuf = (uint8_t *) NULL; + uint64_t *pu8GlCookie = (uint64_t *) NULL; + uint8_t ucRoleIdx = 0, ucBssIdx = 0; + struct net_device *dev = NULL; + + do { + if ((wiphy == NULL) || (wdev == NULL) + || (params == 0) || (cookie == NULL)) + break; + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_mgmt_tx\n"); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + /* The owner of this function please check following line*/ + prGlueP2pInfo = (struct GL_P2P_INFO *) prGlueInfo->prP2PInfo; + + dev = wdev->netdev; + + /* The owner of this function please check following line*/ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) { + /* Device Interface. */ + ucBssIdx = prGlueInfo->prAdapter->ucP2PDevBssIdx; + } else { + ASSERT(ucRoleIdx < KAL_P2P_NUM); + /* Role Interface. */ + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, + ucRoleIdx, &ucBssIdx) != WLAN_STATUS_SUCCESS) { + /* Can't find BSS index. */ + break; + } + } + /* The owner of this function please check following line*/ + *cookie = prGlueInfo->u8Cookie++; + + /* Channel & Channel Type & Wait time are ignored. */ + prMsgTxReq = cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, sizeof(struct MSG_P2P_MGMT_TX_REQUEST)); + + if (prMsgTxReq == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + if (params->offchan) { + DBGLOG(P2P, TRACE, " Off channel TRUE\n"); + prMsgTxReq->fgIsOffChannel = TRUE; + + mtk_p2p_cfg80211func_channel_format_switch(NULL, + params->chan, + &prMsgTxReq->rChannelInfo); + mtk_p2p_cfg80211func_channel_sco_switch( + NL80211_CHAN_NO_HT, + &prMsgTxReq->eChnlExt); + } else { + prMsgTxReq->fgIsOffChannel = FALSE; + } + + if (params->no_cck) + prMsgTxReq->fgNoneCckRate = TRUE; + else + prMsgTxReq->fgNoneCckRate = FALSE; + + if (params->dont_wait_for_ack) + prMsgTxReq->fgIsWaitRsp = FALSE; + else + prMsgTxReq->fgIsWaitRsp = TRUE; + prMgmtFrame = + cnmMgtPktAlloc(prGlueInfo->prAdapter, + (int32_t) + (params->len + sizeof(uint64_t) + + MAC_TX_RESERVED_FIELD)); + prMsgTxReq->prMgmtMsduInfo = prMgmtFrame; + if (prMsgTxReq->prMgmtMsduInfo == NULL) { + /* ASSERT(FALSE); */ + i4Rslt = -ENOMEM; + break; + } + + prMsgTxReq->u8Cookie = *cookie; + prMsgTxReq->rMsgHdr.eMsgId = MID_MNY_P2P_MGMT_TX; + prMsgTxReq->ucBssIdx = ucBssIdx; + + pucFrameBuf = + (uint8_t *) + ((unsigned long) prMgmtFrame->prPacket + + MAC_TX_RESERVED_FIELD); + + pu8GlCookie = + (uint64_t *) + ((unsigned long) prMgmtFrame->prPacket + + (unsigned long)params->len + + MAC_TX_RESERVED_FIELD); + + kalMemCopy(pucFrameBuf, params->buf, params->len); + + *pu8GlCookie = *cookie; + + prMgmtFrame->u2FrameLength = params->len; + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) 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 */ +#else +int mtk_p2p_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, bool offchan, + unsigned int wait, const u8 *buf, size_t len, + bool no_cck, bool dont_wait_for_ack, u64 *cookie) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + struct GL_P2P_DEV_INFO *prGlueP2pDevInfo = + (struct GL_P2P_DEV_INFO *) NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_P2P_MGMT_TX_REQUEST *prMsgTxReq = + (struct MSG_P2P_MGMT_TX_REQUEST *) NULL; + struct MSDU_INFO *prMgmtFrame = (struct MSDU_INFO *) NULL; + uint8_t *pucFrameBuf = (uint8_t *) NULL; + uint64_t *pu8GlCookie = (uint64_t *) NULL; + uint8_t ucRoleIdx = 0, ucBssIdx = 0; + struct net_device *dev = NULL; + + do { + if ((wiphy == NULL) || (buf == NULL) || (len == 0) || + /* (dev == NULL) || */ + (cookie == NULL)) { + break; + } + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_mgmt_tx\n"); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + prGlueP2pDevInfo = prGlueInfo->prP2PDevInfo; + + dev = wdev->netdev; + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) { + /* Device Interface. */ + ucBssIdx = prGlueInfo->prAdapter->ucP2PDevBssIdx; + } else { + ASSERT(ucRoleIdx < KAL_P2P_NUM); + /* Role Interface. */ + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, + ucRoleIdx, &ucBssIdx) < 0) { + /* Can't find BSS index. */ + break; + } + } + + *cookie = prGlueP2pDevInfo->u8Cookie++; + + /* Channel & Channel Type & Wait time are ignored. */ + prMsgTxReq = cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, sizeof(struct MSG_P2P_MGMT_TX_REQUEST)); + + if (prMsgTxReq == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + if (offchan) { + DBGLOG(P2P, TRACE, " Off channel TRUE\n"); + prMsgTxReq->fgIsOffChannel = TRUE; + + mtk_p2p_cfg80211func_channel_format_switch(NULL, chan, + &prMsgTxReq->rChannelInfo); + mtk_p2p_cfg80211func_channel_sco_switch( + NL80211_CHAN_NO_HT, &prMsgTxReq->eChnlExt); + } else { + prMsgTxReq->fgIsOffChannel = FALSE; + } + + if (no_cck) + prMsgTxReq->fgNoneCckRate = TRUE; + else + prMsgTxReq->fgNoneCckRate = FALSE; + + if (dont_wait_for_ack) + prMsgTxReq->fgIsWaitRsp = FALSE; + else + prMsgTxReq->fgIsWaitRsp = TRUE; + + prMgmtFrame = + cnmMgtPktAlloc(prGlueInfo->prAdapter, + (uint32_t) + (len + sizeof(uint64_t) + + MAC_TX_RESERVED_FIELD)); + + prMsgTxReq->prMgmtMsduInfo = prMgmtFrame; + if (prMsgTxReq->prMgmtMsduInfo == NULL) { + /* ASSERT(FALSE); */ + i4Rslt = -ENOMEM; + break; + } + + prMsgTxReq->u8Cookie = *cookie; + prMsgTxReq->rMsgHdr.eMsgId = MID_MNY_P2P_MGMT_TX; + prMsgTxReq->ucBssIdx = ucBssIdx; + + pucFrameBuf = + (uint8_t *) + ((unsigned long) prMgmtFrame->prPacket + + MAC_TX_RESERVED_FIELD); + + pu8GlCookie = + (uint64_t *) + ((unsigned long) prMgmtFrame->prPacket + + (unsigned long) len + + MAC_TX_RESERVED_FIELD); + + kalMemCopy(pucFrameBuf, buf, len); + + *pu8GlCookie = *cookie; + DBGLOG(P2P, INFO, + "cfg80211: Tx frame with cookie: 0x%llx\n", + *cookie); + + prMgmtFrame->u2FrameLength = len; + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) 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 */ +#endif + +int mtk_p2p_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct wireless_dev *wdev, u64 cookie) +{ + int32_t i4Rslt = -EINVAL; + + DBGLOG(P2P, INFO, "%s: not support now\n", __func__); + return i4Rslt; +} /* mtk_p2p_cfg80211_mgmt_tx_cancel_wait */ + +int mtk_p2p_cfg80211_change_bss(struct wiphy *wiphy, + struct net_device *dev, + struct bss_parameters *params) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + int32_t i4Rslt = -EINVAL; + + ASSERT(wiphy); + + DBGLOG(P2P, INFO, "%s\n", __func__); + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + 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 */ + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +#if KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE +static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, + struct station_del_parameters *params) +{ + const u8 *mac = params->mac ? params->mac : bcast_addr; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_P2P_CONNECTION_ABORT *prDisconnectMsg = + (struct MSG_P2P_CONNECTION_ABORT *) NULL; + uint8_t aucBcMac[] = BC_MAC_ADDR; + uint8_t ucRoleIdx = 0; + + do { + if ((wiphy == NULL) || (dev == NULL)) + break; + + if (mac == NULL) + mac = aucBcMac; + + DBGLOG(P2P, INFO, + "mtk_p2p_cfg80211_del_station " MACSTR ". reason: %d\n", + MAC2STR(mac), params->reason_code); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + /* prDisconnectMsg = (struct MSG_P2P_CONNECTION_ABORT *) + * kalMemAlloc(sizeof(struct MSG_P2P_CONNECTION_ABORT), + * VIR_MEM_TYPE); + */ + + prDisconnectMsg = (struct MSG_P2P_CONNECTION_ABORT *) + cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_P2P_CONNECTION_ABORT)); + + if (prDisconnectMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prDisconnectMsg->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT; + prDisconnectMsg->ucRoleIdx = ucRoleIdx; + COPY_MAC_ADDR(prDisconnectMsg->aucTargetID, mac); + prDisconnectMsg->u2ReasonCode = params->reason_code; + prDisconnectMsg->fgSendDeauth = TRUE; + + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prDisconnectMsg, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; + +} /* mtk_p2p_cfg80211_del_station */ +#else +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, const u8 *mac) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_P2P_CONNECTION_ABORT *prDisconnectMsg = + (struct MSG_P2P_CONNECTION_ABORT *) NULL; + uint8_t aucBcMac[] = BC_MAC_ADDR; + uint8_t ucRoleIdx = 0; + + do { + if ((wiphy == NULL) || (dev == NULL)) + break; + + if (mac == NULL) + mac = aucBcMac; + + DBGLOG(P2P, INFO, + "mtk_p2p_cfg80211_del_station " MACSTR ".\n", + MAC2STR(mac)); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + /* prDisconnectMsg = (struct MSG_P2P_CONNECTION_ABORT *) + * kalMemAlloc(sizeof(struct MSG_P2P_CONNECTION_ABORT), + * VIR_MEM_TYPE); + */ + + prDisconnectMsg = (struct MSG_P2P_CONNECTION_ABORT *) + cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_P2P_CONNECTION_ABORT)); + + if (prDisconnectMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prDisconnectMsg->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT; + prDisconnectMsg->ucRoleIdx = ucRoleIdx; + COPY_MAC_ADDR(prDisconnectMsg->aucTargetID, mac); + prDisconnectMsg->u2ReasonCode = REASON_CODE_UNSPECIFIED; + prDisconnectMsg->fgSendDeauth = TRUE; + + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prDisconnectMsg, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; + +} /* mtk_p2p_cfg80211_del_station */ +#endif +#else +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, u8 *mac) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_P2P_CONNECTION_ABORT *prDisconnectMsg = + (struct MSG_P2P_CONNECTION_ABORT *) NULL; + uint8_t aucBcMac[] = BC_MAC_ADDR; + uint8_t ucRoleIdx = 0; + + do { + if ((wiphy == NULL) || (dev == NULL)) + break; + + if (mac == NULL) + mac = aucBcMac; + + DBGLOG(P2P, INFO, + "mtk_p2p_cfg80211_del_station " MACSTR ".\n", + MAC2STR(mac)); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + /* prDisconnectMsg = (struct MSG_P2P_CONNECTION_ABORT *) + * kalMemAlloc(sizeof(struct MSG_P2P_CONNECTION_ABORT), + * VIR_MEM_TYPE); + */ + + prDisconnectMsg = + (struct MSG_P2P_CONNECTION_ABORT *) + cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_P2P_CONNECTION_ABORT)); + + if (prDisconnectMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prDisconnectMsg->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT; + prDisconnectMsg->ucRoleIdx = ucRoleIdx; + COPY_MAC_ADDR(prDisconnectMsg->aucTargetID, mac); + prDisconnectMsg->u2ReasonCode = REASON_CODE_UNSPECIFIED; + prDisconnectMsg->fgSendDeauth = TRUE; + + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prDisconnectMsg, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; + +} /* mtk_p2p_cfg80211_del_station */ +#endif + +int mtk_p2p_cfg80211_connect(struct wiphy *wiphy, + struct net_device *dev, struct cfg80211_connect_params *sme) +{ + int32_t i4Rslt = -EINVAL; + struct GLUE_INFO *prGlueInfo = NULL; + struct MSG_P2P_CONNECTION_REQUEST *prConnReqMsg = + (struct MSG_P2P_CONNECTION_REQUEST *) NULL; + uint8_t ucRoleIdx = 0; + const u8 *bssid = NULL; + struct ieee80211_channel *channel = NULL; + struct cfg80211_bss *bss = NULL; + + do { + if ((wiphy == NULL) || (dev == NULL) || (sme == NULL)) + break; + + if (sme->bssid) + bssid = sme->bssid; +#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE + else if (sme->bssid_hint) + bssid = sme->bssid_hint; +#endif + if (sme->channel) + channel = sme->channel; +#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE + else if (sme->channel_hint) + channel = sme->channel_hint; +#endif + + if ((bssid == NULL) || (channel == NULL)) { +#if KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE + bss = cfg80211_get_bss(wiphy, NULL, NULL, + sme->ssid, sme->ssid_len, + IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY); +#else + bss = cfg80211_get_bss(wiphy, NULL, NULL, + sme->ssid, sme->ssid_len, + WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); +#endif + if (bss == NULL) { + DBGLOG(P2P, ERROR, + "Reject connect without bssid/channel/bss.\n"); + break; + } + + bssid = bss->bssid; + channel = bss->channel; + + if ((bssid == NULL) || (channel == NULL)) { + DBGLOG(P2P, ERROR, + "Reject connect: no bssid/channel in bss.\n"); + break; + } + } + + DBGLOG(P2P, INFO, + "bssid: " MACSTR ", band: %d, freq: %d.\n", + MAC2STR(bssid), channel->band, channel->center_freq); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + + prConnReqMsg = + (struct MSG_P2P_CONNECTION_REQUEST *) + cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + (sizeof(struct MSG_P2P_CONNECTION_REQUEST) + + sme->ie_len)); + + if (prConnReqMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prConnReqMsg->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_REQ; + prConnReqMsg->ucRoleIdx = ucRoleIdx; + + COPY_SSID(prConnReqMsg->rSsid.aucSsid, + prConnReqMsg->rSsid.ucSsidLen, + sme->ssid, sme->ssid_len); + + COPY_MAC_ADDR(prConnReqMsg->aucBssid, bssid); + COPY_MAC_ADDR(prConnReqMsg->aucSrcMacAddr, dev->dev_addr); + + DBGLOG(P2P, TRACE, + "Assoc Req IE Buffer Length:%zu\n", sme->ie_len); + + kalMemCopy(prConnReqMsg->aucIEBuf, sme->ie, sme->ie_len); + prConnReqMsg->u4IELen = sme->ie_len; + + kalP2PSetCipher(prGlueInfo, IW_AUTH_CIPHER_NONE, ucRoleIdx); + + if (sme->crypto.n_ciphers_pairwise) { + switch (sme->crypto.ciphers_pairwise[0]) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + kalP2PSetCipher(prGlueInfo, + IW_AUTH_CIPHER_WEP40, ucRoleIdx); + break; + case WLAN_CIPHER_SUITE_TKIP: + kalP2PSetCipher(prGlueInfo, + IW_AUTH_CIPHER_TKIP, ucRoleIdx); + break; + case WLAN_CIPHER_SUITE_CCMP: + case WLAN_CIPHER_SUITE_AES_CMAC: + kalP2PSetCipher(prGlueInfo, + IW_AUTH_CIPHER_CCMP, ucRoleIdx); + break; + default: + cnmMemFree(prGlueInfo->prAdapter, prConnReqMsg); + DBGLOG(REQ, WARN, + "invalid cipher pairwise (%d)\n", + sme->crypto.ciphers_pairwise[0]); + /* do cfg80211_put_bss before return */ + if (bss) + cfg80211_put_bss(wiphy, bss); + return -EINVAL; + } + } + + mtk_p2p_cfg80211func_channel_format_switch(NULL, channel, + &prConnReqMsg->rChannelInfo); + mtk_p2p_cfg80211func_channel_sco_switch( + NL80211_CHAN_NO_HT, &prConnReqMsg->eChnlSco); + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prConnReqMsg, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + /* do cfg80211_put_bss before return */ + if (bss) + cfg80211_put_bss(wiphy, bss); + + return i4Rslt; +} /* mtk_p2p_cfg80211_connect */ + +int mtk_p2p_cfg80211_disconnect(struct wiphy *wiphy, + struct net_device *dev, u16 reason_code) +{ + int32_t i4Rslt = -EINVAL; + struct GLUE_INFO *prGlueInfo = NULL; + struct MSG_P2P_CONNECTION_ABORT *prDisconnMsg = + (struct MSG_P2P_CONNECTION_ABORT *) NULL; + uint8_t aucBCAddr[] = BC_MAC_ADDR; + uint8_t ucRoleIdx = 0; + + do { + if ((wiphy == NULL) || (dev == NULL)) + break; + + DBGLOG(P2P, INFO, + "mtk_p2p_cfg80211_disconnect reason: %d.\n", + reason_code); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; +/* prDisconnMsg = (P_MSG_P2P_CONNECTION_ABORT_T) + * MemAlloc(sizeof(P_MSG_P2P_CONNECTION_ABORT_T), VIR_MEM_TYPE); + */ + prDisconnMsg = + (struct MSG_P2P_CONNECTION_ABORT *) + cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_P2P_CONNECTION_ABORT)); + + if (prDisconnMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prDisconnMsg->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT; + prDisconnMsg->ucRoleIdx = ucRoleIdx; + prDisconnMsg->u2ReasonCode = reason_code; + prDisconnMsg->fgSendDeauth = TRUE; + COPY_MAC_ADDR(prDisconnMsg->aucTargetID, aucBCAddr); + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prDisconnMsg, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_disconnect */ + +int +mtk_p2p_cfg80211_change_iface(IN struct wiphy *wiphy, + IN struct net_device *ndev, + IN enum nl80211_iftype type, + IN u32 *flags, + IN struct vif_params *params) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + int32_t i4Rslt = -EINVAL; + struct MSG_P2P_SWITCH_OP_MODE *prSwitchModeMsg = + (struct MSG_P2P_SWITCH_OP_MODE *) NULL; + uint8_t ucRoleIdx = 0; + + do { + if ((wiphy == NULL) || (ndev == NULL)) { + DBGLOG(P2P, ERROR, "wiphy=%p, ndev=%p.\n", wiphy, ndev); + break; + } + + DBGLOG(P2P, INFO, + "mtk_p2p_cfg80211_change_iface, type: %d\n", type); + + if (ndev->ieee80211_ptr) + ndev->ieee80211_ptr->iftype = type; + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, ndev, &ucRoleIdx) != 0) { + DBGLOG(P2P, TRACE, + "Device Interface no need to change interface type.\n"); + return 0; + } + /* Switch OP MOde. */ + prSwitchModeMsg = + (struct MSG_P2P_SWITCH_OP_MODE *) + cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_P2P_SWITCH_OP_MODE)); + + if (prSwitchModeMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prSwitchModeMsg->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; + prSwitchModeMsg->ucRoleIdx = ucRoleIdx; + + switch (type) { + case NL80211_IFTYPE_P2P_CLIENT: + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_P2P_CLIENT.\n"); + prSwitchModeMsg->eIftype = IFTYPE_P2P_CLIENT; + /* This case need to fall through */ + case NL80211_IFTYPE_STATION: + if (type == NL80211_IFTYPE_STATION) { + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_STATION.\n"); + prSwitchModeMsg->eIftype = IFTYPE_STATION; + } + prSwitchModeMsg->eOpMode = OP_MODE_INFRASTRUCTURE; + kalP2PSetRole(prGlueInfo, 1, ucRoleIdx); + break; + case NL80211_IFTYPE_AP: + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_AP.\n"); + kalP2PSetRole(prGlueInfo, 2, ucRoleIdx); + prSwitchModeMsg->eIftype = IFTYPE_AP; + /* This case need to fall through */ + case NL80211_IFTYPE_P2P_GO: + if (type == NL80211_IFTYPE_P2P_GO) { + DBGLOG(P2P, TRACE, + "NL80211_IFTYPE_P2P_GO not AP.\n"); + prSwitchModeMsg->eIftype = IFTYPE_P2P_GO; + } + prSwitchModeMsg->eOpMode = OP_MODE_ACCESS_POINT; + kalP2PSetRole(prGlueInfo, 2, ucRoleIdx); + break; + default: + DBGLOG(P2P, TRACE, "Other type :%d .\n", type); + prSwitchModeMsg->eOpMode = OP_MODE_P2P_DEVICE; + kalP2PSetRole(prGlueInfo, 0, ucRoleIdx); + prSwitchModeMsg->eIftype = IFTYPE_P2P_DEVICE; + break; + } + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prSwitchModeMsg, + MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + + } while (FALSE); + + return i4Rslt; + +} /* mtk_p2p_cfg80211_change_iface */ + +int mtk_p2p_cfg80211_set_channel(IN struct wiphy *wiphy, + struct cfg80211_chan_def *chandef) +{ + int32_t i4Rslt = -EINVAL; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + struct RF_CHANNEL_INFO rRfChnlInfo; + uint8_t ucRoleIdx = 0; + struct net_device *dev = NULL; + + if ((wiphy == NULL) || (chandef == NULL)) + return i4Rslt; + + dev = (struct net_device *) wiphy_dev(wiphy); + + do { + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_set_channel.\n"); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + mtk_p2p_cfg80211func_channel_format_switch( + chandef, chandef->chan, &rRfChnlInfo); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + + p2pFuncSetChannel(prGlueInfo->prAdapter, + ucRoleIdx, &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) +{ + int32_t i4Rslt = -EINVAL; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + + do { + if ((wiphy == NULL) || (dev == NULL) || (mask == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_set_bitrate_mask\n"); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + /* TODO: Set bitrate mask of the peer? */ + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_set_bitrate_mask */ + +void mtk_p2p_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, + struct wireless_dev *wdev, + IN u16 frame_type, IN bool reg) +{ +#if 0 + struct MSG_P2P_MGMT_FRAME_REGISTER *prMgmtFrameRegister = + (struct MSG_P2P_MGMT_FRAME_REGISTER *) NULL; +#endif + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + uint8_t ucRoleIdx = 0; + uint32_t *pu4P2pPacketFilter = NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + + do { + if ((wiphy == NULL) || (wdev == NULL)) + break; + + DBGLOG(P2P, TRACE, "netdev: 0x%p, frame_type: 0x%x, reg: %d\n", + wdev->netdev, frame_type, reg); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + /* since p2p device share the aprRoleHandler + * so needs to check DevHandler 1st + */ + if (prGlueInfo->prP2PInfo[0]->prDevHandler == wdev->netdev) { + /* P2P device*/ + pu4P2pPacketFilter = + &prGlueInfo->prP2PDevInfo->u4OsMgmtFrameFilter; + } else { + if (mtk_Netdev_To_RoleIdx(prGlueInfo, + wdev->netdev, &ucRoleIdx) < 0) { + DBGLOG(P2P, WARN, "wireless dev match fail!\n"); + break; + } else { + /* Non P2P device*/ + ASSERT(ucRoleIdx < KAL_P2P_NUM); + DBGLOG(P2P, TRACE, + "Open packet filer RoleIdx %u\n", + ucRoleIdx); + prP2pRoleFsmInfo = + prGlueInfo->prAdapter + ->rWifiVar.aprP2pRoleFsmInfo[ucRoleIdx]; + pu4P2pPacketFilter = + &prP2pRoleFsmInfo->u4P2pPacketFilter; + } + } + switch (frame_type) { + case MAC_FRAME_PROBE_REQ: + if (reg) { + *pu4P2pPacketFilter + |= PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(P2P, TRACE, + "Open packet filer probe request\n"); + } else { + *pu4P2pPacketFilter + &= ~PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(P2P, TRACE, + "Close packet filer probe request\n"); + } + break; + case MAC_FRAME_ACTION: + if (reg) { + *pu4P2pPacketFilter + |= PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(P2P, TRACE, + "Open packet filer action frame.\n"); + } else { + *pu4P2pPacketFilter + &= ~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; + } + + set_bit(GLUE_FLAG_FRAME_FILTER_BIT, &prGlueInfo->ulFlag); + + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + + if (in_interrupt()) + DBGLOG(P2P, TRACE, "It is in interrupt level\n"); +#if 0 + + prMgmtFrameRegister = + (struct MSG_P2P_MGMT_FRAME_REGISTER *) + cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_P2P_MGMT_FRAME_REGISTER)); + + 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, + (struct MSG_HDR *) prMgmtFrameRegister, + MSG_SEND_METHOD_BUF); + +#endif + + } while (FALSE); + +} /* mtk_p2p_cfg80211_mgmt_frame_register */ + +#ifdef CONFIG_NL80211_TESTMODE + +#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_testmode_cmd(struct wiphy *wiphy, + struct wireless_dev *wdev, void *data, + int len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct NL80211_DRIVER_TEST_PARAMS *prParams = + (struct NL80211_DRIVER_TEST_PARAMS *) NULL; + int32_t i4Status = -EINVAL; + + ASSERT(wiphy); + ASSERT(wdev); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_testmode_cmd\n"); + + if (data && len) { + prParams = (struct NL80211_DRIVER_TEST_PARAMS *) data; + } else { + DBGLOG(P2P, ERROR, + "mtk_p2p_cfg80211_testmode_cmd, data is NULL\n"); + return i4Status; + } + if (prParams->index >> 24 == 0x01) { + /* New version */ + prParams->index = prParams->index & ~BITS(24, 31); + } else { + /* Old version */ + mtk_p2p_cfg80211_testmode_p2p_sigma_pre_cmd(wiphy, data, len); + i4Status = 0; + return i4Status; + } + + /* Clear the version byte */ + prParams->index = prParams->index & ~BITS(24, 31); + + if (prParams) { + switch (prParams->index) { + case 1: /* P2P Simga */ +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION + { + struct NL80211_DRIVER_SW_CMD_PARAMS + *prParamsCmd; + + prParamsCmd = + (struct NL80211_DRIVER_SW_CMD_PARAMS *) + data; + + if ((prParamsCmd->adr & 0xffff0000) + == 0xffff0000) { + i4Status = + mtk_p2p_cfg80211_testmode_sw_cmd( + wiphy, data, len); + break; + } + } +#endif + i4Status = mtk_p2p_cfg80211_testmode_p2p_sigma_cmd( + wiphy, data, len); + break; + case 2: /* WFD */ +#if CFG_SUPPORT_WFD + /* use normal driver command wifi_display */ + /* i4Status = + * mtk_p2p_cfg80211_testmode_wfd_update_cmd( + * wiphy, data, len); + */ +#endif + break; + case 3: /* Hotspot Client Management */ +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + i4Status = + mtk_p2p_cfg80211_testmode_hotspot_block_list_cmd( + wiphy, data, len); +#endif + break; + case 0x10: + i4Status = + mtk_cfg80211_testmode_get_sta_statistics( + wiphy, data, len, prGlueInfo); + break; +#if CFG_SUPPORT_NFC_BEAM_PLUS + case 0x11: /*NFC Beam + Indication */ + if (data && len) { + struct NL80211_DRIVER_SET_NFC_PARAMS *prParams = + (struct NL80211_DRIVER_SET_NFC_PARAMS *) + data; + + DBGLOG(P2P, INFO, + "NFC: BEAM[%d]\n", + prParams->NFC_Enable); + } + break; + case 0x12: /*NFC Beam + Indication */ + DBGLOG(P2P, INFO, "NFC: Polling\n"); + i4Status = + mtk_cfg80211_testmode_get_scan_done( + wiphy, data, len, prGlueInfo); + break; +#endif +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + case 0x30: + i4Status = + mtk_p2p_cfg80211_testmode_get_best_channel( + wiphy, data, len); + break; +#endif + case TESTMODE_CMD_ID_HS_CONFIG: + i4Status = + mtk_p2p_cfg80211_testmode_hotspot_config_cmd( + wiphy, data, len); + break; + + default: + i4Status = -EINVAL; + break; + } + } + + return i4Status; + +} +#else +int mtk_p2p_cfg80211_testmode_cmd(struct wiphy *wiphy, void *data, int len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct NL80211_DRIVER_TEST_PARAMS *prParams = + (struct NL80211_DRIVER_TEST_PARAMS *) NULL; + int32_t i4Status = -EINVAL; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_testmode_cmd\n"); + + if (data && len) { + prParams = (struct NL80211_DRIVER_TEST_PARAMS *) data; + } else { + DBGLOG(P2P, ERROR, "data is NULL\n"); + return i4Status; + } + 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); + i4Status = 0; + return i4Status; + } + + /* Clear the version byte */ + prParams->index = prParams->index & ~BITS(24, 31); + + if (prParams) { + switch (prParams->index) { + case 1: /* P2P Simga */ +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION + { + struct NL80211_DRIVER_SW_CMD_PARAMS + *prParamsCmd; + + prParamsCmd = + (struct NL80211_DRIVER_SW_CMD_PARAMS *) + data; + + if ((prParamsCmd->adr & 0xffff0000) + == 0xffff0000) { + i4Status = + mtk_p2p_cfg80211_testmode_sw_cmd( + wiphy, data, len); + break; + } + } +#endif + i4Status = mtk_p2p_cfg80211_testmode_p2p_sigma_cmd( + wiphy, data, len); + break; + case 2: /* WFD */ +#if CFG_SUPPORT_WFD + /* use normal driver command wifi_display */ + /* i4Status = mtk_p2p_cfg80211_testmode_wfd_update_cmd( + * wiphy, data, len); + */ +#endif + break; + case 3: /* Hotspot Client Management */ +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + i4Status = + mtk_p2p_cfg80211_testmode_hotspot_block_list_cmd( + wiphy, data, len); +#endif + break; + case 0x10: + i4Status = + mtk_cfg80211_testmode_get_sta_statistics( + wiphy, data, len, prGlueInfo); + break; +#if CFG_SUPPORT_NFC_BEAM_PLUS + case 0x11: /*NFC Beam + Indication */ + if (data && len) { + struct NL80211_DRIVER_SET_NFC_PARAMS *prParams = + (struct NL80211_DRIVER_SET_NFC_PARAMS *) + data; + + DBGLOG(P2P, INFO, + "NFC: BEAM[%d]\n", + prParams->NFC_Enable); + } + break; + case 0x12: /*NFC Beam + Indication */ + DBGLOG(P2P, INFO, "NFC: Polling\n"); + i4Status = + mtk_cfg80211_testmode_get_scan_done( + wiphy, data, len, prGlueInfo); + break; +#endif +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + case 0x30: /* Auto channel selection in LTE safe channels */ + i4Status = + mtk_p2p_cfg80211_testmode_get_best_channel( + wiphy, data, len); + break; +#endif + case TESTMODE_CMD_ID_HS_CONFIG: + i4Status = + mtk_p2p_cfg80211_testmode_hotspot_config_cmd( + wiphy, data, len); + break; + + default: + i4Status = -EINVAL; + break; + } + } + + return i4Status; + +} +#endif + +int mtk_p2p_cfg80211_testmode_hotspot_config_cmd(IN struct wiphy *wiphy, + IN void *data, IN int len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct NL80211_DRIVER_HOTSPOT_CONFIG_PARAMS *prParams = + (struct NL80211_DRIVER_HOTSPOT_CONFIG_PARAMS *) NULL; + uint32_t index; + uint32_t value; + uint32_t i; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (data && len) { + prParams = (struct NL80211_DRIVER_HOTSPOT_CONFIG_PARAMS *) data; + } else { + DBGLOG(P2P, ERROR, "data is NULL or len is 0\n"); + return -EINVAL; + } + + index = prParams->idx; + value = prParams->value; + + DBGLOG(P2P, INFO, "NL80211_ATTR_TESTDATA, idx=%d value=%d\n", + (uint32_t) prParams->idx, (uint32_t) prParams->value); + + switch (index) { + case 1: /* Max Clients */ + for (i = 0; i < KAL_P2P_NUM; i++) + kalP2PSetMaxClients(prGlueInfo, value, i); + break; + default: + break; + } + + return 0; +} + +int mtk_p2p_cfg80211_testmode_p2p_sigma_pre_cmd(IN struct wiphy *wiphy, + IN void *data, IN int len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct NL80211_DRIVER_TEST_PRE_PARAMS rParams; + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo = + (struct P2P_SPECIFIC_BSS_INFO *) NULL; + /* P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = + * (P_P2P_CONNECTION_SETTINGS_T)NULL; + */ + uint32_t index_mode; + uint32_t index; + int32_t value; + int status = 0; + uint32_t u4Leng; + uint8_t ucBssIdx; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + kalMemZero(&rParams, sizeof(struct NL80211_DRIVER_TEST_PRE_PARAMS)); + + prP2pSpecificBssInfo = + prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo[0]; + /* prP2pConnSettings = + * prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings; + */ + + if (data && len) + memcpy(&rParams, data, len); + + DBGLOG(P2P, TRACE, + "NL80211_ATTR_TESTDATA, idx_mode=%d idx=%d value=%u\n", + rParams.idx_mode, + rParams.idx, + rParams.value); + + index_mode = rParams.idx_mode; + index = rParams.idx; + value = rParams.value; + + /* 3 FIX ME: Add p2p role index selection */ + if (p2pFuncRoleToBssIdx( + prGlueInfo->prAdapter, 0, &ucBssIdx) != WLAN_STATUS_SUCCESS) + return -EINVAL; + + 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 */ + { + struct PARAM_POWER_MODE_ rPowerMode; + + rPowerMode.ePowerMode = Param_PowerModeMAX_PSP; + rPowerMode.ucBssIdx = ucBssIdx; + + kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, + sizeof(rPowerMode), + FALSE, FALSE, 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 */ + { + struct PARAM_POWER_MODE_ rPowerMode; + + rPowerMode.ePowerMode = value; + rPowerMode.ucBssIdx = ucBssIdx; + + kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, + sizeof(rPowerMode), + FALSE, FALSE, 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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct NL80211_DRIVER_P2P_SIGMA_PARAMS *prParams = + (struct NL80211_DRIVER_P2P_SIGMA_PARAMS *) NULL; + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo = + (struct P2P_SPECIFIC_BSS_INFO *) NULL; + /* P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = + * (P_P2P_CONNECTION_SETTINGS_T)NULL; + */ + uint32_t index; + int32_t value; + int status = 0; + uint32_t u4Leng; + uint8_t ucBssIdx; + uint32_t i; + struct NL80211_DRIVER_P2P_NOA_PARAMS { + struct NL80211_DRIVER_TEST_PARAMS hdr; + uint32_t idx; + uint32_t value; /* should not be used in this case */ + uint32_t count; + uint32_t interval; + uint32_t duration; + }; + struct NL80211_DRIVER_P2P_NOA_PARAMS *prNoaParams = NULL; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + prP2pSpecificBssInfo = + prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo[0]; + /* prP2pConnSettings = + * prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings; + */ + + if (data && len) + prParams = (struct NL80211_DRIVER_P2P_SIGMA_PARAMS *) data; + else { + DBGLOG(P2P, ERROR, "data is NULL\n"); + return -EINVAL; + } + + index = (int32_t) prParams->idx; + value = (int32_t) prParams->value; + + DBGLOG(P2P, INFO, "NL80211_ATTR_TESTDATA, idx=%u value=%u\n", + prParams->idx, prParams->value); + + /* 3 FIX ME: Add p2p role index selection */ + if (p2pFuncRoleToBssIdx( + prGlueInfo->prAdapter, 0, &ucBssIdx) != WLAN_STATUS_SUCCESS) + return -EINVAL; + + switch (index) { + case 0: /* Listen CH */ + break; + case 1: /* P2p mode */ + break; + case 4: /* Noa duration */ + prNoaParams = data; + prP2pSpecificBssInfo->rNoaParam.u4NoaCount = prNoaParams->count; + prP2pSpecificBssInfo->rNoaParam.u4NoaIntervalMs = + prNoaParams->interval; + prP2pSpecificBssInfo->rNoaParam.u4NoaDurationMs = + prNoaParams->duration; + prP2pSpecificBssInfo->rNoaParam.ucBssIdx = + ucBssIdx; + DBGLOG(P2P, INFO, + "SET NOA[%d]: %d %d %d\n", + ucBssIdx, + prNoaParams->count, + prNoaParams->interval, + prNoaParams->duration); + + /* only to apply setting when setting NOA count */ + kalIoctl(prGlueInfo, + wlanoidSetNoaParam, + &prP2pSpecificBssInfo->rNoaParam, + sizeof(struct PARAM_CUSTOM_NOA_PARAM_STRUCT), + FALSE, FALSE, TRUE, &u4Leng); + 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 */ + { + struct PARAM_POWER_MODE_ rPowerMode; + + rPowerMode.ePowerMode = Param_PowerModeMAX_PSP; + rPowerMode.ucBssIdx = ucBssIdx; + + kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, + sizeof(rPowerMode), + FALSE, FALSE, TRUE, &u4Leng); + } + break; + case 107: /* P2P set opps, CTWindowl */ + prP2pSpecificBssInfo->rOppPsParam.u4CTwindowMs = value; + prP2pSpecificBssInfo->rOppPsParam.ucBssIdx = ucBssIdx; + DBGLOG(P2P, INFO, "SET OPPS[%d]: %d\n", ucBssIdx, value); + kalIoctl(prGlueInfo, + wlanoidSetOppPsParam, + &prP2pSpecificBssInfo->rOppPsParam, + sizeof(struct PARAM_CUSTOM_OPPPS_PARAM_STRUCT), + FALSE, FALSE, TRUE, &u4Leng); + break; + case 108: /* p2p_set_power_save */ + { + struct PARAM_POWER_MODE_ rPowerMode; + + rPowerMode.ePowerMode = value; + rPowerMode.ucBssIdx = ucBssIdx; + + kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, sizeof(rPowerMode), + FALSE, FALSE, TRUE, &u4Leng); + } + break; + case 109: /* Max Clients */ +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + for (i = 0; i < KAL_P2P_NUM; i++) + kalP2PSetMaxClients(prGlueInfo, value, i); +#endif + break; + case 110: /* Hotspot WPS mode */ +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + kalIoctl(prGlueInfo, + wlanoidSetP2pWPSmode, + &value, sizeof(value), + FALSE, FALSE, TRUE, &u4Leng); +#endif + break; + default: + break; + } + + return status; + +} + +#if CFG_SUPPORT_WFD && 0 +/* obsolete/decrepated */ +int mtk_p2p_cfg80211_testmode_wfd_update_cmd(IN struct wiphy *wiphy, + IN void *data, IN int len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct NL80211_DRIVER_WFD_PARAMS *prParams = + (struct NL80211_DRIVER_WFD_PARAMS *) NULL; + int status = 0; + struct WFD_CFG_SETTINGS *prWfdCfgSettings = + (struct WFD_CFG_SETTINGS *) NULL; + struct MSG_WFD_CONFIG_SETTINGS_CHANGED *prMsgWfdCfgUpdate = + (struct MSG_WFD_CONFIG_SETTINGS_CHANGED *) NULL; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + prParams = (struct 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.rWfdConfigureSettings); + + kalMemCopy(&prWfdCfgSettings->u4WfdCmdType, + &prParams->WfdCmdType, + sizeof(struct WFD_CFG_SETTINGS)); + + prMsgWfdCfgUpdate = cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_WFD_CONFIG_SETTINGS_CHANGED)); + + 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, + (struct MSG_HDR *) 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; + { + uint8_t 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 */ + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + +int mtk_p2p_cfg80211_testmode_hotspot_block_list_cmd(IN struct wiphy *wiphy, + IN void *data, IN int len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct NL80211_DRIVER_hotspot_block_PARAMS *prParams = + (struct NL80211_DRIVER_hotspot_block_PARAMS *) NULL; + int fgIsValid = 0; + uint32_t i; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (data && len) + prParams = (struct NL80211_DRIVER_hotspot_block_PARAMS *) data; + else + return fgIsValid; + + DBGLOG(P2P, INFO, + "%s" MACSTR "\n", + prParams->ucblocked?"Block":"Unblock", + MAC2STR(prParams->aucBssid)); + + for (i = 0; i < KAL_P2P_NUM; i++) + fgIsValid |= + kalP2PSetBlackList(prGlueInfo, + prParams->aucBssid, prParams->ucblocked, i); + + return fgIsValid; + +} + +#endif + +int mtk_p2p_cfg80211_testmode_sw_cmd(IN struct wiphy *wiphy, + IN void *data, IN int len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct NL80211_DRIVER_SW_CMD_PARAMS *prParams = + (struct NL80211_DRIVER_SW_CMD_PARAMS *) NULL; + uint32_t rstatus = WLAN_STATUS_SUCCESS; + int fgIsValid = 0; + uint32_t u4SetInfoLen = 0; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + DBGLOG(P2P, TRACE, "--> %s()\n", __func__); + + if (data && len) + prParams = (struct NL80211_DRIVER_SW_CMD_PARAMS *) data; + + if (prParams) { + if (prParams->set == 1) { + rstatus = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC) wlanoidSetSwCtrlWrite, + &prParams->adr, (uint32_t) 8, + FALSE, FALSE, TRUE, &u4SetInfoLen); + } + } + + if (rstatus != WLAN_STATUS_SUCCESS) + fgIsValid = -EFAULT; + + return fgIsValid; +} + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +/* Move to global to fix build error + * Cannot allocate big array in local function + * which will cause stack overflow. + * GCC option: -Werror=frame-larget-than + */ +/* For ACS information print */ +int8_t acLogChannel[ACS_PRINT_BUFFER_LEN]; +int8_t acLogAPNum[ACS_PRINT_BUFFER_LEN]; +int8_t acLogScore[ACS_PRINT_BUFFER_LEN]; + +int mtk_p2p_cfg80211_testmode_get_best_channel(IN struct wiphy *wiphy, + IN void *data, IN int len) +{ + + struct sk_buff *skb; + + u_int8_t fgIsReady = FALSE; + + struct GLUE_INFO *prGlueInfo = NULL; + struct RF_CHANNEL_INFO aucChannelList[MAX_2G_BAND_CHN_NUM]; + uint8_t ucNumOfChannel, i, ucIdx; + uint16_t u2APNumScore = 0, u2UpThreshold = 0, + u2LowThreshold = 0, ucInnerIdx = 0; + uint32_t u4BufLen, u4LteSafeChnBitMask_2G = 0; + uint32_t u4AcsChnReport[5]; + + struct PARAM_GET_CHN_INFO *prGetChnLoad, *prQueryLteChn; + struct PARAM_PREFER_CHN_INFO rPreferChannel = { 0, 0xFFFF, 0 }; + struct PARAM_PREFER_CHN_INFO + arChannelDirtyScore_2G[MAX_2G_BAND_CHN_NUM]; + + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + ASSERT(wiphy); + + P2P_WIPHY_PRIV(wiphy, prGlueInfo); + + if (!prGlueInfo) { + DBGLOG(P2P, ERROR, "prGlueInfo is NULL\n"); + return -EFAULT; + } + + /* Prepare reply skb buffer */ + skb = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(u4AcsChnReport)); + if (!skb) { + DBGLOG(P2P, ERROR, "Allocate skb failed\n"); + return -ENOMEM; + } + + kalMemZero(u4AcsChnReport, sizeof(u4AcsChnReport)); + + fgIsReady = prGlueInfo->prAdapter->rWifiVar.rChnLoadInfo.fgDataReadyBit; + if (fgIsReady == FALSE) + goto acs_report; + + /* + * 1. Get 2.4G Band channel list in current regulatory domain + */ + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_2G4, TRUE, + MAX_2G_BAND_CHN_NUM, &ucNumOfChannel, aucChannelList); + + /* + * 2. Calculate each channel's dirty score + */ + prGetChnLoad = &(prGlueInfo->prAdapter->rWifiVar.rChnLoadInfo); + + for (i = 0; i < ucNumOfChannel; i++) { + ucIdx = aucChannelList[i].ucChannelNum - 1; + + /* Current channel's dirty score */ + u2APNumScore = + prGetChnLoad->rEachChnLoad[ucIdx].u2APNum + * CHN_DIRTY_WEIGHT_UPPERBOUND; + u2LowThreshold = u2UpThreshold = 3; + + if (ucIdx < 3) { + u2LowThreshold = ucIdx; + u2UpThreshold = 3; + } else if (ucIdx >= (ucNumOfChannel - 3)) { + u2LowThreshold = 3; + u2UpThreshold = ucNumOfChannel - (ucIdx + 1); + } + + /* Lower channel's dirty score */ + for (ucInnerIdx = 0; + ucInnerIdx < u2LowThreshold; ucInnerIdx++) { + u2APNumScore += + (prGetChnLoad->rEachChnLoad + [ucIdx - ucInnerIdx - 1].u2APNum * + (CHN_DIRTY_WEIGHT_UPPERBOUND - 1 - ucInnerIdx)); + } + + /* Upper channel's dirty score */ + for (ucInnerIdx = 0; ucInnerIdx < u2UpThreshold; ucInnerIdx++) { + u2APNumScore += + (prGetChnLoad->rEachChnLoad + [ucIdx + ucInnerIdx + 1].u2APNum * + (CHN_DIRTY_WEIGHT_UPPERBOUND - 1 - ucInnerIdx)); + } + + arChannelDirtyScore_2G[i].ucChannel = + aucChannelList[i].ucChannelNum; + arChannelDirtyScore_2G[i].u2APNumScore = u2APNumScore; + + kalSprintf(acLogChannel + i*5, "%5d", + aucChannelList[i].ucChannelNum); + kalSprintf(acLogAPNum + i*5, "%5d", + prGetChnLoad->rEachChnLoad[ucIdx].u2APNum); + kalSprintf(acLogScore + i*5, "%5d", u2APNumScore); + } + + DBGLOG(P2P, INFO, "[ACS]Channel :%s\n", acLogChannel); + DBGLOG(P2P, INFO, "[ACS]AP num :%s\n", acLogAPNum); + DBGLOG(P2P, INFO, "[ACS]Score :%s\n", acLogScore); + + /* + * 3. Query LTE safe channels + */ + prQueryLteChn = kalMemAlloc( + sizeof(struct PARAM_GET_CHN_INFO), VIR_MEM_TYPE); + if (prQueryLteChn == NULL) { + DBGLOG(P2P, ERROR, "Alloc prQueryLteChn failed\n"); + /* Continue anyway */ + } else { + kalMemZero(prQueryLteChn, sizeof(struct PARAM_GET_CHN_INFO)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryLteSafeChannel, + prQueryLteChn, + sizeof(struct PARAM_GET_CHN_INFO), + TRUE, + FALSE, + TRUE, + &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(P2P, ERROR, "Query LTE safe channels failed\n"); + /* Continue anyway */ + } + + u4LteSafeChnBitMask_2G = + prQueryLteChn->rLteSafeChnList.au4SafeChannelBitmask + [NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_2G_BASE_1 - 1]; + if (!u4LteSafeChnBitMask_2G) { + DBGLOG(P2P, WARN, + "FW report 2.4G all channels unsafe!?\n"); + u4LteSafeChnBitMask_2G = BITS(1, 14); + } + + kalMemFree(prQueryLteChn, + VIR_MEM_TYPE, + sizeof(struct PARAM_GET_CHN_INFO)); + } + +#if CFG_TC1_FEATURE + /* Restrict 2.4G band channel selection range + * to 1/6/11 per customer's request + */ + u4LteSafeChnBitMask_2G &= 0x0842; +#elif CFG_TC10_FEATURE + /* Restrict 2.4G band channel selection range + * to 1~11 per customer's request + */ + u4LteSafeChnBitMask_2G &= 0x0FFE; +#endif + + /* 4. Find out the best channel, skip LTE unsafe channels */ + for (i = 0; i < ucNumOfChannel; i++) { + if (!(u4LteSafeChnBitMask_2G + & BIT(arChannelDirtyScore_2G[i].ucChannel))) + continue; + + if (rPreferChannel.u2APNumScore + >= arChannelDirtyScore_2G[i].u2APNumScore) { + rPreferChannel.ucChannel = + arChannelDirtyScore_2G[i].ucChannel; + rPreferChannel.u2APNumScore = + arChannelDirtyScore_2G[i].u2APNumScore; + } + } + + u4AcsChnReport + [NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_2G_BASE_1 - 1] = BIT(31); + if (rPreferChannel.ucChannel > 0) + u4AcsChnReport + [NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_2G_BASE_1 - 1] + |= BIT(rPreferChannel.ucChannel - 1); + + /* ToDo: Support 5G Channel Selection */ + +acs_report: + if (unlikely(nla_put_u32(skb, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_2G_BASE_1, + u4AcsChnReport + [NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_2G_BASE_1 - 1]) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put_u32(skb, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_36, + u4AcsChnReport + [NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_36 - 1]) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put_u32(skb, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_52, + u4AcsChnReport + [NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_52 - 1]) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put_u32(skb, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_100, + u4AcsChnReport + [NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_100 - 1]) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put_u32(skb, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_149, + u4AcsChnReport + [NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_149 - 1]) < 0)) + goto nla_put_failure; + + DBGLOG(P2P, INFO, + "[ACS]Relpy u4AcsChnReport[2G_BASE_1]=0x%08x\n", + u4AcsChnReport[0]); + + return cfg80211_testmode_reply(skb); + +nla_put_failure: + kfree_skb(skb); + return -EMSGSIZE; +} +#endif +#endif + +#endif /* CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_WIFI_DIRECT_CFG_80211 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_p2p_init.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_p2p_init.c new file mode 100644 index 0000000000000..917075d2c9357 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_p2p_init.c @@ -0,0 +1,275 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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_INF_NAME "p2p%d" +#define AP_INF_NAME "ap%d" + +/****************************************************************************** + * 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 uint8_t *ifname = P2P_INF_NAME; +static uint8_t *ifname2 = P2P_INF_NAME; +static uint16_t mode = RUNNING_P2P_MODE; + + +/****************************************************************************** + * M A C R O S + ****************************************************************************** + */ + +/****************************************************************************** + * F U N C T I O N D E C L A R A T I O N S + ****************************************************************************** + */ + +/****************************************************************************** + * F U N C T I O N S + ****************************************************************************** + */ + +void p2pSetSuspendMode(struct GLUE_INFO *prGlueInfo, u_int8_t fgEnable) +{ + struct net_device *prDev = NULL; + + if (!prGlueInfo) + return; + + if (!prGlueInfo->prAdapter->fgIsP2PRegistered) { + DBGLOG(INIT, INFO, "%s: P2P is not enabled, SKIP!\n", __func__); + return; + } + + prDev = prGlueInfo->prP2PInfo[0]->prDevHandler; + if (!prDev) { + DBGLOG(INIT, INFO, + "%s: P2P dev is not available, SKIP!\n", __func__); + return; + } + + kalSetNetAddressFromInterface(prGlueInfo, prDev, fgEnable); + wlanNotifyFwSuspend(prGlueInfo, prDev, fgEnable); +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief + * run p2p init procedure, glue register p2p and set p2p registered flag + * + * \retval 1 Success + */ +/*---------------------------------------------------------------------------*/ +u_int8_t p2pLaunch(struct GLUE_INFO *prGlueInfo) +{ + if (prGlueInfo->prAdapter->fgIsP2PRegistered == TRUE) { + DBGLOG(P2P, INFO, "p2p is already registered\n"); + return FALSE; + } + + if (!glRegisterP2P(prGlueInfo, ifname, ifname2, mode)) { + DBGLOG(P2P, ERROR, "Launch failed\n"); + return FALSE; + } + + prGlueInfo->prAdapter->fgIsP2PRegistered = TRUE; + prGlueInfo->prAdapter->p2p_scan_report_all_bss = + CFG_P2P_SCAN_REPORT_ALL_BSS; + DBGLOG(P2P, TRACE, "Launch success, fgIsP2PRegistered TRUE\n"); + return TRUE; +} + +void p2pSetMode(IN uint8_t ucAPMode) +{ + uint8_t *prAPInfName = AP_INF_NAME; + uint8_t *prP2PInfName = P2P_INF_NAME; + +#ifdef CFG_DRIVER_INF_NAME_CHANGE + + if (kalStrLen(gprifnamep2p) > 0) { + prP2PInfName = kalStrCat(gprifnamep2p, "%d"); + DBGLOG(INIT, WARN, + "P2P ifname customized, use %s\n", prP2PInfName); + } + + if (kalStrLen(gprifnameap) > 0) { + prAPInfName = kalStrCat(gprifnameap, "%d"); + DBGLOG(INIT, WARN, + "AP ifname customized, use %s\n", prAPInfName); + } + +#endif /* CFG_DRIVER_INF_NAME_CHANGE */ + + switch (ucAPMode) { + case 0: + mode = RUNNING_P2P_MODE; + ifname = prP2PInfName; + break; + case 1: + mode = RUNNING_AP_MODE; + ifname = prAPInfName; + break; + case 2: + mode = RUNNING_DUAL_AP_MODE; + ifname = prAPInfName; + break; + case 3: + mode = RUNNING_P2P_AP_MODE; + ifname = prP2PInfName; + ifname2 = prAPInfName; + break; + } +} /* p2pSetMode */ + +/*---------------------------------------------------------------------------*/ +/*! + * \brief + * run p2p exit procedure, glue unregister p2p and set p2p registered flag + * + * \retval 1 Success + */ +/*---------------------------------------------------------------------------*/ +u_int8_t p2pRemove(struct GLUE_INFO *prGlueInfo) +{ + int idx = 0; + + if (prGlueInfo->prAdapter->fgIsP2PRegistered == FALSE) { + DBGLOG(P2P, INFO, "p2p is not registered\n"); + return FALSE; + } + + DBGLOG(P2P, INFO, "fgIsP2PRegistered FALSE\n"); + prGlueInfo->prAdapter->fgIsP2PRegistered = FALSE; + prGlueInfo->prAdapter->p2p_scan_report_all_bss = FALSE; + + glUnregisterP2P(prGlueInfo, 0xff); + + /* Release ap0 wdev. + * ap0 wdev is created in wlanProbe. So we need to release it in + * wlanRemove. Other wdevs shall be released in exitWlan. + */ + for (idx = 0 ; idx < KAL_P2P_NUM; idx++) { + if (gprP2pRoleWdev[idx] == NULL) + continue; +#if CFG_ENABLE_UNIFY_WIPHY + if (gprP2pRoleWdev[idx] == gprWdev) { + /* This is AIS/AP Interface */ + gprP2pRoleWdev[idx] = NULL; + continue; + } +#endif + /* free gprP2pWdev in wlanDestroyAllWdev */ + if (gprP2pRoleWdev[idx] == gprP2pWdev) + continue; + + DBGLOG(INIT, INFO, "Unregister gprP2pRoleWdev[%d]\n", idx); +#if (CFG_ENABLE_UNIFY_WIPHY == 0) + set_wiphy_dev(gprP2pRoleWdev[idx]->wiphy, NULL); + wiphy_unregister(gprP2pRoleWdev[idx]->wiphy); + wiphy_free(gprP2pRoleWdev[idx]->wiphy); +#endif + kfree(gprP2pRoleWdev[idx]); + gprP2pRoleWdev[idx] = NULL; + break; + } +#if (CFG_ENABLE_UNIFY_WIPHY == 0) + /* gprP2pWdev: base P2P dev + * Becase the interface dev (ex: usb_device) would be free + * after un-plug event. Should set the wiphy->dev->parent which + * pointer to the interface dev to NULL. Otherwise, the corresponding + * system operation (poweroff, suspend) might reference it. + * set_wiphy_dev(wiphy, NULL): set the wiphy->dev->parent = NULL + */ + if (gprP2pWdev != NULL) + set_wiphy_dev(gprP2pWdev->wiphy, NULL); +#endif + + return TRUE; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_p2p_kal.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_p2p_kal.c new file mode 100644 index 0000000000000..54d35956f1815 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_p2p_kal.c @@ -0,0 +1,2017 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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" +#include "gl_wext.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 + ****************************************************************************** + */ + +struct ieee80211_channel *kalP2pFuncGetChannelEntry( + IN struct GL_P2P_INFO *prP2pInfo, + IN struct RF_CHANNEL_INFO *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 + */ +/*---------------------------------------------------------------------------*/ +#if 0 +enum ENUM_PARAM_MEDIA_STATE kalP2PGetState(IN struct GLUE_INFO *prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->prP2PInfo[0]->eState; +} /* end of kalP2PGetState() */ +#endif +/*---------------------------------------------------------------------------*/ +/*! + * \brief to update the assoc req to p2p + * + * \param[in] + * prGlueInfo + * pucFrameBody + * u4FrameBodyLen + * fgReassocRequest + * \return + * none + */ +/*---------------------------------------------------------------------------*/ +void +kalP2PUpdateAssocInfo(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucFrameBody, + IN uint32_t u4FrameBodyLen, + IN u_int8_t fgReassocRequest, + IN uint8_t ucBssIndex) +{ + struct BSS_INFO *prBssInfo; + union iwreq_data wrqu; + unsigned char *pucExtraInfo = NULL; + unsigned char *pucDesiredIE = NULL; +/* unsigned char aucExtraInfoBuf[200]; */ + uint8_t *cp; + struct net_device *prNetdevice = (struct net_device *)NULL; + + memset(&wrqu, 0, sizeof(wrqu)); + + if (fgReassocRequest) { + if (u4FrameBodyLen < 15) { + return; + } + } else { + if (u4FrameBodyLen < 9) { + 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)) { + /* WPS IE found */ + } else if (wextSrchDesiredWPAIE(cp, + u4FrameBodyLen, 0x30, &pucDesiredIE)) { + /* RSN IE found */ + } else if (wextSrchDesiredWPAIE(cp, + u4FrameBodyLen, 0xDD, &pucDesiredIE)) { + /* WPA IE found */ + } else { + /* no WPA/RSN IE found, skip this event */ + return; + } + + /* IWEVASSOCREQIE, indicate binary string */ + pucExtraInfo = pucDesiredIE; + wrqu.data.length = pucDesiredIE[1] + 2; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, ucBssIndex); + + if (ucBssIndex == prGlueInfo->prAdapter->ucP2PDevBssIdx) + prNetdevice = prGlueInfo->prP2PInfo + [prBssInfo->u4PrivateData]->prDevHandler; + else + prNetdevice = prGlueInfo->prP2PInfo + [prBssInfo->u4PrivateData]->aprRoleHandler; + + /* Send event to user space */ + wireless_send_event(prNetdevice, IWEVASSOCREQIE, &wrqu, pucExtraInfo); +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief to set Wi-Fi Direct state in glue layer + * + * \param[in] + * prGlueInfo + * eBowState + * rPeerAddr + * \return + * none + */ +/*---------------------------------------------------------------------------*/ +#if 0 +void +kalP2PSetState(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_PARAM_MEDIA_STATE eState, + IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN], + IN uint8_t ucRole) +{ + union iwreq_data evt; + uint8_t aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + + if (eState == PARAM_MEDIA_STATE_CONNECTED) { + prGlueInfo->prP2PInfo[0]->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[0]->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[0]->prDevHandler, + IWEVCUSTOM, &evt, aucBuffer); + } else { + ASSERT(0); + } + +} /* end of kalP2PSetState() */ +#endif +/*---------------------------------------------------------------------------*/ +/*! + * \brief to retrieve Wi-Fi Direct operating frequency + * + * \param[in] + * prGlueInfo + * + * \return + * in unit of KHz + */ +/*---------------------------------------------------------------------------*/ +#if 0 +uint32_t kalP2PGetFreqInKHz(IN struct GLUE_INFO *prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->prP2PInfo[0]->u4FreqInKHz; +} /* end of kalP2PGetFreqInKHz() */ +#endif + +/*---------------------------------------------------------------------------*/ +/*! + * \brief to retrieve Bluetooth-over-Wi-Fi role + * + * \param[in] + * prGlueInfo + * + * \return + * 0: P2P Device + * 1: Group Client + * 2: Group Owner + */ +/*----------------------------------------------------------------------------*/ +uint8_t kalP2PGetRole(IN struct GLUE_INFO *prGlueInfo, IN uint8_t ucRoleIdx) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->prP2PInfo[ucRoleIdx]->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 + */ +/*---------------------------------------------------------------------------*/ +#if 1 +void kalP2PSetRole(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRole, IN uint8_t ucRoleIdx) +{ + ASSERT(prGlueInfo); + ASSERT(ucRole <= 2); + + prGlueInfo->prP2PInfo[ucRoleIdx]->ucRole = ucRole; + /* Remove non-used code */ +} /* end of kalP2PSetRole() */ + +#else +void +kalP2PSetRole(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucResult, IN uint8_t *pucSSID, + IN uint8_t ucSSIDLen, IN uint8_t ucRole) +{ + union iwreq_data evt; + uint8_t aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + ASSERT(ucRole <= 2); + + memset(&evt, 0, sizeof(evt)); + + if (ucResult == 0) + prGlueInfo->prP2PInfo[0]->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); + + /* indicate in IWECUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo[0]->prDevHandler, + IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PSetRole() */ + +#endif +/*---------------------------------------------------------------------------*/ +/*! + * \brief to set the cipher for p2p + * + * \param[in] + * prGlueInfo + * u4Cipher + * + * \return + * none + */ +/*---------------------------------------------------------------------------*/ +void kalP2PSetCipher(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Cipher, IN uint8_t ucRoleIdx) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo[ucRoleIdx]); + + /* It can be WEP40 (used to identify cipher is WEP), TKIP and CCMP */ + prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise = u4Cipher; + +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief to get the cipher, return false for security is none + * + * \param[in] + * prGlueInfo + * + * \return + * TRUE: cipher is ccmp + * FALSE: cipher is none + */ +/*---------------------------------------------------------------------------*/ +u_int8_t kalP2PGetCipher(IN struct GLUE_INFO *prGlueInfo, IN uint8_t ucRoleIdx) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo[ucRoleIdx]); + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise + == IW_AUTH_CIPHER_CCMP) + return TRUE; + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise + == IW_AUTH_CIPHER_TKIP) + return TRUE; + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise + == IW_AUTH_CIPHER_WEP40) + return TRUE; + + return FALSE; +} + +u_int8_t kalP2PGetWepCipher(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIdx) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo[ucRoleIdx]); + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise + == IW_AUTH_CIPHER_WEP40) + return TRUE; + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise + == IW_AUTH_CIPHER_WEP104) + return TRUE; + + return FALSE; +} + +#if CFG_SUPPORT_SUITB +u_int8_t kalP2PGetGcmp256Cipher(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIdx) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo[ucRoleIdx]); + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise + == IW_AUTH_CIPHER_GCMP256) + return TRUE; + + return FALSE; +} +#endif + +u_int8_t kalP2PGetCcmpCipher(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIdx) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo[ucRoleIdx]); + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise + == IW_AUTH_CIPHER_CCMP) + return TRUE; + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise + == IW_AUTH_CIPHER_TKIP) + return FALSE; + + return FALSE; +} + +u_int8_t kalP2PGetTkipCipher(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIdx) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo[ucRoleIdx]); + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise + == IW_AUTH_CIPHER_CCMP) + return FALSE; + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise + == IW_AUTH_CIPHER_TKIP) + return TRUE; + + return FALSE; +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief to set the status of WSC + * + * \param[in] + * prGlueInfo + * + * \return + */ +/*---------------------------------------------------------------------------*/ +void kalP2PSetWscMode(IN struct GLUE_INFO *prGlueInfo, IN uint8_t ucWscMode) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PDevInfo); + + prGlueInfo->prP2PDevInfo->ucWSCRunning = ucWscMode; +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief to get the status of WSC + * + * \param[in] + * prGlueInfo + * + * \return + */ +/*---------------------------------------------------------------------------*/ +uint8_t kalP2PGetWscMode(IN struct GLUE_INFO *prGlueInfo) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PDevInfo); + + return prGlueInfo->prP2PDevInfo->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 + */ +/*---------------------------------------------------------------------------*/ +uint16_t kalP2PCalWSC_IELen(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucType, IN uint8_t ucRoleIdx) +{ + ASSERT(prGlueInfo); + + ASSERT(ucType < 4); + + return prGlueInfo->prP2PInfo[ucRoleIdx]->u2WSCIELen[ucType]; +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief to copy the wsc ie setting from p2p supplicant + * + * \param[in] + * prGlueInfo + * + * \return + * The WPS IE length + */ +/*---------------------------------------------------------------------------*/ +void kalP2PGenWSC_IE(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucType, IN uint8_t *pucBuffer, IN uint8_t ucRoleIdx) +{ + struct GL_P2P_INFO *prGlP2pInfo = (struct GL_P2P_INFO *) NULL; + + do { + if ((prGlueInfo == NULL) + || (ucType >= 4) || (pucBuffer == NULL)) + break; + + prGlP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + + kalMemCopy(pucBuffer, + prGlP2pInfo->aucWSCIE[ucType], + prGlP2pInfo->u2WSCIELen[ucType]); + + } while (FALSE); + +} + +void kalP2PUpdateWSC_IE(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucType, IN uint8_t *pucBuffer, + IN uint16_t u2BufferLength, IN uint8_t ucRoleIdx) +{ + struct GL_P2P_INFO *prGlP2pInfo = (struct GL_P2P_INFO *) NULL; + + do { + if ((prGlueInfo == NULL) || (ucType >= 4) + || ((u2BufferLength > 0) && (pucBuffer == NULL))) + break; + + if (u2BufferLength > 400) { + log_dbg(P2P, ERROR, + "Buffer length is not enough, GLUE only 400 bytes but %d received\n", + u2BufferLength); + ASSERT(FALSE); + break; + } + + prGlP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + + kalMemCopy(prGlP2pInfo->aucWSCIE[ucType], + pucBuffer, u2BufferLength); + + prGlP2pInfo->u2WSCIELen[ucType] = u2BufferLength; + + } while (FALSE); + +} /* kalP2PUpdateWSC_IE */ + +uint16_t kalP2PCalP2P_IELen(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucIndex, IN uint8_t ucRoleIdx) +{ + ASSERT(prGlueInfo); + + ASSERT(ucIndex < MAX_P2P_IE_SIZE); + + return prGlueInfo->prP2PInfo[ucRoleIdx]->u2P2PIELen[ucIndex]; +} + +void kalP2PGenP2P_IE(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucIndex, IN uint8_t *pucBuffer, IN uint8_t ucRoleIdx) +{ + struct GL_P2P_INFO *prGlP2pInfo = (struct GL_P2P_INFO *) NULL; + + do { + if ((prGlueInfo == NULL) || (ucIndex >= MAX_P2P_IE_SIZE) + || (pucBuffer == NULL)) + break; + + prGlP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + + kalMemCopy(pucBuffer, + prGlP2pInfo->aucP2PIE[ucIndex], + prGlP2pInfo->u2P2PIELen[ucIndex]); + + } while (FALSE); +} + +void kalP2PUpdateP2P_IE(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucIndex, IN uint8_t *pucBuffer, + IN uint16_t u2BufferLength, IN uint8_t ucRoleIdx) +{ + struct GL_P2P_INFO *prGlP2pInfo = (struct GL_P2P_INFO *) NULL; + + do { + if ((prGlueInfo == NULL) || + (ucIndex >= MAX_P2P_IE_SIZE) || + ((u2BufferLength > 0) && (pucBuffer == NULL))) + break; + + if (u2BufferLength > 400) { + log_dbg(P2P, ERROR, + "kalP2PUpdateP2P_IE > Buffer length is not enough, GLUE only 400 bytes but %d received\n", + u2BufferLength); + ASSERT(FALSE); + break; + } + + prGlP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + + kalMemCopy(prGlP2pInfo->aucP2PIE[ucIndex], + pucBuffer, u2BufferLength); + + prGlP2pInfo->u2P2PIELen[ucIndex] = u2BufferLength; + + } while (FALSE); + +} + +#if 0 +/*---------------------------------------------------------------------------*/ +/*! + * \brief indicate an event to supplicant for device connection request + * + * \param[in] prGlueInfo Pointer of GLUE_INFO_T + * + * \retval none + */ +/*---------------------------------------------------------------------------*/ +void kalP2PIndicateConnReq(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucDevName, IN int32_t u4NameLength, + IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN], + IN uint8_t ucDevType,/* 0: P2P Device / 1: GC / 2: GO */ + IN int32_t i4ConfigMethod, IN int32_t i4ActiveConfigMethod +) +{ + union iwreq_data evt; + uint8_t aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + /* buffer peer information + * for later IOC_P2P_GET_REQ_DEVICE_INFO access + */ + prGlueInfo->prP2PInfo[0]->u4ConnReqNameLength = + u4NameLength > 32 ? 32 : u4NameLength; + kalMemCopy(prGlueInfo->prP2PInfo[0]->aucConnReqDevName, + pucDevName, + prGlueInfo->prP2PInfo[0]->u4ConnReqNameLength); + COPY_MAC_ADDR(prGlueInfo->prP2PInfo[0]->rConnReqPeerAddr, rPeerAddr); + prGlueInfo->prP2PInfo[0]->ucConnReqDevType = ucDevType; + prGlueInfo->prP2PInfo[0]->i4ConnReqConfigMethod = i4ConfigMethod; + prGlueInfo->prP2PInfo[0]->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[0]->prDevHandler, + IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PIndicateConnReq() */ + +/*---------------------------------------------------------------------------*/ +/*! + * \brief Indicate an event to supplicant + * for device connection request from other device. + * + * \param[in] prGlueInfo Pointer of GLUE_INFO_T + * \param[in] pucGroupBssid Only valid when invitation Type equals to 0. + * + * \retval none + */ +/*---------------------------------------------------------------------------*/ +void +kalP2PInvitationIndication(IN struct GLUE_INFO *prGlueInfo, + IN struct P2P_DEVICE_DESC *prP2pDevDesc, + IN uint8_t *pucSsid, + IN uint8_t ucSsidLen, + IN uint8_t ucOperatingChnl, + IN uint8_t ucInvitationType, + IN uint8_t *pucGroupBssid) +{ +#if 1 + union iwreq_data evt; + uint8_t aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + /* buffer peer information for later IOC_P2P_GET_STRUCT access */ + prGlueInfo->prP2PInfo[0]->u4ConnReqNameLength = + (uint32_t) ((prP2pDevDesc->u2NameLength > 32) + ? 32 : prP2pDevDesc->u2NameLength); + kalMemCopy(prGlueInfo->prP2PInfo[0]->aucConnReqDevName, + prP2pDevDesc->aucName, + prGlueInfo->prP2PInfo[0]->u4ConnReqNameLength); + COPY_MAC_ADDR(prGlueInfo->prP2PInfo[0]->rConnReqPeerAddr, + prP2pDevDesc->aucDeviceAddr); + COPY_MAC_ADDR(prGlueInfo->prP2PInfo[0]->rConnReqGroupAddr, + pucGroupBssid); + prGlueInfo->prP2PInfo[0]->i4ConnReqConfigMethod = (int32_t) + (prP2pDevDesc->u2ConfigMethod); + prGlueInfo->prP2PInfo[0]->ucOperatingChnl = ucOperatingChnl; + prGlueInfo->prP2PInfo[0]->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[0]->prDevHandler, + IWEVCUSTOM, &evt, aucBuffer); + +#else + struct MSG_P2P_CONNECTION_REQUEST *prP2pConnReq = + (struct MSG_P2P_CONNECTION_REQUEST *) NULL; + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo = + (struct P2P_SPECIFIC_BSS_INFO *) NULL; + struct P2P_CONNECTION_SETTINGS *prP2pConnSettings = + (struct P2P_CONNECTION_SETTINGS *) NULL; + + do { + ASSERT_BREAK((prGlueInfo != NULL) && (prP2pDevDesc != NULL)); + + /* Not a real solution */ + + prP2pSpecificBssInfo = + prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo; + prP2pConnSettings = + prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings; + + prP2pConnReq = (struct MSG_P2P_CONNECTION_REQUEST *) + cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_P2P_CONNECTION_REQUEST)); + + if (prP2pConnReq == NULL) + break; + + kalMemZero(prP2pConnReq, + sizeof(struct MSG_P2P_CONNECTION_REQUEST)); + + 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[0]->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, + (struct MSG_HDR *) prP2pConnReq, + MSG_SEND_METHOD_BUF); + + } while (FALSE); + + /* frog add. */ + /* TODO: Invitation Indication */ + +#endif + +} /* kalP2PInvitationIndication */ +#endif + +#if 0 +/*---------------------------------------------------------------------------*/ +/*! + * \brief Indicate an status to supplicant for device invitation status. + * + * \param[in] prGlueInfo Pointer of GLUE_INFO_T + * + * \retval none + */ +/*---------------------------------------------------------------------------*/ +void kalP2PInvitationStatus(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4InvStatus) +{ + union iwreq_data evt; + uint8_t aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + /* buffer peer information for later IOC_P2P_GET_STRUCT access */ + prGlueInfo->prP2PInfo[0]->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[0]->prDevHandler, + IWEVCUSTOM, &evt, aucBuffer); + +} /* kalP2PInvitationStatus */ +#endif + +/*---------------------------------------------------------------------------*/ +/*! + * \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 struct GLUE_INFO *prGlueInfo, + IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN], IN uint8_t ucSeqNum) +{ + union iwreq_data evt; + uint8_t 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[0]->prDevHandler, + IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PIndicateSDRequest() */ + +/*---------------------------------------------------------------------------*/ +/*! + * \brief Indicate an event to supplicant for Service Discovery response + * from other device. + * + * \param[in] prGlueInfo Pointer of GLUE_INFO_T + * + * \retval none + */ +/*---------------------------------------------------------------------------*/ +void kalP2PIndicateSDResponse(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN], IN uint8_t ucSeqNum) +{ + union iwreq_data evt; + uint8_t 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[0]->prDevHandler, + IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PIndicateSDResponse() */ + +/*---------------------------------------------------------------------------*/ +/*! + * \brief Indicate an event to supplicant for Service Discovery TX Done + * from other device. + * + * \param[in] prGlueInfo Pointer of GLUE_INFO_T + * \param[in] ucSeqNum Sequence number of the frame + * \param[in] ucStatus Status code for TX + * + * \retval none + */ +/*---------------------------------------------------------------------------*/ +void kalP2PIndicateTXDone(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucSeqNum, IN uint8_t ucStatus) +{ + union iwreq_data evt; + uint8_t 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[0]->prDevHandler, + IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PIndicateSDResponse() */ + +struct net_device *kalP2PGetDevHdlr(struct GLUE_INFO *prGlueInfo) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo[0]); + return prGlueInfo->prP2PInfo[0]->prDevHandler; +} + +#if CFG_SUPPORT_ANTI_PIRACY +#if 0 +/*---------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] prAdapter Pointer of ADAPTER_T + * + * \return none + */ +/*---------------------------------------------------------------------------*/ +void kalP2PIndicateSecCheckRsp(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucRsp, IN uint16_t u2RspLen) +{ + union iwreq_data evt; + uint8_t aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_SEC_CHECK_RSP="); + + kalMemCopy(prGlueInfo->prP2PInfo[0]->aucSecCheckRsp, pucRsp, u2RspLen); + evt.data.length = strlen(aucBuffer); + +#if DBG + DBGLOG_MEM8(SEC, LOUD, + prGlueInfo->prP2PInfo[0]->aucSecCheckRsp, u2RspLen); +#endif + /* indicate in IWECUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo[0]->prDevHandler, + IWEVCUSTOM, &evt, aucBuffer); +} /* p2pFsmRunEventRxDisassociation */ +#endif +#endif + +/*---------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] prAdapter Pointer of ADAPTER_T + * + * \return none + */ +/*---------------------------------------------------------------------------*/ +void +kalGetChnlList(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_BAND eSpecificBand, + IN uint8_t ucMaxChannelNum, + IN uint8_t *pucNumOfChannel, + IN struct RF_CHANNEL_INFO *paucChannelList) +{ + rlmDomainGetChnlList(prGlueInfo->prAdapter, eSpecificBand, + FALSE, ucMaxChannelNum, pucNumOfChannel, paucChannelList); +} /* kalGetChnlList */ + +/* ////////////////////////////ICS SUPPORT////////////////////////////// */ + +void +kalP2PIndicateChannelReady(IN struct GLUE_INFO *prGlueInfo, + IN uint64_t u8SeqNum, + IN uint32_t u4ChannelNum, + IN enum ENUM_BAND eBand, + IN enum ENUM_CHNL_EXT eSco, + IN uint32_t u4Duration) +{ + struct ieee80211_channel *prIEEE80211ChnlStruct = + (struct ieee80211_channel *)NULL; + struct RF_CHANNEL_INFO rChannelInfo; + enum nl80211_channel_type eChnlType = NL80211_CHAN_NO_HT; + + do { + if (prGlueInfo == NULL) + break; + + kalMemZero(&rChannelInfo, sizeof(struct RF_CHANNEL_INFO)); + + rChannelInfo.ucChannelNum = u4ChannelNum; + rChannelInfo.eBand = eBand; + + prIEEE80211ChnlStruct = + kalP2pFuncGetChannelEntry(prGlueInfo->prP2PInfo[0], + &rChannelInfo); + + kalP2pFuncGetChannelType(eSco, &eChnlType); + + cfg80211_ready_on_channel( + /* struct wireless_dev, */ + prGlueInfo->prP2PInfo[0]->prWdev, + /* u64 cookie, */ + u8SeqNum, + /* struct ieee80211_channel * chan, */ + prIEEE80211ChnlStruct, + /* unsigned int duration, */ + u4Duration, + /* gfp_t gfp *//* allocation flags */ + GFP_KERNEL); + } while (FALSE); + +} /* kalP2PIndicateChannelReady */ + +void +kalP2PIndicateChannelExpired(IN struct GLUE_INFO *prGlueInfo, + IN uint64_t u8SeqNum, + IN uint32_t u4ChannelNum, + IN enum ENUM_BAND eBand, + IN enum ENUM_CHNL_EXT eSco) +{ + + struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL; + struct ieee80211_channel *prIEEE80211ChnlStruct = + (struct ieee80211_channel *)NULL; + enum nl80211_channel_type eChnlType = NL80211_CHAN_NO_HT; + struct RF_CHANNEL_INFO rRfChannelInfo; + + do { + if (prGlueInfo == NULL) { + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo[0]; + + if (prGlueP2pInfo == NULL) { + ASSERT(FALSE); + break; + } + + DBGLOG(P2P, TRACE, "kalP2PIndicateChannelExpired\n"); + + rRfChannelInfo.eBand = eBand; + rRfChannelInfo.ucChannelNum = u4ChannelNum; + + prIEEE80211ChnlStruct = + kalP2pFuncGetChannelEntry(prGlueP2pInfo, + &rRfChannelInfo); + + kalP2pFuncGetChannelType(eSco, &eChnlType); + + /* struct wireless_dev, */ + cfg80211_remain_on_channel_expired(prGlueP2pInfo->prWdev, + u8SeqNum, prIEEE80211ChnlStruct, GFP_KERNEL); + } while (FALSE); + +} /* kalP2PIndicateChannelExpired */ + +void kalP2PIndicateScanDone(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex, IN u_int8_t fgIsAbort) +{ + struct GL_P2P_DEV_INFO *prP2pGlueDevInfo = + (struct GL_P2P_DEV_INFO *) NULL; + struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL; + struct cfg80211_scan_request *prScanRequest = NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + do { + if (prGlueInfo == NULL) { + + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo[0]; + prP2pGlueDevInfo = prGlueInfo->prP2PDevInfo; + + if ((prGlueP2pInfo == NULL) || (prP2pGlueDevInfo == NULL)) { + ASSERT(FALSE); + break; + } + + DBGLOG(INIT, INFO, + "[p2p] scan complete %p\n", + prP2pGlueDevInfo->prScanRequest); + + KAL_ACQUIRE_MUTEX(prGlueInfo->prAdapter, MUTEX_DEL_INF); + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + if (prP2pGlueDevInfo->prScanRequest != NULL) { + prScanRequest = prP2pGlueDevInfo->prScanRequest; + kalCfg80211ScanDone(prScanRequest, fgIsAbort); + prP2pGlueDevInfo->prScanRequest = NULL; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + if ((prScanRequest != NULL) + && (prGlueInfo->prAdapter->fgIsP2PRegistered == TRUE)) { + + /* report all queued beacon/probe response frames + * to upper layer + */ + scanReportBss2Cfg80211(prGlueInfo->prAdapter, + BSS_TYPE_P2P_DEVICE, NULL); + + DBGLOG(INIT, TRACE, "DBG:p2p_cfg_scan_done\n"); + } + KAL_RELEASE_MUTEX(prGlueInfo->prAdapter, MUTEX_DEL_INF); + + } while (FALSE); + +} /* kalP2PIndicateScanDone */ + +void +kalP2PIndicateBssInfo(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucFrameBuf, + IN uint32_t u4BufLen, + IN struct RF_CHANNEL_INFO *prChannelInfo, + IN int32_t i4SignalStrength) +{ + struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) 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[0]; + + 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; + */ + + if (u4BufLen > 0) { + prCfg80211Bss = cfg80211_inform_bss_frame( + /* struct wiphy * wiphy, */ + prGlueP2pInfo->prWdev->wiphy, + prChannelEntry, + prBcnProbeRspFrame, + u4BufLen, i4SignalStrength, GFP_KERNEL); + } + + /* Return this structure. */ + if (prCfg80211Bss) + cfg80211_put_bss(prGlueP2pInfo->prWdev->wiphy, + prCfg80211Bss); + else + DBGLOG(P2P, WARN, + "indicate BSS to cfg80211 failed [" MACSTR + "]: bss channel %d, rcpi %d, frame_len=%d\n", + MAC2STR(prBcnProbeRspFrame->bssid), + prChannelInfo->ucChannelNum, + i4SignalStrength, u4BufLen); + + } while (FALSE); + + return; + +} /* kalP2PIndicateBssInfo */ + +void kalP2PIndicateMgmtTxStatus(IN struct GLUE_INFO *prGlueInfo, + IN struct MSDU_INFO *prMsduInfo, IN u_int8_t fgIsAck) +{ + struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL; + uint64_t *pu8GlCookie = (uint64_t *) NULL; + struct net_device *prNetdevice = (struct net_device *)NULL; + + do { + if ((prGlueInfo == NULL) || (prMsduInfo == NULL)) { + DBGLOG(P2P, WARN, + "Unexpected pointer PARAM. 0x%lx, 0x%lx.\n", + prGlueInfo, prMsduInfo); + ASSERT(FALSE); + break; + } + + pu8GlCookie = + (uint64_t *) ((unsigned long) prMsduInfo->prPacket + + (unsigned long) prMsduInfo->u2FrameLength + + MAC_TX_RESERVED_FIELD); + + if (prMsduInfo->ucBssIndex + == prGlueInfo->prAdapter->ucP2PDevBssIdx) { + + prGlueP2pInfo = prGlueInfo->prP2PInfo[0]; + + if (prGlueP2pInfo == NULL) + return; + + prNetdevice = prGlueP2pInfo->prDevHandler; + + } else { + struct BSS_INFO *prP2pBssInfo = + GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, + prMsduInfo->ucBssIndex); + + prGlueP2pInfo = + prGlueInfo->prP2PInfo + [prP2pBssInfo->u4PrivateData]; + + if (prGlueP2pInfo == NULL) + return; + + prNetdevice = prGlueP2pInfo->aprRoleHandler; + } + + cfg80211_mgmt_tx_status( + /* struct net_device * dev, */ + prNetdevice->ieee80211_ptr, + *pu8GlCookie, + (uint8_t *) ((unsigned long) prMsduInfo->prPacket + + MAC_TX_RESERVED_FIELD), + prMsduInfo->u2FrameLength, fgIsAck, GFP_KERNEL); + + } while (FALSE); + +} /* kalP2PIndicateMgmtTxStatus */ + +void +kalP2PIndicateRxMgmtFrame(IN struct GLUE_INFO *prGlueInfo, + IN struct SW_RFB *prSwRfb, + IN u_int8_t fgIsDevInterface, + IN uint8_t ucRoleIdx) +{ +#define DBG_P2P_MGMT_FRAME_INDICATION 1 + struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL; + int32_t i4Freq = 0; + uint8_t ucChnlNum = 0; +#if DBG_P2P_MGMT_FRAME_INDICATION + struct WLAN_MAC_HEADER *prWlanHeader = (struct WLAN_MAC_HEADER *) NULL; +#endif + struct net_device *prNetdevice = (struct net_device *)NULL; + + do { + if ((prGlueInfo == NULL) || (prSwRfb == NULL)) { + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + + /* ToDo[6630]: Get the following by channel freq */ + /* HAL_RX_STATUS_GET_CHAN_FREQ( prSwRfb->prRxStatus) */ + /* ucChnlNum = prSwRfb->prHifRxHdr->ucHwChannelNum; */ + + ucChnlNum = HAL_RX_STATUS_GET_CHNL_NUM(prSwRfb->prRxStatus); + +#if DBG_P2P_MGMT_FRAME_INDICATION + + prWlanHeader = (struct WLAN_MAC_HEADER *) 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); + p2pFuncClassifyAction(prSwRfb); + 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 (fgIsDevInterface) + prNetdevice = prGlueP2pInfo->prDevHandler; + else + prNetdevice = prGlueP2pInfo->aprRoleHandler; + +#if (KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE) + cfg80211_rx_mgmt( + /* struct net_device * dev, */ + prNetdevice->ieee80211_ptr, + i4Freq, + RCPI_TO_dBm( + nicRxGetRcpiValueFromRxv(RCPI_MODE_MAX, + prSwRfb)), + prSwRfb->pvHeader, + prSwRfb->u2PacketLen, + NL80211_RXMGMT_FLAG_ANSWERED); +#elif (KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE) + cfg80211_rx_mgmt( + /* struct net_device * dev, */ + prNetdevice->ieee80211_ptr, + i4Freq, + RCPI_TO_dBm( + nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0, + prSwRfb)), + prSwRfb->pvHeader, + prSwRfb->u2PacketLen, + NL80211_RXMGMT_FLAG_ANSWERED, + GFP_ATOMIC); +#else + cfg80211_rx_mgmt( + /* struct net_device * dev, */ + prNetdevice->ieee80211_ptr, + i4Freq, + RCPI_TO_dBm( + nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0, + prSwRfb)), + prSwRfb->pvHeader, + prSwRfb->u2PacketLen, + GFP_ATOMIC); +#endif + + + } while (FALSE); + +} /* kalP2PIndicateRxMgmtFrame */ + +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) +void +kalP2PGCIndicateConnectionStatus(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex, + IN struct P2P_CONNECTION_REQ_INFO *prP2pConnInfo, + IN uint8_t *pucRxIEBuf, + IN uint16_t u2RxIELen, + IN uint16_t u2StatusReason, + IN uint32_t eStatus) +{ + struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL; + struct ADAPTER *prAdapter = NULL; + + do { + if (prGlueInfo == NULL) { + ASSERT(FALSE); + break; + } + + prAdapter = prGlueInfo->prAdapter; + prGlueP2pInfo = prGlueInfo->prP2PInfo[ucRoleIndex]; + + /* FIXME: This exception occurs at wlanRemove. */ + if ((prGlueP2pInfo == NULL) || + (prGlueP2pInfo->aprRoleHandler == NULL) || + (prAdapter->rP2PNetRegState != + ENUM_NET_REG_STATE_REGISTERED) || + ((prGlueInfo->ulFlag & GLUE_FLAG_HALT) == 1)) { + break; + } + + if (prP2pConnInfo) { + /* switch netif on */ + netif_carrier_on(prGlueP2pInfo->aprRoleHandler); +#if !CFG_SUPPORT_CFG80211_AUTH + cfg80211_connect_result(prGlueP2pInfo->aprRoleHandler, + /* struct net_device * dev, */ + prP2pConnInfo->aucBssid, + prP2pConnInfo->aucIEBuf, + prP2pConnInfo->u4BufLength, + pucRxIEBuf, u2RxIELen, + u2StatusReason, + /* gfp_t gfp *//* allocation flags */ + GFP_KERNEL); +#endif + prP2pConnInfo->eConnRequest = P2P_CONNECTION_TYPE_IDLE; + } else { + /* Disconnect, what if u2StatusReason == 0? */ + cfg80211_disconnected(prGlueP2pInfo->aprRoleHandler, + /* struct net_device * dev, */ + u2StatusReason, + pucRxIEBuf, u2RxIELen, + eStatus == WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY, + GFP_KERNEL); + } + + } while (FALSE); + +} /* kalP2PGCIndicateConnectionStatus */ + +#else +void +kalP2PGCIndicateConnectionStatus(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex, + IN struct P2P_CONNECTION_REQ_INFO *prP2pConnInfo, + IN uint8_t *pucRxIEBuf, + IN uint16_t u2RxIELen, + IN uint16_t u2StatusReason) +{ + struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL; + struct ADAPTER *prAdapter = NULL; + + do { + if (prGlueInfo == NULL) { + ASSERT(FALSE); + break; + } + + prAdapter = prGlueInfo->prAdapter; + prGlueP2pInfo = prGlueInfo->prP2PInfo[ucRoleIndex]; + + /* FIXME: This exception occurs at wlanRemove. */ + if ((prGlueP2pInfo == NULL) || + (prGlueP2pInfo->aprRoleHandler == NULL) || + (prAdapter->rP2PNetRegState != + ENUM_NET_REG_STATE_REGISTERED) || + ((prGlueInfo->ulFlag & GLUE_FLAG_HALT) == 1)) { + break; + } + + if (prP2pConnInfo) { + /* switch netif on */ + netif_carrier_on(prGlueP2pInfo->aprRoleHandler); + + cfg80211_connect_result(prGlueP2pInfo->aprRoleHandler, + /* struct net_device * dev, */ + prP2pConnInfo->aucBssid, + prP2pConnInfo->aucIEBuf, + prP2pConnInfo->u4BufLength, + pucRxIEBuf, u2RxIELen, + u2StatusReason, + /* gfp_t gfp *//* allocation flags */ + GFP_KERNEL); + + prP2pConnInfo->eConnRequest = P2P_CONNECTION_TYPE_IDLE; + } else { + /* Disconnect, what if u2StatusReason == 0? */ + cfg80211_disconnected(prGlueP2pInfo->aprRoleHandler, + /* struct net_device * dev, */ + u2StatusReason, pucRxIEBuf, + u2RxIELen, GFP_KERNEL); + } + + } while (FALSE); + +} /* kalP2PGCIndicateConnectionStatus */ + +#endif + +void +kalP2PGOStationUpdate(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex, + IN struct STA_RECORD *prCliStaRec, + IN u_int8_t fgIsNew) +{ + struct GL_P2P_INFO *prP2pGlueInfo = (struct GL_P2P_INFO *) NULL; + + do { + if ((prGlueInfo == NULL) || (prCliStaRec == NULL) + || (ucRoleIndex >= 2)) + break; + + prP2pGlueInfo = prGlueInfo->prP2PInfo[ucRoleIndex]; + + if ((prP2pGlueInfo == NULL) || + (prP2pGlueInfo->aprRoleHandler == NULL)) { + /* This case may occur when the usb is unplugged */ + break; + } + + if (fgIsNew) { + struct station_info rStationInfo; + + kalMemZero(&rStationInfo, sizeof(rStationInfo)); + +#if KERNEL_VERSION(4, 0, 0) > CFG80211_VERSION_CODE + rStationInfo.filled = STATION_INFO_ASSOC_REQ_IES; +#endif + rStationInfo.generation = ++prP2pGlueInfo->i4Generation; + + rStationInfo.assoc_req_ies = prCliStaRec->pucAssocReqIe; + rStationInfo.assoc_req_ies_len = + prCliStaRec->u2AssocReqIeLen; + + cfg80211_new_sta(prP2pGlueInfo->aprRoleHandler, + /* struct net_device * dev, */ + prCliStaRec->aucMacAddr, + &rStationInfo, GFP_KERNEL); + } else { + ++prP2pGlueInfo->i4Generation; + + /* FIXME: The exception occurs at wlanRemove, and + * check GLUE_FLAG_HALT is the temporarily solution. + */ + if ((prGlueInfo->ulFlag & GLUE_FLAG_HALT) == 0) { + cfg80211_del_sta(prP2pGlueInfo->aprRoleHandler, + /* struct net_device * dev, */ + prCliStaRec->aucMacAddr, GFP_KERNEL); + } + } + + } while (FALSE); + + return; + +} /* kalP2PGOStationUpdate */ + +#if (CFG_SUPPORT_DFS_MASTER == 1) +void kalP2PRddDetectUpdate(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex) +{ + DBGLOG(INIT, INFO, "Radar Detection event\n"); + + do { + if (prGlueInfo == NULL) { + ASSERT(FALSE); + break; + } + + if (prGlueInfo->prP2PInfo[ucRoleIndex]->chandef == NULL) { + ASSERT(FALSE); + break; + } + + /* cac start disable for next cac slot + * if enable in dfs channel + */ + prGlueInfo->prP2PInfo[ucRoleIndex]->prWdev->cac_started = FALSE; + DBGLOG(INIT, INFO, + "kalP2PRddDetectUpdate: Update to OS\n"); + cfg80211_radar_event( + prGlueInfo->prP2PInfo[ucRoleIndex]->prWdev->wiphy, + prGlueInfo->prP2PInfo[ucRoleIndex]->chandef, + GFP_KERNEL); + DBGLOG(INIT, INFO, + "kalP2PRddDetectUpdate: Update to OS Done\n"); + + netif_carrier_off( + prGlueInfo->prP2PInfo[ucRoleIndex]->prDevHandler); + netif_tx_stop_all_queues( + prGlueInfo->prP2PInfo[ucRoleIndex]->prDevHandler); + + } while (FALSE); + +} /* kalP2PRddDetectUpdate */ + +void kalP2PCacFinishedUpdate(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex) +{ + DBGLOG(INIT, INFO, "CAC Finished event\n"); + + if (prGlueInfo == NULL) + return; + + if (prGlueInfo->prP2PInfo[ucRoleIndex]->chandef == NULL) + return; + + DBGLOG(INIT, INFO, "kalP2PCacFinishedUpdate: Update to OS\n"); +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE + cfg80211_cac_event(prGlueInfo->prP2PInfo[ucRoleIndex]->prDevHandler, + prGlueInfo->prP2PInfo[ucRoleIndex]->chandef, + NL80211_RADAR_CAC_FINISHED, GFP_KERNEL); +#else + cfg80211_cac_event(prGlueInfo->prP2PInfo[ucRoleIndex]->prDevHandler, + NL80211_RADAR_CAC_FINISHED, GFP_KERNEL); +#endif + DBGLOG(INIT, INFO, "kalP2PCacFinishedUpdate: Update to OS Done\n"); + + +} /* kalP2PRddDetectUpdate */ +#endif + +u_int8_t kalP2pFuncGetChannelType(IN enum ENUM_CHNL_EXT rChnlSco, + OUT enum nl80211_channel_type *channel_type) +{ + u_int8_t 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 struct GL_P2P_INFO *prP2pInfo, + IN struct RF_CHANNEL_INFO *prChannelInfo) +{ + struct ieee80211_channel *prTargetChannelEntry = + (struct ieee80211_channel *)NULL; + uint32_t u4TblSize = 0, u4Idx = 0; + struct wiphy *wiphy = NULL; + + if ((prP2pInfo == NULL) || (prChannelInfo == NULL)) + return NULL; + + wiphy = prP2pInfo->prWdev->wiphy; + + do { + + switch (prChannelInfo->eBand) { + case BAND_2G4: + if (wiphy->bands[KAL_BAND_2GHZ] == NULL) + DBGLOG(P2P, ERROR, + "kalP2pFuncGetChannelEntry 2.4G NULL Bands!!\n"); + else { + prTargetChannelEntry = + wiphy->bands[KAL_BAND_2GHZ]->channels; + u4TblSize = + wiphy->bands[KAL_BAND_2GHZ]->n_channels; + } + break; + case BAND_5G: + if (wiphy->bands[KAL_BAND_5GHZ] == NULL) + DBGLOG(P2P, ERROR, + "kalP2pFuncGetChannelEntry 5G NULL Bands!!\n"); + else { + prTargetChannelEntry = + wiphy->bands[KAL_BAND_5GHZ]->channels; + u4TblSize = + wiphy->bands[KAL_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 */ + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + +/*---------------------------------------------------------------------------*/ +/*! + * \brief to set the block list of Hotspot + * + * \param[in] + * prGlueInfo + * + * \return + */ +/*---------------------------------------------------------------------------*/ +u_int8_t kalP2PSetBlackList(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t rbssid[PARAM_MAC_ADDR_LEN], + IN u_int8_t fgIsblock, + IN uint8_t ucRoleIndex) +{ + uint8_t aucNullAddr[] = NULL_MAC_ADDR; + u_int8_t fgIsValid = FALSE; + uint32_t i; + + ASSERT(prGlueInfo); + /*ASSERT(prGlueInfo->prP2PInfo[ucRoleIndex]);*/ + + + /*if only one ap mode register, prGlueInfo->prP2PInfo[1] would be null*/ + if (!prGlueInfo->prP2PInfo[ucRoleIndex]) + return fgIsValid; + + + if (fgIsblock) { + for (i = 0; i < P2P_MAXIMUM_CLIENT_COUNT; i++) { + if (UNEQUAL_MAC_ADDR(rbssid, aucNullAddr)) { + if (UNEQUAL_MAC_ADDR( + &(prGlueInfo->prP2PInfo[ucRoleIndex] + ->aucblackMACList[i]), rbssid)) { + if (EQUAL_MAC_ADDR( + &(prGlueInfo->prP2PInfo + [ucRoleIndex] + ->aucblackMACList[i]), + aucNullAddr)) { + COPY_MAC_ADDR( + &(prGlueInfo->prP2PInfo + [ucRoleIndex] + ->aucblackMACList[i]), + rbssid); + fgIsValid = FALSE; + return fgIsValid; + } + } + } + } + } else { + for (i = 0; i < P2P_MAXIMUM_CLIENT_COUNT; i++) { + if (EQUAL_MAC_ADDR( + &(prGlueInfo->prP2PInfo[ucRoleIndex] + ->aucblackMACList[i]), rbssid)) { + COPY_MAC_ADDR( + &(prGlueInfo->prP2PInfo[ucRoleIndex] + ->aucblackMACList[i]), aucNullAddr); + + fgIsValid = FALSE; + return fgIsValid; + } + } + } + + return fgIsValid; + +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief to compare the black list of Hotspot + * + * \param[in] + * prGlueInfo + * + * \return + */ +/*---------------------------------------------------------------------------*/ +u_int8_t kalP2PCmpBlackList(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t rbssid[PARAM_MAC_ADDR_LEN], + IN uint8_t ucRoleIndex) +{ + uint8_t aucNullAddr[] = NULL_MAC_ADDR; + u_int8_t fgIsExsit = FALSE; + uint32_t i; + + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo[ucRoleIndex]); + + for (i = 0; i < P2P_MAXIMUM_CLIENT_COUNT; i++) { + if (UNEQUAL_MAC_ADDR(rbssid, aucNullAddr)) { + if (EQUAL_MAC_ADDR( + &(prGlueInfo->prP2PInfo + [ucRoleIndex]->aucblackMACList[i]), + rbssid)) { + fgIsExsit = TRUE; + return fgIsExsit; + } + } + } + + return fgIsExsit; + +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief to return the max clients of Hotspot + * + * \param[in] + * prGlueInfo + * + * \return + */ +/*---------------------------------------------------------------------------*/ +void kalP2PSetMaxClients(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4MaxClient, + IN uint8_t ucRoleIndex) +{ + ASSERT(prGlueInfo); + + if (prGlueInfo->prP2PInfo[ucRoleIndex] == NULL) + return; + + if (u4MaxClient == 0 || + prGlueInfo->prP2PInfo[ucRoleIndex]->ucMaxClients + >= P2P_MAXIMUM_CLIENT_COUNT) + prGlueInfo->prP2PInfo[ucRoleIndex]->ucMaxClients = + P2P_MAXIMUM_CLIENT_COUNT; + else + prGlueInfo->prP2PInfo[ucRoleIndex]->ucMaxClients = u4MaxClient; +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief to return the max clients of Hotspot + * + * \param[in] + * prGlueInfo + * + * \return + */ +/*---------------------------------------------------------------------------*/ +u_int8_t kalP2PMaxClients(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4NumClient, IN uint8_t ucRoleIndex) +{ + ASSERT(prGlueInfo); + + if (prGlueInfo->prP2PInfo[ucRoleIndex] && + prGlueInfo->prP2PInfo[ucRoleIndex]->ucMaxClients) { + if ((uint8_t) u4NumClient + > prGlueInfo->prP2PInfo[ucRoleIndex]->ucMaxClients) + return TRUE; + else + return FALSE; + } + + return FALSE; +} + +#endif + +void kalP2pUnlinkBss(IN struct GLUE_INFO *prGlueInfo, IN uint8_t aucBSSID[]) +{ + struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL; + struct cfg80211_bss *bss = NULL; + + ASSERT(prGlueInfo); + ASSERT(aucBSSID); + + DBGLOG(P2P, INFO, "bssid: " MACSTR "\n", MAC2STR(aucBSSID)); + + prGlueP2pInfo = prGlueInfo->prP2PInfo[0]; + + if (prGlueP2pInfo == NULL) + return; + +#if (KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE) + bss = cfg80211_get_bss(prGlueP2pInfo->prWdev->wiphy, + NULL, /* channel */ + aucBSSID, + NULL, /* ssid */ + 0, /* ssid length */ + IEEE80211_BSS_TYPE_ESS, + IEEE80211_PRIVACY_ANY); +#else + bss = cfg80211_get_bss(prGlueP2pInfo->prWdev->wiphy, + NULL, /* channel */ + aucBSSID, + NULL, /* ssid */ + 0, /* ssid length */ + WLAN_CAPABILITY_ESS, + WLAN_CAPABILITY_ESS); +#endif + + if (bss != NULL) { + cfg80211_unlink_bss(prGlueP2pInfo->prWdev->wiphy, bss); + cfg80211_put_bss(prGlueP2pInfo->prWdev->wiphy, bss); + } + + if (scanSearchBssDescByBssidAndSsid(prGlueInfo->prAdapter, + aucBSSID, FALSE, NULL) != NULL) + scanRemoveBssDescByBssid(prGlueInfo->prAdapter, aucBSSID); +} + +void kalP2pIndicateQueuedMgmtFrame(IN struct GLUE_INFO *prGlueInfo, + IN struct P2P_QUEUED_ACTION_FRAME *prFrame) +{ + struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL; + struct net_device *prNetdevice = (struct net_device *) NULL; + + if ((prGlueInfo == NULL) || (prFrame == NULL)) { + ASSERT(FALSE); + return; + } + + DBGLOG(P2P, INFO, "Indicate queued p2p action frame.\n"); + + if (prFrame->prHeader == NULL || prFrame->u2Length == 0) { + DBGLOG(P2P, WARN, "Frame pointer is null or length is 0.\n"); + return; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo[prFrame->ucRoleIdx]; + prNetdevice = prGlueP2pInfo->prDevHandler; + +#if (KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE) + cfg80211_rx_mgmt( + /* struct net_device * dev, */ + prNetdevice->ieee80211_ptr, + prFrame->u4Freq, + 0, + prFrame->prHeader, + prFrame->u2Length, + NL80211_RXMGMT_FLAG_ANSWERED); +#elif (KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE) + cfg80211_rx_mgmt( + /* struct net_device * dev, */ + prNetdevice->ieee80211_ptr, + prFrame->u4Freq, + 0, + prFrame->prHeader, + prFrame->u2Length, + NL80211_RXMGMT_FLAG_ANSWERED, + GFP_ATOMIC); +#else + cfg80211_rx_mgmt( + /* struct net_device * dev, */ + prNetdevice->ieee80211_ptr, + prFrame->u4Freq, + 0, + prFrame->prHeader, + prFrame->u2Length, + GFP_ATOMIC); +#endif +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_proc.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_proc.c new file mode 100644 index 0000000000000..fe4f8100da22e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_proc.c @@ -0,0 +1,3033 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: /os/linux/gl_proc.c + */ + +/*! \file "gl_proc.c" + * \brief This file defines the interface which can interact with users + * in /proc fs. + * + * Detail description. + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" +#include "gl_os.h" +#include "gl_kal.h" +#include "debug.h" +#include "wlan_lib.h" +#include "debug.h" +#include "wlan_oid.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define PROC_MCR_ACCESS "mcr" +#define PROC_ROOT_NAME "wlan" + +#if CFG_SUPPORT_DEBUG_FS +#define PROC_ROAM_PARAM "roam_param" +#endif +#define PROC_COUNTRY "country" +#define PROC_DRV_STATUS "status" +#define PROC_RX_STATISTICS "rx_statistics" +#define PROC_TX_STATISTICS "tx_statistics" +#define PROC_DBG_LEVEL_NAME "dbgLevel" +#define PROC_DRIVER_CMD "driver" +#define PROC_CFG "cfg" +#define PROC_EFUSE_DUMP "efuse_dump" +#define PROC_GET_TXPWR_TBL "get_txpwr_tbl" +#define PROC_PKT_DELAY_DBG "pktDelay" +#if CFG_SUPPORT_SET_CAM_BY_PROC +#define PROC_SET_CAM "setCAM" +#endif +#define PROC_AUTO_PERF_CFG "autoPerfCfg" + +#if CFG_DISCONN_DEBUG_FEATURE +#define PROC_DISCONN_INFO "disconn_info" +#endif + +#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 +#define PROC_UID_SHELL 2000 +#define PROC_GID_WIFI 1010 + +/* notice: str only can be an array */ +#define SNPRINTF(buf, str, arg) {buf += \ + snprintf((char *)(buf), sizeof(str)-kalStrLen(str), PRINTF_ARG arg); } + +#ifdef CFG_GET_TEMPURATURE +#define PROC_GET_TEMPETATURE "get_temperature" +#endif + + +/******************************************************************************* + * 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 struct GLUE_INFO *g_prGlueInfo_proc; +static uint32_t u4McrOffset; +static struct proc_dir_entry *gprProcRoot; +static uint8_t aucDbModuleName[][PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN] = { + "INIT", "HAL", "INTR", "REQ", "TX", "RX", "RFTEST", "EMU", + "SW1", "SW2", "SW3", "SW4", "HEM", "AIS", "RLM", "MEM", + "CNM", "RSN", "BSS", "SCN", "SAA", "AAA", "P2P", "QM", + "SEC", "BOW", "WAPI", "ROAMING", "TDLS", "PF", "OID", "NIC" +}; + +/* This buffer could be overwrite by any proc commands */ +static uint8_t g_aucProcBuf[3000]; + +/* This u32 is only for DriverCmdRead/Write, + * should not be used by other function + */ +static int32_t g_NextDriverReadLen; +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +#define GET_VARNAME(var) #var + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +static ssize_t procDbgLevelRead(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + uint8_t *temp = &g_aucProcBuf[0]; + uint8_t *str = NULL; + uint32_t u4CopySize = 0; + uint16_t i; + uint16_t u2ModuleNum = 0; + uint32_t u4StrLen = 0; + uint32_t u4Level1, u4Level2; + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0 || buf == NULL) + return 0; + + str = "\nTEMP|LOUD|INFO|TRACE | EVENT|STATE|WARN|ERROR\n" + "bit7|bit6|bit5|bit4 | bit3|bit2|bit1|bit0\n\n" + "Usage: Module Index:Module Level, such as 0x00:0xff\n\n" + "Debug Module\tIndex\tLevel\tDebug Module\tIndex\tLevel\n\n"; + u4StrLen = kalStrLen(str); + kalStrnCpy(temp, str, u4StrLen + 1); + temp += kalStrLen(temp); + + u2ModuleNum = + (sizeof(aucDbModuleName) / + PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN) & 0xfe; + + for (i = 0; i < u2ModuleNum; i += 2) { + wlanGetDriverDbgLevel(i, &u4Level1); + wlanGetDriverDbgLevel(i + 1, &u4Level2); + SNPRINTF(temp, g_aucProcBuf, + ("DBG_%s_IDX\t(0x%02x):\t0x%02x\t" + "DBG_%s_IDX\t(0x%02x):\t0x%02x\n", + &aucDbModuleName[i][0], i, (uint8_t) u4Level1, + &aucDbModuleName[i + 1][0], i + 1, + (uint8_t) u4Level2)); + } + + if ((sizeof(aucDbModuleName) / + PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN) & 0x1) { + wlanGetDriverDbgLevel(u2ModuleNum, &u4Level1); + SNPRINTF(temp, g_aucProcBuf, + ("DBG_%s_IDX\t(0x%02x):\t0x%02x\n", + &aucDbModuleName[u2ModuleNum][0], u2ModuleNum, + (uint8_t) u4Level1)); + } + + u4CopySize = kalStrLen(g_aucProcBuf); + if (u4CopySize > count) + u4CopySize = count; + if (copy_to_user(buf, g_aucProcBuf, u4CopySize)) { + DBGLOG(INIT, ERROR, "copy to user failed\n"); + return -EFAULT; + } + + *f_pos += u4CopySize; + return (ssize_t) u4CopySize; +} + +#if WLAN_INCLUDE_PROC +#if CFG_SUPPORT_EASY_DEBUG + +static void *procEfuseDump_start(struct seq_file *s, loff_t *pos) +{ + static unsigned long counter; + + if (*pos == 0) + counter = *pos; /* read file init */ + + if (counter >= EFUSE_ADDR_MAX) + return NULL; + return &counter; +} + +static void *procEfuseDump_next(struct seq_file *s, void *v, loff_t *pos) +{ + unsigned long *tmp_v = (unsigned long *)v; + + (*tmp_v) += EFUSE_BLOCK_SIZE; + + if (*tmp_v >= EFUSE_ADDR_MAX) + return NULL; + return tmp_v; +} + +static void procEfuseDump_stop(struct seq_file *s, void *v) +{ + /* nothing to do, we use a static value in start() */ +} + +static int procEfuseDump_show(struct seq_file *s, void *v) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo; + uint32_t idx_addr, idx_value; + struct PARAM_CUSTOM_ACCESS_EFUSE rAccessEfuseInfo = { }; + + prGlueInfo = g_prGlueInfo_proc; + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + ASSERT(prGlueInfo); + if (prGlueInfo->prAdapter && + prGlueInfo->prAdapter->chip_info && + !prGlueInfo->prAdapter->chip_info->is_support_efuse) { + seq_puts(s, "efuse ops is invalid\n"); + return -EPERM; /* return negative value to stop read process */ + } + + idx_addr = *(loff_t *) v; + rAccessEfuseInfo.u4Address = + (idx_addr / EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfo, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), TRUE, TRUE, + TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + seq_printf(s, "efuse read fail (0x%03X)\n", + rAccessEfuseInfo.u4Address); + return 0; + } + + for (idx_value = 0; idx_value < EFUSE_BLOCK_SIZE; idx_value++) + seq_printf(s, "0x%03X=0x%02X\n", + rAccessEfuseInfo.u4Address + idx_value, + prGlueInfo->prAdapter->aucEepromVaule[idx_value]); + return 0; +#else + seq_puts(s, "efuse ops is invalid\n"); + return -EPERM; /* return negative value to stop read process */ +#endif +} + +static int procEfuseDumpOpen(struct inode *inode, struct file *file) +{ + static const struct seq_operations procEfuseDump_ops = { + .start = procEfuseDump_start, + .next = procEfuseDump_next, + .stop = procEfuseDump_stop, + .show = procEfuseDump_show + }; + + return seq_open(file, &procEfuseDump_ops); +} + +static ssize_t procCfgRead(struct file *filp, char __user *buf, size_t count, + loff_t *f_pos) +{ + uint8_t *temp = &g_aucProcBuf[0]; + uint8_t *str = NULL; + uint8_t *str2 = "\nERROR DUMP CONFIGURATION:\n"; + uint32_t u4CopySize = 0; + uint32_t i; + uint32_t u4StrLen = 0; + +#define BUFFER_RESERVE_BYTE 50 + + struct GLUE_INFO *prGlueInfo; + + struct WLAN_CFG_ENTRY *prWlanCfgEntry; + struct ADAPTER *prAdapter; + + prGlueInfo = *((struct GLUE_INFO **)netdev_priv(gPrDev)); + + if (!prGlueInfo) { + DBGLOG(INIT, ERROR, "procCfgRead prGlueInfo is NULL????\n"); + return 0; + } + + prAdapter = prGlueInfo->prAdapter; + + if (!prAdapter) { + DBGLOG(INIT, ERROR, "procCfgRead prAdapter is NULL????\n"); + return 0; + } + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0 || buf == NULL) + return 0; + + str = "\nDUMP CONFIGURATION :\n" + " OR \n" + "'D': driver part current setting\n" + "===================================\n"; + u4StrLen = kalStrLen(str); + kalStrnCpy(temp, str, u4StrLen + 1); + temp += kalStrLen(temp); + + for (i = 0; i < WLAN_CFG_ENTRY_NUM_MAX; i++) { + prWlanCfgEntry = wlanCfgGetEntryByIndex(prAdapter, i, 0); + + if ((!prWlanCfgEntry) || (prWlanCfgEntry->aucKey[0] == '\0')) + break; + + SNPRINTF(temp, g_aucProcBuf, + ("%s|%s\n", prWlanCfgEntry->aucKey, + prWlanCfgEntry->aucValue)); + + if ((temp - g_aucProcBuf) != kalStrLen(g_aucProcBuf)) { + DBGLOG(INIT, ERROR, + "Dump configuration error: temp offset=%d, buf length=%u, key[%d]=[%u], val[%d]=[%u]\n", + (int)(temp - g_aucProcBuf), + (uint32_t)kalStrLen(g_aucProcBuf), + WLAN_CFG_VALUE_LEN_MAX, + (uint32_t)prWlanCfgEntry->aucKey[ + WLAN_CFG_VALUE_LEN_MAX - 1], + WLAN_CFG_VALUE_LEN_MAX, + (uint32_t)prWlanCfgEntry->aucValue[ + WLAN_CFG_VALUE_LEN_MAX - 1]); + kalMemSet(g_aucProcBuf, ' ', u4StrLen); + kalStrnCpy(g_aucProcBuf, str2, kalStrLen(str2) + 1); + goto procCfgReadLabel; + } + + if (kalStrLen(g_aucProcBuf) > + (sizeof(g_aucProcBuf) - BUFFER_RESERVE_BYTE)) + break; + } + + for (i = 0; i < WLAN_CFG_REC_ENTRY_NUM_MAX; i++) { + prWlanCfgEntry = wlanCfgGetEntryByIndex(prAdapter, i, 1); + + + if ((!prWlanCfgEntry) || (prWlanCfgEntry->aucKey[0] == '\0')) + break; + + SNPRINTF(temp, g_aucProcBuf, + ("D:%s|%s\n", prWlanCfgEntry->aucKey, + prWlanCfgEntry->aucValue)); + + if ((temp - g_aucProcBuf) != kalStrLen(g_aucProcBuf)) { + DBGLOG(INIT, ERROR, + "D:Dump configuration error: temp offset=%d, buf length=%u, key[%d]=[%u], val[%d]=[%u]\n", + (int)(temp - g_aucProcBuf), + (uint32_t)kalStrLen(g_aucProcBuf), + WLAN_CFG_VALUE_LEN_MAX, + (uint32_t)prWlanCfgEntry->aucKey[ + WLAN_CFG_VALUE_LEN_MAX - 1], + WLAN_CFG_VALUE_LEN_MAX, + (uint32_t)prWlanCfgEntry->aucValue[ + WLAN_CFG_VALUE_LEN_MAX - 1]); + kalMemSet(g_aucProcBuf, ' ', u4StrLen); + kalStrnCpy(g_aucProcBuf, str2, kalStrLen(str2) + 1); + goto procCfgReadLabel; + } + + if (kalStrLen(g_aucProcBuf) > + (sizeof(g_aucProcBuf) - BUFFER_RESERVE_BYTE)) + break; + } + +procCfgReadLabel: + u4CopySize = kalStrLen(g_aucProcBuf); + if (u4CopySize > count) + u4CopySize = count; + if (copy_to_user(buf, g_aucProcBuf, u4CopySize)) { + DBGLOG(INIT, ERROR, "copy to user failed\n"); + return -EFAULT; + } + + *f_pos += u4CopySize; + return (ssize_t) u4CopySize; +} + +static ssize_t procCfgWrite(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + + /* uint32_t u4DriverCmd, u4DriverValue; + *uint8_t *temp = &g_aucProcBuf[0]; + */ + int32_t i4CopySize = sizeof(g_aucProcBuf)-8; + struct GLUE_INFO *prGlueInfo; + uint8_t *pucTmp; + /* PARAM_CUSTOM_P2P_SET_STRUCT_T rSetP2P; */ + + + kalMemSet(g_aucProcBuf, 0, i4CopySize); + i4CopySize = (count < i4CopySize) ? count : (i4CopySize - 1); + + pucTmp = g_aucProcBuf; + SNPRINTF(pucTmp, g_aucProcBuf, ("%s ", "set_cfg")); + + if ((i4CopySize < 0) || (copy_from_user(pucTmp, buffer, i4CopySize))) { + DBGLOG(INIT, ERROR, "error of copy from user\n"); + return -EFAULT; + } + g_aucProcBuf[i4CopySize + 8] = '\0'; + + + prGlueInfo = g_prGlueInfo_proc; + /* if g_u4NextDriverReadLen >0, + * the content for next DriverCmdRead will be + * in : g_aucProcBuf with length : g_u4NextDriverReadLen + */ + g_NextDriverReadLen = + priv_driver_set_cfg(prGlueInfo->prDevHandler, g_aucProcBuf, + sizeof(g_aucProcBuf)); + + return count; + +} + +static ssize_t procDriverCmdRead(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + /* DriverCmd read should only be executed right after + * a DriverCmd write because content buffer 'g_aucProcBuf' + * is a global buffer for all proc command, otherwise , + * the content could be overwrite by other proc command + */ + uint32_t u4CopySize = 0; + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0 || buf == NULL) + return 0; + + if (g_NextDriverReadLen > 0) /* Detect content to show */ + u4CopySize = g_NextDriverReadLen; + + if (u4CopySize > count) + u4CopySize = count; + + if (copy_to_user(buf, g_aucProcBuf, u4CopySize)) { + DBGLOG(INIT, ERROR, "copy to user failed\n"); + return -EFAULT; + } + g_NextDriverReadLen = 0; + + *f_pos += u4CopySize; + return (ssize_t) u4CopySize; +} + + + +static ssize_t procDriverCmdWrite(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ +/* UINT_32 u4DriverCmd, u4DriverValue; + * UINT_8 *temp = &g_aucProcBuf[0]; + */ + uint32_t u4CopySize = sizeof(g_aucProcBuf); + struct GLUE_INFO *prGlueInfo; +/* PARAM_CUSTOM_P2P_SET_STRUCT_T rSetP2P; */ + + kalMemSet(g_aucProcBuf, 0, u4CopySize); + u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1); + + if (copy_from_user(g_aucProcBuf, buffer, u4CopySize)) { + DBGLOG(INIT, ERROR, "error of copy from user\n"); + return -EFAULT; + } + g_aucProcBuf[u4CopySize] = '\0'; + + + prGlueInfo = g_prGlueInfo_proc; + /* if g_u4NextDriverReadLen >0, + * the content for next DriverCmdRead will be + * in : g_aucProcBuf with length : g_u4NextDriverReadLen + */ + g_NextDriverReadLen = + priv_driver_cmds(prGlueInfo->prDevHandler, g_aucProcBuf, + sizeof(g_aucProcBuf)); + + return count; +} +#endif +#endif + +static ssize_t procDbgLevelWrite(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + uint32_t u4NewDbgModule, u4NewDbgLevel; + uint8_t *temp = &g_aucProcBuf[0]; + uint32_t u4CopySize = sizeof(g_aucProcBuf); + + kalMemSet(g_aucProcBuf, 0, u4CopySize); + u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1); + + if (copy_from_user(g_aucProcBuf, buffer, u4CopySize)) { + DBGLOG(INIT, ERROR, "error of copy from user\n"); + return -EFAULT; + } + g_aucProcBuf[u4CopySize] = '\0'; + + /*add chip reset cmd for manual test*/ +#if CFG_CHIP_RESET_SUPPORT + if (temp[0] == 'R') { + + DBGLOG(INIT, ERROR, "WIFI trigger reset!!\n"); + glGetRstReason(RST_CMD_TRIGGER); + GL_RESET_TRIGGER(g_prGlueInfo_proc->prAdapter, + RST_FLAG_CHIP_RESET); + temp[0] = 'X'; + } +#endif + + while (temp) { + if (sscanf(temp, + "0x%x:0x%x", &u4NewDbgModule, &u4NewDbgLevel) != 2) { + DBGLOG(INIT, INFO, + "debug module and debug level should be one byte in length\n"); + break; + } + if (u4NewDbgModule == 0xFF) { + wlanSetDriverDbgLevel(DBG_ALL_MODULE_IDX, + (u4NewDbgLevel & DBG_CLASS_MASK)); + break; + } + if (u4NewDbgModule >= DBG_MODULE_NUM) { + DBGLOG(INIT, INFO, + "debug module index should less than %d\n", + DBG_MODULE_NUM); + break; + } + wlanSetDriverDbgLevel(u4NewDbgModule, + (u4NewDbgLevel & DBG_CLASS_MASK)); + temp = kalStrChr(temp, ','); + if (!temp) + break; + temp++; /* skip ',' */ + } + return count; +} + +#define TXPWR_TABLE_ENTRY(_siso_mcs, _cdd_mcs, _mimo_mcs, _idx) \ +{ \ + .mcs[STREAM_SISO] = _siso_mcs, \ + .mcs[STREAM_CDD] = _cdd_mcs, \ + .mcs[STREAM_MIMO] = _mimo_mcs, \ + .idx = (_idx), \ +} + +static struct txpwr_table_entry dsss[] = { + TXPWR_TABLE_ENTRY("DSSS1", "", "", MODULATION_SYSTEM_CCK_1M), + TXPWR_TABLE_ENTRY("DSSS2", "", "", MODULATION_SYSTEM_CCK_2M), + TXPWR_TABLE_ENTRY("CCK5", "", "", MODULATION_SYSTEM_CCK_5M), + TXPWR_TABLE_ENTRY("CCK11", "", "", MODULATION_SYSTEM_CCK_11M), +}; + +static struct txpwr_table_entry ofdm[] = { + TXPWR_TABLE_ENTRY("OFDM6", "OFDM6", "", MODULATION_SYSTEM_OFDM_6M), + TXPWR_TABLE_ENTRY("OFDM9", "OFDM9", "", MODULATION_SYSTEM_OFDM_9M), + TXPWR_TABLE_ENTRY("OFDM12", "OFDM12", "", MODULATION_SYSTEM_OFDM_12M), + TXPWR_TABLE_ENTRY("OFDM18", "OFDM18", "", MODULATION_SYSTEM_OFDM_18M), + TXPWR_TABLE_ENTRY("OFDM24", "OFDM24", "", MODULATION_SYSTEM_OFDM_24M), + TXPWR_TABLE_ENTRY("OFDM36", "OFDM36", "", MODULATION_SYSTEM_OFDM_36M), + TXPWR_TABLE_ENTRY("OFDM48", "OFDM48", "", MODULATION_SYSTEM_OFDM_48M), + TXPWR_TABLE_ENTRY("OFDM54", "OFDM54", "", MODULATION_SYSTEM_OFDM_54M), +}; + +static struct txpwr_table_entry ht20[] = { + TXPWR_TABLE_ENTRY("MCS0", "MCS0", "MCS8", MODULATION_SYSTEM_HT20_MCS0), + TXPWR_TABLE_ENTRY("MCS1", "MCS1", "MCS9", MODULATION_SYSTEM_HT20_MCS1), + TXPWR_TABLE_ENTRY("MCS2", "MCS2", "MCS10", MODULATION_SYSTEM_HT20_MCS2), + TXPWR_TABLE_ENTRY("MCS3", "MCS3", "MCS11", MODULATION_SYSTEM_HT20_MCS3), + TXPWR_TABLE_ENTRY("MCS4", "MCS4", "MCS12", MODULATION_SYSTEM_HT20_MCS4), + TXPWR_TABLE_ENTRY("MCS5", "MCS5", "MCS13", MODULATION_SYSTEM_HT20_MCS5), + TXPWR_TABLE_ENTRY("MCS6", "MCS6", "MCS14", MODULATION_SYSTEM_HT20_MCS6), + TXPWR_TABLE_ENTRY("MCS7", "MCS7", "MCS15", MODULATION_SYSTEM_HT20_MCS7), +}; +static struct txpwr_table_entry ht40[] = { + TXPWR_TABLE_ENTRY("MCS0", "MCS0", "MCS8", MODULATION_SYSTEM_HT40_MCS0), + TXPWR_TABLE_ENTRY("MCS1", "MCS1", "MCS9", MODULATION_SYSTEM_HT40_MCS1), + TXPWR_TABLE_ENTRY("MCS2", "MCS2", "MCS10", MODULATION_SYSTEM_HT40_MCS2), + TXPWR_TABLE_ENTRY("MCS3", "MCS3", "MCS11", MODULATION_SYSTEM_HT40_MCS3), + TXPWR_TABLE_ENTRY("MCS4", "MCS4", "MCS12", MODULATION_SYSTEM_HT40_MCS4), + TXPWR_TABLE_ENTRY("MCS5", "MCS5", "MCS13", MODULATION_SYSTEM_HT40_MCS5), + TXPWR_TABLE_ENTRY("MCS6", "MCS6", "MCS14", MODULATION_SYSTEM_HT40_MCS6), + TXPWR_TABLE_ENTRY("MCS7", "MCS7", "MCS15", MODULATION_SYSTEM_HT40_MCS7), + TXPWR_TABLE_ENTRY("MCS32", "MCS32", "MCS32", + MODULATION_SYSTEM_HT40_MCS32), +}; +static struct txpwr_table_entry vht[] = { + TXPWR_TABLE_ENTRY("MCS0", "MCS0", "MCS0", MODULATION_SYSTEM_VHT20_MCS0), + TXPWR_TABLE_ENTRY("MCS1", "MCS1", "MCS1", MODULATION_SYSTEM_VHT20_MCS1), + TXPWR_TABLE_ENTRY("MCS2", "MCS2", "MCS2", MODULATION_SYSTEM_VHT20_MCS2), + TXPWR_TABLE_ENTRY("MCS3", "MCS3", "MCS3", MODULATION_SYSTEM_VHT20_MCS3), + TXPWR_TABLE_ENTRY("MCS4", "MCS4", "MCS4", MODULATION_SYSTEM_VHT20_MCS4), + TXPWR_TABLE_ENTRY("MCS5", "MCS5", "MCS5", MODULATION_SYSTEM_VHT20_MCS5), + TXPWR_TABLE_ENTRY("MCS6", "MCS6", "MCS6", MODULATION_SYSTEM_VHT20_MCS6), + TXPWR_TABLE_ENTRY("MCS7", "MCS7", "MCS7", MODULATION_SYSTEM_VHT20_MCS7), + TXPWR_TABLE_ENTRY("MCS8", "MCS8", "MCS8", MODULATION_SYSTEM_VHT20_MCS8), + TXPWR_TABLE_ENTRY("MCS9", "MCS9", "MCS9", MODULATION_SYSTEM_VHT20_MCS9), +}; + +static struct txpwr_table txpwr_tables[] = { + {"Legacy", dsss, ARRAY_SIZE(dsss)}, + {"11g", ofdm, ARRAY_SIZE(ofdm)}, + {"11a", ofdm, ARRAY_SIZE(ofdm)}, + {"HT20", ht20, ARRAY_SIZE(ht20)}, + {"HT40", ht40, ARRAY_SIZE(ht40)}, + {"VHT20", vht, ARRAY_SIZE(vht)}, + {"VHT40", vht, ARRAY_SIZE(vht)}, + {"VHT80", vht, ARRAY_SIZE(vht)}, + {"VHT160", vht, ARRAY_SIZE(vht)}, +}; + +#define TMP_SZ (512) +#define CDD_PWR_OFFSET (6) +#define TXPWR_DUMP_SZ (8192) +void print_txpwr_tbl(struct txpwr_table *txpwr_tbl, unsigned char ch, + unsigned char *tx_pwr[], char pwr_offset[], + char *stream_buf[], unsigned int stream_pos[]) +{ + struct txpwr_table_entry *tmp_tbl = txpwr_tbl->tables; + unsigned int idx, pwr_idx, stream_idx; + char pwr[TXPWR_TBL_NUM] = {0}, tmp_pwr = 0; + char prefix[5], tmp[4]; + char *buf = NULL; + unsigned int *pos = NULL; + int i; + + for (i = 0; i < txpwr_tbl->n_tables; i++) { + idx = tmp_tbl[i].idx; + + for (pwr_idx = 0; pwr_idx < TXPWR_TBL_NUM; pwr_idx++) { + if (!tx_pwr[pwr_idx]) { + DBGLOG(REQ, WARN, + "Power table[%d] is NULL\n", pwr_idx); + return; + } + pwr[pwr_idx] = tx_pwr[pwr_idx][idx] + + pwr_offset[pwr_idx]; + pwr[pwr_idx] = (pwr[pwr_idx] > MAX_TX_POWER) ? + MAX_TX_POWER : pwr[pwr_idx]; + } + + for (stream_idx = 0; stream_idx < STREAM_NUM; stream_idx++) { + buf = stream_buf[stream_idx]; + pos = &stream_pos[stream_idx]; + + if (tmp_tbl[i].mcs[stream_idx][0] == '\0') + continue; + + switch (stream_idx) { + case STREAM_SISO: + kalStrnCpy(prefix, "siso", sizeof(prefix)); + break; + case STREAM_CDD: + kalStrnCpy(prefix, "cdd", sizeof(prefix)); + break; + case STREAM_MIMO: + kalStrnCpy(prefix, "mimo", sizeof(prefix)); + break; + } + + *pos += kalScnprintf(buf + *pos, TMP_SZ - *pos, + "%s, %d, %s, %s, ", + prefix, ch, + txpwr_tbl->phy_mode, + tmp_tbl[i].mcs[stream_idx]); + + for (pwr_idx = 0; pwr_idx < TXPWR_TBL_NUM; pwr_idx++) { + tmp_pwr = pwr[pwr_idx]; + + tmp_pwr = (tmp_pwr > 0) ? tmp_pwr : 0; + + if (pwr_idx + 1 == TXPWR_TBL_NUM) + kalStrnCpy(tmp, "\n", sizeof(tmp)); + else + kalStrnCpy(tmp, ", ", sizeof(tmp)); + *pos += kalScnprintf(buf + *pos, TMP_SZ - *pos, + "%d.%d%s", + tmp_pwr / 2, + tmp_pwr % 2 * 5, + tmp); + + } + } + } +} + +char *g_txpwr_tbl_read_buffer; +char *g_txpwr_tbl_read_buffer_head; +unsigned int g_txpwr_tbl_read_residual; + +static ssize_t procGetTxpwrTblRead(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct BSS_INFO *prBssInfo = NULL; + unsigned char ucBssIndex; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = NULL; + uint32_t status; + struct PARAM_CMD_GET_TXPWR_TBL pwr_tbl; + struct POWER_LIMIT *tx_pwr_tbl = pwr_tbl.tx_pwr_tbl; + char *buffer; + unsigned int pos = 0, buf_len = TXPWR_DUMP_SZ, oid_len; + unsigned char i, j; + char *stream_buf[STREAM_NUM] = {NULL}; + unsigned int stream_pos[STREAM_NUM] = {0}; + unsigned char *tx_pwr[TXPWR_TBL_NUM] = {NULL}; + char pwr_offset[TXPWR_TBL_NUM] = {0}; + int ret; + + if (*f_pos > 0) { /* re-entry */ + pos = g_txpwr_tbl_read_residual; + buffer = g_txpwr_tbl_read_buffer; + goto next_entry; + } + + prGlueInfo = g_prGlueInfo_proc; + if (!prGlueInfo) + return -EFAULT; + + prAdapter = prGlueInfo->prAdapter; + prNetDevPrivate = + (struct NETDEV_PRIVATE_GLUE_INFO *) netdev_priv(gPrDev); + + if (prNetDevPrivate->prGlueInfo != prGlueInfo) + return -EFAULT; + ucBssIndex = prNetDevPrivate->ucBssIdx; + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + if (!prBssInfo) + return -EFAULT; + + kalMemZero(&pwr_tbl, sizeof(pwr_tbl)); + /* MT7663 no DBDC design */ +#if 0 + if (prAdapter->rWifiVar.fgDbDcModeEn) + pwr_tbl.ucDbdcIdx = prBssInfo->eDBDCBand; + else + pwr_tbl.ucDbdcIdx = ENUM_BAND_0; +#endif + status = kalIoctl(prGlueInfo, + wlanoidGetTxPwrTbl, + &pwr_tbl, + sizeof(pwr_tbl), TRUE, FALSE, TRUE, &oid_len); + + if (status != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "Query Tx Power Table fail\n"); + return -EINVAL; + } + + buffer = (char *) kalMemAlloc(buf_len, VIR_MEM_TYPE); + if (!buffer) + return -ENOMEM; + + g_txpwr_tbl_read_buffer = buffer; + g_txpwr_tbl_read_buffer_head = buffer; + + for (i = 0; i < STREAM_NUM; i++) { + stream_buf[i] = (char *) kalMemAlloc(TMP_SZ, VIR_MEM_TYPE); + if (!stream_buf[i]) { + ret = -ENOMEM; + goto out; + } + } + + pos = kalScnprintf(buffer, buf_len, + "\n%s", + "spatial stream, Channel, bw, modulation, "); + pos += kalScnprintf(buffer + pos, buf_len - pos, + "%s\n", + "regulatory limit, board limit, target power"); + + for (i = 0; i < ARRAY_SIZE(txpwr_tables); i++) { + for (j = 0; j < STREAM_NUM; j++) { + kalMemZero(stream_buf[j], TMP_SZ); + stream_pos[j] = 0; + } + + for (j = 0; j < TXPWR_TBL_NUM; j++) { + tx_pwr[j] = NULL; + pwr_offset[j] = 0; + } + + switch (i) { + case DSSS: + if (pwr_tbl.ucCenterCh > 14) + continue; + for (j = 0; j < TXPWR_TBL_NUM; j++) + tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_dsss; + break; + case OFDM_24G: + if (pwr_tbl.ucCenterCh > 14) + continue; + for (j = 0; j < TXPWR_TBL_NUM; j++) + tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_ofdm; + break; + case OFDM_5G: + if (pwr_tbl.ucCenterCh <= 14) + continue; + for (j = 0; j < TXPWR_TBL_NUM; j++) + tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_ofdm; + break; + case HT20: + for (j = 0; j < TXPWR_TBL_NUM; j++) + tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_ht20; + break; + case HT40: + for (j = 0; j < TXPWR_TBL_NUM; j++) + tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_ht40; + break; + case VHT20: + if (pwr_tbl.ucCenterCh <= 14) + continue; + for (j = 0; j < TXPWR_TBL_NUM; j++) + tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_vht20; + break; +#if 0 + case VHT40: + case VHT80: + if (pwr_tbl.ucCenterCh <= 14) + continue; + offset = (i == VHT40) ? + PWR_Vht40_OFFSET : PWR_Vht80_OFFSET; + for (j = 0; j < TXPWR_TBL_NUM; j++) { + tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_vht20; + pwr_offset[j] = + tx_pwr_tbl[j].tx_pwr_vht_OFST[offset]; + /* Covert 7bit 2'complement value to 8bit */ + pwr_offset[j] |= (pwr_offset[j] & BIT(6)) ? + BIT(7) : 0; + } + break; +#else + case VHT40: + if (pwr_tbl.ucCenterCh <= 14) + continue; + for (j = 0; j < TXPWR_TBL_NUM; j++) + tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_vht40; + break; + case VHT80: + if (pwr_tbl.ucCenterCh <= 14) + continue; + for (j = 0; j < TXPWR_TBL_NUM; j++) + tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_vht80; + break; + case VHT160: + if (pwr_tbl.ucCenterCh <= 14) + continue; + for (j = 0; j < TXPWR_TBL_NUM; j++) + tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_vht160; + break; +#endif + default: + break; + } + + print_txpwr_tbl(&txpwr_tables[i], pwr_tbl.ucCenterCh, + tx_pwr, pwr_offset, + stream_buf, stream_pos); + + for (j = 0; j < STREAM_NUM; j++) { + pos += kalScnprintf(buffer + pos, buf_len - pos, + "%s", + stream_buf[j]); + } + } + + g_txpwr_tbl_read_residual = pos; + +next_entry: + if (pos > count) + pos = count; + + if (copy_to_user(buf, buffer, pos)) { + DBGLOG(INIT, ERROR, "copy to user failed\n"); + ret = -EFAULT; + goto out; + } + g_txpwr_tbl_read_buffer += pos; + g_txpwr_tbl_read_residual -= pos; + + *f_pos += pos; + ret = pos; +out: + if (ret == 0 || ret == -ENOMEM) { + for (i = 0; i < STREAM_NUM; i++) { + if (stream_buf[i]) + kalMemFree(stream_buf[i], VIR_MEM_TYPE, TMP_SZ); + } + if (g_txpwr_tbl_read_buffer_head) + kalMemFree(g_txpwr_tbl_read_buffer_head, + VIR_MEM_TYPE, buf_len); + g_txpwr_tbl_read_buffer = NULL; + g_txpwr_tbl_read_buffer_head = NULL; + g_txpwr_tbl_read_residual = 0; + } + + return ret; +} + +#ifdef CFG_GET_TEMPURATURE +static ssize_t proc_get_temperature(struct file *filp, + char __user *buf, + size_t count, + loff_t *f_pos) +{ + struct GLUE_INFO *prGlueInfo = NULL; + unsigned int pos = 0, buf_len = 128, oid_len; + char *buffer; + int temperature = 0; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + if (*f_pos > 0) + return 0; + + prGlueInfo = g_prGlueInfo_proc; + if (!prGlueInfo) + return -EFAULT; + + buffer = (char *) kalMemAlloc(buf_len, VIR_MEM_TYPE); + if (!buffer) + return -ENOMEM; + + rStatus = kalIoctl(prGlueInfo, + wlanoidGetTemperature, &temperature, + sizeof(temperature), TRUE, TRUE, TRUE, &oid_len); + + pos = kalScnprintf(buffer, buf_len, "Temperature = %d\n", temperature); + + if (copy_to_user(buf, buffer, pos)) { + DBGLOG(INIT, ERROR, "copy to user failed\n"); + kalMemFree(buffer, VIR_MEM_TYPE, buf_len); + return -EFAULT; + } + + *f_pos += pos; + + kalMemFree(buffer, VIR_MEM_TYPE, buf_len); + return pos; +} +#endif + +#if CFG_DISCONN_DEBUG_FEATURE +static int32_t parseTxRateInfo(IN char *pcBuffer, IN int i4Size, + IN struct TX_VECTOR_BBP_LATCH *prTxV) +{ + uint8_t rate, txmode, frmode, sgi, ldpc, nsts, stbc; + int8_t txpwr; + int32_t i4BytesWritten = 0; + + rate = TX_VECTOR_GET_TX_RATE(prTxV); + txmode = TX_VECTOR_GET_TX_MODE(prTxV); + frmode = TX_VECTOR_GET_TX_FRMODE(prTxV); + nsts = TX_VECTOR_GET_TX_NSTS(prTxV) + 1; + sgi = TX_VECTOR_GET_TX_SGI(prTxV); + ldpc = TX_VECTOR_GET_TX_LDPC(prTxV); + stbc = TX_VECTOR_GET_TX_STBC(prTxV); + txpwr = TX_VECTOR_GET_TX_PWR(prTxV); + + if (prTxV->u4TxVector1 == 0xFFFFFFFF) { + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%-26s%s%s\n", "Last TX Rate", " = ", "N/A"); + } else { + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%-26s%s", "Last TX Rate", " = "); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf( + pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%s, ", rate < 4 ? HW_TX_RATE_CCK_STR[rate] : + HW_TX_RATE_CCK_STR[4]); + else if (txmode == TX_RATE_MODE_OFDM) + i4BytesWritten += kalScnprintf( + pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%s, ", hw_rate_ofdm_str(rate)); + else if ((txmode == TX_RATE_MODE_HTMIX) || + (txmode == TX_RATE_MODE_HTGF)) + i4BytesWritten += kalScnprintf( + pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "MCS%d, ", rate); + else + i4BytesWritten += kalScnprintf( + pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "NSS%d_MCS%d, ", nsts, rate); + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, "%s, ", + frmode < 4 ? HW_TX_RATE_BW[frmode] : HW_TX_RATE_BW[4]); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf( + pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%s, ", rate < 4 ? "LP" : "SP"); + else if (txmode == TX_RATE_MODE_OFDM) + ; + else + i4BytesWritten += kalScnprintf( + pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%s, ", sgi == 0 ? "LGI" : "SGI"); + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, "%s%s%s\n", + txmode < 5 ? HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5], + stbc ? ", STBC, " : ", ", ldpc == 0 ? "BCC" : "LDPC"); + } + + return i4BytesWritten; +} + +static int32_t parseRxRateInfo(IN char *pcBuffer, IN int i4Size, + IN struct STA_RECORD *prStaRec) +{ + uint32_t txmode, rate, frmode, sgi, nsts, ldpc, stbc, groupid, mu; + int32_t i4BytesWritten = 0; + uint32_t u4RxVector0 = 0, u4RxVector1 = 0; + + u4RxVector0 = prStaRec->u4RxVector0; + u4RxVector1 = prStaRec->u4RxVector1; + + txmode = (u4RxVector0 & RX_VT_RX_MODE_MASK) >> RX_VT_RX_MODE_OFFSET; + rate = (u4RxVector0 & RX_VT_RX_RATE_MASK) >> RX_VT_RX_RATE_OFFSET; + frmode = (u4RxVector0 & RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET; + nsts = ((u4RxVector1 & RX_VT_NSTS_MASK) >> RX_VT_NSTS_OFFSET); + stbc = (u4RxVector0 & RX_VT_STBC_MASK) >> RX_VT_STBC_OFFSET; + sgi = u4RxVector0 & RX_VT_SHORT_GI; + ldpc = u4RxVector0 & RX_VT_LDPC; + groupid = (u4RxVector1 & RX_VT_GROUP_ID_MASK) >> RX_VT_GROUP_ID_OFFSET; + + if (groupid && groupid != 63) { + mu = 1; + } else { + mu = 0; + nsts += 1; + } + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, "%-26s%s", "Last RX Rate", " = "); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, "%s, ", + rate < 4 ? HW_TX_RATE_CCK_STR[rate] : + HW_TX_RATE_CCK_STR[4]); + else if (txmode == TX_RATE_MODE_OFDM) + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, "%s, ", + hw_rate_ofdm_str(rate)); + else if ((txmode == TX_RATE_MODE_HTMIX) || + (txmode == TX_RATE_MODE_HTGF)) + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, "MCS%d, ", rate); + else + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, "NSS%d_MCS%d, ", + nsts, rate); + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, "%s, ", + frmode < 4 ? HW_TX_RATE_BW[frmode] : HW_TX_RATE_BW[4]); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, "%s, ", + rate < 4 ? "LP" : "SP"); + else if (txmode == TX_RATE_MODE_OFDM) + ; + else + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, "%s, ", + sgi == 0 ? "LGI" : "SGI"); + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, "%s", stbc == 0 ? "" : "STBC, "); + + if (mu) { + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, "%s, %s, %s (%d)\n", + txmode < 5 ? HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5], + ldpc == 0 ? "BCC" : "LDPC", "MU", groupid); + } else { + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, "%s, %s\n", + txmode < 5 ? HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5], + ldpc == 0 ? "BCC" : "LDPC"); + } + + return i4BytesWritten; + +} + +static int32_t parseRxRssiInfo(IN char *pcBuffer, IN int i4Size, + IN struct ADAPTER *prAdapter, IN struct STA_RECORD *prStaRec) +{ + int32_t i4RSSI0 = 0, i4RSSI1 = 0, i4RSSI2 = 0, i4RSSI3 = 0; + int32_t i4BytesWritten = 0; + uint32_t u4RxVector3 = 0; + + u4RxVector3 = prStaRec->u4RxVector3; + + i4RSSI0 = RCPI_TO_dBm((u4RxVector3 & RX_VT_RCPI0_MASK) >> + RX_VT_RCPI0_OFFSET); + i4RSSI1 = RCPI_TO_dBm((u4RxVector3 & RX_VT_RCPI1_MASK) >> + RX_VT_RCPI1_OFFSET); + + if (prAdapter->rWifiVar.ucNSS > 2) { + i4RSSI2 = RCPI_TO_dBm((u4RxVector3 & RX_VT_RCPI2_MASK) >> + RX_VT_RCPI2_OFFSET); + i4RSSI3 = RCPI_TO_dBm((u4RxVector3 & RX_VT_RCPI3_MASK) >> + RX_VT_RCPI3_OFFSET); + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, "%-26s%s%d %d %d %d\n", + "Last RX Data RSSI", " = ", + i4RSSI0, i4RSSI1, i4RSSI2, i4RSSI3); + } else + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, "%-26s%s%d %d\n", + "Last RX Data RSSI", " = ", i4RSSI0, i4RSSI1); + + return i4BytesWritten; + +} + +static uint32_t parseRxRespRssiInfo(IN char *pcBuffer, IN int i4Size, + IN struct ADAPTER *prAdapter, + IN struct PARAM_HW_WLAN_INFO *prHwWlanInfo) +{ + int32_t i4BytesWritten = 0; + + if (prAdapter->rWifiVar.ucNSS > 2) + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%-26s%s%d %d %d %d\n", "Tx Response RSSI", " = ", + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi0), + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi1), + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi2), + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi3)); + else + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%-26s%s%d %d\n", "Tx Response RSSI", " = ", + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi0), + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi1)); + + return i4BytesWritten; +} + +static int32_t parseTxPerInfo(IN char *pcBuffer, IN int i4Size, + IN struct PARAM_HW_WLAN_INFO *prHwWlanInfo, + IN struct PARAM_GET_STA_STATISTICS *prQueryStaStatistics) +{ + uint32_t u4InstantPer; + int32_t i4BytesWritten = 0; + uint8_t ucSkipAr; + + ucSkipAr = prQueryStaStatistics->ucSkipAr; + + if (ucSkipAr) { + u4InstantPer = + (prHwWlanInfo->rWtblTxCounter.u2Rate1TxCnt == 0) ? + (0) : + (1000 * (prHwWlanInfo->rWtblTxCounter.u2Rate1FailCnt) + / (prHwWlanInfo->rWtblTxCounter.u2Rate1TxCnt)); + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%-26s%s%d.%1d%%\n", "instant PER", " = ", + u4InstantPer/10, u4InstantPer%10); + } else { + u4InstantPer = (prQueryStaStatistics->ucPer == 0) ? + (0) : (prQueryStaStatistics->ucPer); + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%-26s%s%d%%\n", "instant PER", " = ", + u4InstantPer); + } + + return i4BytesWritten; +} + +static int32_t parseRxPerInfo(IN char *pcBuffer, IN int i4Size, + IN struct ADAPTER *prAdapter, + IN struct PARAM_GET_STA_STATISTICS *prQueryStaStatistics) +{ + uint32_t u4InstantPer[ENUM_BAND_NUM]; + int32_t i4BytesWritten = 0; + uint8_t ucDbdcIdx; + struct MIB_INFO_STAT *prMibInfo; + + prMibInfo = prQueryStaStatistics->rMibInfo; + + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; ucDbdcIdx++) { + u4InstantPer[ucDbdcIdx] = ((prMibInfo[ucDbdcIdx].u4RxMpduCnt + + prMibInfo[ucDbdcIdx].u4FcsError) == 0) ? + (0) : (1000 * prMibInfo[ucDbdcIdx].u4FcsError / + (prMibInfo[ucDbdcIdx].u4RxMpduCnt + + prMibInfo[ucDbdcIdx].u4FcsError)); + + if (prAdapter->rWifiVar.fgDbDcModeEn) + i4BytesWritten += kalScnprintf( + pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "[DBDC_%d] :\n", + ucDbdcIdx); + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%-26s%s%d.%1d%%\n", "instant PER", " = ", + u4InstantPer[ENUM_BAND_0]/10, + u4InstantPer[ENUM_BAND_0]%10); + + if (!prAdapter->rWifiVar.fgDbDcModeEn) + break; + + } + + return i4BytesWritten; +} + +static uint32_t parseTrigger(IN char *pcBuffer, + IN int i4Size, IN uint8_t trigger) +{ + int32_t i4BytesWritten = 0; + char *pString; + + switch (trigger) { + case DISCONNECT_TRIGGER_RESERVED: + pString = GET_VARNAME(DISCONNECT_TRIGGER_RESERVED); + break; + case DISCONNECT_TRIGGER_ACTIVE: + pString = GET_VARNAME(DISCONNECT_TRIGGER_ACTIVE); + break; + case DISCONNECT_TRIGGER_PASSIVE: + pString = GET_VARNAME(DISCONNECT_TRIGGER_PASSIVE); + break; + default: + pString = "N/A"; + break; + } + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%-26s%s%s\n", + "Trigger", + " = ", + pString); + + return i4BytesWritten; +} + +static uint32_t parseDisconnReasonCode(IN char *pcBuffer, + IN int i4Size, IN uint8_t ucReason) +{ + int32_t i4BytesWritten = 0; + char *pString; + + switch (ucReason) { + case DISCONNECT_REASON_CODE_RESERVED: + pString = GET_VARNAME(DISCONNECT_REASON_CODE_RESERVED); + break; + case DISCONNECT_REASON_CODE_RADIO_LOST: + pString = GET_VARNAME(DISCONNECT_REASON_CODE_RADIO_LOST); + break; + case DISCONNECT_REASON_CODE_DEAUTHENTICATED: + pString = GET_VARNAME(DISCONNECT_REASON_CODE_DEAUTHENTICATED); + break; + case DISCONNECT_REASON_CODE_DISASSOCIATED: + pString = GET_VARNAME(DISCONNECT_REASON_CODE_DISASSOCIATED); + break; + case DISCONNECT_REASON_CODE_NEW_CONNECTION: + pString = GET_VARNAME(DISCONNECT_REASON_CODE_NEW_CONNECTION); + break; + case DISCONNECT_REASON_CODE_REASSOCIATION: + pString = GET_VARNAME(DISCONNECT_REASON_CODE_REASSOCIATION); + break; + case DISCONNECT_REASON_CODE_ROAMING: + pString = GET_VARNAME(DISCONNECT_REASON_CODE_ROAMING); + break; + default: + pString = "N/A"; + break; + } + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%-26s%s%s\n", + "Disconnect reason", + " = ", + pString); + + return i4BytesWritten; +} + +static uint32_t parseBcnTimeoutReasonCode(IN char *pcBuffer, + IN int i4Size, IN uint8_t ucReason) +{ + int32_t i4BytesWritten = 0; + char *pString; + + switch (ucReason) { + case BEACON_TIMEOUT_DUE_2_HW_BEACON_LOST_NONADHOC: + pString = GET_VARNAME( + BEACON_TIMEOUT_DUE_2_HW_BEACON_LOST_NONADHOC); + break; + case BEACON_TIMEOUT_DUE_2_HW_BEACON_LOST_ADHOC: + pString = GET_VARNAME( + BEACON_TIMEOUT_DUE_2_HW_BEACON_LOST_ADHOC); + break; + case BEACON_TIMEOUT_DUE_2_HW_TSF_DRIFT: + pString = GET_VARNAME( + BEACON_TIMEOUT_DUE_2_HW_TSF_DRIFT); + break; + case BEACON_TIMEOUT_DUE_2_NULL_FRAME_THRESHOLD: + pString = GET_VARNAME( + BEACON_TIMEOUT_DUE_2_NULL_FRAME_THRESHOLD); + break; + case BEACON_TIMEOUT_DUE_2_AGING_THRESHOLD: + pString = GET_VARNAME( + BEACON_TIMEOUT_DUE_2_AGING_THRESHOLD); + break; + case BEACON_TIMEOUT_DUE_2_BSSID_BEACON_PEIROD_NOT_ILLIGAL: + pString = GET_VARNAME( + BEACON_TIMEOUT_DUE_2_BSSID_BEACON_PEIROD_NOT_ILLIGAL); + break; + case BEACON_TIMEOUT_DUE_2_CONNECTION_FAIL: + pString = GET_VARNAME( + BEACON_TIMEOUT_DUE_2_CONNECTION_FAIL); + break; + case BEACON_TIMEOUT_DUE_2_ALLOCAT_NULL_PKT_FAIL_THRESHOLD: + pString = GET_VARNAME( + BEACON_TIMEOUT_DUE_2_ALLOCAT_NULL_PKT_FAIL_THRESHOLD); + break; + case BEACON_TIMEOUT_DUE_2_NO_TX_DONE_EVENT: + pString = GET_VARNAME( + BEACON_TIMEOUT_DUE_2_NO_TX_DONE_EVENT); + break; + case BEACON_TIMEOUT_DUE_2_UNSPECIF_REASON: + pString = GET_VARNAME( + BEACON_TIMEOUT_DUE_2_UNSPECIF_REASON); + break; + case BEACON_TIMEOUT_DUE_2_SET_CHIP: + pString = GET_VARNAME( + BEACON_TIMEOUT_DUE_2_SET_CHIP); + break; + case BEACON_TIMEOUT_DUE_2_KEEP_SCAN_AP_MISS_CHECK_FAIL: + pString = GET_VARNAME( + BEACON_TIMEOUT_DUE_2_KEEP_SCAN_AP_MISS_CHECK_FAIL); + break; + case BEACON_TIMEOUT_DUE_2_KEEP_UNCHANGED_LOW_RSSI_CHECK_FAIL: + pString = GET_VARNAME( + BEACON_TIMEOUT_DUE_2_KEEP_UNCHANGED_LOW_RSSI_CHECK_FAIL); + break; + case BEACON_TIMEOUT_DUE_2_NULL_FRAME_LIFE_TIMEOUT: + pString = GET_VARNAME( + BEACON_TIMEOUT_DUE_2_NULL_FRAME_LIFE_TIMEOUT); + break; + case BEACON_TIMEOUT_DUE_2_APR_NO_RESPONSE: + pString = GET_VARNAME( + BEACON_TIMEOUT_DUE_2_APR_NO_RESPONSE); + break; + default: + pString = "N/A"; + break; + } + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%-26s%s%s\n", + "Beacon timeout reason", + " = ", + pString); + + return i4BytesWritten; +} + +static uint32_t parseDisassocReasonCode(IN char *pcBuffer, + IN int i4Size, IN uint8_t ucReason) +{ + int32_t i4BytesWritten = 0; + char *pString; + + switch (ucReason) { + case REASON_CODE_RESERVED: + pString = GET_VARNAME( + REASON_CODE_RESERVED); + break; + case REASON_CODE_UNSPECIFIED: + pString = GET_VARNAME( + REASON_CODE_UNSPECIFIED); + break; + case REASON_CODE_PREV_AUTH_INVALID: + pString = GET_VARNAME( + REASON_CODE_PREV_AUTH_INVALID); + break; + case REASON_CODE_DEAUTH_LEAVING_BSS: + pString = GET_VARNAME( + REASON_CODE_DEAUTH_LEAVING_BSS); + break; + case REASON_CODE_DISASSOC_INACTIVITY: + pString = GET_VARNAME( + REASON_CODE_DISASSOC_INACTIVITY); + break; + case REASON_CODE_DISASSOC_AP_OVERLOAD: + pString = GET_VARNAME( + REASON_CODE_DISASSOC_AP_OVERLOAD); + break; + case REASON_CODE_CLASS_2_ERR: + pString = GET_VARNAME( + REASON_CODE_CLASS_2_ERR); + break; + case REASON_CODE_CLASS_3_ERR: + pString = GET_VARNAME( + REASON_CODE_CLASS_3_ERR); + break; + case REASON_CODE_DISASSOC_LEAVING_BSS: + pString = GET_VARNAME( + REASON_CODE_DISASSOC_LEAVING_BSS); + break; + case REASON_CODE_ASSOC_BEFORE_AUTH: + pString = GET_VARNAME( + REASON_CODE_ASSOC_BEFORE_AUTH); + break; + case REASON_CODE_DISASSOC_PWR_CAP_UNACCEPTABLE: + pString = GET_VARNAME( + REASON_CODE_DISASSOC_PWR_CAP_UNACCEPTABLE); + break; + case REASON_CODE_DISASSOC_SUP_CHS_UNACCEPTABLE: + pString = GET_VARNAME( + REASON_CODE_DISASSOC_SUP_CHS_UNACCEPTABLE); + break; + case REASON_CODE_INVALID_INFO_ELEM: + pString = GET_VARNAME( + REASON_CODE_INVALID_INFO_ELEM); + break; + case REASON_CODE_MIC_FAILURE: + pString = GET_VARNAME( + REASON_CODE_MIC_FAILURE); + break; + case REASON_CODE_4_WAY_HANDSHAKE_TIMEOUT: + pString = GET_VARNAME( + REASON_CODE_4_WAY_HANDSHAKE_TIMEOUT); + break; + case REASON_CODE_GROUP_KEY_UPDATE_TIMEOUT: + pString = GET_VARNAME( + REASON_CODE_GROUP_KEY_UPDATE_TIMEOUT); + break; + case REASON_CODE_DIFFERENT_INFO_ELEM: + pString = GET_VARNAME( + REASON_CODE_DIFFERENT_INFO_ELEM); + break; + case REASON_CODE_MULTICAST_CIPHER_NOT_VALID: + pString = GET_VARNAME( + REASON_CODE_MULTICAST_CIPHER_NOT_VALID); + break; + case REASON_CODE_UNICAST_CIPHER_NOT_VALID: + pString = GET_VARNAME( + REASON_CODE_UNICAST_CIPHER_NOT_VALID); + break; + case REASON_CODE_AKMP_NOT_VALID: + pString = GET_VARNAME( + REASON_CODE_AKMP_NOT_VALID); + break; + case REASON_CODE_UNSUPPORTED_RSNE_VERSION: + pString = GET_VARNAME( + REASON_CODE_UNSUPPORTED_RSNE_VERSION); + break; + case REASON_CODE_INVALID_RSNE_CAPABILITIES: + pString = GET_VARNAME( + REASON_CODE_INVALID_RSNE_CAPABILITIES); + break; + case REASON_CODE_IEEE_802_1X_AUTH_FAILED: + pString = GET_VARNAME( + REASON_CODE_IEEE_802_1X_AUTH_FAILED); + break; + case REASON_CODE_CIPHER_REJECT_SEC_POLICY: + pString = GET_VARNAME( + REASON_CODE_CIPHER_REJECT_SEC_POLICY); + break; + case REASON_CODE_DISASSOC_UNSPECIFIED_QOS: + pString = GET_VARNAME( + REASON_CODE_DISASSOC_UNSPECIFIED_QOS); + break; + case REASON_CODE_DISASSOC_LACK_OF_BANDWIDTH: + pString = GET_VARNAME( + REASON_CODE_DISASSOC_LACK_OF_BANDWIDTH); + break; + case REASON_CODE_DISASSOC_ACK_LOST_POOR_CHANNEL: + pString = GET_VARNAME( + REASON_CODE_DISASSOC_ACK_LOST_POOR_CHANNEL); + break; + case REASON_CODE_DISASSOC_TX_OUTSIDE_TXOP_LIMIT: + pString = GET_VARNAME( + REASON_CODE_DISASSOC_TX_OUTSIDE_TXOP_LIMIT); + break; + case REASON_CODE_PEER_WHILE_LEAVING: + pString = GET_VARNAME( + REASON_CODE_PEER_WHILE_LEAVING); + break; + case REASON_CODE_PEER_REFUSE_DLP: + pString = GET_VARNAME( + REASON_CODE_PEER_REFUSE_DLP); + break; + case REASON_CODE_PEER_SETUP_REQUIRED: + pString = GET_VARNAME( + REASON_CODE_PEER_SETUP_REQUIRED); + break; + case REASON_CODE_PEER_TIME_OUT: + pString = GET_VARNAME( + REASON_CODE_PEER_TIME_OUT); + break; + case REASON_CODE_PEER_CIPHER_UNSUPPORTED: + pString = GET_VARNAME( + REASON_CODE_PEER_CIPHER_UNSUPPORTED); + break; + case REASON_CODE_BEACON_TIMEOUT: + pString = GET_VARNAME( + REASON_CODE_BEACON_TIMEOUT); + break; + default: + pString = "N/A"; + break; + } + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%-26s%s%s\n", + "Disassociation reason", + " = ", + pString); + + return i4BytesWritten; + +} + +static uint32_t parseRssiInfo(IN char *pcBuffer, IN int i4Size, + IN struct CMD_NOISE_HISTOGRAM_REPORT *prNoise) +{ + int32_t i4BytesWritten = 0; + struct CMD_NOISE_HISTOGRAM_REPORT rEmptyNoise; + + kalMemZero(&rEmptyNoise, sizeof(rEmptyNoise)); + rEmptyNoise.u2Type = prNoise->u2Type; + rEmptyNoise.u2Len = prNoise->u2Len; + rEmptyNoise.ucAction = prNoise->ucAction; + + if (kalMemCmp(prNoise, &rEmptyNoise, + sizeof(struct CMD_NOISE_HISTOGRAM_REPORT)) == 0) { + DBGLOG(INIT, WARN, "Empty info\n"); + return i4BytesWritten; + } + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "\n%s", "----- Noise Info -----"); + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "\n Power > -55: %10d", + prNoise->u4IPI10); + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "\n-55 >= Power > -60: %10d", + prNoise->u4IPI9); + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "\n-60 >= Power > -65: %10d", + prNoise->u4IPI8); + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "\n-65 >= Power > -70: %10d", + prNoise->u4IPI7); + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "\n-70 >= Power > -75: %10d", + prNoise->u4IPI6); + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "\n-75 >= Power > -80: %10d", + prNoise->u4IPI5); + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "\n-80 >= Power > -83: %10d", + prNoise->u4IPI4); + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "\n-83 >= Power > -86: %10d", + prNoise->u4IPI3); + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "\n-86 >= Power > -89: %10d", + prNoise->u4IPI2); + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "\n-89 >= Power > -92: %10d", + prNoise->u4IPI1); + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "\n-92 >= Power : %10d\n", + prNoise->u4IPI0); + + return i4BytesWritten; +} + +static ssize_t procDisconnInfoRead(struct file *filp, + char __user *buf, size_t count, loff_t *f_pos) +{ + struct GLUE_INFO *prGlueInfo; + struct ADAPTER *prAdapter; + int32_t i4Count = 0; + uint8_t ucDbdcIdx; + uint8_t *temp = &g_aucProcBuf[0]; + struct AIS_DISCONN_INFO_T *prDisconn = NULL; + uint8_t cnt; + uint8_t temp_idx = 0; + struct tm broken; + char date[20] = {0}; + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0) + return 0; + + if (g_prDisconnInfo == NULL) { + DBGLOG(INIT, WARN, "NULL g_prDisconnInfo\n"); + return 0; + } + + if (g_DisconnInfoIdx >= MAX_DISCONNECT_RECORD) { + DBGLOG(AIS, LOUD, "Invalid g_DisconnInfoIdx\n"); + return 0; + } + + prGlueInfo = g_prGlueInfo_proc; + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(g_aucProcBuf, sizeof(g_aucProcBuf)); + + for (cnt = 0; cnt < MAX_DISCONNECT_RECORD; cnt++) { + + temp_idx = (g_DisconnInfoIdx + cnt) % MAX_DISCONNECT_RECORD; + + prDisconn = g_prDisconnInfo + temp_idx; + + time_to_tm(prDisconn->tv.tv_sec, 0, &broken); + kalScnprintf(date, + sizeof(date), + "%02d-%02d %02d:%02d:%02d.%ld", + broken.tm_mon + 1, + broken.tm_mday, + broken.tm_hour, + broken.tm_min, + broken.tm_sec, + prDisconn->tv.tv_usec); + + i4Count += kalScnprintf(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + "%s %s %d %s %s %s %s", + "===============", + "Record", + temp_idx, + "(", + date, + ")", + "==============="); + + /* Dump misc info*/ + i4Count += kalScnprintf(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + "\n%s", "\n"); + + i4Count += parseTrigger(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + prDisconn->ucTrigger); + + i4Count += parseDisconnReasonCode(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + prDisconn->ucDisConnReason); + + i4Count += parseBcnTimeoutReasonCode(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + prDisconn->ucBcnTimeoutReason); + + i4Count += parseDisassocReasonCode(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + prDisconn->ucDisassocReason); + + if (prDisconn->u2DisassocSeqNum != 0xFFFF) { + i4Count += kalScnprintf(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + "%-26s%s%ld\n", + "Disassociation SeqNum", + " = ", + prDisconn->u2DisassocSeqNum); + } + + /* Noise info*/ + i4Count += parseRssiInfo(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + &prDisconn->rNoise); + + /* Dump RX info */ + i4Count += kalScnprintf(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + "\n%s", "\n"); + + /* Last RX Rate info */ + i4Count += parseRxRateInfo(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + &prDisconn->rStaRec); + + /* RX PER info */ + i4Count += parseRxPerInfo(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + prAdapter, + &prDisconn->rStaStatistics); + + /* Last RX RSSI info*/ + i4Count += parseRxRssiInfo(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + prAdapter, + &prDisconn->rStaRec); + + /* Last RX Resp RSSI */ + i4Count += parseRxRespRssiInfo(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + prAdapter, + &prDisconn->rHwInfo); + + /* Last Beacon RSSI */ + i4Count += kalScnprintf(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + "%-26s%s%d\n", "Beacon RSSI", " = ", + prDisconn->rBcnRssi); + + /* Dump TX info */ + i4Count += kalScnprintf(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + "\n%s", "\n"); + + /* Last TX Rate info */ + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; ucDbdcIdx++) { + + if (prAdapter->rWifiVar.fgDbDcModeEn) + + i4Count += kalScnprintf( + temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + "[DBDC_%d] :\n", + ucDbdcIdx); + + i4Count += parseTxRateInfo(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + &prDisconn->rStaStatistics + .rTxVector[ucDbdcIdx]); + + if (!prAdapter->rWifiVar.fgDbDcModeEn) + break; + } + + /* TX PER info */ + i4Count += parseTxPerInfo(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + &prDisconn->rHwInfo, + &prDisconn->rStaStatistics); + } + + if (copy_to_user(buf, g_aucProcBuf, i4Count)) { + DBGLOG(INIT, ERROR, "copy to user failed\n"); + return -EFAULT; + } + + *f_pos += i4Count; + + return i4Count; +} +#endif /* CFG_DISCONN_DEBUG_FEATURE */ + + + +static const struct file_operations dbglevel_ops = { + .owner = THIS_MODULE, + .read = procDbgLevelRead, + .write = procDbgLevelWrite, +}; + +#if WLAN_INCLUDE_PROC +#if CFG_SUPPORT_EASY_DEBUG + +static const struct file_operations efusedump_ops = { + .owner = THIS_MODULE, + .open = procEfuseDumpOpen, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static const struct file_operations drivercmd_ops = { + .owner = THIS_MODULE, + .read = procDriverCmdRead, + .write = procDriverCmdWrite, +}; + +static const struct file_operations cfg_ops = { + .owner = THIS_MODULE, + .read = procCfgRead, + .write = procCfgWrite, +}; +#endif +#endif +static const struct file_operations get_txpwr_tbl_ops = { + .owner = THIS_MODULE, + .read = procGetTxpwrTblRead, +}; + +#ifdef CFG_GET_TEMPURATURE +static const struct file_operations get_temperature_ops = { + .owner = THIS_MODULE, + .read = proc_get_temperature, +}; +#endif + +#if CFG_DISCONN_DEBUG_FEATURE +static const struct file_operations disconn_info_ops = { + .owner = THIS_MODULE, + .read = procDisconnInfoRead, +}; +#endif + +/******************************************************************************* + * 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 ssize_t procMCRRead(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + struct GLUE_INFO *prGlueInfo; + struct PARAM_CUSTOM_MCR_RW_STRUCT rMcrInfo; + uint32_t u4BufLen; + uint32_t u4Count; + uint8_t *temp = &g_aucProcBuf[0]; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + /* Kevin: Apply PROC read method 1. */ + if (*f_pos > 0) + return 0; /* To indicate end of file. */ + + prGlueInfo = g_prGlueInfo_proc; + + rMcrInfo.u4McrOffset = u4McrOffset; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryMcrRead, (void *)&rMcrInfo, + sizeof(rMcrInfo), TRUE, TRUE, TRUE, &u4BufLen); + kalMemZero(g_aucProcBuf, sizeof(g_aucProcBuf)); + SNPRINTF(temp, g_aucProcBuf, + ("MCR (0x%08xh): 0x%08x\n", rMcrInfo.u4McrOffset, + rMcrInfo.u4McrData)); + + u4Count = kalStrLen(g_aucProcBuf); + if (copy_to_user(buf, g_aucProcBuf, u4Count)) { + DBGLOG(INIT, ERROR, "copy to user failed\n"); + return -EFAULT; + } + + *f_pos += u4Count; + + 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 ssize_t procMCRWrite(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + struct GLUE_INFO *prGlueInfo; + /* + 1 for "\0" */ + char acBuf[PROC_MCR_ACCESS_MAX_USER_INPUT_LEN + 1]; + int i4CopySize; + struct PARAM_CUSTOM_MCR_RW_STRUCT rMcrInfo; + uint32_t u4BufLen; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + int num = 0; + + ASSERT(data); + + i4CopySize = + (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + if (copy_from_user(acBuf, buffer, i4CopySize)) + return 0; + acBuf[i4CopySize] = '\0'; + + num = + sscanf(acBuf, "0x%x 0x%x", &rMcrInfo.u4McrOffset, + &rMcrInfo.u4McrData); + switch (num) { + 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 = g_prGlueInfo_proc; + + u4McrOffset = rMcrInfo.u4McrOffset; + + /* rMcrInfo.u4McrOffset, rMcrInfo.u4McrData); */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetMcrWrite, + (void *)&rMcrInfo, sizeof(rMcrInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + } + break; + case 1: + /* if (IS_ALIGN_4(rMcrInfo.u4McrOffset)) */ + { + u4McrOffset = rMcrInfo.u4McrOffset; + } + break; + + default: + break; + } + + return count; + +} /* end of procMCRWrite() */ + +static const struct file_operations mcr_ops = { + .owner = THIS_MODULE, + .read = procMCRRead, + .write = procMCRWrite, +}; + +#if CFG_SUPPORT_SET_CAM_BY_PROC +static ssize_t procSetCamCfgWrite(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ +#define MODULE_NAME_LEN_1 5 + + uint32_t u4CopySize = sizeof(g_aucProcBuf); + uint8_t *temp = &g_aucProcBuf[0]; + u_int8_t fgSetCamCfg = FALSE; + uint8_t aucModule[MODULE_NAME_LEN_1]; + uint32_t u4Enabled; + uint8_t aucModuleArray[MODULE_NAME_LEN_1] = "CAM"; + u_int8_t fgParamValue = TRUE; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + + kalMemSet(g_aucProcBuf, 0, u4CopySize); + u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1); + + if (copy_from_user(g_aucProcBuf, buffer, u4CopySize)) { + DBGLOG(INIT, ERROR, "error of copy from user\n"); + return -EFAULT; + } + g_aucProcBuf[u4CopySize] = '\0'; + temp = &g_aucProcBuf[0]; + while (temp) { + kalMemSet(aucModule, 0, MODULE_NAME_LEN_1); + + /* pick up a string and teminated after meet : */ + if (sscanf(temp, "%4s %d", aucModule, &u4Enabled) != 2) { + DBGLOG(INIT, INFO, + "read param fail, aucModule=%s\n", aucModule); + fgParamValue = FALSE; + break; + } + + if (kalStrnCmp + (aucModule, aucModuleArray, MODULE_NAME_LEN_1) == 0) { + if (u4Enabled) + fgSetCamCfg = TRUE; + else + fgSetCamCfg = FALSE; + } + temp = kalStrChr(temp, ','); + if (!temp) + break; + temp++; /* skip ',' */ + } + + if (fgParamValue) { + prGlueInfo = wlanGetGlueInfo(); + if (!prGlueInfo) + return count; + + prAdapter = prGlueInfo->prAdapter; + if (!prAdapter) + return count; + + nicConfigProcSetCamCfgWrite(prAdapter, fgSetCamCfg); + } + + return count; +} + +static const struct file_operations proc_set_cam_ops = { + .owner = THIS_MODULE, + .write = procSetCamCfgWrite, +}; +#endif /*CFG_SUPPORT_SET_CAM_BY_PROC */ + +static ssize_t procPktDelayDbgCfgRead(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + uint8_t *temp = &g_aucProcBuf[0]; + uint8_t *str = NULL; + uint32_t u4CopySize = 0; + uint8_t ucTxRxFlag; + uint8_t ucTxIpProto; + uint16_t u2TxUdpPort; + uint32_t u4TxDelayThreshold; + uint8_t ucRxIpProto; + uint16_t u2RxUdpPort; + uint32_t u4RxDelayThreshold; + uint32_t u4StrLen = 0; + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0 || buf == NULL) + return 0; + + str = "\nUsage: txLog/rxLog/reset 1(ICMP)/6(TCP)/11(UDP) Dst/SrcPortNum DelayThreshold(us)\n" + "Print tx delay log, such as: echo txLog 0 0 0 > pktDelay\n" + "Print tx UDP delay log, such as: echo txLog 11 0 0 > pktDelay\n" + "Print tx UDP dst port19305 delay log, such as: echo txLog 11 19305 0 > pktDelay\n" + "Print rx UDP src port19305 delay more than 500us log, such as: echo rxLog 11 19305 500 > pktDelay\n" + "Print tx TCP delay more than 500us log, such as: echo txLog 6 0 500 > pktDelay\n" + "Close log, such as: echo reset 0 0 0 > pktDelay\n\n"; + u4StrLen = kalStrLen(str); + kalStrnCpy(temp, str, u4StrLen + 1); + temp += kalStrLen(temp); + + StatsEnvGetPktDelay(&ucTxRxFlag, &ucTxIpProto, &u2TxUdpPort, + &u4TxDelayThreshold, &ucRxIpProto, &u2RxUdpPort, + &u4RxDelayThreshold); + + if (ucTxRxFlag & BIT(0)) { + SNPRINTF(temp, g_aucProcBuf, + ("txLog %x %d %d\n", ucTxIpProto, u2TxUdpPort, + u4TxDelayThreshold)); + temp += kalStrLen(temp); + } + if (ucTxRxFlag & BIT(1)) { + SNPRINTF(temp, g_aucProcBuf, + ("rxLog %x %d %d\n", ucRxIpProto, u2RxUdpPort, + u4RxDelayThreshold)); + temp += kalStrLen(temp); + } + if (ucTxRxFlag == 0) + SNPRINTF(temp, g_aucProcBuf, + ("reset 0 0 0, there is no tx/rx delay log\n")); + + u4CopySize = kalStrLen(g_aucProcBuf); + if (u4CopySize > count) + u4CopySize = count; + if (copy_to_user(buf, g_aucProcBuf, u4CopySize)) { + DBGLOG(INIT, ERROR, "copy to user failed\n"); + return -EFAULT; + } + + *f_pos += u4CopySize; + return (ssize_t) u4CopySize; +} + +static ssize_t procPktDelayDbgCfgWrite(struct file *file, const char *buffer, + size_t count, loff_t *data) +{ +#define MODULE_NAME_LENGTH 7 +#define MODULE_RESET 0 +#define MODULE_TX 1 +#define MODULE_RX 2 + + uint32_t u4CopySize = sizeof(g_aucProcBuf); + uint8_t *temp = &g_aucProcBuf[0]; + uint8_t aucModule[MODULE_NAME_LENGTH]; + uint32_t u4DelayThreshold = 0; + uint32_t u4PortNum = 0; + uint32_t u4IpProto = 0; + uint8_t aucResetArray[MODULE_NAME_LENGTH] = "reset"; + uint8_t aucTxArray[MODULE_NAME_LENGTH] = "txLog"; + uint8_t aucRxArray[MODULE_NAME_LENGTH] = "rxLog"; + uint8_t ucTxOrRx = 0; + + kalMemSet(g_aucProcBuf, 0, u4CopySize); + u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1); + + if (copy_from_user(g_aucProcBuf, buffer, u4CopySize)) { + DBGLOG(INIT, ERROR, "error of copy from user\n"); + return -EFAULT; + } + g_aucProcBuf[u4CopySize] = '\0'; + + while (temp) { + kalMemSet(aucModule, 0, MODULE_NAME_LENGTH); + + /* pick up a string and teminated after meet : */ + if (sscanf + (temp, "%6s %x %d %d", aucModule, &u4IpProto, &u4PortNum, + &u4DelayThreshold) != 4) { + DBGLOG(INIT, INFO, + "read param fail, aucModule=%s\n", aucModule); + break; + } + + if (kalStrnCmp + (aucModule, aucResetArray, MODULE_NAME_LENGTH) == 0) { + ucTxOrRx = MODULE_RESET; + } else if (kalStrnCmp + (aucModule, aucTxArray, MODULE_NAME_LENGTH) == 0) { + ucTxOrRx = MODULE_TX; + } else if (kalStrnCmp + (aucModule, aucRxArray, MODULE_NAME_LENGTH) == 0) { + ucTxOrRx = MODULE_RX; + } else { + DBGLOG(INIT, INFO, "input module error!\n"); + break; + } + + temp = kalStrChr(temp, ','); + if (!temp) + break; + temp++; /* skip ',' */ + } + + StatsEnvSetPktDelay(ucTxOrRx, (uint8_t) u4IpProto, (uint16_t) u4PortNum, + u4DelayThreshold); + + return count; +} + +static const struct file_operations proc_pkt_delay_dbg_ops = { + .owner = THIS_MODULE, + .read = procPktDelayDbgCfgRead, + .write = procPktDelayDbgCfgWrite, +}; + +#if CFG_SUPPORT_DEBUG_FS +static ssize_t procRoamRead(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + uint32_t u4CopySize; + uint32_t rStatus; + uint32_t u4BufLen; + + /* if *f_pos > 0, it means has read successed last time, + * don't try again + */ + if (*f_pos > 0 || buf == NULL) + return 0; + + rStatus = + kalIoctl(g_prGlueInfo_proc, wlanoidGetRoamParams, g_aucProcBuf, + sizeof(g_aucProcBuf), TRUE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "failed to read roam params\n"); + return -EINVAL; + } + + u4CopySize = kalStrLen(g_aucProcBuf); + if (copy_to_user(buf, g_aucProcBuf, u4CopySize)) { + DBGLOG(INIT, ERROR, "copy to user failed\n"); + return -EFAULT; + } + *f_pos += u4CopySize; + + return (int32_t) u4CopySize; +} + +static ssize_t procRoamWrite(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + uint32_t rStatus; + uint32_t u4BufLen = 0; + uint32_t u4CopySize = sizeof(g_aucProcBuf); + + kalMemSet(g_aucProcBuf, 0, u4CopySize); + u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1); + + if (copy_from_user(g_aucProcBuf, buffer, u4CopySize)) { + DBGLOG(INIT, ERROR, "error of copy from user\n"); + return -EFAULT; + } + g_aucProcBuf[u4CopySize] = '\0'; + + if (kalStrnCmp(g_aucProcBuf, "force_roam", 10) == 0) + rStatus = + kalIoctl(g_prGlueInfo_proc, wlanoidSetForceRoam, NULL, 0, + FALSE, FALSE, TRUE, &u4BufLen); + else + rStatus = + kalIoctl(g_prGlueInfo_proc, wlanoidSetRoamParams, + g_aucProcBuf, kalStrLen(g_aucProcBuf), FALSE, + FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "failed to set roam params: %s\n", + g_aucProcBuf); + return -EINVAL; + } + return count; +} + +static const struct file_operations roam_ops = { + .owner = THIS_MODULE, + .read = procRoamRead, + .write = procRoamWrite, +}; +#endif + +static ssize_t procCountryRead(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + uint32_t u4CopySize; + uint32_t country = 0; + + /* if *f_pos > 0, it means has read successed last time */ + if (*f_pos > 0) + return 0; + + country = rlmDomainGetCountryCode(); + + kalMemZero(g_aucProcBuf, sizeof(g_aucProcBuf)); + if (country) + kalSnprintf(g_aucProcBuf, sizeof(g_aucProcBuf), + "Current Country Code: %s\n", &country); + else + kalSnprintf(g_aucProcBuf, sizeof(g_aucProcBuf), + "Current Country Code: NULL\n"); + + u4CopySize = kalStrLen(g_aucProcBuf); + if (copy_to_user(buf, g_aucProcBuf, u4CopySize)) { + DBGLOG(INIT, ERROR, "copy to user failed\n"); + return -EFAULT; + } + *f_pos += u4CopySize; + + return (int32_t) u4CopySize; +} + +static ssize_t procCountryWrite(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + uint32_t u4BufLen = 0; + uint32_t rStatus; + uint32_t u4CopySize = sizeof(g_aucProcBuf); + + kalMemSet(g_aucProcBuf, 0, u4CopySize); + u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1); + + if (copy_from_user(g_aucProcBuf, buffer, u4CopySize)) { + DBGLOG(INIT, ERROR, "error of copy from user\n"); + return -EFAULT; + } + g_aucProcBuf[u4CopySize] = '\0'; + + rStatus = kalIoctl(g_prGlueInfo_proc, wlanoidSetCountryCode, + &g_aucProcBuf[0], 2, FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "failed set country code: %s\n", + g_aucProcBuf); + return -EINVAL; + } + return count; +} + +static const struct file_operations country_ops = { + .owner = THIS_MODULE, + .read = procCountryRead, + .write = procCountryWrite, +}; + +static ssize_t procAutoPerfCfgRead(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + uint8_t *temp = &g_aucProcBuf[0]; + uint8_t *str = NULL; + uint32_t u4CopySize = 0; + uint32_t u4StrLen = 0; + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0) + return 0; + + str = "Auto Performance Configure Usage:\n" + "\n" + "echo ForceEnable:0 or 1 > /proc/net/wlan/autoPerfCfg\n" + " 1: always enable performance monitor\n" + " 0: restore performance monitor's default strategy\n"; + u4StrLen = kalStrLen(str); + kalStrnCpy(temp, str, u4StrLen + 1); + + u4CopySize = kalStrLen(g_aucProcBuf); + if (u4CopySize > count) + u4CopySize = count; + + if (copy_to_user(buf, g_aucProcBuf, u4CopySize)) { + DBGLOG(INIT, WARN, "copy_to_user error\n"); + return -EFAULT; + } + + *f_pos += u4CopySize; + return (ssize_t) u4CopySize; +} + +static ssize_t procAutoPerfCfgWrite(struct file *file, const char *buffer, + size_t count, loff_t *data) +{ + uint32_t u4CoreNum = 0; + uint32_t u4CoreFreq = 0; + uint8_t *temp = &g_aucProcBuf[0]; + uint32_t u4CopySize = count; + uint8_t i = 0; + uint32_t u4ForceEnable = 0; + uint8_t aucBuf[32]; + + if (u4CopySize >= sizeof(g_aucProcBuf)) + u4CopySize = sizeof(g_aucProcBuf) - 1; + + kalMemSet(g_aucProcBuf, 0, u4CopySize); + + if (copy_from_user(g_aucProcBuf, buffer, u4CopySize)) { + DBGLOG(INIT, WARN, "copy_from_user error\n"); + return -EFAULT; + } + + g_aucProcBuf[u4CopySize] = '\0'; + + i = sscanf(temp, "%d:%d", &u4CoreNum, &u4CoreFreq); + if (i == 2) { + DBGLOG(INIT, INFO, "u4CoreNum:%d, u4CoreFreq:%d\n", u4CoreNum, + u4CoreFreq); + kalSetCpuNumFreq(u4CoreNum, u4CoreFreq); + return u4CopySize; + } + + if (strlen(temp) > sizeof(aucBuf)) { + DBGLOG(INIT, WARN, + "input string(%s) len is too long, over %d\n", + g_aucProcBuf, (uint32_t) sizeof(aucBuf)); + return -EFAULT; + } + + i = sscanf(temp, "%11s:%d", aucBuf, &u4ForceEnable); + + if ((i == 2) && strstr(aucBuf, "ForceEnable")) { + kalPerMonSetForceEnableFlag(u4ForceEnable); + return u4CopySize; + } + + DBGLOG(INIT, WARN, "parameter format should be ForceEnable:0 or 1\n"); + + return -EFAULT; +} + +static const struct file_operations auto_perf_ops = { + .owner = THIS_MODULE, + .read = procAutoPerfCfgRead, + .write = procAutoPerfCfgWrite, +}; + + +int32_t procInitFs(void) +{ + struct proc_dir_entry *prEntry; + + g_NextDriverReadLen = 0; + + if (init_net.proc_net == (struct proc_dir_entry *)NULL) { + DBGLOG(INIT, ERROR, "init proc fs fail: proc_net == NULL\n"); + return -ENOENT; + } + + /* + * Directory: Root (/proc/net/wlan0) + */ + + gprProcRoot = proc_mkdir(PROC_ROOT_NAME, init_net.proc_net); + if (!gprProcRoot) { + DBGLOG(INIT, ERROR, "gprProcRoot == NULL\n"); + return -ENOENT; + } + proc_set_user(gprProcRoot, KUIDT_INIT(PROC_UID_SHELL), + KGIDT_INIT(PROC_GID_WIFI)); + + prEntry = + proc_create(PROC_DBG_LEVEL_NAME, 0664, gprProcRoot, &dbglevel_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, + "Unable to create /proc entry dbgLevel\n\r"); + return -1; + } + proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL), + KGIDT_INIT(PROC_GID_WIFI)); + + prEntry = + proc_create(PROC_AUTO_PERF_CFG, 0664, gprProcRoot, &auto_perf_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry %s/n", + PROC_AUTO_PERF_CFG); + return -1; + } + proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL), + KGIDT_INIT(PROC_GID_WIFI)); + + return 0; +} /* end of procInitProcfs() */ + +int32_t procUninitProcFs(void) +{ +#if KERNEL_VERSION(3, 9, 0) <= LINUX_VERSION_CODE + remove_proc_subtree(PROC_AUTO_PERF_CFG, gprProcRoot); + remove_proc_subtree(PROC_DBG_LEVEL_NAME, gprProcRoot); + + /* + * move PROC_ROOT_NAME to last since it's root directory of the others + * incorrect sequence would cause use-after-free error + */ + remove_proc_subtree(PROC_ROOT_NAME, init_net.proc_net); +#else + remove_proc_entry(PROC_AUTO_PERF_CFG, gprProcRoot); + remove_proc_entry(PROC_DBG_LEVEL_NAME, gprProcRoot); + + /* + * move PROC_ROOT_NAME to last since it's root directory of the others + * incorrect sequence would cause use-after-free error + */ + remove_proc_entry(PROC_ROOT_NAME, init_net.proc_net); +#endif + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function clean up a PROC fs created by procInitProcfs(). + * + * \param[in] prDev Pointer to the struct net_device. + * \param[in] pucDevName Pointer to the name of net_device. + * + * \return N/A + */ +/*----------------------------------------------------------------------------*/ +int32_t procRemoveProcfs(void) +{ + remove_proc_entry(PROC_MCR_ACCESS, gprProcRoot); + remove_proc_entry(PROC_DRIVER_CMD, gprProcRoot); + remove_proc_entry(PROC_CFG, gprProcRoot); + remove_proc_entry(PROC_EFUSE_DUMP, gprProcRoot); + remove_proc_entry(PROC_GET_TXPWR_TBL, gprProcRoot); + remove_proc_entry(PROC_PKT_DELAY_DBG, gprProcRoot); + remove_proc_entry(PROC_COUNTRY, gprProcRoot); +#if CFG_SUPPORT_SET_CAM_BY_PROC + remove_proc_entry(PROC_SET_CAM, gprProcRoot); +#endif +#ifdef CFG_GET_TEMPURATURE + remove_proc_entry(PROC_GET_TEMPETATURE, gprProcRoot); +#endif +#if CFG_SUPPORT_DEBUG_FS + remove_proc_entry(PROC_ROAM_PARAM, gprProcRoot); +#endif +#if CFG_DISCONN_DEBUG_FEATURE + remove_proc_entry(PROC_DISCONN_INFO, gprProcRoot); +#endif + + return 0; +} /* end of procRemoveProcfs() */ + +int32_t procCreateFsEntry(struct GLUE_INFO *prGlueInfo) +{ + struct proc_dir_entry *prEntry; + + DBGLOG(INIT, INFO, "[%s]\n", __func__); + g_prGlueInfo_proc = prGlueInfo; + + prEntry = proc_create(PROC_MCR_ACCESS, 0664, gprProcRoot, &mcr_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry mcr\n\r"); + return -1; + } + + prEntry = + proc_create(PROC_PKT_DELAY_DBG, 0664, gprProcRoot, + &proc_pkt_delay_dbg_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, + "Unable to create /proc entry pktDelay\n\r"); + return -1; + } + proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL), + KGIDT_INIT(PROC_GID_WIFI)); + +#if CFG_SUPPORT_SET_CAM_BY_PROC + prEntry = + proc_create(PROC_SET_CAM, 0664, gprProcRoot, &proc_set_cam_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry SetCAM\n\r"); + return -1; + } + proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL), + KGIDT_INIT(PROC_GID_WIFI)); +#endif +#if CFG_SUPPORT_DEBUG_FS + prEntry = proc_create(PROC_ROAM_PARAM, 0664, gprProcRoot, &roam_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, + "Unable to create /proc entry roam_param\n\r"); + return -1; + } +#endif + prEntry = proc_create(PROC_COUNTRY, 0664, gprProcRoot, &country_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry country\n\r"); + return -1; + } + +#if CFG_SUPPORT_EASY_DEBUG + + prEntry = + proc_create(PROC_DRIVER_CMD, 0664, gprProcRoot, &drivercmd_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, + "Unable to create /proc entry for driver command\n\r"); + return -1; + } + + prEntry = proc_create(PROC_CFG, 0664, gprProcRoot, &cfg_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, + "Unable to create /proc entry for driver cfg\n\r"); + return -1; + } + + prEntry = + proc_create(PROC_EFUSE_DUMP, 0664, gprProcRoot, &efusedump_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry efuse\n\r"); + return -1; + } +#endif + prEntry = proc_create(PROC_GET_TXPWR_TBL, 0664, gprProcRoot, + &get_txpwr_tbl_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, + "Unable to create /proc entry TXPWR Table\n\r"); + return -1; + } +#ifdef CFG_GET_TEMPURATURE + prEntry = proc_create(PROC_GET_TEMPETATURE, 0664, gprProcRoot, + &get_temperature_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry efuse\n\r"); + return -1; + } +#endif + +#if CFG_DISCONN_DEBUG_FEATURE + prEntry = proc_create(PROC_DISCONN_INFO, 0664, gprProcRoot, + &disconn_info_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, + "Unable to create /proc entry disconn_info\n\r"); + return -1; + } +#endif + + return 0; +} + +#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) +{ + struct GLUE_INFO *prGlueInfo = ((struct net_device *)data)->priv; + char *p = page; + uint32_t u4Count; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(data); + + /* Kevin: Apply PROC read method 1. */ + if (off != 0) + return 0; /* To indicate end of file. */ + + SNPRINTF(p, page, ("GLUE LAYER STATUS:")); + SNPRINTF(p, page, ("\n==================")); + + SNPRINTF(p, page, + ("\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 += (uint32_t) (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) +{ + struct GLUE_INFO *prGlueInfo = ((struct net_device *)data)->priv; + char *p = page; + uint32_t u4Count; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(data); + + /* Kevin: Apply PROC read method 1. */ + if (off != 0) + return 0; /* To indicate end of file. */ + + SNPRINTF(p, page, ("RX STATISTICS (Write 1 to clear):")); + SNPRINTF(p, page, ("\n=================================\n")); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + wlanoidQueryRxStatisticsForLinuxProc(prGlueInfo->prAdapter, p, + &u4Count); + + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + u4Count += (uint32_t) (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) +{ + struct GLUE_INFO *prGlueInfo = ((struct net_device *)data)->priv; + /* + 1 for "\0" */ + char acBuf[PROC_RX_STATISTICS_MAX_USER_INPUT_LEN + 1]; + uint32_t u4CopySize; + uint32_t u4ClearCounter; + int32_t rv; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(data); + + u4CopySize = + (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + copy_from_user(acBuf, buffer, u4CopySize); + acBuf[u4CopySize] = '\0'; + + rv = kstrtoint(acBuf, 0, &u4ClearCounter); + if (rv == 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) +{ + struct GLUE_INFO *prGlueInfo = ((struct net_device *)data)->priv; + char *p = page; + uint32_t u4Count; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(data); + + /* Kevin: Apply PROC read method 1. */ + if (off != 0) + return 0; /* To indicate end of file. */ + + SNPRINTF(p, page, ("TX STATISTICS (Write 1 to clear):")); + SNPRINTF(p, page, ("\n=================================\n")); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + wlanoidQueryTxStatisticsForLinuxProc(prGlueInfo->prAdapter, p, + &u4Count); + + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + u4Count += (uint32_t) (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) +{ + struct GLUE_INFO *prGlueInfo = ((struct net_device *)data)->priv; + /* + 1 for "\0" */ + char acBuf[PROC_RX_STATISTICS_MAX_USER_INPUT_LEN + 1]; + uint32_t u4CopySize; + uint32_t u4ClearCounter; + int32_t rv; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(data); + + u4CopySize = + (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + copy_from_user(acBuf, buffer, u4CopySize); + acBuf[u4CopySize] = '\0'; + + rv = kstrtoint(acBuf, 0, &u4ClearCounter); + if (rv == 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 + +#ifdef FW_CFG_SUPPORT +#define MAX_CFG_OUTPUT_BUF_LENGTH 1024 +static uint8_t aucCfgBuf[CMD_FORMAT_V1_LENGTH]; +static uint8_t aucCfgQueryKey[MAX_CMD_NAME_MAX_LENGTH]; +static uint8_t aucCfgOutputBuf[MAX_CFG_OUTPUT_BUF_LENGTH]; + +static ssize_t cfgRead(struct file *filp, char __user *buf, size_t count, + loff_t *f_pos) +{ + uint32_t rStatus = WLAN_STATUS_FAILURE; + uint8_t *temp = &aucCfgOutputBuf[0]; + uint32_t u4CopySize = 0; + + struct CMD_HEADER cmdV1Header; + struct CMD_FORMAT_V1 *pr_cmd_v1 = + (struct CMD_FORMAT_V1 *)cmdV1Header.buffer; + + /* if *f_pos > 0, we should return 0 to make cat command exit */ + if (*f_pos > 0 || gprGlueInfo == NULL) + return 0; + if (!kalStrLen(aucCfgQueryKey)) + return 0; + + kalMemSet(aucCfgOutputBuf, 0, MAX_CFG_OUTPUT_BUF_LENGTH); + + SNPRINTF(temp, aucCfgOutputBuf, + ("\nprocCfgRead() %s:\n", aucCfgQueryKey)); + + /* send to FW */ + cmdV1Header.cmdVersion = CMD_VER_1; + cmdV1Header.cmdType = CMD_TYPE_QUERY; + cmdV1Header.itemNum = 1; + cmdV1Header.cmdBufferLen = sizeof(struct CMD_FORMAT_V1); + kalMemSet(cmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); + + pr_cmd_v1->itemStringLength = kalStrLen(aucCfgQueryKey); + + kalMemCopy(pr_cmd_v1->itemString, aucCfgQueryKey, + kalStrLen(aucCfgQueryKey)); + + rStatus = kalIoctl(gprGlueInfo, + wlanoidQueryCfgRead, + (void *)&cmdV1Header, + sizeof(cmdV1Header), TRUE, TRUE, TRUE, &u4CopySize); + if (rStatus == WLAN_STATUS_FAILURE) + DBGLOG(INIT, ERROR, + "kalIoctl wlanoidQueryCfgRead fail 0x%x\n", + rStatus); + + SNPRINTF(temp, aucCfgOutputBuf, + ("%s\n", cmdV1Header.buffer)); + + u4CopySize = kalStrLen(aucCfgOutputBuf); + if (u4CopySize > count) + u4CopySize = count; + + if (copy_to_user(buf, aucCfgOutputBuf, u4CopySize)) + DBGLOG(INIT, ERROR, "copy to user failed\n"); + + *f_pos += u4CopySize; + return (ssize_t) u4CopySize; +} + +static ssize_t cfgWrite(struct file *filp, const char __user *buf, + size_t count, loff_t *f_pos) +{ + /* echo xxx xxx > /proc/net/wlan/cfg */ + uint8_t i = 0; + uint32_t u4CopySize = sizeof(aucCfgBuf); + uint8_t token_num = 1; + + kalMemSet(aucCfgBuf, 0, u4CopySize); + u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1); + + if (copy_from_user(aucCfgBuf, buf, u4CopySize)) { + DBGLOG(INIT, ERROR, "copy from user failed\n"); + return -EFAULT; + } + aucCfgBuf[u4CopySize] = '\0'; + for (; i < u4CopySize; i++) { + if (aucCfgBuf[i] == ' ') { + token_num++; + break; + } + } + + if (token_num == 1) { + kalMemSet(aucCfgQueryKey, 0, sizeof(aucCfgQueryKey)); + /* remove the 0x0a */ + memcpy(aucCfgQueryKey, aucCfgBuf, u4CopySize); + if (aucCfgQueryKey[u4CopySize - 1] == 0x0a) + aucCfgQueryKey[u4CopySize - 1] = '\0'; + } else { + if (u4CopySize) + wlanFwCfgParse(gprGlueInfo->prAdapter, aucCfgBuf); + } + + return count; +} + +static const struct file_operations fwcfg_ops = { + .owner = THIS_MODULE, + .read = cfgRead, + .write = cfgWrite, +}; + +int32_t cfgRemoveProcEntry(void) +{ + remove_proc_entry(PROC_CFG_NAME, gprProcRoot); + return 0; +} + +int32_t cfgCreateProcEntry(struct GLUE_INFO *prGlueInfo) +{ + struct proc_dir_entry *prEntry; + + prGlueInfo->pProcRoot = gprProcRoot; + gprGlueInfo = prGlueInfo; + + prEntry = proc_create(PROC_CFG_NAME, 0664, gprProcRoot, &fwcfg_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry cfg\n\r"); + return -1; + } + proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL), + KGIDT_INIT(PROC_GID_WIFI)); + + return 0; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_qa_agent.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_qa_agent.c new file mode 100644 index 0000000000000..dc07673635830 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_qa_agent.c @@ -0,0 +1,8999 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + Module Name: + gl_qa_agent.c +*/ +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ + +#include "precomp.h" +#if (CFG_SUPPORT_QA_TOOL == 1) +#include "gl_wext.h" +#include "gl_cfg80211.h" +#include "gl_ate_agent.h" +#include "gl_qa_agent.h" +#include "gl_hook_api.h" +#if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE +#include +#endif + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +struct PARAM_RX_STAT g_HqaRxStat; +uint32_t u4RxStatSeqNum; +u_int8_t g_DBDCEnable = FALSE; +/* For SA Buffer Mode Temp Solution */ +u_int8_t g_BufferDownload = FALSE; +uint32_t u4EepromMode = 4; +uint32_t g_u4Chip_ID; +uint32_t g_ucEepromCurrentMode = EFUSE_MODE; + +#if CFG_SUPPORT_BUFFER_MODE +uint8_t uacEEPROMImage[MAX_EEPROM_BUFFER_SIZE] = { + /* 0x000 ~ 0x00F */ + 0xAE, 0x86, 0x06, 0x00, 0x18, 0x0D, 0x00, 0x00, + 0xC0, 0x1F, 0xBD, 0x81, 0x3F, 0x01, 0x19, 0x00, + /* 0x010 ~ 0x01F */ + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, + /* 0x020 ~ 0x02F */ + 0x80, 0x02, 0x00, 0x00, 0x32, 0x66, 0xC3, 0x14, + 0x32, 0x66, 0xC3, 0x14, 0x03, 0x22, 0xFF, 0xFF, + /* 0x030 ~ 0x03F */ + 0x23, 0x04, 0x0D, 0xF2, 0x8F, 0x02, 0x00, 0x80, + 0x0A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x040 ~ 0x04F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x33, 0x40, 0x00, 0x00, + /* 0x050 ~ 0x05F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x08, + /* 0x060 ~ 0x06F */ + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x08, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x08, + /* 0x070 ~ 0x07F */ + 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x080 ~ 0x08F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x090 ~ 0x09F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x0A0 ~ 0x0AF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x0B0 ~ 0x0BF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x92, 0x10, 0x10, 0x28, 0x00, 0x00, 0x00, 0x00, + /* 0x0C0 ~ 0x0CF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x0D0 ~ 0x0DF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x0E0 ~ 0x0EF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x0F0 ~ 0x0FF */ + 0x0E, 0x05, 0x06, 0x06, 0x06, 0x0F, 0x00, 0x00, + 0x0E, 0x05, 0x06, 0x05, 0x05, 0x09, 0xFF, 0x00, + /* 0x100 ~ 0x10F */ + 0x12, 0x34, 0x56, 0x78, 0x2C, 0x2C, 0x28, 0x28, + 0x28, 0x26, 0x26, 0x28, 0x28, 0x28, 0x26, 0xFF, + /* 0x110 ~ 0x11F */ + 0x26, 0x25, 0x28, 0x21, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x27, 0x27, 0x27, 0x25, + /* 0x120 ~ 0x12F */ + 0x25, 0x25, 0x25, 0x25, 0x23, 0x23, 0x23, 0x21, + 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, + /* 0x130 ~ 0x13F */ + 0x40, 0x40, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, + 0xD0, 0xD0, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + /* 0x140 ~ 0x14F */ + 0x25, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x150 ~ 0x15F */ + 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, + 0x40, 0x40, 0x40, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, + /* 0x160 ~ 0x16F */ + 0xD0, 0xD0, 0xD0, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x170 ~ 0x17F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC2, 0xC4, 0xC5, 0xC8, + /* 0x180 ~ 0x18F */ + 0x00, 0x26, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x190 ~ 0x19F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x1A0 ~ 0x1AF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0xD0, + 0xD0, 0x0E, 0x05, 0x06, 0x05, 0x09, 0x0E, 0x00, + /* 0x1B0 ~ 0x1BF */ + 0x05, 0x06, 0x05, 0x05, 0x09, 0x00, 0x00, 0x00, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + /* 0x1C0 ~ 0x1CF */ + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, + /* 0x1D0 ~ 0x1DF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x1E0 ~ 0x1EF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x1F0 ~ 0x1FF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x200 ~ 0x20F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x210 ~ 0x21F */ + 0x48, 0xF5, 0x27, 0x49, 0x48, 0xF5, 0x57, 0x12, + 0x4B, 0x71, 0x80, 0x50, 0x91, 0xF6, 0x87, 0x50, + /* 0x220 ~ 0x22F */ + 0x7D, 0x29, 0x09, 0x42, 0x7D, 0x29, 0x41, 0x44, + 0x7D, 0x29, 0x41, 0x3C, 0x7D, 0x29, 0x31, 0x4D, + /* 0x230 ~ 0x23F */ + 0x49, 0x71, 0x24, 0x49, 0x49, 0x71, 0x54, 0x12, + 0x4B, 0x71, 0x80, 0x50, 0x91, 0xF6, 0x87, 0x50, + /* 0x240 ~ 0x24F */ + 0x7D, 0x29, 0x09, 0x42, 0x7D, 0x29, 0x41, 0x04, + 0x7D, 0x29, 0x41, 0x04, 0x7D, 0x29, 0x01, 0x40, + /* 0x250 ~ 0x25F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x260 ~ 0x26F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x270 ~ 0x27F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x280 ~ 0x28F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x290 ~ 0x29F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x2A0 ~ 0x2AF */ + 0x7D, 0x29, 0xC9, 0x16, 0x7D, 0x29, 0xC9, 0x16, + 0x44, 0x22, 0x32, 0x15, 0xEE, 0xEE, 0xEE, 0x08, + /* 0x2B0 ~ 0x2BF */ + 0x78, 0x90, 0x79, 0x1C, 0x78, 0x90, 0x79, 0x1C, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x2C0 ~ 0x2CF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x2D0 ~ 0x2DF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x2E0 ~ 0x2EF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x2F0 ~ 0x2FF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x300 ~ 0x30F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x310 ~ 0x31F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x42, 0x10, 0x42, 0x08, 0x21, + /* 0x320 ~ 0x32F */ + 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x21, + 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x21, + /* 0x330 ~ 0x33F */ + 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x21, + 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x21, + /* 0x340 ~ 0x34F */ + 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x21, + 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x01, + /* 0x350 ~ 0x35F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x360 ~ 0x36F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x370 ~ 0x37F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x380 ~ 0x38F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x390 ~ 0x39F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x3A0 ~ 0x3AF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x3B0 ~ 0x3BF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x3C0 ~ 0x3CF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x3D0 ~ 0x3DF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x3E0 ~ 0x3EF */ + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + /* 0x3F0 ~ 0x3FF */ + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + /* 0x400 ~ 0x40F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x410 ~ 0x41F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x420 ~ 0x42F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x430 ~ 0x43F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x440 ~ 0x44F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x450 ~ 0x45F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x460 ~ 0x46F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x470 ~ 0x47F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x480 ~ 0x48F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x490 ~ 0x49F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x4A0 ~ 0x4AF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Response ACK to QA Tool DLL. + * + * \param[in] HqaCmdFrame Ethernet Frame Format respond to QA Tool DLL + * \param[in] prIwReqData + * \param[in] i4Length Length of Ethernet Frame data field + * \param[in] i4Status Status to respond + * \param[out] None + * + * \retval 0 On success. + * \retval -EFAULT If copy_to_user fail + */ +/*----------------------------------------------------------------------------*/ +static int32_t ResponseToQA(struct HQA_CMD_FRAME + *HqaCmdFrame, + IN union iwreq_data *prIwReqData, int32_t i4Length, + int32_t i4Status) +{ + HqaCmdFrame->Length = ntohs((i4Length)); + + i4Status = ntohs((i4Status)); + memcpy(HqaCmdFrame->Data, &i4Status, 2); + + prIwReqData->data.length = sizeof((HqaCmdFrame)->MagicNo) + + sizeof((HqaCmdFrame)->Type) + + sizeof((HqaCmdFrame)->Id) + + sizeof((HqaCmdFrame)->Length) + + sizeof((HqaCmdFrame)->Sequence) + + ntohs((HqaCmdFrame)->Length); + + if (copy_to_user(prIwReqData->data.pointer, + (uint8_t *) (HqaCmdFrame), prIwReqData->data.length)) { + DBGLOG(RFTEST, INFO, "QA_AGENT copy_to_user() fail in %s\n", + __func__); + return -EFAULT; + } + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA command(0x%04x)[Magic number(0x%08x)] is done\n", + ntohs(HqaCmdFrame->Id), ntohl(HqaCmdFrame->MagicNo)); + + return 0; +} + +static int32_t ToDoFunction(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT ToDoFunction\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Open Adapter (called when QA Tool UI Open). + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_OpenAdapter(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_OpenAdapter\n"); + + i4Ret = MT_ATEStart(prNetDev, "ATESTART"); + + /* For SA Buffer Mode Temp Solution */ + g_BufferDownload = FALSE; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Close Adapter (called when QA Tool UI Close). + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_CloseAdapter(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_CloseAdapter\n"); + + i4Ret = MT_ATEStop(prNetDev, "ATESTOP"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Start TX. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_StartTx(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t TxCount; + uint16_t TxLength; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StartTx\n"); + + memcpy((uint8_t *)&TxCount, HqaCmdFrame->Data + 4 * 0, 4); + TxCount = ntohl(TxCount); + memcpy((uint8_t *)&TxLength, HqaCmdFrame->Data + 4 * 1, 2); + TxLength = ntohs(TxLength); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StartTx TxCount = %d\n", + TxCount); + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StartTx TxLength = %d\n", + TxLength); + + i4Ret = MT_ATESetTxCount(prNetDev, TxCount); + i4Ret = MT_ATESetTxLength(prNetDev, (uint32_t) TxLength); + i4Ret = MT_ATEStartTX(prNetDev, "TXFRAME"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +/* 1 todo not support yet */ +static int32_t HQA_StartTxExt(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StartTxExt\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Start Continuous TX. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +/* 1 todo not support yet */ +static int32_t HQA_StartTxContiTx(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StartTxContiTx\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +/* 1 todo not support yets */ +static int32_t HQA_StartTxCarrier(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StartTxCarrier\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Start RX (Legacy function). + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_StartRx(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StartRx\n"); + + MT_ATESetDBDCBandIndex(prNetDev, 0); + MT_ATEStartRX(prNetDev, "RXFRAME"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Stop TX (Legacy function). + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_StopTx(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StopTx\n"); + + MT_ATESetDBDCBandIndex(prNetDev, 0); + MT_ATEStopRX(prNetDev, "RXSTOP"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Stop Continuous TX. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_StopContiTx(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StopContiTx\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_StopTxCarrier(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StopTxCarrier\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Stop RX (Legacy function). + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_StopRx(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StopRx\n"); + + MT_ATESetDBDCBandIndex(prNetDev, 0); + MT_ATEStopRX(prNetDev, "RXSTOP"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set TX Path. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetTxPath(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetTxPath\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set RX Path. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetRxPath(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + /* INT_16 Value = 0; + * P_GLUE_INFO_T prGlueInfo = NULL; + * PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + * UINT_32 u4BufLen = 0; + */ + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetRxPath\n"); + +#if 0 + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + memcpy(&Value, HqaCmdFrame->Data + 4 * 0, 2); + Value = ntohs(Value); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetRxPath Value : %d\n", + Value); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_RX_PATH; + rRfATInfo.u4FuncData = (uint32_t) ((Value << 16) + || (0 & BITS(0, 15))); + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; +#endif + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set TX Inter-Packet Guard. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetTxIPG(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Aifs = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetTxIPG\n"); + + memcpy(&u4Aifs, HqaCmdFrame->Data + 4 * 0, 4); + u4Aifs = ntohs(u4Aifs); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetTxIPG u4Aifs : %d\n", + u4Aifs); + + MT_ATESetTxIPG(prNetDev, u4Aifs); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set TX Power0 (Legacy Function). + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetTxPower0(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetTxPower0\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set TX Power1. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HAQ_SetTxPower1(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HAQ_SetTxPower1\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetTxPowerExt(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Power = 0; + uint32_t u4Channel = 0; + uint32_t u4Dbdc_idx = 0; + uint32_t u4Band_idx = 0; + uint32_t u4Ant_idx = 0; + + memcpy(&u4Power, HqaCmdFrame->Data + 4 * 0, 4); + u4Power = ntohl(u4Power); + memcpy(&u4Dbdc_idx, HqaCmdFrame->Data + 4 * 1, 4); + u4Dbdc_idx = ntohl(u4Dbdc_idx); + memcpy(&u4Channel, HqaCmdFrame->Data + 4 * 2, 4); + u4Channel = ntohl(u4Channel); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 3, 4); + u4Band_idx = ntohl(u4Band_idx); + memcpy(&u4Ant_idx, HqaCmdFrame->Data + 4 * 4, 4); + u4Ant_idx = ntohl(u4Ant_idx); + + DBGLOG(RFTEST, INFO, + " QA_AGENT HQA_SetTxPowerExt u4Power : %u,u4Dbdc_idx:%u, u4Channel:%u,u4Band_idx:%u, u4Ant_idx:%u\n", + u4Power, u4Dbdc_idx, u4Channel, u4Band_idx, u4Ant_idx); + + MT_ATESetDBDCBandIndex(prNetDev, u4Dbdc_idx); + MT_ATESetTxPower0(prNetDev, u4Power); + /* u4Freq = nicChannelNum2Freq(u4Channel); */ + /* i4Ret = MT_ATESetChannel(prNetDev, 0, u4Freq); */ + /* MT_ATESetBand(prNetDev, u4Band_idx); */ + /* Antenna?? */ + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetOnOff(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetOnOff\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Antenna Selection. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_AntennaSel(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_AntennaSel\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_FWPacketCMD_ClockSwitchDisable( + struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_FWPacketCMD_ClockSwitchDisable\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_CMD_SET0[] = { + /* cmd id start from 0x1000 */ + HQA_OpenAdapter, /* 0x1000 */ + HQA_CloseAdapter, /* 0x1001 */ + HQA_StartTx, /* 0x1002 */ + HQA_StartTxExt, /* 0x1003 */ + HQA_StartTxContiTx, /* 0x1004 */ + HQA_StartTxCarrier, /* 0x1005 */ + HQA_StartRx, /* 0x1006 */ + HQA_StopTx, /* 0x1007 */ + HQA_StopContiTx, /* 0x1008 */ + HQA_StopTxCarrier, /* 0x1009 */ + HQA_StopRx, /* 0x100A */ + HQA_SetTxPath, /* 0x100B */ + HQA_SetRxPath, /* 0x100C */ + HQA_SetTxIPG, /* 0x100D */ + HQA_SetTxPower0, /* 0x100E */ + HAQ_SetTxPower1, /* 0x100F */ + ToDoFunction, /* 0x1010 */ + HQA_SetTxPowerExt, /* 0x1011 */ + HQA_SetOnOff, /* 0x1012 */ + HQA_AntennaSel, /* 0x1013 */ + HQA_FWPacketCMD_ClockSwitchDisable, /* 0x1014 */ +}; + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set Channel Frequency (Legacy Function). + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetChannel(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + uint32_t i4SetFreq = 0, i4SetChan = 0; + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetChannel\n"); + + memcpy((uint8_t *)&i4SetChan, HqaCmdFrame->Data, 4); + i4SetChan = ntohl(i4SetChan); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetChannel Channel = %d\n", i4SetChan); + + i4SetFreq = nicChannelNum2Freq(i4SetChan); + i4Ret = MT_ATESetChannel(prNetDev, 0, i4SetFreq); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set Preamble (Legacy Function). + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetPreamble(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Mode = 0; + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetPreamble\n"); + + memcpy((uint8_t *)&i4Mode, HqaCmdFrame->Data, 4); + i4Mode = ntohl(i4Mode); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetPreamble Mode = %d\n", + i4Mode); + + i4Ret = MT_ATESetPreamble(prNetDev, i4Mode); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set Rate (Legacy Function). + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetRate(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + /* INT_32 i4Value = 0; */ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetRate\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set Nss. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetNss(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetNss\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set System BW (Legacy Function). + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetSystemBW(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + uint32_t i4BW; + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetSystemBW\n"); + + memcpy((uint8_t *)&i4BW, HqaCmdFrame->Data, 4); + i4BW = ntohl(i4BW); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetSystemBW BW = %d\n", + i4BW); + + i4Ret = MT_ATESetSystemBW(prNetDev, i4BW); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set Data BW (Legacy Function). + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetPerPktBW(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Perpkt_bw; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetPerPktBW\n"); + + memcpy((uint8_t *)&u4Perpkt_bw, HqaCmdFrame->Data, 4); + u4Perpkt_bw = ntohl(u4Perpkt_bw); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetPerPktBW u4Perpkt_bw = %d\n", u4Perpkt_bw); + + i4Ret = MT_ATESetPerPacketBW(prNetDev, u4Perpkt_bw); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set Primary BW. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetPrimaryBW(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Pri_sel = 0; + + memcpy(&u4Pri_sel, HqaCmdFrame->Data, 4); + u4Pri_sel = ntohl(u4Pri_sel); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetPrimaryBW u4Pri_sel : %d\n", u4Pri_sel); + + i4Ret = MT_ATEPrimarySetting(prNetDev, u4Pri_sel); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set Frequency Offset. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetFreqOffset(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4FreqOffset = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t u4BufLen = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + memcpy(&u4FreqOffset, HqaCmdFrame->Data, 4); + u4FreqOffset = ntohl(u4FreqOffset); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetFreqOffset u4FreqOffset : %d\n", + u4FreqOffset); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_FRWQ_OFFSET; + rRfATInfo.u4FuncData = (uint32_t) u4FreqOffset; + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetAutoResponder(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetAutoResponder\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetTssiOnOff(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetTssiOnOff\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +/* 1 todo not support yet */ + +static int32_t HQA_SetRxHighLowTemperatureCompensation( + struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetRxHighLowTemperatureCompensation\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_LowPower(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_LowPower\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_CMD_SET1[] = { + /* cmd id start from 0x1100 */ + HQA_SetChannel, /* 0x1100 */ + HQA_SetPreamble, /* 0x1101 */ + HQA_SetRate, /* 0x1102 */ + HQA_SetNss, /* 0x1103 */ + HQA_SetSystemBW, /* 0x1104 */ + HQA_SetPerPktBW, /* 0x1105 */ + HQA_SetPrimaryBW, /* 0x1106 */ + HQA_SetFreqOffset, /* 0x1107 */ + HQA_SetAutoResponder, /* 0x1108 */ + HQA_SetTssiOnOff, /* 0x1109 */ + HQA_SetRxHighLowTemperatureCompensation, /* 0x110A */ + HQA_LowPower, /* 0x110B */ +}; + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Reset TRX Counter + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_ResetTxRxCounter(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + uint32_t i4Status; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_ResetTxRxCounter\n"); + + i4Status = MT_ATEResetTXRXCounter(prNetDev); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetStatistics(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_GetStatistics\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetRxOKData(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_GetRxOKData\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetRxOKOther(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_GetRxOKOther\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetRxAllPktCount(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_GetRxAllPktCount\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetTxTransmitted(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_GetTxTransmitted\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetHwCounter(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_GetHwCounter\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_CalibrationOperation(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_CalibrationOperation\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_CalibrationBypassExt(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Status = 0; + uint32_t u4Item = 0; + uint32_t u4Band_idx = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t u4BufLen = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + memcpy(&u4Item, HqaCmdFrame->Data, 4); + u4Item = ntohl(u4Item); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_CalibrationBypassExt u4Item : 0x%08x\n", + u4Item); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_CalibrationBypassExt u4Band_idx : %d\n", + u4Band_idx); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_BYPASS_CAL_STEP; + rRfATInfo.u4FuncData = u4Item; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetRXVectorIdx(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t band_idx = 0; + uint32_t Group_1 = 0, Group_2 = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t u4BufLen = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + memcpy(&band_idx, HqaCmdFrame->Data + 4 * 0, 4); + band_idx = ntohl(band_idx); + memcpy(&Group_1, HqaCmdFrame->Data + 4 * 1, 4); + Group_1 = ntohl(Group_1); + memcpy(&Group_2, HqaCmdFrame->Data + 4 * 2, 4); + Group_2 = ntohl(Group_2); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetRXVectorIdx band_idx : %d\n", band_idx); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetRXVectorIdx Group_1 : %d\n", Group_1); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetRXVectorIdx Group_2 : %d\n", Group_2); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_RXV_INDEX; + rRfATInfo.u4FuncData = (uint32_t) (Group_1); + rRfATInfo.u4FuncData |= (uint32_t) (Group_2 << 8); + rRfATInfo.u4FuncData |= (uint32_t) (band_idx << 16); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetRXVectorIdx rRfATInfo.u4FuncData : 0x%08x\n", + rRfATInfo.u4FuncData); + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set FAGC Rssi Path + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetFAGCRssiPath(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4band_idx = 0; + uint32_t u4FAGC_Path = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t u4BufLen = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + memcpy(&u4band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4band_idx = ntohl(u4band_idx); + memcpy(&u4FAGC_Path, HqaCmdFrame->Data + 4 * 1, 4); + u4FAGC_Path = ntohl(u4FAGC_Path); + + DBGLOG(RFTEST, INFO, "u4band_idx : %d, u4FAGC_Path : %d\n", + u4band_idx, u4FAGC_Path); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_FAGC_RSSI_PATH; + rRfATInfo.u4FuncData = (uint32_t) ((u4band_idx << 16) | + (u4FAGC_Path & BITS(0, 15))); + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_CMD_SET2[] = { + /* cmd id start from 0x1200 */ + HQA_ResetTxRxCounter, /* 0x1200 */ + HQA_GetStatistics, /* 0x1201 */ + HQA_GetRxOKData, /* 0x1202 */ + HQA_GetRxOKOther, /* 0x1203 */ + HQA_GetRxAllPktCount, /* 0x1204 */ + HQA_GetTxTransmitted, /* 0x1205 */ + HQA_GetHwCounter, /* 0x1206 */ + HQA_CalibrationOperation, /* 0x1207 */ + HQA_CalibrationBypassExt, /* 0x1208 */ + HQA_SetRXVectorIdx, /* 0x1209 */ + HQA_SetFAGCRssiPath, /* 0x120A */ +}; + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For MAC CR Read. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_MacBbpRegRead(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + uint32_t u4Offset, u4Value; + int32_t i4Status; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MCR_RW_STRUCT rMcrInfo; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MacBbpRegRead\n"); + + memcpy(&u4Offset, HqaCmdFrame->Data, 4); + u4Offset = ntohl(u4Offset); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MacBbpRegRead Offset = 0x%08x\n", u4Offset); + + rMcrInfo.u4McrOffset = u4Offset; + rMcrInfo.u4McrData = 0; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, wlanoidQueryMcrRead, + &rMcrInfo, sizeof(rMcrInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + u4Value = rMcrInfo.u4McrData; + + DBGLOG(RFTEST, INFO, + "QA_AGENT Address = 0x%08x, Result = 0x%08x\n", u4Offset, + u4Value); + + u4Value = ntohl(u4Value); + memcpy(HqaCmdFrame->Data + 2, &u4Value, 4); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For MAC CR Write. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_MacBbpRegWrite(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + + /* INT_32 i4Ret = 0; */ + uint32_t u4Offset, u4Value; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MCR_RW_STRUCT rMcrInfo; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MacBbpRegWrite\n"); + + memcpy(&u4Offset, HqaCmdFrame->Data, 4); + memcpy(&u4Value, HqaCmdFrame->Data + 4, 4); + + u4Offset = ntohl(u4Offset); + u4Value = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MacBbpRegWrite Offset = 0x%08x\n", u4Offset); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MacBbpRegWrite Value = 0x%08x\n", u4Value); + + rMcrInfo.u4McrOffset = u4Offset; + rMcrInfo.u4McrData = u4Value; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, wlanoidSetMcrWrite, &rMcrInfo, + sizeof(rMcrInfo), FALSE, FALSE, TRUE, &u4BufLen); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Read Bulk MAC CR. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_MACBbpRegBulkRead(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + uint32_t u4Index, u4Offset, u4Value; + uint16_t u2Len; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MCR_RW_STRUCT rMcrInfo; + + memcpy(&u4Offset, HqaCmdFrame->Data, 4); + u4Offset = ntohl(u4Offset); + memcpy(&u2Len, HqaCmdFrame->Data + 4, 2); + u2Len = ntohs(u2Len); + + DBGLOG(RFTEST, INFO, "Offset = 0x%08x, Len = 0x%08x\n", + u4Offset, u2Len); + + for (u4Index = 0; u4Index < u2Len; u4Index++) { + rMcrInfo.u4McrOffset = u4Offset + u4Index * 4; + rMcrInfo.u4McrData = 0; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, wlanoidQueryMcrRead, + &rMcrInfo, sizeof(rMcrInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + u4Value = rMcrInfo.u4McrData; + + DBGLOG(RFTEST, INFO, + "Address = 0x%08x, Result = 0x%08x\n", + u4Offset + u4Index * 4, u4Value); + + u4Value = ntohl(u4Value); + memcpy(HqaCmdFrame->Data + 2 + (u4Index * 4), &u4Value, + 4); + } + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + (u2Len * 4), + i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Read Bulk RF CR. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_RfRegBulkRead(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + uint32_t u4Index, u4WfSel, u4Offset, u4Length, u4Value; + int32_t i4Status = 0; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MCR_RW_STRUCT rMcrInfo; + + memcpy(&u4WfSel, HqaCmdFrame->Data, 4); + u4WfSel = ntohl(u4WfSel); + memcpy(&u4Offset, HqaCmdFrame->Data + 4, 4); + u4Offset = ntohl(u4Offset); + memcpy(&u4Length, HqaCmdFrame->Data + 8, 4); + u4Length = ntohl(u4Length); + + DBGLOG(RFTEST, INFO, " WfSel = %u, Offset = 0x%08x, Length = %u\n", + u4WfSel, u4Offset, u4Length); + + if (u4WfSel == 0) + u4Offset = u4Offset | 0x99900000; + else if (u4WfSel == 1) + u4Offset = u4Offset | 0x99910000; + else if (u4WfSel == 0x0F) { + u4Offset = u4Offset | 0x99000000; + u4Offset = u4Offset | (u4WfSel << 16); + } + + + for (u4Index = 0; u4Index < u4Length; u4Index++) { + rMcrInfo.u4McrOffset = u4Offset + u4Index * 4; + rMcrInfo.u4McrData = 0; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, wlanoidQueryMcrRead, + &rMcrInfo, sizeof(rMcrInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + u4Value = rMcrInfo.u4McrData; + + DBGLOG(RFTEST, INFO, + "Address = 0x%08x, Result = 0x%08x\n", + u4Offset + u4Index * 4, u4Value); + + u4Value = ntohl(u4Value); + memcpy(HqaCmdFrame->Data + 2 + (u4Index * 4), &u4Value, + 4); + } + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + (u4Length * 4), + i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Write RF CR. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_RfRegBulkWrite(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + uint32_t u4WfSel, u4Offset, u4Length, u4Value; + int32_t i4Status; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_MCR_RW_STRUCT rMcrInfo; + + memcpy(&u4WfSel, HqaCmdFrame->Data, 4); + u4WfSel = ntohl(u4WfSel); + memcpy(&u4Offset, HqaCmdFrame->Data + 4, 4); + u4Offset = ntohl(u4Offset); + memcpy(&u4Length, HqaCmdFrame->Data + 8, 4); + u4Length = ntohl(u4Length); + memcpy(&u4Value, HqaCmdFrame->Data + 12, 4); + u4Value = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, + "WfSel = %u, Offset = 0x%08x, Length = %u, Value = 0x%08x\n", + u4WfSel, u4Offset, u4Length, u4Value); + + if (u4WfSel == 0) + u4Offset = u4Offset | 0x99900000; + else if (u4WfSel == 1) + u4Offset = u4Offset | 0x99910000; + else if (u4WfSel == 0x0F) { + u4Offset = u4Offset | 0x99000000; + u4Offset = u4Offset | (u4WfSel << 16); + } + + + rMcrInfo.u4McrOffset = u4Offset; + rMcrInfo.u4McrData = u4Value; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, wlanoidSetMcrWrite, + &rMcrInfo, sizeof(rMcrInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_ReadEEPROM(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + + uint16_t Offset; + uint16_t Len; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + uint32_t u4BufLen = 0; + uint8_t u4Index = 0; + uint16_t u4Value = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_ACCESS_EFUSE rAccessEfuseInfo; +#endif + + DBGLOG(INIT, INFO, "QA_AGENT HQA_ReadEEPROM\n"); + + memcpy(&Offset, HqaCmdFrame->Data + 2 * 0, 2); + Offset = ntohs(Offset); + memcpy(&Len, HqaCmdFrame->Data + 2 * 1, 2); + Len = ntohs(Len); + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (prGlueInfo->prAdapter && + prGlueInfo->prAdapter->chip_info && + !prGlueInfo->prAdapter->chip_info->is_support_efuse) { + rStatus = WLAN_STATUS_NOT_SUPPORTED; + log_dbg(RFTEST, WARN, "Efuse not support\n"); + ResponseToQA(HqaCmdFrame, prIwReqData, 2, rStatus); + return rStatus; + } + + kalMemSet(&rAccessEfuseInfo, 0, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + + + rAccessEfuseInfo.u4Address = + (Offset / EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfo, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), + TRUE, TRUE, TRUE, &u4BufLen); + + u4Index = Offset % EFUSE_BLOCK_SIZE; + if (u4Index <= 14) + u4Value = + (prGlueInfo->prAdapter->aucEepromVaule[u4Index]) | + (prGlueInfo->prAdapter->aucEepromVaule[u4Index + 1] << 8); + + + /* isVaild = pResult->u4Valid; */ + + if (rStatus == WLAN_STATUS_SUCCESS) { + + DBGLOG(INIT, INFO, "QA_AGENT HQA_ReadEEPROM u4Value = %x\n", + u4Value); + + u4Value = ntohl(u4Value); + memcpy(HqaCmdFrame->Data + 2, &u4Value, sizeof(u4Value)); + } +#endif + + ResponseToQA(HqaCmdFrame, prIwReqData, 4, rStatus); + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_WriteEEPROM(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + uint16_t u4WriteData = 0; + uint32_t u4BufLen = 0; + uint8_t u4Index = 0; + uint16_t Offset; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_ACCESS_EFUSE rAccessEfuseInfoWrite; + + memcpy(&Offset, HqaCmdFrame->Data + 2 * 0, 2); + Offset = ntohs(Offset); + memcpy(&u4WriteData, HqaCmdFrame->Data + 2 * 1, 2); + u4WriteData = ntohs(u4WriteData); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); +#if 0 + /* Read */ + DBGLOG(INIT, INFO, "QA_AGENT HQA_ReadEEPROM\n"); + kalMemSet(&rAccessEfuseInfoRead, 0, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + rAccessEfuseInfoRead.u4Address = (Offset / EFUSE_BLOCK_SIZE) + * EFUSE_BLOCK_SIZE; + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfoRead, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), + FALSE, FALSE, TRUE, &u4BufLen); +#endif + + /* Write */ + DBGLOG(INIT, INFO, "QA_AGENT HQA_WriteEEPROM\n"); + kalMemSet(&rAccessEfuseInfoWrite, 0, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + u4Index = Offset % EFUSE_BLOCK_SIZE; + + if (prGlueInfo->prAdapter->rWifiVar.ucEfuseBufferModeCal == + LOAD_EEPROM_BIN) { + uacEEPROMImage[Offset] = u4WriteData & 0xff; + uacEEPROMImage[Offset + 1] = u4WriteData >> 8 & 0xff; + } else if (u4Index >= EFUSE_BLOCK_SIZE - 1) { + DBGLOG(INIT, ERROR, "u4Index [%d] overrun\n", u4Index); + } else { + prGlueInfo->prAdapter->aucEepromVaule[u4Index] = u4WriteData + & 0xff; /* Note: u4WriteData is UINT_16 */ + prGlueInfo->prAdapter->aucEepromVaule[u4Index + 1] = + u4WriteData >> 8 & 0xff; + + kalMemCopy(rAccessEfuseInfoWrite.aucData, + prGlueInfo->prAdapter->aucEepromVaule, 16); + rAccessEfuseInfoWrite.u4Address = + (Offset / EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseWrite, + &rAccessEfuseInfoWrite, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), + FALSE, FALSE, TRUE, &u4BufLen); + } +#endif + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_ReadBulkEEPROM(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint16_t Offset; + uint16_t Len; +#if (CFG_EEPROM_PAGE_ACCESS == 1) + struct PARAM_CUSTOM_ACCESS_EFUSE rAccessEfuseInfo; + uint32_t u4BufLen = 0; + uint8_t u4Loop = 0; + + uint16_t Buffer; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint8_t tmp = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + kalMemSet(&rAccessEfuseInfo, 0, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); +#endif + + DBGLOG(INIT, INFO, "QA_AGENT HQA_ReadBulkEEPROM\n"); + if (prAdapter->chip_info && + !prAdapter->chip_info->is_support_efuse) { + log_dbg(RFTEST, WARN, "Efuse not support\n"); + rStatus = WLAN_STATUS_NOT_SUPPORTED; + ResponseToQA(HqaCmdFrame, prIwReqData, + 2, rStatus); + return rStatus; + } + + memcpy(&Offset, HqaCmdFrame->Data + 2 * 0, 2); + Offset = ntohs(Offset); + memcpy(&Len, HqaCmdFrame->Data + 2 * 1, 2); + Len = ntohs(Len); + tmp = Offset; + DBGLOG(INIT, INFO, + "QA_AGENT HQA_ReadBulkEEPROM Offset : %d\n", Offset); + DBGLOG(INIT, INFO, "QA_AGENT HQA_ReadBulkEEPROM Len : %d\n", + Len); + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + rAccessEfuseInfo.u4Address = (Offset / EFUSE_BLOCK_SIZE) * + EFUSE_BLOCK_SIZE; + + DBGLOG(INIT, INFO, + "QA_AGENT HQA_ReadBulkEEPROM Address : %d\n", + rAccessEfuseInfo.u4Address); + + if ((g_ucEepromCurrentMode == EFUSE_MODE) + && (prGlueInfo->prAdapter->fgIsSupportQAAccessEfuse == + TRUE)) { + + /* Read from Efuse */ + DBGLOG(INIT, INFO, + "QA_AGENT HQA_ReadBulkEEPROM Efuse Mode\n"); + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfo, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_FAILURE) + DBGLOG(INIT, INFO, + "QA_AGENT HQA_ReadBulkEEPROM kal fail\n"); + + Offset = Offset % EFUSE_BLOCK_SIZE; + +#if 0 + for (u4Loop = 0; u4Loop < 16; u4Loop++) { + DBGLOG(INIT, INFO, + "MT6632:QA_AGENT HQA_ReadBulkEEPROM Efuse Offset=%x u4Loop=%d u4Value=%x\n", + Offset, u4Loop, + prGlueInfo->prAdapter->aucEepromVaule[u4Loop]); + } +#endif + for (u4Loop = 0; u4Loop < Len; u4Loop += 2) { + memcpy(&Buffer, prGlueInfo->prAdapter->aucEepromVaule + + Offset + u4Loop, 2); + Buffer = ntohs(Buffer); + DBGLOG(INIT, INFO, + ":From Efuse u4Loop=%d Buffer=%x\n", + u4Loop, Buffer); + memcpy(HqaCmdFrame->Data + 2 + u4Loop, &Buffer, 2); + } + + } else { /* Read from EEPROM */ + for (u4Loop = 0; u4Loop < Len; u4Loop += 2) { + memcpy(&Buffer, uacEEPROMImage + Offset + u4Loop, 2); + Buffer = ntohs(Buffer); + memcpy(HqaCmdFrame->Data + 2 + u4Loop, &Buffer, 2); + DBGLOG(INIT, INFO, + "QA_AGENT HQA_ReadBulkEEPROM u4Loop=%d u4Value=%x\n", + u4Loop, uacEEPROMImage[Offset + u4Loop]); + } + } +#endif + + /*kfree(Buffer);*/ + + /* Read from buffer array in driver */ + /* Pass these data to FW also */ +#if 0 + for (i = 0 ; i < Len ; i += 2) { + memcpy(&u2Temp, uacEEPROMImage + Offset + i, 2); + u2Temp = ntohs(u2Temp); + memcpy(HqaCmdFrame->Data + 2 + i, &u2Temp, 2); + } +#endif + /* For SA Buffer Mode Temp Solution */ +#if 0 + if (Offset == 0x4A0 && !g_BufferDownload) { + + uint16_t u2InitAddr = 0x000; + uint32_t i = 0, j = 0; + uint32_t u4BufLen = 0; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE rSetEfuseBufModeInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + for (i = 0 ; i < MAX_EEPROM_BUFFER_SIZE / 16 ; i++) { + for (j = 0 ; j < 16 ; j++) { + rSetEfuseBufModeInfo.aBinContent[j].u2Addr = + u2InitAddr; + rSetEfuseBufModeInfo.aBinContent[j].ucValue = + uacEEPROMImage[u2InitAddr]; + u2InitAddr += 1; + } + + rSetEfuseBufModeInfo.ucSourceMode = 1; + rSetEfuseBufModeInfo.ucCount = EFUSE_CONTENT_SIZE; + rStatus = kalIoctl(prGlueInfo, wlanoidSetEfusBufferMode, + &rSetEfuseBufModeInfo, + sizeof(struct PARAM_CUSTOM_EFUSE_BUFFER_MODE), + FALSE, FALSE, TRUE, &u4BufLen); + } + + g_BufferDownload = TRUE; + } +#endif + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + Len, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_WriteBulkEEPROM(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint16_t Offset; + uint16_t Len; + struct ADAPTER *prAdapter = NULL; + + uint32_t u4BufLen = 0; + struct PARAM_CUSTOM_ACCESS_EFUSE rAccessEfuseInfoRead, + rAccessEfuseInfoWrite; + uint16_t testBuffer1, testBuffer2, testBuffer; + uint16_t *Buffer = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint8_t u4Loop = 0, u4Index = 0; + uint16_t ucTemp2; + uint16_t i = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + kalMemSet(&rAccessEfuseInfoRead, 0, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + kalMemSet(&rAccessEfuseInfoWrite, 0, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + + DBGLOG(INIT, INFO, "QA_AGENT HQA_WriteBulkEEPROM\n"); + + + memcpy(&Offset, HqaCmdFrame->Data + 2 * 0, 2); + Offset = ntohs(Offset); + memcpy(&Len, HqaCmdFrame->Data + 2 * 1, 2); + Len = ntohs(Len); + + memcpy(&testBuffer1, HqaCmdFrame->Data + 2 * 2, Len); + testBuffer2 = ntohs(testBuffer1); + testBuffer = ntohs(testBuffer1); + + DBGLOG(INIT, INFO, "Offset : %x, Len : %u\n", Offset, Len); + + /* Support Delay Calibraiton */ + if (prGlueInfo->prAdapter->fgIsSupportQAAccessEfuse == + TRUE) { + + Buffer = kmalloc(sizeof(uint8_t) * (EFUSE_BLOCK_SIZE), + GFP_KERNEL); + ASSERT(Buffer); + kalMemSet(Buffer, 0, sizeof(uint8_t) * (EFUSE_BLOCK_SIZE)); + + kalMemCopy((uint8_t *)Buffer, + (uint8_t *)HqaCmdFrame->Data + 4, Len); +#if 0 + for (u4Loop = 0; u4Loop < (Len); u4Loop++) { + + DBGLOG(INIT, INFO, + "QA_AGENT HQA_WriteBulkEEPROM u4Loop=%d u4Value=%x\n", + u4Loop, Buffer[u4Loop]); + } +#endif + if (g_ucEepromCurrentMode == BUFFER_BIN_MODE) { + /* EEPROM */ + DBGLOG(INIT, INFO, + "Direct EEPROM buffer, offset=%x, len=%x\n", + Offset, Len); +#if 0 + for (i = 0; i < EFUSE_BLOCK_SIZE; i++) + memcpy(uacEEPROMImage + Offset + i, Buffer + i, + 1); + +#endif + if (Len > 2) { + for (u4Loop = 0; u4Loop < EFUSE_BLOCK_SIZE/2; + u4Loop++) { + + Buffer[u4Loop] = ntohs(Buffer[u4Loop]); + + uacEEPROMImage[Offset] = + Buffer[u4Loop] & 0xff; + + uacEEPROMImage[Offset + 1] = + Buffer[u4Loop] >> 8 & 0xff; + + Offset += 2; + } + } else { + *Buffer = ntohs(*Buffer); + uacEEPROMImage[Offset] = *Buffer & 0xff; + + uacEEPROMImage[Offset + 1] = + *Buffer >> 8 & 0xff; + } + } else if (g_ucEepromCurrentMode == EFUSE_MODE) { + /* EFUSE */ + /* Read */ + DBGLOG(INIT, INFO, + "QA_AGENT HQA_WriteBulkEEPROM Read\n"); + if (prAdapter->chip_info && + !prAdapter->chip_info->is_support_efuse) { + log_dbg(RFTEST, WARN, "Efuse not support\n"); + rStatus = WLAN_STATUS_NOT_SUPPORTED; + ResponseToQA(HqaCmdFrame, prIwReqData, + 2, rStatus); + kfree(Buffer); + return rStatus; + } + kalMemSet(&rAccessEfuseInfoRead, 0, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + rAccessEfuseInfoRead.u4Address = + (Offset / EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfoRead, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), + TRUE, TRUE, TRUE, &u4BufLen); + + /* Write */ + kalMemSet(&rAccessEfuseInfoWrite, 0, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + + if (Len > 2) { + for (u4Loop = 0; u4Loop < 8 ; u4Loop++) + Buffer[u4Loop] = ntohs(Buffer[u4Loop]); + memcpy(rAccessEfuseInfoWrite.aucData, Buffer, + 16); + } else { + u4Index = Offset % EFUSE_BLOCK_SIZE; + DBGLOG(INIT, INFO, + "MT6632:QA_AGENT HQA_WriteBulkEEPROM Wr,u4Index=%x,Buffer=%x\n", + u4Index, testBuffer); + + *Buffer = ntohs(*Buffer); + DBGLOG(INIT, INFO, + "Buffer[0]=%x, Buffer[0]&0xff=%x\n", + Buffer[0], Buffer[0] & 0xff); + DBGLOG(INIT, INFO, "Buffer[0] >> 8 & 0xff=%x\n" + , Buffer[0] >> 8 & 0xff); + + if (u4Index < EFUSE_BLOCK_SIZE - 1) { + prGlueInfo->prAdapter + ->aucEepromVaule[u4Index] = + *Buffer & 0xff; + prGlueInfo->prAdapter + ->aucEepromVaule[u4Index + 1] = + *Buffer >> 8 & 0xff; + kalMemCopy( + rAccessEfuseInfoWrite.aucData, + prGlueInfo->prAdapter + ->aucEepromVaule, 16); + } else { + DBGLOG(INIT, ERROR, + "u4Index [%d] overrun\n", + u4Index); + goto end; + } + } + + rAccessEfuseInfoWrite.u4Address = + (Offset / EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + for (u4Loop = 0; u4Loop < (EFUSE_BLOCK_SIZE); + u4Loop++) { + DBGLOG(INIT, INFO, " Loop=%d aucData=%x\n", + u4Loop, + rAccessEfuseInfoWrite.aucData[u4Loop]); + } + + DBGLOG(INIT, INFO, "Going for e-Fuse\n"); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseWrite, + &rAccessEfuseInfoWrite, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), + FALSE, TRUE, TRUE, &u4BufLen); + } else { + DBGLOG(INIT, INFO, "Invalid ID!!\n"); + } + + } else { + + if (Len == 2) { + memcpy(&ucTemp2, HqaCmdFrame->Data + 2 * 2, 2); + ucTemp2 = ntohs(ucTemp2); + memcpy(uacEEPROMImage + Offset, &ucTemp2, Len); + } else { + for (i = 0 ; i < 8 ; i++) { + memcpy(&ucTemp2, + HqaCmdFrame->Data + 2 * 2 + 2 * i, 2); + ucTemp2 = ntohs(ucTemp2); + memcpy(uacEEPROMImage + Offset + 2 * i, + &ucTemp2, 2); + } + + if (!g_BufferDownload) { + uint16_t u2InitAddr = Offset; + uint32_t j = 0; + uint32_t u4BufLen = 0; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE + *prSetEfuseBufModeInfo = NULL; + struct BIN_CONTENT *pBinContent; + + prSetEfuseBufModeInfo = + ( + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE *) + kalMemAlloc(sizeof( + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE), + VIR_MEM_TYPE); + if (prSetEfuseBufModeInfo == NULL) + return 0; + kalMemZero(prSetEfuseBufModeInfo, + sizeof( + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE)); + + prGlueInfo = + *((struct GLUE_INFO **) + netdev_priv(prNetDev)); + pBinContent = (struct BIN_CONTENT *) + prSetEfuseBufModeInfo->aBinContent; + + for (j = 0 ; j < 16 ; j++) { + pBinContent->u2Addr = u2InitAddr; + pBinContent->ucValue = + uacEEPROMImage[u2InitAddr]; + + pBinContent++; + } + + prSetEfuseBufModeInfo->ucSourceMode = 1; + prSetEfuseBufModeInfo->ucCount = + EFUSE_CONTENT_SIZE; + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEfusBufferMode, + (void *)prSetEfuseBufModeInfo, sizeof( + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE), + FALSE, FALSE, TRUE, &u4BufLen); + + kalMemFree(prSetEfuseBufModeInfo, VIR_MEM_TYPE, + sizeof( + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE)); + + if (Offset == 0x4A0) + g_BufferDownload = TRUE; + } + } + } + +end: + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + Len, i4Ret); + kfree(Buffer); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_CheckEfuseMode(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t Value = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_CheckEfuseMode\n"); + + /* Value: 0:eeprom mode, 1:eFuse mode */ + Value = ntohl(Value); + memcpy(HqaCmdFrame->Data + 2, &(Value), sizeof(Value)); + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetFreeEfuseBlock(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + + int32_t i4Ret = 0, u4FreeBlockCount = 0; + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + struct PARAM_CUSTOM_EFUSE_FREE_BLOCK rEfuseFreeBlock; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo = NULL; +#endif + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(INIT, INFO, "QA_AGENT HQA_GetFreeEfuseBlock\n"); + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + if (prGlueInfo->prAdapter->fgIsSupportGetFreeEfuseBlockCount + == TRUE) { + kalMemSet(&rEfuseFreeBlock, 0, + sizeof(struct PARAM_CUSTOM_EFUSE_FREE_BLOCK)); + + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryEfuseFreeBlock, + &rEfuseFreeBlock, + sizeof(struct PARAM_CUSTOM_EFUSE_FREE_BLOCK), + TRUE, TRUE, TRUE, &u4BufLen); + + u4FreeBlockCount = prGlueInfo->prAdapter->u4FreeBlockNum; + u4FreeBlockCount = ntohl(u4FreeBlockCount); + kalMemCopy(HqaCmdFrame->Data + 2, &u4FreeBlockCount, 4); + } +#endif + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetEfuseBlockNr(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_GetEfuseBlockNr\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_WriteEFuseFromBuffer(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_WriteEFuseFromBuffer\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetTxPower(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Channel = 0, u4Band = 0, u4Ch_Band = 0, + u4TxTargetPower = 0; + /* UINT_32 u4EfuseAddr = 0, u4Power = 0; */ + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + struct PARAM_CUSTOM_GET_TX_POWER rGetTxPower; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo = NULL; +#endif + + memcpy(&u4Channel, HqaCmdFrame->Data + 4 * 0, 4); + u4Channel = ntohl(u4Channel); + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 1, 4); + u4Band = ntohl(u4Band); + memcpy(&u4Ch_Band, HqaCmdFrame->Data + 4 * 2, 4); + u4Ch_Band = ntohl(u4Ch_Band); + + DBGLOG(RFTEST, INFO, "u4Channel : %u, u4Band : %u, u4Ch_Band : %u\n", + u4Channel, u4Band, u4Ch_Band); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (prGlueInfo->prAdapter->fgIsSupportGetTxPower == TRUE) { + kalMemSet(&rGetTxPower, 0, + sizeof(struct PARAM_CUSTOM_GET_TX_POWER)); + + rGetTxPower.ucCenterChannel = u4Channel; + rGetTxPower.ucBand = u4Ch_Band; + rGetTxPower.ucDbdcIdx = u4Band; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryGetTxPower, + &rGetTxPower, + sizeof(struct PARAM_CUSTOM_GET_TX_POWER), + TRUE, TRUE, TRUE, &u4BufLen); + + u4TxTargetPower = prGlueInfo->prAdapter->u4GetTxPower; + u4TxTargetPower = ntohl(u4TxTargetPower); + kalMemCopy(HqaCmdFrame->Data + 6, &u4TxTargetPower, 4); + } + ResponseToQA(HqaCmdFrame, prIwReqData, 10, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetCfgOnOff(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t Type, Enable, Band; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t u4BufLen = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + memcpy(&Type, HqaCmdFrame->Data + 4 * 0, 4); + Type = ntohl(Type); + memcpy(&Enable, HqaCmdFrame->Data + 4 * 1, 4); + Enable = ntohl(Enable); + memcpy(&Band, HqaCmdFrame->Data + 4 * 2, 4); + Band = ntohl(Band); + + DBGLOG(RFTEST, INFO, "Type : %u, Enable : %u, Band : %u\n", + Type, Enable, Band); + + switch (Type) { + case 0: /* TSSI */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TSSI; + break; + case 1: /* DPD */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_DPD_MODE; + break; + default: + DBGLOG(RFTEST, WARN, "Type [%d] not support\n", Type); + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + return i4Ret; + } + + + + rRfATInfo.u4FuncData = 0; + + if (Enable == 0) + rRfATInfo.u4FuncData &= ~BIT(0); + else + rRfATInfo.u4FuncData |= BIT(0); + + if (Band == 0) + rRfATInfo.u4FuncData &= ~BIT(1); + else + rRfATInfo.u4FuncData |= BIT(1); + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetBufferBin(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t Ret = 0; + uint32_t data = 0; + + kalMemCopy(&data, HqaCmdFrame->Data, sizeof(data)); + data = ntohl(data); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetBufferBin data=%x\n" + , data); + + if (data == BUFFER_BIN_MODE) { + /*Buffer mode*/ + g_ucEepromCurrentMode = BUFFER_BIN_MODE; + } else if (data == EFUSE_MODE) { + /*Efuse mode */ + g_ucEepromCurrentMode = EFUSE_MODE; + } else { + DBGLOG(RFTEST, INFO, "Invalid data!!\n"); + } + + DBGLOG(RFTEST, INFO, "MT6632 : ucEepromCurrentMode=%x\n", + g_ucEepromCurrentMode); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, Ret); + return Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetFreqOffset(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4FreqOffset = 0; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct mt66xx_chip_info *prChipInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + if (!prGlueInfo) { + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + return i4Ret; + } + + if (prGlueInfo->prAdapter) + prChipInfo = prGlueInfo->prAdapter->chip_info; + + /* Mobile chips don't support GetFreqOffset */ + if (prChipInfo && prChipInfo->u4ChipIpVersion + == CONNAC_CHIP_IP_VERSION) { + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + return i4Ret; + } + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_GET_FREQ_OFFSET; + rRfATInfo.u4FuncData = 0; + + i4Ret = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, &rRfATInfo, + sizeof(rRfATInfo), TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Ret == 0) { + u4FreqOffset = rRfATInfo.u4FuncData; + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_GetFreqOffset u4FreqOffset = %d\n", + u4FreqOffset); + + u4FreqOffset = ntohl(u4FreqOffset); + memcpy(HqaCmdFrame->Data + 2, &u4FreqOffset, + sizeof(u4FreqOffset)); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_DBDCTXTone(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + int32_t i4BandIdx = 0, i4Control = 0, i4AntIndex = 0, + i4ToneType = 0, i4ToneFreq = 0; + int32_t i4DcOffsetI = 0, i4DcOffsetQ = 0, i4Band = 0, + i4RF_Power = 0, i4Digi_Power = 0; + + memcpy(&i4BandIdx, HqaCmdFrame->Data + 4 * 0, + 4); /* DBDC Band Index : Band0, Band1 */ + i4BandIdx = ntohl(i4BandIdx); + memcpy(&i4Control, HqaCmdFrame->Data + 4 * 1, + 4); /* Control TX Tone Start and Stop */ + i4Control = ntohl(i4Control); + memcpy(&i4AntIndex, HqaCmdFrame->Data + 4 * 2, + 4); /* Select TX Antenna */ + i4AntIndex = ntohl(i4AntIndex); + memcpy(&i4ToneType, HqaCmdFrame->Data + 4 * 3, + 4); /* ToneType : Single or Two */ + i4ToneType = ntohl(i4ToneType); + memcpy(&i4ToneFreq, HqaCmdFrame->Data + 4 * 4, + 4); /* ToneFreq: DC/5M/10M/20M/40M */ + i4ToneFreq = ntohl(i4ToneFreq); + memcpy(&i4DcOffsetI, HqaCmdFrame->Data + 4 * 5, + 4); /* DC Offset I : -512~1535 */ + i4DcOffsetI = ntohl(i4DcOffsetI); + memcpy(&i4DcOffsetQ, HqaCmdFrame->Data + 4 * 6, + 4); /* DC Offset Q : -512~1535 */ + i4DcOffsetQ = ntohl(i4DcOffsetQ); + memcpy(&i4Band, HqaCmdFrame->Data + 4 * 7, + 4); /* Band : 2.4G/5G */ + i4Band = ntohl(i4Band); + memcpy(&i4RF_Power, HqaCmdFrame->Data + 4 * 8, + 4); /* RF_Power: (1db) 0~15 */ + i4RF_Power = ntohl(i4RF_Power); + memcpy(&i4Digi_Power, HqaCmdFrame->Data + 4 * 9, + 4); /* Digi_Power: (0.25db) -32~31 */ + i4Digi_Power = ntohl(i4Digi_Power); + + DBGLOG(RFTEST, INFO, "BandIdx = 0x%08x\n", i4BandIdx); + DBGLOG(RFTEST, INFO, "Control = 0x%08x\n", i4Control); + DBGLOG(RFTEST, INFO, "AntIndex = 0x%08x\n", i4AntIndex); + DBGLOG(RFTEST, INFO, "ToneType = 0x%08x\n", i4ToneType); + DBGLOG(RFTEST, INFO, "ToneFreq = 0x%08x\n", i4ToneFreq); + DBGLOG(RFTEST, INFO, "DcOffsetI = 0x%08x\n", i4DcOffsetI); + DBGLOG(RFTEST, INFO, "DcOffsetQ = 0x%08x\n", i4DcOffsetQ); + DBGLOG(RFTEST, INFO, "Band = 0x%08x\n", i4Band); + DBGLOG(RFTEST, INFO, "RF_Power = 0x%08x\n", i4RF_Power); + DBGLOG(RFTEST, INFO, "Digi_Power = 0x%08x\n", i4Digi_Power); + + /* + * Select TX Antenna + * RF_Power: (1db) 0~15 + * Digi_Power: (0.25db) -32~31 + */ + MT_ATESetDBDCTxTonePower(prNetDev, i4AntIndex, i4RF_Power, + i4Digi_Power); + + /* DBDC Band Index : Band0, Band1 */ + MT_ATESetDBDCBandIndex(prNetDev, i4BandIdx); + + if (i4Control) { + /* Band : 2.4G/5G */ + MT_ATESetBand(prNetDev, i4Band); + + /* ToneType : Single or Two */ + MT_ATESetTxToneType(prNetDev, i4ToneType); + + /* ToneFreq: DC/5M/10M/20M/40M */ + MT_ATESetTxToneBW(prNetDev, i4ToneFreq); + + /* DC Offset I, DC Offset Q */ + MT_ATESetTxToneDCOffset(prNetDev, i4DcOffsetI, i4DcOffsetQ); + + /* Control TX Tone Start and Stop */ + MT_ATEDBDCTxTone(prNetDev, i4Control); + } else { + /* Control TX Tone Start and Stop */ + MT_ATEDBDCTxTone(prNetDev, i4Control); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_DBDCContinuousTX(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Band = 0, u4Control = 0, u4AntMask = 0, + u4Phymode = 0, u4BW = 0; + uint32_t u4Pri_Ch = 0, u4Rate = 0, u4Central_Ch = 0, + u4TxfdMode = 0, u4Freq = 0; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 0, 4); + u4Band = ntohl(u4Band); + memcpy(&u4Control, HqaCmdFrame->Data + 4 * 1, 4); + u4Control = ntohl(u4Control); + memcpy(&u4AntMask, HqaCmdFrame->Data + 4 * 2, 4); + u4AntMask = ntohl(u4AntMask); + memcpy(&u4Phymode, HqaCmdFrame->Data + 4 * 3, 4); + u4Phymode = ntohl(u4Phymode); + memcpy(&u4BW, HqaCmdFrame->Data + 4 * 4, 4); + u4BW = ntohl(u4BW); + memcpy(&u4Pri_Ch, HqaCmdFrame->Data + 4 * 5, 4); + u4Pri_Ch = ntohl(u4Pri_Ch); + memcpy(&u4Rate, HqaCmdFrame->Data + 4 * 6, 4); + u4Rate = ntohl(u4Rate); + memcpy(&u4Central_Ch, HqaCmdFrame->Data + 4 * 7, 4); + u4Central_Ch = ntohl(u4Central_Ch); + memcpy(&u4TxfdMode, HqaCmdFrame->Data + 4 * 8, 4); + u4TxfdMode = ntohl(u4TxfdMode); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_DBDCContinuousTX u4Band : %d\n", + u4Band); /* ok */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_DBDCContinuousTX u4Control : %d\n", + u4Control); /* ok */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_DBDCContinuousTX u4AntMask : %d\n", + u4AntMask); /* ok */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_DBDCContinuousTX u4Phymode : %d\n", + u4Phymode); /* ok */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_DBDCContinuousTX u4BW : %d\n", u4BW); /* ok */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_DBDCContinuousTX u4Pri_Ch : %d\n", + u4Pri_Ch); /* ok */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_DBDCContinuousTX u4Rate : %d\n", + u4Rate); /* ok */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_DBDCContinuousTX u4Central_Ch : %d\n", + u4Central_Ch); /* ok */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_DBDCContinuousTX u4TxfdMode : %d\n", + u4TxfdMode); /* ok */ + + if (u4Control) { + MT_ATESetDBDCBandIndex(prNetDev, u4Band); + u4Freq = nicChannelNum2Freq(u4Central_Ch); + MT_ATESetChannel(prNetDev, 0, u4Freq); + MT_ATEPrimarySetting(prNetDev, u4Pri_Ch); + + if (u4Phymode == 1) { + u4Phymode = 0; + u4Rate += 4; + } else if ((u4Phymode == 0) && + ((u4Rate == 9) || (u4Rate == 10) || (u4Rate == 11))) + u4Phymode = 1; + MT_ATESetPreamble(prNetDev, u4Phymode); + + if (u4Phymode == 0) { + u4Rate |= 0x00000000; + + DBGLOG(RFTEST, INFO, + "QA_AGENT CCK/OFDM (normal preamble) rate : %d\n", + u4Rate); + + MT_ATESetRate(prNetDev, u4Rate); + } else if (u4Phymode == 1) { + if (u4Rate == 9) + u4Rate = 1; + else if (u4Rate == 10) + u4Rate = 2; + else if (u4Rate == 11) + u4Rate = 3; + u4Rate |= 0x00000000; + + DBGLOG(RFTEST, INFO, + "QA_AGENT CCK (short preamble) rate : %d\n", + u4Rate); + + MT_ATESetRate(prNetDev, u4Rate); + } else if (u4Phymode >= 2 && u4Phymode <= 4) { + u4Rate |= 0x80000000; + + DBGLOG(RFTEST, INFO, "QA_AGENT HT/VHT rate : %d\n", + u4Rate); + + MT_ATESetRate(prNetDev, u4Rate); + } + + MT_ATESetSystemBW(prNetDev, u4BW); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_CW_MODE; + rRfATInfo.u4FuncData = u4TxfdMode; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ANTMASK; + rRfATInfo.u4FuncData = u4AntMask; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_CW; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + } else { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_STOPTEST; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetRXFilterPktLen(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Band = 0, u4Control = 0, u4RxPktlen = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t u4BufLen = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 0, 4); + u4Band = ntohl(u4Band); + memcpy(&u4Control, HqaCmdFrame->Data + 4 * 1, 4); + u4Control = ntohl(u4Control); + memcpy(&u4RxPktlen, HqaCmdFrame->Data + 4 * 2, 4); + u4RxPktlen = ntohl(u4RxPktlen); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetRXFilterPktLen Band : %d\n", u4Band); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetRXFilterPktLen Control : %d\n", u4Control); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetRXFilterPktLen RxPktlen : %d\n", + u4RxPktlen); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_RX_FILTER_PKT_LEN; + rRfATInfo.u4FuncData = (uint32_t) (u4RxPktlen & BITS(0, + 23)); + rRfATInfo.u4FuncData |= (uint32_t) (u4Band << 24); + + if (u4Control == 1) + rRfATInfo.u4FuncData |= BIT(30); + else + rRfATInfo.u4FuncData &= ~BIT(30); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetRXFilterPktLen rRfATInfo.u4FuncData : 0x%08x\n", + rRfATInfo.u4FuncData); + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetTXInfo(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + uint32_t u4Txed_band0 = 0; + uint32_t u4Txed_band1 = 0; + int32_t i4Status; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_GetTXInfo\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_TXED_COUNT; + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, &rRfATInfo, + sizeof(rRfATInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + u4Txed_band0 = rRfATInfo.u4FuncData; + + DBGLOG(RFTEST, INFO, + "QA_AGENT u4Txed_band0 packet count = %d\n", + u4Txed_band0); + + u4Txed_band0 = ntohl(u4Txed_band0); + memcpy(HqaCmdFrame->Data + 2, &u4Txed_band0, + sizeof(u4Txed_band0)); + } + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_TXED_COUNT; + rRfATInfo.u4FuncIndex |= BIT(8); + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, &rRfATInfo, + sizeof(rRfATInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + u4Txed_band1 = rRfATInfo.u4FuncData; + + DBGLOG(RFTEST, INFO, + "QA_AGENT u4Txed_band1 packet count = %d\n", + u4Txed_band1); + + u4Txed_band1 = ntohl(u4Txed_band1); + memcpy(HqaCmdFrame->Data + 2 + 4, &u4Txed_band1, + sizeof(u4Txed_band1)); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, + 2 + sizeof(u4Txed_band0) + sizeof(u4Txed_band1), i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetCfgOnOff(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_GetCfgOnOff\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_CMD_SET3[] = { + /* cmd id start from 0x1300 */ + HQA_MacBbpRegRead, /* 0x1300 */ + HQA_MacBbpRegWrite, /* 0x1301 */ + HQA_MACBbpRegBulkRead, /* 0x1302 */ + HQA_RfRegBulkRead, /* 0x1303 */ + HQA_RfRegBulkWrite, /* 0x1304 */ + HQA_ReadEEPROM, /* 0x1305 */ + HQA_WriteEEPROM, /* 0x1306 */ + HQA_ReadBulkEEPROM, /* 0x1307 */ + HQA_WriteBulkEEPROM, /* 0x1308 */ + HQA_CheckEfuseMode, /* 0x1309 */ + HQA_GetFreeEfuseBlock, /* 0x130A */ + HQA_GetEfuseBlockNr, /* 0x130B */ + HQA_WriteEFuseFromBuffer, /* 0x130C */ + HQA_GetTxPower, /* 0x130D */ + HQA_SetCfgOnOff, /* 0x130E */ + HQA_GetFreqOffset, /* 0x130F */ + HQA_DBDCTXTone, /* 0x1310 */ + HQA_DBDCContinuousTX, /* 0x1311 */ + HQA_SetRXFilterPktLen, /* 0x1312 */ + HQA_GetTXInfo, /* 0x1313 */ + HQA_GetCfgOnOff, /* 0x1314 */ + NULL, /* 0x1315 */ + HQA_SetBufferBin, /* 0x1316 */ +}; + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_ReadTempReferenceValue( + struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_ReadTempReferenceValue\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Get Thermal Value. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetThermalValue(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + uint32_t u4Value; + uint32_t u4BufLen = 0; + int32_t i4Status; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_TEMP_SENSOR; + rRfATInfo.u4FuncData = 0; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, &rRfATInfo, + sizeof(rRfATInfo), TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + u4Value = rRfATInfo.u4FuncData; + u4Value = u4Value >> 16; + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_GetThermalValue Value = %d\n", u4Value); + + u4Value = ntohl(u4Value); + memcpy(HqaCmdFrame->Data + 2, &u4Value, 4); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetSideBandOption(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetSideBandOption\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_CMD_SET4[] = { + /* cmd id start from 0x1400 */ + HQA_ReadTempReferenceValue, /* 0x1400 */ + HQA_GetThermalValue, /* 0x1401 */ + HQA_SetSideBandOption, /* 0x1402 */ +}; + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetFWInfo(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_GetFWInfo\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_StartContinousTx(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StartContinousTx\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetSTBC(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetSTBC\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Set short GI. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetShortGI(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4ShortGi; + + memcpy(&u4ShortGi, HqaCmdFrame->Data, 4); + u4ShortGi = ntohl(u4ShortGi); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetShortGI u4ShortGi = %d\n", u4ShortGi); + + i4Ret = MT_ATESetTxGi(prNetDev, u4ShortGi); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetDPD(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetDPD\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Get Rx Statistics. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetRxStatisticsAll(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4BufLen = 0; + struct PARAM_CUSTOM_ACCESS_RX_STAT rRxStatisticsTest; + + /* memset(&g_HqaRxStat, 0, sizeof(PARAM_RX_STAT_T)); */ + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_GetRxStatisticsAll\n"); + + rRxStatisticsTest.u4SeqNum = u4RxStatSeqNum; + rRxStatisticsTest.u4TotalNum = HQA_RX_STATISTIC_NUM + 6; + + i4Ret = kalIoctl(prGlueInfo, + wlanoidQueryRxStatistics, + &rRxStatisticsTest, sizeof(rRxStatisticsTest), + TRUE, TRUE, TRUE, &u4BufLen); + + /* ASSERT(rRxStatisticsTest.u4SeqNum == u4RxStatSeqNum); */ + + u4RxStatSeqNum++; + + memcpy(HqaCmdFrame->Data + 2, &(g_HqaRxStat), + sizeof(struct PARAM_RX_STAT)); + ResponseToQA(HqaCmdFrame, prIwReqData, + (2 + sizeof(struct PARAM_RX_STAT)), i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_StartContiTxTone(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StartContiTxTone\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_StopContiTxTone(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StopContiTxTone\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_CalibrationTestMode(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Mode = 0; + uint32_t u4IcapLen = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_CalibrationTestMode\n"); + + memcpy(&u4Mode, HqaCmdFrame->Data + 4 * 0, 4); + u4Mode = ntohl(u4Mode); + memcpy(&u4IcapLen, HqaCmdFrame->Data + 4 * 1, 4); + u4IcapLen = ntohl(u4IcapLen); + + if (u4Mode == 2) + i4Ret = MT_ICAPStart(prNetDev, "ICAPSTART"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_DoCalibrationTestItem(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Status = 0; + uint32_t u4Item = 0; + uint32_t u4Band_idx = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + struct ADAPTER *prAdapter; + uint32_t u4BufLen = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + memcpy(&u4Item, HqaCmdFrame->Data, 4); + u4Item = ntohl(u4Item); + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_DoCalibrationTestItem item : 0x%08x\n", + u4Item); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_DoCalibrationTestItem band_idx : %d\n", + u4Band_idx); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_RECAL_CAL_STEP; + rRfATInfo.u4FuncData = u4Item; + + kalMemSet((void *)&prAdapter->rReCalInfo, + 0, + sizeof(struct RECAL_INFO_T)); + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_eFusePhysicalWrite(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_eFusePhysicalWrite\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_eFusePhysicalRead(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_eFusePhysicalRead\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_eFuseLogicalRead(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_eFuseLogicalRead\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_eFuseLogicalWrite(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_eFuseLogicalWrite\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_TMRSetting(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Setting; + uint32_t u4Version; + uint32_t u4MPThres; + uint32_t u4MPIter; + + memcpy(&u4Setting, HqaCmdFrame->Data + 4 * 0, 4); + u4Setting = ntohl(u4Setting); + memcpy(&u4Version, HqaCmdFrame->Data + 4 * 1, 4); + u4Version = ntohl(u4Version); + memcpy(&u4MPThres, HqaCmdFrame->Data + 4 * 2, 4); + u4MPThres = ntohl(u4MPThres); + memcpy(&u4MPIter, HqaCmdFrame->Data + 4 * 3, 4); + u4MPIter = ntohl(u4MPIter); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_TMRSetting u4Setting : %d\n", u4Setting); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_TMRSetting u4Version : %d\n", u4Version); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_TMRSetting u4MPThres : %d\n", u4MPThres); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_TMRSetting u4MPIter : %d\n", u4MPIter); + + i4Ret = MT_ATE_TMRSetting(prNetDev, u4Setting, u4Version, + u4MPThres, u4MPIter); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetRxSNR(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_GetRxSNR\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_WriteBufferDone(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t Value; + /* UINT_32 i = 0, j = 0; + * UINT_32 u4BufLen = 0; + */ + int32_t rStatus = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo = NULL; + /* PARAM_CUSTOM_EFUSE_BUFFER_MODE_T rSetEfuseBufModeInfo; */ + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE_CONNAC_T *prSetEfuseBufModeInfo + = NULL; + + uint8_t *pucConfigBuf = NULL; + uint32_t u4ContentLen; + uint32_t u4BufLen = 0; + struct ADAPTER *prAdapter = NULL; + + + prGlueInfo = *((struct GLUE_INFO **)netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + + memcpy(&Value, HqaCmdFrame->Data + 4 * 0, 4); + Value = ntohl(Value); + + u4EepromMode = Value; + + /* allocate memory for buffer mode info */ + prSetEfuseBufModeInfo = + (struct PARAM_CUSTOM_EFUSE_BUFFER_MODE_CONNAC_T *) + kalMemAlloc(sizeof( + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE_CONNAC_T), + VIR_MEM_TYPE); + + if (prSetEfuseBufModeInfo == NULL) + goto label_exit; + + kalMemZero(prSetEfuseBufModeInfo, + sizeof(struct PARAM_CUSTOM_EFUSE_BUFFER_MODE_CONNAC_T)); + + /* copy to the command buffer */ + u4ContentLen = prAdapter->rBufferModeInfo.u2EfuseTotalSize; + if (u4ContentLen > MAX_EEPROM_BUFFER_SIZE) + goto label_exit; + + kalMemCopy(prSetEfuseBufModeInfo->aBinContent, + &uacEEPROMImage[0], u4ContentLen); + + prSetEfuseBufModeInfo->ucSourceMode = Value; + + prSetEfuseBufModeInfo->ucContentFormat = CONTENT_FORMAT_WHOLE_CONTENT | + (prAdapter->rWifiVar.ucCalTimingCtrl << 4); + + + prSetEfuseBufModeInfo->u2Count = u4ContentLen; + + rStatus = kalIoctl(prGlueInfo, + wlanoidConnacSetEfusBufferMode, + (void *)prSetEfuseBufModeInfo, + sizeof(struct PARAM_CUSTOM_EFUSE_BUFFER_MODE_CONNAC_T), + FALSE, TRUE, TRUE, &u4BufLen); + +#if 0 + + for (i = 0; i < MAX_EEPROM_BUFFER_SIZE / 16; i++) { + for (j = 0; j < 16; j++) { + rSetEfuseBufModeInfo.aBinContent[j].u2Addr = u2InitAddr; + rSetEfuseBufModeInfo.aBinContent[j].ucValue = + uacEEPROMImage[u2InitAddr]; + DBGLOG(RFTEST, INFO, "u2Addr = %x\n", + rSetEfuseBufModeInfo.aBinContent[j].u2Addr); + DBGLOG(RFTEST, INFO, "ucValue = %x\n", + rSetEfuseBufModeInfo.aBinContent[j].ucValue); + u2InitAddr += 1; + } + + rSetEfuseBufModeInfo.ucSourceMode = 1; + rSetEfuseBufModeInfo.ucCount = EFUSE_CONTENT_SIZE; + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEfusBufferMode, + &rSetEfuseBufModeInfo, + sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T), + FALSE, FALSE, TRUE, &u4BufLen); + } + +#endif + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + +label_exit: + + /* free memory */ + if (prSetEfuseBufModeInfo != NULL) + kalMemFree(prSetEfuseBufModeInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_CUSTOM_EFUSE_BUFFER_MODE_CONNAC_T)); + + if (pucConfigBuf != NULL) + kalMemFree(pucConfigBuf, VIR_MEM_TYPE, MAX_EEPROM_BUFFER_SIZE); + + return i4Ret; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_FFT(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_FFT\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetTxTonePower(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetTxTonePower\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetChipID(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4ChipId; + struct mt66xx_chip_info *prChipInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + /* UINT_32 u4BufLen = 0; + * PARAM_CUSTOM_MCR_RW_STRUCT_T rMcrInfo; + */ + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + prChipInfo = prAdapter->chip_info; + g_u4Chip_ID = prChipInfo->chip_id; + if (prChipInfo->u4ChipIpVersion == CONNAC_CHIP_IP_VERSION) + u4ChipId = 0x00066310; + else + u4ChipId = g_u4Chip_ID; + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_GetChipID ChipId = 0x%08x\n", u4ChipId); + + u4ChipId = ntohl(u4ChipId); + memcpy(HqaCmdFrame->Data + 2, &u4ChipId, 4); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_MPSSetSeqData(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t *mps_setting = NULL; + uint32_t u4Band_idx = 0; + uint32_t u4Offset = 0; + uint32_t u4Len = 0; + uint32_t i = 0; + uint32_t u4Value = 0; + uint32_t u4Mode = 0; + uint32_t u4TxPath = 0; + uint32_t u4Mcs = 0; + + u4Len = ntohs(HqaCmdFrame->Length) / sizeof(uint32_t) - 1; + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetSeqData u4Len : %d\n", u4Len); + + mps_setting = kmalloc(sizeof(uint32_t) * (u4Len), + GFP_KERNEL); + ASSERT(mps_setting); + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetSeqData u4Band_idx : %d\n", u4Band_idx); + + for (i = 0 ; i < u4Len ; i++) { + u4Offset = 4 + 4 * i; + /* Reserved at least 4 byte availbale data */ + if (u4Offset + 4 > sizeof(HqaCmdFrame->Data)) + break; + memcpy(&u4Value, HqaCmdFrame->Data + 4 + 4 * i, 4); + u4Value = ntohl(u4Value); + + u4Mode = (u4Value & BITS(24, 27)) >> 24; + u4TxPath = (u4Value & BITS(8, 23)) >> 8; + u4Mcs = (u4Value & BITS(0, 7)); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetSeqData mps_setting Case %d (Mode : %d / TX Path : %d / MCS : %d)\n" + , i, u4Mode, u4TxPath, u4Mcs); + + if (u4Mode == 1) { + u4Mode = 0; + u4Mcs += 4; + } else if ((u4Mode == 0) && ((u4Mcs == 9) || (u4Mcs == 10) + || (u4Mcs == 11))) + u4Mode = 1; + + if (u4Mode == 0) { + u4Mcs |= 0x00000000; + + DBGLOG(RFTEST, INFO, + "QA_AGENT CCK/OFDM (normal preamble) rate : %d\n", + u4Mcs); + } else if (u4Mode == 1) { + if (u4Mcs == 9) + u4Mcs = 1; + else if (u4Mcs == 10) + u4Mcs = 2; + else if (u4Mcs == 11) + u4Mcs = 3; + u4Mcs |= 0x00000000; + + DBGLOG(RFTEST, INFO, + "QA_AGENT CCK (short preamble) rate : %d\n", + u4Mcs); + } else if (u4Mode >= 2 && u4Mode <= 4) { + u4Mcs |= 0x80000000; + + DBGLOG(RFTEST, INFO, "QA_AGENT HT/VHT rate : %d\n", + u4Mcs); + } + + mps_setting[i] = (u4Mcs) | (u4TxPath << 8) | (u4Mode << 24); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetSeqData mps_setting Case %d (Mode : %d / TX Path : %d / MCS : %d)\n", + i, + (int)((mps_setting[i] & BITS(24, 27)) >> 24), + (int)((mps_setting[i] & BITS(8, 23)) >> 8), + (int)((mps_setting[i] & BITS(0, 7)))); + + } + + i4Ret = MT_ATEMPSSetSeqData(prNetDev, u4Len, mps_setting, + u4Band_idx); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(mps_setting); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_MPSSetPayloadLength(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t *mps_setting = NULL; + uint32_t u4Band_idx = 0; + uint32_t u4Offset = 0; + uint32_t u4Len = 0; + uint32_t i = 0; + uint32_t u4Value = 0; + + u4Len = ntohs(HqaCmdFrame->Length) / sizeof(uint32_t) - 1; + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetPayloadLength u4Len : %d\n", u4Len); + + mps_setting = kmalloc(sizeof(uint32_t) * (u4Len), + GFP_KERNEL); + ASSERT(mps_setting); + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetPayloadLength u4Band_idx : %d\n", + u4Band_idx); + + for (i = 0 ; i < u4Len ; i++) { + u4Offset = 4 + 4 * i; + /* Reserved at least 4 byte availbale data */ + if (u4Offset + 4 > sizeof(HqaCmdFrame->Data)) + break; + memcpy(&u4Value, HqaCmdFrame->Data + 4 + 4 * i, 4); + mps_setting[i] = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetPayloadLength mps_setting Case %d (Payload Length : %d)\n", + i, mps_setting[i]); + } + + i4Ret = MT_ATEMPSSetPayloadLength(prNetDev, u4Len, + mps_setting, u4Band_idx); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(mps_setting); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_MPSSetPacketCount(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t *mps_setting = NULL; + uint32_t u4Band_idx = 0; + uint32_t u4Offset = 0; + uint32_t u4Len = 0; + uint32_t i = 0; + uint32_t u4Value = 0; + + u4Len = ntohs(HqaCmdFrame->Length) / sizeof(uint32_t) - 1; + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetPacketCount u4Len : %d\n", u4Len); + + mps_setting = kmalloc(sizeof(uint32_t) * (u4Len), + GFP_KERNEL); + ASSERT(mps_setting); + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetPacketCount u4Band_idx : %d\n", + u4Band_idx); + + for (i = 0 ; i < u4Len ; i++) { + u4Offset = 4 + 4 * i; + /* Reserved at least 4 byte availbale data */ + if (u4Offset + 4 > sizeof(HqaCmdFrame->Data)) + break; + memcpy(&u4Value, HqaCmdFrame->Data + 4 + 4 * i, 4); + mps_setting[i] = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetPacketCount mps_setting Case %d (Packet Count : %d)\n", + i, mps_setting[i]); + } + + i4Ret = MT_ATEMPSSetPacketCount(prNetDev, u4Len, + mps_setting, u4Band_idx); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(mps_setting); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_MPSSetPowerGain(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t *mps_setting = NULL; + uint32_t u4Band_idx = 0; + uint32_t u4Offset = 0; + uint32_t u4Len = 0; + uint32_t i = 0; + uint32_t u4Value = 0; + + u4Len = ntohs(HqaCmdFrame->Length) / sizeof(uint32_t) - 1; + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetPowerGain u4Len : %d\n", u4Len); + + mps_setting = kmalloc(sizeof(uint32_t) * (u4Len), + GFP_KERNEL); + ASSERT(mps_setting); + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetPowerGain u4Band_idx : %d\n", + u4Band_idx); + + for (i = 0 ; i < u4Len ; i++) { + u4Offset = 4 + 4 * i; + /* Reserved at least 4 byte availbale data */ + if (u4Offset + 4 > sizeof(HqaCmdFrame->Data)) + break; + memcpy(&u4Value, HqaCmdFrame->Data + 4 + 4 * i, 4); + mps_setting[i] = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetPowerGain mps_setting Case %d (Power : %d)\n", + i, mps_setting[i]); + } + + i4Ret = MT_ATEMPSSetPowerGain(prNetDev, u4Len, mps_setting, + u4Band_idx); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(mps_setting); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_MPSStart(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Band_idx = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MPSStart\n"); + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + MT_ATEStartTX(prNetDev, "TXFRAME"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_MPSStop(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Band_idx = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MPSStop\n"); + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + /* To Do : MPS Stop for Specific Band. */ + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_MPSSetNss(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t *mps_setting = NULL; + uint32_t u4Band_idx = 0; + uint32_t u4Offset = 0; + uint32_t u4Len = 0; + uint32_t i = 0; + uint32_t u4Value = 0; + + u4Len = ntohs(HqaCmdFrame->Length) / sizeof(uint32_t) - 1; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MPSSetNss u4Len : %d\n", + u4Len); + + mps_setting = kmalloc(sizeof(uint32_t) * (u4Len), + GFP_KERNEL); + ASSERT(mps_setting); + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetNss u4Band_idx : %d\n", u4Band_idx); + + for (i = 0; i < u4Len; i++) { + u4Offset = 4 + 4 * i; + /* Reserved at least 4 byte availbale data */ + if (u4Offset + 4 > sizeof(HqaCmdFrame->Data)) + break; + memcpy(&u4Value, HqaCmdFrame->Data + 4 + 4 * i, 4); + mps_setting[i] = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetNss mps_setting Case %d (Nss : %d)\n", + i, mps_setting[i]); + } + + i4Ret = MT_ATEMPSSetNss(prNetDev, u4Len, mps_setting, + u4Band_idx); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(mps_setting); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_MPSSetPerpacketBW( + struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t *mps_setting = NULL; + uint32_t u4Band_idx = 0; + uint32_t u4Offset = 0; + uint32_t u4Len = 0; + uint32_t i = 0; + uint32_t u4Value = 0; + + u4Len = ntohs(HqaCmdFrame->Length) / sizeof(uint32_t) - 1; + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetPerpacketBW u4Len : %d\n", u4Len); + + mps_setting = kmalloc(sizeof(uint32_t) * (u4Len), + GFP_KERNEL); + ASSERT(mps_setting); + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetPerpacketBW u4Band_idx : %d\n", + u4Band_idx); + + for (i = 0 ; i < u4Len ; i++) { + u4Offset = 4 + 4 * i; + /* Reserved at least 4 byte availbale data */ + if (u4Offset + 4 > sizeof(HqaCmdFrame->Data)) + break; + memcpy(&u4Value, HqaCmdFrame->Data + 4 + 4 * i, 4); + mps_setting[i] = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MPSSetPerpacketBW mps_setting Case %d (BW : %d)\n", + i, mps_setting[i]); + } + + i4Ret = MT_ATEMPSSetPerpacketBW(prNetDev, u4Len, + mps_setting, u4Band_idx); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(mps_setting); + + return i4Ret; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetAIFS(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t SlotTime = 0; + uint32_t SifsTime = 0; + + memcpy(&SlotTime, HqaCmdFrame->Data + 4 * 0, 4); + SlotTime = ntohl(SlotTime); + memcpy(&SifsTime, HqaCmdFrame->Data + 4 * 1, 4); + SifsTime = ntohl(SifsTime); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetAIFS SlotTime = %d\n", + SlotTime); + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_SetAIFS SifsTime = %d\n", + SifsTime); + + i4Ret = MT_ATESetTxIPG(prNetDev, SifsTime); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_CheckEfuseModeType(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t Value = u4EepromMode; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_CheckEfuseModeType\n"); + + /* + * Value: + * 1 -> efuse Mode + * 2 -> flash Mode + * 3 -> eeprom Mode + * 4 -> bin Mode + */ + Value = ntohl(Value); + memcpy(HqaCmdFrame->Data + 2, &(Value), sizeof(Value)); + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_CheckEfuseNativeModeType( + struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_CheckEfuseNativeModeType\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_SetBandMode(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Band_mode = 0; + uint32_t u4Band_type = 0; + + memcpy((uint8_t *)&u4Band_mode, HqaCmdFrame->Data + 4 * 0, + 4); + u4Band_mode = ntohl(u4Band_mode); + memcpy((uint8_t *)&u4Band_type, HqaCmdFrame->Data + 4 * 1, + 4); + u4Band_type = ntohl(u4Band_type); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetBandMode u4Band_mode : %d\n", u4Band_mode); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_SetBandMode u4Band_type : %d\n", u4Band_type); + + if (u4Band_mode == 2) + g_DBDCEnable = TRUE; + else if (u4Band_mode == 1) + g_DBDCEnable = FALSE; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_GetBandMode(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Band_mode = 0; + uint32_t u4Band_idx = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t u4BufLen = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + memcpy((uint8_t *)&u4Band_idx, HqaCmdFrame->Data, 4); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_GetBandMode u4Band_idx : %d\n", u4Band_idx); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_DBDC_ENABLE; + if (g_DBDCEnable) + rRfATInfo.u4FuncData = 1; + else + rRfATInfo.u4FuncData = 0; + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_GetBandMode g_DBDCEnable = %d\n", + g_DBDCEnable); + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + + if (u4Band_idx == 0) { + u4Band_mode = 3; + } else { + if (g_DBDCEnable) + u4Band_mode = 3; + else + u4Band_mode = 0; + } + + u4Band_mode = ntohl(u4Band_mode); + + memcpy(HqaCmdFrame->Data + 2, &(u4Band_mode), + sizeof(u4Band_mode)); + + ResponseToQA(HqaCmdFrame, prIwReqData, + 2 + sizeof(u4Band_mode), i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_RDDStartExt(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_RDDStartExt\n"); + + DBGLOG(RFTEST, INFO, "[RDD DUMP START]\n"); + + i4Ret = MT_ATERDDStart(prNetDev, "RDDSTART"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_RDDStopExt(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_RDDStopExt\n"); + + i4Ret = MT_ATERDDStop(prNetDev, "RDDSTOP"); + + DBGLOG(RFTEST, INFO, "[RDD DUMP END]\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_BssInfoUpdate(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t OwnMacIdx = 0, BssIdx = 0; + uint8_t ucAddr1[MAC_ADDR_LEN]; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + memcpy(&OwnMacIdx, HqaCmdFrame->Data + 4 * 0, 4); + OwnMacIdx = ntohl(OwnMacIdx); + memcpy(&BssIdx, HqaCmdFrame->Data + 4 * 1, 4); + BssIdx = ntohl(BssIdx); + memcpy(ucAddr1, HqaCmdFrame->Data + 4 * 2, 6); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_BssInfoUpdate OwnMacIdx : %d\n", OwnMacIdx); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_BssInfoUpdate BssIdx : %d\n", BssIdx); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_BssInfoUpdate addr1:%02x:%02x:%02x:%02x:%02x:%02x\n", + ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], ucAddr1[4], + ucAddr1[5]); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSnprintf(prInBuf, sizeof(uint8_t) * (HQA_BF_STR_SIZE), + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + OwnMacIdx, BssIdx, ucAddr1[0], ucAddr1[1], ucAddr1[2], + ucAddr1[3], ucAddr1[4], ucAddr1[5]); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_BssInfoUpdate(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_DevInfoUpdate(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t Band = 0, OwnMacIdx = 0; + uint8_t ucAddr1[MAC_ADDR_LEN]; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + memcpy(&Band, HqaCmdFrame->Data + 4 * 0, 4); + Band = ntohl(Band); + memcpy(&OwnMacIdx, HqaCmdFrame->Data + 4 * 1, 4); + OwnMacIdx = ntohl(OwnMacIdx); + memcpy(ucAddr1, HqaCmdFrame->Data + 4 * 2, 6); + + DBGLOG(RFTEST, INFO, "Band : %d, OwnMacIdx : %d\n", Band, OwnMacIdx); + DBGLOG(RFTEST, INFO, "addr1:%02x:%02x:%02x:%02x:%02x:%02x\n", + ucAddr1[0], ucAddr1[1], ucAddr1[2], + ucAddr1[3], ucAddr1[4], ucAddr1[5]); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSnprintf(prInBuf, sizeof(uint8_t) * (HQA_BF_STR_SIZE), + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + OwnMacIdx, ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], + ucAddr1[4], ucAddr1[5], Band); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_DevInfoUpdate(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_LogOnOff(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Band_idx = 0; + uint32_t u4Log_type = 0; + uint32_t u4Log_ctrl = 0; + uint32_t u4Log_size = 200; + + memcpy(&u4Band_idx, HqaCmdFrame->Data, 4); + u4Band_idx = ntohl(u4Band_idx); + memcpy(&u4Log_type, HqaCmdFrame->Data + 4, 4); + u4Log_type = ntohl(u4Log_type); + memcpy(&u4Log_ctrl, HqaCmdFrame->Data + 4 + 4, 4); + u4Log_ctrl = ntohl(u4Log_ctrl); + memcpy(&u4Log_size, HqaCmdFrame->Data + 4 + 4 + 4, 4); + u4Log_size = ntohl(u4Log_size); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_LogOnOff band_idx : %d\n", u4Band_idx); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_LogOnOff log_type : %d\n", u4Log_type); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_LogOnOff log_ctrl : %d\n", u4Log_ctrl); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_LogOnOff log_size : %d\n", u4Log_size); + + i4Ret = MT_ATELogOnOff(prNetDev, u4Log_type, u4Log_ctrl, + u4Log_size); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + + +static int32_t HQA_GetDumpRecal(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct RECAL_INFO_T *prReCalInfo = NULL; + struct RECAL_DATA_T *prCalArray = NULL; + uint32_t i = 0, u4Value = 0, u4RespLen = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + prReCalInfo = &prAdapter->rReCalInfo; + prCalArray = prReCalInfo->prCalArray; + + DBGLOG(RFTEST, INFO, "prReCalInfo->u4Count = [%d]\n", + prReCalInfo->u4Count); + if (prReCalInfo->u4Count > 0) { + for (i = 0; i < prReCalInfo->u4Count; i++) { + u4Value = ntohl(prCalArray[i].u4CalId); + kalMemCopy(HqaCmdFrame->Data + 6 + u4RespLen, + &u4Value, + sizeof(u4Value)); + u4RespLen += sizeof(u4Value); + + u4Value = ntohl(prCalArray[i].u4CalAddr); + DBGLOG(RFTEST, INFO, "CalAddr[%d] = [0x%08x]\n", + i, prCalArray[i].u4CalAddr); + kalMemCopy(HqaCmdFrame->Data + 6 + u4RespLen, + &u4Value, + sizeof(u4Value)); + u4RespLen += sizeof(u4Value); + + u4Value = ntohl(prCalArray[i].u4CalValue); + kalMemCopy(HqaCmdFrame->Data + 6 + u4RespLen, + &u4Value, + sizeof(u4Value)); + u4RespLen += sizeof(u4Value); + } + + u4Value = ntohl(prReCalInfo->u4Count); + kalMemCopy(HqaCmdFrame->Data + 2, &u4Value, sizeof(u4Value)); + ResponseToQA(HqaCmdFrame, + prIwReqData, + 6 + prReCalInfo->u4Count * 12, + 0); + } else { + kalMemCopy(HqaCmdFrame->Data + 2, &prReCalInfo->u4Count, 4); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, 0); + } + + /* free resources */ + if (prReCalInfo->prCalArray != NULL) { + kalMemFree(prReCalInfo->prCalArray, + VIR_MEM_TYPE, + 2048 * sizeof(struct RECAL_DATA_T)); + prReCalInfo->prCalArray = 0; + prReCalInfo->u4Count = 0; + } + + return 0; +} + +static int32_t HQA_GetDumpRXV(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Count = 0, i4Ret = 0; + + i4Ret = MT_ATEGetDumpRXV(prNetDev, HqaCmdFrame->Data, &i4Count); + ResponseToQA(HqaCmdFrame, prIwReqData, 6 + i4Count, i4Ret); + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_ReCal_CMDS[] = { + HQA_GetDumpRecal, /*0x1581 */ +}; + +static HQA_CMD_HANDLER HQA_RXV_CMDS[] = { + HQA_GetDumpRXV, /* 0x1581 */ +}; + + +static HQA_CMD_HANDLER HQA_CMD_SET5[] = { + /* cmd id start from 0x1500 */ + HQA_GetFWInfo, /* 0x1500 */ + HQA_StartContinousTx, /* 0x1501 */ + HQA_SetSTBC, /* 0x1502 */ + HQA_SetShortGI, /* 0x1503 */ + HQA_SetDPD, /* 0x1504 */ + HQA_SetTssiOnOff, /* 0x1505 */ + HQA_GetRxStatisticsAll, /* 0x1506 */ + HQA_StartContiTxTone, /* 0x1507 */ + HQA_StopContiTxTone, /* 0x1508 */ + HQA_CalibrationTestMode, /* 0x1509 */ + HQA_DoCalibrationTestItem, /* 0x150A */ + HQA_eFusePhysicalWrite, /* 0x150B */ + HQA_eFusePhysicalRead, /* 0x150C */ + HQA_eFuseLogicalRead, /* 0x150D */ + HQA_eFuseLogicalWrite, /* 0x150E */ + HQA_TMRSetting, /* 0x150F */ + HQA_GetRxSNR, /* 0x1510 */ + HQA_WriteBufferDone, /* 0x1511 */ + HQA_FFT, /* 0x1512 */ + HQA_SetTxTonePower, /* 0x1513 */ + HQA_GetChipID, /* 0x1514 */ + HQA_MPSSetSeqData, /* 0x1515 */ + HQA_MPSSetPayloadLength, /* 0x1516 */ + HQA_MPSSetPacketCount, /* 0x1517 */ + HQA_MPSSetPowerGain, /* 0x1518 */ + HQA_MPSStart, /* 0x1519 */ + HQA_MPSStop, /* 0x151A */ + ToDoFunction, /* 0x151B */ + ToDoFunction, /* 0x151C */ + ToDoFunction, /* 0x151D */ + ToDoFunction, /* 0x151E */ + ToDoFunction, /* 0x151F */ + ToDoFunction, /* 0x1520 */ + HQA_SetAIFS, /* 0x1521 */ + HQA_CheckEfuseModeType, /* 0x1522 */ + HQA_CheckEfuseNativeModeType, /* 0x1523 */ + ToDoFunction, /* 0x1524 */ + ToDoFunction, /* 0x1525 */ + ToDoFunction, /* 0x1526 */ + ToDoFunction, /* 0x1527 */ + ToDoFunction, /* 0x1528 */ + ToDoFunction, /* 0x1529 */ + ToDoFunction, /* 0x152A */ + ToDoFunction, /* 0x152B */ + HQA_SetBandMode, /* 0x152C */ + HQA_GetBandMode, /* 0x152D */ + HQA_RDDStartExt, /* 0x152E */ + HQA_RDDStopExt, /* 0x152F */ + ToDoFunction, /* 0x1530 */ + HQA_BssInfoUpdate, /* 0x1531 */ + HQA_DevInfoUpdate, /* 0x1532 */ + HQA_LogOnOff, /* 0x1533 */ + ToDoFunction, /* 0x1534 */ + ToDoFunction, /* 0x1535 */ + HQA_MPSSetNss, /* 0x1536 */ + HQA_MPSSetPerpacketBW, /* 0x1537 */ +}; + +#if CFG_SUPPORT_TX_BF +static int32_t HQA_TxBfProfileTagInValid(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t invalid = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(invalid), GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_TxBfProfileTagInValid\n"); + + memcpy(&invalid, HqaCmdFrame->Data, 4); + invalid = ntohl(invalid); + + kalMemSet(prInBuf, 0, sizeof(invalid)); + kalSnprintf(prInBuf, sizeof(invalid), "%u", invalid); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_InValid(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagPfmuIdx(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t pfmuidx = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(pfmuidx), GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_TxBfProfileTagPfmuIdx\n"); + + memcpy(&pfmuidx, HqaCmdFrame->Data, 4); + pfmuidx = ntohl(pfmuidx); + + kalMemSet(prInBuf, 0, sizeof(pfmuidx)); + kalSnprintf(prInBuf, sizeof(pfmuidx), "%u", pfmuidx); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_PfmuIdx(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagBfType(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t bftype = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(bftype), GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_TxBfProfileTagBfType\n"); + + memcpy(&bftype, HqaCmdFrame->Data, 4); + bftype = ntohl(bftype); + + kalMemSet(prInBuf, 0, sizeof(bftype)); + kalSnprintf(prInBuf, sizeof(bftype), "%u", bftype); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_BfType(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagBw(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t tag_bw = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(tag_bw), GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_TxBfProfileTagBw\n"); + + memcpy(&tag_bw, HqaCmdFrame->Data, 4); + tag_bw = ntohl(tag_bw); + + kalMemSet(prInBuf, 0, sizeof(tag_bw)); + kalSnprintf(prInBuf, sizeof(tag_bw), "%u", tag_bw); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_DBW(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagSuMu(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t su_mu = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(su_mu), GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_TxBfProfileTagSuMu\n"); + + memcpy(&su_mu, HqaCmdFrame->Data, 4); + su_mu = ntohl(su_mu); + + kalMemSet(prInBuf, 0, sizeof(su_mu)); + kalSnprintf(prInBuf, sizeof(su_mu), "%u", su_mu); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_SuMu(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagMemAlloc( + struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t col_idx0, row_idx0, col_idx1, row_idx1; + uint32_t col_idx2, row_idx2, col_idx3, row_idx3; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_TxBfProfileTagMemAlloc\n"); + + memcpy(&col_idx0, HqaCmdFrame->Data + 4 * 0, 4); + col_idx0 = ntohl(col_idx0); + memcpy(&row_idx0, HqaCmdFrame->Data + 4 * 1, 4); + row_idx0 = ntohl(row_idx0); + memcpy(&col_idx1, HqaCmdFrame->Data + 4 * 2, 4); + col_idx1 = ntohl(col_idx1); + memcpy(&row_idx1, HqaCmdFrame->Data + 4 * 3, 4); + row_idx1 = ntohl(row_idx1); + memcpy(&col_idx2, HqaCmdFrame->Data + 4 * 4, 4); + col_idx2 = ntohl(col_idx2); + memcpy(&row_idx2, HqaCmdFrame->Data + 4 * 5, 4); + row_idx2 = ntohl(row_idx2); + memcpy(&col_idx3, HqaCmdFrame->Data + 4 * 6, 4); + col_idx3 = ntohl(col_idx3); + memcpy(&row_idx3, HqaCmdFrame->Data + 4 * 7, 4); + row_idx3 = ntohl(row_idx3); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSnprintf(prInBuf, sizeof(uint8_t) * (HQA_BF_STR_SIZE), + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + col_idx0, row_idx0, col_idx1, row_idx1, col_idx2, row_idx2, + col_idx3, row_idx3); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_Mem(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagMatrix(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t nrow, ncol, ngroup, LM, code_book, htc_exist; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_TxBfProfileTagMatrix\n"); + + memcpy(&nrow, HqaCmdFrame->Data + 4 * 0, 4); + nrow = ntohl(nrow); + memcpy(&ncol, HqaCmdFrame->Data + 4 * 1, 4); + ncol = ntohl(ncol); + memcpy(&ngroup, HqaCmdFrame->Data + 4 * 2, 4); + ngroup = ntohl(ngroup); + memcpy(&LM, HqaCmdFrame->Data + 4 * 3, 4); + LM = ntohl(LM); + memcpy(&code_book, HqaCmdFrame->Data + 4 * 4, 4); + code_book = ntohl(code_book); + memcpy(&htc_exist, HqaCmdFrame->Data + 4 * 5, 4); + htc_exist = ntohl(htc_exist); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSnprintf(prInBuf, sizeof(uint8_t) * (HQA_BF_STR_SIZE), + "%02x:%02x:%02x:%02x:%02x:%02x", nrow, ncol, + ngroup, LM, code_book, htc_exist); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_Matrix(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagSnr(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t snr_sts0, snr_sts1, snr_sts2, snr_sts3; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_TxBfProfileTagSnr\n"); + + memcpy(&snr_sts0, HqaCmdFrame->Data + 4 * 0, 4); + snr_sts0 = ntohl(snr_sts0); + memcpy(&snr_sts1, HqaCmdFrame->Data + 4 * 1, 4); + snr_sts1 = ntohl(snr_sts1); + memcpy(&snr_sts2, HqaCmdFrame->Data + 4 * 2, 4); + snr_sts2 = ntohl(snr_sts2); + memcpy(&snr_sts3, HqaCmdFrame->Data + 4 * 3, 4); + snr_sts3 = ntohl(snr_sts3); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSnprintf(prInBuf, sizeof(uint8_t) * (HQA_BF_STR_SIZE), + "%02x:%02x:%02x:%02x", snr_sts0, snr_sts1, snr_sts2, snr_sts3); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_SNR(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagSmtAnt(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t smt_ant = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(smt_ant), GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_TxBfProfileTagSmtAnt\n"); + + memcpy(&smt_ant, HqaCmdFrame->Data + 4 * 0, 4); + smt_ant = ntohl(smt_ant); + + kalMemSet(prInBuf, 0, sizeof(smt_ant)); + kalSnprintf(prInBuf, sizeof(smt_ant), "%u", smt_ant); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_SmartAnt(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagSeIdx(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t se_idx = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(se_idx), GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_TxBfProfileTagSeIdx\n"); + + memcpy(&se_idx, HqaCmdFrame->Data + 4 * 0, 4); + se_idx = ntohl(se_idx); + + kalMemSet(prInBuf, 0, sizeof(se_idx)); + kalSnprintf(prInBuf, sizeof(se_idx), "%u", se_idx); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_SeIdx(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagRmsdThrd( + struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t rmsd_thrd = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(rmsd_thrd), GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_TxBfProfileTagRmsdThrd\n"); + + memcpy(&rmsd_thrd, HqaCmdFrame->Data + 4 * 0, 4); + rmsd_thrd = ntohl(rmsd_thrd); + + kalMemSet(prInBuf, 0, sizeof(rmsd_thrd)); + kalSnprintf(prInBuf, sizeof(rmsd_thrd), "%u", rmsd_thrd); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_RmsdThrd(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagMcsThrd(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t mcs_lss0, mcs_sss0, mcs_lss1, mcs_sss1, mcs_lss2, + mcs_sss2; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_TxBfProfileTagMcsThrd\n"); + + memcpy(&mcs_lss0, HqaCmdFrame->Data + 4 * 0, 4); + mcs_lss0 = ntohl(mcs_lss0); + memcpy(&mcs_sss0, HqaCmdFrame->Data + 4 * 1, 4); + mcs_sss0 = ntohl(mcs_sss0); + memcpy(&mcs_lss1, HqaCmdFrame->Data + 4 * 2, 4); + mcs_lss1 = ntohl(mcs_lss1); + memcpy(&mcs_sss1, HqaCmdFrame->Data + 4 * 3, 4); + mcs_sss1 = ntohl(mcs_sss1); + memcpy(&mcs_lss2, HqaCmdFrame->Data + 4 * 4, 4); + mcs_lss2 = ntohl(mcs_lss2); + memcpy(&mcs_sss2, HqaCmdFrame->Data + 4 * 5, 4); + mcs_sss2 = ntohl(mcs_sss2); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSnprintf(prInBuf, sizeof(uint8_t) * (HQA_BF_STR_SIZE), + "%02x:%02x:%02x:%02x:%02x:%02x", mcs_lss0, + mcs_sss0, mcs_lss1, mcs_sss1, mcs_lss2, + mcs_sss2); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_McsThrd(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagTimeOut(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t bf_tout = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(bf_tout), GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_TxBfProfileTagTimeOut\n"); + + memcpy(&bf_tout, HqaCmdFrame->Data + 4 * 0, 4); + bf_tout = ntohl(bf_tout); + + kalMemSet(prInBuf, 0, sizeof(bf_tout)); + kalSnprintf(prInBuf, sizeof(bf_tout), "%x", bf_tout); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_TimeOut(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagDesiredBw( + struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t desire_bw = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(desire_bw), GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_TxBfProfileTagDesiredBw\n"); + + memcpy(&desire_bw, HqaCmdFrame->Data + 4 * 0, 4); + desire_bw = ntohl(desire_bw); + + kalMemSet(prInBuf, 0, sizeof(desire_bw)); + kalSnprintf(prInBuf, sizeof(desire_bw), "%u", desire_bw); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_DesiredBW(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagDesiredNc( + struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t desire_nc = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(desire_nc), GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_TxBfProfileTagDesiredNc\n"); + + memcpy(&desire_nc, HqaCmdFrame->Data + 4 * 0, 4); + desire_nc = ntohl(desire_nc); + + kalMemSet(prInBuf, 0, sizeof(desire_nc)); + kalSnprintf(prInBuf, sizeof(desire_nc), "%u", desire_nc); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_DesiredNc(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagDesiredNr( + struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t desire_nr = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(desire_nr), GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_TxBfProfileTagDesiredNr\n"); + + memcpy(&desire_nr, HqaCmdFrame->Data + 4 * 0, 4); + desire_nr = ntohl(desire_nr); + + kalMemSet(prInBuf, 0, sizeof(desire_nr)); + kalSnprintf(prInBuf, sizeof(desire_nr), "%u", desire_nr); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_DesiredNr(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagWrite(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t idx = 0; /* WLAN_IDX */ + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(idx), GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_TxBfProfileTagWrite\n"); + + memcpy(&idx, HqaCmdFrame->Data + 4 * 0, 4); + idx = ntohl(idx); + + kalMemSet(prInBuf, 0, sizeof(idx)); + kalSnprintf(prInBuf, sizeof(idx), "%u", idx); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTagWrite(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TxBfProfileTagRead(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t idx = 0, isBFer = 0; + uint8_t *prInBuf; + union PFMU_PROFILE_TAG1 rPfmuTag1; + union PFMU_PROFILE_TAG2 rPfmuTag2; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_TxBfProfileTagRead\n"); + + memcpy(&idx, HqaCmdFrame->Data + 4 * 0, 4); + idx = ntohl(idx); + memcpy(&isBFer, HqaCmdFrame->Data + 4 * 1, 4); + isBFer = ntohl(isBFer); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSnprintf(prInBuf, sizeof(uint8_t) * (HQA_BF_STR_SIZE), + "%02x:%02x", idx, isBFer); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTagRead(prNetDev, prInBuf); + + rPfmuTag1.au4RawData[0] = ntohl(g_rPfmuTag1.au4RawData[0]); + rPfmuTag1.au4RawData[1] = ntohl(g_rPfmuTag1.au4RawData[1]); + rPfmuTag1.au4RawData[2] = ntohl(g_rPfmuTag1.au4RawData[2]); + rPfmuTag1.au4RawData[3] = ntohl(g_rPfmuTag1.au4RawData[3]); + + rPfmuTag2.au4RawData[0] = ntohl(g_rPfmuTag2.au4RawData[0]); + rPfmuTag2.au4RawData[1] = ntohl(g_rPfmuTag2.au4RawData[1]); + rPfmuTag2.au4RawData[2] = ntohl(g_rPfmuTag2.au4RawData[2]); + + memcpy(HqaCmdFrame->Data + 2, &rPfmuTag1, + sizeof(union PFMU_PROFILE_TAG1)); + memcpy(HqaCmdFrame->Data + 2 + sizeof(union + PFMU_PROFILE_TAG1), &rPfmuTag2, + sizeof(union PFMU_PROFILE_TAG2)); + + ResponseToQA(HqaCmdFrame, prIwReqData, + 2 + sizeof(union PFMU_PROFILE_TAG1) + sizeof( + union PFMU_PROFILE_TAG2), i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_StaRecCmmUpdate(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t wlan_idx, bss_idx, aid; + uint8_t mac[MAC_ADDR_LEN]; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StaRecCmmUpdate\n"); + + memcpy(&wlan_idx, HqaCmdFrame->Data + 4 * 0, 4); + wlan_idx = ntohl(wlan_idx); + memcpy(&bss_idx, HqaCmdFrame->Data + 4 * 1, 4); + bss_idx = ntohl(bss_idx); + memcpy(&aid, HqaCmdFrame->Data + 4 * 2, 4); + aid = ntohl(aid); + + memcpy(mac, HqaCmdFrame->Data + 4 * 3, 6); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSnprintf(prInBuf, sizeof(uint8_t) * (HQA_BF_STR_SIZE), + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + wlan_idx, bss_idx, aid, mac[0], mac[1], mac[2], mac[3], + mac[4], mac[5]); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_StaRecCmmUpdate(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_StaRecBfUpdate(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t wlan_idx, bss_idx, PfmuId, su_mu, etxbf_cap, + ndpa_rate, ndp_rate; + uint32_t report_poll_rate, tx_mode, nc, nr, cbw, spe_idx, + tot_mem_req; + uint32_t mem_req_20m, mem_row0, mem_col0, mem_row1, + mem_col1; + uint32_t mem_row2, mem_col2, mem_row3, mem_col3; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_StaRecBfUpdate\n"); + + memcpy(&wlan_idx, HqaCmdFrame->Data + 4 * 0, 4); + wlan_idx = ntohl(wlan_idx); + memcpy(&bss_idx, HqaCmdFrame->Data + 4 * 1, 4); + bss_idx = ntohl(bss_idx); + memcpy(&PfmuId, HqaCmdFrame->Data + 4 * 2, 4); + PfmuId = ntohl(PfmuId); + memcpy(&su_mu, HqaCmdFrame->Data + 4 * 3, 4); + su_mu = ntohl(su_mu); + memcpy(&etxbf_cap, HqaCmdFrame->Data + 4 * 4, 4); + etxbf_cap = ntohl(etxbf_cap); + memcpy(&ndpa_rate, HqaCmdFrame->Data + 4 * 5, 4); + ndpa_rate = ntohl(ndpa_rate); + memcpy(&ndp_rate, HqaCmdFrame->Data + 4 * 6, 4); + ndp_rate = ntohl(ndp_rate); + memcpy(&report_poll_rate, HqaCmdFrame->Data + 4 * 7, 4); + report_poll_rate = ntohl(report_poll_rate); + memcpy(&tx_mode, HqaCmdFrame->Data + 4 * 8, 4); + tx_mode = ntohl(tx_mode); + memcpy(&nc, HqaCmdFrame->Data + 4 * 9, 4); + nc = ntohl(nc); + memcpy(&nr, HqaCmdFrame->Data + 4 * 10, 4); + nr = ntohl(nr); + memcpy(&cbw, HqaCmdFrame->Data + 4 * 11, 4); + cbw = ntohl(cbw); + memcpy(&spe_idx, HqaCmdFrame->Data + 4 * 12, 4); + spe_idx = ntohl(spe_idx); + memcpy(&tot_mem_req, HqaCmdFrame->Data + 4 * 13, 4); + tot_mem_req = ntohl(tot_mem_req); + memcpy(&mem_req_20m, HqaCmdFrame->Data + 4 * 14, 4); + mem_req_20m = ntohl(mem_req_20m); + memcpy(&mem_row0, HqaCmdFrame->Data + 4 * 15, 4); + mem_row0 = ntohl(mem_row0); + memcpy(&mem_col0, HqaCmdFrame->Data + 4 * 16, 4); + mem_col0 = ntohl(mem_col0); + memcpy(&mem_row1, HqaCmdFrame->Data + 4 * 17, 4); + mem_row1 = ntohl(mem_row1); + memcpy(&mem_col1, HqaCmdFrame->Data + 4 * 18, 4); + mem_col1 = ntohl(mem_col1); + memcpy(&mem_row2, HqaCmdFrame->Data + 4 * 19, 4); + mem_row2 = ntohl(mem_row2); + memcpy(&mem_col2, HqaCmdFrame->Data + 4 * 20, 4); + mem_col2 = ntohl(mem_col2); + memcpy(&mem_row3, HqaCmdFrame->Data + 4 * 21, 4); + mem_row3 = ntohl(mem_row3); + memcpy(&mem_col3, HqaCmdFrame->Data + 4 * 22, 4); + mem_col3 = ntohl(mem_col3); + + /* For Tool wrong memory row and col num 20160501 */ + if (PfmuId == 0) { + mem_row0 = 0; + mem_col0 = 0; + mem_row1 = 1; + mem_col1 = 0; + mem_row2 = 2; + mem_col2 = 0; + mem_row3 = 3; + mem_col3 = 0; + } else if (PfmuId == 1) { + mem_row0 = 0; + mem_col0 = 2; + mem_row1 = 1; + mem_col1 = 2; + mem_row2 = 2; + mem_col2 = 2; + mem_row3 = 3; + mem_col3 = 2; + } + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSnprintf(prInBuf, sizeof(uint8_t) * (HQA_BF_STR_SIZE), + "%02x:%02x:%02x:%02x:%02x:%02d:%02d:%02d:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + wlan_idx, bss_idx, PfmuId, su_mu, etxbf_cap, ndpa_rate, + ndp_rate, report_poll_rate, tx_mode, nc, nr, + cbw, spe_idx, tot_mem_req, mem_req_20m, mem_row0, mem_col0, + mem_row1, mem_col1, mem_row2, mem_col2, + mem_row3, mem_col3); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_StaRecBfUpdate(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_BFProfileDataRead(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t idx = 0, fgBFer = 0, subcarrIdx = 0, + subcarr_start = 0, subcarr_end = 0; + uint32_t NumOfsub = 0; + uint32_t offset = 0; + uint8_t *SubIdx = NULL; + uint8_t *prInBuf; + union PFMU_DATA rPfmuData; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_BFProfileDataRead\n"); + + memcpy(&idx, HqaCmdFrame->Data + 4 * 0, 4); + idx = ntohl(idx); + memcpy(&fgBFer, HqaCmdFrame->Data + 4 * 1, 4); + fgBFer = ntohl(fgBFer); + memcpy(&subcarr_start, HqaCmdFrame->Data + 4 * 2, 4); + subcarr_start = ntohl(subcarr_start); + memcpy(&subcarr_end, HqaCmdFrame->Data + 4 * 3, 4); + subcarr_end = ntohl(subcarr_end); + + NumOfsub = subcarr_end - subcarr_start + 1; + NumOfsub = ntohl(NumOfsub); + + memcpy(HqaCmdFrame->Data + 2, &NumOfsub, sizeof(NumOfsub)); + offset += sizeof(NumOfsub); + + for (subcarrIdx = subcarr_start; subcarrIdx <= subcarr_end; + subcarrIdx++) { + SubIdx = (uint8_t *) &subcarrIdx; + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSnprintf(prInBuf, sizeof(uint8_t) * (HQA_BF_STR_SIZE), + "%02x:%02x:%02x:%02x", idx, fgBFer, + SubIdx[1], SubIdx[0]); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileDataRead(prNetDev, prInBuf); + + rPfmuData.au4RawData[0] = ntohl(g_rPfmuData.au4RawData[0]); + rPfmuData.au4RawData[1] = ntohl(g_rPfmuData.au4RawData[1]); + rPfmuData.au4RawData[2] = ntohl(g_rPfmuData.au4RawData[2]); + rPfmuData.au4RawData[3] = ntohl(g_rPfmuData.au4RawData[3]); + rPfmuData.au4RawData[4] = ntohl(g_rPfmuData.au4RawData[4]); + + memcpy(HqaCmdFrame->Data + 2 + offset, &rPfmuData, + sizeof(rPfmuData)); + offset += sizeof(rPfmuData); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + offset, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_BFProfileDataWrite(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t pfmuid, subcarrier, phi11, psi21, phi21, psi31, + phi31, psi41; + uint32_t phi22, psi32, phi32, psi42, phi33, psi43, snr00, + snr01, snr02, snr03; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_BFProfileDataWrite\n"); + + memcpy(&pfmuid, HqaCmdFrame->Data + 4 * 0, 4); + pfmuid = ntohl(pfmuid); + memcpy(&subcarrier, HqaCmdFrame->Data + 4 * 1, 4); + subcarrier = ntohl(subcarrier); + memcpy(&phi11, HqaCmdFrame->Data + 4 * 2, 4); + phi11 = ntohl(phi11); + memcpy(&psi21, HqaCmdFrame->Data + 4 * 3, 4); + psi21 = ntohl(psi21); + memcpy(&phi21, HqaCmdFrame->Data + 4 * 4, 4); + phi21 = ntohl(phi21); + memcpy(&psi31, HqaCmdFrame->Data + 4 * 5, 4); + psi31 = ntohl(psi31); + memcpy(&phi31, HqaCmdFrame->Data + 4 * 6, 4); + phi31 = ntohl(phi31); + memcpy(&psi41, HqaCmdFrame->Data + 4 * 7, 4); + psi41 = ntohl(psi41); + memcpy(&phi22, HqaCmdFrame->Data + 4 * 8, 4); + phi22 = ntohl(phi22); + memcpy(&psi32, HqaCmdFrame->Data + 4 * 9, 4); + psi32 = ntohl(psi32); + memcpy(&phi32, HqaCmdFrame->Data + 4 * 10, 4); + phi32 = ntohl(phi32); + memcpy(&psi42, HqaCmdFrame->Data + 4 * 11, 4); + psi42 = ntohl(psi42); + memcpy(&phi33, HqaCmdFrame->Data + 4 * 12, 4); + phi33 = ntohl(phi33); + memcpy(&psi43, HqaCmdFrame->Data + 4 * 13, 4); + psi43 = ntohl(psi43); + memcpy(&snr00, HqaCmdFrame->Data + 4 * 14, 4); + snr00 = ntohl(snr00); + memcpy(&snr01, HqaCmdFrame->Data + 4 * 15, 4); + snr01 = ntohl(snr01); + memcpy(&snr02, HqaCmdFrame->Data + 4 * 16, 4); + snr02 = ntohl(snr02); + memcpy(&snr03, HqaCmdFrame->Data + 4 * 17, 4); + snr03 = ntohl(snr03); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSnprintf(prInBuf, sizeof(uint8_t) * (HQA_BF_STR_SIZE), + "%02x:%03x:%03x:%02x:%03x:%02x:%03x:%02x:%03x:%02x:%03x:%02x:%03x:%02x:%02x:%02x:%02x:%02x", + pfmuid, subcarrier, phi11, psi21, phi21, psi31, phi31, + psi41, + phi22, psi32, phi32, psi42, phi33, psi43, snr00, snr01, + snr02, snr03); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileDataWrite(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_BFSounding(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t su_mu, mu_num, snd_interval, wlan_id0; + uint32_t wlan_id1, wlan_id2, wlan_id3, band_idx; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_BFSounding\n"); + + memcpy(&su_mu, HqaCmdFrame->Data + 4 * 0, 4); + su_mu = ntohl(su_mu); + memcpy(&mu_num, HqaCmdFrame->Data + 4 * 1, 4); + mu_num = ntohl(mu_num); + memcpy(&snd_interval, HqaCmdFrame->Data + 4 * 2, 4); + snd_interval = ntohl(snd_interval); + memcpy(&wlan_id0, HqaCmdFrame->Data + 4 * 3, 4); + wlan_id0 = ntohl(wlan_id0); + memcpy(&wlan_id1, HqaCmdFrame->Data + 4 * 4, 4); + wlan_id1 = ntohl(wlan_id1); + memcpy(&wlan_id2, HqaCmdFrame->Data + 4 * 5, 4); + wlan_id2 = ntohl(wlan_id2); + memcpy(&wlan_id3, HqaCmdFrame->Data + 4 * 6, 4); + wlan_id3 = ntohl(wlan_id3); + memcpy(&band_idx, HqaCmdFrame->Data + 4 * 7, 4); + band_idx = ntohl(band_idx); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSnprintf(prInBuf, sizeof(uint8_t) * (HQA_BF_STR_SIZE), + "%02x:%02x:%02x:%02x:%02x:%02x:%02x", su_mu, mu_num, + snd_interval, wlan_id0, wlan_id1, wlan_id2, + wlan_id3); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_Trigger_Sounding_Proc(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_TXBFSoundingStop(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_TXBFSoundingStop\n"); + + i4Ret = Set_Stop_Sounding_Proc(prNetDev, NULL); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static int32_t HQA_TXBFProfileDataWriteAllExt( + struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static int32_t HQA_TxBfTxApply(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t eBF_enable = 0; + uint32_t iBF_enable = 0; + uint32_t wlan_id = 0; + uint32_t MuTx_enable = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_TxBfTxApply\n"); + + memcpy(&eBF_enable, HqaCmdFrame->Data + 4 * 0, 4); + eBF_enable = ntohl(eBF_enable); + memcpy(&iBF_enable, HqaCmdFrame->Data + 4 * 1, 4); + iBF_enable = ntohl(iBF_enable); + memcpy(&wlan_id, HqaCmdFrame->Data + 4 * 2, 4); + wlan_id = ntohl(wlan_id); + memcpy(&MuTx_enable, HqaCmdFrame->Data + 4 * 3, 4); + MuTx_enable = ntohl(MuTx_enable); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSnprintf(prInBuf, sizeof(uint8_t) * (HQA_BF_STR_SIZE), + "%02x:%02x:%02x:%02x", wlan_id, eBF_enable, + iBF_enable, MuTx_enable); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfTxApply(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_ManualAssoc(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t type; + uint32_t wtbl_idx; + uint32_t ownmac_idx; + uint32_t phymode; + uint32_t bw; + uint32_t pfmuid; + uint32_t marate_mode; + uint32_t marate_mcs; + uint32_t spe_idx; + uint32_t aid; + uint8_t ucAddr1[MAC_ADDR_LEN]; + uint32_t nss = 1; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_ManualAssoc\n"); + + memcpy(&type, HqaCmdFrame->Data + 4 * 0, 4); + type = ntohl(type); + memcpy(&wtbl_idx, HqaCmdFrame->Data + 4 * 1, 4); + wtbl_idx = ntohl(wtbl_idx); + memcpy(&ownmac_idx, HqaCmdFrame->Data + 4 * 2, 4); + ownmac_idx = ntohl(ownmac_idx); + memcpy(&phymode, HqaCmdFrame->Data + 4 * 3, 4); + phymode = ntohl(phymode); + memcpy(&bw, HqaCmdFrame->Data + 4 * 4, 4); + bw = ntohl(bw); + memcpy(&pfmuid, HqaCmdFrame->Data + 4 * 5, 4); + pfmuid = ntohl(pfmuid); + memcpy(&marate_mode, HqaCmdFrame->Data + 4 * 6, 4); + marate_mode = ntohl(marate_mode); + memcpy(&marate_mcs, HqaCmdFrame->Data + 4 * 7, 4); + marate_mcs = ntohl(marate_mcs); + memcpy(&spe_idx, HqaCmdFrame->Data + 4 * 8, 4); + spe_idx = ntohl(spe_idx); + memcpy(&aid, HqaCmdFrame->Data + 4 * 9, 4); + aid = ntohl(aid); + memcpy(ucAddr1, HqaCmdFrame->Data + 4 * 10, 6); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSnprintf(prInBuf, sizeof(uint8_t) * (HQA_BF_STR_SIZE), + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], ucAddr1[4], + ucAddr1[5], type, wtbl_idx, ownmac_idx, + phymode, bw, nss, pfmuid, marate_mode, marate_mcs, spe_idx, + aid, 0); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfManualAssoc(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_TXBF_CMDS[] = { + HQA_TxBfProfileTagInValid, /* 0x1540 */ + HQA_TxBfProfileTagPfmuIdx, /* 0x1541 */ + HQA_TxBfProfileTagBfType, /* 0x1542 */ + HQA_TxBfProfileTagBw, /* 0x1543 */ + HQA_TxBfProfileTagSuMu, /* 0x1544 */ + HQA_TxBfProfileTagMemAlloc, /* 0x1545 */ + HQA_TxBfProfileTagMatrix, /* 0x1546 */ + HQA_TxBfProfileTagSnr, /* 0x1547 */ + HQA_TxBfProfileTagSmtAnt, /* 0x1548 */ + HQA_TxBfProfileTagSeIdx, /* 0x1549 */ + HQA_TxBfProfileTagRmsdThrd, /* 0x154A */ + HQA_TxBfProfileTagMcsThrd, /* 0x154B */ + HQA_TxBfProfileTagTimeOut, /* 0x154C */ + HQA_TxBfProfileTagDesiredBw, /* 0x154D */ + HQA_TxBfProfileTagDesiredNc, /* 0x154E */ + HQA_TxBfProfileTagDesiredNr, /* 0x154F */ + HQA_TxBfProfileTagWrite, /* 0x1550 */ + HQA_TxBfProfileTagRead, /* 0x1551 */ + HQA_StaRecCmmUpdate, /* 0x1552 */ + HQA_StaRecBfUpdate, /* 0x1553 */ + HQA_BFProfileDataRead, /* 0x1554 */ + HQA_BFProfileDataWrite, /* 0x1555 */ + HQA_BFSounding, /* 0x1556 */ + HQA_TXBFSoundingStop, /* 0x1557 */ + HQA_TXBFProfileDataWriteAllExt, /* 0x1558 */ + HQA_TxBfTxApply, /* 0x1559 */ + HQA_ManualAssoc, /* 0x155A */ +}; + +#if CFG_SUPPORT_MU_MIMO +static int32_t HQA_MUGetInitMCS(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Gid = 0; + uint32_t u4User0InitMCS = 0; + uint32_t u4User1InitMCS = 0; + uint32_t u4User2InitMCS = 0; + uint32_t u4User3InitMCS = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MUGetInitMCS\n"); + + memcpy(&u4Gid, HqaCmdFrame->Data, 4); + u4Gid = ntohl(u4Gid); + + kalMemSet(prInBuf, 0, sizeof(u4Gid)); + kalSnprintf(prInBuf, sizeof(u4Gid), "%u", u4Gid); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUGetInitMCS(prNetDev, prInBuf); + + u4User0InitMCS = ntohl(u4User0InitMCS); + u4User1InitMCS = ntohl(u4User1InitMCS); + u4User2InitMCS = ntohl(u4User2InitMCS); + u4User3InitMCS = ntohl(u4User3InitMCS); + + memcpy(HqaCmdFrame->Data + 2, &u4User0InitMCS, + sizeof(uint32_t)); + memcpy(HqaCmdFrame->Data + 2 + 1 * sizeof(uint32_t), + &u4User1InitMCS, sizeof(uint32_t)); + memcpy(HqaCmdFrame->Data + 2 + 2 * sizeof(uint32_t), + &u4User2InitMCS, sizeof(uint32_t)); + memcpy(HqaCmdFrame->Data + 2 + 3 * sizeof(uint32_t), + &u4User3InitMCS, sizeof(uint32_t)); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_MUCalInitMCS(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Num_of_user; + uint32_t u4Bandwidth; + uint32_t u4Nss_of_user0; + uint32_t u4Nss_of_user1; + uint32_t u4Nss_of_user2; + uint32_t u4Nss_of_user3; + uint32_t u4Pf_mu_id_of_user0; + uint32_t u4Pf_mu_id_of_user1; + uint32_t u4Pf_mu_id_of_user2; + uint32_t u4Pf_mu_id_of_user3; + uint32_t u4Num_of_txer; /* number of antenna */ + uint32_t u4Spe_index; + uint32_t u4Group_index; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MUCalInitMCS\n"); + + memcpy(&u4Num_of_user, HqaCmdFrame->Data + 4 * 0, 4); + u4Num_of_user = ntohl(u4Num_of_user); + memcpy(&u4Bandwidth, HqaCmdFrame->Data + 4 * 1, 4); + u4Bandwidth = ntohl(u4Bandwidth); + memcpy(&u4Nss_of_user0, HqaCmdFrame->Data + 4 * 2, 4); + u4Nss_of_user0 = ntohl(u4Nss_of_user0); + memcpy(&u4Nss_of_user1, HqaCmdFrame->Data + 4 * 3, 4); + u4Nss_of_user1 = ntohl(u4Nss_of_user1); + memcpy(&u4Nss_of_user2, HqaCmdFrame->Data + 4 * 4, 4); + u4Nss_of_user2 = ntohl(u4Nss_of_user2); + memcpy(&u4Nss_of_user3, HqaCmdFrame->Data + 4 * 5, 4); + u4Nss_of_user3 = ntohl(u4Nss_of_user3); + memcpy(&u4Pf_mu_id_of_user0, HqaCmdFrame->Data + 4 * 6, 4); + u4Pf_mu_id_of_user0 = ntohl(u4Pf_mu_id_of_user0); + memcpy(&u4Pf_mu_id_of_user1, HqaCmdFrame->Data + 4 * 7, 4); + u4Pf_mu_id_of_user1 = ntohl(u4Pf_mu_id_of_user1); + memcpy(&u4Pf_mu_id_of_user2, HqaCmdFrame->Data + 4 * 8, 4); + u4Pf_mu_id_of_user2 = ntohl(u4Pf_mu_id_of_user2); + memcpy(&u4Pf_mu_id_of_user3, HqaCmdFrame->Data + 4 * 9, 4); + u4Pf_mu_id_of_user3 = ntohl(u4Pf_mu_id_of_user3); + memcpy(&u4Num_of_txer, HqaCmdFrame->Data + 4 * 10, 4); + u4Num_of_txer = ntohl(u4Num_of_txer); + memcpy(&u4Spe_index, HqaCmdFrame->Data + 4 * 11, 4); + u4Spe_index = ntohl(u4Spe_index); + memcpy(&u4Group_index, HqaCmdFrame->Data + 4 * 12, 4); + u4Group_index = ntohl(u4Group_index); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSnprintf(prInBuf, sizeof(uint8_t) * (HQA_BF_STR_SIZE), + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + u4Num_of_user, u4Bandwidth, u4Nss_of_user0, u4Nss_of_user1, + u4Pf_mu_id_of_user0, u4Pf_mu_id_of_user1, + u4Num_of_txer, u4Spe_index, u4Group_index); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUCalInitMCS(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_MUCalLQ(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Type = 0; + uint32_t u4Num_of_user; + uint32_t u4Bandwidth; + uint32_t u4Nss_of_user0; + uint32_t u4Nss_of_user1; + uint32_t u4Nss_of_user2; + uint32_t u4Nss_of_user3; + uint32_t u4Pf_mu_id_of_user0; + uint32_t u4Pf_mu_id_of_user1; + uint32_t u4Pf_mu_id_of_user2; + uint32_t u4Pf_mu_id_of_user3; + uint32_t u4Num_of_txer; /* number of antenna */ + uint32_t u4Spe_index; + uint32_t u4Group_index; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MUCalLQ\n"); + + memcpy(&u4Type, HqaCmdFrame->Data + 4 * 0, 4); + u4Type = ntohl(u4Type); + memcpy(&u4Num_of_user, HqaCmdFrame->Data + 4 * 1, 4); + u4Num_of_user = ntohl(u4Num_of_user); + memcpy(&u4Bandwidth, HqaCmdFrame->Data + 4 * 2, 4); + u4Bandwidth = ntohl(u4Bandwidth); + memcpy(&u4Nss_of_user0, HqaCmdFrame->Data + 4 * 3, 4); + u4Nss_of_user0 = ntohl(u4Nss_of_user0); + memcpy(&u4Nss_of_user1, HqaCmdFrame->Data + 4 * 4, 4); + u4Nss_of_user1 = ntohl(u4Nss_of_user1); + memcpy(&u4Nss_of_user2, HqaCmdFrame->Data + 4 * 5, 4); + u4Nss_of_user2 = ntohl(u4Nss_of_user2); + memcpy(&u4Nss_of_user3, HqaCmdFrame->Data + 4 * 6, 4); + u4Nss_of_user3 = ntohl(u4Nss_of_user3); + memcpy(&u4Pf_mu_id_of_user0, HqaCmdFrame->Data + 4 * 7, 4); + u4Pf_mu_id_of_user0 = ntohl(u4Pf_mu_id_of_user0); + memcpy(&u4Pf_mu_id_of_user1, HqaCmdFrame->Data + 4 * 8, 4); + u4Pf_mu_id_of_user1 = ntohl(u4Pf_mu_id_of_user1); + memcpy(&u4Pf_mu_id_of_user2, HqaCmdFrame->Data + 4 * 9, 4); + u4Pf_mu_id_of_user2 = ntohl(u4Pf_mu_id_of_user2); + memcpy(&u4Pf_mu_id_of_user3, HqaCmdFrame->Data + 4 * 10, 4); + u4Pf_mu_id_of_user3 = ntohl(u4Pf_mu_id_of_user3); + memcpy(&u4Num_of_txer, HqaCmdFrame->Data + 4 * 11, 4); + u4Num_of_txer = ntohl(u4Num_of_txer); + memcpy(&u4Spe_index, HqaCmdFrame->Data + 4 * 12, 4); + u4Spe_index = ntohl(u4Spe_index); + memcpy(&u4Group_index, HqaCmdFrame->Data + 4 * 13, 4); + u4Group_index = ntohl(u4Group_index); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSnprintf(prInBuf, sizeof(uint8_t) * (HQA_BF_STR_SIZE), + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + u4Num_of_user, u4Bandwidth, u4Nss_of_user0, u4Nss_of_user1, + u4Pf_mu_id_of_user0, u4Pf_mu_id_of_user1, + u4Num_of_txer, u4Spe_index, u4Group_index); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUCalLQ(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_MUGetLQ(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t i; + uint8_t u4LqReport[NUM_OF_USER * NUM_OF_MODUL] = {0}; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MUGetLQ\n"); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUGetLQ(prNetDev, prInBuf); + + for (i = 0; i < NUM_OF_USER * NUM_OF_MODUL; i++) { + u4LqReport[i] = ntohl(u4LqReport[i]); + memcpy(HqaCmdFrame->Data + 2 + i * sizeof(uint32_t), + &u4LqReport[i], sizeof(uint32_t)); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_MUSetSNROffset(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Offset = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MUSetSNROffset\n"); + + memcpy(&u4Offset, HqaCmdFrame->Data + 4 * 0, 4); + u4Offset = ntohl(u4Offset); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSnprintf(prInBuf, sizeof(uint8_t) * (HQA_BF_STR_SIZE), + "%02x", u4Offset); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUSetSNROffset(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_MUSetZeroNss(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Zero_nss = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MUSetZeroNss\n"); + + memcpy(&u4Zero_nss, HqaCmdFrame->Data + 4 * 0, 4); + u4Zero_nss = ntohl(u4Zero_nss); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSnprintf(prInBuf, sizeof(uint8_t) * (HQA_BF_STR_SIZE), + "%02x", u4Zero_nss); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUSetZeroNss(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_MUSetSpeedUpLQ(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4SpeedUpLq = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MUSetSpeedUpLQ\n"); + + memcpy(&u4SpeedUpLq, HqaCmdFrame->Data + 4 * 0, 4); + u4SpeedUpLq = ntohl(u4SpeedUpLq); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSnprintf(prInBuf, sizeof(uint8_t) * (HQA_BF_STR_SIZE), + "%02x", u4SpeedUpLq); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUSetSpeedUpLQ(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; + +} + +static int32_t HQA_MUSetMUTable(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint8_t *prTable; + uint16_t u2Len = 0; + uint32_t u4SuMu = 0; + + prTable = kmalloc_array(u2Len, sizeof(uint8_t), GFP_KERNEL); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MUSetMUTable\n"); + + u2Len = ntohl(HqaCmdFrame->Length) - sizeof(u4SuMu); + + memcpy(&u4SuMu, HqaCmdFrame->Data + 4 * 0, 4); + u4SuMu = ntohl(u4SuMu); + + memcpy(prTable, HqaCmdFrame->Data + 4, u2Len); + + i4Ret = Set_MUSetMUTable(prNetDev, prTable); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static int32_t HQA_MUSetGroup(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4GroupIndex, u4NumOfUser, u4User0Ldpc, + u4User1Ldpc, u4User2Ldpc, u4User3Ldpc; + uint32_t u4ShortGI, u4Bw, u4User0Nss, u4User1Nss, + u4User2Nss, u4User3Nss; + uint32_t u4GroupId, u4User0UP, u4User1UP, u4User2UP, + u4User3UP; + uint32_t u4User0MuPfId, u4User1MuPfId, u4User2MuPfId, + u4User3MuPfId; + uint32_t u4User0InitMCS, u4User1InitMCS, u4User2InitMCS, + u4User3InitMCS; + uint8_t ucAddr1[MAC_ADDR_LEN], ucAddr2[MAC_ADDR_LEN], + ucAddr3[MAC_ADDR_LEN], ucAddr4[MAC_ADDR_LEN]; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MUSetGroup\n"); + + memcpy(&u4GroupIndex, HqaCmdFrame->Data + 4 * 0, 4); + u4GroupIndex = ntohl(u4GroupIndex); + memcpy(&u4NumOfUser, HqaCmdFrame->Data + 4 * 1, 4); + u4NumOfUser = ntohl(u4NumOfUser); + memcpy(&u4User0Ldpc, HqaCmdFrame->Data + 4 * 2, 4); + u4User0Ldpc = ntohl(u4User0Ldpc); + memcpy(&u4User1Ldpc, HqaCmdFrame->Data + 4 * 3, 4); + u4User1Ldpc = ntohl(u4User1Ldpc); + memcpy(&u4User2Ldpc, HqaCmdFrame->Data + 4 * 4, 4); + u4User2Ldpc = ntohl(u4User2Ldpc); + memcpy(&u4User3Ldpc, HqaCmdFrame->Data + 4 * 5, 4); + u4User3Ldpc = ntohl(u4User3Ldpc); + memcpy(&u4ShortGI, HqaCmdFrame->Data + 4 * 6, 4); + u4ShortGI = ntohl(u4ShortGI); + memcpy(&u4Bw, HqaCmdFrame->Data + 4 * 7, 4); + u4Bw = ntohl(u4Bw); + memcpy(&u4User0Nss, HqaCmdFrame->Data + 4 * 8, 4); + u4User0Nss = ntohl(u4User0Nss); + memcpy(&u4User1Nss, HqaCmdFrame->Data + 4 * 9, 4); + u4User1Nss = ntohl(u4User1Nss); + memcpy(&u4User2Nss, HqaCmdFrame->Data + 4 * 10, 4); + u4User2Nss = ntohl(u4User2Nss); + memcpy(&u4User3Nss, HqaCmdFrame->Data + 4 * 11, 4); + u4User3Nss = ntohl(u4User3Nss); + memcpy(&u4GroupId, HqaCmdFrame->Data + 4 * 12, 4); + u4GroupId = ntohl(u4GroupId); + memcpy(&u4User0UP, HqaCmdFrame->Data + 4 * 13, 4); + u4User0UP = ntohl(u4User0UP); + memcpy(&u4User1UP, HqaCmdFrame->Data + 4 * 14, 4); + u4User1UP = ntohl(u4User1UP); + memcpy(&u4User2UP, HqaCmdFrame->Data + 4 * 15, 4); + u4User2UP = ntohl(u4User2UP); + memcpy(&u4User3UP, HqaCmdFrame->Data + 4 * 16, 4); + u4User3UP = ntohl(u4User3UP); + memcpy(&u4User0MuPfId, HqaCmdFrame->Data + 4 * 17, 4); + u4User0MuPfId = ntohl(u4User0MuPfId); + memcpy(&u4User1MuPfId, HqaCmdFrame->Data + 4 * 18, 4); + u4User1MuPfId = ntohl(u4User1MuPfId); + memcpy(&u4User2MuPfId, HqaCmdFrame->Data + 4 * 19, 4); + u4User2MuPfId = ntohl(u4User2MuPfId); + memcpy(&u4User3MuPfId, HqaCmdFrame->Data + 4 * 20, 4); + u4User3MuPfId = ntohl(u4User3MuPfId); + memcpy(&u4User0InitMCS, HqaCmdFrame->Data + 4 * 21, 4); + u4User0InitMCS = ntohl(u4User0InitMCS); + memcpy(&u4User1InitMCS, HqaCmdFrame->Data + 4 * 22, 4); + u4User1InitMCS = ntohl(u4User1InitMCS); + memcpy(&u4User2InitMCS, HqaCmdFrame->Data + 4 * 23, 4); + u4User2InitMCS = ntohl(u4User2InitMCS); + memcpy(&u4User3InitMCS, HqaCmdFrame->Data + 4 * 24, 4); + u4User3InitMCS = ntohl(u4User3InitMCS); + + memcpy(ucAddr1, HqaCmdFrame->Data + 4 * 25, 6); + memcpy(ucAddr2, HqaCmdFrame->Data + 4 * 25 + 6 * 1, 6); + memcpy(ucAddr3, HqaCmdFrame->Data + 4 * 25 + 6 * 2, 6); + memcpy(ucAddr4, HqaCmdFrame->Data + 4 * 25 + 6 * 3, 6); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSnprintf(prInBuf, sizeof(uint8_t) * (HQA_BF_STR_SIZE), + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + u4GroupIndex, u4NumOfUser, u4User0Ldpc, u4User1Ldpc, + u4ShortGI, u4Bw, u4User0Nss, u4User1Nss, + u4GroupId, u4User0UP, u4User1UP, u4User0MuPfId, + u4User1MuPfId, u4User0InitMCS, u4User1InitMCS, + ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], ucAddr1[4], + ucAddr1[5], ucAddr2[0], ucAddr2[1], + ucAddr2[2], ucAddr2[3], ucAddr2[4], ucAddr2[5]); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUSetGroup(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_MUGetQD(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4SubIdx = 0; + + /* TODO */ + uint32_t u4User0InitMCS = 0; + uint32_t u4User1InitMCS = 0; + uint32_t u4User2InitMCS = 0; + uint32_t u4User3InitMCS = 0; + + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MUGetQD\n"); + + memcpy(&u4SubIdx, HqaCmdFrame->Data, 4); + u4SubIdx = ntohl(u4SubIdx); + + kalMemSet(prInBuf, 0, sizeof(u4SubIdx)); + kalSnprintf(prInBuf, sizeof(u4SubIdx), "%u", u4SubIdx); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUGetQD(prNetDev, prInBuf); + + /* TODO */ + u4User0InitMCS = ntohl(u4User0InitMCS); + u4User1InitMCS = ntohl(u4User1InitMCS); + u4User2InitMCS = ntohl(u4User2InitMCS); + u4User3InitMCS = ntohl(u4User3InitMCS); + + memcpy(HqaCmdFrame->Data + 2, &u4User0InitMCS, + sizeof(uint32_t)); + memcpy(HqaCmdFrame->Data + 2 + 1 * sizeof(uint32_t), + &u4User1InitMCS, sizeof(uint32_t)); + memcpy(HqaCmdFrame->Data + 2 + 2 * sizeof(uint32_t), + &u4User2InitMCS, sizeof(uint32_t)); + memcpy(HqaCmdFrame->Data + 2 + 3 * sizeof(uint32_t), + &u4User3InitMCS, sizeof(uint32_t)); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_MUSetEnable(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Enable = 0; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MUSetEnable\n"); + + memcpy(&u4Enable, HqaCmdFrame->Data + 4 * 0, 4); + u4Enable = ntohl(u4Enable); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSnprintf(prInBuf, sizeof(uint8_t) * (HQA_BF_STR_SIZE), + "%02x", u4Enable); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUSetEnable(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_MUSetGID_UP(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t au4Gid[2]; + uint32_t au4Up[4]; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MUSetGID_UP\n"); + + memcpy(&au4Gid[0], HqaCmdFrame->Data + 4 * 0, 4); + au4Gid[0] = ntohl(au4Gid[0]); + memcpy(&au4Gid[1], HqaCmdFrame->Data + 4 * 1, 4); + au4Gid[1] = ntohl(au4Gid[1]); + memcpy(&au4Up[0], HqaCmdFrame->Data + 4 * 2, 4); + au4Up[0] = ntohl(au4Up[0]); + memcpy(&au4Up[1], HqaCmdFrame->Data + 4 * 3, 4); + au4Up[1] = ntohl(au4Up[1]); + memcpy(&au4Up[2], HqaCmdFrame->Data + 4 * 4, 4); + au4Up[2] = ntohl(au4Up[2]); + memcpy(&au4Up[3], HqaCmdFrame->Data + 4 * 5, 4); + au4Up[3] = ntohl(au4Up[3]); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSnprintf(prInBuf, sizeof(uint8_t) * (HQA_BF_STR_SIZE), + "%02x:%02x:%02x:%02x:%02x:%02x", au4Gid[0], + au4Gid[1], au4Up[0], au4Up[1], au4Up[2], + au4Up[3]); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUSetGID_UP(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static int32_t HQA_MUTriggerTx(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4BandIdx, u4IsRandomPattern; + uint32_t u4MsduPayloadLength0, u4MsduPayloadLength1, + u4MsduPayloadLength2, u4MsduPayloadLength3; + uint32_t u4MuPacketCount, u4NumOfSTAs; + uint8_t ucAddr1[MAC_ADDR_LEN], ucAddr2[MAC_ADDR_LEN], + ucAddr3[MAC_ADDR_LEN], ucAddr4[MAC_ADDR_LEN]; + uint8_t *prInBuf; + + prInBuf = kmalloc(sizeof(uint8_t) * (HQA_BF_STR_SIZE), + GFP_KERNEL); + ASSERT(prInBuf); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_MUTriggerTx\n"); + + memcpy(&u4BandIdx, HqaCmdFrame->Data + 4 * 0, 4); + u4BandIdx = ntohl(u4BandIdx); + memcpy(&u4IsRandomPattern, HqaCmdFrame->Data + 4 * 1, 4); + u4IsRandomPattern = ntohl(u4IsRandomPattern); + memcpy(&u4MsduPayloadLength0, HqaCmdFrame->Data + 4 * 2, 4); + u4MsduPayloadLength0 = ntohl(u4MsduPayloadLength0); + memcpy(&u4MsduPayloadLength1, HqaCmdFrame->Data + 4 * 3, 4); + u4MsduPayloadLength1 = ntohl(u4MsduPayloadLength1); + memcpy(&u4MsduPayloadLength2, HqaCmdFrame->Data + 4 * 4, 4); + u4MsduPayloadLength2 = ntohl(u4MsduPayloadLength2); + memcpy(&u4MsduPayloadLength3, HqaCmdFrame->Data + 4 * 5, 4); + u4MsduPayloadLength3 = ntohl(u4MsduPayloadLength3); + memcpy(&u4MuPacketCount, HqaCmdFrame->Data + 4 * 6, 4); + u4MuPacketCount = ntohl(u4MuPacketCount); + memcpy(&u4NumOfSTAs, HqaCmdFrame->Data + 4 * 7, 4); + u4NumOfSTAs = ntohl(u4NumOfSTAs); + memcpy(ucAddr1, HqaCmdFrame->Data + 4 * 8, 6); + memcpy(ucAddr2, HqaCmdFrame->Data + 4 * 8 + 6 * 1, 6); + memcpy(ucAddr3, HqaCmdFrame->Data + 4 * 8 + 6 * 2, 6); + memcpy(ucAddr4, HqaCmdFrame->Data + 4 * 8 + 6 * 3, 6); + + kalMemSet(prInBuf, 0, sizeof(uint8_t) * (HQA_BF_STR_SIZE)); + kalSnprintf(prInBuf, sizeof(uint8_t) * (HQA_BF_STR_SIZE), + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + u4IsRandomPattern, u4MsduPayloadLength0, + u4MsduPayloadLength1, u4MuPacketCount, u4NumOfSTAs, + ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], ucAddr1[4], + ucAddr1[5], + ucAddr2[0], ucAddr2[1], ucAddr2[2], ucAddr2[3], ucAddr2[4], + ucAddr2[5]); + + DBGLOG(RFTEST, ERROR, "prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUTriggerTx(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + kfree(prInBuf); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_TXMU_CMDS[] = { + HQA_MUGetInitMCS, /* 0x1560 */ + HQA_MUCalInitMCS, /* 0x1561 */ + HQA_MUCalLQ, /* 0x1562 */ + HQA_MUGetLQ, /* 0x1563 */ + HQA_MUSetSNROffset, /* 0x1564 */ + HQA_MUSetZeroNss, /* 0x1565 */ + HQA_MUSetSpeedUpLQ, /* 0x1566 */ + HQA_MUSetMUTable, /* 0x1567 */ + HQA_MUSetGroup, /* 0x1568 */ + HQA_MUGetQD, /* 0x1569 */ + HQA_MUSetEnable, /* 0x156A */ + HQA_MUSetGID_UP, /* 0x156B */ + HQA_MUTriggerTx, /* 0x156C */ +}; +#endif +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For ICAP + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t HQA_CapWiFiSpectrum(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct mt66xx_chip_info *prChipInfo = NULL; + struct ATE_OPS_T *prAteOps = NULL; + uint32_t u4Control = 0; + uint32_t u4Trigger = 0; + uint32_t u4RingCapEn = 0; + uint32_t u4Event = 0; + uint32_t u4Node = 0; + uint32_t u4Len = 0; + uint32_t u4StopCycle = 0; + uint32_t u4BW = 0; + uint32_t u4MacTriggerEvent = 0; + uint32_t u4SourceAddrLSB = 0; + uint32_t u4SourceAddrMSB = 0; + uint8_t aucSourceAddress[MAC_ADDR_LEN]; + uint32_t u4Band = 0; + uint32_t u4WFNum; + uint32_t u4IQ; + uint32_t u4DataLen = 0, u4TempLen = 0; + int32_t i4Ret = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prChipInfo = prGlueInfo->prAdapter->chip_info; + prAteOps = prChipInfo->prAteOps; + + memcpy((uint8_t *)&u4Control, HqaCmdFrame->Data + 4 * 0, 4); + u4Control = ntohl(u4Control); + + DBGLOG(RFTEST, INFO, "u4Control = %d\n", u4Control); + + if (u4Control == 1) { + if (prAteOps->setICapStart) { + memcpy((uint8_t *)&u4Trigger, + HqaCmdFrame->Data + 4 * 1, 4); + u4Trigger = ntohl(u4Trigger); + memcpy((uint8_t *)&u4RingCapEn, + HqaCmdFrame->Data + 4 * 2, 4); + u4RingCapEn = ntohl(u4RingCapEn); + memcpy((uint8_t *)&u4Event, + HqaCmdFrame->Data + 4 * 3, 4); + u4Event = ntohl(u4Event); + memcpy((uint8_t *)&u4Node, + HqaCmdFrame->Data + 4 * 4, 4); + u4Node = ntohl(u4Node); + memcpy((uint8_t *)&u4Len, HqaCmdFrame->Data + 4 * 5, 4); + u4Len = ntohl(u4Len); + memcpy((uint8_t *)&u4StopCycle, + HqaCmdFrame->Data + 4 * 6, + 4); + u4StopCycle = ntohl(u4StopCycle); + memcpy((uint8_t *)&u4BW, HqaCmdFrame->Data + 4 * 7, 4); + u4BW = ntohl(u4BW); + memcpy((uint8_t *)&u4MacTriggerEvent, + HqaCmdFrame->Data + 4 * 8, 4); + u4MacTriggerEvent = ntohl(u4MacTriggerEvent); + memcpy((uint8_t *)&aucSourceAddress, + HqaCmdFrame->Data + 4 * 9, MAC_ADDR_LEN); + memcpy((uint8_t *)&u4Band, + HqaCmdFrame->Data + 4 * 9 + MAC_ADDR_LEN, 4); + u4Band = ntohl(u4Band); + + /* AT Command #1, Trigger always = 1 */ + DBGLOG(RFTEST, INFO, + "u4Trigger=%u, u4RingCapEn=%u, u4TriggerEvent=%u\n", + u4Trigger, u4RingCapEn, u4Trigger); + /* AT Command #81 */ + DBGLOG(RFTEST, INFO, + "u4Node=%u, u4Len=%u, u4topCycle=%u, u4BW=%u, u4Band=%d", + u4Node, u4Len, u4StopCycle, u4BW, u4Band); + + u4SourceAddrLSB = ((aucSourceAddress[0]) | + (aucSourceAddress[1] << 8) | + (aucSourceAddress[2]) << 16 | + (aucSourceAddress[3]) << 24); + u4SourceAddrMSB = ((aucSourceAddress[4]) | + (aucSourceAddress[5] << 8) | + (0x1 << 16)); + + prGlueInfo->prAdapter->rIcapInfo.u4CapNode = u4Node; + i4Ret = prAteOps->setICapStart(prGlueInfo, u4Trigger, + u4RingCapEn, u4Event, u4Node, + u4Len, u4StopCycle, u4BW, + u4MacTriggerEvent, + u4SourceAddrLSB, + u4SourceAddrMSB, u4Band); + prGlueInfo->prAdapter->fgIcapMode = u4Trigger; + } else + i4Ret = 1; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + } else if (u4Control == 2) { + if (prAteOps->getICapStatus) + i4Ret = prAteOps->getICapStatus(prGlueInfo); + else + i4Ret = 1; + /* Query whether ICAP Done */ + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + } else if (u4Control == 3) { + if (prAteOps->getICapIQData) { + kalMemCopy((uint8_t *)&u4WFNum, + HqaCmdFrame->Data + 4 * 1, + 4); + u4WFNum = ntohl(u4WFNum); + kalMemCopy((uint8_t *)&u4IQ, + HqaCmdFrame->Data + 4 * 2, + 4); + u4IQ = ntohl(u4IQ); + + DBGLOG(RFTEST, INFO, + "u4WFNum = %d, u4IQ = %d\n", u4WFNum, u4IQ); + + u4DataLen = prAteOps->getICapIQData( + prGlueInfo, + &HqaCmdFrame->Data[2 + 4 * 4], + u4IQ, + u4WFNum); + u4TempLen = u4DataLen; + u4Control = ntohl(u4Control); + kalMemCopy(HqaCmdFrame->Data + 2 + 4 * 0, + (uint8_t *)&u4Control, + sizeof(u4Control)); + u4WFNum = ntohl(u4WFNum); + kalMemCopy(HqaCmdFrame->Data + 2 + 4 * 1, + (uint8_t *)&u4WFNum, + sizeof(u4WFNum)); + u4IQ = ntohl(u4IQ); + kalMemCopy(HqaCmdFrame->Data + 2 + 4 * 2, + (uint8_t *)&u4IQ, + sizeof(u4IQ)); + u4TempLen = ntohl(u4DataLen); + kalMemCopy(HqaCmdFrame->Data + 2 + 4 * 3, + (uint8_t *)&u4TempLen, + sizeof(u4DataLen)); + + } + + i4Ret = 0; + /* Get IQ Data and transmit them to UI DLL */ + ResponseToQA(HqaCmdFrame, + prIwReqData, + 2 + 4 * 4 + u4DataLen * sizeof(int32_t), + i4Ret); + } else { + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + } + return 0; +} + +int32_t mt6632SetICapStart(struct GLUE_INFO *prGlueInfo, + uint32_t u4Trigger, uint32_t u4RingCapEn, + uint32_t u4Event, uint32_t u4Node, uint32_t u4Len, + uint32_t u4StopCycle, + uint32_t u4BW, uint32_t u4MacTriggerEvent, + uint32_t u4SourceAddrLSB, + uint32_t u4SourceAddrMSB, uint32_t u4Band) +{ + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + /* iwpriv wlan205 set_test_cmd 75 0 (J mode Setting) */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_J_MODE; + rRfATInfo.u4FuncData = 0; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + /* iwpriv wlan205 set_test_cmd 71 0 (Channel Bandwidth) */ + if (u4BW == 4) + u4BW = 3; + else if (u4BW == 3) + u4BW = 4; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_CBW; + rRfATInfo.u4FuncData = u4BW; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + /* iwpriv wlan205 set_test_cmd 24 0 (ADC clock mode) */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_ADC_CLK_MODE; + rRfATInfo.u4FuncData = 0; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + /* iwpriv wlan205 set_test_cmd 84 18000 + * (Internal Capture Trigger Offset) + */ + rRfATInfo.u4FuncIndex = + RF_AT_FUNCID_SET_ICAP_TRIGGER_OFFSET; + rRfATInfo.u4FuncData = u4StopCycle; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + if (u4Len == 0) + u4Len = 196615;/* 24000; */ + /* iwpriv wlan205 set_test_cmd 83 24576 (Internal Capture Size) */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ICAP_SIZE; + rRfATInfo.u4FuncData = u4Len; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + /* iwpriv wlan205 set_test_cmd 80 0 (Internal Capture Content) */ + if (u4Node == 0x6) + u4Node = 0x10000006; + else if (u4Node == 0x8) + u4Node = 0x49; + else if (u4Node == 0x9) + u4Node = 0x48; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ICAP_CONTENT; + rRfATInfo.u4FuncData = u4Node; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + /* iwpriv wlan205 set_test_cmd 81 0 (Internal Capture Trigger mode) */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ICAP_MODE; + rRfATInfo.u4FuncData = u4Trigger; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ICAP_RING; + rRfATInfo.u4FuncData = u4RingCapEn; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + /* iwpriv wlan205 set_test_cmd 1 13 */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_CH_SWITCH_FOR_ICAP; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + /* iwpriv wlan205 set_test_cmd 1 11 */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_ICAP; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + return 0; +} + +int32_t mt6632GetICapStatus(struct GLUE_INFO *prGlueInfo) +{ + struct ADAPTER *prAdapter; + + ASSERT(prGlueInfo); + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + if (prAdapter->rIcapInfo.fgCaptureDone) { + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_CapWiFiSpectrum Done!!!!!!!!!!!!!!!!!\n"); + return 0; + } + return 1; +} + +int32_t connacSetICapStart(struct GLUE_INFO *prGlueInfo, + uint32_t u4Trigger, uint32_t u4RingCapEn, + uint32_t u4Event, uint32_t u4Node, uint32_t u4Len, + uint32_t u4StopCycle, + uint32_t u4BW, uint32_t u4MacTriggerEvent, + uint32_t u4SourceAddrLSB, + uint32_t u4SourceAddrMSB, uint32_t u4Band) +{ + struct PARAM_MTK_WIFI_TEST_STRUCT_EXT_T rRfATInfo; + struct RBIST_CAP_START_T *prICapInfo = NULL; + uint32_t u4BufLen = 0, u4IQArrayLen = 0; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + if (u4Trigger) { + if (prGlueInfo->prAdapter->rIcapInfo.fgIcapEnable) { + log_dbg(RFTEST, ERROR, "Already starting, ignore\n"); + return 1; + } + } else { + log_dbg(RFTEST, INFO, "Shutdown Icap\n"); + prGlueInfo->prAdapter->rIcapInfo.fgIcapEnable = FALSE; + if (prGlueInfo->prAdapter->rIcapInfo.prIQArray != NULL) + kalMemFree(prGlueInfo->prAdapter->rIcapInfo.prIQArray, + VIR_MEM_TYPE, + u4IQArrayLen); + prGlueInfo->prAdapter->rIcapInfo.u4IQArrayIndex = 0; + prGlueInfo->prAdapter->rIcapInfo.u4ICapEventCnt = 0; + prGlueInfo->prAdapter->rIcapInfo.prIQArray = NULL; + return 0; + } + + prICapInfo = &(rRfATInfo.Data.rICapInfo); + kalMemZero(prICapInfo, sizeof(struct RBIST_CAP_START_T)); + prICapInfo->u4Trigger = u4Trigger; + prICapInfo->u4TriggerEvent = u4Event; + + u4IQArrayLen = MAX_ICAP_IQ_DATA_CNT * sizeof(struct _RBIST_IQ_DATA_T); +#if 0 + if (prGlueInfo->prAdapter->rIcapInfo.prIQArray != NULL) + kalMemFree(prGlueInfo->prAdapter->rIcapInfo.prIQArray, + VIR_MEM_TYPE, + u4IQArrayLen); +#endif + + if (!prGlueInfo->prAdapter->rIcapInfo.prIQArray) { + prGlueInfo->prAdapter->rIcapInfo.prIQArray = + kalMemAlloc(u4IQArrayLen, VIR_MEM_TYPE); + if (!prGlueInfo->prAdapter->rIcapInfo.prIQArray) { + DBGLOG(RFTEST, ERROR, + "Not enough memory for IQ_Array\n"); + return 0; + } + } + + prGlueInfo->prAdapter->rIcapInfo.u4IQArrayIndex = 0; + prGlueInfo->prAdapter->rIcapInfo.u4ICapEventCnt = 0; + kalMemZero(prGlueInfo->prAdapter->rIcapInfo.au4ICapDumpIndex, + sizeof(prGlueInfo->prAdapter->rIcapInfo.au4ICapDumpIndex)); + kalMemZero(prGlueInfo->prAdapter->rIcapInfo.prIQArray, u4IQArrayLen); + + if (prICapInfo->u4TriggerEvent == CAP_FREE_RUN) + prICapInfo->u4RingCapEn = CAP_RING_MODE_DISABLE; + else + prICapInfo->u4RingCapEn = CAP_RING_MODE_ENABLE; + + prICapInfo->u4CaptureNode = u4Node; + prICapInfo->u4CaptureLen = u4Len; + prICapInfo->u4CapStopCycle = u4StopCycle; + prICapInfo->u4BW = u4BW; + prICapInfo->u4MacTriggerEvent = u4MacTriggerEvent; + prICapInfo->u4SourceAddressLSB = u4SourceAddrLSB; + prICapInfo->u4SourceAddressMSB = u4SourceAddrMSB; + prICapInfo->u4BandIdx = u4Band; + prICapInfo->u4EnBitWidth = CAP_96_BIT; + prICapInfo->u4Architech = CAP_ON_CHIP; + prICapInfo->u4PhyIdx = 0; + prICapInfo->u4CapSource = CAP_WIFI_PHY; +#if CFG_MTK_EMI + prICapInfo->u4EmiStartAddress = + (uint32_t) (gConEmiPhyBase & 0xFFFFFFFF); + prICapInfo->u4EmiEndAddress = + (uint32_t) ((gConEmiPhyBase + gConEmiSize) & 0xFFFFFFFF); + prICapInfo->u4EmiMsbAddress = + (uint32_t) ((((uint64_t) gConEmiPhyBase) >> 32) & 0xFFFFFFFF); + + DBGLOG(RFTEST, INFO, + "startAddr = 0x%08x, endAddress = 0x%08x, MsbAddr = 0x%08x\n", + prICapInfo->u4EmiStartAddress, + prICapInfo->u4EmiEndAddress, + prICapInfo->u4EmiMsbAddress); +#else + DBGLOG(RFTEST, WARN, "Platform doesn't support WMT, no EMI address\n"); +#endif + + DBGLOG(RFTEST, INFO, + "%s :\n prICapInfo->u4Trigger = 0x%08x\n prICapInfo->u4RingCapEn = 0x%08x\n" + "prICapInfo->u4TriggerEvent = 0x%08x\n prICapInfo->u4CaptureNode = 0x%08x\n" + "prICapInfo->u4CaptureLen = 0x%08x\n prICapInfo->u4CapStopCycle = 0x%08x\n" + "prICapInfo->ucBW = 0x%08x\n prICapInfo->u4MacTriggerEvent = 0x%08x\n" + "prICapInfo->u4SourceAddressLSB = 0x%08x\n prICapInfo->u4SourceAddressMSB = 0x%08x\n" + "prICapInfo->u4BandIdx = 0x%08x\n", + __func__, + prICapInfo->u4Trigger, prICapInfo->u4RingCapEn, + prICapInfo->u4TriggerEvent, prICapInfo->u4CaptureNode, + prICapInfo->u4CaptureLen, + prICapInfo->u4CapStopCycle, prICapInfo->u4BW, + prICapInfo->u4MacTriggerEvent, + prICapInfo->u4SourceAddressLSB, + prICapInfo->u4SourceAddressMSB, prICapInfo->u4BandIdx); + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidExtRfTestICapStart, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + return 0; +} + +int32_t connacGetICapStatus(struct GLUE_INFO *prGlueInfo) +{ + struct ADAPTER *prAdapter; + struct PARAM_MTK_WIFI_TEST_STRUCT_EXT_T rRfATInfo; + uint32_t u4BufLen = 0; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prGlueInfo); + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + if (prAdapter->rIcapInfo.fgCaptureDone) { + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_CapWiFiSpectrum Done!!!!!!!!!!!!!!!!!\n"); + return 0; + } + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidExtRfTestICapStatus, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_CapWiFiSpectrum Wait!!!!!!!!!!!!!!!!!\n"); + return 1; +} + +int32_t commonGetICapIQData(struct GLUE_INFO *prGlueInfo, + uint8_t *pData, uint32_t u4IQType, uint32_t u4WFNum) +{ + struct ADAPTER *prAdapter; + uint32_t u4TempLen = 0; + uint32_t u4DataLen = 0; + int32_t *prIQAry; + int32_t i = 0; + + ASSERT(prGlueInfo); + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + if (u4WFNum <= 1) { + GetIQData(prAdapter, &prIQAry, &u4DataLen, u4IQType, + u4WFNum); + u4TempLen = u4DataLen; + u4DataLen /= 4; + + u4DataLen = ntohl(u4DataLen); + memcpy(pData + 2 + 4 * 3, (uint8_t *) &u4DataLen, + sizeof(u4DataLen)); + + for (i = 0; i < u4TempLen / sizeof(uint32_t); i++) + prIQAry[i] = ntohl(prIQAry[i]); + + memcpy(pData + 2 + 4 * 4, (uint8_t *) &prIQAry[0], + u4TempLen); + } + return u4TempLen; +} + +int32_t connacGetICapIQData(struct GLUE_INFO *prGlueInfo, + uint8_t *pData, uint32_t u4IQType, uint32_t u4WFNum) +{ + struct ADAPTER *prAdapter; + struct _RBIST_IQ_DATA_T *prIQArray = NULL; + struct ICAP_INFO_T *prICapInfo = NULL; + int32_t i = 0; + uint32_t u4MaxTxCount = 0; + uint32_t u4DumpIndex = 0; + uint32_t u4Value, u4RespLen = 0; + + ASSERT(prGlueInfo); + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + prICapInfo = &prAdapter->rIcapInfo; + prIQArray = prICapInfo->prIQArray; + ASSERT(prIQArray); + u4DumpIndex = prICapInfo->au4ICapDumpIndex[u4WFNum][u4IQType]; + + /* 1. Maximum 1KB = ICAP_EVENT_DATA_SAMPLE (256) slots */ + u4MaxTxCount = prICapInfo->u4IQArrayIndex - u4DumpIndex; + if (u4MaxTxCount > ICAP_EVENT_DATA_SAMPLE) + u4MaxTxCount = ICAP_EVENT_DATA_SAMPLE; + + DBGLOG(RFTEST, INFO, "prICapInfo->au4ICapDumpIndex[%d][%c] = %d\n", + u4WFNum, + (u4IQType == CAP_I_TYPE) ? + 'I' : 'Q', + u4DumpIndex); + + /* 2. Copy to buffer */ + for (i = 0; i < u4MaxTxCount; i++) { + u4Value = prIQArray[u4DumpIndex++].u4IQArray[u4WFNum][u4IQType]; + u4Value = ntohl(u4Value); + kalMemCopy(pData + u4RespLen, (uint8_t *) &u4Value, + sizeof(u4Value)); + u4RespLen += sizeof(u4Value); + } + prICapInfo->au4ICapDumpIndex[u4WFNum][u4IQType] = u4DumpIndex; + DBGLOG(RFTEST, INFO, "u4MaxTxCount = %d\n", u4MaxTxCount); + return u4MaxTxCount; +} + + +static HQA_CMD_HANDLER HQA_ICAP_CMDS[] = { + HQA_CapWiFiSpectrum, /* 0x1580 */ +}; + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t hqa_set_channel_ext(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Ext_id = 0; + uint32_t u4Param_num = 0; + uint32_t u4Band_idx = 0; + uint32_t u4Central_ch0 = 0; + uint32_t u4Central_ch1 = 0; + uint32_t u4Sys_bw = 0; + uint32_t u4Perpkt_bw = 0; + uint32_t u4Pri_sel = 0; + uint32_t u4Reason = 0; + uint32_t u4Ch_band = 0; + uint32_t u4SetFreq = 0; + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4Param_num, HqaCmdFrame->Data + 4 * 1, 4); + u4Param_num = ntohl(u4Param_num); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 2, 4); + u4Band_idx = ntohl(u4Band_idx); + memcpy(&u4Central_ch0, HqaCmdFrame->Data + 4 * 3, 4); + u4Central_ch0 = ntohl(u4Central_ch0); + memcpy(&u4Central_ch1, HqaCmdFrame->Data + 4 * 4, 4); + u4Central_ch1 = ntohl(u4Central_ch1); + memcpy(&u4Sys_bw, HqaCmdFrame->Data + 4 * 5, 4); + u4Sys_bw = ntohl(u4Sys_bw); + memcpy(&u4Perpkt_bw, HqaCmdFrame->Data + 4 * 6, 4); + u4Perpkt_bw = ntohl(u4Perpkt_bw); + memcpy(&u4Pri_sel, HqaCmdFrame->Data + 4 * 7, 4); + u4Pri_sel = ntohl(u4Pri_sel); + memcpy(&u4Reason, HqaCmdFrame->Data + 4 * 8, 4); + u4Reason = ntohl(u4Reason); + memcpy(&u4Ch_band, HqaCmdFrame->Data + 4 * 9, 4); + u4Ch_band = ntohl(u4Ch_band); + + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_channel_ext ext_id : %d\n", u4Ext_id); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_channel_ext param_num : %d\n", + u4Param_num); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_channel_ext band_idx : %d\n", u4Band_idx); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_channel_ext central_ch0 : %d\n", + u4Central_ch0); + /* for BW80+80 */ + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_channel_ext central_ch1 : %d\n", + u4Central_ch1); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_channel_ext sys_bw : %d\n", u4Sys_bw); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_channel_ext perpkt_bw : %d\n", + u4Perpkt_bw); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_channel_ext pri_sel : %d\n", u4Pri_sel); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_channel_ext reason : %d\n", u4Reason); + /* 0:2.4G 1:5G */ + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_channel_ext ch_band : %d\n", u4Ch_band); + + /* BW Mapping in QA Tool + * 0: BW20 + * 1: BW40 + * 2: BW80 + * 3: BW10 + * 4: BW5 + * 5: BW160C + * 6: BW160NC + */ + /* BW Mapping in FW + * 0: BW20 + * 1: BW40 + * 2: BW80 + * 3: BW160C + * 4: BW160NC + * 5: BW5 + * 6: BW10 + */ + /* For POR Cal Setting - 20160601 */ + if ((u4Central_ch0 == u4Central_ch1) && (u4Sys_bw == 6) + && (u4Perpkt_bw == 6)) { + DBGLOG(RFTEST, INFO, "Wrong Setting for POR Cal\n"); + goto exit; + } + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + if ((u4Central_ch0 >= 7 && u4Central_ch0 <= 16) + && u4Ch_band == 1) { + /*Ch7 - Ch12, 5G (5035-5060)*/ + u4SetFreq = 1000 * (5000 + u4Central_ch0 * 5); + } else if (u4Central_ch0 == 6 && u4Ch_band == 1) { + u4SetFreq = 1000 * 5032; + } else { + u4SetFreq = nicChannelNum2Freq(u4Central_ch0); + } + MT_ATESetChannel(prNetDev, 0, u4SetFreq); + + if (u4Sys_bw == 6) { + u4SetFreq = nicChannelNum2Freq(u4Central_ch1); + MT_ATESetChannel(prNetDev, 1, u4SetFreq); + } + + MT_ATESetSystemBW(prNetDev, u4Sys_bw); + + /* For POR Cal Setting - 20160601 */ + if ((u4Sys_bw == 6) && (u4Perpkt_bw == 6)) + MT_ATESetPerPacketBW(prNetDev, 5); + else + MT_ATESetPerPacketBW(prNetDev, u4Perpkt_bw); + + MT_ATEPrimarySetting(prNetDev, u4Pri_sel); + /* PeiHsuan Memo : No Set Reason ? */ + MT_ATESetBand(prNetDev, u4Ch_band); + +exit: + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (uint8_t *) &u4Ext_id, + sizeof(u4Ext_id)); + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t hqa_set_txcontent_ext(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Len = 0; + uint32_t u4Ext_id = 0; + uint32_t u4Param_num = 0; + uint32_t u4Band_idx = 0; + uint32_t u4FC = 0; + uint32_t u4Dur = 0; + uint32_t u4Seq = 0; + uint32_t u4Gen_payload_rule = 0; + uint32_t u4Txlen = 0; + uint32_t u4Payload_len = 0; + uint8_t ucAddr1[MAC_ADDR_LEN]; + uint8_t ucAddr2[MAC_ADDR_LEN]; + uint8_t ucAddr3[MAC_ADDR_LEN]; + uint32_t ucPayload = 0; + + u4Len = ntohs(HqaCmdFrame->Length); + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4Param_num, HqaCmdFrame->Data + 4 * 1, 4); + u4Param_num = ntohl(u4Param_num); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 2, 4); + u4Band_idx = ntohl(u4Band_idx); + memcpy(&u4FC, HqaCmdFrame->Data + 4 * 3, 4); + u4FC = ntohl(u4FC); + memcpy(&u4Dur, HqaCmdFrame->Data + 4 * 4, 4); + u4Dur = ntohl(u4Dur); + memcpy(&u4Seq, HqaCmdFrame->Data + 4 * 5, 4); + u4Seq = ntohl(u4Seq); + memcpy(&u4Gen_payload_rule, HqaCmdFrame->Data + 4 * 6, 4); + u4Gen_payload_rule = ntohl(u4Gen_payload_rule); + memcpy(&u4Txlen, HqaCmdFrame->Data + 4 * 7, 4); + u4Txlen = ntohl(u4Txlen); + memcpy(&u4Payload_len, HqaCmdFrame->Data + 4 * 8, 4); + u4Payload_len = ntohl(u4Payload_len); + memcpy(ucAddr1, HqaCmdFrame->Data + 4 * 9, 6); + memcpy(ucAddr2, HqaCmdFrame->Data + 4 * 9 + 6 * 1, 6); + memcpy(ucAddr3, HqaCmdFrame->Data + 4 * 9 + 6 * 2, 6); + memcpy(&ucPayload, HqaCmdFrame->Data + 4 * 9 + 6 * 3, 1); + + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_txcontent_ext ext_id : %d\n", u4Ext_id); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_txcontent_ext param_num : %d\n", + u4Param_num); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_txcontent_ext band_idx : %d\n", + u4Band_idx); + /* Frame Control...0800 : Beacon */ + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_txcontent_ext FC : 0x%x\n", u4FC); + /* Duration....NAV */ + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_txcontent_ext dur : 0x%x\n", u4Dur); + /* Sequence Control */ + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_txcontent_ext seq : 0x%x\n", u4Seq); + /* Normal:0,Repeat:1,Random:2 */ + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_txcontent_ext gen_payload_rule : %d\n", + u4Gen_payload_rule); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_txcontent_ext txlen : %d\n", u4Txlen); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_txcontent_ext payload_len : %d\n", + u4Payload_len); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_txcontent_ext addr1:%02x:%02x:%02x:%02x:%02x:%02x\n", + ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], ucAddr1[4], + ucAddr1[5]); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_txcontent_ext addr2:%02x:%02x:%02x:%02x:%02x:%02x\n", + ucAddr2[0], ucAddr2[1], ucAddr2[2], ucAddr2[3], ucAddr2[4], + ucAddr2[5]); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_set_txcontent_ext addr3:%02x:%02x:%02x:%02x:%02x:%02x\n", + ucAddr3[0], ucAddr3[1], ucAddr3[2], ucAddr3[3], ucAddr3[4], + ucAddr3[5]); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_tx_ext payload : 0x%x\n", ucPayload); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + MT_ATESetMacHeader(prNetDev, u4FC, u4Dur, u4Seq); + MT_ATESetTxPayLoad(prNetDev, u4Gen_payload_rule, ucPayload); + MT_ATESetTxLength(prNetDev, u4Txlen); + MT_ATESetMACAddress(prNetDev, RF_AT_FUNCID_SET_MAC_ADDRESS, + ucAddr1); + MT_ATESetMACAddress(prNetDev, RF_AT_FUNCID_SET_TA, ucAddr2); + /* PeiHsuan Memo : No Set Addr3 */ + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (uint8_t *) &u4Ext_id, + sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + sizeof(u4Ext_id), + i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t hqa_start_tx_ext(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Ext_id = 0; + uint32_t u4Param_num = 0; + uint32_t u4Band_idx = 0; + uint32_t u4Pkt_cnt = 0; + uint32_t u4Phymode = 0; + uint32_t u4Rate = 0; + uint32_t u4Pwr = 0; + uint32_t u4Stbc = 0; + uint32_t u4Ldpc = 0; + uint32_t u4iBF = 0; + uint32_t u4eBF = 0; + uint32_t u4Wlan_id = 0; + uint32_t u4Aifs = 0; + uint32_t u4Gi = 0; + uint32_t u4Tx_path = 0; + uint32_t u4Nss = 0; + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4Param_num, HqaCmdFrame->Data + 4 * 1, 4); + u4Param_num = ntohl(u4Param_num); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 2, 4); + u4Band_idx = ntohl(u4Band_idx); + memcpy(&u4Pkt_cnt, HqaCmdFrame->Data + 4 * 3, 4); + u4Pkt_cnt = ntohl(u4Pkt_cnt); + memcpy(&u4Phymode, HqaCmdFrame->Data + 4 * 4, 4); + u4Phymode = ntohl(u4Phymode); + memcpy(&u4Rate, HqaCmdFrame->Data + 4 * 5, 4); + u4Rate = ntohl(u4Rate); + memcpy(&u4Pwr, HqaCmdFrame->Data + 4 * 6, 4); + u4Pwr = ntohl(u4Pwr); + memcpy(&u4Stbc, HqaCmdFrame->Data + 4 * 7, 4); + u4Stbc = ntohl(u4Stbc); + memcpy(&u4Ldpc, HqaCmdFrame->Data + 4 * 8, 4); + u4Ldpc = ntohl(u4Ldpc); + memcpy(&u4iBF, HqaCmdFrame->Data + 4 * 9, 4); + u4iBF = ntohl(u4iBF); + memcpy(&u4eBF, HqaCmdFrame->Data + 4 * 10, 4); + u4eBF = ntohl(u4eBF); + memcpy(&u4Wlan_id, HqaCmdFrame->Data + 4 * 11, 4); + u4Wlan_id = ntohl(u4Wlan_id); + memcpy(&u4Aifs, HqaCmdFrame->Data + 4 * 12, 4); + u4Aifs = ntohl(u4Aifs); + memcpy(&u4Gi, HqaCmdFrame->Data + 4 * 13, 4); + u4Gi = ntohl(u4Gi); + memcpy(&u4Tx_path, HqaCmdFrame->Data + 4 * 14, 4); + u4Tx_path = ntohl(u4Tx_path); + memcpy(&u4Nss, HqaCmdFrame->Data + 4 * 15, 4); + u4Nss = ntohl(u4Nss); + + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_tx_ext ext_id : %d\n", u4Ext_id); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_tx_ext param_num : %d\n", u4Param_num); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_tx_ext band_idx : %d\n", u4Band_idx); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_tx_ext pkt_cnt : %d\n", u4Pkt_cnt); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_tx_ext phymode : %d\n", u4Phymode); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_tx_ext rate : %d\n", u4Rate); + DBGLOG(RFTEST, INFO, "QA_AGENT hqa_start_tx_ext pwr : %d\n", + u4Pwr); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_tx_ext stbc : %d\n", u4Stbc); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_tx_ext ldpc : %d\n", u4Ldpc); + DBGLOG(RFTEST, INFO, "QA_AGENT hqa_start_tx_ext ibf : %d\n", + u4iBF); + DBGLOG(RFTEST, INFO, "QA_AGENT hqa_start_tx_ext ebf : %d\n", + u4eBF); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_tx_ext wlan_id : %d\n", u4Wlan_id); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_tx_ext aifs : %d\n", u4Aifs); + DBGLOG(RFTEST, INFO, "QA_AGENT hqa_start_tx_ext gi : %d\n", + u4Gi); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_tx_ext tx_path : %d\n", u4Tx_path); + DBGLOG(RFTEST, INFO, "QA_AGENT hqa_start_tx_ext nss : %d\n", + u4Nss); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + MT_ATESetTxCount(prNetDev, u4Pkt_cnt); + +#if 1 + if (u4Phymode == 1) { + u4Phymode = 0; + u4Rate += 4; + } else if ((u4Phymode == 0) && ((u4Rate == 9) + || (u4Rate == 10) || (u4Rate == 11))) + u4Phymode = 1; + MT_ATESetPreamble(prNetDev, u4Phymode); + + if (u4Phymode == 0) { + u4Rate |= 0x00000000; + + DBGLOG(RFTEST, INFO, + "QA_AGENT CCK/OFDM (normal preamble) rate : %d\n", + u4Rate); + + MT_ATESetRate(prNetDev, u4Rate); + } else if (u4Phymode == 1) { + if (u4Rate == 9) + u4Rate = 1; + else if (u4Rate == 10) + u4Rate = 2; + else if (u4Rate == 11) + u4Rate = 3; + u4Rate |= 0x00000000; + + DBGLOG(RFTEST, INFO, + "QA_AGENT CCK (short preamble) rate : %d\n", u4Rate); + + MT_ATESetRate(prNetDev, u4Rate); + } else if (u4Phymode >= 2 && u4Phymode <= 4) { + u4Rate |= 0x80000000; + + DBGLOG(RFTEST, INFO, "QA_AGENT HT/VHT rate : %d\n", u4Rate); + + MT_ATESetRate(prNetDev, u4Rate); + } +#endif + + MT_ATESetTxPower0(prNetDev, u4Pwr); + MT_ATESetTxSTBC(prNetDev, u4Stbc); + MT_ATESetEncodeMode(prNetDev, u4Ldpc); + MT_ATESetiBFEnable(prNetDev, u4iBF); + MT_ATESeteBFEnable(prNetDev, u4eBF); + /* PeiHsuan Memo : No Set Wlan ID */ + MT_ATESetTxIPG(prNetDev, u4Aifs); + MT_ATESetTxGi(prNetDev, u4Gi); + MT_ATESetTxVhtNss(prNetDev, u4Nss); + MT_ATESetTxPath(prNetDev, u4Tx_path); + MT_ATEStartTX(prNetDev, "TXFRAME"); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (uint8_t *) &u4Ext_id, + sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + sizeof(u4Ext_id), + i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t hqa_start_rx_ext(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Ext_id = 0; + uint32_t u4Param_num = 0; + uint32_t u4Band_idx = 0; + uint32_t u4Rx_path = 0; + uint8_t ucOwn_mac[MAC_ADDR_LEN]; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + uint32_t u4BufLen = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + memcpy(&u4Ext_id, HqaCmdFrame->Data, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4Param_num, HqaCmdFrame->Data + 4, 4); + u4Param_num = ntohl(u4Param_num); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 + 4, 4); + u4Band_idx = ntohl(u4Band_idx); + memcpy(ucOwn_mac, HqaCmdFrame->Data + 4 + 4 + 4, 6); + memcpy(&u4Rx_path, HqaCmdFrame->Data + 4 + 4 + 4 + 6, 4); + u4Rx_path = ntohl(u4Rx_path); + + memset(&g_HqaRxStat, 0, sizeof(struct PARAM_RX_STAT)); + + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_rx_ext ext_id : %d\n", u4Ext_id); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_rx_ext param_num : %d\n", u4Param_num); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_rx_ext band_idx : %d\n", u4Band_idx); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_rx_ext own_mac:%02x:%02x:%02x:%02x:%02x:%02x\n", + ucOwn_mac[0], ucOwn_mac[1], ucOwn_mac[2], ucOwn_mac[3], + ucOwn_mac[4], ucOwn_mac[5]); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_start_rx_ext rx_path : 0x%x\n", u4Rx_path); + + u4RxStatSeqNum = 0; + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_RX_PATH; + rRfATInfo.u4FuncData = u4Rx_path << 16 | u4Band_idx; + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + /* PeiHsuan Memo : No Set Own MAC Address */ + MT_ATEStartRX(prNetDev, "RXFRAME"); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (uint8_t *) &u4Ext_id, + sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + sizeof(u4Ext_id), + i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t hqa_stop_tx_ext(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Ext_id = 0; + uint32_t u4Param_num = 0; + uint32_t u4Band_idx = 0; + + memcpy(&u4Ext_id, HqaCmdFrame->Data, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4Param_num, HqaCmdFrame->Data + 4, 4); + u4Param_num = ntohl(u4Param_num); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 + 4, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_stop_tx_ext ext_id : %d\n", u4Ext_id); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_stop_tx_ext param_num : %d\n", u4Param_num); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_stop_tx_ext band_idx : %d\n", u4Band_idx); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + MT_ATEStopTX(prNetDev, "TXSTOP"); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (uint8_t *) &u4Ext_id, + sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t hqa_stop_rx_ext(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Ext_id = 0; + uint32_t u4Param_num = 0; + uint32_t u4Band_idx = 0; + + memcpy(&u4Ext_id, HqaCmdFrame->Data, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4Param_num, HqaCmdFrame->Data + 4, 4); + u4Param_num = ntohl(u4Param_num); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 + 4, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_stop_rx_ext ext_id : %d\n", u4Ext_id); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_stop_rx_ext param_num : %d\n", u4Param_num); + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_stop_rx_ext band_idx : %d\n", u4Band_idx); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + MT_ATEStopRX(prNetDev, "RXSTOP"); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (uint8_t *) &u4Ext_id, + sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +static int32_t HQA_iBFInit(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_iBFInit\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static int32_t HQA_iBFSetValue(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_iBFSetValue\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static int32_t HQA_iBFGetStatus(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_iBFGetStatus\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static int32_t HQA_iBFChanProfUpdate(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_iBFChanProfUpdate\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static int32_t HQA_iBFProfileRead(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_iBFProfileRead\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static int32_t HQA_IRRSetADC(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4WFIdx; + uint32_t u4ChFreq; + uint32_t u4BW; + uint32_t u4Sx; + uint32_t u4Band; + uint32_t u4Ext_id; + uint32_t u4RunType; + uint32_t u4FType; + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4WFIdx, HqaCmdFrame->Data + 4 * 1, 4); + u4WFIdx = ntohl(u4WFIdx); + memcpy(&u4ChFreq, HqaCmdFrame->Data + 4 * 2, 4); + u4ChFreq = ntohl(u4ChFreq); + memcpy(&u4BW, HqaCmdFrame->Data + 4 * 3, 4); + u4BW = ntohl(u4BW); + memcpy(&u4Sx, HqaCmdFrame->Data + 4 * 4, 4); + u4Sx = ntohl(u4Sx); + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 5, 4); + u4Band = ntohl(u4Band); + memcpy(&u4RunType, HqaCmdFrame->Data + 4 * 6, 4); + u4RunType = ntohl(u4RunType); + memcpy(&u4FType, HqaCmdFrame->Data + 4 * 7, 4); + u4FType = ntohl(u4FType); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_IRRSetADC ext_id : %d\n", + u4Ext_id); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetADC u4WFIdx : %d\n", u4WFIdx); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetADC u4ChFreq : %d\n", u4ChFreq); + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_IRRSetADC u4BW : %d\n", + u4BW); + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_IRRSetADC u4Sx : %d\n", + u4Sx); /* SX : 0, 2 */ + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_IRRSetADC u4Band : %d\n", + u4Band); + /* RunType : 0 -> QA, 1 -> ATE */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetADC u4RunType : %d\n", u4RunType); + /* FType : 0 -> FI, 1 -> FD */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetADC u4FType : %d\n", u4FType); + + i4Ret = MT_ATE_IRRSetADC(prNetDev, u4WFIdx, u4ChFreq, u4BW, + u4Sx, u4Band, u4RunType, u4FType); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (uint8_t *) &u4Ext_id, + sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +static int32_t HQA_IRRSetRxGain(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4PgaLpfg; + uint32_t u4Lna; + uint32_t u4Band; + uint32_t u4WF_inx; + uint32_t u4Rfdgc; + uint32_t u4Ext_id; + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4PgaLpfg, HqaCmdFrame->Data + 4 * 1, 4); + u4PgaLpfg = ntohl(u4PgaLpfg); + memcpy(&u4Lna, HqaCmdFrame->Data + 4 * 2, 4); + u4Lna = ntohl(u4Lna); + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 3, 4); + u4Band = ntohl(u4Band); + memcpy(&u4WF_inx, HqaCmdFrame->Data + 4 * 4, 4); + u4WF_inx = ntohl(u4WF_inx); + memcpy(&u4Rfdgc, HqaCmdFrame->Data + 4 * 5, 4); + u4Rfdgc = ntohl(u4Rfdgc); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetRxGain ext_id : %d\n", u4Ext_id); + /* PGA is for MT663, LPFG is for MT7615 */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetRxGain u4PgaLpfg : %d\n", u4PgaLpfg); + /* 5 : UH, 4 : H, 3 : M, 2 : L, 1 : UL */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetRxGain u4Lna : %d\n", u4Lna); + /* DBDC band0 or band1 */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetRxGain u4Band : %d\n", u4Band); + /* (each bit for each WF) */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetRxGain u4WF_inx : 0x%x\n", u4WF_inx); + /* only for */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetRxGain u4Rfdgc : %d\n", u4Rfdgc); + + i4Ret = MT_ATE_IRRSetRxGain(prNetDev, u4PgaLpfg, u4Lna, + u4Band, u4WF_inx, u4Rfdgc); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (uint8_t *) &u4Ext_id, + sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +static int32_t HQA_IRRSetTTG(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Ext_id; + uint32_t u4TTGPwrIdx; + uint32_t u4ChFreq; + uint32_t u4FIToneFreq; + uint32_t u4Band; + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4TTGPwrIdx, HqaCmdFrame->Data + 4 * 1, 4); + u4TTGPwrIdx = ntohl(u4TTGPwrIdx); + memcpy(&u4ChFreq, HqaCmdFrame->Data + 4 * 2, 4); + u4ChFreq = ntohl(u4ChFreq); + memcpy(&u4FIToneFreq, HqaCmdFrame->Data + 4 * 3, 4); + u4FIToneFreq = ntohl(u4FIToneFreq); + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 4, 4); + u4Band = ntohl(u4Band); + + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_IRRSetTTG ext_id : %d\n", + u4Ext_id); + /* TTG Power Index: Power index value 0~15 */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetTTG u4TTGPwrIdx : %d\n", u4TTGPwrIdx); + /* Ch Freq: channel frequency value */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetTTG u4ChFreq : %d\n", u4ChFreq); + /* FI Tone Freq(float): driver calculate TTG Freq(TTG Freq = Ch_freq + + * FI tone freq) + */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetTTG u4FIToneFreq : %d\n", u4FIToneFreq); + /* Band: DBDC band0 or band1 */ + DBGLOG(RFTEST, INFO, "QA_AGENT HQA_IRRSetTTG u4Band : %d\n", + u4Band); + + i4Ret = MT_ATE_IRRSetTTG(prNetDev, u4TTGPwrIdx, u4ChFreq, + u4FIToneFreq, u4Band); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (uint8_t *) &u4Ext_id, + sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +static int32_t HQA_IRRSetTrunOnTTG(struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Ext_id; + uint32_t u4TTGOnOff; + uint32_t u4Band; + uint32_t u4WF_inx = 0; + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4TTGOnOff, HqaCmdFrame->Data + 4 * 1, 4); + u4TTGOnOff = ntohl(u4TTGOnOff); + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 2, 4); + u4Band = ntohl(u4Band); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetTrunOnTTG ext_id : %d\n", u4Ext_id); + /* TTG on/off: 0:off, 1: on */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetTrunOnTTG u4TTGOnOff : %d\n", + u4TTGOnOff); + /* Band: DBDC band0 or band1 */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetTrunOnTTG u4Band : %d\n", u4Band); + /* (each bit for each WF) */ + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_IRRSetTrunOnTTG u4WF_inx : %d\n", u4WF_inx); + + i4Ret = MT_ATE_IRRSetTrunOnTTG(prNetDev, u4TTGOnOff, u4Band, + u4WF_inx); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (uint8_t *) &u4Ext_id, + sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +static HQA_CMD_HANDLER hqa_ext_cmd_set[] = { + NULL, + hqa_set_channel_ext, /* 0x00000001 */ + hqa_set_txcontent_ext, /* 0x00000002 */ + hqa_start_tx_ext, /* 0x00000003 */ + hqa_start_rx_ext, /* 0x00000004 */ + hqa_stop_tx_ext, /* 0x00000005 */ + hqa_stop_rx_ext, /* 0x00000006 */ + HQA_iBFInit, /* 0x00000007 */ + HQA_iBFSetValue, /* 0x00000008 */ + HQA_iBFGetStatus, /* 0x00000009 */ + HQA_iBFChanProfUpdate, /* 0x0000000A */ + HQA_iBFProfileRead, /* 0x0000000B */ + ToDoFunction, /* 0x0000000C */ + ToDoFunction, /* 0x0000000D */ + ToDoFunction, /* 0x0000000E */ + ToDoFunction, /* 0x0000000F */ + ToDoFunction, /* 0x00000010 */ + ToDoFunction, /* 0x00000011 */ + ToDoFunction, /* 0x00000012 */ + ToDoFunction, /* 0x00000013 */ + ToDoFunction, /* 0x00000014 */ + ToDoFunction, /* 0x00000015 */ + ToDoFunction, /* 0x00000016 */ + ToDoFunction, /* 0x00000017 */ + ToDoFunction, /* 0x00000018 */ + ToDoFunction, /* 0x00000019 */ + ToDoFunction, /* 0x0000001A */ + ToDoFunction, /* 0x0000001B */ + ToDoFunction, /* 0x0000001C */ + ToDoFunction, /* 0x0000001D */ + ToDoFunction, /* 0x0000001E */ + ToDoFunction, /* 0x0000001F */ + HQA_IRRSetADC, /* 0x00000020 */ + HQA_IRRSetRxGain, /* 0x00000021 */ + HQA_IRRSetTTG, /* 0x00000022 */ + HQA_IRRSetTrunOnTTG, /* 0x00000023 */ +}; + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Extension Commands (For MT7615). + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +static int32_t hqa_ext_cmds(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Ret = 0; + uint32_t u4Idx = 0; + + memmove((uint8_t *)&u4Idx, (uint8_t *)&HqaCmdFrame->Data, + 4); + u4Idx = ntohl(u4Idx); + + DBGLOG(RFTEST, INFO, "QA_AGENT hqa_ext_cmds index : %d\n", + u4Idx); + + if (u4Idx < (sizeof(hqa_ext_cmd_set) / sizeof(HQA_CMD_HANDLER))) { + if (hqa_ext_cmd_set[u4Idx] != NULL) { + /* valid command */ + i4Ret = (*hqa_ext_cmd_set[u4Idx])(prNetDev, + prIwReqData, HqaCmdFrame); + } else { + /* invalid command */ + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_ext_cmds cmd idx is NULL: %d\n", + u4Idx); + } + } else { + /* invalid command */ + DBGLOG(RFTEST, INFO, + "QA_AGENT hqa_ext_cmds cmd idx is not supported: %d\n", u4Idx); + } + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_CMD_SET6[] = { + /* cmd id start from 0x1600 */ + hqa_ext_cmds, /* 0x1600 */ +}; + +static struct HQA_CMD_TABLE HQA_CMD_TABLES[] = { + { + HQA_CMD_SET0, + sizeof(HQA_CMD_SET0) / sizeof(HQA_CMD_HANDLER), + 0x1000, + } + , + { + HQA_CMD_SET1, + sizeof(HQA_CMD_SET1) / sizeof(HQA_CMD_HANDLER), + 0x1100, + } + , + { + HQA_CMD_SET2, + sizeof(HQA_CMD_SET2) / sizeof(HQA_CMD_HANDLER), + 0x1200, + } + , + { + HQA_CMD_SET3, + sizeof(HQA_CMD_SET3) / sizeof(HQA_CMD_HANDLER), + 0x1300, + } + , + { + HQA_CMD_SET4, + sizeof(HQA_CMD_SET4) / sizeof(HQA_CMD_HANDLER), + 0x1400, + } + , + { + HQA_CMD_SET5, + sizeof(HQA_CMD_SET5) / sizeof(HQA_CMD_HANDLER), + 0x1500, + } + , +#if CFG_SUPPORT_TX_BF + { + HQA_TXBF_CMDS, + sizeof(HQA_TXBF_CMDS) / sizeof(HQA_CMD_HANDLER), + 0x1540, + } + , +#if CFG_SUPPORT_MU_MIMO + { + HQA_TXMU_CMDS, + sizeof(HQA_TXMU_CMDS) / sizeof(HQA_CMD_HANDLER), + 0x1560, + } + , +#endif +#endif + { + HQA_ICAP_CMDS, + sizeof(HQA_ICAP_CMDS) / sizeof(HQA_CMD_HANDLER), + 0x1580, + } + , + { + HQA_ReCal_CMDS, + sizeof(HQA_ReCal_CMDS) / sizeof(HQA_CMD_HANDLER), + 0x1581, + } + , + { + HQA_RXV_CMDS, + sizeof(HQA_RXV_CMDS) / sizeof(HQA_CMD_HANDLER), + 0x1582, + } + , + { + HQA_CMD_SET6, + sizeof(HQA_CMD_SET6) / sizeof(HQA_CMD_HANDLER), + 0x1600, + } + , +}; + +/*----------------------------------------------------------------------------*/ +/*! + * \brief QA Agent For Handle Ethernet command by Command Idx. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqData + * \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +int HQA_CMDHandler(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame) +{ + int32_t i4Status = 0; + uint32_t u4CmdId; + uint32_t u4TableIndex = 0; + + u4CmdId = ntohs(HqaCmdFrame->Id); + + while (u4TableIndex < (sizeof(HQA_CMD_TABLES) / sizeof( + struct HQA_CMD_TABLE))) { + int CmdIndex = 0; + + CmdIndex = u4CmdId - HQA_CMD_TABLES[u4TableIndex].CmdOffset; + if ((CmdIndex >= 0) + && (CmdIndex < HQA_CMD_TABLES[u4TableIndex].CmdSetSize)) { + HQA_CMD_HANDLER *pCmdSet; + + pCmdSet = HQA_CMD_TABLES[u4TableIndex].CmdSet; + + if (pCmdSet[CmdIndex] != NULL) + i4Status = (*pCmdSet[CmdIndex])(prNetDev, + prIwReqData, HqaCmdFrame); + break; + } + u4TableIndex++; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Ioctl entry from ATE Daemon. + * + * \param[in] prNetDev Pointer to the Net Device + * \param[in] prIwReqInfo + * \param[in] prIwReqData + * \param[in] pcExtra + * \param[out] None + * + * \retval 0 On success. + */ +/*----------------------------------------------------------------------------*/ +int priv_qa_agent(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN char *pcExtra) +{ + int32_t i4Status = 0; + struct HQA_CMD_FRAME *HqaCmdFrame; + uint32_t u4ATEMagicNum, u4ATEId, u4ATEData; + + HqaCmdFrame = kmalloc(sizeof(*HqaCmdFrame), GFP_KERNEL); + + if (!HqaCmdFrame) { + i4Status = -ENOMEM; + goto ERROR0; + } + + memset(HqaCmdFrame, 0, sizeof(*HqaCmdFrame)); + + if (copy_from_user(HqaCmdFrame, prIwReqData->data.pointer, + prIwReqData->data.length)) { + i4Status = -EFAULT; + goto ERROR1; + } + + u4ATEMagicNum = ntohl(HqaCmdFrame->MagicNo); + u4ATEId = ntohs(HqaCmdFrame->Id); + memcpy((uint8_t *)&u4ATEData, HqaCmdFrame->Data, 4); + u4ATEData = ntohl(u4ATEData); + + switch (u4ATEMagicNum) { + case HQA_CMD_MAGIC_NO: + i4Status = HQA_CMDHandler(prNetDev, prIwReqData, + HqaCmdFrame); + break; + default: + i4Status = -EINVAL; + DBGLOG(RFTEST, INFO, "QA_AGENT ATEMagicNum Error!!!\n"); + break; + } + +ERROR1: + kfree(HqaCmdFrame); +ERROR0: + return i4Status; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_rst.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_rst.c new file mode 100644 index 0000000000000..f787772d5a7fb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_rst.c @@ -0,0 +1,529 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** 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. + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include +#include + +#include "precomp.h" +#include "gl_rst.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + + + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +#if CFG_CHIP_RESET_SUPPORT +enum _ENUM_CHIP_RESET_REASON_TYPE_T eResetReason; +uint64_t u8ResetTime; + +#if CFG_CHIP_RESET_HANG +u_int8_t fgIsResetHangState = SER_L0_HANG_RST_NONE; +#endif + +#endif + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +#if CFG_CHIP_RESET_SUPPORT +static struct RESET_STRUCT wifi_rst; +u_int8_t fgIsResetting = FALSE; +#endif + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +#if CFG_CHIP_RESET_SUPPORT +static void mtk_wifi_reset(struct work_struct *work); + +#if CFG_WMT_RESET_API_SUPPORT +static void mtk_wifi_trigger_reset(struct work_struct *work); +static void *glResetCallback(enum ENUM_WMTDRV_TYPE eSrcType, + enum ENUM_WMTDRV_TYPE eDstType, + enum ENUM_WMTMSG_TYPE eMsgType, void *prMsgBody, + unsigned int u4MsgLength); +#else +static u_int8_t is_bt_exist(void); +static u_int8_t rst_L0_notify_step1(void); +static u_int8_t rst_L0_notify_step2(void); +static void wait_core_dump_end(void); +#endif +#endif + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#if CFG_CHIP_RESET_SUPPORT + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for + * 1. register wifi reset callback + * 2. initialize wifi reset work + * + * @param none + * + * @retval none + */ +/*----------------------------------------------------------------------------*/ +void glResetInit(struct GLUE_INFO *prGlueInfo) +{ +#if CFG_WMT_RESET_API_SUPPORT + /* 1. Register reset callback */ + mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_WIFI, + (PF_WMT_CB) glResetCallback); + + /* 2. Initialize reset work */ + INIT_WORK(&(wifi_rst.rst_trigger_work), + mtk_wifi_trigger_reset); +#endif + fgIsResetting = FALSE; + wifi_rst.prGlueInfo = prGlueInfo; + INIT_WORK(&(wifi_rst.rst_work), mtk_wifi_reset); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for + * 1. deregister wifi reset callback + * + * @param none + * + * @retval none + */ +/*----------------------------------------------------------------------------*/ +void glResetUninit(void) +{ +#if CFG_WMT_RESET_API_SUPPORT + /* 1. Deregister reset callback */ + mtk_wcn_wmt_msgcb_unreg(WMTDRV_TYPE_WIFI); +#endif +} +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is called for generating reset request to WMT + * + * @param None + * + * @retval None + */ +/*----------------------------------------------------------------------------*/ +void glSendResetRequest(void) +{ +#if CFG_WMT_RESET_API_SUPPORT + + /* WMT thread would trigger whole chip reset itself */ +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is called for checking if connectivity chip is resetting + * + * @param None + * + * @retval TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalIsResetting(void) +{ + return fgIsResetting; +} + + +u_int8_t glResetTrigger(struct ADAPTER *prAdapter, + uint32_t u4RstFlag, const uint8_t *pucFile, uint32_t u4Line) +{ + u_int8_t fgResult = TRUE; + uint16_t u2FwOwnVersion; + uint16_t u2FwPeerVersion; + + dump_stack(); + if (kalIsResetting()) + return fgResult; + + fgIsResetting = TRUE; + if (eResetReason != RST_BT_TRIGGER) + DBGLOG(INIT, STATE, "[SER][L0] wifi trigger eResetReason=%d\n", + eResetReason); + else + DBGLOG(INIT, STATE, "[SER][L0] BT trigger\n"); + +#if CFG_WMT_RESET_API_SUPPORT + if (u4RstFlag & RST_FLAG_DO_CORE_DUMP) + if (glIsWmtCodeDump()) + DBGLOG(INIT, WARN, "WMT is code dumping !\n"); +#endif + if (prAdapter == NULL) { + prAdapter = wifi_rst.prGlueInfo->prAdapter; + if (prAdapter == NULL) { + DBGLOG(INIT, ERROR, + "[SER][L0] Adapter is null, stop reset flow\n"); + return fgResult; + } + } + u2FwOwnVersion = prAdapter->rVerInfo.u2FwOwnVersion; + u2FwPeerVersion = prAdapter->rVerInfo.u2FwPeerVersion; + + DBGLOG(INIT, ERROR, + "Trigger chip reset in %s line %u! Chip[%04X E%u] FW Ver DEC[%u.%u] HEX[%x.%x], Driver Ver[%u.%u]\n", + pucFile, u4Line, MTK_CHIP_REV, + wlanGetEcoVersion(prAdapter), + (uint16_t)(u2FwOwnVersion >> 8), + (uint16_t)(u2FwOwnVersion & BITS(0, 7)), + (uint16_t)(u2FwOwnVersion >> 8), + (uint16_t)(u2FwOwnVersion & BITS(0, 7)), + (uint16_t)(u2FwPeerVersion >> 8), + (uint16_t)(u2FwPeerVersion & BITS(0, 7))); + + prAdapter->u4HifDbgFlag |= DEG_HIF_DEFAULT_DUMP; + halPrintHifDbgInfo(prAdapter); + +#if CFG_WMT_RESET_API_SUPPORT + wifi_rst.rst_trigger_flag = u4RstFlag; + schedule_work(&(wifi_rst.rst_trigger_work)); +#else + wifi_rst.prGlueInfo = prAdapter->prGlueInfo; + schedule_work(&(wifi_rst.rst_work)); +#endif + + return fgResult; +} + +void glGetRstReason(enum _ENUM_CHIP_RESET_REASON_TYPE_T + eReason) +{ + if (kalIsResetting()) + return; + + u8ResetTime = sched_clock(); + eResetReason = eReason; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is called for wifi reset + * + * @param skb + * info + * + * @retval 0 + * nonzero + */ +/*----------------------------------------------------------------------------*/ +static void mtk_wifi_reset(struct work_struct *work) +{ + struct RESET_STRUCT *rst = container_of(work, + struct RESET_STRUCT, rst_work); + u_int8_t fgResult = FALSE; + +#if CFG_WMT_RESET_API_SUPPORT + wifi_reset_end(rst->rst_data); +#else + fgResult = rst_L0_notify_step1(); + + wait_core_dump_end(); + + fgResult = rst_L0_notify_step2(); + +#if CFG_CHIP_RESET_HANG + if (fgIsResetHangState == SER_L0_HANG_RST_NONE) + fgIsResetHangState = SER_L0_HANG_RST_TRGING; +#endif + + if (is_bt_exist() == FALSE) + kalRemoveProbe(rst->prGlueInfo); + +#endif + + DBGLOG(INIT, STATE, "[SER][L0] flow end, fgResult=%d\n", fgResult); + +} + + +#if CFG_WMT_RESET_API_SUPPORT + +static void mtk_wifi_trigger_reset(struct work_struct *work) +{ + u_int8_t fgResult = FALSE; + struct RESET_STRUCT *rst = container_of(work, + struct RESET_STRUCT, rst_trigger_work); + + fgIsResetting = TRUE; + /* Set the power off flag to FALSE in WMT to prevent chip power off + * after wlanProbe return failure, because we need to do core dump + * afterward. + */ + if (rst->rst_trigger_flag & RST_FLAG_PREVENT_POWER_OFF) + mtk_wcn_set_connsys_power_off_flag(FALSE); + + fgResult = mtk_wcn_wmt_assert_timeout(WMTDRV_TYPE_WIFI, 0x40, 0); + DBGLOG(INIT, INFO, "reset result %d, trigger flag 0x%x\n", + fgResult, rst->rst_trigger_flag); +} + +/* Weak reference for those platform doesn't support wmt functions */ +u_int8_t __weak mtk_wcn_stp_coredump_start_get(void) +{ + return FALSE; +} + + +/*0= f/w assert flag is not set, others=f/w assert flag is set */ +u_int8_t glIsWmtCodeDump(void) +{ + return mtk_wcn_stp_coredump_start_get(); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is invoked when there is reset messages indicated + * + * @param eSrcType + * eDstType + * eMsgType + * prMsgBody + * u4MsgLength + * + * @retval + */ +/*----------------------------------------------------------------------------*/ +static void *glResetCallback(enum ENUM_WMTDRV_TYPE eSrcType, + enum ENUM_WMTDRV_TYPE eDstType, + enum ENUM_WMTMSG_TYPE eMsgType, void *prMsgBody, + unsigned int u4MsgLength) +{ + switch (eMsgType) { + case WMTMSG_TYPE_RESET: + if (u4MsgLength == sizeof(enum ENUM_WMTRSTMSG_TYPE)) { + enum ENUM_WMTRSTMSG_TYPE *prRstMsg = + (enum ENUM_WMTRSTMSG_TYPE *) prMsgBody; + + switch (*prRstMsg) { + case WMTRSTMSG_RESET_START: + DBGLOG(INIT, WARN, "Whole chip reset start!\n"); + wifi_reset_start(); + break; + + case WMTRSTMSG_RESET_END: + DBGLOG(INIT, WARN, "Whole chip reset end!\n"); + fgIsResetting = FALSE; + wifi_rst.rst_data = RESET_SUCCESS; + schedule_work(&(wifi_rst.rst_work)); + break; + + case WMTRSTMSG_RESET_END_FAIL: + DBGLOG(INIT, WARN, "Whole chip reset fail!\n"); + fgIsResetting = FALSE; + wifi_rst.rst_data = RESET_FAIL; + schedule_work(&(wifi_rst.rst_work)); + break; + + default: + break; + } + } + break; + + default: + break; + } + + return NULL; +} +#else +static u_int8_t is_bt_exist(void) +{ + typedef int (*p_bt_fun_type) (int); + p_bt_fun_type bt_func; + char *bt_func_name = "WF_rst_L0_notify_BT_step1"; + + bt_func = (p_bt_fun_type) kal_kallsyms_lookup_name(bt_func_name); + if (bt_func) + return TRUE; + + DBGLOG(INIT, ERROR, "[SER][L0] %s does not exist\n", bt_func_name); + return FALSE; +} + +static u_int8_t rst_L0_notify_step1(void) +{ + if (eResetReason != RST_BT_TRIGGER) { + typedef int (*p_bt_fun_type) (int); + p_bt_fun_type bt_func; + char *bt_func_name = "WF_rst_L0_notify_BT_step1"; + + DBGLOG(INIT, STATE, "[SER][L0] %s\n", bt_func_name); + bt_func = + (p_bt_fun_type) kal_kallsyms_lookup_name(bt_func_name); + if (bt_func) { + bt_func(0); + } else { + DBGLOG(INIT, ERROR, + "[SER][L0] %s does not exist\n", bt_func_name); + return FALSE; + } + } + + return TRUE; +} + +static u_int8_t rst_L0_notify_step2(void) +{ + +#ifdef CFG_SUPPORT_CONNAC2X + if (eResetReason == RST_BT_TRIGGER) { + typedef void (*p_bt_fun_type) (void); + p_bt_fun_type bt_func; + char *bt_func_name = "WF_rst_L0_notify_BT_step2"; + + bt_func = + (p_bt_fun_type) kal_kallsyms_lookup_name(bt_func_name); + if (bt_func) { + bt_func(); + } else { + DBGLOG(INIT, WARN, "[SER][L0] %s does not exist\n", + bt_func_name); + return FALSE; + } + } else { + /* if wifi trigger, then wait bt ready notify */ + DBGLOG(INIT, WARN, "[SER][L0] not support..\n"); + } +#else + typedef int (*p_bt_fun_type) (void); + p_bt_fun_type bt_func; + char *bt_func_name = "WF_rst_L0_notify_BT_step2"; + + DBGLOG(INIT, STATE, "[SER][L0] %s\n", bt_func_name); + bt_func = + (p_bt_fun_type) kal_kallsyms_lookup_name(bt_func_name); + if (bt_func) { + bt_func(); + } else { + DBGLOG(INIT, WARN, "[SER][L0] %s does not exist\n", + bt_func_name); + return FALSE; + } +#endif + return TRUE; +} + +static void wait_core_dump_end(void) +{ +#ifdef CFG_SUPPORT_CONNAC2X + if (eResetReason == RST_OID_TIMEOUT) + return; + DBGLOG(INIT, WARN, "[SER][L0] not support..\n"); +#endif +} + +int32_t BT_rst_L0_notify_WF_step1(int32_t reserved) +{ + glGetRstReason(RST_BT_TRIGGER); + GL_RESET_TRIGGER(NULL, RST_FLAG_CHIP_RESET); + + return 0; +} +EXPORT_SYMBOL(BT_rst_L0_notify_WF_step1); + +int32_t BT_rst_L0_notify_WF_step2(int32_t reserved) +{ + DBGLOG(INIT, WARN, "[SER][L0] not support...\n"); + + return 0; +} +EXPORT_SYMBOL(BT_rst_L0_notify_WF_step2); + +#endif + + +#else + +u_int8_t kalIsResetting(void) +{ + return FALSE; +} + +#endif + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_sec.o.new b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_sec.o.new new file mode 100644 index 0000000000000000000000000000000000000000..0756dd14f46395dfcdf67ae6ef41c2c0d3563772 GIT binary patch literal 19504 zcmchf3wTu3x%b!3Op+m)2POn00_s2l1c+fGL8G7q0fj@r+`y>8BqV{Pgk(%65Grbr zpi!a*!BZ?)rUfe=u+mDat@M}*6%@26*iy0WOolXGsK*|$atfO7|6lvvGei2dPcPqh z_VcX#)_YlNz3Z~~UVHC>`)23eWEh6B4nw7@h@{k-tF$FHTO(bKP$?>*%O6xHul&%y zH?LcHkXPy>!?UhixsUfKRTw(o*Eigz$^&ZGQyvk#wF4U=%KSZ+bPk(2|;XF3K+v(}- zQTd%cE?4J=)g}I5rNbYrn&S`F9rg$N+J7GEYdIL|+tn57t2r9#Ydsw5^BxNI`QHfj z6~i_QHal$PuZ8*!!d?np9&}FVjvfuAxA}wPeE#5so&Mm3tnEExtNg*(;`X3@)`LN1 ze>mto_&~6={QhoFd18+$f4s-(O$)@8j|-^sv4K8+T=&>^e{d|y_q95@`@HepW9yFh zCisu{I$DqS#(R(V#??I>w0Az<5Taf0Zp&oZ&+0Dq$O4Ie(|A9K4(RFqqwqGC}K{}KX7|@A04`u}H<>Ld+ zf1pm6`~Gf6JNw=qj8}+lkUQWhAJMZc5&3v`AP(zencW?D25XCRYt3sp=D4o~bF~F? zm5zDK!F+LEJ6{j=xnB+Sc@9M8m-EUww&oV|%K7EIj^FGLj!yFjQ?s$2?dvd~_hW7! z3dZ^#3_87Qdkojw4;;B`d(w~1>;Ck4u0br?sP*S4$J%S{?6G@0dzRMtgEg4%zQb5c zC0J)&Xs7D6(6Scj>Y&RZctDx$W@7ywpLq*;|7( zqqg_dV9my1T>oFJ&Dead>x@9}ZDRtx|Kggo=Z@2Bv3G7-p!Z)~i_Wfbf!^1#2Fnqb zUV~%*={2a-xIj+%_MYAW?m#cr9oL`AUyEzY+7F#dvwJtzBGgCXsdDY8rgVdb zkL}RKLpQ+f4^mFZ_Xh`cIlAq+TYJ*)hi|z*G#J-WS72z*G|z~hfu7WW%VY1!LEZ@+ zWhdlp$PSSmkUfy?BHJN%btU$&{;n?gsYN*dBJCRG4|Kco*LS;e+qzHp^<8IoZ|!lQ zZHMdr0IvNZN9)6ZY3_NrR;!O}>SV7i_nls)(gHU1vtHg4oVbRcLpffvt#e18H@}Wt zw~a3JMdgQLRB5t8e`9j}L0h>$c%xG9@qU8)M6$~FCmZ>G+w~Z)b834}jB9Ooj61K} zyK--F!dJt#(%1aV(Vi1D20 zjp;hpYv7v1`1L)=?GHLVhzsk$iSe+(57z|ryCBq!bubKdIWc!tp6xx4XN?N97i{c_ zMHyTsK4Lw}^A7HfMf%>D!}#6R0mjPs8G9`H+=TeGKk8SWcfJ+i-MGI_j&T-*oG$;j4Ohnt3i07ynGzmHH^$NJw?XGf@7msz?m{dx zHul7T%T<7aC&+DG?);zst>|J@?Ttlksk)EL#_iXoeoG06RVv{!Y z4pH;E4OeSG4Jqh}b-mhaaQ&-=p)WWdSo6x$)-wci;n8~$rQC?o6Jw6c|F0O&eD$xz z=s}ELiP74-aSVChU7-q+W3Z0mW$a?n6`qG~%)JZa=EAseoQ@y{C;H8O9qVJijU;2t zz~n^Rz!3wJjKPL0PN|q=!!|H6@w&vRi3Wz=mY{3{Da=jI!P#X`Q;CT;pny`bgOHsI zm$?C8eC%Q3Bkvk{Mra z977rytFn?~5bB_8W)PK2YmiBbt~gR+u*89ISq@uRt4}OFB+@XgLnBR7yhOT{$Vekq z4uhAB3+qUUh)P`=5m>`;!D5b_EqL5N!qy2EF)T0P}dQ_|E z()g%WAx@A^F$jngbziX7G9sOw?xaN>!wh4s;;rv8*!O8eX%@lgZpv9REUS+Ij22NFU+F&|eiDHROS&(T=Y`V(I)g!}5Rl-UB#gSn`6`{z$k04Ay8uS_d z7)2_9tr!Nl0#_F1J8a$g0-(qKf zf|T4B7L9@-jmu%8*PAdo8>| zkT^bmR*n&6wMoWn&>C+T3@-z#=m5l5VIMNDdNuS6@efexsNT>88Gj!B7;mtGWaJp+ z(MXUwI~IB!q?T^i5`xsyIxQhcE$z_~g4EKxkQn4q-PR>}Xu>$F=aA9m;_Ube9?v1# z!FpMpWrXPzv!OS%SU~X$_UkO8YM|%~Tena=uB|NlBZ$MUruZk;8nZEX*cdkY1p_cj zhE0qJ1u2hGcaFtUo`__(g|nB=qWAx>Rc>uAvc&$2Ssjg6$8L4b(w1MldQXRO@WT7Hl+tuZ~x5L25?tt!cp4^ZR z0&SGJF2w#Ep%-Tbqie>U;YgZQIH z^TgQ;?=B=`vhf(bZ$$m6mNJbe531$4Lnmx5==ftex>^`W$-ujS8_@Kq8f284ReI1r z-X4wV#&4}E$IO93svAqEayWUBj2VX6rllCiHXBhRj#&Fa{JqS$oo(SY4M$Gl+PD?w zCZu#ddN=9OGxE)`yGf76&tWyk&a|GSw;sEj433>q#F3k$eLsebMy7I#N)3Yz_>jJW zS{KuelwQ--O{?{5X6hph{3>PtYM8rI2ap8hs8u^30( zXBp72?@(LVYif~?<26K=yAiGZl~(9<`uoH5G0uhElQC zRPf9jJ_djC(FeICWh`P9jZ2_0B%oa6hx6=OWw{Mf8N3P^Ee}PxEkiy--xXK;`>R*8 z(yzbRU;Q$BdG}lW)G7y~7^4=k1>;YjC*UtmH3*rRlU7t$)mHebmrrVHXl|^mp0vEW zvA())QdMK^%Ie0ZNtF#NmNY|x*Tj1eLKi< zTfpJqHZTeFgKT#vNc%33?d<^vgL}okPvnoE_8=gN$RO z&<(O&n#dW#VquBc%SEmMZB6W19de^UZbwW_i)hw_HLb|8_iZ3sZ5MV3J3-FZW|6lD zxecMeU+gnRnv9OQXc1-if*(bs{j&nvPIWIZh)<6Hx>Tq{VwHjw>n7kdZDb~b}7$Biic zwt;MCC#cVF(eD8VLBAK|xa<@AOCbICgRJK$$a>C#tp6Oyc$D4L+l3C0{dI|)BFqI@ zZWhRLd7{r37K1ETDsq*u17x{Qkma_B-Y?t5Yk`|Evy2nD3DEE{fgaPqkzg+91m}pH57J%^vW6;YYNraIdgScue>{$oc{x>pLUz1(46ym=|oAt_FvI9JdsZ zEpUHGIR|9PT#!A>2U)HdJ&5iyqz!s2G)B$oTw}70I!ysc1fb{21hI($r*%v2Bc^XK+ zVvv62B6By*`r1K`Ne4*(Eg<{8O=NC@ZQs3*F5C;>4Sou;stX{iwqu*ZVd8d|p=NON z2YNsb=QNP3Ay;JXQf(V_mE5dufoU_yD*Yg<+y$~qZctg}QIJ)g09n;Zk-68jeWJ&b zTh6^O>32PbaVc)hF{l%Njq?K|dnbm5{fn3UXvnMS=QCm_F8k)n3IAz7 z@E^01$Ig8q?#XR8=AYg8Ut7LDxj1p=AAYfC$>|qHKKr`kgC|;lxB1V_k4^vX&GFA% z_^fHzPuATw?b6?`zhzg=^0hy>tLnWC=RO`Z&%5ZUDVL`WytA_8?eB~ky=JO0s^!5G z>ZV(_A0JnkcXdp!|KQdw4>=^N!;<5PDh6fJ0Y_tZ7BfBWU5lWcuoYg|!xN5LZ_o`3x1-|W9H>DQ$* zu5jIcGT~=g?N7gX_fN0%9UJ^o&%V76)qdmOod3S+-s&I!alp^(Uu#SG^qw=sBBj?{VJ*Rfb9mVVKUFH4uH#c?s^heL{`t>_U4u1YgZy+hb zcHzpgSES6nacXw;oww$%{d!Z~Q~&;0`;ULHd*{1v9qRhyN1^u<;`+{wA3b8o>>IA} zRNP*achAa(nkOIM(DuXcJ>!4-jRX7t@cZAL91wHgw%liyGU;#zYA$A@(&=bLGmCSLUKWW8_11+ z3epZF)-?s`4y5%+Iq>-&_%srIaJf~uov2kv$C3DSb{EnUNLL`yMjytyPV#sqttN}^ zYA^|j<+xw{spMIAA`<(03TZVG{nC)GMEVWVV@R(evEQuw>q0)4PCzQVwWh&c(OB(X z-OxO}OwBKza_v=FWizT~czxB4Wo7ey^UBIn(-vG$#|oe2+33dm#OlVS6_wQ}l$$zj z{({+MWks{*Hk6fBR;G@*bL@f}rmM0!4XfNMnk#GERSnfmY{6aG(BwmjvU=ad)ZEn6 z)Cm*PZd}lETk*m>Q}4|(3pCVKSlDe8u79T~{XN^s6f8W@8mmy~FqL0lKTspJwCS)9EBKlH?`p-9XUhSrB!s{NsPioj?R`6 zoZ{%h^kfJqTnumokZlFp%q;%ug9ST~P$jWhXG;mresq=e+@sB`SRYi4#Dp2DP&CQ| zagJ6k;=|WAGt1|xPt9xw7Zj4ApWSsaKmMLTGSoso64q$Pg?xtNlL@ri3xE7bCy@+Q z%xlp{(5ArZ($-S0Wj@1R(X(Bf!$U?D_pXL2h^~)Y`lwOlPX4r3E#l_fqYEtJ zetV6XjcD%I%$k&d=rD4bLD5k)gqa7EO z0^77>DR=Q^jp0$ugLSiZEaEc?_wQJ3+_amH;oej9=x7!bIXYWP@Z66cI(p`5b3VaM zH|Cc+UwTGOH68P{wSX|K{BWd?h_#Sb?%54h5~-#n+L1edLls4=MbXwySYy;iMbd@Q zTCUVv2ivgg7{isfLUjTO3y-^hGsf`fbwK6R1r`yeHQY4CS=zdo$kW+Ug1g@6A){xV zHs=%VI$OX!GCiXf939I|E3r*yOCyfq$Rafsvc^{JSWI;2Y#~viD=&@|53ip{@uEoa zMJ&!I5sWlp#>V$}`tU=QW`-N7F?_1f%4Zd_nfyqZ@S019g-;wf1Bf{~ zTS)j!t<^Lm>C~#l#1@?`C3q8w9%*{+(dKYuR2|f+@TKqs#7{3)u_8MXul@j^LwNNE zcn^whf}U<|4mUwnj#h=6m;T^o&|B zbmXHCR797~mPQ=I>xGW{wY4x}4F?-(uZZpK(~iZ&L7gok%%;Ojh~h{c&0->5XG;m* zWTSgS&so}>Pk42x9<#wY88qt+S=X z8B&3>_}_; z&5Ct86fJ3JQM!3cGjpB{a8sdq7#IZ#)0=Xa@}G2ZeFm^J=2|?nVsp;A#+CS zFgxHa%|3>1PAVom`pomznX}(7;4HfK$SF5-HJktzX&@E#rG(wJA3?n8i)9ovh5PXxF8U z6)WIt)>GF|8Ex}6FR6zW4M&=)XsoDTMwMCOVhPo&Oq?StshpV3&BQh@H`pD%=o~VOu z@tBB2|7gEl$kt)C>w&^5LmTT`XkJjYt7W^fpWhQs^RA?wqHH%HAKj0fX{ZyOXFoUw zRzG-ex9Ub#)egmbvZ#WVZ2@diYSn^3_M&5~kNvaiTY@~xSfL-pYUMXK>#+KJClt~3 zrO!ir(6K%arB&b8kY{~YA@T5yQtCg=to}+41#GmZZxb@Q@ht=+C$kFZApj~Tz zquYHLeo@7hJ5A|LpjDq`d$ONjAOm}O%NS+jJHzO9Q}WDlV}D&pR)3$1Dub-DXDa1p zMh>g$XCX(|=SF?3hxH9cvg+H9yj2ESm4^DtnUTY?y#bkdu0tMe@Ov|A-e_ZbR|x2% zAj@pelCAoF3kBA^*V0$QZ@eXdmS2+T7q)c3?~||;@uPoKIBFkWuKLlyaOioCvA^s; z$HY3^^^69tQ}1M zI-b~3vag@)3@<>_pN|L8{(Jk$++|1G?cqU)9(|5y0)873cGbNLyJ~fUo^wu1D`c~E z@ds>p#dxv59p4tsgKNaVd`$AAy{IOFjgV^Sx8-d4Ye zGS?~JhFbCnzM#+&MCZ$!Vw5oo4a%(51cbArcjb(WM7unrM9t^@y16BcS zEw~Ae67{w&dhdAAhP2;CF{}TM?k~1@llyyQ_g75muP~p?5R!g8G54L;0|AM>ZS;=Q z%Il{vJLWqEHvl)T17w;oU04N<#C6?A;zJW(&yl=N#NZOvMxtE1kk<$5`O7-$c|D-) zB_Z?tr|c3AA))7aPyIgOOQPrbPQ63OeMk&qaFXffH!zZC1Bt3s4A#VD!cin*87p?~ z3FwzATp;B4CF<`It`xQlc`nfI7w!?hBs?K}Psp1A{dpf@Jp92lc^#RC-MX+u^rgab z(XSBRPokcO#QunIqu9SG_MIX>EAlHM|4P^+{7h&d7RJFJ+>>KSw8PI1jFaaXnN2cY zA@`S*`2%(O^YuSvzW*m57H$!KSI93EwDULUEcX_P^p5bCB<#NO_ z!v%)@8%RP<7Ws0KQ$@}cdAi6&B4|#xuYH+A*#qwheW>Se!pVuk$-=3^nZkL(BH-!XVrN~o+*9&J0=L_}y3i-t%R|{7Nn}zoX*9#vJJ|TQc__Xjj;SYtc2oDM07XDfo z5`HZFOn6>svzh%%6ebJx{R}>-B2N@f7ETq;6wVVC3GWbA3YQD@eGc{BE%G|y2H_^* zR^bleZs7~UmxTv}M})_Pr-UKl$HLEq=Y=+08#urEehBhkd{Nf-Loik3iNeXkslu7U zdBP&$9l}bXb>D0f`EKDl;RfL*;a1@e;cnpz!k2{yghzzOg{Ooe;m5+ygy)4exi8`0 z66<~^3r7f3g%gF7g;Rwyh4X|(!aIbO!sWsy;oZV@!VSVr!mYv`!rj6bgf9yZ2#*Ml z3r`7qgntlzA?y>z^L~bT9wfX}I7&EPm?gYcI72vBSRlMj$baa?dTWJu3Hgt-s9!65 zNVrk>r10CqXNBJv{#f`k;p@V;g{Ooe;m5+yg#5>2Y~RNFBbX>m7LE|63i(gJ=r>t7 zRXAHXU&!xX^eY$E2))7iq!xXNjCAEEbjutAzTw6aIW3!FJXN+k|@G z0R1;a-Y$Gb_`Hz+%!=h-5gro$Lij6Tx9}t3e+&OCjN$Vv>PZj|77iDV7G5cwBIJ+5 zV(>8AF6xJDxqCeRp^LMb6_46$3*7NKdvGY9-?fN+tb{!|=qhjZe(`d(Oq4+-sSaeCd F{|DzCfT#cf literal 0 HcmV?d00001 diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_vendor.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_vendor.c new file mode 100644 index 0000000000000..d3484c6604f32 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_vendor.c @@ -0,0 +1,1407 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** gl_vendor.c + ** + ** + */ + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "gl_os.h" +#include "debug.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "precomp.h" +#include +#include +#include +#include "gl_cfg80211.h" +#include "gl_vendor.h" +#include "wlan_oid.h" + +#if KERNEL_VERSION(3, 16, 0) <= LINUX_VERSION_CODE + +/******************************************************************************* + * 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 + ******************************************************************************* + */ +uint8_t g_GetResultsBufferedCnt; +uint8_t g_GetResultsCmdCnt; + +static struct nla_policy nla_parse_wifi_policy[ + WIFI_ATTRIBUTE_ROAMING_STATE + 1] = { + [WIFI_ATTRIBUTE_BAND] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_NUM_CHANNELS] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_CHANNEL_LIST] = {.type = NLA_UNSPEC}, + + [WIFI_ATTRIBUTE_NUM_FEATURE_SET] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_FEATURE_SET] = {.type = NLA_UNSPEC}, + [WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI] = {.type = NLA_UNSPEC}, + [WIFI_ATTRIBUTE_NODFS_VALUE] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_COUNTRY_CODE] = {.type = NLA_STRING}, + + [WIFI_ATTRIBUTE_MAX_RSSI] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_MIN_RSSI] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_RSSI_MONITOR_START] = {.type = NLA_U32}, + + [WIFI_ATTRIBUTE_ROAMING_CAPABILITIES] = {.type = NLA_UNSPEC}, + [WIFI_ATTRIBUTE_ROAMING_BLACKLIST_NUM] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_ROAMING_BLACKLIST_BSSID] = {.type = NLA_UNSPEC}, + [WIFI_ATTRIBUTE_ROAMING_WHITELIST_NUM] = {.type = NLA_U32}, + [WIFI_ATTRIBUTE_ROAMING_WHITELIST_SSID] = {.type = NLA_UNSPEC}, + [WIFI_ATTRIBUTE_ROAMING_STATE] = {.type = NLA_U32}, +}; + +static struct nla_policy nla_parse_offloading_policy[ + MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC + 1] = { + [MKEEP_ALIVE_ATTRIBUTE_ID] = {.type = NLA_U8}, + [MKEEP_ALIVE_ATTRIBUTE_IP_PKT] = {.type = NLA_UNSPEC}, + [MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN] = {.type = NLA_U16}, + [MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR] = {.type = NLA_UNSPEC}, + [MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR] = {.type = NLA_UNSPEC}, + [MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC] = {.type = NLA_U32}, +}; + +static struct nla_policy nla_get_preferred_freq_list_policy[ + WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_MAX] = { + [WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_IFACE_TYPE] = {.type = NLA_U32}, +}; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +int mtk_cfg80211_NLA_PUT(struct sk_buff *skb, int attrtype, + int attrlen, const void *data) +{ + if (unlikely(nla_put(skb, attrtype, attrlen, data) < 0)) + return 0; + return 1; +} + +int mtk_cfg80211_nla_put_type(struct sk_buff *skb, + enum ENUM_NLA_PUT_DATE_TYPE type, int attrtype, + const void *value) +{ + u8 u8data = 0; + u16 u16data = 0; + u32 u32data = 0; + u64 u64data = 0; + + switch (type) { + case NLA_PUT_DATE_U8: + u8data = *(u8 *)value; + return mtk_cfg80211_NLA_PUT(skb, attrtype, sizeof(u8), + &u8data); + case NLA_PUT_DATE_U16: + u16data = *(u16 *)value; + return mtk_cfg80211_NLA_PUT(skb, attrtype, sizeof(u16), + &u16data); + case NLA_PUT_DATE_U32: + u32data = *(u32 *)value; + return mtk_cfg80211_NLA_PUT(skb, attrtype, sizeof(u32), + &u32data); + case NLA_PUT_DATE_U64: + u64data = *(u64 *)value; + return mtk_cfg80211_NLA_PUT(skb, attrtype, sizeof(u64), + &u64data); + default: + break; + } + + return 0; +} + +int mtk_cfg80211_vendor_get_channel_list(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + struct GLUE_INFO *prGlueInfo; + struct nlattr *attr; + uint32_t band = 0; + uint8_t ucNumOfChannel, i, j; + struct RF_CHANNEL_INFO *aucChannelList; + uint32_t num_channels; + uint32_t channels[MAX_CHN_NUM]; + struct sk_buff *skb; + uint16_t u2CountryCode; + + ASSERT(wiphy && wdev); + if ((data == NULL) || !data_len) + return -EINVAL; + + DBGLOG(REQ, TRACE, "data_len=%d, iftype=%d\n", data_len, wdev->iftype); + + attr = (struct nlattr *)data; + if (attr->nla_type == WIFI_ATTRIBUTE_BAND) + band = nla_get_u32(attr); + + DBGLOG(REQ, TRACE, "Get channel list for band: %d\n", band); + +#if CFG_ENABLE_UNIFY_WIPHY + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); +#else /* CFG_ENABLE_UNIFY_WIPHY */ + if (wdev == gprWdev) /* wlan0 */ + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + else + prGlueInfo = *((struct GLUE_INFO **) wiphy_priv(wiphy)); +#endif /* CFG_ENABLE_UNIFY_WIPHY */ + + if (!prGlueInfo) + return -EFAULT; + + aucChannelList = (struct RF_CHANNEL_INFO *) + kalMemAlloc(sizeof(struct RF_CHANNEL_INFO)*MAX_CHN_NUM, + VIR_MEM_TYPE); + if (!aucChannelList) { + DBGLOG(REQ, ERROR, + "Can not alloc memory for rf channel info\n"); + return -ENOMEM; + } + kalMemZero(aucChannelList, + sizeof(struct RF_CHANNEL_INFO)*MAX_CHN_NUM); + + switch (band) { + case 1: /* 2.4G band */ + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_2G4, TRUE, + MAX_CHN_NUM, &ucNumOfChannel, aucChannelList); + break; + case 2: /* 5G band without DFS channels */ + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_5G, TRUE, + MAX_CHN_NUM, &ucNumOfChannel, aucChannelList); + break; + case 4: /* 5G band DFS channels only */ + rlmDomainGetDfsChnls(prGlueInfo->prAdapter, MAX_CHN_NUM, + &ucNumOfChannel, aucChannelList); + break; + default: + ucNumOfChannel = 0; + break; + } + + kalMemZero(channels, sizeof(channels)); + u2CountryCode = prGlueInfo->prAdapter-> + rWifiVar.rConnSettings.u2CountryCode; + for (i = 0, j = 0; i < ucNumOfChannel; i++) { + /* We need to report frequency list to HAL */ + channels[j] = + nicChannelNum2Freq(aucChannelList[i].ucChannelNum) / 1000; + if (channels[j] == 0) + continue; + else if ((u2CountryCode == COUNTRY_CODE_TW) && + (channels[j] >= 5180 && channels[j] <= 5260)) { + /* Taiwan NCC has resolution to follow FCC spec + * to support 5G Band 1/2/3/4 + * (CH36~CH48, CH52~CH64, CH100~CH140, CH149~CH165) + * Filter CH36~CH52 for compatible with some old + * devices. + */ + DBGLOG(REQ, TRACE, "skip channels[%d]=%d, country=%d\n", + j, channels[j], u2CountryCode); + continue; + } else { + DBGLOG(REQ, TRACE, "channels[%d] = %d\n", j, + channels[j]); + j++; + } + } + num_channels = j; + DBGLOG(REQ, INFO, "Get channel list for band: %d, num_channels=%d\n", + band, num_channels); + + kalMemFree(aucChannelList, VIR_MEM_TYPE, + sizeof(struct RF_CHANNEL_INFO)*MAX_CHN_NUM); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(channels)); + if (!skb) { + DBGLOG(REQ, ERROR, "Allocate skb failed\n"); + return -ENOMEM; + } + + if (unlikely(nla_put_u32(skb, WIFI_ATTRIBUTE_NUM_CHANNELS, + num_channels) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put(skb, WIFI_ATTRIBUTE_CHANNEL_LIST, + (sizeof(uint32_t) * num_channels), channels) < 0)) + goto nla_put_failure; + + return cfg80211_vendor_cmd_reply(skb); + +nla_put_failure: + kfree_skb(skb); + return -EFAULT; +} + +int mtk_cfg80211_vendor_set_country_code(struct wiphy + *wiphy, struct wireless_dev *wdev, const void *data, + int data_len) +{ + struct GLUE_INFO *prGlueInfo; + uint32_t rStatus; + uint32_t u4BufLen; + struct nlattr *attr; + uint8_t country[2] = {0}; + + ASSERT(wiphy && wdev); + if ((data == NULL) || (data_len == 0)) + return -EINVAL; + + DBGLOG(REQ, INFO, + "vendor command: data_len=%d, iftype=%d\n", data_len, + wdev->iftype); + + attr = (struct nlattr *)data; + if (attr->nla_type == WIFI_ATTRIBUTE_COUNTRY_CODE) { + country[0] = *((uint8_t *)nla_data(attr)); + country[1] = *((uint8_t *)nla_data(attr) + 1); + } + + DBGLOG(REQ, INFO, "Set country code: %c%c\n", country[0], + country[1]); + +#if CFG_ENABLE_UNIFY_WIPHY + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); +#else /* CFG_ENABLE_UNIFY_WIPHY */ + if (wdev == gprWdev) /* wlan0 */ + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + else + prGlueInfo = *((struct GLUE_INFO **) wiphy_priv(wiphy)); +#endif /* CFG_ENABLE_UNIFY_WIPHY */ + + if (!prGlueInfo) + return -EFAULT; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetCountryCode, + country, 2, FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "Set country code error: %x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +int mtk_cfg80211_vendor_set_scan_mac_oui(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct nlattr *attr; + uint32_t i = 0; + struct PARAM_BSS_MAC_OUI rParamMacOui; + uint32_t u4BufLen = 0; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = NULL; + + ASSERT(wiphy); + ASSERT(wdev); + + if (data == NULL || data_len <= 0) { + log_dbg(REQ, ERROR, "data error(len=%d)\n", data_len); + return -EINVAL; + } + +#if CFG_ENABLE_UNIFY_WIPHY + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); +#else /* CFG_ENABLE_UNIFY_WIPHY */ + if (wdev == gprWdev) + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + else + prGlueInfo = *((struct GLUE_INFO **) wiphy_priv(wiphy)); +#endif /* CFG_ENABLE_UNIFY_WIPHY */ + if (!prGlueInfo) { + log_dbg(REQ, ERROR, "Invalid glue info\n"); + return -EFAULT; + } + prNetDevPrivate = + (struct NETDEV_PRIVATE_GLUE_INFO *) netdev_priv(wdev->netdev); + if (!prNetDevPrivate) { + log_dbg(REQ, ERROR, "Invalid net device private\n"); + return -EFAULT; + } + rParamMacOui.ucBssIndex = prNetDevPrivate->ucBssIdx; + + attr = (struct nlattr *)data; + kalMemZero(rParamMacOui.ucMacOui, MAC_OUI_LEN); + if (nla_type(attr) != WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI) { + log_dbg(REQ, ERROR, "Set MAC oui type error(%u)\n", + nla_type(attr)); + return -EINVAL; + } + + if (nla_len(attr) != MAC_OUI_LEN) { + log_dbg(REQ, ERROR, "Set MAC oui length error(%u), %u needed\n", + nla_len(attr), MAC_OUI_LEN); + return -EINVAL; + } + + for (i = 0; i < MAC_OUI_LEN; i++) + rParamMacOui.ucMacOui[i] = *((uint8_t *)nla_data(attr) + i); + + log_dbg(REQ, INFO, "Set MAC oui: %02x-%02x-%02x\n", + rParamMacOui.ucMacOui[0], rParamMacOui.ucMacOui[1], + rParamMacOui.ucMacOui[2]); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetScanMacOui, + &rParamMacOui, sizeof(rParamMacOui), + FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + log_dbg(REQ, ERROR, "Set MAC oui error: 0x%X\n", rStatus); + return -EFAULT; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is to answer FWK that we can support FW Roaming. + * + * \param[in] wiphy wiphy for AIS STA. + * + * \param[in] wdev (not used here). + * + * \param[in] data (not used here). + * + * \param[in] data_len (not used here). + * + * \retval TRUE Success. + * + * \note we use cfg80211_vendor_cmd_reply to send the max number of our + * blacklist and whiltlist directly without receiving any data + * from the upper layer. + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_vendor_get_roaming_capabilities(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + uint32_t maxNumOfList[2] = { MAX_FW_ROAMING_BLACKLIST_SIZE, + MAX_FW_ROAMING_WHITELIST_SIZE }; + struct sk_buff *skb; + + ASSERT(wiphy); + + DBGLOG(REQ, INFO, + "Get roaming capabilities: max black/whitelist=%d/%d", + maxNumOfList[0], maxNumOfList[1]); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(maxNumOfList)); + if (!skb) { + DBGLOG(REQ, ERROR, "Allocate skb failed\n"); + return -ENOMEM; + } + + if (unlikely(nla_put(skb, WIFI_ATTRIBUTE_ROAMING_CAPABILITIES, + sizeof(uint32_t), &maxNumOfList[0]) < 0)) + goto nla_put_failure; + if (unlikely(nla_put(skb, WIFI_ATTRIBUTE_ROAMING_CAPABILITIES, + sizeof(uint32_t), &maxNumOfList[1]) < 0)) + goto nla_put_failure; + + return cfg80211_vendor_cmd_reply(skb); + +nla_put_failure: + kfree_skb(skb); + return -EFAULT; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is to receive the black/whiltelist. from FWK. + * + * \param[in] wiphy wiphy for AIS STA. + * + * \param[in] wdev (not used here). + * + * \param[in] data BSSIDs in the FWK blact&whitelist. + * + * \param[in] data_len the byte-length of the FWK blact&whitelist. + * + * \retval TRUE Success. + * + * \note we iterate each BSSID in 'data' and put it into driver blacklist. + * For now, whiltelist doesn't be implemented by the FWK currently. + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_vendor_config_roaming(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct nlattr *attrlist; + struct AIS_BLACKLIST_ITEM *prBlackList; + struct BSS_DESC *prBssDesc = NULL; + uint32_t len_shift = 0; + uint32_t numOfList[2] = { 0 }; + uint8_t *aucBSSID = NULL; + int i; + + DBGLOG(REQ, INFO, + "Receives roaming blacklist & whitelist with data_len=%d\n", + data_len); + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || (data_len == 0)) + return -EINVAL; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + if (!prGlueInfo) + return -EINVAL; + + if (prGlueInfo->u4FWRoamingEnable == 0) { + DBGLOG(REQ, INFO, + "FWRoaming is disabled (FWRoamingEnable=%d)\n", + prGlueInfo->u4FWRoamingEnable); + return WLAN_STATUS_SUCCESS; + } + + attrlist = (struct nlattr *)((uint8_t *) data); + + /* get the number of blacklist and copy those mac addresses from HAL */ + if (attrlist->nla_type == + WIFI_ATTRIBUTE_ROAMING_BLACKLIST_NUM) { + numOfList[0] = nla_get_u32(attrlist); + len_shift += NLA_ALIGN(attrlist->nla_len); + } + DBGLOG(REQ, INFO, "Get the number of blacklist=%d\n", + numOfList[0]); + + if (numOfList[0] < 0 + || numOfList[0] > MAX_FW_ROAMING_BLACKLIST_SIZE) + return -EINVAL; + + /*Refresh all the FWKBlacklist */ + aisRefreshFWKBlacklist(prGlueInfo->prAdapter); + + /* Start to receive blacklist mac addresses and set to FWK blacklist */ + attrlist = (struct nlattr *)((uint8_t *) data + len_shift); + for (i = 0; i < numOfList[0]; i++) { + if (attrlist->nla_type == + WIFI_ATTRIBUTE_ROAMING_BLACKLIST_BSSID) { + prBssDesc = + scanSearchBssDescByBssid(prGlueInfo->prAdapter, + nla_data(attrlist)); + len_shift += NLA_ALIGN(attrlist->nla_len); + attrlist = + (struct nlattr *)((uint8_t *) data + len_shift); + + if (prBssDesc == NULL) { + aucBSSID = nla_data(attrlist); + DBGLOG(REQ, ERROR, "No found blacklist BSS=" + MACSTR "\n", + MAC2STR(aucBSSID)); + continue; + } + + prBlackList = aisAddBlacklist(prGlueInfo->prAdapter, + prBssDesc); + prBlackList->fgIsInFWKBlacklist = TRUE; + DBGLOG(REQ, INFO, "Gets roaming blacklist SSID=%s addr=" + MACSTR "\n", + prBssDesc->aucSSID, + MAC2STR(prBssDesc->aucBSSID)); + } + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is to turn on/off FW Roaming. + * + * \param[in] wiphy wiphy for AIS STA. + * + * \param[in] wdev (not used here). + * + * \param[in] data 1 for ON / 0 for OFF. + * + * \param[in] data_len the byte-length of the data. + * + * \retval TRUE Success. + * + * \note we only receive the data and make the interface available to FWK. + * For now, this SUBCMD woundn't be sent from the FWK currently. + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_vendor_enable_roaming(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct nlattr *attr; + + ASSERT(wiphy); /* change to if (wiphy == NULL) then return? */ + ASSERT(wdev); /* change to if (wiphy == NULL) then return? */ + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + if (!prGlueInfo) + return -EFAULT; + + attr = (struct nlattr *)data; + if (attr->nla_type == WIFI_ATTRIBUTE_ROAMING_STATE) + prGlueInfo->u4FWRoamingEnable = nla_get_u32(attr); + + DBGLOG(REQ, INFO, "FWK set FWRoamingEnable = %d\n", + prGlueInfo->u4FWRoamingEnable); + + return WLAN_STATUS_SUCCESS; +} + +int mtk_cfg80211_vendor_get_rtt_capabilities( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Status = -EINVAL; + struct PARAM_WIFI_RTT_CAPABILITIES rRttCapabilities; + struct sk_buff *skb; + + DBGLOG(REQ, TRACE, "vendor command\r\n"); + + ASSERT(wiphy); + ASSERT(wdev); + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, + sizeof(rRttCapabilities)); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed:%x\n", + __func__, i4Status); + return -ENOMEM; + } + + kalMemZero(&rRttCapabilities, sizeof(rRttCapabilities)); + + /* RTT Capabilities return from driver not firmware */ + rRttCapabilities.rtt_one_sided_supported = 0; + rRttCapabilities.rtt_ftm_supported = 1; + rRttCapabilities.lci_support = 1; + rRttCapabilities.lcr_support = 1; + rRttCapabilities.preamble_support = 0x07; + rRttCapabilities.bw_support = 0x1c; + + if (unlikely(nla_put(skb, RTT_ATTRIBUTE_CAPABILITIES, + sizeof(rRttCapabilities), &rRttCapabilities) < 0)) + goto nla_put_failure; + + i4Status = cfg80211_vendor_cmd_reply(skb); + return i4Status; + +nla_put_failure: + kfree_skb(skb); + return i4Status; +} + +int mtk_cfg80211_vendor_llstats_get_info( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + int32_t i4Status = -EINVAL; + struct WIFI_RADIO_STAT *pRadioStat = NULL; + struct sk_buff *skb = NULL; + uint32_t u4BufLen = 0; + + ASSERT(wiphy); + ASSERT(wdev); + + u4BufLen = sizeof(struct WIFI_RADIO_STAT) + sizeof( + struct WIFI_IFACE_STAT); + pRadioStat = kalMemAlloc(u4BufLen, VIR_MEM_TYPE); + if (!pRadioStat) { + DBGLOG(REQ, ERROR, "%s kalMemAlloc pRadioStat failed\n", + __func__); + i4Status = -ENOMEM; + goto nla_put_failure; + } + kalMemZero(pRadioStat, u4BufLen); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, u4BufLen); + if (!skb) { + DBGLOG(REQ, TRACE, "%s allocate skb failed:%x\n", __func__, + i4Status); + i4Status = -ENOMEM; + goto nla_put_failure; + } + +#if 0 + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStatistics, + &rRadioStat, + sizeof(rRadioStat), + TRUE, + TRUE, + TRUE, + FALSE, + &u4BufLen); +#endif + /* only for test */ + pRadioStat->radio = 10; + pRadioStat->on_time = 11; + pRadioStat->tx_time = 12; + pRadioStat->num_channels = 4; + + /*NLA_PUT(skb, LSTATS_ATTRIBUTE_STATS, u4BufLen, pRadioStat);*/ + if (unlikely(nla_put(skb, LSTATS_ATTRIBUTE_STATS, u4BufLen, + pRadioStat) < 0)) + goto nla_put_failure; + + i4Status = cfg80211_vendor_cmd_reply(skb); + kalMemFree(pRadioStat, VIR_MEM_TYPE, u4BufLen); + return -1; /* not support LLS now*/ + /* return i4Status; */ + +nla_put_failure: + if (skb != NULL) + kfree_skb(skb); + if (pRadioStat != NULL) + kalMemFree(pRadioStat, VIR_MEM_TYPE, u4BufLen); + return i4Status; +} + +int mtk_cfg80211_vendor_set_band(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct nlattr *attr; + uint8_t setBand = 0; + enum ENUM_BAND band; + + ASSERT(wiphy); + ASSERT(wdev); + + DBGLOG(REQ, INFO, "%s()\n", __func__); + + if ((data == NULL) || !data_len) + goto nla_put_failure; + + DBGLOG(REQ, TRACE, + "vendor command: data_len=%d, data=0x%x 0x%x\r\n", + data_len, *((uint32_t *) data), *((uint32_t *) data + 1)); + + attr = (struct nlattr *)data; + setBand = nla_get_u32(attr); + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, INFO, "Vendor Set Band value=%d\r\n", setBand); + + if (setBand == QCA_SETBAND_5G) + band = BAND_5G; + else if (setBand == QCA_SETBAND_2G) + band = BAND_2G4; + else + band = BAND_NULL; + + prGlueInfo->prAdapter->aePreferBand[NETWORK_TYPE_AIS] = + band; + return 0; + +nla_put_failure: + return -1; +} + +int mtk_cfg80211_vendor_set_roaming_policy( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct nlattr *attr; + uint32_t setRoaming = 0; + uint32_t u4BufLen = 0; + int32_t i4Status = -EINVAL; + + ASSERT(wiphy); + ASSERT(wdev); + + if ((data == NULL) || !data_len) + goto nla_put_failure; + + attr = (struct nlattr *)data; + setRoaming = nla_get_u32(attr); + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, INFO, + "vendor command: data_len=%d, data=0x%x 0x%x, roaming policy=%d\r\n", + data_len, *((uint32_t *) data), *((uint32_t *) data + 1), + setRoaming); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetDrvRoamingPolicy, + &setRoaming, sizeof(uint32_t), FALSE, FALSE, TRUE, + &u4BufLen); + + return rStatus; + +nla_put_failure: + return i4Status; + +} + +int mtk_cfg80211_vendor_set_rssi_monitoring( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo = NULL; + + int32_t i4Status = -EINVAL; + struct PARAM_RSSI_MONITOR_T rRSSIMonitor; + struct nlattr *attr[WIFI_ATTRIBUTE_RSSI_MONITOR_START + 1]; + uint32_t i = 0; + + ASSERT(wiphy); + ASSERT(wdev); + + DBGLOG(REQ, TRACE, "vendor command: data_len=%d\r\n", + data_len); + kalMemZero(&rRSSIMonitor, + sizeof(struct PARAM_RSSI_MONITOR_T)); + if ((data == NULL) || !data_len) + goto nla_put_failure; + kalMemZero(attr, sizeof(struct nlattr *) * + (WIFI_ATTRIBUTE_RSSI_MONITOR_START + 1)); + + if (NLA_PARSE_NESTED(attr, + WIFI_ATTRIBUTE_RSSI_MONITOR_START, + (struct nlattr *)(data - NLA_HDRLEN), + nla_parse_wifi_policy) < 0) { + DBGLOG(REQ, ERROR, "%s nla_parse_nested failed\n", + __func__); + goto nla_put_failure; + } + + for (i = WIFI_ATTRIBUTE_MAX_RSSI; + i <= WIFI_ATTRIBUTE_RSSI_MONITOR_START; i++) { + if (attr[i]) { + switch (i) { + case WIFI_ATTRIBUTE_MAX_RSSI: + rRSSIMonitor.max_rssi_value = + nla_get_u32(attr[i]); + break; + case WIFI_ATTRIBUTE_MIN_RSSI: + rRSSIMonitor.min_rssi_value + = nla_get_u32(attr[i]); + break; + case WIFI_ATTRIBUTE_RSSI_MONITOR_START: + rRSSIMonitor.enable = nla_get_u32(attr[i]); + break; + } + } + } + + DBGLOG(REQ, TRACE, + "mMax_rssi=%d, mMin_rssi=%d enable=%d\r\n", + rRSSIMonitor.max_rssi_value, rRSSIMonitor.min_rssi_value, + rRSSIMonitor.enable); + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidRssiMonitor, + &rRSSIMonitor, sizeof(struct PARAM_RSSI_MONITOR_T), + FALSE, FALSE, TRUE, &u4BufLen); + return rStatus; + +nla_put_failure: + return i4Status; +} + +int mtk_cfg80211_vendor_packet_keep_alive_start( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + unsigned short u2IpPktLen = 0; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo = NULL; + + int32_t i4Status = -EINVAL; + struct PARAM_PACKET_KEEPALIVE_T *prPkt = NULL; + struct nlattr *attr[MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC + 1]; + uint32_t i = 0; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + + DBGLOG(REQ, TRACE, "vendor command: data_len=%d\r\n", + data_len); + prPkt = (struct PARAM_PACKET_KEEPALIVE_T *) + kalMemAlloc(sizeof(struct PARAM_PACKET_KEEPALIVE_T), + VIR_MEM_TYPE); + if (!prPkt) { + DBGLOG(REQ, ERROR, + "Can not alloc memory for struct PARAM_PACKET_KEEPALIVE_T\n"); + return -ENOMEM; + } + kalMemZero(prPkt, sizeof(struct PARAM_PACKET_KEEPALIVE_T)); + kalMemZero(attr, sizeof(struct nlattr *) + * (MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC + 1)); + + prPkt->enable = TRUE; /*start packet keep alive*/ + if (NLA_PARSE_NESTED(attr, + MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC, + (struct nlattr *)(data - NLA_HDRLEN), + nla_parse_offloading_policy) < 0) { + DBGLOG(REQ, ERROR, "%s nla_parse_nested failed\n", + __func__); + goto nla_put_failure; + } + + for (i = MKEEP_ALIVE_ATTRIBUTE_ID; + i <= MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC; i++) { + if (attr[i]) { + switch (i) { + case MKEEP_ALIVE_ATTRIBUTE_ID: + prPkt->index = nla_get_u8(attr[i]); + break; + case MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN: + prPkt->u2IpPktLen = nla_get_u16(attr[i]); + break; + case MKEEP_ALIVE_ATTRIBUTE_IP_PKT: + u2IpPktLen = prPkt->u2IpPktLen <= 256 + ? prPkt->u2IpPktLen : 256; + kalMemCopy(prPkt->pIpPkt, nla_data(attr[i]), + u2IpPktLen); + break; + case MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR: + kalMemCopy(prPkt->ucSrcMacAddr, + nla_data(attr[i]), sizeof(uint8_t) * 6); + break; + case MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR: + kalMemCopy(prPkt->ucDstMacAddr, + nla_data(attr[i]), sizeof(uint8_t) * 6); + break; + case MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC: + prPkt->u4PeriodMsec = nla_get_u32(attr[i]); + break; + } + } + } + + DBGLOG(REQ, INFO, + "enable=%d, index=%d, u2IpPktLen=%d u4PeriodMsec=%d\n", + prPkt->enable, prPkt->index, + prPkt->u2IpPktLen, prPkt->u4PeriodMsec); + DBGLOG(REQ, TRACE, "prPkt->pIpPkt=0x%02x%02x%02x%02x\n", + prPkt->pIpPkt[0], prPkt->pIpPkt[1], + prPkt->pIpPkt[2], prPkt->pIpPkt[3]); + DBGLOG(REQ, TRACE, "%02x%02x%02x%02x, %02x%02x%02x%02x\n", + prPkt->pIpPkt[4], prPkt->pIpPkt[5], + prPkt->pIpPkt[6], prPkt->pIpPkt[7], + prPkt->pIpPkt[8], prPkt->pIpPkt[9], + prPkt->pIpPkt[10], prPkt->pIpPkt[11]); + DBGLOG(REQ, TRACE, "%02x%02x%02x%02x\n", + prPkt->pIpPkt[12], prPkt->pIpPkt[13], + prPkt->pIpPkt[14], prPkt->pIpPkt[15]); + DBGLOG(REQ, TRACE, + "prPkt->srcMAC=%02x:%02x:%02x:%02x:%02x:%02x\n", + prPkt->ucSrcMacAddr[0], prPkt->ucSrcMacAddr[1], + prPkt->ucSrcMacAddr[2], prPkt->ucSrcMacAddr[3], + prPkt->ucSrcMacAddr[4], prPkt->ucSrcMacAddr[5]); + DBGLOG(REQ, TRACE, "dstMAC=%02x:%02x:%02x:%02x:%02x:%02x\n", + prPkt->ucDstMacAddr[0], prPkt->ucDstMacAddr[1], + prPkt->ucDstMacAddr[2], prPkt->ucDstMacAddr[3], + prPkt->ucDstMacAddr[4], prPkt->ucDstMacAddr[5]); + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidPacketKeepAlive, + prPkt, sizeof(struct PARAM_PACKET_KEEPALIVE_T), + FALSE, FALSE, TRUE, &u4BufLen); + kalMemFree(prPkt, VIR_MEM_TYPE, + sizeof(struct PARAM_PACKET_KEEPALIVE_T)); + return rStatus; + +nla_put_failure: + if (prPkt != NULL) + kalMemFree(prPkt, VIR_MEM_TYPE, + sizeof(struct PARAM_PACKET_KEEPALIVE_T)); + return i4Status; +} + +int mtk_cfg80211_vendor_packet_keep_alive_stop( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + struct GLUE_INFO *prGlueInfo = NULL; + + int32_t i4Status = -EINVAL; + struct PARAM_PACKET_KEEPALIVE_T *prPkt = NULL; + struct nlattr *attr; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + + DBGLOG(REQ, TRACE, "vendor command: data_len=%d\r\n", + data_len); + prPkt = (struct PARAM_PACKET_KEEPALIVE_T *) + kalMemAlloc(sizeof(struct PARAM_PACKET_KEEPALIVE_T), + VIR_MEM_TYPE); + if (!prPkt) { + DBGLOG(REQ, ERROR, + "Can not alloc memory for PARAM_PACKET_KEEPALIVE_T\n"); + return -ENOMEM; + } + kalMemZero(prPkt, sizeof(struct PARAM_PACKET_KEEPALIVE_T)); + + prPkt->enable = FALSE; /*stop packet keep alive*/ + attr = (struct nlattr *)data; + if (attr->nla_type == MKEEP_ALIVE_ATTRIBUTE_ID) + prPkt->index = nla_get_u8(attr); + + DBGLOG(REQ, INFO, "enable=%d, index=%d\r\n", + prPkt->enable, prPkt->index); + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidPacketKeepAlive, + prPkt, sizeof(struct PARAM_PACKET_KEEPALIVE_T), + FALSE, FALSE, TRUE, &u4BufLen); + kalMemFree(prPkt, VIR_MEM_TYPE, + sizeof(struct PARAM_PACKET_KEEPALIVE_T)); + return rStatus; + +nla_put_failure: + if (prPkt != NULL) + kalMemFree(prPkt, VIR_MEM_TYPE, + sizeof(struct PARAM_PACKET_KEEPALIVE_T)); + return i4Status; +} + +int mtk_cfg80211_vendor_get_version(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ +#define STR_HELPER(x) #x +#define STR(x) STR_HELPER(x) + struct GLUE_INFO *prGlueInfo = NULL; + struct sk_buff *skb = NULL; + struct nlattr *attrlist = NULL; + char aucVersionBuf[256]; + uint16_t u2CopySize = 0; + uint16_t u2Len = 0; + + ASSERT(wiphy); + ASSERT(wdev); + + if ((data == NULL) || !data_len) + return -ENOMEM; + + kalMemZero(aucVersionBuf, 256); + attrlist = (struct nlattr *)((uint8_t *) data); + if (attrlist->nla_type == LOGGER_ATTRIBUTE_DRIVER_VER) { + char aucDriverVersionStr[] = STR(NIC_DRIVER_MAJOR_VERSION) "_" + STR(NIC_DRIVER_MINOR_VERSION) "_" + STR(NIC_DRIVER_SERIAL_VERSION) "-" + DRIVER_BUILD_DATE; + + u2Len = kalStrLen(aucDriverVersionStr); + DBGLOG(REQ, INFO, "Get driver version len: %d\n", u2Len); + u2CopySize = (u2Len >= 256) ? 255 : u2Len; + if (u2CopySize > 0) + kalMemCopy(aucVersionBuf, &aucDriverVersionStr[0], + u2CopySize); + } else if (attrlist->nla_type == LOGGER_ATTRIBUTE_FW_VER) { + struct ADAPTER *prAdapter; + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + prAdapter = prGlueInfo->prAdapter; + if (prAdapter) { + u2Len = kalStrLen( + prAdapter->rVerInfo.aucReleaseManifest); + DBGLOG(REQ, INFO, + "Get FW manifest version len: %d\n", u2Len); + u2CopySize = (u2Len >= 256) ? 255 : u2Len; + if (u2CopySize > 0) + kalMemCopy(aucVersionBuf, + prAdapter->rVerInfo.aucReleaseManifest, + u2CopySize); + } + } + + if (u2CopySize <= 0) + return -EFAULT; + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, u2CopySize); + if (!skb) { + DBGLOG(REQ, ERROR, "Allocate skb failed\n"); + return -ENOMEM; + } + + DBGLOG(REQ, INFO, "Get version(%d)=[%s]\n", u2CopySize, aucVersionBuf); + if (unlikely(nla_put_nohdr(skb, u2CopySize, &aucVersionBuf[0]) < 0)) + goto nla_put_failure; + + return cfg80211_vendor_cmd_reply(skb); + +nla_put_failure: + kfree_skb(skb); + return -EFAULT; +} + +int mtk_cfg80211_vendor_get_supported_feature_set(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + uint32_t u4FeatureSet; + struct GLUE_INFO *prGlueInfo; + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(wdev); + +#if CFG_ENABLE_UNIFY_WIPHY + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); +#else /* CFG_ENABLE_UNIFY_WIPHY */ + if (wdev == gprWdev) /* wlan0 */ + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + else + prGlueInfo = *((struct GLUE_INFO **) wiphy_priv(wiphy)); +#endif /* CFG_ENABLE_UNIFY_WIPHY */ + + if (!prGlueInfo) + return -EFAULT; + + u4FeatureSet = wlanGetSupportedFeatureSet(prGlueInfo); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u4FeatureSet)); + if (!skb) { + DBGLOG(REQ, ERROR, "Allocate skb failed\n"); + return -ENOMEM; + } + + if (unlikely( + nla_put_nohdr(skb, sizeof(u4FeatureSet), &u4FeatureSet) < 0)) { + DBGLOG(REQ, ERROR, "nla_put_nohdr failed\n"); + goto nla_put_failure; + } + + DBGLOG(REQ, TRACE, "supported feature set=0x%x\n", u4FeatureSet); + + return cfg80211_vendor_cmd_reply(skb); + +nla_put_failure: + kfree_skb(skb); + return -EFAULT; +} + +int mtk_cfg80211_vendor_set_tx_power_scenario(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + return -EOPNOTSUPP; +} + +int mtk_cfg80211_vendor_event_rssi_beyond_range( + struct wiphy *wiphy, struct wireless_dev *wdev, int rssi) +{ + struct sk_buff *skb; + struct PARAM_RSSI_MONITOR_EVENT rRSSIEvt; + struct BSS_INFO *prAisBssInfo; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter; + + ASSERT(wiphy); + ASSERT(wdev); + + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, TRACE, "vendor command rssi=%d\r\n", rssi); + kalMemZero(&rRSSIEvt, + sizeof(struct PARAM_RSSI_MONITOR_EVENT)); + +#if KERNEL_VERSION(4, 4, 0) <= LINUX_VERSION_CODE + skb = cfg80211_vendor_event_alloc(wiphy, wdev, + sizeof(struct PARAM_RSSI_MONITOR_EVENT), + WIFI_EVENT_RSSI_MONITOR, GFP_KERNEL); +#else + skb = cfg80211_vendor_event_alloc(wiphy, + sizeof(struct PARAM_RSSI_MONITOR_EVENT), + WIFI_EVENT_RSSI_MONITOR, GFP_KERNEL); +#endif /* KERNEL_VERSION(4, 4, 0) <= LINUX_VERSION_CODE */ + + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + prAdapter = prGlueInfo->prAdapter; + prAisBssInfo = + &(prAdapter->rWifiVar.arBssInfoPool[NETWORK_TYPE_AIS]); + kalMemCopy(rRSSIEvt.BSSID, prAisBssInfo->aucBSSID, + sizeof(uint8_t) * MAC_ADDR_LEN); + + rRSSIEvt.version = 1; /* RSSI_MONITOR_EVT_VERSION = 1 */ + if (rssi > PARAM_WHQL_RSSI_MAX_DBM) + rssi = PARAM_WHQL_RSSI_MAX_DBM; + else if (rssi < -120) + rssi = -120; + rRSSIEvt.rssi = (int8_t)rssi; + DBGLOG(REQ, INFO, + "RSSI Event: version=%d, rssi=%d, BSSID=" MACSTR "\r\n", + rRSSIEvt.version, rRSSIEvt.rssi, MAC2STR(rRSSIEvt.BSSID)); + + /*NLA_PUT_U32(skb, GOOGLE_RSSI_MONITOR_EVENT, rssi);*/ + { + /* unsigned int __tmp = rssi; */ + + if (unlikely(nla_put(skb, WIFI_EVENT_RSSI_MONITOR, + sizeof(struct PARAM_RSSI_MONITOR_EVENT), + &rRSSIEvt) < 0)) + goto nla_put_failure; + } + + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -ENOMEM; +} + +#if CFG_SUPPORT_MAGIC_PKT_VENDOR_EVENT +int mtk_cfg80211_vendor_event_wowlan_magic_pkt(struct wiphy *wiphy, + struct wireless_dev *wdev, uint32_t num) +{ + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(wdev); + + DBGLOG(REQ, INFO, "%s for vendor command %d\r\n", __func__, num); + +#if KERNEL_VERSION(4, 4, 0) <= LINUX_VERSION_CODE + skb = cfg80211_vendor_event_alloc(wiphy, wdev, sizeof(num), + WIFI_EVENT_MAGIC_PACKET_RECEIVED, GFP_KERNEL); +#else + skb = cfg80211_vendor_event_alloc(wiphy, sizeof(num), + WIFI_EVENT_MAGIC_PACKET_RECEIVED, GFP_KERNEL); +#endif /* KERNEL_VERSION(4, 4, 0) <= LINUX_VERSION_CODE */ + + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + /*NLA_PUT_U32(skb, WIFI_EVENT_MAGIC_PACKET_RECEIVED, num);*/ + { + unsigned int __tmp = num; + + if (unlikely(nla_put(skb, WIFI_EVENT_MAGIC_PACKET_RECEIVED, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + cfg80211_vendor_event(skb, GFP_KERNEL); + DBGLOG(REQ, INFO, "%s for vendor command done\r\n", __func__); + return 0; + +nla_put_failure: + kfree_skb(skb); + DBGLOG(REQ, INFO, "%s nla_put_fail!\r\n", __func__); + return -ENOMEM; +} +#endif + +#endif /* KERNEL_VERSION(3, 16, 0) <= LINUX_VERSION_CODE */ + +int mtk_cfg80211_vendor_get_preferred_freq_list(struct wiphy + *wiphy, struct wireless_dev *wdev, const void *data, + int data_len) +{ + struct GLUE_INFO *prGlueInfo; + struct sk_buff *skb; + struct nlattr *tb[WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_LAST]; + uint32_t freq_list[MAX_CHN_NUM]; + uint32_t num_freq_list = 0; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + enum CONN_MODE_IFACE_TYPE type; + enum ENUM_IFTYPE eIftype; + uint32_t i; + + ASSERT(wiphy); + ASSERT(wdev); + + if ((data == NULL) || !data_len) + return -EINVAL; + +#if CFG_ENABLE_UNIFY_WIPHY + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); +#else /* CFG_ENABLE_UNIFY_WIPHY */ + if (wdev == gprWdev) /* wlan0 */ + prGlueInfo = (struct GLUE_INFO *) wiphy_priv(wiphy); + else + prGlueInfo = *((struct GLUE_INFO **) wiphy_priv(wiphy)); +#endif /* CFG_ENABLE_UNIFY_WIPHY */ + + if (!prGlueInfo) + return -EFAULT; + + if (NLA_PARSE(tb, WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_MAX, + data, data_len, nla_get_preferred_freq_list_policy)) { + DBGLOG(REQ, ERROR, "Invalid ATTR.\n"); + return -EINVAL; + } + + type = nla_get_u32(tb[WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_IFACE_TYPE]); + + DBGLOG(REQ, INFO, "type: %d\n", type); + + switch (type) { + case CONN_MODE_IFACE_TYPE_STA: + eIftype = IFTYPE_STATION; + break; + case CONN_MODE_IFACE_TYPE_SAP: + eIftype = IFTYPE_AP; + break; + case CONN_MODE_IFACE_TYPE_P2P_GC: + eIftype = IFTYPE_P2P_CLIENT; + break; + case CONN_MODE_IFACE_TYPE_P2P_GO: + eIftype = IFTYPE_P2P_GO; + break; + default: + eIftype = IFTYPE_NUM; + break; + } + + if (eIftype != IFTYPE_P2P_CLIENT && eIftype != IFTYPE_P2P_GO) { + DBGLOG(REQ, ERROR, "Only support p2p gc/go type.\n"); + return -EINVAL; + } + + rStatus = p2pFunGetPreferredFreqList(prGlueInfo->prAdapter, eIftype, + freq_list, &num_freq_list); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "get preferred freq list failed.\n"); + return -EINVAL; + } + + DBGLOG(P2P, INFO, "num. of preferred freq list = %d\n", num_freq_list); + for (i = 0; i < num_freq_list; i++) + DBGLOG(P2P, INFO, "dump preferred freq list[%d] = %d\n", + i, freq_list[i]); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) + + sizeof(uint32_t) * num_freq_list + NLMSG_HDRLEN); + if (!skb) { + DBGLOG(REQ, ERROR, "Allocate skb failed.\n"); + return -ENOMEM; + } + + if (unlikely(nla_put_u32(skb, + WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_IFACE_TYPE, + type) < 0)) { + DBGLOG(REQ, ERROR, "put iface into skb failed.\n"); + goto nla_put_failure; + } + + if (unlikely(nla_put(skb, WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_GET, + sizeof(uint32_t) * num_freq_list, freq_list) < 0)) { + DBGLOG(REQ, ERROR, "put freq list into skb failed.\n"); + goto nla_put_failure; + } + + return cfg80211_vendor_cmd_reply(skb); + +nla_put_failure: + kfree_skb(skb); + return -EFAULT; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_wext.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_wext.c new file mode 100644 index 0000000000000..d06ad18a8a3fb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_wext.c @@ -0,0 +1,5001 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux + * /gl_wext.c#5 + */ + +/*! \file gl_wext.c + * \brief ioctl() (mostly Linux Wireless Extensions) routines for STA + * driver. + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ + +#include "gl_os.h" + +#include "config.h" +#include "wlan_oid.h" + +#include "gl_wext.h" +#include "gl_wext_priv.h" + +#include "precomp.h" + +#if CFG_SUPPORT_WAPI +#include "gl_sec.h" +#endif + +/* compatibility to wireless extensions */ +#ifdef WIRELESS_EXT + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +const long channel_freq[] = { + 2412, 2417, 2422, 2427, 2432, 2437, 2442, + 2447, 2452, 2457, 2462, 2467, 2472, 2484 +}; + +#define NUM_CHANNELS (ARRAY_SIZE(channel_freq)) + +#define MAX_SSID_LEN 32 +#define COUNTRY_CODE_LEN 10 /* country code length */ + +/******************************************************************************* + * 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, + IW_PRIV_TYPE_CHAR | sizeof(struct NDIS_TRANSPORT_STRUCT), 0, ""}, + {IOCTL_GET_STRUCT, 0, + IW_PRIV_TYPE_CHAR | sizeof(struct NDIS_TRANSPORT_STRUCT), ""}, + + {IOCTL_GET_DRIVER, IW_PRIV_TYPE_CHAR | 2000, IW_PRIV_TYPE_CHAR | + 2000, "driver"}, + +#if CFG_SUPPORT_QA_TOOL + /* added for ATE iwpriv Command */ + {IOCTL_QA_TOOL_DAEMON, IW_PRIV_TYPE_BYTE | + sizeof(struct HQA_CMD_FRAME), 0, ""}, + {IOCTL_IWPRIV_ATE, IW_PRIV_TYPE_CHAR | 2000, 0, ""}, +#endif + {IOC_AP_SET_CFG, IW_PRIV_TYPE_CHAR | 256, + IW_PRIV_TYPE_CHAR | 1024, "AP_SET_CFG"}, + {IOC_AP_GET_STA_LIST, IW_PRIV_TYPE_CHAR | 1024, + IW_PRIV_TYPE_CHAR | 1024, "AP_GET_STA_LIST"}, + {IOC_AP_SET_MAC_FLTR, IW_PRIV_TYPE_CHAR | 256, + IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 1024, "AP_SET_MAC_FLTR"}, + {IOC_AP_STA_DISASSOC, IW_PRIV_TYPE_CHAR | 256, + IW_PRIV_TYPE_CHAR | 1024, "AP_STA_DISASSOC"}, + + /* 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 + +#if CFG_SUPPORT_QA_TOOL + {PRIV_QACMD_SET, IW_PRIV_TYPE_CHAR | 2000, 0, "set"}, +#endif + + {PRIV_CMD_SW_CTRL, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | + 2, 0, "set_sw_ctrl"}, + { + PRIV_CMD_SW_CTRL, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_sw_ctrl" + }, + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS + {PRIV_CUSTOM_BWCS_CMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | + 1, 0, "set_bwcs"}, + /* GET STRUCT sub-ioctls commands */ + { + PRIV_CUSTOM_BWCS_CMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_bwcs" + }, +#endif + + /* SET STRUCT sub-ioctls commands */ + {PRIV_CMD_OID, 256, 0, "set_oid"}, + /* GET STRUCT sub-ioctls commands */ + {PRIV_CMD_OID, 0, 256, "get_oid"}, + + {PRIV_CMD_BAND_CONFIG, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | + 1, 0, "set_band"}, + {PRIV_CMD_BAND_CONFIG, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | + 1, "get_band"}, + + {PRIV_CMD_SET_TX_POWER, IW_PRIV_TYPE_INT | 4, 0, "set_txpower"}, + {PRIV_CMD_GET_CH_LIST, 0, IW_PRIV_TYPE_INT | 50, "get_ch_list"}, + { + PRIV_CMD_DUMP_MEM, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_mem" + }, + +#if CFG_ENABLE_WIFI_DIRECT + {PRIV_CMD_P2P_MODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | + 2, 0, "set_p2p_mode"}, +#endif + {PRIV_CMD_MET_PROFILING, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | + 2, 0, "set_met_prof"}, + {PRIV_CMD_SET_SER, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | + 1, 0, "set_ser"}, + +}; + +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, +#if CFG_MTK_ENGINEER_MODE_SUPPORT + [IOCTL_SET_STRUCT_FOR_EM - SIOCIWFIRSTPRIV] = priv_set_struct, +#endif + [IOCTL_SET_INTS - SIOCIWFIRSTPRIV] = priv_set_ints, + [IOCTL_GET_INTS - SIOCIWFIRSTPRIV] = priv_get_ints, + [IOCTL_GET_DRIVER - SIOCIWFIRSTPRIV] = priv_set_driver, + [IOC_AP_GET_STA_LIST - SIOCIWFIRSTPRIV] = priv_set_ap, + [IOC_AP_SET_MAC_FLTR - SIOCIWFIRSTPRIV] = priv_set_ap, + [IOC_AP_SET_CFG - SIOCIWFIRSTPRIV] = priv_set_ap, + [IOC_AP_STA_DISASSOC - SIOCIWFIRSTPRIV] = priv_set_ap, +#if CFG_SUPPORT_QA_TOOL + [IOCTL_QA_TOOL_DAEMON - SIOCIWFIRSTPRIV] = priv_qa_agent, + [IOCTL_IWPRIV_ATE - SIOCIWFIRSTPRIV] = priv_ate_set +#endif +}; + +/* standard ioctls */ +static int std_get_name(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_freq(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_freq(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_mode(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_mode(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_ap(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_ap(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_rate(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_rts(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_rts(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_frag(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_txpow(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_txpow(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_power(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_power(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_range(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_priv(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_priv(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_mlme(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_scan(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_scan(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_essid(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_essid(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_encode(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_get_encode(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_auth(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +#if (WIRELESS_EXT > 17) +static int std_set_genie(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); +#endif + +static int std_set_encode_ext(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static int std_set_pmska(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra); + +static const iw_handler mtk_std_handler[] = { + IW_HANDLER(SIOCGIWNAME, std_get_name), /* factory mode used */ + IW_HANDLER(SIOCSIWFREQ, std_set_freq), + IW_HANDLER(SIOCGIWFREQ, std_get_freq), /* factory mode used */ + IW_HANDLER(SIOCSIWMODE, std_set_mode), /* factory mode used */ + IW_HANDLER(SIOCGIWMODE, std_get_mode), /* factory mode used */ + IW_HANDLER(SIOCGIWRANGE, std_get_range), /* factory mode used */ + IW_HANDLER(SIOCSIWPRIV, std_set_priv), + IW_HANDLER(SIOCGIWPRIV, std_get_priv), + IW_HANDLER(SIOCSIWAP, std_set_ap), + IW_HANDLER(SIOCGIWAP, std_get_ap), /* factory mode used */ + IW_HANDLER(SIOCSIWMLME, std_set_mlme), + IW_HANDLER(SIOCSIWSCAN, std_set_scan), /* factory mode used */ + IW_HANDLER(SIOCGIWSCAN, std_get_scan), /* factory mode used */ + IW_HANDLER(SIOCSIWESSID, std_set_essid), /* factory mode used */ + IW_HANDLER(SIOCGIWESSID, std_get_essid), /* factory mode used */ + IW_HANDLER(SIOCGIWRATE, std_get_rate), /* factory mode used */ + IW_HANDLER(SIOCSIWRTS, std_set_rts), + IW_HANDLER(SIOCGIWRTS, std_get_rts), /* factory mode used */ + IW_HANDLER(SIOCGIWFRAG, std_get_frag), /* factory mode used */ + IW_HANDLER(SIOCSIWTXPOW, std_set_txpow), + IW_HANDLER(SIOCGIWTXPOW, std_get_txpow), /* factory mode used */ + IW_HANDLER(SIOCSIWENCODE, std_set_encode), + IW_HANDLER(SIOCGIWENCODE, std_get_encode),/* factory mode used */ + IW_HANDLER(SIOCSIWPOWER, std_set_power), + IW_HANDLER(SIOCGIWPOWER, std_get_power), /* factory mode used */ + IW_HANDLER(SIOCSIWAUTH, std_set_auth), +#if (WIRELESS_EXT > 17) + IW_HANDLER(SIOCSIWGENIE, std_set_genie), +#endif + IW_HANDLER(SIOCSIWENCODEEXT, std_set_encode_ext), + IW_HANDLER(SIOCSIWPMKSA, std_set_pmska), +}; + + +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), + .private = rIwPrivHandler, + .private_args = rIwPrivTable, + .get_wireless_stats = wext_get_wireless_stats, + .num_standard = (__u16) sizeof(mtk_std_handler) / sizeof(iw_handler), + .standard = (iw_handler *) mtk_std_handler, +}; + +/******************************************************************************* + * 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 wext_support_ioctl_SIOCSIWGENIE( + IN struct GLUE_INFO *prGlueInfo, IN char *prExtraBuf, + IN uint32_t u4ExtraSize); + +static void +wext_support_ioctl_SIOCSIWPMKSA_Action(IN struct net_device + *prDev, IN char *prExtraBuf, IN int ioMode, OUT int *ret); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#if 0 /* not in use */ +void MAP_CHANNEL_ID_TO_KHZ(uint32_t ch, uint32_t 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: + khz = 5220000; + break; + case 48: + khz = 5240000; + break; + case 52: + khz = 5260000; + break; + case 56: + khz = 5280000; + break; + case 60: + khz = 5300000; + break; + case 64: + khz = 5320000; + break; + case 149: + khz = 5745000; + break; + case 153: + khz = 5765000; + break; + case 157: + 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; + } +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t +wextSrchDesiredWPAIE(IN uint8_t *pucIEStart, + IN int32_t i4TotalIeLen, IN uint8_t ucDesiredElemId, + OUT uint8_t **ppucDesiredIE) +{ + int32_t i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (int32_t) pucIEStart[1] + 2; + + if (pucIEStart[0] == ucDesiredElemId + && i4InfoElemLen <= i4TotalIeLen) { + if (ucDesiredElemId != 0xDD) { + /* Non 0xDD, OK! */ + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } /* EID == 0xDD, check WPA IE */ + if (pucIEStart[1] >= 4) { + if (memcmp(&pucIEStart[2], "\x00\x50\xf2\x01", + 4) == 0) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + } /* check WPA IE length */ + /* check EID == 0xDD */ + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* parseSearchDesiredWPAIE */ + +#if CFG_SUPPORT_WAPI +/*----------------------------------------------------------------------------*/ +/*! + * \brief Find the desired WAPI Information Element . + * + * \param[in] pucIEStart IE starting address. + * \param[in] i4TotalIeLen Total length of all the IE. + * \param[out] ppucDesiredIE Pointer to the desired IE. + * + * \retval TRUE Find the desired IE. + * \retval FALSE Desired IE not found. + * + * \note + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wextSrchDesiredWAPIIE(IN uint8_t *pucIEStart, + IN int32_t i4TotalIeLen, OUT uint8_t **ppucDesiredIE) +{ + int32_t i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (int32_t) 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_PASSPOINT +/*----------------------------------------------------------------------------*/ +/*! + * \brief Check if exist the desired HS2.0 Information Element according to + * desiredElemID. + * + * \param[in] pucIEStart IE starting address. + * \param[in] i4TotalIeLen Total length of all the IE. + * \param[in] ucDesiredElemId Desired element ID. + * \param[out] ppucDesiredIE Pointer to the desired IE. + * + * \retval TRUE Find the desired IE. + * \retval FALSE Desired IE not found. + * + * \note + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wextIsDesiredHS20IE(IN uint8_t *pucCurIE, + IN int32_t i4TotalIeLen) +{ + int32_t i4InfoElemLen; + + ASSERT(pucCurIE); + + i4InfoElemLen = (int32_t) pucCurIE[1] + 2; + + if (pucCurIE[0] == ELEM_ID_VENDOR + && i4InfoElemLen <= i4TotalIeLen) { + if (pucCurIE[1] >= ELEM_MIN_LEN_HS20_INDICATION) { + if (memcmp(&pucCurIE[2], "\x50\x6f\x9a\x10", 4) == 0) + return TRUE; + } + } + /* check desired EID */ + return FALSE; +} /* wextIsDesiredHS20IE */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Check if exist the desired interworking Information Element according + * to desiredElemID. + * + * \param[in] pucIEStart IE starting address. + * \param[in] i4TotalIeLen Total length of all the IE. + * \param[in] ucDesiredElemId Desired element ID. + * \param[out] ppucDesiredIE Pointer to the desired IE. + * + * \retval TRUE Find the desired IE. + * \retval FALSE Desired IE not found. + * + * \note + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wextIsDesiredInterworkingIE(IN uint8_t *pucCurIE, + IN int32_t i4TotalIeLen) +{ + int32_t i4InfoElemLen; + + ASSERT(pucCurIE); + + i4InfoElemLen = (int32_t) pucCurIE[1] + 2; + + if (pucCurIE[0] == ELEM_ID_INTERWORKING + && i4InfoElemLen <= i4TotalIeLen) { + switch (pucCurIE[1]) { + case IW_IE_LENGTH_ANO: + case IW_IE_LENGTH_ANO_HESSID: + case IW_IE_LENGTH_ANO_VENUE: + case IW_IE_LENGTH_ANO_VENUE_HESSID: + return TRUE; + default: + break; + } + + } + /* check desired EID */ + return FALSE; +} /* wextIsDesiredInterworkingIE */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Check if exist the desired Adv Protocol Information Element according + * to desiredElemID. + * + * \param[in] pucIEStart IE starting address. + * \param[in] i4TotalIeLen Total length of all the IE. + * \param[in] ucDesiredElemId Desired element ID. + * \param[out] ppucDesiredIE Pointer to the desired IE. + * + * \retval TRUE Find the desired IE. + * \retval FALSE Desired IE not found. + * + * \note + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wextIsDesiredAdvProtocolIE(IN uint8_t *pucCurIE, + IN int32_t i4TotalIeLen) +{ + int32_t i4InfoElemLen; + + ASSERT(pucCurIE); + + i4InfoElemLen = (int32_t) pucCurIE[1] + 2; + + if (pucCurIE[0] == ELEM_ID_ADVERTISEMENT_PROTOCOL + && i4InfoElemLen <= i4TotalIeLen) + return TRUE; + /* check desired EID */ + return FALSE; +} /* wextIsDesiredAdvProtocolIE */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Check if exist the desired Roaming Consortium Information Element + * according to desiredElemID. + * + * \param[in] pucIEStart IE starting address. + * \param[in] i4TotalIeLen Total length of all the IE. + * \param[in] ucDesiredElemId Desired element ID. + * \param[out] ppucDesiredIE Pointer to the desired IE. + * + * \retval TRUE Find the desired IE. + * \retval FALSE Desired IE not found. + * + * \note + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wextIsDesiredRoamingConsortiumIE( + IN uint8_t *pucCurIE, IN int32_t i4TotalIeLen) +{ + int32_t i4InfoElemLen; + + ASSERT(pucCurIE); + + i4InfoElemLen = (int32_t) pucCurIE[1] + 2; + + if (pucCurIE[0] == ELEM_ID_ROAMING_CONSORTIUM + && i4InfoElemLen <= i4TotalIeLen) + return TRUE; + /* check desired EID */ + return FALSE; +} /* wextIsDesiredRoamingConsortiumIE */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Find the desired HS2.0 Information Element according to desiredElemID. + * + * \param[in] pucIEStart IE starting address. + * \param[in] i4TotalIeLen Total length of all the IE. + * \param[in] ucDesiredElemId Desired element ID. + * \param[out] ppucDesiredIE Pointer to the desired IE. + * + * \retval TRUE Find the desired IE. + * \retval FALSE Desired IE not found. + * + * \note + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wextSrchDesiredHS20IE(IN uint8_t *pucIEStart, + IN int32_t i4TotalIeLen, OUT uint8_t **ppucDesiredIE) +{ + int32_t i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (int32_t) pucIEStart[1] + 2; + + if (pucIEStart[0] == ELEM_ID_VENDOR + && i4InfoElemLen <= i4TotalIeLen) { + if (pucIEStart[1] >= ELEM_MIN_LEN_HS20_INDICATION) { + if (memcmp(&pucIEStart[2], "\x50\x6f\x9a\x10", + 4) == 0) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + } + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* wextSrchDesiredHS20IE */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Find the desired HS2.0 Information Element according to desiredElemID. + * + * \param[in] pucIEStart IE starting address. + * \param[in] i4TotalIeLen Total length of all the IE. + * \param[in] ucDesiredElemId Desired element ID. + * \param[out] ppucDesiredIE Pointer to the desired IE. + * + * \retval TRUE Find the desired IE. + * \retval FALSE Desired IE not found. + * + * \note + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wextSrchDesiredOsenIE(IN uint8_t *pucIEStart, + IN int32_t i4TotalIeLen, OUT uint8_t **ppucDesiredIE) +{ + int32_t i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (int32_t) pucIEStart[1] + 2; + if (pucIEStart[0] == ELEM_ID_VENDOR + && i4InfoElemLen <= i4TotalIeLen) { + if (pucIEStart[1] >= 4) { + if (memcmp(&pucIEStart[2], "\x50\x6f\x9a\x12", + 4) == 0) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + } + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Find the desired interworking Information Element according to + * desiredElemID. + * + * \param[in] pucIEStart IE starting address. + * \param[in] i4TotalIeLen Total length of all the IE. + * \param[in] ucDesiredElemId Desired element ID. + * \param[out] ppucDesiredIE Pointer to the desired IE. + * + * \retval TRUE Find the desired IE. + * \retval FALSE Desired IE not found. + * + * \note + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wextSrchDesiredInterworkingIE(IN uint8_t + *pucIEStart, IN int32_t i4TotalIeLen, + OUT uint8_t **ppucDesiredIE) +{ + int32_t i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (int32_t) pucIEStart[1] + 2; + + if (pucIEStart[0] == ELEM_ID_INTERWORKING + && i4InfoElemLen <= i4TotalIeLen) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* wextSrchDesiredInterworkingIE */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Find the desired Adv Protocol Information Element according to + * desiredElemID. + * + * \param[in] pucIEStart IE starting address. + * \param[in] i4TotalIeLen Total length of all the IE. + * \param[in] ucDesiredElemId Desired element ID. + * \param[out] ppucDesiredIE Pointer to the desired IE. + * + * \retval TRUE Find the desired IE. + * \retval FALSE Desired IE not found. + * + * \note + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wextSrchDesiredAdvProtocolIE(IN uint8_t + *pucIEStart, IN int32_t i4TotalIeLen, + OUT uint8_t **ppucDesiredIE) +{ + int32_t i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (int32_t) pucIEStart[1] + 2; + + if (pucIEStart[0] == ELEM_ID_ADVERTISEMENT_PROTOCOL + && i4InfoElemLen <= i4TotalIeLen) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* wextSrchDesiredAdvProtocolIE */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Find the desired Roaming Consortium Information Element according to + * desiredElemID. + * + * \param[in] pucIEStart IE starting address. + * \param[in] i4TotalIeLen Total length of all the IE. + * \param[in] ucDesiredElemId Desired element ID. + * \param[out] ppucDesiredIE Pointer to the desired IE. + * + * \retval TRUE Find the desired IE. + * \retval FALSE Desired IE not found. + * + * \note + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wextSrchDesiredRoamingConsortiumIE( + IN uint8_t *pucIEStart, IN int32_t i4TotalIeLen, + OUT uint8_t **ppucDesiredIE) +{ + int32_t i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (int32_t) pucIEStart[1] + 2; + + if (pucIEStart[0] == ELEM_ID_ROAMING_CONSORTIUM + && i4InfoElemLen <= i4TotalIeLen) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* wextSrchDesiredRoamingConsortiumIE */ + +#endif /* CFG_SUPPORT_PASSPOINT */ + +u_int8_t wextSrchOkcAndPMKID(IN uint8_t *pucIEStart, + IN int32_t i4TotalIeLen, OUT uint8_t **ppucPMKID, + OUT uint8_t *okc) +{ + int32_t i4InfoElemLen; + uint8_t ucDone = 0; + + ASSERT(pucIEStart); + ASSERT(ppucPMKID); + ASSERT(okc); + *okc = 0; + *ppucPMKID = NULL; + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (int32_t) pucIEStart[1] + 2; + if (i4InfoElemLen > i4TotalIeLen) + break; + if (pucIEStart[0] == ELEM_ID_VENDOR) { + if (pucIEStart[1] != 4 || pucIEStart[2] != 0 + || pucIEStart[3] != 0x8 || pucIEStart[4] != 0x22) + goto check_next; + *okc = pucIEStart[5]; + ucDone |= 1; + } else if (pucIEStart[0] == ELEM_ID_RSN) { + /* + * RSN IE: + * EID(1), Len(1), Version(2), GrpCipher(4), + * PairCipherCnt(2), PairCipherList(PairCipherCnt * 4), + * AKMCnt(2), AkmList(4*AkmCnt), RSNCap(2), PMKIDCnt(2), + * PMKIDList(16*PMKIDCnt), GrpMgtCipher(4) + */ + uint16_t u2CipherCnt = 0; + uint16_t u2AkmCnt = 0; + int32_t i4LenToCheck = 8; + + /* if no Pairwise Cipher Count field, bypass */ + if (i4InfoElemLen < i4LenToCheck + 2) + goto check_next; + u2CipherCnt = *(uint16_t *)&pucIEStart[i4LenToCheck]; + i4LenToCheck += + 2; /* include length of Pairwise Cipher Count + * field + */ + i4LenToCheck += u2CipherCnt * + 4; /* include cipher list field */ + /* if no AKM Count, bypass */ + if (i4InfoElemLen < i4LenToCheck + 2) + goto check_next; + u2AkmCnt = *(uint16_t *)&pucIEStart[i4LenToCheck]; + i4LenToCheck += 2; /* include length of AKM Count */ + i4LenToCheck += u2AkmCnt * 4 + + 2; /* include akm list field */ + /* + * if IE length is + * 10 + u2CipherCnt * 4 + 2 + u2AkmCnt * 4 + 2 + 6, + * means PMKID count field is zero, and Group Mgmt + * Cipher may be exist + */ + if (i4InfoElemLen <= i4LenToCheck + 6) + goto check_next; + *ppucPMKID = pucIEStart + + i4LenToCheck; /* return PMKID field and + * started at PMKID count + */ + ucDone |= 2; + } + if (ucDone == 3) + return TRUE; + /* check desired EID */ + /* Select next information element. */ +check_next: + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + return FALSE; +} + +#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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t +wextSrchDesiredWPSIE(IN uint8_t *pucIEStart, + IN int32_t i4TotalIeLen, IN uint8_t ucDesiredElemId, + OUT uint8_t **ppucDesiredIE) +{ + int32_t i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (int32_t) pucIEStart[1] + 2; + + if (pucIEStart[0] == ucDesiredElemId + && i4InfoElemLen <= i4TotalIeLen) { + if (ucDesiredElemId != 0xDD) { + /* Non 0xDD, OK! */ + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + /* EID == 0xDD, check WPS IE */ + if (pucIEStart[1] >= 4) { + if (memcmp(&pucIEStart[2], "\x00\x50\xf2\x04", + 4) == 0) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + } /* check WPS IE length */ + /* check EID == 0xDD */ + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* parseSearchDesiredWPSIE */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Get the name of the protocol used on the air. + * + * \param[in] prDev Net device requested. + * \param[in] prIwrInfo NULL. + * \param[out] pcName Buffer to store protocol name string + * \param[in] pcExtra NULL. + * + * \retval 0 For success. + * + * \note If netif_carrier_ok, protocol name is returned; + * otherwise, "disconnected" is returned. + */ +/*----------------------------------------------------------------------------*/ +static int +wext_get_name(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + OUT char *pcName, IN uint32_t pcNameSize, IN char *pcExtra) +{ + enum ENUM_PARAM_NETWORK_TYPE eNetWorkType; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(pcName); + if (GLUE_CHK_PR2(prNetDev, pcName) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (netif_carrier_ok(prNetDev)) { + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryNetworkTypeInUse, + &eNetWorkType, sizeof(eNetWorkType), + TRUE, FALSE, FALSE, &u4BufLen); + + switch (eNetWorkType) { + case PARAM_NETWORK_TYPE_DS: + strncpy(pcName, "IEEE 802.11b", pcNameSize); + break; + case PARAM_NETWORK_TYPE_OFDM24: + strncpy(pcName, "IEEE 802.11bgn", pcNameSize); + break; + case PARAM_NETWORK_TYPE_AUTOMODE: + case PARAM_NETWORK_TYPE_OFDM5: + strncpy(pcName, "IEEE 802.11abgn", pcNameSize); + break; + case PARAM_NETWORK_TYPE_FH: + default: + strncpy(pcName, "IEEE 802.11", pcNameSize); + break; + } + } else { + strncpy(pcName, "Disconnected", pcNameSize); + } + + pcName[pcNameSize - 1] = '\0'; + + 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 + uint32_t u4ChnlFreq; /* Store channel or frequency information */ + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prIwFreq); + if (GLUE_CHK_PR2(prNetDev, prIwFreq) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + + /* If setting by frequency, convert to a channel */ + if ((prIwFreq->e == 1) && (prIwFreq->m >= 2.412e8) + && (prIwFreq->m <= 2.484e8)) { + + /* Change to KHz format */ + u4ChnlFreq = (uint32_t) (prIwFreq->m / (KILO / 10)); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetFrequency, &u4ChnlFreq, + sizeof(u4ChnlFreq), + FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EINVAL; + } + /* Setting by channel number */ + else if ((prIwFreq->m > KILO) || (prIwFreq->e > 0)) + return -EOPNOTSUPP; + /* Change to channel number format */ + u4ChnlFreq = (uint32_t) prIwFreq->m; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetChannel, &u4ChnlFreq, + sizeof(u4ChnlFreq), FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + 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) +{ + uint32_t u4Channel = 0; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prIwFreq); + if (GLUE_CHK_PR2(prNetDev, prIwFreq) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) 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, &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 ENUM_PARAM_OP_MODE eOpMode; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(pu4Mode); + if (GLUE_CHK_PR2(prNetDev, pu4Mode) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) 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", + __func__, *pu4Mode); + return -EOPNOTSUPP; + } + + + rStatus = kalIoctl(prGlueInfo, wlanoidSetInfrastructureMode, &eOpMode, + sizeof(eOpMode), FALSE, FALSE, TRUE, &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 ENUM_PARAM_OP_MODE eOpMode; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(pu4Mode); + if (GLUE_CHK_PR2(prNetDev, pu4Mode) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryInfrastructureMode, &eOpMode, + sizeof(eOpMode), TRUE, 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", __func__); + return -EINVAL; + } + + return 0; +} /* wext_get_mode */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To get the valid range for each configurable STA setting value. + * + * \param[in] prDev Net device requested. + * \param[in] prIwrInfo NULL. + * \param[in] prData Pointer to iw_point structure, not used. + * \param[out] pcExtra Pointer to buffer which is allocated by caller of this + * function, wext_support_ioctl() or ioctl_standard_call() + * in wireless.c. + * + * \retval 0 If data is valid. + * + * \note The extra buffer (pcExtra) is filled with information from driver. + */ +/*----------------------------------------------------------------------------*/ +static int +wext_get_range(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + IN struct iw_point *prData, OUT char *pcExtra) +{ + struct iw_range *prRange = NULL; + uint8_t aucSuppRate[PARAM_MAX_LEN_RATES_EX] = { 0 }; /* data buffers */ + int i = 0; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(pcExtra); + if (GLUE_CHK_PR2(prNetDev, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) 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, &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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prAddr); + if (GLUE_CHK_PR2(prNetDev, prAddr) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + /* if (!netif_carrier_ok(prNetDev)) { */ + /* return -ENOTCONN; */ + /* } */ + + if (prGlueInfo->eParamMediaStateIndicated == + PARAM_MEDIA_STATE_DISCONNECTED) { + memset(prAddr, 0, sizeof(struct sockaddr)); + return 0; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryBssid, prAddr->sa_data, + ETH_ALEN, TRUE, 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; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(pcExtra); + if (GLUE_CHK_PR2(prNetDev, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) 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, &u4BufLen); + return 0; + } + 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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int essid_len = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_DEV(prNetDev) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) 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, &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) +{ + uint32_t i = 0; + uint32_t j = 0; + struct PARAM_BSSID_LIST_EX *prList = NULL; + struct PARAM_BSSID_EX *prBss = NULL; + struct PARAM_VARIABLE_IE *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 */ + + uint32_t u4AllocBufLen = 0; + + /* arrange rate information */ + uint32_t u4HighestRate = 0; + char aucRatesBuf[64]; + uint32_t u4BufIndex; + + /* return value */ + int ret = 0; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prData); + ASSERT(pcExtra); + if (GLUE_CHK_PR3(prNetDev, prData, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (prData->length < sizeof(struct PARAM_BSSID_LIST_EX)) { + DBGLOG(INIT, WARN, "[wifi] invalid input length:%d < %d\n", + prData->length, + sizeof(struct PARAM_BSSID_LIST_EX)); + return -EINVAL; + } + + /* Initialize local variables */ + pcCur = pcExtra; + pcValidEntryEnd = pcExtra; + pcEnd = pcExtra + prData->length; /* end of extra buffer */ + + /* Allocate another query buffer to match internal structure needed */ + u4AllocBufLen = sizeof(struct PARAM_BSSID_LIST_EX); + + 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 */ + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryBssidList, prList, + u4AllocBufLen, TRUE, FALSE, FALSE, &u4BufLen); + + if (rStatus == WLAN_STATUS_INVALID_LENGTH) { + /* Buffer length is not large enough. */ + +#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 :%d\n", + u4BufLen); + ret = -ENOMEM; + goto error; + } + prList->NumberOfItems = 0; + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryBssidList, prList, + u4AllocBufLen, + TRUE, FALSE, FALSE, &u4BufLen); + + if (rStatus == WLAN_STATUS_INVALID_LENGTH) { + DBGLOG(INIT, INFO, "[wifi] larger buf:%d result:%d\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:%d\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) { + kalMemSet(&iwEvent, 0, sizeof(iwEvent)); + /* BSSID */ + iwEvent.cmd = SIOCGIWAP; + iwEvent.len = IW_EV_ADDR_LEN; + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.ap_addr.sa_family = ARPHRD_ETHER; + kalMemCopy(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 = snprintf(aucRatesBuf, sizeof(aucRatesBuf), + "Rates (Mb/s):"); + u4HighestRate = 0; + for (j = 0; j < PARAM_MAX_LEN_RATES_EX; ++j) { + uint8_t curRate = prBss->rSupportedRates[j] & 0x7F; + + if (curRate == 0) + break; + + if (curRate > u4HighestRate) + u4HighestRate = curRate; + + if (curRate == RATE_5_5M) + u4BufIndex += snprintf(aucRatesBuf + u4BufIndex, + sizeof(aucRatesBuf) + - u4BufIndex, " 5.5"); + else + u4BufIndex += snprintf(aucRatesBuf + u4BufIndex, + sizeof(aucRatesBuf) + - u4BufIndex, " %d", + curRate / 2); +#if DBG + if (u4BufIndex > sizeof(aucRatesBuf)) { + 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( + struct PARAM_FIXED_IEs)], + prBss->u4IELength - sizeof(struct PARAM_FIXED_IEs), 0xDD, + (uint8_t **) &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( + struct PARAM_FIXED_IEs)], + prBss->u4IELength - sizeof(struct PARAM_FIXED_IEs), 0xDD, + (uint8_t **) &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( + struct PARAM_FIXED_IEs)], + prBss->u4IELength - sizeof(struct PARAM_FIXED_IEs), 0x30, + (uint8_t **) &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(struct PARAM_FIXED_IEs)], + prBss->u4IELength - sizeof(struct PARAM_FIXED_IEs), + (uint8_t **) &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, + (uint8_t *) 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 = (struct PARAM_BSSID_EX *) ((char *)prBss + + prBss->u4Length); + } + + /* Update valid data length for caller function and upper layer + * applications. + */ + prData->length = (pcValidEntryEnd - pcExtra); + + /* kalIndicateStatusAndComplete(prGlueInfo, + * WLAN_STATUS_SCAN_COMPLETE, NULL, 0); + */ + +error: + /* free local query buffer */ + if (prList) + kalMemFree(prList, VIR_MEM_TYPE, u4AllocBufLen); + + return ret; +} /* wext_get_scan */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To set desired network name ESSID. + * + * \param[in] prDev Net device requested. + * \param[in] prIwrInfo NULL. + * \param[in] prEssid Pointer of iw_point header. + * \param[in] pcExtra Pointer to buffer srtoring essid string. + * + * \retval 0 If netif_carrier_ok. + * \retval -E2BIG Essid string length is too big. + * \retval -EINVAL pcExtra is null pointer. + * \retval -EFAULT Driver fail to set new essid. + * + * \note If string length is ok, device will try connecting to the new network. + */ +/*----------------------------------------------------------------------------*/ +static int +wext_set_essid(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + IN struct iw_point *prEssid, IN char *pcExtra) +{ + struct PARAM_SSID rNewSsid; + uint32_t cipher; + enum ENUM_WEP_STATUS eEncStatus; + enum ENUM_PARAM_AUTH_MODE eAuthMode; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prEssid); + ASSERT(pcExtra); + if (GLUE_CHK_PR3(prNetDev, prEssid, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) 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; + } 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; + break; + case IW_AUTH_KEY_MGMT_PSK: + eAuthMode = + (prGlueInfo->rWpaInfo.u4WpaVersion == + IW_AUTH_WPA_VERSION_WPA) ? + AUTH_MODE_WPA_PSK : AUTH_MODE_WPA2_PSK; + 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; */ + /* 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: + eAuthMode = AUTH_MODE_AUTO_SWITCH; + break; + } + } + + rStatus = kalIoctl(prGlueInfo, wlanoidSetAuthMode, &eAuthMode, + sizeof(eAuthMode), FALSE, FALSE, FALSE, &u4BufLen); + + /* set encryption status */ + cipher = prGlueInfo->rWpaInfo.u4CipherGroup | + prGlueInfo->rWpaInfo.u4CipherPairwise; + 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; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidSetEncryptionStatus, &eEncStatus, + sizeof(eEncStatus), + 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); + + + if (kalIoctl(prGlueInfo, + wlanoidSetSsid, + (void *)&rNewSsid, sizeof(struct PARAM_SSID), FALSE, FALSE, + TRUE, &u4BufLen) != WLAN_STATUS_SUCCESS) { + 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; */ + + struct PARAM_SSID *prSsid; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prEssid); + ASSERT(pcExtra); + + if (GLUE_CHK_PR3(prNetDev, prEssid, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + /* if (!netif_carrier_ok(prNetDev)) { */ + /* return -ENOTCONN; */ + /* } */ + + prSsid = kalMemAlloc(sizeof(struct PARAM_SSID), + VIR_MEM_TYPE); + + if (!prSsid) + return -ENOMEM; + + rStatus = kalIoctl(prGlueInfo, wlanoidQuerySsid, prSsid, + sizeof(struct PARAM_SSID), + TRUE, 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(struct PARAM_SSID)); + + return rStatus; +} /* 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) +{ + uint8_t aucSuppRate[PARAM_MAX_LEN_RATES_EX] = { 0 }; + uint8_t aucNewRate[PARAM_MAX_LEN_RATES_EX] = { 0 }; + uint32_t u4NewRateLen = 0; + uint32_t i; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prRate); + if (GLUE_CHK_PR2(prNetDev, prRate) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + + 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 */ + + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetDesiredRates, + &aucSuppRate, + sizeof(aucSuppRate), + &u4BufLen); + return 0; + } + /* iwconfig wlan0 rate fixed */ + + /* fix rate to what? DO NOTHING */ + return -EINVAL; + } + + aucNewRate[0] = prRate->value / + 500000; /* In unit of 500k */ + + for (i = 0; i < PARAM_MAX_LEN_RATES_EX; i++) { + /* check the given value is supported */ + if (aucSuppRate[i] == 0) + break; + + if (aucNewRate[0] == aucSuppRate[i]) { + u4NewRateLen = 1; + break; + } + } + + if (u4NewRateLen == 0) { + /* the given value is not supported */ + /* return error or use given rate as upper bound? */ + return -EINVAL; + } + + if (prRate->fixed == 0) { + /* add all rates lower than desired rate */ + for (i = 0; i < PARAM_MAX_LEN_RATES_EX; ++i) { + if (aucSuppRate[i] == 0) + break; + + if (aucSuppRate[i] < aucNewRate[0]) + aucNewRate[u4NewRateLen++] = aucSuppRate[i]; + } + } + + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetDesiredRates, &aucNewRate, + sizeof(aucNewRate), &u4BufLen); + return 0; +} /* wext_set_rate */ + +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To get current tx bit rate. + * + * \param[in] prDev Net device requested. + * \param[in] prIwrInfo NULL. + * \param[out] prRate Pointer to iw_param structure to store current tx rate. + * \param[in] pcExtra NULL. + * + * \retval 0 If netif_carrier_ok. + * \retval -ENOTCONN Otherwise. + * + * \note If netif_carrier_ok, current tx rate is stored in pRate. + */ +/*----------------------------------------------------------------------------*/ +static int +wext_get_rate(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, + OUT struct iw_param *prRate, IN char *pcExtra) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + uint32_t u4Rate = 0; + + ASSERT(prNetDev); + ASSERT(prRate); + if (GLUE_CHK_PR2(prNetDev, prRate) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (!netif_carrier_ok(prNetDev)) + return -ENOTCONN; + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryLinkSpeed, + &u4Rate, sizeof(u4Rate), + TRUE, 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) +{ + uint32_t u4RtsThresh; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prRts); + if (GLUE_CHK_PR2(prNetDev, prRts) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (prRts->value < 0 || prRts->value > 2347) + return -EINVAL; + + if (prRts->disabled == 1) + u4RtsThresh = 2347; + else + u4RtsThresh = (uint32_t) prRts->value; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetRtsThreshold, &u4RtsThresh, + sizeof(u4RtsThresh), + 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) +{ + uint32_t u4RtsThresh; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prRts); + if (GLUE_CHK_PR2(prNetDev, prRts) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryRtsThreshold, &u4RtsThresh, + sizeof(u4RtsThresh), TRUE, 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; */ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prTxPow); + if (GLUE_CHK_PR2(prNetDev, prTxPow) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (prTxPow->disabled) { + /* <1> disconnect */ + rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, NULL, + 0, FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + /* ToDo:: DBGLOG */ + DBGLOG(INIT, INFO, "######set disassoc failed\n"); + } else { + DBGLOG(INIT, INFO, "######set assoc ok\n"); + } + /* <2> mark to power state flag */ + DBGLOG(INIT, INFO, "set to acpi d3(0)\n"); + wlanSetAcpiState(prGlueInfo->prAdapter, ACPI_STATE_D0); + + } else { + DBGLOG(INIT, INFO, "set to acpi d0\n"); + wlanSetAcpiState(prGlueInfo->prAdapter, ACPI_STATE_D0); + } + + prGlueInfo->ePowerState = ParamDeviceStateD0; + 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; */ + + struct GLUE_INFO *prGlueInfo = NULL; + + ASSERT(prNetDev); + ASSERT(prTxPow); + if (GLUE_CHK_PR2(prNetDev, prTxPow) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + /* GeorgeKuo: wlanoidQueryAcpiDevicePowerState() reports capability, not + * current state. Use struct GLUE_INFO 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 ENUM_WEP_STATUS eEncMode; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prEnc); + if (GLUE_CHK_PR2(prNetDev, prEnc) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryEncryptionStatus, &eEncMode, + sizeof(eEncMode), TRUE, 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 uint8_t 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 ENUM_WEP_STATUS eEncStatus; + enum ENUM_PARAM_AUTH_MODE eAuthMode; + /* UINT_8 wepBuf[48]; */ + struct PARAM_WEP *prWepKey = (struct PARAM_WEP *) wepBuf; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prEnc); + ASSERT(pcExtra); + if (GLUE_CHK_PR3(prNetDev, prEnc, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) 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, &u4BufLen); + + eEncStatus = ENUM_ENCRYPTION_DISABLED; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetEncryptionStatus, + &eEncStatus, sizeof(eEncStatus), + 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, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "wlanoidSetAddWep fail 0x%x\n", + rStatus); + return -EFAULT; + } + + /* change to auto switch */ + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_SHARED_KEY | + IW_AUTH_ALG_OPEN_SYSTEM; + eAuthMode = AUTH_MODE_AUTO_SWITCH; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetAuthMode, &eAuthMode, + sizeof(eAuthMode), + FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + 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 ENUM_WEP_STATUS), + FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + 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 + enum PARAM_POWER_MODE ePowerMode; + int32_t i4PowerValue; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + struct PARAM_POWER_MODE_ rPowerMode; + + ASSERT(prNetDev); + ASSERT(prPower); + if (GLUE_CHK_PR2(prNetDev, prPower) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (!prGlueInfo) + return -EFAULT; + + if (!prGlueInfo->prAdapter->prAisBssInfo) + return -EFAULT; + + 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", + __func__, prPower->value); + + return -EINVAL; + } + } + + rPowerMode.ePowerMode = ePowerMode; + rPowerMode.ucBssIdx = + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, sizeof(struct PARAM_POWER_MODE_), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + 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) +{ + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + enum PARAM_POWER_MODE ePowerMode = Param_PowerModeCAM; + + ASSERT(prNetDev); + ASSERT(prPower); + if (GLUE_CHK_PR2(prNetDev, prPower) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) 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 + + + 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) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + ASSERT(prNetDev); + ASSERT(prAuth); + if (GLUE_CHK_PR2(prNetDev, prAuth) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) 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) { + uint32_t u4BufLen; + uint32_t rStatus; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetWapiMode, + &prAuth->value, sizeof(uint32_t), + FALSE, FALSE, TRUE, &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: + prGlueInfo->rWpaInfo.u4Mfp = prAuth->value; + break; +#endif +#if CFG_SUPPORT_WAPI + case IW_AUTH_WAPI_ENABLED: { + uint32_t u4BufLen; + uint32_t rStatus; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetWapiMode, + &prAuth->value, sizeof(uint32_t), + FALSE, FALSE, TRUE, &u4BufLen); + } + DBGLOG(INIT, INFO, "IW_AUTH_WAPI_ENABLED :%d\n", + prAuth->value); + break; +#endif + default: + 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 +uint8_t keyStructBuf[1024]; /* add/remove key shared buffer */ +#else +uint8_t 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) +{ + struct PARAM_REMOVE_KEY *prRemoveKey = + (struct PARAM_REMOVE_KEY *) keyStructBuf; + struct PARAM_KEY *prKey = (struct PARAM_KEY *) keyStructBuf; + + struct PARAM_WEP *prWepKey = (struct PARAM_WEP *) wepBuf; + + struct iw_encode_ext *prIWEncExt = (struct iw_encode_ext *) + pcExtra; + + enum ENUM_WEP_STATUS eEncStatus; + enum ENUM_PARAM_AUTH_MODE eAuthMode; + /* ENUM_PARAM_OP_MODE_T eOpMode = NET_TYPE_AUTO_SWITCH; */ + +#if CFG_SUPPORT_WAPI + struct PARAM_WPI_KEY *prWpiKey = (struct PARAM_WPI_KEY *) + keyStructBuf; +#endif + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prEnc); + if (GLUE_CHK_PR3(prNetDev, prEnc, pcExtra) == FALSE) + return -EINVAL; + + if (prIWEncExt == NULL) { + DBGLOG(REQ, ERROR, "prIWEncExt is NULL!\n"); + return -EINVAL; + } + + prGlueInfo = *((struct GLUE_INFO **) 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) { + return 0; + } + /* KeyID */ + prWpiKey->ucKeyID = (prEnc->flags & IW_ENCODE_INDEX); + prWpiKey->ucKeyID--; + if (prWpiKey->ucKeyID > 1) { + /* key id is out of range */ + return -EINVAL; + } + + if (prIWEncExt->key_len != 32) { + /* key length not valid */ + return -EINVAL; + } + + 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[0], &prIWEncExt->tx_seq[0], + IW_ENCODE_SEQ_MAX_SIZE); + memcpy(&prWpiKey->aucPN[IW_ENCODE_SEQ_MAX_SIZE], + &prIWEncExt->rx_seq[0], IW_ENCODE_SEQ_MAX_SIZE); + + /* 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(struct PARAM_WPI_KEY), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + /* do nothing */ + } + + } else +#endif + { + + if ((prEnc->flags & IW_ENCODE_MODE) == IW_ENCODE_DISABLED) { + prRemoveKey->u4Length = sizeof(*prRemoveKey); + memcpy(prRemoveKey->arBSSID, + prIWEncExt->addr.sa_data, 6); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetRemoveKey, + prRemoveKey, prRemoveKey->u4Length, + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "remove key error:%x\n", + rStatus); + return 0; + } + /* return 0; */ + + 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, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, + "wlanoidSetAddWep fail 0x%x\n", + rStatus); + return -EFAULT; + } + + /* change to auto switch */ + prGlueInfo->rWpaInfo.u4AuthAlg = + IW_AUTH_ALG_SHARED_KEY | + IW_AUTH_ALG_OPEN_SYSTEM; + eAuthMode = AUTH_MODE_AUTO_SWITCH; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAuthMode, + &eAuthMode, + sizeof(eAuthMode), + FALSE, FALSE, FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, + "wlanoidSetAuthMode fail 0x%x\n", + rStatus); + return -EFAULT; + } + + prGlueInfo->rWpaInfo.u4CipherPairwise = + IW_AUTH_CIPHER_WEP104 | + IW_AUTH_CIPHER_WEP40; + prGlueInfo->rWpaInfo.u4CipherGroup = + IW_AUTH_CIPHER_WEP104 | + IW_AUTH_CIPHER_WEP40; + + eEncStatus = ENUM_WEP_ENABLED; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEncryptionStatus, + &eEncStatus, + sizeof(enum ENUM_WEP_STATUS), + FALSE, FALSE, FALSE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, + "wlanoidSetEncryptionStatus fail 0x%x\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%x\n", + prKey->u4KeyIndex); + /* key id is out of range */ + return -EINVAL; + } + + /* bit(31) and bit(30) are shared by pKey and + * pRemoveKey + */ + /* Tx Key Bit(31) */ + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + prKey->u4KeyIndex |= 0x1UL << 31; + + /* 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(((uint8_t *) prKey->aucKeyMaterial) + 16, + prIWEncExt->key + 24, 8); + memcpy((prKey->aucKeyMaterial) + 24, + prIWEncExt->key + 16, 8); + } else { + if (prIWEncExt->key_len > + sizeof(prKey->aucKeyMaterial)) { + DBGLOG(REQ, ERROR, + "prIWEncExt->key_len: %u is too long!\n", + prIWEncExt->key_len); + return -EINVAL; + } + memcpy(prKey->aucKeyMaterial, prIWEncExt->key, + prIWEncExt->key_len); + } + + prKey->u4KeyLength = prIWEncExt->key_len; + prKey->u4Length = ((unsigned long) &(((struct PARAM_KEY *) + 0)->aucKeyMaterial)) + prKey->u4KeyLength; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetAddKey, prKey, + prKey->u4Length, + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "add key error:%x\n", rStatus); + return -EFAULT; + } + break; + } + } + + return 0; +} /* wext_set_encode_ext */ + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Set country code + * + * \param[in] prNetDev Net device requested. + * \param[in] prData iwreq.u.data carries country code value. + * + * \retval 0 For success. + * \retval -EEFAULT For fail. + * + * \note Country code is stored and channel list is updated based on current + * country domain. + */ +/*----------------------------------------------------------------------------*/ +static int wext_set_country(IN struct net_device *prNetDev, + IN struct iw_point *prData) +{ + struct GLUE_INFO *prGlueInfo; + uint32_t rStatus; + uint32_t u4BufLen; + uint8_t aucCountry[COUNTRY_CODE_LEN]; + + ASSERT(prNetDev); + + /* prData->pointer should be like "COUNTRY US", "COUNTRY EU" + * and "COUNTRY JP" + */ + if (GLUE_CHK_PR2(prNetDev, prData) == FALSE + || !prData->pointer || prData->length < COUNTRY_CODE_LEN) + return -EINVAL; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (copy_from_user(aucCountry, prData->pointer, + COUNTRY_CODE_LEN)) + return -EFAULT; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetCountryCode, + &aucCountry[COUNTRY_CODE_LEN - 2], 2, + FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "Set country code error: %x\n", rStatus); + return -EFAULT; + } + + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To report the iw private args table to user space. + * + * \param[in] prNetDev Net device requested. + * \param[out] prData iwreq.u.data to carry the private args table. + * + * \retval 0 For success. + * \retval -E2BIG For user's buffer size is too small. + * \retval -EFAULT For fail. + * + */ +/*----------------------------------------------------------------------------*/ +int wext_get_priv(IN struct net_device *prNetDev, + OUT struct iw_point *prData) +{ + uint16_t u2BufferSize = prData->length; + + /* Update our private args table size */ + prData->length = (__u16)sizeof(rIwPrivTable); + if (u2BufferSize < prData->length) + return -E2BIG; + + if (prData->length) { + if (copy_to_user(prData->pointer, rIwPrivTable, + sizeof(rIwPrivTable))) + return -EFAULT; + } + + return 0; +} /* wext_get_priv */ + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief ioctl() (Linux Wireless Extensions) routines + * + * \param[in] prDev Net device requested. + * \param[in] ifr The ifreq structure for seeting the wireless extension. + * \param[in] i4Cmd The wireless extension ioctl command. + * + * \retval zero On success. + * \retval -EOPNOTSUPP If the cmd is not supported. + * \retval -EFAULT If copy_to_user goes wrong. + * \retval -EINVAL If any value's out of range. + * + * \note + */ +/*----------------------------------------------------------------------------*/ +int wext_support_ioctl(IN struct net_device *prDev, + IN struct ifreq *prIfReq, IN int i4Cmd) +{ + /* 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; + uint32_t u4ExtraSize = 0; + + /* prDev is verified in the caller function wlanDoIOCTL() */ + DBGLOG(REQ, INFO, "CMD:0x%x\n", 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, + sizeof(iwr->u.name), NULL); + break; + + /* case SIOCSIWNWID: 0x8B02, deprecated */ + /* case SIOCGIWNWID: 0x8B03, deprecated */ + + case SIOCSIWFREQ: /* 0x8B04, set channel */ + ret = wext_set_freq(prDev, NULL, &iwr->u.freq, NULL); + break; + + case SIOCGIWFREQ: /* 0x8B05, get channel */ + ret = wext_get_freq(prDev, NULL, &iwr->u.freq, NULL); + break; + + case SIOCSIWMODE: /* 0x8B06, set operation mode */ + ret = wext_set_mode(prDev, NULL, &iwr->u.mode, NULL); + /* ret = 0; */ + break; + + case SIOCGIWMODE: /* 0x8B07, get operation mode */ + ret = wext_get_mode(prDev, NULL, &iwr->u.mode, NULL); + break; + + /* case SIOCSIWSENS: 0x8B08, unsupported */ + /* case SIOCGIWSENS: 0x8B09, unsupported */ + + /* case SIOCSIWRANGE: 0x8B0A, unused */ + case SIOCGIWRANGE: /* 0x8B0B, get range of parameters */ + if (iwr->u.data.pointer != NULL) { + /* Buffer size should be large enough */ + if (iwr->u.data.length < sizeof(struct iw_range)) { + ret = -E2BIG; + break; + } + + prExtraBuf = kalMemAlloc(sizeof(struct iw_range), + VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + /* reset all fields */ + memset(prExtraBuf, 0, sizeof(struct iw_range)); + iwr->u.data.length = sizeof(struct iw_range); + + ret = wext_get_range(prDev, NULL, &iwr->u.data, + prExtraBuf); + /* Push up to the caller */ + if (copy_to_user(iwr->u.data.pointer, prExtraBuf, + iwr->u.data.length)) + ret = -EFAULT; + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, + sizeof(struct iw_range)); + prExtraBuf = NULL; + } else { + ret = -EINVAL; + } + break; + + case SIOCSIWPRIV: /* 0x8B0C, set country code */ + ret = wext_set_country(prDev, &iwr->u.data); + break; + + case SIOCGIWPRIV: /* 0x8B0D, get private args table */ + ret = wext_get_priv(prDev, &iwr->u.data); + break; + + /* 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; + } + 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 > %d)\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) */ + u4ExtraSize = iwr->u.essid.length; + if (u4ExtraSize > 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, + u4ExtraSize)) { + ret = -EFAULT; + } else { + ret = wext_set_essid(prDev, NULL, &iwr->u.essid, + prExtraBuf); + } + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, IW_ESSID_MAX_SIZE + 4); + prExtraBuf = NULL; + break; + +#endif + + case SIOCGIWESSID: /* 0x8B1B, get SSID */ + u4ExtraSize = iwr->u.essid.length; + if (!iwr->u.essid.pointer) { + ret = -EINVAL; + break; + } + + if (u4ExtraSize != IW_ESSID_MAX_SIZE + && u4ExtraSize != IW_ESSID_MAX_SIZE + 1) { + 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 + 1, + 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 + 1); + 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 */ + u4ExtraSize = iwr->u.encoding.length; + if (iwr->u.encoding.pointer) { + if (u4ExtraSize > 16) { + ret = -E2BIG; + break; + } + + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, iwr->u.encoding.pointer, + u4ExtraSize)) + ret = -EFAULT; + + if (ret == 0) + ret = wext_set_encode(prDev, NULL, + &iwr->u.encoding, + prExtraBuf); + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); + prExtraBuf = NULL; + + } else if (u4ExtraSize != 0) + ret = -EINVAL; + 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) { + struct GLUE_INFO *prGlueInfo = *((struct GLUE_INFO **) + netdev_priv(prDev)); + + u4ExtraSize = iwr->u.data.length; + if (1 /* wlanQueryWapiMode(prGlueInfo->prAdapter) */) { + /* Fixed length structure */ +#if CFG_SUPPORT_WAPI + if (u4ExtraSize > 42 /* The max wapi ie buffer + */ + ) { +#else + /*aucWSCAssocInfoIE max size */ + if (u4ExtraSize > 200) { +#endif + ret = -EINVAL; + break; + } + if (u4ExtraSize) { + prExtraBuf = kalMemAlloc(u4ExtraSize, + VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + if (copy_from_user(prExtraBuf, + iwr->u.data.pointer, u4ExtraSize)) + ret = -EFAULT; + else + wext_support_ioctl_SIOCSIWGENIE( + prGlueInfo, prExtraBuf, + u4ExtraSize); + 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; + if (u4ExtraSize > sizeof(struct iw_encode_ext)) { + ret = -EINVAL; + break; + } + + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, iwr->u.encoding.pointer, + u4ExtraSize)) + 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: + { + wext_support_ioctl_SIOCSIWPMKSA_Action( + prDev, prExtraBuf, + IW_PMKSA_ADD, &ret); + } + break; + case IW_PMKSA_REMOVE: + break; + case IW_PMKSA_FLUSH: + { + wext_support_ioctl_SIOCSIWPMKSA_Action( + prDev, prExtraBuf, + IW_PMKSA_FLUSH, &ret); + } + 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: + ret = -EOPNOTSUPP; + break; + } + + + return ret; +} /* wext_support_ioctl */ + +static void wext_support_ioctl_SIOCSIWGENIE( + IN struct GLUE_INFO *prGlueInfo, IN char *prExtraBuf, + IN uint32_t u4ExtraSize) +{ + uint32_t rStatus; + uint32_t u4BufLen; +#if CFG_SUPPORT_WAPI + rStatus = kalIoctl(prGlueInfo, wlanoidSetWapiAssocInfo, prExtraBuf, + u4ExtraSize, FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { +#endif +#if CFG_SUPPORT_WPS2 + uint8_t *prDesiredIE = NULL; + + if (wextSrchDesiredWPSIE(prExtraBuf, u4ExtraSize, 0xDD, + (uint8_t **) &prDesiredIE)) { + rStatus = + kalIoctl(prGlueInfo, wlanoidSetWSCAssocInfo, + prDesiredIE, IE_SIZE(prDesiredIE), + FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + /* do nothing */ + } + } +#endif +#if CFG_SUPPORT_WAPI + } +#endif + +} + +static void +wext_support_ioctl_SIOCSIWPMKSA_Action(IN struct net_device + *prDev, IN char *prExtraBuf, IN int ioMode, OUT int *ret) +{ + struct GLUE_INFO *prGlueInfo = *((struct GLUE_INFO **) + netdev_priv(prDev)); + uint32_t rStatus; + uint32_t u4BufLen; + struct PARAM_PMKID *prPmkid; + + switch (ioMode) { + case IW_PMKSA_ADD: + prPmkid = (struct PARAM_PMKID *) kalMemAlloc(8 + sizeof( + struct PARAM_BSSID_INFO), VIR_MEM_TYPE); + if (!prPmkid) { + DBGLOG(INIT, INFO, + "Can not alloc memory for IW_PMKSA_ADD\n"); + *ret = -ENOMEM; + break; + } + + prPmkid->u4Length = 8 + sizeof(struct PARAM_BSSID_INFO); + 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(struct PARAM_PMKID), + FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "add pmkid error:%x\n", rStatus); + + kalMemFree(prPmkid, VIR_MEM_TYPE, + 8 + sizeof(struct PARAM_BSSID_INFO)); + break; + case IW_PMKSA_FLUSH: + prPmkid = (struct PARAM_PMKID *) 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(struct PARAM_PMKID), + FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "flush pmkid error:%x\n", rStatus); + + kalMemFree(prPmkid, VIR_MEM_TYPE, 8); + break; + default: + break; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To send an event (RAW socket pacekt) to user process actively. + * + * \param[in] prGlueInfo Glue layer info. + * \param[in] u4cmd Which event command we want to indicate to user process. + * \param[in] pData Data buffer to be indicated. + * \param[in] dataLen Available data size in pData. + * + * \return (none) + * + * \note Event is indicated to upper layer if cmd is supported and data is + * valid. Using of kernel symbol wireless_send_event(), which is defined + * in after WE-14 (2.4.20). + */ +/*----------------------------------------------------------------------------*/ +void +wext_indicate_wext_event(IN struct GLUE_INFO *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) + kalMemCopy(&wrqu.ap_addr.sa_data, pucData, ETH_ALEN); + else + eth_zero_addr((u8 *)&wrqu.ap_addr.sa_data); + 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 */ + /* RSN IE found */ + } +#if 0 + else if (wextSrchDesiredWPSIE(pucData, u4dataLen, 0xDD, + &pucDesiredIE)) { + /* WPS IE found */ + /* WPS IE found */ + } +#endif + else if (wextSrchDesiredWPAIE(pucData, u4dataLen, 0xDD, + &pucDesiredIE)) { + /* WPA IE found */ + /* WPA IE found */ + } +#if CFG_SUPPORT_WAPI /* Android+ */ + else if (wextSrchDesiredWAPIIE(pucData, u4dataLen, + &pucDesiredIE)) { + /* 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="); + /* 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) { + struct PARAM_AUTH_REQUEST *pAuthReq = + (struct PARAM_AUTH_REQUEST *) pucData; + uint32_t nleft = 0, nsize = 0; + /* under WE-18, only IWEVCUSTOM can be used */ + u4Cmd = IWEVCUSTOM; + pucExtraInfo = aucExtraInfoBuf; + nleft = sizeof(aucExtraInfoBuf); + nsize = snprintf(pucExtraInfo, nleft, + "MLME-MICHAELMICFAILURE.indication "); + if (nsize < nleft) { + nleft -= nsize; + pucExtraInfo += nsize; + } + + nsize = snprintf(pucExtraInfo, + nleft, "%s", + (pAuthReq->u4Flags == + PARAM_AUTH_REQUEST_GROUP_ERROR) ? + "groupcast " : "unicast "); + + if (nsize < nleft) { + nleft -= nsize; + pucExtraInfo += nsize; + } + wrqu.data.length = sizeof(aucExtraInfoBuf) - nleft; + 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 + struct PARAM_PMKID_CANDIDATE *prPmkidCand = + (struct PARAM_PMKID_CANDIDATE *) 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, (uint8_t *) &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 + goto skip_indicate_event; +#endif + } else { + goto skip_indicate_event; + } + break; + + case IWEVCUSTOM: + u4Cmd = IWEVCUSTOM; + pucExtraInfo = aucExtraInfoBuf; + kalMemCopy(pucExtraInfo, pucData, sizeof(struct PTA_IPC)); + wrqu.data.length = sizeof(struct PTA_IPC); + break; + + default: + 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) +{ + + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct GLUE_INFO *prGlueInfo = NULL; + struct iw_statistics *pStats = NULL; + int32_t i4Rssi; + uint32_t bufLen = 0; + + prGlueInfo = *((struct GLUE_INFO **) 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, &bufLen); + +stat_out: + return pStats; +} /* wlan_get_wireless_stats */ + +/* Standard call implementations */ +static int std_get_name(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_name(prDev, NULL, (char *)(&(prData->name)), + sizeof(prData->name), NULL); +} + +static int std_set_freq(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_freq(prDev, NULL, &(prData->freq), NULL); +} + +static int std_get_freq(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_freq(prDev, NULL, &(prData->freq), NULL); +} + +static int std_set_mode(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_mode(prDev, NULL, &prData->mode, NULL); +} + +static int std_get_mode(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_mode(prDev, NULL, &prData->mode, NULL); +} + +static int std_set_ap(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + int ret = 0; + + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + + if (prData->ap_addr.sa_data[0] == 0 && + prData->ap_addr.sa_data[1] == 0 && + prData->ap_addr.sa_data[2] == 0 && + prData->ap_addr.sa_data[3] == 0 && + prData->ap_addr.sa_data[4] == 0 + && prData->ap_addr.sa_data[5] == 0) { + /* WPA Supplicant will set 000000000000 in + * wpa_driver_wext_deinit(), do nothing here or + * disassoc again? + */ + ret = 0; + } else { + ret = wext_set_ap(prDev, NULL, &(prData->ap_addr), NULL); + } + return ret; +} + +static int std_get_ap(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_ap(prDev, NULL, &(prData->ap_addr), NULL); +} + +static int std_get_rate(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_rate(prDev, NULL, &prData->bitrate, NULL); +} + +static int std_set_rts(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_rts(prDev, NULL, &(prData->rts), NULL); +} + +static int std_get_rts(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_rts(prDev, NULL, &prData->rts, NULL); +} + +static int std_get_frag(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_frag(prDev, NULL, &prData->frag, NULL); +} + +static int std_set_txpow(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_txpow(prDev, NULL, &(prData->txpower), NULL); +} + +static int std_get_txpow(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_txpow(prDev, NULL, &prData->txpower, NULL); +} + +static int std_set_power(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_power(prDev, NULL, &prData->power, NULL); +} + +static int std_get_power(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_power(prDev, NULL, &prData->power, NULL); +} + +static int std_get_range(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_range(prDev, NULL, &(prData->data), + pcExtra); +} + +static int std_set_priv(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_country(prDev, &(prData->data)); +} + +static int std_get_priv(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_priv(prDev, &(prData->data)); +} + +static int std_set_scan(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_scan(prDev, NULL, NULL, NULL); +} + +static int std_set_mlme(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_mlme(prDev, NULL, &(prData->data), pcExtra); +} + +static int std_get_scan(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_scan(prDev, NULL, &(prData->data), pcExtra); +} + +static int std_set_essid(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_essid(prDev, NULL, &(prData->essid), pcExtra); +} + +static int std_get_essid(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_essid(prDev, NULL, &(prData->essid), pcExtra); +} + +static int std_set_encode(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_encode(prDev, NULL, + &(prData->encoding), + pcExtra); +} + +static int std_get_encode(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_get_encode(prDev, NULL, &(prData->encoding), NULL); +} + +static int std_set_auth(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_auth(prDev, NULL, &(prData->param), NULL); +} + +#if WIRELESS_EXT > 17 +static int std_set_genie(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + uint32_t u4ExtraSize = prData->data.length; + struct GLUE_INFO *prGlueInfo = NULL; + + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + +#if CFG_SUPPORT_WAPI + /* The max wapi ie buffer */ + if (u4ExtraSize > 42) + return -EINVAL; +#endif + + if (prData->data.pointer) { + u4ExtraSize = prData->data.length; + prGlueInfo = *((struct GLUE_INFO **) + netdev_priv(prDev)); + wext_support_ioctl_SIOCSIWGENIE( + prGlueInfo, pcExtra, + u4ExtraSize); + } + + return 0; +} +#endif /* end of WIRELESS_EXT */ + +static int std_set_encode_ext(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + return wext_set_encode_ext(prDev, NULL, &(prData->encoding), + pcExtra); +} + +static int std_set_pmska(struct net_device *prDev, + struct iw_request_info *rIwReqInfo, + union iwreq_data *prData, + char *pcExtra) +{ + int ret = 0; + + DBGLOG(INIT, INFO, " mtk std ioctl is called.\n"); + + switch (((struct iw_pmksa *)pcExtra)->cmd) { + case IW_PMKSA_ADD: + wext_support_ioctl_SIOCSIWPMKSA_Action( + prDev, pcExtra, + IW_PMKSA_ADD, &ret); + break; + case IW_PMKSA_REMOVE: + break; + case IW_PMKSA_FLUSH: + wext_support_ioctl_SIOCSIWPMKSA_Action( + prDev, pcExtra, + IW_PMKSA_FLUSH, &ret); + break; + default: + DBGLOG(INIT, INFO, + "UNKNOWN iw_pmksa command:%d\n", + ((struct iw_pmksa *)pcExtra) + ->cmd); + ret = -EFAULT; + break; + } + return ret; +} + + +#endif /* WIRELESS_EXT */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_wext_priv.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_wext_priv.c new file mode 100644 index 0000000000000..2ed883027395e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/gl_wext_priv.c @@ -0,0 +1,18893 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux + * /gl_wext_priv.c#8 + */ + +/*! \file gl_wext_priv.c + * \brief This file includes private ioctl support. + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" +#include "gl_os.h" +#include "gl_wext_priv.h" + +#if CFG_SUPPORT_QA_TOOL +#include "gl_ate_agent.h" +#include "gl_qa_agent.h" +#endif + +#if CFG_SUPPORT_WAPI +#include "gl_sec.h" +#endif +#if CFG_ENABLE_WIFI_DIRECT +#include "gl_p2p_os.h" +#endif + +/* + * #if CFG_SUPPORT_QA_TOOL + * extern UINT_16 g_u2DumpIndex; + * #endif + */ + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define NUM_SUPPORTED_OIDS (sizeof(arWlanOidReqTable) / \ + sizeof(struct WLAN_REQ_ENTRY)) +#define CMD_OID_BUF_LENGTH 4096 + +#define CFG_STAT_DBG_PEER_NUM 10 + +/******************************************************************************* + * 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 struct NDIS_TRANSPORT_STRUCT *prNdisReq, + OUT uint32_t *pu4OutputLen); + +static int +priv_set_ndis(IN struct net_device *prNetDev, + IN struct NDIS_TRANSPORT_STRUCT *prNdisReq, + OUT uint32_t *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 u_int8_t reqSearchSupportedOidEntry(IN uint32_t rOid, + OUT struct WLAN_REQ_ENTRY **ppWlanReqEntry); + +#if 0 +static uint32_t +reqExtQueryConfiguration(IN struct GLUE_INFO *prGlueInfo, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +static uint32_t +reqExtSetConfiguration(IN struct GLUE_INFO *prGlueInfo, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif + +static uint32_t +reqExtSetAcpiDevicePowerState(IN struct GLUE_INFO + *prGlueInfo, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +static uint8_t aucOidBuf[CMD_OID_BUF_LENGTH] = { 0 }; + +/* OID processing table */ +/* Order is important here because the OIDs should be in order of + * increasing value for binary searching. + */ +static struct WLAN_REQ_ENTRY arWlanOidReqTable[] = { +#if 0 + { + (NDIS_OID)rOid, + (uint8_t *)pucOidName, + fgQryBufLenChecking, fgSetBufLenChecking, + fgIsHandleInGlueLayerOnly, u4InfoBufLen, + pfOidQueryHandler, + pfOidSetHandler + } +#endif + /* 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(uint8_t) * PARAM_MAX_LEN_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(struct PARAM_802_11_CONFIG), + * (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(enum 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 0 +#if PTA_ENABLED + { + OID_CUSTOM_BT_COEXIST_CTRL, + DISP_STRING("OID_CUSTOM_BT_COEXIST_CTRL"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, + sizeof(PARAM_CUSTOM_BT_COEXIST_T), + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetBtCoexistCtrl + }, +#endif + + { + OID_CUSTOM_POWER_MANAGEMENT_PROFILE, + DISP_STRING("OID_CUSTOM_POWER_MANAGEMENT_PROFILE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryPwrMgmtProfParam, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetPwrMgmtProfParam}, + { + OID_CUSTOM_PATTERN_CONFIG, + DISP_STRING("OID_CUSTOM_PATTERN_CONFIG"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, + sizeof(PARAM_CUSTOM_PATTERN_SEARCH_CONFIG_STRUCT_T), + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetPatternConfig + }, + { + OID_CUSTOM_BG_SSID_SEARCH_CONFIG, + DISP_STRING("OID_CUSTOM_BG_SSID_SEARCH_CONFIG"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetBgSsidParam + }, + { + OID_CUSTOM_VOIP_SETUP, + DISP_STRING("OID_CUSTOM_VOIP_SETUP"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryVoipConnectionStatus, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetVoipConnectionStatus + }, + { + OID_CUSTOM_ADD_TS, + DISP_STRING("OID_CUSTOM_ADD_TS"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidAddTS + }, + { + OID_CUSTOM_DEL_TS, + DISP_STRING("OID_CUSTOM_DEL_TS"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidDelTS + }, + +#if CFG_LP_PATTERN_SEARCH_SLT + { + OID_CUSTOM_SLT, + DISP_STRING("OID_CUSTOM_SLT"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQuerySltResult, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetSltMode + }, +#endif + + { + OID_CUSTOM_ROAMING_EN, + DISP_STRING("OID_CUSTOM_ROAMING_EN"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryRoamingFunction, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetRoamingFunction}, + { + OID_CUSTOM_WMM_PS_TEST, + DISP_STRING("OID_CUSTOM_WMM_PS_TEST"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetWiFiWmmPsTest + }, + { + OID_CUSTOM_COUNTRY_STRING, + DISP_STRING("OID_CUSTOM_COUNTRY_STRING"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryCurrentCountry, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetCurrentCountry + }, + +#if CFG_SUPPORT_802_11D + { + OID_CUSTOM_MULTI_DOMAIN_CAPABILITY, + DISP_STRING("OID_CUSTOM_MULTI_DOMAIN_CAPABILITY"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryMultiDomainCap, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetMultiDomainCap + }, +#endif + + { + OID_CUSTOM_GPIO2_MODE, + DISP_STRING("OID_CUSTOM_GPIO2_MODE"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, + sizeof(ENUM_PARAM_GPIO2_MODE_T), + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetGPIO2Mode}, + { + OID_CUSTOM_CONTINUOUS_POLL, + DISP_STRING("OID_CUSTOM_CONTINUOUS_POLL"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, + sizeof(PARAM_CONTINUOUS_POLL_T), + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryContinuousPollInterval, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetContinuousPollProfile + }, + { + OID_CUSTOM_DISABLE_BEACON_DETECTION, + DISP_STRING("OID_CUSTOM_DISABLE_BEACON_DETECTION"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, 4, + (PFN_OID_HANDLER_FUNC_REQ) + wlanoidQueryDisableBeaconDetectionFunc, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetDisableBeaconDetectionFunc + }, + + /* WPS */ + { + OID_CUSTOM_DISABLE_PRIVACY_CHECK, + DISP_STRING("OID_CUSTOM_DISABLE_PRIVACY_CHECK"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, 4, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetDisablePriavcyCheck + }, +#endif + + { + OID_CUSTOM_MCR_RW, + DISP_STRING("OID_CUSTOM_MCR_RW"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, + sizeof(struct PARAM_CUSTOM_MCR_RW_STRUCT), + (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(struct PARAM_CUSTOM_EEPROM_RW_STRUCT), + (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(struct PARAM_CUSTOM_SW_CTRL_STRUCT), + (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(struct PARAM_CUSTOM_MEM_DUMP_STRUCT), + (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 + } + , + +#if 0 + { + OID_CUSTOM_TEST_RX_STATUS, + DISP_STRING("OID_CUSTOM_TEST_RX_STATUS"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, + sizeof(struct PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT), + (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(struct PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT), + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryRfTestTxStatus, + NULL + }, +#endif + { + 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"), + /* PeiHsuan Temp Remove this check for workaround Gen2/Gen3 EM + * Mode Modification + */ + /* TRUE, TRUE, ENUM_OID_DRIVER_CORE, + * sizeof(PARAM_MTK_WIFI_TEST_STRUCT_T), + */ + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestQueryAutoTest, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestSetAutoTest + } + , + { + OID_CUSTOM_TEST_ICAP_MODE, + DISP_STRING("OID_CUSTOM_TEST_ICAP_MODE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + NULL, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestSetTestIcapMode + } + , + + /* 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(struct PTA_IPC), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryBT, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetBT + } + , +#endif +#if 0 + { + 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 + }, +#endif + + { + OID_CUSTOM_MTK_NVRAM_RW, + DISP_STRING("OID_CUSTOM_MTK_NVRAM_RW"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, + sizeof(struct PARAM_CUSTOM_EEPROM_RW_STRUCT), + (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 ENUM_CFG_SRC_TYPE), + (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 ENUM_EEPROM_TYPE), + (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(struct PARAM_WPI_KEY), + 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 + +#if CFG_SUPPORT_LOWLATENCY_MODE + /* Note: we should put following code in order */ + { + OID_CUSTOM_LOWLATENCY_MODE, /* 0xFFA0CC00 */ + DISP_STRING("OID_CUSTOM_LOWLATENCY_MODE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(uint32_t), + NULL, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetLowLatencyMode + } + , +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + + { + OID_IPC_WIFI_LOG_UI, + DISP_STRING("OID_IPC_WIFI_LOG_UI"), + FALSE, + FALSE, + ENUM_OID_DRIVER_CORE, + sizeof(struct PARAM_WIFI_LOG_LEVEL_UI), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryWifiLogLevelSupport, + NULL + } + , + + { + OID_IPC_WIFI_LOG_LEVEL, + DISP_STRING("OID_IPC_WIFI_LOG_LEVEL"), + FALSE, + FALSE, + ENUM_OID_DRIVER_CORE, + sizeof(struct PARAM_WIFI_LOG_LEVEL), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryWifiLogLevel, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetWifiLogLevel + } + , +}; + +/******************************************************************************* + * 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; + + /* prNetDev 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: +#if CFG_MTK_ENGINEER_MODE_SUPPORT + case IOCTL_SET_STRUCT_FOR_EM: +#endif + 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)); + +#if (CFG_SUPPORT_QA_TOOL) + case IOCTL_QA_TOOL_DAEMON: + return priv_qa_agent(prNetDev, &rIwReqInfo, &(prIwReq->u), + (char *) &(prIwReq->u)); +#endif + + /* This case need to fall through */ + case IOC_AP_GET_STA_LIST: + /* This case need to fall through */ + case IOC_AP_SET_MAC_FLTR: + /* This case need to fall through */ + case IOC_AP_SET_CFG: + /* This case need to fall through */ + case IOC_AP_STA_DISASSOC: + return priv_set_ap(prNetDev, &rIwReqInfo, &(prIwReq->u), + (char *) &(prIwReq->u)); +#if CFG_SUPPORT_WAC + case IOCTL_SET_DRIVER: + return priv_set_struct(prNetDev, &rIwReqInfo, &prIwReq->u, + (char *) &(prIwReq->u)); +#endif + + case IOCTL_GET_STR: + + default: + return -EOPNOTSUPP; + + } /* end of switch */ + +} /* priv_support_ioctl */ + +#if CFG_SUPPORT_BATCH_SCAN + +struct EVENT_BATCH_RESULT + g_rEventBatchResult[CFG_BATCH_MAX_MSCAN]; + +uint32_t batchChannelNum2Freq(uint32_t u4ChannelNum) +{ + uint32_t u4ChannelInMHz; + + if (u4ChannelNum >= 1 && u4ChannelNum <= 13) + u4ChannelInMHz = 2412 + (u4ChannelNum - 1) * 5; + else if (u4ChannelNum == 14) + u4ChannelInMHz = 2484; + else if (u4ChannelNum == 133) + u4ChannelInMHz = 3665; /* 802.11y */ + else if (u4ChannelNum == 137) + u4ChannelInMHz = 3685; /* 802.11y */ + else if (u4ChannelNum >= 34 && u4ChannelNum <= 165) + u4ChannelInMHz = 5000 + u4ChannelNum * 5; + else if (u4ChannelNum >= 183 && u4ChannelNum <= 196) + u4ChannelInMHz = 4000 + u4ChannelNum * 5; + else + u4ChannelInMHz = 0; + + return u4ChannelInMHz; +} + +#define TMP_TEXT_LEN_S 40 +#define TMP_TEXT_LEN_L 60 +static uint8_t text1[TMP_TEXT_LEN_S], text2[TMP_TEXT_LEN_L], + text3[TMP_TEXT_LEN_L]; /* A safe len */ + +uint32_t +batchConvertResult(IN struct EVENT_BATCH_RESULT + *prEventBatchResult, + OUT void *pvBuffer, IN uint32_t u4MaxBufferLen, + OUT uint32_t *pu4RetLen) +{ + int8_t *p = pvBuffer; + int8_t ssid[ELEM_MAX_LEN_SSID + 1]; + int32_t nsize, nsize1, nsize2, nsize3, scancount; + int32_t i, j, nleft; + uint32_t freq; + + struct EVENT_BATCH_RESULT_ENTRY *prEntry; + struct EVENT_BATCH_RESULT *pBr; + + nsize = 0; + nleft = u4MaxBufferLen - 5; /* -5 for "----\n" */ + + pBr = prEventBatchResult; + scancount = 0; + for (j = 0; j < CFG_BATCH_MAX_MSCAN; j++) { + scancount += pBr->ucScanCount; + pBr++; + } + + nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, + "scancount=%d\nnextcount=%d\n", scancount, + scancount); + if (nsize1 < nleft) { + kalStrnCpy(p, text1, nsize1); + p += nsize1; + nleft -= nsize1; + } else + goto short_buf; + + pBr = prEventBatchResult; + for (j = 0; j < CFG_BATCH_MAX_MSCAN; j++) { + DBGLOG(SCN, TRACE, + "convert mscan = %d, apcount=%d, nleft=%d\n", j, + pBr->ucScanCount, nleft); + + if (pBr->ucScanCount == 0) { + pBr++; + continue; + } + + nleft -= 5; /* -5 for "####\n" */ + + /* We only support one round scan result now. */ + nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "apcount=%d\n", + pBr->ucScanCount); + if (nsize1 < nleft) { + kalStrnCpy(p, text1, nsize1); + p += nsize1; + nleft -= nsize1; + } else + goto short_buf; + + for (i = 0; i < pBr->ucScanCount; i++) { + prEntry = &pBr->arBatchResult[i]; + + nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, + "bssid=" MACSTR "\n", + MAC2STR(prEntry->aucBssid)); + kalMemCopy(ssid, + prEntry->aucSSID, + (prEntry->ucSSIDLen < ELEM_MAX_LEN_SSID ? + prEntry->ucSSIDLen : ELEM_MAX_LEN_SSID)); + ssid[(prEntry->ucSSIDLen < + (ELEM_MAX_LEN_SSID - 1) ? prEntry->ucSSIDLen : + (ELEM_MAX_LEN_SSID - 1))] = '\0'; + nsize2 = kalSnprintf(text2, TMP_TEXT_LEN_L, "ssid=%s\n", + ssid); + + freq = batchChannelNum2Freq(prEntry->ucFreq); + nsize3 = + kalSnprintf(text3, TMP_TEXT_LEN_L, + "freq=%u\nlevel=%d\ndist=%u\ndistSd=%u\n====\n", + freq, prEntry->cRssi, prEntry->u4Dist, + prEntry->u4Distsd); + + nsize = nsize1 + nsize2 + nsize3; + if (nsize < nleft) { + + kalStrnCpy(p, text1, TMP_TEXT_LEN_S); + p += nsize1; + + kalStrnCpy(p, text2, TMP_TEXT_LEN_L); + p += nsize2; + + kalStrnCpy(p, text3, TMP_TEXT_LEN_L); + p += nsize3; + + nleft -= nsize; + } else { + DBGLOG(SCN, TRACE, + "Warning: Early break! (%d)\n", i); + break; /* discard following entries, + * TODO: apcount? + */ + } + } + + nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "%s", "####\n"); + if (nsize1 < nleft) { + kalStrnCpy(p, text1, nsize1); + p += nsize1; + nleft -= nsize1; + } + + pBr++; + } + + nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "%s", "----\n"); + if (nsize1 < nleft) { + kalStrnCpy(p, text1, nsize1); + p += nsize1; + nleft -= nsize1; + } + + *pu4RetLen = u4MaxBufferLen - nleft; + DBGLOG(SCN, TRACE, "total len = %d (max len = %d)\n", + *pu4RetLen, u4MaxBufferLen); + + return WLAN_STATUS_SUCCESS; + +short_buf: + DBGLOG(SCN, TRACE, + "Short buffer issue! %d > %d, %s\n", + u4MaxBufferLen + (nsize - nleft), u4MaxBufferLen, + (char *)pvBuffer); + return WLAN_STATUS_INVALID_LENGTH; +} +#endif + +void +parseNoiseHistogramReport(uint32_t *i4BytesWritten, char *pcCommand, + int *i4TotalLen, IN struct CMD_NOISE_HISTOGRAM_REPORT *cmd) +{ + if (cmd->ucAction == CMD_NOISE_HISTOGRAM_GET) { + *i4BytesWritten += snprintf(pcCommand + *i4BytesWritten, + *i4TotalLen - *i4BytesWritten, + "\nWF0 Noise IPI"); +#if CFG_IPI_2CHAIN_SUPPORT + } else if (cmd->ucAction == CMD_NOISE_HISTOGRAM_GET2) { + *i4BytesWritten += snprintf(pcCommand + *i4BytesWritten, + *i4TotalLen - *i4BytesWritten, + "\nWF1 Noise IPI"); +#endif /* CFG_IPI_2CHAIN_SUPPORT */ + } + + *i4BytesWritten += snprintf(pcCommand + *i4BytesWritten, + *i4TotalLen - *i4BytesWritten, + "\n Power > -55: %10d", cmd->u4IPI10); + *i4BytesWritten += snprintf(pcCommand + *i4BytesWritten, + *i4TotalLen - *i4BytesWritten, + "\n-55 >= Power > -60: %10d", cmd->u4IPI9); + *i4BytesWritten += snprintf(pcCommand + *i4BytesWritten, + *i4TotalLen - *i4BytesWritten, + "\n-60 >= Power > -65: %10d", cmd->u4IPI8); + *i4BytesWritten += snprintf(pcCommand + *i4BytesWritten, + *i4TotalLen - *i4BytesWritten, + "\n-65 >= Power > -70: %10d", cmd->u4IPI7); + *i4BytesWritten += snprintf(pcCommand + *i4BytesWritten, + *i4TotalLen - *i4BytesWritten, + "\n-70 >= Power > -75: %10d", cmd->u4IPI6); + *i4BytesWritten += snprintf(pcCommand + *i4BytesWritten, + *i4TotalLen - *i4BytesWritten, + "\n-75 >= Power > -80: %10d", cmd->u4IPI5); + *i4BytesWritten += snprintf(pcCommand + *i4BytesWritten, + *i4TotalLen - *i4BytesWritten, + "\n-80 >= Power > -83: %10d", cmd->u4IPI4); + *i4BytesWritten += snprintf(pcCommand + *i4BytesWritten, + *i4TotalLen - *i4BytesWritten, + "\n-83 >= Power > -86: %10d", cmd->u4IPI3); + *i4BytesWritten += snprintf(pcCommand + *i4BytesWritten, + *i4TotalLen - *i4BytesWritten, + "\n-86 >= Power > -89: %10d", cmd->u4IPI2); + *i4BytesWritten += snprintf(pcCommand + *i4BytesWritten, + *i4TotalLen - *i4BytesWritten, + "\n-89 >= Power > -92: %10d", cmd->u4IPI1); + *i4BytesWritten += snprintf(pcCommand + *i4BytesWritten, + *i4TotalLen - *i4BytesWritten, + "\n-92 >= Power : %10d", cmd->u4IPI0); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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) +{ + uint32_t u4SubCmd; + uint32_t *pu4IntBuf; + struct NDIS_TRANSPORT_STRUCT *prNdisReq; + struct GLUE_INFO *prGlueInfo; + uint32_t u4BufLen = 0; + int status = 0; + struct PTA_IPC *prPtaIpc; + + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + + if (GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + u4SubCmd = (uint32_t) prIwReqData->mode; + pu4IntBuf = (uint32_t *) pcExtra; + + switch (u4SubCmd) { + case PRIV_CMD_TEST_MODE: + prNdisReq = (struct 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 if (pu4IntBuf[1] == PRIV_CMD_TEST_MAGIC_KEY_ICAP) { + prNdisReq->ndisOidCmd = OID_CUSTOM_TEST_ICAP_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: + prNdisReq = (struct 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: + prNdisReq = (struct 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; + } + + if (pu4IntBuf[1] == PRIV_CMD_TEST_MAGIC_KEY + && pu4IntBuf[2] == PRIV_CMD_TEST_MAGIC_KEY) { + 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: + prNdisReq = (struct 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: + /* pu4IntBuf[0] is used as input SubCmd */ + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetBeaconInterval, (void *)&pu4IntBuf[1], + sizeof(uint32_t), &u4BufLen); + break; +#endif + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + case PRIV_CMD_CSUM_OFFLOAD: { + uint32_t u4CSUMFlags; + + if (pu4IntBuf[1] == 1) + u4CSUMFlags = CSUM_OFFLOAD_EN_ALL; + else if (pu4IntBuf[1] == 0) + u4CSUMFlags = 0; + else + return -EINVAL; + + if (kalIoctl(prGlueInfo, wlanoidSetCSUMOffload, + (void *)&u4CSUMFlags, sizeof(uint32_t), FALSE, FALSE, TRUE, + &u4BufLen) == WLAN_STATUS_SUCCESS) { + if (pu4IntBuf[1] == 1) + prNetDev->features |= NETIF_F_IP_CSUM | + NETIF_F_IPV6_CSUM | + NETIF_F_RXCSUM; + else if (pu4IntBuf[1] == 0) + prNetDev->features &= ~(NETIF_F_IP_CSUM | + NETIF_F_IPV6_CSUM | + NETIF_F_RXCSUM); + } + } + break; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + case PRIV_CMD_POWER_MODE: { + struct PARAM_POWER_MODE_ rPowerMode; + struct BSS_INFO *prBssInfo = + prGlueInfo->prAdapter->prAisBssInfo; + + if (!prBssInfo) + break; + + rPowerMode.ePowerMode = (enum PARAM_POWER_MODE) + pu4IntBuf[1]; + rPowerMode.ucBssIdx = prBssInfo->ucBssIndex; + + /* pu4IntBuf[0] is used as input SubCmd */ + kalIoctl(prGlueInfo, wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, sizeof(struct PARAM_POWER_MODE_), + FALSE, FALSE, TRUE, &u4BufLen); + } + break; + + case PRIV_CMD_WMM_PS: { + struct PARAM_CUSTOM_WMM_PS_TEST_STRUCT rWmmPsTest; + + rWmmPsTest.bmfgApsdEnAc = (uint8_t) pu4IntBuf[1]; + rWmmPsTest.ucIsEnterPsAtOnce = (uint8_t) pu4IntBuf[2]; + rWmmPsTest.ucIsDisableUcTrigger = (uint8_t) pu4IntBuf[3]; + rWmmPsTest.reserved = 0; + + kalIoctl(prGlueInfo, wlanoidSetWiFiWmmPsTest, + (void *)&rWmmPsTest, + sizeof(struct PARAM_CUSTOM_WMM_PS_TEST_STRUCT), + FALSE, FALSE, TRUE, &u4BufLen); + } + break; + +#if 0 + case PRIV_CMD_ADHOC_MODE: + /* pu4IntBuf[0] is used as input SubCmd */ + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetAdHocMode, (void *)&pu4IntBuf[1], + sizeof(uint32_t), &u4BufLen); + break; +#endif + + case PRIV_CUSTOM_BWCS_CMD: + + DBGLOG(REQ, INFO, + "pu4IntBuf[1] = %x, size of struct PTA_IPC = %d.\n", + pu4IntBuf[1], (uint32_t) sizeof(struct PTA_IPC)); + + prPtaIpc = (struct PTA_IPC *) aucOidBuf; + prPtaIpc->u.aucBTPParams[0] = (uint8_t) (pu4IntBuf[1] >> + 24); + prPtaIpc->u.aucBTPParams[1] = (uint8_t) (pu4IntBuf[1] >> + 16); + prPtaIpc->u.aucBTPParams[2] = (uint8_t) (pu4IntBuf[1] >> 8); + prPtaIpc->u.aucBTPParams[3] = (uint8_t) (pu4IntBuf[1]); + + DBGLOG(REQ, INFO, + "BCM BWCS CMD : PRIV_CUSTOM_BWCS_CMD : aucBTPParams[0] = %02x, aucBTPParams[1] = %02x.\n", + prPtaIpc->u.aucBTPParams[0], + prPtaIpc->u.aucBTPParams[1]); + DBGLOG(REQ, INFO, + "BCM BWCS CMD : PRIV_CUSTOM_BWCS_CMD : aucBTPParams[2] = %02x, aucBTPParams[3] = %02x.\n", + prPtaIpc->u.aucBTPParams[2], + prPtaIpc->u.aucBTPParams[3]); + +#if 0 + status = wlanSetInformation(prGlueInfo->prAdapter, wlanoidSetBT, + (void *)&aucOidBuf[0], u4CmdLen, &u4BufLen); +#endif + + status = wlanoidSetBT(prGlueInfo->prAdapter, + (void *)&aucOidBuf[0], sizeof(struct PTA_IPC), + &u4BufLen); + + if (status != WLAN_STATUS_SUCCESS) + status = -EFAULT; + + break; + + case PRIV_CMD_BAND_CONFIG: { + DBGLOG(INIT, INFO, "CMD set_band = %u\n", + (uint32_t) pu4IntBuf[1]); + } + break; + +#if CFG_ENABLE_WIFI_DIRECT + case PRIV_CMD_P2P_MODE: { + struct PARAM_CUSTOM_P2P_SET_STRUCT rSetP2P; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + rSetP2P.u4Enable = pu4IntBuf[1]; + rSetP2P.u4Mode = pu4IntBuf[2]; +#if 1 + if (!rSetP2P.u4Enable) + p2pNetUnregister(prGlueInfo, TRUE); + + /* pu4IntBuf[0] is used as input SubCmd */ + rWlanStatus = kalIoctl(prGlueInfo, wlanoidSetP2pMode, + (void *)&rSetP2P, + sizeof(struct PARAM_CUSTOM_P2P_SET_STRUCT), + FALSE, FALSE, TRUE, &u4BufLen); + + if ((rSetP2P.u4Enable) + && (rWlanStatus == WLAN_STATUS_SUCCESS)) + p2pNetRegister(prGlueInfo, TRUE); +#endif + + } + break; +#endif + +#if (CFG_MET_PACKET_TRACE_SUPPORT == 1) + case PRIV_CMD_MET_PROFILING: { + /* PARAM_CUSTOM_WFD_DEBUG_STRUCT_T rWfdDebugModeInfo; */ + /* rWfdDebugModeInfo.ucWFDDebugMode=(UINT_8)pu4IntBuf[1]; */ + /* rWfdDebugModeInfo.u2SNPeriod=(UINT_16)pu4IntBuf[2]; */ + /* DBGLOG(REQ, INFO, ("WFD Debug Mode:%d Period:%d\n", + * rWfdDebugModeInfo.ucWFDDebugMode, + * rWfdDebugModeInfo.u2SNPeriod)); + */ + prGlueInfo->fgMetProfilingEn = (uint8_t) pu4IntBuf[1]; + prGlueInfo->u2MetUdpPort = (uint16_t) pu4IntBuf[2]; + /* DBGLOG(INIT, INFO, ("MET_PROF: Enable=%d UDP_PORT=%d\n", + * prGlueInfo->fgMetProfilingEn, prGlueInfo->u2MetUdpPort); + */ + + } + break; + +#endif + case PRIV_CMD_SET_SER: + kalIoctl(prGlueInfo, wlanoidSetSer, (void *)&pu4IntBuf[1], + sizeof(uint32_t), FALSE, FALSE, TRUE, &u4BufLen); + break; + + default: + return -EOPNOTSUPP; + } + + return status; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Private ioctl get int handler. + * + * \param[in] pDev Net device requested. + * \param[out] pIwReq Pointer to iwreq structure. + * \param[in] prIwReqData The ioctl req structure, use the field of sub-command. + * \param[out] pcExtra The buffer with put the return value + * + * \retval 0 For success. + * \retval -EOPNOTSUPP If cmd is not supported. + * \retval -EFAULT For fail. + * + */ +/*----------------------------------------------------------------------------*/ +int +priv_get_int(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + uint32_t u4SubCmd; + uint32_t *pu4IntBuf; + struct GLUE_INFO *prGlueInfo; + uint32_t u4BufLen = 0; + int status = 0; + struct NDIS_TRANSPORT_STRUCT *prNdisReq; + int32_t ch[MAX_CHN_NUM]; + + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + if (GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + u4SubCmd = (uint32_t) prIwReqData->mode; + pu4IntBuf = (uint32_t *) pcExtra; + + switch (u4SubCmd) { + case PRIV_CMD_TEST_CMD: + prNdisReq = (struct 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) { + prIwReqData->mode = *(uint32_t *) + &prNdisReq->ndisOidContent[4]; + + } + return status; + +#if CFG_SUPPORT_PRIV_MCR_RW + case PRIV_CMD_ACCESS_MCR: + prNdisReq = (struct 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) { + prIwReqData->mode = *(uint32_t *) + &prNdisReq->ndisOidContent[4]; + } + return status; +#endif + + case PRIV_CMD_DUMP_MEM: + prNdisReq = (struct NDIS_TRANSPORT_STRUCT *) &aucOidBuf[0]; + + if (!prGlueInfo->fgMcrAccessAllowed + || !capable(CAP_NET_ADMIN)) { + DBGLOG(REQ, WARN, "Access Denied\n"); + status = 0; + return status; + } + + kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); + + prNdisReq->ndisOidCmd = OID_CUSTOM_MEM_DUMP; + prNdisReq->inNdisOidlength = sizeof(struct + PARAM_CUSTOM_MEM_DUMP_STRUCT); + prNdisReq->outNdisOidLength = sizeof(struct + PARAM_CUSTOM_MEM_DUMP_STRUCT); + + status = priv_get_ndis(prNetDev, prNdisReq, &u4BufLen); + if (status == 0) + prIwReqData->mode = *(uint32_t *) + &prNdisReq->ndisOidContent[0]; + return status; + + case PRIV_CMD_SW_CTRL: + prNdisReq = (struct 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) { + prIwReqData->mode = *(uint32_t *) + &prNdisReq->ndisOidContent[4]; + } + return status; + +#if 0 + case PRIV_CMD_BEACON_PERIOD: + status = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryBeaconInterval, (void *) pu4IntBuf, + sizeof(uint32_t), &u4BufLen); + return status; + + case PRIV_CMD_POWER_MODE: + status = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQuery802dot11PowerSaveProfile, + (void *)pu4IntBuf, sizeof(uint32_t), &u4BufLen); + return status; + + case PRIV_CMD_ADHOC_MODE: + status = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryAdHocMode, (void *) pu4IntBuf, + sizeof(uint32_t), &u4BufLen); + return status; +#endif + + case PRIV_CMD_BAND_CONFIG: + DBGLOG(INIT, INFO, "CMD get_band=\n"); + prIwReqData->mode = 0; + return status; + + default: + break; + } + + u4SubCmd = (uint32_t) prIwReqData->data.flags; + + switch (u4SubCmd) { + case PRIV_CMD_GET_CH_LIST: { + uint16_t i, j = 0; + uint8_t NumOfChannel = MAX_CHN_NUM; + uint8_t ucMaxChannelNum = MAX_CHN_NUM; + struct RF_CHANNEL_INFO *aucChannelList; + + DBGLOG(RLM, INFO, "Domain: Query Channel List.\n"); + aucChannelList = (struct RF_CHANNEL_INFO *) + kalMemAlloc(sizeof(struct RF_CHANNEL_INFO)*MAX_CHN_NUM, + VIR_MEM_TYPE); + if (!aucChannelList) { + DBGLOG(REQ, ERROR, + "Can not alloc memory for rf channel info\n"); + return -ENOMEM; + } + kalMemZero(aucChannelList, + sizeof(struct RF_CHANNEL_INFO)*MAX_CHN_NUM); + + kalGetChannelList(prGlueInfo, BAND_NULL, ucMaxChannelNum, + &NumOfChannel, aucChannelList); + if (NumOfChannel > MAX_CHN_NUM) + NumOfChannel = MAX_CHN_NUM; + + 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] = (int32_t) aucChannelList[i] + .ucChannelNum; + j++; + } + } + } else { + for (j = 0; j < NumOfChannel; j++) + ch[j] = (int32_t)aucChannelList[j].ucChannelNum; + } + kalMemFree(aucChannelList, VIR_MEM_TYPE, + sizeof(struct RF_CHANNEL_INFO)*MAX_CHN_NUM); + + prIwReqData->data.length = j; + if (copy_to_user(prIwReqData->data.pointer, ch, + NumOfChannel * sizeof(int32_t))) + 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) +{ + uint16_t i = 0; + uint32_t u4SubCmd, u4BufLen, u4CmdLen; + struct GLUE_INFO *prGlueInfo; + int32_t setting[4] = {0}; + int status = 0; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct SET_TXPWR_CTRL *prTxpwr; + + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + + if (GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + u4SubCmd = (uint32_t) prIwReqData->data.flags; + u4CmdLen = (uint32_t) prIwReqData->data.length; + + switch (u4SubCmd) { + case PRIV_CMD_SET_TX_POWER: { + if (u4CmdLen > 4) + return -EINVAL; + if (copy_from_user(setting, prIwReqData->data.pointer, + u4CmdLen)) + return -EFAULT; + +#if 0 + DBGLOG(INIT, INFO, "Tx power num = %d\n", + prIwReqData->data.length); + + DBGLOG(INIT, INFO, + "Tx power setting = %d %d %d %d\n", setting[0], + setting[1], setting[2], setting[3]); +#endif + prTxpwr = &prGlueInfo->rTxPwr; + if (setting[0] == 0 + && prIwReqData->data.length == 4 /* argc num */) { + /* 0 (All networks), 1 (legacy STA), 2 (Hotspot AP), + * 3 (P2P), 4 (BT over Wi-Fi) + */ + if (setting[1] == 1 || setting[1] == 0) { + if (setting[2] == 0 || setting[2] == 1) + prTxpwr->c2GLegacyStaPwrOffset = + setting[3]; + if (setting[2] == 0 || setting[2] == 2) + prTxpwr->c5GLegacyStaPwrOffset = + setting[3]; + } + if (setting[1] == 2 || setting[1] == 0) { + if (setting[2] == 0 || setting[2] == 1) + prTxpwr->c2GHotspotPwrOffset = + setting[3]; + if (setting[2] == 0 || setting[2] == 2) + prTxpwr->c5GHotspotPwrOffset = + setting[3]; + } + if (setting[1] == 3 || setting[1] == 0) { + if (setting[2] == 0 || setting[2] == 1) + prTxpwr->c2GP2pPwrOffset = setting[3]; + if (setting[2] == 0 || setting[2] == 2) + prTxpwr->c5GP2pPwrOffset = setting[3]; + } + if (setting[1] == 4 || setting[1] == 0) { + if (setting[2] == 0 || setting[2] == 1) + prTxpwr->c2GBowPwrOffset = setting[3]; + if (setting[2] == 0 || setting[2] == 2) + prTxpwr->c5GBowPwrOffset = setting[3]; + } + } else if (setting[0] == 1 + && prIwReqData->data.length == 2) { + prTxpwr->ucConcurrencePolicy = setting[1]; + } else if (setting[0] == 2 + && prIwReqData->data.length == 3) { + if (setting[1] == 0) { + for (i = 0; i < 14; i++) + prTxpwr->acTxPwrLimit2G[i] = setting[2]; + } else if (setting[1] <= 14) + prTxpwr->acTxPwrLimit2G[setting[1] - 1] = + setting[2]; + } else if (setting[0] == 3 + && prIwReqData->data.length == 3) { + if (setting[1] == 0) { + for (i = 0; i < 4; i++) + prTxpwr->acTxPwrLimit5G[i] = setting[2]; + } else if (setting[1] <= 4) + prTxpwr->acTxPwrLimit5G[setting[1] - 1] = + setting[2]; + } else if (setting[0] == 4 + && prIwReqData->data.length == 2) { + if (setting[1] == 0) + wlanDefTxPowerCfg(prGlueInfo->prAdapter); + rStatus = kalIoctl(prGlueInfo, wlanoidSetTxPower, + prTxpwr, + sizeof(struct SET_TXPWR_CTRL), + FALSE, FALSE, TRUE, &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) +{ + uint32_t u4SubCmd; + struct GLUE_INFO *prGlueInfo; + int status = 0; + int32_t ch[MAX_CHN_NUM]; + + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + if (GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + u4SubCmd = (uint32_t) prIwReqData->data.flags; + + switch (u4SubCmd) { + case PRIV_CMD_GET_CH_LIST: { + uint16_t i; + uint8_t NumOfChannel = MAX_CHN_NUM; + uint8_t ucMaxChannelNum = MAX_CHN_NUM; + struct RF_CHANNEL_INFO aucChannelList[MAX_CHN_NUM]; + + kalGetChannelList(prGlueInfo, BAND_NULL, ucMaxChannelNum, + &NumOfChannel, aucChannelList); + if (NumOfChannel > MAX_CHN_NUM) + NumOfChannel = MAX_CHN_NUM; + + for (i = 0; i < NumOfChannel; i++) + ch[i] = (int32_t) aucChannelList[i].ucChannelNum; + + prIwReqData->data.length = NumOfChannel; + if (copy_to_user(prIwReqData->data.pointer, ch, + NumOfChannel * sizeof(int32_t))) + 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) +{ + uint32_t u4SubCmd = 0; + int status = 0; + /* WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; */ + uint32_t u4CmdLen = 0; + struct NDIS_TRANSPORT_STRUCT *prNdisReq; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4BufLen = 0; + + ASSERT(prNetDev); + /* ASSERT(prIwReqInfo); */ + ASSERT(prIwReqData); + /* ASSERT(pcExtra); */ + + kalMemZero(&aucOidBuf[0], sizeof(aucOidBuf)); + + if (GLUE_CHK_PR2(prNetDev, prIwReqData) == FALSE) + return -EINVAL; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + u4SubCmd = (uint32_t) prIwReqData->data.flags; + +#if 0 + DBGLOG(INIT, INFO, + "priv_set_struct(): prIwReqInfo->cmd(0x%X), u4SubCmd(%ld)\n", + prIwReqInfo->cmd, u4SubCmd); +#endif + + switch (u4SubCmd) { +#if 0 /* PTA_ENABLED */ + case PRIV_CMD_BT_COEXIST: + u4CmdLen = prIwReqData->data.length * sizeof(uint32_t); + 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, (void *)&aucOidBuf[0], + u4CmdLen, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + status = -EFAULT; + break; +#endif + + case PRIV_CUSTOM_BWCS_CMD: + u4CmdLen = prIwReqData->data.length * sizeof(uint32_t); + ASSERT(sizeof(struct PTA_IPC) >= u4CmdLen); + if (sizeof(struct PTA_IPC) < u4CmdLen) + return -EFAULT; +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS && CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(REQ, INFO, + "ucCmdLen = %d, size of struct PTA_IPC = %d, prIwReqData->data = 0x%x.\n", + u4CmdLen, sizeof(struct PTA_IPC), 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, + (void *)&aucOidBuf[0], u4CmdLen, &u4BufLen); +#endif + +#if 1 + status = wlanoidSetBT(prGlueInfo->prAdapter, + (void *)&aucOidBuf[0], u4CmdLen, &u4BufLen); +#endif + + if (status != WLAN_STATUS_SUCCESS) + status = -EFAULT; + + break; + +#if CFG_SUPPORT_WPS2 + case PRIV_CMD_WSC_PROBE_REQ: { + /* retrieve IE for Probe Request */ + u4CmdLen = prIwReqData->data.length; + if (u4CmdLen > GLUE_INFO_WSCIE_LENGTH) { + DBGLOG(REQ, ERROR, "Input data length is invalid %u\n", + u4CmdLen); + return -EINVAL; + } + + if (prIwReqData->data.length > 0) { + if (copy_from_user(prGlueInfo->aucWSCIE, + prIwReqData->data.pointer, + u4CmdLen)) { + status = -EFAULT; + break; + } + prGlueInfo->u2WSCIELen = u4CmdLen; + } else { + prGlueInfo->u2WSCIELen = 0; + } + } + break; +#endif + case PRIV_CMD_OID: + u4CmdLen = prIwReqData->data.length; + if (u4CmdLen > CMD_OID_BUF_LENGTH) { + DBGLOG(REQ, ERROR, "Input data length is invalid %u\n", + u4CmdLen); + return -EINVAL; + } + if (copy_from_user(&aucOidBuf[0], prIwReqData->data.pointer, + u4CmdLen)) { + status = -EFAULT; + break; + } + if (!kalMemCmp(&aucOidBuf[0], pcExtra, u4CmdLen)) { + /* ToDo:: DBGLOG */ + 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, + (struct NDIS_TRANSPORT_STRUCT *) &aucOidBuf[0], + &u4BufLen); + /* Copy result to user space */ + ((struct NDIS_TRANSPORT_STRUCT *) + &aucOidBuf[0])->outNdisOidLength = u4BufLen; + + if (copy_to_user(prIwReqData->data.pointer, &aucOidBuf[0], + OFFSET_OF(struct NDIS_TRANSPORT_STRUCT, ndisOidContent))) { + DBGLOG(REQ, INFO, "copy_to_user oidBuf fail\n"); + status = -EFAULT; + } + + break; + + case PRIV_CMD_SW_CTRL: + u4CmdLen = prIwReqData->data.length; + if (u4CmdLen > CMD_OID_BUF_LENGTH) { + DBGLOG(REQ, ERROR, "Input data length is invalid %u\n", + u4CmdLen); + return -EINVAL; + } + prNdisReq = (struct NDIS_TRANSPORT_STRUCT *) &aucOidBuf[0]; + + if (u4CmdLen > sizeof(prNdisReq->ndisOidContent)) { + DBGLOG(REQ, ERROR, "Input data length is invalid %u\n", + u4CmdLen); + return -EINVAL; + } + + if (copy_from_user(&prNdisReq->ndisOidContent[0], + prIwReqData->data.pointer, u4CmdLen)) { + 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; + +#if CFG_SUPPORT_WAC + case PRIV_CMD_WAC_IE: + /* Set WAC IE */ + if (prIwReqData->data.length > 0) { + if (prIwReqData->data.length > ELEM_MAX_LEN_WAC_INFO) { + DBGLOG(REQ, ERROR, "exceed len(%ld),ignore\n", + prIwReqData->data.length); + break; + } + kalMemZero(prGlueInfo->prAdapter-> + rWifiVar.aucWACIECache, + sizeof(prGlueInfo->prAdapter->rWifiVar.aucWACIECache)); + if (copy_from_user(prGlueInfo->prAdapter-> + rWifiVar.aucWACIECache, + prIwReqData->data.pointer, + prIwReqData->data.length)) { + status = -EFAULT; + DBGLOG(REQ, ERROR, "cp_f_us WACIE failed!\n"); + break; + } + + prGlueInfo->prAdapter->rWifiVar.u2WACIELen = + prIwReqData->data.length; + DBGLOG(REQ, INFO, "Set WAC IE:\n"); + dumpMemory8(prGlueInfo->prAdapter-> + rWifiVar.aucWACIECache, + prGlueInfo->prAdapter->rWifiVar.u2WACIELen); + } else { + prGlueInfo->prAdapter->rWifiVar.u2WACIELen = 0; + } + break; +#endif + + 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) +{ + uint32_t u4SubCmd = 0; + struct NDIS_TRANSPORT_STRUCT *prNdisReq = NULL; + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4BufLen = 0; + /* uint32_t *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 = (uint32_t) prIwReqData->data.flags; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, + "priv_get_struct(): invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, + *((struct GLUE_INFO **) netdev_priv(prNetDev))); + return -EINVAL; + } +#if 0 + DBGLOG(INIT, INFO, + "priv_get_struct(): prIwReqInfo->cmd(0x%X), u4SubCmd(%ld)\n", + prIwReqInfo->cmd, u4SubCmd); +#endif + memset(aucOidBuf, 0, sizeof(aucOidBuf)); + + switch (u4SubCmd) { + case PRIV_CMD_OID: + if (copy_from_user(&aucOidBuf[0], prIwReqData->data.pointer, + sizeof(struct NDIS_TRANSPORT_STRUCT))) { + DBGLOG(REQ, INFO, + "priv_get_struct() copy_from_user oidBuf fail\n"); + return -EFAULT; + } + + prNdisReq = (struct NDIS_TRANSPORT_STRUCT *) &aucOidBuf[0]; +#if 0 + DBGLOG(INIT, INFO, + "\n priv_get_struct cmd 0x%02x len:%d OID:0x%08x OID Len:%d\n", + cmd, + pIwReq->u.data.length, ndisReq->ndisOidCmd, + ndisReq->inNdisOidlength); +#endif + if (priv_get_ndis(prNetDev, prNdisReq, &u4BufLen) == 0) { + prNdisReq->outNdisOidLength = u4BufLen; + kalMemCopy(pcExtra, prNdisReq, + u4BufLen + sizeof(struct NDIS_TRANSPORT_STRUCT) + - sizeof(prNdisReq->ndisOidContent)); + return 0; + } + prNdisReq->outNdisOidLength = u4BufLen; + if (copy_to_user(prIwReqData->data.pointer, + &aucOidBuf[0], OFFSET_OF(struct NDIS_TRANSPORT_STRUCT, + ndisOidContent))) { + DBGLOG(REQ, INFO, + "priv_get_struct() copy_to_user oidBuf fail(2)\n" + ); + } + return -EFAULT; + + case PRIV_CMD_SW_CTRL: + /* pu4IntBuf = (uint32_t *) prIwReqData->data.pointer; */ + prNdisReq = (struct NDIS_TRANSPORT_STRUCT *) &aucOidBuf[0]; + + if (prIwReqData->data.length > (sizeof(aucOidBuf) - + OFFSET_OF(struct NDIS_TRANSPORT_STRUCT, ndisOidContent))) { + DBGLOG(REQ, INFO, + "priv_get_struct() exceeds length limit\n"); + return -EFAULT; + } + + /* if (copy_from_user(&prNdisReq->ndisOidContent[0], + * prIwReqData->data.pointer, + */ + /* Coverity uanble to detect real size of ndisOidContent, + * it's 4084 bytes instead of 16 bytes + */ + if (copy_from_user(&aucOidBuf[OFFSET_OF(struct + NDIS_TRANSPORT_STRUCT, ndisOidContent)], + 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; + + if (copy_to_user(prIwReqData->data.pointer, + &prNdisReq->ndisOidContent[4], 4)) + DBGLOG(REQ, INFO, + "priv_get_struct() copy_to_user oidBuf fail(2)\n" + ); + } + return 0; + default: + DBGLOG(REQ, WARN, "get struct cmd:0x%x\n", u4SubCmd); + return -EOPNOTSUPP; + } +} /* priv_get_struct */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief The routine handles a set operation for a single OID. + * + * \param[in] pDev Net device requested. + * \param[in] ndisReq Ndis request OID information copy from user. + * \param[out] outputLen_p If the call is successful, returns the number of + * bytes written into the query buffer. If the + * call failed due to invalid length of the query + * buffer, returns the amount of storage needed.. + * + * \retval 0 On success. + * \retval -EOPNOTSUPP If cmd is not supported. + * + */ +/*----------------------------------------------------------------------------*/ +static int +priv_set_ndis(IN struct net_device *prNetDev, + IN struct NDIS_TRANSPORT_STRUCT *prNdisReq, + OUT uint32_t *pu4OutputLen) +{ + struct WLAN_REQ_ENTRY *prWlanReqEntry = NULL; + uint32_t status = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t 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 = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, + "priv_set_ndis(): invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, + *((struct GLUE_INFO **) netdev_priv(prNetDev))); + return -EINVAL; + } +#if 0 + DBGLOG(INIT, INFO, + "priv_set_ndis(): prNdisReq->ndisOidCmd(0x%lX)\n", + prNdisReq->ndisOidCmd); +#endif + + if (reqSearchSupportedOidEntry(prNdisReq->ndisOidCmd, + &prWlanReqEntry) == FALSE) { + /* WARNLOG( + * ("Set OID: 0x%08lx (unknown)\n", + * prNdisReq->ndisOidCmd)); + */ + return -EOPNOTSUPP; + } + + if (prWlanReqEntry->pfOidSetHandler == NULL) { + /* WARNLOG( + * ("Set %s: Null set handler\n", + * prWlanReqEntry->pucOidName)); + */ + return -EOPNOTSUPP; + } +#if 0 + DBGLOG(INIT, INFO, "priv_set_ndis(): %s\n", + prWlanReqEntry->pucOidName); +#endif + + if (prWlanReqEntry->fgSetBufLenChecking) { + if (prNdisReq->inNdisOidlength != + prWlanReqEntry->u4InfoBufLen) { + DBGLOG(REQ, WARN, + "Set %s: Invalid length (current=%d, needed=%d)\n", + prWlanReqEntry->pucOidName, + prNdisReq->inNdisOidlength, + prWlanReqEntry->u4InfoBufLen); + + *pu4OutputLen = prWlanReqEntry->u4InfoBufLen; + return -EINVAL; + } + } else { + if (prNdisReq->inNdisOidlength > + (sizeof(aucOidBuf) - + OFFSET_OF(struct NDIS_TRANSPORT_STRUCT, ndisOidContent))) { + DBGLOG(REQ, INFO, "exceeds length limit\n"); + 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, &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 (status != WLAN_STATUS_SUCCESS) + 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 struct NDIS_TRANSPORT_STRUCT *prNdisReq, + OUT uint32_t *pu4OutputLen) +{ + struct WLAN_REQ_ENTRY *prWlanReqEntry = NULL; + uint32_t u4BufLen = 0; + uint32_t status = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *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 = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, + "priv_get_ndis(): invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, + *((struct GLUE_INFO **) netdev_priv(prNetDev))); + return -EINVAL; + } +#if 0 + DBGLOG(INIT, INFO, + "priv_get_ndis(): prNdisReq->ndisOidCmd(0x%lX)\n", + prNdisReq->ndisOidCmd); +#endif + + if (reqSearchSupportedOidEntry(prNdisReq->ndisOidCmd, + &prWlanReqEntry) == FALSE) { + /* WARNLOG( + * ("Query OID: 0x%08lx (unknown)\n", + * prNdisReq->ndisOidCmd)); + */ + return -EOPNOTSUPP; + } + + if (prWlanReqEntry->pfOidQueryHandler == NULL) { + /* WARNLOG( + * ("Query %s: Null query handler\n", + * prWlanReqEntry->pucOidName)); + */ + return -EOPNOTSUPP; + } +#if 0 + DBGLOG(INIT, INFO, "priv_get_ndis(): %s\n", + prWlanReqEntry->pucOidName); +#endif + + if (prWlanReqEntry->fgQryBufLenChecking) { + if (prNdisReq->inNdisOidlength < + prWlanReqEntry->u4InfoBufLen) { + /* Not enough room in InformationBuffer. Punt */ + /* WARNLOG( + * ("Query %s: Buffer too short (current=%ld, + * needed=%ld)\n", + * prWlanReqEntry->pucOidName, + * prNdisReq->inNdisOidlength, + * prWlanReqEntry->u4InfoBufLen)); + */ + + *pu4OutputLen = prWlanReqEntry->u4InfoBufLen; + + status = WLAN_STATUS_INVALID_LENGTH; + return -EINVAL; + } + } else { + if (prNdisReq->inNdisOidlength > + (sizeof(aucOidBuf) - + OFFSET_OF(struct NDIS_TRANSPORT_STRUCT, ndisOidContent))) { + DBGLOG(REQ, INFO, "exceeds length limit\n"); + 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, &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 (status != WLAN_STATUS_SUCCESS) + return -EOPNOTSUPP; + + return 0; +} /* priv_get_ndis */ + +#if CFG_SUPPORT_QA_TOOL +/*----------------------------------------------------------------------------*/ +/*! + * \brief The routine handles ATE set operation. + * + * \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 -EFAULT If copy from user space buffer fail. + * + */ +/*----------------------------------------------------------------------------*/ +int +priv_ate_set(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, + IN char *pcExtra) +{ + int32_t i4Status; + /* uint8_t *InBuf; + * uint8_t *addr_str, *value_str; + * uint32_t InBufLen; + */ + uint32_t u4SubCmd; + /* u_int8_t isWrite = 0; + * uint32_t u4BufLen = 0; + * struct NDIS_TRANSPORT_STRUCT *prNdisReq; + * uint32_t pu4IntBuf[2]; + */ + uint32_t u4CopySize = sizeof(aucOidBuf); + + /* sanity check */ + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + + if (GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra) == FALSE) + return -EINVAL; + + u4SubCmd = (uint32_t) prIwReqData->data.flags; + DBGLOG(REQ, INFO, "MT6632: %s, u4SubCmd=%d\n", __func__, + u4SubCmd); + + switch (u4SubCmd) { + case PRIV_QACMD_SET: + u4CopySize = (prIwReqData->data.length < u4CopySize) + ? prIwReqData->data.length : (u4CopySize - 1); + if (copy_from_user(&aucOidBuf[0], prIwReqData->data.pointer, + u4CopySize)) + return -EFAULT; + aucOidBuf[u4CopySize] = '\0'; + DBGLOG(REQ, INFO, + "PRIV_QACMD_SET: priv_set_string=(%s)(%u,%d)\n", + aucOidBuf, u4CopySize, + (int32_t)prIwReqData->data.length); + i4Status = AteCmdSetHandle(prNetDev, &aucOidBuf[0], + u4CopySize); + break; + default: + return -EOPNOTSUPP; + } + return 0; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \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 u_int8_t reqSearchSupportedOidEntry(IN uint32_t rOid, + OUT struct WLAN_REQ_ENTRY **ppWlanReqEntry) +{ + int32_t 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 */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Private ioctl driver 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_set_driver(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + uint32_t u4SubCmd = 0; + uint16_t u2Cmd = 0; + + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + + ASSERT(prNetDev); + ASSERT(prIwReqData); + if (!prNetDev || !prIwReqData) { + DBGLOG(REQ, INFO, + "priv_set_driver(): invalid param(0x%p, 0x%p)\n", + prNetDev, prIwReqData); + return -EINVAL; + } + + u2Cmd = prIwReqInfo->cmd; + DBGLOG(REQ, INFO, "prIwReqInfo->cmd %u\n", u2Cmd); + + u4SubCmd = (uint32_t) prIwReqData->data.flags; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, + "priv_set_driver(): invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, + *((struct GLUE_INFO **) netdev_priv(prNetDev))); + return -EINVAL; + } + + /* trick,hack in ./net/wireless/wext-priv.c ioctl_private_iw_point */ + /* because the cmd number is odd (get), the input string will not be + * copy_to_user + */ + + DBGLOG(REQ, INFO, "prIwReqData->data.length %u\n", + prIwReqData->data.length); + + /* Use GET type becauase large data by iwpriv. */ + + ASSERT(IW_IS_GET(u2Cmd)); + if (prIwReqData->data.length != 0) { + if (!access_ok(VERIFY_READ, prIwReqData->data.pointer, + prIwReqData->data.length)) { + DBGLOG(REQ, INFO, + "%s access_ok Read fail written = %d\n", + __func__, i4BytesWritten); + return -EFAULT; + } + if (copy_from_user(pcExtra, prIwReqData->data.pointer, + prIwReqData->data.length)) { + DBGLOG(REQ, INFO, + "%s copy_form_user fail written = %d\n", + __func__, prIwReqData->data.length); + return -EFAULT; + } + /* prIwReqData->data.length include the terminate '\0' */ + pcExtra[prIwReqData->data.length - 1] = 0; + } + + if (pcExtra) { + DBGLOG(REQ, INFO, "pcExtra %s\n", pcExtra); + /* Please check max length in rIwPrivTable */ + DBGLOG(REQ, INFO, "%s prIwReqData->data.length = %d\n", + __func__, prIwReqData->data.length); + i4BytesWritten = priv_driver_cmds(prNetDev, pcExtra, + 2000 /*prIwReqData->data.length */); + DBGLOG(REQ, INFO, "%s i4BytesWritten = %d\n", __func__, + i4BytesWritten); + } + + DBGLOG(REQ, INFO, "pcExtra done\n"); + + if (i4BytesWritten > 0) { + + if (i4BytesWritten > 2000) + i4BytesWritten = 2000; + prIwReqData->data.length = + i4BytesWritten; /* the iwpriv will use the length */ + + } else if (i4BytesWritten == 0) { + prIwReqData->data.length = i4BytesWritten; + } +#if 0 + /* trick,hack in ./net/wireless/wext-priv.c ioctl_private_iw_point */ + /* because the cmd number is even (set), the return string will not be + * copy_to_user + */ + ASSERT(IW_IS_SET(u2Cmd)); + if (!access_ok(VERIFY_WRITE, prIwReqData->data.pointer, + i4BytesWritten)) { + DBGLOG(REQ, INFO, "%s access_ok Write fail written = %d\n", + __func__, i4BytesWritten); + return -EFAULT; + } + if (copy_to_user(prIwReqData->data.pointer, pcExtra, + i4BytesWritten)) { + DBGLOG(REQ, INFO, "%s copy_to_user fail written = %d\n", + __func__, i4BytesWritten); + return -EFAULT; + } + DBGLOG(RSN, INFO, "%s copy_to_user written = %d\n", + __func__, i4BytesWritten); +#endif + return 0; + +} /* priv_set_driver */ +#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 uint32_t +reqExtQueryConfiguration(IN struct GLUE_INFO *prGlueInfo, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen) +{ + struct PARAM_802_11_CONFIG *prQueryConfig = + (struct PARAM_802_11_CONFIG *) pvQueryBuffer; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4QueryInfoLen = 0; + + DEBUGFUNC("wlanoidQueryConfiguration"); + + ASSERT(prGlueInfo); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(struct PARAM_802_11_CONFIG); + if (u4QueryBufferLen < sizeof(struct PARAM_802_11_CONFIG)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvQueryBuffer); + + kalMemZero(prQueryConfig, + sizeof(struct PARAM_802_11_CONFIG)); + + /* Update the current radio configuration. */ + prQueryConfig->u4Length = sizeof(struct PARAM_802_11_CONFIG); + +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidSetBeaconInterval, + &prQueryConfig->u4BeaconPeriod, sizeof(uint32_t), + TRUE, TRUE, &u4QueryInfoLen); +#else + rStatus = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryBeaconInterval, + &prQueryConfig->u4BeaconPeriod, + sizeof(uint32_t), &u4QueryInfoLen); +#endif + if (rStatus != WLAN_STATUS_SUCCESS) + return rStatus; +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidQueryAtimWindow, + &prQueryConfig->u4ATIMWindow, sizeof(uint32_t), + TRUE, TRUE, &u4QueryInfoLen); +#else + rStatus = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryAtimWindow, + &prQueryConfig->u4ATIMWindow, + sizeof(uint32_t), + &u4QueryInfoLen); +#endif + if (rStatus != WLAN_STATUS_SUCCESS) + return rStatus; +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidQueryFrequency, + &prQueryConfig->u4DSConfig, sizeof(uint32_t), + TRUE, TRUE, &u4QueryInfoLen); +#else + rStatus = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryFrequency, + &prQueryConfig->u4DSConfig, + sizeof(uint32_t), + &u4QueryInfoLen); +#endif + if (rStatus != WLAN_STATUS_SUCCESS) + return rStatus; + + prQueryConfig->rFHConfig.u4Length = sizeof( + struct PARAM_802_11_CONFIG_FH); + + 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 uint32_t +reqExtSetConfiguration(IN struct GLUE_INFO *prGlueInfo, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct PARAM_802_11_CONFIG *prNewConfig = + (struct PARAM_802_11_CONFIG *) pvSetBuffer; + uint32_t u4SetInfoLen = 0; + + DEBUGFUNC("wlanoidSetConfiguration"); + + ASSERT(prGlueInfo); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_802_11_CONFIG); + + 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(uint32_t), + FALSE, TRUE, &u4SetInfoLen); +#else + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetBeaconInterval, + &prNewConfig->u4BeaconPeriod, + sizeof(uint32_t), + &u4SetInfoLen); +#endif + if (rStatus != WLAN_STATUS_SUCCESS) + return rStatus; +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidSetAtimWindow, + &prNewConfig->u4ATIMWindow, sizeof(uint32_t), + FALSE, TRUE, &u4SetInfoLen); +#else + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetAtimWindow, + &prNewConfig->u4ATIMWindow, + sizeof(uint32_t), &u4SetInfoLen); +#endif + if (rStatus != WLAN_STATUS_SUCCESS) + return rStatus; +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, wlanoidSetFrequency, + &prNewConfig->u4DSConfig, sizeof(uint32_t), + FALSE, TRUE, &u4SetInfoLen); +#else + rStatus = wlanSetInformation(prGlueInfo->prAdapter, wlanoidSetFrequency, + &prNewConfig->u4DSConfig, + sizeof(uint32_t), &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 uint32_t +reqExtSetAcpiDevicePowerState(IN struct GLUE_INFO + *prGlueInfo, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen) +{ + uint32_t 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; +} + +#define CMD_START "START" +#define CMD_STOP "STOP" +#define CMD_SCAN_ACTIVE "SCAN-ACTIVE" +#define CMD_SCAN_PASSIVE "SCAN-PASSIVE" +#define CMD_RSSI "RSSI" +#define CMD_LINKSPEED "LINKSPEED" +#define CMD_RXFILTER_START "RXFILTER-START" +#define CMD_RXFILTER_STOP "RXFILTER-STOP" +#define CMD_RXFILTER_ADD "RXFILTER-ADD" +#define CMD_RXFILTER_REMOVE "RXFILTER-REMOVE" +#define CMD_BTCOEXSCAN_START "BTCOEXSCAN-START" +#define CMD_BTCOEXSCAN_STOP "BTCOEXSCAN-STOP" +#define CMD_BTCOEXMODE "BTCOEXMODE" +#define CMD_SETSUSPENDOPT "SETSUSPENDOPT" +#define CMD_SETSUSPENDMODE "SETSUSPENDMODE" +#define CMD_P2P_DEV_ADDR "P2P_DEV_ADDR" +#define CMD_SETFWPATH "SETFWPATH" +#define CMD_SETBAND "SETBAND" +#define CMD_GETBAND "GETBAND" +#define CMD_AP_START "AP_START" + +#if CFG_SUPPORT_QA_TOOL +#define CMD_GET_RX_STATISTICS "GET_RX_STATISTICS" +#endif +#define CMD_GET_STAT "GET_STAT" +#define CMD_GET_BSS_STATISTICS "GET_BSS_STATISTICS" +#define CMD_GET_STA_STATISTICS "GET_STA_STATISTICS" +#define CMD_GET_WTBL_INFO "GET_WTBL" +#define CMD_GET_MIB_INFO "GET_MIB" +#define CMD_GET_STA_INFO "GET_STA" +#define CMD_SET_FW_LOG "SET_FWLOG" +#define CMD_GET_QUE_INFO "GET_QUE" +#define CMD_GET_MEM_INFO "GET_MEM" +#define CMD_GET_HIF_INFO "GET_HIF" +#define CMD_GET_TP_INFO "GET_TP" +#define CMD_GET_STA_KEEP_CNT "KEEPCOUNTER" +#define CMD_STAT_RESET_CNT "RESETCOUNTER" +#define CMD_STAT_NOISE_SEL "NOISESELECT" +#define CMD_STAT_GROUP_SEL "GROUP" + +#define CMD_SET_TXPOWER "SET_TXPOWER" +#define CMD_COUNTRY "COUNTRY" +#define CMD_CSA "CSA" +#define CMD_GET_COUNTRY "GET_COUNTRY" +#define CMD_GET_CHANNELS "GET_CHANNELS" +#define CMD_GET_AP_CHANNELS "GET_AP_CHANNELS" +#define CMD_P2P_SET_NOA "P2P_SET_NOA" +#define CMD_P2P_GET_NOA "P2P_GET_NOA" +#define CMD_P2P_SET_PS "P2P_SET_PS" +#define CMD_SET_AP_WPS_P2P_IE "SET_AP_WPS_P2P_IE" +#define CMD_SETROAMMODE "SETROAMMODE" +#define CMD_MIRACAST "MIRACAST" + +#ifdef CFG_SUPPORT_ADJUST_MCC_STAY_TIME +#define CMD_MCCTIME "MCCTIME" +#endif + + +#if (CFG_SUPPORT_DFS_MASTER == 1) +#define CMD_SHOW_DFS_STATE "SHOW_DFS_STATE" +#define CMD_SHOW_DFS_RADAR_PARAM "SHOW_DFS_RADAR_PARAM" +#define CMD_SHOW_DFS_HELP "SHOW_DFS_HELP" +#define CMD_SHOW_DFS_CAC_TIME "SHOW_DFS_CAC_TIME" +#endif + +#define CMD_PNOSSIDCLR_SET "PNOSSIDCLR" +#define CMD_PNOSETUP_SET "PNOSETUP " +#define CMD_PNOENABLE_SET "PNOFORCE" +#define CMD_PNODEBUG_SET "PNODEBUG" +#define CMD_WLS_BATCHING "WLS_BATCHING" + +#define CMD_OKC_SET_PMK "SET_PMK" +#define CMD_OKC_ENABLE "OKC_ENABLE" + +#define CMD_SETMONITOR "MONITOR" +#define CMD_SETBUFMODE "BUFFER_MODE" + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +#define CMD_GET_CH_RANK_LIST "GET_CH_RANK_LIST" +#define CMD_GET_CH_DIRTINESS "GET_CH_DIRTINESS" +#endif + +#if CFG_SUPPORT_ANT_DIV +#define CMD_SET_ANT_DIV "ANT_DIV_SET" +#define CMD_GET_ANT_DIV "ANT_DIV_GET" +#define CMD_DETC_ANT_DIV "ANT_DIV_DETC" +#define CMD_SWH_ANT_DIV "ANT_DIV_SWH" + +#define CMD_SET_ANT_DIV_ARG_NUM 2 +#define CMD_GET_ANT_DIV_ARG_NUM 1 +#define CMD_DETC_ANT_DIV_ARG_NUM 1 +#define CMD_SWH_ANT_DIV_ARG_NUM 1 +#endif + +#if CFG_CHIP_RESET_HANG +#define CMD_SET_RST_HANG "RST_HANG_SET" + +#define CMD_SET_RST_HANG_ARG_NUM 2 +#endif + + +#define CMD_EFUSE "EFUSE" +#define CMD_CCCR "CCCR" + +/* miracast related definition */ +#define MIRACAST_MODE_OFF 0 +#define MIRACAST_MODE_SOURCE 1 +#define MIRACAST_MODE_SINK 2 + +#ifndef MIRACAST_AMPDU_SIZE +#define MIRACAST_AMPDU_SIZE 8 +#endif + +#ifndef MIRACAST_MCHAN_ALGO +#define MIRACAST_MCHAN_ALGO 1 +#endif + +#ifndef MIRACAST_MCHAN_BW +#define MIRACAST_MCHAN_BW 25 +#endif + +#define CMD_BAND_AUTO 0 +#define CMD_BAND_5G 1 +#define CMD_BAND_2G 2 +#define CMD_BAND_ALL 3 + +/* Mediatek private command */ +#define CMD_SET_MCR "SET_MCR" +#define CMD_GET_MCR "GET_MCR" +#define CMD_SET_DRV_MCR "SET_DRV_MCR" +#define CMD_GET_DRV_MCR "GET_DRV_MCR" +#define CMD_SET_SW_CTRL "SET_SW_CTRL" +#define CMD_GET_SW_CTRL "GET_SW_CTRL" +#define CMD_SET_CFG "SET_CFG" +#define CMD_GET_CFG "GET_CFG" +#define CMD_SET_CHIP "SET_CHIP" +#define CMD_GET_CHIP "GET_CHIP" +#define CMD_SET_DBG_LEVEL "SET_DBG_LEVEL" +#define CMD_GET_DBG_LEVEL "GET_DBG_LEVEL" +#define CMD_ADD_TS "addts" +#define CMD_DEL_TS "delts" +#define CMD_DUMP_TS "dumpts" +#define CMD_RM_IT "RM-IT" +#define CMD_DUMP_UAPSD "dumpuapsd" +#define CMD_FW_EVENT "FW-EVENT " +#ifdef CFG_ALPS_ANDROID_AOSP_PRIV_CMD +#define PRIV_CMD_SIZE 512 +#else +#define PRIV_CMD_SIZE 2000 +#endif +#define CMD_SET_FIXED_RATE "FixedRate" +#define CMD_GET_VERSION "VER" +#define CMD_SET_TEST_MODE "SET_TEST_MODE" +#define CMD_SET_TEST_CMD "SET_TEST_CMD" +#define CMD_GET_TEST_RESULT "GET_TEST_RESULT" +#define CMD_GET_STA_STAT "STAT" +#define CMD_GET_STA_STAT2 "STAT2" +#define CMD_GET_STA_RX_STAT "RX_STAT" +#define CMD_SET_ACL_POLICY "SET_ACL_POLICY" +#define CMD_ADD_ACL_ENTRY "ADD_ACL_ENTRY" +#define CMD_DEL_ACL_ENTRY "DEL_ACL_ENTRY" +#define CMD_SHOW_ACL_ENTRY "SHOW_ACL_ENTRY" +#define CMD_CLEAR_ACL_ENTRY "CLEAR_ACL_ENTRY" +#define CMD_SET_RA_DBG "RADEBUG" +#define CMD_SET_FIXED_FALLBACK "FIXEDRATEFALLBACK" +#define CMD_GET_STA_IDX "GET_STA_IDX" +#define CMD_GET_TX_POWER_INFO "TxPowerInfo" +#define CMD_GET_IPI "GET_IPI" + +#if CFG_SUPPORT_ADJUST_MCC_MODE_SET +#define CMD_SET_MCC_MODE "SET_MCHAN_SCHED_MODE" +#endif + +#if CFG_WOW_SUPPORT +#define CMD_WOW_START "WOW_START" +#define CMD_SET_WOW_ENABLE "SET_WOW_ENABLE" +#define CMD_SET_WOW_PAR "SET_WOW_PAR" +#define CMD_SET_WOW_UDP "SET_WOW_UDP" +#define CMD_SET_WOW_TCP "SET_WOW_TCP" +#define CMD_GET_WOW_PORT "GET_WOW_PORT" +#define CMD_GET_WOW_REASON "GET_WOW_REASON" +#define CMD_SET_SUSP_CMD "sET_SUSP_CMD" +#define CMD_SET_MDNS_OFFLOAD_ENABLE "ENABLE_MDNS_OFFLOADING" +#define CMD_SET_SHOW_CACHE "SHOW_MDNS_CACHE" + + +#endif +#define CMD_SET_ADV_PWS "SET_ADV_PWS" +#define CMD_SET_MDTIM "SET_MDTIM" +#define CMD_GET_DSLP_CNT "GET_DSLEEP_CNT" +#define CMD_ENFORCE_POWER_MODE "ENFORCE_POWER_MODE" +#define CMD_GET_POWER_MODE "GET_POWER_MODE" + +#define CMD_SET_DBDC "SET_DBDC" + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +#define CMD_SET_CALBACKUP_TEST_DRV_FW "SET_CALBACKUP_TEST_DRV_FW" +#endif + +#define CMD_GET_CNM "GET_CNM" + +#define CMD_SET_SW_AMSDU_NUM "SET_SW_AMSDU_NUM" +#define CMD_SET_SW_AMSDU_SIZE "SET_SW_AMSDU_SIZE" + +#define CMD_SET_DRV_SER "SET_DRV_SER" + +/* Debug for consys */ +#define CMD_DBG_SHOW_TR_INFO "show-tr" +#define CMD_DBG_SHOW_PLE_INFO "show-ple" +#define CMD_DBG_SHOW_PSE_INFO "show-pse" +#define CMD_DBG_SHOW_CSR_INFO "show-csr" +#define CMD_DBG_SHOW_DMASCH_INFO "show-dmasch" + +#if CFG_SUPPORT_EASY_DEBUG +#define CMD_FW_PARAM "set_fw_param" +#endif /* CFG_SUPPORT_EASY_DEBUG */ + +#if CFG_SUPPORT_802_11K +#define CMD_NEIGHBOR_REQ "neighbor-request" +#endif + +#if CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT +#define CMD_BTM_QUERY "bss-transition-query" +#endif + +#define CMD_GET_BSS_TABLE "BSSTABLE_RSSI" + +#if CFG_SUPPORT_GET_MCS_INFO +#define CMD_GET_MCS_INFO "GET_MCS_INFO" +#endif + +#ifdef CFG_SUPPORT_TIME_MEASURE +#define CMD_START_FTM "START_FTM" +#define CMD_GET_TMR_DISTANCE "GET_TMR_DISTANCE" +#define CMD_GET_TMR_AUDIOSYNC "GET_TMR_AUDIOSYNC" +#define CMD_START_FTM_NON_BLOCK "START_FTM_NON_BLOCK" +#define CMD_ENABLE_TMR "ENABLE_TMR" +#endif + +#if CFG_SUPPORT_WAC +#define CMD_SET_WAC_IE_ENABLE "SET_WAC_IE_ENABLE" +#endif + +static uint8_t g_ucMiracastMode = MIRACAST_MODE_OFF; + +struct cmd_tlv { + char prefix; + char version; + char subver; + char reserved; +}; + +struct priv_driver_cmd_s { + char buf[PRIV_CMD_SIZE]; + int used_len; + int total_len; +}; + +#ifdef CFG_ANDROID_AOSP_PRIV_CMD +struct android_wifi_priv_cmd { + char *buf; + int used_len; + int total_len; +}; +#endif /* CFG_ANDROID_AOSP_PRIV_CMD */ + +void CoexGetArbMode(char *pcCommand, + uint32_t *pu4Offset, + uint8_t **ppucData) +{ + uint8_t *pucRegValue = *ppucData; + uint32_t u4RegValue = *pucRegValue | + *(pucRegValue+1) << 8 | + *(pucRegValue+2) << 16 | + *(pucRegValue+3) << 24; + pucRegValue += 4; + *ppucData = pucRegValue; + /* In-Band ARB Mode */ + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, "%-20s : ", + "InBand ARB mode"); + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, + "WF Rx BT Tx %s common action\n", + ((u4RegValue & BIT(12))) ? "all" : "no"); + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, + "%-20s : WF Wx BT Rx %s common action\n", + " ", + ((u4RegValue & BIT(13))) ? "all" : "no"); + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, + "%-20s : WF Rx BT Rx %s common action\n", + " ", + ((u4RegValue & BIT(14))) ? "all" : "no"); + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, + "%-20s : WF Tx BT Tx %s common action\n", + " ", + ((u4RegValue & BIT(15))) ? "all" : "no"); + + /* Out-Band ARB Mode */ + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, "%-20s : ", + "OutBand ARB mode"); + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, + "WF Rx BT Tx %s common action\n", + ((u4RegValue & BIT(28))) ? "all" : "no"); + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, + "%-20s : WF Tx BT Rx %s common action\n", + " ", + ((u4RegValue & BIT(29))) ? "all" : "no"); + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, + "%-20s : WF Rx BT Rx %s common action\n", + " ", + ((u4RegValue & BIT(30))) ? "all" : "no"); + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, + "%-20s : WF Tx BT Tx %s common action\n", + " ", + ((u4RegValue & BIT(31))) ? "all" : "no"); +} + +void CoexGetBtProfile(char *pcCommand, + uint32_t *pu4Offset, + uint8_t **ppucData) +{ + uint8_t *pucRegValue = *ppucData; + uint32_t u4RegValue = *pucRegValue | + *(pucRegValue+1) << 8 | + *(pucRegValue+2) << 16 | + *(pucRegValue+3) << 24; + pucRegValue += 4; + *ppucData = pucRegValue; + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, "%-20s : ", + "BT Profile"); + + if (COEX_BCM_IS_BT_NONE(u4RegValue)) { + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, + "none\n"); + return; + } + + if (COEX_BCM_IS_BT_SCO(u4RegValue)) { + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, + "SCO\n"); + } + + if (COEX_BCM_IS_BT_A2DP(u4RegValue)) { + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, + "A2DP\n"); + } + + if (COEX_BCM_IS_BT_LINK_CONNECTED(u4RegValue)) { + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, + "LINK CONNECTED\n"); + } + + if (COEX_BCM_IS_BT_HID(u4RegValue)) { + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, + "HID\n"); + } + + if (COEX_BCM_IS_BT_PAGE(u4RegValue)) { + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, + "PAGE\n"); + } + + if (COEX_BCM_IS_BT_INQUIRY(u4RegValue)) { + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, + "INQUIRY\n"); + } + + if (COEX_BCM_IS_BT_ESCO(u4RegValue)) { + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, + "ESCO\n"); + } + + if (COEX_BCM_IS_BT_MULTI_HID(u4RegValue)) { + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, + "MULTI HID\n"); + } + + if (COEX_BCM_IS_BT_BLE_VOBLE(u4RegValue)) { + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, + "BLE VOBLE\n"); + } + + if (COEX_BCM_IS_BT_A2DP_SINK(u4RegValue)) { + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, + "A2DP SINK\n"); + } +} + +void CoexGetProtFrmType(char *pcCommand, + uint32_t *pu4Offset, + uint8_t **ppucData) +{ + uint8_t *pucRegValue = *ppucData; + uint32_t u4RegValue = *pucRegValue | + *(pucRegValue+1) << 8 | + *(pucRegValue+2) << 16 | + *(pucRegValue+3) << 24; + pucRegValue += 4; + *ppucData = pucRegValue; + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, "%-20s : %s\n", + "Protection Type", + u4RegValue ? "PS-NULL" : "CTS"); +} + +void CoexGetRxBaSize(char *pcCommand, + uint32_t *pu4Offset, + uint8_t **ppucData) +{ + uint8_t *pucRegValue = *ppucData; + /* BA Size */ + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, "%-20s : %d\n", + "Rx BA Size", + *pucRegValue); + *ppucData = ++pucRegValue; +} + +void CoexGetCfgCoexIsoCtrl(char *pcCommand, + uint32_t *pu4Offset, + uint8_t **ppucData) +{ + uint8_t *pucRegValue = *ppucData; + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, "%-20s : %d\n", + "CFG CoexIsoCtrl", + *pucRegValue); + *ppucData = ++pucRegValue; +} + +void CoexGetCfgCoexModeCtrl(char *pcCommand, + uint32_t *pu4Offset, + uint8_t **ppucData) +{ + uint8_t *pucRegValue = *ppucData; + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, "%-20s : %d\n", + "CFG CoexModeCtrl", + *pucRegValue); + *ppucData = ++pucRegValue; +} + +void CoexGetCfgFddPerPkt(char *pcCommand, + uint32_t *pu4Offset, + uint8_t **ppucData) +{ + uint8_t *pucRegValue = *ppucData; + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, "%-20s : %d\n", + "CFG FddPerPkt", + *pucRegValue); + *ppucData = ++pucRegValue; +} + +/* Coex Ctrl Cmd - Coex Info Content */ +struct COEX_REF_TABLE { + uint16_t ucCoexInfoId; + char *cContent; + void (*pCoexRefHandle)(char *pcCommand, + uint32_t *pu4Offset, + uint8_t **ppucData); +}; + +const struct COEX_REF_TABLE coex_ref_table[] = { + {COEX_REF_TABLE_ID_ISO_DETECTION_VALUE, + "Isolation Detection Value", NULL}, + {COEX_REF_TABLE_ID_COEX_BT_PROFILE, + "Coex BT Profile", CoexGetBtProfile}, + {COEX_REF_TABLE_ID_RX_BASIZE, + "Rx Ba Size", CoexGetRxBaSize}, + {COEX_REF_TABLE_ID_ARB_MODE, + "ARB Mode", CoexGetArbMode}, + {COEX_REF_TABLE_ID_PROT_FRM_TYPE, + "Prot Frame Type", CoexGetProtFrmType}, + {COEX_REF_TABLE_ID_CFG_COEXISOCTRL, + "CFG CoexIsoCtrl", CoexGetCfgCoexIsoCtrl}, + {COEX_REF_TABLE_ID_CFG_COEXMODECTRL, + "CFG CoexModeCtrl", CoexGetCfgCoexModeCtrl}, + {COEX_REF_TABLE_ID_CFG_FDDPERPKT, + "CFG FddPerPkt", CoexGetCfgFddPerPkt}, + {COEX_REF_TABLE_ID_CFG_BT_FIX_POWER, + "CFG BT FIX POWER", NULL}, + {COEX_REF_TABLE_ID_CFG_BT_FDD_GAIN, + "CFG BT FDD GAIN", NULL}, + {COEX_REF_TABLE_ID_CFG_BT_FDD_POWER, + "CFG BT FDD POWER", NULL}, + {COEX_REF_TABLE_ID_CFG_WF_FDD_POWER, + "CFG WF FDD POWER", NULL} +}; + +int priv_driver_get_dbg_level(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + uint32_t u4DbgIdx, u4DbgMask; + u_int8_t fgIsCmdAccept = FALSE; + int32_t u4Ret = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= 2) { + /* u4DbgIdx = kalStrtoul(apcArgv[1], NULL, 0); */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4DbgIdx); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + + if (wlanGetDriverDbgLevel(u4DbgIdx, &u4DbgMask) == + WLAN_STATUS_SUCCESS) { + fgIsCmdAccept = TRUE; + i4BytesWritten = + snprintf(pcCommand, i4TotalLen, + "Get DBG module[%u] log level => [0x%02x]!", + u4DbgIdx, + (uint8_t) u4DbgMask); + } + } + + if (!fgIsCmdAccept) + i4BytesWritten = snprintf(pcCommand, i4TotalLen, + "Get DBG module log level failed!"); + + return i4BytesWritten; + +} /* priv_driver_get_sw_ctrl */ + +static int priv_cmd_not_support(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + DBGLOG(REQ, WARN, "not support priv command: %s\n", pcCommand); + + return -EOPNOTSUPP; +} + +#if CFG_SUPPORT_QA_TOOL +#if CFG_SUPPORT_BUFFER_MODE +static int priv_driver_set_efuse_buffer_mode( + IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int32_t i4BytesWritten = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + struct PARAM_CUSTOM_EFUSE_BUFFER_MODE + *prSetEfuseBufModeInfo = NULL; +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 0) + struct BIN_CONTENT *pBinContent; + int i = 0; +#endif + uint8_t *pucConfigBuf = NULL; + uint32_t u4ConfigReadLen; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + pucConfigBuf = (uint8_t *) kalMemAlloc(2048, VIR_MEM_TYPE); + + if (!pucConfigBuf) { + DBGLOG(INIT, INFO, "allocate pucConfigBuf failed\n"); + i4BytesWritten = -1; + goto out; + } + + kalMemZero(pucConfigBuf, 2048); + u4ConfigReadLen = 0; + + if (kalReadToFile("/MT6632_eFuse_usage_table.xlsm.bin", + pucConfigBuf, 2048, &u4ConfigReadLen) == 0) { + /* ToDo:: Nothing */ + } else { + DBGLOG(INIT, INFO, "can't find file\n"); + i4BytesWritten = -1; + goto out; + } + + /* pucConfigBuf */ + prSetEfuseBufModeInfo = + (struct PARAM_CUSTOM_EFUSE_BUFFER_MODE *) kalMemAlloc( + sizeof(struct PARAM_CUSTOM_EFUSE_BUFFER_MODE), + VIR_MEM_TYPE); + + if (prSetEfuseBufModeInfo == NULL) { + DBGLOG(INIT, INFO, + "allocate prSetEfuseBufModeInfo failed\n"); + i4BytesWritten = -1; + goto out; + } + + kalMemZero(prSetEfuseBufModeInfo, + sizeof(struct PARAM_CUSTOM_EFUSE_BUFFER_MODE)); + + prSetEfuseBufModeInfo->ucSourceMode = 1; + prSetEfuseBufModeInfo->ucCount = (uint8_t) + EFUSE_CONTENT_SIZE; + +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 0) + pBinContent = (struct BIN_CONTENT *) + prSetEfuseBufModeInfo->aBinContent; + for (i = 0; i < EFUSE_CONTENT_SIZE; i++) { + pBinContent->u2Addr = i; + pBinContent->ucValue = *(pucConfigBuf + i); + + pBinContent++; + } + + for (i = 0; i < 20; i++) + DBGLOG(INIT, INFO, "%x\n", + prSetEfuseBufModeInfo->aBinContent[i].ucValue); +#endif + + rStatus = kalIoctl(prGlueInfo, wlanoidSetEfusBufferMode, + prSetEfuseBufModeInfo, + sizeof(struct PARAM_CUSTOM_EFUSE_BUFFER_MODE), + FALSE, FALSE, TRUE, &u4BufLen); + + i4BytesWritten = + snprintf(pcCommand, i4TotalLen, "set buffer mode %s", + (rStatus == WLAN_STATUS_SUCCESS) ? "success" : "fail"); + +out: + if (pucConfigBuf) + kalMemFree(pucConfigBuf, VIR_MEM_TYPE, 2048); + + if (prSetEfuseBufModeInfo) + kalMemFree(prSetEfuseBufModeInfo, VIR_MEM_TYPE, + sizeof(truct PARAM_CUSTOM_EFUSE_BUFFER_MODE)); + + return i4BytesWritten; +} +#endif /* CFG_SUPPORT_BUFFER_MODE */ + +static int priv_driver_get_rx_statistics(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t u4Ret = 0; + struct PARAM_CUSTOM_ACCESS_RX_STAT rRxStatisticsTest; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + DBGLOG(INIT, ERROR, + "MT6632 : priv_driver_get_rx_statistics\n"); + + if (i4Argc >= 2) { + u4Ret = kalkStrtou32(apcArgv[1], 0, + &(rRxStatisticsTest.u4SeqNum)); + rRxStatisticsTest.u4TotalNum = sizeof(struct + PARAM_RX_STAT) / 4; + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryRxStatistics, + &rRxStatisticsTest, sizeof(rRxStatisticsTest), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } + + return i4BytesWritten; +} +#endif /* CFG_SUPPORT_QA_TOOL */ + +#if CFG_SUPPORT_MSP +#if 0 +static int priv_driver_get_stat(IN struct net_device + *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t i4ArgNum = 2; + struct PARAM_GET_STA_STATISTICS rQueryStaStatistics; + int32_t rRssi; + uint16_t u2LinkSpeed; + uint32_t u4Per; + UINTT_8 i; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + kalMemZero(&rQueryStaStatistics, + sizeof(rQueryStaStatistics)); + + if (i4Argc >= i4ArgNum) { + wlanHwAddrToBin(apcArgv[1], + &rQueryStaStatistics.aucMacAddr[0]); + + rQueryStaStatistics.ucReadClear = TRUE; + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryStaStatistics, + &rQueryStaStatistics, + sizeof(rQueryStaStatistics), + TRUE, FALSE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_SUCCESS) { + rRssi = RCPI_TO_dBm(rQueryStaStatistics.ucRcpi); + u2LinkSpeed = rQueryStaStatistics.u2LinkSpeed == 0 ? 0 : + rQueryStaStatistics.u2LinkSpeed / 2; + + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, + "%s", "\n\nSTA Stat:\n"); + + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "CurrentTemperature = %d\n", 0); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Tx success = %lu\n", 0); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Tx fail count = %ld, PER=%ld.%1ld%%\n", + 0, 0, 0); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Rx success = %lu\n", 0); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Rx with CRC = %ld, PER=%ld.%1ld%%\n", + 0, 0, 0); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Rx with PhyErr = %lu\n", 0); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Rx with PlcpErr = %lu\n", 0); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Rx drop due to out of resource= %lu\n", 0); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Rx duplicate frame = %lu\n", 0); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "False CCA = %lu\n", 0); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "RSSI = %d %d %d %d\n", + 0, 0, 0, 0); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Last TX Rate = %s, %s, %s, %s, %s\n", + "NA", "NA", "NA", "NA", "NA"); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Last RX Rate = %s, %s, %s, %s, %s\n", + "NA", "NA", "NA", "NA", "NA"); + + for (i = 0; i < 2 /* band num */; i++) { + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "BandIdx: = %d\n", i); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s", + "\tRange: 1 2~5 6~15 16~22 23~33 34~49 50~57 58~64\n" + ); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\t\t%d \t%d \t%d \t%d \t%d \t%d \t%d \t%d\n", + 0, 0, 0, 0, 0, 0, 0, 0); + } + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Tx success = %ld\n", + rQueryStaStatistics.u4TransmitCount - + rQueryStaStatistics.u4TransmitFailCount); + + u4Per = rQueryStaStatistics.u4TransmitFailCount == 0 ? + 0 : + (1000 * (rQueryStaStatistics.u4TransmitFailCount)) + / rQueryStaStatistics.u4TransmitCount; + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Tx fail count = %ld, PER=%ld.%1ld%%\n", + rQueryStaStatistics.u4TransmitFailCount, + u4Per / 10, u4Per % 10); + + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "RSSI = %d\n", rRssi); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "LinkSpeed = %d\n", u2LinkSpeed); + } + } else + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, "%s", + "\n\nNo STA Stat:\n"); + + return i4BytesWritten; +} +#endif + + +static int priv_driver_get_sta_statistics( + IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t i4ArgNum = 3; + struct PARAM_GET_STA_STATISTICS rQueryStaStatistics; + int32_t rRssi; + uint16_t u2LinkSpeed; + uint32_t u4Per; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + kalMemZero(&rQueryStaStatistics, + sizeof(rQueryStaStatistics)); + rQueryStaStatistics.ucReadClear = TRUE; + + if (i4Argc >= i4ArgNum) { + if (strnicmp(apcArgv[1], CMD_GET_STA_KEEP_CNT, + strlen(CMD_GET_STA_KEEP_CNT)) == 0) { + wlanHwAddrToBin(apcArgv[2], + &rQueryStaStatistics.aucMacAddr[0]); + rQueryStaStatistics.ucReadClear = FALSE; + } else if (strnicmp(apcArgv[2], CMD_GET_STA_KEEP_CNT, + strlen(CMD_GET_STA_KEEP_CNT)) == 0) { + wlanHwAddrToBin(apcArgv[1], + &rQueryStaStatistics.aucMacAddr[0]); + rQueryStaStatistics.ucReadClear = FALSE; + } + } else { + /* Get AIS AP address for no argument */ + if (prGlueInfo->prAdapter->prAisBssInfo->prStaRecOfAP) { + COPY_MAC_ADDR(rQueryStaStatistics.aucMacAddr, + prGlueInfo->prAdapter->prAisBssInfo + ->prStaRecOfAP->aucMacAddr); + DBGLOG(RSN, INFO, "use ais ap "MACSTR"\n", + MAC2STR(prGlueInfo->prAdapter->prAisBssInfo + ->prStaRecOfAP->aucMacAddr)); + } else { + DBGLOG(RSN, INFO, "not connect to ais ap %lx\n", + prGlueInfo->prAdapter->prAisBssInfo + ->prStaRecOfAP); + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, + "%s", "\n\nNo STA Stat:\n"); + return i4BytesWritten; + } + + if (i4Argc == 2) { + if (strnicmp(apcArgv[1], CMD_GET_STA_KEEP_CNT, + strlen(CMD_GET_STA_KEEP_CNT)) == 0) + rQueryStaStatistics.ucReadClear = FALSE; + } + } + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryStaStatistics, + &rQueryStaStatistics, sizeof(rQueryStaStatistics), + TRUE, FALSE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_SUCCESS) { + rRssi = RCPI_TO_dBm(rQueryStaStatistics.ucRcpi); + u2LinkSpeed = rQueryStaStatistics.u2LinkSpeed == 0 ? 0 : + rQueryStaStatistics.u2LinkSpeed / 2; + + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, "%s", + "\n\nSTA Stat:\n"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Tx total cnt = %d\n", + rQueryStaStatistics.u4TransmitCount); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Tx success = %d\n", + rQueryStaStatistics.u4TransmitCount - + rQueryStaStatistics.u4TransmitFailCount); + + u4Per = rQueryStaStatistics.u4TransmitCount == 0 ? 0 : + (1000 * (rQueryStaStatistics.u4TransmitFailCount)) / + rQueryStaStatistics.u4TransmitCount; + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Tx fail count = %d, PER=%d.%d%%\n", + rQueryStaStatistics.u4TransmitFailCount, u4Per / 10, + u4Per % 10); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "RSSI = %d\n", rRssi); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "LinkSpeed = %d\n", u2LinkSpeed); + + } else + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, "%s", + "\n\nNo STA Stat:\n"); + + return i4BytesWritten; + +} + + +static int priv_driver_get_bss_statistics( + IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus; + uint8_t arBssid[PARAM_MAC_ADDR_LEN]; + uint32_t u4BufLen; + int32_t i4Rssi; + struct PARAM_GET_BSS_STATISTICS rQueryBssStatistics; + struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = + (struct NETDEV_PRIVATE_GLUE_INFO *) NULL; + uint8_t ucBssIndex; + int32_t i4BytesWritten = 0; +#if 0 + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i4Argc = 0; + uint32_t u4Index; +#endif + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + + kalMemZero(arBssid, MAC_ADDR_LEN); + wlanQueryInformation(prGlueInfo->prAdapter, wlanoidQueryBssid, + &arBssid[0], sizeof(arBssid), &u4BufLen); + +#if 0 /* Todo:: Get the none-AIS statistics */ + if (i4Argc >= 2) + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Index); +#endif + + /* 2. fill RSSI */ + if (prGlueInfo->eParamMediaStateIndicated != + PARAM_MEDIA_STATE_CONNECTED) { + /* not connected */ + DBGLOG(REQ, WARN, "not yet connected\n"); + return WLAN_STATUS_SUCCESS; + } + rStatus = kalIoctl(prGlueInfo, wlanoidQueryRssi, &i4Rssi, + sizeof(i4Rssi), TRUE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "unable to retrieve rssi\n"); + + + /* 3 get per-BSS link statistics */ + if (rStatus == WLAN_STATUS_SUCCESS) { + /* get Bss Index from ndev */ + prNetDevPrivate = (struct NETDEV_PRIVATE_GLUE_INFO *) + netdev_priv(prNetDev); + ASSERT(prNetDevPrivate->prGlueInfo == prGlueInfo); + ucBssIndex = prNetDevPrivate->ucBssIdx; + + kalMemZero(&rQueryBssStatistics, + sizeof(rQueryBssStatistics)); + rQueryBssStatistics.ucBssIndex = ucBssIndex; + + rQueryBssStatistics.ucReadClear = TRUE; + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryBssStatistics, + &rQueryBssStatistics, + sizeof(rQueryBssStatistics), + TRUE, FALSE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_SUCCESS) { + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, + "%s", "\n\nStat:\n"); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "CurrentTemperature = -\n"); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Tx success = %d\n", + rQueryBssStatistics.u4TransmitCount - + rQueryBssStatistics.u4TransmitFailCount); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Tx fail count = %d\n", + rQueryBssStatistics.u4TransmitFailCount); +#if 0 + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Rx success = %ld\n", 0); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Rx with CRC = %ld\n", + prStatistics->rFCSErrorCount.QuadPart); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "Rx with PhyErr = 0\n"); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + "%s", "Rx with PlcpErr = 0\n"); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "Rx drop due to out of resource = 0\n"); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Rx duplicate frame = %ld\n", + prStatistics->rFrameDuplicateCount.QuadPart); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "False CCA = 0\n"); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "RSSI = %d\n", i4Rssi); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Last TX Rate = %s, %s, %s, %s, %s\n", + "NA", "NA", "NA", "NA", "NA"); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Last RX Rate = %s, %s, %s, %s, %s\n", + "NA", "NA", "NA", "NA", "NA"); +#endif + + } + + } else { + DBGLOG(REQ, WARN, + "unable to retrieve per-BSS link statistics\n"); + } + + + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, + pcCommand); + + return i4BytesWritten; + +} + +#if CFG_SUPPORT_GET_MCS_INFO +#define GET_TX_MCS_BW(_x) (((_x) & (0x3 << 12)) >> 12) +#define GET_TX_MCS_SGI(_x) (((_x) & (0x1 << 14)) >> 14) +#define GET_TX_MCS_LDPC(_x) (((_x) & (0x1 << 15)) >> 15) +#endif + +char *HW_TX_MODE_STR[] = {"CCK", "OFDM", "MM", "GF", "VHT", "N/A"}; +char *HW_TX_RATE_CCK_STR[] = {"1M", "2M", "5.5M", "11M", "N/A"}; +char *HW_TX_RATE_OFDM_STR[] = {"6M", "9M", "12M", "18M", "24M", "36M", + "48M", "54M", "N/A"}; +char *HW_TX_RATE_BW[] = {"BW20", "BW40", "BW80", "BW160/BW8080", "N/A"}; + +#if (CFG_SUPPORT_RA_GEN == 0) +static char *RATE_TBLE[] = {"B", "G", "N", "N_2SS", "AC", "AC_2SS", "N/A"}; +#else +static char *RATE_TBLE[] = {"B", "G", "N", "N_2SS", "AC", "AC_2SS", "BG", + "N/A"}; +static char *RA_STATUS_TBLE[] = {"INVALID", "POWER_SAVING", "SLEEP", "STANDBY", + "RUNNING", "N/A"}; +#if 0 +static char *LT_MODE_TBLE[] = {"RSSI", "LAST_RATE", "TRACKING", "N/A"}; +static char *SGI_UNSP_STATE_TBLE[] = {"INITIAL", "PROBING", "SUCCESS", + "FAILURE", "N/A"}; +static char *BW_STATE_TBLE[] = {"UNCHANGED", "DOWN", "N/A"}; +#endif +#endif + +#if 0 +static char *AR_STATE[] = {"NULL", "STEADY", "PROBE", "N/A"}; +static char *AR_ACTION[] = {"NULL", "INDEX", "RATE_UP", "RATE_DOWN", "RATE_GRP", + "RATE_BACK", "GI", "SGI_EN", "SGI_DIS", "PWR", + "PWR_UP", "PWR_DOWN", "PWR_RESET_UP", "BF", "BF_EN", + "BF_DIS", "N/A"}; +#endif +#define BW_20 0 +#define BW_40 1 +#define BW_80 2 +#define BW_160 3 +#define BW_10 4 +#define BW_5 6 +#define BW_8080 7 +#define BW_ALL 0xFF + +char *hw_rate_ofdm_str(uint16_t ofdm_idx) +{ + switch (ofdm_idx) { + case 11: /* 6M */ + return HW_TX_RATE_OFDM_STR[0]; + case 15: /* 9M */ + return HW_TX_RATE_OFDM_STR[1]; + case 10: /* 12M */ + return HW_TX_RATE_OFDM_STR[2]; + case 14: /* 18M */ + return HW_TX_RATE_OFDM_STR[3]; + case 9: /* 24M */ + return HW_TX_RATE_OFDM_STR[4]; + case 13: /* 36M */ + return HW_TX_RATE_OFDM_STR[5]; + case 8: /* 48M */ + return HW_TX_RATE_OFDM_STR[6]; + case 12: /* 54M */ + return HW_TX_RATE_OFDM_STR[7]; + default: + return HW_TX_RATE_OFDM_STR[8]; + } +} + +static u_int8_t priv_driver_get_sgi_info( + IN struct PARAM_PEER_CAP *prWtblPeerCap) +{ + if (!prWtblPeerCap) + return FALSE; + + switch (prWtblPeerCap->ucFrequencyCapability) { + case BW_20: + return prWtblPeerCap->fgG2; + case BW_40: + return prWtblPeerCap->fgG4; + case BW_80: + return prWtblPeerCap->fgG8; + case BW_160: + return prWtblPeerCap->fgG16; + default: + return FALSE; + } +} + +static u_int8_t priv_driver_get_ldpc_info( + IN struct PARAM_TX_CONFIG *prWtblTxConfig) +{ + if (!prWtblTxConfig) + return FALSE; + + if (prWtblTxConfig->fgIsVHT) + return prWtblTxConfig->fgVhtLDPC; + else + return prWtblTxConfig->fgLDPC; +} + +int32_t priv_driver_rate_to_string(IN char *pcCommand, + IN int i4TotalLen, uint8_t TxRx, + struct PARAM_HW_WLAN_INFO *prHwWlanInfo) +{ + uint8_t i, txmode, rate, stbc; + uint8_t nss; + int32_t i4BytesWritten = 0; + + for (i = 0; i < AUTO_RATE_NUM; i++) { + + txmode = HW_TX_RATE_TO_MODE( + prHwWlanInfo->rWtblRateInfo.au2RateCode[i]); + if (txmode >= MAX_TX_MODE) + txmode = MAX_TX_MODE; + rate = HW_TX_RATE_TO_MCS( + prHwWlanInfo->rWtblRateInfo.au2RateCode[i], + txmode); + nss = HW_TX_RATE_TO_NSS( + prHwWlanInfo->rWtblRateInfo.au2RateCode[i]) + 1; + stbc = HW_TX_RATE_TO_STBC( + prHwWlanInfo->rWtblRateInfo.au2RateCode[i]); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRate index[%d] ", i); + + if (prHwWlanInfo->rWtblRateInfo.ucRateIdx == i) { + if (TxRx == 0) + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "[Last RX Rate] "); + else + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "[Last TX Rate] "); + } else + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", " "); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + rate < 4 ? HW_TX_RATE_CCK_STR[rate] : + HW_TX_RATE_CCK_STR[4]); + else if (txmode == TX_RATE_MODE_OFDM) + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + hw_rate_ofdm_str(rate)); + else { + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "NSS%d_MCS%d, ", nss, rate); + } + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", HW_TX_RATE_BW[ + prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability]); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + rate < 4 ? "LP" : "SP"); + else if (txmode == TX_RATE_MODE_OFDM) + ; + else + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + priv_driver_get_sgi_info( + &prHwWlanInfo->rWtblPeerCap) == 0 ? + "LGI" : "SGI"); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s%s %s\n", + HW_TX_MODE_STR[txmode], stbc ? "STBC" : " ", + priv_driver_get_ldpc_info(&prHwWlanInfo->rWtblTxConfig) + == 0 ? "BCC" : "LDPC"); + } + + return i4BytesWritten; +} + +static int32_t priv_driver_dump_helper_wtbl_info(IN char *pcCommand, + IN int i4TotalLen, struct PARAM_HW_WLAN_INFO *prHwWlanInfo) +{ + uint8_t i; + int32_t i4BytesWritten = 0; + + ASSERT(pcCommand); + + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, "%s", + "\n\nwtbl:\n"); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Dump WTBL info of WLAN_IDX = %d\n", + prHwWlanInfo->u4Index); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tAddr="MACSTR"\n", + MAC2STR(prHwWlanInfo->rWtblTxConfig.aucPA)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tMUAR_Idx = %d\n", + prHwWlanInfo->rWtblSecConfig.ucMUARIdx); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\trc_a1/rc_a2:%d/%d\n", + prHwWlanInfo->rWtblSecConfig.fgRCA1, + prHwWlanInfo->rWtblSecConfig.fgRCA2); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tKID:%d/RCID:%d/RKV:%d/RV:%d/IKV:%d/WPI_FLAG:%d\n", + prHwWlanInfo->rWtblSecConfig.ucKeyID, + prHwWlanInfo->rWtblSecConfig.fgRCID, + prHwWlanInfo->rWtblSecConfig.fgRKV, + prHwWlanInfo->rWtblSecConfig.fgRV, + prHwWlanInfo->rWtblSecConfig.fgIKV, + prHwWlanInfo->rWtblSecConfig.fgEvenPN); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s", "\tGID_SU:NA"); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tsw/DIS_RHTR:%d/%d\n", + prHwWlanInfo->rWtblTxConfig.fgSW, + prHwWlanInfo->rWtblTxConfig.fgDisRxHdrTran); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tHT/VHT/HT-LDPC/VHT-LDPC/DYN_BW/MMSS:%d/%d/%d/%d/%d/%d\n", + prHwWlanInfo->rWtblTxConfig.fgIsHT, + prHwWlanInfo->rWtblTxConfig.fgIsVHT, + prHwWlanInfo->rWtblTxConfig.fgLDPC, + prHwWlanInfo->rWtblTxConfig.fgVhtLDPC, + prHwWlanInfo->rWtblTxConfig.fgDynBw, + prHwWlanInfo->rWtblPeerCap.ucMMSS); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tFCAP/G2/G4/G8/G16/CBRN:%d/%d/%d/%d/%d/%d\n", + prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability, + prHwWlanInfo->rWtblPeerCap.fgG2, + prHwWlanInfo->rWtblPeerCap.fgG4, + prHwWlanInfo->rWtblPeerCap.fgG8, + prHwWlanInfo->rWtblPeerCap.fgG16, + prHwWlanInfo->rWtblPeerCap.ucChangeBWAfterRateN); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tHT-TxBF(tibf/tebf):%d/%d, VHT-TxBF(tibf/tebf):%d/%d, PFMU_IDX=%d\n", + prHwWlanInfo->rWtblTxConfig.fgTIBF, + prHwWlanInfo->rWtblTxConfig.fgTEBF, + prHwWlanInfo->rWtblTxConfig.fgVhtTIBF, + prHwWlanInfo->rWtblTxConfig.fgVhtTEBF, + prHwWlanInfo->rWtblTxConfig.ucPFMUIdx); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s", "\tSPE_IDX=NA\n"); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tBA Enable:0x%x, BAFail Enable:%d\n", + prHwWlanInfo->rWtblBaConfig.ucBaEn, + prHwWlanInfo->rWtblTxConfig.fgBAFEn); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tQoS Enable:%d\n", prHwWlanInfo->rWtblTxConfig.fgIsQoS); + if (prHwWlanInfo->rWtblTxConfig.fgIsQoS) { + for (i = 0; i < 8; i += 2) { + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\t\tBA WinSize: TID 0 - %d, TID 1 - %d\n", + (uint32_t) + ((prHwWlanInfo->rWtblBaConfig.u4BaWinSize >> + (i * 3)) & BITS(0, 2)), + (uint32_t) + ((prHwWlanInfo->rWtblBaConfig.u4BaWinSize >> + ((i + 1) * 3)) & BITS(0, 2))); + } + } + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tpartial_aid:%d\n", + prHwWlanInfo->rWtblTxConfig.u2PartialAID); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\twpi_even:%d\n", + prHwWlanInfo->rWtblSecConfig.fgEvenPN); + i4BytesWritten += scnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tAAD_OM/CipherSuit:%d/%d\n", + prHwWlanInfo->rWtblTxConfig.fgAADOM, + prHwWlanInfo->rWtblSecConfig.ucCipherSuit); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\taf:%d\n", + prHwWlanInfo->rWtblPeerCap.ucAmpduFactor); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\trdg_ba:%d/rdg capability:%d\n", + prHwWlanInfo->rWtblTxConfig.fgRdgBA, + prHwWlanInfo->rWtblTxConfig.fgRDG); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tcipher_suit:%d\n", + prHwWlanInfo->rWtblSecConfig.ucCipherSuit); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tFromDS:%d\n", + prHwWlanInfo->rWtblTxConfig.fgIsFromDS); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tToDS:%d\n", + prHwWlanInfo->rWtblTxConfig.fgIsToDS); +#if 0 + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRCPI = %d %d %d %d\n", + prHwWlanInfo->rWtblRxCounter.ucRxRcpi0, + prHwWlanInfo->rWtblRxCounter.ucRxRcpi1, + prHwWlanInfo->rWtblRxCounter.ucRxRcpi2, + prHwWlanInfo->rWtblRxCounter.ucRxRcpi3); +#endif + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRSSI = %d %d %d %d\n", + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi0), + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi1), + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi2), + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi3)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s", "\tRate Info\n"); + + i4BytesWritten += priv_driver_rate_to_string(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, 1, prHwWlanInfo); + +#if 0 + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, i4TotalLen - + i4BytesWritten, + "%s", "\t===Key======\n"); + for (i = 0; i < 32; i += 8) { + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\t0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", + prHwWlanInfo->rWtblKeyConfig.aucKey[i + 0], + prHwWlanInfo->rWtblKeyConfig.aucKey[i + 1], + prHwWlanInfo->rWtblKeyConfig.aucKey[i + 2], + prHwWlanInfo->rWtblKeyConfig.aucKey[i + 3], + prHwWlanInfo->rWtblKeyConfig.aucKey[i + 4], + prHwWlanInfo->rWtblKeyConfig.aucKey[i + 5], + prHwWlanInfo->rWtblKeyConfig.aucKey[i + 6], + prHwWlanInfo->rWtblKeyConfig.aucKey[i + 7]); + } +#endif + + return i4BytesWritten; +} + +static int priv_driver_get_wtbl_info(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int32_t u4Ret = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + struct PARAM_HW_WLAN_INFO *prHwWlanInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + /* DBGLOG(RSN, INFO, "MT6632 : priv_driver_get_wtbl_info\n"); */ + + prHwWlanInfo = (struct PARAM_HW_WLAN_INFO *)kalMemAlloc( + sizeof(struct PARAM_HW_WLAN_INFO), VIR_MEM_TYPE); + if (!prHwWlanInfo) + return -1; + + if (i4Argc >= 2) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &prHwWlanInfo->u4Index); + + DBGLOG(REQ, INFO, "MT6632 : index = %d\n", + prHwWlanInfo->u4Index); + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryWlanInfo, + prHwWlanInfo, + sizeof(struct PARAM_HW_WLAN_INFO), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, INFO, "rStatus %u u4BufLen = %d\n", rStatus, + u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + kalMemFree(prHwWlanInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_HW_WLAN_INFO)); + return -1; + } + i4BytesWritten = priv_driver_dump_helper_wtbl_info(pcCommand, + i4TotalLen, prHwWlanInfo); + } + + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + + kalMemFree(prHwWlanInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_HW_WLAN_INFO)); + + return i4BytesWritten; +} + +/* Private Coex Ctrl Subcmd for Getting Coex Info */ +static int priv_driver_get_coex_info(IN struct GLUE_INFO *prGlueInfo, + IN struct CMD_COEX_HANDLER *prCmdCoexHandler, + IN signed char *argv[]) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + uint32_t u4Ret = 0; + + struct CMD_COEX_GET_INFO rCmdCoexGetInfo; + + kalMemSet(&rCmdCoexGetInfo, + 0, + sizeof(struct CMD_COEX_GET_INFO)); + + /* Copy Memory */ + kalMemCopy(prCmdCoexHandler->aucBuffer, + &rCmdCoexGetInfo, + sizeof(struct CMD_COEX_GET_INFO)); + DBGLOG(INIT, INFO, "priv_driver_get_coex_info end\n"); + + /* Ioctl Get Coex Info */ + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryCoexGetInfo, + prCmdCoexHandler, + sizeof(struct CMD_COEX_HANDLER), + TRUE, + TRUE, + TRUE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + /* If all pass, return u4Ret to 0 */ + return u4Ret; +} + +static void priv_coex_get_info(IN char *pcCommand, + IN int i4TotalLen, + IN uint32_t *pu4Offset, + IN struct CMD_COEX_HANDLER *prCmdCoexHandler) +{ +#define CMD_DEFAULT_LEN 2 +#define DEFAULT_LEN_BYTE 2 + struct CMD_COEX_GET_INFO *prCmdCoexGetInfo; + uint8_t ucIdx = 0; + uint16_t u2TotLen; + uint8_t ucCoexId; + uint8_t ucCoexLen; + uint8_t *pucCoexInfo; + + prCmdCoexGetInfo = + (struct CMD_COEX_GET_INFO *) prCmdCoexHandler->aucBuffer; + + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, "\n"); + + pucCoexInfo = &prCmdCoexGetInfo->ucCoexInfo[0]; + u2TotLen = *pucCoexInfo | (*(pucCoexInfo+1) << 8); + pucCoexInfo += DEFAULT_LEN_BYTE; + + while (ucIdx < u2TotLen) { + ucCoexId = *pucCoexInfo++; + ucCoexLen = *pucCoexInfo++; + ucIdx += ucCoexLen + CMD_DEFAULT_LEN; + + if (ucCoexId >= COEX_REF_TABLE_ID_NUM) { + *pu4Offset += snprintf(pcCommand + *pu4Offset, + PRIV_CMD_SIZE - *pu4Offset, "Wrong coex info id...\n"); + return; + } + + if (coex_ref_table[ucCoexId].pCoexRefHandle) { + coex_ref_table[ucCoexId].pCoexRefHandle(pcCommand, + pu4Offset, + &pucCoexInfo); + } else{ + pucCoexInfo += ucCoexLen; + } + } +} + +/* Private Coex Ctrl Subcmd for Isolation Detection */ +static int priv_driver_iso_detect(IN struct GLUE_INFO *prGlueInfo, + IN struct CMD_COEX_HANDLER *prCmdCoexHandler, + IN signed char *argv[]) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + uint32_t u4Ret = 0; + + struct CMD_COEX_ISO_DETECT rCmdCoexIsoDetect; + + rCmdCoexIsoDetect.u4Isolation = 0; + + u4Ret = kalkStrtou32(argv[2], 0, &(rCmdCoexIsoDetect.u4IsoPath)); + if (u4Ret) { + DBGLOG(REQ, LOUD, + "Parse Iso Path failed u4Ret=%d\n", u4Ret); + return -1; + } + + u4Ret = kalkStrtou32(argv[3], 0, &(rCmdCoexIsoDetect.u4Channel)); + if (u4Ret) { + DBGLOG(REQ, LOUD, + "Parse channel failed u4Ret = %d\n", u4Ret); + return -1; + } + + /* Copy Memory */ + kalMemCopy(prCmdCoexHandler->aucBuffer, + &rCmdCoexIsoDetect, + sizeof(struct CMD_COEX_ISO_DETECT)); + + DBGLOG(REQ, INFO, "priv_driver_get_coex_info end\n"); + + /* Ioctl Isolation Detect */ + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryCoexIso, + prCmdCoexHandler, + sizeof(struct CMD_COEX_HANDLER), + TRUE, + TRUE, + TRUE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + /* If all pass, return u4Ret to 0 */ + return u4Ret; +} + +/* Private Command for Coex Ctrl */ +static int priv_driver_coex_ctrl(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int32_t i4ArgNum = 2; + signed char *apcArgv[WLAN_CFG_ARGV_MAX]; + uint32_t u4Ret = 0; + uint32_t u4Offset = 0; + int32_t i4SubArgNum; + enum ENUM_COEX_CMD_CTRL CoexCmdCtrl; + struct CMD_COEX_HANDLER rCmdCoexHandler; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + /* Prevent Kernel Panic, set default i4ArgNum to 2 */ + if (i4Argc >= i4ArgNum) { + + /* Parse Coex SubCmd */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &rCmdCoexHandler.u4SubCmd); + if (u4Ret) + return -1; + + CoexCmdCtrl = + (enum ENUM_COEX_CMD_CTRL)rCmdCoexHandler.u4SubCmd; + + switch (CoexCmdCtrl) { + case COEX_CMD_GET_INFO: + { + u4Ret = priv_driver_get_coex_info(prGlueInfo, + &rCmdCoexHandler, + apcArgv); + if (u4Ret) + return -1; + priv_coex_get_info(pcCommand, + i4TotalLen, + &u4Offset, + &rCmdCoexHandler); + break; + } + case COEX_CMD_GET_ISO_DETECT: + { + struct CMD_COEX_ISO_DETECT *prCmdCoexIsoDetect; + + i4SubArgNum = 3; + /* Safely dereference "argv[3]".*/ + if (i4Argc < i4SubArgNum) + break; + /* Isolation Detection Method */ + u4Ret = priv_driver_iso_detect(prGlueInfo, + &rCmdCoexHandler, + apcArgv); + if (u4Ret) + return -1; + + /* Get Isolation value */ + prCmdCoexIsoDetect = + (struct CMD_COEX_ISO_DETECT *)rCmdCoexHandler.aucBuffer; + + /* Set Return i4BytesWritten Value */ + u4Offset = snprintf(pcCommand, i4TotalLen, "%d", + (prCmdCoexIsoDetect->u4Isolation/2)); + DBGLOG(REQ, INFO, "Isolation: %d\n", + (prCmdCoexIsoDetect->u4Isolation/2)); + break; + } + /* Default Coex Cmd */ + default: + break; + } + + /* Set Return i4BytesWritten Value */ + i4BytesWritten = (int32_t)u4Offset; + } + return i4BytesWritten; +} + +static int priv_driver_get_sta_info(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + uint8_t aucMacAddr[MAC_ADDR_LEN]; + uint8_t ucWlanIndex; + uint8_t *pucMacAddr = NULL; + struct PARAM_HW_WLAN_INFO *prHwWlanInfo; + struct PARAM_GET_STA_STATISTICS rQueryStaStatistics; + int32_t rRssi; + uint16_t u2LinkSpeed; + uint32_t u4Per; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + kalMemZero(&rQueryStaStatistics, sizeof(rQueryStaStatistics)); + rQueryStaStatistics.ucReadClear = TRUE; + + /* DBGLOG(RSN, INFO, "MT6632 : priv_driver_get_sta_info\n"); */ + if (i4Argc >= 3) { + if (strnicmp(apcArgv[1], CMD_GET_STA_KEEP_CNT, + strlen(CMD_GET_STA_KEEP_CNT)) == 0) { + wlanHwAddrToBin(apcArgv[2], &aucMacAddr[0]); + rQueryStaStatistics.ucReadClear = FALSE; + } else if (strnicmp(apcArgv[2], CMD_GET_STA_KEEP_CNT, + strlen(CMD_GET_STA_KEEP_CNT)) == 0) { + wlanHwAddrToBin(apcArgv[1], &aucMacAddr[0]); + rQueryStaStatistics.ucReadClear = FALSE; + } + + if (!wlanGetWlanIdxByAddress(prGlueInfo->prAdapter, + &aucMacAddr[0], &ucWlanIndex)) + return i4BytesWritten; + } else { + /* Get AIS AP address for no argument */ + if (prGlueInfo->prAdapter->prAisBssInfo->prStaRecOfAP) + ucWlanIndex = prGlueInfo->prAdapter->prAisBssInfo + ->prStaRecOfAP->ucWlanIndex; + else if (!wlanGetWlanIdxByAddress(prGlueInfo->prAdapter, NULL, + &ucWlanIndex)) /* try get a peer */ + return i4BytesWritten; + + if (i4Argc == 2) { + if (strnicmp(apcArgv[1], CMD_GET_STA_KEEP_CNT, + strlen(CMD_GET_STA_KEEP_CNT)) == 0) + rQueryStaStatistics.ucReadClear = FALSE; + } + } + + prHwWlanInfo = (struct PARAM_HW_WLAN_INFO *)kalMemAlloc( + sizeof(struct PARAM_HW_WLAN_INFO), VIR_MEM_TYPE); + prHwWlanInfo->u4Index = ucWlanIndex; + + DBGLOG(REQ, INFO, "MT6632 : index = %d i4TotalLen = %d\n", + prHwWlanInfo->u4Index, i4TotalLen); + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryWlanInfo, prHwWlanInfo, + sizeof(struct PARAM_HW_WLAN_INFO), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + kalMemFree(prHwWlanInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_HW_WLAN_INFO)); + return -1; + } + + i4BytesWritten = priv_driver_dump_helper_wtbl_info(pcCommand, + i4TotalLen, prHwWlanInfo); + + pucMacAddr = wlanGetStaAddrByWlanIdx(prGlueInfo->prAdapter, + ucWlanIndex); + if (pucMacAddr) { + COPY_MAC_ADDR(rQueryStaStatistics.aucMacAddr, pucMacAddr); + /* i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + * i4TotalLen - i4BytesWritten, + * "\tAddr="MACSTR"\n", + * MAC2STR(rQueryStaStatistics.aucMacAddr)); + */ + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryStaStatistics, + &rQueryStaStatistics, + sizeof(rQueryStaStatistics), + TRUE, FALSE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_SUCCESS) { + rRssi = RCPI_TO_dBm(rQueryStaStatistics.ucRcpi); + u2LinkSpeed = rQueryStaStatistics.u2LinkSpeed == 0 ? + 0 : rQueryStaStatistics.u2LinkSpeed/2; + + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "\n\nSTA Stat:\n"); + + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Tx total cnt = %d\n", + rQueryStaStatistics.u4TransmitCount); + + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Tx success = %d\n", + rQueryStaStatistics.u4TransmitCount - + rQueryStaStatistics.u4TransmitFailCount); + + u4Per = rQueryStaStatistics.u4TransmitCount == 0 ? 0 : + (1000 * + (rQueryStaStatistics.u4TransmitFailCount)) / + rQueryStaStatistics.u4TransmitCount; + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Tx fail count = %d, PER=%d.%1d%%\n", + rQueryStaStatistics.u4TransmitFailCount, + u4Per/10, u4Per%10); + + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "RSSI = %d\n", rRssi); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "LinkSpeed = %d\n", u2LinkSpeed); + } + } + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + + kalMemFree(prHwWlanInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_HW_WLAN_INFO)); + + return i4BytesWritten; +} + +static int priv_driver_get_mib_info(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + uint8_t i; + uint32_t u4Per; + int32_t u4Ret = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + struct PARAM_HW_MIB_INFO *prHwMibInfo; + struct RX_CTRL *prRxCtrl; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + prRxCtrl = &prGlueInfo->prAdapter->rRxCtrl; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + DBGLOG(REQ, INFO, "MT6632 : priv_driver_get_mib_info\n"); + + prHwMibInfo = (struct PARAM_HW_MIB_INFO *)kalMemAlloc( + sizeof(struct PARAM_HW_MIB_INFO), VIR_MEM_TYPE); + if (!prHwMibInfo) + return -1; + + if (i4Argc == 1) + prHwMibInfo->u4Index = 0; + + if (i4Argc >= 2) + u4Ret = kalkStrtou32(apcArgv[1], 0, &prHwMibInfo->u4Index); + + DBGLOG(REQ, INFO, "MT6632 : index = %d\n", prHwMibInfo->u4Index); + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryMibInfo, prHwMibInfo, + sizeof(struct PARAM_HW_MIB_INFO), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) { + kalMemFree(prHwMibInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_HW_MIB_INFO)); + return -1; + } + + if (prHwMibInfo->u4Index < 2) { + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, "%s", + "\n\nmib state:\n"); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Dump MIB info of IDX = %d\n", + prHwMibInfo->u4Index); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "===Rx Related Counters===\n"); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tRx with CRC=%d\n", + prHwMibInfo->rHwMibCnt.u4RxFcsErrCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx drop due to out of resource=%d\n", + prHwMibInfo->rHwMibCnt.u4RxFifoFullCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tRx Mpdu=%d\n", + prHwMibInfo->rHwMibCnt.u4RxMpduCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tRx AMpdu=%d\n", + prHwMibInfo->rHwMibCnt.u4RxAMPDUCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tRx PF Drop=%d\n", + prHwMibInfo->rHwMibCnt.u4PFDropCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx Len Mismatch=%d\n", + prHwMibInfo->rHwMibCnt.u4RxLenMismatchCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx data indicate total=%ld\n", + RX_GET_CNT(prRxCtrl, RX_DATA_INDICATION_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx data retain total=%ld\n", + RX_GET_CNT(prRxCtrl, RX_DATA_RETAINED_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx drop by SW total=%ld\n", + RX_GET_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tRx reorder miss=%ld\n", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_MISS_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx reorder within=%ld\n", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_WITHIN_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tRx reorder ahead=%ld\n", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_AHEAD_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx reorder behind=%ld\n", RX_GET_CNT(prRxCtrl, + RX_DATA_REORDER_BEHIND_COUNT)); + + do { + uint32_t u4AmsduCntx100 = 0; + + if (RX_GET_CNT(prRxCtrl, RX_DATA_AMSDU_COUNT)) + u4AmsduCntx100 = + (uint32_t)div64_u64(RX_GET_CNT(prRxCtrl, + RX_DATA_MSDU_IN_AMSDU_COUNT) * 100, + RX_GET_CNT(prRxCtrl, + RX_DATA_AMSDU_COUNT)); + + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx avg MSDU in AMSDU=%1d.%02d\n", + u4AmsduCntx100 / 100, u4AmsduCntx100 % 100); + } while (FALSE); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx total MSDU in AMSDU=%ld\n", RX_GET_CNT(prRxCtrl, + RX_DATA_MSDU_IN_AMSDU_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx AMSDU=%ld\n", RX_GET_CNT(prRxCtrl, + RX_DATA_AMSDU_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tRx AMSDU miss=%ld\n", + RX_GET_CNT(prRxCtrl, RX_DATA_AMSDU_MISS_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx no StaRec drop=%ld\n", + RX_GET_CNT(prRxCtrl, RX_NO_STA_DROP_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx inactive BSS drop=%ld\n", + RX_GET_CNT(prRxCtrl, RX_INACTIVE_BSS_DROP_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx HS20 drop=%ld\n", + RX_GET_CNT(prRxCtrl, RX_HS20_DROP_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx low SwRfb drop=%ld\n", RX_GET_CNT(prRxCtrl, + RX_LESS_SW_RFB_DROP_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tRx dupicate drop=%ld\n", + RX_GET_CNT(prRxCtrl, RX_DUPICATE_DROP_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tRx MIC err drop=%ld\n", + RX_GET_CNT(prRxCtrl, RX_MIC_ERROR_DROP_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tRx BAR handle=%ld\n", + RX_GET_CNT(prRxCtrl, RX_BAR_DROP_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx non-interest drop=%ld\n", RX_GET_CNT(prRxCtrl, + RX_NO_INTEREST_DROP_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tRx type err drop=%ld\n", + RX_GET_CNT(prRxCtrl, RX_TYPE_ERR_DROP_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRx class err drop=%ld\n", RX_GET_CNT(prRxCtrl, + RX_CLASS_ERR_DROP_COUNT)); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "===Phy/Timing Related Counters===\n"); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tChannelIdleCnt=%d\n", + prHwMibInfo->rHwMibCnt.u4ChannelIdleCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tCCA_NAV_Tx_Time=%d\n", + prHwMibInfo->rHwMibCnt.u4CcaNavTx); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tRx_MDRDY_CNT=%d\n", + prHwMibInfo->rHwMibCnt.u4MdrdyCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tCCK_MDRDY=%d, OFDM_MDRDY=0x%x, OFDM_GREEN_MDRDY=0x%x\n", + prHwMibInfo->rHwMibCnt.u4CCKMdrdyCnt, + prHwMibInfo->rHwMibCnt.u4OFDMLGMixMdrdy, + prHwMibInfo->rHwMibCnt.u4OFDMGreenMdrdy); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tPrim CCA Time=%d\n", + prHwMibInfo->rHwMibCnt.u4PCcaTime); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tSec CCA Time=%d\n", + prHwMibInfo->rHwMibCnt.u4SCcaTime); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tPrim ED Time=%d\n", + prHwMibInfo->rHwMibCnt.u4PEDTime); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s", + "===Tx Related Counters(Generic)===\n"); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tBeaconTxCnt=%d\n", + prHwMibInfo->rHwMibCnt.u4BeaconTxCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tTx 40MHz Cnt=%d\n", + prHwMibInfo->rHwMib2Cnt.u4Tx40MHzCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tTx 80MHz Cnt=%d\n", + prHwMibInfo->rHwMib2Cnt.u4Tx80MHzCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tTx 160MHz Cnt=%d\n", + prHwMibInfo->rHwMib2Cnt.u4Tx160MHzCnt); + for (i = 0; i < BSSID_NUM; i++) { + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\t===BSSID[%d] Related Counters===\n", i); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tBA Miss Cnt=%d\n", + prHwMibInfo->rHwMibCnt.au4BaMissedCnt[i]); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRTS Tx Cnt=%d\n", + prHwMibInfo->rHwMibCnt.au4RtsTxCnt[i]); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tFrame Retry Cnt=%d\n", + prHwMibInfo->rHwMibCnt.au4FrameRetryCnt[i]); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tFrame Retry 2 Cnt=%d\n", + prHwMibInfo->rHwMibCnt.au4FrameRetry2Cnt[i]); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tRTS Retry Cnt=%d\n", + prHwMibInfo->rHwMibCnt.au4RtsRetryCnt[i]); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tAck Failed Cnt=%d\n", + prHwMibInfo->rHwMibCnt.au4AckFailedCnt[i]); + } + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "===AMPDU Related Counters===\n"); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tTx AMPDU_Pkt_Cnt=%d\n", + prHwMibInfo->rHwTxAmpduMts.u2TxAmpduCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tTx AMPDU_MPDU_Pkt_Cnt=%d\n", + prHwMibInfo->rHwTxAmpduMts.u4TxSfCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\tAMPDU SuccessCnt=%d\n", + prHwMibInfo->rHwTxAmpduMts.u4TxAckSfCnt); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tAMPDU Tx success = %d\n", + prHwMibInfo->rHwTxAmpduMts.u4TxAckSfCnt); + + u4Per = prHwMibInfo->rHwTxAmpduMts.u4TxSfCnt == 0 ? 0 : + (1000 * (prHwMibInfo->rHwTxAmpduMts.u4TxSfCnt - + prHwMibInfo->rHwTxAmpduMts.u4TxAckSfCnt)) / + prHwMibInfo->rHwTxAmpduMts.u4TxSfCnt; + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tAMPDU Tx fail count = %d, PER=%d.%1d%%\n", + prHwMibInfo->rHwTxAmpduMts.u4TxSfCnt - + prHwMibInfo->rHwTxAmpduMts.u4TxAckSfCnt, + u4Per/10, u4Per%10); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s", "\tTx Agg\n"); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s", + "\tRange: 1 2~5 6~15 16~22 23~33 34~49 50~57 58~64\n" + ); + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\t\t%d \t%d \t%d \t%d \t%d \t%d \t%d \t%d\n", + prHwMibInfo->rHwTxAmpduMts.u2TxRange1AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange2AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange3AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange4AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange5AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange6AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange7AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange8AmpduCnt); + } else + i4BytesWritten = kalSnprintf(pcCommand, i4TotalLen, "%s", + "\nClear All Statistics\n"); + + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + + kalMemFree(prHwMibInfo, VIR_MEM_TYPE, sizeof(struct PARAM_HW_MIB_INFO)); + + nicRxClearStatistics(prGlueInfo->prAdapter); + + return i4BytesWritten; +} + +static int priv_driver_set_fw_log(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + uint32_t u4McuDest = 0; + uint32_t u4LogType = 0; + struct CMD_FW_LOG_2_HOST_CTRL *prFwLog2HostCtrl; + uint32_t u4Ret = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RSN, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + DBGLOG(RSN, INFO, "MT6632 : priv_driver_set_fw_log\n"); + + prFwLog2HostCtrl = (struct CMD_FW_LOG_2_HOST_CTRL *)kalMemAlloc( + sizeof(struct CMD_FW_LOG_2_HOST_CTRL), VIR_MEM_TYPE); + if (!prFwLog2HostCtrl) + return -1; + + if (i4Argc == 3) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4McuDest); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse u4McuDest error u4Ret=%d\n", + u4Ret); + + u4Ret = kalkStrtou32(apcArgv[2], 0, &u4LogType); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse u4LogType error u4Ret=%d\n", + u4Ret); + + prFwLog2HostCtrl->ucMcuDest = (uint8_t)u4McuDest; + prFwLog2HostCtrl->ucFwLog2HostCtrl = (uint8_t)u4LogType; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetFwLog2Host, + prFwLog2HostCtrl, + sizeof(struct CMD_FW_LOG_2_HOST_CTRL), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, INFO, "%s: command result is %s (%d %d)\n", + __func__, pcCommand, u4McuDest, u4LogType); + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + + if (rStatus != WLAN_STATUS_SUCCESS) { + kalMemFree(prFwLog2HostCtrl, VIR_MEM_TYPE, + sizeof(struct CMD_FW_LOG_2_HOST_CTRL)); + return -1; + } + } else { + DBGLOG(REQ, ERROR, "argc %i is not equal to 3\n", i4Argc); + i4BytesWritten = -1; + } + + kalMemFree(prFwLog2HostCtrl, VIR_MEM_TYPE, + sizeof(struct CMD_FW_LOG_2_HOST_CTRL)); + return i4BytesWritten; +} +#endif + +static int priv_driver_get_mcr(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + uint32_t u4Ret; + int32_t i4ArgNum = 2; + struct CMD_ACCESS_REG rCmdAccessReg; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rCmdAccessReg.u4Address)); + if (u4Ret) + DBGLOG(REQ, LOUD, + "parse get_mcr error (Address) u4Ret=%d\n", + u4Ret); + + /* rCmdAccessReg.u4Address = kalStrtoul(apcArgv[1], NULL, 0); */ + rCmdAccessReg.u4Data = 0; + + DBGLOG(REQ, LOUD, "address is %x\n", rCmdAccessReg.u4Address); + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryMcrRead, + &rCmdAccessReg, sizeof(rCmdAccessReg), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "0x%08x", + (unsigned int)rCmdAccessReg.u4Data); + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, + pcCommand); + } + + return i4BytesWritten; + +} /* priv_driver_get_mcr */ + +int priv_driver_set_mcr(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Ret; + int32_t i4ArgNum = 3; + struct CMD_ACCESS_REG rCmdAccessReg; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rCmdAccessReg.u4Address)); + if (u4Ret) + DBGLOG(REQ, LOUD, + "parse get_mcr error (Address) u4Ret=%d\n", + u4Ret); + + u4Ret = kalkStrtou32(apcArgv[2], 0, &(rCmdAccessReg.u4Data)); + if (u4Ret) + DBGLOG(REQ, LOUD, + "parse get_mcr error (Data) u4Ret=%d\n", u4Ret); + + /* rCmdAccessReg.u4Address = kalStrtoul(apcArgv[1], NULL, 0); */ + /* rCmdAccessReg.u4Data = kalStrtoul(apcArgv[2], NULL, 0); */ + + rStatus = kalIoctl(prGlueInfo, wlanoidSetMcrWrite, + &rCmdAccessReg, sizeof(rCmdAccessReg), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + } + + return i4BytesWritten; + +} + +static int priv_driver_set_test_mode(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + uint32_t u4Ret; + int32_t i4ArgNum = 2, u4MagicKey; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &(u4MagicKey)); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse Magic Key error u4Ret=%d\n", + u4Ret); + + DBGLOG(REQ, LOUD, "The Set Test Mode Magic Key is %d\n", + u4MagicKey); + + if (u4MagicKey == PRIV_CMD_TEST_MAGIC_KEY) { + rStatus = kalIoctl(prGlueInfo, + wlanoidRftestSetTestMode, + NULL, 0, FALSE, FALSE, TRUE, + &u4BufLen); + } else if (u4MagicKey == 0) { + rStatus = kalIoctl(prGlueInfo, + wlanoidRftestSetAbortTestMode, + NULL, 0, FALSE, FALSE, TRUE, + &u4BufLen); + } + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } + + return i4BytesWritten; + +} /* priv_driver_set_test_mode */ + +static int priv_driver_set_test_cmd(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + uint32_t u4Ret; + int32_t i4ArgNum = 3; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rRfATInfo.u4FuncIndex)); + if (u4Ret) + DBGLOG(REQ, LOUD, + "Parse Test CMD Index error u4Ret=%d\n", u4Ret); + + u4Ret = kalkStrtou32(apcArgv[2], 0, &(rRfATInfo.u4FuncData)); + if (u4Ret) + DBGLOG(REQ, LOUD, + "Parse Test CMD Data error u4Ret=%d\n", u4Ret); + + DBGLOG(REQ, LOUD, + "Set Test CMD FuncIndex = %d, FuncData = %d\n", + rRfATInfo.u4FuncIndex, rRfATInfo.u4FuncData); + + rStatus = kalIoctl(prGlueInfo, wlanoidRftestSetAutoTest, + &rRfATInfo, sizeof(rRfATInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } + + return i4BytesWritten; + +} /* priv_driver_set_test_cmd */ + +static int priv_driver_get_test_result(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + uint32_t u4Ret; + uint32_t u4Data = 0; + int32_t i4ArgNum = 3; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rRfATInfo.u4FuncIndex)); + if (u4Ret) + DBGLOG(REQ, LOUD, + "Parse Test CMD Index error u4Ret=%d\n", u4Ret); + + u4Ret = kalkStrtou32(apcArgv[2], 0, &(rRfATInfo.u4FuncData)); + if (u4Ret) + DBGLOG(REQ, LOUD, + "Parse Test CMD Data error u4Ret=%d\n", + u4Ret); + + DBGLOG(REQ, LOUD, + "Get Test CMD FuncIndex = %d, FuncData = %d\n", + rRfATInfo.u4FuncIndex, rRfATInfo.u4FuncData); + + rStatus = kalIoctl(prGlueInfo, wlanoidRftestQueryAutoTest, + &rRfATInfo, sizeof(rRfATInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + u4Data = (unsigned int)rRfATInfo.u4FuncData; + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%d[0x%08x]", + u4Data, u4Data); + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, + pcCommand); + } + + return i4BytesWritten; + +} /* priv_driver_get_test_result */ + +int32_t priv_driver_tx_rate_info(IN char *pcCommand, IN int i4TotalLen, + u_int8_t fgDumpAll, + struct PARAM_HW_WLAN_INFO *prHwWlanInfo, + struct PARAM_GET_STA_STATISTICS *prQueryStaStatistics) +{ + uint8_t i, txmode, rate, stbc; + uint8_t nsts; + int32_t i4BytesWritten = 0; + + for (i = 0; i < AUTO_RATE_NUM; i++) { + txmode = HW_TX_RATE_TO_MODE( + prHwWlanInfo->rWtblRateInfo.au2RateCode[i]); + if (txmode >= MAX_TX_MODE) + txmode = MAX_TX_MODE; + rate = HW_TX_RATE_TO_MCS( + prHwWlanInfo->rWtblRateInfo.au2RateCode[i], txmode); + nsts = HW_TX_RATE_TO_NSS( + prHwWlanInfo->rWtblRateInfo.au2RateCode[i]) + 1; + stbc = HW_TX_RATE_TO_STBC( + prHwWlanInfo->rWtblRateInfo.au2RateCode[i]); + + if (fgDumpAll) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Rate index - %d ", i); + + if (prHwWlanInfo->rWtblRateInfo.ucRateIdx == i) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "--> "); + } else { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", " "); + } + } + + if (!fgDumpAll) { + if (prHwWlanInfo->rWtblRateInfo.ucRateIdx != i) + continue; + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s", "Auto TX Rate", " = "); + } + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", HW_TX_RATE_CCK_STR[rate & 0x3]); + else if (txmode == TX_RATE_MODE_OFDM) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", hw_rate_ofdm_str(rate)); + else if ((txmode == TX_RATE_MODE_HTMIX) || + (txmode == TX_RATE_MODE_HTGF)) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "MCS%d, ", rate); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "NSS%d_MCS%d, ", nsts, rate); + + if (prQueryStaStatistics->ucSkipAr) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability + < 4 ? HW_TX_RATE_BW[ + prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability] + : HW_TX_RATE_BW[4]); + } else { + if ((txmode == TX_RATE_MODE_CCK) || + (txmode == TX_RATE_MODE_OFDM)) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", HW_TX_RATE_BW[0]); + else + if (i > prHwWlanInfo->rWtblPeerCap + .ucChangeBWAfterRateN) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + prHwWlanInfo->rWtblPeerCap. + ucFrequencyCapability < 4 ? + (prHwWlanInfo->rWtblPeerCap. + ucFrequencyCapability > BW_20 ? + HW_TX_RATE_BW[prHwWlanInfo-> + rWtblPeerCap + .ucFrequencyCapability - 1] : + HW_TX_RATE_BW[prHwWlanInfo->rWtblPeerCap + .ucFrequencyCapability]) : + HW_TX_RATE_BW[4]); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", + prHwWlanInfo->rWtblPeerCap. + ucFrequencyCapability < 4 ? + HW_TX_RATE_BW[ + prHwWlanInfo->rWtblPeerCap + .ucFrequencyCapability] : + HW_TX_RATE_BW[4]); + } + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", rate < 4 ? "LP" : "SP"); + else if (txmode == TX_RATE_MODE_OFDM) + ; + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", + priv_driver_get_sgi_info( + &prHwWlanInfo->rWtblPeerCap) == 0 ? + "LGI" : "SGI"); + + if (prQueryStaStatistics->ucSkipAr) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s%s%s\n", + txmode < 5 ? + HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5], + stbc ? ", STBC, " : ", ", + priv_driver_get_ldpc_info( + &prHwWlanInfo->rWtblTxConfig) == 0 ? + "BCC" : "LDPC"); + } else { +#if (CFG_SUPPORT_RA_GEN == 0) + if (prQueryStaStatistics->aucArRatePer[ + prQueryStaStatistics->aucRateEntryIndex[i]] == 0xFF) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s%s%s (--)\n", + txmode < 5 ? + HW_TX_MODE_STR[txmode] : + HW_TX_MODE_STR[5], + stbc ? ", STBC, " : ", ", + ((priv_driver_get_ldpc_info( + &prHwWlanInfo->rWtblTxConfig) == 0) + || (txmode == TX_RATE_MODE_CCK) + || (txmode == TX_RATE_MODE_OFDM)) ? + "BCC" : "LDPC"); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s%s%s (%d)\n", + txmode < 5 ? + HW_TX_MODE_STR[txmode] : + HW_TX_MODE_STR[5], + stbc ? ", STBC, " : ", ", + ((priv_driver_get_ldpc_info( + &prHwWlanInfo->rWtblTxConfig) == 0) + || (txmode == TX_RATE_MODE_CCK) + || (txmode == TX_RATE_MODE_OFDM)) + ? "BCC" : "LDPC", + prQueryStaStatistics->aucArRatePer[ + prQueryStaStatistics + ->aucRateEntryIndex[i]]); +#else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s%s%s\n", + txmode < 5 ? + HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5], + stbc ? ", STBC, " : ", ", + ((priv_driver_get_ldpc_info( + &prHwWlanInfo->rWtblTxConfig) == 0) || + (txmode == TX_RATE_MODE_CCK) || + (txmode == TX_RATE_MODE_OFDM)) ? + "BCC" : "LDPC"); +#endif + } + + if (!fgDumpAll) + break; + } + + return i4BytesWritten; +} + +int32_t priv_driver_last_rx_rssi(struct ADAPTER *prAdapter, IN char *pcCommand, + IN int i4TotalLen, IN uint8_t ucWlanIdx) +{ + int32_t i4RSSI0 = 0, i4RSSI1 = 0, i4RSSI2 = 0, i4RSSI3 = 0; + int32_t i4BytesWritten = 0; + uint32_t u4RxVector3 = 0; + uint8_t ucStaIdx; + + if (wlanGetStaIdxByWlanIdx(prAdapter, ucWlanIdx, &ucStaIdx) == + WLAN_STATUS_SUCCESS) { + u4RxVector3 = prAdapter->arStaRec[ucStaIdx].u4RxVector3; + DBGLOG(REQ, LOUD, "****** RX Vector3 = 0x%08x ******\n", + u4RxVector3); + } else { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s", "Last RX RSSI", " = NOT SUPPORT"); + return i4BytesWritten; + } + + i4RSSI0 = RCPI_TO_dBm((u4RxVector3 & RX_VT_RCPI0_MASK) >> + RX_VT_RCPI0_OFFSET); + i4RSSI1 = RCPI_TO_dBm((u4RxVector3 & RX_VT_RCPI1_MASK) >> + RX_VT_RCPI1_OFFSET); + + if (prAdapter->rWifiVar.ucNSS > 2) { + i4RSSI2 = RCPI_TO_dBm((u4RxVector3 & RX_VT_RCPI2_MASK) >> + RX_VT_RCPI2_OFFSET); + i4RSSI3 = RCPI_TO_dBm((u4RxVector3 & RX_VT_RCPI3_MASK) >> + RX_VT_RCPI3_OFFSET); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%-20s%s%d %d %d %d\n", + "Last RX Data RSSI", " = ", + i4RSSI0, i4RSSI1, i4RSSI2, i4RSSI3); + } else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%-20s%s%d %d\n", + "Last RX Data RSSI", " = ", i4RSSI0, i4RSSI1); + + return i4BytesWritten; +} + +#if CFG_SUPPORT_ADVANCE_CONTROL +static int32_t priv_driver_get_snr(IN struct GLUE_INFO *prGlueInfo, + IN char *pcCommand, IN int i4TotalLen) +{ + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + int32_t i4BytesWritten = 0; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int8_t iSnrR0Phase1 = 0, iSnrR1Phase1 = 0; + int8_t iSnrR0Phase2 = 0, iSnrR1Phase2 = 0; + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + CMD_ADVCTL_SNR_ID; + + rStatus = kalIoctl(prGlueInfo, wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + TRUE, TRUE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(HAL, ERROR, "CMD_ADVCTL_SNR_ID rStatus %u\n", rStatus); + return -1; + } + + iSnrR1Phase2 = rSwCtrlInfo.u4Data & 0xFF; + iSnrR0Phase2 = (rSwCtrlInfo.u4Data >> 8) & 0xFF; + iSnrR1Phase1 = (rSwCtrlInfo.u4Data >> 16) & 0xFF; + iSnrR0Phase1 = (rSwCtrlInfo.u4Data >> 24) & 0xFF; + + i4BytesWritten += + kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s %-d %-d\n", "SNR", " = ", + iSnrR0Phase2, iSnrR1Phase2); + + DBGLOG(HAL, INFO, "SNR: R0P1:0x%02x R1P1:0x%02x\n", + iSnrR0Phase1, iSnrR1Phase1); + + DBGLOG(HAL, INFO, "SNR: R0P2:0x%02x R1P2:0x%02x u4Data:0x%08x\n", + iSnrR0Phase2, iSnrR1Phase2, rSwCtrlInfo.u4Data); + + return i4BytesWritten; +} +#endif + +int32_t priv_driver_rx_rate_info(struct ADAPTER *prAdapter, IN char *pcCommand, + IN int i4TotalLen, IN uint8_t ucWlanIdx) +{ + uint32_t txmode, rate, frmode, sgi, nsts, ldpc, stbc, groupid, mu; + int32_t i4BytesWritten = 0; + uint32_t u4RxVector0 = 0, u4RxVector1 = 0; + uint8_t ucStaIdx; + + if (wlanGetStaIdxByWlanIdx(prAdapter, ucWlanIdx, &ucStaIdx) == + WLAN_STATUS_SUCCESS) { + u4RxVector0 = prAdapter->arStaRec[ucStaIdx].u4RxVector0; + u4RxVector1 = prAdapter->arStaRec[ucStaIdx].u4RxVector1; + DBGLOG(REQ, LOUD, "****** RX Vector0 = 0x%08x ******\n", + u4RxVector0); + DBGLOG(REQ, LOUD, "****** RX Vector1 = 0x%08x ******\n", + u4RxVector1); + } else { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s", "Last RX Rate", " = NOT SUPPORT"); + return i4BytesWritten; + } + + txmode = (u4RxVector0 & RX_VT_RX_MODE_MASK) >> RX_VT_RX_MODE_OFFSET; + rate = (u4RxVector0 & RX_VT_RX_RATE_MASK) >> RX_VT_RX_RATE_OFFSET; + frmode = (u4RxVector0 & RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET; + nsts = ((u4RxVector1 & RX_VT_NSTS_MASK) >> RX_VT_NSTS_OFFSET); + stbc = (u4RxVector0 & RX_VT_STBC_MASK) >> RX_VT_STBC_OFFSET; + sgi = u4RxVector0 & RX_VT_SHORT_GI; + ldpc = u4RxVector0 & RX_VT_LDPC; + groupid = (u4RxVector1 & RX_VT_GROUP_ID_MASK) >> RX_VT_GROUP_ID_OFFSET; + + if (groupid && groupid != 63) { + mu = 1; + } else { + mu = 0; + nsts += 1; + } + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%-20s%s", "Last RX Rate", " = "); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + rate < 4 ? HW_TX_RATE_CCK_STR[rate] : + HW_TX_RATE_CCK_STR[4]); + else if (txmode == TX_RATE_MODE_OFDM) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + hw_rate_ofdm_str(rate)); + else if ((txmode == TX_RATE_MODE_HTMIX) || + (txmode == TX_RATE_MODE_HTGF)) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "MCS%d, ", rate); + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "NSS%d_MCS%d, ", + nsts, rate); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + frmode < 4 ? HW_TX_RATE_BW[frmode] : HW_TX_RATE_BW[4]); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + rate < 4 ? "LP" : "SP"); + else if (txmode == TX_RATE_MODE_OFDM) + ; + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + sgi == 0 ? "LGI" : "SGI"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s", stbc == 0 ? "" : "STBC, "); + + if (mu) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, %s, %s (%d)\n", + txmode < 5 ? HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5], + ldpc == 0 ? "BCC" : "LDPC", "MU", groupid); + } else { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, %s\n", + txmode < 5 ? HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5], + ldpc == 0 ? "BCC" : "LDPC"); + } + + return i4BytesWritten; +} + +int32_t priv_driver_tx_vector_info(IN char *pcCommand, IN int i4TotalLen, + IN struct TX_VECTOR_BBP_LATCH *prTxV) +{ + uint8_t rate, txmode, frmode, sgi, ldpc, nsts, stbc; + int8_t txpwr; + int32_t i4BytesWritten = 0; + + rate = TX_VECTOR_GET_TX_RATE(prTxV); + txmode = TX_VECTOR_GET_TX_MODE(prTxV); + frmode = TX_VECTOR_GET_TX_FRMODE(prTxV); + nsts = TX_VECTOR_GET_TX_NSTS(prTxV) + 1; + sgi = TX_VECTOR_GET_TX_SGI(prTxV); + ldpc = TX_VECTOR_GET_TX_LDPC(prTxV); + stbc = TX_VECTOR_GET_TX_STBC(prTxV); + txpwr = TX_VECTOR_GET_TX_PWR(prTxV); + + if (prTxV->u4TxVector1 == 0xFFFFFFFF) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Last TX Rate", " = ", "N/A"); + } else { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s", "Last TX Rate", " = "); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", rate < 4 ? HW_TX_RATE_CCK_STR[rate] : + HW_TX_RATE_CCK_STR[4]); + else if (txmode == TX_RATE_MODE_OFDM) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", hw_rate_ofdm_str(rate)); + else if ((txmode == TX_RATE_MODE_HTMIX) || + (txmode == TX_RATE_MODE_HTGF)) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "MCS%d, ", rate); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "NSS%d_MCS%d, ", nsts, rate); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + frmode < 4 ? HW_TX_RATE_BW[frmode] : HW_TX_RATE_BW[4]); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", rate < 4 ? "LP" : "SP"); + else if (txmode == TX_RATE_MODE_OFDM) + ; + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", sgi == 0 ? "LGI" : "SGI"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s%s%s\n", + txmode < 5 ? HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5], + stbc ? ", STBC, " : ", ", ldpc == 0 ? "BCC" : "LDPC"); + } + + return i4BytesWritten; +} + +uint16_t priv_driver_get_idx_info(IN struct ADAPTER *prAdapter, + IN uint8_t ucWlanIdx) +{ + static uint8_t aucWlanIdxArray[CFG_STAT_DBG_PEER_NUM] = {0}; + static uint16_t u2ValidBitMask; /* support max 16 peers */ + uint8_t ucIdx, ucStaIdx, ucCnt = 0; + uint8_t ucWlanIdxExist; + + /* check every wlanIdx and unmask no longer used wlanIdx */ + for (ucIdx = 0; ucIdx < CFG_STAT_DBG_PEER_NUM; ucIdx++) { + if (u2ValidBitMask & BIT(ucIdx)) { + ucWlanIdxExist = aucWlanIdxArray[ucIdx]; + + if (wlanGetStaIdxByWlanIdx(prAdapter, ucWlanIdxExist, + &ucStaIdx) != WLAN_STATUS_SUCCESS) + u2ValidBitMask &= ~BIT(ucIdx); + } + } + + /* Search matched WlanIdx */ + for (ucIdx = 0; ucIdx < CFG_STAT_DBG_PEER_NUM; ucIdx++) { + if (u2ValidBitMask & BIT(ucIdx)) { + ucCnt++; + ucWlanIdxExist = aucWlanIdxArray[ucIdx]; + + if (ucWlanIdxExist == ucWlanIdx) { + DBGLOG(REQ, INFO, + "=== Matched, Mask=0x%x, ucIdx=%d ===\n", + u2ValidBitMask, ucIdx); + return ucIdx; + } + } + } + + /* No matched WlanIdx, add new one */ + if (ucCnt < CFG_STAT_DBG_PEER_NUM) { + for (ucIdx = 0; ucIdx < CFG_STAT_DBG_PEER_NUM; ucIdx++) { + if (~u2ValidBitMask & BIT(ucIdx)) { + u2ValidBitMask |= BIT(ucIdx); + aucWlanIdxArray[ucIdx] = ucWlanIdx; + DBGLOG(REQ, INFO, + "=== New Add, Mask=0x%x, ucIdx=%d ===\n", + u2ValidBitMask, ucIdx); + return ucIdx; + } + } + } + + return 0xFFFF; +} + +#if (CFG_SUPPORT_RA_GEN == 0) +static int32_t priv_driver_dump_stat_info(struct ADAPTER *prAdapter, + IN char *pcCommand, IN int i4TotalLen, + struct PARAM_HW_WLAN_INFO *prHwWlanInfo, + struct PARAM_GET_STA_STATISTICS *prQueryStaStatistics, + u_int8_t fgResetCnt, uint32_t u4StatGroup) +{ + int32_t i4BytesWritten = 0; + int32_t rRssi; + uint16_t u2LinkSpeed; + uint32_t u4Per, u4RxPer[ENUM_BAND_NUM], u4AmpduPer[ENUM_BAND_NUM], + u4InstantPer; + uint8_t ucDbdcIdx, ucStaIdx, ucNss; + uint8_t ucSkipAr; + static uint32_t u4TotalTxCnt, u4TotalFailCnt; + static uint32_t u4Rate1TxCnt, u4Rate1FailCnt; + static uint32_t au4RxMpduCnt[ENUM_BAND_NUM] = {0}; + static uint32_t au4FcsError[ENUM_BAND_NUM] = {0}; + static uint32_t au4RxFifoCnt[ENUM_BAND_NUM] = {0}; + static uint32_t au4AmpduTxSfCnt[ENUM_BAND_NUM] = {0}; + static uint32_t au4AmpduTxAckSfCnt[ENUM_BAND_NUM] = {0}; + struct RX_CTRL *prRxCtrl; + uint32_t u4InstantRxPer[ENUM_BAND_NUM]; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + int16_t i2Wf0AvgPwr; + int16_t i2Wf1AvgPwr; + uint32_t u4BufLen = 0; + + ucSkipAr = prQueryStaStatistics->ucSkipAr; + prRxCtrl = &prAdapter->rRxCtrl; + ucNss = prAdapter->rWifiVar.ucNSS; + + if (ucSkipAr) { + u4TotalTxCnt += prHwWlanInfo->rWtblTxCounter.u2CurBwTxCnt + + prHwWlanInfo->rWtblTxCounter.u2OtherBwTxCnt; + u4TotalFailCnt += prHwWlanInfo->rWtblTxCounter.u2CurBwFailCnt + + prHwWlanInfo->rWtblTxCounter.u2OtherBwFailCnt; + u4Rate1TxCnt += prHwWlanInfo->rWtblTxCounter.u2Rate1TxCnt; + u4Rate1FailCnt += prHwWlanInfo->rWtblTxCounter.u2Rate1FailCnt; + } + + if (ucSkipAr) { + u4Per = (prHwWlanInfo->rWtblTxCounter.u2Rate1TxCnt == 0) ? + (0) : (1000 * u4Rate1FailCnt / u4Rate1TxCnt); + + u4InstantPer = + (prHwWlanInfo->rWtblTxCounter.u2Rate1TxCnt == 0) ? (0) : + (1000 * (prHwWlanInfo->rWtblTxCounter.u2Rate1FailCnt) / + (prHwWlanInfo->rWtblTxCounter.u2Rate1TxCnt)); + } else { + u4Per = (prQueryStaStatistics->u4Rate1TxCnt == 0) ? + (0) : (1000 * (prQueryStaStatistics->u4Rate1FailCnt) / + (prQueryStaStatistics->u4Rate1TxCnt)); + + u4InstantPer = (prQueryStaStatistics->ucPer == 0) ? + (0) : (prQueryStaStatistics->ucPer); + } + + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; ucDbdcIdx++) { + au4RxMpduCnt[ucDbdcIdx] += + prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4RxMpduCnt; + au4FcsError[ucDbdcIdx] += + prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4FcsError; + au4RxFifoCnt[ucDbdcIdx] += + prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4RxFifoFull; + au4AmpduTxSfCnt[ucDbdcIdx] += + prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4AmpduTxSfCnt; + au4AmpduTxAckSfCnt[ucDbdcIdx] += + prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4AmpduTxAckSfCnt; + + u4RxPer[ucDbdcIdx] = ((au4RxMpduCnt[ucDbdcIdx] + + au4FcsError[ucDbdcIdx]) == 0) ? (0) : + (1000 * au4FcsError[ucDbdcIdx] / + (au4RxMpduCnt[ucDbdcIdx] + au4FcsError[ucDbdcIdx])); + + u4AmpduPer[ucDbdcIdx] = + (au4AmpduTxSfCnt[ucDbdcIdx] == 0) ? (0) : + (1000 * (au4AmpduTxSfCnt[ucDbdcIdx] - + au4AmpduTxAckSfCnt[ucDbdcIdx]) / + au4AmpduTxSfCnt[ucDbdcIdx]); + + u4InstantRxPer[ucDbdcIdx] = + ((prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4RxMpduCnt + + prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4FcsError) == 0) + ? (0) : + (1000 * prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4FcsError + / (prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4RxMpduCnt + + prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4FcsError)); + } + + /* get Beacon RSSI */ + rStatus = kalIoctl(prAdapter->prGlueInfo, wlanoidQueryRssi, &rRssi, + sizeof(rRssi), TRUE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "unable to retrieve rssi\n"); + + u2LinkSpeed = (prQueryStaStatistics->u2LinkSpeed == 0) ? + 0 : prQueryStaStatistics->u2LinkSpeed / 2; + + /* =========== Group 0x0001 =========== */ + if (u4StatGroup & 0x0001) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "\n----- STA Stat (Group 0x01) -----\n"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CurrTemperature", " = ", + prQueryStaStatistics->ucTemperature); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Tx Total cnt", " = ", + ucSkipAr ? (u4TotalTxCnt) : + (prQueryStaStatistics->u4TransmitCount)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Tx Fail Cnt", " = ", + ucSkipAr ? (u4TotalFailCnt) : + (prQueryStaStatistics->u4TransmitFailCount)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Rate1 Tx Cnt", " = ", + ucSkipAr ? (u4Rate1TxCnt) : + (prQueryStaStatistics->u4Rate1TxCnt)); + + if (ucSkipAr) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d, PER = %d.%1d%%, instant PER = %d.%1d%%\n", + "Rate1 Fail Cnt", " = ", + u4Rate1FailCnt, u4Per/10, u4Per%10, + u4InstantPer/10, u4InstantPer%10); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d, PER = %d.%1d%%, instant PER = %d%%\n", + "Rate1 Fail Cnt", " = ", + prQueryStaStatistics->u4Rate1FailCnt, + u4Per/10, u4Per%10, u4InstantPer); + + if ((ucSkipAr) && (fgResetCnt)) { + u4TotalTxCnt = 0; + u4TotalFailCnt = 0; + u4Rate1TxCnt = 0; + u4Rate1FailCnt = 0; + } + } + + /* =========== Group 0x0002 =========== */ + if (u4StatGroup & 0x0002) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "----- MIB Info (Group 0x02) -----\n"); + + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; ucDbdcIdx++) { + if (prAdapter->rWifiVar.fgDbDcModeEn) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "[DBDC_%d] :\n", ucDbdcIdx); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RX Success", " = ", + au4RxMpduCnt[ucDbdcIdx]); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d, PER = %d.%1d%%, instant PER = %d.%1d%%\n", + "RX with CRC", " = ", + au4FcsError[ucDbdcIdx], u4RxPer[ucDbdcIdx]/10, + u4RxPer[ucDbdcIdx] % 10, + u4InstantRxPer[ucDbdcIdx] / 10, + u4InstantRxPer[ucDbdcIdx]%10); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RX drop FIFO full", " = ", + au4RxFifoCnt[ucDbdcIdx]); + + if (!prAdapter->rWifiVar.fgDbDcModeEn) + break; + } + + if (fgResetCnt) { + kalMemZero(au4RxMpduCnt, sizeof(au4RxMpduCnt)); + kalMemZero(au4FcsError, sizeof(au4RxMpduCnt)); + kalMemZero(au4RxFifoCnt, sizeof(au4RxMpduCnt)); + kalMemZero(au4AmpduTxSfCnt, sizeof(au4RxMpduCnt)); + kalMemZero(au4AmpduTxAckSfCnt, sizeof(au4RxMpduCnt)); + } + } + + /* =========== Group 0x0004 =========== */ + if (u4StatGroup & 0x0004) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "----- Last Rx Info (Group 0x04) -----\n"); + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + 1; + + rStatus = kalIoctl(prAdapter->prGlueInfo, + wlanoidQuerySwCtrlRead, &rSwCtrlInfo, + sizeof(rSwCtrlInfo), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u, rSwCtrlInfo.u4Data 0x%x\n", + rStatus, rSwCtrlInfo.u4Data); + if (rStatus == WLAN_STATUS_SUCCESS) { + i2Wf0AvgPwr = rSwCtrlInfo.u4Data & 0xFFFF; + i2Wf1AvgPwr = (rSwCtrlInfo.u4Data >> 16) & 0xFFFF; + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d %d\n", "NOISE", " = ", + i2Wf0AvgPwr, i2Wf1AvgPwr); + } + + /* Last RX Rate */ + i4BytesWritten += priv_driver_rx_rate_info(prAdapter, + pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + (uint8_t)(prHwWlanInfo->u4Index)); + +#if CFG_SUPPORT_ADVANCE_CONTROL + /* Last RX SNR */ + i4BytesWritten += priv_driver_get_snr(prAdapter->prGlueInfo, + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten); +#endif + + /* Last RX RSSI */ + i4BytesWritten += priv_driver_last_rx_rssi(prAdapter, + pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + (uint8_t)(prHwWlanInfo->u4Index)); + + /* Last TX Resp RSSI */ + if (ucNss > 2) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d %d %d %d\n", "Tx Response RSSI", + " = ", + RCPI_TO_dBm(prHwWlanInfo-> + rWtblRxCounter.ucRxRcpi0), + RCPI_TO_dBm(prHwWlanInfo-> + rWtblRxCounter.ucRxRcpi1), + RCPI_TO_dBm(prHwWlanInfo-> + rWtblRxCounter.ucRxRcpi2), + RCPI_TO_dBm(prHwWlanInfo-> + rWtblRxCounter.ucRxRcpi3)); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d %d\n", "Tx Response RSSI", " = ", + RCPI_TO_dBm( + prHwWlanInfo->rWtblRxCounter.ucRxRcpi0), + RCPI_TO_dBm( + prHwWlanInfo->rWtblRxCounter.ucRxRcpi1)); + + /* Last Beacon RSSI */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Beacon RSSI", " = ", rRssi); + } + + /* =========== Group 0x0008 =========== */ + if (u4StatGroup & 0x0008) { + /* TxV */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "----- Last TX Info (Group 0x08) -----\n"); + + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; ucDbdcIdx++) { + int8_t txpwr; + + txpwr = TX_VECTOR_GET_TX_PWR( + &prQueryStaStatistics->rTxVector[ucDbdcIdx]); + + if (prAdapter->rWifiVar.fgDbDcModeEn) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "[DBDC_%d] :\n", ucDbdcIdx); + + i4BytesWritten += priv_driver_tx_vector_info( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + &prQueryStaStatistics->rTxVector[ucDbdcIdx]); + + if (prQueryStaStatistics-> + rTxVector[ucDbdcIdx].u4TxVector1 == 0xFFFFFFFF) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Chip Out TX Power", + " = ", "N/A"); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%c%d.%1d dBm\n", + "Chip Out TX Power", " = ", + (txpwr < 0) ? '-' : '+', + abs(txpwr / 2), + 5 * abs(txpwr % 2)); + + if (!prAdapter->rWifiVar.fgDbDcModeEn) + break; + } + } + + /* =========== Group 0x0010 =========== */ + if (u4StatGroup & 0x0010) { + /* RX Reorder */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "----- RX Reorder (Group 0x10) -----\n"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%ld\n", "Rx reorder miss", " = ", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_MISS_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%ld\n", "Rx reorder within", " = ", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_WITHIN_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%ld\n", "Rx reorder ahead", " = ", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_AHEAD_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%ld\n", "Rx reorder behind", " = ", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_BEHIND_COUNT)); +#if CFG_SUPPORT_RX_DYNAMIC_MCC_PRIORITY + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Rx reorder STA", " = ", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_WITHIN_COUNT_STA)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Rx reorder P2P", " = ", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_WITHIN_COUNT_P2P)); +#endif + } + + /* =========== Group 0x0020 =========== */ + if (u4StatGroup & 0x0020) { + /* AR info */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "----- AR Info (Group 0x20) -----\n"); + + /* Last TX Rate */ + i4BytesWritten += priv_driver_tx_rate_info( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, FALSE, + prHwWlanInfo, prQueryStaStatistics); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "LinkSpeed", " = ", u2LinkSpeed); + + if (!prQueryStaStatistics->ucSkipAr) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "RateTable", " = ", + prQueryStaStatistics->ucArTableIdx < 6 ? + RATE_TBLE[ + prQueryStaStatistics->ucArTableIdx] : + RATE_TBLE[6]); + + if (wlanGetStaIdxByWlanIdx(prAdapter, + (uint8_t)(prHwWlanInfo->u4Index), &ucStaIdx) == + WLAN_STATUS_SUCCESS){ + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "2G Support 256QAM TX", + " = ", + (prAdapter->arStaRec[ucStaIdx].u4Flags & + MTK_SYNERGY_CAP_SUPPORT_24G_MCS89) ? + 1 : 0); + } + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d%%\n", "Rate1 instantPer", " = ", + u4InstantPer); + + if (prQueryStaStatistics->ucAvePer == 0xFF) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Train Down", " = ", + "N/A"); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Train Up", " = ", + "N/A"); + } else { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d -> %hd\n", "Train Down", + " = ", + (uint16_t)((prQueryStaStatistics + ->u2TrainDown) & BITS(0, 7)), + (uint16_t)(((prQueryStaStatistics + ->u2TrainDown) >> 8) & BITS(0, 7))); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d -> %hd\n", "Train Up", " = ", + (uint16_t)((prQueryStaStatistics-> + u2TrainUp) & BITS(0, 7)), + (uint16_t)(((prQueryStaStatistics-> + u2TrainUp) >> 8) & BITS(0, 7))); + } + + if (prQueryStaStatistics->fgIsForceTxStream == 0) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Force Tx Stream", " = ", + "N/A"); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Force Tx Stream", " = ", + prQueryStaStatistics->fgIsForceTxStream); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Force SE off", " = ", + prQueryStaStatistics->fgIsForceSeOff); + } + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CBRN", " = ", + prHwWlanInfo->rWtblPeerCap.ucChangeBWAfterRateN); + + /* Rate1~Rate8 */ + i4BytesWritten += priv_driver_tx_rate_info( + pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + TRUE, prHwWlanInfo, prQueryStaStatistics); + } + + /* =========== Group 0x0040 =========== */ + if (u4StatGroup & 0x0040) { + /* Tx Agg */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "------ TX AGG (Group 0x40) -----\n"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-12s%s", "Range:", + "1 2~5 6~15 16~22 23~33 34~49 50~57 58~64\n"); + + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; ucDbdcIdx++) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "DBDC%d:", ucDbdcIdx); + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%7d%8d%9d%9d%9d%9d%9d%9d\n", + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].u2TxRange1AmpduCnt, + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].u2TxRange2AmpduCnt, + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].u2TxRange3AmpduCnt, + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].u2TxRange4AmpduCnt, + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].u2TxRange5AmpduCnt, + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].u2TxRange6AmpduCnt, + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].u2TxRange7AmpduCnt, + prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].u2TxRange8AmpduCnt); + + if (!prAdapter->rWifiVar.fgDbDcModeEn) + break; + } + } + + return i4BytesWritten; +} +#else +static int32_t priv_driver_dump_stat_info(struct ADAPTER *prAdapter, + IN char *pcCommand, IN int i4TotalLen, + struct PARAM_HW_WLAN_INFO *prHwWlanInfo, + struct PARAM_GET_STA_STATISTICS *prQueryStaStatistics, + u_int8_t fgResetCnt, uint32_t u4StatGroup) +{ + int32_t i4BytesWritten = 0; + int32_t rRssi; + uint16_t u2LinkSpeed; + uint32_t u4Per, u4RxPer[ENUM_BAND_NUM], u4AmpduPer[ENUM_BAND_NUM], + u4InstantPer; + uint8_t ucDbdcIdx, ucSkipAr, ucStaIdx, ucNss; + static uint32_t u4TotalTxCnt[CFG_STAT_DBG_PEER_NUM] = {0}; + static uint32_t u4TotalFailCnt[CFG_STAT_DBG_PEER_NUM] = {0}; + static uint32_t u4Rate1TxCnt[CFG_STAT_DBG_PEER_NUM] = {0}; + static uint32_t u4Rate1FailCnt[CFG_STAT_DBG_PEER_NUM] = {0}; + static uint32_t au4RxMpduCnt[ENUM_BAND_NUM] = {0}; + static uint32_t au4FcsError[ENUM_BAND_NUM] = {0}; + static uint32_t au4RxFifoCnt[ENUM_BAND_NUM] = {0}; + static uint32_t au4AmpduTxSfCnt[ENUM_BAND_NUM] = {0}; + static uint32_t au4AmpduTxAckSfCnt[ENUM_BAND_NUM] = {0}; + struct RX_CTRL *prRxCtrl; + uint32_t u4InstantRxPer[ENUM_BAND_NUM]; +#if CFG_SUPPORT_ADVANCE_CONTROL + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; +#endif + uint32_t rStatus = WLAN_STATUS_SUCCESS; + int16_t i2Wf0AvgPwr = 0, i2Wf1AvgPwr = 0; + uint32_t u4BufLen = 0; + uint8_t ucRaTableNum = sizeof(RATE_TBLE) / sizeof(char *); + uint8_t ucRaStatusNum = sizeof(RA_STATUS_TBLE) / sizeof(char *); +#if 0 + uint8_t ucRaLtModeNum = sizeof(LT_MODE_TBLE) / sizeof(char *); + uint8_t ucRaSgiUnSpStateNum = sizeof(SGI_UNSP_STATE_TBLE) / + sizeof(char *); + uint8_t ucRaBwStateNum = sizeof(BW_STATE_TBLE) / sizeof(char *); +#endif + uint8_t ucAggRange[AGG_RANGE_SEL_NUM] = {0}; + uint32_t u4RangeCtrl_0, u4RangeCtrl_1; + enum AGG_RANGE_TYPE_T eRangeType = ENUM_AGG_RANGE_TYPE_TX; + uint16_t u2Idx = 0; + uint8_t ucRcpi0 = 0, ucRcpi1 = 0, ucRcpi2 = 0, ucRcpi3 = 0; + + ucSkipAr = prQueryStaStatistics->ucSkipAr; + prRxCtrl = &prAdapter->rRxCtrl; + ucNss = prAdapter->rWifiVar.ucNSS; + + if (ucSkipAr) { + u2Idx = priv_driver_get_idx_info(prAdapter, + (uint8_t)(prHwWlanInfo->u4Index)); + + if (u2Idx == 0xFFFF) + return i4BytesWritten; + } + + if (ucSkipAr) { + u4TotalTxCnt[u2Idx] += prQueryStaStatistics->u4TransmitCount; + u4TotalFailCnt[u2Idx] += prQueryStaStatistics-> + u4TransmitFailCount; + u4Rate1TxCnt[u2Idx] += prQueryStaStatistics->u4Rate1TxCnt; + u4Rate1FailCnt[u2Idx] += prQueryStaStatistics->u4Rate1FailCnt; + } + + if (ucSkipAr) { + u4Per = (u4Rate1TxCnt[u2Idx] == 0) ? + (0) : (1000 * (u4Rate1FailCnt[u2Idx]) / + (u4Rate1TxCnt[u2Idx])); + + u4InstantPer = (prQueryStaStatistics->u4Rate1TxCnt == 0) ? + (0) : (1000 * (prQueryStaStatistics->u4Rate1FailCnt) / + (prQueryStaStatistics->u4Rate1TxCnt)); + } else { + u4Per = (prQueryStaStatistics->u4Rate1TxCnt == 0) ? + (0) : (1000 * (prQueryStaStatistics->u4Rate1FailCnt) / + (prQueryStaStatistics->u4Rate1TxCnt)); + + u4InstantPer = (prQueryStaStatistics->ucPer == 0) ? + (0) : (prQueryStaStatistics->ucPer); + } + + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; ucDbdcIdx++) { + au4RxMpduCnt[ucDbdcIdx] += g_arMibInfo[ucDbdcIdx].u4RxMpduCnt; + au4FcsError[ucDbdcIdx] += g_arMibInfo[ucDbdcIdx].u4FcsError; + au4RxFifoCnt[ucDbdcIdx] += g_arMibInfo[ucDbdcIdx].u4RxFifoFull; + au4AmpduTxSfCnt[ucDbdcIdx] += + g_arMibInfo[ucDbdcIdx].u4AmpduTxSfCnt; + au4AmpduTxAckSfCnt[ucDbdcIdx] += + g_arMibInfo[ucDbdcIdx].u4AmpduTxAckSfCnt; + + u4RxPer[ucDbdcIdx] = + ((au4RxMpduCnt[ucDbdcIdx] + au4FcsError[ucDbdcIdx]) == 0) ? + (0) : (1000 * au4FcsError[ucDbdcIdx] / + (au4RxMpduCnt[ucDbdcIdx] + + au4FcsError[ucDbdcIdx])); + + u4AmpduPer[ucDbdcIdx] = + (au4AmpduTxSfCnt[ucDbdcIdx] == 0) ? + (0) : (1000 * (au4AmpduTxSfCnt[ucDbdcIdx] - + au4AmpduTxAckSfCnt[ucDbdcIdx]) / + au4AmpduTxSfCnt[ucDbdcIdx]); + + u4InstantRxPer[ucDbdcIdx] = + ((prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4RxMpduCnt + + prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4FcsError) + == 0) ? + (0) : (1000 * prQueryStaStatistics-> + rMibInfo[ucDbdcIdx].u4FcsError / + (prQueryStaStatistics->rMibInfo[ucDbdcIdx]. + u4RxMpduCnt + + prQueryStaStatistics->rMibInfo[ucDbdcIdx]. + u4FcsError)); + } + + rRssi = RCPI_TO_dBm(prQueryStaStatistics->ucRcpi); + u2LinkSpeed = (prQueryStaStatistics->u2LinkSpeed == 0) ? 0 : + prQueryStaStatistics->u2LinkSpeed / 2; + + if (ucSkipAr) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d(%d)\n", "\nWlanIdx(BackupIdx)", " = ", + prHwWlanInfo->u4Index, u2Idx); + } else { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "\nWlanIdx", " = ", + prHwWlanInfo->u4Index); + } + + /* =========== Group 0x0001 =========== */ + if (u4StatGroup & 0x0001) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "----- STA Stat (Group 0x01) -----\n"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CurrTemperature", " = ", + prQueryStaStatistics->ucTemperature); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Tx Total cnt", " = ", + ucSkipAr ? (u4TotalTxCnt[u2Idx]) : + (prQueryStaStatistics->u4TransmitCount)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Tx Fail Cnt", " = ", + ucSkipAr ? (u4TotalFailCnt[u2Idx]) : + (prQueryStaStatistics->u4TransmitFailCount)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Rate1 Tx Cnt", " = ", + ucSkipAr ? (u4Rate1TxCnt[u2Idx]) : + (prQueryStaStatistics->u4Rate1TxCnt)); + + if (ucSkipAr) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d, PER = %d.%1d%%, instant PER = %d.%1d%%\n", + "Rate1 Fail Cnt", " = ", + u4Rate1FailCnt[u2Idx], u4Per/10, u4Per%10, + u4InstantPer/10, u4InstantPer%10); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d, PER = %d.%1d%%, instant PER = %d%%\n", + "Rate1 Fail Cnt", " = ", + prQueryStaStatistics->u4Rate1FailCnt, + u4Per/10, u4Per%10, u4InstantPer); + + if ((ucSkipAr) && (fgResetCnt)) { + u4TotalTxCnt[u2Idx] = 0; + u4TotalFailCnt[u2Idx] = 0; + u4Rate1TxCnt[u2Idx] = 0; + u4Rate1FailCnt[u2Idx] = 0; + } + } + + /* =========== Group 0x0002 =========== */ + if (u4StatGroup & 0x0002) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "----- MIB Info (Group 0x02) -----\n"); + + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; ucDbdcIdx++) { + if (prAdapter->rWifiVar.fgDbDcModeEn) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "[DBDC_%d] :\n", ucDbdcIdx); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RX Success", " = ", + au4RxMpduCnt[ucDbdcIdx]); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d, PER = %d.%1d%%, instant PER = %d.%1d%%\n", + "RX with CRC", " = ", au4FcsError[ucDbdcIdx], + u4RxPer[ucDbdcIdx]/10, u4RxPer[ucDbdcIdx]%10, + u4InstantRxPer[ucDbdcIdx]/10, + u4InstantRxPer[ucDbdcIdx]%10); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RX drop FIFO full", " = ", + au4RxFifoCnt[ucDbdcIdx]); + + if (!prAdapter->rWifiVar.fgDbDcModeEn) + break; + } + + if (fgResetCnt) { + kalMemZero(au4RxMpduCnt, sizeof(au4RxMpduCnt)); + kalMemZero(au4FcsError, sizeof(au4RxMpduCnt)); + kalMemZero(au4RxFifoCnt, sizeof(au4RxMpduCnt)); + kalMemZero(au4AmpduTxSfCnt, sizeof(au4RxMpduCnt)); + kalMemZero(au4AmpduTxAckSfCnt, sizeof(au4RxMpduCnt)); + } + } + + /* =========== Group 0x0004 =========== */ + if (u4StatGroup & 0x0004) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "----- Last Rx Info (Group 0x04) -----\n"); + + /* get Beacon RSSI */ + rStatus = kalIoctl(prAdapter->prGlueInfo, + wlanoidQueryRssi, &rRssi, + sizeof(rRssi), TRUE, TRUE, TRUE, + &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "unable to retrieve rssi\n"); + +#if CFG_SUPPORT_ADVANCE_CONTROL + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + + CMD_ADVCTL_NOISE_ID; + + rStatus = kalIoctl(prAdapter->prGlueInfo, + wlanoidQuerySwCtrlRead, &rSwCtrlInfo, + sizeof(rSwCtrlInfo), TRUE, TRUE, TRUE, + &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u, rSwCtrlInfo.u4Data 0x%x\n", + rStatus, rSwCtrlInfo.u4Data); + if (rStatus == WLAN_STATUS_SUCCESS) { + i2Wf0AvgPwr = rSwCtrlInfo.u4Data & 0xFFFF; + i2Wf1AvgPwr = (rSwCtrlInfo.u4Data >> 16) & 0xFFFF; + + } +#endif /* CFG_SUPPORT_ADVANCE_CONTROL */ + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d %d\n", "NOISE", " = ", + i2Wf0AvgPwr, i2Wf1AvgPwr); + + /* Last RX Rate */ + i4BytesWritten += priv_driver_rx_rate_info(prAdapter, + pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + (uint8_t)(prHwWlanInfo->u4Index)); + +#if CFG_SUPPORT_ADVANCE_CONTROL + /* Last RX SNR */ + i4BytesWritten += priv_driver_get_snr(prAdapter->prGlueInfo, + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten); +#endif + /* Last RX RSSI */ + i4BytesWritten += priv_driver_last_rx_rssi(prAdapter, + pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + (uint8_t)(prHwWlanInfo->u4Index)); + + ucRcpi0 = prHwWlanInfo->rWtblRxCounter.ucRxRcpi0; + ucRcpi1 = prHwWlanInfo->rWtblRxCounter.ucRxRcpi1; + if (ucNss > 2) { + ucRcpi2 = prHwWlanInfo->rWtblRxCounter.ucRxRcpi2; + ucRcpi3 = prHwWlanInfo->rWtblRxCounter.ucRxRcpi3; + } + +#if CFG_RCPI_COMPENSATION + if (wlanGetStaIdxByWlanIdx(prAdapter, + (uint8_t)(prHwWlanInfo->u4Index), &ucStaIdx) == + WLAN_STATUS_SUCCESS){ + ucRcpi0 = (ucRcpi0 >= RCPI_MEASUREMENT_NOT_AVAILABLE) ? + ucRcpi0 : (ucRcpi0 + + wlanGetCurrChRxFELoss(prAdapter, ucStaIdx, 0)); + ucRcpi1 = (ucRcpi1 >= RCPI_MEASUREMENT_NOT_AVAILABLE) ? + ucRcpi1 : (ucRcpi1 + + wlanGetCurrChRxFELoss(prAdapter, ucStaIdx, 1)); + + if (ucNss > 2) { + ucRcpi2 = (ucRcpi2 >= + RCPI_MEASUREMENT_NOT_AVAILABLE) ? + ucRcpi2 : (ucRcpi2 + + wlanGetCurrChRxFELoss(prAdapter, + ucStaIdx, 2)); + ucRcpi3 = (ucRcpi3 >= + RCPI_MEASUREMENT_NOT_AVAILABLE) ? + ucRcpi3 : (ucRcpi3 + + wlanGetCurrChRxFELoss(prAdapter, + ucStaIdx, 3)); + + } + } + DBGLOG(REQ, LOUD, "ucRcpi0:%d ucRcpi1:%d\n", ucRcpi0, ucRcpi1); +#endif /* CFG_RCPI_COMPENSATION */ + + /* Last TX Resp RSSI */ + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d %d", "Tx Response RSSI", " = ", + RCPI_TO_dBm(ucRcpi0), RCPI_TO_dBm(ucRcpi1)); + if (ucNss > 2) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + " %d %d\n", + RCPI_TO_dBm(ucRcpi2), RCPI_TO_dBm(ucRcpi3)); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\n"); + + /* Last Beacon RSSI */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Beacon RSSI", " = ", rRssi); + } + + /* =========== Group 0x0008 =========== */ + if (u4StatGroup & 0x0008) { + /* TxV */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "----- Last TX Info (Group 0x08) -----\n"); + + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; ucDbdcIdx++) { + int8_t txpwr; + + txpwr = TX_VECTOR_GET_TX_PWR( + &prQueryStaStatistics->rTxVector[ucDbdcIdx]); + + if (prAdapter->rWifiVar.fgDbDcModeEn) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "[DBDC_%d] :\n", ucDbdcIdx); + + i4BytesWritten += priv_driver_tx_vector_info( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + &prQueryStaStatistics->rTxVector[ucDbdcIdx]); + + if (prQueryStaStatistics->rTxVector[ucDbdcIdx] + .u4TxVector1 == 0xFFFFFFFF) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Chip Out TX Power", + " = ", "N/A"); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%c%d.%1d dBm\n", + "Chip Out TX Power", " = ", + (txpwr < 0) ? '-' : '+', + abs(txpwr / 2), + 5 * abs(txpwr % 2)); + + if (!prAdapter->rWifiVar.fgDbDcModeEn) + break; + } + } + + /* =========== Group 0x0010 =========== */ + if (u4StatGroup & 0x0010) { + /* RX Reorder */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "----- RX Reorder (Group 0x10) -----\n"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%ld\n", "Rx reorder miss", " = ", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_MISS_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%ld\n", "Rx reorder within", " = ", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_WITHIN_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%ld\n", "Rx reorder ahead", " = ", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_AHEAD_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%ld\n", "Rx reorder behind", " = ", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_BEHIND_COUNT)); + } + + /* =========== Group 0x0020 =========== */ + if (u4StatGroup & 0x0020) { + /* RA info */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "----- RA Info (Group 0x20) -----\n"); +#if 0 + /* Last TX Rate */ + i4BytesWritten += priv_driver_tx_rate_info( + pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + FALSE, prHwWlanInfo, prQueryStaStatistics); +#endif + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%-20s%s%d\n", "LinkSpeed", + " = ", u2LinkSpeed); + + if (!prQueryStaStatistics->ucSkipAr) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "RateTable", " = ", + prQueryStaStatistics->ucArTableIdx < + (ucRaTableNum - 1) ? + RATE_TBLE[ + prQueryStaStatistics->ucArTableIdx] : + RATE_TBLE[ucRaTableNum - 1]); + + if (wlanGetStaIdxByWlanIdx(prAdapter, + (uint8_t)(prHwWlanInfo->u4Index), &ucStaIdx) == + WLAN_STATUS_SUCCESS){ + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "2G Support 256QAM TX", + " = ", + ((prAdapter->arStaRec[ucStaIdx].u4Flags + & MTK_SYNERGY_CAP_SUPPORT_24G_MCS89) || + (prQueryStaStatistics-> + ucDynamicGband256QAMState == 2)) ? + 1 : 0); + } +#if 0 + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d%%\n", "Rate1 instantPer", " = ", + u4InstantPer); +#endif + if (prQueryStaStatistics->ucAvePer == 0xFF) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Train Down", " = ", + "N/A"); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Train Up", " = ", + "N/A"); + } else { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d -> %d\n", "Train Down", + " = ", + (uint16_t) + (prQueryStaStatistics->u2TrainDown + & BITS(0, 7)), + (uint16_t) + ((prQueryStaStatistics->u2TrainDown >> + 8) & BITS(0, 7))); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d -> %d\n", "Train Up", " = ", + (uint16_t) + (prQueryStaStatistics->u2TrainUp + & BITS(0, 7)), + (uint16_t) + ((prQueryStaStatistics->u2TrainUp >> 8) + & BITS(0, 7))); + } + + if (prQueryStaStatistics->fgIsForceTxStream == 0) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Force Tx Stream", + " = ", "N/A"); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Force Tx Stream", " = ", + prQueryStaStatistics-> + fgIsForceTxStream); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Force SE off", " = ", + prQueryStaStatistics->fgIsForceSeOff); +#if 0 + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s%d%s%d%s%d%s%d\n", "TxQuality", " = ", + "KEEP_", prQueryStaStatistics->aucTxQuality[0], + ", UP_", prQueryStaStatistics->aucTxQuality[1], + ", DOWN_", prQueryStaStatistics-> + aucTxQuality[2], + ", BWUP_", prQueryStaStatistics-> + aucTxQuality[3]); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "UpPenalty", " = ", + prQueryStaStatistics->ucTxRateUpPenalty); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "LtMode", " = ", + prQueryStaStatistics->ucLowTrafficMode < + (ucRaLtModeNum - 1) ? + LT_MODE_TBLE[prQueryStaStatistics-> + ucLowTrafficMode] : + LT_MODE_TBLE[ucRaLtModeNum - 1]); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "LtCnt", " = ", + prQueryStaStatistics->ucLowTrafficCount); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "LtDashBoard", " = ", + prQueryStaStatistics->ucLowTrafficDashBoard); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "SgiState", " = ", + prQueryStaStatistics->ucDynamicSGIState < + (ucRaSgiUnSpStateNum - 1) ? + SGI_UNSP_STATE_TBLE[prQueryStaStatistics-> + ucDynamicSGIState] : + SGI_UNSP_STATE_TBLE[ucRaSgiUnSpStateNum - 1]); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "SgiScore", " = ", + prQueryStaStatistics->ucDynamicSGIScore); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "BwState", " = ", + prQueryStaStatistics->ucDynamicBWState < + (ucRaBwStateNum - 1) ? + BW_STATE_TBLE[prQueryStaStatistics-> + ucDynamicBWState] : + BW_STATE_TBLE[ucRaBwStateNum - 1]); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "NonSpState", " = ", + prQueryStaStatistics->ucDynamicSGIState < + (ucRaSgiUnSpStateNum - 1) ? + SGI_UNSP_STATE_TBLE[prQueryStaStatistics-> + ucVhtNonSpRateState] : + SGI_UNSP_STATE_TBLE[ucRaSgiUnSpStateNum - 1]); +#endif + } + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RunningCnt", " = ", + prQueryStaStatistics->u2RaRunningCnt); + + prQueryStaStatistics->ucRaStatus &= ~0x80; + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Status", " = ", + prQueryStaStatistics->ucRaStatus < (ucRaStatusNum - 1) ? + RA_STATUS_TBLE[prQueryStaStatistics->ucRaStatus] : + RA_STATUS_TBLE[ucRaStatusNum - 1]); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "MaxAF", " = ", + prHwWlanInfo->rWtblPeerCap.ucAmpduFactor); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s0x%x\n", "SpeIdx", " = ", + prHwWlanInfo->rWtblPeerCap.ucSpatialExtensionIndex); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CBRN", " = ", + prHwWlanInfo->rWtblPeerCap.ucChangeBWAfterRateN); + + /* Rate1~Rate8 */ + i4BytesWritten += priv_driver_tx_rate_info( + pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + TRUE, prHwWlanInfo, prQueryStaStatistics); + } + + /* =========== Group 0x0040 =========== */ + if (u4StatGroup & 0x0040) { + u4RangeCtrl_0 = prQueryStaStatistics->u4AggRangeCtrl_0; + u4RangeCtrl_1 = prQueryStaStatistics->u4AggRangeCtrl_1; + eRangeType = (enum AGG_RANGE_TYPE_T) + prQueryStaStatistics->ucRangeType; + + ucAggRange[0] = (((u4RangeCtrl_0) & AGG_RANGE_SEL_0_MASK) >> + AGG_RANGE_SEL_0_OFFSET); + ucAggRange[1] = (((u4RangeCtrl_0) & AGG_RANGE_SEL_1_MASK) >> + AGG_RANGE_SEL_1_OFFSET); + ucAggRange[2] = (((u4RangeCtrl_0) & AGG_RANGE_SEL_2_MASK) >> + AGG_RANGE_SEL_2_OFFSET); + ucAggRange[3] = (((u4RangeCtrl_0) & AGG_RANGE_SEL_3_MASK) >> + AGG_RANGE_SEL_3_OFFSET); + ucAggRange[4] = (((u4RangeCtrl_1) & AGG_RANGE_SEL_4_MASK) >> + AGG_RANGE_SEL_4_OFFSET); + ucAggRange[5] = (((u4RangeCtrl_1) & AGG_RANGE_SEL_5_MASK) >> + AGG_RANGE_SEL_5_OFFSET); + ucAggRange[6] = (((u4RangeCtrl_1) & AGG_RANGE_SEL_6_MASK) >> + AGG_RANGE_SEL_6_OFFSET); + + /* Tx Agg */ + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s%s%s", "------ ", + (eRangeType > ENUM_AGG_RANGE_TYPE_TX) ? ( + (eRangeType == ENUM_AGG_RANGE_TYPE_TRX) ? + ("TRX") : ("RX")) : ("TX"), + " AGG (Group 0x40) -----\n"); + + if (eRangeType == ENUM_AGG_RANGE_TYPE_TRX) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-6s%8d%5d%1s%2d%5d%1s%2d%5d%3s", + " TX :", ucAggRange[0] + 1, + ucAggRange[0] + 2, "~", ucAggRange[1] + 1, + ucAggRange[1] + 2, "~", ucAggRange[2] + 1, + ucAggRange[2] + 2, "~64\n"); + + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; + ucDbdcIdx++) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "DBDC%d:", ucDbdcIdx); + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%8d%8d%8d%8d\n", + g_arMibInfo[ucDbdcIdx]. + u2TxRange1AmpduCnt, + g_arMibInfo[ucDbdcIdx]. + u2TxRange2AmpduCnt, + g_arMibInfo[ucDbdcIdx]. + u2TxRange3AmpduCnt, + g_arMibInfo[ucDbdcIdx]. + u2TxRange4AmpduCnt); + + if (!prAdapter->rWifiVar.fgDbDcModeEn) + break; + } + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-6s%8d%5d%1s%2d%5d%1s%2d%5d%3s", + " RX :", ucAggRange[3] + 1, + ucAggRange[3] + 2, "~", ucAggRange[4] + 1, + ucAggRange[4] + 2, "~", ucAggRange[5] + 1, + ucAggRange[5] + 2, "~64\n"); + + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; + ucDbdcIdx++) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "DBDC%d:", ucDbdcIdx); + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%8d%8d%8d%8d\n", + g_arMibInfo[ucDbdcIdx]. + u2TxRange5AmpduCnt, + g_arMibInfo[ucDbdcIdx]. + u2TxRange6AmpduCnt, + g_arMibInfo[ucDbdcIdx]. + u2TxRange7AmpduCnt, + g_arMibInfo[ucDbdcIdx]. + u2TxRange8AmpduCnt); + + if (!prAdapter->rWifiVar.fgDbDcModeEn) + break; + } + } else { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-6s%8d%5d%1s%2d%5d%1s%2d%5d%1s%2d%5d%1s%2d%5d%1s%2d%5d%1s%2d%5d%3s", + "Range:", ucAggRange[0] + 1, + ucAggRange[0] + 2, "~", ucAggRange[1] + 1, + ucAggRange[1] + 2, "~", ucAggRange[2] + 1, + ucAggRange[2] + 2, "~", ucAggRange[3] + 1, + ucAggRange[3] + 2, "~", ucAggRange[4] + 1, + ucAggRange[4] + 2, "~", ucAggRange[5] + 1, + ucAggRange[5] + 2, "~", ucAggRange[6] + 1, + ucAggRange[6] + 2, "~64\n"); + + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; + ucDbdcIdx++) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "DBDC%d:", ucDbdcIdx); + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%8d%8d%8d%8d%8d%8d%8d%8d\n", + g_arMibInfo[ucDbdcIdx]. + u2TxRange1AmpduCnt, + g_arMibInfo[ucDbdcIdx]. + u2TxRange2AmpduCnt, + g_arMibInfo[ucDbdcIdx]. + u2TxRange3AmpduCnt, + g_arMibInfo[ucDbdcIdx]. + u2TxRange4AmpduCnt, + g_arMibInfo[ucDbdcIdx]. + u2TxRange5AmpduCnt, + g_arMibInfo[ucDbdcIdx]. + u2TxRange6AmpduCnt, + g_arMibInfo[ucDbdcIdx]. + u2TxRange7AmpduCnt, + g_arMibInfo[ucDbdcIdx]. + u2TxRange8AmpduCnt); + + if (!prAdapter->rWifiVar.fgDbDcModeEn) + break; + } + } + } + + kalMemZero(g_arMibInfo, sizeof(g_arMibInfo)); + + return i4BytesWritten; +} + +static int32_t priv_driver_set_ra_debug_proc(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + int8_t *this_char = NULL; + int32_t i4Recv = 0; + uint32_t u4WCID = 0, u4DebugType = 0; + uint32_t u4Id = 0xa0650000; + struct PARAM_CUSTOM_SW_CTRL_STRUCT *prSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %d, apcArgv[0] = %s\n\n", i4Argc, *apcArgv); + + this_char = kalStrStr(*apcArgv, "="); + if (!this_char) + return -1; + this_char++; + + DBGLOG(REQ, LOUD, "string = %s\n", this_char); + + i4Recv = sscanf(this_char, "%d:%d", &(u4WCID), &(u4DebugType)); + + prSwCtrlInfo = + (struct PARAM_CUSTOM_SW_CTRL_STRUCT *)kalMemAlloc( + sizeof(struct PARAM_CUSTOM_SW_CTRL_STRUCT), + VIR_MEM_TYPE); + if (!prSwCtrlInfo) + return -1; + + if (i4Recv == 2) { + prSwCtrlInfo->u4Id = u4Id; + prSwCtrlInfo->u4Data = u4WCID | + ((u4DebugType & BITS(0, 15)) << 16); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, + prSwCtrlInfo, + sizeof(struct PARAM_CUSTOM_SW_CTRL_STRUCT), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + kalMemFree(prSwCtrlInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_CUSTOM_SW_CTRL_STRUCT)); + return -1; + } + + DBGLOG(REQ, LOUD, "WlanIdx=%d\nDebugType=%d\nu4Data=0x%08x\n", + u4WCID, u4DebugType, prSwCtrlInfo->u4Data); + } else { + DBGLOG(INIT, ERROR, + "iwpriv wlanXX driver RaDebug=[wlanIdx]:[debugType]\n"); + } + + kalMemFree(prSwCtrlInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_CUSTOM_SW_CTRL_STRUCT)); + + return i4BytesWritten; +} + +int priv_driver_set_fixed_fallback(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + /* INT_32 u4Ret = 0; */ + uint32_t u4WCID = 0; + uint32_t u4Mode = 0, u4Bw = 0, u4Mcs = 0, u4VhtNss = 0, u4Band = 0; + uint32_t u4SGI = 0, u4Preamble = 0, u4STBC = 0, u4LDPC = 0, u4SpeEn = 0; + int32_t i4Recv = 0; + int8_t *this_char = NULL; + uint32_t u4Id = 0xa0660000; + uint32_t u4Data = 0x80000000; + uint32_t u4Id2 = 0xa0600000; + uint8_t u4Nsts = 1; + u_int8_t fgStatus = TRUE; + static uint8_t fgIsUseWCID = FALSE; + + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %d, apcArgv[0] = %s\n\n", i4Argc, *apcArgv); + + this_char = kalStrStr(*apcArgv, "="); + if (!this_char) + return -1; + this_char++; + + DBGLOG(REQ, LOUD, "string = %s\n", this_char); + + if (strnicmp(this_char, "auto", strlen("auto")) == 0) { + i4Recv = 1; + } else if (strnicmp(this_char, "UseWCID", strlen("UseWCID")) == 0) { + i4Recv = 2; + fgIsUseWCID = TRUE; + } else if (strnicmp(this_char, "ApplyAll", strlen("ApplyAll")) == 0) { + i4Recv = 3; + fgIsUseWCID = FALSE; + } else { + i4Recv = sscanf(this_char, "%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d", + &(u4WCID), &(u4Mode), &(u4Bw), &(u4Mcs), + &(u4VhtNss), &(u4SGI), &(u4Preamble), &(u4STBC), + &(u4LDPC), &(u4SpeEn), &(u4Band)); + + DBGLOG(REQ, LOUD, "u4WCID=%d\nu4Mode=%d\nu4Bw=%d\n", + u4WCID, u4Mode, u4Bw); + DBGLOG(REQ, LOUD, "u4Mcs=%d\nu4VhtNss=%d\nu4SGI=%d\n", + u4Mcs, u4VhtNss, u4SGI); + DBGLOG(REQ, LOUD, "u4Preamble=%d\nu4STBC=%d\n", + u4Preamble, u4STBC); + DBGLOG(REQ, LOUD, "u4LDPC=%d\nu4SpeEn=%d\nu4Band=%d\n", + u4LDPC, u4SpeEn, u4Band); + DBGLOG(REQ, LOUD, "fgIsUseWCID=%d\n\n", + fgIsUseWCID); + } + + if (i4Recv == 1) { + rSwCtrlInfo.u4Id = u4Id2; + rSwCtrlInfo.u4Data = 0; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } else if (i4Recv == 2 || i4Recv == 3) { + i4BytesWritten = snprintf(pcCommand, i4TotalLen, + "Update fgIsUseWCID %d\n", fgIsUseWCID); + } else if (i4Recv == 11) { + rSwCtrlInfo.u4Id = u4Id; + rSwCtrlInfo.u4Data = u4Data; + + if (fgIsUseWCID && u4WCID < WTBL_SIZE && + prAdapter->rWifiVar.arWtbl[u4WCID].ucUsed) { + rSwCtrlInfo.u4Id |= u4WCID; + rSwCtrlInfo.u4Id |= BIT(8); + i4BytesWritten = snprintf( + pcCommand, i4TotalLen, + "Apply WCID %d\n", u4WCID); + } else { + i4BytesWritten = snprintf( + pcCommand, i4TotalLen, "Apply All\n"); + } + + if (u4SGI) + rSwCtrlInfo.u4Data |= BIT(30); + if (u4LDPC) + rSwCtrlInfo.u4Data |= BIT(29); + if (u4SpeEn) + rSwCtrlInfo.u4Data |= BIT(28); + if (u4Band) + rSwCtrlInfo.u4Data |= BIT(25); + if (u4STBC) + rSwCtrlInfo.u4Data |= BIT(11); + + if (u4Bw <= 3) + rSwCtrlInfo.u4Data |= ((u4Bw << 26) & BITS(26, 27)); + else { + fgStatus = FALSE; + DBGLOG(INIT, ERROR, + "Wrong BW! BW20=0, BW40=1, BW80=2,BW160=3\n"); + } + if (u4Mode <= 4) { + rSwCtrlInfo.u4Data |= ((u4Mode << 6) & BITS(6, 8)); + + switch (u4Mode) { + case 0: + if (u4Mcs <= 3) + rSwCtrlInfo.u4Data |= u4Mcs; + else { + fgStatus = FALSE; + DBGLOG(INIT, ERROR, + "CCK mode but wrong MCS!\n"); + } + + if (u4Preamble) + rSwCtrlInfo.u4Data |= BIT(2); + else + rSwCtrlInfo.u4Data &= ~BIT(2); + break; + case 1: + switch (u4Mcs) { + case 0: + /* 6'b001011 */ + rSwCtrlInfo.u4Data |= 11; + break; + case 1: + /* 6'b001111 */ + rSwCtrlInfo.u4Data |= 15; + break; + case 2: + /* 6'b001010 */ + rSwCtrlInfo.u4Data |= 10; + break; + case 3: + /* 6'b001110 */ + rSwCtrlInfo.u4Data |= 14; + break; + case 4: + /* 6'b001001 */ + rSwCtrlInfo.u4Data |= 9; + break; + case 5: + /* 6'b001101 */ + rSwCtrlInfo.u4Data |= 13; + break; + case 6: + /* 6'b001000 */ + rSwCtrlInfo.u4Data |= 8; + break; + case 7: + /* 6'b001100 */ + rSwCtrlInfo.u4Data |= 12; + break; + default: + fgStatus = FALSE; + DBGLOG(INIT, ERROR, + "OFDM mode but wrong MCS!\n"); + break; + } + break; + case 2: + case 3: + if (u4Mcs <= 32) + rSwCtrlInfo.u4Data |= u4Mcs; + else { + fgStatus = FALSE; + DBGLOG(INIT, ERROR, + "HT mode but wrong MCS!\n"); + } + + if (u4Mcs != 32) { + u4Nsts += (u4Mcs >> 3); + if (u4STBC && (u4Nsts == 1)) + u4Nsts++; + } + break; + case 4: + if (u4Mcs <= 9) + rSwCtrlInfo.u4Data |= u4Mcs; + else { + fgStatus = FALSE; + DBGLOG(INIT, ERROR, + "VHT mode but wrong MCS!\n"); + } + if (u4STBC && (u4VhtNss == 1)) + u4Nsts++; + else + u4Nsts = u4VhtNss; + break; + default: + break; + } + } else { + fgStatus = FALSE; + DBGLOG(INIT, ERROR, + "Wrong TxMode! CCK=0, OFDM=1, HT=2, GF=3, VHT=4\n"); + } + + rSwCtrlInfo.u4Data |= (((u4Nsts - 1) << 9) & BITS(9, 10)); + + if (fgStatus) { + rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + FALSE, FALSE, TRUE, &u4BufLen); + } + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } else { + DBGLOG(INIT, ERROR, "iwpriv wlanXX driver FixedRate=Option\n"); + DBGLOG(INIT, ERROR, + "Option:[WCID]-[Mode]-[BW]-[MCS]-[VhtNss]-[SGI]-[Preamble]-[STBC]-[LDPC]-[SPE_EN]-[BAND]\n"); + DBGLOG(INIT, ERROR, "[WCID]Wireless Client ID\n"); + DBGLOG(INIT, ERROR, "[Mode]CCK=0, OFDM=1, HT=2, GF=3, VHT=4\n"); + DBGLOG(INIT, ERROR, "[BW]BW20=0, BW40=1, BW80=2,BW160=3\n"); + DBGLOG(INIT, ERROR, + "[MCS]CCK=0~3, OFDM=0~7, HT=0~32, VHT=0~9\n"); + DBGLOG(INIT, ERROR, "[VhtNss]VHT=1~4, Other=ignore\n"); + DBGLOG(INIT, ERROR, "[Preamble]Long=0, Other=Short\n"); + DBGLOG(INIT, ERROR, "[BAND]2G=0, Other=5G\n"); + } + + return i4BytesWritten; +} +#endif + +#if (CFG_SUPPORT_TXPOWER_INFO == 1) +static int32_t priv_driver_dump_txpower_info(struct ADAPTER *prAdapter, + IN char *pcCommand, IN int i4TotalLen, + struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T *prTxPowerInfo) +{ + int32_t i4BytesWritten = 0; + + if (prTxPowerInfo->ucTxPowerCategory == + TXPOWER_EVENT_SHOW_ALL_RATE_TXPOWER_INFO) { +#define CCK_IDX 0 +#define OFDM_IDX 1 +#define HT20_IDX 2 +#define HT40_IDX 3 +#define VHT20_IDX 4 +#define VHT40_IDX 5 +#define VHT80_IDX 6 +#define VHT160_IDX 7 + + uint8_t ucTxPwrIdx = 0, ucTxPwrType = 0, ucIdx = 0, + ucIdxOffset = 0; + u_int8_t fgIsHt = TRUE; + uint8_t *pucTxPwrRate = NULL; + struct FRAME_POWER_CONFIG_INFO_T rRatePowerInfo; + uint8_t ucTxPwrCckRate[MODULATION_SYSTEM_CCK_NUM] = { + 1, 2, 5, 11}; + uint8_t ucTxPwrOfdmRate[MODULATION_SYSTEM_OFDM_NUM] = { + 6, 9, 12, 18, 24, 36, 48, 54 }; + uint8_t ucTxPwrHt20Rate[MODULATION_SYSTEM_HT20_NUM] = { + 0, 1, 2, 3, 4, 5, 6, 7 }; + uint8_t ucTxPwrHt40Rate[MODULATION_SYSTEM_HT40_NUM] = { + 0, 1, 2, 3, 4, 5, 6, 7, 32 }; + uint8_t *POWER_TYPE_STR[] = { + [CCK_IDX] = "CCK", + [OFDM_IDX] = "OFDM", + [HT20_IDX] = "HT20", + [HT40_IDX] = "HT40", + [VHT20_IDX] = "VHT20", + [VHT40_IDX] = "VHT40", + [VHT80_IDX] = "VHT80", + [VHT160_IDX] = "VHT160"}; + uint8_t ucPwrIdxLen[] = { + MODULATION_SYSTEM_CCK_NUM, MODULATION_SYSTEM_OFDM_NUM, + MODULATION_SYSTEM_HT20_NUM, MODULATION_SYSTEM_HT40_NUM, + MODULATION_SYSTEM_VHT20_NUM, MODULATION_SYSTEM_VHT40_NUM, + MODULATION_SYSTEM_VHT80_NUM, MODULATION_SYSTEM_VHT160_NUM }; + + if ((sizeof(POWER_TYPE_STR)/sizeof(uint8_t *)) != + (sizeof(ucPwrIdxLen)/sizeof(uint8_t))) + return i4BytesWritten; + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s", + "\n====== TX POWER INFO ======\n"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s", + "------\n"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "DBDC Index: %d, Channel Band: %s\n", + prTxPowerInfo->ucBandIdx, + (prTxPowerInfo->ucChBand) ? + ("5G") : ("2G")); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "------\n"); + + for (ucTxPwrType = 0; + ucTxPwrType < sizeof(POWER_TYPE_STR)/sizeof(uint8_t *); + ucTxPwrType++) { + for (ucTxPwrIdx = 0; + ucTxPwrIdx < ucPwrIdxLen[ucTxPwrType]; + ucTxPwrIdx++) { + if ((ucTxPwrType == CCK_IDX) || + (ucTxPwrType == OFDM_IDX)) { + pucTxPwrRate = + (ucTxPwrType == CCK_IDX) ? + (ucTxPwrCckRate) : + (ucTxPwrOfdmRate); + + ucIdx = ucTxPwrIdx + ucIdxOffset; + rRatePowerInfo = + prTxPowerInfo->rRatePowerInfo; + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "[%s_%02dM]: 0x%02x (%03d)\n", + POWER_TYPE_STR[ucTxPwrType], + pucTxPwrRate[ucTxPwrIdx], + rRatePowerInfo. + aicFramePowerConfig[ucIdx]. + icFramePowerDbm, + rRatePowerInfo. + aicFramePowerConfig[ucIdx]. + icFramePowerDbm); + } else { + if (ucTxPwrType == HT20_IDX) { + pucTxPwrRate = ucTxPwrHt20Rate; + fgIsHt = TRUE; + } else if (ucTxPwrType == HT40_IDX) { + pucTxPwrRate = ucTxPwrHt40Rate; + fgIsHt = TRUE; + } else { + fgIsHt = FALSE; + } + + rRatePowerInfo = + prTxPowerInfo->rRatePowerInfo; + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "[%s_M%02d]: 0x%02x (%03d)\n", + POWER_TYPE_STR[ucTxPwrType], + ((fgIsHt) ? + (pucTxPwrRate[ucTxPwrIdx]) : + (ucTxPwrIdx)), + rRatePowerInfo. + aicFramePowerConfig[ucIdx] + .icFramePowerDbm, + rRatePowerInfo. + aicFramePowerConfig[ucIdx] + .icFramePowerDbm); + } + } + + if ((ucTxPwrType == OFDM_IDX) || + (ucTxPwrType == HT40_IDX) || + (ucTxPwrType == VHT160_IDX)) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "------\n"); + + ucIdxOffset += ucPwrIdxLen[ucTxPwrType]; + } + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "[MAX][Bound]: 0x%02x (%03d)\n", + prTxPowerInfo->icPwrMaxBnd, + prTxPowerInfo->icPwrMaxBnd); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "[MIN][Bound]: 0x%02x (%03d)\n", + prTxPowerInfo->icPwrMinBnd, + prTxPowerInfo->icPwrMinBnd); + } + + return i4BytesWritten; +} + +static int32_t priv_driver_get_txpower_info(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0, u4Size = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + int8_t *this_char = NULL; + uint32_t u4Ret = 0; + uint8_t ucParam = 0; + struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T *prTxPowerInfo = NULL; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %d, apcArgv[0] = %s\n\n", i4Argc, *apcArgv); + + this_char = kalStrStr(*apcArgv, "="); + if (!this_char) + return -1; + this_char++; + + DBGLOG(REQ, LOUD, "string = %s\n", this_char); + u4Ret = kalkStrtou8(this_char, 0, &ucParam); + DBGLOG(REQ, LOUD, "u4Ret = %d, ucParam = %d\n", u4Ret, ucParam); + + u4Size = sizeof(struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T); + + prTxPowerInfo = + (struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T *)kalMemAlloc( + u4Size, VIR_MEM_TYPE); + if (!prTxPowerInfo) + return -1; + + if (u4Ret == 0) { + prTxPowerInfo->ucTxPowerCategory = ucParam; + + /* + * FIX ME: Mobile driver can't get correct band, + * so assigned Band_0 as temp solution. + * Remember to fix it when needed to use this command on Band_1. + */ + prTxPowerInfo->ucBandIdx = ENUM_BAND_0; + rStatus = kalIoctl(prGlueInfo, wlanoidQueryTxPowerInfo, + prTxPowerInfo, + sizeof(struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + kalMemFree(prTxPowerInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T)); + return -1; + } + + i4BytesWritten = priv_driver_dump_txpower_info(prAdapter, + pcCommand, i4TotalLen, prTxPowerInfo); + } else { + DBGLOG(INIT, ERROR, + "iwpriv wlanXX driver TxPowerInfo=[Param]\n"); + } + + kalMemFree(prTxPowerInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T)); + + return i4BytesWritten; +} +#endif + +static int priv_driver_get_sta_stat(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0, u4Ret, u4StatGroup = 0xFFFFFFFF; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + uint8_t aucMacAddr[MAC_ADDR_LEN]; + uint8_t ucWlanIndex; + uint8_t *pucMacAddr = NULL; + struct PARAM_HW_WLAN_INFO *prHwWlanInfo = NULL; + struct PARAM_GET_STA_STATISTICS *prQueryStaStatistics = NULL; + u_int8_t fgResetCnt = FALSE; + u_int8_t fgRxCCSel = FALSE; + u_int8_t fgSearchMacAddr = FALSE; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= 4) { + if (strnicmp(apcArgv[2], CMD_STAT_GROUP_SEL, + strlen(CMD_STAT_GROUP_SEL)) == 0) { + u4Ret = kalkStrtou32(apcArgv[3], 0, &(u4StatGroup)); + + if (u4Ret) + DBGLOG(REQ, LOUD, + "parse get_sta_stat error (Group) u4Ret=%d\n", + u4Ret); + if (u4StatGroup == 0) + u4StatGroup = 0xFFFFFFFF; + + wlanHwAddrToBin(apcArgv[1], &aucMacAddr[0]); + + if (!wlanGetWlanIdxByAddress(prGlueInfo->prAdapter, + &aucMacAddr[0], &ucWlanIndex)) { + DBGLOG(REQ, INFO, + "wlan index of %pM is not found!\n", + aucMacAddr); + goto out; + } + } else { + goto out; + } + } else if (i4Argc >= 3) { + if (strnicmp(apcArgv[1], CMD_STAT_GROUP_SEL, + strlen(CMD_STAT_GROUP_SEL)) == 0) { + u4Ret = kalkStrtou32(apcArgv[2], 0, &(u4StatGroup)); + + if (u4Ret) + DBGLOG(REQ, LOUD, + "parse get_sta_stat error (Group) u4Ret=%d\n", + u4Ret); + if (u4StatGroup == 0) + u4StatGroup = 0xFFFFFFFF; + + if (prGlueInfo->prAdapter->prAisBssInfo->prStaRecOfAP) { + ucWlanIndex = prGlueInfo->prAdapter + ->prAisBssInfo->prStaRecOfAP + ->ucWlanIndex; + } else if (!wlanGetWlanIdxByAddress( + prGlueInfo->prAdapter, NULL, + &ucWlanIndex)) { + DBGLOG(REQ, INFO, + "wlan index of %pM is not found!\n", + aucMacAddr); + goto out; + } + } else { + if (strnicmp(apcArgv[1], CMD_STAT_RESET_CNT, + strlen(CMD_STAT_RESET_CNT)) == 0) { + wlanHwAddrToBin(apcArgv[2], &aucMacAddr[0]); + fgResetCnt = TRUE; + } else if (strnicmp(apcArgv[2], CMD_STAT_RESET_CNT, + strlen(CMD_STAT_RESET_CNT)) == 0) { + wlanHwAddrToBin(apcArgv[1], &aucMacAddr[0]); + fgResetCnt = TRUE; + } else { + wlanHwAddrToBin(apcArgv[1], &aucMacAddr[0]); + fgResetCnt = FALSE; + } + + if (!wlanGetWlanIdxByAddress(prGlueInfo->prAdapter, + &aucMacAddr[0], &ucWlanIndex)) { + DBGLOG(REQ, INFO, + "wlan index of %pM is not found!\n", + aucMacAddr); + goto out; + } + } + } else { + if (i4Argc == 1) { + fgSearchMacAddr = TRUE; + } else if (i4Argc == 2) { + if (strnicmp(apcArgv[1], CMD_STAT_RESET_CNT, + strlen(CMD_STAT_RESET_CNT)) == 0) { + fgResetCnt = TRUE; + fgSearchMacAddr = TRUE; + } else if (strnicmp(apcArgv[1], CMD_STAT_NOISE_SEL, + strlen(CMD_STAT_NOISE_SEL)) == 0) { + fgRxCCSel = TRUE; + fgSearchMacAddr = TRUE; + } else { + wlanHwAddrToBin(apcArgv[1], &aucMacAddr[0]); + + if (!wlanGetWlanIdxByAddress(prGlueInfo-> + prAdapter, &aucMacAddr[0], &ucWlanIndex)) { + DBGLOG(REQ, INFO, + "No connected peer found!\n"); + goto out; + } + } + } + + if (fgSearchMacAddr) { + /* Get AIS AP address for no argument */ + if (prGlueInfo->prAdapter->prAisBssInfo->prStaRecOfAP) { + ucWlanIndex = prGlueInfo->prAdapter-> + prAisBssInfo->prStaRecOfAP->ucWlanIndex; + } else if (!wlanGetWlanIdxByAddress(prGlueInfo-> + prAdapter, NULL, &ucWlanIndex)) { + DBGLOG(REQ, INFO, "No connected peer found!\n"); + goto out; + } + } + } + + prHwWlanInfo = (struct PARAM_HW_WLAN_INFO *)kalMemAlloc( + sizeof(struct PARAM_HW_WLAN_INFO), VIR_MEM_TYPE); + if (!prHwWlanInfo) { + DBGLOG(REQ, ERROR, + "Allocate prHwWlanInfo failed!\n"); + i4BytesWritten = -1; + goto out; + } + + prHwWlanInfo->u4Index = ucWlanIndex; + if (fgRxCCSel == TRUE) + prHwWlanInfo->rWtblRxCounter.fgRxCCSel = TRUE; + else + prHwWlanInfo->rWtblRxCounter.fgRxCCSel = FALSE; + + DBGLOG(REQ, INFO, "MT6632 : index = %d i4TotalLen = %d\n", + prHwWlanInfo->u4Index, i4TotalLen); + + /* Get WTBL info */ + rStatus = kalIoctl(prGlueInfo, wlanoidQueryWlanInfo, prHwWlanInfo, + sizeof(struct PARAM_HW_WLAN_INFO), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "Query prHwWlanInfo failed!\n"); + i4BytesWritten = -1; + goto out; + } + + /* Get Statistics info */ + prQueryStaStatistics = + (struct PARAM_GET_STA_STATISTICS *)kalMemAlloc( + sizeof(struct PARAM_GET_STA_STATISTICS), VIR_MEM_TYPE); + if (!prQueryStaStatistics) { + DBGLOG(REQ, ERROR, + "Allocate prQueryStaStatistics failed!\n"); + i4BytesWritten = -1; + goto out; + } + + prQueryStaStatistics->ucResetCounter = fgResetCnt; + + pucMacAddr = wlanGetStaAddrByWlanIdx(prGlueInfo->prAdapter, + ucWlanIndex); + + if (!pucMacAddr) { + DBGLOG(REQ, ERROR, "Addr of WlanIndex %d is not found!\n", + ucWlanIndex); + i4BytesWritten = -1; + goto out; + } + COPY_MAC_ADDR(prQueryStaStatistics->aucMacAddr, pucMacAddr); + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryStaStatistics, + prQueryStaStatistics, + sizeof(struct PARAM_GET_STA_STATISTICS), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "Query prQueryStaStatistics failed!\n"); + i4BytesWritten = -1; + goto out; + } + + if (pucMacAddr) { + i4BytesWritten = priv_driver_dump_stat_info(prAdapter, + pcCommand, i4TotalLen, prHwWlanInfo, + prQueryStaStatistics, fgResetCnt, u4StatGroup); + } + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + +out: + if (prHwWlanInfo) + kalMemFree(prHwWlanInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_HW_WLAN_INFO)); + + if (prQueryStaStatistics) + kalMemFree(prQueryStaStatistics, VIR_MEM_TYPE, + sizeof(struct PARAM_GET_STA_STATISTICS)); + + + if (fgResetCnt) + nicRxClearStatistics(prGlueInfo->prAdapter); + + return i4BytesWritten; +} + +static int32_t priv_driver_dump_stat2_info(struct ADAPTER *prAdapter, + IN char *pcCommand, IN int i4TotalLen, + struct UMAC_STAT2_GET *prUmacStat2GetInfo, + struct PARAM_GET_DRV_STATISTICS *prQueryDrvStatistics) +{ + int32_t i4BytesWritten = 0; + uint16_t u2PleTotalRevPage = 0; + uint16_t u2PleTotalSrcPage = 0; + uint16_t u2PseTotalRevPage = 0; + uint16_t u2PseTotalSrcPage = 0; + + u2PleTotalRevPage = prUmacStat2GetInfo->u2PleRevPgHif0Group0 + + prUmacStat2GetInfo->u2PleRevPgCpuGroup2; + + u2PleTotalSrcPage = prUmacStat2GetInfo->u2PleSrvPgHif0Group0 + + prUmacStat2GetInfo->u2PleSrvPgCpuGroup2; + + u2PseTotalRevPage = prUmacStat2GetInfo->u2PseRevPgHif0Group0 + + prUmacStat2GetInfo->u2PseRevPgHif1Group1 + + prUmacStat2GetInfo->u2PseRevPgCpuGroup2 + + prUmacStat2GetInfo->u2PseRevPgLmac0Group3 + + prUmacStat2GetInfo->u2PseRevPgLmac1Group4 + + prUmacStat2GetInfo->u2PseRevPgLmac2Group5 + + prUmacStat2GetInfo->u2PseRevPgPleGroup6; + + u2PseTotalSrcPage = prUmacStat2GetInfo->u2PseSrvPgHif0Group0 + + prUmacStat2GetInfo->u2PseSrvPgHif1Group1 + + prUmacStat2GetInfo->u2PseSrvPgCpuGroup2 + + prUmacStat2GetInfo->u2PseSrvPgLmac0Group3 + + prUmacStat2GetInfo->u2PseSrvPgLmac1Group4 + + prUmacStat2GetInfo->u2PseSrvPgLmac2Group5 + + prUmacStat2GetInfo->u2PseSrvPgPleGroup6; + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "\n----- Stat2 Info -----\n"); + + + /* Rev Page number Info. */ + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "\n----- PLE Reservation Page Info. -----\n"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Ple Hif0 Group0 RevPage", " = ", + prUmacStat2GetInfo->u2PleRevPgHif0Group0); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Ple Cpu Group2 RevPage", " = ", + prUmacStat2GetInfo->u2PleRevPgCpuGroup2); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Ple Total RevPage", " = ", + u2PleTotalRevPage); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "\n----- PLE Source Page Info. ----------\n"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Ple Hif0 Group0 SrcPage", " = ", + prUmacStat2GetInfo->u2PleSrvPgHif0Group0); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Ple Cpu Group2 SrcPage", " = ", + prUmacStat2GetInfo->u2PleSrvPgCpuGroup2); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Ple Total SrcPage", " = ", + u2PleTotalSrcPage); + + /* umac MISC Info. */ + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "\n----- PLE Misc Info. -----------------\n"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "ple Total Page Number", " = ", + prUmacStat2GetInfo->u2PleTotalPageNum); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "ple Free Page Number", " = ", + prUmacStat2GetInfo->u2PleFreePageNum); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "ple FFA Page Number", " = ", + prUmacStat2GetInfo->u2PleFfaNum); + + /* PSE Info. */ + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "\n----- PSE Reservation Page Info. -----\n"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Hif0 Group0 RevPage", " = ", + prUmacStat2GetInfo->u2PseRevPgHif0Group0); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Hif1 Group1 RevPage", " = ", + prUmacStat2GetInfo->u2PseRevPgHif1Group1); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Cpu Group2 RevPage", " = ", + prUmacStat2GetInfo->u2PseRevPgCpuGroup2); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Lmac0 Group3 RevPage", " = ", + prUmacStat2GetInfo->u2PseRevPgLmac0Group3); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Lmac1 Group4 RevPage", " = ", + prUmacStat2GetInfo->u2PseRevPgLmac1Group4); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Lmac2 Group5 RevPage", " = ", + prUmacStat2GetInfo->u2PseRevPgLmac2Group5); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Ple Group6 RevPage", " = ", + prUmacStat2GetInfo->u2PseRevPgPleGroup6); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Total RevPage", " = ", + u2PseTotalRevPage); + + /* PSE Info. */ + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "\n----- PSE Source Page Info. ----------\n"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Hif0 Group0 SrcPage", " = ", + prUmacStat2GetInfo->u2PseSrvPgHif0Group0); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Hif1 Group1 SrcPage", " = ", + prUmacStat2GetInfo->u2PseSrvPgHif1Group1); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Cpu Group2 SrcPage", " = ", + prUmacStat2GetInfo->u2PseSrvPgCpuGroup2); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Lmac0 Group3 SrcPage", " = ", + prUmacStat2GetInfo->u2PseSrvPgLmac0Group3); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Lmac1 Group4 SrcPage", " = ", + prUmacStat2GetInfo->u2PseSrvPgLmac1Group4); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Lmac2 Group5 SrcPage", " = ", + prUmacStat2GetInfo->u2PseSrvPgLmac2Group5); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Ple Group6 SrcPage", " = ", + prUmacStat2GetInfo->u2PseSrvPgPleGroup6); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Total SrcPage", " = ", + u2PseTotalSrcPage); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "\n----- PSE Misc Info. -----------------\n"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "pse Total Page Number", " = ", + prUmacStat2GetInfo->u2PseTotalPageNum); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "pse Free Page Number", " = ", + prUmacStat2GetInfo->u2PseFreePageNum); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "pse FFA Page Number", " = ", + prUmacStat2GetInfo->u2PseFfaNum); + + + /* driver info */ + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "\n\n----- DRV Stat -----------------------\n\n"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pending Data", " = ", + prQueryDrvStatistics->i4TxPendingFrameNum); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pending Sec", " = ", + prQueryDrvStatistics->i4TxPendingSecurityFrameNum); +#if 0 + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%s\n", "Tx Pending Cmd Number", " = ", + prQueryDrvStatistics->i4TxPendingCmdNum); +#endif + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Tx Pending For-pkt Number", " = ", + prQueryDrvStatistics->i4PendingFwdFrameCount); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "MsduInfo Available Number", " = ", + prQueryDrvStatistics->u4MsduNumElem); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "MgmtTxRing Pending Number", " = ", + prQueryDrvStatistics->u4TxMgmtTxringQueueNumElem); + + /* Driver Rx Info. */ + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Rx Free Sw Rfb Number", " = ", + prQueryDrvStatistics->u4RxFreeSwRfbMsduNumElem); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Rx Received Sw Rfb Number", " = ", + prQueryDrvStatistics->u4RxReceivedRfbNumElem); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Rx Indicated Sw Rfb Number", " = ", + prQueryDrvStatistics->u4RxIndicatedNumElem); + + return i4BytesWritten; +} + +static int priv_driver_get_sta_stat2(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + int32_t i4BytesWritten = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i4ArgNum = 1; + struct UMAC_STAT2_GET *prUmacStat2GetInfo; + struct PARAM_GET_DRV_STATISTICS *prQueryDrvStatistics; + struct QUE *prQueList, *prTxMgmtTxRingQueList; + struct RX_CTRL *prRxCtrl; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc < i4ArgNum) + return -1; + + prQueList = &prAdapter->rTxCtrl.rFreeMsduInfoList; + + prTxMgmtTxRingQueList = &prAdapter->rTxCtrl.rTxMgmtTxingQueue; + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + /* to do for UMAC Dump */ + prUmacStat2GetInfo = (struct UMAC_STAT2_GET *)kalMemAlloc( + sizeof(struct UMAC_STAT2_GET), VIR_MEM_TYPE); + if (prUmacStat2GetInfo == NULL) + return -1; + + halUmacInfoGetMiscStatus(prAdapter, prUmacStat2GetInfo); + + + /* Get Driver stat info */ + prQueryDrvStatistics = + (struct PARAM_GET_DRV_STATISTICS *)kalMemAlloc(sizeof( + struct PARAM_GET_DRV_STATISTICS), VIR_MEM_TYPE); + if (prQueryDrvStatistics == NULL) { + kalMemFree(prUmacStat2GetInfo, VIR_MEM_TYPE, + sizeof(struct UMAC_STAT2_GET)); + return -1; + } + + prQueryDrvStatistics->i4TxPendingFrameNum = + (uint32_t) GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum); + prQueryDrvStatistics->i4TxPendingSecurityFrameNum = + (uint32_t) GLUE_GET_REF_CNT( + prGlueInfo->i4TxPendingSecurityFrameNum); +#if 0 + prQueryDrvStatistics->i4TxPendingCmdNum = + (uint32_t) GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingCmdNum); +#endif + + prQueryDrvStatistics->i4PendingFwdFrameCount = + prAdapter->rTxCtrl.i4PendingFwdFrameCount; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + prQueryDrvStatistics->u4MsduNumElem = prQueList->u4NumElem; + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + prQueryDrvStatistics->u4TxMgmtTxringQueueNumElem = + prTxMgmtTxRingQueList->u4NumElem; + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + prQueryDrvStatistics->u4RxFreeSwRfbMsduNumElem = + prRxCtrl->rFreeSwRfbList.u4NumElem; + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + prQueryDrvStatistics->u4RxReceivedRfbNumElem = + prRxCtrl->rReceivedRfbList.u4NumElem; + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + prQueryDrvStatistics->u4RxIndicatedNumElem = + prRxCtrl->rIndicatedRfbList.u4NumElem; + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + i4BytesWritten = priv_driver_dump_stat2_info(prAdapter, pcCommand, + i4TotalLen, prUmacStat2GetInfo, prQueryDrvStatistics); + + kalMemFree(prUmacStat2GetInfo, VIR_MEM_TYPE, + sizeof(struct UMAC_STAT2_GET)); + kalMemFree(prQueryDrvStatistics, VIR_MEM_TYPE, + sizeof(struct PARAM_GET_DRV_STATISTICS)); + + return i4BytesWritten; +} + + +static int32_t priv_driver_dump_rx_stat_info(struct ADAPTER *prAdapter, + IN char *pcCommand, IN int i4TotalLen, + IN u_int8_t fgResetCnt) +{ + int32_t i4BytesWritten = 0; + uint32_t u4RxVector0 = 0, u4RxVector2 = 0, u4RxVector3 = 0, + u4RxVector4 = 0; + uint8_t ucStaIdx, ucWlanIndex, cbw; + u_int8_t fgWlanIdxFound = TRUE, fgSkipRxV = FALSE; + uint32_t u4FAGCRssiWBR0, u4FAGCRssiIBR0; + uint32_t u4Value, u4Foe, foe_const; + static uint32_t au4MacMdrdy[ENUM_BAND_NUM] = {0}; + static uint32_t au4FcsError[ENUM_BAND_NUM] = {0}; + static uint32_t au4OutOfResource[ENUM_BAND_NUM] = {0}; + static uint32_t au4LengthMismatch[ENUM_BAND_NUM] = {0}; + + au4MacMdrdy[ENUM_BAND_0] += htonl(g_HqaRxStat.MAC_Mdrdy); + au4MacMdrdy[ENUM_BAND_1] += htonl(g_HqaRxStat.MAC_Mdrdy1); + au4FcsError[ENUM_BAND_0] += htonl(g_HqaRxStat.MAC_FCS_Err); + au4FcsError[ENUM_BAND_1] += htonl(g_HqaRxStat.MAC_FCS_Err1); + au4OutOfResource[ENUM_BAND_0] += htonl(g_HqaRxStat.OutOfResource); + au4OutOfResource[ENUM_BAND_1] += htonl(g_HqaRxStat.OutOfResource1); + au4LengthMismatch[ENUM_BAND_0] += htonl( + g_HqaRxStat.LengthMismatchCount_B0); + au4LengthMismatch[ENUM_BAND_1] += htonl( + g_HqaRxStat.LengthMismatchCount_B1); + + if (fgResetCnt) { + kalMemZero(au4MacMdrdy, sizeof(au4MacMdrdy)); + kalMemZero(au4FcsError, sizeof(au4FcsError)); + kalMemZero(au4OutOfResource, sizeof(au4OutOfResource)); + kalMemZero(au4LengthMismatch, sizeof(au4LengthMismatch)); + } + + if (prAdapter->prAisBssInfo->prStaRecOfAP) + ucWlanIndex = + prAdapter->prAisBssInfo->prStaRecOfAP->ucWlanIndex; + else if (!wlanGetWlanIdxByAddress(prAdapter, NULL, &ucWlanIndex)) + fgWlanIdxFound = FALSE; + + if (fgWlanIdxFound) { + if (wlanGetStaIdxByWlanIdx(prAdapter, ucWlanIndex, &ucStaIdx) + == WLAN_STATUS_SUCCESS) { + u4RxVector0 = prAdapter->arStaRec[ucStaIdx].u4RxVector0; + u4RxVector2 = prAdapter->arStaRec[ucStaIdx].u4RxVector2; + u4RxVector3 = prAdapter->arStaRec[ucStaIdx].u4RxVector3; + u4RxVector4 = prAdapter->arStaRec[ucStaIdx].u4RxVector4; + } else{ + fgSkipRxV = TRUE; + } + } else{ + fgSkipRxV = TRUE; + } + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s", "\n\nRX Stat:\n"); +#if 0 + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "PER0", " = ", + g_HqaRxStat.PER0); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "PER1", " = ", + g_HqaRxStat.PER1); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RX OK0", " = ", + g_HqaRxStat.RXOK0); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RX OK1", " = ", + g_HqaRxStat.RXOK1); +#endif + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "MAC Mdrdy0", " = ", + au4MacMdrdy[ENUM_BAND_0]); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "MAC Mdrdy1", " = ", + au4MacMdrdy[ENUM_BAND_1]); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "FCS Err0", " = ", + au4FcsError[ENUM_BAND_0]); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "FCS Err1", " = ", + au4FcsError[ENUM_BAND_1]); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK PD Cnt B0", " = ", + htonl(g_HqaRxStat.CCK_PD)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK PD Cnt B1", " = ", + htonl(g_HqaRxStat.CCK_PD_Band1)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK SIG Err B0", " = ", + htonl(g_HqaRxStat.CCK_SIG_Err)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK SIG Err B1", " = ", + htonl(g_HqaRxStat.CCK_SIG_Err_Band1)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM PD Cnt B0", " = ", + htonl(g_HqaRxStat.OFDM_PD)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM PD Cnt B1", " = ", + htonl(g_HqaRxStat.OFDM_PD_Band1)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM TAG Error", " = ", + htonl(g_HqaRxStat.OFDM_TAG_Err)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK SFD Err B0", " = ", + htonl(g_HqaRxStat.CCK_SFD_Err)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK SFD Err B1", " = ", + htonl(g_HqaRxStat.CCK_SFD_Err_Band1)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM SIG Err B0", " = ", + htonl(g_HqaRxStat.OFDM_SIG_Err)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM SIG Err B1", " = ", + htonl(g_HqaRxStat.OFDM_SIG_Err_Band1)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK FCS Err B0", " = ", + htonl(g_HqaRxStat.FCSErr_CCK)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK FCS Err B1", " = ", + htonl(g_HqaRxStat.CCK_FCS_Err_Band1)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM FCS Err B0", " = ", + htonl(g_HqaRxStat.FCSErr_OFDM)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM FCS Err B1", " = ", + htonl(g_HqaRxStat.OFDM_FCS_Err_Band1)); + + if (!fgSkipRxV) { + u4FAGCRssiIBR0 = (u4RxVector2 & BITS(16, 23)) >> 16; + u4FAGCRssiWBR0 = (u4RxVector2 & BITS(24, 31)) >> 24; + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "FAGC RSSI W", " = ", + (u4FAGCRssiWBR0 >= 128) ? (u4FAGCRssiWBR0 - 256) : + (u4FAGCRssiWBR0)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "FAGC RSSI I", " = ", + (u4FAGCRssiIBR0 >= 128) ? (u4FAGCRssiIBR0 - 256) : + (u4FAGCRssiIBR0)); + } else{ + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "FAGC RSSI W", " = ", "N/A"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "FAGC RSSI I", " = ", "N/A"); + } + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK MDRDY B0", " = ", + htonl(g_HqaRxStat.PhyMdrdyCCK)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK MDRDY B1", " = ", + htonl(g_HqaRxStat.PHY_CCK_MDRDY_Band1)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM MDRDY B0", " = ", + htonl(g_HqaRxStat.PhyMdrdyOFDM)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM MDRDY B1", " = ", + htonl(g_HqaRxStat.PHY_OFDM_MDRDY_Band1)); + + if (!fgSkipRxV) { +#if 0 + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Driver RX Cnt0", " = ", + htonl(g_HqaRxStat.DriverRxCount)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Driver RX Cnt1", " = ", + htonl(g_HqaRxStat.DriverRxCount1)); +#endif + u4Value = (u4RxVector0 & BITS(12, 14)) >> 12; + if (u4Value == 0) { + u4Foe = (((u4RxVector4 & BITS(7, 31)) >> 7) & 0x7ff); + u4Foe = (u4Foe * 1000)>>11; + } else{ + cbw = ((u4RxVector0 & BITS(15, 16)) >> 15); + foe_const = ((1 << (cbw + 1)) & 0xf) * 10000; + u4Foe = (((u4RxVector4 & BITS(7, 31)) >> 7) & 0xfff); + u4Foe = (u4Foe * foe_const) >> 15; + } + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Freq Offset From RX", " = ", u4Foe); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RX SNR (dB)", " = ", + (uint32_t)(((u4RxVector4 & BITS(26, 31)) >> 26) - 16)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "uint8_t RX0", " = ", + (uint32_t)(u4RxVector3 & BITS(0, 7))); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "uint8_t RX1", " = ", + (uint32_t)((u4RxVector3 & BITS(8, 15)) >> 8)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "uint8_t RX2", " = ", + ((u4RxVector3 & BITS(16, 23)) >> 16) == 0xFF ? + (0) : ((uint32_t)(u4RxVector3 & BITS(16, 23)) >> 16)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "uint8_t RX3", " = ", + ((u4RxVector3 & BITS(24, 31)) >> 24) == 0xFF ? + (0) : ((uint32_t)(u4RxVector3 & BITS(24, 31)) >> 24)); + } else{ +#if 0 + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Driver RX Cnt0", + " = ", "N/A"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Driver RX Cnt1", + " = ", "N/A"); +#endif + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", + "Freq Offset From RX", + " = ", "N/A"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "RX SNR (dB)", + " = ", "N/A"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "uint8_t RX0", + " = ", "N/A"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "uint8_t RX1", + " = ", "N/A"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "uint8_t RX2", + " = ", "N/A"); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "uint8_t RX3", + " = ", "N/A"); + } + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Inst RSSI IB R0", " = ", + htonl(g_HqaRxStat.InstRssiIBR0)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Inst RSSI WB R0", " = ", + htonl(g_HqaRxStat.InstRssiWBR0)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Inst RSSI IB R1", " = ", + htonl(g_HqaRxStat.InstRssiIBR1)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Inst RSSI WB R1", " = ", + htonl(g_HqaRxStat.InstRssiWBR1)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Inst RSSI IB R2", " = ", + htonl(g_HqaRxStat.InstRssiIBR2)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Inst RSSI WB R2", " = ", + htonl(g_HqaRxStat.InstRssiWBR2)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Inst RSSI IB R3", " = ", + htonl(g_HqaRxStat.InstRssiIBR3)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Inst RSSI WB R3", " = ", + htonl(g_HqaRxStat.InstRssiWBR3)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "ACI Hit Lower", " = ", + htonl(g_HqaRxStat.ACIHitLower)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "ACI Hit Higher", + " = ", htonl(g_HqaRxStat.ACIHitUpper)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OutOf Resource Pkt0", + " = ", au4OutOfResource[ENUM_BAND_0]); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OutOf Resource Pkt1", + " = ", au4OutOfResource[ENUM_BAND_1]); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Len Mismatch Cnt B0", + " = ", au4LengthMismatch[ENUM_BAND_0]); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Len Mismatch Cnt B1", + " = ", au4LengthMismatch[ENUM_BAND_1]); +#if 0 + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "MU RX Cnt", " = ", + htonl(g_HqaRxStat.MRURxCount)); +#endif + return i4BytesWritten; +} + + +static int priv_driver_show_rx_stat(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + struct PARAM_CUSTOM_ACCESS_RX_STAT *prRxStatisticsTest; + u_int8_t fgResetCnt = FALSE; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + uint32_t u4Id = 0x99980000; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + DBGLOG(INIT, ERROR, "MT6632 : priv_driver_show_rx_stat\n"); + + if (i4Argc >= 2) { + if (strnicmp(apcArgv[1], CMD_STAT_RESET_CNT, + strlen(CMD_STAT_RESET_CNT)) == 0) + fgResetCnt = TRUE; + } + + if (i4Argc >= 1) { + if (fgResetCnt) { + rSwCtrlInfo.u4Id = u4Id; + rSwCtrlInfo.u4Data = 0; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } + + prRxStatisticsTest = + (struct PARAM_CUSTOM_ACCESS_RX_STAT *)kalMemAlloc( + sizeof(struct PARAM_CUSTOM_ACCESS_RX_STAT), + VIR_MEM_TYPE); + if (!prRxStatisticsTest) + return -1; + + prRxStatisticsTest->u4SeqNum = u4RxStatSeqNum; + prRxStatisticsTest->u4TotalNum = + sizeof(struct PARAM_RX_STAT) / 4; + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryRxStatistics, + prRxStatisticsTest, + sizeof(struct PARAM_CUSTOM_ACCESS_RX_STAT), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + kalMemFree(prRxStatisticsTest, VIR_MEM_TYPE, + sizeof(struct PARAM_CUSTOM_ACCESS_RX_STAT)); + return -1; + } + + i4BytesWritten = priv_driver_dump_rx_stat_info(prAdapter, + pcCommand, i4TotalLen, fgResetCnt); + + kalMemFree(prRxStatisticsTest, VIR_MEM_TYPE, + sizeof(struct PARAM_CUSTOM_ACCESS_RX_STAT)); + } + + return i4BytesWritten; +} + +static int priv_driver_get_ipi(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int32_t u4Ret = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + struct PARAM_GET_IPI_INFO_T rCmdGetIpiInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + kalMemZero(&rCmdGetIpiInfo, sizeof(struct PARAM_GET_IPI_INFO_T)); + + if (i4Argc >= 3) { + u4Ret = kalkStrtou32(apcArgv[1], 0, + &(rCmdGetIpiInfo.u4DurInSec)); + if (u4Ret) + DBGLOG(REQ, LOUD, + "parse get_ipi error (DurInSec) u4Ret=%d\n", + u4Ret); + + u4Ret = kalkStrtou32(apcArgv[2], 0, + &(rCmdGetIpiInfo.u4Interval)); + if (u4Ret) + DBGLOG(REQ, LOUD, + "parse get_ipi error (Interval) u4Ret=%d\n", + u4Ret); + + rStatus = kalIoctl(prGlueInfo, wlanoidGetIpiInfo, + &rCmdGetIpiInfo, sizeof(rCmdGetIpiInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } + + return i4BytesWritten; +} + +/*----------------------------------------------------------------------------*/ +/* + * @ The function will set policy of ACL. + * 0: disable ACL + * 1: enable accept list + * 2: enable deny list + * example: iwpriv p2p0 driver "set_acl_policy 1" + */ +/*----------------------------------------------------------------------------*/ +static int priv_driver_set_acl_policy(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct BSS_INFO *prBssInfo = NULL; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i4Argc = 0, i4BytesWritten = 0, i4Ret = 0, i4Policy = 0; + uint8_t ucRoleIdx = 0, ucBssIdx = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + /* get Bss Index from ndev */ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prNetDev, &ucRoleIdx) != 0) + return -1; + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) + return -1; + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + DBGLOG(REQ, LOUD, "ucRoleIdx %hhu ucBssIdx %hhu\n", ucRoleIdx, + ucBssIdx); + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc < 2) + return -1; + + i4Ret = kalkStrtou32(apcArgv[1], 0, &i4Policy); + if (i4Ret) { + DBGLOG(REQ, ERROR, "integer format error i4Ret=%d\n", i4Ret); + return -1; + } + + switch (i4Policy) { + case PARAM_CUSTOM_ACL_POLICY_DISABLE: + case PARAM_CUSTOM_ACL_POLICY_ACCEPT: + case PARAM_CUSTOM_ACL_POLICY_DENY: + prBssInfo->rACL.ePolicy = i4Policy; + break; + default: /*Invalid argument */ + DBGLOG(REQ, ERROR, "Invalid ACL Policy=%d\n", i4Policy); + return -1; + } + + DBGLOG(REQ, TRACE, "ucBssIdx[%hhu] ACL Policy=%d\n", ucBssIdx, + prBssInfo->rACL.ePolicy); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "ucBssIdx[%hhu] ACL Policy=%d\n", + ucBssIdx, prBssInfo->rACL.ePolicy); + + /* check if the change in ACL affects any existent association */ + if (prBssInfo->rACL.ePolicy != PARAM_CUSTOM_ACL_POLICY_DISABLE) + p2pRoleUpdateACLEntry(prAdapter, ucBssIdx); + + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + + return i4BytesWritten; +} /* priv_driver_set_acl_policy */ + +static int32_t priv_driver_inspect_mac_addr(IN char *pcMacAddr) +{ + int32_t i = 0; + + if (pcMacAddr == NULL) + return -1; + + for (i = 0; i < 17; i++) { + if ((i % 3 != 2) && (!kalIsXdigit(pcMacAddr[i]))) { + DBGLOG(REQ, ERROR, "[%c] is not hex digit\n", + pcMacAddr[i]); + return -1; + } + if ((i % 3 == 2) && (pcMacAddr[i] != ':')) { + DBGLOG(REQ, ERROR, "[%c]separate symbol is error\n", + pcMacAddr[i]); + return -1; + } + } + + if (pcMacAddr[17] != '\0') { + DBGLOG(REQ, ERROR, "no null-terminated character\n"); + return -1; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/* + * @ The function will add entry to ACL for accept or deny list. + * example: iwpriv p2p0 driver "add_acl_entry 01:02:03:04:05:06" + */ +/*----------------------------------------------------------------------------*/ +static int priv_driver_add_acl_entry(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct BSS_INFO *prBssInfo = NULL; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + uint8_t aucMacAddr[MAC_ADDR_LEN] = {0}; + int32_t i = 0, i4Argc = 0, i4BytesWritten = 0, i4Ret = 0; + uint8_t ucRoleIdx = 0, ucBssIdx = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + /* get Bss Index from ndev */ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prNetDev, &ucRoleIdx) != 0) + return -1; + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) + return -1; + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + DBGLOG(REQ, LOUD, "ucRoleIdx %hhu ucBssIdx %hhu\n", ucRoleIdx, + ucBssIdx); + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc < 2) + return -1; + + i4Ret = priv_driver_inspect_mac_addr(apcArgv[1]); + if (i4Ret) { + DBGLOG(REQ, ERROR, "inspect mac format error u4Ret=%d\n", + i4Ret); + return -1; + } + + i4Ret = sscanf(apcArgv[1], "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", + &aucMacAddr[0], &aucMacAddr[1], &aucMacAddr[2], + &aucMacAddr[3], &aucMacAddr[4], &aucMacAddr[5]); + + if (i4Ret != MAC_ADDR_LEN) { + DBGLOG(REQ, ERROR, "sscanf mac format fail u4Ret=%d\n", i4Ret); + return -1; + } + + for (i = 0; i <= prBssInfo->rACL.u4Num; i++) { + if (memcmp(prBssInfo->rACL.rEntry[i].aucAddr, &aucMacAddr, + MAC_ADDR_LEN) == 0) { + DBGLOG(REQ, ERROR, "add this mac [" MACSTR + "] is duplicate.\n", MAC2STR(aucMacAddr)); + return -1; + } + } + + if ((i < 1) || (i > MAX_NUMBER_OF_ACL)) { + DBGLOG(REQ, ERROR, "idx[%d] error or ACL is full.\n", i); + return -1; + } + + memcpy(prBssInfo->rACL.rEntry[i-1].aucAddr, &aucMacAddr, MAC_ADDR_LEN); + prBssInfo->rACL.u4Num = i; + DBGLOG(REQ, TRACE, "add mac addr [" MACSTR "] to ACL(%d).\n", + MAC2STR(prBssInfo->rACL.rEntry[i-1].aucAddr), i); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "add mac addr [" MACSTR "] to ACL(%d)\n", + MAC2STR(prBssInfo->rACL.rEntry[i-1].aucAddr), + i); + + /* Check if the change in ACL affects any existent association. */ + if (prBssInfo->rACL.ePolicy == PARAM_CUSTOM_ACL_POLICY_DENY) + p2pRoleUpdateACLEntry(prAdapter, ucBssIdx); + + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + + return i4BytesWritten; +} /* priv_driver_add_acl_entry */ + +/*----------------------------------------------------------------------------*/ +/* + * @ The function will delete entry to ACL for accept or deny list. + * example: iwpriv p2p0 driver "add_del_entry 01:02:03:04:05:06" + */ +/*----------------------------------------------------------------------------*/ +static int priv_driver_del_acl_entry(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct BSS_INFO *prBssInfo = NULL; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + uint8_t aucMacAddr[MAC_ADDR_LEN] = {0}; + int32_t i = 0, j = 0, i4Argc = 0, i4BytesWritten = 0, i4Ret = 0; + uint8_t ucRoleIdx = 0, ucBssIdx = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + /* get Bss Index from ndev */ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prNetDev, &ucRoleIdx) != 0) + return -1; + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) + return -1; + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + DBGLOG(REQ, LOUD, "ucRoleIdx %hhu ucBssIdx %hhu\n", ucRoleIdx, + ucBssIdx); + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc < 2) + return -1; + + i4Ret = priv_driver_inspect_mac_addr(apcArgv[1]); + if (i4Ret) { + DBGLOG(REQ, ERROR, "inspect mac format error u4Ret=%d\n", + i4Ret); + return -1; + } + + i4Ret = sscanf(apcArgv[1], "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", + &aucMacAddr[0], &aucMacAddr[1], &aucMacAddr[2], + &aucMacAddr[3], &aucMacAddr[4], &aucMacAddr[5]); + + if (i4Ret != MAC_ADDR_LEN) { + DBGLOG(REQ, ERROR, "sscanf mac format fail u4Ret=%d\n", i4Ret); + return -1; + } + + for (i = 0; i < prBssInfo->rACL.u4Num; i++) { + if (memcmp(prBssInfo->rACL.rEntry[i].aucAddr, &aucMacAddr, + MAC_ADDR_LEN) == 0) { + memset(&prBssInfo->rACL.rEntry[i], 0x00, + sizeof(struct PARAM_CUSTOM_ACL_ENTRY)); + DBGLOG(REQ, TRACE, "delete this mac [" MACSTR "]\n", + MAC2STR(aucMacAddr)); + + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "delete this mac [" MACSTR "] from ACL(%d)\n", + MAC2STR(aucMacAddr), i+1); + break; + } + } + + if ((prBssInfo->rACL.u4Num == 0) || (i == MAX_NUMBER_OF_ACL)) { + DBGLOG(REQ, ERROR, "delete entry fail, num of entries=%d\n", i); + return -1; + } + + for (j = i+1; j < prBssInfo->rACL.u4Num; j++) + memcpy(prBssInfo->rACL.rEntry[j-1].aucAddr, + prBssInfo->rACL.rEntry[j].aucAddr, MAC_ADDR_LEN); + + prBssInfo->rACL.u4Num = j-1; + memset(prBssInfo->rACL.rEntry[j-1].aucAddr, 0x00, MAC_ADDR_LEN); + + /* check if the change in ACL affects any existent association */ + if (prBssInfo->rACL.ePolicy == PARAM_CUSTOM_ACL_POLICY_ACCEPT) + p2pRoleUpdateACLEntry(prAdapter, ucBssIdx); + + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + + return i4BytesWritten; +} /* priv_driver_del_acl_entry */ + +/*----------------------------------------------------------------------------*/ +/* + * @ The function will show all entries to ACL for accept or deny list. + * example: iwpriv p2p0 driver "show_acl_entry" + */ +/*----------------------------------------------------------------------------*/ +static int priv_driver_show_acl_entry(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct BSS_INFO *prBssInfo = NULL; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i = 0, i4Argc = 0, i4BytesWritten = 0; + uint8_t ucRoleIdx = 0, ucBssIdx = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + /* get Bss Index from ndev */ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prNetDev, &ucRoleIdx) != 0) + return -1; + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) + return -1; + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + DBGLOG(REQ, TRACE, "ACL Policy = %d\n", prBssInfo->rACL.ePolicy); + DBGLOG(REQ, TRACE, "Total ACLs = %d\n", prBssInfo->rACL.u4Num); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "ACL Policy = %d, Total ACLs = %d\n", + prBssInfo->rACL.ePolicy, + prBssInfo->rACL.u4Num); + + for (i = 0; i < prBssInfo->rACL.u4Num; i++) { + DBGLOG(REQ, TRACE, "ACL(%d): [" MACSTR "]\n", i+1, + MAC2STR(prBssInfo->rACL.rEntry[i].aucAddr)); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "ACL(%d): [" MACSTR + "]\n", i+1, MAC2STR(prBssInfo->rACL.rEntry[i].aucAddr)); + } + + return i4BytesWritten; +} /* priv_driver_show_acl_entry */ + +/*----------------------------------------------------------------------------*/ +/* + * @ The function will clear all entries to ACL for accept or deny list. + * example: iwpriv p2p0 driver "clear_acl_entry" + */ +/*----------------------------------------------------------------------------*/ +static int priv_driver_clear_acl_entry(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct BSS_INFO *prBssInfo = NULL; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i4Argc = 0, i4BytesWritten = 0; + uint8_t ucRoleIdx = 0, ucBssIdx = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + /* get Bss Index from ndev */ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prNetDev, &ucRoleIdx) != 0) + return -1; + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) + return -1; + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (prBssInfo->rACL.u4Num) { + memset(&prBssInfo->rACL.rEntry[0], 0x00, + sizeof(struct PARAM_CUSTOM_ACL_ENTRY) * MAC_ADDR_LEN); + prBssInfo->rACL.u4Num = 0; + } + + DBGLOG(REQ, TRACE, "ACL Policy = %d\n", prBssInfo->rACL.ePolicy); + DBGLOG(REQ, TRACE, "Total ACLs = %d\n", prBssInfo->rACL.u4Num); + + i4BytesWritten += kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "ACL Policy = %d, Total ACLs = %d\n", + prBssInfo->rACL.ePolicy, + prBssInfo->rACL.u4Num); + + /* check if the change in ACL affects any existent association */ + if (prBssInfo->rACL.ePolicy == PARAM_CUSTOM_ACL_POLICY_ACCEPT) + p2pRoleUpdateACLEntry(prAdapter, ucBssIdx); + + return i4BytesWritten; +} /* priv_driver_clear_acl_entry */ + +static int priv_driver_get_drv_mcr(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + uint32_t u4Ret; + + /* Add Antenna Selection Input */ + /* INT_32 i4ArgNum_with_ant_sel = 3; */ + + int32_t i4ArgNum = 2; + + struct CMD_ACCESS_REG rCmdAccessReg; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rCmdAccessReg.u4Address)); + if (u4Ret) + DBGLOG(REQ, LOUD, + "parse get_drv_mcr error (Address) u4Ret=%d\n", + u4Ret); + + /* rCmdAccessReg.u4Address = kalStrtoul(apcArgv[1], NULL, 0); */ + rCmdAccessReg.u4Data = 0; + + DBGLOG(REQ, LOUD, "address is %x\n", rCmdAccessReg.u4Address); + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryDrvMcrRead, + &rCmdAccessReg, sizeof(rCmdAccessReg), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "0x%08x", + (unsigned int)rCmdAccessReg.u4Data); + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, + pcCommand); + } + + return i4BytesWritten; + +} /* priv_driver_get_drv_mcr */ + +int priv_driver_set_drv_mcr(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Ret; + + /* Add Antenna Selection Input */ + /* INT_32 i4ArgNum_with_ant_sel = 4; */ + + int32_t i4ArgNum = 3; + + struct CMD_ACCESS_REG rCmdAccessReg; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rCmdAccessReg.u4Address)); + if (u4Ret) + DBGLOG(REQ, LOUD, + "parse get_drv_mcr error (Address) u4Ret=%d\n", + u4Ret); + + u4Ret = kalkStrtou32(apcArgv[2], 0, &(rCmdAccessReg.u4Data)); + if (u4Ret) + DBGLOG(REQ, LOUD, + "parse get_drv_mcr error (Data) u4Ret=%d\n", + u4Ret); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetDrvMcrWrite, + &rCmdAccessReg, sizeof(rCmdAccessReg), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + } + + return i4BytesWritten; + +} + +static int priv_driver_get_sw_ctrl(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t u4Ret = 0; + + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= 2) { + /* rSwCtrlInfo.u4Id = kalStrtoul(apcArgv[1], NULL, 0); */ + rSwCtrlInfo.u4Data = 0; + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rSwCtrlInfo.u4Id)); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse rSwCtrlInfo error u4Ret=%d\n", + u4Ret); + + DBGLOG(REQ, LOUD, "id is %x\n", rSwCtrlInfo.u4Id); + + rStatus = kalIoctl(prGlueInfo, wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "0x%08x", + (unsigned int)rSwCtrlInfo.u4Data); + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, + pcCommand); + } + + return i4BytesWritten; + +} /* priv_driver_get_sw_ctrl */ + + +int priv_driver_set_sw_ctrl(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t u4Ret = 0; + + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= 3) { + /* rSwCtrlInfo.u4Id = kalStrtoul(apcArgv[1], NULL, 0); + * rSwCtrlInfo.u4Data = kalStrtoul(apcArgv[2], NULL, 0); + */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rSwCtrlInfo.u4Id)); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse rSwCtrlInfo error u4Ret=%d\n", + u4Ret); + u4Ret = kalkStrtou32(apcArgv[2], 0, &(rSwCtrlInfo.u4Data)); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse rSwCtrlInfo error u4Ret=%d\n", + u4Ret); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + } + + return i4BytesWritten; + +} /* priv_driver_set_sw_ctrl */ + + + +int priv_driver_set_fixed_rate(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + /* INT_32 u4Ret = 0; */ + uint32_t u4WCID = 0; + uint32_t u4Mode = 0, u4Bw = 0, u4Mcs = 0, u4VhtNss = 0; + uint32_t u4SGI = 0, u4Preamble = 0, u4STBC = 0, u4LDPC = 0, u4SpeEn = 0; + int32_t i4Recv = 0; + int8_t *this_char = NULL; + uint32_t u4Id = 0xa0610000; + uint32_t u4Data = 0x80000000; + uint32_t u4Id2 = 0xa0600000; + uint8_t u4Nsts = 1; + u_int8_t fgStatus = TRUE; + static uint8_t fgIsUseWCID = FALSE; + + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %d, apcArgv[0] = %s\n\n", i4Argc, *apcArgv); + + this_char = kalStrStr(*apcArgv, "="); + if (!this_char) + return -1; + this_char++; + + DBGLOG(REQ, LOUD, "string = %s\n", this_char); + + if (strnicmp(this_char, "auto", strlen("auto")) == 0) { + i4Recv = 1; + } else if (strnicmp(this_char, "UseWCID", strlen("UseWCID")) == 0) { + i4Recv = 2; + fgIsUseWCID = TRUE; + } else if (strnicmp(this_char, "ApplyAll", strlen("ApplyAll")) == 0) { + i4Recv = 3; + fgIsUseWCID = FALSE; + } else { + i4Recv = sscanf(this_char, "%d-%d-%d-%d-%d-%d-%d-%d-%d-%d", + &(u4WCID), &(u4Mode), &(u4Bw), &(u4Mcs), + &(u4VhtNss), &(u4SGI), &(u4Preamble), &(u4STBC), + &(u4LDPC), &(u4SpeEn)); + + DBGLOG(REQ, LOUD, "u4WCID=%d\nu4Mode=%d\nu4Bw=%d\n", u4WCID, + u4Mode, u4Bw); + DBGLOG(REQ, LOUD, "u4Mcs=%d\nu4VhtNss=%d\nu4SGI=%d\n", u4Mcs, + u4VhtNss, u4SGI); + DBGLOG(REQ, LOUD, "u4Preamble=%d\nu4STBC=%d\n", u4Preamble, + u4STBC); + DBGLOG(REQ, LOUD, "u4LDPC=%d\nu4SpeEn=%d\nfgIsUseWCID=%d\n", + u4LDPC, u4SpeEn, fgIsUseWCID); + } + + if (i4Recv == 1) { + rSwCtrlInfo.u4Id = u4Id2; + rSwCtrlInfo.u4Data = 0; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } else if (i4Recv == 2 || i4Recv == 3) { + i4BytesWritten = snprintf(pcCommand, i4TotalLen, + "Update fgIsUseWCID %d\n", fgIsUseWCID); + } else if (i4Recv == 10) { + rSwCtrlInfo.u4Id = u4Id; + rSwCtrlInfo.u4Data = u4Data; + + if (fgIsUseWCID && u4WCID < WTBL_SIZE && + prAdapter->rWifiVar.arWtbl[u4WCID].ucUsed) { + rSwCtrlInfo.u4Id |= u4WCID; + rSwCtrlInfo.u4Id |= BIT(8); + i4BytesWritten = snprintf( + pcCommand, i4TotalLen, + "Apply WCID %d\n", u4WCID); + } else { + i4BytesWritten = snprintf( + pcCommand, i4TotalLen, "Apply All\n"); + } + + if (u4SGI) + rSwCtrlInfo.u4Data |= BIT(30); + if (u4LDPC) + rSwCtrlInfo.u4Data |= BIT(29); + if (u4SpeEn) + rSwCtrlInfo.u4Data |= BIT(28); + if (u4STBC) + rSwCtrlInfo.u4Data |= BIT(11); + + if (u4Bw <= 3) + rSwCtrlInfo.u4Data |= ((u4Bw << 26) & BITS(26, 27)); + else { + fgStatus = FALSE; + DBGLOG(INIT, ERROR, + "Wrong BW! BW20=0, BW40=1, BW80=2,BW160=3\n"); + } + if (u4Mode <= 4) { + rSwCtrlInfo.u4Data |= ((u4Mode << 6) & BITS(6, 8)); + + switch (u4Mode) { + case 0: + if (u4Mcs <= 3) + rSwCtrlInfo.u4Data |= u4Mcs; + else { + fgStatus = FALSE; + DBGLOG(INIT, ERROR, + "CCK mode but wrong MCS!\n"); + } + + if (u4Preamble) + rSwCtrlInfo.u4Data |= BIT(2); + else + rSwCtrlInfo.u4Data &= ~BIT(2); + break; + case 1: + switch (u4Mcs) { + case 0: + /* 6'b001011 */ + rSwCtrlInfo.u4Data |= 11; + break; + case 1: + /* 6'b001111 */ + rSwCtrlInfo.u4Data |= 15; + break; + case 2: + /* 6'b001010 */ + rSwCtrlInfo.u4Data |= 10; + break; + case 3: + /* 6'b001110 */ + rSwCtrlInfo.u4Data |= 14; + break; + case 4: + /* 6'b001001 */ + rSwCtrlInfo.u4Data |= 9; + break; + case 5: + /* 6'b001101 */ + rSwCtrlInfo.u4Data |= 13; + break; + case 6: + /* 6'b001000 */ + rSwCtrlInfo.u4Data |= 8; + break; + case 7: + /* 6'b001100 */ + rSwCtrlInfo.u4Data |= 12; + break; + default: + fgStatus = FALSE; + DBGLOG(INIT, ERROR, + "OFDM mode but wrong MCS!\n"); + break; + } + break; + case 2: + case 3: + if (u4Mcs <= 32) + rSwCtrlInfo.u4Data |= u4Mcs; + else { + fgStatus = FALSE; + DBGLOG(INIT, ERROR, + "HT mode but wrong MCS!\n"); + } + + if (u4Mcs != 32) { + u4Nsts += (u4Mcs >> 3); + if (u4STBC && (u4Nsts == 1)) + u4Nsts++; + } + break; + case 4: + if (u4Mcs <= 9) + rSwCtrlInfo.u4Data |= u4Mcs; + else { + fgStatus = FALSE; + DBGLOG(INIT, ERROR, + "VHT mode but wrong MCS!\n"); + } + if (u4STBC && (u4VhtNss == 1)) + u4Nsts++; + else + u4Nsts = u4VhtNss; + break; + default: + break; + } + } else { + fgStatus = FALSE; + DBGLOG(INIT, ERROR, + "Wrong TxMode! CCK=0, OFDM=1, HT=2, GF=3, VHT=4\n"); + } + + rSwCtrlInfo.u4Data |= (((u4Nsts - 1) << 9) & BITS(9, 10)); + + if (fgStatus) { + rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + FALSE, FALSE, TRUE, &u4BufLen); + } + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } else { + DBGLOG(INIT, ERROR, "iwpriv wlanXX driver FixedRate=Option\n"); + DBGLOG(INIT, ERROR, + "Option:[WCID]-[Mode]-[BW]-[MCS]-[VhtNss]-[SGI]-[Preamble]-[STBC]-[LDPC]-[SPE_EN]\n"); + DBGLOG(INIT, ERROR, "[WCID]Wireless Client ID\n"); + DBGLOG(INIT, ERROR, "[Mode]CCK=0, OFDM=1, HT=2, GF=3, VHT=4\n"); + DBGLOG(INIT, ERROR, "[BW]BW20=0, BW40=1, BW80=2,BW160=3\n"); + DBGLOG(INIT, ERROR, + "[MCS]CCK=0~3, OFDM=0~7, HT=0~32, VHT=0~9\n"); + DBGLOG(INIT, ERROR, "[VhtNss]VHT=1~4, Other=ignore\n"); + DBGLOG(INIT, ERROR, "[Preamble]Long=0, Other=Short\n"); + } + + return i4BytesWritten; +} /* priv_driver_set_fixed_rate */ + +int priv_driver_set_cfg(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + + struct PARAM_CUSTOM_KEY_CFG_STRUCT rKeyCfgInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rKeyCfgInfo, sizeof(rKeyCfgInfo)); + + if (i4Argc >= 3) { + + int8_t ucTmp[WLAN_CFG_VALUE_LEN_MAX]; + uint8_t *pucCurrBuf = ucTmp; + uint8_t i = 0; + uint32_t offset = 0; + + pucCurrBuf = ucTmp; + kalMemZero(ucTmp, WLAN_CFG_VALUE_LEN_MAX); + + if (i4Argc == 3) { + /* no space for it, driver can't accept space in the end + * of the line + */ + /* ToDo: skip the space when parsing */ + u4BufLen = kalStrLen(apcArgv[2]); + if (offset + u4BufLen > WLAN_CFG_VALUE_LEN_MAX - 1) { + DBGLOG(INIT, ERROR, + "apcArgv[2] length [%d] overrun\n", + u4BufLen); + return -1; + } + kalMemCopy(pucCurrBuf + offset, apcArgv[2], u4BufLen); + offset += u4BufLen; + } else { + for (i = 2; i < i4Argc; i++) { + u4BufLen = kalStrLen(apcArgv[i]); + if (offset + u4BufLen > + WLAN_CFG_VALUE_LEN_MAX - 1) { + DBGLOG(INIT, ERROR, + "apcArgv[%d] length [%d] overrun\n", + i, u4BufLen); + return -1; + } + kalMemCopy(pucCurrBuf + offset, apcArgv[i], + u4BufLen); + offset += u4BufLen; + } + } + + DBGLOG(INIT, WARN, "Update to driver temp buffer as [%s]\n", + ucTmp); + + /* wlanCfgSet(prAdapter, apcArgv[1], apcArgv[2], 0); */ + /* Call by wlanoid because the set_cfg will trigger callback */ + kalMemCopy(rKeyCfgInfo.aucKey, apcArgv[1], + WLAN_CFG_KEY_LEN_MAX); + kalStrnCpy(rKeyCfgInfo.aucValue, ucTmp, WLAN_CFG_KEY_LEN_MAX); + rStatus = kalIoctl(prGlueInfo, wlanoidSetKeyCfg, &rKeyCfgInfo, + sizeof(rKeyCfgInfo), FALSE, FALSE, TRUE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } + + return i4BytesWritten; + +} /* priv_driver_set_cfg */ + +int priv_driver_get_cfg(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int8_t aucValue[WLAN_CFG_VALUE_LEN_MAX]; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + prAdapter = prGlueInfo->prAdapter; + + if (i4Argc >= 2) { + /* by wlanoid ? */ + if (wlanCfgGet(prAdapter, apcArgv[1], aucValue, "", 0) == + WLAN_STATUS_SUCCESS) { + kalStrnCpy(pcCommand, aucValue, WLAN_CFG_VALUE_LEN_MAX); + i4BytesWritten = kalStrnLen(pcCommand, + WLAN_CFG_VALUE_LEN_MAX); + } + } + + return i4BytesWritten; + +} /* priv_driver_get_cfg */ + +int priv_driver_set_chip_config(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + uint32_t u4CmdLen = 0; + uint32_t u4PrefixLen = 0; + /* INT_32 i4Argc = 0; */ + /* PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = {0}; */ + + struct PARAM_CUSTOM_CHIP_CONFIG_STRUCT rChipConfigInfo = {0}; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + /* wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); */ + /* DBGLOG(REQ, LOUD,("argc is %i\n",i4Argc)); */ + /* */ + u4CmdLen = kalStrnLen(pcCommand, i4TotalLen); + u4PrefixLen = kalStrLen(CMD_SET_CHIP) + 1 /*space */; + + kalMemZero(&rChipConfigInfo, sizeof(rChipConfigInfo)); + + /* if(i4Argc >= 2) { */ + if (u4CmdLen > u4PrefixLen) { + rChipConfigInfo.ucType = CHIP_CONFIG_TYPE_WO_RESPONSE; + /* rChipConfigInfo.u2MsgSize = kalStrnLen(apcArgv[1], + * CHIP_CONFIG_RESP_SIZE); + */ + rChipConfigInfo.u2MsgSize = u4CmdLen - u4PrefixLen; + /* kalStrnCpy(rChipConfigInfo.aucCmd, apcArgv[1], + * CHIP_CONFIG_RESP_SIZE); + */ + kalStrnCpy(rChipConfigInfo.aucCmd, pcCommand + u4PrefixLen, + CHIP_CONFIG_RESP_SIZE - 1); + rChipConfigInfo.aucCmd[CHIP_CONFIG_RESP_SIZE - 1] = '\0'; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetChipConfig, + &rChipConfigInfo, sizeof(rChipConfigInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, INFO, "%s: kalIoctl ret=%d\n", __func__, + rStatus); + i4BytesWritten = -1; + } + } + + return i4BytesWritten; + +} /* priv_driver_set_chip_config */ + +void +priv_driver_get_chip_config_16(uint8_t *pucStartAddr, uint32_t u4Length, + uint32_t u4Line, int i4TotalLen, + int32_t i4BytesWritten, char *pcCommand) +{ + + while (u4Length >= 16) { + if (i4TotalLen > i4BytesWritten) { + i4BytesWritten += + snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%04x %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x %02x %02x %02x\n", + u4Line, 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]); + } + + pucStartAddr += 16; + u4Length -= 16; + u4Line += 16; + } /* u4Length */ +} + + +void +priv_driver_get_chip_config_4(uint32_t *pu4StartAddr, uint32_t u4Length, + uint32_t u4Line, int i4TotalLen, + int32_t i4BytesWritten, char *pcCommand) +{ + while (u4Length >= 16) { + if (i4TotalLen > i4BytesWritten) { + i4BytesWritten += + snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%04x %08x %08x %08x %08x\n", u4Line, + pu4StartAddr[0], pu4StartAddr[1], + pu4StartAddr[2], pu4StartAddr[3]); + } + + pu4StartAddr += 4; + u4Length -= 16; + u4Line += 4; + } /* u4Length */ +} + +int priv_driver_get_chip_config(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + int32_t i4BytesWritten = 0; + uint32_t u4BufLen = 0; + uint32_t u2MsgSize = 0; + uint32_t u4CmdLen = 0; + uint32_t u4PrefixLen = 0; + /* INT_32 i4Argc = 0; */ + /* PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; */ + + struct PARAM_CUSTOM_CHIP_CONFIG_STRUCT rChipConfigInfo = {0}; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + /* wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); */ + /* DBGLOG(REQ, LOUD,("argc is %i\n",i4Argc)); */ + + u4CmdLen = kalStrnLen(pcCommand, i4TotalLen); + u4PrefixLen = kalStrLen(CMD_GET_CHIP) + 1 /*space */; + + /* if(i4Argc >= 2) { */ + if (u4CmdLen > u4PrefixLen) { + rChipConfigInfo.ucType = CHIP_CONFIG_TYPE_ASCII; + /* rChipConfigInfo.u2MsgSize = kalStrnLen(apcArgv[1], + * CHIP_CONFIG_RESP_SIZE); + */ + rChipConfigInfo.u2MsgSize = u4CmdLen - u4PrefixLen; + /* kalStrnCpy(rChipConfigInfo.aucCmd, apcArgv[1], + * CHIP_CONFIG_RESP_SIZE); + */ + kalStrnCpy(rChipConfigInfo.aucCmd, pcCommand + u4PrefixLen, + CHIP_CONFIG_RESP_SIZE - 1); + rChipConfigInfo.aucCmd[CHIP_CONFIG_RESP_SIZE - 1] = '\0'; + rStatus = kalIoctl(prGlueInfo, wlanoidQueryChipConfig, + &rChipConfigInfo, sizeof(rChipConfigInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, INFO, "%s: kalIoctl ret=%d\n", __func__, + rStatus); + return -1; + } + + /* Check respType */ + u2MsgSize = rChipConfigInfo.u2MsgSize; + DBGLOG(REQ, INFO, "%s: RespTyep %u\n", __func__, + rChipConfigInfo.ucRespType); + DBGLOG(REQ, INFO, "%s: u2MsgSize %u\n", __func__, + rChipConfigInfo.u2MsgSize); + + if (u2MsgSize > sizeof(rChipConfigInfo.aucCmd)) { + DBGLOG(REQ, INFO, "%s: u2MsgSize error ret=%u\n", + __func__, rChipConfigInfo.u2MsgSize); + return -1; + } + + if (u2MsgSize > 0) { + + if (rChipConfigInfo.ucRespType == + CHIP_CONFIG_TYPE_ASCII) { + i4BytesWritten = + snprintf(pcCommand + i4BytesWritten, + i4TotalLen, "%s", + rChipConfigInfo.aucCmd); + } else { + uint32_t u4Length; + uint32_t u4Line; + + if (rChipConfigInfo.ucRespType == + CHIP_CONFIG_TYPE_MEM8) { + uint8_t *pucStartAddr = NULL; + + pucStartAddr = (uint8_t *) + rChipConfigInfo.aucCmd; + /* align 16 bytes because one print line + * is 16 bytes + */ + u4Length = (((u2MsgSize + 15) >> 4)) + << 4; + u4Line = 0; + priv_driver_get_chip_config_16( + pucStartAddr, u4Length, u4Line, + i4TotalLen, i4BytesWritten, + pcCommand); + } else { + uint32_t *pu4StartAddr = NULL; + + pu4StartAddr = (uint32_t *) + rChipConfigInfo.aucCmd; + /* align 16 bytes because one print line + * is 16 bytes + */ + u4Length = (((u2MsgSize + 15) >> 4)) + << 4; + u4Line = 0; + + if (IS_ALIGN_4( + (unsigned long) pu4StartAddr)) { + priv_driver_get_chip_config_4( + pu4StartAddr, u4Length, + u4Line, i4TotalLen, + i4BytesWritten, + pcCommand); + } else { + DBGLOG(REQ, INFO, + "%s: rChipConfigInfo.aucCmd is not 4 bytes alignment %p\n", + __func__, + rChipConfigInfo.aucCmd); + } + } /* ChipConfigInfo.ucRespType */ + } + } + /* u2MsgSize > 0 */ + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, + pcCommand); + } + /* i4Argc */ + return i4BytesWritten; + +} /* priv_driver_get_chip_config */ + + + +int priv_driver_set_ap_start(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + + struct PARAM_CUSTOM_P2P_SET_STRUCT rSetP2P; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Ret; + int32_t i4ArgNum = 2; + + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rSetP2P.u4Mode)); + if (u4Ret) + DBGLOG(REQ, LOUD, + "parse ap-start error (u4Enable) u4Ret=%d\n", + u4Ret); + + if (rSetP2P.u4Mode >= RUNNING_P2P_MODE_NUM) { + rSetP2P.u4Mode = 0; + rSetP2P.u4Enable = 0; + } else + rSetP2P.u4Enable = 1; + + set_p2p_mode_handler(prNetDev, rSetP2P); + } + + return 0; +} + +int priv_driver_get_linkspeed(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + uint32_t u4Rate = 0; + uint32_t u4LinkSpeed = 0; + int32_t i4BytesWritten = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (!netif_carrier_ok(prNetDev)) + return -1; + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryLinkSpeed, &u4Rate, + sizeof(u4Rate), TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + u4LinkSpeed = u4Rate * 100; + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "LinkSpeed %u", + (unsigned int)u4LinkSpeed); + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + return i4BytesWritten; + +} /* priv_driver_get_linkspeed */ + +int priv_driver_set_band(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct ADAPTER *prAdapter = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Argc = 0; + uint32_t ucBand = 0; + uint8_t ucBssIndex; + enum ENUM_BAND eBand = BAND_NULL; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t u4Ret = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + prAdapter = prGlueInfo->prAdapter; + if (i4Argc >= 2) { + /* ucBand = kalStrtoul(apcArgv[1], NULL, 0); */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &ucBand); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse ucBand error u4Ret=%d\n", + u4Ret); + + ucBssIndex = wlanGetAisBssIndex(prGlueInfo->prAdapter); + eBand = BAND_NULL; + if (ucBand == CMD_BAND_5G) + eBand = BAND_5G; + else if (ucBand == CMD_BAND_2G) + eBand = BAND_2G4; + prAdapter->aePreferBand[ucBssIndex] = eBand; + /* XXX call wlanSetPreferBandByNetwork directly in different + * thread + */ + /* wlanSetPreferBandByNetwork (prAdapter, eBand, ucBssIndex); */ + } + + return 0; +} + +int priv_driver_set_txpower(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + struct SET_TXPWR_CTRL *prTxpwr; + uint16_t i; + int32_t u4Ret = 0; + int32_t ai4Setting[4]; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + prTxpwr = &prGlueInfo->rTxPwr; + + if (i4Argc >= 3 && i4Argc <= 5) { + for (i = 0; i < (i4Argc - 1); i++) { + /* ai4Setting[i] = kalStrtol(apcArgv[i + 1], NULL, 0); + */ + u4Ret = kalkStrtos32(apcArgv[i + 1], 0, + &(ai4Setting[i])); + if (u4Ret) + DBGLOG(REQ, LOUD, + "parse apcArgv error u4Ret=%d\n", u4Ret); + } + } else { + DBGLOG(REQ, INFO, "set_txpower wrong argc : %d\n", i4Argc); + return -1; + } + + /* + * ai4Setting[0] + * 0 : Set TX power offset for specific network + * 1 : Set TX power offset policy when multiple networks are in the + * same channel + * 2 : Set TX power limit for specific channel in 2.4GHz band + * 3 : Set TX power limit of specific sub-band in 5GHz band + * 4 : Enable or reset setting + */ + if (ai4Setting[0] == 0 && (i4Argc - 1) == 4 /* argc num */) { + /* ai4Setting[1] : 0 (All networks), 1 (legacy STA), + * 2 (Hotspot AP), 3 (P2P), 4 (BT over Wi-Fi) + * ai4Setting[2] : 0 (All bands),1 (2.4G), 2 (5G) + * ai4Setting[3] : -30 ~ 20 in unit of 0.5dBm (default: 0) + */ + if (ai4Setting[1] == 1 || ai4Setting[1] == 0) { + if (ai4Setting[2] == 0 || ai4Setting[2] == 1) + prTxpwr->c2GLegacyStaPwrOffset = ai4Setting[3]; + if (ai4Setting[2] == 0 || ai4Setting[2] == 2) + prTxpwr->c5GLegacyStaPwrOffset = ai4Setting[3]; + } + if (ai4Setting[1] == 2 || ai4Setting[1] == 0) { + if (ai4Setting[2] == 0 || ai4Setting[2] == 1) + prTxpwr->c2GHotspotPwrOffset = ai4Setting[3]; + if (ai4Setting[2] == 0 || ai4Setting[2] == 2) + prTxpwr->c5GHotspotPwrOffset = ai4Setting[3]; + } + if (ai4Setting[1] == 3 || ai4Setting[1] == 0) { + if (ai4Setting[2] == 0 || ai4Setting[2] == 1) + prTxpwr->c2GP2pPwrOffset = ai4Setting[3]; + if (ai4Setting[2] == 0 || ai4Setting[2] == 2) + prTxpwr->c5GP2pPwrOffset = ai4Setting[3]; + } + if (ai4Setting[1] == 4 || ai4Setting[1] == 0) { + if (ai4Setting[2] == 0 || ai4Setting[2] == 1) + prTxpwr->c2GBowPwrOffset = ai4Setting[3]; + if (ai4Setting[2] == 0 || ai4Setting[2] == 2) + prTxpwr->c5GBowPwrOffset = ai4Setting[3]; + } + } else if (ai4Setting[0] == 1 && (i4Argc - 1) == 2) { + /* ai4Setting[1] : 0 (highest power is used) (default), + * 1 (lowest power is used) + */ + prTxpwr->ucConcurrencePolicy = ai4Setting[1]; + } else if (ai4Setting[0] == 2 && (i4Argc - 1) == 3) { + /* ai4Setting[1] : 0 (all channels in 2.4G), 1~14 */ + /* ai4Setting[2] : 10 ~ 46 in unit of 0.5dBm (default: 46) */ + if (ai4Setting[1] == 0) { + for (i = 0; i < 14; i++) + prTxpwr->acTxPwrLimit2G[i] = ai4Setting[2]; + } else if (ai4Setting[1] <= 14) + prTxpwr->acTxPwrLimit2G[ai4Setting[1] - 1] = + ai4Setting[2]; + } else if (ai4Setting[0] == 3 && (i4Argc - 1) == 3) { + /* ai4Setting[1] : 0 (all sub-bands in 5G), + * 1 (5000 ~ 5250MHz), + * 2 (5255 ~ 5350MHz), + * 3 (5355 ~ 5725MHz), + * 4 (5730 ~ 5825MHz) + */ + /* ai4Setting[2] : 10 ~ 46 in unit of 0.5dBm (default: 46) */ + if (ai4Setting[1] == 0) { + for (i = 0; i < 4; i++) + prTxpwr->acTxPwrLimit5G[i] = ai4Setting[2]; + } else if (ai4Setting[1] <= 4) + prTxpwr->acTxPwrLimit5G[ai4Setting[1] - 1] = + ai4Setting[2]; + } else if (ai4Setting[0] == 4 && (i4Argc - 1) == 2) { + /* ai4Setting[1] : 1 (enable), 0 (reset and disable) */ + if (ai4Setting[1] == 0) + wlanDefTxPowerCfg(prGlueInfo->prAdapter); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetTxPower, prTxpwr, + sizeof(struct SET_TXPWR_CTRL), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } else + return -EFAULT; + + return 0; +} + +int priv_driver_set_country(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + uint8_t aucCountry[2]; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (regd_is_single_sku_en()) { + uint8_t aucCountry_code[4] = {0, 0, 0, 0}; + uint8_t i, count; + + /* command like "COUNTRY US", "COUNTRY US1" and + * "COUNTRY US01" + */ + count = kalStrnLen(apcArgv[1], sizeof(aucCountry_code)); + for (i = 0; i < count; i++) + aucCountry_code[i] = apcArgv[1][i]; + + + rStatus = kalIoctl(prGlueInfo, wlanoidSetCountryCode, + &aucCountry_code[0], count, + FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + return 0; + } + + + if (i4Argc >= 2) { + /* command like "COUNTRY US", "COUNTRY EU" and "COUNTRY JP" */ + aucCountry[0] = apcArgv[1][0]; + aucCountry[1] = apcArgv[1][1]; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetCountryCode, + &aucCountry[0], 2, FALSE, FALSE, TRUE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } + return 0; +} + +int priv_driver_set_csa(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + uint32_t ch_num = 0; + uint32_t u4Ret = 0; + uint8_t ucRoleIdx = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, INFO, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, INFO, "argc is %i\n", i4Argc); + + if (i4Argc >= 2) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &ch_num); + u4Ret = cnmIdcCsaReq(prGlueInfo->prAdapter, ch_num, ucRoleIdx); + DBGLOG(REQ, INFO, "u4Ret is %d\n", u4Ret); + } else { + DBGLOG(REQ, INFO, "Input insufficent\n"); + } + + return 0; +} + +int priv_driver_get_country(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + uint32_t i4BytesWritten = 0; + uint32_t country = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (!regd_is_single_sku_en()) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "Not Supported."); + return i4BytesWritten; + } + + country = rlmDomainGetCountryCode(); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nCountry Code: (0x%x)", + country); + + return i4BytesWritten; +} + +int priv_driver_get_channels(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + uint32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; +#if (CFG_SUPPORT_SINGLE_SKU == 1) + uint32_t ch_idx, start_idx, end_idx; + struct channel *pCh; + uint32_t ch_num = 0; + uint8_t maxbw = 160; + uint32_t u4Ret = 0; +#endif + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (!regd_is_single_sku_en()) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "Not Supported."); + return i4BytesWritten; + } + +#if (CFG_SUPPORT_SINGLE_SKU == 1) + /** + * Usage: iwpriv wlan0 driver "get_channels [2g |5g |ch_num]" + **/ + if (i4Argc >= 2 && (apcArgv[1][0] == '2') && (apcArgv[1][1] == 'g')) { + start_idx = 0; + end_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + } else if (i4Argc >= 2 && (apcArgv[1][0] == '5') && + (apcArgv[1][1] == 'g')) { + start_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + end_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ) + + rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ); + } else { + start_idx = 0; + end_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ) + + rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ); + if (i4Argc >= 2) + /* Dump only specified channel */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &ch_num); + } + + if (regd_is_single_sku_en()) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\n"); + + for (ch_idx = start_idx; ch_idx < end_idx; ch_idx++) { + + pCh = (rlmDomainGetActiveChannels() + ch_idx); + + if (ch_num && (ch_num != pCh->chNum)) + continue; /*show specific channel information*/ + + /* Channel number */ + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "CH-%d:", + pCh->chNum); + + /* Active/Passive */ + if (pCh->flags & IEEE80211_CHAN_PASSIVE_FLAG) { + /* passive channel */ + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + " " IEEE80211_CHAN_PASSIVE_STR); + } else + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + " ACTIVE"); + + /* Max BW */ + if ((pCh->flags & IEEE80211_CHAN_NO_160MHZ) == + IEEE80211_CHAN_NO_160MHZ) + maxbw = 80; + if ((pCh->flags & IEEE80211_CHAN_NO_80MHZ) == + IEEE80211_CHAN_NO_80MHZ) + maxbw = 40; + if ((pCh->flags & IEEE80211_CHAN_NO_HT40) == + IEEE80211_CHAN_NO_HT40) + maxbw = 20; + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + " BW_%dMHz", maxbw); + /* Channel flags */ + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + " (flags=0x%x)\n", pCh->flags); + } + } +#endif + + return i4BytesWritten; +} + +int priv_driver_get_ap_channels(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + uint32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; +#if (CFG_SUPPORT_SINGLE_SKU == 1) + uint32_t ch_idx, start_idx, end_idx; + struct channel *pCh; + uint32_t ch_num = 0; + uint8_t maxbw = 160; + uint32_t u4Ret = 0; +#endif + struct ADAPTER *prAdapter = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct WIFI_VAR *prWifiVar = NULL; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + prWifiVar = &prAdapter->rWifiVar; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (!regd_is_single_sku_en()) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "Not Supported."); + return i4BytesWritten; + } + +#if (CFG_SUPPORT_SINGLE_SKU == 1) + /** + * Usage: iwpriv wlan0 driver "get_ap_channels [2g |5g |ch_num]" + **/ + if (i4Argc >= 2 && (apcArgv[1][0] == '2') && (apcArgv[1][1] == 'g')) { + start_idx = 0; + end_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + } else if (i4Argc >= 2 && (apcArgv[1][0] == '5') && + (apcArgv[1][1] == 'g')) { + start_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + end_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ) + + rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ); + } else { + start_idx = 0; + end_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ) + + rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ); + if (i4Argc >= 2) + /* Dump only specified channel */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &ch_num); + } + + if (regd_is_single_sku_en()) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\n"); + + for (ch_idx = start_idx; ch_idx < end_idx; ch_idx++) { + uint8_t ApMaxbw = 0; + + pCh = (rlmDomainGetActiveChannels() + ch_idx); + + if (ch_num && (ch_num != pCh->chNum)) + continue; /*show specific channel information*/ + + /* Channel number */ + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "CH-%d:", + pCh->chNum); + /* Active/Passive */ + if (pCh->flags & IEEE80211_CHAN_PASSIVE_FLAG) { + LOGBUF(pcCommand, i4TotalLen, + i4BytesWritten, + " " IEEE80211_CHAN_PASSIVE_STR); + } else { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + " ACTIVE"); + } + /* Max BW */ + if ((pCh->flags & IEEE80211_CHAN_NO_160MHZ) == + IEEE80211_CHAN_NO_160MHZ) + maxbw = 80; + if ((pCh->flags & IEEE80211_CHAN_NO_80MHZ) == + IEEE80211_CHAN_NO_80MHZ) + maxbw = 40; + if ((pCh->flags & IEEE80211_CHAN_NO_HT40) == + IEEE80211_CHAN_NO_HT40) + maxbw = 20; + + /* Checking 2G BW setting */ + if (pCh->chNum < MAX_2G_BAND_CHN_NUM) { + switch (prWifiVar->ucAp2gBandwidth) { + case MAX_BW_40MHZ: + ApMaxbw = 40; + break; + case MAX_BW_20MHZ: + ApMaxbw = 20; + break; + default: + ApMaxbw = 40; + break; + } + } else { + switch (prWifiVar->ucAp5gBandwidth) { + case MAX_BW_80MHZ: + ApMaxbw = 80; + break; + case MAX_BW_40MHZ: + ApMaxbw = 40; + break; + case MAX_BW_20MHZ: + ApMaxbw = 20; + break; + default: + ApMaxbw = 80; + break; + } + } + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + " BW_%dMHz", + ((maxbw <= ApMaxbw)?(maxbw):(ApMaxbw))); + /* Channel flags */ + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + " (flags=0x%x)\n", + pCh->flags); + } + } +#endif + return i4BytesWritten; +} + + +#if (CFG_SUPPORT_DFS_MASTER == 1) +int priv_driver_show_dfs_state(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i4BytesWritten = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nDFS State: \"%s\"", + p2pFuncShowDfsState()); + + return i4BytesWritten; +} + +int priv_driver_show_dfs_radar_param(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i4BytesWritten = 0; + uint8_t ucCnt = 0; + struct P2P_RADAR_INFO *prP2pRadarInfo = (struct P2P_RADAR_INFO *) NULL; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + prP2pRadarInfo = (struct P2P_RADAR_INFO *) cnmMemAlloc( + prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(*prP2pRadarInfo)); + + if (prP2pRadarInfo == NULL) { + DBGLOG(REQ, ERROR, + "NCHO no memory for P2pRadarInfo req\n"); + return -1; + } + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + p2pFuncGetRadarInfo(prP2pRadarInfo); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nRDD idx: %d\n", + prP2pRadarInfo->ucRddIdx); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nLong Pulse detected: %d\n", prP2pRadarInfo->ucLongDetected); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nPeriodic Pulse detected: %d\n", + prP2pRadarInfo->ucPeriodicDetected); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nLPB Num: %d\n", + prP2pRadarInfo->ucLPBNum); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nPPB Num: %d\n", + prP2pRadarInfo->ucPPBNum); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n==========================="); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nLong Pulse Buffer Contents:\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\npulse_time pulse_width PRI\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\n%-10d %-11d -\n" + , prP2pRadarInfo->arLpbContent[ucCnt].u4LongStartTime + , prP2pRadarInfo->arLpbContent[ucCnt].u2LongPulseWidth); + for (ucCnt = 1; ucCnt < prP2pRadarInfo->ucLPBNum; ucCnt++) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n%-10d %-11d %d\n", + prP2pRadarInfo->arLpbContent[ucCnt].u4LongStartTime, + prP2pRadarInfo->arLpbContent[ucCnt].u2LongPulseWidth, + (prP2pRadarInfo->arLpbContent[ucCnt].u4LongStartTime + - prP2pRadarInfo->arLpbContent[ucCnt-1] + .u4LongStartTime) * 2 / 5); + } + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nLPB Period Valid: %d", prP2pRadarInfo->ucLPBPeriodValid); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nLPB Period Valid: %d\n", prP2pRadarInfo->ucLPBWidthValid); + + ucCnt = 0; + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n==========================="); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nPeriod Pulse Buffer Contents:\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\npulse_time pulse_width PRI\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\n%-10d %-11d -\n" + , prP2pRadarInfo->arPpbContent[ucCnt].u4PeriodicStartTime + , prP2pRadarInfo->arPpbContent[ucCnt].u2PeriodicPulseWidth); + for (ucCnt = 1; ucCnt < prP2pRadarInfo->ucPPBNum; ucCnt++) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n%-10d %-11d %d\n" + , prP2pRadarInfo->arPpbContent[ucCnt].u4PeriodicStartTime + , prP2pRadarInfo->arPpbContent[ucCnt] + .u2PeriodicPulseWidth + , (prP2pRadarInfo->arPpbContent[ucCnt] + .u4PeriodicStartTime + - prP2pRadarInfo->arPpbContent[ucCnt-1] + .u4PeriodicStartTime) * 2 / 5); + } + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nPRI Count M1 TH: %d; PRI Count M1: %d", + prP2pRadarInfo->ucPRICountM1TH, prP2pRadarInfo->ucPRICountM1); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nPRI Count M2 TH: %d; PRI Count M2: %d", + prP2pRadarInfo->ucPRICountM2TH, + prP2pRadarInfo->ucPRICountM2); + + + cnmMemFree(prGlueInfo->prAdapter, prP2pRadarInfo); + + return i4BytesWritten; +} + +int priv_driver_show_dfs_help(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i4BytesWritten = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n--iwpriv wlanX driver \"show_dfs_state\"\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nINACTIVE: RDD disable or temporary RDD disable"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nCHECKING: During CAC time"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nACTIVE : In-serive monitoring"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nDETECTED: Has detected radar but hasn't moved to new channel\n"); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n--iwpriv wlanX driver \"show_dfs_radar_param\"\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nShow the latest pulse information\n"); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n--iwpriv wlanX driver \"show_dfs_cac_time\"\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nShow the remaining time of CAC\n"); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n--iwpriv wlanX set ByPassCac=yy\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nValue yy: set the time of CAC\n"); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n--iwpriv wlanX set RDDReport=yy\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nValue yy is \"0\" or \"1\""); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n\"0\": Emulate RDD0 manual radar event"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n\"1\": Emulate RDD1 manual radar event\n"); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n--iwpriv wlanX set RadarDetectMode=yy\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nValue yy is \"0\" or \"1\""); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n\"0\": Switch channel when radar detected (default)"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n\"1\": Do not switch channel when radar detected"); + + return i4BytesWritten; +} + +int priv_driver_show_dfs_cac_time(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i4BytesWritten = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (p2pFuncGetDfsState() != DFS_STATE_CHECKING) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nNot in CAC period"); + return i4BytesWritten; + } + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nRemaining time of CAC: %dsec", p2pFuncGetCacRemainingTime()); + + return i4BytesWritten; +} + +#endif +#ifdef CFG_SUPPORT_ADJUST_MCC_STAY_TIME +#define CFG_MCC_AIS_QUOTA_TYPE 0 +#define CFG_MCC_P2PGC_QUOTA_TYPE 1 +#define CFG_MCC_P2PGO_QUOTA_TYPE 2 + +int priv_driver_set_mcc_time(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct ADAPTER *prAdapter = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Argc = 0; + uint32_t i4BytesWritten = 0; + uint32_t ucLinkType = 0; /* 0 for AIS and 1 for P2P */ + uint32_t ucStayTime = 0; /* In unit of us */ + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i4Ret = 0; + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + prAdapter = prGlueInfo->prAdapter; + if (i4Argc != 3) + goto out; + + i4Ret = kalkStrtou32(apcArgv[1], 0, &ucLinkType); + if (i4Ret) { + DBGLOG(REQ, LOUD, "parse ucLinkType error i4Ret=%d\n", i4Ret); + goto out; + } + i4Ret = kalkStrtou32(apcArgv[2], 0, &ucStayTime); + if (i4Ret) { + DBGLOG(REQ, LOUD, "parse ucStayTime error i4Ret=%d\n", i4Ret); + goto out; + } + if (ucLinkType == CFG_MCC_AIS_QUOTA_TYPE) { + snprintf(pcCommand, i4TotalLen, CMD_SET_CHIP " mccTime 0 %d", + ucStayTime); + } else if (ucLinkType == CFG_MCC_P2PGC_QUOTA_TYPE) { + snprintf(pcCommand, i4TotalLen, CMD_SET_CHIP " mccTime 1 %d", + ucStayTime); + } else if (ucLinkType == CFG_MCC_P2PGO_QUOTA_TYPE) { + snprintf(pcCommand, i4TotalLen, CMD_SET_CHIP " mccTime 2 %d", + ucStayTime); + } else { + DBGLOG(REQ, LOUD, "Wrong network type %i\n", ucLinkType); + i4BytesWritten = -1; + goto out; + } + priv_driver_set_chip_config(prNetDev, pcCommand, i4TotalLen); +out: + return i4BytesWritten; +} +#endif + +int priv_driver_set_miracast(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + + struct ADAPTER *prAdapter = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t i4BytesWritten = 0; + /* WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; */ + /* UINT_32 u4BufLen = 0; */ + int32_t i4Argc = 0; + uint32_t ucMode = 0; + struct WFD_CFG_SETTINGS *prWfdCfgSettings = + (struct WFD_CFG_SETTINGS *) NULL; + struct MSG_WFD_CONFIG_SETTINGS_CHANGED *prMsgWfdCfgUpdate = + (struct MSG_WFD_CONFIG_SETTINGS_CHANGED *) NULL; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t u4Ret = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + prAdapter = prGlueInfo->prAdapter; + if (i4Argc >= 2) { + /* ucMode = kalStrtoul(apcArgv[1], NULL, 0); */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &ucMode); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse ucMode error u4Ret=%d\n", + u4Ret); + + if (g_ucMiracastMode == (uint8_t) ucMode) { + /* XXX: continue or skip */ + /* XXX: continue or skip */ + } + + g_ucMiracastMode = (uint8_t) ucMode; + prMsgWfdCfgUpdate = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_WFD_CONFIG_SETTINGS_CHANGED)); + + if (prMsgWfdCfgUpdate != NULL) { + + prWfdCfgSettings = + &(prAdapter->rWifiVar.rWfdConfigureSettings); + prMsgWfdCfgUpdate->rMsgHdr.eMsgId = + MID_MNY_P2P_WFD_CFG_UPDATE; + prMsgWfdCfgUpdate->prWfdCfgSettings = prWfdCfgSettings; + + if (ucMode == MIRACAST_MODE_OFF) { + prWfdCfgSettings->ucWfdEnable = 0; + snprintf(pcCommand, i4TotalLen, + CMD_SET_CHIP " mira 0"); + } else if (ucMode == MIRACAST_MODE_SOURCE) { + prWfdCfgSettings->ucWfdEnable = 1; + snprintf(pcCommand, i4TotalLen, + CMD_SET_CHIP " mira 1"); + } else if (ucMode == MIRACAST_MODE_SINK) { + prWfdCfgSettings->ucWfdEnable = 2; + snprintf(pcCommand, i4TotalLen, + CMD_SET_CHIP " mira 2"); + } else { + prWfdCfgSettings->ucWfdEnable = 0; + snprintf(pcCommand, i4TotalLen, + CMD_SET_CHIP " mira 0"); + } + + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *) + prMsgWfdCfgUpdate, MSG_SEND_METHOD_BUF); + + priv_driver_set_chip_config(prNetDev, pcCommand, + i4TotalLen); + } /* prMsgWfdCfgUpdate */ + else { + ASSERT(FALSE); + i4BytesWritten = -1; + } + } + + /* i4Argc */ + return i4BytesWritten; +} + +int parseValueInString( + IN char **pcCommand, + IN const char *acDelim, + IN void *aucValue, + IN int u4MaxLen) +{ + uint8_t *pcPtr; + uint32_t u4Len; + uint8_t *pucValueHead = NULL; + uint8_t *pucValueTail = NULL; + + if (*pcCommand + && !kalStrnCmp(*pcCommand, acDelim, kalStrLen(acDelim))) { + pcPtr = kalStrSep(pcCommand, "=,"); + pucValueHead = *pcCommand; + pcPtr = kalStrSep(pcCommand, "=,"); + DBGLOG(REQ, TRACE, "pucValueHead = %s\n", pucValueHead); + if (pucValueHead) { + u4Len = kalStrLen(pucValueHead); + if (*pcCommand) { + pucValueTail = *pcCommand - 1; + u4Len = pucValueTail - pucValueHead; + } + if (u4Len > u4MaxLen) + u4Len = u4MaxLen; + + /* MAC */ + if (!kalStrnCmp(acDelim, "MAC=", kalStrLen(acDelim))) { + u8 *addr = aucValue; + + wlanHwAddrToBin(pucValueHead, addr); + DBGLOG(REQ, TRACE, "MAC type"); + } else { + u8 *addr = aucValue; + + kalStrnCpy(addr, pucValueHead, u4Len); + *((char *)aucValue + u4Len) = '\0'; + DBGLOG(REQ, TRACE, + "STR type = %s\n", (char *)aucValue); + } + return 0; + } + } + + return -1; +} + +int priv_driver_set_ap_set_mac_acl(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct BSS_INFO *prBssInfo = NULL; + uint8_t aucValue[WLAN_CFG_ARGV_MAX]; + uint8_t ucRoleIdx = 0, ucBssIdx = 0; + int32_t i4BytesWritten = 0; + int32_t i4Count = 0, i4Mode = 0; + int i = 0; + + DBGLOG(REQ, INFO, "command is %s\n", pcCommand); + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + goto error; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + /* get Bss Index from ndev */ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prNetDev, &ucRoleIdx) != 0) + goto error; + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) + goto error; + + DBGLOG(REQ, INFO, "ucRoleIdx = %d\n", ucRoleIdx); + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + if (!prBssInfo) { + DBGLOG(REQ, WARN, "bss is not active\n"); + goto error; + } + + /* Mode */ + if (parseValueInString(&pcCommand, + "MAC_MODE=", &aucValue, WLAN_CFG_ARGV_MAX)) { + DBGLOG(REQ, ERROR, "[MODE] parse error\n"); + goto error; + } + if (kalkStrtou32(aucValue, 0, &i4Mode)) { + DBGLOG(REQ, ERROR, "[MODE] convert to int error\n"); + goto error; + } + if (i4Mode == 0) + prBssInfo->rACL.ePolicy = PARAM_CUSTOM_ACL_POLICY_DISABLE; + else if (i4Mode == 1) + prBssInfo->rACL.ePolicy = PARAM_CUSTOM_ACL_POLICY_DENY; + else if (i4Mode == 2) + prBssInfo->rACL.ePolicy = PARAM_CUSTOM_ACL_POLICY_ACCEPT; + else { + DBGLOG(REQ, ERROR, "[MODE] invalid ACL policy= %d\n", i4Mode); + goto error; + } + + /* Count */ + if (parseValueInString(&pcCommand, + "MAC_CNT=", &aucValue, WLAN_CFG_ARGV_MAX)) { + DBGLOG(REQ, ERROR, "[CNT] parse count error\n"); + goto error; + } + if (kalkStrtou32(aucValue, 0, &i4Count)) { + DBGLOG(REQ, ERROR, "[CNT] convert to int error\n"); + goto error; + } + if (i4Count > MAX_NUMBER_OF_ACL) { + DBGLOG(REQ, ERROR, "[CNT] invalid count > max ACL\n"); + goto error; + } + + /* MAC */ + if (prBssInfo->rACL.u4Num) { + /* Clear */ + kalMemZero(&prBssInfo->rACL.rEntry[0], + sizeof(struct PARAM_CUSTOM_ACL_ENTRY) * MAC_ADDR_LEN); + prBssInfo->rACL.u4Num = 0; + } + + if (prBssInfo->rACL.ePolicy != PARAM_CUSTOM_ACL_POLICY_DISABLE) { + for (i = 0; i < i4Count; i++) { + /* Add */ + if (parseValueInString(&pcCommand, + "MAC=", &aucValue, WLAN_CFG_ARGV_MAX)) + break; + kalMemCopy(prBssInfo->rACL.rEntry[i].aucAddr, + &aucValue, MAC_ADDR_LEN); + DBGLOG(REQ, INFO, + "[MAC] add mac addr " MACSTR " to ACL(%d).\n", + MAC2STR(prBssInfo->rACL.rEntry[i].aucAddr), i); + } + + prBssInfo->rACL.u4Num = i; + /* check ACL affects any existent association */ + p2pRoleUpdateACLEntry(prAdapter, ucBssIdx); + DBGLOG(REQ, INFO, + "[MAC] Mode = %d, #ACL = %d, count = %d\n", + i4Mode, i, i4Count); + } + + return i4BytesWritten; + +error: + return -1; +} + +int priv_driver_set_ap_set_cfg(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct WIFI_VAR *prWifiVar = NULL; + uint8_t aucValue[WLAN_CFG_ARGV_MAX]; + uint8_t ucRoleIdx = 0; + int32_t i4BytesWritten = 0; + int32_t i4MaxCount = 0, i4Channel = 0; + + DBGLOG(REQ, INFO, "command is %s\n", pcCommand); + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + goto error; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + prWifiVar = &prAdapter->rWifiVar; + + /* get role index from ndev */ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prNetDev, &ucRoleIdx) != 0) + goto error; + + DBGLOG(REQ, INFO, "ucRoleIdx = %d\n", ucRoleIdx); + + /* Cfg */ + if (parseValueInString(&pcCommand, "ASCII_CMD=", + &aucValue, WLAN_CFG_ARGV_MAX)) { + DBGLOG(REQ, ERROR, "[CFG] cmd parse error\n"); + goto error; + } + if (kalStrnCmp(aucValue, "AP_CFG", 6)) { + DBGLOG(REQ, ERROR, "[CFG] sub cmd parse error\n"); + goto error; + } + + /* Channel */ + if (parseValueInString(&pcCommand, "CHANNEL=", + &aucValue, WLAN_CFG_ARGV_MAX)) { + DBGLOG(REQ, ERROR, "[CH] parse error\n"); + goto error; + } + if (kalkStrtou32(aucValue, 0, &i4Channel)) { + DBGLOG(REQ, ERROR, "[CH] convert to int error\n"); + goto error; + } + + /* Max SCB */ + if (parseValueInString(&pcCommand, "MAX_SCB=", + &aucValue, WLAN_CFG_ARGV_MAX)) { + DBGLOG(REQ, ERROR, "[MAX_SCB] parse error\n"); + goto error; + } + if (kalkStrtou32(aucValue, 0, &i4MaxCount)) { + DBGLOG(REQ, ERROR, "[MAX_SCB] convert to int error\n"); + goto error; + } + + /* Overwrite AP channel */ + prWifiVar->ucApChannel = i4Channel; + + /* Set max clients of Hotspot */ + kalP2PSetMaxClients(prGlueInfo, i4MaxCount, ucRoleIdx); + + DBGLOG(REQ, INFO, + "[CFG] CH = %d, MAX_SCB = %d\n", + i4Channel, i4MaxCount); + + /* Stop ap */ +#if 0 + { + struct PARAM_CUSTOM_P2P_SET_STRUCT rSetP2P; + + rSetP2P.u4Mode = 0; + rSetP2P.u4Enable = 0; + set_p2p_mode_handler(prNetDev, rSetP2P); + } +#endif + + return i4BytesWritten; + +error: + return -1; +} + +int priv_driver_set_ap_get_sta_list(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct BSS_INFO *prBssInfo = NULL; + struct LINK *prClientList; + struct STA_RECORD *prCurrStaRec, *prNextStaRec; + uint8_t ucRoleIdx = 0, ucBssIdx = 0; + int32_t i4BytesWritten = 0; + int i = 0; + + DBGLOG(REQ, INFO, "command is %s\n", pcCommand); + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + goto error; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + /* get Bss Index from ndev */ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prNetDev, &ucRoleIdx) != 0) + goto error; + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) + goto error; + + DBGLOG(REQ, INFO, "ucRoleIdx = %d\n", ucRoleIdx); + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + if (!prBssInfo) { + DBGLOG(REQ, WARN, "bss is not active\n"); + goto error; + } + + prClientList = &prBssInfo->rStaRecOfClientList; + LINK_FOR_EACH_ENTRY_SAFE(prCurrStaRec, + prNextStaRec, prClientList, rLinkEntry, struct STA_RECORD) { + if (!prCurrStaRec) { + DBGLOG(REQ, WARN, "NULL STA_REC\n"); + break; + } + DBGLOG(SW4, INFO, "STA[%u] [" MACSTR "]\n", + prCurrStaRec->ucIndex, + MAC2STR(prCurrStaRec->aucMacAddr)); + i4BytesWritten += kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "MAC[%d]=" MACSTR "\n", + i++, + MAC2STR(prCurrStaRec->aucMacAddr)); + } + + return i4BytesWritten; + +error: + return -1; +} + +int priv_driver_set_ap_sta_disassoc(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint8_t aucValue[WLAN_CFG_ARGV_MAX]; + uint8_t ucRoleIdx = 0; + int32_t i4BytesWritten = 0; + struct MSG_P2P_CONNECTION_ABORT *prDisconnectMsg = + (struct MSG_P2P_CONNECTION_ABORT *) NULL; + + DBGLOG(REQ, INFO, "command is %s\n", pcCommand); + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + goto error; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + /* get role index from ndev */ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prNetDev, &ucRoleIdx) != 0) + goto error; + + DBGLOG(REQ, INFO, "ucRoleIdx = %d\n", ucRoleIdx); + + if (parseValueInString(&pcCommand, "MAC=", + &aucValue, WLAN_CFG_ARGV_MAX)) { + DBGLOG(REQ, ERROR, "[MAC] parse error\n"); + goto error; + } + + prDisconnectMsg = + (struct MSG_P2P_CONNECTION_ABORT *) + cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_P2P_CONNECTION_ABORT)); + if (prDisconnectMsg == NULL) { + ASSERT(FALSE); + goto error; + } + + prDisconnectMsg->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT; + prDisconnectMsg->ucRoleIdx = ucRoleIdx; + COPY_MAC_ADDR(prDisconnectMsg->aucTargetID, aucValue); + prDisconnectMsg->u2ReasonCode = REASON_CODE_UNSPECIFIED; + prDisconnectMsg->fgSendDeauth = TRUE; + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prDisconnectMsg, + MSG_SEND_METHOD_BUF); + + return i4BytesWritten; + +error: + return -1; +} + +int +priv_set_ap(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + uint32_t u4SubCmd = 0; + uint16_t u2Cmd = 0; + int32_t i4TotalFixLen = 1024; + int32_t i4CmdFound = 0; + + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + + ASSERT(prNetDev); + ASSERT(prIwReqData); + if (!prNetDev || !prIwReqData) { + DBGLOG(REQ, INFO, + "invalid param(0x%p, 0x%p)\n", + prNetDev, prIwReqData); + return -EINVAL; + } + + u2Cmd = prIwReqInfo->cmd; + DBGLOG(REQ, INFO, "prIwReqInfo->cmd %x\n", u2Cmd); + + u4SubCmd = (uint32_t) prIwReqData->data.flags; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, + "invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, + *((struct GLUE_INFO **) netdev_priv(prNetDev))); + return -EINVAL; + } + + DBGLOG(REQ, INFO, "prIwReqData->data.length %u\n", + prIwReqData->data.length); + + ASSERT(IW_IS_GET(u2Cmd)); + if (prIwReqData->data.length != 0) { + if (!access_ok(VERIFY_READ, prIwReqData->data.pointer, + prIwReqData->data.length)) { + DBGLOG(REQ, INFO, + "%s access_ok Read fail written = %d\n", + __func__, i4BytesWritten); + return -EFAULT; + } + if (copy_from_user(pcExtra, + prIwReqData->data.pointer, + prIwReqData->data.length)) { + DBGLOG(REQ, INFO, + "%s copy_form_user fail written = %d\n", + __func__, + prIwReqData->data.length); + return -EFAULT; + } + /* prIwReqData->data.length include the terminate '\0' */ + pcExtra[prIwReqData->data.length - 1] = 0; + } + + if (!pcExtra) + goto exit; + + DBGLOG(REQ, INFO, "%s pcExtra %s\n", __func__, pcExtra); + + i4CmdFound = 1; + switch (u2Cmd) { + case IOC_AP_GET_STA_LIST: + i4BytesWritten = + priv_driver_set_ap_get_sta_list( + prNetDev, + pcExtra, + i4TotalFixLen); + break; + case IOC_AP_SET_MAC_FLTR: + i4BytesWritten = + priv_driver_set_ap_set_mac_acl( + prNetDev, + pcExtra, + i4TotalFixLen); + break; + case IOC_AP_SET_CFG: + i4BytesWritten = + priv_driver_set_ap_set_cfg( + prNetDev, + pcExtra, + i4TotalFixLen); + break; + case IOC_AP_STA_DISASSOC: + i4BytesWritten = + priv_driver_set_ap_sta_disassoc( + prNetDev, + pcExtra, + i4TotalFixLen); + break; + default: + i4CmdFound = 0; + break; + } + + if (i4CmdFound == 0) + DBGLOG(REQ, INFO, + "Unknown driver command\n"); + + if (i4BytesWritten >= 0) { + if ((i4BytesWritten == 0) && (i4TotalFixLen > 0)) { + /* reset the command buffer */ + pcExtra[0] = '\0'; + } + if (i4BytesWritten >= i4TotalFixLen) { + DBGLOG(REQ, INFO, + "%s: i4BytesWritten %d > i4TotalFixLen < %d\n", + __func__, i4BytesWritten, i4TotalFixLen); + i4BytesWritten = i4TotalFixLen; + } else { + pcExtra[i4BytesWritten] = '\0'; + i4BytesWritten++; + } + } + + DBGLOG(REQ, INFO, "%s i4BytesWritten = %d\n", __func__, + i4BytesWritten); + +exit: + + DBGLOG(REQ, INFO, "pcExtra done\n"); + + if (i4BytesWritten >= 0) + prIwReqData->data.length = i4BytesWritten; + + return 0; +} + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +/* + * Memo + * 00 : Reset All Cal Data in Driver + * 01 : Trigger All Cal Function + * 02 : Get Thermal Temp from FW + * 03 : Get Cal Data Size from FW + * 04 : Get Cal Data from FW (Rom) + * 05 : Get Cal Data from FW (Ram) + * 06 : Print Cal Data in Driver (Rom) + * 07 : Print Cal Data in Driver (Ram) + * 08 : Print Cal Data in FW (Rom) + * 09 : Print Cal Data in FW (Ram) + * 10 : Send Cal Data to FW (Rom) + * 11 : Send Cal Data to FW (Ram) + */ +static int priv_driver_set_calbackup_test_drv_fw(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + uint32_t u4Ret, u4GetInput; + int32_t i4ArgNum = 2; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "%s\r\n", __func__); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4GetInput); + if (u4Ret) + DBGLOG(RFTEST, INFO, + "priv_driver_set_calbackup_test_drv_fw Parsing Fail\n"); + + if (u4GetInput == 0) { + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#0 : Reset All Cal Data in Driver.\n"); + /* (New Flow 20160720) Step 0 : Reset All Cal Data + * Structure + */ + memset(&g_rBackupCalDataAllV2, 1, + sizeof(struct RLM_CAL_RESULT_ALL_V2)); + g_rBackupCalDataAllV2.u4MagicNum1 = 6632; + g_rBackupCalDataAllV2.u4MagicNum2 = 6632; + } else if (u4GetInput == 1) { + DBGLOG(RFTEST, INFO, + "CMD#1 : Trigger FW Do All Cal.\n"); + /* Step 1 : Trigger All Cal Function */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 1, 2, 0); + DBGLOG(RFTEST, INFO, + "Trigger FW Do All Cal, rStatus = 0x%08x\n", + rStatus); + } else if (u4GetInput == 2) { + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#2 : Get Thermal Temp from FW.\n"); + /* (New Flow 20160720) Step 2 : Get Thermal Temp from + * FW + */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 0, 0, 0); + DBGLOG(RFTEST, INFO, + "Get Thermal Temp from FW, rStatus = 0x%08x\n", + rStatus); + + } else if (u4GetInput == 3) { + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#3 : Get Cal Data Size from FW.\n"); + /* (New Flow 20160720) Step 3 : Get Cal Data Size from + * FW + */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 0, 1, 0); + DBGLOG(RFTEST, INFO, + "Get Rom Cal Data Size, rStatus = 0x%08x\n", + rStatus); + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 0, 1, 1); + DBGLOG(RFTEST, INFO, + "Get Ram Cal Data Size, rStatus = 0x%08x\n", + rStatus); + + } else if (u4GetInput == 4) { +#if 1 + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#4 : Print Cal Data in FW (Ram) (Part 1 - [0]~[3327]).\n"); + /* Debug Use : Print Cal Data in FW (Ram) */ + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 4, 6, 1); + DBGLOG(RFTEST, INFO, + "Print Cal Data in FW (Ram), rStatus = 0x%08x\n", + rStatus); +#else /* For Temp Use this Index */ + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#4 : Get Cal Data from FW (Rom). Start!!!!!!!!!!!\n"); + DBGLOG(RFTEST, INFO, "Thermal Temp = %d\n", + g_rBackupCalDataAllV2.u4ThermalInfo); + DBGLOG(RFTEST, INFO, "Total Length (Rom) = %d\n", + g_rBackupCalDataAllV2.u4ValidRomCalDataLength); + /* (New Flow 20160720) Step 3 : Get Cal Data from FW */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 2, 4, 0); + DBGLOG(RFTEST, INFO, + "Get Cal Data from FW (Rom), rStatus = 0x%08x\n", + rStatus); +#endif + } else if (u4GetInput == 5) { +#if 1 + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#5 : Print RAM Cal Data in Driver (Part 1 - [0]~[3327]).\n"); + DBGLOG(RFTEST, INFO, + "==================================================================\n"); + /* RFTEST_INFO_LOGDUMP32( + * &(g_rBackupCalDataAllV2.au4RamCalData[0]), + * 3328*sizeof(uint32_t)); + */ + DBGLOG(RFTEST, INFO, + "==================================================================\n"); + DBGLOG(RFTEST, INFO, + "Dumped Ram Cal Data Szie : %d bytes\n", + 3328*sizeof(uint32_t)); + DBGLOG(RFTEST, INFO, + "Total Ram Cal Data Szie : %d bytes\n", + g_rBackupCalDataAllV2.u4ValidRamCalDataLength); + DBGLOG(RFTEST, INFO, + "==================================================================\n"); +#else /* For Temp Use this Index */ + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#5 : Get Cal Data from FW (Ram). Start!!!!!!!!!!!\n"); + DBGLOG(RFTEST, INFO, "Thermal Temp = %d\n", + g_rBackupCalDataAllV2.u4ThermalInfo); + DBGLOG(RFTEST, INFO, "Total Length (Ram) = %d\n", + g_rBackupCalDataAllV2.u4ValidRamCalDataLength); + /* (New Flow 20160720) Step 3 : Get Cal Data from FW */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 2, 4, 1); + DBGLOG(RFTEST, INFO, + "Get Cal Data from FW (Ram), rStatus = 0x%08x\n", + rStatus); +#endif + } else if (u4GetInput == 6) { + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#6 : Print ROM Cal Data in Driver.\n"); + DBGLOG(RFTEST, INFO, + "==================================================================\n"); + /* RFTEST_INFO_LOGDUMP32( + * &(g_rBackupCalDataAllV2.au4RomCalData[0]), + * g_rBackupCalDataAllV2.u4ValidRomCalDataLength); + */ + DBGLOG(RFTEST, INFO, + "==================================================================\n"); + DBGLOG(RFTEST, INFO, + "Total Rom Cal Data Szie : %d bytes\n", + g_rBackupCalDataAllV2.u4ValidRomCalDataLength); + DBGLOG(RFTEST, INFO, + "==================================================================\n"); + } else if (u4GetInput == 7) { + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#7 : Print RAM Cal Data in Driver (Part 2 - [3328]~[6662]).\n"); + DBGLOG(RFTEST, INFO, + "==================================================================\n"); + /* RFTEST_INFO_LOGDUMP32( + * &(g_rBackupCalDataAllV2.au4RamCalData[3328]), + * (g_rBackupCalDataAllV2.u4ValidRamCalDataLength - + * 3328*sizeof(uint32_t))); + */ + DBGLOG(RFTEST, INFO, + "==================================================================\n"); + DBGLOG(RFTEST, INFO, + "Dumped Ram Cal Data Szie : %d bytes\n", + (g_rBackupCalDataAllV2.u4ValidRamCalDataLength - + 3328*sizeof(uint32_t))); + DBGLOG(RFTEST, INFO, + "Total Ram Cal Data Szie : %d bytes\n", + g_rBackupCalDataAllV2.u4ValidRamCalDataLength); + DBGLOG(RFTEST, INFO, + "==================================================================\n"); + } else if (u4GetInput == 8) { + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#8 : Print Cal Data in FW (Rom).\n"); + /* Debug Use : Print Cal Data in FW (Rom) */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 4, 6, 0); + DBGLOG(RFTEST, INFO, + "Print Cal Data in FW (Rom), rStatus = 0x%08x\n", + rStatus); + + } else if (u4GetInput == 9) { + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#9 : Print Cal Data in FW (Ram) (Part 2 - [3328]~[6662]).\n"); + /* Debug Use : Print Cal Data in FW (Ram) */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 4, 6, 2); + DBGLOG(RFTEST, INFO, + "Print Cal Data in FW (Ram), rStatus = 0x%08x\n", + rStatus); + + } else if (u4GetInput == 10) { + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#10 : Send Cal Data to FW (Rom).\n"); + /* Send Cal Data to FW (Rom) */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 3, 5, 0); + DBGLOG(RFTEST, INFO, + "Send Cal Data to FW (Rom), rStatus = 0x%08x\n", + rStatus); + + } else if (u4GetInput == 11) { + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#11 : Send Cal Data to FW (Ram).\n"); + /* Send Cal Data to FW (Ram) */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 3, 5, 1); + DBGLOG(RFTEST, INFO, + "Send Cal Data to FW (Ram), rStatus = 0x%08x\n", + rStatus); + + } + } + + return i4BytesWritten; +} /* priv_driver_set_calbackup_test_drv_fw */ +#endif + +#if CFG_SUPPORT_ADJUST_MCC_MODE_SET +static int priv_driver_set_mcc_mode(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct ADAPTER *prAdapter = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Argc = 0; + int32_t i4BytesWritten = 0; + /* MCC mode 0: fair (5:5), 1: favor STA (7:3), 2: favor P2P (3:7) */ + uint32_t ucMccMode = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i4Ret = 0; + uint8_t ucRole; + uint32_t u4MccTimeToSet = 0; + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + prAdapter = prGlueInfo->prAdapter; + if (i4Argc != 2) + goto out; + + i4Ret = kalkStrtou32(apcArgv[1], 0, &ucMccMode); + if (i4Ret) { + DBGLOG(REQ, LOUD, "Parse ucMccMode error i4Ret=%d\n", i4Ret); + goto out; + } + + if (ucMccMode == MCC_FAIR) { + prAdapter->ucModeMCC = MCC_FAIR; + DBGLOG(REQ, TRACE, + "Current dynamic MCC priority : Fair\n"); +#if CFG_SUPPORT_RX_DYNAMIC_MCC_PRIORITY + prAdapter->ucModeMCC_STA_time = MCC_TIME_5; + prAdapter->ucModeMCC_P2P_time = MCC_TIME_5; +#endif + } else if (ucMccMode == MCC_FAV_STA) { + prAdapter->ucModeMCC = MCC_FAV_STA; + DBGLOG(REQ, TRACE, + "Current dynamic MCC priority : STA favor\n"); +#if CFG_SUPPORT_RX_DYNAMIC_MCC_PRIORITY + prAdapter->ucModeMCC_STA_time = MCC_TIME_7; + prAdapter->ucModeMCC_P2P_time = MCC_TIME_3; +#endif + } else if (ucMccMode == MCC_FAV_P2P) { + prAdapter->ucModeMCC = MCC_FAV_P2P; + DBGLOG(REQ, TRACE, + "Current dynamic MCC priority : P2P Favor\n"); +#if CFG_SUPPORT_RX_DYNAMIC_MCC_PRIORITY + prAdapter->ucModeMCC_STA_time = MCC_TIME_3; + prAdapter->ucModeMCC_P2P_time = MCC_TIME_7; +#endif + } else { + DBGLOG(REQ, LOUD, "Wrong MCC mode %i\n", ucMccMode); + i4BytesWritten = -1; + goto out; + } + + /*0:CFG_MCC_AIS_QUOTA_TYPE, + **1:CFG_MCC_P2PGC_QUOTA_TYPE, 2:CFG_MCC_P2PGO_QUOTA_TYPE + */ + for (ucRole = CFG_MCC_AIS_QUOTA_TYPE; + ucRole <= CFG_MCC_P2PGO_QUOTA_TYPE; ucRole++) { + if (ucRole == CFG_MCC_AIS_QUOTA_TYPE) + u4MccTimeToSet = prAdapter->ucModeMCC_STA_time; + else + u4MccTimeToSet = prAdapter->ucModeMCC_P2P_time; + + snprintf(pcCommand, i4TotalLen, + CMD_SET_CHIP " mccTime %d %d", + ucRole, u4MccTimeToSet); + priv_driver_set_chip_config(prNetDev, pcCommand, + i4TotalLen); + } + +out: + return i4BytesWritten; +} +#endif + +#if CFG_WOW_SUPPORT +static int priv_driver_set_wow(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct WOW_CTRL *pWOW_CTRL = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Ret = 0; + uint32_t Enable = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + pWOW_CTRL = &prGlueInfo->prAdapter->rWowCtrl; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + u4Ret = kalkStrtou32(apcArgv[1], 0, &Enable); + + if (u4Ret) + DBGLOG(REQ, LOUD, "parse bEnable error u4Ret=%d\n", u4Ret); + + DBGLOG(INIT, INFO, "CMD set_wow_enable = %d\n", Enable); + DBGLOG(INIT, INFO, "Scenario ID %d\n", pWOW_CTRL->ucScenarioId); + DBGLOG(INIT, INFO, "ucBlockCount %d\n", pWOW_CTRL->ucBlockCount); + DBGLOG(INIT, INFO, "interface %d\n", + pWOW_CTRL->astWakeHif[0].ucWakeupHif); + DBGLOG(INIT, INFO, "gpio_pin %d\n", + pWOW_CTRL->astWakeHif[0].ucGpioPin); + DBGLOG(INIT, INFO, "gpio_level 0x%x\n", + pWOW_CTRL->astWakeHif[0].ucTriggerLvl); + DBGLOG(INIT, INFO, "gpio_timer %d\n", + pWOW_CTRL->astWakeHif[0].u4GpioInterval); + kalWowProcess(prGlueInfo, Enable); + + return 0; +} + +static int priv_driver_set_wow_enable(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct WOW_CTRL *pWOW_CTRL = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Ret = 0; + uint8_t ucEnable = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + pWOW_CTRL = &prGlueInfo->prAdapter->rWowCtrl; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + u4Ret = kalkStrtou8(apcArgv[1], 0, &ucEnable); + + if (u4Ret) + DBGLOG(REQ, LOUD, "parse bEnable error u4Ret=%d\n", u4Ret); + + pWOW_CTRL->fgWowEnable = ucEnable; + + DBGLOG(PF, INFO, "WOW enable %d\n", pWOW_CTRL->fgWowEnable); + + return 0; +} + +static int priv_driver_set_wow_par(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct WOW_CTRL *pWOW_CTRL = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t u4Ret = 0; + uint8_t ucWakeupHif = 0, GpioPin = 0, ucGpioLevel = 0, ucBlockCount, + ucScenario = 0; + uint32_t u4GpioTimer = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + pWOW_CTRL = &prGlueInfo->prAdapter->rWowCtrl; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc > 3) { + + u4Ret = kalkStrtou8(apcArgv[1], 0, &ucWakeupHif); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse ucWakeupHif error u4Ret=%d\n", + u4Ret); + pWOW_CTRL->astWakeHif[0].ucWakeupHif = ucWakeupHif; + + u4Ret = kalkStrtou8(apcArgv[2], 0, &GpioPin); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse GpioPin error u4Ret=%d\n", + u4Ret); + pWOW_CTRL->astWakeHif[0].ucGpioPin = GpioPin; + + u4Ret = kalkStrtou8(apcArgv[3], 0, &ucGpioLevel); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse Gpio level error u4Ret=%d\n", + u4Ret); + pWOW_CTRL->astWakeHif[0].ucTriggerLvl = ucGpioLevel; + + u4Ret = kalkStrtou32(apcArgv[4], 0, &u4GpioTimer); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse u4GpioTimer error u4Ret=%d\n", + u4Ret); + pWOW_CTRL->astWakeHif[0].u4GpioInterval = u4GpioTimer; + + u4Ret = kalkStrtou8(apcArgv[5], 0, &ucScenario); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse ucScenario error u4Ret=%d\n", + u4Ret); + pWOW_CTRL->ucScenarioId = ucScenario; + + u4Ret = kalkStrtou8(apcArgv[6], 0, &ucBlockCount); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse ucBlockCnt error u4Ret=%d\n", + u4Ret); + pWOW_CTRL->ucBlockCount = ucBlockCount; + + DBGLOG(INIT, INFO, "gpio_scenario%d\n", + pWOW_CTRL->ucScenarioId); + DBGLOG(INIT, INFO, "interface %d\n", + pWOW_CTRL->astWakeHif[0].ucWakeupHif); + DBGLOG(INIT, INFO, "gpio_pin %d\n", + pWOW_CTRL->astWakeHif[0].ucGpioPin); + DBGLOG(INIT, INFO, "gpio_level %d\n", + pWOW_CTRL->astWakeHif[0].ucTriggerLvl); + DBGLOG(INIT, INFO, "gpio_timer %d\n", + pWOW_CTRL->astWakeHif[0].u4GpioInterval); + + return 0; + } else + return -1; + + +} + +static int priv_driver_set_wow_udpport(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct WOW_CTRL *pWOW_CTRL = NULL; + int32_t i4Argc = 0; + int8_t *apcPortArgv[WLAN_CFG_ARGV_MAX_LONG] = { 0 }; /* to input 20 port + */ + int32_t u4Ret = 0, ii; + uint8_t ucVer, ucCount; + uint16_t u2Port = 0; + uint16_t *pausPortArry; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + pWOW_CTRL = &prGlueInfo->prAdapter->rWowCtrl; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgumentLong(pcCommand, &i4Argc, apcPortArgv); + DBGLOG(REQ, WARN, "argc is %i\n", i4Argc); + + /* example ipv4: set_wow_udp 0 5353,8080 (set) */ + /* example ipv4: set_wow_udp 0 (clear) */ + /* example ipv6: set_wow_udp 1 8000 (set) */ + /* example ipv6: set_wow_udp 1 (clear) */ + + if (i4Argc >= 3) { + + /* Pick Max */ + ucCount = ((i4Argc - 2) > MAX_TCP_UDP_PORT) ? MAX_TCP_UDP_PORT : + (i4Argc - 2); + DBGLOG(PF, INFO, "UDP ucCount=%d\n", ucCount); + + u4Ret = kalkStrtou8(apcPortArgv[1], 0, &ucVer); + if (u4Ret) { + DBGLOG(REQ, LOUD, "parse ucWakeupHif error u4Ret=%d\n", + u4Ret); + return -1; + } + + /* IPv4/IPv6 */ + DBGLOG(PF, INFO, "ucVer=%d\n", ucVer); + if (ucVer == 0) { + pWOW_CTRL->stWowPort.ucIPv4UdpPortCnt = ucCount; + pausPortArry = pWOW_CTRL->stWowPort.ausIPv4UdpPort; + } else { + pWOW_CTRL->stWowPort.ucIPv6UdpPortCnt = ucCount; + pausPortArry = pWOW_CTRL->stWowPort.ausIPv6UdpPort; + } + + /* Port */ + for (ii = 0; ii < ucCount; ii++) { + u4Ret = kalkStrtou16(apcPortArgv[ii+2], 0, &u2Port); + if (u4Ret) { + DBGLOG(PF, ERROR, + "parse u2Port error u4Ret=%d\n", u4Ret); + return -1; + } + + pausPortArry[ii] = u2Port; + DBGLOG(PF, INFO, "ucPort=%d, idx=%d\n", u2Port, ii); + } + + return 0; + } else if (i4Argc == 2) { + + u4Ret = kalkStrtou8(apcPortArgv[1], 0, &ucVer); + if (u4Ret) { + DBGLOG(REQ, LOUD, "parse ucWakeupHif error u4Ret=%d\n", + u4Ret); + return -1; + } + + if (ucVer == 0) { + kalMemZero(prGlueInfo->prAdapter->rWowCtrl.stWowPort + .ausIPv4UdpPort, + sizeof(uint16_t) * MAX_TCP_UDP_PORT); + prGlueInfo->prAdapter->rWowCtrl.stWowPort + .ucIPv4UdpPortCnt = 0; + } else { + kalMemZero(prGlueInfo->prAdapter->rWowCtrl.stWowPort + .ausIPv6UdpPort, + sizeof(uint16_t) * MAX_TCP_UDP_PORT); + prGlueInfo->prAdapter->rWowCtrl.stWowPort + .ucIPv6UdpPortCnt = 0; + } + + return 0; + } else + return -1; + +} + +static int priv_driver_set_wow_tcpport(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct WOW_CTRL *pWOW_CTRL = NULL; + int32_t i4Argc = 0; + int8_t *apcPortArgv[WLAN_CFG_ARGV_MAX_LONG] = { 0 }; /* to input 20 port + */ + int32_t u4Ret = 0, ii; + uint8_t ucVer, ucCount; + uint16_t u2Port = 0; + uint16_t *pausPortArry; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + pWOW_CTRL = &prGlueInfo->prAdapter->rWowCtrl; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgumentLong(pcCommand, &i4Argc, apcPortArgv); + DBGLOG(REQ, WARN, "argc is %i\n", i4Argc); + + /* example ipv4: set_wow_tcp 0 5353,8080 (set) */ + /* example ipv4: set_wow_tcp 0 (clear) */ + /* example ipv6: set_wow_tcp 1 8000 (set) */ + /* example ipv6: set_wow_tcp 1 (clear) */ + + if (i4Argc >= 3) { + + /* Pick Max */ + ucCount = ((i4Argc - 2) > MAX_TCP_UDP_PORT) ? MAX_TCP_UDP_PORT : + (i4Argc - 2); + DBGLOG(PF, INFO, "TCP ucCount=%d\n", ucCount); + + u4Ret = kalkStrtou8(apcPortArgv[1], 0, &ucVer); + if (u4Ret) { + DBGLOG(REQ, LOUD, "parse ucWakeupHif error u4Ret=%d\n", + u4Ret); + return -1; + } + + /* IPv4/IPv6 */ + DBGLOG(PF, INFO, "Ver=%d\n", ucVer); + if (ucVer == 0) { + pWOW_CTRL->stWowPort.ucIPv4TcpPortCnt = ucCount; + pausPortArry = pWOW_CTRL->stWowPort.ausIPv4TcpPort; + } else { + pWOW_CTRL->stWowPort.ucIPv6TcpPortCnt = ucCount; + pausPortArry = pWOW_CTRL->stWowPort.ausIPv6TcpPort; + } + + /* Port */ + for (ii = 0; ii < ucCount; ii++) { + u4Ret = kalkStrtou16(apcPortArgv[ii+2], 0, &u2Port); + if (u4Ret) { + DBGLOG(PF, ERROR, + "parse u2Port error u4Ret=%d\n", u4Ret); + return -1; + } + + pausPortArry[ii] = u2Port; + DBGLOG(PF, INFO, "ucPort=%d, idx=%d\n", u2Port, ii); + } + + return 0; + } else if (i4Argc == 2) { + + u4Ret = kalkStrtou8(apcPortArgv[1], 0, &ucVer); + if (u4Ret) { + DBGLOG(REQ, LOUD, "parse ucWakeupHif error u4Ret=%d\n", + u4Ret); + return -1; + } + + if (ucVer == 0) { + kalMemZero( + prGlueInfo->prAdapter->rWowCtrl.stWowPort + .ausIPv4UdpPort, + sizeof(uint16_t) * MAX_TCP_UDP_PORT); + prGlueInfo->prAdapter->rWowCtrl.stWowPort + .ucIPv4UdpPortCnt = 0; + } else { + kalMemZero( + prGlueInfo->prAdapter->rWowCtrl.stWowPort + .ausIPv6UdpPort, + sizeof(uint16_t) * MAX_TCP_UDP_PORT); + prGlueInfo->prAdapter->rWowCtrl.stWowPort + .ucIPv6UdpPortCnt = 0; + } + + return 0; + } else + return -1; + +} + +static int priv_driver_get_wow_port(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct WOW_CTRL *pWOW_CTRL = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t u4Ret = 0, ii; + uint8_t ucVer, ucProto; + uint16_t ucCount; + uint16_t *pausPortArry; + int8_t *aucIp[2] = {"IPv4", "IPv6"}; + int8_t *aucProto[2] = {"UDP", "TCP"}; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + pWOW_CTRL = &prGlueInfo->prAdapter->rWowCtrl; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + /* example: get_wow_port 0 0 (ipv4-udp) */ + /* example: get_wow_port 0 1 (ipv4-tcp) */ + /* example: get_wow_port 1 0 (ipv6-udp) */ + /* example: get_wow_port 1 1 (ipv6-tcp) */ + + if (i4Argc >= 3) { + + /* 0=IPv4, 1=IPv6 */ + u4Ret = kalkStrtou8(apcArgv[1], 0, &ucVer); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse argc[1] error u4Ret=%d\n", + u4Ret); + + /* 0=UDP, 1=TCP */ + u4Ret = kalkStrtou8(apcArgv[2], 0, &ucProto); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse argc[2] error u4Ret=%d\n", + u4Ret); + + if (ucVer > 1) + ucVer = 0; + + if (ucProto > 1) + ucProto = 0; + + if (ucVer == 0) { + if (ucProto == 0) { + /* IPv4/UDP */ + ucCount = pWOW_CTRL->stWowPort.ucIPv4UdpPortCnt; + pausPortArry = + pWOW_CTRL->stWowPort.ausIPv4UdpPort; + } else { + /* IPv4/TCP */ + ucCount = pWOW_CTRL->stWowPort.ucIPv4TcpPortCnt; + pausPortArry = + pWOW_CTRL->stWowPort.ausIPv4TcpPort; + } + } else { + if (ucProto == 0) { + /* IPv6/UDP */ + ucCount = pWOW_CTRL->stWowPort.ucIPv6UdpPortCnt; + pausPortArry = + pWOW_CTRL->stWowPort.ausIPv6UdpPort; + } else { + /* IPv6/TCP */ + ucCount = pWOW_CTRL->stWowPort.ucIPv6TcpPortCnt; + pausPortArry = + pWOW_CTRL->stWowPort.ausIPv6TcpPort; + } + } + + /* Dunp Port */ + for (ii = 0; ii < ucCount; ii++) + DBGLOG(PF, INFO, "ucPort=%d, idx=%d\n", + pausPortArry[ii], ii); + + + DBGLOG(PF, INFO, "[%s/%s] count:%d\n", aucIp[ucVer], + aucProto[ucProto], ucCount); + + return 0; + } else + return -1; + +} + +static int priv_driver_get_wow_reason(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Argc = 0; + int32_t i4BytesWritten = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + struct WOW_CTRL *pWOW_CTRL = NULL; + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + pWOW_CTRL = &prGlueInfo->prAdapter->rWowCtrl; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (pWOW_CTRL->ucReason != INVALID_WOW_WAKE_UP_REASON) + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nwakeup_reason:%d", pWOW_CTRL->ucReason); + + return i4BytesWritten; +} + +static int priv_driver_set_suspend_cmd(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct WOW_CTRL *pWOW_CTRL = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Ret = 0; + uint32_t Enable = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + pWOW_CTRL = &prGlueInfo->prAdapter->rWowCtrl; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + u4Ret = kalkStrtou32(apcArgv[1], 0, &Enable); + + if (u4Ret) + DBGLOG(REQ, LOUD, "parse bEnable error u4Ret=%d\n", u4Ret); + + wlanSetSuspendMode(prGlueInfo, Enable); + + return 0; +} + +static int priv_driver_set_mdns_offload_enable(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Ret = 0; + uint8_t ucEnable = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + u4Ret = kalkStrtou8(apcArgv[1], 0, &ucEnable); + + if (u4Ret) + DBGLOG(REQ, LOUD, "parse bEnable error u4Ret=%d\n", u4Ret); + + if (prGlueInfo->prAdapter->mdns_offload_enable == FALSE + && ucEnable != 0) { + DBGLOG(PF, STATE, "Mdns offload enable.\n"); + prGlueInfo->prAdapter->mdns_offload_enable = TRUE; + kalSendMdnsEnableToFw(prGlueInfo); + } else if (prGlueInfo->prAdapter->mdns_offload_enable == TRUE + && ucEnable == 0) { + DBGLOG(PF, STATE, "Mdns offload disable.\n"); + prGlueInfo->prAdapter->mdns_offload_enable = FALSE; + kalInitMdnsCache(); + kalSendMdnsDisableToFw(prGlueInfo); + } else + DBGLOG(PF, STATE, "Mdns offload already %s\n", + ucEnable ? "enable" : "disable"); + + return 0; +} +#endif + +static int priv_driver_set_adv_pws(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Ret = 0; + uint8_t ucAdvPws = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + u4Ret = kalkStrtou8(apcArgv[1], 0, &ucAdvPws); + + if (u4Ret) + DBGLOG(REQ, LOUD, "parse bEnable error u4Ret=%d\n", + u4Ret); + + prGlueInfo->prAdapter->rWifiVar.ucAdvPws = ucAdvPws; + + DBGLOG(INIT, INFO, "AdvPws:%d\n", + prGlueInfo->prAdapter->rWifiVar.ucAdvPws); + + return 0; + +} + +static int priv_driver_set_mdtim(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Ret = 0; + uint8_t ucMultiDtim = 0, ucVer; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + /* iwpriv wlan0 driver "set_mdtim 1 3 */ + if (i4Argc >= 3) { + + u4Ret = kalkStrtou8(apcArgv[1], 0, &ucVer); + if (u4Ret) { + DBGLOG(REQ, ERROR, "parse apcArgv1 error u4Ret=%d\n", + u4Ret); + return -1; + } + + u4Ret = kalkStrtou8(apcArgv[2], 0, &ucMultiDtim); + if (u4Ret) { + DBGLOG(REQ, ERROR, "parse apcArgv2 error u4Ret=%d\n", + u4Ret); + return -1; + } + + if (ucVer == 0) { + prGlueInfo->prAdapter->rWifiVar.ucWowOnMdtim = + ucMultiDtim; + DBGLOG(REQ, INFO, "WOW On MDTIM:%d\n", + prGlueInfo->prAdapter->rWifiVar.ucWowOnMdtim); + } else { + prGlueInfo->prAdapter->rWifiVar.ucWowOffMdtim = + ucMultiDtim; + DBGLOG(REQ, INFO, "WOW Off MDTIM:%d\n", + prGlueInfo->prAdapter->rWifiVar.ucWowOffMdtim); + } + } + + return 0; + +} + +static int priv_driver_get_deep_sleep_cnt(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rWlanStatus; + int32_t i4BytesWritten = 0; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + + ASSERT(prNetDev); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = 0xb0100000; + rWlanStatus = kalIoctl(prGlueInfo, wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, STATE, "Deep sleep cnt=%d\n", rSwCtrlInfo.u4Data); + if (rWlanStatus == WLAN_STATUS_SUCCESS) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n Deep sleep cnt: %d\n", rSwCtrlInfo.u4Data); + } + + return i4BytesWritten; +} + +static int priv_driver_enforce_power_mode(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rWlanStatus; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t i4Ret = 0; + uint16_t ucEnforcePowerMode; + struct PARAM_POWER_MODE_ rPowerMode; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc != 2) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n format:enforce_power_mode [0|1|2|3]\n"); + return i4BytesWritten; + } + + i4Ret = kalkStrtou16(apcArgv[1], 0, &ucEnforcePowerMode); + if (i4Ret) + DBGLOG(REQ, ERROR, "parse enforce_power_mode error i4Ret=%d\n", + i4Ret); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + if (!prGlueInfo) + return -EFAULT; + + if (!prGlueInfo->prAdapter->prAisBssInfo) + return -EFAULT; + + rPowerMode.ucBssIdx = prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + rPowerMode.ePowerMode = (enum PARAM_POWER_MODE) ucEnforcePowerMode; + prGlueInfo->prAdapter->rWifiVar.ucEnforcePSMode = rPowerMode.ePowerMode; + + /* Restore Android's power mode setting + * if we do not enforce power mode. + */ + if (rPowerMode.ePowerMode >= Param_PowerModeMax && + prGlueInfo->prAdapter->prAisBssInfo->ePowerModeFromUser + < Param_PowerModeMax) { + rPowerMode.ePowerMode = + prGlueInfo->prAdapter->prAisBssInfo->ePowerModeFromUser; + } + + rWlanStatus = kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, + sizeof(struct PARAM_POWER_MODE_), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rWlanStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rWlanStatus); + return -1; + } + return i4BytesWritten; +} + +static int priv_driver_get_power_mode(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + uint16_t ucEnforcePowerMode; + uint16_t ePowerModeFromUser; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + if (!prGlueInfo) + return -EFAULT; + + if (!prGlueInfo->prAdapter->prAisBssInfo) + return -EFAULT; + + ucEnforcePowerMode = + prGlueInfo->prAdapter->rWifiVar.ucEnforcePSMode; + ePowerModeFromUser = + prGlueInfo->prAdapter->prAisBssInfo->ePowerModeFromUser; + if (ucEnforcePowerMode < Param_PowerModeMax) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n enforce power mode %d\n", ucEnforcePowerMode); + } else { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\n enforce power mode: disabled\n"); + } + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + " system power mode: %d\n", ePowerModeFromUser); + + return i4BytesWritten; +} + +#if CFG_CHIP_RESET_HANG +static int priv_driver_set_rst_hang(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + uint32_t u4Ret; + + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc == 0) { + DBGLOG(REQ, INFO, "set_rst_hang Argc = %d\n", i4Argc); + return -EFAULT; + } + + if (strnicmp(apcArgv[0], CMD_SET_RST_HANG, + strlen(CMD_SET_RST_HANG)) == 0) { + if (i4Argc < CMD_SET_RST_HANG_ARG_NUM) { + DBGLOG(REQ, STATE, + "[SER][L0] RST_HANG_SET arg num=%d,must be %d\n", + i4Argc, CMD_SET_RST_HANG_ARG_NUM); + return -EFAULT; + } + u4Ret = kalkStrtou8(apcArgv[1], 0, &fgIsResetHangState); + if (u4Ret) + DBGLOG(REQ, ERROR, "u4Ret=%d\n", u4Ret); + + DBGLOG(REQ, STATE, "[SER][L0] set fgIsResetHangState=%d\n", + fgIsResetHangState); + + if (fgIsResetHangState == SER_L0_HANG_RST_CMD_TRG) { + DBGLOG(REQ, STATE, "[SER][L0] cmd trigger\n"); + glGetRstReason(RST_CMD_TRIGGER); + GL_RESET_TRIGGER(NULL, RST_FLAG_CHIP_RESET); + } + + } else { + DBGLOG(REQ, STATE, "[SER][L0] get fgIsResetSqcState=%d\n", + fgIsResetHangState); + DBGLOG(REQ, ERROR, "[SER][L0] RST HANG subcmd(%s) error !\n", + apcArgv[0]); + + return -EFAULT; + } + + return 0; + +} +#endif + +#if CFG_SUPPORT_ANT_DIV +static int priv_driver_ant_diversity_config(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + uint32_t u4Ret; + uint8_t fgRead = FALSE; + uint8_t fgWaitResp = FALSE; + struct CMD_ANT_DIV_CTRL rAntDivInfo; + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -EFAULT; + + rAntDivInfo.ucAction = 0; + rAntDivInfo.ucAntId = 0; + rAntDivInfo.ucRcpi = 0; + rAntDivInfo.ucState = 0; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc == 0) { + DBGLOG(REQ, INFO, "ANT_DIV Argc = %d\n", i4Argc); + return -EFAULT; + } + + if (strnicmp(apcArgv[0], + CMD_GET_ANT_DIV, + strlen(CMD_GET_ANT_DIV)) == 0) { + if (i4Argc < CMD_GET_ANT_DIV_ARG_NUM) { + DBGLOG(REQ, INFO, + "GET_ANT_DIV arg num=%d, must be %d\n", + i4Argc, CMD_GET_ANT_DIV_ARG_NUM); + return -EFAULT; + } + rAntDivInfo.ucAction = ANT_DIV_CMD_GET_ANT; + fgRead = TRUE; + fgWaitResp = TRUE; + } else if (strnicmp(apcArgv[0], + CMD_DETC_ANT_DIV, + strlen(CMD_DETC_ANT_DIV)) == 0) { + if (i4Argc < CMD_DETC_ANT_DIV_ARG_NUM) { + DBGLOG(REQ, INFO, + "DECT_ANT_DIV arg num=%d, must be %d\n", + i4Argc, CMD_DETC_ANT_DIV_ARG_NUM); + return -EFAULT; + } + + rAntDivInfo.ucAction = ANT_DIV_CMD_DETC; + fgRead = TRUE; + fgWaitResp = TRUE; + } else if (strnicmp(apcArgv[0], + CMD_SWH_ANT_DIV, + strlen(CMD_SWH_ANT_DIV)) == 0) { + if (i4Argc < CMD_SWH_ANT_DIV_ARG_NUM) { + DBGLOG(REQ, INFO, + "SWH_ANT_DIV arg num=%d, must be %d\n", + i4Argc, CMD_SWH_ANT_DIV_ARG_NUM); + return -EFAULT; + } + + rAntDivInfo.ucAction = ANT_DIV_CMD_SWH; + fgRead = TRUE; + fgWaitResp = TRUE; + } else if (strnicmp(apcArgv[0], + CMD_SET_ANT_DIV, + strlen(CMD_SET_ANT_DIV)) == 0) { + if (i4Argc < CMD_SET_ANT_DIV_ARG_NUM) { + DBGLOG(REQ, INFO, + "SET_ANT_DIV arg num=%d, must be %d\n", + i4Argc, CMD_SET_ANT_DIV_ARG_NUM); + return -EFAULT; + } + + rAntDivInfo.ucAction = ANT_DIV_CMD_SET_ANT; + fgRead = FALSE; + fgWaitResp = FALSE; + u4Ret = kalkStrtou8(apcArgv[1], 0, &(rAntDivInfo.ucAntId)); + if (u4Ret || + ((rAntDivInfo.ucAntId != 1) && + (rAntDivInfo.ucAntId != 2))) { + DBGLOG(REQ, INFO, + "Parse ANT Index error Ret=%d, AntId =%d\n", + u4Ret, rAntDivInfo.ucAntId); + return -EFAULT; + } + } else { + DBGLOG(REQ, INFO, "ANT DIV subcmd(%s) error !\n", apcArgv[0]); + return -EFAULT; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidAntDivCfg, + &rAntDivInfo, + sizeof(rAntDivInfo), + fgRead, + fgWaitResp, + TRUE, + &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + + if (fgWaitResp) { + DBGLOG(REQ, LOUD, + "[ANT-DIV] priv_driver_ant_diversity_config\n"); + DBGLOG(REQ, LOUD, "[ANT-DIV] action=%d\n", + rAntDivInfo.ucAction); + DBGLOG(REQ, LOUD, "[ANT-DIV] ucState=%d\n", + rAntDivInfo.ucState); + + switch (rAntDivInfo.ucAction) { + case ANT_DIV_CMD_GET_ANT: + i4BytesWritten = scnprintf(pcCommand, + i4TotalLen, + "%d", + rAntDivInfo.ucState); + break; + case ANT_DIV_CMD_DETC: + if (rAntDivInfo.ucState == ANT_DIV_SUCCESS) { + /* rcpi to rssi */ + DBGLOG(REQ, LOUD, + "[ANT-DIV] ucRcpi=%d rssi=%d\n", + rAntDivInfo.ucRcpi, + RCPI_TO_dBm(rAntDivInfo.ucRcpi)); + i4BytesWritten = scnprintf(pcCommand, + i4TotalLen, + "%d", + RCPI_TO_dBm(rAntDivInfo.ucRcpi)); + } else { + i4BytesWritten = scnprintf(pcCommand, + i4TotalLen, + "%d", + rAntDivInfo.ucState); + } + break; + case ANT_DIV_CMD_SWH: + i4BytesWritten = scnprintf(pcCommand, + i4TotalLen, + "%d", + rAntDivInfo.ucState); + break; + default: + DBGLOG(REQ, ERROR, + "[ANT-DIV][WARN] ucAction=%d\n", + rAntDivInfo.ucAction); + i4BytesWritten = scnprintf(pcCommand, + i4TotalLen, "fail"); + break; + } + + DBGLOG(REQ, INFO, "%s: command result is %s\n", + __func__, pcCommand); + } + + return i4BytesWritten; +} +#endif + + + +int priv_driver_set_suspend_mode(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + u_int8_t fgEnable; + uint32_t u4Enable; + int32_t u4Ret = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= 2) { + /* fgEnable = (kalStrtoul(apcArgv[1], NULL, 0) == 1) ? TRUE : + * FALSE; + */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Enable); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse u4Enable error u4Ret=%d\n", + u4Ret); + if (u4Enable == 1) + fgEnable = TRUE; + else + fgEnable = FALSE; + + if (prGlueInfo->fgIsInSuspendMode == fgEnable) { + DBGLOG(REQ, INFO, + "%s: Already in suspend mode [%u], SKIP!\n", + __func__, fgEnable); + return 0; + } + + DBGLOG(REQ, INFO, "%s: Set suspend mode [%u]\n", __func__, + fgEnable); + + prGlueInfo->fgIsInSuspendMode = fgEnable; + + wlanSetSuspendMode(prGlueInfo, fgEnable); + p2pSetSuspendMode(prGlueInfo, fgEnable); + } + + return 0; +} + +#if CFG_SUPPORT_SNIFFER +int priv_driver_set_monitor(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int32_t i4BytesWritten = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + struct PARAM_CUSTOM_MONITOR_SET_STRUCT rMonitorSetInfo; + uint8_t ucEnable = 0; + uint8_t ucPriChannel = 0; + uint8_t ucChannelWidth = 0; + uint8_t ucExt = 0; + uint8_t ucSco = 0; + uint8_t ucChannelS1 = 0; + uint8_t ucChannelS2 = 0; + u_int8_t fgIsLegalChannel = FALSE; + u_int8_t fgError = FALSE; + u_int8_t fgEnable = FALSE; + enum ENUM_BAND eBand = BAND_NULL; + uint32_t u4Parse = 0; + int32_t u4Ret = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc >= 5) { + /* ucEnable = (uint8_t) (kalStrtoul(apcArgv[1], NULL, 0)); + * ucPriChannel = (uint8_t) (kalStrtoul(apcArgv[2], NULL, 0)); + * ucChannelWidth = (uint8_t) (kalStrtoul(apcArgv[3], NULL, 0)); + * ucExt = (uint8_t) (kalStrtoul(apcArgv[4], NULL, 0)); + */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + ucEnable = (uint8_t) u4Parse; + u4Ret = kalkStrtou32(apcArgv[2], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + ucPriChannel = (uint8_t) u4Parse; + u4Ret = kalkStrtou32(apcArgv[3], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + ucChannelWidth = (uint8_t) u4Parse; + u4Ret = kalkStrtou32(apcArgv[4], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + ucExt = (uint8_t) u4Parse; + + eBand = (ucPriChannel <= 14) ? BAND_2G4 : BAND_5G; + fgIsLegalChannel = rlmDomainIsLegalChannel(prAdapter, eBand, + ucPriChannel); + + if (fgIsLegalChannel == FALSE) { + i4BytesWritten = snprintf(pcCommand, i4TotalLen, + "Illegal primary channel %d", + ucPriChannel); + return i4BytesWritten; + } + + switch (ucChannelWidth) { + case 160: + ucChannelWidth = (uint8_t) CW_160MHZ; + ucSco = (uint8_t) CHNL_EXT_SCN; + + if (ucPriChannel >= 36 && ucPriChannel <= 64) + ucChannelS2 = 50; + else if (ucPriChannel >= 100 && ucPriChannel <= 128) + ucChannelS2 = 114; + else + fgError = TRUE; + break; + + case 80: + ucChannelWidth = (uint8_t) CW_80MHZ; + ucSco = (uint8_t) CHNL_EXT_SCN; + + if (ucPriChannel >= 36 && ucPriChannel <= 48) + ucChannelS1 = 42; + else if (ucPriChannel >= 52 && ucPriChannel <= 64) + ucChannelS1 = 58; + else if (ucPriChannel >= 100 && ucPriChannel <= 112) + ucChannelS1 = 106; + else if (ucPriChannel >= 116 && ucPriChannel <= 128) + ucChannelS1 = 122; + else if (ucPriChannel >= 132 && ucPriChannel <= 144) + ucChannelS1 = 138; + else if (ucPriChannel >= 149 && ucPriChannel <= 161) + ucChannelS1 = 155; + else + fgError = TRUE; + break; + + case 40: + ucChannelWidth = (uint8_t) CW_20_40MHZ; + ucSco = (ucExt) ? (uint8_t) CHNL_EXT_SCA : + (uint8_t) CHNL_EXT_SCB; + break; + + case 20: + ucChannelWidth = (uint8_t) CW_20_40MHZ; + ucSco = (uint8_t) CHNL_EXT_SCN; + break; + + default: + fgError = TRUE; + break; + } + + if (fgError) { + i4BytesWritten = + snprintf(pcCommand, i4TotalLen, + "Invalid primary channel %d with bandwidth %d", + ucPriChannel, ucChannelWidth); + return i4BytesWritten; + } + + fgEnable = (ucEnable) ? TRUE : FALSE; + + if (prGlueInfo->fgIsEnableMon != fgEnable) { + prGlueInfo->fgIsEnableMon = fgEnable; + schedule_work(&prGlueInfo->monWork); + } + + kalMemZero(&rMonitorSetInfo, sizeof(rMonitorSetInfo)); + + rMonitorSetInfo.ucEnable = ucEnable; + rMonitorSetInfo.ucPriChannel = ucPriChannel; + rMonitorSetInfo.ucSco = ucSco; + rMonitorSetInfo.ucChannelWidth = ucChannelWidth; + rMonitorSetInfo.ucChannelS1 = ucChannelS1; + rMonitorSetInfo.ucChannelS2 = ucChannelS2; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetMonitor, + &rMonitorSetInfo, sizeof(rMonitorSetInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + i4BytesWritten = + snprintf(pcCommand, i4TotalLen, "set monitor config %s", + (rStatus == WLAN_STATUS_SUCCESS) ? + "success" : "fail"); + + return i4BytesWritten; + } + + i4BytesWritten = snprintf(pcCommand, i4TotalLen, + "monitor [Enable][PriChannel][ChannelWidth][Sco]"); + + return i4BytesWritten; +} +#endif + +static int priv_driver_get_sta_index(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter; + int32_t i4BytesWritten = 0, i4Argc = 0; + uint8_t ucStaIdx, ucWlanIndex; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + uint8_t aucMacAddr[MAC_ADDR_LEN]; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= 2) { + wlanHwAddrToBin(apcArgv[1], &aucMacAddr[0]); + + if (!wlanGetWlanIdxByAddress(prGlueInfo->prAdapter, + &aucMacAddr[0], &ucWlanIndex)) + return i4BytesWritten; + + if (wlanGetStaIdxByWlanIdx(prAdapter, ucWlanIndex, &ucStaIdx) + != WLAN_STATUS_SUCCESS) + return i4BytesWritten; + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "StaIdx = %d, WlanIdx = %d\n", ucStaIdx, + ucWlanIndex); + } + + return i4BytesWritten; +} + +static int priv_driver_get_version(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter; + int32_t i4BytesWritten = 0; + uint32_t u4Offset = 0; + + ASSERT(prNetDev); + + prGlueInfo = *((struct GLUE_INFO **)netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + u4Offset += fwDlGetFwdlInfo(prAdapter, pcCommand, i4TotalLen); + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "WiFi Driver Version %u.%u.%u\n", + NIC_DRIVER_MAJOR_VERSION, + NIC_DRIVER_MINOR_VERSION, + NIC_DRIVER_SERIAL_VERSION); + + i4BytesWritten = (int32_t)u4Offset; + + return i4BytesWritten; +} + +#if CFG_SUPPORT_DBDC +int priv_driver_set_dbdc(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + uint32_t u4Ret, u4Parse; + uint8_t ucDBDCEnable; + /*UINT_8 ucBssIndex;*/ + /*P_BSS_INFO_T prBssInfo;*/ + + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); +#if 0 + for (ucBssIndex = 0; ucBssIndex < (prAdapter->ucHwBssIdNum + 1); + ucBssIndex++) { + prBssInfo = prGlueInfo->prAdapter->aprBssInfo[ucBssIndex]; + pr_info("****BSS %u inUse %u active %u Mode %u priCh %u state %u rfBand %u\n", + ucBssIndex, + prBssInfo->fgIsInUse, + prBssInfo->fgIsNetActive, + prBssInfo->eCurrentOPMode, + prBssInfo->ucPrimaryChannel, + prBssInfo->eConnectionState, + prBssInfo->eBand); + } +#endif + if (prGlueInfo->prAdapter->rWifiVar.eDbdcMode != + ENUM_DBDC_MODE_DYNAMIC) { + DBGLOG(REQ, LOUD, + "Current DBDC mode %u cannot enable/disable DBDC!!\n", + prGlueInfo->prAdapter->rWifiVar.eDbdcMode); + return -1; + } + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc == 2) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", + u4Ret); + + ucDBDCEnable = (uint8_t) u4Parse; + if ((!prGlueInfo->prAdapter->rWifiVar.fgDbDcModeEn && + !ucDBDCEnable) || + (prGlueInfo->prAdapter->rWifiVar.fgDbDcModeEn && + ucDBDCEnable)) + return i4BytesWritten; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetDbdcEnable, + &ucDBDCEnable, 1, FALSE, FALSE, TRUE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + } else { + DBGLOG(INIT, ERROR, "iwpriv wlanXX driver SET_DBDC \n"); + DBGLOG(INIT, ERROR, " 1: enable. 0: disable.\n"); + } + + return i4BytesWritten; +} +#endif /*CFG_SUPPORT_DBDC*/ + +#if CFG_SUPPORT_BATCH_SCAN +#define CMD_BATCH_SET "WLS_BATCHING SET" +#define CMD_BATCH_GET "WLS_BATCHING GET" +#define CMD_BATCH_STOP "WLS_BATCHING STOP" +#endif + +static int priv_driver_get_que_info(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + return qmDumpQueueStatus(prGlueInfo->prAdapter, pcCommand, i4TotalLen); +} + +static int priv_driver_get_mem_info(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + return cnmDumpMemoryStatus(prGlueInfo->prAdapter, pcCommand, + i4TotalLen); +} + +static int priv_driver_get_hif_info(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + return halDumpHifStatus(prGlueInfo->prAdapter, pcCommand, i4TotalLen); +} + +static int priv_driver_get_cnm(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + struct PARAM_GET_CNM_T *prCnmInfo = NULL; + + enum ENUM_DBDC_BN eDbdcIdx, eDbdcIdxMax; + uint8_t ucBssIdx; + struct BSS_INFO *prBssInfo; + enum ENUM_CNM_NETWORK_TYPE_T eNetworkType; + uint8_t ucNss; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + + prCnmInfo = (struct PARAM_GET_CNM_T *)kalMemAlloc( + sizeof(struct PARAM_GET_CNM_T), VIR_MEM_TYPE); + if (prCnmInfo == NULL) + return -1; + + kalMemZero(prCnmInfo, sizeof(struct PARAM_GET_CNM_T)); + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryCnm, prCnmInfo, + sizeof(struct PARAM_GET_CNM_T), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\n[CNM Info]\n"); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "DBDC Mode : %s\n\n", + (prCnmInfo->fgIsDbdcEnable) ? + "Enable" : "Disable"); + + eDbdcIdxMax = (prCnmInfo->fgIsDbdcEnable)?ENUM_BAND_NUM:ENUM_BAND_1; + for (eDbdcIdx = ENUM_BAND_0; eDbdcIdx < eDbdcIdxMax; eDbdcIdx++) { + /* Do not clean history information */ + /* if argc is bigger than 1 */ + if (i4Argc < 2) { + if (prCnmInfo->ucOpChNum[eDbdcIdx] < 3) + prCnmInfo->ucChList[eDbdcIdx][2] = 0; + if (prCnmInfo->ucOpChNum[eDbdcIdx] < 2) + prCnmInfo->ucChList[eDbdcIdx][1] = 0; + if (prCnmInfo->ucOpChNum[eDbdcIdx] < 1) + prCnmInfo->ucChList[eDbdcIdx][0] = 0; + } + + /* backward compatible for 7668 format */ + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "BAND%u channels : %u %u %u\n", + eDbdcIdx, + prCnmInfo->ucChList[eDbdcIdx][0], + prCnmInfo->ucChList[eDbdcIdx][1], + prCnmInfo->ucChList[eDbdcIdx][2]); + + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Band %u OPCH %d [%u, %u, %u]\n", + eDbdcIdx, + prCnmInfo->ucOpChNum[eDbdcIdx], + prCnmInfo->ucChList[eDbdcIdx][0], + prCnmInfo->ucChList[eDbdcIdx][1], + prCnmInfo->ucChList[eDbdcIdx][2]); + + } + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\n"); + + for (ucBssIdx = BSSID_0; ucBssIdx < (BSSID_NUM+1); ucBssIdx++) { + + prBssInfo = prGlueInfo->prAdapter->aprBssInfo[ucBssIdx]; + if (!prBssInfo) + continue; + + eNetworkType = cnmGetBssNetworkType(prBssInfo); + if (prCnmInfo->ucBssInuse[ucBssIdx] && + prCnmInfo->ucBssActive[ucBssIdx] && + ((eNetworkType == ENUM_CNM_NETWORK_TYPE_P2P_GO) || + ((eNetworkType == ENUM_CNM_NETWORK_TYPE_AIS || + eNetworkType == ENUM_CNM_NETWORK_TYPE_P2P_GC) && + (prCnmInfo->ucBssConnectState[ucBssIdx] == + PARAM_MEDIA_STATE_CONNECTED)))) { + if (eNetworkType == ENUM_CNM_NETWORK_TYPE_P2P_GO) { + struct STA_RECORD *prCurrStaRec = + (struct STA_RECORD *) NULL; + + prCurrStaRec = LINK_PEEK_HEAD( + &prBssInfo->rStaRecOfClientList, + struct STA_RECORD, rLinkEntry); + + if (prCurrStaRec != NULL && + IS_CONNECTION_NSS2(prBssInfo, + prCurrStaRec)) { + ucNss = 2; + } else + ucNss = 1; + } else if (prBssInfo->prStaRecOfAP != NULL && + IS_CONNECTION_NSS2(prBssInfo, + prBssInfo->prStaRecOfAP)) { + ucNss = 2; + } else + ucNss = 1; + + } else { + eNetworkType = ENUM_CNM_NETWORK_TYPE_OTHER; + ucNss = prBssInfo->ucNss; + /* Do not show history information */ + /* if argc is 1 */ + if (i4Argc < 2) + continue; + } + + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "BSS%u Inuse%u Act%u ConnStat%u [NetType%u][CH%3u][DBDC b%u][WMM%u b%u][OMAC%u b%u][BW%3u][NSS%u]\n", + ucBssIdx, + prCnmInfo->ucBssInuse[ucBssIdx], + prCnmInfo->ucBssActive[ucBssIdx], + prCnmInfo->ucBssConnectState[ucBssIdx], + eNetworkType, + prCnmInfo->ucBssCh[ucBssIdx], + prCnmInfo->ucBssDBDCBand[ucBssIdx], + prCnmInfo->ucBssWmmSet[ucBssIdx], + prCnmInfo->ucBssWmmDBDCBand[ucBssIdx], + prCnmInfo->ucBssOMACSet[ucBssIdx], + prCnmInfo->ucBssOMACDBDCBand[ucBssIdx], + 20 * (0x01 << rlmGetBssOpBwByVhtAndHtOpInfo(prBssInfo)), + ucNss); + } + + kalMemFree(prCnmInfo, VIR_MEM_TYPE, sizeof(struct PARAM_GET_CNM_T)); + return i4BytesWritten; +} /* priv_driver_get_sw_ctrl */ + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +static int priv_driver_get_ch_rank_list(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t i4BytesWritten = 0; + int8_t ucIdx = 0, ucIdx2 = 0, ucChannelNum = 0, + ucNumOf2gChannel = 0, ucNumOf5gChannel = 0; + struct PARAM_GET_CHN_INFO *prChnLoadInfo = NULL; + struct RF_CHANNEL_INFO *prChannelList = NULL, + auc2gChannelList[MAX_2G_BAND_CHN_NUM], + auc5gChannelList[MAX_5G_BAND_CHN_NUM]; + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prChnLoadInfo = &(prGlueInfo->prAdapter->rWifiVar.rChnLoadInfo); + kalMemZero(pcCommand, i4TotalLen); + + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_2G4, TRUE, + MAX_2G_BAND_CHN_NUM, &ucNumOf2gChannel, + auc2gChannelList); + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_5G, TRUE, + MAX_5G_BAND_CHN_NUM, &ucNumOf5gChannel, + auc5gChannelList); + + for (ucIdx = 0; ucIdx < MAX_CHN_NUM; ucIdx++) { + + if (prChnLoadInfo->rChnRankList[ucIdx].ucChannel > 14) { + prChannelList = auc5gChannelList; + ucChannelNum = ucNumOf5gChannel; + } else { + prChannelList = auc2gChannelList; + ucChannelNum = ucNumOf2gChannel; + } + + for (ucIdx2 = 0; ucIdx2 < ucChannelNum; ucIdx2++) { + if (prChnLoadInfo->rChnRankList[ucIdx].ucChannel == + prChannelList[ucIdx2].ucChannelNum) { + pcCommand[i4BytesWritten++] = + prChnLoadInfo->rChnRankList[ucIdx] + .ucChannel; + DBGLOG(SCN, TRACE, "ch %u, dirtiness %d\n", + prChnLoadInfo->rChnRankList[ucIdx] + .ucChannel, + prChnLoadInfo->rChnRankList[ucIdx] + .u4Dirtiness); + break; + } + } + } + + return i4BytesWritten; +} + +static int priv_driver_get_ch_dirtiness(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int8_t cIdx = 0; + uint8_t ucNumOf2gChannel = 0; + uint8_t ucNumOf5gChannel = 0; + uint32_t i4BytesWritten = 0; + struct PARAM_GET_CHN_INFO *prChnLoadInfo = NULL; + struct RF_CHANNEL_INFO ar2gChannelList[MAX_2G_BAND_CHN_NUM]; + struct RF_CHANNEL_INFO ar5gChannelList[MAX_5G_BAND_CHN_NUM]; + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prChnLoadInfo = &(prGlueInfo->prAdapter->rWifiVar.rChnLoadInfo); + kalMemZero(pcCommand, i4TotalLen); + + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_2G4, TRUE, + MAX_2G_BAND_CHN_NUM, &ucNumOf2gChannel, + ar2gChannelList); + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_5G, TRUE, + MAX_5G_BAND_CHN_NUM, &ucNumOf5gChannel, + ar5gChannelList); + + for (cIdx = 0; cIdx < MAX_CHN_NUM; cIdx++) { + int8_t cIdx2 = 0; + uint8_t ucChannelNum = 0; + uint32_t u4Offset = 0; + struct RF_CHANNEL_INFO *prChannelList = NULL; + + if (prChnLoadInfo->rChnRankList[cIdx].ucChannel > 14) { + prChannelList = ar5gChannelList; + ucChannelNum = ucNumOf5gChannel; + } else { + prChannelList = ar2gChannelList; + ucChannelNum = ucNumOf2gChannel; + } + + for (cIdx2 = 0; cIdx2 < ucChannelNum; cIdx2++) { + if (prChnLoadInfo->rChnRankList[cIdx].ucChannel == + prChannelList[cIdx2].ucChannelNum) { + u4Offset = kalSnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nch %03u -> dirtiness %u", + prChnLoadInfo->rChnRankList[cIdx] + .ucChannel, + prChnLoadInfo->rChnRankList[cIdx] + .u4Dirtiness); + i4BytesWritten += u4Offset; + break; + } + } + } + + return i4BytesWritten; +} +#endif + +static int priv_driver_efuse_ops(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + enum EFUSE_OP_MODE { + EFUSE_READ, + EFUSE_WRITE, + EFUSE_FREE, + EFUSE_INVALID, + }; + uint8_t ucOpMode = EFUSE_INVALID; + uint8_t ucOpChar; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + uint32_t u4Ret; + int32_t i4Parameter; + uint32_t u4Efuse_addr = 0; + uint8_t ucEfuse_value = 0; + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4Offset = 0; + uint32_t u4BufLen = 0; + uint8_t u4Index = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CUSTOM_ACCESS_EFUSE rAccessEfuseInfo; +#endif + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + /* Sanity check */ + if (i4Argc < 2) + goto efuse_op_invalid; + + ucOpChar = (uint8_t)apcArgv[1][0]; + if ((i4Argc == 3) && (ucOpChar == 'r' || ucOpChar == 'R')) + ucOpMode = EFUSE_READ; + else if ((i4Argc == 4) && (ucOpChar == 'w' || ucOpChar == 'W')) + ucOpMode = EFUSE_WRITE; + else if ((ucOpChar == 'f' || ucOpChar == 'F')) + ucOpMode = EFUSE_FREE; + + /* Print out help if input format is wrong */ + if (ucOpMode == EFUSE_INVALID) + goto efuse_op_invalid; + + /* convert address */ + if (ucOpMode == EFUSE_READ || ucOpMode == EFUSE_WRITE) { + u4Ret = kalkStrtos32(apcArgv[2], 16, &i4Parameter); + u4Efuse_addr = (uint32_t)i4Parameter; + } + + /* convert value */ + if (ucOpMode == EFUSE_WRITE) { + u4Ret = kalkStrtos32(apcArgv[3], 16, &i4Parameter); + ucEfuse_value = (uint8_t)i4Parameter; + } + + /* Start operation */ +#if (CFG_EEPROM_PAGE_ACCESS == 1) + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (prGlueInfo->prAdapter && + prGlueInfo->prAdapter->chip_info && + !prGlueInfo->prAdapter->chip_info->is_support_efuse) { + u4Offset += snprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "efuse ops is invalid\n"); + return (int32_t)u4Offset; + } + + kalMemSet(&rAccessEfuseInfo, 0, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE)); + rAccessEfuseInfo.u4Address = (u4Efuse_addr / EFUSE_BLOCK_SIZE) + * EFUSE_BLOCK_SIZE; + u4Index = u4Efuse_addr % EFUSE_BLOCK_SIZE; + + if (ucOpMode == EFUSE_READ) { + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfo, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_SUCCESS) { + u4Offset += snprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "Read success 0x%X = 0x%X\n", u4Efuse_addr, + prGlueInfo->prAdapter->aucEepromVaule[u4Index]); + } + } else if (ucOpMode == EFUSE_WRITE) { + + prGlueInfo->prAdapter->aucEepromVaule[u4Index] = ucEfuse_value; + + kalMemCopy(rAccessEfuseInfo.aucData, + prGlueInfo->prAdapter->aucEepromVaule, 16); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseWrite, + &rAccessEfuseInfo, + sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), + FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus == WLAN_STATUS_SUCCESS) { + u4Offset += snprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "Write success 0x%X = 0x%X\n", + u4Efuse_addr, ucEfuse_value); + } + } else if (ucOpMode == EFUSE_FREE) { + struct PARAM_CUSTOM_EFUSE_FREE_BLOCK rEfuseFreeBlock = {}; + + if (prGlueInfo->prAdapter->fgIsSupportGetFreeEfuseBlockCount + == FALSE) { + u4Offset += snprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "Cannot read free block size\n"); + return (int32_t)u4Offset; + } + rStatus = kalIoctl(prGlueInfo, wlanoidQueryEfuseFreeBlock, + &rEfuseFreeBlock, + sizeof(struct PARAM_CUSTOM_EFUSE_FREE_BLOCK), + TRUE, TRUE, TRUE, &u4BufLen); + if (rStatus == WLAN_STATUS_SUCCESS) { + u4Offset += snprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "Free block size 0x%X\n", + prGlueInfo->prAdapter->u4FreeBlockNum); + } + } +#else + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "efuse ops is invalid\n"); +#endif + + return (int32_t)u4Offset; + +efuse_op_invalid: + + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "\nHelp menu\n"); + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "\tRead:\t\"efuse read addr_hex\"\n"); + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "\tWrite:\t\"efuse write addr_hex val_hex\"\n"); + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "\tFree Blocks:\t\"efuse free\"\n"); + return (int32_t)u4Offset; +} + +#if defined(_HIF_SDIO) && (MTK_WCN_HIF_SDIO == 0) +static int priv_driver_cccr_ops(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + enum CCCR_OP_MODE { + CCCR_READ, + CCCR_WRITE, + CCCR_FREE, + CCCR_INVALID, + }; + uint8_t ucOpMode = CCCR_INVALID; + uint8_t ucOpChar; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i4Ret; + int32_t i4Parameter; + uint32_t u4CCCR_addr = 0; + uint8_t ucCCCR_value = 0; + + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4Offset = 0; + struct GLUE_INFO *prGlueInfo = NULL; + + struct sdio_func *func; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + + if (!IS_SDIO_INF(prGlueInfo)) { + u4Offset += snprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "Not SDIO bus(%d)\n", + prGlueInfo->u4InfType); + return (int32_t)u4Offset; + } + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + /* Sanity check */ + if (i4Argc < 2) + goto cccr_op_invalid; + + ucOpChar = (uint8_t)apcArgv[1][0]; + if ((i4Argc == 3) && (ucOpChar == 'r' || ucOpChar == 'R')) + ucOpMode = CCCR_READ; + else if ((i4Argc == 4) && (ucOpChar == 'w' || ucOpChar == 'W')) + ucOpMode = CCCR_WRITE; + + /* Print out help if input format is wrong */ + if (ucOpMode == CCCR_INVALID) + goto cccr_op_invalid; + + /* convert address */ + if (ucOpMode == CCCR_READ || ucOpMode == CCCR_WRITE) { + i4Ret = kalkStrtos32(apcArgv[2], 16, &i4Parameter); + /* Valid address 0x0~0xFF */ + u4CCCR_addr = (uint32_t)(i4Parameter & 0xFF); + } + + /* convert value */ + if (ucOpMode == CCCR_WRITE) { + i4Ret = kalkStrtos32(apcArgv[3], 16, &i4Parameter); + ucCCCR_value = (uint8_t)i4Parameter; + } + + /* Set SDIO host reference */ + func = prGlueInfo->rHifInfo.func; + + /* Start operation */ + if (ucOpMode == CCCR_READ) { + sdio_claim_host(func); + ucCCCR_value = sdio_f0_readb(func, u4CCCR_addr, &rStatus); + sdio_release_host(func); + + if (rStatus) /* Fail case */ + u4Offset += snprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "Read Fail 0x%X (ret=%d)\n", + u4CCCR_addr, rStatus); + else + u4Offset += snprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "Read success 0x%X = 0x%X\n", + u4CCCR_addr, ucCCCR_value); + } else if (ucOpMode == CCCR_WRITE) { + uint32_t quirks_bak; + + sdio_claim_host(func); + /* Enable capability to write CCCR */ + quirks_bak = func->card->quirks; + func->card->quirks |= MMC_QUIRK_LENIENT_FN0; + /* Write CCCR into card */ + sdio_f0_writeb(func, ucCCCR_value, u4CCCR_addr, &rStatus); + func->card->quirks = quirks_bak; + sdio_release_host(func); + + if (rStatus) /* Fail case */ + u4Offset += snprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "Write Fail 0x%X (ret=%d)\n", + u4CCCR_addr, rStatus); + else + u4Offset += snprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "Write success 0x%X = 0x%X\n", + u4CCCR_addr, ucCCCR_value); + } + + return (int32_t)u4Offset; + +cccr_op_invalid: + + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "\nHelp menu\n"); + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "\tRead:\t\"cccr read addr_hex\"\n"); + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "\tWrite:\t\"cccr write addr_hex val_hex\"\n"); + return (int32_t)u4Offset; +} +#endif /* _HIF_SDIO && (MTK_WCN_HIF_SDIO == 0) */ + +#if CFG_SUPPORT_ADVANCE_CONTROL +static int priv_driver_set_noise(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t u4Ret = 0; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_SET_ID + 1; + uint32_t u4Sel = 0; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + rSwCtrlInfo.u4Id = u4Id; + + if (i4Argc <= 1) { + DBGLOG(REQ, ERROR, "Argc(%d) ERR: SET_NOISE \n", i4Argc); + return -1; + } + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Sel); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + + rSwCtrlInfo.u4Data = u4Sel << 30; + DBGLOG(REQ, LOUD, "u4Sel=%d u4Data=0x%x,\n", u4Sel, rSwCtrlInfo.u4Data); + rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, &rSwCtrlInfo, + sizeof(rSwCtrlInfo), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + return i4BytesWritten; + +} + +static int priv_driver_get_noise(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + CMD_ADVCTL_NOISE_ID; + uint32_t u4Offset = 0; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + int16_t u2Wf0AvgPwr, u2Wf1AvgPwr; + + ASSERT(prNetDev); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = u4Id; + + rStatus = kalIoctl(prGlueInfo, wlanoidQuerySwCtrlRead, &rSwCtrlInfo, + sizeof(rSwCtrlInfo), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + u2Wf0AvgPwr = rSwCtrlInfo.u4Data & 0xFFFF; + u2Wf1AvgPwr = (rSwCtrlInfo.u4Data >> 16) & 0xFFFF; + + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "Noise Idle Avg. Power: WF0:%ddB WF1:%ddB\n", + u2Wf0AvgPwr, u2Wf1AvgPwr); + + i4BytesWritten = (int32_t)u4Offset; + + return i4BytesWritten; + +} /* priv_driver_get_sw_ctrl */ + +static int priv_driver_set_pop(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t u4Ret = 0; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_SET_ID + CMD_ADVCTL_POP_ID; + uint32_t u4Sel = 0, u4CckTh = 0, u4OfdmTh = 0; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + rSwCtrlInfo.u4Id = u4Id; + + if (i4Argc <= 3) { + DBGLOG(REQ, ERROR, + "Argc(%d) ERR: SET_POP \n", + i4Argc); + return -1; + } + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Sel); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + u4Ret = kalkStrtou32(apcArgv[2], 0, &u4CckTh); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + u4Ret = kalkStrtou32(apcArgv[3], 0, &u4OfdmTh); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + + rSwCtrlInfo.u4Data = (u4CckTh | (u4OfdmTh<<8) | (u4Sel<<30)); + DBGLOG(REQ, LOUD, "u4Sel=%d u4CckTh=%d u4OfdmTh=%d, u4Data=0x%x,\n", + u4Sel, u4CckTh, u4OfdmTh, rSwCtrlInfo.u4Data); + rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, &rSwCtrlInfo, + sizeof(rSwCtrlInfo), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + return i4BytesWritten; + +} + +static int priv_driver_get_traffic_report(IN struct net_device + *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + struct CMD_GET_TRAFFIC_REPORT *cmd = NULL; + uint8_t ucBand = ENUM_BAND_0; + uint16_t u2Val = 0; + uint8_t ucVal = 0; + int32_t u4Ret = 0; + u_int8_t fgWaitResp = FALSE; + u_int8_t fgRead = FALSE; + u_int8_t fgGetDbg = FALSE; + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (!prGlueInfo) + goto get_report_invalid; + + cmd = (struct CMD_GET_TRAFFIC_REPORT *) + kalMemAlloc(sizeof(*cmd), VIR_MEM_TYPE); + if (!cmd) + goto get_report_invalid; + + if ((i4Argc > 4) || (i4Argc < 2)) + goto get_report_invalid; + + memset(cmd, 0, sizeof(*cmd)); + + cmd->u2Type = CMD_GET_REPORT_TYPE; + cmd->u2Len = sizeof(*cmd); + cmd->ucBand = ucBand; + + if (strnicmp(apcArgv[1], "ENABLE", strlen("ENABLE")) == 0) { + prGlueInfo->prAdapter->u4IsKeepFullPwrBitmap + |= KEEP_FULL_PWR_TRAFFIC_REPORT_BIT; + cmd->ucAction = CMD_GET_REPORT_ENABLE; + cmd->u2Type |= CMD_ADV_CONTROL_SET; + } else if (strnicmp(apcArgv[1], "DISABLE", strlen("DISABLE")) == 0) { + prGlueInfo->prAdapter->u4IsKeepFullPwrBitmap + &= ~KEEP_FULL_PWR_TRAFFIC_REPORT_BIT; + cmd->ucAction = CMD_GET_REPORT_DISABLE; + cmd->u2Type |= CMD_ADV_CONTROL_SET; + } else if (strnicmp(apcArgv[1], "RESET", strlen("RESET")) == 0) { + cmd->ucAction = CMD_GET_REPORT_RESET; + cmd->u2Type |= CMD_ADV_CONTROL_SET; + } else if ((strnicmp(apcArgv[1], "GET", strlen("GET")) == 0) || + (strnicmp(apcArgv[1], "GETDBG", strlen("GETDBG")) == 0)) { + cmd->ucAction = CMD_GET_REPORT_GET; + fgWaitResp = TRUE; + fgRead = TRUE; + if ((i4Argc == 4) && (strnicmp(apcArgv[2], + "BAND", strlen("BAND")) == 0)) { + u4Ret = kalkStrtou8(apcArgv[3], 0, &ucVal); + cmd->ucBand = ucVal; + } + if (strnicmp(apcArgv[1], "GETDBG", strlen("GETDBG")) == 0) + fgGetDbg = TRUE; + } else if ((strnicmp(apcArgv[1], "SAMPLEPOINTS", + strlen("SAMPLEPOINTS")) == 0) && (i4Argc == 3)) { + u4Ret = kalkStrtou16(apcArgv[2], 0, &u2Val); + cmd->u2SamplePoints = u2Val; + cmd->u2Type |= CMD_ADV_CONTROL_SET; + cmd->ucAction = CMD_SET_REPORT_SAMPLE_POINT; + } else if ((strnicmp(apcArgv[1], "TXTHRES", + strlen("TXTHRES")) == 0) && (i4Argc == 3)) { + u4Ret = kalkStrtou8(apcArgv[2], 0, &ucVal); + /* valid val range is from 0 - 100% */ + if (ucVal > 100) + ucVal = 100; + cmd->ucTxThres = ucVal; + cmd->u2Type |= CMD_ADV_CONTROL_SET; + cmd->ucAction = CMD_SET_REPORT_TXTHRES; + } else if ((strnicmp(apcArgv[1], "RXTHRES", + strlen("RXTHRES")) == 0) && (i4Argc == 3)) { + u4Ret = kalkStrtou8(apcArgv[2], 0, &ucVal); + /* valid val range is from 0 - 100% */ + if (ucVal > 100) + ucVal = 100; + cmd->ucRxThres = ucVal; + cmd->u2Type |= CMD_ADV_CONTROL_SET; + cmd->ucAction = CMD_SET_REPORT_RXTHRES; + } else + goto get_report_invalid; + + DBGLOG(REQ, LOUD, "%s(%s) action %x band %x wait_resp %x\n" + , __func__, pcCommand, cmd->ucAction, ucBand, fgWaitResp); + + rStatus = kalIoctl(prGlueInfo, wlanoidAdvCtrl, cmd, + sizeof(*cmd), TRUE, TRUE, TRUE, &u4BufLen); + + if ((rStatus != WLAN_STATUS_SUCCESS) + && (rStatus != WLAN_STATUS_PENDING)) + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\ncommand failed %x", rStatus); + else if (cmd->ucAction == CMD_GET_REPORT_GET) { + int persentage = 0; + int sample_dur = cmd->u4FetchEd - cmd->u4FetchSt; + + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nCCK false detect cnt: %d" + , (cmd->u4FalseCCA >> EVENT_REPORT_CCK_FCCA) + & EVENT_REPORT_CCK_FCCA_FEILD); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nOFDM false detect cnt: %d" + , (cmd->u4FalseCCA >> EVENT_REPORT_OFDM_FCCA) + & EVENT_REPORT_OFDM_FCCA_FEILD); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nCCK Sig CRC cnt: %d" + , (cmd->u4HdrCRC >> EVENT_REPORT_CCK_SIGERR) + & EVENT_REPORT_CCK_SIGERR_FEILD); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nOFDM Sig CRC cnt: %d" + , (cmd->u4HdrCRC >> EVENT_REPORT_OFDM_SIGERR) + & EVENT_REPORT_OFDM_SIGERR_FEILD); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nBand%d Info:", cmd->ucBand); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\n\tSample every %u ms with %u points", + cmd->u4TimerDur, cmd->u2SamplePoints); + if (fgGetDbg) { + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "from systime%u-%u total_dur %u us f_cost %u us t_drift %d ms" + , cmd->u4FetchSt, cmd->u4FetchEd + , sample_dur + , cmd->u4FetchCost, cmd->TimerDrift); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\n\tbusy-RMAC %u us, idle-TMAC %u us, t_total %u" + , cmd->u4ChBusy, cmd->u4ChIdle, + cmd->u4ChBusy + cmd->u4ChIdle); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\n\theavy tx threshold %u%% rx threshold %u%%" + , cmd->ucTxThres, cmd->ucRxThres); + } + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\n\tch_busy %u us, ch_idle %u us, total_period %u us" + , sample_dur - cmd->u4ChIdle + , cmd->u4ChIdle, sample_dur); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\n\tmy_tx_time: %u us" + , cmd->u4TxAirTime); + if (cmd->u4FetchEd - cmd->u4FetchSt) { + persentage = cmd->u4TxAirTime / (sample_dur / 1000); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + ", tx utility: %d.%1d%%" + , persentage / 10 + , persentage % 10); + } + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\n\tmy_data_rx_time (no BMC data): %u us" + , cmd->u4RxAirTime); + if (cmd->u4FetchEd - cmd->u4FetchSt) { + persentage = cmd->u4RxAirTime / (sample_dur / 1000); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + ", rx utility: %d.%1d%%" + , persentage / 10 + , persentage % 10); + } + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\n\tTotal packet transmitted: %u", + cmd->u4PktSent); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\n\tTotal tx ok packet: %u", + cmd->u4PktSent - cmd->u4PktTxfailed); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\n\tTotal tx failed packet: %u", + cmd->u4PktTxfailed); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\n\tTotal tx retried packet: %u", + cmd->u4PktRetried); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\n\tTotal rx mpdu: %u", cmd->u4RxMPDU); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\n\tTotal rx fcs: %u", cmd->u4RxFcs); + } else + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\ncommand sent %x", rStatus); + + if (cmd) + kalMemFree(cmd, VIR_MEM_TYPE, sizeof(*cmd)); + + return i4BytesWritten; +get_report_invalid: + if (cmd) + kalMemFree(cmd, VIR_MEM_TYPE, sizeof(*cmd)); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nformat:get_report [enable|disable|get|reset]"); + return i4BytesWritten; +} + +static int priv_driver_get_pop(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + CMD_ADVCTL_POP_ID; + uint32_t u4Offset = 0; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + int32_t u4CckTh = 0, u4OfdmTh = 0; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = u4Id; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + u4CckTh = rSwCtrlInfo.u4Data & 0xFF; + u4OfdmTh = (rSwCtrlInfo.u4Data >> 8) & 0xFF; + + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "PoP: CckTh:%ddB OfdmTh:%ddB\n", + u4CckTh, u4OfdmTh); + + i4BytesWritten = (int32_t)u4Offset; + + return i4BytesWritten; + +} + + +static int priv_driver_set_ed(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t i4Ret = 0; + int32_t i4EdVal[2] = { 0 }; + uint32_t u4Sel = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return WLAN_STATUS_FAILURE; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + if (prAdapter == NULL) { + DBGLOG(REQ, LOUD, "Adapter is NULL!\n"); + return WLAN_STATUS_FAILURE; + } + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc <= 3) { + DBGLOG(REQ, ERROR, "Argc(%d) ERR! Parameters for SET_ED:\n", + i4Argc); + DBGLOG(REQ, ERROR, + " <2.4G ED(-49~-81dBm)> <5G ED(-49~-81dBm)>\n"); + + return WLAN_STATUS_FAILURE; + } + + i4Ret = kalkStrtou32(apcArgv[1], 0, &u4Sel); + if (i4Ret) + DBGLOG(REQ, ERROR, "parse error i4Ret=%d\n", i4Ret); + i4Ret = kalkStrtos32(apcArgv[2], 0, &i4EdVal[0]); + if (i4Ret) + DBGLOG(REQ, ERROR, + "parse i4EdVal(2.4G) error i4Ret=%d\n", i4Ret); + i4Ret = kalkStrtos32(apcArgv[3], 0, &i4EdVal[1]); + if (i4Ret) + DBGLOG(REQ, ERROR, + "parse i4EdVal(5G) error u4Ret=%d\n", i4Ret); + + u4Status = wlanSetEd(prAdapter, i4EdVal[0], i4EdVal[1], u4Sel); + + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", u4Status); + return WLAN_STATUS_FAILURE; + } + + return i4BytesWritten; + +} + +static int priv_driver_get_ed(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + CMD_ADVCTL_ED_ID; + uint32_t u4Offset = 0; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + int8_t iEdVal[2] = { 0 }; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return WLAN_STATUS_FAILURE; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = u4Id; + + u4Status = kalIoctl(prGlueInfo, + wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "Status %u\n", u4Status); + if (u4Status != WLAN_STATUS_SUCCESS) + return WLAN_STATUS_FAILURE; + + iEdVal[0] = rSwCtrlInfo.u4Data & 0xFF; + iEdVal[1] = (rSwCtrlInfo.u4Data >> 16) & 0xFF; + + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "ED: 2.4G(%ddB), 5G(%ddB)\n", iEdVal[0], iEdVal[1]); + + i4BytesWritten = (int32_t)u4Offset; + + return i4BytesWritten; + +} + + +static int priv_driver_get_tp_info(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + return kalPerMonGetInfo(prGlueInfo->prAdapter, pcCommand, i4TotalLen); +} + +static int priv_driver_set_pd(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t u4Ret = 0; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_SET_ID + CMD_ADVCTL_PD_ID; + uint32_t u4Sel = 0; + int32_t u4CckTh = 0, u4OfdmTh = 0; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + rSwCtrlInfo.u4Id = u4Id; + + if (i4Argc <= 1) { + DBGLOG(REQ, ERROR, + "Argc(%d) ERR: SET_PD [CCK TH] [OFDM TH]\n", + i4Argc); + return -1; + } + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Sel); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + + if (u4Sel == 1) { + if (i4Argc <= 3) { + DBGLOG(REQ, ERROR, + "Argc(%d) ERR: SET_PD 1 \n", + i4Argc); + return -1; + } + u4Ret = kalkStrtos32(apcArgv[2], 0, &u4CckTh); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", + u4Ret); + u4Ret = kalkStrtos32(apcArgv[3], 0, &u4OfdmTh); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", + u4Ret); + } + + rSwCtrlInfo.u4Data = ((u4OfdmTh & 0xFFFF) | ((u4CckTh & 0xFF) << 16) | + (u4Sel << 30)); + DBGLOG(REQ, LOUD, "u4Sel=%d u4OfdmTh=%d, u4CckTh=%d, u4Data=0x%x,\n", + u4Sel, u4OfdmTh, u4CckTh, rSwCtrlInfo.u4Data); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, &rSwCtrlInfo, + sizeof(rSwCtrlInfo), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + return i4BytesWritten; +} + +static int priv_driver_get_pd(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + CMD_ADVCTL_PD_ID; + uint32_t u4Offset = 0; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + int8_t u4CckTh = 0, u4OfdmTh = 0; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = u4Id; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + u4CckTh = rSwCtrlInfo.u4Data & 0xFF; + u4OfdmTh = (rSwCtrlInfo.u4Data >> 8) & 0xFF; + + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "PD: CckTh:%ddB OfdmTh:%ddB\n", u4CckTh, u4OfdmTh); + + i4BytesWritten = (int32_t)u4Offset; + + return i4BytesWritten; +} + + +static int priv_driver_set_maxrfgain(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t u4Ret = 0; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_SET_ID + CMD_ADVCTL_MAX_RFGAIN_ID; + uint32_t u4Sel = 0; + int32_t u4Wf0Gain = 0, u4Wf1Gain = 0; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + rSwCtrlInfo.u4Id = u4Id; + + if (i4Argc <= 1) { + DBGLOG(REQ, ERROR, + "Argc(%d) ERR: SET_RFGAIN \n", + i4Argc); + return -1; + } + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Sel); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + + if (u4Sel == 1) { + if (i4Argc <= 3) { + DBGLOG(REQ, ERROR, + "Argc(%d) ERR: SET_RFGAIN 1 \n", + i4Argc); + return -1; + } + u4Ret = kalkStrtos32(apcArgv[2], 0, &u4Wf0Gain); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", + u4Ret); + u4Ret = kalkStrtos32(apcArgv[3], 0, &u4Wf1Gain); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", + u4Ret); + } + + rSwCtrlInfo.u4Data = ((u4Wf0Gain & 0xFF) | ((u4Wf1Gain & 0xFF) << 8) | + (u4Sel << 31)); + DBGLOG(REQ, LOUD, "u4Sel=%d u4Wf0Gain=%d, u4Wf1Gain=%d, u4Data=0x%x,\n", + u4Sel, u4Wf0Gain, u4Wf1Gain, rSwCtrlInfo.u4Data); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, &rSwCtrlInfo, + sizeof(rSwCtrlInfo), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + return i4BytesWritten; +} + +static int priv_driver_get_maxrfgain(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + CMD_ADVCTL_MAX_RFGAIN_ID; + uint32_t u4Offset = 0; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + uint8_t u4Wf0Gain = 0, u4Wf1Gain = 0; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = u4Id; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + u4Wf0Gain = rSwCtrlInfo.u4Data & 0xFF; + u4Wf1Gain = (rSwCtrlInfo.u4Data >> 8) & 0xFF; + + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "Max RFGain: WF0:%ddB WF1:%ddB\n", + u4Wf0Gain, u4Wf1Gain); + + i4BytesWritten = (int32_t)u4Offset; + return i4BytesWritten; + +} + +static int priv_driver_noise_histogram(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + uint32_t u4Status = WLAN_STATUS_SUCCESS; + struct GLUE_INFO *prGlueInfo; + int32_t i4BytesWritten = 0; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + struct CMD_NOISE_HISTOGRAM_REPORT *cmd = NULL; + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + if (!prGlueInfo) + goto noise_histogram_invalid; + + cmd = (struct CMD_NOISE_HISTOGRAM_REPORT *)kalMemAlloc(sizeof(*cmd), + VIR_MEM_TYPE); + if (!cmd) + goto noise_histogram_invalid; + + if ((i4Argc > 4) || (i4Argc < 2)) + goto noise_histogram_invalid; + + memset(cmd, 0, sizeof(*cmd)); + + cmd->u2Type = CMD_NOISE_HISTOGRAM_TYPE; + cmd->u2Len = sizeof(*cmd); + + if (strnicmp(apcArgv[1], "ENABLE", strlen("ENABLE")) == 0) { + prGlueInfo->prAdapter->u4IsKeepFullPwrBitmap |= + KEEP_FULL_PWR_NOISE_HISTOGRAM_BIT; + cmd->ucAction = CMD_NOISE_HISTOGRAM_ENABLE; + cmd->u2Type |= CMD_ADV_CONTROL_SET; + } else if (strnicmp(apcArgv[1], "DISABLE", strlen("DISABLE")) == 0) { + prGlueInfo->prAdapter->u4IsKeepFullPwrBitmap &= + ~KEEP_FULL_PWR_NOISE_HISTOGRAM_BIT; + cmd->ucAction = CMD_NOISE_HISTOGRAM_DISABLE; + cmd->u2Type |= CMD_ADV_CONTROL_SET; + } else if (strnicmp(apcArgv[1], "RESET", strlen("RESET")) == 0) { + cmd->ucAction = CMD_NOISE_HISTOGRAM_RESET; + cmd->u2Type |= CMD_ADV_CONTROL_SET; +#if CFG_IPI_2CHAIN_SUPPORT + } else if (strnicmp(apcArgv[1], "GET2", strlen("GET2")) == 0) { + /* + * For getting backward compatibility + * to original format for default chain + */ + cmd->u2Type = CMD_NOISE_HISTOGRAM_TYPE2; + cmd->ucAction = CMD_NOISE_HISTOGRAM_GET; + u4Status = kalIoctl(prGlueInfo, wlanoidAdvCtrl, + cmd, sizeof(*cmd), TRUE, TRUE, TRUE, &u4BufLen); + if (u4Status == WLAN_STATUS_SUCCESS) + parseNoiseHistogramReport(&i4BytesWritten, + pcCommand, &i4TotalLen, cmd); + + cmd->ucAction = CMD_NOISE_HISTOGRAM_GET2; +#endif /* CFG_IPI_2CHAIN_SUPPORT */ + } else if (strnicmp(apcArgv[1], "GET", strlen("GET")) == 0) { + cmd->ucAction = CMD_NOISE_HISTOGRAM_GET; + } else + goto noise_histogram_invalid; + + DBGLOG(REQ, LOUD, "%s(%s) action %x\n" + , __func__, pcCommand, cmd->ucAction); + + u4Status = kalIoctl(prGlueInfo, wlanoidAdvCtrl, cmd, sizeof(*cmd), + TRUE, TRUE, TRUE, &u4BufLen); + + if (u4Status == WLAN_STATUS_NOT_SUPPORTED) { + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nThis fw version does not support priv command: %s\n", + pcCommand); + } else if ((u4Status != WLAN_STATUS_SUCCESS) + && (u4Status != WLAN_STATUS_PENDING)) { + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\ncommand failed %x", u4Status); + } else if (cmd->ucAction == CMD_NOISE_HISTOGRAM_GET +#if CFG_IPI_2CHAIN_SUPPORT + || cmd->ucAction == CMD_NOISE_HISTOGRAM_GET2 +#endif /* CFG_IPI_2CHAIN_SUPPORT */ + ) { + parseNoiseHistogramReport(&i4BytesWritten, + pcCommand, &i4TotalLen, cmd); + } else + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\ncommand sent %x", u4Status); + + if (cmd) + kalMemFree(cmd, VIR_MEM_TYPE, sizeof(*cmd)); + + return i4BytesWritten; +noise_histogram_invalid: + if (cmd) + kalMemFree(cmd, VIR_MEM_TYPE, sizeof(*cmd)); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nformat:get_report [enable|disable|get|reset]"); + return i4BytesWritten; +} + +#if CFG_RX_SINGLE_CHAIN_SUPPORT +static int priv_driver_set_rxchain(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t u4Ret = 0; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_SET_ID + CMD_ADVCTL_RXC_ID; + uint32_t u4Sel = 0; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + uint32_t u4Offset = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + rSwCtrlInfo.u4Id = u4Id; + + if (i4Argc <= 1) { + u4Offset += snprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "SET RX CHAIN:Fail!(%d) SET_RXC\n", i4Argc); + goto out; + } + + /* not connected */ + /* if (prGlueInfo->eParamMediaStateIndicated != + * PARAM_MEDIA_STATE_CONNECTED) { + * u4Offset += snprintf(pcCommand + u4Offset, + * i4TotalLen - u4Offset, + * "SET RX CHAIN: Fail! not connected\n"); + * goto out; + * } + */ + + /* if (prAdapter->rWifiVar.ucNSS > 1 || + * prAdapter->rWifiVar.ucSpeIdxCtrl == 2) { + * u4Offset += snprintf(pcCommand + u4Offset, + * i4TotalLen - u4Offset, + * "SET RX CHAIN: Fail!NSS =%d & + * SpeIdxCtrl =%d wrong setting\n", + * prAdapter->rWifiVar.ucNSS, + * prAdapter->rWifiVar.ucSpeIdxCtrl); + * goto out; + * } + */ + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Sel); + if (u4Ret) { + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + return -1; + } + if ((u4Sel < 0 || u4Sel > 2) && (u4Sel != 5)) { + u4Offset += snprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "SET RX CHAIN:Fail!(%d) not equal 0/1/2/5\n", u4Sel); + goto out; + } + /* else if (u4Sel != prAdapter->rWifiVar.ucSpeIdxCtrl) { + * u4Offset += snprintf(pcCommand + u4Offset, + * i4TotalLen - u4Offset, + * "SET RX CHAIN:Fail!(%d) + * not equal to SpeIdxCtrl(%d)\n", + * u4Sel, prAdapter->rWifiVar.ucSpeIdxCtrl); + * goto out; + * } + */ + + rSwCtrlInfo.u4Data = u4Sel; + rStatus = kalIoctl(prGlueInfo, + wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + u4Offset += snprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "SET RX CHAIN: kalIoctl fail (%d)\n", rStatus); + + goto out; + } else { + u4Offset += snprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "SET RX CHAIN: %d (0: WF0 1:WF1 2:WF0+1 5:Disable)Success\n" + , u4Sel); + } +out: + i4BytesWritten = (int32_t)u4Offset; + + return i4BytesWritten; + +} + +static int priv_driver_get_rxchain(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + CMD_ADVCTL_RXC_ID; + uint32_t u4Offset = 0; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + uint8_t ucRxChain; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + /*not connected*/ + /*if (prGlueInfo->eParamMediaStateIndicated != + * PARAM_MEDIA_STATE_CONNECTED) { + * u4Offset += snprintf(pcCommand + u4Offset, + * i4TotalLen - u4Offset, + * "GET RX CHAIN: Fail! not yet connected\n"); + * goto out; + * } + */ + + + /*if (prAdapter->rWifiVar.ucNSS > 1 || + * prAdapter->rWifiVar.ucSpeIdxCtrl == 2) { + * u4Offset += snprintf(pcCommand + u4Offset, + * i4TotalLen - u4Offset, + * "GET RX CHAIN: Fail! NSS=%d (Need <2) + * SpeIdxCtrl=%d (Need <2) \n", + * prAdapter->rWifiVar.ucNSS, + * prAdapter->rWifiVar.ucSpeIdxCtrl); + * goto out; + * } + */ + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = u4Id; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + ucRxChain = (rSwCtrlInfo.u4Data) & 0xFF; + + + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "GET RX CHAIN: %d (0: WF0 1:WF1 2:WF0+WF1)\n", + ucRxChain); + + /*out:*/ + i4BytesWritten = (int32_t)u4Offset; + + return i4BytesWritten; + +} +#endif +static int priv_driver_set_adm_ctrl(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t u4Ret = 0; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_SET_ID + CMD_ADVCTL_ADM_CTRL_ID; + uint32_t u4Enable = 0, u4TimeRatio = 100, u4AdmBase = 0; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + rSwCtrlInfo.u4Id = u4Id; + + if ((i4Argc > 4) || (i4Argc < 2)) { + DBGLOG(REQ, ERROR, "Argc(%d) ERR: set_adm_ctrl\n", i4Argc); + return -1; + } + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Enable); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse u4Enable error u4Ret=%d\n", u4Ret); + + if (i4Argc > 2) { + /* u4AdmTime default is 100% */ + u4Ret = kalkStrtos32(apcArgv[2], 0, &u4TimeRatio); + if (u4Ret) + DBGLOG(REQ, ERROR, "u4AdmTime err u4Ret=%d\n", u4Ret); + } + + if (i4Argc > 3) { + u4Ret = kalkStrtos32(apcArgv[3], 0, &u4AdmBase); + if (u4Ret) + DBGLOG(REQ, ERROR, "u4AdmBase err u4Ret=%d\n", u4Ret); + } + + rSwCtrlInfo.u4Data = ((u4AdmBase & 0xFFFF) | + ((u4TimeRatio & 0xFF) << 16) | + ((u4Enable & 0xFF) << 24)); + DBGLOG(REQ, LOUD, + "u4Enable=%d u4AdmTime=%d, u4AdmBase=%d, u4Data=0x%x,\n", + u4Enable, u4TimeRatio, u4AdmBase, rSwCtrlInfo.u4Data); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, &rSwCtrlInfo, + sizeof(rSwCtrlInfo), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + return i4BytesWritten; +} + +static int priv_driver_get_adm_ctrl(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + CMD_ADVCTL_ADM_CTRL_ID; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + uint32_t u4Enable = 0, u4TimeRatio = 100, u4AdmBase = 0; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = u4Id; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + u4Enable = (rSwCtrlInfo.u4Data >> 24) & 0xFF; + u4TimeRatio = (rSwCtrlInfo.u4Data >> 16) & 0xFF; + u4AdmBase = rSwCtrlInfo.u4Data & 0xFFFF; + + i4BytesWritten += scnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tAdminCtrl: %s", + (u4Enable) ? + "Enabled" : "Disabled\n"); + + if (u4Enable == 1) + i4BytesWritten += scnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nLimited %% from thermal: %u%%\n", + u4TimeRatio); + + return i4BytesWritten; +} + +#if CFG_ENABLE_1RPD_MMPS_CTRL +static int priv_driver_set_1rpd( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t u4Ret = 0; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_SET_ID + + CMD_ADVCTL_1RPD; + uint32_t u4Enable = FALSE; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + rSwCtrlInfo.u4Id = u4Id; + + if (i4Argc <= 1) { + DBGLOG(REQ, ERROR, "Argc(%d) ERR: SET_1RPD \n", i4Argc); + return -1; + } + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Enable); + + if (u4Ret) { + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nCommand failed, invalid parameter"); + return i4BytesWritten; + } + + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nSet 1RPD %d", u4Enable); + + rSwCtrlInfo.u4Data = u4Enable; + u4Status = kalIoctl(prGlueInfo, + wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + FALSE, FALSE, g_fgIsOid, &u4BufLen); + + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", u4Status); + return -1; + } + + return i4BytesWritten; +} + +static int priv_driver_get_1rpd( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + + CMD_ADVCTL_1RPD; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + uint32_t u4Sel = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = u4Id; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), TRUE, + TRUE, g_fgIsOid, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + u4Sel = rSwCtrlInfo.u4Data & 0xFF; + + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\n1RPD status: %d", u4Sel); + + return i4BytesWritten; + +} +static int priv_driver_set_mmps( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t u4Ret = 0; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_SET_ID + + CMD_ADVCTL_MMPS; + uint32_t u4Enable = FALSE; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + rSwCtrlInfo.u4Id = u4Id; + + if (i4Argc <= 1) { + DBGLOG(REQ, ERROR, "Argc(%d) ERR: SET_NOISE \n", i4Argc); + return -1; + } + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Enable); + + if (u4Ret) { + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nCommand failed, invalid parameter"); + return i4BytesWritten; + } + + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nSet MMPS %d", u4Enable); + + rSwCtrlInfo.u4Data = u4Enable; + rStatus = kalIoctl(prGlueInfo, + wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + FALSE, FALSE, g_fgIsOid, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + return i4BytesWritten; +} + +static int priv_driver_get_mmps( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + + CMD_ADVCTL_MMPS; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + uint32_t u4Sel = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = u4Id; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), TRUE, + TRUE, g_fgIsOid, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + u4Sel = rSwCtrlInfo.u4Data & 0xFF; + + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nMMPS status: %d", u4Sel); + + return i4BytesWritten; +} +#endif +#if CFG_ENABLE_DEWEIGHTING_CTRL +static int priv_driver_set_deweighting_th( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Ret = 0; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_SET_ID + + CMD_ADVCTL_DEWEIGHTING_TH_ID; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + uint32_t u4Sel = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + rSwCtrlInfo.u4Id = u4Id; + + if (i4Argc <= 1) { + DBGLOG(REQ, ERROR, "Argc(%d) ERR: SET_NOISE \n", i4Argc); + return -1; + } + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Sel); + + if (u4Ret) { + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nCommand failed, threshold range is 0 to 15"); + return i4BytesWritten; + } + + if ((u4Sel < 0) || (u4Sel > 15)) { + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nCommand failed, threshold range is 0 to 15"); + return i4BytesWritten; + } + + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nSetting noise difference threshold %d", u4Sel); + + rSwCtrlInfo.u4Data = u4Sel << 16; + rStatus = kalIoctl(prGlueInfo, + wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + return i4BytesWritten; +} + +static int priv_driver_get_deweighting_th( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + + CMD_ADVCTL_DEWEIGHTING_TH_ID; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + uint32_t u4Sel = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = u4Id; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), TRUE, + TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + u4Sel = rSwCtrlInfo.u4Data & 0xFF; + + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nNoise difference threshold is %d", u4Sel); + + return i4BytesWritten; + +} + +static int priv_driver_get_deweighting_noise( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + + CMD_ADVCTL_DEWEIGHTING_NOISE_ID; + uint8_t u2Wf0AvgNoise = 0, u2Wf1AvgNoise = 0; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = u4Id; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + u2Wf1AvgNoise = rSwCtrlInfo.u4Data & 0xFF; + u2Wf0AvgNoise = (rSwCtrlInfo.u4Data >> 16) & 0xFF; + + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nDeweighting Average noise, WF0 = %d, WF1 = %d", + u2Wf0AvgNoise, u2Wf1AvgNoise); + + return i4BytesWritten; +} + +static int priv_driver_get_deweighting_weight( + IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + + CMD_ADVCTL_DEWEIGHTING_WEIGHT_ID; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + uint8_t ucWF0OfdmSetpt, ucWF0CckSetpt, ucWF1OfdmSetpt, ucWF1CckSetpt; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = u4Id; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + ucWF1CckSetpt = rSwCtrlInfo.u4Data & 0xFF; + ucWF1OfdmSetpt = (rSwCtrlInfo.u4Data >> 8) & 0xFF; + ucWF0CckSetpt = (rSwCtrlInfo.u4Data >> 16) & 0xFF; + ucWF0OfdmSetpt = (rSwCtrlInfo.u4Data >> 24) & 0xFF; + + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nDeweighting weight, WF0 ofdm=%02X cck=%02X, WF1 ofdm=%02X cck=%02X", + ucWF0OfdmSetpt, ucWF0CckSetpt, + ucWF1OfdmSetpt, ucWF1CckSetpt); + + return i4BytesWritten; +} +#endif /* CFG_ENABLE_DEWEIGHTING_CTRL */ + + +static int priv_driver_set_bcn_th(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_SET_ID + CMD_ADVCTL_BCN_TH_ID; + int32_t i4Ret = 0; + int8_t ucP2P, ucInfra, ucWithbt; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc != 4) { + i4BytesWritten += scnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nformat:set_bcn_th "); + return i4BytesWritten; + } + + i4Ret = kalkStrtou8(apcArgv[1], 0, &ucP2P); + if (i4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error i4Ret=%d\n", i4Ret); + i4Ret = kalkStrtou8(apcArgv[2], 0, &ucInfra); + if (i4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error i4Ret=%d\n", i4Ret); + i4Ret = kalkStrtou8(apcArgv[3], 0, &ucWithbt); + if (i4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error i4Ret=%d\n", i4Ret); + + rSwCtrlInfo.u4Data = (ucP2P | (ucInfra << 8) | (ucWithbt << 16)); + rSwCtrlInfo.u4Id = u4Id; + + DBGLOG(REQ, LOUD, "ucP2P=%d ucInfra=%d, ucWithbt=%d u4Data=0x%x,\n", + ucP2P, ucInfra, ucWithbt, rSwCtrlInfo.u4Data); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + return i4BytesWritten; +} + + +static int priv_driver_get_bcn_th(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + CMD_ADVCTL_BCN_TH_ID; + int8_t ucAdhoc, ucInfra, ucWithbt; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc != 1) { + i4BytesWritten += scnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nformat:get_bcn_th"); + return i4BytesWritten; + } + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = u4Id; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + ucAdhoc = rSwCtrlInfo.u4Data & 0xFF; + ucInfra = (rSwCtrlInfo.u4Data >> 8) & 0xFF; + ucWithbt = (rSwCtrlInfo.u4Data >> 16) & 0xFF; + + i4BytesWritten += scnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nBeacon loss threshold: P2P:%d, INFRA:%d, With BT:%d\n", + ucAdhoc, ucInfra, ucWithbt); + + return i4BytesWritten; +} + +static int priv_driver_get_bcntimeout_cnt(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + + CMD_ADVCTL_BCNTIMOUT_NUM_ID; + struct PARAM_CUSTOM_SW_CTRL_STRUCT rSwCtrlInfo; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (!prGlueInfo->prAdapter->prAisBssInfo) + return -EFAULT; + rSwCtrlInfo.u4Data = prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + rSwCtrlInfo.u4Id = u4Id; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + i4BytesWritten += scnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\tbeacon timeout count: %d", + rSwCtrlInfo.u4Data); + + return i4BytesWritten; +} + + +#endif /* CFG_SUPPORT_ADVANCE_CONTROL */ + +#if CFG_SUPPORT_GET_MCS_INFO +static int32_t priv_driver_last_sec_mcs_info(struct ADAPTER *prAdapter, + IN char *pcCommand, IN int i4TotalLen, + struct PARAM_TX_MCS_INFO *prTxMcsInfo) +{ + int32_t i4BytesWritten = 0; + uint8_t ucStaIdx = 0, i, j, ucCnt = 0, ucPerSum = 0; + uint16_t u2RateCode; + struct STA_RECORD *prStaRec = NULL; + uint32_t au4RxV0[MCS_INFO_SAMPLE_CNT], au4RxV1[MCS_INFO_SAMPLE_CNT]; + uint32_t txmode, rate, frmode, sgi, nsts, ldpc, stbc, groupid, mu, bw; + uint32_t u4RxV0, u4RxV1; + + + if (prAdapter->prAisBssInfo->prStaRecOfAP != NULL) { + ucStaIdx = prAdapter->prAisBssInfo->prStaRecOfAP->ucIndex; + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaIdx); + } + + if (prStaRec != NULL && prStaRec->fgIsValid && prStaRec->fgIsInUse) { + kalMemCopy(au4RxV0, prStaRec->au4RxV0, sizeof(au4RxV0)); + kalMemCopy(au4RxV1, prStaRec->au4RxV1, sizeof(au4RxV1)); + } else { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Not Connect to AP\n"); + return i4BytesWritten; + } + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\nTx MCS:\n"); + + for (i = 0; i < MCS_INFO_SAMPLE_CNT; i++) { + if (prTxMcsInfo->au2TxRateCode[i] == 0xFFFF) + continue; + + txmode = HW_TX_RATE_TO_MODE(prTxMcsInfo->au2TxRateCode[i]); + if (txmode >= MAX_TX_MODE) + txmode = MAX_TX_MODE; + + rate = HW_TX_RATE_TO_MCS(prTxMcsInfo->au2TxRateCode[i], txmode); + nsts = HW_TX_RATE_TO_NSS(prTxMcsInfo->au2TxRateCode[i]) + 1; + stbc = HW_TX_RATE_TO_STBC(prTxMcsInfo->au2TxRateCode[i]); + bw = GET_TX_MCS_BW(prTxMcsInfo->au2TxRateCode[i]); + sgi = GET_TX_MCS_SGI(prTxMcsInfo->au2TxRateCode[i]); + ldpc = GET_TX_MCS_LDPC(prTxMcsInfo->au2TxRateCode[i]); + + ucCnt = 0; + ucPerSum = 0; + u2RateCode = prTxMcsInfo->au2TxRateCode[i]; + for (j = 0; j < MCS_INFO_SAMPLE_CNT; j++) { + if (u2RateCode == prTxMcsInfo->au2TxRateCode[j]) { + ucPerSum += prTxMcsInfo->aucTxRatePer[j]; + ucCnt++; + prTxMcsInfo->au2TxRateCode[j] = 0xFFFF; + } + } + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", HW_TX_RATE_CCK_STR[rate & 0x3]); + else if (txmode == TX_RATE_MODE_OFDM) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", hw_rate_ofdm_str(rate)); + else if ((txmode == TX_RATE_MODE_HTMIX) || + (txmode == TX_RATE_MODE_HTGF)) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "MCS%d, ", rate); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "NSS%d_MCS%d, ", nsts, rate); +#if 0 + if ((txmode == TX_RATE_MODE_CCK) || + (txmode == TX_RATE_MODE_OFDM)) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", HW_TX_RATE_BW[0]); + else if (i > prHwWlanInfo->rWtblPeerCap.ucChangeBWAfterRateN) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + prHwWlanInfo->rWtblPeerCap. + ucFrequencyCapability < 4 ? + (prHwWlanInfo->rWtblPeerCap. + ucFrequencyCapability > BW_20 ? + HW_TX_RATE_BW[prHwWlanInfo-> + rWtblPeerCap + .ucFrequencyCapability - 1] : + HW_TX_RATE_BW[prHwWlanInfo->rWtblPeerCap + .ucFrequencyCapability]) : + HW_TX_RATE_BW[4]); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", + prHwWlanInfo->rWtblPeerCap. + ucFrequencyCapability < 4 ? + HW_TX_RATE_BW[ + prHwWlanInfo->rWtblPeerCap + .ucFrequencyCapability] : + HW_TX_RATE_BW[4]); +#endif + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", HW_TX_RATE_BW[bw]); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", rate < 4 ? "LP" : "SP"); + else if (txmode == TX_RATE_MODE_OFDM) + ; + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, ", sgi == 0 ? + "LGI" : "SGI"); + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s%s%s [PER: %02d%%]\t", txmode < 5 ? + HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5], + stbc ? ", STBC, " : ", ", + ((ldpc == 0) || + (txmode == TX_RATE_MODE_CCK) || + (txmode == TX_RATE_MODE_OFDM)) ? + "BCC" : "LDPC", ucPerSum/ucCnt); + + for (j = 0; j < ucCnt; j++) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "*"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\n"); + + } + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\nRx MCS:\n"); + + for (i = 0; i < MCS_INFO_SAMPLE_CNT; i++) { + if (au4RxV0[i] == 0xFFFFFFFF) + continue; + + u4RxV0 = au4RxV0[i]; + u4RxV1 = au4RxV1[i]; + + txmode = (u4RxV0 & RX_VT_RX_MODE_MASK) >> RX_VT_RX_MODE_OFFSET; + rate = (u4RxV0 & RX_VT_RX_RATE_MASK) >> RX_VT_RX_RATE_OFFSET; + frmode = (u4RxV0 & RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET; + nsts = ((u4RxV1 & RX_VT_NSTS_MASK) >> RX_VT_NSTS_OFFSET); + stbc = (u4RxV0 & RX_VT_STBC_MASK) >> RX_VT_STBC_OFFSET; + sgi = u4RxV0 & RX_VT_SHORT_GI; + ldpc = u4RxV0 & RX_VT_LDPC; + groupid = (u4RxV1 & RX_VT_GROUP_ID_MASK) + >> RX_VT_GROUP_ID_OFFSET; + + if (groupid && groupid != 63) { + mu = 1; + } else { + mu = 0; + nsts += 1; + } + + /* Distribution Calculation clear the same sample content */ + ucCnt = 0; + for (j = 0; j < MCS_INFO_SAMPLE_CNT; j++) { + if ((u4RxV0 & RX_MCS_INFO_MASK) == + (au4RxV0[j] & RX_MCS_INFO_MASK)) { + au4RxV0[j] = 0xFFFFFFFF; + ucCnt++; + } + } + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + rate < 4 ? HW_TX_RATE_CCK_STR[rate] : + HW_TX_RATE_CCK_STR[4]); + else if (txmode == TX_RATE_MODE_OFDM) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + hw_rate_ofdm_str(rate)); + else if ((txmode == TX_RATE_MODE_HTMIX) || + (txmode == TX_RATE_MODE_HTGF)) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "MCS%d, ", rate); + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "NSS%d_MCS%d, ", + nsts, rate); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + frmode < 4 ? HW_TX_RATE_BW[frmode] : HW_TX_RATE_BW[4]); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + rate < 4 ? "LP" : "SP"); + else if (txmode == TX_RATE_MODE_OFDM) + ; + else + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + sgi == 0 ? "LGI" : "SGI"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s", + stbc == 0 ? "" : "STBC, "); + + if (mu) { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%s, %s, %s (%d)\n", + txmode < 5 ? + HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5], + ldpc == 0 ? "BCC" : "LDPC", "MU", groupid); + } else { + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, %s\n", + txmode < 5 ? + HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5], + ldpc == 0 ? "BCC" : "LDPC"); + } + + for (j = 0; j < ucCnt; j++) + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "*"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "\n"); + } + + + return i4BytesWritten; +} + +static int32_t priv_driver_get_mcs_info(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + int32_t i4BytesWritten = 0, i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + struct PARAM_TX_MCS_INFO *prTxMcsInfo = NULL; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (prAdapter->rRxMcsInfoTimer.pfMgmtTimeOutFunc == NULL) { + cnmTimerInitTimer(prAdapter, + &prAdapter->rRxMcsInfoTimer, + (PFN_MGMT_TIMEOUT_FUNC) wlanRxMcsInfoMonitor, + (unsigned long) NULL); + } + + if (i4Argc >= 2) { + if (strnicmp(apcArgv[1], "START", strlen("START")) == 0) { + cnmTimerStartTimer(prAdapter, + &prAdapter->rRxMcsInfoTimer, MCS_INFO_SAMPLE_PERIOD); + prAdapter->fgIsMcsInfoValid = TRUE; + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nStart the MCS Info Function\n"); + return i4BytesWritten; + } else if (strnicmp(apcArgv[1], "STOP", strlen("STOP")) == 0) { + cnmTimerStopTimer(prAdapter, + &prAdapter->rRxMcsInfoTimer); + prAdapter->fgIsMcsInfoValid = FALSE; + + i4BytesWritten += kalScnprintf( + pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nStop the MCS Info Function\n"); + return i4BytesWritten; + } + } + + if (prGlueInfo->prAdapter->fgIsMcsInfoValid != TRUE) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nWARNING: Use GET_MCS_INFO [START/STOP]\n"); + return i4BytesWritten; + } + + + if (rStatus != WLAN_STATUS_SUCCESS) + goto out; + + prTxMcsInfo = (struct PARAM_TX_MCS_INFO *)kalMemAlloc( + sizeof(struct PARAM_TX_MCS_INFO), VIR_MEM_TYPE); + if (!prTxMcsInfo) { + DBGLOG(REQ, ERROR, "Allocate prTxMcsInfo failed!\n"); + i4BytesWritten = -1; + goto out; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidTxQueryMcsInfo, prTxMcsInfo, + sizeof(struct PARAM_TX_MCS_INFO), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + goto out; + + i4BytesWritten = priv_driver_last_sec_mcs_info(prGlueInfo->prAdapter, + pcCommand, i4TotalLen, prTxMcsInfo); + + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + +out: + + if (prTxMcsInfo) + kalMemFree(prTxMcsInfo, VIR_MEM_TYPE, + sizeof(struct PARAM_TX_MCS_INFO)); + + return i4BytesWritten; +} +#endif /* CFG_SUPPORT_GET_MCS_INFO */ + +#if CFG_ENABLE_WIFI_DIRECT +static int priv_driver_set_p2p_ps(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct BSS_INFO *prBssInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t ucRoleIdx; + uint8_t ucBssIdx; + uint32_t u4CTwindowMs; + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecBssInfo = NULL; + struct PARAM_CUSTOM_OPPPS_PARAM_STRUCT *rOppPsParam = NULL; + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc < 2) { + DBGLOG(REQ, ERROR, + "Expect param: . argc=%d now\n", i4Argc); + return -1; + } + + if (kalkStrtou32(apcArgv[1], 0, &ucRoleIdx)) { + DBGLOG(REQ, ERROR, "parse ucRoleIdx error\n"); + return -1; + } + + if (kalkStrtou32(apcArgv[2], 0, &u4CTwindowMs)) { + DBGLOG(REQ, ERROR, "parse u4CTwindowMs error\n"); + return -1; + } + + /* get Bss Index from ndev */ + if (p2pFuncRoleToBssIdx(prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "can't find ucBssIdx\n"); + return -1; + } + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + if (!(prBssInfo->fgIsInUse) || (prBssInfo->eIftype != IFTYPE_P2P_GO)) { + DBGLOG(REQ, ERROR, "wrong bss InUse=%d, iftype=%d\n", + prBssInfo->fgIsInUse, prBssInfo->eIftype); + return -1; + } + + DBGLOG(REQ, INFO, "ucRoleIdx=%d, ucBssIdx=%d, u4CTwindowMs=%d\n", + ucRoleIdx, ucBssIdx, u4CTwindowMs); + + if (u4CTwindowMs > 0) + u4CTwindowMs |= BIT(7); /* FW checks BIT(7) for enable */ + + prP2pSpecBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo[ucRoleIdx]; + rOppPsParam = &prP2pSpecBssInfo->rOppPsParam; + rOppPsParam->u4CTwindowMs = u4CTwindowMs; + rOppPsParam->ucBssIdx = ucBssIdx; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetOppPsParam, rOppPsParam, + sizeof(struct PARAM_CUSTOM_OPPPS_PARAM_STRUCT), + FALSE, FALSE, TRUE, &u4BufLen); + + return !(rStatus == WLAN_STATUS_SUCCESS); +} + +static int priv_driver_set_p2p_noa(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct BSS_INFO *prBssInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint8_t ucBssIdx; + uint32_t ucRoleIdx; + uint32_t u4NoaDurationMs; + uint32_t u4NoaIntervalMs; + uint32_t u4NoaCount; + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecBssInfo = NULL; + struct PARAM_CUSTOM_NOA_PARAM_STRUCT *rNoaParam = NULL; + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc < 4) { + DBGLOG(REQ, ERROR, + "SET_P2P_NOA \n"); + return -1; + } + + if (kalkStrtou32(apcArgv[1], 0, &ucRoleIdx)) { + DBGLOG(REQ, ERROR, "parse ucRoleIdx error\n"); + return -1; + } + + if (kalkStrtou32(apcArgv[2], 0, &u4NoaCount)) { + DBGLOG(REQ, ERROR, "parse u4NoaCount error\n"); + return -1; + } + + if (kalkStrtou32(apcArgv[3], 0, &u4NoaIntervalMs)) { + DBGLOG(REQ, ERROR, "parse u4NoaIntervalMs error\n"); + return -1; + } + + if (kalkStrtou32(apcArgv[4], 0, &u4NoaDurationMs)) { + DBGLOG(REQ, ERROR, "parse u4NoaDurationMs error\n"); + return -1; + } + + /* get Bss Index from ndev */ + if (p2pFuncRoleToBssIdx(prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "can't find ucBssIdx\n"); + return -1; + } + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + if (!(prBssInfo->fgIsInUse) || (prBssInfo->eIftype != IFTYPE_P2P_GO)) { + DBGLOG(REQ, ERROR, "wrong bss InUse=%d, iftype=%d\n", + prBssInfo->fgIsInUse, prBssInfo->eIftype); + return -1; + } + + DBGLOG(REQ, INFO, + "RoleIdx=%d, BssIdx=%d, count=%d, interval=%d, duration=%d\n", + ucRoleIdx, ucBssIdx, u4NoaCount, u4NoaIntervalMs, + u4NoaDurationMs); + + prP2pSpecBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo[ucRoleIdx]; + rNoaParam = &prP2pSpecBssInfo->rNoaParam; + rNoaParam->u4NoaCount = u4NoaCount; + rNoaParam->u4NoaIntervalMs = u4NoaIntervalMs; + rNoaParam->u4NoaDurationMs = u4NoaDurationMs; + rNoaParam->ucBssIdx = ucBssIdx; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetNoaParam, rNoaParam, + sizeof(struct PARAM_CUSTOM_NOA_PARAM_STRUCT), + FALSE, FALSE, TRUE, &u4BufLen); + + return !(rStatus == WLAN_STATUS_SUCCESS); +} +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +static int priv_driver_set_drv_ser(struct net_device *prNetDev, + char *pcCommand, int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t i4Argc = 0; + int32_t i4BytesWritten = 0; + uint32_t u4Num = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc <= 0) { + DBGLOG(REQ, ERROR, "Argc(%d) ERR: Set driver SER\n", i4Argc); + return -1; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidSetDrvSer, + (void *)&u4Num, sizeof(uint32_t), + FALSE, FALSE, FALSE, &u4BufLen); + + i4BytesWritten += snprintf(pcCommand, i4TotalLen, + "trigger driver SER\n"); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + return i4BytesWritten; +} + +static int priv_driver_set_amsdu_num(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t i4Argc = 0; + int32_t i4BytesWritten = 0; + int32_t u4Ret = 0; + uint32_t u4Num = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc <= 1) { + DBGLOG(REQ, ERROR, "Argc(%d) ERR: Sw Amsdu Num\n", i4Argc); + return -1; + } + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Num); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse amsdu num error u4Ret=%d\n", u4Ret); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAmsduNum, + (void *)&u4Num, sizeof(uint32_t), + FALSE, FALSE, FALSE, &u4BufLen); + + i4BytesWritten += snprintf(pcCommand, i4TotalLen, + "Set Sw Amsdu Num:%u\n", u4Num); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + return i4BytesWritten; + +} + +static int priv_driver_set_amsdu_size(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t i4Argc = 0; + int32_t i4BytesWritten = 0; + int32_t u4Ret = 0; + uint32_t u4Size = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc <= 1) { + DBGLOG(REQ, ERROR, "Argc(%d) ERR: Sw Amsdu Max Size\n", i4Argc); + return -1; + } + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Size); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse amsdu size error u4Ret=%d\n", u4Ret); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAmsduSize, + (void *)&u4Size, sizeof(uint32_t), + FALSE, FALSE, FALSE, &u4BufLen); + + i4BytesWritten += snprintf(pcCommand, i4TotalLen, + "Set Sw Amsdu Max Size:%u\n", u4Size); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + return i4BytesWritten; + +} + +#if CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT +static int priv_driver_bss_transition_query(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + uint8_t *pucQueryReason = NULL; + + if (strnicmp(pcCommand, "BSS-TRANSITION-QUERY", 20) == 0) { + if (strnicmp(pcCommand+20, " reason=", 8) == 0) { + pucQueryReason = pcCommand + 28; + DBGLOG(REQ, INFO, + "BSS-TRANSITION-QUERY, pucQueryReason=%s\r\n", + pucQueryReason); + } + } + if ((pucQueryReason != NULL) && (strlen(pucQueryReason) > 3)) { + DBGLOG(REQ, ERROR, "ERR: BTM query wrong reason!\r\n"); + return -EFAULT; + } + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + if (!prGlueInfo) + return -EFAULT; + + if (!prGlueInfo->prAdapter->prAisBssInfo) + return -EFAULT; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSendBTMQuery, + (void *)pucQueryReason, strlen(pucQueryReason), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\r\n", rStatus); + return -1; + } + + return i4BytesWritten; +} +#endif +#if CFG_SUPPORT_802_11K +static int priv_driver_neighbor_request(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = 0; + uint8_t *pucSSID = NULL; + + if (strnicmp(pcCommand, "NEIGHBOR-REQUEST", 16) == 0) { + if (strnicmp(pcCommand+16, " SSID=", 6) == 0) { + pucSSID = pcCommand + 22; + DBGLOG(REQ, INFO, + "NEIGHBOR-REQUEST, ssid=%s\r\n", pucSSID); + } + } + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + if (!prGlueInfo) + return -EFAULT; + + if (!prGlueInfo->prAdapter->prAisBssInfo) + return -EFAULT; + + if (pucSSID == NULL) + rStatus = kalIoctl(prGlueInfo, + wlanoidSendNeighborRequest, + NULL, 0, FALSE, FALSE, TRUE, &u4BufLen); + else + rStatus = kalIoctl(prGlueInfo, + wlanoidSendNeighborRequest, + pucSSID, kalStrLen(pucSSID), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\r\n", rStatus); + return -1; + } + + return i4BytesWritten; +} +#endif + +int priv_driver_get_bsstable(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + int32_t i4BytesWritten = 0; + struct GLUE_INFO *prGlueInfo = NULL; + struct SCAN_INFO *prScanInfo; + struct LINK *prBSSDescList; + struct BSS_DESC *prBssDesc; + struct ADAPTER *prAdapter = NULL; + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nBSSID, rssi0, rssi1\n------\n"); + + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, + struct BSS_DESC) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "%02x:%02x:%02x:%02x:%02x:%02x, %d, %d\n", + prBssDesc->aucBSSID[0], prBssDesc->aucBSSID[1], + prBssDesc->aucBSSID[2], prBssDesc->aucBSSID[3], + prBssDesc->aucBSSID[4], prBssDesc->aucBSSID[5], + RCPI_TO_dBm(prBssDesc->ucRCPI0), + RCPI_TO_dBm(prBssDesc->ucRCPI1)); + } + + return i4BytesWritten; +} + +#ifdef CFG_SUPPORT_TIME_MEASURE +int priv_driver_start_ftm(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct PARAM_TM_T *prTmParam = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t u4Ret = 0; + int8_t *pucMac; + uint32_t u4BufLen; + uint8_t fgWaitResp = TRUE; + + if (prNetDev == NULL) + return -EFAULT; + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + prTmParam = + (struct PARAM_TM_T *)kalMemAlloc(sizeof(struct PARAM_TM_T), + VIR_MEM_TYPE); + if (!prTmParam) { + DBGLOG(REQ, ERROR, + "Can not alloc memory for prTmParam\n"); + return -ENOMEM; + } + kalMemZero(prTmParam, sizeof(struct PARAM_TM_T)); + + if (i4Argc >= 5) { + pucMac = apcArgv[1]; + pucMac[2] = '\0'; + u4Ret = kalkStrtou8(pucMac, 16, &prTmParam->aucRttPeerAddr[0]); + pucMac += 3; + pucMac[2] = '\0'; + u4Ret = kalkStrtou8(pucMac, 16, &prTmParam->aucRttPeerAddr[1]); + pucMac += 3; + pucMac[2] = '\0'; + u4Ret = kalkStrtou8(pucMac, 16, &prTmParam->aucRttPeerAddr[2]); + pucMac += 3; + pucMac[2] = '\0'; + u4Ret = kalkStrtou8(pucMac, 16, &prTmParam->aucRttPeerAddr[3]); + pucMac += 3; + pucMac[2] = '\0'; + u4Ret = kalkStrtou8(pucMac, 16, &prTmParam->aucRttPeerAddr[4]); + pucMac += 3; + pucMac[2] = '\0'; + u4Ret = kalkStrtou8(pucMac, 16, &prTmParam->aucRttPeerAddr[5]); + + u4Ret = kalkStrtou8(apcArgv[2], 0, &prTmParam->ucFTMBandwidth); + u4Ret = kalkStrtou8(apcArgv[3], 0, &prTmParam->ucFTMNum); + u4Ret = kalkStrtou8(apcArgv[4], 0, + &prTmParam->ucMinDeltaIn100US); + + prTmParam->u4DistanceCm = 0; + prTmParam->u2NumOfValidResult = 0; + prTmParam->u8DistStdevSq = 0; + + DBGLOG(REQ, INFO, + "TMR PeerMac["MACSTR"] BW[%d] ucFTMNum[%d] ucMinDeltaFtm[%d]\n", + MAC2STR(prTmParam->aucRttPeerAddr), + prTmParam->ucFTMBandwidth, + prTmParam->ucFTMNum, + prTmParam->ucMinDeltaIn100US); + + if (strnicmp(apcArgv[0], CMD_START_FTM_NON_BLOCK, + strlen(CMD_START_FTM_NON_BLOCK)) == 0) { + fgWaitResp = FALSE; + prTmParam->u4DistanceCm = 1; + } else + fgWaitResp = TRUE; + + u4Ret = kalIoctl(prGlueInfo, wlanoidQueryStartFtm, prTmParam, + sizeof(struct PARAM_TM_T), fgWaitResp, + fgWaitResp, TRUE, &u4BufLen); + } + + if (prTmParam) { + i4BytesWritten = snprintf(pcCommand, i4TotalLen, + "["MACSTR"] Success = %d, Distance = %d (cm), STDEV = %lld", + MAC2STR(prTmParam->aucRttPeerAddr), + prTmParam->u2NumOfValidResult, + prTmParam->u4DistanceCm, + prTmParam->u8DistStdevSq); + + } + kalMemFree(prTmParam, VIR_MEM_TYPE, sizeof(struct PARAM_TM_T)); + return i4BytesWritten; +} + +int priv_driver_get_ftm(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct PARAM_TM_T *prTmParam = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t u4Ret = 0; + uint32_t u4BufLen; + struct timespec Ftmtv_raw; + uint64_t u8SysClkns; + + if (prNetDev == NULL) + return -EFAULT; + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + prTmParam = (struct PARAM_TM_T *)kalMemAlloc( + sizeof(struct PARAM_TM_T), VIR_MEM_TYPE); + if (!prTmParam) { + DBGLOG(REQ, ERROR, "Can not alloc memory for prTmParam\n"); + return -ENOMEM; + } + kalMemZero(prTmParam, sizeof(struct PARAM_TM_T)); + if (strnicmp(pcCommand, CMD_GET_TMR_AUDIOSYNC, + strlen(CMD_GET_TMR_AUDIOSYNC)) == 0) { + prTmParam->ucTmCategory = TM_ACTION_TMSYNC_QUERY; + } else if (strnicmp(pcCommand, CMD_GET_TMR_DISTANCE, + strlen(CMD_GET_TMR_DISTANCE)) == 0) { + prTmParam->ucTmCategory = TM_ACTION_DISTANCE_QUERY; + } + u4Ret = kalIoctl(prGlueInfo, wlanoidQueryFtm, prTmParam, + sizeof(struct PARAM_TM_T), + TRUE, TRUE, TRUE, &u4BufLen); + + if (prTmParam) { + if (prTmParam->ucTmCategory == TM_ACTION_TMSYNC_QUERY) { + i4BytesWritten = snprintf(pcCommand, i4TotalLen, + "["MACSTR"] Success = %d\n\n", + MAC2STR(prTmParam->aucRttPeerAddr), + prTmParam->u2NumOfValidResult); + + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Clk Value = %lld (ps)\n", + prTmParam->u8Tsf); + + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Clk Offset = %lld (ps)\n", + prTmParam->i8ClockOffset); + + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "CODPer10ms = %lld (ps)\n", + prTmParam->i8ClkRateDiffRatioIn10ms); + + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Last ToA = %lld (ps)\n", + prTmParam->u8LastToA); + + getrawmonotonic(&Ftmtv_raw); + u8SysClkns = (uint64_t)(Ftmtv_raw.tv_sec * 1000000000LL + + Ftmtv_raw.tv_nsec); + + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Cur SysClk = %lld (ns)\n", + u8SysClkns); + + u8SysClkns = nicFtmRAWASCtrl(u8SysClkns); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "Cur GlbCnt = %lld (ps)\n", + u8SysClkns); + + } else if (prTmParam->ucTmCategory == + TM_ACTION_DISTANCE_QUERY) { + i4BytesWritten = snprintf(pcCommand, i4TotalLen, + "["MACSTR"] Success = %d, Distance = %d (cm), STDEV = %lld", + MAC2STR(prTmParam->aucRttPeerAddr), + prTmParam->u2NumOfValidResult, + prTmParam->u4DistanceCm, + prTmParam->u8DistStdevSq); + } + } + kalMemFree(prTmParam, VIR_MEM_TYPE, sizeof(struct PARAM_TM_T)); + return i4BytesWritten; +} + +int priv_driver_enable_tmr(IN struct net_device *prNetDev, + IN char *pcCommand, + IN int i4TotalLen) +{ + struct PARAM_TM_T *prTmParam = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t u4Ret = 0; + uint32_t u4BufLen; + + if (prNetDev == NULL) + return -EFAULT; + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + prTmParam = (struct PARAM_TM_T *)kalMemAlloc( + sizeof(struct PARAM_TM_T), VIR_MEM_TYPE); + if (!prTmParam) { + DBGLOG(REQ, ERROR, + "Can not alloc memory for prTmParam\n"); + return -ENOMEM; + } + kalMemZero(prTmParam, sizeof(struct PARAM_TM_T)); + + if (i4Argc >= 2) { + u4Ret = kalkStrtou8(apcArgv[1], 0, &prTmParam->fgFtmEnable); + + u4Ret = kalIoctl(prGlueInfo, wlanoidSetEnableTmr, prTmParam, + sizeof(struct PARAM_TM_T), + FALSE, FALSE, TRUE, &u4BufLen); + } + kalMemFree(prTmParam, VIR_MEM_TYPE, sizeof(struct PARAM_TM_T)); + return i4BytesWritten; + +} +#endif + +#if CFG_SUPPORT_WAC +static int priv_driver_set_wac_ie_enable(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct BSS_INFO *prBssInfo = NULL; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + int32_t u4Ret = 0; + int32_t Enable = -1; + uint8_t ucRoleIdx = 0, ucBssIdx = 0; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + u4Ret = kalkStrtos32(apcArgv[1], 0, &Enable); + + if (u4Ret) + DBGLOG(REQ, ERROR, "parse bEnable error u4Ret=%d\n", u4Ret); + + if (Enable == 0) { + DBGLOG(REQ, INFO, "disable WAC IE!\n"); + prAdapter->rWifiVar.fgEnableWACIE = FALSE; + } else if (Enable == 1) { + DBGLOG(REQ, INFO, "enable WAC IE!\n"); + prAdapter->rWifiVar.fgEnableWACIE = TRUE; + } else { + DBGLOG(REQ, INFO, "invalid WAC IE enable flag!\n"); + return -1; + } + + /* get Bss Index from ndev */ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prNetDev, &ucRoleIdx) != 0) { + DBGLOG(REQ, ERROR, "Failed to get role index!\n"); + return -1; + } + if (p2pFuncRoleToBssIdx(prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "Failed to get Bss index!\n"); + return -1; + } + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + bssUpdateBeaconContent(prAdapter, prBssInfo->ucBssIndex); + + return 0; +} +#endif + +int32_t priv_driver_cmds(IN struct net_device *prNetDev, IN int8_t *pcCommand, + IN int32_t i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = 0; + + if (g_u4HaltFlag) { + DBGLOG(REQ, WARN, "wlan is halt, skip priv_driver_cmds\n"); + return -1; + } + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + if (strnicmp(pcCommand, CMD_RSSI, strlen(CMD_RSSI)) == 0) { + /* i4BytesWritten = + * wl_android_get_rssi(net, command, i4TotalLen); + */ + } else if (strnicmp(pcCommand, CMD_AP_START, + strlen(CMD_AP_START)) == 0) { + i4BytesWritten = priv_driver_set_ap_start(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_LINKSPEED, + strlen(CMD_LINKSPEED)) == 0) { + i4BytesWritten = priv_driver_get_linkspeed(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_PNOSSIDCLR_SET, + strlen(CMD_PNOSSIDCLR_SET)) == 0) { + /* ToDo:: Nothing */ + } else if (strnicmp(pcCommand, CMD_PNOSETUP_SET, + strlen(CMD_PNOSETUP_SET)) == 0) { + /* ToDo:: Nothing */ + } else if (strnicmp(pcCommand, CMD_PNOENABLE_SET, + strlen(CMD_PNOENABLE_SET)) == 0) { + /* ToDo:: Nothing */ + } else if (strnicmp(pcCommand, CMD_SETSUSPENDOPT, + strlen(CMD_SETSUSPENDOPT)) == 0) { + /* i4BytesWritten = wl_android_set_suspendopt(net, + * pcCommand, i4TotalLen); + */ + } else if (strnicmp(pcCommand, CMD_SETSUSPENDMODE, + strlen(CMD_SETSUSPENDMODE)) == 0) { + i4BytesWritten = priv_driver_set_suspend_mode(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SETBAND, + strlen(CMD_SETBAND)) == 0) { + i4BytesWritten = priv_driver_set_band(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GETBAND, + strlen(CMD_GETBAND)) == 0) { + /* i4BytesWritten = wl_android_get_band(net, pcCommand, + * i4TotalLen); + */ + } else if (strnicmp(pcCommand, CMD_SET_TXPOWER, + strlen(CMD_SET_TXPOWER)) == 0) { + i4BytesWritten = priv_driver_set_txpower(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_COUNTRY, + strlen(CMD_COUNTRY)) == 0) { + i4BytesWritten = priv_driver_set_country(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_CSA, + strlen(CMD_CSA)) == 0) { + i4BytesWritten = priv_driver_set_csa(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_COUNTRY, + strlen(CMD_GET_COUNTRY)) == 0) { + i4BytesWritten = priv_driver_get_country(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_CHANNELS, + strlen(CMD_GET_CHANNELS)) == 0) { + i4BytesWritten = priv_driver_get_channels(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_AP_CHANNELS, + strlen(CMD_GET_AP_CHANNELS)) == 0) { + i4BytesWritten = priv_driver_get_ap_channels(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_MIRACAST, + strlen(CMD_MIRACAST)) == 0) { + i4BytesWritten = priv_driver_set_miracast(prNetDev, + pcCommand, i4TotalLen); + } + /* Mediatek private command */ + else if (strnicmp(pcCommand, CMD_SET_SW_CTRL, + strlen(CMD_SET_SW_CTRL)) == 0) { + i4BytesWritten = priv_driver_set_sw_ctrl(prNetDev, + pcCommand, i4TotalLen); +#if (CFG_SUPPORT_RA_GEN == 1) + } else if (strnicmp(pcCommand, CMD_SET_FIXED_FALLBACK, + strlen(CMD_SET_FIXED_FALLBACK)) == 0) { + i4BytesWritten = priv_driver_set_fixed_fallback( + prNetDev, pcCommand, + i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_RA_DBG, + strlen(CMD_SET_RA_DBG)) == 0) { + i4BytesWritten = priv_driver_set_ra_debug_proc(prNetDev, + pcCommand, i4TotalLen); +#endif +#if (CFG_SUPPORT_TXPOWER_INFO == 1) + } else if (strnicmp(pcCommand, CMD_GET_TX_POWER_INFO, + strlen(CMD_GET_TX_POWER_INFO)) == 0) { + i4BytesWritten = priv_driver_get_txpower_info(prNetDev, + pcCommand, i4TotalLen); +#endif + } else if (strnicmp(pcCommand, CMD_SET_FIXED_RATE, + strlen(CMD_SET_FIXED_RATE)) == 0) { + i4BytesWritten = priv_driver_set_fixed_rate(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_IPI, + strlen(CMD_GET_IPI)) == 0) { + i4BytesWritten = priv_driver_get_ipi(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_SW_CTRL, + strlen(CMD_GET_SW_CTRL)) == 0) { + i4BytesWritten = priv_driver_get_sw_ctrl(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_MCR, + strlen(CMD_SET_MCR)) == 0) { + i4BytesWritten = priv_driver_set_mcr(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_MCR, + strlen(CMD_GET_MCR)) == 0) { + i4BytesWritten = priv_driver_get_mcr(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_DRV_MCR, + strlen(CMD_SET_DRV_MCR)) == 0) { + i4BytesWritten = priv_driver_set_drv_mcr(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_DRV_MCR, + strlen(CMD_GET_DRV_MCR)) == 0) { + i4BytesWritten = priv_driver_get_drv_mcr(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_TEST_MODE, + strlen(CMD_SET_TEST_MODE)) == 0) { + i4BytesWritten = priv_driver_set_test_mode(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_TEST_CMD, + strlen(CMD_SET_TEST_CMD)) == 0) { + i4BytesWritten = priv_driver_set_test_cmd(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_TEST_RESULT, + strlen(CMD_GET_TEST_RESULT)) == 0) { + i4BytesWritten = priv_driver_get_test_result(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_STA_STAT2, + strlen(CMD_GET_STA_STAT2)) == 0) { + i4BytesWritten = priv_driver_get_sta_stat2(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_STA_STAT, + strlen(CMD_GET_STA_STAT)) == 0) { + i4BytesWritten = priv_driver_get_sta_stat(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_STA_RX_STAT, + strlen(CMD_GET_STA_RX_STAT)) == 0) { + i4BytesWritten = priv_driver_show_rx_stat(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_ACL_POLICY, + strlen(CMD_SET_ACL_POLICY)) == 0) { + i4BytesWritten = priv_driver_set_acl_policy(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_ADD_ACL_ENTRY, + strlen(CMD_ADD_ACL_ENTRY)) == 0) { + i4BytesWritten = priv_driver_add_acl_entry(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_DEL_ACL_ENTRY, + strlen(CMD_DEL_ACL_ENTRY)) == 0) { + i4BytesWritten = priv_driver_del_acl_entry(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SHOW_ACL_ENTRY, + strlen(CMD_SHOW_ACL_ENTRY)) == 0) { + i4BytesWritten = priv_driver_show_acl_entry(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_CLEAR_ACL_ENTRY, + strlen(CMD_CLEAR_ACL_ENTRY)) == 0) { + i4BytesWritten = priv_driver_clear_acl_entry(prNetDev, + pcCommand, i4TotalLen); + } +#if (CFG_SUPPORT_DFS_MASTER == 1) + else if (strnicmp(pcCommand, CMD_SHOW_DFS_STATE, + strlen(CMD_SHOW_DFS_STATE)) == 0) { + i4BytesWritten = priv_driver_show_dfs_state(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SHOW_DFS_RADAR_PARAM, + strlen(CMD_SHOW_DFS_RADAR_PARAM)) == 0) { + i4BytesWritten = priv_driver_show_dfs_radar_param( + prNetDev, pcCommand, + i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SHOW_DFS_HELP, + strlen(CMD_SHOW_DFS_HELP)) == 0) { + i4BytesWritten = priv_driver_show_dfs_help(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SHOW_DFS_CAC_TIME, + strlen(CMD_SHOW_DFS_CAC_TIME)) == 0) { + i4BytesWritten = priv_driver_show_dfs_cac_time(prNetDev, + pcCommand, i4TotalLen); + } +#endif +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST + else if (strnicmp(pcCommand, + CMD_SET_CALBACKUP_TEST_DRV_FW, + strlen(CMD_SET_CALBACKUP_TEST_DRV_FW)) == 0) + i4BytesWritten = priv_driver_set_calbackup_test_drv_fw( + prNetDev, pcCommand, + i4TotalLen); +#endif +#if CFG_WOW_SUPPORT + else if (strnicmp(pcCommand, CMD_WOW_START, + strlen(CMD_WOW_START)) == 0) + i4BytesWritten = priv_driver_set_wow(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_WOW_ENABLE, + strlen(CMD_SET_WOW_ENABLE)) == 0) + i4BytesWritten = priv_driver_set_wow_enable(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_WOW_PAR, + strlen(CMD_SET_WOW_PAR)) == 0) + i4BytesWritten = priv_driver_set_wow_par(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_WOW_UDP, + strlen(CMD_SET_WOW_UDP)) == 0) + i4BytesWritten = priv_driver_set_wow_udpport(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_WOW_TCP, + strlen(CMD_SET_WOW_TCP)) == 0) + i4BytesWritten = priv_driver_set_wow_tcpport(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_WOW_PORT, + strlen(CMD_GET_WOW_PORT)) == 0) + i4BytesWritten = priv_driver_get_wow_port(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_WOW_REASON, + strlen(CMD_GET_WOW_PORT)) == 0) + i4BytesWritten = priv_driver_get_wow_reason(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_SUSP_CMD, + strlen(CMD_SET_SUSP_CMD)) == 0) + i4BytesWritten = priv_driver_set_suspend_cmd(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_MDNS_OFFLOAD_ENABLE, + strlen(CMD_SET_MDNS_OFFLOAD_ENABLE)) == 0) + i4BytesWritten = priv_driver_set_mdns_offload_enable( + prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_SHOW_CACHE, + strlen(CMD_SET_SHOW_CACHE)) == 0) + kalShowMdnsCache(); + +#endif + else if (strnicmp(pcCommand, CMD_SET_ADV_PWS, + strlen(CMD_SET_ADV_PWS)) == 0) + i4BytesWritten = priv_driver_set_adv_pws( + prNetDev, pcCommand, + i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_MDTIM, + strlen(CMD_SET_MDTIM)) == 0) + i4BytesWritten = priv_driver_set_mdtim( + prNetDev, pcCommand, + i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_DSLP_CNT, + strlen(CMD_GET_DSLP_CNT)) == 0) + i4BytesWritten = priv_driver_get_deep_sleep_cnt( + prNetDev, pcCommand, + i4TotalLen); + else if (strnicmp(pcCommand, + CMD_ENFORCE_POWER_MODE, + strlen(CMD_ENFORCE_POWER_MODE)) == 0) + i4BytesWritten = + priv_driver_enforce_power_mode( + prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_POWER_MODE, + strlen(CMD_GET_POWER_MODE)) == 0) + i4BytesWritten = + priv_driver_get_power_mode( + prNetDev, pcCommand, i4TotalLen); +#ifdef CFG_SUPPORT_ADJUST_MCC_STAY_TIME + else if (strnicmp(pcCommand, CMD_MCCTIME, + strlen(CMD_MCCTIME)) == 0) + i4BytesWritten = priv_driver_set_mcc_time(prNetDev, + pcCommand, i4TotalLen); +#endif + +#if CFG_SUPPORT_ADJUST_MCC_MODE_SET + else if (strnicmp(pcCommand, CMD_SET_MCC_MODE, + strlen(CMD_SET_MCC_MODE)) == 0) + i4BytesWritten = priv_driver_set_mcc_mode(prNetDev, + pcCommand, i4TotalLen); +#endif + +#if CFG_SUPPORT_ANT_DIV + else if (strnicmp(pcCommand, CMD_GET_ANT_DIV, + strlen(CMD_GET_ANT_DIV)) == 0) + i4BytesWritten = priv_driver_ant_diversity_config( + prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_DETC_ANT_DIV, + strlen(CMD_DETC_ANT_DIV)) == 0) + i4BytesWritten = priv_driver_ant_diversity_config( + prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SWH_ANT_DIV, + strlen(CMD_SWH_ANT_DIV)) == 0) + i4BytesWritten = priv_driver_ant_diversity_config( + prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_ANT_DIV, + strlen(CMD_SET_ANT_DIV)) == 0) + i4BytesWritten = priv_driver_ant_diversity_config( + prNetDev, pcCommand, i4TotalLen); +#endif + +#if CFG_CHIP_RESET_HANG + else if (strnicmp(pcCommand, CMD_SET_RST_HANG, + strlen(CMD_SET_RST_HANG)) == 0) + i4BytesWritten = priv_driver_set_rst_hang( + prNetDev, pcCommand, i4TotalLen); +#endif + +#if CFG_SUPPORT_QA_TOOL + else if (strnicmp(pcCommand, CMD_GET_RX_STATISTICS, + strlen(CMD_GET_RX_STATISTICS)) == 0) + i4BytesWritten = priv_driver_get_rx_statistics( + prNetDev, pcCommand, + i4TotalLen); +#if CFG_SUPPORT_BUFFER_MODE + else if (strnicmp(pcCommand, CMD_SETBUFMODE, + strlen(CMD_SETBUFMODE)) == 0) + i4BytesWritten = priv_driver_set_efuse_buffer_mode( + prNetDev, pcCommand, + i4TotalLen); +#endif +#endif +#if CFG_SUPPORT_MSP +#if 0 + else if (strnicmp(pcCommand, CMD_GET_STAT, + strlen(CMD_GET_STAT)) == 0) + i4BytesWritten = priv_driver_get_stat(prNetDev, + pcCommand, i4TotalLen); +#endif + else if (strnicmp(pcCommand, CMD_GET_STA_STATISTICS, + strlen(CMD_GET_STA_STATISTICS)) == 0) + i4BytesWritten = priv_driver_get_sta_statistics( + prNetDev, pcCommand, + i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_BSS_STATISTICS, + strlen(CMD_GET_BSS_STATISTICS)) == 0) + i4BytesWritten = priv_driver_get_bss_statistics( + prNetDev, pcCommand, + i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_STA_IDX, + strlen(CMD_GET_STA_IDX)) == 0) + i4BytesWritten = priv_driver_get_sta_index(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_STA_INFO, + strlen(CMD_GET_STA_INFO)) == 0) + i4BytesWritten = priv_driver_get_sta_info(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_WTBL_INFO, + strlen(CMD_GET_WTBL_INFO)) == 0) + i4BytesWritten = priv_driver_get_wtbl_info(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_MIB_INFO, + strlen(CMD_GET_MIB_INFO)) == 0) + i4BytesWritten = priv_driver_get_mib_info(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_FW_LOG, + strlen(CMD_SET_FW_LOG)) == 0) + i4BytesWritten = priv_driver_set_fw_log(prNetDev, + pcCommand, i4TotalLen); +#endif + else if (strnicmp(pcCommand, CMD_SET_CFG, + strlen(CMD_SET_CFG)) == 0) { + i4BytesWritten = priv_driver_set_cfg(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_CFG, + strlen(CMD_GET_CFG)) == 0) { + i4BytesWritten = priv_driver_get_cfg(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_COEX_CONTROL, + strlen(CMD_COEX_CONTROL)) == 0) { + i4BytesWritten = priv_driver_coex_ctrl(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_CHIP, + strlen(CMD_SET_CHIP)) == 0) { + i4BytesWritten = priv_driver_set_chip_config(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_CHIP, + strlen(CMD_GET_CHIP)) == 0) { + i4BytesWritten = priv_driver_get_chip_config(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_VERSION, + strlen(CMD_GET_VERSION)) == 0) { + i4BytesWritten = priv_driver_get_version(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_CNM, + strlen(CMD_GET_CNM)) == 0) { + i4BytesWritten = priv_driver_get_cnm(prNetDev, + pcCommand, i4TotalLen); +#if CFG_SUPPORT_DBDC + + } else if (strnicmp(pcCommand, CMD_SET_DBDC, + strlen(CMD_SET_DBDC)) == 0) { + i4BytesWritten = priv_driver_set_dbdc(prNetDev, + pcCommand, i4TotalLen); +#endif /*CFG_SUPPORT_DBDC*/ +#if CFG_SUPPORT_BATCH_SCAN + } else if (strnicmp(pcCommand, CMD_BATCH_SET, + strlen(CMD_BATCH_SET)) == 0) { + kalIoctl(prGlueInfo, wlanoidSetBatchScanReq, + (void *) pcCommand, i4TotalLen, + FALSE, FALSE, TRUE, &i4BytesWritten); + } else if (strnicmp(pcCommand, CMD_BATCH_GET, + strlen(CMD_BATCH_GET)) == 0) { + /* strcpy(pcCommand, "BATCH SCAN DATA FROM FIRMWARE"); + */ + /* i4BytesWritten = + * strlen("BATCH SCAN DATA FROM FIRMWARE") + * + 1; + */ + /* i4BytesWritten = priv_driver_get_linkspeed (prNetDev, + * pcCommand, i4TotalLen); + */ + + uint32_t u4BufLen; + int i; + /* int rlen=0; */ + + for (i = 0; i < CFG_BATCH_MAX_MSCAN; i++) { + /* for get which mscan */ + g_rEventBatchResult[i].ucScanCount = i + 1; + + kalIoctl(prGlueInfo, + wlanoidQueryBatchScanResult, + (void *)&g_rEventBatchResult[i], + sizeof(struct EVENT_BATCH_RESULT), + TRUE, TRUE, TRUE, &u4BufLen); + } + +#if 0 + DBGLOG(SCN, INFO, + "Batch Scan Results, scan count = %u\n", + g_rEventBatchResult.ucScanCount); + for (i = 0; i < g_rEventBatchResult.ucScanCount; i++) { + prEntry = &g_rEventBatchResult.arBatchResult[i]; + DBGLOG(SCN, INFO, "Entry %u\n", i); + DBGLOG(SCN, INFO, " BSSID = " MACSTR "\n", + MAC2STR(prEntry->aucBssid)); + DBGLOG(SCN, INFO, " SSID = %s\n", + prEntry->aucSSID); + DBGLOG(SCN, INFO, " SSID len = %u\n", + prEntry->ucSSIDLen); + DBGLOG(SCN, INFO, " RSSI = %d\n", + prEntry->cRssi); + DBGLOG(SCN, INFO, " Freq = %u\n", + prEntry->ucFreq); + } +#endif + + batchConvertResult(&g_rEventBatchResult[0], pcCommand, + i4TotalLen, &i4BytesWritten); + + /* Dump for debug */ + /* print_hex_dump(KERN_INFO, + * "BATCH", DUMP_PREFIX_ADDRESS, 16, 1, pcCommand, + * i4BytesWritten, TRUE); + */ + + } else if (strnicmp(pcCommand, CMD_BATCH_STOP, + strlen(CMD_BATCH_STOP)) == 0) { + kalIoctl(prGlueInfo, wlanoidSetBatchScanReq, + (void *) pcCommand, i4TotalLen, + FALSE, FALSE, TRUE, &i4BytesWritten); +#endif + } +#if CFG_SUPPORT_SNIFFER + else if (strnicmp(pcCommand, CMD_SETMONITOR, + strlen(CMD_SETMONITOR)) == 0) + i4BytesWritten = priv_driver_set_monitor(prNetDev, + pcCommand, i4TotalLen); +#endif + else if (strnicmp(pcCommand, CMD_GET_QUE_INFO, + strlen(CMD_GET_QUE_INFO)) == 0) + i4BytesWritten = priv_driver_get_que_info(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_MEM_INFO, + strlen(CMD_GET_MEM_INFO)) == 0) + i4BytesWritten = priv_driver_get_mem_info(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_HIF_INFO, + strlen(CMD_GET_HIF_INFO)) == 0) + i4BytesWritten = priv_driver_get_hif_info(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_TP_INFO, + strlen(CMD_GET_TP_INFO)) == 0) + i4BytesWritten = priv_driver_get_tp_info(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_CNM, + strlen(CMD_GET_CNM)) == 0) + i4BytesWritten = priv_driver_get_cnm(prNetDev, + pcCommand, i4TotalLen); +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + else if (strnicmp(pcCommand, CMD_GET_CH_RANK_LIST, + strlen(CMD_GET_CH_RANK_LIST)) == 0) + i4BytesWritten = priv_driver_get_ch_rank_list(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_CH_DIRTINESS, + strlen(CMD_GET_CH_DIRTINESS)) == 0) + i4BytesWritten = priv_driver_get_ch_dirtiness(prNetDev, + pcCommand, i4TotalLen); +#endif + else if (strnicmp(pcCommand, CMD_EFUSE, + sizeof(CMD_EFUSE)-1) == 0) + i4BytesWritten = priv_driver_efuse_ops(prNetDev, + pcCommand, i4TotalLen); +#if defined(_HIF_SDIO) && (MTK_WCN_HIF_SDIO == 0) + else if (strnicmp(pcCommand, CMD_CCCR, + strlen(CMD_CCCR)) == 0) + i4BytesWritten = priv_driver_cccr_ops(prNetDev, + pcCommand, i4TotalLen); +#endif /* _HIF_SDIO && (MTK_WCN_HIF_SDIO == 0) */ +#if CFG_SUPPORT_ADVANCE_CONTROL + else if (strnicmp(pcCommand, CMD_SET_NOISE, + strlen(CMD_SET_NOISE)) == 0) + i4BytesWritten = priv_driver_set_noise(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_NOISE, + strlen(CMD_GET_NOISE)) == 0) + i4BytesWritten = priv_driver_get_noise(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_TRAFFIC_REPORT, + strlen(CMD_TRAFFIC_REPORT)) == 0) + i4BytesWritten = priv_driver_get_traffic_report( + prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_POP, + strlen(CMD_SET_POP)) == 0) + i4BytesWritten = priv_driver_set_pop(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_POP, + strlen(CMD_GET_POP)) == 0) + i4BytesWritten = priv_driver_get_pop(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_ED, + strlen(CMD_SET_ED)) == 0) + i4BytesWritten = priv_driver_set_ed(prNetDev, pcCommand, + i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_ED, + strlen(CMD_GET_ED)) == 0) + i4BytesWritten = priv_driver_get_ed(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_PD, + strlen(CMD_SET_PD)) == 0) + i4BytesWritten = priv_driver_set_pd(prNetDev, pcCommand, + i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_PD, + strlen(CMD_GET_PD)) == 0) + i4BytesWritten = priv_driver_get_pd(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_MAX_RFGAIN, + strlen(CMD_SET_MAX_RFGAIN)) == 0) + i4BytesWritten = priv_driver_set_maxrfgain(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_MAX_RFGAIN, + strlen(CMD_GET_MAX_RFGAIN)) == 0) + i4BytesWritten = priv_driver_get_maxrfgain(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_NOISE_HISTOGRAM, + strlen(CMD_NOISE_HISTOGRAM)) == 0) + i4BytesWritten = priv_driver_noise_histogram(prNetDev, + pcCommand, i4TotalLen); +#if CFG_RX_SINGLE_CHAIN_SUPPORT + else if (strnicmp(pcCommand, CMD_SET_RXC, + strlen(CMD_SET_RXC)) == 0) + i4BytesWritten = priv_driver_set_rxchain(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_RXC, + strlen(CMD_GET_RXC)) == 0) + i4BytesWritten = priv_driver_get_rxchain(prNetDev, + pcCommand, i4TotalLen); +#endif + else if (strnicmp(pcCommand, CMD_SET_ADM_CTRL, + strlen(CMD_SET_ADM_CTRL)) == 0) + i4BytesWritten = priv_driver_set_adm_ctrl(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_ADM_CTRL, + strlen(CMD_GET_ADM_CTRL)) == 0) + i4BytesWritten = priv_driver_get_adm_ctrl(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_BCN_TH, + strlen(CMD_SET_BCN_TH)) == 0) + i4BytesWritten = priv_driver_set_bcn_th(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_BCN_TH, + strlen(CMD_GET_BCN_TH)) == 0) + i4BytesWritten = priv_driver_get_bcn_th(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_BCNTIMEOUT_NUM, + strlen(CMD_GET_BCNTIMEOUT_NUM)) == 0) + i4BytesWritten = priv_driver_get_bcntimeout_cnt( + prNetDev, pcCommand, i4TotalLen); +#if CFG_ENABLE_1RPD_MMPS_CTRL + else if (strnicmp(pcCommand, CMD_SET_1RPD, + strlen(CMD_SET_1RPD)) == 0) + i4BytesWritten = priv_driver_set_1rpd(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_1RPD, + strlen(CMD_GET_1RPD)) == 0) + i4BytesWritten = priv_driver_get_1rpd(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_MMPS, + strlen(CMD_SET_MMPS)) == 0) + i4BytesWritten = priv_driver_set_mmps(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_MMPS, + strlen(CMD_GET_MMPS)) == 0) + i4BytesWritten = priv_driver_get_mmps(prNetDev, + pcCommand, i4TotalLen); +#endif /* CFG_ENABLE_1RPD_MMPS_CTRL */ +#if CFG_ENABLE_DEWEIGHTING_CTRL + else if (strnicmp(pcCommand, CMD_SET_DEWEIGHTING_TH, + strlen(CMD_SET_DEWEIGHTING_TH)) == 0) + i4BytesWritten = priv_driver_set_deweighting_th( + prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_DEWEIGHTING_TH, + strlen(CMD_GET_DEWEIGHTING_TH)) == 0) + i4BytesWritten = priv_driver_get_deweighting_th( + prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_DEWEIGHTING_NOISE, + strlen(CMD_GET_DEWEIGHTING_NOISE)) == 0) + i4BytesWritten = priv_driver_get_deweighting_noise( + prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_DEWEIGHTING_WEIGHT, + strlen(CMD_GET_DEWEIGHTING_WEIGHT)) + == 0) + i4BytesWritten = priv_driver_get_deweighting_weight( + prNetDev, pcCommand, i4TotalLen); +#endif /* CFG_ENABLE_DEWEIGHTING_CTRL */ + + +#endif /* CFG_SUPPORT_ADVANCE_CONTROL */ +#if CFG_SUPPORT_GET_MCS_INFO + else if (strnicmp(pcCommand, CMD_GET_MCS_INFO, + strlen(CMD_GET_MCS_INFO)) == 0) + i4BytesWritten = priv_driver_get_mcs_info(prNetDev, + pcCommand, i4TotalLen); +#endif +#if CFG_ENABLE_WIFI_DIRECT + else if (strnicmp(pcCommand, CMD_P2P_SET_PS, + strlen(CMD_P2P_SET_PS)) == 0) + i4BytesWritten = priv_driver_set_p2p_ps(prNetDev, + pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_P2P_SET_NOA, + strlen(CMD_P2P_SET_NOA)) == 0) + i4BytesWritten = priv_driver_set_p2p_noa(prNetDev, + pcCommand, i4TotalLen); +#endif /* CFG_ENABLE_WIFI_DIRECT */ + else if (strnicmp(pcCommand, CMD_SET_DRV_SER, + strlen(CMD_SET_DRV_SER)) == 0) + i4BytesWritten = priv_driver_set_drv_ser( + prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_SW_AMSDU_NUM, + strlen(CMD_SET_SW_AMSDU_NUM)) == 0) + i4BytesWritten = priv_driver_set_amsdu_num( + prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_SW_AMSDU_SIZE, + strlen(CMD_SET_SW_AMSDU_SIZE)) == 0) + i4BytesWritten = priv_driver_set_amsdu_size( + prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_DBG_SHOW_TR_INFO, + strlen(CMD_DBG_SHOW_TR_INFO)) == 0) { + kalIoctl(prGlueInfo, + wlanoidShowPdmaInfo, + (void *) pcCommand, i4TotalLen, + FALSE, FALSE, TRUE, &i4BytesWritten); + } else if (strnicmp(pcCommand, CMD_DBG_SHOW_PLE_INFO, + strlen(CMD_DBG_SHOW_PLE_INFO)) == 0) { + kalIoctl(prGlueInfo, + wlanoidShowPleInfo, + (void *) pcCommand, i4TotalLen, + FALSE, FALSE, TRUE, &i4BytesWritten); + } else if (strnicmp(pcCommand, CMD_DBG_SHOW_PSE_INFO, + strlen(CMD_DBG_SHOW_PSE_INFO)) == 0) { + kalIoctl(prGlueInfo, + wlanoidShowPseInfo, + (void *) pcCommand, i4TotalLen, + FALSE, FALSE, TRUE, &i4BytesWritten); + } else if (strnicmp(pcCommand, CMD_DBG_SHOW_CSR_INFO, + strlen(CMD_DBG_SHOW_CSR_INFO)) == 0) { + kalIoctl(prGlueInfo, + wlanoidShowCsrInfo, + (void *) pcCommand, i4TotalLen, + FALSE, FALSE, TRUE, &i4BytesWritten); + } else if (strnicmp(pcCommand, CMD_DBG_SHOW_DMASCH_INFO, + strlen(CMD_DBG_SHOW_DMASCH_INFO)) == 0) { + kalIoctl(prGlueInfo, + wlanoidShowDmaschInfo, + (void *) pcCommand, i4TotalLen, + FALSE, FALSE, TRUE, &i4BytesWritten); + } else if (!strnicmp(pcCommand, CMD_DUMP_TS, + strlen(CMD_DUMP_TS)) || + !strnicmp(pcCommand, CMD_ADD_TS, + strlen(CMD_ADD_TS)) || + !strnicmp(pcCommand, CMD_DEL_TS, + strlen(CMD_DEL_TS))) { + kalIoctl(prGlueInfo, wlanoidTspecOperation, + (void *)pcCommand, i4TotalLen, FALSE, FALSE, + FALSE, &i4BytesWritten); + } else if (kalStrStr(pcCommand, "-IT ")) { + kalIoctl(prGlueInfo, wlanoidPktProcessIT, + (void *)pcCommand, i4TotalLen, FALSE, FALSE, + FALSE, &i4BytesWritten); + } else if (!strnicmp(pcCommand, CMD_FW_EVENT, 9)) { + kalIoctl(prGlueInfo, wlanoidFwEventIT, + (void *)(pcCommand + 9), i4TotalLen, FALSE, + FALSE, FALSE, &i4BytesWritten); + } else if (!strnicmp(pcCommand, CMD_DUMP_UAPSD, + strlen(CMD_DUMP_UAPSD))) { + kalIoctl(prGlueInfo, wlanoidDumpUapsdSetting, + (void *)pcCommand, i4TotalLen, FALSE, FALSE, + FALSE, &i4BytesWritten); +#if CFG_SUPPORT_802_11K + } else if (!strnicmp(pcCommand, CMD_NEIGHBOR_REQ, + strlen(CMD_NEIGHBOR_REQ))) { + i4BytesWritten = priv_driver_neighbor_request( + prNetDev, pcCommand, i4TotalLen); +#endif +#if CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT + } else if (!strnicmp(pcCommand, CMD_BTM_QUERY, + strlen(CMD_BTM_QUERY))) { + i4BytesWritten = priv_driver_bss_transition_query( + prNetDev, pcCommand, i4TotalLen); +#endif + } else if (strnicmp(pcCommand, CMD_GET_BSS_TABLE, + strlen(CMD_GET_BSS_TABLE)) == 0) { + i4BytesWritten = priv_driver_get_bsstable(prNetDev, + pcCommand, i4TotalLen); +#ifdef CFG_SUPPORT_TIME_MEASURE + } else if (strnicmp(pcCommand, CMD_START_FTM_NON_BLOCK, + strlen(CMD_START_FTM_NON_BLOCK)) == 0) { + i4BytesWritten = priv_driver_start_ftm(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_START_FTM, + strlen(CMD_START_FTM)) == 0) { + i4BytesWritten = priv_driver_start_ftm(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_TMR_DISTANCE, + strlen(CMD_GET_TMR_DISTANCE)) == 0) { + i4BytesWritten = priv_driver_get_ftm(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_TMR_AUDIOSYNC, + strlen(CMD_GET_TMR_AUDIOSYNC)) == 0) { + i4BytesWritten = priv_driver_get_ftm(prNetDev, + pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_ENABLE_TMR, + strlen(CMD_ENABLE_TMR)) == 0) { + i4BytesWritten = priv_driver_enable_tmr(prNetDev, + pcCommand, i4TotalLen); +#endif +#if CFG_SUPPORT_WAC + } else if (strnicmp(pcCommand, CMD_SET_WAC_IE_ENABLE, + strlen(CMD_SET_WAC_IE_ENABLE)) == 0) { + i4BytesWritten = priv_driver_set_wac_ie_enable(prNetDev, + pcCommand, i4TotalLen); +#endif + } else + i4BytesWritten = priv_cmd_not_support + (prNetDev, pcCommand, i4TotalLen); + + if (i4BytesWritten >= 0) { + if ((i4BytesWritten == 0) && (i4TotalLen > 0)) { + /* reset the command buffer */ + pcCommand[0] = '\0'; + } + + if (i4BytesWritten >= i4TotalLen) { + DBGLOG(REQ, INFO, + "%s: i4BytesWritten %d > i4TotalLen < %d\n", + __func__, i4BytesWritten, i4TotalLen); + i4BytesWritten = i4TotalLen; + } else { + pcCommand[i4BytesWritten] = '\0'; + i4BytesWritten++; + } + } + + return i4BytesWritten; + +} /* priv_driver_cmds */ + +#ifdef CFG_ANDROID_AOSP_PRIV_CMD +int android_private_support_driver_cmd(IN struct net_device *prNetDev, + IN OUT struct ifreq *prReq, IN int i4Cmd) +{ + struct android_wifi_priv_cmd priv_cmd; + char *command = NULL; + int ret = 0, bytes_written = 0; + + if (!prReq->ifr_data) + return -EINVAL; + + if (copy_from_user(&priv_cmd, prReq->ifr_data, sizeof(priv_cmd))) + return -EFAULT; + /* total_len is controlled by the user. need check length */ + if (priv_cmd.total_len <= 0) + return -EINVAL; + + command = kzalloc(priv_cmd.total_len, GFP_KERNEL); + if (!command) { + DBGLOG(REQ, WARN, "%s, alloc mem failed\n", __func__); + return -ENOMEM; + } + + if (copy_from_user(command, priv_cmd.buf, priv_cmd.total_len)) { + ret = -EFAULT; + goto FREE; + } + + bytes_written = priv_driver_cmds(prNetDev, command, priv_cmd.total_len); + + if (bytes_written == -EOPNOTSUPP) { + /* Report positive status */ + bytes_written = kalSnprintf(command, priv_cmd.total_len, + "%s", "NotSupport"); + } + + if (bytes_written >= 0) { + /* priv_cmd in but no response */ + if ((bytes_written == 0) && (priv_cmd.total_len > 0)) + command[0] = '\0'; + + if (bytes_written >= priv_cmd.total_len) + bytes_written = priv_cmd.total_len; + else + bytes_written++; + + priv_cmd.used_len = bytes_written; + + if (copy_to_user(priv_cmd.buf, command, bytes_written)) + ret = -EFAULT; + } else + ret = bytes_written; + +FREE: + kfree(command); + + return ret; +} +#endif /* CFG_ANDROID_AOSP_PRIV_CMD */ + +int priv_support_driver_cmd(IN struct net_device *prNetDev, + IN OUT struct ifreq *prReq, IN int i4Cmd) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int ret = 0; + char *pcCommand = NULL; + struct priv_driver_cmd_s *priv_cmd = NULL; + int i4BytesWritten = 0; + int i4TotalLen = 0; + + if (!prReq->ifr_data) { + ret = -EINVAL; + goto exit; + } + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + if (!prGlueInfo) { + DBGLOG(REQ, WARN, "No glue info\n"); + ret = -EFAULT; + goto exit; + } + if (prGlueInfo->u4ReadyFlag == 0) { + ret = -EINVAL; + goto exit; + } + + priv_cmd = kzalloc(sizeof(struct priv_driver_cmd_s), GFP_KERNEL); + if (!priv_cmd) { + DBGLOG(REQ, WARN, "%s, alloc mem failed\n", __func__); + return -ENOMEM; + } + + if (copy_from_user(priv_cmd, prReq->ifr_data, + sizeof(struct priv_driver_cmd_s))) { + DBGLOG(REQ, INFO, "%s: copy_from_user fail\n", __func__); + ret = -EFAULT; + goto exit; + } + + i4TotalLen = priv_cmd->total_len; + + if (i4TotalLen <= 0 || i4TotalLen > PRIV_CMD_SIZE) { + ret = -EINVAL; + DBGLOG(REQ, INFO, "%s: i4TotalLen invalid\n", __func__); + goto exit; + } + priv_cmd->buf[PRIV_CMD_SIZE - 1] = '\0'; + pcCommand = priv_cmd->buf; + + DBGLOG(REQ, INFO, "%s: driver cmd \"%s\" on %s\n", __func__, pcCommand, + prReq->ifr_name); + + i4BytesWritten = priv_driver_cmds(prNetDev, pcCommand, i4TotalLen); + + if (i4BytesWritten < 0) { + DBGLOG(REQ, INFO, "%s: command %s Written is %d\n", __func__, + pcCommand, i4BytesWritten); + if (i4TotalLen >= 3) { + snprintf(pcCommand, 3, "OK"); + i4BytesWritten = strlen("OK"); + } + } + +exit: + kfree(priv_cmd); + + return ret; +} /* priv_support_driver_cmd */ + +#if CFG_SUPPORT_NCHO +/* NCHO related command definition. Setting by supplicant */ +#define CMD_NCHO_ROAM_TRIGGER_GET "GETROAMTRIGGER" +#define CMD_NCHO_ROAM_TRIGGER_SET "SETROAMTRIGGER" +#define CMD_NCHO_ROAM_DELTA_GET "GETROAMDELTA" +#define CMD_NCHO_ROAM_DELTA_SET "SETROAMDELTA" +#define CMD_NCHO_ROAM_SCAN_PERIOD_GET "GETROAMSCANPERIOD" +#define CMD_NCHO_ROAM_SCAN_PERIOD_SET "SETROAMSCANPERIOD" +#define CMD_NCHO_ROAM_SCAN_CHANNELS_GET "GETROAMSCANCHANNELS" +#define CMD_NCHO_ROAM_SCAN_CHANNELS_SET "SETROAMSCANCHANNELS" +#define CMD_NCHO_ROAM_SCAN_CONTROL_GET "GETROAMSCANCONTROL" +#define CMD_NCHO_ROAM_SCAN_CONTROL_SET "SETROAMSCANCONTROL" +#define CMD_NCHO_SCAN_CHANNEL_TIME_GET "GETSCANCHANNELTIME" +#define CMD_NCHO_SCAN_CHANNEL_TIME_SET "SETSCANCHANNELTIME" +#define CMD_NCHO_SCAN_HOME_TIME_GET "GETSCANHOMETIME" +#define CMD_NCHO_SCAN_HOME_TIME_SET "SETSCANHOMETIME" +#define CMD_NCHO_SCAN_HOME_AWAY_TIME_GET "GETSCANHOMEAWAYTIME" +#define CMD_NCHO_SCAN_HOME_AWAY_TIME_SET "SETSCANHOMEAWAYTIME" +#define CMD_NCHO_SCAN_NPROBES_GET "GETSCANNPROBES" +#define CMD_NCHO_SCAN_NPROBES_SET "SETSCANNPROBES" +#define CMD_NCHO_REASSOC_SEND "REASSOC" +#define CMD_NCHO_ACTION_FRAME_SEND "SENDACTIONFRAME" +#define CMD_NCHO_WES_MODE_GET "GETWESMODE" +#define CMD_NCHO_WES_MODE_SET "SETWESMODE" +#define CMD_NCHO_BAND_GET "GETBAND" +#define CMD_NCHO_BAND_SET "SETBAND" +#define CMD_NCHO_DFS_SCAN_MODE_GET "GETDFSSCANMODE" +#define CMD_NCHO_DFS_SCAN_MODE_SET "SETDFSSCANMODE" +#define CMD_NCHO_DFS_SCAN_MODE_GET "GETDFSSCANMODE" +#define CMD_NCHO_DFS_SCAN_MODE_SET "SETDFSSCANMODE" +#define CMD_NCHO_ENABLE "NCHOENABLE" +#define CMD_NCHO_DISABLE "NCHODISABLE" +static int +priv_driver_enable_ncho(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen); +static int +priv_driver_disable_ncho(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen); + +int +priv_driver_set_ncho_roam_trigger(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Param = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i4Ret = -1; + uint32_t u4SetInfoLen = 0; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, apcArgv[1]); + i4Ret = kalkStrtos32(apcArgv[1], 0, &i4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", + i4Ret); + return -1; + } + + DBGLOG(INIT, TRACE, "NCHO set roam trigger cmd %d\n", i4Param); + rStatus = kalIoctl(prGlueInfo, wlanoidSetNchoRoamTrigger, + &i4Param, sizeof(int32_t), + FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO set roam trigger fail 0x%x\n", + rStatus); + i4Ret = -1; + } else { + DBGLOG(INIT, TRACE, + "NCHO set roam trigger successed\n"); + i4Ret = 0; + } + + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4Ret; +} + +int +priv_driver_get_ncho_roam_trigger(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = -1; + int32_t i4Param = 0; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER cmdV1Header; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4BytesWritten; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return i4BytesWritten; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryNchoRoamTrigger, + &cmdV1Header, sizeof(cmdV1Header), + TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "NCHO wlanoidQueryNchoRoamTrigger fail 0x%x\n", rStatus); + return i4BytesWritten; + } + + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %s\n", cmdV1Header.buffer); + i4BytesWritten = kalkStrtou32(cmdV1Header.buffer, 0, &i4Param); + if (i4BytesWritten) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d!\n", + i4BytesWritten); + i4BytesWritten = -1; + } else { + i4Param = RCPI_TO_dBm(i4Param); /* RCPI to DB */ + DBGLOG(INIT, TRACE, "NCHO query RoamTrigger is %d\n", i4Param); + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%d", i4Param); + } + + return i4BytesWritten; +} + +int priv_driver_set_ncho_roam_delta(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Param = 0; + uint32_t u4SetInfoLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i4Ret = -1; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, apcArgv[1]); + i4Ret = kalkStrtos32(apcArgv[1], 0, &i4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, + "NCHO parse u4Param error %d\n", i4Ret); + return -1; + } + + DBGLOG(INIT, TRACE, "NCHO set roam delta cmd %d\n", i4Param); + rStatus = kalIoctl(prGlueInfo, wlanoidSetNchoRoamDelta, + &i4Param, sizeof(int32_t), + FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "NCHO set roam delta fail 0x%x\n", rStatus); + i4Ret = -1; + } else { + DBGLOG(INIT, TRACE, "NCHO set roam delta successed\n"); + i4Ret = 0; + } + + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4Ret; +} +int priv_driver_get_ncho_roam_delta(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = -1; + int32_t i4Param = 0; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4BytesWritten; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return i4BytesWritten; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryNchoRoamDelta, + &i4Param, sizeof(int32_t), + TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "NCHO wlanoidQueryNchoRoamDelta fail 0x%x\n", rStatus); + } else { + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %d\n", i4Param); + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%d", i4Param); + } + return i4BytesWritten; +} + +int priv_driver_set_ncho_roam_scn_period(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4Param = 0; + uint32_t u4SetInfoLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i4Ret = -1; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, apcArgv[1]); + i4Ret = kalkStrtou32(apcArgv[1], 0, &u4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", + i4Ret); + return -1; + } + + DBGLOG(INIT, TRACE, "NCHO set roam period cmd %d\n", u4Param); + rStatus = kalIoctl(prGlueInfo, wlanoidSetNchoRoamScnPeriod, + &u4Param, sizeof(uint32_t), + FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO set roam period fail 0x%x\n", + rStatus); + i4Ret = -1; + } else { + DBGLOG(INIT, TRACE, "NCHO set roam period successed\n"); + i4Ret = 0; + } + + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4Ret; +} + +int priv_driver_get_ncho_roam_scn_period(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = -1; + uint32_t u4Param = 0; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4BytesWritten; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return i4BytesWritten; + } + rStatus = kalIoctl(prGlueInfo, wlanoidQueryNchoRoamScnPeriod, + &u4Param, sizeof(uint32_t), + TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "NCHO wlanoidQueryNchoRoamScnPeriod fail 0x%x\n", + rStatus); + } else { + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %d\n", u4Param); + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%u", u4Param); + } + return i4BytesWritten; +} + +int priv_driver_set_ncho_roam_scn_chnl(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4ChnlInfo = 0; + uint8_t i = 1; + uint8_t t = 0; + uint32_t u4SetInfoLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i4Ret = -1; + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct _CFG_NCHO_SCAN_CHNL_T rRoamScnChnl; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, cmd is %s\n", i4Argc, + apcArgv[1]); + i4Ret = kalkStrtou32(apcArgv[1], 0, &u4ChnlInfo); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", + i4Ret); + return -1; + } + + rRoamScnChnl.ucChannelListNum = u4ChnlInfo; + DBGLOG(REQ, ERROR, "NCHO ChannelListNum is %d\n", u4ChnlInfo); + if (i4Argc != u4ChnlInfo + 2) { + DBGLOG(REQ, ERROR, "NCHO param mismatch %d\n", + u4ChnlInfo); + return -1; + } + for (i = 2; i < i4Argc; i++) { + i4Ret = kalkStrtou32(apcArgv[i], 0, &u4ChnlInfo); + if (i4Ret) { + while (i != 2) { + rRoamScnChnl.arChnlInfoList[i] + .ucChannelNum = 0; + i--; + } + DBGLOG(REQ, ERROR, + "NCHO parse chnl num error %d\n", i4Ret); + return -1; + } + if (u4ChnlInfo != 0) { + DBGLOG(INIT, TRACE, + "NCHO t = %d, channel value=%d\n", + t, u4ChnlInfo); + if ((u4ChnlInfo >= 1) && (u4ChnlInfo <= 14)) + rRoamScnChnl.arChnlInfoList[t].eBand = + BAND_2G4; + else + rRoamScnChnl.arChnlInfoList[t].eBand = + BAND_5G; + + rRoamScnChnl.arChnlInfoList[t].ucChannelNum = + u4ChnlInfo; + t++; + } + + } + + DBGLOG(INIT, TRACE, "NCHO set roam scan channel cmd\n"); + rStatus = kalIoctl(prGlueInfo, wlanoidSetNchoRoamScnChnl, + &rRoamScnChnl, + sizeof(struct _CFG_NCHO_SCAN_CHNL_T), + FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "NCHO set roam scan channel fail 0x%x\n", + rStatus); + i4Ret = -1; + } else { + DBGLOG(INIT, TRACE, + "NCHO set roam scan channel successed\n"); + i4Ret = 0; + } + + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4Ret; +} + +int priv_driver_get_ncho_roam_scn_chnl(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t i = 0; + uint32_t u4BufLen = 0; + int32_t i4BytesWritten = -1; + int32_t i4Argc = 0; + uint32_t u4ChnlInfo = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + struct _CFG_NCHO_SCAN_CHNL_T rRoamScnChnl; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4BytesWritten; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return i4BytesWritten; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryNchoRoamScnChnl, + &rRoamScnChnl, sizeof(struct _CFG_NCHO_SCAN_CHNL_T), + TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "NCHO wlanoidQueryNchoRoamScnChnl fail 0x%x\n", rStatus); + } else { + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %d\n", + rRoamScnChnl.ucChannelListNum); + u4ChnlInfo = rRoamScnChnl.ucChannelListNum; + i4BytesWritten = 0; + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%u", + u4ChnlInfo); + for (i = 0; i < rRoamScnChnl.ucChannelListNum; i++) { + u4ChnlInfo = + rRoamScnChnl.arChnlInfoList[i].ucChannelNum; + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + " %u", u4ChnlInfo); + } + } + + DBGLOG(REQ, TRACE, "NCHO i4BytesWritten is %d and channel list is %s\n", + i4BytesWritten, pcCommand); + return i4BytesWritten; +} + +int priv_driver_set_ncho_roam_scn_ctrl(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4Param = 0; + uint32_t u4SetInfoLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i4Ret = -1; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, apcArgv[1]); + i4Ret = kalkStrtou32(apcArgv[1], 0, &u4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", + i4Ret); + return -1; + } + + DBGLOG(INIT, TRACE, "NCHO set roam scan control cmd %d\n", + u4Param); + rStatus = kalIoctl(prGlueInfo, wlanoidSetNchoRoamScnCtrl, + &u4Param, sizeof(uint32_t), + FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "NCHO set roam scan control fail 0x%x\n", + rStatus); + i4Ret = -1; + } else { + DBGLOG(INIT, TRACE, + "NCHO set roam scan control successed\n"); + i4Ret = 0; + } + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4Ret; +} +int priv_driver_get_ncho_roam_scn_ctrl(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = -1; + uint32_t u4Param = 0; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4BytesWritten; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return i4BytesWritten; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryNchoRoamScnCtrl, + &u4Param, sizeof(uint32_t), + TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "NCHO wlanoidQueryNchoRoamScnCtrl fail 0x%x\n", rStatus); + } else { + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %d\n", u4Param); + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%u", u4Param); + } + return i4BytesWritten; +} + +int priv_driver_set_ncho_scn_chnl_time(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4Param = 0; + uint32_t u4SetInfoLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i4Ret = -1; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, apcArgv[1]); + i4Ret = kalkStrtou32(apcArgv[1], 0, &u4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", + i4Ret); + return -1; + } + + DBGLOG(INIT, TRACE, "NCHO set scan channel time cmd %d\n", + u4Param); + rStatus = kalIoctl(prGlueInfo, wlanoidSetNchoScnChnlTime, + &u4Param, sizeof(uint32_t), + FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "NCHO set scan channel time fail 0x%x\n", + rStatus); + i4Ret = -1; + } else { + DBGLOG(INIT, TRACE, + "NCHO set scan channel time successed\n"); + i4Ret = 0; + } + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4Ret; +} +int priv_driver_get_ncho_scn_chnl_time(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = -1; + uint32_t u4Param = 0; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER cmdV1Header; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4BytesWritten; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return i4BytesWritten; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryNchoScnChnlTime, + &cmdV1Header, sizeof(cmdV1Header), + TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "NCHO wlanoidQueryNchoScnChnlTime fail 0x%x\n", rStatus); + } else { + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %s\n", + cmdV1Header.buffer); + i4BytesWritten = kalkStrtou32(cmdV1Header.buffer, 0, &u4Param); + if (i4BytesWritten) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d!\n", + i4BytesWritten); + i4BytesWritten = -1; + } else { + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%u", + u4Param); + } + } + return i4BytesWritten; +} + +int priv_driver_set_ncho_scn_home_time(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4Param = 0; + uint32_t u4SetInfoLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i4Ret = -1; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, + apcArgv[1]); + i4Ret = kalkStrtou32(apcArgv[1], 0, &u4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", + i4Ret); + return -1; + } + + DBGLOG(INIT, TRACE, "NCHO set scan home time cmd %d\n", + u4Param); + rStatus = kalIoctl(prGlueInfo, wlanoidSetNchoScnHomeTime, + &u4Param, sizeof(uint32_t), + FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "NCHO set scan home time fail 0x%x\n", rStatus); + i4Ret = -1; + } else { + DBGLOG(INIT, TRACE, + "NCHO set scan home time successed\n"); + i4Ret = 0; + } + + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4Ret; +} +int priv_driver_get_ncho_scn_home_time(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = -1; + uint32_t u4Param = 0; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER cmdV1Header; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4BytesWritten; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return i4BytesWritten; + } + rStatus = kalIoctl(prGlueInfo, wlanoidQueryNchoScnHomeTime, + &cmdV1Header, sizeof(cmdV1Header), + TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "NCHO wlanoidQueryNchoScnChnlTime fail 0x%x\n", rStatus); + } else { + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %s\n", + cmdV1Header.buffer); + i4BytesWritten = kalkStrtou32(cmdV1Header.buffer, 0, &u4Param); + if (i4BytesWritten) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d!\n", + i4BytesWritten); + i4BytesWritten = -1; + } else { + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%u", + u4Param); + } + } + return i4BytesWritten; +} + +int priv_driver_set_ncho_scn_home_away_time(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4Param = 0; + uint32_t u4SetInfoLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i4Ret = -1; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, apcArgv[1]); + i4Ret = kalkStrtou32(apcArgv[1], 0, &u4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", + i4Ret); + return -1; + } + + DBGLOG(INIT, TRACE, "NCHO set scan home away time cmd %d\n", + u4Param); + rStatus = kalIoctl(prGlueInfo, wlanoidSetNchoScnHomeAwayTime, + &u4Param, sizeof(uint32_t), + FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "NCHO set scan home away time fail 0x%x\n", + rStatus); + i4Ret = -1; + } else { + DBGLOG(INIT, TRACE, + "NCHO set scan home away time successed\n"); + i4Ret = 0; + } + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4Ret; +} +int priv_driver_get_ncho_scn_home_away_time(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = -1; + uint32_t u4Param = 0; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER cmdV1Header; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4BytesWritten; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return i4BytesWritten; + } + rStatus = kalIoctl(prGlueInfo, wlanoidQueryNchoScnHomeAwayTime, + &cmdV1Header, sizeof(cmdV1Header), + TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "NCHO wlanoidQueryNchoScnHomeAwayTime fail 0x%x\n", + rStatus); + return i4BytesWritten; + } + + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %s\n", cmdV1Header.buffer); + i4BytesWritten = kalkStrtou32(cmdV1Header.buffer, 0, &u4Param); + if (i4BytesWritten) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d!\n", + i4BytesWritten); + i4BytesWritten = -1; + } else { + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%u", u4Param); + } + + return i4BytesWritten; +} + +int priv_driver_set_ncho_scn_nprobes(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4Param = 0; + uint32_t u4SetInfoLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i4Ret = -1; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, apcArgv[1]); + + i4Ret = kalkStrtou32(apcArgv[1], 0, &u4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", + i4Ret); + return -1; + } + + DBGLOG(INIT, TRACE, "NCHO set scan nprobes cmd %d\n", u4Param); + rStatus = kalIoctl(prGlueInfo, wlanoidSetNchoScnNprobes, + &u4Param, sizeof(uint32_t), + FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO set scan nprobes fail 0x%x\n", + rStatus); + i4Ret = -1; + } else { + DBGLOG(INIT, TRACE, + "NCHO set scan nprobes successed\n"); + i4Ret = 0; + } + + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4Ret; +} + +int priv_driver_get_ncho_scn_nprobes(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = -1; + uint32_t u4Param = 0; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER cmdV1Header; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4BytesWritten; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return i4BytesWritten; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryNchoScnNprobes, + &cmdV1Header, sizeof(cmdV1Header), + TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "NCHO wlanoidQueryNchoScnNprobes fail 0x%x\n", rStatus); + return i4BytesWritten; + } + + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %s\n", cmdV1Header.buffer); + i4BytesWritten = kalkStrtou32(cmdV1Header.buffer, 0, &u4Param); + if (i4BytesWritten) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d!\n", + i4BytesWritten); + i4BytesWritten = -1; + } else { + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%u", u4Param); + } + + return i4BytesWritten; +} + +/* handle this command as framework roaming */ +int priv_driver_send_ncho_reassoc(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Ret = -1; + uint32_t u4Param = 0; + uint32_t u4SetInfoLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct _CFG_NCHO_RE_ASSOC_T rReAssoc; + struct PARAM_CONNECT rParamConn; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc == 3) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s %s\n", i4Argc, + apcArgv[1], apcArgv[2]); + + i4Ret = kalkStrtou32(apcArgv[2], 0, &u4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", + i4Ret); + return -1; + } + DBGLOG(INIT, TRACE, "NCHO send reassoc cmd %d\n", u4Param); + kalMemZero(&rReAssoc, sizeof(struct _CFG_NCHO_RE_ASSOC_T)); + rReAssoc.u4CenterFreq = nicChannelNum2Freq(u4Param); + CmdStringMacParse(apcArgv[1], (uint8_t **)&apcArgv[1], + &u4SetInfoLen, rReAssoc.aucBssid); + DBGLOG(INIT, TRACE, "NCHO Bssid " MACSTR " to roam\n", + MAC2STR(rReAssoc.aucBssid)); + rParamConn.pucBssid = (uint8_t *)rReAssoc.aucBssid; + rParamConn.pucSsid = (uint8_t *)rReAssoc.aucSsid; + rParamConn.u4SsidLen = rReAssoc.u4SsidLen; + rParamConn.u4CenterFreq = rReAssoc.u4CenterFreq; + + rStatus = kalIoctl(prGlueInfo, wlanoidGetNchoReassocInfo, + &rParamConn, sizeof(struct PARAM_CONNECT), + FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "NCHO get reassoc information fail 0x%x\n", + rStatus); + return -1; + } + DBGLOG(INIT, TRACE, "NCHO ssid %s to roam\n", + rParamConn.pucSsid); + rStatus = kalIoctl(prGlueInfo, wlanoidSetConnect, &rParamConn, + sizeof(struct PARAM_CONNECT), + FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO send reassoc fail 0x%x\n", + rStatus); + i4Ret = -1; + } else { + DBGLOG(INIT, TRACE, "NCHO send reassoc successed\n"); + i4Ret = 0; + } + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4Ret; +} + +int +nchoRemainOnChannel(IN struct ADAPTER *prAdapter, IN uint8_t ucChannelNum, + IN uint32_t u4DewellTime) +{ + int32_t i4Ret = -1; + struct MSG_REMAIN_ON_CHANNEL *prMsgChnlReq = + (struct MSG_REMAIN_ON_CHANNEL *) NULL; + + do { + if (!prAdapter) + break; + + prMsgChnlReq = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_REMAIN_ON_CHANNEL)); + + if (prMsgChnlReq == NULL) { + ASSERT(FALSE); + DBGLOG(REQ, ERROR, + "NCHO there is no memory for message channel req\n"); + return i4Ret; + } + kalMemZero(prMsgChnlReq, sizeof(struct MSG_REMAIN_ON_CHANNEL)); + + prMsgChnlReq->rMsgHdr.eMsgId = MID_MNY_AIS_REMAIN_ON_CHANNEL; + prMsgChnlReq->u4DurationMs = u4DewellTime; + prMsgChnlReq->u8Cookie = 0; + prMsgChnlReq->ucChannelNum = ucChannelNum; + + if ((ucChannelNum >= 1) && (ucChannelNum <= 14)) + prMsgChnlReq->eBand = BAND_2G4; + else + prMsgChnlReq->eBand = BAND_5G; + + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prMsgChnlReq, + MSG_SEND_METHOD_BUF); + + i4Ret = 0; + } while (FALSE); + + return i4Ret; +} + +int +nchoSendActionFrame(IN struct ADAPTER *prAdapter, + struct _NCHO_ACTION_FRAME_PARAMS_T *prParamActionFrame) +{ + int32_t i4Ret = -1; + struct MSG_MGMT_TX_REQUEST *prMsgTxReq = + (struct MSG_MGMT_TX_REQUEST *) NULL; + + if (!prAdapter || !prParamActionFrame) + return i4Ret; + + do { + /* Channel & Channel Type & Wait time are ignored. */ + prMsgTxReq = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_MGMT_TX_REQUEST)); + + if (prMsgTxReq == NULL) { + ASSERT(FALSE); + DBGLOG(REQ, ERROR, + "NCHO there is no memory for message tx req\n"); + return i4Ret; + } + + prMsgTxReq->fgNoneCckRate = FALSE; + prMsgTxReq->fgIsWaitRsp = TRUE; + + prMsgTxReq->u8Cookie = 0; + prMsgTxReq->rMsgHdr.eMsgId = MID_MNY_AIS_NCHO_ACTION_FRAME; + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *) prMsgTxReq, + MSG_SEND_METHOD_BUF); + + i4Ret = 0; + } while (FALSE); + + if ((i4Ret != 0) && (prMsgTxReq != NULL)) { + if (prMsgTxReq->prMgmtMsduInfo != NULL) + cnmMgtPktFree(prAdapter, prMsgTxReq->prMgmtMsduInfo); + + cnmMemFree(prAdapter, prMsgTxReq); + } + + return i4Ret; +} + +uint32_t nchoParseActionFrame( + IN struct _NCHO_ACTION_FRAME_PARAMS_T *prParamActionFrame, + IN char *pcCommand) +{ + uint32_t u4SetInfoLen = 0; + uint32_t u4Num = 0; + struct _NCHO_AF_INFO_T *prAfInfo = NULL; + + if (!prParamActionFrame || !pcCommand) + return WLAN_STATUS_FAILURE; + + prAfInfo = (struct _NCHO_AF_INFO_T *)(pcCommand + + kalStrLen(CMD_NCHO_ACTION_FRAME_SEND) + 1); + if (prAfInfo->i4len > CMD_NCHO_AF_DATA_LENGTH) { + DBGLOG(INIT, ERROR, "NCHO AF data length is %d\n", + prAfInfo->i4len); + return WLAN_STATUS_FAILURE; + } + + prParamActionFrame->i4len = prAfInfo->i4len; + prParamActionFrame->i4channel = prAfInfo->i4channel; + prParamActionFrame->i4DwellTime = prAfInfo->i4DwellTime; + kalMemZero(prParamActionFrame->aucData, CMD_NCHO_AF_DATA_LENGTH/2); + u4SetInfoLen = prAfInfo->i4len; + while (u4SetInfoLen > 0 && u4Num < CMD_NCHO_AF_DATA_LENGTH/2) { + *(prParamActionFrame->aucData + u4Num) = + CmdString2HexParse(prAfInfo->pucData, + (uint8_t **)&prAfInfo->pucData, + (uint8_t *)&u4SetInfoLen); + u4Num++; + } + DBGLOG(INIT, TRACE, "NCHO MAC str is %s\n", prAfInfo->aucBssid); + CmdStringMacParse(prAfInfo->aucBssid, + (uint8_t **)&prAfInfo->aucBssid, + &u4SetInfoLen, + prParamActionFrame->aucBssid); + return WLAN_STATUS_SUCCESS; +} + +int +priv_driver_send_ncho_action_frame(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + NCHO_ACTION_FRAME_PARAMS rParamActionFrame; + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4Ret = -1; + uint32_t u4SetInfoLen = 0; + unsigned long ulTimer = 0; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rStatus = nchoParseActionFrame(&rParamActionFrame, pcCommand); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO action frame parse error\n"); + return -1; + } + + DBGLOG(INIT, TRACE, "NCHO MAC is " MACSTR "\n", + MAC2STR(rParamActionFrame.aucBssid)); + rStatus = kalIoctl(prGlueInfo, + wlanoidSendNchoActionFrameStart, + &rParamActionFrame, + sizeof(NCHO_ACTION_FRAME_PARAMS), + FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO send action fail 0x%x\n", rStatus); + return -1; + } + + reinit_completion(&prGlueInfo->rAisChGrntComp); + i4Ret = nchoRemainOnChannel(prGlueInfo->prAdapter, + rParamActionFrame.i4channel, + rParamActionFrame.i4DwellTime); + + ulTimer = wait_for_completion_timeout(&prGlueInfo->rAisChGrntComp, + msecs_to_jiffies(CMD_NCHO_COMP_TIMEOUT)); + if (ulTimer) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSendNchoActionFrameEnd, + NULL, 0, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO send action fail 0x%x\n", + rStatus); + return -1; + } + i4Ret = nchoSendActionFrame(prGlueInfo->prAdapter, + &rParamActionFrame); + } else { + i4Ret = -1; + DBGLOG(INIT, ERROR, "NCHO req channel timeout\n"); + } + + return i4Ret; +} + +int +priv_driver_set_ncho_wes_mode(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4Param = 0; + uint32_t u4SetInfoLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i4Ret = -1; + uint32_t rStatus = WLAN_STATUS_FAILURE; + uint8_t puCommondBuf[WLAN_CFG_ARGV_MAX]; + + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, apcArgv[1]); + i4Ret = kalkStrtou32(apcArgv[1], 0, &u4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", + i4Ret); + return -1; + } + /*If WES mode is 1, enable NCHO*/ + /*If WES mode is 0, disable NCHO*/ + if (u4Param == TRUE && + prGlueInfo->prAdapter->rNchoInfo.fgECHOEnabled == FALSE) { + kalSnprintf(puCommondBuf, WLAN_CFG_ARGV_MAX, "%s %d", + CMD_NCHO_ENABLE, 1); + priv_driver_enable_ncho(prNetDev, puCommondBuf, + sizeof(puCommondBuf)); + } else if (u4Param == FALSE && + prGlueInfo->prAdapter->rNchoInfo.fgECHOEnabled == TRUE) { + kalSnprintf(puCommondBuf, WLAN_CFG_ARGV_MAX, "%s", + CMD_NCHO_DISABLE); + priv_driver_disable_ncho(prNetDev, puCommondBuf, + sizeof(puCommondBuf)); + } + + DBGLOG(INIT, INFO, "NCHO set WES mode cmd %d\n", u4Param); + rStatus = kalIoctl(prGlueInfo, wlanoidSetNchoWesMode, &u4Param, + sizeof(uint32_t), + FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO set WES mode fail 0x%x\n", + rStatus); + i4Ret = -1; + } else { + DBGLOG(INIT, TRACE, "NCHO set WES mode successed\n"); + i4Ret = 0; + } + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4Ret; +} + +int priv_driver_get_ncho_wes_mode(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = -1; + uint32_t u4Param = 0; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -WLAN_STATUS_FAILURE; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return i4BytesWritten; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryNchoWesMode, &u4Param, + sizeof(uint32_t), + TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO wlanoidQueryNchoWesMode fail 0x%x\n", + rStatus); + } else { + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %d\n", u4Param); + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%u", u4Param); + } + DBGLOG(REQ, TRACE, "NCHO get result is %s\n", pcCommand); + return i4BytesWritten; +} + +int priv_driver_set_ncho_band(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4Param = 0; + uint32_t u4SetInfoLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i4Ret = -1; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, apcArgv[1]); + i4Ret = kalkStrtou32(apcArgv[1], 0, &u4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", + i4Ret); + return -1; + } + + DBGLOG(INIT, TRACE, "NCHO set band cmd %d\n", u4Param); + rStatus = kalIoctl(prGlueInfo, wlanoidSetNchoBand, &u4Param, + sizeof(uint32_t), + FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO set band fail 0x%x\n", + rStatus); + i4Ret = -1; + } else { + DBGLOG(INIT, TRACE, "NCHO set band successed\n"); + i4Ret = 0; + } + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4Ret; +} +int priv_driver_get_ncho_band(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = -1; + uint32_t u4Param = 0; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4BytesWritten; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return i4BytesWritten; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryNchoBand, &u4Param, + sizeof(uint32_t), + TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO wlanoidQueryNchoBand fail 0x%x\n", + rStatus); + } else { + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %d\n", u4Param); + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%u", u4Param); + } + return i4BytesWritten; +} + +int priv_driver_set_ncho_dfs_scn_mode(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4Param = 0; + uint32_t u4SetInfoLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i4Ret = -1; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4Ret; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, apcArgv[1]); + i4Ret = kalkStrtou32(apcArgv[1], 0, &u4Param); + if (i4Ret) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", + i4Ret); + return -1; + } + + DBGLOG(INIT, TRACE, "NCHO set DFS scan cmd %d\n", u4Param); + rStatus = kalIoctl(prGlueInfo, wlanoidSetNchoDfsScnMode, + &u4Param, sizeof(uint32_t), + FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO set DFS scan fail 0x%x\n", + rStatus); + i4Ret = -1; + } else { + DBGLOG(INIT, TRACE, "NCHO set DFS scan successed\n"); + i4Ret = 0; + } + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4Ret; +} +int +priv_driver_get_ncho_dfs_scn_mode(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = -1; + uint32_t u4Param = 0; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER cmdV1Header; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4BytesWritten; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO Error input parameter %d\n", i4Argc); + return i4BytesWritten; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryNchoDfsScnMode, &cmdV1Header, + sizeof(struct CMD_HEADER), + TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "NCHO wlanoidQueryNchoDfsScnMode fail 0x%x\n", rStatus); + return i4BytesWritten; + } + + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %s\n", cmdV1Header.buffer); + i4BytesWritten = kalkStrtou32(cmdV1Header.buffer, 0, &u4Param); + if (i4BytesWritten) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d!\n", + i4BytesWritten); + i4BytesWritten = -1; + } else { + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%u", u4Param); + } + + return i4BytesWritten; +} + +int +priv_driver_enable_ncho(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4Param = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i4BytesWritten = -1; + uint32_t u4SetInfoLen = 0; + uint32_t rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4BytesWritten; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (rStatus == WLAN_STATUS_SUCCESS && i4Argc >= 2) { + DBGLOG(REQ, TRACE, "NCHO argc is %i, %s\n", i4Argc, + apcArgv[1]); + i4BytesWritten = kalkStrtou32(apcArgv[1], 0, &u4Param); + if (i4BytesWritten) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d\n", + i4BytesWritten); + i4BytesWritten = -1; + } else { + DBGLOG(INIT, TRACE, "NCHO set enable cmd %d\n", + u4Param); + rStatus = kalIoctl(prGlueInfo, wlanoidSetNchoEnable, + &u4Param, sizeof(uint32_t), + FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "NCHO set enable fail 0x%x\n", rStatus); + i4BytesWritten = -1; + } else { + DBGLOG(INIT, TRACE, + "NCHO set enable successed\n"); + i4BytesWritten = 0; + } + } + } else { + DBGLOG(REQ, ERROR, "NCHO set failed\n"); + } + return i4BytesWritten; +} + +int +priv_driver_disable_ncho(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t i4BytesWritten = -1; + uint32_t u4Param = 0; + uint32_t u4BufLen = 0; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CMD_HEADER cmdV1Header; + + DBGLOG(INIT, TRACE, "NCHO command is %s\n", pcCommand); + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return i4BytesWritten; + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + + rStatus = wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + if (rStatus != WLAN_STATUS_SUCCESS || i4Argc >= 2) { + DBGLOG(REQ, ERROR, "NCHO error input parameter %d\n", i4Argc); + return i4BytesWritten; + } + /*<1> Set NCHO Disable to FW*/ + u4Param = FALSE; + rStatus = kalIoctl(prGlueInfo, wlanoidSetNchoEnable, &u4Param, + sizeof(uint32_t), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "NCHO wlanoidSetNchoEnable :%d fail 0x%x\n", + u4Param, rStatus); + return i4BytesWritten; + } + + /*<2> Query NCHOEnable Satus*/ + rStatus = kalIoctl(prGlueInfo, wlanoidQueryNchoEnable, + &cmdV1Header, sizeof(cmdV1Header), + TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "NCHO wlanoidQueryNchoEnable fail 0x%x\n", + rStatus); + return i4BytesWritten; + } + + DBGLOG(REQ, TRACE, "NCHO query ok and ret is %s\n", cmdV1Header.buffer); + + + i4BytesWritten = kalkStrtou32(cmdV1Header.buffer, 0, &u4Param); + if (i4BytesWritten) { + DBGLOG(REQ, ERROR, "NCHO parse u4Param error %d!\n", + i4BytesWritten); + i4BytesWritten = -1; + } else { + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%u", u4Param); + } + + return i4BytesWritten; +} +/*Check NCHO is enable or not.*/ +u_int8_t +priv_driver_auto_enable_ncho(IN struct net_device *prNetDev) +{ + uint8_t puCommondBuf[WLAN_CFG_ARGV_MAX]; + struct GLUE_INFO *prGlueInfo = NULL; + + ASSERT(prNetDev); + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + + kalSnprintf(puCommondBuf, WLAN_CFG_ARGV_MAX, "%s %d", CMD_NCHO_ENABLE, + 1); +#if CFG_SUPPORT_NCHO_AUTO_ENABLE + if (prGlueInfo->prAdapter->rNchoInfo.fgECHOEnabled == FALSE) { + DBGLOG(INIT, INFO, + "NCHO is unavailable now! Start to NCHO Enable CMD\n"); + priv_driver_enable_ncho(prNetDev, puCommondBuf, + sizeof(puCommondBuf)); + + } +#endif + return TRUE; +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/axi/axi.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/axi/axi.c new file mode 100644 index 0000000000000..1e5d7bfbffdf7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/axi/axi.c @@ -0,0 +1,1318 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** + *[File] axi.c + *[Version] v1.0 + *[Revision Date] 2010-03-01 + *[Author] + *[Description] + * The program provides AXI HIF driver + *[Copyright] + * Copyright (C) 2010 MediaTek Incorporation. All Rights Reserved. + ******************************************************************************/ + + +/******************************************************************************* + * C O M P I L E 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 "hif_pdma.h" + +#include "precomp.h" + +#include +#include +#include +#include +#ifndef CONFIG_X86 +#include +#endif + +#include "mt66xx_reg.h" + +#include +#include +#include + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +static const struct platform_device_id mtk_axi_ids[] = { +#ifdef CONNAC + { .name = "CONNAC", + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_connac}, +#endif /* CONNAC */ +#ifdef CONNAC2X2 + { .name = "CONNAC2X2", + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_connac2x2}, +#endif /* CONNAC2X2 */ + { /* end: all zeroes */ }, +}; + +MODULE_DEVICE_TABLE(axi, mtk_axi_ids); + +/******************************************************************************* + * 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 struct platform_device *prPlatDev; +static probe_card pfWlanProbe; +static remove_card pfWlanRemove; + +static struct platform_driver mtk_axi_driver = { + .driver = { + .name = "wlan", + .owner = THIS_MODULE, + }, + .id_table = mtk_axi_ids, + .probe = NULL, + .remove = NULL, +}; + +static struct GLUE_INFO *g_prGlueInfo; +static void *CSRBaseAddress; +static u64 g_u8CsrOffset; +static u32 g_u4CsrSize; +static u_int8_t g_fgDriverProbed = FALSE; + +#if AXI_CFG_PREALLOC_MEMORY_BUFFER +struct HIF_PREALLOC_MEM grMem; +#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 AXI_CFG_PREALLOC_MEMORY_BUFFER + +static void axiAllocTxDesc(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing, + uint32_t u4Num); +static void axiAllocRxDesc(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing, + uint32_t u4Num); +static void axiAllocTxCmdBuf(struct RTMP_DMABUF *prDmaBuf, + uint32_t u4Num, uint32_t u4Idx); +static void axiflushCache(struct GL_HIF_INFO *prHifInfo, + void *pucSrc, uint32_t u4Len); +#else +static void axiAllocDesc(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing, + uint32_t u4Num); +static void *axiAllocRuntimeMem(uint32_t u4SrcLen); +static phys_addr_t axiMapTxBuf(struct GL_HIF_INFO *prHifInfo, + void *pucBuf, uint32_t u4Offset, uint32_t u4Len); +static phys_addr_t axiMapRxBuf(struct GL_HIF_INFO *prHifInfo, + void *pucBuf, uint32_t u4Offset, uint32_t u4Len); +static void axiUnmapTxBuf(struct GL_HIF_INFO *prHifInfo, + phys_addr_t rDmaAddr, uint32_t u4Len); +static void axiUnmapRxBuf(struct GL_HIF_INFO *prHifInfo, + phys_addr_t rDmaAddr, uint32_t u4Len); +static void axiFreeDesc(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing); +static void axiFreeBuf(void *pucSrc, uint32_t u4Len); +static void axiFreePacket(void *pvPacket); +#endif /* AXI_CFG_PREALLOC_MEMORY_BUFFER */ + +static void axiAllocTxDataBuf(struct MSDU_TOKEN_ENTRY *prToken, uint32_t u4Idx); +static void *axiAllocRxBuf(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDmaBuf, + uint32_t u4Num, uint32_t u4Idx); +static bool axiCopyCmd(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *prTxCell, void *pucBuf, + void *pucSrc1, uint32_t u4SrcLen1, + void *pucSrc2, uint32_t u4SrcLen2); +static bool axiCopyEvent(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *pRxCell, + struct RXD_STRUCT *pRxD, + struct RTMP_DMABUF *prDmaBuf, + uint8_t *pucDst, uint32_t u4Len); +static bool axiCopyTxData(struct MSDU_TOKEN_ENTRY *prToken, + void *pucSrc, uint32_t u4Len); +static bool axiCopyRxData(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *pRxCell, + struct RTMP_DMABUF *prDmaBuf, + struct SW_RFB *prSwRfb); +static void axiDumpTx(struct GL_HIF_INFO *prHifInfo, + struct RTMP_TX_RING *prTxRing, + uint32_t u4Idx, uint32_t u4DumpLen); +static void axiDumpRx(struct GL_HIF_INFO *prHifInfo, + struct RTMP_RX_RING *prRxRing, + uint32_t u4Idx, uint32_t u4DumpLen); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +static int hifAxiProbe(void) +{ + int ret = 0; + + ASSERT(prPlatDev); + + DBGLOG(INIT, TRACE, "driver.name = %s\n", prPlatDev->id_entry->name); + + if (pfWlanProbe((void *)prPlatDev, + (void *)prPlatDev->id_entry->driver_data) != + WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "pfWlanProbe fail!call pfWlanRemove()\n"); + pfWlanRemove(); + ret = -1; + goto out; + } + g_fgDriverProbed = TRUE; +out: + DBGLOG(INIT, TRACE, "hifAxiProbe() done(%d)\n", ret); + + return ret; +} + +static int hifAxiRemove(void) +{ + ASSERT(prPlatDev); + + if (g_fgDriverProbed) + pfWlanRemove(); + DBGLOG(INIT, TRACE, "pfWlanRemove done\n"); + DBGLOG(INIT, TRACE, "hifAxiRemove() done\n"); + return 0; +} + +#if CFG_MTK_ANDROID_WMT +static int hifAxiGetBusCnt(void) +{ + if (!g_prGlueInfo) + return 0; + + return g_prGlueInfo->rHifInfo.u4HifCnt; +} + +static int hifAxiClrBusCnt(void) +{ + if (g_prGlueInfo) + g_prGlueInfo->rHifInfo.u4HifCnt = 0; + + return 0; +} + +static int hifAxiSetMpuProtect(bool enable) +{ +#if CFG_MTK_ANDROID_EMI + kalSetEmiMpuProtection(gConEmiPhyBase, WIFI_EMI_MEM_OFFSET, + WIFI_EMI_MEM_SIZE, enable); +#endif + return 0; +} +#endif /* CFG_MTK_ANDROID_WMT */ + +static void axiDmaSetup(struct platform_device *pdev) +{ + struct mt66xx_chip_info *prChipInfo; + const struct dma_map_ops *dma_ops = NULL; + u64 required_mask, dma_mask; + int ret = 0; + + prChipInfo = ((struct mt66xx_hif_driver_data *) + mtk_axi_ids[0].driver_data)->chip_info; + + dma_mask = DMA_BIT_MASK(prChipInfo->bus_info->u4DmaMask); + required_mask = dma_get_required_mask(&pdev->dev); + DBGLOG(INIT, INFO, + "pdev=%p, pdev->dev=%p, name=%s, required_mask=%llx, dma_addr_t=%zu\n", + pdev, &pdev->dev, pdev->id_entry->name, + required_mask, sizeof(dma_addr_t)); + + pdev->dev.coherent_dma_mask = dma_mask; + pdev->dev.dma_mask = &(pdev->dev.coherent_dma_mask); + + KAL_ARCH_SETUP_DMA_OPS(&pdev->dev, 0, dma_mask, NULL, false); + dma_ops = get_dma_ops(&pdev->dev); + DBGLOG(INIT, INFO, "dma_supported=%d, dma_mask=%llx\n", + dma_supported(&pdev->dev, dma_mask), dma_mask); + + ret = dma_set_mask_and_coherent(&pdev->dev, dma_mask); + if (ret) + DBGLOG(INIT, INFO, "set DMA mask failed! errno=%d\n", ret); +} + +static bool axiCsrIoremap(struct platform_device *pdev) +{ + +#ifdef CONFIG_OF + struct device_node *node = NULL; + struct resource res; + + node = of_find_compatible_node(NULL, NULL, "mediatek,wifi"); + if (!node) { + DBGLOG(INIT, ERROR, "WIFI-OF: get wifi device node fail\n"); + return false; + } + + if (of_address_to_resource(node, 0, &res)) { + DBGLOG(INIT, ERROR, "WIFI-OF: of_address_to_resource fail\n"); + return false; + } + + g_u8CsrOffset = (u64)res.start; + g_u4CsrSize = resource_size(&res); +#else + g_u8CsrOffset = axi_resource_start(pdev, 0); + g_u4CsrSize = axi_resource_len(pdev, 0); +#endif + if (CSRBaseAddress) { + DBGLOG(INIT, ERROR, "CSRBaseAddress not iounmap!\n"); + return false; + } + + request_mem_region(g_u8CsrOffset, g_u4CsrSize, axi_name(pdev)); + + /* map physical address to virtual address for accessing register */ +#ifdef CONFIG_OF + CSRBaseAddress = of_iomap(node, 0); +#else + CSRBaseAddress = ioremap(g_u8CsrOffset, g_u4CsrSize); +#endif + + if (!CSRBaseAddress) { + DBGLOG(INIT, INFO, + "ioremap failed for device %s, region 0x%X @ 0x%lX\n", + axi_name(pdev), g_u4CsrSize, g_u8CsrOffset); + release_mem_region(g_u8CsrOffset, g_u4CsrSize); + return false; + } + + DBGLOG(INIT, INFO, "CSRBaseAddress:0x%lX ioremap region 0x%X @ 0x%lX\n", + CSRBaseAddress, g_u4CsrSize, g_u8CsrOffset); + + return true; +} + +static void axiCsrIounmap(struct platform_device *pdev) +{ + if (!CSRBaseAddress) + return; + + /* Unmap CSR base address */ + iounmap(CSRBaseAddress); + release_mem_region(g_u8CsrOffset, g_u4CsrSize); + + CSRBaseAddress = NULL; + g_u8CsrOffset = 0; + g_u4CsrSize = 0; +} + +#if AXI_CFG_PREALLOC_MEMORY_BUFFER + +static bool axiAllocRsvMem(uint32_t u4Size, struct HIF_MEM *prMem, + bool fgIsCached) +{ + /* 8 bytes alignment */ + if (u4Size & 7) + u4Size += 8 - (u4Size & 7); + prMem->pa = grMem.pucRsvMemBase + grMem.u4Offset; + if (fgIsCached) + prMem->va = ioremap_cache(prMem->pa, u4Size); + else + prMem->va = ioremap_nocache(prMem->pa, u4Size); + grMem.u4Offset += u4Size; + + return prMem->va != NULL; +} + +static void axiAllocHifMem(struct platform_device *pdev) +{ + uint32_t u4Idx; + + request_mem_region(gWifiRsvMemPhyBase, gWifiRsvMemSize, axi_name(pdev)); + +#if CFG_MTK_ANDROID_EMI + kalSetDrvEmiMpuProtection(gWifiRsvMemPhyBase, 0, gWifiRsvMemSize); +#endif + + grMem.pucRsvMemBase = gWifiRsvMemPhyBase; + grMem.u4RsvMemSize = (uint64_t)gWifiRsvMemSize; + grMem.u4Offset = 0; + DBGLOG(INIT, INFO, + "gWifiRsvMemPhyBase[0x%p], gWifiRsvMemSize[0x%llx]\n", + grMem.pucRsvMemBase, grMem.u4RsvMemSize); + + for (u4Idx = 0; u4Idx < NUM_OF_TX_RING; u4Idx++) { + if (!axiAllocRsvMem(TX_RING_SIZE * TXD_SIZE, + &grMem.rTxDesc[u4Idx], false)) + DBGLOG(INIT, ERROR, "TxDesc[%u] alloc fail\n", u4Idx); + } + + if (!axiAllocRsvMem(RX_RING0_SIZE * RXD_SIZE, &grMem.rRxDesc[0], false)) + DBGLOG(INIT, ERROR, "RxDesc[0] alloc fail\n"); + + if (!axiAllocRsvMem(RX_RING1_SIZE * RXD_SIZE, &grMem.rRxDesc[1], false)) + DBGLOG(INIT, ERROR, "RxDesc[1] alloc fail\n"); + + for (u4Idx = 0; u4Idx < TX_RING_SIZE; u4Idx++) { + if (!axiAllocRsvMem(AXI_TX_CMD_BUFF_SIZE, + &grMem.rTxCmdBuf[u4Idx], false)) + DBGLOG(INIT, ERROR, "TxCmdBuf[%u] alloc fail\n", u4Idx); + } + + for (u4Idx = 0; u4Idx < RX_RING0_SIZE; u4Idx++) { + if (!axiAllocRsvMem(CFG_RX_MAX_PKT_SIZE, + &grMem.rRxDataBuf[u4Idx], true)) + DBGLOG(INIT, ERROR, + "RxDataBuf[%u] alloc fail\n", u4Idx); + } + + for (u4Idx = 0; u4Idx < RX_RING1_SIZE; u4Idx++) { + if (!axiAllocRsvMem(RX_BUFFER_AGGRESIZE, + &grMem.rRxEventBuf[u4Idx], false)) + DBGLOG(INIT, ERROR, + "RxEventBuf[%u] alloc fail\n", u4Idx); + } + +#if HIF_TX_PREALLOC_DATA_BUFFER + for (u4Idx = 0; u4Idx < HIF_TX_MSDU_TOKEN_NUM; u4Idx++) { + if (!axiAllocRsvMem(AXI_TX_MAX_SIZE_PER_FRAME, + &grMem.rMsduBuf[u4Idx], true)) + DBGLOG(INIT, ERROR, "MsduBuf[%u] alloc fail\n", u4Idx); + } +#endif + DBGLOG(INIT, INFO, "grMem.u4Offset[0x%x]\n", grMem.u4Offset); +} + +static void axiFreeHifMem(struct platform_device *pdev) +{ + uint32_t u4Idx; + + for (u4Idx = 0; u4Idx < NUM_OF_TX_RING; u4Idx++) { + if (grMem.rTxDesc[u4Idx].va) + iounmap(grMem.rTxDesc[u4Idx].va); + } + + for (u4Idx = 0; u4Idx < NUM_OF_RX_RING; u4Idx++) { + if (grMem.rRxDesc[u4Idx].va) + iounmap(grMem.rRxDesc[u4Idx].va); + } + + for (u4Idx = 0; u4Idx < RX_RING0_SIZE; u4Idx++) { + if (grMem.rRxDataBuf[u4Idx].va) + iounmap(grMem.rRxDataBuf[u4Idx].va); + } + + for (u4Idx = 0; u4Idx < RX_RING1_SIZE; u4Idx++) { + if (grMem.rRxEventBuf[u4Idx].va) + iounmap(grMem.rRxEventBuf[u4Idx].va); + } + +#if HIF_TX_PREALLOC_DATA_BUFFER + for (u4Idx = 0; u4Idx < HIF_TX_MSDU_TOKEN_NUM; u4Idx++) { + if (grMem.rMsduBuf[u4Idx].va) + iounmap(grMem.rMsduBuf[u4Idx].va); + } +#endif + release_mem_region(gWifiRsvMemPhyBase, gWifiRsvMemSize); +} +#endif /* AXI_CFG_PREALLOC_MEMORY_BUFFER */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is a AXI interrupt callback function + * + * \param[in] func pointer to AXI handle + * + * \return void + */ +/*----------------------------------------------------------------------------*/ +static irqreturn_t mtk_axi_interrupt(int irq, void *dev_instance) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *)dev_instance; + if (!prGlueInfo) { + DBGLOG(HAL, INFO, "No glue info in mtk_axi_interrupt()\n"); + return IRQ_NONE; + } + + halDisableInterrupt(prGlueInfo->prAdapter); + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(HAL, INFO, "GLUE_FLAG_HALT skip INT\n"); + return IRQ_NONE; + } + + kalSetIntEvent(prGlueInfo); + + return IRQ_HANDLED; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is a AXI probe function + * + * \param[in] func pointer to AXI handle + * \param[in] id pointer to AXI device id table + * + * \return void + */ +/*----------------------------------------------------------------------------*/ +static int mtk_axi_probe(IN struct platform_device *pdev) +{ +#if CFG_MTK_ANDROID_WMT + struct MTK_WCN_WMT_WLAN_CB_INFO rWmtCb; +#endif + + axiDmaSetup(pdev); + axiCsrIoremap(pdev); + +#if AXI_CFG_PREALLOC_MEMORY_BUFFER + axiAllocHifMem(pdev); +#endif + +#if CFG_MTK_ANDROID_WMT + rWmtCb.wlan_probe_cb = hifAxiProbe; + rWmtCb.wlan_remove_cb = hifAxiRemove; + rWmtCb.wlan_bus_cnt_get_cb = hifAxiGetBusCnt; + rWmtCb.wlan_bus_cnt_clr_cb = hifAxiClrBusCnt; + rWmtCb.wlan_emi_mpu_set_protection_cb = hifAxiSetMpuProtect; + mtk_wcn_wmt_wlan_reg(&rWmtCb); +#else + hifAxiProbe(); +#endif + DBGLOG(INIT, INFO, "mtk_axi_probe() done\n"); + + return 0; +} + +static int mtk_axi_remove(IN struct platform_device *pdev) +{ + axiCsrIounmap(pdev); + +#if AXI_CFG_PREALLOC_MEMORY_BUFFER + axiFreeHifMem(pdev); +#endif + +#if CFG_MTK_ANDROID_WMT + mtk_wcn_wmt_wlan_unreg(); +#else + hifAxiRemove(); +#endif + return 0; +} + +static int mtk_axi_suspend(IN struct platform_device *pdev, + IN pm_message_t state) +{ + return 0; +} + +int mtk_axi_resume(IN struct platform_device *pdev) +{ + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will register pci 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 pci bus + */ +/*----------------------------------------------------------------------------*/ +uint32_t glRegisterBus(probe_card pfProbe, remove_card pfRemove) +{ + int ret = 0; + + ASSERT(pfProbe); + ASSERT(pfRemove); + + pfWlanProbe = pfProbe; + pfWlanRemove = pfRemove; + + mtk_axi_driver.probe = mtk_axi_probe; + mtk_axi_driver.remove = mtk_axi_remove; + + mtk_axi_driver.suspend = mtk_axi_suspend; + mtk_axi_driver.resume = mtk_axi_resume; + + ret = (platform_driver_register(&mtk_axi_driver) == 0) + ? WLAN_STATUS_SUCCESS : WLAN_STATUS_FAILURE; + DBGLOG(INIT, INFO, "platform_driver_register ret = %d\n", ret); + DBGLOG(INIT, INFO, "bus_type = %s\n", mtk_axi_driver.driver.bus->name); + if (!ret) + ret = ((prPlatDev = + platform_device_alloc("CONNAC", -1)) != NULL) + ? WLAN_STATUS_SUCCESS : WLAN_STATUS_FAILURE; + + DBGLOG(INIT, INFO, "platform_device_alloc ret = %d\n", ret); + ret = (platform_device_add(prPlatDev) == 0) + ? WLAN_STATUS_SUCCESS : WLAN_STATUS_FAILURE; + DBGLOG(INIT, INFO, "platform_device_add ret = %d\n", ret); + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will unregister pci bus to the os + * + * \param[in] pfRemove Function pointer to remove card + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void glUnregisterBus(remove_card pfRemove) +{ + if (g_fgDriverProbed) { + pfRemove(); + g_fgDriverProbed = FALSE; + } + if (prPlatDev) + platform_device_del(prPlatDev); + platform_driver_unregister(&mtk_axi_driver); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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(struct GLUE_INFO *prGlueInfo, unsigned long ulCookie) +{ + struct GL_HIF_INFO *prHif = NULL; + struct HIF_MEM_OPS *prMemOps; + + g_prGlueInfo = prGlueInfo; + prHif = &prGlueInfo->rHifInfo; + prMemOps = &prHif->rMemOps; + + prHif->pdev = (struct platform_device *)ulCookie; + prHif->prDmaDev = &prHif->pdev->dev; + + prHif->CSRBaseAddress = CSRBaseAddress; + + platform_set_drvdata(prHif->pdev, prGlueInfo); + + SET_NETDEV_DEV(prGlueInfo->prDevHandler, &prHif->pdev->dev); + + prGlueInfo->u4InfType = MT_DEV_INF_AXI; + + prHif->rErrRecoveryCtl.eErrRecovState = ERR_RECOV_STOP_IDLE; + prHif->rErrRecoveryCtl.u4Status = 0; + prHif->fgIsErrRecovery = FALSE; + + INIT_LIST_HEAD(&prHif->rTxCmdQ); + INIT_LIST_HEAD(&prHif->rTxDataQ); + prHif->u4TxDataQLen = 0; + + prHif->fgIsPowerOff = true; + prHif->fgIsDumpLog = false; + +#if AXI_CFG_PREALLOC_MEMORY_BUFFER + prMemOps->allocTxDesc = axiAllocTxDesc; + prMemOps->allocRxDesc = axiAllocRxDesc; + prMemOps->allocTxCmdBuf = axiAllocTxCmdBuf; + prMemOps->allocTxDataBuf = axiAllocTxDataBuf; + prMemOps->allocRxBuf = axiAllocRxBuf; + prMemOps->allocRuntimeMem = NULL; + prMemOps->copyCmd = axiCopyCmd; + prMemOps->copyEvent = axiCopyEvent; + prMemOps->copyTxData = axiCopyTxData; + prMemOps->copyRxData = axiCopyRxData; + prMemOps->flushCache = axiflushCache; + prMemOps->mapTxBuf = NULL; + prMemOps->mapRxBuf = NULL; + prMemOps->unmapTxBuf = NULL; + prMemOps->unmapRxBuf = NULL; + prMemOps->freeDesc = NULL; + prMemOps->freeBuf = NULL; + prMemOps->freePacket = NULL; + prMemOps->dumpTx = axiDumpTx; + prMemOps->dumpRx = axiDumpRx; +#else + prMemOps->allocTxDesc = axiAllocDesc; + prMemOps->allocRxDesc = axiAllocDesc; + prMemOps->allocTxCmdBuf = NULL; + prMemOps->allocTxDataBuf = axiAllocTxDataBuf; + prMemOps->allocRxBuf = axiAllocRxBuf; + prMemOps->allocRuntimeMem = axiAllocRuntimeMem; + prMemOps->copyCmd = axiCopyCmd; + prMemOps->copyEvent = axiCopyEvent; + prMemOps->copyTxData = axiCopyTxData; + prMemOps->copyRxData = axiCopyRxData; + prMemOps->flushCache = NULL; + prMemOps->mapTxBuf = axiMapTxBuf; + prMemOps->mapRxBuf = axiMapRxBuf; + prMemOps->unmapTxBuf = axiUnmapTxBuf; + prMemOps->unmapRxBuf = axiUnmapRxBuf; + prMemOps->freeDesc = axiFreeDesc; + prMemOps->freeBuf = axiFreeBuf; + prMemOps->freePacket = axiFreePacket; + prMemOps->dumpTx = axiDumpTx; + prMemOps->dumpRx = axiDumpRx; +#endif /* AXI_CFG_PREALLOC_MEMORY_BUFFER */ +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function clears hif related info. + * + * \param[in] prGlueInfo Pointer to glue info structure + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void glClearHifInfo(struct GLUE_INFO *prGlueInfo) +{ + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + struct list_head *prCur, *prNext; + struct TX_CMD_REQ *prTxCmdReq; + struct TX_DATA_REQ *prTxDataReq; + + halUninitMsduTokenInfo(prGlueInfo->prAdapter); + halWpdmaFreeRing(prGlueInfo); + + list_for_each_safe(prCur, prNext, &prHifInfo->rTxCmdQ) { + prTxCmdReq = list_entry(prCur, struct TX_CMD_REQ, list); + list_del(prCur); + kfree(prTxCmdReq); + } + + list_for_each_safe(prCur, prNext, &prHifInfo->rTxDataQ) { + prTxDataReq = list_entry(prCur, struct TX_DATA_REQ, list); + list_del(prCur); + prHifInfo->u4TxDataQLen--; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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) + */ +/*----------------------------------------------------------------------------*/ +u_int8_t glBusInit(void *pvData) +{ + ASSERT(pvData); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Stop bus operation and release resources. + * + * \param[in] pvData A pointer to struct net_device. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void glBusRelease(void *pvData) +{ +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ + +int32_t glBusSetIrq(void *pvData, void *pfnIsr, void *pvCookie) +{ + struct net_device *prNetDevice = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct GL_HIF_INFO *prHifInfo = NULL; + struct platform_device *pdev = NULL; +#ifdef CONFIG_OF + struct device_node *node = NULL; +#endif + int ret = 0; + + ASSERT(pvData); + if (!pvData) + return -1; + + prNetDevice = (struct net_device *)pvData; + prGlueInfo = (struct GLUE_INFO *)pvCookie; + ASSERT(prGlueInfo); + if (!prGlueInfo) + return -1; + + prHifInfo = &prGlueInfo->rHifInfo; + pdev = prHifInfo->pdev; + + prHifInfo->u4IrqId = AXI_WLAN_IRQ_NUMBER; +#ifdef CONFIG_OF + node = of_find_compatible_node(NULL, NULL, "mediatek,wifi"); + if (node) + prHifInfo->u4IrqId = irq_of_parse_and_map(node, 0); + else + DBGLOG(INIT, ERROR, + "WIFI-OF: get wifi device node fail\n"); +#endif + DBGLOG(INIT, INFO, "glBusSetIrq: request_irq num(%d)\n", + prHifInfo->u4IrqId); + ret = request_irq(prHifInfo->u4IrqId, mtk_axi_interrupt, IRQF_SHARED, + prNetDevice->name, prGlueInfo); + if (ret != 0) + DBGLOG(INIT, INFO, + "glBusSetIrq: request_irq ERROR(%d)\n", ret); + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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(void *pvData, void *pvCookie) +{ + struct net_device *prNetDevice = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct GL_HIF_INFO *prHifInfo = NULL; + struct platform_device *pdev = NULL; + + ASSERT(pvData); + if (!pvData) { + DBGLOG(INIT, INFO, "%s null pvData\n", __func__); + return; + } + prNetDevice = (struct net_device *)pvData; + prGlueInfo = (struct GLUE_INFO *) pvCookie; + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(INIT, INFO, "%s no glue info\n", __func__); + return; + } + + prHifInfo = &prGlueInfo->rHifInfo; + pdev = prHifInfo->pdev; + + synchronize_irq(prHifInfo->u4IrqId); + free_irq(prHifInfo->u4IrqId, prGlueInfo); +} + +u_int8_t glIsReadClearReg(uint32_t u4Address) +{ + return TRUE; +} + +void glSetPowerState(IN struct GLUE_INFO *prGlueInfo, IN uint32_t ePowerMode) +{ +} + +void glGetDev(void *ctx, struct device **dev) +{ + *dev = &((struct platform_device *)ctx)->dev; +} + +void glGetHifDev(struct GL_HIF_INFO *prHif, struct device **dev) +{ + *dev = &(prHif->pdev->dev); +} + +#if AXI_CFG_PREALLOC_MEMORY_BUFFER +static void axiAllocTxDesc(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing, + uint32_t u4Num) +{ + prDescRing->AllocVa = grMem.rTxDesc[u4Num].va; + prDescRing->AllocPa = grMem.rTxDesc[u4Num].pa; + memset_io(prDescRing->AllocVa, 0, prDescRing->AllocSize); +} + +static void axiAllocRxDesc(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing, + uint32_t u4Num) +{ + prDescRing->AllocVa = grMem.rRxDesc[u4Num].va; + prDescRing->AllocPa = grMem.rRxDesc[u4Num].pa; + memset_io(prDescRing->AllocVa, 0, prDescRing->AllocSize); +} + +static void axiAllocTxCmdBuf(struct RTMP_DMABUF *prDmaBuf, + uint32_t u4Num, uint32_t u4Idx) +{ + /* only for cmd & fw download ring */ + if (u4Num == 2 || u4Num == 3) { + prDmaBuf->AllocSize = AXI_TX_CMD_BUFF_SIZE; + prDmaBuf->AllocPa = grMem.rTxCmdBuf[u4Idx].pa; + prDmaBuf->AllocVa = grMem.rTxCmdBuf[u4Idx].va; + memset_io(prDmaBuf->AllocVa, 0, prDmaBuf->AllocSize); + } +} + +static void axiAllocTxDataBuf(struct MSDU_TOKEN_ENTRY *prToken, uint32_t u4Idx) +{ + prToken->prPacket = grMem.rMsduBuf[u4Idx].va; + prToken->rDmaAddr = grMem.rMsduBuf[u4Idx].pa; +} + +static void *axiAllocRxBuf(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDmaBuf, + uint32_t u4Num, uint32_t u4Idx) +{ + /* ring 0 for data, ring 1 for event */ + if (u4Num == 0) { + prDmaBuf->AllocPa = grMem.rRxDataBuf[u4Idx].pa; + prDmaBuf->AllocVa = grMem.rRxDataBuf[u4Idx].va; + } else { + prDmaBuf->AllocPa = grMem.rRxEventBuf[u4Idx].pa; + prDmaBuf->AllocVa = grMem.rRxEventBuf[u4Idx].va; + } + memset_io(prDmaBuf->AllocVa, 0, prDmaBuf->AllocSize); + + return prDmaBuf->AllocVa; +} + +static bool axiCopyCmd(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *prTxCell, void *pucBuf, + void *pucSrc1, uint32_t u4SrcLen1, + void *pucSrc2, uint32_t u4SrcLen2) +{ + struct RTMP_DMABUF *prDmaBuf = &prTxCell->DmaBuf; + + memcpy_toio(prDmaBuf->AllocVa, pucSrc1, u4SrcLen1); + if (pucSrc2 != NULL && u4SrcLen2 > 0) + memcpy_toio(prDmaBuf->AllocVa + u4SrcLen1, pucSrc2, u4SrcLen2); + prTxCell->PacketPa = prDmaBuf->AllocPa; + + return true; +} + +static bool axiCopyEvent(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *pRxCell, + struct RXD_STRUCT *pRxD, + struct RTMP_DMABUF *prDmaBuf, + uint8_t *pucDst, uint32_t u4Len) +{ + memcpy_fromio(pucDst, prDmaBuf->AllocVa, u4Len); + + return true; +} + +static bool axiCopyTxData(struct MSDU_TOKEN_ENTRY *prToken, + void *pucSrc, uint32_t u4Len) +{ + memcpy(prToken->prPacket, pucSrc, u4Len); + + return true; +} + +static bool axiCopyRxData(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *pRxCell, + struct RTMP_DMABUF *prDmaBuf, + struct SW_RFB *prSwRfb) +{ + struct RXD_STRUCT *pRxD = (struct RXD_STRUCT *)pRxCell->AllocVa; + struct sk_buff *prSkb = ((struct sk_buff *)prSwRfb->pvPacket); + uint32_t u4Size = pRxD->SDLen0; + + if (u4Size > CFG_RX_MAX_PKT_SIZE) { + DBGLOG(RX, ERROR, "Rx Data too large[%u]\n", u4Size); + return false; + } + + memcpy(prSkb->data, prDmaBuf->AllocVa, u4Size); + + return true; +} + + +static void axiflushCache(struct GL_HIF_INFO *prHifInfo, + void *pucSrc, uint32_t u4Len) +{ +#if CFG_MTK_ANDROID_WMT + connectivity_flush_dcache_area(pucSrc, u4Len); +#endif +} + +static void axiDumpTx(struct GL_HIF_INFO *prHifInfo, + struct RTMP_TX_RING *prTxRing, + uint32_t u4Idx, uint32_t u4DumpLen) +{ + struct RTMP_DMACB *prTxCell; + struct RTMP_DMABUF *prDmaBuf; + void *prAddr = NULL; + + prTxCell = &prTxRing->Cell[u4Idx]; + prDmaBuf = &prTxCell->DmaBuf; + + if (prTxCell->prToken) + prAddr = prTxCell->prToken->prPacket; + else if (prDmaBuf->AllocVa) + prAddr = prDmaBuf->AllocVa; + + if (prAddr) + DBGLOG_MEM32(HAL, INFO, prAddr, u4DumpLen); +} + +static void axiDumpRx(struct GL_HIF_INFO *prHifInfo, + struct RTMP_RX_RING *prRxRing, + uint32_t u4Idx, uint32_t u4DumpLen) +{ + struct RTMP_DMACB *prRxCell; + struct RTMP_DMABUF *prDmaBuf; + + prRxCell = &prRxRing->Cell[u4Idx]; + prDmaBuf = &prRxCell->DmaBuf; + + if (prRxCell->pPacket) { + axiflushCache(prHifInfo, prRxCell->pPacket, u4DumpLen); + DBGLOG_MEM32(HAL, INFO, prRxCell->pPacket, u4DumpLen); + } +} +#else /* AXI_CFG_PREALLOC_MEMORY_BUFFER */ +static void axiAllocDesc(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing, + uint32_t u4Num) +{ + dma_addr_t rAddr; + + prDescRing->AllocVa = (void *)KAL_DMA_ALLOC_COHERENT( + prHifInfo->prDmaDev, prDescRing->AllocSize, &rAddr); + prDescRing->AllocPa = (phys_addr_t)rAddr; + if (prDescRing->AllocVa) + memset(prDescRing->AllocVa, 0, prDescRing->AllocSize); +} + +static void *axiAllocRxBuf(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDmaBuf, + uint32_t u4Num, uint32_t u4Idx) +{ + struct sk_buff *pkt = dev_alloc_skb(prDmaBuf->AllocSize); + dma_addr_t rAddr; + + if (!pkt) { + DBGLOG(HAL, ERROR, "can't allocate rx %u size packet\n", + prDmaBuf->AllocSize); + prDmaBuf->AllocPa = 0; + prDmaBuf->AllocVa = NULL; + return NULL; + } + + prDmaBuf->AllocVa = (void *)pkt->data; + memset(prDmaBuf->AllocVa, 0, prDmaBuf->AllocSize); + + rAddr = KAL_DMA_MAP_SINGLE(prHifInfo->prDmaDev, prDmaBuf->AllocVa, + prDmaBuf->AllocSize, KAL_DMA_FROM_DEVICE); + if (KAL_DMA_MAPPING_ERROR(prHifInfo->prDmaDev, rAddr)) { + DBGLOG(HAL, ERROR, "sk_buff dma mapping error!\n"); + dev_kfree_skb(pkt); + return NULL; + } + prDmaBuf->AllocPa = (phys_addr_t)rAddr; + return (void *)pkt; +} + +static void axiAllocTxDataBuf(struct MSDU_TOKEN_ENTRY *prToken, uint32_t u4Idx) +{ + prToken->prPacket = kalMemAlloc(prToken->u4DmaLength, PHY_MEM_TYPE); + prToken->rDmaAddr = 0; +} + +static void *axiAllocRuntimeMem(uint32_t u4SrcLen) +{ + return kalMemAlloc(u4SrcLen, PHY_MEM_TYPE); +} + +static bool axiCopyCmd(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *prTxCell, void *pucBuf, + void *pucSrc1, uint32_t u4SrcLen1, + void *pucSrc2, uint32_t u4SrcLen2) +{ + dma_addr_t rAddr; + uint32_t u4TotalLen = u4SrcLen1 + u4SrcLen2; + + prTxCell->pBuffer = pucBuf; + + memcpy(pucBuf, pucSrc1, u4SrcLen1); + if (pucSrc2 != NULL && u4SrcLen2 > 0) + memcpy(pucBuf + u4SrcLen1, pucSrc2, u4SrcLen2); + rAddr = KAL_DMA_MAP_SINGLE(prHifInfo->prDmaDev, pucBuf, + u4TotalLen, KAL_DMA_TO_DEVICE); + if (KAL_DMA_MAPPING_ERROR(prHifInfo->prDmaDev, rAddr)) { + DBGLOG(HAL, ERROR, "KAL_DMA_MAP_SINGLE() error!\n"); + return false; + } + + prTxCell->PacketPa = (phys_addr_t)rAddr; + + return true; +} + +static bool axiCopyEvent(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *pRxCell, + struct RXD_STRUCT *pRxD, + struct RTMP_DMABUF *prDmaBuf, + uint8_t *pucDst, uint32_t u4Len) +{ + struct sk_buff *prSkb = NULL; + void *pRxPacket = NULL; + dma_addr_t rAddr; + + KAL_DMA_UNMAP_SINGLE(prHifInfo->prDmaDev, + (dma_addr_t)prDmaBuf->AllocPa, + prDmaBuf->AllocSize, KAL_DMA_FROM_DEVICE); + + pRxPacket = pRxCell->pPacket; + ASSERT(pRxPacket); + + prSkb = (struct sk_buff *)pRxPacket; + memcpy(pucDst, (uint8_t *)prSkb->data, u4Len); + + prDmaBuf->AllocVa = ((struct sk_buff *)pRxCell->pPacket)->data; + rAddr = KAL_DMA_MAP_SINGLE(prHifInfo->prDmaDev, prDmaBuf->AllocVa, + prDmaBuf->AllocSize, KAL_DMA_FROM_DEVICE); + if (KAL_DMA_MAPPING_ERROR(prHifInfo->prDmaDev, rAddr)) { + DBGLOG(HAL, ERROR, "KAL_DMA_MAP_SINGLE() error!\n"); + return false; + } + prDmaBuf->AllocPa = (phys_addr_t)rAddr; + return true; +} + +static bool axiCopyTxData(struct MSDU_TOKEN_ENTRY *prToken, + void *pucSrc, uint32_t u4Len) +{ + memcpy(prToken->prPacket, pucSrc, u4Len); + return true; +} + +static bool axiCopyRxData(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *pRxCell, + struct RTMP_DMABUF *prDmaBuf, + struct SW_RFB *prSwRfb) +{ + void *pRxPacket = NULL; + dma_addr_t rAddr; + + pRxPacket = pRxCell->pPacket; + ASSERT(pRxPacket); + + pRxCell->pPacket = prSwRfb->pvPacket; + + KAL_DMA_UNMAP_SINGLE(prHifInfo->prDmaDev, + (dma_addr_t)prDmaBuf->AllocPa, + prDmaBuf->AllocSize, KAL_DMA_FROM_DEVICE); + prSwRfb->pvPacket = pRxPacket; + + prDmaBuf->AllocVa = ((struct sk_buff *)pRxCell->pPacket)->data; + rAddr = KAL_DMA_MAP_SINGLE(prHifInfo->prDmaDev, + prDmaBuf->AllocVa, prDmaBuf->AllocSize, KAL_DMA_FROM_DEVICE); + if (KAL_DMA_MAPPING_ERROR(prHifInfo->prDmaDev, rAddr)) { + DBGLOG(HAL, ERROR, "KAL_DMA_MAP_SINGLE() error!\n"); + ASSERT(0); + return false; + } + prDmaBuf->AllocPa = (phys_addr_t)rAddr; + + return true; +} + +static phys_addr_t axiMapTxBuf(struct GL_HIF_INFO *prHifInfo, + void *pucBuf, uint32_t u4Offset, uint32_t u4Len) +{ + dma_addr_t rDmaAddr = 0; + + rDmaAddr = KAL_DMA_MAP_SINGLE(prHifInfo->prDmaDev, pucBuf + u4Offset, + u4Len, KAL_DMA_TO_DEVICE); + if (KAL_DMA_MAPPING_ERROR(prHifInfo->prDmaDev, rDmaAddr)) { + DBGLOG(HAL, ERROR, "KAL_DMA_MAP_SINGLE() error!\n"); + return 0; + } + + return (phys_addr_t)rDmaAddr; +} + +static phys_addr_t axiMapRxBuf(struct GL_HIF_INFO *prHifInfo, + void *pucBuf, uint32_t u4Offset, uint32_t u4Len) +{ + dma_addr_t rDmaAddr = 0; + + rDmaAddr = KAL_DMA_MAP_SINGLE(prHifInfo->prDmaDev, pucBuf + u4Offset, + u4Len, KAL_DMA_FROM_DEVICE); + if (KAL_DMA_MAPPING_ERROR(prHifInfo->prDmaDev, rDmaAddr)) { + DBGLOG(HAL, ERROR, "KAL_DMA_MAP_SINGLE() error!\n"); + return 0; + } + + return (phys_addr_t)rDmaAddr; +} + +static void axiUnmapTxBuf(struct GL_HIF_INFO *prHifInfo, + phys_addr_t rDmaAddr, uint32_t u4Len) +{ + KAL_DMA_UNMAP_SINGLE(prHifInfo->prDmaDev, + (dma_addr_t)rDmaAddr, + u4Len, KAL_DMA_TO_DEVICE); +} + +static void axiUnmapRxBuf(struct GL_HIF_INFO *prHifInfo, + phys_addr_t rDmaAddr, uint32_t u4Len) +{ + KAL_DMA_UNMAP_SINGLE(prHifInfo->prDmaDev, + (dma_addr_t)rDmaAddr, + u4Len, KAL_DMA_FROM_DEVICE); +} + +static void axiFreeDesc(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing) +{ + if (prDescRing->AllocVa == NULL) + return; + + KAL_DMA_FREE_COHERENT(prHifInfo->prDmaDev, + prDescRing->AllocSize, + prDescRing->AllocVa, + (dma_addr_t)prDescRing->AllocPa); + memset(prDescRing, 0, sizeof(struct RTMP_DMABUF)); +} + +static void axiFreeBuf(void *pucSrc, uint32_t u4Len) +{ + kalMemFree(pucSrc, PHY_MEM_TYPE, u4Len); +} + +static void axiFreePacket(void *pvPacket) +{ + kalPacketFree(NULL, pvPacket); +} + +static void axiDumpTx(struct GL_HIF_INFO *prHifInfo, + struct RTMP_TX_RING *prTxRing, + uint32_t u4Idx, uint32_t u4DumpLen) +{ + struct RTMP_DMACB *prTxCell; + void *prAddr = NULL; + + prTxCell = &prTxRing->Cell[u4Idx]; + + if (prTxCell->prToken) + prAddr = prTxCell->prToken->prPacket; + else + prAddr = prTxCell->pBuffer; + + if (prAddr) + DBGLOG_MEM32(HAL, INFO, prAddr, u4DumpLen); +} + +static void axiDumpRx(struct GL_HIF_INFO *prHifInfo, + struct RTMP_RX_RING *prRxRing, + uint32_t u4Idx, uint32_t u4DumpLen) +{ + struct RTMP_DMACB *prRxCell; + struct RTMP_DMABUF *prDmaBuf; + + prRxCell = &prRxRing->Cell[u4Idx]; + prDmaBuf = &prRxCell->DmaBuf; + + if (!prRxCell->pPacket) + return; + + axiUnmapRxBuf(prHifInfo, prDmaBuf->AllocPa, prDmaBuf->AllocSize); + + DBGLOG_MEM32(HAL, INFO, ((struct sk_buff *)prRxCell->pPacket)->data, + u4DumpLen); + + prDmaBuf->AllocPa = axiMapRxBuf(prHifInfo, prDmaBuf->AllocVa, + 0, prDmaBuf->AllocSize); +} +#endif /* AXI_CFG_PREALLOC_MEMORY_BUFFER */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/axi/include/hif.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/axi/include/hif.h new file mode 100644 index 0000000000000..af641379db101 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/axi/include/hif.h @@ -0,0 +1,308 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \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 + */ + +#ifndef _HIF_H +#define _HIF_H + +#include "hif_pdma.h" +#include "connac.h" + +#if defined(_HIF_AXI) +#define HIF_NAME "AXI" +#else +#error "No HIF defined!" +#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 + ******************************************************************************* + */ +#if CFG_MTK_ANDROID_WMT +struct MTK_WCN_WMT_WLAN_CB_INFO; +extern int mtk_wcn_wmt_wlan_reg( + struct MTK_WCN_WMT_WLAN_CB_INFO *pWmtWlanCbInfo); +extern int mtk_wcn_wmt_wlan_unreg(void); +#endif + +extern phys_addr_t gWifiRsvMemPhyBase; +extern unsigned long long gWifiRsvMemSize; + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define AXI_CFG_PREALLOC_MEMORY_BUFFER 1 + +#define AXI_TX_MAX_SIZE_PER_FRAME (NIC_TX_MAX_SIZE_PER_FRAME + \ + NIC_TX_DESC_AND_PADDING_LENGTH + \ + CONNAC_TX_DESC_APPEND_LENGTH) + +#define AXI_TX_CMD_BUFF_SIZE 4096 +#define AXI_WLAN_IRQ_NUMBER 16 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +struct GL_HIF_INFO; + +struct HIF_MEM_OPS { + void (*allocTxDesc)(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing, + uint32_t u4Num); + void (*allocRxDesc)(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing, + uint32_t u4Num); + void (*allocTxCmdBuf)(struct RTMP_DMABUF *prDmaBuf, + uint32_t u4Num, uint32_t u4Idx); + void (*allocTxDataBuf)(struct MSDU_TOKEN_ENTRY *prToken, + uint32_t u4Idx); + void *(*allocRxBuf)(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDmaBuf, + uint32_t u4Num, uint32_t u4Idx); + void *(*allocRuntimeMem)(uint32_t u4SrcLen); + bool (*copyCmd)(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *prTxCell, void *pucBuf, + void *pucSrc1, uint32_t u4SrcLen1, + void *pucSrc2, uint32_t u4SrcLen2); + bool (*copyEvent)(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *pRxCell, + struct RXD_STRUCT *pRxD, + struct RTMP_DMABUF *prDmaBuf, + uint8_t *pucDst, uint32_t u4Len); + bool (*copyTxData)(struct MSDU_TOKEN_ENTRY *prToken, + void *pucSrc, uint32_t u4Len); + bool (*copyRxData)(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *pRxCell, + struct RTMP_DMABUF *prDmaBuf, + struct SW_RFB *prSwRfb); + void (*flushCache)(struct GL_HIF_INFO *prHifInfo, + void *pucSrc, uint32_t u4Len); + phys_addr_t (*mapTxBuf)(struct GL_HIF_INFO *prHifInfo, + void *pucBuf, uint32_t u4Offset, uint32_t u4Len); + phys_addr_t (*mapRxBuf)(struct GL_HIF_INFO *prHifInfo, + void *pucBuf, uint32_t u4Offset, uint32_t u4Len); + void (*unmapTxBuf)(struct GL_HIF_INFO *prHifInfo, + phys_addr_t rDmaAddr, uint32_t u4Len); + void (*unmapRxBuf)(struct GL_HIF_INFO *prHifInfo, + phys_addr_t rDmaAddr, uint32_t u4Len); + void (*freeDesc)(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing); + void (*freeBuf)(void *pucSrc, uint32_t u4Len); + void (*freePacket)(void *pvPacket); + void (*dumpTx)(struct GL_HIF_INFO *prHifInfo, + struct RTMP_TX_RING *prTxRing, + uint32_t u4Idx, uint32_t u4DumpLen); + void (*dumpRx)(struct GL_HIF_INFO *prHifInfo, + struct RTMP_RX_RING *prRxRing, + uint32_t u4Idx, uint32_t u4DumpLen); +}; + +/* host interface's private data structure, which is attached to os glue + ** layer info structure. + */ +struct GL_HIF_INFO { + struct platform_device *pdev; + struct device *prDmaDev; + struct HIF_MEM_OPS rMemOps; + + uint32_t u4IrqId; + int32_t u4HifCnt; + + /* AXI MMIO Base Address, all access will use */ + void *CSRBaseAddress; + + /* Shared memory of all 1st pre-allocated + * TxBuf associated with each TXD + */ + /* Shared memory for Tx descriptors */ + struct RTMP_DMABUF TxDescRing[NUM_OF_TX_RING]; + struct RTMP_TX_RING TxRing[NUM_OF_TX_RING]; /* AC0~3 + HCCA */ + + /* Shared memory for RX descriptors */ + struct RTMP_DMABUF RxDescRing[NUM_OF_RX_RING]; + struct RTMP_RX_RING RxRing[NUM_OF_RX_RING]; + + u_int8_t fgIntReadClear; + u_int8_t fgMbxReadClear; + + uint32_t u4IntStatus; + + struct MSDU_TOKEN_INFO rTokenInfo; + + struct ERR_RECOVERY_CTRL_T rErrRecoveryCtl; + u_int8_t fgIsErrRecovery; + struct timer_list rSerTimer; + struct list_head rTxCmdQ; + struct list_head rTxDataQ; + uint32_t u4TxDataQLen; + + bool fgIsPowerOff; + bool fgIsDumpLog; +}; + +struct BUS_INFO { + const unsigned int top_cfg_base; /* TOP_CFG_BASE address */ + const struct PCIE_CHIP_CR_MAPPING *bus2chip; + const unsigned int tx_ring_cmd_idx; + const unsigned int tx_ring_fwdl_idx; + const unsigned int tx_ring_data_idx; + const bool fgCheckDriverOwnInt; + const bool fgInitPCIeInt; + const uint32_t u4DmaMask; + + void (*pdmaSetup)(struct GLUE_INFO *prGlueInfo, u_int8_t enable); + void (*enableInterrupt)(struct ADAPTER *prAdapter); + void (*disableInterrupt)(struct ADAPTER *prAdapter); + void (*lowPowerOwnRead)(struct ADAPTER *prAdapter, u_int8_t *pfgResult); + void (*lowPowerOwnSet)(struct ADAPTER *prAdapter, u_int8_t *pfgResult); + void (*lowPowerOwnClear)(struct ADAPTER *prAdapter, + u_int8_t *pfgResult); + void (*wakeUpWiFi)(struct ADAPTER *prAdapter); + bool (*isValidRegAccess)(struct ADAPTER *prAdapter, + uint32_t u4Register); + void (*getMailboxStatus)(struct ADAPTER *prAdapter, uint32_t *pu4Val); + void (*setDummyReg)(struct GLUE_INFO *prGlueInfo); + void (*checkDummyReg)(struct GLUE_INFO *prGlueInfo); +}; + +struct HIF_MEM { + phys_addr_t pa; + void *va; +}; + +struct HIF_PREALLOC_MEM { + struct HIF_MEM rTxDesc[NUM_OF_TX_RING]; + struct HIF_MEM rRxDesc[NUM_OF_RX_RING]; + struct HIF_MEM rTxCmdBuf[TX_RING_SIZE]; + struct HIF_MEM rRxDataBuf[RX_RING0_SIZE]; + struct HIF_MEM rRxEventBuf[RX_RING1_SIZE]; +#if HIF_TX_PREALLOC_DATA_BUFFER + struct HIF_MEM rMsduBuf[HIF_TX_MSDU_TOKEN_NUM]; +#endif + phys_addr_t pucRsvMemBase; + uint64_t u4RsvMemSize; + uint32_t u4Offset; +}; + +#if CFG_MTK_ANDROID_WMT +struct MTK_WCN_WMT_WLAN_CB_INFO { + int (*wlan_probe_cb)(void); + int (*wlan_remove_cb)(void); + int (*wlan_bus_cnt_get_cb)(void); + int (*wlan_bus_cnt_clr_cb)(void); + int (*wlan_emi_mpu_set_protection_cb)(bool); +}; +#endif + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +#define axi_resource_start(d, v) (0x18000000) +#define axi_resource_len(d, v) (0x100000) +#define axi_name(d) ("AXI-BUS") + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +uint32_t glRegisterBus(probe_card pfProbe, remove_card pfRemove); + +void glUnregisterBus(remove_card pfRemove); + +void glSetHifInfo(struct GLUE_INFO *prGlueInfo, unsigned long ulCookie); + +void glClearHifInfo(struct GLUE_INFO *prGlueInfo); + +u_int8_t glBusInit(void *pvData); + +void glBusRelease(void *pData); + +int32_t glBusSetIrq(void *pvData, void *pfnIsr, void *pvCookie); + +void glBusFreeIrq(void *pvData, void *pvCookie); + +void glSetPowerState(IN struct GLUE_INFO *prGlueInfo, IN uint32_t ePowerMode); + +void glGetDev(void *ctx, struct device **dev); + +void glGetHifDev(struct GL_HIF_INFO *prHif, struct device **dev); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#endif /* _HIF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/common/dbg_pdma.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/common/dbg_pdma.c new file mode 100644 index 0000000000000..d0541b46e1f32 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/common/dbg_pdma.c @@ -0,0 +1,1597 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** + *[File] dbg_pdma.c + *[Version] v1.0 + *[Revision Date] 2015-09-08 + *[Author] + *[Description] + * The program provides PDMA HIF APIs + *[Copyright] + * Copyright (C) 2015 MediaTek Incorporation. All Rights Reserved. + ******************************************************************************/ + +/******************************************************************************* + * C O M P I L E 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 "pse.h" +#include "wf_ple.h" +#include "host_csr.h" +#include "dma_sch.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 halCheckHifState(struct ADAPTER *prAdapter); +static void halDumpHifDebugLog(struct ADAPTER *prAdapter); +static bool halIsTxHang(struct ADAPTER *prAdapter); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +void halPrintHifDbgInfo(IN struct ADAPTER *prAdapter) +{ + halCheckHifState(prAdapter); + halDumpHifDebugLog(prAdapter); +} + +static void halCheckHifState(struct ADAPTER *prAdapter) +{ + if (prAdapter->u4HifChkFlag & HIF_CHK_TX_HANG) { + if (halIsTxHang(prAdapter)) { + DBGLOG(HAL, ERROR, + "Tx timeout, set hif debug info flag\n"); + prAdapter->u4HifDbgFlag |= DEG_HIF_ALL; + } + } + + if (prAdapter->u4HifChkFlag & HIF_DRV_SER) + halSetDrvSer(prAdapter); + + prAdapter->u4HifChkFlag = 0; +} + +static void halDumpHifDebugLog(struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo = NULL; + struct GL_HIF_INFO *prHifInfo = NULL; + uint32_t u4Value = 0; + bool fgIsClkEn = false; + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + /* Only dump all hif log once */ + if (prAdapter->u4HifDbgFlag & DEG_HIF_ALL) { + if (!prAdapter->fgEnHifDbgInfo) { + prAdapter->u4HifDbgFlag = 0; + return; + } + prAdapter->fgEnHifDbgInfo = false; + } + + /* Avoid register checking */ + prHifInfo->fgIsDumpLog = true; + + if (prAdapter->u4HifDbgFlag & (DEG_HIF_ALL | DEG_HIF_HOST_CSR)) + fgIsClkEn = halShowHostCsrInfo(prAdapter); + else { + HAL_MCR_WR(prAdapter, HOST_CSR_DRIVER_OWN_INFO, 0x00030000); + kalUdelay(1); + HAL_MCR_RD(prAdapter, HOST_CSR_DRIVER_OWN_INFO, &u4Value); + + /* check clock is enabled */ + fgIsClkEn = ((u4Value & BIT(17)) != 0) && + ((u4Value & BIT(16)) != 0); + } + + if (!fgIsClkEn) + return; + + if (prAdapter->u4HifDbgFlag & (DEG_HIF_ALL | DEG_HIF_PDMA)) + halShowPdmaInfo(prAdapter); + + if (prAdapter->u4HifDbgFlag & (DEG_HIF_ALL | DEG_HIF_DMASCH)) + halShowDmaschInfo(prAdapter); + + if (prAdapter->u4HifDbgFlag & (DEG_HIF_ALL | DEG_HIF_PSE)) + halShowPseInfo(prAdapter); + + if (prAdapter->u4HifDbgFlag & (DEG_HIF_ALL | DEG_HIF_PLE)) + halShowPleInfo(prAdapter); + + if (prAdapter->u4HifDbgFlag & (DEG_HIF_ALL | DEG_HIF_MAC)) + haldumpMacInfo(prAdapter); + + if (prAdapter->u4HifDbgFlag & (DEG_HIF_ALL | DEG_HIF_PHY)) + haldumpPhyInfo(prAdapter); + + prHifInfo->fgIsDumpLog = false; + prAdapter->u4HifDbgFlag = 0; +} + +static void halDumpTxRing(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port, IN uint32_t u4Idx) +{ + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + struct RTMP_TX_RING *prTxRing; + struct TXD_STRUCT *pTxD; + + if (u2Port >= NUM_OF_TX_RING || u4Idx >= TX_RING_SIZE) { + DBGLOG(HAL, INFO, "Dump fail u2Port[%u] u4Idx[%u]\n", + u2Port, u4Idx); + return; + } + + prTxRing = &prHifInfo->TxRing[u2Port]; + + pTxD = (struct TXD_STRUCT *) prTxRing->Cell[u4Idx].AllocVa; + + log_dbg(SW4, INFO, "TX Ring[%u] Idx[%04u] SDP0[0x%08x] SDL0[%u] LS[%u] B[%u] DDONE[%u] SDP0_EXT[%u]\n", + u2Port, u4Idx, pTxD->SDPtr0, pTxD->SDLen0, pTxD->LastSec0, + pTxD->Burst, pTxD->DMADONE, pTxD->SDPtr0Ext); +} + +uint32_t halDumpHifStatus(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, IN uint32_t u4Max) +{ + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + uint32_t u4Idx, u4DmaIdx, u4CpuIdx, u4MaxCnt; + uint32_t u4Len = 0; + struct RTMP_TX_RING *prTxRing; + struct RTMP_RX_RING *prRxRing; + + LOGBUF(pucBuf, u4Max, u4Len, "\n------------\n"); + + for (u4Idx = 0; u4Idx < NUM_OF_TX_RING; u4Idx++) { + prTxRing = &prHifInfo->TxRing[u4Idx]; + kalDevRegRead(prGlueInfo, prTxRing->hw_cnt_addr, &u4MaxCnt); + kalDevRegRead(prGlueInfo, prTxRing->hw_cidx_addr, &u4CpuIdx); + kalDevRegRead(prGlueInfo, prTxRing->hw_didx_addr, &u4DmaIdx); + + LOGBUF(pucBuf, u4Max, u4Len, + "TX[%u] SZ[%04u] CPU[%04u/%04u] DMA[%04u/%04u] SW_UD[%04u] Used[%u]\n", + u4Idx, u4MaxCnt, prTxRing->TxCpuIdx, + u4CpuIdx, prTxRing->TxDmaIdx, + u4DmaIdx, prTxRing->TxSwUsedIdx, prTxRing->u4UsedCnt); + + if (u4Idx == TX_RING_DATA0_IDX_0) { + halDumpTxRing(prGlueInfo, u4Idx, prTxRing->TxCpuIdx); + halDumpTxRing(prGlueInfo, u4Idx, u4CpuIdx); + halDumpTxRing(prGlueInfo, u4Idx, u4DmaIdx); + halDumpTxRing(prGlueInfo, u4Idx, prTxRing->TxSwUsedIdx); + } + } + + for (u4Idx = 0; u4Idx < NUM_OF_RX_RING; u4Idx++) { + prRxRing = &prHifInfo->RxRing[u4Idx]; + + kalDevRegRead(prGlueInfo, prRxRing->hw_cnt_addr, &u4MaxCnt); + kalDevRegRead(prGlueInfo, prRxRing->hw_cidx_addr, &u4CpuIdx); + kalDevRegRead(prGlueInfo, prRxRing->hw_didx_addr, &u4DmaIdx); + + LOGBUF(pucBuf, u4Max, u4Len, + "RX[%u] SZ[%04u] CPU[%04u/%04u] DMA[%04u/%04u]\n", + u4Idx, u4MaxCnt, prRxRing->RxCpuIdx, u4CpuIdx, + prRxRing->RxDmaIdx, u4DmaIdx); + } + + LOGBUF(pucBuf, u4Max, u4Len, "MSDU Tok: Free[%u] Used[%u]\n", + halGetMsduTokenFreeCnt(prGlueInfo->prAdapter), + prGlueInfo->rHifInfo.rTokenInfo.i4UsedCnt); + LOGBUF(pucBuf, u4Max, u4Len, "Pending QLen Normal[%u] Sec[%u]\n", + prGlueInfo->i4TxPendingFrameNum, + prGlueInfo->i4TxPendingSecurityFrameNum); + + LOGBUF(pucBuf, u4Max, u4Len, "---------------------------------\n\n"); + + return u4Len; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Compare two struct timeval + * + * @param prTs1 a pointer to timeval + * @param prTs2 a pointer to timeval + * + * + * @retval 0 two time value is equal + * @retval 1 prTs1 value > prTs2 value + * @retval -1 prTs1 value < prTs2 value + */ +/*----------------------------------------------------------------------------*/ +int halTimeCompare(struct timeval *prTs1, struct timeval *prTs2) +{ + if (prTs1->tv_sec > prTs2->tv_sec) + return 1; + else if (prTs1->tv_sec < prTs2->tv_sec) + return -1; + /* sec part is equal */ + else if (prTs1->tv_usec > prTs2->tv_usec) + return 1; + else if (prTs1->tv_usec < prTs2->tv_usec) + return -1; + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Checking tx hang + * + * @param prAdapter a pointer to adapter private data structure. + * + * @retval true tx is hang because msdu report too long + */ +/*----------------------------------------------------------------------------*/ +static bool halIsTxHang(struct ADAPTER *prAdapter) +{ + struct MSDU_TOKEN_INFO *prTokenInfo; + struct MSDU_TOKEN_ENTRY *prToken; + struct timeval rNowTs, rTime, rLongest, rTimeout; + uint32_t u4Idx = 0, u4TokenId = 0; + bool fgIsTimeout = false; + + ASSERT(prAdapter); + ASSERT(prAdapter->prGlueInfo); + + prTokenInfo = &prAdapter->prGlueInfo->rHifInfo.rTokenInfo; + + rTimeout.tv_sec = HIF_MSDU_REPORT_DUMP_TIMEOUT; + rTimeout.tv_usec = 0; + rLongest.tv_sec = 0; + rLongest.tv_usec = 0; + do_gettimeofday(&rNowTs); + + for (u4Idx = 0; u4Idx < HIF_TX_MSDU_TOKEN_NUM; u4Idx++) { + prToken = &prTokenInfo->arToken[u4Idx]; + if (!prToken->fgInUsed) + continue; + + /* Ignore now time < token time */ + if (halTimeCompare(&rNowTs, &prToken->rTs) < 0) + continue; + + rTime.tv_sec = rNowTs.tv_sec - prToken->rTs.tv_sec; + rTime.tv_usec = rNowTs.tv_usec; + if (prToken->rTs.tv_usec > rNowTs.tv_usec) { + rTime.tv_sec -= 1; + rTime.tv_usec += SEC_TO_USEC(1); + } + rTime.tv_usec -= prToken->rTs.tv_usec; + + if (halTimeCompare(&rTime, &rTimeout) >= 0) + fgIsTimeout = true; + + /* rTime > rLongest */ + if (halTimeCompare(&rTime, &rLongest) > 0) { + rLongest.tv_sec = rTime.tv_sec; + rLongest.tv_usec = rTime.tv_usec; + u4TokenId = u4Idx; + } + } + + if (fgIsTimeout) { + DBGLOG(HAL, INFO, "TokenId[%u] timeout[sec:%u, usec:%u]\n", + u4TokenId, rLongest.tv_sec, rLongest.tv_usec); + prToken = &prTokenInfo->arToken[u4TokenId]; + if (prToken->prPacket) + DBGLOG_MEM32(HAL, INFO, prToken->prPacket, 64); + } + + /* Return token to free stack */ + rTimeout.tv_sec = HIF_MSDU_REPORT_RETURN_TIMEOUT; + rTimeout.tv_usec = 0; + if (halTimeCompare(&rLongest, &rTimeout) >= 0) + halReturnTimeoutMsduToken(prAdapter); + + return fgIsTimeout; +} + +void kalDumpTxRing(struct GLUE_INFO *prGlueInfo, + struct RTMP_TX_RING *prTxRing, + uint32_t u4Num, bool fgDumpContent) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct HIF_MEM_OPS *prMemOps; + struct RTMP_DMACB *pTxCell; + struct TXD_STRUCT *pTxD; + uint32_t u4DumpLen = 64; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + + if (u4Num >= TX_RING_SIZE) + return; + + pTxCell = &prTxRing->Cell[u4Num]; + pTxD = (struct TXD_STRUCT *) pTxCell->AllocVa; + + if (!pTxD) + return; + + DBGLOG(HAL, INFO, "Tx Dese Num[%u]\n", u4Num); + DBGLOG_MEM32(HAL, INFO, pTxD, sizeof(struct TXD_STRUCT)); + + if (!fgDumpContent) + return; + + DBGLOG(HAL, INFO, "Tx Contents\n"); + if (prMemOps->dumpTx) + prMemOps->dumpTx(prHifInfo, prTxRing, u4Num, u4DumpLen); + DBGLOG(HAL, INFO, "\n\n"); +} + +void kalDumpRxRing(struct GLUE_INFO *prGlueInfo, + struct RTMP_RX_RING *prRxRing, + uint32_t u4Num, bool fgDumpContent) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct HIF_MEM_OPS *prMemOps; + struct RTMP_DMACB *pRxCell; + struct RXD_STRUCT *pRxD; + uint32_t u4DumpLen = 64; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + + if (u4Num >= prRxRing->u4RingSize) + return; + + pRxCell = &prRxRing->Cell[u4Num]; + pRxD = (struct RXD_STRUCT *) pRxCell->AllocVa; + + if (!pRxD) + return; + + DBGLOG(HAL, INFO, "Rx Dese Num[%u]\n", u4Num); + DBGLOG_MEM32(HAL, INFO, pRxD, sizeof(struct RXD_STRUCT)); + + if (!fgDumpContent) + return; + + if (u4DumpLen > pRxD->SDLen0) + u4DumpLen = pRxD->SDLen0; + + DBGLOG(HAL, INFO, "Rx Contents\n"); + if (prMemOps->dumpRx) + prMemOps->dumpRx(prHifInfo, prRxRing, u4Num, u4DumpLen); + DBGLOG(HAL, INFO, "\n\n"); +} + +void halShowPdmaInfo(IN struct ADAPTER *prAdapter) +{ + uint32_t i = 0, u4Value = 0; + uint32_t Base[6], Base_Ext[6], Cnt[6], Cidx[6], Didx[6]; + uint32_t offset, offset_ext, SwIdx; + char buf[100] = {0}; + struct GL_HIF_INFO *prHifInfo = NULL; + struct BUS_INFO *prBus_info; + struct RTMP_TX_RING *prTxRing; + struct RTMP_RX_RING *prRxRing; + + /* PDMA HOST_INT */ + HAL_MCR_RD(prAdapter, WPDMA_INT_STA, &u4Value); + DBGLOG(HAL, INFO, "WPDMA HOST_INT:0x%08x = 0x%08x\n", + WPDMA_INT_STA, u4Value); + + /* PDMA GLOBAL_CFG */ + HAL_MCR_RD(prAdapter, WPDMA_GLO_CFG, &u4Value); + DBGLOG(HAL, INFO, "WPDMA GLOBAL_CFG:0x%08x = 0x%08x\n", + WPDMA_GLO_CFG, u4Value); + + HAL_MCR_RD(prAdapter, CONN_HIF_RST, &u4Value); + DBGLOG(HAL, INFO, "WPDMA CONN_HIF_RST:0x%08x = 0x%08x\n", + CONN_HIF_RST, u4Value); + + HAL_MCR_RD(prAdapter, MCU2HOST_SW_INT_STA, &u4Value); + DBGLOG(HAL, INFO, "WPDMA MCU2HOST_SW_INT_STA:0x%08x = 0x%08x\n", + MCU2HOST_SW_INT_STA, u4Value); + + /* PDMA Tx/Rx Ring Info */ + prBus_info = prAdapter->chip_info->bus_info; + DBGLOG(HAL, INFO, "Tx Ring configuration\n"); + DBGLOG(HAL, INFO, "%10s%12s%18s%10s%10s%10s\n", + "Tx Ring", "Reg", "Base", "Cnt", "CIDX", "DIDX"); + + for (i = 0; i < 3; i++) { + if (i == 0) { + offset = prBus_info->tx_ring_data_idx * MT_RINGREG_DIFF; + offset_ext = prBus_info->tx_ring_data_idx * + MT_RINGREG_EXT_DIFF; + } else if (i == 1) { + offset = prBus_info->tx_ring_fwdl_idx * MT_RINGREG_DIFF; + offset_ext = prBus_info->tx_ring_fwdl_idx * + MT_RINGREG_EXT_DIFF; + } else { + offset = prBus_info->tx_ring_cmd_idx * MT_RINGREG_DIFF; + offset_ext = prBus_info->tx_ring_cmd_idx * + MT_RINGREG_EXT_DIFF; + } + + HAL_MCR_RD(prAdapter, WPDMA_TX_RING0_CTRL0 + offset, &Base[i]); + HAL_MCR_RD(prAdapter, WPDMA_TX_RING0_BASE_PTR_EXT + offset_ext, + &Base_Ext[i]); + HAL_MCR_RD(prAdapter, WPDMA_TX_RING0_CTRL1 + offset, &Cnt[i]); + HAL_MCR_RD(prAdapter, WPDMA_TX_RING0_CTRL2 + offset, &Cidx[i]); + HAL_MCR_RD(prAdapter, WPDMA_TX_RING0_CTRL3 + offset, &Didx[i]); + + kalSprintf(buf, "%10d 0x%08x 0x%016llx%10d%10d%10d", + offset/MT_RINGREG_DIFF, WPDMA_TX_RING0_CTRL0 + offset, + (Base[i] + ((uint64_t) Base_Ext[i] << 32)), + Cnt[i], Cidx[i], Didx[i]); + DBGLOG(HAL, INFO, "%s\n", buf); + } + + DBGLOG(HAL, INFO, "Rx Ring configuration\n"); + DBGLOG(HAL, INFO, "%10s%12s%18s%10s%10s%10s\n", + "Rx Ring", "Reg", "Base", "Cnt", "CIDX", "DIDX"); + HAL_MCR_RD(prAdapter, WPDMA_RX_RING0_CTRL0, &Base[3]); + HAL_MCR_RD(prAdapter, WPDMA_RX_RING0_BASE_PTR_EXT, &Base_Ext[3]); + HAL_MCR_RD(prAdapter, WPDMA_RX_RING0_CTRL1, &Cnt[3]); + HAL_MCR_RD(prAdapter, WPDMA_RX_RING0_CTRL2, &Cidx[3]); + HAL_MCR_RD(prAdapter, WPDMA_RX_RING0_CTRL3, &Didx[3]); + kalSprintf(buf, "%10d 0x%08x 0x%016llx%10d%10d%10d", + 0, WPDMA_RX_RING0_CTRL0, + (Base[3] + ((uint64_t)Base_Ext[3] << 32)), + Cnt[3], Cidx[3], Didx[3]); + DBGLOG(HAL, INFO, "%s\n", buf); + + HAL_MCR_RD(prAdapter, WPDMA_RX_RING0_CTRL0 + MT_RINGREG_DIFF, &Base[4]); + HAL_MCR_RD(prAdapter, WPDMA_RX_RING0_BASE_PTR_EXT + MT_RINGREG_EXT_DIFF, + &Base_Ext[4]); + HAL_MCR_RD(prAdapter, WPDMA_RX_RING0_CTRL1 + MT_RINGREG_DIFF, &Cnt[4]); + HAL_MCR_RD(prAdapter, WPDMA_RX_RING0_CTRL2 + MT_RINGREG_DIFF, &Cidx[4]); + HAL_MCR_RD(prAdapter, WPDMA_RX_RING0_CTRL3 + MT_RINGREG_DIFF, &Didx[4]); + kalSprintf(buf, "%10d 0x%08x 0x%016llx%10d%10d%10d", + 1, WPDMA_RX_RING0_CTRL0 + MT_RINGREG_DIFF, + (Base[4] + ((uint64_t)Base_Ext[4] << 32)), + Cnt[4], Cidx[4], Didx[4]); + DBGLOG(HAL, INFO, "%s\n", buf); + + /* PDMA Tx/Rx descriptor & packet content */ + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + for (i = 0; i < 3; i++) { + DBGLOG(HAL, INFO, "Dump PDMA Tx Ring[%u]\n", i); + prTxRing = &prHifInfo->TxRing[i]; + SwIdx = Didx[i]; + kalDumpTxRing(prAdapter->prGlueInfo, prTxRing, + SwIdx, true); + SwIdx = Didx[i] == 0 ? Cnt[i] - 1 : Didx[i] - 1; + kalDumpTxRing(prAdapter->prGlueInfo, prTxRing, + SwIdx, true); + } + + for (i = 0; i < 2; i++) { + DBGLOG(HAL, INFO, "Dump PDMA Rx Ring[%u]\n", i); + prRxRing = &prHifInfo->RxRing[i]; + SwIdx = Didx[i+3]; + kalDumpRxRing(prAdapter->prGlueInfo, prRxRing, + SwIdx, true); + SwIdx = Didx[i+3] == 0 ? Cnt[i+3] - 1 : Didx[i+3] - 1; + kalDumpRxRing(prAdapter->prGlueInfo, prRxRing, + SwIdx, true); + } + + /* PDMA Busy Status */ + HAL_MCR_RD(prAdapter, PDMA_DEBUG_BUSY_STATUS, &u4Value); + DBGLOG(HAL, INFO, "PDMA busy status:0x%08x = 0x%08x\n", + PDMA_DEBUG_STATUS, u4Value); + HAL_MCR_RD(prAdapter, PDMA_DEBUG_HIF_BUSY_STATUS, &u4Value); + DBGLOG(HAL, INFO, "CONN_HIF busy status:0x%08x = 0x%08x\n\n", + PDMA_DEBUG_HIF_BUSY_STATUS, u4Value); + + /* PDMA Debug Flag Info */ + DBGLOG(HAL, INFO, "PDMA core dbg"); + for (i = 0; i < 24; i++) { + u4Value = 256 + i; + HAL_MCR_WR(prAdapter, PDMA_DEBUG_EN, u4Value); + HAL_MCR_RD(prAdapter, PDMA_DEBUG_STATUS, &u4Value); + DBGLOG(HAL, INFO, "Set:0x%02x, result = 0x%08x\n", i, u4Value); + mdelay(1); + } + + /* AXI Debug Flag */ + HAL_MCR_WR(prAdapter, AXI_DEBUG_DEBUG_EN, PDMA_AXI_DEBUG_FLAG); + HAL_MCR_RD(prAdapter, CONN_HIF_DEBUG_STATUS, &u4Value); + DBGLOG(HAL, INFO, "Set:0x%04x, pdma axi dbg:0x%08x", + PDMA_AXI_DEBUG_FLAG, u4Value); + + HAL_MCR_WR(prAdapter, AXI_DEBUG_DEBUG_EN, GALS_AXI_DEBUG_FLAG); + HAL_MCR_RD(prAdapter, CONN_HIF_DEBUG_STATUS, &u4Value); + DBGLOG(HAL, INFO, "Set:0x%04x, gals axi dbg:0x%08x", + GALS_AXI_DEBUG_FLAG, u4Value); + + HAL_MCR_WR(prAdapter, AXI_DEBUG_DEBUG_EN, MCU_AXI_DEBUG_FLAG); + HAL_MCR_RD(prAdapter, CONN_HIF_DEBUG_STATUS, &u4Value); + DBGLOG(HAL, INFO, "Set:0x%04x, mcu axi dbg:0x%08x", + MCU_AXI_DEBUG_FLAG, u4Value); + + /* Rbus Bridge Debug Flag */ + DBGLOG(HAL, INFO, "rbus dbg"); + HAL_MCR_WR(prAdapter, PDMA_DEBUG_EN, RBUS_DEBUG_FLAG); + for (i = 0; i < 9; i++) { + u4Value = i << 16; + HAL_MCR_WR(prAdapter, AXI_DEBUG_DEBUG_EN, u4Value); + HAL_MCR_RD(prAdapter, PDMA_DEBUG_STATUS, &u4Value); + DBGLOG(HAL, INFO, "Set[19:16]:0x%02x, result = 0x%08x\n", + i, u4Value); + } +} + +void halShowPseInfo(IN struct ADAPTER *prAdapter) +{ + uint32_t pse_buf_ctrl, pg_sz, pg_num; + uint32_t pse_stat, pg_flow_ctrl[16] = {0}; + uint32_t fpg_cnt, ffa_cnt, fpg_head, fpg_tail; + uint32_t max_q, min_q, rsv_pg, used_pg; + uint32_t i, page_offset, addr, value; + + HAL_MCR_RD(prAdapter, PSE_PBUF_CTRL, &pse_buf_ctrl); + HAL_MCR_RD(prAdapter, PSE_QUEUE_EMPTY, &pse_stat); + HAL_MCR_RD(prAdapter, PSE_FREEPG_CNT, &pg_flow_ctrl[0]); + HAL_MCR_RD(prAdapter, PSE_FREEPG_HEAD_TAIL, &pg_flow_ctrl[1]); + HAL_MCR_RD(prAdapter, PSE_PG_HIF0_GROUP, &pg_flow_ctrl[2]); + HAL_MCR_RD(prAdapter, PSE_HIF0_PG_INFO, &pg_flow_ctrl[3]); + HAL_MCR_RD(prAdapter, PSE_PG_HIF1_GROUP, &pg_flow_ctrl[4]); + HAL_MCR_RD(prAdapter, PSE_HIF1_PG_INFO, &pg_flow_ctrl[5]); + HAL_MCR_RD(prAdapter, PSE_PG_CPU_GROUP, &pg_flow_ctrl[6]); + HAL_MCR_RD(prAdapter, PSE_CPU_PG_INFO, &pg_flow_ctrl[7]); + HAL_MCR_RD(prAdapter, PSE_PG_LMAC0_GROUP, &pg_flow_ctrl[8]); + HAL_MCR_RD(prAdapter, PSE_LMAC0_PG_INFO, &pg_flow_ctrl[9]); + HAL_MCR_RD(prAdapter, PSE_PG_LMAC1_GROUP, &pg_flow_ctrl[10]); + HAL_MCR_RD(prAdapter, PSE_LMAC1_PG_INFO, &pg_flow_ctrl[11]); + HAL_MCR_RD(prAdapter, PSE_PG_LMAC2_GROUP, &pg_flow_ctrl[12]); + HAL_MCR_RD(prAdapter, PSE_LMAC2_PG_INFO, &pg_flow_ctrl[13]); + HAL_MCR_RD(prAdapter, PSE_PG_PLE_GROUP, &pg_flow_ctrl[14]); + HAL_MCR_RD(prAdapter, PSE_PLE_PG_INFO, &pg_flow_ctrl[15]); + + /* Configuration Info */ + DBGLOG(HAL, INFO, "PSE Configuration Info:\n"); + + HAL_MCR_RD(prAdapter, PSE_GC, &value); + DBGLOG(HAL, INFO, "\tGC(0x82068000): 0x%08x\n", value); + HAL_MCR_RD(prAdapter, PSE_INT_STS, &value); + DBGLOG(HAL, INFO, "\tINT_STS(0x82068024): 0x%08x\n", value); + HAL_MCR_RD(prAdapter, PSE_INT_ERR_STS, &value); + DBGLOG(HAL, INFO, "\tINT_ERR_STS(0x82068028): 0x%08x\n", value); + + DBGLOG(HAL, INFO, "\tPacket Buffer Control(0x82068014): 0x%08x\n", + pse_buf_ctrl); + pg_sz = (pse_buf_ctrl & (0x1 << 31)) >> 31; + DBGLOG(HAL, INFO, + "\t\tPage Size=%d(%d bytes per page)\n", + pg_sz, (pg_sz == 1 ? 256 : 128)); + page_offset = (pse_buf_ctrl & 0x3FFFFFF) >> 17; + DBGLOG(HAL, INFO, + "\t\tPage Offset=%d(in unit of 2KB)\n", page_offset); + pg_num = (pse_buf_ctrl & PSE_TOTAL_PAGE_NUM_MASK); + DBGLOG(HAL, INFO, "\t\tAvailable Total Page=%d pages\n", pg_num); + /* Page Flow Control */ + DBGLOG(HAL, INFO, "PSE Page Flow Control:\n"); + + DBGLOG(HAL, INFO, + "\tFree page counter(0x82068100): 0x%08x\n", pg_flow_ctrl[0]); + fpg_cnt = pg_flow_ctrl[0] & 0xfff; + DBGLOG(HAL, INFO, + "\t\tThe toal page number of free=0x%03x\n", fpg_cnt); + ffa_cnt = (pg_flow_ctrl[0] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe free page numbers of free for all=0x%03x\n", ffa_cnt); + DBGLOG(HAL, INFO, + "\tFree page head and tail(0x82068104): 0x%08x\n", + pg_flow_ctrl[1]); + fpg_head = pg_flow_ctrl[1] & 0xfff; + fpg_tail = (pg_flow_ctrl[1] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe tail/head page of free page list=0x%03x/0x%03x\n", + fpg_tail, fpg_head); + DBGLOG(HAL, INFO, + "\tReserved page counter of HIF0 group(0x82068110): 0x%08x\n", + pg_flow_ctrl[2]); + DBGLOG(HAL, INFO, + "\tHIF0 group page status(0x82068114): 0x%08x\n", + pg_flow_ctrl[3]); + min_q = pg_flow_ctrl[2] & 0xfff; + max_q = (pg_flow_ctrl[2] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of HIF0 group=0x%03x/0x%03x\n", + max_q, min_q); + rsv_pg = pg_flow_ctrl[3] & 0xfff; + used_pg = (pg_flow_ctrl[3] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of HIF0 group=0x%03x/0x%03x\n", + used_pg, rsv_pg); + DBGLOG(HAL, INFO, + "\tReserved page counter of HIF1 group(0x82068118): 0x%08x\n", + pg_flow_ctrl[4]); + DBGLOG(HAL, INFO, + "\tHIF1 group page status(0x8206811c): 0x%08x\n", + pg_flow_ctrl[5]); + min_q = pg_flow_ctrl[4] & 0xfff; + max_q = (pg_flow_ctrl[4] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of HIF1 group=0x%03x/0x%03x\n", + max_q, min_q); + rsv_pg = pg_flow_ctrl[5] & 0xfff; + used_pg = (pg_flow_ctrl[5] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of HIF1 group=0x%03x/0x%03x\n", + used_pg, rsv_pg); + DBGLOG(HAL, INFO, + "\tReserved page counter of CPU group(0x82068150): 0x%08x\n", + pg_flow_ctrl[6]); + DBGLOG(HAL, INFO, + "\tCPU group page status(0x82068154): 0x%08x\n", + pg_flow_ctrl[7]); + min_q = pg_flow_ctrl[6] & 0xfff; + max_q = (pg_flow_ctrl[6] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of CPU group=0x%03x/0x%03x\n", + max_q, min_q); + rsv_pg = pg_flow_ctrl[7] & 0xfff; + used_pg = (pg_flow_ctrl[7] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of CPU group=0x%03x/0x%03x\n", + used_pg, rsv_pg); + DBGLOG(HAL, INFO, + "\tReserved page counter of LMAC0 group(0x82068170): 0x%08x\n", + pg_flow_ctrl[8]); + DBGLOG(HAL, INFO, + "\tLMAC0 group page status(0x82068174): 0x%08x\n", + pg_flow_ctrl[9]); + min_q = pg_flow_ctrl[8] & 0xfff; + max_q = (pg_flow_ctrl[8] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of LMAC0 group=0x%03x/0x%03x\n", + max_q, min_q); + rsv_pg = pg_flow_ctrl[9] & 0xfff; + used_pg = (pg_flow_ctrl[9] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of LMAC0 group=0x%03x/0x%03x\n", + used_pg, rsv_pg); + DBGLOG(HAL, INFO, + "\tReserved page counter of LMAC1 group(0x82068178): 0x%08x\n", + pg_flow_ctrl[10]); + DBGLOG(HAL, INFO, + "\tLMAC1 group page status(0x8206817c): 0x%08x\n", + pg_flow_ctrl[11]); + min_q = pg_flow_ctrl[10] & 0xfff; + max_q = (pg_flow_ctrl[10] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of LMAC1 group=0x%03x/0x%03x\n", + max_q, min_q); + rsv_pg = pg_flow_ctrl[11] & 0xfff; + used_pg = (pg_flow_ctrl[11] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of LMAC1 group=0x%03x/0x%03x\n", + used_pg, rsv_pg); + DBGLOG(HAL, INFO, + "\tReserved page counter of LMAC2 group(0x82068180): 0x%08x\n", + pg_flow_ctrl[12]); + DBGLOG(HAL, INFO, + "\tLMAC2 group page status(0x82068184): 0x%08x\n", + pg_flow_ctrl[13]); + min_q = pg_flow_ctrl[12] & 0xfff; + max_q = (pg_flow_ctrl[12] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of LMAC2 group=0x%03x/0x%03x\n", + max_q, min_q); + rsv_pg = pg_flow_ctrl[13] & 0xfff; + used_pg = (pg_flow_ctrl[13] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of LMAC2 group=0x%03x/0x%03x\n", + used_pg, rsv_pg); + DBGLOG(HAL, INFO, + "\tReserved page counter of PLE group(0x82068190): 0x%08x\n", + pg_flow_ctrl[14]); + DBGLOG(HAL, INFO, + "\tPLE group page status(0x82068194): 0x%08x\n", + pg_flow_ctrl[15]); + min_q = pg_flow_ctrl[14] & 0xfff; + max_q = (pg_flow_ctrl[14] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of PLE group=0x%03x/0x%03x\n", + max_q, min_q); + rsv_pg = pg_flow_ctrl[15] & 0xfff; + used_pg = (pg_flow_ctrl[15] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of PLE group=0x%03x/0x%03x\n", + used_pg, rsv_pg); + /* Queue Empty Status */ + DBGLOG(HAL, INFO, "PSE Queue Empty Status:\n"); + DBGLOG(HAL, INFO, + "\tQUEUE_EMPTY(0x820680b0): 0x%08x\n", pse_stat); + DBGLOG(HAL, INFO, + "\t\tCPU Q0/1/2/3 empty=%d/%d/%d/%d\n", + pse_stat & 0x1, ((pse_stat & 0x2) >> 1), + ((pse_stat & 0x4) >> 2), ((pse_stat & 0x8) >> 3)); + DBGLOG(HAL, INFO, + "\t\tHIF Q0/1 empty=%d/%d\n", + ((pse_stat & (0x1 << 16)) >> 16), + ((pse_stat & (0x1 << 17)) >> 17)); + DBGLOG(HAL, INFO, + "\t\tLMAC TX Q empty=%d\n", + ((pse_stat & (0x1 << 24)) >> 24)); + DBGLOG(HAL, INFO, + "\t\tRLS_Q empty=%d\n", + ((pse_stat & (0x1 << 31)) >> 31)); + DBGLOG(HAL, INFO, "Nonempty Q info:\n"); + + for (i = 0; i < 31; i++) { + if (((pse_stat & (0x1 << i)) >> i) == 0) { + uint32_t hfid, tfid, pktcnt, fl_que_ctrl[3] = {0}; + + if (i < 4) { + DBGLOG(HAL, INFO, + "\tCPU Q%d: ", i); + fl_que_ctrl[0] |= (0x1 << 14); + fl_que_ctrl[0] |= (i << 8); + } else if (i == 16) { + DBGLOG(HAL, INFO, "\tHIF Q0: "); + fl_que_ctrl[0] |= (0x0 << 14); + fl_que_ctrl[0] |= (0x0 << 8); + } else if (i == 17) { + DBGLOG(HAL, INFO, "\tHIF Q1: "); + fl_que_ctrl[0] |= (0x0 << 14); + fl_que_ctrl[0] |= (0x1 << 8); + } else if (i == 24) { + DBGLOG(HAL, INFO, "\tLMAC TX Q: "); + fl_que_ctrl[0] |= (0x2 << 14); + fl_que_ctrl[0] |= (0x0 << 8); + } else if (i == 31) { + DBGLOG(HAL, INFO, "\tRLS Q: "); + fl_que_ctrl[0] |= (0x3 << 14); + fl_que_ctrl[0] |= (i << 8); + } else + continue; + + fl_que_ctrl[0] |= (0x1 << 31); + HAL_MCR_WR(prAdapter, PSE_FL_QUE_CTRL_0, + fl_que_ctrl[0]); + HAL_MCR_RD(prAdapter, PSE_FL_QUE_CTRL_2, + &fl_que_ctrl[1]); + HAL_MCR_RD(prAdapter, PSE_FL_QUE_CTRL_3, + &fl_que_ctrl[2]); + hfid = fl_que_ctrl[1] & 0xfff; + tfid = (fl_que_ctrl[1] & 0xfff << 16) >> 16; + pktcnt = fl_que_ctrl[2] & 0xfff; + DBGLOG(HAL, INFO, + "tail/head fid = 0x%03x/0x%03x, pkt cnt = %x\n", + tfid, hfid, pktcnt); + } + } + + for (i = 0; i < PSE_PEEK_CR_NUM; i++) { + addr = PSE_PEEK_CR_0 + PSE_PEEK_CR_OFFSET * i; + HAL_MCR_RD(prAdapter, addr, &value); + DBGLOG(HAL, INFO, "PSE_PEEK_CR_%u[0x%08x/0x%08x]\n", + i, addr, value); + } + + for (i = 0; i < PSE_ENDEQ_NUM; i++) { + addr = PSE_ENQ_0 + PSE_ENDEQ_OFFSET * i; + HAL_MCR_RD(prAdapter, addr, &value); + DBGLOG(HAL, INFO, "PSE_ENQ_%u[0x%08x/0x%08x]\n", + i, addr, value); + } + + for (i = 0; i < PSE_ENDEQ_NUM; i++) { + addr = PSE_DEQ_0 + PSE_ENDEQ_OFFSET * i; + HAL_MCR_RD(prAdapter, addr, &value); + DBGLOG(HAL, INFO, "PSE_DEQ_%u[0x%08x/0x%08x]\n", + i, addr, value); + } +} + +#define UMAC_FID_FAULT 0xFFF +#define DUMP_MEM_SIZE 64 +static int8_t *sta_ctrl_reg[] = {"ENABLE", "*DISABLE", "*PAUSE"}; +static struct EMPTY_QUEUE_INFO Queue_Empty_info[] = { + {"CPU Q0", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_0}, + {"CPU Q1", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_1}, + {"CPU Q2", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_2}, + {"CPU Q3", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_3}, + {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, + {"ALTX Q0", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_ALTX_0}, + {"BMC Q0", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_BMC_0}, + {"BCN Q0", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_BNC_0}, + {"PSMP Q0", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_PSMP_0}, + {"ALTX Q1", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_ALTX_1}, + {"BMC Q1", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_BMC_1}, + {"BCN Q1", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_BNC_1}, + {"PSMP Q1", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_PSMP_1}, + {"NAF Q", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_NAF}, + {"NBCN Q", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_NBCN}, + {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, + {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, + {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, + {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, + {"RLS Q", ENUM_PLE_CTRL_PSE_PORT_3, ENUM_UMAC_PLE_CTRL_P3_Q_0X1E}, + {"RLS2 Q", ENUM_PLE_CTRL_PSE_PORT_3, ENUM_UMAC_PLE_CTRL_P3_Q_0X1F} +}; + +void halShowPleInfo(IN struct ADAPTER *prAdapter) +{ + uint32_t ple_buf_ctrl[3] = {0}, pg_sz, pg_num, bit_field_1, bit_field_2; + uint32_t ple_stat[17] = {0}, pg_flow_ctrl[6] = {0}; + uint32_t sta_pause[4] = {0}, dis_sta_map[4] = {0}; + uint32_t fpg_cnt, ffa_cnt, fpg_head, fpg_tail, hif_max_q, hif_min_q; + uint32_t rpg_hif, upg_hif, cpu_max_q, cpu_min_q, rpg_cpu, upg_cpu; + uint32_t i, j, addr, value; + + HAL_MCR_RD(prAdapter, PLE_PBUF_CTRL, &ple_buf_ctrl[0]); + HAL_MCR_RD(prAdapter, PLE_RELEASE_CTRL, &ple_buf_ctrl[1]); + HAL_MCR_RD(prAdapter, PLE_HIF_REPORT, &ple_buf_ctrl[2]); + HAL_MCR_RD(prAdapter, PLE_QUEUE_EMPTY, &ple_stat[0]); + HAL_MCR_RD(prAdapter, PLE_AC0_QUEUE_EMPTY_0, &ple_stat[1]); + HAL_MCR_RD(prAdapter, PLE_AC0_QUEUE_EMPTY_1, &ple_stat[2]); + HAL_MCR_RD(prAdapter, PLE_AC0_QUEUE_EMPTY_2, &ple_stat[3]); + HAL_MCR_RD(prAdapter, PLE_AC0_QUEUE_EMPTY_3, &ple_stat[4]); + HAL_MCR_RD(prAdapter, PLE_AC1_QUEUE_EMPTY_0, &ple_stat[5]); + HAL_MCR_RD(prAdapter, PLE_AC1_QUEUE_EMPTY_1, &ple_stat[6]); + HAL_MCR_RD(prAdapter, PLE_AC1_QUEUE_EMPTY_2, &ple_stat[7]); + HAL_MCR_RD(prAdapter, PLE_AC1_QUEUE_EMPTY_3, &ple_stat[8]); + HAL_MCR_RD(prAdapter, PLE_AC2_QUEUE_EMPTY_0, &ple_stat[9]); + HAL_MCR_RD(prAdapter, PLE_AC2_QUEUE_EMPTY_1, &ple_stat[10]); + HAL_MCR_RD(prAdapter, PLE_AC2_QUEUE_EMPTY_2, &ple_stat[11]); + HAL_MCR_RD(prAdapter, PLE_AC2_QUEUE_EMPTY_3, &ple_stat[12]); + HAL_MCR_RD(prAdapter, PLE_AC3_QUEUE_EMPTY_0, &ple_stat[13]); + HAL_MCR_RD(prAdapter, PLE_AC3_QUEUE_EMPTY_1, &ple_stat[14]); + HAL_MCR_RD(prAdapter, PLE_AC3_QUEUE_EMPTY_2, &ple_stat[15]); + HAL_MCR_RD(prAdapter, PLE_AC3_QUEUE_EMPTY_3, &ple_stat[16]); + HAL_MCR_RD(prAdapter, PLE_FREEPG_CNT, &pg_flow_ctrl[0]); + HAL_MCR_RD(prAdapter, PLE_FREEPG_HEAD_TAIL, &pg_flow_ctrl[1]); + HAL_MCR_RD(prAdapter, PLE_PG_HIF_GROUP, &pg_flow_ctrl[2]); + HAL_MCR_RD(prAdapter, PLE_HIF_PG_INFO, &pg_flow_ctrl[3]); + HAL_MCR_RD(prAdapter, PLE_PG_CPU_GROUP, &pg_flow_ctrl[4]); + HAL_MCR_RD(prAdapter, PLE_CPU_PG_INFO, &pg_flow_ctrl[5]); + HAL_MCR_RD(prAdapter, DIS_STA_MAP0, &dis_sta_map[0]); + HAL_MCR_RD(prAdapter, DIS_STA_MAP1, &dis_sta_map[1]); + HAL_MCR_RD(prAdapter, DIS_STA_MAP2, &dis_sta_map[2]); + HAL_MCR_RD(prAdapter, DIS_STA_MAP3, &dis_sta_map[3]); + HAL_MCR_RD(prAdapter, STATION_PAUSE0, &sta_pause[0]); + HAL_MCR_RD(prAdapter, STATION_PAUSE1, &sta_pause[1]); + HAL_MCR_RD(prAdapter, STATION_PAUSE2, &sta_pause[2]); + HAL_MCR_RD(prAdapter, STATION_PAUSE3, &sta_pause[3]); + /* Configuration Info */ + DBGLOG(HAL, INFO, "PLE Configuration Info:\n"); + + HAL_MCR_RD(prAdapter, PLE_GC, &value); + DBGLOG(HAL, INFO, "\tGC(0x82060000): 0x%08x\n", value); + HAL_MCR_RD(prAdapter, PLE_INT_STS, &value); + DBGLOG(HAL, INFO, "\tINT_STS(0x82060024): 0x%08x\n", value); + HAL_MCR_RD(prAdapter, PLE_INT_ERR_STS, &value); + DBGLOG(HAL, INFO, "\tINT_ERR_STS(0x82060028): 0x%08x\n", value); + + DBGLOG(HAL, INFO, + "\tPacket Buffer Control(0x82060014): 0x%08x\n", + ple_buf_ctrl[0]); + pg_sz = (ple_buf_ctrl[0] & (0x1 << 31)) >> 31; + DBGLOG(HAL, INFO, + "\t\tPage Size=%d(%d bytes per page)\n", + pg_sz, (pg_sz == 1 ? 128 : 64)); + DBGLOG(HAL, INFO, + "\t\tPage Offset=%d(in unit of 2KB)\n", + (ple_buf_ctrl[0] & (0xf << 17)) >> 17); + pg_num = (ple_buf_ctrl[0] & 0xfff); + DBGLOG(HAL, INFO, + "\t\tTotal Page=%d pages\n", (ple_buf_ctrl[0] & 0xfff)); + DBGLOG(HAL, INFO, + "\tRelease Control(0x82060030): 0x%08x\n", ple_buf_ctrl[1]); + bit_field_1 = (ple_buf_ctrl[1] & 0x1f); + bit_field_2 = ((ple_buf_ctrl[1] & (0x3 << 6)) >> 6); + DBGLOG(HAL, INFO, + "\t\tNormalTx Release Pid/Qid=%d/%d\n", + bit_field_2, bit_field_1); + bit_field_1 = ((ple_buf_ctrl[1] & (0x1f << 8)) >> 8); + bit_field_2 = ((ple_buf_ctrl[1] & (0x3 << 14)) >> 14); + DBGLOG(HAL, INFO, + "\t\tDropTx Release Pid/Qid=%d/%d\n", bit_field_2, bit_field_1); + bit_field_1 = ((ple_buf_ctrl[1] & (0x1f << 16)) >> 16); + bit_field_2 = ((ple_buf_ctrl[1] & (0x3 << 22)) >> 22); + DBGLOG(HAL, INFO, + "\t\tBCN0 Release Pid/Qid=%d/%d\n", bit_field_2, bit_field_1); + bit_field_1 = ((ple_buf_ctrl[1] & (0x1f << 24)) >> 24); + bit_field_2 = ((ple_buf_ctrl[1] & (0x3 << 30)) >> 30); + DBGLOG(HAL, INFO, + "\t\tBCN1 Release Pid/Qid=%d/%d\n", bit_field_2, bit_field_1); + DBGLOG(HAL, INFO, + "\tHIF Report Control(0x82060034): 0x%08x\n", ple_buf_ctrl[2]); + bit_field_1 = ((ple_buf_ctrl[2] & (0x1 << 1)) >> 1); + DBGLOG(HAL, INFO, + "\t\tHostReportQSel/HostReportDisable=%d/%d\n", + (ple_buf_ctrl[2] & 0x1), bit_field_1); + /* Page Flow Control */ + DBGLOG(HAL, INFO, "PLE Page Flow Control:\n"); + DBGLOG(HAL, INFO, + "\tFree page counter(0x82060100): 0x%08x\n", pg_flow_ctrl[0]); + fpg_cnt = pg_flow_ctrl[0] & 0xfff; + DBGLOG(HAL, INFO, + "\t\tThe toal page number of free=0x%03x\n", fpg_cnt); + ffa_cnt = (pg_flow_ctrl[0] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe free page numbers of free for all=0x%03x\n", ffa_cnt); + DBGLOG(HAL, INFO, + "\tFree page head and tail(0x82060104): 0x%08x\n", + pg_flow_ctrl[1]); + fpg_head = pg_flow_ctrl[1] & 0xfff; + fpg_tail = (pg_flow_ctrl[1] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe tail/head page of free page list=0x%03x/0x%03x\n", + fpg_tail, fpg_head); + DBGLOG(HAL, INFO, + "\tReserved page counter of HIF group(0x82060110): 0x%08x\n", + pg_flow_ctrl[2]); + DBGLOG(HAL, INFO, + "\tHIF group page status(0x82060114): 0x%08x\n", + pg_flow_ctrl[3]); + hif_min_q = pg_flow_ctrl[2] & 0xfff; + hif_max_q = (pg_flow_ctrl[2] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of HIF group=0x%03x/0x%03x\n", + hif_max_q, hif_min_q); + rpg_hif = pg_flow_ctrl[3] & 0xfff; + upg_hif = (pg_flow_ctrl[3] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of HIF group=0x%03x/0x%03x\n", + upg_hif, rpg_hif); + DBGLOG(HAL, INFO, + "\tReserved page counter of CPU group(0x82060150): 0x%08x\n", + pg_flow_ctrl[4]); + DBGLOG(HAL, INFO, + "\tCPU group page status(0x82060154): 0x%08x\n", + pg_flow_ctrl[5]); + cpu_min_q = pg_flow_ctrl[4] & 0xfff; + cpu_max_q = (pg_flow_ctrl[4] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe max/min quota pages of CPU group=0x%03x/0x%03x\n", + cpu_max_q, cpu_min_q); + rpg_cpu = pg_flow_ctrl[5] & 0xfff; + upg_cpu = (pg_flow_ctrl[5] & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "\t\tThe used/reserved pages of CPU group=0x%03x/0x%03x\n", + upg_cpu, rpg_cpu); + + if (((ple_stat[0] & (0x1 << 24)) >> 24) == 0) { + DBGLOG(HAL, INFO, + "\tAC0_QUEUE_EMPTY0(0x82060300): 0x%08x\n", + ple_stat[1]); + DBGLOG(HAL, INFO, + "\tAC1_QUEUE_EMPTY0(0x82060310): 0x%08x\n", + ple_stat[5]); + DBGLOG(HAL, INFO, + "\tAC2_QUEUE_EMPTY0(0x82060320): 0x%08x\n", + ple_stat[9]); + DBGLOG(HAL, INFO, + "\tAC3_QUEUE_EMPTY0(0x82060330): 0x%08x\n", + ple_stat[13]); + + for (j = 0; j < 16; j = j + 4) { + if (j % 4 == 0) + DBGLOG(HAL, INFO, "\tNonempty AC%d Q of STA#:", + j / 4); + + for (i = 0; i < 32; i++) { + if (((ple_stat[j + 1] & (0x1 << i)) >> i) == 0) + DBGLOG(HAL, INFO, "%d ", + i + (j % 4) * 32); + } + } + + DBGLOG(HAL, INFO, "\n"); + } + + DBGLOG(HAL, INFO, "Nonempty Q info:\n"); + + for (i = 0; i < 31; i++) { + if (((ple_stat[0] & (0x1 << i)) >> i) == 0) { + uint32_t hfid, tfid, pktcnt, fl_que_ctrl[3] = {0}; + + if (Queue_Empty_info[i].QueueName != NULL) { + DBGLOG(HAL, INFO, "\t%s: ", + Queue_Empty_info[i].QueueName); + fl_que_ctrl[0] |= (0x1 << 31); + fl_que_ctrl[0] |= + (Queue_Empty_info[i].Portid << 14); + fl_que_ctrl[0] |= + (Queue_Empty_info[i].Queueid << 8); + } else + continue; + + HAL_MCR_WR(prAdapter, + PLE_FL_QUE_CTRL_0, fl_que_ctrl[0]); + HAL_MCR_RD(prAdapter, + PLE_FL_QUE_CTRL_2, &fl_que_ctrl[1]); + HAL_MCR_RD(prAdapter, + PLE_FL_QUE_CTRL_3, &fl_que_ctrl[2]); + hfid = fl_que_ctrl[1] & 0xfff; + tfid = (fl_que_ctrl[1] & 0xfff << 16) >> 16; + pktcnt = fl_que_ctrl[2] & 0xfff; + DBGLOG(HAL, INFO, + "tail/head fid = 0x%03x/0x%03x, pkt cnt = %x\n", + tfid, hfid, pktcnt); + } + } + + for (j = 0; j < 16; j = j + 4) { /* show AC Q info */ + for (i = 0; i < 32; i++) { + if (((ple_stat[j + 1] & (0x1 << i)) >> i) == 0) { + uint32_t hfid, tfid, pktcnt, + ac_num = j / 4, ctrl = 0; + uint32_t sta_num = i + (j % 4) * 32, + fl_que_ctrl[3] = {0}; + + DBGLOG(HAL, INFO, "\tSTA%d AC%d: ", + sta_num, ac_num); + fl_que_ctrl[0] |= (0x1 << 31); + fl_que_ctrl[0] |= (0x2 << 14); + fl_que_ctrl[0] |= (ac_num << 8); + fl_que_ctrl[0] |= sta_num; + HAL_MCR_WR(prAdapter, + PLE_FL_QUE_CTRL_0, fl_que_ctrl[0]); + HAL_MCR_RD(prAdapter, + PLE_FL_QUE_CTRL_2, &fl_que_ctrl[1]); + HAL_MCR_RD(prAdapter, + PLE_FL_QUE_CTRL_3, &fl_que_ctrl[2]); + hfid = fl_que_ctrl[1] & 0xfff; + tfid = (fl_que_ctrl[1] & 0xfff << 16) >> 16; + pktcnt = fl_que_ctrl[2] & 0xfff; + DBGLOG(HAL, INFO, + "tail/head fid = 0x%03x/0x%03x, pkt cnt = %x", + tfid, hfid, pktcnt); + + if (((sta_pause[j % 4] & 0x1 << i) >> i) == 1) + ctrl = 2; + + if (((dis_sta_map[j % 4] & 0x1 << i) >> i) == 1) + ctrl = 1; + + DBGLOG(HAL, INFO, " ctrl = %s", + sta_ctrl_reg[ctrl]); + } + } + } + + for (i = 0; i < PLE_PEEK_CR_NUM; i++) { + addr = PLE_PEEK_CR_0 + PLE_PEEK_CR_OFFSET * i; + HAL_MCR_RD(prAdapter, addr, &value); + DBGLOG(HAL, INFO, "PLE_PEEK_CR_%u[0x%08x/0x%08x]\n", + i, addr, value); + } +} + +bool halShowHostCsrInfo(IN struct ADAPTER *prAdapter) +{ + uint32_t i = 0, u4Value = 0; + bool fgIsDriverOwn = false; + bool fgEnClock = false; + + DBGLOG(HAL, INFO, "Host CSR Configuration Info:\n\n"); + + HAL_MCR_RD(prAdapter, HOST_CSR_BASE, &u4Value); + DBGLOG(HAL, INFO, "Get 0x87654321: 0x%08x = 0x%08x\n", + HOST_CSR_BASE, u4Value); + + HAL_MCR_RD(prAdapter, HOST_CSR_DRIVER_OWN_INFO, &u4Value); + DBGLOG(HAL, INFO, "Driver own info: 0x%08x = 0x%08x\n", + HOST_CSR_BASE, u4Value); + fgIsDriverOwn = (u4Value & PCIE_LPCR_HOST_SET_OWN) == 0; + + for (i = 0; i < 5; i++) { + HAL_MCR_RD(prAdapter, HOST_CSR_MCU_PORG_COUNT, &u4Value); + DBGLOG(HAL, INFO, + "MCU programming Counter info (no sync): 0x%08x = 0x%08x\n", + HOST_CSR_MCU_PORG_COUNT, u4Value); + } + + HAL_MCR_RD(prAdapter, HOST_CSR_RGU, &u4Value); + DBGLOG(HAL, INFO, "RGU Info: 0x%08x = 0x%08x\n", HOST_CSR_RGU, u4Value); + + HAL_MCR_RD(prAdapter, HOST_CSR_HIF_BUSY_CORQ_WFSYS_ON, &u4Value); + DBGLOG(HAL, INFO, "HIF_BUSY / CIRQ / WFSYS_ON info: 0x%08x = 0x%08x\n", + HOST_CSR_HIF_BUSY_CORQ_WFSYS_ON, u4Value); + + HAL_MCR_RD(prAdapter, HOST_CSR_PINMUX_MON_FLAG, &u4Value); + DBGLOG(HAL, INFO, "Pinmux/mon_flag info: 0x%08x = 0x%08x\n", + HOST_CSR_PINMUX_MON_FLAG, u4Value); + + HAL_MCR_RD(prAdapter, HOST_CSR_MCU_PWR_STAT, &u4Value); + DBGLOG(HAL, INFO, "Bit[5] mcu_pwr_stat: 0x%08x = 0x%08x\n", + HOST_CSR_MCU_PWR_STAT, u4Value); + + HAL_MCR_RD(prAdapter, HOST_CSR_FW_OWN_SET, &u4Value); + DBGLOG(HAL, INFO, "Bit[15] fw_own_stat: 0x%08x = 0x%08x\n", + HOST_CSR_FW_OWN_SET, u4Value); + + HAL_MCR_RD(prAdapter, HOST_CSR_MCU_SW_MAILBOX_0, &u4Value); + DBGLOG(HAL, INFO, "WF Mailbox[0]: 0x%08x = 0x%08x\n", + HOST_CSR_MCU_SW_MAILBOX_0, u4Value); + + HAL_MCR_RD(prAdapter, HOST_CSR_MCU_SW_MAILBOX_1, &u4Value); + DBGLOG(HAL, INFO, "MCU Mailbox[1]: 0x%08x = 0x%08x\n", + HOST_CSR_MCU_SW_MAILBOX_1, u4Value); + + HAL_MCR_RD(prAdapter, HOST_CSR_MCU_SW_MAILBOX_2, &u4Value); + DBGLOG(HAL, INFO, "BT Mailbox[2]: 0x%08x = 0x%08x\n", + HOST_CSR_MCU_SW_MAILBOX_2, u4Value); + + HAL_MCR_RD(prAdapter, HOST_CSR_MCU_SW_MAILBOX_3, &u4Value); + DBGLOG(HAL, INFO, "GPS Mailbox[3]: 0x%08x = 0x%08x\n", + HOST_CSR_MCU_SW_MAILBOX_3, u4Value); + + HAL_MCR_RD(prAdapter, HOST_CSR_CONN_CFG_ON, &u4Value); + DBGLOG(HAL, INFO, "Conn_cfg_on info: 0x%08x = 0x%08x\n", + HOST_CSR_CONN_CFG_ON, u4Value); + + HAL_MCR_WR(prAdapter, HOST_CSR_DRIVER_OWN_INFO, 0x00030000); + kalUdelay(1); + HAL_MCR_RD(prAdapter, HOST_CSR_DRIVER_OWN_INFO, &u4Value); + DBGLOG(HAL, INFO, "Bit[17]/[16], Get HCLK info: 0x%08x = 0x%08x\n", + HOST_CSR_DRIVER_OWN_INFO, u4Value); + + /* check clock is enabled */ + fgEnClock = ((u4Value & BIT(17)) != 0) && ((u4Value & BIT(16)) != 0); + + return fgIsDriverOwn && fgEnClock; +} + +void halShowDmaschInfo(IN struct ADAPTER *prAdapter) +{ + uint32_t value; + uint32_t ple_pkt_max_sz; + uint32_t pse_pkt_max_sz; + uint32_t max_quota; + uint32_t min_quota; + uint32_t rsv_cnt; + uint32_t src_cnt; + uint32_t pse_rsv_cnt = 0; + uint32_t pse_src_cnt = 0; + uint32_t odd_group_pktin_cnt = 0; + uint32_t odd_group_ask_cnt = 0; + uint32_t pktin_cnt; + uint32_t ask_cnt; + uint32_t total_src_cnt = 0; + uint32_t total_rsv_cnt = 0; + uint32_t ffa_cnt; + uint32_t free_pg_cnt; + uint32_t Group_Mapping_Q[16] = {0}; + uint32_t qmapping_addr = MT_HIF_DMASHDL_Q_MAP0; + uint32_t status_addr = MT_HIF_DMASHDL_STATUS_RD_GP0; + uint32_t quota_addr = MT_HIF_DMASHDL_GROUP0_CTRL; + uint32_t pkt_cnt_addr = MT_HIF_DMASHDLRD_GP_PKT_CNT_0; + uint32_t mapping_mask = 0xf; + uint32_t mapping_offset = 0; + uint32_t mapping_qidx; + uint32_t groupidx = 0; + uint8_t idx = 0; + u_int8_t pktin_int_refill_ena; + u_int8_t pdma_add_int_refill_ena; + u_int8_t ple_add_int_refill_ena; + u_int8_t ple_sub_ena; + u_int8_t hif_ask_sub_ena; + u_int8_t ple_txd_gt_max_size_flag_clr; + uint32_t ple_rpg_hif; + uint32_t ple_upg_hif; + uint32_t pse_rpg_hif = 0; + uint32_t pse_upg_hif = 0; + uint8_t is_mismatch = FALSE; + + for (mapping_qidx = 0; mapping_qidx < 32; mapping_qidx++) { + uint32_t mapping_group; + + idx = 0; + + if (mapping_qidx == 0) { + qmapping_addr = MT_HIF_DMASHDL_Q_MAP0; + mapping_mask = 0xf; + mapping_offset = 0; + } else if ((mapping_qidx % 8) == 0) { + qmapping_addr += 0x4; + mapping_mask = 0xf; + mapping_offset = 0; + } else { + mapping_offset += 4; + mapping_mask = 0xf << mapping_offset; + } + + HAL_MCR_RD(prAdapter, qmapping_addr, &value); + mapping_group = (value & mapping_mask) >> mapping_offset; + Group_Mapping_Q[mapping_group] |= 1 << mapping_qidx; + } + + DBGLOG(HAL, INFO, "Dma scheduler info:\n"); + HAL_MCR_RD(prAdapter, MT_HIF_DMASHDL_CTRL_SIGNAL, &value); + pktin_int_refill_ena = + (value & DMASHDL_PKTIN_INT_REFILL_ENA) ? TRUE : FALSE; + pdma_add_int_refill_ena = + (value & DMASHDL_PDMA_ADD_INT_REFILL_ENA) ? TRUE : FALSE; + ple_add_int_refill_ena = + (value & DMASHDL_PLE_ADD_INT_REFILL_ENA) ? TRUE : FALSE; + ple_sub_ena = (value & DMASHDL_PLE_SUB_ENA) ? TRUE : FALSE; + hif_ask_sub_ena = (value & DMASHDL_HIF_ASK_SUB_ENA) ? TRUE : FALSE; + ple_txd_gt_max_size_flag_clr = + (value & DMASHDL_PLE_TXD_GT_MAX_SIZE_FLAG_CLR) ? TRUE : FALSE; + DBGLOG(HAL, INFO, "DMASHDL Ctrl Signal(0x5000A018): 0x%08x\n", value); + DBGLOG(HAL, INFO, "\tple_txd_gt_max_size_flag_clr(BIT0) = %d\n", + ple_txd_gt_max_size_flag_clr); + DBGLOG(HAL, INFO, "\thif_ask_sub_ena(BIT16) = %d\n", hif_ask_sub_ena); + DBGLOG(HAL, INFO, "\tple_sub_ena(BIT17) = %d\n", ple_sub_ena); + DBGLOG(HAL, INFO, "\tple_add_int_refill_ena(BIT29) = %d\n", + ple_add_int_refill_ena); + DBGLOG(HAL, INFO, "\tpdma_add_int_refill_ena(BIT30) = %d\n", + pdma_add_int_refill_ena); + DBGLOG(HAL, INFO, "\tpktin_int_refill(BIT31)_ena = %d\n", + pktin_int_refill_ena); + HAL_MCR_RD(prAdapter, MT_HIF_DMASHDL_PKT_MAX_SIZE, &value); + ple_pkt_max_sz = GET_PLE_PKT_MAX_SIZE_NUM(value); + pse_pkt_max_sz = GET_PSE_PKT_MAX_SIZE_NUM(value); + DBGLOG(HAL, INFO, + "DMASHDL Packet_max_size(0x5000A01c): 0x%08x\n", value); + DBGLOG(HAL, INFO, + "PLE/PSE packet max size=0x%03x/0x%03x\n", + ple_pkt_max_sz, pse_pkt_max_sz); + HAL_MCR_RD(prAdapter, MT_HIF_DMASHDL_ERROR_FLAG_CTRL, &value); + DBGLOG(HAL, INFO, "DMASHDL ERR FLAG CTRL(0x5000A09c): 0x%08x\n", value); + HAL_MCR_RD(prAdapter, MT_HIF_DMASHDL_STATUS_RD, &value); + ffa_cnt = (value & DMASHDL_FFA_CNT_MASK) >> DMASHDL_FFA_CNT_OFFSET; + free_pg_cnt = (value & DMASHDL_FREE_PG_CNT_MASK) >> + DMASHDL_FREE_PG_CNT_OFFSET; + DBGLOG(HAL, INFO, "DMASHDL Status_RD(0x5000A100): 0x%08x\n", value); + DBGLOG(HAL, INFO, + "free page cnt = 0x%03x, ffa cnt = 0x%03x\n", + free_pg_cnt, ffa_cnt); + HAL_MCR_RD(prAdapter, PDMA_DEBUG_REFill, &value); + DBGLOG(HAL, INFO, + "DMASHDL ReFill Control(0x5000A010): 0x%08x\n", value); + + for (groupidx = 0; groupidx < 16; groupidx++) { + DBGLOG(HAL, INFO, "Group %d info:", groupidx); + HAL_MCR_RD(prAdapter, status_addr, &value); + rsv_cnt = (value & DMASHDL_RSV_CNT_MASK) >> + DMASHDL_RSV_CNT_OFFSET; + src_cnt = (value & DMASHDL_SRC_CNT_MASK) >> + DMASHDL_SRC_CNT_OFFSET; + DBGLOG(HAL, INFO, + "\tDMASHDL Status_RD_GP%d(0x%08x): 0x%08x\n", + groupidx, status_addr, value); + HAL_MCR_RD(prAdapter, quota_addr, &value); + max_quota = (value & DMASHDL_MAX_QUOTA_MASK) >> + DMASHDL_MAX_QUOTA_OFFSET; + min_quota = (value & DMASHDL_MIN_QUOTA_MASK) >> + DMASHDL_MIN_QUOTA_OFFSET; + DBGLOG(HAL, INFO, + "\tDMASHDL Group%d control(0x%08x): 0x%08x\n", + groupidx, quota_addr, value); + + if ((groupidx & 0x1) == 0) { + HAL_MCR_RD(prAdapter, pkt_cnt_addr, &value); + DBGLOG(HAL, INFO, + "\tDMASHDL RD_group_pkt_cnt_%d(0x%08x): 0x%08x\n", + groupidx / 2, pkt_cnt_addr, value); + odd_group_pktin_cnt = GET_ODD_GROUP_PKT_IN_CNT(value); + odd_group_ask_cnt = GET_ODD_GROUP_ASK_CNT(value); + pktin_cnt = GET_EVEN_GROUP_PKT_IN_CNT(value); + ask_cnt = GET_EVEN_GROUP_ASK_CNT(value); + } else { + pktin_cnt = odd_group_pktin_cnt; + ask_cnt = odd_group_ask_cnt; + } + + DBGLOG(HAL, INFO, + "\trsv_cnt = 0x%03x, src_cnt = 0x%03x\n", + rsv_cnt, src_cnt); + DBGLOG(HAL, INFO, + "\tmax/min quota = 0x%03x/ 0x%03x\n", + max_quota, min_quota); + DBGLOG(HAL, INFO, + "\tpktin_cnt = 0x%02x, ask_cnt = 0x%02x", + pktin_cnt, ask_cnt); + + if (hif_ask_sub_ena && pktin_cnt != ask_cnt) { + DBGLOG(HAL, INFO, ", mismatch!"); + is_mismatch = TRUE; + } + + /* Group15 is for PSE */ + if (groupidx == 15 && Group_Mapping_Q[groupidx] == 0) { + pse_src_cnt = src_cnt; + pse_rsv_cnt = rsv_cnt; + break; + } + + DBGLOG(HAL, INFO, "\tMapping Qidx: 0x%x", + Group_Mapping_Q[groupidx]); + + total_src_cnt += src_cnt; + total_rsv_cnt += rsv_cnt; + status_addr = status_addr + 4; + quota_addr = quota_addr + 4; + + if (groupidx & 0x1) + pkt_cnt_addr = pkt_cnt_addr + 4; + } + + DBGLOG(HAL, INFO, "\nCounter Check:\n"); + HAL_MCR_RD(prAdapter, PLE_HIF_PG_INFO, &value); + ple_rpg_hif = value & 0xfff; + ple_upg_hif = (value & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "PLE:\n\tThe used/reserved pages of PLE HIF group=0x%03x/0x%03x\n", + ple_upg_hif, ple_rpg_hif); + HAL_MCR_RD(prAdapter, PSE_HIF1_PG_INFO, &value); + pse_rpg_hif = value & 0xfff; + pse_upg_hif = (value & (0xfff << 16)) >> 16; + DBGLOG(HAL, INFO, + "PSE:\n\tThe used/reserved pages of PSE HIF group=0x%03x/0x%03x\n", + pse_upg_hif, pse_rpg_hif); + DBGLOG(HAL, INFO, + "DMASHDL:\n\tThe total used pages of group0~14=0x%03x", + total_src_cnt); + + if (ple_upg_hif != total_src_cnt) { + DBGLOG(HAL, INFO, ", mismatch!"); + is_mismatch = TRUE; + } + + DBGLOG(HAL, INFO, "\n"); + DBGLOG(HAL, INFO, + "\tThe total reserved pages of group0~14=0x%03x\n", + total_rsv_cnt); + DBGLOG(HAL, INFO, + "\tThe total ffa pages of group0~14=0x%03x\n", + ffa_cnt); + DBGLOG(HAL, INFO, + "\tThe total free pages of group0~14=0x%03x", free_pg_cnt); + + if (free_pg_cnt != total_rsv_cnt + ffa_cnt) { + DBGLOG(HAL, INFO, + ", mismatch(total_rsv_cnt + ffa_cnt in DMASHDL)"); + is_mismatch = TRUE; + } + + if (free_pg_cnt != ple_rpg_hif) { + DBGLOG(HAL, INFO, ", mismatch(reserved pages in PLE)"); + is_mismatch = TRUE; + } + + DBGLOG(HAL, INFO, "\n"); + DBGLOG(HAL, INFO, "\tThe used pages of group15=0x%03x", pse_src_cnt); + + if (pse_upg_hif != pse_src_cnt) { + DBGLOG(HAL, INFO, ", mismatch!"); + is_mismatch = TRUE; + } + + DBGLOG(HAL, INFO, "\n"); + DBGLOG(HAL, INFO, + "\tThe reserved pages of group15=0x%03x", pse_rsv_cnt); + + if (pse_rpg_hif != pse_rsv_cnt) { + DBGLOG(HAL, INFO, ", mismatch!"); + is_mismatch = TRUE; + } + + DBGLOG(HAL, INFO, "\n"); + + if (!is_mismatch) + DBGLOG(HAL, INFO, "DMASHDL: no counter mismatch\n"); +} + +void haldumpPhyInfo(struct ADAPTER *prAdapter) +{ + uint32_t i = 0, value = 0; + + for (i = 0; i < 20; i++) { + HAL_MCR_RD(prAdapter, 0x82072644, &value); + DBGLOG(HAL, INFO, "0x82072644: 0x%08x\n", value); + kalMdelay(1); + } +} + +void haldumpMacInfo(struct ADAPTER *prAdapter) +{ + uint32_t i = 0, j = 0; + uint32_t value = 0, index = 0, flag = 0; + + DBGLOG(HAL, INFO, "Print 0x820F3190 5*20 times\n"); + for (i = 0; i < 5; i++) { + for (j = 0; j < 20; j++) { + HAL_MCR_RD(prAdapter, 0x820F3190, &value); + DBGLOG(HAL, INFO, "0x820F3190: 0x%08x\n", value); + } + kalMdelay(1); + } + + for (j = 0; j < 20; j++) { + HAL_MCR_RD(prAdapter, 0x820FD020, &value); + DBGLOG(HAL, INFO, "0x820FD020: 0x%08x\n", value); + kalMdelay(1); + } + + HAL_MCR_RD(prAdapter, 0x820F4124, &value); + DBGLOG(HAL, INFO, "Dump CR: 0x820F4124 = %08x\n", value); + + for (j = 0x820F4130; j < 0x820F4148; j += 4) { + HAL_MCR_RD(prAdapter, j, &value); + DBGLOG(HAL, INFO, "0x%08x: 0x%08x\n", j, value); + kalMdelay(1); + } + + HAL_MCR_RD(prAdapter, 0x820F409C, &value); + DBGLOG(HAL, INFO, "Dump CR: 0x820F409C = %08x\n", value); + + HAL_MCR_RD(prAdapter, 0x820F409C, &value); + DBGLOG(HAL, INFO, "Dump CR: 0x820F409C = %08x\n", value); + + HAL_MCR_RD(prAdapter, 0x820F3080, &value); + DBGLOG(HAL, INFO, "Dump CR: 0x820F3080 = %08x\n", value); + + DBGLOG(HAL, INFO, "Dump ARB CR: 820F3000~820F33FF\n"); + for (index = 0x820f3000; index < 0x820f33ff; index += 4) { + HAL_MCR_RD(prAdapter, index, &value); + DBGLOG(HAL, INFO, "0x%08x: 0x%08x\n", index, value); + } + + DBGLOG(HAL, INFO, "Dump AGG CR: 820F000~820F21FF\n"); + for (index = 0x820f2000; index < 0x820f21ff; index += 4) { + HAL_MCR_RD(prAdapter, index, &value); + DBGLOG(HAL, INFO, "0x%08x: 0x%08x\n", index, value); + } + + DBGLOG(HAL, INFO, "Dump TRB\n"); + HAL_MCR_WR(prAdapter, 0x80025104, 0x02020202); + flag = 0x01010000; + for (i = 0; i < 64; i++) { + HAL_MCR_WR(prAdapter, 0x80025104, flag); + HAL_MCR_RD(prAdapter, 0x820f0024, &value); + DBGLOG(HAL, INFO, "write flag = 0x%08x, 0x820f0024: 0x%08x\n", + flag, value); + flag += 0x02020202; + } + + DBGLOG(HAL, INFO, "Dump ARB\n"); + HAL_MCR_WR(prAdapter, 0x80025104, 0x04040404); + flag = 0x01010000; + for (i = 0; i < 64; i++) { + HAL_MCR_WR(prAdapter, 0x80025104, flag); + HAL_MCR_RD(prAdapter, 0x820f0024, &value); + DBGLOG(HAL, INFO, "write flag = 0x%08x, 0x820f0024: 0x%08x\n", + flag, value); + flag += 0x02020202; + } + + DBGLOG(HAL, INFO, "Dump AGG\n"); + HAL_MCR_WR(prAdapter, 0x80025104, 0x05050505); + flag = 0x01010000; + for (i = 0; i < 64; i++) { + HAL_MCR_WR(prAdapter, 0x80025104, flag); + HAL_MCR_RD(prAdapter, 0x820f0024, &value); + DBGLOG(HAL, INFO, "write flag = 0x%08x, 0x820f0024: 0x%08x\n", + flag, value); + flag += 0x02020202; + } + + DBGLOG(HAL, INFO, "Dump DMA\n"); + HAL_MCR_WR(prAdapter, 0x80025104, 0x06060606); + flag = 0x01010000; + for (i = 0; i < 64; i++) { + HAL_MCR_WR(prAdapter, 0x80025104, flag); + HAL_MCR_RD(prAdapter, 0x820f0024, &value); + DBGLOG(HAL, INFO, "write flag = 0x%08x, 0x820f0024: 0x%08x\n", + flag, value); + flag += 0x02020202; + } + + DBGLOG(HAL, INFO, "Dump TMAC\n"); + HAL_MCR_WR(prAdapter, 0x80025104, 0x07070707); + flag = 0x01010000; + for (i = 0; i < 33; i++) { + HAL_MCR_WR(prAdapter, 0x80025104, flag); + HAL_MCR_RD(prAdapter, 0x820f0024, &value); + DBGLOG(HAL, INFO, "write flag = 0x%08x, 0x820f0024: 0x%08x\n", + flag, value); + flag += 0x02020202; + } + + DBGLOG(HAL, INFO, "Read TXV\n"); + for (i = 0x820F4120; i <= 0x820F412C; i += 4) { + HAL_MCR_RD(prAdapter, i, &value); + DBGLOG(HAL, INFO, "0x%08x: 0x%08x\n", i, value); + } + for (i = 0x820F4130; i <= 0x820F4148; i += 4) { + HAL_MCR_RD(prAdapter, i, &value); + DBGLOG(HAL, INFO, "0x%08x: 0x%08x\n", i, value); + } +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/common/hal_pdma.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/common/hal_pdma.c new file mode 100644 index 0000000000000..b0aaa728ec24e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/common/hal_pdma.c @@ -0,0 +1,2537 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** + *[File] hif_pdma.c + *[Version] v1.0 + *[Revision Date] 2015-09-08 + *[Author] + *[Description] + * The program provides PDMA HIF APIs + *[Copyright] + * Copyright (C) 2015 MediaTek Incorporation. All Rights Reserved. + ******************************************************************************/ + +/******************************************************************************* + * C O M P I L E 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 "hif_pdma.h" + +#include +#ifndef CONFIG_X86 +#include +#endif + +#include "mt66xx_reg.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define RX_RESPONSE_TIMEOUT (3000) + + +/******************************************************************************* + * 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 check is timeout or not + * + * @param u4StartTime start time + * + * @param u4Timeout timeout value + * + * @return is timeout + */ +/*----------------------------------------------------------------------------*/ +static inline bool halIsTimeout(uint32_t u4StartTime, uint32_t u4Timeout) +{ + uint32_t u4CurTime = kalGetTimeTick(); + uint32_t u4Time = 0; + + if (u4CurTime >= u4StartTime) + u4Time = u4CurTime - u4StartTime; + else + u4Time = u4CurTime + (0xFFFFFFFF - u4StartTime); + + return u4Time > u4Timeout; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t halVerifyChipID(IN struct ADAPTER *prAdapter) +{ + struct mt66xx_chip_info *prChipInfo; + struct BUS_INFO *prBusInfo; + uint32_t u4CIR = 0; + + ASSERT(prAdapter); + + prChipInfo = prAdapter->chip_info; + prBusInfo = prChipInfo->bus_info; + + if (prAdapter->fgIsReadRevID || !prChipInfo->should_verify_chip_id) + return TRUE; + + HAL_MCR_RD(prAdapter, prBusInfo->top_cfg_base + TOP_HW_CONTROL, &u4CIR); + + DBGLOG(INIT, INFO, "WCIR_CHIP_ID = 0x%x, chip_id = 0x%x\n", + (uint32_t)(u4CIR & WCIR_CHIP_ID), prChipInfo->chip_id); + + if ((u4CIR & WCIR_CHIP_ID) != prChipInfo->chip_id) + return FALSE; + + HAL_MCR_RD(prAdapter, prBusInfo->top_cfg_base + TOP_HW_VERSION, &u4CIR); + + prAdapter->ucRevID = (uint8_t)(u4CIR & 0xF); + prAdapter->fgIsReadRevID = TRUE; + + return TRUE; +} + +uint32_t halRxWaitResponse(IN struct ADAPTER *prAdapter, IN uint8_t ucPortIdx, + OUT uint8_t *pucRspBuffer, IN uint32_t u4MaxRespBufferLen, + OUT uint32_t *pu4Length) +{ + struct GLUE_INFO *prGlueInfo; + uint32_t u4PktLen = 0, u4Value = 0, u4Time; + u_int8_t fgStatus; + + DEBUGFUNC("nicRxWaitResponse"); + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + ASSERT(prGlueInfo); + ASSERT(pucRspBuffer); + ASSERT(ucPortIdx < 2); + + u4Time = kalGetTimeTick(); + u4PktLen = u4MaxRespBufferLen; + + do { + if (wlanIsChipNoAck(prAdapter)) { + DBGLOG(HAL, ERROR, "Chip No Ack\n"); + return WLAN_STATUS_FAILURE; + } + + fgStatus = kalDevPortRead( + prGlueInfo, HIF_IMG_DL_STATUS_PORT_IDX, u4PktLen, + pucRspBuffer, HIF_RX_COALESCING_BUFFER_SIZE); + if (fgStatus) { + *pu4Length = u4PktLen; + break; + } + + if (halIsTimeout(u4Time, RX_RESPONSE_TIMEOUT)) { + kalDevRegRead(prGlueInfo, CONN_HIF_ON_DBGCR01, + &u4Value); + DBGLOG(HAL, ERROR, "CONN_HIF_ON_DBGCR01[0x%x]\n", + u4Value); + return WLAN_STATUS_FAILURE; + } + + /* Response packet is not ready */ + kalUdelay(50); + } while (TRUE); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief enable global interrupt + * + * @param prAdapter pointer to the Adapter handler + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void halEnableInterrupt(IN struct ADAPTER *prAdapter) +{ + struct BUS_INFO *prBusInfo = NULL; + + ASSERT(prAdapter); + + prBusInfo = prAdapter->chip_info->bus_info; + + if (prBusInfo->enableInterrupt) + prBusInfo->enableInterrupt(prAdapter); + + prAdapter->fgIsIntEnable = TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief disable global interrupt + * + * @param prAdapter pointer to the Adapter handler + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void halDisableInterrupt(IN struct ADAPTER *prAdapter) +{ + struct BUS_INFO *prBusInfo; + + ASSERT(prAdapter); + + prBusInfo = prAdapter->chip_info->bus_info; + + if (prBusInfo->disableInterrupt) + prBusInfo->disableInterrupt(prAdapter); + + prAdapter->fgIsIntEnable = FALSE; +} + +static u_int8_t halDriverOwnCheckCR4(struct ADAPTER *prAdapter) +{ + struct mt66xx_chip_info *prChipInfo; + uint32_t u4CurrTick; + uint32_t ready_bits; + u_int8_t fgStatus = TRUE; + u_int8_t fgReady = FALSE; + u_int8_t fgDummyReq = FALSE; + bool fgTimeout; + + ASSERT(prAdapter); + + prChipInfo = prAdapter->chip_info; + ready_bits = prChipInfo->sw_ready_bits; + + HAL_WIFI_FUNC_READY_CHECK(prAdapter, + WIFI_FUNC_DUMMY_REQ, &fgDummyReq); + + u4CurrTick = kalGetTimeTick(); + /* Wait CR4 ready */ + while (1) { + fgTimeout = halIsTimeout(u4CurrTick, + LP_OWN_BACK_TOTAL_DELAY_MS); + HAL_WIFI_FUNC_READY_CHECK(prAdapter, ready_bits, &fgReady); + + if (fgReady) { + break; + } else if (kalIsCardRemoved(prAdapter->prGlueInfo) || + fgIsBusAccessFailed || fgTimeout + || wlanIsChipNoAck(prAdapter)) { + DBGLOG(INIT, INFO, + "Skip waiting CR4 ready for next %ums\n", + LP_OWN_BACK_FAILED_LOG_SKIP_MS); + fgStatus = FALSE; +#if CFG_CHIP_RESET_SUPPORT + glGetRstReason(RST_DRV_OWN_FAIL); + GL_RESET_TRIGGER(prAdapter, + RST_FLAG_CHIP_RESET); +#endif + break; + } + /* Delay for CR4 to complete its operation. */ + kalUsleep_range(LP_OWN_BACK_LOOP_DELAY_MIN_US, + LP_OWN_BACK_LOOP_DELAY_MAX_US); + } + + /* Send dummy cmd and clear flag */ + if (fgDummyReq) { + wlanSendDummyCmd(prAdapter, FALSE); + HAL_CLEAR_DUMMY_REQ(prAdapter); + } + + return fgStatus; +} + +static void halDriverOwnTimeout(struct ADAPTER *prAdapter, + uint32_t u4CurrTick, u_int8_t fgTimeout) +{ + if ((prAdapter->u4OwnFailedCount == 0) || + CHECK_FOR_TIMEOUT(u4CurrTick, prAdapter->rLastOwnFailedLogTime, + MSEC_TO_SYSTIME(LP_OWN_BACK_FAILED_LOG_SKIP_MS)) + ) { + DBGLOG(INIT, ERROR, + "LP cannot be own back, Timeout[%u](%ums), BusAccessError[%u]", + fgTimeout, + kalGetTimeTick() - u4CurrTick, + fgIsBusAccessFailed); + DBGLOG(INIT, ERROR, + "Resetting[%u], CardRemoved[%u] NoAck[%u] Cnt[%u]\n", + kalIsResetting(), + kalIsCardRemoved(prAdapter->prGlueInfo), + wlanIsChipNoAck(prAdapter), + prAdapter->u4OwnFailedCount); + + DBGLOG(INIT, INFO, + "Skip LP own back failed log for next %ums\n", + LP_OWN_BACK_FAILED_LOG_SKIP_MS); + + prAdapter->u4OwnFailedLogCount++; + if (prAdapter->u4OwnFailedLogCount > + LP_OWN_BACK_FAILED_RESET_CNT) { + halShowHostCsrInfo(prAdapter); +#if CFG_CHIP_RESET_SUPPORT + /* Trigger RESET */ + glGetRstReason(RST_DRV_OWN_FAIL); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_CHIP_RESET); +#endif + } + GET_CURRENT_SYSTIME(&prAdapter->rLastOwnFailedLogTime); + } + + prAdapter->u4OwnFailedCount++; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to process the POWER OFF procedure. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +u_int8_t halSetDriverOwn(IN struct ADAPTER *prAdapter) +{ + struct mt66xx_chip_info *prChipInfo; + struct BUS_INFO *prBusInfo; + u_int8_t fgStatus = TRUE; + uint32_t i, u4CurrTick, u4WriteTick, u4WriteTickTemp; + u_int8_t fgTimeout; + u_int8_t fgResult; + + KAL_TIME_INTERVAL_DECLARATION(); + + ASSERT(prAdapter); + + prChipInfo = prAdapter->chip_info; + prBusInfo = prChipInfo->bus_info; + + GLUE_INC_REF_CNT(prAdapter->u4PwrCtrlBlockCnt); + + if (prAdapter->fgIsFwOwn == FALSE) + return fgStatus; + + DBGLOG(INIT, TRACE, "DRIVER OWN Start\n"); + KAL_REC_TIME_START(); + + u4WriteTick = 0; + u4CurrTick = kalGetTimeTick(); + i = 0; +#if CFG_SUPPORT_PCIE_ASPM + glBusConfigASPM(prAdapter->prGlueInfo->rHifInfo.pdev->bus->self, + DISABLE_ASPM_L1); + glBusConfigASPM(prAdapter->prGlueInfo->rHifInfo.pdev, + DISABLE_ASPM_L1); +#endif + + /* PCIE/AXI need to do clear own, then could start polling status */ + HAL_LP_OWN_CLR(prAdapter, &fgResult); + fgResult = FALSE; + while (1) { + if (!prBusInfo->fgCheckDriverOwnInt || + test_bit(GLUE_FLAG_INT_BIT, &prAdapter->prGlueInfo->ulFlag)) + HAL_LP_OWN_RD(prAdapter, &fgResult); + + fgTimeout = ((kalGetTimeTick() - u4CurrTick) > + LP_OWN_BACK_TOTAL_DELAY_MS) ? TRUE : FALSE; + + if (fgResult) { + /* Check WPDMA FW own interrupt status and clear */ + if (prBusInfo->fgCheckDriverOwnInt) + HAL_MCR_WR(prAdapter, WPDMA_INT_STA, + WPDMA_FW_CLR_OWN_INT); + prAdapter->fgIsFwOwn = FALSE; + prAdapter->u4OwnFailedCount = 0; + prAdapter->u4OwnFailedLogCount = 0; + break; + } else if ((i > LP_OWN_BACK_FAILED_RETRY_CNT) && + (kalIsCardRemoved(prAdapter->prGlueInfo) || + fgIsBusAccessFailed || fgTimeout || + wlanIsChipNoAck(prAdapter))) { + halDriverOwnTimeout(prAdapter, u4CurrTick, fgTimeout); + fgStatus = FALSE; + break; + } + + u4WriteTickTemp = kalGetTimeTick(); + if ((i == 0) || TIME_AFTER(u4WriteTickTemp, + (u4WriteTick + LP_OWN_REQ_CLR_INTERVAL_MS))) { + /* Driver get LP ownership per 200 ms, + * to avoid iteration time not accurate + */ + HAL_LP_OWN_CLR(prAdapter, &fgResult); + u4WriteTick = u4WriteTickTemp; + } + + /* Delay for LP engine to complete its operation. */ + kalUsleep_range(LP_OWN_BACK_LOOP_DELAY_MIN_US, + LP_OWN_BACK_LOOP_DELAY_MAX_US); + i++; + } + + /* For Low power Test */ + /* 1. Driver need to polling until CR4 ready, + * then could do normal Tx/Rx + * 2. After CR4 ready, send a dummy command to change data path + * to store-forward mode + */ + if (prAdapter->fgIsFwDownloaded && prChipInfo->is_support_cr4) + fgStatus &= halDriverOwnCheckCR4(prAdapter); + + if (fgStatus) { + /* Check consys enter sleep mode DummyReg(0x0F) */ + if (prBusInfo->checkDummyReg) + prBusInfo->checkDummyReg(prAdapter->prGlueInfo); + } + + KAL_REC_TIME_END(); + DBGLOG(INIT, INFO, + "DRIVER OWN Done[%lu us]\n", KAL_GET_TIME_INTERVAL()); + + return fgStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to process the POWER ON procedure. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void halSetFWOwn(IN struct ADAPTER *prAdapter, IN u_int8_t fgEnableGlobalInt) +{ + struct BUS_INFO *prBusInfo; + u_int8_t fgResult; + + ASSERT(prAdapter); + ASSERT(prAdapter->u4PwrCtrlBlockCnt != 0); + + prBusInfo = prAdapter->chip_info->bus_info; + + /* Decrease Block to Enter Low Power Semaphore count */ + GLUE_DEC_REF_CNT(prAdapter->u4PwrCtrlBlockCnt); + if (!(prAdapter->fgWiFiInSleepyState && + (prAdapter->u4PwrCtrlBlockCnt == 0))) + return; + + if (prAdapter->fgIsFwOwn == TRUE) + return; + + if (nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) { + DBGLOG(INIT, STATE, "Skip FW OWN due to pending INT\n"); + /* pending interrupts */ + return; + } + + if (fgEnableGlobalInt) { + prAdapter->fgIsIntEnableWithLPOwnSet = TRUE; + } else { + /* Write sleep mode magic num to dummy reg */ + if (prBusInfo->setDummyReg) + prBusInfo->setDummyReg(prAdapter->prGlueInfo); + + HAL_LP_OWN_SET(prAdapter, &fgResult); + + prAdapter->fgIsFwOwn = TRUE; +#if CFG_SUPPORT_PCIE_ASPM + glBusConfigASPM(prAdapter->prGlueInfo->rHifInfo.pdev->bus->self, + ENABLE_ASPM_L1); + glBusConfigASPM(prAdapter->prGlueInfo->rHifInfo.pdev, + ENABLE_ASPM_L1); +#endif + DBGLOG(INIT, INFO, "FW OWN:%u\n", fgResult); + } +} + +void halWakeUpWiFi(IN struct ADAPTER *prAdapter) +{ + struct BUS_INFO *prBusInfo; + + ASSERT(prAdapter); + + prBusInfo = prAdapter->chip_info->bus_info; + if (prBusInfo->wakeUpWiFi) + prBusInfo->wakeUpWiFi(prAdapter); +} + +void halTxCancelSendingCmd(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo) +{ +} + +u_int8_t halTxIsDataBufEnough(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct RTMP_TX_RING *prTxRing; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + prTxRing = &prHifInfo->TxRing[TX_RING_DATA0_IDX_0]; + + if ((prHifInfo->u4TxDataQLen < halGetMsduTokenFreeCnt(prAdapter)) && + (prTxRing->u4UsedCnt + prHifInfo->u4TxDataQLen + 1 < TX_RING_SIZE)) + return TRUE; + + DBGLOG(HAL, TRACE, + "Low Tx Data Resource Tok[%u] Ring[%u] List[%u]\n", + halGetMsduTokenFreeCnt(prAdapter), + (TX_RING_SIZE - prTxRing->u4UsedCnt), prHifInfo->u4TxDataQLen); + return FALSE; +} + +void halProcessTxInterrupt(IN struct ADAPTER *prAdapter) +{ + struct BUS_INFO *prBusInfo = prAdapter->chip_info->bus_info; + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + union WPDMA_INT_STA_STRUCT rIntrStatus; + + rIntrStatus = (union WPDMA_INT_STA_STRUCT)prHifInfo->u4IntStatus; + + if (rIntrStatus.field.tx_done & BIT(prBusInfo->tx_ring_fwdl_idx)) + halWpdmaProcessCmdDmaDone(prAdapter->prGlueInfo, + TX_RING_FWDL_IDX_3); + + if (rIntrStatus.field.tx_done & BIT(prBusInfo->tx_ring_cmd_idx)) + halWpdmaProcessCmdDmaDone(prAdapter->prGlueInfo, + TX_RING_CMD_IDX_2); + + if (rIntrStatus.field.tx_done & BIT(prBusInfo->tx_ring_data_idx)) { + halWpdmaProcessDataDmaDone(prAdapter->prGlueInfo, + TX_RING_DATA0_IDX_0); + + kalSetTxEvent2Hif(prAdapter->prGlueInfo); + } +} + +void halInitMsduTokenInfo(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo; + struct HIF_MEM_OPS *prMemOps; + struct MSDU_TOKEN_INFO *prTokenInfo; + struct MSDU_TOKEN_ENTRY *prToken; + struct mt66xx_chip_info *prChipInfo; + uint32_t u4Idx; + uint32_t u4TxHeadRoomSize; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + prTokenInfo = &prHifInfo->rTokenInfo; + prChipInfo = prAdapter->chip_info; + + prTokenInfo->i4UsedCnt = 0; + u4TxHeadRoomSize = NIC_TX_DESC_AND_PADDING_LENGTH + + prChipInfo->txd_append_size; + + for (u4Idx = 0; u4Idx < HIF_TX_MSDU_TOKEN_NUM; u4Idx++) { + prToken = &prTokenInfo->arToken[u4Idx]; + prToken->fgInUsed = FALSE; + prToken->prMsduInfo = NULL; + +#if HIF_TX_PREALLOC_DATA_BUFFER + prToken->u4DmaLength = NIC_TX_MAX_SIZE_PER_FRAME + + u4TxHeadRoomSize; + if (prMemOps->allocTxDataBuf) + prMemOps->allocTxDataBuf(prToken, u4Idx); + + if (prToken->prPacket) { + DBGLOG(HAL, TRACE, + "Msdu Entry[0x%p] Tok[%u] Buf[0x%p] len[%u]\n", + prToken, u4Idx, prToken->prPacket, + prToken->u4DmaLength); + } else { + prTokenInfo->i4UsedCnt++; + DBGLOG(HAL, WARN, + "Msdu Token Memory alloc failed[%u]\n", + u4Idx); + continue; + } +#else + prToken->prPacket = NULL; + prToken->u4DmaLength = 0; + prToken->rDmaAddr = 0; +#endif + prToken->rPktDmaAddr = 0; + prToken->u4PktDmaLength = 0; + prToken->u4Token = u4Idx; + prToken->u4CpuIdx = TX_RING_SIZE; + + prTokenInfo->aprTokenStack[u4Idx] = prToken; + } + + spin_lock_init(&prTokenInfo->rTokenLock); + + DBGLOG(HAL, INFO, "Msdu Token Init: Tot[%u] Used[%u]\n", + HIF_TX_MSDU_TOKEN_NUM, prTokenInfo->i4UsedCnt); +} + +void halUninitMsduTokenInfo(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo; + struct HIF_MEM_OPS *prMemOps; + struct MSDU_TOKEN_INFO *prTokenInfo; + struct MSDU_TOKEN_ENTRY *prToken; + uint32_t u4Idx; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + prTokenInfo = &prHifInfo->rTokenInfo; + + for (u4Idx = 0; u4Idx < HIF_TX_MSDU_TOKEN_NUM; u4Idx++) { + prToken = &prTokenInfo->arToken[u4Idx]; + + if (prToken->fgInUsed) { + if (prMemOps->unmapTxBuf) { + prMemOps->unmapTxBuf( + prHifInfo, prToken->rPktDmaAddr, + prToken->u4PktDmaLength); + prMemOps->unmapTxBuf( + prHifInfo, prToken->rDmaAddr, + prToken->u4DmaLength); + } + + log_dbg(HAL, TRACE, "Clear pending Tok[%u] Msdu[0x%p] Free[%u]\n", + prToken->u4Token, prToken->prMsduInfo, + halGetMsduTokenFreeCnt(prAdapter)); + +#if !HIF_TX_PREALLOC_DATA_BUFFER + nicTxFreePacket(prAdapter, prToken->prMsduInfo, FALSE); + nicTxReturnMsduInfo(prAdapter, prToken->prMsduInfo); +#endif + } + +#if HIF_TX_PREALLOC_DATA_BUFFER + if (prMemOps->freeBuf) + prMemOps->freeBuf(prToken->prPacket, + prToken->u4DmaLength); + prToken->prPacket = NULL; +#endif + } + + prTokenInfo->i4UsedCnt = 0; + + DBGLOG(HAL, INFO, "Msdu Token Uninit: Tot[%u] Used[%u]\n", + HIF_TX_MSDU_TOKEN_NUM, prTokenInfo->i4UsedCnt); +} + +uint32_t halGetMsduTokenFreeCnt(IN struct ADAPTER *prAdapter) +{ + struct PERF_MONITOR_T *prPerMonitor; + struct MSDU_TOKEN_INFO *prTokenInfo = + &prAdapter->prGlueInfo->rHifInfo.rTokenInfo; + prPerMonitor = &prAdapter->rPerMonitor; + prPerMonitor->u4UsedCnt = prTokenInfo->i4UsedCnt; + + return HIF_TX_MSDU_TOKEN_NUM - prTokenInfo->i4UsedCnt; +} + +struct MSDU_TOKEN_ENTRY *halGetMsduTokenEntry(IN struct ADAPTER *prAdapter, + uint32_t u4TokenNum) +{ + struct MSDU_TOKEN_INFO *prTokenInfo = + &prAdapter->prGlueInfo->rHifInfo.rTokenInfo; + + return &prTokenInfo->arToken[u4TokenNum]; +} + +struct MSDU_TOKEN_ENTRY *halAcquireMsduToken(IN struct ADAPTER *prAdapter) +{ + struct MSDU_TOKEN_INFO *prTokenInfo = + &prAdapter->prGlueInfo->rHifInfo.rTokenInfo; + struct MSDU_TOKEN_ENTRY *prToken; + unsigned long flags = 0; + + if (!halGetMsduTokenFreeCnt(prAdapter)) { + DBGLOG(HAL, INFO, "No more free MSDU token, Used[%u]\n", + prTokenInfo->i4UsedCnt); + return NULL; + } + + spin_lock_irqsave(&prTokenInfo->rTokenLock, flags); + + prToken = prTokenInfo->aprTokenStack[prTokenInfo->i4UsedCnt]; + do_gettimeofday(&prToken->rTs); + prToken->fgInUsed = TRUE; + prTokenInfo->i4UsedCnt++; + + spin_unlock_irqrestore(&prTokenInfo->rTokenLock, flags); + + DBGLOG_LIMITED(HAL, TRACE, + "Acquire Entry[0x%p] Tok[%u] Buf[%p] Len[%u]\n", + prToken, prToken->u4Token, + prToken->prPacket, prToken->u4DmaLength); + + return prToken; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Reset all msdu token. Return used msdu & re-init token. + * + * @param prAdapter a pointer to adapter private data structure. + * + */ +/*----------------------------------------------------------------------------*/ + +static void halResetMsduToken(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo; + struct HIF_MEM_OPS *prMemOps; + struct MSDU_TOKEN_INFO *prTokenInfo; + struct MSDU_TOKEN_ENTRY *prToken; + uint32_t u4Idx = 0; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + prTokenInfo = &prHifInfo->rTokenInfo; + + for (u4Idx = 0; u4Idx < HIF_TX_MSDU_TOKEN_NUM; u4Idx++) { + prToken = &prTokenInfo->arToken[u4Idx]; + if (prToken->fgInUsed) { + if (prMemOps->unmapTxBuf) { + prMemOps->unmapTxBuf( + prHifInfo, prToken->rPktDmaAddr, + prToken->u4PktDmaLength); + prMemOps->unmapTxBuf( + prHifInfo, prToken->rDmaAddr, + prToken->u4DmaLength); + prToken->rPktDmaAddr = 0; + prToken->u4PktDmaLength = 0; + prToken->rDmaAddr = 0; + } + +#if !HIF_TX_PREALLOC_DATA_BUFFER + nicTxFreePacket(prAdapter, prToken->prMsduInfo, FALSE); + nicTxReturnMsduInfo(prAdapter, prToken->prMsduInfo); +#endif + } + + prToken->fgInUsed = FALSE; + prTokenInfo->aprTokenStack[u4Idx] = prToken; + } + prTokenInfo->i4UsedCnt = 0; +} + +void halReturnMsduToken(IN struct ADAPTER *prAdapter, uint32_t u4TokenNum) +{ + struct MSDU_TOKEN_INFO *prTokenInfo = + &prAdapter->prGlueInfo->rHifInfo.rTokenInfo; + struct MSDU_TOKEN_ENTRY *prToken; + unsigned long flags = 0; + + if (!prTokenInfo->i4UsedCnt) { + DBGLOG(HAL, INFO, "MSDU token is full, Used[%u]\n", + prTokenInfo->i4UsedCnt); + return; + } + + prToken = &prTokenInfo->arToken[u4TokenNum]; + if (!prToken->fgInUsed) { + DBGLOG(HAL, ERROR, "Return unuse token[%u]\n", u4TokenNum); + return; + } + + spin_lock_irqsave(&prTokenInfo->rTokenLock, flags); + + prToken->fgInUsed = FALSE; + prTokenInfo->i4UsedCnt--; + prTokenInfo->aprTokenStack[prTokenInfo->i4UsedCnt] = prToken; + + spin_unlock_irqrestore(&prTokenInfo->rTokenLock, flags); +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Return all timeout msdu token. + * + * @param prAdapter a pointer to adapter private data structure. + * + */ +/*----------------------------------------------------------------------------*/ +void halReturnTimeoutMsduToken(struct ADAPTER *prAdapter) +{ + struct MSDU_TOKEN_INFO *prTokenInfo; + struct MSDU_TOKEN_ENTRY *prToken; + struct timeval rNowTs, rTime; + struct timeval rTimeout; + uint32_t u4Idx = 0; + + ASSERT(prAdapter); + ASSERT(prAdapter->prGlueInfo); + + prTokenInfo = &prAdapter->prGlueInfo->rHifInfo.rTokenInfo; + + rTimeout.tv_sec = HIF_MSDU_REPORT_RETURN_TIMEOUT; + rTimeout.tv_usec = 0; + do_gettimeofday(&rNowTs); + + for (u4Idx = 0; u4Idx < HIF_TX_MSDU_TOKEN_NUM; u4Idx++) { + prToken = &prTokenInfo->arToken[u4Idx]; + if (!prToken->fgInUsed) + continue; + + /* Ignore now time < token time */ + if (halTimeCompare(&rNowTs, &prToken->rTs) < 0) + continue; + + rTime.tv_sec = rNowTs.tv_sec - prToken->rTs.tv_sec; + rTime.tv_usec = rNowTs.tv_usec; + if (prToken->rTs.tv_usec > rNowTs.tv_usec) { + rTime.tv_sec -= 1; + rTime.tv_usec += SEC_TO_USEC(1); + } + rTime.tv_usec -= prToken->rTs.tv_usec; + + /* Return token to free stack */ + if (halTimeCompare(&rTime, &rTimeout) >= 0) { + DBGLOG(HAL, INFO, + "Free TokenId[%u] timeout[sec:%u, usec:%u]\n", + u4Idx, rTime.tv_sec, rTime.tv_usec); + halReturnMsduToken(prAdapter, u4Idx); + } + } +} + +bool halHifSwInfoInit(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + asicPcieDmaShdlInit(prAdapter); + + if (!halWpdmaAllocRing(prAdapter->prGlueInfo, true)) + return false; + + halWpdmaInitRing(prAdapter->prGlueInfo); + halInitMsduTokenInfo(prAdapter); + + prHifInfo->fgIsPowerOff = false; + + return true; +} + +void halRxProcessMsduReport(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb) +{ + struct GL_HIF_INFO *prHifInfo; + struct HIF_MEM_OPS *prMemOps; + struct RTMP_DMACB *prTxCell; + struct RTMP_TX_RING *prTxRing; + struct HW_MAC_MSDU_REPORT *prMsduReport; + struct MSDU_TOKEN_ENTRY *prTokenEntry; +#if !HIF_TX_PREALLOC_DATA_BUFFER + struct MSDU_INFO *prMsduInfo; +#endif + struct QUE rFreeQueue; + struct QUE *prFreeQueue; + uint16_t u2TokenCnt; + uint32_t u4Idx, u4Token; + + ASSERT(prAdapter); + ASSERT(prAdapter->prGlueInfo); + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + prTxRing = &prHifInfo->TxRing[TX_RING_DATA0_IDX_0]; + prMemOps = &prHifInfo->rMemOps; + + prFreeQueue = &rFreeQueue; + QUEUE_INITIALIZE(prFreeQueue); + + prMsduReport = (struct HW_MAC_MSDU_REPORT *)prSwRfb->pucRecvBuff; + u2TokenCnt = prMsduReport->u2MsduCount; + + for (u4Idx = 0; u4Idx < u2TokenCnt; u4Idx++) { + if (prMsduReport->u4Ver == 0) + u4Token = prMsduReport->au4MsduToken[u4Idx >> 1]. + rFormatV1.u2MsduID[u4Idx & 1]; + else + u4Token = prMsduReport->au4MsduToken[u4Idx]. + rFormatV2.u2MsduID; + + if (u4Token >= HIF_TX_MSDU_TOKEN_NUM) { + DBGLOG(HAL, ERROR, "Error MSDU report[%u]\n", u4Token); + DBGLOG_MEM32(HAL, ERROR, prMsduReport, 64); + prAdapter->u4HifDbgFlag |= DEG_HIF_DEFAULT_DUMP; + halPrintHifDbgInfo(prAdapter); + return; + } + + prTokenEntry = halGetMsduTokenEntry(prAdapter, u4Token); + +#if HIF_TX_PREALLOC_DATA_BUFFER + DBGLOG_LIMITED(HAL, TRACE, + "MsduRpt: Cnt[%u] Tok[%u] Free[%u]\n", + u2TokenCnt, u4Token, + halGetMsduTokenFreeCnt(prAdapter)); +#else + prMsduInfo = prTokenEntry->prMsduInfo; + prMsduInfo->prToken = NULL; + if (!prMsduInfo->pfTxDoneHandler) + QUEUE_INSERT_TAIL(prFreeQueue, + (struct QUE_ENTRY *) prMsduInfo); + + DBGLOG_LIMITED(HAL, TRACE, + "MsduRpt: Cnt[%u] Tok[%u] Msdu[0x%p] TxDone[%u] Free[%u]\n", + u2TokenCnt, u4Token, prMsduInfo, + (prMsduInfo->pfTxDoneHandler ? TRUE : FALSE), + halGetMsduTokenFreeCnt(prAdapter)); +#endif + if (prMemOps->unmapTxBuf) { + prMemOps->unmapTxBuf(prHifInfo, + prTokenEntry->rPktDmaAddr, + prTokenEntry->u4PktDmaLength); + prMemOps->unmapTxBuf(prHifInfo, + prTokenEntry->rDmaAddr, + prTokenEntry->u4DmaLength); + } + + if (prTokenEntry->u4CpuIdx < TX_RING_SIZE) { + prTxCell = &prTxRing->Cell[prTokenEntry->u4CpuIdx]; + prTxCell->prToken = NULL; + } + prTokenEntry->u4CpuIdx = TX_RING_SIZE; + halReturnMsduToken(prAdapter, u4Token); + } + +#if !HIF_TX_PREALLOC_DATA_BUFFER + nicTxMsduDoneCb(prAdapter->prGlueInfo, prFreeQueue); +#endif + + /* Indicate Service Thread */ + if (wlanGetTxPendingFrameCount(prAdapter) > 0) + kalSetEvent(prAdapter->prGlueInfo); + + kalSetTxEvent2Hif(prAdapter->prGlueInfo); +} + +void halTxUpdateCutThroughDesc(struct GLUE_INFO *prGlueInfo, + struct MSDU_INFO *prMsduInfo, + struct MSDU_TOKEN_ENTRY *prFillToken, + struct MSDU_TOKEN_ENTRY *prDataToken, + uint32_t u4Idx, bool fgIsLast) +{ + struct GL_HIF_INFO *prHifInfo; + struct HIF_MEM_OPS *prMemOps; + struct mt66xx_chip_info *prChipInfo; + struct TX_DESC_OPS_T *prTxDescOps; + uint8_t *pucBufferTxD; + uint32_t u4TxHeadRoomSize; + phys_addr_t rPhyAddr = 0; + + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + prChipInfo = prGlueInfo->prAdapter->chip_info; + prTxDescOps = prChipInfo->prTxDescOps; + pucBufferTxD = prDataToken->prPacket; + u4TxHeadRoomSize = NIC_TX_DESC_AND_PADDING_LENGTH + + prChipInfo->txd_append_size; + + if (prMemOps->mapTxBuf) { + rPhyAddr = prMemOps->mapTxBuf( + prHifInfo, pucBufferTxD, u4TxHeadRoomSize, + prMsduInfo->u2FrameLength); + } else { + if (prDataToken->rDmaAddr) + rPhyAddr = prDataToken->rDmaAddr + u4TxHeadRoomSize; + } + + if (!rPhyAddr) { + DBGLOG(HAL, ERROR, "Get address error!\n"); + return; + } + + if (prTxDescOps->fillHifAppend) + prTxDescOps->fillHifAppend(prGlueInfo->prAdapter, + prMsduInfo, prDataToken->u4Token, + rPhyAddr, u4Idx, fgIsLast, prFillToken->prPacket); + + prDataToken->rPktDmaAddr = rPhyAddr; + prDataToken->u4PktDmaLength = prMsduInfo->u2FrameLength; +} + +uint32_t halTxGetPageCount(IN struct ADAPTER *prAdapter, + IN uint32_t u4FrameLength, IN u_int8_t fgIncludeDesc) +{ + return 1; +} + +uint32_t halTxPollingResource(IN struct ADAPTER *prAdapter, IN uint8_t ucTC) +{ + return WLAN_STATUS_SUCCESS; +} + +void halSerHifReset(IN struct ADAPTER *prAdapter) +{ +} + +void halRxReceiveRFBs(IN struct ADAPTER *prAdapter, uint32_t u4Port) +{ + struct RX_CTRL *prRxCtrl; + struct SW_RFB *prSwRfb = (struct SW_RFB *) NULL; + uint8_t *pucBuf = NULL; + struct HW_MAC_RX_DESC *prRxStatus; + u_int8_t fgStatus; + uint32_t u4RxCnt; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxPCIeReceiveRFBs"); + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + u4RxCnt = halWpdmaGetRxDmaDoneCnt(prAdapter->prGlueInfo, u4Port); + + while (u4RxCnt--) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, + prSwRfb, struct SW_RFB *); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + if (!prSwRfb) { + DBGLOG(RX, WARN, "No More RFB for P[%u]\n", u4Port); + break; + } + + if (u4Port == RX_RING_DATA_IDX_0) { + fgStatus = kalDevReadData(prAdapter->prGlueInfo, + u4Port, prSwRfb); + } else { + pucBuf = prSwRfb->pucRecvBuff; + ASSERT(pucBuf); + + fgStatus = kalDevPortRead(prAdapter->prGlueInfo, + u4Port, CFG_RX_MAX_PKT_SIZE, + pucBuf, CFG_RX_MAX_PKT_SIZE); + } + if (!fgStatus) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_INSERT_TAIL(&prRxCtrl->rFreeSwRfbList, + &prSwRfb->rQueEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + continue; + } + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + prSwRfb->ucPacketType = (uint8_t) + HAL_RX_STATUS_GET_PKT_TYPE(prRxStatus); + DBGLOG_LIMITED(RX, LOUD, "ucPacketType = %u, ucSecMode = %u\n", + prSwRfb->ucPacketType, + (uint8_t)HAL_RX_STATUS_GET_SEC_MODE( + prRxStatus)); + + if (prSwRfb->ucPacketType == RX_PKT_TYPE_MSDU_REPORT) { + nicRxProcessMsduReport(prAdapter, prSwRfb); + + continue; + } + + GLUE_RX_SET_PKT_INT_TIME(prSwRfb->pvPacket, + prAdapter->prGlueInfo->u8HifIntTime); + GLUE_RX_SET_PKT_RX_TIME(prSwRfb->pvPacket, sched_clock()); + + prSwRfb->ucStaRecIdx = + secGetStaIdxByWlanIdx(prAdapter, + (uint8_t)HAL_RX_STATUS_GET_WLAN_IDX( + prRxStatus)); + + 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); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Read frames from the data port for PCIE + * I/F, fill RFB and put each frame into the rReceivedRFBList queue. + * + * @param prAdapter Pointer to the Adapter structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void halProcessRxInterrupt(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + union WPDMA_INT_STA_STRUCT rIntrStatus; + + rIntrStatus = (union WPDMA_INT_STA_STRUCT)prHifInfo->u4IntStatus; + prAdapter->prGlueInfo->u8HifIntTime = sched_clock(); + + if (rIntrStatus.field.rx_done_1) + halRxReceiveRFBs(prAdapter, RX_RING_EVT_IDX_1); + + if (rIntrStatus.field.rx_done_0) + halRxReceiveRFBs(prAdapter, RX_RING_DATA_IDX_0); +} + +static int32_t halWpdmaFreeRingDesc(struct GLUE_INFO *prGlueInfo, + struct RTMP_DMABUF *prDescRing) +{ + struct GL_HIF_INFO *prHifInfo; + struct HIF_MEM_OPS *prMemOps; + + ASSERT(prGlueInfo); + + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + + if (prMemOps->freeDesc) + prMemOps->freeDesc(prHifInfo, prDescRing); + + return TRUE; +} + +bool halWpdmaAllocTxRing(struct GLUE_INFO *prGlueInfo, uint32_t u4Num, + uint32_t u4Size, uint32_t u4DescSize, bool fgAllocMem) +{ + struct GL_HIF_INFO *prHifInfo; + struct HIF_MEM_OPS *prMemOps; + struct RTMP_TX_RING *pTxRing; + struct RTMP_DMABUF *prTxDesc; + struct RTMP_DMACB *prTxCell; + phys_addr_t RingBasePa; + void *RingBaseVa; + uint32_t u4Idx; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + prTxDesc = &prHifInfo->TxDescRing[u4Num]; + + /* Don't re-alloc memory when second time call alloc ring */ + prTxDesc->AllocSize = u4Size * u4DescSize; + if (fgAllocMem && prMemOps->allocTxDesc) + prMemOps->allocTxDesc(prHifInfo, prTxDesc, u4Num); + + if (prTxDesc->AllocVa == NULL) { + DBGLOG(HAL, ERROR, "TxDescRing[%d] allocation failed\n", u4Num); + return false; + } + + DBGLOG(HAL, TRACE, "TxDescRing[%p]: total %lu bytes allocated\n", + prTxDesc->AllocVa, prTxDesc->AllocSize); + + /* Save PA & VA for further operation */ + RingBasePa = prTxDesc->AllocPa; + RingBaseVa = prTxDesc->AllocVa; + + /* + * Initialize Tx Ring Descriptor and associated buffer memory + */ + pTxRing = &prHifInfo->TxRing[u4Num]; + for (u4Idx = 0; u4Idx < u4Size; u4Idx++) { + prTxCell = &pTxRing->Cell[u4Idx]; + prTxCell->pPacket = NULL; + prTxCell->pBuffer = NULL; + + /* Init Tx Ring Size, Va, Pa variables */ + prTxCell->AllocSize = u4DescSize; + prTxCell->AllocVa = RingBaseVa; + prTxCell->AllocPa = RingBasePa; + prTxCell->prToken = NULL; + + RingBasePa += u4DescSize; + RingBaseVa += u4DescSize; + + if (fgAllocMem && prMemOps->allocTxCmdBuf) + prMemOps->allocTxCmdBuf(&prTxCell->DmaBuf, + u4Num, u4Idx); + } + + DBGLOG(HAL, TRACE, "TxRing[%d]: total %d entry allocated\n", + u4Num, u4Idx); + + return true; +} + +bool halWpdmaAllocRxRing(struct GLUE_INFO *prGlueInfo, uint32_t u4Num, + uint32_t u4Size, uint32_t u4DescSize, + uint32_t u4BufSize, bool fgAllocMem) +{ + struct GL_HIF_INFO *prHifInfo; + struct HIF_MEM_OPS *prMemOps; + struct RTMP_RX_RING *pRxRing; + struct RTMP_DMABUF *prRxDesc; + struct RTMP_DMABUF *pDmaBuf; + struct RTMP_DMACB *prRxCell; + struct RXD_STRUCT *pRxD; + phys_addr_t RingBasePa; + void *RingBaseVa; + uint32_t u4Idx; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + prRxDesc = &prHifInfo->RxDescRing[u4Num]; + + /* Don't re-alloc memory when second time call alloc ring */ + prRxDesc->AllocSize = u4Size * u4DescSize; + if (fgAllocMem && prMemOps->allocRxDesc) + prMemOps->allocRxDesc(prHifInfo, prRxDesc, u4Num); + + if (prRxDesc->AllocVa == NULL) { + DBGLOG(HAL, ERROR, "RxDescRing allocation failed!!\n"); + return false; + } + + DBGLOG(HAL, TRACE, "RxDescRing[%p]: total %lu bytes allocated\n", + prRxDesc->AllocVa, prRxDesc->AllocSize); + + /* Initialize Rx Ring and associated buffer memory */ + RingBasePa = prRxDesc->AllocPa; + RingBaseVa = prRxDesc->AllocVa; + + pRxRing = &prHifInfo->RxRing[u4Num]; + pRxRing->u4BufSize = u4BufSize; + pRxRing->u4RingSize = u4Size; + pRxRing->fgRxSegPkt = FALSE; + + for (u4Idx = 0; u4Idx < u4Size; u4Idx++) { + /* Init RX Ring Size, Va, Pa variables */ + prRxCell = &pRxRing->Cell[u4Idx]; + prRxCell->AllocSize = u4DescSize; + prRxCell->AllocVa = RingBaseVa; + prRxCell->AllocPa = RingBasePa; + prRxCell->prToken = NULL; + + /* Offset to next ring descriptor address */ + RingBasePa += u4DescSize; + RingBaseVa += u4DescSize; + + /* Setup Rx associated Buffer size & allocate share memory */ + pDmaBuf = &prRxCell->DmaBuf; + pDmaBuf->AllocSize = u4BufSize; + + if (fgAllocMem && prMemOps->allocRxBuf) + prRxCell->pPacket = prMemOps->allocRxBuf( + prHifInfo, pDmaBuf, u4Num, u4Idx); + if (pDmaBuf->AllocVa == NULL) { + log_dbg(HAL, ERROR, "\nFailed to allocate RxRing buffer idx[%u]\n", + u4Idx); + return false; + } + + /* Write RxD buffer address & allocated buffer length */ + pRxD = (struct RXD_STRUCT *)prRxCell->AllocVa; + pRxD->SDPtr0 = ((uint64_t)pDmaBuf->AllocPa) & + DMA_LOWER_32BITS_MASK; + pRxD->SDPtr1 = (((uint64_t)pDmaBuf->AllocPa >> + DMA_BITS_OFFSET) & DMA_HIGHER_4BITS_MASK); + pRxD->SDLen0 = u4BufSize; + pRxD->DMADONE = 0; + } + + DBGLOG(HAL, TRACE, "Rx[%d] Ring: total %d entry allocated\n", + u4Num, u4Idx); + + return true; +} + +void halHifRst(struct GLUE_INFO *prGlueInfo) +{ + /* Reset dmashdl and wpdma */ + kalDevRegWrite(prGlueInfo, CONN_HIF_RST, 0x00000000); + kalDevRegWrite(prGlueInfo, CONN_HIF_RST, 0x00000030); +} + +bool halWpdmaAllocRing(struct GLUE_INFO *prGlueInfo, bool fgAllocMem) +{ + struct GL_HIF_INFO *prHifInfo; + int32_t u4Num, u4Index; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + /* + * Allocate all ring descriptors, include TxD, RxD, MgmtD. + * Although each size is different, to prevent cacheline and alignment + * issue, I intentional set them all to 64 bytes + */ + for (u4Num = 0; u4Num < NUM_OF_TX_RING; u4Num++) { + if (!halWpdmaAllocTxRing(prGlueInfo, u4Num, TX_RING_SIZE, + TXD_SIZE, fgAllocMem)) { + DBGLOG(HAL, ERROR, "AllocTxRing[%d] fail\n", u4Num); + return false; + } + } + + /* Data Rx path */ + if (!halWpdmaAllocRxRing(prGlueInfo, RX_RING_DATA_IDX_0, + RX_RING0_SIZE, RXD_SIZE, + CFG_RX_MAX_PKT_SIZE, fgAllocMem)) { + DBGLOG(HAL, ERROR, "AllocRxRing[0] fail\n"); + return false; + } + /* Event Rx path */ + if (!halWpdmaAllocRxRing(prGlueInfo, RX_RING_EVT_IDX_1, + RX_RING1_SIZE, RXD_SIZE, + RX_BUFFER_AGGRESIZE, fgAllocMem)) { + DBGLOG(HAL, ERROR, "AllocRxRing[1] fail\n"); + return false; + } + + /* Initialize all transmit related software queues */ + + /* Init TX rings index pointer */ + for (u4Index = 0; u4Index < NUM_OF_TX_RING; u4Index++) { + prHifInfo->TxRing[u4Index].TxSwUsedIdx = 0; + prHifInfo->TxRing[u4Index].TxCpuIdx = 0; + } + + return true; +} + +void halWpdmaFreeRing(struct GLUE_INFO *prGlueInfo) +{ + struct GL_HIF_INFO *prHifInfo; + struct HIF_MEM_OPS *prMemOps; + struct RTMP_TX_RING *pTxRing; + struct RTMP_RX_RING *pRxRing; + struct TXD_STRUCT *pTxD; + struct RTMP_DMACB *prDmaCb; + void *pPacket, *pBuffer; + uint32_t i, j; + + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + + /* Free Tx Ring Packet */ + for (i = 0; i < NUM_OF_TX_RING; i++) { + pTxRing = &prHifInfo->TxRing[i]; + for (j = 0; j < TX_RING_SIZE; j++) { + pTxD = (struct TXD_STRUCT *) (pTxRing->Cell[j].AllocVa); + + pPacket = pTxRing->Cell[j].pPacket; + pBuffer = pTxRing->Cell[j].pBuffer; + if (prMemOps->unmapTxBuf && pPacket) + prMemOps->unmapTxBuf( + prHifInfo, pTxRing->Cell[j].PacketPa, + pTxD->SDLen0); + pTxRing->Cell[j].pPacket = NULL; + + if (prMemOps->freeBuf && pBuffer) + prMemOps->freeBuf(pBuffer, pTxD->SDLen0); + pTxRing->Cell[j].pBuffer = NULL; + } + + halWpdmaFreeRingDesc(prGlueInfo, &prHifInfo->TxDescRing[i]); + } + + for (i = 0; i < NUM_OF_RX_RING; i++) { + pRxRing = &prHifInfo->RxRing[i]; + for (j = 0; j < pRxRing->u4RingSize; j++) { + prDmaCb = &pRxRing->Cell[j]; + if (prMemOps->unmapRxBuf && prDmaCb->DmaBuf.AllocVa) + prMemOps->unmapRxBuf(prHifInfo, + prDmaCb->DmaBuf.AllocPa, + prDmaCb->DmaBuf.AllocSize); + if (prMemOps->freePacket && prDmaCb->pPacket) + prMemOps->freePacket(prDmaCb->pPacket); + } + + halWpdmaFreeRingDesc(prGlueInfo, &prHifInfo->RxDescRing[i]); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief enable firmware download. + * + * @param[in] fgEnable 1 for fw download, 0 for normal data operation. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void halEnableFWDownload(IN struct ADAPTER *prAdapter, IN u_int8_t fgEnable) +{ + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + + prChipInfo = prAdapter->chip_info; + + if (prChipInfo->asicEnableFWDownload) + prChipInfo->asicEnableFWDownload(prAdapter, fgEnable); +} + +static u_int8_t halWpdmaWaitIdle(struct GLUE_INFO *prGlueInfo, + int32_t round, int32_t wait_us) +{ + int32_t i = 0; + union WPDMA_GLO_CFG_STRUCT GloCfg; + + do { + kalDevRegRead(prGlueInfo, WPDMA_GLO_CFG, &GloCfg.word); + if ((GloCfg.field.TxDMABusy == 0) && + (GloCfg.field.RxDMABusy == 0)) { + DBGLOG(HAL, TRACE, + "==> DMAIdle, GloCfg=0x%x\n", GloCfg.word); + return TRUE; + } + kalUdelay(wait_us); + } while ((i++) < round); + + DBGLOG(HAL, INFO, "==> DMABusy, GloCfg=0x%x\n", GloCfg.word); + + return FALSE; +} + +void halWpdmaInitRing(struct GLUE_INFO *prGlueInfo) +{ + struct GL_HIF_INFO *prHifInfo; + struct BUS_INFO *prBusInfo; + + ASSERT(prGlueInfo); + + prHifInfo = &prGlueInfo->rHifInfo; + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + + /* Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits */ + if (prBusInfo->pdmaSetup) + prBusInfo->pdmaSetup(prGlueInfo, FALSE); + + halWpdmaWaitIdle(prGlueInfo, 100, 1000); + + /* Reset DMA Index */ + kalDevRegWrite(prGlueInfo, WPDMA_RST_PTR, 0xFFFFFFFF); + + halWpdmaInitTxRing(prGlueInfo); + + /* Init RX Ring0 Base/Size/Index pointer CSR */ + halWpdmaInitRxRing(prGlueInfo); + + if (prBusInfo->pdmaSetup) + prBusInfo->pdmaSetup(prGlueInfo, TRUE); + + /* Write sleep mode magic num to dummy reg */ + if (prBusInfo->setDummyReg) + prBusInfo->setDummyReg(prGlueInfo); +} + +void halWpdmaInitTxRing(IN struct GLUE_INFO *prGlueInfo) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct BUS_INFO *prBusInfo = NULL; + struct RTMP_TX_RING *prTxRing = NULL; + struct RTMP_DMACB *prTxCell; + uint32_t i = 0, offset = 0, phy_addr = 0; + uint32_t phy_addr_ext = 0, ext_offset = 0; + + prHifInfo = &prGlueInfo->rHifInfo; + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + + /* reset all TX Ring register */ + for (i = 0; i < NUM_OF_TX_RING; i++) { + prTxRing = &prHifInfo->TxRing[i]; + prTxCell = &prTxRing->Cell[0]; + if (i == TX_RING_CMD_IDX_2) + offset = prBusInfo->tx_ring_cmd_idx * MT_RINGREG_DIFF; + else + offset = i * MT_RINGREG_DIFF; + phy_addr = ((uint64_t)prTxCell->AllocPa) & + DMA_LOWER_32BITS_MASK; + phy_addr_ext = (((uint64_t)prTxCell->AllocPa >> + DMA_BITS_OFFSET) & DMA_HIGHER_4BITS_MASK); + ext_offset = i * MT_RINGREG_EXT_DIFF; + prTxRing->TxSwUsedIdx = 0; + prTxRing->u4UsedCnt = 0; + prTxRing->TxCpuIdx = 0; + prTxRing->hw_desc_base = MT_TX_RING_BASE + offset; + prTxRing->hw_desc_base_ext = MT_TX_RING_BASE_EXT + ext_offset; + prTxRing->hw_cidx_addr = MT_TX_RING_CIDX + offset; + prTxRing->hw_didx_addr = MT_TX_RING_DIDX + offset; + prTxRing->hw_cnt_addr = MT_TX_RING_CNT + offset; + kalDevRegWrite(prGlueInfo, prTxRing->hw_desc_base, phy_addr); + kalDevRegWrite(prGlueInfo, prTxRing->hw_desc_base_ext, + phy_addr_ext); + kalDevRegWrite(prGlueInfo, prTxRing->hw_cidx_addr, + prTxRing->TxCpuIdx); + kalDevRegWrite(prGlueInfo, prTxRing->hw_cnt_addr, + TX_RING_SIZE); + + DBGLOG(HAL, TRACE, "-->TX_RING_%d[0x%x]: Base=0x%x, Cnt=%d!\n", + i, prHifInfo->TxRing[i].hw_desc_base, + phy_addr, TX_RING_SIZE); + } +} + +void halWpdmaInitRxRing(IN struct GLUE_INFO *prGlueInfo) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct RTMP_RX_RING *prRxRing = NULL; + uint32_t i = 0, offset = 0, phy_addr = 0; + uint32_t phy_addr_ext = 0, ext_offset = 0; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + /* reset all RX Ring register */ + for (i = 0; i < NUM_OF_RX_RING; i++) { + prRxRing = &prHifInfo->RxRing[i]; + offset = i * MT_RINGREG_DIFF; + phy_addr = ((uint64_t)prRxRing->Cell[0].AllocPa & + DMA_LOWER_32BITS_MASK); + phy_addr_ext = (((uint64_t)prRxRing->Cell[0].AllocPa >> + DMA_BITS_OFFSET) & DMA_HIGHER_4BITS_MASK); + ext_offset = i * MT_RINGREG_EXT_DIFF; + prRxRing->RxCpuIdx = prRxRing->u4RingSize - 1; + prRxRing->hw_desc_base = MT_RX_RING_BASE + offset; + prRxRing->hw_desc_base_ext = MT_RX_RING_BASE_EXT + ext_offset; + prRxRing->hw_cidx_addr = MT_RX_RING_CIDX + offset; + prRxRing->hw_didx_addr = MT_RX_RING_DIDX + offset; + prRxRing->hw_cnt_addr = MT_RX_RING_CNT + offset; + kalDevRegWrite(prGlueInfo, prRxRing->hw_desc_base, phy_addr); + kalDevRegWrite(prGlueInfo, prRxRing->hw_desc_base_ext, + phy_addr_ext); + kalDevRegWrite(prGlueInfo, prRxRing->hw_cidx_addr, + prRxRing->RxCpuIdx); + kalDevRegWrite(prGlueInfo, prRxRing->hw_cnt_addr, + prRxRing->u4RingSize); + + prRxRing->fgIsDumpLog = false; + + DBGLOG(HAL, TRACE, "-->RX_RING_%d[0x%x]: Base=0x%x, Cnt=%d\n", + i, prRxRing->hw_desc_base, + phy_addr, prRxRing->u4RingSize); + } +} + +void halWpdmaProcessCmdDmaDone(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct HIF_MEM_OPS *prMemOps; + struct RTMP_TX_RING *prTxRing; + struct TXD_STRUCT *pTxD; + phys_addr_t PacketPa = 0; + void *pBuffer = NULL; + uint32_t u4SwIdx, u4DmaIdx; + + ASSERT(prGlueInfo); + + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + prTxRing = &prHifInfo->TxRing[u2Port]; + + kalDevRegRead(prGlueInfo, prTxRing->hw_didx_addr, &u4DmaIdx); + u4SwIdx = prTxRing->TxSwUsedIdx; + + do { + pBuffer = prTxRing->Cell[u4SwIdx].pBuffer; + PacketPa = prTxRing->Cell[u4SwIdx].PacketPa; + pTxD = (struct TXD_STRUCT *) prTxRing->Cell[u4SwIdx].AllocVa; + + if (pTxD->DMADONE == 0) + break; + + log_dbg(HAL, TRACE, "DMA done: port[%u] dma[%u] idx[%u] done[%u] pkt[0x%p] used[%u]\n", + u2Port, u4DmaIdx, u4SwIdx, pTxD->DMADONE, + prTxRing->Cell[u4SwIdx].pPacket, prTxRing->u4UsedCnt); + + if (prMemOps->unmapTxBuf && PacketPa) + prMemOps->unmapTxBuf(prHifInfo, PacketPa, pTxD->SDLen0); + + pTxD->DMADONE = 0; + if (prMemOps->freeBuf && pBuffer) + prMemOps->freeBuf(pBuffer, 0); + prTxRing->Cell[u4SwIdx].pBuffer = NULL; + prTxRing->Cell[u4SwIdx].pPacket = NULL; + prTxRing->u4UsedCnt--; + + if (u2Port == TX_RING_CMD_IDX_2) + nicTxReleaseResource_PSE(prGlueInfo->prAdapter, + TC4_INDEX, + nicTxGetPageCount(prGlueInfo->prAdapter, + pTxD->SDLen0, TRUE), TRUE); + + INC_RING_INDEX(u4SwIdx, TX_RING_SIZE); + } while (u4SwIdx != u4DmaIdx); + + prTxRing->TxSwUsedIdx = u4SwIdx; + +} + +void halWpdmaProcessDataDmaDone(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + uint32_t u4SwIdx, u4DmaIdx; + struct RTMP_TX_RING *prTxRing; + + ASSERT(prGlueInfo); + + prHifInfo = &prGlueInfo->rHifInfo; + prTxRing = &prHifInfo->TxRing[u2Port]; + + kalDevRegRead(prGlueInfo, prTxRing->hw_didx_addr, &u4DmaIdx); + u4SwIdx = prTxRing->TxSwUsedIdx; + + if (u4DmaIdx > u4SwIdx) + prTxRing->u4UsedCnt -= u4DmaIdx - u4SwIdx; + else if (u4DmaIdx < u4SwIdx) + prTxRing->u4UsedCnt -= (TX_RING_SIZE + u4DmaIdx) - u4SwIdx; + else { + /* DMA index == SW used index */ + if (prTxRing->u4UsedCnt == TX_RING_SIZE) + prTxRing->u4UsedCnt = 0; + } + + DBGLOG(HAL, TRACE, + "DMA done: port[%u] dma[%u] idx[%u] used[%u]\n", u2Port, + u4DmaIdx, u4SwIdx, prTxRing->u4UsedCnt); + + prTxRing->TxSwUsedIdx = u4DmaIdx; +} + +uint32_t halWpdmaGetRxDmaDoneCnt(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRingNum) +{ + struct RTMP_RX_RING *prRxRing; + struct GL_HIF_INFO *prHifInfo; + uint32_t u4MaxCnt, u4CpuIdx, u4DmaIdx, u4RxPktCnt; + + prHifInfo = &prGlueInfo->rHifInfo; + prRxRing = &prHifInfo->RxRing[ucRingNum]; + + kalDevRegRead(prGlueInfo, prRxRing->hw_cnt_addr, &u4MaxCnt); + kalDevRegRead(prGlueInfo, prRxRing->hw_cidx_addr, &u4CpuIdx); + kalDevRegRead(prGlueInfo, prRxRing->hw_didx_addr, &u4DmaIdx); + + if (u4MaxCnt == 0 || u4MaxCnt > RX_RING_SIZE) + return 0; + + if (u4CpuIdx > u4DmaIdx) + u4RxPktCnt = u4MaxCnt + u4DmaIdx - u4CpuIdx - 1; + else if (u4CpuIdx < u4DmaIdx) + u4RxPktCnt = u4DmaIdx - u4CpuIdx - 1; + else + u4RxPktCnt = u4MaxCnt - 1; + + return u4RxPktCnt; +} + +bool halWpdmaWriteCmd(IN struct GLUE_INFO *prGlueInfo, + IN struct CMD_INFO *prCmdInfo, IN uint8_t ucTC) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct HIF_MEM_OPS *prMemOps; + struct RTMP_TX_RING *prTxRing; + struct RTMP_DMACB *pTxCell; + struct TXD_STRUCT *pTxD; + uint16_t u2Port = TX_RING_CMD_IDX_2; + uint32_t u4TotalLen; + void *pucSrc = NULL; + + ASSERT(prGlueInfo); + + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + prTxRing = &prHifInfo->TxRing[u2Port]; + + u4TotalLen = prCmdInfo->u4TxdLen + prCmdInfo->u4TxpLen; + if (prMemOps->allocRuntimeMem) + pucSrc = prMemOps->allocRuntimeMem(u4TotalLen); + + kalDevRegRead(prGlueInfo, prTxRing->hw_cidx_addr, &prTxRing->TxCpuIdx); + if (prTxRing->TxCpuIdx >= TX_RING_SIZE) { + DBGLOG(HAL, ERROR, "Error TxCpuIdx[%u]\n", prTxRing->TxCpuIdx); + if (prMemOps->freeBuf) + prMemOps->freeBuf(pucSrc, u4TotalLen); + return FALSE; + } + + pTxCell = &prTxRing->Cell[prTxRing->TxCpuIdx]; + pTxD = (struct TXD_STRUCT *)pTxCell->AllocVa; + pTxCell->pPacket = (void *)prCmdInfo; + pTxCell->pBuffer = pucSrc; + + if (prMemOps->copyCmd && + !prMemOps->copyCmd(prHifInfo, pTxCell, pucSrc, + prCmdInfo->pucTxd, prCmdInfo->u4TxdLen, + prCmdInfo->pucTxp, prCmdInfo->u4TxpLen)) { + if (prMemOps->freeBuf) + prMemOps->freeBuf(pucSrc, u4TotalLen); + ASSERT(0); + return FALSE; + } + + pTxD->SDPtr0 = (uint64_t)pTxCell->PacketPa & DMA_LOWER_32BITS_MASK; + pTxD->SDPtr0Ext = ((uint64_t)pTxCell->PacketPa >> DMA_BITS_OFFSET) & + DMA_HIGHER_4BITS_MASK; + pTxD->SDLen0 = u4TotalLen; + pTxD->SDPtr1 = 0; + pTxD->SDLen1 = 0; + pTxD->LastSec0 = 1; + pTxD->LastSec1 = 0; + pTxD->Burst = 0; + pTxD->DMADONE = 0; + + /* Increase TX_CTX_IDX, but write to register later. */ + INC_RING_INDEX(prTxRing->TxCpuIdx, TX_RING_SIZE); + + prTxRing->u4UsedCnt++; + kalDevRegWrite(prGlueInfo, prTxRing->hw_cidx_addr, prTxRing->TxCpuIdx); + + DBGLOG(HAL, TRACE, + "%s: CmdInfo[0x%p], TxD[0x%p/%u] TxP[0x%p/%u] CPU idx[%u] Used[%u]\n", + __func__, prCmdInfo, prCmdInfo->pucTxd, prCmdInfo->u4TxdLen, + prCmdInfo->pucTxp, prCmdInfo->u4TxpLen, + prTxRing->TxCpuIdx, prTxRing->u4UsedCnt); + DBGLOG_MEM32(HAL, TRACE, prCmdInfo->pucTxd, prCmdInfo->u4TxdLen); + + return TRUE; +} + +static bool halWpdmaFillTxRing(struct GLUE_INFO *prGlueInfo, + struct MSDU_TOKEN_ENTRY *prToken) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct mt66xx_chip_info *prChipInfo; + struct RTMP_TX_RING *prTxRing; + struct RTMP_DMACB *pTxCell; + struct TXD_STRUCT *pTxD; + uint16_t u2Port = TX_RING_DATA0_IDX_0; + + ASSERT(prGlueInfo); + + prHifInfo = &prGlueInfo->rHifInfo; + prChipInfo = prGlueInfo->prAdapter->chip_info; + prTxRing = &prHifInfo->TxRing[u2Port]; + + kalDevRegRead(prGlueInfo, prTxRing->hw_cidx_addr, &prTxRing->TxCpuIdx); + if (prTxRing->TxCpuIdx >= TX_RING_SIZE) { + DBGLOG(HAL, ERROR, "Error TxCpuIdx[%u]\n", prTxRing->TxCpuIdx); + halReturnMsduToken(prGlueInfo->prAdapter, prToken->u4Token); + return FALSE; + } + + pTxCell = &prTxRing->Cell[prTxRing->TxCpuIdx]; + prToken->u4CpuIdx = prTxRing->TxCpuIdx; + pTxCell->prToken = prToken; + + pTxD = (struct TXD_STRUCT *)pTxCell->AllocVa; + pTxD->SDPtr0 = (uint64_t)prToken->rDmaAddr & DMA_LOWER_32BITS_MASK; + pTxD->SDPtr0Ext = ((uint64_t)prToken->rDmaAddr >> DMA_BITS_OFFSET) & + DMA_HIGHER_4BITS_MASK; + pTxD->SDLen0 = NIC_TX_DESC_AND_PADDING_LENGTH + + prChipInfo->txd_append_size; + if (prChipInfo->is_support_cr4) + pTxD->SDLen0 += HIF_TX_PAYLOAD_LENGTH; + pTxD->SDPtr1 = 0; + pTxD->SDLen1 = 0; + pTxD->LastSec0 = 1; + pTxD->LastSec1 = 0; + pTxD->Burst = 0; + pTxD->DMADONE = 0; + + /* Increase TX_CTX_IDX, but write to register later. */ + INC_RING_INDEX(prTxRing->TxCpuIdx, TX_RING_SIZE); + + /* Update HW Tx DMA ring */ + prTxRing->u4UsedCnt++; + kalDevRegWrite(prGlueInfo, prTxRing->hw_cidx_addr, prTxRing->TxCpuIdx); + + DBGLOG_LIMITED(HAL, TRACE, "Tx Data: CPU idx[0x%x] Used[%u]\n", + prTxRing->TxCpuIdx, prTxRing->u4UsedCnt); + + return TRUE; +} + +static bool halFlushToken(struct GLUE_INFO *prGlueInfo, + struct MSDU_TOKEN_ENTRY *prToken) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct HIF_MEM_OPS *prMemOps; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + + if (prMemOps->mapTxBuf) { + prToken->rDmaAddr = prMemOps->mapTxBuf( + prHifInfo, prToken->prPacket, 0, prToken->u4DmaLength); + if (!prToken->rDmaAddr) + return false; + } + + if (prMemOps->flushCache) + prMemOps->flushCache(prHifInfo, prToken->prPacket, + prToken->u4DmaLength); + + return true; +} + +static bool halWpdmaWriteData(struct GLUE_INFO *prGlueInfo, + struct MSDU_INFO *prMsduInfo, + struct MSDU_TOKEN_ENTRY *prFillToken, + struct MSDU_TOKEN_ENTRY *prToken, + uint32_t u4Idx, uint32_t u4Num) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct mt66xx_chip_info *prChipInfo; + bool fgIsLast = (u4Idx + 1) == u4Num; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + prChipInfo = prGlueInfo->prAdapter->chip_info; + + /* Update Tx descriptor */ + halTxUpdateCutThroughDesc(prGlueInfo, prMsduInfo, prFillToken, + prToken, u4Idx, fgIsLast); + + /* Update token exclude FillToken */ + if (prToken != prFillToken) { + if (!halFlushToken(prGlueInfo, prToken)) + return false; + } + + /* Update FillToken */ + if (fgIsLast) { + if (!halFlushToken(prGlueInfo, prFillToken)) + return false; + halWpdmaFillTxRing(prGlueInfo, prFillToken); + } + + return true; +} + +void halWpdamFreeMsdu(struct GLUE_INFO *prGlueInfo, + struct MSDU_INFO *prMsduInfo, + bool fgSetEvent) +{ + + DBGLOG(HAL, LOUD, "Tx Data: Msdu[0x%p], TokFree[%u] TxDone[%u]\n", + prMsduInfo, halGetMsduTokenFreeCnt(prGlueInfo->prAdapter), + (prMsduInfo->pfTxDoneHandler ? TRUE : FALSE)); + + nicTxReleaseResource_PSE(prGlueInfo->prAdapter, prMsduInfo->ucTC, + nicTxGetPageCount(prGlueInfo->prAdapter, + prMsduInfo->u2FrameLength, TRUE), TRUE); + +#if HIF_TX_PREALLOC_DATA_BUFFER + if (!prMsduInfo->pfTxDoneHandler) { + nicTxFreePacket(prGlueInfo->prAdapter, prMsduInfo, FALSE); + nicTxReturnMsduInfo(prGlueInfo->prAdapter, prMsduInfo); + } +#endif + + if (fgSetEvent && wlanGetTxPendingFrameCount(prGlueInfo->prAdapter)) + kalSetEvent(prGlueInfo); +} + +bool halWpdmaWriteMsdu(struct GLUE_INFO *prGlueInfo, + struct MSDU_INFO *prMsduInfo, + struct list_head *prCurList) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct HIF_MEM_OPS *prMemOps; + struct MSDU_TOKEN_ENTRY *prToken = NULL; + struct sk_buff *prSkb; + uint8_t *pucSrc; + uint32_t u4TotalLen; + + ASSERT(prGlueInfo); + ASSERT(prMsduInfo); + + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + prSkb = (struct sk_buff *)prMsduInfo->prPacket; + pucSrc = prSkb->data; + u4TotalLen = prSkb->len; + + /* Acquire MSDU token */ + prToken = halAcquireMsduToken(prGlueInfo->prAdapter); + if (!prToken) { + DBGLOG(HAL, ERROR, "Write MSDU acquire token fail\n"); + return false; + } + +#if HIF_TX_PREALLOC_DATA_BUFFER + if (prMemOps->copyTxData) + prMemOps->copyTxData(prToken, pucSrc, u4TotalLen); +#else + prToken->prMsduInfo = prMsduInfo; + prToken->prPacket = pucSrc; + prToken->u4DmaLength = u4TotalLen; + prMsduInfo->prToken = prToken; +#endif + + if (!halWpdmaWriteData(prGlueInfo, prMsduInfo, prToken, + prToken, 0, 1)) { + halReturnMsduToken(prGlueInfo->prAdapter, prToken->u4Token); + return false; + } + + if (prCurList) { + list_del(prCurList); + prHifInfo->u4TxDataQLen--; + } + halWpdamFreeMsdu(prGlueInfo, prMsduInfo, true); + + return true; +} + +bool halWpdmaWriteAmsdu(struct GLUE_INFO *prGlueInfo, + struct list_head *prList, + uint32_t u4Num, uint16_t u2Size) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct HIF_MEM_OPS *prMemOps; + struct RTMP_TX_RING *prTxRing; + struct list_head *prCur, *prNext; + struct TX_DATA_REQ *prTxReq; + struct MSDU_TOKEN_ENTRY *prFillToken = NULL, *prToken = NULL; + struct MSDU_INFO *prMsduInfo; + struct AMSDU_MAC_TX_DESC *prTxD = NULL; + struct sk_buff *prSkb; + uint8_t *pucSrc; + uint32_t u4TotalLen, u4Idx, u4FreeToken, u4FreeRing; + bool fgIsLast; + + ASSERT(prGlueInfo); + + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + prTxRing = &prHifInfo->TxRing[TX_RING_DATA0_IDX_0]; + + u4FreeToken = halGetMsduTokenFreeCnt(prGlueInfo->prAdapter); + u4FreeRing = TX_RING_SIZE - prTxRing->u4UsedCnt; + if ((u4FreeToken < u4Num) || (u4FreeRing <= 1)) { + DBGLOG(HAL, WARN, + "Amsdu low tx res acquire[%u], tok[%u], ring[%u]\n", + u4Num, u4FreeToken, u4FreeRing); + return false; + } + + prCur = prList; + for (u4Idx = 0; u4Idx < u4Num; u4Idx++) { + prTxReq = list_entry(prCur, struct TX_DATA_REQ, list); + prMsduInfo = prTxReq->prMsduInfo; + prSkb = (struct sk_buff *)prMsduInfo->prPacket; + pucSrc = prSkb->data; + u4TotalLen = prSkb->len; + fgIsLast = (u4Idx == u4Num - 1); + + /* Acquire MSDU token */ + prToken = halAcquireMsduToken(prGlueInfo->prAdapter); + if (!prToken) { + DBGLOG(HAL, ERROR, "Write AMSDU acquire token fail\n"); + return false; + } +#if HIF_TX_PREALLOC_DATA_BUFFER + if (prMemOps->copyTxData) + prMemOps->copyTxData(prToken, pucSrc, u4TotalLen); +#else + prToken->prMsduInfo = prMsduInfo; + prToken->prPacket = pucSrc; + prToken->u4DmaLength = u4TotalLen; + prMsduInfo->prToken = prToken; +#endif + + if (!prFillToken) { + prFillToken = prToken; + prTxD = (struct AMSDU_MAC_TX_DESC *)prToken->prPacket; + } + + if (fgIsLast) { + prTxD->u2TxByteCount = u2Size; + prTxD->u4DW1 |= TXD_DW1_AMSDU_C; + } + + if (!halWpdmaWriteData(prGlueInfo, prMsduInfo, prFillToken, + prToken, u4Idx, u4Num)) { + halReturnMsduToken(prGlueInfo->prAdapter, + prToken->u4Token); + return false; + } + prCur = prCur->next; + } + + prCur = prList; + for (u4Idx = 0; u4Idx < u4Num; u4Idx++) { + prNext = prCur->next; + prTxReq = list_entry(prCur, struct TX_DATA_REQ, list); + prMsduInfo = prTxReq->prMsduInfo; + + list_del(prCur); + prHifInfo->u4TxDataQLen--; + + halWpdamFreeMsdu(prGlueInfo, prMsduInfo, true); + prCur = prNext; + } + + DBGLOG(HAL, LOUD, "Amsdu num:%d tx byte: %d\n", u4Num, u2Size); + return true; +} + +u_int8_t halIsStaticMapBusAddr(IN uint32_t u4Addr) +{ + if (u4Addr < MAX_PCIE_BUS_STATIC_MAP_ADDR) + return TRUE; + else + return FALSE; +} + +u_int8_t halChipToStaticMapBusAddr(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4ChipAddr, + OUT uint32_t *pu4BusAddr) +{ + struct BUS_INFO *prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + uint32_t u4StartAddr, u4EndAddr, u4BusAddr; + uint32_t u4Idx = 0; + + if (halIsStaticMapBusAddr(u4ChipAddr)) { + *pu4BusAddr = u4ChipAddr; + return TRUE; + } + + while (TRUE) { + u4StartAddr = prBusInfo->bus2chip[u4Idx].u4ChipAddr; + u4EndAddr = prBusInfo->bus2chip[u4Idx].u4ChipAddr + + prBusInfo->bus2chip[u4Idx].u4Range; + + /* End of mapping table */ + if (u4EndAddr == 0x0) + return FALSE; + + if ((u4ChipAddr >= u4StartAddr) && (u4ChipAddr <= u4EndAddr)) { + u4BusAddr = (u4ChipAddr - u4StartAddr) + + prBusInfo->bus2chip[u4Idx].u4BusAddr; + break; + } + + u4Idx++; + } + + *pu4BusAddr = u4BusAddr; + return TRUE; +} + +u_int8_t halGetDynamicMapReg(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4ChipAddr, OUT uint32_t *pu4Value) +{ + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + uint32_t u4ReMapReg, u4BusAddr; + + if (!halChipToStaticMapBusAddr(prGlueInfo, MCU_CFG_PCIE_REMAP2, + &u4ReMapReg)) + return FALSE; + + + RTMP_IO_WRITE32(prHifInfo, u4ReMapReg, u4ChipAddr & PCIE_REMAP2_MASK); + u4BusAddr = PCIE_REMAP2_BUS_ADDR + (u4ChipAddr & ~PCIE_REMAP2_MASK); + RTMP_IO_READ32(prHifInfo, u4BusAddr, pu4Value); + + return TRUE; +} + +u_int8_t halSetDynamicMapReg(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4ChipAddr, IN uint32_t u4Value) +{ + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + uint32_t u4ReMapReg, u4BusAddr; + + if (!halChipToStaticMapBusAddr(prGlueInfo, MCU_CFG_PCIE_REMAP2, + &u4ReMapReg)) + return FALSE; + + RTMP_IO_WRITE32(prHifInfo, u4ReMapReg, u4ChipAddr & PCIE_REMAP2_MASK); + u4BusAddr = PCIE_REMAP2_BUS_ADDR + (u4ChipAddr & ~PCIE_REMAP2_MASK); + RTMP_IO_WRITE32(prHifInfo, u4BusAddr, u4Value); + + return TRUE; +} + +u_int8_t halIsPendingRx(IN struct ADAPTER *prAdapter) +{ + /* TODO: check pending Rx + * if previous Rx handling is break due to lack of SwRfb + */ + return FALSE; +} + +uint32_t halGetValidCoalescingBufSize(IN struct ADAPTER *prAdapter) +{ + uint32_t u4BufSize; + + if (HIF_TX_COALESCING_BUFFER_SIZE > HIF_RX_COALESCING_BUFFER_SIZE) + u4BufSize = HIF_TX_COALESCING_BUFFER_SIZE; + else + u4BufSize = HIF_RX_COALESCING_BUFFER_SIZE; + + return u4BufSize; +} + +uint32_t halAllocateIOBuffer(IN struct ADAPTER *prAdapter) +{ + return WLAN_STATUS_SUCCESS; +} + +uint32_t halReleaseIOBuffer(IN struct ADAPTER *prAdapter) +{ + return WLAN_STATUS_SUCCESS; +} + +void halProcessAbnormalInterrupt(IN struct ADAPTER *prAdapter) +{ + +} + +void halProcessSoftwareInterrupt(IN struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo; + struct GL_HIF_INFO *prHifInfo; + struct ERR_RECOVERY_CTRL_T *prErrRecoveryCtrl; + uint32_t u4Status = 0; + + if (prAdapter == NULL || prAdapter->prGlueInfo == NULL) { + DBGLOG(HAL, ERROR, "prAdapter or prGlueInfo is NULL\n"); + return; + } + + prGlueInfo = prAdapter->prGlueInfo; + prHifInfo = &prGlueInfo->rHifInfo; + prErrRecoveryCtrl = &prHifInfo->rErrRecoveryCtl; + + kalDevRegRead(prGlueInfo, MCU2HOST_SW_INT_STA, &u4Status); + if (u4Status & ERROR_DETECT_MASK) { + prErrRecoveryCtrl->u4Status = u4Status; + kalDevRegWrite(prGlueInfo, MCU2HOST_SW_INT_STA, + ERROR_DETECT_MASK); + halHwRecoveryFromError(prAdapter); + } +} + +static void halHwRecoveryTimeout(unsigned long arg) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)arg; + struct ADAPTER *prAdapter = NULL; + + ASSERT(prGlueInfo); + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + DBGLOG(HAL, ERROR, "SER timer Timeout\n"); + +#if CFG_CHIP_RESET_SUPPORT + GL_RESET_TRIGGER(prAdapter, RST_FLAG_CHIP_RESET); +#endif +} + +void halSetDrvSer(struct ADAPTER *prAdapter) +{ + ASSERT(prAdapter); + ASSERT(prAdapter->prGlueInfo); + + DBGLOG(HAL, INFO, "Set Driver Ser\n"); + kalDevRegWrite(prAdapter->prGlueInfo, HOST2MCU_SW_INT_SET, + MCU_INT_DRIVER_SER); +} + +void halInitSerTimer(IN struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo; + struct GL_HIF_INFO *prHifInfo; + + prGlueInfo = prAdapter->prGlueInfo; + prHifInfo = &prGlueInfo->rHifInfo; + + init_timer(&prHifInfo->rSerTimer); + prHifInfo->rSerTimer.function = halHwRecoveryTimeout; + prHifInfo->rSerTimer.data = (unsigned long)prGlueInfo; + prHifInfo->rSerTimer.expires = + jiffies + HIF_SER_TIMEOUT * HZ / MSEC_PER_SEC; + add_timer(&prHifInfo->rSerTimer); + + DBGLOG(HAL, INFO, "Start SER timer\n"); +} + +void halHwRecoveryFromError(IN struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo; + struct GL_HIF_INFO *prHifInfo; + struct BUS_INFO *prBusInfo = NULL; + struct ERR_RECOVERY_CTRL_T *prErrRecoveryCtrl; + uint32_t u4Status = 0; + + prGlueInfo = prAdapter->prGlueInfo; + prHifInfo = &prGlueInfo->rHifInfo; + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + prErrRecoveryCtrl = &prHifInfo->rErrRecoveryCtl; + + u4Status = prErrRecoveryCtrl->u4Status; + prErrRecoveryCtrl->u4Status = 0; + + switch (prErrRecoveryCtrl->eErrRecovState) { + case ERR_RECOV_STOP_IDLE: + case ERR_RECOV_EVENT_REENTRY: + if (u4Status & ERROR_DETECT_STOP_PDMA) { + if (!prHifInfo->fgIsErrRecovery) { + prHifInfo->fgIsErrRecovery = TRUE; + halInitSerTimer(prAdapter); + } + + DBGLOG(HAL, INFO, + "SER(E) Host stop PDMA tx/rx ring operation\n"); + nicSerStopTxRx(prAdapter); + + DBGLOG(HAL, INFO, + "SER(F) Host ACK PDMA tx/rx ring stop operation\n"); + kalDevRegWrite(prGlueInfo, HOST2MCU_SW_INT_SET, + MCU_INT_PDMA0_STOP_DONE); + + /* re-call for change status to stop dma0 */ + prErrRecoveryCtrl->eErrRecovState = + ERR_RECOV_STOP_IDLE_DONE; + halHwRecoveryFromError(prAdapter); + } else { + DBGLOG(HAL, ERROR, "SER CurStat=%u Event=%x\n", + prErrRecoveryCtrl->eErrRecovState, u4Status); + } + break; + + case ERR_RECOV_STOP_PDMA0: + if (u4Status & ERROR_DETECT_RESET_DONE) { + DBGLOG(HAL, INFO, "SER(L) Host re-initialize PDMA\n"); + /* only reset TXD & RXD */ + halWpdmaAllocRing(prAdapter->prGlueInfo, false); + halResetMsduToken(prAdapter); + + DBGLOG(HAL, INFO, "SER(M) Host enable PDMA\n"); + halWpdmaInitRing(prGlueInfo); + kalDevRegWrite(prGlueInfo, WPDMA_PAUSE_TX_Q, 0); + + DBGLOG(HAL, INFO, + "SER(N) Host interrupt N9 PDMA ring init done\n"); + prErrRecoveryCtrl->eErrRecovState = + ERR_RECOV_RESET_PDMA0; + kalDevRegWrite(prGlueInfo, HOST2MCU_SW_INT_SET, + MCU_INT_PDMA0_INIT_DONE); + } else { + DBGLOG(HAL, ERROR, "SER CurStat=%u Event=%x\n", + prErrRecoveryCtrl->eErrRecovState, u4Status); + } + break; + + case ERR_RECOV_RESET_PDMA0: + if (u4Status & ERROR_DETECT_RECOVERY_DONE) { + DBGLOG(HAL, INFO, + "SER(Q) Host interrupt N9 SER handle done\n"); + prErrRecoveryCtrl->eErrRecovState = + ERR_RECOV_WAIT_N9_NORMAL; + kalDevRegWrite(prGlueInfo, HOST2MCU_SW_INT_SET, + MCU_INT_PDMA0_RECOVERY_DONE); + } else { + DBGLOG(HAL, ERROR, "SER CurStat=%u Event=%x\n", + prErrRecoveryCtrl->eErrRecovState, u4Status); + } + break; + + case ERR_RECOV_STOP_IDLE_DONE: + prErrRecoveryCtrl->eErrRecovState = ERR_RECOV_STOP_PDMA0; + break; + + case ERR_RECOV_WAIT_N9_NORMAL: + if (u4Status & ERROR_DETECT_N9_NORMAL_STATE) { + del_timer(&prHifInfo->rSerTimer); + + /* update Beacon frame if operating in AP mode. */ + DBGLOG(HAL, INFO, "SER(T) Host re-initialize BCN\n"); + nicSerReInitBeaconFrame(prAdapter); + + kalDevKickCmd(prAdapter->prGlueInfo); + kalDevKickData(prAdapter->prGlueInfo); + halRxReceiveRFBs(prAdapter, RX_RING_EVT_IDX_1); + halRxReceiveRFBs(prAdapter, RX_RING_DATA_IDX_0); + prHifInfo->fgIsErrRecovery = FALSE; + nicSerStartTxRx(prAdapter); + prErrRecoveryCtrl->eErrRecovState = ERR_RECOV_STOP_IDLE; + } else if (u4Status & ERROR_DETECT_STOP_PDMA) { + DBGLOG(HAL, ERROR, "SER re-entry CurStat=%u Event=%x\n", + prErrRecoveryCtrl->eErrRecovState, u4Status); + prErrRecoveryCtrl->eErrRecovState = + ERR_RECOV_EVENT_REENTRY; + halHwRecoveryFromError(prAdapter); + } else { + DBGLOG(HAL, ERROR, "SER CurStat=%u Event=%x\n", + prErrRecoveryCtrl->eErrRecovState, u4Status); + } + break; + + default: + DBGLOG(HAL, ERROR, "SER CurStat=%u Event=%x!!!\n", + prErrRecoveryCtrl->eErrRecovState, u4Status); + break; + } +} +#if CFG_SUPPORT_PCIE_L2 + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Send HIF_CTRL command to inform FW allow send packet/event to host +* suspend = 0 +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (void) +*/ +/*----------------------------------------------------------------------------*/ +void halPreResumeCmd(IN struct ADAPTER *prAdapter) +{ + struct CMD_HIF_CTRL rCmdHifCtrl; + uint32_t rStatus; + + rCmdHifCtrl.ucHifType = ENUM_HIF_TYPE_PCIE; + rCmdHifCtrl.ucHifDirection = ENUM_HIF_TX; + rCmdHifCtrl.ucHifStop = 0; + rCmdHifCtrl.ucHifSuspend = 0; + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_HIF_CTRL, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* nicEventHifCtrl */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct CMD_HIF_CTRL), + (uint8_t *)&rCmdHifCtrl, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (kalIsResetting()) + return; + + ASSERT(rStatus == WLAN_STATUS_PENDING); +} +/*----------------------------------------------------------------------------*/ +/*! +* @brief Send HIF_CTRL command to inform FW stop send packet/event to host +* suspend = 1 +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (void) +*/ +/*----------------------------------------------------------------------------*/ + +void halPreSuspendCmd(IN struct ADAPTER *prAdapter) +{ + struct CMD_HIF_CTRL rCmdHifCtrl; + uint32_t rStatus; + + rCmdHifCtrl.ucHifType = ENUM_HIF_TYPE_PCIE; + rCmdHifCtrl.ucHifDirection = ENUM_HIF_TX; + rCmdHifCtrl.ucHifStop = 1; + rCmdHifCtrl.ucHifSuspend = 1; + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_HIF_CTRL, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* nicEventHifCtrl */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct CMD_HIF_CTRL), + (uint8_t *)&rCmdHifCtrl, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (kalIsResetting()) + return; + + ASSERT(rStatus == WLAN_STATUS_PENDING); +} + + +#endif +void halDeAggRxPktWorker(struct work_struct *work) +{ + +} + +void halRxTasklet(unsigned long data) +{ + +} + +void halTxCompleteTasklet(unsigned long data) +{ + +} + +/* Hif power off wifi */ +uint32_t halHifPowerOffWifi(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + DBGLOG(INIT, INFO, "Power off Wi-Fi!\n"); + + nicDisableInterrupt(prAdapter); + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + /* Power off Wi-Fi */ + wlanSendNicPowerCtrlCmd(prAdapter, TRUE); + + prHifInfo->fgIsPowerOff = true; + + /* prAdapter->fgWiFiInSleepyState = TRUE; */ + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + + rStatus = wlanCheckWifiFunc(prAdapter, FALSE); + + return rStatus; +} + +u_int8_t halIsTxResourceControlEn(IN struct ADAPTER *prAdapter) +{ + return FALSE; +} + +void halTxResourceResetHwTQCounter(IN struct ADAPTER *prAdapter) +{ +} + +uint32_t halGetHifTxPageSize(IN struct ADAPTER *prAdapter) +{ + return HIF_TX_PAGE_SIZE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Check if HIF state is READY for upper layer cfg80211 +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (TRUE: ready, FALSE: not ready) +*/ +/*----------------------------------------------------------------------------*/ +bool halIsHifStateReady(IN struct ADAPTER *prAdapter, uint8_t *pucState) +{ + /* PCIE owner should implement this function */ + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Check if HIF state is during supend process +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (TRUE: suspend, reject the caller action. FALSE: not suspend) +*/ +/*----------------------------------------------------------------------------*/ +bool halIsHifStateSuspend(IN struct ADAPTER *prAdapter) +{ + /* PCIE owner should implement this function */ + + return FALSE; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/common/include/hif_pdma.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/common/include/hif_pdma.h new file mode 100644 index 0000000000000..b7039959e9a87 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/common/include/hif_pdma.h @@ -0,0 +1,473 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + Module Name: + hif_pdma.h + */ + +#ifndef __HIF_PDMA_H__ +#define __HIF_PDMA_H__ + +#include + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +#define NUM_OF_TX_RING 4 +#define NUM_OF_RX_RING 2 + +#define TX_RING_SIZE 256 +#define RX_RING_SIZE 256 /* Max Rx ring size */ + +/* Data Rx ring */ +#define RX_RING0_SIZE 256 +/* Event/MSDU_report Rx ring */ +#define RX_RING1_SIZE 16 + +/* TXD_SIZE = TxD + TxInfo */ +#define TXD_SIZE 16 +#define RXD_SIZE 16 + +#define RX_BUFFER_AGGRESIZE 3840 +#define RX_BUFFER_NORMSIZE 3840 +#define TX_BUFFER_NORMSIZE 3840 + +#define HIF_TX_PREALLOC_DATA_BUFFER 1 + +#define HIF_NUM_OF_QM_RX_PKT_NUM 4096 +#define HIF_IST_LOOP_COUNT 32 +/* Min msdu count to trigger Tx during INT polling state */ +#define HIF_IST_TX_THRESHOLD 1 + +#define HIF_TX_BUFF_COUNT_TC0 4096 +#define HIF_TX_BUFF_COUNT_TC1 4096 +#define HIF_TX_BUFF_COUNT_TC2 4096 +#define HIF_TX_BUFF_COUNT_TC3 4096 +#define HIF_TX_BUFF_COUNT_TC4 (TX_RING_SIZE - 1) +#define HIF_TX_BUFF_COUNT_TC5 4096 + +/* enable/disable TX resource control */ +#define HIF_TX_RESOURCE_CTRL 1 +/* enable/disable TX resource control PLE */ +#define HIF_TX_RESOURCE_CTRL_PLE 0 + + +#define HIF_TX_PAGE_SIZE_IN_POWER_OF_2 11 +/* in unit of bytes */ +#define HIF_TX_PAGE_SIZE 2048 + +#define HIF_EXTRA_IO_BUFFER_SIZE 0 + +#define HIF_TX_COALESCING_BUFFER_SIZE (TX_BUFFER_NORMSIZE) +#define HIF_RX_COALESCING_BUFFER_SIZE (RX_BUFFER_AGGRESIZE) + +#define HIF_CR4_FWDL_SECTION_NUM 1 +#define HIF_IMG_DL_STATUS_PORT_IDX 1 + +#define HIF_TX_INIT_CMD_PORT TX_RING_FWDL_IDX_3 + +#define HIF_TX_MSDU_TOKEN_NUM (TX_RING_SIZE * 2) + +#define HIF_TX_PAYLOAD_LENGTH 72 + +#define HIF_MSDU_REPORT_DUMP_TIMEOUT 1 /* sec */ +#define HIF_MSDU_REPORT_RETURN_TIMEOUT 10 /* sec */ +#define HIF_SER_TIMEOUT 10000 /* msec */ + +#define MAX_PCIE_BUS_STATIC_MAP_ADDR 0x00040000 + +#define MT_RINGREG_DIFF 0x10 +#define MT_RINGREG_EXT_DIFF 0x04 + +#define MT_TX_RING_BASE WPDMA_TX_RING0_CTRL0 +#define MT_TX_RING_PTR WPDMA_TX_RING0_CTRL0 +#define MT_TX_RING_CNT WPDMA_TX_RING0_CTRL1 +#define MT_TX_RING_CIDX WPDMA_TX_RING0_CTRL2 +#define MT_TX_RING_DIDX WPDMA_TX_RING0_CTRL3 + +#define MT_RX_RING_BASE WPDMA_RX_RING0_CTRL0 +#define MT_RX_RING_PTR WPDMA_RX_RING0_CTRL0 +#define MT_RX_RING_CNT WPDMA_RX_RING0_CTRL1 +#define MT_RX_RING_CIDX WPDMA_RX_RING0_CTRL2 +#define MT_RX_RING_DIDX WPDMA_RX_RING0_CTRL3 + +#define DMA_LOWER_32BITS_MASK 0x00000000FFFFFFFF +#define DMA_HIGHER_4BITS_MASK 0x0000000F +#define DMA_BITS_OFFSET 32 + +#define DMA_DONE_WAITING_TIME 10 +#define DMA_DONE_WAITING_COUNT 100 + +#define MT_TX_RING_BASE_EXT WPDMA_TX_RING0_BASE_PTR_EXT +#define MT_RX_RING_BASE_EXT WPDMA_RX_RING0_BASE_PTR_EXT + +#define PDMA_DUMMY_RESET_VALUE 0x0F +#define PDMA_DUMMY_MAGIC_NUM 0x13 + +#define TXD_DW1_RMVL BIT(10) +#define TXD_DW1_VLAN BIT(11) +#define TXD_DW1_ETYP BIT(12) +#define TXD_DW1_AMSDU_C BIT(20) + +#define HIF_DEADFEED_VALUE 0xdeadfeed + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +#define INC_RING_INDEX(_idx, _RingSize) \ +{ \ + (_idx) = (_idx+1) % (_RingSize); \ +} + +#define RTMP_IO_READ32(_A, _R, _pV) \ +{ \ + (*(_pV) = readl((void *)((_A)->CSRBaseAddress + (_R)))); \ +} + +#define RTMP_IO_WRITE32(_A, _R, _V) \ +{ \ + writel(_V, (void *)((_A)->CSRBaseAddress + (_R))); \ +} + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +enum ENUM_TX_RING_IDX { + TX_RING_DATA0_IDX_0 = 0, + TX_RING_DATA1_IDX_1, + TX_RING_CMD_IDX_2, + TX_RING_FWDL_IDX_3, +}; + +enum ENUM_RX_RING_IDX { + RX_RING_DATA_IDX_0 = 0, + RX_RING_EVT_IDX_1 +}; + +/* ============================================================================ + * PCI/RBUS TX / RX Frame Descriptors format + * + * Memory Layout + * + * 1. Tx Descriptor + * TxD (12 bytes) + TXINFO (4 bytes) + * 2. Packet Buffer + * TXWI + 802.11 + * 31 0 + * +--------------------------------------------------------------------------+ + * | SDP0[31:0] | + * +-+--+---------------------+-+--+------------------------------------------+ + * |D |L0| SDL0[13:0] |B|L1| SDL1[13:0] | + * +-+--+---------------------+-+--+------------------------------------------+ + * | SDP1[31:0] | + * +--------------------------------------------------------------------------+ + * | TX / RX INFO | + * +--------------------------------------------------------------------------+ + * ========================================================================= + */ +/* + * TX descriptor format for Tx Data/Mgmt Rings + */ +struct TXD_STRUCT { + /* Word 0 */ + uint32_t SDPtr0; + + /* Word 1 */ + uint32_t SDLen1:14; + uint32_t LastSec1:1; + uint32_t Burst:1; + uint32_t SDLen0:14; + uint32_t LastSec0:1; + uint32_t DMADONE:1; + + /*Word2 */ + uint32_t SDPtr1; + + /*Word3 */ + uint16_t SDPtr0Ext; + uint16_t SDPtr1Ext; +}; + +/* + * Rx descriptor format for Rx Rings + */ +struct RXD_STRUCT { + /* Word 0 */ + uint32_t SDPtr0; + + /* Word 1 */ + uint32_t SDLen1:14; + uint32_t LastSec1:1; + uint32_t Burst:1; + uint32_t SDLen0:14; + uint32_t LastSec0:1; + uint32_t DMADONE:1; + + /* Word 2 */ + uint32_t SDPtr1; + + /* Word 3 */ + uint32_t RXINFO; +}; + +/* + * Data buffer for DMA operation, the buffer must be contiguous + * physical memory Both DMA to / from CPU use the same structure. + */ +struct RTMP_DMABUF { + unsigned long AllocSize; + void *AllocVa; /* TxBuf virtual address */ + phys_addr_t AllocPa; /* TxBuf physical address */ +}; + +/* + * Control block (Descriptor) for all ring descriptor DMA operation, + * buffer must be contiguous physical memory. NDIS_PACKET stored the + * binding Rx packet descriptor which won't be released, driver has to + * wait until upper layer return the packet before giveing up this rx + * ring descriptor to ASIC. NDIS_BUFFER is assocaited pair to describe + * the packet buffer. For Tx, NDIS_PACKET stored the tx packet descriptor + * which driver should ACK upper layer when the tx is physically done or + * failed. + */ +struct RTMP_DMACB { + unsigned long AllocSize; /* Control block size */ + void *AllocVa; /* Control block virtual address */ + phys_addr_t AllocPa; /* Control block physical address */ + void *pPacket; + void *pBuffer; + phys_addr_t PacketPa; + struct RTMP_DMABUF DmaBuf; /* Associated DMA buffer structure */ + struct MSDU_TOKEN_ENTRY *prToken; +}; + +struct RTMP_TX_RING { + struct RTMP_DMACB Cell[TX_RING_SIZE]; + uint32_t TxCpuIdx; + uint32_t TxDmaIdx; + uint32_t u4BufSize; + uint32_t TxSwUsedIdx; + uint32_t u4UsedCnt; + uint32_t hw_desc_base; + uint32_t hw_desc_base_ext; + uint32_t hw_cidx_addr; + uint32_t hw_didx_addr; + uint32_t hw_cnt_addr; +}; + +struct RTMP_RX_RING { + struct RTMP_DMACB Cell[RX_RING_SIZE]; + uint32_t RxCpuIdx; + uint32_t RxDmaIdx; + uint32_t u4BufSize; + uint32_t u4RingSize; + u_int8_t fgRxSegPkt; + uint32_t hw_desc_base; + uint32_t hw_desc_base_ext; + uint32_t hw_cidx_addr; + uint32_t hw_didx_addr; + uint32_t hw_cnt_addr; + bool fgIsDumpLog; +}; + +struct PCIE_CHIP_CR_MAPPING { + uint32_t u4ChipAddr; + uint32_t u4BusAddr; + uint32_t u4Range; +}; + +struct MSDU_TOKEN_ENTRY { + uint32_t u4Token; + u_int8_t fgInUsed; + struct timeval rTs; /* token tx timestamp */ + uint32_t u4CpuIdx; /* tx ring cell index */ + struct MSDU_INFO *prMsduInfo; + void *prPacket; + phys_addr_t rDmaAddr; + uint32_t u4DmaLength; + phys_addr_t rPktDmaAddr; + uint32_t u4PktDmaLength; +}; + +struct MSDU_TOKEN_INFO { + int32_t i4UsedCnt; + struct MSDU_TOKEN_ENTRY *aprTokenStack[HIF_TX_MSDU_TOKEN_NUM]; + spinlock_t rTokenLock; + struct MSDU_TOKEN_ENTRY arToken[HIF_TX_MSDU_TOKEN_NUM]; +}; + +struct TX_CMD_REQ { + struct CMD_INFO *prCmdInfo; + uint8_t ucTC; + struct list_head list; +}; + +struct TX_DATA_REQ { + struct MSDU_INFO *prMsduInfo; + struct list_head list; +}; + +struct AMSDU_MAC_TX_DESC { + uint16_t u2TxByteCount; + uint16_t u2DW0; + uint32_t u4DW1; + uint32_t u4DW2:31; + uint32_t u4FR:1; + uint32_t u4DW3; + uint32_t u4DW4; + uint32_t u4DW5_1:9; + uint32_t u4TXS:2; + uint32_t u4DW5_2:21; + uint32_t u4DW6; + uint32_t u4DW7; +}; + +enum ERR_RECOVERY_STATE { + ERR_RECOV_STOP_IDLE = 0, + ERR_RECOV_STOP_PDMA0, + ERR_RECOV_RESET_PDMA0, + ERR_RECOV_STOP_IDLE_DONE, + ERR_RECOV_WAIT_N9_NORMAL, + ERR_RECOV_EVENT_REENTRY, + ERR_RECOV_STATE_NUM +}; + +struct ERR_RECOVERY_CTRL_T { + enum ERR_RECOVERY_STATE eErrRecovState; + uint32_t u4Status; +}; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +void halHifRst(struct GLUE_INFO *prGlueInfo); +bool halWpdmaAllocRing(struct GLUE_INFO *prGlueInfo, bool fgAllocMem); +void halWpdmaFreeRing(struct GLUE_INFO *prGlueInfo); +void halWpdmaInitRing(struct GLUE_INFO *prGlueInfo); +void halWpdmaInitTxRing(IN struct GLUE_INFO *prGlueInfo); +void halWpdmaInitRxRing(IN struct GLUE_INFO *prGlueInfo); +void halWpdmaProcessCmdDmaDone(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port); +void halWpdmaProcessDataDmaDone(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port); +uint32_t halWpdmaGetRxDmaDoneCnt(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRingNum); +void halInitMsduTokenInfo(IN struct ADAPTER *prAdapter); +void halUninitMsduTokenInfo(IN struct ADAPTER *prAdapter); +uint32_t halGetMsduTokenFreeCnt(IN struct ADAPTER *prAdapter); +struct MSDU_TOKEN_ENTRY *halGetMsduTokenEntry(IN struct ADAPTER *prAdapter, + uint32_t u4TokenNum); +struct MSDU_TOKEN_ENTRY *halAcquireMsduToken(IN struct ADAPTER *prAdapter); +void halReturnMsduToken(IN struct ADAPTER *prAdapter, uint32_t u4TokenNum); +void halReturnTimeoutMsduToken(struct ADAPTER *prAdapter); +void halTxUpdateCutThroughDesc(struct GLUE_INFO *prGlueInfo, + struct MSDU_INFO *prMsduInfo, + struct MSDU_TOKEN_ENTRY *prFillToken, + struct MSDU_TOKEN_ENTRY *prDataToken, + uint32_t u4Idx, bool fgIsLast); +u_int8_t halIsStaticMapBusAddr(IN uint32_t u4Addr); +u_int8_t halChipToStaticMapBusAddr(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4ChipAddr, + OUT uint32_t *pu4BusAddr); +u_int8_t halGetDynamicMapReg(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4ChipAddr, + OUT uint32_t *pu4Value); +u_int8_t halSetDynamicMapReg(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4ChipAddr, + IN uint32_t u4Value); +void halConnacWpdmaConfig(struct GLUE_INFO *prGlueInfo, u_int8_t enable); +void halConnacEnableInterrupt(IN struct ADAPTER *prAdapter); +bool halWpdmaWriteCmd(struct GLUE_INFO *prGlueInfo, + struct CMD_INFO *prCmdInfo, + uint8_t ucTC); +bool halWpdmaWriteMsdu(struct GLUE_INFO *prGlueInfo, + struct MSDU_INFO *prMsduInfo, + struct list_head *prCurList); +bool halWpdmaWriteAmsdu(struct GLUE_INFO *prGlueInfo, + struct list_head *prList, + uint32_t u4Num, uint16_t u2Size); +void halWpdamFreeMsdu(struct GLUE_INFO *prGlueInfo, + struct MSDU_INFO *prMsduInfo, + bool fgSetEvent); + +void halSetDrvSer(struct ADAPTER *prAdapter); +void halHwRecoveryFromError(IN struct ADAPTER *prAdapter); + +bool kalDevReadData(struct GLUE_INFO *prGlueInfo, uint16_t u2Port, + struct SW_RFB *prSwRfb); +bool kalDevKickCmd(struct GLUE_INFO *prGlueInfo); + +/* Debug functions */ +int halTimeCompare(struct timeval *prTs1, struct timeval *prTs2); +void halShowPdmaInfo(IN struct ADAPTER *prAdapter); +void halShowPseInfo(IN struct ADAPTER *prAdapter); +void halShowPleInfo(IN struct ADAPTER *prAdapter); +bool halShowHostCsrInfo(IN struct ADAPTER *prAdapter); +void halShowDmaschInfo(IN struct ADAPTER *prAdapter); +void kalDumpTxRing(struct GLUE_INFO *prGlueInfo, + struct RTMP_TX_RING *prTxRing, + uint32_t u4Num, bool fgDumpContent); +void kalDumpRxRing(struct GLUE_INFO *prGlueInfo, + struct RTMP_RX_RING *prRxRing, + uint32_t u4Num, bool fgDumpContent); +void haldumpMacInfo(IN struct ADAPTER *prAdapter); +void haldumpPhyInfo(struct ADAPTER *prAdapter); + +#endif /* HIF_PDMA_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/common/kal_pdma.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/common/kal_pdma.c new file mode 100644 index 0000000000000..7e1480e63890b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/common/kal_pdma.c @@ -0,0 +1,942 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** + *[File] kal_pdma.c + *[Version] v1.0 + *[Revision Date] 2010-03-01 + *[Author] + *[Description] + * The program provides PCIE HIF driver + *[Copyright] + * Copyright (C) 2010 MediaTek Incorporation. All Rights Reserved. + ******************************************************************************/ + + +/******************************************************************************* + * C O M P I L E 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 "hif_pdma.h" + +#include "precomp.h" + +#include +#ifndef CONFIG_X86 +#include +#endif + +#include "mt66xx_reg.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 bool kalDevWriteCmdByQueue(struct GLUE_INFO *prGlueInfo, + struct CMD_INFO *prCmdInfo, uint8_t ucTC); +static bool kalDevWriteDataByQueue(struct GLUE_INFO *prGlueInfo, + struct MSDU_INFO *prMsduInfo); +static bool kalDevKickMsduData(struct GLUE_INFO *prGlueInfo); +static bool kalDevKickAmsduData(struct GLUE_INFO *prGlueInfo); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Check connsys is dead or not + * + * \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. + * \param[in] u4Register Register address + * \param[in] pu4Value Pointer to read value + * + * \retval TRUE connsys is dead + * \retval FALSE connsys is alive + */ +/*----------------------------------------------------------------------------*/ +static inline bool kalIsChipDead(struct GLUE_INFO *prGlueInfo, + uint32_t u4Register, uint32_t *pu4Value) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + uint32_t u4Value; + uint32_t u4BusAddr; + + prHifInfo = &prGlueInfo->rHifInfo; + + if (*pu4Value != HIF_DEADFEED_VALUE) + return false; + + if (!halChipToStaticMapBusAddr(prGlueInfo, CONN_CFG_CHIP_ID_ADDR, + &u4BusAddr)) { + DBGLOG(HAL, ERROR, "Not exist CR read[0x%08x]\n", u4Register); + return false; + } + + RTMP_IO_READ32(prHifInfo, u4BusAddr, &u4Value); + + return u4Value == HIF_DEADFEED_VALUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevRegRead(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Register, OUT uint32_t *pu4Value) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct BUS_INFO *prBusInfo = NULL; + uint32_t u4BusAddr = u4Register; + + ASSERT(prGlueInfo); + ASSERT(pu4Value); + + prHifInfo = &prGlueInfo->rHifInfo; + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + prBusInfo = prAdapter->chip_info->bus_info; + + if (!prHifInfo->fgIsDumpLog && prBusInfo->isValidRegAccess && + !prBusInfo->isValidRegAccess(prAdapter, u4Register)) { + /* Don't print log when resetting */ + if (!wlanIsChipNoAck(prAdapter)) { + DBGLOG(HAL, ERROR, + "Invalid access! Get CR[0x%08x/0x%08x] value[0x%08x]\n", + u4Register, u4BusAddr, *pu4Value); + } + *pu4Value = HIF_DEADFEED_VALUE; + return FALSE; + } + + /* Static mapping */ + if (halChipToStaticMapBusAddr(prGlueInfo, u4Register, &u4BusAddr)) { + RTMP_IO_READ32(prHifInfo, u4BusAddr, pu4Value); + if (kalIsChipDead(prGlueInfo, u4Register, pu4Value)) { + /* Don't print log when resetting */ + if (!wlanIsChipNoAck(prAdapter)) { + DBGLOG(HAL, ERROR, + "Read register is deadfeed\n"); + GL_RESET_TRIGGER(prAdapter, + RST_FLAG_CHIP_RESET); + } + return FALSE; + } + } else { + DBGLOG(HAL, ERROR, "Not exist CR read[0x%08x]\n", u4Register); + } + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevRegWrite(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Register, IN uint32_t u4Value) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct ADAPTER *prAdapter = NULL; + struct BUS_INFO *prBusInfo = NULL; + uint32_t u4BusAddr = u4Register; + + ASSERT(prGlueInfo); + + prHifInfo = &prGlueInfo->rHifInfo; + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + prBusInfo = prAdapter->chip_info->bus_info; + + if (!prHifInfo->fgIsDumpLog && prBusInfo->isValidRegAccess && + !prBusInfo->isValidRegAccess(prAdapter, u4Register)) { + /* Don't print log when resetting */ + if (!wlanIsChipNoAck(prAdapter)) { + DBGLOG(HAL, ERROR, + "Invalid access! Set CR[0x%08x/0x%08x] value[0x%08x]\n", + u4Register, u4BusAddr, u4Value); + } + return FALSE; + } + + /* Static mapping */ + if (halChipToStaticMapBusAddr(prGlueInfo, u4Register, &u4BusAddr)) { + RTMP_IO_WRITE32(prHifInfo, u4BusAddr, u4Value); + } else { + DBGLOG(HAL, ERROR, "Not exist CR write[0x%08x] value[0x%08x]\n", + u4Register, u4Value); + } + + prHifInfo->u4HifCnt++; + + return TRUE; +} + +static bool kalWaitRxDmaDone(struct GLUE_INFO *prGlueInfo, + struct RTMP_RX_RING *prRxRing, + struct RXD_STRUCT *pRxD, + uint16_t u2Port) +{ + uint32_t u4Count = 0; + + for (u4Count = 0; pRxD->DMADONE == 0; u4Count++) { + kalDevRegRead(prGlueInfo, prRxRing->hw_didx_addr, + &prRxRing->RxDmaIdx); + if (u4Count > DMA_DONE_WAITING_COUNT) { + DBGLOG(HAL, INFO, + "Rx DMA done P[%u] DMA[%u] CPU[%u]\n", + u2Port, prRxRing->RxDmaIdx, prRxRing->RxCpuIdx); + return false; + } + + kalMdelay(DMA_DONE_WAITING_TIME); + } + return true; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevPortRead(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port, IN uint32_t u4Len, + OUT uint8_t *pucBuf, IN uint32_t u4ValidOutBufSize) +{ + struct ADAPTER *prAdapter = NULL; + struct GL_HIF_INFO *prHifInfo = NULL; + struct HIF_MEM_OPS *prMemOps; + struct RTMP_RX_RING *prRxRing; + struct RTMP_DMACB *pRxCell; + struct RXD_STRUCT *pRxD; + struct RTMP_DMABUF *prDmaBuf; + u_int8_t fgRet = TRUE; + uint32_t u4CpuIdx = 0; + + ASSERT(prGlueInfo); + ASSERT(pucBuf); + ASSERT(u4Len <= u4ValidOutBufSize); + + prAdapter = prGlueInfo->prAdapter; + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + prRxRing = &prHifInfo->RxRing[u2Port]; + + kalDevRegRead(prGlueInfo, prRxRing->hw_cidx_addr, &prRxRing->RxCpuIdx); + u4CpuIdx = prRxRing->RxCpuIdx; + INC_RING_INDEX(u4CpuIdx, prRxRing->u4RingSize); + + pRxCell = &prRxRing->Cell[u4CpuIdx]; + pRxD = (struct RXD_STRUCT *)pRxCell->AllocVa; + + if (halWpdmaGetRxDmaDoneCnt(prGlueInfo, u2Port) == 0) + return FALSE; + + if (!kalWaitRxDmaDone(prGlueInfo, prRxRing, pRxD, u2Port)) { + if (!prRxRing->fgIsDumpLog) { + prAdapter->u4HifDbgFlag |= DEG_HIF_DEFAULT_DUMP; + halPrintHifDbgInfo(prAdapter); + } + prRxRing->fgIsDumpLog = true; + return FALSE; + } + + if (pRxD->LastSec0 == 0 || prRxRing->fgRxSegPkt) { + /* Rx segmented packet */ + DBGLOG(HAL, WARN, + "Skip Rx segmented packet, SDL0[%u] LS0[%u]\n", + pRxD->SDLen0, pRxD->LastSec0); + if (pRxD->LastSec0 == 1) { + /* Last segmented packet */ + prRxRing->fgRxSegPkt = FALSE; + } else { + /* Segmented packet */ + prRxRing->fgRxSegPkt = TRUE; + } + + fgRet = FALSE; + goto skip; + } + + if (pRxD->SDLen0 > u4Len) { + DBGLOG(HAL, WARN, + "Skip Rx packet, SDL0[%u] > SwRfb max len[%u]\n", + pRxD->SDLen0, u4Len); + goto skip; + } + + prDmaBuf = &pRxCell->DmaBuf; + if (prMemOps->copyEvent && + !prMemOps->copyEvent(prHifInfo, pRxCell, pRxD, + prDmaBuf, pucBuf, u4Len)) { + ASSERT(0); + return FALSE; + } + + pRxD->SDPtr0 = (uint64_t)prDmaBuf->AllocPa & DMA_LOWER_32BITS_MASK; + pRxD->SDPtr1 = ((uint64_t)prDmaBuf->AllocPa >> DMA_BITS_OFFSET) & + DMA_HIGHER_4BITS_MASK; +skip: + pRxD->SDLen0 = prRxRing->u4BufSize; + pRxD->DMADONE = 0; + + prRxRing->RxCpuIdx = u4CpuIdx; + kalDevRegWrite(prGlueInfo, prRxRing->hw_cidx_addr, prRxRing->RxCpuIdx); + prRxRing->fgIsDumpLog = false; + + return fgRet; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t +kalDevPortWrite(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port, IN uint32_t u4Len, IN uint8_t *pucBuf, + IN uint32_t u4ValidInBufSize) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct HIF_MEM_OPS *prMemOps; + struct RTMP_TX_RING *prTxRing; + struct RTMP_DMACB *pTxCell; + struct TXD_STRUCT *pTxD; + void *pucDst = NULL; + + ASSERT(prGlueInfo); + ASSERT(pucBuf); + ASSERT(u4Len <= u4ValidInBufSize); + + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + prTxRing = &prHifInfo->TxRing[u2Port]; + + if (prMemOps->allocRuntimeMem) + pucDst = prMemOps->allocRuntimeMem(u4Len); + + kalDevRegRead(prGlueInfo, prTxRing->hw_cidx_addr, &prTxRing->TxCpuIdx); + if (prTxRing->TxCpuIdx >= TX_RING_SIZE) { + DBGLOG(HAL, ERROR, "Error TxCpuIdx[%u]\n", prTxRing->TxCpuIdx); + if (prMemOps->freeBuf) + prMemOps->freeBuf(pucDst, u4Len); + return FALSE; + } + + pTxCell = &prTxRing->Cell[prTxRing->TxCpuIdx]; + pTxD = (struct TXD_STRUCT *)pTxCell->AllocVa; + + pTxCell->pPacket = NULL; + pTxCell->pBuffer = pucDst; + + if (prMemOps->copyCmd && + !prMemOps->copyCmd(prHifInfo, pTxCell, pucDst, + pucBuf, u4Len, NULL, 0)) { + if (prMemOps->freeBuf) + prMemOps->freeBuf(pucDst, u4Len); + ASSERT(0); + return FALSE; + } + + pTxD->LastSec0 = 1; + pTxD->LastSec1 = 0; + pTxD->SDLen0 = u4Len; + pTxD->SDLen1 = 0; + pTxD->SDPtr0 = (uint64_t)pTxCell->PacketPa & DMA_LOWER_32BITS_MASK; + pTxD->SDPtr0Ext = ((uint64_t)pTxCell->PacketPa >> DMA_BITS_OFFSET) & + DMA_HIGHER_4BITS_MASK; + pTxD->SDPtr1 = 0; + pTxD->Burst = 0; + pTxD->DMADONE = 0; + + /* Increase TX_CTX_IDX, but write to register later. */ + INC_RING_INDEX(prTxRing->TxCpuIdx, TX_RING_SIZE); + + prTxRing->u4UsedCnt++; + + kalDevRegWrite(prGlueInfo, prTxRing->hw_cidx_addr, prTxRing->TxCpuIdx); + + return TRUE; +} + +void kalDevReadIntStatus(IN struct ADAPTER *prAdapter, + OUT uint32_t *pu4IntStatus) +{ + uint32_t u4RegValue; + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + *pu4IntStatus = 0; + + HAL_MCR_RD(prAdapter, WPDMA_INT_STA, &u4RegValue); + + if (HAL_IS_RX_DONE_INTR(u4RegValue)) + *pu4IntStatus |= WHISR_RX0_DONE_INT; + + if (HAL_IS_TX_DONE_INTR(u4RegValue)) + *pu4IntStatus |= WHISR_TX_DONE_INT; + + if (u4RegValue & CONNAC_MCU_SW_INT) + *pu4IntStatus |= WHISR_D2H_SW_INT; + + prHifInfo->u4IntStatus = u4RegValue; + + /* clear interrupt */ + HAL_MCR_WR(prAdapter, WPDMA_INT_STA, u4RegValue); + +} + +u_int8_t kalDevWriteCmd(IN struct GLUE_INFO *prGlueInfo, + IN struct CMD_INFO *prCmdInfo, IN uint8_t ucTC) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + if (prHifInfo->fgIsErrRecovery) + return kalDevWriteCmdByQueue(prGlueInfo, prCmdInfo, ucTC); + + return halWpdmaWriteCmd(prGlueInfo, prCmdInfo, ucTC); +} + +static bool kalDevWriteCmdByQueue(struct GLUE_INFO *prGlueInfo, + struct CMD_INFO *prCmdInfo, uint8_t ucTC) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct TX_CMD_REQ *prTxReq; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + prTxReq = kalMemAlloc(sizeof(struct TX_CMD_REQ), PHY_MEM_TYPE); + + if (prTxReq == NULL) { + DBGLOG(HAL, ERROR, "kmalloc() TX_CMD_REQ error\n"); + halWpdmaWriteCmd(prGlueInfo, prCmdInfo, ucTC); + goto error; + } + + prTxReq->prCmdInfo = prCmdInfo; + prTxReq->ucTC = ucTC; + list_add_tail(&prTxReq->list, &prHifInfo->rTxCmdQ); + +error: + + return true; +} + +bool kalDevKickCmd(IN struct GLUE_INFO *prGlueInfo) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct list_head *prCur, *prNext; + struct TX_CMD_REQ *prTxReq; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + list_for_each_safe(prCur, prNext, &prHifInfo->rTxCmdQ) { + prTxReq = list_entry(prCur, struct TX_CMD_REQ, list); + if (prTxReq->prCmdInfo) + halWpdmaWriteCmd(prGlueInfo, + prTxReq->prCmdInfo, prTxReq->ucTC); + list_del(prCur); + kfree(prTxReq); + } + + return true; +} + +static uint8_t kalGetSwAmsduNum(struct GLUE_INFO *prGlueInfo, + struct MSDU_INFO *prMsduInfo) +{ + struct ADAPTER *prAdapter; + struct sk_buff *prSkb; + struct HW_MAC_TX_DESC *prTxDesc; + struct STA_RECORD *prStaRec; + uint8_t ucTid, ucStaRecIndex; + + ASSERT(prGlueInfo); + ASSERT(prMsduInfo); + + prAdapter = prGlueInfo->prAdapter; + prSkb = (struct sk_buff *)prMsduInfo->prPacket; + prTxDesc = (struct HW_MAC_TX_DESC *)prSkb->data; + + ucTid = HAL_MAC_TX_DESC_GET_TID(prTxDesc); + ucStaRecIndex = prMsduInfo->ucStaRecIndex; + if (ucStaRecIndex >= CFG_STA_REC_NUM || ucTid >= TX_DESC_TID_NUM) + return 0; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIndex); + if (!prStaRec || !(prStaRec->ucAmsduEnBitmap & BIT(ucTid))) + return 0; + + return prStaRec->ucMaxMpduCount; +} + +u_int8_t kalDevWriteData(IN struct GLUE_INFO *prGlueInfo, + IN struct MSDU_INFO *prMsduInfo) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prGlueInfo); + + prHifInfo = &prGlueInfo->rHifInfo; + prChipInfo = prGlueInfo->prAdapter->chip_info; + + if (prHifInfo->fgIsErrRecovery || + (prChipInfo->ucMaxSwAmsduNum > 1 && + kalGetSwAmsduNum(prGlueInfo, prMsduInfo) > 1)) + return kalDevWriteDataByQueue(prGlueInfo, prMsduInfo); + + return halWpdmaWriteMsdu(prGlueInfo, prMsduInfo, NULL); +} + +static bool kalDevWriteDataByQueue(IN struct GLUE_INFO *prGlueInfo, + IN struct MSDU_INFO *prMsduInfo) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct TX_DATA_REQ *prTxReq; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + prTxReq = &prMsduInfo->rTxReq; + prTxReq->prMsduInfo = prMsduInfo; + list_add_tail(&prTxReq->list, &prHifInfo->rTxDataQ); + prHifInfo->u4TxDataQLen++; + + return true; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Kick Tx data to device + * + * \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. + * + * \retval TRUE operation success + * \retval FALSE operation fail + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevKickData(IN struct GLUE_INFO *prGlueInfo) +{ + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prGlueInfo); + + prChipInfo = prGlueInfo->prAdapter->chip_info; + + if (prChipInfo->ucMaxSwAmsduNum > 1) + return kalDevKickAmsduData(prGlueInfo); + + return kalDevKickMsduData(prGlueInfo); +} + +static uint16_t kalGetPaddingSize(uint16_t u2TxByteCount) +{ + uint16_t u2Size = 0; + + if (u2TxByteCount & 3) + u2Size = 4 - (u2TxByteCount & 3); + return u2Size; +} + +static uint16_t kalGetMoreSizeForAmsdu(uint32_t u4TxdDW1) +{ + /* + * ETYPE=0/VLAN=0/RMVL=X PLlength = PL length + * ETYPE=0/VLAN=1/RMVL=1 PLlength = PL length - 4 + * ETYPE=0/VLAN=1/RMVL=0 PLlength = PL length + 6 + * ETYPE=1/VLAN=0/RMVL=X PLlength = PL length + 8 + * ETYPE=1/VLAN=1/RMVL=1 PLlength = PL length + 4 + * ETYPE=1/VLAN=1/RMVL=0 PLlength = PL length + 14 + */ + uint16_t u2Size = 0; + + if (u4TxdDW1 & TXD_DW1_ETYP) + u2Size += 8; + if (u4TxdDW1 & TXD_DW1_VLAN) { + if (u4TxdDW1 & TXD_DW1_RMVL) + u2Size -= 4; + else + u2Size += 6; + } + return u2Size; +} + +static bool kalDevKickMsduData(struct GLUE_INFO *prGlueInfo) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct BUS_INFO *prBusInfo = NULL; + struct list_head *prCur, *prNext; + struct TX_DATA_REQ *prTxReq; + struct MSDU_INFO *prMsduInfo; + bool fgRet = true; + + ASSERT(prGlueInfo); + + prHifInfo = &prGlueInfo->rHifInfo; + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + + list_for_each_safe(prCur, prNext, &prHifInfo->rTxDataQ) { + prTxReq = list_entry(prCur, struct TX_DATA_REQ, list); + prMsduInfo = prTxReq->prMsduInfo; + if (!prMsduInfo || + !halWpdmaWriteMsdu(prGlueInfo, prMsduInfo, prCur)) { + fgRet = false; + break; + } + } + + return fgRet; +} + +static int kalAmsduTxDCmp(void *prPriv, struct list_head *prList1, + struct list_head *prList2) +{ + struct TX_DATA_REQ *prTxReq1, *prTxReq2; + struct sk_buff *prSkb1, *prSkb2; + struct AMSDU_MAC_TX_DESC *prTxD1, *prTxD2; + + prTxReq1 = list_entry(prList1, struct TX_DATA_REQ, list); + prTxReq2 = list_entry(prList2, struct TX_DATA_REQ, list); + prSkb1 = (struct sk_buff *)prTxReq1->prMsduInfo->prPacket; + prSkb2 = (struct sk_buff *)prTxReq2->prMsduInfo->prPacket; + prTxD1 = (struct AMSDU_MAC_TX_DESC *)prSkb1->data; + prTxD2 = (struct AMSDU_MAC_TX_DESC *)prSkb2->data; + + if (prTxD1->u2DW0 != prTxD2->u2DW0) + return prTxD2->u2DW0 - prTxD1->u2DW0; + + return prTxD1->u4DW1 - prTxD2->u4DW1; +} + +static bool kalIsAggregatedMsdu(struct GLUE_INFO *prGlueInfo, + struct MSDU_INFO *prMsduInfo) +{ + struct sk_buff *prSkb; + struct AMSDU_MAC_TX_DESC *prTxD; + + prSkb = (struct sk_buff *)prMsduInfo->prPacket; + prTxD = (struct AMSDU_MAC_TX_DESC *)prSkb->data; + + if (prTxD->u4FR || prTxD->u4TXS) + return false; + return true; +} + +static uint32_t kalGetNumOfAmsdu(struct GLUE_INFO *prGlueInfo, + struct list_head *prTarget, + struct list_head *prHead, + uint16_t *pu2Size) +{ + struct TX_DATA_REQ *prTxReq; + struct MSDU_INFO *prMsduInfo; + struct sk_buff *prSkb; + struct AMSDU_MAC_TX_DESC *prTxD; + struct STA_RECORD *prStaRec; + struct list_head *prCur; + uint16_t u2TotalSize, u2Size; + uint32_t u4Cnt = 1; + uint8_t ucStaRecIndex; + + prTxReq = list_entry(prTarget, struct TX_DATA_REQ, list); + prMsduInfo = prTxReq->prMsduInfo; + prSkb = (struct sk_buff *)prMsduInfo->prPacket; + prTxD = (struct AMSDU_MAC_TX_DESC *)prSkb->data; + + ucStaRecIndex = prMsduInfo->ucStaRecIndex; + prStaRec = cnmGetStaRecByIndex(prGlueInfo->prAdapter, ucStaRecIndex); + if (!prStaRec) + return 1; + + u2TotalSize = NIC_TX_DESC_LONG_FORMAT_LENGTH; + u2TotalSize += prMsduInfo->u2FrameLength; + u2TotalSize += kalGetMoreSizeForAmsdu(prTxD->u4DW1); + + for (prCur = prTarget->next; prCur != prHead; prCur = prCur->next) { + if (u4Cnt >= kalGetSwAmsduNum(prGlueInfo, prMsduInfo) || + kalAmsduTxDCmp((void *)prGlueInfo, prTarget, prCur)) + break; + + prTxReq = list_entry(prCur, struct TX_DATA_REQ, list); + prMsduInfo = prTxReq->prMsduInfo; + prSkb = (struct sk_buff *)prMsduInfo->prPacket; + prTxD = (struct AMSDU_MAC_TX_DESC *)prSkb->data; + + u2Size = prMsduInfo->u2FrameLength; + u2Size += kalGetMoreSizeForAmsdu(prTxD->u4DW1); + u2Size += kalGetPaddingSize(u2TotalSize); + if ((u2TotalSize + u2Size) > prStaRec->u4MaxMpduLen) + break; + + u2TotalSize += u2Size; + u4Cnt++; + } + + if (u2TotalSize < prStaRec->u4MinMpduLen) + return 1; + + *pu2Size = u2TotalSize; + return u4Cnt; +} + +static bool kalDevKickAmsduData(struct GLUE_INFO *prGlueInfo) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + struct BUS_INFO *prBusInfo = NULL; + struct list_head *prHead, *prCur, *prNext; + struct TX_DATA_REQ *prTxReq; + struct MSDU_INFO *prMsduInfo; + uint32_t u4Num = 0, u4Idx; + uint16_t u2Size = 0; + bool fgRet = true; + + ASSERT(prGlueInfo); + + prHifInfo = &prGlueInfo->rHifInfo; + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + + prHead = &prHifInfo->rTxDataQ; + list_for_each_safe(prCur, prNext, prHead) { + prTxReq = list_entry(prCur, struct TX_DATA_REQ, list); + prMsduInfo = prTxReq->prMsduInfo; + if (!kalIsAggregatedMsdu(prGlueInfo, prMsduInfo)) { + if (!halWpdmaWriteMsdu(prGlueInfo, prMsduInfo, prCur)) + return false; + } + } + + list_sort((void *)prGlueInfo, prHead, kalAmsduTxDCmp); + + for (prCur = prHead->next; prCur != prHead; prCur = prNext) { + u4Num = kalGetNumOfAmsdu(prGlueInfo, prCur, prHead, &u2Size); + prNext = prCur->next; + if (u4Num > 1) { + for (u4Idx = 1; u4Idx < u4Num; u4Idx++) + prNext = prNext->next; + fgRet = halWpdmaWriteAmsdu(prGlueInfo, prCur, + u4Num, u2Size); + } else { + prTxReq = list_entry(prCur, struct TX_DATA_REQ, list); + prMsduInfo = prTxReq->prMsduInfo; + fgRet = halWpdmaWriteMsdu(prGlueInfo, prMsduInfo, + prCur); + } + if (!fgRet) + break; + } + + return fgRet; +} + +bool kalDevReadData(struct GLUE_INFO *prGlueInfo, uint16_t u2Port, + struct SW_RFB *prSwRfb) +{ + struct ADAPTER *prAdapter = NULL; + struct GL_HIF_INFO *prHifInfo = NULL; + struct HIF_MEM_OPS *prMemOps; + struct RXD_STRUCT *pRxD; + struct RTMP_RX_RING *prRxRing; + struct RTMP_DMACB *pRxCell; + struct RTMP_DMABUF *prDmaBuf; + u_int8_t fgRet = TRUE; + uint32_t u4CpuIdx = 0; + + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + prHifInfo = &prGlueInfo->rHifInfo; + prMemOps = &prHifInfo->rMemOps; + prRxRing = &prHifInfo->RxRing[u2Port]; + + kalDevRegRead(prGlueInfo, prRxRing->hw_cidx_addr, &prRxRing->RxCpuIdx); + u4CpuIdx = prRxRing->RxCpuIdx; + INC_RING_INDEX(u4CpuIdx, prRxRing->u4RingSize); + + pRxCell = &prRxRing->Cell[u4CpuIdx]; + pRxD = (struct RXD_STRUCT *)pRxCell->AllocVa; + + if (halWpdmaGetRxDmaDoneCnt(prGlueInfo, u2Port) == 0) + return FALSE; + + if (!kalWaitRxDmaDone(prGlueInfo, prRxRing, pRxD, u2Port)) { + if (!prRxRing->fgIsDumpLog) { + prAdapter->u4HifDbgFlag |= DEG_HIF_DEFAULT_DUMP; + halPrintHifDbgInfo(prAdapter); + } + prRxRing->fgIsDumpLog = true; + return false; + } + + if (pRxD->LastSec0 == 0 || prRxRing->fgRxSegPkt) { + /* Rx segmented packet */ + DBGLOG(HAL, WARN, + "Skip Rx segmented data packet, SDL0[%u] LS0[%u]\n", + pRxD->SDLen0, pRxD->LastSec0); + if (pRxD->LastSec0 == 1) { + /* Last segmented packet */ + prRxRing->fgRxSegPkt = FALSE; + } else { + /* Segmented packet */ + prRxRing->fgRxSegPkt = TRUE; + } + + fgRet = false; + goto skip; + } + + prDmaBuf = &pRxCell->DmaBuf; + + if (prMemOps->flushCache) + prMemOps->flushCache(prHifInfo, prDmaBuf->AllocVa, + pRxD->SDLen0); + + if (prMemOps->copyRxData && + !prMemOps->copyRxData(prHifInfo, pRxCell, prDmaBuf, prSwRfb)) + return FALSE; + + prSwRfb->pucRecvBuff = ((struct sk_buff *)prSwRfb->pvPacket)->data; + prSwRfb->prRxStatus = (struct HW_MAC_RX_DESC *)prSwRfb->pucRecvBuff; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + prSwRfb->u4TcpUdpIpCksStatus = pRxD->RXINFO; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + pRxD->SDPtr0 = (uint64_t)prDmaBuf->AllocPa & DMA_LOWER_32BITS_MASK; + pRxD->SDPtr1 = ((uint64_t)prDmaBuf->AllocPa >> + DMA_BITS_OFFSET) & DMA_HIGHER_4BITS_MASK; +skip: + pRxD->SDLen0 = prRxRing->u4BufSize; + pRxD->DMADONE = 0; + + prRxRing->RxCpuIdx = u4CpuIdx; + kalDevRegWrite(prGlueInfo, prRxRing->hw_cidx_addr, prRxRing->RxCpuIdx); + prRxRing->fgIsDumpLog = false; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + if (fgRet) + DBGLOG(RX, LOUD, "u4TcpUdpIpCksStatus[0x%02x]\n", + prSwRfb->u4TcpUdpIpCksStatus); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + return fgRet; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/ehpi/arm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/ehpi/arm.c new file mode 100644 index 0000000000000..cfd20641f86be --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/ehpi/arm.c @@ -0,0 +1,539 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/ehpi/arm.c#1 +*/ + +/*! \file "colibri.c" +* \brief Brief description. +* +* Detail description. +*/ + + +/****************************************************************************** +* C O M P I L E R F L A G S +******************************************************************************* +*/ +#if !defined(MCR_EHTCR) +#define MCR_EHTCR 0x0054 +#endif + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "colibri.h" +#include "wlan_lib.h" + +/******************************************************************************* +* 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 void __iomem *mt5931_mcr_base; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#if CFG_EHPI_FASTER_BUS_TIMING +#define EHPI_CONFIG MSC_CS(4, MSC_RBUFF_SLOW | \ + MSC_RRR(4) | \ + MSC_RDN(8) | \ + MSC_RDF(7) | \ + MSC_RBW_16 | \ + MSC_RT_VLIO) +#else +#define EHPI_CONFIG MSC_CS(4, MSC_RBUFF_SLOW | \ + MSC_RRR(7) | \ + MSC_RDN(13) | \ + MSC_RDF(12) | \ + MSC_RBW_16 | \ + MSC_RT_VLIO) +#endif /* CFG_EHPI_FASTER_BUS_TIMING */ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static void collibri_ehpi_reg_init(void); + +static void collibri_ehpi_reg_uninit(void); + +static void mt5931_ehpi_reg_init(void); + +static void mt5931_ehpi_reg_uninit(void); + +static void busSetIrq(void); + +static void busFreeIrq(void); + +static irqreturn_t glEhpiInterruptHandler(int irq, void *dev_id); + +#if DBG +static void initTrig(void); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will register sdio bus to the os +* +* \param[in] pfProbe Function pointer to detect card +* \param[in] pfRemove Function pointer to remove card +* +* \return The result of registering sdio bus +*/ +/*----------------------------------------------------------------------------*/ +uint32_t glRegisterBus(probe_card pfProbe, remove_card pfRemove) +{ + + ASSERT(pfProbe); + ASSERT(pfRemove); + + pr_info("mtk_sdio: MediaTek eHPI WLAN driver\n"); + pr_info("mtk_sdio: Copyright MediaTek Inc.\n"); + + if (pfProbe(NULL) != WLAN_STATUS_SUCCESS) { + pfRemove(); + return WLAN_STATUS_FAILURE; + } + + return WLAN_STATUS_SUCCESS; +} /* 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(); + + /* TODO: eHPI uninitialization */ +} /* 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(struct GLUE_INFO *prGlueInfo, unsigned long ulCookie) +{ + struct GL_HIF_INFO *prHif = NULL; + + ASSERT(prGlueInfo); + + prHif = &prGlueInfo->rHifInfo; + + /* fill some buffered information into prHif */ + prHif->mcr_addr_base = mt5931_mcr_base + EHPI_OFFSET_ADDR; + prHif->mcr_data_base = mt5931_mcr_base + EHPI_OFFSET_DATA; + + prGlueInfo->u4InfType = MT_DEV_INF_EHPI; +} /* end of glSetHifInfo() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function clears hif related info. +* +* \param[in] prGlueInfo Pointer to glue info structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void glClearHifInfo(struct GLUE_INFO *prGlueInfo) +{ + struct GL_HIF_INFO *prHif = NULL; + + ASSERT(prGlueInfo); + + prHif = &prGlueInfo->rHifInfo; + + /* do something */ + prHif->mcr_addr_base = 0; + prHif->mcr_data_base = 0; +} /* 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) +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t glBusInit(void *pvData) +{ +#if DBG + initTrig(); +#endif + + /* 1. initialize eHPI control registers */ + collibri_ehpi_reg_init(); + + /* 2. memory remapping for MT5931 */ + mt5931_ehpi_reg_init(); + + return TRUE; +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus operation and release resources. +* +* \param[in] pvData A pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void glBusRelease(void *pvData) +{ + /* 1. memory unmapping for MT5931 */ + mt5931_ehpi_reg_uninit(); + + /* 2. uninitialize eHPI control registers */ + collibri_ehpi_reg_uninit(); +} /* 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 +*/ +/*----------------------------------------------------------------------------*/ +int32_t glBusSetIrq(void *pvData, void *pfnIsr, void *pvCookie) +{ + struct net_device *pDev = (struct net_device *)pvData; + int i4Status = 0; + + /* 1. enable GPIO pin as IRQ */ + busSetIrq(); + + /* 2. Specify IRQ number into net_device */ + pDev->irq = WLAN_STA_IRQ; + + /* 3. register ISR callback */ + + i4Status = request_irq(pDev->irq, + glEhpiInterruptHandler, + IRQF_DISABLED | IRQF_SHARED | IRQF_TRIGGER_FALLING, pDev->name, pvCookie); + + if (i4Status < 0) + pr_debug("request_irq(%d) failed\n", pDev->irq); + else + pr_info("request_irq(%d) success with dev_id(%x)\n", pDev->irq, (unsigned int)pvCookie); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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(void *pvData, void *pvCookie) +{ + struct net_device *prDev = (struct net_device *)pvData; + + if (!prDev) { + pr_info("Invalid net_device context.\n"); + return; + } + + if (prDev->irq) { + disable_irq(prDev->irq); + free_irq(prDev->irq, pvCookie); + prDev->irq = 0; + } + + busFreeIrq(); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set power state +* +* \param[in] pvGlueInfo A pointer to GLUE_INFO_T +* \param[in] ePowerMode Power Mode Setting +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void glSetPowerState(IN struct GLUE_INFO *prGlueInfo, IN uint32_t ePowerMode) +{ +} + +#if DBG +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setup the GPIO pin. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void setTrig(void) +{ + GPSR1 = (0x1UL << 8); +} /* end of setTrig() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Clear the GPIO pin. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void clearTrig(void) +{ + GPCR1 = (0x1UL << 8); +} /* end of clearTrig() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set a specified GPIO pin to H or L. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static void initTrig(void) +{ + set_GPIO_mode(GPIO40_FFDTR | GPIO_OUT); + clearTrig(); +} /* end of initTrig() */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function congifure platform-dependent interrupt triger type. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void busSetIrq(void) +{ +#if defined(WLAN_STA_IRQ_GPIO) + pxa_gpio_mode(WLAN_STA_IRQ_GPIO | GPIO_IN); + set_irq_type(WLAN_STA_IRQ, IRQT_FALLING); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function should restore settings changed by busSetIrq(). +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void busFreeIrq(void) +{ +#if defined(WLAN_STA_IRQ_GPIO) + pxa_gpio_mode(WLAN_STA_IRQ_GPIO | GPIO_OUT); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function configures colibri memory controller registers +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static void collibri_ehpi_reg_init(void) +{ + uint32_t u4RegValue; + + /* 1. enable nCS as memory controller */ + pxa_gpio_mode(GPIO80_nCS_4_MD); + + /* 2. nCS<4> configuration */ + u4RegValue = MSC2; + u4RegValue &= ~MSC_CS(4, 0xFFFF); + u4RegValue |= EHPI_CONFIG; + MSC2 = u4RegValue; + + pr_info("EHPI new MSC2:0x%08x\n", MSC2); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function restores colibri memory controller registers +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static void collibri_ehpi_reg_uninit(void) +{ + uint32_t u4RegValue; + + /* 1. restore nCS<4> configuration */ + u4RegValue = MSC2; + u4RegValue &= ~MSC_CS(4, 0xFFFF); + MSC2 = u4RegValue; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function configures MT5931 mapped registers on colibri +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static void mt5931_ehpi_reg_init(void) +{ + struct resource *reso = NULL; + + /* 1. request memory regioin */ + reso = request_mem_region((unsigned long)MEM_MAPPED_ADDR, (unsigned long)MEM_MAPPED_LEN, (char *)MODULE_PREFIX); + if (!reso) { + DBGLOG(INIT, ERROR, + "request_mem_region(0x%08X) failed.\n", + MEM_MAPPED_ADDR); + return; + } + + /* 2. memory regioin remapping */ + mt5931_mcr_base = ioremap_nocache(MEM_MAPPED_ADDR, MEM_MAPPED_LEN); + if (!(mt5931_mcr_base)) { + release_mem_region(MEM_MAPPED_ADDR, MEM_MAPPED_LEN); + DBGLOG(INIT, ERROR, + "ioremap_nocache(0x%08X) failed.\n", MEM_MAPPED_ADDR); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function releases MT5931 mapped registers on colibri +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static void mt5931_ehpi_reg_uninit(void) +{ + iounmap(mt5931_mcr_base); + mt5931_mcr_base = NULL; + + release_mem_region(MEM_MAPPED_ADDR, MEM_MAPPED_LEN); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Callback for interrupt coming from device +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static irqreturn_t glEhpiInterruptHandler(int irq, void *dev_id) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) dev_id; + + ASSERT(prGlueInfo); + + if (!prGlueInfo) + return IRQ_HANDLED; + + /* 1. Running for ISR */ + wlanISR(prGlueInfo->prAdapter, TRUE); + + /* 1.1 Halt flag Checking */ + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) + return IRQ_HANDLED; + + /* 2. Flag marking for interrupt */ + set_bit(GLUE_FLAG_INT_BIT, &prGlueInfo->ulFlag); + + /* 3. wake up tx service thread */ + wake_up_interruptible(&prGlueInfo->waitq); + + return IRQ_HANDLED; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/ehpi/colibri.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/ehpi/colibri.c new file mode 100644 index 0000000000000..adf77dc9f3619 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/ehpi/colibri.c @@ -0,0 +1,541 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/ehpi/colibri.c#1 +*/ + +/*! \file "colibri.c" +* \brief Brief description. +* +* Detail description. +*/ + + +/****************************************************************************** +* C O M P I L E R F L A G S +******************************************************************************* +*/ +#if !defined(MCR_EHTCR) +#define MCR_EHTCR 0x0054 +#endif + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "colibri.h" +#include "wlan_lib.h" + +/******************************************************************************* +* 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 void __iomem *mt5931_mcr_base; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#if CFG_EHPI_FASTER_BUS_TIMING +#define EHPI_CONFIG MSC_CS(4, MSC_RBUFF_SLOW | \ + MSC_RRR(4) | \ + MSC_RDN(8) | \ + MSC_RDF(7) | \ + MSC_RBW_16 | \ + MSC_RT_VLIO) +#else +#define EHPI_CONFIG MSC_CS(4, MSC_RBUFF_SLOW | \ + MSC_RRR(7) | \ + MSC_RDN(13) | \ + MSC_RDF(12) | \ + MSC_RBW_16 | \ + MSC_RT_VLIO) +#endif /* CFG_EHPI_FASTER_BUS_TIMING */ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static void collibri_ehpi_reg_init(void); + +static void collibri_ehpi_reg_uninit(void); + +static void mt5931_ehpi_reg_init(void); + +static void mt5931_ehpi_reg_uninit(void); + +static void busSetIrq(void); + +static void busFreeIrq(void); + +static irqreturn_t glEhpiInterruptHandler(int irq, void *dev_id); + +#if DBG +static void initTrig(void); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will register sdio bus to the os +* +* \param[in] pfProbe Function pointer to detect card +* \param[in] pfRemove Function pointer to remove card +* +* \return The result of registering sdio bus +*/ +/*----------------------------------------------------------------------------*/ +uint32_t glRegisterBus(probe_card pfProbe, remove_card pfRemove) +{ + + ASSERT(pfProbe); + ASSERT(pfRemove); + + DBGLOG(INIT, INFO, "mtk_sdio: MediaTek eHPI WLAN driver\n"); + DBGLOG(INIT, INFO, "mtk_sdio: Copyright MediaTek Inc.\n"); + + if (pfProbe(NULL) != WLAN_STATUS_SUCCESS) { + pfRemove(); + return WLAN_STATUS_FAILURE; + } + + return WLAN_STATUS_SUCCESS; +} /* 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(); + + /* TODO: eHPI uninitialization */ +} /* 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(struct GLUE_INFO *prGlueInfo, unsigned long ulCookie) +{ + struct GL_HIF_INFO *prHif = NULL; + + ASSERT(prGlueInfo); + + prHif = &prGlueInfo->rHifInfo; + + /* fill some buffered information into prHif */ + prHif->mcr_addr_base = mt5931_mcr_base + EHPI_OFFSET_ADDR; + prHif->mcr_data_base = mt5931_mcr_base + EHPI_OFFSET_DATA; + + prGlueInfo->u4InfType = MT_DEV_INF_EHPI; +} /* end of glSetHifInfo() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function clears hif related info. +* +* \param[in] prGlueInfo Pointer to glue info structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void glClearHifInfo(struct GLUE_INFO *prGlueInfo) +{ + struct GL_HIF_INFO *prHif = NULL; + + ASSERT(prGlueInfo); + + prHif = &prGlueInfo->rHifInfo; + + /* do something */ + prHif->mcr_addr_base = 0; + prHif->mcr_data_base = 0; +} /* 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) +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t glBusInit(void *pvData) +{ +#if DBG + initTrig(); +#endif + + /* 1. initialize eHPI control registers */ + collibri_ehpi_reg_init(); + + /* 2. memory remapping for MT5931 */ + mt5931_ehpi_reg_init(); + + return TRUE; +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus operation and release resources. +* +* \param[in] pvData A pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void glBusRelease(void *pvData) +{ + /* 1. memory unmapping for MT5931 */ + mt5931_ehpi_reg_uninit(); + + /* 2. uninitialize eHPI control registers */ + collibri_ehpi_reg_uninit(); +} /* 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 +*/ +/*----------------------------------------------------------------------------*/ +int32_t glBusSetIrq(void *pvData, void *pfnIsr, void *pvCookie) +{ + struct net_device *pDev = (struct net_device *)pvData; + int i4Status = 0; + + /* 1. enable GPIO pin as IRQ */ + busSetIrq(); + + /* 2. Specify IRQ number into net_device */ + pDev->irq = WLAN_STA_IRQ; + + /* 3. register ISR callback */ + + i4Status = request_irq(pDev->irq, + glEhpiInterruptHandler, + IRQF_DISABLED | IRQF_SHARED | IRQF_TRIGGER_FALLING, pDev->name, pvCookie); + + if (i4Status < 0) + DBGLOG(INIT, LOUD, "request_irq(%d) failed\n", pDev->irq); + else + DBGLOG(INIT, INFO, + "request_irq(%d) success with dev_id(%x)\n", + pDev->irq, (unsigned int)pvCookie); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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(void *pvData, void *pvCookie) +{ + struct net_device *prDev = (struct net_device *)pvData; + + if (!prDev) { + DBGLOG(INIT, INFO, "Invalid net_device context.\n"); + return; + } + + if (prDev->irq) { + disable_irq(prDev->irq); + free_irq(prDev->irq, pvCookie); + prDev->irq = 0; + } + + busFreeIrq(); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set power state +* +* \param[in] pvGlueInfo A pointer to GLUE_INFO_T +* \param[in] ePowerMode Power Mode Setting +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void glSetPowerState(IN struct GLUE_INFO *prGlueInfo, IN uint32_t ePowerMode) +{ +} + +#if DBG +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setup the GPIO pin. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void setTrig(void) +{ + GPSR1 = (0x1UL << 8); +} /* end of setTrig() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Clear the GPIO pin. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void clearTrig(void) +{ + GPCR1 = (0x1UL << 8); +} /* end of clearTrig() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set a specified GPIO pin to H or L. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static void initTrig(void) +{ + set_GPIO_mode(GPIO40_FFDTR | GPIO_OUT); + clearTrig(); +} /* end of initTrig() */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function congifure platform-dependent interrupt triger type. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void busSetIrq(void) +{ +#if defined(WLAN_STA_IRQ_GPIO) + pxa_gpio_mode(WLAN_STA_IRQ_GPIO | GPIO_IN); + set_irq_type(WLAN_STA_IRQ, IRQT_FALLING); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function should restore settings changed by busSetIrq(). +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void busFreeIrq(void) +{ +#if defined(WLAN_STA_IRQ_GPIO) + pxa_gpio_mode(WLAN_STA_IRQ_GPIO | GPIO_OUT); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function configures colibri memory controller registers +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static void collibri_ehpi_reg_init(void) +{ + uint32_t u4RegValue; + + /* 1. enable nCS as memory controller */ + pxa_gpio_mode(GPIO80_nCS_4_MD); + + /* 2. nCS<4> configuration */ + u4RegValue = MSC2; + u4RegValue &= ~MSC_CS(4, 0xFFFF); + u4RegValue |= EHPI_CONFIG; + MSC2 = u4RegValue; + + DBGLOG(INIT, INFO, "EHPI new MSC2:0x%08x\n", MSC2); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function restores colibri memory controller registers +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static void collibri_ehpi_reg_uninit(void) +{ + uint32_t u4RegValue; + + /* 1. restore nCS<4> configuration */ + u4RegValue = MSC2; + u4RegValue &= ~MSC_CS(4, 0xFFFF); + MSC2 = u4RegValue; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function configures MT5931 mapped registers on colibri +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static void mt5931_ehpi_reg_init(void) +{ + struct resource *reso = NULL; + + /* 1. request memory regioin */ + reso = request_mem_region((unsigned long)MEM_MAPPED_ADDR, (unsigned long)MEM_MAPPED_LEN, (char *)MODULE_PREFIX); + if (!reso) { + DBGLOG(INIT, ERROR, + "request_mem_region(0x%08X) failed.\n", + MEM_MAPPED_ADDR); + return; + } + + /* 2. memory regioin remapping */ + mt5931_mcr_base = ioremap_nocache(MEM_MAPPED_ADDR, MEM_MAPPED_LEN); + if (!(mt5931_mcr_base)) { + release_mem_region(MEM_MAPPED_ADDR, MEM_MAPPED_LEN); + DBGLOG(INIT, ERROR, + "ioremap_nocache(0x%08X) failed.\n", MEM_MAPPED_ADDR); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function releases MT5931 mapped registers on colibri +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static void mt5931_ehpi_reg_uninit(void) +{ + iounmap(mt5931_mcr_base); + mt5931_mcr_base = NULL; + + release_mem_region(MEM_MAPPED_ADDR, MEM_MAPPED_LEN); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Callback for interrupt coming from device +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static irqreturn_t glEhpiInterruptHandler(int irq, void *dev_id) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) dev_id; + + ASSERT(prGlueInfo); + + if (!prGlueInfo) + return IRQ_HANDLED; + + /* 1. Running for ISR */ + wlanISR(prGlueInfo->prAdapter, TRUE); + + /* 1.1 Halt flag Checking */ + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) + return IRQ_HANDLED; + + /* 2. Flag marking for interrupt */ + set_bit(GLUE_FLAG_INT_BIT, &prGlueInfo->ulFlag); + + /* 3. wake up tx service thread */ + wake_up_interruptible(&prGlueInfo->waitq); + + return IRQ_HANDLED; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/ehpi/ehpi.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/ehpi/ehpi.c new file mode 100644 index 0000000000000..1ca0aaf9feeed --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/ehpi/ehpi.c @@ -0,0 +1,414 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/ehpi/ehpi.c#1 +*/ + +/*! \file "ehpi.c" +* \brief Brief description. +* +* Detail description. +*/ + + +/****************************************************************************** +* C O M P I L E R F L A G S +******************************************************************************* +*/ +#if !defined(MCR_EHTCR) +#define MCR_EHTCR 0x0054 +#endif + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "colibri.h" +#include "wlan_lib.h" + +/******************************************************************************* +* 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 u_int8_t kalDevRegRead_impl(IN struct GLUE_INFO *prGlueInfo, IN uint32_t u4Register, OUT uint32_t *pu4Value); + +static u_int8_t kalDevRegWrite_impl(IN struct GLUE_INFO *prGlueInfo, IN uint32_t u4Register, IN uint32_t u4Value); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to read a 32 bit register value from device. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u4Register The register offset. +* \param[out] pu4Value Pointer to the 32-bit value of the register been read. +* +* \retval TRUE +* \retval FALSE +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevRegRead(IN struct GLUE_INFO *prGlueInfo, IN uint32_t u4Register, OUT uint32_t *pu4Value) +{ + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + ASSERT(pu4Value); + + /* 0. acquire spinlock */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + /* 1. I/O stuff */ + kalDevRegRead_impl(prGlueInfo, u4Register, pu4Value); + + /* 2. release spin lock */ + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to write a 32 bit register value to device. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u4Register The register offset. +* \param[out] u4Value The 32-bit value of the register to be written. +* +* \retval TRUE +* \retval FALSE +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevRegWrite(struct GLUE_INFO *prGlueInfo, IN uint32_t u4Register, IN uint32_t u4Value) +{ + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + /* 0. acquire spinlock */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + /* 1. I/O stuff */ + kalDevRegWrite_impl(prGlueInfo, u4Register, u4Value); + + /* 2. release spin lock */ + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to read port data from device in unit of byte. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u2Port The register offset. +* \param[in] u2Len The number of byte to be read. +* \param[out] pucBuf Pointer to data buffer for read +* \param[in] u2ValidOutBufSize Length of the buffer valid to be accessed +* +* \retval TRUE +* \retval FALSE +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t +kalDevPortRead(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port, IN uint16_t u2Len, OUT uint8_t *pucBuf, IN uint16_t u2ValidOutBufSize) +{ + uint32_t i; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + /* 0. acquire spinlock */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + /* 1. indicate correct length to HIFSYS if larger than 4-bytes */ + if (u2Len > 4) + kalDevRegWrite_impl(prGlueInfo, MCR_EHTCR, ALIGN_4(u2Len)); + + /* 2. address cycle */ +#if EHPI16 + writew(u2Port, prGlueInfo->rHifInfo.mcr_addr_base); +#elif EHPI8 + writew((u2Port & 0xFF), prGlueInfo->rHifInfo.mcr_addr_base); + writew(((u2Port & 0xFF00) >> 8), prGlueInfo->rHifInfo.mcr_addr_base); +#endif + + /* 3. data cycle */ + for (i = 0; i < ALIGN_4(u2Len); i += 4) { +#if EHPI16 + *((uint16_t *)&(pucBuf[i])) = (uint16_t) (readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFFFF); + *((uint16_t *)&(pucBuf[i + 2])) = (uint16_t) (readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFFFF); +#elif EHPI8 + *((uint8_t *)&(pucBuf[i])) = (uint8_t) (readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF); + *((uint8_t *)&(pucBuf[i + 1])) = (uint8_t) (readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF); + *((uint8_t *)&(pucBuf[i + 2])) = (uint8_t) (readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF); + *((uint8_t *)&(pucBuf[i + 3])) = (uint8_t) (readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF); +#endif + } + + /* 4. restore length to 4 if necessary */ + if (u2Len > 4) + kalDevRegWrite_impl(prGlueInfo, MCR_EHTCR, 4); + + /* 5. release spin lock */ + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to write port data to device in unit of byte. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u2Port The register offset. +* \param[in] u2Len The number of byte to be write. +* \param[out] pucBuf Pointer to data buffer for write +* \param[in] u2ValidOutBufSize Length of the buffer valid to be accessed +* +* \retval TRUE +* \retval FALSE +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t +kalDevPortWrite(struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port, IN uint16_t u2Len, IN uint8_t *pucBuf, IN uint16_t u2ValidInBufSize) +{ + uint32_t i; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + /* 0. acquire spinlock */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + /* 1. indicate correct length to HIFSYS if larger than 4-bytes */ + if (u2Len > 4) + kalDevRegWrite_impl(prGlueInfo, MCR_EHTCR, ALIGN_4(u2Len)); + + /* 2. address cycle */ +#if EHPI16 + writew(u2Port, prGlueInfo->rHifInfo.mcr_addr_base); +#elif EHPI8 + writew((u2Port & 0xFF), prGlueInfo->rHifInfo.mcr_addr_base); + writew(((u2Port & 0xFF00) >> 8), prGlueInfo->rHifInfo.mcr_addr_base); +#endif + + /* 3. data cycle */ + for (i = 0; i < ALIGN_4(u2Len); i += 4) { +#if EHPI16 + writew((uint32_t) (*((uint16_t *)&(pucBuf[i]))), prGlueInfo->rHifInfo.mcr_data_base); + writew((uint32_t) (*((uint16_t *)&(pucBuf[i + 2]))), prGlueInfo->rHifInfo.mcr_data_base); +#elif EHPI8 + writew((uint32_t) (*((uint8_t *)&(pucBuf[i]))), prGlueInfo->rHifInfo.mcr_data_base); + writew((uint32_t) (*((uint8_t *)&(pucBuf[i + 1]))), prGlueInfo->rHifInfo.mcr_data_base); + writew((uint32_t) (*((uint8_t *)&(pucBuf[i + 2]))), prGlueInfo->rHifInfo.mcr_data_base); + writew((uint32_t) (*((uint8_t *)&(pucBuf[i + 3]))), prGlueInfo->rHifInfo.mcr_data_base); +#endif + } + + /* 4. restore length to 4 if necessary */ + if (u2Len > 4) + kalDevRegWrite_impl(prGlueInfo, MCR_EHTCR, 4); + + /* 5. release spin lock */ + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write device I/O port with single byte (for SDIO compatibility) +* +* \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 +* \param[in] u4ValidInBufSize Length of the buffer valid to be accessed +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevWriteWithSdioCmd52(IN struct GLUE_INFO *prGlueInfo, IN uint32_t u4Addr, IN uint8_t ucData) +{ + uint32_t u4RegValue; + u_int8_t bRet; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + /* 0. acquire spinlock */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + /* 1. there is no single byte access support for eHPI, use 4-bytes write-after-read approach instead */ + if (kalDevRegRead_impl(prGlueInfo, u4Addr, &u4RegValue) == TRUE) { + u4RegValue &= 0x00; + u4RegValue |= ucData; + + bRet = kalDevRegWrite_impl(prGlueInfo, u4Addr, u4RegValue); + } else { + bRet = FALSE; + } + + /* 2. release spin lock */ + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + return bRet; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to read a 32 bit register value from device +* without spin lock protection and dedicated for internal use +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u4Register The register offset. +* \param[out] pu4Value Pointer to the 32-bit value of the register been read. +* +* \retval TRUE +* \retval FALSE +*/ +/*----------------------------------------------------------------------------*/ +static u_int8_t kalDevRegRead_impl(IN struct GLUE_INFO *prGlueInfo, IN uint32_t u4Register, OUT uint32_t *pu4Value) +{ + ASSERT(prGlueInfo); + + /* 1. address cycle */ +#if EHPI16 + writew(u4Register, prGlueInfo->rHifInfo.mcr_addr_base); +#elif EHPI8 + writew((u4Register & 0xFF), prGlueInfo->rHifInfo.mcr_addr_base); + writew(((u4Register & 0xFF00) >> 8), prGlueInfo->rHifInfo.mcr_addr_base); +#endif + + /* 2. data cycle */ +#if EHPI16 + *pu4Value = (readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFFFF); + *pu4Value |= ((readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFFFF) << 16); +#elif EHPI8 + *pu4Value = (readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF); + *pu4Value |= ((readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF) << 8); + *pu4Value |= ((readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF) << 16); + *pu4Value |= ((readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF) << 24); +#endif + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to write a 32 bit register value to device. +* without spin lock protection and dedicated for internal use +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u4Register The register offset. +* \param[out] u4Value The 32-bit value of the register to be written. +* +* \retval TRUE +* \retval FALSE +*/ +/*----------------------------------------------------------------------------*/ +static u_int8_t kalDevRegWrite_impl(IN struct GLUE_INFO *prGlueInfo, IN uint32_t u4Register, IN uint32_t u4Value) +{ + ASSERT(prGlueInfo); + + /* 1. address cycle */ +#if EHPI16 + writew(u4Register, prGlueInfo->rHifInfo.mcr_addr_base); +#elif EHPI8 + writew((u4Register & 0xFF), prGlueInfo->rHifInfo.mcr_addr_base); + writew(((u4Register & 0xFF00) >> 8), prGlueInfo->rHifInfo.mcr_addr_base); +#endif + + /* 2. data cycle */ +#if EHPI16 + writew(u4Value, prGlueInfo->rHifInfo.mcr_data_base); + writew((u4Value & 0xFFFF0000) >> 16, prGlueInfo->rHifInfo.mcr_data_base); +#elif EHPI8 + writew((u4Value & 0x000000FF), prGlueInfo->rHifInfo.mcr_data_base); + writew((u4Value & 0x0000FF00) >> 8, prGlueInfo->rHifInfo.mcr_data_base); + writew((u4Value & 0x00FF0000) >> 16, prGlueInfo->rHifInfo.mcr_data_base); + writew((u4Value & 0xFF000000) >> 24, prGlueInfo->rHifInfo.mcr_data_base); +#endif + + return TRUE; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/ehpi/include/colibri.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/ehpi/include/colibri.h new file mode 100644 index 0000000000000..a877b79d8fa96 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/ehpi/include/colibri.h @@ -0,0 +1,190 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/ehpi/include/colibri.h#1 +*/ + +/*! \file "colibri.h" +* \brief This file contains colibri BSP configuration based on eHPI interface +* +* N/A +*/ + +#ifndef _COLIBRI_H +#define _COLIBRI_H +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include +#include +#include +#include +#include + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define WLAN_STA_IRQ_GPIO 23 /* use SSP_EXTCLK as interrupt source */ +#define WLAN_STA_IRQ IRQ_GPIO(WLAN_STA_IRQ_GPIO) + +#define MSC_CS(cs, val) ((val)<<(((cs)&1)<<4)) + +#define MSC_RBUFF_SHIFT 15 +#define MSC_RBUFF(x) ((x)< +#ifndef CONFIG_X86 +#include +#endif + +#include "mt66xx_reg.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +#define MTK_PCI_VENDOR_ID 0x14C3 +#define NIC6632_PCIe_DEVICE_ID 0x6632 +#define NIC7668_PCIe_DEVICE_ID 0x7668 +#define MT7663_PCI_PFGA2_VENDOR_ID 0x0E8D +#define NIC7663_PCIe_DEVICE_ID 0x7663 +#define CONNAC_PCI_VENDOR_ID 0x0E8D +#define CONNAC_PCIe_DEVICE_ID 0x3280 + +#define PDMA_AXI_SLPPROT_RDY BIT(16) +#define CONN_HIF_PDMA_CSR_PDMA_BUSY_STATUS_ADDR 0x4168 /*0x50000168*/ +#define CONN_HIF_PDMA_CSR_PDMA_SLP_PROT_ADDR 0x4154 /*0x50000154*/ +#define WF_PSE_TOP_QUEUE_EMPTY_ADDR 0xC0B4 /*0x820680B4*/ +#define WF_PSE_TOP_PG_PLE_ADDR 0xC194 /*82068194*/ +#define WF_PLE_TOP_HIF_PG_INFO_ADDR 0x8114 /*82060114*/ + +static const struct pci_device_id mtk_pci_ids[] = { +#ifdef MT6632 + { PCI_DEVICE(MTK_PCI_VENDOR_ID, NIC6632_PCIe_DEVICE_ID), + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_mt6632}, +#endif /* MT6632 */ +#ifdef MT7668 + { PCI_DEVICE(MTK_PCI_VENDOR_ID, NIC7668_PCIe_DEVICE_ID), + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_mt7668}, +#endif /* MT7668 */ +#ifdef MT7663 + { PCI_DEVICE(MTK_PCI_VENDOR_ID, NIC7663_PCIe_DEVICE_ID), + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_mt7663}, + /* For FPGA2 temparay */ + { PCI_DEVICE(MT7663_PCI_PFGA2_VENDOR_ID, NIC7663_PCIe_DEVICE_ID), + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_mt7663}, +#endif /* MT7663 */ +#ifdef CONNAC + { PCI_DEVICE(CONNAC_PCI_VENDOR_ID, CONNAC_PCIe_DEVICE_ID), + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_connac}, +#endif /* CONNAC */ +#ifdef CONNAC2X2 + { PCI_DEVICE(CONNAC_PCI_VENDOR_ID, CONNAC_PCIe_DEVICE_ID), + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_connac2x2}, +#endif /* CONNAC */ + { /* end: all zeroes */ }, +}; + +MODULE_DEVICE_TABLE(pci, mtk_pci_ids); + +/******************************************************************************* + * 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 probe_card pfWlanProbe; +static remove_card pfWlanRemove; + +static struct pci_driver mtk_pci_driver = { + .name = "wlan", + .id_table = mtk_pci_ids, + .probe = NULL, + .remove = NULL, +}; + +static u_int8_t g_fgDriverProbed = FALSE; +static uint32_t g_u4DmaMask = 32; +/******************************************************************************* + * M A 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 pcieAllocDesc(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing, + uint32_t u4Num); +static void *pcieAllocRxBuf(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDmaBuf, + uint32_t u4Num, uint32_t u4Idx); +static void pcieAllocTxDataBuf(struct MSDU_TOKEN_ENTRY *prToken, + uint32_t u4Idx); +static void *pcieAllocRuntimeMem(uint32_t u4SrcLen); +static bool pcieCopyCmd(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *prTxCell, void *pucBuf, + void *pucSrc1, uint32_t u4SrcLen1, + void *pucSrc2, uint32_t u4SrcLen2); +static bool pcieCopyEvent(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *pRxCell, + struct RXD_STRUCT *pRxD, + struct RTMP_DMABUF *prDmaBuf, + uint8_t *pucDst, uint32_t u4Len); +static bool pcieCopyTxData(struct MSDU_TOKEN_ENTRY *prToken, + void *pucSrc, uint32_t u4Len); +static bool pcieCopyRxData(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *pRxCell, + struct RTMP_DMABUF *prDmaBuf, + struct SW_RFB *prSwRfb); +static phys_addr_t pcieMapTxBuf(struct GL_HIF_INFO *prHifInfo, + void *pucBuf, uint32_t u4Offset, uint32_t u4Len); +static phys_addr_t pcieMapRxBuf(struct GL_HIF_INFO *prHifInfo, + void *pucBuf, uint32_t u4Offset, uint32_t u4Len); +static void pcieUnmapTxBuf(struct GL_HIF_INFO *prHifInfo, + phys_addr_t rDmaAddr, uint32_t u4Len); +static void pcieUnmapRxBuf(struct GL_HIF_INFO *prHifInfo, + phys_addr_t rDmaAddr, uint32_t u4Len); +static void pcieFreeDesc(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing); +static void pcieFreeBuf(void *pucSrc, uint32_t u4Len); +static void pcieFreePacket(void *pvPacket); +static void pcieDumpTx(struct GL_HIF_INFO *prHifInfo, + struct RTMP_TX_RING *prTxRing, + uint32_t u4Idx, uint32_t u4DumpLen); +static void pcieDumpRx(struct GL_HIF_INFO *prHifInfo, + struct RTMP_RX_RING *prRxRing, + uint32_t u4Idx, uint32_t u4DumpLen); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is a PCIE interrupt callback function + * + * \param[in] func pointer to PCIE handle + * + * \return void + */ +/*----------------------------------------------------------------------------*/ +static void *CSRBaseAddress; + +static irqreturn_t mtk_pci_interrupt(int irq, void *dev_instance) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = (struct GLUE_INFO *) dev_instance; + if (!prGlueInfo) { + DBGLOG(HAL, INFO, "No glue info in mtk_pci_interrupt()\n"); + return IRQ_NONE; + } + + halDisableInterrupt(prGlueInfo->prAdapter); + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(HAL, INFO, "GLUE_FLAG_HALT skip INT\n"); + return IRQ_NONE; + } + + kalSetIntEvent(prGlueInfo); + + return IRQ_HANDLED; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is a PCIE probe function + * + * \param[in] func pointer to PCIE handle + * \param[in] id pointer to PCIE device id table + * + * \return void + */ +/*----------------------------------------------------------------------------*/ +static int mtk_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + int ret = 0; + + ASSERT(pdev); + ASSERT(id); + + ret = pci_enable_device(pdev); + + if (ret) { + DBGLOG(INIT, INFO, "pci_enable_device failed!\n"); + goto out; + } + + DBGLOG(INIT, INFO, "pci_enable_device done!\n"); + + if (pfWlanProbe((void *) pdev, + (void *) id->driver_data) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "pfWlanProbe fail!call pfWlanRemove()\n"); + pfWlanRemove(); + ret = -1; + } else { + struct mt66xx_chip_info *prChipInfo; + + prChipInfo = ((struct mt66xx_hif_driver_data *) + id->driver_data)->chip_info; + g_fgDriverProbed = TRUE; + g_u4DmaMask = prChipInfo->bus_info->u4DmaMask; + } +out: + DBGLOG(INIT, INFO, "mtk_pci_probe() done(%d)\n", ret); + + return ret; +} + +static void mtk_pci_remove(struct pci_dev *pdev) +{ + ASSERT(pdev); + + if (g_fgDriverProbed) + pfWlanRemove(); + DBGLOG(INIT, INFO, "pfWlanRemove done\n"); + + /* Unmap CSR base address */ + iounmap(CSRBaseAddress); + + /* release memory region */ + pci_release_regions(pdev); + + pci_disable_device(pdev); + DBGLOG(INIT, INFO, "mtk_pci_remove() done\n"); +} +#if CFG_SUPPORT_PCIE_L2 + + +static int mtk_pci_polling_cr(struct GLUE_INFO *prGlueInfo, uint32_t reg_cr, + int bitStart, int bitEnd, uint32_t expected_val){ + uint32_t reg_32, temResult = 0; + int i = 0; + + if (bitStart == bitEnd) + temResult = temResult | BIT(bitStart); + else + temResult = temResult | BITS(bitStart, bitEnd); + + while (1) { + kalDevRegRead(prGlueInfo, reg_cr, ®_32); + if (((reg_32 & temResult) >> bitStart) == expected_val) { + DBGLOG(INIT, STATE, "Polling CR ready %x!\n", reg_32); + break; + } + if (i == 100) { + DBGLOG(INIT, STATE, "Polling CR Timeout %x!\n", reg_32); + return -1; + } + i++; + kalMsleep(1); + } + return 0; +} + +#endif +static int mtk_pci_suspend(struct pci_dev *pdev, pm_message_t state) +{ +#if CFG_SUPPORT_PCIE_L2 + + struct GLUE_INFO *prGlueInfo = + (struct GLUE_INFO *)pci_get_drvdata(pdev); + uint32_t reg_32; + uint8_t count = 0; + int ret = 0, wait = 0; + uint8_t checkResult; + struct BUS_INFO *prBusInfo; + uint8_t drv_own_fail = FALSE; + + if (!prGlueInfo) { + DBGLOG(HAL, ERROR, "pci_get_drvdata fail!\n"); + return -1; + } + + if (kalIsResetting()) { + DBGLOG(HAL, WARN, "Chip resetting, skip\n"); + return -1; + } + + ACQUIRE_POWER_CONTROL_FROM_PM(prGlueInfo->prAdapter); + /* Stop upper layers calling the device hard_start_xmit routine. */ + netif_tx_stop_all_queues(prGlueInfo->prDevHandler); + + wlanWaitCfg80211SuspendDone(prGlueInfo); + wlanSuspendPmHandle(prGlueInfo); + glPCIeSetState(&prGlueInfo->rHifInfo, PCIE_STATE_PRE_SUSPEND_START); + halPreSuspendCmd(prGlueInfo->prAdapter); + + while (prGlueInfo->rHifInfo.state != PCIE_STATE_PRE_SUSPEND_DONE) { + if (count > 50) { + DBGLOG(HAL, ERROR, "pre_suspend timeout\n"); + ret = -EFAULT; + break; + } + msleep(20); + count++; + } + if (ret == 0) { + /*2. Polling UMAC,PDMA TX relative RING*/ + checkResult = mtk_pci_polling_cr(prGlueInfo, + CONN_HIF_PDMA_CSR_PDMA_BUSY_STATUS_ADDR, 2, 2, 0); + if (checkResult == -1) { + DBGLOG(HAL, ERROR, "Polling TX Fail ST1\n"); + ret = -EFAULT; + } + checkResult = mtk_pci_polling_cr(prGlueInfo, + WF_PLE_TOP_HIF_PG_INFO_ADDR, 16, 27, 0); + if (checkResult == -1) { + DBGLOG(HAL, ERROR, "Polling TX Fail ST2\n"); + ret = -EFAULT; + } + + checkResult = mtk_pci_polling_cr(prGlueInfo, + WF_PSE_TOP_PG_PLE_ADDR, 16, 27, 0); + if (checkResult == -1) { + DBGLOG(HAL, ERROR, "Polling TX Fail ST3\n"); + ret = -EFAULT; + } + /*3. Polling UMAC RX token report done */ + + checkResult = mtk_pci_polling_cr(prGlueInfo, + CONN_HIF_PDMA_CSR_PDMA_BUSY_STATUS_ADDR, 31, 31, 0); + if (checkResult == -1) { + DBGLOG(HAL, ERROR, "Polling RX Fail ST2\n"); + ret = -EFAULT; + } + + /*4. Sleep Protection*/ + kalDevRegRead(prGlueInfo, CONN_HIF_PDMA_CSR_PDMA_SLP_PROT_ADDR, + ®_32); + kalDevRegWrite(prGlueInfo, CONN_HIF_PDMA_CSR_PDMA_SLP_PROT_ADDR, + reg_32 | BIT(0)); + DBGLOG(INIT, STATE, "Enable Sleep Protection\n"); + + checkResult = mtk_pci_polling_cr(prGlueInfo, + CONN_HIF_PDMA_CSR_PDMA_SLP_PROT_ADDR, 16, 16, 1); + if (checkResult == -1) { + DBGLOG(HAL, ERROR, "Polling SL PROT FAIL\n"); + ret = -EFAULT; + } + + if (ret == -EFAULT) { + /* 1. Disable Sleep protection */ + kalDevRegRead(prGlueInfo, + CONN_HIF_PDMA_CSR_PDMA_SLP_PROT_ADDR, ®_32); + kalDevRegWrite(prGlueInfo, + CONN_HIF_PDMA_CSR_PDMA_SLP_PROT_ADDR, + reg_32 & ~(BIT(0))); + halPreResumeCmd(prGlueInfo->prAdapter); + netif_tx_start_all_queues(prGlueInfo->prDevHandler); + RECLAIM_POWER_CONTROL_TO_PM(prGlueInfo->prAdapter, + FALSE); + return -EFAULT; + } + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + if (prGlueInfo->prAdapter->chip_info->bus_info->pdmaStop) + prBusInfo->pdmaStop(prGlueInfo, TRUE); + /*5. Set OWN*/ + /* Set FW own directly without waiting sleep notify */ + prGlueInfo->prAdapter->fgWiFiInSleepyState = TRUE; + RECLAIM_POWER_CONTROL_TO_PM(prGlueInfo->prAdapter, + FALSE); + + /* Wait for + * 1. The other unfinished ownership handshakes + * 2. FW own back + */ + while (wait < 500) { + if ((prGlueInfo->prAdapter->u4PwrCtrlBlockCnt == 0) && + (prGlueInfo->prAdapter->fgIsFwOwn == TRUE) && + (drv_own_fail == FALSE)) { + DBGLOG(HAL, STATE, "*********************\n"); + DBGLOG(HAL, STATE, "* Enter PCIE Suspend *\n"); + DBGLOG(HAL, STATE, "*********************\n"); + DBGLOG(HAL, INFO, "wait = %d\n\n", wait); + break; + } + + ACQUIRE_POWER_CONTROL_FROM_PM(prGlueInfo->prAdapter); + /* Prevent that suspend without FW Own: + * Set Drv own has failed, + * and then Set FW Own is skipped + */ + if (prGlueInfo->prAdapter->fgIsFwOwn == FALSE) + drv_own_fail = FALSE; + else + drv_own_fail = TRUE; + /* For single core CPU */ + /* let hif_thread can be completed */ + usleep_range(1000, 3000); + RECLAIM_POWER_CONTROL_TO_PM(prGlueInfo->prAdapter, + FALSE); + + wait++; + } + + if (wait >= 500) { + DBGLOG(HAL, ERROR, "Set FW Own Timeout !!\n"); + /* 1. Disable Sleep protection */ + kalDevRegRead(prGlueInfo, + CONN_HIF_PDMA_CSR_PDMA_SLP_PROT_ADDR, ®_32); + kalDevRegWrite(prGlueInfo, + CONN_HIF_PDMA_CSR_PDMA_SLP_PROT_ADDR, + reg_32 & ~(BIT(0))); + if (prBusInfo->pdmaStop) + prBusInfo->pdmaStop(prGlueInfo, FALSE); + halPreResumeCmd(prGlueInfo->prAdapter); + netif_tx_start_all_queues(prGlueInfo->prDevHandler); + + return -EAGAIN; + } +#if CFG_SUPPORT_PCIE_ASPM + glBusConfigASPM(pdev->bus->self, DISABLE_ASPM_L1); + glBusConfigASPM(pdev, DISABLE_ASPM_L1); +#endif + + /*6. Set D state*/ + pci_save_state(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + glPCIeSetState(&prGlueInfo->rHifInfo, PCIE_STATE_SUSPEND); + + DBGLOG(HAL, STATE, "mtk_pci_suspend() done!\n"); + wlanReleaseAllTxCmdQueue(prGlueInfo->prAdapter); + } + return ret; +#else + + + return 0; +#endif +} + + + +int mtk_pci_resume(struct pci_dev *pdev) +{ +#if CFG_SUPPORT_PCIE_L2 + + struct GLUE_INFO *prGlueInfo = NULL; + struct BUS_INFO *prBusInfo; + uint32_t reg_32; + uint8_t count = 0; + int ret = 0; + + prGlueInfo = (struct GLUE_INFO *)pci_get_drvdata(pdev); + + if (!prGlueInfo) { + DBGLOG(HAL, ERROR, "pci_get_drvdata fail!\n"); + return -1; + } + + if (kalIsResetting()) { + DBGLOG(HAL, WARN, "Chip resetting, skip\n"); + return -1; + } + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + ACQUIRE_POWER_CONTROL_FROM_PM(prGlueInfo->prAdapter); + + + + + /* 1. Disable Sleep protection */ + kalDevRegRead(prGlueInfo, CONN_HIF_PDMA_CSR_PDMA_SLP_PROT_ADDR, + ®_32); + kalDevRegWrite(prGlueInfo, CONN_HIF_PDMA_CSR_PDMA_SLP_PROT_ADDR, + reg_32 & ~(BIT(0))); + + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + if (prBusInfo->fgInitPCIeInt) + HAL_MCR_WR(prGlueInfo->prAdapter, MT_PCIE_IRQ_ENABLE, 1); + if (prBusInfo->pdmaStop) + prBusInfo->pdmaStop(prGlueInfo, FALSE); + + /* 2. Re-init PDMA flow perform in CMDBT */ + /* 3.Enable UMAC */ + halPreResumeCmd(prGlueInfo->prAdapter); + + while (prGlueInfo->rHifInfo.state != PCIE_STATE_LINK_UP) { + if (count > 50) { + DBGLOG(HAL, ERROR, "pre_resume timeout\n"); + break; + } + msleep(20); + count++; + } + + kalDevRegRead(prGlueInfo, WF_PSE_TOP_QUEUE_EMPTY_ADDR, ®_32); + DBGLOG(INIT, STATE, "UMAC Result %x\n", reg_32); + + + wlanResumePmHandle(prGlueInfo); + + /* Allow upper layers to call the device hard_start_xmit routine. */ + netif_tx_start_all_queues(prGlueInfo->prDevHandler); + + RECLAIM_POWER_CONTROL_TO_PM(prGlueInfo->prAdapter, FALSE); + DBGLOG(HAL, STATE, "mtk_pci_resume() done!\n"); + return ret; +#else + + + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will register pci 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 pci bus + */ +/*----------------------------------------------------------------------------*/ +uint32_t glRegisterBus(probe_card pfProbe, remove_card pfRemove) +{ + int ret = 0; + + ASSERT(pfProbe); + ASSERT(pfRemove); + + pfWlanProbe = pfProbe; + pfWlanRemove = pfRemove; + + mtk_pci_driver.probe = mtk_pci_probe; + mtk_pci_driver.remove = mtk_pci_remove; + + mtk_pci_driver.suspend = mtk_pci_suspend; + mtk_pci_driver.resume = mtk_pci_resume; + + ret = (pci_register_driver(&mtk_pci_driver) == 0) ? + WLAN_STATUS_SUCCESS : WLAN_STATUS_FAILURE; + + return ret; +} +#if CFG_SUPPORT_PCIE_ASPM +void glBusConfigASPM(struct pci_dev *dev, int val) +{ + u16 reg16; + int pos = dev->pcie_cap; + + + pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, ®16); + reg16 &= ~0x3; + reg16 |= val; + pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, reg16); +} +#endif +#if CFG_SUPPORT_PCIE_L2 +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function set PCIE state +* +* \param[in] prHifInfo Pointer to the struct GL_HIF_INFO structure +* \param[in] state Specify TC index +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +void glPCIeSetState(struct GL_HIF_INFO *prHifInfo, enum pcie_state state) +{ + unsigned long flags; + + spin_lock_irqsave(&prHifInfo->rStateLock, flags); + prHifInfo->state = state; + spin_unlock_irqrestore(&prHifInfo->rStateLock, flags); +} + +#endif +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will unregister pci bus to the os + * + * \param[in] pfRemove Function pointer to remove card + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void glUnregisterBus(remove_card pfRemove) +{ + if (g_fgDriverProbed) { + pfRemove(); + g_fgDriverProbed = FALSE; + } + pci_unregister_driver(&mtk_pci_driver); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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(struct GLUE_INFO *prGlueInfo, unsigned long ulCookie) +{ + struct GL_HIF_INFO *prHif = NULL; + struct HIF_MEM_OPS *prMemOps; + + prHif = &prGlueInfo->rHifInfo; + + prHif->pdev = (struct pci_dev *)ulCookie; + prMemOps = &prHif->rMemOps; + prHif->prDmaDev = prHif->pdev; + + prHif->CSRBaseAddress = CSRBaseAddress; + + pci_set_drvdata(prHif->pdev, prGlueInfo); + + SET_NETDEV_DEV(prGlueInfo->prDevHandler, &prHif->pdev->dev); + + prGlueInfo->u4InfType = MT_DEV_INF_PCIE; + + prHif->rErrRecoveryCtl.eErrRecovState = ERR_RECOV_STOP_IDLE; + prHif->rErrRecoveryCtl.u4Status = 0; + prHif->fgIsErrRecovery = FALSE; + + INIT_LIST_HEAD(&prHif->rTxCmdQ); + INIT_LIST_HEAD(&prHif->rTxDataQ); + prHif->u4TxDataQLen = 0; + + prHif->fgIsPowerOff = true; + prHif->fgIsDumpLog = false; + + prMemOps->allocTxDesc = pcieAllocDesc; + prMemOps->allocRxDesc = pcieAllocDesc; + prMemOps->allocTxCmdBuf = NULL; + prMemOps->allocTxDataBuf = pcieAllocTxDataBuf; + prMemOps->allocRxBuf = pcieAllocRxBuf; + prMemOps->allocRuntimeMem = pcieAllocRuntimeMem; + prMemOps->copyCmd = pcieCopyCmd; + prMemOps->copyEvent = pcieCopyEvent; + prMemOps->copyTxData = pcieCopyTxData; + prMemOps->copyRxData = pcieCopyRxData; + prMemOps->flushCache = NULL; + prMemOps->mapTxBuf = pcieMapTxBuf; + prMemOps->mapRxBuf = pcieMapRxBuf; + prMemOps->unmapTxBuf = pcieUnmapTxBuf; + prMemOps->unmapRxBuf = pcieUnmapRxBuf; + prMemOps->freeDesc = pcieFreeDesc; + prMemOps->freeBuf = pcieFreeBuf; + prMemOps->freePacket = pcieFreePacket; + prMemOps->dumpTx = pcieDumpTx; + prMemOps->dumpRx = pcieDumpRx; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function clears hif related info. + * + * \param[in] prGlueInfo Pointer to glue info structure + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void glClearHifInfo(struct GLUE_INFO *prGlueInfo) +{ + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + struct list_head *prCur, *prNext; + struct TX_CMD_REQ *prTxCmdReq; + struct TX_DATA_REQ *prTxDataReq; + + halUninitMsduTokenInfo(prGlueInfo->prAdapter); + halWpdmaFreeRing(prGlueInfo); + + list_for_each_safe(prCur, prNext, &prHifInfo->rTxCmdQ) { + prTxCmdReq = list_entry(prCur, struct TX_CMD_REQ, list); + list_del(prCur); + kfree(prTxCmdReq); + } + + list_for_each_safe(prCur, prNext, &prHifInfo->rTxDataQ) { + prTxDataReq = list_entry(prCur, struct TX_DATA_REQ, list); + list_del(prCur); + prHifInfo->u4TxDataQLen--; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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) + */ +/*----------------------------------------------------------------------------*/ +u_int8_t glBusInit(void *pvData) +{ + int ret = 0; + struct pci_dev *pdev = NULL; + + ASSERT(pvData); + + pdev = (struct pci_dev *)pvData; + + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(g_u4DmaMask)); + if (ret != 0) { + DBGLOG(INIT, INFO, "set DMA mask failed!errno=%d\n", ret); + return FALSE; + } + + ret = pci_request_regions(pdev, pci_name(pdev)); + if (ret != 0) { + DBGLOG(INIT, INFO, + "Request PCI resource failed, errno=%d!\n", ret); + } + + /* map physical address to virtual address for accessing register */ + CSRBaseAddress = ioremap(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + DBGLOG(INIT, INFO, "ioremap for device %s, region 0x%lX @ 0x%lX\n", + pci_name(pdev), (unsigned long) pci_resource_len(pdev, 0), + (unsigned long) pci_resource_start(pdev, 0)); + if (!CSRBaseAddress) { + DBGLOG(INIT, INFO, + "ioremap failed for device %s, region 0x%lX @ 0x%lX\n", + pci_name(pdev), + (unsigned long) pci_resource_len(pdev, 0), + (unsigned long) pci_resource_start(pdev, 0)); + goto err_out_free_res; + } + + /* Set DMA master */ + pci_set_master(pdev); + + return TRUE; + +err_out_free_res: + pci_release_regions(pdev); + + pci_disable_device(pdev); + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Stop bus operation and release resources. + * + * \param[in] pvData A pointer to struct net_device. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void glBusRelease(void *pvData) +{ +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +int32_t glBusSetIrq(void *pvData, void *pfnIsr, void *pvCookie) +{ + struct BUS_INFO *prBusInfo; + struct net_device *prNetDevice = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct GL_HIF_INFO *prHifInfo = NULL; + struct pci_dev *pdev = NULL; + int ret = 0; + + ASSERT(pvData); + if (!pvData) + return -1; + + prNetDevice = (struct net_device *)pvData; + prGlueInfo = (struct GLUE_INFO *)pvCookie; + ASSERT(prGlueInfo); + if (!prGlueInfo) + return -1; + + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + + prHifInfo = &prGlueInfo->rHifInfo; + pdev = prHifInfo->pdev; + + prHifInfo->u4IrqId = pdev->irq; + ret = request_irq(prHifInfo->u4IrqId, mtk_pci_interrupt, + IRQF_SHARED, prNetDevice->name, prGlueInfo); + if (ret != 0) + DBGLOG(INIT, INFO, + "glBusSetIrq: request_irq ERROR(%d)\n", ret); + else if (prBusInfo->fgInitPCIeInt) + HAL_MCR_WR(prGlueInfo->prAdapter, MT_PCIE_IRQ_ENABLE, 1); + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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(void *pvData, void *pvCookie) +{ + struct net_device *prNetDevice = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct GL_HIF_INFO *prHifInfo = NULL; + struct pci_dev *pdev = NULL; + + ASSERT(pvData); + if (!pvData) { + DBGLOG(INIT, INFO, "%s null pvData\n", __func__); + return; + } + prNetDevice = (struct net_device *)pvData; + prGlueInfo = (struct GLUE_INFO *) pvCookie; + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(INIT, INFO, "%s no glue info\n", __func__); + return; + } + + prHifInfo = &prGlueInfo->rHifInfo; + pdev = prHifInfo->pdev; + + synchronize_irq(pdev->irq); + free_irq(pdev->irq, prGlueInfo); +} + +u_int8_t glIsReadClearReg(uint32_t u4Address) +{ + return TRUE; +} + +void glSetPowerState(IN struct GLUE_INFO *prGlueInfo, IN uint32_t ePowerMode) +{ +} + +void glGetDev(void *ctx, struct device **dev) +{ + + *dev = &((struct pci_dev *)ctx)->dev; +} + +void glGetHifDev(struct GL_HIF_INFO *prHif, struct device **dev) +{ + *dev = &(prHif->pdev->dev); +} + +static void pcieAllocDesc(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing, + uint32_t u4Num) +{ + dma_addr_t rAddr; + + prDescRing->AllocVa = KAL_DMA_ALLOC_COHERENT( + prHifInfo->prDmaDev, prDescRing->AllocSize, &rAddr); + prDescRing->AllocPa = (phys_addr_t)rAddr; + if (prDescRing->AllocVa) + memset(prDescRing->AllocVa, 0, prDescRing->AllocSize); +} + +static void pcieAllocTxDataBuf(struct MSDU_TOKEN_ENTRY *prToken, uint32_t u4Idx) +{ + prToken->prPacket = kalMemAlloc(prToken->u4DmaLength, PHY_MEM_TYPE); + prToken->rDmaAddr = 0; +} + +static void *pcieAllocRxBuf(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDmaBuf, + uint32_t u4Num, uint32_t u4Idx) +{ + struct sk_buff *pkt = dev_alloc_skb(prDmaBuf->AllocSize); + dma_addr_t rAddr; + + if (!pkt) { + DBGLOG(HAL, ERROR, "can't allocate rx %lu size packet\n", + prDmaBuf->AllocSize); + prDmaBuf->AllocPa = 0; + prDmaBuf->AllocVa = NULL; + return NULL; + } + + prDmaBuf->AllocVa = (void *)pkt->data; + memset(prDmaBuf->AllocVa, 0, prDmaBuf->AllocSize); + + rAddr = KAL_DMA_MAP_SINGLE(prHifInfo->prDmaDev, prDmaBuf->AllocVa, + prDmaBuf->AllocSize, KAL_DMA_FROM_DEVICE); + if (KAL_DMA_MAPPING_ERROR(prHifInfo->prDmaDev, rAddr)) { + DBGLOG(HAL, ERROR, "sk_buff dma mapping error!\n"); + dev_kfree_skb(pkt); + return NULL; + } + prDmaBuf->AllocPa = (phys_addr_t)rAddr; + return (void *)pkt; +} + +static void *pcieAllocRuntimeMem(uint32_t u4SrcLen) +{ + return kalMemAlloc(u4SrcLen, PHY_MEM_TYPE); +} + +static bool pcieCopyCmd(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *prTxCell, void *pucBuf, + void *pucSrc1, uint32_t u4SrcLen1, + void *pucSrc2, uint32_t u4SrcLen2) +{ + dma_addr_t rAddr; + uint32_t u4TotalLen = u4SrcLen1 + u4SrcLen2; + + prTxCell->pBuffer = pucBuf; + + memcpy(pucBuf, pucSrc1, u4SrcLen1); + if (pucSrc2 != NULL && u4SrcLen2 > 0) + memcpy(pucBuf + u4SrcLen1, pucSrc2, u4SrcLen2); + rAddr = KAL_DMA_MAP_SINGLE(prHifInfo->prDmaDev, pucBuf, + u4TotalLen, KAL_DMA_TO_DEVICE); + if (KAL_DMA_MAPPING_ERROR(prHifInfo->prDmaDev, rAddr)) { + DBGLOG(HAL, ERROR, "KAL_DMA_MAP_SINGLE() error!\n"); + return false; + } + + prTxCell->PacketPa = (phys_addr_t)rAddr; + + return true; +} + +static bool pcieCopyEvent(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *pRxCell, + struct RXD_STRUCT *pRxD, + struct RTMP_DMABUF *prDmaBuf, + uint8_t *pucDst, uint32_t u4Len) +{ + struct sk_buff *prSkb = NULL; + void *pRxPacket = NULL; + dma_addr_t rAddr; + + KAL_DMA_UNMAP_SINGLE(prHifInfo->prDmaDev, + (dma_addr_t)prDmaBuf->AllocPa, + prDmaBuf->AllocSize, KAL_DMA_FROM_DEVICE); + + pRxPacket = pRxCell->pPacket; + ASSERT(pRxPacket) + + prSkb = (struct sk_buff *)pRxPacket; + memcpy(pucDst, (uint8_t *)prSkb->data, u4Len); + + prDmaBuf->AllocVa = ((struct sk_buff *)pRxCell->pPacket)->data; + rAddr = KAL_DMA_MAP_SINGLE(prHifInfo->prDmaDev, prDmaBuf->AllocVa, + prDmaBuf->AllocSize, KAL_DMA_FROM_DEVICE); + if (KAL_DMA_MAPPING_ERROR(prHifInfo->prDmaDev, rAddr)) { + DBGLOG(HAL, ERROR, "KAL_DMA_MAP_SINGLE() error!\n"); + return false; + } + prDmaBuf->AllocPa = (phys_addr_t)rAddr; + return true; +} + +static bool pcieCopyTxData(struct MSDU_TOKEN_ENTRY *prToken, + void *pucSrc, uint32_t u4Len) +{ + memcpy(prToken->prPacket, pucSrc, u4Len); + return true; +} + +static bool pcieCopyRxData(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMACB *pRxCell, + struct RTMP_DMABUF *prDmaBuf, + struct SW_RFB *prSwRfb) +{ + void *pRxPacket = NULL; + dma_addr_t rAddr; + + pRxPacket = pRxCell->pPacket; + ASSERT(pRxPacket); + + pRxCell->pPacket = prSwRfb->pvPacket; + + KAL_DMA_UNMAP_SINGLE(prHifInfo->prDmaDev, + (dma_addr_t)prDmaBuf->AllocPa, + prDmaBuf->AllocSize, KAL_DMA_FROM_DEVICE); + prSwRfb->pvPacket = pRxPacket; + + prDmaBuf->AllocVa = ((struct sk_buff *)pRxCell->pPacket)->data; + rAddr = KAL_DMA_MAP_SINGLE(prHifInfo->prDmaDev, + prDmaBuf->AllocVa, prDmaBuf->AllocSize, KAL_DMA_FROM_DEVICE); + if (KAL_DMA_MAPPING_ERROR(prHifInfo->prDmaDev, rAddr)) { + DBGLOG(HAL, ERROR, "KAL_DMA_MAP_SINGLE() error!\n"); + ASSERT(0); + return false; + } + prDmaBuf->AllocPa = (phys_addr_t)rAddr; + + return true; +} + +static phys_addr_t pcieMapTxBuf(struct GL_HIF_INFO *prHifInfo, + void *pucBuf, uint32_t u4Offset, uint32_t u4Len) +{ + dma_addr_t rDmaAddr; + + rDmaAddr = KAL_DMA_MAP_SINGLE(prHifInfo->prDmaDev, pucBuf + u4Offset, + u4Len, KAL_DMA_TO_DEVICE); + if (KAL_DMA_MAPPING_ERROR(prHifInfo->prDmaDev, rDmaAddr)) { + DBGLOG(HAL, ERROR, "KAL_DMA_MAP_SINGLE() error!\n"); + return 0; + } + + return (phys_addr_t)rDmaAddr; +} + +static phys_addr_t pcieMapRxBuf(struct GL_HIF_INFO *prHifInfo, + void *pucBuf, uint32_t u4Offset, uint32_t u4Len) +{ + dma_addr_t rDmaAddr; + + rDmaAddr = KAL_DMA_MAP_SINGLE(prHifInfo->prDmaDev, pucBuf + u4Offset, + u4Len, KAL_DMA_FROM_DEVICE); + if (KAL_DMA_MAPPING_ERROR(prHifInfo->prDmaDev, rDmaAddr)) { + DBGLOG(HAL, ERROR, "KAL_DMA_MAP_SINGLE() error!\n"); + return 0; + } + + return (phys_addr_t)rDmaAddr; +} + +static void pcieUnmapTxBuf(struct GL_HIF_INFO *prHifInfo, + phys_addr_t rDmaAddr, uint32_t u4Len) +{ + KAL_DMA_UNMAP_SINGLE(prHifInfo->prDmaDev, + (dma_addr_t)rDmaAddr, + u4Len, KAL_DMA_TO_DEVICE); +} + +static void pcieUnmapRxBuf(struct GL_HIF_INFO *prHifInfo, + phys_addr_t rDmaAddr, uint32_t u4Len) +{ + KAL_DMA_UNMAP_SINGLE(prHifInfo->prDmaDev, + (dma_addr_t)rDmaAddr, + u4Len, KAL_DMA_FROM_DEVICE); +} + +static void pcieFreeDesc(struct GL_HIF_INFO *prHifInfo, + struct RTMP_DMABUF *prDescRing) +{ + if (prDescRing->AllocVa == NULL) + return; + + KAL_DMA_FREE_COHERENT(prHifInfo->prDmaDev, + prDescRing->AllocSize, + prDescRing->AllocVa, + (dma_addr_t)prDescRing->AllocPa); + memset(prDescRing, 0, sizeof(struct RTMP_DMABUF)); +} + +static void pcieFreeBuf(void *pucSrc, uint32_t u4Len) +{ + kalMemFree(pucSrc, PHY_MEM_TYPE, u4Len); +} + +static void pcieFreePacket(void *pvPacket) +{ + kalPacketFree(NULL, pvPacket); +} + +static void pcieDumpTx(struct GL_HIF_INFO *prHifInfo, + struct RTMP_TX_RING *prTxRing, + uint32_t u4Idx, uint32_t u4DumpLen) +{ + struct RTMP_DMACB *prTxCell; + void *prAddr = NULL; + + prTxCell = &prTxRing->Cell[u4Idx]; + + if (prTxCell->prToken) + prAddr = prTxCell->prToken->prPacket; + else + prAddr = prTxCell->pBuffer; + + if (prAddr) + DBGLOG_MEM32(HAL, INFO, prAddr, u4DumpLen); +} + +static void pcieDumpRx(struct GL_HIF_INFO *prHifInfo, + struct RTMP_RX_RING *prRxRing, + uint32_t u4Idx, uint32_t u4DumpLen) +{ + struct RTMP_DMACB *prRxCell; + struct RTMP_DMABUF *prDmaBuf; + + prRxCell = &prRxRing->Cell[u4Idx]; + prDmaBuf = &prRxCell->DmaBuf; + + if (!prRxCell->pPacket) + return; + + pcieUnmapRxBuf(prHifInfo, prDmaBuf->AllocPa, prDmaBuf->AllocSize); + + DBGLOG_MEM32(HAL, INFO, ((struct sk_buff *)prRxCell->pPacket)->data, + u4DumpLen); + + prDmaBuf->AllocPa = pcieMapRxBuf(prHifInfo, prDmaBuf->AllocVa, + 0, prDmaBuf->AllocSize); +} + +#if CFG_CHIP_RESET_SUPPORT +void kalRemoveProbe(IN struct GLUE_INFO *prGlueInfo) +{ + DBGLOG(INIT, WARN, "[SER][L0] not support...\n"); +} +#endif + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/arm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/arm.c new file mode 100644 index 0000000000000..7cbc34e29cdef --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/arm.c @@ -0,0 +1,62 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** +*[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. +******************************************************************************/ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/hal_api.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/hal_api.c new file mode 100644 index 0000000000000..cbc5c51226b2e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/hal_api.c @@ -0,0 +1,3082 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** +*[File] hif_api.c +*[Version] v1.0 +*[Revision Date] 2015-09-08 +*[Author] +*[Description] +* The program provides SDIO HIF APIs +*[Copyright] +* Copyright (C) 2015 MediaTek Incorporation. All Rights Reserved. +******************************************************************************/ + +/******************************************************************************* +* C O M P I L E 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 MTK_WCN_HIF_SDIO +#include "hif_sdio.h" +#else +#include +#include +#include +#include /* sdio_readl(), etc */ +#include +#endif + +#include +#ifndef CONFIG_X86 +#include +#endif + +#include "mt66xx_reg.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define RX_RESPONSE_TIMEOUT (3000) + +/******************************************************************************* +* 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 +******************************************************************************** +*/ +/* + *TX Done Counter Layout + * + * enum HIF_TX_COUNT_IDX_T { + * + * /==== First WMM ====/ + * + * HIF_TXC_IDX_0, ==>AC0 PSE + * HIF_TXC_IDX_1, ==>AC1 PSE + * HIF_TXC_IDX_2, ==>AC2 PSE + * HIF_TXC_IDX_3, ==>AC3 PLE + * HIF_TXC_IDX_4, ==>CPU PSE + * HIF_TXC_IDX_5, ==>AC0 PLE + * HIF_TXC_IDX_6, ==>AC1 PLE + * HIF_TXC_IDX_7, ==>AC2 PLE + * HIF_TXC_IDX_8, ==>AC3 PLE + * + * /==== Second WMM ====/ + * + * HIF_TXC_IDX_9, ==>AC10, AC11 PSE + * HIF_TXC_IDX_10, ==> AC12 PSE + * HIF_TXC_IDX_11, ==>AC13 PSE + * HIF_TXC_IDX_12, ==>AC10, AC11 PLE + * HIF_TXC_IDX_13, ==>AC12 PLE + * HIF_TXC_IDX_14, ==>Reservec + * HIF_TXC_IDX_15, ==>AC13 PLE + * }; +*/ +#define HIF_TXC_IDX_2_TC_IDX_PSE(hif_idx) (hif_idx) +#define HIF_TXC_IDX_2_TC_IDX_PLE(hif_idx) (hif_idx - HIF_TXC_IDX_5) +#define TC_IDX_PSE_2_HIF_TXC_IDX(ucTc) (ucTc) +#define TC_IDX_PLE_2_HIF_TXC_IDX(ucTc) (ucTc + HIF_TXC_IDX_5) + +/******************************************************************************* +* 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 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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t halVerifyChipID(IN struct ADAPTER *prAdapter) +{ + uint32_t u4CIR = 0; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + + if (prAdapter->fgIsReadRevID) + return TRUE; + + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4CIR); + + DBGLOG(INIT, TRACE, "Chip ID: 0x%lx\n", u4CIR & WCIR_CHIP_ID); + DBGLOG(INIT, TRACE, "Revision ID: 0x%lx\n", ((u4CIR & WCIR_REVISION_ID) >> 16)); + + prChipInfo = prAdapter->chip_info; + + if ((u4CIR & WCIR_CHIP_ID) != prChipInfo->chip_id) + return FALSE; + + prAdapter->ucRevID = (uint8_t) (((u4CIR & WCIR_REVISION_ID) >> 16) & 0xF); + prAdapter->fgIsReadRevID = TRUE; + + return TRUE; +} + +uint32_t +halRxWaitResponse(IN struct ADAPTER *prAdapter, IN uint8_t ucPortIdx, OUT uint8_t *pucRspBuffer, + IN uint32_t u4MaxRespBufferLen, OUT uint32_t *pu4Length) +{ + struct mt66xx_chip_info *prChipInfo; + uint32_t u4Value = 0, u4PktLen = 0, i = 0, u4CpyLen; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + uint32_t u4Time, u4Current; + struct RX_CTRL *prRxCtrl; + struct WIFI_EVENT *prEvent; + + DEBUGFUNC("halRxWaitResponse"); + + ASSERT(prAdapter); + ASSERT(pucRspBuffer); + prChipInfo = prAdapter->chip_info; + + prRxCtrl = &prAdapter->rRxCtrl; + + u4Time = (uint32_t) kalGetTimeTick(); + + do { + /* Read the packet length */ + HAL_MCR_RD(prAdapter, MCR_WRPLR, &u4Value); + + if ((u4Value & 0xFFFF) != 0) { + u4PktLen = u4Value & 0xFFFF; + i = 0; + } else { + u4PktLen = (u4Value >> 16) & 0xFFFF; + i = 1; + } + + if (u4PktLen > u4MaxRespBufferLen) { + DBGLOG(RX, ERROR, "Packet length over buffer! Dump Response buffer, length = 0x%x\n", + *pu4Length); + prEvent = (struct WIFI_EVENT *) + (pucRspBuffer + prChipInfo->rxd_size); + DBGLOG(RX, ERROR, "RX EVENT: ID[0x%02X] SEQ[%u] LEN[%u]\n", + prEvent->ucEID, prEvent->ucSeqNum, prEvent->u2PacketLength); + DBGLOG_MEM8(RX, ERROR, pucRspBuffer, u4MaxRespBufferLen); + return WLAN_STATUS_FAILURE; + } + + if (u4PktLen == 0) { + /* timeout exceeding check */ + u4Current = (uint32_t) kalGetTimeTick(); + + if ((u4Current > u4Time) && ((u4Current - u4Time) > RX_RESPONSE_TIMEOUT)) { + DBGLOG(RX, ERROR, "Timeout! %d - %d = %d\n", u4Current, u4Time, (u4Current-u4Time)); + return WLAN_STATUS_FAILURE; + } else if (u4Current < u4Time && ((u4Current + (0xFFFFFFFF - u4Time)) > RX_RESPONSE_TIMEOUT)) { + DBGLOG(RX, ERROR, "Timeout! %d - %d = %d\n", + u4Current, u4Time, (u4Current + (0xFFFFFFFF - u4Time))); + return WLAN_STATUS_FAILURE; + } + + /* Response packet is not ready */ + kalUdelay(50); + } else { + +#if (CFG_ENABLE_READ_EXTRA_4_BYTES == 1) +#if CFG_SDIO_RX_AGG + /* decide copy length */ + if (u4PktLen > u4MaxRespBufferLen) + u4CpyLen = u4MaxRespBufferLen; + else + u4CpyLen = u4PktLen; + + /* read from SDIO to tmp. buffer */ + HAL_PORT_RD(prAdapter, i == 0 ? MCR_WRDR0 : MCR_WRDR1, + ALIGN_4(u4PktLen + 4), prRxCtrl->pucRxCoalescingBufPtr, + HIF_RX_COALESCING_BUFFER_SIZE); + + /* copy to destination buffer */ + kalMemCopy(pucRspBuffer, prRxCtrl->pucRxCoalescingBufPtr, u4CpyLen); + + /* update valid buffer count */ + u4PktLen = u4CpyLen; +#else +#error "Please turn on RX coalescing" +#endif +#else + HAL_PORT_RD(prAdapter, + i == 0 ? MCR_WRDR0 : MCR_WRDR1, u4PktLen, pucRspBuffer, u4MaxRespBufferLen); +#endif + *pu4Length = u4PktLen; + break; + } + } while (TRUE); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief enable global interrupt +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void halEnableInterrupt(IN struct ADAPTER *prAdapter) +{ + u_int8_t fgIsIntEnableCache, fgIsPendingInt; + + ASSERT(prAdapter); + fgIsIntEnableCache = prAdapter->fgIsIntEnable; + /* Not to enable interrupt if there is pending interrupt */ + fgIsPendingInt = prAdapter->prGlueInfo->rHifInfo.fgIsPendingInt; + + if (!fgIsPendingInt) + 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 if (!fgIsPendingInt) { + 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 && !fgIsPendingInt) + HAL_BYTE_WR(prAdapter, MCR_WHLPCR, WHLPCR_INT_EN_SET); + + if (fgIsPendingInt) + kalSetIntEvent(prAdapter->prGlueInfo); +} /* end of nicEnableInterrupt() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief disable global interrupt +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void halDisableInterrupt(IN struct ADAPTER *prAdapter) +{ + + ASSERT(prAdapter); + + HAL_BYTE_WR(prAdapter, MCR_WHLPCR, WHLPCR_INT_EN_CLR); + + prAdapter->fgIsIntEnable = FALSE; + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to process the POWER OFF procedure. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t halSetDriverOwn(IN struct ADAPTER *prAdapter) +{ + u_int8_t fgStatus = TRUE; + uint32_t i, j, u4CurrTick = 0, u4WriteTick, u4WriteTickTemp; + u_int8_t fgTimeout; + u_int8_t fgResult; + uint32_t u4DriverOwnTime = 0, u4Cr4ReadyTime = 0; + struct GL_HIF_INFO *prHifInfo; + u_int8_t fgWmtCoreDump = FALSE; + + ASSERT(prAdapter); + + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_SET_OWN); + + GLUE_INC_REF_CNT(prAdapter->u4PwrCtrlBlockCnt); + + if (prAdapter->fgIsFwOwn == FALSE) + goto unlock; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + DBGLOG(INIT, TRACE, "DRIVER OWN\n"); + + u4WriteTick = 0; + u4CurrTick = kalGetTimeTick(); + i = 0; + j = 0; + + glWakeupSdio(prAdapter->prGlueInfo); + + while (1) { + HAL_LP_OWN_RD(prAdapter, &fgResult); + + if (TIME_BEFORE(kalGetTimeTick(), u4CurrTick)) { /* To prevent timer wraparound */ + fgTimeout = + ((kalGetTimeTick() + (~u4CurrTick)) > LP_OWN_BACK_TOTAL_DELAY_MS) ? TRUE : FALSE; + } else { + fgTimeout = + ((kalGetTimeTick() - u4CurrTick) > LP_OWN_BACK_TOTAL_DELAY_MS) ? TRUE : FALSE; + } + + if (fgResult) { + prAdapter->fgIsFwOwn = FALSE; + prAdapter->u4OwnFailedCount = 0; + prAdapter->u4OwnFailedLogCount = 0; + + if (nicSerIsWaitingReset(prAdapter)) { + DBGLOG(INIT, WARN, + "[SER][L1] driver own pass\n"); + + /* SER is done, start Tx/Rx */ + nicSerStartTxRx(prAdapter); + nicTxRelease(prAdapter, 0x0); + } + break; + } else if ((i > LP_OWN_BACK_FAILED_RETRY_CNT) && + (kalIsCardRemoved(prAdapter->prGlueInfo) || fgIsBusAccessFailed || fgTimeout + || wlanIsChipNoAck(prAdapter))) { + + /* For driver own back fail debug, get current PC value */ + halPrintMailbox(prAdapter); + halPollDbgCr(prAdapter, LP_OWN_BACK_FAILED_DBGCR_POLL_ROUND); + + if ((prAdapter->u4OwnFailedCount == 0) || + CHECK_FOR_TIMEOUT(u4CurrTick, prAdapter->rLastOwnFailedLogTime, + MSEC_TO_SYSTIME(LP_OWN_BACK_FAILED_LOG_SKIP_MS))) { + + DBGLOG(INIT, ERROR, + "LP cannot be own back, Timeout[%u](%ums), BusAccessError[%u]", + fgTimeout, kalGetTimeTick() - u4CurrTick, fgIsBusAccessFailed); + DBGLOG(INIT, ERROR, + "Resetting[%u], CardRemoved[%u] NoAck[%u] Cnt[%u] fgCoreDump[%u]\n", + kalIsResetting(), + kalIsCardRemoved(prAdapter->prGlueInfo), wlanIsChipNoAck(prAdapter), + prAdapter->u4OwnFailedCount, fgWmtCoreDump); + + DBGLOG(INIT, INFO, + "Skip LP own back failed log for next %ums\n", LP_OWN_BACK_FAILED_LOG_SKIP_MS); + + prAdapter->u4OwnFailedLogCount++; + if (prAdapter->u4OwnFailedLogCount > LP_OWN_BACK_FAILED_RESET_CNT) { + /* Trigger RESET */ + glGetRstReason(RST_DRV_OWN_FAIL); + GL_RESET_TRIGGER(prAdapter, + RST_FLAG_DO_CORE_DUMP); + } + GET_CURRENT_SYSTIME(&prAdapter->rLastOwnFailedLogTime); + } + + prAdapter->u4OwnFailedCount++; + fgStatus = FALSE; + break; + } + + u4WriteTickTemp = kalGetTimeTick(); + if ((i == 0) || TIME_AFTER(u4WriteTickTemp, (u4WriteTick + LP_OWN_REQ_CLR_INTERVAL_MS))) { + /* Driver get LP ownership per 200 ms, to avoid iteration time not accurate */ + HAL_LP_OWN_CLR(prAdapter, &fgResult); + u4WriteTick = u4WriteTickTemp; + } + + /* Delay for LP engine to complete its operation. */ + kalUsleep_range(LP_OWN_BACK_LOOP_DELAY_MIN_US, LP_OWN_BACK_LOOP_DELAY_MAX_US); + i++; + } + u4DriverOwnTime = ((kalGetTimeTick() >= u4CurrTick) ? + (kalGetTimeTick() - u4CurrTick) : (kalGetTimeTick() + (~u4CurrTick))); + + /* 1. Driver need to polling until CR4 ready, then could do normal Tx/Rx */ + /* 2. Send a dummy command to change data path to store-forward mode */ + if (prAdapter->fgIsCr4FwDownloaded && prAdapter->fgIsFwDownloaded) { + const uint32_t ready_bits = prAdapter->chip_info->sw_ready_bits; + u_int8_t fgReady = FALSE; + + DBGLOG(INIT, INFO, "halSetDriverOwn:: Check ready_bits(=0x%x)\n", ready_bits); + u4CurrTick = kalGetTimeTick(); + while (1) { + HAL_WIFI_FUNC_READY_CHECK(prAdapter, ready_bits/*WIFI_FUNC_READY_BITS*/, &fgReady); + + if (TIME_BEFORE(kalGetTimeTick(), u4CurrTick)) { /* To prevent timer wraparound */ + fgTimeout = + ((kalGetTimeTick() + (~u4CurrTick)) > LP_OWN_BACK_TOTAL_DELAY_MS) + ? TRUE : FALSE; + } else { + fgTimeout = + ((kalGetTimeTick() - u4CurrTick) > LP_OWN_BACK_TOTAL_DELAY_MS) + ? TRUE : FALSE; + } + + if (fgReady) { + break; + } else if (kalIsCardRemoved(prAdapter->prGlueInfo) || fgIsBusAccessFailed || fgTimeout + || wlanIsChipNoAck(prAdapter)) { + + /* For driver own back fail debug, get current PC value */ + halPrintMailbox(prAdapter); + halPollDbgCr(prAdapter, LP_OWN_BACK_FAILED_DBGCR_POLL_ROUND); + + DBGLOG(INIT, ERROR, + "Resetting[%u], CardRemoved[%u] NoAck[%u] Timeout[%u](%u - %u)ms, fgCoreDump[%u]\n", + kalIsResetting(), + kalIsCardRemoved(prAdapter->prGlueInfo), wlanIsChipNoAck(prAdapter), + fgTimeout, kalGetTimeTick(), u4CurrTick, fgWmtCoreDump); + + + DBGLOG(INIT, INFO, + "Skip waiting CR4 ready for next %ums\n", LP_OWN_BACK_FAILED_LOG_SKIP_MS); + fgStatus = FALSE; + + if (fgTimeout) { + /* Trigger RESET */ + glGetRstReason(RST_DRV_OWN_FAIL); + GL_RESET_TRIGGER(prAdapter, + RST_FLAG_DO_CORE_DUMP); + } + + break; + } + /* Delay for CR4 to complete its operation. */ + kalUsleep_range(LP_OWN_BACK_LOOP_DELAY_MIN_US, LP_OWN_BACK_LOOP_DELAY_MAX_US); + } + + halTagIntLog(prAdapter, SDIO_INT_DRV_OWN); + HAL_MCR_RD(prAdapter, MCR_D2HRM1R, &j); + + if (j == 0x77889901) { + + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + + if (halIsPendingTxDone(prAdapter)) { + /* Workaround for missing Tx done */ + halSerHifReset(prAdapter); + } + + /* fgIsWakeupFromDeepSleep */ + wlanSendDummyCmd(prAdapter, FALSE); + + /* Workaround for dummy command which is not count in Tx done count */ + if (prChipInfo->is_support_cr4) + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[TC4_INDEX]--; + halTagIntLog(prAdapter, SDIO_INT_WAKEUP_DSLP); + } + u4Cr4ReadyTime = ((kalGetTimeTick() >= u4CurrTick) ? + (kalGetTimeTick() - u4CurrTick) : (kalGetTimeTick() + (~u4CurrTick))); + } + + DBGLOG(NIC, INFO, "DRIVER OWN %d, %d, DSLP %s, count %d\n", + u4DriverOwnTime, u4Cr4ReadyTime, ((j == 0x77889901)?"1":"0"), i); +unlock: + KAL_RELEASE_MUTEX(prAdapter, MUTEX_SET_OWN); + return fgStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to process the POWER ON procedure. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void halSetFWOwn(IN struct ADAPTER *prAdapter, IN u_int8_t fgEnableGlobalInt) +{ + + u_int8_t fgResult; + + ASSERT(prAdapter); + ASSERT(prAdapter->u4PwrCtrlBlockCnt != 0); + + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_SET_OWN); + + /* Decrease Block to Enter Low Power Semaphore count */ + GLUE_DEC_REF_CNT(prAdapter->u4PwrCtrlBlockCnt); + + if (prAdapter->u4PwrCtrlBlockCnt != 0) { + DBGLOG(INIT, TRACE, "prAdapter->u4PwrCtrlBlockCnt = %d\n", + prAdapter->u4PwrCtrlBlockCnt); + goto unlock; + } + + if (prAdapter->fgForceFwOwn == FALSE + && prAdapter->fgWiFiInSleepyState == FALSE) + goto unlock; + + if (prAdapter->fgIsFwOwn == TRUE) + goto unlock; + + if ((nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) && + !nicSerIsWaitingReset(prAdapter)) { + DBGLOG(INIT, INFO, "FW OWN Skipped due to pending INT\n"); + /* pending interrupts */ + goto unlock; + } + + if (fgEnableGlobalInt) { + prAdapter->fgIsIntEnableWithLPOwnSet = TRUE; + } else { + if (nicSerIsWaitingReset(prAdapter)) + DBGLOG(INIT, WARN, "[SER][L1] set fw own\n"); + + HAL_LP_OWN_SET(prAdapter, &fgResult); + + if (fgResult) { + /* if set firmware own not successful (possibly pending + * interrupts), indicate an own clear event + */ + HAL_LP_OWN_CLR(prAdapter, &fgResult); + } else { + prAdapter->fgIsFwOwn = TRUE; + + DBGLOG(INIT, INFO, "FW OWN\n"); + + if (nicSerIsWaitingReset(prAdapter)) + DBGLOG(INIT, WARN, "[SER][L1] set fw pass\n"); + } + } + +unlock: + KAL_RELEASE_MUTEX(prAdapter, MUTEX_SET_OWN); +} + +void halWakeUpWiFi(IN struct ADAPTER *prAdapter) +{ + + u_int8_t fgResult; + + ASSERT(prAdapter); + + HAL_LP_OWN_RD(prAdapter, &fgResult); + + if (fgResult) + prAdapter->fgIsFwOwn = FALSE; + else + HAL_LP_OWN_CLR(prAdapter, &fgResult); +} + +void halDevInit(IN struct ADAPTER *prAdapter) +{ + uint32_t u4Value = 0; + + ASSERT(prAdapter); + +#if CFG_SDIO_INTR_ENHANCE + /* 4 <1> Check STATUS Buffer is DW alignment. */ + ASSERT(IS_ALIGN_4((unsigned long)&prAdapter->prGlueInfo->rHifInfo.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); + } +#endif /* CFG_SDIO_INTR_ENHANCE */ + + HAL_MCR_WR(prAdapter, MCR_WHIER, WHIER_DEFAULT); + + HAL_CFG_MAX_HIF_RX_LEN_NUM(prAdapter, HIF_RX_MAX_AGG_NUM); +} + +void halTxCancelSendingCmd(IN struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo) +{ +} + +u_int8_t halTxIsDataBufEnough(IN struct ADAPTER *prAdapter, IN struct MSDU_INFO *prMsduInfo) +{ + return TRUE; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Driver maintain a variable that is synchronous with the usage of individual +* TC Buffer Count. This function will calculate TC page count according to +* the given TX_STATUS COUNTER after TX Done. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] au2TxRlsCnt array of TX STATUS +* \param[in] au2FreeTcResource array of free & available resource count +* +* @return TRUE there are available resource to release +* @return FALSE no available resource to release +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t halTxCalculateResource(IN struct ADAPTER *prAdapter, IN uint16_t *au2TxRlsCnt, OUT uint16_t *au2FreeTcResource) +{ + struct TX_TCQ_STATUS *prTcqStatus; + u_int8_t bStatus = FALSE; + uint8_t ucTcIdx; + uint32_t u4TotalTxDoneCnt = 0; + uint32_t u4TotalExtraTxDone = 0; + uint32_t au4UsedCnt[TC_NUM]; + uint32_t au4ExtraTxDone[TC_NUM]; + + uint32_t *au4TxDoneCnt; + uint32_t *au4PreUsedCnt; + uint32_t u4AvaliableCnt; + u_int8_t fgEnExtraTxDone; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prTcqStatus = &prAdapter->rTxCtrl.rTc; + + au4TxDoneCnt = prTcqStatus->au4TxDonePageCount; + au4PreUsedCnt = prTcqStatus->au4PreUsedPageCount; + u4AvaliableCnt = prTcqStatus->u4AvaliablePageCount; + fgEnExtraTxDone = prAdapter->rWifiVar.ucExtraTxDone; + + /* Get used page count */ + if (fgEnExtraTxDone) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + for (ucTcIdx = TC0_INDEX; ucTcIdx < TC_NUM; ucTcIdx++) { + au4UsedCnt[ucTcIdx] = prTcqStatus->au4MaxNumOfPage[ucTcIdx] - + prTcqStatus->au4FreePageCount[ucTcIdx]; + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + } + + /* Get Tx done & available page count */ + u4AvaliableCnt += au2TxRlsCnt[HIF_TX_FFA_INDEX]; + for (ucTcIdx = TC0_INDEX; ucTcIdx < TC_NUM; ucTcIdx++) { + + /* Get Tx done count from Tx interrupt status */ + au4TxDoneCnt[ucTcIdx] += au2TxRlsCnt[nicTxGetTxQByTc(prAdapter, ucTcIdx)]; + + /* Get available EXTRA Tx done */ + if (fgEnExtraTxDone) { + /* Release Tx done if there are pre-used resource */ + if (au4TxDoneCnt[ucTcIdx] >= au4PreUsedCnt[ucTcIdx]) { + au4TxDoneCnt[ucTcIdx] -= au4PreUsedCnt[ucTcIdx]; + au4PreUsedCnt[ucTcIdx] = 0; + } else { + au4PreUsedCnt[ucTcIdx] -= au4TxDoneCnt[ucTcIdx]; + au4TxDoneCnt[ucTcIdx] = 0; + } + + /* Calculate extra Tx done to share rest FFA resource */ + if (au4TxDoneCnt[ucTcIdx] >= au4UsedCnt[ucTcIdx]) { + au4TxDoneCnt[ucTcIdx] = au4UsedCnt[ucTcIdx]; + au4ExtraTxDone[ucTcIdx] = 0; + } else { + au4ExtraTxDone[ucTcIdx] = au4UsedCnt[ucTcIdx] - au4TxDoneCnt[ucTcIdx]; + } + u4TotalExtraTxDone += au4ExtraTxDone[ucTcIdx]; + } + + u4TotalTxDoneCnt += au4TxDoneCnt[ucTcIdx]; + + } + + DBGLOG(TX, TRACE, "TxDone result, FFA[%u] AC[%u:%u:%u:%u] CPU[%u]\n", + au2TxRlsCnt[HIF_TX_FFA_INDEX], au2TxRlsCnt[HIF_TX_AC0_INDEX], + au2TxRlsCnt[HIF_TX_AC1_INDEX], au2TxRlsCnt[HIF_TX_AC2_INDEX], + au2TxRlsCnt[HIF_TX_AC3_INDEX], au2TxRlsCnt[HIF_TX_CPU_INDEX]); + + DBGLOG(TX, TRACE, "TxDone Page count, TC[%u:%u:%u:%u:%u]\n", + au4TxDoneCnt[TC0_INDEX], au4TxDoneCnt[TC1_INDEX], au4TxDoneCnt[TC2_INDEX], + au4TxDoneCnt[TC3_INDEX], au4TxDoneCnt[TC4_INDEX]); + + /* Calculate free Tc page count */ + if (u4AvaliableCnt && u4TotalTxDoneCnt) { + /* Distribute resource by Tx done counter */ + if (u4AvaliableCnt >= u4TotalTxDoneCnt) { + /* Fulfill all TC resource */ + kalMemCopy(au2FreeTcResource, prTcqStatus->au4TxDonePageCount, + sizeof(prTcqStatus->au4TxDonePageCount)); + + kalMemZero(prTcqStatus->au4TxDonePageCount, sizeof(prTcqStatus->au4TxDonePageCount)); + + u4AvaliableCnt -= u4TotalTxDoneCnt; + } else { + /* Round-robin distribute resource */ + ucTcIdx = prTcqStatus->ucNextTcIdx; + while (u4AvaliableCnt) { + /* Enough resource, fulfill this TC */ + if (u4AvaliableCnt >= au4TxDoneCnt[ucTcIdx]) { + au2FreeTcResource[ucTcIdx] = au4TxDoneCnt[ucTcIdx]; + u4AvaliableCnt -= au4TxDoneCnt[ucTcIdx]; + au4TxDoneCnt[ucTcIdx] = 0; + + /* Round-robin get next TC */ + ucTcIdx++; + ucTcIdx %= TC_NUM; + } + /* no more resource, distribute rest of resource to this TC */ + else { + au2FreeTcResource[ucTcIdx] = u4AvaliableCnt; + au4TxDoneCnt[ucTcIdx] -= u4AvaliableCnt; + u4AvaliableCnt = 0; + } + } + prTcqStatus->ucNextTcIdx = ucTcIdx; + } + bStatus = TRUE; + } + + if (u4AvaliableCnt && u4TotalExtraTxDone && fgEnExtraTxDone) { + /* Distribute resource by EXTRA Tx done counter */ + if (u4AvaliableCnt >= u4TotalExtraTxDone) { + for (ucTcIdx = TC0_INDEX; ucTcIdx < TC_NUM; ucTcIdx++) { + au2FreeTcResource[ucTcIdx] += au4ExtraTxDone[ucTcIdx]; + au4PreUsedCnt[ucTcIdx] += au4ExtraTxDone[ucTcIdx]; + au4ExtraTxDone[ucTcIdx] = 0; + } + + u4AvaliableCnt -= u4TotalExtraTxDone; + } else { + /* Round-robin distribute resource */ + ucTcIdx = prTcqStatus->ucNextTcIdx; + while (u4AvaliableCnt) { + /* Enough resource, fulfill this TC */ + if (u4AvaliableCnt >= au4ExtraTxDone[ucTcIdx]) { + au2FreeTcResource[ucTcIdx] += au4ExtraTxDone[ucTcIdx]; + au4PreUsedCnt[ucTcIdx] += au4ExtraTxDone[ucTcIdx]; + u4AvaliableCnt -= au4ExtraTxDone[ucTcIdx]; + au4ExtraTxDone[ucTcIdx] = 0; + + /* Round-robin get next TC */ + ucTcIdx++; + ucTcIdx %= TC_NUM; + } + /* no more resource, distribute rest of resource to this TC */ + else { + au2FreeTcResource[ucTcIdx] += u4AvaliableCnt; + au4PreUsedCnt[ucTcIdx] += u4AvaliableCnt; + au4ExtraTxDone[ucTcIdx] -= u4AvaliableCnt; + u4AvaliableCnt = 0; + } + } + prTcqStatus->ucNextTcIdx = ucTcIdx; + } + bStatus = TRUE; + } + + prTcqStatus->u4AvaliablePageCount = u4AvaliableCnt; + + return bStatus; +} +u_int8_t halTxReleaseResource(IN struct ADAPTER *prAdapter, IN uint16_t *au2TxRlsCnt) +{ + struct TX_TCQ_STATUS *prTcqStatus; + u_int8_t bStatus = FALSE; + uint32_t i; + struct SDIO_STAT_COUNTER *prStatCnt; + uint16_t au2TxDoneCnt[HIF_TX_NUM] = { 0 }; + + ASSERT(prAdapter); + prTcqStatus = &prAdapter->rTxCtrl.rTc; + prStatCnt = &prAdapter->prGlueInfo->rHifInfo.rStatCounter; + + /* Update Free Tc resource counter */ + halTxGetFreeResource(prAdapter, au2TxDoneCnt, au2TxRlsCnt); + + /* Return free Tc page count */ + halTxReturnFreeResource(prAdapter, au2TxDoneCnt); + bStatus = TRUE; + + /* Update Statistic counter */ + prStatCnt->u4TxDonePendingPktCnt += nicTxGetMsduPendingCnt(prAdapter); + prStatCnt->u4TxDoneIntTotCnt++; + + for (i = HIF_TXC_IDX_0; i < HIF_TXC_IDX_NUM; i++) { + if (au2TxRlsCnt[i]) { + prStatCnt->u4TxDoneCnt[i] += au2TxRlsCnt[i]; + prStatCnt->u4TxDoneIntCnt[i]++; + } + } + + if (!nicTxSanityCheckResource(prAdapter)) + DBGLOG(TX, ERROR, "Tx Done INT result, FFA[%u] AC[%u:%u:%u:%u] CPU[%u]\n", + au2TxRlsCnt[HIF_TX_FFA_INDEX], au2TxRlsCnt[HIF_TX_AC0_INDEX], + au2TxRlsCnt[HIF_TX_AC1_INDEX], au2TxRlsCnt[HIF_TX_AC2_INDEX], + au2TxRlsCnt[HIF_TX_AC3_INDEX], au2TxRlsCnt[HIF_TX_CPU_INDEX]); + + DBGLOG(TX, LOUD, "TCQ Status Free Page <>:Buf[%u:%u, %u:%u, %u:%u, %u:%u, %u:%u]\n", + prTcqStatus->au4FreePageCount[TC0_INDEX], prTcqStatus->au4FreeBufferCount[TC0_INDEX], + prTcqStatus->au4FreePageCount[TC1_INDEX], prTcqStatus->au4FreeBufferCount[TC1_INDEX], + prTcqStatus->au4FreePageCount[TC2_INDEX], prTcqStatus->au4FreeBufferCount[TC2_INDEX], + prTcqStatus->au4FreePageCount[TC3_INDEX], prTcqStatus->au4FreeBufferCount[TC3_INDEX], + prTcqStatus->au4FreePageCount[TC4_INDEX], prTcqStatus->au4FreeBufferCount[TC4_INDEX]); + + + if (prAdapter->rTxCtrl.rTc.fgNeedPleCtrl) + DBGLOG(TX, LOUD, "TCQ Status Free Page <>:Buf[%u:%u, %u:%u, %u:%u, %u:%u, %u:%u]\n", + prTcqStatus->au4FreePageCount_PLE[TC0_INDEX], prTcqStatus->au4FreePageCount_PLE[TC0_INDEX], + prTcqStatus->au4FreePageCount_PLE[TC1_INDEX], prTcqStatus->au4FreePageCount_PLE[TC1_INDEX], + prTcqStatus->au4FreePageCount_PLE[TC2_INDEX], prTcqStatus->au4FreePageCount_PLE[TC2_INDEX], + prTcqStatus->au4FreePageCount_PLE[TC3_INDEX], prTcqStatus->au4FreePageCount_PLE[TC3_INDEX], + prTcqStatus->au4FreePageCount_PLE[TC4_INDEX], prTcqStatus->au4FreePageCount_PLE[TC4_INDEX]); + + return bStatus; +} + +uint32_t halTxPollingResource(IN struct ADAPTER *prAdapter, IN uint8_t ucTC) +{ + struct TX_CTRL *prTxCtrl; + uint32_t u4Status = WLAN_STATUS_RESOURCES; + uint32_t au4WTSR[8]; + struct GL_HIF_INFO *prHifInfo; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + prTxCtrl = &prAdapter->rTxCtrl; + + if (prHifInfo->fgIsPendingInt && (prHifInfo->prSDIOCtrl->u4WHISR & WHISR_TX_DONE_INT)) { + /* Get Tx done resource from pending interrupt status */ + kalMemCopy(au4WTSR, &prHifInfo->prSDIOCtrl->rTxInfo, sizeof(uint32_t) * 8); + + /* Clear pending Tx done interrupt */ + prHifInfo->prSDIOCtrl->u4WHISR &= ~WHISR_TX_DONE_INT; + } else + HAL_READ_TX_RELEASED_COUNT(prAdapter, au4WTSR); + + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + } else if (halTxReleaseResource(prAdapter, (uint16_t *) au4WTSR)) { + if (prTxCtrl->rTc.au4FreeBufferCount[ucTC] > 0) + u4Status = WLAN_STATUS_SUCCESS; + } + + return u4Status; +} + +void halTxInterruptSanityCheck(IN struct ADAPTER *prAdapter, IN uint16_t *au2TxRlsCnt) +{ + uint8_t ucIdx; + u_int8_t fgError = FALSE; + + if (prAdapter->rWifiVar.ucTxDbg & BIT(1)) { + for (ucIdx = HIF_TX_AC0_INDEX; ucIdx < HIF_TX_NUM; ucIdx++) { + if (au2TxRlsCnt[ucIdx] > prAdapter->rTxCtrl.u4TotalPageNum) + fgError = TRUE; + } + + if (fgError) + DBGLOG(TX, ERROR, "Tx Done INT result, FFA[%u] AC[%u:%u:%u:%u] CPU[%u]\n", + au2TxRlsCnt[HIF_TX_FFA_INDEX], au2TxRlsCnt[HIF_TX_AC0_INDEX], + au2TxRlsCnt[HIF_TX_AC1_INDEX], au2TxRlsCnt[HIF_TX_AC2_INDEX], + au2TxRlsCnt[HIF_TX_AC3_INDEX], au2TxRlsCnt[HIF_TX_CPU_INDEX]); + } +} + +#if CFG_SDIO_INTR_ENHANCE +void halProcessEnhanceInterruptStatus(IN struct ADAPTER *prAdapter) +{ + struct ENHANCE_MODE_DATA_STRUCT *prSDIOCtrl = prAdapter->prGlueInfo->rHifInfo.prSDIOCtrl; + + /* Set Tx done interrupt if there are Tx done count */ + if ((prSDIOCtrl->u4WHISR & WHISR_TX_DONE_INT) == 0 && + (prSDIOCtrl->rTxInfo.au4WTSR[0] | prSDIOCtrl->rTxInfo.au4WTSR[1] | + prSDIOCtrl->rTxInfo.au4WTSR[2] | prSDIOCtrl->rTxInfo.au4WTSR[3] | + prSDIOCtrl->rTxInfo.au4WTSR[4] | prSDIOCtrl->rTxInfo.au4WTSR[5] | + prSDIOCtrl->rTxInfo.au4WTSR[6] | prSDIOCtrl->rTxInfo.au4WTSR[7])) { + + prSDIOCtrl->u4WHISR |= WHISR_TX_DONE_INT; + } + + /* Set SW ASSERT INFO interrupt if there are pending mail box */ + if (((prSDIOCtrl->u4WHISR & WHISR_D2H_SW_ASSERT_INFO_INT) == 0) && + HAL_GET_MAILBOX_READ_CLEAR(prAdapter) && + (prSDIOCtrl->u4RcvMailbox0 || prSDIOCtrl->u4RcvMailbox1)) { + + prSDIOCtrl->u4WHISR |= WHISR_D2H_SW_ASSERT_INFO_INT; + } +} +#endif + +void halProcessTxInterrupt(IN struct ADAPTER *prAdapter) +{ + struct TX_CTRL *prTxCtrl; +#if CFG_SDIO_INTR_ENHANCE + struct ENHANCE_MODE_DATA_STRUCT *prSDIOCtrl; +#else + uint32_t au4TxCount[2]; +#endif /* CFG_SDIO_INTR_ENHANCE */ + SDIO_TIME_INTERVAL_DEC(); + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + SDIO_REC_TIME_START(); + + /* Get the TX STATUS */ +#if CFG_SDIO_INTR_ENHANCE + + prSDIOCtrl = prAdapter->prGlueInfo->rHifInfo.prSDIOCtrl; +#if DBG + /* DBGLOG_MEM8(RX, TRACE, (PUINT_8)prSDIOCtrl, sizeof(SDIO_CTRL_T)); */ +#endif + + halTxInterruptSanityCheck(prAdapter, (uint16_t *)&prSDIOCtrl->rTxInfo); + halTxReleaseResource(prAdapter, (uint16_t *)&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]); + + halTxReleaseResource(prAdapter, (uint8_t *) au4TxCount); + +#endif /* CFG_SDIO_INTR_ENHANCE */ + + nicTxAdjustTcq(prAdapter); + kalSetTxEvent2Hif(prAdapter->prGlueInfo); + + SDIO_REC_TIME_END(); + SDIO_ADD_TIME_INTERVAL(prAdapter->prGlueInfo->rHifInfo.rStatCounter.u4TxDoneIntTime); + +} /* end of nicProcessTxInterrupt() */ + +#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 +* +*/ +/*----------------------------------------------------------------------------*/ +uint32_t halRxReadBuffer(IN struct ADAPTER *prAdapter, IN OUT struct SW_RFB *prSwRfb) +{ + struct RX_CTRL *prRxCtrl; + uint8_t *pucBuf; + struct HW_MAC_RX_DESC *prRxStatus; + uint32_t u4PktLen = 0, u4ReadBytes; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + u_int8_t fgResult = TRUE; + uint32_t u4RegValue; + uint32_t rxNum; +#if CFG_TCP_IP_CHKSUM_OFFLOAD + uint32_t *pu4HwAppendDW; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + DEBUGFUNC("halRxReadBuffer"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + pucBuf = prSwRfb->pucRecvBuff; + prRxStatus = prSwRfb->prRxStatus; + + ASSERT(prRxStatus); + ASSERT(pucBuf); + DBGLOG(RX, TRACE, "pucBuf= 0x%x, prRxStatus= 0x%x\n", pucBuf, prRxStatus); + + 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 != (uint32_t) HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus)) { + DBGLOG(RX, ERROR, "Read u4PktLen = %d, prHifRxHdr->u2PacketLen: %d\n", + u4PktLen, HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus)); +#if DBG + DBGLOG_MEM8(RX, TRACE, (uint8_t *) prRxStatus, + (HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus) > + 4096) ? 4096 : prRxStatus->u2RxByteCount); +#endif + ASSERT(0); + } + /* u4PktLen is byte unit, not inlude HW appended DW */ + + prSwRfb->ucPacketType = (uint8_t) HAL_RX_STATUS_GET_PKT_TYPE(prRxStatus); + DBGLOG(RX, TRACE, "ucPacketType = %d\n", prSwRfb->ucPacketType); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + pu4HwAppendDW = (uint32_t *) prRxStatus; + pu4HwAppendDW += (ALIGN_4(prRxStatus->u2RxByteCount) >> 2); + prSwRfb->u4TcpUdpIpCksStatus = *pu4HwAppendDW; + DBGLOG(RX, TRACE, "u4TcpUdpIpCksStatus[0x%02x]\n", prSwRfb->u4TcpUdpIpCksStatus); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + prSwRfb->ucStaRecIdx = + secGetStaIdxByWlanIdx(prAdapter, (uint8_t) HAL_RX_STATUS_GET_WLAN_IDX(prRxStatus)); + + /* 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 halRxSDIOReceiveRFBs(IN struct ADAPTER *prAdapter) +{ + struct RX_CTRL *prRxCtrl; + struct SW_RFB *prSwRfb = (struct SW_RFB *) NULL; + struct HW_MAC_RX_DESC *prRxStatus; + uint32_t u4HwAppendDW; + uint32_t *pu4Temp; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("halRxSDIOReceiveRFBs"); + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + do { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, struct SW_RFB *); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + if (!prSwRfb) { + DBGLOG(RX, TRACE, "No More RFB\n"); + break; + } + /* need to consider */ + if (halRxReadBuffer(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); + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + pu4Temp = (uint32_t *) prRxStatus; + u4HwAppendDW = *(pu4Temp + (ALIGN_4(prRxStatus->u2RxByteCount) >> 2)); + DBGLOG(RX, TRACE, "u4HwAppendDW = 0x%x\n", u4HwAppendDW); + DBGLOG(RX, TRACE, "u2PacketLen = 0x%x\n", HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus)); + } while (FALSE); + +} /* 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) +*/ +/*----------------------------------------------------------------------------*/ + +uint32_t +halRxEnhanceReadBuffer(IN struct ADAPTER *prAdapter, + IN uint32_t u4DataPort, IN uint16_t u2RxLength, IN OUT struct SW_RFB *prSwRfb) +{ + struct RX_CTRL *prRxCtrl; + uint8_t *pucBuf; + struct HW_MAC_RX_DESC *prRxStatus; + uint32_t u4PktLen = 0; + uint32_t u4Status = WLAN_STATUS_FAILURE; + u_int8_t fgResult = TRUE; +#if CFG_TCP_IP_CHKSUM_OFFLOAD + uint32_t *pu4HwAppendDW; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + DEBUGFUNC("halRxEnhanceReadBuffer"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + pucBuf = prSwRfb->pucRecvBuff; + ASSERT(pucBuf); + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + /* 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 = (uint32_t) (HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus)); + /* DBGLOG(RX, TRACE, ("u4PktLen = %d\n", u4PktLen)); */ + + prSwRfb->ucPacketType = (uint8_t) HAL_RX_STATUS_GET_PKT_TYPE(prRxStatus); + /* DBGLOG(RX, TRACE, ("ucPacketType = %d\n", prSwRfb->ucPacketType)); */ + + prSwRfb->ucStaRecIdx = + secGetStaIdxByWlanIdx(prAdapter, (uint8_t) HAL_RX_STATUS_GET_WLAN_IDX(prRxStatus)); + + /* 4 <2> if the RFB dw size or packet size is zero */ + if (u4PktLen == 0) { + DBGLOG(RX, ERROR, "Packet Length = %u\n", + u4PktLen); + ASSERT(0); + break; + } + /* 4 <3> if the packet is too large or too small */ + /* ToDo[6630]: adjust CFG_RX_MAX_PKT_SIZE */ + if (u4PktLen > CFG_RX_MAX_PKT_SIZE) { + DBGLOG(RX, TRACE, "Read RX Packet Lentgh Error (%u)\n", + u4PktLen); + ASSERT(0); + break; + } + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + pu4HwAppendDW = (uint32_t *) prRxStatus; + pu4HwAppendDW += (ALIGN_4(prRxStatus->u2RxByteCount) >> 2); + prSwRfb->u4TcpUdpIpCksStatus = *pu4HwAppendDW; + DBGLOG(RX, TRACE, "u4TcpUdpIpCksStatus[0x%02x]\n", prSwRfb->u4TcpUdpIpCksStatus); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + 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 halRxSDIOEnhanceReceiveRFBs(IN struct ADAPTER *prAdapter) +{ + struct ENHANCE_MODE_DATA_STRUCT *prSDIOCtrl; + struct RX_CTRL *prRxCtrl; + struct SW_RFB *prSwRfb = (struct SW_RFB *) NULL; + uint32_t i, rxNum; + uint16_t u2RxPktNum, u2RxLength = 0, u2Tmp = 0; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("halRxSDIOEnhanceReceiveRFBs"); + + ASSERT(prAdapter); + + prSDIOCtrl = prAdapter->prGlueInfo->rHifInfo.prSDIOCtrl; + ASSERT(prSDIOCtrl); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + for (rxNum = 0; rxNum < 2; rxNum++) { + u2RxPktNum = + (rxNum == 0 ? prSDIOCtrl->rRxInfo.u.u2NumValidRx0Len : prSDIOCtrl->rRxInfo.u.u2NumValidRx1Len); + + if (u2RxPktNum == 0) + continue; + + for (i = 0; i < u2RxPktNum; i++) { + if (rxNum == 0) { + /* HAL_READ_RX_LENGTH */ + HAL_READ_RX_LENGTH(prAdapter, &u2RxLength, &u2Tmp); + } else if (rxNum == 1) { + /* HAL_READ_RX_LENGTH */ + HAL_READ_RX_LENGTH(prAdapter, &u2Tmp, &u2RxLength); + } + + if (!u2RxLength) + break; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, struct SW_RFB *); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + if (!prSwRfb) { + DBGLOG(RX, TRACE, "No More RFB\n"); + break; + } + ASSERT(prSwRfb); + + if (halRxEnhanceReadBuffer(prAdapter, rxNum, u2RxLength, prSwRfb) == WLAN_STATUS_FAILURE) { + DBGLOG(RX, TRACE, "nicRxEnhanceRxReadBuffer failed\n"); + nicRxReturnRFB(prAdapter, prSwRfb); + break; + } + /* prSDIOCtrl->au4RxLength[i] = 0; */ + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_INSERT_TAIL(&prRxCtrl->rReceivedRfbList, &prSwRfb->rQueEntry); + RX_INC_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + } + } + + prSDIOCtrl->rRxInfo.u.u2NumValidRx0Len = 0; + prSDIOCtrl->rRxInfo.u.u2NumValidRx1Len = 0; + +} /* end of nicRxSDIOReceiveRFBs() */ + +#endif /* CFG_SDIO_INTR_ENHANCE */ + +#if CFG_SDIO_RX_AGG +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read frames from the data port for SDIO with Rx aggregation enabled +* I/F, fill RFB and put each frame into the rReceivedRFBList queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void halRxSDIOAggReceiveRFBs(IN struct ADAPTER *prAdapter) +{ + struct ENHANCE_MODE_DATA_STRUCT *prEnhDataStr; + struct RX_CTRL *prRxCtrl; + uint32_t u4RxLength; + uint32_t i, rxNum; + uint32_t u4RxAggCount = 0, u4RxAggLength = 0; + uint32_t u4RxAvailAggLen; + uint8_t *pucSrcAddr; + uint16_t u2RxPktNum; + struct GL_HIF_INFO *prHifInfo; + struct SDIO_RX_COALESCING_BUF *prRxBuf; + u_int8_t fgNoFreeBuf = FALSE; + + SDIO_TIME_INTERVAL_DEC(); + + DEBUGFUNC("halRxSDIOAggReceiveRFBs"); + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + prEnhDataStr = prHifInfo->prSDIOCtrl; + + if (prEnhDataStr->rRxInfo.u.u2NumValidRx0Len == 0 && prEnhDataStr->rRxInfo.u.u2NumValidRx1Len == 0) + return; + + for (rxNum = 0; rxNum < 2; rxNum++) { + u2RxPktNum = (rxNum == 0 ? prEnhDataStr->rRxInfo.u.u2NumValidRx0Len : + prEnhDataStr->rRxInfo.u.u2NumValidRx1Len); + + if (u2RxPktNum > HIF_RX_MAX_AGG_NUM) { + DBGLOG(RX, ERROR, + "[%s] u2RxPktNum (%d) > HIF_RX_MAX_AGG_NUM\n", + __func__, u2RxPktNum); + + halProcessAbnormalInterrupt(prAdapter); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP); + return; + } + + if (u2RxPktNum == 0) + continue; + +#if CFG_HIF_STATISTICS + prRxCtrl->u4TotalRxAccessNum++; + prRxCtrl->u4TotalRxPacketNum += u2RxPktNum; +#endif + + mutex_lock(&prHifInfo->rRxFreeBufQueMutex); + fgNoFreeBuf = QUEUE_IS_EMPTY(&prHifInfo->rRxFreeBufQueue); + mutex_unlock(&prHifInfo->rRxFreeBufQueMutex); + + if (fgNoFreeBuf) { + DBGLOG(RX, TRACE, "[%s] No free Rx buffer\n", __func__); + prHifInfo->rStatCounter.u4RxBufUnderFlowCnt++; + + if (prAdapter->prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + struct QUE rTempQue; + struct QUE *prTempQue = &rTempQue; + + /* During halt state, move all pending Rx buffer to free queue */ + mutex_lock(&prHifInfo->rRxDeAggQueMutex); + QUEUE_MOVE_ALL(prTempQue, &prHifInfo->rRxDeAggQueue); + mutex_unlock(&prHifInfo->rRxDeAggQueMutex); + + mutex_lock(&prHifInfo->rRxFreeBufQueMutex); + QUEUE_CONCATENATE_QUEUES(&prHifInfo->rRxFreeBufQueue, prTempQue); + mutex_unlock(&prHifInfo->rRxFreeBufQueMutex); + } + + continue; + } + + u4RxAvailAggLen = HIF_RX_COALESCING_BUFFER_SIZE; +#if CFG_SDIO_RX_ENHANCE + u4RxAvailAggLen -= (sizeof(struct ENHANCE_MODE_DATA_STRUCT) + HIF_RX_ENHANCE_MODE_PAD_LEN); +#endif + u4RxAggCount = 0; + + for (i = 0; i < u2RxPktNum; i++) { + u4RxLength = (rxNum == 0 ? (uint32_t) prEnhDataStr->rRxInfo.u.au2Rx0Len[i] : + (uint32_t) prEnhDataStr->rRxInfo.u.au2Rx1Len[i]); + + if (!u4RxLength) { + DBGLOG(RX, ERROR, "[%s] RxLength == 0\n", __func__); + halProcessAbnormalInterrupt(prAdapter); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP); + return; + } + + if (ALIGN_4(u4RxLength + HIF_RX_HW_APPENDED_LEN) < u4RxAvailAggLen) { + u4RxAvailAggLen -= ALIGN_4(u4RxLength + HIF_RX_HW_APPENDED_LEN); + u4RxAggCount++; + } else { + /* CFG_RX_COALESCING_BUFFER_SIZE is not large enough */ + DBGLOG(RX, ERROR, "[%s] Request_len(%d) >= Available_len(%d)\n", + __func__, (ALIGN_4(u4RxLength + HIF_RX_HW_APPENDED_LEN)), u4RxAvailAggLen); + + halProcessAbnormalInterrupt(prAdapter); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP); + return; + } + } + + mutex_lock(&prHifInfo->rRxFreeBufQueMutex); + QUEUE_REMOVE_HEAD(&prHifInfo->rRxFreeBufQueue, prRxBuf, struct SDIO_RX_COALESCING_BUF *); + mutex_unlock(&prHifInfo->rRxFreeBufQueMutex); + + prRxBuf->u4PktCount = u4RxAggCount; + + u4RxAggLength = (HIF_RX_COALESCING_BUFFER_SIZE - u4RxAvailAggLen); + + prRxBuf->u4PktTotalLength = u4RxAggLength - sizeof(struct ENHANCE_MODE_DATA_STRUCT); + + prRxBuf->u4IntLogIdx = prHifInfo->u4IntLogIdx; + + SDIO_REC_TIME_START(); + HAL_READ_RX_PORT(prAdapter, rxNum, u4RxAggLength, + prRxBuf->pvRxCoalescingBuf, HIF_RX_COALESCING_BUFFER_SIZE); + SDIO_REC_TIME_END(); + SDIO_ADD_TIME_INTERVAL(prHifInfo->rStatCounter.u4PortReadTime); + +#if CFG_SDIO_RX_ENHANCE + pucSrcAddr = prRxBuf->pvRxCoalescingBuf + u4RxAggLength - sizeof(struct ENHANCE_MODE_DATA_STRUCT); + + /* Sanity check of zero padding before interrupt status */ + if (((uint32_t)*(pucSrcAddr - HIF_RX_ENHANCE_MODE_PAD_LEN)) == 0) { + kalMemCopy(prHifInfo->prSDIOCtrl, pucSrcAddr, sizeof(struct ENHANCE_MODE_DATA_STRUCT)); + + halProcessEnhanceInterruptStatus(prAdapter); + + if (prHifInfo->prSDIOCtrl->u4WHISR) { + /* Interrupt status without Rx done */ + /* Mask Rx done interrupt to avoid recurrsion */ + uint32_t u4IntStatus = prHifInfo->prSDIOCtrl->u4WHISR & + (~(WHISR_RX0_DONE_INT | WHISR_RX1_DONE_INT)); + + if ((rxNum == 0) && prEnhDataStr->rRxInfo.u.u2NumValidRx1Len && u4IntStatus) { + /* Handle interrupt here if there are pending Rx port1 */ + + nicProcessIST_impl(prAdapter, u4IntStatus); + } else { + prAdapter->prGlueInfo->rHifInfo.fgIsPendingInt = TRUE; + } + } + } +#endif + halDeAggRxPkt(prAdapter, prRxBuf); + + /* Update statistic counter */ + prHifInfo->rStatCounter.u4PktReadCnt[rxNum] += u4RxAggCount; + prHifInfo->rStatCounter.u4PortReadCnt[rxNum]++; + } + +} +#endif /* CFG_SDIO_RX_AGG */ + + +void halProcessRxInterrupt(IN struct ADAPTER *prAdapter) +{ + if (prAdapter->prGlueInfo->rHifInfo.fgSkipRx) + return; + +#if CFG_SDIO_INTR_ENHANCE +#if CFG_SDIO_RX_AGG + halRxSDIOAggReceiveRFBs(prAdapter); +#else + halRxSDIOEnhanceReceiveRFBs(prAdapter); +#endif +#else + halRxSDIOReceiveRFBs(prAdapter); +#endif /* CFG_SDIO_INTR_ENHANCE */ +} + +bool halHifSwInfoInit(IN struct ADAPTER *prAdapter) +{ + return true; +} + +void halRxProcessMsduReport(IN struct ADAPTER *prAdapter, IN OUT struct SW_RFB *prSwRfb) +{ + +} + +uint32_t halTxGetPageCountPSE(IN struct ADAPTER *prAdapter, IN uint32_t u4FrameLength) +{ + uint32_t u4PageSize = prAdapter->rTxCtrl.u4PageSize; + + return ((u4FrameLength + prAdapter->nicTxReousrce.ucPpTxAddCnt + u4PageSize - 1)/u4PageSize); +} + +uint32_t halTxGetPageCount(IN struct ADAPTER *prAdapter, IN uint32_t u4FrameLength, IN u_int8_t fgIncludeDesc) +{ + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + + if (prChipInfo->is_support_cr4) + return 1; + + return halTxGetPageCountPSE(prAdapter, u4FrameLength); +} + +uint32_t halDumpHifStatus(IN struct ADAPTER *prAdapter, IN uint8_t *pucBuf, IN uint32_t u4Max) +{ + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + struct SDIO_STAT_COUNTER *prStatCnt = &prHifInfo->rStatCounter; + uint32_t u4Len = 0; + uint32_t u4Idx; + + /* Print out counter */ + LOGBUF(pucBuf, u4Max, u4Len, "\n"); + LOGBUF(pucBuf, u4Max, u4Len, "------------\n"); + + LOGBUF(pucBuf, u4Max, u4Len, "Coalescing buffer size[%u] Rx Cnt[%u/%u] DeAgg[%u] UF Cnt[%u]\n", + prAdapter->u4CoalescingBufCachedSize, prHifInfo->rRxFreeBufQueue.u4NumElem, + HIF_RX_COALESCING_BUF_COUNT, prHifInfo->rRxDeAggQueue.u4NumElem, + prStatCnt->u4RxBufUnderFlowCnt); + + LOGBUF(pucBuf, u4Max, u4Len, "Pkt cnt Tx[%u] RxP0[%u] RxP1[%u] Tx/Rx ratio[%u.%u]\n", + prStatCnt->u4DataPktWriteCnt, prStatCnt->u4PktReadCnt[0], prStatCnt->u4PktReadCnt[1], + DIV2INT(prStatCnt->u4DataPktWriteCnt, prStatCnt->u4PktReadCnt[0]), + DIV2DEC(prStatCnt->u4DataPktWriteCnt, prStatCnt->u4PktReadCnt[0])); + + LOGBUF(pucBuf, u4Max, u4Len, "Tx pkt/wt[%u.%u] pkt/kick[%u.%u] cmd/wt[%u.%u]\n", + DIV2INT(prStatCnt->u4DataPktWriteCnt, prStatCnt->u4DataPortWriteCnt), + DIV2DEC(prStatCnt->u4DataPktWriteCnt, prStatCnt->u4DataPortWriteCnt), + DIV2INT(prStatCnt->u4DataPktWriteCnt, prStatCnt->u4DataPortKickCnt), + DIV2DEC(prStatCnt->u4DataPktWriteCnt, prStatCnt->u4DataPortKickCnt), + DIV2INT(prStatCnt->u4CmdPktWriteCnt, prStatCnt->u4CmdPortWriteCnt), + DIV2DEC(prStatCnt->u4CmdPktWriteCnt, prStatCnt->u4CmdPortWriteCnt)); + + LOGBUF(pucBuf, u4Max, u4Len, "Rx P0 pkt/rd[%u.%u] P1 pkt/rd[%u.%u]\n", + DIV2INT(prStatCnt->u4PktReadCnt[0], prStatCnt->u4PortReadCnt[0]), + DIV2DEC(prStatCnt->u4PktReadCnt[0], prStatCnt->u4PortReadCnt[0]), + DIV2INT(prStatCnt->u4PktReadCnt[1], prStatCnt->u4PortReadCnt[1]), + DIV2DEC(prStatCnt->u4PktReadCnt[1], prStatCnt->u4PortReadCnt[1])); + + LOGBUF(pucBuf, u4Max, u4Len, "Tx done pending cnt HIF_TXC00~04[%u, %u, %u, %u, %u]\n", + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_0], + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_1], + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_2], + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_3], + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_4]); + + LOGBUF(pucBuf, u4Max, u4Len, "Tx done pending cnt HIF_TXC05~09[%u, %u, %u, %u, %u]\n", + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_5], + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_6], + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_7], + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_8], + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_9]); + + LOGBUF(pucBuf, u4Max, u4Len, "Tx done pending cnt HIF_TXC10~15[%u, %u, %u, %u, %u, %u]\n", + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_10], + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_11], + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_12], + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_13], + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_14], + prHifInfo->au4PendingTxDoneCount[HIF_TXC_IDX_15]); + + + LOGBUF(pucBuf, u4Max, u4Len, "Tx done counter/int:\n"); + LOGBUF(pucBuf, u4Max, u4Len, "AC00~03[%u.%u, %u.%u, %u.%u, %u.%u]\n", + DIV2INT(prStatCnt->u4TxDoneCnt[0], prStatCnt->u4TxDoneIntCnt[0]), + DIV2DEC(prStatCnt->u4TxDoneCnt[0], prStatCnt->u4TxDoneIntCnt[0]), + DIV2INT(prStatCnt->u4TxDoneCnt[1], prStatCnt->u4TxDoneIntCnt[1]), + DIV2DEC(prStatCnt->u4TxDoneCnt[1], prStatCnt->u4TxDoneIntCnt[1]), + DIV2INT(prStatCnt->u4TxDoneCnt[2], prStatCnt->u4TxDoneIntCnt[2]), + DIV2DEC(prStatCnt->u4TxDoneCnt[2], prStatCnt->u4TxDoneIntCnt[2]), + DIV2INT(prStatCnt->u4TxDoneCnt[3], prStatCnt->u4TxDoneIntCnt[3]), + DIV2DEC(prStatCnt->u4TxDoneCnt[3], prStatCnt->u4TxDoneIntCnt[3])); + + LOGBUF(pucBuf, u4Max, u4Len, "AC10~13[%u.%u, %u.%u, %u.%u, %u.%u]\n", + DIV2INT(prStatCnt->u4TxDoneCnt[4], prStatCnt->u4TxDoneIntCnt[4]), + DIV2DEC(prStatCnt->u4TxDoneCnt[4], prStatCnt->u4TxDoneIntCnt[4]), + DIV2INT(prStatCnt->u4TxDoneCnt[5], prStatCnt->u4TxDoneIntCnt[5]), + DIV2DEC(prStatCnt->u4TxDoneCnt[5], prStatCnt->u4TxDoneIntCnt[5]), + DIV2INT(prStatCnt->u4TxDoneCnt[6], prStatCnt->u4TxDoneIntCnt[6]), + DIV2DEC(prStatCnt->u4TxDoneCnt[5], prStatCnt->u4TxDoneIntCnt[5]), + DIV2INT(prStatCnt->u4TxDoneCnt[7], prStatCnt->u4TxDoneIntCnt[7]), + DIV2DEC(prStatCnt->u4TxDoneCnt[7], prStatCnt->u4TxDoneIntCnt[7])); + + LOGBUF(pucBuf, u4Max, u4Len, "AC20~23[%u.%u, %u.%u, %u.%u, %u.%u] FFA,CPU[%u.%u, %u.%u]\n", + DIV2INT(prStatCnt->u4TxDoneCnt[8], prStatCnt->u4TxDoneIntCnt[8]), + DIV2DEC(prStatCnt->u4TxDoneCnt[8], prStatCnt->u4TxDoneIntCnt[8]), + DIV2INT(prStatCnt->u4TxDoneCnt[9], prStatCnt->u4TxDoneIntCnt[9]), + DIV2DEC(prStatCnt->u4TxDoneCnt[9], prStatCnt->u4TxDoneIntCnt[9]), + DIV2INT(prStatCnt->u4TxDoneCnt[10], prStatCnt->u4TxDoneIntCnt[10]), + DIV2DEC(prStatCnt->u4TxDoneCnt[10], prStatCnt->u4TxDoneIntCnt[10]), + DIV2INT(prStatCnt->u4TxDoneCnt[11], prStatCnt->u4TxDoneIntCnt[11]), + DIV2DEC(prStatCnt->u4TxDoneCnt[11], prStatCnt->u4TxDoneIntCnt[11]), + DIV2INT(prStatCnt->u4TxDoneCnt[14], prStatCnt->u4TxDoneIntCnt[14]), + DIV2DEC(prStatCnt->u4TxDoneCnt[14], prStatCnt->u4TxDoneIntCnt[14]), + DIV2INT(prStatCnt->u4TxDoneCnt[15], prStatCnt->u4TxDoneIntCnt[15]), + DIV2DEC(prStatCnt->u4TxDoneCnt[15], prStatCnt->u4TxDoneIntCnt[15])); + + LOGBUF(pucBuf, u4Max, u4Len, "Pending pkt/int[%u.%u] kick/int[%u.%u] rx_enh/sts[%u.%u]\n", + DIV2INT(prStatCnt->u4TxDonePendingPktCnt, prStatCnt->u4TxDoneIntTotCnt), + DIV2DEC(prStatCnt->u4TxDonePendingPktCnt, prStatCnt->u4TxDoneIntTotCnt), + DIV2INT(prStatCnt->u4DataPortKickCnt, prStatCnt->u4TxDoneIntTotCnt), + DIV2DEC(prStatCnt->u4DataPortKickCnt, prStatCnt->u4TxDoneIntTotCnt), + DIV2INT((prStatCnt->u4IntCnt - prStatCnt->u4IntReadCnt), prStatCnt->u4IntCnt), + DIV2DEC((prStatCnt->u4IntCnt - prStatCnt->u4IntReadCnt), prStatCnt->u4IntCnt)); + +#if CFG_SDIO_TIMING_PROFILING + LOGBUF(pucBuf, u4Max, u4Len, "Tx cp_t/pkt[%u.%uus] free/pkt[%u.%uus]\n", + DIV2INT(prStatCnt->u4TxDataCpTime, prStatCnt->u4DataPktWriteCnt), + DIV2DEC(prStatCnt->u4TxDataCpTime, prStatCnt->u4DataPktWriteCnt), + DIV2INT(prStatCnt->u4TxDataFreeTime, prStatCnt->u4DataPktWriteCnt), + DIV2DEC(prStatCnt->u4TxDataFreeTime, prStatCnt->u4DataPktWriteCnt)); + + LOGBUF(pucBuf, u4Max, u4Len, "Rx P0 cp_t/pkt[%u.%uus] avg read[%u.%uus]\n", + DIV2INT(prStatCnt->u4RxDataCpTime, prStatCnt->u4PktReadCnt[0]), + DIV2DEC(prStatCnt->u4RxDataCpTime, prStatCnt->u4PktReadCnt[0]), + DIV2INT(prStatCnt->u4PortReadTime, prStatCnt->u4PortReadCnt[0]), + DIV2DEC(prStatCnt->u4PortReadTime, prStatCnt->u4PortReadCnt[0])); + + LOGBUF(pucBuf, u4Max, u4Len, "INT rd_sts/sts[%u.%uus] tx_sts/sts[%u.%uus]\n", + DIV2INT(prStatCnt->u4IntReadTime, prStatCnt->u4IntReadCnt), + DIV2DEC(prStatCnt->u4IntReadTime, prStatCnt->u4IntReadCnt), + DIV2INT(prStatCnt->u4TxDoneIntTime, prStatCnt->u4TxDoneIntTotCnt), + DIV2DEC(prStatCnt->u4TxDoneIntTime, prStatCnt->u4TxDoneIntTotCnt)); +#endif + + LOGBUF(pucBuf, u4Max, u4Len, "---------------------------------\n"); + + for (u4Idx = 0; u4Idx < CFG_SDIO_INT_LOG_CNT; u4Idx++) { + struct SDIO_INT_LOG_T *prIntLog = &prHifInfo->arIntLog[u4Idx]; + struct ENHANCE_MODE_DATA_STRUCT *prIntSts = (struct ENHANCE_MODE_DATA_STRUCT *)&prIntLog->aucIntSts[0]; + uint8_t ucPktIdx; + + LOGBUF(pucBuf, u4Max, u4Len, "INT IDX[%u] STS[0x%08x] FG[0x%08x] Rx Pkt[%u] Sts0/1[%u:%u]\n", + prIntLog->u4Idx, prIntSts->u4WHISR, prIntLog->u4Flag, prIntLog->ucRxPktCnt, + prIntSts->rRxInfo.u.u2NumValidRx0Len, prIntSts->rRxInfo.u.u2NumValidRx1Len); + + if (prIntLog->ucRxPktCnt) { + LOGBUF(pucBuf, u4Max, u4Len, "RxDAggLen["); + for (ucPktIdx = 0; ucPktIdx < prIntLog->ucRxPktCnt; ucPktIdx++) + LOGBUF(pucBuf, u4Max, u4Len, "%4u:", prIntLog->au2RxPktLen[ucPktIdx]); + LOGBUF(pucBuf, u4Max, u4Len, "]\n"); + + LOGBUF(pucBuf, u4Max, u4Len, "RxDAggSn ["); + for (ucPktIdx = 0; ucPktIdx < prIntLog->ucRxPktCnt; ucPktIdx++) + LOGBUF(pucBuf, u4Max, u4Len, "0x%08x: ", prIntLog->au4RxPktInfo[ucPktIdx]); + LOGBUF(pucBuf, u4Max, u4Len, "]\n"); + } + + if (prIntSts->rRxInfo.u.u2NumValidRx0Len) { + LOGBUF(pucBuf, u4Max, u4Len, "Rx0StsLen["); + for (ucPktIdx = 0; ucPktIdx < prIntSts->rRxInfo.u.u2NumValidRx0Len; ucPktIdx++) + LOGBUF(pucBuf, u4Max, u4Len, "%4u:", prIntSts->rRxInfo.u.au2Rx0Len[ucPktIdx]); + LOGBUF(pucBuf, u4Max, u4Len, "]\n"); + } + + if (prIntSts->rRxInfo.u.u2NumValidRx1Len) { + LOGBUF(pucBuf, u4Max, u4Len, "Rx1StsLen["); + for (ucPktIdx = 0; ucPktIdx < HIF_RX_MAX_AGG_NUM; ucPktIdx++) + LOGBUF(pucBuf, u4Max, u4Len, "%4u:", prIntSts->rRxInfo.u.au2Rx1Len[ucPktIdx]); + LOGBUF(pucBuf, u4Max, u4Len, "]\n"); + } + } + + LOGBUF(pucBuf, u4Max, u4Len, "---------------------------------\n"); + + /* Reset statistic counter */ + kalMemZero(prStatCnt, sizeof(struct SDIO_STAT_COUNTER)); + + halDumpIntLog(prAdapter); + + return u4Len; +} + +#if (CFG_SDIO_ACCESS_N9_REGISTER_BY_MAILBOX == 1) +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* This routine is used to get the value of N9 register +* by SDIO SW interrupt and mailbox. +* +* \param[in] +* pvAdapter: Pointer to the Adapter structure. +* addr: the interested address to be read +* prresult: to stored the value of the addr +* +* \return +* the error of the reading operation +*/ +/*----------------------------------------------------------------------------*/ + +u_int8_t halReadN9RegisterByMailBox(IN struct ADAPTER *prAdapter, IN uint32_t addr, IN uint32_t *prresult) +{ + uint32_t ori_whlpcr, temp, counter = 0; + u_int8_t err = TRUE, stop = FALSE; + + /* use polling mode */ + HAL_MCR_RD(prAdapter, MCR_WHLPCR, &ori_whlpcr); /* backup the original setting of W_INT_EN */ + ori_whlpcr &= WHLPCR_INT_EN_SET; + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_INT_EN_CLR); /* disabel interrupt */ + + /* progrqm h2d mailbox0 as interested register address */ + HAL_MCR_WR(prAdapter, MCR_H2DSM0R, addr); + + /* set h2d interrupt to notify firmware (bit16) */ + HAL_MCR_WR(prAdapter, MCR_WSICR, SDIO_MAILBOX_FUNC_READ_REG_IDX); + + /* polling interrupt status for the returned result */ + while (!stop) { + HAL_MCR_RD(prAdapter, MCR_WHISR, &temp); /* read clear mode */ + if (temp & SDIO_MAILBOX_FUNC_READ_REG_IDX) { + /* get the result */ + + /* read d2h mailbox0 for interested register address */ + HAL_MCR_RD(prAdapter, MCR_D2HRM0R, &temp); + if (temp == addr) { + /* read d2h mailbox1 for the value of the register */ + HAL_MCR_RD(prAdapter, MCR_D2HRM1R, prresult); + err = FALSE; + } else { + DBGLOG(HAL, ERROR, "halReadN9RegisterByMailBox >> interested address is not correct.\n"); + } + stop = TRUE; + } else { +counter++; + +if (counter > 300000) { + DBGLOG(HAL, ERROR, "halReadN9RegisterByMailBox >> get response failure.\n"); + ASSERT(0); + break; + } + } + } + + HAL_MCR_WR(prAdapter, MCR_WHLPCR, ori_whlpcr); /* restore the W_INT_EN */ + + return err; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* This routine is used to write the value of N9 register by SDIO SW interrupt and mailbox. +* +* \param[in] +* pvAdapter: Pointer to the Adapter structure. +* addr: the interested address to be write +* value: the value to write into the addr +* +* \return +* the error of the write operation +*/ +/*----------------------------------------------------------------------------*/ + +u_int8_t halWriteN9RegisterByMailBox(IN struct ADAPTER *prAdapter, IN uint32_t addr, IN uint32_t value) +{ + uint32_t ori_whlpcr, temp, counter = 0; + u_int8_t err = TRUE, stop = FALSE; + + /* use polling mode */ + HAL_MCR_RD(prAdapter, MCR_WHLPCR, &ori_whlpcr); /* backup the original setting of W_INT_EN */ + ori_whlpcr &= WHLPCR_INT_EN_SET; + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_INT_EN_CLR); /* disabel interrupt */ + + /* progrqm h2d mailbox0 as interested register address */ + HAL_MCR_WR(prAdapter, MCR_H2DSM0R, addr); + + /* progrqm h2d mailbox1 as the value to write */ + HAL_MCR_WR(prAdapter, MCR_H2DSM1R, value); + + /* set h2d interrupt to notify firmware (bit17) */ + HAL_MCR_WR(prAdapter, MCR_WSICR, SDIO_MAILBOX_FUNC_WRITE_REG_IDX); + + /* polling interrupt status for the returned result */ + while (!stop) { + HAL_MCR_RD(prAdapter, MCR_WHISR, &temp); /* read clear mode */ + + if (temp & SDIO_MAILBOX_FUNC_WRITE_REG_IDX) { + /* get the result */ + + /* read d2h mailbox0 for interested register address */ + HAL_MCR_RD(prAdapter, MCR_D2HRM0R, &temp); + if (temp == addr) + err = FALSE; + else { + DBGLOG(HAL, ERROR, "halWriteN9RegisterByMailBox >> "); + DBGLOG(HAL, ERROR, "interested address is not correct.\n"); + } + stop = TRUE; + } else { + counter++; + +if (counter > 300000) { + DBGLOG(HAL, ERROR, "halWriteN9RegisterByMailBox >> get response failure.\n"); + ASSERT(0); + break; + } + } + } + + HAL_MCR_WR(prAdapter, MCR_WHLPCR, ori_whlpcr); /* restore the W_INT_EN */ + + return err; +} +#endif + +u_int8_t halIsPendingRx(IN struct ADAPTER *prAdapter) +{ + return FALSE; +} + +uint32_t halGetValidCoalescingBufSize(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo; + uint32_t u4BufSize; +#if (MTK_WCN_HIF_SDIO == 0) + struct sdio_func *prSdioFunc; + uint32_t u4RuntimeMaxBuf; + +#endif + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + if (HIF_TX_COALESCING_BUFFER_SIZE > HIF_RX_COALESCING_BUFFER_SIZE) + u4BufSize = HIF_TX_COALESCING_BUFFER_SIZE; + else + u4BufSize = HIF_RX_COALESCING_BUFFER_SIZE; + +#if (MTK_WCN_HIF_SDIO == 0) + prSdioFunc = prHifInfo->func; + + /* Check host capability */ + /* 1. Should less than host-max_req_size */ + if (u4BufSize > prSdioFunc->card->host->max_req_size) + u4BufSize = prSdioFunc->card->host->max_req_size; + + /* 2. Should less than runtime-blksize * host-blk_count */ + u4RuntimeMaxBuf = prSdioFunc->cur_blksize * + prSdioFunc->card->host->max_blk_count; + if (u4BufSize > u4RuntimeMaxBuf) + u4BufSize = u4RuntimeMaxBuf; + + DBGLOG(INIT, TRACE, "\n" + "Final buf : 0x%X\n" + "Default TX buf : 0x%X\n" + "Default RX buf : 0x%X\n" + "Host caps -\n" + "max_req_size : 0x%X\n" + "max_seg_size : 0x%X\n" + "max_segs : 0x%X\n" + "max_blk_size : 0x%X\n" + "max_blk_count : 0x%X\n" + "Runtime -\n" + "cur_blksize : 0x%X\n", + u4BufSize, + HIF_TX_COALESCING_BUFFER_SIZE, + HIF_RX_COALESCING_BUFFER_SIZE, + prSdioFunc->card->host->max_req_size, + prSdioFunc->card->host->max_seg_size, + prSdioFunc->card->host->max_segs, + prSdioFunc->card->host->max_blk_size, + prSdioFunc->card->host->max_blk_count, + prSdioFunc->cur_blksize); +#endif + + return u4BufSize; +} + +uint32_t halAllocateIOBuffer(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo; + uint8_t ucIdx; + struct SDIO_RX_COALESCING_BUF *prRxBuf; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + /* 4 <5> Memory for enhanced interrupt response */ +#ifdef CFG_PREALLOC_MEMORY + prHifInfo->prSDIOCtrl = (struct ENHANCE_MODE_DATA_STRUCT *) + preallocGetMem(MEM_ID_IO_CTRL); +#else + prHifInfo->prSDIOCtrl = (struct ENHANCE_MODE_DATA_STRUCT *) + kalAllocateIOBuffer(sizeof(struct ENHANCE_MODE_DATA_STRUCT)); +#endif + if (prHifInfo->prSDIOCtrl == NULL) { + DBGLOG(HAL, ERROR, + "Could not allocate %d bytes for interrupt response.\n", + sizeof(struct ENHANCE_MODE_DATA_STRUCT)); + + return WLAN_STATUS_RESOURCES; + } + + /* Alloc coalescing buffer */ + for (ucIdx = 0; ucIdx < HIF_RX_COALESCING_BUF_COUNT; ucIdx++) { + prRxBuf = &prHifInfo->rRxCoalesingBuf[ucIdx]; + + prRxBuf->u4PktCount = 0; + + prRxBuf->u4BufSize = HIF_RX_COALESCING_BUFFER_SIZE; +#ifdef CFG_PREALLOC_MEMORY + prRxBuf->pvRxCoalescingBuf = preallocGetMem(MEM_ID_RX_DATA); +#else + prRxBuf->pvRxCoalescingBuf = kalAllocateIOBuffer(prRxBuf->u4BufSize); +#endif + if (!prRxBuf->pvRxCoalescingBuf) { + DBGLOG(HAL, ERROR, "Rx coalescing alloc failed!\n"); + continue; + } + + QUEUE_INSERT_TAIL(&prHifInfo->rRxFreeBufQueue, &prRxBuf->rQueEntry); + } + + return WLAN_STATUS_SUCCESS; +} + +uint32_t halReleaseIOBuffer(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo; + uint8_t ucIdx; + struct SDIO_RX_COALESCING_BUF *prRxBuf; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + /* Release coalescing buffer */ + for (ucIdx = 0; ucIdx < HIF_RX_COALESCING_BUF_COUNT; ucIdx++) { + prRxBuf = &prHifInfo->rRxCoalesingBuf[ucIdx]; +#ifndef CFG_PREALLOC_MEMORY + kalReleaseIOBuffer(prRxBuf->pvRxCoalescingBuf, prRxBuf->u4BufSize); +#endif + prRxBuf->pvRxCoalescingBuf = NULL; + } + + /* 4 <5> Memory for enhanced interrupt response */ + if (prHifInfo->prSDIOCtrl) { +#ifndef CFG_PREALLOC_MEMORY + kalReleaseIOBuffer((void *) prHifInfo->prSDIOCtrl, sizeof(struct ENHANCE_MODE_DATA_STRUCT)); +#endif + prHifInfo->prSDIOCtrl = (struct ENHANCE_MODE_DATA_STRUCT *) NULL; + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief dump firmware Assert message +* +* \param[in] +* prAdapter +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +void halPrintFirmwareAssertInfo(IN struct ADAPTER *prAdapter) +{ + uint32_t u4MailBox0, u4MailBox1; + uint32_t line = 0; + uint8_t aucAssertFile[7]; + /* UINT_32 u4ChipId; */ + +#if CFG_SDIO_INTR_ENHANCE + u4MailBox0 = prAdapter->prGlueInfo->rHifInfo.prSDIOCtrl->u4RcvMailbox0; + u4MailBox1 = prAdapter->prGlueInfo->rHifInfo.prSDIOCtrl->u4RcvMailbox1; +#else + halGetMailbox(prAdapter, 0, &u4MailBox0); + halGetMailbox(prAdapter, 1, &u4MailBox1); +#endif + + line = u4MailBox0 & 0x0000FFFF; + + u4MailBox0 = ((u4MailBox0 >> 16) & 0x0000FFFF); + + kalMemCopy(&aucAssertFile[0], &u4MailBox0, 2); + kalMemCopy(&aucAssertFile[2], &u4MailBox1, 4); + + aucAssertFile[6] = '\0'; + + LOG_FUNC("[%s][wifi][Firmware] Assert at \"%s\" #%u\n\n", + NIC_NAME, aucAssertFile, line); + +} + +void halPrintMailbox(IN struct ADAPTER *prAdapter) +{ + uint32_t u4MailBoxStatus0, u4MailBoxStatus1; + uint8_t fgResult; + + HAL_LP_OWN_RD(prAdapter, &fgResult); + if (fgResult != TRUE) + return; + + halGetMailbox(prAdapter, 0, &u4MailBoxStatus0); + halGetMailbox(prAdapter, 1, &u4MailBoxStatus1); + DBGFWLOG(INIT, ERROR, "MailBox Status = 0x%08X, 0x%08X\n", u4MailBoxStatus0, u4MailBoxStatus1); +} + +void halPrintIntStatus(IN struct ADAPTER *prAdapter) +{ +#if CFG_SDIO_INTR_ENHANCE + struct ENHANCE_MODE_DATA_STRUCT *prSDIOCtrl; + + prSDIOCtrl = prAdapter->prGlueInfo->rHifInfo.prSDIOCtrl; + ASSERT(prSDIOCtrl); + + DBGLOG_MEM32(REQ, WARN, prSDIOCtrl, sizeof(struct ENHANCE_MODE_DATA_STRUCT)); +#else + uint32_t u4IntStatus; + + HAL_MCR_RD(prAdapter, MCR_WHISR, u4IntStatus); + + DBGLOG(REQ, WARN, "INT status[0x%08x]\n", u4IntStatus); +#endif /* CFG_SDIO_INTR_ENHANCE */ +} + +void halDumpIntLog(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + struct SDIO_INT_LOG_T *prIntLog; + struct ENHANCE_MODE_DATA_STRUCT *prIntSts; + uint32_t u4Idx; + + for (u4Idx = 0; u4Idx < CFG_SDIO_INT_LOG_CNT; u4Idx++) { + prIntLog = &prHifInfo->arIntLog[u4Idx]; + prIntSts = (struct ENHANCE_MODE_DATA_STRUCT *)&prIntLog->aucIntSts[0]; + + DBGLOG(INTR, ERROR, "INT IDX[%u] STS[0x%08x] FG[0x%08x] Rx Pkt[%u] Sts0/1[%u:%u]\n", + prIntLog->u4Idx, prIntSts->u4WHISR, prIntLog->u4Flag, prIntLog->ucRxPktCnt, + prIntSts->rRxInfo.u.u2NumValidRx0Len, prIntSts->rRxInfo.u.u2NumValidRx1Len); + DBGLOG_MEM32(INTR, ERROR, &prIntLog->au2RxPktLen[0], sizeof(uint16_t) * HIF_RX_MAX_AGG_NUM); + DBGLOG_MEM32(INTR, ERROR, &prIntLog->au4RxPktInfo[0], sizeof(uint32_t) * HIF_RX_MAX_AGG_NUM); + DBGLOG_MEM32(INTR, ERROR, prIntSts, sizeof(struct ENHANCE_MODE_DATA_STRUCT)); + } + + DBGLOG(INTR, ERROR, "---------------------------------\n"); +} + +void halTagIntLog(IN struct ADAPTER *prAdapter, IN enum HIF_SDIO_INT_STS eTag) +{ + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + prHifInfo->arIntLog[prHifInfo->ucIntLogEntry].u4Flag |= BIT(eTag); +} + +void halRecIntLog(IN struct ADAPTER *prAdapter, IN struct ENHANCE_MODE_DATA_STRUCT *prSDIOCtrl) +{ + struct SDIO_INT_LOG_T *prIntLog; + uint8_t ucLogEntry; + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + prHifInfo->u4IntLogIdx++; + ucLogEntry = prHifInfo->u4IntLogIdx % CFG_SDIO_INT_LOG_CNT; + prIntLog = &prHifInfo->arIntLog[ucLogEntry]; + kalMemZero(prIntLog, sizeof(struct SDIO_INT_LOG_T)); + + prIntLog->u4Idx = prHifInfo->u4IntLogIdx; + prHifInfo->ucIntLogEntry = ucLogEntry; + kalMemCopy(&prIntLog->aucIntSts[0], prSDIOCtrl, sizeof(struct ENHANCE_MODE_DATA_STRUCT)); +} + +struct SDIO_INT_LOG_T *halGetIntLog(IN struct ADAPTER *prAdapter, IN uint32_t u4Idx) +{ + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + return &prHifInfo->arIntLog[u4Idx % CFG_SDIO_INT_LOG_CNT]; +} + +void halProcessAbnormalInterrupt(IN struct ADAPTER *prAdapter) +{ + uint32_t u4Data = 0; + uint8_t fgResult; + + /* dump abnormal status */ + + /* Need driver own */ + HAL_LP_OWN_RD(prAdapter, &fgResult); + if (fgResult == TRUE) + HAL_MCR_RD(prAdapter, MCR_WASR, &u4Data); + + halPollDbgCr(prAdapter, 5); + + halPrintIntStatus(prAdapter); + + if (u4Data) { + DBGLOG(REQ, WARN, "SDIO Abnormal: WASR = 0x%x!\n", + u4Data); + } + + if (u4Data & (WASR_RX0_UNDER_FLOW | WASR_RX1_UNDER_FLOW)) { + DBGLOG(REQ, ERROR, + "Skip all SDIO Rx due to Rx underflow error!\n"); + prAdapter->prGlueInfo->rHifInfo.fgSkipRx = TRUE; + halDumpHifStatus(prAdapter, NULL, 0); + GL_RESET_TRIGGER(prAdapter, RST_FLAG_DO_CORE_DUMP); + } + + halDumpIntLog(prAdapter); +} + +void halProcessSoftwareInterrupt(IN struct ADAPTER *prAdapter) +{ + uint32_t u4IntrBits; + + ASSERT(prAdapter); + + u4IntrBits = prAdapter->u4IntStatus & BITS(8, 31); + + if ((u4IntrBits & WHISR_D2H_SW_ASSERT_INFO_INT) != 0) { + halPrintFirmwareAssertInfo(prAdapter); +#if CFG_CHIP_RESET_SUPPORT + glSendResetRequest(); +#endif + } + + if (u4IntrBits & WHISR_D2H_WKUP_BY_RX_PACKET) + DBGLOG(RX, INFO, "Wake up by Rx\n"); + + if (u4IntrBits & WHISR_D2H_SW_RD_MAILBOX_INT) + halPrintMailbox(prAdapter); + + if (u4IntrBits & SER_SDIO_N9_HOST_STOP_TX_OP) { + halPrintMailbox(prAdapter); + /* Stop HIF Tx operation */ + nicSerStopTx(prAdapter); + } + + if (u4IntrBits & SER_SDIO_N9_HOST_STOP_TX_RX_OP) { + DBGLOG(INIT, WARN, "[SER][L1] fw notify host L1 start\n"); + halPrintMailbox(prAdapter); + /* Stop HIF Tx/Rx operation */ + nicSerStopTxRx(prAdapter); + } + + if (u4IntrBits & SER_SDIO_N9_HOST_RECOVERY_DONE) + DBGLOG(INIT, WARN, "[SER][L1] fw L1 rst done\n"); + + if ((u4IntrBits & ~WHISR_D2H_WKUP_BY_RX_PACKET) != 0) + DBGLOG(SW4, WARN, "u4IntrBits: 0x%08x\n", u4IntrBits); + +} /* end of halProcessSoftwareInterrupt() */ + +void halPutMailbox(IN struct ADAPTER *prAdapter, IN uint32_t u4MailboxNum, IN uint32_t u4Data) +{ + + switch (u4MailboxNum) { + case 0: + HAL_MCR_WR(prAdapter, MCR_H2DSM0R, u4Data); + break; + case 1: + HAL_MCR_WR(prAdapter, MCR_H2DSM1R, u4Data); + break; + + default: + ASSERT(0); + } + +} + +void halGetMailbox(IN struct ADAPTER *prAdapter, IN uint32_t u4MailboxNum, OUT uint32_t *pu4Data) +{ + switch (u4MailboxNum) { + case 0: + HAL_MCR_RD(prAdapter, MCR_D2HRM0R, pu4Data); + break; + case 1: + HAL_MCR_RD(prAdapter, MCR_D2HRM1R, pu4Data); + break; + + default: + ASSERT(0); + } +} + +u_int8_t halDeAggErrorCheck(struct ADAPTER *prAdapter, + struct SDIO_RX_COALESCING_BUF *prRxBuf, + uint8_t *pucPktAddr) +{ + struct mt66xx_chip_info *prChipInfo; + uint16_t u2PktLength; + uint8_t *pucRxBufEnd; + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + pucRxBufEnd = (uint8_t *)prRxBuf->pvRxCoalescingBuf + prRxBuf->u4PktTotalLength; + + u2PktLength = HAL_RX_STATUS_GET_RX_BYTE_CNT((struct HW_MAC_RX_DESC *)pucPktAddr); + + /* Rx buffer boundary check */ + if ((pucPktAddr + ALIGN_4(u2PktLength + HIF_RX_HW_APPENDED_LEN)) >= pucRxBufEnd) + return TRUE; + + /* Rx packet min length check */ + if (u2PktLength <= prChipInfo->rxd_size) + return TRUE; + + /* Rx packet max length check */ + if (u2PktLength >= CFG_RX_MAX_PKT_SIZE) + return TRUE; + + return FALSE; +} + +void halDeAggRxPktProc(struct ADAPTER *prAdapter, + struct SDIO_RX_COALESCING_BUF *prRxBuf) +{ + struct GL_HIF_INFO *prHifInfo; + uint32_t i; + struct QUE rTempFreeRfbList, rTempRxRfbList; + struct QUE *prTempFreeRfbList = &rTempFreeRfbList; + struct QUE *prTempRxRfbList = &rTempRxRfbList; + struct RX_CTRL *prRxCtrl; + struct SW_RFB *prSwRfb = (struct SW_RFB *) NULL; + uint8_t *pucSrcAddr; + uint16_t u2PktLength; + u_int8_t fgReschedule = FALSE; +#if CFG_TCP_IP_CHKSUM_OFFLOAD + uint32_t *pu4HwAppendDW; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + u_int8_t fgDeAggErr = FALSE; + struct SDIO_INT_LOG_T *prIntLog; + uint64_t u8Current = 0; + + KAL_SPIN_LOCK_DECLARATION(); + SDIO_TIME_INTERVAL_DEC(); + + prRxCtrl = &prAdapter->rRxCtrl; + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + QUEUE_INITIALIZE(prTempFreeRfbList); + QUEUE_INITIALIZE(prTempRxRfbList); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + if (prRxCtrl->rFreeSwRfbList.u4NumElem < prRxBuf->u4PktCount) { + fgReschedule = TRUE; + } else { + /* Get enough free SW_RFB to be Rx */ + for (i = 0; i < prRxBuf->u4PktCount; i++) { + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, + prSwRfb, struct SW_RFB *); + + QUEUE_INSERT_TAIL(prTempFreeRfbList, + &prSwRfb->rQueEntry); + } + fgReschedule = FALSE; + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + if (fgReschedule) { + mutex_lock(&prHifInfo->rRxDeAggQueMutex); + + QUEUE_INSERT_HEAD(&prHifInfo->rRxDeAggQueue, + (struct QUE_ENTRY *)prRxBuf); + + mutex_unlock(&prHifInfo->rRxDeAggQueMutex); + + /* Reschedule this work */ + if ((prAdapter->prGlueInfo->ulFlag & GLUE_FLAG_HALT) == 0) + schedule_delayed_work( + &prAdapter->prGlueInfo->rRxPktDeAggWork, 0); + + return; + } + + pucSrcAddr = prRxBuf->pvRxCoalescingBuf; + fgDeAggErr = FALSE; + + prIntLog = halGetIntLog(prAdapter, prRxBuf->u4IntLogIdx); + u8Current = sched_clock(); + + SDIO_REC_TIME_START(); + for (i = 0; i < prRxBuf->u4PktCount; i++) { + /* Rx de-aggregation check */ + if (halDeAggErrorCheck(prAdapter, prRxBuf, pucSrcAddr)) { + fgDeAggErr = TRUE; + break; + } + + u2PktLength = + HAL_RX_STATUS_GET_RX_BYTE_CNT( + (struct HW_MAC_RX_DESC *)pucSrcAddr); + + prIntLog->au2RxPktLen[i] = u2PktLength; + + QUEUE_REMOVE_HEAD(prTempFreeRfbList, + prSwRfb, struct SW_RFB *); + + kalMemCopy(prSwRfb->pucRecvBuff, pucSrcAddr, + ALIGN_4(u2PktLength + HIF_RX_HW_APPENDED_LEN)); + + prSwRfb->ucPacketType = + (uint8_t)HAL_RX_STATUS_GET_PKT_TYPE(prSwRfb->prRxStatus); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + pu4HwAppendDW = (uint32_t *) prSwRfb->prRxStatus; + pu4HwAppendDW += + (ALIGN_4(prSwRfb->prRxStatus->u2RxByteCount) >> 2); + prSwRfb->u4TcpUdpIpCksStatus = *pu4HwAppendDW; + DBGLOG(RX, TRACE, + "u4TcpUdpIpCksStatus[0x%02x]\n", + prSwRfb->u4TcpUdpIpCksStatus); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + kalMemCopy(&prIntLog->au4RxPktInfo[i], + pucSrcAddr + ALIGN_4(u2PktLength), sizeof(uint32_t)); + + GLUE_RX_SET_PKT_INT_TIME(prSwRfb->pvPacket, + prAdapter->prGlueInfo->u8HifIntTime); + + GLUE_RX_SET_PKT_RX_TIME(prSwRfb->pvPacket, u8Current); + + QUEUE_INSERT_TAIL(prTempRxRfbList, &prSwRfb->rQueEntry); + + pucSrcAddr += ALIGN_4(u2PktLength + HIF_RX_HW_APPENDED_LEN); + } + SDIO_REC_TIME_END(); + SDIO_ADD_TIME_INTERVAL(prHifInfo->rStatCounter.u4RxDataCpTime); + + prIntLog->ucRxPktCnt = i; + + if (fgDeAggErr) { + /* Rx de-aggregation error */ + /* Dump current Rx buffer */ + DBGLOG(RX, ERROR, + "Rx de-aggregation error!, INT sts: total len[%u] pkt cnt[%u]\n", + prRxBuf->u4PktTotalLength, prRxBuf->u4PktCount); +#if 0 + /* Sometimes the larger frame is received, and dump + * those message will let platform stop application. + */ + DBGLOG_MEM32(RX, ERROR, + prRxBuf->pvRxCoalescingBuf, + prRxBuf->u4PktTotalLength); + + halDumpIntLog(prAdapter); +#endif + + /* Free all de-aggregated SwRfb */ + QUEUE_CONCATENATE_QUEUES(prTempFreeRfbList, prTempRxRfbList); + } else { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + RX_ADD_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT, + prTempRxRfbList->u4NumElem); + + QUEUE_CONCATENATE_QUEUES(&prRxCtrl->rReceivedRfbList, + prTempRxRfbList); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + /* Wake up Rx handling thread */ + set_bit(GLUE_FLAG_RX_BIT, &(prAdapter->prGlueInfo->ulFlag)); + wake_up_interruptible(&(prAdapter->prGlueInfo->waitq)); + } + + if (prTempFreeRfbList->u4NumElem) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_CONCATENATE_QUEUES(&prRxCtrl->rFreeSwRfbList, + prTempFreeRfbList); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + } + + prRxBuf->u4PktCount = 0; + mutex_lock(&prHifInfo->rRxFreeBufQueMutex); + QUEUE_INSERT_TAIL(&prHifInfo->rRxFreeBufQueue, + (struct QUE_ENTRY *)prRxBuf); + mutex_unlock(&prHifInfo->rRxFreeBufQueMutex); +} + + +void halDeAggRxPktWorker(struct work_struct *work) +{ + struct GLUE_INFO *prGlueInfo; + struct GL_HIF_INFO *prHifInfo; + struct ADAPTER *prAdapter; + struct SDIO_RX_COALESCING_BUF *prRxBuf; + struct RX_CTRL *prRxCtrl; + + if (g_u4HaltFlag) + return; + + prGlueInfo = ENTRY_OF(work, struct GLUE_INFO, rRxPktDeAggWork); + prHifInfo = &prGlueInfo->rHifInfo; + prAdapter = prGlueInfo->prAdapter; + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) + return; + + prRxCtrl = &prAdapter->rRxCtrl; + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + mutex_lock(&prHifInfo->rRxDeAggQueMutex); + + QUEUE_REMOVE_HEAD(&prHifInfo->rRxDeAggQueue, + prRxBuf, struct SDIO_RX_COALESCING_BUF *); + + mutex_unlock(&prHifInfo->rRxDeAggQueMutex); + while (prRxBuf) { + halDeAggRxPktProc(prAdapter, prRxBuf); + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) + return; + + mutex_lock(&prHifInfo->rRxDeAggQueMutex); + QUEUE_REMOVE_HEAD(&prHifInfo->rRxDeAggQueue, prRxBuf, struct SDIO_RX_COALESCING_BUF *); + mutex_unlock(&prHifInfo->rRxDeAggQueMutex); + } +} + +void halDeAggRxPkt(struct ADAPTER *prAdapter, struct SDIO_RX_COALESCING_BUF *prRxBuf) +{ + struct GL_HIF_INFO *prHifInfo; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + /* Avoid to schedule DeAggWorker during uninit flow */ + if (prAdapter->prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + mutex_lock(&prHifInfo->rRxFreeBufQueMutex); + QUEUE_INSERT_TAIL(&prHifInfo->rRxFreeBufQueue, (struct QUE_ENTRY *)prRxBuf); + mutex_unlock(&prHifInfo->rRxFreeBufQueMutex); + + return; + } + +#if CFG_SDIO_RX_AGG_WORKQUE + mutex_lock(&prHifInfo->rRxDeAggQueMutex); + QUEUE_INSERT_TAIL(&prHifInfo->rRxDeAggQueue, (struct QUE_ENTRY *)prRxBuf); + mutex_unlock(&prHifInfo->rRxDeAggQueMutex); + + schedule_delayed_work(&prAdapter->prGlueInfo->rRxPktDeAggWork, 0); +#else + halDeAggRxPktProc(prAdapter, prRxBuf); +#endif +} + +void halRxTasklet(unsigned long data) +{ + +} + +void halTxCompleteTasklet(unsigned long data) +{ + +} + +/* Hif power off wifi */ +uint32_t halHifPowerOffWifi(IN struct ADAPTER *prAdapter) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + if (prAdapter->rAcpiState == ACPI_STATE_D0 && + !wlanIsChipNoAck(prAdapter) && !kalIsCardRemoved(prAdapter->prGlueInfo)) { + /* 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) { + uint32_t i; + /* 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 */ + rStatus = wlanCheckWifiFunc(prAdapter, FALSE); + } +#if !CFG_ENABLE_FULL_PM + /* 4. Set Onwership to F/W */ + nicpmSetFWOwn(prAdapter, FALSE); +#endif + +#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); + } + return rStatus; +} + +void halPollDbgCr(IN struct ADAPTER *prAdapter, IN uint32_t u4LoopCount) +{ + uint32_t au4Value[] = {MCR_WCIR, MCR_WHLPCR, MCR_D2HRM2R}; + uint32_t au4Value1[] = {MCR_WHIER, MCR_D2HRM0R, MCR_D2HRM1R}; + uint32_t u4Loop = 0; + uint32_t u4Data = 0; + uint8_t i = 0, fgResult; +#if MTK_WCN_HIF_SDIO + uint8_t *pucCCR = (uint8_t *)&au4Value[0]; + unsigned long cltCtx = prAdapter->prGlueInfo->rHifInfo.cltCtx; +#endif + for (; i < sizeof(au4Value)/sizeof(uint32_t); i++) + HAL_MCR_RD(prAdapter, au4Value[i], &au4Value[i]); + + DBGLOG(REQ, WARN, "MCR_WCIR:0x%x, MCR_WHLPCR:0x%x, MCR_D2HRM2R:0x%x\n", + au4Value[0], au4Value[1], au4Value[2]); + + /* Need driver own */ + HAL_LP_OWN_RD(prAdapter, &fgResult); + if (fgResult == TRUE) { + /* dump N9 programming counter */ + for (u4Loop = 0; u4Loop < u4LoopCount; u4Loop++) { + HAL_MCR_RD(prAdapter, MCR_SWPCDBGR, &u4Data); + DBGLOG(INIT, WARN, "SWPCDBGR 0x%08X\n", u4Data); + } + + /* dump others */ + for (i = 0; i < sizeof(au4Value1)/sizeof(uint32_t); i++) + HAL_MCR_RD(prAdapter, au4Value1[i], &au4Value1[i]); + + DBGLOG(REQ, WARN, "MCR_WHIER:0x%x, MCR_D2HRM0R:0x%x", + au4Value1[0], au4Value1[1]); + DBGLOG(REQ, WARN, "MCR_D2HRM1R:0x%x\n", + au4Value1[2]); + } + +#if MTK_WCN_HIF_SDIO + for (i = 0; i < 8; i++) + mtk_wcn_hif_sdio_f0_readb(cltCtx, 0xf8 + i, &pucCCR[i]); + DBGLOG(REQ, WARN, "CCCR %02x %02x %02x %02x %02x %02x %02x %02x\n", + pucCCR[0], pucCCR[1], pucCCR[2], pucCCR[3], pucCCR[4], pucCCR[5], pucCCR[6], pucCCR[7]); +#endif +} + +void halSerHifReset(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + /* Restore Tx resource */ + halRestoreTxResource(prAdapter); + + /* Clear interrupt status from Rx interrupt enhance mode */ + prHifInfo->fgIsPendingInt = FALSE; + kalMemZero(prHifInfo->prSDIOCtrl, sizeof(struct ENHANCE_MODE_DATA_STRUCT)); +} + +u_int8_t halIsPendingTxDone(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + uint32_t i; + u_int8_t fgIsPendingTxDone = FALSE; + + for (i = TC0_INDEX; i <= TC4_INDEX; i++) { + if (prHifInfo->au4PendingTxDoneCount[i]) { + fgIsPendingTxDone = TRUE; + break; + } + } + + if (fgIsPendingTxDone) + DBGLOG(NIC, ERROR, "Missing Tx done[%u:%u:%u:%u:%u]\n", + prHifInfo->au4PendingTxDoneCount[TC0_INDEX], + prHifInfo->au4PendingTxDoneCount[TC1_INDEX], + prHifInfo->au4PendingTxDoneCount[TC2_INDEX], + prHifInfo->au4PendingTxDoneCount[TC3_INDEX], + prHifInfo->au4PendingTxDoneCount[TC4_INDEX]); + + return fgIsPendingTxDone; +} + +void halPrintHifDbgInfo(IN struct ADAPTER *prAdapter) +{ + if (prAdapter->u4HifDbgFlag & DEG_HIF_ALL || + prAdapter->u4HifDbgFlag & DEG_HIF_DEFAULT_DUMP) { + halPrintMailbox(prAdapter); + halPollDbgCr(prAdapter, LP_DBGCR_POLL_ROUND); + } + prAdapter->u4HifDbgFlag = 0; +} + +u_int8_t halIsTxResourceControlEn(IN struct ADAPTER *prAdapter) +{ + return TRUE; +} + +void halTxResourceResetHwTQCounter(IN struct ADAPTER *prAdapter) +{ + uint32_t *pu4WHISR = NULL; + uint16_t au2TxCount[16]; + + pu4WHISR = (uint32_t *)kalMemAlloc(sizeof(uint32_t), PHY_MEM_TYPE); + if (!pu4WHISR) { + DBGLOG(INIT, ERROR, "Allocate pu4WHISR fail\n"); + return; + } + + HAL_READ_INTR_STATUS(prAdapter, sizeof(uint32_t), (uint8_t *)pu4WHISR); + if (HAL_IS_TX_DONE_INTR(*pu4WHISR)) + HAL_READ_TX_RELEASED_COUNT(prAdapter, au2TxCount); + + if (pu4WHISR) + kalMemFree(pu4WHISR, PHY_MEM_TYPE, sizeof(uint32_t)); +} + +uint32_t halGetHifTxPageSize(IN struct ADAPTER *prAdapter) +{ + if (!prAdapter->chip_info->is_support_cr4) { + if (prAdapter->fgIsNicTxReousrceValid) + return prAdapter->nicTxReousrce.u4DataResourceUnit; + else + return HIF_TX_PAGE_SIZE_STORED_FORWARD; + } + + /*cr4 mode*/ + return HIF_TX_PAGE_SIZE; +} +/*----------------------------------------------------------------------------*/ +/*! +* @brief Generic update Tx done counter +* +* @param prAdapter Pointer to the Adapter structure. +* @param au2TxDoneCnt Pointer to the final reference table +* @param au2TxRlsCnt Pointer to the Tx done counter result got fom interrupt +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ + +void halTxGetFreeResource(IN struct ADAPTER *prAdapter, IN uint16_t *au2TxDoneCnt, IN uint16_t *au2TxRlsCnt) +{ + uint8_t i; + struct BUS_INFO *prBusInfo = prAdapter->chip_info->bus_info; + + if (prBusInfo->halTxGetFreeResource) + return prBusInfo->halTxGetFreeResource(prAdapter, au2TxDoneCnt, au2TxRlsCnt); + + /* 6632, 7668 ways */ + for (i = HIF_TX_AC0_INDEX; i <= HIF_TX_AC23_INDEX; i++) + au2TxDoneCnt[i % WMM_AC_INDEX_NUM] += au2TxRlsCnt[i]; + au2TxDoneCnt[HIF_TX_CPU_INDEX] = au2TxRlsCnt[HIF_TX_CPU_INDEX]; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Update Tx done counter for mt7663 +* +* @param prAdapter Pointer to the Adapter structure. +* @param au2TxDoneCnt Pointer to the final reference table +* @param au2TxRlsCnt Pointer to the Tx done counter result got fom interrupt +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ + +void halTxGetFreeResource_v1(IN struct ADAPTER *prAdapter, IN uint16_t *au2TxDoneCnt, IN uint16_t *au2TxRlsCnt) +{ + uint8_t i; + + for (i = HIF_TXC_IDX_0; i < HIF_TXC_IDX_NUM; i++) + au2TxDoneCnt[i] = au2TxRlsCnt[i]; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Generic return free resource to TCs +* +* @param prAdapter Pointer to the Adapter structure. +* @param au2TxDoneCnt Pointer to the final reference table +* @param au2TxRlsCnt Pointer to the Tx done counter result got fom interrupt +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ + +void halTxReturnFreeResource(IN struct ADAPTER *prAdapter, IN uint16_t *au2TxDoneCnt) +{ + uint8_t i; + struct BUS_INFO *prBusInfo = prAdapter->chip_info->bus_info; + uint16_t u2ReturnCnt; + + KAL_SPIN_LOCK_DECLARATION(); + + + if (prBusInfo->halTxReturnFreeResource) + prBusInfo->halTxReturnFreeResource(prAdapter, au2TxDoneCnt); + else { + /* 6632, 7668 ways */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + for (i = TC0_INDEX; i < TC_NUM; i++) { + u2ReturnCnt = au2TxDoneCnt[nicTxGetTxQByTc(prAdapter, i)]; + nicTxReleaseResource_PSE(prAdapter, i, u2ReturnCnt, FALSE); + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[i] -= u2ReturnCnt; + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Return free resource to TCs for mt7663 +* +* @param prAdapter Pointer to the Adapter structure. +* @param au2TxDoneCnt Pointer to the final reference table +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void halTxReturnFreeResource_v1(IN struct ADAPTER *prAdapter, IN uint16_t *au2TxDoneCnt) +{ + uint8_t i; + uint16_t u2ReturnCnt; + + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + /* WMM 1 */ + for (i = HIF_TXC_IDX_0; i <= HIF_TXC_IDX_8; i++) { + uint8_t ucTc; + + u2ReturnCnt = au2TxDoneCnt[i]; + + if (i < HIF_TXC_IDX_5) { + ucTc = HIF_TXC_IDX_2_TC_IDX_PSE(i); + nicTxReleaseResource_PSE(prAdapter, ucTc, u2ReturnCnt, FALSE); + } else { + ucTc = HIF_TXC_IDX_2_TC_IDX_PLE(i); + nicTxReleaseResource_PLE(prAdapter, ucTc, u2ReturnCnt, FALSE); + } + + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[i] -= u2ReturnCnt; + } + + /* WMM 2,3 */ + /*TBD*/ + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Generic rollback resource to TCs +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ + +void halRestoreTxResource(IN struct ADAPTER *prAdapter) +{ + uint8_t i; + struct BUS_INFO *prBusInfo = prAdapter->chip_info->bus_info; + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + if (prBusInfo->halRestoreTxResource) + prBusInfo->halRestoreTxResource(prAdapter); + else { + /* 6632, 7668 ways */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + for (i = TC0_INDEX; i < TC_NUM; i++) { + nicTxReleaseResource_PSE(prAdapter, i, prHifInfo->au4PendingTxDoneCount[i], FALSE); + prHifInfo->au4PendingTxDoneCount[i] = 0; + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Rollback resource to TCs for mt7663 +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ + +void halRestoreTxResource_v1(IN struct ADAPTER *prAdapter) +{ + uint8_t i; + + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + /* WMM 1 */ + /* PSE pages: HIF_TXC_IDX_0- */ + for (i = HIF_TXC_IDX_0; i <= HIF_TXC_IDX_4; i++) { + nicTxReleaseResource_PSE(prAdapter, HIF_TXC_IDX_2_TC_IDX_PSE(i), + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[i], + FALSE); + + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[i] = 0; + } + + /* PLE pages */ + for (i = HIF_TXC_IDX_5; i <= HIF_TXC_IDX_8; i++) { + nicTxReleaseResource_PLE(prAdapter, HIF_TXC_IDX_2_TC_IDX_PLE(i), + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[i], + FALSE); + + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[i] = 0; + } + + /* WMM 2,3 */ + /*TBD*/ + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); +} + +void halUpdateTxDonePendingCount(IN struct ADAPTER *prAdapter, IN u_int8_t isIncr, IN uint8_t ucTc, IN uint32_t u4Len) +{ + uint8_t u2PageCnt; + struct BUS_INFO *prBusInfo = prAdapter->chip_info->bus_info; + + u2PageCnt = halTxGetPageCount(prAdapter, u4Len, FALSE); + + if (prBusInfo->halUpdateTxDonePendingCount) + prBusInfo->halUpdateTxDonePendingCount(prAdapter, isIncr, ucTc, u2PageCnt); + else { + /* 6632, 7668 ways */ + if (isIncr) + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[ucTc] += u2PageCnt; + else + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[ucTc] -= u2PageCnt; + } +} + +void halUpdateTxDonePendingCount_v1(IN struct ADAPTER *prAdapter, IN u_int8_t isIncr, IN uint8_t ucTc, IN uint16_t u2Cnt) +{ + uint8_t idx; + + /* Update PSE part */ + idx = TC_IDX_PSE_2_HIF_TXC_IDX(ucTc); + + if (idx >= HIF_TXC_IDX_NUM) + ASSERT(0); + + if (isIncr) + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[idx] += u2Cnt; + else + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[idx] -= u2Cnt; + + /* Update PLE part */ + if (!nicTxResourceIsPleCtrlNeeded(prAdapter, ucTc)) + return; + + idx = TC_IDX_PLE_2_HIF_TXC_IDX(ucTc); + + if (idx >= HIF_TXC_IDX_NUM) + ASSERT(0); + + if (isIncr) + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[idx] += NIX_TX_PLE_PAGE_CNT_PER_FRAME; + else + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[idx] -= NIX_TX_PLE_PAGE_CNT_PER_FRAME; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Send HIF_CTRL command to inform FW stop send packet/event to host +* suspend = 1 +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (void) +*/ +/*----------------------------------------------------------------------------*/ +void halPreSuspendCmd(IN struct ADAPTER *prAdapter) +{ + struct CMD_HIF_CTRL rCmdHifCtrl; + uint32_t rStatus; + + rCmdHifCtrl.ucHifType = ENUM_HIF_TYPE_SDIO; + rCmdHifCtrl.ucHifDirection = ENUM_HIF_TX; + rCmdHifCtrl.ucHifStop = 1; + rCmdHifCtrl.ucHifSuspend = 1; + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_HIF_CTRL, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* nicEventHifCtrl */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct CMD_HIF_CTRL), + (uint8_t *)&rCmdHifCtrl, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (kalIsResetting()) + return; + + ASSERT(rStatus == WLAN_STATUS_PENDING); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Send HIF_CTRL command to inform FW allow send packet/event to host +* suspend = 0 +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (void) +*/ +/*----------------------------------------------------------------------------*/ +void halPreResumeCmd(IN struct ADAPTER *prAdapter) +{ + struct CMD_HIF_CTRL rCmdHifCtrl; + uint32_t rStatus; + + rCmdHifCtrl.ucHifType = ENUM_HIF_TYPE_SDIO; + rCmdHifCtrl.ucHifDirection = ENUM_HIF_TX; + rCmdHifCtrl.ucHifStop = 0; + rCmdHifCtrl.ucHifSuspend = 0; + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_HIF_CTRL, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* nicEventHifCtrl */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct CMD_HIF_CTRL), + (uint8_t *)&rCmdHifCtrl, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (kalIsResetting()) + return; + + ASSERT(rStatus == WLAN_STATUS_PENDING); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Check if HIF state is READY for upper layer cfg80211 +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (TRUE: ready, FALSE: not ready) +*/ +/*----------------------------------------------------------------------------*/ +bool halIsHifStateReady(IN struct ADAPTER *prAdapter, uint8_t *pucState) +{ + if (!prAdapter) + return FALSE; + + if (!prAdapter->prGlueInfo) + return FALSE; + + if (prAdapter->prGlueInfo->u4ReadyFlag == 0) + return FALSE; + + if (pucState) + *pucState = prAdapter->prGlueInfo->rHifInfo.state; + + if (prAdapter->prGlueInfo->rHifInfo.state != SDIO_STATE_READY) + return FALSE; + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Check if HIF state is during supend process +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (TRUE: suspend, reject the caller action. FALSE: not suspend) +*/ +/*----------------------------------------------------------------------------*/ +bool halIsHifStateSuspend(IN struct ADAPTER *prAdapter) +{ + enum sdio_state state; + + if (!prAdapter) + return FALSE; + + if (!prAdapter->prGlueInfo) + return FALSE; + + state = prAdapter->prGlueInfo->rHifInfo.state; + + if (state == SDIO_STATE_SUSPEND) + return TRUE; + + return FALSE; +} + + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/include/hif.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/include/hif.h new file mode 100644 index 0000000000000..371c5b4275a3a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/include/hif.h @@ -0,0 +1,453 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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 +*/ + + +#ifndef _HIF_H +#define _HIF_H + +#if MTK_WCN_HIF_SDIO +#include "hif_sdio.h" +#endif + +#ifdef _SDIO_RING +#include "sdio_ring.h" +#endif +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#if MTK_WCN_HIF_SDIO +#define HIF_SDIO_SUPPORT_GPIO_SLEEP_MODE 1 +#else +#define HIF_SDIO_SUPPORT_GPIO_SLEEP_MODE 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 +******************************************************************************** +*/ +#if defined(_HIF_SDIO) +#define HIF_NAME "SDIO" +#else +#error "No HIF defined!" +#endif + + +/* Enable driver timing profiling */ +#define CFG_SDIO_TIMING_PROFILING 0 + +#define CFG_SDIO_INT_LOG_CNT 8 + +#define SDIO_X86_WORKAROUND_WRITE_MCR 0x00C4 +#define HIF_NUM_OF_QM_RX_PKT_NUM 512 + +#define HIF_TX_INIT_CMD_PORT TX_RING_FWDL_IDX_3 + +#define HIF_IST_LOOP_COUNT 128 +#define HIF_IST_TX_THRESHOLD 32 /* Min msdu count to trigger Tx during INT polling state */ + +#define HIF_TX_MAX_AGG_LENGTH (511 * 512) /* 511 blocks x 512 */ + +#define HIF_RX_MAX_AGG_NUM 16 +/*!< Setting the maximum RX aggregation number 0: no limited (16) */ + +#define HIF_TX_BUFF_COUNT_TC0 8 +#define HIF_TX_BUFF_COUNT_TC1 167 +#define HIF_TX_BUFF_COUNT_TC2 8 +#define HIF_TX_BUFF_COUNT_TC3 8 +#define HIF_TX_BUFF_COUNT_TC4 7 +#define HIF_TX_BUFF_COUNT_TC5 0 + +#define HIF_TX_RESOURCE_CTRL 1 /* enable/disable TX resource control */ +#define HIF_TX_RESOURCE_CTRL_PLE 1 /* enable/disable TX resource control PLE */ + + +#define HIF_TX_PAGE_SIZE_IN_POWER_OF_2 11 +#define HIF_TX_PAGE_SIZE 2048 /* in unit of bytes */ +#define HIF_TX_PAGE_SIZE_STORED_FORWARD 128 /* in unit of bytes */ + +#define HIF_EXTRA_IO_BUFFER_SIZE \ + (sizeof(struct ENHANCE_MODE_DATA_STRUCT) + HIF_RX_COALESCING_BUF_COUNT * HIF_RX_COALESCING_BUFFER_SIZE) + +#define HIF_CR4_FWDL_SECTION_NUM 2 +#define HIF_IMG_DL_STATUS_PORT_IDX 0 + +#define HIF_RX_ENHANCE_MODE_PAD_LEN 4 + +#define HIF_TX_TERMINATOR_LEN 4 + +#if CFG_SDIO_TX_AGG +#define HIF_TX_COALESCING_BUFFER_SIZE (HIF_TX_MAX_AGG_LENGTH) +#else +#define HIF_TX_COALESCING_BUFFER_SIZE (CFG_TX_MAX_PKT_SIZE) +#endif + +/* To handle size over CFG_RX_MAX_PKT_SIZE of single rx pkt */ +/* had seen around 3200 */ +#define HIF_RX_COALESCING_TOLERANCE_SIZE 896 + +#if CFG_SDIO_RX_AGG +#define HIF_RX_COALESCING_BUFFER_SIZE \ +((HIF_RX_MAX_AGG_NUM + 1) * \ +(CFG_RX_MAX_PKT_SIZE + HIF_RX_COALESCING_TOLERANCE_SIZE)) +#else +#define HIF_RX_COALESCING_BUFFER_SIZE \ +(CFG_RX_MAX_PKT_SIZE + HIF_RX_COALESCING_TOLERANCE_SIZE) +#endif + +#define HIF_RX_COALESCING_BUF_COUNT 16 + +/* WHISR device to host (D2H) */ +/* N9 Interrupt Host to stop tx/rx operation (at the moment, HIF tx/rx are stopted) */ +#define SER_SDIO_N9_HOST_STOP_TX_RX_OP BIT(8) +/* N9 Interrupt Host to stop tx operation (at the moment, HIF tx are stopted) */ +#define SER_SDIO_N9_HOST_STOP_TX_OP BIT(9) +/* N9 Interrupt Host all modules were reset done (to let host reinit HIF) */ +#define SER_SDIO_N9_HOST_RESET_DONE BIT(10) +/* N9 Interrupt Host System Error Recovery Done */ +#define SER_SDIO_N9_HOST_RECOVERY_DONE BIT(11) + +/* WSICR host to device (H2D) */ +/* Host ACK HIF tx/rx ring stop operatio */ +#define SER_SDIO_HOST_N9_STOP_TX_RX_OP_ACK BIT(19) +/* Host interrupt N9 HIF init done */ +#define SER_SDIO_HOST_N9_RESET_DONE_ACK BIT(20) +/* Host interrupt N9 System Error Recovery done */ +#define SER_SDIO_HOST_N9_RECOVERY_DONE_ACK BIT(21) +enum HIF_TX_COUNT_IDX_T { + HIF_TXC_IDX_0, + HIF_TXC_IDX_1, + HIF_TXC_IDX_2, + HIF_TXC_IDX_3, + HIF_TXC_IDX_4, + HIF_TXC_IDX_5, + HIF_TXC_IDX_6, + HIF_TXC_IDX_7, + HIF_TXC_IDX_8, + HIF_TXC_IDX_9, + HIF_TXC_IDX_10, + HIF_TXC_IDX_11, + HIF_TXC_IDX_12, + HIF_TXC_IDX_13, + HIF_TXC_IDX_14, + HIF_TXC_IDX_15, + HIF_TXC_IDX_NUM +}; + +#ifdef _SDIO_RING + +#ifndef SDIO_RING_SIZE +#define SDIO_RING_SIZE 16 +#endif + +#ifndef SDIO_RING_BUF_LEN +#define SDIO_RING_BUF_LEN (1024*64) +#endif + +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +struct ENHANCE_MODE_DATA_STRUCT; /* declare SDIO_CTRL_T */ + +struct SDIO_STAT_COUNTER { + /* Tx data */ + uint32_t u4DataPortWriteCnt; + uint32_t u4DataPktWriteCnt; + uint32_t u4DataPortKickCnt; + + /* Tx command */ + uint32_t u4CmdPortWriteCnt; + uint32_t u4CmdPktWriteCnt; + + /* Tx done interrupt */ + uint32_t u4TxDoneCnt[HIF_TXC_IDX_NUM]; + uint32_t u4TxDoneIntCnt[HIF_TXC_IDX_NUM]; + uint32_t u4TxDoneIntTotCnt; + uint32_t u4TxDonePendingPktCnt; + + uint32_t u4IntReadCnt; + uint32_t u4IntCnt; + + /* Rx data/cmd*/ + uint32_t u4PortReadCnt[2]; + uint32_t u4PktReadCnt[2]; + + uint32_t u4RxBufUnderFlowCnt; + +#if CFG_SDIO_TIMING_PROFILING + uint32_t u4TxDataCpTime; + uint32_t u4TxDataFreeTime; + + uint32_t u4RxDataCpTime; + uint32_t u4PortReadTime; + + uint32_t u4TxDoneIntTime; + uint32_t u4IntReadTime; +#endif +}; + +struct SDIO_RX_COALESCING_BUF { + struct QUE_ENTRY rQueEntry; + void *pvRxCoalescingBuf; + uint32_t u4BufSize; + uint32_t u4PktCount; + uint32_t u4PktTotalLength; + + uint32_t u4IntLogIdx; +}; + +struct SDIO_INT_LOG_T { + uint32_t u4Idx; + uint8_t aucIntSts[128]; + uint32_t u4Flag; + uint16_t au2RxPktLen[HIF_RX_MAX_AGG_NUM]; + uint32_t au4RxPktInfo[HIF_RX_MAX_AGG_NUM]; + uint8_t ucRxPktCnt; +}; + +enum sdio_state { + SDIO_STATE_WIFI_OFF, /* Hif power off wifi */ + SDIO_STATE_LINK_DOWN, + SDIO_STATE_PRE_SUSPEND_START, + SDIO_STATE_PRE_SUSPEND_DONE, + SDIO_STATE_PRE_SUSPEND_FAIL, + SDIO_STATE_SUSPEND, + SDIO_STATE_PRE_RESUME, + SDIO_STATE_LINK_UP, + SDIO_STATE_READY +}; + +/* host interface's private data structure, which is attached to os glue +** layer info structure. + */ +struct GL_HIF_INFO { +#if MTK_WCN_HIF_SDIO + unsigned long cltCtx; + + const struct MTK_WCN_HIF_SDIO_FUNCINFO *prFuncInfo; +#else + struct sdio_func *func; +#endif + + enum sdio_state state; + + spinlock_t rStateLock; + spinlock_t rSuspendLock; + + struct ENHANCE_MODE_DATA_STRUCT *prSDIOCtrl; + + u_int8_t fgIntReadClear; + u_int8_t fgMbxReadClear; + struct QUE rFreeQueue; + u_int8_t fgIsPendingInt; + + uint32_t au4PendingTxDoneCount[HIF_TXC_IDX_NUM]; + + /* Statistic counter */ + struct SDIO_STAT_COUNTER rStatCounter; + + struct SDIO_RX_COALESCING_BUF rRxCoalesingBuf[HIF_RX_COALESCING_BUF_COUNT]; + + struct QUE rRxDeAggQueue; + struct QUE rRxFreeBufQueue; + + struct mutex rRxFreeBufQueMutex; + struct mutex rRxDeAggQueMutex; + + /* Error handling */ + u_int8_t fgSkipRx; + + struct SDIO_INT_LOG_T arIntLog[CFG_SDIO_INT_LOG_CNT]; + uint32_t u4IntLogIdx; + uint8_t ucIntLogEntry; +#ifdef _SDIO_RING + struct task_struct *sdio_ring_thread; + uint8_t *ring_buffer[SDIO_RING_SIZE]; + uint32_t ring_len[SDIO_RING_SIZE]; + uint32_t ring_PSE[SDIO_RING_SIZE]; + uint32_t ring_PLE[SDIO_RING_SIZE]; + uint32_t ring_head; + uint32_t ring_tail; +#endif +}; + +struct BUS_INFO { + void (*halTxGetFreeResource)(IN struct ADAPTER *prAdapter, IN uint16_t *au2TxDoneCnt, IN uint16_t *au2TxRlsCnt); + void (*halTxReturnFreeResource)(IN struct ADAPTER *prAdapter, IN uint16_t *au2TxDoneCnt); + void (*halRestoreTxResource)(IN struct ADAPTER *prAdapter); + void (*halUpdateTxDonePendingCount)(IN struct ADAPTER *prAdapter, + IN u_int8_t isIncr, IN uint8_t ucTc, IN uint16_t u2Cnt); +}; + +enum HIF_SDIO_INT_STS { + SDIO_INT_RX_ENHANCE = 0, + SDIO_INT_DRV_OWN, + SDIO_INT_WAKEUP_DSLP +}; + +/******************************************************************************* +* P U B 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_SDIO_TIMING_PROFILING +#define SDIO_TIME_INTERVAL_DEC() KAL_TIME_INTERVAL_DECLARATION() +#define SDIO_REC_TIME_START() KAL_REC_TIME_START() +#define SDIO_REC_TIME_END() KAL_REC_TIME_END() +#define SDIO_GET_TIME_INTERVAL() KAL_GET_TIME_INTERVAL() +#define SDIO_ADD_TIME_INTERVAL(_Interval) KAL_ADD_TIME_INTERVAL(_Interval) +#else +#define SDIO_TIME_INTERVAL_DEC() +#define SDIO_REC_TIME_START() +#define SDIO_REC_TIME_END() +#define SDIO_GET_TIME_INTERVAL() +#define SDIO_ADD_TIME_INTERVAL(_Interval) +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +uint32_t glRegisterBus(probe_card pfProbe, remove_card pfRemove); + +void glUnregisterBus(remove_card pfRemove); + +void glSetHifInfo(struct GLUE_INFO *prGlueInfo, unsigned long ulCookie); + +void glClearHifInfo(struct GLUE_INFO *prGlueInfo); + +u_int8_t glBusInit(void *pvData); + +void glBusRelease(void *pData); + +int32_t glBusSetIrq(void *pvData, void *pfnIsr, void *pvCookie); + +void glBusFreeIrq(void *pvData, void *pvCookie); + +void glSetPowerState(IN struct GLUE_INFO *prGlueInfo, IN uint32_t ePowerMode); + +void glGetDev(void *ctx, struct device **dev); + +void glGetHifDev(struct GL_HIF_INFO *prHif, struct device **dev); + +u_int8_t glWakeupSdio(struct GLUE_INFO *prGlueInfo); + +#if !CFG_SDIO_INTR_ENHANCE +void halRxSDIOReceiveRFBs(IN struct ADAPTER *prAdapter); + +uint32_t halRxReadBuffer(IN struct ADAPTER *prAdapter, IN OUT struct SW_RFB *prSwRfb); + +#else +void halRxSDIOEnhanceReceiveRFBs(IN struct ADAPTER *prAdapter); + +uint32_t halRxEnhanceReadBuffer(IN struct ADAPTER *prAdapter, IN uint32_t u4DataPort, + IN uint16_t u2RxLength, IN OUT struct SW_RFB *prSwRfb); + +void halProcessEnhanceInterruptStatus(IN struct ADAPTER *prAdapter); + +#endif /* CFG_SDIO_INTR_ENHANCE */ + +#if CFG_SDIO_RX_AGG +void halRxSDIOAggReceiveRFBs(IN struct ADAPTER *prAdapter); +#endif + +void halPutMailbox(IN struct ADAPTER *prAdapter, IN uint32_t u4MailboxNum, IN uint32_t u4Data); +void halGetMailbox(IN struct ADAPTER *prAdapter, IN uint32_t u4MailboxNum, OUT uint32_t *pu4Data); +void halDeAggRxPkt(struct ADAPTER *prAdapter, struct SDIO_RX_COALESCING_BUF *prRxBuf); +void halPrintMailbox(IN struct ADAPTER *prAdapter); +void halPollDbgCr(IN struct ADAPTER *prAdapter, IN uint32_t u4LoopCount); +void halTxGetFreeResource_v1(IN struct ADAPTER *prAdapter, IN uint16_t *au2TxDoneCnt, IN uint16_t *au2TxRlsCnt); + +u_int8_t halIsPendingTxDone(IN struct ADAPTER *prAdapter); +void halDumpIntLog(IN struct ADAPTER *prAdapter); +void halTagIntLog(IN struct ADAPTER *prAdapter, IN enum HIF_SDIO_INT_STS eTag); +void halRecIntLog(IN struct ADAPTER *prAdapter, IN struct ENHANCE_MODE_DATA_STRUCT *prSDIOCtrl); +struct SDIO_INT_LOG_T *halGetIntLog(IN struct ADAPTER *prAdapter, IN uint32_t u4Idx); +void halPreSuspendCmd(IN struct ADAPTER *prAdapter); +void halPreResumeCmd(IN struct ADAPTER *prAdapter); +void glSdioSetState(struct GL_HIF_INFO *prHifInfo, enum sdio_state state); +enum sdio_state glSdioGetState(struct GL_HIF_INFO *prHifInfo); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _HIF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/include/hif_sdio.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/include/hif_sdio.h new file mode 100644 index 0000000000000..9adba8b18dd7b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/include/hif_sdio.h @@ -0,0 +1,267 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/sdio/include/hif_sdio.h#2 +*/ + +/*! \file "hif_sdio.h" +* \brief +* +* +*/ + + +#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:turn off debug msg and assert, 1:turn 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 (8) + +#define HIF_DEFAULT_BLK_SIZE (256) +#define HIF_DEFAULT_VENDOR (0x037A) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/* sdio driver data mapping */ +struct MTK_WCN_SDIO_DRIVER_DATA_MAPPING { + uint16_t card_id; /* TPLMID_CARD: card ID */ + struct mt66xx_hif_driver_data *mt66xx_driver_data; +}; + + +/* Function info provided by client driver */ +struct MTK_WCN_HIF_SDIO_FUNCINFO; /* declare MTK_WCN_HIF_SDIO_FUNCINFO */ + +/* Client context provided by hif_sdio driver for the following function call */ + +/* Callback functions provided by client driver */ +typedef int32_t(*MTK_WCN_HIF_SDIO_PROBE)(unsigned long, const struct MTK_WCN_HIF_SDIO_FUNCINFO *prFuncInfo); +typedef int32_t(*MTK_WCN_HIF_SDIO_REMOVE)(unsigned long); +typedef int32_t(*MTK_WCN_HIF_SDIO_IRQ)(unsigned long); + +/* Function info provided by client driver */ +struct MTK_WCN_HIF_SDIO_FUNCINFO { + uint16_t manf_id; /* TPLMID_MANF: manufacturer ID */ + uint16_t card_id; /* TPLMID_CARD: card ID */ + uint16_t func_num; /* Function Number */ + uint16_t blk_sz; /* Function block size */ +}; + +/* Client info provided by client driver */ +struct MTK_WCN_HIF_SDIO_CLTINFO { + const struct MTK_WCN_HIF_SDIO_FUNCINFO *func_tbl; /* supported function info table */ + uint32_t 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 */ +}; + +/* function info provided by registed function */ +struct MTK_WCN_HIF_SDIO_REGISTINFO { + const struct MTK_WCN_HIF_SDIO_CLTINFO *sdio_cltinfo; /* client's MTK_WCN_HIF_SDIO_CLTINFO pointer */ + const struct MTK_WCN_HIF_SDIO_FUNCINFO *func_info; /* supported function info pointer */ +}; + +/* Card info provided by probed function */ +struct MTK_WCN_HIF_SDIO_PROBEINFO { + struct sdio_func *func; /* probed sdio function pointer */ + int8_t clt_idx; /* registered function table info element number (initial value is -1) */ + int interrupted; /* TRUE: interrupted, FALSE: not interrupted */ + void *private_data_p; /* clt's private data pointer */ +}; + +/* work queue info needed by worker */ +struct MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO { + struct work_struct probe_work; /* work queue structure */ + struct MTK_WCN_HIF_SDIO_REGISTINFO *registinfo_p; /* MTK_WCN_HIF_SDIO_REGISTINFO pointer of the client */ + int8_t probe_idx; /* probed function table info element number (initial value is -1) */ +}; + +/* error code returned by hif_sdio driver (use NEGATIVE number) */ +enum MTK_WCN_HIF_SDIO_ERR { + HIF_SDIO_ERR_SUCCESS = 0, + HIF_SDIO_ERR_FAIL, /* generic error */ + HIF_SDIO_ERR_INVALID_PARAM, + HIF_SDIO_ERR_DUPLICATED, + HIF_SDIO_ERR_UNSUP_MANF_ID, + HIF_SDIO_ERR_UNSUP_CARD_ID, + HIF_SDIO_ERR_INVALID_FUNC_NUM, + HIF_SDIO_ERR_INVALID_BLK_SZ, +}; + +/******************************************************************************* +* P U B 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) + +/*! + * \brief A debug print used to print debug messages while compiler flag HIF_SDIO_DEBUG on. + * + */ +#if HIF_SDIO_DEBUG +#define DPRINTK(fmt, args...) pr_debug("%s: " fmt, __func__, ## args) +#else +#define DPRINTK(fmt, args...) +#endif + +/*! + * \brief ASSERT function definition. + * + */ +#if HIF_SDIO_DEBUG +#define ASSERT(expr) \ + { \ + if (!(expr)) { \ + LOG_FUNC("assertion failed! %s[%d]: %s\n",\ + __func__, __LINE__, #expr); \ + WARN_ON(!(expr));\ + } \ + } +#else +#define 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_t mtk_wcn_hif_sdio_client_reg(const struct MTK_WCN_HIF_SDIO_CLTINFO *pinfo); + +extern int32_t mtk_wcn_hif_sdio_client_unreg(const struct MTK_WCN_HIF_SDIO_CLTINFO *pinfo); + +extern int32_t mtk_wcn_hif_sdio_readb(unsigned long ctx, uint32_t offset, uint8_t *pvb); + +extern int32_t mtk_wcn_hif_sdio_writeb(unsigned long ctx, uint32_t offset, uint8_t vb); + +extern int32_t mtk_wcn_hif_sdio_f0_readb(unsigned long ctx, uint32_t offset, uint8_t *pvb); + +extern int32_t mtk_wcn_hif_sdio_f0_writeb(unsigned long ctx, uint32_t offset, uint8_t vb); + +extern int32_t mtk_wcn_hif_sdio_readl(unsigned long ctx, uint32_t offset, uint32_t *pvl); + +extern int32_t mtk_wcn_hif_sdio_writel(unsigned long ctx, uint32_t offset, uint32_t vl); + +extern int32_t mtk_wcn_hif_sdio_read_buf(unsigned long ctx, uint32_t offset, uint32_t *pbuf, uint32_t len); + +extern int32_t mtk_wcn_hif_sdio_write_buf(unsigned long ctx, uint32_t offset, uint32_t *pbuf, uint32_t len); + +extern void mtk_wcn_hif_sdio_set_drvdata(unsigned long ctx, void *private_data_p); + +extern void *mtk_wcn_hif_sdio_get_drvdata(unsigned long ctx); + +extern void mtk_wcn_hif_sdio_get_dev(unsigned long ctx, struct device **dev); + +extern void mtk_wcn_hif_sdio_enable_irq(unsigned long ctx, int enable); + +#if KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE +extern int32_t mtk_wcn_stp_sdio_wake_up_ctrl(unsigned long ctx); +#else +extern int32_t mtk_wcn_hif_sdio_wake_up_ctrl(unsigned long ctx); +#endif + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _HIF_SDIO_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/include/mtk_porting.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/include/mtk_porting.h new file mode 100644 index 0000000000000..9be2f55d64c63 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/include/mtk_porting.h @@ -0,0 +1,89 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* porting layer */ +/* Android */ + +#ifndef _MTK_PORTING_H_ +#define _MTK_PORTING_H_ + +#include /* include stddef.h for NULL */ + +/* typedef void VOID, *PVOID; */ + +#ifndef MTK_WCN_BOOL_TRUE +#define MTK_WCN_BOOL_FALSE ((int) 0) +#define MTK_WCN_BOOL_TRUE ((int) 1) +#endif + + + +/* system APIs */ +/* mutex */ +typedef int(*MUTEX_CREATE) (const char *const name); +typedef int32_t(*MUTEX_DESTROY) (int mtx); +typedef int32_t(*MUTEX_LOCK) (int mtx); +typedef int32_t(*MUTEX_UNLOCK) (int mtx, unsigned long flags); +/* debug */ +typedef int32_t(*DBG_PRINT) (const char *str, ...); +typedef int32_t(*DBG_ASSERT) (int32_t expr, const char *file, int32_t line); +/* timer */ +typedef void (*MTK_WCN_TIMER_CB) (void); +typedef int(*TIMER_CREATE) (const char *const name); +typedef int32_t(*TIMER_DESTROY) (int tmr); +typedef int32_t(*TIMER_START) (int tmr, uint32_t timeout, MTK_WCN_TIMER_CB tmr_cb, void *param); +typedef int32_t(*TIMER_STOP) (int tmr); +/* kernel lib */ +typedef void *(*SYS_MEMCPY) (void *dest, const void *src, uint32_t n); +typedef void *(*SYS_MEMSET) (void *s, int32_t c, uint32_t n); +typedef int32_t(*SYS_SPRINTF) (char *str, const char *format, ...); + +#endif /* _MTK_PORTING_H_ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/include/sdio_ring.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/include/sdio_ring.h new file mode 100644 index 0000000000000..521a355ae8d1d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/include/sdio_ring.h @@ -0,0 +1,107 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** +*[File] sdio_ring.h +*[Version] v1.0 +*[Revision Date] 2018-09-03 +*[Author] +*[Description] +* The program provides SDIO HIF ring buffer architecture +*[Copyright] +*Copyright (C) 2018 MediaTek Incorporation. All Rights Reserved. +******************************************************************************/ +#ifndef _SDIO_RING_H +#define _SDIO_RING_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 SDIO_RING_TX_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 +******************************************************************************** +*/ +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +uint32_t Initial_sdio_ring(struct GLUE_INFO *prGlueInfo); +uint32_t sdio_ring_kcik_data(struct GLUE_INFO *prGlueInfo); +void Set_sdio_ring_event(void); +uint8_t sdio_ring_push(struct GLUE_INFO *prGlueInfo); +uint8_t sdio_ring_pop(struct GLUE_INFO *prGlueInfo); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/include/test_driver_sdio_ops.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/include/test_driver_sdio_ops.h new file mode 100644 index 0000000000000..e396c46229657 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/include/test_driver_sdio_ops.h @@ -0,0 +1,48 @@ +/* + * linux/drivers/mmc/sdio_ops.c + * + * Copyright 2006-2007 Pierre Ossman + * + * 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. + */ + + +#ifndef __TEST_DRV_SDIO_OPS_H__ +#define __TEST_DRV_SDIO_OPS_H__ + +#include +#include +#include +#include +#include + + +int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr); +int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, + unsigned addr, u8 in, u8 *out); +int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, + unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz); + +int sdio_disable_wide(struct mmc_card *card); +int sdio_enable_4bit_bus(struct mmc_card *card); + + + +#include +#include +#define MMC_CMD_RETRIES 3 + +static inline void mmc_delay(unsigned int ms) +{ + if (ms < 1000 / HZ) { + cond_resched(); + mdelay(ms); + } else { + msleep(ms); + } +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/sdio.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/sdio.c new file mode 100644 index 0000000000000..4ffaa9dfadb34 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/sdio.c @@ -0,0 +1,1979 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** +*[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. +******************************************************************************/ + + +/******************************************************************************* +* C O M P I L E 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 "precomp.h" + +#if MTK_WCN_HIF_SDIO +#include "hif_sdio.h" +#else +#include +#include +#include +#include /* sdio_readl(), etc */ +#include /* mmc_add_host(), etc */ +#include +#endif + +#include +#ifndef CONFIG_X86 +#include +#endif + +#include "mt66xx_reg.h" + +#if CFG_SUPPORT_WOW_EINT +#include +#include +#include +#endif + +#if (CFG_SDIO_1BIT_DATA_MODE == 1) +#include "test_driver_sdio_ops.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" + +#define HIF_SDIO_ACCESS_RETRY_LIMIT 250 +#define HIF_SDIO_INTERRUPT_RESPONSE_TIMEOUT (15000) + +#if CFG_SUPPORT_WOW_EINT +#define WIFI_COMPATIBLE_NODE_NAME "mediatek,mt7663_wifi_ctrl" +#define WIFI_INTERRUPT_NAME "mt7663_wifi_ctrl-eint" +#endif + +#if MTK_WCN_HIF_SDIO + +/* + * function prototypes + * + */ + +static int32_t mtk_sdio_probe(unsigned long, const struct MTK_WCN_HIF_SDIO_FUNCINFO *); + +static int32_t mtk_sdio_remove(unsigned long); +static int32_t mtk_sdio_interrupt(unsigned long); + +/* + * sdio function info table + */ + +static struct MTK_WCN_HIF_SDIO_FUNCINFO funcInfo[] = { + {MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x6602, 0x1, 512)}, +}; + +static struct MTK_WCN_SDIO_DRIVER_DATA_MAPPING sdio_driver_data_mapping[] = { + {0x6602, &mt66xx_driver_data_mt6632}, +}; + +static struct MTK_WCN_HIF_SDIO_CLTINFO cltInfo = { + .func_tbl = funcInfo, + .func_tbl_size = sizeof(funcInfo) / sizeof(struct MTK_WCN_HIF_SDIO_FUNCINFO), + .hif_clt_probe = mtk_sdio_probe, + .hif_clt_remove = mtk_sdio_remove, + .hif_clt_irq = mtk_sdio_interrupt, +}; + +#else +/* + * function prototypes + * + */ +static int mtk_sdio_pm_suspend(struct device *pDev); +static int mtk_sdio_pm_resume(struct device *pDev); + +static const struct sdio_device_id mtk_sdio_ids[] = { +#ifdef MT6632 + { SDIO_DEVICE(0x037a, 0x6602), + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_mt6632},/* Not an SDIO standard class device */ +#endif /* MT6632 */ +#ifdef MT7668 + { SDIO_DEVICE(0x037a, 0x7608), + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_mt7668},/* Not an SDIO standard class device */ +#endif /* MT7668 */ +#ifdef MT7663 + { SDIO_DEVICE(0x037a, 0x7603), + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_mt7663}, +#endif /* MT7663 */ + { /* 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 +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static probe_card pfWlanProbe; +static remove_card pfWlanRemove; + +#if (MTK_WCN_HIF_SDIO == 0) +static const struct dev_pm_ops mtk_sdio_pm_ops = { + .suspend = mtk_sdio_pm_suspend, + .resume = mtk_sdio_pm_resume, +}; + +static struct sdio_driver mtk_sdio_driver = { + .name = "wlan", /* "MTK SDIO WLAN Driver" */ + .id_table = mtk_sdio_ids, + .probe = NULL, + .remove = NULL, + .drv = { + .owner = THIS_MODULE, + .pm = &mtk_sdio_pm_ops, + } +}; +#endif + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define dev_to_sdio_func(d) container_of(d, struct sdio_func, dev) + + +/******************************************************************************* +* 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 a SDIO interrupt callback function +* +* \param[in] func pointer to SDIO handle +* +* \return void +*/ +/*----------------------------------------------------------------------------*/ +#if CFG_SUPPORT_WOW_EINT +static irqreturn_t wifi_wow_isr(int irq, void *dev) +{ + return IRQ_HANDLED; +} + +static void wlan_register_irq(struct WOWLAN_DEV_NODE *node) +{ + struct device_node *eint_node = NULL; + int interrupts[2]; + + eint_node = of_find_compatible_node(NULL, + NULL, WIFI_COMPATIBLE_NODE_NAME); + if (eint_node) { + node->wowlan_irq = irq_of_parse_and_map(eint_node, 0); + DBGLOG(INIT, INFO, "%s, WOWLAN irq_number = %d\n", __func__, + node->wowlan_irq); + if (node->wowlan_irq) { + of_property_read_u32_array(eint_node, + "interrupts", + interrupts, + ARRAY_SIZE(interrupts)); + node->wowlan_irqlevel = interrupts[1]; + if (request_irq(node->wowlan_irq, + wifi_wow_isr, + node->wowlan_irqlevel, + WIFI_INTERRUPT_NAME, + node)) { + DBGLOG(INIT, ERROR, + "%s, WOWLAN irq NOT AVAILABLE!\n", + __func__); + } else { + disable_irq_nosync(node->wowlan_irq); + } + } else { + DBGLOG(INIT, ERROR, + "%s, can't find wifi_ctrl irq\n", + __func__); + } + + } else { + node->wowlan_irq = 0; + DBGLOG(INIT, ERROR, + "%s, can't find wifi_ctrl compatible node\n", + __func__); + } +} + +static void mtk_sdio_eint_interrupt(struct sdio_func *func) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + prGlueInfo = sdio_get_drvdata(func); + if (!prGlueInfo) + return; + + prGlueInfo->prAdapter->rWowlanDevNode.func = func; + wlan_register_irq(&(prGlueInfo->prAdapter->rWowlanDevNode)); +} + +static void mtk_sdio_eint_free_irq(struct sdio_func *func) +{ + struct GLUE_INFO *prGlueInfo = NULL; + uint32_t u4Irq = 0; + + prGlueInfo = sdio_get_drvdata(func); + if (!prGlueInfo) + return; + + u4Irq = prGlueInfo->prAdapter->rWowlanDevNode.wowlan_irq; + if (u4Irq) { + disable_irq_nosync(u4Irq); + free_irq(u4Irq, + &prGlueInfo->prAdapter->rWowlanDevNode); + } +} + +#endif + +#if MTK_WCN_HIF_SDIO + +static int32_t mtk_sdio_interrupt(unsigned long cltCtx) +{ + struct GLUE_INFO *prGlueInfo = NULL; + int32_t ret = 0; + + prGlueInfo = mtk_wcn_hif_sdio_get_drvdata(cltCtx); + + /* ASSERT(prGlueInfo); */ + + if (!prGlueInfo) { + return -HIF_SDIO_ERR_FAIL; + } + + prGlueInfo->u8HifIntTime = sched_clock(); + + prGlueInfo->IsrCnt++; + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + ret = mtk_wcn_hif_sdio_writeb(cltCtx, MCR_WHLPCR, WHLPCR_INT_EN_CLR); + return ret; + } + + ret = mtk_wcn_hif_sdio_writeb(cltCtx, MCR_WHLPCR, WHLPCR_INT_EN_CLR); + + prGlueInfo->rHifInfo.fgIsPendingInt = FALSE; + + kalSetIntEvent(prGlueInfo); + prGlueInfo->IsrPassCnt++; + + return ret; +} + +#else +static void mtk_sdio_interrupt(struct sdio_func *func) +{ + struct GLUE_INFO *prGlueInfo = NULL; + + int ret = 0; + + prGlueInfo = sdio_get_drvdata(func); + /* ASSERT(prGlueInfo); */ + + if (!prGlueInfo) { + return; + } + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + sdio_writeb(prGlueInfo->rHifInfo.func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, &ret); + return; + } + + sdio_writeb(prGlueInfo->rHifInfo.func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, &ret); + + kalSetIntEvent(prGlueInfo); +} +#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 struct MTK_WCN_HIF_SDIO_FUNCINFO *prFunc; + +static int32_t mtk_sdio_probe(unsigned long cltCtx, const struct MTK_WCN_HIF_SDIO_FUNCINFO *prFuncInfo) +{ + int32_t ret = HIF_SDIO_ERR_SUCCESS; + int32_t i = 0; + int32_t dd_table_len = sizeof(sdio_driver_data_mapping) / sizeof(struct MTK_WCN_SDIO_DRIVER_DATA_MAPPING); + struct mt66xx_hif_driver_data *sdio_driver_data = NULL; + + prFunc = prFuncInfo; + + for (i = 0; i < dd_table_len; i++) { + if (prFunc->card_id == sdio_driver_data_mapping[i].card_id) { + sdio_driver_data = sdio_driver_data_mapping[i].mt66xx_driver_data; + break; + } + } + + if (sdio_driver_data == NULL) { + DBGLOG(HAL, ERROR, "sdio probe error: %x driver data not found!\n", prFunc->card_id); + return HIF_SDIO_ERR_UNSUP_CARD_ID; + } + + if (pfWlanProbe((void *)&cltCtx, (void *) sdio_driver_data) != WLAN_STATUS_SUCCESS) { + pfWlanRemove(); + ret = -(HIF_SDIO_ERR_FAIL); + } else { + + } + return ret; +} +#else +static int mtk_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) +{ + int ret = 0; + /* int i = 0; */ + + + + ASSERT(func); + ASSERT(id); + + sdio_claim_host(func); + ret = sdio_enable_func(func); + sdio_release_host(func); + + if (ret) { + goto out; + } + + if (pfWlanProbe((void *) func, (void *) id->driver_data) != WLAN_STATUS_SUCCESS) { + pfWlanRemove(); + ret = -1; + } + +out: + return ret; +} +#endif + +#if MTK_WCN_HIF_SDIO +static int32_t mtk_sdio_remove(unsigned long cltCtx) +{ + int32_t ret = HIF_SDIO_ERR_SUCCESS; + + pfWlanRemove(); + + return ret; +} +#else +static void mtk_sdio_remove(struct sdio_func *func) +{ + + ASSERT(func); + + pfWlanRemove(); + + sdio_claim_host(func); + sdio_disable_func(func); + sdio_release_host(func); + +} +#endif + +#if (MTK_WCN_HIF_SDIO == 0) +static int mtk_sdio_pm_suspend(struct device *pDev) +{ + int ret = 0, wait = 0; + int pm_caps, set_flag; + const char *func_id; + struct sdio_func *func; + struct GLUE_INFO *prGlueInfo = NULL; + struct ADAPTER *prAdapter = NULL; + uint8_t count = 0; + uint8_t drv_own_fail = FALSE; + + DBGLOG(HAL, STATE, "mtk_sdio_pm_suspend\n"); + + if (kalIsResetting()) { + DBGLOG(HAL, WARN, "Chip resetting, skip\n"); + return -1; + } + + func = dev_to_sdio_func(pDev); + prGlueInfo = sdio_get_drvdata(func); + prAdapter = prGlueInfo->prAdapter; + + /* Stop upper layers calling the device hard_start_xmit routine. */ + netif_tx_stop_all_queues(prGlueInfo->prDevHandler); + wlanWaitCfg80211SuspendDone(prGlueInfo); + + /* change to non-READY state to block cfg80211 ops */ + glSdioSetState(&prGlueInfo->rHifInfo, SDIO_STATE_PRE_SUSPEND_START); + +#if CFG_ENABLE_WAKE_LOCK + /* AIS flow: disassociation if wow_en=0 */ + /* cancel scan report done event */ + aisPreSuspendFlow(prGlueInfo); + + /* In current design, only support AIS connection during suspend only. + * It need to add flow to deactive P2P (GC/GO) link during suspend flow. + * Otherwise, MT7668 would fail to enter deep sleep. + */ + p2pProcessPreSuspendFlow(prGlueInfo->prAdapter); +#endif + wlan_fb_power_down = TRUE; + if (!wlan_perf_monitor_force_enable) + kalPerMonDisable(prGlueInfo); + + wlanSuspendPmHandle(prGlueInfo); + + /* send pre-suspend cmd to notify FW do not send pkt/event to host */ + halPreSuspendCmd(prAdapter); + + while (prGlueInfo->rHifInfo.state != SDIO_STATE_PRE_SUSPEND_DONE) { + if (count > 500) { + DBGLOG(HAL, ERROR, "pre_suspend timeout\n"); + break; + } + usleep_range(2000, 3000); + count++; + } + + halDisableInterrupt(prAdapter); + + prAdapter->fgForceFwOwn = TRUE; + +#if CFG_SUPPORT_WOW_EINT + if (prAdapter->rWowlanDevNode.wowlan_irq != 0 && + atomic_read( + &(prAdapter->rWowlanDevNode.irq_enable_count)) == 0) { + DBGLOG(HAL, ERROR, "%s:enable WIFI IRQ:%d\n", __func__, + prAdapter->rWowlanDevNode.wowlan_irq); + enable_irq(prAdapter->rWowlanDevNode.wowlan_irq); + enable_irq_wake(prAdapter->rWowlanDevNode.wowlan_irq); + atomic_inc(&(prAdapter->rWowlanDevNode.irq_enable_count)); + } else { + DBGLOG(HAL, ERROR, "%s:irq_enable count:%d\n", __func__, + atomic_read( + &(prAdapter->rWowlanDevNode.irq_enable_count))); + } +#endif + + /* Wait for + * 1. The other unfinished ownership handshakes + * 2. FW own back + */ + while (wait < 500) { + if ((prAdapter->u4PwrCtrlBlockCnt == 0) && + (prAdapter->fgIsFwOwn == TRUE) && + (drv_own_fail == FALSE)) { + DBGLOG(HAL, STATE, "************************\n"); + DBGLOG(HAL, STATE, "* Entered SDIO Suspend *\n"); + DBGLOG(HAL, STATE, "************************\n"); + DBGLOG(HAL, INFO, "wait = %d\n\n", wait); + break; + } + + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + /* Prevent that suspend without FW Own: + * Set Drv own has failed, and then Set FW Own is skipped + */ + if (prAdapter->fgIsFwOwn == FALSE) + drv_own_fail = FALSE; + else + drv_own_fail = TRUE; + /* For single core CPU, let hif_thread can be completed */ + usleep_range(1000, 3000); + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + + wait++; + } + + if (wait >= 500) { + DBGLOG(HAL, ERROR, "Set FW Own Timeout !!\n"); + return -EAGAIN; + } + + pm_caps = sdio_get_host_pm_caps(func); + func_id = sdio_func_id(func); + + /* Ask kernel keeping SDIO bus power-on */ + set_flag = MMC_PM_KEEP_POWER; + ret = sdio_set_host_pm_flags(func, set_flag); + if (ret) { + DBGLOG(HAL, ERROR, "set flag %d err %d\n", set_flag, ret); + DBGLOG(HAL, ERROR, + "%s: cannot remain alive(0x%X)\n", func_id, pm_caps); + return -ENOSYS; + } + + /* If wow enable, ask kernel accept SDIO IRQ in suspend mode */ + if (prGlueInfo->prAdapter->rWifiVar.ucWow && + prGlueInfo->prAdapter->rWowCtrl.fgWowEnable) { + set_flag = MMC_PM_WAKE_SDIO_IRQ; + ret = sdio_set_host_pm_flags(func, set_flag); + if (ret) { + DBGLOG(HAL, ERROR, "set flag %d err %d\n", set_flag, ret); + DBGLOG(HAL, ERROR, + "%s: cannot sdio wake-irq(0x%X)\n", func_id, pm_caps); + } + } + + glSdioSetState(&prGlueInfo->rHifInfo, SDIO_STATE_SUSPEND); + wlanReleaseAllTxCmdQueue(prGlueInfo->prAdapter); + + DBGLOG(HAL, STATE, "<==\n"); + return 0; +} + +static int mtk_sdio_pm_resume(struct device *pDev) +{ + struct sdio_func *func; + struct GLUE_INFO *prGlueInfo = NULL; + uint8_t count = 0; +#if CFG_SUPPORT_WOW_EINT + struct ADAPTER *prAdapter = NULL; +#endif + + DBGLOG(HAL, STATE, "==>\n"); + + if (kalIsResetting()) { + DBGLOG(HAL, WARN, "Chip resetting, skip\n"); + return -1; + } + + func = dev_to_sdio_func(pDev); + prGlueInfo = sdio_get_drvdata(func); + + halEnableInterrupt(prGlueInfo->prAdapter); + +#if CFG_SUPPORT_WOW_EINT + prAdapter = prGlueInfo->prAdapter; + + if (prAdapter->rWowlanDevNode.wowlan_irq != 0 && + atomic_read( + &(prAdapter->rWowlanDevNode.irq_enable_count)) == 1) { + DBGLOG(HAL, ERROR, "%s:disable WIFI IRQ:%d\n", __func__, + prAdapter->rWowlanDevNode.wowlan_irq); + atomic_dec(&(prAdapter->rWowlanDevNode.irq_enable_count)); + disable_irq_wake(prAdapter->rWowlanDevNode.wowlan_irq); + disable_irq(prAdapter->rWowlanDevNode.wowlan_irq); + } else { + DBGLOG(HAL, ERROR, "%s:irq_enable count:%d\n", __func__, + atomic_read( + &(prAdapter->rWowlanDevNode.irq_enable_count))); + } +#endif + + glSdioSetState(&prGlueInfo->rHifInfo, SDIO_STATE_PRE_RESUME); + + prGlueInfo->prAdapter->fgForceFwOwn = FALSE; + + halPreResumeCmd(prGlueInfo->prAdapter); + kalPerMonEnable(prGlueInfo); + wlan_fb_power_down = FALSE; + + while (prGlueInfo->rHifInfo.state != SDIO_STATE_LINK_UP) { + if (count > 500) { + DBGLOG(HAL, ERROR, "pre_resume timeout\n"); + break; + } + + kalUdelay(2000); + schedule(); + count++; + } + + wlanResumePmHandle(prGlueInfo); + + /* change to READY state to allow cfg80211 ops */ + glSdioSetState(&prGlueInfo->rHifInfo, SDIO_STATE_READY); + + /* Allow upper layers to call the device hard_start_xmit routine. */ + netif_tx_start_all_queues(prGlueInfo->prDevHandler); + + DBGLOG(HAL, STATE, "<==\n"); + + return 0; +} + +#if (CFG_SDIO_ASYNC_IRQ_AUTO_ENABLE == 1) +int mtk_sdio_async_irq_enable(struct sdio_func *func) +{ +#define SDIO_CCCR_IRQ_EXT 0x16 +#define SDIO_IRQ_EXT_SAI BIT(0) +#define SDIO_IRQ_EXT_EAI BIT(1) + unsigned char data = 0; + unsigned int quirks_bak; + int ret; + + /* Read CCCR 0x16 (interrupt extension)*/ + data = sdio_f0_readb(func, SDIO_CCCR_IRQ_EXT, &ret); + if (ret) { + DBGLOG(HAL, ERROR, "CCCR 0x%X read fail (%d).\n", SDIO_CCCR_IRQ_EXT, ret); + return FALSE; + } + /* Check CCCR capability status */ + if (!(data & SDIO_IRQ_EXT_SAI)) { + /* SAI = 0 */ + DBGLOG(HAL, ERROR, "No Async-IRQ capability.\n"); + return FALSE; + } else if (data & SDIO_IRQ_EXT_EAI) { + /* EAI = 1 */ + DBGLOG(INIT, INFO, "Async-IRQ enabled already.\n"); + return TRUE; + } + + /* Set EAI bit */ + data |= SDIO_IRQ_EXT_EAI; + + /* Enable capability to write CCCR */ + quirks_bak = func->card->quirks; + func->card->quirks |= MMC_QUIRK_LENIENT_FN0; + /* Write CCCR into card */ + sdio_f0_writeb(func, data, SDIO_CCCR_IRQ_EXT, &ret); + if (ret) { + DBGLOG(HAL, ERROR, "CCCR 0x%X write fail (%d).\n", SDIO_CCCR_IRQ_EXT, ret); + return FALSE; + } + func->card->quirks = quirks_bak; + + data = sdio_f0_readb(func, SDIO_CCCR_IRQ_EXT, &ret); + if (ret || !(data & SDIO_IRQ_EXT_EAI)) { + DBGLOG(HAL, ERROR, "CCCR 0x%X write fail (%d).\n", SDIO_CCCR_IRQ_EXT, ret); + return FALSE; + } + return TRUE; +} +#endif +#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 +*/ +/*----------------------------------------------------------------------------*/ +uint32_t glRegisterBus(probe_card pfProbe, remove_card pfRemove) +{ + int ret = 0; + + ASSERT(pfProbe); + ASSERT(pfRemove); + + + 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; + + 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 +} /* 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(struct GLUE_INFO *prGlueInfo, unsigned long ulCookie) +{ + struct GL_HIF_INFO *prHif = NULL; + uint8_t ucIdx; + + prHif = &prGlueInfo->rHifInfo; + + QUEUE_INITIALIZE(&prHif->rFreeQueue); + QUEUE_INITIALIZE(&prHif->rRxDeAggQueue); + QUEUE_INITIALIZE(&prHif->rRxFreeBufQueue); + +#if MTK_WCN_HIF_SDIO + /* prHif->prFuncInfo = ((MTK_WCN_HIF_SDIO_FUNCINFO *) u4Cookie); */ + prHif->prFuncInfo = prFunc; + prHif->cltCtx = *((unsigned long *) ulCookie); + mtk_wcn_hif_sdio_set_drvdata(prHif->cltCtx, prGlueInfo); + +#else + prHif->func = (struct sdio_func *)ulCookie; + + sdio_set_drvdata(prHif->func, prGlueInfo); + + SET_NETDEV_DEV(prGlueInfo->prDevHandler, &prHif->func->dev); +#endif + + /* Reset statistic counter */ + kalMemZero(&prHif->rStatCounter, sizeof(struct SDIO_STAT_COUNTER)); + + for (ucIdx = HIF_TXC_IDX_0; ucIdx < HIF_TXC_IDX_NUM; ucIdx++) + prHif->au4PendingTxDoneCount[ucIdx] = 0; + + spin_lock_init(&prHif->rStateLock); + spin_lock_init(&prHif->rSuspendLock); + + mutex_init(&prHif->rRxFreeBufQueMutex); + mutex_init(&prHif->rRxDeAggQueMutex); + + prHif->fgSkipRx = FALSE; + glSdioSetState(prHif, SDIO_STATE_READY); + prGlueInfo->u4InfType = MT_DEV_INF_SDIO; +} /* end of glSetHifInfo() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function clears hif related info. +* +* \param[in] prGlueInfo Pointer to glue info structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void glClearHifInfo(struct GLUE_INFO *prGlueInfo) +{ + /* P_GL_HIF_INFO_T prHif = NULL; */ + /* ASSERT(prGlueInfo); */ + /* prHif = &prGlueInfo->rHifInfo; */ +} /* 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) +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t glBusInit(void *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); + +#if (CFG_SDIO_1BIT_DATA_MODE == 1) + ret = sdio_disable_wide(func->card); + if (ret) + DBGLOG(HAL, ERROR, "glBusInit() Error at enabling SDIO 1-BIT data mode.\n"); + else + DBGLOG(HAL, INFO, "glBusInit() SDIO 1-BIT data mode is working.\n"); +#endif + +#if (CFG_SDIO_ASYNC_IRQ_AUTO_ENABLE == 1) + ret = mtk_sdio_async_irq_enable(func); + if (ret == FALSE) + DBGLOG(HAL, ERROR, "Async-IRQ auto-enable fail.\n"); + else + DBGLOG(INIT, INFO, "Async-IRQ is enabled.\n"); +#endif + + ret = sdio_set_block_size(func, 512); + sdio_release_host(func); + +#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(void *pvData) +{ +} /* end of glBusRelease() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setup bus interrupt operation and interrupt handler for os. +* +* \param[in] pvData A pointer to struct net_device. +* \param[in] pfnIsr A pointer to interrupt handler function. +* \param[in] pvCookie Private data for pfnIsr function. +* +* \retval WLAN_STATUS_SUCCESS if success +* NEGATIVE_VALUE if fail +*/ +/*----------------------------------------------------------------------------*/ +int32_t glBusSetIrq(void *pvData, void *pfnIsr, void *pvCookie) +{ + int ret = 0; + + struct net_device *prNetDevice = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct GL_HIF_INFO *prHifInfo = NULL; + + ASSERT(pvData); + if (!pvData) + return -1; + + prNetDevice = (struct net_device *)pvData; + prGlueInfo = (struct GLUE_INFO *) pvCookie; + ASSERT(prGlueInfo); + if (!prGlueInfo) + return -1; + + prHifInfo = &prGlueInfo->rHifInfo; + +#if (MTK_WCN_HIF_SDIO == 0) + sdio_claim_host(prHifInfo->func); + ret = sdio_claim_irq(prHifInfo->func, mtk_sdio_interrupt); + sdio_release_host(prHifInfo->func); +#else + mtk_wcn_hif_sdio_enable_irq(prHifInfo->cltCtx, TRUE); +#endif + +#if CFG_SUPPORT_WOW_EINT + mtk_sdio_eint_interrupt(prHifInfo->func); +#endif + + prHifInfo->fgIsPendingInt = FALSE; + + prHifInfo->u4IntLogIdx = 0; + prHifInfo->ucIntLogEntry = 0; + + 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(void *pvData, void *pvCookie) +{ + struct net_device *prNetDevice = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct GL_HIF_INFO *prHifInfo = NULL; + + ASSERT(pvData); + if (!pvData) { + return; + } + prNetDevice = (struct net_device *)pvData; + prGlueInfo = (struct GLUE_INFO *) pvCookie; + ASSERT(prGlueInfo); + if (!prGlueInfo) { + return; + } + + prHifInfo = &prGlueInfo->rHifInfo; +#if (MTK_WCN_HIF_SDIO == 0) + sdio_claim_host(prHifInfo->func); + sdio_release_irq(prHifInfo->func); + sdio_release_host(prHifInfo->func); +#else + mtk_wcn_hif_sdio_enable_irq(prHifInfo->cltCtx, FALSE); +#endif + +#if CFG_SUPPORT_WOW_EINT + mtk_sdio_eint_free_irq(prHifInfo->func); +#endif + +} /* end of glBusreeIrq() */ + +u_int8_t glIsReadClearReg(uint32_t u4Address) +{ + switch (u4Address) { + case MCR_WHISR: + case MCR_WASR: + case MCR_D2HRM0R: + case MCR_D2HRM1R: + case MCR_WTQCR0: + case MCR_WTQCR1: + case MCR_WTQCR2: + case MCR_WTQCR3: + case MCR_WTQCR4: + case MCR_WTQCR5: + case MCR_WTQCR6: + case MCR_WTQCR7: + return TRUE; + + default: + return FALSE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Read a 32-bit device register of SDIO host driver domian +* +* \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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevRegRead(IN struct GLUE_INFO *prGlueInfo, IN uint32_t u4Register, OUT uint32_t *pu4Value) +{ + int ret = 0; + uint8_t ucRetryCount = 0; + + ASSERT(prGlueInfo); + ASSERT(pu4Value); + + do { +#if MTK_WCN_HIF_SDIO + ret = mtk_wcn_hif_sdio_readl(prGlueInfo->rHifInfo.cltCtx, u4Register, (uint32_t *) pu4Value); +#else + sdio_claim_host(prGlueInfo->rHifInfo.func); + *pu4Value = sdio_readl(prGlueInfo->rHifInfo.func, u4Register, &ret); + sdio_release_host(prGlueInfo->rHifInfo.func); +#endif + + if (ret || ucRetryCount) { + /* DBGLOG(HAL, ERROR, + * ("sdio_readl() addr: 0x%08x value: 0x%08x status: %x retry: %u\n", + * u4Register, (unsigned int)*pu4Value, (unsigned int)ret, ucRetryCount)); + */ + + if (glIsReadClearReg(u4Register) && (ucRetryCount == 0)) { + /* Read Snapshot CR instead */ + u4Register = MCR_WSR; + } + } + + ucRetryCount++; + if (ucRetryCount > HIF_SDIO_ACCESS_RETRY_LIMIT) + break; + } while (ret); + + if (ret) { + kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, + HIF_SDIO_ERR_DESC_STR "sdio_readl() reports error: %x retry: %u", ret, ucRetryCount); + DBGLOG(HAL, ERROR, "sdio_readl() reports error: %x retry: %u\n", ret, ucRetryCount); + } + + return (ret) ? FALSE : TRUE; +} /* end of kalDevRegRead() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Read a 32-bit device register of chip firmware register domain +* +* \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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevRegRead_mac(IN struct GLUE_INFO *prGlueInfo, IN uint32_t u4Register, OUT uint32_t *pu4Value) +{ + uint32_t value; + uint32_t u4Time, u4Current; + uint8_t ucResult;/* For Unchecked return value*/ + + /* progrqm h2d mailbox0 as interested register address */ + ucResult = kalDevRegWrite(prGlueInfo, MCR_H2DSM0R, u4Register); + + /* set h2d interrupt to notify firmware. bit16 */ + ucResult = kalDevRegWrite(prGlueInfo, MCR_WSICR, + SDIO_MAILBOX_FUNC_READ_REG_IDX); + + /* polling interrupt status asserted. bit16 */ + + /* first, disable interrupt enable for SDIO_MAILBOX_FUNC_READ_REG_IDX */ + ucResult = kalDevRegRead(prGlueInfo, MCR_WHIER, &value); + ucResult = kalDevRegWrite(prGlueInfo, MCR_WHIER, + (value & ~SDIO_MAILBOX_FUNC_READ_REG_IDX)); + + u4Time = (uint32_t) kalGetTimeTick(); + + do { + /* check bit16 of WHISR assert for read register response */ + ucResult = kalDevRegRead(prGlueInfo, MCR_WHISR, &value); + + if (value & SDIO_MAILBOX_FUNC_READ_REG_IDX) { + /* read d2h mailbox0 for interested register address */ + ucResult = kalDevRegRead(prGlueInfo, + MCR_D2HRM0R, &value); + + if (value != u4Register) { + DBGLOG(HAL, ERROR, "ERROR! kalDevRegRead_mac():register address mis-match"); + DBGLOG(HAL, ERROR, "(u4Register = 0x%08x, reported register = 0x%08x)\n", + u4Register, value); + return FALSE; + } + + /* read d2h mailbox1 for the value of the register */ + ucResult = kalDevRegRead(prGlueInfo, + MCR_D2HRM1R, &value); + *pu4Value = value; + return TRUE; + } + + /* timeout exceeding check */ + u4Current = (uint32_t) kalGetTimeTick(); + + if (((u4Current > u4Time) && ((u4Current - u4Time) > HIF_SDIO_INTERRUPT_RESPONSE_TIMEOUT)) + || (u4Current < u4Time && ((u4Current + (0xFFFFFFFF - u4Time)) + > HIF_SDIO_INTERRUPT_RESPONSE_TIMEOUT))) { + DBGLOG(HAL, ERROR, "ERROR: kalDevRegRead_mac(): response timeout\n"); + return FALSE; + } + + /* Response packet is not ready */ + kalUdelay(50); + } while (1); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write a 32-bit device register of SDIO driver domian +* +* \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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevRegWrite(IN struct GLUE_INFO *prGlueInfo, IN uint32_t u4Register, IN uint32_t u4Value) +{ + int ret = 0; + uint8_t ucRetryCount = 0; + + ASSERT(prGlueInfo); + + do { +#if MTK_WCN_HIF_SDIO + ret = mtk_wcn_hif_sdio_writel(prGlueInfo->rHifInfo.cltCtx, u4Register, u4Value); +#else + sdio_claim_host(prGlueInfo->rHifInfo.func); + sdio_writel(prGlueInfo->rHifInfo.func, u4Value, u4Register, &ret); + sdio_release_host(prGlueInfo->rHifInfo.func); +#endif + + if (ret || ucRetryCount) { + /* DBGLOG(HAL, ERROR, + * ("sdio_writel() addr: 0x%x status: %x retry: %u\n", u4Register, + * ret, ucRetryCount)); + */ + } + + ucRetryCount++; + if (ucRetryCount > HIF_SDIO_ACCESS_RETRY_LIMIT) + break; + + } while (ret); + + if (ret) { + kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, + HIF_SDIO_ERR_DESC_STR "sdio_writel() reports error: %x retry: %u", ret, ucRetryCount); + DBGLOG(HAL, ERROR, "sdio_writel() reports error: %x retry: %u\n", ret, ucRetryCount); + } + + return (ret) ? FALSE : TRUE; +} /* end of kalDevRegWrite() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write a 32-bit device register of chip firmware register domain +* +* \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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevRegWrite_mac(IN struct GLUE_INFO *prGlueInfo, IN uint32_t u4Register, IN uint32_t u4Value) +{ + uint32_t value; + uint32_t u4Time, u4Current; + uint8_t ucResult; /* For Unchecked return value*/ + + /* progrqm h2d mailbox0 as interested register address */ + ucResult = kalDevRegWrite(prGlueInfo, MCR_H2DSM0R, u4Register); + + /* progrqm h2d mailbox1 as the value to write */ + ucResult = kalDevRegWrite(prGlueInfo, MCR_H2DSM1R, u4Value); + + /* set h2d interrupt to notify firmware bit17 */ + ucResult = kalDevRegWrite(prGlueInfo, MCR_WSICR, + SDIO_MAILBOX_FUNC_WRITE_REG_IDX); + + /* polling interrupt status asserted. bit17 */ + + /* first, disable interrupt enable for SDIO_MAILBOX_FUNC_WRITE_REG_IDX */ + ucResult = kalDevRegRead(prGlueInfo, MCR_WHIER, &value); + ucResult = kalDevRegWrite(prGlueInfo, MCR_WHIER, + (value & ~SDIO_MAILBOX_FUNC_WRITE_REG_IDX)); + + u4Time = (uint32_t) kalGetTimeTick(); + + do { + /* check bit17 of WHISR assert for response */ + ucResult = kalDevRegRead(prGlueInfo, MCR_WHISR, &value); + + if (value & SDIO_MAILBOX_FUNC_WRITE_REG_IDX) { + /* read d2h mailbox0 for interested register address */ + ucResult = kalDevRegRead(prGlueInfo, + MCR_D2HRM0R, &value); + + if (value != u4Register) { + DBGLOG(HAL, ERROR, "ERROR! kalDevRegWrite_mac():register address mis-match"); + DBGLOG(HAL, ERROR, "(u4Register = 0x%08x, reported register = 0x%08x)\n", + u4Register, value); + return FALSE; + } + return TRUE; + } + + /* timeout exceeding check */ + u4Current = (uint32_t) kalGetTimeTick(); + + if (((u4Current > u4Time) && ((u4Current - u4Time) > HIF_SDIO_INTERRUPT_RESPONSE_TIMEOUT)) + || (u4Current < u4Time && ((u4Current + (0xFFFFFFFF - u4Time)) + > HIF_SDIO_INTERRUPT_RESPONSE_TIMEOUT))) { + DBGLOG(HAL, ERROR, "ERROR: kalDevRegWrite_mac(): response timeout\n"); + return FALSE; + } + + /* Response packet is not ready */ + kalUdelay(50); + } while (1); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t +kalDevPortRead(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port, IN uint32_t u4Len, OUT uint8_t *pucBuf, IN uint32_t u4ValidOutBufSize) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + uint8_t *pucDst = NULL; + int count = u4Len; + int ret = 0; + int bNum = 0; + +#if (MTK_WCN_HIF_SDIO == 0) + struct sdio_func *prSdioFunc = NULL; +#endif + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + ASSERT(pucBuf); + pucDst = pucBuf; + + ASSERT(u4Len <= u4ValidOutBufSize); + +#if (MTK_WCN_HIF_SDIO == 0) + prSdioFunc = prHifInfo->func; + + ASSERT(prSdioFunc->cur_blksize > 0); + + 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); + } + + 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, (uint32_t *) pucDst, + ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz) * bNum); + } else { + ret = mtk_wcn_hif_sdio_read_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (uint32_t *) pucDst, count); + } +#endif + + if (ret) { + kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_readsb() reports error: %d", ret); + + DBGLOG(HAL, ERROR, "\n"); + DBGLOG(HAL, ERROR, "\nSDIO BUS ERROR: "); + DBGLOG(HAL, ERROR, "sdio_readsb() reports error: %d\n", ret); + DBGLOG(HAL, ERROR, "\n"); + } + + 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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t +kalDevPortWrite(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port, IN uint32_t u4Len, IN uint8_t *pucBuf, IN uint32_t u4ValidInBufSize) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + uint8_t *pucSrc = NULL; + int count = u4Len; + int ret = 0; + int bNum = 0; + +#if (MTK_WCN_HIF_SDIO == 0) + struct sdio_func *prSdioFunc = NULL; +#endif + + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + ASSERT(pucBuf); + pucSrc = pucBuf; + + ASSERT(u4Len <= u4ValidInBufSize); + +#if (MTK_WCN_HIF_SDIO == 0) + prSdioFunc = prHifInfo->func; + ASSERT(prSdioFunc->cur_blksize > 0); + + 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); + } + + 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, + (uint32_t *) pucSrc, ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz) * bNum); + } else { /* byte mode */ + ret = mtk_wcn_hif_sdio_write_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (uint32_t *) pucSrc, count); + } +#endif + + if (ret) { + kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, + HIF_SDIO_ERR_DESC_STR "sdio_writesb() reports error: %d", ret); + + DBGLOG(HAL, ERROR, "\n"); + DBGLOG(HAL, ERROR, "\nSDIO BUS ERROR: "); + DBGLOG(HAL, ERROR, "sdio_writesb() reports error: %d\n", ret); + DBGLOG(HAL, ERROR, "\n"); + } + + return (ret) ? FALSE : TRUE; +} /* end of kalDevPortWrite() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read interrupt status from hardware +* +* @param prAdapter pointer to the Adapter handler +* @param the interrupts +* +* @return N/A +* +*/ +/*----------------------------------------------------------------------------*/ +void kalDevReadIntStatus(IN struct ADAPTER *prAdapter, OUT uint32_t *pu4IntStatus) +{ +#if CFG_SDIO_INTR_ENHANCE + struct ENHANCE_MODE_DATA_STRUCT *prSDIOCtrl; + struct SDIO_STAT_COUNTER *prStatCounter; + u_int8_t fgPendingInt = FALSE; + + SDIO_TIME_INTERVAL_DEC(); + + DEBUGFUNC("nicSDIOReadIntStatus"); + + ASSERT(prAdapter); + ASSERT(pu4IntStatus); + + prSDIOCtrl = prAdapter->prGlueInfo->rHifInfo.prSDIOCtrl; + ASSERT(prSDIOCtrl); + + prStatCounter = &prAdapter->prGlueInfo->rHifInfo.rStatCounter; + + /* There are pending interrupt to be handled */ + if (prAdapter->prGlueInfo->rHifInfo.fgIsPendingInt) { + prAdapter->prGlueInfo->rHifInfo.fgIsPendingInt = FALSE; + fgPendingInt = TRUE; + } + else { + SDIO_REC_TIME_START(); + HAL_PORT_RD(prAdapter, MCR_WHISR, sizeof(struct ENHANCE_MODE_DATA_STRUCT), + (uint8_t *) prSDIOCtrl, sizeof(struct ENHANCE_MODE_DATA_STRUCT)); + SDIO_REC_TIME_END(); + SDIO_ADD_TIME_INTERVAL(prStatCounter->u4IntReadTime); + prStatCounter->u4IntReadCnt++; + } + + prStatCounter->u4IntCnt++; + + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + *pu4IntStatus = 0; + return; + } + + halProcessEnhanceInterruptStatus(prAdapter); + + if (prSDIOCtrl->u4WHISR) { + halRecIntLog(prAdapter, prSDIOCtrl); + if (fgPendingInt) + halTagIntLog(prAdapter, SDIO_INT_RX_ENHANCE); + } + + *pu4IntStatus = prSDIOCtrl->u4WHISR; +#else + HAL_MCR_RD(prAdapter, MCR_WHISR, pu4IntStatus); +#endif /* CFG_SDIO_INTR_ENHANCE */ + + if (*pu4IntStatus & ~(WHIER_DEFAULT | WHIER_FW_OWN_BACK_INT_EN)) { + DBGLOG(INTR, WARN, + "Un-handled HISR %lx, HISR = %lx (HIER:0x%lx)\n", + (*pu4IntStatus & ~WHIER_DEFAULT), *pu4IntStatus, + WHIER_DEFAULT); + *pu4IntStatus &= WHIER_DEFAULT; + } +} /* end of nicSDIOReadIntStatus() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevWriteWithSdioCmd52(IN struct GLUE_INFO *prGlueInfo, IN uint32_t u4Addr, IN uint8_t ucData) +{ + int ret = 0; + +#if (MTK_WCN_HIF_SDIO == 0) + sdio_claim_host(prGlueInfo->rHifInfo.func); + sdio_writeb(prGlueInfo->rHifInfo.func, ucData, u4Addr, &ret); + 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\n", ret); + } + + return (ret) ? FALSE : TRUE; + +} /* end of kalDevWriteWithSdioCmd52() */ + +void glSetPowerState(IN struct GLUE_INFO *prGlueInfo, IN uint32_t ePowerMode) +{ +} +#ifdef _SDIO_RING +u_int8_t kalDevWriteData(IN struct GLUE_INFO *prGlueInfo, +IN struct MSDU_INFO *prMsduInfo) +{ + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + uint8_t *pucOutputBuf = (uint8_t *) NULL; + uint32_t u4PaddingLength; + struct sk_buff *skb; + uint8_t *pucBuf; + uint32_t u4Length; + uint8_t ucTC; + uint32_t head; + uint32_t data_len; + + SDIO_TIME_INTERVAL_DEC(); + + skb = (struct sk_buff *)prMsduInfo->prPacket; + pucBuf = skb->data; + u4Length = skb->len; + ucTC = prMsduInfo->ucTC; + + head = prHifInfo->ring_head; + + pucOutputBuf = prHifInfo->ring_buffer[head]; + data_len = prHifInfo->ring_len[head]; + + if ((data_len + ALIGN_4(u4Length)) > SDIO_RING_BUF_LEN) { + if (kalDevKickData(prGlueInfo) == FALSE) + return FALSE; + head = prHifInfo->ring_head; + pucOutputBuf = prHifInfo->ring_buffer[head]; + data_len = prHifInfo->ring_len[head]; + } + if (prHifInfo->ring_PLE[head] == + prAdapter->nicTxReousrce.u4DataTotalResourcePle) { + if (kalDevKickData(prGlueInfo) == FALSE) + return FALSE; + head = prHifInfo->ring_head; + pucOutputBuf = prHifInfo->ring_buffer[head]; + data_len = prHifInfo->ring_len[head]; + } + + SDIO_REC_TIME_START(); + memcpy(pucOutputBuf + data_len, pucBuf, u4Length); + SDIO_REC_TIME_END(); + SDIO_ADD_TIME_INTERVAL(prHifInfo->rStatCounter.u4TxDataCpTime); + data_len += u4Length; + + u4PaddingLength = (ALIGN_4(u4Length) - u4Length); + if (u4PaddingLength) { + memset(pucOutputBuf + data_len, 0, u4PaddingLength); + data_len += u4PaddingLength; + } + + prHifInfo->ring_len[head] = data_len; + prHifInfo->ring_PSE[head] += + nicTxGetPageCount(prAdapter, + prMsduInfo->u2FrameLength, FALSE); + prHifInfo->ring_PLE[head]++; + + SDIO_REC_TIME_START(); + if (!prMsduInfo->pfTxDoneHandler) + kalFreeTxMsdu(prAdapter, prMsduInfo); + SDIO_REC_TIME_END(); + SDIO_ADD_TIME_INTERVAL + (prHifInfo->rStatCounter.u4TxDataFreeTime); + + /* Update pending Tx done count */ + halUpdateTxDonePendingCount + (prAdapter, TRUE, ucTC, prMsduInfo->u2FrameLength); + + prHifInfo->rStatCounter.u4DataPktWriteCnt++; + + return TRUE; +} +u_int8_t kalDevKickData(IN struct GLUE_INFO *prGlueInfo) +{ + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + uint32_t head; + uint32_t *data_len; + u_int8_t ret; + + + head = prHifInfo->ring_head; + data_len = &prHifInfo->ring_len[head]; + + if (*data_len == 0) { + kalSetTxEvent2Hif(prGlueInfo); + kalSetEvent(prGlueInfo); + + return FALSE; + } + ret = sdio_ring_push(prGlueInfo); + + if (ret == TRUE) + kalSetEvent(prGlueInfo); + + kalSetTxEvent2Hif(prGlueInfo); + + return ret; +} +#else +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write data to device +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] prMsduInfo msdu info +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevWriteData(IN struct GLUE_INFO *prGlueInfo, IN struct MSDU_INFO *prMsduInfo) +{ + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + struct TX_CTRL *prTxCtrl; + uint8_t *pucOutputBuf = (uint8_t *) NULL; + uint32_t u4PaddingLength; + struct sk_buff *skb; + uint8_t *pucBuf; + uint32_t u4Length; + uint8_t ucTC; + + SDIO_TIME_INTERVAL_DEC(); + + skb = (struct sk_buff *)prMsduInfo->prPacket; + pucBuf = skb->data; + u4Length = skb->len; + ucTC = prMsduInfo->ucTC; + + prTxCtrl = &prAdapter->rTxCtrl; + pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; + + if (prTxCtrl->u4WrIdx + ALIGN_4(u4Length) > prAdapter->u4CoalescingBufCachedSize) { + if ((prAdapter->u4CoalescingBufCachedSize - ALIGN_4(prTxCtrl->u4WrIdx)) >= HIF_TX_TERMINATOR_LEN) { + /* fill with single dword of zero as TX-aggregation termination */ + *(uint32_t *) (&((pucOutputBuf)[ALIGN_4(prTxCtrl->u4WrIdx)])) = 0; + } + + if (HAL_TEST_FLAG(prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { + if (kalDevPortWrite(prGlueInfo, MCR_WTDR1, prTxCtrl->u4WrIdx, + pucOutputBuf, prAdapter->u4CoalescingBufCachedSize) == FALSE) { + HAL_SET_FLAG(prAdapter, ADAPTER_FLAG_HW_ERR); + fgIsBusAccessFailed = TRUE; + } + prHifInfo->rStatCounter.u4DataPortWriteCnt++; + } + prTxCtrl->u4WrIdx = 0; + } + + SDIO_REC_TIME_START(); + memcpy(pucOutputBuf + prTxCtrl->u4WrIdx, pucBuf, u4Length); + SDIO_REC_TIME_END(); + SDIO_ADD_TIME_INTERVAL(prHifInfo->rStatCounter.u4TxDataCpTime); + + prTxCtrl->u4WrIdx += u4Length; + + u4PaddingLength = (ALIGN_4(u4Length) - u4Length); + if (u4PaddingLength) { + memset(pucOutputBuf + prTxCtrl->u4WrIdx, 0, u4PaddingLength); + prTxCtrl->u4WrIdx += u4PaddingLength; + } + + SDIO_REC_TIME_START(); + if (!prMsduInfo->pfTxDoneHandler) + kalFreeTxMsdu(prAdapter, prMsduInfo); + SDIO_REC_TIME_END(); + SDIO_ADD_TIME_INTERVAL(prHifInfo->rStatCounter.u4TxDataFreeTime); + + /* Update pending Tx done count */ + halUpdateTxDonePendingCount(prAdapter, TRUE, ucTC, + prMsduInfo->u2FrameLength); + + prHifInfo->rStatCounter.u4DataPktWriteCnt++; + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Kick Tx data to device +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevKickData(IN struct GLUE_INFO *prGlueInfo) +{ + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + struct TX_CTRL *prTxCtrl; + uint8_t *pucOutputBuf = (uint8_t *) NULL; + + prTxCtrl = &prAdapter->rTxCtrl; + pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; + + if (prTxCtrl->u4WrIdx == 0) + return FALSE; + + if ((prAdapter->u4CoalescingBufCachedSize - ALIGN_4(prTxCtrl->u4WrIdx)) >= HIF_TX_TERMINATOR_LEN) { + /* fill with single dword of zero as TX-aggregation termination */ + *(uint32_t *) (&((pucOutputBuf)[ALIGN_4(prTxCtrl->u4WrIdx)])) = 0; + } + + if (HAL_TEST_FLAG(prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { + if (kalDevPortWrite(prGlueInfo, MCR_WTDR1, prTxCtrl->u4WrIdx, + pucOutputBuf, prAdapter->u4CoalescingBufCachedSize) == FALSE) { + HAL_SET_FLAG(prAdapter, ADAPTER_FLAG_HW_ERR); + fgIsBusAccessFailed = TRUE; + } + prHifInfo->rStatCounter.u4DataPortWriteCnt++; + } + + prTxCtrl->u4WrIdx = 0; + + prHifInfo->rStatCounter.u4DataPortKickCnt++; + + return TRUE; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write command to device +* +* \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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevWriteCmd(IN struct GLUE_INFO *prGlueInfo, IN struct CMD_INFO *prCmdInfo, IN uint8_t ucTC) +{ + struct ADAPTER *prAdapter = prGlueInfo->prAdapter; +/* P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; */ + struct TX_CTRL *prTxCtrl; + uint8_t *pucOutputBuf = (uint8_t *) NULL; + uint16_t u2OverallBufferLength = 0; +/* WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; */ + + prTxCtrl = &prAdapter->rTxCtrl; + pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; + + if (TFCB_FRAME_PAD_TO_DW(prCmdInfo->u4TxdLen + prCmdInfo->u4TxpLen) > + prAdapter->u4CoalescingBufCachedSize) { + DBGLOG(HAL, ERROR, "Command TX buffer underflow!\n"); + return FALSE; + } + + if (prCmdInfo->u4TxdLen) { + memcpy((pucOutputBuf + u2OverallBufferLength), prCmdInfo->pucTxd, prCmdInfo->u4TxdLen); + u2OverallBufferLength += prCmdInfo->u4TxdLen; + } + + if (prCmdInfo->u4TxpLen) { + memcpy((pucOutputBuf + u2OverallBufferLength), prCmdInfo->pucTxp, prCmdInfo->u4TxpLen); + u2OverallBufferLength += prCmdInfo->u4TxpLen; + } + + memset(pucOutputBuf + u2OverallBufferLength, 0, + (TFCB_FRAME_PAD_TO_DW(u2OverallBufferLength) - u2OverallBufferLength)); + + if ((prAdapter->u4CoalescingBufCachedSize - ALIGN_4(u2OverallBufferLength)) >= HIF_TX_TERMINATOR_LEN) { + /* fill with single dword of zero as TX-aggregation termination */ + *(uint32_t *) (&((pucOutputBuf)[ALIGN_4(u2OverallBufferLength)])) = 0; + } + if (HAL_TEST_FLAG(prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { + if (kalDevPortWrite(prGlueInfo, MCR_WTDR1, TFCB_FRAME_PAD_TO_DW(u2OverallBufferLength), + pucOutputBuf, prAdapter->u4CoalescingBufCachedSize) == FALSE) { + HAL_SET_FLAG(prAdapter, ADAPTER_FLAG_HW_ERR); + fgIsBusAccessFailed = TRUE; + } + prGlueInfo->rHifInfo.rStatCounter.u4CmdPortWriteCnt++; + } + + /* Update pending Tx done count */ + halUpdateTxDonePendingCount(prAdapter, TRUE, ucTC, + (prCmdInfo->u4TxdLen + prCmdInfo->u4TxpLen)); + + prGlueInfo->rHifInfo.rStatCounter.u4CmdPktWriteCnt++; + return TRUE; +} + +void glGetDev(void *ctx, struct device **dev) +{ +#if MTK_WCN_HIF_SDIO + mtk_wcn_hif_sdio_get_dev(*((unsigned long *) ctx), dev); +#else + *dev = &((struct sdio_func *)ctx)->dev; +#endif +} + +void glGetHifDev(struct GL_HIF_INFO *prHif, struct device **dev) +{ +#if MTK_WCN_HIF_SDIO + mtk_wcn_hif_sdio_get_dev(prHif->cltCtx, dev); +#else + *dev = &(prHif->func->dev); +#endif +} + +u_int8_t glWakeupSdio(struct GLUE_INFO *prGlueInfo) +{ + u_int8_t fgSuccess = TRUE; + +#if (HIF_SDIO_SUPPORT_GPIO_SLEEP_MODE && MTK_WCN_HIF_SDIO) + #if KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE + if (mtk_wcn_stp_sdio_wake_up_ctrl(prGlueInfo->rHifInfo.cltCtx) != 0) + #else + if (mtk_wcn_hif_sdio_wake_up_ctrl(prGlueInfo->rHifInfo.cltCtx) != 0) + #endif + fgSuccess = FALSE; +#endif + + return fgSuccess; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function set SDIO state +* +* \param[in] prHifInfo Pointer to the GL_HIF_INFO_T structure +* \param[in] state Specify TC index +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +void glSdioSetState(struct GL_HIF_INFO *prHifInfo, enum sdio_state state) +{ + unsigned long flags; + + spin_lock_irqsave(&prHifInfo->rStateLock, flags); + prHifInfo->state = state; + spin_unlock_irqrestore(&prHifInfo->rStateLock, flags); + DBGLOG(HAL, STATE, "sdio state:%d\n", state); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function get SDIO state +* +* \param[in] prHifInfo Pointer to the GL_HIF_INFO_T structure +* \param[in] state Specify TC index +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +enum sdio_state glSdioGetState(struct GL_HIF_INFO *prHifInfo) +{ + return prHifInfo->state; +} + +#if (CFG_CHIP_RESET_SUPPORT == 1) && (MTK_WCN_HIF_SDIO == 0) +void kalRemoveProbe(IN struct GLUE_INFO *prGlueInfo) +{ + struct mmc_host *host; + + ASSERT(prGlueInfo); + + host = prGlueInfo->rHifInfo.func->card->host; + host->rescan_entered = 0; + + /* clear trx fifo */ + DBGLOG(INIT, STATE, "[SER][L0] mmc_remove_host\n"); + mmc_remove_host(prGlueInfo->rHifInfo.func->card->host); + + DBGLOG(INIT, STATE, "[SER][L0] mmc_add_host\n"); + mmc_add_host(host); + +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/sdio_ring.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/sdio_ring.c new file mode 100644 index 0000000000000..1dfa3c7ff73f0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/sdio_ring.c @@ -0,0 +1,368 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** +*[File] sdio_ring.c +*[Version] v1.0 +*[Revision Date] 2018-09-03 +*[Author] +*[Description] +* The program provides SDIO HIF ring buffer architecture +*[Copyright] +* Copyright (C) 2018 MediaTek Incorporation. All Rights Reserved. +******************************************************************************/ + + +/******************************************************************************* +* C O M P I L E 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 "precomp.h" +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static wait_queue_head_t waitq_sdio_ring; +static unsigned long ulFlag; +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +int sdio_ring_thread(void *data) +{ + int ret; + struct GL_HIF_INFO *prHif = NULL; + uint32_t i; + struct net_device *dev = data; + struct GLUE_INFO *prGlueInfo = *((struct GLUE_INFO **) + netdev_priv(dev)); + + set_user_nice(current, + prGlueInfo->prAdapter->rWifiVar.cThreadNice); + DBGLOG(INIT, INFO, "%s:%u starts running...\n", + KAL_GET_CURRENT_THREAD_NAME(), + KAL_GET_CURRENT_THREAD_ID()); + + while (TRUE) { + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(INIT, INFO, + "%s:%u should stop now...\n", + KAL_GET_CURRENT_THREAD_NAME(), + KAL_GET_CURRENT_THREAD_ID()); + break; + } + do { + ret = wait_event_interruptible(waitq_sdio_ring, + ((ulFlag & BIT(SDIO_RING_TX_BIT)) != 0)); + } while (ret != 0); + if (test_and_clear_bit(SDIO_RING_TX_BIT, &ulFlag)) + nicTxMsduQueueMthread(prGlueInfo->prAdapter); + } + + /* Resource destroy */ + prHif = &prGlueInfo->rHifInfo; + for (i = 0; i < SDIO_RING_SIZE; i++) { + kalReleaseIOBuffer(prHif->ring_buffer[i], + SDIO_RING_BUF_LEN); + prHif->ring_buffer[i] = NULL; + } + prHif->sdio_ring_thread = NULL; + + DBGLOG(INIT, INFO, "%s:%u stopped!\n", + KAL_GET_CURRENT_THREAD_NAME(), + KAL_GET_CURRENT_THREAD_ID()); + + return 0; +} + +uint32_t Initial_sdio_ring(struct GLUE_INFO *prGlueInfo) +{ + struct ADAPTER *prAdapter; + struct GL_HIF_INFO *prHif = NULL; + uint32_t i; + + prAdapter = prGlueInfo->prAdapter; + prHif = &prGlueInfo->rHifInfo; + + for (i = 0; i < SDIO_RING_SIZE; i++) { + prHif->ring_buffer[i] = (uint8_t *)kalAllocateIOBuffer( + SDIO_RING_BUF_LEN); + if (prHif->ring_buffer[i] == NULL) { + DBGLOG(INIT, ERROR, + "Could not allocate %u bytes for SDIO ring buffer[%u].\n", + SDIO_RING_BUF_LEN, i); + return FALSE; + } + } + kalMemSet(&prHif->ring_len, 0, sizeof(uint32_t)*SDIO_RING_SIZE); + kalMemSet(&prHif->ring_PSE, 0, sizeof(uint32_t)*SDIO_RING_SIZE); + kalMemSet(&prHif->ring_PLE, 0, sizeof(uint32_t)*SDIO_RING_SIZE); + prHif->ring_head = 0; + prHif->ring_tail = 0; + ulFlag = 0; + prAdapter->rQM.fgTcResourcePostHandle = 1; + init_waitqueue_head(&waitq_sdio_ring); + + prHif->sdio_ring_thread = kthread_run(sdio_ring_thread, + prGlueInfo->prDevHandler, "sdio_ring_thread"); + if (prGlueInfo->prAdapter->rWifiVar.ucThreadPriority > 0) { + struct sched_param param = { + .sched_priority = prGlueInfo->prAdapter + ->rWifiVar.ucThreadPriority + }; + sched_setscheduler(prHif->sdio_ring_thread, + prGlueInfo->prAdapter->rWifiVar + .ucThreadScheduling, ¶m); + } + + return TRUE; +} +uint8_t sdio_ring_push(struct GLUE_INFO *prGlueInfo) +{ + struct ADAPTER *prAdapter; + struct GL_HIF_INFO *prHif = NULL; + uint32_t head; + uint32_t tail; + uint32_t data_len; + uint8_t *buf; + + prAdapter = prGlueInfo->prAdapter; + prHif = &prGlueInfo->rHifInfo; + + head = prHif->ring_head; + tail = prHif->ring_tail; + buf = prHif->ring_buffer[head]; + data_len = prHif->ring_len[head]; + + + + if (((head + 1) % SDIO_RING_SIZE) != tail) { + if ((SDIO_RING_BUF_LEN - ALIGN_4(data_len)) >= + HIF_TX_TERMINATOR_LEN) { + /* fill with single dword of zero as */ + /* TX-aggregation termination */ + *(uint32_t *) (&((buf)[ALIGN_4(data_len)])) = 0; + } + + head = ((head + 1) % SDIO_RING_SIZE); + prHif->ring_head = head; + + return TRUE; + } + + return FALSE; +} +uint8_t sdio_ring_pop(struct GLUE_INFO *prGlueInfo) +{ + struct ADAPTER *prAdapter; + struct GL_HIF_INFO *prHif = NULL; + uint32_t head; + uint32_t tail; + + prAdapter = prGlueInfo->prAdapter; + prHif = &prGlueInfo->rHifInfo; + + head = prHif->ring_head; + tail = prHif->ring_tail; + + + + if (tail != head) { + tail = ((tail + 1) % SDIO_RING_SIZE); + prHif->ring_tail = tail; + + return TRUE; + } + + return FALSE; +} +static u_int8_t +Acquire_All_Resource(struct ADAPTER *prAdapter, +u_int32_t PLE_cnt, u_int32_t PSE_cnt) +{ + uint8_t i; + u_int32_t total_PSE, total_PLE; + struct TX_CTRL *prTxCtrl; + struct TX_TCQ_STATUS *prTc; + struct QUE_MGT *prQM; + + KAL_SPIN_LOCK_DECLARATION(); + + prTxCtrl = &prAdapter->rTxCtrl; + prTc = &prTxCtrl->rTc; + prQM = &prAdapter->rQM; + + total_PSE = 0; + total_PLE = 0; + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + for (i = 0; i < 4; i++) { + total_PSE += prTc->au4FreePageCount[i]; + total_PLE += prTc->au4FreePageCount_PLE[i]; + } + + if ((total_PSE < PSE_cnt) || (total_PLE < PLE_cnt)) { + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + return FALSE; + } + + for (i = 0; i < 4; i++) { + if ((PLE_cnt != 0) || (PSE_cnt != 0)) { + /* PSE part */ + if (prTc->au4FreePageCount[i] >= PSE_cnt) { + prTc->au4FreePageCount[i] -= PSE_cnt; + prQM->au4QmTcUsedPageCounter[i] += PSE_cnt; + PSE_cnt = 0; + } else { + PSE_cnt -= prTc->au4FreePageCount[i]; + prQM->au4QmTcUsedPageCounter[i] += + prTc->au4FreePageCount[i]; + prTc->au4FreePageCount[i] = 0; + } + prTc->au4FreeBufferCount[i] = + (prTc->au4FreePageCount[i] / + (prAdapter->rTxCtrl.u4MaxPageCntPerFrame)); + + /* PLE part */ + if (prTc->au4FreePageCount_PLE[i] >= PLE_cnt) { + prTc->au4FreePageCount_PLE[i] -= PLE_cnt; + PLE_cnt = 0; + } else { + PLE_cnt -= prTc->au4FreePageCount_PLE[i]; + prTc->au4FreePageCount_PLE[i] = 0; + } + + } else { + break; + } + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + return TRUE; +} +void Set_sdio_ring_event(void) +{ + set_bit(SDIO_RING_TX_BIT, &ulFlag); + wake_up_interruptible(&waitq_sdio_ring); +} +uint32_t sdio_ring_kcik_data(struct GLUE_INFO *prGlueInfo) +{ + struct ADAPTER *prAdapter; + struct GL_HIF_INFO *prHif = NULL; + uint32_t head; + uint32_t tail; + uint32_t data_len; + uint32_t req_PSE; + uint32_t req_PLE; + uint8_t *buf; + + prAdapter = prGlueInfo->prAdapter; + prHif = &prGlueInfo->rHifInfo; + + head = prHif->ring_head; + tail = prHif->ring_tail; + + if (tail != head) { + buf = prHif->ring_buffer[tail]; + data_len = prHif->ring_len[tail]; + req_PSE = prHif->ring_PSE[tail]; + req_PLE = prHif->ring_PLE[tail]; + if (Acquire_All_Resource(prAdapter, req_PLE, req_PSE) == TRUE) { + if (kalDevPortWrite(prGlueInfo, MCR_WTDR1, data_len, + buf, SDIO_RING_BUF_LEN) == FALSE) { + HAL_SET_FLAG(prAdapter, ADAPTER_FLAG_HW_ERR); + fgIsBusAccessFailed = TRUE; + return FALSE; + } + + prHif->ring_len[tail] = 0; + prHif->ring_PSE[tail] = 0; + prHif->ring_PLE[tail] = 0; + + sdio_ring_pop(prGlueInfo); + + kalSetTxEvent2Hif(prGlueInfo); + Set_sdio_ring_event(); + + } else { + return FALSE; + } + } + return TRUE; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/sdio_test_driver_core.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/sdio_test_driver_core.c new file mode 100644 index 0000000000000..0d15962af4765 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/sdio_test_driver_core.c @@ -0,0 +1,448 @@ +#include "gl_os.h" + +#if (CFG_SDIO_1BIT_DATA_MODE == 1) +/* + * linux/drivers/mmc/core/core.c + * + * Copyright (C) 2003-2004 Russell King, All Rights Reserved. + * SD support Copyright (C) 2004 Ian Molton, All Rights Reserved. + * Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved. + * MMCv4 support Copyright (C) 2006 Philip Langdale, All Rights Reserved. + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +#include "test_driver_sdio_ops.h" + + +/* + * Internal function that does the actual ios call to the host driver, + * optionally printing some debug output. + */ +static inline void mmc_set_ios(struct mmc_host *host) +{ + struct mmc_ios *ios = &host->ios; + + pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u width %u timing %u\n", + mmc_hostname(host), ios->clock, ios->bus_mode, + ios->power_mode, ios->chip_select, ios->vdd, + ios->bus_width, ios->timing); + + host->ops->set_ios(host, ios); +} + +/* + * Control chip select pin on a host. + */ +void mmc_set_chip_select(struct mmc_host *host, int mode) +{ + host->ios.chip_select = mode; + mmc_set_ios(host); +} + +/* + * Sets the host clock to the highest possible frequency that + * is below "hz". + */ +void mmc_set_clock(struct mmc_host *host, unsigned int hz) +{ + WARN_ON(hz < host->f_min); + + if (hz > host->f_max) + hz = host->f_max; + + #if 1 + pr_debug("%s(): %dHz\n", __func__, hz); + #endif + + host->ios.clock = hz; + mmc_set_ios(host); +} + +/* + * Change the bus mode (open drain/push-pull) of a host. + */ +void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode) +{ + host->ios.bus_mode = mode; + mmc_set_ios(host); +} + +/* + * Change data bus width of a host. + */ +void mmc_set_bus_width(struct mmc_host *host, unsigned int width) +{ + host->ios.bus_width = width; + mmc_set_ios(host); +} + +/* + * Mask off any voltages we don't support and select + * the lowest voltage + */ +u32 mmc_select_voltage(struct mmc_host *host, u32 ocr) +{ + int bit; + + ocr &= host->ocr_avail; + + bit = ffs(ocr); + if (bit) { + bit -= 1; + + ocr &= 3 << bit; + + host->ios.vdd = bit; + mmc_set_ios(host); + } else { + pr_info("%s: host doesn't support card's voltages\n", + mmc_hostname(host)); + ocr = 0; + } + + return ocr; +} + +/* + * Select timing parameters for host. + */ +void mmc_set_timing(struct mmc_host *host, unsigned int timing) +{ + host->ios.timing = timing; + mmc_set_ios(host); +} + + +static void mmc_power_off(struct mmc_host *host) +{ + host->ios.clock = 0; + host->ios.vdd = 0; + if (!mmc_host_is_spi(host)) { + host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; + host->ios.chip_select = MMC_CS_DONTCARE; + } + host->ios.power_mode = MMC_POWER_OFF; + host->ios.bus_width = MMC_BUS_WIDTH_1; + host->ios.timing = MMC_TIMING_LEGACY; + mmc_set_ios(host); +} + +/* + * Cleanup when the last reference to the bus operator is dropped. + */ +static void __mmc_release_bus(struct mmc_host *host) +{ + BUG_ON(!host); + BUG_ON(host->bus_refs); + BUG_ON(!host->bus_dead); + + host->bus_ops = NULL; +} + +/* + * Increase reference count of bus operator + */ +static inline void mmc_bus_get(struct mmc_host *host) +{ + unsigned long flags; + + spin_lock_irqsave(&host->lock, flags); + host->bus_refs++; + spin_unlock_irqrestore(&host->lock, flags); +} + +/* + * Decrease reference count of bus operator and free it if + * it is the last reference. + */ +static inline void mmc_bus_put(struct mmc_host *host) +{ + unsigned long flags; + + spin_lock_irqsave(&host->lock, flags); + host->bus_refs--; + if ((host->bus_refs == 0) && host->bus_ops) + __mmc_release_bus(host); + spin_unlock_irqrestore(&host->lock, flags); +} + +/* + * Assign a mmc bus handler to a host. Only one bus handler may control a + * host at any given time. + */ +void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops) +{ + unsigned long flags; + + BUG_ON(!host); + BUG_ON(!ops); + + WARN_ON(!host->claimed); + + spin_lock_irqsave(&host->lock, flags); + + BUG_ON(host->bus_ops); + BUG_ON(host->bus_refs); + + host->bus_ops = ops; + host->bus_refs = 1; + host->bus_dead = 0; + + spin_unlock_irqrestore(&host->lock, flags); +} + +/* + * Remove the current bus handler from a host. Assumes that there are + * no interesting cards left, so the bus is powered down. + */ +void mmc_detach_bus(struct mmc_host *host) +{ + unsigned long flags; + + BUG_ON(!host); + + WARN_ON(!host->claimed); + WARN_ON(!host->bus_ops); + + spin_lock_irqsave(&host->lock, flags); + + host->bus_dead = 1; + + spin_unlock_irqrestore(&host->lock, flags); + + mmc_power_off(host); + + mmc_bus_put(host); +} + +int mmc_app_set_bus_width(struct mmc_card *card, int width) +{ + int err; + struct mmc_command cmd; + + BUG_ON(!card); + BUG_ON(!card->host); + + memset(&cmd, 0, sizeof(struct mmc_command)); + + cmd.opcode = SD_APP_SET_BUS_WIDTH; + cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; + + switch (width) { + case MMC_BUS_WIDTH_1: + cmd.arg = SD_BUS_WIDTH_1; + break; + case MMC_BUS_WIDTH_4: + cmd.arg = SD_BUS_WIDTH_4; + break; + default: + return -EINVAL; + } + + err = mmc_wait_for_app_cmd(card->host, card, &cmd, MMC_CMD_RETRIES); + if (err) + return err; + + return 0; +} + +int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) +{ + struct mmc_command cmd; + int i, err = 0; + + BUG_ON(!host); + + memset(&cmd, 0, sizeof(struct mmc_command)); + + cmd.opcode = SD_APP_OP_COND; + if (mmc_host_is_spi(host)) + cmd.arg = ocr & (1 << 30); /* SPI only defines one bit */ + else + cmd.arg = ocr; + cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR; + + for (i = 100; i; i--) { + err = mmc_wait_for_app_cmd(host, NULL, &cmd, MMC_CMD_RETRIES); + if (err) + break; + + /* if we're just probing, do a single pass */ + if (ocr == 0) + break; + + /* otherwise wait until reset completes */ + if (mmc_host_is_spi(host)) { + if (!(cmd.resp[0] & R1_SPI_IDLE)) + break; + } else { + if (cmd.resp[0] & MMC_CARD_BUSY) + break; + } + + err = -ETIMEDOUT; + + mmc_delay(10); + } + + if (rocr && !mmc_host_is_spi(host)) + *rocr = cmd.resp[0]; + + return err; +} + +int mmc_send_if_cond(struct mmc_host *host, u32 ocr) +{ + struct mmc_command cmd; + int err; + static const u8 test_pattern = 0xAA; + u8 result_pattern; + + /* + * To support SD 2.0 cards, we must always invoke SD_SEND_IF_COND + * before SD_APP_OP_COND. This command will harmlessly fail for + * SD 1.0 cards. + */ + cmd.opcode = SD_SEND_IF_COND; + cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern; + cmd.flags = MMC_RSP_SPI_R7 | MMC_RSP_R7 | MMC_CMD_BCR; + + err = mmc_wait_for_cmd(host, &cmd, 0); + if (err) + return err; + + if (mmc_host_is_spi(host)) + result_pattern = cmd.resp[1] & 0xFF; + else + result_pattern = cmd.resp[0] & 0xFF; + + if (result_pattern != test_pattern) + return -EIO; + + return 0; +} + + + +static int sdio_enable_wide(struct mmc_card *card) +{ + int ret; + u8 ctrl; + + if (!(card->host->caps & MMC_CAP_4_BIT_DATA)) + return 0; + + + if (card->cccr.low_speed && !card->cccr.wide_bus) + return 0; + + + ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_IF, 0, &ctrl); + if (ret) + return ret; + + + if ((ctrl & SDIO_BUS_WIDTH_MASK) == SDIO_BUS_WIDTH_RESERVED) + pr_info("%s: SDIO_CCCR_IF is invalid: 0x%02x\n", + mmc_hostname(card->host), ctrl); + + /* set as 4-bit bus width */ + ctrl &= ~SDIO_BUS_WIDTH_MASK; + ctrl |= SDIO_BUS_WIDTH_4BIT; + + ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_IF, ctrl, NULL); + if (ret) + return ret; + + return 1; +} + + + +/* + * Devices that remain active during a system suspend are + * put back into 1-bit mode. + */ +int sdio_disable_wide(struct mmc_card *card) +{ + int ret; + u8 ctrl; + + if (!(card->host->caps & MMC_CAP_4_BIT_DATA)) + return 0; + + + if (card->cccr.low_speed && !card->cccr.wide_bus) + return 0; + + + ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_IF, 0, &ctrl); + if (ret) + return ret; + + + if (!(ctrl & SDIO_BUS_WIDTH_4BIT)) + return 0; + + + ctrl &= ~SDIO_BUS_WIDTH_4BIT; + ctrl |= SDIO_BUS_ASYNC_INT; + + ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_IF, ctrl, NULL); + if (ret) + return ret; + + + mmc_set_bus_width(card->host, MMC_BUS_WIDTH_1); + + return 0; +} + + +int sdio_enable_4bit_bus(struct mmc_card *card) +{ + int err; + + if (card->type == MMC_TYPE_SDIO) + return sdio_enable_wide(card); + + + if ((card->host->caps & MMC_CAP_4_BIT_DATA) && + (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) { + + err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4); + if (err) + return err; + } else + return 0; + + + err = sdio_enable_wide(card); + if (err <= 0) + mmc_app_set_bus_width(card, MMC_BUS_WIDTH_1); + + return err; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/sdio_test_driver_ops.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/sdio_test_driver_ops.c new file mode 100644 index 0000000000000..96ec0ef9893fc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/sdio_test_driver_ops.c @@ -0,0 +1,194 @@ + +#include "gl_os.h" + +#if (CFG_SDIO_1BIT_DATA_MODE == 1) +/* + * linux/drivers/mmc/sdio_ops.c + * + * Copyright 2006-2007 Pierre Ossman + * + * 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. + */ + +#include + +#if 0 +#include +#include +#include +#include +#include +#endif + +#include "test_driver_sdio_ops.h" + +int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) +{ + struct mmc_command cmd; + int i, err = 0; + + BUG_ON(!host); + + memset(&cmd, 0, sizeof(struct mmc_command)); + + cmd.opcode = SD_IO_SEND_OP_COND; + cmd.arg = ocr; + cmd.flags = MMC_RSP_SPI_R4 | MMC_RSP_R4 | MMC_CMD_BCR; + + for (i = 100; i; i--) { + err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); + if (err) + break; + + /* if we're just probing, do a single pass */ + if (ocr == 0) { + pr_info("PROBE ONLY! RESP[0] = 0x%08x\n", cmd.resp[0]); + break; + } + + /* otherwise wait until reset completes */ + if (mmc_host_is_spi(host)) { + /* + * Both R1_SPI_IDLE and MMC_CARD_BUSY indicate + * an initialized card under SPI, but some cards + * (Marvell's) only behave when looking at this + * one. + */ + if (cmd.resp[1] & MMC_CARD_BUSY) + break; + } else { + if (cmd.resp[0] & MMC_CARD_BUSY) + break; + } + + err = -ETIMEDOUT; + + mmc_delay(10); + } + + if (rocr) + *rocr = cmd.resp[mmc_host_is_spi(host) ? 1 : 0]; + + return err; +} + +int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, + unsigned addr, u8 in, u8 *out) +{ + struct mmc_command cmd; + int err; + + BUG_ON(!card); + BUG_ON(fn > 7); + + /* sanity check */ + if (addr & ~0x1FFFF) + return -EINVAL; + + memset(&cmd, 0, sizeof(struct mmc_command)); + + cmd.opcode = SD_IO_RW_DIRECT; + cmd.arg = write ? 0x80000000 : 0x00000000; + cmd.arg |= fn << 28; + cmd.arg |= (write && out) ? 0x08000000 : 0x00000000; + cmd.arg |= addr << 9; + cmd.arg |= in; + cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC; + + err = mmc_wait_for_cmd(card->host, &cmd, 0); + if (err) + return err; + + if (mmc_host_is_spi(card->host)) { + /* host driver already reported errors */ + } else { + if (cmd.resp[0] & R5_ERROR) + return -EIO; + if (cmd.resp[0] & R5_FUNCTION_NUMBER) + return -EINVAL; + if (cmd.resp[0] & R5_OUT_OF_RANGE) + return -ERANGE; + } + + if (out) { + if (mmc_host_is_spi(card->host)) + *out = (cmd.resp[0] >> 8) & 0xFF; + else + *out = cmd.resp[0] & 0xFF; + } + + return 0; +} + +int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, + unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz) +{ + struct mmc_request mrq; + struct mmc_command cmd; + struct mmc_data data; + struct scatterlist sg; + + BUG_ON(!card); + BUG_ON(fn > 7); + BUG_ON(blocks == 1 && blksz > 512); + WARN_ON(blocks == 0); + WARN_ON(blksz == 0); + + /* sanity check */ + if (addr & ~0x1FFFF) + return -EINVAL; + + memset(&mrq, 0, sizeof(struct mmc_request)); + memset(&cmd, 0, sizeof(struct mmc_command)); + memset(&data, 0, sizeof(struct mmc_data)); + + mrq.cmd = &cmd; + mrq.data = &data; + + cmd.opcode = SD_IO_RW_EXTENDED; + cmd.arg = write ? 0x80000000 : 0x00000000; + cmd.arg |= fn << 28; + cmd.arg |= incr_addr ? 0x04000000 : 0x00000000; + cmd.arg |= addr << 9; + if (blocks == 1 && blksz <= 512) + cmd.arg |= (blksz == 512) ? 0 : blksz; /* byte mode */ + else + cmd.arg |= 0x08000000 | blocks; /* block mode */ + cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC; + + data.blksz = blksz; + data.blocks = blocks; + data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ; + data.sg = &sg; + data.sg_len = 1; + + sg_init_one(&sg, buf, blksz * blocks); + + mmc_set_data_timeout(&data, card); + + mmc_wait_for_req(card->host, &mrq); + + if (cmd.error) + return cmd.error; + if (data.error) + return data.error; + + if (mmc_host_is_spi(card->host)) { + /* host driver already reported errors */ + } else { + if (cmd.resp[0] & R5_ERROR) + return -EIO; + if (cmd.resp[0] & R5_FUNCTION_NUMBER) + return -EINVAL; + if (cmd.resp[0] & R5_OUT_OF_RANGE) + return -ERANGE; + } + + return 0; +} + +#endif + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/x86.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/x86.c new file mode 100644 index 0000000000000..7cbc34e29cdef --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/sdio/x86.c @@ -0,0 +1,62 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** +*[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. +******************************************************************************/ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/usb/hal_api.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/usb/hal_api.c new file mode 100644 index 0000000000000..b2553279900ef --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/usb/hal_api.c @@ -0,0 +1,1927 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** +*[File] hif_api.c +*[Version] v1.0 +*[Revision Date] 2015-09-08 +*[Author] +*[Description] +* The program provides USB HIF APIs +*[Copyright] +* Copyright (C) 2015 MediaTek Incorporation. All Rights Reserved. +******************************************************************************/ + +/******************************************************************************* +* C O M P I L E 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 +#include + +#include +#ifndef CONFIG_X86 +#include +#endif +#include + +#include "mt66xx_reg.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 const uint16_t arTcToUSBEP[USB_TC_NUM] = { + USB_DATA_BULK_OUT_EP4, + USB_DATA_BULK_OUT_EP5, + USB_DATA_BULK_OUT_EP6, + USB_DATA_BULK_OUT_EP7, + USB_DATA_BULK_OUT_EP8, + USB_DATA_BULK_OUT_EP9, + + /* Second HW queue */ +#if NIC_TX_ENABLE_SECOND_HW_QUEUE + USB_DATA_BULK_OUT_EP9, + USB_DATA_BULK_OUT_EP9, + USB_DATA_BULK_OUT_EP9, + USB_DATA_BULK_OUT_EP9, +#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 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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t halVerifyChipID(IN struct ADAPTER *prAdapter) +{ + uint32_t u4CIR = 0; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + + if (prAdapter->fgIsReadRevID) + return TRUE; + + prChipInfo = prAdapter->chip_info; + + HAL_MCR_RD(prAdapter, TOP_HCR, &u4CIR); + DBGLOG(INIT, TRACE, "Chip ID: 0x%4x\n", u4CIR); + + if (u4CIR != prChipInfo->chip_id) + return FALSE; + + HAL_MCR_RD(prAdapter, TOP_HVR, &u4CIR); + DBGLOG(INIT, TRACE, "Revision ID: 0x%4x\n", u4CIR); + + prAdapter->ucRevID = (uint8_t) (u4CIR & 0xF); + prAdapter->fgIsReadRevID = TRUE; + return TRUE; +} + +uint32_t +halRxWaitResponse(IN struct ADAPTER *prAdapter, IN uint8_t ucPortIdx, OUT uint8_t *pucRspBuffer, + IN uint32_t u4MaxRespBufferLen, OUT uint32_t *pu4Length) +{ + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + struct RX_CTRL *prRxCtrl; + u_int8_t ret = FALSE; + struct BUS_INFO *prBusInfo; + + DEBUGFUNC("halRxWaitResponse"); + + ASSERT(prAdapter); + ASSERT(pucRspBuffer); + + prRxCtrl = &prAdapter->rRxCtrl; + prBusInfo = prAdapter->chip_info->bus_info; + + if (prBusInfo->asicUsbEventEpDetected) + ucPortIdx = prBusInfo->asicUsbEventEpDetected(prAdapter); + else { + if (prHifInfo->fgEventEpDetected == FALSE) { + /* NOTE: This is temporary compatiable code with old/new CR4 FW to detect + * which EVENT endpoint that. + * CR4 FW is using. If the new EP4IN-using CR4 FW works without + * any issue for a while, + * this code block will be removed. + */ + if (prAdapter->fgIsCr4FwDownloaded) { + ucPortIdx = USB_DATA_EP_IN; + ret = kalDevPortRead(prAdapter->prGlueInfo, ucPortIdx, + ALIGN_4(u4MaxRespBufferLen) + LEN_USB_RX_PADDING_CSO, + prRxCtrl->pucRxCoalescingBufPtr, HIF_RX_COALESCING_BUFFER_SIZE); + + if (ret == TRUE) { + prHifInfo->eEventEpType = EVENT_EP_TYPE_DATA_EP; + } else { + ucPortIdx = USB_EVENT_EP_IN; + ret = kalDevPortRead(prAdapter->prGlueInfo, ucPortIdx, + ALIGN_4(u4MaxRespBufferLen) + LEN_USB_RX_PADDING_CSO, + prRxCtrl->pucRxCoalescingBufPtr, HIF_RX_COALESCING_BUFFER_SIZE); + } + prHifInfo->fgEventEpDetected = TRUE; + + kalMemCopy(pucRspBuffer, prRxCtrl->pucRxCoalescingBufPtr, u4MaxRespBufferLen); + *pu4Length = u4MaxRespBufferLen; + + if (ret == FALSE) + u4Status = WLAN_STATUS_FAILURE; + return u4Status; + } + + ucPortIdx = USB_EVENT_EP_IN; + } else { + if (prHifInfo->eEventEpType == EVENT_EP_TYPE_DATA_EP) + if (prAdapter->fgIsCr4FwDownloaded) + ucPortIdx = USB_DATA_EP_IN; + else + ucPortIdx = USB_EVENT_EP_IN; + else + ucPortIdx = USB_EVENT_EP_IN; + } + } + ret = kalDevPortRead(prAdapter->prGlueInfo, ucPortIdx, + ALIGN_4(u4MaxRespBufferLen) + LEN_USB_RX_PADDING_CSO, + prRxCtrl->pucRxCoalescingBufPtr, HIF_RX_COALESCING_BUFFER_SIZE); + + kalMemCopy(pucRspBuffer, prRxCtrl->pucRxCoalescingBufPtr, u4MaxRespBufferLen); + *pu4Length = u4MaxRespBufferLen; + + if (ret == FALSE) + u4Status = WLAN_STATUS_FAILURE; + + return u4Status; +} + +uint32_t halTxUSBSendCmd(IN struct GLUE_INFO *prGlueInfo, IN uint8_t ucTc, IN struct CMD_INFO *prCmdInfo) +{ + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + struct USB_REQ *prUsbReq; + struct BUF_CTRL *prBufCtrl; + uint16_t u2OverallBufferLength = 0; + unsigned long flags; + struct HW_MAC_TX_DESC *prTxDesc; + uint8_t ucQueIdx; + struct mt66xx_chip_info *prChipInfo; + int ret; + + prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxCmdFreeQ, &prHifInfo->rTxCmdQLock); + if (prUsbReq == NULL) + return WLAN_STATUS_RESOURCES; + + prBufCtrl = prUsbReq->prBufCtrl; + + if ((TFCB_FRAME_PAD_TO_DW(prCmdInfo->u4TxdLen + prCmdInfo->u4TxpLen) + LEN_USB_UDMA_TX_TERMINATOR) > + prBufCtrl->u4BufSize) { + DBGLOG(HAL, ERROR, "Command TX buffer underflow!\n"); + glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxCmdFreeQ, prUsbReq, + &prHifInfo->rTxCmdQLock, FALSE); + return WLAN_STATUS_RESOURCES; + } + + DBGLOG(HAL, INFO, "TX URB[0x%p]\n", prUsbReq->prUrb); + + prChipInfo = prGlueInfo->prAdapter->chip_info; + HAL_WRITE_HIF_TXD(prChipInfo, prBufCtrl->pucBuf, (prCmdInfo->u4TxdLen + prCmdInfo->u4TxpLen)); + u2OverallBufferLength += prChipInfo->u2HifTxdSize; + + if (prCmdInfo->u4TxdLen) { + memcpy((prBufCtrl->pucBuf + u2OverallBufferLength), prCmdInfo->pucTxd, prCmdInfo->u4TxdLen); + u2OverallBufferLength += prCmdInfo->u4TxdLen; + } + + if (prCmdInfo->u4TxpLen) { + memcpy((prBufCtrl->pucBuf + u2OverallBufferLength), prCmdInfo->pucTxp, prCmdInfo->u4TxpLen); + u2OverallBufferLength += prCmdInfo->u4TxpLen; + } + + prTxDesc = (struct HW_MAC_TX_DESC *)prBufCtrl->pucBuf; + ucQueIdx = HAL_MAC_TX_DESC_GET_QUEUE_INDEX(prTxDesc); + /* For H2CDMA Tx CMD mapping */ + /* Mapping port1 queue0~3 to queue28~31, and CR4 will unmask this */ + HAL_MAC_TX_DESC_SET_QUEUE_INDEX(prTxDesc, (ucQueIdx | USB_TX_CMD_QUEUE_MASK)); + + /* DBGLOG_MEM32(SW4, INFO, prBufCtrl->pucBuf, 32); */ + + memset(prBufCtrl->pucBuf + u2OverallBufferLength, 0, + ((TFCB_FRAME_PAD_TO_DW(u2OverallBufferLength) - u2OverallBufferLength) + LEN_USB_UDMA_TX_TERMINATOR)); + prBufCtrl->u4WrIdx = TFCB_FRAME_PAD_TO_DW(u2OverallBufferLength) + LEN_USB_UDMA_TX_TERMINATOR; + + prUsbReq->prPriv = (void *) prCmdInfo; + usb_fill_bulk_urb(prUsbReq->prUrb, + prHifInfo->udev, + usb_sndbulkpipe(prHifInfo->udev, arTcToUSBEP[ucTc]), + (void *)prUsbReq->prBufCtrl->pucBuf, + prBufCtrl->u4WrIdx, halTxUSBSendCmdComplete, (void *)prUsbReq); + +#if CFG_USB_CONSISTENT_DMA + prUsbReq->prUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; +#endif + spin_lock_irqsave(&prHifInfo->rTxCmdQLock, flags); + + if (prHifInfo->prGlueInfo->prAdapter->ucSerState == SER_IDLE_DONE) { + ret = glUsbSubmitUrb(prHifInfo, prUsbReq->prUrb, + SUBMIT_TYPE_TX_CMD); + if (ret) { + DBGLOG(HAL, ERROR, + "glUsbSubmitUrb() error (0x%08X)(EP%d OUT)\n", + u4Status, arTcToUSBEP[ucTc]); + goto error; + } + } else { + DBGLOG(HAL, ERROR, "[SER] BYPASS USB send cmd\n"); + + /* THIS fw cmd would be dropped if SER is on-going. */ + + goto error; + } + + list_add_tail(&prUsbReq->list, &prHifInfo->rTxCmdSendingQ); + spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, flags); + + if (wlanIsChipRstRecEnabled(prGlueInfo->prAdapter) + && wlanIsChipNoAck(prGlueInfo->prAdapter)) { + wlanChipRstPreAct(prGlueInfo->prAdapter); + DBGLOG(HAL, ERROR, "usb trigger whole reset\n"); + HAL_WIFI_FUNC_CHIP_RESET(prGlueInfo->prAdapter); + } + return u4Status; + +error: + list_add_tail(&prUsbReq->list, &prHifInfo->rTxCmdFreeQ); + spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, flags); + return WLAN_STATUS_FAILURE; +} + +void halTxUSBSendCmdComplete(struct urb *urb) +{ + struct USB_REQ *prUsbReq = urb->context; + struct GL_HIF_INFO *prHifInfo = prUsbReq->prHifInfo; + struct GLUE_INFO *prGlueInfo = prHifInfo->prGlueInfo; + unsigned long flags; + +#if CFG_USB_TX_HANDLE_IN_HIF_THREAD + spin_lock_irqsave(&prHifInfo->rTxCmdQLock, flags); + list_del_init(&prUsbReq->list); + list_add_tail(&prUsbReq->list, &prHifInfo->rTxCmdCompleteQ); + spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, flags); + + kalSetIntEvent(prGlueInfo); +#else + spin_lock_irqsave(&prHifInfo->rTxCmdQLock, flags); + list_del_init(&prUsbReq->list); + spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, flags); + + halTxUSBProcessCmdComplete(prGlueInfo->prAdapter, prUsbReq); +#endif +} + +void halTxUSBProcessCmdComplete(IN struct ADAPTER *prAdapter, struct USB_REQ *prUsbReq) +{ + struct urb *urb = prUsbReq->prUrb; + uint32_t u4SentDataSize; + struct GL_HIF_INFO *prHifInfo = prUsbReq->prHifInfo; + + if (urb->status != 0) { + DBGLOG(TX, ERROR, "[%s] send CMD fail (status = %d)\n", __func__, urb->status); + /* TODO: handle error */ + } + + DBGLOG(HAL, INFO, "TX CMD DONE: URB[0x%p]\n", urb); + + glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxCmdFreeQ, prUsbReq, &prHifInfo->rTxCmdQLock, FALSE); + + u4SentDataSize = urb->actual_length - LEN_USB_UDMA_TX_TERMINATOR; + nicTxReleaseResource_PSE(prAdapter, TC4_INDEX, nicTxGetPageCount(prAdapter, u4SentDataSize, TRUE), TRUE); +} + +void halTxCancelSendingCmd(IN struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo) +{ + struct USB_REQ *prUsbReq, *prNext; + unsigned long flags; + struct urb *urb = NULL; + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + spin_lock_irqsave(&prHifInfo->rTxCmdQLock, flags); + list_for_each_entry_safe(prUsbReq, prNext, &prHifInfo->rTxCmdSendingQ, list) { + if (prUsbReq->prPriv == (void *) prCmdInfo) { + list_del_init(&prUsbReq->list); + urb = prUsbReq->prUrb; + break; + } + } + spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, flags); + + if (urb) { + prCmdInfo->pfHifTxCmdDoneCb = NULL; + usb_kill_urb(urb); + } +} + +void halTxCancelAllSending(IN struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo; + struct USB_REQ *prUsbReq, *prUsbReqNext; + struct GL_HIF_INFO *prHifInfo; +#if CFG_USB_TX_AGG + uint8_t ucTc; +#endif + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + prHifInfo = &prGlueInfo->rHifInfo; + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxCmdSendingQ, list) { + usb_kill_urb(prUsbReq->prUrb); + } + +#if CFG_USB_TX_AGG + for (ucTc = 0; ucTc < USB_TC_NUM; ++ucTc) + usb_kill_anchored_urbs(&prHifInfo->rTxDataAnchor[ucTc]); +#else + usb_kill_anchored_urbs(&prHifInfo->rTxDataAnchor); +#endif + + nicTxReleaseSafe(prGlueInfo->prAdapter, FALSE); +} + +#if CFG_USB_TX_AGG +uint32_t halTxUSBSendAggData(IN struct GL_HIF_INFO *prHifInfo, IN uint8_t ucTc, IN struct USB_REQ *prUsbReq) +{ + struct GLUE_INFO *prGlueInfo = prHifInfo->prGlueInfo; + struct BUF_CTRL *prBufCtrl = prUsbReq->prBufCtrl; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + int ret; + + memset(prBufCtrl->pucBuf + prBufCtrl->u4WrIdx, 0, LEN_USB_UDMA_TX_TERMINATOR); + prBufCtrl->u4WrIdx += LEN_USB_UDMA_TX_TERMINATOR; + + list_del_init(&prUsbReq->list); + + usb_fill_bulk_urb(prUsbReq->prUrb, + prHifInfo->udev, + usb_sndbulkpipe(prHifInfo->udev, arTcToUSBEP[ucTc]), + (void *)prBufCtrl->pucBuf, prBufCtrl->u4WrIdx, halTxUSBSendDataComplete, (void *)prUsbReq); +#if CFG_USB_CONSISTENT_DMA + prUsbReq->prUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; +#endif + + usb_anchor_urb(prUsbReq->prUrb, &prHifInfo->rTxDataAnchor[ucTc]); + + if (prHifInfo->prGlueInfo->prAdapter->ucSerState == SER_IDLE_DONE) { + ret = glUsbSubmitUrb(prHifInfo, prUsbReq->prUrb, + SUBMIT_TYPE_TX_DATA); + if (ret) { + DBGLOG(HAL, ERROR, + "glUsbSubmitUrb() error(0x%08X) (EP%d OUT)\n", + u4Status, arTcToUSBEP[ucTc]); + goto error; + } + } else { + DBGLOG(HAL, ERROR, "[SER] BYPASS USB send agg data\n"); + + goto error; + } + + return u4Status; + +error: + halTxUSBProcessMsduDone(prHifInfo->prGlueInfo, prUsbReq); + prBufCtrl->u4WrIdx = 0; + usb_unanchor_urb(prUsbReq->prUrb); + list_add_tail(&prUsbReq->list, &prHifInfo->rTxDataCompleteQ); +#if CFG_USB_TX_HANDLE_IN_HIF_THREAD + kalSetIntEvent(prGlueInfo); +#else + /*tasklet_hi_schedule(&prGlueInfo->rTxCompleteTask);*/ + tasklet_schedule(&prGlueInfo->rTxCompleteTask); +#endif + return WLAN_STATUS_FAILURE; +} +#endif + +uint32_t halTxUSBSendData(IN struct GLUE_INFO *prGlueInfo, IN struct MSDU_INFO *prMsduInfo) +{ + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + struct mt66xx_chip_info *prChipInfo; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + struct USB_REQ *prUsbReq; + struct BUF_CTRL *prBufCtrl; + uint32_t u4PaddingLength; + struct sk_buff *skb; + uint8_t ucTc; + uint8_t *pucBuf; + uint32_t u4Length; + uint32_t u4TotalLen; + unsigned long flags; +#if !CFG_USB_TX_AGG + int ret; +#endif + + prChipInfo = prGlueInfo->prAdapter->chip_info; + skb = (struct sk_buff *)prMsduInfo->prPacket; + pucBuf = skb->data; + u4Length = skb->len; + u4TotalLen = u4Length + prChipInfo->u2HifTxdSize; + ucTc = USB_TRANS_MSDU_TC(prMsduInfo); + +#if CFG_USB_TX_AGG + spin_lock_irqsave(&prHifInfo->rTxDataQLock, flags); + + if (list_empty(&prHifInfo->rTxDataFreeQ[ucTc])) { + if (glUsbBorrowFfaReq(prHifInfo, ucTc) == FALSE) { + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, flags); + DBGLOG(HAL, ERROR, "run out of rTxDataFreeQ #1!!\n"); + wlanProcessQueuedMsduInfo(prGlueInfo->prAdapter, prMsduInfo); + return WLAN_STATUS_RESOURCES; + } + } + prUsbReq = list_entry(prHifInfo->rTxDataFreeQ[ucTc].next, struct USB_REQ, list); + prBufCtrl = prUsbReq->prBufCtrl; + + if (prHifInfo->u4AggRsvSize[ucTc] < ALIGN_4(u4TotalLen)) + DBGLOG(HAL, ERROR, "u4AggRsvSize[%hhu] count FAIL (%u, %u)\n", + ucTc, prHifInfo->u4AggRsvSize[ucTc], u4TotalLen); + prHifInfo->u4AggRsvSize[ucTc] -= ALIGN_4(u4TotalLen); + + if (prBufCtrl->u4WrIdx + ALIGN_4(u4TotalLen) + LEN_USB_UDMA_TX_TERMINATOR > prBufCtrl->u4BufSize) { + halTxUSBSendAggData(prHifInfo, ucTc, prUsbReq); + + if (list_empty(&prHifInfo->rTxDataFreeQ[ucTc])) { + if (glUsbBorrowFfaReq(prHifInfo, ucTc) == FALSE) { + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, + flags); + DBGLOG(HAL, ERROR, "run out of rTxDataFreeQ #2!!\n"); + wlanProcessQueuedMsduInfo(prGlueInfo->prAdapter, prMsduInfo); + return WLAN_STATUS_FAILURE; + } + } + + prUsbReq = list_entry(prHifInfo->rTxDataFreeQ[ucTc].next, struct USB_REQ, list); + prBufCtrl = prUsbReq->prBufCtrl; + } + + HAL_WRITE_HIF_TXD(prChipInfo, prBufCtrl->pucBuf + prBufCtrl->u4WrIdx, u4Length); + prBufCtrl->u4WrIdx += prChipInfo->u2HifTxdSize; + memcpy(prBufCtrl->pucBuf + prBufCtrl->u4WrIdx, pucBuf, u4Length); + prBufCtrl->u4WrIdx += u4Length; + + u4PaddingLength = (ALIGN_4(u4TotalLen) - u4TotalLen); + if (u4PaddingLength) { + memset(prBufCtrl->pucBuf + prBufCtrl->u4WrIdx, 0, u4PaddingLength); + prBufCtrl->u4WrIdx += u4PaddingLength; + } + + if (!prMsduInfo->pfTxDoneHandler) { + QUEUE_INSERT_TAIL(&prUsbReq->rSendingDataMsduInfoList, (struct QUE_ENTRY *) prMsduInfo); + } else { + KAL_SPIN_LOCK_DECLARATION(); + + /* Record native packet pointer for Tx done log */ + WLAN_GET_FIELD_32(&prMsduInfo->prPacket, + &prMsduInfo->u4TxDoneTag); + + KAL_ACQUIRE_SPIN_LOCK(prGlueInfo->prAdapter, + SPIN_LOCK_TXING_MGMT_LIST); + QUEUE_INSERT_TAIL( + &(prGlueInfo->prAdapter->rTxCtrl.rTxMgmtTxingQueue), + (struct QUE_ENTRY *) prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prGlueInfo->prAdapter, + SPIN_LOCK_TXING_MGMT_LIST); + } + + if (usb_anchor_empty(&prHifInfo->rTxDataAnchor[ucTc])) + halTxUSBSendAggData(prHifInfo, ucTc, prUsbReq); + + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, flags); +#else + prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxDataFreeQ, + &prHifInfo->rTxDataQLock); + if (prUsbReq == NULL) { + DBGLOG(HAL, ERROR, "run out of rTxDataFreeQ!!\n"); + wlanProcessQueuedMsduInfo(prGlueInfo->prAdapter, prMsduInfo); + return WLAN_STATUS_RESOURCES; + } + + prBufCtrl = prUsbReq->prBufCtrl; + prBufCtrl->u4WrIdx = 0; + + HAL_WRITE_HIF_TXD(prChipInfo, prBufCtrl->pucBuf, u4Length); + prBufCtrl->u4WrIdx += prChipInfo->u2HifTxdSize; + + memcpy(prBufCtrl->pucBuf + prChipInfo->u2HifTxdSize, pucBuf, u4Length); + prBufCtrl->u4WrIdx += u4Length; + + u4PaddingLength = (ALIGN_4(u4TotalLen) - u4TotalLen); + if (u4PaddingLength) { + memset(prBufCtrl->pucBuf + prBufCtrl->u4WrIdx, 0, u4PaddingLength); + prBufCtrl->u4WrIdx += u4PaddingLength; + } + + memset(prBufCtrl->pucBuf + prBufCtrl->u4WrIdx, 0, LEN_USB_UDMA_TX_TERMINATOR); + prBufCtrl->u4WrIdx += LEN_USB_UDMA_TX_TERMINATOR; + + if (!prMsduInfo->pfTxDoneHandler) { + QUEUE_INSERT_TAIL(&prUsbReq->rSendingDataMsduInfoList, (struct QUE_ENTRY *) prMsduInfo); + } else { + KAL_SPIN_LOCK_DECLARATION(); + + /* Record native packet pointer for Tx done log */ + WLAN_GET_FIELD_32(&prMsduInfo->prPacket, + &prMsduInfo->u4TxDoneTag); + + KAL_ACQUIRE_SPIN_LOCK(prGlueInfo->prAdapter, + SPIN_LOCK_TXING_MGMT_LIST); + QUEUE_INSERT_TAIL( + &(prGlueInfo->prAdapter->rTxCtrl.rTxMgmtTxingQueue), + (struct QUE_ENTRY *) prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prGlueInfo->prAdapter, + SPIN_LOCK_TXING_MGMT_LIST); + } + + *((uint8_t *)&prUsbReq->prPriv) = ucTc; + usb_fill_bulk_urb(prUsbReq->prUrb, + prHifInfo->udev, + usb_sndbulkpipe(prHifInfo->udev, arTcToUSBEP[ucTc]), + (void *)prUsbReq->prBufCtrl->pucBuf, + prBufCtrl->u4WrIdx, halTxUSBSendDataComplete, (void *)prUsbReq); +#if CFG_USB_CONSISTENT_DMA + prUsbReq->prUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; +#endif + + usb_anchor_urb(prUsbReq->prUrb, &prHifInfo->rTxDataAnchor); + + spin_lock_irqsave(&prHifInfo->rTxDataQLock, flags); + + if (prHifInfo->prGlueInfo->prAdapter->ucSerState == SER_IDLE_DONE) { + ret = glUsbSubmitUrb(prHifInfo, prUsbReq->prUrb, + SUBMIT_TYPE_TX_DATA); + if (ret) { + DBGLOG(HAL, ERROR, + "glUsbSubmitUrb() error (0x%X) (EP%d OUT)\n", + ret, arTcToUSBEP[ucTc]); + + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, flags); + + halTxUSBProcessMsduDone(prHifInfo->prGlueInfo, + prUsbReq); + prBufCtrl->u4WrIdx = 0; + usb_unanchor_urb(prUsbReq->prUrb); + glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxDataFreeQ, + prUsbReq, &prHifInfo->rTxDataQLock, + FALSE); + return WLAN_STATUS_FAILURE; + } + } else { + DBGLOG(HAL, ERROR, "[SER] BYPASS USB send data\n"); + + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, flags); + + halTxUSBProcessMsduDone(prHifInfo->prGlueInfo, + prUsbReq); + prBufCtrl->u4WrIdx = 0; + usb_unanchor_urb(prUsbReq->prUrb); + glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxDataFreeQ, prUsbReq, + &prHifInfo->rTxDataQLock, FALSE); + return WLAN_STATUS_FAILURE; + } + + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, flags); +#endif + + if (wlanIsChipRstRecEnabled(prGlueInfo->prAdapter) + && wlanIsChipNoAck(prGlueInfo->prAdapter)) { + wlanChipRstPreAct(prGlueInfo->prAdapter); + DBGLOG(HAL, ERROR, "usb trigger whole reset\n"); + HAL_WIFI_FUNC_CHIP_RESET(prGlueInfo->prAdapter); + } + return u4Status; +} + +uint32_t halTxUSBKickData(IN struct GLUE_INFO *prGlueInfo) +{ +#if CFG_USB_TX_AGG + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + struct USB_REQ *prUsbReq; + struct BUF_CTRL *prBufCtrl; + uint8_t ucTc; + unsigned long flags; + + spin_lock_irqsave(&prHifInfo->rTxDataQLock, flags); + + for (ucTc = TC0_INDEX; ucTc < USB_TC_NUM; ucTc++) { + if (list_empty(&prHifInfo->rTxDataFreeQ[ucTc])) + continue; + + prUsbReq = list_entry(prHifInfo->rTxDataFreeQ[ucTc].next, struct USB_REQ, list); + prBufCtrl = prUsbReq->prBufCtrl; + + if (prBufCtrl->u4WrIdx) + halTxUSBSendAggData(prHifInfo, ucTc, prUsbReq); + } + + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, flags); +#endif + + return WLAN_STATUS_SUCCESS; +} + +void halTxUSBSendDataComplete(struct urb *urb) +{ + struct USB_REQ *prUsbReq = urb->context; + struct GL_HIF_INFO *prHifInfo = prUsbReq->prHifInfo; + struct GLUE_INFO *prGlueInfo = prHifInfo->prGlueInfo; + + glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxDataCompleteQ, prUsbReq, &prHifInfo->rTxDataQLock, FALSE); + +#if CFG_USB_TX_HANDLE_IN_HIF_THREAD + kalSetIntEvent(prGlueInfo); +#else + /*tasklet_hi_schedule(&prGlueInfo->rTxCompleteTask);*/ + tasklet_schedule(&prGlueInfo->rTxCompleteTask); +#endif +} + +void halTxUSBProcessMsduDone(IN struct GLUE_INFO *prGlueInfo, struct USB_REQ *prUsbReq) +{ + uint8_t ucTc; + struct QUE rFreeQueue; + struct QUE *prFreeQueue; + struct urb *urb = prUsbReq->prUrb; + uint32_t u4SentDataSize; + + if (g_u4HaltFlag) { + DBGLOG(TX, WARN, "wlan is halt\n"); + return; + } + + ucTc = *((uint8_t *)&prUsbReq->prPriv) & TC_MASK; + + prFreeQueue = &rFreeQueue; + QUEUE_INITIALIZE(prFreeQueue); + QUEUE_MOVE_ALL((prFreeQueue), (&(prUsbReq->rSendingDataMsduInfoList))); + if (g_pfTxDataDoneCb) + g_pfTxDataDoneCb(prGlueInfo, prFreeQueue); + + u4SentDataSize = urb->actual_length - LEN_USB_UDMA_TX_TERMINATOR; + nicTxReleaseResource_PSE(prGlueInfo->prAdapter, ucTc, + nicTxGetPageCount(prGlueInfo->prAdapter, u4SentDataSize, TRUE), TRUE); +} + +void halTxUSBProcessDataComplete(IN struct ADAPTER *prAdapter, struct USB_REQ *prUsbReq) +{ + uint8_t ucTc; + u_int8_t fgFfa; + struct urb *urb = prUsbReq->prUrb; + struct GL_HIF_INFO *prHifInfo = prUsbReq->prHifInfo; +#if CFG_USB_TX_AGG + struct BUF_CTRL *prBufCtrl = prUsbReq->prBufCtrl; +#endif + unsigned long flags; + + ucTc = *((uint8_t *)&prUsbReq->prPriv) & TC_MASK; + fgFfa = *((uint8_t *)&prUsbReq->prPriv) & FFA_MASK; + + if (urb->status != 0) { + DBGLOG(TX, ERROR, "[%s] send DATA fail (status = %d)\n", __func__, urb->status); + /* TODO: handle error */ + } + + halTxUSBProcessMsduDone(prAdapter->prGlueInfo, prUsbReq); + + spin_lock_irqsave(&prHifInfo->rTxDataQLock, flags); +#if CFG_USB_TX_AGG + prBufCtrl->u4WrIdx = 0; + + if ((fgFfa == FALSE) || list_empty(&prHifInfo->rTxDataFreeQ[ucTc])) + list_add_tail(&prUsbReq->list, &prHifInfo->rTxDataFreeQ[ucTc]); + else + list_add_tail(&prUsbReq->list, &prHifInfo->rTxDataFfaQ); + + if (usb_anchor_empty(&prHifInfo->rTxDataAnchor[ucTc])) { + prUsbReq = list_entry(prHifInfo->rTxDataFreeQ[ucTc].next, struct USB_REQ, list); + prBufCtrl = prUsbReq->prBufCtrl; + + if (prBufCtrl->u4WrIdx != 0) + halTxUSBSendAggData(prHifInfo, ucTc, prUsbReq); /* TODO */ + } +#else + list_add_tail(&prUsbReq->list, &prHifInfo->rTxDataFreeQ); +#endif + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, flags); + + if (!HAL_IS_TX_DIRECT(prAdapter)) { + if (kalGetTxPendingCmdCount(prAdapter->prGlueInfo) > 0 || wlanGetTxPendingFrameCount(prAdapter) > 0) + kalSetEvent(prAdapter->prGlueInfo); + kalSetTxEvent2Hif(prAdapter->prGlueInfo); + } +} + +void halRxUSBSchedTask(void *info) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)info; + + /*tasklet_hi_schedule(&prGlueInfo->rRxTask);*/ + tasklet_schedule(&prGlueInfo->rRxTask); +} + +void halRxUSBDispatchCpu(struct GLUE_INFO *prGlueInfo) +{ +#if CFG_USB_RX_DISPATCH_CPU + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + int cpuid, ret; + + /* avoid possible deadlock when smp_call_function_single called + * with interrupts disabled. + */ + if (irqs_disabled()) { + tasklet_schedule(&prGlueInfo->rRxTask); + return; + } + + if (unlikely(prHifInfo->rx_cpuid == INVALID_CPUID)) { + for_each_online_cpu(cpuid) { + if (cpuid != smp_processor_id()) { + prHifInfo->rx_cpuid = cpuid; + break; + } + } + if (prHifInfo->rx_cpuid == INVALID_CPUID) + prHifInfo->rx_cpuid = smp_processor_id(); + + DBGLOG(HAL, STATE, "Dipatch Rx cpuid (src, dst) = %d, %d\n", + smp_processor_id(), prHifInfo->rx_cpuid); + } + ret = smp_call_function_single(prHifInfo->rx_cpuid, halRxUSBSchedTask, + (void *)prGlueInfo, 0); + if (unlikely(ret != 0)) { + DBGLOG(HAL, ERROR, "smp_call_function_single ret = %d\n", ret); + halRxUSBSchedTask(prGlueInfo); + prHifInfo->rx_cpuid = INVALID_CPUID; + } +#else + halRxUSBSchedTask(prGlueInfo); +#endif /* CFG_USB_RX_DISPATCH_CPU */ +} + +uint32_t halRxUSBEnqueueRFB(IN struct ADAPTER *prAdapter, IN uint8_t *pucBuf, IN uint32_t u4Length, + IN uint32_t u4MinRfbCnt) +{ + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct mt66xx_chip_info *prChipInfo; + struct RX_CTRL *prRxCtrl = &prAdapter->rRxCtrl; + struct SW_RFB *prSwRfb = (struct SW_RFB *) NULL; + struct HW_MAC_RX_DESC *prRxStatus; + uint32_t u4RemainCount; + uint16_t u2RxByteCount; + uint8_t *pucRxFrame; + uint32_t u4EnqCnt = 0; +#if CFG_TCP_IP_CHKSUM_OFFLOAD + uint32_t *pu4HwAppendDW; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prChipInfo = prAdapter->chip_info; + + pucRxFrame = pucBuf; + u4RemainCount = u4Length; + while (u4RemainCount > 4) { + u2RxByteCount = HAL_RX_STATUS_GET_RX_BYTE_CNT((struct HW_MAC_RX_DESC *) pucRxFrame); + u2RxByteCount = ALIGN_4(u2RxByteCount) + LEN_USB_RX_PADDING_CSO; + + if (u2RxByteCount <= CFG_RX_MAX_PKT_SIZE) { + prSwRfb = NULL; + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + if (prRxCtrl->rFreeSwRfbList.u4NumElem > u4MinRfbCnt) + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, struct SW_RFB *); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + if (!prSwRfb) + return u4Length - u4RemainCount; + + kalMemCopy(prSwRfb->pucRecvBuff, pucRxFrame, u2RxByteCount); + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + prSwRfb->ucPacketType = (uint8_t) HAL_RX_STATUS_GET_PKT_TYPE(prRxStatus); + /* DBGLOG(RX, TRACE, ("ucPacketType = %d\n", prSwRfb->ucPacketType)); */ +#if CFG_TCP_IP_CHKSUM_OFFLOAD + pu4HwAppendDW = (uint32_t *) prRxStatus; + pu4HwAppendDW += (ALIGN_4(prRxStatus->u2RxByteCount) >> 2); + prSwRfb->u4TcpUdpIpCksStatus = *pu4HwAppendDW; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ +#if DBG + DBGLOG(RX, TRACE, "Rx status flag = %x wlan index = %d SecMode = %d\n", + prRxStatus->u2StatusFlag, prRxStatus->ucWlanIdx, HAL_RX_STATUS_GET_SEC_MODE(prRxStatus)); +#endif + if (HAL_IS_RX_DIRECT(prAdapter)) { + switch (prSwRfb->ucPacketType) { + case RX_PKT_TYPE_RX_DATA: + if (HAL_MON_EN(prAdapter)) + nicRxProcessMonitorPacket( + prAdapter, prSwRfb); + else + nicRxProcessDataPacket( + prAdapter, prSwRfb); + break; + default: + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_INSERT_TAIL(&prRxCtrl->rReceivedRfbList, &prSwRfb->rQueEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + u4EnqCnt++; + break; + } + } else { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_INSERT_TAIL(&prRxCtrl->rReceivedRfbList, &prSwRfb->rQueEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + u4EnqCnt++; + } + RX_INC_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT); + } else { + DBGLOG(RX, WARN, "Rx byte count:%u exceeds SW_RFB max length:%u\n!", + u2RxByteCount, CFG_RX_MAX_PKT_SIZE); + DBGLOG_MEM32(RX, WARN, pucRxFrame, + prChipInfo->rxd_size); + break; + } + + u4RemainCount -= u2RxByteCount; + pucRxFrame += u2RxByteCount; + } + + if (u4EnqCnt) { + set_bit(GLUE_FLAG_RX_BIT, &(prGlueInfo->ulFlag)); + wake_up_interruptible(&(prGlueInfo->waitq)); + } + + return u4Length; +} + +uint32_t halRxUSBReceiveEvent(IN struct ADAPTER *prAdapter, IN u_int8_t fgFillUrb) +{ + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + struct USB_REQ *prUsbReq; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + int ret; + + while (1) { + prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, &prHifInfo->rRxEventQLock); + if (prUsbReq == NULL) + return WLAN_STATUS_RESOURCES; + + usb_anchor_urb(prUsbReq->prUrb, &prHifInfo->rRxEventAnchor); + + prUsbReq->prBufCtrl->u4ReadSize = 0; + if (prHifInfo->eEventEpType == EVENT_EP_TYPE_INTR && fgFillUrb) { + usb_fill_int_urb(prUsbReq->prUrb, + prHifInfo->udev, + usb_rcvintpipe(prHifInfo->udev, + USB_EVENT_EP_IN), + (void *)prUsbReq->prBufCtrl->pucBuf, + prUsbReq->prBufCtrl->u4BufSize, + halRxUSBReceiveEventComplete, + (void *)prUsbReq, + 1); + } else if (prHifInfo->eEventEpType == EVENT_EP_TYPE_BULK) { + usb_fill_bulk_urb(prUsbReq->prUrb, + prHifInfo->udev, + usb_rcvbulkpipe(prHifInfo->udev, + USB_EVENT_EP_IN), + (void *)prUsbReq->prBufCtrl->pucBuf, + prUsbReq->prBufCtrl->u4BufSize, + halRxUSBReceiveEventComplete, + (void *)prUsbReq); + } + ret = glUsbSubmitUrb(prHifInfo, prUsbReq->prUrb, + SUBMIT_TYPE_RX_EVENT); + if (ret) { + DBGLOG(HAL, ERROR, + "glUsbSubmitUrb() reports error (%d) [%s] (EP%d IN)\n", + ret, __func__, (USB_EVENT_EP_IN & 0x0F)); + usb_unanchor_urb(prUsbReq->prUrb); + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, + &prHifInfo->rRxEventQLock, FALSE); + break; + } + } + + return u4Status; +} + +void halRxUSBReceiveEventComplete(struct urb *urb) +{ + struct USB_REQ *prUsbReq = urb->context; + struct GL_HIF_INFO *prHifInfo = prUsbReq->prHifInfo; + struct GLUE_INFO *prGlueInfo = prHifInfo->prGlueInfo; + + if (!(prHifInfo->state == USB_STATE_LINK_UP || + prHifInfo->state == USB_STATE_READY || + prHifInfo->state == USB_STATE_PRE_RESUME || + prHifInfo->state == USB_STATE_PRE_SUSPEND_START)) { + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); + return; + } + + /* Hif power off wifi, drop rx packets and continue polling RX packets until RX path empty */ + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); + halRxUSBReceiveEvent(prGlueInfo->prAdapter, FALSE); + return; + } + + if (urb->status == -ESHUTDOWN || urb->status == -ENOENT) { + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); + DBGLOG(RX, ERROR, "USB device shutdown skip Rx [%s]\n", __func__); + return; + } + +#if CFG_USB_RX_HANDLE_IN_HIF_THREAD + DBGLOG(RX, TRACE, "[%s] Rx URB[0x%p] Len[%u] Sts[%u]\n", __func__, urb, urb->actual_length, urb->status); + + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventCompleteQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); + + kalSetIntEvent(prGlueInfo); +#else + if (urb->status == 0) { + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventCompleteQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); + + halRxUSBDispatchCpu(prGlueInfo); + } else { + DBGLOG(RX, ERROR, "[%s] receive EVENT fail (status = %d)\n", __func__, urb->status); + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); + + halRxUSBReceiveEvent(prGlueInfo->prAdapter, FALSE); + } +#endif +} + +uint32_t halRxUSBReceiveData(IN struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + struct USB_REQ *prUsbReq; + uint32_t u4Status = WLAN_STATUS_SUCCESS; + int ret; + + while (1) { + prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, &prHifInfo->rRxDataQLock); + if (prUsbReq == NULL) + return WLAN_STATUS_RESOURCES; + + usb_anchor_urb(prUsbReq->prUrb, &prHifInfo->rRxDataAnchor); + + prUsbReq->prBufCtrl->u4ReadSize = 0; + usb_fill_bulk_urb(prUsbReq->prUrb, + prHifInfo->udev, + usb_rcvbulkpipe(prHifInfo->udev, USB_DATA_EP_IN), + (void *)prUsbReq->prBufCtrl->pucBuf, + prUsbReq->prBufCtrl->u4BufSize, halRxUSBReceiveDataComplete, (void *)prUsbReq); + ret = glUsbSubmitUrb(prHifInfo, prUsbReq->prUrb, + SUBMIT_TYPE_RX_DATA); + if (ret) { + DBGLOG(HAL, ERROR, + "glUsbSubmitUrb() reports error (%d) [%s] (EP%d IN)\n", + ret, __func__, (USB_EVENT_EP_IN & 0x0F)); + usb_unanchor_urb(prUsbReq->prUrb); + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE); + break; + } + } + + return u4Status; +} + +void halRxUSBReceiveDataComplete(struct urb *urb) +{ + struct USB_REQ *prUsbReq = urb->context; + struct GL_HIF_INFO *prHifInfo = prUsbReq->prHifInfo; + struct GLUE_INFO *prGlueInfo = prHifInfo->prGlueInfo; + + if (!(prHifInfo->state == USB_STATE_LINK_UP || + prHifInfo->state == USB_STATE_READY || + prHifInfo->state == USB_STATE_PRE_RESUME || + prHifInfo->state == USB_STATE_PRE_SUSPEND_START)) { + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE); + return; + } + + /* Hif power off wifi, drop rx packets and continue polling RX packets until RX path empty */ + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE); + halRxUSBReceiveData(prGlueInfo->prAdapter); + return; + } + + if (urb->status == -ESHUTDOWN || urb->status == -ENOENT) { + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE); + DBGLOG(RX, ERROR, "USB device shutdown skip Rx [%s]\n", __func__); + return; + } + +#if CFG_USB_RX_HANDLE_IN_HIF_THREAD + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataCompleteQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE); + + kalSetIntEvent(prGlueInfo); +#else + if (urb->status == 0) { + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataCompleteQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE); + + halRxUSBDispatchCpu(prGlueInfo); + } else { + DBGLOG_LIMITED(RX, ERROR, + "Receive DATA fail (status = %d)\n", urb->status); + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE); + + halRxUSBReceiveData(prGlueInfo->prAdapter); + } +#endif +} + +void halRxUSBProcessEventDataComplete(IN struct ADAPTER *prAdapter, + enum usb_rx_type type) +{ + struct USB_REQ *prUsbReq; + struct urb *prUrb; + struct BUF_CTRL *prBufCtrl; + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + uint8_t *pucBufAddr; + uint32_t u4BufLen; + static u_int8_t s_fgOutOfSwRfb = FALSE; + static uint32_t s_u4OutOfSwRfbPrintLimit; + struct list_head *prCompleteQ, *prFreeQ; + spinlock_t *prQLock; + uint32_t u4MinRfbCnt; + + if (type == USB_RX_TYPE_DATA) { + prCompleteQ = &prHifInfo->rRxDataCompleteQ; + prFreeQ = &prHifInfo->rRxDataFreeQ; + prQLock = &prHifInfo->rRxDataQLock; + u4MinRfbCnt = USB_RX_DATA_RFB_RSV_CNT; + } else if (type == USB_RX_TYPE_EVENT) { + prCompleteQ = &prHifInfo->rRxEventCompleteQ; + prFreeQ = &prHifInfo->rRxEventFreeQ; + prQLock = &prHifInfo->rRxEventQLock; + u4MinRfbCnt = USB_RX_EVENT_RFB_RSV_CNT; + } else { + return; + } + + /* Process complete event/data */ + prUsbReq = glUsbDequeueReq(prHifInfo, prCompleteQ, prQLock); + while (prUsbReq) { + prUrb = prUsbReq->prUrb; + prBufCtrl = prUsbReq->prBufCtrl; + + DBGLOG(RX, LOUD, "[%s] Rx URB[0x%p] Len[%u] Sts[%u]\n", __func__, + prUrb, prUrb->actual_length, prUrb->status); + + if (prUrb->status != 0) { + DBGLOG(RX, ERROR, "[%s] receive EVENT/DATA fail (status = %d)\n", __func__, prUrb->status); + + glUsbEnqueueReq(prHifInfo, prFreeQ, prUsbReq, prQLock, + FALSE); + prUsbReq = glUsbDequeueReq(prHifInfo, prCompleteQ, + prQLock); + continue; + } + + pucBufAddr = prBufCtrl->pucBuf + prBufCtrl->u4ReadSize; + u4BufLen = prUrb->actual_length - prBufCtrl->u4ReadSize; + + prBufCtrl->u4ReadSize += halRxUSBEnqueueRFB(prAdapter, pucBufAddr, u4BufLen, u4MinRfbCnt); + + if (unlikely(prUrb->actual_length - prBufCtrl->u4ReadSize > 4)) { + if (s_fgOutOfSwRfb == FALSE) { + if ((long)jiffies - (long)s_u4OutOfSwRfbPrintLimit > 0) { + DBGLOG(RX, WARN, "Out of SwRfb!\n"); + s_u4OutOfSwRfbPrintLimit = jiffies + MSEC_TO_JIFFIES(SW_RFB_LOG_LIMIT_MS); + } + s_fgOutOfSwRfb = TRUE; + } + glUsbEnqueueReq(prHifInfo, prCompleteQ, prUsbReq, + prQLock, TRUE); + + set_bit(GLUE_FLAG_RX_BIT, &prGlueInfo->ulFlag); + wake_up_interruptible(&prGlueInfo->waitq); + + schedule_delayed_work(&prGlueInfo->rRxPktDeAggWork, MSEC_TO_JIFFIES(SW_RFB_RECHECK_MS)); + break; + } + + if (unlikely(s_fgOutOfSwRfb == TRUE)) + s_fgOutOfSwRfb = FALSE; + + glUsbEnqueueReq(prHifInfo, prFreeQ, prUsbReq, prQLock, FALSE); + prUsbReq = glUsbDequeueReq(prHifInfo, prCompleteQ, prQLock); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief enable global interrupt +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void halEnableInterrupt(IN struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo; + struct GL_HIF_INFO *prHifInfo; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + prHifInfo = &prGlueInfo->rHifInfo; + + halRxUSBReceiveData(prAdapter); + if (prHifInfo->eEventEpType != EVENT_EP_TYPE_DATA_EP) + halRxUSBReceiveEvent(prAdapter, TRUE); + + glUdmaRxAggEnable(prGlueInfo, TRUE); +} /* end of halEnableInterrupt() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief disable global interrupt +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void halDisableInterrupt(IN struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo; + struct GL_HIF_INFO *prHifInfo; + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + prHifInfo = &prGlueInfo->rHifInfo; + + usb_kill_anchored_urbs(&prHifInfo->rRxDataAnchor); + usb_kill_anchored_urbs(&prHifInfo->rRxEventAnchor); + + glUdmaRxAggEnable(prGlueInfo, FALSE); + prAdapter->fgIsIntEnable = FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to process the POWER OFF procedure. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t halSetDriverOwn(IN struct ADAPTER *prAdapter) +{ + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to process the POWER ON procedure. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void halSetFWOwn(IN struct ADAPTER *prAdapter, IN u_int8_t fgEnableGlobalInt) +{ +} + +void halWakeUpWiFi(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo; + u_int8_t fgResult; + uint8_t ucCount = 0; + + DBGLOG(INIT, INFO, "Power on Wi-Fi....\n"); + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + HAL_WIFI_FUNC_READY_CHECK(prAdapter, WIFI_FUNC_INIT_DONE, &fgResult); + + while (!fgResult) { + HAL_WIFI_FUNC_POWER_ON(prAdapter); + kalMdelay(50); + HAL_WIFI_FUNC_READY_CHECK(prAdapter, WIFI_FUNC_INIT_DONE, &fgResult); + + ucCount++; + + if (ucCount >= 5) { + DBGLOG(INIT, WARN, "Power on failed!!!\n"); + break; + } + } + + if (prHifInfo->state == USB_STATE_WIFI_OFF) + glUsbSetState(&prAdapter->prGlueInfo->rHifInfo, + USB_STATE_READY); + + prAdapter->fgIsFwOwn = FALSE; +} + +void halEnableFWDownload(IN struct ADAPTER *prAdapter, IN u_int8_t fgEnable) +{ +#if (CFG_UMAC_GENERATION >= 0x20) + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + + prChipInfo = prAdapter->chip_info; + if (prChipInfo->asicEnableFWDownload) { + prChipInfo->asicEnableFWDownload(prAdapter, fgEnable); + } else { + uint32_t u4Value = 0; + + HAL_MCR_RD(prAdapter, UDMA_TX_QSEL, &u4Value); + + if (fgEnable) + u4Value |= FW_DL_EN; + else + u4Value &= ~FW_DL_EN; + + HAL_MCR_WR(prAdapter, UDMA_TX_QSEL, u4Value); + } +#endif +} + +void halDevInit(IN struct ADAPTER *prAdapter) +{ + struct GLUE_INFO *prGlueInfo; + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + + glUdmaRxAggEnable(prGlueInfo, FALSE); + glUdmaTxRxEnable(prGlueInfo, TRUE); +} + +u_int8_t halTxIsDataBufEnough(IN struct ADAPTER *prAdapter, IN struct MSDU_INFO *prMsduInfo) +{ + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; +#if CFG_USB_TX_AGG + struct USB_REQ *prUsbReq; + struct BUF_CTRL *prBufCtrl; +#endif + uint8_t ucTc; + struct sk_buff *skb; + uint32_t u4Length; + struct mt66xx_chip_info *prChipInfo; + + unsigned long flags; + + prChipInfo = prAdapter->chip_info; + skb = (struct sk_buff *)prMsduInfo->prPacket; + u4Length = skb->len; + u4Length += prChipInfo->u2HifTxdSize; + ucTc = USB_TRANS_MSDU_TC(prMsduInfo); + + spin_lock_irqsave(&prHifInfo->rTxDataQLock, flags); + +#if CFG_USB_TX_AGG + if (list_empty(&prHifInfo->rTxDataFreeQ[ucTc])) { + if (glUsbBorrowFfaReq(prHifInfo, ucTc) == FALSE) { + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, flags); + return FALSE; + } + } + + prUsbReq = list_entry(prHifInfo->rTxDataFreeQ[ucTc].next, struct USB_REQ, list); + prBufCtrl = prUsbReq->prBufCtrl; + + if (prHifInfo->rTxDataFreeQ[ucTc].next->next == &prHifInfo->rTxDataFreeQ[ucTc]) { + /* length of rTxDataFreeQ equals 1 */ + if (prBufCtrl->u4WrIdx + ALIGN_4(u4Length) > + prBufCtrl->u4BufSize - prHifInfo->u4AggRsvSize[ucTc] - LEN_USB_UDMA_TX_TERMINATOR) { + /* Buffer is not enough */ + if (glUsbBorrowFfaReq(prHifInfo, ucTc) == FALSE) { + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, + flags); + return FALSE; + } + } + } + prHifInfo->u4AggRsvSize[ucTc] += ALIGN_4(u4Length); +#else + if (list_empty(&prHifInfo->rTxDataFreeQ)) { + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, flags); + + return FALSE; + } +#endif + + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, flags); + return TRUE; +} + +void halProcessTxInterrupt(IN struct ADAPTER *prAdapter) +{ +#if CFG_USB_TX_HANDLE_IN_HIF_THREAD + struct USB_REQ *prUsbReq; + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + /* Process complete Tx cmd */ + prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxCmdCompleteQ, &prHifInfo->rTxCmdQLock); + while (prUsbReq) { + halTxUSBProcessCmdComplete(prAdapter, prUsbReq); + prUsbReq = glUsbDequeueReq(prHifInfo, + &prHifInfo->rTxCmdCompleteQ, + &prHifInfo->rTxCmdQLock); + } + + /* Process complete Tx data */ + prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxDataCompleteQ, + &prHifInfo->rTxDataQLock); + while (prUsbReq) { + halTxUSBProcessDataComplete(prAdapter, prUsbReq); + prUsbReq = glUsbDequeueReq(prHifInfo, + &prHifInfo->rTxDataCompleteQ, + &prHifInfo->rTxDataQLock); + } +#endif +} + +bool halHifSwInfoInit(IN struct ADAPTER *prAdapter) +{ + return true; +} + +void halRxProcessMsduReport(IN struct ADAPTER *prAdapter, IN OUT struct SW_RFB *prSwRfb) +{ + +} + +uint32_t halTxGetPageCount(IN struct ADAPTER *prAdapter, IN uint32_t u4FrameLength, IN u_int8_t fgIncludeDesc) +{ +#if CFG_USB_TX_AGG + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + uint32_t u4RequiredBufferSize; + uint32_t u4PageCount; + uint32_t u4TxHeadRoomSize = NIC_TX_DESC_AND_PADDING_LENGTH + prChipInfo->txd_append_size; + + /* Frame Buffer + * |<--Tx Descriptor-->|<--Tx descriptor padding-->| + * <--802.3/802.11 Header-->|<--Header padding-->|<--Payload-->| + */ + + if (fgIncludeDesc) + u4RequiredBufferSize = u4FrameLength; + else + u4RequiredBufferSize = u4TxHeadRoomSize + u4FrameLength; + + u4RequiredBufferSize = ALIGN_4(u4RequiredBufferSize); + + if (NIC_TX_PAGE_SIZE_IS_POWER_OF_2) + u4PageCount = (u4RequiredBufferSize + (NIC_TX_PAGE_SIZE - 1)) >> NIC_TX_PAGE_SIZE_IN_POWER_OF_2; + else + u4PageCount = (u4RequiredBufferSize + (NIC_TX_PAGE_SIZE - 1)) / NIC_TX_PAGE_SIZE; + + return u4PageCount; +#else + return 1; +#endif +} + +uint32_t halTxPollingResource(IN struct ADAPTER *prAdapter, IN uint8_t ucTC) +{ + return WLAN_STATUS_SUCCESS; +} + +void halSerHifReset(IN struct ADAPTER *prAdapter) +{ + uint32_t i; + + /** + * usb_reset_endpoint - Reset an endpoint's state. + * @dev: the device whose endpoint is to be reset + * @epaddr: the endpoint's address. Endpoint number for output, + * endpoint number + USB_DIR_IN for input + * + * Resets any host-side endpoint state such as the toggle bit, + * sequence number or current window. + * + * void usb_reset_endpoint(struct usb_device *dev, unsigned int epaddr); + */ + + /* reset ALL BULK OUT endpoints */ + for (i = MTK_USB_BULK_OUT_MIN_EP; i <= MTK_USB_BULK_OUT_MAX_EP; i++) + usb_reset_endpoint(prAdapter->prGlueInfo->rHifInfo.udev, i); + + /* reset ALL BULK IN endpoints */ + for (i = MTK_USB_BULK_IN_MIN_EP; i <= MTK_USB_BULK_IN_MAX_EP; i++) + usb_reset_endpoint(prAdapter->prGlueInfo->rHifInfo.udev, + (i | USB_DIR_IN)); +} + +void halProcessRxInterrupt(IN struct ADAPTER *prAdapter) +{ + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + if (g_u4HaltFlag) { + DBGLOG(RX, WARN, "wlan is halt\n"); + return; + } + + /* Process complete data */ + halRxUSBProcessEventDataComplete(prAdapter, USB_RX_TYPE_DATA); + halRxUSBReceiveData(prAdapter); + + if (prHifInfo->eEventEpType != EVENT_EP_TYPE_DATA_EP) { + /* Process complete event */ + halRxUSBProcessEventDataComplete(prAdapter, USB_RX_TYPE_EVENT); + halRxUSBReceiveEvent(prAdapter, FALSE); + } +} + +uint32_t halDumpHifStatus(IN struct ADAPTER *prAdapter, IN uint8_t *pucBuf, IN uint32_t u4Max) +{ + uint32_t u4CpuIdx, u4DmaIdx, u4Int, u4GloCfg, u4Reg; + uint32_t u4Len = 0; + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + uint8_t pBuffer[512] = {0}; + + HAL_MCR_RD(prAdapter, 0x820b0118, &u4CpuIdx); + HAL_MCR_RD(prAdapter, 0x820b011c, &u4DmaIdx); + HAL_MCR_RD(prAdapter, 0x820b0220, &u4Int); + HAL_MCR_RD(prAdapter, 0x820b0204, &u4GloCfg); + + LOGBUF(pucBuf, u4Max, u4Len, "\n"); + LOGBUF(pucBuf, u4Max, u4Len, "PDMA1R1 CPU[%u] DMA[%u] INT[0x%08x] CFG[0x%08x]\n", u4CpuIdx, + u4DmaIdx, u4Int, u4GloCfg); + + HAL_MCR_RD(prAdapter, UDMA_WLCFG_0, &u4Reg); + + LOGBUF(pucBuf, u4Max, u4Len, "UDMA WLCFG[0x%08x]\n", u4Reg); + + LOGBUF(pucBuf, u4Max, u4Len, "\n"); + LOGBUF(pucBuf, u4Max, u4Len, "VenderID: %04x\n", + glGetUsbDeviceVendorId(prGlueInfo->rHifInfo.udev)); + LOGBUF(pucBuf, u4Max, u4Len, "ProductID: %04x\n", + glGetUsbDeviceProductId(prGlueInfo->rHifInfo.udev)); + + glGetUsbDeviceManufacturerName(prGlueInfo->rHifInfo.udev, pBuffer, + sizeof(pBuffer)); + LOGBUF(pucBuf, u4Max, u4Len, "Manufacturer: %s\n", + pBuffer); + + glGetUsbDeviceProductName(prGlueInfo->rHifInfo.udev, pBuffer, + sizeof(pBuffer)); + LOGBUF(pucBuf, u4Max, u4Len, "Product: %s\n", pBuffer); + + glGetUsbDeviceSerialNumber(prGlueInfo->rHifInfo.udev, pBuffer, + sizeof(pBuffer)); + LOGBUF(pucBuf, u4Max, u4Len, "SerialNumber: %s\n", + pBuffer); + + return u4Len; +} + +void halGetCompleteStatus(IN struct ADAPTER *prAdapter, OUT uint32_t *pu4IntStatus) +{ +#if CFG_USB_RX_HANDLE_IN_HIF_THREAD || CFG_USB_TX_HANDLE_IN_HIF_THREAD + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; +#endif + + *pu4IntStatus = 0; + +#if CFG_USB_RX_HANDLE_IN_HIF_THREAD + if (!list_empty(&prHifInfo->rRxDataCompleteQ) || !list_empty(&prHifInfo->rRxEventCompleteQ)) + *pu4IntStatus |= WHISR_RX0_DONE_INT; +#endif + +#if CFG_USB_TX_HANDLE_IN_HIF_THREAD + if (!list_empty(&prHifInfo->rTxDataCompleteQ) || !list_empty(&prHifInfo->rTxCmdCompleteQ)) + *pu4IntStatus |= WHISR_TX_DONE_INT; +#endif +} + +u_int8_t halIsPendingRx(IN struct ADAPTER *prAdapter) +{ +#if CFG_USB_RX_HANDLE_IN_HIF_THREAD + struct GL_HIF_INFO *prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + if (!list_empty(&prHifInfo->rRxDataCompleteQ) || !list_empty(&prHifInfo->rRxEventCompleteQ)) + return TRUE; + else + return FALSE; +#else + return FALSE; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Send HIF_CTRL command to inform FW stop send packet/event to host +* suspend = 1 +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (void) +*/ +/*----------------------------------------------------------------------------*/ +void halPreSuspendCmd(IN struct ADAPTER *prAdapter) +{ + struct CMD_HIF_CTRL rCmdHifCtrl; + uint32_t rStatus; + + rCmdHifCtrl.ucHifType = ENUM_HIF_TYPE_USB; + rCmdHifCtrl.ucHifDirection = ENUM_HIF_TX; + rCmdHifCtrl.ucHifStop = 1; + rCmdHifCtrl.ucHifSuspend = 1; + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_HIF_CTRL, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct CMD_HIF_CTRL), + (uint8_t *)&rCmdHifCtrl, + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (kalIsResetting()) + return; + + ASSERT(rStatus == WLAN_STATUS_PENDING); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Send HIF_CTRL command to inform FW allow send packet/event to host +* suspend = 0 +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (void) +*/ +/*----------------------------------------------------------------------------*/ +void halPreResumeCmd(IN struct ADAPTER *prAdapter) +{ + struct CMD_HIF_CTRL rCmdHifCtrl; + uint32_t rStatus; + + rCmdHifCtrl.ucHifType = ENUM_HIF_TYPE_USB; + rCmdHifCtrl.ucHifDirection = ENUM_HIF_TX; + rCmdHifCtrl.ucHifStop = 0; + rCmdHifCtrl.ucHifSuspend = 0; + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_HIF_CTRL, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* nicEventHifCtrl */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct CMD_HIF_CTRL), + (uint8_t *)&rCmdHifCtrl, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (kalIsResetting()) + return; + + ASSERT(rStatus == WLAN_STATUS_PENDING); +} + +void halUSBPreSuspendDone(IN struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + unsigned long flags; + struct GL_HIF_INFO *prHifInfo; + + ASSERT(prAdapter); + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + spin_lock_irqsave(&prHifInfo->rStateLock, flags); + + if (prHifInfo->state == USB_STATE_LINK_UP || + prHifInfo->state == USB_STATE_READY || + prHifInfo->state == USB_STATE_PRE_SUSPEND_START) + prHifInfo->state = USB_STATE_PRE_SUSPEND_DONE; + else + DBGLOG(HAL, ERROR, "Previous USB state (%d)!\n", + prHifInfo->state); + + spin_unlock_irqrestore(&prHifInfo->rStateLock, flags); +} + +void halUSBPreSuspendTimeout(IN struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo) +{ + unsigned long flags; + struct GL_HIF_INFO *prHifInfo; + + ASSERT(prAdapter); + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + spin_lock_irqsave(&prHifInfo->rStateLock, flags); + + if (prHifInfo->state == USB_STATE_LINK_UP || + prHifInfo->state == USB_STATE_READY || + prHifInfo->state == USB_STATE_PRE_SUSPEND_START) + prHifInfo->state = USB_STATE_PRE_SUSPEND_FAIL; + else + DBGLOG(HAL, ERROR, "Previous USB state (%d)!\n", + prHifInfo->state); + + spin_unlock_irqrestore(&prHifInfo->rStateLock, flags); +} + +uint32_t halGetValidCoalescingBufSize(IN struct ADAPTER *prAdapter) +{ + uint32_t u4BufSize; + + if (HIF_TX_COALESCING_BUFFER_SIZE > HIF_RX_COALESCING_BUFFER_SIZE) + u4BufSize = HIF_TX_COALESCING_BUFFER_SIZE; + else + u4BufSize = HIF_RX_COALESCING_BUFFER_SIZE; + + return u4BufSize; +} + +uint32_t halAllocateIOBuffer(IN struct ADAPTER *prAdapter) +{ + return WLAN_STATUS_SUCCESS; +} + +uint32_t halReleaseIOBuffer(IN struct ADAPTER *prAdapter) +{ + return WLAN_STATUS_SUCCESS; +} + +void halProcessAbnormalInterrupt(IN struct ADAPTER *prAdapter) +{ + +} + +void halProcessSoftwareInterrupt(IN struct ADAPTER *prAdapter) +{ + +} +void halDeAggRxPktWorker(struct work_struct *work) +{ + struct GLUE_INFO *prGlueInfo = ENTRY_OF(work, struct GLUE_INFO, rRxPktDeAggWork); + + halRxUSBDispatchCpu(prGlueInfo); +} + +void halRxTasklet(unsigned long data) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)data; +#if CFG_USB_RX_DISPATCH_CPU + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + + if (smp_processor_id() == prHifInfo->rx_cpuid) + halProcessRxInterrupt(prGlueInfo->prAdapter); + else + halRxUSBDispatchCpu(prGlueInfo); +#else + halProcessRxInterrupt(prGlueInfo->prAdapter); +#endif /* CFG_USB_RX_DISPATCH_CPU */ +} + +void halTxCompleteTasklet(unsigned long data) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)data; + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + struct USB_REQ *prUsbReq; + + /* Process complete Tx data */ + prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxDataCompleteQ, &prHifInfo->rTxDataQLock); + while (prUsbReq) { + halTxUSBProcessDataComplete(prGlueInfo->prAdapter, prUsbReq); + prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxDataCompleteQ, &prHifInfo->rTxDataQLock); + } +} + +/* Hif power off wifi */ +uint32_t halHifPowerOffWifi(IN struct ADAPTER *prAdapter) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + DBGLOG(INIT, INFO, "Power off Wi-Fi!\n"); + + /* Power off Wi-Fi */ + wlanSendNicPowerCtrlCmd(prAdapter, TRUE); + + rStatus = wlanCheckWifiFunc(prAdapter, FALSE); + + glUsbSetState(&prAdapter->prGlueInfo->rHifInfo, USB_STATE_WIFI_OFF); + + nicDisableInterrupt(prAdapter); + + wlanClearPendingInterrupt(prAdapter); + + halTxCancelAllSending(prAdapter); + + return rStatus; +} + +void halPrintHifDbgInfo(IN struct ADAPTER *prAdapter) +{ + +} + +u_int8_t halIsTxResourceControlEn(IN struct ADAPTER *prAdapter) +{ + return FALSE; +} + +void halTxResourceResetHwTQCounter(IN struct ADAPTER *prAdapter) +{ +} + +uint32_t halGetHifTxPageSize(IN struct ADAPTER *prAdapter) +{ + return HIF_TX_PAGE_SIZE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Check if HIF state is READY for upper layer cfg80211 +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (TRUE: ready, FALSE: not ready) +*/ +/*----------------------------------------------------------------------------*/ +bool halIsHifStateReady(IN struct ADAPTER *prAdapter, uint8_t *pucState) +{ + if (!prAdapter) + return FALSE; + + if (!prAdapter->prGlueInfo) + return FALSE; + + if (prAdapter->prGlueInfo->u4ReadyFlag == 0) + return FALSE; + + if (pucState) + *pucState = prAdapter->prGlueInfo->rHifInfo.state; + + if (prAdapter->prGlueInfo->rHifInfo.state != USB_STATE_READY) + return FALSE; + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Check if HIF state is LINK_UP or READY for USB TX/RX +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (TRUE: ready, FALSE: not ready) +*/ +/*----------------------------------------------------------------------------*/ +bool halIsHifStateLinkup(IN struct ADAPTER *prAdapter) +{ + if (!prAdapter) + return FALSE; + + if (!prAdapter->prGlueInfo) + return FALSE; + + if ((prAdapter->prGlueInfo->rHifInfo.state != USB_STATE_LINK_UP) && + (prAdapter->prGlueInfo->rHifInfo.state != USB_STATE_READY)) + return FALSE; + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Check if HIF state is during supend process +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (TRUE: suspend, reject the caller action. FALSE: not suspend) +*/ +/*----------------------------------------------------------------------------*/ +bool halIsHifStateSuspend(IN struct ADAPTER *prAdapter) +{ + enum usb_state state; + + if (!prAdapter) + return FALSE; + + if (!prAdapter->prGlueInfo) + return FALSE; + + state = prAdapter->prGlueInfo->rHifInfo.state; + + if (state == USB_STATE_SUSPEND) + return TRUE; + + return FALSE; +} + + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/usb/include/cust_usb_id.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/usb/include/cust_usb_id.h new file mode 100644 index 0000000000000..5471e249f73a4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/usb/include/cust_usb_id.h @@ -0,0 +1,127 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "cust_usb_id.h" + * \brief Define USB vid/pid table for customers + */ + + +#ifndef _CUST_USB_ID_H +#define _CUST_USB_ID_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 +******************************************************************************** +*/ +#if CFG_CHIP_RESET_SUPPORT +/** +* For chip reset pin set low time +*/ +#define RESET_PIN_SET_LOW_TIME 500 + +/** + * For chip reset pin number configureation + */ +#define WIFI_DONGLE_RESET_GPIO_PIN 220 +#endif + +/*! + * \brief Additional USB vid/pid tables for customers. + * Please add your vid/pid in table below as the example shows. + * + */ +#define CUST_USB_ID_TABLES \ +/* + * { USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x7618, 0xff, 0xff, 0xff), \ + * .driver_info = (kernel_ulong_t)&mt66xx_driver_data_mt7668},\ + * { USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x7658, 0xff, 0xff, 0xff), \ + * .driver_info = (kernel_ulong_t)&mt66xx_driver_data_mt7668},\ +*/ + +/******************************************************************************* +* 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 /* _CUST_USB_ID_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/usb/include/hif.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/usb/include/hif.h new file mode 100644 index 0000000000000..a0cf6826e6033 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/usb/include/hif.h @@ -0,0 +1,459 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \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 +*/ + + +#ifndef _HIF_H +#define _HIF_H + +#include "nic_cmd_event.h" +#include "wlan_typedef.h" +#include "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 +******************************************************************************** +*/ + +#if defined(_HIF_USB) +#define HIF_NAME "USB" +#else +#error "No HIF defined!" +#endif +#define HIF_CR4_FWDL_SECTION_NUM 2 +#define HIF_IMG_DL_STATUS_PORT_IDX 0 +#define HIF_IST_LOOP_COUNT (4) +#define HIF_IST_TX_THRESHOLD (1) /* Min msdu count to trigger Tx during INT polling state */ + +#define HIF_NUM_OF_QM_RX_PKT_NUM (512) + +#define HIF_TX_BUFF_COUNT_TC0 256 +#define HIF_TX_BUFF_COUNT_TC1 256 +#define HIF_TX_BUFF_COUNT_TC2 256 +#define HIF_TX_BUFF_COUNT_TC3 256 +#define HIF_TX_BUFF_COUNT_TC4 256 +#define HIF_TX_BUFF_COUNT_TC5 256 + +#define HIF_TX_RESOURCE_CTRL 0 /* enable/disable TX resource control */ +#define HIF_TX_RESOURCE_CTRL_PLE 0 /* enable/disable TX resource control PLE */ + + +#if CFG_USB_TX_AGG +#define HIF_TX_PAGE_SIZE_IN_POWER_OF_2 0 +#define HIF_TX_PAGE_SIZE 1 /* in unit of bytes */ +#else +#define HIF_TX_PAGE_SIZE_IN_POWER_OF_2 11 +#define HIF_TX_PAGE_SIZE 2048 /* in unit of bytes */ +#endif + +#define USB_EVENT_TYPE (EVENT_EP_TYPE_UNKONW) + +#define USB_CMD_EP_OUT (USB_DATA_BULK_OUT_EP8) +#define USB_EVENT_EP_IN (0x85) +#define USB_DATA_EP_IN (0x84) + +#define HIF_TX_INIT_CMD_PORT USB_CMD_EP_OUT + +#ifdef CFG_USB_REQ_TX_DATA_FFA_CNT +#define USB_REQ_TX_DATA_FFA_CNT (CFG_USB_REQ_TX_DATA_FFA_CNT) /* platform specific USB_REQ_TX_DATA_FFA_CNT */ +#else +#define USB_REQ_TX_DATA_FFA_CNT (10) +#endif + +#ifdef CFG_USB_REQ_TX_DATA_CNT +#define USB_REQ_TX_DATA_CNT (CFG_USB_REQ_TX_DATA_CNT) /* platform specific USB_REQ_TX_DATA_CNT */ +#else +#if CFG_USB_TX_AGG +#define USB_REQ_TX_DATA_CNT (2) /* must be >= 2 */ +#else +#define USB_REQ_TX_DATA_CNT (CFG_TX_MAX_PKT_NUM) +#endif +#endif + +#define USB_REQ_TX_CMD_CNT (CFG_TX_MAX_CMD_PKT_NUM) +#define USB_REQ_RX_EVENT_CNT (1) +#ifdef CFG_USB_REQ_RX_DATA_CNT +#define USB_REQ_RX_DATA_CNT (CFG_USB_REQ_RX_DATA_CNT) /* platform specific USB_REQ_RX_DATA_CNT */ +#else +#define USB_REQ_RX_DATA_CNT (2) +#endif + +#define USB_RX_AGGREGTAION_LIMIT (32) /* Unit: K-bytes */ +#define USB_RX_AGGREGTAION_TIMEOUT (100) /* Unit: us */ +#define USB_RX_AGGREGTAION_PKT_LIMIT (30) + +#ifdef MT7668 +/* Due to CR4, MT7668 can't enlarge this setting */ +#define USB_TX_CMD_BUF_SIZE (1608) +#else +/* enlarge to 2048 from 1608: Radio Measurment frame may be > 1608 bytes */ +#define USB_TX_CMD_BUF_SIZE (2048) +#endif +#if CFG_USB_TX_AGG +#define USB_TX_DATA_BUFF_SIZE (32*1024) +#else +#define USB_TX_DATA_BUF_SIZE (NIC_TX_DESC_AND_PADDING_LENGTH + NIC_TX_DESC_HEADER_PADDING_LENGTH + \ + NIC_TX_MAX_SIZE_PER_FRAME + LEN_USB_UDMA_TX_TERMINATOR) +#endif +#define USB_RX_EVENT_BUF_SIZE (CFG_RX_MAX_PKT_SIZE + 3 + LEN_USB_RX_PADDING_CSO + 4) +#define USB_RX_DATA_BUF_SIZE (CFG_RX_MAX_PKT_SIZE + \ + min(USB_RX_AGGREGTAION_LIMIT * 1024, \ + (USB_RX_AGGREGTAION_PKT_LIMIT * \ + (CFG_RX_MAX_PKT_SIZE + 3 + LEN_USB_RX_PADDING_CSO) + 4))) + +#define LEN_USB_UDMA_TX_TERMINATOR (4) /*HW design spec */ +#define LEN_USB_RX_PADDING_CSO (4) /*HW design spec */ + +#define USB_RX_EVENT_RFB_RSV_CNT (0) +#define USB_RX_DATA_RFB_RSV_CNT (4) + +#if CFG_USB_RX_DISPATCH_CPU +#define INVALID_CPUID (-1) +#endif + +#define DEVICE_VENDOR_REQUEST_IN (0xc0) +#define DEVICE_VENDOR_REQUEST_OUT (0x40) +#define VENDOR_TIMEOUT_MS (1000) +#define BULK_TIMEOUT_MS (1500) +#define INTERRUPT_TIMEOUT_MS (1000) +#define SW_RFB_RECHECK_MS (10) +#define SW_RFB_LOG_LIMIT_MS (5000) + +/* Vendor Request */ +#define VND_REQ_POWER_ON_WIFI (0x4) +#if CFG_SUPPORT_SER +#define VND_REQ_WIFI_SER_CONTROL (0x5) +#endif /* CFG_SUPPORT_SER */ +#define VND_REQ_REG_READ (0x63) +#define VND_REQ_REG_WRITE (0x66) +#define VND_REQ_EP5_IN_INFO (0x67) +#define VND_REQ_FEATURE_SET (0x91) +#define FEATURE_SET_WVALUE_RESUME (0x5) +#define FEATURE_SET_WVALUE_SUSPEND (0x6) +#if CFG_SUPPORT_SER +#define WVALUE_WIFI_GET_SER_STATE (0x0) +#define WVALUE_WIFI_SET_SER_STATE (0x1) +#endif /* CFG_SUPPORT_SER */ + +#define USB_TX_CMD_QUEUE_MASK (BITS(2, 4)) /* For H2CDMA Tx CMD mapping */ + +#define USB_DBDC1_TC (TC_NUM)/* for DBDC1 */ +#define USB_TC_NUM (TC_NUM + 1)/* for DBDC1 */ + +#define HIF_EXTRA_IO_BUFFER_SIZE (0) + +#define HIF_TX_COALESCING_BUFFER_SIZE (USB_TX_CMD_BUF_SIZE) +#define HIF_RX_COALESCING_BUFFER_SIZE (USB_RX_EVENT_BUF_SIZE) + +#define MTK_USB_BULK_IN_MIN_EP 4 +#define MTK_USB_BULK_IN_MAX_EP 5 +#define MTK_USB_BULK_OUT_MIN_EP 4 +#define MTK_USB_BULK_OUT_MAX_EP 9 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/* host interface's private data structure, which is attached to os glue +** layer info structure. + */ + +enum ENUM_USB_END_POINT { + USB_DATA_BULK_OUT_EP4 = 4, + USB_DATA_BULK_OUT_EP5, + USB_DATA_BULK_OUT_EP6, + USB_DATA_BULK_OUT_EP7, + USB_DATA_BULK_OUT_EP8, + USB_DATA_BULK_OUT_EP9, +}; + +enum usb_state { + USB_STATE_WIFI_OFF, /* Hif power off wifi */ + USB_STATE_LINK_DOWN, + USB_STATE_PRE_SUSPEND_START, + USB_STATE_PRE_SUSPEND_DONE, + USB_STATE_PRE_SUSPEND_FAIL, + USB_STATE_SUSPEND, + USB_STATE_PRE_RESUME, + USB_STATE_LINK_UP, + USB_STATE_READY +}; + +enum usb_submit_type { + SUBMIT_TYPE_TX_CMD, + SUBMIT_TYPE_TX_DATA, + SUBMIT_TYPE_RX_EVENT, + SUBMIT_TYPE_RX_DATA +}; + +enum usb_rx_type { + USB_RX_TYPE_DATA, + USB_RX_TYPE_EVENT, +}; + +enum EVENT_EP_TYPE { + EVENT_EP_TYPE_UNKONW, + EVENT_EP_TYPE_BULK, + EVENT_EP_TYPE_INTR, + EVENT_EP_TYPE_DATA_EP +}; + +struct BUF_CTRL { + uint8_t *pucBuf; + uint32_t u4BufSize; + uint32_t u4WrIdx; + uint32_t u4ReadSize; +}; + +struct GL_HIF_INFO { + struct usb_interface *intf; + struct usb_device *udev; + + struct GLUE_INFO *prGlueInfo; + enum usb_state state; + + spinlock_t rTxDataQLock; + spinlock_t rTxCmdQLock; + spinlock_t rRxEventQLock; + spinlock_t rRxDataQLock; + spinlock_t rStateLock; + + void *prTxCmdReqHead; + void *arTxDataFfaReqHead; + void *arTxDataReqHead[USB_TC_NUM]; + void *prRxEventReqHead; + void *prRxDataReqHead; + struct list_head rTxCmdFreeQ; + spinlock_t rTxCmdFreeQLock; + struct list_head rTxCmdSendingQ; + spinlock_t rTxCmdSendingQLock; + struct list_head rTxDataFfaQ; +#if CFG_USB_TX_AGG + uint32_t u4AggRsvSize[USB_TC_NUM]; + struct list_head rTxDataFreeQ[USB_TC_NUM]; + struct usb_anchor rTxDataAnchor[USB_TC_NUM]; +#else + struct list_head rTxDataFreeQ; + struct usb_anchor rTxDataAnchor; +#endif + /*spinlock_t rTxDataFreeQLock;*/ + struct list_head rRxEventFreeQ; + /*spinlock_t rRxEventFreeQLock;*/ + struct usb_anchor rRxEventAnchor; + struct list_head rRxDataFreeQ; + /*spinlock_t rRxDataFreeQLock;*/ + struct usb_anchor rRxDataAnchor; + struct list_head rRxEventCompleteQ; + /*spinlock_t rRxEventCompleteQLock;*/ + struct list_head rRxDataCompleteQ; + /*spinlock_t rRxDataCompleteQLock;*/ + struct list_head rTxCmdCompleteQ; + struct list_head rTxDataCompleteQ; + + struct BUF_CTRL rTxCmdBufCtrl[USB_REQ_TX_CMD_CNT]; + struct BUF_CTRL rTxDataFfaBufCtrl[USB_REQ_TX_DATA_FFA_CNT]; +#if CFG_USB_TX_AGG + struct BUF_CTRL rTxDataBufCtrl[USB_TC_NUM][USB_REQ_TX_DATA_CNT]; +#else + struct BUF_CTRL rTxDataBufCtrl[USB_REQ_TX_DATA_CNT]; +#endif + struct BUF_CTRL rRxEventBufCtrl[USB_REQ_RX_EVENT_CNT]; + struct BUF_CTRL rRxDataBufCtrl[USB_REQ_RX_DATA_CNT]; + + struct mutex vendor_req_sem; + u_int8_t fgIntReadClear; + u_int8_t fgMbxReadClear; + u_int8_t fgEventEpDetected; + enum EVENT_EP_TYPE eEventEpType; +#if CFG_USB_RX_DISPATCH_CPU + int rx_cpuid; +#endif +}; + +struct USB_REQ { + struct list_head list; + struct urb *prUrb; + struct BUF_CTRL *prBufCtrl; + struct GL_HIF_INFO *prHifInfo; + void *prPriv; + struct QUE rSendingDataMsduInfoList; +}; + +struct BUS_INFO { + const uint32_t u4UdmaWlCfg_0_Addr; + const uint32_t u4UdmaWlCfg_1_Addr; + uint32_t u4UdmaWlCfg_0; + uint32_t u4UdmaTxTimeout; /* UDMA Tx time out limit, unit: us */ + u_int8_t (*asicUsbSuspend)(IN struct ADAPTER *prAdapter, IN struct GLUE_INFO *prGlueInfo); + uint8_t (*asicUsbEventEpDetected)(IN struct ADAPTER *prAdapter); +}; + +/* USB_REQ_T prPriv field for TxData */ +#define FFA_MASK BIT(7) /* Indicate if this UsbReq is from FFA queue. */ +#define TC_MASK BITS(0, 6) /* Indicate which TC this UsbReq belongs to */ + +/******************************************************************************* +* P U B 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 USB_TRANS_MSDU_TC(_prMsduInfo) \ + ((_prMsduInfo)->ucWmmQueSet ? USB_DBDC1_TC : (_prMsduInfo)->ucTC) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +uint32_t glRegisterBus(probe_card pfProbe, remove_card pfRemove); + +void glUnregisterBus(remove_card pfRemove); + +void glSetHifInfo(struct GLUE_INFO *prGlueInfo, unsigned long ulCookie); + +void glClearHifInfo(struct GLUE_INFO *prGlueInfo); + +u_int8_t glBusInit(void *pvData); + +void glBusRelease(void *pData); + +int32_t glBusSetIrq(void *pvData, void *pfnIsr, void *pvCookie); + +void glBusFreeIrq(void *pvData, void *pvCookie); + +void glSetPowerState(IN struct GLUE_INFO *prGlueInfo, IN uint32_t ePowerMode); + +void glUdmaTxRxEnable(struct GLUE_INFO *prGlueInfo, u_int8_t enable); + +void glUdmaRxAggEnable(struct GLUE_INFO *prGlueInfo, u_int8_t enable); + +u_int8_t mtk_usb_vendor_request(IN struct GLUE_INFO *prGlueInfo, IN uint8_t uEndpointAddress, IN uint8_t RequestType, + IN uint8_t Request, IN uint16_t Value, IN uint16_t Index, IN void *TransferBuffer, + IN uint32_t TransferBufferLength); + +void glUsbEnqueueReq(struct GL_HIF_INFO *prHifInfo, struct list_head *prHead, struct USB_REQ *prUsbReq, + spinlock_t *prLock, u_int8_t fgHead); +struct USB_REQ *glUsbDequeueReq(struct GL_HIF_INFO *prHifInfo, struct list_head *prHead, spinlock_t *prLock); +u_int8_t glUsbBorrowFfaReq(struct GL_HIF_INFO *prHifInfo, uint8_t ucTc); + +void glUsbSetState(IN struct GL_HIF_INFO *prHifInfo, enum usb_state state); + +int glUsbSubmitUrb(IN struct GL_HIF_INFO *prHifInfo, struct urb *urb, + enum usb_submit_type type); + +uint32_t halTxUSBSendCmd(IN struct GLUE_INFO *prGlueInfo, IN uint8_t ucTc, IN struct CMD_INFO *prCmdInfo); +void halTxUSBSendCmdComplete(struct urb *urb); +void halTxUSBProcessCmdComplete(IN struct ADAPTER *prAdapter, struct USB_REQ *prUsbReq); + +uint32_t halTxUSBSendData(IN struct GLUE_INFO *prGlueInfo, IN struct MSDU_INFO *prMsduInfo); +uint32_t halTxUSBKickData(IN struct GLUE_INFO *prGlueInfo); +void halTxUSBSendDataComplete(struct urb *urb); +void halTxUSBProcessMsduDone(IN struct GLUE_INFO *prGlueInfo, struct USB_REQ *prUsbReq); +void halTxUSBProcessDataComplete(IN struct ADAPTER *prAdapter, struct USB_REQ *prUsbReq); + +uint32_t halRxUSBEnqueueRFB(IN struct ADAPTER *prAdapter, IN uint8_t *pucBuf, IN uint32_t u4Length, + IN uint32_t u4MinRfbCnt); +uint32_t halRxUSBReceiveEvent(IN struct ADAPTER *prAdapter, IN u_int8_t fgFillUrb); +void halRxUSBReceiveEventComplete(struct urb *urb); +uint32_t halRxUSBReceiveData(IN struct ADAPTER *prAdapter); +void halRxUSBReceiveDataComplete(struct urb *urb); +void halRxUSBProcessEventDataComplete(IN struct ADAPTER *prAdapter, + enum usb_rx_type); + +void halPreSuspendCmd(IN struct ADAPTER *prAdapter); +void halPreResumeCmd(IN struct ADAPTER *prAdapter); +void halUSBPreSuspendDone(IN struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); +void halUSBPreSuspendTimeout(IN struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo); + +void glGetDev(void *ctx, struct device **dev); +void glGetHifDev(struct GL_HIF_INFO *prHif, struct device **dev); + +void halGetCompleteStatus(IN struct ADAPTER *prAdapter, OUT uint32_t *pu4IntStatus); + +uint16_t glGetUsbDeviceVendorId(struct usb_device *dev); +uint16_t glGetUsbDeviceProductId(struct usb_device *dev); + +int32_t glGetUsbDeviceManufacturerName(struct usb_device *dev, uint8_t *buffer, uint32_t bufLen); +int32_t glGetUsbDeviceProductName(struct usb_device *dev, uint8_t *buffer, uint32_t bufLen); +int32_t glGetUsbDeviceSerialNumber(struct usb_device *dev, uint8_t *buffer, uint32_t bufLen); + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _HIF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/usb/include/hif_usb.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/usb/include/hif_usb.h new file mode 100644 index 0000000000000..f058ca8ca1edf --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/usb/include/hif_usb.h @@ -0,0 +1,131 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "hif_usb.h" + * \brief + */ + + +#ifndef _HIF_USB_H +#define _HIF_USB_H +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#define HIF_USB_DEBUG (0) /* 0:turn off debug msg and assert, 1:turn off debug msg and assert */ + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + +/*! + * \brief A debug print used to print debug messages while compiler flag HIF_SDIO_DEBUG on. + * + */ +#if HIF_USB_DEBUG +#define DPRINTK(fmt, args...) pr_debug("%s: " fmt, __func__, ## args) +#else +#define DPRINTK(fmt, args...) +#endif + +/*! + * \brief ASSERT function definition. + * + */ +#if HIF_USB_DEBUG +#define ASSERT(expr) \ + do { \ + if (!(expr)) { \ + pr_info("assertion failed! %s[%d]: %s\n", \ + __func__, __LINE__, #expr); \ + WARN_ON(!(expr)); \ + } \ + } while (0) +#else +#define 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 +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _HIF_USB_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/usb/usb.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/usb/usb.c new file mode 100644 index 0000000000000..af461532b6b28 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/hif/usb/usb.c @@ -0,0 +1,1670 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** +*[File] usb.c +*[Version] v1.0 +*[Revision Date] 2010-03-01 +*[Author] +*[Description] +* The program provides USB HIF driver +*[Copyright] +* Copyright (C) 2010 MediaTek Incorporation. All Rights Reserved. +******************************************************************************/ + + +/******************************************************************************* +* C O M P I L E 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 +#include + +#include +#ifndef CONFIG_X86 +#include +#endif + +#include "mt66xx_reg.h" +#include "cust_usb_id.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define HIF_USB_ERR_TITLE_STR "["CHIP_NAME"] USB Access Error!" +#define HIF_USB_ERR_DESC_STR "**USB Access Error**\n" + +#define HIF_USB_ACCESS_RETRY_LIMIT 1 + +#define MT_MAC_BASE 0x2 + +#define MTK_USB_PORT_MASK 0x0F + +static const struct usb_device_id mtk_usb_ids[] = { + /* {USB_DEVICE(0x0E8D,0x6632), .driver_info = MT_MAC_BASE}, */ +#ifdef MT6632 + { USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x6632, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&mt66xx_driver_data_mt6632}, + { USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x7666, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&mt66xx_driver_data_mt6632}, +#endif /* MT6632 */ +#ifdef MT7668 + { USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x7668, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&mt66xx_driver_data_mt7668}, +#endif /* MT7668 */ +#ifdef MT7663 + { USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x7663, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&mt66xx_driver_data_mt7663}, +#endif /* MT7663 */ + /* If customer usb id is presented, add to the table. */ + CUST_USB_ID_TABLES + { /* end: all zeroes */ }, +}; + +MODULE_DEVICE_TABLE(usb, mtk_usb_ids); + +/******************************************************************************* +* 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 probe_card pfWlanProbe; +static remove_card pfWlanRemove; + +static u_int8_t g_fgDriverProbed = FALSE; + +static struct usb_driver mtk_usb_driver = { + .name = "wlan", /* "MTK USB WLAN Driver" */ + .id_table = mtk_usb_ids, + .probe = NULL, + .disconnect = NULL, + .suspend = NULL, + .resume = NULL, + .reset_resume = NULL, + .supports_autosuspend = 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 +******************************************************************************** +*/ +static int mtk_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id); +static void mtk_usb_disconnect(struct usb_interface *intf); +static int mtk_usb_suspend(struct usb_interface *intf, pm_message_t message); +static int mtk_usb_resume(struct usb_interface *intf); +#ifndef CFG_DISABLE_USB_RESET_RESUME +static int mtk_usb_reset_resume(struct usb_interface *intf); +#endif +static int mtk_usb_bulk_in_msg(struct GL_HIF_INFO *prHifInfo, uint32_t len, + uint8_t *buffer, int InEp); +static int mtk_usb_intr_in_msg(struct GL_HIF_INFO *prHifInfo, uint32_t len, + uint8_t *buffer, int InEp); +static int mtk_usb_bulk_out_msg(struct GL_HIF_INFO *prHifInfo, uint32_t len, + uint8_t *buffer, int OutEp); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a USB probe function +* +* \param[in] intf USB interface +* \param[in] id USB device id +* +* \return void +*/ +/*----------------------------------------------------------------------------*/ +static int mtk_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + int ret = 0; + struct usb_device *dev; + + DBGLOG(HAL, EVENT, "mtk_usb_probe()\n"); + + ASSERT(intf); + ASSERT(id); + + dev = interface_to_usbdev(intf); + dev = usb_get_dev(dev); + + /* Prevent un-expected usb operation */ + if (g_fgDriverProbed) { + DBGLOG(HAL, ERROR, "wlan_probe(): Device already probed!!\n"); + return -EBUSY; + } + + DBGLOG(HAL, EVENT, "wlan_probe()\n"); + if (pfWlanProbe((void *) intf, (void *) id->driver_info) != WLAN_STATUS_SUCCESS) { + pfWlanRemove(); + DBGLOG(HAL, ERROR, "wlan_probe() failed\n"); + ret = -1; + } else { + g_fgDriverProbed = TRUE; + } + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a USB remove function +* +* \param[in] intf USB interface +* +* \return void +*/ +/*----------------------------------------------------------------------------*/ +static void mtk_usb_disconnect(struct usb_interface *intf) +{ + struct GLUE_INFO *prGlueInfo; + + DBGLOG(HAL, STATE, "mtk_usb_disconnect()\n"); + + ASSERT(intf); + prGlueInfo = (struct GLUE_INFO *)usb_get_intfdata(intf); + + glUsbSetState(&prGlueInfo->rHifInfo, USB_STATE_LINK_DOWN); + + if (g_fgDriverProbed) + pfWlanRemove(); + + usb_set_intfdata(intf, NULL); + usb_put_dev(interface_to_usbdev(intf)); + + g_fgDriverProbed = FALSE; + + DBGLOG(HAL, STATE, "mtk_usb_disconnect() done\n"); +} + +static int mtk_usb_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)usb_get_intfdata(intf); + uint8_t count = 0; + int ret = 0; + + DBGLOG(HAL, STATE, "mtk_usb_suspend()\n"); + + if (kalIsResetting()) { + DBGLOG(HAL, WARN, "Chip resetting, skip\n"); + return -1; + } + + /* Stop upper layers calling the device hard_start_xmit routine. */ + netif_tx_stop_all_queues(prGlueInfo->prDevHandler); + + wlanWaitCfg80211SuspendDone(prGlueInfo); + + /* change to non-READY state to block cfg80211 ops */ + glUsbSetState(&prGlueInfo->rHifInfo, USB_STATE_PRE_SUSPEND_START); + + wlanSuspendPmHandle(prGlueInfo); + + halPreSuspendCmd(prGlueInfo->prAdapter); + + while (prGlueInfo->rHifInfo.state != USB_STATE_PRE_SUSPEND_DONE) { + if (count > 50) { + DBGLOG(HAL, ERROR, "pre_suspend timeout\n"); + ret = -EFAULT; + break; + } + msleep(20); + count++; + } + + glUsbSetState(&prGlueInfo->rHifInfo, USB_STATE_SUSPEND); + halDisableInterrupt(prGlueInfo->prAdapter); + halTxCancelAllSending(prGlueInfo->prAdapter); + + wlanReleaseAllTxCmdQueue(prGlueInfo->prAdapter); + + DBGLOG(HAL, STATE, "mtk_usb_suspend() done! ret %d\n", ret); + + if (ret && PMSG_IS_AUTO(message)) + mtk_usb_resume(intf); + + return ret; +} + +static int mtk_usb_resume(struct usb_interface *intf) +{ + int ret = 0; + uint8_t count = 0; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *)usb_get_intfdata(intf); + + DBGLOG(HAL, STATE, "mtk_usb_resume()\n"); + + if (kalIsResetting()) { + DBGLOG(HAL, WARN, "Chip resetting, skip\n"); + return -1; + } + + /* NOTE: USB bus may not really do suspend and resume*/ + ret = usb_control_msg(prGlueInfo->rHifInfo.udev, + usb_sndctrlpipe(prGlueInfo->rHifInfo.udev, 0), VND_REQ_FEATURE_SET, + DEVICE_VENDOR_REQUEST_OUT, FEATURE_SET_WVALUE_RESUME, 0, NULL, 0, + VENDOR_TIMEOUT_MS); + if (ret) + DBGLOG(HAL, ERROR, "VendorRequest FeatureSetResume ERROR: %x\n", (unsigned int)ret); + + glUsbSetState(&prGlueInfo->rHifInfo, USB_STATE_PRE_RESUME); + /* To trigger CR4 path */ + wlanSendDummyCmd(prGlueInfo->prAdapter, FALSE); + halEnableInterrupt(prGlueInfo->prAdapter); + + halPreResumeCmd(prGlueInfo->prAdapter); + + while (prGlueInfo->rHifInfo.state != USB_STATE_LINK_UP) { + if (count > 50) { + DBGLOG(HAL, ERROR, "pre_resume timeout\n"); + break; + } + msleep(20); + count++; + } + + DBGLOG(HAL, STATE, "pre_resume event check(count %d)\n", count); + + wlanResumePmHandle(prGlueInfo); + + /* Allow upper layers to call the device hard_start_xmit routine. */ + netif_tx_start_all_queues(prGlueInfo->prDevHandler); + + /* change to READY state to allow cfg80211 ops */ + glUsbSetState(&prGlueInfo->rHifInfo, USB_STATE_READY); + + DBGLOG(HAL, STATE, "mtk_usb_resume() done!\n"); + + /* TODO */ + return 0; +} + +#ifndef CFG_DISABLE_USB_RESET_RESUME +static int mtk_usb_reset_resume(struct usb_interface *intf) +{ + DBGLOG(HAL, STATE, "mtk_usb_reset_resume()\n"); + + mtk_usb_resume(intf); + + DBGLOG(HAL, STATE, "mtk_usb_reset_resume done!()\n"); + + /* TODO */ + return 0; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! +* \brief USB EP0 vendor request +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] uEndpointAddress +* \param[in] RequestType +* \param[in] Request +* \param[in] Value +* \param[in] Index +* \param[in] TransferBuffer +* \param[in] TransferBufferLength +* +* \retval 0 if success +* non-zero if fail, the return value of usb_control_msg() +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t mtk_usb_vendor_request(IN struct GLUE_INFO *prGlueInfo, IN uint8_t uEndpointAddress, IN uint8_t RequestType, + IN uint8_t Request, IN uint16_t Value, IN uint16_t Index, IN void *TransferBuffer, + IN uint32_t TransferBufferLength) +{ + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + void *prBuffer; + + /* refer to RTUSB_VendorRequest */ + int ret = 0; + + /* TODO: semaphore */ + + if (in_interrupt()) { + DBGLOG(REQ, ERROR, "BUG: mtk_usb_vendor_request is called from invalid context\n"); + return FALSE; + } + + mutex_lock(&prHifInfo->vendor_req_sem); + + if (RequestType == DEVICE_VENDOR_REQUEST_OUT) { + prBuffer = kmalloc(TransferBufferLength, GFP_KERNEL); + if (!prBuffer) + return -ENOMEM; + memcpy(prBuffer, TransferBuffer, TransferBufferLength); + ret = usb_control_msg( + prHifInfo->udev, + usb_sndctrlpipe(prHifInfo->udev, uEndpointAddress), + Request, RequestType, Value, Index, prBuffer, + TransferBufferLength, VENDOR_TIMEOUT_MS); + kfree(prBuffer); + } else if (RequestType == DEVICE_VENDOR_REQUEST_IN) { + prBuffer = kmalloc(TransferBufferLength, GFP_KERNEL); + if (!prBuffer) + return -ENOMEM; + ret = usb_control_msg( + prHifInfo->udev, + usb_rcvctrlpipe(prHifInfo->udev, uEndpointAddress), + Request, RequestType, Value, Index, prBuffer, + TransferBufferLength, VENDOR_TIMEOUT_MS); + memcpy(TransferBuffer, prBuffer, TransferBufferLength); + kfree(prBuffer); + } + + mutex_unlock(&prHifInfo->vendor_req_sem); + + return (ret == TransferBufferLength) ? 0 : ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief USB Bulk IN msg +* +* \param[in] prHifInfo Pointer to the struct GL_HIF_INFO structure +* \param[in] len +* \param[in] buffer +* \param[in] InEp +* +* \retval +*/ +/*----------------------------------------------------------------------------*/ +static int mtk_usb_bulk_in_msg(IN struct GL_HIF_INFO *prHifInfo, IN uint32_t len, OUT uint8_t *buffer, int InEp) +{ + int ret = 0; + uint32_t count; + + if (in_interrupt()) { + DBGLOG(REQ, ERROR, "BUG: mtk_usb_bulk_in_msg is called from invalid context\n"); + return FALSE; + } + + mutex_lock(&prHifInfo->vendor_req_sem); + + /* do a blocking bulk read to get data from the device */ + ret = usb_bulk_msg(prHifInfo->udev, + usb_rcvbulkpipe(prHifInfo->udev, InEp), buffer, len, &count, BULK_TIMEOUT_MS); + + mutex_unlock(&prHifInfo->vendor_req_sem); + + if (ret >= 0) { +#if 0 /* maximize buff len for usb in */ + if (count != len) { + DBGLOG(HAL, WARN, "usb_bulk_msg(IN=%d) Warning. Data is not completed. (receive %d/%u)\n", + InEp, count, len); + } +#endif + return count; + } + + DBGLOG(HAL, ERROR, "usb_bulk_msg(IN=%d) Fail. Error code = %d.\n", InEp, ret); + return ret; +} + +static int mtk_usb_intr_in_msg(IN struct GL_HIF_INFO *prHifInfo, IN uint32_t len, OUT uint8_t *buffer, int InEp) +{ + int ret = 0; + uint32_t count; + + if (in_interrupt()) { + DBGLOG(REQ, ERROR, "BUG: mtk_usb_intr_in_msg is called from invalid context\n"); + return FALSE; + } + + mutex_lock(&prHifInfo->vendor_req_sem); + + /* do a blocking interrupt read to get data from the device */ + ret = usb_interrupt_msg(prHifInfo->udev, + usb_rcvintpipe(prHifInfo->udev, InEp), buffer, len, &count, INTERRUPT_TIMEOUT_MS); + + mutex_unlock(&prHifInfo->vendor_req_sem); + + if (ret >= 0) { +#if 0 /* maximize buff len for usb in */ + if (count != len) { + DBGLOG(HAL, WARN, "usb_interrupt_msg(IN=%d) Warning. Data is not completed. (receive %d/%u)\n", + InEp, count, len); + } +#endif + return count; + } + + DBGLOG(HAL, ERROR, "usb_interrupt_msg(IN=%d) Fail. Error code = %d.\n", InEp, ret); + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief USB Bulk OUT msg +* +* \param[in] prHifInfo Pointer to the struct GL_HIF_INFO structure +* \param[in] len +* \param[in] buffer +* \param[in] OutEp +* +* \retval +*/ +/*----------------------------------------------------------------------------*/ +static int mtk_usb_bulk_out_msg(IN struct GL_HIF_INFO *prHifInfo, IN uint32_t len, IN uint8_t *buffer, int OutEp) +{ + int ret = 0; + uint32_t count; + + if (in_interrupt()) { + DBGLOG(REQ, ERROR, "BUG: mtk_usb_bulk_out_msg is called from invalid context\n"); + return FALSE; + } + + mutex_lock(&prHifInfo->vendor_req_sem); + + /* do a blocking bulk read to get data from the device */ + ret = usb_bulk_msg(prHifInfo->udev, + usb_sndbulkpipe(prHifInfo->udev, OutEp), buffer, len, &count, BULK_TIMEOUT_MS); + + mutex_unlock(&prHifInfo->vendor_req_sem); + + if (ret >= 0) { +#if 0 + if (count != len) { + DBGLOG(HAL, ERROR, "usb_bulk_msg(OUT=%d) Warning. Data is not completed. (send %d/%u)\n", OutEp, + count, len); + } +#endif + return count; + } + + DBGLOG(HAL, ERROR, "usb_bulk_msg(OUT=%d) Fail. Error code = %d.\n", OutEp, ret); + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will register USB 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 USB bus +*/ +/*----------------------------------------------------------------------------*/ +uint32_t glRegisterBus(probe_card pfProbe, remove_card pfRemove) +{ + int ret = 0; + + ASSERT(pfProbe); + ASSERT(pfRemove); + + pfWlanProbe = pfProbe; + pfWlanRemove = pfRemove; + + mtk_usb_driver.probe = mtk_usb_probe; + mtk_usb_driver.disconnect = mtk_usb_disconnect; + mtk_usb_driver.suspend = mtk_usb_suspend; + mtk_usb_driver.resume = mtk_usb_resume; +#ifndef CFG_DISABLE_USB_RESET_RESUME + mtk_usb_driver.reset_resume = mtk_usb_reset_resume; +#endif + mtk_usb_driver.supports_autosuspend = 1; + + ret = (usb_register(&mtk_usb_driver) == 0) ? WLAN_STATUS_SUCCESS : WLAN_STATUS_FAILURE; + + return ret; +} /* end of glRegisterBus() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will unregister USB bus to the os +* +* \param[in] pfRemove Function pointer to remove card +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void glUnregisterBus(remove_card pfRemove) +{ + if (g_fgDriverProbed) { + pfRemove(); + g_fgDriverProbed = FALSE; + } + usb_deregister(&mtk_usb_driver); +} /* end of glUnregisterBus() */ + +void glUdmaTxRxEnable(struct GLUE_INFO *prGlueInfo, u_int8_t enable) +{ + uint32_t u4Value = 0; + struct BUS_INFO *prBusInfo; + + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + kalDevRegRead(prGlueInfo, prBusInfo->u4UdmaWlCfg_0_Addr, &u4Value); + + /* enable UDMA TX & RX */ + if (enable) + u4Value |= prBusInfo->u4UdmaWlCfg_0; + else + u4Value &= ~prBusInfo->u4UdmaWlCfg_0; + + kalDevRegWrite(prGlueInfo, prBusInfo->u4UdmaWlCfg_0_Addr, u4Value); +} + +void glUdmaRxAggEnable(struct GLUE_INFO *prGlueInfo, u_int8_t enable) +{ + uint32_t u4Value = 0; + struct BUS_INFO *prBusInfo; + + prBusInfo = prGlueInfo->prAdapter->chip_info->bus_info; + if (enable) { + kalDevRegRead(prGlueInfo, prBusInfo->u4UdmaWlCfg_0_Addr, &u4Value); + /* enable UDMA TX & RX */ + u4Value &= ~(UDMA_WLCFG_0_RX_AGG_EN_MASK | + UDMA_WLCFG_0_RX_AGG_LMT_MASK | + UDMA_WLCFG_0_RX_AGG_TO_MASK); + u4Value |= UDMA_WLCFG_0_RX_AGG_EN(1) | + UDMA_WLCFG_0_RX_AGG_LMT(USB_RX_AGGREGTAION_LIMIT) | + UDMA_WLCFG_0_RX_AGG_TO(USB_RX_AGGREGTAION_TIMEOUT); + kalDevRegWrite(prGlueInfo, prBusInfo->u4UdmaWlCfg_0_Addr, u4Value); + + kalDevRegRead(prGlueInfo, prBusInfo->u4UdmaWlCfg_1_Addr, &u4Value); + u4Value &= ~UDMA_WLCFG_1_RX_AGG_PKT_LMT_MASK; + u4Value |= UDMA_WLCFG_1_RX_AGG_PKT_LMT(USB_RX_AGGREGTAION_PKT_LIMIT); + kalDevRegWrite(prGlueInfo, prBusInfo->u4UdmaWlCfg_1_Addr, u4Value); + } else { + kalDevRegRead(prGlueInfo, prBusInfo->u4UdmaWlCfg_0_Addr, &u4Value); + u4Value &= ~UDMA_WLCFG_0_RX_AGG_EN(1); + kalDevRegWrite(prGlueInfo, prBusInfo->u4UdmaWlCfg_0_Addr, u4Value); + } +} + +void *glUsbInitQ(struct GL_HIF_INFO *prHifInfo, struct list_head *prHead, uint32_t u4Cnt) +{ + uint32_t i; + struct USB_REQ *prUsbReqs, *prUsbReq; + + INIT_LIST_HEAD(prHead); + + prUsbReqs = kcalloc(u4Cnt, sizeof(struct USB_REQ), GFP_ATOMIC); + prUsbReq = prUsbReqs; + + for (i = 0; i < u4Cnt; ++i) { + prUsbReq->prHifInfo = prHifInfo; + prUsbReq->prUrb = usb_alloc_urb(0, GFP_ATOMIC); + + if (prUsbReq->prUrb == NULL) + DBGLOG(HAL, ERROR, "usb_alloc_urb() reports error\n"); + + prUsbReq->prBufCtrl = NULL; + + INIT_LIST_HEAD(&prUsbReq->list); + list_add_tail(&prUsbReq->list, prHead); + + prUsbReq++; + } + + return (void *) prUsbReqs; +} + +void glUsbUnInitQ(struct list_head *prHead) +{ + struct USB_REQ *prUsbReq, *prUsbReqNext; + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, prHead, list) { + usb_free_urb(prUsbReq->prUrb); + list_del_init(&prUsbReq->list); + } +} + +void glUsbEnqueueReq(struct GL_HIF_INFO *prHifInfo, struct list_head *prHead, struct USB_REQ *prUsbReq, spinlock_t *prLock, + u_int8_t fgHead) +{ + unsigned long flags; + + spin_lock_irqsave(prLock, flags); + if (fgHead) + list_add(&prUsbReq->list, prHead); + else + list_add_tail(&prUsbReq->list, prHead); + spin_unlock_irqrestore(prLock, flags); +} + +struct USB_REQ *glUsbDequeueReq(struct GL_HIF_INFO *prHifInfo, struct list_head *prHead, spinlock_t *prLock) +{ + struct USB_REQ *prUsbReq; + unsigned long flags; + + spin_lock_irqsave(prLock, flags); + if (list_empty(prHead)) { + spin_unlock_irqrestore(prLock, flags); + return NULL; + } + prUsbReq = list_entry(prHead->next, struct USB_REQ, list); + list_del_init(prHead->next); + spin_unlock_irqrestore(prLock, flags); + + return prUsbReq; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function borrow UsbReq from Tx data FFA queue to the spcified TC Tx data free queue +* +* \param[in] prHifInfo Pointer to the struct GL_HIF_INFO structure +* \param[in] ucTc Specify TC index +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t glUsbBorrowFfaReq(struct GL_HIF_INFO *prHifInfo, uint8_t ucTc) +{ + struct USB_REQ *prUsbReq; + + if (list_empty(&prHifInfo->rTxDataFfaQ)) + return FALSE; + prUsbReq = list_entry(prHifInfo->rTxDataFfaQ.next, struct USB_REQ, list); + list_del_init(prHifInfo->rTxDataFfaQ.next); + + *((uint8_t *)&prUsbReq->prPriv) = FFA_MASK | ucTc; + list_add_tail(&prUsbReq->list, &prHifInfo->rTxDataFreeQ[ucTc]); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function set USB state +* +* \param[in] prHifInfo Pointer to the struct GL_HIF_INFO structure +* \param[in] state Specify TC index +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +void glUsbSetState(struct GL_HIF_INFO *prHifInfo, enum usb_state state) +{ + unsigned long flags; + + spin_lock_irqsave(&prHifInfo->rStateLock, flags); + prHifInfo->state = state; + spin_unlock_irqrestore(&prHifInfo->rStateLock, flags); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a wrapper of submit urb to ensure driver can transmit +* WiFi packet when WiFi path of device is allowed. +* +* \param[in] prHifInfo Pointer to the struct GL_HIF_INFO structure +* \param[in] type Specify submit type +* +* \retval 0 Successful submissions. +* \retval negative Error number. +*/ +/*----------------------------------------------------------------------------*/ +int glUsbSubmitUrb(struct GL_HIF_INFO *prHifInfo, struct urb *urb, + enum usb_submit_type type) +{ + unsigned long flags; + uint32_t ret = 0; + + if (type == SUBMIT_TYPE_RX_EVENT || type == SUBMIT_TYPE_RX_DATA) + return usb_submit_urb(urb, GFP_ATOMIC); + + spin_lock_irqsave(&prHifInfo->rStateLock, flags); + if (type == SUBMIT_TYPE_TX_CMD) { + if (!(prHifInfo->state == USB_STATE_LINK_UP || + prHifInfo->state == USB_STATE_PRE_RESUME || + prHifInfo->state == + USB_STATE_PRE_SUSPEND_START || + prHifInfo->state == USB_STATE_READY)) { + spin_unlock_irqrestore(&prHifInfo->rStateLock, flags); + DBGLOG(HAL, INFO, + "not allowed to transmit CMD packet. (%d)\n", + prHifInfo->state); + return -ESHUTDOWN; + } + } else if (type == SUBMIT_TYPE_TX_DATA) { + if (!(prHifInfo->state == USB_STATE_LINK_UP || + prHifInfo->state == USB_STATE_READY)) { + spin_unlock_irqrestore(&prHifInfo->rStateLock, flags); + DBGLOG(HAL, INFO, + "not allowed to transmit DATA packet. (%d)\n", + prHifInfo->state); + return -ESHUTDOWN; + } + } + ret = usb_submit_urb(urb, GFP_ATOMIC); + spin_unlock_irqrestore(&prHifInfo->rStateLock, flags); + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function stores hif related info, which is initialized before. +* +* \param[in] prGlueInfo Pointer to glue info structure +* \param[in] u4Cookie Pointer to uint32_t memory base variable for _HIF_HPI +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void glSetHifInfo(struct GLUE_INFO *prGlueInfo, unsigned long ulCookie) +{ + struct usb_host_interface *alts; + struct usb_host_endpoint *ep; + struct usb_endpoint_descriptor *ep_desc; + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + struct USB_REQ *prUsbReq, *prUsbReqNext; + uint32_t i; +#if CFG_USB_TX_AGG + uint8_t ucTc; +#endif + + prHifInfo->eEventEpType = USB_EVENT_TYPE; + prHifInfo->fgEventEpDetected = FALSE; + + prHifInfo->intf = (struct usb_interface *)ulCookie; + prHifInfo->udev = interface_to_usbdev(prHifInfo->intf); + + alts = prHifInfo->intf->cur_altsetting; + DBGLOG(HAL, STATE, "USB Device speed: %x [%u]\n", + prHifInfo->udev->speed, alts->endpoint[0].desc.wMaxPacketSize); + + if (prHifInfo->eEventEpType == EVENT_EP_TYPE_UNKONW) { + for (i = 0; i < alts->desc.bNumEndpoints; ++i) { + ep = &alts->endpoint[i]; + if (ep->desc.bEndpointAddress == USB_EVENT_EP_IN) { + ep_desc = &alts->endpoint[i].desc; + switch (ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + case USB_ENDPOINT_XFER_INT: + prHifInfo->eEventEpType = EVENT_EP_TYPE_INTR; + break; + case USB_ENDPOINT_XFER_BULK: + default: + prHifInfo->eEventEpType = EVENT_EP_TYPE_BULK; + break; + } + } + } + } + ASSERT(prHifInfo->eEventEpType != EVENT_EP_TYPE_UNKONW); + DBGLOG(HAL, INFO, "Event EP Type: %x\n", prHifInfo->eEventEpType); + + prHifInfo->prGlueInfo = prGlueInfo; + usb_set_intfdata(prHifInfo->intf, prGlueInfo); + + SET_NETDEV_DEV(prGlueInfo->prDevHandler, &prHifInfo->udev->dev); + + spin_lock_init(&prHifInfo->rTxCmdQLock); + spin_lock_init(&prHifInfo->rTxDataQLock); + spin_lock_init(&prHifInfo->rRxEventQLock); + spin_lock_init(&prHifInfo->rRxDataQLock); + spin_lock_init(&prHifInfo->rStateLock); + + mutex_init(&prHifInfo->vendor_req_sem); + +#if CFG_USB_TX_AGG + for (ucTc = 0; ucTc < USB_TC_NUM; ++ucTc) { + prHifInfo->u4AggRsvSize[ucTc] = 0; + init_usb_anchor(&prHifInfo->rTxDataAnchor[ucTc]); + } +#else + init_usb_anchor(&prHifInfo->rTxDataAnchor); +#endif + init_usb_anchor(&prHifInfo->rRxDataAnchor); + init_usb_anchor(&prHifInfo->rRxEventAnchor); + +#if CFG_USB_RX_DISPATCH_CPU + prHifInfo->rx_cpuid = INVALID_CPUID; +#endif + + /* TX CMD */ + prHifInfo->prTxCmdReqHead = glUsbInitQ(prHifInfo, &prHifInfo->rTxCmdFreeQ, USB_REQ_TX_CMD_CNT); + prUsbReq = list_entry(prHifInfo->rTxCmdFreeQ.next, struct USB_REQ, list); + i = 0; + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxCmdFreeQ, list) { + prUsbReq->prBufCtrl = &prHifInfo->rTxCmdBufCtrl[i]; +#if CFG_USB_CONSISTENT_DMA + prUsbReq->prBufCtrl->pucBuf = usb_alloc_coherent(prHifInfo->udev, USB_TX_CMD_BUF_SIZE, GFP_ATOMIC, + &prUsbReq->prUrb->transfer_dma); +#else +#ifdef CFG_PREALLOC_MEMORY + prUsbReq->prBufCtrl->pucBuf = preallocGetMem(MEM_ID_TX_CMD); +#else + prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_TX_CMD_BUF_SIZE, GFP_ATOMIC); +#endif +#endif + if (prUsbReq->prBufCtrl->pucBuf == NULL) { + DBGLOG(HAL, ERROR, "kmalloc() reports error\n"); + goto error; + } + prUsbReq->prBufCtrl->u4BufSize = USB_TX_CMD_BUF_SIZE; + ++i; + } + + glUsbInitQ(prHifInfo, &prHifInfo->rTxCmdSendingQ, 0); + + /* TX Data FFA */ + prHifInfo->arTxDataFfaReqHead = glUsbInitQ(prHifInfo, + &prHifInfo->rTxDataFfaQ, USB_REQ_TX_DATA_FFA_CNT); + i = 0; + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxDataFfaQ, list) { + QUEUE_INITIALIZE(&prUsbReq->rSendingDataMsduInfoList); + *((uint8_t *)&prUsbReq->prPriv) = FFA_MASK; + prUsbReq->prBufCtrl = &prHifInfo->rTxDataFfaBufCtrl[i]; +#if CFG_USB_CONSISTENT_DMA + prUsbReq->prBufCtrl->pucBuf = + usb_alloc_coherent(prHifInfo->udev, USB_TX_DATA_BUFF_SIZE, GFP_ATOMIC, + &prUsbReq->prUrb->transfer_dma); +#else +#ifdef CFG_PREALLOC_MEMORY + prUsbReq->prBufCtrl->pucBuf = + preallocGetMem(MEM_ID_TX_DATA_FFA); +#else + prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_TX_DATA_BUFF_SIZE, GFP_ATOMIC); +#endif +#endif + if (prUsbReq->prBufCtrl->pucBuf == NULL) { + DBGLOG(HAL, ERROR, "kmalloc() reports error\n"); + goto error; + } + prUsbReq->prBufCtrl->u4BufSize = USB_TX_DATA_BUFF_SIZE; + prUsbReq->prBufCtrl->u4WrIdx = 0; + ++i; + } + + /* TX Data */ +#if CFG_USB_TX_AGG + for (ucTc = 0; ucTc < USB_TC_NUM; ++ucTc) { + /* Only for TC0 ~ TC3 and DBDC1_TC */ + if (ucTc >= TC4_INDEX && ucTc < USB_DBDC1_TC) + continue; + prHifInfo->arTxDataReqHead[ucTc] = glUsbInitQ(prHifInfo, + &prHifInfo->rTxDataFreeQ[ucTc], USB_REQ_TX_DATA_CNT); + i = 0; + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxDataFreeQ[ucTc], list) { + QUEUE_INITIALIZE(&prUsbReq->rSendingDataMsduInfoList); + /* TODO: every endpoint should has an unique and only TC */ + *((uint8_t *)&prUsbReq->prPriv) = ucTc; + prUsbReq->prBufCtrl = &prHifInfo->rTxDataBufCtrl[ucTc][i]; +#if CFG_USB_CONSISTENT_DMA + prUsbReq->prBufCtrl->pucBuf = + usb_alloc_coherent(prHifInfo->udev, USB_TX_DATA_BUFF_SIZE, GFP_ATOMIC, + &prUsbReq->prUrb->transfer_dma); +#else +#ifdef CFG_PREALLOC_MEMORY + prUsbReq->prBufCtrl->pucBuf = + preallocGetMem(MEM_ID_TX_DATA); +#else + prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_TX_DATA_BUFF_SIZE, GFP_ATOMIC); +#endif +#endif + if (prUsbReq->prBufCtrl->pucBuf == NULL) { + DBGLOG(HAL, ERROR, "kmalloc() reports error\n"); + goto error; + } + prUsbReq->prBufCtrl->u4BufSize = USB_TX_DATA_BUFF_SIZE; + prUsbReq->prBufCtrl->u4WrIdx = 0; + ++i; + } + + DBGLOG(INIT, INFO, "USB Tx URB INIT Tc[%u] cnt[%u] len[%u]\n", ucTc, i, + prHifInfo->rTxDataBufCtrl[ucTc][0].u4BufSize); + } +#else + glUsbInitQ(prHifInfo, &prHifInfo->rTxDataFreeQ, USB_REQ_TX_DATA_CNT); + prUsbReq = list_entry(prHifInfo->rTxDataFreeQ.next, struct USB_REQ, list); + i = 0; + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxDataFreeQ, list) { + QUEUE_INITIALIZE(&prUsbReq->rSendingDataMsduInfoList); + prUsbReq->prBufCtrl = &prHifInfo->rTxDataBufCtrl[i]; +#if CFG_USB_CONSISTENT_DMA + prUsbReq->prBufCtrl->pucBuf = + usb_alloc_coherent(prHifInfo->udev, USB_TX_DATA_BUF_SIZE, GFP_ATOMIC, + &prUsbReq->prUrb->transfer_dma); +#else +#ifdef CFG_PREALLOC_MEMORY + prUsbReq->prBufCtrl->pucBuf = preallocGetMem(MEM_ID_TX_DATA); +#else + prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_TX_DATA_BUF_SIZE, GFP_ATOMIC); +#endif +#endif + if (prUsbReq->prBufCtrl->pucBuf == NULL) { + DBGLOG(HAL, ERROR, "kmalloc() reports error\n"); + goto error; + } + prUsbReq->prBufCtrl->u4BufSize = USB_TX_DATA_BUF_SIZE; + ++i; + } +#endif + + glUsbInitQ(prHifInfo, &prHifInfo->rTxCmdCompleteQ, 0); + glUsbInitQ(prHifInfo, &prHifInfo->rTxDataCompleteQ, 0); + + /* RX EVENT */ + prHifInfo->prRxEventReqHead = glUsbInitQ(prHifInfo, &prHifInfo->rRxEventFreeQ, USB_REQ_RX_EVENT_CNT); + i = 0; + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxEventFreeQ, list) { + prUsbReq->prBufCtrl = &prHifInfo->rRxEventBufCtrl[i]; +#ifdef CFG_PREALLOC_MEMORY + prUsbReq->prBufCtrl->pucBuf = preallocGetMem(MEM_ID_RX_EVENT); +#else + prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_RX_EVENT_BUF_SIZE, GFP_ATOMIC); +#endif + if (prUsbReq->prBufCtrl->pucBuf == NULL) { + DBGLOG(HAL, ERROR, "kmalloc() reports error\n"); + goto error; + } + prUsbReq->prBufCtrl->u4BufSize = USB_RX_EVENT_BUF_SIZE; + prUsbReq->prBufCtrl->u4ReadSize = 0; + ++i; + } + + /* RX Data */ + prHifInfo->prRxDataReqHead = glUsbInitQ(prHifInfo, &prHifInfo->rRxDataFreeQ, USB_REQ_RX_DATA_CNT); + i = 0; + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxDataFreeQ, list) { + prUsbReq->prBufCtrl = &prHifInfo->rRxDataBufCtrl[i]; +#ifdef CFG_PREALLOC_MEMORY + prUsbReq->prBufCtrl->pucBuf = preallocGetMem(MEM_ID_RX_DATA); +#else + prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_RX_DATA_BUF_SIZE, GFP_ATOMIC); +#endif + if (prUsbReq->prBufCtrl->pucBuf == NULL) { + DBGLOG(HAL, ERROR, "kmalloc() reports error\n"); + goto error; + } + prUsbReq->prBufCtrl->u4BufSize = USB_RX_DATA_BUF_SIZE; + prUsbReq->prBufCtrl->u4ReadSize = 0; + ++i; + } + + glUsbInitQ(prHifInfo, &prHifInfo->rRxEventCompleteQ, 0); + glUsbInitQ(prHifInfo, &prHifInfo->rRxDataCompleteQ, 0); + + glUsbSetState(prHifInfo, USB_STATE_READY); + prGlueInfo->u4InfType = MT_DEV_INF_USB; + + return; + +error: + /* TODO */ + ; +} /* end of glSetHifInfo() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function clears hif related info. +* +* \param[in] prGlueInfo Pointer to glue info structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void glClearHifInfo(struct GLUE_INFO *prGlueInfo) +{ + /* struct GL_HIF_INFO *prHifInfo = NULL; */ + /* ASSERT(prGlueInfo); */ + /* prHifInfo = &prGlueInfo->rHifInfo; */ +#if CFG_USB_TX_AGG + uint8_t ucTc; +#endif + struct USB_REQ *prUsbReq, *prUsbReqNext; + struct GL_HIF_INFO *prHifInfo = &prGlueInfo->rHifInfo; + +#if CFG_USB_TX_AGG + for (ucTc = 0; ucTc < USB_TC_NUM; ++ucTc) { + if (ucTc >= TC4_INDEX && ucTc < USB_DBDC1_TC) + continue; + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxDataFreeQ[ucTc], list) { +#if CFG_USB_CONSISTENT_DMA + usb_free_coherent(prHifInfo->udev, USB_TX_DATA_BUFF_SIZE, + prUsbReq->prBufCtrl->pucBuf, prUsbReq->prUrb->transfer_dma); +#else +#ifndef CFG_PREALLOC_MEMORY + kfree(prUsbReq->prBufCtrl->pucBuf); +#endif +#endif + usb_free_urb(prUsbReq->prUrb); + } + } +#else + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxDataFreeQ, list) { +#if CFG_USB_CONSISTENT_DMA + usb_free_coherent(prHifInfo->udev, USB_TX_DATA_BUFF_SIZE, + prUsbReq->prBufCtrl->pucBuf, prUsbReq->prUrb->transfer_dma); +#else +#ifndef CFG_PREALLOC_MEMORY + kfree(prUsbReq->prBufCtrl->pucBuf); +#endif +#endif + usb_free_urb(prUsbReq->prUrb); + } +#endif + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxDataFfaQ, list) { +#if CFG_USB_CONSISTENT_DMA + usb_free_coherent(prHifInfo->udev, USB_TX_DATA_BUFF_SIZE, + prUsbReq->prBufCtrl->pucBuf, prUsbReq->prUrb->transfer_dma); +#else +#ifndef CFG_PREALLOC_MEMORY + kfree(prUsbReq->prBufCtrl->pucBuf); +#endif +#endif + usb_free_urb(prUsbReq->prUrb); + } + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxCmdFreeQ, list) { +#if CFG_USB_CONSISTENT_DMA + usb_free_coherent(prHifInfo->udev, USB_TX_CMD_BUF_SIZE, + prUsbReq->prBufCtrl->pucBuf, prUsbReq->prUrb->transfer_dma); +#else +#ifndef CFG_PREALLOC_MEMORY + kfree(prUsbReq->prBufCtrl->pucBuf); +#endif +#endif + usb_free_urb(prUsbReq->prUrb); + } + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxCmdCompleteQ, list) { +#if CFG_USB_CONSISTENT_DMA + usb_free_coherent(prHifInfo->udev, USB_TX_CMD_BUF_SIZE, + prUsbReq->prBufCtrl->pucBuf, prUsbReq->prUrb->transfer_dma); +#else + kfree(prUsbReq->prBufCtrl->pucBuf); +#endif + usb_free_urb(prUsbReq->prUrb); + } + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxDataCompleteQ, list) { +#if CFG_USB_CONSISTENT_DMA + usb_free_coherent(prHifInfo->udev, USB_TX_CMD_BUF_SIZE, + prUsbReq->prBufCtrl->pucBuf, prUsbReq->prUrb->transfer_dma); +#else + kfree(prUsbReq->prBufCtrl->pucBuf); +#endif + usb_free_urb(prUsbReq->prUrb); + } + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxDataFreeQ, list) { +#ifndef CFG_PREALLOC_MEMORY + kfree(prUsbReq->prBufCtrl->pucBuf); +#endif + usb_free_urb(prUsbReq->prUrb); + } + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxEventFreeQ, list) { +#ifndef CFG_PREALLOC_MEMORY + kfree(prUsbReq->prBufCtrl->pucBuf); +#endif + usb_free_urb(prUsbReq->prUrb); + } + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxDataCompleteQ, list) { + kfree(prUsbReq->prBufCtrl->pucBuf); + usb_free_urb(prUsbReq->prUrb); + } + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxEventCompleteQ, list) { + kfree(prUsbReq->prBufCtrl->pucBuf); + usb_free_urb(prUsbReq->prUrb); + } + + kfree(prHifInfo->prTxCmdReqHead); + kfree(prHifInfo->arTxDataFfaReqHead); + for (ucTc = 0; ucTc < USB_TC_NUM; ++ucTc) + kfree(prHifInfo->arTxDataReqHead[ucTc]); + kfree(prHifInfo->prRxEventReqHead); + kfree(prHifInfo->prRxDataReqHead); + + mutex_destroy(&prHifInfo->vendor_req_sem); +} /* 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 uint32_t type and +* stores a mapped base address. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t glBusInit(void *pvData) +{ + return TRUE; +} /* end of glBusInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus operation and release resources. +* +* \param[in] pvData A pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void glBusRelease(void *pvData) +{ +} /* end of glBusRelease() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setup bus interrupt operation and interrupt handler for os. +* +* \param[in] pvData A pointer to struct net_device. +* \param[in] pfnIsr A pointer to interrupt handler function. +* \param[in] pvCookie Private data for pfnIsr function. +* +* \retval WLAN_STATUS_SUCCESS if success +* NEGATIVE_VALUE if fail +*/ +/*----------------------------------------------------------------------------*/ +int32_t glBusSetIrq(void *pvData, void *pfnIsr, void *pvCookie) +{ + int ret = 0; + + struct net_device *prNetDevice = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct GL_HIF_INFO *prHifInfo = NULL; + + ASSERT(pvData); + if (!pvData) + return -1; + + prNetDevice = (struct net_device *)pvData; + prGlueInfo = (struct GLUE_INFO *) pvCookie; + ASSERT(prGlueInfo); + if (!prGlueInfo) + return -1; + + prHifInfo = &prGlueInfo->rHifInfo; + + 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(void *pvData, void *pvCookie) +{ + struct net_device *prNetDevice = NULL; + struct GLUE_INFO *prGlueInfo = NULL; + struct GL_HIF_INFO *prHifInfo = NULL; + + ASSERT(pvData); + if (!pvData) { + return; + } + prNetDevice = (struct net_device *)pvData; + prGlueInfo = (struct GLUE_INFO *) pvCookie; + ASSERT(prGlueInfo); + if (!prGlueInfo) { + return; + } + + prHifInfo = &prGlueInfo->rHifInfo; +} /* end of glBusreeIrq() */ + +u_int8_t glIsReadClearReg(uint32_t u4Address) +{ + switch (u4Address) { + case MCR_WHISR: + case MCR_WASR: + case MCR_D2HRM0R: + case MCR_D2HRM1R: + case MCR_WTQCR0: + case MCR_WTQCR1: + case MCR_WTQCR2: + case MCR_WTQCR3: + case MCR_WTQCR4: + case MCR_WTQCR5: + case MCR_WTQCR6: + case MCR_WTQCR7: + return TRUE; + + default: + return FALSE; + } +} + +uint16_t glGetUsbDeviceVendorId(struct usb_device *dev) +{ + return dev->descriptor.idVendor; +} /* end of glGetUsbDeviceVendorId() */ + +uint16_t glGetUsbDeviceProductId(struct usb_device *dev) +{ + return dev->descriptor.idProduct; +} /* end of glGetUsbDeviceProductId() */ + +int32_t glGetUsbDeviceManufacturerName(struct usb_device *dev, uint8_t *buffer, uint32_t bufLen) +{ + return usb_string(dev, dev->descriptor.iManufacturer, buffer, bufLen); +} /* end of glGetUsbDeviceManufacturerName() */ + +int32_t glGetUsbDeviceProductName(struct usb_device *dev, uint8_t *buffer, uint32_t bufLen) +{ + return usb_string(dev, dev->descriptor.iProduct, buffer, bufLen); +} /* end of glGetUsbDeviceManufacturerName() */ + +int32_t glGetUsbDeviceSerialNumber(struct usb_device *dev, uint8_t *buffer, uint32_t bufLen) +{ + return usb_string(dev, dev->descriptor.iSerialNumber, buffer, bufLen); +} /* end of glGetUsbDeviceSerialNumber() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevRegRead(IN struct GLUE_INFO *prGlueInfo, IN uint32_t u4Register, OUT uint32_t *pu4Value) +{ + int ret = 0; + uint8_t ucRetryCount = 0; + + ASSERT(prGlueInfo); + ASSERT(pu4Value); + + *pu4Value = 0xFFFFFFFF; + + do { + ret = mtk_usb_vendor_request(prGlueInfo, 0, DEVICE_VENDOR_REQUEST_IN, VND_REQ_REG_READ, + (u4Register & 0xffff0000) >> 16, (u4Register & 0x0000ffff), pu4Value, + sizeof(*pu4Value)); + + if (ret || ucRetryCount) + DBGLOG(HAL, ERROR, "usb_control_msg() status: %x retry: %u\n", (unsigned int)ret, ucRetryCount); + + + ucRetryCount++; + if (ucRetryCount > HIF_USB_ACCESS_RETRY_LIMIT) + break; + } while (ret); + + if (ret) { + kalSendAeeWarning(HIF_USB_ERR_TITLE_STR, + HIF_USB_ERR_DESC_STR "USB() reports error: %x retry: %u", ret, ucRetryCount); + DBGLOG(HAL, ERROR, "usb_readl() reports error: %x retry: %u\n", ret, ucRetryCount); + } else { + DBGLOG(HAL, INFO, "Get CR[0x%08x] value[0x%08x]\n", u4Register, *pu4Value); + } + + 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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevRegWrite(IN struct GLUE_INFO *prGlueInfo, IN uint32_t u4Register, IN uint32_t u4Value) +{ + int ret = 0; + uint8_t ucRetryCount = 0; + + ASSERT(prGlueInfo); + + do { + ret = mtk_usb_vendor_request(prGlueInfo, 0, DEVICE_VENDOR_REQUEST_OUT, VND_REQ_REG_WRITE, + (u4Register & 0xffff0000) >> 16, (u4Register & 0x0000ffff), &u4Value, + sizeof(u4Value)); + + if (ret || ucRetryCount) + DBGLOG(HAL, ERROR, "usb_control_msg() status: %x retry: %u\n", (unsigned int)ret, ucRetryCount); + + ucRetryCount++; + if (ucRetryCount > HIF_USB_ACCESS_RETRY_LIMIT) + break; + + } while (ret); + + if (ret) { + kalSendAeeWarning(HIF_USB_ERR_TITLE_STR, + HIF_USB_ERR_DESC_STR "usb_writel() reports error: %x retry: %u", ret, ucRetryCount); + DBGLOG(HAL, ERROR, "usb_writel() reports error: %x retry: %u\n", ret, ucRetryCount); + } else { + DBGLOG(HAL, INFO, "Set CR[0x%08x] value[0x%08x]\n", u4Register, u4Value); + } + + 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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t +kalDevPortRead(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port, IN uint32_t u4Len, OUT uint8_t *pucBuf, IN uint32_t u4ValidOutBufSize) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + uint8_t *pucDst = NULL; + /* int count = u4Len; */ + int ret = 0; + /* int bNum = 0; */ + +#if DBG + DBGLOG(HAL, INFO, "++kalDevPortRead++ buf:0x%p, port:0x%x, length:%d\n", pucBuf, u2Port, u4Len); +#endif + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + ASSERT(pucBuf); + pucDst = pucBuf; + + ASSERT(u4Len <= u4ValidOutBufSize); + + u2Port &= MTK_USB_PORT_MASK; + if (prGlueInfo->rHifInfo.eEventEpType == EVENT_EP_TYPE_INTR && + u2Port == (USB_EVENT_EP_IN & USB_ENDPOINT_NUMBER_MASK)) { + /* maximize buff len for usb in */ + ret = mtk_usb_intr_in_msg(&prGlueInfo->rHifInfo, u4ValidOutBufSize, pucDst, u2Port); + if (ret != u4Len) { + DBGLOG(HAL, WARN, "usb_interrupt_msg(IN=%d) Warning. Data is not completed. (receive %d/%u)\n", + u2Port, ret, u4Len); + } + ret = ret >= 0 ? 0 : ret; + } else if (u2Port >= MTK_USB_BULK_IN_MIN_EP && u2Port <= MTK_USB_BULK_IN_MAX_EP) { + /* maximize buff len for usb in */ + ret = mtk_usb_bulk_in_msg(&prGlueInfo->rHifInfo, u4ValidOutBufSize, pucDst, u2Port); + if (ret != u4Len) { + DBGLOG(HAL, WARN, "usb_bulk_msg(IN=%d) Warning. Data is not completed. (receive %d/%u)\n", + u2Port, ret, u4Len); + } + ret = ret >= 0 ? 0 : ret; + } else { + DBGLOG(HAL, ERROR, "kalDevPortRead reports error: invalid port %x\n", u2Port); + ret = -EINVAL; + } + + if (ret) { + kalSendAeeWarning(HIF_USB_ERR_TITLE_STR, HIF_USB_ERR_DESC_STR "usb_readsb() reports error: %x", ret); + DBGLOG(HAL, ERROR, "usb_readsb() reports error: %x\n", 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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t +kalDevPortWrite(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port, IN uint32_t u4Len, IN uint8_t *pucBuf, IN uint32_t u4ValidInBufSize) +{ + struct GL_HIF_INFO *prHifInfo = NULL; + uint8_t *pucSrc = NULL; + /* int count = u4Len; */ + int ret = 0; + /* int bNum = 0; */ + +#if DBG + DBGLOG(HAL, INFO, "++kalDevPortWrite++ buf:0x%p, port:0x%x, length:%d\n", pucBuf, u2Port, u4Len); +#endif + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + ASSERT(pucBuf); + pucSrc = pucBuf; + + ASSERT((u4Len + LEN_USB_UDMA_TX_TERMINATOR) <= u4ValidInBufSize); + + kalMemZero(pucSrc + u4Len, LEN_USB_UDMA_TX_TERMINATOR); + u4Len += LEN_USB_UDMA_TX_TERMINATOR; + + u2Port &= MTK_USB_PORT_MASK; + if (u2Port >= MTK_USB_BULK_OUT_MIN_EP && u2Port <= MTK_USB_BULK_OUT_MAX_EP) { + ret = mtk_usb_bulk_out_msg(&prGlueInfo->rHifInfo, u4Len, pucSrc, u2Port/*8*/); + if (ret != u4Len) { + DBGLOG(HAL, WARN, "usb_bulk_msg(OUT=%d) Warning. Data is not completed. (receive %d/%u)\n", + u2Port, ret, u4Len); + } + ret = ret >= 0 ? 0 : ret; + } else { + DBGLOG(HAL, ERROR, "kalDevPortWrite reports error: invalid port %x\n", u2Port); + ret = -EINVAL; + } + + if (ret) { + kalSendAeeWarning(HIF_USB_ERR_TITLE_STR, HIF_USB_ERR_DESC_STR "usb_writesb() reports error: %x", ret); + DBGLOG(HAL, ERROR, "usb_writesb() reports error: %x\n", ret); + } + + return (ret) ? FALSE : TRUE; +} /* end of kalDevPortWrite() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set power state +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] ePowerMode +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void glSetPowerState(IN struct GLUE_INFO *prGlueInfo, IN uint32_t ePowerMode) +{ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write data to device +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] prMsduInfo msdu info +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevWriteData(IN struct GLUE_INFO *prGlueInfo, IN struct MSDU_INFO *prMsduInfo) +{ + halTxUSBSendData(prGlueInfo, prMsduInfo); + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Kick Tx data to device +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevKickData(IN struct GLUE_INFO *prGlueInfo) +{ +#if 0 + halTxUSBKickData(prGlueInfo); +#endif + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write command to device +* +* \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 +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevWriteCmd(IN struct GLUE_INFO *prGlueInfo, IN struct CMD_INFO *prCmdInfo, IN uint8_t ucTC) +{ + halTxUSBSendCmd(prGlueInfo, ucTC, prCmdInfo); + return TRUE; +} + +void glGetDev(void *ctx, struct device **dev) +{ + struct usb_interface *prUsbIntf = (struct usb_interface *) ctx; + struct usb_device *prUsbDev = interface_to_usbdev(prUsbIntf); + + *dev = &prUsbDev->dev; +} + +void glGetHifDev(struct GL_HIF_INFO *prHif, struct device **dev) +{ + *dev = &(prHif->udev->dev); +} + +#if CFG_CHIP_RESET_SUPPORT +/*----------------------------------------------------------------------------*/ +/*! +* \brief perform whole chip reset operation +* \You need set the reset pin low level and set it high level to +* \reset 7663 chip; The operation will different in other platform; +* \the following code is a example in mtk DTV platform. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +*/ +/*----------------------------------------------------------------------------*/ +void kalRemoveProbe(IN struct GLUE_INFO *prGlueInfo) +{ + typedef void (*func_ptr) (unsigned int gpio, int init_value); + char *func_name = "mtk_gpio_set_value"; + func_ptr pFunc = (func_ptr) kal_kallsyms_lookup_name(func_name); + + if (!pFunc) { + DBGLOG(HAL, WARN, "[SER][L0]%s: No Exported Func Found [%s]\n", + __func__, func_name); + } else { + DBGLOG(HAL, INFO, "[SER][L0]%s: Invoke %s(%d,%d)\n", __func__, + func_name, WIFI_DONGLE_RESET_GPIO_PIN, 0); + pFunc(WIFI_DONGLE_RESET_GPIO_PIN, 0); + mdelay(RESET_PIN_SET_LOW_TIME); + DBGLOG(HAL, INFO, "[SER][L0]%s: Invoke %s(%d,%d)\n", __func__, + func_name, WIFI_DONGLE_RESET_GPIO_PIN, 1); + pFunc(WIFI_DONGLE_RESET_GPIO_PIN, 1); + } + +} +#endif + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_ate_agent.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_ate_agent.h new file mode 100644 index 0000000000000..81b2de9871547 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_ate_agent.h @@ -0,0 +1,288 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/*! \file gl_ate_agent.h + * \brief This file includes private ioctl support. + */ + +#ifndef _GL_ATE_AGENT_H +#define _GL_ATE_AGENT_H +#if CFG_SUPPORT_QA_TOOL +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ + +extern uint32_t u4RxStatSeqNum; + +#if CFG_SUPPORT_TX_BF +extern union PFMU_PROFILE_TAG1 g_rPfmuTag1; +extern union PFMU_PROFILE_TAG2 g_rPfmuTag2; +extern union PFMU_DATA g_rPfmuData; +#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 + ******************************************************************************* + */ + +struct STA_REC_BF_UPD_ARGUMENT { + uint32_t u4WlanId; + uint32_t u4BssId; + uint32_t u4PfmuId; + uint32_t u4SuMu; + uint32_t u4eTxBfCap; + uint32_t u4NdpaRate; + uint32_t u4NdpRate; + uint32_t u4ReptPollRate; + uint32_t u4TxMode; + uint32_t u4Nc; + uint32_t u4Nr; + uint32_t u4Bw; + uint32_t u4SpeIdx; + uint32_t u4TotalMemReq; + uint32_t u4MemReq20M; + uint32_t au4MemRow[4]; + uint32_t au4MemCol[4]; +}; + +struct ATE_OPS_T { + int32_t (*setICapStart)(struct GLUE_INFO *prGlueInfo, + uint32_t fgTrigger, + uint32_t fgRingCapEn, + uint32_t u4Event, + uint32_t u4Node, + uint32_t u4Len, + uint32_t u4StopCycle, + uint32_t u4BW, + uint32_t u4MACTriggerEvent, + uint32_t u4SourceAddrLSB, + uint32_t u4SourceAddrMSB, + uint32_t u4Band); + int32_t (*getICapStatus)(struct GLUE_INFO *prGlueInfo); + int32_t (*getICapIQData)(struct GLUE_INFO *prGlueInfo, + uint8_t *pData, + uint32_t u4IQType, + uint32_t u4WFNum); + void (*getRbistDataDumpEvent)(struct ADAPTER *prAdapter, + uint8_t *pucEventBuf); +}; + + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +int Set_ResetStatCounter_Proc(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATE(struct net_device *prNetDev, uint8_t *prInBuf); +int SetATEDa(struct net_device *prNetDev, uint8_t *prInBuf); +int SetATESa(struct net_device *prNetDev, uint8_t *prInBuf); +int SetATEChannel(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATETxPower0(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATETxGi(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATETxBw(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATETxMode(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATETxLength(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATETxCount(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATETxMcs(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetATEIpg(struct net_device *prNetDev, + uint8_t *prInBuf); + +#if CFG_SUPPORT_TX_BF +int Set_TxBfProfileTag_Help(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_InValid(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_PfmuIdx(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_BfType(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_DBW(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_SuMu(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_Mem(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_Matrix(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_SNR(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_SmartAnt(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_SeIdx(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_RmsdThrd(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_McsThrd(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_TimeOut(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTag_DesiredBW(struct net_device + *prNetDev, uint8_t *prInBuf); +int Set_TxBfProfileTag_DesiredNc(struct net_device + *prNetDev, uint8_t *prInBuf); +int Set_TxBfProfileTag_DesiredNr(struct net_device + *prNetDev, uint8_t *prInBuf); +int Set_TxBfProfileTagRead(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileTagWrite(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_StaRecCmmUpdate(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_StaRecBfUpdate(struct net_device *prNetDev, + uint8_t *prInBuf); + +int Set_DevInfoUpdate(struct net_device *prNetDev, + uint8_t *prInBuf); + +int Set_BssInfoUpdate(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileDataRead(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfileDataWrite(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_Trigger_Sounding_Proc(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_Stop_Sounding_Proc(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfTxApply(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfilePnRead(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfProfilePnWrite(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfManualAssoc(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfPfmuMemAlloc(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_TxBfPfmuMemRelease(struct net_device *prNetDev, + uint8_t *prInBuf); + +#if CFG_SUPPORT_MU_MIMO +int Set_MUGetInitMCS(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUCalInitMCS(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUCalLQ(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUGetLQ(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUSetSNROffset(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUSetZeroNss(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUSetSpeedUpLQ(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUSetMUTable(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUSetGroup(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUGetQD(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUSetEnable(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUSetGID_UP(struct net_device *prNetDev, + uint8_t *prInBuf); +int Set_MUTriggerTx(struct net_device *prNetDev, + uint8_t *prInBuf); +#endif + +#if CFG_SUPPORT_TX_BF_FPGA +int Set_TxBfProfileSwTagWrite(struct net_device *prNetDev, + uint8_t *prInBuf); +#endif +#endif + + +int WriteEfuse(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetTxTargetPower(struct net_device *prNetDev, + uint8_t *prInBuf); + +#if (CFG_SUPPORT_DFS_MASTER == 1) +int SetRddReport(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetByPassCac(struct net_device *prNetDev, + uint8_t *prInBuf); +int SetRadarDetectMode(struct net_device *prNetDev, + uint8_t *prInBuf); +#endif + +int AteCmdSetHandle(struct net_device *prNetDev, + uint8_t *prInBuf, uint32_t u4InBufLen); + +#endif /*CFG_SUPPORT_QA_TOOL */ +#endif /* _GL_ATE_AGENT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_cfg80211.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_cfg80211.h new file mode 100644 index 0000000000000..2b552f9e966b5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_cfg80211.h @@ -0,0 +1,754 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** 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. + */ + + +#ifndef _GL_CFG80211_H +#define _GL_CFG80211_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include +#include +#include +#include +#include + +#include "gl_os.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#ifdef CONFIG_NL80211_TESTMODE +#define NL80211_DRIVER_TESTMODE_VERSION 2 +#endif + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +#ifdef CONFIG_NL80211_TESTMODE +#if CFG_SUPPORT_NFC_BEAM_PLUS + +struct NL80211_DRIVER_SET_NFC_PARAMS { + struct NL80211_DRIVER_TEST_MODE_PARAMS hdr; + uint32_t NFC_Enable; + +}; + +#endif + + + +struct NL80211_DRIVER_GET_STA_STATISTICS_PARAMS { + struct NL80211_DRIVER_TEST_MODE_PARAMS hdr; + uint32_t u4Version; + uint32_t u4Flag; + uint8_t aucMacAddr[MAC_ADDR_LEN]; +}; + +enum _ENUM_TESTMODE_LINK_DETECTION_ATTR { + NL80211_TESTMODE_LINK_INVALID = 0, + NL80211_TESTMODE_LINK_TX_FAIL_CNT, + NL80211_TESTMODE_LINK_TX_RETRY_CNT, + NL80211_TESTMODE_LINK_TX_MULTI_RETRY_CNT, + NL80211_TESTMODE_LINK_ACK_FAIL_CNT, + NL80211_TESTMODE_LINK_FCS_ERR_CNT, + NL80211_TESTMODE_LINK_TX_CNT, + NL80211_TESTMODE_LINK_RX_CNT, + NL80211_TESTMODE_LINK_RST_REASON, + NL80211_TESTMODE_LINK_RST_TIME, + NL80211_TESTMODE_LINK_ROAM_FAIL_TIMES, + NL80211_TESTMODE_LINK_ROAM_FAIL_TIME, + NL80211_TESTMODE_LINK_TX_DONE_DELAY_IS_ARP, + NL80211_TESTMODE_LINK_ARRIVE_DRV_TICK, + NL80211_TESTMODE_LINK_ENQUE_TICK, + NL80211_TESTMODE_LINK_DEQUE_TICK, + NL80211_TESTMODE_LINK_LEAVE_DRV_TICK, + NL80211_TESTMODE_LINK_CURR_TICK, + NL80211_TESTMODE_LINK_CURR_TIME, + + NL80211_TESTMODE_LINK_DETECT_NUM +}; + +enum ENUM_TESTMODE_STA_STATISTICS_ATTR { + NL80211_TESTMODE_STA_STATISTICS_INVALID = 0, + NL80211_TESTMODE_STA_STATISTICS_VERSION, + NL80211_TESTMODE_STA_STATISTICS_MAC, + NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE, + NL80211_TESTMODE_STA_STATISTICS_FLAG, + + NL80211_TESTMODE_STA_STATISTICS_PER, + NL80211_TESTMODE_STA_STATISTICS_RSSI, + NL80211_TESTMODE_STA_STATISTICS_PHY_MODE, + NL80211_TESTMODE_STA_STATISTICS_TX_RATE, + + NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT, + NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT, + + NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME, + NL80211_TESTMODE_STA_STATISTICS_MAX_PROCESS_TIME, + NL80211_TESTMODE_STA_STATISTICS_AVG_HIF_PROCESS_TIME, + NL80211_TESTMODE_STA_STATISTICS_MAX_HIF_PROCESS_TIME, + + NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT, + NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT, + NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME, + + NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY, + + /* + * how many packages TX during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_ENQUEUE, + + /* + * how many packages this TX during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_STA_ENQUEUE, + + /* + * how many packages dequeue during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_DEQUEUE, + + /* + * how many packages this sta dequeue during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_STA_DEQUEUE, + + /* + * how many TC[0-3] resource back from firmware during + * statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_RB_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_NO_TC_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_USED_TC_PGCT_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_WANTED_TC_PGCT_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_PASS_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_TASK_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_AB_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_SW_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_TX_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_RX_CNT, + + NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_NUM +}; +#endif +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +/* cfg80211 hooks */ +int +mtk_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, enum nl80211_iftype type, + u32 *flags, struct vif_params *params); + +int +mtk_cfg80211_add_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, bool pairwise, const u8 *mac_addr, + struct key_params *params); + +int +mtk_cfg80211_get_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, + bool pairwise, + const u8 *mac_addr, void *cookie, + void (*callback)(void *cookie, struct key_params *)); + +int +mtk_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_index, + bool pairwise, const u8 *mac_addr); + +int +mtk_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *ndev, + u8 key_index, bool unicast, bool multicast); + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *ndev, const u8 *mac, + struct station_info *sinfo); +#else +int mtk_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac, + struct station_info *sinfo); +#endif + +int +mtk_cfg80211_get_link_statistics(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac, + struct station_info *sinfo); + +int mtk_cfg80211_scan(struct wiphy *wiphy, + struct cfg80211_scan_request *request); + +void mtk_cfg80211_abort_scan(struct wiphy *wiphy, + struct wireless_dev *wdev); + +#if CFG_SUPPORT_CFG80211_AUTH +int mtk_cfg80211_auth(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_auth_request *req); +#endif + +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); + +#if CFG_SUPPORT_CFG80211_AUTH +int mtk_cfg80211_deauth(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_deauth_request *req); +#endif + +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_set_rekey_data(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_gtk_rekey_data *data); + +int mtk_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, struct ieee80211_channel *chan, + unsigned int duration, u64 *cookie); + +int mtk_cfg80211_cancel_remain_on_channel( + struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie); +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie); +#else +int mtk_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *channel, bool offscan, + unsigned int wait, + const u8 *buf, size_t len, bool no_cck, + bool dont_wait_for_ack, u64 *cookie); +#endif + +void mtk_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, + IN struct wireless_dev *wdev, IN u16 frame_type, IN bool reg); + +int mtk_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct wireless_dev *wdev, u64 cookie); + +#ifdef CONFIG_NL80211_TESTMODE +int +mtk_cfg80211_testmode_get_sta_statistics(IN struct wiphy + *wiphy, + IN void *data, IN int len, IN struct GLUE_INFO *prGlueInfo); + +int mtk_cfg80211_testmode_get_scan_done(IN struct wiphy + *wiphy, IN void *data, IN int len, + IN struct GLUE_INFO *prGlueInfo); + +#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_testmode_cmd(struct wiphy *wiphy, + struct wireless_dev *wdev, + void *data, int len); +#else +int mtk_cfg80211_testmode_cmd(struct wiphy *wiphy, + void *data, int len); +#endif + +int mtk_cfg80211_testmode_sw_cmd(IN struct wiphy *wiphy, + IN void *data, IN int len); + +#if CFG_SUPPORT_PASSPOINT +int mtk_cfg80211_testmode_hs20_cmd(IN struct wiphy *wiphy, + IN void *data, IN int len); +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_WAPI +int mtk_cfg80211_testmode_set_key_ext(IN struct wiphy + *wiphy, IN void *data, IN int len); +#endif +#if CFG_SUPPORT_NFC_BEAM_PLUS +int mtk_cfg80211_testmode_get_scan_done(IN struct wiphy *wiphy, + IN void *data, IN int len, IN struct GLUE_INFO *prGlueInfo); +#endif +#else +/* IGNORE KERNEL DEPENCY ERRORS */ +/* #error "Please ENABLE kernel config (CONFIG_NL80211_TESTMODE) to support + * Wi-Fi Direct" + */ +#endif + +#if CFG_SUPPORT_SCHED_SCAN +int +mtk_cfg80211_sched_scan_start(IN struct wiphy *wiphy, + IN struct net_device *ndev, + IN struct cfg80211_sched_scan_request *request); + +int mtk_cfg80211_sched_scan_stop(IN struct wiphy *wiphy, + IN struct net_device *ndev); +#endif /* CFG_SUPPORT_SCHED_SCAN */ + +int mtk_cfg80211_assoc(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_assoc_request *req); + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int +mtk_cfg80211_change_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, struct station_parameters *params); + +int mtk_cfg80211_add_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, struct station_parameters *params); + +#if KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *ndev, + struct station_del_parameters *params); +#else +int mtk_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac); +#endif +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, + bool initiator, const u8 *buf, size_t len); +#else +int mtk_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, + const u8 *buf, size_t len); +#endif + +int mtk_cfg80211_tdls_oper(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, enum nl80211_tdls_operation oper); +#else +int +mtk_cfg80211_change_station(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac, + struct station_parameters *params); + +int mtk_cfg80211_add_station(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac, + struct station_parameters *params); + +int mtk_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac); + +int +mtk_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + u8 *peer, u8 action_code, + u8 dialog_token, u16 status_code, + const u8 *buf, size_t len); + +int mtk_cfg80211_tdls_oper(struct wiphy *wiphy, + struct net_device *dev, u8 *peer, + enum nl80211_tdls_operation oper); +#endif + +int32_t mtk_cfg80211_process_str_cmd(struct GLUE_INFO + *prGlueInfo, uint8_t *cmd, int32_t len); + +void mtk_reg_notify(IN struct wiphy *pWiphy, + IN struct regulatory_request *pRequest); +void cfg80211_regd_set_wiphy(IN struct wiphy *pWiphy); + +int mtk_cfg80211_suspend(struct wiphy *wiphy, + struct cfg80211_wowlan *wow); + +int mtk_cfg80211_resume(struct wiphy *wiphy); + +/* cfg80211 wrapper hooks */ +#if CFG_ENABLE_UNIFY_WIPHY +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +struct wireless_dev *mtk_cfg_add_iface(struct wiphy *wiphy, + const char *name, + unsigned char name_assign_type, + enum nl80211_iftype type, + struct vif_params *params); +#elif KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE +struct wireless_dev *mtk_cfg_add_iface(struct wiphy *wiphy, + const char *name, + unsigned char name_assign_type, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params); +#else +struct wireless_dev *mtk_cfg_add_iface(struct wiphy *wiphy, + const char *name, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params); +#endif +int mtk_cfg_del_iface(struct wiphy *wiphy, + struct wireless_dev *wdev); +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_change_iface(struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type, + struct vif_params *params); +#else +int mtk_cfg_change_iface(struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params); +#endif +int mtk_cfg_add_key(struct wiphy *wiphy, + struct net_device *ndev, u8 key_index, + bool pairwise, const u8 *mac_addr, + struct key_params *params); +int mtk_cfg_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_cfg_del_key(struct wiphy *wiphy, + struct net_device *ndev, u8 key_index, + bool pairwise, const u8 *mac_addr); +int mtk_cfg_set_default_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, bool unicast, bool multicast); + +int mtk_cfg_set_default_mgmt_key(struct wiphy *wiphy, + struct net_device *ndev, u8 key_index); + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_get_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, struct station_info *sinfo); +#else +int mtk_cfg_get_station(struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, struct station_info *sinfo); +#endif + +#if CFG_SUPPORT_TDLS +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_change_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, struct station_parameters *params); +#else +int mtk_cfg_change_station(struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, struct station_parameters *params); +#endif +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_add_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, struct station_parameters *params); +#else +int mtk_cfg_add_station(struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, struct station_parameters *params); +#endif +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_tdls_oper(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *peer, enum nl80211_tdls_operation oper); +#else +int mtk_cfg_tdls_oper(struct wiphy *wiphy, + struct net_device *ndev, + u8 *peer, enum nl80211_tdls_operation oper); +#endif +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_tdls_mgmt(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, + u32 peer_capability, bool initiator, const u8 *buf, + size_t len); +#elif KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_tdls_mgmt(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, + u32 peer_capability, const u8 *buf, size_t len); +#else +int mtk_cfg_tdls_mgmt(struct wiphy *wiphy, + struct net_device *ndev, + u8 *peer, u8 action_code, + u8 dialog_token, u16 status_code, + const u8 *buf, size_t len); +#endif +#endif /* CFG_SUPPORT_TDLS */ + +#if KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_del_station(struct wiphy *wiphy, + struct net_device *ndev, + struct station_del_parameters *params); +#elif KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_del_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac); +#else +int mtk_cfg_del_station(struct wiphy *wiphy, + struct net_device *ndev, u8 *mac); +#endif +int mtk_cfg_scan(struct wiphy *wiphy, + struct cfg80211_scan_request *request); +#if KERNEL_VERSION(4, 5, 0) <= CFG80211_VERSION_CODE +void mtk_cfg_abort_scan(struct wiphy *wiphy, + struct wireless_dev *wdev); +#endif + +#if CFG_SUPPORT_SCHED_SCAN +int mtk_cfg_sched_scan_start(IN struct wiphy *wiphy, + IN struct net_device *ndev, + IN struct cfg80211_sched_scan_request *request); + +int mtk_cfg_sched_scan_stop(IN struct wiphy *wiphy, + IN struct net_device *ndev); +#endif /* CFG_SUPPORT_SCHED_SCAN */ + +int mtk_cfg_connect(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_connect_params *sme); +int mtk_cfg_disconnect(struct wiphy *wiphy, + struct net_device *ndev, + u16 reason_code); +int mtk_cfg_join_ibss(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_ibss_params *params); +int mtk_cfg_leave_ibss(struct wiphy *wiphy, + struct net_device *ndev); +int mtk_cfg_set_power_mgmt(struct wiphy *wiphy, + struct net_device *ndev, + bool enabled, int timeout); +int mtk_cfg_set_pmksa(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_pmksa *pmksa); +int mtk_cfg_del_pmksa(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_pmksa *pmksa); +int mtk_cfg_flush_pmksa(struct wiphy *wiphy, + struct net_device *ndev); +#if CONFIG_SUPPORT_GTK_REKEY +int mtk_cfg_set_rekey_data(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_gtk_rekey_data *data); +#endif /* CONFIG_SUPPORT_GTK_REKEY */ +int mtk_cfg_suspend(struct wiphy *wiphy, + struct cfg80211_wowlan *wow); +int mtk_cfg_resume(struct wiphy *wiphy); +int mtk_cfg_assoc(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_assoc_request *req); +int mtk_cfg_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, + unsigned int duration, + u64 *cookie); +int mtk_cfg_cancel_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, u64 cookie); +uint16_t cfg80211_get_non_wfa_vendor_ie(struct GLUE_INFO + *prGlueInfo, uint8_t *ies, int32_t len); + +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, u64 *cookie); +#else +int mtk_cfg_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *channel, bool offscan, + unsigned int wait, + const u8 *buf, size_t len, bool no_cck, + bool dont_wait_for_ack, + u64 *cookie); +#endif +void mtk_cfg_mgmt_frame_register(struct wiphy *wiphy, + struct wireless_dev *wdev, + u16 frame_type, bool reg); + +#ifdef CONFIG_NL80211_TESTMODE +#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_testmode_cmd(struct wiphy *wiphy, + struct wireless_dev *wdev, + void *data, int len); +#else +int mtk_cfg_testmode_cmd(struct wiphy *wiphy, void *data, + int len); +#endif +#endif /* CONFIG_NL80211_TESTMODE */ + +#if (CFG_SUPPORT_DFS_MASTER == 1) +#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_start_radar_detection(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef, + unsigned int cac_time_ms); +#else +int mtk_cfg_start_radar_detection(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef); +#endif + +#if KERNEL_VERSION(3, 13, 0) <= CFG80211_VERSION_CODE +int mtk_cfg_channel_switch(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_csa_settings *params); +#endif +#endif + +#if (CFG_ENABLE_WIFI_DIRECT_CFG_80211 != 0) +int mtk_cfg_change_bss(struct wiphy *wiphy, + struct net_device *dev, + struct bss_parameters *params); +int mtk_cfg_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie); +int mtk_cfg_deauth(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_deauth_request *req); +int mtk_cfg_disassoc(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_disassoc_request *req); +int mtk_cfg_start_ap(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ap_settings *settings); +int mtk_cfg_change_beacon(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_beacon_data *info); +int mtk_cfg_stop_ap(struct wiphy *wiphy, + struct net_device *dev); +int mtk_cfg_set_wiphy_params(struct wiphy *wiphy, + u32 changed); +int mtk_cfg_set_bitrate_mask(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, + const struct cfg80211_bitrate_mask *mask); +int mtk_cfg_set_txpower(struct wiphy *wiphy, + struct wireless_dev *wdev, + enum nl80211_tx_power_setting type, int mbm); +int mtk_cfg_get_txpower(struct wiphy *wiphy, + struct wireless_dev *wdev, + int *dbm); +#endif /* (CFG_ENABLE_WIFI_DIRECT_CFG_80211 != 0) */ + +#endif /* CFG_ENABLE_UNIFY_WIPHY */ + +int mtk_cfg80211_update_ft_ies(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_update_ft_ies_params *ftie); + +int mtk_IsP2PNetDevice(struct GLUE_INFO *prGlueInfo, + struct net_device *ndev); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _GL_CFG80211_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_hook_api.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_hook_api.h new file mode 100644 index 0000000000000..e61eec76c8c5a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_hook_api.h @@ -0,0 +1,335 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/*! \file gl_hook_api.h + * \brief This file includes private ioctl support. + */ + +#ifndef _GL_HOOK_API_H +#define _GL_HOOK_API_H +#if CFG_SUPPORT_QA_TOOL +/******************************************************************************* + * C O M P I L E 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 + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +int32_t MT_ATEStart(struct net_device *prNetDev, + uint8_t *prInBuf); +int32_t MT_ICAPStart(struct net_device *prNetDev, + uint8_t *prInBuf); +int32_t MT_ICAPCommand(struct net_device *prNetDev, + uint8_t *prInBuf); +int32_t MT_ATEStop(struct net_device *prNetDev, + uint8_t *prInBuf); +int32_t MT_ATEStartTX(struct net_device *prNetDev, + uint8_t *prInBuf); +int32_t MT_ATEStopTX(struct net_device *prNetDev, + uint8_t *prInBuf); +int32_t MT_ATEStartRX(struct net_device *prNetDev, + uint8_t *prInBuf); +int32_t MT_ATEStopRX(struct net_device *prNetDev, + uint8_t *prInBuf); +int32_t MT_ATESetChannel(struct net_device *prNetDev, + uint32_t u4SXIdx, uint32_t u4SetFreq); +int32_t MT_ATESetPreamble(struct net_device *prNetDev, + uint32_t u4Mode); +int32_t MT_ATESetSystemBW(struct net_device *prNetDev, + uint32_t u4BW); +int32_t MT_ATESetTxLength(struct net_device *prNetDev, + uint32_t u4TxLength); +int32_t MT_ATESetTxCount(struct net_device *prNetDev, + uint32_t u4TxCount); +int32_t MT_ATESetTxIPG(struct net_device *prNetDev, + uint32_t u4TxIPG); +int32_t MT_ATESetTxPower0(struct net_device *prNetDev, + uint32_t u4TxPower0); +int32_t MT_ATESetPerPacketBW(struct net_device *prNetDev, + uint32_t u4BW); +int32_t MT_ATEPrimarySetting(struct net_device *prNetDev, + uint32_t u4PrimaryCh); +int32_t MT_ATESetTxGi(struct net_device *prNetDev, + uint32_t u4SetTxGi); +int32_t MT_ATESetTxPayLoad(struct net_device *prNetDev, + uint32_t u4Gen_payload_rule, uint8_t ucPayload); +int32_t MT_ATESetTxSTBC(struct net_device *prNetDev, + uint32_t u4Stbc); +int32_t MT_ATESetTxPath(struct net_device *prNetDev, + uint32_t u4Tx_path); +int32_t MT_ATESetTxVhtNss(struct net_device *prNetDev, + uint32_t u4VhtNss); +int32_t MT_ATESetRate(struct net_device *prNetDev, + uint32_t u4Rate); +int32_t MT_ATESetEncodeMode(struct net_device *prNetDev, + uint32_t u4Ldpc); +int32_t MT_ATESetiBFEnable(struct net_device *prNetDev, + uint32_t u4iBF); +int32_t MT_ATESeteBFEnable(struct net_device *prNetDev, + uint32_t u4eBF); +int32_t MT_ATESetMACAddress(struct net_device *prNetDev, + uint32_t u4Type, uint8_t ucAddr[]); +int32_t MT_ATELogOnOff(struct net_device *prNetDev, + uint32_t u4Type, uint32_t u4On_off, uint32_t u4Size); +int32_t MT_ATEGetDumpRXV(struct net_device *prNetDev, + uint8_t *pData, int32_t *pCount); +int32_t MT_ATEResetTXRXCounter(struct net_device *prNetDev); +int32_t MT_ATESetDBDCBandIndex(struct net_device *prNetDev, + uint32_t u4BandIdx); +int32_t MT_ATESetBand(struct net_device *prNetDev, + int32_t i4Band); +int32_t MT_ATESetTxToneType(struct net_device *prNetDev, + int32_t i4ToneType); +int32_t MT_ATESetTxToneBW(struct net_device *prNetDev, + int32_t i4ToneFreq); +int32_t MT_ATESetTxToneDCOffset(struct net_device *prNetDev, + int32_t i4DcOffsetI, int32_t i4DcOffsetQ); +int32_t MT_ATESetDBDCTxTonePower(struct net_device *prNetDev, + int32_t i4AntIndex, int32_t i4RF_Power, int32_t i4Digi_Power); +int32_t MT_ATEDBDCTxTone(struct net_device *prNetDev, + int32_t i4Control); +int32_t MT_ATESetMacHeader(struct net_device *prNetDev, + uint32_t u2FrameCtrl, uint32_t u2DurationID, + uint32_t u4SeqCtrl); +int32_t MT_ATE_IRRSetADC(struct net_device *prNetDev, + uint32_t u4WFIdx, + uint32_t u4ChFreq, + uint32_t u4BW, uint32_t u4Sx, uint32_t u4Band, + uint32_t u4RunType, uint32_t u4FType); +int32_t MT_ATE_IRRSetRxGain(struct net_device *prNetDev, + uint32_t u4PgaLpfg, uint32_t u4Lna, uint32_t u4Band, + uint32_t u4WF_inx, uint32_t u4Rfdgc); +int32_t MT_ATE_IRRSetTTG(struct net_device *prNetDev, + uint32_t u4TTGPwrIdx, uint32_t u4ChFreq, + uint32_t u4FIToneFreq, uint32_t u4Band); +int32_t MT_ATE_IRRSetTrunOnTTG(struct net_device *prNetDev, uint32_t u4TTGOnOff, + uint32_t u4Band, uint32_t u4WF_inx); +int32_t MT_ATE_TMRSetting(struct net_device *prNetDev, uint32_t u4Setting, + uint32_t u4Version, uint32_t u4MPThres, uint32_t u4MPIter); +int32_t MT_ATERDDStart(struct net_device *prNetDev, + uint8_t *prInBuf); +int32_t MT_ATERDDStop(struct net_device *prNetDev, + uint8_t *prInBuf); +int32_t MT_ATEMPSSetSeqData(struct net_device *prNetDev, uint32_t u4TestNum, + uint32_t *pu4Phy, uint32_t u4Band); +int32_t MT_ATEMPSSetPayloadLength(struct net_device *prNetDev, + uint32_t u4TestNum, uint32_t *pu4Length, uint32_t u4Band); +int32_t MT_ATEMPSSetPacketCount(struct net_device *prNetDev, uint32_t u4TestNum, + uint32_t *pu4PktCnt, uint32_t u4Band); +int32_t MT_ATEMPSSetPowerGain(struct net_device *prNetDev, uint32_t u4TestNum, + uint32_t *pu4PwrGain, uint32_t u4Band); +int32_t MT_ATEMPSSetNss(struct net_device *prNetDev, + uint32_t u4TestNum, uint32_t *pu4Nss, uint32_t u4Band); +int32_t MT_ATEMPSSetPerpacketBW(struct net_device *prNetDev, uint32_t u4TestNum, + uint32_t *pu4PerPktBW, uint32_t u4Band); + + +int32_t MT_ATEWriteEfuse(struct net_device *prNetDev, + uint16_t u2Offset, uint16_t u2Content); +int32_t MT_ATESetTxTargetPower(struct net_device *prNetDev, + uint8_t ucTxTargetPower); +#if (CFG_SUPPORT_DFS_MASTER == 1) +int32_t MT_ATESetRddReport(struct net_device *prNetDev, + uint8_t ucDbdcIdx); +int32_t MT_ATESetRadarDetectMode(struct net_device + *prNetDev, uint8_t ucRadarDetectMode); +#endif + + +#if CFG_SUPPORT_TX_BF +int32_t TxBfProfileTag_InValid(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + uint8_t ucInValid); +int32_t TxBfProfileTag_PfmuIdx(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + uint8_t ucProfileIdx); +int32_t TxBfProfileTag_TxBfType(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + uint8_t ucBFType); +int32_t TxBfProfileTag_DBW(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, uint8_t ucBW); +int32_t TxBfProfileTag_SuMu(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, uint8_t ucSuMu); +int32_t TxBfProfileTag_Mem(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + uint8_t *aucMemAddrColIdx, uint8_t *aucMemAddrRowIdx); +int32_t TxBfProfileTag_Matrix(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + uint8_t ucNrow, + uint8_t ucNcol, uint8_t ucNgroup, uint8_t ucLM, + uint8_t ucCodeBook, uint8_t ucHtcExist); +int32_t TxBfProfileTag_SNR(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + uint8_t ucSNR_STS0, uint8_t ucSNR_STS1, + uint8_t ucSNR_STS2, + uint8_t ucSNR_STS3); +int32_t TxBfProfileTag_SmtAnt(struct net_device *prNetDev, + union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t ucSmartAnt); +int32_t TxBfProfileTag_SeIdx(struct net_device *prNetDev, + union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t ucSeIdx); +int32_t TxBfProfileTag_RmsdThd(struct net_device *prNetDev, + union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t ucRmsdThrd); +int32_t TxBfProfileTag_McsThd(struct net_device *prNetDev, + union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t *pMCSThLSS, + uint8_t *pMCSThSSS); +int32_t TxBfProfileTag_TimeOut(struct net_device *prNetDev, + union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t ucTimeOut); +int32_t TxBfProfileTag_DesiredBW(struct net_device + *prNetDev, union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t ucDesiredBW); +int32_t TxBfProfileTag_DesiredNc(struct net_device + *prNetDev, union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t ucDesiredNc); +int32_t TxBfProfileTag_DesiredNr(struct net_device + *prNetDev, union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t ucDesiredNr); +int32_t TxBfProfileTagWrite(struct net_device *prNetDev, + union PFMU_PROFILE_TAG1 *prPfmuTag1, + union PFMU_PROFILE_TAG2 *prPfmuTag2, + uint8_t profileIdx); +int32_t TxBfProfileTagRead(struct net_device *prNetDev, + uint8_t PfmuIdx, uint8_t fgBFer); +int32_t TxBfProfileDataRead(struct net_device *prNetDev, + uint8_t profileIdx, uint8_t fgBFer, + uint8_t subcarrierIdxMsb, uint8_t subcarrierIdxLsb); +int32_t TxBfProfileDataWrite(struct net_device *prNetDev, + uint8_t profileIdx, + uint16_t subcarrierIdx, + uint16_t au2Phi[6], + uint8_t aucPsi[6], uint8_t aucDSnr[4] + ); +int32_t TxBfProfilePnRead(struct net_device *prNetDev, + uint8_t profileIdx); +int32_t TxBfProfilePnWrite(struct net_device *prNetDev, uint8_t ucProfileIdx, + uint16_t u2bw, uint16_t au2XSTS[12]); + +int32_t TxBfSounding(struct net_device *prNetDev, + uint8_t ucSuMu, /* 0/1/2/3 */ + uint8_t ucNumSta, /* 00~04 */ + uint8_t ucSndInterval, /* 00~FF */ + uint8_t ucWLan0, /* 00~7F */ + uint8_t ucWLan1, /* 00~7F */ + uint8_t ucWLan2, /* 00~7F */ + + uint8_t ucWLan3 /* 00~7F */ + ); +int32_t TxBfSoundingStop(struct net_device *prNetDev); +int32_t TxBfTxApply(struct net_device *prNetDev, + uint8_t ucWlanId, uint8_t fgETxBf, uint8_t fgITxBf, + uint8_t fgMuTxBf); + +int32_t TxBfManualAssoc(struct net_device *prNetDev, + uint8_t aucMac[MAC_ADDR_LEN], + uint8_t ucType, + uint8_t ucWtbl, + uint8_t ucOwnmac, + uint8_t ucPhyMode, + uint8_t ucBw, + uint8_t ucNss, uint8_t ucPfmuId, uint8_t ucMarate, + uint8_t ucSpeIdx, uint8_t ucRca2, uint8_t ucRv); + +int32_t TxBfPfmuMemAlloc(struct net_device *prNetDev, + uint8_t ucSuMuMode, uint8_t ucWlanIdx); + +int32_t TxBfPfmuMemRelease(struct net_device *prNetDev, + uint8_t ucWlanId); + +int32_t DevInfoUpdate(struct net_device *prNetDev, + uint8_t ucOwnMacIdx, uint8_t fgBand, + uint8_t aucMacAddr[MAC_ADDR_LEN]); + +int32_t BssInfoUpdate(struct net_device *prNetDev, + uint8_t u4OwnMacIdx, uint8_t u4BssIdx, + uint8_t u4BssId[MAC_ADDR_LEN]); + +int32_t StaRecCmmUpdate(struct net_device *prNetDev, + uint8_t ucWlanId, uint8_t ucBssId, uint8_t u4Aid, + uint8_t aucMacAddr[MAC_ADDR_LEN] + ); + +int32_t StaRecBfUpdate(struct net_device *prNetDev, + struct STA_REC_BF_UPD_ARGUMENT rStaRecBfUpdArg, + uint8_t aucMemRow[4], uint8_t aucMemCol[4] + ); + +#if CFG_SUPPORT_TX_BF_FPGA +int32_t TxBfPseudoTagUpdate(struct net_device *prNetDev, + uint8_t ucLm, uint8_t ucNr, + uint8_t ucNc, uint8_t ucBw, uint8_t ucCodeBook, + uint8_t ucGroup); +#endif + +#endif +#endif /*CFG_SUPPORT_QA_TOOL */ +#endif /* _GL_HOOK_API_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_kal.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_kal.h new file mode 100644 index 0000000000000..9f53cd4839fd8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_kal.h @@ -0,0 +1,1591 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: /os/linux/include/gl_kal.h + */ + +/*! \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. + */ + +#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_wext_priv.h" +#include "link.h" +#include "nic/mac.h" +#include "nic/wlan_def.h" +#include "wlan_lib.h" +#include "wlan_oid.h" + +#if CFG_ENABLE_BT_OVER_WIFI +#include "nic/bow.h" +#endif + +#include "linux/kallsyms.h" +#include "linux/sched.h" + +#if CFG_SUPPORT_SCAN_CACHE_RESULT +#include "wireless/core.h" +#endif + +#if DBG +extern int allocatedMemSize; +#endif + +extern struct semaphore g_halt_sem; +extern int g_u4HaltFlag; + +extern struct delayed_work sched_workq; + +extern u_int8_t wlan_fb_power_down; +extern u_int8_t wlan_perf_monitor_force_enable; +extern u_int8_t g_fgIsOid; + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +/* Define how many concurrent operation networks. */ +#define KAL_BSS_NUM 4 + +#if CFG_DUAL_P2PLIKE_INTERFACE +#define KAL_P2P_NUM 2 +#else +#define KAL_P2P_NUM 1 +#endif + +#if CFG_SUPPORT_MULTITHREAD +#define GLUE_FLAG_MAIN_PROCESS \ + (GLUE_FLAG_HALT | GLUE_FLAG_SUB_MOD_MULTICAST | \ + GLUE_FLAG_TX_CMD_DONE | GLUE_FLAG_TXREQ | GLUE_FLAG_TIMEOUT | \ + GLUE_FLAG_FRAME_FILTER | GLUE_FLAG_OID | GLUE_FLAG_RX) + +#define GLUE_FLAG_HIF_PROCESS \ + (GLUE_FLAG_HALT | GLUE_FLAG_INT | GLUE_FLAG_HIF_TX | \ + GLUE_FLAG_HIF_TX_CMD | GLUE_FLAG_HIF_FW_OWN) + +#define GLUE_FLAG_RX_PROCESS (GLUE_FLAG_HALT | GLUE_FLAG_RX_TO_OS) +#else +/* All flags for single thread driver */ +#define GLUE_FLAG_TX_PROCESS 0xFFFFFFFF +#endif + +#if CFG_SUPPORT_SNIFFER +#define RADIOTAP_FIELD_TSFT BIT(0) +#define RADIOTAP_FIELD_FLAGS BIT(1) +#define RADIOTAP_FIELD_RATE BIT(2) +#define RADIOTAP_FIELD_CHANNEL BIT(3) +#define RADIOTAP_FIELD_ANT_SIGNAL BIT(5) +#define RADIOTAP_FIELD_ANT_NOISE BIT(6) +#define RADIOTAP_FIELD_ANT BIT(11) +#define RADIOTAP_FIELD_MCS BIT(19) +#define RADIOTAP_FIELD_AMPDU BIT(20) +#define RADIOTAP_FIELD_VHT BIT(21) +#define RADIOTAP_FIELD_VENDOR BIT(30) + +#define RADIOTAP_LEN_VHT 48 +#define RADIOTAP_FIELDS_VHT (RADIOTAP_FIELD_TSFT | \ + RADIOTAP_FIELD_FLAGS | \ + RADIOTAP_FIELD_RATE | \ + RADIOTAP_FIELD_CHANNEL | \ + RADIOTAP_FIELD_ANT_SIGNAL | \ + RADIOTAP_FIELD_ANT_NOISE | \ + RADIOTAP_FIELD_ANT | \ + RADIOTAP_FIELD_AMPDU | \ + RADIOTAP_FIELD_VHT | \ + RADIOTAP_FIELD_VENDOR) + +#define RADIOTAP_LEN_HT 36 +#define RADIOTAP_FIELDS_HT (RADIOTAP_FIELD_TSFT | \ + RADIOTAP_FIELD_FLAGS | \ + RADIOTAP_FIELD_RATE | \ + RADIOTAP_FIELD_CHANNEL | \ + RADIOTAP_FIELD_ANT_SIGNAL | \ + RADIOTAP_FIELD_ANT_NOISE | \ + RADIOTAP_FIELD_ANT | \ + RADIOTAP_FIELD_MCS | \ + RADIOTAP_FIELD_AMPDU | \ + RADIOTAP_FIELD_VENDOR) + +#define RADIOTAP_LEN_LEGACY 26 +#define RADIOTAP_FIELDS_LEGACY (RADIOTAP_FIELD_TSFT | \ + RADIOTAP_FIELD_FLAGS | \ + RADIOTAP_FIELD_RATE | \ + RADIOTAP_FIELD_CHANNEL | \ + RADIOTAP_FIELD_ANT_SIGNAL | \ + RADIOTAP_FIELD_ANT_NOISE | \ + RADIOTAP_FIELD_ANT | \ + RADIOTAP_FIELD_VENDOR) +#endif + +#define PERF_MON_DISABLE_BIT (0) +#define PERF_MON_STOP_BIT (1) +#define PERF_MON_RUNNING_BIT (2) + +#define PERF_MON_UPDATE_INTERVAL (1000) +#define PERF_MON_TP_MAX_THRESHOLD (10) + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +enum ENUM_SPIN_LOCK_CATEGORY_E { + SPIN_LOCK_FSM = 0, + +#if CFG_SUPPORT_MULTITHREAD + SPIN_LOCK_TX_PORT_QUE, + SPIN_LOCK_TX_CMD_QUE, + SPIN_LOCK_TX_CMD_DONE_QUE, + SPIN_LOCK_TC_RESOURCE, + SPIN_LOCK_RX_TO_OS_QUE, +#endif + + /* FIX ME */ + SPIN_LOCK_RX_QUE, + SPIN_LOCK_RX_FREE_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, + /* TX/RX Direct : BEGIN */ + SPIN_LOCK_TX_DIRECT, + SPIN_LOCK_TX_DESC, + SPIN_LOCK_RX_DIRECT_REORDER, + /* TX/RX Direct : END */ + 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 ENUM_MUTEX_CATEGORY_E { + MUTEX_TX_CMD_CLEAR, + MUTEX_TX_DATA_DONE_QUE, + MUTEX_DEL_INF, + MUTEX_CHIP_RST, + MUTEX_SET_OWN, + MUTEX_NUM +}; + +/* event for assoc information update */ +struct EVENT_ASSOC_INFO { + uint8_t ucAssocReq; /* 1 for assoc req, 0 for assoc rsp */ + uint8_t ucReassoc; /* 0 for assoc, 1 for reassoc */ + uint16_t u2Length; + uint8_t *pucIe; +}; + +enum ENUM_KAL_NETWORK_TYPE_INDEX { + 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 ENUM_KAL_MEM_ALLOCATION_TYPE_E { + PHY_MEM_TYPE, /* physically continuous */ + VIR_MEM_TYPE, /* virtually continuous */ + MEM_TYPE_NUM +}; + +#ifdef CONFIG_ANDROID /* Defined in Android kernel source */ +#if (KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE) +#define KAL_WAKE_LOCK_T struct wakeup_source +#else +#define KAL_WAKE_LOCK_T struct wake_lock +#endif +#else +#define KAL_WAKE_LOCK_T uint32_t +#endif + +#if CFG_SUPPORT_AGPS_ASSIST +enum ENUM_MTK_AGPS_ATTR { + MTK_ATTR_AGPS_INVALID, + MTK_ATTR_AGPS_CMD, + MTK_ATTR_AGPS_DATA, + MTK_ATTR_AGPS_IFINDEX, + MTK_ATTR_AGPS_IFNAME, + MTK_ATTR_AGPS_MAX +}; + +enum ENUM_AGPS_EVENT { + AGPS_EVENT_WLAN_ON, + AGPS_EVENT_WLAN_OFF, + AGPS_EVENT_WLAN_AP_LIST, +}; +u_int8_t kalIndicateAgpsNotify(struct ADAPTER *prAdapter, + uint8_t cmd, + uint8_t *data, uint16_t dataLen); +#endif /* CFG_SUPPORT_AGPS_ASSIST */ + +#if CFG_SUPPORT_SNIFFER +/* Vendor Namespace + * Bit Number 30 + * Required Alignment 2 bytes + */ +struct RADIOTAP_FIELD_VENDOR_ { + uint8_t aucOUI[3]; + uint8_t ucSubNamespace; + uint16_t u2DataLen; + uint8_t ucData; +} __KAL_ATTRIB_PACKED__; + +struct MONITOR_RADIOTAP { + /* radiotap header */ + uint8_t ucItVersion; /* set to 0 */ + uint8_t ucItPad; + uint16_t u2ItLen; /* entire length */ + uint32_t u4ItPresent; /* fields present */ + + /* TSFT + * Bit Number 0 + * Required Alignment 8 bytes + * Unit microseconds + */ + uint64_t u8MacTime; + + /* Flags + * Bit Number 1 + */ + uint8_t ucFlags; + + /* Rate + * Bit Number 2 + * Unit 500 Kbps + */ + uint8_t ucRate; + + /* Channel + * Bit Number 3 + * Required Alignment 2 bytes + */ + uint16_t u2ChFrequency; + uint16_t u2ChFlags; + + /* Antenna signal + * Bit Number 5 + * Unit dBm + */ + uint8_t ucAntennaSignal; + + /* Antenna noise + * Bit Number 6 + * Unit dBm + */ + uint8_t ucAntennaNoise; + + /* Antenna + * Bit Number 11 + * Unit antenna index + */ + uint8_t ucAntenna; + + /* MCS + * Bit Number 19 + * Required Alignment 1 byte + */ + uint8_t ucMcsKnown; + uint8_t ucMcsFlags; + uint8_t ucMcsMcs; + + /* A-MPDU status + * Bit Number 20 + * Required Alignment 4 bytes + */ + uint32_t u4AmpduRefNum; + uint16_t u2AmpduFlags; + uint8_t ucAmpduDelimiterCRC; + uint8_t ucAmpduReserved; + + /* VHT + * Bit Number 21 + * Required Alignment 2 bytes + */ + uint16_t u2VhtKnown; + uint8_t ucVhtFlags; + uint8_t ucVhtBandwidth; + uint8_t aucVhtMcsNss[4]; + uint8_t ucVhtCoding; + uint8_t ucVhtGroupId; + uint16_t u2VhtPartialAid; + + /* extension space */ + uint8_t aucReserve[12]; +} __KAL_ATTRIB_PACKED__; +#endif + +struct KAL_HALT_CTRL_T { + struct semaphore lock; + struct task_struct *owner; + u_int8_t fgHalt; + u_int8_t fgHeldByKalIoctl; + OS_SYSTIME u4HoldStart; +}; + +struct KAL_THREAD_SCHEDSTATS { + /* when marked: the profiling start time(ms), + * when unmarked: total duration(ms) + */ + unsigned long long time; + /* time spent in exec (sum_exec_runtime) */ + unsigned long long exec; + /* time spent in run-queue while not being scheduled (wait_sum) */ + unsigned long long runnable; + /* time spent waiting for I/O (iowait_sum) */ + unsigned long long iowait; +}; + +/******************************************************************************* + * P U B 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 KAL_SET_BIT(bitOffset, value) set_bit(bitOffset, &value) +#define KAL_CLR_BIT(bitOffset, value) clear_bit(bitOffset, &value) +#define KAL_TEST_AND_CLEAR_BIT(bitOffset, value) \ + test_and_clear_bit(bitOffset, &value) +#define KAL_TEST_BIT(bitOffset, value) test_bit(bitOffset, &value) +#define SUSPEND_FLAG_FOR_WAKEUP_REASON (0) +#define SUSPEND_FLAG_CLEAR_WHEN_RESUME (1) + + +/*----------------------------------------------------------------------------*/ +/* Macros of getting current thread id */ +/*----------------------------------------------------------------------------*/ +#define KAL_GET_CURRENT_THREAD_ID() (current->pid) +#define KAL_GET_CURRENT_THREAD_NAME() (current->comm) + +/*----------------------------------------------------------------------------*/ +/* Macros of SPIN LOCK operations for using in Driver Layer */ +/*----------------------------------------------------------------------------*/ +#define KAL_SPIN_LOCK_DECLARATION() unsigned long __ulFlags + +#define KAL_ACQUIRE_SPIN_LOCK(_prAdapter, _rLockCategory) \ + kalAcquireSpinLock(((struct ADAPTER *)_prAdapter)->prGlueInfo, \ + _rLockCategory, &__ulFlags) + +#define KAL_RELEASE_SPIN_LOCK(_prAdapter, _rLockCategory) \ + kalReleaseSpinLock(((struct ADAPTER *)_prAdapter)->prGlueInfo, \ + _rLockCategory, __ulFlags) + +/*----------------------------------------------------------------------------*/ +/* Macros of MUTEX operations for using in Driver Layer */ +/*----------------------------------------------------------------------------*/ +#define KAL_ACQUIRE_MUTEX(_prAdapter, _rLockCategory) \ + kalAcquireMutex(((struct ADAPTER *)_prAdapter)->prGlueInfo, \ + _rLockCategory) + +#define KAL_RELEASE_MUTEX(_prAdapter, _rLockCategory) \ + kalReleaseMutex(((struct ADAPTER *)_prAdapter)->prGlueInfo, \ + _rLockCategory) + +/*----------------------------------------------------------------------------*/ +/* 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 for kernel related defines */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(3, 14, 0) > CFG80211_VERSION_CODE +#define IEEE80211_CHAN_PASSIVE_FLAG IEEE80211_CHAN_PASSIVE_SCAN +#define IEEE80211_CHAN_PASSIVE_STR "PASSIVE" +#else +#define IEEE80211_CHAN_PASSIVE_FLAG IEEE80211_CHAN_NO_IR +#define IEEE80211_CHAN_PASSIVE_STR "NO_IR" +#endif + +#if KERNEL_VERSION(4, 7, 0) <= CFG80211_VERSION_CODE +/** + * enum nl80211_band - Frequency band + * @NL80211_BAND_2GHZ: 2.4 GHz ISM band + * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz) + * @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 64.80 GHz) + * @NUM_NL80211_BANDS: number of bands, avoid using this in userspace + * since newer kernel versions may support more bands + */ +#define KAL_BAND_2GHZ NL80211_BAND_2GHZ +#define KAL_BAND_5GHZ NL80211_BAND_5GHZ +#define KAL_NUM_BANDS NUM_NL80211_BANDS +#else +#define KAL_BAND_2GHZ IEEE80211_BAND_2GHZ +#define KAL_BAND_5GHZ IEEE80211_BAND_5GHZ +#define KAL_NUM_BANDS IEEE80211_NUM_BANDS +#endif + +/** + * enum nl80211_reg_rule_flags - regulatory rule flags + * @NL80211_RRF_NO_OFDM: OFDM modulation not allowed + * @NL80211_RRF_AUTO_BW: maximum available bandwidth should be calculated + * base on contiguous rules and wider channels will be allowed to cross + * multiple contiguous/overlapping frequency ranges. + * @NL80211_RRF_DFS: DFS support is required to be used + */ +#define KAL_RRF_NO_OFDM NL80211_RRF_NO_OFDM +#define KAL_RRF_DFS NL80211_RRF_DFS +#if KERNEL_VERSION(3, 15, 0) > CFG80211_VERSION_CODE +#define KAL_RRF_AUTO_BW 0 +#else +#define KAL_RRF_AUTO_BW NL80211_RRF_AUTO_BW +#endif + +/** + * kalCfg80211ScanDone - abstraction of cfg80211_scan_done + * + * @request: the corresponding scan request (sanity checked by callers!) + * @aborted: set to true if the scan was aborted for any reason, + * userspace will be notified of that + * + * Since linux-4.8.y the 2nd parameter is changed from bool to + * struct cfg80211_scan_info, but we don't use all fields yet. + */ +#if KERNEL_VERSION(4, 8, 0) <= CFG80211_VERSION_CODE +static inline void kalCfg80211ScanDone(struct cfg80211_scan_request *request, + bool aborted) +{ + struct cfg80211_scan_info info = {.aborted = aborted }; + + cfg80211_scan_done(request, &info); +} +#else +static inline void kalCfg80211ScanDone(struct cfg80211_scan_request *request, + bool aborted) +{ + cfg80211_scan_done(request, aborted); +} +#endif + +/* Consider on some Android platform, using request_firmware_direct() + * may cause system failed to load firmware. So we still use + * request_firmware(). + */ +#define REQUEST_FIRMWARE(_fw, _name, _dev) \ + request_firmware(_fw, _name, _dev) + +/*----------------------------------------------------------------------------*/ +/* Macros of wake_lock operations for using in Driver Layer */ +/*----------------------------------------------------------------------------*/ +#if CFG_ENABLE_WAKE_LOCK +/* CONFIG_ANDROID is defined in Android kernel source */ +#if (KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE) +#define KAL_WAKE_LOCK_INIT(_prAdapter, _prWakeLock, _pcName) \ + wakeup_source_init(_prWakeLock, _pcName) + +#define KAL_WAKE_LOCK_DESTROY(_prAdapter, _prWakeLock) \ + wakeup_source_trash(_prWakeLock) + +#define KAL_WAKE_LOCK(_prAdapter, _prWakeLock) ({ \ + u_int8_t state = 0; \ + if (halIsHifStateReady(_prAdapter, &state)) { \ + __pm_stay_awake(_prWakeLock); \ + } \ +}) + +#define KAL_WAKE_LOCK_TIMEOUT(_prAdapter, _prWakeLock, _u4Timeout) ({ \ + u_int8_t state = 0; \ + if (halIsHifStateReady(_prAdapter, &state)) { \ + __pm_wakeup_event(_prWakeLock, _u4Timeout); \ + } \ +}) +#define KAL_WAKE_UNLOCK(_prAdapter, _prWakeLock) \ + __pm_relax(_prWakeLock) + +#define KAL_WAKE_LOCK_ACTIVE(_prAdapter, _prWakeLock) \ + ((_prWakeLock)->active) + +#else +#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) ({ \ + u_int8_t state = 0; \ + if (halIsHifStateReady(_prAdapter, &state)) { \ + wake_lock(_prWakeLock); \ + } \ +}) + +#define KAL_WAKE_LOCK_TIMEOUT(_prAdapter, _prWakeLock, _u4Timeout) ({ \ + u_int8_t state = 0; \ + if (halIsHifStateReady(_prAdapter, &state)) { \ + wake_lock_timeout(_prWakeLock, _u4Timeout); \ + } \ +}) + +#define KAL_WAKE_UNLOCK(_prAdapter, _prWakeLock) \ + wake_unlock(_prWakeLock) + +#define KAL_WAKE_LOCK_ACTIVE(_prAdapter, _prWakeLock) \ + wake_lock_active(_prWakeLock) +#endif + +#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) +#define KAL_WAKE_LOCK_ACTIVE(_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) { \ + if (in_interrupt()) \ + pvAddr = kmalloc(u4Size, GFP_ATOMIC); \ + else \ + pvAddr = kmalloc(u4Size, GFP_KERNEL); \ + } \ + else { \ + pvAddr = vmalloc(u4Size); \ + } \ + if (pvAddr) { \ + allocatedMemSize += u4Size; \ + DBGLOG(INIT, INFO, "0x%p(%ld) allocated (%s:%s)\n", \ + pvAddr, (uint32_t)u4Size, __FILE__, __func__); \ + } \ + pvAddr; \ +}) +#else +#define kalMemAlloc(u4Size, eMemType) ({ \ + void *pvAddr; \ + if (eMemType == PHY_MEM_TYPE) { \ + if (in_interrupt()) \ + pvAddr = kmalloc(u4Size, GFP_ATOMIC); \ + else \ + pvAddr = kmalloc(u4Size, GFP_KERNEL); \ + } \ + else { \ + pvAddr = vmalloc(u4Size); \ + } \ + if (!pvAddr) \ + ASSERT_NOMEM(); \ + pvAddr; \ +}) +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Free allocated cache memory + * + * \param[in] pvAddr Required memory size. + * \param[in] eMemType Memory allocation type + * \param[in] u4Size Allocated memory size. + * + * \return - + */ +/*----------------------------------------------------------------------------*/ +#if DBG +#define kalMemFree(pvAddr, eMemType, u4Size) \ +{ \ + if (pvAddr) { \ + allocatedMemSize -= u4Size; \ + DBGLOG(INIT, INFO, "0x%p(%ld) freed (%s:%s)\n", \ + pvAddr, (uint32_t)u4Size, __FILE__, __func__); \ + } \ + if (eMemType == PHY_MEM_TYPE) { \ + kfree(pvAddr); \ + pvAddr = NULL; \ + } \ + else { \ + vfree(pvAddr); \ + pvAddr = NULL; \ + } \ +} +#else +#define kalMemFree(pvAddr, eMemType, u4Size) \ +{ \ + if (eMemType == PHY_MEM_TYPE) { \ + kfree(pvAddr); \ + pvAddr = NULL; \ + } \ + else { \ + vfree(pvAddr); \ + pvAddr = NULL; \ + } \ +} +#endif + +#define kalUdelay(u4USec) udelay(u4USec) + +#define kalMdelay(u4MSec) mdelay(u4MSec) +#define kalMsleep(u4MSec) msleep(u4MSec) +#define kalUsleep_range(u4MinUSec, u4MaxUSec) \ + usleep_range(u4MinUSec, u4MaxUSec) + +/* 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) + +/* Move memory block with specific size */ +#define kalMemMove(pvDst, pvSrc, u4Size) \ + memmove(pvDst, pvSrc, u4Size) + +#if KERNEL_VERSION(4, 0, 0) <= LINUX_VERSION_CODE +#define strnicmp(s1, s2, n) strncasecmp(s1, s2, n) +#endif + +/* string operation */ +#define kalStrCpy(dest, src) strcpy(dest, src) +#define kalStrnCpy(dest, src, n) strncpy(dest, src, n) +#define kalStrCmp(ct, cs) strcmp(ct, cs) +#define kalStrnCmp(ct, cs, n) strncmp(ct, cs, n) +#define kalStrChr(s, c) strchr(s, c) +#define kalStrrChr(s, c) strrchr(s, c) +#define kalStrnChr(s, n, c) strnchr(s, n, c) +#define kalStrLen(s) strlen(s) +#define kalStrnLen(s, b) strnlen(s, b) +#define kalStrniCmp(ct, cs, n) strncasecmp(ct, cs, n) +/* #define kalStrtoul(cp, endp, base) simple_strtoul(cp, endp, base) */ +/* #define kalStrtol(cp, endp, base) simple_strtol(cp, endp, base) */ +#define kalkStrtou8(cp, base, resp) kstrtou8(cp, base, resp) +#define kalkStrtou16(cp, base, resp) kstrtou16(cp, base, resp) +#define kalkStrtou32(cp, base, resp) kstrtou32(cp, base, resp) +#define kalkStrtos32(cp, base, resp) kstrtos32(cp, base, resp) +#define kalSnprintf(buf, size, fmt, ...) \ + snprintf(buf, size, fmt, ##__VA_ARGS__) +#define kalScnprintf(buf, size, fmt, ...) \ + scnprintf(buf, size, fmt, ##__VA_ARGS__) +#define kalSprintf(buf, fmt, ...) sprintf(buf, fmt, __VA_ARGS__) +/* remove for AOSP */ +/* #define kalSScanf(buf, fmt, ...) sscanf(buf, fmt, __VA_ARGS__) */ +#define kalStrStr(ct, cs) strstr(ct, cs) +#define kalStrSep(s, ct) strsep(s, ct) +#define kalStrCat(dest, src) strcat(dest, src) +#define kalIsXdigit(c) isxdigit(c) + +/* 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) \ + ((uint8_t *)((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) \ + ((uint32_t)((struct sk_buff *)pvPacket)->end - \ + (uint32_t)((struct sk_buff *)pvPacket)->data) + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is used to copy the entire frame from skb to the + * destination address in the input parameter. + * + * \param[in] prGlueInfo Pointer of GLUE Data Structure + * \param[in] pvPacket Pointer of Packet Handle + * \param[in] pucDestBuffer Destination Address + * + * \return - + */ +/*----------------------------------------------------------------------------*/ +#define kalCopyFrame(prGlueInfo, pvPacket, pucDestBuffer) \ + do {struct sk_buff *skb = (struct sk_buff *)pvPacket; \ + memcpy(pucDestBuffer, skb->data, skb->len); } while (0) + +#define kalGetTimeTick() jiffies_to_msecs(jiffies) + +#define WLAN_TAG "[wlan]" +#define kalPrint(_Fmt...) pr_info(WLAN_TAG _Fmt) +#define kalPrintLimited(_Fmt...) pr_info_ratelimited(WLAN_TAG _Fmt) + +#define kalBreakPoint() \ +do { \ + WARN_ON(1); \ + panic("Oops"); \ +} while (0) + +#if CFG_ENABLE_AEE_MSG +#define kalSendAeeException aee_kernel_exception +#define kalSendAeeWarning aee_kernel_warning +#define kalSendAeeReminding aee_kernel_reminding +#else +#define kalSendAeeException(_module, _desc, ...) +#define kalSendAeeWarning(_module, _desc, ...) +#define kalSendAeeReminding(_module, _desc, ...) +#endif + +#define PRINTF_ARG(...) __VA_ARGS__ +#define SPRINTF(buf, arg) {buf += sprintf((char *)(buf), PRINTF_ARG arg); } + +#define USEC_TO_SYSTIME(_usec) ((_usec) / USEC_PER_MSEC) +#define MSEC_TO_SYSTIME(_msec) (_msec) + +#define MSEC_TO_JIFFIES(_msec) msecs_to_jiffies(_msec) + +#define KAL_TIME_INTERVAL_DECLARATION() struct timeval __rTs, __rTe +#define KAL_REC_TIME_START() do_gettimeofday(&__rTs) +#define KAL_REC_TIME_END() do_gettimeofday(&__rTe) +#define KAL_GET_TIME_INTERVAL() \ + ((SEC_TO_USEC(__rTe.tv_sec) + __rTe.tv_usec) - \ + (SEC_TO_USEC(__rTs.tv_sec) + __rTs.tv_usec)) +#define KAL_ADD_TIME_INTERVAL(_Interval) \ + { \ + (_Interval) += KAL_GET_TIME_INTERVAL(); \ + } + +#if defined(_HIF_PCIE) +#define KAL_DMA_TO_DEVICE PCI_DMA_TODEVICE +#define KAL_DMA_FROM_DEVICE PCI_DMA_FROMDEVICE + +#define KAL_DMA_ALLOC_COHERENT(_dev, _size, _handle) \ + pci_alloc_consistent(_dev, _size, _handle) +#define KAL_DMA_FREE_COHERENT(_dev, _size, _addr, _handle) \ + pci_free_consistent(_dev, _size, _addr, _handle) +#define KAL_DMA_MAP_SINGLE(_dev, _ptr, _size, _dir) \ + pci_map_single(_dev, _ptr, _size, _dir) +#define KAL_DMA_UNMAP_SINGLE(_dev, _addr, _size, _dir) \ + pci_unmap_single(_dev, _addr, _size, _dir) +#define KAL_DMA_MAPPING_ERROR(_dev, _addr) \ + pci_dma_mapping_error(_dev, _addr) +#else +#define KAL_DMA_TO_DEVICE DMA_TO_DEVICE +#define KAL_DMA_FROM_DEVICE DMA_FROM_DEVICE + +#define KAL_DMA_ALLOC_COHERENT(_dev, _size, _handle) \ + dma_alloc_coherent(_dev, _size, _handle, GFP_DMA) +#define KAL_DMA_FREE_COHERENT(_dev, _size, _addr, _handle) \ + dma_free_coherent(_dev, _size, _addr, _handle) +#define KAL_DMA_MAP_SINGLE(_dev, _ptr, _size, _dir) \ + dma_map_single(_dev, _ptr, _size, _dir) +#define KAL_DMA_UNMAP_SINGLE(_dev, _addr, _size, _dir) \ + dma_unmap_single(_dev, _addr, _size, _dir) +#define KAL_DMA_MAPPING_ERROR(_dev, _addr) \ + dma_mapping_error(_dev, _addr) +#endif + +#if defined(_HIF_AXI) +#define KAL_ARCH_SETUP_DMA_OPS(_dev, _base, _size, _iommu, _coherent) \ + connectivity_arch_setup_dma_ops(_dev, _base, _size, _iommu, _coherent) +#else +#define KAL_ARCH_SETUP_DMA_OPS(_dev, _base, _size, _iommu, _coherent) +#endif + +/*----------------------------------------------------------------------------*/ +/* Macros of show stack operations for using in Driver Layer */ +/*----------------------------------------------------------------------------*/ +#ifdef CONFIG_X86 +#define kal_show_stack(_adapter, _task, _sp) +#else +#define kal_show_stack(_adapter, _task, _sp) \ +{ \ + if (_adapter->chip_info->showTaskStack) { \ + _adapter->chip_info->showTaskStack(_task, _sp); \ + } \ +} +#endif + +/******************************************************************************* + * 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 struct GLUE_INFO *prGlueInfo, + IN enum ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, + OUT unsigned long *plFlags); + +void kalReleaseSpinLock(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, + IN unsigned long ulFlags); + +void kalUpdateMACAddress(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucMacAddr); + +void kalAcquireMutex(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_MUTEX_CATEGORY_E rMutexCategory); + +void kalReleaseMutex(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_MUTEX_CATEGORY_E rMutexCategory); + +void kalPacketFree(IN struct GLUE_INFO *prGlueInfo, + IN void *pvPacket); + +void *kalPacketAlloc(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Size, + OUT uint8_t **ppucData); + +void *kalPacketAllocWithHeadroom(IN struct GLUE_INFO + *prGlueInfo, + IN uint32_t u4Size, OUT uint8_t **ppucData); + +void kalOsTimerInitialize(IN struct GLUE_INFO *prGlueInfo, + IN void *prTimerHandler); + +u_int8_t kalSetTimer(IN struct GLUE_INFO *prGlueInfo, + IN OS_SYSTIME rInterval); + +uint32_t +kalProcessRxPacket(IN struct GLUE_INFO *prGlueInfo, + IN void *pvPacket, + IN uint8_t *pucPacketStart, IN uint32_t u4PacketLen, + /* IN PBOOLEAN pfgIsRetain, */ + IN u_int8_t fgIsRetain, IN enum ENUM_CSUM_RESULT aeCSUM[]); + +uint32_t kalRxIndicatePkts(IN struct GLUE_INFO *prGlueInfo, + IN void *apvPkts[], + IN uint8_t ucPktNum); + +uint32_t kalRxIndicateOnePkt(IN struct GLUE_INFO + *prGlueInfo, IN void *pvPkt); + +void +kalIndicateStatusAndComplete(IN struct GLUE_INFO + *prGlueInfo, + IN uint32_t eStatus, IN void *pvBuf, + IN uint32_t u4BufLen); + +void +kalUpdateReAssocReqInfo(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucFrameBody, IN uint32_t u4FrameBodyLen, + IN u_int8_t fgReassocRequest); + +void kalUpdateReAssocRspInfo(IN struct GLUE_INFO + *prGlueInfo, + IN uint8_t *pucFrameBody, + IN uint32_t u4FrameBodyLen); + +#if CFG_TX_FRAGMENT +u_int8_t +kalQueryTxPacketHeader(IN struct GLUE_INFO *prGlueInfo, + IN void *pvPacket, OUT uint16_t *pu2EtherTypeLen, + OUT uint8_t *pucEthDestAddr); +#endif /* CFG_TX_FRAGMENT */ + +void kalSendCompleteAndAwakeQueue(IN struct GLUE_INFO + *prGlueInfo, + IN void *pvPacket); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +void kalQueryTxChksumOffloadParam(IN void *pvPacket, + OUT uint8_t *pucFlag); + +void kalUpdateRxCSUMOffloadParam(IN void *pvPacket, + IN enum ENUM_CSUM_RESULT eCSUM[]); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +u_int8_t kalRetrieveNetworkAddress(IN struct GLUE_INFO *prGlueInfo, + IN OUT uint8_t *prMacAddr); + +void +kalReadyOnChannel(IN struct GLUE_INFO *prGlueInfo, + IN uint64_t u8Cookie, + IN enum ENUM_BAND eBand, IN enum ENUM_CHNL_EXT eSco, + IN uint8_t ucChannelNum, IN uint32_t u4DurationMs); + +void +kalRemainOnChannelExpired(IN struct GLUE_INFO *prGlueInfo, + IN uint64_t u8Cookie, IN enum ENUM_BAND eBand, + IN enum ENUM_CHNL_EXT eSco, IN uint8_t ucChannelNum); + +#if CFG_SUPPORT_DFS +void +kalIndicateChannelSwitch(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_CHNL_EXT eSco, + IN uint8_t ucChannelNum); +#endif + +void +kalIndicateMgmtTxStatus(IN struct GLUE_INFO *prGlueInfo, + IN uint64_t u8Cookie, IN u_int8_t fgIsAck, + IN uint8_t *pucFrameBuf, IN uint32_t u4FrameLen); + +void kalIndicateRxMgmtFrame(IN struct GLUE_INFO *prGlueInfo, + IN struct SW_RFB *prSwRfb); + +/*----------------------------------------------------------------------------*/ +/* Routines in interface - ehpi/sdio.c */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalDevRegRead(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Register, + OUT uint32_t *pu4Value); +u_int8_t kalDevRegRead_mac(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Register, OUT uint32_t *pu4Value); + +u_int8_t kalDevRegWrite(struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Register, + IN uint32_t u4Value); +u_int8_t kalDevRegWrite_mac(struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Register, IN uint32_t u4Value); + +u_int8_t +kalDevPortRead(IN struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port, IN uint32_t u2Len, OUT uint8_t *pucBuf, + IN uint32_t u2ValidOutBufSize); + +u_int8_t +kalDevPortWrite(struct GLUE_INFO *prGlueInfo, + IN uint16_t u2Port, IN uint32_t u2Len, IN uint8_t *pucBuf, + IN uint32_t u2ValidInBufSize); + +u_int8_t kalDevWriteData(IN struct GLUE_INFO *prGlueInfo, + IN struct MSDU_INFO *prMsduInfo); +u_int8_t kalDevWriteCmd(IN struct GLUE_INFO *prGlueInfo, + IN struct CMD_INFO *prCmdInfo, IN uint8_t ucTC); +u_int8_t kalDevKickData(IN struct GLUE_INFO *prGlueInfo); +void kalDevReadIntStatus(IN struct ADAPTER *prAdapter, + OUT uint32_t *pu4IntStatus); + +u_int8_t kalDevWriteWithSdioCmd52(IN struct GLUE_INFO + *prGlueInfo, + IN uint32_t u4Addr, IN uint8_t ucData); + +#if CFG_SUPPORT_EXT_CONFIG +uint32_t kalReadExtCfg(IN struct GLUE_INFO *prGlueInfo); +#endif + +u_int8_t +kalQoSFrameClassifierAndPacketInfo(IN struct GLUE_INFO + *prGlueInfo, + IN void *prPacket, + OUT struct TX_PACKET_INFO *prTxPktInfo); + +u_int8_t kalGetEthDestAddr(IN struct GLUE_INFO *prGlueInfo, + IN void *prPacket, + OUT uint8_t *pucEthDestAddr); + +void +kalOidComplete(IN struct GLUE_INFO *prGlueInfo, + IN u_int8_t fgSetQuery, IN uint32_t u4SetQueryInfoLen, + IN uint32_t rOidStatus); + +uint32_t +kalIoctl(IN struct GLUE_INFO *prGlueInfo, + IN PFN_OID_HANDLER_FUNC pfnOidHandler, + IN void *pvInfoBuf, + IN uint32_t u4InfoBufLen, IN u_int8_t fgRead, + IN u_int8_t fgWaitResp, + IN u_int8_t fgCmd, OUT uint32_t *pu4QryInfoLen); + +void kalHandleAssocInfo(IN struct GLUE_INFO *prGlueInfo, + IN struct EVENT_ASSOC_INFO *prAssocInfo); + +#if CFG_ENABLE_FW_DOWNLOAD +void *kalFirmwareImageMapping(IN struct GLUE_INFO + *prGlueInfo, + OUT void **ppvMapFileBuf, + OUT uint32_t *pu4FileLength, + IN enum ENUM_IMG_DL_IDX_T eDlIdx); +void kalFirmwareImageUnmapping(IN struct GLUE_INFO + *prGlueInfo, + IN void *prFwHandle, IN void *pvMapFileBuf); +#endif + +#if CFG_CHIP_RESET_SUPPORT +void kalRemoveProbe(IN struct GLUE_INFO *prGlueInfo); +#endif +/*----------------------------------------------------------------------------*/ +/* Card Removal Check */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalIsCardRemoved(IN struct GLUE_INFO *prGlueInfo); + +/*----------------------------------------------------------------------------*/ +/* TX */ +/*----------------------------------------------------------------------------*/ +void kalFlushPendingTxPackets(IN struct GLUE_INFO + *prGlueInfo); + +/*----------------------------------------------------------------------------*/ +/* Media State Indication */ +/*----------------------------------------------------------------------------*/ +enum ENUM_PARAM_MEDIA_STATE kalGetMediaStateIndicated( + IN struct GLUE_INFO + *prGlueInfo); + +void kalSetMediaStateIndicated(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_PARAM_MEDIA_STATE eParamMediaStateIndicate); + +/*----------------------------------------------------------------------------*/ +/* OID handling */ +/*----------------------------------------------------------------------------*/ +void kalOidCmdClearance(IN struct GLUE_INFO *prGlueInfo); + +void kalOidClearance(IN struct GLUE_INFO *prGlueInfo); + +void kalEnqueueCommand(IN struct GLUE_INFO *prGlueInfo, + IN struct QUE_ENTRY *prQueueEntry); + +#if CFG_ENABLE_BT_OVER_WIFI +/*----------------------------------------------------------------------------*/ +/* Bluetooth over Wi-Fi handling */ +/*----------------------------------------------------------------------------*/ +void kalIndicateBOWEvent(IN struct GLUE_INFO *prGlueInfo, + IN struct BT_OVER_WIFI_EVENT *prEvent); + +enum ENUM_BOW_DEVICE_STATE kalGetBowState( + IN struct GLUE_INFO *prGlueInfo, + IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN]); + +u_int8_t kalSetBowState(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_BOW_DEVICE_STATE eBowState, + uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN]); + +enum ENUM_BOW_DEVICE_STATE kalGetBowGlobalState( + IN struct GLUE_INFO + *prGlueInfo); + +uint32_t kalGetBowFreqInKHz(IN struct GLUE_INFO + *prGlueInfo); + +uint8_t kalGetBowRole(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN]); + +void kalSetBowRole(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRole, + IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN]); + +uint8_t kalGetBowAvailablePhysicalLinkCount( + IN struct GLUE_INFO *prGlueInfo); + +#if CFG_BOW_SEPARATE_DATA_PATH +/*----------------------------------------------------------------------------*/ +/* Bluetooth over Wi-Fi Net Device Init/Uninit */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalInitBowDevice(IN struct GLUE_INFO *prGlueInfo, + IN const char *prDevName); + +u_int8_t kalUninitBowDevice(IN struct GLUE_INFO + *prGlueInfo); +#endif /* CFG_BOW_SEPARATE_DATA_PATH */ +#endif /* CFG_ENABLE_BT_OVER_WIFI */ + +/*----------------------------------------------------------------------------*/ +/* Security Frame Clearance */ +/*----------------------------------------------------------------------------*/ +void kalClearSecurityFrames(IN struct GLUE_INFO + *prGlueInfo); + +void kalClearSecurityFramesByBssIdx(IN struct GLUE_INFO + *prGlueInfo, + IN uint8_t ucBssIndex); + +void kalSecurityFrameSendComplete(IN struct GLUE_INFO + *prGlueInfo, + IN void *pvPacket, IN uint32_t rStatus); + +/*----------------------------------------------------------------------------*/ +/* Management Frame Clearance */ +/*----------------------------------------------------------------------------*/ +void kalClearMgmtFrames(IN struct GLUE_INFO *prGlueInfo); + +void kalClearMgmtFramesByBssIdx(IN struct GLUE_INFO + *prGlueInfo, + IN uint8_t ucBssIndex); + +uint32_t kalGetTxPendingFrameCount(IN struct GLUE_INFO + *prGlueInfo); + +uint32_t kalGetTxPendingCmdCount(IN struct GLUE_INFO + *prGlueInfo); + +void kalClearCommandQueue(IN struct GLUE_INFO *prGlueInfo); + +u_int8_t kalSetTimer(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Interval); + +u_int8_t kalCancelTimer(IN struct GLUE_INFO *prGlueInfo); + +void kalScanDone(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_KAL_NETWORK_TYPE_INDEX eNetTypeIdx, + IN uint32_t status); + +#if CFG_SUPPORT_SCAN_CACHE_RESULT +uint8_t kalUpdateBssTimestamp(IN struct GLUE_INFO *prGlueInfo); +#endif /* CFG_SUPPORT_SCAN_CACHE_RESULT */ + +uint32_t kalRandomNumber(void); + +#if KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE +void kalTimeoutHandler(struct timer_list *timer); +#else +void kalTimeoutHandler(unsigned long arg); +#endif + +void kalSetEvent(struct GLUE_INFO *pr); + +void kalSetIntEvent(struct GLUE_INFO *pr); + +void kalSetHifDbgEvent(struct GLUE_INFO *pr); + +#if CFG_SUPPORT_MULTITHREAD +void kalSetTxEvent2Hif(struct GLUE_INFO *pr); + +void kalSetTxEvent2Rx(struct GLUE_INFO *pr); + +void kalSetTxCmdEvent2Hif(struct GLUE_INFO *pr); +#endif +/*----------------------------------------------------------------------------*/ +/* NVRAM/Registry Service */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalIsConfigurationExist(IN struct GLUE_INFO + *prGlueInfo); + +struct REG_INFO *kalGetConfiguration(IN struct GLUE_INFO + *prGlueInfo); + +u_int8_t kalCfgDataRead(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Offset, + IN ssize_t len, OUT uint16_t *pu2Data); + +u_int8_t kalCfgDataRead16(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Offset, + OUT uint16_t *pu2Data); + +u_int8_t kalCfgDataWrite16(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Offset, IN uint16_t u2Data); + +/*----------------------------------------------------------------------------*/ +/* WSC Connection */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalWSCGetActiveState(IN struct GLUE_INFO + *prGlueInfo); + +/*----------------------------------------------------------------------------*/ +/* RSSI Updating */ +/*----------------------------------------------------------------------------*/ +void +kalUpdateRSSI(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_KAL_NETWORK_TYPE_INDEX eNetTypeIdx, + IN int8_t cRssi, + IN int8_t cLinkQuality); + +/*----------------------------------------------------------------------------*/ +/* I/O Buffer Pre-allocation */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalInitIOBuffer(u_int8_t is_pre_alloc); + +void kalUninitIOBuffer(void); + +void *kalAllocateIOBuffer(IN uint32_t u4AllocSize); + +void kalReleaseIOBuffer(IN void *pvAddr, + IN uint32_t u4Size); + +void +kalGetChannelList(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_BAND eSpecificBand, + IN uint8_t ucMaxChannelNum, IN uint8_t *pucNumOfChannel, + IN struct RF_CHANNEL_INFO *paucChannelList); + +u_int8_t kalIsAPmode(IN struct GLUE_INFO *prGlueInfo); + +#if CFG_SUPPORT_802_11W +/*----------------------------------------------------------------------------*/ +/* 802.11W */ +/*----------------------------------------------------------------------------*/ +uint32_t kalGetMfpSetting(IN struct GLUE_INFO *prGlueInfo); +uint8_t kalGetRsnIeMfpCap(IN struct GLUE_INFO *prGlueInfo); +#endif + +/*----------------------------------------------------------------------------*/ +/* file opetation */ +/*----------------------------------------------------------------------------*/ +uint32_t kalWriteToFile(const uint8_t *pucPath, + u_int8_t fgDoAppend, + uint8_t *pucData, uint32_t u4Size); + +uint32_t kalCheckPath(const uint8_t *pucPath); + +uint32_t kalTrunkPath(const uint8_t *pucPath); + +int32_t kalReadToFile(const uint8_t *pucPath, + uint8_t *pucData, + uint32_t u4Size, uint32_t *pu4ReadSize); + +int32_t kalRequestFirmware(const uint8_t *pucPath, + uint8_t *pucData, + uint32_t u4Size, uint32_t *pu4ReadSize, + struct device *dev); + + +/*----------------------------------------------------------------------------*/ +/* NL80211 */ +/*----------------------------------------------------------------------------*/ +void +kalIndicateBssInfo(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucFrameBuf, IN uint32_t u4BufLen, + IN uint8_t ucChannelNum, IN int32_t i4SignalStrength); + +/*----------------------------------------------------------------------------*/ +/* Net device */ +/*----------------------------------------------------------------------------*/ +uint32_t +kalHardStartXmit(struct sk_buff *prSkb, + IN struct net_device *prDev, + struct GLUE_INFO *prGlueInfo, uint8_t ucBssIndex); + +u_int8_t kalIsPairwiseEapolPacket(IN void *prPacket); + +u_int8_t +kalGetIPv4Address(IN struct net_device *prDev, + IN uint32_t u4MaxNumOfAddr, OUT uint8_t *pucIpv4Addrs, + OUT uint32_t *pu4NumOfIpv4Addr); + +#if IS_ENABLED(CONFIG_IPV6) +u_int8_t +kalGetIPv6Address(IN struct net_device *prDev, + IN uint32_t u4MaxNumOfAddr, OUT uint8_t *pucIpv6Addrs, + OUT uint32_t *pu4NumOfIpv6Addr); +#else +static inline u_int8_t +kalGetIPv6Address(IN struct net_device *prDev, + IN uint32_t u4MaxNumOfAddr, OUT uint8_t *pucIpv6Addrs, + OUT uint32_t *pu4NumOfIpv6Addr) { + /* Not support IPv6 */ + *pu4NumOfIpv6Addr = 0; + return 0; +} +#endif /* IS_ENABLED(CONFIG_IPV6) */ + +void kalSetNetAddressFromInterface(IN struct GLUE_INFO + *prGlueInfo, + IN struct net_device *prDev, + IN u_int8_t fgSet); + +uint32_t kalResetStats(IN struct net_device *prDev); + +void *kalGetStats(IN struct net_device *prDev); + +void kalResetPacket(IN struct GLUE_INFO *prGlueInfo, + IN void *prPacket); + +#if CFG_SUPPORT_QA_TOOL +struct file *kalFileOpen(const char *path, int flags, + int rights); + +void kalFileClose(struct file *file); + +uint32_t kalFileRead(struct file *file, + unsigned long long offset, + unsigned char *data, unsigned int size); +#endif + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN +/*----------------------------------------------------------------------------*/ +/* SDIO Read/Write Pattern Support */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalSetSdioTestPattern(IN struct GLUE_INFO + *prGlueInfo, + IN u_int8_t fgEn, IN u_int8_t fgRead); +#endif + +/*----------------------------------------------------------------------------*/ +/* PNO Support */ +/*----------------------------------------------------------------------------*/ +void kalSchedScanResults(IN struct GLUE_INFO *prGlueInfo); + +void kalSchedScanStopped(IN struct GLUE_INFO *prGlueInfo, + u_int8_t fgDriverTriggerd); + +void kalSetFwOwnEvent2Hif(struct GLUE_INFO *pr); +#if CFG_ASSERT_DUMP +/* Core Dump out put file */ +uint32_t kalOpenCorDumpFile(u_int8_t fgIsN9); +uint32_t kalWriteCorDumpFile(uint8_t *pucBuffer, + uint16_t u2Size, + u_int8_t fgIsN9); +uint32_t kalCloseCorDumpFile(u_int8_t fgIsN9); +#endif +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#if CFG_WOW_SUPPORT +void kalWowInit(IN struct GLUE_INFO *prGlueInfo); +void kalWowProcess(IN struct GLUE_INFO *prGlueInfo, + uint8_t enable); +void kalInitMdnsCache(void); +void kalShowMdnsCache(void); +uint8_t kalAddMdnsCache(struct MDNS_RESP_INFO_T *resp); +void kalDelMdnsCache(struct MDNS_RESP_INFO_T *respInfo); +void kalSendAddMdnsCacheToFw(struct GLUE_INFO *prGlueInfo); +void kalSendDelMdnsCacheToFw(struct GLUE_INFO *prGlueInfo); +void kalSendMdnsEnableToFw(struct GLUE_INFO *prGlueInfo); +void kalSendMdnsDisableToFw(struct GLUE_INFO *prGlueInfo); +bool kalParseMdnsRespPkt(uint8_t *pucMdnsHdr, + struct MDNS_RESP_INFO_T *resp); +#endif + +int main_thread(void *data); + +#if CFG_SUPPORT_MULTITHREAD +int hif_thread(void *data); +int rx_thread(void *data); +#endif +uint64_t kalGetBootTime(void); + +int kalMetInitProcfs(IN struct GLUE_INFO *prGlueInfo); +int kalMetRemoveProcfs(void); + +uint8_t kalGetEapolKeyType(void *prPacket); + +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG +u_int8_t kalIsWakeupByWlan(struct ADAPTER *prAdapter); +#endif + +int32_t kalHaltLock(uint32_t waitMs); +int32_t kalHaltTryLock(void); +void kalHaltUnlock(void); +void kalSetHalted(u_int8_t fgHalt); +u_int8_t kalIsHalted(void); + +void kalFreeTxMsduWorker(struct work_struct *work); +void kalFreeTxMsdu(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +int32_t kalPerMonInit(IN struct GLUE_INFO *prGlueInfo); +int32_t kalPerMonDisable(IN struct GLUE_INFO *prGlueInfo); +int32_t kalPerMonEnable(IN struct GLUE_INFO *prGlueInfo); +int32_t kalPerMonStart(IN struct GLUE_INFO *prGlueInfo); +int32_t kalPerMonStop(IN struct GLUE_INFO *prGlueInfo); +int32_t kalPerMonDestroy(IN struct GLUE_INFO *prGlueInfo); +void kalPerMonHandler(IN struct ADAPTER *prAdapter, + unsigned long ulParam); +uint32_t kalPerMonGetInfo(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, + IN uint32_t u4Max); +int32_t kalBoostCpu(IN struct ADAPTER *prAdapter, + IN uint32_t u4TarPerfLevel, + IN uint32_t u4BoostCpuTh); +#if CFG_MTK_ANDROID_EMI +void kalSetEmiMpuProtection(phys_addr_t emiPhyBase, uint32_t offset, + uint32_t size, bool enable); +void kalSetDrvEmiMpuProtection(phys_addr_t emiPhyBase, uint32_t offset, + uint32_t size); +#endif +int32_t kalSetCpuNumFreq(uint32_t u4CoreNum, + uint32_t u4Freq); +int32_t kalPerMonSetForceEnableFlag(uint8_t uFlag); +int32_t kalFbNotifierReg(IN struct GLUE_INFO *prGlueInfo); +void kalFbNotifierUnReg(void); + +#if KERNEL_VERSION(3, 0, 0) <= LINUX_VERSION_CODE +/* since: 0b5c9db1b11d3175bb42b80663a9f072f801edf5 */ +static inline void kal_skb_reset_mac_len(struct sk_buff + *skb) +{ + skb_reset_mac_len(skb); +} +#else +static inline void kal_skb_reset_mac_len(struct sk_buff + *skb) +{ + skb->mac_len = skb->network_header - skb->mac_header; +} +#endif + +void kalInitDevWakeup(struct ADAPTER *prAdapter, struct device *prDev); + +u_int8_t kalIsValidMacAddr(const uint8_t *addr); + +u_int8_t kalScanParseRandomMac(const struct net_device *ndev, + const struct cfg80211_scan_request *request, uint8_t *pucRandomMac); + +u_int8_t kalSchedScanParseRandomMac(const struct net_device *ndev, + const struct cfg80211_sched_scan_request *request, + uint8_t *pucRandomMac, uint8_t *pucRandomMacMask); + +void kalScanReqLog(struct cfg80211_scan_request *request); +void kalScanChannelLog(struct cfg80211_scan_request *request, + const uint16_t logBufLen); +void kalScanSsidLog(struct cfg80211_scan_request *request, + const uint16_t logBufLen); +void kalScanResultLog(struct ADAPTER *prAdapter, struct ieee80211_mgmt *mgmt); +void kalScanLogCacheFlushBSS(struct ADAPTER *prAdapter, + const uint16_t logBufLen); + +void kalRxNapiSetEnable( + IN struct GLUE_INFO *prGlueInfo, + IN uint8_t enable); +uint8_t kalRxNapiIsEnable(IN struct GLUE_INFO *prGlueInfo); +uint8_t kalRxNapiValidSkb(struct GLUE_INFO *prGlueInfo, + struct sk_buff *prSkb); +int kalRxNapiPoll(struct napi_struct *napi, int budget); + +unsigned long kal_kallsyms_lookup_name(const char *name); + +#endif /* _GL_KAL_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_os.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_os.h new file mode 100644 index 0000000000000..9184cd8df4eef --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_os.h @@ -0,0 +1,1327 @@ + +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include + * /gl_os.h#4 + */ + +/*! \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. + */ + + +#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 */ + +/* 1: Enable use of SPIN LOCK Bottom Half for LINUX */ +/* 0: Disable - use SPIN LOCK IRQ SAVE instead */ +#define CFG_USE_SPIN_LOCK_BOTTOM_HALF 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_PADDING_SMALL_ETH_PACKET 0 + +#define CFG_TX_STOP_NETIF_QUEUE_THRESHOLD 256 /* packets */ + +#define CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD 256 /* packets */ +#define CFG_TX_START_NETIF_PER_QUEUE_THRESHOLD 128 /* packets */ + +#define CHIP_NAME "MT6632" + +#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) +#define GLUE_INFO_WSCIE_LENGTH (500) +/* for non-wfa vendor specific IE buffer */ +#define NON_WFA_VENDOR_IE_MAX_LEN (128) + + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include /* constant of kernel version */ + +#include /* bitops.h */ + +#include /* struct timer_list */ +#include /* jiffies */ +#include /* udelay and mdelay macro */ + +#ifdef CONFIG_ANDROID +#if (KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE) +#include +#include +#else +#include +#endif +#endif + +#if KERNEL_VERSION(2, 6, 12) < LINUX_VERSION_CODE +#include /* IRQT_FALLING */ +#endif + +#include /* struct net_device, struct net_device_stats */ +#include /* for eth_type_trans() function */ +#include /* struct iw_statistics */ +#include +#include /* struct in_device */ + +#include /* struct iphdr */ + +#include /* for memcpy()/memset() function */ +#include /* for offsetof() macro */ + +#include /* The proc filesystem constants/structures */ + +#include /* for rtnl_lock() and rtnl_unlock() */ +#include /* kthread_should_stop(), kthread_run() */ +#include /* for copy_from_user() */ +#include /* for firmware download */ +#include + +#include /* for kfifo interface */ +#include /* for cdev interface */ + +#include /* for firmware download */ +#include + +#include + +#if KERNEL_VERSION(4, 11, 0) <= LINUX_VERSION_CODE +#include +#endif + +#if defined(_HIF_USB) +#include +#include +#include +#endif + +#if defined(_HIF_PCIE) +#include +#endif + +#if defined(_HIF_SDIO) +#include +#include +#include +#endif + +#include + +#include /* readw and writew */ + +#if WIRELESS_EXT > 12 +#include +#endif + +#ifdef CFG_CFG80211_VERSION +#define CFG80211_VERSION_CODE CFG_CFG80211_VERSION +#else +#define CFG80211_VERSION_CODE LINUX_VERSION_CODE +#endif + +#include "version.h" +#include "config.h" + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#include +#include +#endif + +#include +#include +#include + +#if IS_ENABLED(CONFIG_IPV6) +#include +#include +#include +#endif + +#if CFG_SUPPORT_PASSPOINT +#include +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE +#include +#endif + +#include "gl_typedef.h" +#include "typedef.h" +#include "queue.h" +#include "gl_kal.h" +#include "gl_rst.h" +#include "hif.h" + +#if CFG_SUPPORT_TDLS +#include "tdls.h" +#endif + +#include "debug.h" + +#include "wlan_lib.h" +#include "wlan_oid.h" + +#if CFG_ENABLE_AEE_MSG +#ifdef CONFIG_ANDROID +#include +#else +#include +#endif +#endif + +#if CFG_MET_TAG_SUPPORT +#include +#endif +#include +#include +#include + + +extern u_int8_t fgIsBusAccessFailed; +extern const struct ieee80211_iface_combination + *p_mtk_iface_combinations_sta; +extern const int32_t mtk_iface_combinations_sta_num; +extern const struct ieee80211_iface_combination + *p_mtk_iface_combinations_p2p; +extern const int32_t mtk_iface_combinations_p2p_num; + +#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH +typedef void (*wifi_fwlog_event_func_cb)(int, int); +/* adaptor ko */ +extern int wifi_fwlog_onoff_status(void); +extern void wifi_fwlog_event_func_register(wifi_fwlog_event_func_cb pfFwlog); +#endif + +/******************************************************************************* + * 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_MULTICAST BIT(7) +#define GLUE_FLAG_FRAME_FILTER BIT(8) +#define GLUE_FLAG_FRAME_FILTER_AIS BIT(9) + +#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_MULTICAST_BIT (7) +#define GLUE_FLAG_FRAME_FILTER_BIT (8) +#define GLUE_FLAG_FRAME_FILTER_AIS_BIT (9) + +#if CFG_SUPPORT_MULTITHREAD +#define GLUE_FLAG_RX BIT(10) +#define GLUE_FLAG_TX_CMD_DONE BIT(11) +#define GLUE_FLAG_HIF_TX BIT(12) +#define GLUE_FLAG_HIF_TX_CMD BIT(13) +#define GLUE_FLAG_RX_TO_OS BIT(14) +#define GLUE_FLAG_HIF_FW_OWN BIT(15) +#define GLUE_FLAG_HIF_PRT_HIF_DBG_INFO BIT(16) + +#define GLUE_FLAG_RX_BIT (10) +#define GLUE_FLAG_TX_CMD_DONE_BIT (11) +#define GLUE_FLAG_HIF_TX_BIT (12) +#define GLUE_FLAG_HIF_TX_CMD_BIT (13) +#define GLUE_FLAG_RX_TO_OS_BIT (14) +#define GLUE_FLAG_HIF_FW_OWN_BIT (15) +#define GLUE_FLAG_HIF_PRT_HIF_DBG_INFO_BIT (16) +#endif + +#define GLUE_BOW_KFIFO_DEPTH (1024) +/* #define GLUE_BOW_DEVICE_NAME "MT6620 802.11 AMP" */ +#define GLUE_BOW_DEVICE_NAME "ampc0" + +#define WAKE_LOCK_RX_TIMEOUT 300 /* ms */ +#define WAKE_LOCK_THREAD_WAKEUP_TIMEOUT 50 /* ms */ + +#if CFG_SUPPORT_CFG80211_AUTH +#if KERNEL_VERSION(4, 0, 0) > CFG80211_VERSION_CODE +#define WLAN_CIPHER_SUITE_GCMP_256 0x000FAC09 +#define WLAN_CIPHER_SUITE_CCMP_256 0x000FAC0A +#define WLAN_CIPHER_SUITE_BIP_GMAC_128 0x000FAC0B +#define WLAN_CIPHER_SUITE_BIP_GMAC_256 0x000FAC0C +#define WLAN_CIPHER_SUITE_BIP_CMAC_256 0x000FAC0D +#endif + +#if KERNEL_VERSION(4, 12, 0) > CFG80211_VERSION_CODE +#define WLAN_AKM_SUITE_8021X_SUITE_B 0x000FAC0B +#define WLAN_AKM_SUITE_8021X_SUITE_B_192 0x000FAC0C +#endif + +#if CFG_SUPPORT_SAE +#ifndef WLAN_AKM_SUITE_SAE +#define WLAN_AKM_SUITE_SAE 0x000FAC08 +#endif +#endif +#if CFG_SUPPORT_OWE +#define WLAN_AKM_SUITE_OWE 0x000FAC12 +#endif + +#define IW_AUTH_CIPHER_GCMP256 0x00000080 +#endif + +/* EFUSE Auto Mode Support */ +#define LOAD_EFUSE 0 +#define LOAD_EEPROM_BIN 1 +#define LOAD_AUTO 2 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +struct GLUE_INFO; + +struct GL_WPA_INFO { + uint32_t u4WpaVersion; + uint32_t u4KeyMgmt; + uint32_t u4CipherGroup; + uint32_t u4CipherPairwise; + uint32_t u4AuthAlg; + u_int8_t fgPrivacyInvoke; +#if CFG_SUPPORT_802_11W + uint32_t u4CipherGroupMgmt; + uint32_t u4Mfp; + uint8_t ucRSNMfpCap; +#endif + uint8_t ucRsneLen; + uint8_t aucKek[NL80211_KEK_LEN]; + uint8_t aucKck[NL80211_KCK_LEN]; + uint8_t aucReplayCtr[NL80211_REPLAY_CTR_LEN]; +}; + +#if CFG_SUPPORT_REPLAY_DETECTION +struct GL_REPLEY_PN_INFO { + uint8_t auPN[16]; + u_int8_t fgRekey; + u_int8_t fgFirstPkt; +}; +struct GL_DETECT_REPLAY_INFO { + uint8_t ucCurKeyId; + uint8_t ucKeyType; + struct GL_REPLEY_PN_INFO arReplayPNInfo[4]; + uint32_t u4KeyLength; + uint8_t aucKeyMaterial[32]; + u_int8_t fgPairwiseInstalled; + u_int8_t fgKeyRscFresh; +}; +#endif + +#if CFG_SUPPORT_WOW_EINT +struct WOWLAN_DEV_NODE { + struct sdio_func *func; + + unsigned int wowlan_irq; + int wowlan_irqlevel; + atomic_t irq_enable_count; +}; +#endif + +enum ENUM_NET_DEV_IDX { + NET_DEV_WLAN_IDX = 0, + NET_DEV_P2P_IDX, + NET_DEV_BOW_IDX, + NET_DEV_NUM +}; + +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 +}; + +#if CFG_ENABLE_WIFI_DIRECT +enum ENUM_NET_REG_STATE { + 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 +}; +#endif + +enum ENUM_PKT_FLAG { + ENUM_PKT_802_11, /* 802.11 or non-802.11 */ + ENUM_PKT_802_3, /* 802.3 or ethernetII */ + ENUM_PKT_1X, /* 1x frame or not */ + ENUM_PKT_PROTECTED_1X, /* protected 1x frame */ + ENUM_PKT_NON_PROTECTED_1X, /* Non protected 1x frame */ + ENUM_PKT_VLAN_EXIST, /* VLAN tag exist */ + ENUM_PKT_DHCP, /* DHCP frame */ + ENUM_PKT_ARP, /* ARP */ + ENUM_PKT_ICMP, /* ICMP */ + ENUM_PKT_TDLS, /* TDLS */ + ENUM_PKT_DNS, /* DNS */ + + ENUM_PKT_FLAG_NUM +}; + +struct GL_IO_REQ { + struct QUE_ENTRY rQueEntry; + /* wait_queue_head_t cmdwait_q; */ + u_int8_t fgRead; + u_int8_t fgWaitResp; + struct ADAPTER *prAdapter; + PFN_OID_HANDLER_FUNC pfnOidHandler; + void *pvInfoBuf; + uint32_t u4InfoBufLen; + uint32_t *pu4QryInfoLen; + uint32_t rStatus; + uint32_t u4Flag; +}; + +#if CFG_ENABLE_BT_OVER_WIFI +struct GL_BOW_INFO { + u_int8_t 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; + uint32_t u4FreqInKHz; /* frequency */ + + uint8_t aucRole[CFG_BOW_PHYSICAL_LINK_NUM]; /* 0: Responder, + * 1: Initiator + */ + enum ENUM_BOW_DEVICE_STATE + aeState[CFG_BOW_PHYSICAL_LINK_NUM]; + uint8_t arPeerAddr[CFG_BOW_PHYSICAL_LINK_NUM][PARAM_MAC_ADDR_LEN]; + + wait_queue_head_t outq; + +#if CFG_BOW_SEPARATE_DATA_PATH + /* Device handle */ + struct net_device *prDevHandler; + u_int8_t fgIsNetRegistered; +#endif + +}; +#endif + +#if CFG_SUPPORT_SCAN_CACHE_RESULT +struct GL_SCAN_CACHE_INFO { + struct GLUE_INFO *prGlueInfo; + + /* for cfg80211 scan done indication */ + struct cfg80211_scan_request *prRequest; + + /* total number of channels to scan */ + uint32_t n_channels; + + /* Scan period time */ + OS_SYSTIME u4LastScanTime; +}; +#endif /* CFG_SUPPORT_SCAN_CACHE_RESULT */ + +struct FT_IES { + uint16_t u2MDID; + struct IE_MOBILITY_DOMAIN *prMDIE; + struct IE_FAST_TRANSITION *prFTIE; + struct IE_TIMEOUT_INTERVAL *prTIE; + struct RSN_INFO_ELEM *prRsnIE; + uint8_t *pucIEBuf; + uint32_t u4IeLength; +}; + +#if (CFG_SUPPORT_PERF_IND == 1) +struct GL_PERF_IND_INFO { + uint32_t u4CurTxBytes[BSSID_NUM]; /* Byte */ + uint32_t u4CurRxBytes[BSSID_NUM]; /* Byte */ + uint16_t u2CurRxRate[BSSID_NUM]; /* Unit 500 Kbps */ + uint8_t ucCurRxRCPI0[BSSID_NUM]; + uint8_t ucCurRxRCPI1[BSSID_NUM]; + uint8_t ucCurRxNss[BSSID_NUM]; +}; +#endif /* CFG_SUPPORT_SCAN_CACHE_RESULT */ + +/* + * type definition of pointer to p2p structure + */ +struct GL_P2P_INFO; /* declare GL_P2P_INFO_T */ +struct GL_P2P_DEV_INFO; /* declare GL_P2P_DEV_INFO_T */ + +struct GLUE_INFO { + /* Device handle */ + struct net_device *prDevHandler; + + /* Device */ + struct device *prDev; + + /* Device Index(index of arWlanDevInfo[]) */ + int32_t 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]; + + /* Mutex to protect interruptible section */ + struct mutex arMutex[MUTEX_NUM]; + + /* semaphore for ioctl */ + struct semaphore ioctl_sem; + + uint64_t u8Cookie; + + unsigned long ulFlag; /* GLUE_FLAG_XXX */ + uint32_t u4PendFlag; + uint32_t u4LinkDownPendFlag; + /* UINT_32 u4TimeoutFlag; */ + uint32_t u4OidCompleteFlag; + uint32_t u4ReadyFlag; /* check if card is ready */ + + uint32_t u4OsMgmtFrameFilter; + + /* Number of pending frames, also used for debuging if any frame is + * missing during the process of unloading Driver. + * + * NOTE(Kevin): In Linux, we also use this variable as the threshold + * for manipulating the netif_stop(wake)_queue() func. + */ + int32_t ai4TxPendingFrameNumPerQueue[MAX_BSSID_NUM][CFG_MAX_TXQ_NUM]; + int32_t i4TxPendingFrameNum; + int32_t i4TxPendingSecurityFrameNum; + int32_t i4TxPendingCmdNum; + + /* Tx: for NetDev to BSS index mapping */ + struct NET_INTERFACE_INFO arNetInterfaceInfo[MAX_BSSID_NUM]; + + /* Rx: for BSS index to NetDev mapping */ + /* P_NET_INTERFACE_INFO_T aprBssIdxToNetInterfaceInfo[HW_BSSID_NUM]; */ + + /* current IO request for kalIoctl */ + struct GL_IO_REQ OidEntry; + + /* registry info */ + struct REG_INFO rRegInfo; + + /* firmware */ + struct firmware *prFw; + + /* Host interface related information */ + /* defined in related hif header file */ + struct GL_HIF_INFO rHifInfo; + + /*! \brief wext wpa related information */ + struct GL_WPA_INFO rWpaInfo; +#if CFG_SUPPORT_REPLAY_DETECTION + struct GL_DETECT_REPLAY_INFO prDetRplyInfo; +#endif + + /* Pointer to ADAPTER_T - main data structure of internal protocol + * stack + */ + struct ADAPTER *prAdapter; + +#if WLAN_INCLUDE_PROC + struct proc_dir_entry *pProcRoot; +#endif /* WLAN_INCLUDE_PROC */ + + /* Indicated media state */ + enum ENUM_PARAM_MEDIA_STATE eParamMediaStateIndicated; + + /* Device power state D0~D3 */ + enum 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_SUPPORT_MULTITHREAD + struct completion + rHifHaltComp; /* indicate hif_thread halt complete */ + struct completion + rRxHaltComp; /* indicate hif_thread halt complete */ + + uint32_t u4TxThreadPid; + uint32_t u4RxThreadPid; + uint32_t u4HifThreadPid; +#endif + +#if CFG_SUPPORT_NCHO + struct completion + rAisChGrntComp; /* indicate Ais channel grant complete */ +#endif + + uint32_t rPendStatus; + + struct QUE rTxQueue; + + /* OID related */ + struct QUE 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; + +#if CFG_SUPPORT_MULTITHREAD + wait_queue_head_t waitq_hif; + struct task_struct *hif_thread; + + wait_queue_head_t waitq_rx; + struct task_struct *rx_thread; + +#endif + struct tasklet_struct rRxTask; + struct tasklet_struct rTxCompleteTask; + + struct work_struct rTxMsduFreeWork; + struct delayed_work rRxPktDeAggWork; + + struct timer_list tickfn; + +#if CFG_SUPPORT_EXT_CONFIG + uint16_t au2ExtCfg[256]; /* NVRAM data buffer */ + uint32_t u4ExtCfgLength; /* 0 means data is NOT valid */ +#endif + +#if 1 /* CFG_SUPPORT_WAPI */ + /* Should be large than the PARAM_WAPI_ASSOC_INFO_T */ + uint8_t aucWapiAssocInfoIEs[42]; + uint16_t u2WapiAssocInfoIESz; +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + struct GL_BOW_INFO rBowInfo; +#endif + +#if CFG_ENABLE_WIFI_DIRECT + struct GL_P2P_DEV_INFO *prP2PDevInfo; + struct GL_P2P_INFO *prP2PInfo[KAL_P2P_NUM]; +#if CFG_SUPPORT_P2P_RSSI_QUERY + /* Wireless statistics struct net_device */ + struct iw_statistics rP2pIwStats; +#endif +#endif + u_int8_t fgWpsActive; + uint8_t aucWSCIE[GLUE_INFO_WSCIE_LENGTH]; /*for probe req */ + uint16_t u2WSCIELen; + uint8_t aucWSCAssocInfoIE[200]; /*for Assoc req */ + uint16_t u2WSCAssocInfoIELen; + + /* NVRAM availability */ + u_int8_t fgNvramAvailable; + + u_int8_t fgMcrAccessAllowed; + + /* MAC Address Overridden by IOCTL */ + u_int8_t fgIsMacAddrOverride; + uint8_t rMacAddrOverride[PARAM_MAC_ADDR_LEN]; + + struct SET_TXPWR_CTRL rTxPwr; + + /* for cfg80211 scan done indication */ + struct cfg80211_scan_request *prScanRequest; + + /* for cfg80211 scheduled scan */ + struct cfg80211_sched_scan_request *prSchedScanRequest; + + /* to indicate registered or not */ + u_int8_t fgIsRegistered; + + /* for cfg80211 connected indication */ + uint32_t u4RspIeLength; + uint8_t aucRspIe[CFG_CFG80211_IE_BUF_LEN]; + + uint32_t u4ReqIeLength; + uint8_t aucReqIe[CFG_CFG80211_IE_BUF_LEN]; + + /* + * Buffer to hold non-wfa vendor specific IEs set + * from wpa_supplicant. This is used in sending + * Association Request in AIS mode. + */ + uint16_t non_wfa_vendor_ie_len; + uint8_t non_wfa_vendor_ie_buf[NON_WFA_VENDOR_IE_MAX_LEN]; + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN + u_int8_t fgEnSdioTestPattern; + u_int8_t fgSdioReadWriteMode; + u_int8_t fgIsSdioTestInitialized; + uint8_t aucSdioTestBuffer[256]; +#endif + + u_int8_t fgIsInSuspendMode; + +#if CFG_SUPPORT_PASSPOINT + uint8_t aucHS20AssocInfoIE[200]; /*for Assoc req */ + uint16_t u2HS20AssocInfoIELen; + uint8_t ucHotspotConfig; + u_int8_t fgConnectHS20AP; + + u_int8_t fgIsDad; + uint8_t aucDADipv4[4]; + u_int8_t fgIs6Dad; + uint8_t aucDADipv6[16]; +#endif /* CFG_SUPPORT_PASSPOINT */ + + KAL_WAKE_LOCK_T rIntrWakeLock; + KAL_WAKE_LOCK_T rTimeoutWakeLock; + +#if CFG_MET_PACKET_TRACE_SUPPORT + u_int8_t fgMetProfilingEn; + uint16_t u2MetUdpPort; +#endif + +#if CFG_SUPPORT_SNIFFER + u_int8_t fgIsEnableMon; + struct net_device *prMonDevHandler; + struct work_struct monWork; +#endif + + int32_t i4RssiCache; + uint32_t u4LinkSpeedCache; + + + uint32_t u4InfType; + + uint32_t IsrCnt; + uint32_t IsrPassCnt; + uint32_t TaskIsrCnt; + + uint32_t IsrAbnormalCnt; + uint32_t IsrSoftWareCnt; + uint32_t IsrTxCnt; + uint32_t IsrRxCnt; + uint64_t u8HifIntTime; + + /* save partial scan channel information */ + /* PARTIAL_SCAN_INFO rScanChannelInfo; */ + uint8_t *pucScanChannel; + +#if CFG_SUPPORT_SCAN_CACHE_RESULT + struct GL_SCAN_CACHE_INFO scanCache; +#endif /* CFG_SUPPORT_SCAN_CACHE_RESULT */ +#if (CFG_SUPPORT_PERF_IND == 1) + struct GL_PERF_IND_INFO PerfIndCache; +#endif + /* Full2Partial */ + OS_SYSTIME u4LastFullScanTime; + /* full scan or partial scan */ + uint8_t ucTrScanType; + /* UINT_8 aucChannelNum[FULL_SCAN_MAX_CHANNEL_NUM]; */ + /* PARTIAL_SCAN_INFO rFullScanApChannel; */ + uint8_t *pucFullScan2PartialChannel; + + uint32_t u4RoamFailCnt; + uint64_t u8RoamFailTime; + u_int8_t fgTxDoneDelayIsARP; + uint32_t u4ArriveDrvTick; + uint32_t u4EnQueTick; + uint32_t u4DeQueTick; + uint32_t u4LeaveDrvTick; + uint32_t u4CurrTick; + uint64_t u8CurrTime; + + /* FW Roaming */ + /* store the FW roaming enable state which FWK determines */ + /* if it's = 0, ignore the black/whitelists settings from FWK */ + uint32_t u4FWRoamingEnable; + + /* 11R */ + struct FT_IES rFtIeForTx; + struct cfg80211_ft_event_params rFtEventParam; + +#if IS_ENABLED(CFG_RX_NAPI_SUPPORT) + struct napi_struct rNapi; + uint8_t ucRxNapiEnable; + struct sk_buff_head rRxNapiSkbQ; +#endif +}; + +typedef irqreturn_t(*PFN_WLANISR) (int irq, void *dev_id, + struct pt_regs *regs); + +typedef void (*PFN_LINUX_TIMER_FUNC) (unsigned long); + +/* generic sub module init/exit handler + * now, we only have one sub module, p2p + */ +#if CFG_ENABLE_WIFI_DIRECT +typedef u_int8_t(*SUB_MODULE_INIT) (struct GLUE_INFO + *prGlueInfo); +typedef u_int8_t(*SUB_MODULE_EXIT) (struct GLUE_INFO + *prGlueInfo); + +struct SUB_MODULE_HANDLER { + SUB_MODULE_INIT subModInit; + SUB_MODULE_EXIT subModExit; + u_int8_t fgIsInited; +}; + +#endif + +#ifdef CONFIG_NL80211_TESTMODE + +enum TestModeCmdType { + TESTMODE_CMD_ID_SW_CMD = 1, + TESTMODE_CMD_ID_WAPI = 2, + TESTMODE_CMD_ID_HS20 = 3, + + /* Hotspot managerment testmode command */ + TESTMODE_CMD_ID_HS_CONFIG = 51, + + TESTMODE_CMD_ID_STR_CMD = 102, + NUM_OF_TESTMODE_CMD_ID +}; + +#if CFG_SUPPORT_PASSPOINT +enum Hs20CmdType { + HS20_CMD_ID_SET_BSSID_POOL = 0, + NUM_OF_HS20_CMD_ID +}; +#endif /* CFG_SUPPORT_PASSPOINT */ + +struct NL80211_DRIVER_TEST_MODE_PARAMS { + uint32_t index; + uint32_t buflen; +}; + +/*SW CMD */ +struct NL80211_DRIVER_SW_CMD_PARAMS { + struct NL80211_DRIVER_TEST_MODE_PARAMS hdr; + uint8_t set; + uint32_t adr; + uint32_t data; +}; + +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 */ + /*!< ff:ff:ff:ff:ff:ff for broadcast/multicast + * (group) keys or unicast address for + * individual keys + */ + __u8 addr[MAC_ADDR_LEN]; + __u16 alg; /*!< IW_ENCODE_ALG_* */ + __u16 key_len; + __u8 key[32]; +}; + +/*SET KEY EXT */ +struct NL80211_DRIVER_SET_KEY_EXTS { + struct NL80211_DRIVER_TEST_MODE_PARAMS hdr; + uint8_t key_index; + uint8_t key_len; + struct iw_encode_exts ext; +}; + +#if CFG_SUPPORT_PASSPOINT + +struct param_hs20_set_bssid_pool { + uint8_t fgBssidPoolIsEnable; + uint8_t ucNumBssidPool; + uint8_t arBssidPool[8][ETH_ALEN]; +}; + +struct wpa_driver_hs20_data_s { + struct NL80211_DRIVER_TEST_MODE_PARAMS hdr; + enum Hs20CmdType CmdType; + struct param_hs20_set_bssid_pool hs20_set_bssid_pool; +}; + +#endif /* CFG_SUPPORT_PASSPOINT */ + +#endif + +struct NETDEV_PRIVATE_GLUE_INFO { + struct GLUE_INFO *prGlueInfo; + uint8_t ucBssIdx; +#if CFG_ENABLE_UNIFY_WIPHY + u_int8_t ucIsP2p; +#endif +}; + +struct PACKET_PRIVATE_DATA { + /* tx/rx both use cb */ + struct QUE_ENTRY rQueEntry; /* 16byte total:16 */ + + uint8_t ucBssIdx; /* 1byte */ + /* only rx use cb */ + u_int8_t fgIsIndependentPkt; /* 1byte */ + /* only tx use cb */ + uint8_t ucTid; /* 1byte */ + uint8_t ucHeaderLen; /* 1byte */ + uint8_t ucProfilingFlag; /* 1byte */ + uint8_t ucSeqNo; /* 1byte */ + uint16_t u2Flag; /* 2byte total:24 */ + + uint16_t u2IpId; /* 2byte */ + uint16_t u2FrameLen; /* 2byte */ + OS_SYSTIME rArrivalTime;/* 4byte total:32 */ + + uint64_t u8ArriveTime; /* 8byte total:40 */ +}; + +struct PACKET_PRIVATE_RX_DATA { + uint64_t u8IntTime; /* 8byte */ + uint64_t u8RxTime; /* 8byte */ +}; + +/******************************************************************************* + * P U B 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() unsigned long __ulFlags = 0 +#define GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, rLockCategory) \ + { \ + if (rLockCategory < SPIN_LOCK_NUM) \ + spin_lock_irqsave(\ + &(prGlueInfo)->rSpinLock[rLockCategory], __ulFlags); \ + } +#define GLUE_RELEASE_SPIN_LOCK(prGlueInfo, rLockCategory) \ + { \ + if (rLockCategory < SPIN_LOCK_NUM) \ + spin_unlock_irqrestore(\ + &(prGlueInfo->rSpinLock[rLockCategory]), __ulFlags); \ + } +#endif /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + +/*----------------------------------------------------------------------------*/ +/* Macros for accessing Reserved Fields of native packet */ +/*----------------------------------------------------------------------------*/ + +#define GLUE_GET_PKT_PRIVATE_DATA(_p) \ + ((struct PACKET_PRIVATE_DATA *)(&(((struct sk_buff *)(_p))->cb[0]))) + +#define GLUE_GET_PKT_QUEUE_ENTRY(_p) \ + (&(GLUE_GET_PKT_PRIVATE_DATA(_p)->rQueEntry)) + +#define GLUE_GET_PKT_DESCRIPTOR(_prQueueEntry) \ + ((void *) (((unsigned long)_prQueueEntry) \ + - offsetof(struct sk_buff, cb[0]))) + +#define GLUE_SET_PKT_TID(_p, _tid) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucTid = (uint8_t)(_tid)) + +#define GLUE_GET_PKT_TID(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucTid) + +#define GLUE_SET_PKT_FLAG(_p, _flag) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2Flag |= BIT(_flag)) + +#define GLUE_TEST_PKT_FLAG(_p, _flag) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2Flag & BIT(_flag)) + +#define GLUE_IS_PKT_FLAG_SET(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2Flag) + +#define GLUE_SET_PKT_BSS_IDX(_p, _ucBssIndex) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucBssIdx = (uint8_t)(_ucBssIndex)) + +#define GLUE_GET_PKT_BSS_IDX(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucBssIdx) + +#define GLUE_SET_PKT_HEADER_LEN(_p, _ucMacHeaderLen) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucHeaderLen = \ + (uint8_t)(_ucMacHeaderLen)) + +#define GLUE_GET_PKT_HEADER_LEN(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucHeaderLen) + +#define GLUE_SET_PKT_FRAME_LEN(_p, _u2PayloadLen) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2FrameLen = (uint16_t)(_u2PayloadLen)) + +#define GLUE_GET_PKT_FRAME_LEN(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2FrameLen) + +#define GLUE_SET_PKT_ARRIVAL_TIME(_p, _rSysTime) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->rArrivalTime = (OS_SYSTIME)(_rSysTime)) + +#define GLUE_GET_PKT_ARRIVAL_TIME(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->rArrivalTime) + +#define GLUE_SET_PKT_IP_ID(_p, _u2IpId) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2IpId = (uint16_t)(_u2IpId)) + +#define GLUE_GET_PKT_IP_ID(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2IpId) + +#define GLUE_SET_PKT_SEQ_NO(_p, _ucSeqNo) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucSeqNo = (uint8_t)(_ucSeqNo)) + +#define GLUE_GET_PKT_SEQ_NO(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucSeqNo) + +#define GLUE_SET_PKT_FLAG_PROF_MET(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucProfilingFlag |= BIT(0)) + +#define GLUE_GET_PKT_IS_PROF_MET(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucProfilingFlag & BIT(0)) + +#define GLUE_SET_PKT_XTIME(_p, _rSysTime) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u8ArriveTime = (uint64_t)(_rSysTime)) + +#define GLUE_GET_PKT_XTIME(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u8ArriveTime) + +#define GLUE_GET_PKT_PRIVATE_RX_DATA(_p) \ + ((struct PACKET_PRIVATE_RX_DATA *)(&(((struct sk_buff *)(_p))->cb[24]))) + +#define GLUE_RX_SET_PKT_INT_TIME(_p, _rTime) \ + (GLUE_GET_PKT_PRIVATE_RX_DATA(_p)->u8IntTime = (uint64_t)(_rTime)) + +#define GLUE_RX_GET_PKT_INT_TIME(_p) \ + (GLUE_GET_PKT_PRIVATE_RX_DATA(_p)->u8IntTime) + +#define GLUE_RX_SET_PKT_RX_TIME(_p, _rTime) \ + (GLUE_GET_PKT_PRIVATE_RX_DATA(_p)->u8RxTime = (uint64_t)(_rTime)) + +#define GLUE_RX_GET_PKT_RX_TIME(_p) \ + (GLUE_GET_PKT_PRIVATE_RX_DATA(_p)->u8RxTime) + +#define GLUE_GET_PKT_ETHER_DEST_ADDR(_p) \ + ((uint8_t *)&(((struct sk_buff *)(_p))->data)) + +/* Check validity of prDev, private data, and pointers */ +#define GLUE_CHK_DEV(prDev) \ + ((prDev && *((struct GLUE_INFO **) 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 GLUE_GET_REF_CNT(_refCount) atomic_read((atomic_t *)&(_refCount)) + +#define DbgPrint(...) + +#if CFG_MET_TAG_SUPPORT +#define GL_MET_TAG_START(_id, _name) met_tag_start(_id, _name) +#define GL_MET_TAG_END(_id, _name) met_tag_end(_id, _name) +#define GL_MET_TAG_ONESHOT(_id, _name, _value) \ + met_tag_oneshot(_id, _name, _value) +#define GL_MET_TAG_DISABLE(_id) met_tag_disable(_id) +#define GL_MET_TAG_ENABLE(_id) met_tag_enable(_id) +#define GL_MET_TAG_REC_ON() met_tag_record_on() +#define GL_MET_TAG_REC_OFF() met_tag_record_off() +#define GL_MET_TAG_INIT() met_tag_init() +#define GL_MET_TAG_UNINIT() met_tag_uninit() +#else +#define GL_MET_TAG_START(_id, _name) +#define GL_MET_TAG_END(_id, _name) +#define GL_MET_TAG_ONESHOT(_id, _name, _value) +#define GL_MET_TAG_DISABLE(_id) +#define GL_MET_TAG_ENABLE(_id) +#define GL_MET_TAG_REC_ON() +#define GL_MET_TAG_REC_OFF() +#define GL_MET_TAG_INIT() +#define GL_MET_TAG_UNINIT() +#endif + +#define MET_TAG_ID 0 + +/*----------------------------------------------------------------------------*/ +/* Macros of Data Type Check */ +/*----------------------------------------------------------------------------*/ +/* Kevin: we don't have to call following function to inspect the data + * structure. + * It will check automatically while at compile time. + */ +static __KAL_INLINE__ void glPacketDataTypeCheck(void) +{ + DATA_STRUCT_INSPECTING_ASSERT(sizeof(struct + PACKET_PRIVATE_DATA) <= sizeof(((struct sk_buff *) 0)->cb)); +} + +static inline u16 mtk_wlan_ndev_select_queue( + struct sk_buff *skb) +{ + static u16 ieee8021d_to_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; + + /* cfg80211_classify8021d returns 0~7 */ +#if KERNEL_VERSION(3, 14, 0) > CFG80211_VERSION_CODE + skb->priority = cfg80211_classify8021d(skb); +#else + skb->priority = cfg80211_classify8021d(skb, NULL); +#endif + return ieee8021d_to_queue[skb->priority]; +} + +#if KERNEL_VERSION(2, 6, 34) > LINUX_VERSION_CODE +#define netdev_for_each_mc_addr(mclist, dev) \ + for (mclist = dev->mc_list; mclist; mclist = mclist->next) +#endif + +#if KERNEL_VERSION(2, 6, 34) > LINUX_VERSION_CODE +#define GET_ADDR(ha) (ha->da_addr) +#else +#define GET_ADDR(ha) (ha->addr) +#endif + +#if KERNEL_VERSION(2, 6, 35) <= LINUX_VERSION_CODE +#define LIST_FOR_EACH_IPV6_ADDR(_prIfa, _ip6_ptr) \ + list_for_each_entry(_prIfa, &((struct inet6_dev *) \ + _ip6_ptr)->addr_list, if_list) +#else +#define LIST_FOR_EACH_IPV6_ADDR(_prIfa, _ip6_ptr) \ + for (_prIfa = ((struct inet6_dev *) _ip6_ptr)->addr_list; _prIfa; \ + _prIfa = _prIfa->if_next) +#endif + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +#if WLAN_INCLUDE_PROC +int32_t procCreateFsEntry(struct GLUE_INFO *prGlueInfo); +int32_t procRemoveProcfs(void); + + +int32_t procInitFs(void); +int32_t procUninitProcFs(void); + + + +int32_t procInitProcfs(struct net_device *prDev, + char *pucDevName); +#endif /* WLAN_INCLUDE_PROC */ + +#if CFG_ENABLE_BT_OVER_WIFI +u_int8_t glRegisterAmpc(struct GLUE_INFO *prGlueInfo); + +u_int8_t glUnregisterAmpc(struct GLUE_INFO *prGlueInfo); +#endif + +#if CFG_ENABLE_WIFI_DIRECT +void p2pSetMulticastListWorkQueueWrapper(struct GLUE_INFO + *prGlueInfo); +#endif + +struct GLUE_INFO *wlanGetGlueInfo(void); + +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE +u16 wlanSelectQueue(struct net_device *dev, + struct sk_buff *skb, struct net_device *sb_dev, + select_queue_fallback_t fallback); +#elif KERNEL_VERSION(3, 14, 0) <= LINUX_VERSION_CODE +u16 wlanSelectQueue(struct net_device *dev, + struct sk_buff *skb, + void *accel_priv, select_queue_fallback_t fallback); +#elif KERNEL_VERSION(3, 13, 0) <= LINUX_VERSION_CODE +u16 wlanSelectQueue(struct net_device *dev, + struct sk_buff *skb, + void *accel_priv); +#else +u16 wlanSelectQueue(struct net_device *dev, + struct sk_buff *skb); +#endif + +void wlanDebugInit(void); + +uint32_t wlanSetDriverDbgLevel(IN uint32_t u4DbgIdx, + IN uint32_t u4DbgMask); + +uint32_t wlanGetDriverDbgLevel(IN uint32_t u4DbgIdx, + OUT uint32_t *pu4DbgMask); + +void wlanSetSuspendMode(struct GLUE_INFO *prGlueInfo, + u_int8_t fgEnable); + +void wlanGetConfig(struct ADAPTER *prAdapter); + +uint32_t wlanDownloadBufferBin(struct ADAPTER *prAdapter); + +uint32_t wlanConnacDownloadBufferBin(struct ADAPTER + *prAdapter); + +/******************************************************************************* + * E X T E R N A L F U N C T I O N S / V A R I A B L E + ******************************************************************************* + */ +extern struct net_device *gPrP2pDev[KAL_P2P_NUM]; +extern struct net_device *gPrDev; +extern struct wireless_dev *gprWdev; + +#ifdef CFG_DRIVER_INF_NAME_CHANGE +extern char *gprifnameap; +extern char *gprifnamep2p; +extern char *gprifnamesta; +#endif /* CFG_DRIVER_INF_NAME_CHANGE */ + +extern void wlanRegisterNotifier(void); +extern void wlanUnregisterNotifier(void); +#if CFG_MTK_ANDROID_WMT +typedef int (*set_p2p_mode) (struct net_device *netdev, + struct PARAM_CUSTOM_P2P_SET_STRUCT p2pmode); +extern void register_set_p2p_mode_handler( + set_p2p_mode handler); +#endif + +#if CFG_ENABLE_EARLY_SUSPEND +extern int glRegisterEarlySuspend(struct early_suspend + *prDesc, + early_suspend_callback wlanSuspend, + late_resume_callback wlanResume); + +extern int glUnregisterEarlySuspend(struct early_suspend + *prDesc); +#endif + +#if CFG_MET_PACKET_TRACE_SUPPORT +void kalMetTagPacket(IN struct GLUE_INFO *prGlueInfo, + IN void *prPacket, IN enum ENUM_TX_PROFILING_TAG eTag); + +void kalMetInit(IN struct GLUE_INFO *prGlueInfo); +#endif + +void wlanUpdateChannelTable(struct GLUE_INFO *prGlueInfo); + +#if (CFG_MTK_ANDROID_WMT || WLAN_INCLUDE_PROC) +int set_p2p_mode_handler(struct net_device *netdev, + struct PARAM_CUSTOM_P2P_SET_STRUCT p2pmode); +#endif + +#if CFG_ENABLE_UNIFY_WIPHY +const struct net_device_ops *wlanGetNdevOps(void); +#endif + +#if CFG_MTK_ANDROID_WMT +extern void connectivity_flush_dcache_area(void *addr, size_t len); +extern void connectivity_arch_setup_dma_ops( + struct device *dev, u64 dma_base, + u64 size, struct iommu_ops *iommu, + bool coherent); +#endif + +#if CFG_SUPPORT_CUSTOM_NETLINK +extern void glCustomGenlInit(void); +extern void glCustomGenlDeinit(void); +#endif + +#endif /* _GL_OS_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_p2p_ioctl.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_p2p_ioctl.h new file mode 100644 index 0000000000000..3aa580e52b5c0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_p2p_ioctl.h @@ -0,0 +1,877 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 + */ + + +#ifndef _GL_P2P_IOCTL_H +#define _GL_P2P_IOCTL_H + +/****************************************************************************** + * C O M P I L E R F L A G S + ****************************************************************************** + */ + +/****************************************************************************** + * E X T E R N A L R E F E R E N C E S + ****************************************************************************** + */ +#include +#include +#include +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#include +#include +#endif + +#include "wlan_oid.h" + +/****************************************************************************** + * C O N S T A N T S + ****************************************************************************** + */ + +/* (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 + +#define CHN_DIRTY_WEIGHT_UPPERBOUND 4 + +/****************************************************************************** + * D A T A T Y P E S + ****************************************************************************** + */ +/*------------------------------------------------------------------------*/ +/* Wireless Extension: Private I/O Control */ +/*------------------------------------------------------------------------*/ +struct iw_p2p_cfg_device_type { + void __user *ssid; + uint8_t ssid_len; + uint8_t pri_device_type[8]; + uint8_t snd_device_type[8]; + void __user *device_name; + uint8_t device_name_len; + uint8_t intend; + uint8_t persistence; + uint8_t sec_mode; + uint8_t ch; + uint8_t ch_width; /* 0: 20 Mhz 1:20/40 Mhz auto */ + uint8_t max_scb; +}; + +struct iw_p2p_hostapd_param { + uint8_t cmd; + uint8_t rsv[3]; + uint8_t sta_addr[6]; + void __user *data; + uint16_t len; +}; + +struct iw_p2p_req_device_type { + uint8_t scan_type; /* 0: Full scan + Find + * 1: Full scan + * 2: Scan (Search +Listen) + * 3: Listen + * other : reserved + */ + uint8_t pri_device_type[8]; + void __user *probe_req_ie; + uint16_t probe_req_len; + void __user *probe_rsp_ie; + uint16_t probe_rsp_len; +}; + +struct iw_p2p_connect_device { + uint8_t sta_addr[6]; + /* 0: P2P Device, 1:GC, 2: GO */ + uint8_t p2pRole; + /* 0: Don't needed provision, 1: doing the wsc provision first */ + uint8_t needProvision; + /* 1: auth peer invitation request */ + uint8_t authPeer; + /* Request Peer Device used config method */ + uint8_t intend_config_method; +}; + +struct iw_p2p_password_ready { + uint8_t active_config_method; + void __user *probe_req_ie; + uint16_t probe_req_len; + void __user *probe_rsp_ie; + uint16_t probe_rsp_len; +}; + +struct iw_p2p_device_req { + uint8_t name[33]; + uint32_t name_len; + uint8_t device_addr[6]; + uint8_t device_type; + int32_t config_method; + int32_t active_config_method; +}; + +struct iw_p2p_transport_struct { + uint32_t u4CmdId; + uint32_t inBufferLength; + uint32_t outBufferLength; + uint8_t aucBuffer[16]; +}; + +/* For Invitation */ +struct iw_p2p_ioctl_invitation_struct { + uint8_t aucDeviceID[6]; + /* BSSID */ + uint8_t aucGroupID[6]; + uint8_t aucSsid[32]; + uint32_t u4SsidLen; + uint8_t ucReinvoke; +}; + +struct iw_p2p_ioctl_abort_invitation { + uint8_t dev_addr[6]; +}; + +struct iw_p2p_ioctl_invitation_indicate { + uint8_t dev_addr[6]; + uint8_t group_bssid[6]; + /* peer device supported config method */ + int32_t config_method; + /* for reinvoke */ + uint8_t dev_name[32]; + uint32_t name_len; + /* for re-invoke, target operating channel */ + uint8_t operating_channel; + /* invitation or re-invoke */ + uint8_t invitation_type; +}; + +struct iw_p2p_ioctl_invitation_status { + uint32_t status_code; +}; + +/* For Formation */ +struct iw_p2p_ioctl_start_formation { + /* bssid */ + uint8_t dev_addr[6]; + /* 0: P2P Device, 1:GC, 2: GO */ + uint8_t role; + /* 0: Don't needed provision, 1: doing the wsc provision first */ + uint8_t needProvision; + /* 1: auth peer invitation request */ + uint8_t auth; + /* Request Peer Device used config method */ + + uint8_t config_method; +}; + +/* SET_STRUCT / GET_STRUCT */ +enum ENUM_P2P_CMD_ID { + 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) */ +}; + +/* Service Discovery */ +struct iw_p2p_cmd_send_sd_response { + uint8_t rReceiverAddr[PARAM_MAC_ADDR_LEN]; + uint8_t fgNeedTxDoneIndication; + uint8_t ucSeqNum; + uint16_t u2PacketLength; + uint8_t aucPacketContent[0]; /*native 802.11 */ +}; + +struct iw_p2p_cmd_get_sd_request { + uint8_t rTransmitterAddr[PARAM_MAC_ADDR_LEN]; + uint16_t u2PacketLength; + uint8_t aucPacketContent[0]; /*native 802.11 */ +}; + +struct iw_p2p_cmd_send_service_discovery_request { + uint8_t rReceiverAddr[PARAM_MAC_ADDR_LEN]; + uint8_t fgNeedTxDoneIndication; + uint8_t ucSeqNum; + uint16_t u2PacketLength; + uint8_t aucPacketContent[0]; /*native 802.11 */ +}; + +struct iw_p2p_cmd_get_sd_response { + uint8_t rTransmitterAddr[PARAM_MAC_ADDR_LEN]; + uint16_t u2PacketLength; + uint8_t aucPacketContent[0]; /*native 802.11 */ +}; + +struct iw_p2p_cmd_terminate_sd_phase { + uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN]; +}; + +struct iw_p2p_version { + uint32_t u4Version; +}; + +/*----------------------------------------------------------------------------*/ +/* NL80211 TEST MODE */ +/*----------------------------------------------------------------------------*/ +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +enum ENUM_TESTMODE_AVAILABLE_CHAN_ATTR { + __NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_INVALID, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_2G_BASE_1, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_36, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_52, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_100, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_149, + __NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_AFTER_LAST, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_MAX + = __NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_AFTER_LAST - 1 +}; +#endif + + +/****************************************************************************** + * P U B L I C D A T A + ****************************************************************************** + */ +extern struct ieee80211_supported_band mtk_band_2ghz; +extern struct ieee80211_supported_band mtk_band_5ghz; + +extern const uint32_t mtk_cipher_suites[6]; + + +/****************************************************************************** + * 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 = KAL_BAND_2GHZ, \ + .center_freq = (_freq), \ + .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 (CFG_ENABLE_WIFI_DIRECT_CFG_80211 != 0) + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +struct wireless_dev *mtk_p2p_cfg80211_add_iface(struct wiphy *wiphy, + const char *name, unsigned char name_assign_type, + enum nl80211_iftype type, struct vif_params *params); +#elif KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE +struct wireless_dev *mtk_p2p_cfg80211_add_iface(struct wiphy *wiphy, + const char *name, + unsigned char name_assign_type, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params); +#else +struct wireless_dev *mtk_p2p_cfg80211_add_iface(struct wiphy *wiphy, + const char *name, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params); +#endif + +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_del_iface(struct wiphy *wiphy, + struct wireless_dev *wdev); + +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_set_mgmt_key(struct wiphy *wiphy, + struct net_device *dev, + u8 key_index); + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *ndev, + const u8 *mac, + struct station_info *sinfo); +#else +int mtk_p2p_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, + struct station_info *sinfo); +#endif +int mtk_p2p_cfg80211_scan(struct wiphy *wiphy, + struct cfg80211_scan_request *request); + +void mtk_p2p_cfg80211_abort_scan(struct wiphy *wiphy, + struct wireless_dev *wdev); + +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, + struct wireless_dev *wdev, + enum nl80211_tx_power_setting type, + int mbm); + +int mtk_p2p_cfg80211_get_txpower(struct wiphy *wiphy, + struct wireless_dev *wdev, + int *dbm); + +int mtk_p2p_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, + unsigned int duration, + u64 *cookie); + +int mtk_p2p_cfg80211_cancel_remain_on_channel( + struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie); + +int mtk_p2p_cfg80211_set_power_mgmt(struct wiphy *wiphy, + struct net_device *dev, + bool enabled, + int timeout); + +#if (CFG_SUPPORT_DFS_MASTER == 1) + +#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_start_radar_detection(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef, + unsigned int cac_time_ms); +#else +int mtk_p2p_cfg80211_start_radar_detection(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef); +#endif + + +#if KERNEL_VERSION(3, 13, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_channel_switch(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_csa_settings *params); +#endif +#endif + +int mtk_p2p_cfg80211_change_bss(struct wiphy *wiphy, + struct net_device *dev, + struct bss_parameters *params); + +int mtk_p2p_cfg80211_deauth(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_deauth_request *req); + +int mtk_p2p_cfg80211_disassoc(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_disassoc_request *req); + +int mtk_p2p_cfg80211_start_ap(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ap_settings *settings); + +int mtk_p2p_cfg80211_change_beacon(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_beacon_data *info); + +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie); +#else +int mtk_p2p_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, + bool offchan, + unsigned int wait, + const u8 *buf, + size_t len, + bool no_cck, + bool dont_wait_for_ack, + u64 *cookie); +#endif + +#if KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, + struct station_del_parameters *params); +#elif KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, + const u8 *mac); +#else +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, + u8 *mac); +#endif + +int mtk_p2p_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie); + +int mtk_p2p_cfg80211_stop_ap(struct wiphy *wiphy, + struct net_device *dev); + +int mtk_p2p_cfg80211_set_channel(struct wiphy *wiphy, + struct cfg80211_chan_def *chandef); + +void mtk_p2p_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, + struct wireless_dev *wdev, + IN u16 frame_type, + IN bool reg); + +int +mtk_p2p_cfg80211_set_bitrate_mask(IN struct wiphy *wiphy, + IN struct net_device *dev, + IN const u8 *peer, + IN const struct cfg80211_bitrate_mask *mask); + +#ifdef CONFIG_NL80211_TESTMODE +#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_testmode_cmd(struct wiphy *wiphy, + struct wireless_dev *wdev, + void *data, + int len); +#else +int mtk_p2p_cfg80211_testmode_cmd(struct wiphy *wiphy, + void *data, + int len); +#endif +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); + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +int mtk_p2p_cfg80211_testmode_get_best_channel(IN struct wiphy *wiphy, + IN void *data, + IN int len); +#endif + +int mtk_p2p_cfg80211_testmode_hotspot_config_cmd(IN struct wiphy *wiphy, + IN void *data, + IN int len); + +#else +/* IGNORE KERNEL DEPENCY ERRORS*/ +/*#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 struct GLUE_INFO *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); + +#endif /* _GL_P2P_IOCTL_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_p2p_kal.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_p2p_kal.h new file mode 100644 index 0000000000000..ab9600280c31c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_p2p_kal.h @@ -0,0 +1,376 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + + +#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 + +u_int8_t kalP2pFuncGetChannelType(IN enum ENUM_CHNL_EXT rChnlSco, + OUT enum nl80211_channel_type *channel_type); + +/****************************************************************************** + * 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 struct GLUE_INFO *prGlueInfo, + IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN], + IN uint8_t ucSeqNum); + +void kalP2PIndicateSDResponse(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN], + IN uint8_t ucSeqNum); + +void kalP2PIndicateTXDone(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucSeqNum, IN uint8_t 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 struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucFrameBody, + IN uint32_t u4FrameBodyLen, + IN u_int8_t fgReassocRequest, + IN uint8_t ucBssIndex); + +/*UINT_32 kalP2PGetFreqInKHz(IN P_GLUE_INFO_T prGlueInfo);*/ + +int32_t mtk_Netdev_To_RoleIdx(struct GLUE_INFO *prGlueInfo, + struct net_device *ndev, + uint8_t *pucRoleIdx); + +uint8_t kalP2PGetRole(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIdx); + +#if 1 +void kalP2PSetRole(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRole, + IN uint8_t ucRoleIdx); + +#else +void +kalP2PSetRole(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucResult, + IN uint8_t *pucSSID, + IN uint8_t ucSSIDLen, + IN uint8_t ucRole); +#endif + +void kalP2PSetCipher(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Cipher, + IN uint8_t ucRoleIdx); + +u_int8_t kalP2PGetCipher(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIdx); + +u_int8_t kalP2PGetWepCipher(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIdx); + +u_int8_t kalP2PGetTkipCipher(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIdx); + +u_int8_t kalP2PGetCcmpCipher(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIdx); + +#if CFG_SUPPORT_SUITB +u_int8_t kalP2PGetGcmp256Cipher(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIdx); +#endif + +void kalP2PSetWscMode(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucWscMode); + +uint8_t kalP2PGetWscMode(IN struct GLUE_INFO *prGlueInfo); + +uint16_t kalP2PCalWSC_IELen(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucType, + IN uint8_t ucRoleIdx); + +void kalP2PGenWSC_IE(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucType, + IN uint8_t *pucBuffer, + IN uint8_t ucRoleIdx); + +void kalP2PUpdateWSC_IE(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucType, + IN uint8_t *pucBuffer, + IN uint16_t u2BufferLength, + IN uint8_t ucRoleIdx); + +uint16_t kalP2PCalP2P_IELen(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucIndex, + IN uint8_t ucRoleIdx); + +void kalP2PGenP2P_IE(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucIndex, + IN uint8_t *pucBuffer, + IN uint8_t ucRoleIdx); + +void kalP2PUpdateP2P_IE(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucIndex, + IN uint8_t *pucBuffer, + IN uint16_t u2BufferLength, + IN uint8_t ucRoleIdx); + +u_int8_t kalP2PIndicateFound(IN struct GLUE_INFO *prGlueInfo); + +void kalP2PIndicateConnReq(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucDevName, + IN int32_t u4NameLength, + IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN], + IN uint8_t ucDevType, /* 0: P2P Device / 1: GC / 2: GO */ + IN int32_t i4ConfigMethod, + IN int32_t i4ActiveConfigMethod); + +/*VOID kalP2PInvitationStatus(IN P_GLUE_INFO_T prGlueInfo, + * IN UINT_32 u4InvStatus); + */ + +void +kalP2PInvitationIndication(IN struct GLUE_INFO *prGlueInfo, + IN struct P2P_DEVICE_DESC *prP2pDevDesc, + IN uint8_t *pucSsid, + IN uint8_t ucSsidLen, + IN uint8_t ucOperatingChnl, + IN uint8_t ucInvitationType, + IN uint8_t *pucGroupBssid); + +struct net_device *kalP2PGetDevHdlr(struct GLUE_INFO *prGlueInfo); + +void +kalGetChnlList(IN struct GLUE_INFO *prGlueInfo, + IN enum ENUM_BAND eSpecificBand, + IN uint8_t ucMaxChannelNum, + IN uint8_t *pucNumOfChannel, + IN struct RF_CHANNEL_INFO *paucChannelList); + +#if CFG_SUPPORT_ANTI_PIRACY +void kalP2PIndicateSecCheckRsp(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucRsp, + IN uint16_t u2RspLen); +#endif + +/****************************************************************************** + * F U N C T I O N S + ****************************************************************************** + */ + +void +kalP2PIndicateChannelReady(IN struct GLUE_INFO *prGlueInfo, + IN uint64_t u8SeqNum, + IN uint32_t u4ChannelNum, + IN enum ENUM_BAND eBand, + IN enum ENUM_CHNL_EXT eSco, + IN uint32_t u4Duration); + +void kalP2PIndicateScanDone(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex, + IN u_int8_t fgIsAbort); + +void +kalP2PIndicateBssInfo(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucFrameBuf, + IN uint32_t u4BufLen, + IN struct RF_CHANNEL_INFO *prChannelInfo, + IN int32_t i4SignalStrength); + +void +kalP2PIndicateRxMgmtFrame(IN struct GLUE_INFO *prGlueInfo, + IN struct SW_RFB *prSwRfb, + IN u_int8_t fgIsDevInterface, + IN uint8_t ucRoleIdx); + +void kalP2PIndicateMgmtTxStatus(IN struct GLUE_INFO *prGlueInfo, + IN struct MSDU_INFO *prMsduInfo, + IN u_int8_t fgIsAck); + +void +kalP2PIndicateChannelExpired(IN struct GLUE_INFO *prGlueInfo, + IN uint64_t u8SeqNum, + IN uint32_t u4ChannelNum, + IN enum ENUM_BAND eBand, + IN enum ENUM_CHNL_EXT eSco); + +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) +void +kalP2PGCIndicateConnectionStatus(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex, + IN struct P2P_CONNECTION_REQ_INFO *prP2pConnInfo, + IN uint8_t *pucRxIEBuf, + IN uint16_t u2RxIELen, + IN uint16_t u2StatusReason, + IN uint32_t eStatus); +#else +void +kalP2PGCIndicateConnectionStatus(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex, + IN struct P2P_CONNECTION_REQ_INFO *prP2pConnInfo, + IN uint8_t *pucRxIEBuf, + IN uint16_t u2RxIELen, + IN uint16_t u2StatusReason); + +#endif +void +kalP2PGOStationUpdate(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex, + IN struct STA_RECORD *prCliStaRec, + IN u_int8_t fgIsNew); + +#if (CFG_SUPPORT_DFS_MASTER == 1) +void +kalP2PRddDetectUpdate(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex); + +void +kalP2PCacFinishedUpdate(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucRoleIndex); +#endif + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + +u_int8_t kalP2PSetBlackList(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t rbssid[PARAM_MAC_ADDR_LEN], + IN u_int8_t fgIsblock, + IN uint8_t ucRoleIndex); + +u_int8_t kalP2PCmpBlackList(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t rbssid[PARAM_MAC_ADDR_LEN], + IN uint8_t ucRoleIndex); + +void kalP2PSetMaxClients(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4MaxClient, + IN uint8_t ucRoleIndex); + +u_int8_t kalP2PMaxClients(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4NumClient, + IN uint8_t ucRoleIndex); + +#endif + +void kalP2pUnlinkBss(IN struct GLUE_INFO *prGlueInfo, IN uint8_t aucBSSID[]); + +void kalP2pIndicateQueuedMgmtFrame(IN struct GLUE_INFO *prGlueInfo, + IN struct P2P_QUEUED_ACTION_FRAME *prFrame); + +#endif /* _GL_P2P_KAL_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_p2p_os.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_p2p_os.h new file mode 100644 index 0000000000000..fdfb639754b60 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_p2p_os.h @@ -0,0 +1,371 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 + +#define VENDOR_SPECIFIC_IE_LENGTH 400 +/****************************************************************************** + * C O M P I L E R F L A G S + ****************************************************************************** + */ + +/****************************************************************************** + * E X T E R N A L R E F E R E N C E S + ****************************************************************************** + */ + +/****************************************************************************** + * E X T E R N A L V A R I A B L E + ****************************************************************************** + */ +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_WIFI_DIRECT_CFG_80211 +extern const struct net_device_ops p2p_netdev_ops; +#endif + +/****************************************************************************** + * C O N S T A N T S + ****************************************************************************** + */ + +/****************************************************************************** + * M A C R O S + ****************************************************************************** + */ + +/* For SET_STRUCT/GET_STRUCT */ +#define OID_SET_GET_STRUCT_LENGTH 4096 + +#define MAX_P2P_IE_SIZE 5 + +#define P2P_MAXIMUM_CLIENT_COUNT 10 + +/****************************************************************************** + * D A T A T Y P E S + ****************************************************************************** + */ + +/****************************************************************************** + * P U B L I C D A T A + ****************************************************************************** + */ + +extern struct net_device *g_P2pPrDev; +extern struct wireless_dev *gprP2pWdev; +extern struct wireless_dev *gprP2pRoleWdev[KAL_P2P_NUM]; + +/****************************************************************************** + * 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 { + + /* P2P Device interface handle */ + /*only first p2p have this devhandler*/ + struct net_device *prDevHandler; + /*struct net_device *prRoleDevHandler;*//* TH3 multiple P2P */ + + struct net_device *aprRoleHandler; + + /* Todo : should move to the glueinfo or not*/ + /*UINT_8 ucRoleInterfaceNum;*//* TH3 multiple P2P */ + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + /* cfg80211 */ + struct wireless_dev *prWdev; + /*struct wireless_dev *prRoleWdev[KAL_P2P_NUM];*//* TH3 multiple P2P */ + + /*struct cfg80211_scan_request *prScanRequest;*//* TH3 multiple P2P */ + + /*UINT_64 u8Cookie;*//* TH3 multiple P2P */ + + /* Generation for station list update. */ + int32_t i4Generation; + + /*UINT_32 u4OsMgmtFrameFilter;*//* TH3 multiple P2P */ + +#endif + + /* Device statistics */ + /*struct net_device_stats rNetDevStats;*//* TH3 multiple P2P */ + + /* glue layer variables */ + /*move to glueinfo->adapter */ + /* BOOLEAN fgIsRegistered; */ + /*UINT_32 u4FreqInKHz;*//* TH3 multiple P2P */ /* frequency */ + /* 0: P2P Device, 1: Group Client, 2: Group Owner */ + uint8_t ucRole; + /*UINT_8 ucIntent;*//* TH3 multiple P2P */ /* range: 0-15 */ + /* 0: Search & Listen, 1: Scan without probe response */ + /*UINT_8 ucScanMode;*//* TH3 multiple P2P */ + + /*ENUM_PARAM_MEDIA_STATE_T eState;*//* TH3 multiple P2P */ + /*UINT_32 u4PacketFilter;*//* TH3 multiple P2P */ + /* TH3 multiple P2P */ + /*PARAM_MAC_ADDRESS aucMCAddrList[MAX_NUM_GROUP_ADDR];*/ + + /* connection-requested peer information *//* TH3 multiple P2P */ + /*UINT_8 aucConnReqDevName[32];*//* TH3 multiple P2P */ + /*INT_32 u4ConnReqNameLength;*//* TH3 multiple P2P */ + /*PARAM_MAC_ADDRESS rConnReqPeerAddr;*//* TH3 multiple P2P */ + /* For invitation group. */ + /*PARAM_MAC_ADDRESS rConnReqGroupAddr;*//* TH3 multiple P2P */ + /*UINT_8 ucConnReqDevType;*//* TH3 multiple P2P */ + /*INT_32 i4ConnReqConfigMethod;*//* TH3 multiple P2P */ + /*INT_32 i4ConnReqActiveConfigMethod;*//* TH3 multiple P2P */ + + uint32_t u4CipherPairwise; + /*UINT_8 ucWSCRunning;*//* TH3 multiple P2P */ + + /* 0: beacon, 1: probe req, 2:probe response, 3: assoc response */ + uint8_t aucWSCIE[4][VENDOR_SPECIFIC_IE_LENGTH]; + uint16_t u2WSCIELen[4]; + + uint8_t aucP2PIE[MAX_P2P_IE_SIZE][VENDOR_SPECIFIC_IE_LENGTH]; + uint16_t u2P2PIELen[MAX_P2P_IE_SIZE]; + +#if CFG_SUPPORT_WFD + /* 0 for beacon, 1 for probe req, 2 for probe response */ + uint8_t aucWFDIE[VENDOR_SPECIFIC_IE_LENGTH]; + uint16_t u2WFDIELen; + /* Save the other IE for prove resp */ + /* UINT_8 aucVenderIE[1024]; */ +/* UINT_16 u2VenderIELen; */ +#endif + + /*UINT_8 ucOperatingChnl;*//* TH3 multiple P2P */ + /*UINT_8 ucInvitationType;*//* TH3 multiple P2P */ + + /*UINT_32 u4InvStatus;*//* TH3 multiple P2P */ + + /* For SET_STRUCT/GET_STRUCT */ + /*UINT_8 aucOidBuf[OID_SET_GET_STRUCT_LENGTH];*//* TH3 multiple P2P */ + +#if 1 /* CFG_SUPPORT_ANTI_PIRACY */ + /*UINT_8 aucSecCheck[256];*//* TH3 multiple P2P */ + /*UINT_8 aucSecCheckRsp[256];*//* TH3 multiple P2P */ +#endif + +#if (CFG_SUPPORT_DFS_MASTER == 1) + struct cfg80211_chan_def *chandef; + uint32_t cac_time_ms; +#endif + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + uint8_t aucblackMACList[P2P_MAXIMUM_CLIENT_COUNT][PARAM_MAC_ADDR_LEN]; + uint8_t ucMaxClients; +#endif + +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION + /*BOOLEAN fgEnableHotspotOptimization;*//* TH3 multiple P2P */ + /*UINT_32 u4PsLevel;*//* TH3 multiple P2P */ +#endif +}; + +struct GL_P2P_DEV_INFO { +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + struct cfg80211_scan_request *prScanRequest; +#if 0 + struct cfg80211_scan_request rBackupScanRequest; +#endif + uint64_t u8Cookie; + uint32_t u4OsMgmtFrameFilter; +#endif + uint32_t u4PacketFilter; + uint8_t aucMCAddrList[MAX_NUM_GROUP_ADDR][PARAM_MAC_ADDR_LEN]; + uint8_t ucWSCRunning; +}; + +#ifdef CONFIG_NL80211_TESTMODE +struct NL80211_DRIVER_TEST_PRE_PARAMS { + uint16_t idx_mode; + uint16_t idx; + uint32_t value; +}; + +struct NL80211_DRIVER_TEST_PARAMS { + uint32_t index; + uint32_t buflen; +}; + +/* P2P Sigma*/ +struct NL80211_DRIVER_P2P_SIGMA_PARAMS { + struct NL80211_DRIVER_TEST_PARAMS hdr; + uint32_t idx; + uint32_t value; +}; + +/* Hotspot Client Management */ +struct NL80211_DRIVER_hotspot_block_PARAMS { + struct NL80211_DRIVER_TEST_PARAMS hdr; + uint8_t ucblocked; + uint8_t aucBssid[MAC_ADDR_LEN]; +}; + +/* Hotspot Management set config */ +struct NL80211_DRIVER_HOTSPOT_CONFIG_PARAMS { + struct NL80211_DRIVER_TEST_PARAMS hdr; + uint32_t idx; + uint32_t value; +}; + +#if CFG_SUPPORT_WFD +struct NL80211_DRIVER_WFD_PARAMS { + struct NL80211_DRIVER_TEST_PARAMS hdr; + uint32_t WfdCmdType; + uint8_t WfdEnable; + uint8_t WfdCoupleSinkStatus; + uint8_t WfdSessionAvailable; + uint8_t WfdSigmaMode; + uint16_t WfdDevInfo; + uint16_t WfdControlPort; + uint16_t WfdMaximumTp; + uint16_t WfdExtendCap; + uint8_t WfdCoupleSinkAddress[MAC_ADDR_LEN]; + uint8_t WfdAssociatedBssid[MAC_ADDR_LEN]; + uint8_t WfdVideoIp[4]; + uint8_t WfdAudioIp[4]; + uint16_t WfdVideoPort; + uint16_t WfdAudioPort; + uint32_t WfdFlag; + uint32_t WfdPolicy; + uint32_t WfdState; + /* Include Subelement ID, length */ + uint8_t WfdSessionInformationIE[24 * 8]; + uint16_t WfdSessionInformationIELen; + uint8_t aucReserved1[2]; + uint8_t aucWfdPrimarySinkMac[MAC_ADDR_LEN]; + uint8_t aucWfdSecondarySinkMac[MAC_ADDR_LEN]; + uint32_t WfdAdvanceFlag; + /* Group 1 64 bytes */ + uint8_t aucWfdLocalIp[4]; + uint16_t WfdLifetimeAc2; /* Unit is 2 TU */ + uint16_t WfdLifetimeAc3; /* Unit is 2 TU */ + uint16_t WfdCounterThreshold; /* Unit is ms */ + uint8_t aucReserved2[54]; + /* Group 3 64 bytes */ + uint8_t aucReserved3[64]; + /* Group 3 64 bytes */ + uint8_t aucReserved4[64]; +}; +#endif +#endif + +/****************************************************************************** + * P U B L I C D A T A + ****************************************************************************** + */ + +/****************************************************************************** + * P R I V A T E D A T A + ****************************************************************************** + */ + +u_int8_t p2pRegisterToWlan(struct GLUE_INFO *prGlueInfo); + +u_int8_t p2pUnregisterToWlan(struct GLUE_INFO *prGlueInfo); + +u_int8_t p2pLaunch(struct GLUE_INFO *prGlueInfo); + +u_int8_t p2pRemove(struct GLUE_INFO *prGlueInfo); + +void p2pSetMode(IN uint8_t ucAPMode); + +u_int8_t glRegisterP2P(struct GLUE_INFO *prGlueInfo, + const char *prDevName, + const char *prDevName2, + uint8_t ucApMode); + +int glSetupP2P(struct GLUE_INFO *prGlueInfo, + struct wireless_dev *prP2pWdev, + struct net_device *prP2pDev, + int u4Idx, + u_int8_t fgIsApMode); + +u_int8_t glUnregisterP2P(struct GLUE_INFO *prGlueInfo, uint8_t ucIdx); + +u_int8_t p2pNetRegister(struct GLUE_INFO *prGlueInfo, + u_int8_t fgIsRtnlLockAcquired); + +u_int8_t p2pNetUnregister(struct GLUE_INFO *prGlueInfo, + u_int8_t fgIsRtnlLockAcquired); + + +u_int8_t p2PAllocInfo(IN struct GLUE_INFO *prGlueInfo, IN uint8_t ucIdex); +u_int8_t p2PFreeInfo(struct GLUE_INFO *prGlueInfo, uint8_t ucIdx); + +void p2pSetSuspendMode(struct GLUE_INFO *prGlueInfo, u_int8_t fgEnable); +u_int8_t glP2pCreateWirelessDevice(struct GLUE_INFO *prGlueInfo); +void glP2pDestroyWirelessDevice(void); +void p2pUpdateChannelTableByDomain(struct GLUE_INFO *prGlueInfo); +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_qa_agent.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_qa_agent.h new file mode 100644 index 0000000000000..4924b2b771189 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_qa_agent.h @@ -0,0 +1,356 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/*! \file gl_qa_agent.h + * \brief This file includes private ioctl support. + */ + +#ifndef _GL_QA_AGENT_H +#define _GL_QA_AGENT_H + +#if CFG_SUPPORT_QA_TOOL + +/******************************************************************************* + * C O M P I L E 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_MTK_EMI +extern phys_addr_t gConEmiPhyBase; +extern unsigned long long gConEmiSize; +#endif + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/* Trigger Event */ +#define CAP_FREE_RUN 0 + +/* Ring Mode */ +#define CAP_RING_MODE_ENABLE 1 +#define CAP_RING_MODE_DISABLE 0 + +/* Capture Bit Width */ +#define CAP_32_BIT 0 +#define CAP_96_BIT 1 +#define CAP_128_BIT 2 + +/* I/Q Type */ +#define CAP_I_TYPE 0 +#define CAP_Q_TYPE 1 +#define NUM_OF_CAP_TYPE 2 + +/* RBIST ICAP SOURCE */ +#define CAP_WIFI_PHY 0 + +/* CAPTURE ARCHITECTURE */ +#define CAP_ON_CHIP 0 +#define CAP_ON_THE_FLY 1 + +/* ACTION */ +#define ACTION_SWITCH_TO_RFTEST 0 /* to switch firmware mode between normal mode + * or rf test mode + */ +#define ACTION_IN_RFTEST 1 + +#define HQA_CMD_MAGIC_NO 0x18142880 +#define HQA_CHIP_ID_6632 0x6632 +#define HQA_CHIP_ID_7668 0x7668 + +/* (4096(Samples/Bank) * 6Banks * 3(IQSamples/Sample) * 32bits)/96bits */ +#define MAX_ICAP_IQ_DATA_CNT (4096 * 8) +#define ICAP_EVENT_DATA_SAMPLE 256 + + +#if CFG_SUPPORT_TX_BF +#define HQA_BF_STR_SIZE 512 +#endif + +#define HQA_RX_STATISTIC_NUM 66 +#define BUFFER_BIN_MODE 0x0 +#define EFUSE_MODE 0x2 + +#ifdef MAX_EEPROM_BUFFER_SIZE +#undef MAX_EEPROM_BUFFER_SIZE +#endif +#define MAX_EEPROM_BUFFER_SIZE 1536 + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ + +extern uint8_t uacEEPROMImage[MAX_EEPROM_BUFFER_SIZE]; + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +#if 0 +struct PARAM_RX_STAT { + uint32_t MacFCSErr; /* Y 0x820F_D014 */ + uint32_t MacMdrdy; /* Y 0x820F_D030 */ + uint32_t FCSErr_CCK; /* Y 0x8207_021C [15:00] */ + uint32_t FCSErr_OFDM; /* Y 0x8207_021C [31:16] */ + uint32_t CCK_PD; /* Y 0x8207_020C [15:00] */ + uint32_t OFDM_PD; /* Y 0x8207_020C [15:00] */ + uint32_t CCK_SIG_Err; /* Y 0x8207_0210 [31:16] */ + uint32_t CCK_SFD_Err; /* Y 0x8207_0210 [15:00] */ + uint32_t OFDM_SIG_Err; /* Y 0x8207_0214 [31:16] */ + uint32_t OFDM_TAG_Err; /* Y 0x8207_0214 [15:00] */ + uint32_t WB_RSSSI0; /* Y 0x8207_21A8 [23:16] */ + uint32_t IB_RSSSI0; /* Y 0x8207_21A8 [31:24] */ + uint32_t WB_RSSSI1; /* Y 0x8207_21A8 [07:00] */ + uint32_t IB_RSSSI1; /* Y 0x8207_21A8 [15:08] */ + uint32_t PhyMdrdyCCK; /* Y 0x8207_0220 [15:00] */ + uint32_t PhyMdrdyOFDM; /* Y 0x8207_0220 [31:16] */ + uint32_t DriverRxCount; /* Y FW Counter Band0 */ + uint32_t RCPI0; /* Y RXV4 [07:00] */ + uint32_t RCPI1; /* Y RXV4 [15:08] */ + uint32_t FreqOffsetFromRX; /* Y RXV5 MISC1[24:00] OFDM:[11:00] + * CCK:[10:00] + */ + uint32_t RSSI0; /* N */ + uint32_t RSSI1; /* N */ + uint32_t rx_fifo_full; /* N */ + uint32_t RxLenMismatch; /* N */ + uint32_t MacFCSErr_band1; /* Y 0x820F_D214 */ + uint32_t MacMdrdy_band1; /* Y 0x820F_D230 */ + /* Y RXV3 [23:16] (must set 0x8207066C[1:0] = 0x0 ~ 0x3) */ + uint32_t FAGC_IB_RSSSI[4]; + /* Y RXV3 [31:24] (must set 0x8207066C[1:0] = 0x0 ~ 0x3) */ + uint32_t FAGC_WB_RSSSI[4]; + /* Y 0x8207_21A8 [31:24] [15:08] 0x8207_29A8 [31:24] [15:08] */ + uint32_t Inst_IB_RSSSI[4]; + /* Y 0x8207_21A8 [23:16] [07:00] 0x8207_29A8 [23:16] [07:00] */ + uint32_t Inst_WB_RSSSI[4]; + uint32_t ACIHitLow; /* Y 0x8207_21B0 [18] */ + uint32_t ACIHitHigh; /* Y 0x8207_29B0 [18] */ + uint32_t DriverRxCount1; /* Y FW Counter Band1 */ + uint32_t RCPI2; /* Y RXV4 [23:16] */ + uint32_t RCPI3; /* Y RXV4 [31:24] */ + uint32_t RSSI2; /* N */ + uint32_t RSSI3; /* N */ + uint32_t SNR0; /* Y RXV5 (MISC1 >> 19) - 16 */ + uint32_t SNR1; /* N */ + uint32_t SNR2; /* N */ + uint32_t SNR3; /* N */ + uint32_t rx_fifo_full_band1; /* N */ + uint32_t RxLenMismatch_band1; /* N */ + uint32_t CCK_PD_band1; /* Y 0x8207_040C [15:00] */ + uint32_t OFDM_PD_band1; /* Y 0x8207_040C [31:16] */ + uint32_t CCK_SIG_Err_band1; /* Y 0x8207_0410 [31:16] */ + uint32_t CCK_SFD_Err_band1; /* Y 0x8207_0410 [15:00] */ + uint32_t OFDM_SIG_Err_band1; /* Y 0x8207_0414 [31:16] */ + uint32_t OFDM_TAG_Err_band1; /* Y 0x8207_0414 [15:00] */ + uint32_t PhyMdrdyCCK_band1; /* Y 0x8207_0420 [15:00] */ + uint32_t PhyMdrdyOFDM_band1; /* Y 0x8207_0420 [31:16] */ + uint32_t CCK_FCS_Err_band1; /* Y 0x8207_041C [15:00] */ + uint32_t OFDM_FCS_Err_band1; /* Y 0x8207_041C [31:16] */ + uint32_t MuPktCount; /* Y MT_ATEUpdateRxStatistic + * RXV1_2ND_CYCLE->GroupId + */ +}; +#else +struct PARAM_RX_STAT { + uint32_t MAC_FCS_Err; /* b0 */ + uint32_t MAC_Mdrdy; /* b0 */ + uint32_t FCSErr_CCK; + uint32_t FCSErr_OFDM; + uint32_t CCK_PD; + uint32_t OFDM_PD; + uint32_t CCK_SIG_Err; + uint32_t CCK_SFD_Err; + uint32_t OFDM_SIG_Err; + uint32_t OFDM_TAG_Err; + uint32_t WB_RSSI0; + uint32_t IB_RSSI0; + uint32_t WB_RSSI1; + uint32_t IB_RSSI1; + uint32_t PhyMdrdyCCK; + uint32_t PhyMdrdyOFDM; + uint32_t DriverRxCount; + uint32_t RCPI0; + uint32_t RCPI1; + uint32_t FreqOffsetFromRX; + uint32_t RSSI0; + uint32_t RSSI1; /* insert new member here */ + uint32_t OutOfResource; /* MT7615 begin here */ + uint32_t LengthMismatchCount_B0; + uint32_t MAC_FCS_Err1; /* b1 */ + uint32_t MAC_Mdrdy1; /* b1 */ + uint32_t FAGCRssiIBR0; + uint32_t FAGCRssiIBR1; + uint32_t FAGCRssiIBR2; + uint32_t FAGCRssiIBR3; + uint32_t FAGCRssiWBR0; + uint32_t FAGCRssiWBR1; + uint32_t FAGCRssiWBR2; + uint32_t FAGCRssiWBR3; + + uint32_t InstRssiIBR0; + uint32_t InstRssiIBR1; + uint32_t InstRssiIBR2; + uint32_t InstRssiIBR3; + uint32_t InstRssiWBR0; + uint32_t InstRssiWBR1; + uint32_t InstRssiWBR2; + uint32_t InstRssiWBR3; + uint32_t ACIHitLower; + uint32_t ACIHitUpper; + uint32_t DriverRxCount1; + uint32_t RCPI2; + uint32_t RCPI3; + uint32_t RSSI2; + uint32_t RSSI3; + uint32_t SNR0; + uint32_t SNR1; + uint32_t SNR2; + uint32_t SNR3; + uint32_t OutOfResource1; + uint32_t LengthMismatchCount_B1; + uint32_t CCK_PD_Band1; + uint32_t OFDM_PD_Band1; + uint32_t CCK_SIG_Err_Band1; + uint32_t CCK_SFD_Err_Band1; + uint32_t OFDM_SIG_Err_Band1; + uint32_t OFDM_TAG_Err_Band1; + uint32_t PHY_CCK_MDRDY_Band1; + uint32_t PHY_OFDM_MDRDY_Band1; + uint32_t CCK_FCS_Err_Band1; + uint32_t OFDM_FCS_Err_Band1; + uint32_t MRURxCount; + uint32_t SIGMCS; + uint32_t SINR; + uint32_t RXVRSSI; + uint32_t Reserved[184]; + uint32_t PHY_Mdrdy; + uint32_t Noise_Floor; + uint32_t AllLengthMismatchCount_B0; + uint32_t AllLengthMismatchCount_B1; + uint32_t AllMacMdrdy0; + uint32_t AllMacMdrdy1; + uint32_t AllFCSErr0; + uint32_t AllFCSErr1; + uint32_t RXOK0; + uint32_t RXOK1; + uint32_t PER0; + uint32_t PER1; +}; +extern struct PARAM_RX_STAT g_HqaRxStat; +#endif + +struct HQA_CMD_FRAME { + uint32_t MagicNo; + uint16_t Type; + uint16_t Id; + uint16_t Length; + uint16_t Sequence; + uint8_t Data[2048]; +} __KAL_ATTRIB_PACKED__; + +typedef int32_t(*HQA_CMD_HANDLER) (struct net_device + *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame); + +struct HQA_CMD_TABLE { + HQA_CMD_HANDLER *CmdSet; + uint32_t CmdSetSize; + uint32_t CmdOffset; +}; + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +int HQA_CMDHandler(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + struct HQA_CMD_FRAME *HqaCmdFrame); + +int priv_qa_agent(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN char *pcExtra); + +int32_t mt6632SetICapStart(struct GLUE_INFO *prGlueInfo, + uint32_t u4Trigger, uint32_t u4RingCapEn, + uint32_t u4Event, uint32_t u4Node, uint32_t u4Len, + uint32_t u4StopCycle, + uint32_t u4BW, uint32_t u4MacTriggerEvent, + uint32_t u4SourceAddrLSB, + uint32_t u4SourceAddrMSB, uint32_t u4Band); +int32_t mt6632GetICapStatus(struct GLUE_INFO *prGlueInfo); + +int32_t connacSetICapStart(struct GLUE_INFO *prGlueInfo, + uint32_t u4Trigger, uint32_t u4RingCapEn, + uint32_t u4Event, uint32_t u4Node, uint32_t u4Len, + uint32_t u4StopCycle, + uint32_t u4BW, uint32_t u4MacTriggerEvent, + uint32_t u4SourceAddrLSB, + uint32_t u4SourceAddrMSB, uint32_t u4Band); +int32_t connacGetICapStatus(struct GLUE_INFO *prGlueInfo); + +int32_t commonGetICapIQData(struct GLUE_INFO *prGlueInfo, + uint8_t *pData, uint32_t u4IQType, uint32_t u4WFNum); +int32_t connacGetICapIQData(struct GLUE_INFO *prGlueInfo, + uint8_t *pData, uint32_t u4IQType, uint32_t u4WFNum); + + +#endif /*CFG_SUPPORT_QA_TOOL */ +#endif /* _GL_QA_AGENT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_rst.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_rst.h new file mode 100644 index 0000000000000..e274e722a084b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_rst.h @@ -0,0 +1,298 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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" + +#if 0 +#include "mtk_porting.h" +#endif +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#if (MTK_WCN_HIF_SDIO == 1) || (MTK_WCN_HIF_AXI == 1) +#define CFG_WMT_RESET_API_SUPPORT 1 +#else +#define CFG_WMT_RESET_API_SUPPORT 0 +#endif + +#define RST_FLAG_CHIP_RESET 0 +#define RST_FLAG_DO_CORE_DUMP BIT(0) +#define RST_FLAG_PREVENT_POWER_OFF BIT(1) + +#if CFG_CHIP_RESET_HANG +#define SER_L0_HANG_RST_NONE 0 +#define SER_L0_HANG_RST_TRGING 1 +#define SER_L0_HANG_RST_HAND_DISABLE 2 +#define SER_L0_HANG_RST_HANG 3 +#define SER_L0_HANG_RST_CMD_TRG 9 + +#define SER_L0_HANG_LOG_TIME_INTERVAL 3000 +#endif +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +enum ENUM_RESET_STATUS { + RESET_FAIL, + RESET_SUCCESS +}; + +enum _ENUM_CHIP_RESET_REASON_TYPE_T { + RST_PROCESS_ABNORMAL_INT = 1, + RST_DRV_OWN_FAIL, + RST_FW_ASSERT, + RST_BT_TRIGGER, + RST_OID_TIMEOUT, + RST_CMD_TRIGGER, + RST_REASON_MAX +}; + +struct RESET_STRUCT { + struct GLUE_INFO *prGlueInfo; + struct work_struct rst_work; +#if CFG_WMT_RESET_API_SUPPORT + enum ENUM_RESET_STATUS rst_data; + struct work_struct rst_trigger_work; + uint32_t rst_trigger_flag; +#endif +}; + +#if CFG_WMT_RESET_API_SUPPORT +/* duplicated from wmt_exp.h for better driver isolation */ +enum ENUM_WMTDRV_TYPE { + 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 ENUM_WMTMSG_TYPE { + 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 ENUM_WMTRSTMSG_TYPE { + WMTRSTMSG_RESET_START = 0x0, + WMTRSTMSG_RESET_END = 0x1, + WMTRSTMSG_RESET_END_FAIL = 0x2, + WMTRSTMSG_RESET_MAX, + WMTRSTMSG_RESET_INVALID = 0xff +}; + +typedef void (*PF_WMT_CB) (enum ENUM_WMTDRV_TYPE, /* Source driver type */ + enum ENUM_WMTDRV_TYPE, /* Destination driver type */ + enum ENUM_WMTMSG_TYPE, /* Message type */ + /* READ-ONLY buffer. Buffer is allocated and + * freed by WMT_drv. Client can't touch this + * buffer after this function return. + */ + void *, + unsigned int); /* Buffer size in unit of byte */ + +#endif + +/******************************************************************************* + * E X T E R N A L F U N C T I O N S + ******************************************************************************* + */ +#if CFG_CHIP_RESET_SUPPORT + + +#if CFG_WMT_RESET_API_SUPPORT +extern int mtk_wcn_wmt_assert(enum ENUM_WMTDRV_TYPE type, + uint32_t reason); +extern int mtk_wcn_wmt_msgcb_reg(enum ENUM_WMTDRV_TYPE + eType, PF_WMT_CB pCb); +extern int mtk_wcn_wmt_msgcb_unreg(enum ENUM_WMTDRV_TYPE + eType); +extern int wifi_reset_start(void); +extern int wifi_reset_end(enum ENUM_RESET_STATUS); + +#if CFG_ENABLE_KEYWORD_EXCEPTION_MECHANISM +extern int mtk_wcn_wmt_assert_keyword(enum ENUM_WMTDRV_TYPE type, + unsigned char *keyword); +#endif +#endif +#endif + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +#if CFG_CHIP_RESET_SUPPORT +extern u_int8_t fgIsResetting; + +#if CFG_CHIP_RESET_HANG +extern u_int8_t fgIsResetHangState; +#endif + +#endif +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +#define GL_COREDUMP_TRIGGER(_prAdapter) \ +{ \ + wlanoidSerExtCmd(_prAdapter, SER_ACTION_RECOVER, SER_SET_L0_RECOVER, \ + 0); \ +} + + +#if CFG_CHIP_RESET_SUPPORT +#if CFG_WMT_RESET_API_SUPPORT +#define GL_RESET_TRIGGER(_prAdapter, _u4Flags) \ + glResetTrigger(_prAdapter, (_u4Flags), \ + (const uint8_t *)__FILE__, __LINE__) +#else +#define GL_RESET_TRIGGER(_prAdapter, _u4Flags) \ +{ \ + if (eResetReason == RST_OID_TIMEOUT || \ + eResetReason == RST_FW_ASSERT || \ + eResetReason == RST_CMD_TRIGGER || \ + eResetReason == RST_BT_TRIGGER) { \ + glResetTrigger(_prAdapter, (_u4Flags), \ + (const uint8_t *)__FILE__, __LINE__); \ + } else { \ + GL_COREDUMP_TRIGGER(_prAdapter); \ + DBGLOG(INIT, ERROR, "Trigger coredump in %s line %u!\n", \ + __FILE__, __LINE__); \ + } \ +} +#endif +#else +#define GL_RESET_TRIGGER(_prAdapter, _u4Flags) \ + DBGLOG(INIT, INFO, "DO NOT support chip reset\n") +#endif + + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +#if CFG_CHIP_RESET_SUPPORT +extern uint64_t u8ResetTime; +extern enum _ENUM_CHIP_RESET_REASON_TYPE_T eResetReason; + +#if CFG_WMT_RESET_API_SUPPORT +extern int mtk_wcn_set_connsys_power_off_flag(int value); +extern int mtk_wcn_wmt_assert_timeout(enum ENUM_WMTDRV_TYPE + type, uint32_t reason, int timeout); +extern int mtk_wcn_wmt_do_reset(enum ENUM_WMTDRV_TYPE type); + +/* WMT Core Dump Support */ +extern u_int8_t mtk_wcn_stp_coredump_start_get(void); +#endif +#else + +#endif +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#if CFG_CHIP_RESET_SUPPORT +void glResetInit(struct GLUE_INFO *prGlueInfo); + +void glResetUninit(void); + +void glSendResetRequest(void); + +u_int8_t kalIsResetting(void); + +u_int8_t glResetTrigger(struct ADAPTER *prAdapter, + uint32_t u4RstFlag, const uint8_t *pucFile, + uint32_t u4Line); + +void glGetRstReason(enum _ENUM_CHIP_RESET_REASON_TYPE_T + eReason); +#if CFG_WMT_RESET_API_SUPPORT +u_int8_t glIsWmtCodeDump(void); +#endif +#else + +#endif +#endif /* _GL_RST_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_sec.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_sec.h new file mode 100644 index 0000000000000..e00aab1ff55e5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_sec.h @@ -0,0 +1,79 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include + * /gl_sec.h#1 + */ + +/*! \file p2p_fsm.h + * \brief Declaration of functions and finite state machine for P2P Module. + * + * Declaration of functions and finite state machine for P2P Module. + */ + +#ifndef _GL_SEC_H +#define _GL_SEC_H + +extern void handle_sec_msg_1(unsigned char *msg_in, int msg_in_len, + unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_2(unsigned char *msg_in, int msg_in_len, + unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_3(unsigned char *msg_in, int msg_in_len, + unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_4(unsigned char *msg_in, int msg_in_len, + unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_5(unsigned char *msg_in, int msg_in_len, + unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_final(unsigned char *msg_in, int msg_in_len, + unsigned char *msg_out, int *msg_out_len); + +#endif /* _GL_SEC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_typedef.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_typedef.h new file mode 100644 index 0000000000000..1113e4fd0ba39 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_typedef.h @@ -0,0 +1,272 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + * 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. + */ + + +#ifndef _GL_TYPEDEF_H +#define _GL_TYPEDEF_H + +#if CFG_ENABLE_EARLY_SUSPEND +#include +#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 ((u_int8_t) 0) +#define TRUE ((u_int8_t) 1) +#endif /* FALSE */ + +#ifndef NULL +#if defined(__cplusplus) +#define NULL 0 +#else +#define NULL ((void *) 0) +#endif +#endif + +#if CFG_ENABLE_EARLY_SUSPEND +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 */ + +/* Type definition for Boolean */ + +/* Type definition for signed integers */ + +/* Type definition for unsigned integers */ + + +#define OS_SYSTIME uint32_t + +/* Type definition of large integer (64bits) union to be comptaible with + * Windows definition, so we won't apply our own coding style to these data + * types. + * NOTE: LARGE_INTEGER must NOT be floating variable. + * : Check for big-endian compatibility. + */ +union LARGE_INTEGER { + struct { + uint32_t LowPart; + int32_t HighPart; + } u; + int64_t QuadPart; +}; + +union ULARGE_INTEGER { + struct { + uint32_t LowPart; + uint32_t HighPart; + } u; + uint64_t QuadPart; +}; + +typedef int32_t(*probe_card) (void *pvData, + void *pvDriverData); +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__ inline +#define __KAL_ATTRIB_PACKED__ __attribute__((__packed__)) +#define __KAL_ATTRIB_ALIGN_4__ __aligned(4) + +#ifndef BIT +#define BIT(n) ((uint32_t) 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) ((unsigned long)&(((_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 *)((int8_t *)(_addrOfField) - \ + (int8_t *)OFFSET_OF(_type, _field))) +#endif /* ENTRY_OF */ + +/* This macro align the input value to the DW boundary. + * _value - value need to check + */ +#ifndef ALIGN_4 +#define ALIGN_4(_value) (((_value) + 3) & ~3u) +#endif /* ALIGN_4 */ + +/* This macro check the DW alignment of the input value. + * _value - value of address need to check + */ +#ifndef IS_ALIGN_4 +#define IS_ALIGN_4(_value) (((_value) & 0x3) ? FALSE : TRUE) +#endif /* IS_ALIGN_4 */ + +#ifndef IS_NOT_ALIGN_4 +#define IS_NOT_ALIGN_4(_value) (((_value) & 0x3) ? TRUE : FALSE) +#endif /* IS_NOT_ALIGN_4 */ + +/* This macro evaluate the input length in unit of Double Word(4 Bytes). + * _value - value in unit of Byte, output will round up to DW boundary. + */ +#ifndef BYTE_TO_DWORD +#define BYTE_TO_DWORD(_value) ((_value + 3) >> 2) +#endif /* BYTE_TO_DWORD */ + +/* This macro evaluate the input length in unit of Byte. + * _value - value in unit of DW, output is in unit of Byte. + */ +#ifndef DWORD_TO_BYTE +#define DWORD_TO_BYTE(_value) ((_value) << 2) +#endif /* DWORD_TO_BYTE */ + +#if 1 /* Little-Endian */ +#define CONST_NTOHS(_x) ntohs(_x) + +#define CONST_HTONS(_x) htons(_x) + +#define NTOHS(_x) ntohs(_x) + +#define HTONS(_x) htons(_x) + +#define NTOHL(_x) ntohl(_x) + +#define HTONL(_x) htonl(_x) + +#else /* Big-Endian */ + +#define CONST_NTOHS(_x) + +#define CONST_HTONS(_x) + +#define NTOHS(_x) + +#define HTONS(_x) + +#endif + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _GL_TYPEDEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_vendor.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_vendor.h new file mode 100644 index 0000000000000..98f03d92314e8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_vendor.h @@ -0,0 +1,709 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + * Log: gl_vendor.h + * + * 10 14 2014 + * add vendor declaration + * + * + */ + +#ifndef _GL_VENDOR_H +#define _GL_VENDOR_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include +#include +#include +#include +#include +#include +#include +#include "wlan_lib.h" +#include "gl_wext.h" + + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define GOOGLE_OUI 0x001A11 +#define OUI_QCA 0x001374 + +#define NL80211_VENDOR_SUBCMD_GET_PREFER_FREQ_LIST 103 +#define QCA_NL80211_VENDOR_SUBCMD_SETBAND 105 + +enum ANDROID_VENDOR_SUB_COMMAND { + /* Don't use 0 as a valid subcommand */ + ANDROID_NL80211_SUBCMD_UNSPECIFIED, + + /* Define all vendor startup commands between 0x0 and 0x0FFF */ + ANDROID_NL80211_SUBCMD_WIFI_RANGE_START = 0x0001, + ANDROID_NL80211_SUBCMD_WIFI_RANGE_END = 0x0FFF, + + /* Define all GScan related commands between 0x1000 and 0x10FF */ + ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START = 0x1000, + ANDROID_NL80211_SUBCMD_GSCAN_RANGE_END = 0x10FF, + + /* Define all RTT related commands between 0x1100 and 0x11FF */ + ANDROID_NL80211_SUBCMD_RTT_RANGE_START = 0x1100, + ANDROID_NL80211_SUBCMD_RTT_RANGE_END = 0x11FF, + + ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START = 0x1200, + ANDROID_NL80211_SUBCMD_LSTATS_RANGE_END = 0x12FF, + + /* Define all Logger related commands between 0x1400 and 0x14FF */ + ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START = 0x1400, + ANDROID_NL80211_SUBCMD_DEBUG_RANGE_END = 0x14FF, + + /* Define all wifi offload related commands between 0x1600 and 0x16FF */ + ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START = 0x1600, + ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_END = 0x16FF, + + /* This is reserved for future usage */ + +}; + +enum WIFI_SUB_COMMAND { + WIFI_SUBCMD_GET_CHANNEL_LIST = ANDROID_NL80211_SUBCMD_WIFI_RANGE_START, + + WIFI_SUBCMD_GET_FEATURE_SET, /* 0x0002 */ + WIFI_SUBCMD_GET_FEATURE_SET_MATRIX, /* 0x0003 */ + WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI, /* 0x0004 */ + WIFI_SUBCMD_NODFS_SET, /* 0x0005 */ + WIFI_SUBCMD_SET_COUNTRY_CODE, /* 0x0006 */ + WIFI_SUBCMD_SET_RSSI_MONITOR, /* 0x0007 */ + + /* Add more sub commands here */ + WIFI_SUBCMD_GET_ROAMING_CAPABILITIES, /* 0x0008 */ + WIFI_SUBCMD_SET_ROAMING = 0x0009, /* 0x0009 */ + WIFI_SUBCMD_CONFIG_ROAMING = 0x000a, /* 0x000a */ + WIFI_SUBCMD_ENABLE_ROAMING, /* 0x000b */ + + WIFI_SUBCMD_SELECT_TX_POWER_SCENARIO, /* 0x000c */ +}; + +enum RTT_SUB_COMMAND { + RTT_SUBCMD_SET_CONFIG = ANDROID_NL80211_SUBCMD_RTT_RANGE_START, + RTT_SUBCMD_CANCEL_CONFIG, + RTT_SUBCMD_GETCAPABILITY, +}; + +enum LSTATS_SUB_COMMAND { + LSTATS_SUBCMD_GET_INFO = ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START, +}; + +/* moved from wifi_logger.cpp */ +enum DEBUG_SUB_COMMAND { + LOGGER_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START, + LOGGER_GET_VER +}; + +enum WIFI_OFFLOAD_SUB_COMMAND { + WIFI_OFFLOAD_START_MKEEP_ALIVE = + ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START, + WIFI_OFFLOAD_STOP_MKEEP_ALIVE, +}; + +enum WIFI_VENDOR_EVENT { + GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS, + GSCAN_EVENT_HOTLIST_RESULTS_FOUND, + GSCAN_EVENT_SCAN_RESULTS_AVAILABLE, + GSCAN_EVENT_FULL_SCAN_RESULTS, + RTT_EVENT_COMPLETE, + GSCAN_EVENT_COMPLETE_SCAN, + GSCAN_EVENT_HOTLIST_RESULTS_LOST, + WIFI_EVENT_RSSI_MONITOR, + WIFI_EVENT_MAGIC_PACKET_RECEIVED +}; + +enum WIFI_ATTRIBUTE { + WIFI_ATTRIBUTE_BAND = 1, + WIFI_ATTRIBUTE_NUM_CHANNELS, + WIFI_ATTRIBUTE_CHANNEL_LIST, + + WIFI_ATTRIBUTE_NUM_FEATURE_SET, + WIFI_ATTRIBUTE_FEATURE_SET, + WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, + WIFI_ATTRIBUTE_NODFS_VALUE, + WIFI_ATTRIBUTE_COUNTRY_CODE, + + WIFI_ATTRIBUTE_MAX_RSSI, + WIFI_ATTRIBUTE_MIN_RSSI, + WIFI_ATTRIBUTE_RSSI_MONITOR_START, + + WIFI_ATTRIBUTE_ROAMING_CAPABILITIES, + WIFI_ATTRIBUTE_ROAMING_BLACKLIST_NUM, + WIFI_ATTRIBUTE_ROAMING_BLACKLIST_BSSID, + WIFI_ATTRIBUTE_ROAMING_WHITELIST_NUM, + WIFI_ATTRIBUTE_ROAMING_WHITELIST_SSID, + WIFI_ATTRIBUTE_ROAMING_STATE, + + WIFI_ATTRIBUTE_TX_POWER_SCENARIO, +}; + +/* moved from wifi_logger.cpp */ +enum LOGGER_ATTRIBUTE { + LOGGER_ATTRIBUTE_DRIVER_VER, + LOGGER_ATTRIBUTE_FW_VER +}; + +enum RTT_ATTRIBUTE { + RTT_ATTRIBUTE_CAPABILITIES = 1, + + RTT_ATTRIBUTE_TARGET_CNT = 10, + RTT_ATTRIBUTE_TARGET_INFO, + RTT_ATTRIBUTE_TARGET_MAC, + RTT_ATTRIBUTE_TARGET_TYPE, + RTT_ATTRIBUTE_TARGET_PEER, + RTT_ATTRIBUTE_TARGET_CHAN, + RTT_ATTRIBUTE_TARGET_PERIOD, + RTT_ATTRIBUTE_TARGET_NUM_BURST, + RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST, + RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM, + RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR, + RTT_ATTRIBUTE_TARGET_LCI, + RTT_ATTRIBUTE_TARGET_LCR, + RTT_ATTRIBUTE_TARGET_BURST_DURATION, + RTT_ATTRIBUTE_TARGET_PREAMBLE, + RTT_ATTRIBUTE_TARGET_BW, + RTT_ATTRIBUTE_RESULTS_COMPLETE = 30, + RTT_ATTRIBUTE_RESULTS_PER_TARGET, + RTT_ATTRIBUTE_RESULT_CNT, + RTT_ATTRIBUTE_RESULT +}; + +enum LSTATS_ATTRIBUTE { + LSTATS_ATTRIBUTE_STATS = 2, +}; + +enum WIFI_MKEEP_ALIVE_ATTRIBUTE { + MKEEP_ALIVE_ATTRIBUTE_ID = 1, + MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN, + MKEEP_ALIVE_ATTRIBUTE_IP_PKT, + MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR, + MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR, + MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC +}; + +enum WIFI_SCAN_EVENT { + WIFI_SCAN_BUFFER_FULL, + WIFI_SCAN_COMPLETE, +}; + +/* QCA Vender CMD */ +enum QCA_SET_BAND { + QCA_SETBAND_AUTO, + QCA_SETBAND_5G, + QCA_SETBAND_2G, +}; + +enum WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST { + WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_INVALID, + WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_IFACE_TYPE, + WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_GET, + WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_LAST, + WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_MAX = + WIFI_VENDOR_ATTR_PREFERRED_FREQ_LIST_LAST - 1 +}; + +#define MAX_FW_ROAMING_BLACKLIST_SIZE 16 +#define MAX_FW_ROAMING_WHITELIST_SIZE 8 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +#if CFG_SUPPORT_WAPI +extern uint8_t +keyStructBuf[1024]; /* add/remove key shared buffer */ +#else +extern uint8_t +keyStructBuf[100]; /* add/remove key shared buffer */ +#endif + +/******************************************************************************* + * MACROS + ******************************************************************************* + */ + +#if KERNEL_VERSION(3, 5, 0) <= LINUX_VERSION_CODE +/* + * #define NLA_PUT(skb, attrtype, attrlen, data) \ + * do { \ + * if (unlikely(nla_put(skb, attrtype, attrlen, data) < 0)) \ + * goto nla_put_failure; \ + * } while (0) + * + *#define NLA_PUT_TYPE(skb, type, attrtype, value) \ + * do { \ + * type __tmp = value; \ + * NLA_PUT(skb, attrtype, sizeof(type), &__tmp); \ + * } while (0) + */ +#define NLA_PUT(skb, attrtype, attrlen, data) \ + mtk_cfg80211_NLA_PUT(skb, attrtype, attrlen, data) + +#define NLA_PUT_TYPE(skb, type, attrtype, value) \ + mtk_cfg80211_nla_put_type(skb, type, attrtype, value) + +#define NLA_PUT_U8(skb, attrtype, value) \ + NLA_PUT_TYPE(skb, NLA_PUT_DATE_U8, attrtype, value) + +#define NLA_PUT_U16(skb, attrtype, value) \ + NLA_PUT_TYPE(skb, NLA_PUT_DATE_U16, attrtype, value) + +#define NLA_PUT_U32(skb, attrtype, value) \ + NLA_PUT_TYPE(skb, NLA_PUT_DATE_U32, attrtype, value) + +#define NLA_PUT_U64(skb, attrtype, value) \ + NLA_PUT_TYPE(skb, NLA_PUT_DATE_U64, attrtype, value) + +#endif + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +#define NLA_PARSE_NESTED(nlattr, maxtype, nla, policy) \ + nla_parse_nested(nlattr, maxtype, nla, policy, NULL) +#define NLA_PARSE(tb, maxtype, head, len, policy) \ + nla_parse(tb, maxtype, head, len, policy, NULL) +#else +#define NLA_PARSE_NESTED(nlattr, maxtype, nla, policy) \ + nla_parse_nested(nlattr, maxtype, nla, policy) +#define NLA_PARSE(tb, maxtype, head, len, policy) \ + nla_parse(tb, maxtype, head, len, policy) +#endif + +/******************************************************************************* + * P R I V A T E D A T A + * + ******************************************************************************* + */ +struct PARAM_WIFI_CHANGE_RESULT { + uint16_t flags; + uint16_t channel; + uint8_t bssid[6]; /* BSSID */ + int8_t rssi[8]; /* RSSI history in db */ +}; + +struct PARAM_AP_THRESHOLD { + uint8_t bssid[6]; /* AP BSSID */ + int32_t low; /* low threshold */ + int32_t high; /* high threshold */ + uint32_t channel; /* channel hint */ +}; + +/* channel operating width */ +enum WIFI_CHANNEL_WIDTH { + WIFI_CHAN_WIDTH_20 = 0, + WIFI_CHAN_WIDTH_40 = 1, + WIFI_CHAN_WIDTH_80 = 2, + WIFI_CHAN_WIDTH_160 = 3, + WIFI_CHAN_WIDTH_80P80 = 4, + WIFI_CHAN_WIDTH_5 = 5, + WIFI_CHAN_WIDTH_10 = 6, + WIFI_CHAN_WIDTH_INVALID = -1 +}; + +/* channel information */ +struct WIFI_CHANNEL_INFO { + enum WIFI_CHANNEL_WIDTH width; + uint32_t center_freq; + uint32_t center_freq0; + uint32_t center_freq1; +}; + +/* channel statistics */ +struct WIFI_CHANNEL_STAT { + struct WIFI_CHANNEL_INFO channel; + uint32_t on_time; + uint32_t cca_busy_time; +}; + +/* radio statistics */ +struct WIFI_RADIO_STAT { + uint32_t radio; + uint32_t on_time; + uint32_t tx_time; + uint32_t rx_time; + uint32_t on_time_scan; + uint32_t on_time_nbd; + uint32_t on_time_gscan; + uint32_t on_time_roam_scan; + uint32_t on_time_pno_scan; + uint32_t on_time_hs20; + uint32_t num_channels; + struct WIFI_CHANNEL_STAT channels[]; +}; + +/* wifi rate */ +struct WIFI_RATE { + uint32_t preamble: 3; + uint32_t nss: 2; + uint32_t bw: 3; + uint32_t rateMcsIdx: 8; + + uint32_t reserved: 16; + uint32_t bitrate; +}; + +/* per rate statistics */ +struct WIFI_RATE_STAT { + struct WIFI_RATE rate; + uint32_t tx_mpdu; + uint32_t rx_mpdu; + uint32_t mpdu_lost; + uint32_t retries; + uint32_t retries_short; + uint32_t retries_long; +}; + +/*wifi_interface_link_layer_info*/ +enum WIFI_CONNECTION_STATE { + WIFI_DISCONNECTED = 0, + WIFI_AUTHENTICATING = 1, + WIFI_ASSOCIATING = 2, + WIFI_ASSOCIATED = 3, + WIFI_EAPOL_STARTED = 4, + WIFI_EAPOL_COMPLETED = 5, +}; + +enum WIFI_ROAM_STATE { + WIFI_ROAMING_IDLE = 0, + WIFI_ROAMING_ACTIVE = 1, +}; + +enum WIFI_INTERFACE_MODE { + WIFI_INTERFACE_STA = 0, + WIFI_INTERFACE_SOFTAP = 1, + WIFI_INTERFACE_IBSS = 2, + WIFI_INTERFACE_P2P_CLIENT = 3, + WIFI_INTERFACE_P2P_GO = 4, + WIFI_INTERFACE_NAN = 5, + WIFI_INTERFACE_MESH = 6, + WIFI_INTERFACE_UNKNOWN = -1 +}; + +struct WIFI_INTERFACE_LINK_LAYER_INFO { + enum WIFI_INTERFACE_MODE mode; + u8 mac_addr[6]; + enum WIFI_CONNECTION_STATE state; + enum WIFI_ROAM_STATE roaming; + u32 capabilities; + u8 ssid[33]; + u8 bssid[6]; + u8 ap_country_str[3]; + u8 country_str[3]; +}; + +/* access categories */ +enum WIFI_TRAFFIC_AC { + WIFI_AC_VO = 0, + WIFI_AC_VI = 1, + WIFI_AC_BE = 2, + WIFI_AC_BK = 3, + WIFI_AC_MAX = 4, +}; + +/* wifi peer type */ +enum WIFI_PEER_TYPE { + WIFI_PEER_STA, + WIFI_PEER_AP, + WIFI_PEER_P2P_GO, + WIFI_PEER_P2P_CLIENT, + WIFI_PEER_NAN, + WIFI_PEER_TDLS, + WIFI_PEER_INVALID, +}; + +/* per peer statistics */ +struct WIFI_PEER_INFO { + enum WIFI_PEER_TYPE type; + uint8_t peer_mac_address[6]; + uint32_t capabilities; + uint32_t num_rate; + struct WIFI_RATE_STAT rate_stats[]; +}; + +/* per access category statistics */ +struct WIFI_WMM_AC_STAT_ { + enum WIFI_TRAFFIC_AC ac; + uint32_t tx_mpdu; + uint32_t rx_mpdu; + uint32_t tx_mcast; + + uint32_t rx_mcast; + uint32_t rx_ampdu; + uint32_t tx_ampdu; + uint32_t mpdu_lost; + uint32_t retries; + uint32_t retries_short; + uint32_t retries_long; + uint32_t contention_time_min; + uint32_t contention_time_max; + uint32_t contention_time_avg; + uint32_t contention_num_samples; +}; + +/* RTT Capabilities */ +struct PARAM_WIFI_RTT_CAPABILITIES { + /* if 1-sided rtt data collection is supported */ + uint8_t rtt_one_sided_supported; + /* if ftm rtt data collection is supported */ + uint8_t rtt_ftm_supported; + /* if initiator supports LCI request. Applies to 2-sided RTT */ + uint8_t lci_support; + /* if initiator supports LCR request. Applies to 2-sided RTT */ + uint8_t lcr_support; + /* bit mask indicates what preamble is supported by initiator */ + uint8_t preamble_support; + /* bit mask indicates what BW is supported by initiator */ + uint8_t bw_support; +}; + +/* interface statistics */ +struct WIFI_IFACE_STAT { + struct WIFI_INTERFACE_LINK_LAYER_INFO info; + uint32_t beacon_rx; + uint32_t mgmt_rx; + uint32_t mgmt_action_rx; + uint32_t mgmt_action_tx; + int32_t rssi_mgmt; + int32_t rssi_data; + int32_t rssi_ack; + struct WIFI_WMM_AC_STAT_ ac[WIFI_AC_MAX]; + uint32_t num_peers; + struct WIFI_PEER_INFO peer_info[]; +}; + +enum ENUM_NLA_PUT_DATE_TYPE { + NLA_PUT_DATE_U8 = 0, + NLA_PUT_DATE_U16, + NLA_PUT_DATE_U32, + NLA_PUT_DATE_U64, +}; + +/* RSSI Monitoring */ +struct PARAM_RSSI_MONITOR_T { + bool enable; /* 1=Start, 0=Stop*/ + int8_t max_rssi_value; + int8_t min_rssi_value; + uint8_t reserved[1]; + uint8_t reserved2[4]; /* reserved for MT6632 */ +}; + +struct PARAM_RSSI_MONITOR_EVENT { + uint8_t version; + int8_t rssi; + uint8_t BSSID[PARAM_MAC_ADDR_LEN]; +}; + +/* Packet Keep Alive */ +struct PARAM_PACKET_KEEPALIVE_T { + bool enable; /* 1=Start, 0=Stop*/ + uint8_t index; + int16_t u2IpPktLen; + uint8_t pIpPkt[256]; + uint8_t ucSrcMacAddr[PARAM_MAC_ADDR_LEN]; + uint8_t ucDstMacAddr[PARAM_MAC_ADDR_LEN]; + uint32_t u4PeriodMsec; + uint8_t reserved[8]; /* reserved for MT6632 */ +}; + +struct PARAM_BSS_MAC_OUI { + uint8_t ucBssIndex; + uint8_t ucMacOui[MAC_OUI_LEN]; +}; +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + + + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +int mtk_cfg80211_NLA_PUT(struct sk_buff *skb, int attrtype, + int attrlen, const void *data); + +int mtk_cfg80211_nla_put_type(struct sk_buff *skb, + enum ENUM_NLA_PUT_DATE_TYPE type, int attrtype, + const void *value); + +int mtk_cfg80211_vendor_get_capabilities(struct wiphy + *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_config(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_scan_config(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_significant_change( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_hotlist(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_enable_scan(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_enable_full_scan_results( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_get_scan_results(struct wiphy + *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_get_channel_list(struct wiphy + *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_country_code(struct wiphy + *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_get_rtt_capabilities( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_llstats_get_info(struct wiphy + *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_band(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_scan_mac_oui(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_roaming_policy( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_get_roaming_capabilities( + struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); + +int mtk_cfg80211_vendor_config_roaming(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +int mtk_cfg80211_vendor_enable_roaming(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +int mtk_cfg80211_vendor_set_rssi_monitoring( + struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); + +int mtk_cfg80211_vendor_packet_keep_alive_start( + struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); + +int mtk_cfg80211_vendor_packet_keep_alive_stop( + struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); + +int mtk_cfg80211_vendor_get_version(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_event_rssi_beyond_range( + struct wiphy *wiphy, + struct wireless_dev *wdev, int rssi); + +int mtk_cfg80211_vendor_get_supported_feature_set( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_tx_power_scenario( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +#if CFG_SUPPORT_MAGIC_PKT_VENDOR_EVENT +int mtk_cfg80211_vendor_event_wowlan_magic_pkt( + struct wiphy *wiphy, + struct wireless_dev *wdev, uint32_t num); +#endif + +int mtk_cfg80211_vendor_get_preferred_freq_list(struct wiphy + *wiphy, struct wireless_dev *wdev, const void *data, + int data_len); + +#endif /* _GL_VENDOR_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_wext.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_wext.h new file mode 100644 index 0000000000000..2f3c5c74c4d3a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_wext.h @@ -0,0 +1,399 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + * 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. + */ + + +#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 + ******************************************************************************* + */ +extern void wlanUpdateChannelTable(struct GLUE_INFO + *prGlueInfo); + +#if CFG_SUPPORT_WAPI +extern uint8_t +keyStructBuf[1024]; /* add/remove key shared buffer */ +#else +extern uint8_t +keyStructBuf[100]; /* add/remove key shared buffer */ +#endif + +/* for IE Searching */ +extern u_int8_t +wextSrchDesiredWPAIE(IN uint8_t *pucIEStart, + IN int32_t i4TotalIeLen, IN uint8_t ucDesiredElemId, + OUT uint8_t **ppucDesiredIE); + +#if CFG_SUPPORT_WPS +extern u_int8_t +wextSrchDesiredWPSIE(IN uint8_t *pucIEStart, + IN int32_t i4TotalIeLen, IN uint8_t ucDesiredElemId, + OUT uint8_t **ppucDesiredIE); +#endif + +/******************************************************************************* + * 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 + ******************************************************************************* + */ +struct PARAM_FIXED_IEs { + uint8_t aucTimestamp[8]; + uint16_t u2BeaconInterval; + uint16_t u2Capabilities; +}; + +struct PARAM_VARIABLE_IE { + uint8_t ucElementID; + uint8_t ucLength; + uint8_t aucData[1]; +}; + +#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, + /* used to check the valid filter bits */ + IEEE80211_FILTER_TYPE_ALL = 0xFF +}; + +#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 +#define IW_AUTH_ALG_FT 0x00000008 + +/******************************************************************************* + * 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 struct GLUE_INFO *prGlueInfo, + IN unsigned int u4Cmd, IN unsigned char *pucData, + IN unsigned int u4DataLen); + +struct iw_statistics *wext_get_wireless_stats( + struct net_device *prDev); + + +u_int8_t +wextSrchDesiredWPAIE(IN uint8_t *pucIEStart, + IN int32_t i4TotalIeLen, IN uint8_t ucDesiredElemId, + OUT uint8_t **ppucDesiredIE); + +#if CFG_SUPPORT_WPS +u_int8_t +wextSrchDesiredWPSIE(IN uint8_t *pucIEStart, + IN int32_t i4TotalIeLen, IN uint8_t ucDesiredElemId, + OUT uint8_t **ppucDesiredIE); +#endif + +#if CFG_SUPPORT_PASSPOINT +u_int8_t wextSrchDesiredHS20IE(IN uint8_t *pucIEStart, + IN int32_t i4TotalIeLen, + OUT uint8_t **ppucDesiredIE); + +u_int8_t wextSrchDesiredInterworkingIE(IN uint8_t + *pucIEStart, IN int32_t i4TotalIeLen, + OUT uint8_t **ppucDesiredIE); + +u_int8_t wextSrchDesiredAdvProtocolIE(IN uint8_t + *pucIEStart, IN int32_t i4TotalIeLen, + OUT uint8_t **ppucDesiredIE); + +u_int8_t wextSrchDesiredRoamingConsortiumIE( + IN uint8_t *pucIEStart, IN int32_t i4TotalIeLen, + OUT uint8_t **ppucDesiredIE); +u_int8_t wextSrchDesiredOsenIE(IN uint8_t *pucIEStart, + IN int32_t i4TotalIeLen, + OUT uint8_t **ppucDesiredIE); +#endif /* CFG_SUPPORT_PASSPOINT */ + +u_int8_t wextSrchDesiredWAPIIE(IN uint8_t *pucIEStart, + IN int32_t i4TotalIeLen, + OUT uint8_t **ppucDesiredIE); + +u_int8_t wextSrchOkcAndPMKID(IN uint8_t *pucIEStart, + IN int32_t i4TotalIeLen, + OUT uint8_t **ppucPMKID, + OUT uint8_t *okc); +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* WIRELESS_EXT */ + +#endif /* _GL_WEXT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_wext_priv.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_wext_priv.h new file mode 100644 index 0000000000000..5ae4fbb45e227 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/include/gl_wext_priv.h @@ -0,0 +1,599 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + * 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. + */ + + +#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 + +/* Stat CMD will have different format due to different algorithm support */ +#if (defined(MT6632) || defined(MT7668)) +#define CFG_SUPPORT_RA_GEN 0 +#define CFG_SUPPORT_TXPOWER_INFO 0 +#else +#define CFG_SUPPORT_RA_GEN 1 +#define CFG_SUPPORT_TXPOWER_INFO 1 +#endif + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +extern char *HW_TX_MODE_STR[]; +extern char *HW_TX_RATE_CCK_STR[]; +extern char *HW_TX_RATE_OFDM_STR[]; +extern char *HW_TX_RATE_BW[]; + +/******************************************************************************* + * 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) +#if CFG_MTK_ENGINEER_MODE_SUPPORT +#define IOCTL_SET_STRUCT_FOR_EM (SIOCIWFIRSTPRIV + 11) +#endif +#define IOCTL_SET_INTS (SIOCIWFIRSTPRIV + 12) +#define IOCTL_GET_INTS (SIOCIWFIRSTPRIV + 13) +#define IOCTL_SET_DRIVER (SIOCIWFIRSTPRIV + 14) +#define IOCTL_GET_DRIVER (SIOCIWFIRSTPRIV + 15) + +#if CFG_SUPPORT_QA_TOOL +#define IOCTL_QA_TOOL_DAEMON (SIOCIWFIRSTPRIV + 16) +#define IOCTL_IWPRIV_ATE (SIOCIWFIRSTPRIV + 17) +#endif + +#define IOC_AP_GET_STA_LIST (SIOCIWFIRSTPRIV+19) +#define IOC_AP_SET_MAC_FLTR (SIOCIWFIRSTPRIV+21) +#define IOC_AP_SET_CFG (SIOCIWFIRSTPRIV+23) +#define IOC_AP_STA_DISASSOC (SIOCIWFIRSTPRIV+25) + +#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 + +#if CFG_SUPPORT_QA_TOOL +#define PRIV_QACMD_SET 29 +#endif + +#define PRIV_CMD_MET_PROFILING 33 + +#if CFG_WOW_SUPPORT +#define PRIV_CMD_SET_WOW_ENABLE 34 +#define PRIV_CMD_SET_WOW_PAR 35 +#define MDNS_CMD_ENABLE 1 +#define MDNS_CMD_DISABLE 2 +#define MDNS_CMD_ADD_RECORD 3 +#define MDNS_CMD_DEL_RECORD 4 +#endif + +#define PRIV_CMD_SET_SER 37 + +#if CFG_SUPPORT_WAC +#define PRIV_CMD_WAC_IE 38 +#endif + +/* 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 +#define OID_CUSTOM_TEST_ICAP_MODE 0xFFA0C913 + +/* 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 + +#if CFG_SUPPORT_LOWLATENCY_MODE +#define OID_CUSTOM_LOWLATENCY_MODE 0xFFA0CC00 +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + +#define OID_IPC_WIFI_LOG_UI 0xFFA0CC01 +#define OID_IPC_WIFI_LOG_LEVEL 0xFFA0CC02 + +#if CFG_SUPPORT_NCHO +#define CMD_NCHO_COMP_TIMEOUT 1500 /* ms */ +#define CMD_NCHO_AF_DATA_LENGTH 1040 +#endif + +/* Define magic key of test mode (Don't change it for future compatibity) */ +#define PRIV_CMD_TEST_MAGIC_KEY 2011 +#define PRIV_CMD_TEST_MAGIC_KEY_ICAP 2013 + +/* Customized MCC stay time ratio and the stay time in units of us */ +#if CFG_SUPPORT_ADJUST_MCC_MODE_SET +#define MCC_TIME_3 29000 +#define MCC_TIME_5 48200 +#define MCC_TIME_7 67400 +#endif /*CFG_SUPPORT_ADJUST_MCC_MODE_SET*/ + +#if CFG_SUPPORT_ADVANCE_CONTROL +#define CMD_SW_DBGCTL_ADVCTL_SET_ID 0xa1260000 +#define CMD_SW_DBGCTL_ADVCTL_GET_ID 0xb1260000 + +#define CMD_SET_NOISE "SET_NOISE" +#define CMD_GET_NOISE "GET_NOISE" +#define CMD_TRAFFIC_REPORT "TRAFFIC_REPORT" +#define CMD_SET_POP "SET_POP" +#define CMD_GET_POP "GET_POP" +#define CMD_SET_ED "SET_ED" +#define CMD_GET_ED "GET_ED" +#define CMD_SET_PD "SET_PD" +#define CMD_GET_PD "GET_PD" +#define CMD_SET_MAX_RFGAIN "SET_MAX_RFGAIN" +#define CMD_GET_MAX_RFGAIN "GET_MAX_RFGAIN" +#define CMD_NOISE_HISTOGRAM "NOISE_HISTOGRAM" +#if CFG_RX_SINGLE_CHAIN_SUPPORT +#define CMD_SET_RXC "SET_RXC" +#define CMD_GET_RXC "GET_RXC" +#endif +#define CMD_COEX_CONTROL "COEX_CONTROL" +#define CMD_SET_ADM_CTRL "SET_ADM" +#define CMD_GET_ADM_CTRL "GET_ADM" +#define CMD_SET_BCN_TH "SET_BCN_TH" +#define CMD_GET_BCN_TH "GET_BCN_TH" +#define CMD_GET_BCNTIMEOUT_NUM "GET_BCNTIMEOUT_NUM" +#if CFG_ENABLE_1RPD_MMPS_CTRL +#define CMD_SET_1RPD "SET_1RPD" +#define CMD_GET_1RPD "GET_1RPD" +#define CMD_SET_MMPS "SET_MMPS" +#define CMD_GET_MMPS "GET_MMPS" +#endif /* CFG_ENABLE_1RPD_MMPS_CTRL */ +#if CFG_ENABLE_DEWEIGHTING_CTRL +#define CMD_SET_DEWEIGHTING_TH "SET_DEWEIGHTING_TH" +#define CMD_GET_DEWEIGHTING_TH "GET_DEWEIGHTING_TH" +#define CMD_GET_DEWEIGHTING_NOISE "GET_DEWEIGHTING_NOISE" +#define CMD_GET_DEWEIGHTING_WEIGHT "GET_DEWEIGHTING_WEIGHT" +#endif /* CFG_ENABLE_DEWEIGHTING_CTRL */ + +enum { + CMD_ADVCTL_NOISE_ID = 1, + CMD_ADVCTL_POP_ID, + CMD_ADVCTL_ED_ID, + CMD_ADVCTL_PD_ID, + CMD_ADVCTL_MAX_RFGAIN_ID, + CMD_ADVCTL_ADM_CTRL_ID, + CMD_ADVCTL_BCN_TH_ID = 9, + CMD_ADVCTL_DEWEIGHTING_TH_ID, + CMD_ADVCTL_DEWEIGHTING_NOISE_ID, + CMD_ADVCTL_DEWEIGHTING_WEIGHT_ID, + CMD_ADVCTL_ACT_INTV_ID, + CMD_ADVCTL_1RPD, + CMD_ADVCTL_MMPS, +#if CFG_RX_SINGLE_CHAIN_SUPPORT + CMD_ADVCTL_RXC_ID = 17, +#endif + CMD_ADVCTL_SNR_ID = 18, + CMD_ADVCTL_BCNTIMOUT_NUM_ID = 19, + CMD_ADVCTL_EVERY_TBTT_ID = 20, + CMD_ADVCTL_MAX +}; +#endif /* CFG_SUPPORT_ADVANCE_CONTROL */ + +#if (CFG_SUPPORT_TXPOWER_INFO == 1) +#define TX_POWER_SHOW_INFO 0x7 +#endif + +#define AGG_RANGE_SEL_NUM 7 +#define AGG_RANGE_SEL_0_MASK BITS(0, 7) +#define AGG_RANGE_SEL_0_OFFSET 0 +#define AGG_RANGE_SEL_1_MASK BITS(8, 15) +#define AGG_RANGE_SEL_1_OFFSET 8 +#define AGG_RANGE_SEL_2_MASK BITS(16, 23) +#define AGG_RANGE_SEL_2_OFFSET 16 +#define AGG_RANGE_SEL_3_MASK BITS(24, 31) +#define AGG_RANGE_SEL_3_OFFSET 24 +#define AGG_RANGE_SEL_4_MASK AGG_RANGE_SEL_0_MASK +#define AGG_RANGE_SEL_4_OFFSET AGG_RANGE_SEL_0_OFFSET +#define AGG_RANGE_SEL_5_MASK AGG_RANGE_SEL_1_MASK +#define AGG_RANGE_SEL_5_OFFSET AGG_RANGE_SEL_1_OFFSET +#define AGG_RANGE_SEL_6_MASK AGG_RANGE_SEL_2_MASK +#define AGG_RANGE_SEL_6_OFFSET AGG_RANGE_SEL_2_OFFSET + +enum { + COEX_REF_TABLE_ID_ISO_DETECTION_VALUE = 0, + COEX_REF_TABLE_ID_COEX_BT_PROFILE = 1, + COEX_REF_TABLE_ID_RX_BASIZE = 2, + COEX_REF_TABLE_ID_ARB_MODE = 3, + COEX_REF_TABLE_ID_PROT_FRM_TYPE = 4, + COEX_REF_TABLE_ID_CFG_COEXISOCTRL = 5, + COEX_REF_TABLE_ID_CFG_COEXMODECTRL = 6, + COEX_REF_TABLE_ID_CFG_FDDPERPKT = 7, + COEX_REF_TABLE_ID_CFG_BT_FIX_POWER = 8, + COEX_REF_TABLE_ID_CFG_BT_FDD_GAIN = 9, + COEX_REF_TABLE_ID_CFG_BT_FDD_POWER = 10, + COEX_REF_TABLE_ID_CFG_WF_FDD_POWER = 11, + COEX_REF_TABLE_ID_NUM +}; + +/* BT Profile macros */ +#define VAR_BT_PROF_MASK_ALL 0x0000FFFF +/* these defined name are the same as name in FW */ +#define VAR_BT_PROF_NONE 0x0000 +#define VAR_BT_PROF_SCO 0x0001 +#define VAR_BT_PROF_A2DP 0x0002 +#define VAR_BT_PROF_LINK_CONNECTED 0x0004 +#define VAR_BT_PROF_HID 0x0008 +#define VAR_BT_PROF_PAGE 0x0010 +#define VAR_BT_PROF_INQUIRY 0x0020 +#define VAR_BT_PROF_ESCO 0x0040 +#define VAR_BT_PROF_MULTI_HID 0x0080 +#define VAR_BT_PROF_BLE_VOBLE 0x0200 +#define VAR_BT_PROF_BT_A2DP_SINK 0x0400 + +#define COEX_BCM_IS_BT_NONE(x) \ +(((x) & VAR_BT_PROF_MASK_ALL) == VAR_BT_PROF_NONE) +#define COEX_BCM_IS_BT_SCO(x) ((x) & VAR_BT_PROF_SCO) +#define COEX_BCM_IS_BT_A2DP(x) ((x) & VAR_BT_PROF_A2DP) +#define COEX_BCM_IS_BT_LINK_CONNECTED(x) ((x) & VAR_BT_PROF_LINK_CONNECTED) +#define COEX_BCM_IS_BT_HID(x) ((x) & VAR_BT_PROF_HID) +#define COEX_BCM_IS_BT_PAGE(x) ((x) & VAR_BT_PROF_PAGE) +#define COEX_BCM_IS_BT_INQUIRY(x) ((x) & VAR_BT_PROF_INQUIRY) +#define COEX_BCM_IS_BT_ESCO(x) ((x) & VAR_BT_PROF_ESCO) +#define COEX_BCM_IS_BT_MULTI_HID(x) ((x) & VAR_BT_PROF_MULTI_HID) +#define COEX_BCM_IS_BT_BLE_VOBLE(x) ((x) & VAR_BT_PROF_BLE_VOBLE) +#define COEX_BCM_IS_BT_A2DP_SINK(x) ((x) & VAR_BT_PROF_BT_A2DP_SINK) + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +/* NIC BBCR configuration entry structure */ +struct PRIV_CONFIG_ENTRY { + uint8_t ucOffset; + uint8_t ucValue; +}; + +typedef uint32_t(*PFN_OID_HANDLER_FUNC_REQ) ( + IN void *prAdapter, + IN OUT void *pvBuf, IN uint32_t u4BufLen, + OUT uint32_t *pu4OutInfoLen); + +enum ENUM_OID_METHOD { + ENUM_OID_GLUE_ONLY, + ENUM_OID_GLUE_EXTENSION, + ENUM_OID_DRIVER_CORE +}; + +/* OID set/query processing entry */ +struct WLAN_REQ_ENTRY { + uint32_t rOid; /* OID */ + uint8_t *pucOidName; /* OID name text */ + u_int8_t fgQryBufLenChecking; + u_int8_t fgSetBufLenChecking; + enum ENUM_OID_METHOD eOidMethod; + uint32_t u4InfoBufLen; + PFN_OID_HANDLER_FUNC_REQ pfOidQueryHandler; /* PFN_OID_HANDLER_FUNC */ + PFN_OID_HANDLER_FUNC_REQ pfOidSetHandler; /* PFN_OID_HANDLER_FUNC */ +}; + +struct NDIS_TRANSPORT_STRUCT { + uint32_t ndisOidCmd; + uint32_t inNdisOidlength; + uint32_t outNdisOidLength; + uint8_t ndisOidContent[16]; +}; + +enum AGG_RANGE_TYPE_T { + ENUM_AGG_RANGE_TYPE_TX = 0, + ENUM_AGG_RANGE_TYPE_TRX = 1, + ENUM_AGG_RANGE_TYPE_RX = 2 +}; + +#if CFG_SUPPORT_ADJUST_MCC_MODE_SET +enum ENUM_MCC_MODE { + MCC_FAIR, + MCC_FAV_STA, + MCC_FAV_P2P, + MCC_MODE_NUM +}; +#endif + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +#define HW_TX_RATE_TO_MODE(_x) (((_x) & (0x7 << 6)) >> 6) +#define HW_TX_RATE_TO_MCS(_x, _mode) ((_x) & (0x3f)) +#define HW_TX_RATE_TO_NSS(_x) (((_x) & (0x3 << 9)) >> 9) +#define HW_TX_RATE_TO_STBC(_x) (((_x) & (0x1 << 11)) >> 11) + +#define TX_VECTOR_GET_TX_RATE(_txv) (((_txv)->u4TxVector1) & \ + BITS(0, 6)) +#define TX_VECTOR_GET_TX_LDPC(_txv) ((((_txv)->u4TxVector1) >> 7) & \ + BIT(0)) +#define TX_VECTOR_GET_TX_STBC(_txv) ((((_txv)->u4TxVector1) >> 8) & \ + BITS(0, 1)) +#define TX_VECTOR_GET_TX_FRMODE(_txv) ((((_txv)->u4TxVector1) >> 10) & \ + BITS(0, 1)) +#define TX_VECTOR_GET_TX_MODE(_txv) ((((_txv)->u4TxVector1) >> 12) & \ + BITS(0, 2)) +#define TX_VECTOR_GET_TX_NSTS(_txv) ((((_txv)->u4TxVector1) >> 21) & \ + BITS(0, 1)) +#define TX_VECTOR_GET_TX_PWR(_txv) ( \ + ((_txv)->u4TxVector1 & BIT(30)) \ + ? ((((_txv)->u4TxVector1 >> 24) & \ + BITS(0, 6)) - 0x80) \ + : (((_txv)->u4TxVector1 >> 24) & \ + BITS(0, 6)) \ + ) +#define TX_VECTOR_GET_BF_EN(_txv) ((((_txv)->u4TxVector2) >> 31) & \ + BIT(0)) +#define TX_VECTOR_GET_DYN_BW(_txv) ((((_txv)->u4TxVector4) >> 31) & \ + BIT(0)) +#define TX_VECTOR_GET_NO_SOUNDING(_txv) ((((_txv)->u4TxVector4) >> 28) & \ + BIT(0)) +#define TX_VECTOR_GET_TX_SGI(_txv) ((((_txv)->u4TxVector4) >> 27) & \ + BIT(0)) + +#define TX_RATE_MODE_CCK 0 +#define TX_RATE_MODE_OFDM 1 +#define TX_RATE_MODE_HTMIX 2 +#define TX_RATE_MODE_HTGF 3 +#define TX_RATE_MODE_VHT 4 +#define MAX_TX_MODE 5 + +/******************************************************************************* + * 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); + +#if CFG_SUPPORT_NCHO +uint8_t CmdString2HexParse(IN uint8_t *InStr, + OUT uint8_t **OutStr, OUT uint8_t *OutLen); +#endif + +int +priv_set_driver(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN OUT char *pcExtra); + +int +priv_set_ap(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); + +int priv_support_driver_cmd(IN struct net_device *prDev, + IN OUT struct ifreq *prReq, IN int i4Cmd); + +#ifdef CFG_ANDROID_AOSP_PRIV_CMD +int android_private_support_driver_cmd(IN struct net_device *prDev, +IN OUT struct ifreq *prReq, IN int i4Cmd); +#endif /* CFG_ANDROID_AOSP_PRIV_CMD */ + +int32_t priv_driver_cmds(IN struct net_device *prNetDev, + IN int8_t *pcCommand, IN int32_t i4TotalLen); + +int priv_driver_set_cfg(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen); + +#if CFG_SUPPORT_QA_TOOL +int +priv_ate_set(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN char *pcExtra); +#endif + +char *hw_rate_ofdm_str(uint16_t ofdm_idx); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _GL_WEXT_PRIV_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/platform.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/platform.c new file mode 100644 index 0000000000000..987e967ff0c43 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/linux/platform.c @@ -0,0 +1,558 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux + * /platform.c#3 + */ + +/*! \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 + * + */ + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include +#include +#include +#include +#include + +#include +#include "precomp.h" +#include "gl_os.h" + +#if CFG_ENABLE_EARLY_SUSPEND +#include +#endif + +/******************************************************************************* + * 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 + ******************************************************************************* + */ +#if 1 +static int netdev_event(struct notifier_block *nb, + unsigned long notification, void *ptr) +{ + struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; + struct net_device *prDev = ifa->ifa_dev->dev; + struct GLUE_INFO *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; + } +#if 0 /* CFG_SUPPORT_PASSPOINT */ + { + prGlueInfo->fgIsDad = FALSE; + } +#endif /* CFG_SUPPORT_PASSPOINT */ + if ((prDev != gPrDev) && (prDev != gPrP2pDev[0]) + && (prDev != gPrP2pDev[1])) { + /* DBGLOG(REQ, INFO, ("netdev_event: device is not mine.\n")); + */ + return NOTIFY_DONE; + } + + + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + if (prGlueInfo == NULL) { + DBGLOG(REQ, INFO, "netdev_event: prGlueInfo is empty.\n"); + return NOTIFY_DONE; + } + + if (prGlueInfo->fgIsInSuspendMode == FALSE) { + /* DBGLOG(REQ, INFO, + * ("netdev_event: PARAM_MEDIA_STATE_DISCONNECTED. (%d)\n", + * prGlueInfo->eParamMediaStateIndicated)); + */ + return NOTIFY_DONE; + } + + kalSetNetAddressFromInterface(prGlueInfo, prDev, TRUE); + + return NOTIFY_DONE; + +} +#endif +#if 0 /* CFG_SUPPORT_PASSPOINT */ +static int net6dev_event(struct notifier_block *nb, + unsigned long notification, void *ptr) +{ + struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr; + struct net_device *prDev = ifa->idev->dev; + struct GLUE_INFO *prGlueInfo = NULL; + + if (prDev == NULL) { + DBGLOG(REQ, INFO, "net6dev_event: device is empty.\n"); + return NOTIFY_DONE; + } + + if ((strncmp(prDev->name, "p2p", 3) != 0) + && (strncmp(prDev->name, "wlan", 4) != 0)) { + DBGLOG(REQ, INFO, "net6dev_event: xxx\n"); + return NOTIFY_DONE; + } + + if (strncmp(prDev->name, "p2p", 3) == 0) { + /* because we store the address of prGlueInfo in p2p's private + * date of net device + */ + /* *((P_GLUE_INFO_T *) netdev_priv( + * prGlueInfo->prP2PInfo[0]->prDevHandler)) = prGlueInfo; + */ + prGlueInfo = *((struct GLUE_INFO **) netdev_priv(prDev)); + } else { /* wlan0 */ + prGlueInfo = (struct GLUE_INFO *) netdev_priv(prDev); + } + + if (prGlueInfo == NULL) { + DBGLOG(REQ, INFO, "netdev_event: prGlueInfo is empty.\n"); + return NOTIFY_DONE; + } + + prGlueInfo->fgIs6Dad = FALSE; + + return NOTIFY_DONE; +} +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if 1 /* unused */ +static struct notifier_block inetaddr_notifier = { + .notifier_call = netdev_event, +}; +#endif + +#if 0 /* CFG_SUPPORT_PASSPOINT */ +static struct notifier_block inet6addr_notifier = { + .notifier_call = net6dev_event, +}; +#endif /* CFG_SUPPORT_PASSPOINT */ + +void wlanRegisterNotifier(void) +{ +#if CFG_ENABLE_NET_DEV_NOTIFY + + register_inetaddr_notifier(&inetaddr_notifier); +#if 0 /* CFG_SUPPORT_PASSPOINT */ + register_inet6addr_notifier(&inet6addr_notifier); +#endif /* CFG_SUPPORT_PASSPOINT */ + +#endif +} + +void wlanUnregisterNotifier(void) +{ +#if CFG_ENABLE_NET_DEV_NOTIFY + + unregister_inetaddr_notifier(&inetaddr_notifier); +#if 0 /* CFG_SUPPORT_PASSPOINT */ + unregister_inetaddr_notifier(&inet6addr_notifier); +#endif /* CFG_SUPPORT_PASSPOINT */ + +#endif +} + +#if CFG_ENABLE_EARLY_SUSPEND +/*----------------------------------------------------------------------------*/ +/*! + * \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 (wlanSuspend != NULL) + prDesc->suspend = wlanSuspend; + else { + DBGLOG(REQ, INFO, + "glRegisterEarlySuspend wlanSuspend ERROR.\n"); + ret = -1; + } + + if (wlanResume != NULL) + prDesc->resume = wlanResume; + else { + DBGLOG(REQ, INFO, + "glRegisterEarlySuspend wlanResume ERROR.\n"); + ret = -1; + } + + register_early_suspend(prDesc); + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \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; +#if KERNEL_VERSION(4, 4, 0) <= LINUX_VERSION_CODE + loff_t pos; + char __user *p; +#endif + + 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, "[nvram_read] : failed to open!!\n"); + set_fs(old_fs); + return -1; + } + + do { + if (fd->f_op == NULL) { + DBGLOG(INIT, INFO, "[nvram_read] : f_op is NULL!!\n"); + break; + } + + if (fd->f_pos != offset) { + if (fd->f_op->llseek) { + if (fd->f_op->llseek(fd, offset, 0) != offset) { + DBGLOG(INIT, INFO, + "[nvram_read] : failed to seek!!\n"); + break; + } + } else { + fd->f_pos = offset; + } + } + +#if KERNEL_VERSION(4, 4, 0) <= LINUX_VERSION_CODE + p = (__force char __user *)buf; + pos = (loff_t)offset; + + retLen = __vfs_read(fd, p, len, &pos); +#else + retLen = fd->f_op->read(fd, buf, len, &fd->f_pos); +#endif + if (retLen < 0) + DBGLOG(INIT, ERROR, + "[nvram_read] : read failed!! Error code: %d\n", + retLen); + } 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; +#if KERNEL_VERSION(4, 4, 0) <= LINUX_VERSION_CODE + loff_t pos; + char __user *p; +#endif + + 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, "[nvram_write] : failed to open!!\n"); + set_fs(old_fs); + return -1; + } + + do { + if (fd->f_op == NULL) { + DBGLOG(INIT, INFO, "[nvram_write] : f_op is NULL!!\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, + "[nvram_write] : failed to seek!!\n"); + break; + } + } else { + fd->f_pos = offset; + } + } + +#if KERNEL_VERSION(4, 4, 0) <= LINUX_VERSION_CODE + p = (__force char __user *)buf; + pos = (loff_t)offset; + + retLen = __vfs_write(fd, p, len, &pos); +#else + retLen = fd->f_op->write(fd, buf, len, &fd->f_pos); +#endif + if (retLen < 0) + DBGLOG(INIT, ERROR, + "[nvram_write] : write failed!! Error code: %d\n", + retLen); + } 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 with flexible length. + * + * \param[in] + * prGlueInfo + * u4Offset + * len + * \param[out] + * pu2Data + * \return + * TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalCfgDataRead(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Offset, + IN ssize_t len, OUT uint16_t *pu2Data) +{ + if (pu2Data == NULL) + return FALSE; + + if (nvram_read(WIFI_NVRAM_FILE_NAME, + (char *)pu2Data, len, u4Offset) != len) { + return FALSE; + } else { + return TRUE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief API for reading data on NVRAM with 2 bytes fixed length. + * + * \param[in] + * prGlueInfo + * u4Offset + * \param[out] + * pu2Data + * \return + * TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalCfgDataRead16(IN struct GLUE_INFO *prGlueInfo, + IN uint32_t u4Offset, OUT uint16_t *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 with 2 bytes fixed length. + * + * \param[in] + * prGlueInfo + * u4Offset + * u2Data + * \return + * TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +u_int8_t kalCfgDataWrite16(IN struct GLUE_INFO *prGlueInfo, + uint32_t u4Offset, uint16_t u2Data) +{ + if (nvram_write(WIFI_NVRAM_FILE_NAME, + (char *)&u2Data, sizeof(unsigned short), + u4Offset) != sizeof(unsigned short)) { + return FALSE; + } else { + return TRUE; + } +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/version.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/version.h new file mode 100644 index 0000000000000..26273a1d93543 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/os/version.h @@ -0,0 +1,138 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/version.h#1 + */ + +/*! \file "version.h" + * \brief Driver's version definition + * + */ + + +#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 +#define NIC_NAME "MT6632" +#define NIC_DEVICE_ID "MT6632" +#define NIC_DEVICE_ID_LOW "mt6632" +#endif + +/* NIC driver information */ +#define NIC_VENDOR "MediaTek Inc." +#define NIC_VENDOR_OUI {0x00, 0x0C, 0xE7} + +#define NIC_PRODUCT_NAME "MediaTek Inc. Wireless LAN Adapter" +#define NIC_DRIVER_NAME "MediaTek Inc. Wireless LAN Adapter Driver" + +/* Define our driver version */ +#define NIC_DRIVER_MAJOR_VERSION 1 +#define NIC_DRIVER_MINOR_VERSION 0 +#define NIC_DRIVER_SERIAL_VERSION 1 +#define NIC_DRIVER_VERSION (NIC_DRIVER_MAJOR_VERSION, \ + NIC_DRIVER_MINOR_VERSION, \ + NIC_DRIVER_SERIAL_VERSION) +#define NIC_DRIVER_VERSION_STRING "1.0.1" + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _VERSION_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/prealloc/include/prealloc.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/prealloc/include/prealloc.h new file mode 100644 index 0000000000000..b92d39eb4426d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/prealloc/include/prealloc.h @@ -0,0 +1,120 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2017 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2017 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "prealloc.h" +* \brief This file contains the declairation of memory preallocation module +*/ + +/******************************************************************************* +* C O M P I L E 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 _PREALLOC_H +#define _PREALLOC_H + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +enum ENUM_MEM_ID { + MEM_ID_NIC_ADAPTER, + MEM_ID_IO_BUFFER, +#if defined(_HIF_SDIO) + MEM_ID_IO_CTRL, + MEM_ID_RX_DATA, +#endif +#if defined(_HIF_USB) + MEM_ID_TX_CMD, + MEM_ID_TX_DATA_FFA, + MEM_ID_TX_DATA, + MEM_ID_RX_EVENT, + MEM_ID_RX_DATA, +#endif + + MEM_ID_NUM, /* END, Do not modify */ +}; + +/******************************************************************************* +* P U B 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 MP_Dbg(_Fmt...) pr_info("[wlan][MemPrealloc] " _Fmt) +#define MP_Info(_Fmt...) pr_info("[wlan][MemPrealloc] " _Fmt) +#define MP_Err(_Fmt...) pr_info("[wlan][MemPrealloc] " _Fmt) + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +void *preallocGetMem(enum ENUM_MEM_ID memId); + +#endif /* _PREALLOC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/prealloc/prealloc.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/prealloc/prealloc.c new file mode 100644 index 0000000000000..78715b15dd7bc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/prealloc/prealloc.c @@ -0,0 +1,314 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2017 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2017 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file prealloc.c +* \brief memory preallocation module +* +* This file contains all implementations of memory preallocation module +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* + * ----------------- ---------------- ---------- + * | PRE_MEM_BLOCK |-pItemArray->| PRE_MEM_ITEM |-pvBuffer->| Memory | + * |---------------| |--------------| ---------- + * | PRE_MEM_BLOCK |->... | PRE_MEM_ITEM |-pvBuffer->---------- + * |---------------| |--------------| | Memory | + * . . ---------- + * . . + * . . + */ +struct PRE_MEM_ITEM { + void *pvBuffer; +}; + +struct PRE_MEM_BLOCK { + uint8_t *pucName; + struct PRE_MEM_ITEM *pItemArray; + uint32_t u4Count; + uint32_t u4Size; + uint32_t u4KmallocFlags; + uint32_t u4Curr; +}; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +MODULE_LICENSE("Dual BSD/GPL"); + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static int32_t blockCount; +static struct PRE_MEM_BLOCK arMemBlocks[MEM_ID_NUM]; + +/******************************************************************************* +* M A 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 export function for memory preallocation +* +* \param[in] memId memory id. +* +* \retval void pointer to the memory address +*/ +/*----------------------------------------------------------------------------*/ +void *preallocGetMem(enum ENUM_MEM_ID memId) +{ + struct PRE_MEM_BLOCK *block = NULL; + uint32_t curr = 0, count = 0; + uint8_t *name = NULL; + + /* check memId exist */ + if (memId < 0 || memId >= MEM_ID_NUM) { + MP_Err("request wrong memId %d", memId); + return NULL; + } + + block = &arMemBlocks[memId]; + curr = block->u4Curr; + count = block->u4Count; + name = block->pucName; + block->u4Curr = (curr + 1) % count; /* point to next */ + + /* return request memory address */ + MP_Dbg("request [%s], return [%d]\n", name, curr); + return block->pItemArray[curr].pvBuffer; +} +EXPORT_SYMBOL(preallocGetMem); + +static void preallocFree(void) +{ + int32_t i = 0, j = 0; + struct PRE_MEM_BLOCK *block = NULL; + struct PRE_MEM_ITEM *items = NULL; + void *memory = NULL; + + for (i = 0; i < MEM_ID_NUM; i++) { + block = &arMemBlocks[i]; + MP_Info("free [%d], block name=\"%s\" count=%d size=%d\n", + i, block->pucName, block->u4Count, + block->u4Size); + items = block->pItemArray; + if (items == NULL) + continue; + /* free memory */ + for (j = 0; j < block->u4Count; j++) { + memory = items[j].pvBuffer; + MP_Dbg(" - [%d] memory 0x%p\n", j, memory); + kfree(memory); + } + /* free items */ + MP_Dbg(" - items 0x%p\n", items); + kfree(items); + memset(block, 0, sizeof(*block)); + } +} + +static int preallocAlloc(void) +{ + int32_t i = 0, j = 0; + struct PRE_MEM_BLOCK *block = NULL; + struct PRE_MEM_ITEM *items = NULL; + void *memory = NULL; + + for (i = 0; i < MEM_ID_NUM; i++) { + block = &arMemBlocks[i]; + MP_Info("allocate [%d] block name=\"%s\" count=%d size=%d\n", + i, block->pucName, block->u4Count, + block->u4Size); + /* allocate u4Count items */ + items = kcalloc(block->u4Count, sizeof(*items), GFP_KERNEL); + if (items == NULL) { + MP_Err("allocate [%d] items failed\n", i); + goto fail; + } + MP_Dbg(" + items 0x%p\n", items); + block->pItemArray = items; + for (j = 0; j < block->u4Count; j++) { + /* allocate u4Size memory */ + memory = kmalloc(block->u4Size, block->u4KmallocFlags); + if (memory == NULL) { + MP_Err("allocate [%d][%d] memory failed\n", + i, j); + goto fail; + } + MP_Dbg(" + [%d] memory 0x%p\n", j, memory); + items[j].pvBuffer = memory; + } + } + + return 0; + +fail: + preallocFree(); + return -ENOMEM; +} + +static void preallocAddBlock(enum ENUM_MEM_ID memId, + uint8_t *name, uint32_t count, uint32_t size, + uint32_t kmallocFlags) +{ + if (memId != blockCount) { + MP_Err("memId %d != index %d\n", memId, blockCount); + return; + } + arMemBlocks[blockCount].pucName = name; + arMemBlocks[blockCount].pItemArray = NULL; + arMemBlocks[blockCount].u4Count = count; + arMemBlocks[blockCount].u4Size = size; + arMemBlocks[blockCount].u4KmallocFlags = kmallocFlags; + arMemBlocks[blockCount].u4Curr = 0; + blockCount++; +} + +static int __init preallocInit(void) +{ + uint32_t u4Size; + + blockCount = 0; + + /* ADD BLOCK START, follow the sequence of ENUM_MEM_ID */ + preallocAddBlock(MEM_ID_NIC_ADAPTER, "NIC ADAPTER MEMORY", + 1, MGT_BUFFER_SIZE, + GFP_KERNEL); + + u4Size = HIF_TX_COALESCING_BUFFER_SIZE; + u4Size = u4Size > HIF_RX_COALESCING_BUFFER_SIZE ? + u4Size : HIF_RX_COALESCING_BUFFER_SIZE; + + preallocAddBlock(MEM_ID_IO_BUFFER, "IO BUFFER", + 1, u4Size, + GFP_KERNEL); + +#if defined(_HIF_SDIO) + preallocAddBlock(MEM_ID_IO_CTRL, "IO CTRL", + 1, sizeof(struct ENHANCE_MODE_DATA_STRUCT), + GFP_KERNEL); + preallocAddBlock(MEM_ID_RX_DATA, "RX DATA", + HIF_RX_COALESCING_BUF_COUNT, + HIF_RX_COALESCING_BUFFER_SIZE, + GFP_KERNEL); +#endif +#if defined(_HIF_USB) + preallocAddBlock(MEM_ID_TX_CMD, "TX CMD", + USB_REQ_TX_CMD_CNT, USB_TX_CMD_BUF_SIZE, + GFP_KERNEL); + preallocAddBlock(MEM_ID_TX_DATA_FFA, "TX DATA FFA", + USB_REQ_TX_DATA_FFA_CNT, USB_TX_DATA_BUFF_SIZE, + GFP_KERNEL); +#if CFG_USB_TX_AGG + preallocAddBlock(MEM_ID_TX_DATA, "TX AGG DATA", + (USB_TC_NUM * USB_REQ_TX_DATA_CNT), + USB_TX_DATA_BUFF_SIZE, + GFP_KERNEL); +#else + preallocAddBlock(MEM_ID_TX_DATA, "TX DATA", + USB_REQ_TX_DATA_CNT, USB_TX_DATA_BUFF_SIZE, + GFP_KERNEL); +#endif + preallocAddBlock(MEM_ID_RX_EVENT, "RX EVENT", + USB_REQ_RX_EVENT_CNT, USB_RX_EVENT_BUF_SIZE, + GFP_KERNEL); + preallocAddBlock(MEM_ID_RX_DATA, "RX DATA", + USB_REQ_RX_DATA_CNT, USB_RX_DATA_BUF_SIZE, + GFP_KERNEL); +#endif + /* ADD BLOCK END */ + + return preallocAlloc(); +} + +static void __exit preallocExit(void) +{ + preallocFree(); +} + +module_init(preallocInit); +module_exit(preallocExit); From 34a6fc31b8803cbab2ac0bc9ca43932f5b49af40 Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 22:20:11 +0800 Subject: [PATCH 27/32] Add files via upload --- .../core/gen4-mt7663/include/CFG_Wifi_File.h | 359 ++ .../include/chips/cmm_asic_connac.h | 143 + .../core/gen4-mt7663/include/chips/connac.h | 129 + .../gen4-mt7663/include/chips/connac2x2.h | 129 + .../core/gen4-mt7663/include/chips/dma_sch.h | 199 + .../core/gen4-mt7663/include/chips/fw_dl.h | 295 ++ .../core/gen4-mt7663/include/chips/host_csr.h | 69 + .../core/gen4-mt7663/include/chips/mt6632.h | 118 + .../core/gen4-mt7663/include/chips/mt7663.h | 124 + .../core/gen4-mt7663/include/chips/mt7668.h | 120 + .../wlan/core/gen4-mt7663/include/chips/pse.h | 274 + .../core/gen4-mt7663/include/chips/wf_ple.h | 231 + .../wlan/core/gen4-mt7663/include/config.h | 1401 +++++ .../wlan/core/gen4-mt7663/include/debug.h | 474 ++ .../wlan/core/gen4-mt7663/include/hif_cmm.h | 136 + .../wlan/core/gen4-mt7663/include/link.h | 524 ++ .../core/gen4-mt7663/include/mgmt/aa_fsm.h | 261 + .../core/gen4-mt7663/include/mgmt/ais_fsm.h | 601 +++ .../gen4-mt7663/include/mgmt/ap_selection.h | 20 + .../core/gen4-mt7663/include/mgmt/assoc.h | 150 + .../wlan/core/gen4-mt7663/include/mgmt/auth.h | 174 + .../core/gen4-mt7663/include/mgmt/bow_fsm.h | 189 + .../wlan/core/gen4-mt7663/include/mgmt/bss.h | 272 + .../wlan/core/gen4-mt7663/include/mgmt/cnm.h | 429 ++ .../core/gen4-mt7663/include/mgmt/cnm_mem.h | 1177 +++++ .../core/gen4-mt7663/include/mgmt/cnm_scan.h | 164 + .../core/gen4-mt7663/include/mgmt/cnm_timer.h | 260 + .../core/gen4-mt7663/include/mgmt/hem_mbox.h | 366 ++ .../wlan/core/gen4-mt7663/include/mgmt/hs20.h | 205 + .../wlan/core/gen4-mt7663/include/mgmt/mib.h | 189 + .../core/gen4-mt7663/include/mgmt/p2p_assoc.h | 104 + .../core/gen4-mt7663/include/mgmt/p2p_bss.h | 109 + .../core/gen4-mt7663/include/mgmt/p2p_dev.h | 268 + .../gen4-mt7663/include/mgmt/p2p_dev_state.h | 106 + .../core/gen4-mt7663/include/mgmt/p2p_fsm.h | 87 + .../core/gen4-mt7663/include/mgmt/p2p_func.h | 427 ++ .../core/gen4-mt7663/include/mgmt/p2p_ie.h | 102 + .../core/gen4-mt7663/include/mgmt/p2p_rlm.h | 136 + .../gen4-mt7663/include/mgmt/p2p_rlm_obss.h | 118 + .../core/gen4-mt7663/include/mgmt/p2p_role.h | 483 ++ .../gen4-mt7663/include/mgmt/p2p_role_state.h | 146 + .../core/gen4-mt7663/include/mgmt/p2p_scan.h | 125 + .../core/gen4-mt7663/include/mgmt/privacy.h | 289 ++ .../core/gen4-mt7663/include/mgmt/qosmap.h | 121 + .../wlan/core/gen4-mt7663/include/mgmt/rate.h | 133 + .../wlan/core/gen4-mt7663/include/mgmt/rlm.h | 706 +++ .../gen4-mt7663/include/mgmt/rlm_domain.h | 1052 ++++ .../core/gen4-mt7663/include/mgmt/rlm_obss.h | 148 + .../gen4-mt7663/include/mgmt/rlm_protection.h | 142 + .../gen4-mt7663/include/mgmt/rlm_txpwr_init.h | 1595 ++++++ .../gen4-mt7663/include/mgmt/roaming_fsm.h | 217 + .../wlan/core/gen4-mt7663/include/mgmt/rsn.h | 356 ++ .../wlan/core/gen4-mt7663/include/mgmt/scan.h | 950 ++++ .../core/gen4-mt7663/include/mgmt/stats.h | 105 + .../wlan/core/gen4-mt7663/include/mgmt/swcr.h | 269 + .../wlan/core/gen4-mt7663/include/mgmt/tdls.h | 491 ++ .../wlan/core/gen4-mt7663/include/mgmt/wapi.h | 134 + .../gen4-mt7663/include/mgmt/wlan_typedef.h | 139 + .../wlan/core/gen4-mt7663/include/mgmt/wmm.h | 207 + .../wlan/core/gen4-mt7663/include/mgmt/wnm.h | 184 + .../core/gen4-mt7663/include/nic/adapter.h | 1784 +++++++ .../wlan/core/gen4-mt7663/include/nic/bow.h | 266 + .../core/gen4-mt7663/include/nic/cmd_buf.h | 215 + .../gen4-mt7663/include/nic/connac_dmashdl.h | 458 ++ .../core/gen4-mt7663/include/nic/connac_reg.h | 266 + .../wlan/core/gen4-mt7663/include/nic/hal.h | 1220 +++++ .../core/gen4-mt7663/include/nic/hif_rx.h | 156 + .../core/gen4-mt7663/include/nic/hif_tx.h | 171 + .../wlan/core/gen4-mt7663/include/nic/mac.h | 3380 ++++++++++++ .../core/gen4-mt7663/include/nic/mt66xx_reg.h | 1117 ++++ .../wlan/core/gen4-mt7663/include/nic/nic.h | 525 ++ .../core/gen4-mt7663/include/nic/nic_rate.h | 159 + .../core/gen4-mt7663/include/nic/nic_rx.h | 1200 +++++ .../core/gen4-mt7663/include/nic/nic_tx.h | 1934 +++++++ .../core/gen4-mt7663/include/nic/nic_umac.h | 140 + .../wlan/core/gen4-mt7663/include/nic/p2p.h | 357 ++ .../gen4-mt7663/include/nic/p2p_cmd_buf.h | 121 + .../core/gen4-mt7663/include/nic/p2p_mac.h | 438 ++ .../core/gen4-mt7663/include/nic/p2p_nic.h | 116 + .../include/nic/p2p_nic_cmd_event.h | 122 + .../core/gen4-mt7663/include/nic/que_mgt.h | 1198 +++++ .../core/gen4-mt7663/include/nic/wlan_def.h | 1246 +++++ .../core/gen4-mt7663/include/nic_cmd_event.h | 4624 +++++++++++++++++ .../gen4-mt7663/include/nic_init_cmd_event.h | 307 ++ .../core/gen4-mt7663/include/p2p_precomp.h | 247 + .../core/gen4-mt7663/include/p2p_typedef.h | 246 + .../wlan/core/gen4-mt7663/include/precomp.h | 314 ++ .../wlan/core/gen4-mt7663/include/pwr_mgt.h | 156 + .../wlan/core/gen4-mt7663/include/queue.h | 241 + .../wlan/core/gen4-mt7663/include/rftest.h | 434 ++ .../wlan/core/gen4-mt7663/include/typedef.h | 204 + .../wlan/core/gen4-mt7663/include/wlan_bow.h | 302 ++ .../wlan/core/gen4-mt7663/include/wlan_lib.h | 1815 +++++++ .../wlan/core/gen4-mt7663/include/wlan_oid.h | 4240 +++++++++++++++ .../wlan/core/gen4-mt7663/include/wlan_p2p.h | 318 ++ 95 files changed, 48668 insertions(+) create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/CFG_Wifi_File.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/cmm_asic_connac.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/connac.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/connac2x2.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/dma_sch.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/fw_dl.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/host_csr.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/mt6632.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/mt7663.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/mt7668.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/pse.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/wf_ple.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/config.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/debug.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/hif_cmm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/link.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/aa_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/ais_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/ap_selection.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/assoc.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/auth.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/bow_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/bss.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/cnm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/cnm_mem.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/cnm_scan.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/cnm_timer.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/hem_mbox.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/hs20.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/mib.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_assoc.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_bss.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_dev.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_dev_state.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_func.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_ie.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_rlm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_rlm_obss.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_role.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_role_state.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_scan.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/privacy.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/qosmap.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rate.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rlm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rlm_domain.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rlm_obss.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rlm_protection.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rlm_txpwr_init.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/roaming_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rsn.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/scan.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/stats.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/swcr.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/tdls.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/wapi.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/wlan_typedef.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/wmm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/wnm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/adapter.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/bow.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/cmd_buf.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/connac_dmashdl.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/connac_reg.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/hal.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/hif_rx.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/hif_tx.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/mac.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/mt66xx_reg.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/nic.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/nic_rate.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/nic_rx.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/nic_tx.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/nic_umac.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/p2p.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/p2p_cmd_buf.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/p2p_mac.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/p2p_nic.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/p2p_nic_cmd_event.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/que_mgt.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/wlan_def.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic_cmd_event.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic_init_cmd_event.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/p2p_precomp.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/p2p_typedef.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/precomp.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/pwr_mgt.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/queue.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/rftest.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/typedef.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/wlan_bow.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/wlan_lib.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/wlan_oid.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/wlan_p2p.h diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/CFG_Wifi_File.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/CFG_Wifi_File.h new file mode 100644 index 0000000000000..1f8b88307575e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/CFG_Wifi_File.h @@ -0,0 +1,359 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** 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. + */ + +#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 */ +struct TX_PWR_PARAM { + int8_t cTxPwr2G4Cck; /* signed, in unit of 0.5dBm */ + int8_t cTxPwr2G4Dsss; /* signed, in unit of 0.5dBm */ + int8_t acReserved[2]; + + int8_t cTxPwr2G4OFDM_BPSK; + int8_t cTxPwr2G4OFDM_QPSK; + int8_t cTxPwr2G4OFDM_16QAM; + int8_t cTxPwr2G4OFDM_Reserved; + int8_t cTxPwr2G4OFDM_48Mbps; + int8_t cTxPwr2G4OFDM_54Mbps; + + int8_t cTxPwr2G4HT20_BPSK; + int8_t cTxPwr2G4HT20_QPSK; + int8_t cTxPwr2G4HT20_16QAM; + int8_t cTxPwr2G4HT20_MCS5; + int8_t cTxPwr2G4HT20_MCS6; + int8_t cTxPwr2G4HT20_MCS7; + + int8_t cTxPwr2G4HT40_BPSK; + int8_t cTxPwr2G4HT40_QPSK; + int8_t cTxPwr2G4HT40_16QAM; + int8_t cTxPwr2G4HT40_MCS5; + int8_t cTxPwr2G4HT40_MCS6; + int8_t cTxPwr2G4HT40_MCS7; + + int8_t cTxPwr5GOFDM_BPSK; + int8_t cTxPwr5GOFDM_QPSK; + int8_t cTxPwr5GOFDM_16QAM; + int8_t cTxPwr5GOFDM_Reserved; + int8_t cTxPwr5GOFDM_48Mbps; + int8_t cTxPwr5GOFDM_54Mbps; + + int8_t cTxPwr5GHT20_BPSK; + int8_t cTxPwr5GHT20_QPSK; + int8_t cTxPwr5GHT20_16QAM; + int8_t cTxPwr5GHT20_MCS5; + int8_t cTxPwr5GHT20_MCS6; + int8_t cTxPwr5GHT20_MCS7; + + int8_t cTxPwr5GHT40_BPSK; + int8_t cTxPwr5GHT40_QPSK; + int8_t cTxPwr5GHT40_16QAM; + int8_t cTxPwr5GHT40_MCS5; + int8_t cTxPwr5GHT40_MCS6; + int8_t cTxPwr5GHT40_MCS7; +}; + +struct TX_AC_PWR { + int8_t c11AcTxPwr_BPSK; + int8_t c11AcTxPwr_QPSK; + int8_t c11AcTxPwr_16QAM; + int8_t c11AcTxPwr_MCS5_MCS6; + int8_t c11AcTxPwr_MCS7; + int8_t c11AcTxPwr_MCS8; + int8_t c11AcTxPwr_MCS9; + int8_t c11AcTxPwrVht40_OFFSET; + int8_t c11AcTxPwrVht80_OFFSET; + int8_t c11AcTxPwrVht160_OFFSET; + int8_t acReverse[2]; +}; + +struct RSSI_PATH_COMPASATION { + int8_t c2GRssiCompensation; + int8_t c5GRssiCompensation; +}; + +struct PWR_5G_OFFSET { + int8_t cOffsetBand0; /* 4.915-4.980G */ + int8_t cOffsetBand1; /* 5.000-5.080G */ + int8_t cOffsetBand2; /* 5.160-5.180G */ + int8_t cOffsetBand3; /* 5.200-5.280G */ + int8_t cOffsetBand4; /* 5.300-5.340G */ + int8_t cOffsetBand5; /* 5.500-5.580G */ + int8_t cOffsetBand6; /* 5.600-5.680G */ + int8_t cOffsetBand7; /* 5.700-5.825G */ +}; + +struct PWR_PARAM { + uint32_t au4Data[28]; + uint32_t u4RefValue1; + uint32_t u4RefValue2; +}; + +#if 0 +struct WIFI_CFG_PARAM_STRUCT { + /* 256 bytes of MP data */ + uint16_t u2Part1OwnVersion; + uint16_t u2Part1PeerVersion; + uint8_t aucMacAddress[6]; + uint8_t aucCountryCode[2]; + struct TX_PWR_PARAM rTxPwr; + uint8_t aucEFUSE[144]; + uint8_t ucTxPwrValid; + uint8_t ucSupport5GBand; + uint8_t fg2G4BandEdgePwrUsed; + int8_t cBandEdgeMaxPwrCCK; + int8_t cBandEdgeMaxPwrOFDM20; + int8_t cBandEdgeMaxPwrOFDM40; + + uint8_t ucRegChannelListMap; + uint8_t ucRegChannelListIndex; + uint8_t aucRegSubbandInfo[36]; + + uint8_t aucReserved2[256 - 240]; + + /* 256 bytes of function data */ + uint16_t u2Part2OwnVersion; + uint16_t u2Part2PeerVersion; + uint8_t uc2G4BwFixed20M; + uint8_t uc5GBwFixed20M; + uint8_t ucEnable5GBand; + uint8_t aucPreTailReserved; + uint8_t aucTailReserved[256 - 8]; +}; +#else + +struct AC_PWR_SETTING_STRUCT { + uint8_t c11AcTxPwr_BPSK; + uint8_t c11AcTxPwr_QPSK; + uint8_t c11AcTxPwr_16QAM; + uint8_t c11AcTxPwr_MCS5_MCS6; + uint8_t c11AcTxPwr_MCS7; + uint8_t c11AcTxPwr_MCS8; + uint8_t c11AcTxPwr_MCS9; + uint8_t c11AcTxPwr_Reserved; + uint8_t c11AcTxPwrVht40_OFFSET; + uint8_t c11AcTxPwrVht80_OFFSET; + uint8_t c11AcTxPwrVht160_OFFSET; +}; + +struct BANDEDGE_5G { + uint8_t uc5GBandEdgePwrUsed; + uint8_t c5GBandEdgeMaxPwrOFDM20; + uint8_t c5GBandEdgeMaxPwrOFDM40; + uint8_t c5GBandEdgeMaxPwrOFDM80; + +}; + +struct NEW_EFUSE_MAPPING2NVRAM { + uint8_t ucReverse1[8]; + uint16_t u2Signature; + struct BANDEDGE_5G r5GBandEdgePwr; + uint8_t ucReverse2[14]; + + /* 0x50 */ + uint8_t aucChOffset[3]; + uint8_t ucChannelOffsetVaild; + uint8_t acAllChannelOffset; + uint8_t aucChOffset3[11]; + + /* 0x60 */ + uint8_t auc5GChOffset[8]; + uint8_t uc5GChannelOffsetVaild; + uint8_t aucChOffset4[7]; + + /* 0x70 */ + struct AC_PWR_SETTING_STRUCT r11AcTxPwr; + uint8_t uc11AcTxPwrValid; + + uint8_t ucReverse4[20]; + + /* 0x90 */ + struct AC_PWR_SETTING_STRUCT r11AcTxPwr2G; + uint8_t uc11AcTxPwrValid2G; + + uint8_t ucReverse5[40]; +}; + +struct WIFI_CFG_PARAM_STRUCT { + /* 256 bytes of MP data */ + uint16_t u2Part1OwnVersion; + uint16_t u2Part1PeerVersion; + uint8_t aucMacAddress[6]; + uint8_t aucCountryCode[2]; + struct TX_PWR_PARAM rTxPwr; +#if CFG_SUPPORT_NVRAM_5G + union { + struct NEW_EFUSE_MAPPING2NVRAM u; + uint8_t aucEFUSE[144]; + } EfuseMapping; +#else + uint8_t aucEFUSE[144]; +#endif + uint8_t ucTxPwrValid; + uint8_t ucSupport5GBand; + uint8_t fg2G4BandEdgePwrUsed; + int8_t cBandEdgeMaxPwrCCK; + int8_t cBandEdgeMaxPwrOFDM20; + int8_t cBandEdgeMaxPwrOFDM40; + + uint8_t ucRegChannelListMap; + uint8_t ucRegChannelListIndex; + uint8_t aucRegSubbandInfo[36]; + + uint8_t aucReserved2[256 - 240]; + + /* 256 bytes of function data */ + uint16_t u2Part2OwnVersion; + uint16_t u2Part2PeerVersion; + uint8_t uc2G4BwFixed20M; + uint8_t uc5GBwFixed20M; + uint8_t ucEnable5GBand; + uint8_t ucRxDiversity; + struct RSSI_PATH_COMPASATION rRssiPathCompensation; + uint8_t fgRssiCompensationVaildbit; + uint8_t ucGpsDesense; + uint16_t u2FeatureReserved; + uint8_t aucPreTailReserved; + uint8_t aucTailReserved[256 - 15]; +}; + +#endif +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +#ifndef DATA_STRUCT_INSPECTING_ASSERT +#define DATA_STRUCT_INSPECTING_ASSERT(expr) \ + {switch (0) {case 0: case (expr): default:; } } +#endif + +#define CFG_FILE_WIFI_REC_SIZE sizeof(struct WIFI_CFG_PARAM_STRUCT) + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#ifndef _lint +/* We don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + * We'll need this to guarantee the same member order in different structures + * to simply handling effort in some functions. + */ +static __KAL_INLINE__ void nvramOffsetCheck(void) +{ + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct WIFI_CFG_PARAM_STRUCT, u2Part2OwnVersion) == 256); + + DATA_STRUCT_INSPECTING_ASSERT(sizeof( + struct WIFI_CFG_PARAM_STRUCT) == 512); +#if CFG_SUPPORT_NVRAM_5G + DATA_STRUCT_INSPECTING_ASSERT((OFFSET_OF( + struct WIFI_CFG_PARAM_STRUCT, EfuseMapping) & 0x0001) + == 0); +#else + DATA_STRUCT_INSPECTING_ASSERT((OFFSET_OF( + struct WIFI_CFG_PARAM_STRUCT, aucEFUSE) & 0x0001) + == 0); +#endif + DATA_STRUCT_INSPECTING_ASSERT((OFFSET_OF( + struct WIFI_CFG_PARAM_STRUCT, aucRegSubbandInfo) & 0x0001) + == 0); +} +#endif + +#endif /* _CFG_WIFI_FILE_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/cmm_asic_connac.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/cmm_asic_connac.h new file mode 100644 index 0000000000000..219f168781e6c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/cmm_asic_connac.h @@ -0,0 +1,143 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/ + * MT6620_WIFI_DRIVER_V2_3/include/chips/connac.h#1 + */ + +/*! \file connac.h + * \brief This file contains the info of CONNAC + */ + +#ifndef _CMM_ASIC_CONNAC_H +#define _CMM_ASIC_CONNAC_H + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define CONNAC_CHIP_IP_VERSION (0x10020300) +#define CONNAC_CHIP_IP_CONFIG (0x1) +#define CONNAC_CHIP_ADIE_INFO (0x31) +#define USB_HIF_TXD_LEN 4 + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +void asicCapInit(IN struct ADAPTER *prAdapter); +uint32_t asicGetFwDlInfo(struct ADAPTER *prAdapter, + char *pcBuf, int i4TotalLen); +void asicEnableFWDownload(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnable); +uint32_t asicGetChipID(struct ADAPTER *prAdapter); +void fillNicTxDescAppend(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + OUT uint8_t *prTxDescBuffer); +void fillNicTxDescAppendWithCR4(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + OUT uint8_t *prTxDescBuffer); +void fillTxDescAppendByHost(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN uint16_t u4MsduId, + IN phys_addr_t rDmaAddr, IN uint32_t u4Idx, IN u_int8_t fgIsLast, + OUT uint8_t *pucBuffer); +void fillTxDescAppendByHostV2(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN uint16_t u4MsduId, + IN phys_addr_t rDmaAddr, IN uint32_t u4Idx, IN u_int8_t fgIsLast, + OUT uint8_t *pucBuffer); +void fillTxDescAppendByCR4(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN uint16_t u4MsduId, + IN phys_addr_t rDmaAddr, IN uint32_t u4Idx, IN u_int8_t fgIsLast, + OUT uint8_t *pucBuffer); +void fillTxDescTxByteCount(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + struct HW_MAC_TX_DESC *prTxDesc); +void fillTxDescTxByteCountWithCR4(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + struct HW_MAC_TX_DESC *prTxDesc); + +#if defined(_HIF_PCIE) || defined(_HIF_AXI) +/* DMS Scheduler Init */ +void asicPcieDmaShdlInit(IN struct ADAPTER *prAdapter); +void asicPdmaLoopBackConfig(struct GLUE_INFO *prGlueInfo, u_int8_t fgEnable); +void asicPdmaConfig(struct GLUE_INFO *prGlueInfo, u_int8_t fgEnable); +void asicEnableInterrupt(IN struct ADAPTER *prAdapter); +void asicDisableInterrupt(IN struct ADAPTER *prAdapter); +void asicLowPowerOwnRead(IN struct ADAPTER *prAdapter, OUT u_int8_t *pfgResult); +void asicLowPowerOwnSet(IN struct ADAPTER *prAdapter, OUT u_int8_t *pfgResult); +void asicLowPowerOwnClear(IN struct ADAPTER *prAdapter, + OUT u_int8_t *pfgResult); +void asicLowPowerOwnClearPCIe(IN struct ADAPTER *prAdapter, + OUT u_int8_t *pfgResult); +void asicWakeUpWiFi(IN struct ADAPTER *prAdapter); +bool asicIsValidRegAccess(IN struct ADAPTER *prAdapter, IN uint32_t u4Register); +void asicGetMailboxStatus(IN struct ADAPTER *prAdapter, OUT uint32_t *pu4Val); +void asicSetDummyReg(struct GLUE_INFO *prGlueInfo); +void asicCheckDummyReg(struct GLUE_INFO *prGlueInfo); +#if CFG_SUPPORT_PCIE_L2 +void asicPdmaStop(struct GLUE_INFO *prGlueInfo, u_int8_t enable); +#endif +#endif /* _HIF_PCIE */ + +#if defined(_HIF_USB) +/* DMS Scheduler Init */ +void asicUsbDmaShdlInit(IN struct ADAPTER *prAdapter); +void asicUdmaTxTimeoutEnable(IN struct ADAPTER *prAdapter); +u_int8_t asicUsbSuspend(IN struct ADAPTER *prAdapter, + IN struct GLUE_INFO *prGlueInfo); +uint8_t asicUsbEventEpDetected(IN struct ADAPTER *prAdapter); +void asicUdmaRxFlush(IN struct ADAPTER *prAdapter, IN u_int8_t bEnable); +void asicPdmaHifReset(IN struct ADAPTER *prAdapter, IN u_int8_t bRelease); +void fillUsbHifTxDesc(IN uint8_t **pDest, IN uint16_t *pInfoBufLen); +#endif /* _HIF_USB */ +#endif /* _CMM_ASIC_CONNAC_H */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/connac.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/connac.h new file mode 100644 index 0000000000000..5ddba7da0fd17 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/connac.h @@ -0,0 +1,129 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/ + * MT6620_WIFI_DRIVER_V2_3/include/chips/connac.h#1 + */ + +/*! \file connac.h + * \brief This file contains the info of CONNAC + */ + +#ifdef CONNAC + +#ifndef _CONNAC_H +#define _CONNAC_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/sched.h" +#if CFG_MTK_ANDROID_WMT +extern void connectivity_export_show_stack(struct task_struct *tsk, + unsigned long *sp); +#endif + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define CONNAC_CHIP_ID (0x0001) +#define CONNAC_SW_SYNC0 CONN_CFG_ON_CONN_ON_MISC_ADDR +#define CONNAC_SW_SYNC0_RDY_OFFSET \ + CONN_CFG_ON_CONN_ON_MISC_DRV_FM_STAT_SYNC_SHFT +#define CONNAC_PATCH_START_ADDR (0x0001C000) +#define CONNAC_TOP_CFG_BASE CONN_CFG_BASE +#define CONNAC_TX_DESC_APPEND_LENGTH 32 +#define CONNAC_RX_DESC_LENGTH 16 +#define CONNAC_RX_INIT_EVENT_LENGTH 8 +#define CONNAC_RX_EVENT_HDR_LENGTH 12 + +/******************************************************************************* + * 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 /* _CONNAC_H */ + +#endif /* CONNAC */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/connac2x2.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/connac2x2.h new file mode 100644 index 0000000000000..ae4aed1c13ca0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/connac2x2.h @@ -0,0 +1,129 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/ + * MT6620_WIFI_DRIVER_V2_3/include/chips/connac.h#1 + */ + +/*! \file connac.h + * \brief This file contains the info of CONNAC + */ + +#ifdef CONNAC2X2 + +#ifndef _CONNAC2X2_H +#define _CONNAC2X2_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/sched.h" +#if CFG_MTK_ANDROID_WMT +extern void connectivity_export_show_stack(struct task_struct *tsk, + unsigned long *sp); +#endif + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define CONNAC2X2_CHIP_ID (0x0001) +#define CONNAC2X2_SW_SYNC0 CONN_CFG_ON_CONN_ON_MISC_ADDR +#define CONNAC2X2_SW_SYNC0_RDY_OFFSET \ + CONN_CFG_ON_CONN_ON_MISC_DRV_FM_STAT_SYNC_SHFT +#define CONNAC2X2_PATCH_START_ADDR (0x0001C000) +#define CONNAC2X2_TOP_CFG_BASE CONN_CFG_BASE +#define CONNAC2X2_TX_DESC_APPEND_LENGTH 32 +#define CONNAC2X2_RX_DESC_LENGTH 20 +#define CONNAC2X2_RX_INIT_EVENT_LENGTH 8 +#define CONNAC2X2_RX_EVENT_HDR_LENGTH 12 + +/******************************************************************************* + * 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 /* _CONNAC2X2_H */ + +#endif /* CONNAC2X2 */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/dma_sch.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/dma_sch.h new file mode 100644 index 0000000000000..857ffbe9b2376 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/dma_sch.h @@ -0,0 +1,199 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + dma_sch.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ------------------------------------- +*/ + + +#ifndef __DMA_SCH_H__ +#define __DMA_SCH_H__ + +#define DMASHDL_BASE 0x5000a000 + +#define MT_HIF_DMASHDL_PKT_MAX_SIZE (DMASHDL_BASE + 0x1c) + +#define PLE_PKT_MAX_SIZE_MASK (0xfff << 0) +#define PLE_PKT_MAX_SIZE_NUM(p) (((p) & 0xfff) << 0) +#define GET_PLE_PKT_MAX_SIZE_NUM(p) (((p) & PLE_PKT_MAX_SIZE_MASK) >> 0) + +#define PSE_PKT_MAX_SIZE_MASK (0xfff << 16) +#define PSE_PKT_MAX_SIZE_NUM(p) (((p) & 0xfff) << 16) +#define GET_PSE_PKT_MAX_SIZE_NUM(p) (((p) & PSE_PKT_MAX_SIZE_MASK) >> 16) +#define MT_HIF_DMASHDL_OPTION_CTRL (DMASHDL_BASE + 0x08) +#define MT_HIF_DMASHDL_REFILL_CTRL (DMASHDL_BASE + 0x10) +#define MT_HIF_DMASHDL_GROUP0_CTRL (DMASHDL_BASE + 0x20) +#define MT_HIF_DMASHDL_GROUP1_CTRL (DMASHDL_BASE + 0x24) +#define MT_HIF_DMASHDL_GROUP2_CTRL (DMASHDL_BASE + 0x28) +#define MT_HIF_DMASHDL_GROUP3_CTRL (DMASHDL_BASE + 0x2c) +#define MT_HIF_DMASHDL_GROUP4_CTRL (DMASHDL_BASE + 0x30) +#define MT_HIF_DMASHDL_GROUP5_CTRL (DMASHDL_BASE + 0x34) +#define MT_HIF_DMASHDL_GROUP6_CTRL (DMASHDL_BASE + 0x38) +#define MT_HIF_DMASHDL_GROUP7_CTRL (DMASHDL_BASE + 0x3c) +#define MT_HIF_DMASHDL_GROUP8_CTRL (DMASHDL_BASE + 0x40) +#define MT_HIF_DMASHDL_GROUP9_CTRL (DMASHDL_BASE + 0x44) +#define MT_HIF_DMASHDL_GROUP10_CTRL (DMASHDL_BASE + 0x48) +#define MT_HIF_DMASHDL_GROUP11_CTRL (DMASHDL_BASE + 0x4c) +#define MT_HIF_DMASHDL_GROUP12_CTRL (DMASHDL_BASE + 0x50) +#define MT_HIF_DMASHDL_GROUP13_CTRL (DMASHDL_BASE + 0x54) +#define MT_HIF_DMASHDL_GROUP14_CTRL (DMASHDL_BASE + 0x58) +#define MT_HIF_DMASHDL_GROUP15_CTRL (DMASHDL_BASE + 0x5c) + +#define MT_HIF_DMASHDL_SHDL_SET0 (DMASHDL_BASE + 0xb0) +#define MT_HIF_DMASHDL_SHDL_SET1 (DMASHDL_BASE + 0xb4) + + +#define MT_HIF_DMASHDL_SLOT_SET0 (DMASHDL_BASE + 0xc4) +#define MT_HIF_DMASHDL_SLOT_SET1 (DMASHDL_BASE + 0xc8) + + +#define MT_HIF_DMASHDL_Q_MAP0 (DMASHDL_BASE + 0xd0) +#define MT_HIF_DMASHDL_Q_MAP1 (DMASHDL_BASE + 0xd4) +#define MT_HIF_DMASHDL_Q_MAP2 (DMASHDL_BASE + 0xd8) +#define MT_HIF_DMASHDL_Q_MAP3 (DMASHDL_BASE + 0xdc) + +#define MT_HIF_DMASHDL_PAGE_SET (DMASHDL_BASE + 0x0c) + +/* User program group sequence type control */ +/* 0: user program group sequence order type, + * 1: pre define each slot group strict order + */ +#define DMASHDL_GROUP_SEQ_ORDER_TYPE BIT(16) + + +#define MT_HIF_DMASHDL_CTRL_SIGNAL (DMASHDL_BASE + 0x18) +/* enable to clear the flag of PLE TXD size greater than ple max. size */ +#define DMASHDL_PLE_TXD_GT_MAX_SIZE_FLAG_CLR BIT(0) +/* enable packet in substration action from HIF ask period */ +#define DMASHDL_HIF_ASK_SUB_ENA BIT(16) +/* enable packet in substration action from PLE */ +#define DMASHDL_PLE_SUB_ENA BIT(17) +/* enable terminate refill period when PLE release packet to do addition */ +#define DMASHDL_PLE_ADD_INT_REFILL_ENA BIT(29) +/* enable terminate refill period when packet in to do addition */ +#define DMASHDL_PDMA_ADD_INT_REFILL_ENA BIT(30) +/* enable terminate refill period when packet in to do substration */ +#define DMASHDL_PKTIN_INT_REFILL_ENA BIT(31) + +#define MT_HIF_DMASHDL_ERROR_FLAG_CTRL (DMASHDL_BASE + 0x9c) + +#define MT_HIF_DMASHDL_STATUS_RD (DMASHDL_BASE + 0x100) +#define MT_HIF_DMASHDL_STATUS_RD_GP0 (DMASHDL_BASE + 0x140) +#define MT_HIF_DMASHDL_STATUS_RD_GP1 (DMASHDL_BASE + 0x144) +#define MT_HIF_DMASHDL_STATUS_RD_GP2 (DMASHDL_BASE + 0x148) +#define MT_HIF_DMASHDL_STATUS_RD_GP3 (DMASHDL_BASE + 0x14c) +#define MT_HIF_DMASHDL_STATUS_RD_GP4 (DMASHDL_BASE + 0x150) +#define MT_HIF_DMASHDL_STATUS_RD_GP5 (DMASHDL_BASE + 0x154) +#define MT_HIF_DMASHDL_STATUS_RD_GP6 (DMASHDL_BASE + 0x158) +#define MT_HIF_DMASHDL_STATUS_RD_GP7 (DMASHDL_BASE + 0x15c) +#define MT_HIF_DMASHDL_STATUS_RD_GP8 (DMASHDL_BASE + 0x160) +#define MT_HIF_DMASHDL_STATUS_RD_GP9 (DMASHDL_BASE + 0x164) +#define MT_HIF_DMASHDL_STATUS_RD_GP10 (DMASHDL_BASE + 0x168) +#define MT_HIF_DMASHDL_STATUS_RD_GP11 (DMASHDL_BASE + 0x16c) +#define MT_HIF_DMASHDL_STATUS_RD_GP12 (DMASHDL_BASE + 0x170) +#define MT_HIF_DMASHDL_STATUS_RD_GP13 (DMASHDL_BASE + 0x174) +#define MT_HIF_DMASHDL_STATUS_RD_GP14 (DMASHDL_BASE + 0x178) +#define MT_HIF_DMASHDL_STATUS_RD_GP15 (DMASHDL_BASE + 0x17c) +#define MT_HIF_DMASHDLRD_GP_PKT_CNT_0 (DMASHDL_BASE + 0x180) +#define MT_HIF_DMASHDLRD_GP_PKT_CNT_1 (DMASHDL_BASE + 0x184) +#define MT_HIF_DMASHDLRD_GP_PKT_CNT_2 (DMASHDL_BASE + 0x188) +#define MT_HIF_DMASHDLRD_GP_PKT_CNT_3 (DMASHDL_BASE + 0x18c) +#define MT_HIF_DMASHDLRD_GP_PKT_CNT_4 (DMASHDL_BASE + 0x190) +#define MT_HIF_DMASHDLRD_GP_PKT_CNT_5 (DMASHDL_BASE + 0x194) +#define MT_HIF_DMASHDLRD_GP_PKT_CNT_6 (DMASHDL_BASE + 0x198) +#define MT_HIF_DMASHDLRD_GP_PKT_CNT_7 (DMASHDL_BASE + 0x19c) + +#define DMASHDL_RSV_CNT_MASK (0xfff << 16) +#define DMASHDL_SRC_CNT_MASK (0xfff << 0) +#define DMASHDL_RSV_CNT_OFFSET 16 +#define DMASHDL_SRC_CNT_OFFSET 0 +#define DMASHDL_FREE_PG_CNT_MASK (0xfff << 16) +#define DMASHDL_FFA_CNT_MASK (0xfff << 0) +#define DMASHDL_FREE_PG_CNT_OFFSET 16 +#define DMASHDL_FFA_CNT_OFFSET 0 +#define DMASHDL_MAX_QUOTA_MASK (0xfff << 16) +#define DMASHDL_MIN_QUOTA_MASK (0xfff << 0) +#define DMASHDL_MAX_QUOTA_OFFSET 16 +#define DMASHDL_MIN_QUOTA_OFFSET 0 + +#define DMASHDL_MIN_QUOTA_NUM(p) (((p) & 0xfff) << DMASHDL_MIN_QUOTA_OFFSET) +#define GET_DMASHDL_MIN_QUOTA_NUM(p)\ + (((p) & DMASHDL_MIN_QUOTA_MASK) >> DMASHDL_MIN_QUOTA_OFFSET) + +#define DMASHDL_MAX_QUOTA_NUM(p) (((p) & 0xfff) << DMASHDL_MAX_QUOTA_OFFSET) +#define GET_DMASHDL_MAX_QUOTA_NUM(p)\ + (((p) & DMASHDL_MAX_QUOTA_MASK) >> DMASHDL_MAX_QUOTA_OFFSET) + + +#define ODD_GROUP_ASK_CN_MASK (0xff << 16) +#define ODD_GROUP_ASK_CN_OFFSET 16 +#define GET_ODD_GROUP_ASK_CNT(p)\ + (((p) & ODD_GROUP_ASK_CN_MASK) >> ODD_GROUP_ASK_CN_OFFSET) +#define ODD_GROUP_PKT_IN_CN_MASK (0xff << 24) +#define ODD_GROUP_PKT_IN_CN_OFFSET 24 +#define GET_ODD_GROUP_PKT_IN_CNT(p)\ + (((p) & ODD_GROUP_PKT_IN_CN_MASK) >> ODD_GROUP_PKT_IN_CN_OFFSET) +#define EVEN_GROUP_ASK_CN_MASK (0xff << 0) +#define EVEN_GROUP_ASK_CN_OFFSET 0 +#define GET_EVEN_GROUP_ASK_CNT(p)\ + (((p) & EVEN_GROUP_ASK_CN_MASK) >> EVEN_GROUP_ASK_CN_OFFSET) +#define EVEN_GROUP_PKT_IN_CN_MASK (0xff << 8) +#define EVEN_GROUP_PKT_IN_CN_OFFSET 8 +#define GET_EVEN_GROUP_PKT_IN_CNT(p)\ + (((p) & EVEN_GROUP_PKT_IN_CN_MASK) >> EVEN_GROUP_PKT_IN_CN_OFFSET) +#if defined(P18) || defined(MT7663) || defined(AXE) +#define HIF_DMASHDL_IO_READ32(_A, _R, _pV)\ + HW_IO_READ32(_A->hdev_ctrl, (0x6000+((uint32_t)_R&0xfff)), _pV) +#define HIF_DMASHDL_IO_WRITE32(_A, _R, _pV)\ + HW_IO_WRITE32(_A->hdev_ctrl, (0x6000+((uint32_t)_R&0xfff)), _pV) +#else +#define HIF_DMASHDL_IO_READ32(_A, _R, _pV)\ + do {\ + uint32_t restore_remap_addr;\ + HW_IO_READ32(_A->hdev_ctrl, 0x2504, &restore_remap_addr);\ + \ + HW_IO_WRITE32(_A->hdev_ctrl, 0x2504, DMASHDL_BASE);\ + HW_IO_READ32(_A->hdev_ctrl,\ + (0x80000+((uint32_t)_R&0xffff)), _pV);\ + \ + HW_IO_WRITE32(_A->hdev_ctrl, 0x2504, restore_remap_addr);\ + } while (0) + +#define HIF_DMASHDL_IO_WRITE32(_A, _R, _pV) \ + do {\ + uint32_t restore_remap_addr;\ + \ + HW_IO_READ32(_A->hdev_ctrl, 0x2504, &restore_remap_addr);\ + \ + HW_IO_WRITE32(_A->hdev_ctrl, 0x2504, DMASHDL_BASE);\ + HW_IO_WRITE32(_A->hdev_ctrl,\ + (0x80000+((uint32_t)_R&0xffff)), _pV);\ + \ + HW_IO_WRITE32(_A->hdev_ctrl, 0x2504, restore_remap_addr);\ + } while (0) +#endif + + +#endif /* __DMA_SCH_H__ */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/fw_dl.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/fw_dl.h new file mode 100644 index 0000000000000..dbf0194bcba62 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/fw_dl.h @@ -0,0 +1,295 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file fw_dl.h + */ + +#ifndef _FW_DL_H +#define _FW_DL_H + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/* PDA - Patch Decryption Accelerator */ +#define PDA_N9 0 +#define PDA_CR4 1 + +#define MAX_FWDL_SECTION_NUM 10 +#define N9_FWDL_SECTION_NUM 2 +#define CR4_FWDL_SECTION_NUM HIF_CR4_FWDL_SECTION_NUM +#define IMG_DL_STATUS_PORT_IDX HIF_IMG_DL_STATUS_PORT_IDX + +#define DOWNLOAD_CONFIG_ENCRYPTION_MODE BIT(0) +#define DOWNLOAD_CONFIG_KEY_INDEX_MASK BITS(1, 2) +#define DOWNLOAD_CONFIG_RESET_OPTION BIT(3) +#define DOWNLOAD_CONFIG_WORKING_PDA_OPTION BIT(4) +#define DOWNLOAD_CONFIG_VALID_RAM_ENTRY BIT(5) +#define DOWNLOAD_CONFIG_EMI BIT(7) +#define DOWNLOAD_CONFIG_ACK_OPTION BIT(31) + +#if CFG_SUPPORT_COMPRESSION_FW_OPTION +#define COMPRESSION_OPTION_OFFSET 4 +#define COMPRESSION_OPTION_MASK BIT(4) +#endif + +#define RELEASE_INFO_SEPARATOR_LEN 16 + +#if CFG_MTK_ANDROID_EMI +#define WIFI_EMI_ADDR_MASK 0xFFFFFF +#define WIFI_EMI_MEM_OFFSET 0x177000 +#define WIFI_EMI_MEM_SIZE 0xBD000 +extern phys_addr_t gConEmiPhyBase; +extern unsigned long long gConEmiSize; +#endif + +enum ENUM_IMG_DL_IDX_T { + IMG_DL_IDX_N9_FW, + IMG_DL_IDX_CR4_FW, + IMG_DL_IDX_PATCH +}; + +struct FWDL_OPS_T { + /* load firmware bin priority */ + void (*constructFirmwarePrio)(struct GLUE_INFO *prGlueInfo, + uint8_t **apucNameTable, uint8_t **apucName, + uint8_t *pucNameIdx, uint8_t ucMaxNameIdx); + void (*constructPatchName)(struct GLUE_INFO *prGlueInfo, + uint8_t **apucName, uint8_t *pucNameIdx); + + uint32_t (*downloadPatch)(IN struct ADAPTER *prAdapter); + uint32_t (*downloadFirmware)(IN struct ADAPTER *prAdapter, + IN enum ENUM_IMG_DL_IDX_T eDlIdx); + void (*getFwInfo)(IN struct ADAPTER *prAdapter, + IN uint8_t u4SecIdx, IN enum ENUM_IMG_DL_IDX_T eDlIdx, + OUT uint32_t *pu4Addr, OUT uint32_t *pu4Len, + OUT uint32_t *pu4DataMode, OUT u_int8_t *pfgIsEMIDownload); + unsigned int (*getFwDlInfo)(struct ADAPTER *prAdapter, + char *pcBuf, int i4TotalLen); +}; + +#if (CFG_UMAC_GENERATION >= 0x20) +#define LEN_4_BYTE_CRC (4) + +struct TAILER_COMMON_FORMAT_T { + uint8_t ucChipInfo; + uint8_t ucEcoCode; + uint8_t ucRegionNum; + uint8_t ucFormatVer; + uint8_t ucFormatFlag; + uint8_t aucReserved[2]; + uint8_t aucRamVersion[10]; + uint8_t aucRamBuiltDate[15]; + uint32_t u4CRC; +}; + +struct TAILER_REGION_FORMAT_T { + uint32_t u4CRC; + uint32_t u4RealSize; + uint32_t u4BlockSize; + uint8_t aucReserved1[4]; + uint32_t u4Addr; + uint32_t u4Len; + uint8_t ucFeatureSet; + uint8_t aucReserved2[15]; +}; + +struct TAILER_FORMAT_T { + uint32_t addr; + uint8_t chip_info; + uint8_t feature_set; + uint8_t eco_code; + uint8_t ram_version[10]; + uint8_t ram_built_date[15]; + uint32_t len; +}; + +struct HEADER_RELEASE_INFO { + uint16_t u2Len; + uint8_t ucPaddingLen; + uint8_t ucTag; +}; + +#if CFG_SUPPORT_COMPRESSION_FW_OPTION +struct TAILER_FORMAT_T_2 { + uint32_t crc; + uint32_t addr; + uint32_t block_size; + uint32_t real_size; + uint8_t chip_info; + uint8_t feature_set; + uint8_t eco_code; + uint8_t ram_version[10]; + uint8_t ram_built_date[15]; + uint32_t len; +}; + +struct FW_IMAGE_TAILER_T_2 { + struct TAILER_FORMAT_T_2 ilm_info; + struct TAILER_FORMAT_T_2 dlm_info; +}; + +struct FW_IMAGE_TAILER_CHECK { + uint8_t chip_info; + uint8_t feature_set; + uint8_t eco_code; + uint8_t ram_version[10]; + uint8_t ram_built_date[15]; + uint32_t len; +}; +#endif + +struct PATCH_FORMAT_T { + uint8_t aucBuildDate[16]; + uint8_t aucPlatform[4]; + uint32_t u4SwHwVersion; + uint32_t u4PatchVersion; + uint16_t u2CRC; /* CRC calculated for image only */ + uint8_t ucPatchImage[0]; +}; + +#endif + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +#if CFG_ENABLE_FW_DOWNLOAD +uint32_t wlanGetDataMode(IN struct ADAPTER *prAdapter, + IN enum ENUM_IMG_DL_IDX_T eDlIdx, IN uint8_t ucFeatureSet); + +void wlanGetHarvardFwInfo(IN struct ADAPTER *prAdapter, + IN uint8_t u4SecIdx, IN enum ENUM_IMG_DL_IDX_T eDlIdx, + OUT uint32_t *pu4Addr, OUT uint32_t *pu4Len, + OUT uint32_t *pu4DataMode, OUT u_int8_t *pfgIsEMIDownload); + +void wlanGetConnacFwInfo(IN struct ADAPTER *prAdapter, + IN uint8_t u4SecIdx, IN enum ENUM_IMG_DL_IDX_T eDlIdx, + OUT uint32_t *pu4Addr, OUT uint32_t *pu4Len, + OUT uint32_t *pu4DataMode, OUT u_int8_t *pfgIsEMIDownload); + +#if CFG_SUPPORT_COMPRESSION_FW_OPTION +uint32_t wlanCompressedImageSectionDownloadStage(IN struct ADAPTER *prAdapter, + IN void *pvFwImageMapFile, IN uint32_t u4FwImageFileLength, + uint8_t ucSectionNumber, IN enum ENUM_IMG_DL_IDX_T eDlIdx, + OUT uint8_t *ucIsCompressed, + OUT struct INIT_CMD_WIFI_DECOMPRESSION_START *prFwImageInFo); +#endif +uint32_t wlanImageSectionDownloadStage(IN struct ADAPTER *prAdapter, + IN void *pvFwImageMapFile, + IN uint32_t u4FwImageFileLength, IN uint8_t ucSectionNumber, + IN enum ENUM_IMG_DL_IDX_T eDlIdx); + +uint32_t wlanDownloadSection(IN struct ADAPTER *prAdapter, + IN uint32_t u4Addr, IN uint32_t u4Len, + IN uint32_t u4DataMode, IN uint8_t *pucStartPtr, + IN enum ENUM_IMG_DL_IDX_T eDlIdx); + +uint32_t wlanDownloadEMISection(IN struct ADAPTER *prAdapter, + IN uint32_t u4DestAddr, + IN uint32_t u4Len, IN uint8_t *pucStartPtr); + +uint32_t wlanGetHarvardTailerInfo(IN struct ADAPTER *prAdapter, + IN void *prFwBuffer, IN uint32_t u4FwSize, + IN uint32_t ucTotSecNum, IN enum ENUM_IMG_DL_IDX_T eDlIdx); + +uint32_t wlanGetConnacTailerInfo(IN struct ADAPTER *prAdapter, + IN void *prFwBuffer, + IN uint32_t u4FwSize, IN enum ENUM_IMG_DL_IDX_T eDlIdx); + +uint32_t wlanImageSectionConfig(IN struct ADAPTER *prAdapter, + IN uint32_t u4DestAddr, IN uint32_t u4ImgSecSize, + IN uint32_t u4DataMode, + IN enum ENUM_IMG_DL_IDX_T eDlIdx); + +uint32_t wlanImageSectionDownload(IN struct ADAPTER *prAdapter, + IN uint32_t u4ImgSecSize, IN uint8_t *pucImgSecBuf); + +uint32_t wlanImageQueryStatus(IN struct ADAPTER *prAdapter); + +uint32_t wlanConfigWifiFuncStatus(IN struct ADAPTER *prAdapter, + IN uint8_t ucCmdSeqNum); + +uint32_t wlanConfigWifiFunc(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnable, IN uint32_t u4StartAddress, + IN uint8_t ucPDA); + +uint32_t wlanCRC32(uint8_t *buf, uint32_t len); + +uint32_t wlanDownloadCR4FW(IN struct ADAPTER *prAdapter, + void *prFwBuffer); + +uint32_t wlanDownloadFW(IN struct ADAPTER *prAdapter); + +uint32_t wlanDownloadPatch(IN struct ADAPTER *prAdapter); + +uint32_t wlanHarvardFormatDownload(IN struct ADAPTER *prAdapter, + IN enum ENUM_IMG_DL_IDX_T eDlIdx); + +uint32_t wlanConnacFormatDownload(IN struct ADAPTER *prAdapter, + IN enum ENUM_IMG_DL_IDX_T eDlIdx); + +uint32_t wlanGetPatchInfo(IN struct ADAPTER *prAdapter); + +uint32_t fwDlGetFwdlInfo(struct ADAPTER *prAdapter, + char *pcBuf, int i4TotalLen); + +void fwDlGetReleaseInfoSection(struct ADAPTER *prAdapter, uint8_t *pucStartPtr); +void fwDlGetReleaseManifest(struct ADAPTER *prAdapter, + struct HEADER_RELEASE_INFO *prRelInfo, + uint8_t *pucStartPtr); + +#endif + +#endif /* _FW_DL_H */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/host_csr.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/host_csr.h new file mode 100644 index 0000000000000..f111e57f30bad --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/host_csr.h @@ -0,0 +1,69 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + host_csr.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- -------------------------------------- +*/ + +#ifndef __HOST_CSR_H__ +#define __HOST_CSR_H__ + +#define HOST_CSR_DRIVER_OWN_INFO 0x7000 +#define HOST_CSR_BASE 0x7100 + +/* MCU programming Counter info (no sync) */ +#define HOST_CSR_MCU_PORG_COUNT (HOST_CSR_BASE + 0x04) + +/* RGU Info */ +#define HOST_CSR_RGU (HOST_CSR_BASE + 0x08) + +/* HIF_BUSY / CIRQ / WFSYS_ON info */ +#define HOST_CSR_HIF_BUSY_CORQ_WFSYS_ON (HOST_CSR_BASE + 0x0C) + +/* Pinmux/mon_flag info */ +#define HOST_CSR_PINMUX_MON_FLAG (HOST_CSR_BASE + 0x10) + +/* Bit[5] mcu_pwr_stat */ +#define HOST_CSR_MCU_PWR_STAT (HOST_CSR_BASE + 0x14) + +/* Bit[15] fw_own_stat */ +#define HOST_CSR_FW_OWN_SET (HOST_CSR_BASE + 0x18) + +/* MCU SW Mailbox */ +#define HOST_CSR_MCU_SW_MAILBOX_0 (HOST_CSR_BASE + 0x1C) +#define HOST_CSR_MCU_SW_MAILBOX_1 (HOST_CSR_BASE + 0x20) +#define HOST_CSR_MCU_SW_MAILBOX_2 (HOST_CSR_BASE + 0x24) +#define HOST_CSR_MCU_SW_MAILBOX_3 (HOST_CSR_BASE + 0x28) + +/* Conn_cfg_on info */ +#define HOST_CSR_CONN_CFG_ON (HOST_CSR_BASE + 0x2C) + +/* Get conn_cfg_on IRQ ENA/IRQ Status 0xC_1170~0xC_1174 */ +#define HOST_CSR_IRQ_STA 0xC1170 +#define HOST_CSR_IRQ_ENA 0xC1174 + +/* Get mcu_cfg PC programming Counter log info 0x0_2450~0x0_24D0 */ +#define HOST_CSR_MCU_PROG_COUNT 0x2450 + +#endif /* __HOST_CSR_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/mt6632.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/mt6632.h new file mode 100644 index 0000000000000..0621852cd6440 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/mt6632.h @@ -0,0 +1,118 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/ + * MT6620_WIFI_DRIVER_V2_3/include/chips/mt6632.h#1 + */ + +/*! \file mt6632.h + * \brief This file contains the info of MT6632 + */ + +#ifndef _MT6632_H +#define _MT6632_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 MT6632_CHIP_ID (0x6632) +#define MT6632_SW_SYNC0 WIFI_CFG_SW_SYNC0 +#define MT6632_SW_SYNC0_RDY_OFFSET WIFI_CFG_SYNC0_RDY_OFFSET +#define MT6632_PATCH_START_ADDR (0x000B4000) +#define MT6632_TOP_CFG_BASE (0x0000) +#define MT6632_TX_DESC_APPEND_LENGTH 44 +#define MT6632_RX_DESC_LENGTH 16 +#define MT6632_RX_INIT_EVENT_LENGTH 8 +#define MT6632_RX_EVENT_HDR_LENGTH 12 + +/******************************************************************************* + * 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 /* _MT6632_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/mt7663.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/mt7663.h new file mode 100644 index 0000000000000..ca5b457160ba6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/mt7663.h @@ -0,0 +1,124 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/ + * MT6620_WIFI_DRIVER_V2_3/include/chips/mt7668.h#1 + */ + +/*! \file mt7663.h + * \brief This file contains the info of MT7663 + */ + +#ifdef MT7663 + +#ifndef _MT7663_H +#define _MT7663_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 MT7663_CHIP_ID (0x7663) +#define MT7663_SW_SYNC0 CONN_CFG_ON_CONN_ON_MISC_ADDR +#define MT7663_SW_SYNC0_RDY_OFFSET \ + CONN_CFG_ON_CONN_ON_MISC_DRV_FM_STAT_SYNC_SHFT +#define MT7663_PATCH_START_ADDR (0x000DC000) +#define MT7663_TOP_CFG_BASE CONN_CFG_BASE +#define MT7663_TX_DESC_APPEND_LENGTH 32 +#define MT7663_RX_DESC_LENGTH 16 +#define MT7663_RX_INIT_EVENT_LENGTH 8 +#define MT7663_RX_EVENT_HDR_LENGTH 12 + +/******************************************************************************* + * 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 /* _MT7663_H */ + +#endif /* MT7663 */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/mt7668.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/mt7668.h new file mode 100644 index 0000000000000..867cbc38601eb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/mt7668.h @@ -0,0 +1,120 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/ + * MT6620_WIFI_DRIVER_V2_3/include/chips/mt7668.h#1 + */ + +/*! \file mt7668.h + * \brief This file contains the info of MT7668 + */ + +#ifndef _MT7668_H +#define _MT7668_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 MT7668_CHIP_ID (0x7668) +#define MT7668_SW_SYNC0 WIFI_RGU_SW_SYNC0 +#define MT7668_SW_SYNC0_RDY_OFFSET WIFI_RGU_SYNC0_RDY_OFFSET +#define MT7668_PATCH_START_ADDR (0x000C8000) +#define MT7668_TOP_CFG_BASE (0x0000) +#define MT7668_TX_DESC_APPEND_LENGTH 44 +#define MT7668_RX_DESC_LENGTH 16 +#define MT7668_RX_INIT_EVENT_LENGTH 8 +#define MT7668_RX_EVENT_HDR_LENGTH 12 + +/******************************************************************************* + * 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 /* _MT7668_H */ + + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/pse.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/pse.h new file mode 100644 index 0000000000000..a6ef0b2c063be --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/pse.h @@ -0,0 +1,274 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + pse.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- -------------------------------------- +*/ + + +#ifndef __PSE_H__ +#define __PSE_H__ + +#define PSE_BASE 0xc000 + +/* PSE Reset Control Register */ +#define PSE_RESET (PSE_BASE + 0x00) +#define PSE_ALL_RST (1 << 0) +#define PSE_LOGICAL_RST (1 << 1) +#define PSE_INIT_DONE (1 << 2) +#define GET_PSE_INIT_DONE(p) (((p) & PSE_INIT_DONE) >> 2) + +/* PSE Buffer Control Register */ +#define PSE_PBUF_CTRL (PSE_BASE + 0x14) +#define PSE_TOTAL_PAGE_NUM_MASK (0xfff) +#define PSE_GET_TOTAL_PAGE_NUM(p) (((p) & 0xfff)) +#define PSE_TOTAL_PAGE_CFG_MASK (0xf << 16) +#define PSE_GET_TOTAL_PAGE_CFG(p) (((p) & PSE_TOTAL_PAGE_CFG_MASK) >> 16) + +#define PSE_PBUF_OFFSET_MASK (0xf << 20) +#define GET_PSE_PBUF_OFFSET(p) (((p) & PSE_PBUF_OFFSET_MASK) >> 20) + +#define PSE_GC (PSE_BASE) +#define PSE_INT_STS (PSE_BASE + 0x24) +#define PSE_INT_ERR_STS (PSE_BASE + 0x28) + +/* Queue Empty */ +#define PSE_QUEUE_EMPTY (PSE_BASE + 0xb0) + +/* Page Flow Control */ +#define PSE_FREEPG_CNT (PSE_BASE + 0x100) + +#define PSE_FREEPG_HEAD_TAIL (PSE_BASE + 0x104) + +#define PSE_ENQ_0 (PSE_BASE + 0x60) +#define PSE_DEQ_0 (PSE_BASE + 0x80) +#define PSE_ENDEQ_OFFSET 0x4 +#define PSE_ENDEQ_NUM 3 + +#define PSE_PG_HIF0_GROUP (PSE_BASE + 0x110) +#define PSE_HIF0_PG_INFO (PSE_BASE + 0x114) +#define PSE_PG_HIF1_GROUP (PSE_BASE + 0x118) +#define PSE_HIF1_PG_INFO (PSE_BASE + 0x11c) + +#define PSE_PG_CPU_GROUP (PSE_BASE + 0x150) +#define PSE_CPU_PG_INFO (PSE_BASE + 0x154) + +#define PSE_PG_LMAC0_GROUP (PSE_BASE + 0x170) +#define PSE_LMAC0_PG_INFO (PSE_BASE + 0x174) +#define PSE_PG_LMAC1_GROUP (PSE_BASE + 0x178) +#define PSE_LMAC1_PG_INFO (PSE_BASE + 0x17c) +#define PSE_PG_LMAC2_GROUP (PSE_BASE + 0x180) +#define PSE_LMAC2_PG_INFO (PSE_BASE + 0x184) +#define PSE_PG_PLE_GROUP (PSE_BASE + 0x190) +#define PSE_PLE_PG_INFO (PSE_BASE + 0x194) + +/* Indirect path for read/write */ +#define PSE_FL_QUE_CTRL_0 (PSE_BASE + 0x1b0) +#define PSE_FL_QUE_CTRL_1 (PSE_BASE + 0x1b4) +#define PSE_FL_QUE_CTRL_2 (PSE_BASE + 0x1b8) +#define PSE_FL_QUE_CTRL_3 (PSE_BASE + 0x1bc) +#define PSE_PL_QUE_CTRL_0 (PSE_BASE + 0x1c0) + +/* PSE spare dummy CR */ +#define PSE_SPARE_DUMMY_CR1 (PSE_BASE + 0x1e4) +#define PSE_SPARE_DUMMY_CR2 (PSE_BASE + 0x1e8) +#define PSE_SPARE_DUMMY_CR3 (PSE_BASE + 0x2e8) +#define PSE_SPARE_DUMMY_CR4 (PSE_BASE + 0x2ec) + +#define PSE_PEEK_CR_0 (PSE_BASE + 0x3d0) +#define PSE_PEEK_CR_OFFSET 0x4 +#define PSE_PEEK_CR_NUM 9 + +/* CPU Interface Get First Frame ID Control Regitser */ +#define C_GFF (PSE_BASE + 0x24) +#define GET_FIRST_FID_MASK (0xfff) +#define GET_FIRST_FID(p) (((p) & GET_FIRST_FID_MASK)) +#define GET_QID_MASK (0x1f << 16) +#define SET_GET_QID(p) (((p) & 0x1f) << 16) +#define GET_QID(p) (((p) & GET_QID_MASK) >> 16) +#define GET_PID_MASK (0x3 << 21) +#define SET_GET_PID(p) (((p) & 0x3) << 21) +#define GET_PID(p) (((p) & GET_PID_MASK) >> 21) +#define GET_RVSE_MASK (1 << 23) +#define SET_GET_RVSE(p) (((p) & 0x1) << 23) +#define GET_RVSE(p) (((p) & GET_RVSE_MASK) >> 23) + +/* CPU Interface Get Frame ID Control Register */ +#define C_GF (PSE_BASE + 0x28) +#define GET_RETURN_FID_MASK (0xfff) +#define GET_RETURN_FID(p) (((p) & GET_RETURN_FID_MASK)) +#define CURR_FID_MASK (0xfff << 16) +#define SET_CURR_FID(p) (((p) & 0xfff) << 16) +#define GET_CURR_FID(p) (((p) & CURR_FID_MASK) >> 16) +#define GET_PREV_MASK (1 << 28) +#define SET_GET_PREV(p) (((p) & 0x1) << 28) +#define GET_PREV(p) (((p) & GET_PREV_MASK) >> 28) +#define GET_AUTO_MASK (1 << 29) +#define SET_GET_AUTO(p) (((p) & 0x1) >> 29) +#define GET_AUTO(p) (((p) & GET_AUTO_MASK) >> 29) + +/* Get Queue Length Control Register */ +#define GQC (PSE_BASE + 0x118) +#define QLEN_RETURN_VALUE_MASK (0xfff) +#define GET_QLEN_RETURN_VALUE(p) (((p) & QLEN_RETURN_VALUE_MASK)) +#define GET_QLEN_QID_MASK (0x1f << 16) +#define SET_GET_QLEN_QID(p) (((p) & 0x1f) << 16) +#define GET_QLEN_QID(p) (((p) & GET_QLEN_QID_MASK) >> 16) +#define GET_QLEN_PID_MASK (0x3 << 21) +#define SET_GET_QLEN_PID(p) (((p) & 0x3) << 21) +#define GET_QLEN_PID(p) (((p) & GET_QLEN_PID_MASK) >> 21) +#define QLEN_IN_PAGE (1 << 23) +#define GET_QLEN_IN_PAGE(p) (((p) & QLEN_IN_PAGE) >> 23) + +/* Flow Control P0 Control Register */ +#define FC_P0 (PSE_BASE + 0x120) +#define MIN_RSRV_P0_MASK (0xfff) +#define MIN_RSRV_P0(p) (((p) & 0xfff)) +#define GET_MIN_RSRV_P0(p) (((p) & MIN_RSRV_P0_MASK)) +#define MAX_QUOTA_P0_MASK (0xfff << 16) +#define MAX_QUOTA_P0(p) (((p) & 0xfff) << 16) +#define GET_MAX_QUOTA_P0(p) (((p) & MAX_QUOTA_P0_MASK) >> 16) + +/* Flow Control P1 Control Register */ +#define FC_P1 (PSE_BASE + 0x124) +#define MIN_RSRV_P1_MASK (0xfff) +#define MIN_RSRV_P1(p) (((p) & 0xfff)) +#define GET_MIN_RSRV_P1(p) (((p) & MIN_RSRV_P1_MASK)) +#define MAX_QUOTA_P1_MASK (0xfff << 16) +#define MAX_QUOTA_P1(p) (((p) & 0xfff) << 16) +#define GET_MAX_QUOTA_P1(p) (((p) & MAX_QUOTA_P1_MASK) >> 16) + +/* Flow Control P2_RQ0 Control Register */ +#define FC_P2Q0 (PSE_BASE + 0x128) +#define MIN_RSRV_P2_RQ0_MASK (0xfff) +#define MIN_RSRV_P2_RQ0(p) (((p) & 0xfff)) +#define GET_MIN_RSRV_P2_RQ0(p) (((p) & MIN_RSRV_P2_RQ0_MASK)) +#define MAX_QUOTA_P2_RQ0_MASK (0xfff << 16) +#define MAX_QUOTA_P2_RQ0(p) (((p) & 0xfff) << 16) +#define GET_MAX_QUOTA_P2_RQ0(p) (((p) & MAX_QUOTA_P2_RQ0_MASK) >> 16) + +/* Flow Control P2_RQ1 Control Register */ +#define FC_P2Q1 (PSE_BASE + 0x12c) +#define MIN_RSRV_P2_RQ1_MASK (0xfff) +#define MIN_RSRV_P2_RQ1(p) (((p) & 0xfff)) +#define GET_MIN_RSRV_P2_RQ1(p) (((p) & MIN_RSRV_P2_RQ1_MASK)) +#define MAX_QUOTA_P2_RQ1_MASK (0xfff << 16) +#define MAX_QUOTA_P2_RQ1(p) (((p) & 0xfff) << 16) +#define GET_MAX_QUOTA_P2_RQ1(p) (((p) & MAX_QUOTA_P2_RQ1_MASK) >> 16) + +/* Flow Control P2_RQ2 Control Register */ +#define FC_P2Q2 (PSE_BASE + 0x130) +#define MIN_RSRV_P2_RQ2_MASK (0xfff) +#define MIN_RSRV_P2_RQ2(p) (((p) & 0xfff)) +#define GET_MIN_RSRV_P2_RQ2(p) (((p) & MIN_RSRV_P2_RQ2_MASK)) +#define MAX_QUOTA_P2_RQ2_MASK (0xfff << 16) +#define MAX_QUOTA_P2_RQ2(p) (((p) & 0xfff) << 16) +#define GET_MAX_QUOTA_P2_RQ2(p) (((p) & MAX_QUOTA_P2_RQ2_MASK) >> 16) + +/* Flow Control Free for All and Free Page Counter Register */ +#define FC_FFC (PSE_BASE + 0x134) +#define FREE_PAGE_CNT_MASK (0xfff) +#define GET_FREE_PAGE_CNT(p) (((p) & FREE_PAGE_CNT_MASK)) +#define FFA_CNT_MASK (0xfff << 16) +#define GET_FFA_CNT(p) (((p) & FFA_CNT_MASK) >> 16) + +/* Flow Control Reserve from FFA priority Control Register */ +#define FC_FRP (PSE_BASE + 0x138) +#define RSRV_PRI_P0_MASK (0x7) +#define RSRV_PRI_P0(p) (((p) & 0x7)) +#define GET_RSRV_PRI_P0(p) (((p) & RSRV_PRI_P0_MASK)) +#define RSRV_PRI_P1_MASK (0x7 << 3) +#define RSRV_PRI_P1(p) (((p) & 0x7) << 3) +#define GET_RSRV_PRI_P1(p) (((p) & RSRV_PRI_P1_MASK) >> 3) +#define RSRV_PRI_P2_RQ0_MASK (0x7 << 6) +#define RSRV_PRI_P2_RQ0(p) (((p) & 0x7) << 6) +#define GET_RSRV_PRI_P2_RQ0(p) (((p) & RSRV_PRI_P2_RQ0_MASK) >> 6) +#define RSRV_PRI_P2_RQ1_MASK (0x7 << 9) +#define RSRV_PRI_P2_RQ1(p) (((p) & 0x7) << 9) +#define GET_RSRV_PRI_P2_RQ1(p) (((p) & RSRV_PRI_P2_RQ1_MASK) >> 9) +#define RSRV_PRI_P2_RQ2_MASK (0x7 << 12) +#define RSRV_PRI_P2_RQ2(p) (((p) & 0x7) << 12) +#define GET_RSRV_PRI_P2_RQ2(p) (((p) & RSRV_PRI_P2_RQ2_MASK) >> 12) + +/* Flow Control P0 and P1 Reserve Counter Register */ +#define FC_RP0P1 (PSE_BASE + 0x13c) +#define RSRV_CNT_P0_MASK (0xfff) +#define RSRV_CNT_P0(p) (((p) & 0xfff)) +#define GET_RSRV_CNT_P0(p) (((p) & RSRV_CNT_P0_MASK)) +#define RSRV_CNT_P1_MASK (0xfff << 16) +#define RSRV_CNT_P1(p) (((p) & 0xfff) << 16) +#define GET_RSRV_CNT_P1(p) (((p) & RSRV_CNT_P1_MASK) >> 16) + +/* Flow Control P2_RQ0 and P2_RQ1 Reserve Counter Register */ +#define FC_RP2Q0Q1 (PSE_BASE + 0x140) +#define RSRV_CNT_P2_RQ0_MASK (0xfff) +#define RSRV_CNT_P2_RQ0(p) (((p) & 0xfff)) +#define GET_RSRV_CNT_P2_RQ0(p) (((p) & RSRV_CNT_P2_RQ0_MASK)) +#define RSRV_CNT_P2_RQ1_MASK (0xfff << 16) +#define RSRV_CNT_P2_RQ1(p) (((p) & 0xfff) << 16) +#define GET_RSRV_CNT_P2_RQ1(p) (((p) & RSRV_CNT_P2_RQ1_MASK) >> 16) + +/* Flow Control P2_RQ2 Reserve Counter Register */ +#define FC_RP2Q2 (PSE_BASE + 0x144) +#define RSRV_CNT_P2_RQ2_MASK (0xfff) +#define RSRV_CNT_P2_RQ2(p) (((p) & 0xfff)) +#define GET_RSRV_CNT_P2_RQ2(p) (((p) & RSRV_CNT_P2_RQ2_MASK)) + +/* Flow Control P0 and P1 Source Counter Register */ +#define FC_SP0P1 (PSE_BASE + 0x148) +#define SRC_CNT_P0_MASK (0xfff) +#define GET_SRC_CNT_P0(p) (((p) & SRC_CNT_P0_MASK)) +#define SRC_CNT_P1_MASK (0xfff << 16) +#define GET_SRC_CNT_P1(p) (((p) & SRC_CNT_P1_MASK) >> 16) + +/* FLow Control P2_RQ0 and P2_RQ1 Source Counter Register */ +#define FC_SP2Q0Q1 (PSE_BASE + 0x14c) +#define SRC_CNT_P2_RQ0_MASK (0xfff) +#define GET_SRC_CNT_P2_RQ0(p) (((p) & SRC_CNT_P2_RQ0_MASK)) +#define SRC_CNT_P2_RQ1_MASK (0xfff << 16) +#define GET_SRC_CNT_P2_RQ1(p) (((p) & SRC_CNT_P2_RQ1_MASK) >> 16) + +/* Flow Control P2_RQ2 Source Counter Register */ +#define FC_SP2Q2 (PSE_BASE + 0x150) +#define SRC_CNT_P2_RQ2_MASK (0xfff) +#define GET_SRC_CNT_P2_RQ2(p) (((p) & 0xfff)) + +#define PSE_RTA (PSE_BASE + 0x194) +#define PSE_RTA_RD_RULE_QID_MASK (0x1f) +#define PSE_RTA_RD_RULE_QID(p) (((p) & 0x1f)) +#define GET_PSE_RTA_RD_RULE_QID(p) (((p) & PSE_RTA_RD_RULE_QID_MASK)) +#define PSE_RTA_RD_RULE_PID_MASK (0x3 << 5) +#define PSE_RTA_RD_RULE_PID(p) (((p) & 0x3) << 5) +#define GET_PSE_RTA_RD_RULE_PID(p) (((p) & PSE_RTA_RD_RULE_PID_MASK) >> 5) +#define PSE_RTA_RD_RULE_F (1 << 7) +#define GET_PSE_RTA_RD_RULE_F(p) (((p) & PSE_RTA_RD_RULE_F) >> 7) +#define PSE_RTA_TAG_MASK (0xff << 8) +#define PSE_RTA_TAG(p) (((p) & 0xff) << 8) +#define GET_PSE_RTA_TAG(p) (((p) & PSE_RTA_TAG_MASK) >> 8) +#define PSE_RTA_RD_RW (1 << 16) +#define PSE_RTA_RD_KICK_BUSY (1 << 31) +#define GET_PSE_RTA_RD_KICK_BUSY(p) (((p) & PSE_RTA_RD_KICK_BUSY) >> 31) + +#endif /* _PSE */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/wf_ple.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/wf_ple.h new file mode 100644 index 0000000000000..c6144a0a9aca3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/chips/wf_ple.h @@ -0,0 +1,231 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + wf_ple.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ------------------------------------- +*/ + +#ifndef __WF_PLE_H__ +#define __WF_PLE_H__ + +#define PLE_BASE 0x8000 + + +/* PLE Buffer Control Register */ +#define PLE_PBUF_CTRL (PLE_BASE + 0x14) +#define PLE_TOTAL_PAGE_NUM_MASK (0xfff) +#define PLE_GET_TOTAL_PAGE_NUM(p) (((p) & 0xfff)) +#define PLE_TOTAL_PAGE_CFG_MASK (0xf << 16) +#define PLE_GET_TOTAL_PAGE_CFG(p) (((p) & PSE_TOTAL_PAGE_CFG_MASK) >> 16) +#define PLE_PBUF_OFFSET_MASK (0xf << 20) +#define GET_PLE_PBUF_OFFSET(p) (((p) & PSE_PBUF_OFFSET_MASK) >> 20) + + +/* Release Control */ +#define PLE_RELEASE_CTRL (PLE_BASE + 0x30) +#define PLE_NORMAL_TX_RLS_QID_MASK (0x1f) +#define GET_PLE_NORMAL_TX_RLS_QID(p) (((p) & GET_FIRST_FID_MASK)) +#define PLE_NORMAL_TX_RLS_PID_MASK (0x3 << 6) +#define GET_PLE_NORMAL_TX_RLS_PID(p) (((p) & PLE_NORMAL_TX_RLS_PID_MASK) >> 6) + +#define BCNx_RLS_QID_MASK (0x1f) +#define BCNx_RLS_PID_MASK (0x3) +#define SET_BCN0_RLS_QID(p) (((p) & BCNx_RLS_QID_MASK) << 16) +#define SET_BCN0_RLS_PID(p) (((p) & BCNx_RLS_PID_MASK) << 22) +#define SET_BCN1_RLS_QID(p) (((p) & BCNx_RLS_QID_MASK) << 24) +#define SET_BCN1_RLS_PID(p) (((p) & BCNx_RLS_PID_MASK) << 30) + +#define PLE_GC (PLE_BASE) +#define PLE_INT_STS (PLE_BASE + 0x24) +#define PLE_INT_ERR_STS (PLE_BASE + 0x28) + +/* HIF Report Control */ +#define PLE_HIF_REPORT (PLE_BASE + 0x34) + +/* CPU Interface get frame ID Control */ +#define PLE_C_GET_FID_0 (PLE_BASE + 0x40) + +/* CPU Interface get frame ID Control */ +#define PLE_C_GET_FID_1 (PLE_BASE + 0x44) + +#define PLE_C_EN_QUEUE_0 (PLE_BASE + 0x60) +#define PLE_C_EN_QUEUE_1 (PLE_BASE + 0x64) +#define PLE_C_EN_QUEUE_2 (PLE_BASE + 0x68) + +#define PLE_C_DE_QUEUE_0 (PLE_BASE + 0x80) +#define PLE_C_DE_QUEUE_1 (PLE_BASE + 0x84) +#define PLE_C_DE_QUEUE_2 (PLE_BASE + 0x88) +#define PLE_C_DE_QUEUE_3 (PLE_BASE + 0x8c) + +#define PLE_TO_N9_INT (PLE_BASE + 0xf0) +#define PLE_TO_N9_INT_TOGGLE_MASK 0x80000000 + + + +/* Queue Empty */ +#define PLE_QUEUE_EMPTY (PLE_BASE + 0xb0) +#define PLE_AC0_QUEUE_EMPTY_0 (PLE_BASE + 0x300) +#define PLE_AC0_QUEUE_EMPTY_1 (PLE_BASE + 0x304) +#define PLE_AC0_QUEUE_EMPTY_2 (PLE_BASE + 0x308) +#define PLE_AC0_QUEUE_EMPTY_3 (PLE_BASE + 0x30c) + +#define PLE_AC1_QUEUE_EMPTY_0 (PLE_BASE + 0x310) +#define PLE_AC1_QUEUE_EMPTY_1 (PLE_BASE + 0x314) +#define PLE_AC1_QUEUE_EMPTY_2 (PLE_BASE + 0x318) +#define PLE_AC1_QUEUE_EMPTY_3 (PLE_BASE + 0x31c) + +#define PLE_AC2_QUEUE_EMPTY_0 (PLE_BASE + 0x320) +#define PLE_AC2_QUEUE_EMPTY_1 (PLE_BASE + 0x324) +#define PLE_AC2_QUEUE_EMPTY_2 (PLE_BASE + 0x328) +#define PLE_AC2_QUEUE_EMPTY_3 (PLE_BASE + 0x32c) + +#define PLE_AC3_QUEUE_EMPTY_0 (PLE_BASE + 0x330) +#define PLE_AC3_QUEUE_EMPTY_1 (PLE_BASE + 0x334) +#define PLE_AC3_QUEUE_EMPTY_2 (PLE_BASE + 0x338) +#define PLE_AC3_QUEUE_EMPTY_3 (PLE_BASE + 0x33c) + +#define PLE_STATION_PAUSE0 (PLE_BASE + 0x360) +#define PLE_STATION_PAUSE1 (PLE_BASE + 0x364) +#define PLE_STATION_PAUSE2 (PLE_BASE + 0x368) +#define PLE_STATION_PAUSE3 (PLE_BASE + 0x36C) + +/* Page Flow Control */ +#define PLE_FREEPG_CNT (PLE_BASE + 0x100) + +#define PLE_FREEPG_HEAD_TAIL (PLE_BASE + 0x104) + +#define PLE_PG_HIF_GROUP (PLE_BASE + 0x110) +#define PLE_HIF_PG_INFO (PLE_BASE + 0x114) + +#define PLE_PG_CPU_GROUP (PLE_BASE + 0x150) +#define PLE_CPU_PG_INFO (PLE_BASE + 0x154) + + +/* Indirect path for read/write */ +#define PLE_FL_QUE_CTRL_0 (PLE_BASE + 0x1b0) +#define PLE_FL_QUE_CTRL_1 (PLE_BASE + 0x1b4) +#define PLE_FL_QUE_CTRL_2 (PLE_BASE + 0x1b8) +#define PLE_FL_QUE_CTRL_3 (PLE_BASE + 0x1bc) +#define PLE_PL_QUE_CTRL_0 (PLE_BASE + 0x1c0) + +/* Disable Station control */ +#define DIS_STA_MAP0 (PLE_BASE + 0x260) +#define DIS_STA_MAP1 (PLE_BASE + 0x264) +#define DIS_STA_MAP2 (PLE_BASE + 0x268) +#define DIS_STA_MAP3 (PLE_BASE + 0x26c) + +/* Station Pause control register */ +#define STATION_PAUSE0 (PLE_BASE + 0x360) +#define STATION_PAUSE1 (PLE_BASE + 0x364) +#define STATION_PAUSE2 (PLE_BASE + 0x368) +#define STATION_PAUSE3 (PLE_BASE + 0x36c) + +#define PLE_PEEK_CR_0 (PLE_BASE + 0x3d0) +#define PLE_PEEK_CR_OFFSET 0x4 +#define PLE_PEEK_CR_NUM 12 + +/* VOW Ctrl */ +#define VOW_RESET_DISABLE (1 << 26) +#define STA_MAX_DEFICIT_MASK (0x0000FFFF) +#define VOW_DBDC_BW_GROUP_CTRL (PLE_BASE + 0x2ec) +#define VOW_CONTROL (PLE_BASE + 0x370) +#define AIRTIME_DRR_SIZE (PLE_BASE + 0x374) + + +enum ENUM_UMAC_PORT { + ENUM_UMAC_HIF_PORT_0 = 0, + ENUM_UMAC_CPU_PORT_1 = 1, + ENUM_UMAC_LMAC_PORT_2 = 2, + ENUM_PLE_CTRL_PSE_PORT_3 = 3, + ENUM_UMAC_PSE_PLE_PORT_TOTAL_NUM = 4 +}; + +/* N9 MCU QUEUE LIST */ +enum ENUM_UMAC_CPU_P_QUEUE { + ENUM_UMAC_CTX_Q_0 = 0, + ENUM_UMAC_CTX_Q_1 = 1, + ENUM_UMAC_CTX_Q_2 = 2, + ENUM_UMAC_CTX_Q_3 = 3, + ENUM_UMAC_CRX = 0, + ENUM_UMAC_CIF_QUEUE_TOTAL_NUM = 4 +}; + + +/* LMAC PLE TX QUEUE LIST */ +enum ENUM_UMAC_LMAC_PLE_TX_P_QUEUE { + ENUM_UMAC_LMAC_PLE_TX_Q_00 = 0x00, + ENUM_UMAC_LMAC_PLE_TX_Q_01 = 0x01, + ENUM_UMAC_LMAC_PLE_TX_Q_02 = 0x02, + ENUM_UMAC_LMAC_PLE_TX_Q_03 = 0x03, + + ENUM_UMAC_LMAC_PLE_TX_Q_10 = 0x04, + ENUM_UMAC_LMAC_PLE_TX_Q_11 = 0x05, + ENUM_UMAC_LMAC_PLE_TX_Q_12 = 0x06, + ENUM_UMAC_LMAC_PLE_TX_Q_13 = 0x07, + + ENUM_UMAC_LMAC_PLE_TX_Q_20 = 0x08, + ENUM_UMAC_LMAC_PLE_TX_Q_21 = 0x09, + ENUM_UMAC_LMAC_PLE_TX_Q_22 = 0x0a, + ENUM_UMAC_LMAC_PLE_TX_Q_23 = 0x0b, + + ENUM_UMAC_LMAC_PLE_TX_Q_30 = 0x0c, + ENUM_UMAC_LMAC_PLE_TX_Q_31 = 0x0d, + ENUM_UMAC_LMAC_PLE_TX_Q_32 = 0x0e, + ENUM_UMAC_LMAC_PLE_TX_Q_33 = 0x0f, + + ENUM_UMAC_LMAC_PLE_TX_Q_ALTX_0 = 0x10, + ENUM_UMAC_LMAC_PLE_TX_Q_BMC_0 = 0x11, + ENUM_UMAC_LMAC_PLE_TX_Q_BNC_0 = 0x12, + ENUM_UMAC_LMAC_PLE_TX_Q_PSMP_0 = 0x13, + + ENUM_UMAC_LMAC_PLE_TX_Q_ALTX_1 = 0x14, + ENUM_UMAC_LMAC_PLE_TX_Q_BMC_1 = 0x15, + ENUM_UMAC_LMAC_PLE_TX_Q_BNC_1 = 0x16, + ENUM_UMAC_LMAC_PLE_TX_Q_PSMP_1 = 0x17, + ENUM_UMAC_LMAC_PLE_TX_Q_NAF = 0x18, + ENUM_UMAC_LMAC_PLE_TX_Q_NBCN = 0x19, +/* DE suggests not to use 0x1f, it's only for hw free queue */ + ENUM_UMAC_LMAC_PLE_TX_Q_RELEASE = 0x1f, + ENUM_UMAC_LMAC_QUEUE_TOTAL_NUM = 24, + +}; + +/* LMAC PLE For PSE Control P3 */ +enum ENUM_UMAC_PLE_CTRL_P3_QUEUE { + ENUM_UMAC_PLE_CTRL_P3_Q_0X1E = 0x1e, + ENUM_UMAC_PLE_CTRL_P3_Q_0X1F = 0x1f, + ENUM_UMAC_PLE_CTRL_P3_TOTAL_NUM = 2 +}; + + + +struct EMPTY_QUEUE_INFO { + int8_t *QueueName; + uint32_t Portid; + uint32_t Queueid; +}; + + +#endif /* __WF_PLE_H__ */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/config.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/config.h new file mode 100644 index 0000000000000..5d83a87d237a7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/config.h @@ -0,0 +1,1401 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/config.h#3 + */ + +/*! \file "config.h" + * \brief This file includes the various configurable parameters for + * customers + * + * This file ncludes the configurable parameters except the parameters + * indicate the turning-on/off of some features + */ + +#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 + ******************************************************************************* + */ + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +/* 2 Flags for OS capability */ + +#if defined(_HIF_SDIO) +/* #ifdef CONFIG_X86 */ +/*Kernel-3.10-ARM did not provide X86_FLAG & HIF shouldn't bind platform*/ +#if (CFG_MTK_ANDROID_WMT) +#define MTK_WCN_HIF_SDIO 1 +#else +#define MTK_WCN_HIF_SDIO 0 +#endif +#else +#define MTK_WCN_HIF_SDIO 0 +#endif + +#if defined(_HIF_AXI) +#ifdef LINUX +#ifdef CONFIG_X86 +#define MTK_WCN_HIF_AXI 0 +#else +#define MTK_WCN_HIF_AXI 1 +#endif +#else +#define MTK_WCN_HIF_AXI 0 +#endif +#else +#define MTK_WCN_HIF_AXI 0 +#endif + + + +/* Android build-in driver switch, Mike 2016/11/11*/ +#ifndef CFG_BUILT_IN_DRIVER +#define CFG_BUILT_IN_DRIVER 0 +#endif + +/* Mike 2016/09/01 ALPS update K3.18 80211_disconnect to K4.4 version*/ +/* work around for any alps K3.18 platform*/ +#ifndef CFG_WPS_DISCONNECT +#define CFG_WPS_DISCONNECT 0 +#endif + + +#if (CFG_SUPPORT_AEE == 1) +/* TODO: temp remove for 7663 on mobile */ +/* #define CFG_ENABLE_AEE_MSG 1 */ +#define CFG_ENABLE_AEE_MSG 0 +#else +#define CFG_ENABLE_AEE_MSG 0 +#endif + +#define CFG_ENABLE_EARLY_SUSPEND 0 +#define CFG_ENABLE_NET_DEV_NOTIFY 1 + +/* 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" */ +#define CFG_SUPPORT_DEBUG_FS 0 +#define CFG_SUPPORT_SET_CAM_BY_PROC 1 /*Enable/disable powersave mode*/ + +#ifndef LINUX +#define CFG_FW_FILENAME L"WIFI_RAM_CODE" +#define CFG_CR4_FW_FILENAME L"WIFI_RAM_CODE2" +#else +#define CFG_FW_FILENAME "WIFI_RAM_CODE" +#define CFG_CR4_FW_FILENAME "WIFI_RAM_CODE2" +#endif + +#ifndef CFG_MET_PACKET_TRACE_SUPPORT +#define CFG_MET_PACKET_TRACE_SUPPORT 0 /*move to wlan/MAKEFILE */ +#endif + +#ifndef CFG_MET_TAG_SUPPORT +#define CFG_MET_TAG_SUPPORT 0 +#endif + +/* Support AP Selection */ +#define CFG_SUPPORT_RSN_SCORE 0 +#define CFG_SELECT_BSS_BASE_ON_MULTI_PARAM 1 +#define CFG_MAX_NUM_OF_CHNL_INFO 50 +#define CFG_SUPPORT_CHNL_CONFLICT_REVISE 0 + +#ifndef CFG_RX_NAPI_SUPPORT +#define CFG_RX_NAPI_SUPPORT 0 +#endif + +/* SUPPORT GRO only if NAPI enabled */ +#define CFG_GRO_SUPPORT CFG_RX_NAPI_SUPPORT + + +/*------------------------------------------------------------------------------ + * Driver config + *------------------------------------------------------------------------------ + */ + +#ifndef LINUX +#define CFG_SUPPORT_CFG_FILE 0 +#else +#define CFG_SUPPORT_CFG_FILE 1 +#endif + +#ifndef CFG_SUPPORT_PERF_IND +#define CFG_SUPPORT_PERF_IND 1 +#endif + +/*!< 1(default): Enable 802.11d */ +#define CFG_SUPPORT_802_11D 1 +/* 0: Disable */ + +/* Radio Reasource Measurement (802.11k) */ +#define CFG_SUPPORT_RRM 0 + +/* DFS (802.11h) */ +#define CFG_SUPPORT_DFS 1 +#ifndef CFG_SUPPORT_DFS_MASTER +#define CFG_SUPPORT_DFS_MASTER 1 +/* SoftAp Cross Band Channel Switch */ +#define CFG_SUPPORT_IDC_CH_SWITCH 1 +#endif + +#if (CFG_SUPPORT_DFS == 1) /* Add by Enlai */ +/* Quiet (802.11h) */ +#define CFG_SUPPORT_QUIET 0 +/* Spectrum Management (802.11h): TPC and DFS */ +#define CFG_SUPPORT_SPEC_MGMT 1 +#else +/* Quiet (802.11h) */ +#define CFG_SUPPORT_QUIET 0 +/* Spectrum Management (802.11h): TPC and DFS */ +#define CFG_SUPPORT_SPEC_MGMT 0 +#endif + +/* 11n feature. RX RDG capability */ +#define CFG_SUPPORT_RX_RDG 0 + +/* 802.11n MCS Feedback responder */ +#define CFG_SUPPORT_MFB 0 + +/* 802.11n RX STBC (1SS) */ +#define CFG_SUPPORT_RX_STBC 1 + +/* 802.11n RX short GI for both 20M and 40M BW */ +#define CFG_SUPPORT_RX_SGI 1 + +/* 802.11n RX HT green-field capability */ +#define CFG_SUPPORT_RX_HT_GF 1 + +#define CFG_SUPPORT_BFER 1 +#define CFG_SUPPORT_BFEE 1 + +#ifndef CFG_SUPPORT_WAPI +#define CFG_SUPPORT_WAPI 1 +#endif + +/* Enable QA Tool Support */ +#define CFG_SUPPORT_QA_TOOL 1 + +/* Enable TX BF Support */ +#define CFG_SUPPORT_TX_BF 1 + +#define CFG_SUPPORT_TX_BF_FPGA 1 + +/* Enable MU MIMO Support */ +#define CFG_SUPPORT_MU_MIMO 1 + +/* Enable WOW Support */ +#define CFG_WOW_SUPPORT 1 + +/* Disable WOW EINT mode */ +#ifndef CFG_SUPPORT_WOW_EINT +#define CFG_SUPPORT_WOW_EINT 0 +#endif + +/* Disable magic packet vendor event */ +#ifndef CFG_SUPPORT_MAGIC_PKT_VENDOR_EVENT +#define CFG_SUPPORT_MAGIC_PKT_VENDOR_EVENT 0 +#endif + +/* Enable A-MSDU RX Reordering Support */ +#define CFG_SUPPORT_RX_AMSDU 1 + +/* Disable Android wake_lock operations */ +#ifndef CFG_ENABLE_WAKE_LOCK +#define CFG_ENABLE_WAKE_LOCK 0 +#endif + +#define CFG_SUPPORT_OSHARE 1 + +#define CFG_SUPPORT_LOWLATENCY_MODE 1 + +/*------------------------------------------------------------------------------ + * Flags of Buffer mode SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_BUFFER_MODE 1 + +/*------------------------------------------------------------------------------ + * SLT Option + *------------------------------------------------------------------------------ + */ +#define CFG_SLT_SUPPORT 0 + +#ifdef NDIS60_MINIPORT +#define CFG_NATIVE_802_11 1 + +#define CFG_TX_MAX_PKT_SIZE 2304 + +/* !< 1: Enable TCP/IP header checksum offload */ +#define CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 0 + +/* 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 +#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 + *------------------------------------------------------------------------------ + */ +/*!< 1: Do workaround for faster bus timing */ +/* 0(default): Disable */ +#define CFG_EHPI_FASTER_BUS_TIMING 0 + +/*------------------------------------------------------------------------------ + * Flags for UMAC + *------------------------------------------------------------------------------ + */ +#define CFG_UMAC_GENERATION 0x20 + +/*------------------------------------------------------------------------------ + * Flags for HIFSYS Interface + *------------------------------------------------------------------------------ + */ +#ifdef _lint +/* #define _HIF_SDIO 1 */ +#endif + +/* 1(default): Enable SDIO ISR & TX/RX status enhance mode + * 0: Disable + */ +#define CFG_SDIO_INTR_ENHANCE 1 +/* 1(default): Enable SDIO ISR & TX/RX status enhance mode + * 0: Disable + */ +#define CFG_SDIO_RX_ENHANCE 1 +/* 1: Enable SDIO TX enhance mode(Multiple frames in single BLOCK CMD) + * 0(default): Disable + */ +#define CFG_SDIO_TX_AGG 1 + +/* 1: Enable SDIO RX enhance mode(Multiple frames in single BLOCK CMD) + * 0(default): Disable + */ +#define CFG_SDIO_RX_AGG 1 + +/* 1: Enable SDIO RX Workqueue De-Aggregation + * 0(default): Disable + */ +#ifndef CFG_SDIO_RX_AGG_WORKQUE +#define CFG_SDIO_RX_AGG_WORKQUE 0 +#endif + +#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 + +#ifdef WINDOWS_CE +/*!< 1: Support pass through (PATHRU) mode */ +#define CFG_SDIO_PATHRU_MODE 1 +/* 0: Disable */ +#else +/*!< 0: Always disable if WINDOWS_CE is not defined */ +#define CFG_SDIO_PATHRU_MODE 0 +#endif + +#define CFG_SDIO_ACCESS_N9_REGISTER_BY_MAILBOX 0 +#define CFG_MAX_RX_ENHANCE_LOOP_COUNT 3 + +#define CFG_USB_TX_AGG 1 +#define CFG_USB_CONSISTENT_DMA 0 +#define CFG_USB_TX_HANDLE_IN_HIF_THREAD 0 +#define CFG_USB_RX_HANDLE_IN_HIF_THREAD 0 + +#ifndef CFG_TX_DIRECT_USB +#define CFG_TX_DIRECT_USB 1 +#endif +#ifndef CFG_RX_DIRECT_USB +#define CFG_RX_DIRECT_USB 1 +#endif + +#if CFG_RX_DIRECT_USB +#define CFG_USB_RX_DISPATCH_CPU 0 +#else +#define CFG_USB_RX_DISPATCH_CPU 0 +#endif + +#define CFG_HW_WMM_BY_BSS 1 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Integration + *------------------------------------------------------------------------------ + */ + +#define CFG_MULTI_ECOVER_SUPPORT 1 + +#define CFG_ENABLE_CAL_LOG 1 +#define CFG_REPORT_RFBB_VERSION 1 + +#define MAX_BSSID_NUM 4 /* MAX BSSID number */ + + +#define CFG_CHIP_RESET_SUPPORT 1 +#if CFG_CHIP_RESET_SUPPORT +#define CFG_CHIP_RESET_HANG 0 +#endif + +#define HW_BSSID_NUM 4 /* HW BSSID number by chip */ + +/*------------------------------------------------------------------------------ + * Flags for workaround + *------------------------------------------------------------------------------ + */ + +/*------------------------------------------------------------------------------ + * Flags for driver version + *------------------------------------------------------------------------------ + */ +#define CFG_DRV_OWN_VERSION ((uint16_t)((NIC_DRIVER_MAJOR_VERSION << 8) | \ + (NIC_DRIVER_MINOR_VERSION))) +#define CFG_DRV_PEER_VERSION ((uint16_t)0x0000) + +/*------------------------------------------------------------------------------ + * Flags and Parameters for TX path + *------------------------------------------------------------------------------ + */ + +/*! Maximum number of SW TX packet queue */ +#define CFG_TX_MAX_PKT_NUM 1024 + +/*! Maximum number of SW TX CMD packet buffer */ +#define CFG_TX_MAX_CMD_PKT_NUM 32 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for RX path + *------------------------------------------------------------------------------ + */ + +/*------------------------------------------------------------------------------ + * CONFIG_TITLE : Move BA from FW to Driver + * OWNER : Puff Wen + * Description : Move BA from FW to Driver + *------------------------------------------------------------------------------ + */ +#define CFG_M0VE_BA_TO_DRIVER 0 + +/*! 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 HIF_NUM_OF_QM_RX_PKT_NUM + +/*! 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 */ +/* TODO: it should be 4096 under emulation mode */ +#define CFG_RX_MAX_PKT_SIZE (28 + 2312 + 12 /*HIF_RX_HEADER_T*/) + +/*! 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 */ + +/*! RX BA capability */ +#define CFG_NUM_OF_RX_BA_AGREEMENTS 10 +#if CFG_M0VE_BA_TO_DRIVER +#define CFG_RX_BA_MAX_WINSIZE 64 +#endif +#define CFG_RX_BA_INC_SIZE 64 +#define CFG_RX_MAX_BA_TID_NUM 8 +#define CFG_RX_REORDERING_ENABLED 1 + +#define CFG_PF_ARP_NS_MAX_NUM 3 + +#define CFG_COMPRESSION_DEBUG 0 +#define CFG_DECOMPRESSION_TMP_ADDRESS 0 +#define CFG_SUPPORT_COMPRESSION_FW_OPTION 0 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for CMD/RESPONSE + *------------------------------------------------------------------------------ + */ +#define CFG_RESPONSE_POLLING_TIMEOUT 1000 +#define CFG_RESPONSE_POLLING_DELAY 5 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Protocol Stack + *------------------------------------------------------------------------------ + */ +/*! Maximum number of BSS in the SCAN list */ +#define CFG_MAX_NUM_BSS_LIST 192 + +#define CFG_MAX_COMMON_IE_BUF_LEN ((1500 * CFG_MAX_NUM_BSS_LIST) / 3) + +/*! Maximum size of Header buffer of each SCAN record */ +#define CFG_RAW_BUFFER_SIZE 1024 + +/*! Maximum size of IE buffer of each SCAN record */ +#define CFG_IE_BUFFER_SIZE 512 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Power management + *------------------------------------------------------------------------------ + */ +#define CFG_ENABLE_FULL_PM 1 +#define CFG_ENABLE_WAKEUP_ON_LAN 0 + +/* debug which packet wake up host */ +#define CFG_SUPPORT_WAKEUP_REASON_DEBUG 1 + +#define CFG_INIT_POWER_SAVE_PROF ENUM_PSP_FAST_SWITCH + +#define CFG_INIT_ENABLE_PATTERN_FILTER_ARP 0 + +/* (BIT(3) | BIT(2) | BIT(1) | BIT(0)) */ +#define CFG_INIT_UAPSD_AC_BMP 0 + +/* #define CFG_SUPPORT_WAPI 0 */ +#define CFG_SUPPORT_WPS 1 +#define CFG_SUPPORT_WPS2 1 + +/*------------------------------------------------------------------------------ + * Flags of drop multicast packet when device suspend + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_DROP_MC_PACKET 0 + +/*------------------------------------------------------------------------------ + * 802.11i RSN Pre-authentication PMKID cahce maximun number + *------------------------------------------------------------------------------ + */ +/*!< max number of PMKID cache 16(default) : The Max PMKID cache */ +#define CFG_MAX_PMKID_CACHE 16 + +/*------------------------------------------------------------------------------ + * Auto Channel Selection maximun channel number + *------------------------------------------------------------------------------ + */ +/* ARRAY_SIZE(mtk_5ghz_channels) + ARRAY_SIZE(mtk_2ghz_channels) */ +#define MAX_CHN_NUM 39 + +#define MAX_2G_BAND_CHN_NUM 14 +#define MAX_5G_BAND_CHN_NUM (MAX_CHN_NUM - MAX_2G_BAND_CHN_NUM) +#define ACS_PRINT_BUFFER_LEN 200 + +/*------------------------------------------------------------------------------ + * 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) + +/*------------------------------------------------------------------------------ + * Maximum scan SSID number and channel number + * Should be aligned with FW scan command + *------------------------------------------------------------------------------ + */ +#define SCAN_CMD_SSID_NUM (4) +#define SCAN_CMD_CHNL_NUM (32) + +#if 1 +/* to be compatible with old FW, we set ssid num to 0 here, + * we should set correct num when query of scan capability from FW is done + */ +#define SCAN_CMD_EXT_SSID_NUM (0) +#define SCAN_CMD_EXT_CHNL_NUM (0) +#else +#define SCAN_CMD_EXT_SSID_NUM (6) +#define SCAN_CMD_EXT_CHNL_NUM (32) +#endif +#define CFG_SCAN_SSID_MAX_NUM (SCAN_CMD_SSID_NUM+SCAN_CMD_EXT_SSID_NUM) +#define MAXIMUM_OPERATION_CHANNEL_LIST (SCAN_CMD_CHNL_NUM+SCAN_CMD_EXT_CHNL_NUM) + + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Load Setup Default + *------------------------------------------------------------------------------ + */ + +/*------------------------------------------------------------------------------ + * Flags for enable 802.11A Band setting + *------------------------------------------------------------------------------ + */ + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Interrupt Process + *------------------------------------------------------------------------------ + */ +#define CFG_IST_LOOP_COUNT HIF_IST_LOOP_COUNT + +#define CFG_INT_WRITE_CLEAR 0 + +/* 2 Flags for Driver Debug Options */ +/*------------------------------------------------------------------------------ + * Flags of TX Debug Option. NOTE(Kevin): Confirm with SA before modifying + * following flags. + *------------------------------------------------------------------------------ + */ +/*!< 1: Debug statistics usage of MGMT Buffer */ +/* 0: Disable */ +#define CFG_DBG_MGT_BUF 1 + +#define CFG_HIF_STATISTICS 0 + +#define CFG_HIF_RX_STARVATION_WARNING 0 + +#define CFG_RX_PKTS_DUMP 0 + +#define CFG_SUPPORT_STATISTICS 1 + +#define CFG_ASSERT_DUMP 1 + +#define CFG_SUPPORT_TRACE_TC4 1 +/*------------------------------------------------------------------------------ + * Flags of Firmware Download Option. + *------------------------------------------------------------------------------ + */ +#define CFG_ENABLE_FW_DOWNLOAD 1 + +#define CFG_ENABLE_FW_DOWNLOAD_ACK 1 + +/*------------------------------------------------------------------------------ + * Flags of Bluetooth-over-WiFi (BT 3.0 + HS) support + *------------------------------------------------------------------------------ + */ + +#define CFG_ENABLE_BT_OVER_WIFI 0 + +#define CFG_BOW_SEPARATE_DATA_PATH 1 + +#define CFG_BOW_PHYSICAL_LINK_NUM 4 + +#define CFG_BOW_LIMIT_AIS_CHNL 1 + +#define CFG_BOW_SUPPORT_11N 1 + +#define CFG_BOW_RATE_LIMITATION 1 + +/*------------------------------------------------------------------------------ + * Flags of Wi-Fi Direct support + *------------------------------------------------------------------------------ + */ +/*------------------------------------------------------------------------------ + * Support reporting all BSS networks to cfg80211 kernel when scan + * request is from P2P interface + * Originally only P2P networks will be reported when scan request is from p2p0 + *------------------------------------------------------------------------------ + */ +#ifndef CFG_P2P_SCAN_REPORT_ALL_BSS +#define CFG_P2P_SCAN_REPORT_ALL_BSS 0 +#endif + +/*------------------------------------------------------------------------------ + * Flags for GTK rekey offload + *------------------------------------------------------------------------------ + */ + +#ifdef LINUX +#ifdef CONFIG_X86 +#define CFG_ENABLE_WIFI_DIRECT 1 +#define CFG_SUPPORT_802_11W 1 +#define CONFIG_SUPPORT_GTK_REKEY 1 +#else +#define CFG_ENABLE_WIFI_DIRECT 1 + +/*!< 0(default): Disable 802.11W */ +#define CFG_SUPPORT_802_11W 1 + +#define CONFIG_SUPPORT_GTK_REKEY 1 +#endif +#else /* !LINUX */ +#define CFG_ENABLE_WIFI_DIRECT 0 +#define CFG_SUPPORT_802_11W 0 /* Not support at WinXP */ +#endif /* LINUX */ + +#define CFG_SUPPORT_PERSISTENT_GROUP 0 + +#define CFG_TEST_WIFI_DIRECT_GO 0 + +#define CFG_TEST_ANDROID_DIRECT_GO 0 + +#define CFG_UNITEST_P2P 0 + +/* + * Enable cfg80211 option after Android 2.2(Froyo) is suggested, + * cfg80211 on linux 2.6.29 is not mature yet + */ +#define CFG_ENABLE_WIFI_DIRECT_CFG_80211 1 + +#define CFG_SUPPORT_HOTSPOT_OPTIMIZATION 0 +#define CFG_HOTSPOT_OPTIMIZATION_BEACON_INTERVAL 300 +#define CFG_HOTSPOT_OPTIMIZATION_DTIM 1 +#define CFG_AUTO_CHANNEL_SEL_SUPPORT 1 + +#ifndef CFG_ENABLE_UNIFY_WIPHY +#define CFG_ENABLE_UNIFY_WIPHY 1 +#endif + +/*------------------------------------------------------------------------------ + * 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 500 + +/*------------------------------------------------------------------------------ + * Migration Option + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_ADHOC 1 +#define CFG_SUPPORT_AAA 1 + +#define CFG_SUPPORT_BCM 0 +#define CFG_SUPPORT_BCM_BWCS 0 +#define CFG_SUPPORT_BCM_BWCS_DEBUG 0 + +#define CFG_SUPPORT_RDD_TEST_MODE 0 + +#define CFG_SUPPORT_PWR_MGT 1 + +#define CFG_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 0 +#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_TDLS 1 + +/* Enable/disable QoS TX, AMPDU */ +#define CFG_SUPPORT_QOS 1 + +#define CFG_SUPPORT_AMPDU_TX 1 +#define CFG_SUPPORT_AMPDU_RX 1 + +/* Enable/disable TS-related Action frames handling */ +#define CFG_SUPPORT_TSPEC 0 +#define CFG_SUPPORT_UAPSD 1 +#define CFG_SUPPORT_UL_PSMP 0 + +/* Roaming System */ +#ifndef CFG_SUPPORT_ROAMING +#define CFG_SUPPORT_ROAMING 1 +#endif + +#if (CFG_SUPPORT_ROAMING == 1) + +/* Roaming feature: skip roaming when only one ESSID AP + * Need Android background scan + * if no roaming event occurred + * to trigger roaming scan + * after skip roaming in one ESSID AP case + */ +#define CFG_SUPPORT_ROAMING_SKIP_ONE_AP 1 +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP +#define CFG_MAX_NUM_ROAM_BSS_LIST 64 +#endif +#else +#define CFG_SUPPORT_ROAMING_SKIP_ONE_AP 0 + +#endif /* CFG_SUPPORT_ROAMING */ + +#define CFG_SUPPORT_SWCR 1 + +#define CFG_SUPPORT_ANTI_PIRACY 1 + +#define CFG_SUPPORT_OSC_SETTING 1 + +#define CFG_SUPPORT_P2P_RSSI_QUERY 0 + +#define CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP 0 + +#define CFG_SHOW_MACADDR_SOURCE 1 + +#define CFG_SHOW_FULL_MACADDR 1 + +#define CFG_SUPPORT_VO_ENTERPRISE 1 +#define CFG_SUPPORT_WMM_AC 1 +#if CFG_SUPPORT_VO_ENTERPRISE +#define CFG_SUPPORT_802_11R 1 +#define CFG_SUPPORT_802_11K 1 +#else +#define CFG_SUPPORT_802_11R 0 +#define CFG_SUPPORT_802_11K 0 +#endif + +/* Support 802.11v Wireless Network Management */ +#define CFG_SUPPORT_802_11V 1 +#define CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT 1 +#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 + +#define WNM_UNIT_TEST CFG_SUPPORT_802_11V + +#define CFG_SUPPORT_PPR2 1 +#define CFG_DRIVER_COMPOSE_ASSOC_REQ 1 +#define CFG_SUPPORT_802_11AC 1 +#define CFG_STRICT_CHECK_CAPINFO_PRIVACY 0 + +#define CFG_SUPPORT_WFD 1 +#define CFG_SUPPORT_WFD_COMPOSE_IE 1 + +#define CFG_SUPPORT_HOTSPOT_WPS_MANAGER 1 +#define CFG_SUPPORT_NFC_BEAM_PLUS 1 + +/* Refer to CONFIG_MTK_STAGE_SCAN */ +#define CFG_MTK_STAGE_SCAN 1 + +/* Enable driver support multicore */ +#define CFG_SUPPORT_MULTITHREAD 1 + +#define CFG_SUPPORT_MTK_SYNERGY 1 + +#define CFG_SUPPORT_VHT_IE_IN_2G 1 + +#define CFG_SUPPORT_PWR_LIMIT_COUNTRY 1 + +#define CFG_FIX_2_TX_PORT 0 + +#define CFG_CHANGE_CRITICAL_PACKET_PRIORITY 0 + +/* Flags of WAC (Wireless Accessory Configuration) feature */ +#ifndef CFG_SUPPORT_WAC +#define CFG_SUPPORT_WAC 0 +#endif + +#ifndef CFG_DISCONN_DEBUG_FEATURE +#define CFG_DISCONN_DEBUG_FEATURE 1 +#define MAX_DISCONNECT_RECORD 5 +#endif + +/*------------------------------------------------------------------------------ + * Flags of bus error tolerance + *------------------------------------------------------------------------------ + */ +#define CFG_FORCE_RESET_UNDER_BUS_ERROR 0 + +/*------------------------------------------------------------------------------ + * Build Date Code Integration + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_BUILD_DATE_CODE 0 + +/*------------------------------------------------------------------------------ + * Flags of SDIO test pattern support + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_SDIO_READ_WRITE_PATTERN 1 + +/*------------------------------------------------------------------------------ + * Flags of Workaround + *------------------------------------------------------------------------------ + */ +#define CFG_ENABLE_READ_EXTRA_4_BYTES 1 + +/* Handle IOT issue for 11ac certification */ +#define CFG_OPMODE_CONFLICT_OPINFO 1 + + +/*------------------------------------------------------------------------------ + * Flags of 5G NVRAM SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_NVRAM_5G 1 + +/*------------------------------------------------------------------------------ + * Flags of Packet Lifetime Profiling Mechanism + *------------------------------------------------------------------------------ + */ +#define CFG_ENABLE_PKT_LIFETIME_PROFILE 1 +#define CFG_PRINT_PKT_LIFETIME_PROFILE 0 + +#define CFG_ENABLE_PER_STA_STATISTICS 1 + +#define CFG_ENABLE_PER_STA_STATISTICS_LOG 1 + +/*------------------------------------------------------------------------------ + * Flags for prepare the FW compile flag + *------------------------------------------------------------------------------ + */ +#define COMPILE_FLAG0_GET_STA_LINK_STATUS (1<<0) +#define COMPILE_FLAG0_WFD_ENHANCEMENT_PROTECT (1<<1) + +/*------------------------------------------------------------------------------ + * Flags of Batch Scan SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_BATCH_SCAN (0) +#define CFG_BATCH_MAX_MSCAN (2) + +/*------------------------------------------------------------------------------ + * Flags of SCHEDULE SCAN SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_PNO (0) +#define CFG_SUPPORT_SCHED_SCAN (0) +#define SCHED_SCAN_CMD_VERSION (1) + +/* this value should be aligned to auSsid in struct CMD_SCHED_SCAN_REQ */ +#define CFG_SCAN_HIDDEN_SSID_MAX_NUM (10) +/* this value should be aligned to auMatchSsid in struct CMD_SCHED_SCAN_REQ */ +#define CFG_SCAN_SSID_MATCH_MAX_NUM (16) + +#if CFG_SUPPORT_PNO != CFG_SUPPORT_SCHED_SCAN +#error Value of CFG_SUPPORT_SCHED_SCAN and CFG_SUPPORT_PNO should be the same +#endif + +/*------------------------------------------------------------------------------ + * Full2Partial Scan SUPPORT + *------------------------------------------------------------------------------ + */ +/* During a full2partial scan period, all online full scan requests would be + * changed to partial scan. The unit of this value is second + */ +#define CFG_SUPPORT_FULL2PARTIAL_SCAN (0) +#define CFG_SCAN_FULL2PARTIAL_PERIOD (60) + +/*------------------------------------------------------------------------------ + * Value of scan cache result + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_SCAN_CACHE_RESULT (0) +#define CFG_SCAN_CACHE_RESULT_PERIOD (7000) /* Unit: ms */ +#define CFG_SCAN_CACHE_MIN_CHANNEL_NUM (10) + +/*------------------------------------------------------------------------------ + * Default value: the duration in ms to check TRX + * while the beacon timeout event comes. + * This is the default value for + * prAdapter->rWifiVar.u4BeaconTimoutFilterDurationMs + * can customize + * 1. by project's requirement in this default value + * 2. or by define in wifi.cfg directly (BeaconTimoutFilterDurationMs) + * if the value set to 0, it means disable the filter. + * if the value set to 2000, it means the duration of fitler is 2000 ms + *------------------------------------------------------------------------------ + */ +#define CFG_BEACON_TIMEOUT_FILTER_DURATION_DEFAULT_VALUE 0 + +/*------------------------------------------------------------------------------ + * Flags of Random MAC support + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_SCAN_RANDOM_MAC (1) + +/*------------------------------------------------------------------------------ + * Flags of Sniffer SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_SNIFFER 1 + +#define WLAN_INCLUDE_PROC 1 + +/*------------------------------------------------------------------------------ + * Flags of Sniffer SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_DUAL_P2PLIKE_INTERFACE 1 + +#define RUNNING_P2P_MODE 0 +#define RUNNING_AP_MODE 1 +#define RUNNING_DUAL_AP_MODE 2 +#define RUNNING_P2P_AP_MODE 3 +#define RUNNING_P2P_MODE_NUM 4 + +/*------------------------------------------------------------------------------ + * Flags of MSP SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_MSP 1 + + + +/*------------------------------------------------------------------------------ + * Flags of driver fw customization + *------------------------------------------------------------------------------ + */ + +#define CFG_SUPPORT_EASY_DEBUG 1 + + +/*------------------------------------------------------------------------------ + * Flags of driver delay calibration atfer efuse buffer mode CMD + *------------------------------------------------------------------------------ + */ + +#define CFG_EFUSE_BUFFER_MODE_DELAY_CAL 1 + +/*------------------------------------------------------------------------------ + * Flags of Drop Packet Replay SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_REPLAY_DETECTION 1 + +/*------------------------------------------------------------------------------ + * Flags of driver EEPROM pages for QA tool + *------------------------------------------------------------------------------ + */ + +#define CFG_EEPROM_PAGE_ACCESS 1 + +/*------------------------------------------------------------------------------ + * Flags for HOST_OFFLOAD + *------------------------------------------------------------------------------ + */ + +#define CFG_SUPPORT_WIFI_HOST_OFFLOAD 1 + +/*------------------------------------------------------------------------------ + * Flags for DBDC Feature + *------------------------------------------------------------------------------ + */ + +#define CFG_SUPPORT_DBDC 1 + +/*------------------------------------------------------------------------------ + * Flags for Using TC4 Resource in ROM code stage + *------------------------------------------------------------------------------ + */ + +#define CFG_USE_TC4_RESOURCE_FOR_INIT_CMD 0 + +/*------------------------------------------------------------------------------ + * Flags for Efuse Start and End address report from FW + *------------------------------------------------------------------------------ + */ + +#define CFG_FW_Report_Efuse_Address 1 + +/*------------------------------------------------------------------------------ + * FW name max length + *------------------------------------------------------------------------------ + */ +#define CFG_FW_NAME_MAX_LEN (64) + +/*------------------------------------------------------------------------------ + * Support WMT WIFI Path Config + *------------------------------------------------------------------------------ + */ +#define CFG_WMT_WIFI_PATH_SUPPORT 0 + +/*------------------------------------------------------------------------------ + * Support CFG_SISO_SW_DEVELOP + *------------------------------------------------------------------------------ + */ +#define CFG_SISO_SW_DEVELOP 0 + +/*------------------------------------------------------------------------------ + * Support spatial extension control + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_SPE_IDX_CONTROL 1 + +/*------------------------------------------------------------------------------ + * Support coex wifi/BT non co-Tx + *------------------------------------------------------------------------------ + */ +#ifndef CFG_SUPPORT_COEX_NON_COTX +#define CFG_SUPPORT_COEX_NON_COTX 0 +#endif + +/*------------------------------------------------------------------------------ + * Support HW 1T2R + *------------------------------------------------------------------------------ + */ +#ifndef CFG_SUPPORT_HW_1T2R +#define CFG_SUPPORT_HW_1T2R 0 +#endif + +/*------------------------------------------------------------------------------ + * Flags for a Goal for MT6632 : Cal Result Backup in Host or NVRam when Android + * Boot + *------------------------------------------------------------------------------ + */ +#if 0 /*(MTK_WCN_HIF_SDIO) : 20161003 Default Off, later will enable + * by MTK_WCN_HIF_SDIO + */ +#define CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST 1 +#define CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST_DBGLOG 0 +#else +#define CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST 0 +#define CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST_DBGLOG 0 +#endif + +/*------------------------------------------------------------------------------ + * Enable SDIO 1-bit Data Mode. (Usually debug only) + *------------------------------------------------------------------------------ + */ +#define CFG_SDIO_1BIT_DATA_MODE 0 + +/*------------------------------------------------------------------------------ + * Single Sku + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_SINGLE_SKU 1 +#ifndef CFG_SUPPORT_SINGLE_SKU_LOCAL_DB +#define CFG_SUPPORT_SINGLE_SKU_LOCAL_DB 1 +#endif + + +/*------------------------------------------------------------------------------ + * Direct Control for RF/PHY/BB/MAC for Manual Configuration via command/api + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_ADVANCE_CONTROL 1 + +#define CFG_IPI_2CHAIN_SUPPORT 1 + + +/*------------------------------------------------------------------------------ + * Support antenna diversity + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_ANT_DIV 1 + + +/*------------------------------------------------------------------------------ + * Support mcc stay time setting + *------------------------------------------------------------------------------ + */ + +#define CFG_SUPPORT_ADJUST_MCC_STAY_TIME 1 + + +/*------------------------------------------------------------------------------ + * Driver pre-allocate total size of memory in one time + *------------------------------------------------------------------------------ + */ +#ifndef CFG_PRE_ALLOCATION_IO_BUFFER +#define CFG_PRE_ALLOCATION_IO_BUFFER 0 +#endif + +/*------------------------------------------------------------------------------ + * Auto enable SDIO asynchronous interrupt mode + *------------------------------------------------------------------------------ + */ +#define CFG_SDIO_ASYNC_IRQ_AUTO_ENABLE 1 + +/*------------------------------------------------------------------------------ + * Flags to force enable performance monitor even when screen is OFF + *------------------------------------------------------------------------------ + */ +#define CFG_FORCE_ENABLE_PERF_MONITOR 0 + +/*------------------------------------------------------------------------------ + * Flags to ignore invalid auth tsn issue (ex. ALPS03089071) + *------------------------------------------------------------------------------ + */ +#define CFG_IGNORE_INVALID_AUTH_TSN 1 + +/*------------------------------------------------------------------------------ + * Flags of Network Controlled HandOver(NCHO) support + * TC10 only: To improve the voice quality during handover, + * the NCHO is required to precisely control scanning parameters + * CFG_SUPPORT_NCHO: 1: support, 0: not support + * CFG_SUPPORT_NCHO_AUTO_ENABLE: sub-feature depends with CFG_SUPPORT_NCHO + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_NCHO 0 +#define CFG_SUPPORT_NCHO_AUTO_ENABLE 0 + +/*------------------------------------------------------------------------------ + * Flags of Key Word Exception Mechanism + *------------------------------------------------------------------------------ + */ +#define CFG_ENABLE_KEYWORD_EXCEPTION_MECHANISM 0 + +/*------------------------------------------------------------------------------ + * Driver supports preferred frequency list for p2p operating channel + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_P2P_PREFERRED_FREQ_LIST 1 + +/*------------------------------------------------------------------------------ + * Support Single RX chain setting + *------------------------------------------------------------------------------ + */ +#ifndef CFG_RX_SINGLE_CHAIN_SUPPORT +#define CFG_RX_SINGLE_CHAIN_SUPPORT 0 +#endif + +/*------------------------------------------------------------------------------ + * Support 1RPD MMPS control + *------------------------------------------------------------------------------ + */ +#ifndef CFG_ENABLE_1RPD_MMPS_CTRL +#define CFG_ENABLE_1RPD_MMPS_CTRL 0 +#endif + +/*------------------------------------------------------------------------------ + * Support DEWEIGHTING control + *------------------------------------------------------------------------------ + */ +#ifndef CFG_ENABLE_DEWEIGHTING_CTRL +#define CFG_ENABLE_DEWEIGHTING_CTRL 0 +#endif + +/*------------------------------------------------------------------------------ + * Flags of System Error Recovery Feature + *------------------------------------------------------------------------------ + */ +#ifndef CFG_SUPPORT_SER +#define CFG_SUPPORT_SER 1 +#endif + + +/*------------------------------------------------------------------------------ + * Support thermal API + *------------------------------------------------------------------------------ + */ +#ifndef CFG_THERMAL_API_SUPPORT +#define CFG_THERMAL_API_SUPPORT 0 +#endif + +/*------------------------------------------------------------------------------ + * Support EFUSE / EEPROM Auto Detect + *------------------------------------------------------------------------------ + */ +#ifndef CFG_EFUSE_AUTO_MODE_SUPPORT +#define CFG_EFUSE_AUTO_MODE_SUPPORT 1 +#endif + + +/*------------------------------------------------------------------------------ + * Support MCC mode setting + *------------------------------------------------------------------------------ + */ +#ifndef CFG_SUPPORT_ADJUST_MCC_MODE_SET +#define CFG_SUPPORT_ADJUST_MCC_MODE_SET 0 +#endif + +/*------------------------------------------------------------------------------ + * Support RX dynamic MCC priority scheduling + *------------------------------------------------------------------------------ + */ +#ifndef CFG_SUPPORT_RX_DYNAMIC_MCC_PRIORITY +#define CFG_SUPPORT_RX_DYNAMIC_MCC_PRIORITY 0 +#endif + +#define CFG_SUPPORT_PCIE_L2 1 +#define CFG_SUPPORT_PCIE_ASPM 0 + +#define CFG_SUPPORT_CUSTOM_NETLINK 0 +#if CFG_SUPPORT_CUSTOM_NETLINK +#define CFG_SUPPORT_TX_BEACON_STA_MODE 0 +#else +#define CFG_SUPPORT_TX_BEACON_STA_MODE 0 +#endif + +/*------------------------------------------------------------------------------ + * Support RX FE Loss Compensation + *------------------------------------------------------------------------------ + */ +#ifndef CFG_RCPI_COMPENSATION +#define CFG_RCPI_COMPENSATION 1 +#endif + +/*------------------------------------------------------------------------------ + * Flags of Last Second MCS Tx/Rx Info + *------------------------------------------------------------------------------ + */ +#ifndef CFG_SUPPORT_GET_MCS_INFO +#define CFG_SUPPORT_GET_MCS_INFO 0 +#endif + +#if (CFG_SUPPORT_GET_MCS_INFO == 1) +#define MCS_INFO_SAMPLE_CNT 10 +#define MCS_INFO_SAMPLE_PERIOD 100 /* Unit: ms */ +#endif + +#ifndef CFG_SUPPORT_AAA_CHECK_NO_SSID +#define CFG_SUPPORT_AAA_CHECK_NO_SSID 0 +#endif + +#ifndef CFG_MTK_ENGINEER_MODE_SUPPORT +#define CFG_MTK_ENGINEER_MODE_SUPPORT 1 +#endif + + +#ifndef CFG_SUPPORT_PER_BSS_FILTER +#define CFG_SUPPORT_PER_BSS_FILTER 1 +#endif + + +#ifndef CFG_SUPPORT_PROBE_REQ_REPORT +#define CFG_SUPPORT_PROBE_REQ_REPORT 1 +#endif + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#endif /* _CONFIG_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/debug.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/debug.h new file mode 100644 index 0000000000000..f28e68f7fc949 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/debug.h @@ -0,0 +1,474 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: include/debug.h + */ + +/*! \file debug.h + * \brief Definition of SW debugging level. + * + * In this file, it describes the definition of various SW debugging levels + * and assert functions. + */ + +#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 + +#define DBG_DISABLE_ALL_LOG 0 + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "gl_typedef.h" + +extern uint8_t aucDebugModule[]; +extern uint32_t au4LogLevel[]; + +extern void set_logtoomuch_enable(int value) __attribute__((weak)); +extern int get_logtoomuch_enable(void) __attribute__((weak)); + +/******************************************************************************* + * 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) + +#define DBG_LOG_LEVEL_DEFAULT \ + (DBG_CLASS_ERROR | \ + DBG_CLASS_WARN | \ + DBG_CLASS_STATE | \ + DBG_CLASS_EVENT | \ + DBG_CLASS_INFO) +#define DBG_LOG_LEVEL_MORE \ + (DBG_LOG_LEVEL_DEFAULT | \ + DBG_CLASS_TRACE) +#define DBG_LOG_LEVEL_EXTREME \ + (DBG_LOG_LEVEL_MORE | \ + DBG_CLASS_LOUD) + +#if defined(LINUX) +#define DBG_PRINTF_64BIT_DEC "lld" +#else /* Windows */ +#define DBG_PRINTF_64BIT_DEC "I64d" +#endif +#define DBG_ALL_MODULE_IDX 0xFFFFFFFF + +#define DEG_HIF_ALL BIT(0) +#define DEG_HIF_HOST_CSR BIT(1) +#define DEG_HIF_PDMA BIT(2) +#define DEG_HIF_DMASCH BIT(3) +#define DEG_HIF_PSE BIT(4) +#define DEG_HIF_PLE BIT(5) +#define DEG_HIF_MAC BIT(6) +#define DEG_HIF_PHY BIT(7) + +#define DEG_HIF_DEFAULT_DUMP \ + (DEG_HIF_HOST_CSR | DEG_HIF_PDMA | DEG_HIF_DMASCH | \ + DEG_HIF_PSE | DEG_HIF_PLE) + +#define HIF_CHK_TX_HANG BIT(1) +#define HIF_DRV_SER BIT(2) + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +/* Define debug module index */ +enum ENUM_DBG_MODULE { + DBG_INIT_IDX = 0, /* 0x00 *//* For driver initial */ + DBG_HAL_IDX, /* 0x01 *//* For HAL(HW) Layer */ + DBG_INTR_IDX, /* 0x02 *//* For Interrupt */ + DBG_REQ_IDX, /* 0x03 */ + DBG_TX_IDX, /* 0x04 */ + DBG_RX_IDX, /* 0x05 */ + DBG_RFTEST_IDX, /* 0x06 *//* For RF test mode */ + DBG_EMU_IDX, /* 0x07 *//* Developer specific */ + DBG_SW1_IDX, /* 0x08 *//* Developer specific */ + DBG_SW2_IDX, /* 0x09 *//* Developer specific */ + DBG_SW3_IDX, /* 0x0A *//* Developer specific */ + DBG_SW4_IDX, /* 0x0B *//* Developer specific */ + DBG_HEM_IDX, /* 0x0C *//* HEM */ + DBG_AIS_IDX, /* 0x0D *//* AIS */ + DBG_RLM_IDX, /* 0x0E *//* RLM */ + DBG_MEM_IDX, /* 0x0F *//* RLM */ + DBG_CNM_IDX, /* 0x10 *//* CNM */ + DBG_RSN_IDX, /* 0x11 *//* RSN */ + DBG_BSS_IDX, /* 0x12 *//* BSS */ + DBG_SCN_IDX, /* 0x13 *//* SCN */ + DBG_SAA_IDX, /* 0x14 *//* SAA */ + DBG_AAA_IDX, /* 0x15 *//* AAA */ + DBG_P2P_IDX, /* 0x16 *//* P2P */ + DBG_QM_IDX, /* 0x17 *//* QUE_MGT */ + DBG_SEC_IDX, /* 0x18 *//* SEC */ + DBG_BOW_IDX, /* 0x19 *//* BOW */ + DBG_WAPI_IDX, /* 0x1A *//* WAPI */ + DBG_ROAMING_IDX, /* 0x1B *//* ROAMING */ + DBG_TDLS_IDX, /* 0x1C *//* TDLS *//* CFG_SUPPORT_TDLS */ + DBG_PF_IDX, /* 0x1D *//* PF */ + DBG_OID_IDX, + DBG_NIC_IDX, + DBG_WNM_IDX, + DBG_WMM_IDX, + DBG_MODULE_NUM /* Notice the XLOG check */ +}; +enum ENUM_DBG_ASSERT_CTRL_LEVEL { + DBG_ASSERT_CTRL_LEVEL_ERROR, + DBG_ASSERT_CTRL_LEVEL_WARN, + DBG_ASSERT_CTRL_LEVEL_LITE +}; +enum ENUM_DBG_ASSERT_PATH { + DBG_ASSERT_PATH_WIFI, + DBG_ASSERT_PATH_WMT +}; + +struct CHIP_DBG_OPS { + void (*showPdmaInfo)(IN struct ADAPTER *prAdapter); + void (*showPseInfo)(IN struct ADAPTER *prAdapter); + void (*showPleInfo)(IN struct ADAPTER *prAdapter); + bool (*showCsrInfo)(IN struct ADAPTER *prAdapter); + void (*showDmaschInfo)(IN struct ADAPTER *prAdapter); +}; + +enum PKT_PHASE { + PHASE_XMIT_RCV, + PHASE_ENQ_QM, + PHASE_HIF_TX, +}; + +struct WLAN_DEBUG_INFO { + u_int8_t fgVoE5_7Test:1; + u_int8_t fgReserved:7; +}; + +#if MTK_WCN_HIF_SDIO +#define DBG_ASSERT_PATH_DEFAULT DBG_ASSERT_PATH_WMT +#else +#define DBG_ASSERT_PATH_DEFAULT DBG_ASSERT_PATH_WIFI +#endif +#define DBG_ASSERT_CTRL_LEVEL_DEFAULT DBG_ASSERT_CTRL_LEVEL_ERROR +/******************************************************************************* + * P U B 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) +#if CFG_SHOW_FULL_MACADDR +/* Debug print format string for the MAC Address */ +#define MACSTR "%pM" +/* Debug print argument for the MAC Address */ +#define MAC2STR(a) a +#else +#define MACSTR "%02x:%02x:**:**:**:%02x" +#define MAC2STR(a) ((uint8_t *)a)[0], ((uint8_t *)a)[1], ((uint8_t *)a)[5] +#endif +/* Debug print format string for the IPv4 Address */ +#define IPV4STR "%pI4" +/* Debug print argument for the IPv4 Address */ +#define IPV4TOSTR(a) a +/* Debug print format string for the IPv6 Address */ +#define IPV6STR "%pI6" +/* Debug print argument for the IPv6 Address */ +#define IPV6TOSTR(a) a +/* The pre-defined format to dump the varaible value 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)) +/* Debug print format string for the floating point */ +#define FPSTR "%u.%u" +/* Debug print argument for the floating point */ +#define DIV2INT(_dividend, _divisor) \ + ((_divisor) ? (_dividend) / (_divisor) : 0) +#define DIV2DEC(_dividend, _divisor) \ + ((_divisor) ? (((_dividend) * 100) / (_divisor)) % 100 : 0) +/* 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 kalPrint +#define LOG_FUNC_LIMITED kalPrintLimited + +/* If __FUNCTION__ is already defined by compiler, we just use it. */ +#define DEBUGFUNC(_Func) +/* Disabled due to AOSP + * #if defined(__FUNCTION__) + * #define DEBUGFUNC(_Func) + * #else + * #define DEBUGFUNC(_Func) static const char __FUNCTION__[] = _Func; + * #endif + */ +#if DBG_DISABLE_ALL_LOG +#define DBGLOG(_Module, _Class, _Fmt) +#define DBGLOG_LIMITED(_Module, _Class, _Fmt) +#define DBGLOG_MEM8(_Module, _Class, _StartAddr, _Length) +#define DBGLOG_MEM32(_Module, _Class, _StartAddr, _Length) +#else +#define DBGLOG(_Mod, _Clz, _Fmt, ...) \ + do { \ + if ((aucDebugModule[DBG_##_Mod##_IDX] & \ + DBG_CLASS_##_Clz) == 0) \ + break; \ + LOG_FUNC("[%u]%s:(" #_Mod " " #_Clz ") " _Fmt, \ + KAL_GET_CURRENT_THREAD_ID(), \ + __func__, ##__VA_ARGS__); \ + } while (0) +#define DBGLOG_LIMITED(_Mod, _Clz, _Fmt, ...) \ + do { \ + if ((aucDebugModule[DBG_##_Mod##_IDX] & \ + DBG_CLASS_##_Clz) == 0) \ + break; \ + LOG_FUNC_LIMITED("[%u]%s:(" #_Mod " " #_Clz ") " _Fmt, \ + KAL_GET_CURRENT_THREAD_ID(), \ + __func__, ##__VA_ARGS__); \ + } while (0) +#define DBGFWLOG(_Mod, _Clz, _Fmt, ...) \ + do { \ + if ((aucDebugModule[DBG_##_Mod##_IDX] & \ + DBG_CLASS_##_Clz) == 0) \ + break; \ + wlanPrintFwLog(NULL, 0, DEBUG_MSG_TYPE_DRIVER, \ + "[%u]%s:(" #_Mod " " #_Clz ") " _Fmt, \ + KAL_GET_CURRENT_THREAD_ID(), \ + __func__, ##__VA_ARGS__); \ + } while (0) +#define TOOL_PRINTLOG(_Mod, _Clz, _Fmt, ...) \ + do { \ + if ((aucDebugModule[DBG_##_Mod##_IDX] & \ + DBG_CLASS_##_Clz) == 0) \ + break; \ + LOG_FUNC(_Fmt, ##__VA_ARGS__); \ + } while (0) +#define DBGLOG_MEM8(_Mod, _Clz, _Adr, _Len) \ + { \ + if (aucDebugModule[DBG_##_Mod##_IDX] & DBG_CLASS_##_Clz) { \ + LOG_FUNC("%s:(" #_Mod " " #_Clz ")\n", __func__); \ + dumpMemory8((uint8_t *)(_Adr), (uint32_t)(_Len)); \ + } \ + } +#define DBGLOG_MEM32(_Mod, _Clz, _Adr, _Len) \ + { \ + if (aucDebugModule[DBG_##_Mod##_IDX] & DBG_CLASS_##_Clz) { \ + LOG_FUNC("%s:(" #_Mod " " #_Clz ")\n", __func__); \ + dumpMemory32((uint32_t *)(_Adr), (uint32_t)(_Len)); \ + } \ + } +#endif +#define DISP_STRING(_str) _str +#undef ASSERT +#undef ASSERT_REPORT +#if (BUILD_QA_DBG || DBG) +#define ASSERT_NOMEM() \ +{ \ + LOG_FUNC("alloate memory failed at %s:%d\n", __FILE__, __LINE__); \ + kalSendAeeWarning("Wlan_Gen4 No Mem", "Memory Alloate Failed %s:%d",\ + __FILE__, __LINE__); \ +} +#ifdef _lint +#define ASSERT(_exp) \ + { \ + if (!(_exp)) { \ + do {} while (1); \ + } \ + } +#define ASSERT_REPORT(_exp, _fmt) \ + { \ + LOG_FUNC("Assertion failed: %s:%d (%s)\n", \ + __FILE__, __LINE__, #_exp); \ + LOG_FUNC _fmt; \ + if (!(_exp)) { \ + do {} while (1); \ + } \ + } +#elif defined(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_NOMEM() \ +{ \ + LOG_FUNC("alloate memory failed at %s:%d\n", __FILE__, __LINE__); \ + kalSendAeeWarning("Wlan_Gen4 No Mem", "Memory Alloate Failed %s:%d",\ + __FILE__, __LINE__); \ +} + +#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(); \ + } \ + } +#endif /* WINDOWS_CE */ +#else +#define ASSERT_NOMEM() +#define ASSERT(_exp) +#define ASSERT_REPORT(_exp, _fmt) +#endif /* BUILD_QA_DBG */ +/* LOG function for print to buffer */ +/* If buffer pointer is NULL, redirect to normal DBGLOG */ +#define LOGBUF(_pucBuf, _maxLen, _curLen, _Fmt, ...) \ + { \ + if (_pucBuf) \ + (_curLen) += kalSnprintf((_pucBuf) + (_curLen), \ + (_maxLen) - (_curLen), _Fmt, ##__VA_ARGS__); \ + else \ + DBGLOG(SW4, INFO, _Fmt, ##__VA_ARGS__); \ + } +/* The following macro is used for debugging packed structures. */ +#ifndef DATA_STRUCT_INSPECTING_ASSERT +#define DATA_STRUCT_INSPECTING_ASSERT(expr) \ +{ \ + switch (0) {case 0: case (expr): default:; } \ +} +#endif + +/* Name alias of debug functions to skip check patch*/ +#define log_dbg DBGLOG +#define log_limited_dbg DBGLOG_LIMITED +#define log_fw_dbg DBGFWLOG +#define log_mem8_dbg DBGLOG_MEM8 +#define log_mem32_dbg DBGLOG_MEM32 +#define log_tool_dbg TOOL_PRINTLOG +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +void dumpMemory8(IN uint8_t *pucStartAddr, + IN uint32_t u4Length); +void dumpMemory32(IN uint32_t *pu4StartAddr, + IN uint32_t u4Length); +void wlanPrintFwLog(uint8_t *pucLogContent, + uint16_t u2MsgSize, uint8_t ucMsgType, + const uint8_t *pucFmt, ...); + +void wlanDbgLogLevelInit(void); +void wlanDbgLogLevelUninit(void); +uint32_t wlanDbgLevelUiSupport(IN struct ADAPTER *prAdapter, + uint32_t u4Version, uint32_t ucModule); +uint32_t wlanDbgGetLogLevelImpl(IN struct ADAPTER *prAdapter, + uint32_t u4Version, uint32_t ucModule); +void wlanDbgSetLogLevelImpl(IN struct ADAPTER *prAdapter, + uint32_t u4Version, uint32_t u4Module, uint32_t u4level); +void wlanDriverDbgLevelSync(void); +u_int8_t wlanDbgGetGlobalLogLevel(uint32_t u4Module, uint32_t *pu4Level); +u_int8_t wlanDbgSetGlobalLogLevel(uint32_t u4Module, uint32_t u4Level); + +void wlanFillTimestamp(struct ADAPTER *prAdapter, void *pvPacket, + uint8_t ucPhase); +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#endif /* _DEBUG_H */ + + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/hif_cmm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/hif_cmm.h new file mode 100644 index 0000000000000..8118d82914814 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/hif_cmm.h @@ -0,0 +1,136 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \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 + */ + + +#ifndef _HIF_CMM_H +#define _HIF_CMM_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 + ******************************************************************************* + */ + +/* Interface Type */ +enum MT_INF_TYPE { + MT_DEV_INF_UNKNOWN = 0, + MT_DEV_INF_PCI = 1, + MT_DEV_INF_USB = 2, + MT_DEV_INF_RBUS = 4, + MT_DEV_INF_PCIE = 5, + MT_DEV_INF_SDIO = 6, + MT_DEV_INF_EHPI = 7, + MT_DEV_INF_AXI = 8, +}; + +/******************************************************************************* + * P U B 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 IS_SDIO_INF(__GlueInfo) \ + ((__GlueInfo)->u4InfType == MT_DEV_INF_SDIO) +#define IS_USB_INF(__GlueInfo) \ + ((__GlueInfo)->u4InfType == MT_DEV_INF_USB) +#define IS_PCIE_INF(__GlueInfo) \ + ((__GlueInfo)->u4InfType == MT_DEV_INF_PCIE) +#define IS_EHPI_INF(__GlueInfo) \ + ((__GlueInfo)->u4InfType == MT_DEV_INF_PCIE) + +#define HAL_WRITE_HIF_TXD(_prChipInfo, _pucOutputBuf, _u2InfoBufLen) \ +{ \ + uint16_t _u2DataLen = (uint16_t)(_u2InfoBufLen); \ + uint8_t *_prBuf = (_pucOutputBuf); \ + if (_prChipInfo->fillHifTxDesc) \ + _prChipInfo->fillHifTxDesc(&_prBuf, &_u2DataLen); \ +} + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#endif /* _HIF_CMM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/link.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/link.h new file mode 100644 index 0000000000000..5e55944118a32 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/link.h @@ -0,0 +1,524 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: include/link.h + */ + +/*! \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. + */ + +#ifndef _LINK_H +#define _LINK_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "gl_typedef.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +/* May cause page fault & unalignment issue (data abort) */ +#define INVALID_LINK_POISON1 ((void *) 0x00100101) + +/* Used to verify that nonbody uses non-initialized link entries. */ +#define INVALID_LINK_POISON2 ((void *) 0x00100201) + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +/* Simple Doubly Linked List Structures - Entry Part */ +struct LINK_ENTRY { + struct LINK_ENTRY *prNext, *prPrev; +}; + +/* Simple Doubly Linked List Structures - List Part */ +struct LINK { + struct LINK_ENTRY *prNext; + struct LINK_ENTRY *prPrev; + uint32_t u4NumElem; +}; + +/* Support AP Selection */ +struct LINK_MGMT { + struct LINK rUsingLink; + struct LINK rFreeLink; +}; +/* end Support AP Selection */ +/******************************************************************************* + * P U B 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) \ + { (struct LINK_ENTRY *)(&(rLink)), \ + (struct LINK_ENTRY *)(&(rLink)), 0 } + +#define LINK_DECLARATION(rLink) \ + struct LINK rLink = LINK_ADDR(rLink) +#endif + +#define LINK_INITIALIZE(prLink) \ + do { \ + ((struct LINK *)(prLink))->prNext = \ + (struct LINK_ENTRY *)(prLink); \ + ((struct LINK *)(prLink))->prPrev = \ + (struct LINK_ENTRY *)(prLink); \ + ((struct LINK *)(prLink))->u4NumElem = 0; \ + } while (0) +/* Support AP Selection */ +#define LINK_MGMT_INIT(prLinkMgmt) \ + do { \ + LINK_INITIALIZE(&((struct LINK_MGMT *)prLinkMgmt)->rUsingLink); \ + LINK_INITIALIZE(&((struct LINK_MGMT *)prLinkMgmt)->rFreeLink); \ + } while (0) + +#define LINK_MGMT_GET_ENTRY(prLinkMgmt, prEntry, EntryType, memType) \ + do { \ + LINK_REMOVE_HEAD(&((struct LINK_MGMT *)prLinkMgmt)->rFreeLink, \ + prEntry, EntryType*); \ + if (!prEntry) \ + prEntry = kalMemAlloc(sizeof(EntryType), memType); \ + if (prEntry) {\ + kalMemZero(prEntry, sizeof(EntryType));\ + LINK_INSERT_TAIL( \ + &((struct LINK_MGMT *)prLinkMgmt)->rUsingLink, \ + &prEntry->rLinkEntry); \ + } \ + } while (0) + +#define LINK_MGMT_RETURN_ENTRY(prLinkMgmt, prEntry) \ + do {\ + if (!prEntry)\ + break;\ + LINK_REMOVE_KNOWN_ENTRY( \ + &((struct LINK_MGMT *)prLinkMgmt)->rUsingLink, \ + prEntry); \ + LINK_INSERT_TAIL(&((struct LINK_MGMT *)prLinkMgmt)->rFreeLink, \ + &prEntry->rLinkEntry); \ + } while (0) + +#define LINK_MGMT_UNINIT(prLinkMgmt, EntryType, memType) \ + do { \ + EntryType *prEntry = NULL; \ + struct LINK *prFreeList = &((struct LINK_MGMT *)prLinkMgmt)->rFreeLink; \ + struct LINK *prUsingList = &((struct LINK_MGMT *)prLinkMgmt)->rUsingLink; \ + LINK_REMOVE_HEAD(prFreeList, prEntry, EntryType *); \ + while (prEntry) { \ + kalMemFree(prEntry, memType, sizeof(EntryType)); \ + LINK_REMOVE_HEAD(prFreeList, prEntry, EntryType *); \ + } \ + LINK_REMOVE_HEAD(prUsingList, prEntry, EntryType *); \ + while (prEntry) { \ + kalMemFree(prEntry, memType, sizeof(EntryType)); \ + LINK_REMOVE_HEAD(prUsingList, prEntry, EntryType *); \ + } \ + } while (0) +/* end Support AP Selection */ + +#define LINK_ENTRY_INITIALIZE(prEntry) \ + do { \ + ((struct LINK_ENTRY *)(prEntry))->prNext = \ + (struct LINK_ENTRY *)NULL; \ + ((struct LINK_ENTRY *)(prEntry))->prPrev = \ + (struct LINK_ENTRY *)NULL; \ + } while (0) + +#define LINK_ENTRY_INVALID(prEntry) \ + do { \ + ((struct LINK_ENTRY *)(prEntry))->prNext = \ + (struct LINK_ENTRY *)INVALID_LINK_POISON1; \ + ((struct LINK_ENTRY *)(prEntry))->prPrev = \ + (struct LINK_ENTRY *)INVALID_LINK_POISON2; \ + } while (0) + +#define LINK_IS_EMPTY(prLink) \ + (((struct LINK *)(prLink))->prNext == (struct LINK_ENTRY *)(prLink)) + +#define LINK_ENTRY_IS_VALID(prEntry) \ + (((struct LINK_ENTRY *)(prEntry))->prNext != \ + (struct LINK_ENTRY *)NULL && \ + ((struct LINK_ENTRY *)(prEntry))->prNext != \ + (struct LINK_ENTRY *)INVALID_LINK_POISON1 && \ + ((struct LINK_ENTRY *)(prEntry))->prPrev != (struct LINK_ENTRY *)NULL && \ + ((struct LINK_ENTRY *)(prEntry))->prPrev != \ + (struct LINK_ENTRY *)INVALID_LINK_POISON2) + + + +/* 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) \ + (((struct LINK *)(prLink))->prNext == (struct LINK_ENTRY *)NULL) + +#define LINK_IS_VALID(prLink) \ + (((struct LINK *)(prLink))->prNext != (struct LINK_ENTRY *)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)(((struct LINK *)(prLink))->prNext); \ + linkDel((struct LINK_ENTRY *)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((struct LINK_ENTRY *)prEntry); \ + ((prLink)->u4NumElem)--; \ + } + +/* Merge prSrcLink to prDstLink and put prSrcLink ahead of prDstLink */ +#define LINK_MERGE_TO_HEAD(prDstLink, prSrcLink) \ + { \ + if (!LINK_IS_EMPTY(prSrcLink)) { \ + linkMergeToHead((struct LINK *)prDstLink, \ + (struct LINK *)prSrcLink); \ + (prDstLink)->u4NumElem += (prSrcLink)->u4NumElem; \ + LINK_INITIALIZE(prSrcLink); \ + } \ + } + +/* Merge prSrcLink to prDstLink and put prSrcLink at tail */ +#define LINK_MERGE_TO_TAIL(prDstLink, prSrcLink) \ + { \ + if (!LINK_IS_EMPTY(prSrcLink)) { \ + linkMergeToTail((struct LINK *)prDstLink, \ + (struct LINK *)prSrcLink); \ + (prDstLink)->u4NumElem += (prSrcLink)->u4NumElem; \ + LINK_INITIALIZE(prSrcLink); \ + } \ + } + +/* Iterate over a link list */ +#define LINK_FOR_EACH(prEntry, prLink) \ + for (prEntry = (prLink)->prNext; \ + prEntry != (struct LINK_ENTRY *)(prLink); \ + prEntry = (struct LINK_ENTRY *)prEntry->prNext) + +/* Iterate over a link list backwards */ +#define LINK_FOR_EACH_PREV(prEntry, prLink) \ + for (prEntry = (prLink)->prPrev; \ + prEntry != (struct LINK_ENTRY *)(prLink); \ + prEntry = (struct LINK_ENTRY *)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 != (struct LINK_ENTRY *)(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 != (struct LINK_ENTRY *)(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 != (struct LINK_ENTRY *)(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 != (struct LINK_ENTRY *)(prLink); \ + prObj = prNextObj, \ + prNextObj = LINK_ENTRY(prNextObj->rMember.prNext, _TYPE, rMember)) + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is only for internal link list manipulation. + * + * \param[in] prNew Pointer of new link head + * \param[in] prPrev Pointer of previous link head + * \param[in] prNext Pointer of next link head + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void __linkAdd(IN struct LINK_ENTRY + *prNew, IN struct LINK_ENTRY *prPrev, + IN struct LINK_ENTRY *prNext) +{ + prNext->prPrev = prNew; + prNew->prNext = prNext; + prNew->prPrev = prPrev; + prPrev->prNext = prNew; +} /* end of __linkAdd() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will add a new entry after the specified link head. + * + * \param[in] prNew New entry to be added + * \param[in] prHead Specified link head to add it after + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void linkAdd(IN struct LINK_ENTRY + *prNew, IN struct LINK *prLink) +{ + __linkAdd(prNew, (struct LINK_ENTRY *) prLink, + prLink->prNext); +} /* end of linkAdd() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will add a new entry before the specified link head. + * + * \param[in] prNew New entry to be added + * \param[in] prHead Specified link head to add it before + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void linkAddTail(IN struct LINK_ENTRY + *prNew, IN struct LINK *prLink) +{ + __linkAdd(prNew, prLink->prPrev, + (struct LINK_ENTRY *) prLink); +} /* end of linkAddTail() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is only for internal link list manipulation. + * + * \param[in] prPrev Pointer of previous link head + * \param[in] prNext Pointer of next link head + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void __linkDel(IN struct LINK_ENTRY + *prPrev, IN struct LINK_ENTRY *prNext) +{ + prNext->prPrev = prPrev; + prPrev->prNext = prNext; +} /* end of __linkDel() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will delete a specified entry from link list. + * NOTE: the entry is in an initial state. + * + * \param prEntry Specified link head(entry) + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void linkDel(IN struct LINK_ENTRY + *prEntry) +{ + __linkDel(prEntry->prPrev, prEntry->prNext); + + LINK_ENTRY_INITIALIZE(prEntry); +} /* end of linkDel() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will delete a specified entry from link list + * and then add it after the specified link head. + * + * \param[in] prEntry Specified link head(entry) + * \param[in] prOtherHead Another link head to add it after + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void linkMove(IN struct LINK_ENTRY + *prEntry, IN struct LINK *prLink) +{ + __linkDel(prEntry->prPrev, prEntry->prNext); + linkAdd(prEntry, prLink); +} /* end of linkMove() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will delete a specified entry from link list + * and then add it before the specified link head. + * + * \param[in] prEntry Specified link head(entry) + * \param[in] prOtherHead Another link head to add it before + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void linkMoveTail(IN struct LINK_ENTRY + *prEntry, IN struct LINK *prLink) +{ + __linkDel(prEntry->prPrev, prEntry->prNext); + linkAddTail(prEntry, prLink); +} /* end of linkMoveTail() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will merge source link to the tail of destination link. +* +* \param[in] prDst destination link +* \param[in] prSrc source link +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void linkMergeToTail(struct LINK *prDst, + struct LINK *prSrc) +{ + prSrc->prNext->prPrev = prDst->prPrev; + prSrc->prPrev->prNext = (struct LINK_ENTRY *)prDst; + prDst->prPrev->prNext = prSrc->prNext; + prDst->prPrev = prSrc->prPrev; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will merge source link to the head of destination link. +* +* \param[in] prDst destination link +* \param[in] prSrc source link + +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void linkMergeToHead(struct LINK *prDst, + struct LINK *prSrc) +{ + prSrc->prNext->prPrev = (struct LINK_ENTRY *)prDst; + prSrc->prPrev->prNext = prDst->prNext; + prDst->prNext->prPrev = prSrc->prPrev; + prDst->prNext = prSrc->prNext; +} + +#endif /* _LINK_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/aa_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/aa_fsm.h new file mode 100644 index 0000000000000..ce5377d86e097 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/aa_fsm.h @@ -0,0 +1,261 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + +#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. */ + +#if CFG_SUPPORT_CFG80211_AUTH +/* Wait for a response to a transmitted SAE authentication MMPDU. */ +/* Default value on 802.11-REVmd-D0.5 */ +#define DOT11_RSNA_SAE_RETRANS_PERIOD_TU 2000 +#endif + +#if CFG_SUPPORT_802_11R +#define DOT11_11R_AUTHENTICATION_RESPONSE_TIMEOUT_TU 2000 +#endif + +/* The maximum time to wait for JOIN process complete. */ +/* Beacon Interval, 20 * 100TU = 2 sec. */ +#define JOIN_FAILURE_TIMEOUT_BEACON_INTERVAL 20 + +/* 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 */ + +#define TX_AUTHENTICATION_RESPONSE_TIMEOUT_TU 512 /* TU. */ + +#define TX_ASSOCIATE_TIMEOUT_TU 512 /* TU. */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +enum ENUM_AA_STATE { + 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 +}; + +#if CFG_SUPPORT_CFG80211_AUTH +enum ENUM_AA_SENT_T { + AA_SENT_NONE = 0, + AA_SENT_AUTH1, /* = auth transaction SN */ + AA_SENT_AUTH2, + AA_SENT_AUTH3, + AA_SENT_AUTH4, + AA_SENT_ASSOC1, /* req */ + AA_SENT_ASSOC2, /* resp */ + AA_SENT_RESOURCE, /* A state for debug the case of out of msg buffer */ + AA_SENT_NUM +}; +#endif + +enum ENUM_AA_FRM_TYPE { + FRM_DISASSOC = 0, + FRM_DEAUTH +}; + +/******************************************************************************* + * P U B 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 struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN enum ENUM_AA_STATE eNextState, + IN struct SW_RFB *prRetainedSwRfb); + +uint32_t +saaFsmSendEventJoinComplete(IN struct ADAPTER *prAdapter, + uint32_t rJoinStatus, struct STA_RECORD *prStaRec, + struct SW_RFB *prSwRfb); + +void saaFsmRunEventStart(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +uint32_t +saaFsmRunEventTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +void saaFsmRunEventTxReqTimeOut(IN struct ADAPTER + *prAdapter, IN unsigned long plParamPtr); + +void saaFsmRunEventRxRespTimeOut(IN struct ADAPTER + *prAdapter, IN unsigned long ulParamPtr); + +void saaFsmRunEventRxAuth(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +uint32_t saaFsmRunEventRxAssoc(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +uint32_t saaFsmRunEventRxDeauth(IN struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfb); + +uint32_t saaFsmRunEventRxDisassoc(IN struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfb); + +void saaFsmRunEventAbort(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void saaChkDeauthfrmParamHandler(IN struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfb, + IN struct STA_RECORD *prStaRec); + +void +saaChkDisassocfrmParamHandler(IN struct ADAPTER *prAdapter, + IN struct WLAN_DISASSOC_FRAME *prDisassocFrame, + IN struct STA_RECORD *prStaRec, + IN struct SW_RFB *prSwRfb); + +void +saaSendDisconnectMsgHandler(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct BSS_INFO *prAisBssInfo, + IN enum ENUM_AA_FRM_TYPE eFrmType); + +#if CFG_SUPPORT_CFG80211_AUTH +void saaSendAuthAssoc(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); +void saaSendAuthSeq3(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); +#endif + +void saaFsmRunEventFTContinue(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +/*----------------------------------------------------------------------------*/ +/* Routines in aaa_fsm.c */ +/*----------------------------------------------------------------------------*/ +void aaaFsmRunEventRxAuth(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +uint32_t aaaFsmRunEventRxAssoc(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +uint32_t +aaaFsmRunEventTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + + +#endif /* _AA_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/ais_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/ais_fsm.h new file mode 100644 index 0000000000000..34350ec8f691e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/ais_fsm.h @@ -0,0 +1,601 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/ + * include/mgmt/ais_fsm.h#2 + */ + +/*! \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. + */ + + +#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 + ******************************************************************************* + */ +#if CFG_DISCONN_DEBUG_FEATURE +extern struct AIS_DISCONN_INFO_T g_rDisconnInfoTemp; +extern uint8_t g_DisconnInfoIdx; +extern struct AIS_DISCONN_INFO_T *g_prDisconnInfo; +#endif + +/******************************************************************************* + * 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 5 /* 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 +#if CFG_SUPPORT_CFG80211_AUTH +/* expand 4000 to 6000 to improve SAE connection success probability */ +#define AIS_JOIN_CH_REQUEST_INTERVAL 6000 +#else +#define AIS_JOIN_CH_REQUEST_INTERVAL 4000 +#endif +#define AIS_SCN_DONE_TIMEOUT_SEC 15 /* 15 for 2.4G + 5G */ /* 5 */ +#define AIS_SCN_REPORT_SEQ_NOT_SET (0xFFFF) + +#define AIS_WAIT_OKC_PMKID_SEC 1000 /* unit: ms */ +/* Support AP Selection*/ +#define AIS_BLACKLIST_TIMEOUT 15 /* seconds */ + +#ifdef CFG_SUPPORT_ADJUST_JOIN_CH_REQ_INTERVAL +#define AIS_JOIN_CH_REQUEST_MAX_INTERVAL 4000 +#endif + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +enum ENUM_AIS_STATE { + 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_JOIN_FAILURE, + AIS_STATE_IBSS_ALONE, + AIS_STATE_IBSS_MERGE, + AIS_STATE_NORMAL_TR, + AIS_STATE_DISCONNECTING, + AIS_STATE_REQ_REMAIN_ON_CHANNEL, + AIS_STATE_REMAIN_ON_CHANNEL, + AIS_STATE_NUM +}; + +/* reconnect level for determining if we should reconnect */ +enum ENUM_RECONNECT_LEVEL_T { + RECONNECT_LEVEL_MIN = 0, + RECONNECT_LEVEL_ROAMING_FAIL, /* roaming failed */ + RECONNECT_LEVEL_BEACON_TIMEOUT, /* driver beacon timeout */ + RECONNECT_LEVEL_USER_SET, /* user set connect */ + /* or disassociate */ + RECONNECT_LEVEL_MAX +}; + +struct MSG_AIS_ABORT { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucReasonOfDisconnect; + u_int8_t fgDelayIndication; +}; + +struct MSG_AIS_IBSS_PEER_FOUND { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucBssIndex; + u_int8_t fgIsMergeIn; /* TRUE: Merge In, FALSE: Merge Out */ + struct STA_RECORD *prStaRec; +}; + +enum ENUM_AIS_REQUEST_TYPE { + AIS_REQUEST_SCAN, + AIS_REQUEST_RECONNECT, + AIS_REQUEST_ROAMING_SEARCH, + AIS_REQUEST_ROAMING_CONNECT, + AIS_REQUEST_REMAIN_ON_CHANNEL, + AIS_REQUEST_NUM +}; + +struct AIS_REQ_HDR { + struct LINK_ENTRY rLinkEntry; + enum ENUM_AIS_REQUEST_TYPE eReqType; +}; + +struct AIS_REQ_CHNL_INFO { + enum ENUM_BAND eBand; + enum ENUM_CHNL_EXT eSco; + uint8_t ucChannelNum; + uint32_t u4DurationMs; + uint64_t u8Cookie; +}; + +struct AIS_MGMT_TX_REQ_INFO { + u_int8_t fgIsMgmtTxRequested; + struct MSDU_INFO *prMgmtTxMsdu; + uint64_t u8Cookie; +}; + +/* Support AP Selection */ +struct AIS_BLACKLIST_ITEM { + struct LINK_ENTRY rLinkEntry; + + uint8_t aucBSSID[MAC_ADDR_LEN]; + uint16_t u2DeauthReason; + uint16_t u2AuthStatus; + uint8_t ucCount; + uint8_t ucSSIDLen; + uint8_t aucSSID[32]; + OS_SYSTIME rAddTime; + uint32_t u4DisapperTime; + u_int8_t fgIsInFWKBlacklist; +}; +/* end Support AP Selection */ + +struct AIS_FSM_INFO { + enum ENUM_AIS_STATE ePreviousState; + enum ENUM_AIS_STATE eCurrentState; + + u_int8_t fgTryScan; + + u_int8_t fgIsScanning; + + u_int8_t fgIsInfraChannelFinished; + u_int8_t fgIsChannelRequested; + u_int8_t fgIsChannelGranted; + +#if CFG_SUPPORT_ROAMING + u_int8_t fgIsRoamingScanPending; +#endif /* CFG_SUPPORT_ROAMING */ + + uint8_t ucAvailableAuthTypes; /* Used for AUTH_MODE_AUTO_SWITCH */ + + struct BSS_DESC *prTargetBssDesc; /* For destination */ + + struct STA_RECORD *prTargetStaRec; /* For JOIN Abort */ + + uint32_t u4SleepInterval; + + struct TIMER rBGScanTimer; + + struct TIMER rIbssAloneTimer; + + uint32_t u4PostponeIndStartTime; + + struct TIMER rJoinTimeoutTimer; + + struct TIMER rChannelTimeoutTimer; + + struct TIMER rScanDoneTimer; + + struct TIMER rDeauthDoneTimer; + + struct TIMER rWaitOkcPMKTimer; + + struct TIMER rSecModeChangeTimer; + + uint8_t ucSeqNumOfReqMsg; + uint8_t ucSeqNumOfChReq; + uint8_t ucSeqNumOfScanReq; + + /* Save SeqNum for reporting scan done. + * In order to distinguish seq num and default value, make sure that + * sizeof(u2SeqNumOfScanReport) > sizeof(ucSeqNumOfScanReq). + * Set AIS_SCN_REPORT_SEQ_NOT_SET as default value + */ + uint16_t u2SeqNumOfScanReport; + + uint32_t u4ChGrantedInterval; + + uint8_t ucConnTrialCount; + + struct PARAM_SCAN_REQUEST_ADV rScanRequest; + uint8_t aucScanIEBuf[MAX_IE_LENGTH]; + + u_int8_t fgIsScanOidAborted; + + /* Pending Request List */ + struct LINK rPendingReqList; + + /* Join Request Timestamp */ + OS_SYSTIME rJoinReqTime; + + /* for cfg80211 REMAIN_ON_CHANNEL support */ + struct AIS_REQ_CHNL_INFO rChReqInfo; + + /* Mgmt tx related. */ + struct AIS_MGMT_TX_REQ_INFO rMgmtTxInfo; + + /* Packet filter for AIS module. */ + uint32_t u4AisPacketFilter; + + /* for roaming target */ + struct PARAM_SSID rRoamingSSID; + + /* Support AP Selection */ + uint8_t ucJoinFailCntAfterScan; + /* end Support AP Selection */ + + /* Scan target channel when device roaming */ + uint8_t fgTargetChnlScanIssued; +}; + +enum WNM_AIS_BSS_TRANSITION { + BSS_TRANSITION_NO_MORE_ACTION, + BSS_TRANSITION_REQ_ROAMING, + BSS_TRANSITION_DISASSOC, + BSS_TRANSITION_MAX_NUM +}; +struct MSG_AIS_BSS_TRANSITION_T { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucToken; + u_int8_t fgNeedResponse; + uint8_t ucValidityInterval; + enum WNM_AIS_BSS_TRANSITION eTransitionType; + uint16_t u2CandListLen; + uint8_t *pucCandList; +}; + +#if CFG_DISCONN_DEBUG_FEATURE +struct AIS_DISCONN_INFO_T { + struct timeval tv; + uint8_t ucTrigger; + uint8_t ucDisConnReason; + uint8_t ucBcnTimeoutReason; + uint8_t ucDisassocReason; + uint16_t u2DisassocSeqNum; + struct STA_RECORD rStaRec; + int32_t rBcnRssi; + struct CMD_NOISE_HISTOGRAM_REPORT rNoise; + struct PARAM_HW_WLAN_INFO rHwInfo; + struct PARAM_GET_STA_STATISTICS rStaStatistics; +}; +#endif + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +#define aisChangeMediaState(_prAdapter, _eNewMediaState) \ + (_prAdapter->prAisBssInfo->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 struct ADAPTER + *prAdapter, IN struct REG_INFO *prRegInfo); + +void aisFsmInit(IN struct ADAPTER *prAdapter); + +void aisFsmUninit(IN struct ADAPTER *prAdapter); + +void aisFsmStateInit_JOIN(IN struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc); + +u_int8_t aisFsmStateInit_RetryJOIN(IN struct ADAPTER + *prAdapter, IN struct STA_RECORD *prStaRec); + +void aisFsmStateInit_IBSS_ALONE(IN struct ADAPTER + *prAdapter); + +void aisFsmStateInit_IBSS_MERGE(IN struct ADAPTER + *prAdapter, struct BSS_DESC *prBssDesc); + +void aisFsmStateAbort(IN struct ADAPTER *prAdapter, + uint8_t ucReasonOfDisconnect, u_int8_t fgDelayIndication); + +void aisFsmStateAbort_JOIN(IN struct ADAPTER *prAdapter); + +void aisFsmStateAbort_SCAN(IN struct ADAPTER *prAdapter); + +void aisFsmStateAbort_NORMAL_TR(IN struct ADAPTER + *prAdapter); + +void aisFsmStateAbort_IBSS(IN struct ADAPTER *prAdapter); + +void aisFsmSteps(IN struct ADAPTER *prAdapter, + enum ENUM_AIS_STATE eNextState); + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Handling */ +/*----------------------------------------------------------------------------*/ +void aisFsmRunEventScanDone(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void aisFsmRunEventAbort(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void aisFsmRunEventJoinComplete(IN struct ADAPTER + *prAdapter, IN struct MSG_HDR *prMsgHdr); + +enum ENUM_AIS_STATE aisFsmJoinCompleteAction( + IN struct ADAPTER *prAdapter, IN struct MSG_HDR *prMsgHdr); + +void aisFsmRunEventFoundIBSSPeer(IN struct ADAPTER + *prAdapter, IN struct MSG_HDR *prMsgHdr); + +void aisFsmRunEventRemainOnChannel(IN struct ADAPTER + *prAdapter, IN struct MSG_HDR *prMsgHdr); + +void aisFsmRunEventCancelRemainOnChannel(IN struct ADAPTER + *prAdapter, IN struct MSG_HDR *prMsgHdr); + +/*----------------------------------------------------------------------------*/ +/* Handling for Ad-Hoc Network */ +/*----------------------------------------------------------------------------*/ +void aisFsmCreateIBSS(IN struct ADAPTER *prAdapter); + +void aisFsmMergeIBSS(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +/*----------------------------------------------------------------------------*/ +/* Handling of Incoming Mailbox Message from CNM */ +/*----------------------------------------------------------------------------*/ +void aisFsmRunEventChGrant(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +/*----------------------------------------------------------------------------*/ +/* Generating Outgoing Mailbox Message to CNM */ +/*----------------------------------------------------------------------------*/ +void aisFsmReleaseCh(IN struct ADAPTER *prAdapter); + +/*----------------------------------------------------------------------------*/ +/* Event Indication */ +/*----------------------------------------------------------------------------*/ +void +aisIndicationOfMediaStateToHost(IN struct ADAPTER + *prAdapter, + enum ENUM_PARAM_MEDIA_STATE eConnectionState, + u_int8_t fgDelayIndication); + +void aisPostponedEventOfDisconnTimeout(IN struct ADAPTER *prAdapter, + IN struct AIS_FSM_INFO *prAisFsmInfo); + +void aisUpdateBssInfoForJOIN(IN struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + struct SW_RFB *prAssocRspSwRfb); + +void aisUpdateBssInfoForCreateIBSS(IN struct ADAPTER *prAdapter); + +void aisUpdateBssInfoForMergeIBSS(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +u_int8_t aisValidateProbeReq(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + OUT uint32_t *pu4ControlFlags); + +uint32_t +aisFsmRunEventMgmtFrameTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +/*----------------------------------------------------------------------------*/ +/* Disconnection Handling */ +/*----------------------------------------------------------------------------*/ +void aisFsmDisconnect(IN struct ADAPTER *prAdapter, + IN u_int8_t fgDelayIndication); + +#if CFG_DISCONN_DEBUG_FEATURE +void aisCollectDisconnInfo(IN struct ADAPTER *prAdapter); +#endif +/*----------------------------------------------------------------------------*/ +/* Event Handling */ +/*----------------------------------------------------------------------------*/ +void aisBssBeaconTimeout(IN struct ADAPTER *prAdapter); + +void aisBssLinkDown(IN struct ADAPTER *prAdapter); + +void aisBssSecurityChanged(IN struct ADAPTER *prAdapter); + +uint32_t +aisDeauthXmitComplete(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +#if CFG_SUPPORT_ROAMING +void aisFsmRunEventRoamingDiscovery(IN struct ADAPTER + *prAdapter, uint32_t u4ReqScan); + +enum ENUM_AIS_STATE aisFsmRoamingScanResultsUpdate( + IN struct ADAPTER *prAdapter); + +void aisFsmRoamingDisconnectPrevAP(IN struct ADAPTER + *prAdapter, + IN struct STA_RECORD *prTargetStaRec); + +void aisUpdateBssInfoForRoamingAP(IN struct ADAPTER + *prAdapter, IN struct STA_RECORD *prStaRec, + IN struct SW_RFB *prAssocRspSwRfb); +#endif /*CFG_SUPPORT_ROAMING */ + +/*----------------------------------------------------------------------------*/ +/* Timeout Handling */ +/*----------------------------------------------------------------------------*/ +void aisFsmRunEventBGSleepTimeOut(IN struct ADAPTER + *prAdapter, unsigned long ulParamPtr); + +void aisFsmRunEventIbssAloneTimeOut(IN struct ADAPTER + *prAdapter, unsigned long ulParamPtr); + +void aisFsmRunEventJoinTimeout(IN struct ADAPTER *prAdapter, + unsigned long ulParamPtr); + +void aisFsmRunEventChannelTimeout(IN struct ADAPTER + *prAdapter, unsigned long ulParamPtr); + +void aisFsmRunEventDeauthTimeout(IN struct ADAPTER + *prAdapter, unsigned long ulParamPtr); + +void aisFsmRunEventSecModeChangeTimeout(IN struct ADAPTER + *prAdapter, unsigned long ulParamPtr); + +/*----------------------------------------------------------------------------*/ +/* OID/IOCTL Handling */ +/*----------------------------------------------------------------------------*/ +void aisFsmScanRequest(IN struct ADAPTER *prAdapter, + IN struct PARAM_SSID *prSsid, IN uint8_t *pucIe, + IN uint32_t u4IeLength); + +void +aisFsmScanRequestAdv(IN struct ADAPTER *prAdapter, + IN struct PARAM_SCAN_REQUEST_ADV *prRequestIn); + +/*----------------------------------------------------------------------------*/ +/* Internal State Checking */ +/*----------------------------------------------------------------------------*/ +u_int8_t aisFsmIsRequestPending(IN struct ADAPTER *prAdapter, + IN enum ENUM_AIS_REQUEST_TYPE eReqType, + IN u_int8_t bRemove); + +struct AIS_REQ_HDR *aisFsmGetNextRequest(IN struct ADAPTER *prAdapter); + +u_int8_t aisFsmInsertRequest(IN struct ADAPTER *prAdapter, + IN enum ENUM_AIS_REQUEST_TYPE eReqType); + +void aisFsmFlushRequest(IN struct ADAPTER *prAdapter); + +uint32_t +aisFuncTxMgmtFrame(IN struct ADAPTER *prAdapter, + IN struct AIS_MGMT_TX_REQ_INFO *prMgmtTxReqInfo, + IN struct MSDU_INFO *prMgmtTxMsdu, IN uint64_t u8Cookie); + +void aisFsmRunEventMgmtFrameTx(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void aisFuncValidateRxActionFrame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +void aisFsmRunEventSetOkcPmk(IN struct ADAPTER *prAdapter); + +void aisFsmRunEventBssTransition(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +enum ENUM_AIS_STATE aisFsmStateSearchAction( + IN struct ADAPTER *prAdapter, uint8_t ucPhase); +#if defined(CFG_TEST_MGMT_FSM) && (CFG_TEST_MGMT_FSM != 0) +void aisTest(void); +#endif /* CFG_TEST_MGMT_FSM */ + +/* Support AP Selection */ +void aisRefreshFWKBlacklist(struct ADAPTER *prAdapter); +struct AIS_BLACKLIST_ITEM *aisAddBlacklist(struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc); +void aisRemoveBlackList(struct ADAPTER *prAdapter, struct BSS_DESC *prBssDesc); +void aisRemoveTimeoutBlacklist(struct ADAPTER *prAdapter); +struct AIS_BLACKLIST_ITEM *aisQueryBlackList(struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc); +uint16_t aisCalculateBlackListScore(struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc); +/* end Support AP Selection */ + +/* Support 11K */ +void aisResetNeighborApList(struct ADAPTER *prAdapter); +void aisCollectNeighborAP(struct ADAPTER *prAdapter, uint8_t *pucApBuf, + uint16_t u2ApBufLen, uint8_t ucValidInterval); +void aisSendNeighborRequest(struct ADAPTER *prAdapter); +/* end Support 11K */ + +void aisPreSuspendFlow(IN struct GLUE_INFO *prGlueInfo); + +void aisFuncUpdateMgmtFrameRegister( + IN struct ADAPTER *prAdapter, + IN uint32_t u4NewPacketFilter); + + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _AIS_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/ap_selection.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/ap_selection.h new file mode 100644 index 0000000000000..4e2108a7dacb8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/ap_selection.h @@ -0,0 +1,20 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef _AP_SELECTION_H +#define _AP_SELECTION_H + +/* Support AP Selection */ +struct BSS_DESC *scanSearchBssDescByScoreForAis(struct ADAPTER *prAdapter); +void scanGetCurrentEssChnlList(struct ADAPTER *prAdapter); +/* end Support AP Selection */ + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/assoc.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/assoc.h new file mode 100644 index 0000000000000..a9c9164cdf59c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/assoc.h @@ -0,0 +1,150 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + + +#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 */ +/*----------------------------------------------------------------------------*/ +uint32_t assocSendReAssocReqFrame(IN struct ADAPTER + *prAdapter, IN struct STA_RECORD *prStaRec); + +uint32_t assocCheckTxReAssocReqFrame(IN struct ADAPTER + *prAdapter, IN struct MSDU_INFO *prMsduInfo); + +uint32_t assocCheckTxReAssocRespFrame(IN struct ADAPTER + *prAdapter, IN struct MSDU_INFO *prMsduInfo); + +uint32_t +assocCheckRxReAssocRspFrameStatus(IN struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfb, + OUT uint16_t *pu2StatusCode); + +uint32_t assocSendDisAssocFrame(IN struct ADAPTER + *prAdapter, IN struct STA_RECORD *prStaRec, + IN uint16_t u2ReasonCode); + +uint32_t +assocProcessRxDisassocFrame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint8_t aucBSSID[], + OUT uint16_t *pu2ReasonCode); + +uint32_t assocProcessRxAssocReqFrame(IN struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfb, + OUT uint16_t *pu2StatusCode); + +uint32_t assocSendReAssocRespFrame(IN struct ADAPTER + *prAdapter, IN struct STA_RECORD *prStaRec); + +uint16_t assocBuildCapabilityInfo(IN struct ADAPTER + *prAdapter, IN struct STA_RECORD *prStaRec); + +uint16_t assoc_get_nonwfa_vend_ie_len(struct ADAPTER *prAdapter); + +void assoc_build_nonwfa_vend_ie(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void assocGenerateMDIE(IN struct ADAPTER *prAdapter, + IN OUT struct MSDU_INFO *prMsduInfo); + +#endif /* _ASSOC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/auth.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/auth.h new file mode 100644 index 0000000000000..cb38d2d23070c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/auth.h @@ -0,0 +1,174 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + + +#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 struct ADAPTER *prAdapter, + IN OUT struct MSDU_INFO *prMsduInfo); + +#if !CFG_SUPPORT_AAA +uint32_t authSendAuthFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN uint16_t u2TransactionSeqNum); +#else +uint32_t +authSendAuthFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN uint8_t uBssIndex, + IN struct SW_RFB *prFalseAuthSwRfb, + IN uint16_t u2TransactionSeqNum, + IN uint16_t u2StatusCode); +#endif /* CFG_SUPPORT_AAA */ + +uint32_t authCheckTxAuthFrame(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN uint16_t u2TransactionSeqNum); + +uint32_t authCheckRxAuthFrameTransSeq(IN struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfb); + +uint32_t +authCheckRxAuthFrameStatus(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint16_t u2TransactionSeqNum, + OUT uint16_t *pu2StatusCode); + +void authHandleIEChallengeText(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb, struct IE_HDR *prIEHdr); + +uint32_t authProcessRxAuth2_Auth4Frame(IN struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfb); + +uint32_t +authSendDeauthFrame(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct STA_RECORD *prStaRec, + IN struct SW_RFB *prClassErrSwRfb, IN uint16_t u2ReasonCode, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler); + +uint32_t authProcessRxDeauthFrame(IN struct SW_RFB *prSwRfb, + IN uint8_t aucBSSID[], OUT uint16_t *pu2ReasonCode); + +uint32_t +authProcessRxAuth1Frame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint8_t aucExpectedBSSID[], + IN uint16_t u2ExpectedAuthAlgNum, + IN uint16_t u2ExpectedTransSeqNum, + OUT uint16_t *pu2ReturnStatusCode); + +void authAddMDIE(IN struct ADAPTER *prAdapter, + IN OUT struct MSDU_INFO *prMsduInfo); + +uint32_t authCalculateRSNIELen(struct ADAPTER *prAdapter, uint8_t ucBssIdx, + struct STA_RECORD *prStaRec); + +void authAddRSNIE(IN struct ADAPTER *prAdapter, + IN OUT struct MSDU_INFO *prMsduInfo); + +void authHandleFtIEs(struct ADAPTER *prAdapter, struct SW_RFB *prSwRfb, + struct IE_HDR *prIEHdr); + +#endif /* _AUTH_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/bow_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/bow_fsm.h new file mode 100644 index 0000000000000..51c5ff6987969 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/bow_fsm.h @@ -0,0 +1,189 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +#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 +******************************************************************************** +*/ + +enum ENUM_BOW_STATE { + 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 +}; + +struct BOW_FSM_INFO { + /* Channel Privilege */ + u_int8_t fgIsChannelRequested; + u_int8_t fgIsChannelGranted; + uint32_t u4ChGrantedInterval; + + uint8_t ucPrimaryChannel; + enum ENUM_BAND eBand; + uint16_t u2BeaconInterval; + + struct STA_RECORD *prTargetStaRec; + struct BSS_DESC *prTargetBssDesc; /* For destination */ + + uint8_t aucPeerAddress[6]; + uint8_t ucBssIndex; /* Assume there is only 1 BSS for BOW */ + uint8_t ucRole; /* Initiator or responder */ + uint8_t ucAvailableAuthTypes; /* Used for AUTH_MODE_AUTO_SWITCH */ + + u_int8_t fgSupportQoS; + + /* Sequence number of requested message. */ + uint8_t ucSeqNumOfChReq; + uint8_t ucSeqNumOfReqMsg; + uint8_t ucSeqNumOfScnMsg; + uint8_t ucSeqNumOfScanReq; + uint8_t ucSeqNumOfCancelMsg; + + /* Timer */ + struct TIMER rStartingBeaconTimer; /* For device discovery time of each discovery request from user. */ + struct TIMER rChGrantedTimer; + + /* can be deleted? */ + struct TIMER rIndicationOfDisconnectTimer; + +}; + +/******************************************************************************* +* P U B 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(_prBssInfo, _eNewMediaState) \ + (_prBssInfo->eConnectionState = (_eNewMediaState)) + /* (_prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX].eConnectionState = (_eNewMediaState)); */ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/bss.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/bss.h new file mode 100644 index 0000000000000..ab48dc3f04354 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/bss.h @@ -0,0 +1,272 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/*! \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. + */ + + +#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 + ******************************************************************************* + */ +#include "wlan_def.h" +extern const uint8_t *apucNetworkType[NETWORK_TYPE_NUM]; + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define BSS_DEFAULT_NUM KAL_BSS_NUM + +/* Define how many concurrent operation networks. */ +#define BSS_P2P_NUM KAL_P2P_NUM + +#if (BSS_P2P_NUM > MAX_BSSID_NUM) +#error Exceed HW capability (KAL_BSS_NUM or KAL_P2P_NUM)!! +#endif + +/* 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) + +#define MAX_BSS_INDEX HW_BSSID_NUM +#define P2P_DEV_BSS_INDEX MAX_BSS_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 + ******************************************************************************* + */ +#define IS_BSS_INDEX_VALID(_ucBssIndex) ((_ucBssIndex) <= P2P_DEV_BSS_INDEX) + +#define GET_BSS_INFO_BY_INDEX(_prAdapter, _ucBssIndex) \ + ((_prAdapter)->aprBssInfo[(_ucBssIndex)]) + +#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 */ +/*----------------------------------------------------------------------------*/ +struct STA_RECORD * +bssCreateStaRecFromBssDesc(IN struct ADAPTER *prAdapter, + IN enum ENUM_STA_TYPE eStaType, IN uint8_t uBssIndex, + IN struct BSS_DESC *prBssDesc); + +void bssComposeNullFrame(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuffer, IN struct STA_RECORD *prStaRec); + +void +bssComposeQoSNullFrame(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuffer, IN struct STA_RECORD *prStaRec, + IN uint8_t ucUP, IN u_int8_t fgSetEOSP); + +uint32_t +bssSendNullFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler); + +uint32_t +bssSendQoSNullFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, IN uint8_t ucUP, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler); + +void bssDumpBssInfo(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +void bssDetermineApBssInfoPhyTypeSet(IN struct ADAPTER + *prAdapter, IN u_int8_t fgIsPureAp, + OUT struct BSS_INFO *prBssInfo); + +/*----------------------------------------------------------------------------*/ +/* Routines for both IBSS(AdHoc) and BSS(AP) */ +/*----------------------------------------------------------------------------*/ +void bssGenerateExtSuppRate_IE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +void +bssBuildBeaconProbeRespFrameCommonIEs(IN struct MSDU_INFO + *prMsduInfo, + IN struct BSS_INFO *prBssInfo, + IN uint8_t *pucDestAddr); + +void +bssComposeBeaconProbeRespFrameHeaderAndFF( + IN uint8_t *pucBuffer, + IN uint8_t *pucDestAddr, + IN uint8_t *pucOwnMACAddress, + IN uint8_t *pucBSSID, IN uint16_t u2BeaconInterval, + IN uint16_t u2CapInfo); + +uint32_t +bssSendBeaconProbeResponse(IN struct ADAPTER *prAdapter, + IN uint8_t uBssIndex, IN uint8_t *pucDestAddr, + IN uint32_t u4ControlFlags); + +uint32_t bssProcessProbeRequest(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +void bssInitializeClientList(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo); + +void bssAddClient(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct STA_RECORD *prStaRec); + +u_int8_t bssRemoveClient(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct STA_RECORD *prStaRec); + +struct STA_RECORD *bssRemoveClientByMac(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN uint8_t *pucMac); + +struct STA_RECORD *bssGetClientByMac(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN uint8_t *pucMac); + +struct STA_RECORD *bssRemoveHeadClient(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo); + +uint32_t bssGetClientCount(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo); + +void bssDumpClientList(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo); + +void bssCheckClientList(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo); + +/*----------------------------------------------------------------------------*/ +/* Routines for IBSS(AdHoc) only */ +/*----------------------------------------------------------------------------*/ +void +ibssProcessMatchedBeacon(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct BSS_DESC *prBssDesc, IN uint8_t ucRCPI); + +uint32_t ibssCheckCapabilityForAdHocMode(IN struct ADAPTER + *prAdapter, IN struct BSS_DESC *prBssDesc); + +void ibssInitForAdHoc(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo); + +uint32_t bssUpdateBeaconContent(IN struct ADAPTER + *prAdapter, IN uint8_t uBssIndex); + +/*----------------------------------------------------------------------------*/ +/* Routines for BSS(AP) only */ +/*----------------------------------------------------------------------------*/ +void bssInitForAP(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, IN u_int8_t fgIsRateUpdate); + +void bssUpdateDTIMCount(IN struct ADAPTER *prAdapter, + IN uint8_t uBssIndex); + +void bssSetTIMBitmap(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, IN uint16_t u2AssocId); + +/*link function to p2p module for txBcnIETable*/ + +/* WMM-2.2.2 WMM ACI to AC coding */ +enum ENUM_ACI { + ACI_BE = 0, + ACI_BK = 1, + ACI_VI = 2, + ACI_VO = 3, + ACI_NUM +}; + +enum ENUM_AC_PRIORITY { + AC_BK_PRIORITY = 0, + AC_BE_PRIORITY, + AC_VI_PRIORITY, + AC_VO_PRIORITY +}; + +#endif /* _BSS_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/cnm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/cnm.h new file mode 100644 index 0000000000000..3bdacaad8691b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/cnm.h @@ -0,0 +1,429 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3 + * /include/mgmt/cnm.h#1 + */ + +/*! \file "cnm.h" + * \brief + */ + + +#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 + ******************************************************************************* + */ +#if CFG_SUPPORT_DBDC +#define DBDC_5G_WMM_INDEX 0 +#define DBDC_2G_WMM_INDEX 1 +#endif +#define HW_WMM_NUM (prAdapter->ucWmmSetNum) +#define MAX_HW_WMM_INDEX (HW_WMM_NUM - 1) +#define DEFAULT_HW_WMM_INDEX MAX_HW_WMM_INDEX +#if CFG_SUPPORT_RX_DYNAMIC_MCC_PRIORITY +#define MCC_CMD_MAX_LEN 100 +#define MCC_RX_CNT_LOW_BOUND 100 +#define MCC_RX_CNT_HIGH_BOUND 200 +#define MCC_CHECK_TIME 5 +#endif +#if CFG_SUPPORT_ADJUST_MCC_MODE_SET +#define CFG_MCC_AIS_QUOTA_TYPE 0 +#define CFG_MCC_P2PGC_QUOTA_TYPE 1 +#define CFG_MCC_P2PGO_QUOTA_TYPE 2 +#endif +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +enum ENUM_CH_REQ_TYPE { + CH_REQ_TYPE_JOIN, + CH_REQ_TYPE_P2P_LISTEN, + CH_REQ_TYPE_OFFCHNL_TX, + CH_REQ_TYPE_GO_START_BSS, +#if (CFG_SUPPORT_DFS_MASTER == 1) + CH_REQ_TYPE_DFS_CAC, +#endif + CH_REQ_TYPE_NUM +}; +#if (CFG_SUPPORT_IDC_CH_SWITCH == 1) +enum ENUM_CH_SWITCH_TYPE { + CH_SWITCH_2G, /* Default */ + CH_SWITCH_5G, + CH_SWITCH_NUM +}; +#endif + +struct MSG_CH_REQ { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucBssIndex; + uint8_t ucTokenID; + uint8_t ucPrimaryChannel; + enum ENUM_CHNL_EXT eRfSco; + enum ENUM_BAND eRfBand; + + /* To support 80/160MHz bandwidth */ + enum ENUM_CHANNEL_WIDTH eRfChannelWidth; + + uint8_t ucRfCenterFreqSeg1; /* To support 80/160MHz bandwidth */ + uint8_t ucRfCenterFreqSeg2; /* To support 80/160MHz bandwidth */ + enum ENUM_CH_REQ_TYPE eReqType; + uint32_t u4MaxInterval; /* In unit of ms */ + enum ENUM_DBDC_BN eDBDCBand; +}; + +struct MSG_CH_ABORT { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucBssIndex; + uint8_t ucTokenID; + enum ENUM_DBDC_BN eDBDCBand; +}; + +struct MSG_CH_GRANT { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucBssIndex; + uint8_t ucTokenID; + uint8_t ucPrimaryChannel; + enum ENUM_CHNL_EXT eRfSco; + enum ENUM_BAND eRfBand; + + /* To support 80/160MHz bandwidth */ + enum ENUM_CHANNEL_WIDTH eRfChannelWidth; + + uint8_t ucRfCenterFreqSeg1; /* To support 80/160MHz bandwidth */ + uint8_t ucRfCenterFreqSeg2; /* To support 80/160MHz bandwidth */ + enum ENUM_CH_REQ_TYPE eReqType; + uint32_t u4GrantInterval; /* In unit of ms */ + enum ENUM_DBDC_BN eDBDCBand; +}; + +struct MSG_CH_REOCVER { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucBssIndex; + uint8_t ucTokenID; + uint8_t ucPrimaryChannel; + enum ENUM_CHNL_EXT eRfSco; + enum ENUM_BAND eRfBand; + + /* To support 80/160MHz bandwidth */ + enum ENUM_CHANNEL_WIDTH eRfChannelWidth; + + uint8_t ucRfCenterFreqSeg1; /* To support 80/160MHz bandwidth */ + uint8_t ucRfCenterFreqSeg2; /* To support 80/160MHz bandwidth */ + enum ENUM_CH_REQ_TYPE eReqType; +}; + +struct CNM_INFO { + u_int8_t fgChGranted; + uint8_t ucBssIndex; + uint8_t ucTokenID; +}; + +#if CFG_ENABLE_WIFI_DIRECT +/* Moved from p2p_fsm.h */ +struct DEVICE_TYPE { + uint16_t u2CategoryId; /* Category ID */ + uint8_t aucOui[4]; /* OUI */ + uint16_t u2SubCategoryId; /* Sub Category ID */ +} __KAL_ATTRIB_PACKED__; +#endif + +#if CFG_SUPPORT_DBDC +struct CNM_DBDC_CAP { + uint8_t ucBssIndex; + uint8_t ucNss; + uint8_t ucWmmSetIndex; +}; + +enum ENUM_CNM_DBDC_MODE { + /* A/G traffic separate by WMM, but both + * TRX on band 0, CANNOT enable DBDC + */ + ENUM_DBDC_MODE_DISABLED, + + /* A/G traffic separate by WMM, WMM0/1 + * TRX on band 0/1, CANNOT disable DBDC + */ + ENUM_DBDC_MODE_STATIC, + + /* Automatically enable/disable DBDC, + * setting just like static/disable mode + */ + ENUM_DBDC_MODE_DYNAMIC, + + ENUM_DBDC_MODE_NUM +}; + +enum ENUM_CNM_DBDC_SWITCH_MECHANISM { /* When DBDC available in dynamic DBDC */ + /* Switch to DBDC when available (less latency) */ + ENUM_DBDC_SWITCH_MECHANISM_LATENCY_MODE, + + /* Switch to DBDC when DBDC T-put > MCC T-put */ + ENUM_DBDC_SWITCH_MECHANISM_THROUGHPUT_MODE, + + ENUM_DBDC_SWITCH_MECHANISM_NUM +}; +#endif /* CFG_SUPPORT_DBDC */ + +enum ENUM_CNM_NETWORK_TYPE_T { + ENUM_CNM_NETWORK_TYPE_OTHER, + ENUM_CNM_NETWORK_TYPE_AIS, + ENUM_CNM_NETWORK_TYPE_P2P_GC, + ENUM_CNM_NETWORK_TYPE_P2P_GO, + ENUM_CNM_NETWORK_TYPE_NUM +}; + +/******************************************************************************* + * P U B 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 CNM_CH_GRANTED_FOR_BSS(_prAdapter, _ucBssIndex) \ + ((_prAdapter)->rCnmInfo.fgChGranted && \ + (_prAdapter)->rCnmInfo.ucBssIndex == (_ucBssIndex)) + +#define IS_CONNECTION_NSS2(prBssInfo, prStaRec) \ + ((((prBssInfo)->ucNss > 1) && ((prStaRec)->aucRxMcsBitmask[1] != 0x00) \ + && (((prStaRec)->u2HtCapInfo & HT_CAP_INFO_SM_POWER_SAVE) != 0)) || \ + (((prBssInfo)->ucNss > 1) && ((((prStaRec)->u2VhtRxMcsMap \ + & BITS(2, 3)) >> 2) != BITS(0, 1)) && ((((prStaRec)->ucVhtOpMode \ + & VHT_OP_MODE_RX_NSS) >> VHT_OP_MODE_RX_NSS_OFFSET) > 0))) + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +void cnmInit(struct ADAPTER *prAdapter); + +void cnmUninit(struct ADAPTER *prAdapter); + +void cnmChMngrRequestPrivilege(struct ADAPTER *prAdapter, + struct MSG_HDR *prMsgHdr); + +void cnmChMngrAbortPrivilege(struct ADAPTER *prAdapter, + struct MSG_HDR *prMsgHdr); + +void cnmChMngrHandleChEvent(struct ADAPTER *prAdapter, + struct WIFI_EVENT *prEvent); + +#if (CFG_SUPPORT_DFS_MASTER == 1) +void cnmRadarDetectEvent(struct ADAPTER *prAdapter, + struct WIFI_EVENT *prEvent); + +void cnmCsaDoneEvent(struct ADAPTER *prAdapter, + struct WIFI_EVENT *prEvent); + +#if (CFG_SUPPORT_IDC_CH_SWITCH == 1) +uint8_t cnmIdcCsaReq(IN struct ADAPTER *prAdapter, + IN uint8_t ch_num, IN uint8_t ucRoleIdx); + +void cnmIdcDetectHandler(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +#endif +#endif + +u_int8_t cnmPreferredChannel(struct ADAPTER *prAdapter, enum ENUM_BAND *prBand, + uint8_t *pucPrimaryChannel, enum ENUM_CHNL_EXT *prBssSCO); + +u_int8_t cnmAisInfraChannelFixed(struct ADAPTER *prAdapter, + enum ENUM_BAND *prBand, uint8_t *pucPrimaryChannel); + +void cnmAisInfraConnectNotify(struct ADAPTER *prAdapter); + +u_int8_t cnmAisIbssIsPermitted(struct ADAPTER *prAdapter); + +u_int8_t cnmP2PIsPermitted(struct ADAPTER *prAdapter); + +u_int8_t cnmBowIsPermitted(struct ADAPTER *prAdapter); + +u_int8_t cnmBss40mBwPermitted(struct ADAPTER *prAdapter, uint8_t ucBssIndex); + +u_int8_t cnmBss80mBwPermitted(struct ADAPTER *prAdapter, uint8_t ucBssIndex); + +uint8_t cnmGetBssMaxBw(struct ADAPTER *prAdapter, uint8_t ucBssIndex); + +uint8_t cnmGetBssMaxBwToChnlBW(struct ADAPTER *prAdapter, uint8_t ucBssIndex); + +struct BSS_INFO *cnmGetBssInfoAndInit(struct ADAPTER *prAdapter, + enum ENUM_NETWORK_TYPE eNetworkType, u_int8_t fgIsP2pDevice); + +void cnmFreeBssInfo(struct ADAPTER *prAdapter, struct BSS_INFO *prBssInfo); +#if CFG_SUPPORT_CHNL_CONFLICT_REVISE +u_int8_t cnmAisDetectP2PChannel(struct ADAPTER *prAdapter, + enum ENUM_BAND *prBand, uint8_t *pucPrimaryChannel); +#endif + +u_int8_t cnmWmmIndexDecision(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo); +void cnmFreeWmmIndex(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo); + +#if CFG_SUPPORT_DBDC +void cnmInitDbdcSetting(IN struct ADAPTER *prAdapter); + +void cnmDbdcOpModeChangeDoneCallback( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN u_int8_t fgSuccess); + +void cnmUpdateDbdcSetting(IN struct ADAPTER *prAdapter, IN u_int8_t fgDbdcEn); + +void cnmGetDbdcCapability( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN enum ENUM_BAND eRfBand, + IN uint8_t ucPrimaryChannel, + IN uint8_t ucNss, + OUT struct CNM_DBDC_CAP *prDbdcCap +); + +uint8_t cnmGetDbdcBwCapability( + struct ADAPTER *prAdapter, + uint8_t ucBssIndex +); + +void cnmDbdcEnableDecision( + IN struct ADAPTER *prAdapter, + IN uint8_t ucChangedBssIndex, + IN enum ENUM_BAND eRfBand, + IN uint8_t ucPrimaryChannel, + IN uint8_t ucWmmQueIdx +); + +void cnmDbdcDisableDecision(IN struct ADAPTER *prAdapter, + IN uint8_t ucChangedBssIndex); +void cnmDbdcGuardTimerCallback(IN struct ADAPTER *prAdapter, + IN unsigned long plParamPtr); +void cnmDbdcEventHwSwitchDone(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +#endif /*CFG_SUPPORT_DBDC*/ +void cnmCheckPendingTimer(IN struct ADAPTER *prAdapter); + +enum ENUM_CNM_NETWORK_TYPE_T cnmGetBssNetworkType(struct BSS_INFO *prBssInfo); + +#if CFG_SUPPORT_RX_DYNAMIC_MCC_PRIORITY +void cnmRxCntMonitor(IN struct ADAPTER *prAdapter, + IN unsigned long plParamPtr); +void cnmSetMccTime(IN struct ADAPTER *prAdapter, + IN uint8_t ucRole, IN uint32_t u4StayTime); +#endif /*CFG_SUPPORT_RX_DYNAMIC_MCC_PRIORITY*/ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#ifndef _lint +/* We don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + * We'll need this to guarantee the same member order in different structures + * to simply handling effort in some functions. + */ +static __KAL_INLINE__ void cnmMsgDataTypeCheck(void) +{ + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSG_CH_GRANT, rMsgHdr) + == 0); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSG_CH_GRANT, rMsgHdr) + == OFFSET_OF(struct MSG_CH_REOCVER, rMsgHdr)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSG_CH_GRANT, ucBssIndex) + == OFFSET_OF(struct MSG_CH_REOCVER, ucBssIndex)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSG_CH_GRANT, ucTokenID) + == OFFSET_OF(struct MSG_CH_REOCVER, ucTokenID)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSG_CH_GRANT, ucPrimaryChannel) + == OFFSET_OF(struct MSG_CH_REOCVER, ucPrimaryChannel)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSG_CH_GRANT, eRfSco) + == OFFSET_OF(struct MSG_CH_REOCVER, eRfSco)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSG_CH_GRANT, eRfBand) + == OFFSET_OF(struct MSG_CH_REOCVER, eRfBand)); + + DATA_STRUCT_INSPECTING_ASSERT( + OFFSET_OF(struct MSG_CH_GRANT, eReqType) + == OFFSET_OF(struct MSG_CH_REOCVER, eReqType)); +} +#endif /* _lint */ + +#endif /* _CNM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/cnm_mem.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/cnm_mem.h new file mode 100644 index 0000000000000..0e3fc389d55cf --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/cnm_mem.h @@ -0,0 +1,1177 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + + +#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 + ******************************************************************************* + */ +#include "qosmap.h" +/******************************************************************************* + * 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 */ +/* 7 to the power of 2 = 128 */ +#define MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2 7 + +/* 5 to the power of 2 = 32 */ +#define MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2 5 + +/* 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) \ + ((uint32_t)(n) << MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2) +#define MSG_BUF_BLOCKS_SIZE(n) \ + ((uint32_t)(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 + +/* Number of SW queues in each STA_REC: AC0~AC4 */ +#define STA_WAIT_QUEUE_NUM 5 + +/* Number of SC caches in each STA_REC: AC0~AC4 */ +#define SC_CACHE_INDEX_NUM 5 + +/* P2P related definitions */ +#if CFG_ENABLE_WIFI_DIRECT +/* Moved from p2p_fsm.h */ +#define WPS_ATTRI_MAX_LEN_DEVICE_NAME 32 /* 0x1011 */ + +/* NOTE(Kevin): Shall <= 16 */ +#define P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT 8 +#endif + +/* Define the argument of cnmStaFreeAllStaByNetwork when all station records + * will be free. No one will be free + */ +#define STA_REC_EXCLUDE_NONE CFG_STA_REC_NUM + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +/* Use 32 bits to represent buffur bitmap in BUF_INFO, i.e., the variable + * rFreeBlocksBitmap in BUF_INFO structure. + */ +#if (MAX_NUM_OF_BUF_BLOCKS != 32) +#error > #define MAX_NUM_OF_MGT_BUF_BLOCKS should be 32 ! +#endif /* MAX_NUM_OF_MGT_BUF_BLOCKS */ + +/* Control variable of TX management memory pool */ +struct BUF_INFO { + uint8_t *pucBuf; + +#if CFG_DBG_MGT_BUF + uint32_t u4AllocCount; + uint32_t u4FreeCount; + uint32_t u4AllocNullCount; +#endif /* CFG_DBG_MGT_BUF */ + + uint32_t rFreeBlocksBitmap; + uint8_t aucAllocatedBlockNum[MAX_NUM_OF_BUF_BLOCKS]; +}; + +/* Wi-Fi divides RAM into three types + * MSG: Mailbox message (Small size) + * BUF: HW DMA buffers (HIF/MAC) + */ +enum ENUM_RAM_TYPE { + RAM_TYPE_MSG = 0, + RAM_TYPE_BUF +}; + +enum ENUM_BUFFER_SOURCE { + BUFFER_SOURCE_HIF_TX0 = 0, + BUFFER_SOURCE_HIF_TX1, + BUFFER_SOURCE_MAC_RX, + BUFFER_SOURCE_MNG, + BUFFER_SOURCE_BCN, + BUFFER_SOURCE_NUM +}; + +enum ENUM_SEC_STATE { + 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 +}; + +struct TSPEC_ENTRY { + uint8_t ucStatus; + uint8_t ucToken; /* Dialog Token in ADDTS_REQ or ADDTS_RSP */ + uint16_t u2MediumTime; + uint32_t u4TsInfo; + /* PARAM_QOS_TS_INFO rParamTsInfo; */ + /* Add other retained QoS parameters below */ +}; + +#if 0 +struct SEC_INFO { + + enum ENUM_SEC_STATE ePreviousState; + enum ENUM_SEC_STATE eCurrentState; + + u_int8_t fg2nd1xSend; + u_int8_t fgKeyStored; + + uint8_t aucStoredKey[64]; + + u_int8_t fgAllowOnly1x; +}; +#endif + +#define MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS 3 + +#define UPDATE_BSS_RSSI_INTERVAL_SEC 3 /* Seconds */ + +/* Fragment information structure */ +struct FRAG_INFO { + uint16_t u2NextFragSeqCtrl; + uint8_t *pucNextFragStart; + struct SW_RFB *pr1stFrag; + + /* The receive time of 1st fragment */ + OS_SYSTIME rReceiveLifetimeLimit; +}; + +#if CFG_SUPPORT_802_11W +/* AP PMF */ +struct AP_PMF_CFG { + u_int8_t fgMfpc; + u_int8_t fgMfpr; + u_int8_t fgSha256; + u_int8_t fgAPApplyPmfReq; + u_int8_t fgBipKeyInstalled; +}; + +struct STA_PMF_CFG { + u_int8_t fgMfpc; + u_int8_t fgMfpr; + u_int8_t fgSha256; + u_int8_t fgApplyPmf; + u_int8_t fgBipKeyInstalled; + + /* for certification 4.3.3.1, 4.3.3.2 TX unprotected deauth */ + u_int8_t fgRxDeauthResp; + + /* For PMF SA query TX request retry a timer */ + /* record the start time of 1st SAQ request */ + uint32_t u4SAQueryStart; + + uint32_t u4SAQueryCount; + uint8_t ucSAQueryTimedOut; /* retry more than 1000ms */ + struct TIMER rSAQueryTimer; + uint16_t u2TransactionID; +}; +#endif + +#if DSCP_SUPPORT +struct _DSCP_EXCEPTION { + uint8_t dscp; + uint8_t userPriority; +}; + +struct _DSCP_RANGE { + uint8_t lDscp; + uint8_t hDscp; +}; + +struct _QOS_MAP_SET { + struct _DSCP_RANGE dscpRange[8]; + uint8_t dscpExceptionNum; + struct _DSCP_EXCEPTION dscpException[1]; +}; +#endif + +/* Define STA record structure */ +struct STA_RECORD { + struct LINK_ENTRY rLinkEntry; + uint8_t ucIndex; /* Not modify it except initializing */ + uint8_t ucWlanIndex; /* WLAN table index */ + +#if 0 /* TODO: Remove this */ + /* The BSS STA Rx WLAN index, IBSS Rx BC WLAN table + * index, work at IBSS Open and WEP + */ + uint8_t ucBMCWlanIndex; +#endif + + u_int8_t fgIsInUse; /* Indicate if this entry is in use or not */ + uint8_t aucMacAddr[MAC_ADDR_LEN]; /* MAC address */ + + /* SAA/AAA */ + /* Store STATE Value used in SAA/AAA */ + enum ENUM_AA_STATE eAuthAssocState; + + uint8_t ucAuthAssocReqSeqNum; + + /* Indicate the role of this STA in the network (for example, P2P GO) */ + enum ENUM_STA_TYPE eStaType; + + uint8_t ucBssIndex; /* BSS_INFO_I index */ + + uint8_t ucStaState; /* STATE_1,2,3 */ + + /* Available PHY Type Set of this peer (may deduced from + * received struct BSS_DESC) + */ + uint8_t ucPhyTypeSet; + + /* record from bcn or probe response */ + uint8_t ucVhtCapNumSoundingDimensions; + + /* The match result by AND operation of peer's PhyTypeSet and ours. */ + uint8_t ucDesiredPhyTypeSet; + + /* A flag to indicate a Basic Phy Type which is used to generate some + * Phy Attribute IE (e.g. capability, MIB) during association. + */ + u_int8_t fgHasBasicPhyType; + + /* The Basic Phy Type chosen among the ucDesiredPhyTypeSet. */ + uint8_t ucNonHTBasicPhyType; + + uint16_t u2HwDefaultFixedRateCode; + + /* For Infra Mode, to store Capability Info. from Association Resp(SAA). + * For AP Mode, to store Capability Info. from Association Req(AAA). + */ + uint16_t u2CapInfo; + + /* For Infra Mode, to store AID from Association Resp(SAA). + * For AP Mode, to store the Assigned AID(AAA). + */ + uint16_t u2AssocId; + + uint16_t u2ListenInterval; /* Listen Interval from STA(AAA) */ + + /* Our Current Desired Rate Set after match + * with STA's Operational Rate Set + */ + uint16_t u2DesiredNonHTRateSet; + + uint16_t u2OperationalRateSet; /* Operational Rate Set of peer BSS */ + uint16_t u2BSSBasicRateSet; /* Basic Rate Set of peer BSS */ + + /* For IBSS Mode, to indicate that Merge is ongoing */ + u_int8_t fgIsMerging; + + /* For Infra/AP Mode, to diagnose the Connection with this peer + * by sending ProbeReq/Null frame + */ + u_int8_t fgDiagnoseConnection; + + /*---------------------------------------------------------------------- + * 802.11n HT capabilities when (prStaRec->ucPhyTypeSet & + * PHY_TYPE_BIT_HT) is true. They have the same definition with fields + * of information element + *---------------------------------------------------------------------- + */ + uint8_t ucMcsSet; /* MCS0~7 rate set of peer BSS */ + u_int8_t fgSupMcs32; /* MCS32 is supported by peer BSS */ + uint8_t aucRxMcsBitmask[SUP_MCS_RX_BITMASK_OCTET_NUM]; + uint16_t u2RxHighestSupportedRate; + uint32_t u4TxRateInfo; + uint16_t u2HtCapInfo; /* HT cap info field by HT cap IE */ + uint8_t ucAmpduParam; /* Field A-MPDU Parameters in HT cap IE */ + uint16_t u2HtExtendedCap; /* HT extended cap field by HT cap IE */ + + /* TX beamforming cap field by HT cap IE */ + uint32_t u4TxBeamformingCap; + + uint8_t ucAselCap; /* ASEL cap field by HT cap IE */ + +#if 1 /* CFG_SUPPORT_802_11AC */ + /*---------------------------------------------------------------------- + * 802.11ac VHT capabilities when (prStaRec->ucPhyTypeSet & + * PHY_TYPE_BIT_VHT) is true. They have the same definition with fields + * of information element + *---------------------------------------------------------------------- + */ + uint32_t u4VhtCapInfo; + uint16_t u2VhtRxMcsMap; + uint16_t u2VhtRxHighestSupportedDataRate; + uint16_t u2VhtTxMcsMap; + uint16_t u2VhtTxHighestSupportedDataRate; + uint8_t ucVhtOpMode; +#endif + /*---------------------------------------------------------------------- + * 802.11ac HT operation info when (prStaRec->ucPhyTypeSet & + * PHY_TYPE_BIT_HT) is true. They have the same definition with fields + * of information element + *---------------------------------------------------------------------- + */ + uint8_t ucHtPeerOpInfo1; /* Backup peer HT OP Info */ + + /*---------------------------------------------------------------------- + * 802.11ac VHT operation info when (prStaRec->ucPhyTypeSet & + * PHY_TYPE_BIT_VHT) is true. They have the same definition with fields + * of information element + *---------------------------------------------------------------------- + */ + /* Backup peer VHT Op Info */ + uint8_t ucVhtOpChannelWidth; + uint8_t ucVhtOpChannelFrequencyS1; + uint8_t ucVhtOpChannelFrequencyS2; + + + uint8_t ucRCPI; /* RCPI of peer */ + + /* Target BSS's DTIM Period, we use this value for + * setup Listen Interval + * TODO(Kevin): TBD + */ + uint8_t ucDTIMPeriod; + + /* For Infra/AP Mode, the Auth Algorithm Num used + * in Authentication(SAA/AAA) + */ + uint8_t ucAuthAlgNum; + uint8_t ucAuthTranNum; /* For Infra/AP Mode, the Auth Transaction Number + */ + + /* For Infra/AP Mode, to indicate ReAssoc Frame was in used(SAA/AAA) */ + u_int8_t fgIsReAssoc; + + /* For Infra Mode, the Retry Count of TX Auth/Assod Frame(SAA) */ + uint8_t ucTxAuthAssocRetryCount; + + /* For Infra Mode, the Retry Limit of TX Auth/Assod Frame(SAA) */ + uint8_t ucTxAuthAssocRetryLimit; + +#if CFG_SUPPORT_CFG80211_AUTH + /* Record what we sent for + * retry TX Auth/Assoc without SAA FSM + */ + enum ENUM_AA_SENT_T eAuthAssocSent; +#endif + + uint16_t u2StatusCode; /* Status of Auth/Assoc Req */ + uint16_t u2ReasonCode; /* Reason that been Deauth/Disassoc */ + + /* Point to an allocated buffer for storing Challenge */ + /* Text for Shared Key Authentication */ + struct IE_CHALLENGE_TEXT *prChallengeText; + + /* For Infra Mode, a timer used to send a timeout event + * while waiting for TX request done or RX response. + */ + struct TIMER rTxReqDoneOrRxRespTimer; + + /* For Infra Mode, a timer used to avoid the Deauth frame + * not be sent + */ + struct TIMER rDeauthTxDoneTimer; + + /*---------------------------------------------------------------------- + * Power Management related fields (for STA/ AP/ P2P/ BOW power saving + * mode) + *---------------------------------------------------------------------- + */ + /* For Infra Mode, to indicate that outgoing frame need + * toggle the Pwr Mgt Bit in its Frame Control Field. + */ + u_int8_t fgSetPwrMgtBit; + + /* For AP Mode, to indicate the client PS state(PM). + * TRUE: In PS Mode; FALSE: In Active Mode. + */ + u_int8_t fgIsInPS; + + /* For Infra Mode, to indicate we've sent a PS POLL to AP + * and start the PS_POLL Service Period(LP) + */ + u_int8_t fgIsInPsPollSP; + + /* For Infra Mode, to indicate we've sent a Trigger Frame + * to AP and start the Delivery Service Period(LP) + */ + u_int8_t fgIsInTriggerSP; + + uint8_t ucBmpDeliveryAC; /* 0: AC0, 1: AC1, 2: AC2, 3: AC3 */ + + uint8_t ucBmpTriggerAC; /* 0: AC0, 1: AC1, 2: AC2, 3: AC3 */ + + uint8_t ucUapsdSp; /* Max SP length */ + + /*--------------------------------------------------------------------*/ + + u_int8_t fgIsRtsEnabled; + + /* (4) System Timestamp of Successful TX and RX */ + uint32_t rUpdateTime; + + /* (4) System Timestamp of latest JOIN process */ + uint32_t rLastJoinTime; + + uint8_t ucJoinFailureCount; /* Retry Count of JOIN process */ + + /* For TXM to defer pkt forwarding to MAC TX DMA */ + struct LINK arStaWaitQueue[STA_WAIT_QUEUE_NUM]; + + /* Duplicate removal for HT STA on a + * per-TID basis ("+1" is for MMPDU and non-QoS) + */ + uint16_t au2CachedSeqCtrl[TID_NUM + 1]; + + u_int8_t afgIsIgnoreAmsduDuplicate[TID_NUM + 1]; + +#if 0 + /* RXM */ + struct RX_BA_ENTRY *aprRxBaTable[TID_NUM]; + + /* TXM */ + P_TX_BA_ENTRY_T aprTxBaTable[TID_NUM]; +#endif + + struct FRAG_INFO rFragInfo[MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS]; + +#if 0 /* TODO: Remove this */ + struct SEC_INFO rSecInfo; /* The security state machine */ +#endif + +#if CFG_SUPPORT_ADHOC + /* Ad-hoc RSN Rx BC key exist flag, only reserved two + * entry for each peer + */ + u_int8_t fgAdhocRsnBcKeyExist[2]; + + /* Ad-hoc RSN Rx BC wlan index */ + uint8_t ucAdhocRsnBcWlanIndex[2]; +#endif + + u_int8_t fgPortBlock; /* The 802.1x Port Control flag */ + + u_int8_t fgTransmitKeyExist; /* Unicast key exist for this STA */ + + u_int8_t fgTxAmpduEn; /* Enable TX AMPDU for this Peer */ + u_int8_t fgRxAmpduEn; /* Enable RX AMPDU for this Peer */ + + uint8_t *pucAssocReqIe; + uint16_t u2AssocReqIeLen; + + /* link layer satatistics */ + struct WIFI_WMM_AC_STAT arLinkStatistics[WMM_AC_INDEX_NUM]; + + /*---------------------------------------------------------------------- + * WMM/QoS related fields + *---------------------------------------------------------------------- + */ + /* If the STA is associated as a QSTA or QAP (for TX/RX) */ + u_int8_t fgIsQoS; + + /* If the peer supports WMM, set to TRUE (for association) */ + u_int8_t fgIsWmmSupported; + + /* Set according to the scan result (for association) */ + u_int8_t fgIsUapsdSupported; + + u_int8_t afgAcmRequired[ACI_NUM]; + + /*---------------------------------------------------------------------- + * P2P related fields + *---------------------------------------------------------------------- + */ +#if CFG_ENABLE_WIFI_DIRECT + uint8_t u2DevNameLen; + uint8_t aucDevName[WPS_ATTRI_MAX_LEN_DEVICE_NAME]; + + uint8_t aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ + + uint16_t u2ConfigMethods; + + uint8_t ucDeviceCap; + + uint8_t ucSecondaryDevTypeCount; + + struct DEVICE_TYPE rPrimaryDevTypeBE; + + struct DEVICE_TYPE arSecondaryDevTypeBE[ + P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT]; +#endif /* CFG_SUPPORT_P2P */ + + /*---------------------------------------------------------------------- + * QM related fields + *---------------------------------------------------------------------- + */ + /* Per Sta flow controal. Valid when fgIsInPS is TRUE. + * Change it for per Queue flow control + */ + uint8_t ucFreeQuota; + +#if 0 /* TODO: Remove this */ + /* used in future */ + uint8_t aucFreeQuotaPerQueue[NUM_OF_PER_STA_TX_QUEUES]; +#endif + uint8_t ucFreeQuotaForDelivery; + uint8_t ucFreeQuotaForNonDelivery; + + /*---------------------------------------------------------------------- + * TXM related fields + *---------------------------------------------------------------------- + */ + void *aprTxDescTemplate[TX_DESC_TID_NUM]; + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE && CFG_ENABLE_PER_STA_STATISTICS + uint32_t u4TotalTxPktsNumber; + uint32_t u4TotalTxPktsTime; + uint32_t u4TotalTxPktsHifTxTime; + + uint32_t u4TotalRxPktsNumber; + uint32_t u4MaxTxPktsTime; + uint32_t u4MaxTxPktsHifTime; + + uint32_t u4ThresholdCounter; + uint32_t u4EnqueueCounter; + uint32_t u4DeqeueuCounter; +#endif + +#if 1 + /*---------------------------------------------------------------------- + * To be removed, this is to make que_mgt compilation success only + *---------------------------------------------------------------------- + */ + /* When this STA_REC is in use, set to TRUE. */ + u_int8_t fgIsValid; + + /* TX key is ready */ + u_int8_t fgIsTxKeyReady; + + /* When the STA is connected or TX key is ready */ + u_int8_t fgIsTxAllowed; + + /* Per-STA Queues: [0] AC0, [1] AC1, [2] AC2, [3] AC3 */ + struct QUE arTxQueue[NUM_OF_PER_STA_TX_QUEUES]; + + /* Per-STA Pending Queues: [0] AC0, [1] AC1, [2] AC2, [3] AC3 */ + /* This queue is for Tx packet in protected BSS before key is set */ + struct QUE arPendingTxQueue[NUM_OF_PER_STA_TX_QUEUES]; + + /* Tx packet target queue pointer. Select between arTxQueue & + * arPendingTxQueue + */ + struct QUE *aprTargetQueue[NUM_OF_PER_STA_TX_QUEUES]; + + /* Reorder Parameter reference table */ + struct RX_BA_ENTRY *aprRxReorderParamRefTbl[CFG_RX_MAX_BA_TID_NUM]; +#endif + +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT + struct TIMINGMSMT_PARAM rWNMTimingMsmt; +#endif + uint8_t ucTrafficDataType; /* 0: auto 1: data 2: video 3: voice */ + + /* 0: auto 1:Force enable 2: Force disable 3: enable by peer */ + uint8_t ucTxGfMode; + + /* 0: auto 1:Force enable 2: Force disable 3: enable by peer */ + uint8_t ucTxSgiMode; + + /* 0: auto 1:Force enable 2: Force disable 3: enable by peer */ + uint8_t ucTxStbcMode; + + uint32_t u4FixedPhyRate; + uint16_t u2MaxLinkSpeed; /* unit is 0.5 Mbps */ + uint16_t u2MinLinkSpeed; + uint32_t u4Flags; /* reserved for MTK Synergies */ + +#if CFG_SUPPORT_TDLS + u_int8_t fgTdlsIsProhibited; /* TRUE: AP prohibits TDLS links */ + + /* TRUE: AP prohibits TDLS chan switch */ + u_int8_t fgTdlsIsChSwProhibited; + + u_int8_t flgTdlsIsInitiator; /* TRUE: the peer is the initiator */ + + /* temp to queue HT capability element */ + struct IE_HT_CAP rTdlsHtCap; + + struct PARAM_KEY rTdlsKeyTemp; /* temp to queue the key information */ + uint8_t ucTdlsIndex; +#endif /* CFG_SUPPORT_TDLS */ +#if CFG_SUPPORT_TX_BF + struct TXBF_PFMU_STA_INFO rTxBfPfmuStaInfo; +#endif +#if CFG_SUPPORT_MSP + uint32_t u4RxVector0; + uint32_t u4RxVector1; + uint32_t u4RxVector2; + uint32_t u4RxVector3; + uint32_t u4RxVector4; +#endif + uint8_t ucSmDialogToken; /* Spectrum Mngt Dialog Token */ + uint8_t ucSmMsmtRequestMode; /* Measurement Request Mode */ + uint8_t ucSmMsmtToken; /* Measurement Request Token */ + + /* Element for AMSDU */ + uint8_t ucAmsduEnBitmap; /* Tid bit mask of AMSDU enable */ + uint8_t ucMaxMpduCount; + uint32_t u4MaxMpduLen; + uint32_t u4MinMpduLen; +#if CFG_SUPPORT_802_11W + /* AP PMF */ + struct STA_PMF_CFG rPmfCfg; +#endif +#if DSCP_SUPPORT + struct _QOS_MAP_SET *qosMapSet; +#endif + u_int8_t fgSupportBTM; /* Indicates whether to support BTM */ + uint8_t eapol_re_enqueue_cnt; + +#if CFG_SUPPORT_GET_MCS_INFO + uint32_t au4RxV0[MCS_INFO_SAMPLE_CNT]; + uint32_t au4RxV1[MCS_INFO_SAMPLE_CNT]; +#endif + +}; + +#if 0 +/* use nic_tx.h instead */ +/* MSDU_INFO and SW_RFB structure */ +struct MSDU_INFO { + + /* 4 ----------------MSDU_INFO and SW_RFB Common Fields-------------- */ + + struct LINK_ENTRY rLinkEntry; + uint8_t *pucBuffer; /* Pointer to the associated buffer */ + + uint8_t ucBufferSource; /* HIF TX0, HIF TX1, MAC RX, or MNG Pool */ + + /* Network type index that this TX packet is assocaited with */ + uint8_t ucNetworkTypeIndex; + + /* 0 to 5 (used by HIF TX to increment the corresponding TC counter) */ + uint8_t ucTC; + + uint8_t ucTID; /* Traffic Identification */ + + u_int8_t fgIs802_11Frame; /* Set to TRUE for 802.11 frame */ + uint8_t ucMacHeaderLength; + uint16_t u2PayloadLength; + uint8_t *pucMacHeader; /* 802.11 header */ + uint8_t *pucPayload; /* 802.11 payload */ + + OS_SYSTIME rArrivalTime; /* System Timestamp (4) */ + struct STA_RECORD *prStaRec; + +#if CFG_PROFILE_BUFFER_TRACING + ENUM_BUFFER_ACTIVITY_TYPE_T eActivity[2]; + uint32_t rActivityTime[2]; +#endif +#if DBG && CFG_BUFFER_FREE_CHK + u_int8_t fgBufferInSource; +#endif + + /* For specify some Control Flags, e.g. Basic Rate */ + uint8_t ucControlFlag; + + /* 4 -----------------------Non-Common ------------------------- */ + /* TODO: move flags to ucControlFlag */ + + u_int8_t fgIs1xFrame; /* Set to TRUE for 802.1x frame */ + + /* TXM: For TX Done handling, callback function & parameter (5) */ + u_int8_t fgIsTxFailed; /* Set to TRUE if transmission failure */ + + PFN_TX_DONE_HANDLER pfTxDoneHandler; + + uint64_t u8TimeStamp; /* record the TX timestamp */ + + /* TXM: For PS forwarding control (per-STA flow control) */ + /* Delivery-enabled, non-delivery-enabled, non-PS */ + uint8_t ucPsForwardingType; + + /* The Power Save session id for PS forwarding control */ + uint8_t ucPsSessionID; + + /* TXM: For MAC TX DMA operations */ + uint8_t ucMacTxQueIdx; /* MAC TX queue: AC0-AC6, BCM, or BCN */ + + /* Set to true if Ack is not required for this packet */ + u_int8_t fgNoAck; + + u_int8_t fgBIP; /* Set to true if BIP is used for this packet */ + uint8_t ucFragTotalCount; + uint8_t ucFragFinishedCount; + + /* Fragmentation threshold without WLAN Header & FCS */ + uint16_t u2FragThreshold; + + u_int8_t fgFixedRate; /* If a fixed rate is used, set to TRUE. */ + + /* The rate code copied to MAC TX Desc */ + uint8_t ucFixedRateCode; + + /* The retry limit when a fixed rate is used */ + uint8_t ucFixedRateRetryLimit; + + /* Set to true if this packet is the end of BMC */ + u_int8_t fgIsBmcQueueEnd; + + /* TXM: For flushing ACL frames */ + uint16_t u2PalLLH; /* 802.11 PAL LLH */ + /* UINT_16 u2LLH; */ + uint16_t u2ACLSeq; /* u2LLH+u2ACLSeq for AM HCI flush ACL frame */ + + /* TXM for retransmitting a flushed packet */ + u_int8_t fgIsSnAssigned; + + /* To remember the Sequence Control field of this MPDU */ + uint16_t u2SequenceNumber; +}; +#endif + +#if 0 +/* nic_rx.h */ +struct SW_RFB { + + /* 4 ----------------MSDU_INFO and SW_RFB Common Fields-------------- */ + + struct LINK_ENTRY rLinkEntry; + uint8_t *pucBuffer; /* Pointer to the associated buffer */ + + uint8_t ucBufferSource; /* HIF TX0, HIF TX1, MAC RX, or MNG Pool */ + + /* Network type index that this TX packet is assocaited with */ + uint8_t ucNetworkTypeIndex; + + /* 0 to 5 (used by HIF TX to increment the corresponding TC counter) */ + uint8_t ucTC; + + uint8_t ucTID; /* Traffic Identification */ + + u_int8_t fgIs802_11Frame; /* Set to TRUE for 802.11 frame */ + uint8_t ucMacHeaderLength; + uint16_t u2PayloadLength; + uint8_t *pucMacHeader; /* 802.11 header */ + uint8_t *pucPayload; /* 802.11 payload */ + + OS_SYSTIME rArrivalTime; /* System Timestamp (4) */ + struct STA_RECORD *prStaRec; + +#if CFG_PROFILE_BUFFER_TRACING + ENUM_BUFFER_ACTIVITY_TYPE_T eActivity[2]; + uint32_t rActivityTime[2]; +#endif +#if DBG && CFG_BUFFER_FREE_CHK + u_int8_t fgBufferInSource; +#endif + + /* For specify some Control Flags, e.g. Basic Rate */ + uint8_t ucControlFlag; + + /* 4 -----------------------Non-Common ------------------------- */ + + /* For composing the HIF RX Header (TODO: move flags to + * ucControlFlag) + */ + /* Pointer to the Response packet to * HIF RX0 or RX1 */ + uint8_t *pucHifRxPacket; + + uint16_t u2HifRxPacketLength; + uint8_t ucHeaderOffset; + uint8_t ucHifRxPortIndex; + + uint16_t u2SequenceControl; + + /* (For MAC RX packet parsing) set to TRUE if 4 addresses are present */ + u_int8_t fgIsA4Frame; + + u_int8_t fgIsBAR; + u_int8_t fgIsQoSData; + u_int8_t fgIsAmsduSubframe; /* Set to TRUE for A-MSDU Subframe */ + + /* For HIF RX DMA Desc */ + u_int8_t fgTUChecksumCheckRequired; + u_int8_t fgIPChecksumCheckRequired; + uint8_t ucEtherTypeOffset; + +}; +#endif + +enum ENUM_STA_REC_CMD_ACTION { + STA_REC_CMD_ACTION_STA = 0, + STA_REC_CMD_ACTION_BSS = 1, + STA_REC_CMD_ACTION_BSS_EXCLUDE_STA = 2 +}; + +#if CFG_SUPPORT_TDLS + +/* TDLS FSM */ +struct CMD_PEER_ADD { + + uint8_t aucPeerMac[6]; + enum ENUM_STA_TYPE eStaType; +}; + +struct CMD_PEER_UPDATE_HT_CAP_MCS_INFO { + uint8_t arRxMask[SUP_MCS_RX_BITMASK_OCTET_NUM]; + uint16_t u2RxHighest; + uint8_t ucTxParams; + uint8_t Reserved[3]; +}; + +struct CMD_PEER_UPDATE_VHT_CAP_MCS_INFO { + uint8_t arRxMask[SUP_MCS_RX_BITMASK_OCTET_NUM]; +}; + +struct CMD_PEER_UPDATE_HT_CAP { + uint16_t u2CapInfo; + uint8_t ucAmpduParamsInfo; + + /* 16 bytes MCS information */ + struct CMD_PEER_UPDATE_HT_CAP_MCS_INFO rMCS; + + uint16_t u2ExtHtCapInfo; + uint32_t u4TxBfCapInfo; + uint8_t ucAntennaSelInfo; +}; + +struct CMD_PEER_UPDATE_VHT_CAP { + uint16_t u2CapInfo; + /* 16 bytes MCS information */ + struct CMD_PEER_UPDATE_VHT_CAP_MCS_INFO rVMCS; + +}; + +struct CMD_PEER_UPDATE { + + uint8_t aucPeerMac[6]; + +#define CMD_PEER_UPDATE_SUP_CHAN_MAX 50 + uint8_t aucSupChan[CMD_PEER_UPDATE_SUP_CHAN_MAX]; + + uint16_t u2StatusCode; + +#define CMD_PEER_UPDATE_SUP_RATE_MAX 50 + uint8_t aucSupRate[CMD_PEER_UPDATE_SUP_RATE_MAX]; + uint16_t u2SupRateLen; + + uint8_t UapsdBitmap; + uint8_t UapsdMaxSp; /* MAX_SP */ + + uint16_t u2Capability; +#define CMD_PEER_UPDATE_EXT_CAP_MAXLEN 5 + uint8_t aucExtCap[CMD_PEER_UPDATE_EXT_CAP_MAXLEN]; + uint16_t u2ExtCapLen; + + struct CMD_PEER_UPDATE_HT_CAP rHtCap; + struct CMD_PEER_UPDATE_VHT_CAP rVHtCap; + + u_int8_t fgIsSupHt; + enum ENUM_STA_TYPE eStaType; + + /* TODO */ + /* So far, TDLS only a few of the parameters, the rest will be added + * in the future requiements + */ + /* kernel 3.10 station paramenters */ +#if 0 + struct station_parameters { + const u8 *supported_rates; + struct net_device *vlan; + u32 sta_flags_mask, sta_flags_set; + u32 sta_modify_mask; + int listen_interval; + u16 aid; + u8 supported_rates_len; + u8 plink_action; + u8 plink_state; + const struct ieee80211_ht_cap *ht_capa; + const struct ieee80211_vht_cap *vht_capa; + u8 uapsd_queues; + u8 max_sp; + enum nl80211_mesh_power_mode local_pm; + u16 capability; + const u8 *ext_capab; + u8 ext_capab_len; + const u8 *supported_channels; + u8 supported_channels_len; + const u8 *supported_oper_classes; + u8 supported_oper_classes_len; + }; +#endif + +}; + +#endif +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +#if CFG_DBG_MGT_BUF +#define cnmMgtPktAlloc(_prAdapter, _u4Length) \ + cnmPktAllocWrapper((_prAdapter), (_u4Length), (uint8_t *)__func__) + +#define cnmMgtPktFree(_prAdapter, _prMsduInfo) \ + cnmPktFreeWrapper((_prAdapter), (_prMsduInfo), (uint8_t *)__func__) +#else +#define cnmMgtPktAlloc cnmPktAlloc +#define cnmMgtPktFree cnmPktFree +#endif + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +struct MSDU_INFO *cnmPktAllocWrapper(IN struct ADAPTER *prAdapter, + IN uint32_t u4Length, IN uint8_t *pucStr); + +void cnmPktFreeWrapper(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN uint8_t *pucStr); + +struct MSDU_INFO *cnmPktAlloc(IN struct ADAPTER *prAdapter, + IN uint32_t u4Length); + +void cnmPktFree(IN struct ADAPTER *prAdapter, IN struct MSDU_INFO *prMsduInfo); + +void cnmMemInit(IN struct ADAPTER *prAdapter); + +void *cnmMemAlloc(IN struct ADAPTER *prAdapter, IN enum ENUM_RAM_TYPE eRamType, + IN uint32_t u4Length); + +void cnmMemFree(IN struct ADAPTER *prAdapter, IN void *pvMemory); + +void cnmStaRecInit(IN struct ADAPTER *prAdapter); + +struct STA_RECORD * +cnmStaRecAlloc(IN struct ADAPTER *prAdapter, IN enum ENUM_STA_TYPE eStaType, + IN uint8_t ucBssIndex, IN uint8_t *pucMacAddr); + +void cnmStaRecFree(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +void cnmStaFreeAllStaByNetwork(struct ADAPTER *prAdapter, uint8_t ucBssIndex, + uint8_t ucStaRecIndexExcluded); + +struct STA_RECORD *cnmGetStaRecByIndex(IN struct ADAPTER *prAdapter, + IN uint8_t ucIndex); + +struct STA_RECORD *cnmGetStaRecByAddress(struct ADAPTER *prAdapter, + uint8_t ucBssIndex, uint8_t aucPeerMACAddress[]); + +void cnmStaRecChangeState(IN struct ADAPTER *prAdapter, + IN OUT struct STA_RECORD *prStaRec, IN uint8_t ucNewState); + +struct STA_RECORD *cnmGetAnyStaRecByAddress(struct ADAPTER *prAdapter, + uint8_t *pucPeerMacAddr); + +void cnmDumpStaRec(IN struct ADAPTER *prAdapter, IN uint8_t ucStaRecIdx); + +uint32_t cnmDumpMemoryStatus(IN struct ADAPTER *prAdapter, IN uint8_t *pucBuf, + IN uint32_t u4Max); + +#if CFG_SUPPORT_TDLS +uint32_t /* TDLS_STATUS */ +cnmPeerAdd(struct ADAPTER *prAdapter, void *pvSetBuffer, + uint32_t u4SetBufferLen, uint32_t *pu4SetInfoLen); + +uint32_t /* TDLS_STATUS */ +cnmPeerUpdate(struct ADAPTER *prAdapter, void *pvSetBuffer, + uint32_t u4SetBufferLen, uint32_t *pu4SetInfoLen); + +struct STA_RECORD *cnmGetTdlsPeerByAddress(struct ADAPTER *prAdapter, + uint8_t ucBssIndex, uint8_t aucPeerMACAddress[]); +#endif + +void cnmStaSendUpdateCmd(struct ADAPTER *prAdapter, struct STA_RECORD *prStaRec, + struct TXBF_PFMU_STA_INFO *prTxBfPfmuStaInfo, u_int8_t fgNeedResp); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#ifndef _lint +/* Kevin: we don't have to call following function to inspect the data + * structure. It will check automatically while at compile time. + * We'll need this for porting driver to different RTOS. + */ +static __KAL_INLINE__ void cnmMemDataTypeCheck(void) +{ +#if 0 + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, rLinkEntry) + == 0); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, rLinkEntry) + == OFFSET_OF(struct SW_RFB, rLinkEntry)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, pucBuffer) + == OFFSET_OF(struct SW_RFB, pucBuffer)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, ucBufferSource) + == OFFSET_OF(struct SW_RFB, ucBufferSource)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, pucMacHeader) + == OFFSET_OF(struct SW_RFB, pucMacHeader)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, ucMacHeaderLength) + == OFFSET_OF(struct SW_RFB, ucMacHeaderLength)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, pucPayload) + == OFFSET_OF(struct SW_RFB, pucPayload)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, u2PayloadLength) + == OFFSET_OF(struct SW_RFB, u2PayloadLength)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, prStaRec) + == OFFSET_OF(struct SW_RFB, prStaRec)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, ucNetworkTypeIndex) + == OFFSET_OF(struct SW_RFB, ucNetworkTypeIndex)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, ucTID) + == OFFSET_OF(struct SW_RFB, ucTID)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, fgIs802_11Frame) + == OFFSET_OF(struct SW_RFB, fgIs802_11Frame)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, ucControlFlag) + == OFFSET_OF(struct SW_RFB, ucControlFlag)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, rArrivalTime) + == OFFSET_OF(struct SW_RFB, rArrivalTime)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, ucTC) + == OFFSET_OF(struct SW_RFB, ucTC)); + +#if CFG_PROFILE_BUFFER_TRACING + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, eActivity[0]) + == OFFSET_OF(struct SW_RFB, eActivity[0])); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, rActivityTime[0]) + == OFFSET_OF(struct SW_RFB, rActivityTime[0])); +#endif + +#if DBG && CFG_BUFFER_FREE_CHK + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct MSDU_INFO, fgBufferInSource) + == OFFSET_OF(struct SW_RFB, fgBufferInSource)); +#endif + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF( + struct STA_RECORD, rLinkEntry) + == 0); + + return; +#endif +} +#endif /* _lint */ + +#endif /* _CNM_MEM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/cnm_scan.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/cnm_scan.h new file mode 100644 index 0000000000000..46babe311422c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/cnm_scan.h @@ -0,0 +1,164 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: @(#) + */ + +/*! \file "cnm_scan.h" + * \brief + * + */ + + +#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 + +/* Used by partial scan */ +#define SCN_INTERLACED_CHANNEL_GROUPS_NUM 3 + +#define SCN_PARTIAL_SCAN_NUM 3 + +#define SCN_PARTIAL_SCAN_IDLE_MSEC 100 + +#define SCN_P2P_FULL_SCAN_PARAM 0 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +/* The type of Scan Source */ +enum ENUM_SCN_REQ_SOURCE { + 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 ENUM_SCAN_PROFILE { + SCAN_PROFILE_FULL = 0, + SCAN_PROFILE_PARTIAL, + SCAN_PROFILE_VOIP, + SCAN_PROFILE_FULL_2G4, + SCAN_PROFILE_NUM +}; + +/******************************************************************************* + * P U B 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 struct MSG_HDR *prMsgHdr); + +u_int8_t cnmScanRunEventScanAbort(IN struct MSG_HDR *prMsgHdr); + +void cnmScanProfileSelection(void); + +void cnmScanProcessStart(void); + +void cnmScanProcessStop(void); + +void cnmScanRunEventReqAISAbsDone(IN struct MSG_HDR *prMsgHdr); + +void cnmScanRunEventCancelAISAbsDone(IN struct MSG_HDR *prMsgHdr); + +void cnmScanPartialScanTimeout(uint32_t u4Param); + +void cnmScanRunEventScnFsmComplete(IN struct MSG_HDR *prMsgHdr); +#endif + +#endif /* _CNM_SCAN_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/cnm_timer.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/cnm_timer.h new file mode 100644 index 0000000000000..dab829534ccbb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/cnm_timer.h @@ -0,0 +1,260 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + + +#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 +#undef USEC_PER_SEC +#define USEC_PER_SEC 1000000 + +#define USEC_PER_TU 1024 /* microsecond */ + +#define MSEC_PER_MIN (60 * MSEC_PER_SEC) + +#define MGMT_MAX_TIMEOUT_INTERVAL ((uint32_t)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 + +enum ENUM_TIMER_WAKELOCK_TYPE_T { + TIMER_WAKELOCK_AUTO, + TIMER_WAKELOCK_NONE, + TIMER_WAKELOCK_REQUEST, + TIMER_WAKELOCK_NUM +}; + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +typedef void(*PFN_MGMT_TIMEOUT_FUNC) (struct ADAPTER *, unsigned long); + +struct TIMER { + struct LINK_ENTRY rLinkEntry; + OS_SYSTIME rExpiredSysTime; + uint16_t u2Minutes; + uint16_t u2Reserved; + unsigned long ulDataPtr; + PFN_MGMT_TIMEOUT_FUNC pfMgmtTimeOutFunc; + enum ENUM_TIMER_WAKELOCK_TYPE_T eType; +}; + +/******************************************************************************* + * P U B 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) \ + ((uint32_t)((uint32_t)(a) - (uint32_t)(b)) > 0x7fffffff) + +/* #define TIME_BEFORE(a,b) ((int32_t)((int32_t)(b) - (int32_t)(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) ((uint32_t)(_sec) * MSEC_PER_SEC) +#define SEC_TO_USEC(_sec) ((uint32_t)(_sec) * USEC_PER_SEC) + +/* The macros to convert millisecond & microsecond */ +#define USEC_TO_MSEC(_usec) ((_usec) / USEC_PER_MSEC) +#define MSEC_TO_USEC(_msec) ((uint32_t)(_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) * USEC_PER_SEC) / KAL_HZ) + +/* 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) \ + (((uint32_t)(_currentTime) - (uint32_t)(_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), (uint32_t)(_callbackFunc)) + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +void cnmTimerInitialize(IN struct ADAPTER *prAdapter); + +void cnmTimerDestroy(IN struct ADAPTER *prAdapter); + +void cnmTimerInitTimerOption(IN struct ADAPTER *prAdapter, + IN struct TIMER *prTimer, + IN PFN_MGMT_TIMEOUT_FUNC pfFunc, + IN unsigned long ulDataPtr, + IN enum ENUM_TIMER_WAKELOCK_TYPE_T eType); + +void cnmTimerStopTimer(IN struct ADAPTER *prAdapter, IN struct TIMER *prTimer); + +void cnmTimerStartTimer(IN struct ADAPTER *prAdapter, IN struct TIMER *prTimer, + IN uint32_t u4TimeoutMs); + +void cnmTimerDoTimeOutCheck(IN struct ADAPTER *prAdapter); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +static __KAL_INLINE__ int32_t timerPendingTimer(IN struct TIMER *prTimer) +{ + ASSERT(prTimer); + + return prTimer->rLinkEntry.prNext != NULL; +} + +static __KAL_INLINE__ void cnmTimerInitTimer(IN struct ADAPTER *prAdapter, + IN struct TIMER *prTimer, + IN PFN_MGMT_TIMEOUT_FUNC pfFunc, + IN unsigned long ulDataPtr) +{ + cnmTimerInitTimerOption(prAdapter, prTimer, pfFunc, ulDataPtr, + TIMER_WAKELOCK_AUTO); +} + + +#endif /* _CNM_TIMER_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/hem_mbox.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/hem_mbox.h new file mode 100644 index 0000000000000..a52f01382b90d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/hem_mbox.h @@ -0,0 +1,366 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: include/mgmt/hem_mbox.h + */ + +/*! \file hem_mbox.h + * \brief + * + */ + +#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 */ +enum ENUM_MSG_ID { + /* MANY notify CNM to obtain channel privilege */ + MID_MNY_CNM_CH_REQ, + /* MANY notify CNM to abort/release channel privilege */ + MID_MNY_CNM_CH_ABORT, + + /* CNM notify AIS for indicating channel granted */ + MID_CNM_AIS_CH_GRANT, + /* CNM notify P2P for indicating channel granted */ + MID_CNM_P2P_CH_GRANT, + /* CNM notify BOW for indicating channel granted */ + MID_CNM_BOW_CH_GRANT, + +#if (CFG_SUPPORT_DFS_MASTER == 1) + MID_CNM_P2P_RADAR_DETECT, + MID_CNM_P2P_CSA_DONE, +#endif + /*--------------------------------------------------*/ + /* SCN Module Mailbox Messages */ + /*--------------------------------------------------*/ + /* AIS notify SCN for starting scan */ + MID_AIS_SCN_SCAN_REQ, + /* AIS notify SCN for starting scan with multiple SSID support */ + MID_AIS_SCN_SCAN_REQ_V2, + /* AIS notify SCN for cancelling scan */ + MID_AIS_SCN_SCAN_CANCEL, + /* P2P notify SCN for starting scan */ + MID_P2P_SCN_SCAN_REQ, + /* P2P notify SCN for starting scan with multiple SSID support */ + MID_P2P_SCN_SCAN_REQ_V2, + /* P2P notify SCN for cancelling scan */ + MID_P2P_SCN_SCAN_CANCEL, + /* BOW notify SCN for starting scan */ + MID_BOW_SCN_SCAN_REQ, + /* BOW notify SCN for starting scan with multiple SSID support */ + MID_BOW_SCN_SCAN_REQ_V2, + /* BOW notify SCN for cancelling scan */ + MID_BOW_SCN_SCAN_CANCEL, + /* RLM notify SCN for starting scan (OBSS-SCAN) */ + MID_RLM_SCN_SCAN_REQ, + /* RLM notify SCN for starting scan (OBSS-SCAN) + * with multiple SSID support + */ + MID_RLM_SCN_SCAN_REQ_V2, + /* RLM notify SCN for cancelling scan (OBSS-SCAN) */ + MID_RLM_SCN_SCAN_CANCEL, + /* SCN notify AIS for scan completion */ + MID_SCN_AIS_SCAN_DONE, + /* SCN notify P2P for scan completion */ + MID_SCN_P2P_SCAN_DONE, + /* SCN notify BOW for scan completion */ + MID_SCN_BOW_SCAN_DONE, + /* SCN notify RLM for scan completion (OBSS-SCAN) */ + MID_SCN_RLM_SCAN_DONE, + + /*--------------------------------------------------*/ + /* AIS Module Mailbox Messages */ + /*--------------------------------------------------*/ + /* OID/IOCTL notify AIS for join */ + MID_OID_AIS_FSM_JOIN_REQ, + /* OID/IOCTL notify AIS for abort */ + MID_OID_AIS_FSM_ABORT, + /* AIS notify SAA for Starting authentication/association fsm */ + MID_AIS_SAA_FSM_START, + /* OID notify SAA to continue to do authentication/association fsm for + ** FT + */ + MID_OID_SAA_FSM_CONTINUE, + /* AIS notify SAA for Aborting authentication/association fsm */ + MID_AIS_SAA_FSM_ABORT, + /* SAA notify AIS for indicating join complete */ + MID_SAA_AIS_JOIN_COMPLETE, + +#if CFG_ENABLE_BT_OVER_WIFI + /*--------------------------------------------------*/ + /* BOW Module Mailbox Messages */ + /*--------------------------------------------------*/ + /* BOW notify SAA for Starting authentication/association fsm */ + MID_BOW_SAA_FSM_START, + /* BOW notify SAA for Aborting authentication/association fsm */ + MID_BOW_SAA_FSM_ABORT, + /* SAA notify BOW for indicating join complete */ + MID_SAA_BOW_JOIN_COMPLETE, +#endif + +#if CFG_ENABLE_WIFI_DIRECT + /*--------------------------------------------------*/ + /* P2P Module Mailbox Messages */ + /*--------------------------------------------------*/ + /* P2P notify SAA for Starting authentication/association fsm */ + MID_P2P_SAA_FSM_START, + /* P2P notify SAA for Aborting authentication/association fsm */ + MID_P2P_SAA_FSM_ABORT, + /* SAA notify P2P for indicating join complete */ + MID_SAA_P2P_JOIN_COMPLETE, + + MID_MNY_P2P_FUN_SWITCH, /* Enable P2P FSM. */ + /* Start device discovery. */ + MID_MNY_P2P_DEVICE_DISCOVERY, + /* Connection request. */ + MID_MNY_P2P_CONNECTION_REQ, + /* Abort connection request, P2P FSM return to IDLE. */ + MID_MNY_P2P_CONNECTION_ABORT, + 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_DEL_IFACE, + MID_MNY_P2P_MGMT_FRAME_UPDATE, +#if (CFG_SUPPORT_DFS_MASTER == 1) + MID_MNY_P2P_DFS_CAC, + MID_MNY_P2P_SET_NEW_CHANNEL, +#endif +#if CFG_SUPPORT_WFD + MID_MNY_P2P_WFD_CFG_UPDATE, +#endif + MID_MNY_P2P_ACTIVE_BSS, +#endif + +#if CFG_SUPPORT_ADHOC + /* SCN notify AIS that an IBSS Peer has been found + * and can merge into + */ + MID_SCN_AIS_FOUND_IBSS, +#endif /* CFG_SUPPORT_ADHOC */ + + /* SAA notify AIS for indicating deauthentication/disassociation */ + MID_SAA_AIS_FSM_ABORT, + + /*--------------------------------------------------*/ + /* AIS MGMT-TX Support */ + /*--------------------------------------------------*/ + MID_MNY_AIS_REMAIN_ON_CHANNEL, + MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL, + MID_MNY_AIS_MGMT_TX, + MID_WNM_AIS_BSS_TRANSITION, + MID_OID_WMM_TSPEC_OPERATE, + MID_RLM_RM_SCHEDULE, +#if CFG_SUPPORT_NCHO + MID_MNY_AIS_NCHO_ACTION_FRAME, +#endif + MID_TOTAL_NUM +}; + +/* Message header of inter-components */ +struct MSG_HDR { + struct LINK_ENTRY rLinkEntry; + enum ENUM_MSG_ID eMsgId; +}; + +typedef void(*PFN_MSG_HNDL_FUNC) (struct ADAPTER *, + struct MSG_HDR *); + +struct MSG_HNDL_ENTRY { + enum ENUM_MSG_ID eMsgId; + PFN_MSG_HNDL_FUNC pfMsgHndl; +}; + +enum EUNM_MSG_SEND_METHOD { + /* Message is put in the queue and will be */ + MSG_SEND_METHOD_BUF = 0, + /*executed when mailbox is checked. */ + /* The handler function is called immediately */ + MSG_SEND_METHOD_UNBUF + /* in the same context of the sender */ +}; + +enum ENUM_MBOX_ID { + MBOX_ID_0 = 0, + MBOX_ID_TOTAL_NUM +}; + +/* Define Mailbox structure */ +struct MBOX { + struct LINK rLinkHead; +}; + +struct MSG_SAA_FSM_START { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucSeqNum; + struct STA_RECORD *prStaRec; +}; + +struct MSG_SAA_FSM_COMP { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucSeqNum; + uint32_t rJoinStatus; + struct STA_RECORD *prStaRec; + struct SW_RFB *prSwRfb; +}; + +struct MSG_SAA_FSM_ABORT { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucSeqNum; + struct STA_RECORD *prStaRec; +}; + +struct MSG_CONNECTION_ABORT { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucNetTypeIndex; +}; + +struct MSG_REMAIN_ON_CHANNEL { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + enum ENUM_BAND eBand; + enum ENUM_CHNL_EXT eSco; + uint8_t ucChannelNum; + uint32_t u4DurationMs; + uint64_t u8Cookie; +}; + +struct MSG_CANCEL_REMAIN_ON_CHANNEL { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint64_t u8Cookie; +}; + +struct MSG_MGMT_TX_REQUEST { + struct MSG_HDR rMsgHdr; + struct MSDU_INFO *prMgmtMsduInfo; + uint64_t u8Cookie; /* For indication. */ + u_int8_t fgNoneCckRate; + u_int8_t fgIsWaitRsp; +}; + +struct MSG_SAA_FT_CONTINUE { + struct MSG_HDR rMsgHdr; + struct STA_RECORD *prStaRec; + /* if fgFTRicRequest is TRUE, then will do FT Resource + ** Request Protocol + */ + u_int8_t fgFTRicRequest; +}; + +/* specific message data types */ + +/******************************************************************************* + * P U B 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 struct ADAPTER *prAdapter, + IN enum ENUM_MBOX_ID eMboxId); + +void +mboxSendMsg(IN struct ADAPTER *prAdapter, + IN enum ENUM_MBOX_ID eMboxId, IN struct MSG_HDR *prMsg, + IN enum EUNM_MSG_SEND_METHOD eMethod); + +void mboxRcvAllMsg(IN struct ADAPTER *prAdapter, + IN enum ENUM_MBOX_ID eMboxId); + +void mboxInitialize(IN struct ADAPTER *prAdapter); + +void mboxDestroy(IN struct ADAPTER *prAdapter); + +void mboxDummy(IN struct ADAPTER *prAdapter, + struct MSG_HDR *prMsgHdr); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _HEM_MBOX_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/hs20.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/hs20.h new file mode 100644 index 0000000000000..bbc8c86ff1075 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/hs20.h @@ -0,0 +1,205 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/*! \file hs20.h + * \brief This file contains the function declaration for hs20.c. + */ + +#ifndef _HS20_H +#define _HS20_H + +#if CFG_SUPPORT_PASSPOINT +/****************************************************************************** + * C O M P I L E R F L A G S + ****************************************************************************** + */ + +/****************************************************************************** + * E X T E R N A L R E F E R E N C E S + ****************************************************************************** + */ + +/****************************************************************************** + * C O N S T A N T S + ****************************************************************************** + */ +#define BSSID_POOL_MAX_SIZE 8 +#define HS20_SIGMA_SCAN_RESULT_TIMEOUT 30 /* sec */ + +/****************************************************************************** + * D A T A T Y P E S + ****************************************************************************** + */ + +#if CFG_ENABLE_GTK_FRAME_FILTER +/*For GTK Frame Filter*/ +struct IPV4_NETWORK_ADDRESS_LIST { + uint8_t ucAddrCount; + struct IPV4_NETWORK_ADDRESS arNetAddr[1]; +}; +#endif + +/* Entry of BSSID Pool - For SIGMA Test */ +struct BSSID_ENTRY { + uint8_t aucBSSID[MAC_ADDR_LEN]; +}; + +struct HS20_INFO { + /*Hotspot 2.0 Information */ + uint8_t aucHESSID[MAC_ADDR_LEN]; + uint8_t ucAccessNetworkOptions; + uint8_t ucVenueGroup; /* VenueInfo - Group */ + uint8_t ucVenueType; + uint8_t ucHotspotConfig; + + /*Roaming Consortium Information */ + /* PARAM_HS20_ROAMING_CONSORTIUM_INFO rRCInfo; */ + + /*Hotspot 2.0 dummy AP Info */ + + /*Time Advertisement Information */ + /* UINT_32 u4UTCOffsetTime; */ + /* UINT_8 aucTimeZone[ELEM_MAX_LEN_TIME_ZONE]; */ + /* UINT_8 ucLenTimeZone; */ + + /* For SIGMA Test */ + /* BSSID Pool */ + struct BSSID_ENTRY arBssidPool[BSSID_POOL_MAX_SIZE]; + uint8_t ucNumBssidPoolEntry; + u_int8_t fgIsHS2SigmaMode; +}; + +/****************************************************************************** + * P U B L I C D A T A + ****************************************************************************** + */ + +/****************************************************************************** + * P R I V A T E D A T A + ****************************************************************************** + */ + +/****************************************************************************** + * M A C R O S + ****************************************************************************** + */ + +/*For GTK Frame Filter*/ +#if DBG +#define FREE_IPV4_NETWORK_ADDR_LIST(_prAddrList) \ + { \ + uint32_t u4Size = \ + OFFSET_OF(struct IPV4_NETWORK_ADDRESS_LIST, \ + arNetAddr) + \ + (((_prAddrList)->ucAddrCount) * \ + sizeof(struct IPV4_NETWORK_ADDRESS)); \ + kalMemFree((_prAddrList), VIR_MEM_TYPE, u4Size); \ + (_prAddrList) = NULL; \ + } +#else +#define FREE_IPV4_NETWORK_ADDR_LIST(_prAddrList) \ + { \ + kalMemFree((_prAddrList), VIR_MEM_TYPE, 0); \ + (_prAddrList) = NULL; \ + } +#endif + +/****************************************************************************** + * F U N C T I O N S + ****************************************************************************** + */ + +void hs20GenerateInterworkingIE(IN struct ADAPTER *prAdapter, + OUT struct MSDU_INFO *prMsduInfo); + +void hs20GenerateRoamingConsortiumIE(IN struct ADAPTER *prAdapter, + OUT struct MSDU_INFO *prMsduInfo); + +void hs20GenerateHS20IE(IN struct ADAPTER *prAdapter, + OUT struct MSDU_INFO *prMsduInfo); + +void hs20FillExtCapIE(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, struct MSDU_INFO *prMsduInfo); + +void hs20FillProreqExtCapIE(IN struct ADAPTER *prAdapter, OUT uint8_t *pucIE); + +void hs20FillHS20IE(IN struct ADAPTER *prAdapter, OUT uint8_t *pucIE); + +uint32_t hs20CalculateHS20RelatedIEForProbeReq(IN struct ADAPTER *prAdapter, + IN uint8_t *pucTargetBSSID); + +uint32_t hs20GenerateHS20RelatedIEForProbeReq(IN struct ADAPTER *prAdapter, + IN uint8_t *pucTargetBSSID, OUT uint8_t *prIE); + +u_int8_t hs20IsGratuitousArp(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prCurrSwRfb); + +u_int8_t hs20IsUnsolicitedNeighborAdv(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prCurrSwRfb); + +#if CFG_ENABLE_GTK_FRAME_FILTER +u_int8_t hs20IsForgedGTKFrame(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, IN struct SW_RFB *prCurrSwRfb); +#endif + +u_int8_t hs20IsUnsecuredFrame(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, IN struct SW_RFB *prCurrSwRfb); + +u_int8_t hs20IsFrameFilterEnabled(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo); + +uint32_t hs20SetBssidPool(IN struct ADAPTER *prAdapter, + IN void *pvBuffer, + IN enum ENUM_KAL_NETWORK_TYPE_INDEX eNetTypeIdx); + +#endif /* CFG_SUPPORT_PASSPOINT */ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/mib.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/mib.h new file mode 100644 index 0000000000000..9c7b5513fc58e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/mib.h @@ -0,0 +1,189 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + + +#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 + */ +struct DOT11_AUTHENTICATION_ALGORITHMS_ENTRY { + /* dot11AuthenticationAlgorithmsEntry 3 */ + u_int8_t dot11AuthenticationAlgorithmsEnable; +}; + +/* Entry in SMT dot11RSNAConfigPairwiseCiphersTalbe Table: + * dot11RSNAConfigPairwiseCiphersEntry + */ +struct DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY { + /* dot11RSNAConfigPairwiseCiphersEntry 2 */ + uint32_t dot11RSNAConfigPairwiseCipher; + /* dot11RSNAConfigPairwiseCiphersEntry 3 */ + u_int8_t dot11RSNAConfigPairwiseCipherEnabled; +}; + +/* Entry in SMT dot11RSNAConfigAuthenticationSuitesTalbe Table: + * dot11RSNAConfigAuthenticationSuitesEntry + */ +struct DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY { + /* dot11RSNAConfigAuthenticationSuitesEntry 2 */ + uint32_t dot11RSNAConfigAuthenticationSuite; + /* dot11RSNAConfigAuthenticationSuitesEntry 3 */ + u_int8_t dot11RSNAConfigAuthenticationSuiteEnabled; +}; + +/* ----- IEEE 802.11 MIB Major sections ----- */ +struct IEEE_802_11_MIB { + /* dot11PrivacyTable (dot11smt 5) */ + uint8_t dot11WEPDefaultKeyID; /* dot11PrivacyEntry 2 */ + u_int8_t dot11TranmitKeyAvailable; + uint32_t dot11WEPICVErrorCount; /* dot11PrivacyEntry 5 */ + uint32_t dot11WEPExcludedCount; /* dot11PrivacyEntry 6 */ + + /* dot11RSNAConfigTable (dot11smt 8) */ + uint32_t dot11RSNAConfigGroupCipher; /* dot11RSNAConfigEntry 4 */ + + /* dot11RSNAConfigPairwiseCiphersTable (dot11smt 9) */ + struct DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY + dot11RSNAConfigPairwiseCiphersTable[MAX_NUM_SUPPORTED_CIPHER_SUITES]; + + /* dot11RSNAConfigAuthenticationSuitesTable (dot11smt 10) */ + struct DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY + dot11RSNAConfigAuthenticationSuitesTable[MAX_NUM_SUPPORTED_AKM_SUITES]; + +#if 0 /* SUPPORT_WAPI */ + u_int8_t fgWapiKeyInstalled; + struct PARAM_WPI_KEY rWapiPairwiseKey[2]; + u_int8_t fgPairwiseKeyUsed[2]; + uint8_t ucWpiActivedPWKey; /* Must be 0 or 1, by wapi spec */ + struct PARAM_WPI_KEY rWapiGroupKey[2]; + u_int8_t fgGroupKeyUsed[2]; +#endif +}; + +/* ------------------ IEEE 802.11 non HT PHY characteristics ---------------- */ +struct NON_HT_PHY_ATTRIBUTE { + uint16_t u2SupportedRateSet; + + u_int8_t fgIsShortPreambleOptionImplemented; + + u_int8_t fgIsShortSlotTimeOptionImplemented; +}; + +struct NON_HT_ATTRIBUTE { + enum ENUM_PHY_TYPE_INDEX ePhyTypeIndex; + + uint16_t u2BSSBasicRateSet; +}; + + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +extern const struct NON_HT_PHY_ATTRIBUTE + rNonHTPhyAttributes[]; +extern const struct NON_HT_ATTRIBUTE + rNonHTAdHocModeAttributes[]; +extern const struct NON_HT_ATTRIBUTE + rNonHTApModeAttributes[]; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _MIB_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_assoc.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_assoc.h new file mode 100644 index 0000000000000..da5c3286538bd --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_assoc.h @@ -0,0 +1,104 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/*! \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 + ****************************************************************************** + */ + +uint8_t *p2pBuildReAssocReqFrameCommonIEs(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN uint8_t *pucBuffer); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_bss.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_bss.h new file mode 100644 index 0000000000000..75704fc7d9266 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_bss.h @@ -0,0 +1,109 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 + ****************************************************************************** + */ + +uint32_t p2pGetTxProbRspIeTableSize(void); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_dev.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_dev.h new file mode 100644 index 0000000000000..5687bb3039cbb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_dev.h @@ -0,0 +1,268 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +enum ENUM_P2P_DEV_STATE { + P2P_DEV_STATE_IDLE = 0, + P2P_DEV_STATE_SCAN, + P2P_DEV_STATE_REQING_CHANNEL, + P2P_DEV_STATE_CHNL_ON_HAND, + P2P_DEV_STATE_OFF_CHNL_TX, + /* Requesting Channel to Send Specific Frame. */ + P2P_DEV_STATE_NUM +}; + +/*-------------------- EVENT MESSAGE ---------------------*/ +struct MSG_P2P_SCAN_REQUEST { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucBssIdx; + enum ENUM_SCAN_TYPE eScanType; + struct P2P_SSID_STRUCT *prSSID; + int32_t i4SsidNum; + uint32_t u4NumChannel; + uint8_t *pucIEBuf; + uint32_t u4IELen; + u_int8_t fgIsAbort; + struct RF_CHANNEL_INFO arChannelListInfo[1]; +}; + +struct MSG_P2P_CHNL_REQUEST { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint64_t u8Cookie; + uint32_t u4Duration; + enum ENUM_CHNL_EXT eChnlSco; + struct RF_CHANNEL_INFO rChannelInfo; + enum ENUM_CH_REQ_TYPE eChnlReqType; +}; + +struct MSG_P2P_MGMT_TX_REQUEST { + struct MSG_HDR rMsgHdr; + uint8_t ucBssIdx; + struct MSDU_INFO *prMgmtMsduInfo; + uint64_t u8Cookie; /* For indication. */ + u_int8_t fgNoneCckRate; + u_int8_t fgIsOffChannel; + struct RF_CHANNEL_INFO rChannelInfo; /* Off channel TX. */ + enum ENUM_CHNL_EXT eChnlExt; + u_int8_t fgIsWaitRsp; +}; + +#define P2P_DEV_EXTEND_CHAN_TIME 500 + +#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 { + uint32_t u4WfdCmdType; + uint8_t ucWfdEnable; + uint8_t ucWfdCoupleSinkStatus; + uint8_t ucWfdSessionAvailable; /* 0: NA 1:Set 2:Clear */ + uint8_t ucWfdSigmaMode; + uint16_t u2WfdDevInfo; + uint16_t u2WfdControlPort; + uint16_t u2WfdMaximumTp; + uint16_t u2WfdExtendCap; + uint8_t aucWfdCoupleSinkAddress[MAC_ADDR_LEN]; + uint8_t aucWfdAssociatedBssid[MAC_ADDR_LEN]; + uint8_t aucWfdVideoIp[4]; + uint8_t aucWfdAudioIp[4]; + uint16_t u2WfdVideoPort; + uint16_t u2WfdAudioPort; + uint32_t u4WfdFlag; + uint32_t u4WfdPolicy; + uint32_t u4WfdState; + uint8_t aucWfdSessionInformationIE[24 * 8]; + uint16_t u2WfdSessionInformationIELen; + uint8_t aucReserved1[2]; + uint8_t aucWfdPrimarySinkMac[MAC_ADDR_LEN]; + uint8_t aucWfdSecondarySinkMac[MAC_ADDR_LEN]; + uint32_t u4WfdAdvancedFlag; + /* Group 1 64 bytes */ + uint8_t aucWfdLocalIp[4]; + uint16_t u2WfdLifetimeAc2; /* Unit is 2 TU */ + uint16_t u2WfdLifetimeAc3; /* Unit is 2 TU */ + uint16_t u2WfdCounterThreshold; /* Unit is ms */ + uint8_t aucReverved2[54]; + /* Group 2 64 bytes */ + uint8_t aucReverved3[64]; + /* Group 3 64 bytes */ + uint8_t aucReverved4[64]; +}; + +#endif + +struct MSG_P2P_ACTIVE_DEV_BSS { + struct MSG_HDR rMsgHdr; +}; + +/*-------------------- P2P FSM ACTION STRUCT ---------------------*/ + +struct P2P_OFF_CHNL_TX_REQ_INFO { + struct LINK_ENTRY rLinkEntry; + struct MSDU_INFO *prMgmtTxMsdu; + u_int8_t fgNoneCckRate; + struct RF_CHANNEL_INFO rChannelInfo; /* Off channel TX. */ + enum ENUM_CHNL_EXT eChnlExt; + u_int8_t fgIsWaitRsp; + /* See if driver should keep at the same channel. */ +}; + +struct P2P_MGMT_TX_REQ_INFO { + struct LINK rP2pTxReqLink; + struct MSDU_INFO *prMgmtTxMsdu; + u_int8_t fgIsWaitRsp; +}; + +struct P2P_DEV_FSM_INFO { + uint8_t ucBssIndex; + /* State related. */ + enum ENUM_P2P_DEV_STATE eCurrentState; + + /* Channel related. */ + struct P2P_CHNL_REQ_INFO rChnlReqInfo; + + /* Scan related. */ + struct P2P_SCAN_REQ_INFO rScanReqInfo; + + /* Mgmt tx related. */ + struct P2P_MGMT_TX_REQ_INFO rMgmtTxInfo; + + /* FSM Timer */ + struct TIMER rP2pFsmTimeoutTimer; + + /* Packet filter for P2P module. */ + uint32_t u4P2pPacketFilter; + + /* Queued p2p action frame */ + struct P2P_QUEUED_ACTION_FRAME rQueuedActionFrame; +}; + +struct MSG_P2P_NETDEV_REGISTER { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + u_int8_t fgIsEnable; + uint8_t ucMode; +}; + +#if CFG_SUPPORT_WFD +struct MSG_WFD_CONFIG_SETTINGS_CHANGED { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + struct WFD_CFG_SETTINGS *prWfdCfgSettings; +}; +#endif + +/*========================= Initial ============================*/ + +uint8_t p2pDevFsmInit(IN struct ADAPTER *prAdapter); + +void p2pDevFsmUninit(IN struct ADAPTER *prAdapter); + +/*========================= FUNCTIONs ============================*/ + +void +p2pDevFsmStateTransition(IN struct ADAPTER *prAdapter, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo, + IN enum ENUM_P2P_DEV_STATE eNextState); + +void p2pDevFsmRunEventAbort(IN struct ADAPTER *prAdapter, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo); + +void p2pDevFsmRunEventTimeout(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr); + +/*================ Message Event =================*/ +void p2pDevFsmRunEventScanRequest(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); +void p2pDevFsmRunEventScanAbort(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void +p2pDevFsmRunEventScanDone(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo); + +void p2pDevFsmRunEventChannelRequest(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pDevFsmRunEventChannelAbort(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void +p2pDevFsmRunEventChnlGrant(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo); + +void p2pDevFsmRunEventMgmtTx(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +uint32_t +p2pDevFsmRunEventMgmtFrameTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +void p2pDevFsmRunEventMgmtFrameRegister(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +/* /////////////////////////////// */ + +void p2pDevFsmRunEventActiveDevBss(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void +p2pDevFsmNotifyP2pRx(IN struct ADAPTER *prAdapter, uint8_t p2pFrameType, + u_int8_t *prFgBufferFrame); + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_dev_state.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_dev_state.h new file mode 100644 index 0000000000000..48f9f3bcfb02e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_dev_state.h @@ -0,0 +1,106 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#ifndef _P2P_DEV_STATE_H +#define _P2P_DEV_STATE_H + +u_int8_t +p2pDevStateInit_IDLE(IN struct ADAPTER *prAdapter, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + OUT enum ENUM_P2P_DEV_STATE *peNextState); + +void p2pDevStateAbort_IDLE(IN struct ADAPTER *prAdapter); + +u_int8_t +p2pDevStateInit_REQING_CHANNEL(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + OUT enum ENUM_P2P_DEV_STATE *peNextState); + +void +p2pDevStateAbort_REQING_CHANNEL(IN struct ADAPTER *prAdapter, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN enum ENUM_P2P_DEV_STATE eNextState); + +void +p2pDevStateInit_CHNL_ON_HAND(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo); + +void +p2pDevStateAbort_CHNL_ON_HAND(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN enum ENUM_P2P_DEV_STATE eNextState); + +void p2pDevStateInit_SCAN(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct P2P_SCAN_REQ_INFO *prScanReqInfo); + +void p2pDevStateAbort_SCAN(IN struct ADAPTER *prAdapter, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo); + +u_int8_t +p2pDevStateInit_OFF_CHNL_TX(IN struct ADAPTER *prAdapter, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN struct P2P_MGMT_TX_REQ_INFO *prP2pMgmtTxInfo, + OUT enum ENUM_P2P_DEV_STATE *peNextState); + +void +p2pDevStateAbort_OFF_CHNL_TX(IN struct ADAPTER *prAdapter, + IN struct P2P_MGMT_TX_REQ_INFO *prP2pMgmtTxInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN enum ENUM_P2P_DEV_STATE eNextState); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_fsm.h new file mode 100644 index 0000000000000..81b59f7884cc0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_fsm.h @@ -0,0 +1,87 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + + +#ifndef _P2P_FSM_H +#define _P2P_FSM_H + +void p2pFsmRunEventScanRequest(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pFsmRunEventChGrant(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pFsmRunEventNetDeviceRegister(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pFsmRunEventUpdateMgmtFrame(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +#if CFG_SUPPORT_WFD +void p2pFsmRunEventWfdSettingUpdate(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); +#endif + +void p2pFsmRunEventScanDone(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + + +#endif /* _P2P_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_func.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_func.h new file mode 100644 index 0000000000000..1dabba21271ec --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_func.h @@ -0,0 +1,427 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#ifndef _P2P_FUNC_H +#define _P2P_FUNC_H + +#define P2P_OFF_CHNL_TX_DEFAULT_TIME_MS 1000 + +#if (CFG_SUPPORT_DFS_MASTER == 1) +extern struct P2P_RADAR_INFO g_rP2pRadarInfo; + +enum _ENUM_DFS_STATE_T { + DFS_STATE_INACTIVE = 0, + DFS_STATE_CHECKING, + DFS_STATE_ACTIVE, + DFS_STATE_DETECTED, + DFS_STATE_NUM +}; +#endif + +/****************************************************************************** + * M A C R O S + ****************************************************************************** + */ +#define ATTRI_ID(_fp) (((struct P2P_ATTRIBUTE *)_fp)->ucId) +#define ATTRI_LEN(_fp) \ +(((uint16_t)((uint8_t *)&((struct P2P_ATTRIBUTE *)_fp)->u2Length)[0]) | \ +((uint16_t)((uint8_t *)&((struct P2P_ATTRIBUTE *)_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) ((struct IE_P2P *)_fp) + +#define WSC_ATTRI_ID(_fp) \ +(((uint16_t)((uint8_t *)&((struct WSC_ATTRIBUTE *)_fp)->u2Id)[0] << 8) | \ +((uint16_t)((uint8_t *)&((struct WSC_ATTRIBUTE *)_fp)->u2Id)[1])) + +#define WSC_ATTRI_LEN(_fp) \ +(((uint16_t)((uint8_t *)&((struct WSC_ATTRIBUTE *)_fp)->u2Length)[0] << 8) | \ +((uint16_t)((uint8_t *)&((struct WSC_ATTRIBUTE *)_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) ((struct IE_P2P *)_fp) + +#define WFD_ATTRI_SIZE(_fp) (P2P_ATTRI_HDR_LEN + WSC_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))) + +/****************************************************************************** + * F U N C T I O N D E C L A R A T I O N S + ****************************************************************************** + */ + +void p2pFuncRequestScan(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct P2P_SCAN_REQ_INFO *prScanReqInfo); + +void p2pFuncCancelScan(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct P2P_SCAN_REQ_INFO *prScanReqInfo); + +void +p2pFuncUpdateBssInfoForJOIN(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc, + IN struct STA_RECORD *prStaRec, + IN struct BSS_INFO *prP2pBssInfo, + IN struct SW_RFB *prAssocRspSwRfb); + +void p2pFuncAcquireCh(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo); + +void +p2pFuncDisconnect(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN struct STA_RECORD *prStaRec, + IN u_int8_t fgSendDeauth, + IN uint16_t u2ReasonCode); + +struct BSS_INFO *p2pFuncBSSIDFindBssInfo(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBSSID); + +void p2pFuncGCJoin(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN struct P2P_JOIN_INFO *prP2pJoinInfo); + +void p2pFuncStopComplete(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo); + +void +p2pFuncStartGO(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct P2P_CONNECTION_REQ_INFO *prP2pConnReqInfo, + IN struct P2P_CHNL_REQ_INFO *prP2pChnlReqInfo); + +void p2pFuncStopGO(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo); + +uint32_t p2pFuncRoleToBssIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucRoleIdx, + OUT uint8_t *pucBssIdx); + +struct P2P_ROLE_FSM_INFO *p2pFuncGetRoleByBssIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +void +p2pFuncSwitchOPMode(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN enum ENUM_OP_MODE eOpMode, + IN u_int8_t fgSyncToFW); + +void p2pFuncReleaseCh(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo); + +#if (CFG_SUPPORT_DFS_MASTER == 1) +void p2pFuncStartRdd(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIdx); + +void p2pFuncStopRdd(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIdx); + +void p2pFuncDfsSwitchCh(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct P2P_CHNL_REQ_INFO rP2pChnlReqInfo); + +u_int8_t p2pFuncCheckWeatherRadarBand( + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo); + +int32_t p2pFuncSetDriverCacTime(IN uint32_t u4CacTime); + +void p2pFuncEnableManualCac(void); + +uint32_t p2pFuncGetDriverCacTime(void); + +u_int8_t p2pFuncIsManualCac(void); + +void p2pFuncRadarInfoInit(void); + +void p2pFuncShowRadarInfo(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIdx); + +void p2pFuncGetRadarInfo(IN struct P2P_RADAR_INFO *prP2pRadarInfo); + +uint8_t *p2pFuncJpW53RadarType(void); + +uint8_t *p2pFuncJpW56RadarType(void); + +void p2pFuncSetRadarDetectMode(IN uint8_t ucRadarDetectMode); + +uint8_t p2pFuncGetRadarDetectMode(void); + +void p2pFuncSetDfsState(IN uint8_t ucDfsState); + +uint8_t p2pFuncGetDfsState(void); + +uint8_t *p2pFuncShowDfsState(void); + +void p2pFuncRecordCacStartBootTime(void); + +uint32_t p2pFuncGetCacRemainingTime(void); +#endif + +void p2pFuncSetChannel(IN struct ADAPTER *prAdapter, + IN uint8_t ucRoleIdx, + IN struct RF_CHANNEL_INFO *prRfChannelInfo); + +u_int8_t p2pFuncRetryJOIN(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct P2P_JOIN_INFO *prJoinInfo); + +uint32_t +p2pFuncTxMgmtFrame(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct MSDU_INFO *prMgmtTxMsdu, + IN u_int8_t fgNonCckRate); + +uint32_t +p2pFuncBeaconUpdate(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN struct P2P_BEACON_UPDATE_INFO *prBcnUpdateInfo, + IN uint8_t *pucNewBcnHdr, + IN uint32_t u4NewHdrLen, + IN uint8_t *pucNewBcnBody, + IN uint32_t u4NewBodyLen); + +uint32_t +p2pFuncAssocRespUpdate(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN uint8_t *AssocRespIE, + IN uint32_t u4AssocRespLen); + +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP +uint32_t +p2pFuncProbeRespUpdate(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN uint8_t *ProbeRespIE, IN uint32_t u4ProbeRespLen); +#endif + +u_int8_t +p2pFuncValidateAuth(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, IN struct SW_RFB *prSwRfb, + IN struct STA_RECORD **pprStaRec, OUT uint16_t *pu2StatusCode); + +u_int8_t p2pFuncValidateAssocReq(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, OUT uint16_t *pu2StatusCode); + +void p2pFuncResetStaRecStatus(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +void +p2pFuncInitConnectionSettings(IN struct ADAPTER *prAdapter, + IN struct P2P_CONNECTION_SETTINGS *prP2PConnSettings, + IN u_int8_t fgIsApMode); + +u_int8_t p2pFuncParseCheckForP2PInfoElem(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, OUT uint8_t *pucOuiType); + +u_int8_t p2pFuncParseCheckForTKIPInfoElem(IN uint8_t *pucBuf); + +u_int8_t +p2pFuncValidateProbeReq(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, OUT uint32_t *pu4ControlFlags, + IN u_int8_t fgIsDevInterface, IN uint8_t ucRoleIdx); + +void p2pFuncValidateRxActionFrame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN u_int8_t fgIsDevInterface, IN uint8_t ucRoleIdx); + +u_int8_t p2pFuncIsAPMode(IN struct P2P_CONNECTION_SETTINGS *prP2pConnSettings); + +void +p2pFuncParseBeaconContent(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN uint8_t *pucIEInfo, IN uint32_t u4IELen); + +struct BSS_DESC * +p2pFuncKeepOnConnection(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct P2P_CONNECTION_REQ_INFO *prConnReqInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN struct P2P_SCAN_REQ_INFO *prScanReqInfo); + +void p2pFuncStoreAssocRspIEBuffer(IN struct ADAPTER *prAdapter, + IN struct P2P_JOIN_INFO *prP2pJoinInfo, + IN struct SW_RFB *prSwRfb); + +void +p2pFuncMgmtFrameRegister(IN struct ADAPTER *prAdapter, + IN uint16_t u2FrameType, + IN u_int8_t fgIsRegistered, + OUT uint32_t *pu4P2pPacketFilter); + +void p2pFuncUpdateMgmtFrameRegister(IN struct ADAPTER *prAdapter, + IN uint32_t u4OsFilter); + +void p2pFuncGetStationInfo(IN struct ADAPTER *prAdapter, + IN uint8_t *pucMacAddr, + OUT struct P2P_STATION_INFO *prStaInfo); + +struct MSDU_INFO *p2pFuncProcessP2pProbeRsp(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, IN struct MSDU_INFO *prMgmtTxMsdu); + +#if 0 /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */ +uint32_t +p2pFuncCalculateExtra_IELenForBeacon(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN struct STA_RECORD *prStaRec); + +void p2pFuncGenerateExtra_IEForBeacon(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +#else +uint32_t p2pFuncCalculateP2p_IELenForBeacon(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN struct STA_RECORD *prStaRec); + +void p2pFuncGenerateP2p_IEForBeacon(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +uint32_t p2pFuncCalculateWSC_IELenForBeacon(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN struct STA_RECORD *prStaRec); + +void p2pFuncGenerateWSC_IEForBeacon(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); +#endif +uint32_t +p2pFuncCalculateP2p_IELenForAssocRsp(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN struct STA_RECORD *prStaRec); + +void p2pFuncGenerateP2p_IEForAssocRsp(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +uint32_t +p2pFuncCalculateP2P_IELen(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct STA_RECORD *prStaRec, + IN struct APPEND_VAR_ATTRI_ENTRY arAppendAttriTable[], + IN uint32_t u4AttriTableSize); + +void +p2pFuncGenerateP2P_IE(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN u_int8_t fgIsAssocFrame, + IN uint16_t *pu2Offset, + IN uint8_t *pucBuf, + IN uint16_t u2BufSize, + IN struct APPEND_VAR_ATTRI_ENTRY arAppendAttriTable[], + IN uint32_t u4AttriTableSize); + +uint32_t +p2pFuncAppendAttriStatusForAssocRsp(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN u_int8_t fgIsAssocFrame, + IN uint16_t *pu2Offset, + IN uint8_t *pucBuf, + IN uint16_t u2BufSize); + +uint32_t +p2pFuncAppendAttriExtListenTiming(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN u_int8_t fgIsAssocFrame, + IN uint16_t *pu2Offset, + IN uint8_t *pucBuf, + IN uint16_t u2BufSize); + +void +p2pFuncDissolve(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN u_int8_t fgSendDeauth, + IN uint16_t u2ReasonCode); + +struct IE_HDR * +p2pFuncGetSpecIE(IN struct ADAPTER *prAdapter, + IN uint8_t *pucIEBuf, + IN uint16_t u2BufferLen, + IN uint8_t ucElemID, + IN u_int8_t *pfgIsMore); + +struct P2P_ATTRIBUTE * +p2pFuncGetSpecAttri(IN struct ADAPTER *prAdapter, + IN uint8_t ucOuiType, + IN uint8_t *pucIEBuf, + IN uint16_t u2BufferLen, + IN uint8_t ucAttriID); + +uint32_t wfdFuncCalculateWfdIELenForAssocRsp(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN struct STA_RECORD *prStaRec); + +void wfdFuncGenerateWfdIEForAssocRsp(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +uint32_t p2pFuncCalculateP2P_IE_NoA(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, IN struct STA_RECORD *prStaRec); + +void p2pFuncGenerateP2P_IE_NoA(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +void p2pFunCleanQueuedMgmtFrame(IN struct ADAPTER *prAdapter, + IN struct P2P_QUEUED_ACTION_FRAME *prFrame); + +void p2pFuncClassifyAction(IN struct SW_RFB *prSwRfb); + +uint32_t p2pFunGetPreferredFreqList(IN struct ADAPTER *prAdapter, + IN enum ENUM_IFTYPE eIftype, OUT uint32_t *freq_list, + OUT uint32_t *num_freq_list); + +uint8_t p2pFuncIsBufferableMMPDU(IN struct MSDU_INFO *prMgmtTxMsdu); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_ie.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_ie.h new file mode 100644 index 0000000000000..cd287743cdd15 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_ie.h @@ -0,0 +1,102 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#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 + +/* == OFFSET_OF(IE_P2P_T,*/ +/*aucP2PAttributes[0]) */ +#define WFD_IE_OUI_HDR (ELEM_HDR_LEN + WFD_OUI_TYPE_LEN) + +/* 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 */ + +struct WFD_DEVICE_INFORMATION_IE { + uint8_t ucElemID; + uint16_t u2Length; + uint16_t u2WfdDevInfo; + uint16_t u2SessionMgmtCtrlPort; + uint16_t u2WfdDevMaxSpeed; +} __KAL_ATTRIB_PACKED__; + +#endif + +uint32_t p2pCalculate_IEForAssocReq(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN struct STA_RECORD *prStaRec); + +void p2pGenerate_IEForAssocReq(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_rlm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_rlm.h new file mode 100644 index 0000000000000..ebb91946eeceb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_rlm.h @@ -0,0 +1,136 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/*! \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 + ****************************************************************************** + */ + +#define CHANNEL_SPAN_20 20 + +/****************************************************************************** + * 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(struct ADAPTER *prAdapter, struct BSS_INFO *prBssInfo); + +u_int8_t rlmUpdateBwByChListForAP(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo); + +void rlmUpdateParamsForAP(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, u_int8_t fgUpdateBeacon); + +void rlmFuncInitialChannelList(IN struct ADAPTER *prAdapter); + +void +rlmFuncCommonChannelList(IN struct ADAPTER *prAdapter, + IN struct CHANNEL_ENTRY_FIELD *prChannelEntryII, + IN uint8_t ucChannelListSize); + +uint8_t rlmFuncFindOperatingClass(IN struct ADAPTER *prAdapter, + IN uint8_t ucChannelNum); + +u_int8_t +rlmFuncFindAvailableChannel(IN struct ADAPTER *prAdapter, + IN uint8_t ucCheckChnl, + IN uint8_t *pucSuggestChannel, + IN u_int8_t fgIsSocialChannel, IN u_int8_t fgIsDefaultChannel); + +enum ENUM_CHNL_EXT rlmDecideScoForAP(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo); + +enum ENUM_CHNL_EXT rlmGetScoForAP(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo); + +uint8_t rlmGetVhtS1ForAP(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo); + + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_rlm_obss.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_rlm_obss.h new file mode 100644 index 0000000000000..ba340c9a99c2e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_rlm_obss.h @@ -0,0 +1,118 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rlmProcessPublicAction(struct ADAPTER *prAdapter, struct SW_RFB *prSwRfb); + +void rlmHandleObssStatusEventPkt(struct ADAPTER *prAdapter, + struct EVENT_AP_OBSS_STATUS *prObssStatus); + +uint8_t rlmObssChnlLevel(struct BSS_INFO *prBssInfo, + enum ENUM_BAND eBand, uint8_t ucPriChannel, + enum ENUM_CHNL_EXT eExtend); + +void rlmObssScanExemptionRsp(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, struct SW_RFB *prSwRfb); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_role.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_role.h new file mode 100644 index 0000000000000..ce66e182914c9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_role.h @@ -0,0 +1,483 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#ifndef _P2P_ROLE_H +#define _P2P_ROLE_H + +#define P2P_ROLE_GET_STATISTICS_TIME 5000 + +enum ENUM_BUFFER_TYPE { + 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 ENUM_HIDDEN_SSID_TYPE { + ENUM_HIDDEN_SSID_NONE, + ENUM_HIDDEN_SSID_ZERO_LEN, + ENUM_HIDDEN_SSID_ZERO_CONTENT, + ENUM_HIDDEN_SSID_NUM +}; + +struct P2P_BEACON_UPDATE_INFO { + uint8_t *pucBcnHdr; + uint32_t u4BcnHdrLen; + uint8_t *pucBcnBody; + uint32_t u4BcnBodyLen; +}; + +struct P2P_PROBE_RSP_UPDATE_INFO { + struct MSDU_INFO *prProbeRspMsduTemplate; +}; + +struct P2P_ASSOC_RSP_UPDATE_INFO { + uint8_t *pucAssocRspExtIE; + uint16_t u2AssocIELen; +}; + +struct AP_CRYPTO_SETTINGS { + uint32_t u4WpaVersion; + uint32_t u4CipherGroup; + int32_t i4NumOfCiphers; + uint32_t aucCiphersPairwise[5]; + int32_t i4NumOfAkmSuites; + uint32_t aucAkmSuites[2]; + u_int8_t fgIsControlPort; + uint16_t u2ControlPortBE; + u_int8_t fgIsControlPortEncrypt; +}; + +/* ////////////////////////// Message ////////////////////////////////// */ + +struct MSG_P2P_BEACON_UPDATE { + struct MSG_HDR rMsgHdr; + uint8_t ucRoleIndex; + uint32_t u4BcnHdrLen; + uint32_t u4BcnBodyLen; + uint32_t u4AssocRespLen; +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP + uint32_t u4ProbeRespLen; +#endif + uint8_t *pucBcnHdr; + uint8_t *pucBcnBody; + uint8_t *pucAssocRespIE; +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP + uint8_t *pucProbeRespIE; +#endif + u_int8_t fgIsWepCipher; + uint8_t aucBuffer[1]; /* Header & Body & Extra IEs are put here. */ +}; + +struct MSG_P2P_MGMT_FRAME_UPDATE { + struct MSG_HDR rMsgHdr; + enum ENUM_BUFFER_TYPE eBufferType; + uint32_t u4BufferLen; + uint8_t aucBuffer[1]; +}; + +struct MSG_P2P_SWITCH_OP_MODE { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + enum ENUM_OP_MODE eOpMode; + uint8_t ucRoleIdx; + enum ENUM_IFTYPE eIftype; +}; + +struct MSG_P2P_MGMT_FRAME_REGISTER { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint16_t u2FrameType; + u_int8_t fgIsRegister; +}; + +struct MSG_P2P_CHNL_ABORT { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint64_t u8Cookie; +}; + +struct MSG_P2P_CONNECTION_REQUEST { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucRoleIdx; + struct P2P_SSID_STRUCT rSsid; + uint8_t aucBssid[MAC_ADDR_LEN]; + uint8_t aucSrcMacAddr[MAC_ADDR_LEN]; + enum ENUM_CHNL_EXT eChnlSco; + struct RF_CHANNEL_INFO rChannelInfo; + uint32_t u4IELen; + uint8_t aucIEBuf[1]; + /* TODO: Auth Type, OPEN, SHARED, FT, EAP... */ +}; + +struct MSG_P2P_CONNECTION_ABORT { + struct MSG_HDR rMsgHdr; /* Must be the first member. */ + uint8_t ucRoleIdx; + uint8_t aucTargetID[MAC_ADDR_LEN]; + uint16_t u2ReasonCode; + u_int8_t fgSendDeauth; +}; + +struct MSG_P2P_START_AP { + struct MSG_HDR rMsgHdr; + uint32_t u4DtimPeriod; + uint32_t u4BcnInterval; + uint8_t aucSsid[32]; + uint16_t u2SsidLen; + uint8_t ucHiddenSsidType; + u_int8_t fgIsPrivacy; + uint8_t ucRoleIdx; + struct AP_CRYPTO_SETTINGS rEncryptionSettings; + int32_t i4InactiveTimeout; +}; + +#if (CFG_SUPPORT_DFS_MASTER == 1) +struct MSG_P2P_DFS_CAC { + struct MSG_HDR rMsgHdr; + enum ENUM_CHANNEL_WIDTH eChannelWidth; + uint8_t ucRoleIdx; +}; + +struct MSG_P2P_RADAR_DETECT { + struct MSG_HDR rMsgHdr; + uint8_t ucBssIndex; +}; + +struct P2P_RADAR_INFO { + uint8_t ucRadarReportMode; + /*0: Only report radar detected; 1: Add parameter reports*/ + uint8_t ucRddIdx; + uint8_t ucLongDetected; + uint8_t ucPeriodicDetected; + uint8_t ucLPBNum; + uint8_t ucPPBNum; + uint8_t ucLPBPeriodValid; + uint8_t ucLPBWidthValid; + uint8_t ucPRICountM1; + uint8_t ucPRICountM1TH; + uint8_t ucPRICountM2; + uint8_t ucPRICountM2TH; + uint32_t u4PRI1stUs; + struct LONG_PULSE_BUFFER arLpbContent[LPB_SIZE]; + struct PERIODIC_PULSE_BUFFER arPpbContent[PPB_SIZE]; +}; + +struct MSG_P2P_SET_NEW_CHANNEL { + struct MSG_HDR rMsgHdr; + enum ENUM_CHANNEL_WIDTH eChannelWidth; + uint8_t ucRoleIdx; + uint8_t ucBssIndex; +}; + +struct MSG_P2P_CSA_DONE { + struct MSG_HDR rMsgHdr; + uint8_t ucBssIndex; +}; +#endif + +struct MSG_P2P_DEL_IFACE { + struct MSG_HDR rMsgHdr; + uint8_t ucRoleIdx; +}; + +struct P2P_STATION_INFO { + uint32_t u4InactiveTime; + uint32_t u4RxBytes; /* TODO: */ + uint32_t u4TxBytes; /* TODO: */ + uint32_t u4RxPackets; /* TODO: */ + uint32_t u4TxPackets; /* TODO: */ + /* TODO: Add more for requirement. */ +}; + +/* 3 --------------- WFA P2P Attributes Handler prototype --------------- */ +typedef uint32_t(*PFN_APPEND_ATTRI_FUNC) (struct ADAPTER *, + uint8_t, u_int8_t, uint16_t *, uint8_t *, uint16_t); + +typedef uint32_t(*PFN_CALCULATE_VAR_ATTRI_LEN_FUNC) (struct ADAPTER *, + struct STA_RECORD *); + +struct APPEND_VAR_ATTRI_ENTRY { + uint16_t u2EstimatedFixedAttriLen; /* For fixed length */ + PFN_CALCULATE_VAR_ATTRI_LEN_FUNC pfnCalculateVariableAttriLen; + PFN_APPEND_ATTRI_FUNC pfnAppendAttri; +}; + +/* //////////////////////////////////////////////////////////////// */ + +enum ENUM_P2P_ROLE_STATE { + P2P_ROLE_STATE_IDLE = 0, + P2P_ROLE_STATE_SCAN, + P2P_ROLE_STATE_REQING_CHANNEL, + P2P_ROLE_STATE_AP_CHNL_DETECTION, + /* Requesting Channel to Send Specific Frame. */ + P2P_ROLE_STATE_GC_JOIN, +#if (CFG_SUPPORT_DFS_MASTER == 1) + P2P_ROLE_STATE_DFS_CAC, + P2P_ROLE_STATE_SWITCH_CHANNEL, +#endif + P2P_ROLE_STATE_NUM +}; + +enum ENUM_P2P_CONNECTION_TYPE { + P2P_CONNECTION_TYPE_IDLE = 0, + P2P_CONNECTION_TYPE_GO, + P2P_CONNECTION_TYPE_GC, + P2P_CONNECTION_TYPE_PURE_AP, + P2P_CONNECTION_TYPE_NUM +}; + +struct P2P_JOIN_INFO { + uint8_t ucSeqNumOfReqMsg; + uint8_t ucAvailableAuthTypes; + struct STA_RECORD *prTargetStaRec; + struct BSS_DESC *prTargetBssDesc; + u_int8_t fgIsJoinComplete; + /* For ASSOC Rsp. */ + uint32_t u4BufLength; + uint8_t aucIEBuf[MAX_IE_LENGTH]; +}; + +/* For STA & AP mode. */ +struct P2P_CONNECTION_REQ_INFO { + enum ENUM_P2P_CONNECTION_TYPE eConnRequest; + struct P2P_SSID_STRUCT rSsidStruct; + uint8_t aucBssid[MAC_ADDR_LEN]; + + /* AP preferred channel. */ + struct RF_CHANNEL_INFO rChannelInfo; + enum ENUM_CHNL_EXT eChnlExt; + + /* To record channel bandwidth from CFG80211 */ + enum ENUM_MAX_BANDWIDTH_SETTING eChnlBw; + + /* To record primary channel frequency (MHz) from CFG80211 */ + uint16_t u2PriChnlFreq; + + /* To record Channel Center Frequency Segment 0 (MHz) from CFG80211 */ + uint32_t u4CenterFreq1; + + /* To record Channel Center Frequency Segment 1 (MHz) from CFG80211 */ + uint32_t u4CenterFreq2; + + /* For ASSOC Req. */ + uint32_t u4BufLength; + uint8_t aucIEBuf[MAX_IE_LENGTH]; +}; + +#define P2P_ROLE_INDEX_2_ROLE_FSM_INFO(_prAdapter, _RoleIndex) \ + ((_prAdapter)->rWifiVar.aprP2pRoleFsmInfo[_RoleIndex]) + +struct P2P_ROLE_FSM_INFO { + uint8_t ucRoleIndex; + + uint8_t ucBssIndex; + + /* State related. */ + enum ENUM_P2P_ROLE_STATE eCurrentState; + + /* Channel related. */ + struct P2P_CHNL_REQ_INFO rChnlReqInfo; + + /* Scan related. */ + struct P2P_SCAN_REQ_INFO rScanReqInfo; + + /* FSM Timer */ + struct TIMER rP2pRoleFsmTimeoutTimer; + +#if CFG_ENABLE_PER_STA_STATISTICS_LOG + /* Get statistics Timer */ + struct TIMER rP2pRoleFsmGetStatisticsTimer; +#endif + +#if (CFG_SUPPORT_DFS_MASTER == 1) + struct TIMER rDfsShutDownTimer; +#endif + + /* Packet filter for P2P module. */ + uint32_t u4P2pPacketFilter; + + /* GC Join related. */ + struct P2P_JOIN_INFO rJoinInfo; + + /* Connection related. */ + struct P2P_CONNECTION_REQ_INFO rConnReqInfo; + + /* Beacon Information. */ + struct P2P_BEACON_UPDATE_INFO rBeaconUpdateInfo; +}; + +/*========================= Initial ============================*/ + +uint8_t p2pRoleFsmInit(IN struct ADAPTER *prAdapter, IN uint8_t ucRoleIdx); + +void p2pRoleFsmUninit(IN struct ADAPTER *prAdapter, IN uint8_t ucRoleIdx); + +/*================== Message Event ==================*/ + +void p2pRoleFsmRunEventAbort(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo); + +void p2pRoleFsmRunEventStartAP(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pRoleFsmRunEventDelIface(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pRoleFsmRunEventStopAP(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +#if (CFG_SUPPORT_DFS_MASTER == 1) +void p2pRoleFsmRunEventDfsCac(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pRoleFsmRunEventRadarDet(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pRoleFsmRunEventSetNewChannel(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pRoleFsmRunEventCsaDone(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pRoleFsmRunEventDfsShutDownTimeout(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr); +#endif + +void p2pRoleFsmRunEventScanRequest(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void +p2pRoleFsmRunEventScanDone(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo); + +void p2pRoleFsmRunEventJoinComplete(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pRoleFsmRunEventTimeout(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr); + +void p2pRoleFsmDeauthTimeout(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr); + +void p2pRoleFsmRunEventBeaconTimeout(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo); + +void p2pRoleUpdateACLEntry(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx); + +u_int8_t p2pRoleProcessACLInspection(IN struct ADAPTER *prAdapter, + IN uint8_t *pMacAddr, IN uint8_t ucBssIdx); + +uint32_t +p2pRoleFsmRunEventAAAComplete(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct BSS_INFO *prP2pBssInfo); + +uint32_t +p2pRoleFsmRunEventAAASuccess(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct BSS_INFO *prP2pBssInfo); + +void p2pRoleFsmRunEventAAATxFail(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct BSS_INFO *prP2pBssInfo); + +void p2pRoleFsmRunEventConnectionRequest(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pRoleFsmRunEventConnectionAbort(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void +p2pRoleFsmRunEventChnlGrant(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo); + +uint32_t +p2pRoleFsmRunEventDeauthTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +void p2pRoleFsmRunEventRxDeauthentication(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, IN struct SW_RFB *prSwRfb); + +void p2pRoleFsmRunEventRxDisassociation(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, IN struct SW_RFB *prSwRfb); + +/* //////////////////////// TO BE REFINE ///////////////////// */ +void p2pRoleFsmRunEventSwitchOPMode(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pRoleFsmRunEventBeaconUpdate(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void p2pRoleFsmRunEventDissolve(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void +p2pProcessEvent_UpdateNOAParam(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct EVENT_UPDATE_NOA_PARAMS *prEventUpdateNoaParam); + +#if CFG_ENABLE_PER_STA_STATISTICS_LOG +void p2pRoleFsmGetStaStatistics(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr); +#endif + +void p2pRoleFsmNotifyEapolTxStatus(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN enum ENUM_EAPOL_KEY_TYPE_T rEapolKeyType, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +#endif + +void p2pProcessPreSuspendFlow(IN struct ADAPTER *prAdapter); + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_role_state.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_role_state.h new file mode 100644 index 0000000000000..9d6ace05fdce2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_role_state.h @@ -0,0 +1,146 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#ifndef _P2P_ROLE_STATE_H +#define _P2P_ROLE_STATE_H + +void +p2pRoleStateInit_IDLE(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN struct BSS_INFO *prP2pBssInfo); + +void +p2pRoleStateAbort_IDLE(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN struct P2P_CHNL_REQ_INFO *prP2pChnlReqInfo); + +void p2pRoleStateInit_SCAN(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct P2P_SCAN_REQ_INFO *prScanReqInfo); + +void p2pRoleStateAbort_SCAN(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo); + +void +p2pRoleStateInit_REQING_CHANNEL(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo); + +void +p2pRoleStateAbort_REQING_CHANNEL(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pRoleBssInfo, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN enum ENUM_P2P_ROLE_STATE eNextState); + +void +p2pRoleStateInit_AP_CHNL_DETECTION(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct P2P_SCAN_REQ_INFO *prScanReqInfo, + IN struct P2P_CONNECTION_REQ_INFO *prConnReqInfo); + +void +p2pRoleStateAbort_AP_CHNL_DETECTION(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct P2P_CONNECTION_REQ_INFO *prP2pConnReqInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN struct P2P_SCAN_REQ_INFO *prP2pScanReqInfo, + IN enum ENUM_P2P_ROLE_STATE eNextState); + +void +p2pRoleStateInit_GC_JOIN(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo); + +void +p2pRoleStateAbort_GC_JOIN(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN struct P2P_JOIN_INFO *prJoinInfo, + IN enum ENUM_P2P_ROLE_STATE eNextState); + +#if (CFG_SUPPORT_DFS_MASTER == 1) +void +p2pRoleStateInit_DFS_CAC(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo); + +void +p2pRoleStateAbort_DFS_CAC(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pRoleBssInfo, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN enum ENUM_P2P_ROLE_STATE eNextState); + +void +p2pRoleStateInit_SWITCH_CHANNEL(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo); + +void +p2pRoleStateAbort_SWITCH_CHANNEL(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pRoleBssInfo, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN enum ENUM_P2P_ROLE_STATE eNextState); + +void +p2pRoleStatePrepare_To_DFS_CAC_STATE(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN enum ENUM_CHANNEL_WIDTH rChannelWidth, + IN struct P2P_CONNECTION_REQ_INFO *prConnReqInfo, + OUT struct P2P_CHNL_REQ_INFO *prChnlReqInfo); + +#endif + +void +p2pRoleStatePrepare_To_REQING_CHANNEL_STATE(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct P2P_CONNECTION_REQ_INFO *prConnReqInfo, + OUT struct P2P_CHNL_REQ_INFO *prChnlReqInfo); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_scan.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_scan.h new file mode 100644 index 0000000000000..e33ff64f25e7d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/p2p_scan.h @@ -0,0 +1,125 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 + ****************************************************************************** + */ + +void scnEventReturnChannel(IN struct ADAPTER *prAdapter, + IN uint8_t ucScnSeqNum); + +u_int8_t scanUpdateP2pDeviceDesc(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc); + +void +scanP2pProcessBeaconAndProbeResp(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint32_t *prStatus, + IN struct BSS_DESC *prBssDesc, + IN struct WLAN_BEACON_FRAME *prWlanBeaconFrame); + +void scanRemoveAllP2pBssDesc(struct ADAPTER *prAdapter); + +void scanRemoveP2pBssDesc(struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc); + +struct BSS_DESC *scanP2pSearchDesc(IN struct ADAPTER *prAdapter, + IN struct P2P_CONNECTION_REQ_INFO *prConnReqInfo); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/privacy.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/privacy.h new file mode 100644 index 0000000000000..35b1589dc2c2f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/privacy.h @@ -0,0 +1,289 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: include/mgmt/privacy.h#1 + */ + +/*! \file privacy.h + * \brief This file contains the function declaration for privacy.c. + */ + + +#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 WEP_128_LEN 16 +#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 CIPHER_SUITE_CCMP_W_CCX 9 +#define CIPHER_SUITE_GCMP 10 +#define CIPHER_SUITE_GCMP_128 11 +#define CIPHER_SUITE_GCMP_256 12 + +/* Todo:: Move to register */ +#if defined(MT6630) +#define WTBL_RESERVED_ENTRY 255 +#else +#define WTBL_RESERVED_ENTRY 255 +#endif +/* Todo:: By chip capability */ +/* Max wlan table size, the max+1 used for probe request,... mgmt frame */ +/*sending use basic rate and no security */ +#define WTBL_SIZE 32 + +#define WTBL_ALLOC_FAIL WTBL_RESERVED_ENTRY +#define WTBL_DEFAULT_ENTRY 0 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +struct IEEE_802_1X_HDR { + uint8_t ucVersion; + uint8_t ucType; + uint16_t u2Length; + /* followed by length octets of data */ +}; + +struct EAPOL_KEY { + uint8_t ucType; + /* Note: key_info, key_length, and key_data_length are unaligned */ + uint8_t aucKeyInfo[2]; /* big endian */ + uint8_t aucKeyLength[2]; /* big endian */ + uint8_t aucReplayCounter[8]; + uint8_t aucKeyNonce[16]; + uint8_t aucKeyIv[16]; + uint8_t aucKeyRsc[8]; + uint8_t aucKeyId[8]; /* Reserved in IEEE 802.11i/RSN */ + uint8_t aucKeyMic[16]; + uint8_t aucKeyDataLength[2]; /* big endian */ + /* followed by key_data_length bytes of key_data */ +}; + +/* WPA2 PMKID candicate structure */ +struct PMKID_CANDICATE { + uint8_t aucBssid[MAC_ADDR_LEN]; + uint32_t u4PreAuthFlags; +}; + +#if 0 +/* WPA2 PMKID cache structure */ +struct PMKID_ENTRY { + struct PARAM_BSSID_INFO rBssidInfo; + u_int8_t fgPmkidExist; +}; +#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 struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +void secSetPortBlocked(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prSta, IN u_int8_t fgPort); + +u_int8_t secCheckClassError(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN struct STA_RECORD *prStaRec); + +u_int8_t secTxPortControlCheck(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN struct STA_RECORD *prStaRec); + +u_int8_t secRxPortControlCheck(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSWRfb); + +void secSetCipherSuite(IN struct ADAPTER *prAdapter, + IN uint32_t u4CipherSuitesFlags); + +u_int8_t secIsProtectedFrame(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsdu, + IN struct STA_RECORD *prStaRec); + +void secClearPmkid(IN struct ADAPTER *prAdapter); + +u_int8_t secRsnKeyHandshakeEnabled(IN struct ADAPTER + *prAdapter); + +uint8_t secGetBmcWlanIndex(IN struct ADAPTER *prAdapter, + IN enum ENUM_NETWORK_TYPE eNetType, + IN struct STA_RECORD *prStaRec); + +u_int8_t secTransmitKeyExist(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prSta); + +u_int8_t secEnabledInAis(IN struct ADAPTER *prAdapter); + +u_int8_t secPrivacySeekForEntry(IN struct ADAPTER + *prAdapter, IN struct STA_RECORD *prSta); + +void secPrivacyFreeForEntry(IN struct ADAPTER *prAdapter, + IN uint8_t ucEntry); + +void secPrivacyFreeSta(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +void secRemoveBssBcEntry(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, IN u_int8_t fgRoam); + +uint8_t +secPrivacySeekForBcEntry(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN uint8_t *pucAddr, IN uint8_t ucStaIdx, + IN uint8_t ucAlg, IN uint8_t ucKeyId); + +uint8_t secGetStaIdxByWlanIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucWlanIdx); + +uint8_t secGetBssIdxByWlanIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucWlanIdx); + +uint8_t secLookupStaRecIndexFromTA(struct ADAPTER + *prAdapter, uint8_t *pucMacAddress); + +void secPrivacyDumpWTBL(IN struct ADAPTER *prAdapter); + +u_int8_t secCheckWTBLAssign(IN struct ADAPTER *prAdapter); + +u_int8_t secIsProtected1xFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +u_int8_t secIsProtectedBss(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo); + +u_int8_t secIsWepBss(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo); + +u_int8_t tkipMicDecapsulate(IN struct SW_RFB *prSwRfb, + IN uint8_t *pucMicKey); + +u_int8_t tkipMicDecapsulateInRxHdrTransMode( + IN struct SW_RFB *prSwRfb, IN uint8_t *pucMicKey); + +void secPostUpdateAddr(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo); + +enum ENUM_EAPOL_KEY_TYPE_T secGetEapolKeyType( + uint8_t *pucPacket); + +void secHandleRxEapolPacket(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prRetSwRfb, + IN struct STA_RECORD *prStaRec); + +void secHandleEapolTxStatus(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _PRIVACY_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/qosmap.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/qosmap.h new file mode 100644 index 0000000000000..c041b385c8369 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/qosmap.h @@ -0,0 +1,121 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "qosmap.h" + * \brief This file including the qosmap related function. + * + * This file provided the macros and functions library support for the + * protocol layer qosmap related function. + * + */ + +#ifndef _QOSMAP_H +#define _QOSMAP_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 + ******************************************************************************* + */ +#define DSCP_SUPPORT 1 +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +void handleQosMapConf(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +int qosHandleQosMapConfigure(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +struct _QOS_MAP_SET *qosParseQosMapSet(IN struct ADAPTER + *prAdapter, IN uint8_t *qosMapSet); + +uint8_t getUpFromDscp(IN struct GLUE_INFO *prGlueInfo, + IN int type, IN int dscp); + +void QosMapSetRelease(IN struct STA_RECORD *prStaRec); +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _QOSMAP_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rate.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rate.h new file mode 100644 index 0000000000000..bd4aa0fc395d8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rate.h @@ -0,0 +1,133 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + +#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 + ******************************************************************************* + */ +extern const uint8_t aucDataRate[]; + +/******************************************************************************* + * 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 struct IE_SUPPORTED_RATE + *prIeSupportedRate, + IN struct IE_EXT_SUPPORTED_RATE *prIeExtSupportedRate, OUT + uint16_t *pu2OperationalRateSet, + OUT uint16_t *pu2BSSBasicRateSet, + OUT u_int8_t *pfgIsUnknownBSSBasicRate); + +void +rateGetDataRatesFromRateSet(IN uint16_t + u2OperationalRateSet, IN uint16_t u2BSSBasicRateSet, + OUT uint8_t *pucDataRates, OUT + uint8_t *pucDataRatesLen); + +u_int8_t rateGetHighestRateIndexFromRateSet( + IN uint16_t u2RateSet, OUT uint8_t *pucHighestRateIndex); + +u_int8_t rateGetLowestRateIndexFromRateSet( + IN uint16_t u2RateSet, OUT uint8_t *pucLowestRateIndex); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _RATE_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rlm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rlm.h new file mode 100644 index 0000000000000..44a2123ea8c66 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rlm.h @@ -0,0 +1,706 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/ + * include/mgmt/rlm.h#2 + */ + +/*! \file "rlm.h" + * \brief + */ + + +#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 + ******************************************************************************* + */ +extern u_int8_t g_bIcapEnable; +extern u_int8_t g_bCaptureDone; +extern uint16_t g_u2DumpIndex; +#if CFG_SUPPORT_QA_TOOL +extern uint32_t g_au4Offset[2][2]; +extern uint32_t g_au4IQData[256]; +#endif + +/******************************************************************************* + * 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 | HT_CAP_INFO_DSSS_CCK_IN_40M \ + | HT_CAP_INFO_SM_POWER_SAVE) + +#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 + +#if CFG_SUPPORT_BFEE +#define TX_BEAMFORMING_CAP_BFEE \ + (TXBF_RX_NDP_CAPABLE | \ + TXBF_EXPLICIT_COMPRESSED_FEEDBACK_IMMEDIATE_CAPABLE | \ + TXBF_MINIMAL_GROUPING_1_2_3_CAPABLE | \ + TXBF_COMPRESSED_TX_ANTENNANUM_4_SUPPORTED | \ + TXBF_CHANNEL_ESTIMATION_4STS_CAPABILITY) +#else +#define TX_BEAMFORMING_CAP_BFEE 0 +#endif + +#if CFG_SUPPORT_BFER +#define TX_BEAMFORMING_CAP_BFER \ + (TXBF_TX_NDP_CAPABLE | \ + TXBF_EXPLICIT_COMPRESSED_TX_CAPAB) +#else +#define TX_BEAMFORMING_CAP_BFER 0 +#endif + +#define ASEL_CAP_DEFAULT_VAL 0 + +/* Define bandwidth from user setting */ +#define CONFIG_BW_20_40M 0 +#define CONFIG_BW_20M 1 /* 20MHz only */ + +/* Radio Measurement Request Mode definition */ +#define RM_REQ_MODE_PARALLEL_BIT BIT(0) +#define RM_REQ_MODE_ENABLE_BIT BIT(1) +#define RM_REQ_MODE_REQUEST_BIT BIT(2) +#define RM_REQ_MODE_REPORT_BIT BIT(3) +#define RM_REQ_MODE_DURATION_MANDATORY_BIT BIT(4) +#define RM_REP_MODE_LATE BIT(0) +#define RM_REP_MODE_INCAPABLE BIT(1) +#define RM_REP_MODE_REFUSED BIT(2) + +/* Radio Measurement Report Frame Max Length */ +#define RM_REPORT_FRAME_MAX_LENGTH 1600 +#define RM_BCN_REPORT_SUB_ELEM_MAX_LENGTH 224 +/* beacon request mode definition */ +#define RM_BCN_REQ_PASSIVE_MODE 0 +#define RM_BCN_REQ_ACTIVE_MODE 1 +#define RM_BCN_REQ_TABLE_MODE 2 + +#define RLM_INVALID_POWER_LIMIT -127 /* dbm */ + +#define RLM_MAX_TX_PWR 20 /* dbm */ +#define RLM_MIN_TX_PWR 8 /* dbm */ + +#if CFG_SUPPORT_BFER +#define MODE_LEGACY 0 +#define MODE_HT 1 +#define MODE_VHT 2 + +#define TX_RATE_MODE_CCK 0 +#define TX_RATE_MODE_OFDM 1 +#define TX_RATE_MODE_HTMIX 2 +#define TX_RATE_MODE_HTGF 3 +#define TX_RATE_MODE_VHT 4 +#define MAX_TX_MODE 5 + +#endif + +#if CFG_SUPPORT_802_11AC +#if CFG_SUPPORT_BFEE +#define FIELD_VHT_CAP_INFO_BFEE \ + (VHT_CAP_INFO_SU_BEAMFORMEE_CAPABLE) +#define VHT_CAP_INFO_BEAMFORMEE_STS_CAP_MAX 3 +#else +#define FIELD_VHT_CAP_INFO_BFEE 0 +#endif + +#if CFG_SUPPORT_BFER +#define FIELD_VHT_CAP_INFO_BFER \ + (VHT_CAP_INFO_SU_BEAMFORMER_CAPABLE| \ + VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS_2_SUPPORTED) +#else +#define FIELD_VHT_CAP_INFO_BFER 0 +#endif + +#define VHT_CAP_INFO_DEFAULT_VAL \ + (VHT_CAP_INFO_MAX_MPDU_LEN_3K | \ + (AMPDU_PARAM_MAX_AMPDU_LEN_1024K \ + << VHT_CAP_INFO_MAX_AMPDU_LENGTH_OFFSET)) + +#define VHT_CAP_INFO_DEFAULT_HIGHEST_DATA_RATE 0 +#endif +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +struct RLM_CAL_RESULT_ALL_V2 { + /* Used for checking the Cal Data is damaged */ + uint32_t u4MagicNum1; + + /* Thermal Value when do these Calibration */ + uint32_t u4ThermalInfo; + + /* Total Rom Data Length Backup in Host Side */ + uint32_t u4ValidRomCalDataLength; + + /* Total Ram Data Length Backup in Host Side */ + uint32_t u4ValidRamCalDataLength; + + /* All Rom Cal Data Dumpped by FW */ + uint32_t au4RomCalData[10000]; + + /* All Ram Cal Data Dumpped by FW */ + uint32_t au4RamCalData[10000]; + + /* Used for checking the Cal Data is damaged */ + uint32_t u4MagicNum2; +}; +extern struct RLM_CAL_RESULT_ALL_V2 g_rBackupCalDataAllV2; +#endif + +typedef void (*PFN_OPMODE_NOTIFY_DONE_FUNC)( + struct ADAPTER *, uint8_t, u_int8_t); + +enum ENUM_OP_NOTIFY_TYPE_T { + OP_NOTIFY_TYPE_VHT_NSS_BW = 0, + OP_NOTIFY_TYPE_HT_NSS, + OP_NOTIFY_TYPE_HT_BW, + OP_NOTIFY_TYPE_NUM +}; + +enum ENUM_OP_NOTIFY_STATE_T { + OP_NOTIFY_STATE_KEEP = 0, /* Won't change OP mode */ + OP_NOTIFY_STATE_SENDING, /* Sending OP notification frame */ + OP_NOTIFY_STATE_SUCCESS, /* OP notification Tx success */ + OP_NOTIFY_STATE_FAIL, /* OP notification Tx fail(over retry limit)*/ + OP_NOTIFY_STATE_NUM +}; + +enum ENUM_OP_CHANGE_STATUS_T { + OP_CHANGE_STATUS_INVALID = 0, /* input invalid */ + /* input valid, but no need to change */ + OP_CHANGE_STATUS_VALID_NO_CHANGE, + /* process callback done before function return */ + OP_CHANGE_STATUS_VALID_CHANGE_CALLBACK_DONE, + /* wait next INT to call callback */ + OP_CHANGE_STATUS_VALID_CHANGE_CALLBACK_WAIT, + OP_CHANGE_STATUS_NUM +}; + +struct SUB_ELEMENT_LIST { + struct SUB_ELEMENT_LIST *prNext; + struct SUB_ELEMENT rSubIE; +}; + +enum BCN_RM_STATE { + RM_NO_REQUEST, + RM_ON_GOING, + RM_WAITING, /*waiting normal scan done */ +}; + +enum RM_REQ_PRIORITY { + RM_PRI_BROADCAST, + RM_PRI_MULTICAST, + RM_PRI_UNICAST +}; + +struct NORMAL_SCAN_PARAMS { + u_int8_t fgExist; + struct PARAM_SCAN_REQUEST_ADV rScanRequest; + uint8_t aucScanIEBuf[MAX_IE_LENGTH]; +}; + +/* Beacon RM related parameters */ +struct BCN_RM_PARAMS { + u_int8_t fgExistBcnReq; + enum BCN_RM_STATE eState; + struct NORMAL_SCAN_PARAMS rNormalScan; +}; + +struct RM_BEACON_REPORT_PARAMS { + uint8_t ucChannel; + uint8_t ucRCPI; + uint8_t ucRSNI; + uint8_t ucAntennaID; + uint8_t ucFrameInfo; + uint8_t aucBcnFixedField[12]; +}; + +struct RM_MEASURE_REPORT_ENTRY { + struct LINK_ENTRY rLinkEntry; + /* should greater than sizeof(struct RM_BCN_REPORT) + + * sizeof(struct IE_MEASUREMENT_REPORT) + + * RM_BCN_REPORT_SUB_ELEM_MAX_LENGTH + */ + uint8_t aucMeasReport[260]; +}; + +struct RADIO_MEASUREMENT_REQ_PARAMS { + /* Remain Request Elements Length, started at prMeasElem. if it is 0, + * means RM is done + */ + uint16_t u2RemainReqLen; + uint16_t u2ReqIeBufLen; + struct IE_MEASUREMENT_REQ *prCurrMeasElem; + OS_SYSTIME rStartTime; + uint16_t u2Repetitions; + uint8_t *pucReqIeBuf; + enum RM_REQ_PRIORITY ePriority; + u_int8_t fgRmIsOngoing; + u_int8_t fgInitialLoop; + + struct BCN_RM_PARAMS rBcnRmParam; +}; + +struct RADIO_MEASUREMENT_REPORT_PARAMS { + /* the total length of Measurement Report elements */ + uint16_t u2ReportFrameLen; + uint8_t *pucReportFrameBuff; + /* Variables to collect report */ + struct LINK rReportLink; /* a link to save received report entry */ + struct LINK rFreeReportLink; +}; + +/******************************************************************************* + * P U B 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 RM_EXIST_REPORT(_prRmReportParam) \ + (((struct RADIO_MEASUREMENT_REPORT_PARAMS *)_prRmReportParam) \ + ->u2ReportFrameLen == \ + OFFSET_OF(struct ACTION_RM_REPORT_FRAME, aucInfoElem)) + +/* 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 || \ + IS_BSS_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) + +#if CFG_SUPPORT_802_11AC +#define RLM_NET_IS_11AC(_prBssInfo) \ + ((_prBssInfo)->ucPhyTypeSet & PHY_TYPE_SET_802_11AC) +#endif + +/* 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(struct ADAPTER *prAdapter); + +void rlmFsmEventUninit(struct ADAPTER *prAdapter); + +void rlmReqGenerateHtCapIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rlmReqGeneratePowerCapIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rlmReqGenerateSupportedChIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rlmReqGenerateExtCapIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rlmRspGenerateHtCapIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rlmRspGenerateExtCapIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rlmRspGenerateHtOpIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rlmRspGenerateErpIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rlmGenerateMTKOuiIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +u_int8_t rlmParseCheckMTKOuiIE(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, IN uint32_t *pu4Cap); + +void rlmGenerateCsaIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rlmProcessBcn(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb, uint8_t *pucIE, + uint16_t u2IELength); + +void rlmProcessAssocRsp(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb, uint8_t *pucIE, + uint16_t u2IELength); + +void rlmProcessHtAction(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); + +#if CFG_SUPPORT_802_11AC +void rlmProcessVhtAction(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); +#endif + +void rlmFillSyncCmdParam(struct CMD_SET_BSS_RLM_PARAM + *prCmdBody, struct BSS_INFO *prBssInfo); + +void rlmSyncOperationParams(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo); + +void rlmBssInitForAPandIbss(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo); + +void rlmProcessAssocReq(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb, uint8_t *pucIE, + uint16_t u2IELength); + +void rlmBssAborted(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo); + +#if CFG_SUPPORT_TDLS +uint32_t +rlmFillHtCapIEByParams(u_int8_t fg40mAllowed, + u_int8_t fgShortGIDisabled, + uint8_t u8SupportRxSgi20, + uint8_t u8SupportRxSgi40, uint8_t u8SupportRxGf, + enum ENUM_OP_MODE eCurrentOPMode, uint8_t *pOutBuf); + +uint32_t rlmFillHtCapIEByAdapter(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, uint8_t *pOutBuf); + +uint32_t rlmFillVhtCapIEByAdapter(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, uint8_t *pOutBuf); + +#endif + +#if CFG_SUPPORT_802_11AC +void rlmReqGenerateVhtCapIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rlmRspGenerateVhtCapIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rlmRspGenerateVhtOpIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rlmFillVhtOpIE(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, struct MSDU_INFO *prMsduInfo); + +void rlmRspGenerateVhtOpNotificationIE(struct ADAPTER + *prAdapter, struct MSDU_INFO *prMsduInfo); +void rlmReqGenerateVhtOpNotificationIE(struct ADAPTER + *prAdapter, struct MSDU_INFO *prMsduInfo); + + + + +#endif + +void rlmGenerateCountryIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +#if CFG_SUPPORT_DFS +void rlmProcessSpecMgtAction(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); +#endif + +void +rlmSendOpModeNotificationFrame(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t ucChannelWidth, uint8_t ucNss); + +void +rlmSendSmPowerSaveFrame(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, uint8_t ucNss); + +uint32_t +rlmNotifyVhtOpModeTxDone(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +uint32_t +rlmSmPowerSaveTxDone(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +uint32_t +rlmNotifyChannelWidthtTxDone(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +uint8_t +rlmGetBssOpBwByVhtAndHtOpInfo(struct BSS_INFO *prBssInfo); + +uint8_t +rlmGetVhtOpBwByBssOpBw(uint8_t ucBssOpBw); + +void +rlmFillVhtOpInfoByBssOpBw(struct BSS_INFO *prBssInfo, + uint8_t ucChannelWidth); + +enum ENUM_OP_CHANGE_STATUS_T +rlmChangeOperationMode( + struct ADAPTER *prAdapter, + uint8_t ucBssIndex, + uint8_t ucChannelWidth, + uint8_t ucNss, + PFN_OPMODE_NOTIFY_DONE_FUNC pfOpChangeHandler +); + +void +rlmDummyChangeOpHandler(struct ADAPTER *prAdapter, + uint8_t ucBssIndex, u_int8_t fgIsChangeSuccess); + + +#if CFG_SUPPORT_BFER +void +rlmBfStaRecPfmuUpdate(struct ADAPTER *prAdapter, struct STA_RECORD *prStaRec); + +void +rlmETxBfTriggerPeriodicSounding(struct ADAPTER *prAdapter); + +bool +rlmClientSupportsVhtETxBF(struct STA_RECORD *prStaRec); + +uint8_t +rlmClientSupportsVhtBfeeStsCap(struct STA_RECORD *prStaRec); + +bool +rlmClientSupportsHtETxBF(struct STA_RECORD *prStaRec); +#endif + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +uint32_t rlmCalBackup( + struct ADAPTER *prAdapter, + uint8_t ucReason, + uint8_t ucAction, + uint8_t ucRomRam +); + +uint32_t rlmTriggerCalBackup( + struct ADAPTER *prAdapter, + u_int8_t fgIsCalDataBackuped +); +#endif + +void rlmModifyVhtBwPara(uint8_t *pucVhtChannelFrequencyS1, + uint8_t *pucVhtChannelFrequencyS2, + uint8_t *pucVhtChannelWidth); + +void rlmReviseMaxBw( + struct ADAPTER *prAdapter, + uint8_t ucBssIndex, + enum ENUM_CHNL_EXT *peExtend, + enum ENUM_CHANNEL_WIDTH *peChannelWidth, + uint8_t *pucS1, + uint8_t *pucPrimaryCh); + +void rlmProcessNeighborReportResonse(struct ADAPTER *prAdapter, + struct WLAN_ACTION_FRAME *prAction, + uint16_t u2PacketLen); +void rlmTxNeighborReportRequest(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + struct SUB_ELEMENT_LIST *prSubIEs); + +void rlmGenerateRRMEnabledCapIE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +void rlmGeneratePowerCapIE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +void rlmProcessRadioMeasurementRequest(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); + +void rlmProcessLinkMeasurementRequest(struct ADAPTER *prAdapter, + struct WLAN_ACTION_FRAME *prAction); + +void rlmProcessNeighborReportResonse(struct ADAPTER *prAdapter, + struct WLAN_ACTION_FRAME *prAction, + uint16_t u2PacketLen); + +void rlmFillRrmCapa(uint8_t *pucCapa); + +void rlmSetMaxTxPwrLimit(IN struct ADAPTER *prAdapter, int8_t cLimit, + uint8_t ucEnable); + +void rlmStartNextMeasurement(struct ADAPTER *prAdapter, u_int8_t fgNewStarted); + +u_int8_t rlmBcnRmRunning(struct ADAPTER *prAdapter); + +u_int8_t rlmFillScanMsg(struct ADAPTER *prAdapter, + struct MSG_SCN_SCAN_REQ_V2 *prMsg); + +void rlmDoBeaconMeasurement(struct ADAPTER *prAdapter, unsigned long ulParam); + +void rlmTxNeighborReportRequest(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + struct SUB_ELEMENT_LIST *prSubIEs); + +void rlmTxRadioMeasurementReport(struct ADAPTER *prAdapter); + +void rlmFreeMeasurementResources(struct ADAPTER *prAdapter); + +enum RM_REQ_PRIORITY rlmGetRmRequestPriority(uint8_t *pucDestAddr); + +void rlmRunEventProcessNextRm(struct ADAPTER *prAdapter, + struct MSG_HDR *prMsgHdr); + +void rlmScheduleNextRm(struct ADAPTER *prAdapter); + +void rlmProcessBeaconAndProbeResp(struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +void rlmUpdateBssTimeTsf(struct ADAPTER *prAdapter, struct BSS_DESC *prBssDesc); + +#if CFG_SUPPORT_WAC +uint32_t rlmCalculateWAC_IELen( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct STA_RECORD *prStaRec); + +void rlmGenerateWAC_IE( + IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); +#endif + + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#ifndef _lint +static __KAL_INLINE__ void rlmDataTypeCheck(void) +{ +} +#endif /* _lint */ + +#endif /* _RLM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rlm_domain.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rlm_domain.h new file mode 100644 index 0000000000000..b4138d07856e0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rlm_domain.h @@ -0,0 +1,1052 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/ + * include/mgmt/rlm_domain.h#1 + */ + +/*! \file "rlm_domain.h" + * \brief + */ + + +#ifndef _RLM_DOMAIN_H +#define _RLM_DOMAIN_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define MAX_SUBBAND_NUM 6 +#define MAX_SUBBAND_NUM_5G 8 + +#define COUNTRY_CODE_NULL ((uint16_t)0x0) + +/* ISO/IEC 3166-1 two-character country codes */ + +/* Andorra */ +#define COUNTRY_CODE_AD (((uint16_t) 'A' << 8) | (uint16_t) 'D') +/* UAE */ +#define COUNTRY_CODE_AE (((uint16_t) 'A' << 8) | (uint16_t) 'E') +/* Afghanistan */ +#define COUNTRY_CODE_AF (((uint16_t) 'A' << 8) | (uint16_t) 'F') +/* Antigua & Barbuda */ +#define COUNTRY_CODE_AG (((uint16_t) 'A' << 8) | (uint16_t) 'G') +/* Anguilla */ +#define COUNTRY_CODE_AI (((uint16_t) 'A' << 8) | (uint16_t) 'I') +/* Albania */ +#define COUNTRY_CODE_AL (((uint16_t) 'A' << 8) | (uint16_t) 'L') +/* Armenia */ +#define COUNTRY_CODE_AM (((uint16_t) 'A' << 8) | (uint16_t) 'M') +/* Netherlands Antilles */ +#define COUNTRY_CODE_AN (((uint16_t) 'A' << 8) | (uint16_t) 'N') +/* Angola */ +#define COUNTRY_CODE_AO (((uint16_t) 'A' << 8) | (uint16_t) 'O') +/* Argentina */ +#define COUNTRY_CODE_AR (((uint16_t) 'A' << 8) | (uint16_t) 'R') +/* American Samoa (USA) */ +#define COUNTRY_CODE_AS (((uint16_t) 'A' << 8) | (uint16_t) 'S') +/* Austria */ +#define COUNTRY_CODE_AT (((uint16_t) 'A' << 8) | (uint16_t) 'T') +/* Australia */ +#define COUNTRY_CODE_AU (((uint16_t) 'A' << 8) | (uint16_t) 'U') +/* Aruba */ +#define COUNTRY_CODE_AW (((uint16_t) 'A' << 8) | (uint16_t) 'W') +/* Azerbaijan */ +#define COUNTRY_CODE_AZ (((uint16_t) 'A' << 8) | (uint16_t) 'Z') +/* Bosnia and Herzegovina */ +#define COUNTRY_CODE_BA (((uint16_t) 'B' << 8) | (uint16_t) 'A') +/* Barbados */ +#define COUNTRY_CODE_BB (((uint16_t) 'B' << 8) | (uint16_t) 'B') +/* Bangladesh */ +#define COUNTRY_CODE_BD (((uint16_t) 'B' << 8) | (uint16_t) 'D') +/* Belgium */ +#define COUNTRY_CODE_BE (((uint16_t) 'B' << 8) | (uint16_t) 'E') +/* Burkina Faso */ +#define COUNTRY_CODE_BF (((uint16_t) 'B' << 8) | (uint16_t) 'F') +/* Bulgaria */ +#define COUNTRY_CODE_BG (((uint16_t) 'B' << 8) | (uint16_t) 'G') +/* Bahrain */ +#define COUNTRY_CODE_BH (((uint16_t) 'B' << 8) | (uint16_t) 'H') +/* Burundi */ +#define COUNTRY_CODE_BI (((uint16_t) 'B' << 8) | (uint16_t) 'I') +/* Benin */ +#define COUNTRY_CODE_BJ (((uint16_t) 'B' << 8) | (uint16_t) 'J') +/* Bermuda */ +#define COUNTRY_CODE_BM (((uint16_t) 'B' << 8) | (uint16_t) 'M') +/* Brunei */ +#define COUNTRY_CODE_BN (((uint16_t) 'B' << 8) | (uint16_t) 'N') +/* Bolivia */ +#define COUNTRY_CODE_BO (((uint16_t) 'B' << 8) | (uint16_t) 'O') +/* Brazil */ +#define COUNTRY_CODE_BR (((uint16_t) 'B' << 8) | (uint16_t) 'R') +/* Bahamas */ +#define COUNTRY_CODE_BS (((uint16_t) 'B' << 8) | (uint16_t) 'S') +/* Bhutan */ +#define COUNTRY_CODE_BT (((uint16_t) 'B' << 8) | (uint16_t) 'T') +/* Botswana */ +#define COUNTRY_CODE_BW (((uint16_t) 'B' << 8) | (uint16_t) 'W') +/* Belarus */ +#define COUNTRY_CODE_BY (((uint16_t) 'B' << 8) | (uint16_t) 'Y') +/* Belize */ +#define COUNTRY_CODE_BZ (((uint16_t) 'B' << 8) | (uint16_t) 'Z') +/* Canada */ +#define COUNTRY_CODE_CA (((uint16_t) 'C' << 8) | (uint16_t) 'A') +/* Democratic Republic of the Congo */ +#define COUNTRY_CODE_CD (((uint16_t) 'C' << 8) | (uint16_t) 'D') +/* Central African Republic */ +#define COUNTRY_CODE_CF (((uint16_t) 'C' << 8) | (uint16_t) 'F') +/* Republic of the Congo */ +#define COUNTRY_CODE_CG (((uint16_t) 'C' << 8) | (uint16_t) 'G') +/* Switzerland */ +#define COUNTRY_CODE_CH (((uint16_t) 'C' << 8) | (uint16_t) 'H') +/* Cote d'lvoire */ +#define COUNTRY_CODE_CI (((uint16_t) 'C' << 8) | (uint16_t) 'I') +/* Cook Island */ +#define COUNTRY_CODE_CK (((uint16_t) 'C' << 8) | (uint16_t) 'K') +/* Chile */ +#define COUNTRY_CODE_CL (((uint16_t) 'C' << 8) | (uint16_t) 'L') +/* Cameroon */ +#define COUNTRY_CODE_CM (((uint16_t) 'C' << 8) | (uint16_t) 'M') +/* China */ +#define COUNTRY_CODE_CN (((uint16_t) 'C' << 8) | (uint16_t) 'N') +/* Columbia */ +#define COUNTRY_CODE_CO (((uint16_t) 'C' << 8) | (uint16_t) 'O') +/* Costa Rica */ +#define COUNTRY_CODE_CR (((uint16_t) 'C' << 8) | (uint16_t) 'R') +/* Cuba */ +#define COUNTRY_CODE_CU (((uint16_t) 'C' << 8) | (uint16_t) 'U') +/* Cape Verde */ +#define COUNTRY_CODE_CV (((uint16_t) 'C' << 8) | (uint16_t) 'V') +/* "Christmas Island(Australia) */ +#define COUNTRY_CODE_CX (((uint16_t) 'C' << 8) | (uint16_t) 'X') +/* Cyprus */ +#define COUNTRY_CODE_CY (((uint16_t) 'C' << 8) | (uint16_t) 'Y') +/* Czech */ +#define COUNTRY_CODE_CZ (((uint16_t) 'C' << 8) | (uint16_t) 'Z') +/* Germany */ +#define COUNTRY_CODE_DE (((uint16_t) 'D' << 8) | (uint16_t) 'E') +/* Djibouti */ +#define COUNTRY_CODE_DJ (((uint16_t) 'D' << 8) | (uint16_t) 'J') +/* Denmark */ +#define COUNTRY_CODE_DK (((uint16_t) 'D' << 8) | (uint16_t) 'K') +/* Dominica */ +#define COUNTRY_CODE_DM (((uint16_t) 'D' << 8) | (uint16_t) 'M') +/* Dominican Republic */ +#define COUNTRY_CODE_DO (((uint16_t) 'D' << 8) | (uint16_t) 'O') +/* Algeria */ +#define COUNTRY_CODE_DZ (((uint16_t) 'D' << 8) | (uint16_t) 'Z') +/* Ecuador */ +#define COUNTRY_CODE_EC (((uint16_t) 'E' << 8) | (uint16_t) 'C') +/* Estonia */ +#define COUNTRY_CODE_EE (((uint16_t) 'E' << 8) | (uint16_t) 'E') +/* Egypt */ +#define COUNTRY_CODE_EG (((uint16_t) 'E' << 8) | (uint16_t) 'G') +/* Western Sahara (Morocco) */ +#define COUNTRY_CODE_EH (((uint16_t) 'E' << 8) | (uint16_t) 'H') +/* Eritrea */ +#define COUNTRY_CODE_ER (((uint16_t) 'E' << 8) | (uint16_t) 'R') +/* Spain */ +#define COUNTRY_CODE_ES (((uint16_t) 'E' << 8) | (uint16_t) 'S') +/* Ethiopia */ +#define COUNTRY_CODE_ET (((uint16_t) 'E' << 8) | (uint16_t) 'T') +/* Europe */ +#define COUNTRY_CODE_EU (((uint16_t) 'E' << 8) | (uint16_t) 'U') +/* Finland */ +#define COUNTRY_CODE_FI (((uint16_t) 'F' << 8) | (uint16_t) 'I') +/* Fiji */ +#define COUNTRY_CODE_FJ (((uint16_t) 'F' << 8) | (uint16_t) 'J') +/* Falkland Island */ +#define COUNTRY_CODE_FK (((uint16_t) 'F' << 8) | (uint16_t) 'K') +/* Micronesia */ +#define COUNTRY_CODE_FM (((uint16_t) 'F' << 8) | (uint16_t) 'M') +/* Faroe Island */ +#define COUNTRY_CODE_FO (((uint16_t) 'F' << 8) | (uint16_t) 'O') +/* France */ +#define COUNTRY_CODE_FR (((uint16_t) 'F' << 8) | (uint16_t) 'R') +/* Wallis and Futuna (France) */ +#define COUNTRY_CODE_FR (((uint16_t) 'F' << 8) | (uint16_t) 'R') +/* Gabon */ +#define COUNTRY_CODE_GA (((uint16_t) 'G' << 8) | (uint16_t) 'A') +/* United Kingdom */ +#define COUNTRY_CODE_GB (((uint16_t) 'G' << 8) | (uint16_t) 'B') +/* Grenada */ +#define COUNTRY_CODE_GD (((uint16_t) 'G' << 8) | (uint16_t) 'D') +/* Georgia */ +#define COUNTRY_CODE_GE (((uint16_t) 'G' << 8) | (uint16_t) 'E') +/* French Guiana */ +#define COUNTRY_CODE_GF (((uint16_t) 'G' << 8) | (uint16_t) 'F') +/* Guernsey */ +#define COUNTRY_CODE_GG (((uint16_t) 'G' << 8) | (uint16_t) 'G') +/* Ghana */ +#define COUNTRY_CODE_GH (((uint16_t) 'G' << 8) | (uint16_t) 'H') +/* Gibraltar */ +#define COUNTRY_CODE_GI (((uint16_t) 'G' << 8) | (uint16_t) 'I') +/* Gambia */ +#define COUNTRY_CODE_GM (((uint16_t) 'G' << 8) | (uint16_t) 'M') +/* Guinea */ +#define COUNTRY_CODE_GN (((uint16_t) 'G' << 8) | (uint16_t) 'N') +/* Guadeloupe */ +#define COUNTRY_CODE_GP (((uint16_t) 'G' << 8) | (uint16_t) 'P') +/* Equatorial Guinea */ +#define COUNTRY_CODE_GQ (((uint16_t) 'G' << 8) | (uint16_t) 'Q') +/* Greece */ +#define COUNTRY_CODE_GR (((uint16_t) 'G' << 8) | (uint16_t) 'R') +/* Guatemala */ +#define COUNTRY_CODE_GT (((uint16_t) 'G' << 8) | (uint16_t) 'T') +/* Guam */ +#define COUNTRY_CODE_GU (((uint16_t) 'G' << 8) | (uint16_t) 'U') +/* Guinea-Bissau */ +#define COUNTRY_CODE_GW (((uint16_t) 'G' << 8) | (uint16_t) 'W') +/* Guyana */ +#define COUNTRY_CODE_GY (((uint16_t) 'G' << 8) | (uint16_t) 'Y') +/* Hong Kong */ +#define COUNTRY_CODE_HK (((uint16_t) 'H' << 8) | (uint16_t) 'K') +/* Honduras */ +#define COUNTRY_CODE_HN (((uint16_t) 'H' << 8) | (uint16_t) 'N') +/* Croatia */ +#define COUNTRY_CODE_HR (((uint16_t) 'H' << 8) | (uint16_t) 'R') +/* Haiti */ +#define COUNTRY_CODE_HT (((uint16_t) 'H' << 8) | (uint16_t) 'T') +/* Hungary */ +#define COUNTRY_CODE_HU (((uint16_t) 'H' << 8) | (uint16_t) 'U') +/* Indonesia */ +#define COUNTRY_CODE_ID (((uint16_t) 'I' << 8) | (uint16_t) 'D') +/* Ireland */ +#define COUNTRY_CODE_IE (((uint16_t) 'I' << 8) | (uint16_t) 'E') +/* Israel */ +#define COUNTRY_CODE_IL (((uint16_t) 'I' << 8) | (uint16_t) 'L') +/* Isle of Man */ +#define COUNTRY_CODE_IM (((uint16_t) 'I' << 8) | (uint16_t) 'M') +/* India */ +#define COUNTRY_CODE_IN (((uint16_t) 'I' << 8) | (uint16_t) 'N') +/* Iraq */ +#define COUNTRY_CODE_IQ (((uint16_t) 'I' << 8) | (uint16_t) 'Q') +/* Iran */ +#define COUNTRY_CODE_IR (((uint16_t) 'I' << 8) | (uint16_t) 'R') +/* Iceland */ +#define COUNTRY_CODE_IS (((uint16_t) 'I' << 8) | (uint16_t) 'S') +/* Italy */ +#define COUNTRY_CODE_IT (((uint16_t) 'I' << 8) | (uint16_t) 'T') +/* Jersey */ +#define COUNTRY_CODE_JE (((uint16_t) 'J' << 8) | (uint16_t) 'E') +/* Jameica */ +#define COUNTRY_CODE_JM (((uint16_t) 'J' << 8) | (uint16_t) 'M') +/* Jordan */ +#define COUNTRY_CODE_JO (((uint16_t) 'J' << 8) | (uint16_t) 'O') +/* Japan */ +#define COUNTRY_CODE_JP (((uint16_t) 'J' << 8) | (uint16_t) 'P') +/* Kenya */ +#define COUNTRY_CODE_KE (((uint16_t) 'K' << 8) | (uint16_t) 'E') +/* Kyrgyzstan */ +#define COUNTRY_CODE_KG (((uint16_t) 'K' << 8) | (uint16_t) 'G') +/* Cambodia */ +#define COUNTRY_CODE_KH (((uint16_t) 'K' << 8) | (uint16_t) 'H') +/* Kiribati */ +#define COUNTRY_CODE_KI (((uint16_t) 'K' << 8) | (uint16_t) 'I') +/* Comoros */ +#define COUNTRY_CODE_KM (((uint16_t) 'K' << 8) | (uint16_t) 'M') +/* Saint Kitts and Nevis */ +#define COUNTRY_CODE_KN (((uint16_t) 'K' << 8) | (uint16_t) 'N') +/* North Korea */ +#define COUNTRY_CODE_KP (((uint16_t) 'K' << 8) | (uint16_t) 'P') +/* South Korea */ +#define COUNTRY_CODE_KR (((uint16_t) 'K' << 8) | (uint16_t) 'R') +/* Kuwait */ +#define COUNTRY_CODE_KW (((uint16_t) 'K' << 8) | (uint16_t) 'W') +/* Cayman Islands */ +#define COUNTRY_CODE_KY (((uint16_t) 'K' << 8) | (uint16_t) 'Y') +/* Kazakhstan */ +#define COUNTRY_CODE_KZ (((uint16_t) 'K' << 8) | (uint16_t) 'Z') +/* Laos */ +#define COUNTRY_CODE_LA (((uint16_t) 'L' << 8) | (uint16_t) 'A') +/* Lebanon */ +#define COUNTRY_CODE_LB (((uint16_t) 'L' << 8) | (uint16_t) 'B') +/* Saint Lucia */ +#define COUNTRY_CODE_LC (((uint16_t) 'L' << 8) | (uint16_t) 'C') +/* Liechtenstein */ +#define COUNTRY_CODE_LI (((uint16_t) 'L' << 8) | (uint16_t) 'I') +/* Sri Lanka */ +#define COUNTRY_CODE_LK (((uint16_t) 'L' << 8) | (uint16_t) 'K') +/* Liberia */ +#define COUNTRY_CODE_LR (((uint16_t) 'L' << 8) | (uint16_t) 'R') +/* Lesotho */ +#define COUNTRY_CODE_LS (((uint16_t) 'L' << 8) | (uint16_t) 'S') +/* Lithuania */ +#define COUNTRY_CODE_LT (((uint16_t) 'L' << 8) | (uint16_t) 'T') +/* Luxemburg */ +#define COUNTRY_CODE_LU (((uint16_t) 'L' << 8) | (uint16_t) 'U') +/* Latvia */ +#define COUNTRY_CODE_LV (((uint16_t) 'L' << 8) | (uint16_t) 'V') +/* Libya */ +#define COUNTRY_CODE_LY (((uint16_t) 'L' << 8) | (uint16_t) 'Y') +/* Morocco */ +#define COUNTRY_CODE_MA (((uint16_t) 'M' << 8) | (uint16_t) 'A') +/* Monaco */ +#define COUNTRY_CODE_MC (((uint16_t) 'M' << 8) | (uint16_t) 'C') +/* Moldova */ +#define COUNTRY_CODE_MD (((uint16_t) 'M' << 8) | (uint16_t) 'D') +/* Montenegro */ +#define COUNTRY_CODE_ME (((uint16_t) 'M' << 8) | (uint16_t) 'E') +/* Saint Martin / Sint Marteen (Added on window's list) */ +#define COUNTRY_CODE_MF (((uint16_t) 'M' << 8) | (uint16_t) 'F') +/* Madagascar */ +#define COUNTRY_CODE_MG (((uint16_t) 'M' << 8) | (uint16_t) 'G') +/* Marshall Islands */ +#define COUNTRY_CODE_MH (((uint16_t) 'M' << 8) | (uint16_t) 'H') +/* Macedonia */ +#define COUNTRY_CODE_MK (((uint16_t) 'M' << 8) | (uint16_t) 'K') +/* Mali */ +#define COUNTRY_CODE_ML (((uint16_t) 'M' << 8) | (uint16_t) 'L') +/* Myanmar */ +#define COUNTRY_CODE_MM (((uint16_t) 'M' << 8) | (uint16_t) 'M') +/* Mongolia */ +#define COUNTRY_CODE_MN (((uint16_t) 'M' << 8) | (uint16_t) 'N') +/* Macao */ +#define COUNTRY_CODE_MO (((uint16_t) 'M' << 8) | (uint16_t) 'O') +/* Northern Mariana Islands (Rota Island Saipan and Tinian Island) */ +#define COUNTRY_CODE_MP (((uint16_t) 'M' << 8) | (uint16_t) 'P') +/* Martinique (France) */ +#define COUNTRY_CODE_MQ (((uint16_t) 'M' << 8) | (uint16_t) 'Q') +/* Mauritania */ +#define COUNTRY_CODE_MR (((uint16_t) 'M' << 8) | (uint16_t) 'R') +/* Montserrat (UK) */ +#define COUNTRY_CODE_MS (((uint16_t) 'M' << 8) | (uint16_t) 'S') +/* Malta */ +#define COUNTRY_CODE_MT (((uint16_t) 'M' << 8) | (uint16_t) 'T') +/* Mauritius */ +#define COUNTRY_CODE_MU (((uint16_t) 'M' << 8) | (uint16_t) 'U') +/* Maldives */ +#define COUNTRY_CODE_MV (((uint16_t) 'M' << 8) | (uint16_t) 'V') +/* Malawi */ +#define COUNTRY_CODE_MW (((uint16_t) 'M' << 8) | (uint16_t) 'W') +/* Mexico */ +#define COUNTRY_CODE_MX (((uint16_t) 'M' << 8) | (uint16_t) 'X') +/* Malaysia */ +#define COUNTRY_CODE_MY (((uint16_t) 'M' << 8) | (uint16_t) 'Y') +/* Mozambique */ +#define COUNTRY_CODE_MZ (((uint16_t) 'M' << 8) | (uint16_t) 'Z') +/* Namibia */ +#define COUNTRY_CODE_NA (((uint16_t) 'N' << 8) | (uint16_t) 'A') +/* New Caledonia */ +#define COUNTRY_CODE_NC (((uint16_t) 'N' << 8) | (uint16_t) 'C') +/* Niger */ +#define COUNTRY_CODE_NE (((uint16_t) 'N' << 8) | (uint16_t) 'E') +/* Norfolk Island */ +#define COUNTRY_CODE_NF (((uint16_t) 'N' << 8) | (uint16_t) 'F') +/* Nigeria */ +#define COUNTRY_CODE_NG (((uint16_t) 'N' << 8) | (uint16_t) 'G') +/* Nicaragua */ +#define COUNTRY_CODE_NI (((uint16_t) 'N' << 8) | (uint16_t) 'I') +/* Netherlands */ +#define COUNTRY_CODE_NL (((uint16_t) 'N' << 8) | (uint16_t) 'L') +/* Norway */ +#define COUNTRY_CODE_NO (((uint16_t) 'N' << 8) | (uint16_t) 'O') +/* Nepal */ +#define COUNTRY_CODE_NP (((uint16_t) 'N' << 8) | (uint16_t) 'P') +/* Nauru */ +#define COUNTRY_CODE_NR (((uint16_t) 'N' << 8) | (uint16_t) 'R') +/* Niue */ +#define COUNTRY_CODE_NU (((uint16_t) 'N' << 8) | (uint16_t) 'U') +/* New Zealand */ +#define COUNTRY_CODE_NZ (((uint16_t) 'N' << 8) | (uint16_t) 'Z') +/* Oman */ +#define COUNTRY_CODE_OM (((uint16_t) 'O' << 8) | (uint16_t) 'M') +/* Panama */ +#define COUNTRY_CODE_PA (((uint16_t) 'P' << 8) | (uint16_t) 'A') +/* Peru */ +#define COUNTRY_CODE_PE (((uint16_t) 'P' << 8) | (uint16_t) 'E') +/* "French Polynesia */ +#define COUNTRY_CODE_PF (((uint16_t) 'P' << 8) | (uint16_t) 'F') +/* Papua New Guinea */ +#define COUNTRY_CODE_PG (((uint16_t) 'P' << 8) | (uint16_t) 'G') +/* Philippines */ +#define COUNTRY_CODE_PH (((uint16_t) 'P' << 8) | (uint16_t) 'H') +/* Pakistan */ +#define COUNTRY_CODE_PK (((uint16_t) 'P' << 8) | (uint16_t) 'K') +/* Poland */ +#define COUNTRY_CODE_PL (((uint16_t) 'P' << 8) | (uint16_t) 'L') +/* Saint Pierre and Miquelon */ +#define COUNTRY_CODE_PM (((uint16_t) 'P' << 8) | (uint16_t) 'M') +/* Pitcairn Islands */ +#define COUNTRY_CODE_PN (((uint16_t) 'P' << 8) | (uint16_t) 'N') +/* Puerto Rico (USA) */ +#define COUNTRY_CODE_PR (((uint16_t) 'P' << 8) | (uint16_t) 'R') +/* Palestinian Authority */ +#define COUNTRY_CODE_PS (((uint16_t) 'P' << 8) | (uint16_t) 'S') +/* Portugal */ +#define COUNTRY_CODE_PT (((uint16_t) 'P' << 8) | (uint16_t) 'T') +/* Palau */ +#define COUNTRY_CODE_PW (((uint16_t) 'P' << 8) | (uint16_t) 'W') +/* Paraguay */ +#define COUNTRY_CODE_PY (((uint16_t) 'P' << 8) | (uint16_t) 'Y') +/* Qatar */ +#define COUNTRY_CODE_QA (((uint16_t) 'Q' << 8) | (uint16_t) 'A') +/* Reunion (France) */ +#define COUNTRY_CODE_RE (((uint16_t) 'R' << 8) | (uint16_t) 'E') +/* Kosvo (Added on window's list) */ +#define COUNTRY_CODE_RKS (((uint16_t) 'R' << 8) | (uint16_t) 'K') +/* Romania */ +#define COUNTRY_CODE_RO (((uint16_t) 'R' << 8) | (uint16_t) 'O') +/* Serbia */ +#define COUNTRY_CODE_RS (((uint16_t) 'R' << 8) | (uint16_t) 'S') +/* Russia */ +#define COUNTRY_CODE_RU (((uint16_t) 'R' << 8) | (uint16_t) 'U') +/* Rwanda */ +#define COUNTRY_CODE_RW (((uint16_t) 'R' << 8) | (uint16_t) 'W') +/* Saudi Arabia */ +#define COUNTRY_CODE_SA (((uint16_t) 'S' << 8) | (uint16_t) 'A') +/* Solomon Islands */ +#define COUNTRY_CODE_SB (((uint16_t) 'S' << 8) | (uint16_t) 'B') +/* Seychelles */ +#define COUNTRY_CODE_SC (((uint16_t) 'S' << 8) | (uint16_t) 'C') +/* Sudan */ +#define COUNTRY_CODE_SD (((uint16_t) 'S' << 8) | (uint16_t) 'D') +/* Sweden */ +#define COUNTRY_CODE_SE (((uint16_t) 'S' << 8) | (uint16_t) 'E') +/* Singapole */ +#define COUNTRY_CODE_SG (((uint16_t) 'S' << 8) | (uint16_t) 'G') +/* Slovenia */ +#define COUNTRY_CODE_SI (((uint16_t) 'S' << 8) | (uint16_t) 'I') +/* Slovakia */ +#define COUNTRY_CODE_SK (((uint16_t) 'S' << 8) | (uint16_t) 'K') +/* Sierra Leone */ +#define COUNTRY_CODE_SL (((uint16_t) 'S' << 8) | (uint16_t) 'L') +/* San Marino */ +#define COUNTRY_CODE_SM (((uint16_t) 'S' << 8) | (uint16_t) 'M') +/* Senegal */ +#define COUNTRY_CODE_SN (((uint16_t) 'S' << 8) | (uint16_t) 'N') +/* Somalia */ +#define COUNTRY_CODE_SO (((uint16_t) 'S' << 8) | (uint16_t) 'O') +/* Suriname */ +#define COUNTRY_CODE_SR (((uint16_t) 'S' << 8) | (uint16_t) 'R') +/* South_Sudan */ +#define COUNTRY_CODE_SS (((uint16_t) 'S' << 8) | (uint16_t) 'S') +/* Sao Tome and Principe */ +#define COUNTRY_CODE_ST (((uint16_t) 'S' << 8) | (uint16_t) 'T') +/* El Salvador */ +#define COUNTRY_CODE_SV (((uint16_t) 'S' << 8) | (uint16_t) 'V') +/* Syria */ +#define COUNTRY_CODE_SY (((uint16_t) 'S' << 8) | (uint16_t) 'Y') +/* Swaziland */ +#define COUNTRY_CODE_SZ (((uint16_t) 'S' << 8) | (uint16_t) 'Z') +/* Turks and Caicos Islands (UK) */ +#define COUNTRY_CODE_TC (((uint16_t) 'T' << 8) | (uint16_t) 'C') +/* Chad */ +#define COUNTRY_CODE_TD (((uint16_t) 'T' << 8) | (uint16_t) 'D') +/* French Southern and Antarctic Lands */ +#define COUNTRY_CODE_TF (((uint16_t) 'T' << 8) | (uint16_t) 'F') +/* Togo */ +#define COUNTRY_CODE_TG (((uint16_t) 'T' << 8) | (uint16_t) 'G') +/* Thailand */ +#define COUNTRY_CODE_TH (((uint16_t) 'T' << 8) | (uint16_t) 'H') +/* Tajikistan */ +#define COUNTRY_CODE_TJ (((uint16_t) 'T' << 8) | (uint16_t) 'J') +/* East Timor */ +#define COUNTRY_CODE_TL (((uint16_t) 'T' << 8) | (uint16_t) 'L') +/* Turkmenistan */ +#define COUNTRY_CODE_TM (((uint16_t) 'T' << 8) | (uint16_t) 'M') +/* Tunisia */ +#define COUNTRY_CODE_TN (((uint16_t) 'T' << 8) | (uint16_t) 'N') +/* Tonga */ +#define COUNTRY_CODE_TO (((uint16_t) 'T' << 8) | (uint16_t) 'O') +/* Turkey */ +#define COUNTRY_CODE_TR (((uint16_t) 'T' << 8) | (uint16_t) 'R') +/* Trinidad and Tobago */ +#define COUNTRY_CODE_TT (((uint16_t) 'T' << 8) | (uint16_t) 'T') +/* Tuvalu */ +#define COUNTRY_CODE_TV (((uint16_t) 'T' << 8) | (uint16_t) 'V') +/* Taiwan */ +#define COUNTRY_CODE_TW (((uint16_t) 'T' << 8) | (uint16_t) 'W') +/* Tanzania */ +#define COUNTRY_CODE_TZ (((uint16_t) 'T' << 8) | (uint16_t) 'Z') +/* Ukraine */ +#define COUNTRY_CODE_UA (((uint16_t) 'U' << 8) | (uint16_t) 'A') +/* Ugnada */ +#define COUNTRY_CODE_UG (((uint16_t) 'U' << 8) | (uint16_t) 'G') +/* US */ +#define COUNTRY_CODE_US (((uint16_t) 'U' << 8) | (uint16_t) 'S') +/* Uruguay */ +#define COUNTRY_CODE_UY (((uint16_t) 'U' << 8) | (uint16_t) 'Y') +/* Uzbekistan */ +#define COUNTRY_CODE_UZ (((uint16_t) 'U' << 8) | (uint16_t) 'Z') +/* Vatican (Holy See) */ +#define COUNTRY_CODE_VA (((uint16_t) 'V' << 8) | (uint16_t) 'A') +/* Saint Vincent and the Grenadines */ +#define COUNTRY_CODE_VC (((uint16_t) 'V' << 8) | (uint16_t) 'C') +/* Venezuela */ +#define COUNTRY_CODE_VE (((uint16_t) 'V' << 8) | (uint16_t) 'E') +/* British Virgin Islands */ +#define COUNTRY_CODE_VG (((uint16_t) 'V' << 8) | (uint16_t) 'G') +/* US Virgin Islands */ +#define COUNTRY_CODE_VI (((uint16_t) 'V' << 8) | (uint16_t) 'I') +/* Vietnam */ +#define COUNTRY_CODE_VN (((uint16_t) 'V' << 8) | (uint16_t) 'N') +/* Vanuatu */ +#define COUNTRY_CODE_VU (((uint16_t) 'V' << 8) | (uint16_t) 'U') +/* Samoa */ +#define COUNTRY_CODE_WS (((uint16_t) 'W' << 8) | (uint16_t) 'S') +/* Yemen */ +#define COUNTRY_CODE_YE (((uint16_t) 'Y' << 8) | (uint16_t) 'E') +/* Mayotte (France) */ +#define COUNTRY_CODE_YT (((uint16_t) 'Y' << 8) | (uint16_t) 'T') +/* South Africa */ +#define COUNTRY_CODE_ZA (((uint16_t) 'Z' << 8) | (uint16_t) 'A') +/* Zambia */ +#define COUNTRY_CODE_ZM (((uint16_t) 'Z' << 8) | (uint16_t) 'M') +/* Zimbabwe */ +#define COUNTRY_CODE_ZW (((uint16_t) 'Z' << 8) | (uint16_t) 'W') +/* Default country domain */ +#define COUNTRY_CODE_DF (((uint16_t) 'D' << 8) | (uint16_t) 'F') +/* World Wide */ +#define COUNTRY_CODE_WW (((uint16_t) '0' << 8) | (uint16_t) '0') + + +/* dot11RegDomainsSupportValue */ +#define MIB_REG_DOMAIN_FCC 0x10 /* FCC (US) */ +#define MIB_REG_DOMAIN_IC 0x20 /* IC or DOC (Canada) */ +#define MIB_REG_DOMAIN_ETSI 0x30 /* ETSI (Europe) */ +#define MIB_REG_DOMAIN_SPAIN 0x31 /* Spain */ +#define MIB_REG_DOMAIN_FRANCE 0x32 /* France */ +#define MIB_REG_DOMAIN_JAPAN 0x40 /* MPHPT (Japan) */ +#define MIB_REG_DOMAIN_OTHER 0x00 /* other */ + +/*2.4G*/ +#define BAND_2G4_LOWER_BOUND 1 +#define BAND_2G4_UPPER_BOUND 14 +/*5G SubBand FCC spec*/ +#define UNII1_LOWER_BOUND 36 +#define UNII1_UPPER_BOUND 48 +#define UNII2A_LOWER_BOUND 52 +#define UNII2A_UPPER_BOUND 64 +#define UNII2C_LOWER_BOUND 100 +#define UNII2C_UPPER_BOUND 144 +#define UNII3_LOWER_BOUND 149 +#define UNII3_UPPER_BOUND 165 + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +#define POWER_LIMIT_TABLE_NULL 0xFFFF +#define MAX_TX_POWER 63 +#define MIN_TX_POWER -64 + +#define MAX_CMD_SUPPORT_160NC_CHANNEL_NUM 12 /* BW160NC combination NUM */ +#define MAX_CMD_SUPPORT_FCC_CHANNEL_NUM 60 +#define MAX_CMD_SUPPORT_CHANNEL_NUM \ + (MAX_CMD_SUPPORT_FCC_CHANNEL_NUM \ + + MAX_CMD_SUPPORT_160NC_CHANNEL_NUM + 1) +/* FCC sub-band channel + BW160NC channel + CH50 for BW160C */ +#endif + +#if (CFG_SUPPORT_SINGLE_SKU == 1) +/* ARRAY_SIZE(mtk_2ghz_channels) + ARRAY_SIZE(mtk_5ghz_channels) */ +#define MAX_SUPPORTED_CH_COUNT (MAX_CHN_NUM) +#define REG_RULE_LIGHT(start, end, bw, reg_flags) \ + REG_RULE(start, end, bw, 0, 0, reg_flags) +#endif + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +enum ENUM_POWER_LIMIT { + PWR_LIMIT_CCK = 0, + PWR_LIMIT_20M_L = 1, + PWR_LIMIT_20M_H = 2, + PWR_LIMIT_40M_L = 3, + PWR_LIMIT_40M_H = 4, + PWR_LIMIT_80M_L = 5, + PWR_LIMIT_80M_H = 6, + PWR_LIMIT_160M_L = 7, + PWR_LIMIT_160M_H = 8, + PWR_LIMIT_NUM +}; + +#endif + +enum ENUM_POWER_LIMIT_SUBBAND { + POWER_LIMIT_2G4 = 0, + POWER_LIMIT_UNII1 = 1, + POWER_LIMIT_UNII2A = 2, + POWER_LIMIT_UNII2C = 3, + POWER_LIMIT_UNII3 = 4, + POWER_LIMIT_SUBAND_NUM +}; + +/* Define channel offset in unit of 5MHz bandwidth */ +enum ENUM_CHNL_SPAN { + CHNL_SPAN_5 = 1, + CHNL_SPAN_10 = 2, + CHNL_SPAN_20 = 4, + CHNL_SPAN_40 = 8 +}; + +/* Define BSS operating bandwidth */ +enum ENUM_CHNL_BW { + CHNL_BW_20, + CHNL_BW_20_40, + CHNL_BW_10, + CHNL_BW_5 +}; + +#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. + */ +struct DOMAIN_SUBBAND_INFO { + uint8_t ucRegClass; + enum ENUM_BAND eBand; + enum ENUM_CHNL_SPAN eChannelSpan; + uint8_t ucFirstChannelNum; + uint8_t ucNumChannels; + enum ENUM_CHNL_BW eChannelBw; + u_int8_t fgDfsNeeded; + u_int8_t fgIbssProhibited; +}; + +/* Use it as all available channel list for STA */ +struct DOMAIN_INFO_ENTRY { + uint16_t u2CountryCode; + uint16_t u2MibRegDomainValue; + + /* If different attributes, put them into different rSubBands. + * For example, DFS shall be used or not. + */ + struct DOMAIN_SUBBAND_INFO rSubBand[MAX_SUBBAND_NUM]; +}; + +#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. + */ +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. + */ + uint8_t ucRegClass; /* Regulation class for 20MHz */ + uint8_t ucBand; /* Type: ENUM_BAND_T */ + uint8_t ucChannelSpan; /* Type: ENUM_CHNL_SPAN_T */ + uint8_t ucFirstChannelNum; + uint8_t ucNumChannels; + uint8_t fgDfs; /* Type: BOOLEAN*/ +}; + +/* Use it as all available channel list for STA */ +struct DOMAIN_INFO_ENTRY { + uint16_t *pu2CountryGroup; + uint32_t u4CountryNum; + + /* If different attributes, put them into different rSubBands. + * For example, DFS shall be used or not. + */ + struct DOMAIN_SUBBAND_INFO rSubBand[MAX_SUBBAND_NUM]; +}; +#endif + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +#if (CFG_SUPPORT_SINGLE_SKU == 1) +/* + * MT_TxPwrLimit.dat format + */ +#define SECTION_PREFIX (0x23232323) +#define ELEMENT_PREFIX (0xffff) +#define VERSION (0x00000001) +#define SIZE_OF_VERSION 4 +#define WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE 204800 + +struct tx_pwr_element { + uint16_t prefix; + uint8_t channel_num; + uint8_t reserved; + + /*the followings are in unit: 0.5 dbm*/ + + uint8_t tx_pwr_dsss_cck; + uint8_t tx_pwr_dsss_bpsk; + + uint8_t tx_pwr_ofdm_bpsk; /* 6M, 9M */ + uint8_t tx_pwr_ofdm_qpsk; /* 12M, 18M */ + uint8_t tx_pwr_ofdm_16qam; /* 24M, 36M */ + uint8_t tx_pwr_ofdm_48m; + uint8_t tx_pwr_ofdm_54m; + + uint8_t tx_pwr_ht20_bpsk; /* MCS0*/ + uint8_t tx_pwr_ht20_qpsk; /* MCS1, MCS2*/ + uint8_t tx_pwr_ht20_16qam; /* MCS3, MCS4*/ + uint8_t tx_pwr_ht20_mcs5; /* MCS5*/ + uint8_t tx_pwr_ht20_mcs6; /* MCS6*/ + uint8_t tx_pwr_ht20_mcs7; /* MCS7*/ + + uint8_t tx_pwr_ht40_bpsk; /* MCS0*/ + uint8_t tx_pwr_ht40_qpsk; /* MCS1, MCS2*/ + uint8_t tx_pwr_ht40_16qam; /* MCS3, MCS4*/ + uint8_t tx_pwr_ht40_mcs5; /* MCS5*/ + uint8_t tx_pwr_ht40_mcs6; /* MCS6*/ + uint8_t tx_pwr_ht40_mcs7; /* MCS7*/ + + uint8_t tx_pwr_vht20_bpsk; /* MCS0*/ + uint8_t tx_pwr_vht20_qpsk; /* MCS1, MCS2*/ + uint8_t tx_pwr_vht20_16qam; /* MCS3, MCS4*/ + uint8_t tx_pwr_vht20_64qam; /* MCS5, MCS6*/ + uint8_t tx_pwr_vht20_mcs7; + uint8_t tx_pwr_vht20_mcs8; + uint8_t tx_pwr_vht20_mcs9; + + uint8_t tx_pwr_vht_40; + uint8_t tx_pwr_vht_80; + uint8_t tx_pwr_vht_160nc; + uint8_t tx_pwr_lg_40; + uint8_t tx_pwr_lg_80; + + uint8_t tx_pwr_1ss_delta; + uint8_t reserved_3[3]; +}; + +struct tx_pwr_section { + uint32_t prefix; + uint32_t country_code; +}; +#endif /*#if (CFG_SUPPORT_SINGLE_SKU == 1)*/ + +/* [TODO] To modify the following definition before using: + * set power limit with high/low rate + */ +#if 1 +/* CMD_SET_PWR_LIMIT_TABLE */ +struct CHANNEL_POWER_LIMIT { + uint8_t ucCentralCh; + int8_t cPwrLimitCCK; + int8_t cPwrLimit20; + int8_t cPwrLimit40; + int8_t cPwrLimit80; + int8_t cPwrLimit160; + uint8_t ucFlag; + uint8_t aucReserved[1]; +}; + +struct COUNTRY_CHANNEL_POWER_LIMIT { + uint8_t aucCountryCode[2]; + uint8_t ucCountryFlag; + uint8_t ucChannelNum; + uint8_t aucReserved[4]; + struct CHANNEL_POWER_LIMIT rChannelPowerLimit[80]; +}; + +#define CHANNEL_PWR_LIMIT(_channel, _pwrLimit_cck, _pwrLimit_bw20, \ + _pwrLimit_bw40, _pwrLimit_bw80, _pwrLimit_bw160, _ucFlag) \ + { \ + .ucCentralCh = (_channel), \ + .cPwrLimitCCK = (_pwrLimit_cck), \ + .cPwrLimit20 = (_pwrLimit_bw20), \ + .cPwrLimit40 = (_pwrLimit_bw40), \ + .cPwrLimit80 = (_pwrLimit_bw80), \ + .cPwrLimit160 = (_pwrLimit_bw160), \ + .ucFlag = (_ucFlag), \ + .aucReserved = {0} \ +} +#endif + +struct COUNTRY_POWER_LIMIT_TABLE_DEFAULT { + uint8_t aucCountryCode[2]; + /* 0: ch 1 ~14 + * 1: ch 36 ~48 + * 2: ch 52 ~64 + * 3: ch 100 ~144 + * 4: ch 149 ~165 + */ + int8_t aucPwrLimitSubBand[POWER_LIMIT_SUBAND_NUM]; + /* bit0: cPwrLimit2G4, bit1: cPwrLimitUnii1; bit2: cPwrLimitUnii2A;*/ + /* bit3: cPwrLimitUnii2C; bit4: cPwrLimitUnii3; mW: 0, mW\MHz : 1 */ + uint8_t ucPwrUnit; +}; + +struct COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION { + uint8_t aucCountryCode[2]; + uint8_t ucCentralCh; + int8_t aucPwrLimit[PWR_LIMIT_NUM]; +}; + +struct SUBBAND_CHANNEL { + uint8_t ucStartCh; + uint8_t ucEndCh; + uint8_t ucInterval; + uint8_t ucReserved; +}; + +#endif /* CFG_SUPPORT_PWR_LIMIT_COUNTRY */ + +#if (CFG_SUPPORT_SINGLE_SKU == 1) +/* + * Event from chip for single sku + */ +struct SINGLE_SKU_INFO { + uint32_t u4EfuseCountryCode; + uint8_t isEfuseValid; + uint8_t ucReserved[7]; +}; + + +/* + * channel structure + */ +struct channel { + u16 chNum; + u8 reserved[2]; + u32 flags; /*enum ieee80211_channel_flags*/ +}; + +struct acctive_channel_list { + u8 n_channels_2g; + u8 n_channels_5g; + u8 ucReserved[2]; + struct channel channels[0]; +}; + +/* + * single sku control structure + */ +enum regd_state { + REGD_STATE_UNDEFINED, + REGD_STATE_INIT, + REGD_STATE_SET_WW_CORE, + REGD_STATE_SET_COUNTRY_USER, + REGD_STATE_SET_COUNTRY_DRIVER, + REGD_STATE_SET_COUNTRY_IE, + REGD_STATE_INVALID +}; + +enum regd_control_flag { + REGD_CTRL_FLAG_SUPPORT_LOCAL_REGD_DB = (0x1 << 0) +}; + +struct mtk_regd_control { + u_int8_t en; + u_int8_t isEfuseCountryCodeUsed; + enum regd_state state; + u32 alpha2; + u32 tmp_alpha2; /*store country code set by iwpriv "country XX"*/ + u32 flag; /*enum regd_control_flag*/ + struct GLUE_INFO *pGlueInfo; /*wlan GlueInfo*/ + u8 n_channel_active_2g; + u8 n_channel_active_5g; + struct channel channels[MAX_SUPPORTED_CH_COUNT]; + enum nl80211_dfs_regions dfs_region; +}; + +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) +struct mtk_regdomain { + char country_code[4]; + const struct ieee80211_regdomain *prRegdRules; +}; +#endif + +#endif +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +#define CAL_CH_OFFSET_80M(_PRIMARY_CH, _CENTRAL_CH) \ + (((_PRIMARY_CH - _CENTRAL_CH) + 6) >> 2) + +#define CAL_CH_OFFSET_160M(_PRIMARY_CH, _CENTRAL_CH) \ + (((_PRIMARY_CH - _CENTRAL_CH) + 14) >> 2) + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +struct DOMAIN_INFO_ENTRY *rlmDomainGetDomainInfo( + struct ADAPTER *prAdapter); + +void +rlmDomainGetChnlList(struct ADAPTER *prAdapter, + enum ENUM_BAND eSpecificBand, u_int8_t fgNoDfs, + uint8_t ucMaxChannelNum, uint8_t *pucNumOfChannel, + struct RF_CHANNEL_INFO *paucChannelList); + +void rlmDomainGetDfsChnls(struct ADAPTER *prAdapter, + uint8_t ucMaxChannelNum, uint8_t *pucNumOfChannel, + struct RF_CHANNEL_INFO *paucChannelList); + +void rlmDomainSendCmd(struct ADAPTER *prAdapter); + +void rlmDomainSendDomainInfoCmd(struct ADAPTER *prAdapter); + +void rlmDomainSendPassiveScanInfoCmd(struct ADAPTER + *prAdapter); + +uint32_t rlmDomainSupOperatingClassIeFill(uint8_t *pBuf); + +u_int8_t rlmDomainCheckChannelEntryValid(struct ADAPTER + *prAdapter, uint8_t ucCentralCh); + +uint8_t rlmDomainGetCenterChannel(enum ENUM_BAND eBand, + uint8_t ucPriChannel, + enum ENUM_CHNL_EXT eExtend); + +u_int8_t rlmDomainIsValidRfSetting(struct ADAPTER *prAdapter, + enum ENUM_BAND eBand, uint8_t ucPriChannel, + enum ENUM_CHNL_EXT eExtend, + enum ENUM_CHANNEL_WIDTH eChannelWidth, + uint8_t ucChannelS1, uint8_t ucChannelS2); + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +u_int8_t +rlmDomainCheckPowerLimitValid(struct ADAPTER *prAdapter, + struct COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION + rPowerLimitTableConfiguration, + uint8_t ucPwrLimitNum); + +void rlmDomainCheckCountryPowerLimitTable( + struct ADAPTER *prAdapter); + +uint16_t rlmDomainPwrLimitDefaultTableDecision( + struct ADAPTER *prAdapter, uint16_t u2CountryCode); + +void rlmDomainSendPwrLimitCmd(struct ADAPTER *prAdapter); +#endif + +#if (CFG_SUPPORT_SINGLE_SKU == 1) +extern struct ieee80211_supported_band mtk_band_2ghz; +extern struct ieee80211_supported_band mtk_band_5ghz; + +u_int8_t rlmDomainIsCtrlStateEqualTo(enum regd_state state); +u_int8_t rlmDomainIsUsingLocalRegDomainDataBase(void); +enum regd_state rlmDomainStateTransition(enum regd_state + request_state, struct regulatory_request *pRequest); +void rlmDomainSetCountryCode(char *alpha2, + u8 size_of_alpha2); +void rlmDomainSetDfsRegion(enum nl80211_dfs_regions + dfs_region); +enum nl80211_dfs_regions rlmDomainGetDfsRegion(void); +void rlmDomainResetCtrlInfo(u_int8_t force); +void rlmDomainAddActiveChannel(u8 band); +u8 rlmDomainGetActiveChannelCount(u8 band); +void rlmDomainParsingChannel(IN struct wiphy *pWiphy); +struct channel *rlmDomainGetActiveChannels(void); +void rlmExtractChannelInfo(u32 max_ch_count, + struct acctive_channel_list *prBuff); +void regd_set_using_local_regdomain_db(void); +void rlmDomainSetDefaultCountryCode(void); +enum regd_state rlmDomainGetCtrlState(void); +bool rlmDomainIsSameCountryCode(char *alpha2, + u8 size_of_alpha2); +const struct ieee80211_regdomain +*rlmDomainSearchRegdomainFromLocalDataBase(char *alpha2); +struct GLUE_INFO *rlmDomainGetGlueInfo(void); +bool rlmDomainIsEfuseUsed(void); +uint8_t rlmDomainGetChannelBw(uint8_t channelNum); + +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) +extern const struct mtk_regdomain *g_prRegRuleTable[]; +#endif + +#endif + +const struct ieee80211_regdomain +*rlmDomainGetLocalDefaultRegd(void); +void rlmDomainSendInfoToFirmware(IN struct ADAPTER + *prAdapter); +uint32_t rlmDomainExtractSingleSkuInfoFromFirmware( + IN struct ADAPTER *prAdapter, IN uint8_t *pucEventBuf); +u_int8_t regd_is_single_sku_en(void); +u_int8_t rlmDomainIsLegalChannel(struct ADAPTER *prAdapter, + enum ENUM_BAND eBand, uint8_t ucChannel); +enum ENUM_CHNL_EXT rlmSelectSecondaryChannelType( + struct ADAPTER *prAdapter, enum ENUM_BAND band, + u8 primary_ch); +extern void mtk_reg_notify(IN struct wiphy *pWiphy, + IN struct regulatory_request *pRequest); +void rlmDomainOidSetCountry(IN struct ADAPTER *prAdapter, + char *country, u8 size_of_country); +u32 rlmDomainGetCountryCode(void); +u32 rlmDomainGetTempCountryCode(void); +void rlmDomainAssert(u_int8_t cond); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _RLM_DOMAIN_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rlm_obss.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rlm_obss.h new file mode 100644 index 0000000000000..40f60b92fd327 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rlm_obss.h @@ -0,0 +1,148 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/ + * include/mgmt/rlm_obss.h#1 + */ + +/*! \file "rlm_obss.h" + * \brief + */ + + +#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 */ +enum ENUM_SYS_PCO_PHASE { + SYS_PCO_PHASE_DISABLED = 0, + SYS_PCO_PHASE_20M, + SYS_PCO_PHASE_40M +}; + +/******************************************************************************* + * P U B 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(struct ADAPTER *prAdapter); + +void rlmObssScanDone(struct ADAPTER *prAdapter, + struct MSG_HDR *prMsgHdr); + +void rlmObssTriggerScan(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _RLM_OBSS_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rlm_protection.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rlm_protection.h new file mode 100644 index 0000000000000..ed542da978e76 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rlm_protection.h @@ -0,0 +1,142 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/ + * include/mgmt/rlm_protection.h#1 + */ + +/*! \file "rlm_protection.h" + * \brief + */ + +#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 + ******************************************************************************* + */ +enum ENUM_SYS_PROTECT_MODE { + 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 +}; + +/* This definition follows HT Protection field of HT Operation IE */ +enum ENUM_HT_PROTECT_MODE { + HT_PROTECT_MODE_NONE = 0, + HT_PROTECT_MODE_NON_MEMBER, + HT_PROTECT_MODE_20M, + HT_PROTECT_MODE_NON_HT, + + HT_PROTECT_MODE_NUM +}; + +enum ENUM_GF_MODE { + GF_MODE_NORMAL = 0, + GF_MODE_PROTECT, + GF_MODE_DISALLOWED, + + GF_MODE_NUM +}; + +enum ENUM_RIFS_MODE { + RIFS_MODE_NORMAL = 0, + RIFS_MODE_DISALLOWED, + + RIFS_MODE_NUM +}; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _RLM_PROTECTION_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rlm_txpwr_init.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rlm_txpwr_init.h new file mode 100644 index 0000000000000..75f130a9c8816 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rlm_txpwr_init.h @@ -0,0 +1,1595 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/ + * include/mgmt/rlm_txpwr_init.h#1 + */ + +/*! \file "rlm_txpwr_init.h" + * \brief + */ + +#ifndef _RLM_TXPWR_INIT_H +#define _RLM_TXPWR_INIT_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +/*Support Tx Power Range : 63~ -64 (unit : 0.5dBm)*/ + +#define PWR_LIMIT_2G4_IN_MW_MHZ BIT(0) +#define PWR_LIMIT_UNII1_IN_MW_MHZ BIT(1) +#define PWR_LIMIT_UNII2A_IN_MW_MHZ BIT(2) +#define PWR_LIMIT_UNII2C_IN_MW_MHZ BIT(3) +#define PWR_LIMIT_UNII3_IN_MW_MHZ BIT(4) + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY +/*Set to MAX_TX_PWR = 63dBm if larger than it*/ +struct COUNTRY_POWER_LIMIT_TABLE_DEFAULT + g_rRlmPowerLimitDefault[] = { + + { {'A', 'R'} + , {60, 34, 48, 48, 60} + , 0 + } + , + { {'A', 'U'} + , {63, 46, 46, 60, 63} + , 0 + } + , + { {'N', 'Z'} + , {63, 46, 46, 60, 63} + , 0 + } + , + { {'A', 'T'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'B', 'E'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'B', 'R'} + , {63, 46, 46, 60, 63} + , 0 + } + , + { {'B', 'G'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'C', 'A'} + , {60, 46, 48, 48, 60} + , 0 + } + , + { {'C', 'L'} + , {43, 43, 43, 63, 43} + , 0 + } + , + { {'C', 'N'} + , {40, 46, 46, 63, 63} + , 0 + } + , + { {'H', 'R'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'C', 'Z'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'D', 'K'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'D', 'M'} + , {60, 34, 46, 46, 60} + , 0 + } + , + { {'E', 'C'} + , {60, 34, 48, 48, 60} + , 0 + } + , + { {'E', 'G'} + , {40, 46, 46, 63, 46} + , 0 + } + , + { {'S', 'V'} + , {60, 34, 46, 46, 60} + , 0 + } + , + { {'F', 'I'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'F', 'R'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'G', 'R'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'H', 'N'} + , {60, 60, 48, 48, 60} + , 0 + } + , + { {'H', 'K'} + , {63, 46, 46, 60, 63} + , 0 + } + , + { {'H', 'U'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'I', 'S'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'I', 'N'} + , {63, 46, 46, 63, 46} + , 0 + } + , + { {'I', 'D'} + , {46, 63, 63, 63, 46} + , 0 + } + , + { {'I', 'E'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'I', 'L'} + , {40, 46, 46, 63, 63} + , 0 + } + , + { {'I', 'T'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'J', 'P'} + , {46, 46, 46, 46, 63} + , 0 + } + , + { {'K', 'R'} + , {46, 34, 46, 46, 46} + , 0 + } + , + { {'L', 'U'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'M', 'Y'} + , {54, 60, 60, 63, 60} + , 0 + } + , + { {'M', 'X'} + , {60, 46, 48, 63, 60} + , 0 + } + , + { {'N', 'L'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'N', 'O'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'O', 'M'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'P', 'K'} + , {40, 63, 63, 63, 40} + , 0 + } + , + { {'P', 'Y'} + , {60, 46, 46, 48, 60} + , 0 + } + , + { {'P', 'E'} + , {54, 46, 48, 42, 48} + , 0 + } + , + { {'P', 'H'} + , {48, 48, 48, 48, 48} + , 0 + } + , + { {'P', 'L'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'P', 'T'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'Q', 'A'} + , {40, 63, 63, 63, 40} + , 0 + } + , + { {'R', 'O'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'R', 'U'} + , {48, 40, 40, 60, 60} + , 0 + } + , + { {'S', 'A'} + , {40, 46, 46, 46, 46} + , 0 + } + , + { {'S', 'G'} + , {46, 40, 40, 60, 60} + , 0 + } + , + { {'S', 'K'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'S', 'I'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'Z', 'A'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'E', 'S'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'S', 'E'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'C', 'H'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'T', 'W'} + , {60, 48, 48, 48, 60} + , 0 + } + , + { {'T', 'H'} + , {40, 46, 46, 60, 60} + , 0 + } + , + { {'A', 'E'} + , {40, 46, 46, 60, 60} + , 0 + } + , + { {'G', 'B'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'U', 'Y'} + , {60, 34, 46, 46, 60} + , 0 + } + , + { {'U', 'S'} + , {60, 48, 48, 48, 60} + , 0 + } + , + { {'V', 'E'} + , {60, 46, 46, 63, 46} + , 0 + } + , + { {'V', 'N'} + , {40, 46, 46, 60, 34} + , 0 + } + , + { {'A', 'O'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'B', 'Z'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'B', 'J'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'B', 'T'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'B', 'O'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'B', 'I'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'C', 'M'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'C', 'F'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'T', 'D'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'K', 'M'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'C', 'D'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'C', 'G'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'C', 'I'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'D', 'J'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'G', 'Q'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'E', 'R'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'F', 'J'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'G', 'A'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'G', 'M'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'G', 'N'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'G', 'W'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'R', 'K'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'K', 'G'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'L', 'Y'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'M', 'G'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'M', 'L'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'N', 'R'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'N', 'C'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'S', 'T'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'S', 'C'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'S', 'L'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'S', 'B'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'S', 'O'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'S', 'R'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'S', 'Z'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'T', 'J'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'T', 'G'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'T', 'O'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'T', 'M'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'T', 'V'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'V', 'U'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'Y', 'E'} + , {40, 63, 63, 63, 63} + , 0 + } + , + { {'A', 'S'} + , {60, 34, 46, 48, 60} + , 0 + } + , + { {'A', 'I'} + , {60, 34, 48, 60, 60} + , 0 + } + , + { {'B', 'M'} + , {60, 34, 48, 48, 60} + , 0 + } + , + { {'K', 'Y'} + , {60, 34, 48, 60, 60} + , 0 + } + , + { {'G', 'U'} + , {60, 34, 48, 48, 60} + , 0 + } + , + { {'F', 'M'} + , {60, 34, 48, 48, 60} + , 0 + } + , + { {'P', 'R'} + , {60, 34, 46, 48, 60} + , 0 + } + , + { {'V', 'I'} + , {60, 34, 48, 48, 60} + , 0 + } + , + { {'A', 'Z'} + , {40, 34, 48, 60, 60} + , 0 + } + , + { {'B', 'W'} + , {40, 46, 46, 60, 60} + , 0 + } + , + { {'K', 'H'} + , {40, 46, 46, 48, 60} + , 0 + } + , + { {'C', 'X'} + , {63, 46, 46, 60, 63} + , 0 + } + , + { {'C', 'O'} + , {60, 34, 48, 48, 60} + , 0 + } + , + { {'C', 'R'} + , {60, 34, 48, 48, 60} + , 0 + } + , + { {'G', 'D'} + , {40, 46, 46, 60, 60} + , 0 + } + , + { {'G', 'T'} + , {40, 34, 48, 48, 60} + , 0 + } + , + { {'K', 'I'} + , {63, 46, 46, 60, 63} + , 0 + } + , + { {'L', 'B'} + , {40, 46, 46, 46, 46} + , 0 + } + , + { {'L', 'R'} + , {60, 46, 60, 63, 63} + , 0 + } + , + { {'M', 'N'} + , {46, 32, 46, 46, 58} + , 0 + } + , + { {'A', 'N'} + , {60, 34, 48, 48, 60} + , 0 + } + , + { {'N', 'I'} + , {60, 34, 48, 48, 60} + , 0 + } + , + { {'P', 'W'} + , {60, 60, 60, 60, 60} + , 0 + } + , + { {'W', 'S'} + , {40, 40, 40, 40, 60} + , 0 + } + , + { {'L', 'K'} + , {46, 46, 46, 46, 46} + , 0 + } + , + { {'T', 'T'} + , {60, 46, 46, 60, 60} + , 0 + } + , + { {'A', 'W'} + , {60, 46, 60, 60, 63} + , 0 + } + , + { {'L', 'A'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'U', 'G'} + , {40, 46, 46, 48, 60} + , 0 + } + , + { {'M', 'M'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'A', 'L'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'D', 'Z'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'A', 'D'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'B', 'Y'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'B', 'A'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'V', 'G'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'C', 'V'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'C', 'Y'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'E', 'E'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'E', 'T'} + , {40, 40, 40, 40, 63} + , 0 + } + , + { {'G', 'F'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'P', 'F'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'T', 'F'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'G', 'E'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'D', 'E'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'G', 'H'} + , {40, 34, 48, 60, 63} + , 0 + } + , + { {'G', 'P'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'I', 'Q'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'K', 'E'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'L', 'V'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'L', 'S'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'L', 'I'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'L', 'T'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'M', 'K'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'M', 'T'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'M', 'Q'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'M', 'R'} + , {40, 46, 46, 46, 63} + , 0 + } + , + { {'M', 'U'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'Y', 'T'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'M', 'D'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'M', 'C'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'M', 'E'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'M', 'S'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'R', 'E'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'M', 'F'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'S', 'M'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'S', 'N'} + , {40, 40, 40, 60, 63} + , 0 + } + , + { {'R', 'S'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'T', 'R'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'T', 'C'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'V', 'A'} + , {40, 46, 46, 60, 63} + , 0 + } + , + { {'A', 'M'} + , {40, 40, 40, 63, 63} + , 0 + } + , + { {'K', 'W'} + , {40, 46, 46, 63, 63} + , 0 + } + , + { {'M', 'A'} + , {40, 46, 46, 63, 63} + , 0 + } + , + { {'N', 'E'} + , {40, 46, 46, 63, 63} + , 0 + } + , + { {'T', 'N'} + , {40, 46, 46, 63, 63} + , 0 + } + , + { {'N', 'P'} + , {60, 46, 46, 63, 60} + , 0 + } + , + { {'A', 'F'} + , {40, 46, 63, 63, 63} + , 0 + } + , + { {'A', 'G'} + , {40, 46, 48, 63, 54} + , 0 + } + , + { {'B', 'S'} + , {63, 46, 60, 63, 63} + , 0 + } + , + { {'B', 'H'} + , {40, 46, 46, 63, 63} + , 0 + } + , + { {'B', 'B'} + , {40, 46, 48, 63, 54} + , 0 + } + , + { {'B', 'N'} + , {46, 46, 46, 63, 60} + , 0 + } + , + { {'M', 'V'} + , {40, 46, 46, 63, 40} + , 0 + } + , + { {'P', 'A'} + , {60, 34, 48, 63, 60} + , 0 + } + , + { {'Z', 'M'} + , {60, 46, 46, 63, 60} + , 0 + } + , + { {'J', 'O'} + , {40, 46, 63, 63, 46} + , 0 + } + , + { {'P', 'G'} + , {40, 46, 63, 63, 60} + , 0 + } + , + { {'B', 'F'} + , {40, 63, 63, 63, 60} + , 0 + } + , + { {'G', 'Y'} + , {60, 63, 63, 63, 60} + , 0 + } + , + { {'H', 'T'} + , {40, 63, 63, 63, 60} + , 0 + } + , + { {'J', 'M'} + , {54, 63, 63, 63, 57} + , 0 + } + , + { {'M', 'O'} + , {40, 63, 63, 63, 40} + , 0 + } + , + { {'M', 'W'} + , {60, 63, 63, 63, 60} + , 0 + } + , + { {'R', 'W'} + , {40, 63, 63, 63, 60} + , 0 + } + , + { {'K', 'N'} + , {40, 63, 63, 63, 60} + , 0 + } + , + { {'T', 'Z'} + , {40, 63, 63, 63, 40} + , 0 + } + , + { {'N', 'G'} + , {40, 63, 46, 63, 60} + , 0 + } + , + { {'B', 'D'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'D', 'O'} + , {63, 46, 46, 60, 63} + , 0 + } + , + { {'F', 'K'} + , {40, 46, 46, 60, 28} + , 0 + } + , + { {'K', 'Z'} + , {40, 34, 48, 60, 60} + , 0 + } + , + { {'M', 'Z'} + , {40, 34, 46, 48, 60} + , 0 + } + , + { {'N', 'A'} + , {40, 34, 46, 48, 60} + , 0 + } + , + { {'L', 'C'} + , {40, 34, 48, 48, 60} + , 0 + } + , + { {'V', 'C'} + , {40, 34, 46, 48, 60} + , 0 + } + , + { {'U', 'A'} + , {40, 46, 46, 46, 48} + , 0 + } + , + { {'U', 'Z'} + , {40, 48, 48, 48, 60} + , 0 + } + , + { {'Z', 'W'} + , {40, 34, 46, 48, 60} + , 0 + } + , + { {'M', 'P'} + , {60, 34, 46, 48, 60} + , 0 + } + , + { {'C', 'K'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'C', 'U'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'T', 'L'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'F', 'O'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'G', 'I'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'I', 'R'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'I', 'M'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'J', 'E'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'K', 'P'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'M', 'H'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'N', 'U'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'N', 'F'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'P', 'S'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'P', 'N'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'P', 'M'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'S', 'S'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'S', 'D'} + , {63, 63, 63, 63, 63} + , 0 + } + , + { {'S', 'Y'} + , {63, 63, 63, 63, 63} + , 0 + } + , +#if 1 /* Temp define as 6630 */ + { {'E', 'H'} + , {40, 46, 46, 63, 63} + , 0 + } + , + { {'G', 'G'} + , {63, 63, 63, 63, 63} + , 0 + } + , +#endif + + /*Default*/ + { {0, 0} + , {63, 63, 63, 63, 63} + , 0 + } +}; + +struct COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION + g_rRlmPowerLimitConfiguration[] = { + + { {'A', 'I'} + , 144, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'A', 'Z'} + , 144, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'B', 'W'} + , 144, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'G', 'D'} + , 144, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'L', 'B'} + , 144, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'L', 'R'} + , 144, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'W', 'S'} + , 165, {40, 40, 40, 40, 40, 40, 40, 40, 40} + } + , + { {'U', 'S'} + , 1, {39, 34, 32, 60, 60, 60, 60, 60, 60} + } + , + { {'U', 'S'} + , 6, {60, 60, 60, 60, 60, 60, 60, 60, 60} + } + , + { {'U', 'S'} + , 11, {39, 33, 32, 60, 60, 60, 60, 60, 60} + } + , + { {'U', 'S'} + , 3, {60, 60, 60, 31, 30, 60, 60, 60, 60} + } + , + { {'U', 'S'} + , 9, {60, 60, 60, 31, 30, 60, 60, 60, 60} + } + , + { {'U', 'S'} + , 36, {48, 36, 36, 48, 48, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 40, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 48, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 52, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 60, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 64, {48, 36, 36, 48, 48, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 100, {48, 37, 37, 48, 48, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 116, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 140, {48, 42, 42, 48, 48, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 149, {60, 41, 41, 60, 60, 60, 60, 60, 60} + } + , + { {'U', 'S'} + , 157, {60, 60, 60, 60, 60, 60, 60, 60, 60} + } + , + { {'U', 'S'} + , 165, {60, 42, 42, 60, 60, 60, 60, 60, 60} + } + , + { {'U', 'S'} + , 38, {48, 48, 48, 27, 27, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 46, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 54, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 62, {48, 48, 48, 28, 28, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 102, {48, 48, 48, 29, 29, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 110, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 134, {48, 48, 48, 41, 41, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 151, {60, 60, 60, 36, 36, 60, 60, 60, 60} + } + , + { {'U', 'S'} + , 159, {60, 60, 60, 60, 60, 60, 60, 60, 60} + } + , + { {'U', 'S'} + , 42, {48, 48, 48, 48, 48, 24, 24, 48, 48} + } + , + { {'U', 'S'} + , 58, {48, 48, 48, 48, 48, 26, 26, 48, 48} + } + , + { {'U', 'S'} + , 106, {48, 48, 48, 48, 48, 25, 25, 48, 48} + } + , + { {'U', 'S'} + , 122, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'U', 'S'} + , 155, {60, 60, 60, 60, 60, 36, 36, 60, 60} + } + , + { {'U', 'S'} + , 50, {48, 48, 48, 48, 48, 48, 48, 24, 24} + } + , + { {'U', 'S'} + , 114, {48, 48, 48, 48, 48, 48, 48, 24, 24} + } + , + { {'T', 'W'} + , 1, {39, 34, 32, 60, 60, 60, 60, 60, 60} + } + , + { {'T', 'W'} + , 6, {60, 60, 60, 60, 60, 60, 60, 60, 60} + } + , + { {'T', 'W'} + , 11, {39, 33, 32, 60, 60, 60, 60, 60, 60} + } + , + { {'T', 'W'} + , 3, {60, 60, 60, 31, 30, 60, 60, 60, 60} + } + , + { {'T', 'W'} + , 9, {60, 60, 60, 31, 30, 60, 60, 60, 60} + } + , + { {'T', 'W'} + , 36, {48, 36, 36, 48, 48, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 40, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 48, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 52, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 60, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 64, {48, 36, 36, 48, 48, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 100, {48, 37, 37, 48, 48, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 116, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 140, {48, 42, 42, 48, 48, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 149, {60, 41, 41, 60, 60, 60, 60, 60, 60} + } + , + { {'T', 'W'} + , 157, {60, 60, 60, 60, 60, 60, 60, 60, 60} + } + , + { {'T', 'W'} + , 165, {60, 42, 42, 60, 60, 60, 60, 60, 60} + } + , + { {'T', 'W'} + , 38, {48, 48, 48, 27, 27, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 46, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 54, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 62, {48, 48, 48, 28, 28, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 102, {48, 48, 48, 29, 29, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 110, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 134, {48, 48, 48, 41, 41, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 151, {60, 60, 60, 36, 36, 60, 60, 60, 60} + } + , + { {'T', 'W'} + , 159, {60, 60, 60, 60, 60, 60, 60, 60, 60} + } + , + { {'T', 'W'} + , 42, {48, 48, 48, 48, 48, 24, 24, 48, 48} + } + , + { {'T', 'W'} + , 58, {48, 48, 48, 48, 48, 26, 26, 48, 48} + } + , + { {'T', 'W'} + , 106, {48, 48, 48, 48, 48, 25, 25, 48, 48} + } + , + { {'T', 'W'} + , 122, {48, 48, 48, 48, 48, 48, 48, 48, 48} + } + , + { {'T', 'W'} + , 155, {60, 60, 60, 60, 60, 36, 36, 60, 60} + } + , + { {'T', 'W'} + , 50, {48, 48, 48, 48, 48, 48, 48, 24, 24} + } + , + { {'T', 'W'} + , 114, {48, 48, 48, 48, 48, 48, 48, 24, 24} + } + , + + /*Default*/ + { {0, 0} + , 165, {63, 63, 63, 63, 63, 63, 63, 63, 63} + } +}; + +#endif + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +#endif /* _RLM_TXPWR_INIT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/roaming_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/roaming_fsm.h new file mode 100644 index 0000000000000..81fd22f60e486 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/roaming_fsm.h @@ -0,0 +1,217 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: + */ + +/*! \file "roaming_fsm.h" + * \brief This file defines the FSM for Roaming MODULE. + * + * This file defines the FSM for Roaming MODULE. + */ + + +#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. */ +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP +#define ROAMING_ONE_AP_SKIP_TIMES 3 +#endif + +/* #define ROAMING_NO_SWING_RCPI_STEP 5 //rcpi */ +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +enum ENUM_ROAMING_FAIL_REASON { + ROAMING_FAIL_REASON_CONNLIMIT = 0, + ROAMING_FAIL_REASON_NOCANDIDATE, + ROAMING_FAIL_REASON_NUM +}; + +/* events of roaming between driver and firmware */ +enum ENUM_ROAMING_EVENT { + ROAMING_EVENT_START = 0, + ROAMING_EVENT_DISCOVERY, + ROAMING_EVENT_ROAM, + ROAMING_EVENT_FAIL, + ROAMING_EVENT_ABORT, + ROAMING_EVENT_NUM +}; + +enum ENUM_ROAMING_REASON { + ROAMING_REASON_POOR_RCPI = 0, + ROAMING_REASON_TX_ERR, /*Lowest rate, high PER*/ + ROAMING_REASON_RETRY, + ROAMING_REASON_NUM +}; + +struct CMD_ROAMING_TRANSIT { + uint16_t u2Event; + uint16_t u2Data; + uint16_t u2RcpiLowThreshold; + uint8_t ucIsSupport11B; + uint8_t aucReserved[1]; + enum ENUM_ROAMING_REASON eReason; + uint32_t u4RoamingTriggerTime; /*sec in mcu*/ + uint8_t aucReserved2[8]; +}; + + +struct CMD_ROAMING_CTRL { + uint8_t fgEnable; + uint8_t ucRcpiAdjustStep; + uint16_t u2RcpiLowThr; + uint8_t ucRoamingRetryLimit; + uint8_t ucRoamingStableTimeout; + uint8_t aucReserved[2]; +}; + +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP +struct CMD_ROAMING_SKIP_ONE_AP { + uint8_t fgIsRoamingSkipOneAP; + uint8_t aucReserved[3]; + uint8_t aucReserved2[8]; +}; +#endif + +enum ENUM_ROAMING_STATE { + ROAMING_STATE_IDLE = 0, + ROAMING_STATE_DECISION, + ROAMING_STATE_DISCOVERY, + ROAMING_STATE_REQ_CAND_LIST, + ROAMING_STATE_ROAM, + ROAMING_STATE_NUM +}; + +struct ROAMING_INFO { + u_int8_t fgIsEnableRoaming; + + enum ENUM_ROAMING_STATE eCurrentState; + + OS_SYSTIME rRoamingDiscoveryUpdateTime; + + u_int8_t fgDrvRoamingAllow; + struct TIMER rWaitCandidateTimer; +}; + +/******************************************************************************* + * P U B 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 struct ADAPTER *prAdapter); + +void roamingFsmUninit(IN struct ADAPTER *prAdapter); + +void roamingFsmSendCmd(IN struct ADAPTER *prAdapter, + IN struct CMD_ROAMING_TRANSIT *prTransit); + +void roamingFsmScanResultsUpdate(IN struct ADAPTER *prAdapter); + +void roamingFsmSteps(IN struct ADAPTER *prAdapter, + IN enum ENUM_ROAMING_STATE eNextState); + +void roamingFsmRunEventStart(IN struct ADAPTER *prAdapter); + +void roamingFsmRunEventDiscovery(IN struct ADAPTER *prAdapter, + IN struct CMD_ROAMING_TRANSIT *prTransit); + +void roamingFsmRunEventRoam(IN struct ADAPTER *prAdapter); + +void roamingFsmRunEventFail(IN struct ADAPTER *prAdapter, + IN uint32_t u4Reason); + +void roamingFsmRunEventAbort(IN struct ADAPTER *prAdapter); + +uint32_t roamingFsmProcessEvent(IN struct ADAPTER *prAdapter, + IN struct CMD_ROAMING_TRANSIT *prTransit); + + +#endif /* _ROAMING_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rsn.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rsn.h new file mode 100644 index 0000000000000..f7077ae2fe45f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/rsn.h @@ -0,0 +1,356 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: include/mgmt/rsn.h#1 + */ + +/*! \file rsn.h + * \brief The wpa/rsn related define, macro and structure are described here. + */ + +#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 RSN_CIPHER_SUITE_GROUP_NOT_USED 0x07AC0F00 +#if CFG_SUPPORT_CFG80211_AUTH +#define RSN_CIPHER_SUITE_GCMP 0x08AC0F00 +#define RSN_CIPHER_SUITE_GCMP_256 0x09AC0F00 +#define RSN_CIPHER_SUITE_CCMP_256 0x0AAC0F00 +#define RSN_CIPHER_SUITE_BIP_GMAC_128 0x0BAC0F00 +#define RSN_CIPHER_SUITE_BIP_GMAC_256 0x0CAC0F00 +#define RSN_CIPHER_SUITE_BIP_CMAC_256 0x0DAC0F00 +#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 +#define RSN_AKM_SUITE_FT_802_1X 0x03AC0F00 +#define RSN_AKM_SUITE_FT_PSK 0x04AC0F00 + +#if KERNEL_VERSION(4, 12, 0) < LINUX_VERSION_CODE +#ifndef LINUX_IEEE80211_H +#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03 +#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04 +#endif +#else +#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03 +#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04 +#endif + +#if CFG_SUPPORT_802_11W +#define RSN_AKM_SUITE_802_1X_SHA256 0x05AC0F00 +#define RSN_AKM_SUITE_PSK_SHA256 0x06AC0F00 +#endif +#if CFG_SUPPORT_CFG80211_AUTH +#define RSN_AKM_SUITE_SAE 0x08AC0F00 +#define RSN_AKM_SUITE_8021X_SUITE_B 0x0BAC0F00 +#define RSN_AKM_SUITE_8021X_SUITE_B_192 0x0CAC0F00 +#define RSN_AKM_SUITE_OWE 0x12AC0F00 +#endif + +#define WPA_AKM_SUITE_NONE 0x00F25000 +#define WPA_AKM_SUITE_802_1X 0x01F25000 +#define WPA_AKM_SUITE_PSK 0x02F25000 + +#define WFA_AKM_SUITE_OSEN 0x019A6F50 +/* this define should be in ieee80211.h, but kernel didn't update it. + * so we define here temporary + */ +#define WLAN_AKM_SUITE_OSEN 0x506f9a01 +#define WLAN_CIPHER_SUITE_NO_GROUP_ADDR 0x000fac07 + +/* The RSN IE len for associate request */ +#define ELEM_ID_RSN_LEN_FIXED 20 + +/* The WPA IE len for associate request */ +#define ELEM_ID_WPA_LEN_FIXED 22 + +#define MASK_RSNIE_CAP_PREAUTH BIT(0) + +#define GET_SELECTOR_TYPE(x) ((uint8_t)(((x) >> 24) & 0x000000FF)) +#define SET_SELECTOR_TYPE(x, y) (x = (((x) & 0x00FFFFFF) | \ + (((uint32_t)(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 */ +#if CFG_SUPPORT_SUITB +#define CIPHER_FLAG_GCMP256 0x00000080 /* BIT 7 */ +#endif + +#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 + +#define GTK_REKEY_CMD_MODE_OFFLOAD_ON 0 +#define GTK_REKEY_CMD_MODE_OFLOAD_OFF 1 +#define GTK_REKEY_CMD_MODE_SET_BCMC_PN 2 +#define GTK_REKEY_CMD_MODE_GET_BCMC_PN 3 +#define GTK_REKEY_CMD_MODE_RPY_OFFLOAD_ON 4 +#define GTK_REKEY_CMD_MODE_RPY_OFFLOAD_OFF 5 + +/******************************************************************************* + * 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) ((struct RSN_INFO_ELEM *) fp) +#define WPA_IE(fp) ((struct WPA_INFO_ELEM *) fp) + +#define ELEM_MAX_LEN_ASSOC_RSP_WSC_IE (32 - ELEM_HDR_LEN) +#define ELEM_MAX_LEN_TIMEOUT_IE (5) + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +u_int8_t rsnParseRsnIE(IN struct ADAPTER *prAdapter, + IN struct RSN_INFO_ELEM *prInfoElem, + OUT struct RSN_INFO *prRsnInfo); + +u_int8_t rsnParseWpaIE(IN struct ADAPTER *prAdapter, + IN struct WPA_INFO_ELEM *prInfoElem, + OUT struct RSN_INFO *prWpaInfo); + +u_int8_t rsnSearchSupportedCipher(IN struct ADAPTER + *prAdapter, + IN uint32_t u4Cipher, OUT uint32_t *pu4Index); + +u_int8_t rsnIsSuitableBSS(IN struct ADAPTER *prAdapter, + IN struct RSN_INFO *prBssRsnInfo); + +u_int8_t rsnSearchAKMSuite(IN struct ADAPTER *prAdapter, + IN uint32_t u4AkmSuite, OUT uint32_t *pu4Index); + +u_int8_t rsnPerformPolicySelection(IN struct ADAPTER + *prAdapter, + IN struct BSS_DESC *prBss); + +void rsnGenerateWpaNoneIE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +void rsnGenerateWPAIE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +void rsnGenerateRSNIE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +u_int8_t +rsnParseCheckForWFAInfoElem(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, OUT uint8_t *pucOuiType, + OUT uint16_t *pu2SubTypeVersion); + +#if CFG_SUPPORT_AAA +void rsnParserCheckForRSNCCMPPSK(struct ADAPTER *prAdapter, + struct RSN_INFO_ELEM *prIe, + struct STA_RECORD *prStaRec, + uint16_t *pu2StatusCode); +#endif + +void rsnTkipHandleMICFailure(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prSta, + IN u_int8_t fgErrorKeyType); + +void rsnSelectPmkidCandidateList(IN struct ADAPTER + *prAdapter, IN struct BSS_DESC *prBssDesc); + +void rsnUpdatePmkidCandidateList(IN struct ADAPTER + *prAdapter, IN struct BSS_DESC *prBssDesc); + +u_int8_t rsnSearchPmkidEntry(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBssid, OUT uint32_t *pu4EntryIndex); + +u_int8_t rsnCheckPmkidCandicate(IN struct ADAPTER + *prAdapter); + +void rsnCheckPmkidCache(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBss); + +void rsnGeneratePmkidIndication(IN struct ADAPTER + *prAdapter); + +void rsnIndicatePmkidCand(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr); +#if CFG_SUPPORT_WPS2 +void rsnGenerateWSCIE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); +#endif + +#if CFG_SUPPORT_802_11W +uint32_t rsnCheckBipKeyInstalled(IN struct ADAPTER + *prAdapter, IN struct STA_RECORD *prStaRec); + +uint8_t rsnCheckSaQueryTimeout(IN struct ADAPTER + *prAdapter); + +void rsnStartSaQueryTimer(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr); + +void rsnStartSaQuery(IN struct ADAPTER *prAdapter); + +void rsnStopSaQuery(IN struct ADAPTER *prAdapter); + +void rsnSaQueryRequest(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +void rsnSaQueryAction(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +uint16_t rsnPmfCapableValidation(IN struct ADAPTER + *prAdapter, IN struct BSS_INFO *prBssInfo, + IN struct STA_RECORD *prStaRec); + +void rsnPmfGenerateTimeoutIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +void rsnApStartSaQuery(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +void rsnApSaQueryAction(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +#endif /* CFG_SUPPORT_802_11W */ + +#if CFG_SUPPORT_AAA +void rsnGenerateWSCIEForAssocRsp(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); +#endif + +u_int8_t rsnParseOsenIE(struct ADAPTER *prAdapter, + struct IE_WFA_OSEN *prInfoElem, + struct RSN_INFO *prOsenInfo); + +u_int8_t rsnCheckSecurityModeChanged(struct ADAPTER + *prAdapter, struct BSS_INFO *prBssInfo, + struct BSS_DESC *prBssDesc); + +uint32_t rsnCalculateFTIELen(struct ADAPTER *prAdapter, uint8_t ucBssIdx, + struct STA_RECORD *prStaRec); + +void rsnGenerateFTIE(IN struct ADAPTER *prAdapter, + IN OUT struct MSDU_INFO *prMsduInfo); + +#if CFG_SUPPORT_OWE +void rsnGenerateOWEIE(IN struct ADAPTER *prAdapter, + IN OUT struct MSDU_INFO *prMsduInfo); + +uint32_t rsnCalOweIELen(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, struct STA_RECORD *prStaRec); +#endif + + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _RSN_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/scan.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/scan.h new file mode 100644 index 0000000000000..9e8b1b69bbf47 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/scan.h @@ -0,0 +1,950 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: @(#) + */ + +/*! \file "scan.h" + * \brief + * + */ + + +#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(struct BSS_DESC))) + +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP +#define SCN_ROAM_MAX_BUFFER_SIZE \ + (CFG_MAX_NUM_ROAM_BSS_LIST * ALIGN_4(sizeof(struct ROAM_BSS_DESC))) +#endif + +/* Remove SCAN result except the connected one. */ +#define SCN_RM_POLICY_EXCLUDE_CONNECTED BIT(0) + +/* Remove the timeout one */ +#define SCN_RM_POLICY_TIMEOUT BIT(1) + +/* Remove the oldest one with hidden ssid */ +#define SCN_RM_POLICY_OLDEST_HIDDEN BIT(2) + +/* 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_SMART_WEAKEST BIT(3) + +/* Remove entire SCAN result */ +#define SCN_RM_POLICY_ENTIRE BIT(4) + +/* Remove SCAN result except the specific one. */ +#define SCN_RM_POLICY_EXCLUDE_SPECIFIC_SSID BIT(5) + +/* This is used by POLICY SMART WEAKEST, If exceed this value, remove weakest + * struct BSS_DESC with same SSID first in large network. + */ +#define SCN_BSS_DESC_SAME_SSID_THRESHOLD 20 + +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP +#define REMOVE_TIMEOUT_TWO_DAY (60*60*24*2) +#endif + +#if 1 +#define SCN_BSS_DESC_REMOVE_TIMEOUT_SEC 30 +#define SCN_BSS_DESC_STALE_SEC 20 /* Scan Request Timeout */ +#if CFG_ENABLE_WIFI_DIRECT +#if CFG_SUPPORT_WFD +/* For WFD scan need about 15s. */ +#define SCN_BSS_DESC_STALE_SEC_WFD 20 +#endif +#endif + +#else +/* Second. This is used by POLICY TIMEOUT, If exceed this + * value, remove timeout struct BSS_DESC. + */ +#define SCN_BSS_DESC_REMOVE_TIMEOUT_SEC 5 +#endif + +#define SCN_PROBE_DELAY_MSEC 0 + +#define SCN_ADHOC_BSS_DESC_TIMEOUT_SEC 5 /* Second. */ +#if CFG_ENABLE_WIFI_DIRECT +#if CFG_SUPPORT_WFD + /* Second. For WFD scan timeout. */ +#define SCN_ADHOC_BSS_DESC_TIMEOUT_SEC_WFD 20 +#endif +#endif + +#define SCAN_DONE_DIFFERENCE 3 + +/* Full2Partial */ +/* Define a full scan as scan channel number larger than this number */ +#define SCAN_FULL2PARTIAL_CHANNEL_NUM (25) +#define SCAN_CHANNEL_BITMAP_ARRAY_LEN (8) +#define BITS_OF_UINT (32) +#define BITS_OF_BYTE (8) + +/* dwell time setting, should align FW setting */ +#define SCAN_CHANNEL_DWELL_TIME_MIN_MSEC (42) + +/*----------------------------------------------------------------------------*/ +/* 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) /* two probe req will be sent, wildcard and specified */ +#define SCAN_REQ_SSID_SPECIFIED_ONLY \ + BIT(3) /* only a specified ssid probe request will be sent */ + +/*----------------------------------------------------------------------------*/ +/* Support Multiple SSID SCAN */ +/*----------------------------------------------------------------------------*/ +#define SCN_SSID_MAX_NUM CFG_SCAN_SSID_MAX_NUM +#define SCN_SSID_MATCH_MAX_NUM CFG_SCAN_SSID_MATCH_MAX_NUM + +#if CFG_SUPPORT_AGPS_ASSIST +#define SCN_AGPS_AP_LIST_MAX_NUM 32 +#endif + +#define SCN_BSS_JOIN_FAIL_CNT_RESET_SEC 15 +#define SCN_BSS_JOIN_FAIL_RESET_STEP 2 + +#if CFG_SUPPORT_BATCH_SCAN +/*----------------------------------------------------------------------------*/ +/* SCAN_BATCH_REQ */ +/*----------------------------------------------------------------------------*/ +#define SCAN_BATCH_REQ_START BIT(0) +#define SCAN_BATCH_REQ_STOP BIT(1) +#define SCAN_BATCH_REQ_RESULT BIT(2) +#endif + +/* Support AP Setection */ +#define SCN_BSS_JOIN_FAIL_THRESOLD 4 + +#define SCN_CTRL_SCAN_CHANNEL_LISTEN_TIME_ENABLE BIT(1) +#define SCN_CTRL_IGNORE_AIS_FIX_CHANNEL BIT(1) +#define SCN_CTRL_ENABLE BIT(0) + +#define SCN_CTRL_DEFAULT_SCAN_CTRL SCN_CTRL_IGNORE_AIS_FIX_CHANNEL + +#define SCN_SCAN_DONE_PRINT_BUFFER_LENGTH 200 +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +enum ENUM_SCAN_TYPE { + SCAN_TYPE_PASSIVE_SCAN = 0, + SCAN_TYPE_ACTIVE_SCAN, + SCAN_TYPE_NUM +}; + +enum ENUM_SCAN_STATE { + SCAN_STATE_IDLE = 0, + SCAN_STATE_SCANNING, + SCAN_STATE_NUM +}; + +enum ENUM_FW_SCAN_STATE { + FW_SCAN_STATE_IDLE = 0, /* 0 */ + FW_SCAN_STATE_SCAN_START, /* 1 */ + FW_SCAN_STATE_REQ_CHANNEL, /* 2 */ + FW_SCAN_STATE_SET_CHANNEL, /* 3 */ + FW_SCAN_STATE_DELAYED_ACTIVE_PROB_REQ, /* 4 */ + FW_SCAN_STATE_ACTIVE_PROB_REQ, /* 5 */ + FW_SCAN_STATE_LISTEN, /* 6 */ + FW_SCAN_STATE_SCAN_DONE, /* 7 */ + FW_SCAN_STATE_NLO_START, /* 8 */ + FW_SCAN_STATE_NLO_HIT_CHECK, /* 9 */ + FW_SCAN_STATE_NLO_STOP, /* 10 */ + FW_SCAN_STATE_BATCH_START, /* 11 */ + FW_SCAN_STATE_BATCH_CHECK, /* 12 */ + FW_SCAN_STATE_BATCH_STOP, /* 13 */ + FW_SCAN_STATE_NUM /* 14 */ +}; + +enum ENUM_SCAN_CHANNEL { + SCAN_CHANNEL_FULL = 0, + SCAN_CHANNEL_2G4, + SCAN_CHANNEL_5G, + SCAN_CHANNEL_P2P_SOCIAL, + SCAN_CHANNEL_SPECIFIED, + SCAN_CHANNEL_NUM +}; + +struct MSG_SCN_FSM { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint32_t u4Dummy; +}; + +enum ENUM_SCHED_SCAN_ACT { + SCHED_SCAN_ACT_ENABLE = 0, + SCHED_SCAN_ACT_DISABLE, +}; + +#define SCAN_LOG_PREFIX_MAX_LEN (16) +#define SCAN_LOG_MSG_MAX_LEN (400) +#define SCAN_LOG_BUFF_SIZE (200) +#define SCAN_LOG_DYN_ALLOC_MEM (1) + +enum ENUM_SCAN_LOG_PREFIX { + /* Scan */ + LOG_SCAN_REQ_K2D = 0, /* 0 */ + LOG_SCAN_REQ_D2F, + LOG_SCAN_RESULT_F2D, + LOG_SCAN_RESULT_D2K, + LOG_SCAN_DONE_F2D, + LOG_SCAN_DONE_D2K, /* 5 */ + + /* Sched scan */ + LOG_SCHED_SCAN_REQ_START_K2D, + LOG_SCHED_SCAN_REQ_START_D2F, + LOG_SCHED_SCAN_REQ_STOP_K2D, + LOG_SCHED_SCAN_REQ_STOP_D2F, + LOG_SCHED_SCAN_DONE_F2D, /* 10 */ + LOG_SCHED_SCAN_DONE_D2K, + + /* Scan abort */ + LOG_SCAN_ABORT_REQ_K2D, + LOG_SCAN_ABORT_REQ_D2F, + LOG_SCAN_ABORT_DONE_D2K, + + /* Driver only */ + LOG_SCAN_D2D, + + /* Last one */ + LOG_SCAN_MAX +}; + +/*----------------------------------------------------------------------------*/ +/* BSS Descriptors */ +/*----------------------------------------------------------------------------*/ +struct BSS_DESC { + struct LINK_ENTRY rLinkEntry; + /* Support AP Selection*/ + struct LINK_ENTRY rLinkEntryEss; + + uint8_t aucBSSID[MAC_ADDR_LEN]; + + /* For IBSS, the SrcAddr is different from BSSID */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; + + /* If we are going to connect to this BSS (JOIN or ROAMING to another + * BSS), don't remove this record from BSS List. + */ + u_int8_t fgIsConnecting; + + /* If we have connected to this BSS (NORMAL_TR), don't removed + * this record from BSS list. + */ + u_int8_t fgIsConnected; + + /* This flag is TRUE if the SSID is not hidden */ + u_int8_t fgIsValidSSID; + + /* When this flag is TRUE, means the SSID of this + * BSS is not known yet. + */ + u_int8_t fgIsHiddenSSID; + + uint8_t ucSSIDLen; + uint8_t aucSSID[ELEM_MAX_LEN_SSID]; + + OS_SYSTIME rUpdateTime; + + enum ENUM_BSS_TYPE eBSSType; + + uint16_t u2CapInfo; + + uint16_t u2BeaconInterval; + uint16_t u2ATIMWindow; + + uint16_t u2OperationalRateSet; + uint16_t u2BSSBasicRateSet; + u_int8_t fgIsUnknownBssBasicRate; + + u_int8_t fgIsERPPresent; + u_int8_t fgIsHTPresent; + u_int8_t fgIsVHTPresent; + + uint8_t ucPhyTypeSet; /* Available PHY Type Set of this BSS */ + + /* record from bcn or probe response */ + uint8_t ucVhtCapNumSoundingDimensions; + + uint8_t ucChannelNum; + + /* Record bandwidth for association process. Some AP will + * send association resp by 40MHz BW + */ + enum ENUM_CHNL_EXT eSco; + + enum ENUM_CHANNEL_WIDTH eChannelWidth; /* VHT operation ie */ + uint8_t ucCenterFreqS1; + uint8_t ucCenterFreqS2; + enum ENUM_BAND eBand; + + uint8_t ucDTIMPeriod; + u_int8_t fgTIMPresent; + + /* This BSS's TimeStamp is larger than us(TCL == 1 in RX_STATUS_T) */ + u_int8_t fgIsLargerTSF; + + uint8_t ucRCPI; /* MAX of (WF0/WF1) */ + uint8_t ucRCPI0; /* WF0 */ + uint8_t ucRCPI1; /* WF1 */ + + /* A flag to indicate this BSS's WMM capability */ + uint8_t ucWmmFlag; + + /*! \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 + */ + uint32_t u4RsnSelectedGroupCipher; + uint32_t u4RsnSelectedPairwiseCipher; + uint32_t u4RsnSelectedAKMSuite; + + uint16_t u2RsnCap; + + struct RSN_INFO rRSNInfo; + struct RSN_INFO rWPAInfo; +#if 1 /* CFG_SUPPORT_WAPI */ + struct WAPI_INFO rIEWAPI; + u_int8_t fgIEWAPI; +#endif + u_int8_t fgIERSN; + u_int8_t fgIEWPA; + u_int8_t fgIEOsen; + + /*! \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 + */ + uint8_t ucEncLevel; + +#if CFG_ENABLE_WIFI_DIRECT + u_int8_t fgIsP2PPresent; + u_int8_t fgIsP2PReport; /* TRUE: report to upper layer */ + struct P2P_DEVICE_DESC *prP2pDesc; + + /* For IBSS, the SrcAddr is different from BSSID */ + uint8_t aucIntendIfAddr[MAC_ADDR_LEN]; + +#if 0 /* TODO: Remove this */ + /* Device Capability Attribute. (P2P_DEV_CAPABILITY_XXXX) */ + uint8_t ucDevCapabilityBitmap; + + /* Group Capability Attribute. (P2P_GROUP_CAPABILITY_XXXX) */ + uint8_t ucGroupCapabilityBitmap; +#endif + + struct LINK 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 + + /* The received IE length exceed the maximum IE buffer size */ + u_int8_t fgIsIEOverflow; + + uint16_t u2RawLength; /* The byte count of aucRawBuf[] */ + uint16_t u2IELength; /* The byte count of aucIEBuf[] */ + + /* Place u8TimeStamp before aucIEBuf[1] to force DW align */ + union ULARGE_INTEGER u8TimeStamp; + + uint8_t aucRawBuf[CFG_RAW_BUFFER_SIZE]; + uint8_t aucIEBuf[CFG_IE_BUFFER_SIZE]; + uint16_t u2JoinStatus; + OS_SYSTIME rJoinFailTime; + + /* Support AP Selection */ + struct AIS_BLACKLIST_ITEM *prBlack; + uint16_t u2StaCnt; + uint16_t u2AvaliableAC; /* Available Admission Capacity */ + uint8_t ucJoinFailureCount; + uint8_t ucChnlUtilization; + uint8_t ucSNR; + u_int8_t fgSeenProbeResp; + u_int8_t fgExsitBssLoadIE; + u_int8_t fgMultiAnttenaAndSTBC; + u_int8_t fgDeauthLastTime; + uint32_t u4UpdateIdx; +#if CFG_SUPPORT_RSN_SCORE + u_int8_t fgIsRSNSuitableBss; +#endif + /* end Support AP Selection */ + int8_t cPowerLimit; + uint8_t aucRrmCap[5]; +}; + +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP +struct ROAM_BSS_DESC { + struct LINK_ENTRY rLinkEntry; + uint8_t ucSSIDLen; + uint8_t aucSSID[ELEM_MAX_LEN_SSID]; + OS_SYSTIME rUpdateTime; +}; +#endif + +struct SCAN_PARAM { /* Used by SCAN FSM */ + /* Active or Passive */ + enum ENUM_SCAN_TYPE eScanType; + + /* Network Type */ + uint8_t ucBssIndex; + + /* Specified SSID Type */ + uint8_t ucSSIDType; + uint8_t ucSSIDNum; + + /* Length of Specified SSID */ + uint8_t ucSpecifiedSSIDLen[SCN_SSID_MAX_NUM]; + + /* Specified SSID */ + uint8_t aucSpecifiedSSID[SCN_SSID_MAX_NUM][ELEM_MAX_LEN_SSID]; + +#if CFG_ENABLE_WIFI_DIRECT + u_int8_t fgFindSpecificDev; /* P2P: Discovery Protocol */ + uint8_t aucDiscoverDevAddr[MAC_ADDR_LEN]; + u_int8_t fgIsDevType; + struct P2P_DEVICE_TYPE rDiscoverDevType; + + /* TODO: Find Specific Device Type. */ +#endif /* CFG_ENABLE_WIFI_DIRECT */ + + uint16_t u2ChannelDwellTime; + uint16_t u2ChannelMinDwellTime; + uint16_t u2TimeoutValue; + + uint8_t aucBSSID[MAC_ADDR_LEN]; + + u_int8_t fgIsObssScan; + u_int8_t fgIsScanV2; + + /* Run time flags */ + uint16_t u2ProbeDelayTime; + + /* channel information */ + enum ENUM_SCAN_CHANNEL eScanChannel; + uint8_t ucChannelListNum; + struct RF_CHANNEL_INFO arChnlInfoList[MAXIMUM_OPERATION_CHANNEL_LIST]; + + /* random mac */ + uint8_t ucScnFuncMask; + uint8_t aucRandomMac[MAC_ADDR_LEN]; + + /* Feedback information */ + uint8_t ucSeqNum; + + /* Information Element */ + uint16_t u2IELen; + uint8_t aucIE[MAX_IE_LENGTH]; + +}; + +struct SCHED_SCAN_PARAM { /* Used by SCAN FSM */ + uint8_t ucSeqNum; + uint8_t ucBssIndex; /* Network Type */ + u_int8_t fgStopAfterIndication; /* always FALSE */ + uint8_t ucMatchSSIDNum; /* Match SSID */ + struct BSS_DESC *aprPendingBssDescToInd[SCN_SSID_MATCH_MAX_NUM]; +}; + +struct SCAN_LOG_ELEM_BSS { + struct LINK_ENTRY rLinkEntry; + + uint8_t aucBSSID[MAC_ADDR_LEN]; + uint16_t u2SeqCtrl; +}; + +struct SCAN_LOG_CACHE { + struct LINK rBSSListFW; + struct LINK rBSSListCFG; + + struct SCAN_LOG_ELEM_BSS arBSSListBufFW[SCAN_LOG_BUFF_SIZE]; + struct SCAN_LOG_ELEM_BSS arBSSListBufCFG[SCAN_LOG_BUFF_SIZE]; +}; + +struct SCAN_INFO { + /* Store the STATE variable of SCAN FSM */ + enum ENUM_SCAN_STATE eCurrentState; + + OS_SYSTIME rLastScanCompletedTime; + + struct SCAN_PARAM rScanParam; + struct SCHED_SCAN_PARAM rSchedScanParam; + + uint32_t u4NumOfBssDesc; + + uint8_t aucScanBuffer[SCN_MAX_BUFFER_SIZE]; + + struct LINK rBSSDescList; + + struct LINK rFreeBSSDescList; + + struct LINK rPendingMsgList; +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + uint8_t aucScanRoamBuffer[SCN_ROAM_MAX_BUFFER_SIZE]; + struct LINK rRoamFreeBSSDescList; + struct LINK rRoamBSSDescList; +#endif + /* Sparse Channel Detection */ + u_int8_t fgIsSparseChannelValid; + struct RF_CHANNEL_INFO rSparseChannel; + + /* Sched scan state tracking */ + u_int8_t fgSchedScanning; + + /* Full2Partial */ + OS_SYSTIME u4LastFullScanTime; + u_int8_t fgIsScanForFull2Partial; + u_int8_t ucFull2PartialSeq; + uint32_t au4ChannelBitMap[SCAN_CHANNEL_BITMAP_ARRAY_LEN]; + + /*channel idle count # Mike */ + uint8_t ucSparseChannelArrayValidNum; + uint8_t aucReserved[3]; + uint8_t aucChannelNum[EVENT_SCAN_DONE_CHANNEL_NUM_MAX]; + uint16_t au2ChannelIdleTime[EVENT_SCAN_DONE_CHANNEL_NUM_MAX]; + /* Mdrdy Count in each Channel */ + uint8_t aucChannelMDRDYCnt[EVENT_SCAN_DONE_CHANNEL_NUM_MAX]; + /* Beacon and Probe Response Count in each Channel */ + uint8_t aucChannelBAndPCnt[EVENT_SCAN_DONE_CHANNEL_NUM_MAX]; + + /* Support AP Selection */ + uint32_t u4ScanUpdateIdx; + + /* Scan log cache */ + struct SCAN_LOG_CACHE rScanLogCache; +}; + +/* Incoming Mailbox Messages */ +struct MSG_SCN_SCAN_REQ { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucSeqNum; + uint8_t ucBssIndex; + enum ENUM_SCAN_TYPE eScanType; + + /* BIT(0) wildcard / BIT(1) P2P-wildcard / BIT(2) specific */ + uint8_t ucSSIDType; + + uint8_t ucSSIDLength; + uint8_t aucSSID[PARAM_MAX_LEN_SSID]; + uint16_t u2ChannelDwellTime; /* ms unit */ + uint16_t u2TimeoutValue; /* ms unit */ + enum ENUM_SCAN_CHANNEL eScanChannel; + uint8_t ucChannelListNum; + struct RF_CHANNEL_INFO arChnlInfoList[MAXIMUM_OPERATION_CHANNEL_LIST]; + uint16_t u2IELen; + uint8_t aucIE[MAX_IE_LENGTH]; +}; + +struct MSG_SCN_SCAN_REQ_V2 { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucSeqNum; + uint8_t ucBssIndex; + enum ENUM_SCAN_TYPE eScanType; + + /* BIT(0) wildcard / BIT(1) P2P-wildcard / BIT(2) specific */ + uint8_t ucSSIDType; + + uint8_t ucSSIDNum; + struct PARAM_SSID *prSsid; + uint16_t u2ProbeDelay; + uint16_t u2ChannelDwellTime; /* In TU. 1024us. */ + uint16_t u2ChannelMinDwellTime; /* In TU. 1024us. */ + uint16_t u2TimeoutValue; /* ms unit */ + + uint8_t aucBSSID[MAC_ADDR_LEN]; + enum ENUM_SCAN_CHANNEL eScanChannel; + uint8_t ucChannelListNum; + struct RF_CHANNEL_INFO arChnlInfoList[MAXIMUM_OPERATION_CHANNEL_LIST]; + uint8_t ucScnFuncMask; + uint8_t aucRandomMac[MAC_ADDR_LEN]; /* random mac */ + uint16_t u2IELen; + uint8_t aucIE[MAX_IE_LENGTH]; +}; + +struct MSG_SCN_SCAN_CANCEL { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucSeqNum; + uint8_t ucBssIndex; + u_int8_t fgIsChannelExt; + u_int8_t fgIsOidRequest; +}; + +/* Outgoing Mailbox Messages */ +enum ENUM_SCAN_STATUS { + SCAN_STATUS_DONE = 0, + SCAN_STATUS_CANCELLED, + SCAN_STATUS_FAIL, + SCAN_STATUS_BUSY, + SCAN_STATUS_NUM +}; + +struct MSG_SCN_SCAN_DONE { + struct MSG_HDR rMsgHdr; /* Must be the first member */ + uint8_t ucSeqNum; + uint8_t ucBssIndex; + enum ENUM_SCAN_STATUS eScanStatus; +}; + +#if CFG_SUPPORT_AGPS_ASSIST +enum AP_PHY_TYPE { + AGPS_PHY_A, + AGPS_PHY_B, + AGPS_PHY_G, +}; + +struct AGPS_AP_INFO { + uint8_t aucBSSID[MAC_ADDR_LEN]; + int16_t i2ApRssi; /* -127..128 */ + uint16_t u2Channel; /* 0..256 */ + enum AP_PHY_TYPE ePhyType; +}; + +struct AGPS_AP_LIST { + uint8_t ucNum; + struct AGPS_AP_INFO arApInfo[SCN_AGPS_AP_LIST_MAX_NUM]; +}; +#endif +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +extern const char aucScanLogPrefix[][SCAN_LOG_PREFIX_MAX_LEN]; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +#if DBG_DISABLE_ALL_LOG +#define scanlog_dbg(prefix, _Clz, _Fmt, ...) +#else /* DBG_DISABLE_ALL_LOG */ +#define scanlog_dbg(prefix, _Clz, _Fmt, ...) \ + do { \ + if ((aucDebugModule[DBG_SCN_IDX] & \ + DBG_CLASS_##_Clz) == 0) \ + break; \ + LOG_FUNC("[%u]SCANLOG:(SCN " #_Clz ") %s " _Fmt, \ + KAL_GET_CURRENT_THREAD_ID(), \ + aucScanLogPrefix[prefix], ##__VA_ARGS__); \ + } while (0) +#endif /* DBG_DISABLE_ALL_LOG */ + + +/******************************************************************************* + * 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 struct ADAPTER *prAdapter); + +void scnUninit(IN struct ADAPTER *prAdapter); + +/* Scan utilities */ +uint32_t scanCountBits(IN uint32_t bitMap[], IN uint32_t bitMapSize); + +void scanSetRequestChannel(IN struct ADAPTER *prAdapter, + IN uint32_t u4ScanChannelNum, + IN struct RF_CHANNEL_INFO arChannel[], + IN uint8_t fgIsOnlineScan, + OUT struct MSG_SCN_SCAN_REQ_V2 *prScanReqMsg); + +/* BSS-DESC Search */ +struct BSS_DESC *scanSearchBssDescByBssid(IN struct ADAPTER *prAdapter, + IN uint8_t aucBSSID[]); + +struct BSS_DESC * +scanSearchBssDescByBssidAndSsid(IN struct ADAPTER *prAdapter, + IN uint8_t aucBSSID[], + IN u_int8_t fgCheckSsid, + IN struct PARAM_SSID *prSsid); + +#if CFG_SUPPORT_CFG80211_AUTH +struct BSS_DESC * +scanSearchBssDescByBssidAndChanNum(IN struct ADAPTER *prAdapter, + IN uint8_t aucBSSID[], IN u_int8_t fgCheckChanNum, + IN uint8_t ucChannelNum); +#endif +struct BSS_DESC *scanSearchBssDescByTA(IN struct ADAPTER *prAdapter, + IN uint8_t aucSrcAddr[]); + +struct BSS_DESC * +scanSearchBssDescByTAAndSsid(IN struct ADAPTER *prAdapter, + IN uint8_t aucSrcAddr[], + IN u_int8_t fgCheckSsid, + IN struct PARAM_SSID *prSsid); + +/* BSS-DESC Search - Alternative */ +struct BSS_DESC * +scanSearchExistingBssDesc(IN struct ADAPTER *prAdapter, + IN enum ENUM_BSS_TYPE eBSSType, + IN uint8_t aucBSSID[], + IN uint8_t aucSrcAddr[]); + +struct BSS_DESC * +scanSearchExistingBssDescWithSsid(IN struct ADAPTER *prAdapter, + IN enum ENUM_BSS_TYPE eBSSType, + IN uint8_t aucBSSID[], + IN uint8_t aucSrcAddr[], + IN u_int8_t fgCheckSsid, + IN struct PARAM_SSID *prSsid); + +/* BSS-DESC Allocation */ +struct BSS_DESC *scanAllocateBssDesc(IN struct ADAPTER *prAdapter); + +/* BSS-DESC Removal */ +void scanRemoveBssDescsByPolicy(IN struct ADAPTER *prAdapter, + IN uint32_t u4RemovePolicy); + +void scanRemoveBssDescByBssid(IN struct ADAPTER *prAdapter, + IN uint8_t aucBSSID[]); + +void scanRemoveBssDescByBandAndNetwork( + IN struct ADAPTER *prAdapter, + IN enum ENUM_BAND eBand, + IN uint8_t ucBssIndex); + +/* BSS-DESC State Change */ +void scanRemoveConnFlagOfBssDescByBssid(IN struct ADAPTER *prAdapter, + IN uint8_t aucBSSID[]); + +/* BSS-DESC Insertion - ALTERNATIVE */ +struct BSS_DESC *scanAddToBssDesc(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +uint32_t scanProcessBeaconAndProbeResp(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSWRfb); + +void +scanBuildProbeReqFrameCommonIEs(IN struct MSDU_INFO *prMsduInfo, + IN uint8_t *pucDesiredSsid, + IN uint32_t u4DesiredSsidLen, + IN uint16_t u2SupportedRateSet); + +uint32_t scanSendProbeReqFrames(IN struct ADAPTER *prAdapter, + IN struct SCAN_PARAM *prScanParam); + +void scanUpdateBssDescForSearch(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc); + +struct BSS_DESC *scanSearchBssDescByPolicy(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +uint32_t scanAddScanResult(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc, + IN struct SW_RFB *prSwRfb); + +void scanReportBss2Cfg80211(IN struct ADAPTER *prAdapter, + IN enum ENUM_BSS_TYPE eBSSType, + IN struct BSS_DESC *SpecificprBssDesc); + +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP +struct ROAM_BSS_DESC *scanSearchRoamBssDescBySsid( + IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc); +struct ROAM_BSS_DESC *scanAllocateRoamBssDesc(IN struct ADAPTER *prAdapter); +void scanAddToRoamBssDesc(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc); +void scanSearchBssDescOfRoamSsid(IN struct ADAPTER *prAdapter); +void scanRemoveRoamBssDescsByTime(IN struct ADAPTER *prAdapter, + IN uint32_t u4RemoveTime); +#endif +/*----------------------------------------------------------------------------*/ +/* Routines in scan_fsm.c */ +/*----------------------------------------------------------------------------*/ +void scnFsmSteps(IN struct ADAPTER *prAdapter, + IN enum ENUM_SCAN_STATE eNextState); + +/*----------------------------------------------------------------------------*/ +/* Command Routines */ +/*----------------------------------------------------------------------------*/ +void scnSendScanReq(IN struct ADAPTER *prAdapter); + +void scnSendScanReqV2(IN struct ADAPTER *prAdapter); + +/*----------------------------------------------------------------------------*/ +/* RX Event Handling */ +/*----------------------------------------------------------------------------*/ +void scnEventScanDone(IN struct ADAPTER *prAdapter, + IN struct EVENT_SCAN_DONE *prScanDone, + u_int8_t fgIsNewVersion); + +void scnEventSchedScanDone(IN struct ADAPTER *prAdapter, + IN struct EVENT_SCHED_SCAN_DONE *prSchedScanDone); + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Handling */ +/*----------------------------------------------------------------------------*/ +void scnFsmMsgStart(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void scnFsmMsgAbort(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr); + +void scnFsmHandleScanMsg(IN struct ADAPTER *prAdapter, + IN struct MSG_SCN_SCAN_REQ *prScanReqMsg); + +void scnFsmHandleScanMsgV2(IN struct ADAPTER *prAdapter, + IN struct MSG_SCN_SCAN_REQ_V2 *prScanReqMsg); + +void scnFsmRemovePendingMsg(IN struct ADAPTER *prAdapter, + IN uint8_t ucSeqNum, + IN uint8_t ucBssIndex); + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Generation */ +/*----------------------------------------------------------------------------*/ +void +scnFsmGenerateScanDoneMsg(IN struct ADAPTER *prAdapter, + IN uint8_t ucSeqNum, + IN uint8_t ucBssIndex, + IN enum ENUM_SCAN_STATUS eScanStatus); + +/*----------------------------------------------------------------------------*/ +/* Query for sparse channel */ +/*----------------------------------------------------------------------------*/ +u_int8_t scnQuerySparseChannel(IN struct ADAPTER *prAdapter, + enum ENUM_BAND *prSparseBand, + uint8_t *pucSparseChannel); + +/*----------------------------------------------------------------------------*/ +/* OID/IOCTL Handling */ +/*----------------------------------------------------------------------------*/ +#if CFG_SUPPORT_PASSPOINT +struct BSS_DESC *scanSearchBssDescByBssidAndLatestUpdateTime( + IN struct ADAPTER *prAdapter, + IN uint8_t aucBSSID[]); +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_AGPS_ASSIST +void scanReportScanResultToAgps(struct ADAPTER *prAdapter); +#endif + +#if CFG_SUPPORT_SCHED_SCAN +u_int8_t scnFsmSchedScanRequest(IN struct ADAPTER *prAdapter, + IN struct PARAM_SCHED_SCAN_REQUEST *prSchedScanRequest); + +u_int8_t scnFsmSchedScanStopRequest(IN struct ADAPTER *prAdapter); + +u_int8_t scnFsmSchedScanSetAction(IN struct ADAPTER *prAdapter, + IN enum ENUM_SCHED_SCAN_ACT ucSchedScanAct); + +u_int8_t scnFsmSchedScanSetCmd(IN struct ADAPTER *prAdapter, + IN struct CMD_SCHED_SCAN_REQ *prSchedScanCmd); + +void scnSetSchedScanPlan(IN struct ADAPTER *prAdapter, + IN struct CMD_SCHED_SCAN_REQ *prSchedScanCmd); + +#endif /* CFG_SUPPORT_SCHED_SCAN */ + +void scanLogEssResult(struct ADAPTER *prAdapter); +void scanInitEssResult(struct ADAPTER *prAdapter); +#if CFG_SUPPORT_SCAN_CACHE_RESULT +/*----------------------------------------------------------------------------*/ +/* Routines in scan_cache.c */ +/*----------------------------------------------------------------------------*/ +u_int8_t isScanCacheDone(struct GL_SCAN_CACHE_INFO *prScanCache); +#endif /* CFG_SUPPORT_SCAN_CACHE_RESULT */ + +void scanReqLog(struct CMD_SCAN_REQ_V2 *prCmdScanReq); +void scanReqSsidLog(struct CMD_SCAN_REQ_V2 *prCmdScanReq, + const uint16_t logBufLen); +void scanReqChannelLog(struct CMD_SCAN_REQ_V2 *prCmdScanReq, + const uint16_t logBufLen); +void scanResultLog(struct ADAPTER *prAdapter, struct SW_RFB *prSwRfb); +void scanLogCacheAddBSS(struct LINK *prList, + struct SCAN_LOG_ELEM_BSS *prListBuf, + enum ENUM_SCAN_LOG_PREFIX prefix, + uint8_t bssId[], uint16_t seq); +void scanLogCacheFlushBSS(struct LINK *prList, enum ENUM_SCAN_LOG_PREFIX prefix, + const uint16_t logBufLen); +void scanLogCacheFlushAll(struct SCAN_LOG_CACHE *prScanLogCache, + enum ENUM_SCAN_LOG_PREFIX prefix, const uint16_t logBufLen); + +#endif /* _SCAN_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/stats.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/stats.h new file mode 100644 index 0000000000000..6abca9d597a6b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/stats.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. + * If not, see . + */ + +/******************************************************************************* + * C O M P I L E 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 + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O D E C L A R A T I O N S + ******************************************************************************* + */ +#include + +#if (CFG_SUPPORT_STATISTICS == 1) +#define STATS_RX_PKT_INFO_DISPLAY StatsRxPktInfoDisplay +#define STATS_TX_PKT_INFO_DISPLAY StatsTxPktInfoDisplay +#else +#define STATS_RX_PKT_INFO_DISPLAY(__Pkt__) +#define STATS_TX_PKT_INFO_DISPLAY(__Pkt__) +#endif /* CFG_SUPPORT_STATISTICS */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E F U N C T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C F U N C T I O N S + ******************************************************************************* + */ + +#define STATS_TX_TIME_ARRIVE(__Skb__) \ +do { \ + uint64_t __SysTime; \ + __SysTime = StatsEnvTimeGet(); /* us */ \ + GLUE_SET_PKT_XTIME(__Skb__, __SysTime); \ +} while (FALSE) + +uint64_t StatsEnvTimeGet(void); + +void StatsEnvTxTime2Hif(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +void StatsEnvRxTime2Host(IN struct ADAPTER *prAdapter, + struct sk_buff *prSkb); + +void StatsRxPktInfoDisplay(struct SW_RFB *prSwRfb); + +void StatsTxPktInfoDisplay(uint8_t *pPkt); + +void StatsResetTxRx(void); + +void StatsEnvSetPktDelay(IN uint8_t ucTxOrRx, + IN uint8_t ucIpProto, IN uint16_t u2UdpPort, + uint32_t u4DelayThreshold); + +void StatsEnvGetPktDelay(OUT uint8_t *pucTxRxFlag, + OUT uint8_t *pucTxIpProto, OUT uint16_t *pu2TxUdpPort, + OUT uint32_t *pu4TxDelayThreshold, + OUT uint8_t *pucRxIpProto, + OUT uint16_t *pu2RxUdpPort, + OUT uint32_t *pu4RxDelayThreshold); +/* End of stats.h */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/swcr.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/swcr.h new file mode 100644 index 0000000000000..c1467c6e25d74 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/swcr.h @@ -0,0 +1,269 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/ + * MT6620_WIFI_DRIVER_V2_3/include/mgmt/swcr.h#1 + */ + +/*! \file "swcr.h" + * \brief + */ + +/* + * + */ + +#ifndef _SWCR_H +#define _SWCR_H + +#include "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 TEST_PS 1 + +#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) (ARRAY_SIZE(x)) + +#define SWCR_CR_NUM 7 + +#define SWCR_GET_RW_INDEX(action, rw, index) \ +do { \ + index = action & 0x7F; \ + rw = action >> 7; \ +} while (0) + +extern uint32_t g_au4SwCr[]; /*: 0: command other: data */ + +typedef void(*PFN_SWCR_RW_T) (struct ADAPTER *prAdapter, + uint8_t ucRead, uint16_t u2Addr, uint32_t *pu4Data); +typedef void(*PFN_CMD_RW_T) (struct ADAPTER *prAdapter, + uint8_t ucCate, uint8_t ucAction, uint8_t ucOpt0, + uint8_t ucOpt1); + +struct SWCR_MAP_ENTRY { + uint16_t u2Type; + void *u4Addr; +}; + +struct SWCR_MOD_MAP_ENTRY { + uint8_t ucMapNum; + struct SWCR_MAP_ENTRY *prSwCrMap; +}; + +enum ENUM_SWCR_DBG_TYPE { + SWCR_DBG_TYPE_ALL = 0, + SWCR_DBG_TYPE_TXRX, + SWCR_DBG_TYPE_RX_RATES, + SWCR_DBG_TYPE_PS, + SWCR_DBG_TYPE_NUM +}; + +enum ENUM_SWCR_DBG_ALL { + 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 +}; + +/******************************************************************************* + * 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(struct ADAPTER *prAdapter, + uint8_t ucRead, uint16_t u2Addr, uint32_t *pu4Data); + +/* Debug Support */ +void swCrFrameCheckEnable(struct ADAPTER *prAdapter, + uint32_t u4DumpType); +void swCrDebugInit(struct ADAPTER *prAdapter); +void swCrDebugCheckEnable(struct ADAPTER *prAdapter, + u_int8_t fgIsEnable, uint8_t ucType, uint32_t u4Timeout); +void swCrDebugUninit(struct ADAPTER *prAdapter); + +#if CFG_SUPPORT_SWCR +void swCtrlCmdCategory0(struct ADAPTER *prAdapter, + uint8_t ucCate, uint8_t ucAction, uint8_t ucOpt0, + uint8_t ucOpt1); +void swCtrlCmdCategory1(struct ADAPTER *prAdapter, + uint8_t ucCate, uint8_t ucAction, uint8_t ucOpt0, + uint8_t ucOpt1); +#if TEST_PS +void testPsCmdCategory0(struct ADAPTER *prAdapter, + uint8_t ucCate, uint8_t ucAction, uint8_t ucOpt0, + uint8_t ucOpt1); +void testPsCmdCategory1(struct ADAPTER *prAdapter, + uint8_t ucCate, uint8_t ucAction, uint8_t ucOpt0, + uint8_t ucOpt1); +#endif +#if CFG_SUPPORT_802_11V +#if (CFG_SUPPORT_802_11V_TIMING_MEASUREMENT == 1) && (WNM_UNIT_TEST == 1) +void testWNMCmdCategory0(struct ADAPTER *prAdapter, + uint8_t ucCate, uint8_t ucAction, uint8_t ucOpt0, + uint8_t ucOpt1); +#endif +#endif +void swCtrlSwCr(struct ADAPTER *prAdapter, uint8_t ucRead, + uint16_t u2Addr, uint32_t *pu4Data); + +/* Support Debug */ +void swCrDebugCheck(struct ADAPTER *prAdapter, + struct CMD_SW_DBG_CTRL *prCmdSwCtrl); +void swCrDebugCheckTimeout(IN struct ADAPTER *prAdapter, + unsigned long ulParamPtr); +void swCrDebugQuery(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); +void swCrDebugQueryTimeout(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo); +#endif + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/tdls.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/tdls.h new file mode 100644 index 0000000000000..039b520a4a4d1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/tdls.h @@ -0,0 +1,491 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: include/tdls.h#1 + */ + +/*! \file "tdls.h" + * \brief This file contains the internal used in TDLS modules + * for MediaTek Inc. 802.11 Wireless LAN Adapters. + */ + + +#ifndef _TDLS_H +#define _TDLS_H + +#include "wlan_typedef.h" + +#if CFG_SUPPORT_TDLS + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ +#define TDLS_CFG_CMD_TEST + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/* assign station record idx for the packet */ +#define TDLSEX_STA_REC_IDX_GET(__prAdapter__, __MsduInfo__) \ +{ \ + struct STA_RECORD *__StaRec__; \ + __MsduInfo__->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; \ + __StaRec__ = cnmGetStaRecByAddress(__prAdapter__, \ + (uint8_t) NETWORK_TYPE_AIS_INDEX, \ + __MsduInfo__->aucEthDestAddr); \ + if ((__StaRec__ != NULL) && (IS_DLS_STA(__StaRec__))) \ + __MsduInfo__->ucStaRecIndex = __StaRec__->ucIndex; \ +} + +/* fill wiphy flag */ +#define TDLSEX_WIPHY_FLAGS_INIT(__fgFlag__) \ +{ \ + __fgFlag__ |= (WIPHY_FLAG_SUPPORTS_TDLS | \ + WIPHY_FLAG_TDLS_EXTERNAL_SETUP); \ +} + +#define LR_TDLS_FME_FIELD_FILL(__Len) \ +{ \ + pPkt += __Len; \ + u4PktLen += __Len; \ +} + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +extern int wlanHardStartXmit(struct sk_buff *prSkb, + struct net_device *prDev); + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/* Status code */ +#define TDLS_STATUS uint32_t + +#define TDLS_STATUS_SUCCESS WLAN_STATUS_SUCCESS +#define TDLS_STATUS_FAIL WLAN_STATUS_FAILURE +#define TDLS_STATUS_INVALID_LENGTH WLAN_STATUS_INVALID_LENGTH +#define TDLS_STATUS_RESOURCES WLAN_STATUS_RESOURCES +#define TDLS_FME_MAC_ADDR_LEN 6 +#define TDLS_EX_CAP_PEER_UAPSD BIT(0) +#define TDLS_EX_CAP_CHAN_SWITCH BIT(1) +#define TDLS_EX_CAP_TDLS BIT(2) +#define TDLS_CMD_PEER_UPDATE_EXT_CAP_MAXLEN 5 +#define TDLS_CMD_PEER_UPDATE_SUP_RATE_MAX 50 +#define TDLS_CMD_PEER_UPDATE_SUP_CHAN_MAX 50 +#define TDLS_SEC_BUF_LENGTH 600 + +#define MAXNUM_TDLS_PEER 4 + +/* command */ +enum TDLS_CMD_ID { + TDLS_CMD_TEST_TX_FRAME = 0x00, + TDLS_CMD_TEST_RCV_FRAME, + TDLS_CMD_TEST_PEER_ADD, + TDLS_CMD_TEST_PEER_UPDATE, + TDLS_CMD_TEST_DATA_FRAME, + TDLS_CMD_TEST_RCV_NULL +}; + +/* protocol */ +#define TDLS_FRM_PROT_TYPE 0x890d + +/* payload specific type in the LLC/SNAP header */ +#define TDLS_FRM_PAYLOAD_TYPE 2 + +#define TDLS_FRM_CATEGORY 12 + +enum TDLS_FRM_ACTION_ID { + TDLS_FRM_ACTION_SETUP_REQ = 0x00, + TDLS_FRM_ACTION_SETUP_RSP, + TDLS_FRM_ACTION_CONFIRM, + TDLS_FRM_ACTION_TEARDOWN, + TDLS_FRM_ACTION_PTI, + TDLS_FRM_ACTION_CHAN_SWITCH_REQ, + TDLS_FRM_ACTION_CHAN_SWITCH_RSP, + TDLS_FRM_ACTION_PEER_PSM_REQ, + TDLS_FRM_ACTION_PEER_PSM_RSP, + TDLS_FRM_ACTION_PTI_RSP, + TDLS_FRM_ACTION_DISCOVERY_REQ, + TDLS_FRM_ACTION_DISCOVERY_RSP = 0x0e, + TDLS_FRM_ACTION_EVENT_TEAR_DOWN_TO_SUPPLICANT = 0x30 +}; + +/* 7.3.2.62 Link Identifier element */ +#define ELEM_ID_LINK_IDENTIFIER 101 + +struct IE_LINK_IDENTIFIER { + uint8_t ucId; + uint8_t ucLength; + uint8_t aBSSID[6]; + uint8_t aInitiator[6]; + uint8_t aResponder[6]; +} __KAL_ATTRIB_PACKED__; + +#define TDLS_LINK_IDENTIFIER_IE(__ie__) ((struct IE_LINK_IDENTIFIER *)(__ie__)) + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +struct STATION_PRARAMETERS { + const u8 *supported_rates; + struct net_device *vlan; + u32 sta_flags_mask, sta_flags_set; + u32 sta_modify_mask; + int listen_interval; + u16 aid; + u8 supported_rates_len; + u8 plink_action; + u8 plink_state; + const struct ieee80211_ht_cap *ht_capa; + const struct ieee80211_vht_cap *vht_capa; + u8 uapsd_queues; + u8 max_sp; + /* enum nl80211_mesh_power_mode local_pm; */ + u16 capability; + const u8 *ext_capab; + u8 ext_capab_len; +}; + +/* test command use */ +struct PARAM_CUSTOM_TDLS_CMD_STRUCT { + + uint8_t ucFmeType; /* TDLS_FRM_ACTION_ID */ + + uint8_t ucToken; + uint8_t ucCap; + + /* bit0: TDLS, bit1: Peer U-APSD Buffer, bit2: Channel Switching */ + + uint8_t ucExCap; + + uint8_t arSupRate[4]; + uint8_t arSupChan[4]; + + uint32_t u4Timeout; + + uint8_t arRspAddr[TDLS_FME_MAC_ADDR_LEN]; + uint8_t arBssid[TDLS_FME_MAC_ADDR_LEN]; + + /* Linux Kernel-3.10 */ + + struct ieee80211_ht_cap rHtCapa; + struct ieee80211_vht_cap rVhtCapa; + /* struct */ + struct STATION_PRARAMETERS rPeerInfo; + +}; + +enum ENUM_TDLS_LINK_OPER { + TDLS_DISCOVERY_REQ, + TDLS_SETUP, + TDLS_TEARDOWN, + TDLS_ENABLE_LINK, + TDLS_DISABLE_LINK +}; + +struct TDLS_CMD_LINK_OPER { + + uint8_t aucPeerMac[6]; + enum ENUM_TDLS_LINK_OPER oper; +}; + +struct TDLS_CMD_LINK_MGT { + + uint8_t aucPeer[6]; + uint8_t ucActionCode; + uint8_t ucDialogToken; + uint16_t u2StatusCode; + uint32_t u4SecBufLen; + uint8_t aucSecBuf[TDLS_SEC_BUF_LENGTH]; + +}; + +struct TDLS_CMD_PEER_ADD { + + uint8_t aucPeerMac[6]; + enum ENUM_STA_TYPE eStaType; +}; + +struct TDLS_CMD_PEER_UPDATE_HT_CAP_MCS_INFO { + uint8_t arRxMask[SUP_MCS_RX_BITMASK_OCTET_NUM]; + uint16_t u2RxHighest; + uint8_t ucTxParams; + uint8_t Reserved[3]; +}; + +struct TDLS_CMD_PEER_UPDATE_VHT_CAP_MCS_INFO { + uint8_t arRxMask[SUP_MCS_RX_BITMASK_OCTET_NUM]; +}; + +struct TDLS_CMD_PEER_UPDATE_HT_CAP { + uint16_t u2CapInfo; + uint8_t ucAmpduParamsInfo; + + /* 16 bytes MCS information */ + struct TDLS_CMD_PEER_UPDATE_HT_CAP_MCS_INFO rMCS; + + uint16_t u2ExtHtCapInfo; + uint32_t u4TxBfCapInfo; + uint8_t ucAntennaSelInfo; +}; + +struct TDLS_CMD_PEER_UPDATE_VHT_CAP { + uint16_t u2CapInfo; + /* 16 bytes MCS information */ + struct TDLS_CMD_PEER_UPDATE_VHT_CAP_MCS_INFO rVMCS; + +}; + +struct TDLS_CMD_PEER_UPDATE { + + uint8_t aucPeerMac[6]; + + uint8_t aucSupChan[TDLS_CMD_PEER_UPDATE_SUP_CHAN_MAX]; + + uint16_t u2StatusCode; + + uint8_t aucSupRate[TDLS_CMD_PEER_UPDATE_SUP_RATE_MAX]; + uint16_t u2SupRateLen; + + uint8_t UapsdBitmap; + uint8_t UapsdMaxSp; /* MAX_SP */ + + uint16_t u2Capability; + + uint8_t aucExtCap[TDLS_CMD_PEER_UPDATE_EXT_CAP_MAXLEN]; + uint16_t u2ExtCapLen; + + struct TDLS_CMD_PEER_UPDATE_HT_CAP rHtCap; + struct TDLS_CMD_PEER_UPDATE_VHT_CAP rVHtCap; + + u_int8_t fgIsSupHt; + enum ENUM_STA_TYPE eStaType; + +}; + +/* Command to TDLS core module */ +enum TDLS_CMD_CORE_ID { + TDLS_CORE_CMD_TEST_NULL_RCV = 0x00 +}; + +struct TDLS_CMD_CORE_TEST_NULL_RCV { + + uint32_t u4PM; +}; + +struct TDLS_CMD_CORE { + + uint32_t u4Command; + + uint8_t aucPeerMac[6]; + +#define TDLS_CMD_CORE_RESERVED_SIZE 50 + union { + struct TDLS_CMD_CORE_TEST_NULL_RCV rCmdNullRcv; + uint8_t Reserved[TDLS_CMD_CORE_RESERVED_SIZE]; + } Content; +}; + +enum TDLS_EVENT_HOST_ID { + TDLS_HOST_EVENT_TEAR_DOWN = 0x00, + TDLS_HOST_EVENT_TX_DONE +}; + +enum TDLS_EVENT_HOST_SUBID_TEAR_DOWN { + TDLS_HOST_EVENT_TD_PTI_TIMEOUT = 0x00, + TDLS_HOST_EVENT_TD_AGE_TIMEOUT, + TDLS_HOST_EVENT_TD_PTI_SEND_FAIL, + TDLS_HOST_EVENT_TD_PTI_SEND_MAX_FAIL, + TDLS_HOST_EVENT_TD_WRONG_NETWORK_IDX, + TDLS_HOST_EVENT_TD_NON_STATE3, + TDLS_HOST_EVENT_TD_LOST_TEAR_DOWN +}; + +enum TDLS_REASON_CODE { + TDLS_REASON_CODE_NONE = 0, + + TDLS_REASON_CODE_UNREACHABLE = 25, + TDLS_REASON_CODE_UNSPECIFIED = 26, + + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_UNKNOWN = 0x80, /*128*/ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_WIFI_OFF = 0x81, /*129*/ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_ROAMING = 0x82, /*130*/ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_TIMEOUT = 0x83, /*131*/ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_AGE_TIMEOUT = 0x84, /*132*/ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_REKEY = 0x85, /*133*/ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_SEND_FAIL = 0x86, /*134*/ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_SEND_MAX_FAIL = 0x87,/*135*/ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_WRONG_NETWORK_IDX = 0x88,/*136*/ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_NON_STATE3 = 0x89, /*137*/ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_TX_QUOTA_EMPTY = 0x8a, /*138*/ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_LOST_TEAR_DOWN = 0x8b /*139*/ +}; + +/******************************************************************************* + * P U B 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 + ******************************************************************************* + */ +uint32_t TdlsFrameGeneralIeAppend(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, uint8_t *pPkt); + +uint32_t /* TDLS_STATUS */ + +TdlsDataFrameSend_TearDown(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t *pPeerMac, + uint8_t ucActionCode, + uint8_t ucDialogToken, uint16_t u2StatusCode, + uint8_t *pAppendIe, uint32_t AppendIeLen); + +uint32_t /* TDLS_STATUS */ + +TdlsDataFrameSend_CONFIRM(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t *pPeerMac, + uint8_t ucActionCode, + uint8_t ucDialogToken, uint16_t u2StatusCode, + uint8_t *pAppendIe, uint32_t AppendIeLen); + +uint32_t /* TDLS_STATUS */ + +TdlsDataFrameSend_SETUP_REQ(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t *pPeerMac, + uint8_t ucActionCode, + uint8_t ucDialogToken, uint16_t u2StatusCode, + uint8_t *pAppendIe, uint32_t AppendIeLen); + +uint32_t /* TDLS_STATUS */ + +TdlsDataFrameSend_DISCOVERY_REQ(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t *pPeerMac, + uint8_t ucActionCode, + uint8_t ucDialogToken, uint16_t u2StatusCode, + uint8_t *pAppendIe, uint32_t AppendIeLen); + +uint32_t /* TDLS_STATUS */ + +TdlsDataFrameSend_SETUP_RSP(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t *pPeerMac, + uint8_t ucActionCode, + uint8_t ucDialogToken, uint16_t u2StatusCode, + uint8_t *pAppendIe, uint32_t AppendIeLen); + +uint32_t /* TDLS_STATUS */ + +TdlsDataFrameSend_DISCOVERY_RSP(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t *pPeerMac, + uint8_t ucActionCode, + uint8_t ucDialogToken, uint16_t u2StatusCode, + uint8_t *pAppendIe, uint32_t AppendIeLen); + +uint32_t TdlsexLinkOper(struct ADAPTER *prAdapter, + void *pvSetBuffer, uint32_t u4SetBufferLen, + uint32_t *pu4SetInfoLen); + +uint32_t TdlsexLinkMgt(struct ADAPTER *prAdapter, + void *pvSetBuffer, uint32_t u4SetBufferLen, + uint32_t *pu4SetInfoLen); + +void TdlsexEventHandle(struct GLUE_INFO *prGlueInfo, + uint8_t *prInBuf, uint32_t u4InBufLen); + +void TdlsEventTearDown(struct GLUE_INFO *prGlueInfo, + uint8_t *prInBuf, uint32_t u4InBufLen); + +void TdlsBssExtCapParse(struct STA_RECORD *prStaRec, + uint8_t *pucIE); + +uint32_t +TdlsSendChSwControlCmd(struct ADAPTER *prAdapter, + void *pvSetBuffer, uint32_t u4SetBufferLen, + uint32_t *pu4SetInfoLen); + +uint32_t +TdlsTxCtrl(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, u_int8_t fgEnable); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* CFG_SUPPORT_TDLS */ + +#endif /* _TDLS_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/wapi.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/wapi.h new file mode 100644 index 0000000000000..34552dae5c2b9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/wapi.h @@ -0,0 +1,134 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + + +#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) ((struct WAPI_INFO_ELEM *) fp) + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +void wapiGenerateWAPIIE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +u_int8_t wapiParseWapiIE(IN struct WAPI_INFO_ELEM + *prInfoElem, OUT struct WAPI_INFO *prWapiInfo); + +u_int8_t wapiPerformPolicySelection(IN struct ADAPTER + *prAdapter, IN struct BSS_DESC *prBss); + +/* BOOLEAN */ +/* wapiUpdateTxKeyIdx ( */ +/* IN P_STA_RECORD_T prStaRec, */ +/* IN UINT_8 ucWlanIdx */ +/* ); */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#endif +#endif /* _WAPI_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/wlan_typedef.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/wlan_typedef.h new file mode 100644 index 0000000000000..d80df8fcf391f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/wlan_typedef.h @@ -0,0 +1,139 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + + +#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 structure, to describe the + * attributes used in a common BSS. + */ +struct BSS_INFO; /* declare BSS_INFO_T */ +struct BSS_INFO; /* declare P2P_DEV_INFO_T */ + + +struct AIS_SPECIFIC_BSS_INFO; /* declare AIS_SPECIFIC_BSS_INFO_T */ +struct P2P_SPECIFIC_BSS_INFO; /* declare P2P_SPECIFIC_BSS_INFO_T */ +struct BOW_SPECIFIC_BSS_INFO; /* declare BOW_SPECIFIC_BSS_INFO_T */ +/* CFG_SUPPORT_WFD */ +struct WFD_CFG_SETTINGS; /* declare WFD_CFG_SETTINGS_T */ + +/* BSS related structures */ +/* Type definition for BSS_DESC structure, to describe parameter + * sets of a particular BSS + */ +struct BSS_DESC; /* declare BSS_DESC */ + +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP +struct ROAM_BSS_DESC; /* declare ROAM_BSS_DESC_T */ +#endif + +#if CFG_SUPPORT_PASSPOINT +struct HS20_INFO; /* declare HS20_INFO_T */ +#endif /* CFG_SUPPORT_PASSPOINT */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#endif /* _WLAN_TYPEDEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/wmm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/wmm.h new file mode 100644 index 0000000000000..56ee1e6c344c8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/wmm.h @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. + * If not, see . + */ + +#ifndef WMM_HDR_H +#define WMM_HDR_H + +#define VENDOR_OUI_TYPE_TSRS 8 +#define VENDOR_OUI_TYPE_TSM 7 +#define VENDOR_OUI_TYPE_EDCALIFE 9 +#define WLAN_MAC_ACTION_ADDTS_LEN (WLAN_MAC_MGMT_HEADER_HTC_LEN + 66) +#define WLAN_MAC_ACTION_DELTS_LEN (WLAN_MAC_MGMT_HEADER_HTC_LEN + 7) +#define TSPEC_POLICY_CHECK_INTERVAL 2500 /* unit ms */ + +#define WMM_TS_STATUS_ADMISSION_ACCEPTED 0 +#define WMM_TS_STATUS_ADDTS_INVALID_PARAM 1 +#define WMM_TS_STATUS_ADDTS_REFUSED 3 +#define WMM_TS_STATUS_ASSOC_QOS_FAILED 0xc8 +#define WMM_TS_STATUS_POLICY_CONFIG_REFUSED 0xc9 +#define WMM_TS_STATUS_ASSOC_INSUFFICIENT_BANDWIDTH 0xca +#define WMM_TS_STATUS_ASSOC_INVALID_PARAM 0xcb + +#define CFG_SUPPORT_SOFT_ACM 1 /* do Admission Control in driver */ +/* + * In WMM, TSs are identified with TIDs values 0 through 7. Any TID may + * map onto any UP and thus onto any AC, however for each AC used between + * an RA and TA, only the following combinations are valid: + * No TS, One uplink TS, one Download link TS, one uplink and one uplink + * TS, one bi-directional TS. + * so maximum 8 TSs are allowed in a RA & TA context. + */ +#define WMM_TSPEC_ID_NUM 8 + +/*WMM-2.2.11 WMM TSPEC IE*/ +#define ELEM_MAX_LEN_WMM_TSPEC 61 + +enum WMM_ADDTS_STATUS { + ADDTS_ACCEPTED = 0, + ADDTS_INVALID_PARAMS = 1, + ADDTS_REFUSED = 2 +}; + +enum TSPEC_OP_CODE { + TX_ADDTS_REQ, + RX_ADDTS_RSP, + TX_DELTS_REQ, + RX_DELTS_REQ, + DISC_DELTS_REQ, + UPDATE_TS_REQ +}; + +enum QOS_TS_STATE { + QOS_TS_INACTIVE, + QOS_TS_ACTIVE, + QOS_TS_SETUPING, + QOS_TS_STATE_MAX +}; + +enum TSPEC_DIR { + UPLINK_TS = 0, + DOWNLINK_TS = 1, + BI_DIR_TS = 3 +}; + +struct TSPEC_INFO { + struct TIMER rAddTsTimer; + uint8_t ucToken; + u_int8_t fgUapsd; + enum ENUM_ACI eAC:8; + enum TSPEC_DIR eDir:8; + enum QOS_TS_STATE eState:8; + /* debug information */ + uint16_t u2MediumTime; + uint32_t u4PhyRate; +}; + +struct TSM_TRIGGER_COND { + uint8_t ucCondition; + uint8_t ucAvgErrThreshold; + uint8_t ucConsecutiveErr; + uint8_t ucDelayThreshold; + uint8_t ucMeasureCount; + /* In this time frame, for one condition, only once report is allowed */ + uint8_t ucTriggerTimeout; +}; + +struct RM_TSM_REQ { + uint16_t u2Duration; /* unit: TUs */ + uint8_t aucPeerAddr[MAC_ADDR_LEN]; + uint8_t ucToken; + uint8_t ucTID; + uint8_t ucACI; + uint8_t ucB0Range; /* 2^(i-1)*ucB0Range =< delay < 2^i * ucB0Range */ + struct TSM_TRIGGER_COND rTriggerCond; +}; + +struct ACTIVE_RM_TSM_REQ { + struct LINK_ENTRY rLinkEntry; + struct RM_TSM_REQ *prTsmReq; + struct TIMER rTsmTimer; +}; + +#if CFG_SUPPORT_SOFT_ACM +struct SOFT_ACM_CTRL { + uint32_t u4RemainTime; + uint32_t u4AdmittedTime; + uint32_t u4IntervalEndSec; + uint16_t u2DeqNum; +}; +#endif + +struct WMM_INFO { + /* A TS is identified uniquely by its TID value within the context of + ** the RA and TA + ** the index is TID for this array + */ + struct TSPEC_INFO arTsInfo[WMM_TSPEC_ID_NUM]; + struct LINK rActiveTsmReq; + OS_SYSTIME rTriggeredTsmRptTime; + struct TIMER rTsmTimer; +#if CFG_SUPPORT_SOFT_ACM + struct TIMER rAcmDeqTimer; + struct SOFT_ACM_CTRL arAcmCtrl[ACI_NUM]; /* 0 ~ 3, BE, BK, VI, VO */ +#endif +}; + +struct WMM_ADDTS_RSP_STEP_PARAM { + uint8_t ucDlgToken; + uint8_t ucStatusCode; + uint8_t ucApsd; + enum TSPEC_DIR eDir:8; + uint16_t u2EdcaLifeTime; + uint16_t u2MediumTime; + uint32_t u4PhyRate; +}; + +struct MSG_TS_OPERATE { + struct MSG_HDR rMsgHdr; + enum TSPEC_OP_CODE eOpCode; + uint8_t ucTid; + struct PARAM_QOS_TSPEC rTspecParam; +}; + +#define WMM_TSINFO_TRAFFIC_TYPE(tsinfo) (tsinfo & BIT(0)) +#define WMM_TSINFO_TSID(tsinfo) ((tsinfo & BITS(1, 4)) >> 1) +#define WMM_TSINFO_DIR(tsinfo) ((tsinfo & BITS(5, 6)) >> 5) +#define WMM_TSINFO_AC(tsinfo) ((tsinfo & BITS(7, 8)) >> 7) +#define WMM_TSINFO_PSB(tsinfo) ((tsinfo & BIT(10)) >> 10) +#define WMM_TSINFO_UP(tsinfo) ((tsinfo & BITS(11, 13)) >> 11) + +#define TSM_TRIGGER_CONDITION_ALL BITS(0, 2) +#define TSM_TRIGGER_AVG BIT(0) +#define TSM_TRIGGER_CONSECUTIVE BIT(1) +#define TSM_TIRGGER_DELAY BIT(2) + +extern uint8_t const aucUp2ACIMap[8]; +void wmmFillTsinfo(struct PARAM_QOS_TSINFO *prTsInfo, uint8_t *pucTsInfo); +void wmmSetupTspecTimeOut(struct ADAPTER *prAdapter, unsigned long ulParam); +void wmmStartTsmMeasurement(struct ADAPTER *prAdapter, unsigned long ulParam); +void wmmRunEventTSOperate(struct ADAPTER *prAdapter, struct MSG_HDR *prMsgHdr); +u_int8_t wmmParseQosAction(struct ADAPTER *prAdapter, struct SW_RFB *prSwRfb); +u_int8_t wmmParseTspecIE(struct ADAPTER *prAdapter, uint8_t *pucIE, + struct PARAM_QOS_TSPEC *prTspec); +void wmmTspecSteps(struct ADAPTER *prAdapter, uint8_t ucTid, + enum TSPEC_OP_CODE eOpCode, void *prStepParams); +uint8_t wmmHasActiveTspec(struct WMM_INFO *prWmmInfo); +void wmmNotifyDisconnected(struct ADAPTER *prAdapter); +void wmmComposeTsmRpt(struct ADAPTER *prAdapter, struct CMD_INFO *prCmdInfo, + uint8_t *pucEventBuf); +void wmmInit(IN struct ADAPTER *prAdapter); +void wmmUnInit(IN struct ADAPTER *prAdapter); +u_int8_t wmmTsmIsOngoing(struct ADAPTER *prAdapter); +void wmmNotifyDisconnected(struct ADAPTER *prAdapter); +void wmmRemoveAllTsmMeasurement(struct ADAPTER *prAdapter, + u_int8_t fgOnlyTriggered); +uint8_t wmmCalculateUapsdSetting(struct ADAPTER *prAdapter); +uint32_t wmmDumpActiveTspecs(struct ADAPTER *prAdapter, uint8_t *pucBuffer, + uint16_t u2BufferLen); +#if CFG_SUPPORT_SOFT_ACM +u_int8_t wmmAcmCanDequeue(struct ADAPTER *prAdapter, uint8_t ucAc, + uint32_t u4PktTxTime); +void wmmAcmTxStatistic(struct ADAPTER *prAdapter, uint8_t ucAc, + uint32_t u4Remain, uint16_t u2DeqNum); + +uint32_t wmmCalculatePktUsedTime(struct BSS_INFO *prBssInfo, + struct STA_RECORD *prStaRec, + uint16_t u2PktLen); +void wmmPrepareFastUsedTimeCal(struct ADAPTER *prAdapter); +uint32_t wmmFastCalPktUsedTime(struct WMM_INFO *prWmmInfo, uint8_t ucAc, + uint16_t u2PktLen); +#endif /* CFG_SUPPORT_SOFT_ACM */ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/wnm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/wnm.h new file mode 100644 index 0000000000000..0f71de00afa7e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/mgmt/wnm.h @@ -0,0 +1,184 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + + +#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 + ******************************************************************************* + */ + +struct TIMINGMSMT_PARAM { + u_int8_t fgInitiator; + uint8_t ucTrigger; + uint8_t ucDialogToken; /* Dialog Token */ + uint8_t ucFollowUpDialogToken; /* Follow Up Dialog Token */ + uint32_t u4ToD; /* Timestamp of Departure [10ns] */ + uint32_t u4ToA; /* Timestamp of Arrival [10ns] */ +}; + +struct BSS_TRANSITION_MGT_PARAM_T { + /* for Query */ + uint8_t ucDialogToken; + uint8_t ucQueryReason; + /* for Request */ + uint8_t ucRequestMode; + uint16_t u2DisassocTimer; + uint16_t u2TermDuration; + uint8_t aucTermTsf[8]; + uint8_t ucSessionURLLen; + uint8_t aucSessionURL[255]; + /* for Respone */ + u_int8_t fgPendingResponse:1; + u_int8_t fgUnsolicitedReq:1; + u_int8_t fgReserved:6; + uint8_t ucStatusCode; + uint8_t ucTermDelay; + uint8_t aucTargetBssid[MAC_ADDR_LEN]; + uint8_t *pucOurNeighborBss; + uint16_t u2OurNeighborBssLen; +}; + +/******************************************************************************* + * P U B 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 BTM_REQ_MODE_CAND_INCLUDED_BIT BIT(0) +#define BTM_REQ_MODE_ABRIDGED BIT(1) +#define BTM_REQ_MODE_DISC_IMM BIT(2) +#define BTM_REQ_MODE_BSS_TERM_INCLUDE BIT(3) +#define BTM_REQ_MODE_ESS_DISC_IMM BIT(4) + +#define BSS_TRANSITION_MGT_STATUS_ACCEPT 0 +#define BSS_TRANSITION_MGT_STATUS_UNSPECIFIED 1 +#define BSS_TRANSITION_MGT_STATUS_NEED_SCAN 2 +#define BSS_TRANSITION_MGT_STATUS_CAND_NO_CAPACITY 3 +#define BSS_TRANSITION_MGT_STATUS_TERM_UNDESIRED 4 +#define BSS_TRANSITION_MGT_STATUS_TERM_DELAY_REQUESTED 5 +#define BSS_TRANSITION_MGT_STATUS_CAND_LIST_PROVIDED 6 +#define BSS_TRANSITION_MGT_STATUS_CAND_NO_CANDIDATES 7 +#define BSS_TRANSITION_MGT_STATUS_LEAVING_ESS 8 + +/* 802.11v: define Transtion and Transition Query reasons */ +#define BSS_TRANSITION_BETTER_AP_FOUND 6 +#define BSS_TRANSITION_LOW_RSSI 16 +#define BSS_TRANSITION_INCLUDE_PREFER_CAND_LIST 19 +#define BSS_TRANSITION_LEAVING_ESS 20 + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +void wnmWNMAction(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +void wnmReportTimingMeas(IN struct ADAPTER *prAdapter, + IN uint8_t ucStaRecIndex, IN uint32_t u4ToD, + IN uint32_t u4ToA); + +#if WNM_UNIT_TEST +void wnmTimingMeasUnitTest1(struct ADAPTER *prAdapter, + uint8_t ucStaRecIndex); +#endif + +void wnmRecvBTMRequest(IN struct ADAPTER *prAdapter, IN struct SW_RFB *prSwRfb); + +void wnmSendBTMQueryFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +void wnmSendBTMResponseFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +uint8_t wnmGetBtmToken(void); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _WNM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/adapter.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/adapter.h new file mode 100644 index 0000000000000..5a48aa1c3571b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/adapter.h @@ -0,0 +1,1784 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \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. + */ + +#ifndef _ADAPTER_H +#define _ADAPTER_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#if CFG_SUPPORT_PASSPOINT +#include "hs20.h" +#endif /* CFG_SUPPORT_PASSPOINT */ + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +enum { + ENUM_SW_TEST_MODE_NONE = 0, + ENUM_SW_TEST_MODE_SIGMA_AC = 0x1, + ENUM_SW_TEST_MODE_SIGMA_WFD = 0x2, + ENUM_SW_TEST_MODE_CTIA = 0x3, + ENUM_SW_TEST_MODE_SIGMA_TDLS = 0x4, + ENUM_SW_TEST_MODE_SIGMA_P2P = 0x5, + ENUM_SW_TEST_MODE_SIGMA_N = 0x6, + ENUM_SW_TEST_MODE_SIGMA_HS20_R1 = 0x7, + ENUM_SW_TEST_MODE_SIGMA_HS20_R2 = 0x8, + ENUM_SW_TEST_MODE_SIGMA_PMF = 0x9, + ENUM_SW_TEST_MODE_SIGMA_WMMPS = 0xA, + ENUM_SW_TEST_MODE_SIGMA_AC_R2 = 0xB, + ENUM_SW_TEST_MODE_SIGMA_NAN = 0xC, + ENUM_SW_TEST_MODE_SIGMA_AC_AP = 0xD, + ENUM_SW_TEST_MODE_SIGMA_N_AP = 0xE, + ENUM_SW_TEST_MODE_SIGMA_WFDS = 0xF, + ENUM_SW_TEST_MODE_SIGMA_WFD_R2 = 0x10, + ENUM_SW_TEST_MODE_SIGMA_LOCATION = 0x11, + ENUM_SW_TEST_MODE_SIGMA_TIMING_MANAGEMENT = 0x12, + ENUM_SW_TEST_MODE_SIGMA_WMMAC = 0x13, + ENUM_SW_TEST_MODE_SIGMA_VOICE_ENT = 0x14 +}; + +struct ESS_SCAN_RESULT_T { + uint8_t aucBSSID[MAC_ADDR_LEN]; + uint16_t u2SSIDLen; + uint8_t aucSSID[32]; +}; + +struct WLAN_INFO { + struct PARAM_BSSID_EX rCurrBssId; + + /* Scan Result */ + struct PARAM_BSSID_EX arScanResult[CFG_MAX_NUM_BSS_LIST]; + uint8_t *apucScanResultIEs[CFG_MAX_NUM_BSS_LIST]; + uint32_t u4ScanResultNum; + + struct ESS_SCAN_RESULT_T arScanResultEss[CFG_MAX_NUM_BSS_LIST]; + uint32_t u4ScanResultEssNum; + uint32_t u4ScanDbgTimes1; + uint32_t u4ScanDbgTimes2; + uint32_t u4ScanDbgTimes3; + uint32_t u4ScanDbgTimes4; + + /* IE pool for Scanning Result */ + uint8_t aucScanIEBuf[CFG_MAX_COMMON_IE_BUF_LEN]; + uint32_t u4ScanIEBufferUsage; + + OS_SYSTIME u4SysTime; + + /* connection parameter (for Ad-Hoc) */ + uint16_t u2BeaconPeriod; + uint16_t u2AtimWindow; + + uint8_t eDesiredRates[PARAM_MAX_LEN_RATES]; + struct CMD_LINK_ATTRIB eLinkAttr; +/* CMD_PS_PROFILE_T ePowerSaveMode; */ + struct CMD_PS_PROFILE arPowerSaveMode[MAX_BSSID_NUM]; + struct CMD_PS_PROFILE arPowerSaveWowMode[MAX_BSSID_NUM]; + + /* Support power save flag for the caller */ + uint32_t u4PowerSaveFlag[MAX_BSSID_NUM]; + + /* trigger parameter */ + enum ENUM_RSSI_TRIGGER_TYPE eRssiTriggerType; + int32_t rRssiTriggerValue; + + /* Privacy Filter */ + enum ENUM_PARAM_PRIVACY_FILTER ePrivacyFilter; + + /* RTS Threshold */ + uint32_t eRtsThreshold; + + /* Network Type */ + uint8_t ucNetworkType; + + /* Network Type In Use */ + uint8_t ucNetworkTypeInUse; + + /* Force enable/disable power save mode*/ + u_int8_t fgEnSpecPwrMgt; + +}; + +/* Session for CONNECTION SETTINGS */ +struct CONNECTION_SETTINGS { + + uint8_t aucMacAddress[MAC_ADDR_LEN]; + + uint8_t ucDelayTimeOfDisconnectEvent; + + u_int8_t fgIsConnByBssidIssued; + uint8_t aucBSSID[MAC_ADDR_LEN]; + uint8_t aucBSSIDHint[MAC_ADDR_LEN]; + + u_int8_t fgIsConnReqIssued; + u_int8_t fgIsDisconnectedByNonRequest; + enum ENUM_RECONNECT_LEVEL_T eReConnectLevel; + + uint8_t ucSSIDLen; + uint8_t aucSSID[ELEM_MAX_LEN_SSID]; + + enum ENUM_PARAM_OP_MODE eOPMode; + + enum ENUM_PARAM_CONNECTION_POLICY eConnectionPolicy; + + enum ENUM_PARAM_AD_HOC_MODE eAdHocMode; + + enum ENUM_PARAM_AUTH_MODE eAuthMode; + + enum ENUM_WEP_STATUS eEncStatus; + + u_int8_t fgIsScanReqIssued; + + /* MIB attributes */ + uint16_t u2BeaconPeriod; + + uint16_t u2RTSThreshold; /* User desired setting */ + + uint16_t u2DesiredNonHTRateSet; /* User desired setting */ + + uint8_t ucAdHocChannelNum; /* For AdHoc */ + + enum ENUM_BAND eAdHocBand; /* For AdHoc */ + + uint32_t u4FreqInKHz; /* Center frequency */ + + /* ATIM windows using for IBSS power saving function */ + uint16_t u2AtimWindow; + + /* Features */ + u_int8_t fgIsEnableRoaming; + + u_int8_t fgIsAdHocQoSEnable; + + /* Indicates if OKC feature is enabled in wpa_supplicant for this ESS */ + u_int8_t fgOkcEnabled; + /* Indicates that there's a PMKSA associated with this ESS + ** in supplicant to generate PMKID for each BSS + */ + u_int8_t fgOkcPmksaReady; + + enum ENUM_PARAM_PHY_CONFIG eDesiredPhyConfig; + + /* Used for AP mode for desired channel and bandwidth */ + uint16_t u2CountryCode; + uint8_t uc2G4BandwidthMode; /* 20/40M or 20M only *//* Not used */ + uint8_t uc5GBandwidthMode; /* 20/40M or 20M only *//* Not used */ + +#if CFG_SUPPORT_802_11D + u_int8_t fgMultiDomainCapabilityEnabled; +#endif /* CFG_SUPPORT_802_11D */ + +#if 1 /* CFG_SUPPORT_WAPI */ + u_int8_t fgWapiMode; + uint32_t u4WapiSelectedGroupCipher; + uint32_t u4WapiSelectedPairwiseCipher; + uint32_t u4WapiSelectedAKMSuite; +#endif + + /* CR1486, CR1640 */ + /* for WPS, disable the privacy check for AP selection policy */ + u_int8_t fgPrivacyCheckDisable; + + /* b0~3: trigger-en AC0~3. b4~7: delivery-en AC0~3 */ + uint8_t bmfgApsdEnAc; + + /* for RSN info store, when upper layer set rsn info */ + struct RSN_INFO rRsnInfo; + + u_int8_t fgSecModeChangeStartTimer; + + /* Support AP Selection */ + struct LINK_MGMT rBlackList; + +#if CFG_SUPPORT_CFG80211_AUTH + struct cfg80211_bss *bss; + + u_int8_t fgIsConnInitialized; + + u_int8_t fgIsSendAssoc; + + u_int8_t ucAuthDataLen; + /* Temp assign a fixed large number + * Additional elements for Authentication frame, + * starts with the Authentication transaction sequence number field + */ + u_int8_t aucAuthData[AUTH_DATA_MAX_LEN]; + u_int8_t ucChannelNum; + uint8_t ucRoleIdx; + uint8_t fgIsP2pConn; +#endif +#if CFG_SUPPORT_OWE + /* for OWE info store, when upper layer set rsn info */ + struct OWE_INFO_T rOweInfo; +#endif +}; + +struct BSS_INFO { + + enum ENUM_NETWORK_TYPE eNetworkType; + + /* Private data parameter for each NETWORK type usage. */ + uint32_t u4PrivateData; + /* P2P network type has 3 network interface to distinguish. */ + + /* Connected Flag used in AIS_NORMAL_TR */ + enum ENUM_PARAM_MEDIA_STATE eConnectionState; + /* The Media State that report to HOST */ + enum ENUM_PARAM_MEDIA_STATE eConnectionStateIndicated; + + /* Current Operation Mode - Infra/IBSS */ + enum ENUM_OP_MODE eCurrentOPMode; +#if CFG_ENABLE_WIFI_DIRECT + enum ENUM_OP_MODE eIntendOPMode; +#endif + +#if (CFG_SUPPORT_DFS_MASTER == 1) + u_int8_t fgIsDfsActive; +#endif + + u_int8_t fgIsInUse; /* For CNM to assign BSS_INFO */ + u_int8_t fgIsNetActive; /* TRUE if this network has been activated */ + + uint8_t ucBssIndex; /* BSS_INFO_T index */ + + uint8_t ucReasonOfDisconnect; /* Used by media state indication */ + + uint8_t ucSSIDLen; /* Length of SSID */ + +#if CFG_ENABLE_WIFI_DIRECT + /* For Hidden SSID usage. */ + enum ENUM_HIDDEN_SSID_TYPE eHiddenSsidType; +#endif + + uint8_t aucSSID[ELEM_MAX_LEN_SSID]; /* SSID used in this BSS */ + + uint8_t aucBSSID[MAC_ADDR_LEN]; /* The BSSID of the associated BSS */ + + /* Owned MAC Address used in this BSS */ + uint8_t aucOwnMacAddr[MAC_ADDR_LEN]; + + uint8_t ucOwnMacIndex; /* Owned MAC index used in this BSS */ + + /* For Infra Mode, and valid only if + * eConnectionState == MEDIA_STATE_CONNECTED + */ + struct STA_RECORD *prStaRecOfAP; + /* For IBSS/AP Mode, all known STAs in current BSS */ + struct LINK rStaRecOfClientList; + + /* For open Mode, BC/MC Tx wlan index, For STA, BC/MC Rx wlan index */ + uint8_t ucBMCWlanIndex; + + /* For AP Mode, BC/MC Tx wlan index, For STA, BC/MC Rx wlan index */ + uint8_t ucBMCWlanIndexS[MAX_KEY_NUM]; + uint8_t ucBMCWlanIndexSUsed[MAX_KEY_NUM]; + + u_int8_t fgBcDefaultKeyExist; /* Bc Transmit key exist or not */ + /* Bc default key idx, for STA, the Rx just set, + * for AP, the tx key id + */ + uint8_t ucBcDefaultKeyIdx; + + uint8_t wepkeyUsed[MAX_KEY_NUM]; + uint8_t wepkeyWlanIdx; /* wlan index of the wep key */ + + uint16_t u2CapInfo; /* Change Detection */ + + uint16_t u2BeaconInterval; /* The Beacon Interval of this BSS */ + + uint16_t u2ATIMWindow; /* For IBSS Mode */ + + /* For Infra Mode, it is the Assoc ID assigned by AP. */ + uint16_t u2AssocId; + + uint8_t ucDTIMPeriod; /* For Infra/AP Mode */ + u_int8_t fgTIMPresent; + + /* For AP Mode, it is the DTIM value we should carried in + * the Beacon of next TBTT. + */ + uint8_t ucDTIMCount; + + /* Available PHY Type Set of this peer + * (This is deduced from received struct BSS_DESC) + */ + uint8_t ucPhyTypeSet; + + /* The Basic PHY Type Index, used to setup Phy Capability */ + uint8_t ucNonHTBasicPhyType; + /* The configuration of AdHoc/AP Mode. e.g. 11g or 11b */ + uint8_t ucConfigAdHocAPMode; + u_int8_t fgIsWepCipherGroup; + + /* For Infra/AP Mode, it is a threshold of Beacon Lost Count to + * confirm connection was lost + */ + uint8_t ucBeaconTimeoutCount; + + /* For IBSS Mode, to keep use same BSSID + * to extend the life cycle of an IBSS + */ + u_int8_t fgHoldSameBssidForIBSS; + /* For AP/IBSS Mode, it is used to indicate that Beacon is sending */ + u_int8_t fgIsBeaconActivated; + + struct MSDU_INFO *prBeacon; /* For AP/IBSS Mode - Beacon Frame */ + + /* For IBSS Mode - To indicate that we can reply ProbeResp Frame. + * In current TBTT interval + */ + u_int8_t fgIsIBSSMaster; + + /* From Capability Info. of AssocResp Frame + * AND of Beacon/ProbeResp Frame + */ + u_int8_t fgIsShortPreambleAllowed; + /* Short Preamble is enabled in current BSS. */ + u_int8_t fgUseShortPreamble; + /* Short Slot Time is enabled in current BSS. */ + u_int8_t fgUseShortSlotTime; + + /* Operational Rate Set of current BSS */ + uint16_t u2OperationalRateSet; + uint16_t u2BSSBasicRateSet; /* Basic Rate Set of current BSS */ + + /* Used for composing Beacon Frame in AdHoc or AP Mode */ + uint8_t ucAllSupportedRatesLen; + uint8_t aucAllSupportedRates[RATE_NUM_SW]; + /* TODO(Kevin): Number of associated clients */ + uint8_t ucAssocClientCnt; + + u_int8_t fgIsProtection; + /* For Infra/AP/IBSS Mode, it is used to indicate if we support WMM in + * current BSS. + */ + u_int8_t fgIsQBSS; + u_int8_t fgIsNetAbsent; /* TRUE: BSS is absent, FALSE: BSS is present */ + + uint32_t u4RsnSelectedGroupCipher; + uint32_t u4RsnSelectedPairwiseCipher; + uint32_t u4RsnSelectedAKMSuite; + uint16_t u2RsnSelectedCapInfo; + + /*-------------------------------------------------------------------*/ + /* Operation mode change notification */ + /*-------------------------------------------------------------------*/ + /*Need to change OpMode channel width*/ + u_int8_t fgIsOpChangeChannelWidth; + /* The OpMode channel width that we want to change to*/ + /* 0:20MHz, 1:40MHz, 2:80MHz, 3:160MHz 4:80+80MHz*/ + uint8_t ucOpChangeChannelWidth; + u_int8_t fgIsOpChangeNss; /*Need to change OpMode Nss*/ + uint8_t ucOpChangeNss; /* The OpMode Nss that we want to change to */ + + PFN_OPMODE_NOTIFY_DONE_FUNC pfOpChangeHandler; + + enum ENUM_OP_NOTIFY_STATE_T aucOpModeChangeState[OP_NOTIFY_TYPE_NUM]; + + uint8_t aucOpModeChangeRetryCnt[OP_NOTIFY_TYPE_NUM]; + + + /*-------------------------------------------------------------------*/ + /* Power Management related information */ + /*-------------------------------------------------------------------*/ + struct PM_PROFILE_SETUP_INFO rPmProfSetupInfo; + + /*-------------------------------------------------------------------*/ + /* WMM/QoS related information */ + /*-------------------------------------------------------------------*/ + /* Used to detect the change of EDCA parameters. For AP mode, + * the value is used in WMM IE + */ + uint8_t ucWmmParamSetCount; + + struct AC_QUE_PARMS arACQueParms[WMM_AC_INDEX_NUM]; + /* For AP mode, broadcast the CWminLog2 */ + uint8_t aucCWminLog2ForBcast[WMM_AC_INDEX_NUM]; + /* For AP mode, broadcast the CWmaxLog2 */ + uint8_t aucCWmaxLog2ForBcast[WMM_AC_INDEX_NUM]; + /* For AP mode, broadcast the value */ + struct AC_QUE_PARMS arACQueParmsForBcast[WMM_AC_INDEX_NUM]; + uint8_t ucWmmQueSet; +#if (CFG_HW_WMM_BY_BSS == 1) + u_int8_t fgIsWmmInited; +#endif + + /*-------------------------------------------------------------------*/ + /* 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 ENUM_BAND eBand; + uint8_t ucPrimaryChannel; + uint8_t ucHtOpInfo1; + uint16_t u2HtOpInfo2; + uint16_t u2HtOpInfo3; + uint8_t ucNss; /* Own OP Nss */ + /*-------------------------------------------------------------------*/ + /* 802.11ac VHT operation IE when (prStaRec->ucPhyTypeSet */ + /* & PHY_TYPE_BIT_VHT) is true. They have the same definition with */ + /* fields of information element (EASON) */ + /*-------------------------------------------------------------------*/ +#if 1 /* CFG_SUPPORT_802_11AC */ + uint8_t ucVhtChannelWidth; + uint8_t ucVhtChannelFrequencyS1; + uint8_t ucVhtChannelFrequencyS2; + uint16_t u2VhtBasicMcsSet; +#endif + /*-------------------------------------------------------------------*/ + /* Required protection modes (CM) */ + /*-------------------------------------------------------------------*/ + u_int8_t fgErpProtectMode; + enum ENUM_HT_PROTECT_MODE eHtProtectMode; + enum ENUM_GF_MODE eGfOperationMode; + enum ENUM_RIFS_MODE eRifsOperationMode; + + u_int8_t fgObssErpProtectMode; /* GO only */ + enum ENUM_HT_PROTECT_MODE eObssHtProtectMode; /* GO only */ + enum ENUM_GF_MODE eObssGfOperationMode; /* GO only */ + u_int8_t fgObssRifsOperationMode; /* GO only */ + + /*-------------------------------------------------------------------*/ + /* OBSS to decide if 20/40M bandwidth is permitted. */ + /* The first member indicates the following channel list length. */ + /*-------------------------------------------------------------------*/ + u_int8_t fgAssoc40mBwAllowed; + u_int8_t fg40mBwAllowed; + enum ENUM_CHNL_EXT eBssSCO; /* Real setting for HW + * 20/40M AP mode will always set 40M, + * but its OP IE can be changed. + */ + uint8_t auc2G_20mReqChnlList[CHNL_LIST_SZ_2G + 1]; + uint8_t auc2G_NonHtChnlList[CHNL_LIST_SZ_2G + 1]; + uint8_t auc2G_PriChnlList[CHNL_LIST_SZ_2G + 1]; + uint8_t auc2G_SecChnlList[CHNL_LIST_SZ_2G + 1]; + + uint8_t auc5G_20mReqChnlList[CHNL_LIST_SZ_5G + 1]; + uint8_t auc5G_NonHtChnlList[CHNL_LIST_SZ_5G + 1]; + uint8_t auc5G_PriChnlList[CHNL_LIST_SZ_5G + 1]; + uint8_t auc5G_SecChnlList[CHNL_LIST_SZ_5G + 1]; + + /*-------------------------------------------------------------------*/ + /* Scan related information */ + /*-------------------------------------------------------------------*/ + /* Set scanning MAC OUI */ + u_int8_t fgIsScanOuiSet; + uint8_t ucScanOui[MAC_OUI_LEN]; + + struct TIMER rObssScanTimer; + uint16_t u2ObssScanInterval; /* in unit of sec */ + + u_int8_t fgObssActionForcedTo20M; /* GO only */ + u_int8_t fgObssBeaconForcedTo20M; /* GO only */ + + /*--------------------------------------------------------------------*/ + /* HW Related Fields (Kevin) */ + /*--------------------------------------------------------------------*/ + /* The default rate code copied to MAC TX Desc */ + uint16_t u2HwDefaultFixedRateCode; + uint16_t u2HwLPWakeupGuardTimeUsec; + + uint8_t ucBssFreeQuota; /* The value is updated from FW */ + +#if CFG_ENABLE_GTK_FRAME_FILTER + struct IPV4_NETWORK_ADDRESS_LIST *prIpV4NetAddrList; +#endif + uint16_t u2DeauthReason; + +#if CFG_SUPPORT_TDLS + u_int8_t fgTdlsIsProhibited; + u_int8_t fgTdlsIsChSwProhibited; +#endif +#if CFG_SUPPORT_PNO + u_int8_t fgIsPNOEnable; + u_int8_t fgIsNetRequestInActive; +#endif + + /*link layer statistics */ + struct WIFI_WMM_AC_STAT arLinkStatistics[WMM_AC_INDEX_NUM]; + + uint32_t u4CoexPhyRateLimit; + +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + uint8_t ucRoamSkipTimes; + u_int8_t fgGoodRcpiArea; + u_int8_t fgPoorRcpiArea; +#endif + + u_int8_t fgIsGranted; + enum ENUM_BAND eBandGranted; + uint8_t ucPrimaryChannelGranted; + struct PARAM_CUSTOM_ACL rACL; + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + struct AP_PMF_CFG rApPmfCfg; +#endif + + uint8_t ucCountryIELen; + uint8_t aucCountryStr[3]; + uint8_t aucSubbandTriplet[253]; + + enum ENUM_KEY_ACTION_TYPE_T eKeyAction; + enum ENUM_IFTYPE eIftype; + + enum PARAM_POWER_MODE ePowerModeFromUser; +}; + +/* Support AP Selection */ +struct ESS_CHNL_INFO { + uint8_t ucChannel; + uint8_t ucUtilization; + uint8_t ucApNum; +}; +/* end Support AP Selection */ + +struct NEIGHBOR_AP_T { + struct LINK_ENTRY rLinkEntry; + uint8_t aucBssid[MAC_ADDR_LEN]; + u_int8_t fgHT:1; + u_int8_t fgSameMD:1; + u_int8_t fgRmEnabled:1; + u_int8_t fgFromBtm:1; + u_int8_t fgQoS:1; + uint8_t ucReserved:3; + u_int8_t fgPrefPresence; + uint8_t ucPreference; + uint8_t ucChannel; + uint64_t u8TermTsf; +}; + +struct AIS_SPECIFIC_BSS_INFO { + /* This value indicate the roaming type used in AIS_JOIN */ + uint8_t ucRoamingAuthTypes; + + u_int8_t fgIsIBSSActive; + + /*! \brief Global flag to let arbiter stay at standby + * and not connect to any network + */ + u_int8_t fgCounterMeasure; + +#if 0 + u_int8_t fgWepWapiBcKeyExist; /* WEP WAPI BC key exist flag */ + uint8_t ucWepWapiBcWlanIndex; /* WEP WAPI BC wlan index */ + + /* RSN BC key exist flag, map to key id 0, 1, 2, 3 */ + u_int8_t fgRsnBcKeyExist[4]; + /* RSN BC wlan index, map to key id 0, 1, 2, 3 */ + uint8_t ucRsnBcWlanIndex[4]; +#endif + + /* While Do CounterMeasure procedure, + * check the EAPoL Error report have send out + */ + u_int8_t fgCheckEAPoLTxDone; + + uint32_t u4RsnaLastMICFailTime; + + /* Stored the current bss wpa rsn cap filed, used for roaming policy */ + /* UINT_16 u2RsnCap; */ + struct TIMER 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 + */ + struct TIMER rRsnaBlockTrafficTimer; + struct TIMER rRsnaEAPoLReportTimeoutTimer; + + /* For Keep the Tx/Rx Mic key for TKIP SW Calculate Mic */ + /* This is only one for AIS/AP */ + uint8_t aucTxMicKey[8]; + uint8_t aucRxMicKey[8]; + + /* Buffer for WPA2 PMKID */ + /* The PMKID cache lifetime is expire by media_disconnect_indication */ + uint32_t u4PmkidCandicateCount; + struct PMKID_CANDICATE arPmkidCandicate[CFG_MAX_PMKID_CACHE]; + uint32_t u4PmkidCacheCount; + struct PMKID_ENTRY arPmkidCache[CFG_MAX_PMKID_CACHE]; + u_int8_t fgIndicatePMKID; +#if CFG_SUPPORT_802_11W + u_int8_t fgMgmtProtection; + uint32_t u4SaQueryStart; + uint32_t u4SaQueryCount; + uint8_t ucSaQueryTimedOut; + uint8_t *pucSaQueryTransId; + struct TIMER rSaQueryTimer; + u_int8_t fgBipKeyInstalled; +#endif + uint8_t ucKeyAlgorithmId; + + /* Support AP Selection */ + struct ESS_CHNL_INFO arCurEssChnlInfo[CFG_MAX_NUM_OF_CHNL_INFO]; + uint8_t ucCurEssChnlInfoNum; + struct LINK rCurEssLink; + /* end Support AP Selection */ + + struct BSS_TRANSITION_MGT_PARAM_T rBTMParam; + struct LINK_MGMT rNeighborApList; + OS_SYSTIME rNeiApRcvTime; + uint32_t u4NeiApValidInterval; +}; + +struct BOW_SPECIFIC_BSS_INFO { + uint16_t u2Reserved; /* Reserved for Data Type Check */ +}; + +#if CFG_SLT_SUPPORT +struct SLT_INFO { + + struct BSS_DESC *prPseudoBssDesc; + uint16_t u2SiteID; + uint8_t ucChannel2G4; + uint8_t ucChannel5G; + u_int8_t fgIsDUT; + uint32_t u4BeaconReceiveCnt; + /* ///////Deprecated///////// */ + struct STA_RECORD *prPseudoStaRec; +}; +#endif + +struct WLAN_TABLE { + uint8_t ucUsed; + uint8_t ucBssIndex; + uint8_t ucKeyId; + uint8_t ucPairwise; + uint8_t aucMacAddr[MAC_ADDR_LEN]; + uint8_t ucStaIndex; +}; + +/* Major member variables for WiFi FW operation. + * Variables within this region will be ready for + * access after WIFI function is enabled. + */ +struct WIFI_VAR { + u_int8_t fgIsRadioOff; + + u_int8_t fgIsEnterD3ReqIssued; + + u_int8_t fgDebugCmdResp; + + struct CONNECTION_SETTINGS rConnSettings; + + struct SCAN_INFO rScanInfo; + +#if CFG_SUPPORT_ROAMING + struct ROAMING_INFO rRoamingInfo; +#endif /* CFG_SUPPORT_ROAMING */ + + struct AIS_FSM_INFO rAisFsmInfo; + + enum ENUM_PWR_STATE aePwrState[MAX_BSSID_NUM]; + + struct BSS_INFO arBssInfoPool[MAX_BSSID_NUM]; + + struct BSS_INFO rP2pDevInfo; + + struct AIS_SPECIFIC_BSS_INFO rAisSpecificBssInfo; + +#if CFG_ENABLE_WIFI_DIRECT + struct P2P_CONNECTION_SETTINGS *prP2PConnSettings[BSS_P2P_NUM]; + + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo[BSS_P2P_NUM]; + +/* P_P2P_FSM_INFO_T prP2pFsmInfo; */ + + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo; + + /* Currently we only support 2 p2p interface. */ + struct P2P_ROLE_FSM_INFO *aprP2pRoleFsmInfo[BSS_P2P_NUM]; + +#if CFG_ENABLE_PER_STA_STATISTICS_LOG + struct PARAM_GET_STA_STATISTICS *prP2pQueryStaStatistics[BSS_P2P_NUM]; +#endif + +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +#if CFG_ENABLE_BT_OVER_WIFI + struct BOW_SPECIFIC_BSS_INFO rBowSpecificBssInfo; + struct BOW_FSM_INFO rBowFsmInfo; +#endif /* CFG_ENABLE_BT_OVER_WIFI */ + + struct WLAN_TABLE arWtbl[WTBL_SIZE]; + + struct DEAUTH_INFO arDeauthInfo[MAX_DEAUTH_INFO_COUNT]; + + /* Current Wi-Fi Settings and Flags */ + uint8_t aucPermanentAddress[MAC_ADDR_LEN]; + uint8_t aucMacAddress[MAC_ADDR_LEN]; + uint8_t aucDeviceAddress[MAC_ADDR_LEN]; + uint8_t aucInterfaceAddress[MAC_ADDR_LEN]; + + uint8_t ucAvailablePhyTypeSet; + + /* Basic Phy Type used by SCN according + * to the set of Available PHY Types + */ + enum ENUM_PHY_TYPE_INDEX eNonHTBasicPhyType2G4; + + enum ENUM_PARAM_PREAMBLE_TYPE ePreambleType; + enum ENUM_REGISTRY_FIXED_RATE eRateSetting; + + u_int8_t fgIsShortSlotTimeOptionEnable; + /* User desired setting, but will honor the capability of AP */ + + u_int8_t fgEnableJoinToHiddenSSID; + u_int8_t fgSupportWZCDisassociation; + +#if CFG_SUPPORT_WFD + struct WFD_CFG_SETTINGS rWfdConfigureSettings; +#endif + +#if CFG_SLT_SUPPORT + struct SLT_INFO rSltInfo; +#endif + +#if CFG_SUPPORT_PASSPOINT + struct HS20_INFO rHS20Info; +#endif /* CFG_SUPPORT_PASSPOINT */ + uint8_t aucMediatekOuiIE[64]; + uint16_t u2MediatekOuiIELen; + + /* Feature Options */ + uint8_t ucQoS; + + uint8_t ucStaHt; + uint8_t ucStaVht; + uint8_t ucApHt; + uint8_t ucApVht; + uint8_t ucP2pGoHt; + uint8_t ucP2pGoVht; + uint8_t ucP2pGcHt; + uint8_t ucP2pGcVht; + + /* NIC capability from FW event*/ + uint8_t ucHwNotSupportAC; + + uint8_t ucAmpduTx; + uint8_t ucAmpduRx; + uint8_t ucAmsduInAmpduTx; + uint8_t ucAmsduInAmpduRx; + uint8_t ucHtAmsduInAmpduTx; + uint8_t ucHtAmsduInAmpduRx; + uint8_t ucVhtAmsduInAmpduTx; + uint8_t ucVhtAmsduInAmpduRx; + uint8_t ucTspec; + uint8_t ucUapsd; + uint8_t ucStaUapsd; + uint8_t ucApUapsd; + uint8_t ucP2pUapsd; + + uint8_t ucTxShortGI; + uint8_t ucRxShortGI; + uint8_t ucTxLdpc; + uint8_t ucRxLdpc; + uint8_t ucTxStbc; + uint8_t ucRxStbc; + uint8_t ucRxStbcNss; + uint8_t ucTxGf; + uint8_t ucRxGf; + + uint8_t ucMCS32; + + uint8_t ucTxopPsTx; + uint8_t ucSigTaRts; + uint8_t ucDynBwRts; + + uint8_t ucStaHtBfee; + uint8_t ucStaVhtBfee; + uint8_t ucStaHtBfer; + uint8_t ucStaVhtBfer; + uint8_t ucStaVhtMuBfee; + uint8_t fgForceSTSNum; + + uint8_t ucDataTxDone; + uint8_t ucDataTxRateMode; + uint32_t u4DataTxRateCode; + + uint8_t ucApWpsMode; + uint8_t ucApChannel; + + uint8_t ucApSco; + uint8_t ucP2pGoSco; + + uint8_t ucStaBandwidth; + uint8_t ucSta5gBandwidth; + uint8_t ucSta2gBandwidth; + uint8_t ucApBandwidth; + uint8_t ucAp2gBandwidth; + uint8_t ucAp5gBandwidth; + uint8_t ucP2p5gBandwidth; + uint8_t ucP2p2gBandwidth; + + /* If enable, AP channel bandwidth Channel + * Center Frequency Segment 0/1 + */ + /* and secondary channel offset will align wifi.cfg */ + /* Otherwise align cfg80211 */ + uint8_t ucApChnlDefFromCfg; + + /* + * According TGn/TGac 4.2.44, AP should not connect + * with TKIP client with HT/VHT capabilities. We leave + * a wifi.cfg item for user to decide whether to + * enable HT/VHT capabilities in that case + */ + uint8_t ucApAllowHtVhtTkip; + + uint8_t ucNSS; + + uint8_t ucRxMaxMpduLen; + uint32_t u4TxMaxAmsduInAmpduLen; + + uint8_t ucTxBaSize; + uint8_t ucRxHtBaSize; + uint8_t ucRxVhtBaSize; + + uint8_t ucThreadScheduling; + uint8_t ucThreadPriority; + int8_t cThreadNice; + + uint8_t ucTcRestrict; + uint32_t u4MaxTxDeQLimit; + uint8_t ucAlwaysResetUsedRes; + + uint32_t u4NetifStopTh; + uint32_t u4NetifStartTh; +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + struct PARAM_GET_CHN_INFO rChnLoadInfo; +#endif +#if CFG_SUPPORT_MTK_SYNERGY + uint8_t ucMtkOui; + uint32_t u4MtkOuiCap; + uint8_t aucMtkFeature[4]; + u_int8_t ucGbandProbe256QAM; +#endif +#if CFG_SUPPORT_VHT_IE_IN_2G + uint8_t ucVhtIeIn2g; +#endif + u_int8_t fgCsaInProgress; + uint8_t ucChannelSwitchMode; + uint8_t ucNewChannelNumber; + uint8_t ucChannelSwitchCount; + + uint32_t u4HifIstLoopCount; + uint32_t u4Rx2OsLoopCount; + uint32_t u4HifTxloopCount; + uint32_t u4TxRxLoopCount; + uint32_t u4TxFromOsLoopCount; + uint32_t u4TxIntThCount; + + uint32_t au4TcPageCount[TC_NUM]; + uint32_t au4TcPageCountPle[TC_NUM]; + uint8_t ucExtraTxDone; + uint8_t ucTxDbg; + + uint8_t ucCmdRsvResource; + uint32_t u4MgmtQueueDelayTimeout; + + uint32_t u4StatsLogTimeout; + uint32_t u4StatsLogDuration; + uint8_t ucDhcpTxDone; + uint8_t ucArpTxDone; + + uint8_t ucMacAddrOverride; + uint8_t aucMacAddrStr[32]; + + uint8_t ucCtiaMode; + uint8_t ucTpTestMode; + uint8_t ucSigmaTestMode; +#if CFG_SUPPORT_DBDC + enum ENUM_CNM_DBDC_MODE eDbdcMode; + u_int8_t fgDbDcModeEn; +#endif + uint8_t u4ScanCtrl; + uint8_t ucScanChannelListenTime; + +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1) + uint8_t ucEfuseBufferModeCal; +#endif + uint8_t ucCalTimingCtrl; + uint8_t ucWow; + uint8_t ucOffload; + uint8_t ucAdvPws; /* enable LP multiple DTIM function, default enable */ + uint8_t ucWowOnMdtim; /* multiple DTIM if WOW enable, default 1 */ + uint8_t ucWowOffMdtim; /* multiple DTIM if WOW disable, default 3 */ + uint8_t ucWowPwsMode; /* when enter wow, auto enter power mode */ + uint8_t ucListenDtimInterval; /* the times of the dtim interval */ + uint8_t ucEapolOffload; /* eapol offload when active mode / wow mode */ + uint8_t ucEnforcePSMode; /* Enforce power mode */ + +#if CFG_SUPPORT_REPLAY_DETECTION + uint8_t ucRpyDetectOffload; /* replay detection eapol offload */ +#endif + + uint8_t u4SwTestMode; + uint8_t ucCtrlFlagAssertPath; + uint8_t ucCtrlFlagDebugLevel; + uint32_t u4WakeLockRxTimeout; + uint32_t u4WakeLockThreadWakeup; + uint32_t u4RegP2pIfAtProbe; /* register p2p interface during probe */ + /* p2p group interface use the same mac addr as p2p device interface */ + uint8_t ucP2pShareMacAddr; + uint8_t ucSmartRTS; + + /* The duration in ms to check TRX while the beacon timeout event */ + uint32_t u4BeaconTimoutFilterDurationMs; + + uint32_t u4UapsdAcBmp; + uint32_t u4MaxSpLen; + /* 0: enable online scan, non-zero: disable online scan */ + uint32_t fgDisOnlineScan; + uint32_t fgDisBcnLostDetection; + uint32_t fgDisRoaming; /* 0:enable roaming 1:disable */ + uint32_t fgEnArpFilter; + + uint8_t uDeQuePercentEnable; + uint32_t u4DeQuePercentVHT80Nss1; + uint32_t u4DeQuePercentVHT40Nss1; + uint32_t u4DeQuePercentVHT20Nss1; + uint32_t u4DeQuePercentHT40Nss1; + uint32_t u4DeQuePercentHT20Nss1; + + uint32_t u4PerfMonUpdatePeriod; + uint32_t u4PerfMonTpTh[PERF_MON_TP_MAX_THRESHOLD]; + uint32_t u4BoostCpuTh; + + u_int8_t fgTdlsBufferSTASleep; /* Support TDLS 5.5.4.2 optional case */ + u_int8_t fgChipResetRecover; + enum PARAM_POWER_MODE ePowerMode; + u_int8_t fgActiveModeCam; + + u_int8_t fgNvramCheckEn; /* nvram checking in scan result*/ +#if CFG_SUPPORT_SPE_IDX_CONTROL + u_int8_t ucSpeIdxCtrl; /* 0: WF0, 1: WF1, 2: duplicate */ +#if CFG_SUPPORT_COEX_NON_COTX + u_int8_t ucSpeIdxCtrl2g; /* 0:WF0, 1:WF1, 2: both WF0/1 only in 2G*/ + u_int8_t fgCoexNonCoTx; /* 0(default):allow co-Tx,1:disallow co-Tx*/ +#endif +#endif + int32_t ucEd2GNonEU; + int32_t ucEd5GNonEU; + int32_t ucEd2GEU; + int32_t ucEd5GEU; + uint8_t ucEnforceCAM2G; +#if CFG_SUPPORT_LOWLATENCY_MODE + uint8_t ucLowLatencyModeScan; + uint8_t ucLowLatencyModeReOrder; + uint8_t ucLowLatencyModePower; +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + + /* 11K */ + struct RADIO_MEASUREMENT_REQ_PARAMS rRmReqParams; + struct RADIO_MEASUREMENT_REPORT_PARAMS rRmRepParams; + + /* WMMAC */ + struct WMM_INFO rWmmInfo; +#ifdef CFG_SUPPORT_ADJUST_JOIN_CH_REQ_INTERVAL + uint32_t u4AisJoinChReqIntervel; +#endif + +#if IS_ENABLED(CFG_RX_NAPI_SUPPORT) + uint8_t ucRxNapiEnable; + uint8_t ucRxNapiPktChk; + uint8_t ucRxNapiThread; + uint8_t ucRxNapiNoTx; + uint32_t ucRxNapiThreshold; +#endif /* CFG_RX_NAPI_SUPPORT */ + +#if CFG_SUPPORT_WAC + uint16_t u2WACIELen; + uint8_t aucWACIECache[ELEM_MAX_LEN_WAC_INFO]; + bool fgEnableWACIE; +#endif +}; + +/* cnm_timer module */ +struct ROOT_TIMER { + struct LINK rLinkHead; + OS_SYSTIME rNextExpiredSysTime; + KAL_WAKE_LOCK_T rWakeLock; + u_int8_t fgWakeLocked; +}; + +/* FW/DRV/NVRAM version information */ +struct WIFI_VER_INFO { + + /* NVRAM or Registry */ + uint16_t u2Part1CfgOwnVersion; + uint16_t u2Part1CfgPeerVersion; + uint16_t u2Part2CfgOwnVersion; + uint16_t u2Part2CfgPeerVersion; + + /* Firmware */ + uint8_t aucReleaseManifest[256]; + + /* N9 SW */ + uint16_t u2FwProductID; + uint16_t u2FwOwnVersion; + uint16_t u2FwPeerVersion; + uint8_t ucFwBuildNumber; + uint8_t aucFwBranchInfo[4]; + uint8_t aucFwDateCode[16]; + + struct TAILER_COMMON_FORMAT_T rCommonTailer; + struct TAILER_REGION_FORMAT_T rRegionTailers[MAX_FWDL_SECTION_NUM]; + + /* N9 tailer */ + struct TAILER_FORMAT_T rN9tailer[N9_FWDL_SECTION_NUM]; + + /* CR4 tailer */ + struct TAILER_FORMAT_T rCR4tailer[CR4_FWDL_SECTION_NUM]; +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + /* N9 Compressed tailer */ + struct TAILER_FORMAT_T_2 rN9Compressedtailer; + /* CR4 tailer */ + struct TAILER_FORMAT_T_2 rCR4Compressedtailer; + u_int8_t fgIsN9CompressedFW; + u_int8_t fgIsCR4CompressedFW; +#endif + /* Patch header */ + struct PATCH_FORMAT_T rPatchHeader; + u_int8_t fgPatchIsDlByDrv; +}; + +#if CFG_ENABLE_WIFI_DIRECT +/* + * p2p function pointer structure + */ + +struct P2P_FUNCTION_LINKER { + P2P_REMOVE prP2pRemove; + + P2P_GENERATE_P2P_IE prP2pGenerateWSC_IEForBeacon; + + P2P_NET_REGISTER prP2pNetRegister; + P2P_NET_UNREGISTER prP2pNetUnregister; + /* All IEs generated from supplicant. */ + P2P_CALCULATE_P2P_IE_LEN prP2pCalculateP2p_IELenForAssocReq; + /* All IEs generated from supplicant. */ + P2P_GENERATE_P2P_IE prP2pGenerateP2p_IEForAssocReq; +}; + +#endif + +#if CFG_SUPPORT_NCHO +enum _ENUM_NCHO_ITEM_SET_TYPE_T { + ITEM_SET_TYPE_NUM, + ITEM_SET_TYPE_STR +}; + +enum _ENUM_NCHO_BAND_T { + NCHO_BAND_AUTO = 0, + NCHO_BAND_5G, + NCHO_BAND_2G4, + NCHO_BAND_NUM +}; + +enum _ENUM_NCHO_DFS_SCN_MODE_T { + NCHO_DFS_SCN_DISABLE = 0, + NCHO_DFS_SCN_ENABLE1, + NCHO_DFS_SCN_ENABLE2, + NCHO_DFS_SCN_NUM +}; + +struct _CFG_NCHO_RE_ASSOC_T { + /*!< SSID length in bytes. Zero length is broadcast(any) SSID */ + uint32_t u4SsidLen; + uint8_t aucSsid[ELEM_MAX_LEN_SSID]; + uint8_t aucBssid[MAC_ADDR_LEN]; + uint32_t u4CenterFreq; +}; + +struct _CFG_NCHO_SCAN_CHNL_T { + uint8_t ucChannelListNum; + struct RF_CHANNEL_INFO arChnlInfoList[MAXIMUM_OPERATION_CHANNEL_LIST]; +}; + +struct _NCHO_ACTION_FRAME_PARAMS_T { + uint8_t aucBssid[MAC_ADDR_LEN]; + int32_t i4channel; + int32_t i4DwellTime; + int32_t i4len; + uint8_t aucData[520]; +}; + +struct _NCHO_AF_INFO_T { + uint8_t *aucBssid; + int32_t i4channel; + int32_t i4DwellTime; + int32_t i4len; + uint8_t *pucData; +}; + +struct _NCHO_INFO_T { + u_int8_t fgECHOEnabled; + u_int8_t fgChGranted; + u_int8_t fgIsSendingAF; + int32_t i4RoamTrigger; /* db */ + int32_t i4RoamDelta; /* db */ + uint32_t u4RoamScanPeriod; /* ms */ + uint32_t u4ScanChannelTime; /* ms */ + uint32_t u4ScanHomeTime; /* ms */ + uint32_t u4ScanHomeawayTime; /* ms */ + uint32_t u4ScanNProbes; + uint32_t u4WesMode; + enum _ENUM_NCHO_BAND_T eBand; + enum _ENUM_NCHO_DFS_SCN_MODE_T eDFSScnMode; + uint32_t u4RoamScanControl; + struct _CFG_NCHO_SCAN_CHNL_T rRoamScnChnl; + struct _NCHO_ACTION_FRAME_PARAMS_T rParamActionFrame; +}; +#endif + +struct WIFI_FEM_CFG { + /* WiFi FEM path */ + uint16_t u2WifiPath; + uint16_t u2Reserved; + /* Reserved */ + uint32_t au4Reserved[4]; +}; +/* + * State Machine: + * -->STOP: No Tx/Rx traffic + * -->DISABLE: Screen is off + * -->RUNNING: Screen is on && Tx/Rx traffic is active + */ +struct PERF_MONITOR_T { + struct TIMER rPerfMonTimer; + unsigned long ulPerfMonFlag; + unsigned long ulLastTxBytes; + unsigned long ulLastRxBytes; + unsigned long ulP2PLastRxBytes; + unsigned long ulP2PLastTxBytes; + unsigned long ulThroughput; /* in bps */ + unsigned long ulWlanTxTp; /* in Bps */ + unsigned long ulWlanRxTp; /* in Bps */ + unsigned long ulP2PTxTp; /* in Bps */ + unsigned long ulP2PRxTp; /* in Bps */ + uint32_t u4UpdatePeriod; /* in ms */ + uint32_t u4TarPerfLevel; + uint32_t u4CurrPerfLevel; + uint32_t u4UsedCnt; + unsigned long ulTotalTxSuccessCount; + unsigned long ulTotalTxFailCount; +}; + +/* + * Major ADAPTER structure + * Major data structure for driver operation + */ +struct ADAPTER { + struct mt66xx_chip_info *chip_info; + uint8_t ucRevID; + u_int8_t fgIsReadRevID; + + uint16_t u2NicOpChnlNum; + + u_int8_t fgIsEnableWMM; + /* This flag is used to indicate that WMM is enable in current BSS */ + u_int8_t fgIsWmmAssoc; + + uint32_t u4OsPacketFilter; /* packet filter used by OS */ + u_int8_t fgAllMulicastFilter; /* mDNS filter used by OS */ + + struct BSS_INFO *aprBssInfo[MAX_BSSID_NUM + 1]; + struct BSS_INFO *prAisBssInfo; + uint8_t ucHwBssIdNum; + uint8_t ucWmmSetNum; + uint8_t ucWtblEntryNum; + uint8_t ucTxDefaultWlanIndex; + uint8_t ucP2PDevBssIdx; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + /* Does FW support Checksum Offload feature */ + u_int8_t fgIsSupportCsumOffload; + uint32_t u4CSUMFlags; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + enum ENUM_BAND aePreferBand[NETWORK_TYPE_NUM]; + + /* ADAPTER flags */ + uint32_t u4Flags; + uint32_t u4HwFlags; + + u_int8_t fgIsRadioOff; + + u_int8_t fgIsEnterD3ReqIssued; + + uint8_t aucMacAddress[MAC_ADDR_LEN]; + + /* Current selection basing on the set of Available PHY Types */ + enum ENUM_PHY_TYPE_INDEX eCurrentPhyType; + + uint32_t u4CoalescingBufCachedSize; + uint8_t *pucCoalescingBufCached; + + /* Buffer for CMD_INFO_T, Mgt packet and mailbox message */ + struct BUF_INFO rMgtBufInfo; + struct BUF_INFO rMsgBufInfo; + uint8_t *pucMgtBufCached; + uint32_t u4MgtBufCachedSize; + uint8_t aucMsgBuf[MSG_BUFFER_SIZE]; +#if CFG_DBG_MGT_BUF + uint32_t u4MemAllocDynamicCount; /* Debug only */ + uint32_t u4MemFreeDynamicCount; /* Debug only */ +#endif + + struct STA_RECORD arStaRec[CFG_STA_REC_NUM]; + + /* Element for TX PATH */ + struct TX_CTRL rTxCtrl; + struct QUE rFreeCmdList; + struct CMD_INFO arHifCmdDesc[CFG_TX_MAX_CMD_PKT_NUM]; + + /* Element for RX PATH */ + struct RX_CTRL rRxCtrl; + + /* Timer for restarting RFB setup procedure */ + struct TIMER rPacketDelaySetupTimer; + + /* Buffer for Authentication Event */ + /* Move to glue layer and refine the kal function */ + /* Reference to rsnGeneratePmkidIndication function at rsn.c */ + uint8_t aucIndicationEventBuffer[(CFG_MAX_PMKID_CACHE * 20) + 8]; + + uint32_t u4IntStatus; + + enum ENUM_ACPI_STATE rAcpiState; + + u_int8_t fgIsIntEnable; + u_int8_t fgIsIntEnableWithLPOwnSet; + + u_int8_t fgIsFwOwn; + u_int8_t fgWiFiInSleepyState; + + /* Set by callback to make sure WOW process done before system suspend */ + u_int8_t fgSetPfCapabilityDone; + u_int8_t fgSetWowDone; + u_int8_t fgSetMdnsDone; + + u_int8_t fgForceFwOwn; + + OS_SYSTIME rLastOwnFailedLogTime; + uint32_t u4OwnFailedCount; + uint32_t u4OwnFailedLogCount; + + uint32_t u4PwrCtrlBlockCnt; + + /* TX Direct related : BEGIN */ + u_int8_t fgTxDirectInited; + + #define TX_DIRECT_CHECK_INTERVAL (1000 * HZ / USEC_PER_SEC) + /* check if an empty MsduInfo is available */ + struct timer_list rTxDirectSkbTimer; + /* check if HIF port is ready to accept a new Msdu */ + struct timer_list rTxDirectHifTimer; + + struct sk_buff_head rTxDirectSkbQueue; + struct QUE rTxDirectHifQueue[TX_PORT_NUM]; + + struct QUE rStaPsQueue[CFG_STA_REC_NUM]; + uint32_t u4StaPsBitmap; + struct QUE rBssAbsentQueue[MAX_BSSID_NUM + 1]; + uint32_t u4BssAbsentBitmap; + /* TX Direct related : END */ + + struct QUE rPendingCmdQueue; + +#if CFG_SUPPORT_MULTITHREAD + struct QUE rTxCmdQueue; + struct QUE rTxCmdDoneQueue; +#if CFG_FIX_2_TX_PORT + struct QUE rTxP0Queue; + struct QUE rTxP1Queue; +#else + struct QUE rTxPQueue[TX_PORT_NUM]; +#endif + struct QUE rRxQueue; + struct QUE rTxDataDoneQueue; +#endif + + struct GLUE_INFO *prGlueInfo; + + uint8_t ucCmdSeqNum; + uint8_t ucTxSeqNum; + uint8_t aucPidPool[WTBL_SIZE]; + +#if 1 /* CFG_SUPPORT_WAPI */ + u_int8_t fgUseWapi; +#endif + + /* RF Test flags */ + u_int8_t fgTestMode; + u_int8_t fgIcapMode; + + /* WLAN Info for DRIVER_CORE OID query */ + struct WLAN_INFO rWlanInfo; + +#if CFG_ENABLE_WIFI_DIRECT + u_int8_t fgIsP2PRegistered; + /* flag to report all networks in p2p scan */ + u_int8_t p2p_scan_report_all_bss; + enum ENUM_NET_REG_STATE rP2PNetRegState; + /* BOOLEAN fgIsWlanLaunched; */ + struct P2P_INFO *prP2pInfo; +#if CFG_SUPPORT_P2P_RSSI_QUERY + OS_SYSTIME rP2pLinkQualityUpdateTime; + u_int8_t fgIsP2pLinkQualityValid; + struct EVENT_LINK_QUALITY rP2pLinkQuality; +#endif +#endif + + /* Online Scan Option */ + u_int8_t fgEnOnlineScan; + + /* Online Scan Option */ + u_int8_t fgDisBcnLostDetection; + + /* MAC address */ + uint8_t rMyMacAddr[PARAM_MAC_ADDR_LEN]; + + /* Wake-up Event for WOL */ + uint32_t u4WakeupEventEnable; + + /* Event Buffering */ + struct EVENT_STATISTICS rStatStruct; + OS_SYSTIME rStatUpdateTime; + u_int8_t fgIsStatValid; + +#if CFG_SUPPORT_MSP + struct EVENT_WLAN_INFO rEventWlanInfo; +#endif + + struct EVENT_LINK_QUALITY rLinkQuality; + OS_SYSTIME rLinkQualityUpdateTime; + u_int8_t fgIsLinkQualityValid; + OS_SYSTIME rLinkRateUpdateTime; + u_int8_t fgIsLinkRateValid; + + /* WIFI_VAR_T */ + struct WIFI_VAR rWifiVar; + + /* MTK WLAN NIC driver IEEE 802.11 MIB */ + struct IEEE_802_11_MIB rMib; + + /* Mailboxs for inter-module communication */ + struct MBOX arMbox[MBOX_ID_TOTAL_NUM]; + + /* Timers for OID Pending Handling */ + struct TIMER rOidTimeoutTimer; + uint8_t ucOidTimeoutCount; + + /* Root Timer for cnm_timer module */ + struct ROOT_TIMER rRootTimer; + + u_int8_t fgIsChipNoAck; + u_int8_t fgIsChipAssert; + + /* RLM maintenance */ + enum ENUM_CHNL_EXT eRfSco; + enum ENUM_SYS_PROTECT_MODE eSysProtectMode; + enum ENUM_GF_MODE eSysHtGfMode; + enum ENUM_RIFS_MODE eSysTxRifsMode; + enum ENUM_SYS_PCO_PHASE eSysPcoPhase; + + struct DOMAIN_INFO_ENTRY *prDomainInfo; + + /* QM */ + struct QUE_MGT rQM; + + struct CNM_INFO rCnmInfo; + + uint32_t u4PowerMode; + + uint32_t u4CtiaPowerMode; + u_int8_t fgEnCtiaPowerMode; + /* Bitmap is defined as + * #define KEEP_FULL_PWR_{FEATURE}_BIT in wlan_lib.h + * Each feature controls KeepFullPwr(CMD_ID_KEEP_FULL_PWR) should + * register bitmap to ensure low power during suspend. + */ + uint32_t u4IsKeepFullPwrBitmap; + + uint32_t fgEnArpFilter; + + uint32_t u4UapsdAcBmp; + + uint32_t u4MaxSpLen; + + uint32_t u4PsCurrentMeasureEn; + + /* Version Information */ + struct WIFI_VER_INFO rVerInfo; + + /* 5GHz support (from F/W) */ + u_int8_t fgIsHw5GBandDisabled; + u_int8_t fgEnable5GBand; + u_int8_t fgIsEepromUsed; + u_int8_t fgIsEfuseValid; + u_int8_t fgIsEmbbededMacAddrValid; + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + u_int8_t fgIsPowerLimitTableValid; +#endif + + /* Packet Forwarding Tracking */ + int32_t i4PendingFwdFrameCount; + +#if CFG_SUPPORT_RDD_TEST_MODE + uint8_t ucRddStatus; +#endif + + u_int8_t fgDisStaAgingTimeoutDetection; + + uint32_t u4FwCompileFlag0; + uint32_t u4FwCompileFlag1; + uint32_t u4FwFeatureFlag0; + uint32_t u4FwFeatureFlag1; + +#if CFG_SUPPORT_CFG_FILE + struct WLAN_CFG *prWlanCfg; + struct WLAN_CFG rWlanCfg; + + struct WLAN_CFG_REC *prWlanCfgRec; + struct WLAN_CFG_REC rWlanCfgRec; +#endif + +#if CFG_M0VE_BA_TO_DRIVER + struct TIMER rMqmIdleRxBaDetectionTimer; + uint32_t u4FlagBitmap; +#endif +#if CFG_ASSERT_DUMP + struct TIMER rN9CorDumpTimer; + struct TIMER rCr4CorDumpTimer; + u_int8_t fgN9CorDumpFileOpend; + u_int8_t fgCr4CorDumpFileOpend; + u_int8_t fgN9AssertDumpOngoing; + u_int8_t fgCr4AssertDumpOngoing; + u_int8_t fgKeepPrintCoreDump; +#endif + /* Tx resource information */ + u_int8_t fgIsNicTxReousrceValid; + struct tx_resource_info nicTxReousrce; + + /* Efuse Start and End address */ + uint32_t u4EfuseStartAddress; + uint32_t u4EfuseEndAddress; + + /* Buffer Mode Info */ + struct CAP_BUFFER_MODE_INFO_T rBufferModeInfo; + + /* COEX feature */ + uint32_t u4FddMode; + +#if CFG_WOW_SUPPORT + struct WOW_CTRL rWowCtrl; + uint8_t mdns_offload_enable; +#endif + +#if CFG_SUPPORT_WOW_EINT + struct WOWLAN_DEV_NODE rWowlanDevNode; +#endif + +#if CFG_SUPPORT_NCHO /* NCHO information */ + struct _NCHO_INFO_T rNchoInfo; +#endif + +/*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ + uint8_t aucEepromVaule[16]; /* HQA CMD for Efuse Block size contents */ + uint32_t u4FreeBlockNum; + uint32_t u4GetTxPower; +/*#endif*/ + u_int8_t fgIsCr4FwDownloaded; + u_int8_t fgIsFwDownloaded; + u_int8_t fgIsSupportBufferBinSize16Byte; + u_int8_t fgIsSupportDelayCal; + u_int8_t fgIsSupportGetFreeEfuseBlockCount; + u_int8_t fgIsSupportQAAccessEfuse; + u_int8_t fgIsSupportPowerOnSendBufferModeCMD; + u_int8_t fgIsSupportGetTxPower; + u_int8_t fgIsEnableLpdvt; + + /* SER related info */ + uint8_t ucSerState; +#if CFG_SUPPORT_SER + +#if defined(_HIF_USB) + struct TIMER rSerSyncTimer; +#endif /* _HIF_USB */ + +#endif /* CFG_SUPPORT_SER */ + +#if (CFG_HW_WMM_BY_BSS == 1) + uint8_t ucHwWmmEnBit; +#endif + unsigned long ulSuspendFlag; + struct WIFI_FEM_CFG rWifiFemCfg; + + /* Smar Gear */ + uint8_t ucSmarGearSupportSisoOnly; + uint8_t ucSmartGearWfPathSupport; + + struct PERF_MONITOR_T rPerMonitor; + struct ICAP_INFO_T rIcapInfo; + struct RECAL_INFO_T rReCalInfo; + + /* Support change QM RX BA entry miss timeout (unit: ms) dynamically */ + uint32_t u4QmRxBaMissTimeout; + +#if CFG_SUPPORT_LOWLATENCY_MODE + u_int8_t fgEnLowLatencyMode; + u_int8_t fgEnCfg80211Scan; +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + + bool fgEnHifDbgInfo; + uint32_t u4HifDbgFlag; + uint32_t u4HifChkFlag; + +#if CFG_SUPPORT_OSHARE + bool fgEnOshareMode; +#endif + + struct WLAN_DEBUG_INFO rDebugInfo; + + bool fgIsStartApDone; + bool fgIsStopApDone; + bool fgIsChSwitchDone; + bool fgIsAddKeyDone; + +#if CFG_SUPPORT_ADJUST_MCC_MODE_SET + u_int8_t ucModeMCC; +#endif +#if CFG_SUPPORT_RX_DYNAMIC_MCC_PRIORITY + bool fgMccFirstIn; + uint32_t ucModeMCC_STA_time; + uint32_t ucModeMCC_P2P_time; + uint64_t u8StaRxCount; + uint64_t u8P2pRxCount; + struct TIMER rRxCntMonitorTimer; + uint32_t u4SetStaMccTime; + uint32_t u4SetP2pMccTime; +#endif /*CFG_SUPPORT_RX_DYNAMIC_MCC_PRIORITY*/ + +#if CFG_SUPPORT_GET_MCS_INFO + struct TIMER rRxMcsInfoTimer; + bool fgIsMcsInfoValid; +#endif /* CFG_SUPPORT_GET_MCS_INFO */ +#if CFG_SUPPORT_HW_1T2R + bool fgIsHW1T2R; +#endif +}; /* end of _ADAPTER_T */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +#define SUSPEND_FLAG_FOR_WAKEUP_REASON (0) +#define SUSPEND_FLAG_CLEAR_WHEN_RESUME (1) + +/* Macros for argument _BssIndex */ +#define IS_NET_ACTIVE(_prAdapter, _BssIndex) \ + ((_prAdapter)->aprBssInfo[(_BssIndex)]->fgIsNetActive) + +/* Macros for argument _prBssInfo */ +#define IS_BSS_ACTIVE(_prBssInfo) ((_prBssInfo)->fgIsNetActive) + +#define IS_BSS_AIS(_prBssInfo) \ + ((_prBssInfo)->eNetworkType == NETWORK_TYPE_AIS) + +#define IS_BSS_P2P(_prBssInfo) \ + ((_prBssInfo)->eNetworkType == NETWORK_TYPE_P2P) + +#define IS_BSS_BOW(_prBssInfo) \ + ((_prBssInfo)->eNetworkType == NETWORK_TYPE_BOW) + +#define SET_NET_ACTIVE(_prAdapter, _BssIndex) \ + {(_prAdapter)->aprBssInfo[(_BssIndex)]->fgIsNetActive = TRUE; } + +#define UNSET_NET_ACTIVE(_prAdapter, _BssIndex) \ + {(_prAdapter)->aprBssInfo[(_BssIndex)]->fgIsNetActive = FALSE; } + +#define BSS_INFO_INIT(_prAdapter, _prBssInfo) \ +{ uint8_t _aucZeroMacAddr[] = NULL_MAC_ADDR; \ + \ + (_prBssInfo)->eConnectionState = PARAM_MEDIA_STATE_DISCONNECTED; \ + (_prBssInfo)->eConnectionStateIndicated = \ + PARAM_MEDIA_STATE_DISCONNECTED; \ + (_prBssInfo)->eCurrentOPMode = OP_MODE_INFRASTRUCTURE; \ + (_prBssInfo)->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_RESERVED; \ + COPY_MAC_ADDR((_prBssInfo)->aucBSSID, _aucZeroMacAddr); \ + LINK_INITIALIZE(&((_prBssInfo)->rStaRecOfClientList)); \ + (_prBssInfo)->fgIsBeaconActivated = FALSE; \ + (_prBssInfo)->u2HwDefaultFixedRateCode = RATE_CCK_1M_LONG; \ + (_prBssInfo)->ePowerModeFromUser = Param_PowerModeFast_PSP; \ +} + +/*----------------------------------------------------------------------------*/ +/* Macros for Power State */ +/*----------------------------------------------------------------------------*/ +#define SET_NET_PWR_STATE_IDLE(_prAdapter, _BssIndex) \ + {_prAdapter->rWifiVar.aePwrState[(_BssIndex)] = PWR_STATE_IDLE; } + +#define SET_NET_PWR_STATE_ACTIVE(_prAdapter, _BssIndex) \ + {_prAdapter->rWifiVar.aePwrState[(_BssIndex)] = PWR_STATE_ACTIVE; } + +#define SET_NET_PWR_STATE_PS(_prAdapter, _BssIndex) \ + {_prAdapter->rWifiVar.aePwrState[(_BssIndex)] = PWR_STATE_PS; } + +#define IS_NET_PWR_STATE_ACTIVE(_prAdapter, _BssIndex) \ + (_prAdapter->rWifiVar.aePwrState[(_BssIndex)] == PWR_STATE_ACTIVE) + +#define IS_NET_PWR_STATE_IDLE(_prAdapter, _BssIndex) \ + (_prAdapter->rWifiVar.aePwrState[(_BssIndex)] == 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) + +#define IS_WIFI_2G4_WF0_SUPPORT(_prAdapter) \ + ((_prAdapter)->rWifiFemCfg.u2WifiPath & WLAN_FLAG_2G4_WF0) + +#define IS_WIFI_5G_WF0_SUPPORT(_prAdapter) \ + ((_prAdapter)->rWifiFemCfg.u2WifiPath & WLAN_FLAG_5G_WF0) + +#define IS_WIFI_2G4_WF1_SUPPORT(_prAdapter) \ + ((_prAdapter)->rWifiFemCfg.u2WifiPath & WLAN_FLAG_2G4_WF1) + +#define IS_WIFI_5G_WF1_SUPPORT(_prAdapter) \ + ((_prAdapter)->rWifiFemCfg.u2WifiPath & WLAN_FLAG_5G_WF1) + +#define IS_WIFI_2G4_SISO(_prAdapter) \ + ((IS_WIFI_2G4_WF0_SUPPORT(_prAdapter) && \ + !(IS_WIFI_2G4_WF1_SUPPORT(_prAdapter))) || \ + (IS_WIFI_2G4_WF1_SUPPORT(_prAdapter) && \ + !(IS_WIFI_2G4_WF0_SUPPORT(_prAdapter)))) + +#define IS_WIFI_5G_SISO(_prAdapter) \ + ((IS_WIFI_5G_WF0_SUPPORT(_prAdapter) && \ + !(IS_WIFI_5G_WF1_SUPPORT(_prAdapter))) || \ + (IS_WIFI_5G_WF1_SUPPORT(_prAdapter) && \ + !(IS_WIFI_5G_WF0_SUPPORT(_prAdapter)))) + +#define IS_WIFI_SMART_GEAR_SUPPORT_WF0_SISO(_prAdapter) \ + ((_prAdapter)->ucSmarGearSupportSisoOnly && \ + ((_prAdapter)->ucSmartGearWfPathSupport == BIT(ANTENNA_WF0))) + +#define IS_WIFI_SMART_GEAR_SUPPORT_WF1_SISO(_prAdapter) \ + ((_prAdapter)->ucSmarGearSupportSisoOnly && \ + ((_prAdapter)->ucSmartGearWfPathSupport == BIT(ANTENNA_WF1))) + +#if CFG_SUPPORT_HW_1T2R +#define IS_HW_1T2R(_prAdapter) \ + ((_prAdapter)->fgIsHW1T2R) +#else +#define IS_HW_1T2R(_prAdapter) (FALSE) +#endif + +#if CFG_SUPPORT_SPE_IDX_CONTROL +/* 0: WF0, 1: WF1, 2: duplicate */ +#define GET_SPE_IDX_CTRL(_prAdapter) \ + (IS_HW_1T2R(_prAdapter) ? (1) : (_prAdapter->rWifiVar.ucSpeIdxCtrl)) +#if CFG_SUPPORT_COEX_NON_COTX +/* 0(default):allow co-Tx,1:disallow co-Tx*/ +#define GET_COEX_NON_COTX(_prAdapter) \ + (IS_HW_1T2R(_prAdapter) ? FALSE : (_prAdapter->rWifiVar.fgCoexNonCoTx)) +#endif +#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 /* _ADAPTER_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/bow.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/bow.h new file mode 100644 index 0000000000000..c7e7cbe85b8e1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/bow.h @@ -0,0 +1,266 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/bow.h#1 +*/ + + +#ifndef _BOW_H_ +#define _BOW_H_ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define BOWDEVNAME "bow0" + +#define MAX_BOW_NUMBER_OF_CHANNEL_2G4 14 +#define MAX_BOW_NUMBER_OF_CHANNEL_5G 4 +/* (MAX_BOW_NUMBER_OF_CHANNEL_2G4 + MAX_BOW_NUMBER_OF_CHANNEL_5G) */ +#define MAX_BOW_NUMBER_OF_CHANNEL 18 + +#define MAX_ACTIVITY_REPORT 2 +#define MAX_ACTIVITY_REPROT_TIME 660 + +#define ACTIVITY_REPORT_STATUS_SUCCESS 0 +#define ACTIVITY_REPORT_STATUS_FAILURE 1 +#define ACTIVITY_REPORT_STATUS_TIME_INVALID 2 +#define ACTIVITY_REPORT_STATUS_OTHERS 3 + +#define ACTIVITY_REPORT_SCHEDULE_UNKNOWN 0 /* Does not know the schedule of the interference */ +#define ACTIVITY_REPORT_SCHEDULE_KNOWN 1 + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +struct BT_OVER_WIFI_COMMAND_HEADER { + uint8_t ucCommandId; + uint8_t ucSeqNumber; + uint16_t u2PayloadLength; +}; + +struct BT_OVER_WIFI_COMMAND { + struct BT_OVER_WIFI_COMMAND_HEADER rHeader; + uint8_t aucPayload[0]; +}; + +struct BT_OVER_WIFI_EVENT_HEADER { + uint8_t ucEventId; + uint8_t ucSeqNumber; + uint16_t u2PayloadLength; +}; + +struct BT_OVER_WIFI_EVENT { + struct BT_OVER_WIFI_EVENT_HEADER rHeader; + uint8_t aucPayload[0]; +}; + +struct CHANNEL_DESC { + uint8_t ucChannelBand; + uint8_t ucChannelNum; +}; + +/* Command Structures */ +struct BOW_SETUP_CONNECTION { +/* Fixed to 2.4G */ + uint8_t ucChannelNum; + uint8_t ucReserved1; + uint8_t aucPeerAddress[6]; + uint16_t u2BeaconInterval; + uint8_t ucTimeoutDiscovery; + uint8_t ucTimeoutInactivity; + uint8_t ucRole; + uint8_t ucPAL_Capabilities; + int8_t cMaxTxPower; + uint8_t 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]; + */ +}; + +struct BOW_DESTROY_CONNECTION { + uint8_t aucPeerAddress[6]; + uint8_t aucReserved[2]; +}; + +struct BOW_SET_PTK { + uint8_t aucPeerAddress[6]; + uint8_t aucReserved[2]; + uint8_t aucTemporalKey[16]; +}; + +struct BOW_READ_RSSI { + uint8_t aucPeerAddress[6]; + uint8_t aucReserved[2]; +}; + +struct BOW_READ_LINK_QUALITY { + uint8_t aucPeerAddress[6]; + uint8_t aucReserved[2]; +}; + +struct BOW_SHORT_RANGE_MODE { + uint8_t aucPeerAddress[6]; + int8_t cTxPower; + uint8_t ucReserved; +}; + +/* Event Structures */ +struct BOW_COMMAND_STATUS { + uint8_t ucStatus; + uint8_t ucReserved[3]; +}; + +struct BOW_MAC_STATUS { + uint8_t aucMacAddr[6]; + uint8_t ucAvailability; + uint8_t ucNumOfChannel; + struct CHANNEL_DESC arChannelList[MAX_BOW_NUMBER_OF_CHANNEL]; +}; + +struct BOW_LINK_CONNECTED { + struct CHANNEL_DESC rChannel; + uint8_t aucReserved; + uint8_t aucPeerAddress[6]; +}; + +struct BOW_LINK_DISCONNECTED { + uint8_t ucReason; + uint8_t aucReserved; + uint8_t aucPeerAddress[6]; +}; + +struct BOW_RSSI { + int8_t cRssi; + uint8_t aucReserved[3]; +}; + +struct BOW_LINK_QUALITY { + uint8_t ucLinkQuality; + uint8_t aucReserved[3]; +}; + +enum ENUM_BOW_CMD_ID { + 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 ENUM_BOW_EVENT_ID { + 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 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 +}; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#endif /*_BOW_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/cmd_buf.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/cmd_buf.h new file mode 100644 index 0000000000000..9b04cdf57cc83 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/cmd_buf.h @@ -0,0 +1,215 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + + +#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 + ******************************************************************************* + */ + +enum COMMAND_TYPE { + COMMAND_TYPE_GENERAL_IOCTL, + COMMAND_TYPE_NETWORK_IOCTL, + COMMAND_TYPE_SECURITY_FRAME, + COMMAND_TYPE_MANAGEMENT_FRAME, + COMMAND_TYPE_NUM +}; + +typedef void(*PFN_CMD_DONE_HANDLER) (IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +typedef void(*PFN_CMD_TIMEOUT_HANDLER) (IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo); + +typedef void(*PFN_HIF_TX_CMD_DONE_CB) (IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo); + +struct CMD_INFO { + struct QUE_ENTRY rQueEntry; + + enum COMMAND_TYPE eCmdType; + + uint16_t u2InfoBufLen; /* This is actual CMD buffer length */ + uint8_t *pucInfoBuffer; /* May pointer to structure in prAdapter */ + struct MSDU_INFO + *prMsduInfo; /* only valid when it's a security/MGMT frame */ + void *prPacket; /* only valid when it's a security frame */ + + PFN_CMD_DONE_HANDLER pfCmdDoneHandler; + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler; + PFN_HIF_TX_CMD_DONE_CB pfHifTxCmdDoneCb; + + u_int8_t fgIsOid; /* Used to check if we need indicate */ + + uint8_t ucCID; + u_int8_t fgSetQuery; + u_int8_t fgNeedResp; + uint8_t ucCmdSeqNum; + uint32_t u4SetInfoLen; /* Indicate how many byte we read for Set OID */ + + /* information indicating by OID/ioctl */ + void *pvInformationBuffer; + uint32_t u4InformationBufferLength; + + /* private data */ + uint32_t u4PrivateData; + + /* TXD/TXP pointer/len for hif tx copy */ + uint32_t u4TxdLen; + uint32_t u4TxpLen; + uint8_t *pucTxd; + uint8_t *pucTxp; +}; + +/******************************************************************************* + * P U B 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 struct ADAPTER *prAdapter); + +struct CMD_INFO *cmdBufAllocateCmdInfo(IN struct ADAPTER + *prAdapter, IN uint32_t u4Length); + +void cmdBufFreeCmdInfo(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo); + +/*----------------------------------------------------------------------------*/ +/* Routines for CMDs */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanSendSetQueryCmd(IN struct ADAPTER *prAdapter, + uint8_t ucCID, + u_int8_t fgSetQuery, + u_int8_t fgNeedResp, + u_int8_t fgIsOid, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + uint32_t u4SetQueryInfoLen, + uint8_t *pucInfoBuffer, OUT void *pvSetQueryBuffer, + IN uint32_t u4SetQueryBufferLen); + +#if CFG_SUPPORT_TX_BF +uint32_t +wlanSendSetQueryExtCmd(IN struct ADAPTER *prAdapter, + uint8_t ucCID, + uint8_t ucExtCID, + u_int8_t fgSetQuery, + u_int8_t fgNeedResp, + u_int8_t fgIsOid, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + uint32_t u4SetQueryInfoLen, + uint8_t *pucInfoBuffer, OUT void *pvSetQueryBuffer, + IN uint32_t u4SetQueryBufferLen); +#endif + +void cmdBufDumpCmdQueue(struct QUE *prQueue, + int8_t *queName); +#if (CFG_SUPPORT_TRACE_TC4 == 1) +void wlanDebugTC4Init(void); +void wlanDebugTC4Uninit(void); +void wlanTraceReleaseTcRes(struct ADAPTER *prAdapter, + uint32_t u4TxRlsCnt, uint32_t u4Available); +void wlanTraceTxCmd(struct CMD_INFO *prCmd); +void wlanDumpTcResAndTxedCmd(uint8_t *pucBuf, + uint32_t maxLen); +#endif + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#endif /* _CMD_BUF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/connac_dmashdl.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/connac_dmashdl.h new file mode 100644 index 0000000000000..51750e81530be --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/connac_dmashdl.h @@ -0,0 +1,458 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "connac_dmashdl.h" + * \brief The common register definition of MT6630 + * + * N/A + */ + + + +#ifndef _CONNAC_DMASHDL_H +#define _CONNAC_DMASHDL_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 + ******************************************************************************* + */ + +#if defined(_HIF_PCIE) || defined(_HIF_AXI) +#define PCIE_HIF_DMASHDL_BASE 0x6000 +#endif /* _HIF_PCIE */ + +#if defined(_HIF_USB) +#define USB_HIF_DMASHDL_BASE 0x5000A000 +#endif /* _HIF_USB */ + +#define CONN_HIF_DMASHDL_SW_CONTROL(_base) (_base + 0x04) +#define CONN_HIF_DMASHDL_OPTIONAL_CONTROL(_base) (_base + 0x08) + +#define CONN_HIF_DMASHDL_PAGE_SETTING(_base) (_base + 0x0C) +/* User program group sequence type control */ +/* 0: user program group sequence order type, + * 1: pre define each slot group strict order + */ +#define CONN_HIF_DMASHDL_GROUP_SEQ_ORDER_TYPE BIT(16) + +#define CONN_HIF_DMASHDL_REFILL_CONTROL(_base) (_base + 0x10) +#define CONN_HIF_DMASHDL_TX_PACKET_SIZE_PAGE_MAP(_base) (_base + 0x14) + +#define CONN_HIF_DMASHDL_CONTROL_SIGNAL(_base) (_base + 0x18) +/* enable to clear the flag of PLE TXD size greater than ple max. size */ +#define CONN_HIF_DMASHDL_PLE_TXD_GT_MAX_SIZE_FLAG_CLR \ + BIT(0) +#define CONN_HIF_DMASHDL_HIF_ASK_SUB_ENA \ + BIT(16) /* enable packet in substration action from HIF ask period */ +#define CONN_HIF_DMASHDL_PLE_SUB_ENA \ + BIT(17) /* enable packet in substration action from PLE */ +/* enable terminate refill period when PLE release packet to do addition */ +#define CONN_HIF_DMASHDL_PLE_ADD_INT_REFILL_ENA \ + BIT(29) +/* enable terminate refill period when packet in to do addition */ +#define CONN_HIF_DMASHDL_PDMA_ADD_INT_REFILL_ENA \ + BIT(30) +/* enable terminate refill period when packet in to do substration */ +#define CONN_HIF_DMASHDL_PKTIN_INT_REFILL_ENA \ + BIT(31) + +#define CONN_HIF_DMASHDL_PACKET_MAX_SIZE(_base) (_base + 0x1C) +#define CONN_HIF_DMASHDL_GROUP0_CONTROL(_base) (_base + 0x20) +#define CONN_HIF_DMASHDL_REFILL_CTRL(_base) (_base + 0x10) +#define CONN_HIF_DMASHDL_GROUP0_CTRL(_base) (_base + 0x20) +#define CONN_HIF_DMASHDL_GROUP1_CTRL(_base) (_base + 0x24) +#define CONN_HIF_DMASHDL_GROUP2_CTRL(_base) (_base + 0x28) +#define CONN_HIF_DMASHDL_GROUP3_CTRL(_base) (_base + 0x2c) +#define CONN_HIF_DMASHDL_GROUP4_CTRL(_base) (_base + 0x30) +#define CONN_HIF_DMASHDL_GROUP5_CTRL(_base) (_base + 0x34) +#define CONN_HIF_DMASHDL_GROUP6_CTRL(_base) (_base + 0x38) +#define CONN_HIF_DMASHDL_GROUP7_CTRL(_base) (_base + 0x3c) +#define CONN_HIF_DMASHDL_GROUP8_CTRL(_base) (_base + 0x40) +#define CONN_HIF_DMASHDL_GROUP9_CTRL(_base) (_base + 0x44) +#define CONN_HIF_DMASHDL_GROUP10_CTRL(_base) (_base + 0x48) +#define CONN_HIF_DMASHDL_GROUP11_CTRL(_base) (_base + 0x4c) +#define CONN_HIF_DMASHDL_GROUP12_CTRL(_base) (_base + 0x50) +#define CONN_HIF_DMASHDL_GROUP13_CTRL(_base) (_base + 0x54) +#define CONN_HIF_DMASHDL_GROUP14_CTRL(_base) (_base + 0x58) +#define CONN_HIF_DMASHDL_GROUP15_CTRL(_base) (_base + 0x5c) +#define CONN_HIF_DMASHDL_SHDL_SET0(_base) (_base + 0xb0) +#define CONN_HIF_DMASHDL_SHDL_SET1(_base) (_base + 0xb4) +#define CONN_HIF_DMASHDL_SLOT_SET0(_base) (_base + 0xc4) +#define CONN_HIF_DMASHDL_SLOT_SET1(_base) (_base + 0xc8) +#define CONN_HIF_DMASHDL_Q_MAP0(_base) (_base + 0xd0) +#define CONN_HIF_DMASHDL_Q_MAP1(_base) (_base + 0xd4) +#define CONN_HIF_DMASHDL_Q_MAP2(_base) (_base + 0xd8) +#define CONN_HIF_DMASHDL_Q_MAP3(_base) (_base + 0xdc) + +#define CONN_HIF_DMASHDL_ERROR_FLAG_CTRL(_base) (_base + 0x9c) + +#define CONN_HIF_DMASHDL_STATUS_RD(_base) (_base + 0x100) +#define CONN_HIF_DMASHDL_STATUS_RD_GP0(_base) (_base + 0x140) +#define CONN_HIF_DMASHDL_STATUS_RD_GP1(_base) (_base + 0x144) +#define CONN_HIF_DMASHDL_STATUS_RD_GP2(_base) (_base + 0x148) +#define CONN_HIF_DMASHDL_STATUS_RD_GP3(_base) (_base + 0x14c) +#define CONN_HIF_DMASHDL_STATUS_RD_GP4(_base) (_base + 0x150) +#define CONN_HIF_DMASHDL_STATUS_RD_GP5(_base) (_base + 0x154) +#define CONN_HIF_DMASHDL_STATUS_RD_GP6(_base) (_base + 0x158) +#define CONN_HIF_DMASHDL_STATUS_RD_GP7(_base) (_base + 0x15c) +#define CONN_HIF_DMASHDL_STATUS_RD_GP8(_base) (_base + 0x160) +#define CONN_HIF_DMASHDL_STATUS_RD_GP9(_base) (_base + 0x164) +#define CONN_HIF_DMASHDL_STATUS_RD_GP10(_base) (_base + 0x168) +#define CONN_HIF_DMASHDL_STATUS_RD_GP11(_base) (_base + 0x16c) +#define CONN_HIF_DMASHDL_STATUS_RD_GP12(_base) (_base + 0x170) +#define CONN_HIF_DMASHDL_STATUS_RD_GP13(_base) (_base + 0x174) +#define CONN_HIF_DMASHDL_STATUS_RD_GP14(_base) (_base + 0x178) +#define CONN_HIF_DMASHDL_STATUS_RD_GP15(_base) (_base + 0x17c) +#define CONN_HIF_DMASHDLRD_GP_PKT_CNT_0(_base) (_base + 0x180) +#define CONN_HIF_DMASHDLRD_GP_PKT_CNT_1(_base) (_base + 0x184) +#define CONN_HIF_DMASHDLRD_GP_PKT_CNT_2(_base) (_base + 0x188) +#define CONN_HIF_DMASHDLRD_GP_PKT_CNT_3(_base) (_base + 0x18c) +#define CONN_HIF_DMASHDLRD_GP_PKT_CNT_4(_base) (_base + 0x190) +#define CONN_HIF_DMASHDLRD_GP_PKT_CNT_5(_base) (_base + 0x194) +#define CONN_HIF_DMASHDLRD_GP_PKT_CNT_6(_base) (_base + 0x198) +#define CONN_HIF_DMASHDLRD_GP_PKT_CNT_7(_base) (_base + 0x19c) + +/* ============================================================================ + * + * ---REFILL_CONTROL (0x5000A000 + 0x10)--- + * + * GROUP0_REFILL_DISABLE[16] - (RW) Group0 refill control + * GROUP1_REFILL_DISABLE[17] - (RW) Group1 refill control + * GROUP2_REFILL_DISABLE[18] - (RW) Group2 refill control + * GROUP3_REFILL_DISABLE[19] - (RW) Group3 refill control + * GROUP4_REFILL_DISABLE[20] - (RW) Group4 refill control + * GROUP5_REFILL_DISABLE[21] - (RW) Group5 refill control + * GROUP6_REFILL_DISABLE[22] - (RW) Group6 refill control + * GROUP7_REFILL_DISABLE[23] - (RW) Group7 refill control + * GROUP8_REFILL_DISABLE[24] - (RW) Group8 refill control + * GROUP9_REFILL_DISABLE[25] - (RW) Group9 refill control + * GROUP10_REFILL_DISABLE[26] - (RW) Group10 refill control + * GROUP11_REFILL_DISABLE[27] - (RW) Group11 refill control + * GROUP12_REFILL_DISABLE[28] - (RW) Group12 refill control + * GROUP13_REFILL_DISABLE[29] - (RW) Group13 refill control + * GROUP14_REFILL_DISABLE[30] - (RW) Group14 refill control + * GROUP15_REFILL_DISABLE[31] - (RW) Group15 refill control + * + * ============================================================================ + */ +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP15_REFILL_DISABLE_MASK \ + 0x80000000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP14_REFILL_DISABLE_MASK \ + 0x40000000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP13_REFILL_DISABLE_MASK \ + 0x20000000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP12_REFILL_DISABLE_MASK \ + 0x10000000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP11_REFILL_DISABLE_MASK \ + 0x08000000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP10_REFILL_DISABLE_MASK \ + 0x04000000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP9_REFILL_DISABLE_MASK \ + 0x02000000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP8_REFILL_DISABLE_MASK \ + 0x01000000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP7_REFILL_DISABLE_MASK \ + 0x00800000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP6_REFILL_DISABLE_MASK \ + 0x00400000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP5_REFILL_DISABLE_MASK \ + 0x00200000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP4_REFILL_DISABLE_MASK \ + 0x00100000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP3_REFILL_DISABLE_MASK \ + 0x00080000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP2_REFILL_DISABLE_MASK \ + 0x00040000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP1_REFILL_DISABLE_MASK \ + 0x00020000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP0_REFILL_DISABLE_MASK \ + 0x00010000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP15_REFILL_PRIORITY_MASK \ + 0x00008000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP14_REFILL_PRIORITY_MASK \ + 0x00004000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP13_REFILL_PRIORITY_MASK \ + 0x00002000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP12_REFILL_PRIORITY_MASK \ + 0x00001000 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP11_REFILL_PRIORITY_MASK \ + 0x00000800 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP10_REFILL_PRIORITY_MASK \ + 0x00000400 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP9_REFILL_PRIORITY_MASK \ + 0x00000200 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP8_REFILL_PRIORITY_MASK \ + 0x00000100 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP7_REFILL_PRIORITY_MASK \ + 0x00000080 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP6_REFILL_PRIORITY_MASK \ + 0x00000040 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP5_REFILL_PRIORITY_MASK \ + 0x00000020 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP4_REFILL_PRIORITY_MASK \ + 0x00000010 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP3_REFILL_PRIORITY_MASK \ + 0x00000008 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP2_REFILL_PRIORITY_MASK \ + 0x00000004 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP1_REFILL_PRIORITY_MASK \ + 0x00000002 +#define CONN_HIF_DMASHDL_TOP_REFILL_CONTROL_GROUP0_REFILL_PRIORITY_MASK \ + 0x00000001 + +/* ============================================================================ + * + * ---QUEUE_MAPPING0 (0x5000A000 + 0xd0)--- + * + * QUEUE0_MAPPING[3..0] - (RW) queue 0 use which group ID + * QUEUE1_MAPPING[7..4] - (RW) queue 1 use which group ID + * QUEUE2_MAPPING[11..8] - (RW) queue 2 use which group ID + * QUEUE3_MAPPING[15..12] - (RW) queue 3 use which group ID + * QUEUE4_MAPPING[19..16] - (RW) queue 4 use which group ID + * QUEUE5_MAPPING[23..20] - (RW) queue 5 use which group ID + * QUEUE6_MAPPING[27..24] - (RW) queue 6 use which group ID + * QUEUE7_MAPPING[31..28] - (RW) queue 7 use which group ID + * + * ============================================================================ + */ +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE7_MAPPING 28 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE6_MAPPING 24 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE5_MAPPING 20 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE4_MAPPING 16 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE3_MAPPING 12 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE2_MAPPING 8 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE1_MAPPING 4 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING0_QUEUE0_MAPPING 0 + +/* ============================================================================ + * + * ---QUEUE_MAPPING1 (0x5000A000 + 0xd4)--- + * + * QUEUE8_MAPPING[3..0] - (RW) queue 8 use which group ID + * QUEUE9_MAPPING[7..4] - (RW) queue 9 use which group ID + * QUEUE10_MAPPING[11..8] - (RW) queue 10 use which group ID + * QUEUE11_MAPPING[15..12] - (RW) queue 11 use which group ID + * QUEUE12_MAPPING[19..16] - (RW) queue 12 use which group ID + * QUEUE13_MAPPING[23..20] - (RW) queue 13 use which group ID + * QUEUE14_MAPPING[27..24] - (RW) queue 14 use which group ID + * QUEUE15_MAPPING[31..28] - (RW) queue 15 use which group ID + * + * ============================================================================ + */ +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE15_MAPPING 28 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE14_MAPPING 24 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE13_MAPPING 20 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE12_MAPPING 16 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE11_MAPPING 12 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE10_MAPPING 8 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE9_MAPPING 4 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING1_QUEUE8_MAPPING 0 + +/* ============================================================================ + * + * ---QUEUE_MAPPING2 (0x5000A000 + 0xd8)--- + * + * QUEUE16_MAPPING[3..0] - (RW) queue 16 use which group ID + * QUEUE17_MAPPING[7..4] - (RW) queue 17 use which group ID + * QUEUE18_MAPPING[11..8] - (RW) queue 18 use which group ID + * QUEUE19_MAPPING[15..12] - (RW) queue 19 use which group ID + * QUEUE20_MAPPING[19..16] - (RW) queue 20 use which group ID + * QUEUE21_MAPPING[23..20] - (RW) queue 21 use which group ID + * QUEUE22_MAPPING[27..24] - (RW) queue 22 use which group ID + * QUEUE23_MAPPING[31..28] - (RW) queue 23 use which group ID + * + * ============================================================================= + */ +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE23_MAPPING 28 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE22_MAPPING 24 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE21_MAPPING 20 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE20_MAPPING 16 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE19_MAPPING 12 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE18_MAPPING 8 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE17_MAPPING 4 +#define CONN_HIF_DMASHDL_TOP_QUEUE_MAPPING2_QUEUE16_MAPPING 0 + +#define DMASHDL_RSV_CNT_MASK (0xfff << 16) +#define DMASHDL_SRC_CNT_MASK (0xfff << 0) +#define DMASHDL_RSV_CNT_OFFSET 16 +#define DMASHDL_SRC_CNT_OFFSET 0 +#define DMASHDL_FREE_PG_CNT_MASK (0xfff << 16) +#define DMASHDL_FFA_CNT_MASK (0xfff << 0) +#define DMASHDL_FREE_PG_CNT_OFFSET 16 +#define DMASHDL_FFA_CNT_OFFSET 0 +#define DMASHDL_MAX_QUOTA_MASK (0xfff << 16) +#define DMASHDL_MIN_QUOTA_MASK (0xfff << 0) +#define DMASHDL_MAX_QUOTA_OFFSET 16 +#define DMASHDL_MIN_QUOTA_OFFSET 0 + +#define DMASHDL_MIN_QUOTA_NUM(p) (((p) & 0xfff) << DMASHDL_MIN_QUOTA_OFFSET) +#define GET_DMASHDL_MIN_QUOTA_NUM(p) \ + (((p) & DMASHDL_MIN_QUOTA_MASK) >> DMASHDL_MIN_QUOTA_OFFSET) + +#define DMASHDL_MAX_QUOTA_NUM(p) \ + (((p) & 0xfff) << DMASHDL_MAX_QUOTA_OFFSET) +#define GET_DMASHDL_MAX_QUOTA_NUM(p) \ + (((p) & DMASHDL_MAX_QUOTA_MASK) >> DMASHDL_MAX_QUOTA_OFFSET) + +#define ODD_GROUP_ASK_CN_MASK (0xff << 16) +#define ODD_GROUP_ASK_CN_OFFSET 16 +#define GET_ODD_GROUP_ASK_CNT(p) \ + (((p) & ODD_GROUP_ASK_CN_MASK) >> ODD_GROUP_ASK_CN_OFFSET) +#define ODD_GROUP_PKT_IN_CN_MASK (0xff << 24) +#define ODD_GROUP_PKT_IN_CN_OFFSET 24 +#define GET_ODD_GROUP_PKT_IN_CNT(p) \ + (((p) & ODD_GROUP_PKT_IN_CN_MASK) >> ODD_GROUP_PKT_IN_CN_OFFSET) +#define EVEN_GROUP_ASK_CN_MASK (0xff << 0) +#define EVEN_GROUP_ASK_CN_OFFSET 0 +#define GET_EVEN_GROUP_ASK_CNT(p) \ + (((p) & EVEN_GROUP_ASK_CN_MASK) >> EVEN_GROUP_ASK_CN_OFFSET) +#define EVEN_GROUP_PKT_IN_CN_MASK (0xff << 8) +#define EVEN_GROUP_PKT_IN_CN_OFFSET 8 +#define GET_EVEN_GROUP_PKT_IN_CNT(p) \ + (((p) & EVEN_GROUP_PKT_IN_CN_MASK) >> EVEN_GROUP_PKT_IN_CN_OFFSET) + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +#if defined(_HIF_PCIE) || defined(_HIF_AXI) +/* DMASHDL_REFILL_CONTROL */ +union _DMASHDL_REFILL_CONTROL { + struct { + uint32_t PRIORITY:16; + uint32_t DISABLE:16; + } field; + + uint32_t word; +}; + +/* DMASHDL_PACKET_MAX_SIZE */ +union _DMASHDL_PACKET_MAX_SIZE { + struct { + uint32_t PLE_SIZE:12; + uint32_t RSV_12_15:4; + uint32_t PSE_SIZE:12; + uint32_t RSV_28_31:4; + } field; + + uint32_t word; +}; + +/* DMASHDL_GROUP_CONTROL */ +union _DMASHDL_GROUP_CONTROL { + struct { + uint32_t MIN_QUOTAE:12; + uint32_t RSV_12_15:4; + uint32_t MAX_QUOTAE:12; + uint32_t RSV_28_31:4; + } field; + + uint32_t word; +}; +#endif /* _HIF_PCIE */ + +/* Group index */ +enum _ENUM_GROUP_INDEX_T { + GROUP0_INDEX = 0, + GROUP1_INDEX, + GROUP2_INDEX, + GROUP3_INDEX, + GROUP4_INDEX, + GROUP5_INDEX, + GROUP6_INDEX, + GROUP7_INDEX, + GROUP8_INDEX, + GROUP9_INDEX, + GROUP10_INDEX, + GROUP11_INDEX, + GROUP12_INDEX, + GROUP13_INDEX, + GROUP14_INDEX, + GROUP15_INDEX, + MAX_GROUP_NUM +}; + +/******************************************************************************* + * P U B 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 diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/connac_reg.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/connac_reg.h new file mode 100644 index 0000000000000..089040bc72aeb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/connac_reg.h @@ -0,0 +1,266 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "connac_reg.h" + * \brief The common register definition of MT6630 + * + * N/A + */ + + + +#ifndef _CONNAC_REG_H +#define _CONNAC_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 + ******************************************************************************* + */ +#define CONN_CFG_BASE 0x80020000 + +#define CONN_CFG_ON_BASE 0x81021000 + +#define CONN_CFG_ON_CONN_ON_MISC_ADDR (CONN_CFG_ON_BASE + 0x140) +#define CONN_CFG_CHIP_ID_ADDR (CONN_CFG_BASE + 0x1010) + +#define CONN_MCU_CONFG_ON_BASE 0x81030000 + +#define CONN_MCU_CONFG_ON_HOST_MAILBOX_WF_ADDR \ + (CONN_MCU_CONFG_ON_BASE + 0x100) + +/* + * ============================================================================ + * + * ---CONN_ON_MISC (0x81021000 + 0x140)--- + * + * HOST_LPCR_FW_OWN[0] - (W1C) xxx + * DRV_FM_STAT_SYNC[3..1] - (RW) xxx + * RBIST_MODE[4] - (RW) xxx + * RESERVED5[31..5] - (RO) Reserved bits + * + * ============================================================================ + */ +#define CONN_CFG_ON_CONN_ON_MISC_RBIST_MODE_ADDR \ + CONN_CFG_ON_CONN_ON_MISC_ADDR +#define CONN_CFG_ON_CONN_ON_MISC_RBIST_MODE_MASK \ + 0x00000010/*RBIST_MODE[4]*/ +#define CONN_CFG_ON_CONN_ON_MISC_RBIST_MODE_SHFT 4 +#define CONN_CFG_ON_CONN_ON_MISC_DRV_FM_STAT_SYNC_ADDR \ + CONN_CFG_ON_CONN_ON_MISC_ADDR +#define CONN_CFG_ON_CONN_ON_MISC_DRV_FM_STAT_SYNC_MASK \ + 0x0000000E/*DRV_FM_STAT_SYNC[3..1]*/ +#define CONN_CFG_ON_CONN_ON_MISC_DRV_FM_STAT_SYNC_SHFT 1 +#define CONN_CFG_ON_CONN_ON_MISC_HOST_LPCR_FW_OWN_ADDR \ + CONN_CFG_ON_CONN_ON_MISC_ADDR +#define CONN_CFG_ON_CONN_ON_MISC_HOST_LPCR_FW_OWN_MASK \ + 0x00000001/*HOST_LPCR_FW_OWN[0]*/ +#define CONN_CFG_ON_CONN_ON_MISC_HOST_LPCR_FW_OWN_SHFT 0 + +#define CONN_HIF_BASE 0x7000 +#define CONN_HIF_ON_LPCTL (CONN_HIF_BASE) +#define CONN_HIF_ON_IRQ_STAT (CONN_HIF_BASE + 0x4) +#define CONN_HIF_ON_IRQ_ENA (CONN_HIF_BASE + 0x8) +#define CONN_HIF_ON_DBGCR01 (CONN_HIF_BASE + 0x104) + +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + +/* MCU Interrupt Event */ +#define HOST2MCU_SW_INT_SET (PCIE_HIF_BASE + 0x0108) + +/* MCU2HOST Software interrupt set */ +#define MCU2HOST_SW_INT_SET (PCIE_HIF_BASE + 0x010C) + +/* MCU to Host interrupt status */ +#define MCU2HOST_SW_INT_STA (PCIE_HIF_BASE + 0x01F0) + +/* MCU to Host interrupt enable */ +#define MCU2HOST_SW_INT_ENA (PCIE_HIF_BASE + 0x01F4) + +#define WPDMA_PAUSE_TX_Q (PCIE_HIF_BASE + 0x0224) + +/* Configuraiton Push */ +#define PCIE_DOORBELL_PUSH (0x484) +#define CR_PCIE_CFG_SET_OWN (0x1 << 0) +#define CR_PCIE_CFG_CLEAR_OWN (0x1 << 1) +#endif /* _HIF_PCIE */ + +#if defined(_HIF_USB) +#define CONNAC_UDMA_BASE 0x7C000000 +#define CONNAC_UDMA_TX_QSEL (CONNAC_UDMA_BASE + 0x8) +#define CONNAC_UDMA_RESET (CONNAC_UDMA_BASE + 0x14) +#define CONNAC_UDMA_WLCFG_1 (CONNAC_UDMA_BASE + 0xc) +#define CONNAC_UDMA_WLCFG_0 (CONNAC_UDMA_BASE + 0x18) + +#define UDMA_WLCFG_0_TX_BUSY_MASK (0x1 << 31) +#define UDMA_WLCFG_0_1US_TIMER_EN_MASK (0x1 << 20) +#define UDMA_WLCFG_0_1US_TIMER_EN(p) (((p) & 0x1) << 20) +#define UDMA_WLCFG_0_RX_FLUSH_MASK (0x1 << 19) +#define UDMA_WLCFG_0_TX_TIMEOUT_EN_MASK (0x1 << 16) + +#define UDMA_WLCFG_1_TX_TIMEOUT_LIMIT_MASK (0xFFFFF << 8) +#define UDMA_WLCFG_1_TX_TIMEOUT_LIMIT(p) (((p) & 0xFFFFF) << 8) +#define UDMA_TX_TIMEOUT_STATUS_MASK (0x1 << 13) + +#define UDMA_TX_TIMEOUT_LIMIT (50000) + +#define UDMA_TX_IDLE_MASK 0x00003f00 + +#define PDMA_IF_MISC 0x500000a8 +#define PDMA_IF_MISC_TX_ENABLE_MASK 0x00000001 + +#define PDMA_HIF_RESET 0x50000100 +#define DPMA_HIF_LOGIC_RESET_MASK (0x1 << 4) + +#define PDMA_DEBUG_EN 0x50000124 +#define PDMA_DEBUG_STATUS 0x50000128 +#define PDMA_DEBUG_TX_STATUS_MASK 0x004c0000 /* 0x00400000 */ +#define PDMA_DEBUG_DMASHDL_REQUEST_DONE_MASK 0x00100000 + +#define PDMA_BUSY_STATUS 0x50000168 +#define PDMA_TX_BUSY_MASK 0x00000001 + +#define PDMA_TX_IDLE_WAIT_COUNT 30 +#endif /* _HIF_USB */ + +#if defined(_HIF_PCIE) || defined(_HIF_AXI) +#define PDMA_DEBUG_EN 0x50000124 +#define PDMA_DEBUG_STATUS 0x50000128 +#define AXI_DEBUG_DEBUG_EN 0x5000012C +#define CONN_HIF_DEBUG_STATUS 0x50000130 +#define PDMA_DEBUG_HIF_BUSY_STATUS 0x50000138 +#define PDMA_DEBUG_BUSY_STATUS 0x50000168 +#define PDMA_DEBUG_REFill 0x5000A010 + +#define PDMA_AXI_DEBUG_FLAG 0x2222 +#define GALS_AXI_DEBUG_FLAG 0x3333 +#define MCU_AXI_DEBUG_FLAG 0x4444 +#define RBUS_DEBUG_FLAG 0x118 +#endif /* _HIF_PCIE */ + + +#define PLE_PKT_MAX_SIZE_MASK (0xfff << 0) +#define PLE_PKT_MAX_SIZE_NUM(p) (((p) & 0xfff) << 0) +#define GET_PLE_PKT_MAX_SIZE_NUM(p) (((p) & PLE_PKT_MAX_SIZE_MASK) >> 0) + +#define PSE_PKT_MAX_SIZE_MASK (0xfff << 16) +#define PSE_PKT_MAX_SIZE_NUM(p) (((p) & 0xfff) << 16) +#define GET_PSE_PKT_MAX_SIZE_NUM(p) (((p) & PSE_PKT_MAX_SIZE_MASK) >> 16) + +#define EXTRA_TXD_SIZE_FOR_TX_BYTE_COUNT 32 + +#define MCU_INT_PDMA0_STOP_DONE BIT(0) +#define MCU_INT_PDMA0_INIT_DONE BIT(1) +#define MCU_INT_SER_TRIGGER_FROM_HOST BIT(2) +#define MCU_INT_PDMA0_RECOVERY_DONE BIT(3) +#define MCU_INT_DRIVER_SER BIT(4) +#define CONNAC_MCU_SW_INT BIT(29) + +#define ERROR_DETECT_STOP_PDMA_WITH_FW_RELOAD BIT(1) +#define ERROR_DETECT_STOP_PDMA BIT(2) +#define ERROR_DETECT_RESET_DONE BIT(3) +#define ERROR_DETECT_RECOVERY_DONE BIT(4) +#define ERROR_DETECT_N9_NORMAL_STATE BIT(5) +#define CP_LMAC_HANG_WORKAROUND_STEP1 BIT(8) +#define CP_LMAC_HANG_WORKAROUND_STEP2 BIT(9) +#define ERROR_DETECT_LMAC_ERROR BIT(24) +#define ERROR_DETECT_PSE_ERROR BIT(25) +#define ERROR_DETECT_PLE_ERROR BIT(26) +#define ERROR_DETECT_PDMA_ERROR BIT(27) +#define ERROR_DETECT_PCIE_ERROR BIT(28) + +#define ERROR_DETECT_MASK \ + (ERROR_DETECT_STOP_PDMA \ + | ERROR_DETECT_RESET_DONE \ + | ERROR_DETECT_RECOVERY_DONE \ + | ERROR_DETECT_N9_NORMAL_STATE) + + +/******************************************************************************* + * 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 diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/hal.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/hal.h new file mode 100644 index 0000000000000..f1f9472294649 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/hal.h @@ -0,0 +1,1220 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "hal.h" + * \brief The declaration of hal functions + * + * N/A + */ + + +#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 CFG_SUPPORT_SNIFFER +#define HAL_MON_EN(_prAdapter) (_prAdapter->prGlueInfo->fgIsEnableMon) +#else +#define HAL_MON_EN(_prAdapter) FALSE +#endif + +#if defined(_HIF_SDIO) +#define HAL_MCR_RD(_prAdapter, _u4Offset, _pu4Value) \ +do { \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (_u4Offset > 0xFFFF) { \ + if (kalDevRegRead_mac(_prAdapter->prGlueInfo, \ + _u4Offset, _pu4Value) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, \ + "HAL_MCR_RD (MAC) access fail! 0x%x: 0x%x\n", \ + (uint32_t) (_u4Offset), \ + *((uint32_t *) (_pu4Value))); \ + } \ + } else { \ + if (kalDevRegRead(_prAdapter->prGlueInfo, \ + _u4Offset, _pu4Value) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, \ + "HAL_MCR_RD (SDIO) access fail! 0x%x: 0x%x\n", \ + (uint32_t) (_u4Offset), \ + *((uint32_t *) (_pu4Value))); \ + } \ + } \ + } else { \ + DBGLOG(HAL, WARN, "ignore HAL_MCR_RD access! 0x%x\n", \ + (uint32_t) (_u4Offset)); \ + } \ +} while (0) + +#define HAL_MCR_WR(_prAdapter, _u4Offset, _u4Value) \ +do { \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (_u4Offset > 0xFFFF) { \ + if (kalDevRegWrite_mac(_prAdapter->prGlueInfo, \ + _u4Offset, _u4Value) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, \ + "HAL_MCR_WR (MAC) access fail! 0x%x: 0x%x\n", \ + (uint32_t) (_u4Offset), \ + (uint32_t) (_u4Value)); \ + } \ + } else { \ + if (kalDevRegWrite(_prAdapter->prGlueInfo, \ + _u4Offset, _u4Value) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, \ + "HAL_MCR_WR (SDIO) access fail! 0x%x: 0x%x\n", \ + (uint32_t) (_u4Offset), \ + (uint32_t) (_u4Value)); \ + } \ + } \ + } else { \ + DBGLOG(HAL, WARN, "ignore HAL_MCR_WR access! 0x%x: 0x%x\n", \ + (uint32_t) (_u4Offset), (uint32_t) (_u4Value)); \ + } \ +} while (0) + +#define HAL_PORT_RD(_prAdapter, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ +{ \ + /*fgResult = FALSE; */\ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (kalDevPortRead(_prAdapter->prGlueInfo, _u4Port, _u4Len, \ + _pucBuf, _u4ValidBufSize) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, "HAL_PORT_RD access fail! 0x%x\n", \ + (uint32_t) (_u4Port)); \ + } \ + else { \ + /*fgResult = TRUE;*/ } \ + } else { \ + DBGLOG(HAL, WARN, "ignore HAL_PORT_RD access! 0x%x\n", \ + (uint32_t) (_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", \ + (uint32_t) (_u4Port)); \ + } \ + else \ + ; /*fgResult = TRUE;*/ \ + } else { \ + DBGLOG(HAL, WARN, "ignore HAL_PORT_WR access! 0x%x\n", \ + (uint32_t) (_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", \ + (uint32_t)(_u4Port)); \ + } \ + else { \ + /* Todo:: Nothing*/ \ + } \ + } \ + else { \ + DBGLOG(HAL, WARN, "ignore HAL_BYTE_WR access! 0x%x\n", \ + (uint32_t) (_u4Port)); \ + } \ +} + +#define HAL_DRIVER_OWN_BY_SDIO_CMD52(_prAdapter, _pfgDriverIsOwnReady) \ +{ \ + uint8_t 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) \ +{ \ + HAL_MCR_WR(_prAdapter, _u4Port, (uint32_t)_ucBuf); \ +} + +#endif /* #if defined(_HIF_SDIO) */ + +#define HAL_WRITE_TX_DATA(_prAdapter, _prMsduInfo) \ +{ \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + kalDevWriteData(_prAdapter->prGlueInfo, _prMsduInfo); \ +} + +#define HAL_KICK_TX_DATA(_prAdapter) \ +{ \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + kalDevKickData(_prAdapter->prGlueInfo); \ +} + +#define HAL_WRITE_TX_CMD(_prAdapter, _prCmdInfo, _ucTC) \ +{ \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + kalDevWriteCmd(_prAdapter->prGlueInfo, _prCmdInfo, _ucTC); \ +} + +#if defined(_HIF_PCIE) || defined(_HIF_AXI) +#define HAL_READ_RX_PORT(prAdapter, u4PortId, u4Len, pvBuf, _u4ValidBufSize) \ +{ \ + ASSERT(u4PortId < 2); \ + HAL_PORT_RD(prAdapter, \ + u4PortId, \ + u4Len, \ + pvBuf, \ + _u4ValidBufSize/*temp!!*//*4Kbyte*/) \ +} + +#define HAL_WRITE_TX_PORT(_prAdapter, _u4PortId, _u4Len, _pucBuf, _u4BufSize) \ +{ \ + HAL_PORT_WR(_prAdapter, \ + _u4PortId, \ + _u4Len, \ + _pucBuf, \ + _u4BufSize/*temp!!*//*4KByte*/) \ +} + +#define HAL_MCR_RD_AND_WAIT(_pAdapter, _offset, _pReadValue, \ + _waitCondition, _waitDelay, _waitCount, _status) + +#define HAL_MCR_WR_AND_WAIT(_pAdapter, _offset, _writeValue, \ + _busyMask, _waitDelay, _waitCount, _status) + +#define HAL_GET_CHIP_ID_VER(_prAdapter, pu2ChipId, pu2Version) \ +{ \ + uint32_t u4Value = 0; \ + HAL_MCR_RD(_prAdapter, HIF_SYS_REV, &u4Value); \ + *pu2ChipId = ((u4Value & PCIE_HIF_SYS_PROJ) >> 16); \ + *pu2Version = (u4Value & PCIE_HIF_SYS_REV); \ +} + +#define HAL_WIFI_FUNC_READY_CHECK(_prAdapter, _checkItem, _pfgResult) \ +do { \ + struct mt66xx_chip_info *prChipInfo = NULL; \ + uint32_t u4Value = 0; \ + if (!_prAdapter->chip_info) \ + ASSERT(0); \ + *_pfgResult = FALSE; \ + prChipInfo = _prAdapter->chip_info; \ + HAL_MCR_RD(_prAdapter, prChipInfo->sw_sync0, &u4Value); \ + if ((u4Value & (_checkItem << prChipInfo->sw_ready_bit_offset)) \ + == (_checkItem << prChipInfo->sw_ready_bit_offset)) \ + *_pfgResult = TRUE; \ +} while (0) + +#define HAL_WIFI_FUNC_OFF_CHECK(_prAdapter, _checkItem, _pfgResult) \ +do { \ + u_int8_t fgLpOwnResult; \ + HAL_WIFI_FUNC_READY_CHECK(_prAdapter, _checkItem, _pfgResult); \ + if (*_pfgResult) { \ + HAL_LP_OWN_RD(_prAdapter, &fgLpOwnResult); \ + if (fgLpOwnResult == FALSE) { \ + DBGLOG(INIT, INFO, \ + "HAL_LP_OWN_RD %d\n", fgLpOwnResult); \ + HAL_LP_OWN_SET(prAdapter, &fgLpOwnResult); \ + DBGLOG(INIT, INFO, \ + "HAL_LP_OWN_SET %d\n", fgLpOwnResult); \ + } \ + } \ + *_pfgResult = !*_pfgResult; \ +} while (0) + +#define HAL_WIFI_FUNC_GET_STATUS(_prAdapter, _u4Result) \ +do { \ + struct mt66xx_chip_info *prChipInfo = NULL; \ + struct BUS_INFO *prBusInfo = NULL; \ + uint32_t u4Value = 0; \ + if (!_prAdapter->chip_info || !_prAdapter->chip_info->bus_info) \ + ASSERT(0); \ + prChipInfo = _prAdapter->chip_info; \ + prBusInfo = prChipInfo->bus_info; \ + HAL_MCR_RD(_prAdapter, prChipInfo->sw_sync0, &_u4Result); \ + if (prBusInfo->getMailboxStatus) { \ + prBusInfo->getMailboxStatus(_prAdapter, &u4Value); \ + DBGLOG(INIT, INFO, "Mailbox: 0x%x\n", u4Value); \ + } \ +} while (0) + +#define HAL_INTR_DISABLE(_prAdapter) + +#define HAL_INTR_ENABLE(_prAdapter) + +#define HAL_INTR_ENABLE_AND_LP_OWN_SET(_prAdapter) + +/* Polling interrupt status bit due to CFG_PCIE_LPCR_HOST + * status bit not work when chip sleep + */ +#define HAL_LP_OWN_RD(_prAdapter, _pfgResult) \ +do { \ + struct mt66xx_chip_info *prChipInfo = NULL; \ + struct BUS_INFO *prBusInfo = NULL; \ + if (!_prAdapter->chip_info || !_prAdapter->chip_info->bus_info) \ + ASSERT(0); \ + prChipInfo = _prAdapter->chip_info; \ + prBusInfo = prChipInfo->bus_info; \ + prBusInfo->lowPowerOwnRead(_prAdapter, _pfgResult); \ +} while (0) + +#define HAL_LP_OWN_SET(_prAdapter, _pfgResult) \ +do { \ + struct mt66xx_chip_info *prChipInfo = NULL; \ + struct BUS_INFO *prBusInfo = NULL; \ + if (!_prAdapter->chip_info || !_prAdapter->chip_info->bus_info) \ + ASSERT(0); \ + prChipInfo = _prAdapter->chip_info; \ + prBusInfo = prChipInfo->bus_info; \ + prBusInfo->lowPowerOwnSet(_prAdapter, _pfgResult); \ +} while (0) + +#define HAL_LP_OWN_CLR(_prAdapter, _pfgResult) \ +do { \ + struct mt66xx_chip_info *prChipInfo = NULL; \ + struct BUS_INFO *prBusInfo = NULL; \ + if (!_prAdapter->chip_info || !_prAdapter->chip_info->bus_info) \ + ASSERT(0); \ + prChipInfo = _prAdapter->chip_info; \ + prBusInfo = prChipInfo->bus_info; \ + prBusInfo->lowPowerOwnClear(_prAdapter, _pfgResult); \ +} while (0) + +#define HAL_GET_ABNORMAL_INTERRUPT_REASON_CODE(_prAdapter, pu4AbnormalReason) + +#define HAL_DISABLE_RX_ENHANCE_MODE(_prAdapter) + +#define HAL_ENABLE_RX_ENHANCE_MODE(_prAdapter) + +#define HAL_CFG_MAX_HIF_RX_LEN_NUM(_prAdapter, _ucNumOfRxLen) + +#define HAL_SET_INTR_STATUS_READ_CLEAR(prAdapter) + +#define HAL_SET_INTR_STATUS_WRITE_1_CLEAR(prAdapter) + +#define HAL_READ_INTR_STATUS(prAdapter, length, pvBuf) + +#define HAL_READ_TX_RELEASED_COUNT(_prAdapter, au2TxReleaseCount) + +#define HAL_READ_RX_LENGTH(prAdapter, pu2Rx0Len, pu2Rx1Len) + +#define HAL_GET_INTR_STATUS_FROM_ENHANCE_MODE_STRUCT(pvBuf, u2Len, pu4Status) + +#define HAL_GET_TX_STATUS_FROM_ENHANCE_MODE_STRUCT(pvInBuf, \ + pu4BufOut, u4LenBufOut) + +#define HAL_GET_RX_LENGTH_FROM_ENHANCE_MODE_STRUCT(pvInBuf, \ + pu2Rx0Num, au2Rx0Len, pu2Rx1Num, au2Rx1Len) + +#define HAL_GET_MAILBOX_FROM_ENHANCE_MODE_STRUCT(pvInBuf, \ + pu4Mailbox0, pu4Mailbox1) + +#define HAL_IS_TX_DONE_INTR(u4IntrStatus) \ + ((u4IntrStatus & (WPDMA_TX_DONE_INT0 | \ + WPDMA_TX_DONE_INT1 | WPDMA_TX_DONE_INT2 | WPDMA_TX_DONE_INT3 | \ + WPDMA_TX_DONE_INT15)) ? TRUE : FALSE) + +#define HAL_IS_RX_DONE_INTR(u4IntrStatus) \ + ((u4IntrStatus & (WPDMA_RX_DONE_INT0 | WPDMA_RX_DONE_INT1)) \ + ? TRUE : FALSE) + +#define HAL_IS_ABNORMAL_INTR(u4IntrStatus) + +#define HAL_IS_FW_OWNBACK_INTR(u4IntrStatus) + +#define HAL_PUT_MAILBOX(prAdapter, u4MboxId, u4Data) + +#define HAL_GET_MAILBOX(prAdapter, u4MboxId, pu4Data) + +#define HAL_SET_MAILBOX_READ_CLEAR(prAdapter, fgEnableReadClear) \ +{ \ + prAdapter->prGlueInfo->rHifInfo.fgMbxReadClear = fgEnableReadClear;\ +} + +#define HAL_GET_MAILBOX_READ_CLEAR(prAdapter) \ + (prAdapter->prGlueInfo->rHifInfo.fgMbxReadClear) + +#define HAL_READ_INT_STATUS(prAdapter, _pu4IntStatus) \ +{ \ + kalDevReadIntStatus(prAdapter, _pu4IntStatus);\ +} + +#define HAL_HIF_INIT(prAdapter) + +#define HAL_ENABLE_FWDL(_prAdapter, _fgEnable) \ +{ \ + halEnableFWDownload(_prAdapter, _fgEnable); \ +} + +#define HAL_WAKE_UP_WIFI(_prAdapter) \ +{ \ + halWakeUpWiFi(_prAdapter);\ +} + +#define HAL_CLEAR_DUMMY_REQ(_prAdapter) \ +{ \ + struct mt66xx_chip_info *prChipInfo = NULL; \ + uint32_t u4Value = 0; \ + if (!_prAdapter->chip_info) {\ + ASSERT(0); \ + } else {\ + prChipInfo = _prAdapter->chip_info; \ + HAL_MCR_RD(_prAdapter, prChipInfo->sw_sync0, &u4Value); \ + u4Value &= ~(WIFI_FUNC_DUMMY_REQ << \ + prChipInfo->sw_ready_bit_offset);\ + HAL_MCR_WR(prAdapter, prChipInfo->sw_sync0, u4Value);\ + } \ +} + +#define HAL_IS_TX_DIRECT(_prAdapter) FALSE + +#define HAL_IS_RX_DIRECT(_prAdapter) FALSE + +#define HAL_HAS_AGG_THREAD(_prAdapter) FALSE + +#define HAL_AGG_THREAD(_prAdapter) + +#define HAL_AGG_THREAD_WAKE_UP(_prAdapter) + +#define HAL_AGG_KICK_DATA(_prAdapter) + +#endif + +#if defined(_HIF_SDIO) +#define HIF_H2D_SW_INT_SHFT (16) +/* bit16 */ +#define SDIO_MAILBOX_FUNC_READ_REG_IDX (BIT(0) << HIF_H2D_SW_INT_SHFT) +/* bit17 */ +#define SDIO_MAILBOX_FUNC_WRITE_REG_IDX (BIT(1) << HIF_H2D_SW_INT_SHFT) +/* bit18 */ +#define SDIO_MAILBOX_FUNC_CHECKSUN16_IDX (BIT(2) << HIF_H2D_SW_INT_SHFT) + +#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, _u4PortId, _u4Len, _pucBuf, _u4BufSize) \ +{ \ + if ((_u4BufSize - _u4Len) >= sizeof(uint32_t)) { \ + /* fill with single dword of zero as TX-aggregation end */ \ + *(uint32_t *) (&((_pucBuf)[ALIGN_4(_u4Len)])) = 0; \ + } \ + HAL_PORT_WR(_prAdapter, \ + MCR_WTDR1, \ + _u4Len, \ + _pucBuf, \ + _u4BufSize/*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) \ + { \ + uint32_t count = 0; \ + (_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) \ + { \ + uint32_t u4Temp = 0; \ + uint32_t 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) \ +{ \ + uint32_t u4Value = 0; \ + HAL_MCR_RD(_prAdapter, \ + MCR_WCIR, \ + &u4Value); \ + *pu2ChipId = (uint16_t)(u4Value & WCIR_CHIP_ID); \ + *pu2Version = (uint16_t)(u4Value & WCIR_REVISION_ID) >> 16; \ +} + +#define HAL_WIFI_FUNC_READY_CHECK(_prAdapter, _checkItem, _pfgResult) \ +do { \ + uint32_t u4Value = 0; \ + *_pfgResult = FALSE; \ + HAL_MCR_RD(_prAdapter, \ + MCR_WCIR, \ + &u4Value); \ + if (u4Value & WCIR_WLAN_READY) { \ + *_pfgResult = TRUE; \ + } \ +} while (0) + +#define HAL_WIFI_FUNC_OFF_CHECK(_prAdapter, _checkItem, _pfgResult) \ +do { \ + uint32_t u4Value = 0; \ + *_pfgResult = FALSE; \ + HAL_MCR_RD(_prAdapter, MCR_WCIR, &u4Value); \ + if ((u4Value & WCIR_WLAN_READY) == 0) { \ + *_pfgResult = TRUE; \ + } \ + halPrintMailbox(_prAdapter);\ + halPollDbgCr(_prAdapter, LP_DBGCR_POLL_ROUND); \ +} while (0) + +#define HAL_WIFI_FUNC_GET_STATUS(_prAdapter, _u4Result) \ + halGetMailbox(_prAdapter, 0, &_u4Result) + +#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_RD(_prAdapter, _pfgResult) \ +{ \ + uint32_t u4RegValue = 0; \ + *_pfgResult = FALSE; \ + HAL_MCR_RD(_prAdapter, MCR_WHLPCR, &u4RegValue); \ + if (u4RegValue & WHLPCR_IS_DRIVER_OWN) { \ + *_pfgResult = TRUE; \ + } \ +} + +#define HAL_LP_OWN_SET(_prAdapter, _pfgResult) \ +{ \ + uint32_t u4RegValue = 0; \ + *_pfgResult = FALSE; \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHLPCR, \ + WHLPCR_FW_OWN_REQ_SET); \ + HAL_MCR_RD(_prAdapter, MCR_WHLPCR, &u4RegValue); \ + if (u4RegValue & WHLPCR_IS_DRIVER_OWN) { \ + *_pfgResult = TRUE; \ + } \ +} + +#define HAL_LP_OWN_CLR(_prAdapter, _pfgResult) \ +{ \ + uint32_t u4RegValue = 0; \ + *_pfgResult = FALSE; \ + /* Software get LP ownership */ \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHLPCR, \ + WHLPCR_FW_OWN_REQ_CLR); \ + HAL_MCR_RD(_prAdapter, MCR_WHLPCR, &u4RegValue); \ + if (u4RegValue & WHLPCR_IS_DRIVER_OWN) { \ + *_pfgResult = TRUE; \ + } \ +} + +#define HAL_GET_ABNORMAL_INTERRUPT_REASON_CODE(_prAdapter, pu4AbnormalReason) \ +{ \ + HAL_MCR_RD(_prAdapter, \ + MCR_WASR, \ + pu4AbnormalReason); \ +} + +#define HAL_DISABLE_RX_ENHANCE_MODE(_prAdapter) \ +{ \ + uint32_t u4Value = 0; \ + 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) \ +{ \ + uint32_t u4Value = 0; \ + 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) \ +{ \ + uint32_t u4Value = 0, ucNum; \ + ucNum = ((_ucNumOfRxLen >= 16) ? 0 : _ucNumOfRxLen); \ + HAL_MCR_RD(_prAdapter, \ + MCR_WHCR, \ + &u4Value); \ + u4Value &= ~WHCR_MAX_HIF_RX_LEN_NUM; \ + u4Value |= ((((uint32_t)ucNum) << WHCR_OFFSET_MAX_HIF_RX_LEN_NUM) \ + & WHCR_MAX_HIF_RX_LEN_NUM); \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHCR, \ + u4Value); \ +} + +#define HAL_SET_INTR_STATUS_READ_CLEAR(prAdapter) \ +{ \ + uint32_t u4Value = 0; \ + 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) \ +{ \ + uint32_t u4Value = 0; \ + 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, au2TxReleaseCount) \ +{ \ + uint32_t *pu4Value = (uint32_t *)au2TxReleaseCount; \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTQCR0, \ + &pu4Value[0]); \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTQCR1, \ + &pu4Value[1]); \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTQCR2, \ + &pu4Value[2]); \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTQCR3, \ + &pu4Value[3]); \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTQCR4, \ + &pu4Value[4]); \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTQCR5, \ + &pu4Value[5]); \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTQCR6, \ + &pu4Value[6]); \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTQCR7, \ + &pu4Value[7]); \ +} + +#define HAL_READ_RX_LENGTH(prAdapter, pu2Rx0Len, pu2Rx1Len) \ +{ \ + uint32_t u4Value = 0; \ + HAL_MCR_RD(prAdapter, \ + MCR_WRPLR, \ + &u4Value); \ + *pu2Rx0Len = (uint16_t)u4Value; \ + *pu2Rx1Len = (uint16_t)(u4Value >> 16); \ +} + +#define HAL_GET_INTR_STATUS_FROM_ENHANCE_MODE_STRUCT(pvBuf, \ + u2Len, pu4Status) \ +{ \ + uint32_t *pu4Buf = (uint32_t *)pvBuf; \ + *pu4Status = pu4Buf[0]; \ +} + +#define HAL_GET_TX_STATUS_FROM_ENHANCE_MODE_STRUCT(pvInBuf, \ + pu4BufOut, u4LenBufOut) \ +{ \ + uint32_t *pu4Buf = (uint32_t *)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) \ +{ \ + uint32_t *pu4Buf = (uint32_t *)pvInBuf; \ + ASSERT((sizeof(au2Rx0Len) / sizeof(uint16_t)) >= 16); \ + ASSERT((sizeof(au2Rx1Len) / sizeof(uint16_t)) >= 16); \ + *pu2Rx0Num = (uint16_t)pu4Buf[3]; \ + *pu2Rx1Num = (uint16_t)(pu4Buf[3] >> 16); \ + kalMemCopy(au2Rx0Len, &pu4Buf[4], 8); \ + kalMemCopy(au2Rx1Len, &pu4Buf[12], 8); \ +} + +#define HAL_GET_MAILBOX_FROM_ENHANCE_MODE_STRUCT(pvInBuf, \ + pu4Mailbox0, pu4Mailbox1) \ +{ \ + uint32_t *pu4Buf = (uint32_t *)pvInBuf; \ + *pu4Mailbox0 = (uint16_t)pu4Buf[21]; \ + *pu4Mailbox1 = (uint16_t)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) \ +{ \ + uint32_t u4Value = 0; \ + HAL_MCR_RD(prAdapter, MCR_WHCR, &u4Value);\ + HAL_MCR_WR(prAdapter, MCR_WHCR, \ + (fgEnableReadClear) ? \ + (u4Value | WHCR_RECV_MAILBOX_RD_CLR_EN) : \ + (u4Value & ~WHCR_RECV_MAILBOX_RD_CLR_EN)); \ + prAdapter->prGlueInfo->rHifInfo.fgMbxReadClear = fgEnableReadClear;\ +} + +#define HAL_GET_MAILBOX_READ_CLEAR(prAdapter) \ + (prAdapter->prGlueInfo->rHifInfo.fgMbxReadClear) + +#define HAL_READ_INT_STATUS(prAdapter, _pu4IntStatus) \ +{ \ + kalDevReadIntStatus(prAdapter, _pu4IntStatus);\ +} + +#define HAL_HIF_INIT(_prAdapter) \ +{ \ + halDevInit(_prAdapter);\ +} + +#define HAL_ENABLE_FWDL(_prAdapter, _fgEnable) + +#define HAL_WAKE_UP_WIFI(_prAdapter) \ +{ \ + halWakeUpWiFi(_prAdapter);\ +} + +#define HAL_IS_TX_DIRECT(_prAdapter) FALSE + +#define HAL_IS_RX_DIRECT(_prAdapter) FALSE + +#ifdef _SDIO_RING + +#define HAL_HAS_AGG_THREAD(_prAdapter) TRUE + +#define HAL_AGG_THREAD(_prAdapter) \ +{ \ + Initial_sdio_ring(_prAdapter->prGlueInfo);\ +} + +#define HAL_AGG_THREAD_WAKE_UP(_prAdapter) \ + Set_sdio_ring_event() + +#define HAL_AGG_KICK_DATA(_prAdapter) \ +{ \ + sdio_ring_kcik_data(_prAdapter->prGlueInfo);\ +} + +#else + +#define HAL_HAS_AGG_THREAD(_prAdapter) FALSE + +#define HAL_AGG_THREAD(_prAdapter) + +#define HAL_AGG_THREAD_WAKE_UP(_prAdapter) + +#define HAL_AGG_KICK_DATA(_prAdapter) + +#endif + +#endif + +#if defined(_HIF_USB) +#define HAL_GET_ABNORMAL_INTERRUPT_REASON_CODE(_prAdapter, \ + pu4AbnormalReason) + +#define HAL_DISABLE_RX_ENHANCE_MODE(_prAdapter) + +#define HAL_ENABLE_RX_ENHANCE_MODE(_prAdapter) + +#define HAL_CFG_MAX_HIF_RX_LEN_NUM(_prAdapter, _ucNumOfRxLen) + +#define HAL_SET_INTR_STATUS_READ_CLEAR(prAdapter) + +#define HAL_SET_INTR_STATUS_WRITE_1_CLEAR(prAdapter) + +#define HAL_READ_INTR_STATUS(prAdapter, length, pvBuf) + +#define HAL_READ_TX_RELEASED_COUNT(_prAdapter, au2TxReleaseCount) + +#define HAL_READ_RX_LENGTH(prAdapter, pu2Rx0Len, pu2Rx1Len) + +#define HAL_GET_INTR_STATUS_FROM_ENHANCE_MODE_STRUCT(pvBuf, \ + u2Len, pu4Status) + +#define HAL_GET_TX_STATUS_FROM_ENHANCE_MODE_STRUCT(pvInBuf, \ + pu4BufOut, u4LenBufOut) + +#define HAL_GET_RX_LENGTH_FROM_ENHANCE_MODE_STRUCT(pvInBuf, \ + pu2Rx0Num, au2Rx0Len, pu2Rx1Num, au2Rx1Len) + +#define HAL_GET_MAILBOX_FROM_ENHANCE_MODE_STRUCT(pvInBuf, \ + pu4Mailbox0, pu4Mailbox1) + +#define HAL_READ_TX_RELEASED_COUNT(_prAdapter, au2TxReleaseCount) + +#define HAL_IS_TX_DONE_INTR(u4IntrStatus) FALSE + +#define HAL_IS_RX_DONE_INTR(u4IntrStatus) + +#define HAL_IS_ABNORMAL_INTR(u4IntrStatus) + +#define HAL_IS_FW_OWNBACK_INTR(u4IntrStatus) + +#define HAL_PUT_MAILBOX(prAdapter, u4MboxId, u4Data) + +#define HAL_GET_MAILBOX(prAdapter, u4MboxId, pu4Data) TRUE + +#define HAL_SET_MAILBOX_READ_CLEAR(prAdapter, fgEnableReadClear) + +#define HAL_GET_MAILBOX_READ_CLEAR(prAdapter) TRUE + +#define HAL_WIFI_FUNC_POWER_ON(_prAdapter) \ + mtk_usb_vendor_request(_prAdapter->prGlueInfo, 0, \ + DEVICE_VENDOR_REQUEST_OUT, \ + VND_REQ_POWER_ON_WIFI, 0, 1, NULL, 0) + +#define HAL_WIFI_FUNC_CHIP_RESET(_prAdapter) \ + mtk_usb_vendor_request(_prAdapter->prGlueInfo, 0, \ + DEVICE_VENDOR_REQUEST_OUT, \ + VND_REQ_POWER_ON_WIFI, 1, 1, NULL, 0) + +#if CFG_SUPPORT_SER +#define HAL_WIFI_FUNC_GET_SER_STATE(_prAdapter, _pu2SerState) \ + mtk_usb_vendor_request(_prAdapter->prGlueInfo, \ + 0, \ + DEVICE_VENDOR_REQUEST_IN, \ + VND_REQ_WIFI_SER_CONTROL, \ + WVALUE_WIFI_GET_SER_STATE, \ + 0, \ + _pu2SerState, \ + 2) + +#define HAL_WIFI_FUNC_SET_SER_STATE(_prAdapter, _u2NewSerState) \ + mtk_usb_vendor_request(_prAdapter->prGlueInfo, \ + 0, \ + DEVICE_VENDOR_REQUEST_OUT, \ + VND_REQ_WIFI_SER_CONTROL, \ + WVALUE_WIFI_SET_SER_STATE, \ + _u2NewSerState, \ + NULL, \ + 0) +#endif /* CFG_SUPPORT_SER */ + +#define HAL_WIFI_FUNC_READY_CHECK(_prAdapter, _checkItem, _pfgResult) \ +do { \ + struct mt66xx_chip_info *prChipInfo = NULL; \ + uint32_t u4Value = 0; \ + if (!_prAdapter->chip_info) \ + ASSERT(0); \ + *_pfgResult = FALSE; \ + prChipInfo = _prAdapter->chip_info; \ + HAL_MCR_RD(_prAdapter, prChipInfo->sw_sync0, &u4Value); \ + if ((u4Value & (_checkItem << prChipInfo->sw_ready_bit_offset)) \ + == (_checkItem << prChipInfo->sw_ready_bit_offset)) \ + *_pfgResult = TRUE; \ +} while (0) + +#define HAL_WIFI_FUNC_OFF_CHECK(_prAdapter, _checkItem, _pfgResult) \ +do { \ + struct mt66xx_chip_info *prChipInfo = NULL; \ + uint32_t u4Value = 0; \ + if (!_prAdapter->chip_info) \ + ASSERT(0); \ + *_pfgResult = FALSE; \ + prChipInfo = _prAdapter->chip_info; \ + HAL_MCR_RD(_prAdapter, prChipInfo->sw_sync0, &u4Value); \ + if ((u4Value & (_checkItem << prChipInfo->sw_ready_bit_offset)) == 0) \ + *_pfgResult = TRUE; \ +} while (0) + +#define HAL_WIFI_FUNC_GET_STATUS(_prAdapter, _u4Result) \ +do { \ + struct mt66xx_chip_info *prChipInfo = NULL; \ + if (!_prAdapter->chip_info) \ + ASSERT(0); \ + prChipInfo = _prAdapter->chip_info; \ + HAL_MCR_RD(_prAdapter, prChipInfo->sw_sync0, &_u4Result); \ +} while (0) + +#define HAL_INTR_DISABLE(_prAdapter) + +#define HAL_INTR_ENABLE(_prAdapter) + +#define HAL_INTR_ENABLE_AND_LP_OWN_SET(_prAdapter) + +#define HAL_READ_INT_STATUS(prAdapter, _pu4IntStatus) \ +{ \ + halGetCompleteStatus(prAdapter, _pu4IntStatus); \ +} + +#define HAL_HIF_INIT(_prAdapter) \ +{ \ + halDevInit(_prAdapter);\ +} + +#define HAL_ENABLE_FWDL(_prAdapter, _fgEnable) \ +{ \ + halEnableFWDownload(_prAdapter, _fgEnable);\ +} + +#define HAL_WAKE_UP_WIFI(_prAdapter) \ +{ \ + halWakeUpWiFi(_prAdapter);\ +} + +#define HAL_LP_OWN_RD(_prAdapter, _pfgResult) + +#define HAL_LP_OWN_SET(_prAdapter, _pfgResult) + +#define HAL_LP_OWN_CLR(_prAdapter, _pfgResult) + +#define HAL_WRITE_TX_PORT(_prAdapter, _u4PortId, _u4Len, _pucBuf, _u4BufSize) \ +{ \ + HAL_PORT_WR(_prAdapter, \ + _u4PortId, \ + _u4Len, \ + _pucBuf, \ + _u4BufSize/*temp!!*//*4KByte*/) \ +} + +#define HAL_IS_TX_DIRECT(_prAdapter) \ + ((CFG_TX_DIRECT_USB) ? TRUE : FALSE) + +#define HAL_IS_RX_DIRECT(_prAdapter) \ + ((CFG_RX_DIRECT_USB) ? TRUE : FALSE) + +#define HAL_HAS_AGG_THREAD(_prAdapter) FALSE + +#define HAL_AGG_THREAD(_prAdapter) + +#define HAL_AGG_THREAD_WAKE_UP(_prAdapter) + +#define HAL_AGG_KICK_DATA(_prAdapter) + +#endif + +#define INVALID_VERSION 0xFFFF /* used by HW/FW version */ +/******************************************************************************* + * 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 + ******************************************************************************* + */ + +u_int8_t halVerifyChipID(IN struct ADAPTER *prAdapter); +uint32_t halGetChipHwVer(IN struct ADAPTER *prAdapter); +uint32_t halGetChipSwVer(IN struct ADAPTER *prAdapter); + +uint32_t halRxWaitResponse(IN struct ADAPTER *prAdapter, + IN uint8_t ucPortIdx, OUT uint8_t *pucRspBuffer, + IN uint32_t u4MaxRespBufferLen, OUT uint32_t *pu4Length); + +void halEnableInterrupt(IN struct ADAPTER *prAdapter); +void halDisableInterrupt(IN struct ADAPTER *prAdapter); + +u_int8_t halSetDriverOwn(IN struct ADAPTER *prAdapter); +void halSetFWOwn(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnableGlobalInt); + +void halDevInit(IN struct ADAPTER *prAdapter); +void halEnableFWDownload(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnable); +void halWakeUpWiFi(IN struct ADAPTER *prAdapter); +void halTxCancelSendingCmd(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo); +void halTxCancelAllSending(IN struct ADAPTER *prAdapter); +u_int8_t halTxIsDataBufEnough(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); +void halProcessTxInterrupt(IN struct ADAPTER *prAdapter); +uint32_t halTxPollingResource(IN struct ADAPTER *prAdapter, + IN uint8_t ucTC); +void halSerHifReset(IN struct ADAPTER *prAdapter); + +void halProcessRxInterrupt(IN struct ADAPTER *prAdapter); +void halProcessAbnormalInterrupt(IN struct ADAPTER *prAdapter); +void halProcessSoftwareInterrupt(IN struct ADAPTER *prAdapter); +/* Hif power off wifi */ +uint32_t halHifPowerOffWifi(IN struct ADAPTER *prAdapter); + + +bool halHifSwInfoInit(IN struct ADAPTER *prAdapter); +void halRxProcessMsduReport(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb); +uint32_t halTxGetPageCount(IN struct ADAPTER *prAdapter, + IN uint32_t u4FrameLength, IN u_int8_t fgIncludeDesc); +uint32_t halDumpHifStatus(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, IN uint32_t u4Max); +u_int8_t halIsPendingRx(IN struct ADAPTER *prAdapter); +uint32_t halGetValidCoalescingBufSize(IN struct ADAPTER *prAdapter); +uint32_t halAllocateIOBuffer(IN struct ADAPTER *prAdapter); +uint32_t halReleaseIOBuffer(IN struct ADAPTER *prAdapter); +void halDeAggRxPktWorker(struct work_struct *work); +void halRxTasklet(unsigned long data); +void halTxCompleteTasklet(unsigned long data); +void halPrintHifDbgInfo(IN struct ADAPTER *prAdapter); +u_int8_t halIsTxResourceControlEn(IN struct ADAPTER *prAdapter); +void halTxResourceResetHwTQCounter(IN struct ADAPTER *prAdapter); +uint32_t halGetHifTxPageSize(IN struct ADAPTER *prAdapter); +void halTxReturnFreeResource(IN struct ADAPTER *prAdapter, + IN uint16_t *au2TxDoneCnt); +void halTxGetFreeResource(IN struct ADAPTER *prAdapter, + IN uint16_t *au2TxDoneCnt, IN uint16_t *au2TxRlsCnt); +void halRestoreTxResource(IN struct ADAPTER *prAdapter); +void halRestoreTxResource_v1(IN struct ADAPTER *prAdapter); +void halUpdateTxDonePendingCount_v1(IN struct ADAPTER *prAdapter, + IN u_int8_t isIncr, IN uint8_t ucTc, IN uint16_t u2Cnt); +void halUpdateTxDonePendingCount(IN struct ADAPTER *prAdapter, + IN u_int8_t isIncr, IN uint8_t ucTc, IN uint32_t u4Len); +void halTxReturnFreeResource_v1(IN struct ADAPTER *prAdapter, + IN uint16_t *au2TxDoneCnt); +bool halIsHifStateReady(IN struct ADAPTER *prAdapter, uint8_t *pucState); +bool halIsHifStateLinkup(IN struct ADAPTER *prAdapter); +bool halIsHifStateSuspend(IN struct ADAPTER *prAdapter); + +#endif /* _HAL_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/hif_rx.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/hif_rx.h new file mode 100644 index 0000000000000..2df38d9cd267c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/hif_rx.h @@ -0,0 +1,156 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 + */ + + +#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 + ******************************************************************************* + */ + +/******************************************************************************* + * P U B 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 __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. + */ +static __KAL_INLINE__ void hifDataTypeCheck(void) +{ +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/hif_tx.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/hif_tx.h new file mode 100644 index 0000000000000..891fceb3fd648 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/hif_tx.h @@ -0,0 +1,171 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/ + * MT6620_WIFI_DRIVER_V2_3/include/nic/hif_tx.h#1 + */ + + +#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 */ +/* Reserved field was not included */ +#define HIF_TX_BUFF_MAX_SIZE 1552 + +/* Maximum buffer count for individual HIF TCQ */ +#if 0 +#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 +#endif + +#define TX_HDR_SIZE sizeof(struct HIF_TX_HEADER) + +#define CMD_HDR_SIZE sizeof(struct WIFI_CMD) + +/* !< 2048 Bytes CMD payload buffer */ +#define CMD_PKT_SIZE_FOR_IMAGE 2048 + +/*! NIC_HIF_TX_HEADER_T (for short-header format) */ +/* DW 0, Byte 0,1 */ +#define HIF_TX_HDR_TX_BYTE_COUNT_MASK BITS(0, 15) + +/* DW 0, Byte 2 */ +#define HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK BITS(0, 6) +#define HIF_TX_HDR_IP_CSUM BIT(7) + +/* DW 0, Byte 3 */ +#define HIF_TX_HDR_TCP_CSUM BIT(0) +#define HIF_TX_HDR_QUEUE_IDX_MASK BITS(3, 6) +#define HIF_TX_HDR_QUEUE_IDX_OFFSET 3 +#define HIF_TX_HDR_PORT_IDX_MASK BIT(7) +#define HIF_TX_HDR_PORT_IDX_OFFSET 7 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +struct HIF_HW_TX_HEADER { + uint16_t u2TxByteCount; + uint8_t ucEtherTypeOffset; + uint8_t ucCSflags; + uint8_t aucBuffer[0]; +}; + +struct HIF_TX_HEADER { + uint16_t u2TxByteCount_UserPriority; + uint8_t ucEtherTypeOffset; + uint8_t ucResource_PktType_CSflags; + uint8_t ucWlanHeaderLength; + uint8_t ucPktFormtId_Flags; + uint16_t u2LLH; /* for BOW */ + uint16_t u2SeqNo; /* for BOW */ + uint8_t ucStaRecIdx; + uint8_t ucForwardingType_SessionID_Reserved; + uint8_t ucPacketSeqNo; + uint8_t ucAck_BIP_BasicRate; + uint8_t aucReserved[2]; +}; + +enum ENUM_HIF_OOB_CTRL_PKT_TYPE { + HIF_OOB_CTRL_PKT_TYPE_LOOPBACK = 1, + HIF_OOB_CTRL_PKT_TYP_NUM +}; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +#define TFCB_FRAME_PAD_TO_DW(u2Length) ALIGN_4(u2Length) + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +/* Kevin: we don't have to call following function to inspect the data + * structure. It will check automatically while at compile time. + */ +static __KAL_INLINE__ void hif_txDataTypeCheck(void); + +static __KAL_INLINE__ void hif_txDataTypeCheck(void) +{ + DATA_STRUCT_INSPECTING_ASSERT(sizeof(struct HIF_TX_HEADER) == 16); +} + +#endif /*_HIF_TX_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/mac.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/mac.h new file mode 100644 index 0000000000000..e9f4ca55bc964 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/mac.h @@ -0,0 +1,3380 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "mac.h" + * \brief Brief description. + * + * Detail description. + */ + + +#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 + ******************************************************************************* + */ +#if CFG_SUPPORT_CFG80211_AUTH +#define AUTH_DATA_MAX_LEN 1024 /* temp defined */ +#endif + +/* 3 --------------- Constants for Ethernet/802.11 MAC --------------- */ +/* MAC Address */ +#define MAC_ADDR_LEN 6 +#define MAC_OUI_LEN (3) + +#define MAC_ADDR_LOCAL_ADMIN BIT(1) + +#define ETH_P_IPV4 0x0800 +#define ETH_P_ARP 0x0806 +#define ETH_P_IPX 0x8137 /* Novell IPX */ +/* AppleTalk Address Resolution Protocol (AARP) */ +#define ETH_P_AARP 0x80F3 +#define ETH_P_IPV6 0x86DD +#define ETH_P_VLAN 0x8100 + +#define IP_PRO_ICMP 0x01 +#define IP_PRO_UDP 0x11 +#define IP_PRO_TCP 0x06 + +#define UDP_PORT_DHCPS 0x43 +#define UDP_PORT_DHCPC 0x44 +#define UDP_PORT_DNS 0x35 + +#define ETH_P_1X 0x888E +#define ETH_P_PRE_1X 0x88C7 +#if CFG_SUPPORT_WAPI +#define ETH_WPI_1X 0x88B4 +#endif +#define ETH_EAPOL_KEY 3 + +#define ETH_PRO_TDLS 0x890d + +/* 802.3 Frame If Ether Type/Len <= 1500 */ +#define ETH_802_3_MAX_LEN 1500 + +/* IP Header definition */ +#define IP_VERSION_MASK BITS(4, 7) +#define IP_VERSION_OFFSET 4 +#define IP_VERSION_4 4 +#define IP_VERSION_6 6 + +#define IP_PRO_ICMP 0x01 +#define IP_PRO_UDP 0x11 +#define IP_PRO_TCP 0x06 + +#define UDP_PORT_DHCPS 0x43 +#define UDP_PORT_DHCPC 0x44 +#define UDP_PORT_DNS 0x35 + +/* IPv4 Header definition */ +#define IPV4_HDR_TOS_OFFSET 1 +#define IPV4_HDR_TOS_PREC_MASK BITS(5, 7) +#define IPV4_HDR_TOS_PREC_OFFSET 5 +#define IPV4_HDR_IP_IDENTIFICATION_OFFSET 4 +#define IPV4_HDR_IP_PROTOCOL_OFFSET 9 +#define IPV4_HDR_IP_CSUM_OFFSET 10 +#define IPV4_HDR_IP_SRC_ADDR_OFFSET 12 +#define IPV4_HDR_IP_DST_ADDR_OFFSET 16 + +#define IPV4_HDR_LEN 20 +#define IPV4_ADDR_LEN 4 + +#define IPV6_HDR_IP_PROTOCOL_OFFSET 6 +#define IPV6_HDR_IP_SRC_ADDR_OFFSET 8 +#define IPV6_HDR_IP_DST_ADDR_OFFSET 24 +#define IPV6_HDR_IP_DST_ADDR_MAC_HIGH_OFFSET 32 +#define IPV6_HDR_IP_DST_ADDR_MAC_LOW_OFFSET 37 +#define IPV6_PROTOCOL_ICMPV6 0x3A + +#define IPV6_HDR_TC_PREC_OFFSET 1 +#define IPV6_HDR_TC_PREC_MASK BITS(1, 3) +#define IPV6_HDR_PROTOCOL_OFFSET 6 +#define IPV6_HDR_LEN 40 + +#define IPV6_ADDR_LEN 16 + +#define ICMPV6_TYPE_OFFSET 0 +#define ICMPV6_FLAG_OFFSET 4 +#define ICMPV6_TARGET_ADDR_OFFSET 8 +#define ICMPV6_TARGET_LL_ADDR_TYPE_OFFSET 24 +#define ICMPV6_TARGET_LL_ADDR_LEN_OFFSET 25 +#define ICMPV6_TARGET_LL_ADDR_TA_OFFSET 26 + +#define ICMPV6_FLAG_ROUTER_BIT BIT(7) +#define ICMPV6_FLAG_SOLICITED_BIT BIT(6) +#define ICMPV6_FLAG_OVERWRITE_BIT BIT(5) +#define ICMPV6_TYPE_NEIGHBOR_SOLICITATION 0x87 +#define ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT 0x88 + +#define TCP_HDR_TCP_CSUM_OFFSET 16 + +#define UDP_HDR_LEN 8 + +#define UDP_HDR_SRC_PORT_OFFSET 0 +#define UDP_HDR_DST_PORT_OFFSET 2 +#define UDP_HDR_UDP_CSUM_OFFSET 6 + +#define IP_PORT_BOOTP_SERVER 67 +#define IP_PORT_BOOTP_CLIENT 68 + +#define IP_PORT_MDNS 5353 + +#define DHCP_MAGIC_NUMBER 0x63825363 + +#define ARP_OPERATION_OFFSET 6 +#define ARP_SNEDER_MAC_OFFSET 8 +#define ARP_SENDER_IP_OFFSET 14 +#define ARP_TARGET_MAC_OFFSET 18 +#define ARP_TARGET_IP_OFFSET 24 +#define ARP_OPERATION_REQUEST 0x0001 +#define ARP_OPERATION_RESPONSE 0x0002 + +#define ARP_PRO_REQ 1 +#define ARP_PRO_RSP 2 + +#define TDLS_ACTION_CODE_OFFSET 2 + +/* LLC(3) + SNAP(3) + EtherType(2) */ +#define LLC_LEN 8 + +#define NULL_MAC_ADDR {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} +#define BC_MAC_ADDR {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} + +#if 1 + +#define ETH_HLEN 14 +#define ETH_TYPE_LEN_OFFSET 12 + +#define IPVERSION 4 +#define IP_HEADER_LEN 20 +#define IP_PROTO_HLEN 9 + +#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 + +#define LOOK_AHEAD_LEN \ + (ETH_HLEN + IP_HEADER_LEN + SOURCE_PORT_LEN) + +#endif + +/* 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 + +#define ETHER_TYPE_LEN_OFFSET 12 + +/* 802.1Q (VLAN) */ +#define ETH_802_1Q_HEADER_LEN 4 + +/* 802.2 LLC/SNAP */ +#define ETH_LLC_OFFSET (ETHER_HEADER_LEN) +#define ETH_LLC_LEN 3 +#define ETH_LLC_DSAP_SNAP 0xAA +#define ETH_LLC_SSAP_SNAP 0xAA +#define ETH_LLC_CONTROL_UNNUMBERED_INFORMATION 0x03 +#define ETH_LLC \ + {ETH_LLC_DSAP_SNAP, ETH_LLC_SSAP_SNAP, \ + ETH_LLC_CONTROL_UNNUMBERED_INFORMATION} + +/* Bluetooth SNAP */ +#define ETH_SNAP_OFFSET (ETHER_HEADER_LEN + ETH_LLC_LEN) +#define ETH_SNAP_LEN 5 +#define ETH_SNAP_OUI_LEN 3 +#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 ETH_SNAP_BT_SIG_OUI \ + {ETH_SNAP_BT_SIG_OUI_0, ETH_SNAP_BT_SIG_OUI_1, ETH_SNAP_BT_SIG_OUI_2} + +#define BOW_PROTOCOL_ID_SECURITY_FRAME 0x0003 + +/* IEEE 802.11 WLAN Frame Field Size, in byte */ +/* Address 4 excluded */ +#define WLAN_MAC_HEADER_LEN 24 +/* Address 4 included */ +#define WLAN_MAC_HEADER_A4_LEN 30 +/* QoS Control included */ +#define WLAN_MAC_HEADER_QOS_LEN 26 +/* QoS Control and HTC included */ +#define WLAN_MAC_HEADER_QOS_HTC_LEN 30 +/* Address 4 and QoS Control included */ +#define WLAN_MAC_HEADER_A4_QOS_LEN 32 +/* Address 4, QoS Control and HTC included */ +#define WLAN_MAC_HEADER_A4_QOS_HTC_LEN 36 +/* Address 4 excluded */ +#define WLAN_MAC_MGMT_HEADER_LEN 24 +/* HTC included */ +#define WLAN_MAC_MGMT_HEADER_HTC_LEN 28 + +#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 */ +/* In unit of AP's DTIM interval, */ +#define DEFAULT_LISTEN_INTERVAL_BY_DTIM_PERIOD 2 +#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 */ + +/* BSS Selector - Clause 22. HT PHY */ +#define RATE_VHT_PHY 126 +/* BSS Selector - Clause 20. HT PHY */ +#define RATE_HT_PHY 127 +/* mask bits for the rate */ +#define RATE_MASK BITS(0, 6) +/* mask bit for the rate belonging to the BSSBasicRateSet */ +#define RATE_BASIC_BIT BIT(7) + +/* 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 */ +/* Accept Class 1 frames */ +#define STA_STATE_1 0 +/* Accept Class 1 & 2 frames */ +#define STA_STATE_2 1 +/* Accept Class 1,2 & 3 frames */ +#define STA_STATE_3 2 + +/* 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) */ +/* Long Slot Time */ +#define SLOT_TIME_LONG 20 +/* Short Slot Time */ +#define SLOT_TIME_SHORT 9 + +/* 802.11b aSlotTime */ +#define SLOT_TIME_HR_DSSS SLOT_TIME_LONG +/* 802.11a aSlotTime(20M Spacing) */ +#define SLOT_TIME_OFDM SLOT_TIME_SHORT +/* 802.11a aSlotTime(10M Spacing) */ +#define SLOT_TIME_OFDM_10M_SPACING 13 +/* 802.11g aSlotTime(Long) */ +#define SLOT_TIME_ERP_LONG SLOT_TIME_LONG +/* 802.11g aSlotTime(Short) */ +#define SLOT_TIME_ERP_SHORT SLOT_TIME_SHORT + +/* 17.4.4/18.3.3/19.8.4 Contention Window (aCWmin & aCWmax) */ +/* 802.11a aCWmin */ +#define CWMIN_OFDM 15 +/* 802.11a aCWmax */ +#define CWMAX_OFDM 1023 + +/* 802.11b aCWmin */ +#define CWMIN_HR_DSSS 31 +/* 802.11b aCWmax */ +#define CWMAX_HR_DSSS 1023 + +/* 802.11g aCWmin(0) - for only have 1/2/5/11Mbps Rates */ +#define CWMIN_ERP_0 31 +/* 802.11g aCWmin(1) */ +#define CWMIN_ERP_1 15 +/* 802.11g aCWmax */ +#define CWMAX_ERP 1023 + +/* 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 + +/* 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 + +/* 802.11 define 512 */ +/* MT5921 only aceept N <= 4095 */ +#define DOT11_TRANSMIT_MSDU_LIFETIME_TU_DEFAULT 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) + +/* According to 6.2.1.1.2 + * FRAG_NUM won't equal to 15 + */ +#define INVALID_SEQ_CTRL_NUM 0x000F + +/* 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 + +#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 */ +#if CFG_SUPPORT_CFG80211_AUTH +#define AUTH_ALGORITHM_NUM_SAE 3 /* SAE */ +#endif + +/* 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_RADIO_MEASUREMENT 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 + +/* Reseved */ +#define REASON_CODE_RESERVED 0 +/* Unspecified reason */ +#define REASON_CODE_UNSPECIFIED 1 +/* Previous auth no longer valid */ +#define REASON_CODE_PREV_AUTH_INVALID 2 +/* Deauth because sending STA is leaving BSS */ +#define REASON_CODE_DEAUTH_LEAVING_BSS 3 +/* Disassoc due to inactivity */ +#define REASON_CODE_DISASSOC_INACTIVITY 4 +/* Disassoc because AP is unable to handle all assoc STAs */ +#define REASON_CODE_DISASSOC_AP_OVERLOAD 5 +/* Class 2 frame rx from nonauth STA */ +#define REASON_CODE_CLASS_2_ERR 6 +/* Class 3 frame rx from nonassoc STA */ +#define REASON_CODE_CLASS_3_ERR 7 +/* Disassoc because sending STA is leaving BSS */ +#define REASON_CODE_DISASSOC_LEAVING_BSS 8 +/* STA requesting (re)assoc is not auth with responding STA */ +#define REASON_CODE_ASSOC_BEFORE_AUTH 9 +/* Disassoc because the info in Power Capability is unacceptable */ +#define REASON_CODE_DISASSOC_PWR_CAP_UNACCEPTABLE 10 +/* Disassoc because the info in Supported Channels is unacceptable */ +#define REASON_CODE_DISASSOC_SUP_CHS_UNACCEPTABLE 11 +/* Invalid information element */ +#define REASON_CODE_INVALID_INFO_ELEM 13 +/* MIC failure */ +#define REASON_CODE_MIC_FAILURE 14 +/* 4-way handshake timeout */ +#define REASON_CODE_4_WAY_HANDSHAKE_TIMEOUT 15 +/* Group key update timeout */ +#define REASON_CODE_GROUP_KEY_UPDATE_TIMEOUT 16 +/* Info element in 4-way handshake different from */ +/* (Re-)associate request/Probe response/Beacon */ +#define REASON_CODE_DIFFERENT_INFO_ELEM 17 +/* Multicast Cipher is not valid */ +#define REASON_CODE_MULTICAST_CIPHER_NOT_VALID 18 +/* Unicast Cipher is not valid */ +#define REASON_CODE_UNICAST_CIPHER_NOT_VALID 19 +/* AKMP is not valid */ +#define REASON_CODE_AKMP_NOT_VALID 20 +/* Unsupported RSNE version */ +#define REASON_CODE_UNSUPPORTED_RSNE_VERSION 21 +/* Invalid RSNE Capabilities */ +#define REASON_CODE_INVALID_RSNE_CAPABILITIES 22 +/* IEEE 802.1X Authentication failed */ +#define REASON_CODE_IEEE_802_1X_AUTH_FAILED 23 +/* Cipher suite rejected because of the security policy */ +#define REASON_CODE_CIPHER_REJECT_SEC_POLICY 24 +/* Disassoc for unspecified, QoS-related reason */ +#define REASON_CODE_DISASSOC_UNSPECIFIED_QOS 32 +/* Disassoc because QAP lacks sufficient bandwidth for this QSTA */ +#define REASON_CODE_DISASSOC_LACK_OF_BANDWIDTH 33 +/* Disassoc because of too many ACKs lost for AP transmissions */ +/* and/or poor channel conditions */ +#define REASON_CODE_DISASSOC_ACK_LOST_POOR_CHANNEL 34 +/* Disassoc because QSTA is transmitting outside the limits of its TXOPs */ +#define REASON_CODE_DISASSOC_TX_OUTSIDE_TXOP_LIMIT 35 +/* QSTA is leaving the QBSS or resetting */ +#define REASON_CODE_PEER_WHILE_LEAVING 36 +/* Peer does not want to use this mechanism */ +#define REASON_CODE_PEER_REFUSE_DLP 37 +/* Frames received but a setup is reqired */ +#define REASON_CODE_PEER_SETUP_REQUIRED 38 +/* Time out */ +#define REASON_CODE_PEER_TIME_OUT 39 +/* Peer does not support the requested cipher suite */ +#define REASON_CODE_PEER_CIPHER_UNSUPPORTED 45 +/* for beacon timeout, defined by mediatek */ +#define REASON_CODE_BEACON_TIMEOUT 100 +/* 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 +/* Reserved - Used by TX Auth */ +#define STATUS_CODE_RESERVED 0 +/* Successful */ +#define STATUS_CODE_SUCCESSFUL 0 +/* Unspecified failure */ +#define STATUS_CODE_UNSPECIFIED_FAILURE 1 +/* Cannot support all requested cap in the Cap Info field */ +#define STATUS_CODE_CAP_NOT_SUPPORTED 10 +/* Reassoc denied due to inability to confirm that assoc exists */ +#define STATUS_CODE_REASSOC_DENIED_WITHOUT_ASSOC 11 +/* Assoc denied due to reason outside the scope of this std. */ +#define STATUS_CODE_ASSOC_DENIED_OUTSIDE_STANDARD 12 +/* Responding STA does not support the specified auth algorithm */ +#define STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED 13 +/* Rx an auth frame with auth transaction seq num out of expected seq */ +#define STATUS_CODE_AUTH_OUT_OF_SEQ 14 +/* Auth rejected because of challenge failure */ +#define STATUS_CODE_AUTH_REJECTED_CHAL_FAIL 15 +/* Auth rejected due to timeout waiting for next frame in sequence */ +#define STATUS_CODE_AUTH_REJECTED_TIMEOUT 16 +/* Assoc denied because AP is unable to handle additional assoc STAs */ +#define STATUS_CODE_ASSOC_DENIED_AP_OVERLOAD 17 +/* Assoc denied due to requesting STA not supporting all of basic rates */ +#define STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED 18 +/* Assoc denied due to requesting STA not supporting short preamble */ +#define STATUS_CODE_ASSOC_DENIED_NO_SHORT_PREAMBLE 19 +/* Assoc denied due to requesting STA not supporting PBCC */ +#define STATUS_CODE_ASSOC_DENIED_NO_PBCC 20 +/* Assoc denied due to requesting STA not supporting channel agility */ +#define STATUS_CODE_ASSOC_DENIED_NO_CH_AGILITY 21 +/* Assoc rejected because Spectrum Mgt capability is required */ +#define STATUS_CODE_ASSOC_REJECTED_NO_SPEC_MGT 22 +/* Assoc rejected because the info in Power Capability is unacceptable */ +#define STATUS_CODE_ASSOC_REJECTED_PWR_CAP 23 +/* Assoc rejected because the info in Supported Channels is unacceptable */ +#define STATUS_CODE_ASSOC_REJECTED_SUP_CHS 24 +/* Assoc denied due to requesting STA not supporting short slot time */ +#define STATUS_CODE_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25 +/* Assoc denied due to requesting STA not supporting DSSS-OFDM */ +#define STATUS_CODE_ASSOC_DENIED_NO_DSSS_OFDM 26 +#if CFG_SUPPORT_802_11W +/* IEEE 802.11w, Assoc denied due to the SA query */ +#define STATUS_CODE_ASSOC_REJECTED_TEMPORARILY 30 +/* IEEE 802.11w, Assoc denied due to the MFP select policy */ +#define STATUS_CODE_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31 +#endif +/* Unspecified, QoS-related failure */ +#define STATUS_CODE_UNSPECIFIED_QOS_FAILURE 32 +/* Assoc denied due to insufficient bandwidth to handle another QSTA */ +#define STATUS_CODE_ASSOC_DENIED_BANDWIDTH 33 +/* Assoc denied due to excessive frame loss + * rates and/or poor channel conditions + */ +#define STATUS_CODE_ASSOC_DENIED_POOR_CHANNEL 34 +/* Assoc denied due to requesting STA not supporting QoS facility */ +#define STATUS_CODE_ASSOC_DENIED_NO_QOS_FACILITY 35 +/* Request has been declined */ +#define STATUS_CODE_REQ_DECLINED 37 +/* Request has not been successful as one + * or more parameters have invalid values + */ +#define STATUS_CODE_REQ_INVALID_PARAMETER_VALUE 38 +/* TS not created because request cannot be honored. */ +/* Suggested TSPEC provided. */ +#define STATUS_CODE_REQ_NOT_HONORED_TSPEC 39 +/* Invalid information element */ +#define STATUS_CODE_INVALID_INFO_ELEMENT 40 +/* Invalid group cipher */ +#define STATUS_CODE_INVALID_GROUP_CIPHER 41 +/* Invalid pairwise cipher */ +#define STATUS_CODE_INVALID_PAIRWISE_CIPHER 42 +/* Invalid AKMP */ +#define STATUS_CODE_INVALID_AKMP 43 +/* Unsupported RSN information element version */ +#define STATUS_CODE_UNSUPPORTED_RSN_IE_VERSION 44 +/* Invalid RSN information element capabilities */ +#define STATUS_CODE_INVALID_RSN_IE_CAP 45 +/* Cipher suite rejected because of security policy */ +#define STATUS_CODE_CIPHER_SUITE_REJECTED 46 +/* TS not created because request cannot be honored. */ +/* Attempt to create a TS later. */ +#define STATUS_CODE_REQ_NOT_HONORED_TS_DELAY 47 +/* Direct Link is not allowed in the BSS by policy */ +#define STATUS_CODE_DIRECT_LINK_NOT_ALLOWED 48 +/* Destination STA is not present within this QBSS */ +#define STATUS_CODE_DESTINATION_STA_NOT_PRESENT 49 +/* Destination STA is not a QSTA */ +#define STATUS_CODE_DESTINATION_STA_NOT_QSTA 50 +/* Association denied because the ListenInterval is too large */ +#define STATUS_CODE_ASSOC_DENIED_LARGE_LIS_INTERVAL 51 + +/* proprietary definition of reserved field of Status Code */ +/* Join failure */ +#define STATUS_CODE_JOIN_FAILURE 0xFFF0 +/* Join timeout */ +#define STATUS_CODE_JOIN_TIMEOUT 0xFFF1 +/* Authentication timeout */ +#define STATUS_CODE_AUTH_TIMEOUT 0xFFF2 +/* (Re)Association timeout */ +#define STATUS_CODE_ASSOC_TIMEOUT 0xFFF3 +/* CCX CCKM reassociation failure */ +#define STATUS_CODE_CCX_CCKM_REASSOC_FAILURE 0xFFF4 + +/* 7.3.1.10 Timestamp field */ +#define TIMESTAMP_FIELD_LEN 8 + +/* 7.3.1.11 Category of Action field */ +#define CATEGORY_SPEC_MGT 0 +/* QoS action */ +#define CATEGORY_QOS_ACTION 1 +/* Direct Link Protocol (DLP) action */ +#define CATEGORY_DLS_ACTION 2 +/* Block ack action */ +#define CATEGORY_BLOCK_ACK_ACTION 3 +/* Public action */ +#define CATEGORY_PUBLIC_ACTION 4 +/* Radio measurement action */ +#define CATEGORY_RM_ACTION 5 +#define CATEGORY_HT_ACTION 7 +#if CFG_SUPPORT_802_11W +#define CATEGORY_SA_QUERY_ACTION 8 +#define CATEGORY_PROTECTED_DUAL_OF_PUBLIC_ACTION 9 +#endif +/* 802.11v Wireless Network Management */ +#define CATEGORY_WNM_ACTION 10 +/* 802.11v Wireless Network Management */ +#define CATEGORY_UNPROTECTED_WNM_ACTION 11 +/* WME management notification */ +#define CATEGORY_WME_MGT_NOTIFICATION 17 + +/* VHT action */ +#define CATEGORY_VHT_ACTION 21 + +#if CFG_SUPPORT_802_11W +#define CATEGORY_VENDOR_SPECIFIC_ACTION_PROTECTED 126 +#endif +#define CATEGORY_VENDOR_SPECIFIC_ACTION 127 + +/* 7.3.1.14 Block Ack Parameter Set field */ +#define BA_PARAM_SET_ACK_POLICY_MASK BIT(1) +#define BA_PARAM_SET_ACK_POLICY_MASK_OFFSET 1 +#define BA_PARAM_SET_TID_MASK BITS(2, 5) +#define BA_PARAM_SET_TID_MASK_OFFSET 2 +#define BA_PARAM_SET_BUFFER_SIZE_MASK BITS(6, 15) +#define BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET 6 + +#define BA_PARAM_SET_ACK_POLICY_IMMEDIATE_BA 1 +#define BA_PARAM_SET_ACK_POLICY_DELAYED_BA 0 + +/* 3 Management frame body components (II): Information Elements. */ +/* 7.3.2 Element IDs of information elements */ +#define ELEM_HDR_LEN 2 + +#define ELEM_ID_SSID \ + 0 /* SSID */ +#define ELEM_ID_SUP_RATES \ + 1 /* Supported rates */ +#define ELEM_ID_FH_PARAM_SET \ + 2 /* FH parameter set */ +#define ELEM_ID_DS_PARAM_SET \ + 3 /* DS parameter set */ +#define ELEM_ID_CF_PARAM_SET \ + 4 /* CF parameter set */ +#define ELEM_ID_TIM \ + 5 /* TIM */ +#define ELEM_ID_IBSS_PARAM_SET \ + 6 /* IBSS parameter set */ +#define ELEM_ID_COUNTRY_INFO \ + 7 /* Country information */ +#define ELEM_ID_HOPPING_PATTERN_PARAM \ + 8 /* Hopping pattern parameters */ +#define ELEM_ID_HOPPING_PATTERN_TABLE \ + 9 /* Hopping pattern table */ +#define ELEM_ID_REQUEST \ + 10 /* Request */ +#define ELEM_ID_BSS_LOAD \ + 11 /* BSS load */ +#define ELEM_ID_EDCA_PARAM_SET \ + 12 /* EDCA parameter set */ +#define ELEM_ID_TSPEC \ + 13 /* Traffic specification (TSPEC) */ +#define ELEM_ID_TCLAS \ + 14 /* Traffic classification (TCLAS) */ +#define ELEM_ID_SCHEDULE \ + 15 /* Schedule */ +#define ELEM_ID_CHALLENGE_TEXT \ + 16 /* Challenge text */ + +#define ELEM_ID_PWR_CONSTRAINT \ + 32 /* Power constraint */ +#define ELEM_ID_PWR_CAP \ + 33 /* Power capability */ +#define ELEM_ID_TPC_REQ \ + 34 /* TPC request */ +#define ELEM_ID_TPC_REPORT \ + 35 /* TPC report */ +#define ELEM_ID_SUP_CHS \ + 36 /* Supported channels */ +#define ELEM_ID_CH_SW_ANNOUNCEMENT \ + 37 /* Channel switch announcement */ +#define ELEM_ID_MEASUREMENT_REQ \ + 38 /* Measurement request */ +#define ELEM_ID_MEASUREMENT_REPORT \ + 39 /* Measurement report */ +#define ELEM_ID_QUIET \ + 40 /* Quiet */ +#define ELEM_ID_IBSS_DFS \ + 41 /* IBSS DFS */ +#define ELEM_ID_ERP_INFO \ + 42 /* ERP information */ +#define ELEM_ID_TS_DELAY \ + 43 /* TS delay */ +#define ELEM_ID_TCLAS_PROCESSING \ + 44 /* TCLAS processing */ +#define ELEM_ID_HT_CAP \ + 45 /* HT Capabilities subelement */ +#define ELEM_ID_QOS_CAP \ + 46 /* QoS capability */ +#define ELEM_ID_RSN \ + 48 /* RSN IE */ +#define ELEM_ID_EXTENDED_SUP_RATES \ + 50 /* Extended supported rates */ +#define ELEM_ID_AP_CHANNEL_REPORT \ + 51 /* AP Channel Report Element */ +#define ELEM_ID_NEIGHBOR_REPORT \ + 52 /* Neighbor Report */ +#define ELEM_ID_MOBILITY_DOMAIN \ + 54 /* Mobility Domain for 802.11R */ +#define ELEM_ID_FAST_TRANSITION \ + 55 /* Fast Bss Transition for 802.11 R */ +#if CFG_SUPPORT_802_11W +#define ELEM_ID_TIMEOUT_INTERVAL \ + 56 /* 802.11w SA Timeout interval */ +#endif +#define ELEM_ID_RESOURCE_INFO_CONTAINER \ + 57 /* Resource Information Container for 802.11 R */ +#define ELEM_ID_SUP_OPERATING_CLASS \ + 59 /* Supported Operating Classes */ + +#define ELEM_ID_HT_OP \ + 61 /* HT Operation */ +#define ELEM_ID_SCO \ + 62 /* Secondary Channel Offset */ +#define ELEM_ID_RRM_ENABLED_CAP \ + 70 /* Radio Resource Management Enabled Capabilities */ +#define ELEM_ID_20_40_BSS_COEXISTENCE \ + 72 /* 20/40 BSS Coexistence */ +#define ELEM_ID_20_40_INTOLERANT_CHNL_REPORT \ + 73 /* 20/40 BSS Intolerant Channel Report */ +#define ELEM_ID_OBSS_SCAN_PARAMS \ + 74 /* Overlapping BSS Scan Parameters */ +#define ELEM_ID_EXTENDED_CAP \ + 127 /* Extended capabilities */ + +#define ELEM_ID_INTERWORKING \ + 107 /* Interworking with External Network */ +#define ELEM_ID_ADVERTISEMENT_PROTOCOL \ + 108 /* Advertisement Protocol */ +#define ELEM_ID_QOS_MAP_SET \ + 110 /* QoS Map Set */ +#define ELEM_ID_ROAMING_CONSORTIUM \ + 111 /* Roaming Consortium */ +#define ELEM_ID_EXTENDED_CAP \ + 127 /* Extended capabilities */ + +#define ELEM_ID_VENDOR \ + 221 /* Vendor specific IE */ +#define ELEM_ID_WPA \ + ELEM_ID_VENDOR /* WPA IE */ +#define ELEM_ID_WMM \ + ELEM_ID_VENDOR /* WMM IE */ +#define ELEM_ID_P2P \ + ELEM_ID_VENDOR /* WiFi Direct */ +#define ELEM_ID_WSC \ + ELEM_ID_VENDOR /* WSC IE */ + +#define ELEM_ID_VHT_CAP \ + 191 /* VHT Capabilities subelement */ +#define ELEM_ID_VHT_OP \ + 192 /* VHT Operation information */ +#define ELEM_ID_WIDE_BAND_CHANNEL_SWITCH \ + 194 /*Wide Bandwidth Channel Switch */ +#define ELEM_ID_OP_MODE \ + 199 /* Operation Mode Notification */ +#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 */ +/* NonERP_Present bit */ +#define ERP_INFO_NON_ERP_PRESENT BIT(0) +/* Use_Protection bit */ +#define ERP_INFO_USE_PROTECTION BIT(1) +/* Barker_Preamble_Mode bit */ +#define ERP_INFO_BARKER_PREAMBLE_MODE BIT(2) + +#define ELEM_MAX_LEN_SUPPORTED_CHANNELS (MAX_CHN_NUM * 2) + +/* 7.3.2.14 Extended Supported Rates */ +#define ELEM_MAX_LEN_EXTENDED_SUP_RATES 255 + +/* 7.3.2.16 Power Capability element */ +#define ELEM_MAX_LEN_POWER_CAP 2 + + +/* 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_TSM_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_TSM_REPORT 9 + +/* 7.3.2.37 Subelement IDs for Neighbor Report, Table 7-43b */ +#define ELEM_ID_NR_BSS_TRANSITION_CAND_PREF 3 +#define ELEM_ID_NR_BSS_TERMINATION_DURATION 4 + +/* 7.3.2.25 RSN information element */ +/* one pairwise, one AKM suite, one PMKID */ +#define ELEM_MAX_LEN_WPA 34 +/* one pairwise, one AKM suite, one PMKID */ +#define ELEM_MAX_LEN_RSN 38 +/* one pairwise, one AKM suite, one BKID */ +#define ELEM_MAX_LEN_WAPI 38 +/* one pairwise, one AKM suite, one BKID */ +#define ELEM_MAX_LEN_WSC 200 + +/* 802.11i */ +/* length of one PMKID */ +#define RSN_PMKID_LEN 16 + +#if CFG_SUPPORT_802_11W +#define ELEM_WPA_CAP_MFPR BIT(6) +#define ELEM_WPA_CAP_MFPC BIT(7) +#endif + +/* 7.3.2.27 Extended Capabilities information element */ +#define ELEM_EXT_CAP_20_40_COEXIST_SUPPORT BIT(0) +#define ELEM_EXT_CAP_PSMP_CAP BIT(4) +#define ELEM_EXT_CAP_SERVICE_INTERVAL_GRANULARITY BIT(5) +#define ELEM_EXT_CAP_SCHEDULE_PSMP BIT(6) + +#define ELEM_EXT_CAP_BSS_TRANSITION_BIT 19 +#define ELEM_EXT_CAP_UTC_TSF_OFFSET_BIT 27 +#define ELEM_EXT_CAP_INTERWORKING_BIT 31 +#define ELEM_EXT_CAP_QOSMAPSET_BIT 32 +#define ELEM_EXT_CAP_WNM_NOTIFICATION_BIT 46 +#define ELEM_EXT_CAP_WNM_NOTIFICATION_BIT 46 +#define ELEM_EXT_CAP_OP_MODE_NOTIFICATION_BIT 62 + +#define ELEM_MAX_LEN_EXT_CAP (8) + +/* 7.3.2.30 TSPEC element */ +/* WMM: 0 (Asynchronous TS of low-duty cycles) */ +#define TS_INFO_TRAFFIC_TYPE_MASK BIT(0) +#define TS_INFO_TID_OFFSET 1 +#define TS_INFO_TID_MASK BITS(1, 4) +#define TS_INFO_DIRECTION_OFFSET 5 +#define TS_INFO_DIRECTION_MASK BITS(5, 6) +#define TS_INFO_ACCESS_POLICY_OFFSET 7 +#define TS_INFO_ACCESS_POLICY_MASK BITS(7, 8) +#define TS_INFO_AGGREGATION_MASK BIT(9) /* WMM: 0 */ +#define TS_INFO_APSD_MASK BIT(10) +#define TS_INFO_UP_OFFSET 11 +#define TS_INFO_UP_MASK BITS(11, 13) +#define TS_INFO_ACK_POLICY_OFFSET 14 +#define TS_INFO_ACK_POLICY_MASK BITS(14, 15) +#define TS_INFO_SCHEDULE_MASK 16 + +/* 7.3.2.45 RRM Enabled Capbility element */ +#define ELEM_MAX_LEN_RRM_CAP 5 +#define RRM_CAP_INFO_LINK_MEASURE_BIT 0 +#define RRM_CAP_INFO_NEIGHBOR_REPORT_BIT 1 +#define RRM_CAP_INFO_REPEATED_MEASUREMENT 3 +#define RRM_CAP_INFO_BEACON_PASSIVE_MEASURE_BIT 4 +#define RRM_CAP_INFO_BEACON_ACTIVE_MEASURE_BIT 5 +#define RRM_CAP_INFO_BEACON_TABLE_BIT 6 +#define RRM_CAP_INFO_TSM_BIT 14 +#define RRM_CAP_INFO_RRM_BIT 17 + +/* 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_SM_POWER_SAVE_OFFSET 2 +#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 + +#define ELEM_MAX_LEN_VHT_CAP \ + (14 - ELEM_HDR_LEN) /* sizeof(IE_VHT_CAP_T)-2 */ +/* 8.4.2.161 VHT Operation element */ +#define ELEM_MAX_LEN_VHT_OP \ + (7 - ELEM_HDR_LEN) /* sizeof(IE_VHT_OP_T)-2 */ + +#define ELEM_MAX_LEN_VHT_OP_MODE_NOTIFICATION \ + (3 - ELEM_HDR_LEN) /* sizeof(IE_VHT_OP_MODE_T)-2 */ + +/*8.4.2.160.3 VHT Supported MCS Set field*/ + +/*8.4.2.160.2 VHT Capabilities Info field*/ +#define VHT_CAP_INFO_MAX_MPDU_LEN_3K 0 +#define VHT_CAP_INFO_MAX_MPDU_LEN_8K BIT(0) +#define VHT_CAP_INFO_MAX_MPDU_LEN_11K BIT(1) +#define VHT_CAP_INFO_MAX_MPDU_LEN_MASK BITS(0, 1) + +#define VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_SET_NONE 0 +#define VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_SET_160 BIT(2) +#define VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_SET_160_80P80 BIT(3) +#define VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_MASK BITS(2, 3) + +#define VHT_CAP_INFO_RX_LDPC BIT(4) +#define VHT_CAP_INFO_SHORT_GI_80 BIT(5) +#define VHT_CAP_INFO_SHORT_GI_160_80P80 BIT(6) +#define VHT_CAP_INFO_TX_STBC BIT(7) + +#define VHT_CAP_INFO_RX_STBC_NONE 0 +#define VHT_CAP_INFO_RX_STBC_MASK BITS(8, 10) +#define VHT_CAP_INFO_RX_STBC_OFFSET 8 +#define VHT_CAP_INFO_RX_STBC_ONE_STREAM BIT(8) +#define VHT_CAP_INFO_RX_STBC_TWO_STREAM BIT(9) +#define VHT_CAP_INFO_RX_STBC_THREE_STREAM BITS(8, 9) +#define VHT_CAP_INFO_RX_STBC_FOUR_STREAM BIT(10) + +#define VHT_CAP_INFO_SU_BEAMFORMER_CAPABLE BIT(11) +#define VHT_CAP_INFO_SU_BEAMFORMEE_CAPABLE BIT(12) +#define VHT_CAP_INFO_SU_BEAMFORMEE_CAPABLE_OFFSET 12 + +/* VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF + * _BEAMFORMER_ANTENNAS_SUPPOERTED + */ +#define VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF_BEAMFORMER_ANTENNAS_SUP_OFF \ + 13 +#define VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF_BEAMFORMER_ANTENNAS_SUP \ + BITS(13, 15) +#define VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF_BEAMFORMER_ANTENNAS_2_SUP \ + BIT(13) +#define VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF_BEAMFORMER_ANTENNAS_3_SUP \ + BIT(14) +#define VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF_BEAMFORMER_ANTENNAS_4_SUP \ + BITS(13, 14) + +#define VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS_OFFSET 16 +#define VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS BITS(16, 18) +#define VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS_2_SUPPORTED BIT(16) +#define VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS_3_SUPPORTED BIT(17) +#define VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS_4_SUPPORTED BITS(16, 17) + +#define VHT_CAP_INFO_MU_BEAMFOMER_CAPABLE BIT(19) +#define VHT_CAP_INFO_MU_BEAMFOMEE_CAPABLE BIT(20) +#define VHT_CAP_INFO_VHT_TXOP_PS BIT(21) +#define VHT_CAP_INFO_HTC_VHT_CAPABLE BIT(22) + +#define VHT_CAP_INFO_MAX_AMPDU_LENGTH_OFFSET 23 + +#define VHT_CAP_INFO_VHT_LINK_ADAPTATION_CAPABLE_NOFEEDBACK 0 +#define VHT_CAP_INFO_VHT_LINK_ADAPTATION_CAPABLE_UNSOLICITED BITS(27) +#define VHT_CAP_INFO_VHT_LINK_ADAPTATION_CAPABLE_BOTH BITS(26, 27) + +#define VHT_CAP_INFO_RX_ANTENNA_PATTERN_CONSISTENCY BIT(28) +#define VHT_CAP_INFO_TX_ANTENNA_PATTERN_CONSISTENCY BIT(29) + +#define VHT_CAP_INFO_MCS_MAP_MCS7 0 +#define VHT_CAP_INFO_MCS_MAP_MCS8 BIT(0) +#define VHT_CAP_INFO_MCS_MAP_MCS9 BIT(1) +#define VHT_CAP_INFO_MCS_NOT_SUPPORTED BITS(0, 1) + +#define VHT_CAP_INFO_MCS_1SS_OFFSET 0 +#define VHT_CAP_INFO_MCS_2SS_OFFSET 2 +#define VHT_CAP_INFO_MCS_3SS_OFFSET 4 +#define VHT_CAP_INFO_MCS_4SS_OFFSET 6 +#define VHT_CAP_INFO_MCS_5SS_OFFSET 8 +#define VHT_CAP_INFO_MCS_6SS_OFFSET 10 +#define VHT_CAP_INFO_MCS_7SS_OFFSET 12 +#define VHT_CAP_INFO_MCS_8SS_OFFSET 14 + +#define VHT_CAP_INFO_MCS_1SS_MASK BITS(0, 1) +#define VHT_CAP_INFO_MCS_2SS_MASK BITS(2, 3) +#define VHT_CAP_INFO_MCS_3SS_MASK BITS(4, 5) +#define VHT_CAP_INFO_MCS_4SS_MASK BITS(6, 7) +#define VHT_CAP_INFO_MCS_5SS_MASK BITS(8, 9) +#define VHT_CAP_INFO_MCS_6SS_MASK BITS(10, 11) +#define VHT_CAP_INFO_MCS_7SS_MASK BITS(12, 13) +#define VHT_CAP_INFO_MCS_8SS_MASK BITS(14, 15) + +#define VHT_OP_CHANNEL_WIDTH_20_40 0 +#define VHT_OP_CHANNEL_WIDTH_80 1 +#define VHT_OP_CHANNEL_WIDTH_160 2 +#define VHT_OP_CHANNEL_WIDTH_80P80 3 + +/*8.4.1.50 Operating Mode Field*/ +#define VHT_OP_MODE_CHANNEL_WIDTH BITS(0, 1) +#define VHT_OP_MODE_RX_NSS BITS(4, 6) +#define VHT_OP_MODE_RX_NSS_TYPE BIT(7) + +#define VHT_OP_MODE_CHANNEL_WIDTH_OFFSET 0 +#define VHT_OP_MODE_RX_NSS_OFFSET 4 +#define VHT_OP_MODE_RX_NSS_TYPE_OFFSET 7 + +#define VHT_OP_MODE_CHANNEL_WIDTH_20 0 +#define VHT_OP_MODE_CHANNEL_WIDTH_40 1 +#define VHT_OP_MODE_CHANNEL_WIDTH_80 2 +#define VHT_OP_MODE_CHANNEL_WIDTH_160_80P80 3 + +/* 8.4.1.22 SM Power Control field*/ +#define HT_SM_POWER_SAVE_CONTROL_ENABLED BIT(0) +/* 0:static, 1:dynamic */ +#define HT_SM_POWER_SAVE_CONTROL_SM_MODE BIT(1) +#define HT_SM_POWER_SAVE_CONTROL_SM_MODE_OFFSET 1 + +/* 8.4.1.21 Channel Width field */ +#define HT_NOTIFY_CHANNEL_WIDTH_20 0 +#define HT_NOTIFY_CHANNEL_WIDTH_ANY_SUPPORT_CAHNNAEL_WIDTH 1 + +/* 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_MAX_AMPDU_LEN_128K BIT(2) +#define AMPDU_PARAM_MAX_AMPDU_LEN_256K (BIT(2) | BIT(0)) +#define AMPDU_PARAM_MAX_AMPDU_LEN_512K BITS(1, 2) +#define AMPDU_PARAM_MAX_AMPDU_LEN_1024K BITS(0, 2) + +#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 */ +#define TXBF_IMPLICIT_RX_CAPABLE BIT(0) +#define TXBF_RX_STAGGERED_SOUNDING_CAPABLE BIT(1) +#define TXBF_TX_STAGGERED_SOUNDING_CAPABLE BIT(2) +#define TXBF_RX_NDP_CAPABLE_OFFSET 3 +#define TXBF_RX_NDP_CAPABLE BIT(3) +#define TXBF_TX_NDP_CAPABLE BIT(4) +#define TXBF_IMPLICIT_TX_CAPABLE BIT(5) +#define TXBF_CALIBRATION_CAPABLE BITS(6, 7) +#define TXBF_EXPLICIT_CSI_TX_CAPABLE BIT(8) +#define TXBF_EXPLICIT_NONCOMPRESSED_TX_CAPABLE BIT(9) +#define TXBF_EXPLICIT_COMPRESSED_TX_CAPAB BIT(10) +#define TXBF_EXPLICIT_CSI_FEEDBACK_CAPABLE BITS(11, 12) +#define TXBF_EXPLICIT_NONCOMPRESSED_FEEDBACK_CAPABLE BITS(13, 14) + +#define TXBF_EXPLICIT_COMPRESSED_FEEDBACK_CAPABLE_OFFSET 15 +#define TXBF_EXPLICIT_COMPRESSED_FEEDBACK_CAPABLE BITS(15, 16) +#define TXBF_EXPLICIT_COMPRESSED_FEEDBACK_IMMEDIATE_CAPABLE BIT(16) + +#define TXBF_MINIMAL_GROUPING_CAPABLE BITS(17, 18) +#define TXBF_MINIMAL_GROUPING_1_2_3_CAPABLE BITS(17, 18) + +#define TXBF_CSI_BFER_ANTENNANUM_SUPPORTED BITS(19, 20) +#define TXBF_NONCOMPRESSED_TX_ANTENNANUM_SUPPORTED BITS(21, 22) + +#define TXBF_COMPRESSED_TX_ANTENNANUM_SUPPORTED_OFFSET 23 +#define TXBF_COMPRESSED_TX_ANTENNANUM_SUPPORTED BITS(23, 24) +#define TXBF_COMPRESSED_TX_ANTENNANUM_4_SUPPORTED BITS(23, 24) + +#define TXBF_CSI_MAX_ROWS_BFER_SUPPORTED BITS(25, 26) + +#define TXBF_CHANNEL_ESTIMATION_CAPABILITY BITS(27, 28) +#define TXBF_CHANNEL_ESTIMATION_4STS_CAPABILITY BITS(27, 28) + +/* 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 */ +/* sizeof(IE_HT_OP_T)-2 */ +#define ELEM_MAX_LEN_HT_OP (24 - ELEM_HDR_LEN) + +#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_INFO1_STA_CHNL_WIDTH_OFFSET 2 + +#define HT_OP_INFO2_HT_PROTECTION BITS(0, 1) +#define HT_OP_INFO2_NON_GF_HT_STA_PRESENT BIT(2) +#define HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT BIT(4) + +#define HT_OP_INFO3_DUAL_BEACON BIT(6) +#define HT_OP_INFO3_DUAL_CTS_PROTECTION BIT(7) +#define HT_OP_INFO3_STBC_BEACON BIT(8) +#define HT_OP_INFO3_LSIG_TXOP_FULL_SUPPORT BIT(9) +#define HT_OP_INFO3_PCO_ACTIVE BIT(10) +#define HT_OP_INFO3_PCO_PHASE BIT(11) + +/* 7.3.2.59 OBSS Scan Parameter element */ +#define ELEM_MAX_LEN_OBSS_SCAN (16 - ELEM_HDR_LEN) + +/* 7.3.2.60 20/40 BSS Coexistence element */ +#define ELEM_MAX_LEN_20_40_BSS_COEXIST (3 - ELEM_HDR_LEN) + +#define BSS_COEXIST_INFO_REQ BIT(0) +#define BSS_COEXIST_40M_INTOLERANT BIT(1) +#define BSS_COEXIST_20M_REQ BIT(2) +#define BSS_COEXIST_OBSS_SCAN_EXEMPTION_REQ BIT(3) +#define BSS_COEXIST_OBSS_SCAN_EXEMPTION_GRANT BIT(4) + +/* 802.11u 7.3.2.92 Interworking IE */ +#define ELEM_MAX_LEN_INTERWORKING (11 - ELEM_HDR_LEN) + +/* 802.11u 7.3.2.93 Advertisement Protocol IE */ +#define ELEM_MAX_LEN_ADV_PROTOCOL (4 - ELEM_HDR_LEN) + +/* 802.11u 7.3.2.96 Roaming Consortium IE */ +#define ELEM_MAX_LEN_ROAMING_CONSORTIUM (19 - ELEM_HDR_LEN) + +#define IW_IE_LENGTH_ANO 1 +#define IW_IE_LENGTH_ANO_VENUE 3 +#define IW_IE_LENGTH_ANO_HESSID 7 +#define IW_IE_LENGTH_ANO_VENUE_HESSID 9 + +#if CFG_SUPPORT_PASSPOINT +/* HOTSPOT 2.0 Indication IE*/ +#define ELEM_MAX_LEN_HS20_INDICATION 5 +#define ELEM_MIN_LEN_HS20_INDICATION 4 + +/* Hotspot Configuration*/ +/* Downstream Group-Addressed Forwarding */ +#define ELEM_HS_CONFIG_DGAF_DISABLED_MASK BIT(0) +#endif /* CFG_SUPPORT_PASSPOINT */ + +/* MTK Vendor Specific OUI */ +#define ELEM_MIN_LEN_MTK_OUI 7 +#define VENDOR_OUI_MTK { 0x00, 0x0C, 0xE7 } +#define MTK_SYNERGY_CAP_SUPPORT_24G_MCS89 BIT(3) +#define MTK_SYNERGY_CAP_SUPPORT_24G_MCS89_PROBING BIT(4) +#define MTK_SYNERGY_CAP0 \ + (MTK_SYNERGY_CAP_SUPPORT_24G_MCS89) +#define MTK_SYNERGY_CAP1 0x0 +#define MTK_SYNERGY_CAP2 0x0 +#define MTK_SYNERGY_CAP3 0x0 + +/* 802.11h CSA element */ +#define ELEM_MIN_LEN_CSA 3 + +/* 3 Management frame body components (III): 7.4 Action frame format details. */ +/* 7.4.1 Spectrum Measurement Action frame details */ +/* Spectrum measurement request */ +#define ACTION_MEASUREMENT_REQ 0 +/* Spectrum measurement report */ +#define ACTION_MEASUREMENT_REPORT 1 +/* TPC request */ +#define ACTION_TPC_REQ 2 +/* TPC report */ +#define ACTION_TPC_REPORT 3 +/* Channel Switch Announcement */ +#define ACTION_CHNL_SWITCH 4 + +#define ACTION_SM_TPC_REQ_LEN 5 +#define ACTION_SM_TPC_REPORT_LEN 7 +#define ACTION_SM_MEASURE_REQ_LEN 19 +#define ACTION_SM_MEASURE_REPORT_LEN 8 +#define ACTION_SM_BASIC_REPORT_LEN 12 +#define ACTION_SM_CCA_REPORT_LEN 12 +#define ACTION_SM_PRI_REPORT_LEN 19 +/* Negative value ((dBm) */ +#define MIN_RCV_PWR 100 + +/* 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_QOS_MAP_CONFIGURE 4 /*Qos Map Configure*/ + +/* WMM TSPEC IE: 63 */ +#define ACTION_ADDTS_REQ_FRAME_LEN (24+3+63) +/* WMM Status Code: 1; WMM TSPEC IE: 63 */ +#define ACTION_ADDTS_RSP_FRAME_LEN (24 + 4 + 63) +/*category + action + WMM TSinfo:3 + reason:2*/ +#define ACTION_DELTS_FRAME_LEN (24 + 7) + +/* 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 */ +/* Radio measurement request */ +#define ACTION_RM_REQ 0 +/* Radio measurement report */ +#define ACTION_RM_REPORT 1 +/* Link measurement request */ +#define ACTION_LM_REQ 2 +/* Link measurement report */ +#define ACTION_LM_REPORT 3 +/* Neighbor report request */ +#define ACTION_NEIGHBOR_REPORT_REQ 4 +/* Neighbor report response */ +#define ACTION_NEIGHBOR_REPORT_RSP 5 + +/* 7.4.7 Public Action frame details */ +/* 20/40 BSS coexistence */ +#define ACTION_PUBLIC_20_40_COEXIST 0 + +#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 */ +/* Notify Channel Width */ +#define ACTION_HT_NOTIFY_CHANNEL_WIDTH 0 +/* SM Power Save */ +#define ACTION_HT_SM_POWER_SAVE 1 +/* PSMP */ +#define ACTION_HT_PSMP 2 +/* Set PCO Phase */ +#define ACTION_HT_SET_PCO_PHASE 3 +/* CSI */ +#define ACTION_HT_CSI 4 +/* Non-compressed Beamforming */ +#define ACTION_HT_NON_COMPRESSED_BEAMFORM 5 +/* Compressed Beamforming */ +#define ACTION_HT_COMPRESSED_BEAMFORM 6 +/* Antenna Selection Indices Feedback */ +#define ACTION_HT_ANT_SEL_INDICES_FB 7 + +#define ACTION_WNM_NOTIFICATION_REQUEST 26 +/* 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_WNM_BSS_TRANSITION_MANAGEMENT_QUERY 6 +#define ACTION_WNM_BSS_TRANSITION_MANAGEMENT_REQ 7 +#define ACTION_WNM_BSS_TRANSITION_MANAGEMENT_RSP 8 +#define ACTION_UNPROTECTED_WNM_TIMING_MEAS_LEN 12 + +/* 8.5.23.1 VHT Action */ +#define ACTION_VHT_COMPRESSED_BFEAMFORMING 0 +#define ACTION_GROUP_ID_MANAGEMENT 1 +#define ACTION_OPERATING_MODE_NOTIFICATION 2 + +/* 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 + +#if CFG_SUPPORT_PASSPOINT +#define VENDOR_OUI_TYPE_HS20 16 +#endif /* CFG_SUPPORT_PASSPOINT */ + +/* Length of OUI and Type */ +#define VENDOR_OUI_TYPE_LEN 4 + +/* VERSION(2 octets for WPA) / SUBTYPE(1 octet)-VERSION(1 octet) + * fields for WMM in WFA IE + */ +/* Little Endian Format */ +#define VERSION_WPA 0x0001 +#define VENDOR_OUI_SUBTYPE_VERSION_WMM_INFO 0x0100 +#define VENDOR_OUI_SUBTYPE_VERSION_WMM_PARAM 0x0101 + +/* SUBTYPE(1 octet) for WMM */ +/* WMM Spec version 1.1 */ +#define VENDOR_OUI_SUBTYPE_WMM_INFO 0x00 +#define VENDOR_OUI_SUBTYPE_WMM_PARAM 0x01 +#define VENDOR_OUI_SUBTYPE_WMM_TSPEC 0x02 + +/* VERSION(1 octet) for WMM */ +/* WMM Spec version 1.1 */ +#define VERSION_WMM 0x01 + +/* 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_CONTROL_TID_OFFSET 12 +#define CTRL_BAR_BAR_INFORMATION_OFFSET 18 +#define CTRL_BAR_BAR_INFORMATION_SSN_OFFSET 4 + +/* 802.11-2012, 8.5.7 Radio Measurement action fields, table 8-206 */ +#define RM_ACTION_RM_REQUEST 0 +#define RM_ACTION_RM_REPORT 1 +#define RM_ACTION_LM_REQUEST 2 +#define RM_ACTION_LM_REPORT 3 +#define RM_ACTION_NEIGHBOR_REQUEST 4 +#define RM_ACTION_REIGHBOR_RESPONSE 5 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +#if defined(WINDOWS_DDK) || defined(WINDOWS_CE) +#pragma pack(1) +#endif + +struct LLC_SNAP_HEADER { + uint8_t ucDSAP; + uint8_t ucSSAP; + uint8_t ucControl; + uint8_t aucCode[3]; + uint16_t u2Type; +} __KAL_ATTRIB_PACKED__; + +/* 3 MAC Header. */ +/* Ethernet Frame Header */ +struct ETH_FRAME_HEADER { + uint8_t aucDestAddr[MAC_ADDR_LEN]; + uint8_t aucSrcAddr[MAC_ADDR_LEN]; + uint16_t u2TypeLen; +} __KAL_ATTRIB_PACKED__; + +/* Ethernet Frame Structure */ +struct ETH_FRAME { + uint8_t aucDestAddr[MAC_ADDR_LEN]; + uint8_t aucSrcAddr[MAC_ADDR_LEN]; + uint16_t u2TypeLen; + uint8_t aucData[1]; +} __KAL_ATTRIB_PACKED__; + +struct BOOTP_PROTOCOL { + uint8_t ucOperation; + uint8_t ucHdrType; + uint8_t ucHdrLen; + uint8_t ucHops; + uint32_t u4TransId; + uint16_t u2Seconds; + uint16_t u2Flags; + uint32_t u4CIAddr; + uint32_t u4YIAddr; + uint32_t u4SIAddr; + uint32_t u4GIAddr; + uint8_t aucCHAddr[16]; + uint8_t aucServerName[64]; + uint8_t aucFileName[128]; + uint8_t aucOptions[0]; +} __KAL_ATTRIB_PACKED__; + +/* IEEE 802.11 WLAN Frame Structure */ +/* WLAN MAC Header (without Address 4 and QoS Control fields) */ +struct WLAN_MAC_HEADER { + uint16_t u2FrameCtrl; + uint16_t u2DurationID; + uint8_t aucAddr1[MAC_ADDR_LEN]; + uint8_t aucAddr2[MAC_ADDR_LEN]; + uint8_t aucAddr3[MAC_ADDR_LEN]; + uint16_t u2SeqCtrl; +} __KAL_ATTRIB_PACKED__; + +/* WLAN MAC Header (QoS Control fields included) */ +struct WLAN_MAC_HEADER_QOS { + uint16_t u2FrameCtrl; + uint16_t u2DurationID; + uint8_t aucAddr1[MAC_ADDR_LEN]; + uint8_t aucAddr2[MAC_ADDR_LEN]; + uint8_t aucAddr3[MAC_ADDR_LEN]; + uint16_t u2SeqCtrl; + uint16_t u2QosCtrl; +} __KAL_ATTRIB_PACKED__; + +/* WLAN MAC Header (HT Control fields included) */ +struct WLAN_MAC_HEADER_HT { + uint16_t u2FrameCtrl; + uint16_t u2DurationID; + uint8_t aucAddr1[MAC_ADDR_LEN]; + uint8_t aucAddr2[MAC_ADDR_LEN]; + uint8_t aucAddr3[MAC_ADDR_LEN]; + uint16_t u2SeqCtrl; + uint16_t u2QosCtrl; + uint32_t u4HtCtrl; +} __KAL_ATTRIB_PACKED__; + +/* WLAN MAC Header (Address 4 included) */ +struct WLAN_MAC_HEADER_A4 { + uint16_t u2FrameCtrl; + uint16_t u2DurationID; + uint8_t aucAddr1[MAC_ADDR_LEN]; + uint8_t aucAddr2[MAC_ADDR_LEN]; + uint8_t aucAddr3[MAC_ADDR_LEN]; + uint16_t u2SeqCtrl; + uint8_t aucAddr4[MAC_ADDR_LEN]; +} __KAL_ATTRIB_PACKED__; + +/* WLAN MAC Header (Address 4 and QoS Control fields included) */ +struct WLAN_MAC_HEADER_A4_QOS { + uint16_t u2FrameCtrl; + uint16_t u2DurationID; + uint8_t aucAddr1[MAC_ADDR_LEN]; + uint8_t aucAddr2[MAC_ADDR_LEN]; + uint8_t aucAddr3[MAC_ADDR_LEN]; + uint16_t u2SeqCtrl; + uint8_t aucAddr4[MAC_ADDR_LEN]; + uint16_t u2QosCtrl; +} __KAL_ATTRIB_PACKED__; + +struct WLAN_MAC_HEADER_A4_HT { + uint16_t u2FrameCtrl; + uint16_t u2DurationID; + uint8_t aucAddr1[MAC_ADDR_LEN]; + uint8_t aucAddr2[MAC_ADDR_LEN]; + uint8_t aucAddr3[MAC_ADDR_LEN]; + uint16_t u2SeqCtrl; + uint8_t aucAddr4[MAC_ADDR_LEN]; + uint16_t u2QosCtrl; + uint32_t u4HtCtrl; +} __KAL_ATTRIB_PACKED__; + +/* 7.2.3 WLAN MAC Header for Management Frame - MMPDU */ +struct WLAN_MAC_MGMT_HEADER { + uint16_t u2FrameCtrl; + uint16_t u2Duration; + uint8_t aucDestAddr[MAC_ADDR_LEN]; + uint8_t aucSrcAddr[MAC_ADDR_LEN]; + uint8_t aucBSSID[MAC_ADDR_LEN]; + uint16_t u2SeqCtrl; +} __KAL_ATTRIB_PACKED__; + +/* WLAN MAC Header for Management Frame (HT Control fields included) */ +struct WLAN_MAC_MGMT_HEADER_HT { + uint16_t u2FrameCtrl; + uint16_t u2DurationID; + uint8_t aucAddr1[MAC_ADDR_LEN]; + uint8_t aucAddr2[MAC_ADDR_LEN]; + uint8_t aucAddr3[MAC_ADDR_LEN]; + uint16_t u2SeqCtrl; + uint32_t u4HtCtrl; +} __KAL_ATTRIB_PACKED__; + +/* 3 WLAN CONTROL Frame */ +/* 7.2.1.4 WLAN Control Frame - PS-POLL Frame */ +struct CTRL_PSPOLL_FRAME { + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2AID; /* AID */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint8_t aucTA[MAC_ADDR_LEN]; /* TA */ +} __KAL_ATTRIB_PACKED__; + +/* BAR */ +struct CTRL_BAR_FRAME { + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* RA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* TA */ + uint16_t u2BarControl; + uint8_t aucBarInfo[2]; /* Variable size */ +} __KAL_ATTRIB_PACKED__; + +/* 3 WLAN Management Frame. */ +/* 7.2.3.1 WLAN Management Frame - Beacon Frame */ +struct WLAN_BEACON_FRAME { + /* Beacon header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Beacon frame body */ + uint32_t au4Timestamp[2]; /* Timestamp */ + uint16_t u2BeaconInterval; /* Beacon Interval */ + uint16_t u2CapInfo; /* Capability */ + uint8_t aucInfoElem[1]; /* Various IEs, start from SSID */ +} __KAL_ATTRIB_PACKED__; + +struct WLAN_BEACON_FRAME_BODY { + /* Beacon frame body */ + uint32_t au4Timestamp[2]; /* Timestamp */ + uint16_t u2BeaconInterval; /* Beacon Interval */ + uint16_t u2CapInfo; /* Capability */ + uint8_t aucInfoElem[1]; /* Various IEs, start from SSID */ +} __KAL_ATTRIB_PACKED__; + +/* 7.2.3.3 WLAN Management Frame - Disassociation Frame */ +struct WLAN_DISASSOC_FRAME { + /* Authentication MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Disassociation frame body */ + uint16_t u2ReasonCode; /* Reason code */ + uint8_t aucInfoElem[1]; /* Various IEs, possible no. */ +} __KAL_ATTRIB_PACKED__; + +/* 7.2.3.4 WLAN Management Frame - Association Request frame */ +struct WLAN_ASSOC_REQ_FRAME { + /* Association Request MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Association Request frame body */ + uint16_t u2CapInfo; /* Capability information */ + uint16_t u2ListenInterval; /* Listen interval */ + uint8_t aucInfoElem[1]; /* Information elements, include WPA IE */ +} __KAL_ATTRIB_PACKED__; + +/* 7.2.3.5 WLAN Management Frame - Association Response frame */ +struct WLAN_ASSOC_RSP_FRAME { + /* Association Response MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Association Response frame body */ + uint16_t u2CapInfo; /* Capability information */ + uint16_t u2StatusCode; /* Status code */ + uint16_t u2AssocId; /* Association ID */ + uint8_t aucInfoElem[1]; /* Information elements, such as */ + /* supported rates, and etc. */ +} __KAL_ATTRIB_PACKED__; + +/* 7.2.3.6 WLAN Management Frame - Reassociation Request frame */ +struct WLAN_REASSOC_REQ_FRAME { + /* Reassociation Request MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Reassociation Request frame body */ + uint16_t u2CapInfo; /* Capability information */ + uint16_t u2ListenInterval; /* Listen interval */ + uint8_t aucCurrentAPAddr[MAC_ADDR_LEN]; /* Current AP address */ + uint8_t aucInfoElem[1]; /* Information elements, include WPA IE */ +} __KAL_ATTRIB_PACKED__; + +/* 7.2.3.7 WLAN Management Frame - Reassociation Response frame */ +/* (the same as Association Response frame) */ + +/* 7.2.3.9 WLAN Management Frame - Probe Response Frame */ + +/* 7.2.3.10 WLAN Management Frame - Authentication Frame */ +struct WLAN_AUTH_FRAME { + /* Authentication MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Authentication frame body */ + uint16_t u2AuthAlgNum; /* Authentication algorithm number */ +#if CFG_SUPPORT_CFG80211_AUTH + u_int8_t aucAuthData[AUTH_DATA_MAX_LEN]; +#else + /* Authentication transaction sequence number */ + uint16_t u2AuthTransSeqNo; + uint16_t u2StatusCode; /* Status code */ +#endif + uint8_t aucInfoElem[1]; /* Various IEs for Fast BSS Transition */ +} __KAL_ATTRIB_PACKED__; + +/* 7.2.3.11 WLAN Management Frame - Deauthentication Frame */ +struct WLAN_DEAUTH_FRAME { + /* Authentication MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Deauthentication frame body */ + uint16_t u2ReasonCode; /* Reason code */ + uint8_t aucInfoElem[1]; /* Various IEs, possible no. */ +} __KAL_ATTRIB_PACKED__; + +/* 3 Information Elements. */ +/* 7.3.2 Generic element format */ +struct IE_HDR { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucInfo[1]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.1 SSID element */ +struct IE_SSID { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucSSID[ELEM_MAX_LEN_SSID]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.2 Supported Rates element */ +struct IE_SUPPORTED_RATE { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucSupportedRates[ELEM_MAX_LEN_SUP_RATES]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.4 DS Parameter Set element */ +struct IE_DS_PARAM_SET { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucCurrChnl; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.5 CF Parameter Set element */ +struct IE_CF_PARAM_SET { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucCFPCount; + uint8_t ucCFPPeriod; + uint16_t u2CFPMaxDur; + uint16_t u2DurRemaining; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.6 TIM */ +struct IE_TIM { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucDTIMCount; + uint8_t ucDTIMPeriod; + uint8_t ucBitmapControl; + uint8_t aucPartialVirtualMap[1]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.7 IBSS Parameter Set element */ +struct IE_IBSS_PARAM_SET { + uint8_t ucId; + uint8_t ucLength; + uint16_t u2ATIMWindow; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.8 Challenge Text element */ +struct IE_CHALLENGE_TEXT { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucChallengeText[ELEM_MAX_LEN_CHALLENGE_TEXT]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.9 Country information element */ +#if CFG_SUPPORT_802_11D +/*! \brief COUNTRY_INFO_TRIPLET + * is defined for the COUNTRY_INFO_ELEM structure. + */ +struct COUNTRY_INFO_TRIPLET { + /*!< If param1 >= 201, this triplet is referred to as + * Regulatory Triplet in 802_11J. + */ + uint8_t ucParam1; + uint8_t ucParam2; + uint8_t ucParam3; +} __KAL_ATTRIB_PACKED__; + +struct COUNTRY_INFO_SUBBAND_TRIPLET { + uint8_t ucFirstChnlNum; /*!< First Channel Number */ + uint8_t ucNumOfChnl; /*!< Number of Channels */ + int8_t cMaxTxPwrLv; /*!< Maximum Transmit Power Level */ +} __KAL_ATTRIB_PACKED__; + +struct COUNTRY_INFO_REGULATORY_TRIPLET { + uint8_t ucRegExtId; /*!< Regulatory Extension Identifier, should */ + /* be greater than or equal to 201 */ + uint8_t ucRegClass; /*!< Regulatory Class */ + /*!< Coverage Class, unsigned 1-octet value 0~31 */ + uint8_t ucCoverageClass; + /* , 32~255 reserved */ +} __KAL_ATTRIB_PACKED__; + +struct IE_COUNTRY { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucCountryStr[3]; + struct COUNTRY_INFO_SUBBAND_TRIPLET arCountryStr[1]; +} __KAL_ATTRIB_PACKED__; +#endif /* CFG_SUPPORT_802_11D */ + +/* 7.3.2.13 ERP element */ +struct IE_ERP { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucERP; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.14 Extended Supported Rates element */ +struct IE_EXT_SUPPORTED_RATE { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucExtSupportedRates[ELEM_MAX_LEN_EXTENDED_SUP_RATES]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.15 Power Constraint element */ +struct IE_POWER_CONSTRAINT { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucLocalPowerConstraint; /* Unit: dBm */ +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.16 Power Capability element */ +struct IE_POWER_CAP { + uint8_t ucId; + uint8_t ucLength; + int8_t cMinTxPowerCap; /* Unit: dBm */ + int8_t cMaxTxPowerCap; /* Unit: dBm */ +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.17 TPC request element */ +struct IE_TPC_REQ { + uint8_t ucId; + uint8_t ucLength; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.18 TPC report element */ +struct IE_TPC_REPORT { + uint8_t ucId; + uint8_t ucLength; + int8_t cTxPower; /* Unit: dBm */ + int8_t cLinkMargin; /* Unit: dB */ +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.19 Supported Channels element*/ +struct IE_SUPPORTED_CHANNELS { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucChannelNum[0]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.20 Channel Switch Announcement element*/ +struct IE_CHANNEL_SWITCH { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucChannelSwitchMode; + uint8_t ucNewChannelNum; + uint8_t ucChannelSwitchCount; +} __KAL_ATTRIB_PACKED__; + +struct IE_TIMEOUT_INTERVAL { + uint8_t ucId; + uint8_t ucLength; +#define IE_TIMEOUT_INTERVAL_TYPE_RESERVED 0 +#define IE_TIMEOUT_INTERVAL_TYPE_REASSOC 1 +#define IE_TIMEOUT_INTERVAL_TYPE_KEY_LIFETIME 43200 +#define IE_TIMEOUT_INTERVAL_TYPE_ASSOC_COMEBACK 3 + uint8_t ucType; + uint32_t u4Value; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.20 Channel Switch Announcement element */ +struct IE_CHNL_SWITCH { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucSwitchMode; + uint8_t ucNewChannel; + uint8_t ucSwitchCount; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.21 Measurement Request element */ +struct IE_MEASUREMENT_REQ { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucToken; + uint8_t ucRequestMode; + uint8_t ucMeasurementType; + uint8_t aucRequestFields[1]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.60 20/40 BSS Coexistence element */ +struct IE_SUP_OPERATING_CLASS { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucCur; + uint8_t ucSup[255]; +} __KAL_ATTRIB_PACKED__; + +/* 8.4.2.30 BSS Load element */ +struct IE_BSS_LOAD { + uint8_t ucId; + uint8_t ucLength; + uint16_t u2StaCnt; + uint8_t ucChnlUtilizaion; + uint16_t u2AvailabeAC; +} __KAL_ATTRIB_PACKED__; + +/* 8.4.2.39 Neighbor Report Element */ +struct IE_NEIGHBOR_REPORT { + uint8_t ucId; /* Element ID */ + uint8_t ucLength; /* Length */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* OUI */ + uint32_t u4BSSIDInfo; /* Type */ + uint8_t ucOperClass; /* Hotspot Configuration */ + uint8_t ucChnlNumber; + uint8_t ucPhyType; + uint8_t aucSubElem[0]; +} __KAL_ATTRIB_PACKED__; + +/* 8.5.7.6/8.5.7.7 Neighbor Report Request/Response frame format */ +struct ACTION_NEIGHBOR_REPORT_FRAME { + /* Neighbor Report Request/Response MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Neighbor Report Request/Response frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token */ + uint8_t aucInfoElem[1]; /* subelements */ +} __KAL_ATTRIB_PACKED__; + +struct SUB_ELEMENT { + uint8_t ucSubID; + uint8_t ucLength; + uint8_t aucOptInfo[1]; +} __KAL_ATTRIB_PACKED__; + +struct SM_BASIC_REQ { + uint8_t ucChannel; + uint32_t au4StartTime[2]; + uint16_t u2Duration; +} __KAL_ATTRIB_PACKED__; + +/* SM_COMMON_REQ_T is not specified in Spec. Use it as common structure of SM */ + +struct RM_CHNL_LOAD_REQ { + uint8_t ucRegulatoryClass; + uint8_t ucChannel; + uint16_t u2RandomInterval; + uint16_t u2Duration; + uint8_t aucSubElements[1]; +} __KAL_ATTRIB_PACKED__; + + +struct RM_BCN_REQ { + uint8_t ucRegulatoryClass; + uint8_t ucChannel; + uint16_t u2RandomInterval; + uint16_t u2Duration; + uint8_t ucMeasurementMode; + uint8_t aucBssid[6]; + uint8_t aucSubElements[1]; +} __KAL_ATTRIB_PACKED__; + +struct RM_FRAME_REQ { + uint8_t ucRegulatoryClass; + uint8_t ucChannel; + uint16_t u2RandomInterval; + uint16_t u2Duration; + uint8_t ucFrameReqType; + uint8_t aucMacAddr[6]; + uint8_t aucSubElements[1]; +} __KAL_ATTRIB_PACKED__; + +struct RM_STA_STATS_REQ { + uint8_t aucPeerMacAddr[6]; + uint16_t u2RandomInterval; + uint16_t u2Duration; + uint8_t ucGroupID; + uint8_t aucSubElements[1]; +} __KAL_ATTRIB_PACKED__; + +struct RM_LCI_REQ { + uint8_t ucLocationSubject; + uint8_t ucLatitudeResolution; + uint8_t ucLongitudeResolution; + uint8_t ucAltitudeResolution; + uint8_t aucSubElements[1]; +} __KAL_ATTRIB_PACKED__; + +struct RM_TS_MEASURE_REQ { + uint16_t u2RandomInterval; + uint16_t u2Duration; + uint8_t aucPeerStaAddr[6]; + uint8_t ucTrafficID; + uint8_t ucBin0Range; + uint8_t aucSubElements[1]; +} __KAL_ATTRIB_PACKED__; + +struct RM_MEASURE_PAUSE_REQ { + uint16_t u2PauseTime; + uint8_t aucSubElements[1]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.22 Measurement Report element */ +struct IE_MEASUREMENT_REPORT { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucToken; + uint8_t ucReportMode; + uint8_t ucMeasurementType; + uint8_t aucReportFields[1]; +} __KAL_ATTRIB_PACKED__; + +struct SM_BASIC_REPORT { + uint8_t ucChannel; + uint32_t u4StartTime[2]; + uint16_t u2Duration; + uint8_t ucMap; +} __KAL_ATTRIB_PACKED__; + +struct SM_CCA_REPORT { + uint8_t ucChannel; + uint32_t u4StartTime[2]; + uint16_t u2Duration; + uint8_t ucCcaBusyFraction; +} __KAL_ATTRIB_PACKED__; + +struct SM_RPI_REPORT { + uint8_t ucChannel; + uint32_t u4StartTime[2]; + uint16_t u2Duration; + uint8_t aucRPI[8]; +} __KAL_ATTRIB_PACKED__; + +struct RM_CHNL_LOAD_REPORT { + uint8_t ucRegulatoryClass; + uint8_t ucChannel; + uint32_t u4StartTime[2]; + uint16_t u2Duration; + uint8_t ucChnlLoad; +} __KAL_ATTRIB_PACKED__; + +struct RM_IPI_REPORT { + uint8_t ucRegulatoryClass; + uint8_t ucChannel; + uint32_t u4StartTime[2]; + uint16_t u2Duration; + uint8_t ucAntennaId; + int8_t cANPI; + uint8_t aucIPI[11]; +} __KAL_ATTRIB_PACKED__; + +struct RM_BCN_REPORT { + uint8_t ucRegulatoryClass; + uint8_t ucChannel; + uint8_t aucStartTime[8]; + uint16_t u2Duration; + uint8_t ucReportInfo; + uint8_t ucRCPI; + uint8_t ucRSNI; + uint8_t aucBSSID[MAC_ADDR_LEN]; + uint8_t ucAntennaID; + uint8_t aucParentTSF[4]; + uint8_t aucOptElem[0]; +} __KAL_ATTRIB_PACKED__; + +struct RM_TSM_REPORT { + uint64_t u8ActualStartTime; + uint16_t u2Duration; + uint8_t aucPeerAddress[MAC_ADDR_LEN]; + uint8_t ucTID; + uint8_t ucReason; + uint32_t u4TransmittedMsduCnt; + uint32_t u4DiscardedMsduCnt; + uint32_t u4FailedMsduCnt; + uint32_t u4MultiRetryCnt; + uint32_t u4CfPollLostCnt; + uint32_t u4AvgQueDelay; + uint32_t u4AvgDelay; + uint8_t ucBin0Range; + uint32_t u4Bin[6]; + uint8_t aucOptSubElems[0]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.23 Quiet element */ +struct IE_QUIET { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucCount; + uint8_t ucPeriod; + uint16_t u2Duration; + uint16_t u2Offset; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.27 Extended Capabilities element */ +struct IE_EXT_CAP { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucCapabilities[1]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.27 hs20 Extended Capabilities element */ +struct IE_HS20_EXT_CAP_T { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucCapabilities[6]; +}; + +/* 7.3.2.27 Extended Capabilities element */ +struct IE_RRM_ENABLED_CAP { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucCap[5]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.56 HT Capabilities element */ +struct SUP_MCS_SET_FIELD { + uint8_t aucRxMcsBitmask[SUP_MCS_RX_BITMASK_OCTET_NUM]; + uint16_t u2RxHighestSupportedRate; + uint32_t u4TxRateInfo; +} __KAL_ATTRIB_PACKED__; + +struct IE_HT_CAP { + uint8_t ucId; + uint8_t ucLength; + uint16_t u2HtCapInfo; + uint8_t ucAmpduParam; + struct SUP_MCS_SET_FIELD rSupMcsSet; + uint16_t u2HtExtendedCap; + uint32_t u4TxBeamformingCap; + uint8_t ucAselCap; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.57 HT Operation element */ +struct IE_HT_OP { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucPrimaryChannel; + uint8_t ucInfo1; + uint16_t u2Info2; + uint16_t u2Info3; + uint8_t aucBasicMcsSet[16]; +} __KAL_ATTRIB_PACKED__; + +/*8.4.2.160.3 VHT Supported MCS Set field*/ +struct VHT_SUPPORTED_MCS_FIELD { + uint16_t u2RxMcsMap; + uint16_t u2RxHighestSupportedDataRate; + uint16_t u2TxMcsMap; + uint16_t u2TxHighestSupportedDataRate; +} __KAL_ATTRIB_PACKED__; + +struct IE_VHT_CAP { + uint8_t ucId; + uint8_t ucLength; + uint32_t u4VhtCapInfo; + struct VHT_SUPPORTED_MCS_FIELD rVhtSupportedMcsSet; +} __KAL_ATTRIB_PACKED__; + +/*8.4.2.161 VHT Operation element*/ +struct IE_VHT_OP { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucVhtOperation[3]; + uint16_t u2VhtBasicMcsSet; +} __KAL_ATTRIB_PACKED__; + +/*8.4.1.50 Operating Mode field*/ +struct IE_VHT_OP_MODE_NOTIFICATION { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucOperatingMode; +} __KAL_ATTRIB_PACKED__; + + +/*8.4.2.22 Secondary Channel Offset element*/ +struct IE_SECONDARY_OFFSET { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucSecondaryOffset; +} __KAL_ATTRIB_PACKED__; + +/*8.4.2.105 Mesh Channel Switch Parameters element*/ +struct IE_MESH_CHANNEL { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucTimetoLive; + uint8_t ucFlags; + uint16_t u2ReasonCodes; + uint16_t u2ProcedenceValue; +} __KAL_ATTRIB_PACKED__; + +/*8.4.2.163 Wide Bandwidth Channel Switch element*/ +struct IE_WIDE_BAND_CHANNEL { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucNewChannelWidth; + uint8_t ucChannelS1; + uint8_t ucChannelS2; +} __KAL_ATTRIB_PACKED__; + +/*8.4.2.168 Operating Mode Notification element*/ +struct IE_OP_MODE_NOTIFICATION { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucOpMode; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.25 RSN Information element format */ +struct RSN_INFO_ELEM { + uint8_t ucElemId; + uint8_t ucLength; + uint16_t u2Version; + uint32_t u4GroupKeyCipherSuite; + uint16_t u2PairwiseKeyCipherSuiteCount; + uint8_t aucPairwiseKeyCipherSuite1[4]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.26 WPA Information element format */ +struct WPA_INFO_ELEM { + uint8_t ucElemId; + uint8_t ucLength; + uint8_t aucOui[3]; + uint8_t ucOuiType; + uint16_t u2Version; + uint32_t u4GroupKeyCipherSuite; + uint16_t u2PairwiseKeyCipherSuiteCount; + uint8_t aucPairwiseKeyCipherSuite1[4]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.58 20/40 BSS Intolerant Channel Report element */ +struct IE_INTOLERANT_CHNL_REPORT { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucRegulatoryClass; + uint8_t aucChannelList[1]; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.59 OBSS Scan Parameters element */ +struct IE_OBSS_SCAN_PARAM { + uint8_t ucId; + uint8_t ucLength; + uint16_t u2ScanPassiveDwell; + uint16_t u2ScanActiveDwell; + uint16_t u2TriggerScanInterval; + uint16_t u2ScanPassiveTotalPerChnl; + uint16_t u2ScanActiveTotalPerChnl; + uint16_t u2WidthTransDelayFactor; + uint16_t u2ScanActivityThres; +} __KAL_ATTRIB_PACKED__; + +/* 7.3.2.60 20/40 BSS Coexistence element */ +struct IE_20_40_COEXIST { + uint8_t ucId; + uint8_t ucLength; + uint8_t ucData; +} __KAL_ATTRIB_PACKED__; + +/* 3 7.4 Action Frame. */ +/* 7.4 Action frame format */ +struct WLAN_ACTION_FRAME { + /* Action MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Action frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucActionDetails[1]; /* Action details */ +} __KAL_ATTRIB_PACKED__; + +/* public Action frame format */ +struct WLAN_PUBLIC_VENDOR_ACTION_FRAME { + /* Action MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Action frame body */ + uint8_t ucCategory; /* Category: should be 0x4 */ + uint8_t ucAction; /* Action Value: should be 0x9 */ + uint8_t ucOUI[3]; + uint8_t ucSubType; + uint8_t ucPubSubType; +} __KAL_ATTRIB_PACKED__; + + +/* 7.4.1.1 Spectrum Measurement Request frame format */ +struct ACTION_SM_REQ_FRAME { + /* ADDTS Request MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* ADDTS Request frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token */ + uint8_t aucInfoElem[1]; /* Information elements */ +} __KAL_ATTRIB_PACKED__; + +/* 7.4.1.2 Spectrum Measurement Report frame format */ + +/* 7.4.1.3 Spectrum TPC Request frame format */ +struct ACTION_TPC_REQ_FRAME { + /* ADDTS Request MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* ADDTS Request frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token */ + uint8_t ucElemId; /* Element ID */ + uint8_t ucLength; /* Length */ +} __KAL_ATTRIB_PACKED__; + +/* 7.4.1.4 Spectrum TPC Report frame format */ +struct ACTION_TPC_REPORT_FRAME { + /* ADDTS Request MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* ADDTS Request frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token */ + uint8_t ucElemId; /* Element ID */ + uint8_t ucLength; /* Length */ + uint8_t ucTransPwr; /* Transmit Power */ + uint8_t ucLinkMargin; /* Link Margin */ +} __KAL_ATTRIB_PACKED__; + +/* 7.4.1.5 Channel Switch Announcement frame format */ +struct ACTION_CHANNEL_SWITCH_FRAME { + /* ADDTS Request MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* ADDTS Request frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t aucInfoElem[1]; /* Information elements */ +} __KAL_ATTRIB_PACKED__; + +/* 7.4.2.1 ADDTS Request frame format */ +struct ACTION_ADDTS_REQ_FRAME { + /* ADDTS Request MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* ADDTS Request frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token */ + uint8_t aucInfoElem[1]; /* Information elements, such as */ + /* TS Delay, and etc. */ +} __KAL_ATTRIB_PACKED__; + +/* 7.4.2.2 ADDTS Response frame format */ +struct ACTION_ADDTS_RSP_FRAME { + /* ADDTS Response MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* ADDTS Response frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token */ + uint8_t ucStatusCode; /* WMM Status Code is of one byte */ + uint8_t aucInfoElem[1]; /* Information elements, such as */ + /* TS Delay, and etc. */ +} __KAL_ATTRIB_PACKED__; + +/* 7.4.2.3 DELTS frame format */ +struct ACTION_DELTS_FRAME { + /* DELTS MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* DELTS frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t aucTsInfo[3]; /* TS Info */ +} __KAL_ATTRIB_PACKED__; + +/* 7.4.2.3 QOSMAPSET CONFIGURATE frame format */ +struct _ACTION_QOS_MAP_CONFIGURE_FRAME { + /* QOSMAP CONFIGURE MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* DELTS frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t qosMapSet[1]; /* qosmapset IE */ +}; + +/* 7.4.4.1 ADDBA Request frame format */ +struct ACTION_ADDBA_REQ_FRAME { + /* Action MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Action frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token chosen by the sender */ + uint8_t aucBAParameterSet[2]; /* BA policy, TID, buffer size */ + uint8_t aucBATimeoutValue[2]; + uint8_t aucBAStartSeqCtrl[2]; /* SSN */ +} __KAL_ATTRIB_PACKED__; + +struct ACTION_ADDBA_REQ_BODY { + uint16_t u2BAParameterSet; /* BA policy, TID, buffer size */ + uint16_t u2BATimeoutValue; + uint16_t u2BAStartSeqCtrl; /* SSN */ +} __KAL_ATTRIB_PACKED__; + +/* 7.4.4.2 ADDBA Response frame format */ +struct ACTION_ADDBA_RSP_FRAME { + /* Action MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Action frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token chosen by the sender */ + uint8_t aucStatusCode[2]; + uint8_t aucBAParameterSet[2]; /* BA policy, TID, buffer size */ + uint8_t aucBATimeoutValue[2]; +} __KAL_ATTRIB_PACKED__; + +struct ACTION_ADDBA_RSP_BODY { + uint16_t u2StatusCode; + uint16_t u2BAParameterSet; /* BA policy, TID, buffer size */ + uint16_t u2BATimeoutValue; +} __KAL_ATTRIB_PACKED__; + +/* 7.4.4.3 DELBA frame format */ +struct ACTION_DELBA_FRAME { + /* Action MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Action frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint16_t u2DelBaParameterSet; /* Bit 11 Initiator, Bits 12-15 TID */ + uint16_t u2ReasonCode; /* 7.3.1.7 */ +} __KAL_ATTRIB_PACKED__; + +#if CFG_SUPPORT_NCHO +/* 7.4.5.1 vendor-specific frame format */ +struct _ACTION_VENDOR_SPEC_FRAME_T { + /* Action MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + uint8_t aucElemInfo[0]; /* Pointer to frame data */ +}; +#endif + +/* 7.4.6.1 Radio Measurement Request frame format */ +struct ACTION_RM_REQ_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Radio Measurement Request frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token */ + uint16_t u2Repetitions; /* Number of repetitions */ + uint8_t aucInfoElem[1]; /* Measurement Request elements, such as */ + /* channel load request, and etc. */ +} __KAL_ATTRIB_PACKED__; + +/* 7.4.6.2 Radio Measurement Report frame format */ +struct ACTION_RM_REPORT_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Radio Measurement Report frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token */ + uint8_t aucInfoElem[1]; /* Measurement Report elements, such as */ + /* channel load report, and etc. */ +} __KAL_ATTRIB_PACKED__; + +/* 7.4.7.1a 20/40 BSS Coexistence Management frame format */ +struct ACTION_20_40_COEXIST_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* BSS Coexistence Management frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + + /* 20/40 BSS coexistence element */ + struct IE_20_40_COEXIST rBssCoexist; + /* Intolerant channel report */ + struct IE_INTOLERANT_CHNL_REPORT rChnlReport; + +} __KAL_ATTRIB_PACKED__; + +#if CFG_SUPPORT_802_11W +/* 7.4.9 SA Query Management frame format */ +struct ACTION_SA_QUERY_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* BSS Coexistence Management frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + + uint8_t ucTransId[ACTION_SA_QUERY_TR_ID_LEN]; /* Transaction id */ + +} __KAL_ATTRIB_PACKED__; +#endif + +/* 7.4.10 Notify Channel Width Management frame format */ +struct ACTION_NOTIFY_CHNL_WIDTH_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* BSS Coexistence Management frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucChannelWidth; /* Channel Width */ +} __KAL_ATTRIB_PACKED__; + +/* 802.11v Wireless Network Management: Timing Measurement Request */ +struct ACTION_WNM_TIMING_MEAS_REQ_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Timing Measurement Request Management frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucTrigger; /* Trigger */ +} __KAL_ATTRIB_PACKED__; + +/* 802.11v Wireless Network Management: Timing Measurement */ +struct ACTION_UNPROTECTED_WNM_TIMING_MEAS_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Timing Measurement Management frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token */ + uint8_t ucFollowUpDialogToken; /* Follow Up Dialog Token */ + uint32_t u4ToD; /* Timestamp of Departure [10ns] */ + uint32_t u4ToA; /* Timestamp of Arrival [10ns] */ + uint8_t ucMaxToDErr; /* Maximum of ToD Error [10ns] */ + uint8_t ucMaxToAErr; /* Maximum of ToA Error [10ns] */ +} __KAL_ATTRIB_PACKED__; + +struct IE_WFA_OSEN { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucOui[3]; + uint8_t ucOuiType; + uint32_t u4GroupKeyCipherSuite; + uint16_t u2PairwiseKeyCipherSuiteCount; + uint8_t aucPairwiseKeyCipherSuite1[4]; +}; + +/* 8.5.23.4 Operating Mode Notification frame format */ +struct ACTION_OP_MODE_NOTIFICATION_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Operating Mode Notification frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucOperatingMode; /* Operating Mode */ +} __KAL_ATTRIB_PACKED__; + +/* 8.5.12.3 SM Power Save frame format */ +struct ACTION_SM_POWER_SAVE_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* SM power save frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucSmPowerCtrl; /* SM Power Control (see 8.4.1.22) */ +} __KAL_ATTRIB_PACKED__; + +/* 8.5.12.2 Notify Channel Width frame format */ +struct ACTION_NOTIFY_CHANNEL_WIDTH_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* SM power save frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucChannelWidth; /* Channel Width (see 8.4.1.21) */ +} __KAL_ATTRIB_PACKED__; + + +/* 3 Information Elements from WFA. */ +struct IE_WFA { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucOui[3]; + uint8_t ucOuiType; + uint8_t aucOuiSubTypeVersion[2]; + /*!< Please be noted. WPA defines a 16 bit field version */ + /* instead of one subtype field and one version field */ +} __KAL_ATTRIB_PACKED__; + +#if CFG_SUPPORT_PASSPOINT +/* HS20 3.1 - HS 2.0 Indication Information Element */ +struct IE_HS20_INDICATION { + uint8_t ucId; /* Element ID */ + uint8_t ucLength; /* Length */ + uint8_t aucOui[3]; /* OUI */ + uint8_t ucType; /* Type */ + uint8_t ucHotspotConfig; /* Hotspot Configuration */ +} __KAL_ATTRIB_PACKED__; +#endif /* CFG_SUPPORT_PASSPOINT */ + +/* WAPI Information element format */ +struct WAPI_INFO_ELEM { + uint8_t ucElemId; + uint8_t ucLength; + uint16_t u2Version; + uint16_t u2AuthKeyMgtSuiteCount; + uint8_t aucAuthKeyMgtSuite1[4]; +} __KAL_ATTRIB_PACKED__; + +/* Information Elements from MTK Synergies.*/ +struct IE_MTK_OUI { + uint8_t ucId; + uint8_t ucLength; + uint8_t aucOui[3]; + uint8_t aucCapability[4]; + uint8_t aucInfoElem[1]; +} __KAL_ATTRIB_PACKED__; + +struct SUB_IE_BSS_TERM_DURATION { + uint8_t ucSubId; + uint8_t ucLength; + uint8_t aucTermTsf[8]; + uint16_t u2Duration; +} __KAL_ATTRIB_PACKED__; + +struct SUB_IE_BSS_CAND_PREFERENCE { + uint8_t ucSubId; + uint8_t ucLength; + uint8_t ucPreference; +} __KAL_ATTRIB_PACKED__; + +struct ACTION_BTM_QUERY_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* BSS Coexistence Management frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + + uint8_t ucDialogToken; + uint8_t ucQueryReason; + uint8_t *pucNeighborBss; +} __KAL_ATTRIB_PACKED__; + +struct ACTION_BTM_REQ_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* BSS Coexistence Management frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + + uint8_t ucDialogToken; + uint8_t ucRequestMode; + uint16_t u2DisassocTimer; + uint8_t ucValidityInterval; + uint8_t aucOptInfo[0]; + /* Optional: Bss Termination Duration(0~12 bytes), + ** Session Information URL, Bss Transition Candidate List + */ +} __KAL_ATTRIB_PACKED__; + +struct ACTION_BTM_RSP_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* BSS Coexistence Management frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + + uint8_t ucDialogToken; + uint8_t ucStatusCode; + uint8_t ucBssTermDelay; + uint8_t aucOptInfo[0]; + /* Optional Target BSSID and Transition Candidate Entry list */ +} __KAL_ATTRIB_PACKED__; + +struct IE_MOBILITY_DOMAIN { + uint8_t ucId; /* Element ID = 54 */ + uint8_t ucLength; /* Length is 3 */ + uint16_t u2MDID; + /* Bit 0: FT over DS; Bit 1: Resource Request Protocol Capbility, + ** others: reserved + */ + uint8_t ucBitMap; +} __KAL_ATTRIB_PACKED__; + +struct IE_FAST_TRANSITION { + uint8_t ucId; /* Element ID = 55 */ + uint8_t ucLength; /* Length is variable */ + /* Bit 0 ~ Bit 7: reserved; Bit 8 ~ Bit 15: IE count + ** used to calculate MIC, 0 means No MIC + */ + uint8_t ucMicCtrl; + uint8_t aucMic[16]; /* */ + uint8_t aucANonce[32]; /* Nonce of R1KH */ + uint8_t aucSNonce[32]; /* Nonce of S1KH */ + uint8_t aucOptParam[0]; +} __KAL_ATTRIB_PACKED__; + +struct SUB_IE_FAST_TRANSITION { + uint8_t ucSubId; /* 0, 4-255: reserved; 1: R1KH-ID; 2: GTK; 3: R0KH-ID + */ + uint8_t ucLength; /* bytes, R1KH-ID: 6; GTK: 15-42; R0KH-ID: 1-48 */ + uint8_t aucData[1]; +} __KAL_ATTRIB_PACKED__; + +struct SUB_IE_GTK { + uint8_t ucSubId; /* subId=2 */ + uint8_t ucLength; /* length is 15-42 */ + uint16_t u2KeyInfo; /* Bit0-Bit1: Key ID; Bit2-Bit15: reserved */ + uint8_t ucKeyLength; + uint8_t aucRsc[8]; + uint8_t aucKey[5]; +} __KAL_ATTRIB_PACKED__; + +/* 8.5.7.4 Link Measurement Request frame format */ +struct ACTION_LM_REQUEST_FRAME { + /* Link Measurement Request MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Link Measurement Request frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token */ + uint8_t ucTxPowerUsed; /* */ + uint8_t ucTxPowerMax; /* */ + uint8_t aucInfoElem[1]; /* subelements */ +} __KAL_ATTRIB_PACKED__; + +/* 8.5.7.5 Link Measurement Report frame format */ +struct ACTION_LM_REPORT_FRAME { + /* Link Measurement Report MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* Link Measurement Report frame body */ + uint8_t ucCategory; /* Category */ + uint8_t ucAction; /* Action Value */ + uint8_t ucDialogToken; /* Dialog Token */ + uint8_t aucTpcReportIE[4]; /* */ + uint8_t ucRxAntennaID; + uint8_t ucTxAntennaID; + uint8_t ucRCPI; + uint8_t ucRSNI; + uint8_t aucInfoElem[1]; /* subelements */ +} __KAL_ATTRIB_PACKED__; + +struct IE_REQUEST { + uint8_t ucId; /* ELEM_ID_REQUEST */ + uint8_t ucLength; /* 0 to 237 */ + uint8_t aucReqIds[0]; +} __KAL_ATTRIB_PACKED__; + +struct IE_AP_CHNL_REPORT { + uint8_t ucId; /* ELEM_ID_AP_CHANNEL_REPORT */ + uint8_t ucLength; /* 1 to 237 */ + uint8_t ucOpClass; + uint8_t aucChnlList[0]; +} __KAL_ATTRIB_PACKED__; + +struct SUB_IE_REPORTING_DETAIL { + uint8_t ucSubID; /* 2 */ + uint8_t ucLength; + /* 0: No fixed length fields or elemets. 1: all fixed length fields and + ** requested IEs 2: + */ + uint8_t ucDetailValue; +} __KAL_ATTRIB_PACKED__; + +struct IE_TSPEC_BODY { + uint8_t aucTsInfo[3]; /* TS info field */ + uint16_t u2NominalMSDUSize; /* nominal MSDU size */ + uint16_t u2MaxMSDUsize; /* maximum MSDU size */ + uint32_t u4MinSvcIntv; /* minimum service interval */ + uint32_t u4MaxSvcIntv; /* maximum service interval */ + uint32_t u4InactIntv; /* inactivity interval */ + uint32_t u4SpsIntv; /* suspension interval */ + uint32_t u4SvcStartTime; /* service start time */ + uint32_t u4MinDataRate; /* minimum Data rate */ + uint32_t u4MeanDataRate; /* mean data rate */ + uint32_t u4PeakDataRate; /* peak data rate */ + uint32_t u4MaxBurstSize; /* maximum burst size */ + uint32_t u4DelayBound; /* delay bound */ + uint32_t u4MinPHYRate; /* minimum PHY rate */ + uint16_t u2Sba; /* surplus bandwidth allowance */ + uint16_t u2MediumTime; /* medium time */ +} __KAL_ATTRIB_PACKED__; + +struct WMM_ACTION_TSPEC_FRAME { + /* DELTS MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2DurationID; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* DELTS frame body */ + uint8_t ucCategory; /* Category, value is 17 */ + uint8_t ucAction; /* Action Value, value: 2, delts */ + uint8_t ucDlgToken; + uint8_t ucStatusCode; + uint8_t aucInfoElem[1]; +} __KAL_ATTRIB_PACKED__; + +#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) \ + ((int32_t)(((_rcpi) > RCPI_HIGH_BOUND ? \ + RCPI_HIGH_BOUND : (_rcpi)) >> 1) - NDBM_LOW_BOUND_FOR_RCPI) + +/* Convert the dBm to RCPI */ +#define dBm_TO_RCPI(_dbm) \ + (uint8_t)(((((int32_t)(_dbm) + NDBM_LOW_BOUND_FOR_RCPI) << 1) \ + > RCPI_HIGH_BOUND) ? RCPI_HIGH_BOUND : \ + ((((int32_t)(_dbm) + NDBM_LOW_BOUND_FOR_RCPI) << 1) \ + < RCPI_LOW_BOUND ? RCPI_LOW_BOUND : \ + (((int32_t)(_dbm) + NDBM_LOW_BOUND_FOR_RCPI) << 1))) + +/* Convert an unsigned char pointer to an information element pointer */ +#define IE_ID(fp) (((struct IE_HDR *) fp)->ucId) +#define IE_LEN(fp) (((struct IE_HDR *) fp)->ucLength) +#define IE_SIZE(fp) (ELEM_HDR_LEN + IE_LEN(fp)) + +#define SSID_IE(fp) ((struct IE_SSID *) fp) + +#define SUP_RATES_IE(fp) ((struct IE_SUPPORTED_RATE *) fp) + +#define DS_PARAM_IE(fp) ((struct IE_DS_PARAM_SET *) fp) + +#define TIM_IE(fp) ((struct IE_TIM *) fp) + +#define IBSS_PARAM_IE(fp) ((struct IE_IBSS_PARAM_SET *) fp) + +#define ERP_INFO_IE(fp) ((struct IE_ERP *) fp) + +#define EXT_SUP_RATES_IE(fp) ((struct IE_EXT_SUPPORTED_RATE *) fp) + +#define WFA_IE(fp) ((struct IE_WFA *) fp) + +#if CFG_SUPPORT_802_11D +#define COUNTRY_IE(fp) ((struct IE_COUNTRY *) fp) +#endif + +#define EXT_CAP_IE(fp) ((struct IE_EXT_CAP *) fp) + +#define HT_CAP_IE(fp) ((struct IE_HT_CAP *) fp) + +#define POWER_CAP_IE(fp) ((struct IE_POWER_CAP *) fp) + +#define SUP_CH_IE(fp) ((struct IE_SUPPORTED_CHANNELS *) fp) + +#define HT_OP_IE(fp) ((struct IE_HT_OP *) fp) + +#define VHT_CAP_IE(fp) ((struct IE_VHT_CAP *) fp) + +#define VHT_OP_IE(fp) ((struct IE_VHT_OP *) fp) + +#define OBSS_SCAN_PARAM_IE(fp) ((struct IE_OBSS_SCAN_PARAM *) fp) + +#define BSS_20_40_COEXIST_IE(fp) ((struct IE_20_40_COEXIST *) fp) + +#define SUP_OPERATING_CLASS_IE(fp) ((struct IE_SUP_OPERATING_CLASS *) fp) + +#define QUIET_IE(fp) ((struct IE_QUIET *) fp) + +#define MTK_OUI_IE(fp) ((struct IE_MTK_OUI *) fp) + +#define CSA_IE(fp) ((struct IE_CHANNEL_SWITCH *) fp) + +#define SUPPORTED_CHANNELS_IE(fp) ((struct IE_SUPPORTED_CHANNELS *)fp) +#define TIMEOUT_INTERVAL_IE(fp) ((struct IE_TIMEOUT_INTERVAL *)fp) + +#define SM_TPC_REQ_IE(fp) ((struct IE_TPC_REQ *) fp) +#define SM_TPC_REP_IE(fp) ((struct IE_TPC_REPORT *) fp) +#define SM_MEASUREMENT_REQ_IE(fp) ((struct IE_MEASUREMENT_REQ *) fp) +#define SM_MEASUREMENT_REP_IE(fp) ((struct IE_MEASUREMENT_REPORT *) fp) +#define SM_BASIC_REQ_IE(fp) ((struct SM_BASIC_REQ *) fp) + +/* The macro to check if the MAC address is B/MCAST Address */ +#define IS_BMCAST_MAC_ADDR(_pucDestAddr) \ + ((u_int8_t) (((uint8_t *)(_pucDestAddr))[0] & BIT(0))) + +/* The macro to check if the MAC address is UCAST Address */ +#define IS_UCAST_MAC_ADDR(_pucDestAddr) \ + ((u_int8_t) !(((uint8_t *)(_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((uint8_t *)pucDestIE, \ + (uint8_t *)pucSrcIE,\ + IE_SIZE(pucSrcIE)); \ + } while (FALSE) + +#define IE_FOR_EACH(_pucIEsBuf, _u2IEsBufLen, _u2Offset) \ +for ((_u2Offset) = 0; \ + ((((_u2Offset) + 2) <= (_u2IEsBufLen)) && \ + (((_u2Offset) + IE_SIZE(_pucIEsBuf)) <= (_u2IEsBufLen))); \ + (_u2Offset) += IE_SIZE(_pucIEsBuf), (_pucIEsBuf) += IE_SIZE(_pucIEsBuf)) + +#define SET_EXT_CAP(_aucField, _ucFieldLength, _ucBit) \ +do { \ + if ((_ucBit) < ((_ucFieldLength) * 8)) { \ + uint8_t *aucExtCap = (uint8_t *)(_aucField); \ + ((aucExtCap)[(_ucBit) / 8]) |= BIT((_ucBit) % 8); \ + } \ +} while (FALSE) + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _MAC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/mt66xx_reg.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/mt66xx_reg.h new file mode 100644 index 0000000000000..d97839dcf8697 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/mt66xx_reg.h @@ -0,0 +1,1117 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "mt66xx_reg.h" + * \brief The common register definition of MT6630 + * + * N/A + */ + + + +#ifndef _MT66XX_REG_H +#define _MT66XX_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 + ******************************************************************************* + */ +#ifdef MT6632 +extern struct mt66xx_hif_driver_data mt66xx_driver_data_mt6632; +#endif /* MT6632 */ +#ifdef MT7668 +extern struct mt66xx_hif_driver_data mt66xx_driver_data_mt7668; +#endif /* MT7668 */ +#ifdef MT7663 +extern struct mt66xx_hif_driver_data mt66xx_driver_data_mt7663; +#endif /* MT7663 */ +#ifdef CONNAC +extern struct mt66xx_hif_driver_data mt66xx_driver_data_connac; +#endif /* CONNAC */ +#ifdef CONNAC2X2 +extern struct mt66xx_hif_driver_data mt66xx_driver_data_connac2x2; +#endif /* CONNAC2X2 */ + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +/* 1 MT6630 MCR Definition */ + +/* 2 Host Interface */ + +/* #define TOP_CFG_BASE 0x0000 */ +#define TOP_CFG_BASE 0x80020000 +#define TOP_RGU_BASE 0x81020000 +#define TOP_CFG_AON_base 0x81021000 +#define MCU_CFG_BASE 0x80000000 + +#define TOP_HVR (TOP_CFG_BASE + 0x1000) +#define HW_VER_MASK (0xffff) +#define GET_HW_VER(p) (((p) & HW_VER_MASK)) +#define RESC_CID_MASK (0xf << 28) +#define GET_RESC_CID(p) (((p) & RESC_CID_MASK) >> 28) + +#define TOP_FVR (TOP_CFG_BASE + 0x1004) +#define FW_VER_MASK (0xff) +#define GET_FW_VER(p) (((p) & FW_VER_MASK)) + +#define TOP_HCR (TOP_CFG_BASE + 0x1008) +#define HW_CODE_MASK (0xffff) +#define GET_HW_CODE(p) (((p) & HW_CODE_MASK)) + +#define STRAP_STA (TOP_CFG_BASE + 0x1010) +#define XTAL_SEL_MASK (0x3) +#define GET_XTAL_SEL(p) (((p) & XTAL_SEL_MASK)) +#define EEPROM_SEL (1 << 2) +#define GET_EEPROM_SEL(p) (((p) & EEPROM_SEL) >> 2) +#define CO_CLOCK_SEL (1 << 8) +#define GET_CO_CLOCK_SEL(p) (((p) & CO_CLOCK_SEL) >> 8) +#define ONE_ANT (1 << 24) +#define GET_ONE_ANT(p) (((p) & ONE_ANT) >> 24) +#define USB_MODE (1 << 25) +#define GET_USB_MODE(p) (((p) & USB_MODE) >> 25) + +#define TOP_MISC2 (TOP_CFG_BASE + 0x1134) + +#define TOP_CKGEN2_CR_PMIC_CK_MANUAL (TOP_CFG_AON_base + 0x00000108) +#define TOP_CKGEN2_CR_PMIC_CK_MANUAL_MASK 0x00080000 + +#define MTK_CHIP_REV 0x00006632 + +#define WIFI_RGU_SW_SYNC0 (TOP_RGU_BASE + 0x1250) +#define WIFI_RGU_SYNC0_RDY_OFFSET (0) +#define MCU_CFG_PCIE_REMAP1 (MCU_CFG_BASE + 0x0500) +#define PCIE_REMAP1_OFFSET (18) +#define PCIE_REMAP1_MASK (BITS(18, 31)) +#define PCIE_REMAP1_BUS_ADDR (0x40000) +#define MCU_CFG_PCIE_REMAP2 (MCU_CFG_BASE + 0x0504) +#define PCIE_REMAP2_OFFSET (19) +#define PCIE_REMAP2_MASK (BITS(19, 31)) +#define PCIE_REMAP2_BUS_ADDR (0x80000) + + + +/* UMAC Register */ +#define UMAC_PLE_CR_CFG_BASE_ADDR 0x82060000 +#define UMAC_PSE_CR_CFG_BASE_ADDR 0x82068000 + +#define UMAC_PSE_PLE_CR_ADDR_DIFF \ + (UMAC_PSE_CR_CFG_BASE_ADDR - UMAC_PLE_CR_CFG_BASE_ADDR) +#define UMAC_PSE_CR_BITMAP_OFFSET 15 +#define UMAC_PSE_PLE_ADDR_DIFF_MAR(_x) \ + (_x << UMAC_PSE_CR_BITMAP_OFFSET) + + +#define UMAC_PLE_BASE_ADDRESS (0xa << 28) + +#define UMAC_PSE_BASE_ADDRESS (0xb << 28) + +#define UMAC_FID_SHIFT_16_BIT_VM_MAP 16 + +#define UMAC_BASE(_x) \ + (UMAC_PLE_CR_CFG_BASE_ADDR | (_x << UMAC_PSE_CR_BITMAP_OFFSET)) + +#define UMAC_RESET(_x) (UMAC_BASE(_x) + 0x00000000) + +#define UMAC_INT_CR4_EN_MASK(_x) (UMAC_BASE(_x) + 0x00000004) +#define UMAC_INT_CR4_STS(_x) (UMAC_BASE(_x) + 0x00000008) +#define UMAC_INT_CR4_ERR_RES(_x) (UMAC_BASE(_x) + 0x0000000C) +#define UMAC_INT_CR4_ERR_MASK(_x) (UMAC_BASE(_x) + 0x00000010) + + + +#define UMAC_PBUF_CTRL(_x) (UMAC_BASE(_x) + 0x00000014) + +#define UMAC_CHIP_ID_VER(_x) (UMAC_BASE(_x) + 0x00000018) + +#define UMAC_TIMER_CNF(_x) (UMAC_BASE(_x) + 0x0000001C) + +#define UMAC_INT_N9_EN_MASK(_x) (UMAC_BASE(_x) + 0x00000020) +#define UMAC_INT_N9_STS(_x) (UMAC_BASE(_x) + 0x00000024) +#define UMAC_INT_N9_ERR_STS(_x) (UMAC_BASE(_x) + 0x00000028) +#define UMAC_INT_N9_ERR_MASK(_x) (UMAC_BASE(_x) + 0x0000002C) +#define UMAC_IGNORE_BUSY_EN_MASK(_x) (UMAC_BASE(_x) + 0x0000038C) + +#define UMAC_RELEASE_CTRL(_x) (UMAC_BASE(_x) + 0x00000030) + +#define UMAC_HIF_REPROT(_x) (UMAC_BASE(_x) + 0x00000034) + + +#define UMAC_C_GET_FID_0(_x) (UMAC_BASE(_x) + 0x00000040) +#define UMAC_C_GET_FID_1(_x) (UMAC_BASE(_x) + 0x00000044) + +#define UMAC_C_EN_QUEUE_0(_x) (UMAC_BASE(_x) + 0x00000060) +#define UMAC_C_EN_QUEUE_1(_x) (UMAC_BASE(_x) + 0x00000064) +#define UMAC_C_EN_QUEUE_2(_x) (UMAC_BASE(_x) + 0x00000068) + + +#define UMAC_C_DE_QUEUE_0(_x) (UMAC_BASE(_x) + 0x00000080) +#define UMAC_C_DE_QUEUE_1(_x) (UMAC_BASE(_x) + 0x00000084) +#define UMAC_C_DE_QUEUE_2(_x) (UMAC_BASE(_x) + 0x00000088) +#define UMAC_C_DE_QUEUE_3(_x) (UMAC_BASE(_x) + 0x0000008C) + +#define UMAC_ALLOCATE_0(_x) (UMAC_BASE(_x) + 0x000000A0) +#define UMAC_ALLOCATE_1(_x) (UMAC_BASE(_x) + 0x000000A4) +#define UMAC_ALLOCATE_2(_x) (UMAC_BASE(_x) + 0x000000A8) + +#define UMAC_QUEUE_EMPTY(_x) (UMAC_BASE(_x) + 0x000000B0) + +/* 0x820680B4 QUEUE_EMPTY_MASK Queue empty status mask register, + * 7615 E3 eco item only PSE with this setting, but ple + */ +#define UMAC_QUEUE_EMPTY_MASK \ + (UMAC_BASE(UMAC_PSE_CFG_POOL_INDEX) + 0x000000B4) + +#define UMAC_TO_CR4_INT(_x) (UMAC_BASE(_x) + 0x000000e0) +#define UMAC_TO_N9_INT(_x) (UMAC_BASE(_x) + 0x000000f0) + + +#define UMAC_FREEPG_CNT(_x) (UMAC_BASE(_x) + 0x00000100) + +#define UMAC_FREEPG_HEAD_TAIL(_x) (UMAC_BASE(_x) + 0x00000104) + + +#define UMAC_PG_HIF0_GROUP(_x) (UMAC_BASE(_x) + 0x00000110) +#define UMAC_HIF0_PG_INFO(_x) (UMAC_BASE(_x) + 0x00000114) + +#define UMAC_PG_HIF1_GROUP(_x) (UMAC_BASE(_x) + 0x00000118) +#define UMAC_HIF1_PG_INFO(_x) (UMAC_BASE(_x) + 0x0000011C) + +#define UMAC_PG_CPU_GROUP(_x) (UMAC_BASE(_x) + 0x00000150) +#define UMAC_CPU_PG_INFO(_x) (UMAC_BASE(_x) + 0x00000154) + + +#define UMAC_PG_LMAC0_GROUP(_x) (UMAC_BASE(_x) + 0x00000170) +#define UMAC_LMAC0_PG_INFO(_x) (UMAC_BASE(_x) + 0x00000174) + +#define UMAC_PG_LMAC1_GROUP(_x) (UMAC_BASE(_x) + 0x00000178) +#define UMAC_LMAC1_PG_INFO(_x) (UMAC_BASE(_x) + 0x0000017C) + + +#define UMAC_PG_LMAC2_GROUP(_x) (UMAC_BASE(_x) + 0x00000180) +#define UMAC_LMAC2_PG_INFO(_x) (UMAC_BASE(_x) + 0x00000184) + +#define UMAC_PG_PLE_GROUP(_x) (UMAC_BASE(_x) + 0x00000190) +#define UMAC_PLE_PG_INFO(_x) (UMAC_BASE(_x) + 0x00000194) + + +#define UMAC_RL_BUF_CTRL_0(_x) (UMAC_BASE(_x) + 0x000001A0) +#define UMAC_RL_BUF_CTRL_1(_x) (UMAC_BASE(_x) + 0x000001A4) + +#define UMAC_FL_QUE_CTRL_0(_x) (UMAC_BASE(_x) + 0x000001B0) +#define UMAC_FL_QUE_CTRL_1(_x) (UMAC_BASE(_x) + 0x000001B4) +#define UMAC_FL_QUE_CTRL_2(_x) (UMAC_BASE(_x) + 0x000001B8) +#define UMAC_FL_QUE_CTRL_3(_x) (UMAC_BASE(_x) + 0x000001BC) + +#define UMAC_HIF_ENQ_PKT_NUM(_x) (UMAC_BASE(_x) + 0x000001F0) +#define UMAC_CPU_ENQ_PKT_NUM(_x) (UMAC_BASE(_x) + 0x000001F4) +#define UMAC_RLS_MSDU_PKT_NUM(_x) (UMAC_BASE(_x) + 0x000001F8) +#define UMAC_HOST_REPORT_NUM(_x) (UMAC_BASE(_x) + 0x000001FC) + +#define UMAC_PL_QUE_CTRL_0(_x) (UMAC_BASE(_x) + 0x000001C0) + +#define UMAC_TP_HIF_EN(_x) (UMAC_BASE(_x) + 0x00000200) + +#define UMAC_TP_HIF_Q_CTRL0(_x) (UMAC_BASE(_x) + 0x00000204) +#define UMAC_TP_HIF_Q_CTRL1(_x) (UMAC_BASE(_x) + 0x00000208) +#define UMAC_TP_HIF_Q_CTRL2(_x) (UMAC_BASE(_x) + 0x0000020C) + +#define UMAC_TP_HIF_ALLOC0(_x) (UMAC_BASE(_x) + 0x00000210) +#define UMAC_TP_HIF_ALLOC1(_x) (UMAC_BASE(_x) + 0x00000214) + +#define UMAC_TP_HIF_OPER0(_x) (UMAC_BASE(_x) + 0x00000218) +#define UMAC_TP_HIF_OPER1(_x) (UMAC_BASE(_x) + 0x0000021C) + + +#define UMAC_TP_LMAC_EN(_x) (UMAC_BASE(_x) + 0x00000220) + +#define UMAC_TP_LMAC_Q_CTRL0(_x) (UMAC_BASE(_x) + 0x00000224) +#define UMAC_TP_LMAC_Q_CTRL1(_x) (UMAC_BASE(_x) + 0x00000228) +#define UMAC_TP_LMAC_Q_CTRL2(_x) (UMAC_BASE(_x) + 0x0000022C) + +#define UMAC_TP_LMAC_ALLOC0(_x) (UMAC_BASE(_x) + 0x00000230) +#define UMAC_TP_LMAC_ALLOC1(_x) (UMAC_BASE(_x) + 0x00000234) + +#define UMAC_TP_LMAC_OPER0(_x) (UMAC_BASE(_x) + 0x00000238) +#define UMAC_TP_LMAC_OPER1(_x) (UMAC_BASE(_x) + 0x0000023C) + +#define UMAC_STATE_IDLE_CTL(_x) (UMAC_BASE(_x) + 0x0000024C) + +#define UMAC_DIS_STA_MAP0(_x) (UMAC_BASE(_x) + 0x00000260) +#define UMAC_DIS_STA_MAP1(_x) (UMAC_BASE(_x) + 0x00000264) +#define UMAC_DIS_STA_MAP2(_x) (UMAC_BASE(_x) + 0x00000268) +#define UMAC_DIS_STA_MAP3(_x) (UMAC_BASE(_x) + 0x0000026c) + +#define UMAC_AC0_QUEUE_EMPTY0(_x) (UMAC_BASE(_x) + 0x00000300) +#define UMAC_AC0_QUEUE_EMPTY1(_x) (UMAC_BASE(_x) + 0x00000304) +#define UMAC_AC0_QUEUE_EMPTY2(_x) (UMAC_BASE(_x) + 0x00000308) +#define UMAC_AC0_QUEUE_EMPTY3(_x) (UMAC_BASE(_x) + 0x0000030C) + +#define UMAC_AC1_QUEUE_EMPTY0(_x) (UMAC_BASE(_x) + 0x00000310) +#define UMAC_AC1_QUEUE_EMPTY1(_x) (UMAC_BASE(_x) + 0x00000314) +#define UMAC_AC1_QUEUE_EMPTY2(_x) (UMAC_BASE(_x) + 0x00000318) +#define UMAC_AC1_QUEUE_EMPTY3(_x) (UMAC_BASE(_x) + 0x0000031C) + +#define UMAC_AC2_QUEUE_EMPTY0(_x) (UMAC_BASE(_x) + 0x00000320) +#define UMAC_AC2_QUEUE_EMPTY1(_x) (UMAC_BASE(_x) + 0x00000324) +#define UMAC_AC2_QUEUE_EMPTY2(_x) (UMAC_BASE(_x) + 0x00000328) +#define UMAC_AC2_QUEUE_EMPTY3(_x) (UMAC_BASE(_x) + 0x0000032C) + +#define UMAC_AC3_QUEUE_EMPTY0(_x) (UMAC_BASE(_x) + 0x00000330) +#define UMAC_AC3_QUEUE_EMPTY1(_x) (UMAC_BASE(_x) + 0x00000334) +#define UMAC_AC3_QUEUE_EMPTY2(_x) (UMAC_BASE(_x) + 0x00000338) +#define UMAC_AC3_QUEUE_EMPTY3(_x) (UMAC_BASE(_x) + 0x0000033C) + +#define UMAC_QUEUE_EMPTY_MASK \ + (UMAC_BASE(UMAC_PSE_CFG_POOL_INDEX) + 0x000000B4) + +/* BSS PS INT */ +#define UMAC_N9_BSS_PS_INT_EN \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000000F4) +#define UMAC_N9_BSS_PS_INT_STS \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000000F8) + +/* CR for VoW and BW Ctrl */ + +#define UMAC_DRR_TABLE_CTRL0 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000388) + +#define UMAC_DRR_TABLE_WDATA0 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000340) +#define UMAC_DRR_TABLE_WDATA1 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000344) +#define UMAC_DRR_TABLE_WDATA2 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000348) +#define UMAC_DRR_TABLE_WDATA3 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x0000034C) + + +#define UMAC_DRR_TABLE_RDATA0 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000350) +#define UMAC_DRR_TABLE_RDATA1 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000354) +#define UMAC_DRR_TABLE_RDATA2 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000358) +#define UMAC_DRR_TABLE_RDATA3 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x0000035C) + + +#define UMAC_STATION_PAUSE_0 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000360) +#define UMAC_STATION_PAUSE_1 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000364) +#define UMAC_STATION_PAUSE_2 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000368) +#define UMAC_STATION_PAUSE_3 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x0000036C) +#define UMAC_VOW_ENABLE \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000370) +#define UMAC_AIR_TIME_DRR_SIZE \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000374) +#define UMAC_CHECK_TIME_TOKEN \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000378) +#define UMAC_CHECK_LENGTH_TOKEN \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x0000037C) +#define UMAC_WDRR0 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000380) +#define UMAC_WDRR1 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000384) + +#define UMAC_VOW_CTRL1 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x0000038C) + +#define UMAC_VOW_DBG_MUX \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000003A0) +#define UMAC_AIRTIME_DBG_INFO0 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000003A4) +#define UMAC_AIRTIME_DBG_INFO1 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000003A8) + +#define UMAC_BW_DBG_INFO \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000003AC) + +#define UMAC_BW_WDRR0 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000003B0) +#define UMAC_BW_WDRR1 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000003B4) +#define UMAC_BW_WDRR2 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000003B8) +#define UMAC_BW_WDRR3 \ + (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000003BC) +/* UMAC Register */ + + +#if defined(_HIF_USB) + +#define WIFI_CFG_SW_SYNC0 (TOP_CFG_BASE + 0x1128) +#define WIFI_CFG_SYNC0_RDY_OFFSET (16) + +/* UDMA register */ +#define UDMA_BASE 0x50029000 +#define UDMA_TX_QSEL (UDMA_BASE + 0x8) +#define FW_DL_EN (1 << 3) + +#define UDMA_RESET (UDMA_BASE + 0x14) + +#define UDMA_WLCFG_1 (UDMA_BASE + 0xc) +#define UDMA_WLCFG_1_TX_TMOUT_LMT_MASK (0xfffff << 8) +#define UDMA_WLCFG_1_TX_TMOUT_LMT(p) (((p) & 0xfffff) << 8) +#define UDMA_WLCFG_1_RX_AGG_PKT_LMT_MASK (0xff << 0) +#define UDMA_WLCFG_1_RX_AGG_PKT_LMT(p) (((p) & 0xff) << 0) + +#define UDMA_WLCFG_0 (UDMA_BASE + 0x18) +#define UDMA_WLCFG_0_TX_BT_SIZE_MASK (0x07 << 27) +#define UDMA_WLCFG_0_TX_BT_SIZE(p) (((p) & 0x07) << 27) +#define UDMA_WLCFG_0_RX_BT_SIZE_MASK (0x07 << 24) +#define UDMA_WLCFG_0_RX_BT_SIZE(p) (((p) & 0x07) << 24) +#define UDMA_WLCFG_0_TX_EN_MASK (0x1 << 23) +#define UDMA_WLCFG_0_TX_EN(p) (((p) & 0x1) << 23) +#define UDMA_WLCFG_0_RX_EN_MASK (0x1 << 22) +#define UDMA_WLCFG_0_RX_EN(p) (((p) & 0x1) << 22) +#define UDMA_WLCFG_0_RX_AGG_EN_MASK (0x1 << 21) +#define UDMA_WLCFG_0_RX_AGG_EN(p) (((p) & 0x1) << 21) +#define UDMA_WLCFG_0_LPK_EN_MASK (0x1 << 20) +#define UDMA_WLCFG_0_LPK_EN(p) (((p) & 0x1) << 20) +#define UDMA_WLCFG_0_RX_MPSZ_PAD0_MASK (0x1 << 18) +#define UDMA_WLCFG_0_RX_MPSZ_PAD0(p) (((p) & 0x1) << 18) +#define UDMA_WLCFG_0_RX_AGG_LMT_MASK (0xff << 8) +#define UDMA_WLCFG_0_RX_AGG_LMT(p) (((p) & 0xff) << 8) +#define UDMA_WLCFG_0_RX_AGG_TO_MASK (0xff << 0) +#define UDMA_WLCFG_0_RX_AGG_TO(p) (((p) & 0xff) << 0) + +#define PP_R_RXCUTDISP0 (0x8206C054) +#define PP_R_RXCUTDISP0_CT_EN_MASK (0x1 << 0) +#define PP_R_RXCUTDISP0_CT_EN(p) (((p) & 0x1) << 0) +#define PP_R_RXCUTDISP0_CR4_EN_MASK (0x1 << 1) +#define PP_R_RXCUTDISP0_CR4_EN(p) (((p) & 0x1) << 1) +#define PP_R_RXCUTDISP0_START_OFFSET_MASK (0x3fff << 2) +#define PP_R_RXCUTDISP0_START_OFFSET(p) (((p) & 0x3fff) << 2) +#define PP_R_RXCUTDISP0_END_OFFSET_MASK (0x3fff << 18) +#define PP_R_RXCUTDISP0_END_OFFSET(p) (((p) & 0x3fff) << 18) + + +#elif defined(_HIF_PCIE) || defined(_HIF_AXI) +#define RTC_TOP_BASE 0x0000 + +#define RTC_TOP_MISC2 (RTC_TOP_BASE + 0x1128) + +#define TOP_HIF_BASE 0x0000 +#define TOP_HW_VERSION 0x1000 +#define TOP_HW_CONTROL 0x1008 + +#define WIFI_CFG_SW_SYNC0 RTC_TOP_MISC2 +#define WIFI_CFG_SYNC0_RDY_OFFSET (16) + +#define PCIE_HIF_BASE 0x4000 +#define PCIE_NEW_HIF_BASE 0x7c030000 + +/* HIF Sys Revision */ +#define HIF_SYS_REV (PCIE_HIF_BASE + 0x0000) + +/* Check Enter Slepp Mode Register */ +#define CONN_DUMMY_CR (PCIE_HIF_BASE + 0x00A8) + +#define CONN_HIF_RST (PCIE_HIF_BASE + 0x0100) + +#define WPDMA_FIFO_TEST_MOD (PCIE_HIF_BASE + 0x0140) + +/* HIF Low Power Control Host Register */ +#define CFG_PCIE_LPCR_HOST (PCIE_HIF_BASE + 0x01F0) + +/* HIF Low Power Control Fw Register */ +#define CFG_PCIE_LPCR_FW (PCIE_HIF_BASE + 0x01F4) + +/* Interrupt Status */ +#define WPDMA_INT_STA (PCIE_HIF_BASE + 0x0200) + +/* Interrupt Mask */ +#define WPDMA_INT_MSK (PCIE_HIF_BASE + 0x0204) + +/* Global Configuration */ +#define WPDMA_GLO_CFG (PCIE_HIF_BASE + 0x0208) + +/* Pointer Reset */ +#define WPDMA_RST_PTR (PCIE_HIF_BASE + 0x020C) + +/* Configuration for WPDMA Delayed Interrupt */ +#define WPDMA_DELAY_INT_CFG (PCIE_HIF_BASE + 0x0210) + +#define MT_WPDMA_PAUSE_RX_Q (PCIE_HIF_BASE + 0x0260) + +/* TX Ring0 Control 0 */ +#define WPDMA_TX_RING0_CTRL0 (PCIE_HIF_BASE + 0x0300) + +/* TX Ring0 Control 1 */ +#define WPDMA_TX_RING0_CTRL1 (PCIE_HIF_BASE + 0x0304) + +/* TX Ring0 Control 2 */ +#define WPDMA_TX_RING0_CTRL2 (PCIE_HIF_BASE + 0x0308) + +/* TX Ring0 Control 3 */ +#define WPDMA_TX_RING0_CTRL3 (PCIE_HIF_BASE + 0x030C) + +/* RX Ring0 Control 0 */ +#define WPDMA_RX_RING0_CTRL0 (PCIE_HIF_BASE + 0x0400) + +/* RX Ring0 Control 1 */ +#define WPDMA_RX_RING0_CTRL1 (PCIE_HIF_BASE + 0x0404) + +/* RX Ring0 Control 2 */ +#define WPDMA_RX_RING0_CTRL2 (PCIE_HIF_BASE + 0x0408) + +/* RX Ring0 Control 3 */ +#define WPDMA_RX_RING0_CTRL3 (PCIE_HIF_BASE + 0x040C) + +/* TX RING more than 32bits extension */ +#define WPDMA_TX_RING0_BASE_PTR_EXT (PCIE_HIF_BASE + 0x0500) + +/* RX RING more than 32bits extension */ +#define WPDMA_RX_RING0_BASE_PTR_EXT (PCIE_HIF_BASE + 0x0580) + +#define MT_WPDMA_GLO_CFG_1 (PCIE_HIF_BASE + 0x0500) + +#define MT_WPDMA_TX_PRE_CFG (PCIE_HIF_BASE + 0x0510) + +#define MT_WPDMA_RX_PRE_CFG (PCIE_HIF_BASE + 0x0520) + +#define MT_WPDMA_ABT_CFG (PCIE_HIF_BASE + 0x0530) + +#define MT_WPDMA_ABT_CFG1 (PCIE_HIF_BASE + 0x0534) + +#define MT_PCIE_IRQ_ENABLE (PCIE_NEW_HIF_BASE + 0x0188) + +/* WPDMA_INT_STA */ +union WPDMA_INT_STA_STRUCT { + struct { + uint32_t rx_done_0:1; + uint32_t rx_done_1:1; + uint32_t err_det_int_0:1; + uint32_t err_det_int_1:1; + uint32_t tx_done:16; + uint32_t rx_coherent:1; + uint32_t tx_coherent:1; + uint32_t rx_dly_int:1; + uint32_t tx_dly_int:1; + uint32_t wf_mac_int_0:1; + uint32_t wf_mac_int_1:1; + uint32_t wf_mac_int_2:1; + uint32_t wf_mac_int_3:1; + uint32_t wf_mac_int_4:1; + uint32_t wf_mac_int_5:1; + uint32_t mcu_cmd_int:1; + uint32_t fw_clr_own:1; + } field; + + uint32_t word; +}; + +/* WPDMA_INT_MSK */ +union WPDMA_INT_MASK { + struct { + uint32_t rx_done_0:1; + uint32_t rx_done_1:1; + uint32_t err_det_int_0:1; + uint32_t err_det_int_1:1; + uint32_t tx_done:16; + uint32_t rx_coherent:1; + uint32_t tx_coherent:1; + uint32_t rx_dly_int:1; + uint32_t tx_dly_int:1; + uint32_t wf_mac_int_0:1; + uint32_t wf_mac_int_1:1; + uint32_t wf_mac_int_2:1; + uint32_t wf_mac_int_3:1; + uint32_t wf_mac_int_4:1; + uint32_t wf_mac_int_5:1; + uint32_t mcu_cmd_int:1; + uint32_t fw_clr_own:1; + } field; + + struct { + uint32_t rx_done_0:1; + uint32_t rx_done_1:1; + uint32_t err_det_int_0:1; + uint32_t err_det_int_1:1; + uint32_t tx_done:16; + uint32_t rx_coherent:1; + uint32_t tx_coherent:1; + uint32_t rx_dly_int:1; + uint32_t tx_dly_int:1; + uint32_t wpdma2host_err_int_ena:1; + uint32_t rsv_25_27:3; + uint32_t subsys_int_ena:1; + uint32_t mcu2host_sw_int_ena:1; + uint32_t rsv_30_31:2; + } field_conn; + + uint32_t word; +}; + +/* WPDMA_GLO_CFG */ +union WPDMA_GLO_CFG_STRUCT { + struct { + uint32_t EnableTxDMA:1; + uint32_t TxDMABusy:1; + uint32_t EnableRxDMA:1; + uint32_t RxDMABusy:1; + uint32_t WPDMABurstSIZE:2; + uint32_t EnTXWriteBackDDONE:1; + uint32_t BigEndian:1; + uint32_t Desc32BEn:1; + uint32_t share_fifo_en:1; + uint32_t multi_dma_en:2; + uint32_t fifo_little_endian:1; + uint32_t mi_depth:3; + uint32_t err_det_th:8; + uint32_t sw_rst:1; + uint32_t force_tx_eof:1; + uint32_t rsv_26:1; + uint32_t omit_rx_info:1; + uint32_t omit_tx_info:1; + uint32_t byte_swap:1; + uint32_t clk_gate_dis:1; + uint32_t rx_2b_offset:1; + } field; + + struct { + uint32_t EnableTxDMA:1; + uint32_t TxDMABusy:1; + uint32_t EnableRxDMA:1; + uint32_t RxDMABusy:1; + uint32_t WPDMABurstSIZE:2; + uint32_t EnTXWriteBackDDONE:1; + uint32_t BigEndian:1; + uint32_t dis_bt_size_align:1; + uint32_t tx_bt_size:1; + uint32_t multi_dma_en:2; + uint32_t fifo_little_endian:1; + uint32_t mi_depth:3; + uint32_t mi_depth_rd_3_5:3; + uint32_t mi_depth_rd_8_6:3; + uint32_t tx_bt_size_bit21:2; + uint32_t sw_rst:1; + uint32_t force_tx_eof:1; + uint32_t first_token:1; + uint32_t omit_rx_info:1; + uint32_t omit_tx_info:1; + uint32_t byte_swap:1; + uint32_t reserve_30:1; + uint32_t rx_2b_offset:1; + } field_1; + + struct { + uint32_t tx_dma_en:1; + uint32_t tx_dma_busy:1; + uint32_t rx_dma_en:1; + uint32_t rx_dma_busy:1; + uint32_t pdma_bt_size:2; + uint32_t tx_wb_ddone:1; + uint32_t big_endian:1; + uint32_t dmad_32b_en:1; + uint32_t bypass_dmashdl_txring3:1; + uint32_t multi_dma_en:2; + uint32_t fifo_little_endian:1; + uint32_t mi_depth:3; + uint32_t dfet_arb_mi_depth:3; + uint32_t pfet_arb_mi_depth:3; + uint32_t reserved22:3; + uint32_t force_tx_eof:1; + uint32_t pdma_addr_ext_en:1; + uint32_t omit_rx_info:1; + uint32_t omit_tx_info:1; + uint32_t byte_swap:1; + uint32_t clk_gate_dis:1; + uint32_t rx_2b_offset:1; + } field_conn; + + uint32_t word; +}; + +/* WPDMA_RST_PTR */ +union WPDMA_RST_IDX_STRUCT { + struct { + uint32_t RST_DTX_IDX0:1; + uint32_t RST_DTX_IDX1:1; + uint32_t rsv_2_15:14; + uint32_t RST_DRX_IDX0:1; + uint32_t RST_DRX_IDX1:1; + uint32_t rsv_18_31:14; + } field; + + uint32_t word; +}; + +/* WPDMA_DELAY_INT_CFG */ +union DELAY_INT_CFG_STRUCT { + struct { + uint32_t RXMAX_PTIME:8; + uint32_t RXMAX_PINT:7; + uint32_t RXDLY_INT_EN:1; + uint32_t TXMAX_PTIME:8; + uint32_t TXMAX_PINT:7; + uint32_t TXDLY_INT_EN:1; + } field; + + uint32_t word; +}; + +/* RTC_TOP_MISC2 */ +#define TOP_MISC2_CR4_INIT_DONE BIT(18) +#define TOP_MISC2_N9_INIT_DONE BIT(17) +#define TOP_MISC2_FW_READY BIT(16) +#define WLAN_READY_BITS BITS(16, 18) + +/* HIF_SYS_REV */ +#define PCIE_HIF_SYS_PROJ BITS(16, 31) +#define PCIE_HIF_SYS_REV BITS(0, 15) + +/* CFG_PCIE_LPCR_HOST */ +#define PCIE_LPCR_HOST_CLR_OWN BIT(1) +#define PCIE_LPCR_HOST_SET_OWN BIT(0) + +/* CFG_PCIE_LPCR_FW */ +#define PCIE_LPCR_FW_CLR_OWN BIT(0) + +/* WPDMA_INT_STA */ +#define WPDMA_FW_CLR_OWN_INT BIT(31) +#define WPDMA_TX_DONE_INT15 BIT(19) +#define WPDMA_TX_DONE_INT3 BIT(7) +#define WPDMA_TX_DONE_INT2 BIT(6) +#define WPDMA_TX_DONE_INT1 BIT(5) +#define WPDMA_TX_DONE_INT0 BIT(4) +#define WPDMA_RX_DONE_INT3 BIT(3) +#define WPDMA_RX_DONE_INT2 BIT(2) +#define WPDMA_RX_DONE_INT1 BIT(1) +#define WPDMA_RX_DONE_INT0 BIT(0) + +#else +#define WIFI_CFG_SW_SYNC0 0 +#define WIFI_CFG_SYNC0_RDY_OFFSET 0 +#endif + +/* 4 CHIP ID Register */ +#define MCR_WCIR 0x0000 + +/* 4 HIF Low Power Control Register */ +#define MCR_WHLPCR 0x0004 + +/* 4 Control Status Register */ +#define MCR_WSDIOCSR 0x0008 + +/* 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 0x0020 + +/* 4 WLAN Software Interrupt Control Register */ +#define MCR_WSICR 0x0024 + +/* 4 WLAN TX Data Register 1 */ +#define MCR_WTDR1 0x0034 + +/* 4 WLAN RX Data Register 0 */ +#define MCR_WRDR0 0x0050 + +/* 4 WLAN RX Data Register 1 */ +#define MCR_WRDR1 0x0054 + +/* 4 Host to Device Send Mailbox 0 Register */ +#define MCR_H2DSM0R 0x0070 + +/* 4 Host to Device Send Mailbox 1 Register */ +#define MCR_H2DSM1R 0x0074 + +/* 4 Device to Host Receive Mailbox 0 Register */ +#define MCR_D2HRM0R 0x0078 + +/* 4 Device to Host Receive Mailbox 1 Register */ +#define MCR_D2HRM1R 0x007c + +/* 4 Device to Host Receive Mailbox 2 Register */ +#define MCR_D2HRM2R 0x0080 + + +/* 4 WLAN RX Packet Length Register */ +#define MCR_WRPLR 0x0090 + +/* 4 Test Mode Data Port */ +#define MCR_WTMDR 0x00b0 + +/* 4 Test Mode Control Register */ +#define MCR_WTMCR 0x00b4 + +/* 4 Test Mode Data Pattern Control Register #0 */ +#define MCR_WTMDPCR0 0x00b8 + +/* 4 Test Mode Data Pattern Control Register #1 */ +#define MCR_WTMDPCR1 0x00bc + +/* 4 WLAN Packet Length Report Control Register */ +#define MCR_WPLRCR 0x00d4 + +/* 4 WLAN Snapshot Register */ +#define MCR_WSR 0x00D8 + +/* 4 Clock Pad Macro IO Control Register */ +#define MCR_CLKIOCR 0x0100 + +/* 4 Command Pad Macro IO Control Register */ +#define MCR_CMDIOCR 0x0104 + +/* 4 Data 0 Pad Macro IO Control Register */ +#define MCR_DAT0IOCR 0x0108 + +/* 4 Data 1 Pad Macro IO Control Register */ +#define MCR_DAT1IOCR 0x010C + +/* 4 Data 2 Pad Macro IO Control Register */ +#define MCR_DAT2IOCR 0x0110 + +/* 4 Data 3 Pad Macro IO Control Register */ +#define MCR_DAT3IOCR 0x0114 + +/* 4 Clock Pad Macro Delay Chain Control Register */ +#define MCR_CLKDLYCR 0x0118 + +/* 4 Command Pad Macro Delay Chain Control Register */ +#define MCR_CMDDLYCR 0x011C + +/* 4 SDIO Output Data Delay Chain Control Register */ +#define MCR_ODATDLYCR 0x0120 + +/* 4 SDIO Input Data Delay Chain Control Register 1 */ +#define MCR_IDATDLYCR1 0x0124 + +/* 4 SDIO Input Data Delay Chain Control Register 2 */ +#define MCR_IDATDLYCR2 0x0128 + +/* 4 SDIO Input Data Latch Time Control Register */ +#define MCR_ILCHCR 0x012C + +/* 4 WLAN TXQ Count Register 0 */ +#define MCR_WTQCR0 0x0130 + +/* 4 WLAN TXQ Count Register 1 */ +#define MCR_WTQCR1 0x0134 + +/* 4 WLAN TXQ Count Register 2 */ +#define MCR_WTQCR2 0x0138 + +/* 4 WLAN TXQ Count Register 3 */ +#define MCR_WTQCR3 0x013C + +/* 4 WLAN TXQ Count Register 4 */ +#define MCR_WTQCR4 0x0140 + +/* 4 WLAN TXQ Count Register 5 */ +#define MCR_WTQCR5 0x0144 + +/* 4 WLAN TXQ Count Register 6 */ +#define MCR_WTQCR6 0x0148 + +/* 4 WLAN TXQ Count Register 7 */ +#define MCR_WTQCR7 0x014C + +/* WLAN/Common PC value Debug registre */ +#define MCR_SWPCDBGR 0x0154 + +/* #if CFG_SDIO_INTR_ENHANCE */ +struct ENHANCE_MODE_DATA_STRUCT { + uint32_t u4WHISR; + union { + struct { + uint16_t u2TQ0Cnt; + uint16_t u2TQ1Cnt; + uint16_t u2TQ2Cnt; + uint16_t u2TQ3Cnt; + uint16_t u2TQ4Cnt; + uint16_t u2TQ5Cnt; + uint16_t u2TQ6Cnt; + uint16_t u2TQ7Cnt; + uint16_t u2TQ8Cnt; + uint16_t u2TQ9Cnt; + uint16_t u2TQ10Cnt; + uint16_t u2TQ11Cnt; + uint16_t u2TQ12Cnt; + uint16_t u2TQ13Cnt; + uint16_t u2TQ14Cnt; + uint16_t u2TQ15Cnt; + } u; + uint32_t au4WTSR[8]; + } rTxInfo; + union { + struct { + uint16_t u2NumValidRx0Len; + uint16_t u2NumValidRx1Len; + uint16_t au2Rx0Len[16]; + uint16_t au2Rx1Len[16]; + } u; + uint32_t au4RxStatusRaw[17]; + } rRxInfo; + uint32_t u4RcvMailbox0; + uint32_t u4RcvMailbox1; +}; +/* #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 0x00006632 +#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_DB_CMD7_RESELECT_DIS BIT(4) +#define WSDIOCSR_DB_WR_BUSY_EN BIT(3) +#define WSDIOCSR_DB_RD_BUSY_EN BIT(2) +#define WSDIOCSR_SDIO_INT_CTL BIT(1) +#define WSDIOCSR_SDIO_RE_INIT_EN BIT(0) + +/* 3 WHCR 0x000C */ +#define WHCR_RX_ENHANCE_MODE_EN BIT(16) +#define WHCR_MAX_HIF_RX_LEN_NUM BITS(8, 13) +#define WHCR_RPT_OWN_RX_PACKET_LEN BIT(3) +#define WHCR_RECV_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 8 + +/* 3 WHISR 0x0010 */ +#define WHISR_D2H_SW_INT BITS(8, 31) +#define WHISR_D2H_SW_ASSERT_INFO_INT BIT(31) +#define WHISR_D2H_WKUP_BY_RX_PACKET BIT(30) +#define WHISR_D2H_SW_RD_MAILBOX_INT BIT(29) +#define WHISR_FW_OWN_BACK_INT BIT(7) +#define WHISR_ABNORMAL_INT BIT(6) +#define WHISR_RX1_DONE_INT BIT(2) +#define WHISR_RX0_DONE_INT BIT(1) +#define WHISR_TX_DONE_INT BIT(0) + +/* 3 WHIER 0x0014 */ +#define WHIER_D2H_SW_INT BITS(8, 31) +#define WHIER_FW_OWN_BACK_INT_EN BIT(7) +#define WHIER_ABNORMAL_INT_EN BIT(6) +#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 0x0020 */ +#define WASR_FW_OWN_INVALID_ACCESS BIT(16) +#define WASR_RX1_UNDER_FLOW BIT(9) +#define WASR_RX0_UNDER_FLOW BIT(8) +#define WASR_TX1_OVER_FLOW BIT(1) + +/* 3 WSICR 0x0024 */ +#define WSICR_H2D_SW_INT_SET BITS(16, 31) + +/* 3 WRPLR 0x0090 */ +#define WRPLR_RX1_PACKET_LENGTH BITS(16, 31) +#define WRPLR_RX0_PACKET_LENGTH BITS(0, 15) + +/* 3 WTMCR 0x00b4 */ +#define WMTCR_TEST_MODE_FW_OWN BIT(24) +#define WMTCR_PRBS_INIT_VAL BITS(16, 23) +#define WMTCR_TEST_MODE_STATUS BIT(8) +#define WMTCR_TEST_MODE_SELECT BITS(0, 1) + + + +/* Support features */ +/* Options for VLAN-over-ethernet pkt to/from 802.11 LLC VLAN pkt. + * This should depend on the configurations of HW-header-translation. + */ +#define FEAT_BITS_LLC_VLAN_TX BIT(0) +#define FEAT_BITS_LLC_VLAN_RX BIT(1) + +/* Support features API */ +#define FEAT_SUP_LLC_VLAN_TX(__chip_info) \ + ((__chip_info)->features & FEAT_BITS_LLC_VLAN_TX) +#define FEAT_SUP_LLC_VLAN_RX(__chip_info) \ + ((__chip_info)->features & FEAT_BITS_LLC_VLAN_RX) + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +enum ENUM_WIFI_FUNC { + WIFI_FUNC_INIT_DONE = BIT(0), + WIFI_FUNC_N9_DONE = BIT(1), + WIFI_FUNC_NO_CR4_READY_BITS = BITS(0, 1), + WIFI_FUNC_CR4_READY = BIT(2), + WIFI_FUNC_READY_BITS = BITS(0, 2), + WIFI_FUNC_DUMMY_REQ = BIT(3) +}; + +enum enum_mt66xx_chip { + MT66XX_CHIP_6632 = 0, + MT66XX_CHIP_7666, + MT66XX_CHIP_7668, + MT66XX_CHIP_NUM +}; + +enum enum_workAround { + WORKAROUND_MT7663_BRINGUP_20171205 = 0, + WORKAROUND_NUM +}; + +struct mt66xx_chip_info { + struct BUS_INFO *bus_info; + struct FWDL_OPS_T *fw_dl_ops; + struct TX_DESC_OPS_T *prTxDescOps; +#if CFG_SUPPORT_QA_TOOL + struct ATE_OPS_T *prAteOps; +#endif + struct CHIP_DBG_OPS *prDebugOps; + + const unsigned int chip_id; /* chip id */ + const unsigned int should_verify_chip_id; /* verify chip id */ + const unsigned int sw_sync0; /* sw_sync0 address */ + const unsigned int sw_ready_bits; /* sw_sync0 ready bits */ + const unsigned int sw_ready_bit_offset; /* sw_sync0 ready bit offset */ + const unsigned int patch_addr; /* patch download start address */ + const unsigned int is_support_cr4; /* support CR4 */ + const unsigned int txd_append_size; /* hw mac txd append */ + const unsigned int rxd_size; /* hw mac rxd size */ + const unsigned int init_event_size; /* init event w/o rxd size */ + const unsigned int event_hdr_size; /* event w/o rxd size */ + const unsigned int isNicCapV1; + const unsigned int is_support_efuse; /* efuse support */ + + const struct ECO_INFO *eco_info; /* chip version table */ + uint8_t eco_ver; /* chip version */ + uint8_t ucPacketFormat; + + uint16_t u2TxInitCmdPort; + uint16_t u2TxFwDlPort; + uint16_t u2HifTxdSize; + /* Extra TXD Size for TX Byte Count field (in unit of Byte) */ + uint32_t u4ExtraTxByteCount; + uint32_t u4HifDmaShdlBaseAddr; + /* chip ip version from FW */ + uint32_t u4ChipIpVersion; + uint32_t u4ChipIpConfig; + + void (*asicCapInit)(IN struct ADAPTER *prAdapter); + void (*asicEnableFWDownload)(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnable); + uint32_t (*asicGetChipID)(IN struct ADAPTER *prAdapter); + void (*fillHifTxDesc)(IN uint8_t **pDest, IN uint16_t *pInfoBufLen); + uint32_t (*downloadBufferBin)(IN struct ADAPTER *prAdapter); + void (*showTaskStack)(IN struct task_struct *tsk, + IN unsigned long *sp); + + const uint32_t features; /* feature bits */ + u_int8_t is_support_hw_amsdu; + uint8_t ucMaxSwAmsduNum; + uint32_t workAround; + char *prTxPwrLimitFile; + uint8_t ucTxPwrLimitBatchSize; +}; + +struct mt66xx_hif_driver_data { + struct mt66xx_chip_info *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 + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/nic.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/nic.h new file mode 100644 index 0000000000000..4287d274e13fc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/nic.h @@ -0,0 +1,525 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + + +#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 + ******************************************************************************* + */ +#define PS_SYNC_WITH_FW BIT(31) + +#if CFG_SUPPORT_SER +#if defined(_HIF_USB) +#define WIFI_SER_SYNC_TIMER_TIMEOUT_IN_MS (500) +#endif /* _HIF_USB */ +#endif /* CFG_SUPPORT_SER */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +struct REG_ENTRY { + uint32_t u4Offset; + uint32_t u4Value; +}; + +struct _TABLE_ENTRY_T { + struct REG_ENTRY *pu4TablePtr; + uint16_t u2Size; +}; + +/*! INT status to event map */ +struct INT_EVENT_MAP { + uint32_t u4Int; + uint32_t u4Event; +}; + +struct ECO_INFO { + uint8_t ucHwVer; + uint8_t ucRomVer; + uint8_t ucFactoryVer; + uint8_t ucEcoVer; +}; + +enum ENUM_INT_EVENT_T { + INT_EVENT_ABNORMAL, + INT_EVENT_SW_INT, + INT_EVENT_TX, + INT_EVENT_RX, + INT_EVENT_NUM +}; + +enum ENUM_IE_UPD_METHOD { + IE_UPD_METHOD_UPDATE_RANDOM, + IE_UPD_METHOD_UPDATE_ALL, + IE_UPD_METHOD_DELETE_ALL, +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP + IE_UPD_METHOD_UPDATE_PROBE_RSP, +#endif +}; + +enum ENUM_SER_STATE { + SER_IDLE_DONE, /* SER is idle or done */ + SER_STOP_HOST_TX, /* Host HIF Tx is stopped */ + SER_STOP_HOST_TX_RX, /* Host HIF Tx/Rx is stopped */ + SER_REINIT_HIF, /* Host HIF is reinit */ + + SER_STATE_NUM +}; + +/* The bit map for the caller to set the power save flag */ +enum POWER_SAVE_CALLER { + PS_CALLER_COMMON = 0, + PS_CALLER_CTIA, + PS_CALLER_SW_WRITE, + PS_CALLER_CTIA_CAM, + PS_CALLER_P2P, + PS_CALLER_CAMCFG, + PS_CALLER_GPU, + PS_CALLER_TP, + PS_CALLER_NO_TIM, + PS_CALLER_WOW, + PS_CALLER_MAX_NUM = 24 +}; + +#if CFG_SUPPORT_SER +#if defined(_HIF_USB) +enum ENUM_SER_IPC_STATE_T { + ENUM_SER_STATE_IDLE = 0, + ENUM_SER_STATE_ERR_DET, + ENUM_SER_STATE_HIF_TRX_SUSPEND, + ENUM_SER_STATE_RESET_DONE, + ENUM_SER_STATE_HIF_TRX_RESUME, + ENUM_SER_STATE_NUM +}; +#endif /* _HIF_USB */ +#endif /* CFG_SUPPORT_SER */ + +enum ENUM_REMOVE_BY_MSDU_TPYE { + MSDU_REMOVE_BY_WLAN_INDEX = 0, + MSDU_REMOVE_BY_BSS_INDEX, + ENUM_REMOVE_BY_MSDU_TPYE_NUM +}; + +/* Test mode bitmask of disable flag */ +#define TEST_MODE_DISABLE_ONLINE_SCAN BIT(0) +#define TEST_MODE_DISABLE_ROAMING BIT(1) +#define TEST_MODE_FIXED_CAM_MODE BIT(2) +#define TEST_MODE_DISABLE_BCN_LOST_DET BIT(3) +#define TEST_MODE_NONE 0 +#define TEST_MODE_THROUGHPUT \ + (TEST_MODE_DISABLE_ONLINE_SCAN | TEST_MODE_DISABLE_ROAMING | \ + TEST_MODE_FIXED_CAM_MODE | TEST_MODE_DISABLE_BCN_LOST_DET) +#define TEST_MODE_SIGMA_AC_N_PMF \ + (TEST_MODE_DISABLE_ONLINE_SCAN | TEST_MODE_FIXED_CAM_MODE) +#define TEST_MODE_SIGMA_WMM_PS (TEST_MODE_DISABLE_ONLINE_SCAN) +/******************************************************************************* + * 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 + ******************************************************************************* + */ + +#ifdef CFG_SUPPORT_TIME_MEASURE +/* 11mc Audio Sync */ +extern uint64_t g_u8SysClkps; +extern uint64_t g_u8LastSysClkps; +extern int64_t g_i8HostClkRateDiff; +extern uint64_t g_u8NicCnt; +extern int64_t g_i8ClockOffset; +extern int64_t g_i8ClkRateDiff; +extern uint64_t g_u8LastToA; +#endif + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +#ifdef CFG_SUPPORT_TIME_MEASURE +#ifndef BIT64 +#define BIT64(n) ((uint64_t) 1 << (n)) +#define BITS64(m, n) (~(BIT64(m)-1) & ((BIT64(n) - 1) | BIT64(n))) +#endif /* BIT */ +#define AUDIO_SYNC_CLK_RATE_DIFF_DIVISOR 10000000000LL +/* CLK_RATE_DIFF normalize to CLK_RATE_DIFF per 10ms(10000000000ps) */ +#endif + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +/*----------------------------------------------------------------------------*/ +/* Routines in nic.c */ +/*----------------------------------------------------------------------------*/ +uint32_t nicAllocateAdapterMemory(IN struct ADAPTER + *prAdapter); + +void nicReleaseAdapterMemory(IN struct ADAPTER *prAdapter); + +void nicDisableInterrupt(IN struct ADAPTER *prAdapter); + +void nicEnableInterrupt(IN struct ADAPTER *prAdapter); + +uint32_t nicProcessIST(IN struct ADAPTER *prAdapter); + +uint32_t nicProcessIST_impl(IN struct ADAPTER *prAdapter, + IN uint32_t u4IntStatus); + +uint32_t nicInitializeAdapter(IN struct ADAPTER *prAdapter); + +void nicMCRInit(IN struct ADAPTER *prAdapter); + +u_int8_t nicVerifyChipID(IN struct ADAPTER *prAdapter); + +void nicpmWakeUpWiFi(IN struct ADAPTER *prAdapter); + +u_int8_t nicpmSetDriverOwn(IN struct ADAPTER *prAdapter); + +void nicpmSetFWOwn(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnableGlobalInt); + +u_int8_t nicpmSetAcpiPowerD0(IN struct ADAPTER *prAdapter); + +u_int8_t nicpmSetAcpiPowerD3(IN struct ADAPTER *prAdapter); + +#if defined(_HIF_SPI) +void nicRestoreSpiDefMode(IN struct ADAPTER *prAdapter); +#endif + +void nicProcessSoftwareInterrupt(IN struct ADAPTER + *prAdapter); + +void nicProcessAbnormalInterrupt(IN struct ADAPTER + *prAdapter); + +void nicSetSwIntr(IN struct ADAPTER *prAdapter, + IN uint32_t u4SwIntrBitmap); + +struct CMD_INFO *nicGetPendingCmdInfo(IN struct ADAPTER + *prAdapter, IN uint8_t ucSeqNum); + +struct MSDU_INFO *nicGetPendingTxMsduInfo( + IN struct ADAPTER *prAdapter, IN uint8_t ucWlanIndex, + IN uint8_t ucSeqNum); + +void nicFreePendingTxMsduInfo(IN struct ADAPTER *prAdapter, + IN uint8_t ucIndex, IN enum ENUM_REMOVE_BY_MSDU_TPYE ucFreeType); + +uint8_t nicIncreaseCmdSeqNum(IN struct ADAPTER *prAdapter); + +uint8_t nicIncreaseTxSeqNum(IN struct ADAPTER *prAdapter); + +/* Media State Change */ +uint32_t +nicMediaStateChange(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct EVENT_CONNECTION_STATUS *prConnectionStatus); + +uint32_t nicMediaJoinFailure(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN uint32_t rStatus); + +/* Utility function for channel number conversion */ +uint32_t nicChannelNum2Freq(IN uint32_t u4ChannelNum); + +uint32_t nicFreq2ChannelNum(IN uint32_t u4FreqInKHz); + +uint8_t nicGetVhtS1(IN uint8_t ucPrimaryChannel, + IN uint8_t ucBandwidth); + +/* firmware command wrapper */ +/* NETWORK (WIFISYS) */ +uint32_t nicActivateNetwork(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +uint32_t nicDeactivateNetwork(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +/* BSS-INFO */ +uint32_t nicUpdateBss(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +/* BSS-INFO Indication (PM) */ +uint32_t nicPmIndicateBssCreated(IN struct ADAPTER + *prAdapter, IN uint8_t ucBssIndex); + +uint32_t nicPmIndicateBssConnected(IN struct ADAPTER + *prAdapter, IN uint8_t ucBssIndex); + +uint32_t nicPmIndicateBssAbort(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +/* Beacon Template Update */ +uint32_t +nicUpdateBeaconIETemplate(IN struct ADAPTER *prAdapter, + IN enum ENUM_IE_UPD_METHOD eIeUpdMethod, + IN uint8_t ucBssIndex, IN uint16_t u2Capability, + IN uint8_t *aucIe, IN uint16_t u2IELen); + +uint32_t nicQmUpdateWmmParms(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +uint32_t nicSetAutoTxPower(IN struct ADAPTER *prAdapter, + IN struct CMD_AUTO_POWER_PARAM *prAutoPwrParam); + +/*----------------------------------------------------------------------------*/ +/* Calibration Control */ +/*----------------------------------------------------------------------------*/ +uint32_t nicUpdateTxPower(IN struct ADAPTER *prAdapter, + IN struct CMD_TX_PWR *prTxPwrParam); + +uint32_t nicUpdate5GOffset(IN struct ADAPTER *prAdapter, + IN struct CMD_5G_PWR_OFFSET *pr5GPwrOffset); + +uint32_t nicUpdateDPD(IN struct ADAPTER *prAdapter, + IN struct CMD_PWR_PARAM *prDpdCalResult); + +/*----------------------------------------------------------------------------*/ +/* PHY configuration */ +/*----------------------------------------------------------------------------*/ +void nicSetAvailablePhyTypeSet(IN struct ADAPTER + *prAdapter); + +/*----------------------------------------------------------------------------*/ +/* MGMT and System Service Control */ +/*----------------------------------------------------------------------------*/ +void nicInitSystemService(IN struct ADAPTER *prAdapter); + +void nicResetSystemService(IN struct ADAPTER *prAdapter); + +void nicUninitSystemService(IN struct ADAPTER *prAdapter); + +void nicInitMGMT(IN struct ADAPTER *prAdapter, + IN struct REG_INFO *prRegInfo); + +void nicUninitMGMT(IN struct ADAPTER *prAdapter); + +void +nicPowerSaveInfoMap(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN enum PARAM_POWER_MODE ePowerMode, + IN enum POWER_SAVE_CALLER ucCaller); + +uint32_t +nicConfigPowerSaveProfile(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN enum PARAM_POWER_MODE ePwrMode, + IN u_int8_t fgEnCmdEvent, IN enum POWER_SAVE_CALLER ucCaller); + +uint32_t +nicConfigPowerSaveWowProfile(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN enum PARAM_POWER_MODE ePwrMode, + IN u_int8_t fgEnCmdEvent, + IN u_int8_t fgSuspend); + +uint32_t +nicConfigProcSetCamCfgWrite(IN struct ADAPTER *prAdapter, + IN u_int8_t enabled); + +uint32_t nicEnterCtiaMode(IN struct ADAPTER *prAdapter, + u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent); + +uint32_t nicEnterTPTestMode(IN struct ADAPTER *prAdapter, + IN uint8_t ucFuncMask); + +uint32_t nicEnterCtiaModeOfScan(IN struct ADAPTER + *prAdapter, u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent); + +uint32_t nicEnterCtiaModeOfRoaming(IN struct ADAPTER + *prAdapter, u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent); + +uint32_t nicEnterCtiaModeOfCAM(IN struct ADAPTER *prAdapter, + u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent); + +uint32_t nicEnterCtiaModeOfBCNTimeout(IN struct ADAPTER + *prAdapter, u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent); + +uint32_t nicEnterCtiaModeOfAutoTxPower(IN struct ADAPTER + *prAdapter, u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent); + +uint32_t nicEnterCtiaModeOfFIFOFullNoAck(IN struct ADAPTER + *prAdapter, u_int8_t fgEnterCtia, u_int8_t fgEnCmdEvent); +/*----------------------------------------------------------------------------*/ +/* Scan Result Processing */ +/*----------------------------------------------------------------------------*/ +void +nicAddScanResult(IN struct ADAPTER *prAdapter, + IN uint8_t rMacAddr[PARAM_MAC_ADDR_LEN], + IN struct PARAM_SSID *prSsid, + IN uint16_t u2CapInfo, + IN int32_t rRssi, + IN enum ENUM_PARAM_NETWORK_TYPE eNetworkType, + IN struct PARAM_802_11_CONFIG *prConfiguration, + IN enum ENUM_PARAM_OP_MODE eOpMode, + IN uint8_t rSupportedRates[PARAM_MAX_LEN_RATES_EX], + IN uint16_t u2IELength, IN uint8_t *pucIEBuf); + +void nicFreeScanResultIE(IN struct ADAPTER *prAdapter, + IN uint32_t u4Idx); + +/*----------------------------------------------------------------------------*/ +/* Fixed Rate Hacking */ +/*----------------------------------------------------------------------------*/ +uint32_t +nicUpdateRateParams(IN struct ADAPTER *prAdapter, + IN enum ENUM_REGISTRY_FIXED_RATE eRateSetting, + IN uint8_t *pucDesiredPhyTypeSet, + IN uint16_t *pu2DesiredNonHTRateSet, + IN uint16_t *pu2BSSBasicRateSet, + IN uint8_t *pucMcsSet, IN uint8_t *pucSupMcs32, + IN uint16_t *u2HtCapInfo); + +/*----------------------------------------------------------------------------*/ +/* Write registers */ +/*----------------------------------------------------------------------------*/ +uint32_t nicWriteMcr(IN struct ADAPTER *prAdapter, + IN uint32_t u4Address, IN uint32_t u4Value); + +/*----------------------------------------------------------------------------*/ +/* Update auto rate */ +/*----------------------------------------------------------------------------*/ +uint32_t +nicRlmArUpdateParms(IN struct ADAPTER *prAdapter, + IN uint32_t u4ArSysParam0, + IN uint32_t u4ArSysParam1, IN uint32_t u4ArSysParam2, + IN uint32_t u4ArSysParam3); + +/*----------------------------------------------------------------------------*/ +/* Enable/Disable Roaming */ +/*----------------------------------------------------------------------------*/ +uint32_t nicRoamingUpdateParams(IN struct ADAPTER + *prAdapter, IN uint32_t u4EnableRoaming); + +/*----------------------------------------------------------------------------*/ +/* Link Quality Updating */ +/*----------------------------------------------------------------------------*/ +void +nicUpdateLinkQuality(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct EVENT_LINK_QUALITY_V2 *prEventLinkQuality); + +void nicUpdateRSSI(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN int8_t cRssi, + IN int8_t cLinkQuality); + +void nicUpdateLinkSpeed(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN uint16_t u2LinkSpeed); + +#if CFG_SUPPORT_RDD_TEST_MODE +uint32_t nicUpdateRddTestMode(IN struct ADAPTER *prAdapter, + IN struct CMD_RDD_CH *prRddChParam); +#endif + +/*----------------------------------------------------------------------------*/ +/* Address Setting Apply */ +/*----------------------------------------------------------------------------*/ +uint32_t nicApplyNetworkAddress(IN struct ADAPTER + *prAdapter); + +/*----------------------------------------------------------------------------*/ +/* ECO Version */ +/*----------------------------------------------------------------------------*/ +uint8_t nicGetChipSwVer(void); +uint8_t nicGetChipEcoVer(IN struct ADAPTER *prAdapter); +u_int8_t nicIsEcoVerEqualTo(IN struct ADAPTER *prAdapter, + uint8_t ucEcoVer); +u_int8_t nicIsEcoVerEqualOrLaterTo(IN struct ADAPTER + *prAdapter, uint8_t ucEcoVer); +uint8_t nicSetChipHwVer(uint8_t value); +uint8_t nicSetChipSwVer(uint8_t value); +uint8_t nicSetChipFactoryVer(uint8_t value); + +#if CFG_SUPPORT_SER +void nicSerStopTxRx(IN struct ADAPTER *prAdapter); +void nicSerStopTx(IN struct ADAPTER *prAdapter); +void nicSerStartTxRx(IN struct ADAPTER *prAdapter); +u_int8_t nicSerIsWaitingReset(IN struct ADAPTER *prAdapter); +u_int8_t nicSerIsTxStop(IN struct ADAPTER *prAdapter); +u_int8_t nicSerIsRxStop(IN struct ADAPTER *prAdapter); +void nicSerReInitBeaconFrame(IN struct ADAPTER *prAdapter); + +#if defined(_HIF_USB) +void nicSerSyncTimerHandler(IN struct ADAPTER *prAdapter, + IN unsigned long ulParam); +#endif /* _HIF_USB */ +#endif /* CFG_SUPPORT_SER */ + +#ifdef CFG_SUPPORT_TIME_MEASURE +uint64_t nicFtmRAWASCtrl(uint64_t u8SysTime); +#endif +#endif /* _NIC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/nic_rate.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/nic_rate.h new file mode 100644 index 0000000000000..19b5f37f3b61d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/nic_rate.h @@ -0,0 +1,159 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/ + * MT6620_WIFI_DRIVER_V2_3/include/nic/nic_rate.h#1 + */ + +/*! \file nic_rate.h + * \brief This file contains the rate utility function of + * IEEE 802.11 family for MediaTek 802.11 Wireless LAN Adapters. + */ + + +#ifndef _NIC_RATE_H +#define _NIC_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 + ******************************************************************************* + */ +uint32_t +nicGetPhyRateByMcsRate( + IN uint8_t ucIdx, + IN uint8_t ucBw, + IN uint8_t ucGI +); + +uint32_t +nicGetHwRateByPhyRate( + IN uint8_t ucIdx +); + +uint32_t +nicSwIndex2RateIndex( + IN uint8_t ucRateSwIndex, + OUT uint8_t *pucRateIndex, + OUT uint8_t *pucPreambleOption +); + +uint32_t +nicRateIndex2RateCode( + IN uint8_t ucPreambleOption, + IN uint8_t ucRateIndex, + OUT uint16_t *pu2RateCode +); + +uint32_t +nicRateCode2PhyRate( + IN uint16_t u2RateCode, + IN uint8_t ucBandwidth, + IN uint8_t ucGI, + IN uint8_t ucRateNss +); + +uint32_t +nicRateCode2DataRate( + IN uint16_t u2RateCode, + IN uint8_t ucBandwidth, + IN uint8_t ucGI +); + +u_int8_t +nicGetRateIndexFromRateSetWithLimit( + IN uint16_t u2RateSet, + IN uint32_t u4PhyRateLimit, + IN u_int8_t fgGetLowest, + OUT uint8_t *pucRateSwIndex +); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _NIC_RATE_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/nic_rx.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/nic_rx.h new file mode 100644 index 0000000000000..5219ce6678331 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/nic_rx.h @@ -0,0 +1,1200 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "nic_rx.h" + * \brief The declaration of the nic rx functions + * + */ + + +#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 UNIFIED_MAC_RX_FORMAT 1 + +#define MAX_SEQ_NO 4095 +#define MAX_SEQ_NO_COUNT 4096 +#define HALF_SEQ_NO_CNOUT 2048 + +#define HALF_SEQ_NO_COUNT 2048 + +#define MT6620_FIXED_WIN_SIZE 64 +#define CFG_RX_MAX_BA_ENTRY 4 +#define CFG_RX_MAX_BA_TID_NUM 8 + +#define RX_STATUS_FLAG_MORE_PACKET BIT(30) +#define RX_STATUS_CHKSUM_MASK BITS(0, 10) + +#define RX_RFB_LEN_FIELD_LEN 4 +#define RX_HEADER_OFFSET 2 + +#define RX_RETURN_INDICATED_RFB_TIMEOUT_SEC 1 + +#define RX_PROCESS_TIMEOUT 1000 + +#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 + +/* RXM Definitions */ +/* The payload format of a RX packet */ +#define RX_PAYLOAD_FORMAT_MSDU 0 +#define RX_PAYLOAD_FORMAT_FIRST_SUB_AMSDU 3 +#define RX_PAYLOAD_FORMAT_MIDDLE_SUB_AMSDU 2 +#define RX_PAYLOAD_FORMAT_LAST_SUB_AMSDU 1 + +/* HAL RX from hal_hw_def_rom.h */ +/*------------------------------------------------------------------------------ + * Cipher define + *------------------------------------------------------------------------------ + */ +#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 CIPHER_SUITE_CCMP_W_CCX 9 +#define CIPHER_SUITE_GCMP 10 + +/*------------------------------------------------------------------------------ + * Bit fields for HW_MAC_RX_DESC_T + *------------------------------------------------------------------------------ + */ + +/*! MAC RX DMA Descriptor */ +/* DW 0*/ +/* Word 0 */ +#define RX_STATUS_RX_BYTE_COUNT_MASK BITS(0, 16) +/* Word 1 */ +#define RX_STATUS_ETH_TYPE_OFFSET_MASK BITS(0, 6) +#define RX_STATUS_ETH_TYPE_OFFSET 0 +#define RX_STATUS_IP_CHKSUM BIT(7) +#define RX_STATUS_UDP_TCP_CHKSUM BIT(8) +#define RX_STATUS_GROUP_VLD_MASK BITS(9, 12) +#define RX_STATUS_GROUP_VLD_OFFSET 9 +#define RX_STATUS_PKT_TYPE_MASK BITS(13, 15) +#define RX_STATUS_PKT_TYPE_OFFSET 13 + +/* DW 1 */ +/* Byte 0 */ +#define RX_STATUS_HTC BIT(0) +#define RX_STATUS_UC2ME BIT(1) +#define RX_STATUS_MC_FRAME BIT(2) +#define RX_STATUS_BC_FRAME BIT(3) +#define RX_STATUS_BCN_WITH_BMC BIT(4) +#define RX_STATUS_BCN_WITH_UC BIT(5) +#define RX_STATUS_KEYID_MASK BITS(6, 7) +#define RX_STATUS_KEYID_OFFSET 6 + +/* Byte 1 */ +#define RX_STATUS_CHAN_FREQ_MASK BITS(0, 7) +/* Byte 2 */ +#define RX_STATUS_HEADER_LEN_MASK BITS(0, 5) +#define RX_STATUS_HEADER_OFFSET BIT(6) +#define RX_STATUS_HEADER_TRAN BIT(7) +/* Byte 3 */ +#define RX_STATUS_PAYLOAD_FORMAT_MASK BITS(0, 1) +#define RX_STATUS_PAYLOAD_FORMAT_OFFSET 0 +#define RX_STATUS_BSSID_MASK BITS(2, 7) +#define RX_STATUS_BSSID_OFFSET 2 + +/* DW 2 */ +/* Byte 1 */ +#define RX_STATUS_TID_MASK BITS(0, 3) +#define RX_STATUS_SEC_MASK BITS(4, 7) +#define RX_STATUS_SEC_OFFSET 4 +/* Byte 2-3 */ +#define RX_STATUS_SW_BIT BIT(0) +#define RX_STATUS_FLAG_FCS_ERROR BIT(1) +#define RX_STATUS_FLAG_CIPHER_MISMATCH BIT(2) +#define RX_STATUS_FLAG_CIPHER_LENGTH_MISMATCH BIT(3) +#define RX_STATUS_FLAG_ICV_ERROR BIT(4) +#define RX_STATUS_FLAG_TKIPMIC_ERROR BIT(5) +#define RX_STATUS_FLAG_LEN_MISMATCH BIT(6) +#define RX_STATUS_FLAG_DE_AMSDU_FAIL BIT(7) +#define RX_STATUS_FLAG_EXCEED_LEN BIT(8) +#define RX_STATUS_LLC_MIS BIT(9) +#define RX_STATUS_UDF_VLT BIT(10) +#define RX_STATUS_FRAG BIT(11) +#define RX_STATUS_NULL BIT(12) +#define RX_STATUS_DATA BIT(13) +#define RX_STATUS_AMPDU_SUB_FRAME BIT(14) +#define RX_STATUS_AMPDU_FORMAT BIT(15) +#define PAYLOAD_FORMAT_IS_MSDU_FRAME 0 +#define RX_STATUS_FLAG_ERROR_MASK \ + (RX_STATUS_FLAG_FCS_ERROR | RX_STATUS_FLAG_ICV_ERROR | \ + RX_STATUS_FLAG_CIPHER_LENGTH_MISMATCH) /* No TKIP MIC error */ + +/* DW 3 */ +#define RX_STATUS_RXV_SEQ_NO_MASK BITS(0, 7) +#define RX_STATUS_TCL BIT(8) +#define RX_STATUS_CLS BIT(11) +#define RX_STATUS_OFLD_MASK BITS(12, 13) +#define RX_STATUS_OFLD_OFFSET 12 +#define RX_STATUS_EAPOL_PACKET BIT(12) +#define RX_STATUS_ARP_NS_PACKET BIT(13) +#define RX_STATUS_TDLS_PACKET BITS(12, 13) +#define RX_STATUS_MGC BIT(14) +#define RX_STATUS_WOL_MASK BITS(15, 19) +#define RX_STATUS_WOL_OFFSET 15 +#define RX_STATUS_CLS_BITMAP_MASK BITS(20, 29) +#define RX_STATUS_CLS_BITMAP_OFFSET 20 +#define RX_STATUS_PF_MODE_BLACK_LIST BIT(30) +#define RX_STATUS_PF_STS_CHECKED BIT(31) + +/* DW 12 */ +#define RX_STATUS_FRAG_NUM_MASK BITS(0, 3) +#define RX_STATUS_SEQ_NUM_MASK BITS(4, 15) +#define RX_STATUS_SEQ_NUM_OFFSET 4 + +#define RX_STATUS_GROUP1_VALID BIT(0) +#define RX_STATUS_GROUP2_VALID BIT(1) +#define RX_STATUS_GROUP3_VALID BIT(2) +#define RX_STATUS_GROUP4_VALID BIT(3) + +#define RX_STATUS_FIXED_LEN 16 + +#define RX_STATUS_CHAN_FREQ_MASK_FOR_BY_PASS_MPDE BITS(0, 7) +#define RX_STATUS_FLAG_FCS_ERROR_FOR_BY_PASS_MODE BIT(16) + +/* Timing Measurement Report */ +/* DW0 Word 1 */ +#define RX_TMR_TOA_VALID BIT(11) +#define RX_TMR_TOD_VALID BIT(10) +#define RX_TMR_TYPE_MASK BITS(8, 9) +#define RX_TMR_TYPE_OFFSET 8 +#define RX_TMR_SUBTYPE_MASK BITS(4, 7) +#define RX_TMR_SUBTYPE_OFFSET 4 + +/* DW0 Byte 1*/ +#define RX_TMR_TM_FAILED BIT(2) +#define RX_TMR_NOISY_CHAN BIT(1) +#define RX_TMR_RESPONDER BIT(0) + +/* TBD */ +#define DMA_OWN_TO_HW BIT(0) +#define DMA_OWN_TO_FW_PENDING BIT(1) +#define STATUS_IS_OWN_TO_FW(flag) \ + (((flag) & DMA_OWN_TO_HW) ? FALSE : TRUE) +#define STATUS_IS_FW_PENDING(flag) \ + (((flag) & DMA_OWN_TO_FW_PENDING) ? TRUE : FALSE) + +/* DW 2 */ +#define RX_STATUS_PACKET_LENGTH_MASK BITS(0, 16) + +#define RX_STATUS_HEADER_TRAN_MASK BIT(7) +#define RX_STATUS_HEADER_TRAN_OFFSET 7 +#define RX_STATUS_HEADER_TRAN_BSS0_MASK BIT(6) +#define RX_STATUS_HEADER_TRAN_BSS0_OFFSET 6 +#define RX_STATUS_HEADER_TRAN_BSS1_MASK BIT(7) +#define RX_STATUS_HEADER_TRAN_BSS1_OFFSET 7 + +/* DW 4 */ +#define RX_STATUS_MATCH_PACKET BIT(4) + +#define RX_STATUS_HEADER_OFFSET_MASK 0xC0 +#define RX_STATUS_HEADER_OFFSET_OFFSET 6 + +/*------------------------------------------------------------------------------ + * Bit fields for HW_RX_VECTOR_DESC_T + *------------------------------------------------------------------------------ + */ +/* DW 2 */ +#define RX_VECTOR_FOR_BA_ACK BIT(7) + +/*! HIF RX DMA Descriptor */ +/* DW 2 */ +#define HIF_RX_DESC_BUFFER_LEN BITS(0, 15) +#define HIF_RX_DESC_ETHER_TYPE_OFFSET_MASK BITS(16, 23) +#define HIF_RX_DESC_ETHER_TYPE_OFFSET_OFFSET 16 +#define HIF_RX_DESC_IP_CHKSUM_CHECK BIT(24) +#define HIF_RX_DESC_TCP_UDP_CHKSUM_CHECK BIT(25) + +#define HIF_RX_DATA_QUEUE 0 +#define HIF_RX_EVENT_QUEUE 1 + +/*------------------------------------------------------------------------------ + * Bit fields for PHY Vector + *------------------------------------------------------------------------------ + */ + +/* RX Vector, 1st Cycle */ +#define RX_VT_RX_RATE_AC_MASK BITS(0, 3) +#define RX_VT_RX_RATE_MASK BITS(0, 6) +#define RX_VT_RX_RATE_OFFSET 0 +#define RX_VT_STBC_MASK BITS(7, 8) +#define RX_VT_STBC_OFFSET 7 +#define RX_VT_LDPC BIT(9) +#define RX_VT_NESS_MASK BITS(10, 11) +#define RX_VT_NESS_OFFSET 10 +#define RX_VT_RX_MODE_MASK BITS(12, 14) +#define RX_VT_RX_MODE_OFFSET 12 +#define RX_VT_RX_MODE_VHT BIT(14) +#define RX_VT_FR_MODE_MASK BITS(15, 16) +#define RX_VT_FR_MODE_OFFSET 15 +#define RX_VT_TXOP_PS_NOT_ALLOWED BIT(17) +#define RX_VT_AGGREGATION BIT(18) +#define RX_VT_SHORT_GI BIT(19) +#define RX_VT_SMOOTH BIT(20) +#define RX_VT_NO_SOUNDING BIT(21) +#define RX_VT_SOUNDING BIT(21) +#if CFG_SUPPORT_GET_MCS_INFO +#define RX_MCS_INFO_MASK BITS(0, 17) +#endif +#if 0 +/* VHT_SIG_A2[B1], not defined in MT6632 */ +#define RX_VT_SHORT_GI_NSYM BIT(22) +/* VHT_SIG_A2[B2:B3], not defined in MT6632 */ +#define RX_VT_CODING_MASK BITS(23, 24) +#define RX_VT_CODING_OFFSET 23 +#endif +#define RX_VT_NUM_RX_MASK BITS(22, 23) +#define RX_VT_NUM_RX_OFFSET 22 +#define RX_VT_LDPC_EXTRA_OFDM_SYM BIT(24) /* VHT_SIG_A2[B3] */ +#define RX_VT_SU_VHT_MU1_3_CODING BITS(25, 28) /* VHT_SIG_A2[B4:B7] */ +#define RX_VT_SU_VHT_MU1_3_CODING_OFFSET 25 +#define RX_VT_BEAMFORMED BIT(29) /* VHT_SIG_A2[B8] */ +#define RX_VT_ACID_DET_LOW BIT(30) +#define RX_VT_ACID_DET_HIGH BIT(31) + +#define RX_VT_RX_RATE_1M 0x0 +#define RX_VT_RX_RATE_2M 0x1 +#define RX_VT_RX_RATE_5M 0x2 +#define RX_VT_RX_RATE_11M 0x3 +#define RX_VT_RX_RATE_6M 0xB +#define RX_VT_RX_RATE_9M 0xF +#define RX_VT_RX_RATE_12M 0xA +#define RX_VT_RX_RATE_18M 0xE +#define RX_VT_RX_RATE_24M 0x9 +#define RX_VT_RX_RATE_36M 0xD +#define RX_VT_RX_RATE_48M 0x8 +#define RX_VT_RX_RATE_54M 0xC + +#define RX_VT_RX_RATE_MCS0 0 +#define RX_VT_RX_RATE_MCS1 1 +#define RX_VT_RX_RATE_MCS2 2 +#define RX_VT_RX_RATE_MCS3 3 +#define RX_VT_RX_RATE_MCS4 4 +#define RX_VT_RX_RATE_MCS5 5 +#define RX_VT_RX_RATE_MCS6 6 +#define RX_VT_RX_RATE_MCS7 7 +#define RX_VT_RX_RATE_MCS32 32 + +#define RX_VT_LEGACY_CCK 0 +#define RX_VT_LEGACY_OFDM 1 +#define RX_VT_MIXED_MODE 2 +#define RX_VT_GREEN_MODE 3 +#define RX_VT_VHT_MODE 4 + +#define RX_VT_LG20_HT20 0 +#define RX_VT_DL40_HT40 1 +#define RX_VT_U20 2 +#define RX_VT_L20 3 + +#define RX_VT_FR_MODE_20 0 +#define RX_VT_FR_MODE_40 1 +#define RX_VT_FR_MODE_80 2 +#define RX_VT_FR_MODE_160 3 /*BW160 or BW80+80*/ + +#define RX_VT_CCK_SHORT_PREAMBLE BIT(2) + +/* RX Vector, 2nd Cycle */ +#define RX_VT_RX_LEN_HT_MASK BITS(0, 15) +#define RX_VT_RX_LEN_LEACY_MASK BITS(0, 11) +#define RX_VT_RX_LEN_VHT_MASK BITS(0, 20) +#define RX_VT_GROUP_ID_MASK BITS(21, 26) +#define RX_VT_GROUP_ID_OFFSET 21 +#define RX_VT_GROUPID_0_MASK BITS(21, 22) /* VHT_SIG_A1[B4:B5] */ +#define RX_VT_GROUPID_0_OFFSET 21 +#define RX_VT_GROUPID_1_MASK BITS(23, 26) /* VHT_SIG_A1[B6:B9] */ +#define RX_VT_GROUPID_1_OFFSET 23 + +#define RX_VT_NSTS_MASK BITS(27, 29) +#define RX_VT_NSTS_OFFSET 27 +#define RX_VT_RX_INDICATOR BIT(30) +#define RX_VT_SEL_ANT BIT(31) /* Not use in MT7615 and MT6632 */ + +/* RX Vector, 3rd Cycle */ +#define RX_VT_PART_AID_MASK BITS(3, 11) +#define RX_VT_PART_AID_OFFSET 3 +#define RX_VT_AID_0_MASK BITS(3, 6) /* VHT_SIG_A1[B13:B16] */ +#define RX_VT_AID_0_OFFSET 3 +#define RX_VT_AID_1_MASK BITS(7, 11) /* VHT_SIG_A1[B17:B21] */ +#define RX_VT_AID_1_OFFSET 7 + + +#define RX_VT_NSTS_PART_AID_MASK BITS(0, 11) +#define RX_VT_NSTS_PART_AID_OFFSET 0 +#define RX_VT_POP_EVER_TRIG BIT(12) +#define RX_VT_FAGC_LNA_RX_MASK BITS(13, 15) +#define RX_VT_FAGC_LNA_RX_OFFSET 13 +#define RX_VT_IB_RSSI_MASK BITS(16, 23) +#define RX_VT_IB_RSSI_OFFSET 16 +#define RX_VT_WB_RSSI_MASK BITS(24, 31) +#define RX_VT_WB_RSSI_OFFSET 24 + +/* RX Vector, 4th Cycle */ +#define RX_VT_RCPI0_MASK BITS(0, 7) +#define RX_VT_RCPI0_OFFSET 0 +#define RX_VT_RCPI1_MASK BITS(8, 15) +#define RX_VT_RCPI1_OFFSET 8 +#define RX_VT_RCPI2_MASK BITS(16, 23) +#define RX_VT_RCPI2_OFFSET 16 +#define RX_VT_RCPI3_MASK BITS(24, 31) +#define RX_VT_RCPI3_OFFSET 24 + +/* RX Vector, 5th Cycle */ +#define RX_VT_FAGC_LNA_GAIN_MASK BITS(0, 2) +#define RX_VT_FAGC_LNA_GAIN_OFFSET 0 +#define RX_VT_FAGC_LPF_GAIN_MASK BITS(3, 6) +#define RX_VT_FAGC_LPF_GAIN_OFFSET 3 +#define RX_VT_OFDM_FOE_MASK BITS(7, 18) +#define RX_VT_OFDM_FOE_OFFSET 7 +#define RX_VT_LTF_PROC_TIME_MASK BITS(19, 25) +#define RX_VT_LTF_PROC_TIME_OFFSET 19 +#define RX_VT_LTF_SNR_MASK BITS(26, 31) +#define RX_VT_LTF_SNR_OFFSET 26 + +/*RX Vector, 6th Cycle*/ +#define RX_VT_NF0_MASK BITS(0, 7) +#define RX_VT_NF0_OFFSET 0 +#define RX_VT_NF1_MASK BITS(8, 15) +#define RX_VT_NF1_OFFSET 8 +#define RX_VT_NF2_MASK BITS(16, 23) +#define RX_VT_NF2_OFFSET 16 +#define RX_VT_NF3_MASK BITS(24, 31) +#define RX_VT_NF3_OFFSET 24 + +/* RX Vector Group 2, the 1st cycle */ +#define RX_VT_PRIM_ITFR_ENV BIT(0) +#define RX_VT_SEC_ITFR_ENV BIT(1) +#define RX_VT_SEC40_ITFR_ENV BIT(2) +#define RX_VT_SEC80_ITFR_ENV BIT(3) +#define RX_VT_OFDM_LQ_BPSK_MASK BITS(4, 10) +#define RX_VT_OFDM_LQ_BPSK_OFFSET 4 +#define RX_VT_OFDM_CAPACITY_LQ_MASK BITS(11, 17) +#define RX_VT_OFDM_CAPACITY_LQ_OFFSET 11 +#define RX_VT_CCK_LQ_MASK BITS(4, 13) +#define RX_VT_CCK_LQ_OFFSET 4 + +/* RX Vector Group 2, the 2nd cycle */ +#define RX_VT_DYNA_BW_IN_NON_HT_DYNA BIT(19) +#define RX_VT_CH_BW_IN_NON_HT_MASK BITS(20, 21) +#define RX_VT_CH_BW_IN_NON_HT_OFFSET 20 + +#define RX_VT_CH_BW_IN_NON_HT_CBW40 BIT(20) +#define RX_VT_CH_BW_IN_NON_HT_CBW80 BIT(21) +#define RX_VT_CH_BW_IN_NON_HT_CBW160 BITS(20, 21) + +/* RX Data Type */ +#define RX_DATA_TYPE_RX_VECTOR 0 +#define RX_DATA_TYPE_RX_DATA 1 +#define RX_DATA_TYPE_RX_EVM 2 +#define RX_DATA_TYPE_RX_AMBI 3 +#define RX_DATA_TYPE_RX_BT 4 + +/*------------------------------------------------------------------------------ + * Radiotap define + *------------------------------------------------------------------------------ + */ + +/*Radiotap VHT*/ +#define RADIOTAP_VHT_ALL_KNOWN BITS(0, 8) +#define RADIOTAP_VHT_STBC_KNOWN BIT(0) +#define RADIOTAP_VHT_TXOP_PS_NOT_ALLOWED_KNOWN BIT(1) +#define RADIOTAP_VHT_GI_KNOWN BIT(2) +#define RADIOTAP_VHT_SHORT_GI_NSYM_KNOWN BIT(3) +#define RADIOTAP_VHT_LDPC_EXTRA_OFDM_SYM_KNOWN BIT(4) +#define RADIOTAP_VHT_BEAMFORMED_KNOWN BIT(5) +#define RADIOTAP_VHT_BAND_WIDTH_KNOWN BIT(6) +#define RADIOTAP_VHT_BAND_GROUP_ID_KNOWN BIT(7) +#define RADIOTAP_VHT_BAND_PARTIAL_AID_KNOWN BIT(8) + + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +enum ENUM_RX_STATISTIC_COUNTER { + RX_MPDU_TOTAL_COUNT = 0, + RX_SIZE_ERR_DROP_COUNT, + + RX_DATA_INDICATION_COUNT, + RX_DATA_RETURNED_COUNT, + RX_DATA_RETAINED_COUNT, + + RX_DATA_REORDER_TOTAL_COUNT, + RX_DATA_REORDER_MISS_COUNT, + RX_DATA_REORDER_WITHIN_COUNT, + RX_DATA_REORDER_AHEAD_COUNT, + RX_DATA_REORDER_BEHIND_COUNT, +#if CFG_SUPPORT_RX_DYNAMIC_MCC_PRIORITY + RX_DATA_REORDER_WITHIN_COUNT_STA, + RX_DATA_REORDER_WITHIN_COUNT_P2P, +#endif /*CFG_SUPPORT_RX_DYNAMIC_MCC_PRIORITY*/ + + RX_DATA_MSDU_IN_AMSDU_COUNT, + RX_DATA_AMSDU_MISS_COUNT, + RX_DATA_AMSDU_COUNT, + + RX_DROP_TOTAL_COUNT, + + RX_NO_STA_DROP_COUNT, + RX_INACTIVE_BSS_DROP_COUNT, + RX_HS20_DROP_COUNT, + RX_LESS_SW_RFB_DROP_COUNT, + RX_DUPICATE_DROP_COUNT, + RX_MIC_ERROR_DROP_COUNT, + RX_BAR_DROP_COUNT, + RX_NO_INTEREST_DROP_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 ENUM_RX_PKT_DESTINATION { + /* to OS */ + RX_PKT_DESTINATION_HOST, + /* to TX queue for forward, AP mode */ + RX_PKT_DESTINATION_FORWARD, + /* to both TX and OS, AP mode broadcast packet */ + RX_PKT_DESTINATION_HOST_WITH_FORWARD, + /* packet to be freed */ + RX_PKT_DESTINATION_NULL, + RX_PKT_DESTINATION_NUM +}; + +/* Used for MAC RX */ +enum ENUM_MAC_RX_PKT_TYPE { + RX_PKT_TYPE_TX_STATUS = 0, + RX_PKT_TYPE_RX_VECTOR, + RX_PKT_TYPE_RX_DATA, + RX_PKT_TYPE_DUP_RFB, + RX_PKT_TYPE_TM_REPORT, + RX_PKT_TYPE_MSDU_REPORT = 6, + RX_PKT_TYPE_SW_DEFINED = 7 +}; + +enum ENUM_MAC_RX_GROUP_VLD { + RX_GROUP_VLD_1 = 0, + RX_GROUP_VLD_2, + RX_GROUP_VLD_3, + RX_GROUP_VLD_4, + RX_GROUP_VLD_NUM +}; + +enum ENUM_MAC_GI_INFO { + MAC_GI_NORMAL = 0, + MAC_GI_SHORT +}; + +enum ENUM_RXPI_MODE { + RCPI_MODE_WF0 = 0, + RCPI_MODE_WF1, + RCPI_MODE_WF2, + RCPI_MODE_WF3, + RCPI_MODE_AVG, + RCPI_MODE_MAX, + RCPI_MODE_MIN, + RCPI_MODE_NUM +}; + +#define RXM_RXD_PKT_TYPE_SW_BITMAP 0xE00F +#define RXM_RXD_PKT_TYPE_SW_EVENT 0xE000 +#define RXM_RXD_PKT_TYPE_SW_FRAME 0xE001 + +/* AMPDU data frame with no errors including + * FC/FM/I/T/LM/DAF/EL/LLC-MIS/ UDFVLT and Class 3 error + */ +#define RXS_DW2_AMPDU_nERR_BITMAP 0xFFFB /* ignore CM bit (2) 0xFFFF */ +#define RXS_DW2_AMPDU_nERR_VALUE 0x0000 +/* no error including FC/CLM/I/T/LM/DAF/EL/HTF */ +#define RXS_DW2_RX_nERR_BITMAP 0x03FA /* ignore CM bit (2) 0x03FE */ +#define RXS_DW2_RX_nERR_VALUE 0x0000 +/* Non-Data frames */ +#define RXS_DW2_RX_nDATA_BITMAP 0x3000 +#define RXS_DW2_RX_nDATA_VALUE 0x2000 +/* Claas Error */ +#define RXS_DW2_RX_CLASSERR_BITMAP 0x0001 +#define RXS_DW2_RX_CLASSERR_VALUE 0x0001 +/* Fragmentation */ +#define RXS_DW2_RX_FRAG_BITMAP 0x3800 +#define RXS_DW2_RX_FRAG_VALUE 0x0800 + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/*! A data structure which is identical with MAC RX DMA Descriptor */ +struct HW_MAC_RX_DESC { + uint16_t u2RxByteCount; /* DW 0 */ + uint16_t u2PktTYpe; + uint8_t ucMatchPacket; /* DW 1 */ + uint8_t ucChanFreq; + uint8_t ucHeaderLen; + uint8_t ucBssid; + uint8_t ucWlanIdx; /* DW 2 */ + uint8_t ucTidSecMode; + uint16_t u2StatusFlag; + uint32_t u4PatternFilterInfo; /* DW 3 */ + uint32_t u4PatternFilterInfo2; /* DW 4 */ +}; + +struct HW_MAC_RX_STS_GROUP_1 { + uint8_t aucPN[16]; +}; + +struct HW_MAC_RX_STS_GROUP_2 { + uint32_t u4Timestamp; /* DW 12 */ + uint32_t u4CRC; /* DW 13 */ +}; + +struct HW_MAC_RX_STS_GROUP_4 { + /* For HDR_TRAN */ + uint16_t u2FrameCtl; /* DW 4 */ + uint8_t aucTA[6]; /* DW 4~5 */ + uint16_t u2SeqFrag; /* DW 6 */ + uint16_t u2Qos; /* DW 6 */ + uint32_t u4HTC; /* DW 7 */ +}; + +struct HW_MAC_RX_STS_GROUP_3 { + /*! RX Vector Info */ + uint32_t u4RxVector[6]; /* DW 14~19 */ +}; + +struct HW_MAC_RX_TMRI_PKT_FORMAT { + uint8_t ucPID; + uint8_t ucStatus; + uint16_t u2PktTYpe; + uint32_t u4Reserved[2]; + uint32_t u4ToA; + uint32_t u4ToD; +}; + +struct HW_MAC_RX_TMRR_PKT_FORMAT { + uint8_t ucVtSeq; + uint8_t ucStatus; + uint16_t u2PktTYpe; + uint8_t aucTALow[2]; + uint16_t u2SnField; + uint8_t aucTAHigh[4]; + uint32_t u4ToA; + uint32_t u4ToD; +}; + +/*! A data structure which is identical with MAC RX Vector DMA Descriptor */ +struct HW_RX_VECTOR_DESC { + uint8_t aucTA[6]; /* DW 0~1 */ + uint8_t ucRxVtSeqNo; + /*! RX Vector Info */ + uint32_t u4RxVector[9]; /* DW 2~10 */ + +}; + +union HW_MAC_MSDU_TOKEN_T { + struct { + uint16_t u2MsduID[2]; + } rFormatV1; + struct { + uint16_t u2MsduID; + uint16_t u2WlanID:10; + uint16_t u2Rsv:1; + uint16_t u2QueIdx:5; + } rFormatV2; +}; + +struct HW_MAC_MSDU_REPORT { + /* DW 0 */ + uint32_t u2BufByteCount:16; + uint32_t u2MsduCount:7; + uint32_t u2DoneEventType:6; + uint32_t u2PktType:3; + /* DW 1 */ + uint32_t u4TxdCount:8; + uint32_t u4Rsv1:8; + uint32_t u4Ver:3; + uint32_t u4Rsv2:13; + /* MSDU token array */ + union HW_MAC_MSDU_TOKEN_T au4MsduToken[0]; +}; + +struct SW_RFB { + struct QUE_ENTRY rQueEntry; + void *pvPacket; /*!< ptr to rx Packet Descriptor */ + uint8_t *pucRecvBuff; /*!< ptr to receive data buffer */ + + /* add fot mt6630 */ + uint8_t ucGroupVLD; + uint16_t u2RxStatusOffst; + struct HW_MAC_RX_DESC *prRxStatus; + struct HW_MAC_RX_STS_GROUP_1 *prRxStatusGroup1; + struct HW_MAC_RX_STS_GROUP_2 *prRxStatusGroup2; + struct HW_MAC_RX_STS_GROUP_3 *prRxStatusGroup3; + struct HW_MAC_RX_STS_GROUP_4 *prRxStatusGroup4; + + /* rx data information */ + void *pvHeader; + uint16_t u2PacketLen; + uint16_t u2HeaderLen; + + uint8_t *pucPayload; + uint16_t u2PayloadLength; + + struct STA_RECORD *prStaRec; + + uint8_t ucPacketType; + + /* rx sta record */ + uint8_t ucWlanIdx; + uint8_t ucStaRecIdx; + + u_int8_t fgReorderBuffer; + u_int8_t fgDataFrame; + u_int8_t fgFragFrame; + /* duplicate detection */ + uint16_t u2FrameCtrl; + uint16_t u2SequenceControl; + uint16_t u2SSN; + uint8_t ucTid; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + uint32_t u4TcpUdpIpCksStatus; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + enum ENUM_CSUM_RESULT aeCSUM[CSUM_TYPE_NUM]; + enum ENUM_RX_PKT_DESTINATION eDst; + /* only valid when eDst == FORWARD */ + enum ENUM_TRAFFIC_CLASS_INDEX eTC; +#if 0 + /* RX reorder for one MSDU in AMSDU issue */ + /*QUE_T rAmsduQue;*/ +#endif + uint64_t rIntTime; +}; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +struct RX_CSO_REPORT_T { + uint32_t u4IpV4CksStatus:1; + uint32_t u4Reserved1:1; + uint32_t u4TcpCksStatus:1; + uint32_t u4UdpCksStatus:1; + uint32_t u4IpV4CksType:1; + uint32_t u4IpV6CksType:1; + uint32_t u4TcpCksType:1; + uint32_t u4UdpCksType:1; + uint32_t u4IpDataLenMismatch:1; + uint32_t u4IpFragPkg:1; + uint32_t u4UnknowNextHeader:1; + uint32_t u4Reserved2:21; +}; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +/*! RX configuration type structure */ +struct RX_CTRL { + uint32_t u4RxCachedSize; + uint8_t *pucRxCached; + struct QUE rFreeSwRfbList; + struct QUE rReceivedRfbList; + struct QUE rIndicatedRfbList; + +#if CFG_SDIO_RX_AGG + uint8_t *pucRxCoalescingBufPtr; +#endif + + void *apvIndPacket[CFG_RX_MAX_PKT_NUM]; + void *apvRetainedPacket[CFG_RX_MAX_PKT_NUM]; + + uint8_t ucNumIndPacket; + uint8_t ucNumRetainedPacket; + /*!< RX Counters */ + uint64_t au8Statistics[RX_STATISTIC_COUNTER_NUM]; + +#if CFG_HIF_STATISTICS + uint32_t u4TotalRxAccessNum; + uint32_t u4TotalRxPacketNum; +#endif + +#if CFG_HIF_RX_STARVATION_WARNING + uint32_t u4QueuedCnt; + uint32_t u4DequeuedCnt; +#endif + +#if CFG_RX_PKTS_DUMP + uint32_t u4RxPktsDumpTypeMask; +#endif + +#if CFG_SUPPORT_SNIFFER + uint32_t u4AmpduRefNum; +#endif + + /* Store SysTime of Last Rx */ + uint32_t u4LastRxTime; +}; + +struct RX_MAILBOX { + uint32_t u4RxMailbox[2]; /* for Device-to-Host Mailbox */ +}; + +typedef uint32_t(*PROCESS_RX_MGT_FUNCTION) (struct ADAPTER *, struct SW_RFB *); + +typedef void(*PROCESS_RX_EVENT_FUNCTION) (struct ADAPTER *, + struct WIFI_EVENT *); + +struct RX_EVENT_HANDLER { + enum ENUM_EVENT_ID eEID; + PROCESS_RX_EVENT_FUNCTION pfnHandler; +}; + +struct EMU_MAC_RATE_INFO { + uint8_t ucPhyRateCode; + uint32_t u4PhyRate[4][2]; +}; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +#define RATE_INFO(_RateCode, _Bw20, _Bw20SGI, _Bw40, _BW40SGI, \ + _Bw80, _Bw80SGI, _Bw160, _Bw160SGI) \ + { \ + .ucPhyRateCode = (_RateCode), \ + .u4PhyRate[RX_VT_FR_MODE_20][MAC_GI_NORMAL] = (_Bw20), \ + .u4PhyRate[RX_VT_FR_MODE_20][MAC_GI_SHORT] = (_Bw20SGI), \ + .u4PhyRate[RX_VT_FR_MODE_40][MAC_GI_NORMAL] = (_Bw40), \ + .u4PhyRate[RX_VT_FR_MODE_40][MAC_GI_SHORT] = (_BW40SGI), \ + .u4PhyRate[RX_VT_FR_MODE_80][MAC_GI_NORMAL] = (_Bw80), \ + .u4PhyRate[RX_VT_FR_MODE_80][MAC_GI_SHORT] = (_Bw80SGI), \ + .u4PhyRate[RX_VT_FR_MODE_160][MAC_GI_NORMAL] = (_Bw160), \ + .u4PhyRate[RX_VT_FR_MODE_160][MAC_GI_SHORT] = (_Bw160SGI), \ + } + +#define RX_INC_CNT(prRxCtrl, eCounter) \ + {((struct RX_CTRL *)prRxCtrl)->au8Statistics[eCounter]++; } + +#define RX_ADD_CNT(prRxCtrl, eCounter, u8Amount) \ + {((struct RX_CTRL *)prRxCtrl)->au8Statistics[eCounter] += \ + (uint64_t)u8Amount; } + +#define RX_GET_CNT(prRxCtrl, eCounter) \ + (((struct RX_CTRL *)prRxCtrl)->au8Statistics[eCounter]) + +#define RX_RESET_ALL_CNTS(prRxCtrl) \ + {kalMemZero(&prRxCtrl->au8Statistics[0], \ + sizeof(prRxCtrl->au8Statistics)); } + +#define RX_STATUS_TEST_MORE_FLAG(flag) \ + ((u_int8_t)((flag & RX_STATUS_FLAG_MORE_PACKET) ? TRUE : FALSE)) + +/*------------------------------------------------------------------------------ + * MACRO for HW_MAC_RX_DESC_T + *------------------------------------------------------------------------------ + */ +/* DW 0 */ +#define HAL_RX_STATUS_GET_RX_BYTE_CNT(_prHwMacRxDesc) \ + ((_prHwMacRxDesc)->u2RxByteCount) +#define HAL_RX_STATUS_GET_ETH_TYPE_OFFSET(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2PktTYpe & RX_STATUS_ETH_TYPE_OFFSET_MASK) >> \ + RX_STATUS_ETH_TYPE_OFFSET) +#define HAL_RX_STATUS_GET_GROUP_VLD(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2PktTYpe & RX_STATUS_GROUP_VLD_MASK) >> \ + RX_STATUS_GROUP_VLD_OFFSET) +#define HAL_RX_STATUS_GET_PKT_TYPE(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2PktTYpe & RX_STATUS_PKT_TYPE_MASK) \ + >> RX_STATUS_PKT_TYPE_OFFSET) + +/* DW 1 */ +#define HAL_RX_STATUS_IS_HTC_EXIST(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_HTC)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_UC2ME(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_UC2ME) \ + ? TRUE : FALSE) +#define HAL_RX_STATUS_IS_MC(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_MC_FRAME)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_BC(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_BC_FRAME)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_BCN_WITH_BMC(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_BCN_WITH_BMC)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_BCN_WITH_UC(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_BCN_WITH_UC)?TRUE:FALSE) +#define HAL_RX_STATUS_GET_KEY_ID(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_KEYID_MASK) >> \ + RX_STATUS_KEYID_OFFSET) +#define HAL_RX_STATUS_GET_CHAN_FREQ(_prHwMacRxDesc) \ + ((_prHwMacRxDesc)->ucChanFreq) +#define HAL_RX_STATUS_GET_HEADER_LEN(_prHwMacRxDesc) \ + ((_prHwMacRxDesc)->ucHeaderLen & RX_STATUS_HEADER_LEN_MASK) +#define HAL_RX_STATUS_IS_HEADER_OFFSET(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucHeaderLen & RX_STATUS_HEADER_OFFSET)?TRUE:FALSE) +#define HAL_RX_STATUS_GET_HEADER_OFFSET(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucHeaderLen & RX_STATUS_HEADER_OFFSET) ? 2 : 0) +#define HAL_RX_STATUS_IS_HEADER_TRAN(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucHeaderLen & RX_STATUS_HEADER_TRAN)?TRUE:FALSE) +#define HAL_RX_STATUS_GET_HEADER_TRAN(_prHwMacRxDesc) \ + HAL_RX_STATUS_IS_HEADER_TRAN(_prHwMacRxDesc) +#define HAL_RX_STATUS_GET_PAYLOAD_FORMAT(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucBssid & RX_STATUS_PAYLOAD_FORMAT_MASK) >> \ + RX_STATUS_PAYLOAD_FORMAT_OFFSET) +#define HAL_RX_STATUS_GET_BSSID(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucBssid & RX_STATUS_BSSID_MASK) >> \ + RX_STATUS_BSSID_OFFSET) + +/* DW 2 */ +#define HAL_RX_STATUS_GET_WLAN_IDX(_prHwMacRxDesc) \ + ((_prHwMacRxDesc)->ucWlanIdx) +#define HAL_RX_STATUS_GET_TID(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucTidSecMode & RX_STATUS_TID_MASK)) +#define HAL_RX_STATUS_GET_SEC_MODE(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucTidSecMode & RX_STATUS_SEC_MASK) >> \ + RX_STATUS_SEC_OFFSET) +#define HAL_RX_STATUS_GET_SW_BIT(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_SW_BIT)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_FCS_ERROR(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_FCS_ERROR)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_CIPHER_MISMATCH(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_CIPHER_MISMATCH) \ + ? TRUE : FALSE) +#define HAL_RX_STATUS_IS_CLM_ERROR(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & \ + RX_STATUS_FLAG_CIPHER_LENGTH_MISMATCH) \ + ? TRUE : FALSE) +#define HAL_RX_STATUS_IS_ICV_ERROR(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_ICV_ERROR)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_TKIP_MIC_ERROR(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_TKIPMIC_ERROR) > 0 \ + ? TRUE : FALSE) +#define HAL_RX_STATUS_IS_ERROR(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_ERROR_MASK) \ + ? TRUE : FALSE) +#define HAL_RX_STATUS_IS_LEN_MISMATCH(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_LEN_MISMATCH) \ + ? TRUE : FALSE) +#define HAL_RX_STATUS_IS_DE_AMSDU_FAIL(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_DE_AMSDU_FAIL) \ + ? TRUE : FALSE) +#define HAL_RX_STATUS_IS_EXCEED_LEN(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_EXCEED_LEN) \ + ? TRUE : FALSE) +#define HAL_RX_STATUS_IS_LLC_MIS(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_LLC_MIS)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_UDF_VLT(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_UDF_VLT)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_FRAG(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FRAG)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_NULL(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_NULL)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_DATA(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_DATA)?FALSE:TRUE) +#define HAL_RX_STATUS_IS_AMPDU_SUB_FRAME(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_AMPDU_SUB_FRAME) \ + ? FALSE : TRUE) +#define HAL_RX_STATUS_IS_AMPDU_FORMAT(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_AMPDU_FORMAT)?FALSE:TRUE) + +/* DW 3 */ +#define HAL_RX_STATUS_IS_RV_VALID(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_RXV_SEQ_NO_MASK) \ + ? TRUE : FALSE) +#define HAL_RX_STATUS_GET_RXV_SEQ_NO(_prHwMacRxDesc) \ + ((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_RXV_SEQ_NO_MASK) +#define HAL_RX_STATUS_GET_TCL(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_TCL)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_CLS(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_CLS)?TRUE:FALSE) +#define HAL_RX_STATUS_GET_OFLD(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_OFLD_MASK) >> \ + RX_STATUS_OFLD_OFFSET) +#define HAL_RX_STATUS_IS_MGC(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_MGC)?TRUE:FALSE) +#define HAL_RX_STATUS_GET_WOL(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_WOL_MASK) >> \ + RX_STATUS_WOL_OFFSET) +#define HAL_RX_STATUS_GET_CLS_BITMAP(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_CLS_BITMAP_MASK) \ + >> RX_STATUS_CLS_BITMAP_OFFSET) +#define HAL_RX_STATUS_IS_PF_BLACK_LIST(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo \ + & RX_STATUS_PF_MODE_BLACK_LIST) ? TRUE : FALSE) +#define HAL_RX_STATUS_IS_PF_CHECKED(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_PF_STS_CHECKED) \ + ? TRUE : FALSE) + +/* DW 4~7 */ +#define HAL_RX_STATUS_GET_FRAME_CTL_FIELD(_prHwMacRxStsGroup4) \ + ((_prHwMacRxStsGroup4)->u2FrameCtl) +#define HAL_RX_STATUS_GET_TA(_prHwMacRxStsGroup4, pucTA) \ +{\ + kalMemCopy(pucTA, &(_prHwMacRxStsGroup4)->aucTA[0], 6); \ +} +#define HAL_RX_STATUS_GET_SEQ_FRAG_NUM(_prHwMacRxStsGroup4) \ + ((_prHwMacRxStsGroup4)->u2SeqFrag) +#define HAL_RX_STATUS_GET_QOS_CTL_FIELD(_prHwMacRxStsGroup4) \ + ((_prHwMacRxStsGroup4)->u2Qos) + +#define HAL_RX_STATUS_GET_SEQFrag_NUM(_prHwMacRxStsGroup4) \ + ((_prHwMacRxStsGroup4)->u2SeqFrag) +#define HAL_RX_STATUS_GET_HTC(_prHwMacRxStsGroup4) \ + ((_prHwMacRxStsGroup4)->u4HTC) + +/* DW 8~11 */ +#define HAL_RX_STATUS_GET_RSC(_prHwMacRxStsGroup1, pucRSC) \ +{\ + kalMemCopy(pucRSC, &(_prHwMacRxStsGroup1)->aucPN[0], 6); \ +} + +#define HAL_RX_STATUS_GET_PN(_prHwMacRxStsGroup1, pucPN) \ +{\ + kalMemCopy(pucPN, &(_prHwMacRxStsGroup1)->aucPN[0], 16); \ +} + +/* DW 12~13 */ +#define HAL_RX_STATUS_GET_TIMESTAMP(_prHwMacRxStsGroup2, _ucIdx) \ + ((_prHwMacRxStsGroup2)->u4Timestamp) +#define HAL_RX_STATUS_GET_FCS32(_prHwMacRxStsGroup2) \ + ((_prHwMacRxStsGroup2)->u4CRC) + +/* DW 14~19 */ +#define HAL_RX_STATUS_GET_RX_VECTOR(_prHwMacRxStsGroup3, _ucIdx) \ + ((_prHwMacRxStsGroup3)->u4RxVector[_ucIdx]) + +#define HAL_RX_STATUS_GET_RX_NUM(_prHwMacRxStsGroup3) \ + (((_prHwMacRxStsGroup3)->u4RxVector[0] & RX_VT_NUM_RX_MASK) >> \ + RX_VT_NUM_RX_OFFSET) + +#define HAL_RX_STATUS_GET_RCPI0(_prHwMacRxStsGroup3) \ + (((_prHwMacRxStsGroup3)->u4RxVector[3] & RX_VT_RCPI0_MASK) >> \ + RX_VT_RCPI0_OFFSET) +#define HAL_RX_STATUS_GET_RCPI1(_prHwMacRxStsGroup3) \ + (((_prHwMacRxStsGroup3)->u4RxVector[3] & RX_VT_RCPI1_MASK) >> \ + RX_VT_RCPI1_OFFSET) + +#if CFG_RCPI_COMPENSATION +#define RX_STS_GRUOP_SET_FIELD(_prHwMacRxStsGroup, _value, _mask, _offset) \ +{\ + (_prHwMacRxStsGroup) &= ~(_mask); \ + (_prHwMacRxStsGroup) |= (((_value) << (_offset)) & (_mask)); \ +} + +#define HAL_RX_STATUS_SET_RCPI0(_prHwMacRxStsGroup3, ucRcpi0) \ + RX_STS_GRUOP_SET_FIELD(((_prHwMacRxStsGroup3)->u4RxVector[3]), \ + ((u_int8_t)ucRcpi0), RX_VT_RCPI0_MASK, RX_VT_RCPI0_OFFSET) + +#define HAL_RX_STATUS_SET_RCPI1(_prHwMacRxStsGroup3, ucRcpi1) \ + RX_STS_GRUOP_SET_FIELD(((_prHwMacRxStsGroup3)->u4RxVector[3]), \ + ((u_int8_t)ucRcpi1), RX_VT_RCPI1_MASK, RX_VT_RCPI1_OFFSET) +#endif + +/* TBD */ +#define HAL_RX_STATUS_GET_RX_PACKET_LEN(_prHwMacRxDesc) +#define HAL_RX_STATUS_IS_MATCH_PACKET(_prHwMacRxDesc) + +#define HAL_RX_STATUS_GET_CHNL_NUM(_prHwMacRxDesc) \ + ((((_prHwMacRxDesc)->ucChanFreq) > HW_CHNL_NUM_MAX_4G_5G) ? \ + (((_prHwMacRxDesc)->ucChanFreq) - HW_CHNL_NUM_MAX_4G_5G) : \ + ((_prHwMacRxDesc)->ucChanFreq)) + +/* To do: support more bands other than 2.4G and 5G */ +#define HAL_RX_STATUS_GET_RF_BAND(_prHwMacRxDesc) \ + ((((_prHwMacRxDesc)->ucChanFreq) <= HW_CHNL_NUM_MAX_2G4) ? \ + BAND_2G4 : BAND_5G) + +/*------------------------------------------------------------------------------ + * MACRO for HW_RX_VECTOR_DESC_T + *------------------------------------------------------------------------------ + */ +#define HAL_RX_VECTOR_GET_TA(_prHwRxVector, pucTA) \ +{\ + kalMemCopy(pucTA, &(_prHwRxVector)->aucTA[0], 6); \ +} + +#define HAL_RX_VECTOR_GET_SEQ_NO(_prHwRxVector) \ + ((_prHwRxVector)->ucRxVtSeqNo & RX_STATUS_RXV_SEQ_NO_MASK) +#define HAL_RX_VECTOR_IS_FOR_BA_ACK(_prHwRxVector) \ + (((_prHwRxVector)->ucRxVtSeqNo & RX_VECTOR_FOR_BA_ACK)?TRUE:FALSE) +#define HAL_RX_VECTOR_GET_RX_VECTOR(_prHwRxVector, _ucIdx) \ + ((_prHwRxVector)->u4RxVector[_ucIdx]) + +#define RXM_IS_QOS_DATA_FRAME(_u2FrameCtrl) \ + (((_u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_QOS_DATA) \ + ? TRUE : FALSE) + +#define RXM_IS_DATA_FRAME(_u2FrameCtrl) \ + (((_u2FrameCtrl & MASK_FC_TYPE) == MAC_FRAME_TYPE_DATA) ? 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 struct ADAPTER *prAdapter); + +void nicRxUninitialize(IN struct ADAPTER *prAdapter); + +void nicRxProcessRFBs(IN struct ADAPTER *prAdapter); + +void nicRxProcessMsduReport(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb); + +uint32_t nicRxSetupRFB(IN struct ADAPTER *prAdapter, IN struct SW_RFB *prRfb); + +void nicRxReturnRFB(IN struct ADAPTER *prAdapter, IN struct SW_RFB *prRfb); + +void nicProcessRxInterrupt(IN struct ADAPTER *prAdapter); + +void nicRxProcessPktWithoutReorder(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +void nicRxProcessForwardPkt(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +void nicRxProcessGOBroadcastPkt(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +bool nicRxFillRFB(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb); + +struct SW_RFB *nicRxDefragMPDU(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSWRfb, OUT struct QUE *prReturnedQue); + +u_int8_t nicRxIsDuplicateFrame(IN OUT struct SW_RFB *prSwRfb); + +void nicRxProcessMonitorPacket(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb); + +void nicRxProcessDataPacket(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb); + +void nicRxProcessEventPacket(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb); + +void nicRxProcessMgmtPacket(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +void nicRxFillChksumStatus(IN struct ADAPTER *prAdapter, + IN OUT struct SW_RFB *prSwRfb); + +void nicRxUpdateCSUMStatistics(IN struct ADAPTER *prAdapter, + IN const enum ENUM_CSUM_RESULT aeCSUM[]); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +void nicRxQueryStatus(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuffer, OUT uint32_t *pu4Count); + +void nicRxClearStatistics(IN struct ADAPTER *prAdapter); + +void nicRxQueryStatistics(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuffer, OUT uint32_t *pu4Count); + +uint32_t nicRxWaitResponse(IN struct ADAPTER *prAdapter, + IN uint8_t ucPortIdx, OUT uint8_t *pucRspBuffer, + IN uint32_t u4MaxRespBufferLen, OUT uint32_t *pu4Length); + +void nicRxEnablePromiscuousMode(IN struct ADAPTER *prAdapter); + +void nicRxDisablePromiscuousMode(IN struct ADAPTER *prAdapter); + +uint32_t nicRxFlush(IN struct ADAPTER *prAdapter); + +uint32_t nicRxProcessActionFrame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +uint8_t nicRxGetRcpiValueFromRxv(IN uint8_t ucRcpiMode, + IN struct SW_RFB *prSwRfb); + +#if (CFG_SUPPORT_PERF_IND == 1) +void nicRxProcessRXV(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint8_t ucBssIndex); +#endif + +#endif /* _NIC_RX_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/nic_tx.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/nic_tx.h new file mode 100644 index 0000000000000..974f4644a9a27 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/nic_tx.h @@ -0,0 +1,1934 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + * + */ + + +#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 UNIFIED_MAC_TX_FORMAT 1 + +#define MAC_TX_RESERVED_FIELD 0 + +#define NIC_TX_RESOURCE_POLLING_TIMEOUT 256 +#define NIC_TX_RESOURCE_POLLING_DELAY_MSEC 5 + +#define NIC_TX_CMD_INFO_RESERVED_COUNT 4 + +/* Maximum buffer count for individual HIF TCQ */ +#define NIC_TX_PAGE_COUNT_TC0 \ + (NIC_TX_BUFF_COUNT_TC0 * nicTxGetMaxPageCntPerFrame(prAdapter)) +#define NIC_TX_PAGE_COUNT_TC1 \ + (NIC_TX_BUFF_COUNT_TC1 * nicTxGetMaxPageCntPerFrame(prAdapter)) +#define NIC_TX_PAGE_COUNT_TC2 \ + (NIC_TX_BUFF_COUNT_TC2 * nicTxGetMaxPageCntPerFrame(prAdapter)) +#define NIC_TX_PAGE_COUNT_TC3 \ + (NIC_TX_BUFF_COUNT_TC3 * nicTxGetMaxPageCntPerFrame(prAdapter)) +#define NIC_TX_PAGE_COUNT_TC4 \ + (NIC_TX_BUFF_COUNT_TC4 * nicTxGetMaxPageCntPerFrame(prAdapter)) +#define NIC_TX_PAGE_COUNT_TC5 \ + (NIC_TX_BUFF_COUNT_TC5 * nicTxGetMaxPageCntPerFrame(prAdapter)) + +#define NIC_TX_BUFF_COUNT_TC0 HIF_TX_BUFF_COUNT_TC0 +#define NIC_TX_BUFF_COUNT_TC1 HIF_TX_BUFF_COUNT_TC1 +#define NIC_TX_BUFF_COUNT_TC2 HIF_TX_BUFF_COUNT_TC2 +#define NIC_TX_BUFF_COUNT_TC3 HIF_TX_BUFF_COUNT_TC3 +#define NIC_TX_BUFF_COUNT_TC4 HIF_TX_BUFF_COUNT_TC4 +#define NIC_TX_BUFF_COUNT_TC5 HIF_TX_BUFF_COUNT_TC5 + +#define NIC_TX_RESOURCE_CTRL \ + HIF_TX_RESOURCE_CTRL /* to enable/disable TX resource control */ +#define NIC_TX_RESOURCE_CTRL_PLE \ + HIF_TX_RESOURCE_CTRL_PLE /* to enable/disable TX resource control */ + + +#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 8 +#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) + +#define NIC_TX_INIT_PAGE_COUNT_TC0 \ + (NIC_TX_INIT_BUFF_COUNT_TC0 * nicTxGetMaxPageCntPerFrame(prAdapter)) +#define NIC_TX_INIT_PAGE_COUNT_TC1 \ + (NIC_TX_INIT_BUFF_COUNT_TC1 * nicTxGetMaxPageCntPerFrame(prAdapter)) +#define NIC_TX_INIT_PAGE_COUNT_TC2 \ + (NIC_TX_INIT_BUFF_COUNT_TC2 * nicTxGetMaxPageCntPerFrame(prAdapter)) +#define NIC_TX_INIT_PAGE_COUNT_TC3 \ + (NIC_TX_INIT_BUFF_COUNT_TC3 * nicTxGetMaxPageCntPerFrame(prAdapter)) +#define NIC_TX_INIT_PAGE_COUNT_TC4 \ + (NIC_TX_INIT_BUFF_COUNT_TC4 * nicTxGetMaxPageCntPerFrame(prAdapter)) +#define NIC_TX_INIT_PAGE_COUNT_TC5 \ + (NIC_TX_INIT_BUFF_COUNT_TC5 * nicTxGetMaxPageCntPerFrame(prAdapter)) + +#endif + +#define NIC_TX_ENABLE_SECOND_HW_QUEUE 0 + +/* 4 TODO: The following values shall be got from FW by query CMD */ +/*------------------------------------------------------------------------*/ +/* Resource Management related information */ +/*------------------------------------------------------------------------*/ +#define NIC_TX_PAGE_SIZE_IS_POWER_OF_2 TRUE +#define NIC_TX_PAGE_SIZE_IN_POWER_OF_2 HIF_TX_PAGE_SIZE_IN_POWER_OF_2 +#define NIC_TX_PAGE_SIZE HIF_TX_PAGE_SIZE + +/* For development only */ +/* calculated by MS native 802.11 format */ +#define NIC_TX_MAX_SIZE_PER_FRAME 1532 +#define NIC_TX_MAX_PAGE_PER_FRAME \ + ((NIC_TX_DESC_AND_PADDING_LENGTH + NIC_TX_DESC_HEADER_PADDING_LENGTH + \ + NIC_TX_MAX_SIZE_PER_FRAME + NIC_TX_PAGE_SIZE - 1) / NIC_TX_PAGE_SIZE) + +#define NIX_TX_PLE_PAGE_CNT_PER_FRAME 1 +#define NIC_TX_LEN_ADDING_LENGTH 8 /*0x8206_C000[15:8] x 4.*/ + +/*------------------------------------------------------------------------*/ +/* Tx descriptor related information */ +/*------------------------------------------------------------------------*/ + +/* Frame Buffer + * |<--Tx Descriptor-->|<--Tx descriptor padding-->| + * <--802.3/802.11 Header-->|<--Header padding-->|<--Payload-->| + */ + +/* Tx descriptor length by format (TXD.FT) */ +/* in unit of double word */ +#define NIC_TX_DESC_LONG_FORMAT_LENGTH_DW 8 +#define NIC_TX_DESC_LONG_FORMAT_LENGTH \ + DWORD_TO_BYTE(NIC_TX_DESC_LONG_FORMAT_LENGTH_DW) +/* in unit of double word */ +#define NIC_TX_DESC_SHORT_FORMAT_LENGTH_DW 3 +#define NIC_TX_DESC_SHORT_FORMAT_LENGTH \ + DWORD_TO_BYTE(NIC_TX_DESC_SHORT_FORMAT_LENGTH_DW) + +/* Tx descriptor padding length (DMA.MICR.TXDSCR_PAD) */ +#define NIC_TX_DESC_PADDING_LENGTH_DW 0 /* in unit of double word */ +#define NIC_TX_DESC_PADDING_LENGTH \ + DWORD_TO_BYTE(NIC_TX_DESC_PADDING_LENGTH_DW) + +#define NIC_TX_PSE_HEADER_LENGTH 4 + +#define NIC_TX_DESC_AND_PADDING_LENGTH \ + (NIC_TX_DESC_LONG_FORMAT_LENGTH + NIC_TX_DESC_PADDING_LENGTH) + +/* Tx header padding (TXD.HeaderPadding) */ +/* Warning!! To use MAC header padding, every Tx packet must be decomposed */ +#define NIC_TX_DESC_HEADER_PADDING_LENGTH 0 /* in unit of bytes */ + +#define NIC_TX_DESC_PID_RESERVED 0 +#define NIC_TX_DESC_DRIVER_PID_MIN 1 +#define NIC_TX_DESC_DRIVER_PID_MAX 127 + +#define NIC_TX_DATA_DEFAULT_RETRY_COUNT_LIMIT 30 +#define NIC_TX_MGMT_DEFAULT_RETRY_COUNT_LIMIT 30 + +/* in unit of ms */ +#define NIC_TX_AC_BE_REMAINING_TX_TIME TX_DESC_TX_TIME_NO_LIMIT +#define NIC_TX_AC_BK_REMAINING_TX_TIME TX_DESC_TX_TIME_NO_LIMIT +#define NIC_TX_AC_VO_REMAINING_TX_TIME TX_DESC_TX_TIME_NO_LIMIT +#define NIC_TX_AC_VI_REMAINING_TX_TIME TX_DESC_TX_TIME_NO_LIMIT +#define NIC_TX_MGMT_REMAINING_TX_TIME 2000 + +#define NIC_TX_CRITICAL_DATA_TID 7 + +#define HW_MAC_TX_DESC_APPEND_T_LENGTH 44 +#define NIC_TX_HEAD_ROOM \ + (NIC_TX_DESC_LONG_FORMAT_LENGTH + NIC_TX_DESC_PADDING_LENGTH \ + + HW_MAC_TX_DESC_APPEND_T_LENGTH) + +/*------------------------------------------------------------------------*/ +/* Tx status related information */ +/*------------------------------------------------------------------------*/ + +/* Tx status header & content length */ +#define NIC_TX_STATUS_HEADER_LENGTH_DW \ + 1 /* in unit of double word */ +#define NIC_TX_STATUS_HEADER_LENGTH \ + DWORD_TO_BYTE(NIC_TX_STATUS_HEADER_LENGTH_DW) +#define NIC_TX_STATUS_LENGTH_DW \ + 7 /* in unit of double word */ +#define NIC_TX_STATUS_LENGTH \ + DWORD_TO_BYTE(NIC_TX_STATUS_LENGTH_DW) + +/*------------------------------------------------------------------------*/ +/* Tx descriptor field related information */ +/*------------------------------------------------------------------------*/ +/* DW 0 */ +#define TX_DESC_TX_BYTE_COUNT_MASK BITS(0, 15) +#define TX_DESC_TX_BYTE_COUNT_OFFSET 0 + +#define TX_DESC_ETHER_TYPE_OFFSET_MASK BITS(0, 6) +#define TX_DESC_ETHER_TYPE_OFFSET_OFFSET 0 +#define TX_DESC_IP_CHKSUM_OFFLOAD BIT(7) +#define TX_DESC_TCP_UDP_CHKSUM_OFFLOAD BIT(0) +#define TX_DESC_QUEUE_INDEX_MASK BITS(2, 6) +#define TX_DESC_QUEUE_INDEX_OFFSET 2 +#define TX_DESC_PORT_INDEX BIT(7) +#define TX_DESC_PORT_INDEX_OFFSET 7 + +#define PORT_INDEX_LMAC 0 +#define PORT_INDEX_MCU 1 + +/* DW 1 */ +#define TX_DESC_WLAN_INDEX_MASK BITS(0, 7) +#define TX_DESC_WLAN_INDEX_OFFSET 0 +#define TX_DESC_HEADER_FORMAT_MASK BITS(5, 6) +#define TX_DESC_HEADER_FORMAT_OFFSET 5 + +#define HEADER_FORMAT_NON_802_11 0 /* Non-802.11 */ +#define HEADER_FORMAT_COMMAND 1 /* Command */ +#define HEADER_FORMAT_802_11_NORMAL_MODE \ + 2 /* 802.11 (normal mode) */ +#define HEADER_FORMAT_802_11_ENHANCE_MODE \ + 3 /* 802.11 (Enhancement mode) */ +#define HEADER_FORMAT_802_11_MASK BIT(1) + +#define TX_DESC_NON_802_11_MORE_DATA BIT(0) +#define TX_DESC_NON_802_11_EOSP BIT(1) +#define TX_DESC_NON_802_11_REMOVE_VLAN BIT(2) +#define TX_DESC_NON_802_11_VLAN_FIELD BIT(3) +#define TX_DESC_NON_802_11_ETHERNET_II BIT(4) +#define TX_DESC_NOR_802_11_HEADER_LENGTH_MASK BITS(0, 4) +#define TX_DESC_NOR_802_11_HEADER_LENGTH_OFFSET 0 +#define TX_DESC_ENH_802_11_EOSP BIT(1) +#define TX_DESC_ENH_802_11_AMSDU BIT(2) + +#define TX_DESC_FORMAT BIT(7) +#define TX_DESC_SHORT_FORMAT 0 +#define TX_DESC_LONG_FORMAT 1 + +#define TX_DESC_TXD_LENGTH_MASK BIT(0) +#define TX_DESC_TXD_LENGTH_OFFSET 0 + +#define TX_DESC_HEADER_PADDING_LENGTH_MASK BIT(1) +#define TX_DESC_HEADER_PADDING_LENGTH_OFFSET 1 +#define TX_DESC_HEADER_PADDING_MODE BIT(2) + +#define TX_DESC_TXD_EXTEND_LENGTH_MASK BIT(3) +#define TX_DESC_TXD_EXTEND_LENGTH_OFFSET 3 + +#define TX_DESC_TXD_UTXB_AMSDU_MASK BIT(4) +#define TX_DESC_TXD_UTXB_AMSDU_OFFSET 4 + +#define TX_DESC_TID_MASK BITS(5, 7) +#define TX_DESC_TID_OFFSET 5 +#define TX_DESC_TID_NUM 8 + +#define TX_DESC_PACKET_FORMAT_MASK BITS(0, 1) /* SW Field */ +#define TX_DESC_PACKET_FORMAT_OFFSET 0 +#define TX_DESC_OWN_MAC_MASK BITS(2, 7) +#define TX_DESC_OWN_MAC_OFFSET 2 + +/* DW 2 */ +#define TX_DESC_SUB_TYPE_MASK BITS(0, 3) +#define TX_DESC_SUB_TYPE_OFFSET 0 +#define TX_DESC_TYPE_MASK BITS(4, 5) +#define TX_DESC_TYPE_OFFSET 4 +#define TX_DESC_NDP BIT(6) +#define TX_DESC_NDPA BIT(7) + +#define TX_DESC_SOUNDING BIT(0) +#define TX_DESC_FORCE_RTS_CTS BIT(1) +#define TX_DESC_BROADCAST_MULTICAST BIT(2) +#define TX_DESC_BIP_PROTECTED BIT(3) +#define TX_DESC_DURATION_FIELD_CONTROL BIT(4) +#define TX_DESC_HTC_EXISTS BIT(5) +#define TX_DESC_FRAGMENT_MASK BITS(6, 7) +#define TX_DESC_FRAGMENT_OFFSET 6 +#define FRAGMENT_FISRT_PACKET 1 +#define FRAGMENT_MIDDLE_PACKET 2 +#define FRAGMENT_LAST_PACKET 3 + +#define TX_DESC_REMAINING_MAX_TX_TIME BITS(0, 7) +#define TX_DESC_TX_TIME_NO_LIMIT 0 +/* Unit of life time calculation of Tx descriptor */ +#define TX_DESC_LIFE_TIME_UNIT_IN_POWER_OF_2 5 +#define TX_DESC_LIFE_TIME_UNIT \ + POWER_OF_2(TX_DESC_LIFE_TIME_UNIT_IN_POWER_OF_2) +#define TX_DESC_POWER_OFFSET_MASK BITS(0, 4) +#define TX_DESC_BA_DISABLE BIT(5) +#define TX_DESC_TIMING_MEASUREMENT BIT(6) +#define TX_DESC_FIXED_RATE BIT(7) + +/* DW 3 */ +#define TX_DESC_NO_ACK BIT(0) +#define TX_DESC_PROTECTED_FRAME BIT(1) +#define TX_DESC_EXTEND_MORE_DATA BIT(2) +#define TX_DESC_EXTEND_EOSP BIT(3) + +#define TX_DESC_SW_RESERVED_MASK BITS(4, 5) +#define TX_DESC_SW_RESERVED_OFFSET 4 + +#define TX_DESC_TX_COUNT_MASK BITS(6, 10) +#define TX_DESC_TX_COUNT_OFFSET 6 +#define TX_DESC_TX_COUNT_NO_ATTEMPT 0 +#define TX_DESC_TX_COUNT_NO_LIMIT 31 +#define TX_DESC_REMAINING_TX_COUNT_MASK BITS(11, 15) +#define TX_DESC_REMAINING_TX_COUNT_OFFSET 11 +#define TX_DESC_SEQUENCE_NUMBER BITS(0, 11) +#define TX_DESC_HW_RESERVED_MASK BITS(12, 13) +#define TX_DESC_HW_RESERVED_OFFSET 12 +#define TX_DESC_PN_IS_VALID BIT(14) +#define TX_DESC_SN_IS_VALID BIT(15) + +/* DW 4 */ +#define TX_DESC_PN_PART1 BITS(0, 31) + +/* DW 5 */ +#define TX_DESC_PACKET_ID BIT(0, 7) +#define TX_DESC_TX_STATUS_FORMAT BIT(0) +#define TX_DESC_TX_STATUS_FORMAT_OFFSET 0 +#define TX_DESC_TX_STATUS_TO_MCU BIT(1) +#define TX_DESC_TX_STATUS_TO_HOST BIT(2) +#define TX_DESC_DA_SOURCE BIT(3) +#define TX_DESC_POWER_MANAGEMENT_CONTROL BIT(5) +#define TX_DESC_PN_PART2 BITS(0, 15) + +/* DW 6 *//* FR = 1 */ +#define TX_DESC_BANDWIDTH_MASK BITS(0, 2) +#define TX_DESC_BANDWIDTH_OFFSET 0 +#define TX_DESC_DYNAMIC_BANDWIDTH BIT(3) +#define TX_DESC_ANTENNA_INDEX_MASK BITS(4, 15) +#define TX_DESC_ANTENNA_INDEX_OFFSET 4 + +#define TX_DESC_FIXDE_RATE_MASK BITS(0, 11) +#define TX_DESC_FIXDE_RATE_OFFSET 0 +#define TX_DESC_TX_RATE BITS(0, 5) +#define TX_DESC_TX_RATE_OFFSET 0 +#define TX_DESC_TX_MODE BITS(6, 8) +#define TX_DESC_TX_MODE_OFFSET 6 +#define TX_DESC_NSTS_MASK BITS(9, 10) +#define TX_DESC_NSTS_OFFSET 9 +#define TX_DESC_STBC BIT(11) +#define TX_DESC_BF BIT(12) +#define TX_DESC_LDPC BIT(13) +#define TX_DESC_GUARD_INTERVAL BIT(14) +#define TX_DESC_FIXED_RATE_MODE BIT(15) + +/* DW 7 */ +#define TX_DESC_SPE_EXT_IDX_MASK BITS(11, 15) +#define TX_DESC_SPE_EXT_IDX_OFFSET 11 +#define TX_DESC_PSE_FID_MASK BITS(0, 13) +#define TX_DESC_PSE_FID_OFFSET 0 +#define TX_DESC_HW_AMSDU BIT(14) +#define TX_DESC_HIF_ERR BIT(15) + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE +#define NIC_TX_TIME_THRESHOLD 100 /* in unit of ms */ +#endif + +#define NIC_TX_INIT_CMD_PORT HIF_TX_INIT_CMD_PORT + +/******************************************************************************* + * 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. + */ +/* TXD_PKT_FORMAT options*/ +enum ENUM_TXD_PKT_FORMAT_OPTION { + TXD_PKT_FORMAT_TXD = 0, /* TXD only */ + TXD_PKT_FORMAT_TXD_PAYLOAD, /* TXD and paload */ + TXD_PKT_FORMAT_COMMAND, /* Command */ + TXD_PKT_FORMAT_FWDL, /* Firmware download */ + TXD_PKT_FORMAT_NUM, +}; + +/* HIF Tx interrupt status queue index*/ +enum ENUM_HIF_TX_INDEX { + HIF_TX_AC0_INDEX = 0, + HIF_TX_AC1_INDEX, + HIF_TX_AC2_INDEX, + HIF_TX_AC3_INDEX, + + HIF_TX_AC10_INDEX, + HIF_TX_AC11_INDEX, + HIF_TX_AC12_INDEX, + HIF_TX_AC13_INDEX, + + HIF_TX_AC20_INDEX, + HIF_TX_AC21_INDEX, + HIF_TX_AC22_INDEX, + HIF_TX_AC23_INDEX, + + HIF_TX_RSV0_INDEX, + HIF_TX_RSV1_INDEX, + HIF_TX_FFA_INDEX, + HIF_TX_CPU_INDEX, + + HIF_TX_NUM +}; + +/* LMAC Tx queue index */ +enum ENUM_MAC_TXQ_INDEX { + MAC_TXQ_AC0_INDEX = 0, + MAC_TXQ_AC1_INDEX, + MAC_TXQ_AC2_INDEX, + MAC_TXQ_AC3_INDEX, + + MAC_TXQ_AC10_INDEX, + MAC_TXQ_AC11_INDEX, + MAC_TXQ_AC12_INDEX, + MAC_TXQ_AC13_INDEX, + + MAC_TXQ_AC20_INDEX, + MAC_TXQ_AC21_INDEX, + MAC_TXQ_AC22_INDEX, + MAC_TXQ_AC23_INDEX, + + MAC_TXQ_AC30_INDEX, + MAC_TXQ_AC31_INDEX, + MAC_TXQ_AC32_INDEX, + MAC_TXQ_AC33_INDEX, + + MAC_TXQ_ALTX_0_INDEX, + MAC_TXQ_BMC_0_INDEX, + MAC_TXQ_BCN_0_INDEX, + MAC_TXQ_PSMP_0_INDEX, + + MAC_TXQ_ALTX_1_INDEX, + MAC_TXQ_BMC_1_INDEX, + MAC_TXQ_BCN_1_INDEX, + MAC_TXQ_PSMP_1_INDEX, + + MAC_TXQ_NAF_INDEX, + MAC_TXQ_NBCN_INDEX, + + MAC_TXQ_NUM +}; + +/* MCU quque index */ +enum ENUM_MCU_Q_INDEX { + MCU_Q0_INDEX = 0, + MCU_Q1_INDEX, + MCU_Q2_INDEX, + MCU_Q3_INDEX, + MCU_Q_NUM +}; + +/* Tc Resource index */ +enum ENUM_TRAFFIC_CLASS_INDEX { + /*First HW queue */ + TC0_INDEX = 0, /* HIF TX: AC0 packets */ + TC1_INDEX, /* HIF TX: AC1 packets */ + TC2_INDEX, /* HIF TX: AC2 packets */ + TC3_INDEX, /* HIF TX: AC3 packets */ + TC4_INDEX, /* HIF TX: CPU packets */ + +#if NIC_TX_ENABLE_SECOND_HW_QUEUE + /* Second HW queue */ + TC5_INDEX, /* HIF TX: AC10 packets */ + TC6_INDEX, /* HIF TX: AC11 packets */ + TC7_INDEX, /* HIF TX: AC12 packets */ + TC8_INDEX, /* HIF TX: AC13 packets */ +#endif + + TC_NUM /* Maximum number of Traffic Classes. */ +}; + +/* +1 for DBDC */ +#define TX_PORT_NUM (TC_NUM + 1) + +#define TX_2G_WMM_PORT_NUM (TC_NUM) + +#define BMC_TC_INDEX TC1_INDEX + +/* per-Network Tc Resource index */ +enum ENUM_NETWORK_TC_RESOURCE_INDEX { + /* QoS Data frame, WMM AC index */ + NET_TC_WMM_AC_BE_INDEX = 0, + NET_TC_WMM_AC_BK_INDEX, + NET_TC_WMM_AC_VI_INDEX, + NET_TC_WMM_AC_VO_INDEX, + /* Mgmt frame */ + NET_TC_MGMT_INDEX, + /* nonQoS / non StaRec frame (BMC/non-associated frame) */ + NET_TC_BMC_INDEX, + + NET_TC_NUM +}; + +enum ENUM_TX_STATISTIC_COUNTER { + 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 ENUM_FIX_BW { + FIX_BW_NO_FIXED = 0, + FIX_BW_20 = 4, + FIX_BW_40, + FIX_BW_80, + FIX_BW_160, + FIX_BW_NUM +}; + +enum ENUM_MSDU_OPTION { + MSDU_OPT_NO_ACK = BIT(0), + MSDU_OPT_NO_AGGREGATE = BIT(1), + MSDU_OPT_TIMING_MEASURE = BIT(2), + MSDU_OPT_RCPI_NOISE_STATUS = BIT(3), + + /* Option by Frame Format */ + /* Non-80211 */ + MSDU_OPT_MORE_DATA = BIT(4), + MSDU_OPT_REMOVE_VLAN = BIT(5), /* Remove VLAN tag if exists */ + + /* 80211-enhanced */ + MSDU_OPT_AMSDU = BIT(6), + + /* 80211-enhanced & Non-80211 */ + MSDU_OPT_EOSP = BIT(7), + + /* Beamform */ + MSDU_OPT_NDP = BIT(8), + MSDU_OPT_NDPA = BIT(9), + MSDU_OPT_SOUNDING = BIT(10), + + /* Protection */ + MSDU_OPT_FORCE_RTS = BIT(11), + + /* Security */ + MSDU_OPT_BIP = BIT(12), + MSDU_OPT_PROTECTED_FRAME = BIT(13), + + /* SW Field */ + MSDU_OPT_SW_DURATION = BIT(14), + MSDU_OPT_SW_PS_BIT = BIT(15), + MSDU_OPT_SW_HTC = BIT(16), + MSDU_OPT_SW_BAR_SN = BIT(17), + + /* Manual Mode */ + MSDU_OPT_MANUAL_FIRST_BIT = BIT(18), + + MSDU_OPT_MANUAL_LIFE_TIME = MSDU_OPT_MANUAL_FIRST_BIT, + MSDU_OPT_MANUAL_RETRY_LIMIT = BIT(19), + MSDU_OPT_MANUAL_POWER_OFFSET = BIT(20), + MSDU_OPT_MANUAL_TX_QUE = BIT(21), + MSDU_OPT_MANUAL_SN = BIT(22), + + MSDU_OPT_MANUAL_LAST_BIT = MSDU_OPT_MANUAL_SN +}; + +enum ENUM_MSDU_CONTROL_FLAG { + MSDU_CONTROL_FLAG_FORCE_TX = BIT(0) +}; + +enum ENUM_MSDU_RATE_MODE { + MSDU_RATE_MODE_AUTO = 0, + MSDU_RATE_MODE_MANUAL_DESC, + /* The following rate mode is not implemented yet */ + /* DON'T use!!! */ + MSDU_RATE_MODE_MANUAL_CR, + MSDU_RATE_MODE_LOWEST_RATE +}; + +enum ENUM_DATA_RATE_MODE { + DATA_RATE_MODE_AUTO = 0, + DATA_RATE_MODE_MANUAL, + DATA_RATE_MODE_BSS_LOWEST +}; + +struct TX_TCQ_STATUS { + /* HIF reported page count delta */ + uint32_t au4TxDonePageCount[TC_NUM]; /* other TC */ + uint32_t au4PreUsedPageCount[TC_NUM]; + uint32_t u4AvaliablePageCount; /* FFA */ + uint8_t ucNextTcIdx; /* For round-robin distribute free page count */ + + /* distributed page count */ + uint32_t au4FreePageCount[TC_NUM]; + uint32_t au4MaxNumOfPage[TC_NUM]; + + /* buffer count */ + uint32_t au4FreeBufferCount[TC_NUM]; + uint32_t au4MaxNumOfBuffer[TC_NUM]; + + /* + * PLE part + */ + + u_int8_t fgNeedPleCtrl; + + /* HIF reported page count delta */ + uint32_t au4TxDonePageCount_PLE[TC_NUM]; /* other TC */ + uint32_t au4PreUsedPageCoun_PLE[TC_NUM]; + uint32_t u4AvaliablePageCount_PLE; /* FFA */ + + /* distributed page count */ + uint32_t au4FreePageCount_PLE[TC_NUM]; + uint32_t au4MaxNumOfPage_PLE[TC_NUM]; + + /* buffer count */ + uint32_t au4FreeBufferCount_PLE[TC_NUM]; + uint32_t au4MaxNumOfBuffer_PLE[TC_NUM]; +}; + +struct TX_TCQ_ADJUST { + int32_t ai4Variation[TC_NUM]; +}; + +struct TX_CTRL { + uint32_t u4TxCachedSize; + uint8_t *pucTxCached; + + uint32_t u4PageSize; + + uint32_t u4TotalPageNum; + + uint32_t u4TotalPageNumPle; + uint32_t u4TotalTxRsvPageNum; + +/* Elements below is classified according to TC (Traffic Class) value. */ + + struct TX_TCQ_STATUS rTc; + + uint8_t *pucTxCoalescingBufPtr; + + uint32_t u4WrIdx; + + struct QUE rFreeMsduInfoList; + + /* Management Frame Tracking */ + /* number of management frames to be sent */ + int32_t i4TxMgmtPendingNum; + + /* to tracking management frames need TX done callback */ + struct QUE rTxMgmtTxingQueue; + +#if CFG_HIF_STATISTICS + uint32_t u4TotalTxAccessNum; + uint32_t u4TotalTxPacketNum; +#endif + uint32_t au4Statistics[TX_STATISTIC_COUNTER_NUM]; + + /* Number to track forwarding frames */ + int32_t i4PendingFwdFrameCount; + + /* enable/disable TX resource control */ + u_int8_t fgIsTxResourceCtrl; + /* page counts for a wifi frame */ + uint32_t u4MaxPageCntPerFrame; + + /* Store SysTime of Last TxDone successfully */ + uint32_t u4LastTxTime; +}; + +enum ENUM_TX_PACKET_TYPE { + TX_PACKET_TYPE_DATA = 0, + TX_PACKET_TYPE_MGMT, + /* TX_PACKET_TYPE_1X, */ + X_PACKET_TYPE_NUM +}; + +enum ENUM_TX_PACKET_SRC { + TX_PACKET_OS, + TX_PACKET_OS_OID, + TX_PACKET_FORWARDING, + TX_PACKET_MGMT, + TX_PACKET_NUM +}; + +/* TX Call Back Function */ +typedef uint32_t(*PFN_TX_DONE_HANDLER) (IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE +struct PKT_PROFILE { + u_int8_t fgIsValid; +#if CFG_PRINT_PKT_LIFETIME_PROFILE + u_int8_t fgIsPrinted; + uint16_t u2IpSn; + uint16_t u2RtpSn; + uint8_t ucTcxFreeCount; +#endif + OS_SYSTIME rHardXmitArrivalTimestamp; + OS_SYSTIME rEnqueueTimestamp; + OS_SYSTIME rDequeueTimestamp; + OS_SYSTIME rHifTxDoneTimestamp; +}; +#endif + +enum ENUM_EAPOL_KEY_TYPE_T { + EAPOL_KEY_NOT_KEY = 0, + EAPOL_KEY_1_OF_4, + EAPOL_KEY_2_OF_4, + EAPOL_KEY_3_OF_4, + EAPOL_KEY_4_OF_4, + EAPOL_KEY_NUM +}; + +enum ENUM_KEY_ACTION_TYPE_T { + SEC_DROP_KEY_COMMAND = 0, + SEC_QUEUE_KEY_COMMAND, + SEC_TX_KEY_COMMAND, + SEC_ACTION_KEY_NUM +}; + +/* 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 { + struct QUE_ENTRY rQueEntry; + void *prPacket; /* Pointer to packet buffer */ + + enum ENUM_TX_PACKET_SRC eSrc; /* specify OS/FORWARD packet */ + uint8_t ucUserPriority; /* QoS parameter, convert to TID */ + + /* For composing TX descriptor header */ + uint8_t ucTC; /* Traffic Class: 0~4 (HIF TX0), 5 (HIF TX1) */ + uint8_t ucPacketType; /* 0: Data, 1: Management Frame */ + uint8_t ucStaRecIndex; /* STA_REC index */ + uint8_t ucBssIndex; /* BSS_INFO_T index */ + uint8_t ucWlanIndex; /* Wlan entry index */ + uint8_t ucPacketFormat; /* TXD.DW1[25:24] Packet Format */ + + u_int8_t fgIs802_1x; /* TRUE: 802.1x frame */ + /* TRUE: 802.1x frame - Non-Protected */ + u_int8_t fgIs802_1x_NonProtected; + u_int8_t fgIs802_11; /* TRUE: 802.11 header is present */ + u_int8_t fgIs802_3; /* TRUE: 802.3 frame */ + u_int8_t fgIsVlanExists; /* TRUE: VLAN tag is exists */ + + /* Special Option */ + uint32_t u4Option; /* Special option in bitmask, no ACK, etc... */ + int8_t cPowerOffset; /* Per-packet power offset, in 2's complement */ + uint16_t u2SwSN; /* SW assigned sequence number */ + uint8_t ucRetryLimit; /* The retry limit */ + uint32_t u4RemainingLifetime; /* Remaining lifetime, unit:ms */ + + /* Control flag */ + uint8_t ucControlFlag; /* Control flag in bitmask */ + + /* Fixed Rate Option */ + uint8_t ucRateMode; /* Rate mode: AUTO, MANUAL_DESC, MANUAL_CR */ + /* The rate option, rate code, GI, etc... */ + uint32_t u4FixedRateOption; + + /* There is a valid Tx descriptor for this packet */ + u_int8_t fgIsTXDTemplateValid; + + /* flattened from PACKET_INFO_T */ + uint8_t ucMacHeaderLength; /* MAC header legth */ + uint8_t ucLlcLength; /* w/o EtherType */ + uint16_t u2FrameLength; /* Total frame length */ + /* Ethernet Destination Address */ + uint8_t aucEthDestAddr[MAC_ADDR_LEN]; + uint32_t u4PageCount; /* Required page count for this MSDU */ + + /* for TX done tracking */ + uint8_t ucTxSeqNum; /* MGMT frame serial number */ + uint8_t ucPID; /* PID */ + uint8_t ucWmmQueSet; /* WMM Set */ + PFN_TX_DONE_HANDLER pfTxDoneHandler; /* Tx done handler */ + uint32_t u4TxDoneTag; /* Tag for data frame Tx done log */ + uint8_t ucPktType; + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + struct PKT_PROFILE rPktProfile; +#endif + + /* To be removed */ + uint8_t ucFormatID; /* 0: MAUI, Linux, Windows NDIS 5.1 */ + /* UINT_16 u2PalLLH; */ /* PAL Logical Link Header (for BOW network) */ + /* UINT_16 u2AclSN; */ /* ACL Sequence Number (for BOW network) */ + uint8_t ucPsForwardingType; /* See ENUM_PS_FORWARDING_TYPE_T */ + /* PS Session ID specified by the FW for the STA */ + /* UINT_8 ucPsSessionID; */ + /* TRUE means this is the last packet of the burst for (STA, TID) */ + /* BOOLEAN fgIsBurstEnd; */ +#if CFG_M0VE_BA_TO_DRIVER + uint8_t ucTID; +#endif + +#if CFG_SUPPORT_MULTITHREAD + /* Compose TxDesc in main_thread and place here */ + uint8_t aucTxDescBuffer[NIC_TX_DESC_AND_PADDING_LENGTH]; +#endif + +#if defined(_HIF_PCIE) || defined(_HIF_AXI) + struct MSDU_TOKEN_ENTRY *prToken; + struct TX_DATA_REQ rTxReq; +#endif + enum ENUM_EAPOL_KEY_TYPE_T eEapolKeyType; +}; + +#define HIT_PKT_FLAGS_CT_WITH_TXD BIT(0) +#define HIF_PKT_FLAGS_COPY_HOST_TXD_ALL BIT(1) + +#define MAX_BUF_NUM_PER_PKT 6 + +#define NUM_OF_MSDU_ID_IN_TXD 4 +#define TXD_MAX_BUF_NUM 4 +#define TXD_MSDU_ID_VLD BIT(15) /* MSDU valid */ +#define TXD_LEN_AL BIT(15) /* A-MSDU last */ +#define TXD_LEN_ML BIT(14) /* MSDU last */ +#define TXD_LEN_ML_V2 BIT(15) /* MSDU last */ +#define TXD_LEN_MASK_V2 BITS(0, 11) +#define TXD_ADDR2_MASK BITS(12, 14) +#define TXD_ADDR2_OFFSET 20 + + +struct TXD_PTR_LEN { + uint32_t u4Ptr0; + uint16_t u2Len0; /* Bit15: AL, Bit14: ML */ + uint16_t u2Len1; /* Bit15: AL, Bit14: ML */ + uint32_t u4Ptr1; +}; + +union HW_MAC_TX_DESC_APPEND { + struct { + uint16_t u2PktFlags; + uint16_t u2MsduToken; + uint8_t ucBssIndex; + uint8_t aucReserved[2]; + uint8_t ucBufNum; + uint32_t au4BufPtr[MAX_BUF_NUM_PER_PKT]; + uint16_t au2BufLen[MAX_BUF_NUM_PER_PKT]; + } CR4_APPEND; + + struct { + /* Bit15 indicate valid */ + uint16_t au2MsduId[NUM_OF_MSDU_ID_IN_TXD]; + struct TXD_PTR_LEN arPtrLen[TXD_MAX_BUF_NUM / 2]; + } CONNAC_APPEND; +}; + +/*!A data structure which is identical with HW MAC TX DMA Descriptor */ +struct HW_MAC_TX_DESC { + /* DW 0 */ + uint16_t u2TxByteCount; + uint8_t ucEtherOffset; /* Ether-Type Offset, IP checksum offload */ + /* UDP/TCP checksum offload, + * USB NextVLD/TxBURST, Queue index, Port index + */ + uint8_t ucPortIdx_QueueIdx; + /* DW 1 */ + uint8_t ucWlanIdx; + /* Header format, TX descriptor format */ + uint8_t ucHeaderFormat; + /* Header padding, no ACK, TID, Protect frame */ + uint8_t ucHeaderPadding; + uint8_t ucOwnMAC; + + /* Long Format, the following structure is for long format ONLY */ + /* DW 2 */ + uint8_t ucType_SubType; /* Type, Sub-type, NDP, NDPA */ + /* Sounding, force RTS/CTS, BMC, BIP, Duration, HTC exist, Fragment */ + uint8_t ucFrag; + uint8_t ucRemainingMaxTxTime; + /* Power offset, Disable BA, Timing measurement, Fixed rate */ + uint8_t ucPowerOffset; + /* DW 3 */ + uint16_t u2TxCountLimit; /* TX count limit */ + uint16_t u2SN; /* SN, HW own, PN valid, SN valid */ + /* DW 4 */ + uint32_t u4PN1; + /* DW 5 */ + uint8_t ucPID; + /* TXS format, TXS to mcu, + * TXS to host, DA source, BAR SSN, Power management + */ + uint8_t ucTxStatus; + uint16_t u2PN2; + /* DW 6 */ + uint16_t u2AntID; /* Fixed rate, Antenna ID */ + /* Explicit/implicit beamforming, Fixed rate table, LDPC, GI */ + uint16_t u2FixedRate; + /* DW 7 */ + uint16_t u2SwTxTime; /* Sw Tx time[9:0], SPE_IDX[15:11] */ + uint16_t u2PseFid; /* indicate frame ID in PSE for this TXD */ +}; + +struct TX_RESOURCE_CONTROL { + /* HW TX queue definition */ + uint8_t ucDestPortIndex; + uint8_t ucDestQueueIndex; + /* HIF Interrupt status index */ + uint8_t ucHifTxQIndex; +}; + +struct TX_TC_TRAFFIC_SETTING { + uint32_t u4TxDescLength; + uint32_t u4RemainingTxTime; + uint8_t ucTxCountLimit; +}; + +typedef void (*PFN_TX_DATA_DONE_CB) (IN struct GLUE_INFO *prGlueInfo, + IN struct QUE *prQue); + +struct tx_resource_info { + /* PSE */ + /* the total usable resource for MCU port */ + uint32_t u4CmdTotalResource; + /* the unit of a MCU resource */ + uint32_t u4CmdResourceUnit; + /* the total usable resource for LMAC port */ + uint32_t u4DataTotalResource; + /* the unit of a LMAC resource */ + uint32_t u4DataResourceUnit; + + /* PLE */ + /* the total usable resource for MCU port */ + uint32_t u4CmdTotalResourcePle; + /* the unit of a MCU resource */ + uint32_t u4CmdResourceUnitPle; + /* the total usable resource for LMAC port */ + uint32_t u4DataTotalResourcePle; + /* the unit of a LMAC resource */ + uint32_t u4DataResourceUnitPle; + + /* Packet Processor 0x8206C000[15:8] + * 4. Extra PSE resource is needed for HW. + */ + uint8_t ucPpTxAddCnt;/* in unit of byte */ + + /* update resource callback */ + void (*txResourceInit)(IN struct ADAPTER *prAdapter); +}; + +struct TX_DESC_OPS_T { + void (*fillNicAppend)(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + OUT uint8_t *prTxDescBuffer); + void (*fillHifAppend)(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN uint16_t u4MsduId, + IN dma_addr_t rDmaAddr, IN uint32_t u4Idx, IN u_int8_t fgIsLast, + OUT uint8_t *pucBuffer); + void (*fillTxByteCount)(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + struct HW_MAC_TX_DESC *prTxDesc); +}; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +extern PFN_TX_DATA_DONE_CB g_pfTxDataDoneCb; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +#define TX_INC_CNT(prTxCtrl, eCounter) \ + {((struct TX_CTRL *)prTxCtrl)->au4Statistics[eCounter]++; } + +#define TX_ADD_CNT(prTxCtrl, eCounter, u8Amount) \ + {((struct TX_CTRL *)prTxCtrl)->au4Statistics[eCounter] += \ + (uint32_t)u8Amount; } + +#define TX_GET_CNT(prTxCtrl, eCounter) \ + (((struct TX_CTRL *)prTxCtrl)->au4Statistics[eCounter]) + +#define TX_RESET_ALL_CNTS(prTxCtrl) \ + {kalMemZero(&prTxCtrl->au4Statistics[0], \ + sizeof(prTxCtrl->au4Statistics)); } +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + +#if CFG_PRINT_PKT_LIFETIME_PROFILE +#define PRINT_PKT_PROFILE(_pkt_profile, _note) \ +do { \ + if (!(_pkt_profile)->fgIsPrinted) { \ + DBGLOG(TX, TRACE, \ + "X[%lu] E[%lu] D[%lu] HD[%lu] B[%d] RTP[%d] %s\n", \ + (uint32_t)((_pkt_profile)->rHardXmitArrivalTimestamp), \ + (uint32_t)((_pkt_profile)->rEnqueueTimestamp), \ + (uint32_t)((_pkt_profile)->rDequeueTimestamp), \ + (uint32_t)((_pkt_profile)->rHifTxDoneTimestamp), \ + (uint8_t)((_pkt_profile)->ucTcxFreeCount), \ + (uint16_t)((_pkt_profile)->u2RtpSn), \ + (_note))); \ + (_pkt_profile)->fgIsPrinted = TRUE; \ + } \ +} while (0) +#else +#define PRINT_PKT_PROFILE(_pkt_profile, _note) +#endif + +#define CHK_PROFILES_DELTA(_pkt1, _pkt2, _delta) \ + (CHECK_FOR_TIMEOUT((_pkt1)->rHardXmitArrivalTimestamp, \ + (_pkt2)->rHardXmitArrivalTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt1)->rEnqueueTimestamp, \ + (_pkt2)->rEnqueueTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt1)->rDequeueTimestamp, \ + (_pkt2)->rDequeueTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt1)->rHifTxDoneTimestamp, \ + (_pkt2)->rHifTxDoneTimestamp, (_delta))) + +#define CHK_PROFILE_DELTA(_pkt, _delta) \ + (CHECK_FOR_TIMEOUT((_pkt)->rEnqueueTimestamp, \ + (_pkt)->rHardXmitArrivalTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt)->rDequeueTimestamp, \ + (_pkt)->rEnqueueTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt)->rHifTxDoneTimestamp, \ + (_pkt)->rDequeueTimestamp, (_delta))) +#endif + +/*------------------------------------------------------------------------------ + * MACRO for MSDU_INFO + *------------------------------------------------------------------------------ + */ +#define TX_SET_MMPDU nicTxSetMngPacket +#define TX_SET_DATA_PACKET nicTxSetDataPacket + +/*------------------------------------------------------------------------------ + * MACRO for HW_MAC_TX_DESC_T + *------------------------------------------------------------------------------ + */ +#define TX_DESC_GET_FIELD(_rHwMacTxDescField, _mask, _offset) \ + (((_rHwMacTxDescField) & (_mask)) >> (_offset)) +#define TX_DESC_SET_FIELD(_rHwMacTxDescField, _value, _mask, _offset) \ +{ \ + (_rHwMacTxDescField) &= ~(_mask); \ + (_rHwMacTxDescField) |= (((_value) << (_offset)) & (_mask)); \ +} + +#define HAL_MAC_TX_DESC_SET_DW(_prHwMacTxDesc, _ucOffsetInDw, \ + _ucLengthInDw, _pucValueAddr) \ + kalMemCopy((uint32_t *)(_prHwMacTxDesc) + (_ucOffsetInDw), \ + (uint8_t *)(_pucValueAddr), DWORD_TO_BYTE(_ucLengthInDw)) +#define HAL_MAC_TX_DESC_GET_DW(_prHwMacTxDesc, _ucOffsetInDw, \ + _ucLengthInDw, _pucValueAddr) \ + kalMemCopy((uint8_t *)(_pucValueAddr), \ + (uint32_t *)(_prHwMacTxDesc) + (_ucOffsetInDw), \ + DWORD_TO_BYTE(_ucLengthInDw)) + +/* DW 0 */ +#define HAL_MAC_TX_DESC_GET_TX_BYTE_COUNT(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2TxByteCount) +#define HAL_MAC_TX_DESC_SET_TX_BYTE_COUNT(_prHwMacTxDesc, _u2TxByteCount) \ + (((_prHwMacTxDesc)->u2TxByteCount) = ((uint16_t)_u2TxByteCount)) + +#define HAL_MAC_TX_DESC_GET_ETHER_TYPE_OFFSET(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucEtherOffset, \ + TX_DESC_ETHER_TYPE_OFFSET_MASK, \ + TX_DESC_ETHER_TYPE_OFFSET_OFFSET) +#define HAL_MAC_TX_DESC_SET_ETHER_TYPE_OFFSET(_prHwMacTxDesc, \ + _ucEtherTypeOffset) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucEtherOffset), \ + ((uint8_t)_ucEtherTypeOffset), \ + TX_DESC_ETHER_TYPE_OFFSET_MASK, TX_DESC_ETHER_TYPE_OFFSET_OFFSET) + +#define HAL_MAC_TX_DESC_IS_IP_CHKSUM_ENABLED(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucEtherOffset & TX_DESC_IP_CHKSUM_OFFLOAD) \ + ? FALSE : TRUE) +#define HAL_MAC_TX_DESC_SET_IP_CHKSUM(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucEtherOffset |= TX_DESC_IP_CHKSUM_OFFLOAD) +#define HAL_MAC_TX_DESC_UNSET_IP_CHKSUM(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucEtherOffset &= ~TX_DESC_IP_CHKSUM_OFFLOAD) + +#define HAL_MAC_TX_DESC_IS_TCP_UDP_CHKSUM_ENABLED(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPortIdx_QueueIdx & \ + TX_DESC_TCP_UDP_CHKSUM_OFFLOAD) ? FALSE : TRUE) +#define HAL_MAC_TX_DESC_SET_TCP_UDP_CHKSUM(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPortIdx_QueueIdx |= TX_DESC_TCP_UDP_CHKSUM_OFFLOAD) +#define HAL_MAC_TX_DESC_UNSET_TCP_UDP_CHKSUM(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPortIdx_QueueIdx &= \ + ~TX_DESC_TCP_UDP_CHKSUM_OFFLOAD) + +#if 0 /* USB HIF doesn't use this field. */ +#define HAL_MAC_TX_DESC_IS_USB_NEXT_VLD_ENABLED(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPortIdx_QueueIdx & TX_DESC_USB_NEXT_VLD) \ + ? TRUE : FALSE) +#define HAL_MAC_TX_DESC_SET_USB_NEXT_VLD(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPortIdx_QueueIdx |= TX_DESC_USB_NEXT_VLD) +#define HAL_MAC_TX_DESC_UNSET_USB_NEXT_VLD(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPortIdx_QueueIdx &= ~TX_DESC_USB_NEXT_VLD) +#endif /* if 0 */ + +#define HAL_MAC_TX_DESC_GET_QUEUE_INDEX(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucPortIdx_QueueIdx, \ + TX_DESC_QUEUE_INDEX_MASK, TX_DESC_QUEUE_INDEX_OFFSET) +#define HAL_MAC_TX_DESC_SET_QUEUE_INDEX(_prHwMacTxDesc, _ucQueueIndex) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucPortIdx_QueueIdx), \ + ((uint8_t)_ucQueueIndex), \ + TX_DESC_QUEUE_INDEX_MASK, TX_DESC_QUEUE_INDEX_OFFSET) + +#define HAL_MAC_TX_DESC_GET_PORT_INDEX(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucPortIdx_QueueIdx, \ + TX_DESC_PORT_INDEX, TX_DESC_PORT_INDEX_OFFSET) +#define HAL_MAC_TX_DESC_SET_PORT_INDEX(_prHwMacTxDesc, _ucPortIndex) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucPortIdx_QueueIdx), \ + ((uint8_t)_ucPortIndex), \ + TX_DESC_PORT_INDEX, TX_DESC_PORT_INDEX_OFFSET) + +/* DW 1 */ +#define HAL_MAC_TX_DESC_GET_WLAN_INDEX(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucWlanIdx) +#define HAL_MAC_TX_DESC_SET_WLAN_INDEX(_prHwMacTxDesc, _ucWlanIdx) \ + (((_prHwMacTxDesc)->ucWlanIdx) = (_ucWlanIdx)) + +#define HAL_MAC_TX_DESC_IS_LONG_FORMAT(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_FORMAT)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_LONG_FORMAT(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_FORMAT) +#define HAL_MAC_TX_DESC_SET_SHORT_FORMAT(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_FORMAT) + +#define HAL_MAC_TX_DESC_GET_HEADER_FORMAT(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucHeaderFormat, \ + TX_DESC_HEADER_FORMAT_MASK, TX_DESC_HEADER_FORMAT_OFFSET) +#define HAL_MAC_TX_DESC_SET_HEADER_FORMAT(_prHwMacTxDesc, _ucHdrFormat) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucHeaderFormat), \ + ((uint8_t)_ucHdrFormat), TX_DESC_HEADER_FORMAT_MASK, \ + TX_DESC_HEADER_FORMAT_OFFSET) + +/* HF = 0x00, 802.11 normal mode */ +#define HAL_MAC_TX_DESC_IS_MORE_DATA(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_NON_802_11_MORE_DATA) \ + ? TRUE : FALSE) +#define HAL_MAC_TX_DESC_SET_MORE_DATA(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_NON_802_11_MORE_DATA) +#define HAL_MAC_TX_DESC_UNSET_MORE_DATA(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_NON_802_11_MORE_DATA) + +#define HAL_MAC_TX_DESC_IS_REMOVE_VLAN(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_NON_802_11_REMOVE_VLAN) \ + ? TRUE : FALSE) +#define HAL_MAC_TX_DESC_SET_REMOVE_VLAN(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_NON_802_11_REMOVE_VLAN) +#define HAL_MAC_TX_DESC_UNSET_REMOVE_VLAN(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_NON_802_11_REMOVE_VLAN) + +#define HAL_MAC_TX_DESC_IS_VLAN(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_NON_802_11_VLAN_FIELD) \ + ? TRUE : FALSE) +#define HAL_MAC_TX_DESC_SET_VLAN(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_NON_802_11_VLAN_FIELD) +#define HAL_MAC_TX_DESC_UNSET_VLAN(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_NON_802_11_VLAN_FIELD) + +#define HAL_MAC_TX_DESC_IS_ETHERNET_II(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_NON_802_11_ETHERNET_II) \ + ? TRUE : FALSE) +#define HAL_MAC_TX_DESC_SET_ETHERNET_II(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_NON_802_11_ETHERNET_II) +#define HAL_MAC_TX_DESC_UNSET_ETHERNET_II(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_NON_802_11_ETHERNET_II) + +/* HF = 0x00/0x11, 802.11 normal/enhancement mode */ +#define HAL_MAC_TX_DESC_IS_EOSP(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_NON_802_11_EOSP) \ + ? TRUE : FALSE) +#define HAL_MAC_TX_DESC_SET_EOSP(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_NON_802_11_EOSP) +#define HAL_MAC_TX_DESC_UNSET_EOSP(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_NON_802_11_EOSP) + +/* HF = 0x11, 802.11 enhancement mode */ +#define HAL_MAC_TX_DESC_IS_AMSDU(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_ENH_802_11_AMSDU) \ + ? TRUE : FALSE) +#define HAL_MAC_TX_DESC_SET_AMSDU(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_ENH_802_11_AMSDU) +#define HAL_MAC_TX_DESC_UNSET_AMSDU(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_ENH_802_11_AMSDU) + +/* HF = 0x10, non-802.11 */ +#define HAL_MAC_TX_DESC_GET_802_11_HEADER_LENGTH(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucHeaderFormat, \ + TX_DESC_NOR_802_11_HEADER_LENGTH_MASK, \ + TX_DESC_NOR_802_11_HEADER_LENGTH_OFFSET) +#define HAL_MAC_TX_DESC_SET_802_11_HEADER_LENGTH(_prHwMacTxDesc, \ + _ucHdrLength) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucHeaderFormat), \ + ((uint8_t)_ucHdrLength), \ + TX_DESC_NOR_802_11_HEADER_LENGTH_MASK, \ + TX_DESC_NOR_802_11_HEADER_LENGTH_OFFSET) + +#define HAL_MAC_TX_DESC_GET_TXD_LENGTH(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucHeaderPadding, \ + TX_DESC_TXD_LENGTH_MASK, TX_DESC_TXD_LENGTH_OFFSET) +#define HAL_MAC_TX_DESC_SET_TXD_LENGTH(_prHwMacTxDesc, _ucHdrPadding) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucHeaderPadding), \ + ((uint8_t)_ucHdrPadding), \ + TX_DESC_TXD_LENGTH_MASK, TX_DESC_TXD_LENGTH_OFFSET) + +#define HAL_MAC_TX_DESC_GET_TXD_EXTEND_LENGTH(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucHeaderPadding, \ + TX_DESC_TXD_EXTEND_LENGTH_MASK, \ + TX_DESC_TXD_EXTEND_LENGTH_OFFSET) +#define HAL_MAC_TX_DESC_SET_TXD_EXTEND_LENGTH(_prHwMacTxDesc, _ucHdrPadding) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucHeaderPadding), \ + ((uint8_t)_ucHdrPadding), \ + TX_DESC_TXD_EXTEND_LENGTH_MASK, TX_DESC_TXD_EXTEND_LENGTH_OFFSET) + +#define HAL_MAC_TX_DESC_GET_HEADER_PADDING(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucHeaderPadding, \ + TX_DESC_HEADER_PADDING_LENGTH_MASK, \ + TX_DESC_HEADER_PADDING_LENGTH_OFFSET) +#define HAL_MAC_TX_DESC_SET_HEADER_PADDING(_prHwMacTxDesc, _ucHdrPadding) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucHeaderPadding), \ + ((uint8_t)_ucHdrPadding), \ + TX_DESC_HEADER_PADDING_LENGTH_MASK, \ + TX_DESC_HEADER_PADDING_LENGTH_OFFSET) + +#define HAL_MAC_TX_DESC_GET_UTXB_AMSDU(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucHeaderPadding, \ + TX_DESC_TXD_UTXB_AMSDU_MASK, TX_DESC_TXD_UTXB_AMSDU_OFFSET) +#define HAL_MAC_TX_DESC_SET_UTXB_AMSDU(_prHwMacTxDesc, _ucHdrPadding) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucHeaderPadding), \ + ((uint8_t)_ucHdrPadding), \ + TX_DESC_TXD_UTXB_AMSDU_MASK, TX_DESC_TXD_UTXB_AMSDU_OFFSET) + +#define HAL_MAC_TX_DESC_IS_HEADER_PADDING_IN_THE_HEAD(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderPadding & TX_DESC_HEADER_PADDING_MODE) \ + ? TRUE : FALSE) +#define HAL_MAC_TX_DESC_SET_HEADER_PADDING_IN_THE_HEAD(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderPadding |= TX_DESC_HEADER_PADDING_MODE) +#define HAL_MAC_TX_DESC_SET_HEADER_PADDING_IN_THE_TAIL(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderPadding &= ~TX_DESC_HEADER_PADDING_MODE) + +#define HAL_MAC_TX_DESC_GET_TID(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucHeaderPadding, \ + TX_DESC_TID_MASK, TX_DESC_TID_OFFSET) +#define HAL_MAC_TX_DESC_SET_TID(_prHwMacTxDesc, _ucTID) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucHeaderPadding), \ + ((uint8_t)_ucTID), TX_DESC_TID_MASK, TX_DESC_TID_OFFSET) + +#define HAL_MAC_TX_DESC_GET_PKT_FORMAT(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucOwnMAC, \ + TX_DESC_PACKET_FORMAT_MASK, \ + TX_DESC_PACKET_FORMAT_OFFSET) +#define HAL_MAC_TX_DESC_SET_PKT_FORMAT(_prHwMacTxDesc, _ucPktFormat) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucOwnMAC), \ + ((uint8_t)_ucPktFormat), \ + TX_DESC_PACKET_FORMAT_MASK, TX_DESC_PACKET_FORMAT_OFFSET) + +#define HAL_MAC_TX_DESC_GET_OWN_MAC_INDEX(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucOwnMAC, \ + TX_DESC_OWN_MAC_MASK, TX_DESC_OWN_MAC_OFFSET) +#define HAL_MAC_TX_DESC_SET_OWN_MAC_INDEX(_prHwMacTxDesc, _ucOwnMacIdx) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucOwnMAC), \ + ((uint8_t)_ucOwnMacIdx), \ + TX_DESC_OWN_MAC_MASK, TX_DESC_OWN_MAC_OFFSET) + +/* DW 2 */ +#define HAL_MAC_TX_DESC_GET_SUB_TYPE(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucType_SubType, \ + TX_DESC_SUB_TYPE_MASK, TX_DESC_SUB_TYPE_OFFSET) +#define HAL_MAC_TX_DESC_SET_SUB_TYPE(_prHwMacTxDesc, _ucSubType) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucType_SubType), \ + ((uint8_t)_ucSubType), \ + TX_DESC_SUB_TYPE_MASK, TX_DESC_SUB_TYPE_OFFSET) + +#define HAL_MAC_TX_DESC_GET_TYPE(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucType_SubType, \ + TX_DESC_TYPE_MASK, TX_DESC_TYPE_OFFSET) +#define HAL_MAC_TX_DESC_SET_TYPE(_prHwMacTxDesc, _ucType) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucType_SubType), \ + ((uint8_t)_ucType), TX_DESC_TYPE_MASK, TX_DESC_TYPE_OFFSET) + +#define HAL_MAC_TX_DESC_IS_NDP(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucType_SubType & TX_DESC_NDP)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_NDP(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucType_SubType |= TX_DESC_NDP) +#define HAL_MAC_TX_DESC_UNSET_NDP(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucType_SubType &= ~TX_DESC_NDP) + +#define HAL_MAC_TX_DESC_IS_NDPA(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucType_SubType & TX_DESC_NDPA)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_NDPA(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucType_SubType |= TX_DESC_NDPA) +#define HAL_MAC_TX_DESC_UNSET_NDPA(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucType_SubType &= ~TX_DESC_NDPA) + +#define HAL_MAC_TX_DESC_IS_SOUNDING_FRAME(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucFrag & TX_DESC_SOUNDING)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_SOUNDING_FRAME(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucFrag |= TX_DESC_SOUNDING) +#define HAL_MAC_TX_DESC_UNSET_SOUNDING_FRAME(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucFrag &= ~TX_DESC_SOUNDING) + +#define HAL_MAC_TX_DESC_IS_FORCE_RTS_CTS_EN(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucFrag & TX_DESC_FORCE_RTS_CTS)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_FORCE_RTS_CTS(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucFrag |= TX_DESC_FORCE_RTS_CTS) +#define HAL_MAC_TX_DESC_UNSET_FORCE_RTS_CTS(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucFrag &= ~TX_DESC_FORCE_RTS_CTS) + +#define HAL_MAC_TX_DESC_IS_BMC(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucFrag & TX_DESC_BROADCAST_MULTICAST)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_BMC(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->ucFrag |= TX_DESC_BROADCAST_MULTICAST) +#define HAL_MAC_TX_DESC_UNSET_BMC(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucFrag &= ~TX_DESC_BROADCAST_MULTICAST) + +#define HAL_MAC_TX_DESC_IS_BIP(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucFrag & TX_DESC_BIP_PROTECTED)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_BIP(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucFrag |= TX_DESC_BIP_PROTECTED) +#define HAL_MAC_TX_DESC_UNSET_BIP(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucFrag &= ~TX_DESC_BIP_PROTECTED) + +#define HAL_MAC_TX_DESC_IS_DURATION_CONTROL_BY_SW(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucFrag & TX_DESC_DURATION_FIELD_CONTROL)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_DURATION_CONTROL_BY_SW(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucFrag |= TX_DESC_DURATION_FIELD_CONTROL) +#define HAL_MAC_TX_DESC_SET_DURATION_CONTROL_BY_HW(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucFrag &= ~TX_DESC_DURATION_FIELD_CONTROL) + +#define HAL_MAC_TX_DESC_IS_HTC_EXIST(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucFrag & TX_DESC_HTC_EXISTS)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_HTC_EXIST(_prHwMacTxDesc) \ +((_prHwMacTxDesc)->ucFrag |= TX_DESC_HTC_EXISTS) +#define HAL_MAC_TX_DESC_UNSET_HTC_EXIST(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucFrag &= ~TX_DESC_HTC_EXISTS) + +#define HAL_MAC_TX_DESC_IS_FRAG_PACKET(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucFrag & TX_DESC_FRAGMENT_MASK)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_GET_FRAG_PACKET_POS(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucFrag, \ + TX_DESC_FRAGMENT_MASK, TX_DESC_FRAGMENT_OFFSET) +#define HAL_MAC_TX_DESC_SET_FRAG_PACKET_POS(_prHwMacTxDesc, _ucFragPos) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucFrag), ((uint8_t)_ucFragPos), \ + TX_DESC_FRAGMENT_MASK, TX_DESC_FRAGMENT_OFFSET) + +/* For driver */ +/* in unit of 32TU */ +#define HAL_MAC_TX_DESC_GET_REMAINING_LIFE_TIME(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucRemainingMaxTxTime) +#define HAL_MAC_TX_DESC_SET_REMAINING_LIFE_TIME(_prHwMacTxDesc, _ucLifeTime) \ + ((_prHwMacTxDesc)->ucRemainingMaxTxTime = (_ucLifeTime)) +/* in unit of ms (minimal value is about 40ms) */ +#define HAL_MAC_TX_DESC_GET_REMAINING_LIFE_TIME_IN_MS(_prHwMacTxDesc) \ + (TU_TO_MSEC(HAL_MAC_TX_DESC_GET_REMAINING_LIFE_TIME(_prHwMacTxDesc) \ + << TX_DESC_LIFE_TIME_UNIT_IN_POWER_OF_2)) +#define HAL_MAC_TX_DESC_SET_REMAINING_LIFE_TIME_IN_MS(_prHwMacTxDesc, \ + _u4LifeTimeMs) \ +do { \ + uint32_t u4LifeTimeInUnit = \ + ((MSEC_TO_USEC(_u4LifeTimeMs) / USEC_PER_TU) \ + >> TX_DESC_LIFE_TIME_UNIT_IN_POWER_OF_2); \ + if (u4LifeTimeInUnit >= BIT(8)) \ + u4LifeTimeInUnit = BITS(0, 7); \ + else if ((_u4LifeTimeMs != TX_DESC_TX_TIME_NO_LIMIT) && \ + (u4LifeTimeInUnit == TX_DESC_TX_TIME_NO_LIMIT)) \ + u4LifeTimeInUnit = 1; \ + HAL_MAC_TX_DESC_SET_REMAINING_LIFE_TIME(_prHwMacTxDesc, \ + (uint8_t)u4LifeTimeInUnit); \ +} while (0) + +#define HAL_MAC_TX_DESC_GET_POWER_OFFSET(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucPowerOffset, \ + TX_DESC_POWER_OFFSET_MASK, 0) +#define HAL_MAC_TX_DESC_SET_POWER_OFFSET(_prHwMacTxDesc, _ucPowerOffset) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucPowerOffset), \ + ((uint8_t)_ucPowerOffset), TX_DESC_POWER_OFFSET_MASK, 0) + +#define HAL_MAC_TX_DESC_IS_BA_DISABLE(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPowerOffset & TX_DESC_BA_DISABLE)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_BA_DISABLE(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset |= TX_DESC_BA_DISABLE) +#define HAL_MAC_TX_DESC_SET_BA_ENABLE(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset &= ~TX_DESC_BA_DISABLE) + +#define HAL_MAC_TX_DESC_IS_TIMING_MEASUREMENT(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPowerOffset & TX_DESC_TIMING_MEASUREMENT) \ + ? TRUE : FALSE) +#define HAL_MAC_TX_DESC_SET_TIMING_MEASUREMENT(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset |= TX_DESC_TIMING_MEASUREMENT) +#define HAL_MAC_TX_DESC_UNSET_TIMING_MEASUREMENT(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset &= ~TX_DESC_TIMING_MEASUREMENT) + +#define HAL_MAC_TX_DESC_IS_FIXED_RATE_ENABLE(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPowerOffset & TX_DESC_FIXED_RATE)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_FIXED_RATE_ENABLE(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset |= TX_DESC_FIXED_RATE) +#define HAL_MAC_TX_DESC_SET_FIXED_RATE_DISABLE(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset &= ~TX_DESC_FIXED_RATE) + +/* DW 3 */ +#define HAL_MAC_TX_DESC_IS_NO_ACK(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->u2TxCountLimit & TX_DESC_NO_ACK)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_NO_ACK(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2TxCountLimit |= TX_DESC_NO_ACK) +#define HAL_MAC_TX_DESC_UNSET_NO_ACK(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2TxCountLimit &= ~TX_DESC_NO_ACK) + +#define HAL_MAC_TX_DESC_IS_PROTECTION(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->u2TxCountLimit & TX_DESC_PROTECTED_FRAME) \ + ? TRUE : FALSE) +#define HAL_MAC_TX_DESC_SET_PROTECTION(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2TxCountLimit |= TX_DESC_PROTECTED_FRAME) +#define HAL_MAC_TX_DESC_UNSET_PROTECTION(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2TxCountLimit &= ~TX_DESC_PROTECTED_FRAME) + +#define HAL_MAC_TX_DESC_IS_EXTEND_MORE_DATA(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->u2TxCountLimit & TX_DESC_EXTEND_MORE_DATA) \ + ? TRUE : FALSE) +#define HAL_MAC_TX_DESC_SET_EXTEND_MORE_DATA(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2TxCountLimit |= TX_DESC_EXTEND_MORE_DATA) +#define HAL_MAC_TX_DESC_UNSET_EXTEND_MORE_DATA(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2TxCountLimit &= ~TX_DESC_EXTEND_MORE_DATA) + +#define HAL_MAC_TX_DESC_IS_EXTEND_EOSP(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->u2TxCountLimit & TX_DESC_EXTEND_EOSP)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_EXTEND_EOSP(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2TxCountLimit |= TX_DESC_EXTEND_EOSP) +#define HAL_MAC_TX_DESC_UNSET_EXTEND_EOSP(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2TxCountLimit &= ~TX_DESC_EXTEND_EOSP) + +#define HAL_MAC_TX_DESC_GET_SW_RESERVED(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->u2TxCountLimit, \ + TX_DESC_SW_RESERVED_MASK, TX_DESC_SW_RESERVED_OFFSET) +#define HAL_MAC_TX_DESC_SET_SW_RESERVED(_prHwMacTxDesc, _ucSwReserved) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2TxCountLimit), \ + ((uint8_t)_ucSwReserved), \ + TX_DESC_SW_RESERVED_MASK, TX_DESC_SW_RESERVED_OFFSET) +#define HAL_MAC_TX_DESC_GET_TX_COUNT(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->u2TxCountLimit, \ + TX_DESC_TX_COUNT_MASK, TX_DESC_TX_COUNT_OFFSET) +#define HAL_MAC_TX_DESC_SET_TX_COUNT(_prHwMacTxDesc, _ucTxCountLimit) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2TxCountLimit), \ + ((uint8_t)_ucTxCountLimit), \ + TX_DESC_TX_COUNT_MASK, TX_DESC_TX_COUNT_OFFSET) +#define HAL_MAC_TX_DESC_GET_REMAINING_TX_COUNT(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->u2TxCountLimit, \ + TX_DESC_REMAINING_TX_COUNT_MASK, \ + TX_DESC_REMAINING_TX_COUNT_OFFSET) +#define HAL_MAC_TX_DESC_SET_REMAINING_TX_COUNT(_prHwMacTxDesc, \ + _ucTxCountLimit) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2TxCountLimit), \ + ((uint8_t)_ucTxCountLimit), \ + TX_DESC_REMAINING_TX_COUNT_MASK, \ + TX_DESC_REMAINING_TX_COUNT_OFFSET) +#define HAL_MAC_TX_DESC_GET_SEQUENCE_NUMBER(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->u2SN, TX_DESC_SEQUENCE_NUMBER, 0) +#define HAL_MAC_TX_DESC_SET_SEQUENCE_NUMBER(_prHwMacTxDesc, _u2SN) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2SN), ((uint16_t)_u2SN), \ + TX_DESC_SEQUENCE_NUMBER, 0) +#define HAL_MAC_TX_DESC_SET_HW_RESERVED(_prHwMacTxDesc, _ucHwReserved) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2SN), ((uint8_t)_ucHwReserved), \ + TX_DESC_HW_RESERVED_MASK, TX_DESC_HW_RESERVED_OFFSET) +#define HAL_MAC_TX_DESC_IS_TXD_SN_VALID(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->u2SN & TX_DESC_SN_IS_VALID)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_TXD_SN_VALID(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2SN |= TX_DESC_SN_IS_VALID) +#define HAL_MAC_TX_DESC_SET_TXD_SN_INVALID(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2SN &= ~TX_DESC_SN_IS_VALID) + +#define HAL_MAC_TX_DESC_IS_TXD_PN_VALID(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->u2SN & TX_DESC_PN_IS_VALID)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_TXD_PN_VALID(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2SN |= TX_DESC_PN_IS_VALID) +#define HAL_MAC_TX_DESC_SET_TXD_PN_INVALID(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2SN &= ~TX_DESC_PN_IS_VALID) + +#define HAL_MAC_TX_DESC_ASSIGN_SN_BY_SW(_prHwMacTxDesc, _u2SN) \ +{ \ + HAL_MAC_TX_DESC_SET_SEQUENCE_NUMBER(_prHwMacTxDesc, _u2SN); \ + HAL_MAC_TX_DESC_SET_TXD_SN_VALID(_prHwMacTxDesc); \ +} +#define HAL_MAC_TX_DESC_ASSIGN_SN_BY_HW(_prHwMacTxDesc) \ +{ \ + HAL_MAC_TX_DESC_SET_SEQUENCE_NUMBER(_prHwMacTxDesc, 0); \ + HAL_MAC_TX_DESC_SET_TXD_SN_INVALID(_prHwMacTxDesc); \ +} + +/* DW 4 */ +#define HAL_MAC_TX_DESC_GET_PN(_prHwMacTxDesc, _u4PN_0_31, _u2PN_32_47) \ +{ \ + ((uint32_t)_u4PN_0_31) = (_prHwMacTxDesc)->u4PN1; \ + ((uint16_t)_u2PN_32_47) = (_prHwMacTxDesc)->u2PN2; \ +} +#define HAL_MAC_TX_DESC_SET_PN(_prHwMacTxDesc, _u4PN_0_31, _u2PN_32_47) \ +{ \ + (_prHwMacTxDesc)->u4PN1 = ((uint32_t)_u4PN_0_31); \ + (_prHwMacTxDesc)->u2PN2 = ((uint16_t)_u2PN_32_47); \ +} + +#define HAL_MAC_TX_DESC_ASSIGN_PN_BY_SW(_prTxDesc, _u4PN_0_31, _u2PN_32_47) \ +{ \ + HAL_MAC_TX_DESC_SET_PN(_prTxDesc, _u4PN_0_31, _u2PN_32_47); \ + HAL_MAC_TX_DESC_SET_TXD_PN_VALID(_prTxDesc); \ +} +#define HAL_MAC_TX_DESC_ASSIGN_PSN_BY_HW(_prHwMacTxDesc) \ +{ \ + HAL_MAC_TX_DESC_SET_PN(_prHwMacTxDesc, 0, 0); \ + HAL_MAC_TX_DESC_SET_TXD_PN_INVALID(_prHwMacTxDesc); \ +} + +/* DW 5 */ +#define HAL_MAC_TX_DESC_GET_PID(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPID) +#define HAL_MAC_TX_DESC_SET_PID(_prHwMacTxDesc, _ucPID) \ + (((_prHwMacTxDesc)->ucPID) = (_ucPID)) + +#define HAL_MAC_TX_DESC_GET_TXS_FORMAT(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucTxStatus, \ + TX_DESC_TX_STATUS_FORMAT, TX_DESC_TX_STATUS_FORMAT_OFFSET) +#define HAL_MAC_TX_DESC_SET_TXS_FORMAT(_prHwMacTxDesc, _ucTXSFormat) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucTxStatus), \ + ((uint8_t)_ucTXSFormat), \ + TX_DESC_TX_STATUS_FORMAT, TX_DESC_TX_STATUS_FORMAT_OFFSET) + +#define HAL_MAC_TX_DESC_IS_TXS_TO_MCU(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucTxStatus & TX_DESC_TX_STATUS_TO_MCU)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_TXS_TO_MCU(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucTxStatus |= TX_DESC_TX_STATUS_TO_MCU) +#define HAL_MAC_TX_DESC_UNSET_TXS_TO_MCU(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucTxStatus &= ~TX_DESC_TX_STATUS_TO_MCU) + +#define HAL_MAC_TX_DESC_IS_TXS_TO_HOST(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucTxStatus & TX_DESC_TX_STATUS_TO_HOST)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_TXS_TO_HOST(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucTxStatus |= TX_DESC_TX_STATUS_TO_HOST) +#define HAL_MAC_TX_DESC_UNSET_TXS_TO_HOST(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucTxStatus &= ~TX_DESC_TX_STATUS_TO_HOST) + +#define HAL_MAC_TX_DESC_IS_DA_FROM_WTBL(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPowerOffset & TX_DESC_DA_SOURCE)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_DA_FROM_WTBL(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset |= TX_DESC_DA_SOURCE) +#define HAL_MAC_TX_DESC_SET_DA_FROM_MSDU(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset &= ~TX_DESC_DA_SOURCE) + +#define HAL_MAC_TX_DESC_IS_SW_PM_CONTROL(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPowerOffset & TX_DESC_POWER_MANAGEMENT_CONTROL) \ + ? TRUE : FALSE) +#define HAL_MAC_TX_DESC_SET_SW_PM_CONTROL(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset |= TX_DESC_POWER_MANAGEMENT_CONTROL) +#define HAL_MAC_TX_DESC_SET_HW_PM_CONTROL(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset &= ~TX_DESC_POWER_MANAGEMENT_CONTROL) + +/* DW 6 */ +#define HAL_MAC_TX_DESC_SET_FR_BW(_prHwMacTxDesc, ucBw) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2AntID), \ + ((uint8_t)ucBw), TX_DESC_BANDWIDTH_MASK, TX_DESC_BANDWIDTH_OFFSET) + +#define HAL_MAC_TX_DESC_SET_FR_DYNAMIC_BW_RTS(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2AntID |= TX_DESC_DYNAMIC_BANDWIDTH) + +#define HAL_MAC_TX_DESC_SET_FR_ANTENNA_ID(_prHwMacTxDesc, _ucAntId) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2AntID), \ + ((uint8_t)_ucAntId), \ + TX_DESC_ANTENNA_INDEX_MASK, TX_DESC_ANTENNA_INDEX_OFFSET) + +#define HAL_MAC_TX_DESC_SET_FR_RATE(_prHwMacTxDesc, _u2RatetoFixed) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2FixedRate), \ + ((uint8_t)_u2RatetoFixed), \ + TX_DESC_FIXDE_RATE_MASK, TX_DESC_FIXDE_RATE_OFFSET) + +#define HAL_MAC_TX_DESC_SET_FR_BF(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2FixedRate |= TX_DESC_BF) + +#define HAL_MAC_TX_DESC_SET_FR_LDPC(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2FixedRate |= TX_DESC_LDPC) + +#define HAL_MAC_TX_DESC_SET_FR_SHORT_GI(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2FixedRate |= TX_DESC_GUARD_INTERVAL) + +#define HAL_MAC_TX_DESC_SET_FR_NORMAL_GI(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2FixedRate &= ~TX_DESC_GUARD_INTERVAL) + +#define HAL_MAC_TX_DESC_IS_CR_FIXED_RATE_MODE(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->u2FixedRate & TX_DESC_FIXED_RATE_MODE)?TRUE:FALSE) + +#define HAL_MAC_TX_DESC_SET_FIXED_RATE_MODE_TO_DESC(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2FixedRate &= ~TX_DESC_FIXED_RATE_MODE) +#define HAL_MAC_TX_DESC_SET_FIXED_RATE_MODE_TO_CR(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2FixedRate |= TX_DESC_FIXED_RATE_MODE) + +/* DW 7 */ +#define HAL_MAC_TX_DESC_SET_SPE_IDX(_prHwMacTxDesc, _ucSpeIdx) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2SwTxTime), \ + ((uint16_t)_ucSpeIdx), \ + TX_DESC_SPE_EXT_IDX_MASK, TX_DESC_SPE_EXT_IDX_OFFSET) + +#define HAL_MAC_TX_DESC_IS_HW_AMSDU(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->u2PseFid & TX_DESC_HW_AMSDU)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_HW_AMSDU(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2PseFid |= TX_DESC_HW_AMSDU) +#define HAL_MAC_TX_DESC_UNSET_HW_AMSDU(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2PseFid &= ~TX_DESC_HW_AMSDU) + +#define HAL_MAC_TX_DESC_IS_HIF_ERR(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->u2PseFid & TX_DESC_HIF_ERR)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_HIF_ERR(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2PseFid |= TX_DESC_HIF_ERR) +#define HAL_MAC_TX_DESC_UNSET_HIF_ERR(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2PseFid &= ~TX_DESC_HIF_ERR) + + +#define nicTxReleaseResource_PSE(prAdapter, ucTc, u4PageCount, fgReqLock) \ + nicTxReleaseResource(prAdapter, ucTc, u4PageCount, fgReqLock, FALSE) + +#define nicTxReleaseResource_PLE(prAdapter, ucTc, u4PageCount, fgReqLock) \ + nicTxReleaseResource(prAdapter, ucTc, u4PageCount, fgReqLock, TRUE) +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +void nicTxInitialize(IN struct ADAPTER *prAdapter); + +uint32_t nicTxAcquireResource(IN struct ADAPTER *prAdapter, + IN uint8_t ucTC, IN uint32_t u4PageCount, + IN u_int8_t fgReqLock); + +uint32_t nicTxPollingResource(IN struct ADAPTER *prAdapter, + IN uint8_t ucTC); + +u_int8_t nicTxReleaseResource(IN struct ADAPTER *prAdapter, + IN uint8_t ucTc, IN uint32_t u4PageCount, + IN u_int8_t fgReqLock, IN u_int8_t fgPLE); + +void nicTxReleaseMsduResource(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfoListHead); + +uint32_t nicTxResetResource(IN struct ADAPTER *prAdapter); + +#if defined(_HIF_SDIO) +uint32_t nicTxGetAdjustableResourceCnt(IN struct ADAPTER *prAdapter); +#endif + +uint16_t nicTxGetResource(IN struct ADAPTER *prAdapter, + IN uint8_t ucTC); + +uint8_t nicTxGetFrameResourceType(IN uint8_t eFrameType, + IN struct MSDU_INFO *prMsduInfo); + +uint8_t nicTxGetCmdResourceType(IN struct CMD_INFO *prCmdInfo); + +u_int8_t nicTxSanityCheckResource(IN struct ADAPTER *prAdapter); + +void nicTxFillDesc(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, OUT uint8_t *prTxDescBuffer, + OUT uint32_t *pu4TxDescLength); + +void nicTxFillDataDesc(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +void nicTxComposeSecurityFrameDesc(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, + OUT uint8_t *prTxDescBuffer, OUT uint8_t *pucTxDescLength); + +uint32_t nicTxMsduInfoList(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfoListHead); + +uint8_t nicTxGetTxQByTc(IN struct ADAPTER *prAdapter, IN uint8_t ucTc); + +#if CFG_SUPPORT_MULTITHREAD +uint32_t nicTxMsduInfoListMthread(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfoListHead); + +uint32_t nicTxMsduQueueMthread(IN struct ADAPTER *prAdapter); + +uint32_t nicTxGetMsduPendingCnt(IN struct ADAPTER *prAdapter); +#endif + +uint32_t nicTxMsduQueue(IN struct ADAPTER *prAdapter, + uint8_t ucPortIdx, struct QUE *prQue); + +uint32_t nicTxCmd(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t ucTC); + +void nicTxRelease(IN struct ADAPTER *prAdapter, + IN u_int8_t fgProcTxDoneHandler); + +void nicTxReleaseSafe(IN struct ADAPTER *prAdapter, + IN u_int8_t fgProcTxDoneHandler); + +void nicProcessTxInterrupt(IN struct ADAPTER *prAdapter); + +void nicTxFreeMsduInfoPacket(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfoListHead); + +void nicTxReturnMsduInfo(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfoListHead); + +u_int8_t nicTxFillMsduInfo(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN void *prNdisPacket); + +uint32_t nicTxAdjustTcq(IN struct ADAPTER *prAdapter); + +uint32_t nicTxFlush(IN struct ADAPTER *prAdapter); + +#if CFG_ENABLE_FW_DOWNLOAD +uint32_t nicTxInitCmd(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint16_t u2Port); + +uint32_t nicTxInitResetResource(IN struct ADAPTER *prAdapter); +#endif + +uint32_t nicTxEnqueueMsdu(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +uint8_t nicTxGetWlanIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, IN uint8_t ucStaRecIdx); + +u_int8_t nicTxIsMgmtResourceEnough(IN struct ADAPTER *prAdapter); + +uint32_t nicTxGetFreeCmdCount(IN struct ADAPTER *prAdapter); + +uint32_t nicTxGetPageCount(IN struct ADAPTER *prAdapter, + IN uint32_t u4FrameLength, IN u_int8_t fgIncludeDesc); + +uint32_t nicTxGetCmdPageCount(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo); + +uint32_t nicTxGenerateDescTemplate(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +void nicTxFreeDescTemplate(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +void nicTxSetHwAmsduDescTemplate(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN uint8_t ucTid, IN u_int8_t fgSet); + +void nicTxFreePacket(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN u_int8_t fgDrop); + +void nicTxSetMngPacket(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN uint8_t ucBssIndex, + IN uint8_t ucStaRecIndex, + IN uint8_t ucMacHeaderLength, + IN uint16_t u2FrameLength, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler, + IN uint8_t ucRateMode); + +void nicTxSetDataPacket(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN uint8_t ucBssIndex, + IN uint8_t ucStaRecIndex, + IN uint8_t ucMacHeaderLength, + IN uint16_t u2FrameLength, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler, + IN uint8_t ucRateMode, + IN enum ENUM_TX_PACKET_SRC eSrc, IN uint8_t ucTID, + IN u_int8_t fgIs802_11Frame, IN u_int8_t fgIs1xFrame); + +void nicTxFillDescByPktOption(IN struct MSDU_INFO *prMsduInfo, + IN struct HW_MAC_TX_DESC *prTxDesc); + +void nicTxConfigPktOption(IN struct MSDU_INFO *prMsduInfo, + IN uint32_t u4OptionMask, IN u_int8_t fgSetOption); + +void nicTxFillDescByPktControl(struct MSDU_INFO *prMsduInfo, + struct HW_MAC_TX_DESC *prTxDesc); + +void nicTxConfigPktControlFlag(IN struct MSDU_INFO *prMsduInfo, + IN uint8_t ucControlFlagMask, IN u_int8_t fgSetFlag); + +void nicTxSetPktLifeTime(IN struct MSDU_INFO *prMsduInfo, + IN uint32_t u4TxLifeTimeInMs); + +void nicTxSetPktRetryLimit(IN struct MSDU_INFO *prMsduInfo, + IN uint8_t ucRetryLimit); + +void nicTxSetPktPowerOffset(IN struct MSDU_INFO *prMsduInfo, + IN int8_t cPowerOffset); + +void nicTxSetPktSequenceNumber(IN struct MSDU_INFO *prMsduInfo, + IN uint16_t u2SN); + +void nicTxSetPktMacTxQue(IN struct MSDU_INFO *prMsduInfo, + IN uint8_t ucMacTxQue); + +void nicTxSetPktFixedRateOptionFull(struct MSDU_INFO *prMsduInfo, + uint16_t u2RateCode, uint8_t ucBandwidth, u_int8_t fgShortGI, + u_int8_t fgLDPC, u_int8_t fgDynamicBwRts, u_int8_t fgBeamforming, + uint8_t ucAntennaIndex); + +void nicTxSetPktFixedRateOption(IN struct MSDU_INFO *prMsduInfo, + IN uint16_t u2RateCode, IN uint8_t ucBandwidth, + IN u_int8_t fgShortGI, + IN u_int8_t fgDynamicBwRts); + +void nicTxSetPktLowestFixedRate(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +void nicTxSetPktMoreData(IN struct MSDU_INFO *prCurrentMsduInfo, + IN u_int8_t fgSetMoreDataBit); + +void nicTxSetPktEOSP(IN struct MSDU_INFO *prCurrentMsduInfo, + IN u_int8_t fgSetEOSPBit); + +uint8_t nicTxAssignPID(IN struct ADAPTER *prAdapter, + IN uint8_t ucWlanIndex); + +uint32_t +nicTxDummyTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +void nicTxUpdateBssDefaultRate(IN struct BSS_INFO *prBssInfo); + +void nicTxUpdateStaRecDefaultRate(IN struct STA_RECORD *prStaRec); + +void nicTxPrintMetRTP(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN void *prPacket, + IN uint32_t u4PacketLen, IN u_int8_t bFreeSkb); + +void nicTxProcessTxDoneEvent(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); + +void nicTxChangeDataPortByAc(struct STA_RECORD *prStaRec, uint8_t ucAci, + u_int8_t fgToMcu); + +void nicTxHandleRoamingDone(struct ADAPTER *prAdapter, + struct STA_RECORD *prOldStaRec, + struct STA_RECORD *prNewStaRec); + +void nicTxMsduDoneCb(IN struct GLUE_INFO *prGlueInfo, IN struct QUE *prQue); + +void nicTxCancelSendingCmd(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo); +uint32_t nicTxGetMaxPageCntPerFrame(IN struct ADAPTER *prAdapter); + +/* TX Direct functions : BEGIN */ +void nicTxDirectStartCheckQTimer(IN struct ADAPTER *prAdapter); +void nicTxDirectClearSkbQ(IN struct ADAPTER *prAdapter); +void nicTxDirectClearHifQ(IN struct ADAPTER *prAdapter); +void nicTxDirectClearStaPsQ(IN struct ADAPTER *prAdapter, + uint8_t ucStaRecIndex); +void nicTxDirectClearBssAbsentQ(IN struct ADAPTER *prAdapter, + uint8_t ucBssIndex); +void nicTxDirectClearAllStaPsQ(IN struct ADAPTER *prAdapter); + +#if KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE +void nicTxDirectTimerCheckSkbQ(struct timer_list *timer); +void nicTxDirectTimerCheckHifQ(struct timer_list *timer); +#else +void nicTxDirectTimerCheckSkbQ(unsigned long data); +void nicTxDirectTimerCheckHifQ(unsigned long data); +#endif + +uint32_t nicTxDirectStartXmit(struct sk_buff *prSkb, + struct GLUE_INFO *prGlueInfo); +/* TX Direct functions : END */ + +uint32_t nicTxResourceGetPleFreeCount(IN struct ADAPTER *prAdapter, + IN uint8_t ucTC); +u_int8_t nicTxResourceIsPleCtrlNeeded(IN struct ADAPTER *prAdapter, + IN uint8_t ucTC); +void nicTxResourceUpdate_v1(IN struct ADAPTER *prAdapter); +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _NIC_TX_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/nic_umac.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/nic_umac.h new file mode 100644 index 0000000000000..a6a46f57668ab --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/nic_umac.h @@ -0,0 +1,140 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/ + * MT6620_WIFI_DRIVER_V2_3/include/nic/nic_umac.h#1 + */ + +/*! \file "nic_umac.h" + * \brief The declaration of the nic umac debug functions + * + */ + + +#ifndef _NIC_UMAC_H +#define _NIC_UMAC_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 + ******************************************************************************* + */ + +#define UMAC_FID_MASK 0xFFF + +#define UMAC_FID_FAULT 0xFFF + +#define UMAC_PLE_CFG_POOL_INDEX 0 +#define UMAC_PSE_CFG_POOL_INDEX 1 + +#define UMAC_PG_HIF0_GROUP_0 0 +#define UMAC_PG_HIF1_GROUP_1 1 +#define UMAC_PG_CPU_GROUP_2 2 +#define UMAC_PG_LMAC0_GROUP_3 3 +#define UMAC_PG_LMAC1_GROUP_4 4 +#define UMAC_PG_LMAC2_GROUP_5 5 +#define UMAC_PG_PLE_GROUP_6 6 + +#define UMAC_PBUF_CTRL_TOTAL_PAGE_NUM_MASK BITS(0, 11) +#define UMAC_PBUF_CTRL_TOTAL_PAGE_NUM_OFFSET 0 + +#define UMAC_FREEPG_CNT_FREEPAGE_CNT_MASK BITS(0, 11) +#define UMAC_FREEPG_CNT_FREEPAGE_CNT_OFFSET 0 + +#define UMAC_FREEPG_CNT_FFA_CNT_MASK BITS(16, 27) +#define UMAC_FREEPG_CNT_FFA_CNT_OFFSET 16 + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +OUT u_int8_t +halUmacInfoGetMiscStatus(IN struct ADAPTER *prAdapter, + IN struct UMAC_STAT2_GET *pUmacStat2Get); + +#endif /* _NIC_UMAC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/p2p.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/p2p.h new file mode 100644 index 0000000000000..3cecd2e3b8681 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/p2p.h @@ -0,0 +1,357 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/nic/p2p.h#3 + */ + + +#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 + +/* Device Capability Definition. */ +#define P2P_MAXIMUM_NOA_COUNT 8 + +#define P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE 51 /* Contains 6 sub-band. */ + +/* Memory Size Definition. */ +#define P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE 768 +#define WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE 300 + +#define P2P_WILDCARD_SSID "DIRECT-" + +/* Device Charactoristic. */ +/* 1000 is too short , the deauth would block in the queue */ +#define P2P_AP_CHNL_HOLD_TIME_MS 5000 +#define P2P_DEFAULT_LISTEN_CHANNEL 1 + +#if (CFG_SUPPORT_DFS_MASTER == 1) +#define P2P_AP_CAC_WEATHER_CHNL_HOLD_TIME_MS (600*1000) +#endif + +#define P2P_DEAUTH_TIMEOUT_TIME_MS 1000 + +#define P2P_SAA_RETRY_COUNT 5 + +/****************************************************************************** + * M A C R O S + ****************************************************************************** + */ + +#if DBG +#define ASSERT_BREAK(_exp) \ + { \ + if (!(_exp)) { \ + ASSERT(FALSE); \ + break; \ + } \ + } + +#else +#define ASSERT_BREAK(_exp) +#endif + +#define p2pChangeMediaState(_prAdapter, _prP2pBssInfo, _eNewMediaState) \ + (_prP2pBssInfo->eConnectionState = (_eNewMediaState)) + +/****************************************************************************** + * D A T A T Y P E S + ****************************************************************************** + */ +/* if driver need wait for a longger time when do p2p connection */ +enum ENUM_P2P_CONNECT_STATE { + P2P_CNN_NORMAL = 0, + P2P_CNN_GO_NEG_REQ, + P2P_CNN_GO_NEG_RESP, + P2P_CNN_GO_NEG_CONF, + P2P_CNN_INVITATION_REQ, + P2P_CNN_INVITATION_RESP, + P2P_CNN_DEV_DISC_REQ, + P2P_CNN_DEV_DISC_RESP, + P2P_CNN_PROV_DISC_REQ, + P2P_CNN_PROV_DISC_RES +}; + + +struct P2P_INFO { + uint32_t u4DeviceNum; + enum ENUM_P2P_CONNECT_STATE eConnState; + struct EVENT_P2P_DEV_DISCOVER_RESULT + arP2pDiscoverResult[CFG_MAX_NUM_BSS_LIST]; + uint8_t *pucCurrIePtr; + /* A common pool for IE of all scan results. */ + uint8_t aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN]; + uint8_t ucExtendChanFlag; +}; + +enum ENUM_P2P_PEER_TYPE { + ENUM_P2P_PEER_GROUP, + ENUM_P2P_PEER_DEVICE, + ENUM_P2P_PEER_NUM +}; + +struct P2P_DEVICE_INFO { + uint8_t aucDevAddr[PARAM_MAC_ADDR_LEN]; + uint8_t aucIfAddr[PARAM_MAC_ADDR_LEN]; + uint8_t ucDevCapabilityBitmap; + int32_t i4ConfigMethod; + uint8_t aucPrimaryDeviceType[8]; + uint8_t aucSecondaryDeviceType[8]; + uint8_t aucDeviceName[P2P_DEVICE_NAME_LENGTH]; +}; + +struct P2P_GROUP_INFO { + struct PARAM_SSID rGroupID; + struct P2P_DEVICE_INFO rGroupOwnerInfo; + uint8_t ucMemberNum; + struct P2P_DEVICE_INFO arMemberInfo[P2P_MEMBER_NUM]; +}; + +struct P2P_NETWORK_INFO { + enum ENUM_P2P_PEER_TYPE eNodeType; + + union { + struct P2P_GROUP_INFO rGroupInfo; + struct P2P_DEVICE_INFO rDeviceInfo; + } node; +}; + +struct P2P_NETWORK_LIST { + uint8_t ucNetworkNum; + struct P2P_NETWORK_INFO rP2PNetworkInfo[P2P_NETWORK_NUM]; +}; + +struct P2P_DISCONNECT_INFO { + uint8_t ucRole; + uint8_t ucRsv[3]; +}; + +struct P2P_SSID_STRUCT { + uint8_t aucSsid[32]; + uint8_t ucSsidLen; +}; + +struct P2P_SCAN_REQ_INFO { + enum ENUM_SCAN_TYPE eScanType; + enum ENUM_SCAN_CHANNEL eChannelSet; + uint16_t u2PassiveDewellTime; + uint8_t ucSeqNumOfScnMsg; + u_int8_t fgIsAbort; + u_int8_t fgIsScanRequest; + uint8_t ucNumChannelList; + struct RF_CHANNEL_INFO + arScanChannelList[MAXIMUM_OPERATION_CHANNEL_LIST]; + uint32_t u4BufLength; + uint8_t aucIEBuf[MAX_IE_LENGTH]; + uint8_t ucSsidNum; + /* Currently we can only take one SSID scan request */ + struct P2P_SSID_STRUCT arSsidStruct[SCN_SSID_MAX_NUM]; +}; + +struct P2P_CHNL_REQ_INFO { + struct LINK rP2pChnlReqLink; + u_int8_t fgIsChannelRequested; + uint8_t ucSeqNumOfChReq; + uint64_t u8Cookie; + uint8_t ucReqChnlNum; + enum ENUM_BAND eBand; + enum ENUM_CHNL_EXT eChnlSco; + uint8_t ucOriChnlNum; + enum ENUM_CHANNEL_WIDTH eChannelWidth; /*VHT operation ie */ + uint8_t ucCenterFreqS1; + uint8_t ucCenterFreqS2; + enum ENUM_BAND eOriBand; + enum ENUM_CHNL_EXT eOriChnlSco; + uint32_t u4MaxInterval; + enum ENUM_CH_REQ_TYPE eChnlReqType; +#if CFG_SUPPORT_NFC_BEAM_PLUS + uint32_t NFC_BEAM; /*NFC Beam + Indication */ +#endif +}; + +/* Glubal Connection Settings. */ +struct P2P_CONNECTION_SETTINGS { + /*UINT_8 ucRfChannelListSize;*/ +#if P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE + /*UINT_8 aucChannelEntriesField[P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE];*/ +#endif + + u_int8_t fgIsApMode; +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + u_int8_t fgIsWPSMode; +#endif +}; + +struct NOA_TIMING { + u_int8_t fgIsInUse; /* Indicate if this entry is in use or not */ + uint8_t ucCount; /* Count */ + + uint8_t aucReserved[2]; + + uint32_t u4Duration; /* Duration */ + uint32_t u4Interval; /* Interval */ + uint32_t u4StartTime; /* Start Time */ +}; + +struct P2P_SPECIFIC_BSS_INFO { + /* For GO(AP) Mode - Compose TIM IE */ + /*UINT_16 u2SmallestAID;*//* TH3 multiple P2P */ + /*UINT_16 u2LargestAID;*//* TH3 multiple P2P */ + /*UINT_8 ucBitmapCtrl;*//* TH3 multiple P2P */ + /* UINT_8 aucPartialVirtualBitmap[MAX_LEN_TIM_PARTIAL_BMP]; */ + + /* For GC/GO OppPS */ + u_int8_t fgEnableOppPS; + uint16_t u2CTWindow; + + /* For GC/GO NOA */ + uint8_t ucNoAIndex; + uint8_t ucNoATimingCount; /* Number of NoA Timing */ + struct NOA_TIMING arNoATiming[P2P_MAXIMUM_NOA_COUNT]; + + u_int8_t fgIsNoaAttrExisted; + + /* For P2P Device */ + /* TH3 multiple P2P */ /* Regulatory Class for channel. */ + /*UINT_8 ucRegClass;*/ + /* Linten Channel only on channels 1, 6 and 11 in the 2.4 GHz. */ + /*UINT_8 ucListenChannel;*//* TH3 multiple P2P */ + + /* Operating Channel, should be one of channel */ + /* list in p2p connection settings. */ + uint8_t ucPreferredChannel; + enum ENUM_CHNL_EXT eRfSco; + enum ENUM_BAND eRfBand; + + /* Extended Listen Timing. */ + uint16_t u2AvailabilityPeriod; + uint16_t u2AvailabilityInterval; + + uint16_t u2AttributeLen; + uint8_t aucAttributesCache[P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; + + /*UINT_16 u2WscAttributeLen;*//* TH3 multiple P2P */ + /* TH3 multiple P2P */ + /*UINT_8 aucWscAttributesCache[WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE];*/ + + /*UINT_8 aucGroupID[MAC_ADDR_LEN];*//* TH3 multiple P2P */ + uint16_t u2GroupSsidLen; + uint8_t aucGroupSsid[ELEM_MAX_LEN_SSID]; + + struct PARAM_CUSTOM_NOA_PARAM_STRUCT rNoaParam; + struct PARAM_CUSTOM_OPPPS_PARAM_STRUCT rOppPsParam; + + uint16_t u2WpaIeLen; + uint8_t aucWpaIeBuffer[ELEM_HDR_LEN + ELEM_MAX_LEN_WPA]; +}; + +struct P2P_QUEUED_ACTION_FRAME { + uint8_t ucRoleIdx; + int32_t u4Freq; + uint8_t *prHeader; + uint16_t u2Length; +}; + +/****************************************************************************** + * P U B L I C D A T A + ****************************************************************************** + */ + +/****************************************************************************** + * P R I V A T E D A T A + ****************************************************************************** + */ + +/****************************************************************************** + * F U N C T I O N D E C L A R A T I O N S + ****************************************************************************** + */ + +#endif /*_P2P_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/p2p_cmd_buf.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/p2p_cmd_buf.h new file mode 100644 index 0000000000000..7dbf951a20789 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/p2p_cmd_buf.h @@ -0,0 +1,121 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + + +#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 + ****************************************************************************** + */ + +/****************************************************************************** + * 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 + ****************************************************************************** + */ + + +/*--------------------------------------------------------------*/ +/* Firmware Command Packer */ +/*--------------------------------------------------------------*/ +uint32_t +wlanoidSendSetQueryP2PCmd(IN struct ADAPTER *prAdapter, IN uint8_t ucCID, + IN uint8_t ucBssIdx, IN u_int8_t fgSetQuery, + IN u_int8_t fgNeedResp, IN u_int8_t fgIsOid, + IN PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + IN PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + IN uint32_t u4SetQueryInfoLen, + IN uint8_t *pucInfoBuffer, OUT void *pvSetQueryBuffer, + IN uint32_t u4SetQueryBufferLen); + +#endif /* _P2P_CMD_BUF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/p2p_mac.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/p2p_mac.h new file mode 100644 index 0000000000000..5d74ee9b18436 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/p2p_mac.h @@ -0,0 +1,438 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 + ****************************************************************************** + */ + +/* --------------- WPS Data Element Definitions --------------- */ +/* P2P 4.2.2 - General WSC Attribute */ +/* ID(2 octet) + Length(2 octets) */ +#define WSC_ATTRI_HDR_LEN 4 +#define WSC_ATTRI_MAX_LEN_VERSION 1 +#define WSC_ATTRI_MAX_LEN_DEVICE_PASSWORD_ID 2 +#define WSC_ATTRI_LEN_CONFIG_METHOD 2 + +/* --------------- WFA P2P IE --------------- */ +/* P2P 4.1.1 - P2P IE format */ +#define P2P_OUI_TYPE_LEN 4 +/* == OFFSET_OF(IE_P2P_T, aucP2PAttributes[0]) */ +#define P2P_IE_OUI_HDR (ELEM_HDR_LEN + P2P_OUI_TYPE_LEN) + +/* 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 */ +#define P2P_ATTRI_MAX_LEN_LISTEN_CHANNEL 5 /* 6 */ +#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_MAXIMUM_ATTRIBUTE_LEN 251 + +/* 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.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) +/* Action frame categories (IEEE 802.11-2007, 7.3.1.11, Table 7-24) */ +#define WLAN_ACTION_SPECTRUM_MGMT 0 +#define WLAN_ACTION_QOS 1 +#define WLAN_ACTION_DLS 2 +#define WLAN_ACTION_BLOCK_ACK 3 +#define WLAN_ACTION_PUBLIC 4 +#define WLAN_ACTION_RADIO_MEASUREMENT 5 +#define WLAN_ACTION_FT 6 +#define WLAN_ACTION_HT 7 +#define WLAN_ACTION_SA_QUERY 8 +#define WLAN_ACTION_PROTECTED_DUAL 9 +#define WLAN_ACTION_WNM 10 +#define WLAN_ACTION_UNPROTECTED_WNM 11 +#define WLAN_ACTION_TDLS 12 +#define WLAN_ACTION_SELF_PROTECTED 15 +#define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */ +#define WLAN_ACTION_VENDOR_SPECIFIC 127 +#define P2P_IE_VENDOR_TYPE 0x506f9a09 +#define WFD_IE_VENDOR_TYPE 0x506f9a0a + +/* Public action codes */ +#define WLAN_PA_20_40_BSS_COEX 0 +#define WLAN_PA_VENDOR_SPECIFIC 9 +#define WLAN_PA_GAS_INITIAL_REQ 10 +#define WLAN_PA_GAS_INITIAL_RESP 11 +#define WLAN_PA_GAS_COMEBACK_REQ 12 +#define WLAN_PA_GAS_COMEBACK_RESP 13 +#define WLAN_TDLS_DISCOVERY_RESPONSE 14 + +/* P2P public action frames */ +enum p2p_action_frame_type { + P2P_GO_NEG_REQ = 0, + P2P_GO_NEG_RESP = 1, + P2P_GO_NEG_CONF = 2, + P2P_INVITATION_REQ = 3, + P2P_INVITATION_RESP = 4, + P2P_DEV_DISC_REQ = 5, + P2P_DEV_DISC_RESP = 6, + P2P_PROV_DISC_REQ = 7, + P2P_PROV_DISC_RESP = 8 +}; + +/* --------------- WFA P2P IE and Attributes --------------- */ + +/* P2P 4.1.1 - P2P Information Element */ +struct IE_P2P { + uint8_t ucId; /* Element ID */ + uint8_t ucLength; /* Length */ + uint8_t aucOui[3]; /* OUI */ + uint8_t ucOuiType; /* OUI Type */ + uint8_t aucP2PAttributes[1]; /* P2P Attributes */ +} __KAL_ATTRIB_PACKED__; + +/* P2P 4.1.1 - General WSC Attribute */ +struct WSC_ATTRIBUTE { + uint16_t u2Id; /* Attribute ID */ + uint16_t u2Length; /* Length */ + uint8_t aucBody[1]; /* Body field */ +} __KAL_ATTRIB_PACKED__; + +/* P2P 4.1.2 - P2P Status Attribute */ +struct P2P_ATTRI_STATUS { + uint8_t ucId; /* Attribute ID */ + uint16_t u2Length; /* Length */ + uint8_t ucStatusCode; /* Status Code */ +} __KAL_ATTRIB_PACKED__; + +/* P2P 4.1.10 - Extended Listen Timing Attribute */ +struct P2P_ATTRI_EXT_LISTEN_TIMING { + uint8_t ucId; /* Attribute ID */ + uint16_t u2Length; /* Length */ + uint16_t u2AvailPeriod; /* Availability Period */ + uint16_t u2AvailInterval; /* Availability Interval */ +} __KAL_ATTRIB_PACKED__; + +/* P2P 4.2.8.2 P2P Public Action Frame Format */ +struct P2P_PUBLIC_ACTION_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* P2P Public Action Frame Body */ + uint8_t ucCategory; /* Category, 0x04 */ + uint8_t ucAction; /* Action Value, 0x09 */ + uint8_t aucOui[3]; /* 0x50, 0x6F, 0x9A */ + uint8_t ucOuiType; /* 0x09 */ + /* GO Nego Req/Rsp/Cfm, P2P Invittion Req/Rsp, */ + uint8_t ucOuiSubtype; + /* Device Discovery Req/Rsp */ + uint8_t ucDialogToken; /* Dialog Token. */ + uint8_t aucInfoElem[1]; /* P2P IE, WSC IE. */ +} __KAL_ATTRIB_PACKED__; + +/* P2P 4.2.9.1 - General Action Frame Format. */ +struct P2P_ACTION_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* P2P Action Frame Body */ + uint8_t ucCategory; /* 0x7F */ + uint8_t aucOui[3]; /* 0x50, 0x6F, 0x9A */ + uint8_t ucOuiType; /* 0x09 */ + uint8_t ucOuiSubtype; /* */ + uint8_t ucDialogToken; + uint8_t aucInfoElem[1]; +} __KAL_ATTRIB_PACKED__; + +/* P2P C.1 GAS Public Action Initial Request Frame Format */ +struct GAS_PUBLIC_ACTION_INITIAL_REQUEST_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + /* P2P Public Action Frame Body */ + uint16_t u2SeqCtrl; /* Sequence Control */ + uint8_t ucCategory; /* Category, 0x04 */ + uint8_t ucAction; /* Action Value, 0x09 */ + uint8_t ucDialogToken; /* Dialog Token. */ + uint8_t aucInfoElem[1]; /* Advertisement IE. */ +} __KAL_ATTRIB_PACKED__; + +/* P2P C.2 GAS Public Action Initial Response Frame Format */ +struct GAS_PUBLIC_ACTION_INITIAL_RESPONSE_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* P2P Public Action Frame Body */ + uint8_t ucCategory; /* Category, 0x04 */ + uint8_t ucAction; /* Action Value, 0x09 */ + uint8_t ucDialogToken; /* Dialog Token. */ + uint16_t u2StatusCode; /* Initial Response. */ + uint16_t u2ComebackDelay; + /* Initial Response. *//* In unit of TU. */ + uint8_t aucInfoElem[1]; /* Advertisement IE. */ +} __KAL_ATTRIB_PACKED__; + +/* P2P C.3-1 GAS Public Action Comeback Request Frame Format */ +struct GAS_PUBLIC_ACTION_COMEBACK_REQUEST_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* P2P Public Action Frame Body */ + uint8_t ucCategory; /* Category, 0x04 */ + uint8_t ucAction; /* Action Value, 0x09 */ + uint8_t ucDialogToken; /* Dialog Token. */ +} __KAL_ATTRIB_PACKED__; + +/* P2P C.3-2 GAS Public Action Comeback Response Frame Format */ +struct GAS_PUBLIC_ACTION_COMEBACK_RESPONSE_FRAME { + /* MAC header */ + uint16_t u2FrameCtrl; /* Frame Control */ + uint16_t u2Duration; /* Duration */ + uint8_t aucDestAddr[MAC_ADDR_LEN]; /* DA */ + uint8_t aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + uint8_t aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + uint16_t u2SeqCtrl; /* Sequence Control */ + /* P2P Public Action Frame Body */ + uint8_t ucCategory; /* Category, 0x04 */ + uint8_t ucAction; /* Action Value, 0x09 */ + uint8_t ucDialogToken; /* Dialog Token. */ + uint16_t u2StatusCode; /* Comeback Response. */ + uint8_t ucFragmentID; /*Comeback Response. */ + uint16_t u2ComebackDelay; /* Comeback Response. */ + uint8_t aucInfoElem[1]; /* Advertisement IE. */ +} __KAL_ATTRIB_PACKED__; + +struct P2P_SD_VENDER_SPECIFIC_CONTENT { + /* Service Discovery Vendor-specific Content. */ + uint8_t ucOuiSubtype; /* 0x09 */ + uint16_t u2ServiceUpdateIndicator; + uint8_t aucServiceTLV[1]; +} __KAL_ATTRIB_PACKED__; + +struct P2P_SERVICE_REQUEST_TLV { + uint16_t u2Length; + uint8_t ucServiceProtocolType; + uint8_t ucServiceTransID; + uint8_t aucQueryData[1]; +} __KAL_ATTRIB_PACKED__; + +struct P2P_SERVICE_RESPONSE_TLV { + uint16_t u2Length; + uint8_t ucServiceProtocolType; + uint8_t ucServiceTransID; + uint8_t ucStatusCode; + uint8_t aucResponseData[1]; +} __KAL_ATTRIB_PACKED__; + +/* P2P 4.1.1 - General P2P Attribute */ +struct P2P_ATTRIBUTE { + uint8_t ucId; /* Attribute ID */ + uint16_t u2Length; /* Length */ + uint8_t aucBody[1]; /* Body field */ +} __KAL_ATTRIB_PACKED__; + +/* P2P 4.1.14 - Notice of Absence Attribute */ +struct P2P_ATTRI_NOA { + uint8_t ucId; /* Attribute ID */ + uint16_t u2Length; /* Length */ + uint8_t ucIndex; /* Index */ + uint8_t ucCTWOppPSParam; /* CTWindow and OppPS Parameters */ + uint8_t aucNoADesc[1]; /* NoA Descriptor */ +} __KAL_ATTRIB_PACKED__; + +struct NOA_DESCRIPTOR { + uint8_t ucCountType; /* Count/Type */ + uint32_t u4Duration; /* Duration */ + uint32_t u4Interval; /* Interval */ + uint32_t u4StartTime; /* Start Time */ +} __KAL_ATTRIB_PACKED__; +struct CHANNEL_ENTRY_FIELD { + uint8_t ucRegulatoryClass; /* Regulatory Class */ + uint8_t ucNumberOfChannels; /* Number Of Channels */ + uint8_t aucChannelList[1]; /* Channel List */ +} __KAL_ATTRIB_PACKED__; + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/p2p_nic.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/p2p_nic.h new file mode 100644 index 0000000000000..349c907fecf89 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/p2p_nic.h @@ -0,0 +1,116 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct EVENT_CONNECTION_STATUS *prConnectionStatus); + +void +nicRxAddP2pDevice(IN struct ADAPTER *prAdapter, + IN struct EVENT_P2P_DEV_DISCOVER_RESULT *prP2pResult, + IN uint8_t *pucRxIEBuf, + IN uint16_t u2RxIELength); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/p2p_nic_cmd_event.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/p2p_nic_cmd_event.h new file mode 100644 index 0000000000000..0978fd0c1c677 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/p2p_nic_cmd_event.h @@ -0,0 +1,122 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 + ****************************************************************************** + */ + +struct EVENT_P2P_DEV_DISCOVER_RESULT { +/* UINT_8 aucCommunicateAddr[MAC_ADDR_LEN]; // Deprecated. */ + uint8_t aucDeviceAddr[MAC_ADDR_LEN]; /* Device Address. */ + uint8_t aucInterfaceAddr[MAC_ADDR_LEN]; /* Device Address. */ + uint8_t ucDeviceCapabilityBitmap; + uint8_t ucGroupCapabilityBitmap; + uint16_t u2ConfigMethod; /* Configure Method. */ + struct P2P_DEVICE_TYPE rPriDevType; + uint8_t ucSecDevTypeNum; + struct P2P_DEVICE_TYPE arSecDevType[2]; + uint16_t u2NameLength; + uint8_t aucName[32]; + uint8_t *pucIeBuf; + uint16_t u2IELength; + uint8_t aucBSSID[MAC_ADDR_LEN]; + /* TODO: Service Information or PasswordID valid? */ +}; + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/que_mgt.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/que_mgt.h new file mode 100644 index 0000000000000..ead5b7e131b52 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/que_mgt.h @@ -0,0 +1,1198 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/ + MT6620_WIFI_DRIVER_V2_3/include/nic/que_mgt.h#2 + */ + +/*! \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. + */ + + +#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 + ******************************************************************************* + */ +extern uint8_t g_arTdlsLink[MAXNUM_TDLS_PEER]; +extern const uint8_t *apucACI2Str[4]; +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/* Queue Manager Features */ +/* 1: Indicate the last TX packet to the FW for each burst */ +#define QM_BURST_END_INFO_ENABLED 0 +/* 1: To fairly share TX resource among active STAs */ +#define QM_FORWARDING_FAIRNESS 1 +#if defined(_HIF_SDIO) +#ifdef _SDIO_RING +/* 1: To adaptively adjust resource for each TC */ +#define QM_ADAPTIVE_TC_RESOURCE_CTRL 0 +/* 1: To fast adjust resource for EMPTY TC (assigned resource is 0) */ +#define QM_FAST_TC_RESOURCE_CTRL 0 +#else +/* 1: To adaptively adjust resource for each TC */ +#define QM_ADAPTIVE_TC_RESOURCE_CTRL 1 +/* 1: To fast adjust resource for EMPTY TC (assigned resource is 0) */ +#define QM_FAST_TC_RESOURCE_CTRL 1 +#endif +#else +/* 1: To adaptively adjust resource for each TC */ +#define QM_ADAPTIVE_TC_RESOURCE_CTRL 0 +/* 1: To fast adjust resource for EMPTY TC (assigned resource is 0) */ +#define QM_FAST_TC_RESOURCE_CTRL 0 +#endif +/* 1: To print TC resource adjustment results */ +#define QM_PRINT_TC_RESOURCE_CTRL 0 +/* 1: If pkt with SSN is missing, auto advance the RX reordering window */ +#define QM_RX_WIN_SSN_AUTO_ADVANCING 1 +/* 1: Indicate the packets falling behind to OS + * before the frame with SSN is received + */ +#define QM_RX_INIT_FALL_BEHIND_PASS 1 +/* 1: Count times of TC resource empty happened */ +#define QM_TC_RESOURCE_EMPTY_COUNTER 1 + +/* Parameters */ +/* p: Update queue lengths when p TX packets are enqueued */ +#define QM_INIT_TIME_TO_UPDATE_QUE_LEN 256 +/* s: Adjust the TC resource every s updates of queue lengths */ +#define QM_INIT_TIME_TO_ADJUST_TC_RSC 2 +/* Factor for Que Len averaging */ +#define QM_QUE_LEN_MOVING_AVE_FACTOR 3 + +#define QM_MIN_RESERVED_TC0_RESOURCE 0 +#define QM_MIN_RESERVED_TC1_RESOURCE 1 +#define QM_MIN_RESERVED_TC2_RESOURCE 0 +#define QM_MIN_RESERVED_TC3_RESOURCE 0 +/* Resource for TC4 is not adjustable */ +#define QM_MIN_RESERVED_TC4_RESOURCE 2 +#define QM_MIN_RESERVED_TC5_RESOURCE 0 + +#define QM_GUARANTEED_TC0_RESOURCE 4 +#define QM_GUARANTEED_TC1_RESOURCE 4 +#define QM_GUARANTEED_TC2_RESOURCE 9 +#define QM_GUARANTEED_TC3_RESOURCE 11 +/* Resource for TC4 is not adjustable */ +#define QM_GUARANTEED_TC4_RESOURCE 2 +#define QM_GUARANTEED_TC5_RESOURCE 4 + +#define QM_EXTRA_RESERVED_RESOURCE_WHEN_BUSY 0 + +#define QM_AVERAGE_TC_RESOURCE 6 + +#define QM_ACTIVE_TC_NUM TC_NUM + +#define QM_MGMT_QUEUED_THRESHOLD 6 +#define QM_CMD_RESERVED_THRESHOLD 4 +#define QM_MGMT_QUEUED_TIMEOUT 1000 /* ms */ + +#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 */ +/* Per-Type Queues: [0] BMCAST */ +#define NUM_OF_PER_STA_TX_QUEUES 4 +#define NUM_OF_PER_TYPE_TX_QUEUES 1 + +/* TX Queue Index */ +/* Per-Type */ +#define TX_QUEUE_INDEX_BMCAST 0 +#define TX_QUEUE_INDEX_NO_STA_REC 0 + +/* Per-STA */ +#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_NON_QOS TX_QUEUE_INDEX_AC1 + +#define QM_DEFAULT_USER_PRIORITY 0 + +#define QM_STA_FORWARD_COUNT_UNLIMITED 0xFFFFFFFF +/* Pending Forwarding Frame Threshold: + * + * A conservative estimated value, to reserve enough free MSDU resource for + * OS packet, rather than full consumed by the pending forwarding frame. + * + * Indeed, even if network subqueue is not stopped when no MSDU resource, the + * new arriving skb will be queued in prGlueInfo->rTxQueue and not be dropped. + */ +#define QM_FWD_PKT_QUE_THRESHOLD \ + (CFG_TX_MAX_PKT_NUM - 2 * CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD) + +/* 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 (200) +#if CFG_SUPPORT_LOWLATENCY_MODE +#define QM_RX_BA_ENTRY_MISS_TIMEOUT_MS_SHORT (50) +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + +#if CFG_M0VE_BA_TO_DRIVER +/* MQM internal control bitmap per-bit usage + * (for operations on g_prMqm->u4FlagBitmap) + */ +#define MQM_FLAG_TSPEC_NEGO_ADD_IN_PROGRESS 0 +#define MQM_FLAG_IDLE_TX_BA_TIMER_STARTED 1 +#define MQM_FLAG_IDLE_RX_BA_TIMER_STARTED 2 + +#define MQM_IDLE_RX_BA_DETECTION 0 +#define MQM_IDLE_RX_BA_CHECK_INTERVAL 5000 /* in msec */ +#define MQM_DEL_IDLE_RXBA_THRESHOLD_BK 6 +#define MQM_DEL_IDLE_RXBA_THRESHOLD_BE 12 +#define MQM_DEL_IDLE_RXBA_THRESHOLD_VI 6 +#define MQM_DEL_IDLE_RXBA_THRESHOLD_VO 6 + +/* For indicating whether the role when generating a DELBA message */ +#define DELBA_ROLE_INITIATOR TRUE +#define DELBA_ROLE_RECIPIENT FALSE + +#define MQM_SET_FLAG(_Bitmap, _flag) { (_Bitmap) |= (BIT((_flag))); } +#define MQM_CLEAR_FLAG(_Bitmap, _flag) { (_Bitmap) &= (~BIT((_flag))); } +#define MQM_CHECK_FLAG(_Bitmap, _flag) ((_Bitmap) & (BIT((_flag)))) + +enum ENUM_BA_RESET_SEL { + MAC_ADDR_TID_MATCH = 0, + MAC_ADDR_MATCH, + ALWAYS_MATCH, + MATCH_NUM +}; + +#endif +/* BW80 NSS1 rate: MCS9 433 Mbps */ +#define QM_DEQUE_PERCENT_VHT80_NSS1 23 +/* BW40 NSS1 Max rate: 200 Mbps */ +#define QM_DEQUE_PERCENT_VHT40_NSS1 10 +/* BW20 NSS1 Max rate: 86.7Mbps */ +#define QM_DEQUE_PERCENT_VHT20_NSS1 5 + +/* BW40 NSS1 Max rate: 150 Mbps (MCS9 200Mbps)*/ +#define QM_DEQUE_PERCENT_HT40_NSS1 10 +/* BW20 NSS1 Max rate: 72.2Mbps (MCS8 86.7Mbps)*/ +#define QM_DEQUE_PERCENT_HT20_NSS1 5 + +/******************************************************************************* + * 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 */ +enum ENUM_MAC_TX_QUEUE_INDEX { + 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 +}; + +struct RX_BA_ENTRY { + u_int8_t fgIsValid; + struct QUE rReOrderQue; + uint16_t u2WinStart; + uint16_t u2WinEnd; + uint16_t u2WinSize; + + /* For identifying the RX BA agreement */ + uint8_t ucStaRecIdx; + uint8_t ucTid; + + u_int8_t fgIsWaitingForPktWithSsn; + + struct TIMER rReorderBubbleTimer; + uint16_t u2FirstBubbleSn; + u_int8_t fgHasBubble; + +#if CFG_M0VE_BA_TO_DRIVER + uint8_t ucStatus; + uint8_t ucIdleCount; + uint16_t u2SnapShotSN; +#endif + /* UINT_8 ucTxBufferSize; */ + /* BOOL fgIsAcConstrain; */ + /* BOOL fgIsBaEnabled; */ +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + /* P_SW_RFB_T prMpduSwRfb; */ + uint32_t u4SeqNo; /* for statistic */ + u_int8_t fgAmsduNeedLastFrame; /* for statistic */ + uint8_t u8LastAmsduSubIdx; + u_int8_t fgIsAmsduDuplicated; +#endif + bool fgFirstSnToWinStart; +}; + +typedef uint32_t(*PFN_DEQUEUE_FUNCTION) (IN struct ADAPTER *prAdapter, + OUT struct QUE *prQue, IN uint8_t ucTC, + IN uint32_t u4CurrentQuota, + IN uint32_t *prPleCurrentQuota, IN uint32_t u4TotalQuota); + +/* The mailbox message + * (could be used for Host-To-Device or Device-To-Host Mailbox) + */ +struct MAILBOX_MSG { + /* [0]: D2HRM0R or H2DRM0R, [1]: D2HRM1R or H2DRM1R */ + uint32_t u4Msg[2]; +}; + +/* Used for adaptively adjusting TC resources */ +struct TC_RESOURCE_CTRL { + /* TC0, TC1, TC2, TC3, TC5 */ + uint32_t au4AverageQueLen[TC_NUM - 1]; +}; + +struct QUE_MGT { /* Queue Management Control Info */ + /* Per-Type Queues: [0] BMCAST or UNKNOWN-STA packets */ + struct QUE arTxQueue[NUM_OF_PER_TYPE_TX_QUEUES]; + +#if 0 + /* For TX Scheduling */ + uint8_t arRemainingTxOppt[NUM_OF_PER_STA_TX_QUEUES]; + uint8_t arCurrentTxStaIndex[NUM_OF_PER_STA_TX_QUEUES]; + +#endif + + /* Reordering Queue Parameters */ + struct RX_BA_ENTRY arRxBaTable[CFG_NUM_OF_RX_BA_AGREEMENTS]; + + /* Current number of activated + * RX BA agreements <= CFG_NUM_OF_RX_BA_AGREEMENTS + */ + uint8_t ucRxBaCount; + +#if QM_TEST_MODE + uint32_t u4PktCount; + struct ADAPTER *prAdapter; + +#if QM_TEST_FAIR_FORWARDING + uint32_t u4CurrentStaRecIndexToEnqueue; +#endif + +#endif + +#if QM_FORWARDING_FAIRNESS + /* The current resource used count + * for a STA with respect to a TC index + */ + uint32_t au4ResourceUsedCount[NUM_OF_PER_STA_TX_QUEUES]; + + /* The current serving STA with respect to a TC index */ + uint32_t au4HeadStaRecIndex[NUM_OF_PER_STA_TX_QUEUES]; + + /* For TC5 only */ + u_int8_t fgGlobalQFirst; + uint32_t u4GlobalResourceUsedCount; +#endif + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + uint32_t au4AverageQueLen[TC_NUM]; + uint32_t au4CurrentTcResource[TC_NUM]; /* unit: frame */ + /* The minimum amount of resource no matter busy or idle */ + uint32_t au4MinReservedTcResource[TC_NUM]; + /* The minimum amount of resource when extremely busy */ + uint32_t au4GuaranteedTcResource[TC_NUM]; + + uint32_t u4TimeToAdjustTcResource; + uint32_t u4TimeToUpdateQueLen; + + uint32_t u4QueLenMovingAverage; + uint32_t u4ExtraReservedTcResource; + uint32_t u4ResidualTcResource; + + /* 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) */ + u_int8_t fgTcResourcePostAnnealing; + +#if QM_FAST_TC_RESOURCE_CTRL + u_int8_t fgTcResourceFastReaction; +#endif + + u_int8_t fgForceReassign; + +#endif + +#if QM_DEBUG_COUNTER + uint32_t au4QmDebugCounters[QM_DBG_CNT_NUM]; +#endif + + uint32_t u4TxAllowedStaCount; + +#if QM_TC_RESOURCE_EMPTY_COUNTER + uint32_t au4QmTcResourceEmptyCounter[MAX_BSSID_NUM][TC_NUM]; + uint32_t au4DequeueNoTcResourceCounter[TC_NUM]; + /* + * how many page count back during statistics intervals + */ + uint32_t au4QmTcResourceBackCounter[TC_NUM]; + /* + * how many page count used to TX frame during statistics intervals + */ + uint32_t au4QmTcUsedPageCounter[TC_NUM]; + uint32_t au4QmTcWantedPageCounter[TC_NUM]; + + uint32_t u4EnqueueCounter; + uint32_t u4DequeueCounter; +#endif + + uint32_t u4MaxForwardBufferCount; + + OS_SYSTIME rLastTxPktDumpTime; + u_int8_t fgIsTxResrouceControlEn; + u_int8_t fgTcResourcePostHandle; +}; + +struct EVENT_TX_ADDBA { + uint8_t ucStaRecIdx; + uint8_t ucTid; + uint8_t ucWinSize; + /* AMSDU in AMPDU is enabled or not (TID bitmap)*/ + uint8_t ucAmsduEnBitmap; + uint16_t u2SSN; + + /* + * AMSDU count/length limits by count *OR* length + * Count: MPDU count in an AMSDU shall not exceed ucMaxMpduCount + * Length: AMSDU length shall not exceed u4MaxMpduLen + */ + uint8_t + ucMaxMpduCount; /* Max MPDU count in an AMSDU */ + uint8_t aucReserved1[1]; + uint32_t u4MaxMpduLen; /* Max AMSDU length */ + + /* + * Note: If length of a packet < u4MinMpduLen then it shall not be + * aggregated in an AMSDU + */ + uint32_t + u4MinMpduLen; /* Min MPDU length to be AMSDU */ + uint8_t aucReserved2[16]; +}; + +struct EVENT_RX_ADDBA { + /* Fields not present in the received ADDBA_REQ */ + uint8_t ucStaRecIdx; + + /* Fields that are present in the received ADDBA_REQ */ + uint8_t ucDialogToken; /* Dialog Token chosen by the sender */ + uint16_t u2BAParameterSet; /* BA policy, TID, buffer size */ + uint16_t u2BATimeoutValue; + uint16_t u2BAStartSeqCtrl; /* SSN */ +}; + +struct EVENT_RX_DELBA { + /* Fields not present in the received ADDBA_REQ */ + uint8_t ucStaRecIdx; + uint8_t ucTid; + uint8_t aucReserved[2]; +}; + +struct EVENT_BSS_ABSENCE_PRESENCE { + /* Event Body */ + uint8_t ucBssIndex; + uint8_t ucIsAbsent; + uint8_t ucBssFreeQuota; + uint8_t aucReserved[1]; +}; + +struct EVENT_STA_CHANGE_PS_MODE { + /* Event Body */ + uint8_t ucStaRecIdx; + uint8_t ucIsInPs; + uint8_t ucUpdateMode; + uint8_t ucFreeQuota; +}; + +/* The free quota is used by PS only now */ +/* The event may be used by per STA flow conttrol in general */ +struct EVENT_STA_UPDATE_FREE_QUOTA { + /* Event Body */ + uint8_t ucStaRecIdx; + uint8_t ucUpdateMode; + uint8_t ucFreeQuota; + uint8_t aucReserved[1]; +}; + +struct EVENT_CHECK_REORDER_BUBBLE { + /* Event Body */ + uint8_t ucStaRecIdx; + uint8_t ucTid; +}; + +/* WMM-2.2.1 WMM Information Element */ +struct IE_WMM_INFO { + uint8_t ucId; /* Element ID */ + uint8_t ucLength; /* Length */ + uint8_t aucOui[3]; /* OUI */ + uint8_t ucOuiType; /* OUI Type */ + uint8_t ucOuiSubtype; /* OUI Subtype */ + uint8_t ucVersion; /* Version */ + uint8_t ucQosInfo; /* QoS Info field */ + uint8_t ucDummy[3]; /* Dummy for pack */ +}; + +struct WMM_AC_PARAM { + uint8_t ucAciAifsn; + uint8_t ucEcw; + uint16_t u2TxopLimit; +}; + +/* WMM-2.2.2 WMM Parameter Element */ +struct IE_WMM_PARAM { + uint8_t ucId; /* Element ID */ + uint8_t ucLength; /* Length */ + + /* IE Body */ + uint8_t aucOui[3]; /* OUI */ + uint8_t ucOuiType; /* OUI Type */ + uint8_t ucOuiSubtype; /* OUI Subtype */ + uint8_t ucVersion; /* Version */ + + /* WMM IE Body */ + uint8_t ucQosInfo; /* QoS Info field */ + uint8_t ucReserved; + + /* AC Parameters */ +#if 1 + struct WMM_AC_PARAM arAcParam[4]; +#else + uint8_t ucAciAifsn_BE; + uint8_t ucEcw_BE; + uint8_t aucTxopLimit_BE[2]; + + uint8_t ucAciAifsn_BG; + uint8_t ucEcw_BG; + uint8_t aucTxopLimit_BG[2]; + + uint8_t ucAciAifsn_VI; + uint8_t ucEcw_VI; + uint8_t aucTxopLimit_VI[2]; + + uint8_t ucAciAifsn_VO; + uint8_t ucEcw_VO; + uint8_t aucTxopLimit_VO[2]; +#endif +}; + +struct IE_WMM_TSPEC { + uint8_t ucId; /* Element ID */ + uint8_t ucLength; /* Length */ + uint8_t aucOui[3]; /* OUI */ + uint8_t ucOuiType; /* OUI Type */ + uint8_t ucOuiSubtype; /* OUI Subtype */ + uint8_t ucVersion; /* Version */ + /* WMM TSPEC body */ + uint8_t aucTsInfo[3]; /* TS Info */ + /* Note: Utilize PARAM_QOS_TSPEC to fill (memory copy) */ + uint8_t aucTspecBodyPart[1]; +}; + +struct IE_WMM_HDR { + uint8_t ucId; /* Element ID */ + uint8_t ucLength; /* Length */ + uint8_t aucOui[3]; /* OUI */ + uint8_t ucOuiType; /* OUI Type */ + uint8_t ucOuiSubtype; /* OUI Subtype */ + uint8_t ucVersion; /* Version */ + uint8_t aucBody[1]; /* IE body */ +}; + +struct AC_QUE_PARMS { + uint16_t u2CWmin; /*!< CWmin */ + uint16_t u2CWmax; /*!< CWmax */ + uint16_t u2TxopLimit; /*!< TXOP limit */ + uint16_t u2Aifsn; /*!< AIFSN */ + uint8_t ucGuradTime; /*!< GuardTime for STOP/FLUSH. */ + uint8_t ucIsACMSet; +}; + +/* WMM ACI (AC index) */ +enum ENUM_WMM_ACI { + WMM_AC_BE_INDEX = 0, + WMM_AC_BK_INDEX, + WMM_AC_VI_INDEX, + WMM_AC_VO_INDEX, + WMM_AC_INDEX_NUM +}; + +/* Used for CMD Queue Operation */ +enum ENUM_FRAME_ACTION { + FRAME_ACTION_DROP_PKT = 0, + FRAME_ACTION_QUEUE_PKT, + FRAME_ACTION_TX_PKT, + FRAME_ACTION_NUM +}; + +enum ENUM_FRAME_TYPE_IN_CMD_Q { + FRAME_TYPE_802_1X = 0, + FRAME_TYPE_MMPDU, + FRAME_TYPE_NUM +}; + +enum ENUM_FREE_QUOTA_MODET { + FREE_QUOTA_UPDATE_MODE_INIT = 0, + FREE_QUOTA_UPDATE_MODE_OVERWRITE, + FREE_QUOTA_UPDATE_MODE_INCREASE, + FREE_QUOTA_UPDATE_MODE_DECREASE +}; + +struct CMD_UPDATE_WMM_PARMS { + struct AC_QUE_PARMS arACQueParms[AC_NUM]; + uint8_t ucBssIndex; + uint8_t fgIsQBSS; + uint8_t ucWmmSet; + uint8_t aucReserved; +}; + +struct CMD_TX_AMPDU { + u_int8_t fgEnable; + uint8_t aucReserved[3]; +}; + +struct CMD_ADDBA_REJECT { + u_int8_t fgEnable; + uint8_t aucReserved[3]; +}; + +#if CFG_M0VE_BA_TO_DRIVER +/* The status of an TX/RX BA entry in FW + * (NEGO means the negotiation process is in progress) + */ +enum ENUM_BA_ENTRY_STATUS { + BA_ENTRY_STATUS_INVALID = 0, + BA_ENTRY_STATUS_NEGO, + BA_ENTRY_STATUS_ACTIVE, + BA_ENTRY_STATUS_DELETING +}; +#endif + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +#define QM_TX_SET_NEXT_MSDU_INFO(_prMsduInfoPreceding, _prMsduInfoNext) \ + ((((_prMsduInfoPreceding)->rQueEntry).prNext) = \ + (struct QUE_ENTRY *)(_prMsduInfoNext)) + +#define QM_TX_SET_NEXT_SW_RFB(_prSwRfbPreceding, _prSwRfbNext) \ + ((((_prSwRfbPreceding)->rQueEntry).prNext) = \ + (struct QUE_ENTRY *)(_prSwRfbNext)) + +#define QM_TX_GET_NEXT_MSDU_INFO(_prMsduInfo) \ + ((struct MSDU_INFO *)(((_prMsduInfo)->rQueEntry).prNext)) + +#define QM_RX_SET_NEXT_SW_RFB(_prSwRfbPreceding, _prSwRfbNext) \ + ((((_prSwRfbPreceding)->rQueEntry).prNext) = \ + (struct QUE_ENTRY *)(_prSwRfbNext)) + +#define QM_RX_GET_NEXT_SW_RFB(_prSwRfb) \ + ((struct SW_RFB *)(((_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) + +#if 0 +#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); \ + } +#else +#define QM_TX_SET_MSDU_INFO_FOR_DATA_PACKET( \ + _prMsduInfo, \ + _ucTC, \ + _ucPacketType, \ + _ucFormatID, \ + _fgIs802_1x, \ + _fgIs802_11, \ + _ucPsForwardingType \ + ) \ + { \ + ASSERT(_prMsduInfo); \ + (_prMsduInfo)->ucTC = (_ucTC); \ + (_prMsduInfo)->ucPacketType = (_ucPacketType); \ + (_prMsduInfo)->ucFormatID = (_ucFormatID); \ + (_prMsduInfo)->fgIs802_1x = (_fgIs802_1x); \ + (_prMsduInfo)->fgIs802_11 = (_fgIs802_11); \ + (_prMsduInfo)->ucPsForwardingType = (_ucPsForwardingType); \ + } +#endif + +#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)] >> \ + (_prAdapter)->rQM.u4QueLenMovingAverage)) +#endif + +#define WMM_IE_OUI_TYPE(fp) (((struct IE_WMM_HDR *)(fp))->ucOuiType) +#define WMM_IE_OUI_SUBTYPE(fp) (((struct IE_WMM_HDR *)(fp))->ucOuiSubtype) +#define WMM_IE_OUI(fp) (((struct IE_WMM_HDR *)(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 struct ADAPTER *prAdapter, + IN u_int8_t isTxResrouceControlEn); + +#if QM_TEST_MODE +void qmTestCases(IN struct ADAPTER *prAdapter); +#endif + +void qmActivateStaRec(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +void qmDeactivateStaRec(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +void qmUpdateStaRec(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +/*----------------------------------------------------------------------------*/ +/* TX-Related Queue Management */ +/*----------------------------------------------------------------------------*/ + +struct MSDU_INFO *qmFlushTxQueues(IN struct ADAPTER + *prAdapter); + +struct MSDU_INFO *qmFlushStaTxQueues(IN struct ADAPTER + *prAdapter, IN uint32_t u4StaRecIdx); + +struct MSDU_INFO *qmEnqueueTxPackets(IN struct ADAPTER + *prAdapter, IN struct MSDU_INFO *prMsduInfoListHead); + +struct MSDU_INFO *qmDequeueTxPackets(IN struct ADAPTER + *prAdapter, IN struct TX_TCQ_STATUS *prTcqStatus); + +#if CFG_SUPPORT_MULTITHREAD +struct MSDU_INFO *qmDequeueTxPacketsMthread( + IN struct ADAPTER *prAdapter, + IN struct TX_TCQ_STATUS *prTcqStatus); + +u_int8_t +qmAdjustTcQuotasMthread(IN struct ADAPTER *prAdapter, + OUT struct TX_TCQ_ADJUST *prTcqAdjust, + IN struct TX_TCQ_STATUS *prTcqStatus); +#endif + +u_int8_t qmAdjustTcQuotas(IN struct ADAPTER *prAdapter, + OUT struct TX_TCQ_ADJUST *prTcqAdjust, + IN struct TX_TCQ_STATUS *prTcqStatus); + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL +void qmReassignTcResource(IN struct ADAPTER *prAdapter); + +void qmUpdateAverageTxQueLen(IN struct ADAPTER *prAdapter); + +void qmDoAdaptiveTcResourceCtrl(IN struct ADAPTER + *prAdapter); + +void qmCheckForFastTcResourceCtrl(IN struct ADAPTER + *prAdapter, IN uint8_t ucTc); + +#endif + +void qmDetermineStaRecIndex(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +uint32_t qmDequeueTxPacketsFromPerStaQueues(IN struct ADAPTER + *prAdapter, OUT struct QUE *prQue, IN uint8_t ucTC, + IN uint32_t + u4CurrentQuota, + IN uint32_t + *prPleCurrentQuota, IN uint32_t u4TotalQuota); + +void qmDequeueTxPacketsFromPerTypeQueues(IN struct ADAPTER + *prAdapter, OUT struct QUE *prQue, IN uint8_t ucTC, + IN uint32_t + u4CurrentQuota, + IN uint32_t + *prPleCurrentQuota, IN uint32_t u4TotalQuota); + +uint32_t qmDequeueTxPacketsFromGlobalQueue(IN struct ADAPTER + *prAdapter, OUT struct QUE *prQue, IN uint8_t ucTC, + IN uint32_t + u4CurrentQuota, + IN uint32_t + *prPleCurrentQuota, IN uint32_t u4TotalQuota); + +void qmSetStaRecTxAllowed(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, IN u_int8_t fgIsTxAllowed); + +uint32_t gmGetDequeueQuota( + IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct BSS_INFO *prBssInfo, + IN uint32_t u4TotalQuota +); + +/*----------------------------------------------------------------------------*/ +/* RX-Related Queue Management */ +/*----------------------------------------------------------------------------*/ + +void qmInitRxQueues(IN struct ADAPTER *prAdapter); + +struct SW_RFB *qmFlushRxQueues(IN struct ADAPTER + *prAdapter); + +struct QUE *qmDetermineStaTxQueue(IN struct ADAPTER + *prAdapter, IN struct MSDU_INFO *prMsduInfo, + IN uint8_t ucActiveTs, OUT uint8_t *pucTC); + +void qmSetTxPacketDescTemplate(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +struct SW_RFB *qmHandleRxPackets(IN struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfbListHead); + +void qmProcessPktWithReordering(IN struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfb, + OUT struct QUE *prReturnedQue); + +void qmProcessBarFrame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, OUT struct QUE *prReturnedQue); + +void qmInsertReorderPkt(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN struct RX_BA_ENTRY *prReorderQueParm, + OUT struct QUE *prReturnedQue); + +void qmInsertFallWithinReorderPkt(IN struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfb, + IN struct RX_BA_ENTRY *prReorderQueParm, + OUT struct QUE *prReturnedQue); + +void qmInsertFallAheadReorderPkt(IN struct ADAPTER + *prAdapter, IN struct SW_RFB *prSwRfb, + IN struct RX_BA_ENTRY *prReorderQueParm, + OUT struct QUE *prReturnedQue); + +void qmPopOutReorderPkt(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, OUT struct QUE *prReturnedQue, + IN enum ENUM_RX_STATISTIC_COUNTER eRxCounter); + +void qmPopOutDueToFallWithin(IN struct ADAPTER *prAdapter, + IN struct RX_BA_ENTRY *prReorderQueParm, + OUT struct QUE *prReturnedQue); + +void qmPopOutDueToFallAhead(IN struct ADAPTER *prAdapter, + IN struct RX_BA_ENTRY *prReorderQueParm, + OUT struct QUE *prReturnedQue); + +void qmHandleReorderBubbleTimeout(IN struct ADAPTER + *prAdapter, IN unsigned long ulParamPtr); + +void qmHandleEventCheckReorderBubble(IN struct ADAPTER + *prAdapter, IN struct WIFI_EVENT *prEvent); + +void qmHandleMailboxRxMessage(IN struct MAILBOX_MSG + prMailboxRxMsg); + +u_int8_t qmCompareSnIsLessThan(IN uint32_t u4SnLess, + IN uint32_t u4SnGreater); + +void qmHandleEventTxAddBa(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); + +void qmHandleEventRxAddBa(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); + +void qmHandleEventRxDelBa(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); + +struct RX_BA_ENTRY *qmLookupRxBaEntry(IN struct ADAPTER + *prAdapter, IN uint8_t ucStaRecIdx, IN uint8_t ucTid); + +u_int8_t +qmAddRxBaEntry(IN struct ADAPTER *prAdapter, + IN uint8_t ucStaRecIdx, IN uint8_t ucTid, + IN uint16_t u2WinStart, IN uint16_t + u2WinSize); + +void qmDelRxBaEntry(IN struct ADAPTER *prAdapter, + IN uint8_t ucStaRecIdx, IN uint8_t ucTid, + IN u_int8_t fgFlushToHost); + +void mqmProcessAssocRsp(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, IN uint8_t *pucIE, + IN uint16_t u2IELength); + +void mqmProcessBcn(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, IN uint8_t *pucIE, + IN uint16_t u2IELength); + +u_int8_t +mqmParseEdcaParameters(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, IN uint8_t *pucIE, + IN uint16_t u2IELength, IN + u_int8_t fgForceOverride); + +u_int8_t mqmCompareEdcaParameters(IN struct IE_WMM_PARAM + *prIeWmmParam, IN struct BSS_INFO *prBssInfo); + +void mqmFillAcQueParam(IN struct IE_WMM_PARAM *prIeWmmParam, + IN uint32_t u4AcOffset, + OUT struct AC_QUE_PARMS *prAcQueParams); + +void mqmProcessScanResult(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prScanResult, + OUT struct STA_RECORD *prStaRec); + +uint32_t mqmFillWmmInfoIE(uint8_t *pucOutBuf, + u_int8_t fgSupportUAPSD, uint8_t ucBmpDeliveryAC, + uint8_t ucBmpTriggerAC, uint8_t ucUapsdSp); + +uint32_t mqmGenerateWmmInfoIEByStaRec(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, struct STA_RECORD *prStaRec, + uint8_t * + pucOutBuf); + +void mqmGenerateWmmInfoIE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +void mqmGenerateWmmParamIE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +#if CFG_SUPPORT_TDLS + +uint32_t mqmGenerateWmmParamIEByParam(struct ADAPTER + *prAdapter, struct BSS_INFO *prBssInfo, uint8_t *pOutBuf); +#endif + +enum ENUM_FRAME_ACTION qmGetFrameAction(IN struct ADAPTER + *prAdapter, + IN uint8_t ucBssIndex, IN uint8_t ucStaRecIdx, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_FRAME_TYPE_IN_CMD_Q eFrameType, + IN uint16_t u2FrameLength); + +void qmHandleEventBssAbsencePresence(IN struct ADAPTER + *prAdapter, IN struct WIFI_EVENT *prEvent); + +void qmHandleEventStaChangePsMode(IN struct ADAPTER + *prAdapter, IN struct WIFI_EVENT *prEvent); + +void mqmProcessAssocReq(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, IN uint8_t *pucIE, + IN uint16_t u2IELength); + +void qmHandleEventStaUpdateFreeQuota(IN struct ADAPTER + *prAdapter, IN struct WIFI_EVENT *prEvent); + +void +qmUpdateFreeQuota(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, IN uint8_t ucUpdateMode, + IN uint8_t ucFreeQuota); + +void qmFreeAllByBssIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +uint32_t qmGetRxReorderQueuedBufferCount(IN struct ADAPTER + *prAdapter); + +uint32_t qmDumpQueueStatus(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, IN uint32_t u4MaxLen); + +#if CFG_M0VE_BA_TO_DRIVER +void +mqmSendDelBaFrame(IN struct ADAPTER *prAdapter, + IN u_int8_t fgIsInitiator, IN struct STA_RECORD *prStaRec, + IN uint32_t u4Tid, IN + uint32_t u4ReasonCode); + +uint32_t +mqmCallbackAddBaRspSent(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +void mqmTimeoutCheckIdleRxBa(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr); + +void +mqmRxModifyBaEntryStatus(IN struct ADAPTER *prAdapter, + IN struct RX_BA_ENTRY *prRxBaEntry, + IN enum ENUM_BA_ENTRY_STATUS eStatus); + +void mqmHandleAddBaReq(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +void mqmHandleBaActionFrame(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); +#endif + +void qmResetTcControlResource(IN struct ADAPTER *prAdapter); +void qmAdjustTcQuotaPle(IN struct ADAPTER *prAdapter, + OUT struct TX_TCQ_ADJUST *prTcqAdjust, + IN struct TX_TCQ_STATUS *prTcqStatus); + +#if ARP_MONITER_ENABLE +void qmDetectArpNoResponse(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); +void qmResetArpDetect(void); +void qmHandleRxArpPackets(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); +void qmHandleRxDhcpPackets(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); +#endif +#if CFG_SUPPORT_REPLAY_DETECTION +u_int8_t qmHandleRxReplay(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); +#endif + +#if CFG_SUPPORT_LOWLATENCY_MODE || CFG_SUPPORT_OSHARE +u_int8_t +qmIsNoDropPacket(IN struct ADAPTER *prAdapter, IN struct SW_RFB *prSwRfb); +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + +void qmMoveStaTxQueue(struct STA_RECORD *prSrcStaRec, + struct STA_RECORD *prDstStaRec); +void qmHandleDelTspec(struct ADAPTER *prAdapter, struct STA_RECORD *prStaRec, + enum ENUM_ACI eAci); +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#if QM_TEST_MODE +extern struct QUE_MGT g_rQM; +#endif +extern const uint8_t aucTid2ACI[TX_DESC_TID_NUM]; +extern const uint8_t arNetwork2TcResource[MAX_BSSID_NUM + + 1][NET_TC_NUM]; + +#endif /* _QUE_MGT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/wlan_def.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/wlan_def.h new file mode 100644 index 0000000000000..bcd9bd51fd7ca --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic/wlan_def.h @@ -0,0 +1,1246 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 + * + */ + + +#ifndef _WLAN_DEF_H +#define _WLAN_DEF_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +/* disconnect reason */ +#define DISCONNECT_REASON_CODE_RESERVED 0 +#define DISCONNECT_REASON_CODE_RADIO_LOST 1 +#define DISCONNECT_REASON_CODE_DEAUTHENTICATED 2 +#define DISCONNECT_REASON_CODE_DISASSOCIATED 3 +#define DISCONNECT_REASON_CODE_NEW_CONNECTION 4 +#define DISCONNECT_REASON_CODE_REASSOCIATION 5 +#define DISCONNECT_REASON_CODE_ROAMING 6 + +/* disconnect trigger */ +#define DISCONNECT_TRIGGER_RESERVED 0 +#define DISCONNECT_TRIGGER_ACTIVE 1 +#define DISCONNECT_TRIGGER_PASSIVE 2 + +/* 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 TX_MODE_VHT 0x100 + +#define RATE_CCK_SHORT_PREAMBLE 0x4 + +#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_MCS8 0x8 +#define PHY_RATE_MCS9 0x9 +#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 | PHY_RATE_6M) +#define RATE_OFDM_9M (TX_MODE_OFDM | PHY_RATE_9M) +#define RATE_OFDM_12M (TX_MODE_OFDM | PHY_RATE_12M) +#define RATE_OFDM_18M (TX_MODE_OFDM | PHY_RATE_18M) +#define RATE_OFDM_24M (TX_MODE_OFDM | PHY_RATE_24M) +#define RATE_OFDM_36M (TX_MODE_OFDM | PHY_RATE_36M) +#define RATE_OFDM_48M (TX_MODE_OFDM | PHY_RATE_48M) +#define RATE_OFDM_54M (TX_MODE_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_VHT_MCS_0 (TX_MODE_VHT | PHY_RATE_MCS0) +#define RATE_VHT_MCS_1 (TX_MODE_VHT | PHY_RATE_MCS1) +#define RATE_VHT_MCS_2 (TX_MODE_VHT | PHY_RATE_MCS2) +#define RATE_VHT_MCS_3 (TX_MODE_VHT | PHY_RATE_MCS3) +#define RATE_VHT_MCS_4 (TX_MODE_VHT | PHY_RATE_MCS4) +#define RATE_VHT_MCS_5 (TX_MODE_VHT | PHY_RATE_MCS5) +#define RATE_VHT_MCS_6 (TX_MODE_VHT | PHY_RATE_MCS6) +#define RATE_VHT_MCS_7 (TX_MODE_VHT | PHY_RATE_MCS7) +#define RATE_VHT_MCS_8 (TX_MODE_VHT | PHY_RATE_MCS8) +#define RATE_VHT_MCS_9 (TX_MODE_VHT | PHY_RATE_MCS9) + +#define RATE_NSTS_MASK BITS(9, 10) +#define RATE_NSTS_OFFSET 9 +#define RATE_TX_MODE_MASK BITS(6, 8) +#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(2) +#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 27 + +/* PHY TYPE bit definitions */ +/* HR/DSSS PHY (clause 18) */ +#define PHY_TYPE_BIT_HR_DSSS BIT(PHY_TYPE_HR_DSSS_INDEX) +/* ERP PHY (clause 19) */ +#define PHY_TYPE_BIT_ERP BIT(PHY_TYPE_ERP_INDEX) +/* OFDM 5 GHz PHY (clause 17) */ +#define PHY_TYPE_BIT_OFDM BIT(PHY_TYPE_OFDM_INDEX) +/* HT PHY (clause 20) */ +#define PHY_TYPE_BIT_HT BIT(PHY_TYPE_HT_INDEX) +/* HT PHY (clause 22) */ +#define PHY_TYPE_BIT_VHT BIT(PHY_TYPE_VHT_INDEX) + +/* 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) + +#define PHY_TYPE_SET_802_11AC (PHY_TYPE_BIT_VHT) + +#define PHY_TYPE_SET_802_11ANAC (PHY_TYPE_BIT_OFDM | \ + PHY_TYPE_BIT_HT | \ + PHY_TYPE_BIT_VHT) + +#define PHY_TYPE_SET_802_11ABGNAC (PHY_TYPE_BIT_OFDM | \ + PHY_TYPE_BIT_HR_DSSS | \ + PHY_TYPE_BIT_ERP | \ + PHY_TYPE_BIT_HT | \ + PHY_TYPE_BIT_VHT) + +/* Rate set bit definitions */ +#define RATE_SET_BIT_1M BIT(RATE_1M_SW_INDEX) /* Bit 0: 1M */ +#define RATE_SET_BIT_2M BIT(RATE_2M_SW_INDEX) /* Bit 1: 2M */ +#define RATE_SET_BIT_5_5M BIT(RATE_5_5M_SW_INDEX) /* Bit 2: 5.5M */ +#define RATE_SET_BIT_11M BIT(RATE_11M_SW_INDEX) /* Bit 3: 11M */ +#define RATE_SET_BIT_22M BIT(RATE_22M_SW_INDEX) /* Bit 4: 22M */ +#define RATE_SET_BIT_33M BIT(RATE_33M_SW_INDEX) /* Bit 5: 33M */ +#define RATE_SET_BIT_6M BIT(RATE_6M_SW_INDEX) /* Bit 6: 6M */ +#define RATE_SET_BIT_9M BIT(RATE_9M_SW_INDEX) /* Bit 7: 9M */ +#define RATE_SET_BIT_12M BIT(RATE_12M_SW_INDEX) /* Bit 8: 12M */ +#define RATE_SET_BIT_18M BIT(RATE_18M_SW_INDEX) /* Bit 9: 18M */ +#define RATE_SET_BIT_24M BIT(RATE_24M_SW_INDEX) /* Bit 10: 24M */ +#define RATE_SET_BIT_36M BIT(RATE_36M_SW_INDEX) /* Bit 11: 36M */ +#define RATE_SET_BIT_48M BIT(RATE_48M_SW_INDEX) /* Bit 12: 48M */ +#define RATE_SET_BIT_54M BIT(RATE_54M_SW_INDEX) /* Bit 13: 54M */ +/* Bit 14: BSS Selector */ +#define RATE_SET_BIT_VHT_PHY BIT(RATE_VHT_PHY_SW_INDEX) +/* Bit 15: BSS Selector */ +#define RATE_SET_BIT_HT_PHY BIT(RATE_HT_PHY_SW_INDEX) + +/* 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_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 +/* Available AID: 1 ~ 20(STA_REC_NUM) */ +#define MAX_ASSOC_ID (CFG_STA_REC_NUM) +/* NOTE(Kevin): Used in auth.c */ +#define MAX_DEAUTH_INFO_COUNT 4 +/* The minimum interval if continuously send Deauth Frame */ +#define MIN_DEAUTH_INTERVAL_MSEC 500 + +/* 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) +#if CFG_SUPPORT_CFG80211_AUTH +#define AUTH_TYPE_SAE BIT(AUTH_ALGORITHM_NUM_SAE) +#endif + +/* Authentication Retry Limit */ +#define TX_AUTH_ASSOCI_RETRY_LIMIT 2 +#define TX_AUTH_ASSOCI_RETRY_LIMIT_FOR_ROAMING 1 + +/* WMM-2.2.1 WMM Information Element */ +#define ELEM_MAX_LEN_WMM_INFO 7 + +/* PF TCP/UDP max port number */ +#define MAX_TCP_UDP_PORT 20 + +#if CFG_SUPPORT_WAC +/*Single WAC IE Length*/ +#define ELEM_MAX_LEN_WAC_INFO 256 +#endif + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +enum ENUM_HW_BSSID { + BSSID_0 = 0, + BSSID_1, + BSSID_2, + BSSID_3, + BSSID_NUM +}; + +enum ENUM_HW_MAC_ADDR { + MAC_ADDR_0 = 0, + MAC_ADDR_1, + MAC_ADDR_NUM +}; + +enum ENUM_HW_OP_MODE { + HW_OP_MODE_STA = 0, + HW_OP_MODE_AP, + HW_OP_MODE_ADHOC, + HW_OP_MODE_NUM +}; + +enum ENUM_TSF { + ENUM_LOCAL_TSF_0, + ENUM_LOCAL_TSF_1, + ENUM_LOCAL_TSF_NUM +}; + +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 +}; + +enum ENUM_AC { + AC0 = 0, + AC1, + AC2, + AC3, + AC_NUM +}; + +enum ENUM_NETWORK_TYPE { + NETWORK_TYPE_AIS, + NETWORK_TYPE_P2P, + NETWORK_TYPE_BOW, + NETWORK_TYPE_MBSS, + NETWORK_TYPE_NUM +}; + +/* The Type of STA Type. */ +enum ENUM_STA_TYPE_INDEX { + STA_TYPE_LEGACY_INDEX = 0, + STA_TYPE_P2P_INDEX, + STA_TYPE_BOW_INDEX, + STA_TYPE_INDEX_NUM +}; + +#define STA_ROLE_BASE_INDEX 4 + +enum ENUM_STA_ROLE_INDEX { + STA_ROLE_ADHOC_INDEX = STA_ROLE_BASE_INDEX, /* 4 */ + STA_ROLE_CLIENT_INDEX, + STA_ROLE_AP_INDEX, + STA_ROLE_DLS_INDEX, + STA_ROLE_MAX_INDEX +}; + +#define STA_ROLE_INDEX_NUM (STA_ROLE_MAX_INDEX - STA_ROLE_BASE_INDEX) + +/* The Power State of a specific Network */ +enum ENUM_PWR_STATE { + PWR_STATE_IDLE = 0, + PWR_STATE_ACTIVE, + PWR_STATE_PS, + PWR_STATE_NUM +}; + +enum ENUM_PHY_TYPE_INDEX { + /* 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_VHT_INDEX, /* HT PHY (clause 22) */ + PHY_TYPE_INDEX_NUM /* 6 */ +}; + +enum ENUM_SW_RATE_INDEX { + RATE_1M_SW_INDEX = 0, /* 1M */ + RATE_2M_SW_INDEX, /* 2M */ + RATE_5_5M_SW_INDEX, /* 5.5M */ + RATE_11M_SW_INDEX, /* 11M */ + RATE_22M_SW_INDEX, /* 22M */ + RATE_33M_SW_INDEX, /* 33M */ + RATE_6M_SW_INDEX, /* 6M */ + RATE_9M_SW_INDEX, /* 9M */ + RATE_12M_SW_INDEX, /* 12M */ + RATE_18M_SW_INDEX, /* 18M */ + RATE_24M_SW_INDEX, /* 24M */ + RATE_36M_SW_INDEX, /* 36M */ + RATE_48M_SW_INDEX, /* 48M */ + RATE_54M_SW_INDEX, /* 54M */ + RATE_VHT_PHY_SW_INDEX, /* BSS Selector - VHT PHY */ + RATE_HT_PHY_SW_INDEX, /* BSS Selector - HT PHY */ + RATE_NUM_SW /* 16 */ +}; + +enum ENUM_CCK_RATE_INDEX { + RATE_1M_INDEX = 0, /* 1M */ + RATE_2M_INDEX, /* 2M */ + RATE_5_5M_INDEX, /* 5.5M */ + RATE_11M_INDEX, /* 11M */ + CCK_RATE_NUM /* 4 */ +}; + +enum ENUM_OFDM_RATE_INDEX { + RATE_6M_INDEX = 0, /* 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 */ + OFDM_RATE_NUM /* 8 */ +}; + +enum ENUM_HT_RATE_INDEX { + HT_RATE_MCS32_INDEX = 0, + HT_RATE_MCS0_INDEX, + 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_MCS8_INDEX, + HT_RATE_MCS9_INDEX, + HT_RATE_MCS10_INDEX, + HT_RATE_MCS11_INDEX, + HT_RATE_MCS12_INDEX, + HT_RATE_MCS13_INDEX, + HT_RATE_MCS14_INDEX, + HT_RATE_MCS15_INDEX, + HT_RATE_NUM /* 16 */ +}; + +enum ENUM_VHT_RATE_INDEX { + VHT_RATE_MCS0_INDEX = 0, + VHT_RATE_MCS1_INDEX, + VHT_RATE_MCS2_INDEX, + VHT_RATE_MCS3_INDEX, + VHT_RATE_MCS4_INDEX, + VHT_RATE_MCS5_INDEX, + VHT_RATE_MCS6_INDEX, + VHT_RATE_MCS7_INDEX, + VHT_RATE_MCS8_INDEX, + VHT_RATE_MCS9_INDEX, + VHT_RATE_NUM /* 10 */ +}; + +enum ENUM_PREMABLE_OPTION { + /* LONG for PHY_TYPE_HR_DSSS, NONE for PHY_TYPE_OFDM */ + PREAMBLE_DEFAULT_LONG_NONE = 0, + /* SHORT mandatory for PHY_TYPE_ERP, + * SHORT option for PHY_TYPE_HR_DSSS + */ + PREAMBLE_OPTION_SHORT, + PREAMBLE_OFDM_MODE, + PREAMBLE_HT_MIXED_MODE, + PREAMBLE_HT_GREEN_FIELD, + PREAMBLE_VHT_FIELD, + PREAMBLE_OPTION_NUM +}; + +enum ENUM_MODULATION_SYSTEM { + MODULATION_SYSTEM_CCK = 0, + MODULATION_SYSTEM_OFDM, + MODULATION_SYSTEM_HT20, + MODULATION_SYSTEM_HT40, + MODULATION_SYSTEM_NUM +}; + +enum ENUM_MODULATION_TYPE { + MODULATION_TYPE_CCK_BPSK = 0, + MODULATION_TYPE_QPSK, + MODULATION_TYPE_16QAM, + MODULATION_TYPE_64QAM, + MODULATION_TYPE_MCS6, + MODULATION_TYPE_54M_MCS7, + MODULATION_TYPE_MCS32, + MODULATION_TYPE_NUM +}; + + +enum ENUM_TXPOWER_TYPE_CCK_T { + MODULATION_SYSTEM_CCK_1M = 0, + MODULATION_SYSTEM_CCK_2M, + MODULATION_SYSTEM_CCK_5M, + MODULATION_SYSTEM_CCK_11M, + MODULATION_SYSTEM_CCK_NUM, +}; + +enum ENUM_TXPOWER_TYPE_OFDM_T { + MODULATION_SYSTEM_OFDM_6M = 0, + MODULATION_SYSTEM_OFDM_9M, + MODULATION_SYSTEM_OFDM_12M, + MODULATION_SYSTEM_OFDM_18M, + MODULATION_SYSTEM_OFDM_24M, + MODULATION_SYSTEM_OFDM_36M, + MODULATION_SYSTEM_OFDM_48M, + MODULATION_SYSTEM_OFDM_54M, + MODULATION_SYSTEM_OFDM_NUM, +}; + +enum ENUM_TXPOWER_TYPE_HT20_T { + MODULATION_SYSTEM_HT20_MCS0 = 0, + MODULATION_SYSTEM_HT20_MCS1, + MODULATION_SYSTEM_HT20_MCS2, + MODULATION_SYSTEM_HT20_MCS3, + MODULATION_SYSTEM_HT20_MCS4, + MODULATION_SYSTEM_HT20_MCS5, + MODULATION_SYSTEM_HT20_MCS6, + MODULATION_SYSTEM_HT20_MCS7, + MODULATION_SYSTEM_HT20_NUM, +}; + +enum ENUM_TXPOWER_TYPE_HT40_T { + MODULATION_SYSTEM_HT40_MCS0 = 0, + MODULATION_SYSTEM_HT40_MCS1, + MODULATION_SYSTEM_HT40_MCS2, + MODULATION_SYSTEM_HT40_MCS3, + MODULATION_SYSTEM_HT40_MCS4, + MODULATION_SYSTEM_HT40_MCS5, + MODULATION_SYSTEM_HT40_MCS6, + MODULATION_SYSTEM_HT40_MCS7, + MODULATION_SYSTEM_HT40_MCS32, + MODULATION_SYSTEM_HT40_NUM, +}; + +enum ENUM_TXPOWER_TYPE_VHT20_T { + MODULATION_SYSTEM_VHT20_MCS0 = 0, + MODULATION_SYSTEM_VHT20_MCS1, + MODULATION_SYSTEM_VHT20_MCS2, + MODULATION_SYSTEM_VHT20_MCS3, + MODULATION_SYSTEM_VHT20_MCS4, + MODULATION_SYSTEM_VHT20_MCS5, + MODULATION_SYSTEM_VHT20_MCS6, + MODULATION_SYSTEM_VHT20_MCS7, + MODULATION_SYSTEM_VHT20_MCS8, + MODULATION_SYSTEM_VHT20_MCS9, + MODULATION_SYSTEM_VHT20_NUM, +}; + +enum ENUM_TXPOWER_TYPE_VHT40_T { + MODULATION_SYSTEM_VHT40_MCS0 = 0, + MODULATION_SYSTEM_VHT40_MCS1, + MODULATION_SYSTEM_VHT40_MCS2, + MODULATION_SYSTEM_VHT40_MCS3, + MODULATION_SYSTEM_VHT40_MCS4, + MODULATION_SYSTEM_VHT40_MCS5, + MODULATION_SYSTEM_VHT40_MCS6, + MODULATION_SYSTEM_VHT40_MCS7, + MODULATION_SYSTEM_VHT40_MCS8, + MODULATION_SYSTEM_VHT40_MCS9, + MODULATION_SYSTEM_VHT40_NUM, +}; + +enum ENUM_TXPOWER_TYPE_VHT80_T { + MODULATION_SYSTEM_VHT80_MCS0 = 0, + MODULATION_SYSTEM_VHT80_MCS1, + MODULATION_SYSTEM_VHT80_MCS2, + MODULATION_SYSTEM_VHT80_MCS3, + MODULATION_SYSTEM_VHT80_MCS4, + MODULATION_SYSTEM_VHT80_MCS5, + MODULATION_SYSTEM_VHT80_MCS6, + MODULATION_SYSTEM_VHT80_MCS7, + MODULATION_SYSTEM_VHT80_MCS8, + MODULATION_SYSTEM_VHT80_MCS9, + MODULATION_SYSTEM_VHT80_NUM, +}; + +enum ENUM_TXPOWER_TYPE_VHT160_T { + MODULATION_SYSTEM_VHT160_MCS0 = 0, + MODULATION_SYSTEM_VHT160_MCS1, + MODULATION_SYSTEM_VHT160_MCS2, + MODULATION_SYSTEM_VHT160_MCS3, + MODULATION_SYSTEM_VHT160_MCS4, + MODULATION_SYSTEM_VHT160_MCS5, + MODULATION_SYSTEM_VHT160_MCS6, + MODULATION_SYSTEM_VHT160_MCS7, + MODULATION_SYSTEM_VHT160_MCS8, + MODULATION_SYSTEM_VHT160_MCS9, + MODULATION_SYSTEM_VHT160_NUM, +}; + +struct POWER_LIMIT { + uint8_t ucCentralCh; + uint8_t tx_pwr_dsss[MODULATION_SYSTEM_CCK_NUM]; /*unit: 0.5 dbm*/ + uint8_t tx_pwr_ofdm[MODULATION_SYSTEM_OFDM_NUM]; /*unit: 0.5 dbm*/ + uint8_t tx_pwr_ht20[MODULATION_SYSTEM_HT20_NUM]; /*unit: 0.5 dbm*/ + uint8_t tx_pwr_ht40[MODULATION_SYSTEM_HT40_NUM]; /*unit: 0.5 dbm*/ + uint8_t tx_pwr_vht20[MODULATION_SYSTEM_VHT20_NUM]; /*unit: 0.5 dbm*/ + uint8_t tx_pwr_vht40[MODULATION_SYSTEM_VHT40_NUM]; /*unit: 0.5 dbm*/ + uint8_t tx_pwr_vht80[MODULATION_SYSTEM_VHT80_NUM]; /*unit: 0.5 dbm*/ + uint8_t tx_pwr_vht160[MODULATION_SYSTEM_VHT160_NUM]; /*unit: 0.5 dbm*/ +}; + +enum ENUM_TXPWR_TBL_IDX { + TXPWR_LIMIT_TBL, + TXPWR_EEPROM_TBL, + TXPWR_MAC_TBL, + TXPWR_TBL_NUM +}; + +enum ENUM_ACPI_STATE { + ACPI_STATE_D0 = 0, + ACPI_STATE_D1, + ACPI_STATE_D2, + ACPI_STATE_D3 +}; + +/* The operation mode of a specific Network */ +enum ENUM_OP_MODE { + 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 +}; + +/* + * NL80211 interface type. + * Refer to the definition of nl80211_iftype in kernel/nl80211.h + */ +enum ENUM_IFTYPE { + IFTYPE_UNSPECIFIED = 0, + IFTYPE_ADHOC, + IFTYPE_STATION, + IFTYPE_AP, + IFTYPE_AP_VLAN, + IFTYPE_WDS, + IFTYPE_MONITOR, + IFTYPE_MESH_POINT, + IFTYPE_P2P_CLIENT, + IFTYPE_P2P_GO, + IFTYPE_P2P_DEVICE, + IFTYPE_OCB, + IFTYPE_NAN, + IFTYPE_NUM +}; + +/* Concurrency mode for p2p preferred freq list*/ +enum CONN_MODE_IFACE_TYPE { + CONN_MODE_IFACE_TYPE_STA = 0, + CONN_MODE_IFACE_TYPE_SAP, + CONN_MODE_IFACE_TYPE_P2P_GC, + CONN_MODE_IFACE_TYPE_P2P_GO, + CONN_MODE_IFACE_TYPE_IBSS, + CONN_MODE_IFACE_TYPE_TDLS, + CONN_MODE_IFACE_TYPE_NUM +}; + +enum ENUM_CHNL_EXT { + CHNL_EXT_SCN = 0, + CHNL_EXT_SCA = 1, + CHNL_EXT_RES = 2, + CHNL_EXT_SCB = 3 +}; + +enum ENUM_CHANNEL_WIDTH { + CW_20_40MHZ = 0, + CW_80MHZ = 1, + CW_160MHZ = 2, + CW_80P80MHZ = 3 +}; + +/* This starting freq of the band is unit of kHz */ +enum ENUM_BAND { + BAND_NULL, + BAND_2G4, + BAND_5G, + BAND_NUM +}; + +enum ENUM_DBDC_BN { + ENUM_BAND_0, + ENUM_BAND_1, + ENUM_BAND_NUM, + ENUM_BAND_ALL, + ENUM_BAND_AUTO /*Auto select by A/G band, Driver only*/ +}; + +/* Provide supported channel list to other components in array format */ +struct RF_CHANNEL_INFO { + enum ENUM_BAND eBand; + /* To record Channel Center Frequency Segment 0 (MHz) from CFG80211 */ + uint32_t u4CenterFreq1; + /* To record Channel Center Frequency Segment 1 (MHz) from CFG80211 */ + uint32_t u4CenterFreq2; + /* To record primary channel frequency (MHz) from CFG80211 */ + uint16_t u2PriChnlFreq; + /* To record channel bandwidth from CFG80211 */ + uint8_t ucChnlBw; + uint8_t ucChannelNum; +}; + +enum ENUM_PS_FORWARDING_TYPE { + 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 ENUM_AR_SS { + AR_SS_NULL = 0, + AR_SS_1, + AR_SS_2, + AR_SS_3, + AR_SS_4, + AR_SS_NUM +}; + +enum ENUM_MAC_BANDWIDTH { + MAC_BW_20 = 0, + MAC_BW_40, + MAC_BW_80, + MAC_BW_160 +}; + +struct DEAUTH_INFO { + uint8_t aucRxAddr[MAC_ADDR_LEN]; + OS_SYSTIME rLastSendTime; +}; + +/*----------------------------------------------------------------------------*/ +/* Information Element (IE) handlers */ +/*----------------------------------------------------------------------------*/ +typedef void(*PFN_APPEND_IE_FUNC) (struct ADAPTER *, + struct MSDU_INFO *); +typedef void(*PFN_HANDLE_IE_FUNC) (struct ADAPTER *, + struct SW_RFB *, struct IE_HDR *); +typedef void(*PFN_VERIFY_IE_FUNC) (struct ADAPTER *, + struct SW_RFB *, struct IE_HDR *, + uint16_t *); +typedef uint32_t(*PFN_CALCULATE_VAR_IE_LEN_FUNC) ( + struct ADAPTER *, uint8_t, struct STA_RECORD *); + +struct APPEND_IE_ENTRY { + uint16_t u2EstimatedIELen; + PFN_APPEND_IE_FUNC pfnAppendIE; +}; + +struct APPEND_VAR_IE_ENTRY { + uint16_t u2EstimatedFixedIELen; /* For Fixed Length */ + PFN_CALCULATE_VAR_IE_LEN_FUNC pfnCalculateVariableIELen; + PFN_APPEND_IE_FUNC pfnAppendIE; +}; + +struct HANDLE_IE_ENTRY { + uint8_t ucElemID; + PFN_HANDLE_IE_FUNC pfnHandleIE; +}; + +struct VERIFY_IE_ENTRY { + uint8_t ucElemID; + PFN_VERIFY_IE_FUNC pfnVarifyIE; +}; + +/*----------------------------------------------------------------------------*/ +/* Parameters of User Configuration */ +/*----------------------------------------------------------------------------*/ +enum ENUM_PARAM_CONNECTION_POLICY { + 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_BSSID_HINT, + CONNECT_BY_CUSTOMIZED_RULE /* NOTE(Kevin): TBD */ +}; + +enum ENUM_PARAM_PREAMBLE_TYPE { + PREAMBLE_TYPE_LONG = 0, + PREAMBLE_TYPE_SHORT, + /*!< Try preamble short first, if fail tray preamble long. */ + PREAMBLE_TYPE_AUTO +}; + +/* This is enum defined for user to select a phy config listed in combo box */ +enum ENUM_PARAM_PHY_CONFIG { + /* Can associated with 802.11abg AP but without n capability, + * Scan dual band. + */ + PHY_CONFIG_802_11ABG = 0, + /* Can associated with 802_11bg AP, + * Scan single band and not report 5G BSSs. + */ + PHY_CONFIG_802_11BG, + /* Can associated with 802_11g only AP, + * Scan single band and not report 5G BSSs. + */ + PHY_CONFIG_802_11G, + /* Can associated with 802_11a only AP, + * Scan single band and not report 2.4G BSSs. + */ + PHY_CONFIG_802_11A, + /* Can associated with 802_11b only AP, + * Scan single band and not report 5G BSSs. + */ + PHY_CONFIG_802_11B, + /* Can associated with 802.11abgn AP, Scan dual band. */ + PHY_CONFIG_802_11ABGN, + /* Can associated with 802_11bgn AP, + * Scan single band and not report 5G BSSs. + */ + PHY_CONFIG_802_11BGN, + /* Can associated with 802_11an AP, + * Scan single band and not report 2.4G BSSs. + */ + PHY_CONFIG_802_11AN, + /* Can associated with 802_11gn AP, + * Scan single band and not report 5G BSSs. + */ + PHY_CONFIG_802_11GN, + PHY_CONFIG_802_11AC, + PHY_CONFIG_802_11ANAC, + PHY_CONFIG_802_11ABGNAC, + PHY_CONFIG_NUM /* 12 */ +}; + +/* This is enum defined for user to select an AP Mode */ +enum ENUM_PARAM_AP_MODE { + /* Create 11b BSS if we support 802.11abg/802.11bg. */ + AP_MODE_11B = 0, + /* Create 11bg mixed BSS if we support 802.11abg/802.11bg/802.11g. */ + AP_MODE_MIXED_11BG, + /* Create 11g only BSS if we support 802.11abg/802.11bg/802.11g. */ + AP_MODE_11G, + /* Create 11g only BSS for P2P + * if we support 802.11abg/802.11bg/802.11g. + */ + AP_MODE_11G_P2P, + /* Create 11a only BSS if we support 802.11abg. */ + AP_MODE_11A, + AP_MODE_NUM /* 4 */ +}; + +/* Masks for determining the Network Type + * or the Station Role, given the ENUM_STA_TYPE_T + */ +#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) ((prAdapter->prAisBssInfo != NULL) && \ + ((_prStaRec)->ucBssIndex == prAdapter->prAisBssInfo->ucBssIndex)) +#define IS_STA_IN_P2P(_prStaRec) \ + (prAdapter->aprBssInfo[(_prStaRec)->ucBssIndex]->eNetworkType \ + == NETWORK_TYPE_P2P) +#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. + */ +enum ENUM_STA_TYPE { + 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), +}; + +/* The type of BSS we discovered */ +enum ENUM_BSS_TYPE { + BSS_TYPE_INFRASTRUCTURE = 1, + BSS_TYPE_IBSS, + BSS_TYPE_P2P_DEVICE, + BSS_TYPE_BOW_DEVICE, + BSS_TYPE_NUM +}; + +enum ENUM_ANTENNA_NUM { + ANTENNA_WF0 = 0, + ANTENNA_WF1 = 1, + MAX_ANTENNA_NUM +}; + +/*----------------------------------------------------------------------------*/ +/* RSN structures */ +/*----------------------------------------------------------------------------*/ +/* #if defined(WINDOWS_DDK) || defined(WINDOWS_CE) */ +/* #pragma pack(1) */ +/* #endif */ +#if CFG_SUPPORT_CFG80211_AUTH +/* max number of supported cipher suites */ +#define MAX_NUM_SUPPORTED_CIPHER_SUITES 10 +#if CFG_SUPPORT_802_11W +/* max number of supported AKM suites */ +#define MAX_NUM_SUPPORTED_AKM_SUITES 15 +#else +/* max number of supported AKM suites */ +#define MAX_NUM_SUPPORTED_AKM_SUITES 13 +#endif +#else +/* max number of supported cipher suites */ +#define MAX_NUM_SUPPORTED_CIPHER_SUITES 9 +#if CFG_SUPPORT_802_11W +/* max number of supported AKM suites */ +#define MAX_NUM_SUPPORTED_AKM_SUITES 11 +#else +/* max number of supported AKM suites */ +#define MAX_NUM_SUPPORTED_AKM_SUITES 9 +#endif +#endif +/* max number of supported PMKID */ +#define MAX_NUM_SUPPORTED_PMKID 10 + +/* Structure of RSN Information */ +struct RSN_INFO { + uint8_t ucElemId; + uint8_t ucRsneLen; + uint16_t u2Version; + uint32_t u4GroupKeyCipherSuite; + uint32_t u4PairwiseKeyCipherSuiteCount; + uint32_t au4PairwiseKeyCipherSuite[MAX_NUM_SUPPORTED_CIPHER_SUITES]; + uint32_t u4AuthKeyMgtSuiteCount; + uint32_t au4AuthKeyMgtSuite[MAX_NUM_SUPPORTED_AKM_SUITES]; + uint16_t u2RsnCap; + u_int8_t fgRsnCapPresent; + uint16_t u2PmkidCnt; + u_int8_t aucPmkidList[MAX_NUM_SUPPORTED_PMKID * RSN_PMKID_LEN]; + uint32_t u4GroupMgmtKeyCipherSuite; +} __KAL_ATTRIB_PACKED__; + +/* max number of supported AKM suites */ +#define MAX_NUM_SUPPORTED_WAPI_AKM_SUITES 1 +/* max number of supported cipher suites */ +#define MAX_NUM_SUPPORTED_WAPI_CIPHER_SUITES 1 + +/* Structure of WAPI Information */ +struct WAPI_INFO { + uint8_t ucElemId; + uint8_t ucLength; + uint16_t u2Version; + uint32_t u4AuthKeyMgtSuiteCount; + uint32_t au4AuthKeyMgtSuite[MAX_NUM_SUPPORTED_WAPI_AKM_SUITES]; + uint32_t u4PairwiseKeyCipherSuiteCount; + + uint32_t + au4PairwiseKeyCipherSuite[MAX_NUM_SUPPORTED_WAPI_CIPHER_SUITES]; + uint32_t u4GroupKeyCipherSuite; + uint16_t u2WapiCap; + uint16_t u2Bkid; + uint8_t aucBkid[1][16]; +} __KAL_ATTRIB_PACKED__; + +/* #if defined(WINDOWS_DDK) || defined(WINDOWS_CE) */ +/* #pragma pack() */ +/* #endif */ + +#if CFG_ENABLE_WIFI_DIRECT + +struct P2P_DEVICE_TYPE { + uint16_t u2CategoryID; + uint16_t u2SubCategoryID; +}; + +struct P2P_DEVICE_DESC { + struct LINK_ENTRY rLinkEntry; + u_int8_t fgDevInfoValid; + uint8_t aucDeviceAddr[MAC_ADDR_LEN]; /* Device Address. */ + uint8_t aucInterfaceAddr[MAC_ADDR_LEN]; /* Interface Address. */ + uint8_t ucDeviceCapabilityBitmap; + uint8_t ucGroupCapabilityBitmap; + uint16_t u2ConfigMethod; /* Configure Method support. */ + struct P2P_DEVICE_TYPE rPriDevType; + uint8_t ucSecDevTypeNum; + /* Reference to P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT */ + struct P2P_DEVICE_TYPE arSecDevType[8]; + uint16_t u2NameLength; + uint8_t aucName[32]; /* Reference to WPS_ATTRI_MAX_LEN_DEVICE_NAME */ + /* TODO: Service Information or PasswordID valid? */ +}; + +#endif + +#if CFG_SUPPORT_OWE +/* Structure of OWE Information */ +struct OWE_INFO_T { + uint8_t ucElemId; + uint8_t ucLength; + uint8_t ucElemIdExt; + uint16_t u2Group; + uint8_t aucPublicKey[100]; +}; +#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 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) \ + { \ + uint8_t *__cp = (uint8_t *)(_memAddr_p); \ + *(uint16_t *)(_value_p) = ((uint16_t)__cp[0]) | \ + ((uint16_t)__cp[1] << 8); \ + } + +#define WLAN_GET_FIELD_BE16(_memAddr_p, _value_p) \ + { \ + uint8_t *__cp = (uint8_t *)(_memAddr_p); \ + *(uint16_t *)(_value_p) = ((uint16_t)__cp[0] << 8) | \ + ((uint16_t)__cp[1]); \ + } + +#define WLAN_GET_FIELD_32(_memAddr_p, _value_p) \ + { \ + uint8_t *__cp = (uint8_t *)(_memAddr_p); \ + *(uint32_t *)(_value_p) = ((uint32_t)__cp[0]) | \ + ((uint32_t)__cp[1] << 8) | \ + ((uint32_t)__cp[2] << 16) | ((uint32_t)__cp[3] << 24); \ + } + +#define WLAN_GET_FIELD_BE32(_memAddr_p, _value_p) \ + { \ + uint8_t *__cp = (uint8_t *)(_memAddr_p); \ + *(uint32_t *)(_value_p) = ((uint32_t)__cp[0] << 24) | \ + ((uint32_t)__cp[1] << 16) | ((uint32_t)__cp[2] << 8) | \ + ((uint32_t)__cp[3]); \ + } + +#define WLAN_GET_FIELD_64(_memAddr_p, _value_p) \ + { \ + uint8_t *__cp = (uint8_t *)(_memAddr_p); \ + *(uint64_t *)(_value_p) = \ + ((uint64_t)__cp[0]) | ((uint64_t)__cp[1] << 8) | \ + ((uint64_t)__cp[2] << 16) | \ + ((uint64_t)__cp[3] << 24) | \ + ((uint64_t)__cp[4] << 32) | \ + ((uint64_t)__cp[5] << 40) | \ + ((uint64_t)__cp[6] << 48) | \ + ((uint64_t)__cp[7] << 56); \ + } + +#define WLAN_SET_FIELD_16(_memAddr_p, _value) \ + { \ + uint8_t *__cp = (uint8_t *)(_memAddr_p); \ + __cp[0] = (uint8_t)(_value); \ + __cp[1] = (uint8_t)((_value) >> 8); \ + } + +#define WLAN_SET_FIELD_BE16(_memAddr_p, _value) \ + { \ + uint8_t *__cp = (uint8_t *)(_memAddr_p); \ + __cp[0] = (uint8_t)((_value) >> 8); \ + __cp[1] = (uint8_t)(_value); \ + } + +#define WLAN_SET_FIELD_32(_memAddr_p, _value) \ + { \ + uint8_t *__cp = (uint8_t *)(_memAddr_p); \ + __cp[0] = (uint8_t)(_value); \ + __cp[1] = (uint8_t)((_value) >> 8); \ + __cp[2] = (uint8_t)((_value) >> 16); \ + __cp[3] = (uint8_t)((_value) >> 24); \ + } + +#define WLAN_SET_FIELD_BE24(_memAddr_p, _value) \ + { \ + uint8_t *__cp = (uint8_t *)(_memAddr_p); \ + __cp[0] = (uint8_t)((_value) >> 16); \ + __cp[1] = (uint8_t)((_value) >> 8); \ + __cp[2] = (uint8_t)(_value); \ + } + +#define WLAN_SET_FIELD_BE32(_memAddr_p, _value) \ + { \ + uint8_t *__cp = (uint8_t *)(_memAddr_p); \ + __cp[0] = (uint8_t)((_value) >> 24); \ + __cp[1] = (uint8_t)((_value) >> 16); \ + __cp[2] = (uint8_t)((_value) >> 8); \ + __cp[3] = (uint8_t)(_value); \ + } + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _WLAN_DEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic_cmd_event.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic_cmd_event.h new file mode 100644 index 0000000000000..8606fb41a3ab5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic_cmd_event.h @@ -0,0 +1,4624 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + +#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 + ******************************************************************************* + */ +#include "gl_vendor.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define CMD_PQ_ID (0x8000) +#define CMD_PACKET_TYPE_ID (0xA0) + +#define PKT_FT_CMD 0x2 + +#define CMD_STATUS_SUCCESS 0 +#define CMD_STATUS_REJECTED 1 +#define CMD_STATUS_UNKNOWN 2 + +#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 + +/*CMD_POWER_OFFSET_T , follow 5G sub-band*/ +/* #define MAX_SUBBAND_NUM 8 */ +/* */ +/* */ +/* */ +/* */ +#define S2D_INDEX_CMD_H2N 0x0 +#define S2D_INDEX_CMD_C2N 0x1 +#define S2D_INDEX_CMD_H2C 0x2 +#define S2D_INDEX_CMD_H2N_H2C 0x3 + +#define S2D_INDEX_EVENT_N2H 0x0 +#define S2D_INDEX_EVENT_N2C 0x1 +#define S2D_INDEX_EVENT_C2H 0x2 +#define S2D_INDEX_EVENT_N2H_N2C 0x3 + +#define RDD_EVENT_HDR_SIZE 20 +#define RDD_ONEPLUSE_SIZE 8 /* size of one pulse is 8 bytes */ +#define RDD_PULSE_OFFSET0 0 +#define RDD_PULSE_OFFSET1 1 +#define RDD_PULSE_OFFSET2 2 +#define RDD_PULSE_OFFSET3 3 +#define RDD_PULSE_OFFSET4 4 +#define RDD_PULSE_OFFSET5 5 +#define RDD_PULSE_OFFSET6 6 +#define RDD_PULSE_OFFSET7 7 + +#if (CFG_SUPPORT_DFS_MASTER == 1) +#define RDD_IN_SEL_0 0 +#define RDD_IN_SEL_1 1 +#define PPB_SIZE 32 +#define LPB_SIZE 32 +#endif + +#if (CFG_SUPPORT_TXPOWER_INFO == 1) +#define TXPOWER_EVENT_SHOW_ALL_RATE_TXPOWER_INFO 0x5 +#endif + +#if CFG_SUPPORT_QA_TOOL +#define IQ_FILE_LINE_OFFSET 18 +#define IQ_FILE_IQ_STR_LEN 8 +#define RTN_IQ_DATA_LEN 1024 /* return 1k per packet */ + +#define MCAST_WCID_TO_REMOVE 0 + +/* Network type */ +#define NETWORK_INFRA BIT(16) +#define NETWORK_P2P BIT(17) +#define NETWORK_IBSS BIT(18) +#define NETWORK_MESH BIT(19) +#define NETWORK_BOW BIT(20) +#define NETWORK_WDS BIT(21) + +/* Station role */ +#define STA_TYPE_STA BIT(0) +#define STA_TYPE_AP BIT(1) +#define STA_TYPE_ADHOC BIT(2) +#define STA_TYPE_TDLS BIT(3) +#define STA_TYPE_WDS BIT(4) + +/* Connection type */ +#define CONNECTION_INFRA_STA (STA_TYPE_STA|NETWORK_INFRA) +#define CONNECTION_INFRA_AP (STA_TYPE_AP|NETWORK_INFRA) +#define CONNECTION_P2P_GC (STA_TYPE_STA|NETWORK_P2P) +#define CONNECTION_P2P_GO (STA_TYPE_AP|NETWORK_P2P) +#define CONNECTION_MESH_STA (STA_TYPE_STA|NETWORK_MESH) +#define CONNECTION_MESH_AP (STA_TYPE_AP|NETWORK_MESH) +#define CONNECTION_IBSS_ADHOC (STA_TYPE_ADHOC|NETWORK_IBSS) +#define CONNECTION_TDLS \ + (STA_TYPE_STA|NETWORK_INFRA|STA_TYPE_TDLS) +#define CONNECTION_WDS (STA_TYPE_WDS|NETWORK_WDS) + +#define ICAP_CONTENT_ADC 0x10000006 +#define ICAP_CONTENT_TOAE 0x7 +#define ICAP_CONTENT_SPECTRUM 0xB +#define ICAP_CONTENT_RBIST 0x10 +#define ICAP_CONTENT_DCOC 0x20 +#define ICAP_CONTENT_FIIQ 0x48 +#define ICAP_CONTENT_FDIQ 0x49 + +#if CFG_SUPPORT_BUFFER_MODE + +struct CMD_EFUSE_BUFFER_MODE { + uint8_t ucSourceMode; + uint8_t ucCount; + uint8_t ucCmdType; /* 0:6632, 1: 7668 */ + uint8_t ucReserved; + uint8_t aBinContent[MAX_EEPROM_BUFFER_SIZE]; +}; + +#define SOURCE_MODE_EFUSE (0) +#define SOURCE_MODE_BUFFER_MODE (1) + +#define CMD_TYPE_CONTENT_FORMAT_MASK BITS(0, 3) +#define CONTENT_FORMAT_BIN_CONTENT (0) +#define CONTENT_FORMAT_WHOLE_CONTENT (1) +#define CONTENT_FORMAT_MULTIPLE_SECTIONS (2) + +#define CMD_TYPE_CAL_TIME_REDUCTION_MASK BIT(4) +#define CMD_TYPE_CAL_TIME_REDUCTION_SHFT (4) +#define CAL_TIME_REDUCTION_ENABLE (1) + +struct CMD_EFUSE_BUFFER_MODE_CONNAC_T { + uint8_t ucSourceMode; + uint8_t ucContentFormat; + uint16_t u2Count; + uint8_t aBinContent[MAX_EEPROM_BUFFER_SIZE]; +}; + +/*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ +struct CMD_ACCESS_EFUSE { + uint32_t u4Address; + uint32_t u4Valid; + uint8_t aucData[16]; +}; + +struct CMD_EFUSE_FREE_BLOCK { + uint8_t ucGetFreeBlock; + uint8_t ucVersion; + uint8_t ucDieIndex; + uint8_t aucReserved; +}; + + +struct CMD_GET_TX_POWER { + uint8_t ucTxPwrType; + uint8_t ucCenterChannel; + uint8_t ucDbdcIdx; /* 0:Band 0, 1: Band1 */ + uint8_t ucBand; /* 0:G-band 1: A-band*/ + uint8_t ucReserved[4]; +}; + +/*#endif*/ + +#endif /* CFG_SUPPORT_BUFFER_MODE */ + + +struct CMD_SET_TX_TARGET_POWER { + int8_t cTxPwr2G4Cck; /* signed, in unit of 0.5dBm */ + int8_t cTxPwr2G4Dsss; /* signed, in unit of 0.5dBm */ + uint8_t ucTxTargetPwr; /* Tx target power base for all*/ + uint8_t ucReserved; + + int8_t cTxPwr2G4OFDM_BPSK; + int8_t cTxPwr2G4OFDM_QPSK; + int8_t cTxPwr2G4OFDM_16QAM; + int8_t cTxPwr2G4OFDM_Reserved; + int8_t cTxPwr2G4OFDM_48Mbps; + int8_t cTxPwr2G4OFDM_54Mbps; + + int8_t cTxPwr2G4HT20_BPSK; + int8_t cTxPwr2G4HT20_QPSK; + int8_t cTxPwr2G4HT20_16QAM; + int8_t cTxPwr2G4HT20_MCS5; + int8_t cTxPwr2G4HT20_MCS6; + int8_t cTxPwr2G4HT20_MCS7; + + int8_t cTxPwr2G4HT40_BPSK; + int8_t cTxPwr2G4HT40_QPSK; + int8_t cTxPwr2G4HT40_16QAM; + int8_t cTxPwr2G4HT40_MCS5; + int8_t cTxPwr2G4HT40_MCS6; + int8_t cTxPwr2G4HT40_MCS7; + + int8_t cTxPwr5GOFDM_BPSK; + int8_t cTxPwr5GOFDM_QPSK; + int8_t cTxPwr5GOFDM_16QAM; + int8_t cTxPwr5GOFDM_Reserved; + int8_t cTxPwr5GOFDM_48Mbps; + int8_t cTxPwr5GOFDM_54Mbps; + + int8_t cTxPwr5GHT20_BPSK; + int8_t cTxPwr5GHT20_QPSK; + int8_t cTxPwr5GHT20_16QAM; + int8_t cTxPwr5GHT20_MCS5; + int8_t cTxPwr5GHT20_MCS6; + int8_t cTxPwr5GHT20_MCS7; + + int8_t cTxPwr5GHT40_BPSK; + int8_t cTxPwr5GHT40_QPSK; + int8_t cTxPwr5GHT40_16QAM; + int8_t cTxPwr5GHT40_MCS5; + int8_t cTxPwr5GHT40_MCS6; + int8_t cTxPwr5GHT40_MCS7; +}; + + +/* + * Definitions for extension CMD_ID + */ +enum ENUM_EXT_CMD_ID { + EXT_CMD_ID_EFUSE_ACCESS = 0x01, + EXT_CMD_ID_RF_REG_ACCESS = 0x02, + EXT_CMD_ID_EEPROM_ACCESS = 0x03, + EXT_CMD_ID_RF_TEST = 0x04, + EXT_CMD_ID_RADIO_ON_OFF_CTRL = 0x05, + EXT_CMD_ID_WIFI_RX_DISABLE = 0x06, + EXT_CMD_ID_PM_STATE_CTRL = 0x07, + EXT_CMD_ID_CHANNEL_SWITCH = 0x08, + EXT_CMD_ID_NIC_CAPABILITY = 0x09, + EXT_CMD_ID_AP_PWR_SAVING_CLEAR = 0x0A, + EXT_CMD_ID_SET_WTBL2_RATETABLE = 0x0B, + EXT_CMD_ID_GET_WTBL_INFORMATION = 0x0C, + EXT_CMD_ID_ASIC_INIT_UNINIT_CTRL = 0x0D, + EXT_CMD_ID_MULTIPLE_REG_ACCESS = 0x0E, + EXT_CMD_ID_AP_PWR_SAVING_CAPABILITY = 0x0F, + EXT_CMD_ID_SECURITY_ADDREMOVE_KEY = 0x10, + EXT_CMD_ID_SET_TX_POWER_CONTROL = 0x11, + EXT_CMD_ID_SET_THERMO_CALIBRATION = 0x12, + EXT_CMD_ID_FW_LOG_2_HOST = 0x13, + EXT_CMD_ID_AP_PWR_SAVING_START = 0x14, + EXT_CMD_ID_MCC_OFFLOAD_START = 0x15, + EXT_CMD_ID_MCC_OFFLOAD_STOP = 0x16, + EXT_CMD_ID_LED = 0x17, + EXT_CMD_ID_PACKET_FILTER = 0x18, + EXT_CMD_ID_COEXISTENCE = 0x19, + EXT_CMD_ID_PWR_MGT_BIT_WIFI = 0x1B, + EXT_CMD_ID_GET_TX_POWER = 0x1C, + EXT_CMD_ID_BF_ACTION = 0x1E, + + EXT_CMD_ID_WMT_CMD_OVER_WIFI = 0x20, + EXT_CMD_ID_EFUSE_BUFFER_MODE = 0x21, + EXT_CMD_ID_OFFLOAD_CTRL = 0x22, + EXT_CMD_ID_THERMAL_PROTECT = 0x23, + EXT_CMD_ID_CLOCK_SWITCH_DISABLE = 0x24, + EXT_CMD_ID_STAREC_UPDATE = 0x25, + EXT_CMD_ID_BSSINFO_UPDATE = 0x26, + EXT_CMD_ID_EDCA_SET = 0x27, + EXT_CMD_ID_SLOT_TIME_SET = 0x28, + EXT_CMD_ID_DEVINFO_UPDATE = 0x2A, + EXT_CMD_ID_NOA_OFFLOAD_CTRL = 0x2B, + EXT_CMD_ID_GET_SENSOR_RESULT = 0x2C, + EXT_CMD_ID_TMR_CAL = 0x2D, + EXT_CMD_ID_WAKEUP_OPTION = 0x2E, + EXT_CMD_ID_OBTW = 0x2F, + + EXT_CMD_ID_GET_TX_STATISTICS = 0x30, + EXT_CMD_ID_AC_QUEUE_CONTROL = 0x31, + EXT_CMD_ID_WTBL_UPDATE = 0x32, + EXT_CMD_ID_BCN_UPDATE = 0x33, + + EXT_CMD_ID_DRR_CTRL = 0x36, + EXT_CMD_ID_BSSGROUP_CTRL = 0x37, + EXT_CMD_ID_VOW_FEATURE_CTRL = 0x38, + EXT_CMD_ID_PKT_PROCESSOR_CTRL = 0x39, + EXT_CMD_ID_PALLADIUM = 0x3A, +#if CFG_SUPPORT_MU_MIMO + EXT_CMD_ID_MU_CTRL = 0x40, +#endif /* CFG_SUPPORT_MU_MIMO */ + + EXT_CMD_ID_EFUSE_FREE_BLOCK = 0x4F, + EXT_CMD_ID_TX_POWER_FEATURE_CTRL = 0x58, + EXT_CMD_ID_SER = 0x81, +}; + +enum NDIS_802_11_WEP_STATUS { + Ndis802_11WEPEnabled, + Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, + Ndis802_11WEPDisabled, + Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, + Ndis802_11WEPKeyAbsent, + Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, + Ndis802_11WEPNotSupported, + Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, + Ndis802_11TKIPEnable, + Ndis802_11Encryption2Enabled = Ndis802_11TKIPEnable, + Ndis802_11Encryption2KeyAbsent, + Ndis802_11AESEnable, + Ndis802_11Encryption3Enabled = Ndis802_11AESEnable, + Ndis802_11CCMP256Enable, + Ndis802_11GCMP128Enable, + Ndis802_11GCMP256Enable, + Ndis802_11Encryption3KeyAbsent, + Ndis802_11TKIPAESMix, + /* TKIP or AES mix */ + Ndis802_11Encryption4Enabled = Ndis802_11TKIPAESMix, + Ndis802_11Encryption4KeyAbsent, + Ndis802_11GroupWEP40Enabled, + Ndis802_11GroupWEP104Enabled, +#ifdef WAPI_SUPPORT + Ndis802_11EncryptionSMS4Enabled, /* WPI SMS4 support */ +#endif /* WAPI_SUPPORT */ +}; + +#if CFG_SUPPORT_MU_MIMO +enum { + /* debug commands */ + MU_SET_ENABLE = 0, + MU_GET_ENABLE, + MU_SET_MUPROFILE_ENTRY, + MU_GET_MUPROFILE_ENTRY, + MU_SET_GROUP_TBL_ENTRY, + MU_GET_GROUP_TBL_ENTRY, + MU_SET_CLUSTER_TBL_ENTRY, + MU_GET_CLUSTER_TBL_ENTRY, + MU_SET_GROUP_USER_THRESHOLD, + MU_GET_GROUP_USER_THRESHOLD, + MU_SET_GROUP_NSS_THRESHOLD, + MU_GET_GROUP_NSS_THRESHOLD, + MU_SET_TXREQ_MIN_TIME, + MU_GET_TXREQ_MIN_TIME, + MU_SET_SU_NSS_CHECK, + MU_GET_SU_NSS_CHECK, + MU_SET_CALC_INIT_MCS, + MU_GET_CALC_INIT_MCS, + MU_SET_TXOP_DEFAULT, + MU_GET_TXOP_DEFAULT, + MU_SET_SU_LOSS_THRESHOLD, + MU_GET_SU_LOSS_THRESHOLD, + MU_SET_MU_GAIN_THRESHOLD, + MU_GET_MU_GAIN_THRESHOLD, + MU_SET_SECONDARY_AC_POLICY, + MU_GET_SECONDARY_AC_POLICY, + MU_SET_GROUP_TBL_DMCS_MASK, + MU_GET_GROUP_TBL_DMCS_MASK, + MU_SET_MAX_GROUP_SEARCH_CNT, + MU_GET_MAX_GROUP_SEARCH_CNT, + MU_GET_MU_PROFILE_TX_STATUS_CNT, + MU_SET_TRIGGER_MU_TX, + /* F/W flow test commands */ + MU_SET_TRIGGER_GID_MGMT_FRAME, + /* HQA commands */ + MU_HQA_SET_STA_PARAM, + MU_HQA_SET_ENABLE, + MU_HQA_SET_SNR_OFFSET, + MU_HQA_SET_ZERO_NSS, + MU_HQA_SET_SPEED_UP_LQ, + MU_HQA_SET_GROUP, + MU_HQA_SET_MU_TABLE, + MU_HQA_SET_CALC_LQ, + MU_HQA_GET_CALC_LQ, + MU_HQA_SET_CALC_INIT_MCS, + MU_HQA_GET_CALC_INIT_MCS, + MU_HQA_GET_QD, +}; +#endif /* CFG_SUPPORT_MU_MIMO */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +enum ENUM_CMD_ID { + CMD_ID_DUMMY_RSV = 0x00, /* 0x00 (Set) */ + CMD_ID_TEST_CTRL = 0x01, /* 0x01 (Set) */ + CMD_ID_BASIC_CONFIG, /* 0x02 (Set) */ + CMD_ID_SCAN_REQ_V2, /* 0x03 (Set) */ + CMD_ID_NIC_POWER_CTRL, /* 0x04 (Set) */ + CMD_ID_POWER_SAVE_MODE, /* 0x05 (Set) */ + CMD_ID_LINK_ATTRIB, /* 0x06 (Set) */ + CMD_ID_ADD_REMOVE_KEY, /* 0x07 (Set) */ + CMD_ID_DEFAULT_KEY_ID, /* 0x08 (Set) */ + CMD_ID_INFRASTRUCTURE, /* 0x09 (Set) */ + CMD_ID_SET_RX_FILTER, /* 0x0a (Set) */ + CMD_ID_DOWNLOAD_BUF, /* 0x0b (Set) */ + CMD_ID_WIFI_START, /* 0x0c (Set) */ + CMD_ID_CMD_BT_OVER_WIFI, /* 0x0d (Set) */ + CMD_ID_SET_MEDIA_CHANGE_DELAY_TIME, /* 0x0e (Set) */ + CMD_ID_SET_DOMAIN_INFO, /* 0x0f (Set) */ + CMD_ID_SET_IP_ADDRESS, /* 0x10 (Set) */ + CMD_ID_BSS_ACTIVATE_CTRL, /* 0x11 (Set) */ + CMD_ID_SET_BSS_INFO, /* 0x12 (Set) */ + CMD_ID_UPDATE_STA_RECORD, /* 0x13 (Set) */ + CMD_ID_REMOVE_STA_RECORD, /* 0x14 (Set) */ + CMD_ID_INDICATE_PM_BSS_CREATED, /* 0x15 (Set) */ + CMD_ID_INDICATE_PM_BSS_CONNECTED, /* 0x16 (Set) */ + CMD_ID_INDICATE_PM_BSS_ABORT, /* 0x17 (Set) */ + CMD_ID_UPDATE_BEACON_CONTENT, /* 0x18 (Set) */ + CMD_ID_SET_BSS_RLM_PARAM, /* 0x19 (Set) */ + CMD_ID_SCAN_REQ, /* 0x1a (Set) */ + CMD_ID_SCAN_CANCEL, /* 0x1b (Set) */ + CMD_ID_CH_PRIVILEGE, /* 0x1c (Set) */ + CMD_ID_UPDATE_WMM_PARMS, /* 0x1d (Set) */ + CMD_ID_SET_WMM_PS_TEST_PARMS, /* 0x1e (Set) */ + CMD_ID_TX_AMPDU, /* 0x1f (Set) */ + CMD_ID_ADDBA_REJECT, /* 0x20 (Set) */ + CMD_ID_SET_PS_PROFILE_ADV, /* 0x21 (Set) */ + CMD_ID_SET_RAW_PATTERN, /* 0x22 (Set) */ + CMD_ID_CONFIG_PATTERN_FUNC, /* 0x23 (Set) */ + CMD_ID_SET_TX_PWR, /* 0x24 (Set) */ + CMD_ID_SET_PWR_PARAM, /* 0x25 (Set) */ + CMD_ID_P2P_ABORT, /* 0x26 (Set) */ + CMD_ID_SET_DBDC_PARMS = 0x28, /* 0x28 (Set) */ +#if CFG_SUPPORT_ADVANCE_CONTROL + CMD_ID_KEEP_FULL_PWR = 0x2A, /* 0x2A (Set) */ +#endif + /* SLT commands */ + 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 ) */ + + CMD_ID_ROAMING_TRANSIT = 0x30, /* 0x30 (Set) */ + CMD_ID_SET_PHY_PARAM, /* 0x31 (Set) */ + CMD_ID_SET_NOA_PARAM, /* 0x32 (Set) */ + CMD_ID_SET_OPPPS_PARAM, /* 0x33 (Set) */ + CMD_ID_SET_UAPSD_PARAM, /* 0x34 (Set) */ + CMD_ID_SET_SIGMA_STA_SLEEP, /* 0x35 (Set) */ + CMD_ID_SET_EDGE_TXPWR_LIMIT, /* 0x36 (Set) */ + CMD_ID_SET_DEVICE_MODE, /* 0x37 (Set) */ + CMD_ID_SET_TXPWR_CTRL, /* 0x38 (Set) */ + CMD_ID_SET_AUTOPWR_CTRL, /* 0x39 (Set) */ + CMD_ID_SET_WFD_CTRL, /* 0x3a (Set) */ + CMD_ID_SET_NLO_REQ, /* 0x3b (Set) */ + CMD_ID_SET_NLO_CANCEL, /* 0x3c (Set) */ + CMD_ID_SET_GTK_REKEY_DATA, /* 0x3d (Set) */ + CMD_ID_ROAMING_CONTROL, /* 0x3e (Set) */ + /* CFG_M0VE_BA_TO_DRIVER */ + CMD_ID_RESET_BA_SCOREBOARD = 0x3f, /* 0x3f (Set) */ + CMD_ID_SET_EDGE_TXPWR_LIMIT_5G = 0x40, /* 0x40 (Set) */ + CMD_ID_SET_CHANNEL_PWR_OFFSET, /* 0x41 (Set) */ + CMD_ID_SET_80211AC_TX_PWR, /* 0x42 (Set) */ + CMD_ID_SET_PATH_COMPASATION, /* 0x43 (Set) */ + + CMD_ID_SET_BATCH_REQ = 0x47, /* 0x47 (Set) */ + CMD_ID_SET_NVRAM_SETTINGS, /* 0x48 (Set) */ + CMD_ID_SET_COUNTRY_POWER_LIMIT, /* 0x49 (Set) */ + +#if CFG_WOW_SUPPORT + CMD_ID_SET_WOWLAN, /* 0x4a (Set) */ +#endif + CMD_ID_SET_MDNS_RECORD = 0x4e, + +#if CFG_SUPPORT_WIFI_HOST_OFFLOAD + CMD_ID_SET_AM_FILTER = 0x55, /* 0x55 (Set) */ + CMD_ID_SET_AM_HEARTBEAT, /* 0x56 (Set) */ + CMD_ID_SET_AM_TCP, /* 0x57 (Set) */ +#endif + CMD_ID_SET_SUSPEND_MODE = 0x58, /* 0x58 (Set) */ + + CMD_ID_SET_COUNTRY_POWER_LIMIT_PER_RATE = 0x5d, /* 0x5d (Set) */ + +#if CFG_WOW_SUPPORT + CMD_ID_SET_PF_CAPABILITY = 0x59, /* 0x59 (Set) */ +#endif + CMD_ID_SET_RRM_CAPABILITY = 0x5A, /* 0x5A (Set) */ + CMD_ID_SET_AP_CONSTRAINT_PWR_LIMIT = 0x5B, /* 0x5B (Set) */ + CMD_ID_SET_TSM_STATISTICS_REQUEST = 0x5E, + CMD_ID_GET_TSM_STATISTICS = 0x5F, + CMD_ID_GET_PSCAN_CAPABILITY = 0x60, /* 0x60 (Get) deprecated */ + CMD_ID_SET_SCHED_SCAN_ENABLE, /* 0x61 (Set) */ + CMD_ID_SET_SCHED_SCAN_REQ, /* 0x62 (Set) */ + CMD_ID_SET_GSCAN_ADD_HOTLIST_BSSID, /* 0x63 (Set) deprecated */ + CMD_ID_SET_GSCAN_ADD_SWC_BSSID, /* 0x64 (Set) deprecated */ + CMD_ID_SET_GSCAN_MAC_ADDR, /* 0x65 (Set) deprecated */ + CMD_ID_GET_GSCAN_RESULT, /* 0x66 (Get) deprecated */ + CMD_ID_SET_PSCAN_MAC_ADDR, /* 0x67 (Set) deprecated */ + CMD_ID_UPDATE_AC_PARMS = 0x6A, /* 0x6A (Set) */ +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + /* 0x6D (Set) used to setting roaming skip*/ + CMD_ID_SET_ROAMING_SKIP = 0x6D, +#endif + CMD_ID_GET_SET_CUSTOMER_CFG = 0x70, /* 0x70(Set) */ + CMD_ID_TDLS_PS = 0x75, /* 0x75 (Set) */ + CMD_ID_GET_CNM = 0x79, + CMD_ID_COEX_CTRL = 0x7C, /* 0x7C (Set/Query) */ + CMD_ID_PERF_IND = 0x7E, /* 0x7C (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_STA_STATISTICS = 0x85, /* 0x85 (Query) */ + + CMD_ID_GET_LTE_CHN = 0x87, /* 0x87 (Query) */ + CMD_ID_GET_CHN_LOADING = 0x88, /* 0x88 (Query) */ + CMD_ID_GET_BUG_REPORT = 0x89, /* 0x89 (Query) */ + CMD_ID_GET_NIC_CAPABILITY_V2 = 0x8A,/* 0x8A (Query) */ + CMD_ID_LOG_UI_INFO = 0x8D, /* 0x8D (Set / Query) */ + +#if CFG_SUPPORT_OSHARE + CMD_ID_SET_OSHARE_MODE = 0x8C, +#endif + +#if (CFG_SUPPORT_DFS_MASTER == 1) + CMD_ID_RDD_ON_OFF_CTRL = 0x8F, /* 0x8F(Set) */ +#endif + +#if CFG_SUPPORT_ANT_DIV + CMD_ID_ANT_DIV_CTRL = 0x91, +#endif + + CMD_ID_TMR_ACTION = 0x92, + + CMD_ID_WFC_KEEP_ALIVE = 0xA0, /* 0xa0(Set) */ + CMD_ID_RSSI_MONITOR = 0xA1, /* 0xa1(Set) */ + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST + CMD_ID_CAL_BACKUP_IN_HOST_V2 = 0xAE, /* 0xAE (Set / Query) */ +#endif + + CMD_ID_ACCESS_REG = 0xc0, /* 0xc0 (Set / Query) */ + CMD_ID_MAC_MCAST_ADDR, /* 0xc1 (Set / Query) */ + CMD_ID_802_11_PMKID, /* 0xc2 (Set / Query) */ + CMD_ID_ACCESS_EEPROM, /* 0xc3 (Set / Query) */ + CMD_ID_SW_DBG_CTRL, /* 0xc4 (Set / Query) */ + CMD_ID_FW_LOG_2_HOST, /* 0xc5 (Set) */ + CMD_ID_DUMP_MEM, /* 0xc6 (Query) */ + CMD_ID_RESOURCE_CONFIG, /* 0xc7 (Set / Query) */ +#if CFG_SUPPORT_QA_TOOL + CMD_ID_ACCESS_RX_STAT, /* 0xc8 (Query) */ +#endif /* CFG_SUPPORT_QA_TOOL */ + CMD_ID_CHIP_CONFIG = 0xCA, /* 0xca (Set / Query) */ + CMD_ID_STATS_LOG = 0xCB, /* 0xcb (Set) */ + CMD_ID_IPI_INFO = 0xCC, /* 0xcc (Query) */ + CMD_ID_WLAN_INFO = 0xCD, /* 0xcd (Query) */ + CMD_ID_MIB_INFO = 0xCE, /* 0xce (Query) */ +#if CFG_SUPPORT_GET_MCS_INFO + CMD_ID_TX_MCS_INFO = 0xCF, /* 0xcf (Query) */ +#endif + CMD_ID_GET_TXPWR_TBL = 0xD0, /* 0xd0 (Query) */ + CMD_ID_SET_TXBF_BACKOFF = 0xD1, + + CMD_ID_SET_RDD_CH = 0xE1, + +#if CFG_SUPPORT_QA_TOOL + /* magic number for Extending MT6630 original CMD header */ + CMD_ID_LAYER_0_EXT_MAGIC_NUM = 0xED, +#endif /* CFG_SUPPORT_QA_TOOL */ + + CMD_ID_SET_BWCS = 0xF1, + CMD_ID_SET_OSC = 0xF2, + + CMD_ID_HIF_CTRL = 0xF6, /* 0xF6 (Set) */ + + CMD_ID_GET_BUILD_DATE_CODE = 0xF8, /* 0xf8 (Query) */ + CMD_ID_GET_BSS_INFO = 0xF9, /* 0xF9 (Query) */ + CMD_ID_SET_HOTSPOT_OPTIMIZATION = 0xFA, /* 0xFA (Set) */ + CMD_ID_SET_TDLS_CH_SW = 0xFB, + CMD_ID_SET_MONITOR = 0xFC, /* 0xFC (Set) */ +#if CFG_SUPPORT_ADVANCE_CONTROL + CMD_ID_ADV_CONTROL = 0xFE, /* 0xFE (Set / Query) */ +#endif + CMD_ID_END +}; + +enum ENUM_EVENT_ID { + EVENT_ID_NIC_CAPABILITY = 0x01, /* 0x01 (Query) */ + EVENT_ID_LINK_QUALITY, /* 0x02 (Query / Unsolicited) */ + EVENT_ID_STATISTICS, /* 0x03 (Query) */ + EVENT_ID_MIC_ERR_INFO, /* 0x04 (Unsolicited) */ + EVENT_ID_ACCESS_REG, /* 0x05 (Query - CMD_ID_ACCESS_REG) */ + EVENT_ID_ACCESS_EEPROM, /* 0x06 (Query - CMD_ID_ACCESS_EEPROM) */ + EVENT_ID_SLEEPY_INFO, /* 0x07 (Unsolicited) */ + EVENT_ID_BT_OVER_WIFI, /* 0x08 (Unsolicited) */ + EVENT_ID_TEST_STATUS, /* 0x09 (Query - CMD_ID_TEST_CTRL) */ + EVENT_ID_RX_ADDBA, /* 0x0a (Unsolicited) */ + EVENT_ID_RX_DELBA, /* 0x0b (Unsolicited) */ + EVENT_ID_ACTIVATE_STA_REC, /* 0x0c (Response) */ + EVENT_ID_SCAN_DONE, /* 0x0d (Unsoiicited) */ + EVENT_ID_RX_FLUSH, /* 0x0e (Unsolicited) */ + EVENT_ID_TX_DONE, /* 0x0f (Unsolicited) */ + EVENT_ID_CH_PRIVILEGE, /* 0x10 (Unsolicited) */ + EVENT_ID_BSS_ABSENCE_PRESENCE, /* 0x11 (Unsolicited) */ + EVENT_ID_STA_CHANGE_PS_MODE, /* 0x12 (Unsolicited) */ + EVENT_ID_BSS_BEACON_TIMEOUT, /* 0x13 (Unsolicited) */ + EVENT_ID_UPDATE_NOA_PARAMS, /* 0x14 (Unsolicited) */ + EVENT_ID_AP_OBSS_STATUS, /* 0x15 (Unsolicited) */ + EVENT_ID_STA_UPDATE_FREE_QUOTA, /* 0x16 (Unsolicited) */ + EVENT_ID_SW_DBG_CTRL, /* 0x17 (Query - CMD_ID_SW_DBG_CTRL) */ + EVENT_ID_ROAMING_STATUS, /* 0x18 (Unsolicited) */ + EVENT_ID_STA_AGING_TIMEOUT, /* 0x19 (Unsolicited) */ + EVENT_ID_SEC_CHECK_RSP, /* 0x1a (Query - CMD_ID_SEC_CHECK) */ + EVENT_ID_SEND_DEAUTH, /* 0x1b (Unsolicited) */ + EVENT_ID_UPDATE_RDD_STATUS, /* 0x1c (Unsolicited) */ + EVENT_ID_UPDATE_BWCS_STATUS, /* 0x1d (Unsolicited) */ + EVENT_ID_UPDATE_BCM_DEBUG, /* 0x1e (Unsolicited) */ + EVENT_ID_RX_ERR, /* 0x1f (Unsolicited) */ + EVENT_ID_DUMP_MEM = 0x20, /* 0x20 (Query - CMD_ID_DUMP_MEM) */ + EVENT_ID_STA_STATISTICS, /* 0x21 (Query ) */ + EVENT_ID_STA_STATISTICS_UPDATE, /* 0x22 (Unsolicited) */ + EVENT_ID_SCHED_SCAN_DONE, /* 0x23 (Unsoiicited) */ + EVENT_ID_ADD_PKEY_DONE, /* 0x24 (Unsoiicited) */ + EVENT_ID_ICAP_DONE, /* 0x25 (Unsoiicited) */ + /* 0x26 (Query - CMD_ID_RESOURCE_CONFIG) */ + EVENT_ID_RESOURCE_CONFIG = 0x26, + EVENT_ID_DEBUG_MSG = 0x27, /* 0x27 (Unsoiicited) */ + EVENT_ID_RTT_CALIBR_DONE = 0x28, /* 0x28 (Unsoiicited) */ + EVENT_ID_RTT_UPDATE_RANGE = 0x29, /* 0x29 (Unsoiicited) */ + EVENT_ID_CHECK_REORDER_BUBBLE = 0x2a, /* 0x2a (Unsoiicited) */ + EVENT_ID_BATCH_RESULT = 0x2b, /* 0x2b (Query) */ + EVENT_ID_TX_ADDBA = 0x2e, /* 0x2e (Unsolicited) */ + EVENT_ID_GET_GTK_REKEY_DATA = 0x3d, /* 0x3d (Query) */ + + EVENT_ID_UART_ACK = 0x40, /* 0x40 (Unsolicited) */ + EVENT_ID_UART_NAK, /* 0x41 (Unsolicited) */ + EVENT_ID_GET_CHIPID, /* 0x42 (Query - CMD_ID_GET_CHIPID) */ + EVENT_ID_SLT_STATUS, /* 0x43 (Query - CMD_ID_SET_SLTINFO) */ + EVENT_ID_CHIP_CONFIG, /* 0x44 (Query - CMD_ID_CHIP_CONFIG) */ + +#if CFG_SUPPORT_QA_TOOL + /* 0x45 (Query - CMD_ID_ACCESS_RX_STAT) */ + EVENT_ID_ACCESS_RX_STAT, +#endif /* CFG_SUPPORT_QA_TOOL */ + + EVENT_ID_RDD_SEND_PULSE = 0x50, + +#if CFG_SUPPORT_TX_BF + EVENT_ID_PFMU_TAG_READ = 0x51, + EVENT_ID_PFMU_DATA_READ = 0x52, +#endif + +#if CFG_SUPPORT_MU_MIMO + EVENT_ID_MU_GET_QD = 0x53, + EVENT_ID_MU_GET_LQ = 0x54, +#endif + +#if (CFG_SUPPORT_DFS_MASTER == 1) + EVENT_ID_RDD_REPORT = 0x60, + EVENT_ID_CSA_DONE = 0x61, +#if (CFG_WOW_SUPPORT == 1) + EVENT_ID_WOW_WAKEUP_REASON = 0x62, +#endif +#if CFG_SUPPORT_IDC_CH_SWITCH + EVENT_ID_LTE_IDC_REPORT = 0x64, +#endif +#endif + EVENT_ID_DBDC_SWITCH_DONE = 0x78, + EVENT_ID_GET_CNM = 0x79, + EVENT_ID_TDLS = 0x80, /* TDLS event_id */ + EVENT_ID_LOG_UI_INFO = 0x8D, + + EVENT_ID_UPDATE_COEX_PHYRATE = 0x90, /* 0x90 (Unsolicited) */ + + EVENT_ID_TM_REPORT = 0x92, + + EVENT_ID_RSSI_MONITOR = 0xA1, + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST + /* 0xAE (Query - CMD_ID_CAL_BACKUP) */ + EVENT_ID_CAL_BACKUP_IN_HOST_V2 = 0xAE, + /* 0xAF (FW Cal All Done Event) */ + EVENT_ID_CAL_ALL_DONE = 0xAF, +#endif + EVENT_ID_IPI_INFO = 0xCC, + EVENT_ID_WLAN_INFO = 0xCD, + EVENT_ID_MIB_INFO = 0xCE, +#if CFG_SUPPORT_GET_MCS_INFO + EVENT_ID_TX_MCS_INFO = 0xCF, +#endif + EVENT_ID_GET_TXPWR_TBL = 0xD0, + + /* 0xEC (Query - CMD_ID_GET_NIC_CAPABILITY_V2) */ + EVENT_ID_NIC_CAPABILITY_V2 = 0xEC, + /*#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1)*/ + /* magic number for Extending MT6630 original EVENT header */ + EVENT_ID_LAYER_0_EXT_MAGIC_NUM = 0xED, + /*#endif*/ + +#if CFG_ASSERT_DUMP + EVENT_ID_ASSERT_DUMP = 0xF0, +#endif + EVENT_ID_HIF_CTRL = 0xF6, + EVENT_ID_BUILD_DATE_CODE = 0xF8, + EVENT_ID_GET_AIS_BSS_INFO = 0xF9, + EVENT_ID_DEBUG_CODE = 0xFB, + EVENT_ID_RFTEST_READY = 0xFC, /* 0xFC */ +#if CFG_SUPPORT_ADVANCE_CONTROL + EVENT_ID_ADV_CONTROL = 0xFE, +#endif + EVENT_ID_END +}; + +#if CFG_WOW_SUPPORT + +/* Filter Flag */ +#define WOWLAN_FF_DROP_ALL BIT(0) +#define WOWLAN_FF_SEND_MAGIC_TO_HOST BIT(1) +#define WOWLAN_FF_ALLOW_ARP BIT(2) +#define WOWLAN_FF_ALLOW_BMC BIT(3) +#define WOWLAN_FF_ALLOW_UC BIT(4) +#define WOWLAN_FF_ALLOW_1X BIT(5) +#define WOWLAN_FF_ALLOW_ARP_REQ2ME BIT(6) + +/* wow detect type */ +#define WOWLAN_DETECT_TYPE_NONE 0 +#define WOWLAN_DETECT_TYPE_MAGIC BIT(0) +#define WOWLAN_DETECT_TYPE_ANY BIT(1) +#define WOWLAN_DETECT_TYPE_DISCONNECT BIT(2) +#define WOWLAN_DETECT_TYPE_GTK_REKEY_FAILURE BIT(3) +#define WOWLAN_DETECT_TYPE_BCN_LOST BIT(4) + +/* Wakeup command bit define */ +#define PF_WAKEUP_CMD_BIT0_OUTPUT_MODE_EN BIT(0) +#define PF_WAKEUP_CMD_BIT1_OUTPUT_DATA BIT(1) +#define PF_WAKEUP_CMD_BIT2_WAKEUP_LEVEL BIT(2) + +#define PM_WOWLAN_REQ_START 0x1 +#define PM_WOWLAN_REQ_STOP 0x2 + +struct CMD_WAKE_HIF { + /* use in-band signal to wakeup system, ENUM_HIF_TYPE */ + uint8_t ucWakeupHif; + uint8_t ucGpioPin; /* GPIO Pin */ + uint8_t ucTriggerLvl; /* GPIO Pin */ + uint8_t aucResv1[1]; + /* 0: low to high, 1: high to low */ + uint32_t u4GpioInterval; + uint8_t aucResv2[4]; +}; + +struct CMD_WOWLAN_PARAM { + uint8_t ucCmd; + uint8_t ucDetectType; + /* ARP/MC/DropExceptMagic/SendMagicToHost */ + uint16_t u2FilterFlag; + uint8_t ucScenarioID; /* WOW/WOBLE/Proximity */ + uint8_t ucBlockCount; + uint8_t ucBssid; + uint8_t aucReserved1[1]; + struct CMD_WAKE_HIF astWakeHif[2]; + struct WOW_PORT stWowPort; + uint8_t aucReserved2[32]; +}; + +struct EVENT_WOWLAN_NOTIFY { + uint8_t ucNetTypeIndex; + uint8_t aucReserved[3]; +}; + +/* PACKETFILTER CAPABILITY TYPE */ + +#define PACKETF_CAP_TYPE_ARP BIT(1) +#define PACKETF_CAP_TYPE_MAGIC BIT(2) +#define PACKETF_CAP_TYPE_BITMAP BIT(3) +#define PACKETF_CAP_TYPE_EAPOL BIT(4) +#define PACKETF_CAP_TYPE_TDLS BIT(5) +#define PACKETF_CAP_TYPE_CF BIT(6) +#define PACKETF_CAP_TYPE_HEARTBEAT BIT(7) +#define PACKETF_CAP_TYPE_TCP_SYN BIT(8) +#define PACKETF_CAP_TYPE_UDP_SYN BIT(9) +#define PACKETF_CAP_TYPE_BCAST_SYN BIT(10) +#define PACKETF_CAP_TYPE_MCAST_SYN BIT(11) +#define PACKETF_CAP_TYPE_V6 BIT(12) +#define PACKETF_CAP_TYPE_TDIM BIT(13) + + +enum _ENUM_FUNCTION_SELECT { + FUNCTION_PF = 1, + FUNCTION_BITMAP = 2, + FUNCTION_EAPOL = 3, + FUNCTION_TDLS = 4, + FUNCTION_ARPNS = 5, + FUNCTION_CF = 6, + FUNCTION_MODE = 7, + FUNCTION_BSSID = 8, + FUNCTION_MGMT = 9, + FUNCTION_BMC_DROP = 10, + FUNCTION_UC_DROP = 11, + FUNCTION_ALL_TOMCU = 12, +}; + +enum ENUM_PF_OPCODE { + PF_OPCODE_ADD = 0, + PF_OPCODE_DEL, + PF_OPCODE_ENABLE, + PF_OPCODE_DISABLE, + PF_OPCODE_NUM +}; + +enum ENUM_SCN_FUNC_MASK { + ENUM_SCN_RANDOM_MAC_EN = (1 << 0), +}; + +enum ENUM_WOW_WAKEUP_REASON { + ENUM_PF_CMD_TYPE_MAGIC = 0, + ENUM_PF_CMD_TYPE_BITMAP = 1, + ENUM_PF_CMD_TYPE_ARPNS = 2, + ENUM_PF_CMD_TYPE_GTK_REKEY = 3, + ENUM_PF_CMD_TYPE_COALESCING_FILTER = 4, + ENUM_PF_CMD_TYPE_HW_GLOBAL_ENABLE = 5, + ENUM_PF_CMD_TYPE_TCP_SYN = 6, + ENUM_PF_CMD_TYPE_TDLS = 7, + ENUM_PF_CMD_TYPE_DISCONNECT = 8, + ENUM_PF_CMD_TYPE_IPV4_UDP = 9, + ENUM_PF_CMD_TYPE_IPV4_TCP = 10, + ENUM_PF_CMD_TYPE_IPV6_UDP = 11, + ENUM_PF_CMD_TYPE_IPV6_TCP = 12, + ENUM_PF_CMD_TYPE_BEACON_LOST = 13, + ENUM_PF_CMD_TYPE_UNDEFINED = 255, +}; + +struct CMD_PACKET_FILTER_CAP { + uint8_t ucCmd; + uint16_t packet_cap_type; + uint8_t aucReserved1[1]; + /* GLOBAL */ + uint32_t PFType; + uint32_t FunctionSelect; + uint32_t Enable; + /* MAGIC */ + uint8_t ucBssid; + uint16_t usEnableBits; + uint8_t aucReserved5[1]; + /* DTIM */ + uint8_t DtimEnable; + uint8_t DtimValue; + uint8_t aucReserved2[2]; + /* BITMAP_PATTERN_T */ + uint32_t Index; + uint32_t Offset; + uint32_t FeatureBits; + uint32_t Resv; + uint32_t PatternLength; + uint32_t Mask[4]; + uint32_t Pattern[32]; + /* COALESCE */ + uint32_t FilterID; + uint32_t PacketType; + uint32_t CoalesceOP; + uint8_t FieldLength; + uint8_t CompareOP; + uint8_t FieldID; + uint8_t aucReserved3[1]; + uint32_t Pattern3[4]; + /* TCPSYN */ + uint32_t AddressType; + uint32_t TCPSrcPort; + uint32_t TCPDstPort; + uint32_t SourceIP[4]; + uint32_t DstIP[4]; + uint8_t aucReserved4[64]; +}; + +#endif /*CFG_WOW_SUPPORT*/ + +#if CFG_SUPPORT_WIFI_HOST_OFFLOAD +struct CMD_TCP_GENERATOR { + enum ENUM_PF_OPCODE eOpcode; + uint32_t u4ReplyId; + uint32_t u4Period; + uint32_t u4Timeout; + uint32_t u4IpId; + uint32_t u4DestPort; + uint32_t u4SrcPort; + uint32_t u4Seq; + uint8_t aucDestIp[4]; + uint8_t aucSrcIp[4]; + uint8_t aucDestMac[6]; + uint8_t ucBssId; + uint8_t aucReserved1[1]; + uint8_t aucReserved2[64]; +}; + +struct CMD_PATTERN_GENERATOR { + enum ENUM_PF_OPCODE eOpcode; + uint32_t u4ReplyId; + uint32_t u4EthernetLength; + uint32_t u4Period; + uint8_t aucEthernetFrame[128]; + uint8_t ucBssId; + uint8_t aucReserved1[3]; + uint8_t aucReserved2[64]; +}; + +struct CMD_BITMAP_FILTER { + enum ENUM_PF_OPCODE eOpcode; + uint32_t u4ReplyId; + uint32_t u4Offset; + uint32_t u4Length; + uint8_t aucPattern[64]; + uint8_t aucBitMask[64]; + u_int8_t fgIsEqual; + u_int8_t fgIsAccept; + uint8_t ucBssId; + uint8_t aucReserved1[1]; + uint8_t aucReserved2[64]; +}; + +#endif /*CFG_SUPPORT_WIFI_HOST_OFFLOAD*/ + +#if CFG_SUPPORT_PER_BSS_FILTER +struct CMD_RX_PACKET_FILTER { + uint32_t u4RxPacketFilter; + uint8_t ucIsPerBssFilter; + uint8_t ucBssIndex; + uint8_t aucReserved[2]; + uint32_t u4BssMgmtFilter; + uint8_t aucReserved2[56]; +}; +#else +struct CMD_RX_PACKET_FILTER { + uint32_t u4RxPacketFilter; + uint8_t aucReserved[64]; +}; +#endif + +#if defined(MT6632) +#define S2D_INDEX_CMD_H2N 0x0 +#define S2D_INDEX_CMD_C2N 0x1 +#define S2D_INDEX_CMD_H2C 0x2 +#define S2D_INDEX_CMD_H2N_H2C 0x3 + +#define S2D_INDEX_EVENT_N2H 0x0 +#define S2D_INDEX_EVENT_N2C 0x1 +#define S2D_INDEX_EVENT_C2H 0x2 +#define S2D_INDEX_EVENT_N2H_N2C 0x3 +#endif + +#define EXT_EVENT_TARGET_TX_POWER 0x1 + +#define EXT_EVENT_ID_CMD_RESULT 0x00 +#define EXT_EVENT_ID_EFUSE_ACCESS 0x01 +#define EXT_EVENT_ID_RF_REG_ACCESS 0x02 +#define EXT_EVENT_ID_EEPROM_ACCESS 0x03 +#define EXT_EVENT_ID_RF_TEST 0x04 +#define EXT_EVENT_ID_PS_SYNC 0x05 +#define EXT_EVENT_ID_SLEEPY_NOTIFY 0x06 +#define EXT_EVENT_ID_WLAN_ERROR 0x07 +#define EXT_EVENT_ID_NIC_CAPABILITY 0x09 +#define EXT_EVENT_ID_AP_PWR_SAVING_CLEAR 0x0A +#define EXT_EVENT_ID_SET_WTBL2_RATETABLE 0x0B +#define EXT_EVENT_ID_GET_WTBL2_INFORMATION 0x0C +#define EXT_EVENT_ID_MULTIPLE_REG_ACCESS 0x0E +#define EXT_EVENT_ID_AP_PWR_SAVING_CAPABILITY 0x0F +#define EXT_EVENT_ID_SECURITY_ADDREMOVE_KEY 0x10 +#define EXT_EVENT_ID_FW_LOG_2_HOST 0x13 +#define EXT_EVENT_ID_AP_PWR_SAVING_START 0x14 +#define EXT_EVENT_ID_PACKET_FILTER 0x18 +#define EXT_EVENT_ID_COEXISTENCE 0x19 +#define EXT_EVENT_ID_BEACON_LOSS 0x1A +#define EXT_EVENT_ID_PWR_MGT_BIT_WIFI 0x1B +#define EXT_EVENT_ID_GET_TX_POWER 0x1C + +#define EXT_EVENT_ID_WMT_EVENT_OVER_WIFI 0x20 +#define EXT_EVENT_ID_MCC_TRIGGER 0x21 +#define EXT_EVENT_ID_THERMAL_PROTECT 0x22 +#define EXT_EVENT_ID_ASSERT_DUMP 0x23 +#define EXT_EVENT_ID_GET_SENSOR_RESULT 0x2C +#define EXT_EVENT_ID_ROAMING_DETECT_NOTIFICATION 0x2D +#define EXT_EVENT_ID_TMR_CAL 0x2E +#define EXT_EVENT_ID_RA_THROUGHPUT_BURST 0x2F + +#define EXT_EVENT_ID_GET_TX_STATISTIC 0x30 +#define EXT_EVENT_ID_PRETBTT_INT 0x31 +#define EXT_EVENT_ID_WTBL_UPDATE 0x32 + +#define EXT_EVENT_ID_BF_STATUS_READ 0x35 +#define EXT_EVENT_ID_DRR_CTRL 0x36 +#define EXT_EVENT_ID_BSSGROUP_CTRL 0x37 +#define EXT_EVENT_ID_VOW_FEATURE_CTRL 0x38 +#define EXT_EVENT_ID_PKT_PROCESSOR_CTRL 0x39 +#define EXT_EVENT_ID_RDD_REPORT 0x3A +#define EXT_EVENT_ID_DEVICE_CAPABILITY 0x3B +#define EXT_EVENT_ID_MAC_INFO 0x3C +#define EXT_EVENT_ID_ATE_TEST_MODE 0x3D +#define EXT_EVENT_ID_CAC_END 0x3E +#define EXT_EVENT_ID_MU_CTRL 0x40 + +#define EXT_EVENT_ID_DBDC_CTRL 0x45 +#define EXT_EVENT_ID_CONFIG_MUAR 0x48 + +#define EXT_EVENT_ID_RX_AIRTIME_CTRL 0x4a +#define EXT_EVENT_ID_AT_PROC_MODULE 0x4b +#define EXT_EVENT_ID_MAX_AMSDU_LENGTH_UPDATE 0x4c +#define EXT_EVENT_ID_EFUSE_FREE_BLOCK 0x4d +#define EXT_EVENT_ID_MURA_CTRL 0x4d +#define EXT_EVENT_ID_CSA_NOTIFY 0x4F +#define EXT_EVENT_ID_WIFI_SPECTRUM 0x50 +#define EXT_EVENT_ID_TMR_CALCU_INFO 0x51 +#define EXT_EVENT_ID_DUMP_MEM 0x57 +#define EXT_EVENT_ID_TX_POWER_FEATURE_CTRL 0x58 + +#define EXT_EVENT_ID_G_BAND_256QAM_PROBE_RESULT 0x6B +#define EXT_EVENT_ID_MPDU_TIME_UPDATE 0x6F + +/*#endif*/ + +#if (CFG_SUPPORT_TXPOWER_INFO == 1) +#define EXT_EVENT_ID_TX_POWER_FEATURE_CTRL 0x58 +#endif + +#define SCHED_SCAN_CHANNEL_TYPE_SPECIFIED (0) +#define SCHED_SCAN_CHANNEL_TYPE_DUAL_BAND (1) +#define SCHED_SCAN_CHANNEL_TYPE_2G4_ONLY (2) +#define SCHED_SCAN_CHANNEL_TYPE_5G_ONLY (3) + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +#ifndef LINUX +#endif +/* for Event Packet (via HIF-RX) */ +struct PSE_CMD_HDR { + /* DW0 */ + uint16_t u2TxByteCount; + uint16_t u2Reserved1: 10; + uint16_t u2Qidx: 5; + uint16_t u2Pidx: 1; + + /* DW1 */ + uint16_t u2Reserved2: 13; + uint16_t u2Hf: 2; + uint16_t u2Ft: 1; + uint16_t u2Reserved3: 8; + uint16_t u2PktFt: 2; + uint16_t u2Reserved4: 6; + + /* DW2~7 */ + uint32_t au4Reserved[6]; +}; + +struct WIFI_CMD { + uint16_t u2TxByteCount; /* Max value is over 2048 */ + uint16_t u2PQ_ID; /* Must be 0x8000 (Port1, Queue 0) */ +#if 1 + uint8_t ucWlanIdx; + uint8_t ucHeaderFormat; + uint8_t ucHeaderPadding; + uint8_t ucPktFt: 2; + uint8_t ucOwnMAC: 6; + uint32_t au4Reserved1[6]; + + uint16_t u2Length; + uint16_t u2PqId; +#endif + uint8_t ucCID; + uint8_t ucPktTypeID; /* Must be 0x20 (CMD Packet) */ + uint8_t ucSetQuery; + uint8_t ucSeqNum; +#if 1 + /* padding fields, hw may auto modify this field */ + uint8_t ucD2B0Rev; + uint8_t ucExtenCID; /* Extend CID */ + uint8_t ucS2DIndex; /* Index for Src to Dst in CMD usage */ + uint8_t ucExtCmdOption; /* Extend CID option */ + + uint8_t ucCmdVersion; + uint8_t ucReserved2[3]; + uint32_t au4Reserved3[4]; /* padding fields */ +#endif + uint8_t aucBuffer[0]; +}; + +/* for Command Packet (via HIF-TX) */ +/* following CM's documentation v0.7 */ +struct WIFI_EVENT { + uint16_t u2PacketLength; + uint16_t u2PacketType; /* Must be filled with 0xE000 (EVENT Packet) */ + uint8_t ucEID; + uint8_t ucSeqNum; + uint8_t ucEventVersion; + uint8_t aucReserved[1]; + + uint8_t ucExtenEID; + uint8_t aucReserved2[2]; + uint8_t ucS2DIndex; + + uint8_t aucBuffer[0]; +}; + +/* CMD_ID_TEST_CTRL */ +struct CMD_TEST_CTRL { + uint8_t ucAction; + uint8_t aucReserved[3]; + union { + uint32_t u4OpMode; + uint32_t u4ChannelFreq; + struct PARAM_MTK_WIFI_TEST_STRUCT rRfATInfo; + } u; +}; + +struct CMD_TEST_CTRL_EXT_T { + uint8_t ucAction; + uint8_t ucIcapLen; + uint8_t aucReserved[2]; + union { + uint32_t u4OpMode; + uint32_t u4ChannelFreq; + struct PARAM_MTK_WIFI_TEST_STRUCT_EXT_T rRfATInfo; + } u; +}; + +/* EVENT_TEST_STATUS */ +struct PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT { + uint32_t u4PktSentStatus; + uint32_t u4PktSentCount; + uint16_t u2AvgAlc; + uint8_t ucCckGainControl; + uint8_t ucOfdmGainControl; +}; + +struct PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT { + /*!< number of packets that Rx ok from interrupt */ + uint32_t u4IntRxOk; + /*!< number of packets that CRC error from interrupt */ + uint32_t u4IntCrcErr; + /*!< number of packets that is short preamble from interrupt */ + uint32_t u4IntShort; + /*!< number of packets that is long preamble from interrupt */ + uint32_t u4IntLong; + /*!< number of packets that Rx ok from PAU */ + uint32_t u4PauRxPktCount; + /*!< number of packets that CRC error from PAU */ + uint32_t u4PauCrcErrCount; + /*!< number of packets that is short preamble from PAU */ + uint32_t u4PauRxFifoFullCount; + uint32_t u4PauCCACount; /*!< CCA rising edge count */ +}; + +union EVENT_TEST_STATUS { + struct PARAM_MTK_WIFI_TEST_STRUCT rATInfo; + /* PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T rTxStatus; */ + /* PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T rRxStatus; */ +}; + +/* CMD_BUILD_CONNECTION */ +struct CMD_BUILD_CONNECTION { + uint8_t ucInfraMode; + uint8_t ucAuthMode; + uint8_t ucEncryptStatus; + uint8_t ucSsidLen; + uint8_t aucSsid[PARAM_MAX_LEN_SSID]; + uint8_t aucBssid[PARAM_MAC_ADDR_LEN]; + + /* Ad-hoc mode */ + uint16_t u2BeaconPeriod; + uint16_t u2ATIMWindow; + uint8_t ucJoinOnly; + uint8_t ucReserved; + uint32_t u4FreqInKHz; + + /* for faster connection */ + uint8_t aucScanResult[0]; +}; + +/* CMD_ADD_REMOVE_KEY */ +struct CMD_802_11_KEY { + uint8_t ucAddRemove; + uint8_t ucTxKey; + uint8_t ucKeyType; + uint8_t ucIsAuthenticator; + uint8_t aucPeerAddr[6]; + uint8_t ucBssIdx; + uint8_t ucAlgorithmId; + uint8_t ucKeyId; + uint8_t ucKeyLen; + uint8_t ucWlanIndex; + uint8_t ucMgmtProtection; + uint8_t aucKeyMaterial[32]; + uint8_t aucKeyRsc[16]; +}; + +/* CMD_ID_DEFAULT_KEY_ID */ +struct CMD_DEFAULT_KEY { + uint8_t ucBssIdx; + uint8_t ucKeyId; + uint8_t ucWlanIndex; + uint8_t ucMulticast; +}; + +/* WPA2 PMKID cache structure */ +struct PMKID_ENTRY { + struct PARAM_BSSID_INFO rBssidInfo; + u_int8_t fgPmkidExist; +}; + +struct CMD_802_11_PMKID { + uint32_t u4BSSIDInfoCount; + struct PMKID_ENTRY *arPMKIDInfo[1]; +}; + +struct CMD_GTK_REKEY_DATA { + uint8_t aucKek[16]; + uint8_t aucKck[16]; + uint8_t aucReplayCtr[8]; +}; + +struct CMD_CSUM_OFFLOAD { + uint16_t u2RxChecksum; /* bit0: IP, bit1: UDP, bit2: TCP */ + uint16_t u2TxChecksum; /* bit0: IP, bit1: UDP, bit2: TCP */ +}; + +/* CMD_BASIC_CONFIG */ +struct CMD_BASIC_CONFIG { + uint8_t ucNative80211; + uint8_t ucCtrlFlagAssertPath; + uint8_t ucCtrlFlagDebugLevel; + uint8_t aucReserved[1]; + struct CMD_CSUM_OFFLOAD rCsumOffload; + uint8_t ucCrlFlagSegememt; + uint8_t aucReserved2[3]; +}; + +/* CMD_MAC_MCAST_ADDR */ +struct CMD_MAC_MCAST_ADDR { + uint32_t u4NumOfGroupAddr; + uint8_t ucBssIndex; + uint8_t aucReserved[3]; + uint8_t arAddress[MAX_NUM_GROUP_ADDR][PARAM_MAC_ADDR_LEN]; +}; + +/* CMD_ACCESS_EEPROM */ +struct CMD_ACCESS_EEPROM { + uint16_t u2Offset; + uint16_t u2Data; +}; + +struct CMD_CUSTOM_NOA_PARAM_STRUCT { + uint32_t u4NoaDurationMs; + uint32_t u4NoaIntervalMs; + uint32_t u4NoaCount; + uint8_t ucBssIdx; + uint8_t aucReserved[3]; +}; + +struct CMD_CUSTOM_OPPPS_PARAM_STRUCT { + uint32_t u4CTwindowMs; + uint8_t ucBssIdx; + uint8_t aucReserved[3]; +}; + +struct CMD_CUSTOM_UAPSD_PARAM_STRUCT { + uint8_t fgEnAPSD; + uint8_t fgEnAPSD_AcBe; + uint8_t fgEnAPSD_AcBk; + uint8_t fgEnAPSD_AcVo; + uint8_t fgEnAPSD_AcVi; + uint8_t ucMaxSpLen; + uint8_t aucResv[2]; +}; + +struct CMD_SET_AP_CONSTRAINT_PWR_LIMIT { + /* DWORD_0 - Common Part */ + uint8_t ucCmdVer; + uint8_t aucPadding0[1]; + uint16_t u2CmdLen; /* Cmd size including common part and body */ + + /* DWORD_1 afterwards - Command Body */ + uint8_t ucBssIndex; + uint8_t ucPwrSetEnable; + int8_t cMaxTxPwr; /* In unit of 0.5 dBm (signed) */ + int8_t cMinTxPwr; /* In unit of 0.5 dBm (signed) */ + + uint8_t aucPadding1[32]; /* for new param in the future */ +}; + +struct CMD_SET_RRM_CAPABILITY { + /* DWORD_0 - Common Part */ + uint8_t ucCmdVer; + uint8_t aucPadding0[1]; + uint16_t u2CmdLen; /* Cmd size including common part and body */ + + /* DWORD_1 afterwards - Command Body */ + uint8_t ucBssIndex; + uint8_t ucRrmEnable; /* 802.11k rrm flag */ + /* Table 7-43e, RRM Enabled Capabilities Field */ + uint8_t ucCapabilities[5]; + uint8_t aucPadding1[1]; + + uint8_t aucPadding2[32]; /* for new param in the future */ +}; + +#if CFG_M0VE_BA_TO_DRIVER +struct CMD_RESET_BA_SCOREBOARD { + uint8_t ucflag; + uint8_t ucTID; + uint8_t aucMacAddr[PARAM_MAC_ADDR_LEN]; +}; +#endif + +/* EVENT_CONNECTION_STATUS */ +struct EVENT_CONNECTION_STATUS { + uint8_t ucMediaStatus; + uint8_t ucReasonOfDisconnect; + + uint8_t ucInfraMode; + uint8_t ucSsidLen; + uint8_t aucSsid[PARAM_MAX_LEN_SSID]; + uint8_t aucBssid[PARAM_MAC_ADDR_LEN]; + uint8_t ucAuthenMode; + uint8_t ucEncryptStatus; + uint16_t u2BeaconPeriod; + uint16_t u2AID; + uint16_t u2ATIMWindow; + uint8_t ucNetworkType; + uint8_t aucReserved[1]; + uint32_t u4FreqInKHz; + +#if CFG_ENABLE_WIFI_DIRECT + uint8_t aucInterfaceAddr[PARAM_MAC_ADDR_LEN]; +#endif + +}; + +/* EVENT_NIC_CAPABILITY */ +#define FEATURE_FLAG0_NIC_CAPABILITY_V2 BIT(0) + +struct EVENT_NIC_CAPABILITY { + uint16_t u2ProductID; + uint16_t u2FwVersion; + uint16_t u2DriverVersion; + uint8_t ucHw5GBandDisabled; + uint8_t ucEepromUsed; + uint8_t aucMacAddr[6]; + uint8_t ucEndianOfMacAddrNumber; + uint8_t ucHwNotSupportAC; + + uint8_t ucRfVersion; + uint8_t ucPhyVersion; + uint8_t ucRfCalFail; + uint8_t ucBbCalFail; + uint8_t aucDateCode[16]; + uint32_t u4FeatureFlag0; + uint32_t u4FeatureFlag1; + uint32_t u4CompileFlag0; + uint32_t u4CompileFlag1; + uint8_t aucBranchInfo[4]; + uint8_t ucFwBuildNumber; + uint8_t ucHwSetNss1x1; + uint8_t ucHwNotSupportDBDC; + uint8_t ucHwBssIdNum; + uint8_t aucReserved1[56]; +}; + +struct EVENT_NIC_CAPABILITY_V2 { + uint16_t u2TotalElementNum; + uint8_t aucReserved[2]; + uint8_t aucBuffer[0]; +}; + +struct NIC_CAPABILITY_V2_ELEMENT { + uint32_t tag_type; /* NIC_CAPABILITY_V2_TAG_T */ + uint32_t body_len; + uint8_t aucbody[0]; +}; + +typedef uint32_t(*NIC_CAP_V2_ELEMENT_HDLR)( + struct ADAPTER *prAdapter, uint8_t *buff); +struct NIC_CAPABILITY_V2_REF_TABLE { + uint32_t tag_type; /* NIC_CAPABILITY_V2_TAG_T */ + NIC_CAP_V2_ELEMENT_HDLR hdlr; +}; + +enum NIC_CAPABILITY_V2_TAG { + TAG_CAP_TX_RESOURCE = 0x0, + TAG_CAP_TX_EFUSEADDRESS = 0x1, + TAG_CAP_COEX_FEATURE = 0x2, + TAG_CAP_SINGLE_SKU = 0x3, + TAG_CAP_CSUM_OFFLOAD = 0x4, + TAG_CAP_HW_VERSION = 0x5, + TAG_CAP_SW_VERSION = 0x6, + TAG_CAP_MAC_ADDR = 0x7, + TAG_CAP_PHY_CAP = 0x8, + TAG_CAP_MAC_CAP = 0x9, + TAG_CAP_FRAME_BUF_CAP = 0xa, + TAG_CAP_BEAMFORM_CAP = 0xb, + TAG_CAP_LOCATION_CAP = 0xc, + TAG_CAP_MUMIMO_CAP = 0xd, + TAG_CAP_BUFFER_MODE_INFO = 0xe, + TAG_CAP_TOTAL +}; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +struct NIC_CSUM_OFFLOAD { + uint8_t ucIsSupportCsumOffload; /* 1: Support, 0: Not Support */ + uint8_t aucReseved[3]; +}; +#endif + +struct NIC_COEX_FEATURE { + uint32_t u4FddMode; /* TRUE for COEX FDD mode */ +}; + +struct NIC_EFUSE_ADDRESS { + uint32_t u4EfuseStartAddress; /* Efuse Start Address */ + uint32_t u4EfuseEndAddress; /* Efuse End Address */ +}; + +struct CAP_HW_VERSION { + uint16_t u2ProductID; /* CHIP ID */ + uint8_t ucEcoVersion; /* ECO version */ + uint8_t ucReserved; + uint32_t u4MacIpID; /* MAC IP version */ + uint32_t u4BBIpID; /* Baseband IP version */ + uint32_t u4TopIpID; /* TOP IP version */ + uint32_t u4ConfigId; /* Configuration ID */ +}; + +struct CAP_SW_VERSION { + uint16_t u2FwVersion; /* FW version */ + uint16_t u2FwBuildNumber; /* FW build number */ + uint8_t aucBranchInfo[4]; /* Branch name in ASCII */ + uint8_t aucDateCode[16]; /* FW build data code */ +}; + +struct CAP_MAC_ADDR { + uint8_t aucMacAddr[6]; + uint8_t aucReserved[2]; +}; + +struct CAP_PHY_CAP { + uint8_t ucHt; /* 1:support, 0:not*/ + uint8_t ucVht; /* 1:support, 0:not*/ + uint8_t uc5gBand; /* 1:support, 0:not*/ + /* 0: BW20, 1:BW40, 2:BW80, 3:BW160, 4:BW80+80 */ + uint8_t ucMaxBandwidth; + uint8_t ucNss; /* 1:1x1, 2:2x2, ... */ + uint8_t ucDbdc; /* 1:support, 0:not*/ + uint8_t ucTxLdpc; /* 1:support, 0:not*/ + uint8_t ucRxLdpc; /* 1:support, 0:not*/ + uint8_t ucTxStbc; /* 1:support, 0:not*/ + uint8_t ucRxStbc; /* 1:support, 0:not*/ + /* BIT(0): 2G4_WF0, BIT(1): 5G_WF0, BIT(2): 2G4_WF1, BIT(3): 5G_WF1 */ + uint8_t ucHwWifiPath; + uint8_t aucReserved[1]; +}; + +struct CAP_MAC_CAP { + uint8_t ucHwBssIdNum; /* HW BSSID number */ + uint8_t ucWmmSet; /* 1: AC0~3, 2: AC0~3 and AC10~13, ... */ + uint8_t ucWtblEntryNum; /* WTBL entry number */ + uint8_t ucReserved; +}; + +struct CAP_FRAME_BUF_CAP { + /* 1: support in-chip Tx AMSDU (HW or CR4) */ + uint8_t ucChipTxAmsdu; + /* 2: support 2 MSDU in AMSDU, 3:support 3 MSDU in AMSDU,...*/ + uint8_t ucTxAmsduNum; + /* Rx AMSDU size, 0:4K, 1:8K,2:12K */ + uint8_t ucRxAmsduSize; + uint8_t ucReserved; + /* Txd entry number */ + uint32_t u4TxdCount; + /* Txd and packet buffer in KB (cut through sysram size) */ + uint32_t u4PacketBufSize; +}; + +struct CAP_BEAMFORM_CAP { + uint8_t ucBFer; /* Tx beamformer, 1:support, 0:not*/ + uint8_t ucIBFer; /* Tx implicit beamformer 1:support, 0:not*/ + uint8_t ucBFee; /* Rx beamformee, 1:support, 0:not */ + uint8_t ucReserved; + uint32_t u4BFerCap; /* Tx beamformere cap */ + uint32_t u4BFeeCap; /* Rx beamformee cap */ +}; + +struct CAP_LOCATION_CAP { + uint8_t ucTOAE; /* 1:support, 0:not */ + uint8_t aucReserved[3]; +}; + +struct CAP_MUMIMO_CAP { + uint8_t ucMuMimoRx; /* 1:support, 0:not */ + uint8_t ucMuMimoTx; /* 1:support, 0:not */ + uint8_t aucReserved[2]; +}; + +#define EFUSE_SECTION_TABLE_SIZE (10) /* It should not be changed. */ + +struct EFUSE_SECTION_T { + uint16_t u2StartOffset; + uint16_t u2Length; +}; + +struct CAP_BUFFER_MODE_INFO_T { + uint8_t ucVersion; /* Version */ + uint8_t ucFormatSupportBitmap; /* Format Support Bitmap*/ + uint16_t u2EfuseTotalSize; /* Total eFUSE Size */ + struct EFUSE_SECTION_T arSections[EFUSE_SECTION_TABLE_SIZE]; + /* NOTE: EFUSE_SECTION_TABLE_SIZE should be fixed to + * 10 so that driver don't change. + */ +}; + +/* + * NIC_TX_RESOURCE_REPORT_EVENT related definition + */ + +#define NIC_TX_RESOURCE_REPORT_VERSION_PREFIX (0x80000000) +#define NIC_TX_RESOURCE_REPORT_VERSION_1 \ + (NIC_TX_RESOURCE_REPORT_VERSION_PREFIX | 0x1) + +struct nicTxRsrcEvtHdlr { + uint32_t u4Version; + + uint32_t(*nicEventTxResource) + (IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf); + void (*nicTxResourceInit)(IN struct ADAPTER *prAdapter); +}; + +struct NIC_TX_RESOURCE { + /* the total usable resource for MCU port */ + uint32_t u4CmdTotalResource; + /* the unit of a MCU resource */ + uint32_t u4CmdResourceUnit; + /* the total usable resource for LMAC port */ + uint32_t u4DataTotalResource; + /* the unit of a LMAC resource */ + uint32_t u4DataResourceUnit; +}; + +struct tx_resource_report_v1 { + /* + * u4Version: NIC_TX_RESOURCE_REPORT_VERSION_1 + */ + uint32_t u4Version; + + /* + * the followings are content for u4Verion = 0x80000001 + */ + uint32_t u4HifDataPsePageQuota; + uint32_t u4HifCmdPsePageQuota; + uint32_t u4HifDataPlePageQuota; + uint32_t u4HifCmdPlePageQuota; + + /* + * u4PlePsePageSize: the unit of a page in PLE and PSE + * [31:16] PLE page size + * [15:0] PLE page size + */ + uint32_t u4PlePsePageSize; + + /* + * ucPpTxAddCnt: the extra pse resource needed by HW + */ + uint8_t ucPpTxAddCnt; + + uint8_t ucReserved[3]; +}; + + +/* modified version of WLAN_BEACON_FRAME_BODY_T for simplier buffering */ +struct WLAN_BEACON_FRAME_BODY_T_LOCAL { + /* Beacon frame body */ + uint32_t au4Timestamp[2]; /* Timestamp */ + uint16_t u2BeaconInterval; /* Beacon Interval */ + uint16_t u2CapInfo; /* Capability */ + /* Various IEs, start from SSID */ + uint8_t aucInfoElem[MAX_IE_LENGTH]; + /* This field is *NOT* carried by F/W but caculated by nic_rx */ + uint16_t u2IELength; +}; + +/* EVENT_SCAN_RESULT */ +struct EVENT_SCAN_RESULT { + int32_t i4RSSI; + uint32_t u4LinkQuality; + uint32_t u4DSConfig; /* Center frequency */ + uint32_t u4DomainInfo; /* Require CM opinion */ + uint32_t u4Reserved; + uint8_t ucNetworkType; + uint8_t ucOpMode; + uint8_t aucBssid[MAC_ADDR_LEN]; + uint8_t aucRatesEx[PARAM_MAX_LEN_RATES_EX]; + struct WLAN_BEACON_FRAME_BODY_T_LOCAL rBeaconFrameBody; +}; + +/* event of tkip mic error */ +struct EVENT_MIC_ERR_INFO { + uint32_t u4Flags; +}; + +/* event of add key done for port control */ +struct EVENT_ADD_KEY_DONE_INFO { + uint8_t ucBSSIndex; + uint8_t ucReserved; + uint8_t aucStaAddr[6]; +}; + +struct EVENT_PMKID_CANDIDATE_LIST { + uint32_t u4Version; /*!< Version */ + uint32_t u4NumCandidates; /*!< How many candidates follow */ + struct PARAM_PMKID_CANDIDATE arCandidateList[1]; +}; + +struct EVENT_CMD_RESULT { + uint8_t ucCmdID; + uint8_t ucStatus; + uint8_t aucReserved[2]; +}; + +/* CMD_ID_ACCESS_REG & EVENT_ID_ACCESS_REG */ +struct CMD_ACCESS_REG { + uint32_t u4Address; + uint32_t u4Data; +}; + +#define COEX_CTRL_BUF_LEN 460 +/* CMD_COEX_HANDLER & EVENT_COEX_HANDLER */ +/************************************************/ +/* UINT_32 u4SubCmd : Coex Ctrl Sub Command */ +/* UINT_8 aucBuffer : Reserve for Sub Command */ +/* Data Structure */ +/************************************************/ +struct CMD_COEX_HANDLER { + uint32_t u4SubCmd; + uint8_t aucBuffer[COEX_CTRL_BUF_LEN]; +}; + + +/* Sub Command Data Structure */ +/************************************************/ +/* UINT_32 u4IsoPath : WF Path (WF0/WF1) */ +/* UINT_32 u4Channel : WF Channel */ +/* UINT_32 u4Band : WF Band (Band0/Band1)(Not used now) */ +/* UINT_32 u4Isolation : Isolation value */ +/************************************************/ +struct CMD_COEX_ISO_DETECT { + uint32_t u4IsoPath; + uint32_t u4Channel; + uint32_t u4Isolation; +}; + +/************************************************/ +/* PCHAR pucCoexInfo : CoexInfoTag */ +/************************************************/ +struct CMD_COEX_GET_INFO { + uint8_t ucCoexInfo[COEX_CTRL_BUF_LEN]; +}; + +/* Coex Command Used */ +enum ENUM_COEX_CMD_CTRL { + /* Set */ + COEX_CMD_SET_DISABLE_DATA_RSSI_UPDATE = 0x00, + COEX_CMD_SET_DATA_RSSI = 0x01, + /* Get */ + COEX_CMD_GET_ISO_DETECT = 0x80, + COEX_CMD_GET_INFO = 0x81, + COEX_CMD_NUM +}; + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +/* CMD_ID_CAL_BACKUP_IN_HOST_V2 & EVENT_ID_CAL_BACKUP_IN_HOST_V2 */ +struct CMD_CAL_BACKUP_STRUCT_V2 { + uint8_t ucReason; + uint8_t ucAction; + uint8_t ucNeedResp; + uint8_t ucFragNum; + uint8_t ucRomRam; + uint32_t u4ThermalValue; + uint32_t u4Address; + uint32_t u4Length; + uint32_t u4RemainLength; + uint32_t au4Buffer[PARAM_CAL_DATA_DUMP_MAX_NUM]; +}; + +struct CMD_CAL_BACKUP_STRUCT { + uint8_t ucReason; + uint8_t ucAction; + uint8_t ucNeedResp; + uint8_t ucFragNum; + uint8_t ucRomRam; + uint32_t u4ThermalValue; + uint32_t u4Address; + uint32_t u4Length; + uint32_t u4RemainLength; +}; +#endif + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +struct CMD_ACCESS_CHN_LOAD { + uint32_t u4Address; + uint32_t u4Data; + uint16_t u2Channel; + uint8_t aucReserved[2]; +}; + +struct CMD_GET_LTE_SAFE_CHN { + uint8_t ucIndex; + uint8_t ucFlags; + uint8_t aucReserved0[2]; + uint8_t aucReserved2[16]; +}; +#endif + +/* CMD_DUMP_MEMORY */ +struct CMD_DUMP_MEM { + uint32_t u4Address; + uint32_t u4Length; + uint32_t u4RemainLength; +#if CFG_SUPPORT_QA_TOOL + uint32_t u4IcapContent; +#endif /* CFG_SUPPORT_QA_TOOL */ + uint8_t ucFragNum; +}; + +struct EVENT_DUMP_MEM { + uint32_t u4Address; + uint32_t u4Length; + uint32_t u4RemainLength; +#if CFG_SUPPORT_QA_TOOL + uint32_t eIcapContent; +#endif /* CFG_SUPPORT_QA_TOOL */ + uint8_t ucFragNum; + uint8_t aucBuffer[1]; +}; + +#if CFG_SUPPORT_QA_TOOL +struct CMD_ACCESS_RX_STAT { + uint32_t u4SeqNum; + uint32_t u4TotalNum; +}; + +struct EVENT_ACCESS_RX_STAT { + uint32_t u4SeqNum; + uint32_t u4TotalNum; + uint32_t au4Buffer[1]; +}; + +#if CFG_SUPPORT_TX_BF +union CMD_TXBF_ACTION { + struct PROFILE_TAG_READ rProfileTagRead; + struct PROFILE_TAG_WRITE rProfileTagWrite; + struct PROFILE_DATA_READ rProfileDataRead; + struct PROFILE_DATA_WRITE rProfileDataWrite; + struct PROFILE_PN_READ rProfilePnRead; + struct PROFILE_PN_WRITE rProfilePnWrite; + struct TX_BF_SOUNDING_START rTxBfSoundingStart; + struct TX_BF_SOUNDING_STOP rTxBfSoundingStop; + struct TX_BF_TX_APPLY rTxBfTxApply; + struct TX_BF_PFMU_MEM_ALLOC rTxBfPfmuMemAlloc; + struct TX_BF_PFMU_MEM_RLS rTxBfPfmuMemRls; +#if CFG_SUPPORT_TX_BF_FPGA + struct TX_BF_PROFILE_SW_TAG_WRITE rTxBfProfileSwTagWrite; +#endif +}; + +#define CMD_DEVINFO_UPDATE_HDR_SIZE 8 +struct CMD_DEV_INFO_UPDATE { + uint8_t ucOwnMacIdx; + uint8_t ucReserve; + uint16_t u2TotalElementNum; + uint8_t ucAppendCmdTLV; + uint8_t aucReserve[3]; + uint8_t aucBuffer[0]; + /* CMD_DEVINFO_ACTIVE_T rCmdDevInfoActive; */ +}; + +#define CMD_BSSINFO_UPDATE_HDR_SIZE 8 +struct CMD_BSS_INFO_UPDATE { + uint8_t ucBssIndex; + uint8_t ucReserve; + uint16_t u2TotalElementNum; + uint32_t u4Reserve; + /* CMD_BSSINFO_BASIC_T rCmdBssInfoBasic; */ + uint8_t aucBuffer[0]; +}; + +/* STA record command */ +#define CMD_STAREC_UPDATE_HDR_SIZE 8 +struct CMD_STAREC_UPDATE { + uint8_t ucBssIndex; + uint8_t ucWlanIdx; + uint16_t u2TotalElementNum; + uint32_t u4Reserve; + uint8_t aucBuffer[0]; +}; + +struct EXT_EVENT_BF_STATUS_T { + uint8_t ucEventCategoryID; + uint8_t ucBw; + uint16_t u2SubCarrIdx; + u_int8_t fgBFer; + uint8_t aucReserved[3]; + uint8_t aucBuf[1000]; /* temp size */ +}; + +struct EVENT_PFMU_TAG_READ { + union PFMU_PROFILE_TAG1 ru4TxBfPFMUTag1; + union PFMU_PROFILE_TAG2 ru4TxBfPFMUTag2; +}; + +#if CFG_SUPPORT_MU_MIMO +struct EVENT_HQA_GET_QD { + uint32_t u4EventId; + uint32_t au4RawData[14]; +}; + +struct EVENT_HQA_GET_MU_CALC_LQ { + uint32_t u4EventId; + struct MU_STRUCT_LQ_REPORT rEntry; +}; + +struct EVENT_SHOW_GROUP_TBL_ENTRY { + uint32_t u4EventId; + uint8_t index; + uint8_t numUser: 2; + uint8_t BW: 2; + uint8_t NS0: 2; + uint8_t NS1: 2; + /* UINT_8 NS2:1; */ + /* UINT_8 NS3:1; */ + uint8_t PFIDUser0; + uint8_t PFIDUser1; + /* UINT_8 PFIDUser2; */ + /* UINT_8 PFIDUser3; */ + u_int8_t fgIsShortGI; + u_int8_t fgIsUsed; + u_int8_t fgIsDisable; + uint8_t initMcsUser0: 4; + uint8_t initMcsUser1: 4; + /* UINT_8 initMcsUser2:4; */ + /* UINT_8 initMcsUser3:4; */ + uint8_t dMcsUser0: 4; + uint8_t dMcsUser1: 4; + /* UINT_8 dMcsUser2:4; */ + /* UINT_8 dMcsUser3:4; */ +}; + +union CMD_MUMIMO_ACTION { + uint8_t ucMuMimoCategory; + uint8_t aucRsv[3]; + union { + struct MU_GET_CALC_INIT_MCS rMuGetCalcInitMcs; + struct MU_SET_INIT_MCS rMuSetInitMcs; + struct MU_SET_CALC_LQ rMuSetCalcLq; + struct MU_GET_LQ rMuGetLq; + struct MU_SET_SNR_OFFSET rMuSetSnrOffset; + struct MU_SET_ZERO_NSS rMuSetZeroNss; + struct MU_SPEED_UP_LQ rMuSpeedUpLq; + struct MU_SET_MU_TABLE rMuSetMuTable; + struct MU_SET_GROUP rMuSetGroup; + struct MU_GET_QD rMuGetQd; + struct MU_SET_ENABLE rMuSetEnable; + struct MU_SET_GID_UP rMuSetGidUp; + struct MU_TRIGGER_MU_TX rMuTriggerMuTx; + } unMuMimoParam; +}; +#endif /* CFG_SUPPORT_MU_MIMO */ +#endif /* CFG_SUPPORT_TX_BF */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +struct CMD_SW_DBG_CTRL { + uint32_t u4Id; + uint32_t u4Data; + /* Debug Support */ + uint32_t u4DebugCnt[64]; +}; + + +#if CFG_SUPPORT_ANT_DIV +enum { + ANT_DIV_DISABLE = 0, + ANT_DIV_ANT_1, + ANT_DIV_ANT_2, + ANT_DIV_SUCCESS, + ANT_DIV_WF_SCNING, + ANT_DIV_BT_SCNING, + ANT_DIV_DISCONNECT, + ANT_DIV_INVALID_RSSI, + ANT_DIV_MSG_TIMEOUT, + ANT_DIV_SWH_FAIL, + ANT_DIV_PARA_ERR, + ANT_DIV_OTHER_FAIL, + ANT_DIV_STATE_NUM +}; +enum { + ANT_DIV_CMD_SET_ANT = 0, + ANT_DIV_CMD_GET_ANT, + ANT_DIV_CMD_DETC, + ANT_DIV_CMD_SWH, +}; +struct CMD_ANT_DIV_CTRL { + uint8_t ucAction; + uint8_t ucAntId; + uint8_t ucState; + uint8_t ucRcpi; + uint8_t ucReserve[8]; +}; +#endif + +struct CMD_FW_LOG_2_HOST_CTRL { + uint8_t ucFwLog2HostCtrl; + uint8_t ucMcuDest; + uint8_t ucReserve[2]; +}; + +struct CMD_CHIP_CONFIG { + uint16_t u2Id; + uint8_t ucType; + uint8_t ucRespType; + uint16_t u2MsgSize; + uint8_t aucReserved0[2]; + uint8_t aucCmd[CHIP_CONFIG_RESP_SIZE]; +}; + +/* CMD_ID_LINK_ATTRIB */ +struct CMD_LINK_ATTRIB { + int8_t cRssiTrigger; + uint8_t ucDesiredRateLen; + uint16_t u2DesiredRate[32]; + uint8_t ucMediaStreamMode; + uint8_t aucReserved[1]; +}; + +/* CMD_ID_NIC_POWER_CTRL */ +struct CMD_NIC_POWER_CTRL { + uint8_t ucPowerMode; + uint8_t aucReserved[3]; +}; + +/* CMD_ID_POWER_SAVE_MODE */ +struct CMD_PS_PROFILE { + uint8_t ucBssIndex; + uint8_t ucPsProfile; + uint8_t aucReserved[2]; +}; + +/* EVENT_LINK_QUALITY */ +#if 1 +struct LINK_QUALITY_ { + int8_t cRssi; /* AIS Network. */ + int8_t cLinkQuality; + uint16_t u2LinkSpeed; /* TX rate1 */ + uint8_t ucMediumBusyPercentage; /* Read clear */ + uint8_t ucIsLQ0Rdy; /* Link Quality BSS0 Ready. */ +}; + +struct EVENT_LINK_QUALITY_V2 { + struct LINK_QUALITY_ rLq[BSSID_NUM]; +}; + +struct EVENT_LINK_QUALITY { + int8_t cRssi; + int8_t cLinkQuality; + uint16_t u2LinkSpeed; + uint8_t ucMediumBusyPercentage; +}; +#endif + +#if CFG_SUPPORT_P2P_RSSI_QUERY +/* EVENT_LINK_QUALITY */ +struct EVENT_LINK_QUALITY_EX { + int8_t cRssi; + int8_t cLinkQuality; + uint16_t u2LinkSpeed; + uint8_t ucMediumBusyPercentage; + uint8_t ucIsLQ0Rdy; + int8_t cRssiP2P; /* For P2P Network. */ + int8_t cLinkQualityP2P; + uint16_t u2LinkSpeedP2P; + uint8_t ucMediumBusyPercentageP2P; + uint8_t ucIsLQ1Rdy; +}; +#endif + +/* EVENT_ID_STATISTICS */ +struct EVENT_STATISTICS { + union LARGE_INTEGER rTransmittedFragmentCount; + union LARGE_INTEGER rMulticastTransmittedFrameCount; + union LARGE_INTEGER rFailedCount; + union LARGE_INTEGER rRetryCount; + union LARGE_INTEGER rMultipleRetryCount; + union LARGE_INTEGER rRTSSuccessCount; + union LARGE_INTEGER rRTSFailureCount; + union LARGE_INTEGER rACKFailureCount; + union LARGE_INTEGER rFrameDuplicateCount; + union LARGE_INTEGER rReceivedFragmentCount; + union LARGE_INTEGER rMulticastReceivedFrameCount; + union LARGE_INTEGER rFCSErrorCount; +}; + +struct _EVENT_BUG_REPORT_T { + /* BugReportVersion 1 */ + uint32_t u4BugReportVersion; + + /* FW Module State 2 */ + uint32_t u4FWState; + + /* Scan Counter 3-6 */ + uint32_t u4ReceivedBeaconCount; + uint32_t u4ReceivedProbeResponseCount; + uint32_t u4SentProbeRequestCount; + uint32_t u4SentProbeRequestFailCount; + + /* Roaming Counter 7-9 */ + uint32_t u4RoamingDebugFlag; + uint32_t u4RoamingThreshold; + uint32_t u4RoamingCurrentRcpi; + + /* RF Counter 10-14 */ + uint32_t u4RFPriChannel; + uint32_t u4RFChannelS1; + uint32_t u4RFChannelS2; + uint32_t u4RFChannelWidth; + uint32_t u4RFSco; + + /* Coex Counter 15-17 */ + uint32_t u4BTProfile; + uint32_t u4BTOn; + uint32_t u4LTEOn; + + /* Low Power Counter 18-20 */ + uint32_t u4LPTxUcPktNum; + uint32_t u4LPRxUcPktNum; + uint32_t u4LPPSProfile; + + /* Base Band Counter 21- 32 */ + uint32_t u4OfdmPdCnt; + uint32_t u4CckPdCnt; + uint32_t u4CckSigErrorCnt; + uint32_t u4CckSfdErrorCnt; + uint32_t u4OfdmSigErrorCnt; + uint32_t u4OfdmTaqErrorCnt; + uint32_t u4OfdmFcsErrorCnt; + uint32_t u4CckFcsErrorCnt; + uint32_t u4OfdmMdrdyCnt; + uint32_t u4CckMdrdyCnt; + uint32_t u4PhyCcaStatus; + uint32_t u4WifiFastSpiStatus; + + /* Mac RX Counter 33-45 */ + uint32_t u4RxMdrdyCount; + uint32_t u4RxFcsErrorCount; + uint32_t u4RxbFifoFullCount; + uint32_t u4RxMpduCount; + uint32_t u4RxLengthMismatchCount; + uint32_t u4RxCcaPrimCount; + uint32_t u4RxEdCount; + uint32_t u4LmacFreeRunTimer; + uint32_t u4WtblReadPointer; + uint32_t u4RmacWritePointer; + uint32_t u4SecWritePointer; + uint32_t u4SecReadPointer; + uint32_t u4DmaReadPointer; + + /* Mac TX Counter 46-47 */ + uint32_t u4TxChannelIdleCount; + uint32_t u4TxCcaNavTxTime; + /* If you want to add item, + * please modify BUG_REPORT_NUM in mtk_driver_nl80211.h + */ +}; + +/* EVENT_ID_FW_SLEEPY_NOTIFY */ +struct EVENT_SLEEPY_INFO { + uint8_t ucSleepyState; + uint8_t aucReserved[3]; +}; + +struct EVENT_ACTIVATE_STA_REC { + uint8_t aucMacAddr[6]; + uint8_t ucStaRecIdx; + uint8_t ucBssIndex; +}; + +struct EVENT_DEACTIVATE_STA_REC { + uint8_t ucStaRecIdx; + uint8_t aucReserved[3]; +}; + +/* CMD_BT_OVER_WIFI */ +struct CMD_BT_OVER_WIFI { + uint8_t ucAction; /* 0: query, 1: setup, 2: destroy */ + uint8_t ucChannelNum; + uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN]; + uint16_t u2BeaconInterval; + uint8_t ucTimeoutDiscovery; + uint8_t ucTimeoutInactivity; + uint8_t ucRole; + uint8_t PAL_Capabilities; + uint8_t cMaxTxPower; + uint8_t ucChannelBand; + uint8_t ucReserved[1]; +}; + +#if (CFG_SUPPORT_DFS_MASTER == 1) +enum ENUM_REG_DOMAIN { + REG_DEFAULT = 0, + REG_JP_53, + REG_JP_56 +}; + +struct CMD_RDD_ON_OFF_CTRL { + uint8_t ucDfsCtrl; + uint8_t ucRddIdx; + uint8_t ucRddRxSel; + uint8_t ucSetVal; + uint8_t aucReserve[4]; +}; +#endif + +/* EVENT_BT_OVER_WIFI */ +struct EVENT_BT_OVER_WIFI { + uint8_t ucLinkStatus; + uint8_t ucSelectedChannel; + int8_t cRSSI; + uint8_t ucReserved[1]; +}; + +/* Same with DOMAIN_SUBBAND_INFO */ +struct CMD_SUBBAND_INFO { + uint8_t ucRegClass; + uint8_t ucBand; + uint8_t ucChannelSpan; + uint8_t ucFirstChannelNum; + uint8_t ucNumChannels; + uint8_t aucReserved[3]; +}; + +/* CMD_SET_DOMAIN_INFO */ +#if (CFG_SUPPORT_SINGLE_SKU == 1) +struct CMD_SET_DOMAIN_INFO_V2 { + uint32_t u4CountryCode; + + uint8_t uc2G4Bandwidth; /* CONFIG_BW_20_40M or CONFIG_BW_20M */ + uint8_t uc5GBandwidth; /* CONFIG_BW_20_40M or CONFIG_BW_20M */ + uint8_t aucReserved[2]; + struct acctive_channel_list active_chs; +}; +#endif + +struct CMD_SET_DOMAIN_INFO { + uint16_t u2CountryCode; + uint16_t u2IsSetPassiveScan; + struct CMD_SUBBAND_INFO rSubBand[6]; + + uint8_t uc2G4Bandwidth; /* CONFIG_BW_20_40M or CONFIG_BW_20M */ + uint8_t uc5GBandwidth; /* CONFIG_BW_20_40M or CONFIG_BW_20M */ + uint8_t aucReserved[2]; +}; + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +/* CMD_SET_PWR_LIMIT_TABLE */ +struct CMD_CHANNEL_POWER_LIMIT { + uint8_t ucCentralCh; + + int8_t cPwrLimitCCK; + int8_t cPwrLimit20L; /* MCS0~4 */ + int8_t cPwrLimit20H; /* MCS5~8 */ + int8_t cPwrLimit40L; /* MCS0~4 */ + int8_t cPwrLimit40H; /* MCS5~9 */ + int8_t cPwrLimit80L; /* MCS0~4 */ + int8_t cPwrLimit80H; /* MCS5~9 */ + int8_t cPwrLimit160L; /* MCS0~4 */ + int8_t cPwrLimit160H; /* MCS5~9 */ + + uint8_t ucFlag; /*Not used in driver*/ + uint8_t aucReserved[1]; +}; + +struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT { + uint16_t u2CountryCode; + uint8_t ucCountryFlag; /*Not used in driver*/ + uint8_t ucNum; /*Numbers of channel to set power limit*/ + uint8_t ucTempVersion; /*Temp use for 160nc power limit implementation*/ + uint8_t aucReserved[3]; + struct CMD_CHANNEL_POWER_LIMIT + rChannelPowerLimit[1]; /*Channel power limit entries to be set*/ +}; + +#if (CFG_SUPPORT_SINGLE_SKU == 1) +struct CMD_CHANNEL_POWER_LIMIT_V2 { + uint8_t ucCentralCh; + uint8_t ucReserved[3]; + + uint8_t tx_pwr_dsss_cck; + uint8_t tx_pwr_dsss_bpsk; + + uint8_t tx_pwr_ofdm_bpsk; /* 6M, 9M */ + uint8_t tx_pwr_ofdm_qpsk; /* 12M, 18M */ + uint8_t tx_pwr_ofdm_16qam; /* 24M, 36M */ + uint8_t tx_pwr_ofdm_48m; + uint8_t tx_pwr_ofdm_54m; + + uint8_t tx_pwr_ht20_bpsk; /* MCS0*/ + uint8_t tx_pwr_ht20_qpsk; /* MCS1, MCS2*/ + uint8_t tx_pwr_ht20_16qam; /* MCS3, MCS4*/ + uint8_t tx_pwr_ht20_mcs5; /* MCS5*/ + uint8_t tx_pwr_ht20_mcs6; /* MCS6*/ + uint8_t tx_pwr_ht20_mcs7; /* MCS7*/ + + uint8_t tx_pwr_ht40_bpsk; /* MCS0*/ + uint8_t tx_pwr_ht40_qpsk; /* MCS1, MCS2*/ + uint8_t tx_pwr_ht40_16qam; /* MCS3, MCS4*/ + uint8_t tx_pwr_ht40_mcs5; /* MCS5*/ + uint8_t tx_pwr_ht40_mcs6; /* MCS6*/ + uint8_t tx_pwr_ht40_mcs7; /* MCS7*/ + uint8_t tx_pwr_ht40_mcs32; /* MCS32*/ + + uint8_t tx_pwr_vht20_bpsk; /* MCS0*/ + uint8_t tx_pwr_vht20_qpsk; /* MCS1, MCS2*/ + uint8_t tx_pwr_vht20_16qam; /* MCS3, MCS4*/ + uint8_t tx_pwr_vht20_64qam; /* MCS5, MCS6*/ + uint8_t tx_pwr_vht20_mcs7; + uint8_t tx_pwr_vht20_mcs8; + uint8_t tx_pwr_vht20_mcs9; + + uint8_t tx_pwr_vht_40; + uint8_t tx_pwr_vht_80; + uint8_t tx_pwr_vht_160c; + uint8_t tx_pwr_vht_160nc; + uint8_t tx_pwr_lg_40; + uint8_t tx_pwr_lg_80; + + uint8_t tx_pwr_1ss_delta; + uint8_t ucReserved_1[2]; +}; + +struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2 { + uint8_t ucNum; + uint8_t eband; /*ENUM_BAND_T*/ + uint8_t usReserved[2]; + uint32_t countryCode; + struct CMD_CHANNEL_POWER_LIMIT_V2 rChannelPowerLimit[0]; +}; + +#define BF_TX_PWR_LIMIT_SECTION_NUM 17 +#define BF_TX_PWR_LIMIT_ELEMENT_NUM 10 +#define TX_PWR_LIMIT_SECTION_NUM 9 +#define TX_PWR_LIMIT_ELEMENT_NUM 10 +#define TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN 4 +#define TX_PWR_LIMIT_MAX_VAL 63 + +#define POWER_LIMIT_SKU_CCK_NUM 4 +#define POWER_LIMIT_SKU_OFDM_NUM 8 +#define POWER_LIMIT_SKU_HT20_NUM 8 +#define POWER_LIMIT_SKU_HT40_NUM 9 +#define POWER_LIMIT_SKU_VHT20_NUM 10 +#define POWER_LIMIT_SKU_VHT40_NUM 10 +#define POWER_LIMIT_SKU_VHT80_NUM 10 +#define POWER_LIMIT_SKU_VHT160_NUM 10 +#define SINGLE_SKU_PARAM_NUM \ + (POWER_LIMIT_SKU_CCK_NUM + \ + POWER_LIMIT_SKU_OFDM_NUM + \ + POWER_LIMIT_SKU_HT20_NUM + \ + POWER_LIMIT_SKU_HT40_NUM + \ + POWER_LIMIT_SKU_VHT20_NUM + \ + POWER_LIMIT_SKU_VHT40_NUM + \ + POWER_LIMIT_SKU_VHT80_NUM + \ + POWER_LIMIT_SKU_VHT160_NUM) + +#define POWER_LIMIT_TXBF_BACKOFF_PARAM_NUM 6 + +struct CHANNEL_TX_PWR_LIMIT { + uint8_t ucChannel; + int8_t rTxPwrLimitValue[TX_PWR_LIMIT_SECTION_NUM] + [TX_PWR_LIMIT_ELEMENT_NUM]; + int8_t rTxBfBackoff[POWER_LIMIT_TXBF_BACKOFF_PARAM_NUM]; +}; + +struct TX_PWR_LIMIT_DATA { + uint32_t countryCode; + uint32_t ucChNum; + struct CHANNEL_TX_PWR_LIMIT *rChannelTxPwrLimit; +}; + +struct SKU_TABLE_TYPE { + int8_t i1PwrLimit[SINGLE_SKU_PARAM_NUM]; +}; + +struct CHANNEL_POWER_LIMIT_PER_RATE { + uint8_t ucCentralCh; + struct SKU_TABLE_TYPE aucTxPwrLimit; +}; + +struct CMD_SET_COUNTRY_TX_POWER_LIMIT_PER_RATE { + uint8_t ucCmdVer; + uint8_t aucPadding0[1]; + uint16_t u2CmdLen; + uint8_t ucNum; + uint8_t eBand; + uint8_t bCmdFinished; + uint8_t aucPadding1[1]; + uint32_t countryCode; + uint8_t aucPadding2[32]; + struct CHANNEL_POWER_LIMIT_PER_RATE rChannelPowerLimit[0]; +}; + +struct CMD_TXPWR_TXBF_CHANNEL_BACKOFF { + uint8_t ucCentralCh; + uint8_t aucPadding0[1]; + int8_t aucTxBfBackoff[POWER_LIMIT_TXBF_BACKOFF_PARAM_NUM]; +}; + +#define CMD_POWER_LIMIT_TABLE_SUPPORT_CHANNEL_NUM 64 +struct CMD_TXPWR_TXBF_SET_BACKOFF { + uint8_t ucCmdVer; + uint8_t aucPadding0[1]; + uint16_t u2CmdLen; + uint8_t ucNum; + uint8_t ucBssIdx; + uint8_t aucPadding1[2]; + uint8_t aucPadding2[32]; + struct CMD_TXPWR_TXBF_CHANNEL_BACKOFF + rChannelTxBfBackoff[CMD_POWER_LIMIT_TABLE_SUPPORT_CHANNEL_NUM]; +}; +#endif + +#endif + +/* CMD_SET_IP_ADDRESS */ +struct IPV4_NETWORK_ADDRESS { + uint8_t aucIpAddr[4]; +}; + +struct CMD_SET_NETWORK_ADDRESS_LIST { + uint8_t ucBssIndex; + uint8_t ucAddressCount; + uint8_t ucReserved[2]; + struct IPV4_NETWORK_ADDRESS arNetAddress[1]; +}; + +struct PATTERN_DESCRIPTION { + uint8_t fgCheckBcA1; + uint8_t fgCheckMcA1; + uint8_t ePatternHeader; + uint8_t fgAndOp; + uint8_t fgNotOp; + uint8_t ucPatternMask; + uint16_t u2PatternOffset; + uint8_t aucPattern[8]; +}; + +struct CMD_RAW_PATTERN_CONFIGURATION { + struct PATTERN_DESCRIPTION arPatternDesc[4]; +}; + +struct CMD_PATTERN_FUNC_CONFIG { + u_int8_t fgBcA1En; + u_int8_t fgMcA1En; + u_int8_t fgBcA1MatchDrop; + u_int8_t fgMcA1MatchDrop; +}; + +struct EVENT_TX_DONE { + uint8_t ucPacketSeq; + uint8_t ucStatus; + uint16_t u2SequenceNumber; + + uint8_t ucWlanIndex; + uint8_t ucTxCount; + uint16_t u2TxRate; + + uint8_t ucFlag; + uint8_t ucTid; + uint8_t ucRspRate; + uint8_t ucRateTableIdx; + + uint8_t ucBandwidth; + uint8_t ucTxPower; + uint8_t ucFlushReason; + uint8_t aucReserved0[1]; + + uint32_t u4TxDelay; + uint32_t u4Timestamp; + uint32_t u4AppliedFlag; + + uint8_t aucRawTxS[28]; + + uint8_t aucReserved1[32]; +}; + +enum ENUM_TXS_APPLIED_FLAG { + TX_FRAME_IN_AMPDU_FORMAT = 0, + TX_FRAME_EXP_BF, + TX_FRAME_IMP_BF, + TX_FRAME_PS_BIT +}; + +enum ENUM_TXS_CONTROL_FLAG { + TXS_WITH_ADVANCED_INFO = 0, + TXS_IS_EXIST +}; + +#if (CFG_SUPPORT_DFS_MASTER == 1) +enum ENUM_DFS_CTRL { + RDD_STOP = 0, + RDD_START, + RDD_DET_MODE, + RDD_RADAR_EMULATE, + RDD_START_TXQ = 20 +}; +#endif + +struct CMD_BSS_ACTIVATE_CTRL { + uint8_t ucBssIndex; + uint8_t ucActive; + uint8_t ucNetworkType; + uint8_t ucOwnMacAddrIndex; + uint8_t aucBssMacAddr[6]; + uint8_t ucBMCWlanIndex; + uint8_t ucReserved; +}; + +struct CMD_SET_BSS_RLM_PARAM { + uint8_t ucBssIndex; + uint8_t ucRfBand; + uint8_t ucPrimaryChannel; + uint8_t ucRfSco; + uint8_t ucErpProtectMode; + uint8_t ucHtProtectMode; + uint8_t ucGfOperationMode; + uint8_t ucTxRifsMode; + uint16_t u2HtOpInfo3; + uint16_t u2HtOpInfo2; + uint8_t ucHtOpInfo1; + uint8_t ucUseShortPreamble; + uint8_t ucUseShortSlotTime; + uint8_t ucVhtChannelWidth; + uint8_t ucVhtChannelFrequencyS1; + uint8_t ucVhtChannelFrequencyS2; + uint16_t u2VhtBasicMcsSet; + uint8_t ucNss; +}; + +struct CMD_SET_BSS_INFO { + uint8_t ucBssIndex; + uint8_t ucConnectionState; + uint8_t ucCurrentOPMode; + uint8_t ucSSIDLen; + uint8_t aucSSID[32]; + uint8_t aucBSSID[6]; + uint8_t ucIsQBSS; + uint8_t ucReserved1; + uint16_t u2OperationalRateSet; + uint16_t u2BSSBasicRateSet; + uint8_t ucStaRecIdxOfAP; + uint16_t u2HwDefaultFixedRateCode; + uint8_t ucNonHTBasicPhyType; /* For Slot Time and CWmin */ + uint8_t ucAuthMode; + uint8_t ucEncStatus; + uint8_t ucPhyTypeSet; + uint8_t ucWapiMode; + uint8_t ucIsApMode; + uint8_t ucBMCWlanIndex; + uint8_t ucHiddenSsidMode; + uint8_t ucDisconnectDetectTh; + uint32_t u4PrivateData; + struct CMD_SET_BSS_RLM_PARAM rBssRlmParam; + uint8_t ucDBDCBand; + uint8_t ucWmmSet; + uint8_t ucDBDCAction; + uint8_t ucNss; + uint8_t aucReserved[20]; +}; + +enum ENUM_RTS_POLICY { + RTS_POLICY_AUTO, + RTS_POLICY_STATIC_BW, + RTS_POLICY_DYNAMIC_BW, + RTS_POLICY_LEGACY, + RTS_POLICY_NO_RTS +}; + +struct CMD_UPDATE_STA_RECORD { + uint8_t ucStaIndex; + uint8_t ucStaType; + /* This field should assign at create + * and keep consistency for update usage + */ + uint8_t aucMacAddr[MAC_ADDR_LEN]; + + uint16_t u2AssocId; + uint16_t u2ListenInterval; + /* This field should assign at create + * and keep consistency for update usage + */ + uint8_t ucBssIndex; + uint8_t ucDesiredPhyTypeSet; + uint16_t u2DesiredNonHTRateSet; + + uint16_t u2BSSBasicRateSet; + uint8_t ucIsQoS; + uint8_t ucIsUapsdSupported; + uint8_t ucStaState; + uint8_t ucMcsSet; + uint8_t ucSupMcs32; + uint8_t aucReserved1[1]; + + uint8_t aucRxMcsBitmask[10]; + uint16_t u2RxHighestSupportedRate; + uint32_t u4TxRateInfo; + + uint16_t u2HtCapInfo; + uint16_t u2HtExtendedCap; + uint32_t u4TxBeamformingCap; + + uint8_t ucAmpduParam; + uint8_t ucAselCap; + uint8_t ucRCPI; + uint8_t ucNeedResp; + /* b0~3: Trigger enabled, b4~7: Delivery enabled */ + uint8_t ucUapsdAc; + /* 0: all, 1: max 2, 2: max 4, 3: max 6 */ + uint8_t ucUapsdSp; + /* This field should assign at create + * and keep consistency for update usage + */ + uint8_t ucWlanIndex; + /* This field should assign at create + * and keep consistency for update usage + */ + uint8_t ucBMCWlanIndex; + + uint32_t u4VhtCapInfo; + uint16_t u2VhtRxMcsMap; + uint16_t u2VhtRxHighestSupportedDataRate; + uint16_t u2VhtTxMcsMap; + uint16_t u2VhtTxHighestSupportedDataRate; + /* 0: auto 1: Static BW 2: Dynamic BW 3: Legacy 7: WoRts */ + uint8_t ucRtsPolicy; + /* VHT operating mode, bit 7: Rx NSS Type, + * bit 4-6, Rx NSS, bit 0-1: Channel Width + */ + uint8_t ucVhtOpMode; + + uint8_t ucTrafficDataType; /* 0: auto 1: data 2: video 3: voice */ + uint8_t ucTxGfMode; + uint8_t ucTxSgiMode; + uint8_t ucTxStbcMode; + uint16_t u2HwDefaultFixedRateCode; + uint8_t ucTxAmpdu; + uint8_t ucRxAmpdu; + uint32_t u4FixedPhyRate; /* */ + uint16_t u2MaxLinkSpeed; /* unit is 0.5 Mbps */ + uint16_t u2MinLinkSpeed; + + uint32_t u4Flags; + + uint8_t ucTxBaSize; + uint8_t ucRxBaSize; + uint8_t aucReserved3[2]; + + struct TXBF_PFMU_STA_INFO rTxBfPfmuInfo; + + uint8_t ucTxAmsduInAmpdu; + uint8_t ucRxAmsduInAmpdu; + uint8_t aucReserved5[2]; + + uint32_t u4TxMaxAmsduInAmpduLen; + /* UINT_8 aucReserved4[30]; */ +}; + +struct CMD_REMOVE_STA_RECORD { + uint8_t ucActionType; + uint8_t ucStaIndex; + uint8_t ucBssIndex; + uint8_t ucReserved; +}; + +struct CMD_INDICATE_PM_BSS_CREATED { + uint8_t ucBssIndex; + uint8_t ucDtimPeriod; + uint16_t u2BeaconInterval; + uint16_t u2AtimWindow; + uint8_t aucReserved[2]; +}; + +struct CMD_INDICATE_PM_BSS_CONNECTED { + uint8_t ucBssIndex; + uint8_t ucDtimPeriod; + uint16_t u2AssocId; + uint16_t u2BeaconInterval; + uint16_t u2AtimWindow; + uint8_t fgIsUapsdConnection; + uint8_t ucBmpDeliveryAC; + uint8_t ucBmpTriggerAC; + uint8_t aucReserved[1]; +}; + +struct CMD_INDICATE_PM_BSS_ABORT { + uint8_t ucBssIndex; + uint8_t aucReserved[3]; +}; + +struct CMD_BEACON_TEMPLATE_UPDATE { + /* 0: update randomly, + * 1: update all, + * 2: delete all (1 and 2 will update directly without search) + */ + uint8_t ucUpdateMethod; + uint8_t ucBssIndex; + uint8_t aucReserved[2]; + uint16_t u2Capability; + uint16_t u2IELen; + uint8_t aucIE[MAX_IE_LENGTH]; +}; + +struct CMD_SET_WMM_PS_TEST_STRUCT { + uint8_t ucBssIndex; + /* b0~3: trigger-en AC0~3. b4~7: delivery-en AC0~3 */ + uint8_t bmfgApsdEnAc; + /* enter PS immediately without 5 second guard after connected */ + uint8_t ucIsEnterPsAtOnce; + /* not to trigger UC on beacon TIM is matched (under U-APSD) */ + uint8_t ucIsDisableUcTrigger; +}; + +struct GSCN_CHANNEL_INFO { + uint8_t ucBand; + uint8_t ucChannelNumber; /* Channel Number */ + uint8_t ucPassive; /* 0:active, 1:passive scan; ignored for DFS */ + uint8_t aucReserved[1]; + uint32_t u4DwellTimeMs; /* dwell time hint */ +}; + +enum ENUM_WIFI_BAND { + WIFI_BAND_UNSPECIFIED, + WIFI_BAND_BG = 1, /* 2.4 GHz */ + WIFI_BAND_A = 2, /* 5 GHz without DFS */ + WIFI_BAND_A_DFS = 4, /* 5 GHz DFS only */ + WIFI_BAND_A_WITH_DFS = 6, /* 5 GHz with DFS */ + WIFI_BAND_ABG = 3, /* 2.4 GHz + 5 GHz; no DFS */ + WIFI_BAND_ABG_WITH_DFS = 7, /* 2.4 GHz + 5 GHz with DFS */ +}; + +struct GSCAN_BUCKET { + uint16_t u2BucketIndex; /* bucket index, 0 based */ + /* desired period, in millisecond; + * if this is too low, the firmware should choose to generate + * results as fast as it can instead of failing the command + */ + uint8_t ucBucketFreqMultiple; + /* report_events semantics - + * This is a bit field; which defines following bits - + * REPORT_EVENTS_EACH_SCAN + * report a scan completion event after scan. If this is not set + * then scan completion events should be reported if + * report_threshold_percent or report_threshold_num_scans is + * reached. + * REPORT_EVENTS_FULL_RESULTS + * forward scan results (beacons/probe responses + IEs) + * in real time to HAL, in addition to completion events + * Note: To keep backward compatibility, fire completion + * events regardless of REPORT_EVENTS_EACH_SCAN. + * REPORT_EVENTS_NO_BATCH + * controls if scans for this bucket should be placed in the + * history buffer + */ + uint8_t ucReportFlag; + uint8_t ucMaxBucketFreqMultiple; /* max_period / base_period */ + uint8_t ucStepCount; + uint8_t ucNumChannels; + uint8_t aucReserved[1]; + enum ENUM_WIFI_BAND + eBand; /* when UNSPECIFIED, use channel list */ + /* channels to scan; these may include DFS channels */ + struct GSCN_CHANNEL_INFO arChannelList[8]; +}; + +struct CMD_GSCN_REQ { + uint8_t ucFlags; + uint8_t ucNumScnToCache; + uint8_t aucReserved[2]; + uint32_t u4BufferThreshold; + uint32_t u4BasePeriod; /* base timer period in ms */ + uint32_t u4NumBuckets; + /* number of APs to store in each scan in the */ + uint32_t u4MaxApPerScan; + /* BSSID/RSSI history buffer (keep the highest RSSI APs) */ + struct GSCAN_BUCKET arBucket[8]; +}; + +struct CMD_GSCN_SCN_COFIG { + uint8_t ucNumApPerScn; /* GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN */ + uint32_t u4BufferThreshold; /* GSCAN_ATTRIBUTE_REPORT_THRESHOLD */ + uint32_t u4NumScnToCache; /* GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE */ +}; + +/* Definition for CHANNEL_INFO.ucBand: + * 0: Reserved + * 1: BAND_2G4 + * 2: BAND_5G + * Others: Reserved + */ +struct CHANNEL_INFO { + uint8_t ucBand; + uint8_t ucChannelNum; +}; + +struct CMD_SCAN_REQ { + uint8_t ucSeqNum; + uint8_t ucBssIndex; + uint8_t ucScanType; + /* BIT(0) wildcard / BIT(1) P2P-wildcard / BIT(2) specific */ + uint8_t ucSSIDType; + uint8_t ucSSIDLength; + uint8_t ucNumProbeReq; + uint16_t u2ChannelMinDwellTime; + uint16_t u2ChannelDwellTime; + uint16_t u2TimeoutValue; + uint8_t aucSSID[32]; + uint8_t ucChannelType; + uint8_t ucChannelListNum; + uint8_t aucReserved[2]; + struct CHANNEL_INFO arChannelList[32]; + uint16_t u2IELen; + uint8_t aucIE[MAX_IE_LENGTH]; +}; + +struct CMD_SCAN_REQ_V2 { + uint8_t ucSeqNum; + uint8_t ucBssIndex; + uint8_t ucScanType; + uint8_t ucSSIDType; + uint8_t ucSSIDNum; + uint8_t ucNumProbeReq; + uint8_t ucScnFuncMask; + uint8_t auVersion[1]; + struct PARAM_SSID arSSID[4]; + uint16_t u2ProbeDelayTime; + uint16_t u2ChannelDwellTime; + uint16_t u2TimeoutValue; + uint8_t ucChannelType; + uint8_t ucChannelListNum; /*total 160*/ + struct CHANNEL_INFO arChannelList[32]; /*total 160+64=224*/ + uint16_t u2IELen; /*total 226*/ + uint8_t aucIE[MAX_IE_LENGTH]; /*total 826*/ + uint8_t ucChannelListExtNum; + uint8_t ucSSIDExtNum; + uint16_t u2ChannelMinDwellTime; + struct CHANNEL_INFO arChannelListExtend[32]; + struct PARAM_SSID arSSIDExtend[6]; + uint8_t aucBSSID[MAC_ADDR_LEN]; + uint8_t aucRandomMac[MAC_ADDR_LEN]; + uint8_t aucPadding_2[64]; +}; + +struct CMD_SCAN_CANCEL { + uint8_t ucSeqNum; + uint8_t ucIsExtChannel; /* For P2P channel extension. */ + uint8_t aucReserved[2]; +}; + +/* 20150107 Daniel Added complete channels number in the scan done event */ +/* before*/ +/* + * typedef struct EVENT_SCAN_DONE { + * UINT_8 ucSeqNum; + * UINT_8 ucSparseChannelValid; + * CHANNEL_INFO_T rSparseChannel; + * } EVENT_SCAN_DONE, *P_EVENT_SCAN_DONE; + */ +/* after */ + +#define EVENT_SCAN_DONE_CHANNEL_NUM_MAX 64 +struct EVENT_SCAN_DONE { + uint8_t ucSeqNum; + uint8_t ucSparseChannelValid; + struct CHANNEL_INFO rSparseChannel; + /*scan done version #2 */ + uint8_t ucCompleteChanCount; + uint8_t ucCurrentState; + uint8_t ucScanDoneVersion; + /*scan done version #3 */ + uint8_t ucReserved; + uint32_t u4ScanDurBcnCnt; + uint8_t fgIsPNOenabled; + uint8_t aucReserving[3]; + /*channel idle count # Mike */ + uint8_t ucSparseChannelArrayValidNum; + uint8_t aucReserved[3]; + uint8_t aucChannelNum[EVENT_SCAN_DONE_CHANNEL_NUM_MAX]; + /* Idle format for au2ChannelIdleTime */ + /* 0: first bytes: idle time(ms) 2nd byte: dwell time(ms) */ + /* 1: first bytes: idle time(8ms) 2nd byte: dwell time(8ms) */ + /* 2: dwell time (16us) */ + uint16_t au2ChannelIdleTime[EVENT_SCAN_DONE_CHANNEL_NUM_MAX]; + /* Beacon and Probe Response Count in each Channel */ + uint8_t aucChannelBAndPCnt[EVENT_SCAN_DONE_CHANNEL_NUM_MAX]; + /* Mdrdy Count in each Channel */ + uint8_t aucChannelMDRDYCnt[EVENT_SCAN_DONE_CHANNEL_NUM_MAX]; + +}; + +struct CMD_BATCH_REQ { + uint8_t ucSeqNum; + uint8_t ucNetTypeIndex; + uint8_t ucCmd; /* Start/ Stop */ + /* an integer number of scans per batch */ + uint8_t ucMScan; + /* an integer number of the max AP to remember per scan */ + uint8_t ucBestn; + /* an integer number of highest-strength AP for which we'd */ + uint8_t ucRtt; + /* like approximate distance reported */ + uint8_t ucChannel; /* channels */ + uint8_t ucChannelType; + uint8_t ucChannelListNum; + uint8_t aucReserved[3]; + uint32_t u4Scanfreq; /* an integer number of seconds between scans */ + struct CHANNEL_INFO arChannelList[32]; /* channels */ +}; + +struct EVENT_BATCH_RESULT_ENTRY { + uint8_t aucBssid[MAC_ADDR_LEN]; + uint8_t aucSSID[ELEM_MAX_LEN_SSID]; + uint8_t ucSSIDLen; + int8_t cRssi; + uint32_t ucFreq; + uint32_t u4Age; + uint32_t u4Dist; + uint32_t u4Distsd; +}; + +struct EVENT_BATCH_RESULT { + uint8_t ucScanCount; + uint8_t aucReserved[3]; + /* Must be the same with SCN_BATCH_STORE_MAX_NUM */ + struct EVENT_BATCH_RESULT_ENTRY arBatchResult[12]; +}; + +struct CMD_CH_PRIVILEGE { + uint8_t ucBssIndex; + uint8_t ucTokenID; + uint8_t ucAction; + uint8_t ucPrimaryChannel; + uint8_t ucRfSco; + uint8_t ucRfBand; + uint8_t ucRfChannelWidth; /* To support 80/160MHz bandwidth */ + uint8_t ucRfCenterFreqSeg1; /* To support 80/160MHz bandwidth */ + uint8_t ucRfCenterFreqSeg2; /* To support 80/160MHz bandwidth */ + uint8_t ucReqType; + uint8_t ucDBDCBand; + uint8_t aucReserved; + uint32_t u4MaxInterval; /* In unit of ms */ + uint8_t aucReserved2[8]; +}; + +struct CMD_TX_PWR { + int8_t cTxPwr2G4Cck; /* signed, in unit of 0.5dBm */ + int8_t cTxPwr2G4Dsss; /* signed, in unit of 0.5dBm */ + int8_t acReserved[2]; + + int8_t cTxPwr2G4OFDM_BPSK; + int8_t cTxPwr2G4OFDM_QPSK; + int8_t cTxPwr2G4OFDM_16QAM; + int8_t cTxPwr2G4OFDM_Reserved; + int8_t cTxPwr2G4OFDM_48Mbps; + int8_t cTxPwr2G4OFDM_54Mbps; + + int8_t cTxPwr2G4HT20_BPSK; + int8_t cTxPwr2G4HT20_QPSK; + int8_t cTxPwr2G4HT20_16QAM; + int8_t cTxPwr2G4HT20_MCS5; + int8_t cTxPwr2G4HT20_MCS6; + int8_t cTxPwr2G4HT20_MCS7; + + int8_t cTxPwr2G4HT40_BPSK; + int8_t cTxPwr2G4HT40_QPSK; + int8_t cTxPwr2G4HT40_16QAM; + int8_t cTxPwr2G4HT40_MCS5; + int8_t cTxPwr2G4HT40_MCS6; + int8_t cTxPwr2G4HT40_MCS7; + + int8_t cTxPwr5GOFDM_BPSK; + int8_t cTxPwr5GOFDM_QPSK; + int8_t cTxPwr5GOFDM_16QAM; + int8_t cTxPwr5GOFDM_Reserved; + int8_t cTxPwr5GOFDM_48Mbps; + int8_t cTxPwr5GOFDM_54Mbps; + + int8_t cTxPwr5GHT20_BPSK; + int8_t cTxPwr5GHT20_QPSK; + int8_t cTxPwr5GHT20_16QAM; + int8_t cTxPwr5GHT20_MCS5; + int8_t cTxPwr5GHT20_MCS6; + int8_t cTxPwr5GHT20_MCS7; + + int8_t cTxPwr5GHT40_BPSK; + int8_t cTxPwr5GHT40_QPSK; + int8_t cTxPwr5GHT40_16QAM; + int8_t cTxPwr5GHT40_MCS5; + int8_t cTxPwr5GHT40_MCS6; + int8_t cTxPwr5GHT40_MCS7; +}; + +struct CMD_TX_AC_PWR { + int8_t ucBand; +#if 0 + int8_t c11AcTxPwr_BPSK; + int8_t c11AcTxPwr_QPSK; + int8_t c11AcTxPwr_16QAM; + int8_t c11AcTxPwr_MCS5_MCS6; + int8_t c11AcTxPwr_MCS7; + int8_t c11AcTxPwr_MCS8; + int8_t c11AcTxPwr_MCS9; + int8_t c11AcTxPwrVht40_OFFSET; + int8_t c11AcTxPwrVht80_OFFSET; + int8_t c11AcTxPwrVht160_OFFSET; +#else + struct AC_PWR_SETTING_STRUCT rAcPwr; +#endif +}; + +struct CMD_RSSI_PATH_COMPASATION { + int8_t c2GRssiCompensation; + int8_t c5GRssiCompensation; +}; +struct CMD_5G_PWR_OFFSET { + int8_t cOffsetBand0; /* 4.915-4.980G */ + int8_t cOffsetBand1; /* 5.000-5.080G */ + int8_t cOffsetBand2; /* 5.160-5.180G */ + int8_t cOffsetBand3; /* 5.200-5.280G */ + int8_t cOffsetBand4; /* 5.300-5.340G */ + int8_t cOffsetBand5; /* 5.500-5.580G */ + int8_t cOffsetBand6; /* 5.600-5.680G */ + int8_t cOffsetBand7; /* 5.700-5.825G */ +}; + +struct CMD_PWR_PARAM { + uint32_t au4Data[28]; + uint32_t u4RefValue1; + uint32_t u4RefValue2; +}; + +struct CMD_PHY_PARAM { + uint8_t aucData[144]; /* eFuse content */ +}; + +struct CMD_AUTO_POWER_PARAM { + /* 0: Disable 1: Enalbe 0x10: Change parameters */ + uint8_t ucType; + uint8_t ucBssIndex; + uint8_t aucReserved[2]; + uint8_t aucLevelRcpiTh[3]; + uint8_t aucReserved2[1]; + int8_t aicLevelPowerOffset[3]; /* signed, in unit of 0.5dBm */ + uint8_t aucReserved3[1]; + uint8_t aucReserved4[8]; +}; + +/*for WMMAC, CMD_ID_UPDATE_AC_PARAMS*/ +struct CMD_UPDATE_AC_PARAMS { + uint8_t ucAcIndex; /*0 ~3, from AC0 to AC3*/ + uint8_t ucBssIdx; /*no use*/ + /* if 0, disable ACM for ACx specified by + ** ucAcIndex, otherwise in unit of 32us + */ + uint16_t u2MediumTime; + /* rate to be used to tx packet with priority + ** ucAcIndex , unit: bps + */ + uint32_t u4PhyRate; + uint16_t u2EDCALifeTime; /* msdu life time for this TC, unit: 2TU */ + /* if we use fix rate to tx packets, should tell + ** firmware the limited retries + */ + uint8_t ucRetryCount; + uint8_t aucReserved[5]; +}; + +/* S56 Traffic Stream Metrics */ +struct CMD_SET_TSM_STATISTICS_REQUEST { + uint8_t ucEnabled; /* 0, disable; 1, enable; */ + uint8_t ucBssIdx; /* always AIS Bss index now */ + uint8_t ucAcIndex; /* wmm ac index, the statistics should be on this TC + */ + uint8_t ucTid; + + uint8_t aucPeerAddr + [MAC_ADDR_LEN]; /* packet to the target address to be mesured */ + uint8_t ucBin0Range; + uint8_t aucReserved[3]; + + /* if this variable is 0, followed variables are meaningless + ** only report once for a same trigger condition in this time frame + ** for triggered mode: bit(0):average, bit(1):consecutive, + ** bit(2):delay + */ + uint8_t ucTriggerCondition; + uint8_t ucAvgErrThreshold; + uint8_t ucConsecutiveErrThreshold; + uint8_t ucDelayThreshold; + uint8_t ucMeasureCount; + uint8_t ucTriggerTimeout; /* unit: 100 TU*/ +}; + +struct CMD_GET_TSM_STATISTICS { + uint8_t ucBssIdx; /* always AIS Bss now */ + /* wmm ac index, the statistics should be on this TC or TS */ + uint8_t ucAcIndex; + uint8_t ucTid; /* */ + + uint8_t aucPeerAddr + [MAC_ADDR_LEN]; /* indicating the RA for the measured frames */ + /* for triggered mode: bit(0):average, bit(1):consecutive, + ** bit(2):delay + */ + uint8_t ucReportReason; + uint16_t u2Reserved; + + uint32_t u4PktTxDoneOK; + uint32_t u4PktDiscard; /* u2PktTotal - u2PktTxDoneOK */ + uint32_t u4PktFail; /* failed count for exceeding retry limit */ + uint32_t u4PktRetryTxDoneOK; + uint32_t u4PktQosCfPollLost; + + /* 802.11k - Average Packet Transmission delay for all packets per this + ** TC or TS + */ + uint32_t u4AvgPktTxDelay; + /* 802.11k - Average Packet Queue Delay */ + uint32_t u4AvgPktQueueDelay; + uint64_t u8StartTime; /* represented by TSF */ + /* sum of packets whose packet tx delay is less than Bi (i=0~6) range + ** value(unit: TU) + */ + uint32_t au4PktCntBin[6]; +}; + +struct CMD_DBDC_SETTING { + uint8_t ucDbdcEn; + uint8_t ucWmmBandBitmap; + uint8_t ucUpdateSettingNextChReq; + uint8_t aucPadding0[1]; + uint8_t ucCmdVer; + uint8_t aucPadding1[1]; + uint16_t u2CmdLen; + uint8_t ucPrimaryChannel; + uint8_t ucWmmQueIdx; + uint8_t aucPadding2[2]; + uint8_t aucPadding3[24]; +}; + +struct EVENT_CH_PRIVILEGE { + uint8_t ucBssIndex; + uint8_t ucTokenID; + uint8_t ucStatus; + uint8_t ucPrimaryChannel; + uint8_t ucRfSco; + uint8_t ucRfBand; + uint8_t ucRfChannelWidth; /* To support 80/160MHz bandwidth */ + uint8_t ucRfCenterFreqSeg1; /* To support 80/160MHz bandwidth */ + uint8_t ucRfCenterFreqSeg2; /* To support 80/160MHz bandwidth */ + uint8_t ucReqType; + uint8_t ucDBDCBand; + uint8_t aucReserved; + uint32_t u4GrantInterval; /* In unit of ms */ + uint8_t aucReserved2[8]; +}; + +#if (CFG_SUPPORT_DFS_MASTER == 1) +struct LONG_PULSE_BUFFER { + uint32_t u4LongStartTime; + uint16_t u2LongPulseWidth; +}; + +struct PERIODIC_PULSE_BUFFER { + uint32_t u4PeriodicStartTime; + uint16_t u2PeriodicPulseWidth; + int16_t i2PeriodicPulsePower; +}; + +struct EVENT_RDD_REPORT { + /*0: Only report radar detected; 1: Add parameter reports*/ + uint8_t ucRadarReportMode; + uint8_t ucRddIdx; + uint8_t ucLongDetected; + uint8_t ucPeriodicDetected; + uint8_t ucLPBNum; + uint8_t ucPPBNum; + uint8_t ucLPBPeriodValid; + uint8_t ucLPBWidthValid; + uint8_t ucPRICountM1; + uint8_t ucPRICountM1TH; + uint8_t ucPRICountM2; + uint8_t ucPRICountM2TH; + uint32_t u4PRI1stUs; + struct LONG_PULSE_BUFFER arLpbContent[LPB_SIZE]; + struct PERIODIC_PULSE_BUFFER arPpbContent[PPB_SIZE]; +}; +#endif + +#if (CFG_WOW_SUPPORT == 1) +/* event of wake up reason */ +struct _EVENT_WAKEUP_REASON_INFO { + uint8_t reason; + uint8_t aucReserved[3]; +}; +#endif + +struct EVENT_BSS_BEACON_TIMEOUT { + uint8_t ucBssIndex; + uint8_t ucReasonCode; + uint8_t aucReserved[2]; +}; + +struct EVENT_STA_AGING_TIMEOUT { + uint8_t ucStaRecIdx; + uint8_t aucReserved[3]; +}; + +struct EVENT_NOA_TIMING { + uint8_t ucIsInUse; /* Indicate if this entry is in use or not */ + uint8_t ucCount; /* Count */ + uint8_t aucReserved[2]; + + uint32_t u4Duration; /* Duration */ + uint32_t u4Interval; /* Interval */ + uint32_t u4StartTime; /* Start Time */ +}; + +struct EVENT_UPDATE_NOA_PARAMS { + uint8_t ucBssIndex; + uint8_t aucReserved[2]; + uint8_t ucEnableOppPS; + uint16_t u2CTWindow; + + uint8_t ucNoAIndex; + uint8_t ucNoATimingCount; /* Number of NoA Timing */ + struct EVENT_NOA_TIMING + arEventNoaTiming[8 /*P2P_MAXIMUM_NOA_COUNT */]; +}; + +struct EVENT_AP_OBSS_STATUS { + uint8_t ucBssIndex; + uint8_t ucObssErpProtectMode; + uint8_t ucObssHtProtectMode; + uint8_t ucObssGfOperationMode; + uint8_t ucObssRifsOperationMode; + uint8_t ucObssBeaconForcedTo20M; + uint8_t aucReserved[2]; +}; + +struct EVENT_DEBUG_MSG { + uint16_t u2DebugMsgId; + uint8_t ucMsgType; + uint8_t ucFlags; /* unused */ + uint32_t u4Value; /* memory addre or ... */ + uint16_t u2MsgSize; + uint8_t aucReserved0[2]; + uint8_t aucMsg[1]; +}; + +struct CMD_EDGE_TXPWR_LIMIT { + int8_t cBandEdgeMaxPwrCCK; + int8_t cBandEdgeMaxPwrOFDM20; + int8_t cBandEdgeMaxPwrOFDM40; + int8_t cBandEdgeMaxPwrOFDM80; +}; + +struct CMD_POWER_OFFSET { + uint8_t ucBand; /*1:2.4G ; 2:5G */ + /*the max num subband is 5G, devide with 8 subband */ + uint8_t ucSubBandOffset[MAX_SUBBAND_NUM_5G]; + uint8_t aucReverse[3]; + +}; + +struct CMD_NVRAM_SETTING { + + struct WIFI_CFG_PARAM_STRUCT rNvramSettings; + +}; + +#if CFG_SUPPORT_TDLS +struct CMD_TDLS_CH_SW { + u_int8_t fgIsTDLSChSwProhibit; +}; +#endif + +struct CMD_SET_DEVICE_MODE { + uint16_t u2ChipID; + uint16_t u2Mode; +}; +#if CFG_SUPPORT_ADVANCE_CONTROL +/* command type */ +#define CMD_ADV_CONTROL_SET (1<<15) +#define CMD_PTA_CONFIG_TYPE (0x1) +#define CMD_AFH_CONFIG_TYPE (0x2) +#define CMD_BA_CONFIG_TYPE (0x3) +#define CMD_GET_REPORT_TYPE (0x4) +#define CMD_NOISE_HISTOGRAM_TYPE (0x5) +#if CFG_IPI_2CHAIN_SUPPORT +#define CMD_NOISE_HISTOGRAM_TYPE2 (0x51) +#endif +#define CMD_ADMINCTRL_CONFIG_TYPE (0x6) +#ifdef CFG_SUPPORT_EXT_PTA_DEBUG_COMMAND +#define CMD_EXT_PTA_CONFIG_TYPE (0x7) +#endif + +/* for PtaConfig field */ +#define CMD_PTA_CONFIG_PTA_EN (1<<0) +#define CMD_PTA_CONFIG_RW_EN (1<<1) +#define CMD_PTA_CONFIG_PTA_STAT_EN (1<<2) + +/* pta config related mask */ +#define CMD_PTA_CONFIG_PTA (1<<0) +#define CMD_PTA_CONFIG_RW (1<<1) +#define CMD_PTA_CONFIG_TXDATA_TAG (1<<2) +#define CMD_PTA_CONFIG_RXDATAACK_TAG (1<<3) +#define CMD_PTA_CONFIG_RX_NSW_TAG (1<<4) +#define CMD_PTA_CONFIG_TXACK_TAG (1<<5) +#define CMD_PTA_CONFIG_TXPROTFRAME_TAG (1<<6) +#define CMD_PTA_CONFIG_RXPROTFRAMEACK_TAG (1<<7) +#define CMD_PTA_CONFIG_TX_BMC_TAG (1<<8) +#define CMD_PTA_CONFIG_TX_BCN_TAG (1<<9) +#define CMD_PTA_CONFIG_RX_SP_TAG (1<<10) +#define CMD_PTA_CONFIG_TX_MGMT_TAG (1<<11) +#define CMD_PTA_CONFIG_RXMGMTACK_TAG (1<<12) +#define CMD_PTA_CONFIG_PTA_STAT (1<<13) +#define CMD_PTA_CONFIG_PTA_STAT_RESET (1<<14) +#define CMD_PTA_CONFIG_COMM_ACT_BT_WF0_INBAND (1<<15) +#define CMD_PTA_CONFIG_COMM_ACT_BT_WF0_OUTBAND (1<<16) +#define CMD_PTA_CONFIG_COMM_ACT_BT_WF1_INBAND (1<<17) +#define CMD_PTA_CONFIG_COMM_ACT_BT_WF1_OUTBAND (1<<18) + +#ifdef CFG_SUPPORT_EXT_PTA_DEBUG_COMMAND +/* ext pta config related mask */ +#define CMD_EXT_PTA_CONFIG_EXT_PTA (1<<0) +#define CMD_EXT_PTA_CONFIG_HI_RX_TAG (1<<1) +#define CMD_EXT_PTA_CONFIG_LO_RX_TAG (1<<2) +#define CMD_EXT_PTA_CONFIG_HI_TX_TAG (1<<3) +#define CMD_EXT_PTA_CONFIG_LO_TX_TAG (1<<4) +#define CMD_EXT_PTA_CONFIG_COMM_ACT_ZB_BT_UNSAFE (1<<5) +#define CMD_EXT_PTA_CONFIG_COMM_ACT_ZB_WF0_UNSAFE (1<<6) +#define CMD_EXT_PTA_CONFIG_COMM_ACT_ZB_WF1_UNSAFE (1<<7) +#define CMD_EXT_PTA_CONFIG_COMM_ACT_ZB_BT_HSF (1<<8) +#define CMD_EXT_PTA_CONFIG_COMM_ACT_ZB_WF0_HSF (1<<9) +#define CMD_EXT_PTA_CONFIG_COMM_ACT_ZB_WF1_HSF (1<<10) +#endif + +/* for config PTA Tag */ +#define EVENT_CONFIG_PTA_OFFSET (0) +#define EVENT_CONFIG_PTA_FEILD (0x1) +#define EVENT_CONFIG_PTA_WIFI_OFFSET (12) +#define EVENT_CONFIG_PTA_WIFI_FEILD (0x1) +#define EVENT_CONFIG_PTA_BT_OFFSET (15) +#define EVENT_CONFIG_PTA_BT_FEILD (0x1) +#define EVENT_CONFIG_PTA_ARB_OFFSET (16) +#define EVENT_CONFIG_PTA_ARB_FEILD (0x1) + +#define EVENT_CONFIG_WIFI_GRANT_OFFSET (30) +#define EVENT_CONFIG_WIFI_GRANT_FEILD (0x1) +#define EVENT_CONFIG_WIFI_PRI_OFFSET (12) +#define EVENT_CONFIG_WIFI_PRI_FEILD (0xf) +#define EVENT_CONFIG_WIFI_TXREQ_OFFSET (8) +#define EVENT_CONFIG_WIFI_TXREQ_FEILD (0x1) +#define EVENT_CONFIG_WIFI_RXREQ_OFFSET (9) +#define EVENT_CONFIG_WIFI_RXREQ_FEILD (0x1) + +#define EVENT_CONFIG_BT_GRANT_OFFSET (29) +#define EVENT_CONFIG_BT_GRANT_FEILD (0x1) +#define EVENT_CONFIG_BT_PRI_OFFSET (4) +#define EVENT_CONFIG_BT_PRI_FEILD (0xf) +#define EVENT_CONFIG_BT_TXREQ_OFFSET (0) +#define EVENT_CONFIG_BT_TXREQ_FEILD (0x1) +#define EVENT_CONFIG_BT_RXREQ_OFFSET (1) +#define EVENT_CONFIG_BT_RXREQ_FEILD (0x1) + +#define EVENT_PTA_BTTRX_CNT_OFFSET (16) +#define EVENT_PTA_BTTRX_CNT_FEILD (0xFFFF) +#define EVENT_PTA_BTTRX_GRANT_CNT_OFFSET (0) +#define EVENT_PTA_BTTRX_GRANT_CNT_FEILD (0xFFFF) + +#define EVENT_PTA_WFTRX_CNT_OFFSET (16) +#define EVENT_PTA_WFTRX_CNT_FEILD (0xFFFF) +#define EVENT_PTA_WFTRX_GRANT_CNT_OFFSET (0) +#define EVENT_PTA_WFTRX_GRANT_CNT_FEILD (0xFFFF) + +#define EVENT_PTA_TX_ABT_CNT_OFFSET (16) +#define EVENT_PTA_TX_ABT_CNT_FEILD (0xFFFF) +#define EVENT_PTA_RX_ABT_CNT_OFFSET (0) +#define EVENT_PTA_RX_ABT_CNT_FEILD (0xFFFF) +struct CMD_PTA_CONFIG { + uint16_t u2Type; + uint16_t u2Len; + uint32_t u4ConfigMask; + /* common usage in set/get */ + uint32_t u4PtaConfig; + uint32_t u4TxDataTag; + uint32_t u4RxDataAckTag; + uint32_t u4RxNswTag; + uint32_t u4TxAckTag; + uint32_t u4TxProtFrameTag; + uint32_t u4RxProtFrameAckTag; + uint32_t u4TxBMCTag; + uint32_t u4TxBCNTag; + uint32_t u4RxSPTag; + uint32_t u4TxMgmtTag; + uint32_t u4RxMgmtAckTag; + uint32_t u4CommActBtWf0Inband; + uint32_t u4CommActBtWf0Outband; + uint32_t u4CommActBtWf1Inband; + uint32_t u4CommActBtWf1Outband; + /* Only used in get */ + uint32_t u4PtaWF0TxCnt; + uint32_t u4PtaWF0RxCnt; + uint32_t u4PtaWF0AbtCnt; + uint32_t u4PtaWF1TxCnt; + uint32_t u4PtaWF1RxCnt; + uint32_t u4PtaWF1AbtCnt; + uint32_t u4PtaBTTxCnt; + uint32_t u4PtaBTRxCnt; + uint32_t u4PtaBTAbtCnt; + uint32_t u4GrantStat; + uint32_t u4CoexMode; +}; + +#ifdef CFG_SUPPORT_EXT_PTA_DEBUG_COMMAND +struct CMD_EXT_PTA_CONFIG { + uint16_t u2Type; + uint16_t u2Len; + uint32_t u4ConfigMask; + /* common usage in set/get */ + uint32_t u4ExtPtaConfig; + uint32_t u4ZbHiRxTag; + uint32_t u4ZbLoRxTag; + uint32_t u4ZbHiTxTag; + uint32_t u4ZbLoTxTag; + uint32_t u4CommActZbBtUnsafe; + uint32_t u4CommActZbWf0Unsafe; + uint32_t u4CommActZbWf1Unsafe; + uint32_t u4CommActZbBtHsf; + uint32_t u4CommActZbWf0Hsf; + uint32_t u4CommActZbWf1Hsf; + /* used in get */ + uint32_t u4ZbGntCnt; + uint32_t u4ZbAbtCnt; + uint32_t u4ZbLoTxReqCnt; + uint32_t u4ZbHiTxReqCnt; + uint32_t u4ZbLoRxReqCnt; + uint32_t u4ZbHiRxReqCnt; +}; +#endif + +/* get report related */ +enum ENUM_GET_REPORT_ACTION_T { + CMD_GET_REPORT_ENABLE = 1, + CMD_GET_REPORT_DISABLE, + CMD_GET_REPORT_RESET, + CMD_GET_REPORT_GET, + CMD_SET_REPORT_SAMPLE_DUR, + CMD_SET_REPORT_SAMPLE_POINT, + CMD_SET_REPORT_TXTHRES, + CMD_SET_REPORT_RXTHRES, + CMD_GET_REPORT_ACTIONS +}; +#define EVENT_REPORT_OFDM_FCCA (16) +#define EVENT_REPORT_OFDM_FCCA_FEILD (0xffff) +#define EVENT_REPORT_CCK_FCCA (0) +#define EVENT_REPORT_CCK_FCCA_FEILD (0xffff) +#define EVENT_REPORT_OFDM_SIGERR (16) +#define EVENT_REPORT_OFDM_SIGERR_FEILD (0xffff) +#define EVENT_REPORT_CCK_SIGERR (0) +#define EVENT_REPORT_CCK_SIGERR_FEILD (0xffff) +struct CMD_GET_TRAFFIC_REPORT { + uint16_t u2Type; + uint16_t u2Len; + /* parameter */ + uint8_t ucBand; + uint8_t ucAction; + uint8_t reserved[2]; + /* report 1 */ + uint32_t u4FalseCCA; + uint32_t u4HdrCRC; + uint32_t u4PktSent; + uint32_t u4PktRetried; + uint32_t u4PktTxfailed; + uint32_t u4RxMPDU; + uint32_t u4RxFcs; + /* air time report */ + uint32_t u4FetchSt; /* ms */ + uint32_t u4FetchEd; /* ms */ + uint32_t u4ChBusy; /* us */ + uint32_t u4ChIdle; /* us */ + uint32_t u4TxAirTime; /* us */ + uint32_t u4RxAirTime; /* us */ + uint32_t u4TimerDur; /* ms */ + uint32_t u4FetchCost; /* us */ + int32_t TimerDrift; /* ms */ + int16_t u2SamplePoints; /* ms */ + int8_t ucTxThres; /* ms */ + int8_t ucRxThres; /* ms */ +}; + +/* admission control related define */ +/* support set operations */ +#define ADMIN_CTRL_SET_MODE (0) +#define ADMIN_CTRL_SET_BASE (1) +#define ADMIN_CTRL_SET_TBL1 (2) +#define ADMIN_CTRL_SET_TBL2 (3) +#define ADMIN_CTRL_SET_TBL3 (4) +#define ADMIN_CTRL_SET_METHOD (5) + +/* admission ctrl mode */ +#define ADMIN_CTRL_MODE_DIS (0) +#define ADMIN_CTRL_MODE_AUTO (1) +#define ADMIN_CTRL_MODE_MAN (2) +#define ADMIN_CTRL_MODE_RESET (3) +/* default value */ +#define ADMIN_CTRL_RATE_CODE_NUM (8) /* AUTO_RATE_NUM */ +#define ADMIN_CTRL_TBL_ENTRY_NUM (6) +#define ADMIN_CTRL_MAX_PERCENTAGE (100) +/* status define */ +#define BT_PROF_A2DP_SRC 0x02 +#define BT_PROF_LINK_CONNECTED 0x04 +#define BT_PROF_A2DP_SINK 0x400 +#define ADMIN_LINK_2G BIT(0) +#define ADMIN_LINK_OTHER BIT(1) +#define ADMIN_ENABLED BIT(2) +#define ADMIN_PER_PKT_ENABLED BIT(3) +#define ADMIN_METHOD1_ENABLED BIT(4) +#define ADMIN_METHOD2_ENABLED BIT(5) + +struct ADMIN_CTRL_PARAM { + /* bt info updated to admin ctrl */ + uint32_t u4CoexMode; + /* Ctrl mode */ + uint16_t u2eMode; + /* Admin ctrl related */ + uint16_t u2AdminCtrlBase; + uint16_t u2CurAdminTime; + uint16_t u2ForceAdminTime; + /* Rate related */ + uint16_t au2RateCode[ADMIN_CTRL_RATE_CODE_NUM]; + /* admin ctrl % tbl */ + uint8_t aucAdminTbl1[ADMIN_CTRL_TBL_ENTRY_NUM]; + uint8_t aucAdminTbl2[ADMIN_CTRL_TBL_ENTRY_NUM]; + uint8_t aucAdminTbl3[ADMIN_CTRL_TBL_ENTRY_NUM]; + uint8_t ucAdminThermalLimit; + uint8_t ucLastChosenTbl; + uint8_t ucAdminStatus; + uint8_t reserved[3]; +}; + +struct CMD_ADMIN_CTRL_CONFIG { + uint16_t u2Type; + uint16_t u2Len; + /* parameter */ + uint16_t u2Action; + uint8_t reserved[2]; + /* content */ + struct ADMIN_CTRL_PARAM content; +}; + +struct CMD_ADV_CONFIG_HEADER { + uint16_t u2Type; + uint16_t u2Len; +}; + +/* noise histogram related */ +enum ENUM_NOISE_HISTOGRAM_ACTION_T { + CMD_NOISE_HISTOGRAM_ENABLE = 1, + CMD_NOISE_HISTOGRAM_DISABLE, + CMD_NOISE_HISTOGRAM_RESET, + CMD_NOISE_HISTOGRAM_GET, +#if CFG_IPI_2CHAIN_SUPPORT + CMD_NOISE_HISTOGRAM_GET2 +#endif +}; +struct CMD_NOISE_HISTOGRAM_REPORT { + uint16_t u2Type; + uint16_t u2Len; + /* parameter */ + uint8_t ucAction; + uint8_t reserved[3]; + /* IPI_report */ + uint32_t u4IPI0; /* Power <= -92 */ + uint32_t u4IPI1; /* -92 < Power <= -89 */ + uint32_t u4IPI2; /* -89 < Power <= -86 */ + uint32_t u4IPI3; /* -86 < Power <= -83 */ + uint32_t u4IPI4; /* -83 < Power <= -80 */ + uint32_t u4IPI5; /* -80 < Power <= -75 */ + uint32_t u4IPI6; /* -75 < Power <= -70 */ + uint32_t u4IPI7; /* -70 < Power <= -65 */ + uint32_t u4IPI8; /* -65 < Power <= -60 */ + uint32_t u4IPI9; /* -60 < Power <= -55 */ + uint32_t u4IPI10; /* -55 < Power */ +}; +#endif + + + +#if CFG_SUPPORT_RDD_TEST_MODE +struct CMD_RDD_CH { + uint8_t ucRddTestMode; + uint8_t ucRddShutCh; + uint8_t ucRddStartCh; + uint8_t ucRddStopCh; + uint8_t ucRddDfs; + uint8_t ucReserved; + uint8_t ucReserved1; + uint8_t ucReserved2; +}; + +struct EVENT_RDD_STATUS { + uint8_t ucRddStatus; + uint8_t aucReserved[3]; +}; +#endif + +struct EVENT_ICAP_STATUS { + uint8_t ucRddStatus; + uint8_t aucReserved[3]; + uint32_t u4StartAddress; + uint32_t u4IcapSieze; +#if CFG_SUPPORT_QA_TOOL + uint32_t u4IcapContent; +#endif /* CFG_SUPPORT_QA_TOOL */ +}; + +#if CFG_SUPPORT_QA_TOOL +struct ADC_BUS_FMT { + uint32_t u4Dcoc0Q: 14; /* [13:0] */ + uint32_t u4Dcoc0I: 14; /* [27:14] */ + uint32_t u4DbgData1: 4; /* [31:28] */ + + uint32_t u4Dcoc1Q: 14; /* [45:32] */ + uint32_t u4Dcoc1I: 14; /* [46:59] */ + uint32_t u4DbgData2: 4; /* [63:60] */ + + uint32_t u4DbgData3; /* [95:64] */ +}; + +struct IQC_BUS_FMT { + int32_t u4Iqc0Q: 12; /* [11:0] */ + int32_t u4Iqc0I: 12; /* [23:12] */ + int32_t u4Na1: 8; /* [31:24] */ + + int32_t u4Iqc1Q: 12; /* [43:32] */ + int32_t u4Iqc1I: 12; /* [55:44] */ + int32_t u4Na2: 8; /* [63:56] */ + + int32_t u4Na3; /* [95:64] */ +}; + +struct IQC_160_BUS_FMT { + int32_t u4Iqc0Q1: 12; /* [11:0] */ + int32_t u4Iqc0I1: 12; /* [23:12] */ + uint32_t u4Iqc0Q0P1: 8; /* [31:24] */ + + int32_t u4Iqc0Q0P2: 4; /* [35:32] */ + int32_t u4Iqc0I0: 12; /* [47:36] */ + int32_t u4Iqc1Q1: 12; /* [59:48] */ + uint32_t u4Iqc1I1P1: 4; /* [63:60] */ + + int32_t u4Iqc1I1P2: 8; /* [71:64] */ + int32_t u4Iqc1Q0: 12; /* [83:72] */ + int32_t u4Iqc1I0: 12; /* [95:84] */ +}; + +struct SPECTRUM_BUS_FMT { + int32_t u4DcocQ: 12; /* [11:0] */ + int32_t u4DcocI: 12; /* [23:12] */ + int32_t u4LpfGainIdx: 4; /* [27:24] */ + int32_t u4LnaGainIdx: 2; /* [29:28] */ + int32_t u4AssertData: 2; /* [31:30] */ +}; + +struct PACKED_ADC_BUS_FMT { + uint32_t u4AdcQ0T2: 4; /* [19:16] */ + uint32_t u4AdcQ0T1: 4; /* [11:8] */ + uint32_t u4AdcQ0T0: 4; /* [3:0] */ + + uint32_t u4AdcI0T2: 4; /* [23:20] */ + uint32_t u4AdcI0T1: 4; /* [15:12] */ + uint32_t u4AdcI0T0: 4; /* [7:4] */ + + uint32_t u4AdcQ0T5: 4; /* [43:40] */ + uint32_t u4AdcQ0T4: 4; /* [35:32] */ + uint32_t u4AdcQ0T3: 4; /* [27:24] */ + + uint32_t u4AdcI0T5: 4; /* [47:44] */ + uint32_t u4AdcI0T4: 4; /* [39:36] */ + uint32_t u4AdcI0T3: 4; /* [31:28] */ + + uint32_t u4AdcQ1T2: 4; /* [19:16] */ + uint32_t u4AdcQ1T1: 4; /* [11:8] */ + uint32_t u4AdcQ1T0: 4; /* [3:0] */ + + uint32_t u4AdcI1T2: 4; /* [23:20] */ + uint32_t u4AdcI1T1: 4; /* [15:12] */ + uint32_t u4AdcI1T0: 4; /* [7:4] */ + + uint32_t u4AdcQ1T5: 4; /* [43:40] */ + uint32_t u4AdcQ1T4: 4; /* [35:32] */ + uint32_t u4AdcQ1T3: 4; /* [27:24] */ + + uint32_t u4AdcI1T5: 4; /* [47:44] */ + uint32_t u4AdcI1T4: 4; /* [39:36] */ + uint32_t u4AdcI1T3: 4; /* [31:28] */ +}; + +union ICAP_BUS_FMT { + struct ADC_BUS_FMT rAdcBusData; /* 12 bytes */ + struct IQC_BUS_FMT rIqcBusData; /* 12 bytes */ + struct IQC_160_BUS_FMT rIqc160BusData; /* 12 bytes */ + struct SPECTRUM_BUS_FMT rSpectrumBusData; /* 4 bytes */ + struct PACKED_ADC_BUS_FMT rPackedAdcBusData; /* 12 bytes */ +}; +#endif /* CFG_SUPPORT_QA_TOOL */ + +struct CMD_SET_TXPWR_CTRL { + int8_t c2GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0 */ + int8_t c2GHotspotPwrOffset; + int8_t c2GP2pPwrOffset; + int8_t c2GBowPwrOffset; + int8_t c5GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0 */ + int8_t c5GHotspotPwrOffset; + int8_t c5GP2pPwrOffset; + int8_t c5GBowPwrOffset; + /* TX power policy when concurrence + * in the same channel + * 0: Highest power has priority + * 1: Lowest power has priority + */ + uint8_t ucConcurrencePolicy; + int8_t acReserved1[3]; /* Must be zero */ + + /* Power limit by channel for all data rates */ + int8_t acTxPwrLimit2G[14]; /* Channel 1~14, Unit: 0.5dBm */ + int8_t acTxPwrLimit5G[4]; /* UNII 1~4 */ + int8_t acReserved2[2]; /* Must be zero */ +}; + +struct SSID_MATCH_SETS { + int32_t i4RssiThresold; + uint8_t aucSsid[32]; + uint8_t ucSsidLen; + uint8_t aucPadding_1[3]; +}; + +struct CMD_SCHED_SCAN_REQ { + uint8_t ucVersion; + uint8_t ucSeqNum; + uint8_t fgStopAfterIndication; + uint8_t ucSsidNum; + uint8_t ucMatchSsidNum; + uint8_t aucPadding_0; + uint16_t u2IELen; + struct PARAM_SSID auSsid[10]; + struct SSID_MATCH_SETS auMatchSsid[16]; + uint8_t ucChannelType; + uint8_t ucChnlNum; + uint8_t ucMspEntryNum; + uint8_t ucScnFuncMask; + struct CHANNEL_INFO aucChannel[64]; + uint16_t au2MspList[10]; + uint8_t aucPadding_3[64]; + + /* keep last */ + uint8_t aucIE[0]; /* MUST be the last for IE content */ +}; + +struct EVENT_SCHED_SCAN_DONE { + uint8_t ucSeqNum; + uint8_t ucStatus; + uint8_t aucReserved[2]; +}; + +struct CMD_HIF_CTRL { + uint8_t ucHifType; + uint8_t ucHifDirection; + uint8_t ucHifStop; + uint8_t ucHifSuspend; + uint8_t aucReserved2[32]; +}; + +enum ENUM_HIF_TYPE { + ENUM_HIF_TYPE_SDIO = 0x00, + ENUM_HIF_TYPE_USB = 0x01, + ENUM_HIF_TYPE_PCIE = 0x02, + ENUM_HIF_TYPE_GPIO = 0x03, +}; + +enum ENUM_HIF_DIRECTION { + ENUM_HIF_TX = 0x01, + ENUM_HIF_RX = 0x02, + ENUM_HIF_TRX = 0x03, +}; + +enum ENUM_HIF_TRAFFIC_STATUS { + ENUM_HIF_TRAFFIC_BUSY = 0x01, + ENUM_HIF_TRAFFIC_IDLE = 0x02, + ENUM_HIF_TRAFFIC_INVALID = 0x3, +}; + +struct EVENT_HIF_CTRL { + uint8_t ucHifType; + uint8_t ucHifTxTrafficStatus; + uint8_t ucHifRxTrafficStatus; + uint8_t ucHifSuspend; + uint8_t aucReserved2[32]; +}; + +#if CFG_SUPPORT_BUILD_DATE_CODE +struct CMD_GET_BUILD_DATE_CODE { + uint8_t aucReserved[4]; +}; + +struct EVENT_BUILD_DATE_CODE { + uint8_t aucDateCode[16]; +}; +#endif + +struct CMD_GET_STA_STATISTICS { + uint8_t ucIndex; + uint8_t ucFlags; + uint8_t ucReadClear; + uint8_t ucLlsReadClear; + uint8_t aucMacAddr[MAC_ADDR_LEN]; + uint8_t ucResetCounter; + uint8_t aucReserved1[1]; + uint8_t aucReserved2[16]; +}; + +/* per access category statistics */ +struct WIFI_WMM_AC_STAT_GET_FROM_FW { + uint32_t u4TxFailMsdu; + uint32_t u4TxRetryMsdu; +}; + +/* CFG_SUPPORT_WFD */ +struct EVENT_STA_STATISTICS { + /* Event header */ + /* UINT_16 u2Length; */ + /* Must be filled with 0x0001 (EVENT Packet) */ + /* UINT_16 u2Reserved1; */ + /* UINT_8 ucEID; */ + /* UINT_8 ucSeqNum; */ + /* UINT_8 aucReserved2[2]; */ + + /* Event Body */ + uint8_t ucVersion; + uint8_t aucReserved1[3]; + uint32_t u4Flags; /* Bit0: valid */ + + uint8_t ucStaRecIdx; + uint8_t ucNetworkTypeIndex; + uint8_t ucWTEntry; + uint8_t aucReserved4[1]; + + uint8_t ucMacAddr[MAC_ADDR_LEN]; + uint8_t ucPer; /* base: 128 */ + uint8_t ucRcpi; + + uint32_t u4PhyMode; /* SGI BW */ + uint16_t u2LinkSpeed; /* unit is 0.5 Mbits */ + uint8_t ucLinkQuality; + uint8_t ucLinkReserved; + + uint32_t u4TxCount; + uint32_t u4TxFailCount; + uint32_t u4TxLifeTimeoutCount; + uint32_t u4TxDoneAirTime; + /* Transmit in the air (wtbl) */ + uint32_t u4TransmitCount; + /* Transmit without ack/ba in the air (wtbl) */ + uint32_t u4TransmitFailCount; + + struct WIFI_WMM_AC_STAT_GET_FROM_FW + arLinkStatistics[AC_NUM]; /*link layer statistics */ + + uint8_t ucTemperature; + uint8_t ucSkipAr; + uint8_t ucArTableIdx; + uint8_t ucRateEntryIdx; + uint8_t ucRateEntryIdxPrev; + uint8_t ucTxSgiDetectPassCnt; + uint8_t ucAvePer; +#if (CFG_SUPPORT_RA_GEN == 0) + uint8_t aucArRatePer[AR_RATE_TABLE_ENTRY_MAX]; + uint8_t aucRateEntryIndex[AUTO_RATE_NUM]; +#else + uint32_t u4AggRangeCtrl_0; + uint32_t u4AggRangeCtrl_1; + uint8_t ucRangeType; + uint8_t aucReserved5[24]; +#endif + uint8_t ucArStateCurr; + uint8_t ucArStatePrev; + uint8_t ucArActionType; + uint8_t ucHighestRateCnt; + uint8_t ucLowestRateCnt; + uint16_t u2TrainUp; + uint16_t u2TrainDown; + uint32_t u4Rate1TxCnt; + uint32_t u4Rate1FailCnt; + struct TX_VECTOR_BBP_LATCH rTxVector[ENUM_BAND_NUM]; + struct MIB_INFO_STAT rMibInfo[ENUM_BAND_NUM]; + u_int8_t fgIsForceTxStream; + u_int8_t fgIsForceSeOff; +#if (CFG_SUPPORT_RA_GEN == 0) + uint8_t aucReserved6[17]; +#else + uint16_t u2RaRunningCnt; + uint8_t ucRaStatus; + uint8_t ucFlag; + uint8_t aucTxQuality[MAX_TX_QUALITY_INDEX]; + uint8_t ucTxRateUpPenalty; + uint8_t ucLowTrafficMode; + uint8_t ucLowTrafficCount; + uint8_t ucLowTrafficDashBoard; + uint8_t ucDynamicSGIState; + uint8_t ucDynamicSGIScore; + uint8_t ucDynamicBWState; + uint8_t ucDynamicGband256QAMState; + uint8_t ucVhtNonSpRateState; +#endif + uint8_t aucReserved[4]; +}; + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +struct EVENT_LTE_SAFE_CHN { + uint8_t ucVersion; + uint8_t aucReserved[3]; + uint32_t u4Flags; /* Bit0: valid */ + struct LTE_SAFE_CHN_INFO rLteSafeChn; +}; +#endif + +#if CFG_SUPPORT_SNIFFER +struct CMD_MONITOR_SET_INFO { + uint8_t ucEnable; + uint8_t ucBand; + uint8_t ucPriChannel; + uint8_t ucSco; + uint8_t ucChannelWidth; + uint8_t ucChannelS1; + uint8_t ucChannelS2; + uint8_t aucResv[9]; +}; +#endif + +struct CMD_STATS_LOG { + uint32_t u4DurationInMs; + uint8_t aucReserved[32]; +}; + +struct EVENT_WIFI_RDD_TEST { + uint32_t u4FuncIndex; + uint32_t u4FuncLength; + uint32_t u4Prefix; + uint32_t u4Count; + uint8_t ucRddIdx; + uint8_t aucReserve[3]; + uint8_t aucBuffer[0]; +}; + +#if CFG_SUPPORT_MSP +/* EVENT_ID_WLAN_INFO */ +struct EVENT_WLAN_INFO { + + struct PARAM_TX_CONFIG rWtblTxConfig; + struct PARAM_SEC_CONFIG rWtblSecConfig; + struct PARAM_KEY_CONFIG rWtblKeyConfig; + struct PARAM_PEER_RATE_INFO rWtblRateInfo; + struct PARAM_PEER_BA_CONFIG rWtblBaConfig; + struct PARAM_PEER_CAP rWtblPeerCap; + struct PARAM_PEER_RX_COUNTER_ALL rWtblRxCounter; + struct PARAM_PEER_TX_COUNTER_ALL rWtblTxCounter; +}; + +/* EVENT_ID_MIB_INFO */ +struct EVENT_MIB_INFO { + struct HW_MIB_COUNTER rHwMibCnt; + struct HW_MIB2_COUNTER rHwMib2Cnt; + struct HW_TX_AMPDU_METRICS rHwTxAmpduMts; + +}; +#endif +#if CFG_SUPPORT_GET_MCS_INFO +struct EVENT_TX_MCS_INFO { + uint16_t au2TxRateCode[MCS_INFO_SAMPLE_CNT]; + uint8_t aucTxRatePer[MCS_INFO_SAMPLE_CNT]; + uint8_t aucReserved[2]; +}; +#endif + +/*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ +struct EVENT_ACCESS_EFUSE { + + uint32_t u4Address; + uint32_t u4Valid; + uint8_t aucData[16]; + +}; + +struct EXT_EVENT_EFUSE_FREE_BLOCK { + uint8_t u2FreeBlockNum; + uint8_t ucVersion; /* 0: original format ; 1: modified format */ + uint8_t ucTotalBlockNum; /* Total Block */ + uint8_t ucReserved; +}; + +struct EXT_EVENT_GET_TX_POWER { + + uint8_t ucTxPwrType; + uint8_t ucEfuseAddr; + uint8_t ucTx0TargetPower; + uint8_t ucDbdcIdx; + +}; + +struct EXT_EVENT_RF_TEST_RESULT_T { + uint32_t u4FuncIndex; + uint32_t u4PayloadLength; + uint8_t aucEvent[0]; +}; + +struct EXT_EVENT_RBIST_DUMP_DATA_T { + uint32_t u4FuncIndex; + uint32_t u4PktNum; + uint32_t u4Bank; + uint32_t u4DataLength; + uint32_t u4WFCnt; + uint32_t u4SmplCnt; + uint32_t u4Reserved[6]; + uint32_t u4Data[256]; +}; + +struct EXT_EVENT_RBIST_CAP_STATUS_T { + uint32_t u4FuncIndex; + uint32_t u4CapDone; + uint32_t u4Reserved[15]; +}; + +struct EXT_EVENT_RECAL_DATA_T { + uint32_t u4FuncIndex; + uint32_t u4Type; /* 0 for string, 1 for int data */ + union { + uint8_t ucData[32]; + uint32_t u4Data[3]; + } u; +}; + + +struct CMD_SUSPEND_MODE_SETTING { + uint8_t ucBssIndex; + uint8_t ucEnableSuspendMode; + uint8_t ucMdtim; /* LP parameter */ + uint8_t ucDeviceSuspend; /* kernel 1:suspend 0:resume (reserved) */ + uint32_t u4CtrlFlag; /* b0:Dis ARPNS, b1:Dis REKEY, b2:DTIM policy */ + uint8_t ucWowSuspend; /* 0:updabye by bora origin policy,1:wow mdtim */ + uint8_t ucReserved1[3]; + uint8_t ucReserved2[56]; +}; + +struct EVENT_UPDATE_COEX_PHYRATE { + uint8_t ucVersion; + uint8_t aucReserved1[3]; /* 4 byte alignment */ + uint32_t u4Flags; + uint32_t au4PhyRateLimit[MAX_BSSID_NUM + 1]; + uint8_t ucSupportSisoOnly; + uint8_t ucWfPathSupport; + uint8_t aucReserved2[2]; /* 4 byte alignment */ +}; + +struct CMD_GET_TXPWR_TBL { + /* DWORD_0 - Common Part */ + uint8_t ucCmdVer; + uint8_t ucAction; + uint16_t u2CmdLen; + + /* DWORD_1 ~ x - Command Body */ + uint8_t ucDbdcIdx; + uint8_t aucReserved[3]; +}; + +struct EVENT_GET_TXPWR_TBL { + /* DWORD_0 - Common Part */ + uint8_t ucEvtVer; + uint8_t ucAction; + uint16_t u2EvtLen; + + /* DWORD_1 ~ x - Command Body */ + uint8_t ucCenterCh; + uint8_t aucReserved[3]; + struct POWER_LIMIT tx_pwr_tbl[TXPWR_TBL_NUM]; +}; + +#ifdef CFG_GET_TEMPURATURE + +struct EVENT_GET_THERMAL_SENSOR { + uint8_t u1ThermalCategory; + uint8_t u1Reserved[3]; + uint32_t u4SensorResult; +}; + +struct CMD_THERMAL_SENSOR_INFO { + uint8_t u1ThermalCtrlFormatId; + /* 0: get temperature, 1: get thermal sensor ADC */ + uint8_t u1ActionIdx; + uint8_t u1Reserved[2]; +}; + + +/** enum for EVENT */ +enum THERMAL_EVENT_CATEGORY { + THERMAL_EVENT_TEMPERATURE_INFO = 0x0, + TXPOWER_EVENT_THERMAL_SENSOR_SHOW_INFO = 0x1, + THERMAL_EVENT_NUM +}; + +/** enum for Get Thermal Sensor Info Action */ +enum THERMAL_SENSOR_INFO_ACTION { + THERMAL_SENSOR_INFO_TEMPERATURE = 0, + THERMAL_SENSOR_INFO_ADC, + THERMAL_SENSOR_INFO_NUM +}; + + +/** enum for CMD */ +enum THERMAL_ACTION_CATEGORY { + THERMAL_SENSOR_INFO_GET = 0x0, + THERMAL_MANUAL_CTRL = 0x1, + THERMAL_SENSOR_BASIC_INFO = 0x2, + THERMAL_ACTION_NUM +}; + +#endif + +/*#endif*/ +struct CMD_TDLS_PS_T { + /* 0: disable tdls power save; 1: enable tdls power save */ + uint8_t ucIsEnablePs; + uint8_t aucReserved[3]; +}; + +#if (CFG_SUPPORT_TXPOWER_INFO == 1) +struct CMD_TX_POWER_SHOW_INFO_T { + uint8_t ucPowerCtrlFormatId; + uint8_t ucTxPowerInfoCatg; + uint8_t ucBandIdx; + uint8_t ucReserved; +}; + +struct EXT_EVENT_TXPOWER_ALL_RATE_POWER_INFO_T { + uint8_t ucTxPowerCategory; + uint8_t ucBandIdx; + uint8_t ucChBand; + uint8_t ucReserved; + + /* Rate power info */ + struct FRAME_POWER_CONFIG_INFO_T rRatePowerInfo; + + /* tx Power Max/Min Limit info */ + int8_t icPwrMaxBnd; + int8_t icPwrMinBnd; + uint8_t ucReserved2; +}; +#endif + +struct CMD_SET_SCHED_SCAN_ENABLE { + uint8_t ucSchedScanAct; + uint8_t aucReserved[3]; +}; + +struct CMD_EVENT_LOG_UI_INFO { + uint32_t u4Version; + uint32_t u4LogLevel; + uint8_t aucReserved[4]; +}; + +struct EXT_EVENT_MAX_AMSDU_LENGTH_UPDATE { + uint8_t ucWlanIdx; + uint8_t ucAmsduLen; +}; + +struct EVENT_GET_IPI_INFO_T { + uint32_t au4IpiValue[11]; +}; + +#if (CFG_SUPPORT_PERF_IND == 1) +struct CMD_PERF_IND { + /* DWORD_0 - Common Part */ + uint8_t ucCmdVer; + uint8_t aucPadding0[1]; + uint16_t u2CmdLen; /* cmd size including common part and body. */ + /* DWORD_1 ~ x - Command Body */ + uint32_t u4VaildPeriod; /* in ms */ + /* Current State */ + uint32_t ulCurTxBytes[4]; /* in Bps */ + uint32_t ulCurRxBytes[4]; /* in Bps */ + uint16_t u2CurRxRate[4]; /* Unit 500 Kbps */ + uint8_t ucCurRxRCPI0[4]; + uint8_t ucCurRxRCPI1[4]; + uint8_t ucCurRxNss[4]; + uint32_t au4Reserve[63]; +}; +#endif + +#if CFG_SUPPORT_ADVANCE_CONTROL +struct CMD_KEEP_FULL_PWR { + uint8_t ucEnable; + uint8_t aucReserved[3]; +}; +#endif + +#ifdef CFG_SUPPORT_TIME_MEASURE +/* TM CMD/EVENT */ +enum ENUM_TM_EVENT_INDEX_T { + TM_EVENT_NULLBOT = 0, + TM_EVENT_TM_REPORT, + TM_EVENT_QUERY_TMSYNC, + TM_EVENT_QUERY_DISTANCE, + TM_EVENT_NUM +}; + +enum ENUM_TM_ACTION_CATEGORY { + TM_ACTION_NULLBOT = 0, + TM_ACTION_TMR_ENABLE, + TM_ACTION_TOAE_CAL, + TM_ACTION_START_FTM, + TM_ACTION_TMSYNC_QUERY, + TM_ACTION_DISTANCE_QUERY, + TM_ACTION_NUM +}; + +struct EVENT_TM_REPORT_T { + /* DWORD_0 - Common Part */ + uint8_t ucCmdVer; + uint8_t ucTmrEventIdx; + uint16_t u2CmdLen; /* Cmd size including common part and body */ + + /* DWORD 1/2 - common */ + uint8_t aucRttPeerAddr[6]; /* TM peer address */ + uint16_t u2NumOfValidResult; + + /* DWORD 3 - Distance */ + uint32_t u4DistanceCm; + /* DWORD 4~5 - Distance STDEV in burst */ + uint64_t u8DistStdevSq; + + /* DWORD 6~13 - Audio Sync */ + uint64_t u8Tsf; + int64_t i8ClockOffset; + int64_t i8ClkRateDiffRatioIn10ms; + uint64_t u8LastToA; + + uint8_t aucPadding2[64]; + +}; + +struct CMD_TM_ACTION_T { + /* DWORD_0 - Common Part */ + uint8_t ucCmdVer; + uint8_t ucTmCategory; + uint16_t u2CmdLen; /* Cmd size including common part and body */ + + /* DWORD 1/2 */ + uint8_t aucRttPeerAddr[6]; /* TM peer address */ + uint8_t ucFTMNum; + uint8_t ucMinDeltaIn100US; + + /* DWORD 3 - FTM parameter */ + uint8_t ucFTMBandwidth; + uint8_t fgFtmEnable; + uint8_t ucPadding1[2]; + + uint8_t aucPadding2[64]; + +}; + +#define CMD_TM_ACTION_START_FTM_LEN \ + OFFSET_OF(struct CMD_TM_ACTION_T, fgFtmEnable) +#define CMD_TM_ACTION_QUERY_LEN \ + OFFSET_OF(struct CMD_TM_ACTION_T, aucRttPeerAddr[0]) +#define TM_CMD_EVENT_VER 0 +#endif + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +void nicCmdEventQueryMcrRead(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventQueryCoexGetInfo(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventQueryCoexIso(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +#if CFG_SUPPORT_QA_TOOL +void nicCmdEventQueryRxStatistics(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +uint32_t nicTsfRawData2IqFmt(struct EVENT_DUMP_MEM *prEventDumpMem, + struct ICAP_INFO_T *prIcap); +uint32_t nicExtTsfRawData2IqFmt( + struct EXT_EVENT_RBIST_DUMP_DATA_T *prEventDumpMem, + struct ICAP_INFO_T *prIcap); + +int32_t GetIQData(struct ADAPTER *prAdapter, + int32_t **prIQAry, uint32_t *prDataLen, uint32_t u4IQ, + uint32_t u4GetWf1); + +#if CFG_SUPPORT_TX_BF +void nicCmdEventPfmuDataRead(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventPfmuTagRead(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); +#endif /* CFG_SUPPORT_TX_BF */ +#if CFG_SUPPORT_MU_MIMO +void nicCmdEventGetQd(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); +void nicCmdEventGetCalcLq(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); +void nicCmdEventGetCalcInitMcs(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); +#endif /* CFG_SUPPORT_MU_MIMO */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +void nicCmdEventQueryCalBackupV2(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); +#endif +#if 0 +void nicEventQueryMemDump(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf); +#endif + +void nicCmdEventQueryMemDump(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventQuerySwCtrlRead(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +void nicCmdEventQueryChipConfig(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +void nicCmdEventQueryRfTestATInfo(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +void nicCmdEventSetCommon(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventSetDisassociate(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +void nicCmdEventSetIpAddress(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventQueryLinkQuality(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +void nicCmdEventQueryLinkSpeed(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventQueryStatistics(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +void nicCmdEventEnterRfTest(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventLeaveRfTest(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventQueryMcastAddr(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventQueryEepromRead(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +void nicCmdEventSetMediaStreamMode(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +void nicCmdEventSetStopSchedScan(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +/* Statistics responder */ +void nicCmdEventQueryXmitOk(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventQueryRecvOk(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventQueryXmitError(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventQueryRecvError(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventQueryRecvNoBuffer(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +void nicCmdEventQueryRecvCrcError(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +void nicCmdEventQueryRecvErrorAlignment(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +void nicCmdEventQueryXmitOneCollision(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +void nicCmdEventQueryXmitMoreCollisions(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +void nicCmdEventQueryXmitMaxCollisions(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +/* for timeout check */ +void nicOidCmdTimeoutCommon(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo); + +void nicCmdTimeoutCommon(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo); + +void nicOidCmdEnterRFTestTimeout(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo); + +#if CFG_SUPPORT_BUILD_DATE_CODE +void nicCmdEventBuildDateCode(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); +#endif + +void nicCmdEventQueryStaStatistics(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +void nicCmdEventQueryBugReport(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +/* 4 Auto Channel Selection */ +void nicCmdEventQueryLteSafeChn(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); +#endif + +#if CFG_SUPPORT_BATCH_SCAN +void nicCmdEventBatchScanResult(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); +#endif + +#if CFG_SUPPORT_ADVANCE_CONTROL +void nicCmdEventQueryAdvCtrl(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); +#endif + +void nicEventRddPulseDump(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf); + +#if (CFG_SUPPORT_TXPOWER_INFO == 1) +void nicCmdEventQueryTxPowerInfo(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); +#endif + +void nicCmdEventQueryWlanInfo(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventQueryMibInfo(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicCmdEventQueryNicCapabilityV2(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); + +uint32_t nicCmdEventQueryNicTxResource(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); +uint32_t nicCmdEventQueryNicEfuseAddr(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); +uint32_t nicCmdEventQueryNicCoexFeature(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); +#if CFG_TCP_IP_CHKSUM_OFFLOAD +uint32_t nicCmdEventQueryNicCsumOffload(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); +#endif +uint32_t nicCfgChipCapHwVersion(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); +uint32_t nicCfgChipCapSwVersion(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); +uint32_t nicCfgChipCapMacAddr(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf); +uint32_t nicCfgChipCapPhyCap(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf); +uint32_t nicCfgChipCapMacCap(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf); +uint32_t nicCfgChipCapFrameBufCap(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); +uint32_t nicCfgChipCapBeamformCap(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); +uint32_t nicCfgChipCapLocationCap(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); +uint32_t nicCfgChipCapMuMimoCap(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); +uint32_t nicCfgChipCapBufferModeInfo(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); + +void nicExtEventICapIQData(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf); +void nicExtEventQueryMemDump(IN struct ADAPTER *prAdapter, + IN uint8_t *pucEventBuf); +void nicEventLinkQuality(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventLayer0ExtMagic(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventMicErrorInfo(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventScanDone(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventSchedScanDone(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventSleepyNotify(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventBtOverWifi(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventStatistics(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventWlanInfo(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventMibInfo(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventIpiInfo(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventBeaconTimeout(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventUpdateNoaParams(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventStaAgingTimeout(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventApObssStatus(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventRoamingStatus(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventSendDeauth(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventUpdateRddStatus(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventUpdateBwcsStatus(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventUpdateBcmDebug(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventAddPkeyDone(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventIcapDone(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +void nicEventCalAllDone(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +#endif + +void nicEventDebugMsg(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventTdls(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventRssiMonitor(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventDumpMem(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventAssertDump(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventHifCtrl(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventRddSendPulse(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +void nicEventUpdateCoexPhyrate(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +uint32_t nicEventQueryTxResource_v1(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); +uint32_t nicEventQueryTxResourceEntry(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); +uint32_t nicEventQueryTxResource(IN struct ADAPTER + *prAdapter, IN uint8_t *pucEventBuf); + +#if CFG_SUPPORT_ANT_DIV +void nicCmdEventAntDiv(IN struct ADAPTER + *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); +#endif + +#if (CFG_WOW_SUPPORT == 1) +void nicEventWakeUpReason(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +#endif +void nicCmdEventQueryCnmInfo(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); +void nicEventCnmInfo(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +#if CFG_SUPPORT_REPLAY_DETECTION +void nicCmdEventSetAddKey(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); +void nicOidCmdTimeoutSetAddKey(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo); +void nicEventGetGtkDataSync(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +#endif +void nicCmdEventGetTxPwrTbl(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +#ifdef CFG_GET_TEMPURATURE +void nicCmdEventGetTemperature(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); +#endif + +#if (CFG_SUPPORT_GET_MCS_INFO == 1) +void nicCmdEventQueryTxMcsInfo(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void nicEventTxMcsInfo(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent); +#endif + +#ifdef CFG_SUPPORT_TIME_MEASURE +void nicCmdEventGetTmReport(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); +#endif + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _NIC_CMD_EVENT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic_init_cmd_event.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic_init_cmd_event.h new file mode 100644 index 0000000000000..bdfcb70f1be94 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/nic_init_cmd_event.h @@ -0,0 +1,307 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + +#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 INIT_PKT_FT_CMD 0x2 +#define INIT_PKT_FT_PDA_FWDL 0x3 + +#define INIT_CMD_PQ_ID (0x8000) +#define INIT_CMD_PACKET_TYPE_ID (0xA0) + +#define INIT_CMD_PDA_PQ_ID (0xF800) +#define INIT_CMD_PDA_PACKET_TYPE_ID (0xA0) + +#if (CFG_UMAC_GENERATION >= 0x20) +#define TXD_Q_IDX_MCU_RQ0 0 +#define TXD_Q_IDX_MCU_RQ1 1 +#define TXD_Q_IDX_MCU_RQ2 2 +#define TXD_Q_IDX_MCU_RQ3 3 + +#define TXD_Q_IDX_PDA_FW_DL 0x1E + +/* DW0 Bit31 */ +#define TXD_P_IDX_LMAC 0 +#define TXD_P_IDX_MCU 1 + +/* DW1 Bit 14:13 */ +#define TXD_HF_NON_80211_FRAME 0x0 +#define TXD_HF_CMD 0x1 +#define TXD_HF_80211_NORMAL 0x2 +#define TXD_HF_80211_ENHANCEMENT 0x3 + +/* DW1 Bit 15 */ +#define TXD_FT_OFFSET 15 +#define TXD_FT_SHORT_FORMAT 0x0 +#define TXD_FT_LONG_FORMAT 0x1 + +/* DW1 Bit 16 */ +#define TXD_TXDLEN_OFFSET 16 +#define TXD_TXDLEN_1PAGE 0x0 +#define TXD_TXDLEN_2PAGE 0x1 + +/* DW1 Bit 25:24 */ +#define TXD_PKT_FT_CUT_THROUGH 0x0 +#define TXD_PKT_FT_STORE_FORWARD 0X1 +#define TXD_PKT_FT_CMD 0X2 +#define TXD_PKT_FT_PDA_FW 0X3 +#endif + +enum ENUM_INIT_CMD_ID { + INIT_CMD_ID_DOWNLOAD_CONFIG = 1, + INIT_CMD_ID_WIFI_START, + INIT_CMD_ID_ACCESS_REG, + INIT_CMD_ID_QUERY_PENDING_ERROR, + INIT_CMD_ID_PATCH_START, + INIT_CMD_ID_PATCH_WRITE, + INIT_CMD_ID_PATCH_FINISH, + INIT_CMD_ID_PATCH_SEMAPHORE_CONTROL = 0x10, + INIT_CMD_ID_HIF_LOOPBACK = 0x20, +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + INIT_CMD_ID_DECOMPRESSED_WIFI_START = 0xFF, +#endif + INIT_CMD_ID_NUM +}; + +enum ENUM_INIT_EVENT_ID { + INIT_EVENT_ID_CMD_RESULT = 1, + INIT_EVENT_ID_ACCESS_REG, + INIT_EVENT_ID_PENDING_ERROR, + INIT_EVENT_ID_PATCH_SEMA_CTRL +}; + +enum ENUM_INIT_PATCH_STATUS { + PATCH_STATUS_NO_SEMA_NEED_PATCH = 0, /* no SEMA, need patch */ + PATCH_STATUS_NO_NEED_TO_PATCH, /* patch is DL & ready */ + PATCH_STATUS_GET_SEMA_NEED_PATCH, /* get SEMA, need patch */ + PATCH_STATUS_RELEASE_SEMA /* release SEMA */ +}; + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/* commands */ +struct INIT_WIFI_CMD { + uint8_t ucCID; + uint8_t ucPktTypeID; /* Must be 0xA0 (CMD Packet) */ + uint8_t ucReserved; + uint8_t ucSeqNum; +#if 1 + /* padding fields, hw may auto modify this field */ + uint8_t ucD2B0Rev; + uint8_t ucExtenCID; /* Extend CID */ + uint8_t ucS2DIndex; /* Index for Src to Dst in CMD usage */ + uint8_t ucExtCmdOption; /* Extend CID option */ + + uint32_t au4D3toD7Rev[5]; /* padding fields */ +#endif + uint8_t aucBuffer[0]; +}; + +struct INIT_HIF_TX_HEADER { + uint16_t u2TxByteCount; /* Max value is over 2048 */ + uint16_t u2PQ_ID; /* Must be 0x8000 (Port1, Queue 0) */ +#if 1 + uint8_t ucWlanIdx; + uint8_t ucHeaderFormat; + uint8_t ucHeaderPadding; + uint8_t ucPktFt: 2; + uint8_t ucOwnMAC: 6; + uint32_t au4D2toD7Rev[6]; + + uint16_t u2Length; + uint16_t u2PqId; +#endif + struct INIT_WIFI_CMD rInitWifiCmd; +}; + +struct INIT_CMD_DOWNLOAD_CONFIG { + uint32_t u4Address; + uint32_t u4Length; + uint32_t u4DataMode; +}; + +#define START_OVERRIDE_START_ADDRESS BIT(0) +#define START_DELAY_CALIBRATION BIT(1) +#define START_WORKING_PDA_OPTION BIT(2) +#define START_CRC_CHECK BIT(3) +#define CHANGE_DECOMPRESSION_TMP_ADDRESS BIT(4) + +#if CFG_SUPPORT_COMPRESSION_FW_OPTION +#define WIFI_FW_DECOMPRESSION_FAILED 0xFF +struct INIT_CMD_WIFI_DECOMPRESSION_START { + uint32_t u4Override; + uint32_t u4Address; + uint32_t u4Region1length; + uint32_t u4Region2length; + uint32_t u4Region1Address; + uint32_t u4Region2Address; + uint32_t u4BlockSize; + uint32_t u4Region1CRC; + uint32_t u4Region2CRC; + uint32_t u4DecompressTmpAddress; +}; +#endif + +struct INIT_CMD_WIFI_START { + uint32_t u4Override; + uint32_t u4Address; +}; + +#define PATCH_GET_SEMA_CONTROL 1 +#define PATCH_RELEASE_SEMA_CONTROL 0 +struct INIT_CMD_PATCH_SEMA_CONTROL { + uint8_t ucGetSemaphore; + uint8_t aucReserved[3]; +}; + +struct INIT_CMD_PATCH_FINISH { + uint8_t ucCheckCrc; + uint8_t aucReserved[3]; +}; + +struct INIT_CMD_ACCESS_REG { + uint8_t ucSetQuery; + uint8_t aucReserved[3]; + uint32_t u4Address; + uint32_t u4Data; +}; + +/* Events */ +struct INIT_WIFI_EVENT { + uint16_t u2RxByteCount; + uint16_t u2PacketType; /* Must be filled with 0xE000 (EVENT Packet) */ + uint8_t ucEID; + uint8_t ucSeqNum; + uint8_t aucReserved[2]; + uint8_t aucBuffer[0]; +}; + +struct INIT_HIF_RX_HEADER { + struct INIT_WIFI_EVENT rInitWifiEvent; +}; + +struct INIT_EVENT_CMD_RESULT { + uint8_t ucStatus; /* 0: success */ + /* 1: rejected by invalid param */ + /* 2: rejected by incorrect CRC */ + /* 3: rejected by decryption failure */ + /* 4: unknown CMD */ + /* 5: timeout */ + uint8_t aucReserved[3]; +}; + +struct INIT_EVENT_ACCESS_REG { + uint32_t u4Address; + uint32_t u4Data; +}; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _NIC_INIT_CMD_EVENT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/p2p_precomp.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/p2p_precomp.h new file mode 100644 index 0000000000000..b4cfd5c45c282 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/p2p_precomp.h @@ -0,0 +1,247 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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" + +#include "nic_rate.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" + +#include "mt66xx_reg.h" + +#include "rlm.h" +#include "rlm_domain.h" +#include "rlm_protection.h" +#include "rlm_obss.h" +#include "rate.h" +#include "wnm.h" + +#include "aa_fsm.h" + +#include "cnm_timer.h" +#include "que_mgt.h" +#include "wmm.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_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 "rftest.h" + +#include "rsn.h" + +#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 + ****************************************************************************** + */ + +/****************************************************************************** + * 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 + ****************************************************************************** + */ + +#endif /*_P2P_PRECOMP_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/p2p_typedef.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/p2p_typedef.h new file mode 100644 index 0000000000000..f8a5cf91869c8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/p2p_typedef.h @@ -0,0 +1,246 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 + ****************************************************************************** + */ + +/****************************************************************************** + * M A C R O S + ****************************************************************************** + */ + +/****************************************************************************** + * D A T A T Y P E S + ****************************************************************************** + */ + +/* + * type definition of pointer to p2p structure + */ +/* typedef struct GL_P2P_INFO GL_P2P_INFO_T, *P_GL_P2P_INFO_T; */ +struct P2P_INFO; /* declare P2P_INFO_T */ + +struct P2P_FSM_INFO; /* declare P2P_FSM_INFO_T */ + +struct P2P_DEV_FSM_INFO; /* declare P2P_DEV_FSM_INFO_T */ + +struct P2P_ROLE_FSM_INFO; /* declare P2P_ROLE_FSM_INFO_T */ + +struct P2P_CONNECTION_SETTINGS; /* declare P2P_CONNECTION_SETTINGS_T */ + +/* Type definition for function pointer to p2p function*/ +typedef u_int8_t(*P2P_LAUNCH) (struct GLUE_INFO *prGlueInfo); + +typedef u_int8_t(*P2P_REMOVE) (struct GLUE_INFO *prGlueInfo, + u_int8_t fgIsWlanLaunched); + +typedef u_int8_t(*KAL_P2P_GET_CIPHER) (IN struct GLUE_INFO *prGlueInfo); + +typedef u_int8_t(*KAL_P2P_GET_TKIP_CIPHER) (IN struct GLUE_INFO *prGlueInfo); + +typedef u_int8_t(*KAL_P2P_GET_CCMP_CIPHER) (IN struct GLUE_INFO *prGlueInfo); + +typedef u_int8_t(*KAL_P2P_GET_WSC_MODE) (IN struct GLUE_INFO *prGlueInfo); + +typedef struct net_device *(*KAL_P2P_GET_DEV_HDLR) ( + struct GLUE_INFO *prGlueInfo); + +typedef void(*KAL_P2P_SET_MULTICAST_WORK_ITEM) (struct GLUE_INFO *prGlueInfo); + +typedef void(*P2P_NET_REGISTER) (struct GLUE_INFO *prGlueInfo); + +typedef void(*P2P_NET_UNREGISTER) (struct GLUE_INFO *prGlueInfo); + +typedef void(*KAL_P2P_UPDATE_ASSOC_INFO) (IN struct GLUE_INFO *prGlueInfo, + IN uint8_t *pucFrameBody, + IN uint32_t u4FrameBodyLen, + IN u_int8_t fgReassocRequest); + +typedef u_int8_t(*P2P_VALIDATE_AUTH) (IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN struct STA_RECORD **pprStaRec, + OUT uint16_t *pu2StatusCode); + +typedef u_int8_t(*P2P_VALIDATE_ASSOC_REQ) (IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + OUT uint16_t *pu4ControlFlags); + +typedef void(*P2P_RUN_EVENT_AAA_TX_FAIL) (IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +typedef u_int8_t(*P2P_PARSE_CHECK_FOR_P2P_INFO_ELEM) ( + IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, + OUT uint8_t *pucOuiType); + +typedef uint32_t(*P2P_RUN_EVENT_AAA_COMPLETE) (IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec); + +typedef void(*P2P_PROCESS_EVENT_UPDATE_NOA_PARAM) ( + IN struct ADAPTER *prAdapter, + uint8_t ucNetTypeIndex, + struct EVENT_UPDATE_NOA_PARAMS *prEventUpdateNoaParam); + +typedef void(*SCAN_P2P_PROCESS_BEACON_AND_PROBE_RESP) ( + IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint32_t *prStatus, + IN struct BSS_DESC *prBssDesc, + IN struct WLAN_BEACON_FRAME *prWlanBeaconFrame); + +typedef void(*P2P_RX_PUBLIC_ACTION_FRAME) (struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +typedef void(*RLM_RSP_GENERATE_OBSS_SCAN_IE) (struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo); + +typedef void(*RLM_UPDATE_BW_BY_CH_LIST_FOR_AP) (struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo); + +typedef void(*RLM_PROCESS_PUBLIC_ACTION) (struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); + +typedef void(*RLM_PROCESS_HT_ACTION) (struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb); + +typedef void(*RLM_UPDATE_PARAMS_FOR_AP) (struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, u_int8_t fgUpdateBeacon); + +typedef void(*RLM_HANDLE_OBSS_STATUS_EVENT_PKT) (struct ADAPTER *prAdapter, + struct EVENT_AP_OBSS_STATUS *prObssStatus); + +typedef u_int8_t(*P2P_FUNC_VALIDATE_PROBE_REQ) (IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + OUT uint32_t *pu4ControlFlags); + +typedef void(*RLM_BSS_INIT_FOR_AP) (struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo); + +typedef uint32_t(*P2P_GET_PROB_RSP_IE_TABLE_SIZE) (void); + +typedef uint8_t *(*P2P_BUILD_REASSOC_REQ_FRAME_COMMON_IES) ( + IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, IN uint8_t *pucBuffer); + +typedef void(*P2P_FUNC_DISCONNECT) (IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN u_int8_t fgSendDeauth, IN uint16_t u2ReasonCode); + +typedef void(*P2P_FSM_RUN_EVENT_RX_DEAUTH) (IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct SW_RFB *prSwRfb); + +typedef void(*P2P_FSM_RUN_EVENT_RX_DISASSOC) (IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct SW_RFB *prSwRfb); + +typedef u_int8_t(*P2P_FUN_IS_AP_MODE) (IN struct P2P_FSM_INFO *prP2pFsmInfo); + +typedef void(*P2P_FSM_RUN_EVENT_BEACON_TIMEOUT) (IN struct ADAPTER *prAdapter); + +typedef void(*P2P_FUNC_STORE_ASSOC_RSP_IE_BUFFER) ( + IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +typedef void(*P2P_GENERATE_P2P_IE) (IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo); + +typedef uint32_t(*P2P_CALCULATE_P2P_IE_LEN) (IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN struct STA_RECORD *prStaRec); + +/****************************************************************************** + * 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 /*CFG_ENABLE_WIFI_DIRECT */ + +#endif /* _P2P_TYPEDEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/precomp.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/precomp.h new file mode 100644 index 0000000000000..b531bad3ca9b7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/precomp.h @@ -0,0 +1,314 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + * 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. + */ + +#ifndef _PRECOMP_H +#define _PRECOMP_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +#ifdef __GNUC__ +#if (DBG == 0) +#pragma GCC diagnostic ignored "-Wformat" +#endif +#endif + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "hif_cmm.h" +#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" + +#include "rlm_obss.h" + +/* Dependency: rlm_obss.h (OBSS_SCAN_MIN_INTERVAL) */ +#include "cnm_timer.h" + +/* Dependency: nic_cmd_event.h (P_EVENT_CONNECTION_STATUS) + * cnm_timer.h (TIMER_T) + */ +#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 "nic_umac.h" + +#include "bss.h" + +#include "nic_rate.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 "wlan_lib.h" +#include "wlan_oid.h" +#include "wlan_bow.h" + +#include "fw_dl.h" + +#if CFG_ENABLE_WIFI_DIRECT +#include "wlan_p2p.h" +#endif + +#include "hal.h" + +#include "mt66xx_reg.h" + +#include "connac_reg.h" +#include "connac_dmashdl.h" +#include "cmm_asic_connac.h" + +#include "rlm.h" +#include "rlm_domain.h" +#include "rlm_protection.h" +#include "rate.h" +#include "wnm.h" + +#include "qosmap.h" + +#include "aa_fsm.h" + +#include "que_mgt.h" + +#include "wmm.h" +#if CFG_ENABLE_BT_OVER_WIFI +#include "bow.h" +#include "bow_fsm.h" +#endif + +#include "pwr_mgt.h" + +#if (CFG_SUPPORT_STATISTICS == 1) +#include "stats.h" +#endif /* CFG_SUPPORT_STATISTICS */ + +#include "cnm.h" +/* Dependency: aa_fsm.h (ENUM_AA_STATE_T), p2p_fsm.h + * (WPS_ATTRI_MAX_LEN_DEVICE_NAME) + */ +#include "cnm_mem.h" +#include "cnm_scan.h" + +#if CFG_ENABLE_WIFI_DIRECT +#include "p2p_rlm_obss.h" +#include "p2p_bss.h" +#include "p2p.h" + +#include "p2p_rlm.h" +#include "p2p_assoc.h" +#include "p2p_ie.h" +#include "p2p_role.h" + +#include "p2p_func.h" +#include "p2p_scan.h" +#include "p2p_dev.h" +#include "p2p_fsm.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" + +#include "rsn.h" + +#if CFG_SUPPORT_WAPI +#include "wapi.h" +#endif + +/* Support AP Selection */ +#include "ap_selection.h" + +/*------------------------------------------------------------------------------ + * NVRAM structure + *------------------------------------------------------------------------------ + */ +#include "CFG_Wifi_File.h" + +#if CFG_ENABLE_WIFI_DIRECT +#include "gl_p2p_kal.h" +#endif + +#if CFG_SUPPORT_TDLS +#include "tdls.h" +#endif + +#if CFG_SUPPORT_QA_TOOL +#include "gl_qa_agent.h" +#include "gl_ate_agent.h" +#endif +/*------------------------------------------------------------------------------ + * Memory Prealloc + *------------------------------------------------------------------------------ + */ +#ifdef CFG_PREALLOC_MEMORY +#include "prealloc.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/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/pwr_mgt.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/pwr_mgt.h new file mode 100644 index 0000000000000..d7a93239e6e0b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/pwr_mgt.h @@ -0,0 +1,156 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + +#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 + +#define LP_OWN_BACK_TOTAL_DELAY_MS 2048 /* exponential of 2 */ +#define LP_OWN_BACK_LOOP_DELAY_MS 1 /* exponential of 2 */ +#define LP_OWN_REQ_CLR_INTERVAL_MS 200 +#define LP_OWN_BACK_FAILED_RETRY_CNT 5 +#define LP_OWN_BACK_FAILED_LOG_SKIP_MS 2000 +#define LP_OWN_BACK_FAILED_RESET_CNT 5 +#define LP_OWN_BACK_FAILED_DBGCR_POLL_ROUND 5 +#define LP_DBGCR_POLL_ROUND 1 +#define LP_OWN_BACK_LOOP_DELAY_MIN_US 900 +#define LP_OWN_BACK_LOOP_DELAY_MAX_US 1000 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +struct PM_PROFILE_SETUP_INFO { + /* Profile setup */ + /* 0: AC_BE, 1: AC_BK, 2: AC_VI, 3: AC_VO */ + uint8_t ucBmpDeliveryAC; + /* 0: AC_BE, 1: AC_BK, 2: AC_VI, 3: AC_VO */ + uint8_t ucBmpTriggerAC; + + uint8_t ucUapsdSp; /* Number of triggered packets in UAPSD */ + +}; + +/******************************************************************************* + * P U B 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) \ + { \ + nicpmSetDriverOwn(_prAdapter); \ + } + +#define RECLAIM_POWER_CONTROL_TO_PM(_prAdapter, _fgEnableGINT_in_IST) \ + { \ + nicpmSetFWOwn(_prAdapter, _fgEnableGINT_in_IST); \ + } +#endif + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _PWR_MGT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/queue.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/queue.h new file mode 100644 index 0000000000000..9e89512acba9c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/queue.h @@ -0,0 +1,241 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + +#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 */ +struct QUE_ENTRY { + struct QUE_ENTRY *prNext; + struct QUE_ENTRY + *prPrev; /* For Rx buffer reordering used only */ +}; + +/* Singly Queue Structures - Queue Part */ +struct QUE { + struct QUE_ENTRY *prHead; + struct QUE_ENTRY *prTail; + uint32_t u4NumElem; +}; + +/******************************************************************************* + * P U B 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 MAXNUM_TDLS_PEER 4 + +#define QUEUE_INITIALIZE(prQueue) \ + { \ + (prQueue)->prHead = (struct QUE_ENTRY *)NULL; \ + (prQueue)->prTail = (struct QUE_ENTRY *)NULL; \ + (prQueue)->u4NumElem = 0; \ + } + +#define QUEUE_IS_EMPTY(prQueue) \ + (((struct QUE *)(prQueue))->prHead == (struct QUE_ENTRY *)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 == (struct QUE_ENTRY *)NULL) { \ + (prQueue)->prTail = (prQueueEntry); \ + } \ + ((prQueue)->u4NumElem)++; \ + } + +#define QUEUE_INSERT_TAIL(prQueue, prQueueEntry) \ + { \ + ASSERT(prQueue); \ + ASSERT(prQueueEntry); \ + (prQueueEntry)->prNext = (struct QUE_ENTRY *)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 = \ + ((struct QUE_ENTRY *)(prQueueEntry))->prNext; \ + if ((prQueue)->prHead == (struct QUE_ENTRY *)NULL) { \ + (prQueue)->prTail = (struct QUE_ENTRY *)NULL; \ + } \ + ((struct QUE_ENTRY *)(prQueueEntry))->prNext = \ + (struct QUE_ENTRY *)NULL; \ + ((prQueue)->u4NumElem)--; \ + } \ + } + +#define QUEUE_MOVE_ALL(prDestQueue, prSrcQueue) \ + { \ + ASSERT(prDestQueue); \ + ASSERT(prSrcQueue); \ + *(struct QUE *)prDestQueue = *(struct QUE *)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); \ + } \ + } + +#define QUEUE_CONCATENATE_QUEUES_HEAD(prDestQueue, prSrcQueue) \ + { \ + ASSERT(prDestQueue); \ + ASSERT(prSrcQueue); \ + if ((prSrcQueue)->u4NumElem > 0) { \ + ((prSrcQueue)->prTail)->prNext = \ + (prDestQueue)->prHead; \ + (prDestQueue)->prHead = (prSrcQueue)->prHead; \ + ((prDestQueue)->u4NumElem) += \ + ((prSrcQueue)->u4NumElem); \ + if ((prDestQueue)->prTail == NULL) { \ + (prDestQueue)->prTail = (prSrcQueue)->prTail; \ + } \ + QUEUE_INITIALIZE(prSrcQueue); \ + } \ + } + +/******************************************************************************* + * E X T E R N A L D A T A + ******************************************************************************* + */ +extern uint8_t g_arTdlsLink[MAXNUM_TDLS_PEER]; + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +#endif /* _QUEUE_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/rftest.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/rftest.h new file mode 100644 index 0000000000000..b516f068646d8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/rftest.h @@ -0,0 +1,434 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: include/rftest.h + */ + +/*! \file "rftest.h" + * \brief definitions for RF Productino test + * + */ + +#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 \ + ((uint16_t)(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 */ +enum ENUM_RF_AT_FUNCID { + 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, + RF_AT_FUNCID_PWR_DETECTOR, + RF_AT_FUNCID_WBRSSI_IBSSI, + + /* 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, + RF_AT_FUNCID_SET_TA, + RF_AT_FUNCID_SET_RX_MATCH_RULE, + + /* 80211AC & Jmode */ + RF_AT_FUNCID_SET_CBW = 71, + RF_AT_FUNCID_SET_DBW, + RF_AT_FUNCID_SET_PRIMARY_CH, + RF_AT_FUNCID_SET_ENCODE_MODE, + RF_AT_FUNCID_SET_J_MODE, + + /* ICAP command */ + RF_AT_FUNCID_SET_ICAP_CONTENT = 80, + RF_AT_FUNCID_SET_ICAP_MODE, + RF_AT_FUNCID_SET_ICAP_STARTCAP, + RF_AT_FUNCID_SET_ICAP_SIZE = 83, + RF_AT_FUNCID_SET_ICAP_TRIGGER_OFFSET, + RF_AT_FUNCID_QUERY_ICAP_DUMP_FILE = 85, + +#if CFG_SUPPORT_QA_TOOL + /* 2G 5G Band */ + RF_AT_FUNCID_SET_BAND = 90, + + /* Reset Counter */ + RF_AT_FUNCID_RESETTXRXCOUNTER = 91, + + /* FAGC RSSI Path */ + RF_AT_FUNCID_FAGC_RSSI_PATH = 92, + + /* Set RX Filter Packet Length */ + RF_AT_FUNCID_RX_FILTER_PKT_LEN = 93, + + /* Tone */ + RF_AT_FUNCID_SET_TONE_RF_GAIN = 96, + RF_AT_FUNCID_SET_TONE_DIGITAL_GAIN = 97, + RF_AT_FUNCID_SET_TONE_TYPE = 98, + RF_AT_FUNCID_SET_TONE_DC_OFFSET = 99, + RF_AT_FUNCID_SET_TONE_BW = 100, + + /* MT6632 Add */ + RF_AT_FUNCID_SET_MAC_HEADER = 101, + RF_AT_FUNCID_SET_SEQ_CTRL = 102, + RF_AT_FUNCID_SET_PAYLOAD = 103, + RF_AT_FUNCID_SET_DBDC_BAND_IDX = 104, + RF_AT_FUNCID_SET_BYPASS_CAL_STEP = 105, + + /* Set RX Path */ + RF_AT_FUNCID_SET_RX_PATH = 106, + + /* Set Frequency Offset */ + RF_AT_FUNCID_SET_FRWQ_OFFSET = 107, + + /* Get Frequency Offset */ + RF_AT_FUNCID_GET_FREQ_OFFSET = 108, + + /* Set RXV Debug Index */ + RF_AT_FUNCID_SET_RXV_INDEX = 109, + + /* Set Test Mode DBDC Enable */ + RF_AT_FUNCID_SET_DBDC_ENABLE = 110, + + /* Get Test Mode DBDC Enable */ + RF_AT_FUNCID_GET_DBDC_ENABLE = 111, + + /* Set ICAP Ring Capture */ + RF_AT_FUNCID_SET_ICAP_RING = 112, + + /* Set TX Path */ + RF_AT_FUNCID_SET_TX_PATH = 113, + + /* Set Nss */ + RF_AT_FUNCID_SET_NSS = 114, + + /* Set TX Antenna Mask */ + RF_AT_FUNCID_SET_ANTMASK = 115, + + /* TMR set command */ + RF_AT_FUNCID_SET_TMR_ROLE = 116, + RF_AT_FUNCID_SET_TMR_MODULE = 117, + RF_AT_FUNCID_SET_TMR_DBM = 118, + RF_AT_FUNCID_SET_TMR_ITER = 119, + + /* Set ADC For IRR Feature */ + RF_AT_FUNCID_SET_ADC = 120, + + /* Set RX Gain For IRR Feature */ + RF_AT_FUNCID_SET_RX_GAIN = 121, + + /* Set TTG For IRR Feature */ + RF_AT_FUNCID_SET_TTG = 122, + + /* Set TTG ON/OFF For IRR Feature */ + RF_AT_FUNCID_TTG_ON_OFF = 123, + + /* Set TSSI for QA Tool Setting */ + RF_AT_FUNCID_SET_TSSI = 124, + + /* Set Recal Cal Step */ + RF_AT_FUNCID_SET_RECAL_CAL_STEP = 125, + + /* Set iBF/eBF enable */ + RF_AT_FUNCID_SET_IBF_ENABLE = 126, + RF_AT_FUNCID_SET_EBF_ENABLE = 127, + + /* Set MPS Setting */ + RF_AT_FUNCID_SET_MPS_SIZE = 128, + RF_AT_FUNCID_SET_MPS_SEQ_DATA = 129, + RF_AT_FUNCID_SET_MPS_PAYLOAD_LEN = 130, + RF_AT_FUNCID_SET_MPS_PKT_CNT = 131, + RF_AT_FUNCID_SET_MPS_PWR_GAIN = 132, + RF_AT_FUNCID_SET_MPS_NSS = 133, + RF_AT_FUNCID_SET_MPS_PACKAGE_BW = 134 +#endif +}; + +/* Command */ +enum ENUM_RF_AT_COMMAND { + RF_AT_COMMAND_STOPTEST = 0, + RF_AT_COMMAND_STARTTX, + RF_AT_COMMAND_STARTRX, + RF_AT_COMMAND_RESET, + RF_AT_COMMAND_OUTPUT_POWER, /* Payload */ + /* Local freq is renamed to Local leakage */ + RF_AT_COMMAND_LO_LEAKAGE, + /* OFDM (LTF/STF), CCK (PI,PI/2) */ + RF_AT_COMMAND_CARRIER_SUPPR, + RF_AT_COMMAND_TRX_IQ_CAL, + RF_AT_COMMAND_TSSI_CAL, + RF_AT_COMMAND_DPD_CAL, + RF_AT_COMMAND_CW, + RF_AT_COMMAND_ICAP, + RF_AT_COMMAND_RDD, + RF_AT_COMMAND_CH_SWITCH_FOR_ICAP, + RF_AT_COMMAND_RESET_DUMP_NAME, + RF_AT_COMMAND_SINGLE_TONE, + RF_AT_COMMAND_RDD_OFF, + RF_AT_COMMAND_NUM +}; + +/* Preamble */ +enum ENUM_RF_AT_PREAMBLE { + RF_AT_PREAMBLE_NORMAL = 0, + RF_AT_PREAMBLE_CCK_SHORT, + RF_AT_PREAMBLE_11N_MM, + RF_AT_PREAMBLE_11N_GF, + RF_AT_PREAMBLE_11AC, + RF_AT_PREAMBLE_NUM +}; + +/* Ack Policy */ +enum ENUM_RF_AT_ACK_POLICY { + 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 ENUM_RF_AUTOTEST_STATE { + 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 +}; + +/******************************************************************************* + * P U B 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 + ******************************************************************************* + */ + +uint32_t rftestSetATInfo(IN struct ADAPTER *prAdapter, + uint32_t u4FuncIndex, uint32_t u4FuncData); + +uint32_t +rftestQueryATInfo(IN struct ADAPTER *prAdapter, + uint32_t u4FuncIndex, uint32_t u4FuncData, + OUT void *pvQueryBuffer, IN uint32_t u4QueryBufferLen); + +uint32_t rftestSetFrequency(IN struct ADAPTER *prAdapter, + IN uint32_t u4FreqInKHz, IN uint32_t *pu4SetInfoLen); + +#endif /* _RFTEST_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/typedef.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/typedef.h new file mode 100644 index 0000000000000..2fb0ff00bde7c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/typedef.h @@ -0,0 +1,204 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: include/typedef.h + */ + +/*! \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. + */ + +#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 ((uint32_t) 0x00000000L) +#define WLAN_STATUS_PENDING ((uint32_t) 0x00000103L) +#define WLAN_STATUS_NOT_ACCEPTED ((uint32_t) 0x00010003L) + +#define WLAN_STATUS_MEDIA_CONNECT ((uint32_t) 0x4001000BL) +#define WLAN_STATUS_MEDIA_DISCONNECT ((uint32_t) 0x4001000CL) +#define WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY ((uint32_t) 0x4001000DL) +#define WLAN_STATUS_MEDIA_SPECIFIC_INDICATION ((uint32_t) 0x40010012L) + +#define WLAN_STATUS_SCAN_COMPLETE ((uint32_t) 0x60010001L) +#define WLAN_STATUS_MSDU_OK ((uint32_t) 0x60010002L) + +/* TODO(Kevin): double check if 0x60010001 & 0x60010002 is proprietary */ +#define WLAN_STATUS_ROAM_OUT_FIND_BEST ((uint32_t) 0x60010101L) +#define WLAN_STATUS_ROAM_DISCOVERY ((uint32_t) 0x60010102L) + +#define WLAN_STATUS_FAILURE ((uint32_t) 0xC0000001L) +#define WLAN_STATUS_RESOURCES ((uint32_t) 0xC000009AL) +#define WLAN_STATUS_NOT_SUPPORTED ((uint32_t) 0xC00000BBL) + +#define WLAN_STATUS_MULTICAST_FULL ((uint32_t) 0xC0010009L) +#define WLAN_STATUS_INVALID_PACKET ((uint32_t) 0xC001000FL) +#define WLAN_STATUS_ADAPTER_NOT_READY ((uint32_t) 0xC0010011L) +#define WLAN_STATUS_NOT_INDICATING ((uint32_t) 0xC0010013L) +#define WLAN_STATUS_INVALID_LENGTH ((uint32_t) 0xC0010014L) +#define WLAN_STATUS_INVALID_DATA ((uint32_t) 0xC0010015L) +#define WLAN_STATUS_BUFFER_TOO_SHORT ((uint32_t) 0xC0010016L) +#define WLAN_STATUS_BWCS_UPDATE ((uint32_t) 0xC0010017L) + +#define WLAN_STATUS_JOIN_FAILURE ((uint32_t) 0xc0010018L) + +/* NIC status flags */ +#define ADAPTER_FLAG_HW_ERR 0x00400000 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +/* Type definition for GLUE_INFO structure */ +struct GLUE_INFO; /* declare GLUE_INFO_T */ + +/* Type definition for WLAN STATUS */ + +/* Type definition for ADAPTER structure */ +struct ADAPTER; /* declare ADAPTER_T */ + +/* Type definition for MESSAGE HEADER structure */ +struct MSG_HDR; /* declare MSG_HDR_T */ + +/* Type definition for Pointer to OS Native Packet */ + +/* Type definition for WLAN configuration */ +struct WLAN_CFG; /* declare WLAN_CFG_T */ + +struct WLAN_CFG_REC; /* declare WLAN_CFG_REC_T */ + + +/* Type definition for WLAN configuration entry */ +struct WLAN_CFG_ENTRY; /* declare WLAN_CFG_ENTRY_T */ + +/* Type definition for WLAN configuration callback */ +typedef uint32_t(*WLAN_CFG_SET_CB) (struct ADAPTER + *prAdapter, + uint8_t *pucKey, + uint8_t *pucValue, + void *pPrivate, + uint32_t u4Flags); + +/* Type definition for STA_RECORD_T structure to handle the connectivity + * and packet reception for a particular STA. + */ +struct STA_RECORD; /* declare 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. + */ +struct CMD_INFO; /* declare CMD_INFO_T */ + +/* Following typedef should be removed later, because Glue Layer + * should not be aware of following data type. + */ +struct SW_RFB; /* declare SW_RFB_T */ + +struct MSDU_INFO; /* declare MSDU_INFO_T */ + +struct REG_ENTRY; /* declare REG_ENTRY_T */ + +/* IST handler definition */ +typedef void(*IST_EVENT_FUNCTION) (struct ADAPTER *); + +/* Type definition for function pointer of timer handler */ +typedef void(*PFN_TIMER_CALLBACK) (IN struct GLUE_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 + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +#endif /* _TYPEDEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/wlan_bow.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/wlan_bow.h new file mode 100644 index 0000000000000..1c8a63625264e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/wlan_bow.h @@ -0,0 +1,302 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +#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 + +extern uint32_t g_arBowRevPalPacketTime[32]; + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + +struct BOW_TABLE { + uint8_t ucAcquireID; + u_int8_t fgIsValid; + enum ENUM_BOW_DEVICE_STATE eState; + uint8_t aucPeerAddress[6]; + /* UINT_8 ucRole; */ + /* UINT_8 ucChannelNum; */ + uint16_t u2Reserved; +}; + +typedef uint32_t(*PFN_BOW_CMD_HANDLE) (struct ADAPTER *, struct BT_OVER_WIFI_COMMAND *); + +struct BOW_CMD { + uint8_t uCmdID; + PFN_BOW_CMD_HANDLE pfCmdHandle; +}; + +struct BOW_EVENT_ACTIVITY_REPORT { + uint8_t ucReason; + uint8_t aucReserved; + uint8_t aucPeerAddress[6]; +}; + +/* +*ucReason: 0: success +* 1: general failure +* 2: too much time (> 2/3 second totally) requested for scheduling. +* Others: reserved. +*/ + +struct BOW_EVENT_SYNC_TSF { + uint64_t u4TsfTime; + uint32_t u4TsfSysTime; + uint32_t u4ScoTime; + uint32_t u4ScoSysTime; +}; + +struct BOW_ACTIVITY_REPORT_BODY { + uint32_t u4StartTime; + uint32_t u4Duration; + uint32_t u4Periodicity; +}; + +struct BOW_ACTIVITY_REPORT { + uint8_t aucPeerAddress[6]; + uint8_t ucScheduleKnown; + uint8_t ucNumReports; + struct BOW_ACTIVITY_REPORT_BODY arBowActivityReportBody[MAX_ACTIVITY_REPORT]; +}; + +/******************************************************************************* +* 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 */ +/*--------------------------------------------------------------*/ +uint32_t +wlanoidSendSetQueryBowCmd(IN struct ADAPTER *prAdapter, + uint8_t ucCID, + IN uint8_t ucBssIdx, + u_int8_t fgSetQuery, + u_int8_t fgNeedResp, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + uint32_t u4SetQueryInfoLen, uint8_t *pucInfoBuffer, IN uint8_t ucSeqNumber); + +/*--------------------------------------------------------------*/ +/* Command Dispatcher */ +/*--------------------------------------------------------------*/ +uint32_t wlanbowHandleCommand(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd); + +/*--------------------------------------------------------------*/ +/* Routines to handle command */ +/*--------------------------------------------------------------*/ +uint32_t bowCmdGetMacStatus(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd); + +uint32_t bowCmdSetupConnection(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd); + +uint32_t bowCmdDestroyConnection(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd); + +uint32_t bowCmdSetPTK(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd); + +uint32_t bowCmdReadRSSI(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd); + +uint32_t bowCmdReadLinkQuality(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd); + +uint32_t bowCmdShortRangeMode(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd); + +uint32_t bowCmdGetChannelList(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd); + +void wlanbowCmdEventSetStatus(IN struct ADAPTER *prAdapter, IN struct BT_OVER_WIFI_COMMAND *prCmd, IN uint8_t ucEventBuf); + +/*--------------------------------------------------------------*/ +/* Callbacks for event indication */ +/*--------------------------------------------------------------*/ +void wlanbowCmdEventSetCommon(IN struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void wlanbowCmdEventLinkConnected(IN struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void wlanbowCmdEventLinkDisconnected(IN struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void wlanbowCmdEventSetSetupConnection(IN struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void wlanbowCmdEventReadLinkQuality(IN struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +void wlanbowCmdEventReadRssi(IN struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf); + +uint8_t bowInit(IN struct ADAPTER *prAdapter); + +void bowUninit(IN struct ADAPTER *prAdapter); + +void wlanbowCmdTimeoutHandler(IN struct ADAPTER *prAdapter, IN struct CMD_INFO *prCmdInfo); + +void bowStopping(IN struct ADAPTER *prAdapter); + +void bowStarting(IN struct ADAPTER *prAdapter); + +void bowAssignSsid(IN uint8_t *pucSsid, IN uint8_t *pucSsidLen); + +u_int8_t bowValidateProbeReq(IN struct ADAPTER *prAdapter, IN struct SW_RFB *prSwRfb, OUT uint32_t *pu4ControlFlags); + +void bowSendBeacon(IN struct ADAPTER *prAdapter, unsigned long ulParamPtr); + +void bowResponderScan(IN struct ADAPTER *prAdapter); + +void bowResponderScanDone(IN struct ADAPTER *prAdapter, IN struct MSG_HDR *prMsgHdr); + +void bowResponderCancelScan(IN struct ADAPTER *prAdapter, IN u_int8_t fgIsChannelExtention); + +void bowResponderJoin(IN struct ADAPTER *prAdapter, struct BSS_DESC *prBssDesc); + +void bowFsmRunEventJoinComplete(IN struct ADAPTER *prAdapter, IN struct MSG_HDR *prMsgHdr); + +void +bowIndicationOfMediaStateToHost(IN struct ADAPTER *prAdapter, + enum ENUM_PARAM_MEDIA_STATE eConnectionState, u_int8_t fgDelayIndication); + +void bowRunEventAAATxFail(IN struct ADAPTER *prAdapter, IN struct STA_RECORD *prStaRec); + +uint32_t bowRunEventAAAComplete(IN struct ADAPTER *prAdapter, IN struct STA_RECORD *prStaRec); + +uint32_t bowRunEventRxDeAuth(IN struct ADAPTER *prAdapter, IN struct STA_RECORD *prStaRec, IN struct SW_RFB *prSwRfb); + +void bowDisconnectLink(IN struct ADAPTER *prAdapter, IN struct MSDU_INFO *prMsduInfo, IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +u_int8_t bowValidateAssocReq(IN struct ADAPTER *prAdapter, IN struct SW_RFB *prSwRfb, OUT uint16_t *pu2StatusCode); + +u_int8_t +bowValidateAuth(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, IN struct STA_RECORD **pprStaRec, OUT uint16_t *pu2StatusCode); + +void bowRunEventChGrant(IN struct ADAPTER *prAdapter, IN struct MSG_HDR *prMsgHdr); + +void bowRequestCh(IN struct ADAPTER *prAdapter); + +void bowReleaseCh(IN struct ADAPTER *prAdapter); + +void bowChGrantedTimeout(IN struct ADAPTER *prAdapter, IN unsigned long ulParamPtr); + +u_int8_t bowNotifyAllLinkDisconnected(IN struct ADAPTER *prAdapter); + +u_int8_t bowCheckBowTableIfVaild(IN struct ADAPTER *prAdapter, IN uint8_t aucPeerAddress[6]); + +u_int8_t bowGetBowTableContent(IN struct ADAPTER *prAdapter, IN uint8_t ucBowTableIdx, OUT struct BOW_TABLE *prBowTable); + +u_int8_t +bowGetBowTableEntryByPeerAddress(IN struct ADAPTER *prAdapter, IN uint8_t aucPeerAddress[6], OUT uint8_t *pucBowTableIdx); + +u_int8_t bowGetBowTableFreeEntry(IN struct ADAPTER *prAdapter, OUT uint8_t *pucBowTableIdx); + +enum ENUM_BOW_DEVICE_STATE bowGetBowTableState(IN struct ADAPTER *prAdapter, IN uint8_t aucPeerAddress[6]); + +u_int8_t bowSetBowTableState(IN struct ADAPTER *prAdapter, IN uint8_t aucPeerAddress[6], IN enum ENUM_BOW_DEVICE_STATE eState); + +u_int8_t bowSetBowTableContent(IN struct ADAPTER *prAdapter, IN uint8_t ucBowTableIdx, IN struct BOW_TABLE *prBowTable); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif +#endif /* _WLAN_BOW_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/wlan_lib.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/wlan_lib.h new file mode 100644 index 0000000000000..5d6e27909b778 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/wlan_lib.h @@ -0,0 +1,1815 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include + * /wlan_lib.h#3 + */ + +/*! \file "wlan_lib.h" + * \brief The declaration of the functions of the wlanAdpater objects + * + * Detail description. + */ + +#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 "nic_init_cmd_event.h" +#include "fw_dl.h" + + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +/* These values must sync from Wifi HAL + * /hardware/libhardware_legacy/include/hardware_legacy/wifi_hal.h + */ +/* Basic infrastructure mode */ +#define WIFI_FEATURE_INFRA (0x0001) +/* Support for 5 GHz Band */ +#define WIFI_FEATURE_INFRA_5G (0x0002) +/* Support for GAS/ANQP */ +#define WIFI_FEATURE_HOTSPOT (0x0004) +/* Wifi-Direct */ +#define WIFI_FEATURE_P2P (0x0008) +/* Soft AP */ +#define WIFI_FEATURE_SOFT_AP (0x0010) +/* Google-Scan APIs */ +#define WIFI_FEATURE_GSCAN (0x0020) +/* Neighbor Awareness Networking */ +#define WIFI_FEATURE_NAN (0x0040) +/* Device-to-device RTT */ +#define WIFI_FEATURE_D2D_RTT (0x0080) +/* Device-to-AP RTT */ +#define WIFI_FEATURE_D2AP_RTT (0x0100) +/* Batched Scan (legacy) */ +#define WIFI_FEATURE_BATCH_SCAN (0x0200) +/* Preferred network offload */ +#define WIFI_FEATURE_PNO (0x0400) +/* Support for two STAs */ +#define WIFI_FEATURE_ADDITIONAL_STA (0x0800) +/* Tunnel directed link setup */ +#define WIFI_FEATURE_TDLS (0x1000) +/* Support for TDLS off channel */ +#define WIFI_FEATURE_TDLS_OFFCHANNEL (0x2000) +/* Enhanced power reporting */ +#define WIFI_FEATURE_EPR (0x4000) +/* Support for AP STA Concurrency */ +#define WIFI_FEATURE_AP_STA (0x8000) +/* Link layer stats collection */ +#define WIFI_FEATURE_LINK_LAYER_STATS (0x10000) +/* WiFi Logger */ +#define WIFI_FEATURE_LOGGER (0x20000) +/* WiFi PNO enhanced */ +#define WIFI_FEATURE_HAL_EPNO (0x40000) +/* RSSI Monitor */ +#define WIFI_FEATURE_RSSI_MONITOR (0x80000) +/* WiFi mkeep_alive */ +#define WIFI_FEATURE_MKEEP_ALIVE (0x100000) +/* ND offload configure */ +#define WIFI_FEATURE_CONFIG_NDO (0x200000) +/* Capture Tx transmit power levels */ +#define WIFI_FEATURE_TX_TRANSMIT_POWER (0x400000) +/* Enable/Disable firmware roaming */ +#define WIFI_FEATURE_CONTROL_ROAMING (0x800000) +/* Support Probe IE white listing */ +#define WIFI_FEATURE_IE_WHITELIST (0x1000000) +/* Support MAC & Probe Sequence Number randomization */ +#define WIFI_FEATURE_SCAN_RAND (0x2000000) +/* Support Tx Power Limit setting */ +#define WIFI_FEATURE_SET_TX_POWER_LIMIT (0x4000000) +/* Support Using Body/Head Proximity for SAR */ +#define WIFI_FEATURE_USE_BODY_HEAD_SAR (0x8000000) + +/* note: WIFI_FEATURE_GSCAN be enabled just for ACTS test item: scanner */ +#define WIFI_HAL_FEATURE_SET ((WIFI_FEATURE_P2P) |\ + (WIFI_FEATURE_SOFT_AP) |\ + (WIFI_FEATURE_TDLS) |\ + (WIFI_FEATURE_CONTROL_ROAMING)\ + ) + +#define MAX_NUM_GROUP_ADDR 32 /* max number of group addresses */ +#define AUTO_RATE_NUM 8 +#define AR_RATE_TABLE_ENTRY_MAX 25 +#define AR_RATE_ENTRY_INDEX_NULL 0x80 +#define MAX_TX_QUALITY_INDEX 4 + +#define TX_CS_TCP_UDP_GEN BIT(1) +#define TX_CS_IP_GEN BIT(0) + +#define CSUM_OFFLOAD_EN_TX_TCP BIT(0) +#define CSUM_OFFLOAD_EN_TX_UDP BIT(1) +#define CSUM_OFFLOAD_EN_TX_IP BIT(2) +#define CSUM_OFFLOAD_EN_RX_TCP BIT(3) +#define CSUM_OFFLOAD_EN_RX_UDP BIT(4) +#define CSUM_OFFLOAD_EN_RX_IPv4 BIT(5) +#define CSUM_OFFLOAD_EN_RX_IPv6 BIT(6) +#define CSUM_OFFLOAD_EN_TX_MASK BITS(0, 2) +#define CSUM_OFFLOAD_EN_ALL BITS(0, 6) + +/* TCP, UDP, IP Checksum */ +#define RX_CS_TYPE_UDP BIT(7) +#define RX_CS_TYPE_TCP BIT(6) +#define RX_CS_TYPE_IPv6 BIT(5) +#define RX_CS_TYPE_IPv4 BIT(4) + +#define RX_CS_STATUS_UDP BIT(3) +#define RX_CS_STATUS_TCP BIT(2) +#define RX_CS_STATUS_IP BIT(0) + +#define CSUM_NOT_SUPPORTED 0x0 + +#define TXPWR_USE_PDSLOPE 0 + +/* NVRAM error code definitions */ +#define NVRAM_ERROR_VERSION_MISMATCH BIT(1) +#define NVRAM_ERROR_INVALID_TXPWR BIT(2) +#define NVRAM_ERROR_INVALID_DPD BIT(3) +#define NVRAM_ERROR_INVALID_MAC_ADDR BIT(4) +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY +#define NVRAM_POWER_LIMIT_TABLE_INVALID BIT(5) +#endif + +#define NUM_TC_RESOURCE_TO_STATISTICS 4 +#if CFG_SUPPORT_NCHO +#define WLAN_CFG_ARGV_MAX 64 +#else +#define WLAN_CFG_ARGV_MAX 8 +#endif +#define WLAN_CFG_ARGV_MAX_LONG 22 /* for WOW, 2+20 */ +#define WLAN_CFG_ENTRY_NUM_MAX 200 /* 128 */ +#define WLAN_CFG_KEY_LEN_MAX 32 /* include \x00 EOL */ +#define WLAN_CFG_VALUE_LEN_MAX 32 /* include \x00 EOL */ +#define WLAN_CFG_FLAG_SKIP_CB BIT(0) +#define WLAN_CFG_FILE_BUF_SIZE 2048 + +#define WLAN_CFG_REC_ENTRY_NUM_MAX 200 +#define WLAN_CFG_REC_FLAG_BIT BIT(0) + + +#define WLAN_CFG_SET_CHIP_LEN_MAX 10 +#define WLAN_CFG_SET_DEBUG_LEVEL_LEN_MAX 10 +#define WLAN_CFG_SET_SW_CTRL_LEN_MAX 10 + +/* OID timeout (in ms) */ +#define WLAN_OID_TIMEOUT_THRESHOLD 2000 + +/* OID timeout during chip-resetting (in ms) */ +#define WLAN_OID_TIMEOUT_THRESHOLD_IN_RESETTING 300 + +#define WLAN_OID_NO_ACK_THRESHOLD 3 + + +/* If not setting the priority, 0 is the default */ +#define WLAN_THREAD_TASK_PRIORITY 0 + +/* If not setting the nice, -10 is the default */ +#define WLAN_THREAD_TASK_NICE (-10) + +#define WLAN_TX_STATS_LOG_TIMEOUT 30000 +#define WLAN_TX_STATS_LOG_DURATION 1500 + +/* Define for wifi path usage */ +#define WLAN_FLAG_2G4_WF0 BIT(0) /*1: support, 0: NOT support */ +#define WLAN_FLAG_5G_WF0 BIT(1) /*1: support, 0: NOT support */ +#define WLAN_FLAG_2G4_WF1 BIT(2) /*1: support, 0: NOT support */ +#define WLAN_FLAG_5G_WF1 BIT(3) /*1: support, 0: NOT support */ +#define WLAN_FLAG_2G4_COANT_SUPPORT BIT(4) /*1: support, 0: NOT support */ +#define WLAN_FLAG_2G4_COANT_PATH BIT(5) /*1: WF1, 0:WF0 */ +#define WLAN_FLAG_5G_COANT_SUPPORT BIT(6) /*1: support, 0: NOT support */ +#define WLAN_FLAG_5G_COANT_PATH BIT(7) /*1: WF1, 0:WF0 */ + +/* Define concurrent network channel number, using by CNM/CMD */ +#define MAX_OP_CHNL_NUM 3 + +#if CFG_SUPPORT_EASY_DEBUG + +#define MAX_CMD_ITEM_MAX 4 /* Max item per cmd. */ +#define MAX_CMD_NAME_MAX_LENGTH 32 /* Max name string length */ +#define MAX_CMD_VALUE_MAX_LENGTH 32 /* Max value string length */ +#define MAX_CMD_TYPE_LENGTH 1 +#define MAX_CMD_STRING_LENGTH 1 +#define MAX_CMD_VALUE_LENGTH 1 +#define MAX_CMD_RESERVE_LENGTH 1 + +#define CMD_FORMAT_V1_LENGTH \ + (MAX_CMD_NAME_MAX_LENGTH + MAX_CMD_VALUE_MAX_LENGTH + \ + MAX_CMD_TYPE_LENGTH + MAX_CMD_STRING_LENGTH + MAX_CMD_VALUE_LENGTH + \ + MAX_CMD_RESERVE_LENGTH) + +#define MAX_CMD_BUFFER_LENGTH (CMD_FORMAT_V1_LENGTH * MAX_CMD_ITEM_MAX) + +#if 1 +#define ED_STRING_SITE 0 +#define ED_VALUE_SITE 1 + + +#else +#define ED_ITEMTYPE_SITE 0 +#define ED_STRING_SITE 1 +#define ED_VALUE_SITE 2 +#endif + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +#define ACS_AP_RSSI_LEVEL_HIGH -50 +#define ACS_AP_RSSI_LEVEL_LOW -80 +#define ACS_DIRTINESS_LEVEL_HIGH 52 +#define ACS_DIRTINESS_LEVEL_MID 40 +#define ACS_DIRTINESS_LEVEL_LOW 32 +#endif + +#if CFG_WOW_SUPPORT +#define INVALID_WOW_WAKE_UP_REASON 255 +#endif + +#if CFG_SUPPORT_ADVANCE_CONTROL +#define KEEP_FULL_PWR_TRAFFIC_REPORT_BIT BIT(0) +#define KEEP_FULL_PWR_NOISE_HISTOGRAM_BIT BIT(1) +#endif + +#define ED_CCA_BW20_2G_DEFAULT (0) +#define ED_CCA_BW20_5G_DEFAULT (0) + +#if CFG_RCPI_COMPENSATION +/* wf path module channel group info (Tx FW loss compensation) */ +#define FELOSS_CH_GROUP_NUM 4 /* G-Band:1 A-Band:3*/ + +/* channel group boundary (FW_LOSS On for G-Band) */ +#define G_BAND_FELOSS_BOUND_0 14 + +/* channel group boundary (FW_LOSS On for A-Band) */ +#define A_BAND_FELOSS_BOUND_0 66 +#define A_BAND_FELOSS_BOUND_1 130 +#define A_BAND_FELOSS_BOUND_2 182 + +/* EFUSE offset for FE Loss */ +#define G_BAND_WF0_FELOSS 0xE0 +#define G_BAND_WF1_FELOSS 0xF0 +#define A_BAND_WF0_LB_FELOSS 0x240 +#define A_BAND_WF0_MB_FELOSS 0x241 +#define A_BAND_WF0_HB_FELOSS 0x242 +#define A_BAND_WF1_LB_FELOSS 0x2B0 +#define A_BAND_WF1_MB_FELOSS 0x2B1 +#define A_BAND_WF1_HB_FELOSS 0x2B2 + +#define TX_FELOSS_MASK BITS(4, 7) +#define TX_FELOSS_OFFSET 4 +#define RX_FELOSS_MASK BITS(0, 3) +#define RX_FELOSS_OFFSET 0 +#endif + +#if CFG_SUPPORT_HW_1T2R +#define EFUSE_1T2R_ADDR 0x1B2 +#define EFUSE_1T2R_OFFSET 5 +#endif + + +enum CMD_VER { + CMD_VER_1, /* Type[2]+String[32]+Value[32] */ + CMD_VER_2 /* for furtur define. */ +}; + + +#if 0 +enum ENUM_AIS_REQUEST_TYPE { + AIS_REQUEST_SCAN, + AIS_REQUEST_RECONNECT, + AIS_REQUEST_ROAMING_SEARCH, + AIS_REQUEST_ROAMING_CONNECT, + AIS_REQUEST_REMAIN_ON_CHANNEL, + AIS_REQUEST_NUM +}; +#endif +enum CMD_TYPE { + CMD_TYPE_QUERY, + CMD_TYPE_SET +}; + + +#define ITEM_TYPE_DEC 1 +#define ITEM_TYPE_HEX 2 +#define ITEM_TYPE_STR 3 + +enum CMD_DEFAULT_SETTING_VALUE { + CMD_PNO_ENABLE, + CMD_PNO_SCAN_PERIOD, + CMD_SCN_CHANNEL_PLAN, + CMD_SCN_DWELL_TIME, + CMD_SCN_STOP_SCAN, + CMD_MAX, +}; + +enum CMD_DEFAULT_STR_SETTING_VALUE { + CMD_STR_TEST_STR, + CMD_STR_MAX, +}; + +struct CMD_FORMAT_V1 { + uint8_t itemType; + uint8_t itemStringLength; + uint8_t itemValueLength; + uint8_t Reserved; + uint8_t itemString[MAX_CMD_NAME_MAX_LENGTH]; + uint8_t itemValue[MAX_CMD_VALUE_MAX_LENGTH]; +}; + +struct CMD_HEADER { + enum CMD_VER cmdVersion; + enum CMD_TYPE cmdType; + uint8_t itemNum; + uint16_t cmdBufferLen; + uint8_t buffer[MAX_CMD_BUFFER_LENGTH]; +}; + +struct CFG_DEFAULT_SETTING_TABLE { + uint32_t itemNum; + const char *String; + uint8_t itemType; + uint32_t defaultValue; + uint32_t minValue; + uint32_t maxValue; +}; + +struct CFG_DEFAULT_SETTING_STR_TABLE { + uint32_t itemNum; + const char *String; + uint8_t itemType; + const char *DefString; + uint16_t minLen; + uint16_t maxLen; +}; + +struct CFG_QUERY_FORMAT { + uint32_t Length; + uint32_t Value; + uint32_t Type; + uint32_t *ptr; +}; + +/*Globol Configure define */ +struct CFG_SETTING { + uint8_t PnoEnable; + uint32_t PnoScanPeriod; + uint8_t ScnChannelPlan; + uint16_t ScnDwellTime; + uint8_t ScnStopScan; + uint8_t TestStr[80]; +}; + +#endif + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +typedef uint32_t(*PFN_OID_HANDLER_FUNC) (IN struct ADAPTER *prAdapter, + IN void *pvBuf, IN uint32_t u4BufLen, + OUT uint32_t *pu4OutInfoLen); + +enum ENUM_CSUM_TYPE { + CSUM_TYPE_IPV4, + CSUM_TYPE_IPV6, + CSUM_TYPE_TCP, + CSUM_TYPE_UDP, + CSUM_TYPE_NUM +}; + +enum ENUM_CSUM_RESULT { + CSUM_RES_NONE, + CSUM_RES_SUCCESS, + CSUM_RES_FAILED, + CSUM_RES_NUM +}; + +enum ENUM_PHY_MODE { + 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 ENUM_POWER_SAVE_POLL_MODE { + ENUM_POWER_SAVE_POLL_DISABLE, + ENUM_POWER_SAVE_POLL_LEGACY_NULL, + ENUM_POWER_SAVE_POLL_QOS_NULL, + ENUM_POWER_SAVE_POLL_NUM +}; + +enum ENUM_AC_TYPE { + 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 ENUM_ADV_AC_TYPE { + 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 ENUM_REG_CH_MAP { + REG_CH_MAP_COUNTRY_CODE, + REG_CH_MAP_TBL_IDX, + REG_CH_MAP_CUSTOMIZED, + REG_CH_MAP_NUM +}; + +enum ENUM_FEATURE_OPTION { + FEATURE_DISABLED, + FEATURE_ENABLED, + FEATURE_FORCE_ENABLED +}; + +/* This enum is for later added feature options which use command reserved field + * as option switch + */ +enum ENUM_FEATURE_OPTION_IN_CMD { + FEATURE_OPT_CMD_AUTO, + FEATURE_OPT_CMD_DISABLED, + FEATURE_OPT_CMD_ENABLED, + FEATURE_OPT_CMD_FORCE_ENABLED +}; + +#define DEBUG_MSG_SIZE_MAX 1200 +enum { + DEBUG_MSG_ID_UNKNOWN = 0x00, + DEBUG_MSG_ID_PRINT = 0x01, + DEBUG_MSG_ID_FWLOG = 0x02, + DEBUG_MSG_ID_END +}; + +enum { + DEBUG_MSG_TYPE_UNKNOWN = 0x00, + DEBUG_MSG_TYPE_MEM8 = 0x01, + DEBUG_MSG_TYPE_MEM32 = 0x02, + DEBUG_MSG_TYPE_ASCII = 0x03, + DEBUG_MSG_TYPE_BINARY = 0x04, + DEBUG_MSG_TYPE_DRIVER = 0x05, + DEBUG_MSG_TYPE_END +}; + +#define CHIP_CONFIG_RESP_SIZE 320 +enum { + CHIP_CONFIG_TYPE_WO_RESPONSE = 0x00, + CHIP_CONFIG_TYPE_MEM8 = 0x01, + CHIP_CONFIG_TYPE_MEM32 = 0x02, + CHIP_CONFIG_TYPE_ASCII = 0x03, + CHIP_CONFIG_TYPE_BINARY = 0x04, + CHIP_CONFIG_TYPE_DRV_PASSTHROUGH = 0x05, + CHIP_CONFIG_TYPE_END +}; + +struct SET_TXPWR_CTRL { + int8_t c2GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0 */ + int8_t c2GHotspotPwrOffset; + int8_t c2GP2pPwrOffset; + int8_t c2GBowPwrOffset; + int8_t c5GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0 */ + int8_t c5GHotspotPwrOffset; + int8_t c5GP2pPwrOffset; + int8_t c5GBowPwrOffset; + uint8_t ucConcurrencePolicy; /* TX power policy when concurrence + * in the same channel + * 0: Highest power has priority + * 1: Lowest power has priority + */ + + int8_t acReserved1[3]; /* Must be zero */ + + /* Power limit by channel for all data rates */ + int8_t acTxPwrLimit2G[14]; /* Channel 1~14, Unit: 0.5dBm */ + int8_t acTxPwrLimit5G[4]; /* UNII 1~4 */ + int8_t acReserved2[2]; /* Must be zero */ +}; + +#if CFG_WOW_SUPPORT + +struct WOW_WAKE_HIF { + /* use in-band signal to wakeup system, ENUM_HIF_TYPE */ + uint8_t ucWakeupHif; + + /* GPIO Pin */ + uint8_t ucGpioPin; + + /* refer to PF_WAKEUP_CMD_BIT0_OUTPUT_MODE_EN */ + uint8_t ucTriggerLvl; + + /* non-zero means output reverse wakeup signal after delay time */ + uint32_t u4GpioInterval; + + uint8_t aucResv[5]; +}; + +struct WOW_PORT { + uint8_t ucIPv4UdpPortCnt; + uint8_t ucIPv4TcpPortCnt; + uint8_t ucIPv6UdpPortCnt; + uint8_t ucIPv6TcpPortCnt; + uint16_t ausIPv4UdpPort[MAX_TCP_UDP_PORT]; + uint16_t ausIPv4TcpPort[MAX_TCP_UDP_PORT]; + uint16_t ausIPv6UdpPort[MAX_TCP_UDP_PORT]; + uint16_t ausIPv6TcpPort[MAX_TCP_UDP_PORT]; +}; + +struct WOW_CTRL { + uint8_t fgWowEnable; /* 0: disable, 1: wow enable */ + uint8_t ucScenarioId; /* just a profile ID */ + uint8_t ucBlockCount; + uint8_t ucDetectType; + struct WOW_WAKE_HIF astWakeHif[2]; + struct WOW_PORT stWowPort; + uint8_t ucReason; + uint8_t aucReserved2[3]; +}; + +#define MDNS_CMD_ENABLE 1 +#define MDNS_CMD_DISABLE 2 +#define MDNS_CMD_ADD_RECORD 3 +#define MDNS_CMD_DEL_RECORD 4 + +#define MDNS_NAME_MAX_LEN 100 +#define MDNS_RESPONSE_RECORD_MAX_LEN 500 +#define MDNS_TXT_RR_DATA_MAX_LEN 300 +#define MDNS_SRV_RR_LEN 16 +#define MDNS_TXT_RR_MAX_LEN 310 +#define MDNS_QUESTION_NAME_MAX_LEN 102 +#define MDNS_SERVICE_NAME_MAX_LEN 102 +#define MDNS_A_RR_LEN 14 + +#define MAX_MDNS_CACHE_NUM 6 + +struct MDNS_PTR_INFO_T { + uint8_t queryName[MDNS_QUESTION_NAME_MAX_LEN]; + uint16_t queryNameLen; + uint16_t type; + uint16_t cl; + uint32_t ttl; + uint16_t dataLen; + uint8_t domName[MDNS_SERVICE_NAME_MAX_LEN]; + uint16_t domNameLen; +}; + +struct MDNS_TXT_INFO_T { + uint8_t domName[MDNS_SERVICE_NAME_MAX_LEN]; + uint16_t domNameLen; + uint16_t type; + uint16_t cl; + uint32_t ttl; + uint16_t dataLen; + uint8_t text[MDNS_TXT_RR_DATA_MAX_LEN]; +}; + +struct MDNS_SRV_INFO_T { + uint8_t domName[MDNS_SERVICE_NAME_MAX_LEN]; + uint16_t domNameLen; + uint16_t type; + uint16_t cl; + uint32_t ttl; + uint16_t dataLen; + uint16_t priority; + uint16_t weight; + uint16_t port; + uint8_t target[100]; + uint16_t targetLen; +}; + +struct MDNS_A_INFO_T { + uint8_t domName[100]; + uint16_t domNameLen; + uint16_t type; + uint16_t cl; + uint32_t ttl; + uint16_t dataLen; + uint32_t ipAddr; +}; + + +struct MDNS_RESP_INFO_T { + uint16_t usMdnsId; + uint16_t usMdnsFlags; + uint16_t usQuestionCnt; + uint16_t usAnswerCnt; + uint16_t usAuthCnt; + uint16_t usAddtionCnt; + struct MDNS_PTR_INFO_T ptrInfo; + struct MDNS_TXT_INFO_T txtInfo; + struct MDNS_SRV_INFO_T srvInfo; + struct MDNS_A_INFO_T aInfo; +}; + +struct MDNS_PARAM_T { + uint8_t ucCmd; + uint32_t u4RecordId; + uint8_t ucQueryName[MDNS_NAME_MAX_LEN]; + uint16_t u2QueryNameLen; + uint16_t u2QueryType; + uint16_t u2QueryClass; + uint8_t ucResponseRecord[MDNS_RESPONSE_RECORD_MAX_LEN]; + uint16_t u2ResponseRecordLen; + uint8_t ucServiceName[MDNS_NAME_MAX_LEN]; + uint16_t u2ServiceNameLen; + uint8_t ucServiceType[MDNS_NAME_MAX_LEN]; + uint16_t u2ServiceTypeLen; + uint8_t ucDomainName[MDNS_NAME_MAX_LEN]; + uint16_t u2DomainNameLen; + uint8_t ucHostName[MDNS_NAME_MAX_LEN]; + uint16_t u2HostNameLen; + uint32_t u4Port; + uint8_t ucTxtRecord[MDNS_TXT_RR_DATA_MAX_LEN]; + uint16_t u2TxtRecordLen; +}; + +struct WLAN_MAC_HEADER_QoS_T { + uint16_t u2FrameCtrl; + uint16_t DurationID; + uint8_t aucAddr1[MAC_ADDR_LEN]; + uint8_t aucAddr2[MAC_ADDR_LEN]; + uint8_t aucAddr3[MAC_ADDR_LEN]; + uint16_t u2SeqCtrl; + uint16_t u2QosCtrl; +}; + +#define UDP_HEADER_LENGTH 8 +#define IPV4_HEADER_LENGTH 20 + +struct MDNS_ANSWER_RR { + uint8_t data[MDNS_RESPONSE_RECORD_MAX_LEN]; + uint16_t data_length; +}; + +struct MDNS_SRV_RR { + uint8_t data[MDNS_SRV_RR_LEN]; + uint16_t data_length; +}; + +struct MDNS_TXT_RR { + uint8_t data[MDNS_TXT_RR_MAX_LEN]; + uint16_t data_length; +}; + +struct MDNS_A_RR { + uint8_t data[MDNS_A_RR_LEN]; + uint16_t data_length; +}; + +struct MDNS_QUESTION { + uint8_t name[MDNS_QUESTION_NAME_MAX_LEN]; + uint8_t name_length; + uint8_t label_count; + uint16_t class; + uint16_t type; +}; + +struct MDNS_Template_Record { + uint32_t u4RecordId; + struct MDNS_QUESTION mdnsQuestionTemplate; + struct MDNS_ANSWER_RR mdnsResponseRecord; + uint8_t ucServiceName[MDNS_SERVICE_NAME_MAX_LEN]; + uint16_t ServiceNameLen; + struct MDNS_TXT_RR mdnsTxtRecord; + struct MDNS_SRV_RR mdnsSrvRecord; + uint8_t ucTargetName[MDNS_SERVICE_NAME_MAX_LEN]; + uint16_t TargetNameLen; + struct MDNS_A_RR mdnsARecord; + uint8_t bIsUsed; +}; + +struct CMD_MDNS_PARAM_T { + uint8_t ucCmd; + uint32_t u4RecordId; + struct WLAN_MAC_HEADER_QoS_T aucMdnsMacHdr; + uint8_t aucMdnsIPHdr[IPV4_HEADER_LENGTH]; + uint8_t aucMdnsUdpHdr[UDP_HEADER_LENGTH]; + uint8_t mdnsARecord[MDNS_A_RR_LEN]; + struct MDNS_Template_Record mdnsQueryRespTemplate; +}; + +#endif + +enum ENUM_NVRAM_MTK_FEATURE { + MTK_FEATURE_2G_256QAM_DISABLED = 0, + MTK_FEATURE_NUM +}; + +/* For storing driver initialization value from glue layer */ +struct REG_INFO { + uint32_t u4SdBlockSize; /* SDIO block size */ + uint32_t u4SdBusWidth; /* SDIO bus width. 1 or 4 */ + uint32_t u4SdClockRate; /* SDIO clock rate. (in unit of HZ) */ + + /* Start Frequency for Ad-Hoc network : in unit of KHz */ + uint32_t u4StartFreq; + + /* Default mode for Ad-Hoc network : ENUM_PARAM_AD_HOC_MODE_T */ + uint32_t u4AdhocMode; + + uint32_t u4RddStartFreq; + uint32_t u4RddStopFreq; + uint32_t u4RddTestMode; + uint32_t u4RddShutFreq; + uint32_t u4RddDfs; + int32_t i4HighRssiThreshold; + int32_t i4MediumRssiThreshold; + int32_t i4LowRssiThreshold; + int32_t au4TxPriorityTag[ENUM_AC_TYPE_NUM]; + int32_t au4RxPriorityTag[ENUM_AC_TYPE_NUM]; + int32_t au4AdvPriorityTag[ENUM_ADV_AC_TYPE_NUM]; + uint32_t u4FastPSPoll; + uint32_t u4PTA; /* 0: disable, 1: enable */ + uint32_t u4TXLimit; /* 0: disable, 1: enable */ + uint32_t u4SilenceWindow; /* range: 100 - 625, unit: us */ + uint32_t u4TXLimitThreshold; /* range: 250 - 1250, unit: us */ + uint32_t u4PowerMode; + uint32_t fgEnArpFilter; + uint32_t u4PsCurrentMeasureEn; + uint32_t u4UapsdAcBmp; + uint32_t u4MaxSpLen; + + /* 0: enable online scan, non-zero: disable online scan */ + uint32_t fgDisOnlineScan; + + /* 0: enable online scan, non-zero: disable online scan */ + uint32_t fgDisBcnLostDetection; + + /* 0: automatic, non-zero: fixed rate */ + uint32_t u4FixedRate; + + uint32_t u4ArSysParam0; + uint32_t u4ArSysParam1; + uint32_t u4ArSysParam2; + uint32_t u4ArSysParam3; + + /* 0:enable roaming 1:disable */ + uint32_t fgDisRoaming; + + /* NVRAM - MP Data -START- */ +#if 1 + uint16_t u2Part1OwnVersion; + uint16_t u2Part1PeerVersion; +#endif + uint8_t aucMacAddr[6]; + + /* Country code (in ISO 3166-1 expression, ex: "US", "TW") */ + uint16_t au2CountryCode[4]; + + struct TX_PWR_PARAM rTxPwr; + uint8_t aucEFUSE[144]; + uint8_t ucTxPwrValid; + uint8_t ucSupport5GBand; + uint8_t fg2G4BandEdgePwrUsed; + int8_t cBandEdgeMaxPwrCCK; + int8_t cBandEdgeMaxPwrOFDM20; + int8_t cBandEdgeMaxPwrOFDM40; + enum ENUM_REG_CH_MAP eRegChannelListMap; + uint8_t ucRegChannelListIndex; + struct DOMAIN_INFO_ENTRY rDomainInfo; + struct RSSI_PATH_COMPASATION rRssiPathCompasation; + uint8_t ucRssiPathCompasationUsed; + /* NVRAM - MP Data -END- */ + + /* NVRAM - Functional Data -START- */ + uint8_t uc2G4BwFixed20M; + uint8_t uc5GBwFixed20M; + uint8_t ucEnable5GBand; + uint8_t ucGpsDesense; + uint8_t ucRxDiversity; + /* NVRAM - Functional Data -END- */ + + struct NEW_EFUSE_MAPPING2NVRAM *prOldEfuseMapping; + + uint8_t aucNvram[512]; + struct WIFI_CFG_PARAM_STRUCT *prNvramSettings; +}; + +/* for divided firmware loading */ +struct FWDL_SECTION_INFO { +#if 0 + uint32_t u4Offset; + uint32_t u4Reserved; + uint32_t u4Length; + uint32_t u4DestAddr; +#endif + uint32_t u4DestAddr; + uint8_t ucChipInfo; + uint8_t ucFeatureSet; + uint8_t ucEcoCode; + uint8_t aucReserved[9]; + uint8_t aucBuildDate[16]; + uint32_t u4Length; +}; + +struct FIRMWARE_DIVIDED_DOWNLOAD { +#if 0 + uint32_t u4Signature; + + /* CRC calculated without first 8 bytes included */ + uint32_t u4CRC; + + uint32_t u4NumOfEntries; + uint32_t u4Reserved; + struct FWDL_SECTION_INFO arSection[]; +#endif + struct FWDL_SECTION_INFO arSection[2]; +}; + +struct PARAM_MCR_RW_STRUCT { + uint32_t u4McrOffset; + uint32_t u4McrData; +}; + +/* per access category statistics */ +struct WIFI_WMM_AC_STAT { + uint32_t u4TxMsdu; + uint32_t u4RxMsdu; + uint32_t u4TxDropMsdu; + uint32_t u4TxFailMsdu; + uint32_t u4TxRetryMsdu; +}; + +struct TX_VECTOR_BBP_LATCH { + uint32_t u4TxVector1; + uint32_t u4TxVector2; + uint32_t u4TxVector4; +}; + +struct MIB_INFO_STAT { + uint32_t u4RxMpduCnt; + uint32_t u4FcsError; + uint32_t u4RxFifoFull; + uint32_t u4AmpduTxSfCnt; + uint32_t u4AmpduTxAckSfCnt; + uint16_t u2TxRange1AmpduCnt; + uint16_t u2TxRange2AmpduCnt; + uint16_t u2TxRange3AmpduCnt; + uint16_t u2TxRange4AmpduCnt; + uint16_t u2TxRange5AmpduCnt; + uint16_t u2TxRange6AmpduCnt; + uint16_t u2TxRange7AmpduCnt; + uint16_t u2TxRange8AmpduCnt; +}; + +struct PARAM_GET_STA_STATISTICS { + /* Per-STA statistic */ + uint8_t ucInvalid; + uint8_t ucVersion; + uint8_t aucMacAddr[MAC_ADDR_LEN]; + + uint32_t u4LinkScore; + uint32_t u4Flag; + + uint8_t ucReadClear; + uint8_t ucLlsReadClear; + + /* From driver */ + uint32_t u4TxTotalCount; + uint32_t u4TxExceedThresholdCount; + + uint32_t u4TxMaxTime; + uint32_t u4TxAverageProcessTime; + + uint32_t u4TxMaxHifTime; + uint32_t u4TxAverageHifTime; + + uint32_t u4RxTotalCount; + + /* + * How many packages Enqueue/Deqeue during statistics interval + */ + uint32_t u4EnqueueCounter; + uint32_t u4DequeueCounter; + + uint32_t u4EnqueueStaCounter; + uint32_t u4DequeueStaCounter; + + uint32_t IsrCnt; + uint32_t IsrPassCnt; + uint32_t TaskIsrCnt; + + uint32_t IsrAbnormalCnt; + uint32_t IsrSoftWareCnt; + uint32_t IsrRxCnt; + uint32_t IsrTxCnt; + + uint32_t au4TcResourceEmptyCount[NUM_TC_RESOURCE_TO_STATISTICS]; + uint32_t au4DequeueNoTcResource[NUM_TC_RESOURCE_TO_STATISTICS]; + uint32_t au4TcResourceBackCount[NUM_TC_RESOURCE_TO_STATISTICS]; + uint32_t au4TcResourceUsedPageCount[NUM_TC_RESOURCE_TO_STATISTICS]; + uint32_t au4TcResourceWantedPageCount[NUM_TC_RESOURCE_TO_STATISTICS]; + + uint32_t au4TcQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + + /* From FW */ + uint8_t ucPer; /* base: 128 */ + uint8_t ucRcpi; + uint32_t u4PhyMode; + uint16_t u2LinkSpeed; /* unit is 0.5 Mbits */ + + uint32_t u4TxFailCount; + uint32_t u4TxLifeTimeoutCount; + + uint32_t u4TxAverageAirTime; + + /* Transmit in the air (wtbl) */ + uint32_t u4TransmitCount; + + /* Transmit without ack/ba in the air (wtbl) */ + uint32_t u4TransmitFailCount; + + /*link layer statistics */ + struct WIFI_WMM_AC_STAT arLinkStatistics[AC_NUM]; + + /* Global queue management statistic */ + uint32_t au4TcAverageQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + uint32_t au4TcCurrentQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + + uint8_t ucTemperature; + uint8_t ucSkipAr; + uint8_t ucArTableIdx; + uint8_t ucRateEntryIdx; + uint8_t ucRateEntryIdxPrev; + uint8_t ucTxSgiDetectPassCnt; + uint8_t ucAvePer; +#if (CFG_SUPPORT_RA_GEN == 0) + uint8_t aucArRatePer[AR_RATE_TABLE_ENTRY_MAX]; + uint8_t aucRateEntryIndex[AUTO_RATE_NUM]; +#else + uint32_t u4AggRangeCtrl_0; + uint32_t u4AggRangeCtrl_1; + uint8_t ucRangeType; + uint8_t aucReserved5[24]; +#endif + uint8_t ucArStateCurr; + uint8_t ucArStatePrev; + uint8_t ucArActionType; + uint8_t ucHighestRateCnt; + uint8_t ucLowestRateCnt; + uint16_t u2TrainUp; + uint16_t u2TrainDown; + uint32_t u4Rate1TxCnt; + uint32_t u4Rate1FailCnt; + struct TX_VECTOR_BBP_LATCH rTxVector[ENUM_BAND_NUM]; + struct MIB_INFO_STAT rMibInfo[ENUM_BAND_NUM]; + uint8_t ucResetCounter; + u_int8_t fgIsForceTxStream; + u_int8_t fgIsForceSeOff; +#if (CFG_SUPPORT_RA_GEN == 0) + uint8_t aucReserved6[17]; +#else + uint16_t u2RaRunningCnt; + uint8_t ucRaStatus; + uint8_t ucFlag; + uint8_t aucTxQuality[MAX_TX_QUALITY_INDEX]; + uint8_t ucTxRateUpPenalty; + uint8_t ucLowTrafficMode; + uint8_t ucLowTrafficCount; + uint8_t ucLowTrafficDashBoard; + uint8_t ucDynamicSGIState; + uint8_t ucDynamicSGIScore; + uint8_t ucDynamicBWState; + uint8_t ucDynamicGband256QAMState; + uint8_t ucVhtNonSpRateState; +#endif + /* Reserved fields */ + uint8_t au4Reserved[3]; +}; + +struct PARAM_GET_BSS_STATISTICS { + /* Per-STA statistic */ + uint8_t aucMacAddr[MAC_ADDR_LEN]; + + uint32_t u4Flag; + + uint8_t ucReadClear; + + uint8_t ucLlsReadClear; + + uint8_t ucBssIndex; + + /* From driver */ + uint32_t u4TxTotalCount; + uint32_t u4TxExceedThresholdCount; + + uint32_t u4TxMaxTime; + uint32_t u4TxAverageProcessTime; + + uint32_t u4RxTotalCount; + + uint32_t au4TcResourceEmptyCount[NUM_TC_RESOURCE_TO_STATISTICS]; + uint32_t au4TcQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + + /* From FW */ + uint8_t ucPer; /* base: 128 */ + uint8_t ucRcpi; + uint32_t u4PhyMode; + uint16_t u2LinkSpeed; /* unit is 0.5 Mbits */ + + uint32_t u4TxFailCount; + uint32_t u4TxLifeTimeoutCount; + + uint32_t u4TxAverageAirTime; + + /* Transmit in the air (wtbl) */ + uint32_t u4TransmitCount; + + /* Transmit without ack/ba in the air (wtbl) */ + uint32_t u4TransmitFailCount; + + /*link layer statistics */ + struct WIFI_WMM_AC_STAT arLinkStatistics[AC_NUM]; + + /* Global queue management statistic */ + uint32_t au4TcAverageQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + uint32_t au4TcCurrentQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + + /* Reserved fields */ + uint8_t au4Reserved[32]; /* insufficient for LLS?? */ +}; + +struct PARAM_GET_DRV_STATISTICS { + int32_t i4TxPendingFrameNum; + int32_t i4TxPendingSecurityFrameNum; + int32_t i4TxPendingCmdNum; + + /* sync i4PendingFwdFrameCount in _TX_CTRL_T */ + int32_t i4PendingFwdFrameCount; + + /* sync pad->rTxCtrl.rFreeMsduInfoList.u4NumElem */ + uint32_t u4MsduNumElem; + + /* sync pad->rTxCtrl.rTxMgmtTxingQueue.u4NumElem */ + uint32_t u4TxMgmtTxringQueueNumElem; + + /* sync pad->prRxCtrl.rFreeSwRfbList.u4NumElem */ + uint32_t u4RxFreeSwRfbMsduNumElem; + + /* sync pad->prRxCtrl.rReceivedRfbList.u4NumElem */ + uint32_t u4RxReceivedRfbNumElem; + + /* sync pad->prRxCtrl.rIndicatedRfbList.u4NumElem */ + uint32_t u4RxIndicatedNumElem; +}; + +struct NET_INTERFACE_INFO { + uint8_t ucBssIndex; + void *pvNetInterface; +}; + +enum ENUM_TX_RESULT_CODE { + 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_BIP_ERROR, + TX_RESULT_UNSPECIFIED_ERROR, + TX_RESULT_DROPPED_IN_DRIVER = 32, + TX_RESULT_DROPPED_IN_FW, + TX_RESULT_QUEUE_CLEARANCE, + TX_RESULT_INACTIVE_BSS, + TX_RESULT_NUM +}; + +/* enum of BEACON_TIMEOUT_REASON */ +enum _ENUM_PM_BEACON_TIME_OUT_REACON_CODE_T { + BEACON_TIMEOUT_DUE_2_HW_BEACON_LOST_NONADHOC, + BEACON_TIMEOUT_DUE_2_HW_BEACON_LOST_ADHOC, + BEACON_TIMEOUT_DUE_2_HW_TSF_DRIFT, + BEACON_TIMEOUT_DUE_2_NULL_FRAME_THRESHOLD, + BEACON_TIMEOUT_DUE_2_AGING_THRESHOLD, + BEACON_TIMEOUT_DUE_2_BSSID_BEACON_PEIROD_NOT_ILLIGAL, + BEACON_TIMEOUT_DUE_2_CONNECTION_FAIL, + BEACON_TIMEOUT_DUE_2_ALLOCAT_NULL_PKT_FAIL_THRESHOLD, + BEACON_TIMEOUT_DUE_2_NO_TX_DONE_EVENT, + BEACON_TIMEOUT_DUE_2_UNSPECIF_REASON, + BEACON_TIMEOUT_DUE_2_SET_CHIP, + BEACON_TIMEOUT_DUE_2_KEEP_SCAN_AP_MISS_CHECK_FAIL, + BEACON_TIMEOUT_DUE_2_KEEP_UNCHANGED_LOW_RSSI_CHECK_FAIL, + BEACON_TIMEOUT_DUE_2_NULL_FRAME_LIFE_TIMEOUT, + BEACON_TIMEOUT_DUE_2_APR_NO_RESPONSE, + BEACON_TIMEOUT_DUE_2_NUM +}; + +struct WLAN_CFG_ENTRY { + uint8_t aucKey[WLAN_CFG_KEY_LEN_MAX]; + uint8_t aucValue[WLAN_CFG_VALUE_LEN_MAX]; + WLAN_CFG_SET_CB pfSetCb; + void *pPrivate; + uint32_t u4Flags; +}; + +struct WLAN_CFG { + uint32_t u4WlanCfgEntryNumMax; + uint32_t u4WlanCfgKeyLenMax; + uint32_t u4WlanCfgValueLenMax; + struct WLAN_CFG_ENTRY arWlanCfgBuf[WLAN_CFG_ENTRY_NUM_MAX]; +}; + +struct WLAN_CFG_REC { + uint32_t u4WlanCfgEntryNumMax; + uint32_t u4WlanCfgKeyLenMax; + uint32_t u4WlanCfgValueLenMax; + struct WLAN_CFG_ENTRY arWlanCfgBuf[WLAN_CFG_REC_ENTRY_NUM_MAX]; +}; + +enum ENUM_MAX_BANDWIDTH_SETTING { + MAX_BW_20MHZ = 0, + MAX_BW_40MHZ, + MAX_BW_80MHZ, + MAX_BW_160MHZ, + MAX_BW_80_80_MHZ +}; + +struct TX_PACKET_INFO { + uint8_t ucPriorityParam; + uint32_t u4PacketLen; + uint8_t aucEthDestAddr[MAC_ADDR_LEN]; + uint16_t u2Flag; + +#if 0 + u_int8_t fgIs1X; + u_int8_t fgIsPAL; + u_int8_t fgIs802_3; + u_int8_t fgIsVlanExists; + u_int8_t fgIsDhcp; + u_int8_t fgIsArp; +#endif +}; + +enum ENUM_TX_PROFILING_TAG { + TX_PROF_TAG_OS_TO_DRV = 0, + TX_PROF_TAG_DRV_ENQUE, + TX_PROF_TAG_DRV_DEQUE, + TX_PROF_TAG_DRV_TX_DONE, + TX_PROF_TAG_DRV_FREE_MSDU, + TX_PROF_TAG_MAC_TX_DONE +}; + +#if (CFG_SUPPORT_SPE_IDX_CONTROL == 1) +enum ENUM_WF_PATH_FAVOR_T { + ENUM_WF_NON_FAVOR = 0xff, + ENUM_WF_0_ONE_STREAM_PATH_FAVOR = 0, + ENUM_WF_1_ONE_STREAM_PATH_FAVOR = 1, + ENUM_WF_0_1_TWO_STREAM_PATH_FAVOR = 2, + ENUM_WF_0_1_DUP_STREAM_PATH_FAVOR = 3, +}; +#endif + +struct PARAM_GET_CNM_T { + uint8_t fgIsDbdcEnable; + + uint8_t ucOpChNum[ENUM_BAND_NUM]; + uint8_t ucChList[ENUM_BAND_NUM][MAX_OP_CHNL_NUM]; + uint8_t ucChBw[ENUM_BAND_NUM][MAX_OP_CHNL_NUM]; + uint8_t ucChSco[ENUM_BAND_NUM][MAX_OP_CHNL_NUM]; + uint8_t ucChNetNum[ENUM_BAND_NUM][MAX_OP_CHNL_NUM]; + uint8_t ucChBssList[ENUM_BAND_NUM][MAX_OP_CHNL_NUM][BSSID_NUM]; + + uint8_t ucBssInuse[BSSID_NUM + 1]; + uint8_t ucBssActive[BSSID_NUM + 1]; + uint8_t ucBssConnectState[BSSID_NUM + 1]; + + uint8_t ucBssCh[BSSID_NUM + 1]; + uint8_t ucBssDBDCBand[BSSID_NUM + 1]; + uint8_t ucBssWmmSet[BSSID_NUM + 1]; + uint8_t ucBssWmmDBDCBand[BSSID_NUM + 1]; + uint8_t ucBssOMACSet[BSSID_NUM + 1]; + uint8_t ucBssOMACDBDCBand[BSSID_NUM + 1]; + + /* Reserved fields */ + uint8_t au4Reserved[65]; /*Total 160 byte*/ +}; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +extern struct MIB_INFO_STAT g_arMibInfo[ENUM_BAND_NUM]; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +#define BUILD_SIGN(ch0, ch1, ch2, ch3) \ + ((uint32_t)(uint8_t)(ch0) | ((uint32_t)(uint8_t)(ch1) << 8) | \ + ((uint32_t)(uint8_t)(ch2) << 16) | ((uint32_t)(uint8_t)(ch3) << 24)) + +#define MTK_WIFI_SIGNATURE BUILD_SIGN('M', 'T', 'K', 'W') + +#define IS_FEATURE_ENABLED(_ucFeature) \ + (((_ucFeature) == FEATURE_ENABLED) || \ + ((_ucFeature) == FEATURE_FORCE_ENABLED)) +#define IS_FEATURE_FORCE_ENABLED(_ucFeature) \ + ((_ucFeature) == FEATURE_FORCE_ENABLED) +#define IS_FEATURE_DISABLED(_ucFeature) ((_ucFeature) == FEATURE_DISABLED) + +/* This macro is for later added feature options which use command reserved + * field as option switch + */ +/* 0: AUTO + * 1: Disabled + * 2: Enabled + * 3: Force disabled + */ +#define FEATURE_OPT_IN_COMMAND(_ucFeature) ((_ucFeature) + 1) + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +struct ADAPTER *wlanAdapterCreate(IN struct GLUE_INFO *prGlueInfo); + +void wlanAdapterDestroy(IN struct ADAPTER *prAdapter); + +void wlanCardEjected(IN struct ADAPTER *prAdapter); + +void wlanIST(IN struct ADAPTER *prAdapter); + +u_int8_t wlanISR(IN struct ADAPTER *prAdapter, IN u_int8_t fgGlobalIntrCtrl); + +uint32_t wlanProcessCommandQueue(IN struct ADAPTER *prAdapter, + IN struct QUE *prCmdQue); + +uint32_t wlanSendCommand(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo); + +#if CFG_SUPPORT_MULTITHREAD +uint32_t wlanSendCommandMthread(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo); + +uint32_t wlanTxCmdMthread(IN struct ADAPTER *prAdapter); + +uint32_t wlanTxCmdDoneMthread(IN struct ADAPTER *prAdapter); + +void wlanClearTxCommandQueue(IN struct ADAPTER *prAdapter); + +void wlanClearTxCommandDoneQueue(IN struct ADAPTER *prAdapter); + +void wlanClearDataQueue(IN struct ADAPTER *prAdapter); + +void wlanClearRxToOsQueue(IN struct ADAPTER *prAdapter); +#endif + +void wlanReleaseCommand(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +void wlanReleasePendingOid(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr); + +void wlanReleasePendingCMDbyBssIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +void wlanReturnPacketDelaySetupTimeout(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr); + +void wlanReturnPacket(IN struct ADAPTER *prAdapter, IN void *pvPacket); + +uint32_t +wlanQueryInformation(IN struct ADAPTER *prAdapter, + IN PFN_OID_HANDLER_FUNC pfOidQryHandler, + IN void *pvInfoBuf, IN uint32_t u4InfoBufLen, + OUT uint32_t *pu4QryInfoLen); + +uint32_t +wlanSetInformation(IN struct ADAPTER *prAdapter, + IN PFN_OID_HANDLER_FUNC pfOidSetHandler, + IN void *pvInfoBuf, IN uint32_t u4InfoBufLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanAdapterStart(IN struct ADAPTER *prAdapter, + IN struct REG_INFO *prRegInfo); + +uint32_t wlanAdapterStop(IN struct ADAPTER *prAdapter); + +uint32_t wlanCheckWifiFunc(IN struct ADAPTER *prAdapter, + IN u_int8_t fgRdyChk); + +#if CFG_SUPPORT_WAPI +u_int8_t wlanQueryWapiMode(IN struct ADAPTER *prAdapter); +#endif + +void wlanReturnRxPacket(IN void *pvAdapter, IN void *pvPacket); + +void wlanRxSetBroadcast(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnableBroadcast); + +u_int8_t wlanIsHandlerNeedHwAccess(IN PFN_OID_HANDLER_FUNC pfnOidHandler, + IN u_int8_t fgSetInfo); + +void wlanSetPromiscuousMode(IN struct ADAPTER *prAdapter, + IN u_int8_t fgEnablePromiscuousMode); + +uint32_t wlanSendDummyCmd(IN struct ADAPTER *prAdapter, + IN u_int8_t fgIsReqTxRsrc); + +uint32_t wlanSendNicPowerCtrlCmd(IN struct ADAPTER *prAdapter, + IN uint8_t ucPowerMode); + +u_int8_t wlanIsHandlerAllowedInRFTest(IN PFN_OID_HANDLER_FUNC pfnOidHandler, + IN u_int8_t fgSetInfo); + +uint32_t wlanProcessQueuedSwRfb(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfbListHead); + +uint32_t wlanProcessQueuedMsduInfo(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfoListHead); + +u_int8_t wlanoidTimeoutCheck(IN struct ADAPTER *prAdapter, + IN PFN_OID_HANDLER_FUNC pfnOidHandler); + +void wlanoidClearTimeoutCheck(IN struct ADAPTER *prAdapter); + +uint32_t wlanUpdateNetworkAddress(IN struct ADAPTER *prAdapter); + +uint32_t wlanUpdateBasicConfig(IN struct ADAPTER *prAdapter); + +u_int8_t wlanQueryTestMode(IN struct ADAPTER *prAdapter); + +u_int8_t wlanProcessTxFrame(IN struct ADAPTER *prAdapter, + IN void *prPacket); + +/* Security Frame Handling */ +u_int8_t wlanProcessSecurityFrame(IN struct ADAPTER *prAdapter, + IN void *prPacket); + +void wlanSecurityFrameTxDone(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, + IN uint8_t *pucEventBuf); + +void wlanSecurityFrameTxTimeout(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo); + +/*----------------------------------------------------------------------------*/ +/* OID/IOCTL Handling */ +/*----------------------------------------------------------------------------*/ +void wlanClearScanningResult(IN struct ADAPTER *prAdapter); + +void wlanClearBssInScanningResult(IN struct ADAPTER *prAdapter, + IN uint8_t *arBSSID); + +#if CFG_TEST_WIFI_DIRECT_GO +void wlanEnableP2pFunction(IN struct ADAPTER *prAdapter); + +void wlanEnableATGO(IN struct ADAPTER *prAdapter); +#endif + +/*----------------------------------------------------------------------------*/ +/* NIC Capability Retrieve by Polling */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanQueryNicCapability(IN struct ADAPTER *prAdapter); + +/*----------------------------------------------------------------------------*/ +/* PD MCR Retrieve by Polling */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanQueryPdMcr(IN struct ADAPTER *prAdapter, + IN struct PARAM_MCR_RW_STRUCT *prMcrRdInfo); + +/*----------------------------------------------------------------------------*/ +/* Loading Manufacture Data */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanLoadManufactureData(IN struct ADAPTER *prAdapter, + IN struct REG_INFO *prRegInfo); + +/*----------------------------------------------------------------------------*/ +/* Media Stream Mode */ +/*----------------------------------------------------------------------------*/ +u_int8_t wlanResetMediaStreamMode(IN struct ADAPTER *prAdapter); + +/*----------------------------------------------------------------------------*/ +/* Timer Timeout Check (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanTimerTimeoutCheck(IN struct ADAPTER *prAdapter); + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Check (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanProcessMboxMessage(IN struct ADAPTER *prAdapter); + +/*----------------------------------------------------------------------------*/ +/* TX Pending Packets Handling (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanEnqueueTxPacket(IN struct ADAPTER *prAdapter, + IN void *prNativePacket); + +uint32_t wlanFlushTxPendingPackets(IN struct ADAPTER *prAdapter); + +uint32_t wlanTxPendingPackets(IN struct ADAPTER *prAdapter, + IN OUT u_int8_t *pfgHwAccess); + +/*----------------------------------------------------------------------------*/ +/* Low Power Acquire/Release (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanAcquirePowerControl(IN struct ADAPTER *prAdapter); + +uint32_t wlanReleasePowerControl(IN struct ADAPTER *prAdapter); + +/*----------------------------------------------------------------------------*/ +/* Pending Packets Number Reporting (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanGetTxPendingFrameCount(IN struct ADAPTER *prAdapter); + +/*----------------------------------------------------------------------------*/ +/* ACPI state inquiry (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +enum ENUM_ACPI_STATE wlanGetAcpiState(IN struct ADAPTER *prAdapter); + +void wlanSetAcpiState(IN struct ADAPTER *prAdapter, + IN enum ENUM_ACPI_STATE ePowerState); + +void wlanDefTxPowerCfg(IN struct ADAPTER *prAdapter); + +/*----------------------------------------------------------------------------*/ +/* get ECO version from Revision ID register (for Win32) */ +/*----------------------------------------------------------------------------*/ +uint8_t wlanGetEcoVersion(IN struct ADAPTER *prAdapter); + +/*----------------------------------------------------------------------------*/ +/* get Rom version */ +/*----------------------------------------------------------------------------*/ +uint8_t wlanGetRomVersion(IN struct ADAPTER *prAdapter); +/*----------------------------------------------------------------------------*/ +/* set preferred band configuration corresponding to network type */ +/*----------------------------------------------------------------------------*/ +void wlanSetPreferBandByNetwork(IN struct ADAPTER *prAdapter, + IN enum ENUM_BAND eBand, IN uint8_t ucBssIndex); + +/*----------------------------------------------------------------------------*/ +/* get currently operating channel information */ +/*----------------------------------------------------------------------------*/ +uint8_t wlanGetChannelNumberByNetwork(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex); + +/*----------------------------------------------------------------------------*/ +/* check for system configuration to generate message on scan list */ +/*----------------------------------------------------------------------------*/ +uint32_t wlanCheckSystemConfiguration(IN struct ADAPTER *prAdapter); + +/*----------------------------------------------------------------------------*/ +/* query bss statistics information from driver and firmware */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryBssStatistics(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +/*----------------------------------------------------------------------------*/ +/* dump per-BSS statistics */ +/*----------------------------------------------------------------------------*/ +void wlanDumpBssStatistics(IN struct ADAPTER *prAdapter, uint8_t ucBssIndex); + +/*----------------------------------------------------------------------------*/ +/* query sta statistics information from driver and firmware */ +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidQueryStaStatistics(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanQueryStaStatistics(IN struct ADAPTER *prAdapter, IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen, + u_int8_t fgIsOid); + +/*----------------------------------------------------------------------------*/ +/* query NIC resource information from chip and reset Tx resource for normal */ +/* operation */ +/*----------------------------------------------------------------------------*/ +void wlanQueryNicResourceInformation(IN struct ADAPTER *prAdapter); + +uint32_t wlanQueryNicCapabilityV2(IN struct ADAPTER *prAdapter); + +void wlanUpdateNicResourceInformation(IN struct ADAPTER *prAdapter); + +/*----------------------------------------------------------------------------*/ +/* GET/SET BSS index mapping for network interfaces */ +/*----------------------------------------------------------------------------*/ +void wlanBindNetInterface(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucNetInterfaceIndex, + IN void *pvNetInterface); + +void wlanBindBssIdxToNetInterface(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucBssIndex, + IN void *pvNetInterface); + +uint8_t wlanGetBssIdxByNetInterface(IN struct GLUE_INFO *prGlueInfo, + IN void *pvNetInterface); + +void *wlanGetNetInterfaceByBssIdx(IN struct GLUE_INFO *prGlueInfo, + IN uint8_t ucBssIndex); + +/* for windows as windows glue cannot see through P_ADAPTER_T */ +uint8_t wlanGetAisBssIndex(IN struct ADAPTER *prAdapter); + +void wlanInitFeatureOption(IN struct ADAPTER *prAdapter); + +void wlanCfgSetSwCtrl(IN struct ADAPTER *prAdapter); + +void wlanCfgSetChip(IN struct ADAPTER *prAdapter); + +void wlanCfgSetDebugLevel(IN struct ADAPTER *prAdapter); + +void wlanCfgSetCountryCode(IN struct ADAPTER *prAdapter); + +struct WLAN_CFG_ENTRY *wlanCfgGetEntry(IN struct ADAPTER *prAdapter, + const int8_t *pucKey, + u_int8_t fgGetCfgRec); + +uint32_t +wlanCfgGet(IN struct ADAPTER *prAdapter, const int8_t *pucKey, int8_t *pucValue, + int8_t *pucValueDef, uint32_t u4Flags); + +uint32_t wlanCfgGetUint32(IN struct ADAPTER *prAdapter, const int8_t *pucKey, + uint32_t u4ValueDef); + +int32_t wlanCfgGetInt32(IN struct ADAPTER *prAdapter, const int8_t *pucKey, + int32_t i4ValueDef); + +uint32_t wlanCfgSetUint32(IN struct ADAPTER *prAdapter, const int8_t *pucKey, + uint32_t u4Value); + +uint32_t wlanCfgSet(IN struct ADAPTER *prAdapter, const int8_t *pucKey, + int8_t *pucValue, uint32_t u4Flags); + +uint32_t wlanCfgSetCb(IN struct ADAPTER *prAdapter, const int8_t *pucKey, + WLAN_CFG_SET_CB pfSetCb, void *pPrivate, + uint32_t u4Flags); + +#if CFG_SUPPORT_EASY_DEBUG + +uint32_t wlanCfgParse(IN struct ADAPTER *prAdapter, uint8_t *pucConfigBuf, + uint32_t u4ConfigBufLen, u_int8_t isFwConfig); +void wlanFeatureToFw(IN struct ADAPTER *prAdapter); +#endif + +void wlanLoadDefaultCustomerSetting(IN struct ADAPTER *prAdapter); + +uint32_t wlanCfgInit(IN struct ADAPTER *prAdapter, uint8_t *pucConfigBuf, + uint32_t u4ConfigBufLen, uint32_t u4Flags); + +uint32_t wlanCfgParseArgument(int8_t *cmdLine, int32_t *argc, int8_t *argv[]); + +#if CFG_WOW_SUPPORT +uint32_t wlanCfgParseArgumentLong(int8_t *cmdLine, int32_t *argc, + int8_t *argv[]); +#endif + +int32_t wlanHexToNum(int8_t c); + +int32_t wlanHexToByte(int8_t *hex); + +int32_t wlanHwAddrToBin(int8_t *txt, uint8_t *addr); + +u_int8_t wlanIsChipNoAck(IN struct ADAPTER *prAdapter); + +u_int8_t wlanIsChipRstRecEnabled(IN struct ADAPTER *prAdapter); + +u_int8_t wlanIsChipAssert(IN struct ADAPTER *prAdapter); + +void wlanChipRstPreAct(IN struct ADAPTER *prAdapter); + +void wlanTxProfilingTagPacket(IN struct ADAPTER *prAdapter, IN void *prPacket, + IN enum ENUM_TX_PROFILING_TAG eTag); + +void wlanTxProfilingTagMsdu(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_PROFILING_TAG eTag); + +void wlanTxLifetimeTagPacket(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfoListHead, + IN enum ENUM_TX_PROFILING_TAG eTag); + +#if CFG_ASSERT_DUMP +void wlanCorDumpTimerInit(IN struct ADAPTER *prAdapter, u_int8_t fgIsResetN9); + +void wlanCorDumpTimerReset(IN struct ADAPTER *prAdapter, u_int8_t fgIsResetN9); + +void wlanN9CorDumpTimeOut(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr); + +void wlanCr4CorDumpTimeOut(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr); +#endif +#endif /* _WLAN_LIB_H */ + + +u_int8_t wlanGetWlanIdxByAddress(IN struct ADAPTER *prAdapter, + IN uint8_t *pucAddr, OUT uint8_t *pucIndex); + +uint8_t *wlanGetStaAddrByWlanIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucIndex); + +struct WLAN_CFG_ENTRY *wlanCfgGetEntryByIndex(IN struct ADAPTER *prAdapter, + const uint8_t ucIdx, + uint32_t flag); + +uint32_t wlanGetStaIdxByWlanIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucIndex, OUT uint8_t *pucStaIdx); + +/*----------------------------------------------------------------------------*/ +/* update per-AC statistics for LLS */ +/*----------------------------------------------------------------------------*/ +void wlanUpdateTxStatistics(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, u_int8_t fgTxDrop); + +void wlanUpdateRxStatistics(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); + +uint32_t wlanTriggerStatsLog(IN struct ADAPTER *prAdapter, + IN uint32_t u4DurationInMs); + +uint32_t wlanPktTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +uint32_t wlanPowerOffWifi(IN struct ADAPTER *prAdapter); + +void wlanPrintVersion(struct ADAPTER *prAdapter); + +uint32_t wlanAccessRegister(IN struct ADAPTER *prAdapter, + IN uint32_t u4Addr, IN uint32_t *pru4Result, + IN uint32_t u4Data, + IN uint8_t ucSetQuery); + +uint32_t wlanAccessRegisterStatus(IN struct ADAPTER + *prAdapter, IN uint8_t ucCmdSeqNum, + IN uint8_t ucSetQuery, IN void *prEvent, + IN uint32_t u4EventLen); + +uint32_t wlanSetChipEcoInfo(IN struct ADAPTER *prAdapter); + +void wlanNotifyFwSuspend(struct GLUE_INFO *prGlueInfo, + struct net_device *prDev, u_int8_t fgSuspend); + +void wlanClearPendingInterrupt(IN struct ADAPTER *prAdapter); + +#if (MTK_WCN_HIF_SDIO && CFG_WMT_WIFI_PATH_SUPPORT) +extern int32_t mtk_wcn_wmt_wifi_fem_cfg_report(void *pvInfoBuf); +#endif + +#if ((CFG_SISO_SW_DEVELOP == 1) || (CFG_SUPPORT_SPE_IDX_CONTROL == 1)) +uint8_t wlanGetAntPathType(IN struct ADAPTER *prAdapter, + IN enum ENUM_WF_PATH_FAVOR_T eWfPathFavor, + IN uint8_t ucBssIndex); +#endif + +uint8_t wlanGetSpeIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN enum ENUM_WF_PATH_FAVOR_T eWfPathFavor); + +uint8_t wlanGetSupportNss(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIndex); + +#if CFG_SUPPORT_LOWLATENCY_MODE +uint32_t wlanAdapterStartForLowLatency(IN struct ADAPTER *prAdapter); +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ +int32_t wlanGetFileContent(struct ADAPTER *prAdapter, + const uint8_t *pcFileName, uint8_t *pucBuf, + uint32_t u4MaxFileLen, uint32_t *pu4ReadFileLen, u_int8_t bReqFw); + +void wlanReleasePendingCmdById(struct ADAPTER *prAdapter, uint8_t ucCid); +void wlanReleaseAllTxCmdQueue(struct ADAPTER *prAdapter); +void wlanWaitCfg80211SuspendDone(struct GLUE_INFO *prGlueInfo); + +uint32_t wlanDecimalStr2Hexadecimals(uint8_t *pucDecimalStr, uint16_t *pu2Out); +uint32_t wlanGetSupportedFeatureSet(IN struct GLUE_INFO *prGlueInfo); + +uint32_t wlanSetEd(IN struct ADAPTER *prAdapter, int32_t u4EdVal2G, + int32_t u4EdVal5G, uint32_t u4Sel); +u_int8_t wlanIsDriverReady(IN struct GLUE_INFO *prGlueInfo); +int wlanSuspendRekeyOffload(struct GLUE_INFO *prGlueInfo, uint8_t ucRekeyMode); +void wlanSuspendPmHandle(struct GLUE_INFO *prGlueInfo); +void wlanResumePmHandle(struct GLUE_INFO *prGlueInfo); +uint32_t wlanWakeUpWiFi(IN struct ADAPTER *prAdapter); + +void disconnect_sta(struct ADAPTER *prAdapter, struct STA_RECORD *prStaRec); + +uint32_t wlanData2RateInMs(uint32_t data, uint32_t interval); +#if CFG_RCPI_COMPENSATION +void wlanLoadEfuseRxFELoss(struct ADAPTER *prAdapter); +void wlanLoadBufferbinRxFELoss(struct ADAPTER *prAdapter); +void wlanUpdateRxFELoss(IN struct SW_RFB *prSwRfb); +uint8_t wlanGetCurrChRxFELoss(struct ADAPTER *prAdapter, + uint8_t ucStaIdx, uint8_t ucAnt); +#endif +#if CFG_SUPPORT_HW_1T2R +void wlanLoadEfuse1T2R(struct ADAPTER *prAdapter); +void wlanLoadBufferbin1T2R(struct ADAPTER *prAdapter); +#endif + +#if CFG_SUPPORT_ADVANCE_CONTROL +uint32_t wlanKeepFullPwr(struct ADAPTER *prAdapter, uint8_t fgEnable); +#endif + +#if CFG_SUPPORT_GET_MCS_INFO +void wlanRxMcsInfoMonitor(struct ADAPTER *prAdapter, + unsigned long ulParamPtr); +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/wlan_oid.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/wlan_oid.h new file mode 100644 index 0000000000000..953b49c831f29 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/wlan_oid.h @@ -0,0 +1,4240 @@ +/******************************************************************************* + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include + * /wlan_oid.h#4 + */ + +/*! \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. + */ + +#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_INITIAL_DBM (-50) +#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 | \ + PARAM_PACKET_FILTER_ALL_MULTICAST) +#endif + +#define PARAM_MEM_DUMP_MAX_SIZE 1536 + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +#define PARAM_CAL_DATA_DUMP_MAX_SIZE 1200 +#define PARAM_CAL_DATA_DUMP_MAX_NUM 300 +#endif + +#define BT_PROFILE_PARAM_LEN 8 + +/* Based on EEPROM layout 20160120 */ +#define EFUSE_ADDR_MAX 0x3BF +#if CFG_SUPPORT_BUFFER_MODE + +/* For MT7668 */ +#define EFUSE_CONTENT_BUFFER_START 0x03A +#define EFUSE_CONTENT_BUFFER_END 0x1D9 +#define EFUSE_CONTENT_BUFFER_SIZE (EFUSE_CONTENT_BUFFER_END - \ + EFUSE_CONTENT_BUFFER_START + 1) + +/* For MT6632 */ +#define EFUSE_CONTENT_SIZE 16 + +#define EFUSE_BLOCK_SIZE 16 +#define EEPROM_SIZE 1184 +#define MAX_EEPROM_BUFFER_SIZE 1536 +#endif /* CFG_SUPPORT_BUFFER_MODE */ + +#if CFG_SUPPORT_TX_BF +#define TXBF_CMD_NEED_TO_RESPONSE(u4TxBfCmdId) \ + (u4TxBfCmdId == BF_PFMU_TAG_READ || \ + u4TxBfCmdId == BF_PROFILE_READ) +#endif /* CFG_SUPPORT_TX_BF */ +#define MU_CMD_NEED_TO_RESPONSE(u4MuCmdId) \ + (u4MuCmdId == MU_GET_CALC_INIT_MCS || \ + u4MuCmdId == MU_HQA_GET_QD || \ + u4MuCmdId == MU_HQA_GET_CALC_LQ) +#if CFG_SUPPORT_MU_MIMO +/* @NITESH: MACROS For Init MCS calculation (MU Metric Table) */ +#define NUM_MUT_FEC 2 +#define NUM_MUT_MCS 10 +#define NUM_MUT_NR_NUM 3 +#define NUM_MUT_INDEX 8 + +#define NUM_OF_USER 2 +#define NUM_OF_MODUL 5 +#endif /* CFG_SUPPORT_MU_MIMO */ + +#define SER_ACTION_QUERY 0 +#define SER_ACTION_SET 1 +#define SER_ACTION_SET_ENABLE_MASK 2 +#define SER_ACTION_RECOVER 3 + + +/* SER_ACTION_SET sub action */ +#define SER_SET_DISABLE 0 +#define SER_SET_ENABLE 1 + +/* SER_ACTION_SET_ENABLE_MASK mask define */ +#define SER_ENABLE_TRACKING BIT(0) +#define SER_ENABLE_L1_RECOVER BIT(1) +#define SER_ENABLE_L2_RECOVER BIT(2) +#define SER_ENABLE_L3_RX_ABORT BIT(3) +#define SER_ENABLE_L3_TX_ABORT BIT(4) +#define SER_ENABLE_L3_TX_DISABLE BIT(5) +#define SER_ENABLE_L3_BF_RECOVER BIT(6) + +/* SER_ACTION_RECOVER recover method */ +#define SER_SET_L0_RECOVER 0 +#define SER_SET_L1_RECOVER 1 +#define SER_SET_L2_RECOVER 2 +#define SER_SET_L3_RX_ABORT 3 +#define SER_SET_L3_TX_ABORT 4 +#define SER_SET_L3_TX_DISABLE 5 +#define SER_SET_L3_BF_RECOVER 6 + + +/* SER user command */ +#define SER_USER_CMD_DISABLE 0 +#define SER_USER_CMD_ENABLE 1 + +#define SER_USER_CMD_QUERY 99 + +#define SER_USER_CMD_ENABLE_MASK_TRACKING_ONLY (200) +#define SER_USER_CMD_ENABLE_MASK_L1_RECOVER_ONLY (201) +#define SER_USER_CMD_ENABLE_MASK_L2_RECOVER_ONLY (202) +#define SER_USER_CMD_ENABLE_MASK_L3_RX_ABORT_ONLY (203) +#define SER_USER_CMD_ENABLE_MASK_L3_TX_ABORT_ONLY (204) +#define SER_USER_CMD_ENABLE_MASK_L3_TX_DISABLE_ONLY (205) +#define SER_USER_CMD_ENABLE_MASK_L3_BFRECOVER_ONLY (206) +#define SER_USER_CMD_ENABLE_MASK_RECOVER_ALL (207) + + +/* Use a magic number to prevent human mistake */ +#define SER_USER_CMD_L0_RECOVER 956 +#define SER_USER_CMD_L1_RECOVER 995 + +#define SER_USER_CMD_L2_BN0_RECOVER (300) +#define SER_USER_CMD_L2_BN1_RECOVER (301) +#define SER_USER_CMD_L3_RX0_ABORT (302) +#define SER_USER_CMD_L3_RX1_ABORT (303) +#define SER_USER_CMD_L3_TX0_ABORT (304) +#define SER_USER_CMD_L3_TX1_ABORT (305) +#define SER_USER_CMD_L3_TX0_DISABLE (306) +#define SER_USER_CMD_L3_TX1_DISABLE (307) +#define SER_USER_CMD_L3_BF_RECOVER (308) + + + +#if (CFG_SUPPORT_TXPOWER_INFO == 1) +/* 1M, 2M, 5.5M, 11M */ +#define MODULATION_SYSTEM_CCK_NUM 4 + +/* 6M, 9M, 12M, 18M, 24M, 36M, 48M, 54M */ +#define MODULATION_SYSTEM_OFDM_NUM 8 + +#define MODULATION_SYSTEM_HT20_NUM 8 /* MCS0~7 */ +#define MODULATION_SYSTEM_HT40_NUM 9 /* MCS0~7, MCS32 */ +#define MODULATION_SYSTEM_VHT20_NUM 10 /* MCS0~9 */ +#define MODULATION_SYSTEM_VHT40_NUM MODULATION_SYSTEM_VHT20_NUM +#define MODULATION_SYSTEM_VHT80_NUM MODULATION_SYSTEM_VHT20_NUM +#define MODULATION_SYSTEM_VHT160_NUM MODULATION_SYSTEM_VHT20_NUM + +#define TXPOWER_RATE_CCK_OFFSET (0) +#define TXPOWER_RATE_OFDM_OFFSET (TXPOWER_RATE_CCK_OFFSET + \ + MODULATION_SYSTEM_CCK_NUM) +#define TXPOWER_RATE_HT20_OFFSET (TXPOWER_RATE_OFDM_OFFSET + \ + MODULATION_SYSTEM_OFDM_NUM) +#define TXPOWER_RATE_HT40_OFFSET (TXPOWER_RATE_HT20_OFFSET + \ + MODULATION_SYSTEM_HT20_NUM) +#define TXPOWER_RATE_VHT20_OFFSET (TXPOWER_RATE_HT40_OFFSET + \ + MODULATION_SYSTEM_HT40_NUM) +#define TXPOWER_RATE_VHT40_OFFSET (TXPOWER_RATE_VHT20_OFFSET + \ + MODULATION_SYSTEM_VHT20_NUM) +#define TXPOWER_RATE_VHT80_OFFSET (TXPOWER_RATE_VHT40_OFFSET + \ + MODULATION_SYSTEM_VHT40_NUM) +#define TXPOWER_RATE_VHT160_OFFSET (TXPOWER_RATE_VHT80_OFFSET + \ + MODULATION_SYSTEM_VHT80_NUM) +#define TXPOWER_RATE_NUM (TXPOWER_RATE_VHT160_OFFSET + \ + MODULATION_SYSTEM_VHT160_NUM) +#endif + +#if CFG_SUPPORT_LOWLATENCY_MODE +#define GED_EVENT_GAS (1 << 4) +#define GED_EVENT_NETWORK (1 << 11) +#define GED_EVENT_DOPT_WIFI_SCAN (1 << 12) +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +/*----------------------------------------------------------------------------*/ +/* Parameters of User Configuration which match to NDIS5.1 */ +/*----------------------------------------------------------------------------*/ +/* NDIS_802_11_AUTHENTICATION_MODE */ +enum ENUM_PARAM_AUTH_MODE { + AUTH_MODE_NON_RSN_FT, /* Fast Bss Transition in a Non FT */ + 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_WPA2_FT, /* Fast Bss Transition for 802.1x */ + AUTH_MODE_WPA2_FT_PSK, /* Fast Bss Transition for WPA2 PSK */ + AUTH_MODE_WPA_OSEN, +#if CFG_SUPPORT_CFG80211_AUTH + AUTH_MODE_WPA2_SAE, +#endif + AUTH_MODE_NUM /*!< Upper bound, not real case */ +}; + +/* NDIS_802_11_ENCRYPTION_STATUS *//* Encryption types */ +enum ENUM_WEP_STATUS { + 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, +#if CFG_SUPPORT_SUITB + ENUM_ENCRYPTION4_ENABLED, + ENUM_ENCRYPTION4_KEY_ABSENT, +#endif + ENUM_ENCRYPTION_NUM +}; + +enum ENUM_PARAM_PHY_TYPE { + 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 ENUM_PARAM_OP_MODE { + 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 */ +}; + +struct PARAM_SSID { + uint32_t u4SsidLen; /*!< SSID length in bytes. + * Zero length is broadcast(any) SSID + */ + uint8_t aucSsid[PARAM_MAX_LEN_SSID]; +}; + +struct PARAM_CONNECT { + uint32_t u4SsidLen; /*!< SSID length in bytes. + * Zero length is broadcast(any) SSID + */ + uint8_t *pucSsid; + uint8_t *pucBssid; + uint8_t *pucBssidHint; + uint32_t u4CenterFreq; +}; + +/* This is enum defined for user to select an AdHoc Mode */ +enum ENUM_PARAM_AD_HOC_MODE { + 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 ENUM_PARAM_MEDIA_STATE { + PARAM_MEDIA_STATE_CONNECTED, + PARAM_MEDIA_STATE_DISCONNECTED, + PARAM_MEDIA_STATE_DISCONNECT_PREV, + /* for following MSDN re-association behavior */ + PARAM_MEDIA_STATE_TO_BE_INDICATED +}; + +enum ENUM_PARAM_NETWORK_TYPE { + 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 */ +}; + +struct PARAM_NETWORK_TYPE_LIST { + uint32_t NumberOfItems; /*!< At least 1 */ + enum ENUM_PARAM_NETWORK_TYPE eNetworkType[1]; +}; + +enum ENUM_PARAM_PRIVACY_FILTER { + PRIVACY_FILTER_ACCEPT_ALL, + PRIVACY_FILTER_8021xWEP, + PRIVACY_FILTER_NUM +}; + +enum ENUM_RELOAD_DEFAULTS { + ENUM_RELOAD_WEP_KEYS +}; + +struct PARAM_PM_PACKET_PATTERN { + uint32_t Priority; /* Importance of the given pattern. */ + uint32_t Reserved; /* Context information for transports. */ + uint32_t MaskSize; /* Size in bytes of the pattern mask. */ + uint32_t PatternOffset; /* Offset from beginning of this */ + /* structure to the pattern bytes. */ + uint32_t PatternSize; /* Size in bytes of the pattern. */ + uint32_t PatternFlags; /* Flags (TBD). */ +}; + + +/* Combine ucTpTestMode and ucSigmaTestMode in one flag */ +/* ucTpTestMode == 0, for normal driver */ +/* ucTpTestMode == 1, for pure throughput test mode (ex: RvR) */ +/* ucTpTestMode == 2, for sigma TGn/TGac/PMF */ +/* ucTpTestMode == 3, for sigma WMM PS */ +enum ENUM_TP_TEST_MODE { + ENUM_TP_TEST_MODE_NORMAL = 0, + ENUM_TP_TEST_MODE_THROUGHPUT, + ENUM_TP_TEST_MODE_SIGMA_AC_N_PMF, + ENUM_TP_TEST_MODE_SIGMA_WMM_PS, + ENUM_TP_TEST_MODE_NUM +}; + +/*--------------------------------------------------------------*/ +/*! \brief Struct definition to indicate specific event. */ +/*--------------------------------------------------------------*/ +enum ENUM_STATUS_TYPE { + ENUM_STATUS_TYPE_AUTHENTICATION, + ENUM_STATUS_TYPE_MEDIA_STREAM_MODE, + ENUM_STATUS_TYPE_CANDIDATE_LIST, + ENUM_STATUS_TYPE_FT_AUTH_STATUS, + ENUM_STATUS_TYPE_NUM /*!< Upper bound, not real case */ +}; + +struct PARAM_802_11_CONFIG_FH { + uint32_t u4Length; /*!< Length of structure */ + uint32_t u4HopPattern; /*!< Defined as 802.11 */ + uint32_t u4HopSet; /*!< to one if non-802.11 */ + uint32_t u4DwellTime; /*!< In unit of Kusec */ +}; + +struct PARAM_802_11_CONFIG { + uint32_t u4Length; /*!< Length of structure */ + uint32_t u4BeaconPeriod; /*!< In unit of Kusec */ + uint32_t u4ATIMWindow; /*!< In unit of Kusec */ + uint32_t u4DSConfig; /*!< Channel frequency in unit of kHz */ + struct PARAM_802_11_CONFIG_FH rFHConfig; +}; + +struct PARAM_STATUS_INDICATION { + enum ENUM_STATUS_TYPE eStatusType; +}; + +struct PARAM_AUTH_REQUEST { + uint32_t u4Length; /*!< Length of this struct */ + uint8_t arBssid[PARAM_MAC_ADDR_LEN]; + uint32_t u4Flags; /*!< Definitions are as follows */ +}; + +struct PARAM_AUTH_EVENT { + struct PARAM_STATUS_INDICATION rStatus; + struct PARAM_AUTH_REQUEST arRequest[1]; +}; + +/*! \brief Capabilities, privacy, rssi and IEs of each BSSID */ +struct PARAM_BSSID_EX { + uint32_t u4Length; /*!< Length of structure */ + uint8_t arMacAddress[PARAM_MAC_ADDR_LEN]; /*!< BSSID */ + uint8_t Reserved[2]; + struct PARAM_SSID rSsid; /*!< SSID */ + uint32_t u4Privacy; /*!< Need WEP encryption */ + int32_t rRssi; /*!< in dBm */ + enum ENUM_PARAM_NETWORK_TYPE eNetworkTypeInUse; + struct PARAM_802_11_CONFIG rConfiguration; + enum ENUM_PARAM_OP_MODE eOpMode; + uint8_t rSupportedRates[PARAM_MAX_LEN_RATES_EX]; + uint32_t u4IELength; + uint8_t aucIEs[1]; +}; + +struct PARAM_BSSID_LIST_EX { + uint32_t u4NumberOfItems; /*!< at least 1 */ + struct PARAM_BSSID_EX arBssid[1]; +}; + +struct PARAM_WEP { + uint32_t u4Length; /*!< Length of structure */ + uint32_t u4KeyIndex; /*!< 0: pairwise key, others group keys */ + uint32_t u4KeyLength; /*!< Key length in bytes */ + uint8_t aucKeyMaterial[32]; /*!< Key content by above setting */ +}; + +/*! \brief Key mapping of BSSID */ +struct PARAM_KEY { + uint32_t u4Length; /*!< Length of structure */ + uint32_t u4KeyIndex; /*!< KeyID */ + uint32_t u4KeyLength; /*!< Key length in bytes */ + uint8_t arBSSID[PARAM_MAC_ADDR_LEN]; /*!< MAC address */ + uint64_t rKeyRSC; + uint8_t ucBssIdx; + uint8_t ucCipher; + uint8_t aucKeyMaterial[32]; /*!< Key content by above setting */ + /* Following add to change the original windows structure */ +}; + +struct PARAM_REMOVE_KEY { + uint32_t u4Length; /*!< Length of structure */ + uint32_t u4KeyIndex; /*!< KeyID */ + uint8_t arBSSID[PARAM_MAC_ADDR_LEN]; /*!< MAC address */ + uint8_t ucBssIdx; +}; + +/*! \brief Default key */ +struct PARAM_DEFAULT_KEY { + uint8_t ucKeyID; + uint8_t ucUnicast; + uint8_t ucMulticast; + uint8_t ucBssIdx; +}; + +#if CFG_SUPPORT_WAPI +enum ENUM_KEY_TYPE { + ENUM_WPI_PAIRWISE_KEY = 0, + ENUM_WPI_GROUP_KEY +}; + +enum ENUM_WPI_PROTECT_TYPE { + ENUM_WPI_NONE, + ENUM_WPI_RX, + ENUM_WPI_TX, + ENUM_WPI_RX_TX +}; + +struct PARAM_WPI_KEY { + enum ENUM_KEY_TYPE eKeyType; + enum ENUM_WPI_PROTECT_TYPE eDirection; + uint8_t ucKeyID; + uint8_t aucRsv[3]; + uint8_t aucAddrIndex[12]; + uint32_t u4LenWPIEK; + uint8_t aucWPIEK[256]; + uint32_t u4LenWPICK; + uint8_t aucWPICK[256]; + uint8_t aucPN[16]; +}; +#endif + +enum PARAM_POWER_MODE { + Param_PowerModeCAM, + Param_PowerModeMAX_PSP, + Param_PowerModeFast_PSP, + Param_PowerModeMax /* Upper bound, not real case */ +}; + +enum PARAM_DEVICE_POWER_STATE { + ParamDeviceStateUnspecified = 0, + ParamDeviceStateD0, + ParamDeviceStateD1, + ParamDeviceStateD2, + ParamDeviceStateD3, + ParamDeviceStateMaximum +}; + +struct PARAM_POWER_MODE_ { + uint8_t ucBssIdx; + enum PARAM_POWER_MODE ePowerMode; +}; + +#if CFG_SUPPORT_802_11D + +/*! \brief The enumeration definitions for OID_IPN_MULTI_DOMAIN_CAPABILITY */ +enum PARAM_MULTI_DOMAIN_CAPABILITY { + ParamMultiDomainCapDisabled, + ParamMultiDomainCapEnabled +}; +#endif + +struct COUNTRY_STRING_ENTRY { + uint8_t aucCountryCode[2]; + uint8_t aucEnvironmentCode[2]; +}; + +/* 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) + +enum ENUM_POWER_SAVE_PROFILE { + ENUM_PSP_CONTINUOUS_ACTIVE = 0, + ENUM_PSP_CONTINUOUS_POWER_SAVE, + ENUM_PSP_FAST_SWITCH, + ENUM_PSP_NUM +}; + +/*--------------------------------------------------------------*/ +/*! \brief Set/Query testing type. */ +/*--------------------------------------------------------------*/ +struct PARAM_802_11_TEST { + uint32_t u4Length; + uint32_t u4Type; + union { + struct PARAM_AUTH_EVENT AuthenticationEvent; + int32_t RssiTrigger; + } u; +}; + +/*--------------------------------------------------------------*/ +/*! \brief Set/Query authentication and encryption capability. */ +/*--------------------------------------------------------------*/ +struct PARAM_AUTH_ENCRYPTION { + enum ENUM_PARAM_AUTH_MODE eAuthModeSupported; + enum ENUM_WEP_STATUS eEncryptStatusSupported; +}; + +struct PARAM_CAPABILITY { + uint32_t u4Length; + uint32_t u4Version; + uint32_t u4NoOfPMKIDs; + uint32_t u4NoOfAuthEncryptPairsSupported; + struct PARAM_AUTH_ENCRYPTION + arAuthenticationEncryptionSupported[1]; +}; + +struct PARAM_BSSID_INFO { + uint8_t arBSSID[PARAM_MAC_ADDR_LEN]; + uint8_t arPMKID[16]; +}; + +struct PARAM_PMKID { + uint32_t u4Length; + uint32_t u4BSSIDInfoCount; + struct PARAM_BSSID_INFO arBSSIDInfo[1]; +}; + +/*! \brief PMKID candidate lists. */ +struct PARAM_PMKID_CANDIDATE { + uint8_t arBSSID[PARAM_MAC_ADDR_LEN]; + uint32_t u4Flags; +}; + +/* #ifdef LINUX */ +struct PARAM_PMKID_CANDIDATE_LIST { + uint32_t u4Version; /*!< Version */ + uint32_t u4NumCandidates; /*!< How many candidates follow */ + struct PARAM_PMKID_CANDIDATE arCandidateList[1]; +}; +/* #endif */ + +#define NL80211_KCK_LEN 16 +#define NL80211_KEK_LEN 16 +#define NL80211_REPLAY_CTR_LEN 8 +#define NL80211_KEYRSC_LEN 8 + +struct PARAM_GTK_REKEY_DATA { + uint8_t aucKek[NL80211_KEK_LEN]; + uint8_t aucKck[NL80211_KCK_LEN]; + uint8_t aucReplayCtr[NL80211_REPLAY_CTR_LEN]; + uint8_t ucBssIndex; + uint8_t ucRekeyMode; + uint8_t ucCurKeyId; + uint8_t ucRsv; + uint32_t u4Proto; + uint32_t u4PairwiseCipher; + uint32_t u4GroupCipher; + uint32_t u4KeyMgmt; + uint32_t u4MgmtGroupCipher; +}; + +struct PARAM_CUSTOM_MCR_RW_STRUCT { + uint32_t u4McrOffset; + uint32_t u4McrData; +}; + +#define COEX_CTRL_BUF_LEN 460 +/************************************************/ +/* uint32_t u4SubCmd : Coex Ctrl Sub Command */ +/* uint8_t aucBuffer : Reserve for Sub Command */ +/* Data Structure */ +/************************************************/ +struct PARAM_COEX_HANDLER { + uint32_t u4SubCmd; + uint8_t aucBuffer[COEX_CTRL_BUF_LEN]; +}; + +/************************************************/ +/* uint32_t u4IsoPath : WF Path (WF0/WF1) */ +/* uint32_t u4Channel : WF Channel */ +/* uint32_t u4Isolation : Isolation value */ +/************************************************/ +struct PARAM_COEX_ISO_DETECT { + uint32_t u4IsoPath; + uint32_t u4Channel; + uint32_t u4Isolation; +}; + +/************************************************/ +/* char cCoexInfo[]; */ +/************************************************/ +struct PARAM_COEX_GET_INFO { + uint8_t ucCoexInfo[COEX_CTRL_BUF_LEN]; +}; + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +/* + * Description of Each Parameters : + * ucReason : + * 0 : Query Information of Thermal or Cal Data Length + * 1 : Trigger FW do or don't All Cal + * 2 : Dump Data to Host + * 3 : Send Backupped Cal Data to FW + * 4 : For Debug Use, Tell FW Print Cal Data (Rom or Ram) + * ucAction : + * 0 : Read Thermal Value + * 1 : Ask the Cal Data Total Length (Rom and Ram) + * 2 : Tell FW do All Cal + * 3 : Tell FW don't do Cal + * 4 : Dump Data to Host (Rom or Ram) + * 5 : Send Backupped Cal Data to FW (Rom or Ram) + * 6 : For Debug Use, Tell FW Print Cal Data (Rom or Ram) + * ucNeedResp : + * 0 : FW No Need to Response an EVENT + * 1 : FW Need to Response an EVENT + * ucFragNum : + * Sequence Number + * ucRomRam : + * 0 : Operation for Rom Cal Data + * 1 : Operation for Ram Cal Data + * u4ThermalValue : + * Field for filling the Thermal Value in FW + * u4Address : + * Dumpped Starting Address + * Used for Dump and Send Cal Data Between Driver and FW + * u4Length : + * Memory Size need to allocated in Driver or Data Size in an EVENT + * Used for Dump and Send Cal Data Between Driver and FW + * u4RemainLength : + * Remain Length need to Dump + * Used for Dump and Send Cal Data Between Driver and FW + */ +struct PARAM_CAL_BACKUP_STRUCT_V2 { + uint8_t ucReason; + uint8_t ucAction; + uint8_t ucNeedResp; + uint8_t ucFragNum; + uint8_t ucRomRam; + uint32_t u4ThermalValue; + uint32_t u4Address; + uint32_t u4Length; + uint32_t u4RemainLength; +}; +#endif + +#if CFG_SUPPORT_QA_TOOL +#if CFG_SUPPORT_BUFFER_MODE +struct BIN_CONTENT { + uint16_t u2Addr; + uint8_t ucValue; + uint8_t ucReserved; +}; + +struct PARAM_CUSTOM_EFUSE_BUFFER_MODE { + uint8_t ucSourceMode; + uint8_t ucCount; + uint8_t ucCmdType; + uint8_t ucReserved; + uint8_t aBinContent[MAX_EEPROM_BUFFER_SIZE]; +}; + +struct PARAM_CUSTOM_EFUSE_BUFFER_MODE_CONNAC_T { + uint8_t ucSourceMode; + uint8_t ucContentFormat; + uint16_t u2Count; + uint8_t aBinContent[MAX_EEPROM_BUFFER_SIZE]; +}; + +/*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ +struct PARAM_CUSTOM_ACCESS_EFUSE { + uint32_t u4Address; + uint32_t u4Valid; + uint8_t aucData[16]; +}; + +struct PARAM_CUSTOM_EFUSE_FREE_BLOCK { + uint8_t ucGetFreeBlock; + uint8_t aucReserved[3]; +}; + +struct PARAM_CUSTOM_GET_TX_POWER { + uint8_t ucTxPwrType; + uint8_t ucCenterChannel; + uint8_t ucDbdcIdx; /* 0:Band 0, 1: Band1 */ + uint8_t ucBand; /* 0:G-band 1: A-band*/ + uint8_t ucReserved[4]; +}; + +/*#endif*/ + +#endif /* CFG_SUPPORT_BUFFER_MODE */ + +struct PARAM_CUSTOM_SET_TX_TARGET_POWER { + int8_t cTxPwr2G4Cck; /* signed, in unit of 0.5dBm */ + int8_t cTxPwr2G4Dsss; /* signed, in unit of 0.5dBm */ + uint8_t ucTxTargetPwr; /* Tx target power base for all*/ + uint8_t ucReserved; + + int8_t cTxPwr2G4OFDM_BPSK; + int8_t cTxPwr2G4OFDM_QPSK; + int8_t cTxPwr2G4OFDM_16QAM; + int8_t cTxPwr2G4OFDM_Reserved; + int8_t cTxPwr2G4OFDM_48Mbps; + int8_t cTxPwr2G4OFDM_54Mbps; + + int8_t cTxPwr2G4HT20_BPSK; + int8_t cTxPwr2G4HT20_QPSK; + int8_t cTxPwr2G4HT20_16QAM; + int8_t cTxPwr2G4HT20_MCS5; + int8_t cTxPwr2G4HT20_MCS6; + int8_t cTxPwr2G4HT20_MCS7; + + int8_t cTxPwr2G4HT40_BPSK; + int8_t cTxPwr2G4HT40_QPSK; + int8_t cTxPwr2G4HT40_16QAM; + int8_t cTxPwr2G4HT40_MCS5; + int8_t cTxPwr2G4HT40_MCS6; + int8_t cTxPwr2G4HT40_MCS7; + + int8_t cTxPwr5GOFDM_BPSK; + int8_t cTxPwr5GOFDM_QPSK; + int8_t cTxPwr5GOFDM_16QAM; + int8_t cTxPwr5GOFDM_Reserved; + int8_t cTxPwr5GOFDM_48Mbps; + int8_t cTxPwr5GOFDM_54Mbps; + + int8_t cTxPwr5GHT20_BPSK; + int8_t cTxPwr5GHT20_QPSK; + int8_t cTxPwr5GHT20_16QAM; + int8_t cTxPwr5GHT20_MCS5; + int8_t cTxPwr5GHT20_MCS6; + int8_t cTxPwr5GHT20_MCS7; + + int8_t cTxPwr5GHT40_BPSK; + int8_t cTxPwr5GHT40_QPSK; + int8_t cTxPwr5GHT40_16QAM; + int8_t cTxPwr5GHT40_MCS5; + int8_t cTxPwr5GHT40_MCS6; + int8_t cTxPwr5GHT40_MCS7; +}; + +#if (CFG_SUPPORT_DFS_MASTER == 1) +struct PARAM_CUSTOM_SET_RDD_REPORT { + uint8_t ucDbdcIdx; /* 0:Band 0, 1: Band1 */ +}; + +struct PARAM_CUSTOM_SET_RADAR_DETECT_MODE { + /* 0:Switch channel, 1: Don't switch channel */ + uint8_t ucRadarDetectMode; +}; +#endif + +struct PARAM_CUSTOM_ACCESS_RX_STAT { + uint32_t u4SeqNum; + uint32_t u4TotalNum; +}; + +/* Ext DevInfo Tag */ +enum EXT_ENUM_DEVINFO_TAG_HANDLE { + DEV_INFO_ACTIVE = 0, + DEV_INFO_BSSID, + DEV_INFO_MAX_NUM +}; + +/* STA record TLV tag */ +enum EXT_ENUM_STAREC_TAG_HANDLE { + STA_REC_BASIC = 0, + STA_REC_RA, + STA_REC_RA_COMMON_INFO, + STA_REC_RA_UPDATE, + STA_REC_BF, + STA_REC_MAUNAL_ASSOC, + STA_REC_BA = 6, + STA_REC_MAX_NUM +}; + +#if CFG_SUPPORT_TX_BF +enum BF_ACTION_CATEGORY { + BF_SOUNDING_OFF = 0, + BF_SOUNDING_ON, + BF_DATA_PACKET_APPLY, + BF_PFMU_MEM_ALLOCATE, + BF_PFMU_MEM_RELEASE, + BF_PFMU_TAG_READ, + BF_PFMU_TAG_WRITE, + BF_PROFILE_READ, + BF_PROFILE_WRITE, + BF_PN_READ, + BF_PN_WRITE, + BF_PFMU_MEM_ALLOC_MAP_READ, +#if CFG_SUPPORT_TX_BF_FPGA + BF_PFMU_SW_TAG_WRITE = 24 +#endif +}; + +enum { + DEVINFO_ACTIVE = 0, + DEVINFO_MAX_NUM = 1, +}; + +enum { + DEVINFO_ACTIVE_FEATURE = (1 << DEVINFO_ACTIVE), + DEVINFO_MAX_NUM_FEATURE = (1 << DEVINFO_MAX_NUM) +}; + +enum { + BSS_INFO_OWN_MAC = 0, + BSS_INFO_BASIC = 1, + BSS_INFO_RF_CH = 2, + BSS_INFO_PM = 3, + BSS_INFO_UAPSD = 4, + BSS_INFO_ROAM_DETECTION = 5, + BSS_INFO_LQ_RM = 6, + BSS_INFO_EXT_BSS = 7, + BSS_INFO_BROADCAST_INFO = 8, + BSS_INFO_SYNC_MODE = 9, + BSS_INFO_MAX_NUM +}; + +union PFMU_PROFILE_TAG1 { + struct { + /* [6:0] : 0 ~ 63 */ + uint32_t ucProfileID: 7; + + /* [7] : 0: iBF, 1: eBF */ + uint32_t ucTxBf: 1; + + /* [9:8] : 0/1/2/3: DW20/40/80/160NC */ + uint32_t ucDBW: 2; + + /* [10] : 0:SU, 1: MU */ + uint32_t ucSU_MU: 1; + + /* [11] : 0: default, 1: This profile number is invalid by SW */ + uint32_t ucInvalidProf: 1; + + /* [14:12] : RMSD value from CE */ + uint32_t ucRMSD: 3; + + /* [17 : 15] : column index : 0 ~ 5 */ + uint32_t ucMemAddr1ColIdx: 3; + + /* [23 : 18] : row index : 0 ~ 63 */ + uint32_t ucMemAddr1RowIdx: 6; + + /* [26 : 24] : column index : 0 ~ 5 */ + uint32_t ucMemAddr2ColIdx: 3; + + /* [31 : 27] : row index : 0 ~ 63 */ + uint32_t ucMemAddr2RowIdx: 5; + + /* [32] : MSB of row index */ + uint32_t ucMemAddr2RowIdxMsb: 1; + + /* [35 : 33] : column index : 0 ~ 5 */ + uint32_t ucMemAddr3ColIdx: 3; + + /* [41 : 36] : row index : 0 ~ 63 */ + uint32_t ucMemAddr3RowIdx: 6; + + /* [44 : 42] : column index : 0 ~ 5 */ + uint32_t ucMemAddr4ColIdx: 3; + + /* [50 : 45] : row index : 0 ~ 63 */ + uint32_t ucMemAddr4RowIdx: 6; + + /* [51] : Reserved */ + uint32_t ucReserved: 1; + + /* [53 : 52] : Nrow */ + uint32_t ucNrow: 2; + + /* [55 : 54] : Ncol */ + uint32_t ucNcol: 2; + + /* [57 : 56] : Ngroup */ + uint32_t ucNgroup: 2; + + /* [59 : 58] : 0/1/2 */ + uint32_t ucLM: 2; + + /* [61:60] : Code book */ + uint32_t ucCodeBook: 2; + + /* [62] : HtcExist */ + uint32_t ucHtcExist: 1; + + /* [63] : Reserved */ + uint32_t ucReserved1: 1; + + /* [71:64] : SNR_STS0 */ + uint32_t ucSNR_STS0: 8; + + /* [79:72] : SNR_STS1 */ + uint32_t ucSNR_STS1: 8; + + /* [87:80] : SNR_STS2 */ + uint32_t ucSNR_STS2: 8; + + /* [95:88] : SNR_STS3 */ + uint32_t ucSNR_STS3: 8; + + /* [103:96] : iBF LNA index */ + uint32_t ucIBfLnaIdx: 8; + } rField; + uint32_t au4RawData[4]; +}; + +union PFMU_PROFILE_TAG2 { + struct { + uint32_t u2SmartAnt: 12;/* [11:0] : Smart Ant config */ + uint32_t ucReserved0: 3;/* [14:12] : Reserved */ + uint32_t ucSEIdx: 5; /* [19:15] : SE index */ + uint32_t ucRMSDThd: 3; /* [22:20] : RMSD Threshold */ + uint32_t ucReserved1: 1;/* [23] : Reserved */ + uint32_t ucMCSThL1SS: 4;/* [27:24] : MCS TH long 1SS */ + uint32_t ucMCSThS1SS: 4;/* [31:28] : MCS TH short 1SS */ + uint32_t ucMCSThL2SS: 4;/* [35:32] : MCS TH long 2SS */ + uint32_t ucMCSThS2SS: 4;/* [39:36] : MCS TH short 2SS */ + uint32_t ucMCSThL3SS: 4;/* [43:40] : MCS TH long 3SS */ + uint32_t ucMCSThS3SS: 4;/* [47:44] : MCS TH short 3SS */ + uint32_t uciBfTimeOut: 8;/* [55:48] : iBF timeout limit */ + uint32_t ucReserved2: 8;/* [63:56] : Reserved */ + uint32_t ucReserved3: 8;/* [71:64] : Reserved */ + uint32_t ucReserved4: 8;/* [79:72] : Reserved */ + uint32_t uciBfDBW: 2; /* [81:80] : iBF desired DBW 0/1/2/3 : + * BW20/40/80/160NC + */ + uint32_t uciBfNcol: 2; /* [83:82] : iBF desired Ncol = 1 ~ 3 */ + uint32_t uciBfNrow: 2; /* [85:84] : iBF desired Nrow = 1 ~ 4 */ + uint32_t u2Reserved5: 10;/* [95:86] : Reserved */ + } rField; + uint32_t au4RawData[3]; +}; + +union PFMU_DATA { + struct { + uint32_t u2Phi11: 9; + uint32_t ucPsi21: 7; + uint32_t u2Phi21: 9; + uint32_t ucPsi31: 7; + uint32_t u2Phi31: 9; + uint32_t ucPsi41: 7; + uint32_t u2Phi22: 9; + uint32_t ucPsi32: 7; + uint32_t u2Phi32: 9; + uint32_t ucPsi42: 7; + uint32_t u2Phi33: 9; + uint32_t ucPsi43: 7; + uint32_t u2dSNR00: 4; + uint32_t u2dSNR01: 4; + uint32_t u2dSNR02: 4; + uint32_t u2dSNR03: 4; + uint32_t u2Reserved: 16; + } rField; + uint32_t au4RawData[5]; +}; + +struct PROFILE_TAG_READ { + uint8_t ucTxBfCategory; + uint8_t ucProfileIdx; + u_int8_t fgBfer; + uint8_t ucRsv; +}; + +struct PROFILE_TAG_WRITE { + uint8_t ucTxBfCategory; + uint8_t ucPfmuId; + uint8_t ucBuffer[28]; +}; + +struct PROFILE_DATA_READ { + uint8_t ucTxBfCategory; + uint8_t ucPfmuIdx; + u_int8_t fgBFer; + uint8_t ucReserved[3]; + uint8_t ucSubCarrIdxLsb; + uint8_t ucSubCarrIdxMsb; +}; + +struct PROFILE_DATA_WRITE { + uint8_t ucTxBfCategory; + uint8_t ucPfmuIdx; + uint8_t u2SubCarrIdxLsb; + uint8_t u2SubCarrIdxMsb; + union PFMU_DATA rTxBfPfmuData; +}; + +struct PROFILE_PN_READ { + uint8_t ucTxBfCategory; + uint8_t ucPfmuIdx; + uint8_t ucReserved[2]; +}; + +struct PROFILE_PN_WRITE { + uint8_t ucTxBfCategory; + uint8_t ucPfmuIdx; + uint16_t u2bw; + uint8_t ucBuf[32]; +}; + +enum BF_SOUNDING_MODE { + SU_SOUNDING = 0, + MU_SOUNDING, + SU_PERIODIC_SOUNDING, + MU_PERIODIC_SOUNDING, + AUTO_SU_PERIODIC_SOUNDING +}; + +struct EXT_CMD_ETXBf_SND_PERIODIC_TRIGGER_CTRL { + uint8_t ucCmdCategoryID; + uint8_t ucSuMuSndMode; + uint8_t ucWlanIdx; + uint32_t u4SoundingInterval; /* By ms */ +}; + +struct EXT_CMD_ETXBf_MU_SND_PERIODIC_TRIGGER_CTRL { + uint8_t ucCmdCategoryID; + uint8_t ucSuMuSndMode; + uint8_t ucWlanId[4]; + uint8_t ucStaNum; + uint32_t u4SoundingInterval; /* By ms */ +}; + +/* Device information (Tag0) */ +struct CMD_DEVINFO_ACTIVE { + uint16_t u2Tag; /* Tag = 0x00 */ + uint16_t u2Length; + uint8_t ucActive; + uint8_t ucBandNum; + uint8_t aucOwnMacAddr[6]; + uint8_t aucReserve[4]; +}; + +struct BSSINFO_BASIC { + /* Basic BSS information (Tag1) */ + uint16_t u2Tag; /* Tag = 0x01 */ + uint16_t u2Length; + uint32_t u4NetworkType; + uint8_t ucActive; + uint8_t ucReserve0; + uint16_t u2BcnInterval; + uint8_t aucBSSID[6]; + uint8_t ucWmmIdx; + uint8_t ucDtimPeriod; + uint8_t ucBcMcWlanidx; /* indicate which wlan-idx used for MC/BC + * transmission. + */ + uint8_t ucCipherSuit; + uint8_t acuReserve[6]; +}; + +struct TXBF_PFMU_STA_INFO { + uint16_t u2PfmuId; /* 0xFFFF means no access right for PFMU */ + uint8_t fgSU_MU; /* 0 : SU, 1 : MU */ + uint8_t fgETxBfCap; /* 0 : ITxBf, 1 : ETxBf */ + uint8_t ucSoundingPhy; /* 0: legacy, 1: OFDM, 2: HT, 4: VHT */ + uint8_t ucNdpaRate; + uint8_t ucNdpRate; + uint8_t ucReptPollRate; + uint8_t ucTxMode; /* 0: legacy, 1: OFDM, 2: HT, 4: VHT */ + uint8_t ucNc; + uint8_t ucNr; + uint8_t ucCBW; /* 0 : 20M, 1 : 40M, 2 : 80M, 3 : 80 + 80M */ + uint8_t ucTotMemRequire; + uint8_t ucMemRequire20M; + uint8_t ucMemRow0; + uint8_t ucMemCol0; + uint8_t ucMemRow1; + uint8_t ucMemCol1; + uint8_t ucMemRow2; + uint8_t ucMemCol2; + uint8_t ucMemRow3; + uint8_t ucMemCol3; + uint16_t u2SmartAnt; + uint8_t ucSEIdx; + uint8_t ucAutoSoundingCtrl; + uint8_t uciBfTimeOut; + uint8_t uciBfDBW; + uint8_t uciBfNcol; + uint8_t uciBfNrow; + uint8_t aucReserved[2]; +}; + +struct STA_REC_UPD_ENTRY { + struct TXBF_PFMU_STA_INFO rTxBfPfmuStaInfo; + uint8_t aucAddr[PARAM_MAC_ADDR_LEN]; + uint8_t ucAid; + uint8_t ucRsv; +}; + +struct STAREC_COMMON { + /* Basic STA record (Group0) */ + uint16_t u2Tag; /* Tag = 0x00 */ + uint16_t u2Length; + uint32_t u4ConnectionType; + uint8_t ucConnectionState; + uint8_t ucIsQBSS; + uint16_t u2AID; + uint8_t aucPeerMacAddr[6]; + uint16_t u2Reserve1; +}; + +struct CMD_STAREC_BF { + uint16_t u2Tag; /* Tag = 0x02 */ + uint16_t u2Length; + struct TXBF_PFMU_STA_INFO rTxBfPfmuInfo; + uint8_t ucReserved[3]; +}; + +/* QA tool: maunal assoc */ +struct CMD_MANUAL_ASSOC_STRUCT { + /* + * uint8_t ucBssIndex; + * uint8_t ucWlanIdx; + * uint16_t u2TotalElementNum; + * uint32_t u4Reserve; + */ + /* extension */ + uint16_t u2Tag; /* Tag = 0x05 */ + uint16_t u2Length; + uint8_t aucMac[MAC_ADDR_LEN]; + uint8_t ucType; + uint8_t ucWtbl; + uint8_t ucOwnmac; + uint8_t ucMode; + uint8_t ucBw; + uint8_t ucNss; + uint8_t ucPfmuId; + uint8_t ucMarate; + uint8_t ucSpeIdx; + uint8_t ucaid; +}; + +struct TX_BF_SOUNDING_START { + union { + struct EXT_CMD_ETXBf_SND_PERIODIC_TRIGGER_CTRL + rExtCmdExtBfSndPeriodicTriggerCtrl; + struct EXT_CMD_ETXBf_MU_SND_PERIODIC_TRIGGER_CTRL + rExtCmdExtBfMuSndPeriodicTriggerCtrl; + } rTxBfSounding; +}; + +struct TX_BF_SOUNDING_STOP { + uint8_t ucTxBfCategory; + uint8_t ucSndgStop; + uint8_t ucReserved[2]; +}; + +struct TX_BF_TX_APPLY { + uint8_t ucTxBfCategory; + uint8_t ucWlanId; + uint8_t fgETxBf; + uint8_t fgITxBf; + uint8_t fgMuTxBf; + uint8_t ucReserved[3]; +}; + +struct TX_BF_PFMU_MEM_ALLOC { + uint8_t ucTxBfCategory; + uint8_t ucSuMuMode; + uint8_t ucWlanIdx; + uint8_t ucReserved; +}; + +struct TX_BF_PFMU_MEM_RLS { + uint8_t ucTxBfCategory; + uint8_t ucWlanId; + uint8_t ucReserved[2]; +}; + +#if CFG_SUPPORT_TX_BF_FPGA +struct TX_BF_PROFILE_SW_TAG_WRITE { + uint8_t ucTxBfCategory; + uint8_t ucLm; + uint8_t ucNr; + uint8_t ucNc; + uint8_t ucBw; + uint8_t ucCodebook; + uint8_t ucgroup; + uint8_t ucReserved; +}; +#endif + +union PARAM_CUSTOM_TXBF_ACTION_STRUCT { + struct PROFILE_TAG_READ rProfileTagRead; + struct PROFILE_TAG_WRITE rProfileTagWrite; + struct PROFILE_DATA_READ rProfileDataRead; + struct PROFILE_DATA_WRITE rProfileDataWrite; + struct PROFILE_PN_READ rProfilePnRead; + struct PROFILE_PN_WRITE rProfilePnWrite; + struct TX_BF_SOUNDING_START rTxBfSoundingStart; + struct TX_BF_SOUNDING_STOP rTxBfSoundingStop; + struct TX_BF_TX_APPLY rTxBfTxApply; + struct TX_BF_PFMU_MEM_ALLOC rTxBfPfmuMemAlloc; + struct TX_BF_PFMU_MEM_RLS rTxBfPfmuMemRls; +#if CFG_SUPPORT_TX_BF_FPGA + struct TX_BF_PROFILE_SW_TAG_WRITE rTxBfProfileSwTagWrite; +#endif +}; + +struct PARAM_CUSTOM_STA_REC_UPD_STRUCT { + uint8_t ucBssIndex; + uint8_t ucWlanIdx; + uint16_t u2TotalElementNum; + uint8_t ucAppendCmdTLV; + uint8_t ucMuarIdx; + uint8_t aucReserve[2]; + uint32_t *prStaRec; + struct CMD_STAREC_BF rCmdStaRecBf; +}; + +struct BSSINFO_ARGUMENT { + uint8_t OwnMacIdx; + uint8_t ucBssIndex; + uint8_t Bssid[PARAM_MAC_ADDR_LEN]; + uint8_t ucBcMcWlanIdx; + uint8_t ucPeerWlanIdx; + uint32_t NetworkType; + uint32_t u4ConnectionType; + uint8_t CipherSuit; + uint8_t Active; + uint8_t WmmIdx; + uint32_t u4BssInfoFeature; + uint8_t aucBuffer[0]; +}; + +struct PARAM_CUSTOM_PFMU_TAG_READ_STRUCT { + union PFMU_PROFILE_TAG1 ru4TxBfPFMUTag1; + union PFMU_PROFILE_TAG2 ru4TxBfPFMUTag2; +}; + +#if CFG_SUPPORT_MU_MIMO +struct PARAM_CUSTOM_SHOW_GROUP_TBL_ENTRY_STRUCT { + uint32_t u4EventId; + uint8_t index; + uint8_t numUser: 2; + uint8_t BW: 2; + uint8_t NS0: 2; + uint8_t NS1: 2; + /* UINT_8 NS2:1; */ + /* UINT_8 NS3:1; */ + uint8_t PFIDUser0; + uint8_t PFIDUser1; + /* UINT_8 PFIDUser2; */ + /* UINT_8 PFIDUser3; */ + u_int8_t fgIsShortGI; + u_int8_t fgIsUsed; + u_int8_t fgIsDisable; + uint8_t initMcsUser0: 4; + uint8_t initMcsUser1: 4; + /* UINT_8 initMcsUser2:4; */ + /* UINT_8 initMcsUser3:4; */ + uint8_t dMcsUser0: 4; + uint8_t dMcsUser1: 4; + /* UINT_8 dMcsUser2:4; */ + /* UINT_8 dMcsUser3:4; */ +}; + +struct PARAM_CUSTOM_GET_QD_STRUCT { + uint32_t u4EventId; + uint32_t au4RawData[14]; +}; + +struct MU_STRUCT_LQ_REPORT { + int lq_report[NUM_OF_USER][NUM_OF_MODUL]; +}; + +struct PARAM_CUSTOM_GET_MU_CALC_LQ_STRUCT { + uint32_t u4EventId; + struct MU_STRUCT_LQ_REPORT rEntry; +}; + +struct MU_GET_CALC_INIT_MCS { + uint8_t ucgroupIdx; + uint8_t ucRsv[3]; +}; + +struct MU_SET_INIT_MCS { + uint8_t ucNumOfUser; /* zero-base: 0~3: means 1~2 users */ + uint8_t ucBandwidth; /* zero-base: 0:20 hz 1:40 hz 2: 80 hz 3: 160 */ + uint8_t ucNssOfUser0; /* zero-base: 0~1 means uesr0 use 1~2 ss, + * if no use keep 0 + */ + uint8_t ucNssOfUser1; /* zero-base: 0~1 means uesr0 use 1~2 ss, + * if no use keep 0 + */ + uint8_t ucPfMuIdOfUser0;/* zero-base: for now, uesr0 use pf mu id 0 */ + uint8_t ucPfMuIdOfUser1;/* zero-base: for now, uesr1 use pf mu id 1 */ + uint8_t ucNumOfTxer; /* 0~3: mean use 1~4 anntain, for now, + * should fix 3 + */ + uint8_t ucSpeIndex; /* add new field to fill"special extension + * index" which replace reserve + */ + uint32_t u4GroupIndex; /* 0~ :the index of group table entry for + * calculation + */ +}; + +struct MU_SET_CALC_LQ { + uint8_t ucNumOfUser; /* zero-base: 0~3: means 1~2 users */ + uint8_t ucBandwidth; /* zero-base: 0:20 hz 1:40 hz 2: 80 hz 3: 160 */ + uint8_t ucNssOfUser0; /* zero-base: 0~1 means uesr0 use 1~2 ss, + * if no use keep 0 + */ + uint8_t ucNssOfUser1; /* zero-base: 0~1 means uesr0 use 1~2 ss, + * if no use keep 0 + */ + uint8_t ucPfMuIdOfUser0;/* zero-base: for now, uesr0 use pf mu id 0 */ + uint8_t ucPfMuIdOfUser1;/* zero-base: for now, uesr1 use pf mu id 1 */ + uint8_t ucNumOfTxer; /* 0~3: mean use 1~4 anntain, for now, + * should fix 3 + */ + uint8_t ucSpeIndex; /* add new field to fill"special extension + * index" which replace reserve + */ + uint32_t u4GroupIndex; /* 0~ : the index of group table entry for + * calculation + */ +}; + +struct MU_GET_LQ { + uint8_t ucType; + uint8_t ucRsv[3]; +}; + +struct MU_SET_SNR_OFFSET { + uint8_t ucVal; + uint8_t ucRsv[3]; +}; + +struct MU_SET_ZERO_NSS { + uint8_t ucVal; + uint8_t ucRsv[3]; +}; + +struct MU_SPEED_UP_LQ { + uint32_t u4Val; +}; + +struct MU_SET_MU_TABLE { + /* UINT_16 u2Type; */ + /* UINT_32 u4Length; */ + uint8_t aucMetricTable[NUM_MUT_NR_NUM * NUM_MUT_FEC * + NUM_MUT_MCS * NUM_MUT_INDEX]; +}; + +struct MU_SET_GROUP { + uint32_t u4GroupIndex; /* Group Table Idx */ + uint32_t u4NumOfUser; + uint32_t u4User0Ldpc; + uint32_t u4User1Ldpc; + uint32_t u4ShortGI; + uint32_t u4Bw; + uint32_t u4User0Nss; + uint32_t u4User1Nss; + uint32_t u4GroupId; + uint32_t u4User0UP; + uint32_t u4User1UP; + uint32_t u4User0MuPfId; + uint32_t u4User1MuPfId; + uint32_t u4User0InitMCS; + uint32_t u4User1InitMCS; + uint8_t aucUser0MacAddr[PARAM_MAC_ADDR_LEN]; + uint8_t aucUser1MacAddr[PARAM_MAC_ADDR_LEN]; +}; + +struct MU_GET_QD { + uint8_t ucSubcarrierIndex; + /* UINT_32 u4Length; */ + /* UINT_8 *prQd; */ +}; + +struct MU_SET_ENABLE { + uint8_t ucVal; + uint8_t ucRsv[3]; +}; + +struct MU_SET_GID_UP { + uint32_t au4Gid[2]; + uint32_t au4Up[4]; +}; + +struct MU_TRIGGER_MU_TX { + uint8_t fgIsRandomPattern; /* is random pattern or not */ + uint32_t u4MsduPayloadLength0; /* payload length of the MSDU for + * user 0 + */ + uint32_t u4MsduPayloadLength1; /* payload length of the MSDU for + * user 1 + */ + uint32_t u4MuPacketCount; /* MU TX count */ + uint32_t u4NumOfSTAs; /* number of user in the MU TX */ + uint8_t aucMacAddrs[2][6]; /* MAC address of users*/ +}; + +struct PARAM_CUSTOM_MUMIMO_ACTION_STRUCT { + uint8_t ucMuMimoCategory; + uint8_t aucRsv[3]; + union { + struct MU_GET_CALC_INIT_MCS rMuGetCalcInitMcs; + struct MU_SET_INIT_MCS rMuSetInitMcs; + struct MU_SET_CALC_LQ rMuSetCalcLq; + struct MU_GET_LQ rMuGetLq; + struct MU_SET_SNR_OFFSET rMuSetSnrOffset; + struct MU_SET_ZERO_NSS rMuSetZeroNss; + struct MU_SPEED_UP_LQ rMuSpeedUpLq; + struct MU_SET_MU_TABLE rMuSetMuTable; + struct MU_SET_GROUP rMuSetGroup; + struct MU_GET_QD rMuGetQd; + struct MU_SET_ENABLE rMuSetEnable; + struct MU_SET_GID_UP rMuSetGidUp; + struct MU_TRIGGER_MU_TX rMuTriggerMuTx; + } unMuMimoParam; +}; +#endif /* CFG_SUPPORT_MU_MIMO */ +#endif /* CFG_SUPPORT_TX_BF */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +struct PARAM_CUSTOM_MEM_DUMP_STRUCT { + uint32_t u4Address; + uint32_t u4Length; + uint32_t u4RemainLength; +#if CFG_SUPPORT_QA_TOOL + uint32_t u4IcapContent; +#endif /* CFG_SUPPORT_QA_TOOL */ + uint8_t ucFragNum; +}; + +struct PARAM_CUSTOM_SW_CTRL_STRUCT { + uint32_t u4Id; + uint32_t u4Data; +}; + +struct PARAM_CUSTOM_CHIP_CONFIG_STRUCT { + uint16_t u2Id; + uint8_t ucType; + uint8_t ucRespType; + uint16_t u2MsgSize; + uint8_t aucReserved0[2]; + uint8_t aucCmd[CHIP_CONFIG_RESP_SIZE]; +}; + +struct PARAM_CUSTOM_KEY_CFG_STRUCT { + uint8_t aucKey[WLAN_CFG_KEY_LEN_MAX]; + uint8_t aucValue[WLAN_CFG_VALUE_LEN_MAX]; +}; + +struct PARAM_CUSTOM_EEPROM_RW_STRUCT { + uint8_t ucEepromMethod; /* For read only read: 1, query size: 0 */ + uint8_t ucEepromIndex; + uint8_t reserved; + uint16_t u2EepromData; +}; + +struct PARAM_CUSTOM_WMM_PS_TEST_STRUCT { + uint8_t bmfgApsdEnAc; /* b0~3: trigger-en AC0~3. + * b4~7: delivery-en AC0~3 + */ + uint8_t ucIsEnterPsAtOnce; /* enter PS immediately without 5 second + * guard after connected + */ + uint8_t ucIsDisableUcTrigger; /* not to trigger UC on beacon TIM is + * matched (under U-APSD) + */ + uint8_t reserved; +}; + +struct PARAM_CUSTOM_NOA_PARAM_STRUCT { + uint32_t u4NoaDurationMs; + uint32_t u4NoaIntervalMs; + uint32_t u4NoaCount; + uint8_t ucBssIdx; +}; + +struct PARAM_CUSTOM_OPPPS_PARAM_STRUCT { + uint32_t u4CTwindowMs; + uint8_t ucBssIdx; +}; + +struct PARAM_CUSTOM_UAPSD_PARAM_STRUCT { + uint8_t ucBssIdx; + uint8_t fgEnAPSD; + uint8_t fgEnAPSD_AcBe; + uint8_t fgEnAPSD_AcBk; + uint8_t fgEnAPSD_AcVo; + uint8_t fgEnAPSD_AcVi; + uint8_t ucMaxSpLen; + uint8_t aucResv[2]; +}; + +struct PARAM_CUSTOM_P2P_SET_STRUCT { + uint32_t u4Enable; + uint32_t u4Mode; +}; + +#define MAX_NUMBER_OF_ACL 20 + +enum ENUM_PARAM_CUSTOM_ACL_POLICY { + PARAM_CUSTOM_ACL_POLICY_DISABLE, + PARAM_CUSTOM_ACL_POLICY_ACCEPT, + PARAM_CUSTOM_ACL_POLICY_DENY, + PARAM_CUSTOM_ACL_POLICY_NUM +}; + +struct PARAM_CUSTOM_ACL_ENTRY { + uint8_t aucAddr[MAC_ADDR_LEN]; + uint16_t u2Rsv; +}; + +struct PARAM_CUSTOM_ACL { + enum ENUM_PARAM_CUSTOM_ACL_POLICY ePolicy; + uint32_t u4Num; + struct PARAM_CUSTOM_ACL_ENTRY rEntry[MAX_NUMBER_OF_ACL]; +}; + +enum ENUM_CFG_SRC_TYPE { + CFG_SRC_TYPE_EEPROM, + CFG_SRC_TYPE_NVRAM, + CFG_SRC_TYPE_UNKNOWN, + CFG_SRC_TYPE_NUM +}; + +enum ENUM_EEPROM_TYPE { + EEPROM_TYPE_NO, + EEPROM_TYPE_PRESENT, + EEPROM_TYPE_NUM +}; + +struct PARAM_QOS_TSINFO { + uint8_t ucTrafficType; /* Traffic Type: 1 for isochronous 0 for + * asynchronous + */ + uint8_t ucTid; /* TSID: must be between 8 ~ 15 */ + uint8_t ucDirection; /* direction */ + uint8_t ucAccessPolicy; /* access policy */ + uint8_t ucAggregation; /* aggregation */ + uint8_t ucApsd; /* APSD */ + uint8_t ucuserPriority; /* user priority */ + uint8_t ucTsInfoAckPolicy; /* TSINFO ACK policy */ + uint8_t ucSchedule; /* Schedule */ +}; + +struct PARAM_QOS_TSPEC { + struct PARAM_QOS_TSINFO rTsInfo; /* TS info field */ + uint16_t u2NominalMSDUSize; /* nominal MSDU size */ + uint16_t u2MaxMSDUsize; /* maximum MSDU size */ + uint32_t u4MinSvcIntv; /* minimum service interval */ + uint32_t u4MaxSvcIntv; /* maximum service interval */ + uint32_t u4InactIntv; /* inactivity interval */ + uint32_t u4SpsIntv; /* suspension interval */ + uint32_t u4SvcStartTime; /* service start time */ + uint32_t u4MinDataRate; /* minimum Data rate */ + uint32_t u4MeanDataRate; /* mean data rate */ + uint32_t u4PeakDataRate; /* peak data rate */ + uint32_t u4MaxBurstSize; /* maximum burst size */ + uint32_t u4DelayBound; /* delay bound */ + uint32_t u4MinPHYRate; /* minimum PHY rate */ + uint16_t u2Sba; /* surplus bandwidth allowance */ + uint16_t u2MediumTime; /* medium time */ + uint8_t ucDialogToken; +}; + +struct PARAM_QOS_ADDTS_REQ_INFO { + struct PARAM_QOS_TSPEC rTspec; +}; + +struct PARAM_VOIP_CONFIG { + uint32_t u4VoipTrafficInterval; /* 0: disable VOIP configuration */ +}; + +/*802.11 Statistics Struct*/ +struct PARAM_802_11_STATISTICS_STRUCT { + uint8_t ucInvalid; + union LARGE_INTEGER rTransmittedFragmentCount; + union LARGE_INTEGER rFailedCount; + union LARGE_INTEGER rRetryCount; + union LARGE_INTEGER rMultipleRetryCount; + union LARGE_INTEGER rACKFailureCount; + union LARGE_INTEGER rReceivedFragmentCount; + union LARGE_INTEGER rFCSErrorCount; + uint32_t u4RstReason; + uint64_t u8RstTime; + uint32_t u4RoamFailCnt; + uint64_t u8RoamFailTime; + uint8_t u2TxDoneDelayIsARP; + uint32_t u4ArriveDrvTick; + uint32_t u4EnQueTick; + uint32_t u4DeQueTick; + uint32_t u4LeaveDrvTick; + uint32_t u4CurrTick; + uint64_t u8CurrTime; +}; + +/* Linux Network Device Statistics Struct */ +struct PARAM_LINUX_NETDEV_STATISTICS { + uint32_t u4RxPackets; + uint32_t u4TxPackets; + uint32_t u4RxBytes; + uint32_t u4TxBytes; + uint32_t u4RxErrors; + uint32_t u4TxErrors; + uint32_t u4Multicast; +}; + +struct PARAM_MTK_WIFI_TEST_STRUCT { + uint32_t u4FuncIndex; + uint32_t u4FuncData; +}; + +struct _RBIST_IQ_DATA_T { + int32_t u4IQArray[4][2]; /* IQ_Array[WF][IQ] */ +}; + +struct RECAL_DATA_T { + uint32_t u4CalId; + uint32_t u4CalAddr; + uint32_t u4CalValue; +}; + +struct RECAL_INFO_T { + u_int8_t fgDumped; + uint32_t u4Count; + struct RECAL_DATA_T *prCalArray; +}; + +struct ICAP_INFO_T { + u_int8_t fgCaptureDone; + u_int8_t fgIcapEnable; + uint32_t u4CapNode; + +#if CFG_SUPPORT_QA_TOOL + /* for MT6632/MT7668 file dump mode */ + uint16_t u2DumpIndex; + uint32_t au4Offset[2][2]; + uint32_t au4IQData[256]; + + /* for MT7663/Connad FW parser mode */ + uint32_t u4IQArrayIndex; + uint32_t u4ICapEventCnt; /* Count of packet getting from FW */ + uint32_t au4ICapDumpIndex[4][2];/* Count of packet sent to QA Tool, + * 4 WF * 2 I/Q + */ + struct _RBIST_IQ_DATA_T *prIQArray; +#endif +}; + +struct RF_TEST_CALIBRATION_T { + uint32_t u4FuncData; + uint8_t ucDbdcIdx; + uint8_t aucReserved[3]; +}; + +struct TX_TONE_PARAM_T { + uint8_t ucAntIndex; + uint8_t ucToneType; + uint8_t ucToneFreq; + uint8_t ucDbdcIdx; + int32_t i4DcOffsetI; + int32_t i4DcOffsetQ; + uint32_t u4Band; +}; + +struct CONTINUOUS_TX_PARAM_T { + uint8_t ucCtrlCh; + uint8_t ucCentralCh; + uint8_t ucBW; + uint8_t ucAntIndex; + uint16_t u2RateCode; + uint8_t ucBand; + uint8_t ucTxfdMode; +}; + +struct TX_TONE_POWER_GAIN_T { + uint8_t ucAntIndex; + uint8_t ucTonePowerGain; + uint8_t ucBand; + uint8_t aucReserved[1]; +}; + +struct EXT_CMD_RDD_ON_OFF_CTRL_T { + uint8_t ucDfsCtrl; + uint8_t ucRddIdx; + uint8_t ucRddRxSel; + uint8_t ucSetVal; + uint8_t aucReserved[4]; +}; + +struct SET_ADC_T { + uint32_t u4ChannelFreq; + uint8_t ucAntIndex; + uint8_t ucBW; + uint8_t ucSX; + uint8_t ucDbdcIdx; + uint8_t ucRunType; + uint8_t ucFType; + uint8_t aucReserved[2]; /* Reserving For future */ +}; + +struct SET_RX_GAIN_T { + uint8_t ucLPFG; + uint8_t ucLNA; + uint8_t ucDbdcIdx; + uint8_t ucAntIndex; +}; + +struct SET_TTG_T { + uint32_t u4ChannelFreq; + uint32_t u4ToneFreq; + uint8_t ucTTGPwrIdx; + uint8_t ucDbdcIdx; + uint8_t ucXtalFreq; + uint8_t aucReserved[1]; +}; + +struct TTG_ON_OFF_T { + uint8_t ucTTGEnable; + uint8_t ucDbdcIdx; + uint8_t ucAntIndex; + uint8_t aucReserved[1]; +}; + +struct RBIST_CAP_START_T { + uint32_t u4Trigger; + uint32_t u4RingCapEn; + uint32_t u4TriggerEvent; + uint32_t u4CaptureNode; + uint32_t u4CaptureLen; /* Unit : IQ Sample */ + uint32_t u4CapStopCycle; /* Unit : IQ Sample */ + uint32_t u4MacTriggerEvent; + uint32_t u4SourceAddressLSB; + uint32_t u4SourceAddressMSB; + uint32_t u4BandIdx; + uint32_t u4BW; + uint32_t u4EnBitWidth;/* 0:32bit, 1:96bit, 2:128bit */ + uint32_t u4Architech;/* 0:on-chip, 1:on-the-fly */ + uint32_t u4PhyIdx; + uint32_t u4EmiStartAddress; + uint32_t u4EmiEndAddress; + uint32_t u4EmiMsbAddress; + uint32_t u4CapSource; + uint32_t u4Reserved[2]; +}; + +struct RBIST_DUMP_RAW_DATA_T { + uint32_t u4Address; + uint32_t u4AddrOffset; + uint32_t u4Bank; + uint32_t u4BankSize;/* Uint:Kbytes */ + uint32_t u4Reserved[8]; +}; + +/* FuncIndex */ +enum FUNC_IDX { + RE_CALIBRATION = 0x01, + CALIBRATION_BYPASS = 0x02, + TX_TONE_START = 0x03, + TX_TONE_STOP = 0x04, + CONTINUOUS_TX_START = 0x05, + CONTINUOUS_TX_STOP = 0x06, + RF_AT_EXT_FUNCID_TX_TONE_RF_GAIN = 0x07, + RF_AT_EXT_FUNCID_TX_TONE_DIGITAL_GAIN = 0x08, + CAL_RESULT_DUMP_FLAG = 0x09, + RDD_TEST_MODE = 0x0A, + SET_ICAP_CAPTURE_START = 0x0B, + GET_ICAP_CAPTURE_STATUS = 0x0C, + SET_ADC = 0x0D, + SET_RX_GAIN = 0x0E, + SET_TTG = 0x0F, + TTG_ON_OFF = 0x10, + GET_ICAP_RAW_DATA = 0x11 +}; + +struct PARAM_MTK_WIFI_TEST_STRUCT_EXT_T { + uint32_t u4FuncIndex; + union { + uint32_t u4FuncData; + uint32_t u4CalDump; + struct RF_TEST_CALIBRATION_T rCalParam; + struct TX_TONE_PARAM_T rTxToneParam; + struct CONTINUOUS_TX_PARAM_T rConTxParam; + struct TX_TONE_POWER_GAIN_T rTxToneGainParam; + struct RBIST_CAP_START_T rICapInfo; + struct RBIST_DUMP_RAW_DATA_T rICapDump; + struct EXT_CMD_RDD_ON_OFF_CTRL_T rRDDParam; + struct SET_ADC_T rSetADC; + struct SET_RX_GAIN_T rSetRxGain; + struct SET_TTG_T rSetTTG; + struct TTG_ON_OFF_T rTTGOnOff; + } Data; +}; + +/* 802.11 Media stream constraints */ +enum ENUM_MEDIA_STREAM_MODE { + ENUM_MEDIA_STREAM_OFF, + ENUM_MEDIA_STREAM_ON +}; + +/* for NDIS 5.1 Media Streaming Change */ +struct PARAM_MEDIA_STREAMING_INDICATION { + struct PARAM_STATUS_INDICATION rStatus; + enum ENUM_MEDIA_STREAM_MODE eMediaStreamMode; +}; + +#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 */ +struct PARAM_NETWORK_ADDRESS_IP { + uint16_t sin_port; + uint32_t in_addr; + uint8_t sin_zero[8]; +}; + +struct PARAM_NETWORK_ADDRESS { + uint16_t u2AddressLength;/* length in bytes of Address[] in this */ + uint16_t u2AddressType; /* type of this address + * (PARAM_PROTOCOL_ID_XXX above) + */ + uint8_t aucAddress[1]; /* actually AddressLength bytes long */ +}; + +/* The following is used with OID_GEN_NETWORK_LAYER_ADDRESSES to set network + * layer addresses on an interface + */ + +struct PARAM_NETWORK_ADDRESS_LIST { + uint8_t ucBssIdx; + uint32_t u4AddressCount;/* number of addresses following */ + uint16_t u2AddressType; /* type of this address + * (NDIS_PROTOCOL_ID_XXX above) + */ + struct PARAM_NETWORK_ADDRESS + arAddress[1]; /* actually AddressCount elements long */ +}; + +#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. */ + +enum ENUM_MTK_LP_TEST_MODE { + ENUM_MTK_LP_TEST_NORMAL, + ENUM_MTK_LP_TEST_GOLDEN_SAMPLE, + ENUM_MTK_LP_TEST_DUT, + ENUM_MTK_LP_TEST_MODE_NUM +}; + +enum ENUM_MTK_SLT_FUNC_IDX { + 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 +}; + +struct PARAM_MTK_SLT_LP_TEST_STRUCT { + enum ENUM_MTK_LP_TEST_MODE rLpTestMode; + uint32_t u4BcnRcvNum; +}; + +struct PARAM_MTK_SLT_TR_TEST_STRUCT { + enum ENUM_PARAM_NETWORK_TYPE + rNetworkType; /* Network Type OFDM5G or OFDM2.4G */ + uint32_t u4FixedRate; /* Fixed Rate including BW */ +}; + +struct PARAM_MTK_SLT_INITIAL_STRUCT { + uint8_t aucTargetMacAddr[PARAM_MAC_ADDR_LEN]; + uint16_t u2SiteID; +}; + +struct PARAM_MTK_SLT_TEST_STRUCT { + enum ENUM_MTK_SLT_FUNC_IDX rSltFuncIdx; + uint32_t u4Length; /* Length of structure, */ + /* including myself */ + uint32_t u4FuncInfoLen; /* Include following content */ + /* field and myself */ + union { + struct PARAM_MTK_SLT_INITIAL_STRUCT rMtkInitTest; + struct PARAM_MTK_SLT_LP_TEST_STRUCT rMtkLpTest; + struct PARAM_MTK_SLT_TR_TEST_STRUCT rMtkTRTest; + } unFuncInfoContent; + +}; + +#endif + +#if CFG_SUPPORT_MSP +/* Should by chip */ +struct PARAM_SEC_CONFIG { + u_int8_t fgWPIFlag; + u_int8_t fgRV; + u_int8_t fgIKV; + u_int8_t fgRKV; + + u_int8_t fgRCID; + u_int8_t fgRCA1; + u_int8_t fgRCA2; + u_int8_t fgEvenPN; + + uint8_t ucKeyID; + uint8_t ucMUARIdx; + uint8_t ucCipherSuit; + uint8_t aucReserved[1]; +}; + +struct PARAM_TX_CONFIG { + uint8_t aucPA[6]; + u_int8_t fgSW; + u_int8_t fgDisRxHdrTran; + + u_int8_t fgAADOM; + uint8_t ucPFMUIdx; + uint16_t u2PartialAID; + + u_int8_t fgTIBF; + u_int8_t fgTEBF; + u_int8_t fgIsHT; + u_int8_t fgIsVHT; + + u_int8_t fgMesh; + u_int8_t fgBAFEn; + u_int8_t fgCFAck; + u_int8_t fgRdgBA; + + u_int8_t fgRDG; + u_int8_t fgIsPwrMgt; + u_int8_t fgRTS; + u_int8_t fgSMPS; + + u_int8_t fgTxopPS; + u_int8_t fgDonotUpdateIPSM; + u_int8_t fgSkipTx; + u_int8_t fgLDPC; + + u_int8_t fgIsQoS; + u_int8_t fgIsFromDS; + u_int8_t fgIsToDS; + u_int8_t fgDynBw; + + u_int8_t fgIsAMSDUCrossLG; + u_int8_t fgCheckPER; + u_int8_t fgIsGID63; + uint8_t aucReserved[1]; + +#if (1 /* CFG_SUPPORT_VHT == 1 */) + u_int8_t fgVhtTIBF; + u_int8_t fgVhtTEBF; + u_int8_t fgVhtLDPC; + uint8_t aucReserved2[1]; +#endif +}; + +struct PARAM_KEY_CONFIG { + uint8_t aucKey[32]; +}; + +struct PARAM_PEER_RATE_INFO { + uint8_t ucCounterMPDUFail; + uint8_t ucCounterMPDUTx; + uint8_t ucRateIdx; + uint8_t ucReserved[1]; + + uint16_t au2RateCode[AUTO_RATE_NUM]; +}; + +struct PARAM_PEER_BA_CONFIG { + uint8_t ucBaEn; + uint8_t ucRsv[3]; + uint32_t u4BaWinSize; +}; + +struct PARAM_ANT_ID_CONFIG { + uint8_t ucANTIDSts0; + uint8_t ucANTIDSts1; + uint8_t ucANTIDSts2; + uint8_t ucANTIDSts3; +}; + +struct PARAM_PEER_CAP { + struct PARAM_ANT_ID_CONFIG rAntIDConfig; + + uint8_t ucTxPowerOffset; + uint8_t ucCounterBWSelector; + uint8_t ucChangeBWAfterRateN; + uint8_t ucFrequencyCapability; + uint8_t ucSpatialExtensionIndex; + + u_int8_t fgG2; + u_int8_t fgG4; + u_int8_t fgG8; + u_int8_t fgG16; + + uint8_t ucMMSS; + uint8_t ucAmpduFactor; + uint8_t ucReserved[1]; +}; + +struct PARAM_PEER_RX_COUNTER_ALL { + uint8_t ucRxRcpi0; + uint8_t ucRxRcpi1; + uint8_t ucRxRcpi2; + uint8_t ucRxRcpi3; + + uint8_t ucRxCC0; + uint8_t ucRxCC1; + uint8_t ucRxCC2; + uint8_t ucRxCC3; + + u_int8_t fgRxCCSel; + uint8_t ucCeRmsd; + uint8_t aucReserved[2]; +}; + +struct PARAM_PEER_TX_COUNTER_ALL { + uint16_t u2Rate1TxCnt; + uint16_t u2Rate1FailCnt; + uint16_t u2Rate2OkCnt; + uint16_t u2Rate3OkCnt; + uint16_t u2CurBwTxCnt; + uint16_t u2CurBwFailCnt; + uint16_t u2OtherBwTxCnt; + uint16_t u2OtherBwFailCnt; +}; + +struct PARAM_HW_WLAN_INFO { + uint32_t u4Index; + struct PARAM_TX_CONFIG rWtblTxConfig; + struct PARAM_SEC_CONFIG rWtblSecConfig; + struct PARAM_KEY_CONFIG rWtblKeyConfig; + struct PARAM_PEER_RATE_INFO rWtblRateInfo; + struct PARAM_PEER_BA_CONFIG rWtblBaConfig; + struct PARAM_PEER_CAP rWtblPeerCap; + struct PARAM_PEER_RX_COUNTER_ALL rWtblRxCounter; + struct PARAM_PEER_TX_COUNTER_ALL rWtblTxCounter; +}; + +struct HW_TX_AMPDU_METRICS { + uint32_t u4TxSfCnt; + uint32_t u4TxAckSfCnt; + uint32_t u2TxAmpduCnt; + uint32_t u2TxRspBaCnt; + uint16_t u2TxEarlyStopCnt; + uint16_t u2TxRange1AmpduCnt; + uint16_t u2TxRange2AmpduCnt; + uint16_t u2TxRange3AmpduCnt; + uint16_t u2TxRange4AmpduCnt; + uint16_t u2TxRange5AmpduCnt; + uint16_t u2TxRange6AmpduCnt; + uint16_t u2TxRange7AmpduCnt; + uint16_t u2TxRange8AmpduCnt; + uint16_t u2TxRange9AmpduCnt; +}; + +struct HW_MIB_COUNTER { + uint32_t u4RxFcsErrCnt; + uint32_t u4RxFifoFullCnt; + uint32_t u4RxMpduCnt; + uint32_t u4RxAMPDUCnt; + uint32_t u4RxTotalByte; + uint32_t u4RxValidAMPDUSF; + uint32_t u4RxValidByte; + uint32_t u4ChannelIdleCnt; + uint32_t u4RxVectorDropCnt; + uint32_t u4DelimiterFailedCnt; + uint32_t u4RxVectorMismatchCnt; + uint32_t u4MdrdyCnt; + uint32_t u4CCKMdrdyCnt; + uint32_t u4OFDMLGMixMdrdy; + uint32_t u4OFDMGreenMdrdy; + uint32_t u4PFDropCnt; + uint32_t u4RxLenMismatchCnt; + uint32_t u4PCcaTime; + uint32_t u4SCcaTime; + uint32_t u4CcaNavTx; + uint32_t u4PEDTime; + uint32_t u4BeaconTxCnt; + uint32_t au4BaMissedCnt[BSSID_NUM]; + uint32_t au4RtsTxCnt[BSSID_NUM]; + uint32_t au4FrameRetryCnt[BSSID_NUM]; + uint32_t au4FrameRetry2Cnt[BSSID_NUM]; + uint32_t au4RtsRetryCnt[BSSID_NUM]; + uint32_t au4AckFailedCnt[BSSID_NUM]; +}; + +struct HW_MIB2_COUNTER { + uint32_t u4Tx40MHzCnt; + uint32_t u4Tx80MHzCnt; + uint32_t u4Tx160MHzCnt; +}; + +struct PARAM_HW_MIB_INFO { + uint32_t u4Index; + struct HW_MIB_COUNTER rHwMibCnt; + struct HW_MIB2_COUNTER rHwMib2Cnt; + struct HW_TX_AMPDU_METRICS rHwTxAmpduMts; +}; +#endif + +struct PARAM_CMD_GET_TXPWR_TBL { + uint8_t ucDbdcIdx; + uint8_t ucCenterCh; + struct POWER_LIMIT tx_pwr_tbl[TXPWR_TBL_NUM]; +}; + +enum ENUM_TXPWR_TYPE { + DSSS = 0, + OFDM_24G, + OFDM_5G, + HT20, + HT40, + VHT20, + VHT40, + VHT80, + VHT160, + TXPWR_TYPE_NUM, +}; + +enum ENUM_STREAM_MODE { + STREAM_SISO, + STREAM_CDD, + STREAM_MIMO, + STREAM_NUM +}; + +struct txpwr_table_entry { + char mcs[STREAM_NUM][8]; + unsigned int idx; +}; + +struct txpwr_table { + char phy_mode[8]; + struct txpwr_table_entry *tables; + int n_tables; +}; + +/*--------------------------------------------------------------*/ +/*! \brief For Fixed Rate Configuration (Registry) */ +/*--------------------------------------------------------------*/ +enum ENUM_REGISTRY_FIXED_RATE { + 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 ENUM_BT_CMD { + BT_CMD_PROFILE = 0, + BT_CMD_UPDATE, + BT_CMD_NUM +}; + +enum ENUM_BT_PROFILE { + BT_PROFILE_CUSTOM = 0, + BT_PROFILE_SCO, + BT_PROFILE_ACL, + BT_PROFILE_MIXED, + BT_PROFILE_NO_CONNECTION, + BT_PROFILE_NUM +}; + +struct PTA_PROFILE { + enum ENUM_BT_PROFILE eBtProfile; + union { + uint8_t 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. + */ + uint32_t au4Btcr[4]; + } u; +}; + +struct PTA_IPC { + uint8_t ucCmd; + uint8_t ucLen; + union { + struct PTA_PROFILE rProfile; + uint8_t aucBTPParams[BT_PROFILE_PARAM_LEN]; + } u; +}; + +/*--------------------------------------------------------------*/ +/*! \brief CFG80211 Scan Request Container */ +/*--------------------------------------------------------------*/ +struct PARAM_SCAN_REQUEST_EXT { + struct PARAM_SSID rSsid; + uint32_t u4IELength; + uint8_t *pucIE; +}; + +struct PARAM_SCAN_REQUEST_ADV { + uint32_t u4SsidNum; + struct PARAM_SSID rSsid[CFG_SCAN_SSID_MAX_NUM]; + uint8_t ucScanType; + uint32_t u4IELength; + uint8_t *pucIE; + uint32_t u4ChannelNum; + struct RF_CHANNEL_INFO + arChannel[MAXIMUM_OPERATION_CHANNEL_LIST]; + uint8_t ucScnFuncMask; + uint8_t aucRandomMac[MAC_ADDR_LEN]; +}; + +/*--------------------------------------------------------------*/ +/*! \brief CFG80211 Scheduled Scan Request Container */ +/*--------------------------------------------------------------*/ +#if CFG_SUPPORT_SCHED_SCAN +struct PARAM_SCHED_SCAN_REQUEST { + uint32_t u4SsidNum; /* passed in the probe_reqs */ + struct PARAM_SSID arSsid[CFG_SCAN_HIDDEN_SSID_MAX_NUM]; + uint32_t u4MatchSsidNum; /* matched for a scan request */ + struct PARAM_SSID arMatchSsid[CFG_SCAN_SSID_MATCH_MAX_NUM]; + int32_t ai4RssiThold[CFG_SCAN_SSID_MATCH_MAX_NUM]; + int32_t i4MinRssiThold; + uint8_t ucScnFuncMask; + uint8_t aucRandomMac[MAC_ADDR_LEN]; + uint8_t aucRandomMacMask[MAC_ADDR_LEN]; + uint32_t u4IELength; + uint8_t *pucIE; + uint16_t u2ScanInterval; /* in second */ + uint8_t ucChnlNum; + uint8_t *pucChannels; +}; +#endif /* CFG_SUPPORT_SCHED_SCAN */ + +#if CFG_SUPPORT_PASSPOINT +struct PARAM_HS20_SET_BSSID_POOL { + u_int8_t fgIsEnable; + uint8_t ucNumBssidPool; + uint8_t arBSSID[8][PARAM_MAC_ADDR_LEN]; +}; + +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_SNIFFER +struct PARAM_CUSTOM_MONITOR_SET_STRUCT { + uint8_t ucEnable; + uint8_t ucBand; + uint8_t ucPriChannel; + uint8_t ucSco; + uint8_t ucChannelWidth; + uint8_t ucChannelS1; + uint8_t ucChannelS2; + uint8_t aucResv[9]; +}; +#endif + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +/*--------------------------------------------------------------*/ +/*! \brief MTK Auto Channel Selection related Container */ +/*--------------------------------------------------------------*/ +struct LTE_SAFE_CHN_INFO { + /* NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_MAX */ + uint32_t au4SafeChannelBitmask[5]; +}; + +struct PARAM_CHN_LOAD_INFO { + /* Per-CHN Load */ + uint8_t ucChannel; + uint16_t u2APNum; + uint32_t u4Dirtiness; + uint8_t ucReserved; +}; + +struct PARAM_CHN_RANK_INFO { + uint8_t ucChannel; + uint32_t u4Dirtiness; + uint8_t ucReserved; +}; + +struct PARAM_GET_CHN_INFO { + struct LTE_SAFE_CHN_INFO rLteSafeChnList; + struct PARAM_CHN_LOAD_INFO rEachChnLoad[MAX_CHN_NUM]; + u_int8_t fgDataReadyBit; + struct PARAM_CHN_RANK_INFO rChnRankList[MAX_CHN_NUM]; + uint8_t aucReserved[3]; +}; + +struct PARAM_PREFER_CHN_INFO { + uint8_t ucChannel; + uint16_t u2APNumScore; + uint8_t ucReserved; +}; +#endif + + +struct UMAC_STAT2_GET { + uint16_t u2PleRevPgHif0Group0; + uint16_t u2PleRevPgCpuGroup2; + + uint16_t u2PseRevPgHif0Group0; + uint16_t u2PseRevPgHif1Group1; + uint16_t u2PseRevPgCpuGroup2; + uint16_t u2PseRevPgLmac0Group3; + uint16_t u2PseRevPgLmac1Group4; + uint16_t u2PseRevPgLmac2Group5; + uint16_t u2PseRevPgPleGroup6; + + uint16_t u2PleSrvPgHif0Group0; + uint16_t u2PleSrvPgCpuGroup2; + + uint16_t u2PseSrvPgHif0Group0; + uint16_t u2PseSrvPgHif1Group1; + uint16_t u2PseSrvPgCpuGroup2; + uint16_t u2PseSrvPgLmac0Group3; + uint16_t u2PseSrvPgLmac1Group4; + uint16_t u2PseSrvPgLmac2Group5; + uint16_t u2PseSrvPgPleGroup6; + + uint16_t u2PleTotalPageNum; + uint16_t u2PleFreePageNum; + uint16_t u2PleFfaNum; + + uint16_t u2PseTotalPageNum; + uint16_t u2PseFreePageNum; + uint16_t u2PseFfaNum; +}; + +struct CNM_STATUS { + uint8_t fgDbDcModeEn; + uint8_t ucChNumB0; + uint8_t ucChNumB1; + uint8_t usReserved; +}; + +struct CNM_CH_LIST { + uint8_t ucChNum[4]; +}; + +struct EXT_CMD_SER_T { + uint8_t ucAction; + uint8_t ucSerSet; + uint8_t ucDbdcIdx; + uint8_t aucReserve[1]; +}; + +#if (CFG_SUPPORT_TXPOWER_INFO == 1) +struct HAL_FRAME_POWER_SET_T { + int8_t icFramePowerDbm; +}; + +struct FRAME_POWER_CONFIG_INFO_T { + struct HAL_FRAME_POWER_SET_T + aicFramePowerConfig[TXPOWER_RATE_NUM]; +}; + +struct PARAM_TXPOWER_ALL_RATE_POWER_INFO_T { + uint8_t ucTxPowerCategory; + uint8_t ucBandIdx; + uint8_t ucChBand; + uint8_t ucReserved; + + /* Rate power info */ + struct FRAME_POWER_CONFIG_INFO_T rRatePowerInfo; + + /* tx Power Max/Min Limit info */ + int8_t icPwrMaxBnd; + int8_t icPwrMinBnd; + uint8_t ucReserved2; +}; +#endif + +#if CFG_SUPPORT_OSHARE +/* OSHARE Mode */ +#define MAX_OSHARE_MODE_LENGTH 64 +#define OSHARE_MODE_MAGIC_CODE 0x18 +#define OSHARE_MODE_CMD_V1 0x1 + +struct OSHARE_MODE_T { + uint8_t cmdVersion; /* CMD version = OSHARE_MODE_CMD_V1 */ + uint8_t cmdType; /* 1-set 0-query */ + uint8_t magicCode; /* It's like CRC, OSHARE_MODE_MAGIC_CODE */ + uint8_t cmdBufferLen; /* buffer length <= 64 */ + uint8_t buffer[MAX_OSHARE_MODE_LENGTH]; +}; + +struct OSHARE_MODE_SETTING_V1_T { + uint8_t osharemode; /* 0: disable, 1:Enable */ + uint8_t reserved[7]; +}; +#endif + +struct PARAM_WIFI_LOG_LEVEL_UI { + uint32_t u4Version; + uint32_t u4Module; + uint32_t u4Enable; +}; + +struct PARAM_WIFI_LOG_LEVEL { + uint32_t u4Version; + uint32_t u4Module; + uint32_t u4Level; +}; + +enum ENUM_WIFI_LOG_LEVEL_VERSION_T { + ENUM_WIFI_LOG_LEVEL_VERSION_V1 = 1, + ENUM_WIFI_LOG_LEVEL_VERSION_NUM +}; + +enum ENUM_WIFI_LOG_LEVEL_T { + ENUM_WIFI_LOG_LEVEL_DEFAULT = 0, + ENUM_WIFI_LOG_LEVEL_MORE, + ENUM_WIFI_LOG_LEVEL_EXTREME, + ENUM_WIFI_LOG_LEVEL_NUM +}; + +enum ENUM_WIFI_LOG_MODULE_T { + ENUM_WIFI_LOG_MODULE_DRIVER = 0, + ENUM_WIFI_LOG_MODULE_FW, + ENUM_WIFI_LOG_MODULE_NUM, +}; + +enum ENUM_WIFI_LOG_LEVEL_SUPPORT_T { + ENUM_WIFI_LOG_LEVEL_SUPPORT_DISABLE = 0, + ENUM_WIFI_LOG_LEVEL_SUPPORT_ENABLE, + ENUM_WIFI_LOG_LEVEL_SUPPORT_NUM +}; + +struct PARAM_GET_IPI_INFO_T { + uint32_t u4DurInSec; + uint32_t u4Interval; + uint32_t u4Reserved; +}; + +#if CFG_SUPPORT_GET_MCS_INFO +struct PARAM_TX_MCS_INFO { + uint8_t ucStaIndex; + uint16_t au2TxRateCode[MCS_INFO_SAMPLE_CNT]; + uint8_t aucTxRatePer[MCS_INFO_SAMPLE_CNT]; + +}; +#endif + +#ifdef CFG_SUPPORT_TIME_MEASURE +/* TM/11mc */ +struct PARAM_TM_T { + uint8_t ucTmCategory; + uint8_t aucRttPeerAddr[6]; /* TM peer address */ + uint16_t u2NumOfValidResult; + + uint8_t ucFTMNum; + uint8_t ucMinDeltaIn100US; + uint8_t ucFTMBandwidth; + uint8_t fgFtmEnable; + + uint32_t u4DistanceCm; + uint64_t u8DistStdevSq; + + uint64_t u8Tsf; + int64_t i8ClockOffset; + int64_t i8ClkRateDiffRatioIn10ms; + uint64_t u8LastToA; + +}; +#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 + ******************************************************************************* + */ +/*--------------------------------------------------------------*/ +/* Routines to set parameters or query information. */ +/*--------------------------------------------------------------*/ +/***** Routines in wlan_oid.c *****/ +uint32_t +wlanoidQueryNetworkTypesSupported(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryNetworkTypeInUse(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetNetworkTypeInUse(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryBssid(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetBssidListScan(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetBssidListScanExt(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetBssidListScanAdv(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryBssidList(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetBssid(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetConnect(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetSsid(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQuerySsid(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryInfrastructureMode(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetInfrastructureMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryAuthMode(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetAuthMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#if 0 +uint32_t +wlanoidQueryPrivacyFilter(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetPrivacyFilter(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif + +uint32_t +wlanoidSetEncryptionStatus(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryEncryptionStatus(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetAddWep(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetRemoveWep(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetAddKey(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetRemoveKey(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetReloadDefaults(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetTest(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryCapability(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryFrequency(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetFrequency(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryAtimWindow(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetAtimWindow(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetChannel(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidRssiMonitor(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryRssi(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanQueryRssi(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen, + IN uint8_t fgIsOid); + +uint32_t +wlanoidQueryRssiTrigger(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetRssiTrigger(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryRtsThreshold(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetRtsThreshold(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQuery802dot11PowerSaveProfile(IN struct ADAPTER + *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSet802dot11PowerSaveProfile(IN struct ADAPTER + *prAdapter, + IN void *prSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryPmkid(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetPmkid(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQuerySupportedRates(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryDesiredRates(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetDesiredRates(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryPermanentAddr(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuf, + IN uint32_t u4QueryBufLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryCurrentAddr(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuf, + IN uint32_t u4QueryBufLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryPermanentAddr(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuf, + IN uint32_t u4QueryBufLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryLinkSpeed(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +#if CFG_SUPPORT_QA_TOOL +#if CFG_SUPPORT_BUFFER_MODE +uint32_t wlanoidSetEfusBufferMode(IN struct ADAPTER + *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanoidConnacSetEfusBufferMode(IN struct ADAPTER + *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +/* #if (CFG_EEPROM_PAGE_ACCESS == 1) */ +uint32_t +wlanoidQueryProcessAccessEfuseRead(IN struct ADAPTER + *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryProcessAccessEfuseWrite(IN struct ADAPTER + *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryEfuseFreeBlock(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryGetTxPower(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +/*#endif*/ + +#endif /* CFG_SUPPORT_BUFFER_MODE */ +uint32_t +wlanoidQueryRxStatistics(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidBssInfoBasic(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidDevInfoActive(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidManualAssoc(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#if CFG_SUPPORT_TX_BF +uint32_t +wlanoidTxBfAction(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanoidMuMimoAction(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanoidStaRecUpdate(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanoidStaRecBFUpdate(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif /* CFG_SUPPORT_TX_BF */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +uint32_t +wlanoidSendCalBackupV2Cmd(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen); + +uint32_t +wlanoidSetCalBackup(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryCalBackupV2(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); +#endif + +uint32_t +wlanoidQueryMcrRead(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryMemDump(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetMcrWrite(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryDrvMcrRead(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetDrvMcrWrite(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQuerySwCtrlRead(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetSwCtrlWrite(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetChipConfig(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryChipConfig(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetKeyCfg(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryEepromRead(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetEepromWrite(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryRfTestRxStatus(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryRfTestTxStatus(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryOidInterfaceVersion(IN struct ADAPTER + *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryVendorId(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryMulticastList(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetMulticastList(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryRcvError(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryRcvNoBuffer(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryRcvCrcError(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryStatistics(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryBugReport(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +#ifdef LINUX + +uint32_t +wlanoidQueryStatisticsForLinux(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +#endif + +uint32_t +wlanoidQueryMediaStreamMode(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetMediaStreamMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryRcvOk(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryXmitOk(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryXmitError(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryXmitOneCollision(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryXmitMoreCollisions(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryXmitMaxCollisions(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetCurrentPacketFilter(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanoidSetPacketFilter(struct ADAPTER *prAdapter, + void *pvPacketFiltr, + u_int8_t fgIsOid, + void *pvSetBuffer, + uint32_t u4SetBufferLen); + +uint32_t +wlanoidQueryCurrentPacketFilter(IN struct ADAPTER + *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetAcpiDevicePowerState(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryAcpiDevicePowerState(IN struct ADAPTER + *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetDisassociate(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryFragThreshold(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetFragThreshold(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryAdHocMode(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetAdHocMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryBeaconInterval(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetBeaconInterval(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetCurrentAddr(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +uint32_t +wlanoidSetCSUMOffload(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +uint32_t +wlanoidSetNetworkAddress(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryMaxFrameSize(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryMaxTotalSize(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetCurrentLookahead(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +/* RF Test related APIs */ +uint32_t +wlanoidRftestSetTestMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidRftestSetTestIcapMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidRftestSetAbortTestMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidRftestQueryAutoTest(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidRftestSetAutoTest(IN struct ADAPTER *prAdapter, + OUT void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +uint32_t +wlanoidExtRfTestICapStart(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +uint32_t +wlanoidExtRfTestICapStatus(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +void wlanoidRfTestICapRawDataProc(IN struct ADAPTER *prAdapter, + uint32_t u4CapStartAddr, + uint32_t u4TotalBufferSize); + +#if CFG_SUPPORT_WAPI +uint32_t +wlanoidSetWapiMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetWapiAssocInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetWapiKey(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif + +#if CFG_SUPPORT_WPS2 +uint32_t +wlanoidSetWSCAssocInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif + +#if CFG_ENABLE_WAKEUP_ON_LAN +uint32_t +wlanoidSetAddWakeupPattern(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetRemoveWakeupPattern(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryEnableWakeup(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *u4QueryInfoLen); + +uint32_t +wlanoidSetEnableWakeup(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif + +uint32_t +wlanoidSetWiFiWmmPsTest(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetTxAmpdu(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetAddbaReject(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNvramRead(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetNvramWrite(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryCfgSrcType(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryEepromType(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetCountryCode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetScanMacOui(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanSendMemDumpCmd(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen); + +#if CFG_SLT_SUPPORT + +uint32_t +wlanoidQuerySLTStatus(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidUpdateSLTMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#endif + +#if CFG_SUPPORT_ADVANCE_CONTROL +uint32_t +wlanoidAdvCtrl(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanAdvCtrl(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen, + IN uint8_t fgIsOid); +#endif + + +uint32_t +wlanoidQueryWlanInfo(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanQueryWlanInfo(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen, + IN uint8_t fgIsOid); + +uint32_t +wlanoidQueryMibInfo(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetFwLog2Host(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#if 0 +uint32_t +wlanoidSetNoaParam(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetOppPsParam(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetUApsdParam(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif + +/*----------------------------------------------------------------------------*/ +uint32_t +wlanoidSetBT(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryBT(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetTxPower(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#if 0 +uint32_t +wlanoidQueryBtSingleAntenna( + IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetBtSingleAntenna( + IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetPta( + IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryPta( + IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); +#endif + +#if CFG_ENABLE_WIFI_DIRECT +uint32_t +wlanoidSetP2pMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif + +uint32_t +wlanoidSetDefaultKey(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetGtkRekeyData(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#if CFG_SUPPORT_SCHED_SCAN +uint32_t +wlanoidSetStartSchedScan(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetStopSchedScan(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif /* CFG_SUPPORT_SCHED_SCAN */ + +#if CFG_M0VE_BA_TO_DRIVER +uint32_t wlanoidResetBAScoreboard(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen); +#endif + +#if CFG_SUPPORT_BATCH_SCAN +uint32_t +wlanoidSetBatchScanReq(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryBatchScanResult(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); +#endif + +#if CFG_SUPPORT_PASSPOINT +uint32_t +wlanoidSetHS20Info(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetInterworkingInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetRoamingConsortiumIEInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetHS20BssidPool(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_SNIFFER +uint32_t wlanoidSetMonitor(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif + +uint32_t +wlanoidNotifyFwSuspend(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryCnm( + IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidPacketKeepAlive(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#if CFG_SUPPORT_DBDC +uint32_t +wlanoidSetDbdcEnable(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif /*#if CFG_SUPPORT_DBDC*/ + +uint32_t +wlanoidQuerySetTxTargetPower(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#if (CFG_SUPPORT_DFS_MASTER == 1) +uint32_t +wlanoidQuerySetRddReport(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQuerySetRadarDetectMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +uint32_t +wlanoidQueryLteSafeChannel(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); +uint32_t +wlanCalculateAllChannelDirtiness(IN struct ADAPTER *prAdapter); + +void +wlanInitChnLoadInfoChannelList(IN struct ADAPTER *prAdapter); + +uint8_t +wlanGetChannelIndex(IN uint8_t channel); + +uint8_t +wlanGetChannelNumFromIndex(IN uint8_t ucIdx); + +void +wlanSortChannel(IN struct ADAPTER *prAdapter); + +#endif + +uint32_t +wlanoidLinkDown(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidGetTxPwrTbl(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + + +uint32_t +wlanoidDisableTdlsPs(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanoidSetSer(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanoidSerExtCmd(IN struct ADAPTER *prAdapter, + uint8_t ucAction, + uint8_t ucSerSet, + uint8_t ucDbdcIdx); + +#if CFG_SUPPORT_NCHO +#define NCHO_CMD_MAX_LENGTH 128 + +uint32_t +wlanoidSetNchoRoamTrigger(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNchoRoamTrigger(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetNchoRoamDelta(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNchoRoamDelta(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetNchoRoamScnPeriod(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNchoRoamScnPeriod(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetNchoRoamScnChnl(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNchoRoamScnChnl(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetNchoRoamScnCtrl(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNchoRoamScnCtrl(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetNchoScnChnlTime(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNchoScnChnlTime(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetNchoScnHomeTime(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNchoScnHomeTime(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetNchoScnHomeAwayTime(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNchoScnHomeAwayTime(IN struct ADAPTER + *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetNchoScnNprobes(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNchoScnNprobes(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidGetNchoReassocInfo(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSendNchoActionFrameStart(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSendNchoActionFrameEnd(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetNchoWesMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNchoWesMode(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetNchoBand(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNchoBand(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetNchoDfsScnMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNchoDfsScnMode(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetNchoEnable(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryNchoEnable(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +#endif /* CFG_SUPPORT_NCHO */ + +uint32_t +wlanoidAbortScan(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t wlanoidSetDrvSer(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +uint32_t wlanoidSetAmsduNum(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +uint32_t wlanoidSetAmsduSize(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +/* Show Consys debug information*/ +uint32_t +wlanoidShowPdmaInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +uint32_t +wlanoidShowPseInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +uint32_t +wlanoidShowPleInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +uint32_t +wlanoidShowCsrInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +uint32_t +wlanoidShowDmaschInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +/* end Show Consys debug information*/ + +#if (CFG_SUPPORT_TXPOWER_INFO == 1) +uint32_t +wlanoidQueryTxPowerInfo(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif + +uint32_t wlanoidSetDrvRoamingPolicy(IN struct ADAPTER + *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#if CFG_SUPPORT_OSHARE +uint32_t +wlanoidSetOshareMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif + +uint32_t +wlanoidQueryWifiLogLevelSupport(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryWifiLogLevel(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetWifiLogLevel(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#if CFG_SUPPORT_LOWLATENCY_MODE +uint32_t +wlanoidSetLowLatencyMode(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif /* CFG_SUPPORT_LOWLATENCY_MODE */ + +uint32_t +wlanoidGetIpiInfo(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t wlanoidUpdateFtIes(IN struct ADAPTER *prAdapter, IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanoidSync11kCapabilities(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanoidSendNeighborRequest(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanoidSendBTMQuery(IN struct ADAPTER *prAdapter, IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t wlanoidPktProcessIT(struct ADAPTER *prAdapter, void *pvBuffer, + uint32_t u4BufferLen, uint32_t *pu4InfoLen); + +uint32_t wlanoidFwEventIT(struct ADAPTER *prAdapter, void *pvBuffer, + uint32_t u4BufferLen, uint32_t *pu4InfoLen); + +uint32_t wlanoidTspecOperation(IN struct ADAPTER *prAdapter, IN void *pvBuffer, + IN uint32_t u4BufferLen, + OUT uint32_t *pu4InfoLen); + +uint32_t wlanoidDumpUapsdSetting(struct ADAPTER *prAdapter, void *pvBuffer, + uint32_t u4BufferLen, uint32_t *pu4InfoLen); + +#if CFG_SUPPORT_ANT_DIV +uint32_t +wlanoidAntDivCfg(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif + +uint32_t +wlanoidQueryCoexGetInfo(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidQueryCoexIso(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +#endif /* _WLAN_OID_H */ + +#ifdef CFG_GET_TEMPURATURE +uint32_t +wlanoidGetTemperature(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); +#endif + +#if (CFG_SUPPORT_GET_MCS_INFO == 1) +uint32_t +wlanoidTxQueryMcsInfo(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); +#endif + +#ifdef CFG_SUPPORT_TIME_MEASURE +uint32_t wlanoidQueryStartFtm(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t wlanoidQueryFtm(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t wlanoidSetEnableTmr(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/wlan_p2p.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/wlan_p2p.h new file mode 100644 index 0000000000000..bad8fdd0cd06e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/include/wlan_p2p.h @@ -0,0 +1,318 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + + +#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 */ +struct PARAM_P2P_SEND_SD_RESPONSE { + uint8_t rReceiverAddr[PARAM_MAC_ADDR_LEN]; + uint8_t fgNeedTxDoneIndication; + uint8_t ucChannelNum; + uint16_t u2PacketLength; + uint8_t aucPacketContent[0]; /*native 802.11 */ +}; + +struct PARAM_P2P_GET_SD_REQUEST { + uint8_t rTransmitterAddr[PARAM_MAC_ADDR_LEN]; + uint16_t u2PacketLength; + uint8_t aucPacketContent[0]; /*native 802.11 */ +}; + +struct PARAM_P2P_GET_SD_REQUEST_EX { + uint8_t rTransmitterAddr[PARAM_MAC_ADDR_LEN]; + uint16_t u2PacketLength; + /* Channel Number Where SD Request is received. */ + uint8_t ucChannelNum; + uint8_t ucSeqNum; /* Get SD Request by sequence number. */ + uint8_t aucPacketContent[0]; /*native 802.11 */ +}; + +struct PARAM_P2P_SEND_SD_REQUEST { + uint8_t rReceiverAddr[PARAM_MAC_ADDR_LEN]; + uint8_t fgNeedTxDoneIndication; + /* Indicate the Service Discovery Supplicant Version. */ + uint8_t ucVersionNum; + uint16_t u2PacketLength; + uint8_t aucPacketContent[0]; /*native 802.11 */ +}; + +/* Service Discovery 1.0. */ +struct PARAM_P2P_GET_SD_RESPONSE { + uint8_t rTransmitterAddr[PARAM_MAC_ADDR_LEN]; + uint16_t u2PacketLength; + uint8_t aucPacketContent[0]; /*native 802.11 */ +}; + +/* Service Discovery 2.0. */ +struct PARAM_P2P_GET_SD_RESPONSE_EX { + uint8_t rTransmitterAddr[PARAM_MAC_ADDR_LEN]; + uint16_t u2PacketLength; + uint8_t ucSeqNum; /* Get SD Response by sequence number. */ + uint8_t aucPacketContent[0]; /*native 802.11 */ +}; + +struct PARAM_P2P_TERMINATE_SD_PHASE { + uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN]; +}; + +/*! \brief Key mapping of BSSID */ +struct P2P_PARAM_KEY { + uint32_t u4Length; /*!< Length of structure */ + uint32_t u4KeyIndex; /*!< KeyID */ + uint32_t u4KeyLength; /*!< Key length in bytes */ + uint8_t arBSSID[PARAM_MAC_ADDR_LEN]; /*!< MAC address */ + uint64_t rKeyRSC; + /* Following add to change the original windows structure */ + uint8_t ucBssIdx; /* for specific P2P BSS interface. */ + uint8_t ucCipher; + uint8_t aucKeyMaterial[32]; /*!< Key content by above setting */ +}; + +/****************************************************************************** + * 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); + */ + +uint32_t +wlanoidSetNetworkAddress(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetP2PMulticastList(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +/*--------------------------------------------------------------*/ +/* Service Discovery Subroutines */ +/*--------------------------------------------------------------*/ +uint32_t +wlanoidSendP2PSDRequest(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSendP2PSDResponse(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidGetP2PSDRequest(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidGetP2PSDResponse(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *puQueryInfoLen); + +uint32_t +wlanoidSetP2PTerminateSDPhase(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +#if CFG_SUPPORT_ANTI_PIRACY +uint32_t +wlanoidSetSecCheckRequest(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +/*WLAN_STATUS + *wlanoidGetSecCheckResponse(IN P_ADAPTER_T prAdapter, + * IN PVOID pvQueryBuffer, + * IN UINT_32 u4QueryBufferLen, + * OUT PUINT_32 pu4QueryInfoLen); + */ +#endif + +uint32_t +wlanoidSetNoaParam(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetOppPsParam(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetUApsdParam(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryP2pPowerSaveProfile(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetP2pPowerSaveProfile(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidSetP2pSetNetworkAddress(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +uint32_t +wlanoidQueryP2pVersion(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +uint32_t +wlanoidSetP2pSupplicantVersion(IN struct ADAPTER *prAdapter, + IN void *pvSetBuffer, + IN uint32_t u4SetBufferLen, + OUT uint32_t *pu4SetInfoLen); + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER +uint32_t +wlanoidSetP2pWPSmode(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); +#endif + +#if CFG_SUPPORT_P2P_RSSI_QUERY +uint32_t +wlanoidQueryP2pRssi(IN struct ADAPTER *prAdapter, + IN void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); +#endif + +uint32_t +wlanoidAbortP2pScan(IN struct ADAPTER *prAdapter, + OUT void *pvQueryBuffer, + IN uint32_t u4QueryBufferLen, + OUT uint32_t *pu4QueryInfoLen); + +/*--------------------------------------------------------------*/ +/* Callbacks for event indication */ +/*--------------------------------------------------------------*/ + +#endif +#endif /* _WLAN_P2P_H */ From 2fe2733148988c8c51e71815cdd2d66efc7747ce Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 22:21:25 +0800 Subject: [PATCH 28/32] Add files via upload --- .../wlan/core/gen4-mt7663/mgmt/aaa_fsm.c | 1698 ++++ .../wlan/core/gen4-mt7663/mgmt/ais_fsm.c | 6675 ++++++++++++++ .../wlan/core/gen4-mt7663/mgmt/ap_selection.c | 781 ++ .../wlan/core/gen4-mt7663/mgmt/assoc.c | 2085 +++++ .../wlan/core/gen4-mt7663/mgmt/auth.c | 1529 ++++ .../wlan/core/gen4-mt7663/mgmt/bss.c | 2436 +++++ .../wlan/core/gen4-mt7663/mgmt/cnm.c | 3670 ++++++++ .../wlan/core/gen4-mt7663/mgmt/cnm_mem.c | 1815 ++++ .../wlan/core/gen4-mt7663/mgmt/cnm_timer.c | 539 ++ .../wlan/core/gen4-mt7663/mgmt/hem_mbox.c | 588 ++ .../wlan/core/gen4-mt7663/mgmt/hs20.c | 655 ++ .../wlan/core/gen4-mt7663/mgmt/mib.c | 138 + .../wlan/core/gen4-mt7663/mgmt/p2p_assoc.c | 143 + .../wlan/core/gen4-mt7663/mgmt/p2p_bss.c | 109 + .../wlan/core/gen4-mt7663/mgmt/p2p_dev_fsm.c | 1225 +++ .../core/gen4-mt7663/mgmt/p2p_dev_state.c | 438 + .../wlan/core/gen4-mt7663/mgmt/p2p_fsm.c | 383 + .../wlan/core/gen4-mt7663/mgmt/p2p_func.c | 6235 +++++++++++++ .../wlan/core/gen4-mt7663/mgmt/p2p_ie.c | 223 + .../wlan/core/gen4-mt7663/mgmt/p2p_rlm.c | 1368 +++ .../wlan/core/gen4-mt7663/mgmt/p2p_rlm_obss.c | 396 + .../wlan/core/gen4-mt7663/mgmt/p2p_role_fsm.c | 3470 ++++++++ .../core/gen4-mt7663/mgmt/p2p_role_state.c | 626 ++ .../wlan/core/gen4-mt7663/mgmt/p2p_scan.c | 343 + .../wlan/core/gen4-mt7663/mgmt/privacy.c | 1423 +++ .../wlan/core/gen4-mt7663/mgmt/qosmap.c | 300 + .../wlan/core/gen4-mt7663/mgmt/rate.c | 375 + .../wlan/core/gen4-mt7663/mgmt/reg_rule.c | 388 + .../wlan/core/gen4-mt7663/mgmt/rlm.c | 7822 +++++++++++++++++ .../wlan/core/gen4-mt7663/mgmt/rlm_domain.c | 3917 +++++++++ .../wlan/core/gen4-mt7663/mgmt/rlm_obss.c | 400 + .../core/gen4-mt7663/mgmt/rlm_protection.c | 105 + .../wlan/core/gen4-mt7663/mgmt/roaming_fsm.c | 796 ++ .../wlan/core/gen4-mt7663/mgmt/rsn.c | 4021 +++++++++ .../wlan/core/gen4-mt7663/mgmt/saa_fsm.c | 2918 ++++++ .../wlan/core/gen4-mt7663/mgmt/scan.c | 4373 +++++++++ .../wlan/core/gen4-mt7663/mgmt/scan_cache.c | 234 + .../wlan/core/gen4-mt7663/mgmt/scan_fsm.c | 1405 +++ .../wlan/core/gen4-mt7663/mgmt/stats.c | 597 ++ .../wlan/core/gen4-mt7663/mgmt/swcr.c | 1469 ++++ .../wlan/core/gen4-mt7663/mgmt/tdls.c | 1593 ++++ .../wlan/core/gen4-mt7663/mgmt/tkip_mic.c | 590 ++ .../wlan/core/gen4-mt7663/mgmt/wapi.c | 527 ++ .../wlan/core/gen4-mt7663/mgmt/wmm.c | 1724 ++++ .../wlan/core/gen4-mt7663/mgmt/wnm.c | 642 ++ 45 files changed, 73187 insertions(+) create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/aaa_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/ais_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/ap_selection.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/assoc.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/auth.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/bss.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/cnm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/cnm_mem.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/cnm_timer.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/hem_mbox.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/hs20.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/mib.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_assoc.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_bss.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_dev_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_dev_state.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_func.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_ie.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_rlm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_rlm_obss.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_role_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_role_state.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_scan.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/privacy.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/qosmap.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/rate.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/reg_rule.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/rlm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/rlm_domain.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/rlm_obss.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/rlm_protection.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/roaming_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/rsn.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/saa_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/scan.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/scan_cache.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/scan_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/stats.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/swcr.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/tdls.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/tkip_mic.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/wapi.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/wmm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/wnm.c diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/aaa_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/aaa_fsm.c new file mode 100644 index 0000000000000..2a5e45bd9dd03 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/aaa_fsm.c @@ -0,0 +1,1698 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/aaa_fsm.c#3 $ + */ + +/*! \file "aaa_fsm.c" + * \brief This file defines the FSM for AAA MODULE. + * + * This file defines the FSM for AAA MODULE. + */ + +/****************************************************************************** + * C O M P I L E 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t aaaFsmSendEventJoinComplete(uint32_t rJoinStatus, + struct STA_RECORD *prStaRec, struct SW_RFB *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, + (struct MSG_HDR *) 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 struct MSG_HDR *prMsgHdr) +{ + P_MSG_SAA_JOIN_REQ_T prJoinReqMsg; + struct STA_RECORD *prStaRec; + struct BSS_INFO *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 = (struct IE_CHALLENGE_TEXT *) NULL; + } + + cnmTimerStopTimer(&prStaRec->rTxReqDoneOrRxRespTimer); + + prStaRec->ucStaState = STA_STATE_1; + + /* Trigger SAA MODULE */ + saaFsmSteps(prStaRec, SAA_STATE_SEND_AUTH1, (struct SW_RFB *) NULL); +} /* end of saaFsmRunEventStart() */ +#endif + +#if CFG_SUPPORT_AAA + +void aaaFsmRunEventTxReqTimeOut(IN struct ADAPTER *prAdapter, + IN unsigned long plParamPtr) +{ + struct STA_RECORD *prStaRec = (struct STA_RECORD *) plParamPtr; + struct BSS_INFO *prBssInfo; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + ASSERT(prStaRec); + if (!prStaRec) + return; + + DBGLOG(AAA, LOUD, + "EVENT-TIMER: TX REQ TIMEOUT, Current Time = %d\n", + kalGetTimeTick()); + + /* Trigger statistics log if Auth/Assoc Tx timeout */ + wlanTriggerStatsLog(prAdapter, prAdapter->rWifiVar.u4StatsLogDuration); + + switch (prStaRec->eAuthAssocState) { + case AAA_STATE_SEND_AUTH2: + DBGLOG(AAA, ERROR, + "LOST EVENT ,Auth Tx done disappear for (%d)Ms\n", + TU_TO_MSEC(TX_AUTHENTICATION_RESPONSE_TIMEOUT_TU)); + + prStaRec->eAuthAssocState = AA_STATE_IDLE; + + /* NOTE(Kevin): Change to STATE_1 */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + +#if CFG_ENABLE_WIFI_DIRECT + if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) + p2pRoleFsmRunEventAAATxFail(prAdapter, + prStaRec, prBssInfo); +#endif /* CFG_ENABLE_WIFI_DIRECT */ + break; +#if 0 + /*state 2 to state 3 only check Assoc_req valid, no need for time out + *the fail case already handle at aaaFsmRunEventRxAssoc + */ + case AAA_STATE_SEND_ASSOC2: + DBGLOG(AAA, ERROR, + "LOST EVENT ,Assoc Tx done disappear for (%d)Ms\n", + TU_TO_MSEC(TX_AUTHENTICATION_RESPONSE_TIMEOUT_TU)); + + + prStaRec->eAuthAssocState = AAA_STATE_SEND_AUTH2; + + /* NOTE(Kevin): Change to STATE_2 */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + +#if CFG_ENABLE_WIFI_DIRECT + if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) + p2pRoleFsmRunEventAAATxFail(prAdapter, + prStaRec, prBssInfo); +#endif /* CFG_ENABLE_WIFI_DIRECT */ + break; +#endif + + default: + return; + } + + +} /* end of saaFsmRunEventTxReqTimeOut() */ + + + + + +/*---------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + uint16_t u2StatusCode; + u_int8_t fgReplyAuth = FALSE; + struct WLAN_AUTH_FRAME *prAuthFrame = (struct WLAN_AUTH_FRAME *) NULL; + + ASSERT(prAdapter); + + do { + prAuthFrame = (struct WLAN_AUTH_FRAME *) prSwRfb->pvHeader; + + DBGLOG(AAA, INFO, + "SA: " MACSTR ", bssid: " MACSTR ", sta idx: %d\n", + MAC2STR(prAuthFrame->aucSrcAddr), + MAC2STR(prAuthFrame->aucBSSID), + prSwRfb->ucStaRecIdx); + +#if CFG_ENABLE_WIFI_DIRECT + prBssInfo = p2pFuncBSSIDFindBssInfo(prAdapter, + prAuthFrame->aucBSSID); + + /* 4 <1> Check P2P network conditions */ + + /* if (prBssInfo && prAdapter->fgIsP2PRegistered) */ + /* modify coding sytle to reduce indent */ + + if (!prAdapter->fgIsP2PRegistered) + goto bow_proc; + + if (prBssInfo && 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 (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + DBGLOG(AAA, TRACE, + "process RxAuth status success\n"); + /* 4 <1.2> Validate Auth Frame + * for Network Specific Conditions + */ + fgReplyAuth = p2pFuncValidateAuth( + prAdapter, + prBssInfo, + prSwRfb, + &prStaRec, + &u2StatusCode); + +#if CFG_SUPPORT_802_11W + /* AP PMF, if PMF connection, + * ignore Rx auth + */ + /* Certification 4.3.3.4 */ + if (rsnCheckBipKeyInstalled(prAdapter, + prStaRec)) { + DBGLOG(AAA, INFO, + "Drop RxAuth\n"); + return; + } +#endif + } else { + fgReplyAuth = TRUE; + } + break; + } + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +bow_proc: + + /* 4 <2> Check BOW network conditions */ +#if CFG_ENABLE_BT_OVER_WIFI + { + struct BOW_FSM_INFO *prBowFsmInfo = + (struct BOW_FSM_INFO *) NULL; + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prBowFsmInfo->ucBssIndex); + + if ((prBssInfo->fgIsNetActive) + && (prBssInfo->eCurrentOPMode == OP_MODE_BOW)) { + + /* 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 (u2StatusCode + == STATUS_CODE_SUCCESSFUL) { + + /* 4 <2.2> Validate Auth Frame + * for Network Specific + * Conditions + */ + fgReplyAuth = + bowValidateAuth(prAdapter, + prSwRfb, + &prStaRec, + &u2StatusCode); + + } else { + + fgReplyAuth = TRUE; + } + /* TODO(Kevin): Allocate a STA_RECORD_T + * for new client + */ + break; + } + } + } +#endif /* CFG_ENABLE_BT_OVER_WIFI */ + + return; + } while (FALSE); + + if (prStaRec) { + /* update RCPI */ + ASSERT(prSwRfb->prRxStatusGroup3); + prStaRec->ucRCPI = nicRxGetRcpiValueFromRxv(RCPI_MODE_MAX, + prSwRfb); + } + /* 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, + prBssInfo->ucBssIndex, + prSwRfb, + AUTH_TRANSACTION_SEQ_2, + u2StatusCode); + + + /*sta_rec might be removed + * when client list full, skip timer setting + */ + /* + * check if prStaRec valid as authSendAuthFrame may free + * StaRec when TX resource is not enough + */ + if (prStaRec && prStaRec->fgIsInUse) { + cnmTimerStopTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer); + /*ToDo:Init Timer to check get + * Auth Txdone avoid sta_rec not clear + */ + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC) + aaaFsmRunEventTxReqTimeOut, + (unsigned long) prStaRec); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC( + TX_AUTHENTICATION_RESPONSE_TIMEOUT_TU)); + } + + + + } else if (prStaRec) + cnmStaRecFree(prAdapter, prStaRec); +} /* 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 + */ +/*---------------------------------------------------------------------------*/ +uint32_t aaaFsmRunEventRxAssoc(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + uint16_t u2StatusCode = STATUS_CODE_RESERVED; + u_int8_t fgReplyAssocResp = FALSE; + u_int8_t fgSendSAQ = FALSE; + struct WLAN_ASSOC_REQ_FRAME *prAssocReqFrame = + (struct WLAN_ASSOC_REQ_FRAME *) NULL; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + do { + prAssocReqFrame = + (struct WLAN_ASSOC_REQ_FRAME *) prSwRfb->pvHeader; + + DBGLOG(AAA, INFO, + "SA: " MACSTR ", bssid: " MACSTR ", sta idx: %d\n", + MAC2STR(prAssocReqFrame->aucSrcAddr), + MAC2STR(prAssocReqFrame->aucBSSID), + prSwRfb->ucStaRecIdx); + + /* 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)) { + uint16_t i; + + /* Not to reply association response + * with failure code due to lack of STA_REC + */ + DBGLOG(AAA, ERROR, + "get sta fail, wlan idx: %d, sta index: %d\n", + prSwRfb->ucWlanIdx, + prSwRfb->ucStaRecIdx); + + for (i = 0; i < CFG_STA_REC_NUM; i++) + cnmDumpStaRec(prAdapter, i); + break; + } + + if (!IS_CLIENT_STA(prStaRec)) { + DBGLOG(AAA, ERROR, + "error sta type, skip process rx assoc\n"); + cnmDumpStaRec(prAdapter, prSwRfb->ucStaRecIdx); + break; + } + + DBGLOG(AAA, TRACE, + "RxAssoc enter ucStaState:%d, eAuthassocState:%d\n", + prStaRec->ucStaState, prStaRec->eAuthAssocState); + + 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); + + /* Maybe Auth Response TX fail, + * but actually it success. + */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + } + + /* update RCPI */ + ASSERT(prSwRfb->prRxStatusGroup3); + prStaRec->ucRCPI = + nicRxGetRcpiValueFromRxv(RCPI_MODE_MAX, prSwRfb); + + /* 4 <2> Check P2P network conditions */ +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) + && (IS_STA_IN_P2P(prStaRec))) { + + prBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + 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 (u2StatusCode + == STATUS_CODE_SUCCESSFUL) { + /* 4 <2.2> + * Validate Assoc Req Frame + * for Network Specific + * Conditions + */ + fgReplyAssocResp = + p2pFuncValidateAssocReq( + prAdapter, + prSwRfb, + (uint16_t *) + &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_BOW_TYPE(prStaRec)) { + + prBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + if ((prBssInfo->fgIsNetActive) + && (prBssInfo->eCurrentOPMode == OP_MODE_BOW)) { + + /* 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 (u2StatusCode + == STATUS_CODE_SUCCESSFUL) { + + /* 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) { + uint16_t u2IELength; + uint8_t *pucIE; + + cnmTimerStopTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer); + + if ((((struct WLAN_ASSOC_REQ_FRAME *) + (prSwRfb->pvHeader))->u2FrameCtrl & MASK_FRAME_TYPE) == + MAC_FRAME_REASSOC_REQ) { + + u2IELength = prSwRfb->u2PacketLen - + (uint16_t) + OFFSET_OF(struct WLAN_REASSOC_REQ_FRAME, + aucInfoElem[0]); + + pucIE = ((struct WLAN_REASSOC_REQ_FRAME *) + (prSwRfb->pvHeader))->aucInfoElem; + } else { + u2IELength = prSwRfb->u2PacketLen - + (uint16_t) + OFFSET_OF(struct WLAN_ASSOC_REQ_FRAME, + aucInfoElem[0]); + + pucIE = ((struct WLAN_ASSOC_REQ_FRAME *) + (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))) { + prBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + if (p2pRoleFsmRunEventAAAComplete(prAdapter, + prStaRec, prBssInfo) + == WLAN_STATUS_SUCCESS) { + prStaRec->u2AssocId = + bssAssignAssocID(prStaRec); + /* prStaRec->eAuthAssocState + * = AA_STATE_IDLE; + */ + /* NOTE(Kevin): for TX done */ + prStaRec->eAuthAssocState = + AAA_STATE_SEND_ASSOC2; + /* 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; + + /* Invalid Association ID */ + prStaRec->u2AssocId = 0; + + /* If(Re)association fail, + * remove sta record and + * use class error to handle sta + */ + prStaRec->eAuthAssocState = + AA_STATE_IDLE; + + /* 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_BOW_TYPE(prStaRec))) { + /* if (bowRunEventAAAComplete(prAdapter, + * prStaRec) == WLAN_STATUS_SUCCESS) { + */ + prStaRec->u2AssocId = + bssAssignAssocID(prStaRec); + + /* NOTE(Kevin): for TX done */ + prStaRec->eAuthAssocState = + AAA_STATE_SEND_ASSOC2; + + /* NOTE(Kevin): + * Method A: Change to STATE_3 + * before handle TX Done + */ + /* cnmStaRecChangeState(prAdapter, + * prStaRec, STA_STATE_3); + */ + } +#endif + } else { + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + /* don't change state, + * just send assoc resp + * (NO need TX done, TIE + code30) + * and then SAQ + */ + if (u2StatusCode + == STATUS_CODE_ASSOC_REJECTED_TEMPORARILY) { + DBGLOG(AAA, INFO, "AP send SAQ\n"); + fgSendSAQ = TRUE; + } else +#endif + { + /* Invalid Association ID */ + prStaRec->u2AssocId = 0; + + /* If (Re)association fail, remove sta record + * and use class error to handle sta + */ + prStaRec->eAuthAssocState = AA_STATE_IDLE; + /* Remove from client list if it was previously + * associated + */ + if ((prStaRec->ucStaState > STA_STATE_1) && + prAdapter->fgIsP2PRegistered && + (IS_STA_IN_P2P(prStaRec))) { + struct BSS_INFO *prBssInfo = NULL; + + prBssInfo = GET_BSS_INFO_BY_INDEX( + prAdapter, + prStaRec->ucBssIndex); + if (prBssInfo) { + DBGLOG(AAA, INFO, + "Remove client\n"); + bssRemoveClient( + prAdapter, + prBssInfo, + prStaRec); + } + } + + /* 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); + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if (fgSendSAQ) { + /* if PMF connection, and return code 30, send SAQ */ + rsnApStartSaQuery(prAdapter, prStaRec); + } +#endif + + } + + 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 + */ +/*---------------------------------------------------------------------------*/ +uint32_t +aaaFsmRunEventTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + + DBGLOG(AAA, INFO, + "EVENT-TX DONE [status: %d][seq: %d]: Current Time = %d\n", + rTxDoneStatus, + prMsduInfo->ucTxSeqNum, + kalGetTimeTick()); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + /* For the case of replying ERROR STATUS CODE */ + if ((!prStaRec) || (!prStaRec->fgIsInUse)) + return WLAN_STATUS_SUCCESS; + + ASSERT(prStaRec->ucBssIndex <= prAdapter->ucHwBssIdNum); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + DBGLOG(AAA, TRACE, "TxDone ucStaState:%d, eAuthAssocState:%d\n", + prStaRec->ucStaState, prStaRec->eAuthAssocState); + + /* Trigger statistics log if Auth/Assoc Tx failed */ + if (rTxDoneStatus != TX_RESULT_SUCCESS) + wlanTriggerStatsLog(prAdapter, + prAdapter->rWifiVar.u4StatsLogDuration); + + 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; + + cnmTimerStopTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer); + + if (prStaRec->u2StatusCode == STATUS_CODE_SUCCESSFUL) { + if (rTxDoneStatus == TX_RESULT_SUCCESS) { + + /* NOTE(Kevin): + * Change to STATE_2 at TX Done + */ + cnmStaRecChangeState(prAdapter, + prStaRec, STA_STATE_2); + /* Error handle if can not + * complete the ASSOC flow + */ + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC(TX_ASSOCIATE_TIMEOUT_TU)); + } else { + + prStaRec->eAuthAssocState = + AA_STATE_IDLE; + + /* NOTE(Kevin): Change to STATE_1 */ + cnmStaRecChangeState(prAdapter, + prStaRec, STA_STATE_1); + +#if CFG_ENABLE_WIFI_DIRECT + if (prBssInfo->eNetworkType + == NETWORK_TYPE_P2P) + p2pRoleFsmRunEventAAATxFail( + prAdapter, + prStaRec, prBssInfo); +#endif /* CFG_ENABLE_WIFI_DIRECT */ +#if CFG_ENABLE_BT_OVER_WIFI + if (IS_STA_BOW_TYPE(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 (prStaRec->u2StatusCode == STATUS_CODE_SUCCESSFUL) { + if (rTxDoneStatus == TX_RESULT_SUCCESS) { + + prStaRec->eAuthAssocState = + AA_STATE_IDLE; + + /* NOTE(Kevin): + * Change to STATE_3 at TX Done + */ +#if CFG_ENABLE_WIFI_DIRECT + if (prBssInfo->eNetworkType + == NETWORK_TYPE_P2P) + p2pRoleFsmRunEventAAASuccess( + prAdapter, + prStaRec, + prBssInfo); +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +#if CFG_ENABLE_BT_OVER_WIFI + + if (IS_STA_BOW_TYPE(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 (prBssInfo->eNetworkType + == NETWORK_TYPE_P2P) + p2pRoleFsmRunEventAAATxFail( + prAdapter, + prStaRec, + prBssInfo); +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +#if CFG_ENABLE_BT_OVER_WIFI + if (IS_STA_BOW_TYPE(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 AA_STATE_IDLE: + /* 2013-08-27 frog: Do nothing. + * Somtimes we may send Assoc Resp twice. + * (Rx Assoc Req before the first Assoc TX Done) + * The AssocState is changed to IDLE after first TX done. + * Free station record when IDLE is seriously wrong. + */ + /* 2017-01-12 Do nothing only when STA is in state 3 */ + /* Free the StaRec if found any unexpected status */ + if (prStaRec->ucStaState != STA_STATE_3) + cnmStaRecFree(prAdapter, prStaRec); + break; + + default: + break; /* Ignore other cases */ + } + + DBGLOG(AAA, TRACE, "TxDone end ucStaState:%d, eAuthAssocState:%d\n", + prStaRec->ucStaState, prStaRec->eAuthAssocState); + + 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 struct MSG_HDR *prMsgHdr) +{ + P_JOIN_INFO_T prJoinInfo; + struct STA_RECORD *prStaRec; + + DEBUGFUNC("joinFsmRunEventAbort"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + + DBGLOG(JOIN, EVENT, "JOIN EVENT: ABORT\n"); + + /* NOTE(Kevin): when reach here, + * the ARB_STATE should be in ARB_STATE_JOIN. + */ + ASSERT(prJoinInfo->prBssDesc); + + /* 4 <1> Update Flags and Elements of JOIN Module. */ + /* Reset Send Auth/(Re)Assoc Frame Count */ + prJoinInfo->ucTxAuthAssocRetryCount = 0; + + /* Cancel all JOIN relative Timer */ + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rTxRequestTimer); + + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rRxResponseTimer); + + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rJoinTimer); + + /* 4 <2> Update the associated + * STA_RECORD_T during JOIN. + */ + /* Get a Station Record if possible, TA == BSSID for AP */ + prStaRec = staRecGetStaRecordByAddr(prAdapter, + prJoinInfo->prBssDesc->aucBSSID); + if (prStaRec) + prStaRec->ucStaState = STA_STATE_1; + /* Update Station Record - Class 1 Flag */ +#if DBG + else + ASSERT(0); + /* Shouldn't happened, because we already + * add this STA_RECORD_T at JOIN_STATE_INIT + */ + +#endif /* DBG */ + + /* 4 <3> Pull back to IDLE. */ + joinFsmSteps(prAdapter, JOIN_STATE_IDLE); + + /* 4 <4> If we are in Roaming, recover the settings of previous BSS. */ + /* NOTE: JOIN FAIL - + * Restore original setting from current struct BSS_INFO. + */ + if (prAdapter->eConnectionState == MEDIA_STATE_CONNECTED) + joinAdoptParametersFromCurrentBss(prAdapter); +} /* end of joinFsmRunEventAbort() */ +#endif + +/* TODO(Kevin): following code will be modified and move to AIS FSM */ +#if 0 +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will send Join Timeout Event to JOIN FSM. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * + * \retval WLAN_STATUS_FAILURE Fail because of Join Timeout + */ +/*----------------------------------------------------------------------------*/ +uint32_t joinFsmRunEventJoinTimeOut(IN struct ADAPTER *prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + struct STA_RECORD *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 struct ADAPTER *prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + struct BSS_DESC *prBssDesc; + + DEBUGFUNC("joinAdoptParametersFromPeerBss"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + prBssDesc = prJoinInfo->prBssDesc; + + /* 4 <1> Adopt Peer BSS' PHY TYPE */ + prAdapter->eCurrentPhyType = prBssDesc->ePhyType; + + DBGLOG(JOIN, INFO, "Target BSS[%s]'s PhyType = %s\n", + prBssDesc->aucSSID, + (prBssDesc->ePhyType == PHY_TYPE_ERP_INDEX) ? "ERP" : "HR_DSSS"); + + /* 4 <2> Adopt Peer BSS' Frequency(Band/Channel) */ + DBGLOG(JOIN, INFO, + "Target BSS's Channel = %d, Band = %d\n", + prBssDesc->ucChannelNum, prBssDesc->eBand); + + nicSwitchChannel(prAdapter, + prBssDesc->eBand, prBssDesc->ucChannelNum, 10); + + prJoinInfo->fgIsParameterAdopted = TRUE; +} /* end of joinAdoptParametersFromPeerBss() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will adopt the parameters from current associated BSS. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void joinAdoptParametersFromCurrentBss(IN struct ADAPTER *prAdapter) +{ + /* P_JOIN_INFO_T prJoinInfo = &prAdapter->rJoinInfo; */ + struct BSS_INFO *prBssInfo; + + ASSERT(prAdapter); + prBssInfo = &prAdapter->rBssInfo; + + /* 4 <1> Adopt current BSS' PHY TYPE */ + prAdapter->eCurrentPhyType = prBssInfo->ePhyType; + + /* 4 <2> Adopt current BSS' Frequency(Band/Channel) */ + DBGLOG(JOIN, INFO, + "Current BSS's Channel = %d, Band = %d\n", + prBssInfo->ucChnl, prBssInfo->eBand); + + nicSwitchChannel(prAdapter, prBssInfo->eBand, prBssInfo->ucChnl, 10); +} /* end of joinAdoptParametersFromCurrentBss() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will update all the SW variables and + * HW MCR registers after + * the association with target BSS. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void joinComplete(IN struct ADAPTER *prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + struct BSS_DESC *prBssDesc; + P_PEER_BSS_INFO_T prPeerBssInfo; + struct BSS_INFO *prBssInfo; + struct CONNECTION_SETTINGS *prConnSettings; + struct STA_RECORD *prStaRec; + struct TX_CTRL *prTxCtrl; +#if CFG_SUPPORT_802_11D + struct IE_COUNTRY *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 */ + /* Our BSS's PHY_TYPE is ERP now. */ + if ((prBssInfo->ePhyType == PHY_TYPE_ERP_INDEX) && + (prBssDesc->fgIsERPPresent)) { + + prBssInfo->fgIsERPPresent = TRUE; + /* Save the ERP for later check */ + prBssInfo->ucERP = prBssDesc->ucERP; + } 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) { + struct DOMAIN_INFO_ENTRY rDomainInfo; + + if (domainGetDomainInfoByScanResult(prAdapter, &rDomainInfo)) { + if (prBssDesc->prIECountry) { + prIECountry = prBssDesc->prIECountry; + + domainParseCountryInfoElem(prIECountry, + &prBssInfo->rDomainInfo); + + /* use the domain get from the BSS info */ + prBssInfo->fgIsCountryInfoPresent = TRUE; + nicSetupOpChnlList(prAdapter, + prBssInfo->rDomainInfo.u2CountryCode, + FALSE); + } else { + /* use the domain get from the scan result */ + prBssInfo->fgIsCountryInfoPresent = TRUE; + nicSetupOpChnlList(prAdapter, + rDomainInfo.u2CountryCode, FALSE); + } + } + } +#endif + + /* 4 <2.K> Signal Power of the associated AP */ + prBssInfo->rRcpi = prBssDesc->rRcpi; + prBssInfo->rRssi = RCPI_TO_dBm(prBssInfo->rRcpi); + GET_CURRENT_SYSTIME(&prBssInfo->rRssiLastUpdateTime); + + /* 4 <2.L> Capability Field of the associated AP */ + prBssInfo->u2CapInfo = prBssDesc->u2CapInfo; + + DBGLOG(JOIN, INFO, + "prBssInfo-> fgIsERPPresent = %d, ucERP = %02x, rRcpi = %d, rRssi = %ld\n", + prBssInfo->fgIsERPPresent, + prBssInfo->ucERP, + prBssInfo->rRcpi, + prBssInfo->rRssi); + +/* 4 <3> Update BSS_INFO_T from PEER_BSS_INFO_T & NIC RATE FUNC */ + /* 4 <3.A> Association ID */ + prBssInfo->u2AssocId = prPeerBssInfo->u2AssocId; + + /* 4 <3.B> WMM Information */ + if (prAdapter->fgIsEnableWMM + && (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_SUPPORT_WMM)) { + + prBssInfo->fgIsWmmAssoc = TRUE; + prTxCtrl->rTxQForVoipAccess = TXQ_AC3; + + qosWmmInfoInit(&prBssInfo->rWmmInfo, + (prBssInfo->ePhyType == PHY_TYPE_HR_DSSS_INDEX) + ? TRUE : FALSE); + + if (prPeerBssInfo->rWmmInfo.ucWmmFlag + & WMM_FLAG_AC_PARAM_PRESENT) { + kalMemCopy(&prBssInfo->rWmmInfo, + &prPeerBssInfo->rWmmInfo, sizeof(WMM_INFO_T)); + } else { + kalMemCopy(&prBssInfo->rWmmInfo, + &prPeerBssInfo->rWmmInfo, + sizeof(WMM_INFO_T) - + sizeof(prPeerBssInfo->rWmmInfo.arWmmAcParams)); + } + } else { + prBssInfo->fgIsWmmAssoc = FALSE; + prTxCtrl->rTxQForVoipAccess = TXQ_AC1; + + kalMemZero(&prBssInfo->rWmmInfo, sizeof(WMM_INFO_T)); + } + + /* 4 <3.C> Operational Rate Set & BSS Basic Rate Set */ + prBssInfo->u2OperationalRateSet = prPeerBssInfo->u2OperationalRateSet; + prBssInfo->u2BSSBasicRateSet = prPeerBssInfo->u2BSSBasicRateSet; + + /* 4 <3.D> Short Preamble */ + if (prBssInfo->fgIsERPPresent) { + +/* NOTE(Kevin 2007/12/24): Truth Table. + *Short Preamble Bit in + * Final Driver Setting(Short) + *TRUE FALSE FALSE FALSE(shouldn't have such case, + * use the AssocResp) + *TRUE FALSE TRUE FALSE + *FALSE FALSE FALSE FALSE(shouldn't have such case, + * use the AssocResp) + *FALSE FALSE TRUE FALSE + *TRUE TRUE FALSE TRUE(follow ERP) + *TRUE TRUE TRUE FALSE(follow ERP) + *FALSE TRUE FALSE FALSE(shouldn't have such case, + * and we should set to FALSE) + *FALSE TRUE TRUE FALSE(we should set to FALSE) + */ + if ((prPeerBssInfo->fgIsShortPreambleAllowed) && + ((prConnSettings->ePreambleType == PREAMBLE_TYPE_SHORT) || + /* Short Preamble Option Enable is TRUE */ + ((prConnSettings->ePreambleType == PREAMBLE_TYPE_AUTO) + && (prBssDesc->u2CapInfo & CAP_INFO_SHORT_PREAMBLE)))) { + + prBssInfo->fgIsShortPreambleAllowed = TRUE; + + if (prBssInfo->ucERP & ERP_INFO_BARKER_PREAMBLE_MODE) + prBssInfo->fgUseShortPreamble = FALSE; + else + prBssInfo->fgUseShortPreamble = TRUE; + + } else { + prBssInfo->fgIsShortPreambleAllowed = FALSE; + prBssInfo->fgUseShortPreamble = FALSE; + } + } else { + /* NOTE(Kevin 2007/12/24): Truth Table. + * Short Preamble Bit in + * Final Driver Setting(Short) + * TRUE FALSE FALSE + * FALSE FALSE FALSE + * TRUE TRUE TRUE + * FALSE TRUE(status success) TRUE + * --> Honor the result of prPeerBssInfo. + */ + + prBssInfo->fgIsShortPreambleAllowed = + prBssInfo->fgUseShortPreamble = + prPeerBssInfo->fgIsShortPreambleAllowed; + } + + DBGLOG(JOIN, INFO, + "prBssInfo->fgIsShortPreambleAllowed = %d, prBssInfo->fgUseShortPreamble = %d\n", + prBssInfo->fgIsShortPreambleAllowed, + prBssInfo->fgUseShortPreamble); + + /* 4 <3.E> Short Slot Time */ + /* AP support Short Slot Time */ + prBssInfo->fgUseShortSlotTime = + prPeerBssInfo->fgUseShortSlotTime; + + 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) { + uint16_t 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, + (uint8_t) TXQ_DATA_MASK, (uint8_t) 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, (void *) NULL, 0); +} /* end of joinComplete() */ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/ais_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/ais_fsm.c new file mode 100644 index 0000000000000..3493ba0450a4a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/ais_fsm.c @@ -0,0 +1,6675 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/ais_fsm.c#4 + */ + +/*! \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. + */ + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ +#define AIS_ROAMING_CONNECTION_TRIAL_LIMIT 2 +#define AIS_JOIN_TIMEOUT 7 + +#define AIS_FSM_STATE_SEARCH_ACTION_PHASE_0 0 +#define AIS_FSM_STATE_SEARCH_ACTION_PHASE_1 1 +#define AIS_FSM_STATE_SEARCH_ACTION_PHASE_2 2 + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +#if CFG_DISCONN_DEBUG_FEATURE +struct AIS_DISCONN_INFO_T g_rDisconnInfoTemp; +uint8_t g_DisconnInfoIdx; +struct AIS_DISCONN_INFO_T *g_prDisconnInfo; +#endif + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +static uint8_t *apucDebugAisState[AIS_STATE_NUM] = { + (uint8_t *) DISP_STRING("IDLE"), + (uint8_t *) DISP_STRING("SEARCH"), + (uint8_t *) DISP_STRING("SCAN"), + (uint8_t *) DISP_STRING("ONLINE_SCAN"), + (uint8_t *) DISP_STRING("LOOKING_FOR"), + (uint8_t *) DISP_STRING("WAIT_FOR_NEXT_SCAN"), + (uint8_t *) DISP_STRING("REQ_CHANNEL_JOIN"), + (uint8_t *) DISP_STRING("JOIN"), + (uint8_t *) DISP_STRING("JOIN_FAILURE"), + (uint8_t *) DISP_STRING("IBSS_ALONE"), + (uint8_t *) DISP_STRING("IBSS_MERGE"), + (uint8_t *) DISP_STRING("NORMAL_TR"), + (uint8_t *) DISP_STRING("DISCONNECTING"), + (uint8_t *) DISP_STRING("REQ_REMAIN_ON_CHANNEL"), + (uint8_t *) DISP_STRING("REMAIN_ON_CHANNEL") +}; + +/******************************************************************************* + * M A 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 aisFsmRunEventScanDoneTimeOut(IN struct ADAPTER *prAdapter, + unsigned long ulParam); +static void aisFsmSetOkcTimeout(IN struct ADAPTER *prAdapter, + unsigned long ulParam); +/* Support AP Selection*/ +static void aisRemoveDisappearedBlacklist(struct ADAPTER *prAdapter); +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +static void aisResetBssTranstionMgtParam(struct AIS_SPECIFIC_BSS_INFO + *prSpecificBssInfo) +{ + struct BSS_TRANSITION_MGT_PARAM_T *prBtmParam = + &prSpecificBssInfo->rBTMParam; + +#if !CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT + return; +#endif + if (prBtmParam->u2OurNeighborBssLen > 0) { + kalMemFree(prBtmParam->pucOurNeighborBss, VIR_MEM_TYPE, + prBtmParam->u2OurNeighborBssLen); + prBtmParam->u2OurNeighborBssLen = 0; + } + kalMemZero(prBtmParam, sizeof(*prBtmParam)); +} +/*----------------------------------------------------------------------------*/ +/*! + * @brief the function is used to initialize the value of the connection + * settings for AIS network + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisInitializeConnectionSettings(IN struct ADAPTER *prAdapter, + IN struct REG_INFO *prRegInfo) +{ + struct CONNECTION_SETTINGS *prConnSettings; + uint8_t aucAnyBSSID[] = BC_BSSID; + uint8_t 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->eReConnectLevel = RECONNECT_LEVEL_MIN; + 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 = + (uint8_t) nicFreq2ChannelNum(prRegInfo->u4StartFreq); + prConnSettings->eAdHocBand = + prRegInfo->u4StartFreq < 5000000 ? BAND_2G4 : BAND_5G; + prConnSettings->eAdHocMode = + (enum ENUM_PARAM_AD_HOC_MODE)(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, prAdapter->prAisBssInfo->ucBssIndex); + + /* Features */ + prConnSettings->fgIsEnableRoaming = FALSE; + + prConnSettings->fgSecModeChangeStartTimer = FALSE; + +#if CFG_SUPPORT_ROAMING +#if 0 + if (prRegInfo) + prConnSettings->fgIsEnableRoaming = + ((prRegInfo->fgDisRoaming > 0) ? (FALSE) : (TRUE)); +#else + if (prAdapter->rWifiVar.fgDisRoaming) + prConnSettings->fgIsEnableRoaming = FALSE; + else + prConnSettings->fgIsEnableRoaming = TRUE; +#endif +#endif /* CFG_SUPPORT_ROAMING */ + + prConnSettings->fgIsAdHocQoSEnable = FALSE; + +#if CFG_SUPPORT_802_11AC + prConnSettings->eDesiredPhyConfig = PHY_CONFIG_802_11ABGNAC; +#else + prConnSettings->eDesiredPhyConfig = PHY_CONFIG_802_11ABGN; +#endif + + if (prAdapter->rWifiVar.ucHwNotSupportAC) + 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.u4GroupMgmtKeyCipherSuite = 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; + prConnSettings->rRsnInfo.u2PmkidCnt = 0; + kalMemZero(prConnSettings->rRsnInfo.aucPmkidList, + (sizeof(uint8_t) * MAX_NUM_SUPPORTED_PMKID * RSN_PMKID_LEN)); +#if CFG_SUPPORT_CFG80211_AUTH + prConnSettings->bss = NULL; +#endif +#if CFG_SUPPORT_OWE + kalMemSet(&prConnSettings->rOweInfo, 0, sizeof(struct OWE_INFO_T)); +#endif +} /* 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 struct ADAPTER *prAdapter) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prAisBssInfo; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecificBssInfo; + uint8_t i; + + DEBUGFUNC("aisFsmInit()"); + DBGLOG(SW1, INFO, "->aisFsmInit()\n"); + + /* avoid that the prAisBssInfo is realloc */ + if (prAdapter->prAisBssInfo != NULL) + return; + + prAdapter->prAisBssInfo = prAisBssInfo = + cnmGetBssInfoAndInit(prAdapter, NETWORK_TYPE_AIS, FALSE); + ASSERT(prAisBssInfo); + + /* update MAC address */ + COPY_MAC_ADDR(prAdapter->prAisBssInfo->aucOwnMacAddr, + prAdapter->rMyMacAddr); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisSpecificBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); + + /* 4 <1> Initiate FSM */ + prAisFsmInfo->ePreviousState = AIS_STATE_IDLE; + prAisFsmInfo->eCurrentState = AIS_STATE_IDLE; + + prAisFsmInfo->ucAvailableAuthTypes = 0; + + prAisFsmInfo->prTargetBssDesc = (struct BSS_DESC *)NULL; + + prAisFsmInfo->ucSeqNumOfReqMsg = 0; + prAisFsmInfo->ucSeqNumOfChReq = 0; + prAisFsmInfo->ucSeqNumOfScanReq = 0; + prAisFsmInfo->u2SeqNumOfScanReport = AIS_SCN_REPORT_SEQ_NOT_SET; + + prAisFsmInfo->fgIsInfraChannelFinished = TRUE; +#if CFG_SUPPORT_ROAMING + prAisFsmInfo->fgIsRoamingScanPending = FALSE; +#endif /* CFG_SUPPORT_ROAMING */ + prAisFsmInfo->fgIsChannelRequested = FALSE; + prAisFsmInfo->fgIsChannelGranted = FALSE; + prAisFsmInfo->u4PostponeIndStartTime = 0; + /* Support AP Selection */ + prAisFsmInfo->ucJoinFailCntAfterScan = 0; + + prAisFsmInfo->fgIsScanOidAborted = FALSE; + + prAisFsmInfo->fgIsScanning = FALSE; + + /* 4 <1.1> Initiate FSM - Timer INIT */ + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rBGScanTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventBGSleepTimeOut, + (unsigned long)NULL); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rIbssAloneTimer, + (PFN_MGMT_TIMEOUT_FUNC) + aisFsmRunEventIbssAloneTimeOut, (unsigned long)NULL); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rScanDoneTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventScanDoneTimeOut, + (unsigned long)NULL); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rJoinTimeoutTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventJoinTimeout, + (unsigned long)NULL); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rChannelTimeoutTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventChannelTimeout, + (unsigned long)NULL); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rDeauthDoneTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventDeauthTimeout, + (unsigned long)NULL); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rWaitOkcPMKTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmSetOkcTimeout, + (unsigned long)NULL); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rSecModeChangeTimer, + (PFN_MGMT_TIMEOUT_FUNC) + aisFsmRunEventSecModeChangeTimeout, + (unsigned long)NULL); + + /* 4 <1.2> Initiate PWR STATE */ + SET_NET_PWR_STATE_IDLE(prAdapter, prAisBssInfo->ucBssIndex); + + /* 4 <2> Initiate BSS_INFO_T - common part */ + BSS_INFO_INIT(prAdapter, prAisBssInfo); + 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 = (struct STA_RECORD *) NULL; + prAisBssInfo->ucNss = + wlanGetSupportNss(prAdapter, prAisBssInfo->ucBssIndex); +#if (CFG_HW_WMM_BY_BSS == 0) + prAisBssInfo->ucWmmQueSet = + (prAdapter->rWifiVar.eDbdcMode == + ENUM_DBDC_MODE_DISABLED) ? DBDC_5G_WMM_INDEX : DBDC_2G_WMM_INDEX; +#endif + /* 4 <4> Allocate MSDU_INFO_T for Beacon */ + prAisBssInfo->prBeacon = cnmMgtPktAlloc(prAdapter, + OFFSET_OF(struct WLAN_BEACON_FRAME, + aucInfoElem[0]) + MAX_IE_LENGTH); + + if (prAisBssInfo->prBeacon) { + prAisBssInfo->prBeacon->eSrc = TX_PACKET_MGMT; + /* NULL STA_REC */ + prAisBssInfo->prBeacon->ucStaRecIndex = 0xFF; + } else { + ASSERT(0); + } + + prAisBssInfo->ucBMCWlanIndex = WTBL_RESERVED_ENTRY; + + for (i = 0; i < MAX_KEY_NUM; i++) { + prAisBssInfo->ucBMCWlanIndexS[i] = WTBL_RESERVED_ENTRY; + prAisBssInfo->ucBMCWlanIndexSUsed[i] = FALSE; + prAisBssInfo->wepkeyUsed[i] = FALSE; + } +#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 = + (uint8_t) prAdapter->u4UapsdAcBmp; + prAisBssInfo->rPmProfSetupInfo.ucBmpTriggerAC = + (uint8_t) prAdapter->u4UapsdAcBmp; + prAisBssInfo->rPmProfSetupInfo.ucUapsdSp = + (uint8_t) prAdapter->u4MaxSpLen; +#endif + + /* request list initialization */ + LINK_INITIALIZE(&prAisFsmInfo->rPendingReqList); + + /* Support AP Selection */ + LINK_MGMT_INIT(&prAdapter->rWifiVar.rConnSettings.rBlackList); + kalMemZero(&prAisSpecificBssInfo->arCurEssChnlInfo[0], + sizeof(prAisSpecificBssInfo->arCurEssChnlInfo)); + LINK_INITIALIZE(&prAisSpecificBssInfo->rCurEssLink); + /* end Support AP Selection */ + /* 11K, 11V */ + LINK_MGMT_INIT(&prAisSpecificBssInfo->rNeighborApList); + kalMemZero(&prAisSpecificBssInfo->rBTMParam, + sizeof(prAisSpecificBssInfo->rBTMParam)); + + /* DBGPRINTF("[2] ucBmpDeliveryAC:0x%x, + * ucBmpTriggerAC:0x%x, ucUapsdSp:0x%x", + */ + /* prAisBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC, */ + /* prAisBssInfo->rPmProfSetupInfo.ucBmpTriggerAC, */ + /* prAisBssInfo->rPmProfSetupInfo.ucUapsdSp); */ + + /* Bind NetDev & BssInfo */ + /* wlanBindBssIdxToNetInterface(prAdapter->prGlueInfo, + * NET_DEV_WLAN_IDX, prAisBssInfo->ucBssIndex); + */ + +#if CFG_DISCONN_DEBUG_FEATURE + g_prDisconnInfo = (struct AIS_DISCONN_INFO_T *)kalMemAlloc( + sizeof(struct AIS_DISCONN_INFO_T) * MAX_DISCONNECT_RECORD, + VIR_MEM_TYPE); + if (g_prDisconnInfo != NULL) { + kalMemZero(g_prDisconnInfo, + sizeof(struct AIS_DISCONN_INFO_T) * + MAX_DISCONNECT_RECORD); + } else { + DBGLOG(AIS, ERROR, + "allocate memory for g_prDisconnInfo failed!\n"); + } + + g_DisconnInfoIdx = 0; + + /* default value */ + kalMemZero(&g_rDisconnInfoTemp, sizeof(struct AIS_DISCONN_INFO_T)); + g_rDisconnInfoTemp.ucBcnTimeoutReason = 0xF; + g_rDisconnInfoTemp.u2DisassocSeqNum = 0xFFFF; +#endif + +} /* 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 struct ADAPTER *prAdapter) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prAisBssInfo; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecificBssInfo; + + DEBUGFUNC("aisFsmUninit()"); + DBGLOG(SW1, INFO, "->aisFsmUninit()\n"); + + /* avoid that the prAisBssInfo is double freed */ + if (prAdapter->prAisBssInfo == NULL) + return; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = prAdapter->prAisBssInfo; + prAisSpecificBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); + + /* 4 <1> Stop all timers */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rBGScanTimer); + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rIbssAloneTimer); + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rJoinTimeoutTimer); + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer); + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rWaitOkcPMKTimer); + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rSecModeChangeTimer); + + /* 4 <2> flush pending request */ + aisFsmFlushRequest(prAdapter); + aisResetBssTranstionMgtParam(prAisSpecificBssInfo); + + /* 4 <3> Reset driver-domain BSS-INFO */ + if (prAisBssInfo) { + + if (prAisBssInfo->prBeacon) { + cnmMgtPktFree(prAdapter, prAisBssInfo->prBeacon); + prAisBssInfo->prBeacon = NULL; + } + + cnmFreeBssInfo(prAdapter, prAisBssInfo); + prAdapter->prAisBssInfo = NULL; + } +#if CFG_SUPPORT_802_11W + rsnStopSaQuery(prAdapter); +#endif + /* Support AP Selection */ + LINK_MGMT_UNINIT(&prAdapter->rWifiVar.rConnSettings.rBlackList, + struct AIS_BLACKLIST_ITEM, VIR_MEM_TYPE); + /* end Support AP Selection */ + LINK_MGMT_UNINIT(&prAisSpecificBssInfo->rNeighborApList, + struct NEIGHBOR_AP_T, VIR_MEM_TYPE); + +#if CFG_DISCONN_DEBUG_FEATURE + if (g_prDisconnInfo != NULL) { + kalMemFree(g_prDisconnInfo, + VIR_MEM_TYPE, + sizeof(struct AIS_DISCONN_INFO_T) * + MAX_DISCONNECT_RECORD); + g_prDisconnInfo = NULL; + } +#endif +} /* end of aisFsmUninit() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Initialization of JOIN STATE + * + * @param[in] prBssDesc The pointer of BSS_DESC_T which is the BSS we will + * try to join with. + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisFsmStateInit_JOIN(IN struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prAisBssInfo; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecificBssInfo; + struct CONNECTION_SETTINGS *prConnSettings; + struct STA_RECORD *prStaRec; + struct MSG_SAA_FSM_START *prJoinReqMsg; + + DEBUGFUNC("aisFsmStateInit_JOIN()"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = prAdapter->prAisBssInfo; + 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, + prAdapter-> + prAisBssInfo->ucBssIndex, + prBssDesc); + + prAisFsmInfo->prTargetStaRec = prStaRec; + + /* 4 <2.1> sync. to firmware domain */ + if (prStaRec->ucStaState == STA_STATE_1) + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + /* 4 <3> Update ucAvailableAuthTypes which we can choice during SAA */ + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { + + prStaRec->fgIsReAssoc = FALSE; + + /*Fill Auth Type */ +#if CFG_SUPPORT_CFG80211_AUTH + prAisFsmInfo->ucAvailableAuthTypes = + (uint8_t) prAdapter->prGlueInfo->rWpaInfo.u4AuthAlg; + DBGLOG(AIS, INFO, "JOIN INIT: Auth Algorithm :%d\n", + prAisFsmInfo->ucAvailableAuthTypes); +#else + switch (prConnSettings->eAuthMode) { + /* FT initial mobility doamin association always + ** use Open AA + */ + case AUTH_MODE_NON_RSN_FT: + case AUTH_MODE_WPA2_FT: + case AUTH_MODE_WPA2_FT_PSK: + 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: + case AUTH_MODE_WPA_OSEN: + prAisFsmInfo->ucAvailableAuthTypes = + (uint8_t) AUTH_TYPE_OPEN_SYSTEM; + break; + + case AUTH_MODE_SHARED: + prAisFsmInfo->ucAvailableAuthTypes = + (uint8_t) AUTH_TYPE_SHARED_KEY; + break; + + case AUTH_MODE_AUTO_SWITCH: + DBGLOG(AIS, LOUD, + "JOIN INIT: eAuthMode == AUTH_MODE_AUTO_SWITCH\n"); + prAisFsmInfo->ucAvailableAuthTypes = + (uint8_t) (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; + } +#endif + /* TODO(tyhsu): Assume that Roaming Auth Type + * is equal to ConnSettings eAuthMode + */ + prAisSpecificBssInfo->ucRoamingAuthTypes = + prAisFsmInfo->ucAvailableAuthTypes; + + prStaRec->ucTxAuthAssocRetryLimit = TX_AUTH_ASSOCI_RETRY_LIMIT; + /* reset BTM Params when do first connection */ + aisResetBssTranstionMgtParam(prAisSpecificBssInfo); + + /* Update Bss info before join */ + prAisBssInfo->eBand = prBssDesc->eBand; + prAisBssInfo->ucPrimaryChannel = prBssDesc->ucChannelNum; + + } else { + ASSERT(prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE); + + DBGLOG(AIS, LOUD, "JOIN INIT: AUTH TYPE = %d for Roaming\n", + prAisSpecificBssInfo->ucRoamingAuthTypes); + + /* We do roaming while the medium is connected */ + prStaRec->fgIsReAssoc = TRUE; + + /* TODO(Kevin): We may call a sub function to + * acquire the Roaming Auth Type + */ + switch (prConnSettings->eAuthMode) { + case AUTH_MODE_WPA2_FT: + case AUTH_MODE_WPA2_FT_PSK: + case AUTH_MODE_NON_RSN_FT: + prAisFsmInfo->ucAvailableAuthTypes = + (uint8_t) AUTH_TYPE_FAST_BSS_TRANSITION; + break; + default: + prAisFsmInfo->ucAvailableAuthTypes = + prAisSpecificBssInfo->ucRoamingAuthTypes; + break; + } + + prStaRec->ucTxAuthAssocRetryLimit = + TX_AUTH_ASSOCI_RETRY_LIMIT_FOR_ROAMING; + } + + /* 4 <4> Use an appropriate Authentication Algorithm + * Number among the ucAvailableAuthTypes + */ + if (prAisFsmInfo->ucAvailableAuthTypes & + (uint8_t) AUTH_TYPE_SHARED_KEY) { + + DBGLOG(AIS, LOUD, + "JOIN INIT: Try to do Authentication with AuthType == SHARED_KEY.\n"); + + prAisFsmInfo->ucAvailableAuthTypes &= + ~(uint8_t) AUTH_TYPE_SHARED_KEY; + + prStaRec->ucAuthAlgNum = + (uint8_t) AUTH_ALGORITHM_NUM_SHARED_KEY; + } else if (prAisFsmInfo->ucAvailableAuthTypes & (uint8_t) + AUTH_TYPE_OPEN_SYSTEM) { + + DBGLOG(AIS, LOUD, + "JOIN INIT: Try to do Authentication with AuthType == OPEN_SYSTEM.\n"); + prAisFsmInfo->ucAvailableAuthTypes &= + ~(uint8_t) AUTH_TYPE_OPEN_SYSTEM; + + prStaRec->ucAuthAlgNum = + (uint8_t) AUTH_ALGORITHM_NUM_OPEN_SYSTEM; + } else if (prAisFsmInfo->ucAvailableAuthTypes & (uint8_t) + AUTH_TYPE_FAST_BSS_TRANSITION) { + + DBGLOG(AIS, LOUD, + "JOIN INIT: Try to do Authentication with AuthType == FAST_BSS_TRANSITION.\n"); + + prAisFsmInfo->ucAvailableAuthTypes &= + ~(uint8_t) AUTH_TYPE_FAST_BSS_TRANSITION; + + prStaRec->ucAuthAlgNum = + (uint8_t) AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION; +#if CFG_SUPPORT_SAE + } else if (prAisFsmInfo->ucAvailableAuthTypes & + (uint8_t) AUTH_TYPE_SAE) { + DBGLOG(AIS, LOUD, + "JOIN INIT: Try to do Authentication with AuthType == SAE.\n"); + + prAisFsmInfo->ucAvailableAuthTypes &= ~(uint8_t) AUTH_TYPE_SAE; + + prStaRec->ucAuthAlgNum = (uint8_t) AUTH_ALGORITHM_NUM_SAE; +#endif + } else { + ASSERT(0); + } + + /* 4 <5> Overwrite Connection Setting for eConnectionPolicy + * == ANY (Used by Assoc Req) + */ + if (prBssDesc->ucSSIDLen) + COPY_SSID(prConnSettings->aucSSID, prConnSettings->ucSSIDLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + /* 4 <6> Send a Msg to trigger SAA to start JOIN process. */ + prJoinReqMsg = + (struct MSG_SAA_FSM_START *)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct + MSG_SAA_FSM_START)); + 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; + struct FRAG_INFO *prFragInfo; + + for (j = 0; j < MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS; j++) { + prFragInfo = &prStaRec->rFragInfo[j]; + + if (prFragInfo->pr1stFrag) { + /* nicRxReturnRFB(prAdapter, + * prFragInfo->pr1stFrag); + */ + prFragInfo->pr1stFrag = (struct SW_RFB *)NULL; + } + } + } +#if CFG_SUPPORT_802_11K + rlmSetMaxTxPwrLimit(prAdapter, + (prBssDesc->cPowerLimit != RLM_INVALID_POWER_LIMIT) + ? prBssDesc->cPowerLimit : RLM_MAX_TX_PWR, 1); +#endif +#if CFG_SUPPORT_CFG80211_AUTH + prConnSettings->fgIsConnInitialized = TRUE; +#endif + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *)prJoinReqMsg, + MSG_SEND_METHOD_BUF); +} /* end of aisFsmInit_JOIN() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Retry JOIN for AUTH_MODE_AUTO_SWITCH + * + * @param[in] prStaRec Pointer to the STA_RECORD_T + * + * @retval TRUE We will retry JOIN + * @retval FALSE We will not retry JOIN + */ +/*----------------------------------------------------------------------------*/ +u_int8_t aisFsmStateInit_RetryJOIN(IN struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct MSG_SAA_FSM_START *prJoinReqMsg; + + DEBUGFUNC("aisFsmStateInit_RetryJOIN()"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + /* Retry other AuthType if possible */ + if (!prAisFsmInfo->ucAvailableAuthTypes) + return FALSE; + + if ((prStaRec->u2StatusCode != + STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED) && + (prStaRec->u2StatusCode != + STATUS_CODE_AUTH_TIMEOUT)) { + prAisFsmInfo->ucAvailableAuthTypes = 0; + return FALSE; + } + + + if (prAisFsmInfo->ucAvailableAuthTypes & (uint8_t) + AUTH_TYPE_OPEN_SYSTEM) { + + DBGLOG(AIS, INFO, + "RETRY JOIN INIT: Retry Authentication with AuthType == OPEN_SYSTEM.\n"); + + prAisFsmInfo->ucAvailableAuthTypes &= + ~(uint8_t) AUTH_TYPE_OPEN_SYSTEM; + + prStaRec->ucAuthAlgNum = + (uint8_t) AUTH_ALGORITHM_NUM_OPEN_SYSTEM; + } else { + DBGLOG(AIS, ERROR, + "RETRY JOIN INIT: Retry Authentication with Unexpected AuthType.\n"); + ASSERT(0); + } + + /* No more available Auth Types */ + prAisFsmInfo->ucAvailableAuthTypes = 0; + + /* Trigger SAA to start JOIN process. */ + prJoinReqMsg = + (struct MSG_SAA_FSM_START *)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct + MSG_SAA_FSM_START)); + 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, (struct MSG_HDR *)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 struct ADAPTER *prAdapter) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_INFO *prAisBssInfo; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prAisBssInfo = prAdapter->prAisBssInfo; + + /* 4 <1> Check if IBSS was created before ? */ + if (prAisBssInfo->fgIsBeaconActivated) { + + /* 4 <2> Start IBSS Alone Timer for periodic SCAN and then SEARCH */ +#if !CFG_SLT_SUPPORT + cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rIbssAloneTimer, + SEC_TO_MSEC(AIS_IBSS_ALONE_TIMEOUT_SEC)); +#endif + } + + aisFsmCreateIBSS(prAdapter); +} /* end of aisFsmStateInit_IBSS_ALONE() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief State Initialization of AIS_STATE_IBSS_MERGE + * + * @param[in] prBssDesc The pointer of BSS_DESC_T which is the IBSS we will + * try to merge with. + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisFsmStateInit_IBSS_MERGE(IN struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_INFO *prAisBssInfo; + struct STA_RECORD *prStaRec = (struct STA_RECORD *)NULL; + + ASSERT(prBssDesc); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prAisBssInfo = prAdapter->prAisBssInfo; + + /* 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, + prAdapter-> + prAisBssInfo->ucBssIndex, + 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); +} /* end of aisFsmStateInit_IBSS_MERGE() */ + +#endif /* CFG_SUPPORT_ADHOC */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Process of JOIN Abort + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisFsmStateAbort_JOIN(IN struct ADAPTER *prAdapter) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct MSG_SAA_FSM_ABORT *prJoinAbortMsg; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + /* 1. Abort JOIN process */ + prJoinAbortMsg = + (struct MSG_SAA_FSM_ABORT *)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct + MSG_SAA_FSM_ABORT)); + if (!prJoinAbortMsg) { + + ASSERT(0); /* Can't abort SAA FSM */ + return; + } + + prJoinAbortMsg->rMsgHdr.eMsgId = MID_AIS_SAA_FSM_ABORT; + prJoinAbortMsg->ucSeqNum = prAisFsmInfo->ucSeqNumOfReqMsg; + prJoinAbortMsg->prStaRec = prAisFsmInfo->prTargetStaRec; + + prAisFsmInfo->prTargetBssDesc->fgIsConnected = FALSE; + prAisFsmInfo->prTargetBssDesc->fgIsConnecting = FALSE; + + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *)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; +} /* end of aisFsmAbortJOIN() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Process of SCAN Abort + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisFsmStateAbort_SCAN(IN struct ADAPTER *prAdapter) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct MSG_SCN_SCAN_CANCEL *prScanCancelMsg; + + if (!prAdapter || prAdapter->prAisBssInfo == NULL) { + DBGLOG(AIS, WARN, "Can't abort SCN FSM\n"); + return; + } + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + DBGLOG(AIS, STATE, "aisFsmStateAbort_SCAN\n"); + + /* Abort JOIN process. */ + prScanCancelMsg = + (struct MSG_SCN_SCAN_CANCEL *)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_SCN_SCAN_CANCEL)); + if (!prScanCancelMsg) { + + ASSERT(0); /* Can't abort SCN FSM */ + return; + } + kalMemZero(prScanCancelMsg, sizeof(struct MSG_SCN_SCAN_CANCEL)); + prScanCancelMsg->rMsgHdr.eMsgId = MID_AIS_SCN_SCAN_CANCEL; + prScanCancelMsg->ucSeqNum = prAisFsmInfo->ucSeqNumOfScanReq; + prScanCancelMsg->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + prScanCancelMsg->fgIsChannelExt = FALSE; + if (prAisFsmInfo->fgIsScanOidAborted) { + prScanCancelMsg->fgIsOidRequest = TRUE; + prAisFsmInfo->fgIsScanOidAborted = FALSE; + } + + /* unbuffered message to guarantee scan is cancelled in sequence */ + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *)prScanCancelMsg, + MSG_SEND_METHOD_UNBUF); +} /* end of aisFsmAbortSCAN() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Process of NORMAL_TR Abort + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisFsmStateAbort_NORMAL_TR(IN struct ADAPTER *prAdapter) +{ + struct AIS_FSM_INFO *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; +} /* end of aisFsmAbortNORMAL_TR() */ + +#if CFG_SUPPORT_ADHOC +/*----------------------------------------------------------------------------*/ +/*! + * @brief Process of NORMAL_TR Abort + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisFsmStateAbort_IBSS(IN struct ADAPTER *prAdapter) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_DESC *prBssDesc; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + /* reset BSS-DESC */ + if (prAisFsmInfo->prTargetStaRec) { + prBssDesc = + scanSearchBssDescByTA(prAdapter, + prAisFsmInfo-> + prTargetStaRec->aucMacAddr); + + if (prBssDesc) { + prBssDesc->fgIsConnected = FALSE; + prBssDesc->fgIsConnecting = FALSE; + } + } + /* release channel privilege */ + aisFsmReleaseCh(prAdapter); +} +#endif /* CFG_SUPPORT_ADHOC */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief The Core FSM engine of AIS(Ad-hoc, Infra STA) + * + * @param[in] eNextState Enum value of next AIS STATE + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisFsmSteps(IN struct ADAPTER *prAdapter, enum ENUM_AIS_STATE eNextState) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prAisBssInfo; + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_DESC *prBssDesc; + struct MSG_CH_REQ *prMsgChReq; + struct MSG_SCN_SCAN_REQ_V2 *prScanReqMsg; + struct PARAM_SCAN_REQUEST_ADV *prScanRequest; + struct AIS_REQ_HDR *prAisReq; + enum ENUM_BAND eBand; + uint8_t ucChannel; + uint16_t u2ScanIELen; + u_int8_t fgIsTransition = (u_int8_t) FALSE; +#if CFG_SUPPORT_DBDC + struct CNM_DBDC_CAP rDbdcCap; +#endif /*CFG_SUPPORT_DBDC */ + uint8_t ucRfBw; + uint8_t ucReasonCode; + struct GLUE_INFO *prGlueInfo; + + DEBUGFUNC("aisFsmSteps()"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = prAdapter->prAisBssInfo; + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prGlueInfo = prAdapter->prGlueInfo; + + do { + + /* Do entering Next State */ + prAisFsmInfo->ePreviousState = prAisFsmInfo->eCurrentState; + + DBGLOG(AIS, STATE, "[AIS]TRANSITION: [%s] -> [%s]\n", + apucDebugAisState[prAisFsmInfo->eCurrentState], + apucDebugAisState[eNextState]); + + /* NOTE(Kevin): This is the only place to change the + * eCurrentState(except initial) + */ + prAisFsmInfo->eCurrentState = eNextState; + + fgIsTransition = (u_int8_t) FALSE; + + aisPostponedEventOfDisconnTimeout(prAdapter, prAisFsmInfo); + + /* 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: +#if CFG_SUPPORT_CFG80211_AUTH + if (prAisFsmInfo->ePreviousState != + prAisFsmInfo->eCurrentState) + prConnSettings->fgIsConnInitialized = FALSE; +#endif + prAisReq = aisFsmGetNextRequest(prAdapter); + cnmTimerStopTimer(prAdapter, + &prAisFsmInfo->rScanDoneTimer); + cnmTimerStopTimer(prAdapter, + &prAisFsmInfo->rWaitOkcPMKTimer); + + if (prAisReq) + DBGLOG(AIS, TRACE, + "eReqType=%d, fgIsConnReqIssued=%d, DisByNonRequest=%d\n", + prAisReq->eReqType, + prConnSettings->fgIsConnReqIssued, + prConnSettings->fgIsDisconnectedByNonRequest); + if (prAisReq == NULL + || prAisReq->eReqType == AIS_REQUEST_RECONNECT) { + if (prConnSettings->fgIsConnReqIssued == TRUE + && + prConnSettings->fgIsDisconnectedByNonRequest + == FALSE) { + + prAisFsmInfo->fgTryScan = TRUE; + + if (!IS_NET_ACTIVE + (prAdapter, + prAdapter-> + prAisBssInfo->ucBssIndex)) { + SET_NET_ACTIVE(prAdapter, + prAdapter->prAisBssInfo-> + ucBssIndex); + /* sync with firmware */ + nicActivateNetwork(prAdapter, + prAdapter->prAisBssInfo-> + ucBssIndex); + } + + SET_NET_PWR_STATE_ACTIVE(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex); +#if CFG_SUPPORT_PNO + prAisBssInfo->fgIsNetRequestInActive = + FALSE; +#endif + /* reset trial count */ + prAisFsmInfo->ucConnTrialCount = 0; + + eNextState = AIS_STATE_SEARCH; + fgIsTransition = TRUE; + } else { + SET_NET_PWR_STATE_IDLE(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex); + + /* sync with firmware */ +#if CFG_SUPPORT_PNO + prAisBssInfo->fgIsNetRequestInActive = + TRUE; + if (prAisBssInfo->fgIsPNOEnable) { + DBGLOG(BSS, INFO, + "[BSSidx][Network]=%d PNOEnable&&OP_MODE_INFRASTRUCTURE,KEEP ACTIVE\n", + prAisBssInfo->ucBssIndex); + } else +#endif + { + UNSET_NET_ACTIVE(prAdapter, + prAdapter->prAisBssInfo-> + ucBssIndex); + nicDeactivateNetwork(prAdapter, + prAdapter->prAisBssInfo-> + ucBssIndex); + } + + /* check for other pending request */ + if (prAisReq && (aisFsmIsRequestPending + (prAdapter, + AIS_REQUEST_SCAN, + TRUE) == TRUE)) { + wlanClearScanningResult + (prAdapter); + eNextState = AIS_STATE_SCAN; + prConnSettings-> + fgIsScanReqIssued = TRUE; + + 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); + + prConnSettings->fgIsScanReqIssued = TRUE; + eNextState = AIS_STATE_SCAN; + fgIsTransition = TRUE; + + /* free the message */ + cnmMemFree(prAdapter, prAisReq); + } else if (prAisReq->eReqType == + AIS_REQUEST_ROAMING_CONNECT + || prAisReq->eReqType == + AIS_REQUEST_ROAMING_SEARCH) { + /* ignore */ + /* free the message */ + cnmMemFree(prAdapter, prAisReq); + } else if (prAisReq->eReqType == + AIS_REQUEST_REMAIN_ON_CHANNEL) { + eNextState = AIS_STATE_REQ_REMAIN_ON_CHANNEL; + fgIsTransition = TRUE; + + /* free the message */ + cnmMemFree(prAdapter, prAisReq); + } + + prAisFsmInfo->u4SleepInterval = + AIS_BG_SCAN_INTERVAL_MIN_SEC; + + + if (prGlueInfo->u4LinkDownPendFlag == TRUE) { + prGlueInfo->u4LinkDownPendFlag = FALSE; + kalOidComplete(prAdapter->prGlueInfo, + TRUE, 0, WLAN_STATUS_SUCCESS); + } + break; + + case AIS_STATE_SEARCH: + /* 4 <1> Search for a matched candidate and save + * it to prTargetBssDesc. + * changing the state, + * ATTENTION: anyone can't leave this case without + * except BTM, otherwise, may cause BtmResponseTimer's + * handler run worngly + */ +#if CFG_SLT_SUPPORT + prBssDesc = + prAdapter->rWifiVar.rSltInfo.prPseudoBssDesc; +#else + /* Support AP Selection */ + if (prAisFsmInfo->ucJoinFailCntAfterScan >= + SCN_BSS_JOIN_FAIL_THRESOLD) { + prBssDesc = NULL; + DBGLOG(AIS, STATE, + "Failed to connect %s more than 4 times after last scan, scan again\n", + prConnSettings->aucSSID); + } else { +#if CFG_SELECT_BSS_BASE_ON_MULTI_PARAM && !CFG_SUPPORT_CFG80211_AUTH + prBssDesc = scanSearchBssDescByScoreForAis + (prAdapter); +#else + prBssDesc = scanSearchBssDescByPolicy + (prAdapter, prAisBssInfo->ucBssIndex); +#endif + } +#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 + DBGLOG(AIS, STATE, + "Roaming retry count :%d fail!\n", + prAisFsmInfo->ucConnTrialCount); + roamingFsmRunEventFail(prAdapter, + ROAMING_FAIL_REASON_CONNLIMIT); +#endif /* CFG_SUPPORT_ROAMING */ + /* reset retry count */ + prAisFsmInfo->ucConnTrialCount = 0; + + /* abort connection trial */ + if (prConnSettings->eReConnectLevel < + RECONNECT_LEVEL_BEACON_TIMEOUT) { + prConnSettings->eReConnectLevel = + RECONNECT_LEVEL_ROAMING_FAIL; + prConnSettings->fgIsConnReqIssued = + FALSE; + } else { + DBGLOG(AIS, INFO, + "Do not set fgIsConnReqIssued, level is %d\n", + prConnSettings-> + eReConnectLevel); + } + + eNextState = AIS_STATE_NORMAL_TR; + fgIsTransition = TRUE; + + break; + } + } + /* 4 <2> We are not under Roaming Condition. */ + if (prAisBssInfo->eConnectionState == + PARAM_MEDIA_STATE_DISCONNECTED) { + + /* 4 <2.a> If we have the matched one */ + if (prBssDesc) { + /* 4 Stored the Selected BSS + * security cipher. + */ + /* or later asoc req compose IE */ + prAisBssInfo->u4RsnSelectedGroupCipher = + prBssDesc->u4RsnSelectedGroupCipher; + prAisBssInfo-> + u4RsnSelectedPairwiseCipher = + prBssDesc->u4RsnSelectedPairwiseCipher; + prAisBssInfo->u4RsnSelectedAKMSuite = + prBssDesc->u4RsnSelectedAKMSuite; + prAisBssInfo->eBand = prBssDesc->eBand; + if (prAisBssInfo->fgIsWmmInited + == FALSE) + prAisBssInfo->ucWmmQueSet = + cnmWmmIndexDecision(prAdapter, + prAisBssInfo); +#if CFG_SUPPORT_DBDC + cnmDbdcEnableDecision(prAdapter, + prAisBssInfo->ucBssIndex, + prBssDesc->eBand, + prBssDesc->ucChannelNum, + prAisBssInfo->ucWmmQueSet); + cnmGetDbdcCapability(prAdapter, + prAisBssInfo->ucBssIndex, + prBssDesc->eBand, + prBssDesc->ucChannelNum, + wlanGetSupportNss(prAdapter, + prAisBssInfo->ucBssIndex), + &rDbdcCap); + + prAisBssInfo->ucNss = rDbdcCap.ucNss; +#endif /*CFG_SUPPORT_DBDC*/ + /* 4 Do STATE transition and update + * current Operation Mode. + */ + if (prBssDesc->eBSSType == + BSS_TYPE_INFRASTRUCTURE) { + + prAisBssInfo->eCurrentOPMode = + OP_MODE_INFRASTRUCTURE; + + /* Record the target BSS_DESC_T + * for next STATE. + */ + prAisFsmInfo->prTargetBssDesc = + prBssDesc; + + /* Transit to channel acquire */ + eNextState = + AIS_STATE_REQ_CHANNEL_JOIN; + fgIsTransition = TRUE; + + /* increase connection trial + * count + */ + prAisFsmInfo-> + ucConnTrialCount++; + } +#if CFG_SUPPORT_ADHOC + else if (prBssDesc->eBSSType == + BSS_TYPE_IBSS) { + + prAisBssInfo->eCurrentOPMode = + OP_MODE_IBSS; + + /* Record the target BSS_DESC_T + * for next STATE. + */ + prAisFsmInfo->prTargetBssDesc = + prBssDesc; + + eNextState = + AIS_STATE_IBSS_MERGE; + fgIsTransition = TRUE; + } +#endif /* CFG_SUPPORT_ADHOC */ + else { + ASSERT(0); + eNextState = + AIS_STATE_WAIT_FOR_NEXT_SCAN; + fgIsTransition = TRUE; + } + } + /* 4 <2.b> If we don't have the matched one */ + else { + if (prAisFsmInfo->rJoinReqTime != 0 && + CHECK_FOR_TIMEOUT(kalGetTimeTick(), + prAisFsmInfo->rJoinReqTime, + SEC_TO_SYSTIME + (AIS_JOIN_TIMEOUT))) { + eNextState = + AIS_STATE_JOIN_FAILURE; + fgIsTransition = TRUE; + break; + } + /* increase connection trial count + * for infrastructure connection + */ + if (prConnSettings->eOPMode == + NET_TYPE_INFRA) + prAisFsmInfo-> + ucConnTrialCount++; + + /* 4 Try to SCAN */ + if (prAisFsmInfo->fgTryScan) { + eNextState = + AIS_STATE_LOOKING_FOR; + + fgIsTransition = TRUE; + } + /* 4 We've do SCAN already, now wait + * in some STATE. + */ + else { + eNextState = + aisFsmStateSearchAction + (prAdapter, + AIS_FSM_STATE_SEARCH_ACTION_PHASE_0); + fgIsTransition = TRUE; + } + } + } + /* 4 <3> We are under Roaming Condition. */ + /* prAdapter->eConnectionState == + * MEDIA_STATE_CONNECTED. + */ + else { + + /* 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 (prAisBssInfo->ucReasonOfDisconnect != + DISCONNECT_REASON_CODE_REASSOCIATION && + ((!prBssDesc) || /* CASE I */ + (prBssDesc->eBSSType != + BSS_TYPE_INFRASTRUCTURE) || + /* CASE II */ + (prBssDesc->fgIsConnected) || + /* CASE III */ + (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, + prAisBssInfo->aucBSSID))) /* CASE VI */) { + if (prBssDesc) { + DBGLOG(ROAMING, INFO, + "fgIsConnected=%d, prBssDesc->BSSID " + MACSTR + ", prAisBssInfo->BSSID " + MACSTR "\n", + prBssDesc->fgIsConnected, + MAC2STR + (prBssDesc->aucBSSID), + MAC2STR + (prAisBssInfo-> + aucBSSID)); + } +#if DBG + if ((prBssDesc) + && (prBssDesc->fgIsConnected)) + ASSERT(EQUAL_MAC_ADDR + (prBssDesc->aucBSSID, + prAisBssInfo->aucBSSID)); +#endif /* DBG */ + if (prAisFsmInfo-> + fgTargetChnlScanIssued) { + /* if target channel scan has + * issued, and no roaming + * target is found, need + * to do full scan again + */ + DBGLOG(AIS, INFO, + "[Roaming] No target found, try to full scan again\n"); + prAisFsmInfo-> + fgTargetChnlScanIssued = + FALSE; + eNextState = + AIS_STATE_LOOKING_FOR; + fgIsTransition = TRUE; + break; + } + + /* We already associated with it + * , go back to NORMAL_TR + */ + /* TODO(Kevin): Roaming Fail */ +#if CFG_SUPPORT_ROAMING + roamingFsmRunEventFail(prAdapter, + ROAMING_FAIL_REASON_NOCANDIDATE); +#endif /* CFG_SUPPORT_ROAMING */ + /* Retreat to NORMAL_TR state */ + eNextState = AIS_STATE_NORMAL_TR; + fgIsTransition = TRUE; + break; + } + /* 4 <3.b> Try to roam out for JOIN this + * BSS_DESC_T. + */ + else { + if (!prBssDesc) { + fgIsTransition = TRUE; + eNextState = + aisFsmStateSearchAction + (prAdapter, + AIS_FSM_STATE_SEARCH_ACTION_PHASE_1); + break; + } + aisFsmStateSearchAction(prAdapter, + AIS_FSM_STATE_SEARCH_ACTION_PHASE_2); + /* 4 Record the target BSS_DESC_T + ** for next STATE. + */ + prAisFsmInfo->prTargetBssDesc = + prBssDesc; + + /* tyhsu: increase connection trial + ** count + */ + prAisFsmInfo->ucConnTrialCount++; + + /* Transit to channel acquire */ + eNextState = AIS_STATE_REQ_CHANNEL_JOIN; + /* Find target AP to roaming + * and set + * fgTargetChnlScanIssued + * to false + */ + prAisFsmInfo->fgTargetChnlScanIssued = + FALSE; + fgIsTransition = TRUE; + } + } + if (prBssDesc && prConnSettings->fgOkcEnabled) { + uint8_t + aucBuf[sizeof + (struct PARAM_PMKID_CANDIDATE_LIST) + + sizeof(struct + PARAM_STATUS_INDICATION)]; + struct PARAM_STATUS_INDICATION *prStatusEvent = + (struct PARAM_STATUS_INDICATION *)aucBuf; + struct PARAM_PMKID_CANDIDATE_LIST + *prPmkidCandicate = + (struct PARAM_PMKID_CANDIDATE_LIST + *)(prStatusEvent + 1); + uint32_t u4Entry = 0; + + if (rsnSearchPmkidEntry + (prAdapter, prBssDesc->aucBSSID, &u4Entry) + && prAdapter->rWifiVar. + rAisSpecificBssInfo.arPmkidCache[u4Entry]. + fgPmkidExist) + break; + DBGLOG(AIS, INFO, "No PMK for " MACSTR + ", try to generate a OKC PMK\n", + MAC2STR(prBssDesc->aucBSSID)); + prStatusEvent->eStatusType = + ENUM_STATUS_TYPE_CANDIDATE_LIST; + prPmkidCandicate->u4Version = 1; + prPmkidCandicate->u4NumCandidates = 1; + /* don't request preauth */ + prPmkidCandicate-> + arCandidateList[0].u4Flags = 0; + COPY_MAC_ADDR(prPmkidCandicate->arCandidateList + [0].arBSSID, prBssDesc->aucBSSID); + kalIndicateStatusAndComplete + (prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (void *)aucBuf, sizeof(aucBuf)); + cnmTimerStartTimer(prAdapter, + &prAisFsmInfo->rWaitOkcPMKTimer, + AIS_WAIT_OKC_PMKID_SEC); + } + + break; + + case AIS_STATE_WAIT_FOR_NEXT_SCAN: + + DBGLOG(AIS, LOUD, + "SCAN: Idle Begin - Current Time = %u\n", + kalGetTimeTick()); + + cnmTimerStartTimer(prAdapter, + &prAisFsmInfo->rBGScanTimer, + SEC_TO_MSEC + (prAisFsmInfo->u4SleepInterval)); + + SET_NET_PWR_STATE_IDLE(prAdapter, + prAdapter-> + prAisBssInfo->ucBssIndex); + + 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, prAdapter->prAisBssInfo->ucBssIndex)) { + SET_NET_ACTIVE(prAdapter, + prAdapter-> + prAisBssInfo->ucBssIndex); + + /* sync with firmware */ + nicActivateNetwork(prAdapter, + prAdapter-> + prAisBssInfo->ucBssIndex); +#if CFG_SUPPORT_PNO + prAisBssInfo->fgIsNetRequestInActive = FALSE; +#endif + } + prScanRequest = &(prAisFsmInfo->rScanRequest); + + /* IE length decision */ + if (prScanRequest->u4IELength > 0) { + u2ScanIELen = + (uint16_t) prScanRequest->u4IELength; + } else { +#if CFG_SUPPORT_WPS2 + u2ScanIELen = prAdapter->prGlueInfo->u2WSCIELen; +#else + u2ScanIELen = 0; +#endif + } + + prScanReqMsg = + (struct MSG_SCN_SCAN_REQ_V2 *)cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + OFFSET_OF + (struct + MSG_SCN_SCAN_REQ_V2, + aucIE) + + u2ScanIELen); + if (!prScanReqMsg) { + ASSERT(0); /* Can't trigger SCAN FSM */ + return; + } + kalMemZero(prScanReqMsg, OFFSET_OF + (struct MSG_SCN_SCAN_REQ_V2, + aucIE)+u2ScanIELen); + prScanReqMsg->rMsgHdr.eMsgId = MID_AIS_SCN_SCAN_REQ_V2; + prScanReqMsg->ucSeqNum = + ++prAisFsmInfo->ucSeqNumOfScanReq; + if (prAisFsmInfo->u2SeqNumOfScanReport == + AIS_SCN_REPORT_SEQ_NOT_SET) { + prAisFsmInfo->u2SeqNumOfScanReport = + (uint16_t) prScanReqMsg->ucSeqNum; + } + prScanReqMsg->ucBssIndex = + prAdapter->prAisBssInfo->ucBssIndex; +#if CFG_SUPPORT_802_11K + if (rlmFillScanMsg(prAdapter, prScanReqMsg)) { + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *)prScanReqMsg, + MSG_SEND_METHOD_BUF); + break; + } + COPY_MAC_ADDR(prScanReqMsg->aucBSSID, + "\xff\xff\xff\xff\xff\xff"); +#endif + +#if CFG_SUPPORT_RDD_TEST_MODE + prScanReqMsg->eScanType = SCAN_TYPE_PASSIVE_SCAN; +#else + if (prAisFsmInfo->eCurrentState == AIS_STATE_SCAN + || prAisFsmInfo->eCurrentState == + AIS_STATE_ONLINE_SCAN) { + uint8_t ucScanSSIDNum; + enum ENUM_SCAN_TYPE eScanType; + + ucScanSSIDNum = prScanRequest->u4SsidNum; + eScanType = prScanRequest->ucScanType; + + if (eScanType == SCAN_TYPE_ACTIVE_SCAN + && ucScanSSIDNum == 0) { + prScanReqMsg->eScanType = eScanType; + + prScanReqMsg->ucSSIDType + = SCAN_REQ_SSID_WILDCARD; + prScanReqMsg->ucSSIDNum = 0; + } else if (eScanType == SCAN_TYPE_PASSIVE_SCAN + && ucScanSSIDNum == 0) { + prScanReqMsg->eScanType = eScanType; + + prScanReqMsg->ucSSIDType = 0; + prScanReqMsg->ucSSIDNum = 0; + } else { + prScanReqMsg->eScanType = + SCAN_TYPE_ACTIVE_SCAN; + + prScanReqMsg->ucSSIDType = + SCAN_REQ_SSID_SPECIFIED; + prScanReqMsg->ucSSIDNum = ucScanSSIDNum; + prScanReqMsg->prSsid = + prScanRequest->rSsid; + } + kalMemCopy(prScanReqMsg->aucRandomMac, + prScanRequest->aucRandomMac, + MAC_ADDR_LEN); + prScanReqMsg->ucScnFuncMask |= + prScanRequest->ucScnFuncMask; + + } else { + prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; + + COPY_SSID(prAisFsmInfo->rRoamingSSID.aucSsid, + prAisFsmInfo->rRoamingSSID.u4SsidLen, + prConnSettings->aucSSID, + prConnSettings->ucSSIDLen); + + /* Scan for determined SSID */ + prScanReqMsg->ucSSIDType = + SCAN_REQ_SSID_SPECIFIED; + prScanReqMsg->ucSSIDNum = 1; + prScanReqMsg->prSsid = + &(prAisFsmInfo->rRoamingSSID); +#if CFG_SUPPORT_SCAN_RANDOM_MAC + prScanReqMsg->ucScnFuncMask |= + ENUM_SCN_RANDOM_MAC_EN; +#endif + } +#endif + + /* using default channel dwell time/timeout value */ + prScanReqMsg->u2ProbeDelay = 0; + prScanReqMsg->u2ChannelDwellTime = 0; + prScanReqMsg->u2ChannelMinDwellTime = 0; + prScanReqMsg->u2TimeoutValue = 0; + /* 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 (prAisBssInfo->eConnectionState == + PARAM_MEDIA_STATE_CONNECTED + && (prAdapter->rWifiVar. + rRoamingInfo.eCurrentState == + ROAMING_STATE_DISCOVERY) + && prAisFsmInfo->fgTargetChnlScanIssued) { + struct RF_CHANNEL_INFO *prChnlInfo = + &prScanReqMsg->arChnlInfoList[0]; + uint8_t ucChannelNum = 0; + uint8_t i = 0; +#if CFG_SUPPORT_802_11K + struct LINK *prNeighborAPLink = + &prAdapter->rWifiVar. + rAisSpecificBssInfo.rNeighborApList. + rUsingLink; +#endif + for (i = 0; + i < + prAdapter->rWifiVar.rAisSpecificBssInfo. + ucCurEssChnlInfoNum; i++) { + ucChannelNum = + prAdapter->rWifiVar. + rAisSpecificBssInfo. + arCurEssChnlInfo[i].ucChannel; + if ((ucChannelNum >= 1) + && (ucChannelNum <= 14)) + prChnlInfo[i].eBand = BAND_2G4; + else + prChnlInfo[i].eBand = BAND_5G; + prChnlInfo[i].ucChannelNum + = ucChannelNum; + } + prScanReqMsg->ucChannelListNum + = + prAdapter->rWifiVar.rAisSpecificBssInfo. + ucCurEssChnlInfoNum; + prScanReqMsg->eScanChannel = + SCAN_CHANNEL_SPECIFIED; + DBGLOG(AIS, INFO, + "[Roaming] Target Scan: Total number of scan channel(s)=%d\n", + prScanReqMsg->ucChannelListNum); + +#if CFG_SUPPORT_802_11K + /* Add channels provided by Neighbor Report to + ** channel list for roaming scanning. + */ + if (!LINK_IS_EMPTY(prNeighborAPLink)) { + struct NEIGHBOR_AP_T *prNeiAP = NULL; + struct RF_CHANNEL_INFO *prChnlInfo = + &prScanReqMsg->arChnlInfoList[0]; + uint8_t ucChnlNum = + prScanReqMsg->ucChannelListNum; + uint8_t i = 0; + + LINK_FOR_EACH_ENTRY(prNeiAP, + prNeighborAPLink, + rLinkEntry, struct + NEIGHBOR_AP_T) { + ucChannel = prNeiAP->ucChannel; + eBand = ucChannel <= 14 + ? BAND_2G4 : BAND_5G; + if (!rlmDomainIsLegalChannel + (prAdapter, eBand, + ucChannel)) + continue; + + /* Append channel(s) provided by + * neighbor report into channel + * list of current ESS in scan msg. + */ + for (i = 0; i < ucChnlNum; i++) { + if (ucChannel == + prChnlInfo + [i].ucChannelNum) + break; + } + + if (i != ucChnlNum) + continue; + prChnlInfo[ucChnlNum].eBand = + eBand; + prChnlInfo[ucChnlNum] + .ucChannelNum = ucChannel; + ucChnlNum++; + if (ucChnlNum == + MAXIMUM_OPERATION_CHANNEL_LIST) + break; + } + DBGLOG(AIS, INFO, + "[Roaming] Target Scan: Total number of scan channel(s)=%d and %d channel(s) provided by neighbor report\n", + ucChnlNum, ucChnlNum - + prScanReqMsg->ucChannelListNum); + prScanReqMsg->ucChannelListNum = + ucChnlNum; + } +#endif +#if CFG_SUPPORT_NCHO + } else if (prAdapter->rNchoInfo.fgECHOEnabled && + prAdapter->rNchoInfo.u4RoamScanControl == + TRUE + && prAisBssInfo->eConnectionState == + PARAM_MEDIA_STATE_CONNECTED + && prAdapter->rWifiVar. + rRoamingInfo.eCurrentState == + ROAMING_STATE_DISCOVERY) { + /* handle NCHO scan channel info */ + uint32_t u4size = 0; + struct _CFG_NCHO_SCAN_CHNL_T *prRoamScnChnl = + NULL; + + prRoamScnChnl = + &prAdapter->rNchoInfo.rRoamScnChnl; + /* set partial scan */ + prScanReqMsg->ucChannelListNum = + prRoamScnChnl->ucChannelListNum; + u4size = sizeof(prRoamScnChnl->arChnlInfoList); + + DBGLOG(AIS, TRACE, + "NCHO SCAN channel num = %d, total size=%d\n", + prScanReqMsg->ucChannelListNum, u4size); + + kalMemCopy(&(prScanReqMsg->arChnlInfoList), + &(prRoamScnChnl->arChnlInfoList), + u4size); + + /* set scan channel type for NCHO scan */ + prScanReqMsg->eScanChannel = + SCAN_CHANNEL_SPECIFIED; +#endif + } else + if (prAdapter->aePreferBand + [prAdapter->prAisBssInfo->ucBssIndex] == + BAND_NULL) { + if (prAdapter->fgEnable5GBand == TRUE) + prScanReqMsg->eScanChannel = + SCAN_CHANNEL_FULL; + else + prScanReqMsg->eScanChannel = + SCAN_CHANNEL_2G4; + + } else + if (prAdapter->aePreferBand + [prAdapter->prAisBssInfo->ucBssIndex] == + BAND_2G4) { + prScanReqMsg->eScanChannel = SCAN_CHANNEL_2G4; + } else + if (prAdapter->aePreferBand + [prAdapter->prAisBssInfo->ucBssIndex] == + BAND_5G) { + prScanReqMsg->eScanChannel = SCAN_CHANNEL_5G; + } else { + prScanReqMsg->eScanChannel = SCAN_CHANNEL_FULL; + ASSERT(0); + } + + switch (prScanReqMsg->eScanChannel) { + case SCAN_CHANNEL_FULL: + case SCAN_CHANNEL_2G4: + case SCAN_CHANNEL_5G: + scanSetRequestChannel(prAdapter, + prScanRequest->u4ChannelNum, + prScanRequest->arChannel, + (prAisFsmInfo->eCurrentState == + AIS_STATE_ONLINE_SCAN), + prScanReqMsg); + break; + default: + break; + } + if (u2ScanIELen > 0) { + kalMemCopy(prScanReqMsg->aucIE, + prScanRequest->pucIE, u2ScanIELen); + } 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, + (struct MSG_HDR *)prScanReqMsg, + MSG_SEND_METHOD_BUF); + + kalMemZero(prAisFsmInfo->aucScanIEBuf, + sizeof(prAisFsmInfo->aucScanIEBuf)); + prScanRequest->u4SsidNum = 0; + prScanRequest->ucScanType = 0; + prScanRequest->u4IELength = 0; + prScanRequest->u4ChannelNum = 0; + prScanRequest->ucScnFuncMask = 0; + kalMemZero(prScanRequest->aucRandomMac, MAC_ADDR_LEN); + /* Will enable background sleep for infrastructure */ + prAisFsmInfo->fgTryScan = FALSE; + prAisFsmInfo->fgIsScanning = TRUE; + + /* Support AP Selection */ + prAisFsmInfo->ucJoinFailCntAfterScan = 0; + break; + + case AIS_STATE_REQ_CHANNEL_JOIN: + /* stop Tx due to we need to connect a new AP. even the + ** new AP is operating on the same channel with current + ** , we still need to stop Tx, because firmware should + ** ensure all mgmt and dhcp packets are Tx in time, + ** and may cause normal data packets was queued and + ** eventually flushed in firmware + */ + if (prAisBssInfo->prStaRecOfAP && + prAisBssInfo->ucReasonOfDisconnect != + DISCONNECT_REASON_CODE_REASSOCIATION) + prAdapter->prAisBssInfo-> + prStaRecOfAP->fgIsTxAllowed = FALSE; + + /* send message to CNM for acquiring channel */ + prMsgChReq = + (struct MSG_CH_REQ *)cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_CH_REQ)); + if (!prMsgChReq) { + /* Can't indicate CNM for channel acquiring */ + ASSERT(0); + return; + } + + prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; + prMsgChReq->ucBssIndex = + prAdapter->prAisBssInfo->ucBssIndex; + prMsgChReq->ucTokenID = ++prAisFsmInfo->ucSeqNumOfChReq; + prMsgChReq->eReqType = CH_REQ_TYPE_JOIN; +#ifdef CFG_SUPPORT_ADJUST_JOIN_CH_REQ_INTERVAL + prMsgChReq->u4MaxInterval = + prAdapter->rWifiVar.u4AisJoinChReqIntervel; +#else + prMsgChReq->u4MaxInterval = + AIS_JOIN_CH_REQUEST_INTERVAL; +#endif + DBGLOG(AIS, INFO, "Request join interval: %u\n", + prMsgChReq->u4MaxInterval); + + prMsgChReq->ucPrimaryChannel = + prAisFsmInfo->prTargetBssDesc->ucChannelNum; + prMsgChReq->eRfSco = + prAisFsmInfo->prTargetBssDesc->eSco; + prMsgChReq->eRfBand = + prAisFsmInfo->prTargetBssDesc->eBand; +#if CFG_SUPPORT_DBDC + prMsgChReq->eDBDCBand = ENUM_BAND_AUTO; +#endif /*CFG_SUPPORT_DBDC */ + /* To do: check if 80/160MHz bandwidth is needed here */ + /* Decide RF BW by own OP and Peer OP BW */ + ucRfBw = + cnmGetDbdcBwCapability(prAdapter, + prAisBssInfo->ucBssIndex); + /* Revise to VHT OP BW */ + ucRfBw = rlmGetVhtOpBwByBssOpBw(ucRfBw); + if (ucRfBw > + prAisFsmInfo->prTargetBssDesc->eChannelWidth) + ucRfBw = + prAisFsmInfo-> + prTargetBssDesc->eChannelWidth; + + prMsgChReq->eRfChannelWidth = ucRfBw; + /* TODO: BW80+80 support */ + prMsgChReq->ucRfCenterFreqSeg1 = + nicGetVhtS1(prMsgChReq->ucPrimaryChannel, + prMsgChReq->eRfChannelWidth); + DBGLOG(RLM, INFO, + "AIS req CH for CH:%d, Bw:%d, s1=%d\n", + prAisBssInfo->ucPrimaryChannel, + prMsgChReq->eRfChannelWidth, + prMsgChReq->ucRfCenterFreqSeg1); + prMsgChReq->ucRfCenterFreqSeg2 = 0; + + rlmReviseMaxBw(prAdapter, prAisBssInfo->ucBssIndex, + &prMsgChReq->eRfSco, + (enum ENUM_CHANNEL_WIDTH *) + &prMsgChReq->eRfChannelWidth, + &prMsgChReq->ucRfCenterFreqSeg1, + &prMsgChReq->ucPrimaryChannel); + + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *)prMsgChReq, + MSG_SEND_METHOD_BUF); + + prAisFsmInfo->fgIsChannelRequested = TRUE; + break; + + case AIS_STATE_JOIN: + aisFsmStateInit_JOIN(prAdapter, + prAisFsmInfo->prTargetBssDesc); + break; + + case AIS_STATE_JOIN_FAILURE: + prAdapter->rWifiVar.rConnSettings.eReConnectLevel = + RECONNECT_LEVEL_MIN; + prConnSettings->fgIsDisconnectedByNonRequest = TRUE; + + nicMediaJoinFailure(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, + WLAN_STATUS_JOIN_FAILURE); + + eNextState = AIS_STATE_IDLE; + fgIsTransition = TRUE; + + 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 + */ + break; + } + + /* 1. Process for pending roaming scan */ + if (aisFsmIsRequestPending(prAdapter, + AIS_REQUEST_ROAMING_SEARCH, TRUE) == TRUE) { + eNextState = AIS_STATE_LOOKING_FOR; + fgIsTransition = TRUE; + } + /* 2. Process for pending roaming connect */ + else if (aisFsmIsRequestPending(prAdapter, + AIS_REQUEST_ROAMING_CONNECT, TRUE) + == TRUE) { + eNextState = AIS_STATE_SEARCH; + fgIsTransition = TRUE; + } + /* 3. Process for pending scan */ + else if (aisFsmIsRequestPending(prAdapter, + AIS_REQUEST_SCAN, TRUE) == TRUE) { + wlanClearScanningResult(prAdapter); + eNextState = AIS_STATE_ONLINE_SCAN; + fgIsTransition = TRUE; + } else if (aisFsmIsRequestPending(prAdapter, + AIS_REQUEST_REMAIN_ON_CHANNEL, TRUE) + == TRUE) { + eNextState = AIS_STATE_REQ_REMAIN_ON_CHANNEL; + fgIsTransition = TRUE; + } + + break; + + case AIS_STATE_DISCONNECTING: + /* send for deauth frame for disconnection */ + ucReasonCode = REASON_CODE_DEAUTH_LEAVING_BSS; +#if CFG_DISCONN_DEBUG_FEATURE + g_rDisconnInfoTemp.ucDisassocReason = ucReasonCode; +#endif + authSendDeauthFrame(prAdapter, + prAisBssInfo, + prAisBssInfo->prStaRecOfAP, + (struct SW_RFB *)NULL, + ucReasonCode, + aisDeauthXmitComplete); + /* If it is scanning or BSS absent, HW may go away from + * serving channel, which may cause driver be not able + * to TX mgmt frame. So we need to start a longer timer + * to wait HW return to serving channel. + * We set the time out value to 1 second because + * it is long enough to return to serving channel + * in most cases, and disconnection delay is seamless + * to end-user even time out. + */ + cnmTimerStartTimer(prAdapter, + &prAisFsmInfo->rDeauthDoneTimer, + (prAisFsmInfo->fgIsScanning + || prAisBssInfo->fgIsNetAbsent) ? + 1000 : 100); + break; + + case AIS_STATE_REQ_REMAIN_ON_CHANNEL: + /* send message to CNM for acquiring channel */ + prMsgChReq = + (struct MSG_CH_REQ *)cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_CH_REQ)); + if (!prMsgChReq) { + /* Can't indicate CNM for channel acquiring */ + ASSERT(0); + return; + } + + /* release channel */ + aisFsmReleaseCh(prAdapter); + + /* zero-ize */ + kalMemZero(prMsgChReq, sizeof(struct MSG_CH_REQ)); + + /* filling */ + prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; + prMsgChReq->ucBssIndex = + prAdapter->prAisBssInfo->ucBssIndex; + prMsgChReq->ucTokenID = ++prAisFsmInfo->ucSeqNumOfChReq; + prMsgChReq->eReqType = CH_REQ_TYPE_JOIN; + prMsgChReq->u4MaxInterval = + prAisFsmInfo->rChReqInfo.u4DurationMs; + prMsgChReq->ucPrimaryChannel = + prAisFsmInfo->rChReqInfo.ucChannelNum; + prMsgChReq->eRfSco = prAisFsmInfo->rChReqInfo.eSco; + prMsgChReq->eRfBand = prAisFsmInfo->rChReqInfo.eBand; +#if CFG_SUPPORT_DBDC + prMsgChReq->eDBDCBand = ENUM_BAND_AUTO; +#endif + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *)prMsgChReq, + MSG_SEND_METHOD_BUF); + + prAisFsmInfo->fgIsChannelRequested = TRUE; + + break; + + case AIS_STATE_REMAIN_ON_CHANNEL: + if (!IS_NET_ACTIVE(prAdapter, + prAdapter-> + prAisBssInfo->ucBssIndex)) { + SET_NET_ACTIVE(prAdapter, + prAdapter-> + prAisBssInfo->ucBssIndex); + + /* sync with firmware */ + nicActivateNetwork(prAdapter, + prAdapter-> + prAisBssInfo->ucBssIndex); + } +#if CFG_SUPPORT_PNO + prAisBssInfo->fgIsNetRequestInActive = FALSE; +#endif + break; + + default: + /* Make sure we have handle all STATEs */ + ASSERT(0); + break; + + } + } while (fgIsTransition); + + return; + +} /* end of aisFsmSteps() */ + +enum ENUM_AIS_STATE aisFsmStateSearchAction(IN struct ADAPTER *prAdapter, + uint8_t ucPhase) +{ + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_INFO *prAisBssInfo; + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_DESC *prBssDesc; + enum ENUM_AIS_STATE eState = AIS_STATE_IDLE; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = prAdapter->prAisBssInfo; + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + +#if CFG_SLT_SUPPORT + prBssDesc = prAdapter->rWifiVar.rSltInfo.prPseudoBssDesc; +#else + prBssDesc = + scanSearchBssDescByPolicy(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex); +#endif + + if (ucPhase == AIS_FSM_STATE_SEARCH_ACTION_PHASE_0) { + if (prConnSettings->eOPMode == NET_TYPE_INFRA) { + + /* issue reconnect request, */ + /*and retreat to idle state for scheduling */ + aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); + eState = AIS_STATE_IDLE; + } +#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; + eState = AIS_STATE_IBSS_ALONE; + } +#endif /* CFG_SUPPORT_ADHOC */ + else { + ASSERT(0); + eState = AIS_STATE_WAIT_FOR_NEXT_SCAN; + } + } else if (ucPhase == AIS_FSM_STATE_SEARCH_ACTION_PHASE_1) { + /* increase connection trial count for infrastructure + * connection + */ + if (prConnSettings->eOPMode == NET_TYPE_INFRA) + prAisFsmInfo->ucConnTrialCount++; + /* 4 Try to SCAN */ + if (prAisFsmInfo->fgTryScan) + eState = AIS_STATE_LOOKING_FOR; + + /* 4 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); + + eState = AIS_STATE_IDLE; + } +#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; + + eState = AIS_STATE_IBSS_ALONE; + } +#endif /* CFG_SUPPORT_ADHOC */ + else { + ASSERT(0); + eState = AIS_STATE_WAIT_FOR_NEXT_SCAN; + } + } + } else { +#if DBG + if (prAisBssInfo->ucReasonOfDisconnect != + DISCONNECT_REASON_CODE_REASSOCIATION) + ASSERT(UNEQUAL_MAC_ADDR + (prBssDesc->aucBSSID, prAisBssInfo->aucBSSID)); +#endif /* DBG */ + } + return eState; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void aisFsmRunEventScanDone(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_SCN_SCAN_DONE *prScanDoneMsg; + struct AIS_FSM_INFO *prAisFsmInfo; + enum ENUM_AIS_STATE eNextState; + uint8_t ucSeqNumOfCompMsg; + struct CONNECTION_SETTINGS *prConnSettings; + enum ENUM_SCAN_STATUS eStatus = SCAN_STATUS_DONE; + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq = + &prAdapter->rWifiVar.rRmReqParams; + struct BCN_RM_PARAMS *prBcnRmParam = &prRmReq->rBcnRmParam; + + DEBUGFUNC("aisFsmRunEventScanDone()"); + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + DBGLOG(AIS, LOUD, "EVENT-SCAN DONE: Current Time = %u\n", + kalGetTimeTick()); + + if (prAdapter->prAisBssInfo == NULL) { + /* This case occurs when the AIS isn't done, but the wlan0 */ + /* has changed to AP mode. And the prAisBssInfo is freed. */ + DBGLOG(AIS, WARN, "prAisBssInfo is NULL, and then return\n"); + return; + } + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + prScanDoneMsg = (struct MSG_SCN_SCAN_DONE *)prMsgHdr; + ASSERT(prScanDoneMsg->ucBssIndex == + prAdapter->prAisBssInfo->ucBssIndex); + + ucSeqNumOfCompMsg = prScanDoneMsg->ucSeqNum; + eStatus = prScanDoneMsg->eScanStatus; + cnmMemFree(prAdapter, prMsgHdr); + + DBGLOG(AIS, INFO, "ScanDone %u, status(%d) native req(%u)\n", + ucSeqNumOfCompMsg, eStatus, prAisFsmInfo->u2SeqNumOfScanReport); + + eNextState = prAisFsmInfo->eCurrentState; + + if ((uint16_t) ucSeqNumOfCompMsg == + prAisFsmInfo->u2SeqNumOfScanReport) { + prAisFsmInfo->u2SeqNumOfScanReport = AIS_SCN_REPORT_SEQ_NOT_SET; + prConnSettings->fgIsScanReqIssued = FALSE; + kalScanDone(prAdapter->prGlueInfo, KAL_NETWORK_TYPE_AIS_INDEX, + (eStatus == SCAN_STATUS_DONE) ? + WLAN_STATUS_SUCCESS : WLAN_STATUS_FAILURE); + } + if (ucSeqNumOfCompMsg != prAisFsmInfo->ucSeqNumOfScanReq) { + DBGLOG(AIS, WARN, + "SEQ NO of AIS SCN DONE MSG is not matched %u %u\n", + ucSeqNumOfCompMsg, prAisFsmInfo->ucSeqNumOfScanReq); + } else { + prAisFsmInfo->fgIsScanning = FALSE; + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_SCAN: + eNextState = AIS_STATE_IDLE; +#if CFG_SUPPORT_AGPS_ASSIST + scanReportScanResultToAgps(prAdapter); +#endif + break; + + case AIS_STATE_ONLINE_SCAN: +#if CFG_SUPPORT_ROAMING + eNextState = aisFsmRoamingScanResultsUpdate(prAdapter); +#else + eNextState = AIS_STATE_NORMAL_TR; +#endif /* CFG_SUPPORT_ROAMING */ +#if CFG_SUPPORT_AGPS_ASSIST + scanReportScanResultToAgps(prAdapter); +#endif +/* Support AP Selection */ +#if CFG_SELECT_BSS_BASE_ON_MULTI_PARAM + scanGetCurrentEssChnlList(prAdapter); +#endif +/* end Support AP Selection */ + break; + + case AIS_STATE_LOOKING_FOR: +#if CFG_SUPPORT_ROAMING + eNextState = aisFsmRoamingScanResultsUpdate(prAdapter); +#else + eNextState = AIS_STATE_SEARCH; +#endif /* CFG_SUPPORT_ROAMING */ +/* Support AP Selection */ +#if CFG_SELECT_BSS_BASE_ON_MULTI_PARAM + scanGetCurrentEssChnlList(prAdapter); +#endif +/* ebd Support AP Selection */ + break; + + default: + break; + + } + } + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); + if (prBcnRmParam->eState == RM_NO_REQUEST) + return; + /* normal mode scan done, and beacon measurement is pending, + ** schedule to do measurement + */ + if (prBcnRmParam->eState == RM_WAITING) { + rlmDoBeaconMeasurement(prAdapter, 0); + /* pending normal scan here, should schedule it on time */ + } else if (prBcnRmParam->rNormalScan.fgExist) { + struct PARAM_SCAN_REQUEST_ADV *prScanRequest = + &prBcnRmParam->rNormalScan.rScanRequest; + + DBGLOG(AIS, INFO, + "BCN REQ: Schedule normal scan after a beacon measurement done\n"); + prBcnRmParam->eState = RM_WAITING; + prBcnRmParam->rNormalScan.fgExist = FALSE; + cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer, + SEC_TO_MSEC(AIS_SCN_DONE_TIMEOUT_SEC)); + + aisFsmScanRequestAdv(prAdapter, prScanRequest); + /* Radio Measurement is on-going, schedule to next Measurement + ** Element + */ + } else + rlmStartNextMeasurement(prAdapter, FALSE); + +} /* end of aisFsmRunEventScanDone() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void aisFsmRunEventAbort(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_AIS_ABORT *prAisAbortMsg; + struct AIS_FSM_INFO *prAisFsmInfo; + uint8_t ucReasonOfDisconnect; + u_int8_t fgDelayIndication; + struct CONNECTION_SETTINGS *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 = (struct MSG_AIS_ABORT *)prMsgHdr; + ucReasonOfDisconnect = prAisAbortMsg->ucReasonOfDisconnect; + fgDelayIndication = prAisAbortMsg->fgDelayIndication; + + cnmMemFree(prAdapter, prMsgHdr); + + DBGLOG(AIS, STATE, + "EVENT-ABORT: Current State %s, ucReasonOfDisconnect:%d\n", + apucDebugAisState[prAisFsmInfo->eCurrentState], + ucReasonOfDisconnect); + + /* record join request time */ + GET_CURRENT_SYSTIME(&(prAisFsmInfo->rJoinReqTime)); + + /* 4 <2> clear previous pending connection request and insert new one */ + /* Support AP Selection */ + if (ucReasonOfDisconnect == DISCONNECT_REASON_CODE_DEAUTHENTICATED || + ucReasonOfDisconnect == DISCONNECT_REASON_CODE_DISASSOCIATED) { + struct STA_RECORD *prSta = prAisFsmInfo->prTargetStaRec; + struct BSS_DESC *prBss = prAisFsmInfo->prTargetBssDesc; + + if (prSta && prBss && prSta->u2ReasonCode == + REASON_CODE_DISASSOC_AP_OVERLOAD) { + struct AIS_BLACKLIST_ITEM *prBlackList = + aisAddBlacklist(prAdapter, prBss); + + if (prBlackList) + prBlackList->u2DeauthReason = + prSta->u2ReasonCode; + } + if (prAisFsmInfo->prTargetBssDesc) + prAisFsmInfo->prTargetBssDesc->fgDeauthLastTime = TRUE; + prConnSettings->fgIsDisconnectedByNonRequest = TRUE; + /* end Support AP Selection */ + } else { + prConnSettings->fgIsDisconnectedByNonRequest = FALSE; + } + + /* to support user space triggered roaming */ + if (ucReasonOfDisconnect == DISCONNECT_REASON_CODE_ROAMING && + prAisFsmInfo->eCurrentState != AIS_STATE_DISCONNECTING) { + cnmTimerStopTimer(prAdapter, + &prAisFsmInfo->rSecModeChangeTimer); + if (prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR) { + /* 1. release channel */ + aisFsmReleaseCh(prAdapter); + /* 2.1 stop join timeout timer */ + cnmTimerStopTimer(prAdapter, + &prAisFsmInfo->rJoinTimeoutTimer); + /* 2.2 reset local variable */ + prAisFsmInfo->fgIsInfraChannelFinished = TRUE; + aisFsmSteps(prAdapter, AIS_STATE_SEARCH); + } else { + aisFsmIsRequestPending(prAdapter, + AIS_REQUEST_ROAMING_SEARCH, + TRUE); + aisFsmIsRequestPending(prAdapter, + AIS_REQUEST_ROAMING_CONNECT, + TRUE); + aisFsmInsertRequest(prAdapter, + AIS_REQUEST_ROAMING_CONNECT); + } + return; + } + /* Support AP Selection */ +#if CFG_SELECT_BSS_BASE_ON_MULTI_PARAM + scanGetCurrentEssChnlList(prAdapter); +#endif + /* end Support AP Selection */ + + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_RECONNECT, TRUE); + aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); + + if (prAisFsmInfo->eCurrentState != AIS_STATE_DISCONNECTING) { + if (ucReasonOfDisconnect != + DISCONNECT_REASON_CODE_REASSOCIATION) { + /* 4 <3> invoke abort handler */ + aisFsmStateAbort(prAdapter, ucReasonOfDisconnect, + fgDelayIndication); + } else { + /* 1. release channel */ + aisFsmReleaseCh(prAdapter); + /* 2.1 stop join timeout timer */ + cnmTimerStopTimer(prAdapter, + &prAisFsmInfo->rJoinTimeoutTimer); + /* 2.2 reset local variable */ + prAisFsmInfo->fgIsInfraChannelFinished = TRUE; + + prAdapter->prAisBssInfo->ucReasonOfDisconnect = + ucReasonOfDisconnect; + aisFsmSteps(prAdapter, AIS_STATE_IDLE); + } + } +} /* 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 struct ADAPTER *prAdapter, + uint8_t ucReasonOfDisconnect, u_int8_t fgDelayIndication) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prAisBssInfo; + struct CONNECTION_SETTINGS *prConnSettings; + u_int8_t fgIsCheckConnected; + + ASSERT(prAdapter); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = prAdapter->prAisBssInfo; + + /* XXX: The wlan0 may has been changed to AP mode. */ + if (prAisBssInfo == NULL) + return; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + fgIsCheckConnected = FALSE; + + DBGLOG(AIS, STATE, "aisFsmStateAbort DiscReason[%d], CurState[%d]\n", + ucReasonOfDisconnect, prAisFsmInfo->eCurrentState); + + /* 4 <1> Save information of Abort Message and then free memory. */ + prAisBssInfo->ucReasonOfDisconnect = ucReasonOfDisconnect; + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED && + prAisFsmInfo->eCurrentState != AIS_STATE_DISCONNECTING && + ucReasonOfDisconnect != DISCONNECT_REASON_CODE_REASSOCIATION && + ucReasonOfDisconnect != DISCONNECT_REASON_CODE_ROAMING) + wmmNotifyDisconnected(prAdapter); + + /* 4 <2> Abort current job. */ + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_IDLE: + case AIS_STATE_SEARCH: + case AIS_STATE_JOIN_FAILURE: + 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; + + /* stop okc timeout timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rWaitOkcPMKTimer); + break; + + case AIS_STATE_JOIN: + /* Do abort JOIN */ + aisFsmStateAbort_JOIN(prAdapter); + + /* in case roaming is triggered */ + fgIsCheckConnected = TRUE; + break; + +#if CFG_SUPPORT_ADHOC + case AIS_STATE_IBSS_ALONE: + case AIS_STATE_IBSS_MERGE: + aisFsmStateAbort_IBSS(prAdapter); + break; +#endif /* CFG_SUPPORT_ADHOC */ + + case AIS_STATE_ONLINE_SCAN: + /* Do abort SCAN */ + aisFsmStateAbort_SCAN(prAdapter); + /* queue for later handling */ + if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, FALSE) + == FALSE) + aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); + + fgIsCheckConnected = TRUE; + break; + + case AIS_STATE_NORMAL_TR: + fgIsCheckConnected = TRUE; + break; + + case AIS_STATE_DISCONNECTING: + /* Do abort NORMAL_TR */ + aisFsmStateAbort_NORMAL_TR(prAdapter); + + break; + + case AIS_STATE_REQ_REMAIN_ON_CHANNEL: + fgIsCheckConnected = TRUE; + + /* release channel */ + aisFsmReleaseCh(prAdapter); + break; + + case AIS_STATE_REMAIN_ON_CHANNEL: + fgIsCheckConnected = TRUE; + + /* 1. release channel */ + aisFsmReleaseCh(prAdapter); + + /* 2. stop channel timeout timer */ + cnmTimerStopTimer(prAdapter, + &prAisFsmInfo->rChannelTimeoutTimer); + + break; + + default: + break; + } + + if (fgIsCheckConnected + && (prAisBssInfo->eConnectionState == + PARAM_MEDIA_STATE_CONNECTED)) { + + /* switch into DISCONNECTING state for sending DEAUTH + * if necessary + */ + if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE && +#if !CFG_SUPPORT_CFG80211_AUTH + prAisBssInfo->ucReasonOfDisconnect == + DISCONNECT_REASON_CODE_NEW_CONNECTION && +#endif + prAisBssInfo->prStaRecOfAP && + prAisBssInfo->prStaRecOfAP->fgIsInUse) { + aisFsmSteps(prAdapter, AIS_STATE_DISCONNECTING); + + return; + } + /* Do abort NORMAL_TR */ + aisFsmStateAbort_NORMAL_TR(prAdapter); + } + rlmFreeMeasurementResources(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 struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_SAA_FSM_COMP *prJoinCompMsg; + struct AIS_FSM_INFO *prAisFsmInfo; + enum ENUM_AIS_STATE eNextState; + struct SW_RFB *prAssocRspSwRfb; + + DEBUGFUNC("aisFsmRunEventJoinComplete()"); + ASSERT(prMsgHdr); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prJoinCompMsg = (struct MSG_SAA_FSM_COMP *)prMsgHdr; + prAssocRspSwRfb = prJoinCompMsg->prSwRfb; + + eNextState = prAisFsmInfo->eCurrentState; + + /* Check State and SEQ NUM */ + if (prAisFsmInfo->eCurrentState == AIS_STATE_JOIN) { + /* Check SEQ NUM */ + if (prJoinCompMsg->ucSeqNum == prAisFsmInfo->ucSeqNumOfReqMsg) + eNextState = + aisFsmJoinCompleteAction(prAdapter, prMsgHdr); +#if DBG + else + DBGLOG(AIS, WARN, + "SEQ NO of AIS JOIN COMP MSG is not matched.\n"); +#endif /* DBG */ + } + /* Support AP Selection */ + /* try to remove timeout blacklist item */ + aisRemoveDisappearedBlacklist(prAdapter); + /* end Support AP Selection */ + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); + + if (prAssocRspSwRfb) + nicRxReturnRFB(prAdapter, prAssocRspSwRfb); + + cnmMemFree(prAdapter, prMsgHdr); +} /* end of aisFsmRunEventJoinComplete() */ + +enum ENUM_AIS_STATE aisFsmJoinCompleteAction(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_SAA_FSM_COMP *prJoinCompMsg; + struct AIS_FSM_INFO *prAisFsmInfo; + enum ENUM_AIS_STATE eNextState; + struct STA_RECORD *prStaRec; + struct SW_RFB *prAssocRspSwRfb; + struct BSS_INFO *prAisBssInfo; + OS_SYSTIME rCurrentTime; + struct CONNECTION_SETTINGS *prConnSettings; + + DEBUGFUNC("aisFsmJoinCompleteAction()"); + + ASSERT(prMsgHdr); + + GET_CURRENT_SYSTIME(&rCurrentTime); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prJoinCompMsg = (struct MSG_SAA_FSM_COMP *)prMsgHdr; + prStaRec = prJoinCompMsg->prStaRec; + prAssocRspSwRfb = prJoinCompMsg->prSwRfb; + prAisBssInfo = prAdapter->prAisBssInfo; + eNextState = prAisFsmInfo->eCurrentState; + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + + do { + /* 4 <1> JOIN was successful */ + if (prJoinCompMsg->rJoinStatus == WLAN_STATUS_SUCCESS) { + prAdapter->rWifiVar. + rConnSettings.fgSecModeChangeStartTimer = FALSE; + + /* 1. Reset retry count */ + prAisFsmInfo->ucConnTrialCount = 0; + prAdapter->rWifiVar.rConnSettings.eReConnectLevel = + RECONNECT_LEVEL_MIN; + + /* 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 { + kalResetStats(prAdapter-> + prGlueInfo->prDevHandler); + + /* 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); + cnmStaRecFree(prAdapter, + prAisBssInfo->prStaRecOfAP); + } + + /* For temp solution, need to refine */ + /* 4 <1.4> Update BSS_INFO_T */ + aisUpdateBssInfoForJOIN(prAdapter, prStaRec, + prAssocRspSwRfb); + + /* 4 <1.3> Activate current AP's STA_RECORD_T + * in Driver. + */ + cnmStaRecChangeState(prAdapter, prStaRec, + STA_STATE_3); + + /* 4 <1.5> Update RSSI if necessary */ + nicUpdateRSSI(prAdapter, + prAdapter-> + prAisBssInfo->ucBssIndex, + (int8_t) (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 (prAdapter->rWifiVar.ucTpTestMode == + ENUM_TP_TEST_MODE_THROUGHPUT) + nicEnterTPTestMode(prAdapter, + TEST_MODE_THROUGHPUT); + else if (prAdapter->rWifiVar.ucTpTestMode == + ENUM_TP_TEST_MODE_SIGMA_AC_N_PMF) + nicEnterTPTestMode(prAdapter, + TEST_MODE_SIGMA_AC_N_PMF); + else if (prAdapter->rWifiVar.ucTpTestMode == + ENUM_TP_TEST_MODE_SIGMA_WMM_PS) + nicEnterTPTestMode(prAdapter, + TEST_MODE_SIGMA_WMM_PS); + } + +#if CFG_SUPPORT_ROAMING + /* if user space roaming is enabled, we should + * disable driver/fw roaming + */ + if ((prAdapter->rWifiVar. + rConnSettings.eConnectionPolicy != + CONNECT_BY_BSSID) + && prAdapter->rWifiVar. + rRoamingInfo.fgDrvRoamingAllow) + roamingFsmRunEventStart(prAdapter); +#endif /* CFG_SUPPORT_ROAMING */ + if (aisFsmIsRequestPending + (prAdapter, AIS_REQUEST_ROAMING_CONNECT, + FALSE) == FALSE) + prAisFsmInfo->rJoinReqTime = 0; + + /* Support AP Selection */ + prAisFsmInfo->prTargetBssDesc->fgDeauthLastTime = FALSE; + prAisFsmInfo->ucJoinFailCntAfterScan = 0; + /* end Support AP Selection */ + +#if CFG_SUPPORT_802_11K + aisResetNeighborApList(prAdapter); + if (prAisFsmInfo->prTargetBssDesc->aucRrmCap[0] & + BIT(RRM_CAP_INFO_NEIGHBOR_REPORT_BIT)) + aisSendNeighborRequest(prAdapter); +#endif + + /* 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) { + struct BSS_DESC *prBssDesc; + struct PARAM_SSID rSsid; + struct CONNECTION_SETTINGS *prConnSettings; + + prConnSettings = + &(prAdapter->rWifiVar.rConnSettings); + prBssDesc = prAisFsmInfo->prTargetBssDesc; + + /* 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; + /* Support AP Selection */ + prAisFsmInfo->ucJoinFailCntAfterScan++; + + kalMemZero(&rSsid, sizeof(struct PARAM_SSID)); + if (prBssDesc) + COPY_SSID(rSsid.aucSsid, + rSsid.u4SsidLen, + prBssDesc->aucSSID, + prBssDesc->ucSSIDLen); + else + COPY_SSID(rSsid.aucSsid, + rSsid.u4SsidLen, + prConnSettings->aucSSID, + prConnSettings->ucSSIDLen); + + prBssDesc = + scanSearchBssDescByBssidAndSsid(prAdapter, + prStaRec->aucMacAddr, + TRUE, + &rSsid); + +#if CFG_SUPPORT_CFG80211_AUTH + if (prBssDesc == NULL) { + prBssDesc = + scanSearchBssDescByBssidAndChanNum( + prAdapter, + prConnSettings->aucBSSID, + TRUE, + prConnSettings->ucChannelNum); + } +#endif + if (prBssDesc == NULL) + break; + + DBGLOG(AIS, TRACE, + "ucJoinFailureCount=%d %d, Status=%d Reason=%d, eConnectionState=%d", + prStaRec->ucJoinFailureCount, + prBssDesc->ucJoinFailureCount, + prStaRec->u2StatusCode, + prStaRec->u2ReasonCode, + prAisBssInfo->eConnectionState); + + /* ASSERT(prBssDesc); */ + /* ASSERT(prBssDesc->fgIsConnecting); */ + prBssDesc->u2JoinStatus = + prStaRec->u2StatusCode; + prBssDesc->ucJoinFailureCount++; + if (prBssDesc->ucJoinFailureCount >= + SCN_BSS_JOIN_FAIL_THRESOLD) { + /* Support AP Selection */ + aisAddBlacklist(prAdapter, prBssDesc); + + GET_CURRENT_SYSTIME + (&prBssDesc->rJoinFailTime); + DBGLOG(AIS, INFO, + "Bss " MACSTR + " join fail %d times, temp disable it at time: %u\n", + MAC2STR(prBssDesc->aucBSSID), + SCN_BSS_JOIN_FAIL_THRESOLD, + prBssDesc->rJoinFailTime); + } + + /* Support AP Selection */ + if (prBssDesc->prBlack) + prBssDesc->prBlack->u2AuthStatus = + prStaRec->u2StatusCode; + + if (prBssDesc) + prBssDesc->fgIsConnecting = FALSE; + + /* 3.3 Free STA-REC */ + if (prStaRec != prAisBssInfo->prStaRecOfAP) + cnmStaRecFree(prAdapter, prStaRec); + + if (prAisBssInfo->eConnectionState == + PARAM_MEDIA_STATE_CONNECTED) { + struct PARAM_SSID rSsid; + + /* roaming fail count and time */ + prAdapter->prGlueInfo->u4RoamFailCnt++; + prAdapter->prGlueInfo->u8RoamFailTime = + sched_clock(); +#if CFG_SUPPORT_ROAMING + eNextState = + AIS_STATE_WAIT_FOR_NEXT_SCAN; +#endif /* CFG_SUPPORT_ROAMING */ + + if (prAisBssInfo->prStaRecOfAP) + prAisBssInfo-> + prStaRecOfAP->fgIsTxAllowed + = TRUE; + + if (prConnSettings->eConnectionPolicy + == CONNECT_BY_BSSID + && prBssDesc->u2JoinStatus) { + uint32_t u4InfoBufLen = 0; + /* For framework roaming case, + * if authentication is + * rejected, need to make + * driver disconnecting + * because wpa_supplicant will + * enter disconnected state in + * this case, otherwise, + * connection state between + * driver and supplicant will + * be not synchronized. + */ + wlanoidSetDisassociate + (prAdapter, NULL, 0, + &u4InfoBufLen); + eNextState = + prAisFsmInfo->eCurrentState; + break; + } + COPY_SSID(rSsid.aucSsid, + rSsid.u4SsidLen, + prAisBssInfo->aucSSID, + prAisBssInfo->ucSSIDLen); + prAisFsmInfo->prTargetBssDesc = + scanSearchBssDescByBssidAndSsid + (prAdapter, prAisBssInfo->aucBSSID, + TRUE, &rSsid); + prAisFsmInfo->prTargetStaRec = + prAisBssInfo->prStaRecOfAP; + ASSERT(prAisFsmInfo->prTargetBssDesc); + if (!prAisFsmInfo->prTargetBssDesc) + DBGLOG(AIS, ERROR, + "Can't retrieve target bss descriptor\n"); + } else if (prAisFsmInfo->rJoinReqTime != 0 + && CHECK_FOR_TIMEOUT(rCurrentTime, + prAisFsmInfo->rJoinReqTime, + SEC_TO_SYSTIME + (AIS_JOIN_TIMEOUT))) { + /* 4.a temrminate join operation */ + eNextState = AIS_STATE_JOIN_FAILURE; + } else if (prAisFsmInfo->rJoinReqTime != 0 + && prBssDesc->ucJoinFailureCount >= + SCN_BSS_JOIN_FAIL_THRESOLD + && prBssDesc->u2JoinStatus) { + /* AP reject STA for + * STATUS_CODE_ASSOC_DENIED_AP_OVERLOAD + * , or AP block STA + */ + eNextState = AIS_STATE_JOIN_FAILURE; + } else { + /* 4.b send reconnect request */ + aisFsmInsertRequest(prAdapter, + AIS_REQUEST_RECONNECT); + + eNextState = AIS_STATE_IDLE; + } + } + } + } while (0); + return eNextState; +} + +#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 struct ADAPTER *prAdapter) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + + ASSERT(prAdapter); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + do { + /* Check State */ + if (prAisFsmInfo->eCurrentState == AIS_STATE_IBSS_ALONE) + aisUpdateBssInfoForCreateIBSS(prAdapter); + + } while (FALSE); +} /* end of aisFsmCreateIBSS() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will handle the Grant Msg of IBSS Merge which was + * sent by CNM to indicate that channel was changed for merging IBSS. + * + * @param[in] prAdapter Pointer of ADAPTER_T + * @param[in] prStaRec Pointer of STA_RECORD_T for merge + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisFsmMergeIBSS(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + enum ENUM_AIS_STATE eNextState; + struct BSS_INFO *prAisBssInfo; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = prAdapter->prAisBssInfo; + + do { + + eNextState = prAisFsmInfo->eCurrentState; + + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_IBSS_MERGE: + { + struct BSS_DESC *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. + */ + bssInitializeClientList(prAdapter, + prAisBssInfo); + + /* 4 <1.3> Unmark connection flag of previous + * BSS_DESC_T. + */ + prBssDesc = + scanSearchBssDescByBssid(prAdapter, + prAisBssInfo->aucBSSID); + if (prBssDesc != NULL) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = FALSE; + } + /* 4 <1.4> Add Peers' STA_RECORD_T to + * Client List + */ + bssAddClient(prAdapter, prAisBssInfo, prStaRec); + + /* 4 <1.5> Activate current Peer's STA_RECORD_T + * in Driver. + */ + cnmStaRecChangeState(prAdapter, prStaRec, + STA_STATE_3); + prStaRec->fgIsMerging = FALSE; + + /* 4 <1.6> Update BSS_INFO_T */ + aisUpdateBssInfoForMergeIBSS(prAdapter, + prStaRec); + + /* 4 <1.7> Enable other features */ + + /* 4 <1.8> Indicate Connected Event to Host + * immediately. + */ + aisIndicationOfMediaStateToHost(prAdapter, + PARAM_MEDIA_STATE_CONNECTED, + FALSE); + + /* 4 <1.9> Set the Next State of AIS FSM */ + eNextState = AIS_STATE_NORMAL_TR; + + /* 4 <1.10> Release channel privilege */ + aisFsmReleaseCh(prAdapter); + +#if CFG_SLT_SUPPORT + prAdapter->rWifiVar.rSltInfo.prPseudoStaRec = + prStaRec; +#endif + } + break; + + default: + break; + } + + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); + + } while (FALSE); +} /* end of aisFsmMergeIBSS() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will handle the Notification of existing IBSS was found + * from SCN. + * + * @param[in] prMsgHdr Message of Notification of an IBSS was present. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisFsmRunEventFoundIBSSPeer(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_AIS_IBSS_PEER_FOUND *prAisIbssPeerFoundMsg; + struct AIS_FSM_INFO *prAisFsmInfo; + enum ENUM_AIS_STATE eNextState; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prAisBssInfo; + struct BSS_DESC *prBssDesc; + u_int8_t fgIsMergeIn; + + ASSERT(prMsgHdr); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = prAdapter->prAisBssInfo; + + prAisIbssPeerFoundMsg = (struct MSG_AIS_IBSS_PEER_FOUND *)prMsgHdr; + + ASSERT(prAisIbssPeerFoundMsg->ucBssIndex == + prAdapter->prAisBssInfo->ucBssIndex); + + 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 + */ + bssAddClient(prAdapter, prAisBssInfo, prStaRec); + +#if CFG_SLT_SUPPORT + /* 4 <1.3> Mark connection flag of + * BSS_DESC_T. + */ + prBssDesc = + scanSearchBssDescByTA(prAdapter, + prStaRec->aucMacAddr); + + if (prBssDesc != NULL) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + } else { + /* Should be able to find a + * BSS_DESC_T here. + */ + ASSERT(0); + } + + /* 4 <1.4> Activate current Peer's + * STA_RECORD_T in Driver. + */ + /* TODO(Kevin): TBD */ + prStaRec->fgIsQoS = TRUE; +#else + /* 4 <1.3> Mark connection flag + * of BSS_DESC_T. + */ + prBssDesc = + scanSearchBssDescByBssid(prAdapter, + prAisBssInfo->aucBSSID); + + if (prBssDesc != NULL) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + } else { + /* Should be able to find a + * BSS_DESC_T here. + */ + ASSERT(0); + } + + /* 4 <1.4> Activate current Peer's STA_RECORD_T + * in Driver. + */ + /* TODO(Kevin): TBD */ + prStaRec->fgIsQoS = FALSE; + +#endif + + cnmStaRecChangeState(prAdapter, prStaRec, + STA_STATE_3); + prStaRec->fgIsMerging = FALSE; + + /* 4 <1.6> sync. to firmware */ + nicUpdateBss(prAdapter, + prAdapter-> + prAisBssInfo->ucBssIndex); + + /* 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, + prAdapter->prAisBssInfo->ucBssIndex); + + /* 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 + */ + bssAddClient(prAdapter, prAisBssInfo, prStaRec); + +#if CFG_SLT_SUPPORT + /* 4 <3.2> Activate current Peer's STA_RECORD_T + * in Driver. + */ + /* TODO(Kevin): TBD */ + prStaRec->fgIsQoS = TRUE; +#else + /* 4 <3.2> Activate current Peer's STA_RECORD_T + * in Driver. + */ + /* TODO(Kevin): TBD */ + prStaRec->fgIsQoS = FALSE; +#endif + + cnmStaRecChangeState(prAdapter, prStaRec, + STA_STATE_3); + prStaRec->fgIsMerging = FALSE; + + } + /* 4 <4> We need 'merge out' to this IBSS */ + else { + + /* 4 <4.1> Get corresponding BSS_DESC_T */ + prBssDesc = + scanSearchBssDescByTA(prAdapter, + prStaRec->aucMacAddr); + + prAisFsmInfo->prTargetBssDesc = prBssDesc; + + /* 4 <4.2> Set the Next State of AIS FSM */ + eNextState = AIS_STATE_IBSS_MERGE; + + } + } + break; + + default: + break; + } + + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); +} /* end of aisFsmRunEventFoundIBSSPeer() */ +#endif /* CFG_SUPPORT_ADHOC */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will indicate the Media State to HOST + * + * @param[in] eConnectionState Current Media State + * @param[in] fgDelayIndication Set TRUE for postponing the Disconnect + * Indication. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void +aisIndicationOfMediaStateToHost(IN struct ADAPTER *prAdapter, + enum ENUM_PARAM_MEDIA_STATE eConnectionState, + u_int8_t fgDelayIndication) +{ + struct EVENT_CONNECTION_STATUS rEventConnStatus; + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_INFO *prAisBssInfo; + struct AIS_FSM_INFO *prAisFsmInfo; + + DEBUGFUNC("aisIndicationOfMediaStateToHost()"); + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prAisBssInfo = prAdapter->prAisBssInfo; + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + DBGLOG(AIS, LOUD, + "AIS indicate Media State to Host Current State [%d]\n", + prAisBssInfo->eConnectionState); + + /* 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. + */ + DBGLOG(AIS, INFO, "Current state: %d, connection state indicated: %d\n", + prAisFsmInfo->eCurrentState, + prAisBssInfo->eConnectionStateIndicated); + + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED && + /* if receive DEAUTH in JOIN state, report disconnect*/ + !(prAisBssInfo->ucReasonOfDisconnect == + DISCONNECT_REASON_CODE_DEAUTHENTICATED && + prAisFsmInfo->eCurrentState == AIS_STATE_JOIN)) { + if (prAisBssInfo->eConnectionStateIndicated == eConnectionState) + return; + } + kalMemZero(&rEventConnStatus, sizeof(rEventConnStatus)); + + if (!fgDelayIndication) { + /* 4 <0> Cancel Delay Timer */ + prAisFsmInfo->u4PostponeIndStartTime = 0; + + /* 4 <1> Fill EVENT_CONNECTION_STATUS */ + rEventConnStatus.ucMediaStatus = (uint8_t) eConnectionState; + + if (eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + rEventConnStatus.ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_RESERVED; + + if (prAisBssInfo->eCurrentOPMode == + OP_MODE_INFRASTRUCTURE) { + rEventConnStatus.ucInfraMode = + (uint8_t) NET_TYPE_INFRA; + rEventConnStatus.u2AID = + prAisBssInfo->u2AssocId; + rEventConnStatus.u2ATIMWindow = 0; + } else if (prAisBssInfo->eCurrentOPMode == + OP_MODE_IBSS) { + rEventConnStatus.ucInfraMode = + (uint8_t) 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 = + (uint8_t) PARAM_NETWORK_TYPE_DS; + break; + + case PHY_TYPE_ERP_INDEX: + rEventConnStatus.ucNetworkType = + (uint8_t) PARAM_NETWORK_TYPE_OFDM24; + break; + + case PHY_TYPE_OFDM_INDEX: + rEventConnStatus.ucNetworkType = + (uint8_t) PARAM_NETWORK_TYPE_OFDM5; + break; + + default: + ASSERT(0); + rEventConnStatus.ucNetworkType = + (uint8_t) PARAM_NETWORK_TYPE_DS; + break; + } + } else { + /* Clear the pmkid cache while media disconnect */ + secClearPmkid(prAdapter); + rEventConnStatus.ucReasonOfDisconnect = + prAisBssInfo->ucReasonOfDisconnect; + } + + /* 4 <2> Indication */ + nicMediaStateChange(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, + &rEventConnStatus); + prAisBssInfo->eConnectionStateIndicated = eConnectionState; + if (eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { + prAisFsmInfo->prTargetBssDesc = NULL; + prAisFsmInfo->prTargetStaRec = NULL; + } + } 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); + + prAisFsmInfo->u4PostponeIndStartTime = kalGetTimeTick(); + } +} /* 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 struct ADAPTER *prAdapter, + IN struct AIS_FSM_INFO *prAisFsmInfo) +{ + struct BSS_INFO *prAisBssInfo; + struct CONNECTION_SETTINGS *prConnSettings; + bool fgFound = TRUE; + bool fgIsPostponeTimeout; + bool fgIsBeaconTimeout; + + /* firstly, check if we have started postpone indication. + ** otherwise, give a chance to do join before indicate to host + **/ + if (prAisFsmInfo->u4PostponeIndStartTime == 0) + return; + + /* if we're in req channel/join/search state, + * don't report disconnect. + */ + if (prAisFsmInfo->eCurrentState == AIS_STATE_JOIN || + prAisFsmInfo->eCurrentState == AIS_STATE_SEARCH || + prAisFsmInfo->eCurrentState == AIS_STATE_REQ_CHANNEL_JOIN) + return; + + prAisBssInfo = prAdapter->prAisBssInfo; + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + DBGLOG(AIS, EVENT, "aisPostponedEventOfDisconnTimeout\n"); + + fgIsPostponeTimeout = CHECK_FOR_TIMEOUT(kalGetTimeTick(), + prAisFsmInfo->u4PostponeIndStartTime, + SEC_TO_MSEC + (prConnSettings->ucDelayTimeOfDisconnectEvent)); + + fgIsBeaconTimeout = + prAisBssInfo->ucReasonOfDisconnect == + DISCONNECT_REASON_CODE_RADIO_LOST; + + /* only retry connect once when beacon timeout */ + if (!fgIsPostponeTimeout + && !(fgIsBeaconTimeout && prAisFsmInfo->ucConnTrialCount > 1)) { + DBGLOG(AIS, INFO, + "DelayTimeOfDisconnect, don't report disconnect\n"); + return; + } + + /* 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 = (struct STA_RECORD *)NULL; + } + /* 4 <2> Remove all connection request */ + while (fgFound) + fgFound = + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_RECONNECT, + TRUE); + if (prAisFsmInfo->eCurrentState == AIS_STATE_LOOKING_FOR) + prAisFsmInfo->eCurrentState = AIS_STATE_IDLE; + prConnSettings->fgIsDisconnectedByNonRequest = TRUE; + prAisBssInfo->u2DeauthReason = REASON_CODE_BEACON_TIMEOUT; + /* 4 <3> Indicate Disconnected Event to Host immediately. */ + /* Instead of indicating disconnect directly. + * We use aisFsmStateAbort here. + * Because AIS FSM might be running and need to abort from some state. + * For example: If driver is under LOOKING_FOR state, need abort FSM to cancel scan. + */ + aisFsmStateAbort(prAdapter, + DISCONNECT_REASON_CODE_RADIO_LOST, + FALSE); + + + +} /* end of aisPostponedEventOfDisconnTimeout() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will update the contain of BSS_INFO_T for AIS + * network once the association was completed. + * + * @param[in] prStaRec Pointer to the STA_RECORD_T + * @param[in] prAssocRspSwRfb Pointer to SW RFB of ASSOC RESP FRAME. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisUpdateBssInfoForJOIN(IN struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + struct SW_RFB *prAssocRspSwRfb) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prAisBssInfo; + struct CONNECTION_SETTINGS *prConnSettings; + struct WLAN_ASSOC_RSP_FRAME *prAssocRspFrame; + struct BSS_DESC *prBssDesc; + uint16_t u2IELength; + uint8_t *pucIE; + struct PARAM_SSID rSsid; + + DEBUGFUNC("aisUpdateBssInfoForJOIN()"); + + ASSERT(prStaRec); + ASSERT(prAssocRspSwRfb); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = prAdapter->prAisBssInfo; + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prAssocRspFrame = + (struct WLAN_ASSOC_RSP_FRAME *)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 */ + /* Use AP's Cap Info as BSS Cap Info */ + prAisBssInfo->u2CapInfo = prStaRec->u2CapInfo; + + if (prAisBssInfo->u2CapInfo & CAP_INFO_SHORT_PREAMBLE) + prAisBssInfo->fgIsShortPreambleAllowed = TRUE; + else + prAisBssInfo->fgIsShortPreambleAllowed = FALSE; + +#if CFG_SUPPORT_TDLS + prAisBssInfo->fgTdlsIsProhibited = prStaRec->fgTdlsIsProhibited; + prAisBssInfo->fgTdlsIsChSwProhibited = prStaRec->fgTdlsIsChSwProhibited; +#endif /* CFG_SUPPORT_TDLS */ + + /* 4 <2.3> Setup PHY Attributes and Basic Rate Set/Operational + * Rate Set + */ + prAisBssInfo->ucPhyTypeSet = prStaRec->ucDesiredPhyTypeSet; + + prAisBssInfo->ucNonHTBasicPhyType = prStaRec->ucNonHTBasicPhyType; + + prAisBssInfo->u2OperationalRateSet = prStaRec->u2OperationalRateSet; + prAisBssInfo->u2BSSBasicRateSet = prStaRec->u2BSSBasicRateSet; + + nicTxUpdateBssDefaultRate(prAisBssInfo); + + /* 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 = + (uint16_t) ((prAssocRspSwRfb->u2PacketLen - + prAssocRspSwRfb->u2HeaderLen) - + (OFFSET_OF(struct WLAN_ASSOC_RSP_FRAME, 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 = prAisFsmInfo->prTargetBssDesc; + if (prBssDesc) + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + else + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, + prConnSettings->aucSSID, prConnSettings->ucSSIDLen); + + prBssDesc = + scanSearchBssDescByBssidAndSsid(prAdapter, + prAssocRspFrame->aucBSSID, TRUE, + &rSsid); + +#if CFG_SUPPORT_CFG80211_AUTH + if (prBssDesc == NULL) { + prBssDesc = scanSearchBssDescByBssidAndChanNum( + prAdapter, + prConnSettings->aucBSSID, + TRUE, + prConnSettings->ucChannelNum); + } +#endif + + if (prBssDesc) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + prBssDesc->ucJoinFailureCount = 0; + + aisRemoveBlackList(prAdapter, prBssDesc); + /* 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->fgTIMPresent = TRUE; + prAisBssInfo->u2ATIMWindow = 0; + + prAisBssInfo->ucBeaconTimeoutCount = AIS_BEACON_TIMEOUT_COUNT_INFRA; +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + prAisBssInfo->ucRoamSkipTimes = ROAMING_ONE_AP_SKIP_TIMES; + prAisBssInfo->fgGoodRcpiArea = FALSE; + prAisBssInfo->fgPoorRcpiArea = FALSE; +#endif + + /* 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); + + secPostUpdateAddr(prAdapter, prAdapter->prAisBssInfo); + + /* 4 <4.3> Sync with firmware for BSS-INFO */ + nicUpdateBss(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + + /* 4 <4.4> *DEFER OPERATION* nicPmIndicateBssConnected() + * will be invoked + */ + /* inside scanProcessBeaconAndProbeResp() after 1st beacon + * is received + */ +} /* end of aisUpdateBssInfoForJOIN() */ + +#if CFG_SUPPORT_ADHOC +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will create an Ad-Hoc network and start sending + * Beacon Frames. + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisUpdateBssInfoForCreateIBSS(IN struct ADAPTER *prAdapter) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prAisBssInfo; + struct CONNECTION_SETTINGS *prConnSettings; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = prAdapter->prAisBssInfo; + 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 = (struct STA_RECORD *)NULL; + prAisBssInfo->u2AssocId = 0; + + /* 4 <1.4> Setup Channel, Band and Phy Attributes */ + prAisBssInfo->ucPrimaryChannel = prConnSettings->ucAdHocChannelNum; + prAisBssInfo->eBand = prConnSettings->eAdHocBand; + + if (prAisBssInfo->eBand == BAND_2G4) { + /* Depend on eBand */ + prAisBssInfo->ucPhyTypeSet = + prAdapter-> + rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11BGN; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prAisBssInfo->ucConfigAdHocAPMode = AD_HOC_MODE_MIXED_11BG; + } else { + /* Depend on eBand */ + prAisBssInfo->ucPhyTypeSet = + prAdapter-> + rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11ANAC; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prAisBssInfo->ucConfigAdHocAPMode = AD_HOC_MODE_11A; + } + + /* 4 <1.5> Setup MIB for current BSS */ + prAisBssInfo->u2BeaconInterval = prConnSettings->u2BeaconPeriod; + prAisBssInfo->ucDTIMPeriod = 0; + prAisBssInfo->u2ATIMWindow = prConnSettings->u2AtimWindow; + + prAisBssInfo->ucBeaconTimeoutCount = AIS_BEACON_TIMEOUT_COUNT_ADHOC; + + if (prConnSettings->eEncStatus == ENUM_ENCRYPTION1_ENABLED || + prConnSettings->eEncStatus == ENUM_ENCRYPTION2_ENABLED || + prConnSettings->eEncStatus == ENUM_ENCRYPTION3_ENABLED) { + prAisBssInfo->fgIsProtection = TRUE; + } else { + prAisBssInfo->fgIsProtection = FALSE; + } + + /* 3 <2> Update BSS_INFO_T common part */ + ibssInitForAdHoc(prAdapter, prAisBssInfo); + /* 4 <2.1> Initialize client list */ + bssInitializeClientList(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, prAdapter->prAisBssInfo->ucBssIndex); + + /* 4 <3.3> enable beaconing */ + bssUpdateBeaconContent(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + + /* 4 <3.4> Update AdHoc PM parameter */ + nicPmIndicateBssCreated(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + + /* 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)); +} /* 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 struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prAisBssInfo; + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_DESC *prBssDesc; + /* UINT_16 u2IELength; */ + /* PUINT_8 pucIE; */ + + ASSERT(prStaRec); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = prAdapter->prAisBssInfo; + 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 = (struct STA_RECORD *)NULL; + prAisBssInfo->u2AssocId = 0; + } + /* 3 <2> Update BSS_INFO_T from STA_RECORD_T */ + /* 4 <2.1> Setup Capability */ + /* Use Peer's Cap Info as IBSS Cap Info */ + prAisBssInfo->u2CapInfo = prStaRec->u2CapInfo; + + 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. */ + /* Set to FALSE for AdHoc */ + prAisBssInfo->fgUseShortSlotTime = FALSE; + 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; + /* Support AP Selection */ + aisRemoveBlackList(prAdapter, prBssDesc); + + /* 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 */ + nicTxUpdateBssDefaultRate(prAisBssInfo); + + /* 4 <5.2> Setup channel and bandwidth */ + rlmBssInitForAPandIbss(prAdapter, prAisBssInfo); + + /* 4 <5.3> use command packets to inform firmware */ + nicUpdateBss(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + + /* 4 <5.4> enable beaconing */ + bssUpdateBeaconContent(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + + /* 4 <5.5> Update AdHoc PM parameter */ + nicPmIndicateBssConnected(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex); + + /* 3 <6> Set ACTIVE flag. */ + prAisBssInfo->fgIsBeaconActivated = TRUE; + prAisBssInfo->fgHoldSameBssidForIBSS = TRUE; +} /* end of aisUpdateBssInfoForMergeIBSS() */ + +#endif /* CFG_SUPPORT_ADHOC */ + +#if (CFG_SUPPORT_ADHOC || CFG_SUPPORT_PROBE_REQ_REPORT) + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t aisValidateProbeReq(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + OUT uint32_t *pu4ControlFlags) +{ + struct WLAN_MAC_MGMT_HEADER *prMgtHdr; + struct BSS_INFO *prBssInfo; + struct IE_SSID *prIeSsid = (struct IE_SSID *)NULL; + struct AIS_FSM_INFO *prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + uint8_t *pucIE; + uint16_t u2IELength; + uint16_t u2Offset = 0; + u_int8_t fgReplyProbeResp = FALSE; + + ASSERT(prSwRfb); + ASSERT(pu4ControlFlags); + + prBssInfo = prAdapter->prAisBssInfo; + + /* 4 <1> Parse Probe Req IE and Get IE ptr + * (SSID, Supported Rate IE, ...) + */ + prMgtHdr = (struct WLAN_MAC_MGMT_HEADER *)prSwRfb->pvHeader; + + u2IELength = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen; + pucIE = + (uint8_t *) ((unsigned long)prSwRfb->pvHeader + + prSwRfb->u2HeaderLen); + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (IE_ID(pucIE) == ELEM_ID_SSID) { + if ((!prIeSsid) && (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) + prIeSsid = (struct IE_SSID *)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; + } + } + + if (prAisFsmInfo->u4AisPacketFilter & PARAM_PACKET_FILTER_PROBE_REQ) { + DBGLOG(AIS, INFO, "[AIS] RX Probe Req Frame\n"); + kalIndicateRxMgmtFrame(prAdapter->prGlueInfo, prSwRfb); + } + + + return fgReplyProbeResp; + +} /* end of aisValidateProbeReq() */ + +#endif /* CFG_SUPPORT_ADHOC || CFG_SUPPORT_PROBE_REQ_REPORT */ + +#if CFG_DISCONN_DEBUG_FEATURE +void aisCollectDisconnInfo(IN struct ADAPTER *prAdapter) +{ + struct BSS_INFO *prAisBssInfo; + uint32_t u4BufLen = 0; + uint8_t ucWlanIndex; + uint8_t *pucMacAddr = NULL; + struct AIS_DISCONN_INFO_T *prDisconn = NULL; + + if (prAdapter == NULL) { + DBGLOG(AIS, ERROR, "Null adapter\n"); + return; + } + + if (g_prDisconnInfo == NULL) { + DBGLOG(AIS, ERROR, "Null g_prDisconnInfo\n"); + return; + } + + if (g_DisconnInfoIdx >= MAX_DISCONNECT_RECORD) { + DBGLOG(AIS, ERROR, "Invalid g_DisconnInfoIdx\n"); + return; + } + + prDisconn = g_prDisconnInfo + g_DisconnInfoIdx; + kalMemZero(prDisconn, sizeof(struct AIS_DISCONN_INFO_T)); + + prAisBssInfo = prAdapter->prAisBssInfo; + + do_gettimeofday(&prDisconn->tv); + + prDisconn->ucTrigger = g_rDisconnInfoTemp.ucTrigger; + prDisconn->ucDisConnReason = prAisBssInfo->ucReasonOfDisconnect; + prDisconn->ucBcnTimeoutReason = g_rDisconnInfoTemp.ucBcnTimeoutReason; + prDisconn->ucDisassocReason = g_rDisconnInfoTemp.ucDisassocReason; + prDisconn->u2DisassocSeqNum = g_rDisconnInfoTemp.u2DisassocSeqNum; + +#if CFG_SUPPORT_ADVANCE_CONTROL + /* Query Average noise info */ + prDisconn->rNoise.u2Type = CMD_NOISE_HISTOGRAM_TYPE; + prDisconn->rNoise.u2Len = sizeof(struct CMD_NOISE_HISTOGRAM_REPORT); + prDisconn->rNoise.ucAction = CMD_NOISE_HISTOGRAM_GET; + wlanAdvCtrl(prAdapter, &prDisconn->rNoise, + sizeof(struct CMD_NOISE_HISTOGRAM_REPORT), &u4BufLen, FALSE); +#endif + + /* Query Beacon RSSI info */ + wlanQueryRssi(prAdapter, &prDisconn->rBcnRssi, + sizeof(prDisconn->rBcnRssi), &u4BufLen, FALSE); + + /* Store target sta rec and get wlan index */ + if (prAisBssInfo->prStaRecOfAP) { + kalMemCopy(&prDisconn->rStaRec, + prAisBssInfo->prStaRecOfAP, + sizeof(struct STA_RECORD)); + + ucWlanIndex = prAisBssInfo->prStaRecOfAP->ucWlanIndex; + } else if (!wlanGetWlanIdxByAddress(prAdapter, NULL, &ucWlanIndex)) { + DBGLOG(AIS, LOUD, "Null wlan index\n"); + goto leave; + } + + /* Query WTBL info */ + prDisconn->rHwInfo.u4Index = ucWlanIndex; + prDisconn->rHwInfo.rWtblRxCounter.fgRxCCSel = FALSE; + wlanQueryWlanInfo(prAdapter, &prDisconn->rHwInfo, + sizeof(struct PARAM_HW_WLAN_INFO), &u4BufLen, FALSE); + + /* Query Statistics info */ + prDisconn->rStaStatistics.ucResetCounter = FALSE; + pucMacAddr = wlanGetStaAddrByWlanIdx(prAdapter, ucWlanIndex); + + if (pucMacAddr) { + COPY_MAC_ADDR(prDisconn->rStaStatistics.aucMacAddr, + pucMacAddr); + + wlanQueryStaStatistics(prAdapter, + &prDisconn->rStaStatistics, + sizeof(struct PARAM_GET_STA_STATISTICS), + &u4BufLen, FALSE); + } + +leave: + g_DisconnInfoIdx = (g_DisconnInfoIdx + 1) % MAX_DISCONNECT_RECORD; + + /* Default value */ + kalMemZero(&g_rDisconnInfoTemp, sizeof(struct AIS_DISCONN_INFO_T)); + g_rDisconnInfoTemp.ucBcnTimeoutReason = 0xF; + g_rDisconnInfoTemp.u2DisassocSeqNum = 0xFFFF; +} +#endif /* CFG_DISCONN_DEBUG_FEATURE */ + +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN u_int8_t fgDelayIndication) +{ + struct BSS_INFO *prAisBssInfo; + + ASSERT(prAdapter); + + prAisBssInfo = prAdapter->prAisBssInfo; + cnmTimerStopTimer(prAdapter, + &prAdapter->rWifiVar.rAisFsmInfo.rSecModeChangeTimer); + nicPmIndicateBssAbort(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + +#if CFG_SUPPORT_ADHOC + if (prAisBssInfo->fgIsBeaconActivated) { + nicUpdateBeaconIETemplate(prAdapter, + IE_UPD_METHOD_DELETE_ALL, + prAdapter->prAisBssInfo->ucBssIndex, + 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 (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + + { + if (prAdapter->rWifiVar.ucTpTestMode != + ENUM_TP_TEST_MODE_NORMAL) + nicEnterTPTestMode(prAdapter, TEST_MODE_NONE); + +#if 0 + if (prAdapter->rWifiVar.ucSigmaTestMode) + nicEnterTPTestMode(prAdapter, TEST_MODE_NONE); +#endif + } + /* for NO TIM IE case */ + if (!prAisBssInfo->fgTIMPresent) { + nicConfigPowerSaveProfile(prAdapter, + prAisBssInfo->ucBssIndex, + Param_PowerModeFast_PSP, + FALSE, PS_CALLER_NO_TIM); + } + + 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); + prAdapter->rWifiVar.rAisFsmInfo. + prTargetBssDesc->fgIsConnected = FALSE; + prAdapter->rWifiVar.rAisFsmInfo. + prTargetBssDesc->fgIsConnecting = FALSE; + } + + if (fgDelayIndication) { + if (prAisBssInfo->eCurrentOPMode != OP_MODE_IBSS) + prAisBssInfo->fgHoldSameBssidForIBSS = FALSE; + } else { + prAisBssInfo->fgHoldSameBssidForIBSS = FALSE; + } + } else { + prAisBssInfo->fgHoldSameBssidForIBSS = FALSE; + } + +#if CFG_DISCONN_DEBUG_FEATURE + aisCollectDisconnInfo(prAdapter); +#endif + + /* 4 <4> Change Media State immediately. */ + if (prAisBssInfo->ucReasonOfDisconnect != + DISCONNECT_REASON_CODE_REASSOCIATION) { + aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + + /* 4 <4.1> sync. with firmware */ + nicUpdateBss(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + } + + 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 = (struct STA_RECORD *)NULL; + } + } +#if CFG_SUPPORT_ROAMING + roamingFsmRunEventAbort(prAdapter); + + /* clear pending roaming connection request */ + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_SEARCH, TRUE); + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, TRUE); +#endif /* CFG_SUPPORT_ROAMING */ + + /* 4 <6> Indicate Disconnected Event to Host */ + aisIndicationOfMediaStateToHost(prAdapter, + PARAM_MEDIA_STATE_DISCONNECTED, + fgDelayIndication); + + /* 4 <7> Trigger AIS FSM */ + aisFsmSteps(prAdapter, AIS_STATE_IDLE); +} /* end of aisFsmDisconnect() */ + +static void aisFsmRunEventScanDoneTimeOut(IN struct ADAPTER *prAdapter, + unsigned long ulParam) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct CONNECTION_SETTINGS *prConnSettings; + + DEBUGFUNC("aisFsmRunEventScanDoneTimeOut()"); + + ASSERT(prAdapter); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + DBGLOG(AIS, STATE, "aisFsmRunEventScanDoneTimeOut Current[%d] Seq=%u\n", + prAisFsmInfo->eCurrentState, prAisFsmInfo->ucSeqNumOfScanReq); + + /* try to stop scan in CONNSYS */ + aisFsmStateAbort_SCAN(prAdapter); +} /* end of aisFsmBGSleepTimeout() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will indicate an Event of "Background Scan Time-Out" + * to AIS FSM. + * @param[in] u4Param Unused timer parameter + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisFsmRunEventBGSleepTimeOut(IN struct ADAPTER *prAdapter, + unsigned long ulParamPtr) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + enum ENUM_AIS_STATE eNextState; + + DEBUGFUNC("aisFsmRunEventBGSleepTimeOut()"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + eNextState = prAisFsmInfo->eCurrentState; + + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_WAIT_FOR_NEXT_SCAN: + DBGLOG(AIS, LOUD, + "EVENT - SCAN TIMER: Idle End - Current Time = %u\n", + kalGetTimeTick()); + + eNextState = AIS_STATE_LOOKING_FOR; + + SET_NET_PWR_STATE_ACTIVE(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex); + + break; + + default: + break; + } + + /* Call aisFsmSteps() when we are going to change AIS STATE */ + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); +} /* end of aisFsmBGSleepTimeout() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will indicate an Event of "IBSS ALONE Time-Out" to + * AIS FSM. + * @param[in] u4Param Unused timer parameter + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisFsmRunEventIbssAloneTimeOut(IN struct ADAPTER *prAdapter, + unsigned long ulParamPtr) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + enum ENUM_AIS_STATE eNextState; + + DEBUGFUNC("aisFsmRunEventIbssAloneTimeOut()"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + eNextState = prAisFsmInfo->eCurrentState; + + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_IBSS_ALONE: + + /* There is no one participate in our AdHoc during this + * TIMEOUT Interval so go back to search for a valid + * IBSS again. + */ + + DBGLOG(AIS, LOUD, "EVENT-IBSS ALONE TIMER: Start pairing\n"); + + prAisFsmInfo->fgTryScan = TRUE; + + /* abort timer */ + aisFsmReleaseCh(prAdapter); + + /* Pull back to SEARCH to find candidate again */ + eNextState = AIS_STATE_SEARCH; + + break; + + default: + break; + } + + /* Call aisFsmSteps() when we are going to change AIS STATE */ + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); +} /* end of aisIbssAloneTimeOut() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will indicate an Event of "Join Time-Out" to AIS FSM. + * + * @param[in] u4Param Unused timer parameter + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisFsmRunEventJoinTimeout(IN struct ADAPTER *prAdapter, + unsigned long ulParamPtr) +{ + struct BSS_INFO *prAisBssInfo; + struct AIS_FSM_INFO *prAisFsmInfo; + enum ENUM_AIS_STATE eNextState; + OS_SYSTIME rCurrentTime; + + DEBUGFUNC("aisFsmRunEventJoinTimeout()"); + + prAisBssInfo = prAdapter->prAisBssInfo; + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + eNextState = prAisFsmInfo->eCurrentState; + + GET_CURRENT_SYSTIME(&rCurrentTime); + + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_JOIN: + DBGLOG(AIS, WARN, "EVENT- JOIN TIMEOUT\n"); + + /* 1. Do abort JOIN */ + aisFsmStateAbort_JOIN(prAdapter); + + /* 2. Increase Join Failure Count */ + /* Support AP Selection */ + aisAddBlacklist(prAdapter, prAisFsmInfo->prTargetBssDesc); + prAisFsmInfo->prTargetBssDesc->ucJoinFailureCount++; + + if (prAisFsmInfo->prTargetBssDesc->ucJoinFailureCount < + JOIN_MAX_RETRY_FAILURE_COUNT) { + /* 3.1 Retreat to AIS_STATE_SEARCH state for next try */ + eNextState = AIS_STATE_SEARCH; + } else if (prAisBssInfo->eConnectionState == + PARAM_MEDIA_STATE_CONNECTED) { + /* roaming cases */ + /* 3.2 Retreat to AIS_STATE_WAIT_FOR_NEXT_SCAN state for + * next try + */ + eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; + } else + if (prAisFsmInfo->rJoinReqTime != 0 && !CHECK_FOR_TIMEOUT + (rCurrentTime, prAisFsmInfo->rJoinReqTime, + SEC_TO_SYSTIME(AIS_JOIN_TIMEOUT))) { + /* 3.3 Retreat to AIS_STATE_WAIT_FOR_NEXT_SCAN state + * for next try + */ + eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; + } else { + /* 3.4 Retreat to AIS_STATE_JOIN_FAILURE to + * terminate join operation + */ + eNextState = AIS_STATE_JOIN_FAILURE; + } + + 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; + } + /* 3. Process for pending roaming scan */ + else if (aisFsmIsRequestPending + (prAdapter, AIS_REQUEST_ROAMING_SEARCH, TRUE) == TRUE) + eNextState = AIS_STATE_LOOKING_FOR; + /* 4. Process for pending roaming scan */ + else if (aisFsmIsRequestPending + (prAdapter, AIS_REQUEST_ROAMING_CONNECT, TRUE) == TRUE) + eNextState = AIS_STATE_SEARCH; + else if (aisFsmIsRequestPending + (prAdapter, AIS_REQUEST_REMAIN_ON_CHANNEL, + TRUE) == TRUE) + eNextState = AIS_STATE_REQ_REMAIN_ON_CHANNEL; + + break; + + default: + /* release channel */ + aisFsmReleaseCh(prAdapter); + break; + + } + + /* Call aisFsmSteps() when we are going to change AIS STATE */ + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); +} /* end of aisFsmRunEventJoinTimeout() */ + +void aisFsmRunEventDeauthTimeout(IN struct ADAPTER *prAdapter, + unsigned long ulParamPtr) +{ + aisDeauthXmitComplete(prAdapter, NULL, TX_RESULT_LIFE_TIMEOUT); +} + +void aisFsmRunEventSecModeChangeTimeout(IN struct ADAPTER *prAdapter, + unsigned long ulParamPtr) +{ + DBGLOG(AIS, WARN, + "Beacon security mode change timeout, trigger disconnect!\n"); + aisBssSecurityChanged(prAdapter); +} + +#if defined(CFG_TEST_MGMT_FSM) && (CFG_TEST_MGMT_FSM != 0) +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void aisTest(void) +{ + struct MSG_AIS_ABORT *prAisAbortMsg; + struct CONNECTION_SETTINGS *prConnSettings; + uint8_t aucSSID[] = "pci-11n"; + uint8_t ucSSIDLen = 7; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* Set Connection Request Issued Flag */ + prConnSettings->fgIsConnReqIssued = TRUE; + prConnSettings->ucSSIDLen = ucSSIDLen; + kalMemCopy(prConnSettings->aucSSID, aucSSID, ucSSIDLen); + + prAisAbortMsg = + (struct MSG_AIS_ABORT *)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_AIS_ABORT)); + if (!prAisAbortMsg) { + + ASSERT(0); /* Can't trigger SCAN FSM */ + return; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_HEM_AIS_FSM_ABORT; + + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *)prAisAbortMsg, + MSG_SEND_METHOD_BUF); + + wifi_send_msg(INDX_WIFI, MSG_ID_WIFI_IST, 0); +} +#endif /* CFG_TEST_MGMT_FSM */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is used to handle OID_802_11_BSSID_LIST_SCAN + * + * \param[in] prAdapter Pointer of ADAPTER_T + * \param[in] prSsid Pointer of SSID_T if specified + * \param[in] pucIe Pointer to buffer of extra information elements + * to be attached + * \param[in] u4IeLength Length of information elements + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void aisFsmScanRequest(IN struct ADAPTER *prAdapter, + IN struct PARAM_SSID *prSsid, IN uint8_t *pucIe, + IN uint32_t u4IeLength) +{ + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_INFO *prAisBssInfo; + struct AIS_FSM_INFO *prAisFsmInfo; + struct PARAM_SCAN_REQUEST_ADV *prScanRequest; + + DEBUGFUNC("aisFsmScanRequest()"); + + ASSERT(prAdapter); + ASSERT(u4IeLength <= MAX_IE_LENGTH); + + prAisBssInfo = prAdapter->prAisBssInfo; + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prScanRequest = &(prAisFsmInfo->rScanRequest); + + DBGLOG(SCN, TRACE, "eCurrentState=%d, fgIsScanReqIssued=%d\n", + prAisFsmInfo->eCurrentState, prConnSettings->fgIsScanReqIssued); + if (!prConnSettings->fgIsScanReqIssued) { + prConnSettings->fgIsScanReqIssued = TRUE; + scanInitEssResult(prAdapter); + kalMemZero(prScanRequest, + sizeof(struct PARAM_SCAN_REQUEST_ADV)); + prScanRequest->pucIE = prAisFsmInfo->aucScanIEBuf; + + if (prSsid == NULL) { + prScanRequest->u4SsidNum = 0; + } else { + prScanRequest->u4SsidNum = 1; + + COPY_SSID(prScanRequest->rSsid[0].aucSsid, + prScanRequest->rSsid[0].u4SsidLen, + prSsid->aucSsid, prSsid->u4SsidLen); + } + + if (u4IeLength > 0 && u4IeLength <= MAX_IE_LENGTH) { + prScanRequest->u4IELength = u4IeLength; + kalMemCopy(prScanRequest->pucIE, pucIe, u4IeLength); + } else { + prScanRequest->u4IELength = 0; + } + prScanRequest->ucScanType = SCAN_TYPE_ACTIVE_SCAN; + 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(SCN, 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(SCN, WARN, "Scan Request dropped. (state: %d)\n", + prAisFsmInfo->eCurrentState); + } + +} /* end of aisFsmScanRequest() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is used to handle OID_802_11_BSSID_LIST_SCAN + * + * \param[in] prAdapter Pointer of ADAPTER_T + * \param[in] prRequestIn scan request + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void +aisFsmScanRequestAdv(IN struct ADAPTER *prAdapter, + IN struct PARAM_SCAN_REQUEST_ADV *prRequestIn) +{ + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_INFO *prAisBssInfo; + struct AIS_FSM_INFO *prAisFsmInfo; + struct PARAM_SCAN_REQUEST_ADV *prScanRequest; + + DEBUGFUNC("aisFsmScanRequestAdv()"); + + ASSERT(prAdapter); + if (!prRequestIn) { + log_dbg(SCN, WARN, "Scan request is NULL\n"); + return; + } + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prAisBssInfo = prAdapter->prAisBssInfo; + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prScanRequest = &(prAisFsmInfo->rScanRequest); + + DBGLOG(SCN, TRACE, "eCurrentState=%d, fgIsScanReqIssued=%d\n", + prAisFsmInfo->eCurrentState, prConnSettings->fgIsScanReqIssued); + + if (!prConnSettings->fgIsScanReqIssued) { + prConnSettings->fgIsScanReqIssued = TRUE; + scanInitEssResult(prAdapter); + + kalMemCopy(prScanRequest, prRequestIn, + sizeof(struct PARAM_SCAN_REQUEST_ADV)); + prScanRequest->pucIE = prAisFsmInfo->aucScanIEBuf; + + if (prRequestIn->u4IELength > 0 && + prRequestIn->u4IELength <= MAX_IE_LENGTH) { + prScanRequest->u4IELength = prRequestIn->u4IELength; + kalMemCopy(prScanRequest->pucIE, prRequestIn->pucIE, + prScanRequest->u4IELength); + } else { + prScanRequest->u4IELength = 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(SCN, 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 if (prAdapter->rWifiVar.rRmReqParams.rBcnRmParam.eState == + RM_ON_GOING) { + struct NORMAL_SCAN_PARAMS *prNormalScan = + &prAdapter->rWifiVar.rRmReqParams.rBcnRmParam + .rNormalScan; + struct PARAM_SCAN_REQUEST_ADV *prScanRequest = + &prNormalScan->rScanRequest; + + prNormalScan->fgExist = TRUE; + kalMemCopy(prScanRequest, prRequestIn, + sizeof(struct PARAM_SCAN_REQUEST_ADV)); + if (prRequestIn->u4IELength > 0 && + prRequestIn->u4IELength <= MAX_IE_LENGTH) { + prScanRequest->u4IELength = + prRequestIn->u4IELength; + kalMemCopy(prNormalScan->aucScanIEBuf, + prRequestIn->pucIE, + prRequestIn->u4IELength); + } else { + prScanRequest->u4IELength = 0; + } + + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); + DBGLOG(AIS, INFO, + "BCN REQ: Buffer normal scan while Beacon request is scanning\n"); + } else { + DBGLOG(SCN, WARN, "Scan Request dropped. (state: %d)\n", + prAisFsmInfo->eCurrentState); + } + +} /* end of aisFsmScanRequestAdv() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is invoked when CNM granted channel privilege + * + * \param[in] prAdapter Pointer of ADAPTER_T + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void aisFsmRunEventChGrant(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct BSS_INFO *prAisBssInfo; + struct AIS_FSM_INFO *prAisFsmInfo; + struct MSG_CH_GRANT *prMsgChGrant; + uint8_t ucTokenID; + uint32_t u4GrantInterval; + uint32_t u4Entry = 0; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prAisBssInfo = prAdapter->prAisBssInfo; + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prMsgChGrant = (struct MSG_CH_GRANT *)prMsgHdr; + + ucTokenID = prMsgChGrant->ucTokenID; + u4GrantInterval = prMsgChGrant->u4GrantInterval; + +#if CFG_SISO_SW_DEVELOP + /* Driver record granted CH in BSS info */ + prAisBssInfo->fgIsGranted = TRUE; + prAisBssInfo->eBandGranted = prMsgChGrant->eRfBand; + prAisBssInfo->ucPrimaryChannelGranted = prMsgChGrant->ucPrimaryChannel; +#endif + + /* 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 */ + /* Three cases can switch to join state: + ** 1. There's an available PMKSA in wpa_supplicant + ** 2. found okc pmkid entry for this BSS + ** 3. current state is disconnected. In this case, + ** supplicant may not get a valid pmksa, + ** so no pmkid will be passed to driver, so we no need + ** to wait pmkid anyway. + */ + if (!prAdapter->rWifiVar.rConnSettings.fgOkcPmksaReady || + (rsnSearchPmkidEntry + (prAdapter, prAisFsmInfo->prTargetBssDesc->aucBSSID, + &u4Entry) + && prAdapter->rWifiVar. + rAisSpecificBssInfo.arPmkidCache[u4Entry].fgPmkidExist)) + aisFsmSteps(prAdapter, AIS_STATE_JOIN); + + prAisFsmInfo->fgIsChannelGranted = TRUE; + } else if (prAisFsmInfo->eCurrentState == + AIS_STATE_REQ_REMAIN_ON_CHANNEL + && prAisFsmInfo->ucSeqNumOfChReq == ucTokenID) { + /* 2. channel privilege has been approved */ + prAisFsmInfo->u4ChGrantedInterval = u4GrantInterval; + +#if CFG_SUPPORT_NCHO + if (prAdapter->rNchoInfo.fgECHOEnabled == TRUE && + prAdapter->rNchoInfo.fgIsSendingAF == TRUE && + prAdapter->rNchoInfo.fgChGranted == FALSE) { + DBGLOG(INIT, TRACE, + "NCHO complete rAisChGrntComp trace time is %u\n", + kalGetTimeTick()); + prAdapter->rNchoInfo.fgChGranted = TRUE; + complete(&prAdapter->prGlueInfo->rAisChGrntComp); + } +#endif + /* 3.1 set timeout timer in cases upper layer + * cancel_remain_on_channel never comes + */ + cnmTimerStartTimer(prAdapter, + &prAisFsmInfo->rChannelTimeoutTimer, + prAisFsmInfo->u4ChGrantedInterval); + + /* 3.2 switch to remain_on_channel state */ + aisFsmSteps(prAdapter, AIS_STATE_REMAIN_ON_CHANNEL); + + /* 3.3. indicate upper layer for channel ready */ + kalReadyOnChannel(prAdapter->prGlueInfo, + prAisFsmInfo->rChReqInfo.u8Cookie, + prAisFsmInfo->rChReqInfo.eBand, + prAisFsmInfo->rChReqInfo.eSco, + prAisFsmInfo->rChReqInfo.ucChannelNum, + prAisFsmInfo->rChReqInfo.u4DurationMs); + + prAisFsmInfo->fgIsChannelGranted = TRUE; + } else { /* mismatched grant */ + /* 2. return channel privilege to CNM immediately */ + aisFsmReleaseCh(prAdapter); + } +} /* end of aisFsmRunEventChGrant() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is to inform CNM that channel privilege + * has been released + * + * \param[in] prAdapter Pointer of ADAPTER_T + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void aisFsmReleaseCh(IN struct ADAPTER *prAdapter) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct MSG_CH_ABORT *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 = + (struct MSG_CH_ABORT *)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct + MSG_CH_ABORT)); + if (!prMsgChAbort) { + ASSERT(0); /* Can't release Channel to CNM */ + return; + } + + prMsgChAbort->rMsgHdr.eMsgId = MID_MNY_CNM_CH_ABORT; + prMsgChAbort->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + prMsgChAbort->ucTokenID = prAisFsmInfo->ucSeqNumOfChReq; +#if CFG_SUPPORT_DBDC + prMsgChAbort->eDBDCBand = ENUM_BAND_AUTO; +#endif /*CFG_SUPPORT_DBDC */ + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *)prMsgChAbort, + MSG_SEND_METHOD_BUF); + } +} /* end of aisFsmReleaseCh() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is to inform AIS that corresponding beacon has not + * been received for a while and probing is not successful + * + * \param[in] prAdapter Pointer of ADAPTER_T + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void aisBssBeaconTimeout(IN struct ADAPTER *prAdapter) +{ + struct BSS_INFO *prAisBssInfo; + u_int8_t fgDoAbortIndication = FALSE; + struct CONNECTION_SETTINGS *prConnSettings; + + ASSERT(prAdapter); + + prAisBssInfo = prAdapter->prAisBssInfo; + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* 4 <1> Diagnose Connection for Beacon Timeout Event */ + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + struct STA_RECORD *prStaRec = + prAisBssInfo->prStaRecOfAP; + + if (prStaRec) + fgDoAbortIndication = TRUE; + + } else if (prAisBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + fgDoAbortIndication = TRUE; + } + } + /* 4 <2> invoke abort handler */ + if (fgDoAbortIndication) { +#if CFG_DISCONN_DEBUG_FEATURE + g_rDisconnInfoTemp.ucTrigger = DISCONNECT_TRIGGER_PASSIVE; +#endif + prConnSettings->fgIsDisconnectedByNonRequest = FALSE; + if (prConnSettings->eReConnectLevel < + RECONNECT_LEVEL_USER_SET) { + prConnSettings->eReConnectLevel = + RECONNECT_LEVEL_BEACON_TIMEOUT; +#if CFG_SUPPORT_CFG80211_AUTH + prConnSettings->fgIsConnReqIssued = FALSE; +#else + prConnSettings->fgIsConnReqIssued = TRUE; +#endif + } + DBGLOG(AIS, EVENT, "aisBssBeaconTimeout\n"); + aisFsmStateAbort(prAdapter, DISCONNECT_REASON_CODE_RADIO_LOST, + TRUE); + } +} /* end of aisBssBeaconTimeout() */ + +void aisBssSecurityChanged(struct ADAPTER *prAdapter) +{ + prAdapter->rWifiVar.rConnSettings.fgIsDisconnectedByNonRequest = TRUE; + aisFsmStateAbort(prAdapter, DISCONNECT_REASON_CODE_DEAUTHENTICATED, + FALSE); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 aisBssLinkDown(IN struct ADAPTER *prAdapter) +{ + struct BSS_INFO *prAisBssInfo; + u_int8_t fgDoAbortIndication = FALSE; + struct CONNECTION_SETTINGS *prConnSettings; + + ASSERT(prAdapter); + + prAisBssInfo = prAdapter->prAisBssInfo; + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* 4 <1> Diagnose Connection for Beacon Timeout Event */ + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + struct STA_RECORD *prStaRec = + prAisBssInfo->prStaRecOfAP; + + if (prStaRec) + fgDoAbortIndication = TRUE; + + } else if (prAisBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + fgDoAbortIndication = TRUE; + } + } + /* 4 <2> invoke abort handler */ + if (fgDoAbortIndication) { +#if CFG_DISCONN_DEBUG_FEATURE + g_rDisconnInfoTemp.ucTrigger = DISCONNECT_TRIGGER_ACTIVE; +#endif + prConnSettings->fgIsDisconnectedByNonRequest = TRUE; + DBGLOG(AIS, EVENT, "aisBssLinkDown\n"); + aisFsmStateAbort(prAdapter, + DISCONNECT_REASON_CODE_DISASSOCIATED, FALSE); + } + + /* kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + * WLAN_STATUS_SCAN_COMPLETE, NULL, 0); + */ +} /* 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +aisDeauthXmitComplete(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + + ASSERT(prAdapter); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + if (rTxDoneStatus == TX_RESULT_SUCCESS) + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rDeauthDoneTimer); + + if (prAisFsmInfo->eCurrentState == AIS_STATE_DISCONNECTING) { + DBGLOG(AIS, EVENT, "aisDeauthXmitComplete\n"); + if (rTxDoneStatus != TX_RESULT_DROPPED_IN_DRIVER + && rTxDoneStatus != TX_RESULT_QUEUE_CLEARANCE) +#if CFG_SUPPORT_CFG80211_AUTH + aisFsmStateAbort(prAdapter, + DISCONNECT_REASON_CODE_DEAUTHENTICATED, + FALSE); +#else + aisFsmStateAbort(prAdapter, + DISCONNECT_REASON_CODE_NEW_CONNECTION, + FALSE); +#endif + } 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 struct ADAPTER *prAdapter, + uint32_t u4ReqScan) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct CONNECTION_SETTINGS *prConnSettings; + enum ENUM_AIS_REQUEST_TYPE eAisRequest = AIS_REQUEST_NUM; + + 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; + + /* TODO: Stop roaming event in FW */ +#if CFG_SUPPORT_WFD +#if CFG_ENABLE_WIFI_DIRECT + { + /* Check WFD is running */ + struct WFD_CFG_SETTINGS *prWfdCfgSettings = + (struct WFD_CFG_SETTINGS *)NULL; + + prWfdCfgSettings = &(prAdapter->rWifiVar.rWfdConfigureSettings); + if ((prWfdCfgSettings->ucWfdEnable != 0)) { + DBGLOG(ROAMING, INFO, + "WFD is running. Stop roaming.\n"); + roamingFsmRunEventRoam(prAdapter); + roamingFsmRunEventFail(prAdapter, + ROAMING_FAIL_REASON_NOCANDIDATE); + return; + } + } +#endif +#endif + + /* results are still new */ + if (!u4ReqScan) { + roamingFsmRunEventRoam(prAdapter); + eAisRequest = AIS_REQUEST_ROAMING_CONNECT; + } else { + if (prAisFsmInfo->eCurrentState == AIS_STATE_ONLINE_SCAN + || prAisFsmInfo->eCurrentState == AIS_STATE_LOOKING_FOR) { + eAisRequest = AIS_REQUEST_ROAMING_CONNECT; + } else { + eAisRequest = AIS_REQUEST_ROAMING_SEARCH; + } + } + + if (prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR + && prAisFsmInfo->fgIsInfraChannelFinished == TRUE) { + if (eAisRequest == AIS_REQUEST_ROAMING_SEARCH) { + prAisFsmInfo->fgTargetChnlScanIssued = TRUE; + aisFsmSteps(prAdapter, AIS_STATE_LOOKING_FOR); + } else + aisFsmSteps(prAdapter, AIS_STATE_SEARCH); + } else { + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_SEARCH, + TRUE); + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, + TRUE); + + aisFsmInsertRequest(prAdapter, eAisRequest); + } +} /* end of aisFsmRunEventRoamingDiscovery() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Update the time of ScanDone for roaming and transit to Roam state. + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +enum ENUM_AIS_STATE aisFsmRoamingScanResultsUpdate(IN struct ADAPTER *prAdapter) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct ROAMING_INFO *prRoamingFsmInfo; + enum ENUM_AIS_STATE eNextState; + + DBGLOG(AIS, LOUD, "->aisFsmRoamingScanResultsUpdate()\n"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prRoamingFsmInfo = + (struct ROAMING_INFO *)&(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 struct ADAPTER *prAdapter, + IN struct STA_RECORD *prTargetStaRec) +{ + struct BSS_INFO *prAisBssInfo; + + DBGLOG(AIS, EVENT, "aisFsmRoamingDisconnectPrevAP()"); + + ASSERT(prAdapter); + + prAisBssInfo = prAdapter->prAisBssInfo; + if (prAisBssInfo->prStaRecOfAP != prTargetStaRec) + wmmNotifyDisconnected(prAdapter); + + nicPmIndicateBssAbort(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + + /* 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 (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + struct PARAM_SSID rSsid; + struct BSS_DESC *prBssDesc = NULL; + + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, prAisBssInfo->aucSSID, + prAisBssInfo->ucSSIDLen); + prBssDesc = + scanSearchBssDescByBssidAndSsid(prAdapter, + prAisBssInfo->aucBSSID, + TRUE, &rSsid); + if (prBssDesc) { + prBssDesc->fgIsConnected = FALSE; + prBssDesc->fgIsConnecting = FALSE; + } + } + + /* 4 <4> Change Media State immediately. */ + aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECT_PREV); + + /* 4 <4.1> sync. with firmware */ + /* Virtial BSSID */ + prTargetStaRec->ucBssIndex = (prAdapter->ucHwBssIdNum + 1); + nicUpdateBss(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + + secRemoveBssBcEntry(prAdapter, prAisBssInfo, TRUE); + prTargetStaRec->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + /* before deactivate previous AP, should move its pending MSDUs + ** to the new AP + */ + if (prAisBssInfo->prStaRecOfAP) + if (prAisBssInfo->prStaRecOfAP != prTargetStaRec && + prAisBssInfo->prStaRecOfAP->fgIsInUse) { + qmMoveStaTxQueue(prAisBssInfo->prStaRecOfAP, + prTargetStaRec); + /* Currently, firmware just drop all previous AP's + ** data packets, need to handle waiting tx done + ** status packets so driver no + */ +#if 0 + nicTxHandleRoamingDone(prAdapter, + prAisBssInfo->prStaRecOfAP, + prTargetStaRec); +#endif + cnmStaRecFree(prAdapter, prAisBssInfo->prStaRecOfAP); + } else + DBGLOG(AIS, WARN, "prStaRecOfAP is in use %d\n", + prAisBssInfo->prStaRecOfAP->fgIsInUse); + else + DBGLOG(AIS, WARN, + "NULL pointer of prAisBssInfo->prStaRecOfAP\n"); +} /* 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 struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct SW_RFB *prAssocRspSwRfb) +{ + struct BSS_INFO *prAisBssInfo; + + DBGLOG(AIS, LOUD, "aisUpdateBssInfoForRoamingAP()"); + + ASSERT(prAdapter); + + prAisBssInfo = prAdapter->prAisBssInfo; + + /* 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)) { + /* before deactivate previous AP, should move its pending MSDUs + ** to the new AP + */ + qmMoveStaTxQueue(prAisBssInfo->prStaRecOfAP, prStaRec); + /* cnmStaRecChangeState(prAdapter, prAisBssInfo->prStaRecOfAP, + ** STA_STATE_1); + */ + cnmStaRecFree(prAdapter, prAisBssInfo->prStaRecOfAP); + } + + /* 4 <1.4> Update BSS_INFO_T */ + aisUpdateBssInfoForJOIN(prAdapter, prStaRec, prAssocRspSwRfb); + + /* 4 <1.3> Activate current AP's STA_RECORD_T in Driver. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + /* 4 <1.6> Indicate Connected Event to Host immediately. */ + /* Require BSSID, Association ID, Beacon Interval.. + * from AIS_BSS_INFO_T + */ + aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, + FALSE); +} /* end of aisFsmRoamingUpdateBss() */ + +#endif /* CFG_SUPPORT_ROAMING */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Check if there is any pending request and remove it (optional) + * + * @param prAdapter + * eReqType + * bRemove + * + * @return TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +u_int8_t aisFsmIsRequestPending(IN struct ADAPTER *prAdapter, + IN enum ENUM_AIS_REQUEST_TYPE eReqType, + IN u_int8_t bRemove) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct AIS_REQ_HDR *prPendingReqHdr, *prPendingReqHdrNext; + + ASSERT(prAdapter); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + /* traverse through pending request list */ + LINK_FOR_EACH_ENTRY_SAFE(prPendingReqHdr, + prPendingReqHdrNext, + &(prAisFsmInfo->rPendingReqList), rLinkEntry, + struct AIS_REQ_HDR) { + /* 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 + */ +/*----------------------------------------------------------------------------*/ +struct AIS_REQ_HDR *aisFsmGetNextRequest(IN struct ADAPTER *prAdapter) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct AIS_REQ_HDR *prPendingReqHdr; + + ASSERT(prAdapter); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + LINK_REMOVE_HEAD(&(prAisFsmInfo->rPendingReqList), prPendingReqHdr, + struct AIS_REQ_HDR *); + + return prPendingReqHdr; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Insert a new request + * + * @param prAdapter + * eReqType + * + * @return TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +u_int8_t aisFsmInsertRequest(IN struct ADAPTER *prAdapter, + IN enum ENUM_AIS_REQUEST_TYPE eReqType) +{ + struct AIS_REQ_HDR *prAisReq; + struct AIS_FSM_INFO *prAisFsmInfo; + + ASSERT(prAdapter); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + prAisReq = + (struct AIS_REQ_HDR *)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct AIS_REQ_HDR)); + + if (!prAisReq) { + ASSERT(0); /* Can't generate new message */ + return FALSE; + } + DBGLOG(AIS, INFO, "aisFsmInsertRequest\n"); + + prAisReq->eReqType = eReqType; + + /* attach request into pending request list */ + LINK_INSERT_TAIL(&prAisFsmInfo->rPendingReqList, &prAisReq->rLinkEntry); + + DBGLOG(AIS, TRACE, "eCurrentState=%d, eReqType=%d, u4NumElem=%d\n", + prAisFsmInfo->eCurrentState, eReqType, + prAisFsmInfo->rPendingReqList.u4NumElem); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Flush all pending requests + * + * @param prAdapter + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void aisFsmFlushRequest(IN struct ADAPTER *prAdapter) +{ + struct AIS_REQ_HDR *prAisReq; + + ASSERT(prAdapter); + + while ((prAisReq = aisFsmGetNextRequest(prAdapter)) != NULL) + cnmMemFree(prAdapter, prAisReq); +} + +void aisFsmRunEventRemainOnChannel(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_REMAIN_ON_CHANNEL *prRemainOnChannel; + struct AIS_FSM_INFO *prAisFsmInfo; + struct CONNECTION_SETTINGS *prConnSettings; + + DEBUGFUNC("aisFsmRunEventRemainOnChannel()"); + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + prRemainOnChannel = (struct MSG_REMAIN_ON_CHANNEL *)prMsgHdr; + + /* record parameters */ + prAisFsmInfo->rChReqInfo.eBand = prRemainOnChannel->eBand; + prAisFsmInfo->rChReqInfo.eSco = prRemainOnChannel->eSco; + prAisFsmInfo->rChReqInfo.ucChannelNum = prRemainOnChannel->ucChannelNum; + prAisFsmInfo->rChReqInfo.u4DurationMs = prRemainOnChannel->u4DurationMs; + prAisFsmInfo->rChReqInfo.u8Cookie = prRemainOnChannel->u8Cookie; + + if ((prAisFsmInfo->eCurrentState == AIS_STATE_IDLE) || + (prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR + && prAisFsmInfo->fgIsInfraChannelFinished == TRUE)) { + /* transit to next state */ + aisFsmSteps(prAdapter, AIS_STATE_REQ_REMAIN_ON_CHANNEL); + } else { + aisFsmInsertRequest(prAdapter, AIS_REQUEST_REMAIN_ON_CHANNEL); + } + + /* free messages */ + cnmMemFree(prAdapter, prMsgHdr); +} + +void aisFsmRunEventCancelRemainOnChannel(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prAisBssInfo; + struct MSG_CANCEL_REMAIN_ON_CHANNEL *prCancelRemainOnChannel; + + ASSERT(prAdapter); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = prAdapter->prAisBssInfo; + + prCancelRemainOnChannel = + (struct MSG_CANCEL_REMAIN_ON_CHANNEL *)prMsgHdr; + + /* 1. Check the cookie first */ + if (prCancelRemainOnChannel->u8Cookie == + prAisFsmInfo->rChReqInfo.u8Cookie) { + + /* 2. release channel privilege/request */ + if (prAisFsmInfo->eCurrentState == + AIS_STATE_REQ_REMAIN_ON_CHANNEL) { + /* 2.1 elease channel */ + aisFsmReleaseCh(prAdapter); + } else if (prAisFsmInfo->eCurrentState == + AIS_STATE_REMAIN_ON_CHANNEL) { + /* 2.1 release channel */ + aisFsmReleaseCh(prAdapter); + + /* 2.2 stop channel timeout timer */ + cnmTimerStopTimer(prAdapter, + &prAisFsmInfo->rChannelTimeoutTimer); + } + + /* 3. clear pending request of remain_on_channel */ + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_REMAIN_ON_CHANNEL, + TRUE); + + /* 4. decide which state to retreat */ + if (prAisFsmInfo->eCurrentState == + AIS_STATE_REQ_REMAIN_ON_CHANNEL + || prAisFsmInfo->eCurrentState == + AIS_STATE_REMAIN_ON_CHANNEL) { + if (prAisBssInfo->eConnectionState == + PARAM_MEDIA_STATE_CONNECTED) + aisFsmSteps(prAdapter, AIS_STATE_NORMAL_TR); + else + aisFsmSteps(prAdapter, AIS_STATE_IDLE); + } + } + + /* 5. free message */ + cnmMemFree(prAdapter, prMsgHdr); +} + +void aisFsmRunEventMgmtFrameTx(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct MSG_MGMT_TX_REQUEST *prMgmtTxMsg = + (struct MSG_MGMT_TX_REQUEST *)NULL; + + do { + ASSERT((prAdapter != NULL) && (prMsgHdr != NULL)); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + if (prAisFsmInfo == NULL) + break; + + prMgmtTxMsg = (struct MSG_MGMT_TX_REQUEST *)prMsgHdr; + + aisFuncTxMgmtFrame(prAdapter, + &prAisFsmInfo->rMgmtTxInfo, + prMgmtTxMsg->prMgmtMsduInfo, + prMgmtTxMsg->u8Cookie); + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* aisFsmRunEventMgmtFrameTx */ + +#if CFG_SUPPORT_NCHO +void aisFsmRunEventNchoActionFrameTx(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prAisBssInfo = (struct BSS_INFO *)NULL; + struct MSG_MGMT_TX_REQUEST *prMgmtTxMsg = + (struct MSG_MGMT_TX_REQUEST *)NULL; + struct MSDU_INFO *prMgmtFrame = (struct MSDU_INFO *)NULL; + struct _ACTION_VENDOR_SPEC_FRAME_T *prVendorSpec = NULL; + uint8_t *pucFrameBuf = (uint8_t *) NULL; + struct _NCHO_INFO_T *prNchoInfo = NULL; + uint16_t u2PktLen = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + DBGLOG(REQ, TRACE, "NCHO in aisFsmRunEventNchoActionFrameTx\n"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prNchoInfo = &(prAdapter->rNchoInfo); + prAisBssInfo = + &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS]); + + if (prAisFsmInfo == NULL) + break; + + prMgmtTxMsg = (struct MSG_MGMT_TX_REQUEST *)prMsgHdr; + u2PktLen = + (uint16_t) OFFSET_OF(struct _ACTION_VENDOR_SPEC_FRAME_T, + aucElemInfo[0]) + + prNchoInfo->rParamActionFrame.i4len + MAC_TX_RESERVED_FIELD; + prMgmtFrame = cnmMgtPktAlloc(prAdapter, u2PktLen); + if (prMgmtFrame == NULL) { + ASSERT(FALSE); + DBGLOG(REQ, ERROR, + "NCHO there is no memory for prMgmtFrame\n"); + break; + } + prMgmtTxMsg->prMgmtMsduInfo = prMgmtFrame; + + pucFrameBuf = + (uint8_t *) ((unsigned long)prMgmtFrame->prPacket + + MAC_TX_RESERVED_FIELD); + prVendorSpec = + (struct _ACTION_VENDOR_SPEC_FRAME_T *)pucFrameBuf; + prVendorSpec->u2FrameCtrl = MAC_FRAME_ACTION; + prVendorSpec->u2Duration = 0; + prVendorSpec->u2SeqCtrl = 0; + COPY_MAC_ADDR(prVendorSpec->aucDestAddr, + prNchoInfo->rParamActionFrame.aucBssid); + COPY_MAC_ADDR(prVendorSpec->aucSrcAddr, + prAisBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prVendorSpec->aucBSSID, prAisBssInfo->aucBSSID); + + kalMemCopy(prVendorSpec->aucElemInfo, + prNchoInfo->rParamActionFrame.aucData, + prNchoInfo->rParamActionFrame.i4len); + + prMgmtFrame->u2FrameLength = u2PktLen; + + aisFuncTxMgmtFrame(prAdapter, + &prAisFsmInfo->rMgmtTxInfo, + prMgmtTxMsg->prMgmtMsduInfo, + prMgmtTxMsg->u8Cookie); + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* aisFsmRunEventNchoActionFrameTx */ +#endif + +void aisFsmRunEventChannelTimeout(IN struct ADAPTER *prAdapter, + unsigned long ulParamPtr) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct BSS_INFO *prAisBssInfo; + + DEBUGFUNC("aisFsmRunEventRemainOnChannel()"); + + ASSERT(prAdapter); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = prAdapter->prAisBssInfo; + + if (prAisFsmInfo->eCurrentState == AIS_STATE_REMAIN_ON_CHANNEL) { + /* 1. release channel */ + aisFsmReleaseCh(prAdapter); + + /* 2. stop channel timeout timer */ + cnmTimerStopTimer(prAdapter, + &prAisFsmInfo->rChannelTimeoutTimer); + + /* 3. expiration indication to upper layer */ + kalRemainOnChannelExpired(prAdapter->prGlueInfo, + prAisFsmInfo->rChReqInfo.u8Cookie, + prAisFsmInfo->rChReqInfo.eBand, + prAisFsmInfo->rChReqInfo.eSco, + prAisFsmInfo-> + rChReqInfo.ucChannelNum); + + /* 4. decide which state to retreat */ + if (prAisBssInfo->eConnectionState == + PARAM_MEDIA_STATE_CONNECTED) + aisFsmSteps(prAdapter, AIS_STATE_NORMAL_TR); + else + aisFsmSteps(prAdapter, AIS_STATE_IDLE); + + } else { + DBGLOG(AIS, WARN, + "Unexpected remain_on_channel timeout event\n"); + DBGLOG(AIS, STATE, "CURRENT State: [%s]\n", + apucDebugAisState[prAisFsmInfo->eCurrentState]); + } +} + +uint32_t +aisFsmRunEventMgmtFrameTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + struct AIS_FSM_INFO *prAisFsmInfo; + struct AIS_MGMT_TX_REQ_INFO *prMgmtTxReqInfo = + (struct AIS_MGMT_TX_REQ_INFO *)NULL; + u_int8_t fgIsSuccess = FALSE; + + do { + ASSERT((prAdapter != NULL) && (prMsduInfo != NULL)); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prMgmtTxReqInfo = &(prAisFsmInfo->rMgmtTxInfo); + + if (rTxDoneStatus != TX_RESULT_SUCCESS) { + DBGLOG(AIS, ERROR, "Mgmt Frame TX Fail, Status:%d.\n", + rTxDoneStatus); + } else { + fgIsSuccess = TRUE; +#if CFG_SUPPORT_NCHO + if (prAdapter->rNchoInfo.fgECHOEnabled == TRUE && + prAdapter->rNchoInfo.fgIsSendingAF == TRUE && + prAdapter->rNchoInfo.fgChGranted == TRUE) { + prAdapter->rNchoInfo.fgIsSendingAF = FALSE; + DBGLOG(AIS, TRACE, "NCHO action frame tx done"); + } +#endif + } + + if (prMgmtTxReqInfo->prMgmtTxMsdu == prMsduInfo) { + kalIndicateMgmtTxStatus(prAdapter->prGlueInfo, + prMgmtTxReqInfo->u8Cookie, + fgIsSuccess, + prMsduInfo->prPacket, + (uint32_t) + prMsduInfo->u2FrameLength); + + prMgmtTxReqInfo->prMgmtTxMsdu = NULL; + } + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; + +} /* aisFsmRunEventMgmtFrameTxDone */ + +void aisFsmRunEventSetOkcPmk(IN struct ADAPTER *prAdapter) +{ + struct AIS_FSM_INFO *prAisFsmInfo = &prAdapter->rWifiVar.rAisFsmInfo; + + prAdapter->rWifiVar.rConnSettings.fgOkcPmksaReady = TRUE; + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rWaitOkcPMKTimer); + if (prAisFsmInfo->eCurrentState == AIS_STATE_REQ_CHANNEL_JOIN && + prAisFsmInfo->fgIsChannelGranted) + aisFsmSteps(prAdapter, AIS_STATE_JOIN); +} + +static void aisFsmSetOkcTimeout(IN struct ADAPTER *prAdapter, + unsigned long ulParam) +{ + struct AIS_FSM_INFO *prAisFsmInfo = &prAdapter->rWifiVar.rAisFsmInfo; + + DBGLOG(AIS, WARN, + "Wait OKC PMKID timeout, current state[%d],fgIsChannelGranted=%d\n", + prAisFsmInfo->eCurrentState, prAisFsmInfo->fgIsChannelGranted); + if (prAisFsmInfo->eCurrentState == AIS_STATE_REQ_CHANNEL_JOIN + && prAisFsmInfo->fgIsChannelGranted) + aisFsmSteps(prAdapter, AIS_STATE_JOIN); +} + +uint32_t +aisFuncTxMgmtFrame(IN struct ADAPTER *prAdapter, + IN struct AIS_MGMT_TX_REQ_INFO *prMgmtTxReqInfo, + IN struct MSDU_INFO *prMgmtTxMsdu, IN uint64_t u8Cookie) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct MSDU_INFO *prTxMsduInfo = (struct MSDU_INFO *)NULL; + struct WLAN_MAC_HEADER *prWlanHdr = (struct WLAN_MAC_HEADER *)NULL; + struct STA_RECORD *prStaRec = (struct STA_RECORD *)NULL; + + do { + ASSERT((prAdapter != NULL) && (prMgmtTxReqInfo != NULL)); + + if (prMgmtTxReqInfo->fgIsMgmtTxRequested) { + + /* 1. prMgmtTxReqInfo->prMgmtTxMsdu != NULL */ + /* Packet on driver, not done yet, drop it. */ + prTxMsduInfo = prMgmtTxReqInfo->prMgmtTxMsdu; + if (prTxMsduInfo != NULL) { + + kalIndicateMgmtTxStatus(prAdapter->prGlueInfo, + prMgmtTxReqInfo->u8Cookie, + FALSE, + prTxMsduInfo->prPacket, + (uint32_t) + prTxMsduInfo->u2FrameLength); + + /* Leave it to TX Done handler. */ + /* cnmMgtPktFree(prAdapter, prTxMsduInfo); */ + prMgmtTxReqInfo->prMgmtTxMsdu = NULL; + } + /* 2. prMgmtTxReqInfo->prMgmtTxMsdu == NULL */ + /* Packet transmitted, wait tx done. (cookie issue) */ + } + + ASSERT(prMgmtTxReqInfo->prMgmtTxMsdu == NULL); + + prWlanHdr = + (struct WLAN_MAC_HEADER *)((unsigned long) + prMgmtTxMsdu->prPacket + + MAC_TX_RESERVED_FIELD); + prStaRec = + cnmGetStaRecByAddress(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, + prWlanHdr->aucAddr1); + + TX_SET_MMPDU(prAdapter, + prMgmtTxMsdu, + (prStaRec != + NULL) ? (prStaRec-> + ucBssIndex) + : (prAdapter->prAisBssInfo->ucBssIndex), + (prStaRec != + NULL) ? (prStaRec->ucIndex) + : (STA_REC_INDEX_NOT_FOUND), + WLAN_MAC_MGMT_HEADER_LEN, + prMgmtTxMsdu->u2FrameLength, + aisFsmRunEventMgmtFrameTxDone, + MSDU_RATE_MODE_AUTO); + prMgmtTxReqInfo->u8Cookie = u8Cookie; + prMgmtTxReqInfo->prMgmtTxMsdu = prMgmtTxMsdu; + prMgmtTxReqInfo->fgIsMgmtTxRequested = TRUE; + + nicTxConfigPktControlFlag(prMgmtTxMsdu, + MSDU_CONTROL_FLAG_FORCE_TX, TRUE); + + /* send to TX queue */ + nicTxEnqueueMsdu(prAdapter, prMgmtTxMsdu); + + } while (FALSE); + + return rWlanStatus; +} /* aisFuncTxMgmtFrame */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will validate the Rx Action Frame and indicate to uppoer + * layer if the specified conditions were matched. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] prSwRfb Pointer to SW RFB data structure. + * @param[out] pu4ControlFlags Control flags for replying the Probe Response + * + * @retval none + */ +/*----------------------------------------------------------------------------*/ +void aisFuncValidateRxActionFrame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct AIS_FSM_INFO *prAisFsmInfo = (struct AIS_FSM_INFO *)NULL; + + DEBUGFUNC("aisFuncValidateRxActionFrame"); + + do { + + ASSERT((prAdapter != NULL) && (prSwRfb != NULL)); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + if (prAisFsmInfo->u4AisPacketFilter & PARAM_PACKET_FILTER_ACTION_FRAME) { + /* Leave the action frame to wpa_supplicant. */ + kalIndicateRxMgmtFrame(prAdapter->prGlueInfo, prSwRfb); + } + + } while (FALSE); + + return; + +} /* aisFuncValidateRxActionFrame */ + +/* Support AP Selection */ +void aisRefreshFWKBlacklist(struct ADAPTER *prAdapter) +{ + struct CONNECTION_SETTINGS *prConnSettings = + &prAdapter->rWifiVar.rConnSettings; + struct AIS_BLACKLIST_ITEM *prEntry = NULL; + struct LINK *prBlackList = &prConnSettings->rBlackList.rUsingLink; + + DBGLOG(AIS, INFO, + "Refresh all the BSSes' fgIsInFWKBlacklist to FALSE\n"); + LINK_FOR_EACH_ENTRY(prEntry, prBlackList, rLinkEntry, + struct AIS_BLACKLIST_ITEM) { + prEntry->fgIsInFWKBlacklist = FALSE; + } +} + +struct AIS_BLACKLIST_ITEM *aisAddBlacklist(struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc) +{ + struct CONNECTION_SETTINGS *prConnSettings = + &prAdapter->rWifiVar.rConnSettings; + struct AIS_BLACKLIST_ITEM *prEntry = NULL; + struct LINK_MGMT *prBlackList = &prConnSettings->rBlackList; + + if (!prBssDesc) { + DBGLOG(AIS, ERROR, "bss descriptor is NULL\n"); + return NULL; + } + if (prBssDesc->prBlack) { + GET_CURRENT_SYSTIME(&prBssDesc->prBlack->rAddTime); + prBssDesc->prBlack->ucCount++; + if (prBssDesc->prBlack->ucCount > 10) + prBssDesc->prBlack->ucCount = 10; + DBGLOG(AIS, INFO, "update blacklist for " MACSTR + ", count %d\n", + MAC2STR(prBssDesc->aucBSSID), + prBssDesc->prBlack->ucCount); + return prBssDesc->prBlack; + } + + prEntry = aisQueryBlackList(prAdapter, prBssDesc); + + if (prEntry) { + GET_CURRENT_SYSTIME(&prEntry->rAddTime); + prBssDesc->prBlack = prEntry; + prEntry->ucCount++; + if (prEntry->ucCount > 10) + prEntry->ucCount = 10; + DBGLOG(AIS, INFO, "update blacklist for " MACSTR + ", count %d\n", + MAC2STR(prBssDesc->aucBSSID), prEntry->ucCount); + return prEntry; + } + LINK_MGMT_GET_ENTRY(prBlackList, prEntry, struct AIS_BLACKLIST_ITEM, + VIR_MEM_TYPE); + if (!prEntry) { + DBGLOG(AIS, WARN, "No memory to allocate\n"); + return NULL; + } + prEntry->ucCount = 1; + /* Support AP Selection */ + prEntry->fgIsInFWKBlacklist = FALSE; + COPY_MAC_ADDR(prEntry->aucBSSID, prBssDesc->aucBSSID); + COPY_SSID(prEntry->aucSSID, prEntry->ucSSIDLen, prBssDesc->aucSSID, + prBssDesc->ucSSIDLen); + GET_CURRENT_SYSTIME(&prEntry->rAddTime); + prBssDesc->prBlack = prEntry; + + DBGLOG(AIS, INFO, "Add " MACSTR " to black List\n", + MAC2STR(prBssDesc->aucBSSID)); + return prEntry; +} + +void aisRemoveBlackList(struct ADAPTER *prAdapter, struct BSS_DESC *prBssDesc) +{ + struct CONNECTION_SETTINGS *prConnSettings = + &prAdapter->rWifiVar.rConnSettings; + struct AIS_BLACKLIST_ITEM *prEntry = NULL; + + prEntry = aisQueryBlackList(prAdapter, prBssDesc); + if (!prEntry) + return; + LINK_MGMT_RETURN_ENTRY(&prConnSettings->rBlackList, prEntry); + prBssDesc->prBlack = NULL; + DBGLOG(AIS, INFO, "Remove " MACSTR " from blacklist\n", + MAC2STR(prBssDesc->aucBSSID)); +} + +struct AIS_BLACKLIST_ITEM *aisQueryBlackList(struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc) +{ + struct CONNECTION_SETTINGS *prConnSettings = + &prAdapter->rWifiVar.rConnSettings; + struct AIS_BLACKLIST_ITEM *prEntry = NULL; + struct LINK *prBlackList = &prConnSettings->rBlackList.rUsingLink; + + if (!prBssDesc) + return NULL; + else if (prBssDesc->prBlack) + return prBssDesc->prBlack; + + LINK_FOR_EACH_ENTRY(prEntry, prBlackList, rLinkEntry, + struct AIS_BLACKLIST_ITEM) { + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prEntry) && + EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, + prEntry->aucSSID, prEntry->ucSSIDLen)) { + prBssDesc->prBlack = prEntry; + return prEntry; + } + } + DBGLOG(AIS, TRACE, MACSTR " is not in blacklist\n", + MAC2STR(prBssDesc->aucBSSID)); + return NULL; +} + +void aisRemoveTimeoutBlacklist(struct ADAPTER *prAdapter) +{ + struct CONNECTION_SETTINGS *prConnSettings = + &prAdapter->rWifiVar.rConnSettings; + struct AIS_BLACKLIST_ITEM *prEntry = NULL; + struct AIS_BLACKLIST_ITEM *prNextEntry = NULL; + struct LINK *prBlackList = &prConnSettings->rBlackList.rUsingLink; + OS_SYSTIME rCurrent; + + GET_CURRENT_SYSTIME(&rCurrent); + + LINK_FOR_EACH_ENTRY_SAFE(prEntry, prNextEntry, prBlackList, rLinkEntry, + struct AIS_BLACKLIST_ITEM) { + /* Support AP Selection */ + if (prEntry->fgIsInFWKBlacklist == TRUE) + continue; + /* end Support AP Selection */ + if (!CHECK_FOR_TIMEOUT(rCurrent, prEntry->rAddTime, + SEC_TO_MSEC(AIS_BLACKLIST_TIMEOUT))) + continue; + LINK_MGMT_RETURN_ENTRY(&prConnSettings->rBlackList, prEntry); + } +} + +static void aisRemoveDisappearedBlacklist(struct ADAPTER *prAdapter) +{ + struct CONNECTION_SETTINGS *prConnSettings = + &prAdapter->rWifiVar.rConnSettings; + struct AIS_BLACKLIST_ITEM *prEntry = NULL; + struct AIS_BLACKLIST_ITEM *prNextEntry = NULL; + struct LINK *prBlackList = &prConnSettings->rBlackList.rUsingLink; + struct LINK *prFreeList = &prConnSettings->rBlackList.rFreeLink; + struct BSS_DESC *prBssDesc = NULL; + struct LINK *prBSSDescList = + &prAdapter->rWifiVar.rScanInfo.rBSSDescList; + uint32_t u4Current = (uint32_t)kalGetBootTime(); + u_int8_t fgDisappeared = TRUE; + + LINK_FOR_EACH_ENTRY_SAFE(prEntry, prNextEntry, prBlackList, rLinkEntry, + struct AIS_BLACKLIST_ITEM) { + fgDisappeared = TRUE; + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, + struct BSS_DESC) { + if (prBssDesc->prBlack == prEntry || + (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prEntry) && + EQUAL_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, + prEntry->aucSSID, + prEntry->ucSSIDLen))) { + fgDisappeared = FALSE; + break; + } + } + if (!fgDisappeared || (u4Current - prEntry->u4DisapperTime) < + 600 * USEC_PER_SEC) + continue; + + DBGLOG(AIS, INFO, "Remove disappeared blacklist %s " MACSTR, + prEntry->aucSSID, MAC2STR(prEntry->aucBSSID)); + LINK_REMOVE_KNOWN_ENTRY(prBlackList, &prEntry->rLinkEntry); + LINK_INSERT_HEAD(prFreeList, &prEntry->rLinkEntry); + } +} + +u_int8_t aisApOverload(struct AIS_BLACKLIST_ITEM *prBlack) +{ + switch (prBlack->u2AuthStatus) { + case STATUS_CODE_ASSOC_DENIED_AP_OVERLOAD: + case STATUS_CODE_ASSOC_DENIED_BANDWIDTH: + return TRUE; + } + switch (prBlack->u2DeauthReason) { + case REASON_CODE_DISASSOC_LACK_OF_BANDWIDTH: + case REASON_CODE_DISASSOC_AP_OVERLOAD: + return TRUE; + } + return FALSE; +} + +uint16_t aisCalculateBlackListScore(struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc) +{ + if (!prBssDesc->prBlack) + prBssDesc->prBlack = aisQueryBlackList(prAdapter, prBssDesc); + + if (!prBssDesc->prBlack) + return 100; + else if (aisApOverload(prBssDesc->prBlack) || + prBssDesc->prBlack->ucCount >= 10) + return 0; + return 100 - prBssDesc->prBlack->ucCount * 10; +} + +void aisFsmRunEventBssTransition(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_AIS_BSS_TRANSITION_T *prMsg = + (struct MSG_AIS_BSS_TRANSITION_T *)prMsgHdr; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecificBssInfo = + &prAdapter->rWifiVar.rAisSpecificBssInfo; + struct BSS_TRANSITION_MGT_PARAM_T *prBtmParam = + &prAisSpecificBssInfo->rBTMParam; + enum WNM_AIS_BSS_TRANSITION eTransType = BSS_TRANSITION_MAX_NUM; + struct BSS_DESC *prBssDesc = + prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc; + u_int8_t fgNeedBtmResponse = FALSE; + uint8_t ucStatus = BSS_TRANSITION_MGT_STATUS_UNSPECIFIED; + uint8_t ucRcvToken = 0; + static uint8_t aucChnlList[MAXIMUM_OPERATION_CHANNEL_LIST]; + + if (!prMsg) { + DBGLOG(AIS, WARN, "Msg Header is NULL\n"); + return; + } + eTransType = prMsg->eTransitionType; + fgNeedBtmResponse = prMsg->fgNeedResponse; + ucRcvToken = prMsg->ucToken; + + DBGLOG(AIS, INFO, "Transition Type: %d\n", eTransType); + aisCollectNeighborAP(prAdapter, prMsg->pucCandList, + prMsg->u2CandListLen, prMsg->ucValidityInterval); + cnmMemFree(prAdapter, prMsgHdr); + /* Solicited BTM request: the case we're waiting btm request + ** after send btm query before roaming scan + */ + if (prBtmParam->ucDialogToken == ucRcvToken) { + prBtmParam->fgPendingResponse = fgNeedBtmResponse; + prBtmParam->fgUnsolicitedReq = FALSE; + + switch (prAdapter->rWifiVar.rRoamingInfo.eCurrentState) { + case ROAMING_STATE_REQ_CAND_LIST: + roamingFsmSteps(prAdapter, ROAMING_STATE_DISCOVERY); + return; + case ROAMING_STATE_DISCOVERY: + /* this case need to fall through */ + case ROAMING_STATE_ROAM: + ucStatus = BSS_TRANSITION_MGT_STATUS_UNSPECIFIED; + goto send_response; + default: + /* not solicited btm request, but dialog token matches + ** occasionally. + */ + break; + } + } + prBtmParam->fgUnsolicitedReq = TRUE; + /* Unsolicited BTM request */ + switch (eTransType) { + case BSS_TRANSITION_DISASSOC: + ucStatus = BSS_TRANSITION_MGT_STATUS_ACCEPT; + break; + case BSS_TRANSITION_REQ_ROAMING: + { + struct NEIGHBOR_AP_T *prNeiAP = NULL; + struct LINK *prUsingLink = + &prAisSpecificBssInfo->rNeighborApList.rUsingLink; + uint8_t i = 0; + uint8_t ucChannel = 0; + uint8_t ucChnlCnt = 0; + uint16_t u2LeftTime = 0; + + if (!prBssDesc) { + DBGLOG(AIS, ERROR, "Target Bss Desc is NULL\n"); + break; + } + prBtmParam->fgPendingResponse = fgNeedBtmResponse; + kalMemZero(aucChnlList, sizeof(aucChnlList)); + LINK_FOR_EACH_ENTRY(prNeiAP, prUsingLink, rLinkEntry, + struct NEIGHBOR_AP_T) + { + ucChannel = prNeiAP->ucChannel; + for (i = 0; + i < ucChnlCnt && ucChannel != aucChnlList[i]; i++) + ; + if (i == ucChnlCnt) + ucChnlCnt++; + } + /* reserve 1 second for association */ + u2LeftTime = prBtmParam->u2DisassocTimer * + prBssDesc->u2BeaconInterval - + 1000; + /* check if left time is enough to do partial scan, if not + ** enought, reject directly + */ + if (u2LeftTime < ucChnlCnt * prBssDesc->u2BeaconInterval) { + ucStatus = BSS_TRANSITION_MGT_STATUS_UNSPECIFIED; + goto send_response; + } + roamingFsmSteps(prAdapter, ROAMING_STATE_DISCOVERY); + return; + } + default: + ucStatus = BSS_TRANSITION_MGT_STATUS_ACCEPT; + break; + } +send_response: + if (fgNeedBtmResponse && prAdapter->prAisBssInfo && + prAdapter->prAisBssInfo->prStaRecOfAP) { + prBtmParam->ucStatusCode = ucStatus; + prBtmParam->ucTermDelay = 0; + kalMemZero(prBtmParam->aucTargetBssid, MAC_ADDR_LEN); + prBtmParam->u2OurNeighborBssLen = 0; + prBtmParam->fgPendingResponse = FALSE; + wnmSendBTMResponseFrame(prAdapter, + prAdapter->prAisBssInfo->prStaRecOfAP); + } +} + +#if CFG_SUPPORT_802_11K +void aisSendNeighborRequest(struct ADAPTER *prAdapter) +{ + struct SUB_ELEMENT_LIST *prSSIDIE; + uint8_t aucBuffer[sizeof(*prSSIDIE) + 31]; + struct BSS_INFO *prBssInfo = prAdapter->prAisBssInfo; + + kalMemZero(aucBuffer, sizeof(aucBuffer)); + prSSIDIE = (struct SUB_ELEMENT_LIST *)&aucBuffer[0]; + prSSIDIE->rSubIE.ucSubID = ELEM_ID_SSID; + COPY_SSID(&prSSIDIE->rSubIE.aucOptInfo[0], prSSIDIE->rSubIE.ucLength, + prBssInfo->aucSSID, prBssInfo->ucSSIDLen); + rlmTxNeighborReportRequest(prAdapter, prBssInfo->prStaRecOfAP, + prSSIDIE); +} + +static u_int8_t aisCandPrefIEIsExist(uint8_t *pucSubIe, uint8_t ucLength) +{ + uint16_t u2Offset = 0; + + IE_FOR_EACH(pucSubIe, ucLength, u2Offset) { + if (IE_ID(pucSubIe) == ELEM_ID_NR_BSS_TRANSITION_CAND_PREF) + return TRUE; + } + return FALSE; +} + +static uint8_t aisGetNeighborApPreference(uint8_t *pucSubIe, uint8_t ucLength) +{ + uint16_t u2Offset = 0; + + IE_FOR_EACH(pucSubIe, ucLength, u2Offset) { + if (IE_ID(pucSubIe) == ELEM_ID_NR_BSS_TRANSITION_CAND_PREF) + return pucSubIe[2]; + } + /* If no preference element is presence, give default value(lowest) 0, + */ + /* but it will not be used as a reference. */ + return 0; +} + +static uint64_t aisGetBssTermTsf(uint8_t *pucSubIe, uint8_t ucLength) +{ + uint16_t u2Offset = 0; + + IE_FOR_EACH(pucSubIe, ucLength, u2Offset) { + if (IE_ID(pucSubIe) == ELEM_ID_NR_BSS_TERMINATION_DURATION) + return *(uint64_t *) &pucSubIe[2]; + } + /* If no preference element is presence, give default value(lowest) 0 */ + return 0; +} + +void aisCollectNeighborAP(struct ADAPTER *prAdapter, uint8_t *pucApBuf, + uint16_t u2ApBufLen, uint8_t ucValidInterval) +{ + struct NEIGHBOR_AP_T *prNeighborAP = NULL; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecBssInfo = + &prAdapter->rWifiVar.rAisSpecificBssInfo; + struct LINK_MGMT *prAPlist = &prAisSpecBssInfo->rNeighborApList; + struct IE_NEIGHBOR_REPORT *prIe = (struct IE_NEIGHBOR_REPORT *)pucApBuf; + uint16_t u2BufLen; + uint16_t u2PrefIsZeroCount = 0; + + if (!prIe || !u2ApBufLen || u2ApBufLen < prIe->ucLength) + return; + LINK_MERGE_TO_TAIL(&prAPlist->rFreeLink, &prAPlist->rUsingLink); + for (u2BufLen = u2ApBufLen; u2BufLen > 0; u2BufLen -= IE_SIZE(prIe), + prIe = (struct IE_NEIGHBOR_REPORT *)((uint8_t *) prIe + + IE_SIZE(prIe))) { + /* BIT0-1: AP reachable, BIT2: same security with current + ** setting, + ** BIT3: same authenticator with current AP + */ + if (prIe->ucId != ELEM_ID_NEIGHBOR_REPORT || + (prIe->u4BSSIDInfo & 0x7) != 0x7) + continue; + LINK_MGMT_GET_ENTRY(prAPlist, prNeighborAP, + struct NEIGHBOR_AP_T, VIR_MEM_TYPE); + if (!prNeighborAP) + break; + prNeighborAP->fgHT = !!(prIe->u4BSSIDInfo & BIT(11)); + prNeighborAP->fgFromBtm = !!ucValidInterval; + prNeighborAP->fgRmEnabled = !!(prIe->u4BSSIDInfo & BIT(7)); + prNeighborAP->fgQoS = !!(prIe->u4BSSIDInfo & BIT(5)); + prNeighborAP->fgSameMD = !!(prIe->u4BSSIDInfo & BIT(10)); + prNeighborAP->ucChannel = prIe->ucChnlNumber; + prNeighborAP->fgPrefPresence = aisCandPrefIEIsExist( + prIe->aucSubElem, + IE_SIZE(prIe) - OFFSET_OF(struct IE_NEIGHBOR_REPORT, + aucSubElem)); + prNeighborAP->ucPreference = aisGetNeighborApPreference( + prIe->aucSubElem, + IE_SIZE(prIe) - OFFSET_OF(struct IE_NEIGHBOR_REPORT, + aucSubElem)); + prNeighborAP->u8TermTsf = aisGetBssTermTsf( + prIe->aucSubElem, + IE_SIZE(prIe) - OFFSET_OF(struct IE_NEIGHBOR_REPORT, + aucSubElem)); + COPY_MAC_ADDR(prNeighborAP->aucBssid, prIe->aucBSSID); + DBGLOG(AIS, INFO, + "Bssid" MACSTR + ", PrefPresence %d, Pref %d, Chnl %d, BssidInfo 0x%08x\n", + MAC2STR(prNeighborAP->aucBssid), + prNeighborAP->fgPrefPresence, + prNeighborAP->ucPreference, prIe->ucChnlNumber, + prIe->u4BSSIDInfo); + /* No need to save neighbor ap list with decendant preference + ** for (prTemp = LINK_ENTRY(prAPlist->rUsingLink.prNext, struct + ** NEIGHBOR_AP_T, rLinkEntry); + ** prTemp != prNeighborAP; + ** prTemp = LINK_ENTRY(prTemp->rLinkEntry.prNext, struct + ** NEIGHBOR_AP_T, rLinkEntry)) { + ** if (prTemp->ucPreference < prNeighborAP->ucPreference) { + ** __linkDel(prNeighborAP->rLinkEntry.prPrev, + ** prNeighborAP->rLinkEntry.prNext); + ** __linkAdd(&prNeighborAP->rLinkEntry, + ** prTemp->rLinkEntry.prPrev, &prTemp->rLinkEntry); + ** break; + ** } + ** } + */ + if (prNeighborAP->fgPrefPresence && + prNeighborAP->ucPreference == 0) + u2PrefIsZeroCount++; + } + prAisSpecBssInfo->rNeiApRcvTime = kalGetTimeTick(); + prAisSpecBssInfo->u4NeiApValidInterval = + !ucValidInterval + ? 0xffffffff + : TU_TO_MSEC(ucValidInterval * + prAdapter->prAisBssInfo->u2BeaconInterval); + + if (prAPlist->rUsingLink.u4NumElem > 0 && + prAPlist->rUsingLink.u4NumElem == u2PrefIsZeroCount) + DBGLOG(AIS, INFO, + "The number of valid neighbors is equal to the number of perf value is 0.\n"); +} + +void aisResetNeighborApList(IN struct ADAPTER *prAdapter) +{ + struct AIS_SPECIFIC_BSS_INFO *prAisSpecBssInfo = + &prAdapter->rWifiVar.rAisSpecificBssInfo; + struct LINK_MGMT *prAPlist = &prAisSpecBssInfo->rNeighborApList; + + LINK_MERGE_TO_TAIL(&prAPlist->rFreeLink, &prAPlist->rUsingLink); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Trigger when cfg80211_suspend +* 1. cancel scan and report scan done event +* 2. linkdown if wow is disable +* +* @param prAdapter +* eReqType +* bRemove +* +* @return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +void aisPreSuspendFlow(IN struct GLUE_INFO *prGlueInfo) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint32_t u4BufLen; + struct AIS_FSM_INFO *prAisFsmInfo; + struct MSG_CANCEL_REMAIN_ON_CHANNEL *prMsgChnlAbort; + + GLUE_SPIN_LOCK_DECLARATION(); + + /* report scan abort */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if (prGlueInfo->prScanRequest) { + kalCfg80211ScanDone(prGlueInfo->prScanRequest, TRUE); + prGlueInfo->prScanRequest = NULL; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + /* cancel scan */ + aisFsmStateAbort_SCAN(prGlueInfo->prAdapter); + + DBGLOG(REQ, STATE, "Wow:%d, WowEnable:%d, state:%d\n", + prGlueInfo->prAdapter->rWifiVar.ucWow, + prGlueInfo->prAdapter->rWowCtrl.fgWowEnable, + kalGetMediaStateIndicated(prGlueInfo)); + + prAisFsmInfo = &(prGlueInfo->prAdapter->rWifiVar.rAisFsmInfo); + if ((prAisFsmInfo->eCurrentState == AIS_STATE_REMAIN_ON_CHANNEL) || + (prAisFsmInfo->eCurrentState == AIS_STATE_REQ_REMAIN_ON_CHANNEL)) { + prMsgChnlAbort = + cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_CANCEL_REMAIN_ON_CHANNEL)); + + if (prMsgChnlAbort == NULL) + DBGLOG(REQ, ERROR, "ChnlAbort Msg allocate fail!\n"); + else { + prMsgChnlAbort->rMsgHdr.eMsgId = + MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL; + prMsgChnlAbort->u8Cookie = + prAisFsmInfo->rChReqInfo.u8Cookie; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prMsgChnlAbort, + MSG_SEND_METHOD_BUF); + } + } + + /* 1) wifi cfg "Wow" must be true, + * 2) wow is disable + * 3) AdvPws is disable + * 4) WIfI connected => execute link down flow + */ + /* link down AIS */ + if (prGlueInfo->prAdapter->rWifiVar.ucWow && + !prGlueInfo->prAdapter->rWowCtrl.fgWowEnable && + !prGlueInfo->prAdapter->rWifiVar.ucAdvPws) { + if (kalGetMediaStateIndicated(prGlueInfo) == + PARAM_MEDIA_STATE_CONNECTED) { + DBGLOG(REQ, STATE, "CFG80211 suspend link down\n"); + rStatus = kalIoctl(prGlueInfo, wlanoidLinkDown, NULL, 0, + TRUE, FALSE, FALSE, &u4BufLen); + } + } +} + +void aisFuncUpdateMgmtFrameRegister( + IN struct ADAPTER *prAdapter, + IN uint32_t u4NewPacketFilter) +{ + struct AIS_FSM_INFO *prAisFsmInfo = (struct AIS_FSM_INFO *)NULL; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + +#if CFG_SUPPORT_PER_BSS_FILTER + if (prAisFsmInfo->u4AisPacketFilter^u4NewPacketFilter) { + /* Filter setings changed. */ + struct CMD_RX_PACKET_FILTER rSetRxPacketFilter; + uint32_t u4OsFilter = 0; + + prAisFsmInfo->u4AisPacketFilter = u4NewPacketFilter; + + kalMemZero(&rSetRxPacketFilter, sizeof(rSetRxPacketFilter)); + + /* For not impact original functionality. */ + rSetRxPacketFilter.u4RxPacketFilter = + prAdapter->u4OsPacketFilter; + + if (prAdapter->prAisBssInfo) { + rSetRxPacketFilter.ucIsPerBssFilter = TRUE; + rSetRxPacketFilter.ucBssIndex = + prAdapter->prAisBssInfo->ucBssIndex; + rSetRxPacketFilter.u4BssMgmtFilter = + prAisFsmInfo->u4AisPacketFilter; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RX_FILTER, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_RX_PACKET_FILTER), + (uint8_t *)&rSetRxPacketFilter, + &u4OsFilter, + sizeof(u4OsFilter)); + } + } +#else + + prAisFsmInfo->u4AisPacketFilter = u4NewPacketFilter; + +#endif +} + + + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/ap_selection.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/ap_selection.c new file mode 100644 index 0000000000000..a16e5a8e88407 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/ap_selection.c @@ -0,0 +1,781 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +#include "precomp.h" + +/* + * definition for AP selection algrithm + */ +#define BSS_FULL_SCORE (100) +#define CHNL_BSS_NUM_THRESOLD 100 +#define BSS_STA_CNT_THRESOLD 30 +#define SCORE_PER_AP 1 +#define ROAMING_NO_SWING_SCORE_STEP 100 +/* MCS9 at BW 160 requires rssi at least -48dbm */ +#define BEST_RSSI -48 +/* MCS7 at 20BW, MCS5 at 40BW, MCS4 at 80BW, MCS3 at 160BW */ +#define GOOD_RSSI_FOR_HT_VHT -64 +/* Link speed 1Mbps need at least rssi -94dbm for 2.4G */ +#define MINIMUM_RSSI_2G4 -94 +/* Link speed 6Mbps need at least rssi -86dbm for 5G */ +#define MINIMUM_RSSI_5G -86 + +/* Real Rssi of a Bss may range in current_rssi - 5 dbm + *to current_rssi + 5 dbm + */ +#define RSSI_DIFF_BETWEEN_BSS 10 /* dbm */ +#define LOW_RSSI_FOR_5G_BAND -70 /* dbm */ +#define HIGH_RSSI_FOR_5G_BAND -60 /* dbm */ + +#define WEIGHT_IDX_CHNL_UTIL 2 +#define WEIGHT_IDX_SNR 3 +#define WEIGHT_IDX_RSSI 2 +#define WEIGHT_IDX_SCN_MISS_CNT 2 +#define WEIGHT_IDX_PROBE_RSP 1 +#define WEIGHT_IDX_CLIENT_CNT 1 +#define WEIGHT_IDX_AP_NUM 2 +#define WEIGHT_IDX_5G_BAND 0 +#define WEIGHT_IDX_BAND_WIDTH 1 +#define WEIGHT_IDX_STBC 1 +#define WEIGHT_IDX_DEAUTH_LAST 4 +#define WEIGHT_IDX_BLACK_LIST 2 +#if CFG_SUPPORT_RSN_SCORE +#define WEIGHT_IDX_RSN 2 +#endif +#define WEIGHT_IDX_SAA 2 + + +#define CALCULATE_SCORE_BY_PROBE_RSP(prBssDesc) \ + (WEIGHT_IDX_PROBE_RSP * \ + (prBssDesc->fgSeenProbeResp ? BSS_FULL_SCORE : 0)) + +#define CALCULATE_SCORE_BY_MISS_CNT(prAdapter, prBssDesc) \ + (WEIGHT_IDX_SCN_MISS_CNT * \ + (prAdapter->rWifiVar.rScanInfo.u4ScanUpdateIdx - \ + prBssDesc->u4UpdateIdx > 3 ? 0 : \ + (BSS_FULL_SCORE - (prAdapter->rWifiVar.rScanInfo.u4ScanUpdateIdx - \ + prBssDesc->u4UpdateIdx) * 25))) + +#define CALCULATE_SCORE_BY_BAND(prAdapter, prBssDesc, cRssi) \ + (WEIGHT_IDX_5G_BAND * \ + ((prBssDesc->eBand == BAND_5G && prAdapter->fgEnable5GBand && \ + cRssi > -70) ? BSS_FULL_SCORE : 0)) + +#define CALCULATE_SCORE_BY_STBC(prAdapter, prBssDesc) \ + (WEIGHT_IDX_STBC * \ + (prBssDesc->fgMultiAnttenaAndSTBC ? BSS_FULL_SCORE:0)) + +#define CALCULATE_SCORE_BY_DEAUTH(prBssDesc) \ + (WEIGHT_IDX_DEAUTH_LAST * \ + (prBssDesc->fgDeauthLastTime ? 0:BSS_FULL_SCORE)) + +#if CFG_SUPPORT_RSN_SCORE +#define CALCULATE_SCORE_BY_RSN(prBssDesc) \ + (WEIGHT_IDX_RSN * (prBssDesc->fgIsRSNSuitableBss ? BSS_FULL_SCORE:0)) +#endif + +/* Channel Utilization: weight index will be */ +static uint16_t scanCalculateScoreByChnlInfo( + struct AIS_SPECIFIC_BSS_INFO *prAisSpecificBssInfo, uint8_t ucChannel) +{ + struct ESS_CHNL_INFO *prEssChnlInfo = &prAisSpecificBssInfo-> + arCurEssChnlInfo[0]; + uint8_t i = 0; + uint16_t u2Score = 0; + + for (; i < prAisSpecificBssInfo->ucCurEssChnlInfoNum; i++) { + if (ucChannel == prEssChnlInfo[i].ucChannel) { +#if 0 /* currently, we don't take channel utilization into account */ + /* the channel utilization max value is 255. + *great utilization means little weight value. + * the step of weight value is 2.6 + */ + u2Score = WEIGHT_IDX_CHNL_UTIL * + (BSS_FULL_SCORE - + (prEssChnlInfo[i].ucUtilization * 10 / 26)); +#endif + /* if AP num on this channel is greater than 100, + * the weight will be 0. + * otherwise, the weight value decrease 1 + * if AP number increase 1 + */ + if (prEssChnlInfo[i].ucApNum <= CHNL_BSS_NUM_THRESOLD) + u2Score += WEIGHT_IDX_AP_NUM * (BSS_FULL_SCORE - + prEssChnlInfo[i].ucApNum * + SCORE_PER_AP); + log_dbg(SCN, TRACE, "channel %d, AP num %d\n", + ucChannel, prEssChnlInfo[i].ucApNum); + break; + } + } + return u2Score; +} + +static uint16_t scanCalculateScoreByBandwidth(struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc) +{ + uint16_t u2Score = 0; + + if (prBssDesc->fgIsHTPresent) { + if (prBssDesc->eBand == BAND_2G4) + u2Score = (prBssDesc->eSco == 0) ? 60:100; + else if (prBssDesc->eBand == BAND_5G) + u2Score = (prBssDesc->eSco == 0) ? 60:100; + } else if (prBssDesc->u2BSSBasicRateSet & RATE_SET_OFDM) + u2Score = 20; + else + u2Score = 10; + + log_dbg(SCN, TRACE, "ht %d, eband %d, esco %d, u2Score %d\n", + prBssDesc->fgIsHTPresent, prBssDesc->eBand, prBssDesc->eSco, + u2Score); + + return u2Score * WEIGHT_IDX_BAND_WIDTH; +} + +static uint16_t scanCalculateScoreByClientCnt(struct BSS_DESC *prBssDesc) +{ + uint16_t u2Score = 0; + + log_dbg(SCN, TRACE, "Exist bss load %d, sta cnt %d\n", + prBssDesc->fgExsitBssLoadIE, prBssDesc->u2StaCnt); + + if (!prBssDesc->fgExsitBssLoadIE || prBssDesc->u2StaCnt > + BSS_STA_CNT_THRESOLD) + return 0; + + u2Score = BSS_FULL_SCORE - prBssDesc->u2StaCnt * 3; + return u2Score * WEIGHT_IDX_CLIENT_CNT; +} + +#if CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT +struct NEIGHBOR_AP_T *scanGetNeighborAPEntry(struct LINK *prNeighborApLink, + uint8_t *pucBssid) +{ + struct NEIGHBOR_AP_T *prNeighborAP = NULL; + + LINK_FOR_EACH_ENTRY(prNeighborAP, prNeighborApLink, rLinkEntry, + struct NEIGHBOR_AP_T) + { + if (EQUAL_MAC_ADDR(prNeighborAP->aucBssid, pucBssid)) + return prNeighborAP; + } + return NULL; +} + +u_int8_t scanPreferenceIsZero(struct ADAPTER *prAdapter, uint8_t *pucBssid) +{ + struct LINK *prNeighborAPLink = &prAdapter->rWifiVar.rAisSpecificBssInfo + .rNeighborApList.rUsingLink; + struct NEIGHBOR_AP_T *prNeighborAP = NULL; + + if (prNeighborAPLink->u4NumElem == 0) + return FALSE; + + prNeighborAP = scanGetNeighborAPEntry(prNeighborAPLink, pucBssid); + + if (prNeighborAP == NULL) + return FALSE; + if (!prNeighborAP->fgPrefPresence) + return FALSE; + if (prNeighborAP->ucPreference > 0) + return FALSE; + + return TRUE; +} +#endif + +static u_int8_t scanNeedReplaceCandidate(struct ADAPTER *prAdapter, + struct BSS_DESC *prCandBss, struct BSS_DESC *prCurrBss, + uint16_t u2CandScore, uint16_t u2CurrScore) +{ + int8_t cCandRssi = RCPI_TO_dBm(prCandBss->ucRCPI); + int8_t cCurrRssi = RCPI_TO_dBm(prCurrBss->ucRCPI); + uint32_t u4UpdateIdx = prAdapter->rWifiVar.rScanInfo.u4ScanUpdateIdx; + uint16_t u2CandMiss = u4UpdateIdx - prCandBss->u4UpdateIdx; + uint16_t u2CurrMiss = u4UpdateIdx - prCurrBss->u4UpdateIdx; + + /* 1. No need check score case + * 1.1 Scan missing count of CurrBss is too more, + * but Candidate is suitable, don't replace + */ + if (u2CurrMiss > 2 && u2CurrMiss > u2CandMiss) { + log_dbg(SCN, INFO, "Scan Miss count of CurrBss > 2, and Candidate <= 2\n"); + return FALSE; + } + /* 1.2 Scan missing count of Candidate is too more, + * but CurrBss is suitable, replace + */ + if (u2CandMiss > 2 && u2CandMiss > u2CurrMiss) { + log_dbg(SCN, INFO, "Scan Miss count of Candidate > 2, and CurrBss <= 2\n"); + return TRUE; + } + /* 1.3 Hard connecting RSSI check */ + if ((prCurrBss->eBand == BAND_5G && cCurrRssi < MINIMUM_RSSI_5G) || + (prCurrBss->eBand == BAND_2G4 && cCurrRssi < MINIMUM_RSSI_2G4)) + return FALSE; + else if ((prCandBss->eBand == BAND_5G && cCandRssi < MINIMUM_RSSI_5G) || + (prCandBss->eBand == BAND_2G4 && cCandRssi < MINIMUM_RSSI_2G4)) + return TRUE; + + /* 1.4 prefer to select 5G Bss if Rssi of a 5G band BSS is >= -60dbm */ + if (prCandBss->eBand != prCurrBss->eBand) { + if (prCurrBss->eBand == BAND_5G) { + /* Current AP is 5G, replace candidate + * AP of current AP is good. + */ + if (cCurrRssi >= HIGH_RSSI_FOR_5G_BAND || + (cCandRssi < HIGH_RSSI_FOR_5G_BAND && + cCurrRssi > LOW_RSSI_FOR_5G_BAND)) + return TRUE; + else if (cCurrRssi < LOW_RSSI_FOR_5G_BAND && + cCurrRssi < cCandRssi) + return FALSE; + } else { + /* Candidate AP is 5G, don't replace it + * if it's good enough. + */ + if (cCandRssi >= HIGH_RSSI_FOR_5G_BAND || + (cCurrRssi < HIGH_RSSI_FOR_5G_BAND && + cCandRssi > LOW_RSSI_FOR_5G_BAND)) + return FALSE; + else if (cCandRssi < LOW_RSSI_FOR_5G_BAND && + cCandRssi < cCurrRssi) + return TRUE; + } + } + + /* 1.5 RSSI of Current Bss is lower than Candidate, don't replace + * If the lower Rssi is greater than -59dbm, + * then no need check the difference + * Otherwise, if difference is greater than 10dbm, select the good RSSI + */ + if (cCandRssi - cCurrRssi >= RSSI_DIFF_BETWEEN_BSS) + return FALSE; + /* RSSI of Candidate Bss is lower than Current, replace */ + if (cCurrRssi - cCandRssi >= RSSI_DIFF_BETWEEN_BSS) + return TRUE; + +#if CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT + if (scanPreferenceIsZero(prAdapter, prCurrBss->aucBSSID)) { + log_dbg(SCN, INFO, + "BTM: %s[" MACSTR "] preference value is 0, skip it\n", + prCurrBss->aucSSID, MAC2STR(prCurrBss->aucBSSID)); + return FALSE; + } +#endif + + /* 2. Check Score */ + /* 2.1 Cases that no need to replace candidate */ + if (prCandBss->fgIsConnected) { + if ((u2CandScore + ROAMING_NO_SWING_SCORE_STEP) >= u2CurrScore) + return FALSE; + } else if (prCurrBss->fgIsConnected) { + if (u2CandScore >= (u2CurrScore + ROAMING_NO_SWING_SCORE_STEP)) + return FALSE; + } else if (u2CandScore >= u2CurrScore) + return FALSE; + /* 2.2 other cases, replace candidate */ + return TRUE; +} + +static u_int8_t scanSanityCheckBssDesc(struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc, enum ENUM_BAND eBand, uint8_t ucChannel, + u_int8_t fgIsFixedChannel) +{ + if (!(prBssDesc->ucPhyTypeSet & + (prAdapter->rWifiVar.ucAvailablePhyTypeSet))) { + log_dbg(SCN, WARN, + "SEARCH: Ignore unsupported ucPhyTypeSet = %x\n", + prBssDesc->ucPhyTypeSet); + return FALSE; + } + if (prBssDesc->fgIsUnknownBssBasicRate) + return FALSE; + if (fgIsFixedChannel && + (eBand != prBssDesc->eBand || ucChannel != + prBssDesc->ucChannelNum)) { + log_dbg(SCN, INFO, "Fix channel required band %d, channel %d\n", + eBand, ucChannel); + return FALSE; + } + if (!rlmDomainIsLegalChannel(prAdapter, prBssDesc->eBand, + prBssDesc->ucChannelNum)) { + log_dbg(SCN, WARN, "Band %d channel %d is not legal\n", + prBssDesc->eBand, prBssDesc->ucChannelNum); + return FALSE; + } + + if (CHECK_FOR_TIMEOUT(kalGetTimeTick(), prBssDesc->rUpdateTime, + SEC_TO_SYSTIME(SCN_BSS_DESC_STALE_SEC))) { + log_dbg(SCN, WARN, "BSS " + MACSTR + " description is too old.\n", + MAC2STR(prBssDesc->aucBSSID)); + return FALSE; + } + +#if CFG_SUPPORT_WAPI + if (prAdapter->rWifiVar.rConnSettings.fgWapiMode) { + if (!wapiPerformPolicySelection(prAdapter, prBssDesc)) + return FALSE; + } else +#endif + if (!rsnPerformPolicySelection(prAdapter, prBssDesc)) + return FALSE; + if (prAdapter->rWifiVar.rAisSpecificBssInfo.fgCounterMeasure) { + log_dbg(SCN, WARN, "Skip while at counter measure period!!!\n"); + return FALSE; + } + return TRUE; +} + +static uint16_t scanCalculateScoreByRssi(struct BSS_DESC *prBssDesc) +{ + uint16_t u2Score = 0; + int8_t cRssi = RCPI_TO_dBm(prBssDesc->ucRCPI); + + if (cRssi >= -20) + u2Score = BSS_FULL_SCORE; + else if (cRssi >= -55) + u2Score = 95; + else if (cRssi >= -65) + u2Score = 80; + else if (cRssi >= -70) + u2Score = 50; + else if (cRssi >= -77) + u2Score = 15; + else if (cRssi >= -88) + u2Score = 10; + else if (cRssi < -88 && cRssi > -100) + u2Score = 5; + else if (cRssi <= -100) + u2Score = 0; + + u2Score *= WEIGHT_IDX_RSSI; + + return u2Score; +} + +static uint16_t scanCalculateScoreByBand(struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc, int8_t cRssi) +{ + uint16_t u2Score = 0; + struct AIS_FSM_INFO *prAisFsmInfo; + struct ROAMING_INFO *prRoamingFsmInfo; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prRoamingFsmInfo = (struct ROAMING_INFO *) + &(prAdapter->rWifiVar.rRoamingInfo); + + if (prBssDesc->eBand == BAND_5G && prAdapter->fgEnable5GBand + && cRssi > -60 + && prRoamingFsmInfo->eCurrentState == ROAMING_STATE_IDLE + && prAisFsmInfo->u4PostponeIndStartTime == 0) + u2Score = (WEIGHT_IDX_5G_BAND * BSS_FULL_SCORE); + + return u2Score; +} + +static uint16_t scanCalculateScoreBySaa(struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc) +{ + uint16_t u2Score = 0; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + + prStaRec = cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_AIS, + prBssDesc->aucSrcAddr); + if (prStaRec) + u2Score = WEIGHT_IDX_SAA * (prStaRec->ucTxAuthAssocRetryCount + ? 0 : BSS_FULL_SCORE); + else + u2Score = WEIGHT_IDX_SAA * BSS_FULL_SCORE; + + return u2Score; +} + +/* + * Bss Characteristics to be taken into account when calculate Score: + * Channel Loading Group: + * 1. Client Count (in BSS Load IE). + * 2. AP number on the Channel. + * + * RF Group: + * 1. Channel utilization. + * 2. SNR. + * 3. RSSI. + * + * Misc Group: + * 1. Deauth Last time. + * 2. Scan Missing Count. + * 3. Has probe response in scan result. + * + * Capability Group: + * 1. Prefer 5G band. + * 2. Bandwidth. + * 3. STBC and Multi Anttena. + */ +struct BSS_DESC *scanSearchBssDescByScoreForAis(struct ADAPTER *prAdapter) +{ + struct AIS_SPECIFIC_BSS_INFO *prAisSpecificBssInfo = NULL; + struct LINK *prEssLink = NULL; + struct CONNECTION_SETTINGS *prConnSettings = NULL; + struct BSS_DESC *prBssDesc = NULL; + struct BSS_DESC *prCandBssDesc = NULL; + struct BSS_DESC *prCandBssDescForLowRssi = NULL; + uint16_t u2ScoreBand = 0; + uint16_t u2ScoreChnlInfo = 0; + uint16_t u2ScoreStaCnt = 0; + uint16_t u2ScoreProbeRsp = 0; + uint16_t u2ScoreScanMiss = 0; + uint16_t u2ScoreBandwidth = 0; + uint16_t u2ScoreSTBC = 0; + uint16_t u2ScoreDeauth = 0; + uint16_t u2ScoreRssi = 0; + uint16_t u2ScoreTotal = 0; + uint16_t u2ScoreRSN = 0; + uint16_t u2ScoreSaa = 0; + uint16_t u2CandBssScore = 0; + uint16_t u2CandBssScoreForLowRssi = 0; + uint16_t u2BlackListScore = 0; + u_int8_t fgSearchBlackList = FALSE; + u_int8_t fgIsFixedChannel = FALSE; + enum ENUM_BAND eBand = BAND_2G4; + uint8_t ucChannel = 0; + int8_t cRssi = -128; + + if (!prAdapter) { + log_dbg(SCN, ERROR, "prAdapter is NULL!\n"); + return NULL; + } + prAisSpecificBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prEssLink = &prAisSpecificBssInfo->rCurEssLink; +#if CFG_SUPPORT_CHNL_CONFLICT_REVISE + fgIsFixedChannel = cnmAisDetectP2PChannel + (prAdapter, &eBand, &ucChannel); +#else + fgIsFixedChannel = + cnmAisInfraChannelFixed(prAdapter, &eBand, &ucChannel); +#endif + aisRemoveTimeoutBlacklist(prAdapter); + log_dbg(SCN, INFO, "%s: ConnectionPolicy = %d\n", + __func__, + prConnSettings->eConnectionPolicy); + +try_again: + LINK_FOR_EACH_ENTRY(prBssDesc, prEssLink, rLinkEntryEss, + struct BSS_DESC) { + if (prConnSettings->eConnectionPolicy == CONNECT_BY_BSSID && + EQUAL_MAC_ADDR(prBssDesc->aucBSSID, + prConnSettings->aucBSSID)) { + if (!scanSanityCheckBssDesc(prAdapter, prBssDesc, + eBand, ucChannel, fgIsFixedChannel)) + continue; + + /* Make sure to match with SSID if supplied. + * Some old dualband APs share a single BSSID + * among different BSSes. + */ + if ((prBssDesc->ucSSIDLen > 0 && + prConnSettings->ucSSIDLen > 0 && + EQUAL_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, + prConnSettings->aucSSID, + prConnSettings->ucSSIDLen)) || + prConnSettings->ucSSIDLen == 0) + log_dbg(SCN, LOUD, "%s: BSSID/SSID pair matched\n", + __func__); + else { + log_dbg(SCN, ERROR, "%s: BSSID/SSID pair unmatched (" + MACSTR + ")\n", __func__, + MAC2STR(prBssDesc->aucBSSID)); + continue; + } + prCandBssDesc = prBssDesc; + break; + } else if (prConnSettings->eConnectionPolicy == + CONNECT_BY_BSSID_HINT && + EQUAL_MAC_ADDR(prBssDesc->aucBSSID, + prConnSettings->aucBSSIDHint)) { + if (!scanSanityCheckBssDesc(prAdapter, prBssDesc, + eBand, ucChannel, fgIsFixedChannel)) + continue; + + prCandBssDesc = prBssDesc; + break; + } + + if (!fgSearchBlackList) { + prBssDesc->prBlack = + aisQueryBlackList(prAdapter, prBssDesc); + if (prBssDesc->prBlack) { + if (prBssDesc->prBlack->fgIsInFWKBlacklist == + TRUE) + log_dbg(SCN, INFO, "%s(" + MACSTR + ") is in FWK blacklist, skip it\n", + prBssDesc->aucSSID, + MAC2STR(prBssDesc->aucBSSID)); + continue; + } + } else if (!prBssDesc->prBlack) + continue; + else { + /* never search FWK blacklist even + * if we are trying blacklist + */ + if (prBssDesc->prBlack->fgIsInFWKBlacklist == TRUE) { + log_dbg(SCN, INFO, "Although trying blacklist, %s(" + MACSTR + ") is in FWK blacklist, skip it\n", + prBssDesc->aucSSID, + MAC2STR(prBssDesc->aucBSSID)); + continue; + } + u2BlackListScore = WEIGHT_IDX_BLACK_LIST * + aisCalculateBlackListScore(prAdapter, + prBssDesc); + } + + cRssi = RCPI_TO_dBm(prBssDesc->ucRCPI); + + if (!scanSanityCheckBssDesc(prAdapter, prBssDesc, eBand, + ucChannel, fgIsFixedChannel)) + continue; + + u2ScoreBandwidth = + scanCalculateScoreByBandwidth(prAdapter, prBssDesc); + u2ScoreStaCnt = scanCalculateScoreByClientCnt(prBssDesc); + u2ScoreSTBC = CALCULATE_SCORE_BY_STBC(prAdapter, prBssDesc); + u2ScoreChnlInfo = + scanCalculateScoreByChnlInfo(prAisSpecificBssInfo, + prBssDesc->ucChannelNum); + u2ScoreRssi = scanCalculateScoreByRssi(prBssDesc); + u2ScoreDeauth = CALCULATE_SCORE_BY_DEAUTH(prBssDesc); + u2ScoreProbeRsp = CALCULATE_SCORE_BY_PROBE_RSP(prBssDesc); + u2ScoreScanMiss = CALCULATE_SCORE_BY_MISS_CNT(prAdapter, + prBssDesc); + u2ScoreBand = scanCalculateScoreByBand(prAdapter, prBssDesc, + cRssi); +#if CFG_SUPPORT_RSN_SCORE + u2ScoreRSN = CALCULATE_SCORE_BY_RSN(prBssDesc); +#endif + u2ScoreSaa = scanCalculateScoreBySaa(prAdapter, prBssDesc); + + u2ScoreTotal = u2ScoreBandwidth + u2ScoreChnlInfo + + u2ScoreDeauth + u2ScoreProbeRsp + u2ScoreScanMiss + + u2ScoreRssi + u2ScoreStaCnt + u2ScoreSTBC + + u2ScoreBand + u2BlackListScore + u2ScoreRSN + + u2ScoreSaa; + + log_dbg(SCN, INFO, + MACSTR + " cRSSI[%d] 5G[%d] Score, Total %d, DE[%d], PR[%d], SM[%d], RSSI[%d], BA[%d] RSN[%d], SAA[%d], BW[%d], CN[%d], ST[%d], CI[%d]\n", + MAC2STR(prBssDesc->aucBSSID), cRssi, + (prBssDesc->eBand == BAND_5G ? 1 : 0), u2ScoreTotal, + u2ScoreDeauth, u2ScoreProbeRsp, u2ScoreScanMiss, + u2ScoreRssi, u2BlackListScore, u2ScoreRSN, u2ScoreSaa, + u2ScoreBandwidth, u2ScoreStaCnt, u2ScoreSTBC, + u2ScoreChnlInfo); + + if (!prCandBssDesc || + scanNeedReplaceCandidate(prAdapter, prCandBssDesc, + prBssDesc, u2CandBssScore, u2ScoreTotal)) { + prCandBssDesc = prBssDesc; + u2CandBssScore = u2ScoreTotal; + } + } + + if (prCandBssDesc) { + if (prCandBssDesc->fgIsConnected && !fgSearchBlackList && + prEssLink->u4NumElem > 0) { + fgSearchBlackList = TRUE; + log_dbg(SCN, INFO, "Can't roam out, try blacklist\n"); + goto try_again; + } + if (prConnSettings->eConnectionPolicy == CONNECT_BY_BSSID) + log_dbg(SCN, INFO, "Selected " + MACSTR + " %d base on ssid,when find %s, " + MACSTR + " in %d bssid,fix channel %d.\n", + MAC2STR(prCandBssDesc->aucBSSID), + RCPI_TO_dBm(prCandBssDesc->ucRCPI), + prConnSettings->aucSSID, + MAC2STR(prConnSettings->aucBSSID), + prEssLink->u4NumElem, ucChannel); + else + log_dbg(SCN, INFO, + "Selected " + MACSTR + ", cRSSI[%d] 5G[%d] Score %d when find %s, " + MACSTR + " in %d BSSes, fix channel %d.\n", + MAC2STR(prCandBssDesc->aucBSSID), + cRssi = RCPI_TO_dBm(prCandBssDesc->ucRCPI), + (prCandBssDesc->eBand == BAND_5G ? 1 : 0), + u2CandBssScore, prConnSettings->aucSSID, + MAC2STR(prConnSettings->aucBSSID), + prEssLink->u4NumElem, ucChannel); + + return prCandBssDesc; + } else if (prCandBssDescForLowRssi) { + log_dbg(SCN, INFO, "Selected " MACSTR + ", Score %d when find %s, " MACSTR + " in %d BSSes, fix channel %d.\n", + MAC2STR(prCandBssDescForLowRssi->aucBSSID), + u2CandBssScoreForLowRssi, prConnSettings->aucSSID, + MAC2STR(prConnSettings->aucBSSID), prEssLink->u4NumElem, + ucChannel); + return prCandBssDescForLowRssi; + } + + /* if No Candidate BSS is found, try BSSes which are in blacklist */ + if (!fgSearchBlackList && prEssLink->u4NumElem > 0) { + fgSearchBlackList = TRUE; + log_dbg(SCN, INFO, "No Bss is found, Try blacklist\n"); + goto try_again; + } + log_dbg(SCN, INFO, "Selected None when find %s, " MACSTR + " in %d BSSes, fix channel %d.\n", + prConnSettings->aucSSID, MAC2STR(prConnSettings->aucBSSID), + prEssLink->u4NumElem, ucChannel); + return NULL; +} + +void scanGetCurrentEssChnlList(struct ADAPTER *prAdapter) +{ + struct BSS_DESC *prBssDesc = NULL; + struct LINK *prBSSDescList = + &prAdapter->rWifiVar.rScanInfo.rBSSDescList; + struct CONNECTION_SETTINGS *prConnSettings = &prAdapter-> + rWifiVar.rConnSettings; + struct ESS_CHNL_INFO *prEssChnlInfo = &prAdapter-> + rWifiVar.rAisSpecificBssInfo.arCurEssChnlInfo[0]; + struct LINK *prCurEssLink = &prAdapter-> + rWifiVar.rAisSpecificBssInfo.rCurEssLink; + uint8_t aucChnlBitMap[30] = {0,}; + uint8_t aucChnlApNum[215] = {0,}; + uint8_t aucChnlUtil[215] = {0,}; + uint8_t ucByteNum = 0; + uint8_t ucBitNum = 0; + uint8_t ucChnlCount = 0; + uint8_t j = 0; + + if (prConnSettings->ucSSIDLen == 0) { + log_dbg(SCN, INFO, "No Ess are expected to connect\n"); + return; + } + kalMemZero(prEssChnlInfo, CFG_MAX_NUM_OF_CHNL_INFO * + sizeof(struct ESS_CHNL_INFO)); + while (!LINK_IS_EMPTY(prCurEssLink)) { + prBssDesc = +LINK_PEEK_HEAD(prCurEssLink, + struct BSS_DESC, rLinkEntryEss); + LINK_REMOVE_KNOWN_ENTRY(prCurEssLink, + &prBssDesc->rLinkEntryEss); + } + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, + struct BSS_DESC) { + if (prBssDesc->ucChannelNum > 214) + continue; + /* Statistic AP num for each channel */ + if (aucChnlApNum[prBssDesc->ucChannelNum] < 255) + aucChnlApNum[prBssDesc->ucChannelNum]++; + if (aucChnlUtil[prBssDesc->ucChannelNum] < + prBssDesc->ucChnlUtilization) + aucChnlUtil[prBssDesc->ucChannelNum] = + prBssDesc->ucChnlUtilization; + if (!EQUAL_SSID(prConnSettings->aucSSID, + prConnSettings->ucSSIDLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen)) + continue; + /* Record same BSS list */ + LINK_INSERT_HEAD(prCurEssLink, &prBssDesc->rLinkEntryEss); + ucByteNum = prBssDesc->ucChannelNum / 8; + ucBitNum = prBssDesc->ucChannelNum % 8; + if (aucChnlBitMap[ucByteNum] & BIT(ucBitNum)) + continue; + aucChnlBitMap[ucByteNum] |= BIT(ucBitNum); + prEssChnlInfo[ucChnlCount].ucChannel = prBssDesc->ucChannelNum; + ucChnlCount++; + if (ucChnlCount >= CFG_MAX_NUM_OF_CHNL_INFO) + break; + } + prAdapter->rWifiVar.rAisSpecificBssInfo.ucCurEssChnlInfoNum = + ucChnlCount; + for (j = 0; j < ucChnlCount; j++) { + uint8_t ucChnl = prEssChnlInfo[j].ucChannel; + + prEssChnlInfo[j].ucApNum = aucChnlApNum[ucChnl]; + prEssChnlInfo[j].ucUtilization = aucChnlUtil[ucChnl]; + } +#if 0 + /* Sort according to AP number */ + for (j = 0; j < ucChnlCount; j++) { + for (i = j + 1; i < ucChnlCount; i++) + if (prEssChnlInfo[j].ucApNum > + prEssChnlInfo[i].ucApNum) { + struct ESS_CHNL_INFO rTemp = prEssChnlInfo[j]; + + prEssChnlInfo[j] = prEssChnlInfo[i]; + prEssChnlInfo[i] = rTemp; + } + } +#endif + log_dbg(SCN, INFO, "Find %s in %d BSSes, result %d\n", + prConnSettings->aucSSID, prBSSDescList->u4NumElem, + prCurEssLink->u4NumElem); +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/assoc.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/assoc.c new file mode 100644 index 0000000000000..e655b839beb41 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/assoc.c @@ -0,0 +1,2085 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/assoc.c#5 + */ + +/*! \file "assoc.c" + * \brief This file includes the 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 + ******************************************************************************* + */ +struct APPEND_VAR_IE_ENTRY txAssocReqIETable[] = { +#if CFG_SUPPORT_SPEC_MGMT + {(ELEM_HDR_LEN + ELEM_MAX_LEN_POWER_CAP), + NULL, rlmReqGeneratePowerCapIE} + , /* 33 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_SUPPORTED_CHANNELS), + NULL, rlmReqGenerateSupportedChIE} + , /* 36 */ +#endif +#if CFG_SUPPORT_802_11K + {(ELEM_HDR_LEN + 2), NULL, rlmGeneratePowerCapIE}, /* Element ID: 33 */ +#endif + {(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_802_11R + {(ELEM_HDR_LEN + 1), NULL, assocGenerateMDIE}, /* Element ID: 54 */ + {0, rsnCalculateFTIELen, rsnGenerateFTIE}, /* Element ID: 55 */ +#endif +#if CFG_SUPPORT_WAPI + {(ELEM_HDR_LEN + ELEM_MAX_LEN_WAPI), NULL, wapiGenerateWAPIIE} + , /* 68 */ +#endif +#if CFG_SUPPORT_802_11K + {(ELEM_HDR_LEN + 5), NULL, + rlmGenerateRRMEnabledCapIE}, /* Element ID: 70 */ +#endif +#if CFG_SUPPORT_PASSPOINT + {(ELEM_HDR_LEN + ELEM_MAX_LEN_INTERWORKING), NULL, + hs20GenerateInterworkingIE} + , /* 107 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_ROAMING_CONSORTIUM), NULL, + hs20GenerateRoamingConsortiumIE} + , /* 111 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_HS20_INDICATION), NULL, + hs20GenerateHS20IE} + , /* 221 */ +#endif /* CFG_SUPPORT_PASSPOINT */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP), NULL, rlmReqGenerateExtCapIE} + , /* 127 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_INFO), NULL, mqmGenerateWmmInfoIE} + , /* 221 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_RSN), NULL, rsnGenerateRSNIE} + , /* 48 */ +#if CFG_SUPPORT_802_11AC + {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP), NULL, rlmReqGenerateVhtCapIE} + , /*191 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP_MODE_NOTIFICATION), NULL, + rlmReqGenerateVhtOpNotificationIE} + , /*199 */ +#endif +#if CFG_SUPPORT_MTK_SYNERGY + {(ELEM_HDR_LEN + ELEM_MIN_LEN_MTK_OUI), NULL, rlmGenerateMTKOuiIE} + , /* 221 */ +#endif + {(ELEM_HDR_LEN + ELEM_MAX_LEN_WPA), NULL, rsnGenerateWPAIE} + , /* 221 */ +#if CFG_SUPPORT_OWE + {0, rsnCalOweIELen, rsnGenerateOWEIE} /* 255 */ +#endif +}; + +#if CFG_SUPPORT_AAA +struct VERIFY_IE_ENTRY rxAssocReqIETable[] = { + {ELEM_ID_RESERVED, NULL} /* 255 */ +}; + +struct APPEND_VAR_IE_ENTRY 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 */ +#if CFG_SUPPORT_802_11AC + {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP), NULL, rlmRspGenerateVhtCapIE} + , /*191 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP), NULL, rlmRspGenerateVhtOpIE} + , /*192 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP_MODE_NOTIFICATION), NULL, + rlmRspGenerateVhtOpNotificationIE} + , /*199 */ +#endif + {(ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_PARAM), NULL, mqmGenerateWmmParamIE} + , /* 221 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_ASSOC_RSP_WSC_IE), NULL, + rsnGenerateWSCIEForAssocRsp} + , /* 221 */ +#if CFG_SUPPORT_MTK_SYNERGY + {(ELEM_HDR_LEN + ELEM_MIN_LEN_MTK_OUI), NULL, rlmGenerateMTKOuiIE} + /* 221 */ +#endif + , +#if CFG_SUPPORT_802_11W + {(ELEM_HDR_LEN + ELEM_MAX_LEN_TIMEOUT_IE), NULL, + rsnPmfGenerateTimeoutIE} + /* 56 */ +#endif + +}; +#endif /* 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 + ******************************************************************************* + */ +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is used to compose the Capability Info Field. + * + * @param[in] prStaRec Pointer to the STA_RECORD_T + * + * @retval Capability Info Field + */ +/*----------------------------------------------------------------------------*/ + +uint16_t assocBuildCapabilityInfo(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + uint32_t u4NonHTPhyType; + uint16_t u2CapInfo; + struct BSS_INFO *prBssInfo; + + ASSERT(prStaRec); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + /* Set up our requested capabilities. */ + u2CapInfo = CAP_INFO_ESS; + u2CapInfo |= CAP_CF_STA_NOT_POLLABLE; +#if CFG_SUPPORT_802_11K + u2CapInfo |= CAP_INFO_RADIO_MEASUREMENT; +#endif + + if (prStaRec->u2CapInfo & CAP_INFO_PRIVACY) + u2CapInfo |= CAP_INFO_PRIVACY; + + /* 7.3.1.4 */ + if (prStaRec->fgHasBasicPhyType) { + u4NonHTPhyType = prStaRec->ucNonHTBasicPhyType; + + if ((rNonHTPhyAttributes + [u4NonHTPhyType].fgIsShortPreambleOptionImplemented) && + /* Short Preamble Option Enable is TRUE */ + ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_SHORT) + || + ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_AUTO) + && (prStaRec->u2CapInfo & CAP_INFO_SHORT_PREAMBLE)))) { + + /* Case I: Implemented == TRUE + * and Short Preamble Option Enable == TRUE. + * Case II: Implemented == TRUE + * and Short Preamble == AUTO (depends on + * struct BSS_DESC's capability) + */ + u2CapInfo |= CAP_INFO_SHORT_PREAMBLE; + } +#if CFG_SUPPORT_SPEC_MGMT + /* 802.11h spectrum management is for 5G band, so + * now we only enable spectrum management bit for 5G case. + * In TGn 5.2.22, spectrum management bit should set to 1 + * to pass the UCC's check. + */ + if (prBssInfo && prBssInfo->eBand == BAND_5G) + u2CapInfo |= CAP_INFO_SPEC_MGT; +#endif + + 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) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void assocBuildReAssocReqFrameCommonIEs( + IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct CONNECTION_SETTINGS *prConnSettings; + struct STA_RECORD *prStaRec; + uint8_t *pucBuffer; + uint16_t u2SupportedRateSet; + uint8_t aucAllSupportedRates[RATE_NUM_SW] = { 0 }; + uint8_t ucAllSupportedRatesLen; + uint8_t ucSupRatesLen; + uint8_t ucExtSupRatesLen; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + ASSERT(prMsduInfo); + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + if (!prStaRec) + return; + + pucBuffer = + (uint8_t *) ((unsigned long)prMsduInfo->prPacket + + (unsigned long)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_BOW_TYPE(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 + + /* 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->ucDesiredPhyTypeSet) { + uint32_t u4NonHTPhyType; + + u4NonHTPhyType = prStaRec->ucNonHTBasicPhyType; + + u2SupportedRateSet = (prStaRec->u2OperationalRateSet & + rNonHTPhyAttributes + [u4NonHTPhyType].u2SupportedRateSet); + + /*ASSERT(u2SupportedRateSet); */ + + if (!u2SupportedRateSet) { + DBGLOG(SAA, INFO, + "RateSet NonHTPhyType=%d OperationalRateSet=%d\n", + u4NonHTPhyType, prStaRec->u2OperationalRateSet); + 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); + } + } +} /* 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) + */ +/*----------------------------------------------------------------------------*/ +void +assocComposeReAssocReqFrameHeaderAndFF(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN uint8_t *pucBuffer, + IN uint8_t aucMACAddress[], + IN OUT uint16_t *pu2PayloadLen) +{ + struct WLAN_ASSOC_REQ_FRAME *prAssocFrame; + u_int8_t fgIsReAssoc; + + uint16_t u2FrameCtrl; + uint16_t u2CapInfo; + uint16_t u2ListenInterval; + + ASSERT(prStaRec); + ASSERT(pucBuffer); + ASSERT(aucMACAddress); + ASSERT(pu2PayloadLen); + + prAssocFrame = (struct WLAN_ASSOC_REQ_FRAME *)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)) { + + struct BSS_INFO *prAisBssInfo = prAdapter->prAisBssInfo; + struct WLAN_REASSOC_REQ_FRAME *prReAssocFrame = + (struct WLAN_REASSOC_REQ_FRAME *)prAssocFrame; + + COPY_MAC_ADDR(prReAssocFrame->aucCurrentAPAddr, + prAisBssInfo->aucBSSID); + } else { + ASSERT(0); + /* We don't support ReAssociation for other network */ + } + + *pu2PayloadLen = + (CAP_INFO_FIELD_LEN + LISTEN_INTERVAL_FIELD_LEN + + CURR_AP_ADDR_FIELD_LEN); + } else { + *pu2PayloadLen = + (CAP_INFO_FIELD_LEN + LISTEN_INTERVAL_FIELD_LEN); + } +} /* end of assocComposeReAssocReqFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will send the (Re)Association Request frame + * + * @param[in] prStaRec Pointer to the STA_RECORD_T + * + * @retval WLAN_STATUS_RESOURCES No available resource for frame composing. + * @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module + */ +/*----------------------------------------------------------------------------*/ +uint32_t assocSendReAssocReqFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + struct MSDU_INFO *prMsduInfo; + struct BSS_INFO *prBssInfo; + + uint16_t u2PayloadLen; + uint16_t u2EstimatedFrameLen; + uint16_t u2EstimatedExtraIELen; + u_int8_t fgIsReAssoc; + uint32_t 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_SW - 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_SW - ELEM_MAX_LEN_SUP_RATES)); + } + + /* + Extra IE Length */ + u2EstimatedExtraIELen = 0; + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 && CFG_ENABLE_WIFI_DIRECT + if (IS_STA_IN_P2P(prStaRec)) { + if ((prAdapter->fgIsP2PRegistered)) { + u2EstimatedExtraIELen = + p2pCalculate_IEForAssocReq(prAdapter, + prStaRec->ucBssIndex, + prStaRec); + } else { + DBGLOG(P2P, TRACE, "Function Linker Lost.\n"); + ASSERT(FALSE); + } + } else { + for (i = 0; + i < + sizeof(txAssocReqIETable) / + sizeof(struct APPEND_VAR_IE_ENTRY); i++) { + if (txAssocReqIETable[i].u2EstimatedFixedIELen != 0) { + u2EstimatedExtraIELen += + txAssocReqIETable[i].u2EstimatedFixedIELen; + } else { + u2EstimatedExtraIELen += (uint16_t) + txAssocReqIETable + [i].pfnCalculateVariableIELen(prAdapter, + prStaRec->ucBssIndex, prStaRec); + } + } + /* Calculate non-wfa vendor specific ie len */ + u2EstimatedExtraIELen += + assoc_get_nonwfa_vend_ie_len(prAdapter); + } +#else + for (i = 0; + i < sizeof(txAssocReqIETable) / sizeof(struct APPEND_VAR_IE_ENTRY); + i++) { + if (txAssocReqIETable[i].u2EstimatedFixedIELen != 0) { + u2EstimatedExtraIELen += + txAssocReqIETable[i].u2EstimatedFixedIELen; + } else { + u2EstimatedExtraIELen += (uint16_t) + txAssocReqIETable[i].pfnCalculateVariableIELen + (prAdapter, prStaRec->ucBssIndex, prStaRec); + } + } + /* Calculate non-wfa vendor specific ie len */ + u2EstimatedExtraIELen += assoc_get_nonwfa_vend_ie_len(prAdapter); +#endif + + ASSERT(prStaRec->ucBssIndex <= prAdapter->ucHwBssIdNum); + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SAA, WARN, + "No PKT_INFO_T for sending (Re)Assoc Request.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose (Re)Association Request frame header and fixed fields + * in MSDU_INfO_T. + */ + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + /* Compose Header and Fixed Field */ + assocComposeReAssocReqFrameHeaderAndFF(prAdapter, + prStaRec, + (uint8_t + *) ((unsigned + long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD), + prBssInfo->aucOwnMacAddr, + &u2PayloadLen); + + /* 4 <3> Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, + saaFsmRunEventTxDone, MSDU_RATE_MODE_AUTO); + + /* 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 (IS_STA_IN_P2P(prStaRec)) { + 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(struct APPEND_VAR_IE_ENTRY); i++) { + if (txAssocReqIETable[i].pfnAppendIE) + txAssocReqIETable[i].pfnAppendIE(prAdapter, + prMsduInfo); + + } + /* Append non-wfa vendor specific ies for AIS mode */ + assoc_build_nonwfa_vend_ie(prAdapter, prMsduInfo); + } +#else + /* Append IE */ + for (i = 0; + i < sizeof(txAssocReqIETable) / sizeof(struct APPEND_VAR_IE_ENTRY); + i++) { + if (txAssocReqIETable[i].pfnAppendIE) + txAssocReqIETable[i].pfnAppendIE(prAdapter, prMsduInfo); + + } + /* Append non-wfa vendor specific ies for AIS mode */ + assoc_build_nonwfa_vend_ie(prAdapter, prMsduInfo); +#endif + + /* 4 <6> Update the (Re)association request information */ + if (IS_STA_IN_AIS(prStaRec)) { + struct WLAN_ASSOC_REQ_FRAME *prAssocFrame; + + prAssocFrame = + (struct WLAN_ASSOC_REQ_FRAME + *)((unsigned long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + + kalUpdateReAssocReqInfo(prAdapter->prGlueInfo, + (uint8_t *) &prAssocFrame->u2CapInfo, + prMsduInfo->u2FrameLength - + offsetof(struct WLAN_ASSOC_REQ_FRAME, + u2CapInfo), fgIsReAssoc); + } +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) { + struct WLAN_ASSOC_REQ_FRAME *prAssocFrame; + + prAssocFrame = + (struct WLAN_ASSOC_REQ_FRAME + *)((unsigned long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + + kalP2PUpdateAssocInfo(prAdapter->prGlueInfo, + (uint8_t *) &prAssocFrame->u2CapInfo, + prMsduInfo->u2FrameLength - + offsetof(struct WLAN_ASSOC_REQ_FRAME, + u2CapInfo), fgIsReAssoc, + prStaRec->ucBssIndex); + } +#endif + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU + */ + + nicTxConfigPktControlFlag(prMsduInfo, MSDU_CONTROL_FLAG_FORCE_TX, TRUE); + + /* 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t assocCheckTxReAssocReqFrame(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct WLAN_ASSOC_REQ_FRAME *prAssocReqFrame; + struct STA_RECORD *prStaRec; + uint16_t u2TxFrameCtrl; + + ASSERT(prMsduInfo); + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + + prAssocReqFrame = (struct WLAN_ASSOC_REQ_FRAME *)(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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t assocCheckTxReAssocRespFrame(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct WLAN_ASSOC_RSP_FRAME *prAssocRspFrame; + struct STA_RECORD *prStaRec; + uint16_t u2TxFrameCtrl; + + ASSERT(prMsduInfo); + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + + prAssocRspFrame = (struct WLAN_ASSOC_RSP_FRAME *)(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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t +assocCheckRxReAssocRspFrameStatus(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + OUT uint16_t *pu2StatusCode) +{ + struct STA_RECORD *prStaRec; + struct WLAN_ASSOC_RSP_FRAME *prAssocRspFrame; + uint16_t u2RxFrameCtrl; + uint16_t u2RxCapInfo; + uint16_t u2RxStatusCode; + uint16_t u2RxAssocId; + + if (!prSwRfb || !pu2StatusCode) { + DBGLOG(SAA, ERROR, "Invalid parameter, ignore!\n"); + return WLAN_STATUS_FAILURE; + } + + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < + (CAP_INFO_FIELD_LEN + + STATUS_CODE_FIELD_LEN + + AID_FIELD_LEN)) { + DBGLOG(SAA, WARN, "Invalid AssocRsp length!"); + return WLAN_STATUS_FAILURE; + } + + DBGLOG(SAA, LOUD, "prSwRfb->u2PayloadLength = %d\n", + prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (!prStaRec) { + DBGLOG(SAA, ERROR, "Invalid prStaRec, ignore!\n"); + return WLAN_STATUS_INVALID_PACKET; + } + + /* 4 <1> locate the (Re)Association Resp Frame. */ + prAssocRspFrame = (struct WLAN_ASSOC_RSP_FRAME *)prSwRfb->pvHeader; + + /* If Association Response's BSSID doesn't match + * our target, ignore. + */ + if (!EQUAL_MAC_ADDR(prAssocRspFrame->aucBSSID, + prStaRec->aucMacAddr)) { + DBGLOG(SAA, INFO, "Unknown BSSID\n"); + return WLAN_STATUS_FAILURE; + } + + /* 4 <2> Parse the Header of (Re)Association Resp Frame. */ + /* WLAN_GET_FIELD_16(&prAssocRspFrame->u2FrameCtrl, &u2RxFrameCtrl); */ + u2RxFrameCtrl = prAssocRspFrame->u2FrameCtrl; + /* NOTE(Kevin): Optimized for ARM */ + u2RxFrameCtrl &= MASK_FRAME_TYPE; + if (prStaRec->fgIsReAssoc) { + if (u2RxFrameCtrl != MAC_FRAME_REASSOC_RSP) + return WLAN_STATUS_FAILURE; + + } else { + if (u2RxFrameCtrl != MAC_FRAME_ASSOC_RSP) + return WLAN_STATUS_FAILURE; + + } + + /* 4 <3> Parse the Fixed Fields of (Re)Association Resp Frame Body. */ + /* WLAN_GET_FIELD_16(&prAssocRspFrame->u2CapInfo, &u2RxCapInfo); */ + u2RxCapInfo = prAssocRspFrame->u2CapInfo; + /* NOTE(Kevin): Optimized for ARM */ + + /* WLAN_GET_FIELD_16(&prAssocRspFrame->u2StatusCode, &u2RxStatusCode); + */ + u2RxStatusCode = prAssocRspFrame->u2StatusCode; + /* NOTE(Kevin): Optimized for ARM */ + + /* 4 <4> Check CAP_INFO */ + /* NOTE(Kevin): CM suggest to add MGMT workaround for those APs + * didn't check the CAP Privacy Bit to overcome a corner case + * that the Privacy Bit of our SCAN result didn't consist with + * AP's Association Resp. + */ + if (u2RxStatusCode == STATUS_CODE_SUCCESSFUL) { +#if CFG_SUPPORT_WAPI + if (prAdapter->rWifiVar.rConnSettings.fgWapiMode) { + /* WAPI AP allow the customer use WZC to join mode, + * the privacy bit is 0 even at WAI & WAPI_PSK mode, + * but the assoc respose set the privacy bit set 1 + */ + DBGLOG(SEC, TRACE, + "Workaround the WAPI AP allow the customer to use WZC to join\n"); + } else +#endif +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered && 1) { + /* Todo:: Fixed this */ + } else +#endif + { + } + +#if CFG_STRICT_CHECK_CAPINFO_PRIVACY + if ((prStaRec->u2CapInfo & CAP_INFO_PRIVACY) ^ + (u2RxCapInfo & CAP_INFO_PRIVACY)) + u2RxStatusCode = STATUS_CODE_CAP_NOT_SUPPORTED; + +#endif + } + + if (u2RxStatusCode == STATUS_CODE_SUCCESSFUL) { + /* Update the information in the structure used to query and set + * OID_802_11_ASSOCIATION_INFORMATION. + */ + kalUpdateReAssocRspInfo(prAdapter->prGlueInfo, + (uint8_t *) & + prAssocRspFrame->u2CapInfo, + (uint32_t) (prSwRfb->u2PacketLen)); + } + /* 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->eStaType == STA_TYPE_LEGACY_AP) { + struct AIS_SPECIFIC_BSS_INFO *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) { + uint8_t *pucIE, *pucTime; + uint16_t u2IELength; + uint16_t u2Offset = 0; + + u2IELength = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen; + pucIE = + (uint8_t *) ((unsigned long)prSwRfb->pvHeader + + prSwRfb->u2HeaderLen); + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (IE_ID(pucIE) == ELEM_ID_TIMEOUT_INTERVAL + && IE_LEN(pucIE) == 5) { + pucTime = ((struct IE_HDR *)pucIE)->aucInfo; + if (pucTime[0] == + ACTION_SA_TIMEOUT_ASSOC_COMEBACK) { + uint32_t tu; + + WLAN_GET_FIELD_32(pucTime + 1, &tu); + DBGLOG(SAA, INFO, + "AP rejected association temporarily;comeback duration %u TU (%u ms)\n", + tu, TU_TO_MSEC(tu)); + if (tu > + TX_ASSOCIATION_RETRY_TIMEOUT_TU) { + DBGLOG(SAA, INFO, + "Update timer based on comeback duration\n"); + /* ieee80211_reschedule_timer( + * wpa_s, ms); + */ + } + } + break; + } + } /* end of IE_FOR_EACH */ + } +#endif + *pu2StatusCode = u2RxStatusCode; + + return WLAN_STATUS_SUCCESS; + +} /* end of assocCheckRxReAssocRspFrameStatus() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will compose the Disassociation frame + * + * @param[in] prStaRec Pointer to the STA_RECORD_T + * @param[in] pucBuffer Pointer to the frame buffer. + * @param[in] aucMACAddress Given Our MAC Address. + * @param[in] u2ReasonCode The reason code of disassociation + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void +assocComposeDisassocFrame(IN struct STA_RECORD *prStaRec, + IN uint8_t *pucBuffer, IN uint8_t aucMACAddress[], + IN uint16_t u2ReasonCode) +{ + struct WLAN_DISASSOC_FRAME *prDisAssocFrame; + uint16_t u2FrameCtrl; + + ASSERT(pucBuffer); + ASSERT(pucBuffer); + ASSERT(aucMACAddress); + + prDisAssocFrame = (struct WLAN_DISASSOC_FRAME *)pucBuffer; + + /* 4 <1> Compose the frame header of the DisAssociation frame. */ + /* Fill the Frame Control field. */ + u2FrameCtrl = MAC_FRAME_DISASSOC; + + WLAN_SET_FIELD_16(&prDisAssocFrame->u2FrameCtrl, u2FrameCtrl); + + /* Fill the DA field with Target BSSID. */ + COPY_MAC_ADDR(prDisAssocFrame->aucDestAddr, prStaRec->aucMacAddr); + + /* Fill the SA field with our MAC Address. */ + COPY_MAC_ADDR(prDisAssocFrame->aucSrcAddr, aucMACAddress); + + /* Fill the BSSID field with Target BSSID. */ + COPY_MAC_ADDR(prDisAssocFrame->aucBSSID, prStaRec->aucMacAddr); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, + * so we need to clear it). + */ + prDisAssocFrame->u2SeqCtrl = 0; + + /* 4 <2> Compose the frame body's fixed field part of + * the Disassociation frame. + */ + /* Fill the Reason Code field. */ + WLAN_SET_FIELD_16(&prDisAssocFrame->u2ReasonCode, u2ReasonCode); +} /* end of assocComposeDisassocFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will send the Disassociation frame + * + * @param[in] prStaRec Pointer to the STA_RECORD_T + * @param[in] u2ReasonCode The reason code of disassociation + * + * @retval WLAN_STATUS_RESOURCES No available resource for frame composing. + * @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module + */ +/*----------------------------------------------------------------------------*/ +uint32_t assocSendDisAssocFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN uint16_t u2ReasonCode) +{ + uint8_t *pucMacAddress; + struct MSDU_INFO *prMsduInfo; + uint16_t u2PayloadLen; + uint16_t u2EstimatedFrameLen; +#if CFG_SUPPORT_CFG80211_AUTH + struct WLAN_DISASSOC_FRAME *prDisassocFrame; +#endif + /* UINT_32 u4Status = WLAN_STATUS_SUCCESS; */ + + ASSERT(prStaRec); + ASSERT(prStaRec->ucBssIndex <= prAdapter->ucHwBssIdNum); + + DBGLOG(RSN, INFO, "assocSendDisAssocFrame\n"); + + /* 4 <1> Allocate a PKT_INFO_T for Disassociation Frame */ + /* Init with MGMT Header Length + Length of Fixed Fields + IE Length */ + u2EstimatedFrameLen = + MAC_TX_RESERVED_FIELD + WLAN_MAC_MGMT_HEADER_LEN + + REASON_CODE_FIELD_LEN; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SAA, WARN, "No PKT_INFO_T for sending DisAssoc.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Disassociation frame header and fixed fields + * in MSDU_INfO_T. + */ + pucMacAddress = + GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex)->aucOwnMacAddr; + + /* Compose Header and Fixed Field */ + assocComposeDisassocFrame(prStaRec, + (uint8_t + *) ((unsigned long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD), pucMacAddress, + u2ReasonCode); + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + /* PMF certification 4.3.3.1, 4.3.3.2 send unprotected + * deauth reason 6/7 + */ + if (prStaRec->rPmfCfg.fgRxDeauthResp != TRUE) { + + struct WLAN_DISASSOC_FRAME *prDisassocFrame; + + prDisassocFrame = + (struct WLAN_DISASSOC_FRAME + *)((unsigned long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + + prDisassocFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + } + } +#endif + + u2PayloadLen = REASON_CODE_FIELD_LEN; + + /* 4 <3> Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, NULL, + MSDU_RATE_MODE_AUTO); + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + /* caution: access prStaRec only if true */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + /* 4.3.3.1 send unprotected deauth reason 6/7 */ + if (prStaRec->rPmfCfg.fgRxDeauthResp != TRUE) { + DBGLOG(RSN, INFO, + "Disassoc Set MSDU_OPT_PROTECTED_FRAME\n"); + nicTxConfigPktOption(prMsduInfo, + MSDU_OPT_PROTECTED_FRAME, TRUE); + } + + prStaRec->rPmfCfg.fgRxDeauthResp = FALSE; + } +#endif + DBGLOG(SAA, INFO, "ucTxSeqNum=%d ucStaRecIndex=%d u2ReasonCode=%d\n", + prMsduInfo->ucTxSeqNum, prMsduInfo->ucStaRecIndex, u2ReasonCode); + +#if CFG_SUPPORT_CFG80211_AUTH + prDisassocFrame = (struct WLAN_DISASSOC_FRAME *) + ((unsigned long) (prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + DBGLOG(SAA, INFO, "notification of TX disassociation, %d\n", + prMsduInfo->u2FrameLength); + cfg80211_tx_mlme_mgmt(prAdapter->prGlueInfo->prDevHandler, + (uint8_t *)prDisassocFrame, + (size_t)prMsduInfo->u2FrameLength); + DBGLOG(SAA, INFO, "notification of TX disassociation, Done\n"); +#endif + + /* 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t +assocProcessRxDisassocFrame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, IN uint8_t aucBSSID[], + OUT uint16_t *pu2ReasonCode) +{ + struct WLAN_DISASSOC_FRAME *prDisassocFrame; + uint16_t u2RxReasonCode; + + if (!prSwRfb || !aucBSSID || !pu2ReasonCode) { + DBGLOG(SAA, WARN, "Invalid parameters, ignore pkt!\n"); + return WLAN_STATUS_FAILURE; + } + + /* 4 <1> locate the Disassociation Frame. */ + prDisassocFrame = (struct WLAN_DISASSOC_FRAME *)prSwRfb->pvHeader; + + /* 4 <2> Parse the Header of Disassociation Frame. */ + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < + REASON_CODE_FIELD_LEN) { + DBGLOG(SAA, LOUD, "Invalid DisAssoc packet length!"); + 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t assocProcessRxAssocReqFrame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + OUT uint16_t *pu2StatusCode) +{ + struct WLAN_ASSOC_REQ_FRAME *prAssocReqFrame; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + struct IE_SSID *prIeSsid = (struct IE_SSID *)NULL; + struct RSN_INFO_ELEM *prIeRsn = (struct RSN_INFO_ELEM *)NULL; + struct IE_SUPPORTED_RATE *prIeSupportedRate = + (struct IE_SUPPORTED_RATE *)NULL; + struct IE_EXT_SUPPORTED_RATE *prIeExtSupportedRate = + (struct IE_EXT_SUPPORTED_RATE *)NULL; + struct WIFI_VAR *prWifiVar = NULL; + uint8_t *pucIE, *pucIEStart; + uint16_t u2IELength; + uint16_t u2Offset = 0; + uint16_t u2StatusCode = STATUS_CODE_SUCCESSFUL; + uint16_t u2RxFrameCtrl; + uint16_t u2BSSBasicRateSet; + uint8_t ucFixedFieldLength; + u_int8_t fgIsUnknownBssBasicRate; + uint32_t i; + u_int8_t fgIsTKIP = FALSE; + + if (!prAdapter || !prSwRfb || !pu2StatusCode) { + DBGLOG(SAA, WARN, "Invalid parameters, ignore pkt!\n"); + return WLAN_STATUS_FAILURE; + } + + prWifiVar = &(prAdapter->rWifiVar); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prStaRec == NULL) + return WLAN_STATUS_FAILURE; + + /* 4 <1> locate the Association Req Frame. */ + prAssocReqFrame = (struct WLAN_ASSOC_REQ_FRAME *)prSwRfb->pvHeader; + + /* WLAN_GET_FIELD_16(&prAssocReqFrame->u2FrameCtrl, + * &u2RxFrameCtrl); + */ + u2RxFrameCtrl = prAssocReqFrame->u2FrameCtrl; + /* NOTE(Kevin): Optimized for ARM */ + u2RxFrameCtrl &= MASK_FRAME_TYPE; + + /* 4 <2> Parse the Header of Association Req Frame. */ + if (u2RxFrameCtrl == MAC_FRAME_REASSOC_REQ) + ucFixedFieldLength = + CAP_INFO_FIELD_LEN + LISTEN_INTERVAL_FIELD_LEN + + CURR_AP_ADDR_FIELD_LEN; + else + ucFixedFieldLength = + CAP_INFO_FIELD_LEN + LISTEN_INTERVAL_FIELD_LEN; + + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) + <= ucFixedFieldLength) { + /* Length of this (re)association req is invalid, ignore it */ + return WLAN_STATUS_FAILURE; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + /* 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 */ + + if (u2RxFrameCtrl == MAC_FRAME_REASSOC_REQ) { + prStaRec->fgIsReAssoc = TRUE; + + u2IELength = prSwRfb->u2PacketLen - + (uint16_t) OFFSET_OF(struct WLAN_REASSOC_REQ_FRAME, + aucInfoElem[0]); + + pucIEStart = pucIE = + ((struct WLAN_REASSOC_REQ_FRAME *)(prSwRfb-> + pvHeader))->aucInfoElem; + } else { + prStaRec->fgIsReAssoc = FALSE; + + u2IELength = prSwRfb->u2PacketLen - + (uint16_t) OFFSET_OF(struct WLAN_ASSOC_REQ_FRAME, + aucInfoElem[0]); + + pucIEStart = pucIE = prAssocReqFrame->aucInfoElem; + } + + /* 4 <3> Parse the Fixed Fields of Assoc Req Frame Body. */ + prStaRec->u2CapInfo = prAssocReqFrame->u2CapInfo; + +#if 0 +/* CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_HOTSPOT_PRIVACY_CHECK */ + if (prAdapter->fgIsP2PRegistered && IS_STA_P2P_TYPE(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 = (struct IE_SSID *)pucIE; + } + break; + + case ELEM_ID_SUP_RATES: + if ((!prIeSupportedRate) + && (IE_LEN(pucIE) <= RATE_NUM_SW)) + 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_VHT_CAP: + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_VHT; + 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, + prStaRec, + &u2StatusCode); + if (u2StatusCode != STATUS_CODE_SUCCESSFUL) { + *pu2StatusCode = u2StatusCode; + return WLAN_STATUS_SUCCESS; + } + } +#endif + break; + case ELEM_ID_VENDOR: + if (p2pFuncParseCheckForTKIPInfoElem(pucIE)) + fgIsTKIP = TRUE; + +#if CFG_ENABLE_WIFI_DIRECT + { + if ((prAdapter->fgIsP2PRegistered)) { + uint8_t 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; + case ELEM_ID_IBSS_PARAM_SET: + /* Check IBSS parameter set length to avoid + * abnormal content + */ + if (IE_LEN(pucIE) != ELEM_MAX_LEN_IBSS_PARAMETER_SET) { + *pu2StatusCode = + STATUS_CODE_UNSPECIFIED_FAILURE; + DBGLOG(SAA, WARN, + "Invalid IBSS Parameter IE length!\n"); + return WLAN_STATUS_FAILURE; + } + break; + default: + for (i = 0; + i < + (sizeof(rxAssocReqIETable) / + sizeof(struct VERIFY_IE_ENTRY)); i++) { + + if (((IE_ID(pucIE)) == + rxAssocReqIETable[i].ucElemID) + && (rxAssocReqIETable[i].pfnVarifyIE != + NULL)) { + rxAssocReqIETable[i].pfnVarifyIE + (prAdapter, prSwRfb, + (struct IE_HDR *)pucIE, + &u2StatusCode); + + if (u2StatusCode != + STATUS_CODE_SUCCESSFUL) { + *pu2StatusCode = u2StatusCode; + return WLAN_STATUS_SUCCESS; + } + } + } + + break; + } + } /* end of IE_FOR_EACH */ + + /* + * According to TGn & TGac 4.2.44, AP should not bring HT/VHT Cap IE in + * the IE of Assoc resp, if the STA request to use TKIP cipher + */ + if (fgIsTKIP && !prWifiVar->ucApAllowHtVhtTkip) + prStaRec->ucPhyTypeSet &= ~(PHY_TYPE_BIT_VHT | PHY_TYPE_BIT_HT); + + /* parsing for WMM related information (2010/12/21) */ + mqmProcessAssocReq(prAdapter, prSwRfb, pucIEStart, u2IELength); + + do { +#if CFG_SUPPORT_AAA_CHECK_NO_SSID + DBGLOG(SAA, INFO, + "Driver configured to not check SSID field of Assoc Req!\n"); +#else + 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; + } +#endif + + prStaRec->u2OperationalRateSet = 0; + prStaRec->u2BSSBasicRateSet = 0; + + if (!prIeSupportedRate) { + DBGLOG(SAA, WARN, "Supported Rate not present!\n"); + u2StatusCode = + STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED; + break; + } + /* Ignore any Basic Bit */ + rateGetRateSetFromIEs(prIeSupportedRate, + prIeExtSupportedRate, + &prStaRec->u2OperationalRateSet, + &u2BSSBasicRateSet, + &fgIsUnknownBssBasicRate); + + if ((prBssInfo-> + u2BSSBasicRateSet & prStaRec->u2OperationalRateSet) + != prBssInfo->u2BSSBasicRateSet) { + u2StatusCode = + STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED; + DBGLOG(SAA, WARN, "Basic rate not supported!\n"); + break; + } + + /* Accpet the Sta, update BSSBasicRateSet from Bss */ + prStaRec->u2BSSBasicRateSet = + prBssInfo->u2BSSBasicRateSet; + + prStaRec->u2DesiredNonHTRateSet = + (prStaRec->u2OperationalRateSet & RATE_SET_ALL_ABG); + + if (HAL_RX_STATUS_GET_RF_BAND(prSwRfb->prRxStatus) == + BAND_2G4) { + 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; + } else { /* (BAND_5G == prBssDesc->eBande) */ + if (prStaRec->u2OperationalRateSet & + RATE_SET_OFDM) + prStaRec->ucPhyTypeSet |= + PHY_TYPE_BIT_OFDM; + } + + /* Update default Tx rate */ + nicTxUpdateStaRecDefaultRate(prStaRec); + +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_HOTSPOT_PRIVACY_CHECK + if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { + if (prIeRsn) { + if (!kalP2PGetCipher + (prAdapter->prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData)) { + 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 */ + { + uint8_t *cp = (uint8_t *) &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); + + if (prStaRec->pucAssocReqIe) { + kalMemCopy(prStaRec->pucAssocReqIe, + cp, u2IELength); + } else { + DBGLOG(SAA, LOUD, + "allocate memory for prStaRec->pucAssocReqIe failed!\n"); + return WLAN_STATUS_RESOURCES; + } + } + } +#endif + kalP2PUpdateAssocInfo(prAdapter->prGlueInfo, + (uint8_t *) &prAssocReqFrame->u2CapInfo, + u2IELength + + (prStaRec->fgIsReAssoc ? 10 : 4), + prStaRec->fgIsReAssoc, + prStaRec->ucBssIndex); + } +#endif + + *pu2StatusCode = u2StatusCode; + + return WLAN_STATUS_SUCCESS; + +} /* end of assocProcessRxAssocReqFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is used to compose Common Information Elements for + * Association Response Frame. + * + * @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. + * @param[in] prBssInfo Pointer to the BSS_INFO_T. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void +assocBuildReAssocRespFrameCommonIEs(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN struct BSS_INFO *prBssInfo) +{ + uint8_t *pucBuffer; + struct STA_RECORD *prStaRec; + uint8_t ucSupRatesLen; + uint8_t ucExtSupRatesLen; + + ASSERT(prMsduInfo); + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + pucBuffer = + (uint8_t *) ((unsigned long)prMsduInfo->prPacket + + (unsigned long)prMsduInfo->u2FrameLength); + ASSERT(pucBuffer); + + if (prBssInfo->ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) { + + ucSupRatesLen = ELEM_MAX_LEN_SUP_RATES; + ucExtSupRatesLen = + prBssInfo->ucAllSupportedRatesLen - ELEM_MAX_LEN_SUP_RATES; + } else { + ucSupRatesLen = prBssInfo->ucAllSupportedRatesLen; + ucExtSupRatesLen = 0; + } + + /* Fill the Supported Rates element. */ + if (ucSupRatesLen) { + SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_SUP_RATES; + SUP_RATES_IE(pucBuffer)->ucLength = ucSupRatesLen; + kalMemCopy(SUP_RATES_IE(pucBuffer)->aucSupportedRates, + prBssInfo->aucAllSupportedRates, ucSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } + + /* Fill the Extended Supported Rates element. */ + if (ucExtSupRatesLen) { + + EXT_SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_EXTENDED_SUP_RATES; + EXT_SUP_RATES_IE(pucBuffer)->ucLength = ucExtSupRatesLen; + + kalMemCopy(EXT_SUP_RATES_IE(pucBuffer)->aucExtSupportedRates, + &prBssInfo->aucAllSupportedRates[ucSupRatesLen], + ucExtSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + } +} /* end of assocBuildReAssocRespFrameCommonIEs() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will compose the (Re)Association Response frame + * + * @param[in] prStaRec Pointer to the STA_RECORD_T + * @param[in] pucBuffer Pointer to the frame buffer. + * @param[in] aucBssid Given BSSID. + * @param[in] u2CapInfo Capability Field of current BSS. + * @param[in out] pu2PayloadLen Return the length of the composed + * fixed fields + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void +assocComposeReAssocRespFrameHeaderAndFF(IN struct STA_RECORD *prStaRec, + IN uint8_t *pucBuffer, + IN uint8_t aucBSSID[], + IN uint16_t u2CapInfo, + IN OUT uint16_t *pu2PayloadLen) +{ + struct WLAN_ASSOC_RSP_FRAME *prAssocRspFrame; + u_int8_t fgIsReAssoc; + + uint16_t u2FrameCtrl; + + ASSERT(prStaRec); + ASSERT(pucBuffer); + ASSERT(aucBSSID); + ASSERT(pu2PayloadLen); + + prAssocRspFrame = (struct WLAN_ASSOC_RSP_FRAME *)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)); + */ + /* NOTE(Kevin): Optimized for ARM */ + prAssocRspFrame->u2AssocId = + ((prStaRec->u2AssocId & AID_MASK) | AID_MSB); + + *pu2PayloadLen = + (CAP_INFO_FIELD_LEN + STATUS_CODE_FIELD_LEN + AID_FIELD_LEN); +} /* end of assocComposeReAssocRespFrameHeaderAndFF() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will send the (Re)Association Resp frame + * + * @param[in] prStaRec Pointer to the STA_RECORD_T + * + * @retval WLAN_STATUS_RESOURCES No available resource for frame composing. + * @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module + */ +/*----------------------------------------------------------------------------*/ +uint32_t assocSendReAssocRespFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + struct BSS_INFO *prBssInfo; + struct MSDU_INFO *prMsduInfo; + + uint16_t u2PayloadLen; + uint16_t u2EstimatedFrameLen; + uint16_t u2EstimatedExtraIELen; + u_int8_t fgIsReAssoc; + uint32_t i; + + ASSERT(prStaRec); + ASSERT(prStaRec->ucBssIndex <= prAdapter->ucHwBssIdNum); + + /* 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_SW - ELEM_MAX_LEN_SUP_RATES)); + + /* + Extra IE Length */ + u2EstimatedExtraIELen = 0; + + for (i = 0; + i < + sizeof(txAssocRespIETable) / sizeof(struct APPEND_VAR_IE_ENTRY); + i++) { + if (txAssocRespIETable[i].u2EstimatedFixedIELen != 0) { + u2EstimatedExtraIELen += + txAssocRespIETable[i].u2EstimatedFixedIELen; + } else if (txAssocRespIETable[i].pfnCalculateVariableIELen != + NULL) { + u2EstimatedExtraIELen += (uint16_t) + txAssocRespIETable[i].pfnCalculateVariableIELen + (prAdapter, prStaRec->ucBssIndex, prStaRec); + } + + } + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(AAA, WARN, + "No PKT_INFO_T for sending (Re)Assoc Response.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose (Re)Association Request frame header and fixed fields + * in MSDU_INfO_T. + */ + if (prAdapter->prAisBssInfo != NULL) { + ASSERT(prStaRec->ucBssIndex != + prAdapter->prAisBssInfo->ucBssIndex); + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + /* Compose Header and Fixed Field */ + assocComposeReAssocRespFrameHeaderAndFF(prStaRec, + (uint8_t *) ((unsigned long) + (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + prBssInfo->aucBSSID, prBssInfo->u2CapInfo, + &u2PayloadLen); + + /* 4 <3> Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, + aaaFsmRunEventTxDone, MSDU_RATE_MODE_AUTO); + + /* 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(struct APPEND_VAR_IE_ENTRY); + i++) { + if (txAssocRespIETable[i].pfnAppendIE) + txAssocRespIETable[i].pfnAppendIE(prAdapter, + prMsduInfo); + + } + +#if CFG_SUPPORT_WFD + /* TODO put WFD IE in assoc resp if driver will send assoc resp */ + +#endif + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU + */ + + nicTxConfigPktControlFlag(prMsduInfo, MSDU_CONTROL_FLAG_FORCE_TX, TRUE); + + /* 4 <6> Enqueue the frame to send this (Re)Association request frame. + */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + DBGLOG(SAA, INFO, + "Send Assoc Resp to " MACSTR ", Seq: %d\n", + MAC2STR(prStaRec->aucMacAddr), prMsduInfo->ucTxSeqNum); + + return WLAN_STATUS_SUCCESS; + +} /* end of assocSendReAssocRespFrame() */ + +/*-----------------------------------------------------------------------*/ +/*! + * @brief Get the non-wfa vendor ie length that was previously set + * by wpa_supplicant for association request frame. + * + * @param prAdapter pointer to driver adapter + * + * @retval length of the non-wfa vendor ie + */ +/*-----------------------------------------------------------------------*/ +uint16_t assoc_get_nonwfa_vend_ie_len(struct ADAPTER *prAdapter) +{ + if (!prAdapter || !prAdapter->prGlueInfo) + return 0; + return prAdapter->prGlueInfo->non_wfa_vendor_ie_len; +} + +/*-----------------------------------------------------------------------*/ +/*! + * @brief Builds the non-wfa vendor specific ies into association + * request frame. + * + * @param prAdapter pointer to driver adapter + * prMsduInfo pointer to the msdu frame body + * + * @retval void + */ +/*-----------------------------------------------------------------------*/ +void assoc_build_nonwfa_vend_ie(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + uint8_t *ptr = NULL; + uint16_t len = 0; + + if (!prAdapter || !prMsduInfo) + return; + len = prAdapter->prGlueInfo->non_wfa_vendor_ie_len; + if (!len) + return; + + ptr = (uint8_t *)prMsduInfo->prPacket + + (uint16_t)prMsduInfo->u2FrameLength; + kalMemCopy(ptr, prAdapter->prGlueInfo->non_wfa_vendor_ie_buf, + len); + prMsduInfo->u2FrameLength += len; +} + +void assocGenerateMDIE(IN struct ADAPTER *prAdapter, + IN OUT struct MSDU_INFO *prMsduInfo) +{ + struct FT_IES *prFtIEs = &prAdapter->prGlueInfo->rFtIeForTx; + uint8_t *pucBuffer = + (uint8_t *)prMsduInfo->prPacket + prMsduInfo->u2FrameLength; + enum ENUM_PARAM_AUTH_MODE eAuthMode = + prAdapter->rWifiVar.rConnSettings.eAuthMode; + + /* don't include MDIE in assoc request frame if auth mode is not FT + * related + */ + if (eAuthMode != AUTH_MODE_NON_RSN_FT && + eAuthMode != AUTH_MODE_WPA2_FT && + eAuthMode != AUTH_MODE_WPA2_FT_PSK) + return; + + if (!prFtIEs->prMDIE) { + struct BSS_DESC *prBssDesc = + prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc; + uint8_t *pucIE = &prBssDesc->aucIEBuf[0]; + uint16_t u2IeLen = prBssDesc->u2IELength; + uint16_t u2IeOffSet = 0; + + IE_FOR_EACH(pucIE, u2IeLen, u2IeOffSet) + { + if (IE_ID(pucIE) == ELEM_ID_MOBILITY_DOMAIN) { + /* IE size for MD IE is fixed, it is 5 */ + prMsduInfo->u2FrameLength += 5; + kalMemCopy(pucBuffer, pucIE, 5); + break; + } + } + return; + } + prMsduInfo->u2FrameLength += + 5; /* IE size for MD IE is fixed, it is 5 */ + kalMemCopy(pucBuffer, prFtIEs->prMDIE, 5); +} + +#endif /* CFG_SUPPORT_AAA */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/auth.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/auth.c new file mode 100644 index 0000000000000..9894000453d17 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/auth.c @@ -0,0 +1,1529 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + +/******************************************************************************* + * C O M P I L E 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 + ******************************************************************************* + */ +struct APPEND_VAR_IE_ENTRY txAuthIETable[] = { + {(ELEM_HDR_LEN + ELEM_MAX_LEN_CHALLENGE_TEXT), NULL, + authAddIEChallengeText}, + {0, authCalculateRSNIELen, authAddRSNIE}, /* Element ID: 48 */ + {(ELEM_HDR_LEN + 1), NULL, authAddMDIE}, /* Element ID: 54 */ + {0, rsnCalculateFTIELen, rsnGenerateFTIE}, /* Element ID: 55 */ +}; + +struct HANDLE_IE_ENTRY rxAuthIETable[] = { + {ELEM_ID_CHALLENGE_TEXT, authHandleIEChallengeText} +}; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will compose the Authentication frame header and + * fixed fields. + * + * @param[in] pucBuffer Pointer to the frame buffer. + * @param[in] aucPeerMACAddress Given Peer MAC Address. + * @param[in] aucMACAddress Given Our MAC Address. + * @param[in] u2AuthAlgNum Authentication Algorithm Number + * @param[in] u2TransactionSeqNum Transaction Sequence Number + * @param[in] u2StatusCode Status Code + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void +authComposeAuthFrameHeaderAndFF(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN uint8_t *pucBuffer, + IN uint8_t aucPeerMACAddress[], + IN uint8_t aucMACAddress[], + IN uint16_t u2AuthAlgNum, + IN uint16_t u2TransactionSeqNum, + IN uint16_t u2StatusCode) +{ + struct WLAN_AUTH_FRAME *prAuthFrame; + uint16_t u2FrameCtrl; +#if CFG_SUPPORT_CFG80211_AUTH + struct CONNECTION_SETTINGS *prConnSettings; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); +#endif + + ASSERT(pucBuffer); + ASSERT(aucPeerMACAddress); + ASSERT(aucMACAddress); + + prAuthFrame = (struct WLAN_AUTH_FRAME *)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); + + if (prStaRec != NULL && IS_AP_STA(prStaRec)) { + /* Fill the BSSID field with Target BSSID. */ + COPY_MAC_ADDR(prAuthFrame->aucBSSID, aucPeerMACAddress); + + } else if (prStaRec != NULL && IS_CLIENT_STA(prStaRec)) { + /* Fill the BSSID field with Current BSSID. */ + COPY_MAC_ADDR(prAuthFrame->aucBSSID, aucMACAddress); + } else { + COPY_MAC_ADDR(prAuthFrame->aucBSSID, aucMACAddress); + DBGLOG(SAA, INFO, + "Error status code flow!\n"); + } + + /* 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 */ +#if CFG_SUPPORT_CFG80211_AUTH + if ((prConnSettings->ucAuthDataLen != 0) && + !IS_STA_IN_P2P(prStaRec)) { + kalMemCopy(prAuthFrame->aucAuthData, + prConnSettings->aucAuthData, + prConnSettings->ucAuthDataLen); + } else { + /* Fill the Authentication Transaction Sequence Number field. */ + /* NOTE(Kevin): Optimized for ARM */ + prAuthFrame->aucAuthData[0] = (uint8_t) + (u2TransactionSeqNum & 0xff); + prAuthFrame->aucAuthData[1] = (uint8_t) + ((u2TransactionSeqNum >> 8) & 0xff); + /* Fill the Status Code field. */ + /* NOTE(Kevin): Optimized for ARM */ + prAuthFrame->aucAuthData[2] = (uint8_t)(u2StatusCode & 0xff); + prAuthFrame->aucAuthData[3] = (uint8_t) + ((u2StatusCode >> 8) & 0xff); + } + DBGLOG(SAA, INFO, "Compose auth with TransSN = %d,Status = %d\n", + prAuthFrame->aucAuthData[0], prAuthFrame->aucAuthData[2]); +#else + /* 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 */ +#endif +} /* 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 struct ADAPTER *prAdapter, + IN OUT struct MSDU_INFO *prMsduInfo) +{ + struct WLAN_AUTH_FRAME *prAuthFrame; + struct STA_RECORD *prStaRec; + uint16_t 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 = (struct WLAN_AUTH_FRAME *)prMsduInfo->prPacket; +#if CFG_SUPPORT_CFG80211_AUTH + WLAN_GET_FIELD_16(&prAuthFrame->aucAuthData[0], &u2TransactionSeqNum) +#else + WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, &u2TransactionSeqNum) +#endif + /* 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(((unsigned long)(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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t authSendAuthFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN uint16_t u2TransactionSeqNum) +{ + struct MSDU_INFO *prMsduInfo; + struct BSS_INFO *prBssInfo; + uint16_t u2EstimatedFrameLen; + uint16_t u2EstimatedExtraIELen; + uint16_t u2PayloadLen; + uint32_t 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(struct APPEND_VAR_IE_ENTRY); + i++) { + if (txAssocRespIETable[i].u2EstimatedFixedIELen != 0) + u2EstimatedExtraIELen += + txAssocRespIETable[i].u2EstimatedFixedIELen; + else if (txAssocRespIETable[i].pfnCalculateVariableIELen != + NULL) + u2EstimatedExtraIELen += + (uint16_t)txAssocRespIETable[i] + .pfnCalculateVariableIELen( + prAdapter, prStaRec->ucBssIndex, + prStaRec); + } + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SAA, WARN, "No PKT_INFO_T for sending Auth Frame.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Authentication Request frame header and fixed fields + * in MSDU_INfO_T. + */ + ASSERT(prStaRec->ucBssIndex <= prAdapter->ucHwBssIdNum); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex) + + /* Compose Header and some Fixed Fields */ + authComposeAuthFrameHeaderAndFF(prAdapter, prStaRec, (uint8_t *) + ((uint32_t) (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 */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, + saaFsmRunEventTxDone, MSDU_RATE_MODE_AUTO); + + /* 4 <4> Compose IEs in MSDU_INFO_T */ + for (i = 0; i < sizeof(txAuthIETable) / sizeof(struct APPEND_IE_ENTRY); + i++) { + if (txAuthIETable[i].pfnAppendIE) + txAuthIETable[i].pfnAppendIE(prAdapter, prMsduInfo); + + } + + /* TODO(Kevin): + * Also release the unused tail room of the composed MMPDU + */ + + nicTxConfigPktControlFlag(prMsduInfo, MSDU_CONTROL_FLAG_FORCE_TX, TRUE); + + /* 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +authSendAuthFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN uint8_t ucBssIndex, + IN struct SW_RFB *prFalseAuthSwRfb, + IN uint16_t u2TransactionSeqNum, IN uint16_t u2StatusCode) +{ + uint8_t *pucReceiveAddr; + uint8_t *pucTransmitAddr; + struct MSDU_INFO *prMsduInfo; + struct BSS_INFO *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; + uint16_t u2EstimatedFrameLen; + uint16_t u2EstimatedExtraIELen; + uint16_t u2PayloadLen; + uint16_t ucAuthAlgNum; + uint32_t i; +#if CFG_SUPPORT_CFG80211_AUTH + struct CONNECTION_SETTINGS *prConnSettings; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); +#endif + + DBGLOG(SAA, LOUD, "Send Auth Frame %d, Status Code = %d\n", + u2TransactionSeqNum, u2StatusCode); +#if CFG_SUPPORT_CFG80211_AUTH + if ((prConnSettings->ucAuthDataLen != 0) && + !IS_STA_IN_P2P(prStaRec)) { + DBGLOG(SAA, INFO, "prConnSettings->ucAuthDataLen = %d\n", + prConnSettings->ucAuthDataLen); + u2EstimatedFrameLen = (MAC_TX_RESERVED_FIELD + + WLAN_MAC_MGMT_HEADER_LEN + + AUTH_ALGORITHM_NUM_FIELD_LEN + + prConnSettings->ucAuthDataLen); + } else + 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); +#else + /* 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); +#endif + /* + Extra IE Length */ + u2EstimatedExtraIELen = 0; + + for (i = 0; + i < sizeof(txAuthIETable) / sizeof(struct APPEND_VAR_IE_ENTRY); + i++) { + if (txAuthIETable[i].u2EstimatedFixedIELen != 0) + u2EstimatedExtraIELen += + txAuthIETable[i].u2EstimatedFixedIELen; + else + u2EstimatedExtraIELen += + txAuthIETable[i].pfnCalculateVariableIELen( + prAdapter, ucBssIndex, prStaRec); + } + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SAA, WARN, "No PKT_INFO_T for sending Auth Frame.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Authentication Request frame header and + * fixed fields in MSDU_INfO_T. + */ + if (prStaRec) { + ASSERT(prStaRec->ucBssIndex <= prAdapter->ucHwBssIdNum); + prBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + pucTransmitAddr = prBssInfo->aucOwnMacAddr; + + pucReceiveAddr = prStaRec->aucMacAddr; + + ucAuthAlgNum = prStaRec->ucAuthAlgNum; + +#if CFG_SUPPORT_CFG80211_AUTH + if (IS_AP_STA(prStaRec)) /* STA mode */ + pfTxDoneHandler = saaFsmRunEventTxDone; + else if (IS_CLIENT_STA(prStaRec)) + pfTxDoneHandler = aaaFsmRunEventTxDone; + else { + DBGLOG(SAA, WARN, + "Can't send auth with unsupport peer's StaType:%d\n", + prStaRec->eStaType); + return WLAN_STATUS_FAILURE; + } +#else + 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; + } +#endif + } else { /* For Error Status Code */ + struct WLAN_AUTH_FRAME *prFalseAuthFrame; + + ASSERT(prFalseAuthSwRfb); + prFalseAuthFrame = + (struct WLAN_AUTH_FRAME *)prFalseAuthSwRfb->pvHeader; + + ASSERT(u2StatusCode != STATUS_CODE_SUCCESSFUL); + + pucTransmitAddr = prFalseAuthFrame->aucDestAddr; + + pucReceiveAddr = prFalseAuthFrame->aucSrcAddr; + + ucAuthAlgNum = prFalseAuthFrame->u2AuthAlgNum; +#if CFG_SUPPORT_CFG80211_AUTH + u2TransactionSeqNum = (prFalseAuthFrame->aucAuthData[1] << 8) + + (prFalseAuthFrame->aucAuthData[0] + 1); +#else + u2TransactionSeqNum = (prFalseAuthFrame->u2AuthTransSeqNo + 1); +#endif + } + + /* Compose Header and some Fixed Fields */ + authComposeAuthFrameHeaderAndFF(prAdapter, prStaRec, (uint8_t *) + ((unsigned long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD), pucReceiveAddr, + pucTransmitAddr, ucAuthAlgNum, + u2TransactionSeqNum, u2StatusCode); + + /* fill the length of auth frame body */ +#if CFG_SUPPORT_CFG80211_AUTH + if ((prConnSettings->ucAuthDataLen != 0) && + !IS_STA_IN_P2P(prStaRec)) + u2PayloadLen = (AUTH_ALGORITHM_NUM_FIELD_LEN + + prConnSettings->ucAuthDataLen); + else + u2PayloadLen = (AUTH_ALGORITHM_NUM_FIELD_LEN + + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + + STATUS_CODE_FIELD_LEN); +#else + u2PayloadLen = + (AUTH_ALGORITHM_NUM_FIELD_LEN + + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + STATUS_CODE_FIELD_LEN); +#endif + /* 4 <3> Update information of MSDU_INFO_T */ + + TX_SET_MMPDU(prAdapter, + prMsduInfo, + ucBssIndex, + (prStaRec != + NULL) ? (prStaRec->ucIndex) : (STA_REC_INDEX_NOT_FOUND), + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, pfTxDoneHandler, + MSDU_RATE_MODE_AUTO); + + if ((ucAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY) + && (u2TransactionSeqNum == AUTH_TRANSACTION_SEQ_3)) + nicTxConfigPktOption(prMsduInfo, MSDU_OPT_PROTECTED_FRAME, + TRUE); + /* 4 <4> Compose IEs in MSDU_INFO_T */ + for (i = 0; + i < sizeof(txAuthIETable) / sizeof(struct APPEND_VAR_IE_ENTRY); + i++) { + if (txAuthIETable[i].pfnAppendIE) + txAuthIETable[i].pfnAppendIE(prAdapter, prMsduInfo); + } + + /* TODO(Kevin): + * Also release the unused tail room of the composed MMPDU + */ + + nicTxConfigPktControlFlag(prMsduInfo, MSDU_CONTROL_FLAG_FORCE_TX, TRUE); + + /* 4 <6> Inform TXM to send this Authentication frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + DBGLOG(SAA, INFO, + "Send Auth Frame, TranSeq: %d, Status: %d, Seq: %d\n", + u2TransactionSeqNum, u2StatusCode, prMsduInfo->ucTxSeqNum); + + 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t authCheckTxAuthFrame(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN uint16_t u2TransactionSeqNum) +{ + struct WLAN_AUTH_FRAME *prAuthFrame; + struct STA_RECORD *prStaRec; + uint16_t u2TxFrameCtrl; + uint16_t u2TxAuthAlgNum; + uint16_t u2TxTransactionSeqNum; + + ASSERT(prMsduInfo); + + prAuthFrame = (struct WLAN_AUTH_FRAME *)(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 != (uint16_t) (prStaRec->ucAuthAlgNum)) + return WLAN_STATUS_FAILURE; + + /* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, + * &u2TxTransactionSeqNum) + */ +#if CFG_SUPPORT_CFG80211_AUTH + u2TxTransactionSeqNum = (prAuthFrame->aucAuthData[1] << 8) + + prAuthFrame->aucAuthData[0]; +#else + u2TxTransactionSeqNum = prAuthFrame->u2AuthTransSeqNo; +#endif + /* 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t authCheckRxAuthFrameTransSeq(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct WLAN_AUTH_FRAME *prAuthFrame; + uint16_t u2RxTransactionSeqNum; + uint16_t u2MinPayloadLen; +#if CFG_SUPPORT_SAE +#if CFG_IGNORE_INVALID_AUTH_TSN + struct STA_RECORD *prStaRec; +#endif + struct BSS_INFO *prBssInfo = NULL; +#endif + + + ASSERT(prSwRfb); + + /* 4 <1> locate the Authentication Frame. */ + prAuthFrame = (struct WLAN_AUTH_FRAME *)prSwRfb->pvHeader; + + /* 4 <2> Parse the Header of Authentication Frame. */ + u2MinPayloadLen = (AUTH_ALGORITHM_NUM_FIELD_LEN + + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + + STATUS_CODE_FIELD_LEN); + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < u2MinPayloadLen) { + DBGLOG(SAA, WARN, + "Rx Auth payload: len[%u] < min expected len[%u]\n", + (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen), + u2MinPayloadLen); + DBGLOG(SAA, WARN, "=== Dump Rx Auth ===\n"); + DBGLOG_MEM8(SAA, WARN, prAuthFrame, prSwRfb->u2PacketLen); + return WLAN_STATUS_SUCCESS; + } + /* 4 <3> Parse the Fixed Fields of Authentication Frame Body. */ + /* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, + * &u2RxTransactionSeqNum); + */ +#if CFG_SUPPORT_CFG80211_AUTH + u2RxTransactionSeqNum = (prAuthFrame->aucAuthData[1] << 8) + + prAuthFrame->aucAuthData[0]; +#else + u2RxTransactionSeqNum = prAuthFrame->u2AuthTransSeqNo; + /* NOTE(Kevin): Optimized for ARM */ +#endif + + if ((u2RxTransactionSeqNum < 0) || (u2RxTransactionSeqNum > 4)) { + DBGLOG(SAA, WARN, + "RX auth with unexpected TransactionSeqNum:%d\n", + u2RxTransactionSeqNum); + return WLAN_STATUS_SUCCESS; + } +#if CFG_SUPPORT_SAE + if (prAuthFrame->u2AuthAlgNum == AUTH_ALGORITHM_NUM_SAE) { + if ((u2RxTransactionSeqNum == + AUTH_TRANSACTION_SEQ_1) || + (u2RxTransactionSeqNum == + AUTH_TRANSACTION_SEQ_2)) { + prStaRec = prSwRfb->prStaRec; + if (prStaRec) + prBssInfo = + GET_BSS_INFO_BY_INDEX( + prAdapter, + prStaRec->ucBssIndex); + else + prBssInfo = + p2pFuncBSSIDFindBssInfo( + prAdapter, + prAuthFrame->aucBSSID); + + if (prBssInfo == NULL) + return WLAN_STATUS_SUCCESS; + + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) + saaFsmRunEventRxAuth(prAdapter, prSwRfb); +#if CFG_SUPPORT_AAA + else if (prBssInfo->eCurrentOPMode == + OP_MODE_ACCESS_POINT) + aaaFsmRunEventRxAuth(prAdapter, prSwRfb); +#endif + else + DBGLOG(SAA, WARN, + "Don't support SAE for non-AIS/P2P network\n"); + } else { + DBGLOG(SAA, WARN, + "RX SAE auth with unexpected TransSeqNum:%d\n", + u2RxTransactionSeqNum); + } + + } else { +#endif + 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\n", + u2RxTransactionSeqNum); + } +#if CFG_SUPPORT_SAE + } +#endif + 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t +authCheckRxAuthFrameStatus(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint16_t u2TransactionSeqNum, + OUT uint16_t *pu2StatusCode) +{ + struct STA_RECORD *prStaRec; + struct WLAN_AUTH_FRAME *prAuthFrame; + uint16_t u2RxAuthAlgNum; + uint16_t 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 = (struct WLAN_AUTH_FRAME *)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 != (uint16_t) prStaRec->ucAuthAlgNum) { + DBGLOG(SAA, WARN, + "Discard Auth frame with auth type = %d, current = %d\n", + u2RxAuthAlgNum, prStaRec->ucAuthAlgNum); + *pu2StatusCode = STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED; + return WLAN_STATUS_SUCCESS; + } + /* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, + * &u2RxTransactionSeqNum); + */ +#if CFG_SUPPORT_CFG80211_AUTH + u2RxTransactionSeqNum = (prAuthFrame->aucAuthData[1] << 8) + + prAuthFrame->aucAuthData[0]; + /* Still report to upper layer to let it do the error handling */ + if (u2RxTransactionSeqNum < u2TransactionSeqNum) { + DBGLOG(SAA, WARN, + "Rx Auth frame with unexpected Transaction Seq No = %d\n", + u2RxTransactionSeqNum); + *pu2StatusCode = STATUS_CODE_AUTH_OUT_OF_SEQ; + return WLAN_STATUS_FAILURE; + } +#else + u2RxTransactionSeqNum = prAuthFrame->u2AuthTransSeqNo; + /* NOTE(Kevin): Optimized for ARM */ + if (u2RxTransactionSeqNum != u2TransactionSeqNum) { + DBGLOG(SAA, WARN, + "Discard Auth frame with Transaction Seq No = %d\n", + u2RxTransactionSeqNum); + *pu2StatusCode = STATUS_CODE_AUTH_OUT_OF_SEQ; + return WLAN_STATUS_FAILURE; + } +#endif + /* 4 <3> Get the Status code */ + /* WLAN_GET_FIELD_16(&prAuthFrame->u2StatusCode, &u2RxStatusCode); */ + /* *pu2StatusCode = u2RxStatusCode; */ +#if CFG_SUPPORT_CFG80211_AUTH + *pu2StatusCode = (prAuthFrame->aucAuthData[3] << 8) + + prAuthFrame->aucAuthData[2]; +#else + *pu2StatusCode = prAuthFrame->u2StatusCode; + /* NOTE(Kevin): Optimized for ARM */ +#endif + DBGLOG(SAA, INFO, + "Rx Auth frame with auth type = %d, SN = %d, Status Code = %d\n", + u2RxAuthAlgNum, u2RxTransactionSeqNum, *pu2StatusCode); + + 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(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb, struct IE_HDR *prIEHdr) +{ + struct WLAN_AUTH_FRAME *prAuthFrame; + struct STA_RECORD *prStaRec; + uint16_t 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 = (struct WLAN_AUTH_FRAME *)prSwRfb->pvHeader; + + /* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, + * &u2TransactionSeqNum) + */ +#if CFG_SUPPORT_CFG80211_AUTH + u2TransactionSeqNum = (prAuthFrame->aucAuthData[1] << 8) + + prAuthFrame->aucAuthData[0]; +#else + u2TransactionSeqNum = prAuthFrame->u2AuthTransSeqNo; + /* NOTE(Kevin): Optimized for ARM */ +#endif + /* 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 = + (struct IE_CHALLENGE_TEXT *)NULL; + } + prStaRec->prChallengeText = + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, IE_SIZE(prIEHdr)); + if (prStaRec->prChallengeText == NULL) + return; + + /* Save the Challenge Text from Auth Seq 2 Frame, + * before sending Auth Seq 3 Frame + */ + COPY_IE(prStaRec->prChallengeText, prIEHdr); + } + + return; + +} /* end of authAddIEChallengeText() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will parse and process the incoming Authentication + * frame. + * + * @param[in] prSwRfb Pointer to SW RFB data structure. + * + * @retval WLAN_STATUS_SUCCESS This is the frame we should handle. + */ +/*----------------------------------------------------------------------------*/ +uint32_t authProcessRxAuth2_Auth4Frame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct WLAN_AUTH_FRAME *prAuthFrame; + uint8_t *pucIEsBuffer; + uint16_t u2IEsLen; + uint16_t u2Offset; + uint8_t ucIEID; + uint32_t i; + uint16_t u2TransactionSeqNum; + + ASSERT(prSwRfb); + + prAuthFrame = (struct WLAN_AUTH_FRAME *)prSwRfb->pvHeader; + +#if CFG_SUPPORT_CFG80211_AUTH + pucIEsBuffer = (uint8_t *)&prAuthFrame->aucAuthData[0] + 4; +#else + pucIEsBuffer = &prAuthFrame->aucInfoElem[0]; +#endif + 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(struct HANDLE_IE_ENTRY)); + i++) { + if ((ucIEID == rxAuthIETable[i].ucElemID) + && (rxAuthIETable[i].pfnHandleIE != NULL)) + rxAuthIETable[i].pfnHandleIE(prAdapter, + prSwRfb, + (struct IE_HDR *)pucIEsBuffer); + } + } +#if CFG_SUPPORT_CFG80211_AUTH + u2TransactionSeqNum = (prAuthFrame->aucAuthData[1] << 8) + + prAuthFrame->aucAuthData[0]; +#else + u2TransactionSeqNum = prAuthFrame->u2AuthTransSeqNo; + /* NOTE(Kevin): Optimized for ARM */ +#endif + if (prAuthFrame->u2AuthAlgNum == + AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION) { + if (u2TransactionSeqNum == AUTH_TRANSACTION_SEQ_4) { + /* todo: check MIC, if mic error, return + * WLAN_STATUS_FAILURE + */ + } else if (u2TransactionSeqNum == + AUTH_TRANSACTION_SEQ_2) { + prAdapter->prGlueInfo->rFtEventParam.ies = + &prAuthFrame->aucInfoElem[0]; + prAdapter->prGlueInfo->rFtEventParam.ies_len = u2IEsLen; + } + } + + return WLAN_STATUS_SUCCESS; + +} /* end of authProcessRxAuth2_Auth4Frame() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will compose the Deauthentication frame + * + * @param[in] pucBuffer Pointer to the frame buffer. + * @param[in] aucPeerMACAddress Given Peer MAC Address. + * @param[in] aucMACAddress Given Our MAC Address. + * @param[in] u2StatusCode Status Code + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ void +authComposeDeauthFrameHeaderAndFF(IN uint8_t *pucBuffer, + IN uint8_t aucPeerMACAddress[], + IN uint8_t aucMACAddress[], + IN uint8_t aucBssid[], + IN uint16_t u2ReasonCode) +{ + struct WLAN_DEAUTH_FRAME *prDeauthFrame; + uint16_t u2FrameCtrl; + + ASSERT(pucBuffer); + ASSERT(aucPeerMACAddress); + ASSERT(aucMACAddress); + ASSERT(aucBssid); + + prDeauthFrame = (struct WLAN_DEAUTH_FRAME *)pucBuffer; + + /* 4 <1> Compose the frame header of the Deauthentication frame. */ + /* Fill the Frame Control field. */ + u2FrameCtrl = MAC_FRAME_DEAUTH; + + /* WLAN_SET_FIELD_16(&prDeauthFrame->u2FrameCtrl, u2FrameCtrl); */ + prDeauthFrame->u2FrameCtrl = u2FrameCtrl; + /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the DA field with Target BSSID. */ + COPY_MAC_ADDR(prDeauthFrame->aucDestAddr, aucPeerMACAddress); + + /* Fill the SA field with our MAC Address. */ + COPY_MAC_ADDR(prDeauthFrame->aucSrcAddr, aucMACAddress); + + /* Fill the BSSID field with Target BSSID. */ + COPY_MAC_ADDR(prDeauthFrame->aucBSSID, aucBssid); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, + * so we need to clear it). + */ + prDeauthFrame->u2SeqCtrl = 0; + + /* 4 <2> Compose the frame body's fixed field part of + * the Authentication frame. + */ + /* Fill the Status Code field. */ + /* WLAN_SET_FIELD_16(&prDeauthFrame->u2ReasonCode, u2ReasonCode); */ + prDeauthFrame->u2ReasonCode = u2ReasonCode; + /* NOTE(Kevin): Optimized for ARM */ +} /* end of authComposeDeauthFrameHeaderAndFF() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will send the Deauthenticiation frame + * + * @param[in] prStaRec Pointer to the STA_RECORD_T + * @param[in] prClassErrSwRfb Pointer to the SW_RFB_T which is Class Error. + * @param[in] u2ReasonCode A reason code to indicate why to leave BSS. + * @param[in] pfTxDoneHandler TX Done call back function + * + * @retval WLAN_STATUS_RESOURCES No available resource for frame composing. + * @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module + * @retval WLAN_STATUS_FAILURE Didn't send Deauth frame for various reasons. + */ +/*----------------------------------------------------------------------------*/ +uint32_t +authSendDeauthFrame(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct STA_RECORD *prStaRec, + IN struct SW_RFB *prClassErrSwRfb, IN uint16_t u2ReasonCode, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + uint8_t *pucReceiveAddr; + uint8_t *pucTransmitAddr; + uint8_t *pucBssid = NULL; + struct MSDU_INFO *prMsduInfo; + uint16_t u2EstimatedFrameLen; + + struct DEAUTH_INFO *prDeauthInfo; + OS_SYSTIME rCurrentTime; + int32_t i4NewEntryIndex, i; + uint8_t ucStaRecIdx = STA_REC_INDEX_NOT_FOUND; + uint8_t ucBssIndex = prAdapter->ucHwBssIdNum; + uint8_t aucBMC[] = BC_MAC_ADDR; +#if CFG_SUPPORT_CFG80211_AUTH + struct WLAN_DEAUTH_FRAME *prDeauthFrame; +#endif + + DBGLOG(RSN, INFO, "authSendDeauthFrame\n"); + + /* NOTE(Kevin): The best way to reply the Deauth is according to + * the incoming data frame + */ + /* 4 <1.1> Find the Receiver Address */ + if (prClassErrSwRfb) { + u_int8_t fgIsAbleToSendDeauth = FALSE; + uint16_t u2RxFrameCtrl; + struct WLAN_MAC_HEADER_A4 *prWlanMacHeader = NULL; + + prWlanMacHeader = + (struct WLAN_MAC_HEADER_A4 *)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; + + DBGLOG(SAA, INFO, + "u2FrameCtrl=0x%x, DestAddr=" MACSTR + " srcAddr=" MACSTR " BSSID=" MACSTR + ", u2SeqCtrl=0x%x\n", + prWlanMacHeader->u2FrameCtrl, + MAC2STR(prWlanMacHeader->aucAddr1), + MAC2STR(prWlanMacHeader->aucAddr2), + MAC2STR(prWlanMacHeader->aucAddr3), + prWlanMacHeader->u2SeqCtrl); + /* Check if corresponding BSS is able to send Deauth */ + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, i); + + if (IS_NET_ACTIVE(prAdapter, i) && + (EQUAL_MAC_ADDR + (prWlanMacHeader->aucAddr1, + prBssInfo->aucOwnMacAddr))) { + + fgIsAbleToSendDeauth = TRUE; + ucBssIndex = (uint8_t) i; + break; + } + } + + if (!fgIsAbleToSendDeauth) + return WLAN_STATUS_FAILURE; + + pucReceiveAddr = prWlanMacHeader->aucAddr2; + } else if (prStaRec) { + prBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + ucStaRecIdx = prStaRec->ucIndex; + ucBssIndex = prBssInfo->ucBssIndex; + + pucReceiveAddr = prStaRec->aucMacAddr; + } else if (prBssInfo) { + ucBssIndex = prBssInfo->ucBssIndex; + ucStaRecIdx = STA_REC_INDEX_BMCAST; + + pucReceiveAddr = aucBMC; + } else { + DBGLOG(SAA, WARN, "Not to send Deauth, invalid data!\n"); + return WLAN_STATUS_INVALID_DATA; + } + + /* 4 <1.2> Find Transmitter Address and BSSID. */ + pucTransmitAddr = prBssInfo->aucOwnMacAddr; + pucBssid = prBssInfo->aucBSSID; + + if (ucStaRecIdx != STA_REC_INDEX_BMCAST) { + /* 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 <5> Allocate a PKT_INFO_T for Deauthentication Frame */ + /* Init with MGMT Header Length + Length of Fixed Fields + IE Length */ + u2EstimatedFrameLen = + (MAC_TX_RESERVED_FIELD + WLAN_MAC_MGMT_HEADER_LEN + + REASON_CODE_FIELD_LEN); + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SAA, WARN, + "No PKT_INFO_T for sending Deauth Request.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <6> compose Deauthentication frame header and some fixed fields */ + authComposeDeauthFrameHeaderAndFF((uint8_t *) + ((unsigned long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD), + pucReceiveAddr, pucTransmitAddr, + pucBssid, u2ReasonCode); + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + /* PMF certification 4.3.3.1, 4.3.3.2 send unprotected + * deauth reason 6/7 + * if (AP mode & not for PMF reply case) OR (STA PMF) + */ + if (((GET_BSS_INFO_BY_INDEX + (prAdapter, + prStaRec->ucBssIndex)->eCurrentOPMode == + OP_MODE_ACCESS_POINT) + && (prStaRec->rPmfCfg.fgRxDeauthResp != TRUE)) + || + (GET_BSS_INFO_BY_INDEX + (prAdapter, + prStaRec->ucBssIndex)->eNetworkType == + (uint8_t) NETWORK_TYPE_AIS)) { + + struct WLAN_DEAUTH_FRAME *prDeauthFrame; + + prDeauthFrame = (struct WLAN_DEAUTH_FRAME *)(uint8_t *) + ((unsigned long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + + prDeauthFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + DBGLOG(SAA, INFO, + "Reason=%d, DestAddr=" MACSTR + " srcAddr=" MACSTR " BSSID=" MACSTR "\n", + prDeauthFrame->u2ReasonCode, + MAC2STR(prDeauthFrame->aucDestAddr), + MAC2STR(prDeauthFrame->aucSrcAddr), + MAC2STR(prDeauthFrame->aucBSSID)); + } + } +#endif + nicTxSetPktLifeTime(prMsduInfo, 100); + + nicTxSetPktRetryLimit(prMsduInfo, TX_DESC_TX_COUNT_NO_LIMIT); + + /* 4 <7> Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + ucBssIndex, + ucStaRecIdx, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + REASON_CODE_FIELD_LEN, + pfTxDoneHandler, MSDU_RATE_MODE_AUTO); + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + /* caution: access prStaRec only if true */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + /* 4.3.3.1 send unprotected deauth reason 6/7 */ + if (prStaRec->rPmfCfg.fgRxDeauthResp != TRUE) { + DBGLOG(RSN, INFO, + "Deauth Set MSDU_OPT_PROTECTED_FRAME\n"); + nicTxConfigPktOption(prMsduInfo, + MSDU_OPT_PROTECTED_FRAME, TRUE); + } + + prStaRec->rPmfCfg.fgRxDeauthResp = FALSE; + } +#endif +#if CFG_SUPPORT_CFG80211_AUTH + prDeauthFrame = (struct WLAN_DEAUTH_FRAME *) (uint8_t *) + ((unsigned long) (prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + DBGLOG(SAA, INFO, "notification of TX deauthentication, %d\n", + prMsduInfo->u2FrameLength); + + cfg80211_tx_mlme_mgmt(prAdapter->prGlueInfo->prDevHandler, + (uint8_t *)prDeauthFrame, + (size_t)prMsduInfo->u2FrameLength); + DBGLOG(SAA, INFO, + "notification of TX deauthentication, Done\n"); +#endif + + DBGLOG(SAA, INFO, "ucTxSeqNum=%d ucStaRecIndex=%d u2ReasonCode=%d\n", + prMsduInfo->ucTxSeqNum, prMsduInfo->ucStaRecIndex, u2ReasonCode); + + /* 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t authProcessRxDeauthFrame(IN struct SW_RFB *prSwRfb, + IN uint8_t aucBSSID[], + OUT uint16_t *pu2ReasonCode) +{ + struct WLAN_DEAUTH_FRAME *prDeauthFrame; + uint16_t u2RxReasonCode; + + if (!prSwRfb || !aucBSSID || !pu2ReasonCode) { + DBGLOG(SAA, WARN, "Invalid parameters, ignore pkt!\n"); + return WLAN_STATUS_FAILURE; + } + + /* 4 <1> locate the Deauthentication Frame. */ + prDeauthFrame = (struct WLAN_DEAUTH_FRAME *)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) { + DBGLOG(SAA, WARN, "Invalid Deauth packet length"); + 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t +authProcessRxAuth1Frame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint8_t aucExpectedBSSID[], + IN uint16_t u2ExpectedAuthAlgNum, + IN uint16_t u2ExpectedTransSeqNum, + OUT uint16_t *pu2ReturnStatusCode) +{ + struct WLAN_AUTH_FRAME *prAuthFrame; + uint16_t u2ReturnStatusCode = STATUS_CODE_SUCCESSFUL; + + ASSERT(prSwRfb); + ASSERT(aucExpectedBSSID); + ASSERT(pu2ReturnStatusCode); + + /* 4 <1> locate the Authentication Frame. */ + prAuthFrame = (struct WLAN_AUTH_FRAME *)prSwRfb->pvHeader; + + /* 4 <2> Check the BSSID */ + if (UNEQUAL_MAC_ADDR(prAuthFrame->aucBSSID, aucExpectedBSSID)) + return WLAN_STATUS_FAILURE; /* Just Ignore this MMPDU */ + + /* 4 <3> Check the SA, which should not be MC/BC */ + if (prAuthFrame->aucSrcAddr[0] & BIT(0)) { + DBGLOG(P2P, WARN, + "Invalid STA MAC with MC/BC bit set: " MACSTR "\n", + MAC2STR(prAuthFrame->aucSrcAddr)); + return WLAN_STATUS_FAILURE; + } + + /* 4 <4> Parse the Fixed Fields of Authentication Frame Body. */ + if (prAuthFrame->u2AuthAlgNum != u2ExpectedAuthAlgNum) + u2ReturnStatusCode = STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED; + +#if CFG_SUPPORT_CFG80211_AUTH + if (prAuthFrame->aucAuthData[0] != u2ExpectedTransSeqNum) +#else + if (prAuthFrame->u2AuthTransSeqNo != u2ExpectedTransSeqNum) +#endif + u2ReturnStatusCode = STATUS_CODE_AUTH_OUT_OF_SEQ; + + *pu2ReturnStatusCode = u2ReturnStatusCode; + + return WLAN_STATUS_SUCCESS; + +} /* end of authProcessRxAuth1Frame() */ + +/* ToDo: authAddRicIE, authHandleFtIEs, authAddTimeoutIE */ + +void authAddMDIE(IN struct ADAPTER *prAdapter, + IN OUT struct MSDU_INFO *prMsduInfo) +{ + struct FT_IES *prFtIEs = &prAdapter->prGlueInfo->rFtIeForTx; + uint8_t *pucBuffer = + (uint8_t *)prMsduInfo->prPacket + prMsduInfo->u2FrameLength; + uint8_t ucBssIdx = prMsduInfo->ucBssIndex; + + if (!IS_BSS_INDEX_VALID(ucBssIdx) || + !IS_BSS_AIS(GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx)) || + !prFtIEs->prMDIE) + return; + prMsduInfo->u2FrameLength += + 5; /* IE size for MD IE is fixed, it is 5 */ + kalMemCopy(pucBuffer, prFtIEs->prMDIE, 5); +} + +uint32_t authCalculateRSNIELen(struct ADAPTER *prAdapter, uint8_t ucBssIdx, + struct STA_RECORD *prStaRec) +{ + enum ENUM_PARAM_AUTH_MODE eAuthMode = + prAdapter->rWifiVar.rConnSettings.eAuthMode; + struct FT_IES *prFtIEs = &prAdapter->prGlueInfo->rFtIeForTx; + + if (!IS_BSS_INDEX_VALID(ucBssIdx) || + !IS_BSS_AIS(GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx)) || + !prFtIEs->prRsnIE || (eAuthMode != AUTH_MODE_WPA2_FT && + eAuthMode != AUTH_MODE_WPA2_FT_PSK)) + return 0; + return IE_SIZE(prFtIEs->prRsnIE); +} + +void authAddRSNIE(IN struct ADAPTER *prAdapter, + IN OUT struct MSDU_INFO *prMsduInfo) +{ + enum ENUM_PARAM_AUTH_MODE eAuthMode = + prAdapter->rWifiVar.rConnSettings.eAuthMode; + struct FT_IES *prFtIEs = &prAdapter->prGlueInfo->rFtIeForTx; + uint8_t *pucBuffer = + (uint8_t *)prMsduInfo->prPacket + prMsduInfo->u2FrameLength; + uint32_t ucRSNIeSize = 0; + uint8_t ucBssIdx = prMsduInfo->ucBssIndex; + + if (!IS_BSS_INDEX_VALID(ucBssIdx) || + !IS_BSS_AIS(GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx)) || + !prFtIEs->prRsnIE || (eAuthMode != AUTH_MODE_WPA2_FT && + eAuthMode != AUTH_MODE_WPA2_FT_PSK)) + return; + ucRSNIeSize = IE_SIZE(prFtIEs->prRsnIE); + prMsduInfo->u2FrameLength += ucRSNIeSize; + kalMemCopy(pucBuffer, prFtIEs->prRsnIE, ucRSNIeSize); +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/bss.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/bss.c new file mode 100644 index 0000000000000..c8d604647b0ca --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/bss.c @@ -0,0 +1,2436 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/bss.c#7 + */ + +/*! \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. + */ + +/****************************************************************************** + * C O M P I L E 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 + ****************************************************************************** + */ + +const uint8_t *apucNetworkType[NETWORK_TYPE_NUM] = { + (uint8_t *) "AIS", + (uint8_t *) "P2P", + (uint8_t *) "BOW", + (uint8_t *) "MBSS" +}; + +const uint8_t *apucNetworkOpMode[] = { + (uint8_t *) "INFRASTRUCTURE", + (uint8_t *) "IBSS", + (uint8_t *) "ACCESS_POINT", + (uint8_t *) "P2P_DEVICE", + (uint8_t *) "BOW" +}; + +#if (CFG_SUPPORT_ADHOC) || (CFG_SUPPORT_AAA) +struct APPEND_VAR_IE_ENTRY txBcnIETable[] = { + {(ELEM_HDR_LEN + (RATE_NUM_SW - 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 */ + , {0, p2pFuncCalculateP2p_IELenForBeacon, + p2pFuncGenerateP2p_IEForBeacon} /* 221 */ + , {0, p2pFuncCalculateWSC_IELenForBeacon, + p2pFuncGenerateWSC_IEForBeacon} /* 221 */ + , {0, p2pFuncCalculateP2P_IE_NoA, + p2pFuncGenerateP2P_IE_NoA} /* 221 */ +#endif /* CFG_ENABLE_WIFI_DIRECT */ +#if CFG_SUPPORT_802_11AC + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP), NULL, + rlmRspGenerateVhtCapIE} /*191 */ + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP), NULL, + rlmRspGenerateVhtOpIE} /*192 */ + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP_MODE_NOTIFICATION), NULL, + rlmRspGenerateVhtOpNotificationIE} /*199 */ +#endif +#if CFG_SUPPORT_MTK_SYNERGY + , {(ELEM_HDR_LEN + ELEM_MIN_LEN_MTK_OUI), NULL, + rlmGenerateMTKOuiIE} /* 221 */ +#endif +#if (CFG_SUPPORT_DFS_MASTER == 1) + , {(ELEM_HDR_LEN + ELEM_MIN_LEN_CSA), NULL, + rlmGenerateCsaIE} /* 37 */ +#endif +#if CFG_SUPPORT_WAC + , {0, rlmCalculateWAC_IELen, + rlmGenerateWAC_IE} /* 221 */ +#endif + +}; + +struct APPEND_VAR_IE_ENTRY txProbRspIETable[] = { + {(ELEM_HDR_LEN + (RATE_NUM_SW - 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 */ +#if CFG_SUPPORT_802_11AC + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP), NULL, + rlmRspGenerateVhtCapIE} /*191 */ + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP), NULL, + rlmRspGenerateVhtOpIE} /*192 */ + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP_MODE_NOTIFICATION), NULL, + rlmRspGenerateVhtOpNotificationIE} /*199 */ +#endif +#if CFG_SUPPORT_MTK_SYNERGY + , {(ELEM_HDR_LEN + ELEM_MIN_LEN_MTK_OUI), NULL, + rlmGenerateMTKOuiIE} /* 221 */ +#endif +#if CFG_SUPPORT_WAC + , {0, rlmCalculateWAC_IELen, + rlmGenerateWAC_IE} /* 221 */ +#endif + +}; + +#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 decide PHY type set of STA_RECORD_T by given + * BSS_DESC_T for Infrastructure or AdHoc Mode. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] prBssDesc Received Beacon/ProbeResp from this STA + * @param[out] prStaRec StaRec to be decided PHY type set + * + * @retval VOID + */ +/*---------------------------------------------------------------------------*/ +void bssDetermineStaRecPhyTypeSet(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc, + OUT struct STA_RECORD *prStaRec) +{ + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; + uint8_t ucHtOption = FEATURE_ENABLED; + uint8_t ucVhtOption = FEATURE_ENABLED; + + prStaRec->ucPhyTypeSet = prBssDesc->ucPhyTypeSet; +#if CFG_SUPPORT_BFEE + prStaRec->ucVhtCapNumSoundingDimensions = + prBssDesc->ucVhtCapNumSoundingDimensions; +#endif + + /* Decide AIS PHY type set */ + if (prStaRec->eStaType == STA_TYPE_LEGACY_AP) { + 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) +#if CFG_SUPPORT_WAPI + || (prAdapter->prGlueInfo->u2WapiAssocInfoIESz) +#endif +)) { + DBGLOG(BSS, INFO, + "Ignore the HT Bit for TKIP as pairwise cipher configed!\n"); + prStaRec->ucPhyTypeSet &= + ~(PHY_TYPE_BIT_HT | PHY_TYPE_BIT_VHT); + } + + ucHtOption = prWifiVar->ucStaHt; + ucVhtOption = prWifiVar->ucStaVht; + } + /* Decide P2P GC PHY type set */ + else if (prStaRec->eStaType == STA_TYPE_P2P_GO) { + ucHtOption = prWifiVar->ucP2pGcHt; + ucVhtOption = prWifiVar->ucP2pGcVht; + } + + /* Set HT/VHT capability from Feature Option */ + if (IS_FEATURE_DISABLED(ucHtOption)) + prStaRec->ucPhyTypeSet &= ~PHY_TYPE_BIT_HT; + else if (IS_FEATURE_FORCE_ENABLED(ucHtOption)) + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HT; + + if (IS_FEATURE_DISABLED(ucVhtOption)) + prStaRec->ucPhyTypeSet &= ~PHY_TYPE_BIT_VHT; + else if (IS_FEATURE_FORCE_ENABLED(ucVhtOption)) + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_VHT; + + prStaRec->ucDesiredPhyTypeSet = + prStaRec->ucPhyTypeSet & prAdapter->rWifiVar.ucAvailablePhyTypeSet; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will decide PHY type set of BSS_INFO for + * AP Mode. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] fgIsApMode Legacy AP mode or P2P GO + * @param[out] prBssInfo BssInfo to be decided PHY type set + * + * @retval VOID + */ +/*----------------------------------------------------------------------------*/ +void bssDetermineApBssInfoPhyTypeSet(IN struct ADAPTER *prAdapter, + IN u_int8_t fgIsPureAp, + OUT struct BSS_INFO *prBssInfo) +{ + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; + uint8_t ucHtOption = FEATURE_ENABLED; + uint8_t ucVhtOption = FEATURE_ENABLED; + + /* Decide AP mode PHY type set */ + if (fgIsPureAp) { + ucHtOption = prWifiVar->ucApHt; + ucVhtOption = prWifiVar->ucApVht; + } + /* Decide P2P GO PHY type set */ + else { + ucHtOption = prWifiVar->ucP2pGoHt; + ucVhtOption = prWifiVar->ucP2pGoVht; + } + + /* Set HT/VHT capability from Feature Option */ + if (IS_FEATURE_DISABLED(ucHtOption)) + prBssInfo->ucPhyTypeSet &= ~PHY_TYPE_BIT_HT; + else if (IS_FEATURE_ENABLED(ucHtOption)) + prBssInfo->ucPhyTypeSet |= PHY_TYPE_BIT_HT; + + if (IS_FEATURE_DISABLED(ucVhtOption)) { + prBssInfo->ucPhyTypeSet &= ~PHY_TYPE_BIT_VHT; + } else if (IS_FEATURE_FORCE_ENABLED(ucVhtOption) || + (IS_FEATURE_ENABLED(ucVhtOption) + && (prBssInfo->eBand == BAND_5G))) { + + /* Enable HT capability if VHT is enabled */ + prBssInfo->ucPhyTypeSet |= PHY_TYPE_BIT_VHT; + } + + prBssInfo->ucPhyTypeSet &= prAdapter->rWifiVar.ucAvailablePhyTypeSet; + +} + +/*---------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*---------------------------------------------------------------------------*/ +struct STA_RECORD *bssCreateStaRecFromBssDesc(IN struct ADAPTER *prAdapter, + IN enum ENUM_STA_TYPE eStaType, + IN uint8_t ucBssIndex, + IN struct BSS_DESC *prBssDesc) +{ + struct STA_RECORD *prStaRec; + uint8_t ucNonHTPhyTypeSet; + struct CONNECTION_SETTINGS *prConnSettings; + + ASSERT(prBssDesc); + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* 4 <1> Get a valid STA_RECORD_T */ + prStaRec = + cnmGetStaRecByAddress(prAdapter, ucBssIndex, prBssDesc->aucSrcAddr); + if (!prStaRec) { + prStaRec = + cnmStaRecAlloc(prAdapter, eStaType, ucBssIndex, + prBssDesc->aucSrcAddr); + + if (!prStaRec) { + DBGLOG(BSS, WARN, + "STA_REC entry is full, cannot acquire new entry for [" + MACSTR "]!!\n", MAC2STR(prBssDesc->aucSrcAddr)); + ASSERT(FALSE); + return NULL; + } + + prStaRec->ucStaState = STA_STATE_1; + prStaRec->ucJoinFailureCount = 0; + /* TODO(Kevin): If this is an old entry, + * we may also reset the ucJoinFailureCount to 0. + */ + } + /* 4 <2> Update information from BSS_DESC_T to current P_STA_RECORD_T */ + prStaRec->u2CapInfo = prBssDesc->u2CapInfo; + + prStaRec->u2OperationalRateSet = prBssDesc->u2OperationalRateSet; + prStaRec->u2BSSBasicRateSet = prBssDesc->u2BSSBasicRateSet; + +#if 1 + bssDetermineStaRecPhyTypeSet(prAdapter, prBssDesc, prStaRec); +#else + prStaRec->ucPhyTypeSet = prBssDesc->ucPhyTypeSet; + + if (IS_STA_IN_AIS(prStaRec)) { + if (! + ((prAdapter->rWifiVar.rConnSettings.eEncStatus == + ENUM_ENCRYPTION3_ENABLED) + || (prAdapter->rWifiVar.rConnSettings.eEncStatus == + ENUM_ENCRYPTION3_KEY_ABSENT) + || (prAdapter->rWifiVar.rConnSettings.eEncStatus == + ENUM_ENCRYPTION_DISABLED) + || (prAdapter->prGlueInfo->u2WSCAssocInfoIELen) +#if CFG_SUPPORT_WAPI + || (prAdapter->prGlueInfo->u2WapiAssocInfoIESz) +#endif +)) { + 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; +#endif + + 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 */ + prStaRec->u2DesiredNonHTRateSet = + (prStaRec-> + u2OperationalRateSet & prConnSettings->u2DesiredNonHTRateSet); + + /* 4 <3> 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 struct BSS_DESC + */ + if (prBssDesc->ucDTIMPeriod) + prStaRec->ucDTIMPeriod = prBssDesc->ucDTIMPeriod; + else + prStaRec->ucDTIMPeriod = 0; + /* Means that TIM was not parsed. */ + + } + /* 4 <4> Update default value */ + prStaRec->fgDiagnoseConnection = FALSE; + + /* 4 <5> Update default value for other Modules */ + /* Determine WMM related parameters for STA_REC */ + mqmProcessScanResult(prAdapter, prBssDesc, prStaRec); + + /* 4 <6> Update Tx Rate */ + /* Update default Tx rate */ + nicTxUpdateStaRecDefaultRate(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 struct ADAPTER *prAdapter, IN uint8_t *pucBuffer, + IN struct STA_RECORD *prStaRec) +{ + struct WLAN_MAC_HEADER *prNullFrame; + struct BSS_INFO *prBssInfo; + uint16_t u2FrameCtrl; + uint8_t ucBssIndex; + + ASSERT(prStaRec); + ucBssIndex = prStaRec->ucBssIndex; + + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + ASSERT(pucBuffer); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + ASSERT(prBssInfo); + + prNullFrame = (struct WLAN_MAC_HEADER *)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 struct ADAPTER *prAdapter, + IN uint8_t *pucBuffer, IN struct STA_RECORD *prStaRec, + IN uint8_t ucUP, IN u_int8_t fgSetEOSP) +{ + struct WLAN_MAC_HEADER_QOS *prQoSNullFrame; + struct BSS_INFO *prBssInfo; + uint16_t u2FrameCtrl; + uint16_t u2QosControl; + uint8_t ucBssIndex; + + ASSERT(prStaRec); + ucBssIndex = prStaRec->ucBssIndex; + + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + ASSERT(pucBuffer); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + ASSERT(prBssInfo); + + prQoSNullFrame = (struct WLAN_MAC_HEADER_QOS *)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 = (uint16_t) (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. + */ +/*---------------------------------------------------------------------------*/ +uint32_t +bssSendNullFrame(IN struct ADAPTER *prAdapter, IN struct STA_RECORD *prStaRec, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + struct MSDU_INFO *prMsduInfo; + uint16_t u2EstimatedFrameLen; + + /* 4 <1> Allocate a PKT_INFO_T for Null Frame */ + /* Init with MGMT Header Length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + WLAN_MAC_HEADER_LEN; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(BSS, WARN, "No PKT_INFO_T for sending Null Frame.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Null frame in MSDU_INfO_T. */ + bssComposeNullFrame(prAdapter, + (uint8_t *) ((unsigned long)prMsduInfo->prPacket + + MAC_TX_RESERVED_FIELD), prStaRec); + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_HEADER_LEN, + WLAN_MAC_HEADER_LEN, pfTxDoneHandler, MSDU_RATE_MODE_AUTO); + + /* 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. + */ +/*---------------------------------------------------------------------------*/ +uint32_t +bssSendQoSNullFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, IN uint8_t ucUP, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + struct MSDU_INFO *prMsduInfo; + uint16_t u2EstimatedFrameLen; + + /* 4 <1> Allocate a PKT_INFO_T for Null Frame */ + /* Init with MGMT Header Length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + WLAN_MAC_HEADER_QOS_LEN; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(BSS, WARN, "No PKT_INFO_T for sending Null Frame.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Null frame in MSDU_INfO_T. */ + bssComposeQoSNullFrame(prAdapter, + (uint8_t + *) ((unsigned long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD), prStaRec, ucUP, + FALSE); + + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_HEADER_QOS_LEN, WLAN_MAC_HEADER_QOS_LEN, + pfTxDoneHandler, MSDU_RATE_MODE_AUTO); + + /* 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 struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + uint8_t *pucBuffer; + uint8_t ucExtSupRatesLen; + + ASSERT(prMsduInfo); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + ASSERT(prBssInfo); + + pucBuffer = + (uint8_t *) ((unsigned long)prMsduInfo->prPacket + + (unsigned long)prMsduInfo->u2FrameLength); + ASSERT(pucBuffer); + + if (prBssInfo->ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) + + ucExtSupRatesLen = + prBssInfo->ucAllSupportedRatesLen - ELEM_MAX_LEN_SUP_RATES; + else + ucExtSupRatesLen = 0; + + /* Fill the Extended Supported Rates element. */ + if (ucExtSupRatesLen) { + + EXT_SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_EXTENDED_SUP_RATES; + EXT_SUP_RATES_IE(pucBuffer)->ucLength = ucExtSupRatesLen; + + kalMemCopy(EXT_SUP_RATES_IE(pucBuffer)->aucExtSupportedRates, + &prBssInfo->aucAllSupportedRates + [ELEM_MAX_LEN_SUP_RATES], ucExtSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + } +} /* end of bssGenerateExtSuppRate_IE() */ + +/*---------------------------------------------------------------------------*/ +/*! + * @brief This function is used to compose Common Information Elements for + * Beacon or Probe Response Frame. + * + * @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. + * @param[in] prBssInfo Pointer to the BSS_INFO_T. + * @param[in] pucDestAddr Pointer to the Destination Address, + * if NULL, means Beacon. + * + * @return (none) + */ +/*---------------------------------------------------------------------------*/ +void +bssBuildBeaconProbeRespFrameCommonIEs(IN struct MSDU_INFO *prMsduInfo, + IN struct BSS_INFO *prBssInfo, + IN uint8_t *pucDestAddr) +{ + uint8_t *pucBuffer; + uint8_t ucSupRatesLen; + + ASSERT(prMsduInfo); + ASSERT(prBssInfo); + + pucBuffer = + (uint8_t *) ((unsigned long)prMsduInfo->prPacket + + (unsigned long)prMsduInfo->u2FrameLength); + ASSERT(pucBuffer); + + /* 4 <1> Fill the SSID element. */ + SSID_IE(pucBuffer)->ucId = ELEM_ID_SSID; + + if ((!pucDestAddr) + && (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { + /* For Beacon */ + if (prBssInfo->eHiddenSsidType == + ENUM_HIDDEN_SSID_ZERO_CONTENT) { + /* clear the data, but keep the correct + * length of the SSID + */ + SSID_IE(pucBuffer)->ucLength = prBssInfo->ucSSIDLen; + kalMemZero(SSID_IE(pucBuffer)->aucSSID, + prBssInfo->ucSSIDLen); + } else if (prBssInfo->eHiddenSsidType == + ENUM_HIDDEN_SSID_ZERO_LEN) { + /* empty SSID */ + SSID_IE(pucBuffer)->ucLength = 0; + } else { + SSID_IE(pucBuffer)->ucLength = prBssInfo->ucSSIDLen; + if (prBssInfo->ucSSIDLen) + kalMemCopy(SSID_IE(pucBuffer)->aucSSID, + prBssInfo->aucSSID, + prBssInfo->ucSSIDLen); + } + } else { /* Probe response */ + 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->eNetworkType == NETWORK_TYPE_P2P) { + /* IEEE 802.11 2007 - 7.3.2.6 */ + TIM_IE(pucBuffer)->ucId = ELEM_ID_TIM; + /* NOTE: fixed PVB length + * (AID is allocated from 8 ~ 15 only) + */ + TIM_IE(pucBuffer)->ucLength = + (3 + + MAX_LEN_TIM_PARTIAL_BMP) /*((u4N2 - u4N1) + 4) */; + TIM_IE(pucBuffer)->ucDTIMCount = + 0 /*prBssInfo->ucDTIMCount */; + /* will be overwritten by FW */ + TIM_IE(pucBuffer)->ucDTIMPeriod = + prBssInfo->ucDTIMPeriod; + /* will be overwritten by FW */ + TIM_IE(pucBuffer)->ucBitmapControl = + 0 /*ucBitmapControl | (uint8_t)u4N1 */; + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } else +#endif /* CFG_ENABLE_WIFI_DIRECT */ + { + /* NOTE(Kevin): 1. AIS - Didn't Support AP Mode. + * 2. BOW - Didn't Support BCAST and PS. + */ + } + } + + /* 4 <6> Fill the DS Parameter Set element. */ + if (prBssInfo->ucCountryIELen != 0) { + COUNTRY_IE(pucBuffer)->ucId = ELEM_ID_COUNTRY_INFO; + COUNTRY_IE(pucBuffer)->ucLength = prBssInfo->ucCountryIELen; + COUNTRY_IE(pucBuffer)->aucCountryStr[0] = + prBssInfo->aucCountryStr[0]; + COUNTRY_IE(pucBuffer)->aucCountryStr[1] = + prBssInfo->aucCountryStr[1]; + COUNTRY_IE(pucBuffer)->aucCountryStr[2] = + prBssInfo->aucCountryStr[2]; + kalMemCopy(COUNTRY_IE(pucBuffer)->arCountryStr, + prBssInfo->aucSubbandTriplet, + prBssInfo->ucCountryIELen - 3); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + } +} /* 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 uint8_t *pucBuffer, + IN uint8_t *pucDestAddr, + IN uint8_t *pucOwnMACAddress, + IN uint8_t *pucBSSID, + IN uint16_t u2BeaconInterval, + IN uint16_t u2CapInfo) +{ + struct WLAN_BEACON_FRAME *prBcnProbRspFrame; + uint8_t aucBCAddr[] = BC_MAC_ADDR; + uint16_t u2FrameCtrl; + + DEBUGFUNC("bssComposeBeaconProbeRespFrameHeaderAndFF"); + /* DBGLOG(INIT, LOUD, ("\n")); */ + + ASSERT(pucBuffer); + ASSERT(pucOwnMACAddress); + ASSERT(pucBSSID); + + prBcnProbRspFrame = (struct WLAN_BEACON_FRAME *)pucBuffer; + + /* 4 <1> Compose the frame header of the Beacon /ProbeResp frame. */ + /* Fill the Frame Control field. */ + if (pucDestAddr) { + u2FrameCtrl = MAC_FRAME_PROBE_RSP; + } else { + u2FrameCtrl = MAC_FRAME_BEACON; + pucDestAddr = aucBCAddr; + } + /* WLAN_SET_FIELD_16(&prBcnProbRspFrame->u2FrameCtrl, u2FrameCtrl); */ + prBcnProbRspFrame->u2FrameCtrl = u2FrameCtrl; + /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the DA field with BCAST MAC ADDR or TA of ProbeReq. */ + COPY_MAC_ADDR(prBcnProbRspFrame->aucDestAddr, pucDestAddr); + + /* Fill the SA field with our MAC Address. */ + COPY_MAC_ADDR(prBcnProbRspFrame->aucSrcAddr, pucOwnMACAddress); + + /* Fill the BSSID field with current BSSID. */ + COPY_MAC_ADDR(prBcnProbRspFrame->aucBSSID, pucBSSID); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, + * so we need to clear it). + */ + prBcnProbRspFrame->u2SeqCtrl = 0; + + /* 4 <2> Compose the frame body's common fixed field part of the Beacon + * / ProbeResp frame. + */ + /* MAC will update TimeStamp field */ + + /* Fill the Beacon Interval field. */ + /* WLAN_SET_FIELD_16(&prBcnProbRspFrame->u2BeaconInterval, + * u2BeaconInterval); + */ + prBcnProbRspFrame->u2BeaconInterval = u2BeaconInterval; + /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the Capability Information field. */ + /* WLAN_SET_FIELD_16(&prBcnProbRspFrame->u2CapInfo, u2CapInfo); */ + prBcnProbRspFrame->u2CapInfo = u2CapInfo; + /* NOTE(Kevin): Optimized for ARM */ +} /* end of bssComposeBeaconProbeRespFrameHeaderAndFF() */ + +/*---------------------------------------------------------------------------*/ +/*! + * @brief Update the Beacon Frame Template to FW for AIS AdHoc and P2P GO. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] ucBssIndex Specify which network reply the Probe Response. + * + * @retval WLAN_STATUS_SUCCESS Success. + */ +/*---------------------------------------------------------------------------*/ +uint32_t bssUpdateBeaconContent(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + struct BSS_INFO *prBssInfo; + struct MSDU_INFO *prMsduInfo; + struct WLAN_BEACON_FRAME *prBcnFrame; + uint32_t i; + + DEBUGFUNC("bssUpdateBeaconContent"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + /* 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((uint8_t *) + ((unsigned + long)(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->ucBssIndex = ucBssIndex; + + /* 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(struct APPEND_VAR_IE_ENTRY); + i++) { + if (txBcnIETable[i].pfnAppendIE) + txBcnIETable[i].pfnAppendIE(prAdapter, prMsduInfo); + + } + + prBcnFrame = (struct WLAN_BEACON_FRAME *)prMsduInfo->prPacket; + + return nicUpdateBeaconIETemplate(prAdapter, + IE_UPD_METHOD_UPDATE_ALL, + ucBssIndex, + prBssInfo->u2CapInfo, + (uint8_t *) prBcnFrame->aucInfoElem, + prMsduInfo->u2FrameLength - + OFFSET_OF(struct WLAN_BEACON_FRAME, + 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] ucBssIndex 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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t +bssSendBeaconProbeResponse(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN uint8_t *pucDestAddr, + IN uint32_t u4ControlFlags) +{ + struct BSS_INFO *prBssInfo; + struct MSDU_INFO *prMsduInfo; + uint16_t u2EstimatedFrameLen; + uint16_t u2EstimatedFixedIELen; + uint16_t u2EstimatedExtraIELen; + struct APPEND_VAR_IE_ENTRY *prIeArray = NULL; + uint32_t u4IeArraySize = 0; + uint32_t i; + + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (!pucDestAddr) { /* For Beacon */ + prIeArray = &txBcnIETable[0]; + u4IeArraySize = + sizeof(txBcnIETable) / sizeof(struct APPEND_VAR_IE_ENTRY); + } else { + prIeArray = &txProbRspIETable[0]; + u4IeArraySize = + sizeof(txProbRspIETable) / + sizeof(struct APPEND_VAR_IE_ENTRY); + } + + /* 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 += (uint16_t) + prIeArray[i].pfnCalculateVariableIELen(prAdapter, + ucBssIndex, + NULL); + } + } + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(BSS, WARN, "No PKT_INFO_T for sending %s.\n", + ((!pucDestAddr) ? "Beacon" : "Probe Response")); + return WLAN_STATUS_RESOURCES; + } + + /* 4 <2> Compose Beacon/Probe Response frame header + * and fixed fields in MSDU_INfO_T. + */ + /* Compose Header and Fixed Field */ +#if CFG_ENABLE_WIFI_DIRECT + if (u4ControlFlags & BSS_PROBE_RESP_USE_P2P_DEV_ADDR) { + if (prAdapter->fgIsP2PRegistered) { + bssComposeBeaconProbeRespFrameHeaderAndFF((uint8_t *) + ((unsigned long) + (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((uint8_t *) + ((unsigned long) + (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + pucDestAddr, prBssInfo->aucOwnMacAddr, + prBssInfo->aucBSSID, + prBssInfo->u2BeaconInterval, prBssInfo->u2CapInfo); + } + + /* 4 <3> Update information of MSDU_INFO_T */ + + TX_SET_MMPDU(prAdapter, + prMsduInfo, + ucBssIndex, + STA_REC_INDEX_NOT_FOUND, + WLAN_MAC_MGMT_HEADER_LEN, + (WLAN_MAC_MGMT_HEADER_LEN + TIMESTAMP_FIELD_LEN + + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN), NULL, + MSDU_RATE_MODE_AUTO); + + /* 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); + + } + + /* Set limited retry count and lifetime for Probe Resp is reasonable */ + nicTxSetPktLifeTime(prMsduInfo, 100); + nicTxSetPktRetryLimit(prMsduInfo, 2); + + /* 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t bssProcessProbeRequest(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct WLAN_MAC_MGMT_HEADER *prMgtHdr; + struct BSS_INFO *prBssInfo; + uint8_t ucBssIndex; + uint8_t aucBCBSSID[] = BC_BSSID; + u_int8_t fgIsBcBssid; + u_int8_t fgReplyProbeResp; + uint32_t u4CtrlFlagsForProbeResp = 0; + enum ENUM_BAND eBand; + uint8_t ucHwChannelNum; + + ASSERT(prSwRfb); + + /* 4 <1> Parse Probe Req and Get BSSID */ + prMgtHdr = (struct WLAN_MAC_MGMT_HEADER *)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 (ucBssIndex = 0; ucBssIndex <= prAdapter->ucP2PDevBssIdx; + ucBssIndex++) { + + if (!IS_NET_ACTIVE(prAdapter, ucBssIndex)) + continue; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if ((!fgIsBcBssid) + && UNEQUAL_MAC_ADDR(prBssInfo->aucBSSID, + prMgtHdr->aucBSSID)) + continue; + + eBand = HAL_RX_STATUS_GET_RF_BAND(prSwRfb->prRxStatus); + ucHwChannelNum = + HAL_RX_STATUS_GET_CHNL_NUM(prSwRfb->prRxStatus); + + if (prBssInfo->eBand != eBand) + continue; + + if (prBssInfo->ucPrimaryChannel != ucHwChannelNum) + continue; + + fgReplyProbeResp = FALSE; + + if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) { + +#if CFG_SUPPORT_ADHOC + fgReplyProbeResp = + aisValidateProbeReq(prAdapter, prSwRfb, + &u4CtrlFlagsForProbeResp); +#endif + } +#if CFG_ENABLE_WIFI_DIRECT + else if ((prAdapter->fgIsP2PRegistered) + && (prBssInfo->eNetworkType == NETWORK_TYPE_P2P)) { + + fgReplyProbeResp = + p2pFuncValidateProbeReq(prAdapter, prSwRfb, + &u4CtrlFlagsForProbeResp, + (prBssInfo->ucBssIndex == + prAdapter->ucP2PDevBssIdx), + (uint8_t) + prBssInfo->u4PrivateData); + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (prBssInfo->eNetworkType == NETWORK_TYPE_BOW) + fgReplyProbeResp = + bowValidateProbeReq(prAdapter, prSwRfb, + &u4CtrlFlagsForProbeResp); +#endif + + if (fgReplyProbeResp) { + if (nicTxGetFreeCmdCount(prAdapter) > + (CFG_TX_MAX_CMD_PKT_NUM / 2)) { + /* Resource margin is enough */ + bssSendBeaconProbeResponse(prAdapter, + ucBssIndex, + prMgtHdr->aucSrcAddr, + u4CtrlFlagsForProbeResp); + } + } + } + + return WLAN_STATUS_SUCCESS; + +} /* end of bssProcessProbeRequest() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is used to initialize 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 bssInitializeClientList(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo) +{ + struct LINK *prStaRecOfClientList; + + ASSERT(prBssInfo); + + prStaRecOfClientList = &prBssInfo->rStaRecOfClientList; + + if (!LINK_IS_EMPTY(prStaRecOfClientList)) + LINK_INITIALIZE(prStaRecOfClientList); + + DBGLOG(BSS, INFO, "Init BSS[%u] Client List\n", prBssInfo->ucBssIndex); + + bssCheckClientList(prAdapter, prBssInfo); +} /* 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 bssAddClient(IN struct ADAPTER *prAdapter, IN struct BSS_INFO *prBssInfo, + IN struct STA_RECORD *prStaRec) +{ + struct LINK *prClientList; + struct STA_RECORD *prCurrStaRec; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prBssInfo); + + prClientList = &prBssInfo->rStaRecOfClientList; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_STA_REC); + + LINK_FOR_EACH_ENTRY(prCurrStaRec, prClientList, rLinkEntry, + struct STA_RECORD) { + + if (prCurrStaRec == prStaRec) { + DBGLOG(BSS, WARN, + "Current Client List already contains that struct STA_RECORD[" + MACSTR "]\n", MAC2STR(prStaRec->aucMacAddr)); + + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_STA_REC); + return; + } + } + + LINK_INSERT_TAIL(prClientList, &prStaRec->rLinkEntry); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_STA_REC); + + bssCheckClientList(prAdapter, prBssInfo); +} /* 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) + */ +/*----------------------------------------------------------------------------*/ +u_int8_t bssRemoveClient(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct STA_RECORD *prStaRec) +{ + struct LINK *prClientList; + struct STA_RECORD *prCurrStaRec, *prStaRecNext; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prBssInfo); + + prClientList = &prBssInfo->rStaRecOfClientList; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_STA_REC); + + LINK_FOR_EACH_ENTRY_SAFE(prCurrStaRec, prStaRecNext, prClientList, + rLinkEntry, struct STA_RECORD) { + + if (!prCurrStaRec) { + DBGLOG(BSS, INFO, + "NULL STA_REC ptr in BSS client list\n"); + break; + } + + if (prCurrStaRec == prStaRec) { + + LINK_REMOVE_KNOWN_ENTRY(prClientList, + &prStaRec->rLinkEntry); + + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_STA_REC); + + return TRUE; + } + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_STA_REC); + + DBGLOG(BSS, INFO, + "Current Client List didn't contain that struct STA_RECORD[" + MACSTR "] before removing.\n", MAC2STR(prStaRec->aucMacAddr)); + + bssCheckClientList(prAdapter, prBssInfo); + + return FALSE; +} /* end of bssRemoveStaRecFromClientList() */ + +struct STA_RECORD *bssRemoveClientByMac(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN uint8_t *pucMac) +{ + struct LINK *prClientList; + struct STA_RECORD *prCurrStaRec, *prStaRecNext; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prBssInfo); + + prClientList = &prBssInfo->rStaRecOfClientList; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_STA_REC); + + LINK_FOR_EACH_ENTRY_SAFE(prCurrStaRec, prStaRecNext, prClientList, + rLinkEntry, struct STA_RECORD) { + + if (!prCurrStaRec) { + DBGLOG(BSS, INFO, + "NULL STA_REC ptr in BSS client list\n"); + break; + } + + if (EQUAL_MAC_ADDR(prCurrStaRec->aucMacAddr, pucMac)) { + + LINK_REMOVE_KNOWN_ENTRY(prClientList, + &prCurrStaRec->rLinkEntry); + + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_STA_REC); + + return prCurrStaRec; + } + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_STA_REC); + + DBGLOG(BSS, INFO, + "Current Client List didn't contain that struct STA_RECORD[" + MACSTR "] before removing.\n", MAC2STR(pucMac)); + + bssCheckClientList(prAdapter, prBssInfo); + + return NULL; +} + +struct STA_RECORD *bssGetClientByMac(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN uint8_t *pucMac) +{ + struct LINK *prClientList; + struct STA_RECORD *prCurrStaRec, *prStaRecNext; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prBssInfo); + + prClientList = &prBssInfo->rStaRecOfClientList; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_STA_REC); + + LINK_FOR_EACH_ENTRY_SAFE(prCurrStaRec, prStaRecNext, prClientList, + rLinkEntry, struct STA_RECORD) { + + if (!prCurrStaRec) { + DBGLOG(BSS, INFO, + "NULL STA_REC ptr in BSS client list\n"); + break; + } + + if (EQUAL_MAC_ADDR(prCurrStaRec->aucMacAddr, pucMac)) { + KAL_RELEASE_SPIN_LOCK(prAdapter, + SPIN_LOCK_STA_REC); + return prCurrStaRec; + } + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_STA_REC); + + DBGLOG(BSS, INFO, + "Current Client List didn't contain that struct STA_RECORD[" + MACSTR "] before removing.\n", MAC2STR(pucMac)); + + bssCheckClientList(prAdapter, prBssInfo); + + return NULL; +} + +struct STA_RECORD *bssRemoveHeadClient(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo) +{ + struct LINK *prStaRecOfClientList; + struct STA_RECORD *prStaRec = NULL; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prBssInfo); + + prStaRecOfClientList = &prBssInfo->rStaRecOfClientList; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_STA_REC); + + if (!LINK_IS_EMPTY(prStaRecOfClientList)) + LINK_REMOVE_HEAD(prStaRecOfClientList, prStaRec, + struct STA_RECORD *); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_STA_REC); + + bssCheckClientList(prAdapter, prBssInfo); + + return prStaRec; +} + +uint32_t bssGetClientCount(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo) +{ + return prBssInfo->rStaRecOfClientList.u4NumElem; +} + +void bssDumpClientList(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo) +{ + struct LINK *prClientList; + struct STA_RECORD *prCurrStaRec; + uint8_t ucCount = 0; + + ASSERT(prBssInfo); + + prClientList = &prBssInfo->rStaRecOfClientList; + + DBGLOG(SW4, INFO, "Dump BSS[%u] Client List NUM[%u]\n", + prBssInfo->ucBssIndex, prClientList->u4NumElem); + + LINK_FOR_EACH_ENTRY(prCurrStaRec, prClientList, rLinkEntry, + struct STA_RECORD) { + + if (!prCurrStaRec) { + DBGLOG(SW4, INFO, "[%2u] is NULL STA_REC\n", ucCount); + break; + } + DBGLOG(SW4, INFO, "[%2u] STA[%u] [" MACSTR "]\n", ucCount, + prCurrStaRec->ucIndex, + MAC2STR(prCurrStaRec->aucMacAddr)); + + ucCount++; + } +} + +void bssCheckClientList(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo) +{ + struct LINK *prClientList; + struct STA_RECORD *prCurrStaRec; + uint8_t ucCount = 0; + u_int8_t fgError = FALSE; + + ASSERT(prBssInfo); + + prClientList = &prBssInfo->rStaRecOfClientList; + + /* Check MAX number */ + if (prClientList->u4NumElem > P2P_MAXIMUM_CLIENT_COUNT) { + DBGLOG(SW4, INFO, "BSS[%u] Client List NUM[%u] ERR\n", + prBssInfo->ucBssIndex, prClientList->u4NumElem); + + fgError = TRUE; + } + + /* Check default list status */ + if (prClientList->u4NumElem == 0) { + if ((void *)prClientList->prNext != (void *)prClientList) + fgError = TRUE; + if ((void *)prClientList->prPrev != (void *)prClientList) + fgError = TRUE; + + if (fgError) { + DBGLOG(SW4, INFO, + "BSS[%u] Client List PTR next/prev[%p/%p] ERR\n", + prBssInfo->ucBssIndex, prClientList->prNext, + prClientList->prPrev); + } + } + + /* Traverse list */ + LINK_FOR_EACH_ENTRY(prCurrStaRec, prClientList, rLinkEntry, + struct STA_RECORD) { + if (!prCurrStaRec) { + fgError = TRUE; + DBGLOG(SW4, INFO, "BSS[%u] Client List NULL PTR ERR\n", + prBssInfo->ucBssIndex); + + break; + } + + ucCount++; + } + + /* Check real count and list number */ + if (ucCount != prClientList->u4NumElem) { + DBGLOG(SW4, INFO, + "BSS[%u] Client List NUM[%u] REAL CNT[%u] ERR\n", + prBssInfo->ucBssIndex, prClientList->u4NumElem, ucCount); + + fgError = TRUE; + } + + if (fgError) + bssDumpClientList(prAdapter, prBssInfo); + +} + +#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 struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct BSS_DESC *prBssDesc, IN uint8_t ucRCPI) +{ + struct STA_RECORD *prStaRec = NULL; + + u_int8_t fgIsCheckCapability = FALSE; + u_int8_t fgIsCheckTSF = FALSE; + u_int8_t fgIsGoingMerging = FALSE; + u_int8_t 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, + prAdapter->prAisBssInfo->ucBssIndex, + 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->ucBssIndex == + prAdapter->prAisBssInfo->ucBssIndex) + && 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) { + u_int8_t 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) { + /* 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) { + struct MSG_AIS_IBSS_PEER_FOUND *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, + prAdapter-> + prAisBssInfo->ucBssIndex, + 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 = (struct MSG_AIS_IBSS_PEER_FOUND *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_AIS_IBSS_PEER_FOUND)); + + if (!prAisIbssPeerFoundMsg) { + + ASSERT(0); /* Can't send Merge Msg */ + return; + } + + prAisIbssPeerFoundMsg->rMsgHdr.eMsgId = MID_SCN_AIS_FOUND_IBSS; + prAisIbssPeerFoundMsg->ucBssIndex = + prAdapter->prAisBssInfo->ucBssIndex; + 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, + (struct MSG_HDR *)prAisIbssPeerFoundMsg, + MSG_SEND_METHOD_BUF); + + } +} /* end of ibssProcessMatchedBeacon() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will check the Capability for Ad-Hoc to decide + * if we are able to merge with(same capability). + * + * @param[in] prBSSDesc Pointer to the BSS Descriptor. + * + * @retval WLAN_STATUS_FAILURE Can't pass the check of Capability. + * @retval WLAN_STATUS_SUCCESS Pass the check of Capability. + */ +/*----------------------------------------------------------------------------*/ +uint32_t ibssCheckCapabilityForAdHocMode(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc) +{ + struct CONNECTION_SETTINGS *prConnSettings; + uint32_t 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; + } + /* 4 <4> Check the Security setting. */ + if (!rsnPerformPolicySelection(prAdapter, prBssDesc)) + break; + + 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 struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo) +{ + uint8_t aucBSSID[MAC_ADDR_LEN]; + uint16_t *pu2BSSID = (uint16_t *) &aucBSSID[0]; + uint32_t i; + + ASSERT(prBssInfo); + ASSERT(prBssInfo->eCurrentOPMode == OP_MODE_IBSS); + + /* 4 <1> Setup PHY Attributes and Basic Rate Set/Operational Rate Set */ + prBssInfo->ucNonHTBasicPhyType = (uint8_t) + 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(uint16_t); i++) + pu2BSSID[i] = (uint16_t) (kalRandomNumber() & 0xFFFF); + + /* 7.1.3.3.3 - + * The individual/group bit of the address is set to 0. + */ + aucBSSID[0] &= ~0x01; + /* 7.1.3.3.3 - + * The universal/local bit of the address is set to 1. + */ + aucBSSID[0] |= 0x02; + + COPY_MAC_ADDR(prBssInfo->aucBSSID, aucBSSID); + } + + /* 4 <3> Setup Capability - Short Preamble */ + if (rNonHTPhyAttributes + [prBssInfo->ucNonHTBasicPhyType].fgIsShortPreambleOptionImplemented + && + /* Short Preamble Option Enable is TRUE */ + ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_SHORT) || + (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 */ + nicTxUpdateBssDefaultRate(prBssInfo); +} /* 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 struct ADAPTER *prAdapter, IN struct BSS_INFO *prBssInfo, + IN u_int8_t fgIsRateUpdate) +{ + struct AC_QUE_PARMS *prACQueParms; + + enum ENUM_WMM_ACI eAci; + + uint8_t auCWminLog2ForBcast[WMM_AC_INDEX_NUM] = { 4, 4, 3, 2 }; + uint8_t auCWmaxLog2ForBcast[WMM_AC_INDEX_NUM] = { 10, 10, 4, 3 }; + uint8_t auAifsForBcast[WMM_AC_INDEX_NUM] = { 3, 7, 2, 2 }; + /* If the AP is OFDM */ + uint8_t auTxopForBcast[WMM_AC_INDEX_NUM] = { 0, 0, 94, 47 }; + + uint8_t auCWminLog2[WMM_AC_INDEX_NUM] = { 4, 4, 3, 2 }; + uint8_t auCWmaxLog2[WMM_AC_INDEX_NUM] = { 6, 10, 4, 3 }; + uint8_t auAifs[WMM_AC_INDEX_NUM] = { 3, 7, 1, 1 }; + /* If the AP is OFDM */ + uint8_t auTxop[WMM_AC_INDEX_NUM] = { 0, 0, 94, 47 }; + + DEBUGFUNC("bssInitForAP"); + + 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 = (uint8_t) + 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 + && + /* Short Preamble Option Enable is TRUE */ + ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_SHORT) || + (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; +#ifdef CFG_SET_BCN_CAPINFO_BY_DRIVER + /* 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; +#endif + /* 4 <6> Find Lowest Basic Rate Index for default TX Rate of MMPDU */ + nicTxUpdateBssDefaultRate(prBssInfo); + + /* 4 <7> Fill the EDCA */ + + prACQueParms = prBssInfo->arACQueParmsForBcast; + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + + prACQueParms[eAci].ucIsACMSet = 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]; + + /* used to send WMM IE */ + prBssInfo->aucCWminLog2ForBcast[eAci] = + auCWminLog2ForBcast[eAci]; + prBssInfo->aucCWmaxLog2ForBcast[eAci] = + auCWmaxLog2ForBcast[eAci]; + } + + DBGLOG(BSS, INFO, + "Bcast: ACM[%d,%d,%d,%d] Aifsn[%d,%d,%d,%d] CWmin/max[%d/%d,%d/%d,%d/%d,%d/%d] TxopLimit[%d,%d,%d,%d]\n", + prACQueParms[0].ucIsACMSet, prACQueParms[1].ucIsACMSet, + prACQueParms[2].ucIsACMSet, prACQueParms[3].ucIsACMSet, + prACQueParms[0].u2Aifsn, prACQueParms[1].u2Aifsn, + prACQueParms[2].u2Aifsn, prACQueParms[3].u2Aifsn, + prACQueParms[0].u2CWmin, prACQueParms[0].u2CWmax, + prACQueParms[1].u2CWmin, prACQueParms[1].u2CWmax, + prACQueParms[2].u2CWmin, prACQueParms[2].u2CWmax, + prACQueParms[3].u2CWmin, prACQueParms[3].u2CWmax, + prACQueParms[0].u2TxopLimit, prACQueParms[1].u2TxopLimit, + prACQueParms[2].u2TxopLimit, prACQueParms[3].u2TxopLimit); + + prACQueParms = prBssInfo->arACQueParms; + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + + prACQueParms[eAci].ucIsACMSet = 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, + "ACM[%d,%d,%d,%d] Aifsn[%d,%d,%d,%d] CWmin/max[%d/%d,%d/%d,%d/%d,%d/%d] TxopLimit[%d,%d,%d,%d]\n", + prACQueParms[0].ucIsACMSet, prACQueParms[1].ucIsACMSet, + prACQueParms[2].ucIsACMSet, prACQueParms[3].ucIsACMSet, + prACQueParms[0].u2Aifsn, prACQueParms[1].u2Aifsn, + prACQueParms[2].u2Aifsn, prACQueParms[3].u2Aifsn, + prACQueParms[0].u2CWmin, prACQueParms[0].u2CWmax, + prACQueParms[1].u2CWmin, prACQueParms[1].u2CWmax, + prACQueParms[2].u2CWmin, prACQueParms[2].u2CWmax, + prACQueParms[3].u2CWmin, prACQueParms[3].u2CWmax, + prACQueParms[0].u2TxopLimit, prACQueParms[1].u2TxopLimit, + prACQueParms[2].u2TxopLimit, prACQueParms[3].u2TxopLimit); + + /* Note: Caller should update the EDCA setting to HW by + * nicQmUpdateWmmParms() it there is no AIS network + * Note: In E2, only 4 HW queues. + * The the Edca parameters should be folow by AIS network + * Note: In E3, 8 HW queues. + * the Wmm parameters should be updated to right queues + * according to BSS + */ +} /* end of bssInitForAP() */ + +#endif /* CFG_SUPPORT_AAA */ + +void bssCreateStaRecFromAuth(IN struct ADAPTER *prAdapter) +{ + +} + +void bssUpdateStaRecFromAssocReq(IN struct ADAPTER *prAdapter) +{ + +} + +void bssDumpBssInfo(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIndex) +{ + struct BSS_INFO *prBssInfo; + /* P_LINK_T prStaRecOfClientList = (P_LINK_T) NULL; */ + /* P_STA_RECORD_T prCurrStaRec = (P_STA_RECORD_T) NULL; */ + + if (ucBssIndex > prAdapter->ucHwBssIdNum) { + DBGLOG(SW4, INFO, "Invalid BssInfo index[%u], skip dump!\n", + ucBssIndex); + return; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (!prBssInfo) { + DBGLOG(SW4, INFO, "Invalid BssInfo index[%u], skip dump!\n", + ucBssIndex); + return; + } + + DBGLOG(SW4, INFO, "OWNMAC[" MACSTR "] BSSID[" MACSTR "] SSID[%s]\n", + MAC2STR(prBssInfo->aucOwnMacAddr), MAC2STR(prBssInfo->aucBSSID), + prBssInfo->aucSSID); + + DBGLOG(SW4, INFO, + "BSS IDX[%u] Type[%s] OPMode[%s] ConnState[%u] Absent[%u]\n", + prBssInfo->ucBssIndex, apucNetworkType[prBssInfo->eNetworkType], + apucNetworkOpMode[prBssInfo->eCurrentOPMode], + prBssInfo->eConnectionState, prBssInfo->fgIsNetAbsent); + + DBGLOG(SW4, INFO, + "Channel[%u] Band[%u] SCO[%u] Assoc40mBwAllowed[%u] 40mBwAllowed[%u] MaxBw[%u] Nss[%u]\n", + prBssInfo->ucPrimaryChannel, prBssInfo->eBand, + prBssInfo->eBssSCO, prBssInfo->fgAssoc40mBwAllowed, + prBssInfo->fg40mBwAllowed, cnmGetBssMaxBw(prAdapter, + prBssInfo->ucBssIndex), + prBssInfo->ucNss); + + DBGLOG(SW4, INFO, "QBSS[%u] CapInfo[0x%04x] AID[%u]\n", + prBssInfo->fgIsQBSS, prBssInfo->u2CapInfo, prBssInfo->u2AssocId); + + DBGLOG(SW4, INFO, + "ShortPreamble Allowed[%u] EN[%u], ShortSlotTime[%u]\n", + prBssInfo->fgIsShortPreambleAllowed, + prBssInfo->fgUseShortPreamble, prBssInfo->fgUseShortSlotTime); + + DBGLOG(SW4, INFO, "PhyTypeSet: Basic[0x%02x] NonHtBasic[0x%02x]\n", + prBssInfo->ucPhyTypeSet, prBssInfo->ucNonHTBasicPhyType); + + DBGLOG(SW4, INFO, "RateSet: BssBasic[0x%04x] Operational[0x%04x]\n", + prBssInfo->u2BSSBasicRateSet, prBssInfo->u2OperationalRateSet); + + DBGLOG(SW4, INFO, "ATIMWindow[%u] DTIM Period[%u] Count[%u]\n", + prBssInfo->u2ATIMWindow, prBssInfo->ucDTIMPeriod, + prBssInfo->ucDTIMCount); + + DBGLOG(SW4, INFO, + "HT Operation Info1[0x%02x] Info2[0x%04x] Info3[0x%04x]\n", + prBssInfo->ucHtOpInfo1, prBssInfo->u2HtOpInfo2, + prBssInfo->u2HtOpInfo3); + + DBGLOG(SW4, INFO, + "ProtectMode HT[%u] ERP[%u], OperationMode GF[%u] RIFS[%u]\n", + prBssInfo->eHtProtectMode, prBssInfo->fgErpProtectMode, + prBssInfo->eGfOperationMode, prBssInfo->eRifsOperationMode); + + DBGLOG(SW4, INFO, + "(OBSS) ProtectMode HT[%u] ERP[%u], OperationMode GF[%u] RIFS[%u]\n", + prBssInfo->eObssHtProtectMode, prBssInfo->fgObssErpProtectMode, + prBssInfo->eObssGfOperationMode, + prBssInfo->fgObssRifsOperationMode); + + DBGLOG(SW4, INFO, + "VhtChannelWidth[%u] OpChangeChannelWidth[%u], IsOpChangeChannelWidth[%u]\n", + prBssInfo->ucVhtChannelWidth, prBssInfo->ucOpChangeChannelWidth, + prBssInfo->fgIsOpChangeChannelWidth); + + DBGLOG(SW4, INFO, "======== Dump Connected Client ========\n"); + +#if 0 + DBGLOG(SW4, INFO, "NumOfClient[%u]\n", + bssGetClientCount(prAdapter, prBssInfo)); + + prStaRecOfClientList = &prBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH_ENTRY(prCurrStaRec, prStaRecOfClientList, rLinkEntry, + struct STA_RECORD) { + DBGLOG(SW4, INFO, "STA[%u] [" MACSTR "]\n", + prCurrStaRec->ucIndex, + MAC2STR(prCurrStaRec->aucMacAddr)); + } +#else + bssDumpClientList(prAdapter, prBssInfo); +#endif + + DBGLOG(SW4, INFO, "============== Dump Done ==============\n"); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/cnm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/cnm.c new file mode 100644 index 0000000000000..e94f1c7ae24e6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/cnm.c @@ -0,0 +1,3670 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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 + */ + + +/******************************************************************************* + * C O M P I L E 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 + ******************************************************************************* + */ +#if CFG_SUPPORT_DBDC +#define DBDC_SWITCH_GUARD_TIME (4*1000) /* ms */ +#define DBDC_DISABLE_COUNTDOWN_TIME (2*1000) /* ms */ +#endif /* CFG_SUPPORT_DBDC */ + +#if CFG_SUPPORT_IDC_CH_SWITCH +#define IDC_CSA_GUARD_TIME (60) /* 60 Sec */ +#endif + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ +#if CFG_SUPPORT_DBDC +enum ENUM_DBDC_GUARD_TIMER_T { + ENUM_DBDC_GUARD_TIMER_NONE, + + /* Prevent switch too quick */ + ENUM_DBDC_GUARD_TIMER_SWITCH_GUARD_TIME, + + /* Prevent continuously trigger by reconnection */ + ENUM_DBDC_GUARD_TIMER_DISABLE_COUNT_DOWN, + + ENUM_DBDC_GUARD_TIMER_NUM +}; + +enum ENUM_DBDC_FSM_STATE_T { + ENUM_DBDC_FSM_STATE_DISABLE_IDLE, + ENUM_DBDC_FSM_STATE_WAIT_PROTOCOL_ENABLE, + ENUM_DBDC_FSM_STATE_WAIT_HW_ENABLE, + ENUM_DBDC_FSM_STATE_ENABLE_GUARD, + ENUM_DBDC_FSM_STATE_ENABLE_IDLE, + ENUM_DBDC_FSM_STATE_WAIT_HW_DISABLE, + ENUM_DBDC_FSM_STATE_DISABLE_GUARD, + ENUM_DBDC_FSM_STATE_WAIT_PROTOCOL_DISABLE, + ENUM_DBDC_FSM_STATE_NUM +}; + +enum ENUM_OPMODE_STATE_T { + ENUM_OPMODE_STATE_DONE, + ENUM_OPMODE_STATE_FAIL, + ENUM_OPMODE_STATE_WAIT, + ENUM_OPMODE_STATE_NUM +}; + +struct DBDC_INFO_T { + enum ENUM_DBDC_FSM_STATE_T eDbdcFsmCurrState; + enum ENUM_DBDC_FSM_STATE_T eDbdcFsmPrevState; + enum ENUM_DBDC_FSM_STATE_T eDbdcFsmNextState; + + struct TIMER rDbdcGuardTimer; + enum ENUM_DBDC_GUARD_TIMER_T eDdbcGuardTimerType; + + uint8_t fgReqPrivelegeLock; + struct LINK rPendingMsgList; + + uint8_t fgDbdcDisableOpmodeChangeDone; + enum ENUM_OPMODE_STATE_T eBssOpModeState[BSSID_NUM]; + + /* Set DBDC setting for incoming network */ + uint8_t ucPrimaryChannel; + uint8_t ucWmmQueIdx; + + /* Used for iwpriv to force enable DBDC*/ + bool fgHasSentCmd; + bool fgCmdEn; +}; + +enum ENUM_DBDC_FSM_EVENT_T { + DBDC_FSM_EVENT_BSS_DISCONNECT_LEAVE_AG, + DBDC_FSM_EVENT_BSS_CONNECTING_ENTER_AG, + DBDC_FSM_EVENT_SWITCH_GUARD_TIME_TO, + DBDC_FSM_EVENT_DISABLE_COUNT_DOWN_TO, + DBDC_FSM_EVENT_ACTION_FRAME_ALL_SUCCESS, + DBDC_FSM_EVENT_ACTION_FRAME_SOME_FAIL, + DBDC_FSM_EVENT_DBDC_HW_SWITCH_DONE, + DBDC_FSM_EVENT_ERR, + DBDC_FSM_EVENT_NUM +}; + +enum ENUM_DBDC_PROTOCOL_STATUS_T { + ENUM_DBDC_PROTOCOL_STATUS_DONE_SUCCESS = 0, + ENUM_DBDC_PROTOCOL_STATUS_DONE_FAIL, + ENUM_DBDC_PROTOCOL_STATUS_WAIT, + ENUM_DBDC_PROTOCOL_STATUS_NUM +}; + +typedef void (*DBDC_ENTRY_FUNC)(struct ADAPTER *); +typedef void (*DBDC_EVENT_HNDL_FUNC)(struct ADAPTER *, + enum ENUM_DBDC_FSM_EVENT_T); +typedef void (*DBDC_EXIT_FUNC)(struct ADAPTER *); + +struct DBDC_FSM_T { + DBDC_ENTRY_FUNC pfEntryFunc; + DBDC_EVENT_HNDL_FUNC pfEventHandlerFunc; + DBDC_EXIT_FUNC pfExitFunc; +}; +#endif /*CFG_SUPPORT_DBDC*/ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +#if CFG_SUPPORT_IDC_CH_SWITCH +struct EVENT_LTE_SAFE_CHN g_rLteSafeChInfo; +#endif + +/******************************************************************************* + * P R I V A T E D A T A + ****************************************************************************** + */ +#if CFG_SUPPORT_DBDC +static struct DBDC_INFO_T g_rDbdcInfo; +#endif + +#if CFG_SUPPORT_IDC_CH_SWITCH +OS_SYSTIME g_rLastCsaSysTime; +#endif + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +#if CFG_SUPPORT_DBDC +#define DBDC_IS_BSS_ALIVE(_prBssInfo) \ + (_prBssInfo->fgIsInUse && \ + _prBssInfo->fgIsNetActive && \ + (_prBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED || \ + _prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) + +#define DBDC_IS_BSS_NOT_ALIVE(_prBssInfo) \ + (!_prBssInfo->fgIsInUse || \ + !_prBssInfo->fgIsNetActive || \ + (_prBssInfo->eConnectionState != PARAM_MEDIA_STATE_CONNECTED && \ + _prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT)) + +#define DBDC_SET_GUARD_TIME(_prAdapter) { \ + cnmTimerStartTimer(_prAdapter, \ + &g_rDbdcInfo.rDbdcGuardTimer, \ + DBDC_SWITCH_GUARD_TIME); \ + g_rDbdcInfo.eDdbcGuardTimerType = \ + ENUM_DBDC_GUARD_TIMER_SWITCH_GUARD_TIME; \ +} + +#define DBDC_SET_DISABLE_COUNTDOWN(_prAdapter) { \ + cnmTimerStartTimer(_prAdapter, \ + &g_rDbdcInfo.rDbdcGuardTimer, \ + DBDC_DISABLE_COUNTDOWN_TIME); \ + g_rDbdcInfo.eDdbcGuardTimerType = \ + ENUM_DBDC_GUARD_TIMER_DISABLE_COUNT_DOWN; \ + } + +#define DBDC_FSM_MSG_WRONG_EVT(_eEvent) \ + log_dbg(CNM, WARN, \ + "[DBDC] Should not reveice evt %u during state %u\n", \ + _eEvent, \ + g_rDbdcInfo.eDbdcFsmCurrState) + +#define DBDC_FSM_MSG_ERROR_EVT(_eEvent) \ + log_dbg(CNM, ERROR, "[DBDC] Reveice evt %u during state %u\n", \ + _eEvent, \ + g_rDbdcInfo.eDbdcFsmCurrState) + +#define USE_DBDC_CAPABILITY() \ + ((g_rDbdcInfo.eDbdcFsmCurrState \ + == ENUM_DBDC_FSM_STATE_WAIT_PROTOCOL_ENABLE || \ + g_rDbdcInfo.eDbdcFsmCurrState \ + == ENUM_DBDC_FSM_STATE_WAIT_HW_ENABLE || \ + g_rDbdcInfo.eDbdcFsmCurrState \ + == ENUM_DBDC_FSM_STATE_ENABLE_GUARD || \ + g_rDbdcInfo.eDbdcFsmCurrState \ + == ENUM_DBDC_FSM_STATE_ENABLE_IDLE)?TRUE:FALSE) + +#define DBDC_SET_WMMBAND_FW_AUTO_BY_CHNL(_ucPrimaryChannel, _ucWmmQueIdx) \ + { \ + g_rDbdcInfo.ucPrimaryChannel = (_ucPrimaryChannel);\ + g_rDbdcInfo.ucWmmQueIdx = (_ucWmmQueIdx);\ + } + +#define DBDC_SET_WMMBAND_FW_AUTO_DEFAULT() \ + { \ + g_rDbdcInfo.ucPrimaryChannel = 0; \ + g_rDbdcInfo.ucWmmQueIdx = 0;\ + } + +#define DBDC_UPDATE_CMD_WMMBAND_FW_AUTO(_prCmdBody) \ + { \ + (_prCmdBody)->ucPrimaryChannel = g_rDbdcInfo.ucPrimaryChannel; \ + (_prCmdBody)->ucWmmQueIdx = g_rDbdcInfo.ucWmmQueIdx; \ + DBDC_SET_WMMBAND_FW_AUTO_DEFAULT(); \ + } + +#endif + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +static u_int8_t +cnmDBDCIsReqPeivilegeLock( + void +); + +static void +cnmDbdcFsmEntryFunc_DISABLE_IDLE( + IN struct ADAPTER *prAdapter +); + +static void +cnmDbdcFsmEntryFunc_WAIT_PROTOCOL_ENABLE( + IN struct ADAPTER *prAdapter +); + +static void +cnmDbdcFsmEntryFunc_WAIT_HW_ENABLE( + IN struct ADAPTER *prAdapter +); + +static void +cnmDbdcFsmEntryFunc_ENABLE_GUARD( + IN struct ADAPTER *prAdapter +); + +static void +cnmDbdcFsmEntryFunc_WAIT_HW_DISABLE( + IN struct ADAPTER *prAdapter +); + +static void +cnmDbdcFsmEntryFunc_DISABLE_GUARD( + IN struct ADAPTER *prAdapter +); + +static void +cnmDbdcFsmEventHandler_DISABLE_IDLE( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent +); + +static void +cnmDbdcFsmEventHandler_WAIT_PROTOCOL_ENABLE( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent +); + +static void +cnmDbdcFsmEventHandler_WAIT_HW_ENABLE( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent +); + +static void +cnmDbdcFsmEventHandler_ENABLE_GUARD( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent +); + +static void +cnmDbdcFsmEventHandler_ENABLE_IDLE( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent +); + +static void +cnmDbdcFsmEventHandler_WAIT_HW_DISABLE( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent +); + +static void +cnmDbdcFsmEventHandler_DISABLE_GUARD( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent +); + +static void +cnmDbdcFsmEventHandler_WAIT_PROTOCOL_DISABLE( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent +); + +static void +cnmDbdcFsmExitFunc_WAIT_HW_ENABLE( + IN struct ADAPTER *prAdapter +); + +/******************************************************************************* + * P R I V A T E D A T A 2 + ******************************************************************************* + */ +static struct DBDC_FSM_T arDdbcFsmActionTable[] = { + /* ENUM_DBDC_FSM_STATE_DISABLE_IDLE */ + { + cnmDbdcFsmEntryFunc_DISABLE_IDLE, + cnmDbdcFsmEventHandler_DISABLE_IDLE, + NULL + }, + + /* ENUM_DBDC_FSM_STATE_WAIT_PROTOCOL_ENABLE */ + { + cnmDbdcFsmEntryFunc_WAIT_PROTOCOL_ENABLE, + cnmDbdcFsmEventHandler_WAIT_PROTOCOL_ENABLE, + NULL + }, + + /* ENUM_DBDC_FSM_STATE_WAIT_HW_ENABLE */ + { + cnmDbdcFsmEntryFunc_WAIT_HW_ENABLE, + cnmDbdcFsmEventHandler_WAIT_HW_ENABLE, + cnmDbdcFsmExitFunc_WAIT_HW_ENABLE + }, + + /* ENUM_DBDC_FSM_STATE_ENABLE_GUARD */ + { + cnmDbdcFsmEntryFunc_ENABLE_GUARD, + cnmDbdcFsmEventHandler_ENABLE_GUARD, + NULL + }, + + /* ENUM_DBDC_FSM_STATE_ENABLE_IDLE */ + { + NULL, + cnmDbdcFsmEventHandler_ENABLE_IDLE, + NULL + }, + + /* ENUM_DBDC_FSM_STATE_WAIT_HW_DISABLE */ + { + cnmDbdcFsmEntryFunc_WAIT_HW_DISABLE, + cnmDbdcFsmEventHandler_WAIT_HW_DISABLE, + NULL + }, + + /* ENUM_DBDC_FSM_STATE_DISABLE_GUARD */ + { + cnmDbdcFsmEntryFunc_DISABLE_GUARD, + cnmDbdcFsmEventHandler_DISABLE_GUARD, + NULL + }, + + /* ENUM_DBDC_FSM_STATE_WAIT_PROTOCOL_DISABLE */ + { + NULL, + cnmDbdcFsmEventHandler_WAIT_PROTOCOL_DISABLE, + NULL + }, +}; + +/******************************************************************************* + * M A C R O S 2 + ******************************************************************************* + */ +#define DBDC_FSM_EVENT_HANDLER(_prAdapter, _event) { \ + arDdbcFsmActionTable[g_rDbdcInfo.eDbdcFsmCurrState] \ + .pfEventHandlerFunc(_prAdapter, _event); \ + } + +/******************************************************************************* + * 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(struct ADAPTER *prAdapter) +{ + struct CNM_INFO *prCnmInfo; + + ASSERT(prAdapter); + + prCnmInfo = &prAdapter->rCnmInfo; + prCnmInfo->fgChGranted = FALSE; +#if CFG_SUPPORT_IDC_CH_SWITCH + g_rLastCsaSysTime = 0; +#endif + +#if CFG_SUPPORT_RX_DYNAMIC_MCC_PRIORITY + cnmTimerInitTimer(prAdapter, + &prAdapter->rRxCntMonitorTimer, + (PFN_MGMT_TIMEOUT_FUNC) cnmRxCntMonitor, + (unsigned long)NULL); + + prAdapter->fgMccFirstIn = true; + + cnmTimerStartTimer(prAdapter, + &prAdapter->rRxCntMonitorTimer, + SEC_TO_MSEC(MCC_CHECK_TIME)); +#endif /*CFG_SUPPORT_RX_DYNAMIC_MCC_PRIORITY*/ +} /* end of cnmInit()*/ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is used to initialize variables in CNM_INFO_T. + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void cnmUninit(struct ADAPTER *prAdapter) +{ + cnmTimerStopTimer(prAdapter, + &g_rDbdcInfo.rDbdcGuardTimer); +} /* 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(struct ADAPTER + *prAdapter, + struct MSG_HDR *prMsgHdr) +{ + struct MSG_CH_REQ *prMsgChReq; + struct CMD_CH_PRIVILEGE *prCmdBody; + uint32_t rStatus; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prMsgChReq = (struct MSG_CH_REQ *)prMsgHdr; + +#if CFG_SUPPORT_DBDC + if (cnmDBDCIsReqPeivilegeLock()) { + LINK_INSERT_TAIL(&g_rDbdcInfo.rPendingMsgList, + &prMsgHdr->rLinkEntry); + log_dbg(CNM, INFO, + "[DBDC] ChReq: queued BSS %u Token %u REQ\n", + prMsgChReq->ucBssIndex, prMsgChReq->ucTokenID); + return; + } +#endif + + prCmdBody = (struct CMD_CH_PRIVILEGE *) + cnmMemAlloc(prAdapter, RAM_TYPE_BUF, + sizeof(struct CMD_CH_PRIVILEGE)); + ASSERT(prCmdBody); + + /* To do: exception handle */ + if (!prCmdBody) { + log_dbg(CNM, ERROR, + "ChReq: fail to get buf (net=%d, token=%d)\n", + prMsgChReq->ucBssIndex, prMsgChReq->ucTokenID); + + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + log_dbg(CNM, INFO, + "ChReq net=%d token=%d b=%d c=%d s=%d w=%d s1=%d s2=%d\n", + prMsgChReq->ucBssIndex, prMsgChReq->ucTokenID, + prMsgChReq->eRfBand, prMsgChReq->ucPrimaryChannel, + prMsgChReq->eRfSco, prMsgChReq->eRfChannelWidth, + prMsgChReq->ucRfCenterFreqSeg1, + prMsgChReq->ucRfCenterFreqSeg2); + + prCmdBody->ucBssIndex = prMsgChReq->ucBssIndex; + prCmdBody->ucTokenID = prMsgChReq->ucTokenID; + prCmdBody->ucAction = CMD_CH_ACTION_REQ; /* Request */ + prCmdBody->ucPrimaryChannel = + prMsgChReq->ucPrimaryChannel; + prCmdBody->ucRfSco = (uint8_t)prMsgChReq->eRfSco; + prCmdBody->ucRfBand = (uint8_t)prMsgChReq->eRfBand; + prCmdBody->ucRfChannelWidth = (uint8_t) + prMsgChReq->eRfChannelWidth; + prCmdBody->ucRfCenterFreqSeg1 = (uint8_t) + prMsgChReq->ucRfCenterFreqSeg1; + prCmdBody->ucRfCenterFreqSeg2 = (uint8_t) + prMsgChReq->ucRfCenterFreqSeg2; + prCmdBody->ucReqType = (uint8_t)prMsgChReq->eReqType; + prCmdBody->ucDBDCBand = (uint8_t)prMsgChReq->eDBDCBand; + prCmdBody->aucReserved = 0; + prCmdBody->u4MaxInterval = prMsgChReq->u4MaxInterval; + prCmdBody->aucReserved2[0] = 0; + prCmdBody->aucReserved2[1] = 0; + prCmdBody->aucReserved2[2] = 0; + prCmdBody->aucReserved2[3] = 0; + prCmdBody->aucReserved2[4] = 0; + prCmdBody->aucReserved2[5] = 0; + prCmdBody->aucReserved2[6] = 0; + prCmdBody->aucReserved2[7] = 0; + + ASSERT(prCmdBody->ucBssIndex <= + prAdapter->ucHwBssIdNum); + + /* For monkey testing 20110901 */ + if (prCmdBody->ucBssIndex > prAdapter->ucHwBssIdNum) + log_dbg(CNM, ERROR, + "CNM: ChReq with wrong netIdx=%d\n\n", + prCmdBody->ucBssIndex); + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_CH_PRIVILEGE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + + /* u4SetQueryInfoLen */ + sizeof(struct CMD_CH_PRIVILEGE), + + /* pucInfoBuffer */ + (uint8_t *)prCmdBody, + + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + /* ASSERT(rStatus == WLAN_STATUS_PENDING); */ + + cnmMemFree(prAdapter, prCmdBody); + cnmMemFree(prAdapter, prMsgHdr); +} /* end of cnmChMngrRequestPrivilege()*/ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Before deliver the message to other module, it need to release + * the Channel privilege to Channel Manager. + * + * @param[in] prMsgHdr The message need to be delivered + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void cnmChMngrAbortPrivilege(struct ADAPTER *prAdapter, + struct MSG_HDR *prMsgHdr) +{ + struct MSG_CH_ABORT *prMsgChAbort; + struct CMD_CH_PRIVILEGE *prCmdBody; + struct CNM_INFO *prCnmInfo; + uint32_t rStatus; +#if CFG_SISO_SW_DEVELOP + struct BSS_INFO *prBssInfo; +#endif +#if CFG_SUPPORT_DBDC + struct LINK_ENTRY *prLinkEntry_pendingMsg; + struct MSG_CH_REQ *prPendingMsg; +#endif + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prMsgChAbort = (struct MSG_CH_ABORT *)prMsgHdr; + +#if CFG_SUPPORT_DBDC + if (cnmDBDCIsReqPeivilegeLock()) { + LINK_FOR_EACH(prLinkEntry_pendingMsg, + &g_rDbdcInfo.rPendingMsgList) { + prPendingMsg = (struct MSG_CH_REQ *) + LINK_ENTRY(prLinkEntry_pendingMsg, + struct MSG_HDR, rLinkEntry); + + /* Find matched request and check + * if it is being served. + */ + if (prPendingMsg->ucBssIndex == prMsgChAbort->ucBssIndex + && prPendingMsg->ucTokenID + == prMsgChAbort->ucTokenID) { + + LINK_REMOVE_KNOWN_ENTRY( + &g_rDbdcInfo.rPendingMsgList, + &prPendingMsg->rMsgHdr.rLinkEntry); + + log_dbg(CNM, INFO, "[DBDC] ChAbort: remove BSS %u Token %u REQ)\n", + prPendingMsg->ucBssIndex, + prPendingMsg->ucTokenID); + + cnmMemFree(prAdapter, prPendingMsg); + cnmMemFree(prAdapter, prMsgHdr); + + return; + } + } + } +#endif + + /* Check if being granted channel privilege is aborted */ + prCnmInfo = &prAdapter->rCnmInfo; + if (prCnmInfo->fgChGranted && + prCnmInfo->ucBssIndex == prMsgChAbort->ucBssIndex + && prCnmInfo->ucTokenID == prMsgChAbort->ucTokenID) { + + prCnmInfo->fgChGranted = FALSE; + } + + prCmdBody = (struct CMD_CH_PRIVILEGE *) + cnmMemAlloc(prAdapter, RAM_TYPE_BUF, + sizeof(struct CMD_CH_PRIVILEGE)); + ASSERT(prCmdBody); + + /* To do: exception handle */ + if (!prCmdBody) { + log_dbg(CNM, ERROR, + "ChAbort: fail to get buf (net=%d, token=%d)\n", + prMsgChAbort->ucBssIndex, prMsgChAbort->ucTokenID); + + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + prCmdBody->ucBssIndex = prMsgChAbort->ucBssIndex; + prCmdBody->ucTokenID = prMsgChAbort->ucTokenID; + prCmdBody->ucAction = CMD_CH_ACTION_ABORT; /* Abort */ + prCmdBody->ucDBDCBand = (uint8_t) + prMsgChAbort->eDBDCBand; + + log_dbg(CNM, INFO, "ChAbort net=%d token=%d dbdc=%u\n", + prCmdBody->ucBssIndex, prCmdBody->ucTokenID, + prCmdBody->ucDBDCBand); + + ASSERT(prCmdBody->ucBssIndex <= + prAdapter->ucHwBssIdNum); + + /* For monkey testing 20110901 */ + if (prCmdBody->ucBssIndex > prAdapter->ucHwBssIdNum) + log_dbg(CNM, ERROR, + "CNM: ChAbort with wrong netIdx=%d\n\n", + prCmdBody->ucBssIndex); + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_CH_PRIVILEGE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + + /* u4SetQueryInfoLen */ + sizeof(struct CMD_CH_PRIVILEGE), + + /* pucInfoBuffer */ + (uint8_t *)prCmdBody, + + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + /* ASSERT(rStatus == WLAN_STATUS_PENDING); */ + +#if CFG_SISO_SW_DEVELOP + prBssInfo = + prAdapter->aprBssInfo[prMsgChAbort->ucBssIndex]; + /* Driver clear granted CH in BSS info */ + prBssInfo->fgIsGranted = FALSE; + prBssInfo->eBandGranted = BAND_NULL; + prBssInfo->ucPrimaryChannelGranted = 0; +#endif + + cnmMemFree(prAdapter, prCmdBody); + cnmMemFree(prAdapter, prMsgHdr); +} /* end of cnmChMngrAbortPrivilege()*/ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void cnmChMngrHandleChEvent(struct ADAPTER *prAdapter, + struct WIFI_EVENT *prEvent) +{ + struct EVENT_CH_PRIVILEGE *prEventBody; + struct MSG_CH_GRANT *prChResp; + struct BSS_INFO *prBssInfo; + struct CNM_INFO *prCnmInfo; + + ASSERT(prAdapter); + ASSERT(prEvent); + + prEventBody = (struct EVENT_CH_PRIVILEGE *)( + prEvent->aucBuffer); + prChResp = (struct MSG_CH_GRANT *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_CH_GRANT)); + ASSERT(prChResp); + + /* To do: exception handle */ + if (!prChResp) { + log_dbg(CNM, ERROR, + "ChGrant: fail to get buf (net=%d, token=%d)\n", + prEventBody->ucBssIndex, prEventBody->ucTokenID); + + return; + } + + log_dbg(CNM, INFO, + "ChGrant net=%d token=%d ch=%d sco=%d u4GrantInterval=%d\n", + prEventBody->ucBssIndex, prEventBody->ucTokenID, + prEventBody->ucPrimaryChannel, + prEventBody->ucRfSco, prEventBody->u4GrantInterval); + + ASSERT(prEventBody->ucBssIndex <= + prAdapter->ucHwBssIdNum); + ASSERT(prEventBody->ucStatus == EVENT_CH_STATUS_GRANT); + + prBssInfo = + prAdapter->aprBssInfo[prEventBody->ucBssIndex]; + + /* Decide message ID based on network and response status */ + if (IS_BSS_AIS(prBssInfo)) + prChResp->rMsgHdr.eMsgId = MID_CNM_AIS_CH_GRANT; +#if CFG_ENABLE_WIFI_DIRECT + else if (prAdapter->fgIsP2PRegistered + && IS_BSS_P2P(prBssInfo)) + prChResp->rMsgHdr.eMsgId = MID_CNM_P2P_CH_GRANT; +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (IS_BSS_BOW(prBssInfo)) + prChResp->rMsgHdr.eMsgId = MID_CNM_BOW_CH_GRANT; +#endif + else { + cnmMemFree(prAdapter, prChResp); + return; + } + + prChResp->ucBssIndex = prEventBody->ucBssIndex; + prChResp->ucTokenID = prEventBody->ucTokenID; + prChResp->ucPrimaryChannel = + prEventBody->ucPrimaryChannel; + prChResp->eRfSco = (enum ENUM_CHNL_EXT) + prEventBody->ucRfSco; + prChResp->eRfBand = (enum ENUM_BAND) + prEventBody->ucRfBand; + prChResp->eRfChannelWidth = (enum ENUM_CHANNEL_WIDTH) + prEventBody->ucRfChannelWidth; + prChResp->ucRfCenterFreqSeg1 = + prEventBody->ucRfCenterFreqSeg1; + prChResp->ucRfCenterFreqSeg2 = + prEventBody->ucRfCenterFreqSeg2; + prChResp->eReqType = (enum ENUM_CH_REQ_TYPE) + prEventBody->ucReqType; + prChResp->eDBDCBand = (enum ENUM_DBDC_BN) + prEventBody->ucDBDCBand; + prChResp->u4GrantInterval = + prEventBody->u4GrantInterval; + + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *)prChResp, MSG_SEND_METHOD_BUF); + + /* Record current granted BSS for TXM's reference */ + prCnmInfo = &prAdapter->rCnmInfo; + prCnmInfo->ucBssIndex = prEventBody->ucBssIndex; + prCnmInfo->ucTokenID = prEventBody->ucTokenID; + prCnmInfo->fgChGranted = TRUE; +} + +#if (CFG_SUPPORT_DFS_MASTER == 1) +void cnmRadarDetectEvent(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct EVENT_RDD_REPORT *prEventBody; + struct BSS_INFO *prBssInfo; + struct MSG_P2P_RADAR_DETECT *prP2pRddDetMsg; + uint8_t ucBssIndex; + + log_dbg(CNM, INFO, "cnmRadarDetectEvent.\n"); + + prEventBody = (struct EVENT_RDD_REPORT *)( + prEvent->aucBuffer); + + prP2pRddDetMsg = (struct MSG_P2P_RADAR_DETECT *) + cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(*prP2pRddDetMsg)); + + if (!prP2pRddDetMsg) { + log_dbg(CNM, ERROR, + "cnmMemAlloc for prP2pRddDetMsg failed!\n"); + return; + } + + prP2pRddDetMsg->rMsgHdr.eMsgId = + MID_CNM_P2P_RADAR_DETECT; + + for (ucBssIndex = 0; ucBssIndex < BSS_DEFAULT_NUM; + ucBssIndex++) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex); + + if (prBssInfo && prBssInfo->fgIsDfsActive) { + prP2pRddDetMsg->ucBssIndex = ucBssIndex; + break; + } + } + + p2pFuncSetDfsState(DFS_STATE_DETECTED); + + p2pFuncRadarInfoInit(); + + g_rP2pRadarInfo.ucRadarReportMode = + prEventBody->ucRadarReportMode; + g_rP2pRadarInfo.ucRddIdx = prEventBody->ucRddIdx; + g_rP2pRadarInfo.ucLongDetected = + prEventBody->ucLongDetected; + g_rP2pRadarInfo.ucPeriodicDetected = + prEventBody->ucPeriodicDetected; + g_rP2pRadarInfo.ucLPBNum = prEventBody->ucLPBNum; + g_rP2pRadarInfo.ucPPBNum = prEventBody->ucPPBNum; + g_rP2pRadarInfo.ucLPBPeriodValid = + prEventBody->ucLPBPeriodValid; + g_rP2pRadarInfo.ucLPBWidthValid = + prEventBody->ucLPBWidthValid; + g_rP2pRadarInfo.ucPRICountM1 = + prEventBody->ucPRICountM1; + g_rP2pRadarInfo.ucPRICountM1TH = + prEventBody->ucPRICountM1TH; + g_rP2pRadarInfo.ucPRICountM2 = + prEventBody->ucPRICountM2; + g_rP2pRadarInfo.ucPRICountM2TH = + prEventBody->ucPRICountM2TH; + g_rP2pRadarInfo.u4PRI1stUs = prEventBody->u4PRI1stUs; + if (prEventBody->ucLPBNum <= LPB_SIZE) { + kalMemCopy(&g_rP2pRadarInfo.arLpbContent[0], + &prEventBody->arLpbContent[0], + prEventBody->ucLPBNum * sizeof(struct + LONG_PULSE_BUFFER)); + } + if (prEventBody->ucPPBNum <= PPB_SIZE) { + kalMemCopy(&g_rP2pRadarInfo.arPpbContent[0], + &prEventBody->arPpbContent[0], + prEventBody->ucPPBNum * sizeof(struct + PERIODIC_PULSE_BUFFER)); + } + + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *)prP2pRddDetMsg, MSG_SEND_METHOD_BUF); +} + +void cnmCsaDoneEvent(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct BSS_INFO *prBssInfo; + struct MSG_P2P_CSA_DONE *prP2pCsaDoneMsg; + uint8_t ucBssIndex; + + DBGLOG(CNM, INFO, "cnmCsaDoneEvent.\n"); + + prP2pCsaDoneMsg = (struct MSG_P2P_CSA_DONE *) + cnmMemAlloc( + prAdapter, + RAM_TYPE_MSG, sizeof(*prP2pCsaDoneMsg)); + + if (!prP2pCsaDoneMsg) { + log_dbg(CNM, ERROR, + "cnmMemAlloc for prP2pCsaDoneMsg failed!\n"); + return; + } + + prAdapter->rWifiVar.fgCsaInProgress = FALSE; + + prP2pCsaDoneMsg->rMsgHdr.eMsgId = MID_CNM_P2P_CSA_DONE; + + for (ucBssIndex = 0; ucBssIndex < BSS_DEFAULT_NUM; + ucBssIndex++) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex); + + if (prBssInfo && + (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { + prP2pCsaDoneMsg->ucBssIndex = ucBssIndex; + break; + } + } + DBGLOG(CNM, INFO, "cnmCsaDoneEvent.ucBssIndex=%d\n", + prP2pCsaDoneMsg->ucBssIndex); + + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *)prP2pCsaDoneMsg, MSG_SEND_METHOD_BUF); +} +#endif + +#define CFG_SUPPORT_IDC_CROSS_BAND_SWITCH 1 + +#if CFG_SUPPORT_IDC_CH_SWITCH +uint8_t cnmDecideSapNewChannel( + IN struct GLUE_INFO *prGlueInfo, uint8_t ucCurrentChannel) +{ + + u_int8_t fgIsReady = FALSE; + struct RF_CHANNEL_INFO aucChannelList2G[MAX_2G_BAND_CHN_NUM]; + struct RF_CHANNEL_INFO aucChannelList5G[MAX_5G_BAND_CHN_NUM]; + uint8_t ucNumOfChannel, i, ucIdx, ucSwitchMode; + uint16_t u2APNumScore = 0, u2UpThreshold = 0, + u2LowThreshold = 0, ucInnerIdx = 0; + uint32_t u4LteSafeChnBitMask_2G = 0, u4LteSafeChnBitMask_5G_1 = 0, + u4LteSafeChnBitMask_5G_2 = 0; + + struct PARAM_GET_CHN_INFO *prGetChnLoad; + struct PARAM_PREFER_CHN_INFO rPreferChannel = { 0, 0xFFFF, 0 }; + struct PARAM_PREFER_CHN_INFO + arChannelDirtyScore_2G[MAX_2G_BAND_CHN_NUM]; + kalMemZero(arChannelDirtyScore_2G, + sizeof(struct PARAM_PREFER_CHN_INFO)*MAX_2G_BAND_CHN_NUM); + + if (!prGlueInfo) { + DBGLOG(P2P, ERROR, "prGlueInfo is NULL\n"); + return -EFAULT; + } + + ASSERT(ucCurrentChannel); + + if (ucCurrentChannel <= 14) + ucSwitchMode = CH_SWITCH_2G; + else { + ucSwitchMode = CH_SWITCH_5G; + DBGLOG(P2P, WARN, + "Switch to 5G channel instead\n"); + } + /* + * Get LTE safe channels + */ + if (g_rLteSafeChInfo.u4Flags & BIT(0)) { + u4LteSafeChnBitMask_2G = g_rLteSafeChInfo + .rLteSafeChn.au4SafeChannelBitmask[0]; + u4LteSafeChnBitMask_5G_1 = g_rLteSafeChInfo + .rLteSafeChn.au4SafeChannelBitmask[1]; + u4LteSafeChnBitMask_5G_2 = g_rLteSafeChInfo + .rLteSafeChn.au4SafeChannelBitmask[2]; + } + + if ((ucSwitchMode == CH_SWITCH_2G) + && (!(u4LteSafeChnBitMask_2G & BITS(1, 14)))) { + DBGLOG(P2P, WARN, + "FW report 2.4G all channels unsafe!?\n"); + u4LteSafeChnBitMask_2G = BITS(1, 14); +#if CFG_SUPPORT_IDC_CROSS_BAND_SWITCH + /* Choose 5G non-RDD Channel */ + if (u4LteSafeChnBitMask_5G_1 || u4LteSafeChnBitMask_5G_2) { + ucSwitchMode = CH_SWITCH_5G; + DBGLOG(P2P, WARN, + "Switch to 5G channel instead\n"); + } else { + /* not to switch channel*/ + return 0; + } +#endif + } + + if (ucSwitchMode == CH_SWITCH_2G) { + /* + * 1. Get 2.4G Band channel list in current regulatory domain + */ + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_2G4, TRUE, + MAX_2G_BAND_CHN_NUM, &ucNumOfChannel, aucChannelList2G); + + fgIsReady = prGlueInfo->prAdapter->rWifiVar + .rChnLoadInfo.fgDataReadyBit; + + if (fgIsReady == TRUE) { + /* + * 2. Calculate each channel's dirty score + */ + prGetChnLoad = &(prGlueInfo->prAdapter->rWifiVar + .rChnLoadInfo); + + for (i = 0; i < ucNumOfChannel; i++) { + ucIdx = aucChannelList2G[i] + .ucChannelNum - 1; + + /* Current channel's dirty score */ + u2APNumScore = + prGetChnLoad->rEachChnLoad[ucIdx] + .u2APNum * CHN_DIRTY_WEIGHT_UPPERBOUND; + u2LowThreshold = u2UpThreshold = 3; + + if (ucIdx < 3) { + u2LowThreshold = ucIdx; + u2UpThreshold = 3; + } else if (ucIdx >= (ucNumOfChannel - 3)) { + u2LowThreshold = 3; + u2UpThreshold = + ucNumOfChannel - (ucIdx + 1); + } + + /* Lower channel's dirty score */ + for (ucInnerIdx = 0; + ucInnerIdx < u2LowThreshold; + ucInnerIdx++) { + u2APNumScore += + (prGetChnLoad->rEachChnLoad + [ucIdx - ucInnerIdx - 1].u2APNum * + (CHN_DIRTY_WEIGHT_UPPERBOUND - 1 + - ucInnerIdx)); + } + + /* Upper channel's dirty score */ + for (ucInnerIdx = 0; + ucInnerIdx < u2UpThreshold; + ucInnerIdx++) { + u2APNumScore += + (prGetChnLoad->rEachChnLoad + [ucIdx + ucInnerIdx + 1].u2APNum * + (CHN_DIRTY_WEIGHT_UPPERBOUND - 1 + - ucInnerIdx)); + } + + arChannelDirtyScore_2G[i].ucChannel = + aucChannelList2G[i].ucChannelNum; + arChannelDirtyScore_2G[i].u2APNumScore + = u2APNumScore; + } + } + + /* 4. Find best channel, skip unsafe*/ + for (i = 0; i < ucNumOfChannel; i++) { + if (!(u4LteSafeChnBitMask_2G + & BIT(arChannelDirtyScore_2G[i].ucChannel))) + continue; + + if (rPreferChannel.u2APNumScore + >= arChannelDirtyScore_2G[i].u2APNumScore) { + rPreferChannel.ucChannel = + arChannelDirtyScore_2G[i].ucChannel; + rPreferChannel.u2APNumScore = + arChannelDirtyScore_2G[i].u2APNumScore; + } + } + } else if (ucSwitchMode == CH_SWITCH_5G) { + + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_5G, TRUE, + MAX_5G_BAND_CHN_NUM, &ucNumOfChannel, aucChannelList5G); + + /* 4. Find best channel, skip unsafe*/ + for (i = 0; i < ucNumOfChannel; i++) { + if ((aucChannelList5G[i].ucChannelNum >= 36) + && (aucChannelList5G[i].ucChannelNum <= 144)) { + ucIdx = (aucChannelList5G[i] + .ucChannelNum - 36) / 4; + if (u4LteSafeChnBitMask_5G_1 & BIT(ucIdx)) { + rPreferChannel.ucChannel = + aucChannelList5G[i] + .ucChannelNum; + break; + } + } else if ((aucChannelList5G[i].ucChannelNum >= 149) + && (aucChannelList5G[i].ucChannelNum <= 181)) { + ucIdx = (aucChannelList5G[i] + .ucChannelNum - 149) / 4; + if (u4LteSafeChnBitMask_5G_2 & BIT(ucIdx)) { + rPreferChannel.ucChannel = + aucChannelList5G[i] + .ucChannelNum; + break; + } + } + } + } else { + /* Should not be here */ + DBGLOG(P2P, ERROR, + "ERROR!! ucSwitchMode = %d\n", ucSwitchMode); + ASSERT(0); + } + + DBGLOG(P2P, INFO, "rPreferChannel = %d, u2APNumScore = %d\n", + rPreferChannel.ucChannel, rPreferChannel.u2APNumScore); + + return rPreferChannel.ucChannel; + +} + +uint8_t cnmIdcCsaReq(IN struct ADAPTER *prAdapter, + IN uint8_t ch_num, IN uint8_t ucRoleIdx) +{ + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct BSS_INFO *prBssInfo = NULL; + uint8_t ucBssIdx = 0; + struct RF_CHANNEL_INFO rRfChnlInfo; + struct MSG_P2P_SET_NEW_CHANNEL *prP2pSetNewChannelMsg = + (struct MSG_P2P_SET_NEW_CHANNEL *) NULL; + struct MSG_P2P_BEACON_UPDATE *prP2pBcnUpdateMsg = + (struct MSG_P2P_BEACON_UPDATE *) NULL; + + ASSERT(ch_num); + ASSERT(prGlueInfo); + + if (p2pFuncRoleToBssIdx( + prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) + return -1; + + DBGLOG(REQ, INFO, + "[CSA]RoleIdx = %d ,CH = %d BssIdx = %d\n", + ucRoleIdx, ch_num, ucBssIdx); + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + + if (prBssInfo->ucPrimaryChannel != ch_num) { + + /* allocate chandef buffer to inform Kernel */ + if (prGlueInfo->prP2PInfo[ucRoleIdx]->chandef == NULL) { + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef = + (struct cfg80211_chan_def *) + cnmMemAlloc(prAdapter, + RAM_TYPE_BUF, sizeof(struct cfg80211_chan_def)); + + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->chan = + (struct ieee80211_channel *) + cnmMemAlloc(prAdapter, + RAM_TYPE_BUF, sizeof(struct ieee80211_channel)); + } + + /* Build New CH Info */ + rRfChnlInfo.ucChannelNum = ch_num; + rRfChnlInfo.eBand = + (rRfChnlInfo.ucChannelNum <= 14) + ? BAND_2G4 : BAND_5G; + + /* Heritage BW from Old connection*/ + rRfChnlInfo.ucChnlBw = (uint8_t) CW_20_40MHZ; + rRfChnlInfo.u2PriChnlFreq = + nicChannelNum2Freq((uint32_t)ch_num) / 1000; + rRfChnlInfo.u4CenterFreq1 = + nicGetVhtS1(rRfChnlInfo.ucChannelNum, + prBssInfo->ucVhtChannelWidth); + rRfChnlInfo.u4CenterFreq2 = 0; + + DBGLOG(REQ, INFO, + "[CSA]CH=%d,Band=%d,BW=%d,PriFreq=%d,S1=%d\n", + rRfChnlInfo.ucChannelNum, + rRfChnlInfo.eBand, + rRfChnlInfo.ucChnlBw, + rRfChnlInfo.u2PriChnlFreq, + rRfChnlInfo.u4CenterFreq1); + + /* fill in chinfo to chandef */ + + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->chan->center_freq + = rRfChnlInfo.u2PriChnlFreq; + prGlueInfo->prP2PInfo[ucRoleIdx] + ->chandef->center_freq1 = rRfChnlInfo.u4CenterFreq1; + prGlueInfo->prP2PInfo[ucRoleIdx] + ->chandef->center_freq2 = rRfChnlInfo.u4CenterFreq2; + + if (rRfChnlInfo.ucChnlBw == ((uint8_t)MAX_BW_20MHZ)) + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->width + = NL80211_CHAN_WIDTH_20; + else if (rRfChnlInfo.ucChnlBw == ((uint8_t)MAX_BW_40MHZ)) + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->width + = NL80211_CHAN_WIDTH_40; + else if (rRfChnlInfo.ucChnlBw == ((uint8_t)MAX_BW_80MHZ)) + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->width + = NL80211_CHAN_WIDTH_80; + else + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->width + = NL80211_CHAN_WIDTH_20; + + if (rRfChnlInfo.eBand == BAND_5G) + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef-> + chan->band = KAL_BAND_5GHZ; + else + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef-> + chan->band = KAL_BAND_2GHZ; + + /* Copy NEW CHINFO to Adapter */ + p2pFuncSetChannel(prAdapter, + ucRoleIdx, &rRfChnlInfo); + + p2pFuncSetDfsState(DFS_STATE_INACTIVE); + + /* Set CSA IE parameters */ + prAdapter->rWifiVar.fgCsaInProgress = TRUE; + prAdapter->rWifiVar.ucChannelSwitchMode = 1; + prAdapter->rWifiVar.ucNewChannelNumber = + rRfChnlInfo.ucChannelNum; + prAdapter->rWifiVar.ucChannelSwitchCount = 5; + + /* Set new channel parameters */ + prP2pSetNewChannelMsg = (struct MSG_P2P_SET_NEW_CHANNEL *) + cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(*prP2pSetNewChannelMsg)); + + if (prP2pSetNewChannelMsg == NULL) { + ASSERT(FALSE); + return -1; + } + + prP2pSetNewChannelMsg->rMsgHdr.eMsgId = + MID_MNY_P2P_SET_NEW_CHANNEL; + + prP2pSetNewChannelMsg->eChannelWidth = + (enum ENUM_CHANNEL_WIDTH) rRfChnlInfo.ucChnlBw; + + prP2pSetNewChannelMsg->ucRoleIdx = ucRoleIdx; + + prP2pSetNewChannelMsg->ucBssIndex = ucBssIdx; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prP2pSetNewChannelMsg, + MSG_SEND_METHOD_BUF); + + /* Update beacon */ + prP2pBcnUpdateMsg = (struct MSG_P2P_BEACON_UPDATE *) + cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_P2P_BEACON_UPDATE)); + + if (prP2pBcnUpdateMsg == NULL) { + ASSERT(FALSE); + return -1; + } + + prP2pBcnUpdateMsg->ucRoleIndex = ucRoleIdx; + prP2pBcnUpdateMsg->rMsgHdr.eMsgId = + MID_MNY_P2P_BEACON_UPDATE; + + prP2pBcnUpdateMsg->u4BcnHdrLen = 0; + prP2pBcnUpdateMsg->pucBcnHdr = NULL; + + prP2pBcnUpdateMsg->u4BcnBodyLen = 0; + prP2pBcnUpdateMsg->pucBcnBody = NULL; + + + kalP2PSetRole(prGlueInfo, 2, ucRoleIdx); + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prP2pBcnUpdateMsg, + MSG_SEND_METHOD_BUF); + + /* Record Last Channel Switch Time */ + GET_CURRENT_SYSTIME(&g_rLastCsaSysTime); + + return 0; /* Return Success */ + + } else { + DBGLOG(CNM, INFO, + "[CSA]Req CH = cur CH:%d, Stop Req\n", + prBssInfo->ucPrimaryChannel); + return -1; + } +} + +void cnmIdcDetectHandler(IN struct ADAPTER *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + + struct EVENT_LTE_SAFE_CHN *prEventBody; + uint8_t ucBssIndex, ucIdx; + struct BSS_INFO *prBssInfo; + uint8_t ucRoleIdx = 0; + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + uint8_t ucNewChannel = 0; + uint32_t u4Ret = 0; + OS_SYSTIME rCurrentTime = 0; + bool fgCsaCoolDown = FALSE; + + prEventBody = (struct EVENT_LTE_SAFE_CHN *)( + prEvent->aucBuffer); + + g_rLteSafeChInfo.ucVersion = prEventBody->ucVersion; + g_rLteSafeChInfo.u4Flags = prEventBody->u4Flags; + + /* Statistics from FW is valid */ + if (prEventBody->u4Flags & BIT(0)) { + for (ucIdx = 0; + ucIdx < NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_MAX; + ucIdx++) { + g_rLteSafeChInfo.rLteSafeChn. + au4SafeChannelBitmask[ucIdx] + = prEventBody->rLteSafeChn. + au4SafeChannelBitmask[ucIdx]; + + DBGLOG(P2P, INFO, + "[CSA]LTE safe channels[%d]=0x%08x\n", + ucIdx, + prEventBody->rLteSafeChn. + au4SafeChannelBitmask[ucIdx]); + } + } + + /* Only allow to switch channel once each minute*/ + GET_CURRENT_SYSTIME(&rCurrentTime); + if ((CHECK_FOR_TIMEOUT(rCurrentTime, + g_rLastCsaSysTime, + SEC_TO_SYSTIME(IDC_CSA_GUARD_TIME))) + || (g_rLastCsaSysTime == 0)) { + fgCsaCoolDown = TRUE; + } + + if (!fgCsaCoolDown) { + DBGLOG(CNM, INFO, + "[CSA]CsaCoolDown not Finish yet,rCurrentTime=%d,g_rLastCsaSysTime=%d,IDC_CSA_GUARD_TIME=%d\n", + rCurrentTime, + g_rLastCsaSysTime, + SEC_TO_SYSTIME(IDC_CSA_GUARD_TIME)); + return; + } + + /* Choose New Ch & Start CH Swtich*/ + for (ucBssIndex = 0; ucBssIndex < BSS_DEFAULT_NUM; + ucBssIndex++) { + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + if (prBssInfo && + (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { + DBGLOG(CNM, INFO, "[CSA]BssIdx=%d,CurCH=%d\n", + prBssInfo->ucBssIndex, + prBssInfo->ucPrimaryChannel); + ucNewChannel = cnmDecideSapNewChannel(prGlueInfo, + prBssInfo->ucPrimaryChannel); + if (ucNewChannel) { + u4Ret = cnmIdcCsaReq(prAdapter, ucNewChannel, + ucRoleIdx); + DBGLOG(CNM, INFO, "[CSA]BssIdx=%d,NewCH=%d\n", + ucBssIndex, ucNewChannel); + } else { + DBGLOG(CNM, INFO, + "[CSA]No Safe channel,not switch CH\n"); + } + break; + } + } +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t +cnmPreferredChannel(struct ADAPTER *prAdapter, + enum ENUM_BAND *prBand, uint8_t *pucPrimaryChannel, + enum ENUM_CHNL_EXT *prBssSCO) +{ + struct BSS_INFO *prBssInfo; + uint8_t i; + + ASSERT(prAdapter); + ASSERT(prBand); + ASSERT(pucPrimaryChannel); + ASSERT(prBssSCO); + + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, i); + + if (prBssInfo) { + if (IS_BSS_AIS(prBssInfo) + && 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t cnmAisInfraChannelFixed(struct ADAPTER + *prAdapter, + enum ENUM_BAND *prBand, + uint8_t *pucPrimaryChannel) +{ + struct BSS_INFO *prBssInfo; + uint8_t i; + struct WIFI_VAR *prWifiVar; + + ASSERT(prAdapter); + + prWifiVar = &prAdapter->rWifiVar; + + if (prWifiVar->u4ScanCtrl & + SCN_CTRL_DEFAULT_SCAN_CTRL) { + /* log_dbg(CNM, INFO, "ByPass AIS channel Fix check\n");*/ + return FALSE; + } + + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + +#if 0 + log_dbg(INIT, INFO, + "%s BSS[%u] active[%u] netType[%u]\n", + __func__, i, prBssInfo->fgIsNetActive, + prBssInfo->eNetworkType); +#endif + + if (!IS_NET_ACTIVE(prAdapter, i)) + continue; + +#if CFG_ENABLE_WIFI_DIRECT + if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) { + u_int8_t fgFixedChannel = + p2pFuncIsAPMode( + prAdapter->rWifiVar.prP2PConnSettings[ + prBssInfo->u4PrivateData]); + + if (fgFixedChannel) { + + *prBand = prBssInfo->eBand; + *pucPrimaryChannel + = prBssInfo->ucPrimaryChannel; + + return TRUE; + + } + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI && CFG_BOW_LIMIT_AIS_CHNL + if (prBssInfo->eNetworkType == NETWORK_TYPE_BOW) { + *prBand = prBssInfo->eBand; + *pucPrimaryChannel = prBssInfo->ucPrimaryChannel; + + return TRUE; + } +#endif + + } + + return FALSE; +} + +#if CFG_SUPPORT_CHNL_CONFLICT_REVISE +u_int8_t cnmAisDetectP2PChannel(struct ADAPTER + *prAdapter, + enum ENUM_BAND *prBand, + uint8_t *pucPrimaryChannel) +{ + uint8_t i = 0; + struct BSS_INFO *prBssInfo; + + ASSERT(prAdapter); + +#if CFG_ENABLE_WIFI_DIRECT + for (; i < prAdapter->ucHwBssIdNum; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + if (prBssInfo->eNetworkType != NETWORK_TYPE_P2P) + continue; + if (prBssInfo->eConnectionState == + PARAM_MEDIA_STATE_CONNECTED || + (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT + && prBssInfo->eIntendOPMode == OP_MODE_NUM)) { + *prBand = prBssInfo->eBand; + *pucPrimaryChannel = prBssInfo->ucPrimaryChannel; + return TRUE; + } + } +#endif + return FALSE; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void cnmAisInfraConnectNotify(struct ADAPTER *prAdapter) +{ +#if CFG_ENABLE_BT_OVER_WIFI + struct BSS_INFO *prBssInfo, *prAisBssInfo, *prBowBssInfo; + uint8_t i; + + ASSERT(prAdapter); + + prAisBssInfo = NULL; + prBowBssInfo = NULL; + + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + + if (prBssInfo && IS_BSS_ACTIVE(prBssInfo)) { + if (IS_BSS_AIS(prBssInfo)) + prAisBssInfo = prBssInfo; + else if (IS_BSS_BOW(prBssInfo)) + prBowBssInfo = prBssInfo; + } + } + + if (prAisBssInfo && prBowBssInfo + && 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t cnmAisIbssIsPermitted(struct ADAPTER + *prAdapter) +{ + struct BSS_INFO *prBssInfo; + uint8_t i; + + ASSERT(prAdapter); + + /* P2P device network shall be included */ + for (i = 0; i <= prAdapter->ucHwBssIdNum; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + + if (prBssInfo && IS_BSS_ACTIVE(prBssInfo) + && !IS_BSS_AIS(prBssInfo)) + return FALSE; + } + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param (none) + * + * @return TRUE: permitted + * FALSE: Not permitted + */ +/*----------------------------------------------------------------------------*/ +u_int8_t cnmP2PIsPermitted(struct ADAPTER *prAdapter) +{ + struct BSS_INFO *prBssInfo; + uint8_t i; + u_int8_t fgBowIsActive; + + ASSERT(prAdapter); + + fgBowIsActive = FALSE; + + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + + if (prBssInfo && IS_BSS_ACTIVE(prBssInfo)) { + if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) + return FALSE; + else if (IS_BSS_BOW(prBssInfo)) + fgBowIsActive = TRUE; + } + } + +#if CFG_ENABLE_BT_OVER_WIFI + if (fgBowIsActive) { + /* Notify BOW to do deactivation */ + bowNotifyAllLinkDisconnected(prAdapter); + } +#endif + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param (none) + * + * @return TRUE: permitted + * FALSE: Not permitted + */ +/*----------------------------------------------------------------------------*/ +u_int8_t cnmBowIsPermitted(struct ADAPTER *prAdapter) +{ + struct BSS_INFO *prBssInfo; + uint8_t i; + + ASSERT(prAdapter); + + /* P2P device network shall be included */ + for (i = 0; i <= prAdapter->ucHwBssIdNum; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + + if (prBssInfo && IS_BSS_ACTIVE(prBssInfo) && + (IS_BSS_P2P(prBssInfo) + || prBssInfo->eCurrentOPMode == OP_MODE_IBSS)) { + return FALSE; + } + } + + return TRUE; +} + + + +static uint8_t cnmGetAPBwPermitted(struct ADAPTER + *prAdapter, uint8_t ucBssIndex) +{ + struct BSS_INFO *prBssInfo; + uint8_t ucAPBandwidth = MAX_BW_160MHZ; + struct BSS_DESC *prBssDesc = NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *)NULL; + uint8_t i = 0; + uint8_t ucOffset = (MAX_BW_80MHZ - CW_80MHZ); + + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex); + + + if (IS_BSS_AIS(prBssInfo)) { + /*AIS station mode*/ + prBssDesc = + prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc; + } else if (IS_BSS_P2P(prBssInfo)) { + /* P2P mode */ + + for (i = 0 ; i < BSS_P2P_NUM; i++) { + + if (!prAdapter->rWifiVar.aprP2pRoleFsmInfo[i]) + continue; + + if (prAdapter->rWifiVar.aprP2pRoleFsmInfo[i]->ucBssIndex + == + ucBssIndex) + break; + + } + + if (i >= BSS_P2P_NUM) { + prP2pRoleFsmInfo = NULL; + } else { + prP2pRoleFsmInfo = + prAdapter->rWifiVar.aprP2pRoleFsmInfo[i]; + + /*only GC need to consider GO's BW*/ + if (!p2pFuncIsAPMode( + prAdapter->rWifiVar.prP2PConnSettings[ + prBssInfo->u4PrivateData])) { + prBssDesc = prP2pRoleFsmInfo->rJoinInfo + .prTargetBssDesc; + } + + } + + + } + + if (prBssDesc) { + if (prBssDesc->eChannelWidth == CW_20_40MHZ) { + if ((prBssDesc->eSco == CHNL_EXT_SCA) + || (prBssDesc->eSco == CHNL_EXT_SCB)) + ucAPBandwidth = MAX_BW_40MHZ; + else + ucAPBandwidth = MAX_BW_20MHZ; + } else { + ucAPBandwidth = prBssDesc->eChannelWidth + ucOffset; + } + + } + + return ucAPBandwidth; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param (none) + * + * @return TRUE: permitted + * FALSE: Not permitted + */ +/*----------------------------------------------------------------------------*/ +u_int8_t cnmBss40mBwPermitted(struct ADAPTER *prAdapter, + uint8_t ucBssIndex) +{ + ASSERT(prAdapter); + + /* 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 + */ + + /* Decide max bandwidth by feature option */ + if (cnmGetBssMaxBw(prAdapter, + ucBssIndex) < MAX_BW_40MHZ) + return FALSE; + + /*check AP or GO capbility for Station or GC */ + if (cnmGetAPBwPermitted(prAdapter, + ucBssIndex) < MAX_BW_40MHZ) + return FALSE; +#if 0 + /* Decide max by other BSS */ + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + if (i != ucBssIndex) { + prBssInfo = prAdapter->aprBssInfo[i]; + + if (prBssInfo && IS_BSS_ACTIVE(prBssInfo) && + (prBssInfo->fg40mBwAllowed + || prBssInfo->fgAssoc40mBwAllowed)) + return FALSE; + } + } +#endif + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param (none) + * + * @return TRUE: permitted + * FALSE: Not permitted + */ +/*----------------------------------------------------------------------------*/ +u_int8_t cnmBss80mBwPermitted(struct ADAPTER *prAdapter, + uint8_t ucBssIndex) +{ + ASSERT(prAdapter); + + /* 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 + */ + + /* Check 40Mhz first */ + if (!cnmBss40mBwPermitted(prAdapter, ucBssIndex)) + return FALSE; + + /* Decide max bandwidth by feature option */ + if (cnmGetBssMaxBw(prAdapter, + ucBssIndex) < MAX_BW_80MHZ) + return FALSE; + + /*check AP or GO capbility for Station or GC */ + if (cnmGetAPBwPermitted(prAdapter, + ucBssIndex) < MAX_BW_80MHZ) + return FALSE; + + return TRUE; +} + +uint8_t cnmGetBssMaxBw(struct ADAPTER *prAdapter, + uint8_t ucBssIndex) +{ + struct BSS_INFO *prBssInfo; + uint8_t ucMaxBandwidth = + MAX_BW_80_80_MHZ; /*chip capability*/ + struct BSS_DESC *prBssDesc = NULL; + enum ENUM_BAND eBand = BAND_NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct P2P_CONNECTION_REQ_INFO *prP2pConnReqInfo = + (struct P2P_CONNECTION_REQ_INFO *) NULL; +#if (CFG_SUPPORT_SINGLE_SKU == 1) + uint8_t ucChannelBw = MAX_BW_80_80_MHZ; +#endif + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex); + + if (IS_BSS_AIS(prBssInfo)) { + /* STA mode */ + + + /* should check Bss_info could be used or not + *the info might not be trustable before state3 + */ + + prBssDesc = + prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc; + if (prBssDesc) + eBand = prBssDesc->eBand; + else + eBand = prBssInfo->eBand; + + + ASSERT(eBand != BAND_NULL); + + if (eBand == BAND_2G4) + ucMaxBandwidth = prAdapter->rWifiVar.ucSta2gBandwidth; + else + ucMaxBandwidth = prAdapter->rWifiVar.ucSta5gBandwidth; + + if (ucMaxBandwidth > prAdapter->rWifiVar.ucStaBandwidth) + ucMaxBandwidth = prAdapter->rWifiVar.ucStaBandwidth; + } else if (IS_BSS_P2P(prBssInfo)) { + prP2pRoleFsmInfo = p2pFuncGetRoleByBssIdx(prAdapter, + ucBssIndex); + if (!prAdapter->rWifiVar.ucApChnlDefFromCfg + && prP2pRoleFsmInfo + && prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + prP2pConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + ucMaxBandwidth = prP2pConnReqInfo->eChnlBw; + } else { + /* AP mode */ + if (p2pFuncIsAPMode( + prAdapter->rWifiVar.prP2PConnSettings[ + prBssInfo->u4PrivateData])) { + if (prBssInfo->eBand == BAND_2G4) + ucMaxBandwidth = prAdapter->rWifiVar + .ucAp2gBandwidth; + else + ucMaxBandwidth = prAdapter->rWifiVar + .ucAp5gBandwidth; + + if (ucMaxBandwidth + > prAdapter->rWifiVar.ucApBandwidth) + ucMaxBandwidth = prAdapter->rWifiVar + .ucApBandwidth; + } + /* P2P mode */ + else { + if (prBssInfo->eBand == BAND_2G4) + ucMaxBandwidth = prAdapter->rWifiVar + .ucP2p2gBandwidth; + else + ucMaxBandwidth = prAdapter->rWifiVar + .ucP2p5gBandwidth; + } + + } + + } + +#if (CFG_SUPPORT_SINGLE_SKU == 1) + if (IS_BSS_AIS(prBssInfo) && prBssDesc) + ucChannelBw = rlmDomainGetChannelBw(prBssDesc->ucChannelNum); + else + ucChannelBw = + rlmDomainGetChannelBw(prBssInfo->ucPrimaryChannel); + if (ucMaxBandwidth > ucChannelBw) + ucMaxBandwidth = ucChannelBw; +#endif + DBGLOG(CNM, INFO, "pCH=%d, BW=%d\n", + prBssInfo->ucPrimaryChannel, ucMaxBandwidth); + + return ucMaxBandwidth; +} + + +uint8_t cnmGetBssMaxBwToChnlBW(struct ADAPTER + *prAdapter, + uint8_t ucBssIndex) +{ + uint8_t ucMaxBandwidth = cnmGetBssMaxBw(prAdapter, + ucBssIndex); + return ucMaxBandwidth == MAX_BW_20MHZ ? ucMaxBandwidth : + (ucMaxBandwidth - 1); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Search available HW ID and BSS_INFO structure and initialize + * these parameters, i.e., fgIsNetActive, ucBssIndex, eNetworkType + * and ucOwnMacIndex + * + * @param (none) + * + * @return + */ +/*----------------------------------------------------------------------------*/ +struct BSS_INFO *cnmGetBssInfoAndInit(struct ADAPTER *prAdapter, + enum ENUM_NETWORK_TYPE eNetworkType, + u_int8_t fgIsP2pDevice) +{ + struct BSS_INFO *prBssInfo; + uint8_t i, ucBssIndex, ucOwnMacIdx; + + ASSERT(prAdapter); + + /*specific case for p2p device scan*/ + if (eNetworkType == NETWORK_TYPE_P2P && fgIsP2pDevice) { + prBssInfo = + prAdapter->aprBssInfo[prAdapter->ucP2PDevBssIdx]; + + prBssInfo->fgIsInUse = TRUE; + prBssInfo->ucBssIndex = prAdapter->ucP2PDevBssIdx; + prBssInfo->eNetworkType = eNetworkType; + prBssInfo->ucOwnMacIndex = prAdapter->ucHwBssIdNum; +#if CFG_SUPPORT_PNO + prBssInfo->fgIsPNOEnable = FALSE; + prBssInfo->fgIsNetRequestInActive = FALSE; +#endif + /* init add key action */ + prBssInfo->eKeyAction = SEC_TX_KEY_COMMAND; + + /* initialize wlan id and status for keys */ + prBssInfo->ucBMCWlanIndex = WTBL_RESERVED_ENTRY; + prBssInfo->wepkeyWlanIdx = WTBL_RESERVED_ENTRY; + for (i = 0; i < MAX_KEY_NUM; i++) { + prBssInfo->ucBMCWlanIndexSUsed[i] = FALSE; + prBssInfo->ucBMCWlanIndexS[i] = WTBL_RESERVED_ENTRY; + prBssInfo->wepkeyUsed[i] = FALSE; + } + return prBssInfo; + } + + /*reserve ownMAC0 for MBSS*/ + ucOwnMacIdx = (eNetworkType == NETWORK_TYPE_MBSS) ? 0 : + 1; + + /* Find available HW set with the order 1,2,..*/ + do { + for (ucBssIndex = 0; + ucBssIndex < prAdapter->ucHwBssIdNum; + ucBssIndex++) { + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + + if (prBssInfo && prBssInfo->fgIsInUse + && ucOwnMacIdx == prBssInfo->ucOwnMacIndex) + break; + } + + if (ucBssIndex >= prAdapter->ucHwBssIdNum) { + /* No hit the ucOwnMacIndex could be + * assigned to this new bss + */ + break; + } + } while (++ucOwnMacIdx < prAdapter->ucHwBssIdNum); + + + /* should not dispatch P2P_DEV_BSS_INDEX (prAdapter->ucHwBssIdNum) + * to general bss. It means total BSS_INFO_NUM BSS are created, + * no more reseve for MBSS + */ + if (ucOwnMacIdx == prAdapter->ucHwBssIdNum) { + + for (ucBssIndex = 0; + ucBssIndex < prAdapter->ucHwBssIdNum; + ucBssIndex++) { + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + + /*If the Bss was alredy assigned, and in use*/ + if (prBssInfo && prBssInfo->fgIsInUse + && prBssInfo->ucOwnMacIndex == 0) + break; + } + + if (ucBssIndex >= prAdapter->ucHwBssIdNum) { + /* there is no NETWORK_TYPE_MBSS used before */ + + log_dbg(INIT, WARN, "[Warning] too much Bss in use, take reserve OwnMac(%d)for usage!\n", + ucOwnMacIdx); + ucOwnMacIdx = 0; + } + + } + + /* Find available BSS_INFO */ + for (ucBssIndex = 0; + ucBssIndex < prAdapter->ucHwBssIdNum; + ucBssIndex++) { + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + + if (prBssInfo && !prBssInfo->fgIsInUse) { + prBssInfo->fgIsInUse = TRUE; + prBssInfo->ucBssIndex = ucBssIndex; + prBssInfo->eNetworkType = eNetworkType; + prBssInfo->ucOwnMacIndex = ucOwnMacIdx; +#if (CFG_HW_WMM_BY_BSS == 1) + prBssInfo->ucWmmQueSet = DEFAULT_HW_WMM_INDEX; + prBssInfo->fgIsWmmInited = FALSE; +#endif + break; + } + } + + if (ucOwnMacIdx >= prAdapter->ucHwBssIdNum + || ucBssIndex >= prAdapter->ucHwBssIdNum) + prBssInfo = NULL; + if (prBssInfo) { +#if CFG_SUPPORT_PNO + prBssInfo->fgIsPNOEnable = FALSE; + prBssInfo->fgIsNetRequestInActive = FALSE; +#endif + /* init add key action */ + prBssInfo->eKeyAction = SEC_TX_KEY_COMMAND; + + /* initialize wlan id and status for keys */ + prBssInfo->ucBMCWlanIndex = WTBL_RESERVED_ENTRY; + prBssInfo->wepkeyWlanIdx = WTBL_RESERVED_ENTRY; + for (i = 0; i < MAX_KEY_NUM; i++) { + prBssInfo->ucBMCWlanIndexSUsed[i] = FALSE; + prBssInfo->ucBMCWlanIndexS[i] = WTBL_RESERVED_ENTRY; + prBssInfo->wepkeyUsed[i] = FALSE; + } + } + return prBssInfo; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Search available HW ID and BSS_INFO structure and initialize + * these parameters, i.e., ucBssIndex, eNetworkType and ucOwnMacIndex + * + * @param (none) + * + * @return + */ +/*----------------------------------------------------------------------------*/ +void cnmFreeBssInfo(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo) +{ + ASSERT(prAdapter); + ASSERT(prBssInfo); + + prBssInfo->fgIsInUse = FALSE; +} + +#if CFG_SUPPORT_DBDC +/*----------------------------------------------------------------------------*/ +/*! + * @brief Init DBDC + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void cnmInitDbdcSetting(IN struct ADAPTER *prAdapter) +{ + uint8_t ucBssLoopIndex; + + DBDC_SET_WMMBAND_FW_AUTO_DEFAULT(); + g_rDbdcInfo.fgHasSentCmd = FALSE; + + /* Parameter decision */ + switch (prAdapter->rWifiVar.eDbdcMode) { + case ENUM_DBDC_MODE_DISABLED: + cnmUpdateDbdcSetting(prAdapter, FALSE); + break; + + case ENUM_DBDC_MODE_DYNAMIC: + g_rDbdcInfo.eDbdcFsmCurrState = + ENUM_DBDC_FSM_STATE_DISABLE_IDLE; + g_rDbdcInfo.eDbdcFsmPrevState = + ENUM_DBDC_FSM_STATE_DISABLE_IDLE; + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_DISABLE_IDLE; + + cnmTimerInitTimer(prAdapter, + &g_rDbdcInfo.rDbdcGuardTimer, + (PFN_MGMT_TIMEOUT_FUNC)cnmDbdcGuardTimerCallback, + (unsigned long) NULL); + + g_rDbdcInfo.eDdbcGuardTimerType = + ENUM_DBDC_GUARD_TIMER_NONE; + g_rDbdcInfo.fgReqPrivelegeLock = FALSE; + LINK_INITIALIZE(&g_rDbdcInfo.rPendingMsgList); + g_rDbdcInfo.fgDbdcDisableOpmodeChangeDone = TRUE; + + for (ucBssLoopIndex = 0; + ucBssLoopIndex < prAdapter->ucHwBssIdNum; + ucBssLoopIndex++) + g_rDbdcInfo.eBssOpModeState[ucBssLoopIndex] = + ENUM_OPMODE_STATE_DONE; + + cnmUpdateDbdcSetting(prAdapter, FALSE); + break; + + case ENUM_DBDC_MODE_STATIC: + cnmUpdateDbdcSetting(prAdapter, TRUE); + break; + + default: + log_dbg(CNM, ERROR, "[DBDC]Incorrect DBDC mode %u\n", + prAdapter->rWifiVar.eDbdcMode); + break; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Check A+G Condition + * + * @param (none) + * + * @return TRUE: A+G, FALSE: NOT A+G + */ +/*----------------------------------------------------------------------------*/ +static u_int8_t cnmDbdcIsAGConcurrent( + IN struct ADAPTER *prAdapter, + IN enum ENUM_BAND eRfBand_Connecting) +{ + struct BSS_INFO *prBssInfo; + uint8_t ucBssIndex; + enum ENUM_BAND eBandCompare = eRfBand_Connecting; + u_int8_t fgAGConcurrent = FALSE; + enum ENUM_BAND eBssBand[BSSID_NUM] = {BAND_NULL}; + + for (ucBssIndex = 0; + ucBssIndex < prAdapter->ucHwBssIdNum; ucBssIndex++) { + + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + + if (DBDC_IS_BSS_NOT_ALIVE(prBssInfo)) + continue; + + if (prBssInfo->eBand != BAND_2G4 + && prBssInfo->eBand != BAND_5G) + continue; + + eBssBand[ucBssIndex] = prBssInfo->eBand; + + if (eBandCompare != BAND_2G4 && eBandCompare != BAND_5G) + eBandCompare = prBssInfo->eBand; + + if (eBandCompare != prBssInfo->eBand) + fgAGConcurrent = TRUE; /*A+G*/ + } + + log_dbg(CNM, INFO, "[DBDC] BSS AG[%u.%u.%u.%u][%u]\n", + eBssBand[BSSID_0], + eBssBand[BSSID_1], + eBssBand[BSSID_2], + eBssBand[BSSID_3], + eRfBand_Connecting); + + return fgAGConcurrent; /*NOT A+G*/ +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief MT6632 HW capability will change between BW160+NSS2 and BW80+NSS1 + * + * @param (none) + * + * @return TRUE: WAIT/WAIT FAIL/Done Success/Done Fail + */ +/*----------------------------------------------------------------------------*/ +static enum ENUM_DBDC_PROTOCOL_STATUS_T cnmDbdcOpmodeChangeAndWait( + IN struct ADAPTER *prAdapter, + IN u_int8_t fgDbdcEn) +{ + uint8_t ucBssIndex; + uint8_t ucWmmSetBitmap = 0; + uint8_t ucOpBw; + uint8_t ucNss; + struct BSS_INFO *prBssInfo; + enum ENUM_OP_CHANGE_STATUS_T eBssOpmodeChange; + enum ENUM_DBDC_PROTOCOL_STATUS_T eRetVar = + ENUM_DBDC_PROTOCOL_STATUS_DONE_SUCCESS; + +#define IS_BSS_CLIENT(_prBssInfo) \ +(_prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) + + if (fgDbdcEn) + ucWmmSetBitmap |= BIT(DBDC_2G_WMM_INDEX); + + for (ucBssIndex = 0; + ucBssIndex <= prAdapter->ucHwBssIdNum; ucBssIndex++) { + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + if (DBDC_IS_BSS_ALIVE(prBssInfo)) { + + ucOpBw = rlmGetBssOpBwByVhtAndHtOpInfo(prBssInfo); + if (fgDbdcEn && ucOpBw > MAX_BW_80MHZ) + ucOpBw = MAX_BW_80MHZ; + + ucNss = fgDbdcEn ? 1 : wlanGetSupportNss(prAdapter, + ucBssIndex); + + eBssOpmodeChange = rlmChangeOperationMode(prAdapter, + ucBssIndex, + ucOpBw, + ucNss, + IS_BSS_CLIENT(prBssInfo) ? + cnmDbdcOpModeChangeDoneCallback : + NULL); + + log_dbg(CNM, INFO, "[DBDC] BSS index[%u] to BW %u NSS %u Mode:%s, status %u\n", + ucBssIndex, + ucOpBw, + ucNss, + IS_BSS_CLIENT(prBssInfo) ? "Client" : "Master", + eBssOpmodeChange); + + switch (eBssOpmodeChange) { + case OP_CHANGE_STATUS_VALID_CHANGE_CALLBACK_WAIT: + g_rDbdcInfo.fgDbdcDisableOpmodeChangeDone + = FALSE; + g_rDbdcInfo.eBssOpModeState[ucBssIndex] + = ENUM_OPMODE_STATE_WAIT; + eRetVar = ENUM_DBDC_PROTOCOL_STATUS_WAIT; + + break; + + case OP_CHANGE_STATUS_VALID_CHANGE_CALLBACK_DONE: + case OP_CHANGE_STATUS_VALID_NO_CHANGE: + g_rDbdcInfo.eBssOpModeState[ucBssIndex] + = ENUM_OPMODE_STATE_DONE; + break; + + case OP_CHANGE_STATUS_INVALID: + g_rDbdcInfo.eBssOpModeState[ucBssIndex] + = ENUM_OPMODE_STATE_FAIL; + +#define __SUCCESS__ ENUM_DBDC_PROTOCOL_STATUS_DONE_SUCCESS +#define __FAIL__ ENUM_DBDC_PROTOCOL_STATUS_DONE_FAIL + if (eRetVar == __SUCCESS__) + eRetVar = __FAIL__; +#undef __SUCCESS__ +#undef __FAIL__ + + break; + + default: + ASSERT(0); + break; + } + } else { + g_rDbdcInfo.eBssOpModeState[ucBssIndex] + = ENUM_OPMODE_STATE_DONE; + } + } + + return eRetVar; +} + + +void cnmDbdcOpModeChangeDoneCallback( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN u_int8_t fgSuccess) +{ + uint8_t ucBssLoopIndex; + u_int8_t fgIsAllActionFrameSuccess = TRUE; + + if (fgSuccess) + g_rDbdcInfo.eBssOpModeState[ucBssIndex] = + ENUM_OPMODE_STATE_DONE; + else + g_rDbdcInfo.eBssOpModeState[ucBssIndex] = + ENUM_OPMODE_STATE_FAIL; + + log_dbg(CNM, INFO, "[DBDC] OPMODE STATE [%u/%u/%u/%u]\n", + g_rDbdcInfo.eBssOpModeState[BSSID_0], + g_rDbdcInfo.eBssOpModeState[BSSID_1], + g_rDbdcInfo.eBssOpModeState[BSSID_2], + g_rDbdcInfo.eBssOpModeState[BSSID_3]); + + for (ucBssLoopIndex = 0; + ucBssLoopIndex <= prAdapter->ucHwBssIdNum; + ucBssLoopIndex++) { + + if (g_rDbdcInfo.eBssOpModeState[ucBssIndex] == + ENUM_OPMODE_STATE_WAIT) + return; + + if (g_rDbdcInfo.eBssOpModeState[ucBssIndex] == + ENUM_OPMODE_STATE_FAIL && + fgIsAllActionFrameSuccess == TRUE) { + /* Some OP mode change FAIL */ + fgIsAllActionFrameSuccess = FALSE; + } + } + + if (!g_rDbdcInfo.fgDbdcDisableOpmodeChangeDone) { + if (fgIsAllActionFrameSuccess) { + DBDC_FSM_EVENT_HANDLER(prAdapter, + DBDC_FSM_EVENT_ACTION_FRAME_ALL_SUCCESS); + } else { + DBDC_FSM_EVENT_HANDLER(prAdapter, + DBDC_FSM_EVENT_ACTION_FRAME_SOME_FAIL); + } + + g_rDbdcInfo.fgDbdcDisableOpmodeChangeDone = TRUE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Send DBDC Enable/Disable command to FW + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void cnmUpdateDbdcSetting(IN struct ADAPTER *prAdapter, + IN u_int8_t fgDbdcEn) +{ + struct CMD_DBDC_SETTING rDbdcSetting; + struct CMD_DBDC_SETTING *prCmdBody; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + log_dbg(CNM, INFO, "[DBDC] %s\n", + fgDbdcEn ? "Enable" : "Disable"); + + /* Send event to FW */ + prCmdBody = (struct CMD_DBDC_SETTING *)&rDbdcSetting; + + kalMemZero(prCmdBody, sizeof(struct CMD_DBDC_SETTING)); + + prCmdBody->ucDbdcEn = fgDbdcEn; + + /* Parameter decision */ +#if (CFG_HW_WMM_BY_BSS == 1) + if (fgDbdcEn) { + u_int8_t ucWmmSetBitmapPerBSS; + struct BSS_INFO *prBssInfo; + u_int8_t ucBssIndex; + /* + * As DBDC enabled, for BSS use 2.4g Band, assign related + * WmmGroupSet bitmask to 1. + * This is used to indicate the WmmGroupSet is associated + * to Band#1 (otherwise, use for band#0) + */ + for (ucBssIndex = 0; ucBssIndex < prAdapter->ucHwBssIdNum; + ucBssIndex++) { + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + + if (!prBssInfo || prBssInfo->fgIsInUse == FALSE) + continue; + + if (prBssInfo->eBand == BAND_2G4) { + ucWmmSetBitmapPerBSS = prBssInfo->ucWmmQueSet; + prCmdBody->ucWmmBandBitmap |= + BIT(ucWmmSetBitmapPerBSS); + } + } + /* For P2P Device, we force it to use WMM3 */ + prBssInfo = prAdapter->aprBssInfo[P2P_DEV_BSS_INDEX]; + if (prBssInfo->eBand == BAND_2G4) + prCmdBody->ucWmmBandBitmap |= BIT(MAX_HW_WMM_INDEX); + } +#else + if (fgDbdcEn) + prCmdBody->ucWmmBandBitmap |= BIT(DBDC_2G_WMM_INDEX); +#endif + + /* FW uses ucWmmBandBitmap from driver if it does not support ver 1*/ + prCmdBody->ucCmdVer = 0x1; + prCmdBody->u2CmdLen = sizeof(struct CMD_DBDC_SETTING); + DBDC_UPDATE_CMD_WMMBAND_FW_AUTO(prCmdBody); + + if (g_rDbdcInfo.fgHasSentCmd == TRUE) + log_dbg(CNM, WARN, "Not event came back for DBDC\n"); + + g_rDbdcInfo.fgHasSentCmd = TRUE; + g_rDbdcInfo.fgCmdEn = fgDbdcEn; + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_DBDC_PARMS, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + + /* u4SetQueryInfoLen */ + sizeof(struct CMD_DBDC_SETTING), + + /* pucInfoBuffer */ + (uint8_t *)prCmdBody, + + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief DBDC FSM Entry + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static void +cnmDbdcFsmSteps( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_STATE_T eNextState, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent) +{ + /* Do entering Next State and do its initial function. */ + g_rDbdcInfo.eDbdcFsmPrevState = g_rDbdcInfo.eDbdcFsmCurrState; + g_rDbdcInfo.eDbdcFsmCurrState = eNextState; + g_rDbdcInfo.eDbdcFsmNextState = eNextState; + + log_dbg(CNM, INFO, "[DBDC] event %d state %d->%d\n", + eEvent, + g_rDbdcInfo.eDbdcFsmPrevState, + g_rDbdcInfo.eDbdcFsmCurrState); + + if (g_rDbdcInfo.eDbdcFsmPrevState != g_rDbdcInfo.eDbdcFsmCurrState) { + /* state change, call exit function of previous state */ + if (arDdbcFsmActionTable[g_rDbdcInfo.eDbdcFsmPrevState] + .pfExitFunc) { + arDdbcFsmActionTable[g_rDbdcInfo.eDbdcFsmPrevState] + .pfExitFunc(prAdapter); + } + + /* state change, call entry function of current state */ + if (arDdbcFsmActionTable[g_rDbdcInfo.eDbdcFsmCurrState] + .pfEntryFunc) { + arDdbcFsmActionTable[g_rDbdcInfo.eDbdcFsmCurrState] + .pfEntryFunc(prAdapter); + } + } +} + +static u_int8_t +cnmDBDCIsReqPeivilegeLock(void) +{ + return g_rDbdcInfo.fgReqPrivelegeLock; +} + +static void +cnmDBDCFsmActionReqPeivilegeLock(void) +{ + g_rDbdcInfo.fgReqPrivelegeLock = TRUE; + log_dbg(CNM, INFO, "[DBDC] ReqPrivelege Lock!!\n"); +} + +static void +cnmDBDCFsmActionReqPeivilegeUnLock(IN struct ADAPTER *prAdapter) +{ + struct MSG_CH_REQ *prPendingMsg; + struct MSG_HDR *prMsgHdr; + + g_rDbdcInfo.fgReqPrivelegeLock = FALSE; + log_dbg(CNM, INFO, "[DBDC] ReqPrivelege Unlock!!\n"); + + while (!LINK_IS_EMPTY(&g_rDbdcInfo.rPendingMsgList)) { + + LINK_REMOVE_HEAD(&g_rDbdcInfo.rPendingMsgList, prMsgHdr, + struct MSG_HDR *); + + if (prMsgHdr) { + prPendingMsg = (struct MSG_CH_REQ *)prMsgHdr; + + log_dbg(CNM, INFO, "[DBDC] ChReq: send queued REQ of BSS %u Token %u\n", + prPendingMsg->ucBssIndex, + prPendingMsg->ucTokenID); + + cnmChMngrRequestPrivilege(prAdapter, + &prPendingMsg->rMsgHdr); + } else { + ASSERT(0); + } + } +} + +static void +cnmDbdcFsmEntryFunc_DISABLE_IDLE(IN struct ADAPTER *prAdapter) +{ + cnmDBDCFsmActionReqPeivilegeUnLock(prAdapter); +} + +static void +cnmDbdcFsmEntryFunc_WAIT_PROTOCOL_ENABLE(IN struct ADAPTER *prAdapter) +{ + cnmDBDCFsmActionReqPeivilegeLock(); +} + +static void +cnmDbdcFsmEntryFunc_WAIT_HW_ENABLE(IN struct ADAPTER *prAdapter) +{ + if (!cnmDBDCIsReqPeivilegeLock()) + cnmDBDCFsmActionReqPeivilegeLock(); + + cnmUpdateDbdcSetting(prAdapter, TRUE); +} + +static void +cnmDbdcFsmEntryFunc_ENABLE_GUARD(IN struct ADAPTER *prAdapter) +{ + if (timerPendingTimer(&g_rDbdcInfo.rDbdcGuardTimer)) { + log_dbg(CNM, WARN, + "[DBDC] Guard Timer type %u should not exist, stop it\n", + g_rDbdcInfo.eDdbcGuardTimerType); + cnmTimerStopTimer(prAdapter, + &g_rDbdcInfo.rDbdcGuardTimer); + g_rDbdcInfo.eDdbcGuardTimerType = + ENUM_DBDC_GUARD_TIMER_NONE; + } + DBDC_SET_GUARD_TIME(prAdapter); +} + +static void +cnmDbdcFsmEntryFunc_WAIT_HW_DISABLE(IN struct ADAPTER *prAdapter) +{ + cnmUpdateDbdcSetting(prAdapter, FALSE); +} + +static void +cnmDbdcFsmEntryFunc_DISABLE_GUARD(IN struct ADAPTER *prAdapter) +{ + if (timerPendingTimer(&g_rDbdcInfo.rDbdcGuardTimer)) { + log_dbg(CNM, WARN, + "[DBDC] Guard Timer type %u should not exist, stop it\n", + g_rDbdcInfo.eDdbcGuardTimerType); + cnmTimerStopTimer(prAdapter, + &g_rDbdcInfo.rDbdcGuardTimer); + g_rDbdcInfo.eDdbcGuardTimerType = + ENUM_DBDC_GUARD_TIMER_NONE; + } + DBDC_SET_GUARD_TIME(prAdapter); + + cnmDbdcOpmodeChangeAndWait(prAdapter, FALSE); +} + +static void +cnmDbdcFsmEventHandler_DISABLE_IDLE( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent) +{ + switch (eEvent) { + case DBDC_FSM_EVENT_BSS_DISCONNECT_LEAVE_AG: + /* Do Nothing */ + break; + + case DBDC_FSM_EVENT_BSS_CONNECTING_ENTER_AG: + /* Enable DBDC */ + switch (cnmDbdcOpmodeChangeAndWait(prAdapter, TRUE)) { + case ENUM_DBDC_PROTOCOL_STATUS_WAIT: + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_WAIT_PROTOCOL_ENABLE; + break; + + case ENUM_DBDC_PROTOCOL_STATUS_DONE_SUCCESS: + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_WAIT_HW_ENABLE; + break; + + case ENUM_DBDC_PROTOCOL_STATUS_DONE_FAIL: + /* Should NOT FAIL, not recover anything now. + * Stop enable DBDC + */ + break; + default: + break; + } + break; + + case DBDC_FSM_EVENT_SWITCH_GUARD_TIME_TO: + case DBDC_FSM_EVENT_DISABLE_COUNT_DOWN_TO: + case DBDC_FSM_EVENT_ACTION_FRAME_ALL_SUCCESS: + case DBDC_FSM_EVENT_ACTION_FRAME_SOME_FAIL: + case DBDC_FSM_EVENT_DBDC_HW_SWITCH_DONE: + /* ABNORMAL CASE*/ + DBDC_FSM_MSG_WRONG_EVT(eEvent); + break; + default: + /* WRONG EVENT */ + DBDC_FSM_MSG_ERROR_EVT(eEvent); + break; + } + + cnmDbdcFsmSteps(prAdapter, g_rDbdcInfo.eDbdcFsmNextState, eEvent); +} + +static void +cnmDbdcFsmEventHandler_WAIT_PROTOCOL_ENABLE( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent) +{ + switch (eEvent) { + case DBDC_FSM_EVENT_BSS_DISCONNECT_LEAVE_AG: + case DBDC_FSM_EVENT_BSS_CONNECTING_ENTER_AG: + /* IGNORE */ + break; + + case DBDC_FSM_EVENT_SWITCH_GUARD_TIME_TO: + case DBDC_FSM_EVENT_DISABLE_COUNT_DOWN_TO: + /* ABNORMAL CASE*/ + DBDC_FSM_MSG_WRONG_EVT(eEvent); + break; + + case DBDC_FSM_EVENT_ACTION_FRAME_ALL_SUCCESS: + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_WAIT_HW_ENABLE; + break; + + case DBDC_FSM_EVENT_ACTION_FRAME_SOME_FAIL: + /* Not recover anything. Stop Enable DBDC */ + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_DISABLE_IDLE; + break; + + case DBDC_FSM_EVENT_DBDC_HW_SWITCH_DONE: + /* ABNORMAL CASE*/ + DBDC_FSM_MSG_WRONG_EVT(eEvent); + break; + + default: + /* WRONG EVENT */ + DBDC_FSM_MSG_ERROR_EVT(eEvent); + break; + } + + cnmDbdcFsmSteps(prAdapter, g_rDbdcInfo.eDbdcFsmNextState, eEvent); +} + +static void +cnmDbdcFsmEventHandler_WAIT_HW_ENABLE( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent) +{ + /* Prepare to Enable DBDC */ + + switch (eEvent) { + case DBDC_FSM_EVENT_BSS_DISCONNECT_LEAVE_AG: + case DBDC_FSM_EVENT_BSS_CONNECTING_ENTER_AG: + /* IGNORE */ + break; + + case DBDC_FSM_EVENT_SWITCH_GUARD_TIME_TO: + case DBDC_FSM_EVENT_DISABLE_COUNT_DOWN_TO: + case DBDC_FSM_EVENT_ACTION_FRAME_ALL_SUCCESS: + case DBDC_FSM_EVENT_ACTION_FRAME_SOME_FAIL: + /* ABNORMAL CASE*/ + DBDC_FSM_MSG_WRONG_EVT(eEvent); + break; + + case DBDC_FSM_EVENT_DBDC_HW_SWITCH_DONE: + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_ENABLE_GUARD; + break; + + default: + /* WRONG EVENT */ + DBDC_FSM_MSG_ERROR_EVT(eEvent); + break; + } + + cnmDbdcFsmSteps(prAdapter, g_rDbdcInfo.eDbdcFsmNextState, eEvent); +} + + +static void +cnmDbdcFsmEventHandler_ENABLE_GUARD( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent) +{ + switch (eEvent) { + case DBDC_FSM_EVENT_BSS_DISCONNECT_LEAVE_AG: + case DBDC_FSM_EVENT_BSS_CONNECTING_ENTER_AG: + /* IGNORE */ + break; + + case DBDC_FSM_EVENT_SWITCH_GUARD_TIME_TO: + if (cnmDbdcIsAGConcurrent(prAdapter, BAND_NULL)) { + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_ENABLE_IDLE; + } else { + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_WAIT_HW_DISABLE; + } + break; + + case DBDC_FSM_EVENT_DISABLE_COUNT_DOWN_TO: + case DBDC_FSM_EVENT_ACTION_FRAME_ALL_SUCCESS: + case DBDC_FSM_EVENT_ACTION_FRAME_SOME_FAIL: + case DBDC_FSM_EVENT_DBDC_HW_SWITCH_DONE: + /* ABNORMAL CASE*/ + DBDC_FSM_MSG_WRONG_EVT(eEvent); + break; + + default: + /* WRONG EVENT */ + DBDC_FSM_MSG_ERROR_EVT(eEvent); + break; + } + + cnmDbdcFsmSteps(prAdapter, g_rDbdcInfo.eDbdcFsmNextState, eEvent); +} + +static void +cnmDbdcFsmEventHandler_ENABLE_IDLE( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent) +{ + switch (eEvent) { + case DBDC_FSM_EVENT_BSS_DISCONNECT_LEAVE_AG: + /* start DBDC disable countdown timer */ + if (timerPendingTimer(&g_rDbdcInfo.rDbdcGuardTimer)) { + log_dbg(CNM, WARN, "[DBDC] Guard Timer type %u should not exist, stop it\n", + g_rDbdcInfo.eDdbcGuardTimerType); + cnmTimerStopTimer(prAdapter, + &g_rDbdcInfo.rDbdcGuardTimer); + g_rDbdcInfo.eDdbcGuardTimerType = + ENUM_DBDC_GUARD_TIMER_NONE; + } + DBDC_SET_DISABLE_COUNTDOWN(prAdapter); + break; + + case DBDC_FSM_EVENT_BSS_CONNECTING_ENTER_AG: + /* cancel DBDC disable countdown if exist */ + if (timerPendingTimer(&g_rDbdcInfo.rDbdcGuardTimer) && + g_rDbdcInfo.eDdbcGuardTimerType == + ENUM_DBDC_GUARD_TIMER_DISABLE_COUNT_DOWN) { + cnmTimerStopTimer(prAdapter, + &g_rDbdcInfo.rDbdcGuardTimer); + } + break; + + case DBDC_FSM_EVENT_SWITCH_GUARD_TIME_TO: + /* ABNORMAL CASE*/ + DBDC_FSM_MSG_WRONG_EVT(eEvent); + break; + + case DBDC_FSM_EVENT_DISABLE_COUNT_DOWN_TO: + if (!cnmDbdcIsAGConcurrent(prAdapter, BAND_NULL)) + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_WAIT_HW_DISABLE; + break; + + case DBDC_FSM_EVENT_ACTION_FRAME_ALL_SUCCESS: + case DBDC_FSM_EVENT_ACTION_FRAME_SOME_FAIL: + case DBDC_FSM_EVENT_DBDC_HW_SWITCH_DONE: + /* ABNORMAL CASE*/ + DBDC_FSM_MSG_WRONG_EVT(eEvent); + break; + + default: + /* WRONG EVENT */ + DBDC_FSM_MSG_ERROR_EVT(eEvent); + break; + } + + cnmDbdcFsmSteps(prAdapter, g_rDbdcInfo.eDbdcFsmNextState, eEvent); +} + +static void +cnmDbdcFsmEventHandler_WAIT_HW_DISABLE( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent) +{ + switch (eEvent) { + case DBDC_FSM_EVENT_BSS_DISCONNECT_LEAVE_AG: + case DBDC_FSM_EVENT_BSS_CONNECTING_ENTER_AG: + /* IGNORE */ + break; + + case DBDC_FSM_EVENT_SWITCH_GUARD_TIME_TO: + case DBDC_FSM_EVENT_DISABLE_COUNT_DOWN_TO: + case DBDC_FSM_EVENT_ACTION_FRAME_ALL_SUCCESS: + case DBDC_FSM_EVENT_ACTION_FRAME_SOME_FAIL: + /* ABNORMAL CASE*/ + DBDC_FSM_MSG_WRONG_EVT(eEvent); + break; + + case DBDC_FSM_EVENT_DBDC_HW_SWITCH_DONE: + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_DISABLE_GUARD; + break; + + default: + /* WRONG EVENT */ + DBDC_FSM_MSG_ERROR_EVT(eEvent); + break; + } + + cnmDbdcFsmSteps(prAdapter, g_rDbdcInfo.eDbdcFsmNextState, eEvent); +} + +static void +cnmDbdcFsmEventHandler_DISABLE_GUARD( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent) +{ + switch (eEvent) { + case DBDC_FSM_EVENT_BSS_DISCONNECT_LEAVE_AG: + case DBDC_FSM_EVENT_BSS_CONNECTING_ENTER_AG: + /* IGNORE */ + break; + + case DBDC_FSM_EVENT_SWITCH_GUARD_TIME_TO: + +#define __PRO_ENABLE__ ENUM_DBDC_FSM_STATE_WAIT_PROTOCOL_ENABLE +#define __PRO_DISABLE__ ENUM_DBDC_FSM_STATE_WAIT_PROTOCOL_DISABLE +#define __HW_ENABLE__ ENUM_DBDC_FSM_STATE_WAIT_HW_ENABLE +#define __DISABLE__ ENUM_DBDC_FSM_STATE_DISABLE_IDLE +#define __STAT_WAIT__ ENUM_DBDC_PROTOCOL_STATUS_WAIT + + if (g_rDbdcInfo.fgDbdcDisableOpmodeChangeDone) { + if (cnmDbdcIsAGConcurrent(prAdapter, BAND_NULL)) { + switch (cnmDbdcOpmodeChangeAndWait( + prAdapter, TRUE)) { + case ENUM_DBDC_PROTOCOL_STATUS_WAIT: + g_rDbdcInfo.eDbdcFsmNextState = + __PRO_ENABLE__; + break; + case ENUM_DBDC_PROTOCOL_STATUS_DONE_SUCCESS: + g_rDbdcInfo.eDbdcFsmNextState = + __HW_ENABLE__; + break; + case ENUM_DBDC_PROTOCOL_STATUS_DONE_FAIL: + if (cnmDbdcOpmodeChangeAndWait( + prAdapter, FALSE) + == __STAT_WAIT__) + g_rDbdcInfo.eDbdcFsmNextState = + __PRO_DISABLE__; + else + g_rDbdcInfo.eDbdcFsmNextState = + __DISABLE__; + break; + default: + break; + } + } else { + g_rDbdcInfo.eDbdcFsmNextState = + __DISABLE__; + } + } else { + g_rDbdcInfo.eDbdcFsmNextState = + __PRO_DISABLE__; + } + +#undef __PRO_ENABLE__ +#undef __PRO_DISABLE__ +#undef __HW_ENABLE__ +#undef __DISABLE__ +#undef __STAT_WAIT__ + + break; + + case DBDC_FSM_EVENT_DISABLE_COUNT_DOWN_TO: + /* ABNORMAL CASE */ + DBDC_FSM_MSG_WRONG_EVT(eEvent); + break; + + case DBDC_FSM_EVENT_ACTION_FRAME_ALL_SUCCESS: + case DBDC_FSM_EVENT_ACTION_FRAME_SOME_FAIL: + /* Do nothing */ + break; + + case DBDC_FSM_EVENT_DBDC_HW_SWITCH_DONE: + /* ABNORMAL CASE */ + DBDC_FSM_MSG_WRONG_EVT(eEvent); + break; + + default: + /* WRONG EVENT */ + DBDC_FSM_MSG_ERROR_EVT(eEvent); + break; + } + + cnmDbdcFsmSteps(prAdapter, g_rDbdcInfo.eDbdcFsmNextState, eEvent); +} + +static void +cnmDbdcFsmEventHandler_WAIT_PROTOCOL_DISABLE( + IN struct ADAPTER *prAdapter, + IN enum ENUM_DBDC_FSM_EVENT_T eEvent) +{ + /* Prepare to Enable DBDC */ + + switch (eEvent) { + case DBDC_FSM_EVENT_BSS_DISCONNECT_LEAVE_AG: + case DBDC_FSM_EVENT_BSS_CONNECTING_ENTER_AG: + /* IGNORE */ + break; + + case DBDC_FSM_EVENT_SWITCH_GUARD_TIME_TO: + case DBDC_FSM_EVENT_DISABLE_COUNT_DOWN_TO: + /* ABNORMAL CASE*/ + DBDC_FSM_MSG_WRONG_EVT(eEvent); + break; + + case DBDC_FSM_EVENT_ACTION_FRAME_ALL_SUCCESS: + case DBDC_FSM_EVENT_ACTION_FRAME_SOME_FAIL: + g_rDbdcInfo.eDbdcFsmNextState = + ENUM_DBDC_FSM_STATE_DISABLE_IDLE; + break; + + case DBDC_FSM_EVENT_DBDC_HW_SWITCH_DONE: + /* ABNORMAL CASE*/ + DBDC_FSM_MSG_WRONG_EVT(eEvent); + break; + + default: + /* WRONG EVENT */ + DBDC_FSM_MSG_ERROR_EVT(eEvent); + break; + } + + cnmDbdcFsmSteps(prAdapter, g_rDbdcInfo.eDbdcFsmNextState, eEvent); +} + +static void +cnmDbdcFsmExitFunc_WAIT_HW_ENABLE( + IN struct ADAPTER *prAdapter) +{ + cnmDBDCFsmActionReqPeivilegeUnLock(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Get the connection capability. + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void cnmGetDbdcCapability( + IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN enum ENUM_BAND eRfBand, + IN uint8_t ucPrimaryChannel, + IN uint8_t ucNss, + OUT struct CNM_DBDC_CAP *prDbdcCap) +{ + if (!prDbdcCap) + return; + + /* BSS index */ + prDbdcCap->ucBssIndex = ucBssIndex; + +#if (CFG_HW_WMM_BY_BSS == 0) + /* WMM set */ + if (eRfBand == BAND_5G) + prDbdcCap->ucWmmSetIndex = DBDC_5G_WMM_INDEX; + else + prDbdcCap->ucWmmSetIndex = + (prAdapter->rWifiVar.eDbdcMode == + ENUM_DBDC_MODE_DISABLED) ? + DBDC_5G_WMM_INDEX : DBDC_2G_WMM_INDEX; +#endif + /* Nss & band 0/1 */ + switch (prAdapter->rWifiVar.eDbdcMode) { + case ENUM_DBDC_MODE_DISABLED: + /* DBDC is disabled, all BSS run on band 0 */ + if (wlanGetSupportNss(prAdapter, ucBssIndex) < ucNss) + prDbdcCap->ucNss = wlanGetSupportNss(prAdapter, + ucBssIndex); + else + prDbdcCap->ucNss = ucNss; + break; + + case ENUM_DBDC_MODE_STATIC: + /* Static DBDC mode, 1SS only */ + prDbdcCap->ucNss = 1; + break; + + case ENUM_DBDC_MODE_DYNAMIC: + if (USE_DBDC_CAPABILITY()) { + prDbdcCap->ucNss = 1; + } else { + prDbdcCap->ucNss = wlanGetSupportNss(prAdapter, + ucBssIndex); + } + break; + + default: + break; + } + + log_dbg(CNM, INFO, + "[DBDC] BSS%u RF%u CH%u Nss%u get Wmm%u Nss%u\n", + ucBssIndex, + eRfBand, + ucPrimaryChannel, + ucNss, +#if (CFG_HW_WMM_BY_BSS == 0) + prDbdcCap->ucWmmSetIndex, +#else + /*Wmm Selection varies from Bss instead of RfBand. */ + 0xFF, +#endif + prDbdcCap->ucNss + ); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Get maximum bandwidth capability with considering DBDC mode + * + * @param (none) + * + * @return + */ +/*----------------------------------------------------------------------------*/ +uint8_t cnmGetDbdcBwCapability(IN struct ADAPTER + *prAdapter, + IN uint8_t ucBssIndex) +{ + uint8_t ucMaxBw = MAX_BW_20MHZ; + + ucMaxBw = cnmGetBssMaxBw(prAdapter, ucBssIndex); + + /* Can't use BW160 when DBDC enabled */ + if (USE_DBDC_CAPABILITY() && (ucMaxBw >= MAX_BW_160MHZ)) + ucMaxBw = MAX_BW_80MHZ; + + /* TODO: BW80+80 support */ + if (ucMaxBw == MAX_BW_80_80_MHZ) + ucMaxBw = MAX_BW_80MHZ; /* VHT should default support BW80 */ + + return ucMaxBw; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Run-time check if DBDC Need enable or update guard time. + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void cnmDbdcEnableDecision( + IN struct ADAPTER *prAdapter, + IN uint8_t ucChangedBssIndex, + IN enum ENUM_BAND eRfBand, + IN uint8_t ucPrimaryChannel, + IN uint8_t ucWmmQueIdx) +{ + log_dbg(CNM, INFO, "[DBDC] BSS %u Rf %u", ucChangedBssIndex, eRfBand); + + if (prAdapter->rWifiVar.eDbdcMode != ENUM_DBDC_MODE_DYNAMIC && + (prAdapter->rWifiVar.eDbdcMode != ENUM_DBDC_MODE_STATIC)) { + log_dbg(CNM, INFO, "[DBDC Debug] DBDC Mode %u Return", + prAdapter->rWifiVar.eDbdcMode); + return; + } + + if (prAdapter->rWifiVar.fgDbDcModeEn) { + if (timerPendingTimer(&g_rDbdcInfo.rDbdcGuardTimer) && + g_rDbdcInfo.eDdbcGuardTimerType == + ENUM_DBDC_GUARD_TIMER_SWITCH_GUARD_TIME) { + /* update timer for connection retry */ + log_dbg(CNM, INFO, "[DBDC] DBDC guard time extend\n"); + cnmTimerStopTimer(prAdapter, + &g_rDbdcInfo.rDbdcGuardTimer); + cnmTimerStartTimer(prAdapter, + &g_rDbdcInfo.rDbdcGuardTimer, + DBDC_SWITCH_GUARD_TIME); + } + /* The DBDC is already ON, so renew WMM band information only */ + DBDC_SET_WMMBAND_FW_AUTO_BY_CHNL(ucPrimaryChannel, ucWmmQueIdx); + cnmUpdateDbdcSetting(prAdapter, TRUE); + return; + } + + if (timerPendingTimer(&g_rDbdcInfo.rDbdcGuardTimer) && + g_rDbdcInfo.eDdbcGuardTimerType + == ENUM_DBDC_GUARD_TIMER_SWITCH_GUARD_TIME) { + log_dbg(CNM, INFO, "[DBDC Debug] Guard Time Return"); + return; + } + + if (eRfBand != BAND_2G4 && eRfBand != BAND_5G) { + log_dbg(CNM, INFO, "[DBDC Debug] Wrong RF band Return"); + return; + } + + if (cnmDbdcIsAGConcurrent(prAdapter, eRfBand)) { + DBDC_SET_WMMBAND_FW_AUTO_BY_CHNL(ucPrimaryChannel, ucWmmQueIdx); + DBDC_FSM_EVENT_HANDLER(prAdapter, + DBDC_FSM_EVENT_BSS_CONNECTING_ENTER_AG); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Run-time check if DBDC Need disable or update guard time. + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void cnmDbdcDisableDecision(IN struct ADAPTER + *prAdapter, + IN uint8_t ucChangedBssIndex) +{ + log_dbg(CNM, INFO, "[DBDC Debug] BSS %u", + ucChangedBssIndex); + + if (prAdapter->rWifiVar.eDbdcMode != + ENUM_DBDC_MODE_DYNAMIC) { + log_dbg(CNM, INFO, "[DBDC Debug] DBDC Mode %u Return", + prAdapter->rWifiVar.eDbdcMode); + return; + } + + if (!prAdapter->rWifiVar.fgDbDcModeEn) { + if (timerPendingTimer(&g_rDbdcInfo.rDbdcGuardTimer) && + g_rDbdcInfo.eDdbcGuardTimerType == + ENUM_DBDC_GUARD_TIMER_SWITCH_GUARD_TIME) { + /* update timer for connection retry */ + log_dbg(CNM, INFO, "[DBDC] DBDC guard time extend\n"); + cnmTimerStopTimer(prAdapter, + &g_rDbdcInfo.rDbdcGuardTimer); + cnmTimerStartTimer(prAdapter, + &g_rDbdcInfo.rDbdcGuardTimer, + DBDC_SWITCH_GUARD_TIME); + } + return; + } + + if (timerPendingTimer(&g_rDbdcInfo.rDbdcGuardTimer) && + g_rDbdcInfo.eDdbcGuardTimerType == + ENUM_DBDC_GUARD_TIMER_DISABLE_COUNT_DOWN) { + log_dbg(CNM, INFO, + "[DBDC Debug] Disable Countdown Return"); + return; + } + + if (timerPendingTimer(&g_rDbdcInfo.rDbdcGuardTimer) && + g_rDbdcInfo.eDdbcGuardTimerType == + ENUM_DBDC_GUARD_TIMER_SWITCH_GUARD_TIME) { + log_dbg(CNM, INFO, "[DBDC Debug] Guard Time Return"); + return; + } + + if (!cnmDbdcIsAGConcurrent(prAdapter, BAND_NULL)) + DBDC_FSM_EVENT_HANDLER(prAdapter, + DBDC_FSM_EVENT_BSS_DISCONNECT_LEAVE_AG); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief DBDC Guard Time/Countdown Callback + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void cnmDbdcGuardTimerCallback(IN struct ADAPTER + *prAdapter, + IN unsigned long plParamPtr) +{ + log_dbg(CNM, INFO, "[DBDC Debug] Timer %u", + g_rDbdcInfo.eDdbcGuardTimerType); + + if (prAdapter->rWifiVar.eDbdcMode != + ENUM_DBDC_MODE_DYNAMIC) { + log_dbg(CNM, INFO, "[DBDC Debug] DBDC Mode %u Return", + prAdapter->rWifiVar.eDbdcMode); + return; + } + + if (g_rDbdcInfo.eDdbcGuardTimerType == + ENUM_DBDC_GUARD_TIMER_SWITCH_GUARD_TIME) { + + g_rDbdcInfo.eDdbcGuardTimerType = + ENUM_DBDC_GUARD_TIMER_NONE; + DBDC_FSM_EVENT_HANDLER(prAdapter, + DBDC_FSM_EVENT_SWITCH_GUARD_TIME_TO); + + } else if (g_rDbdcInfo.eDdbcGuardTimerType == + ENUM_DBDC_GUARD_TIMER_DISABLE_COUNT_DOWN) { + + g_rDbdcInfo.eDdbcGuardTimerType = + ENUM_DBDC_GUARD_TIMER_NONE; + DBDC_FSM_EVENT_HANDLER(prAdapter, + DBDC_FSM_EVENT_DISABLE_COUNT_DOWN_TO); + + } else + log_dbg(CNM, ERROR, "[DBDC] WRONG DBDC TO TYPE %u\n", + g_rDbdcInfo.eDdbcGuardTimerType); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief DBDC HW Switch done event + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void cnmDbdcEventHwSwitchDone(IN struct ADAPTER + *prAdapter, + IN struct WIFI_EVENT *prEvent) +{ + struct CMD_INFO *prCmdInfo; + uint8_t ucBssIndex; + struct BSS_INFO *prBssInfo; + u_int8_t fgDbdcEn; + + /* 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); + } + + /* Check DBDC state by FSM */ + if (g_rDbdcInfo.eDbdcFsmCurrState == + ENUM_DBDC_FSM_STATE_WAIT_HW_ENABLE) { + fgDbdcEn = TRUE; + } else if (g_rDbdcInfo.eDbdcFsmCurrState == + ENUM_DBDC_FSM_STATE_WAIT_HW_DISABLE) { + fgDbdcEn = FALSE; + } else if (g_rDbdcInfo.fgHasSentCmd == TRUE) { + log_dbg(CNM, INFO, + "[DBDC] switch event from cmd happen in state %u\n", + g_rDbdcInfo.eDbdcFsmCurrState); + g_rDbdcInfo.fgHasSentCmd = FALSE; + prAdapter->rWifiVar.fgDbDcModeEn = g_rDbdcInfo.fgCmdEn; + return; + } else { + log_dbg(CNM, ERROR, + "[DBDC] switch event happen in state %u\n", + g_rDbdcInfo.eDbdcFsmCurrState); + return; + } + + /* Change DBDC state */ + prAdapter->rWifiVar.fgDbDcModeEn = fgDbdcEn; + for (ucBssIndex = 0; + ucBssIndex <= prAdapter->ucHwBssIdNum; + ucBssIndex++) { + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + } + + DBDC_FSM_EVENT_HANDLER(prAdapter, + DBDC_FSM_EVENT_DBDC_HW_SWITCH_DONE); +} + +#endif /*CFG_SUPPORT_DBDC*/ + + +enum ENUM_CNM_NETWORK_TYPE_T cnmGetBssNetworkType( + struct BSS_INFO *prBssInfo) +{ + if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) + return ENUM_CNM_NETWORK_TYPE_AIS; + else if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) { + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) + return ENUM_CNM_NETWORK_TYPE_P2P_GC; + else if (prBssInfo->eCurrentOPMode == + OP_MODE_ACCESS_POINT) + return ENUM_CNM_NETWORK_TYPE_P2P_GO; + } + return ENUM_CNM_NETWORK_TYPE_OTHER; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Search available HW WMM index. +* +* @param (none) +* +* @return +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t cnmWmmIndexDecision( + IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo) +{ +#if (CFG_HW_WMM_BY_BSS == 1) + + u_int8_t ucWmmIndex; + for (ucWmmIndex = 0; ucWmmIndex < HW_WMM_NUM; ucWmmIndex++) { + if (prBssInfo && prBssInfo->fgIsInUse && + prBssInfo->fgIsWmmInited == FALSE) { + if (!(prAdapter->ucHwWmmEnBit & BIT(ucWmmIndex))) { + prAdapter->ucHwWmmEnBit |= BIT(ucWmmIndex); + prBssInfo->fgIsWmmInited = TRUE; + break; + } + } + } + return (ucWmmIndex < HW_WMM_NUM) ? ucWmmIndex : MAX_HW_WMM_INDEX; + +#else + /* Follow the same rule with cnmUpdateDbdcSetting */ + if (prBssInfo->eBand == BAND_5G) + return DBDC_5G_WMM_INDEX; + else + return (prAdapter->rWifiVar.eDbdcMode == + ENUM_DBDC_MODE_DISABLED) ? + DBDC_5G_WMM_INDEX : DBDC_2G_WMM_INDEX; +#endif +} +/*----------------------------------------------------------------------------*/ +/*! +* @brief Free BSS HW WMM index. +* +* @param (none) +* +* @return None +*/ +/*----------------------------------------------------------------------------*/ +void cnmFreeWmmIndex( + IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo) +{ +#if (CFG_HW_WMM_BY_BSS == 1) + prAdapter->ucHwWmmEnBit &= (~BIT(prBssInfo->ucWmmQueSet)); +#endif + prBssInfo->ucWmmQueSet = DEFAULT_HW_WMM_INDEX; + prBssInfo->fgIsWmmInited = FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Release pending timer. +* +* @param (none) +* +* @return None +*/ +/*----------------------------------------------------------------------------*/ +void cnmCheckPendingTimer(IN struct ADAPTER *prAdapter) +{ + struct BSS_INFO *prAisBssInfo; + struct AIS_FSM_INFO *prAisFsmInfo; + + if (prAdapter == NULL) + return; + + /* Timer 1: rJoinTimeoutTimer + * Driver couldn't get any CH_GRANT event of CH_REQ after resume + * Because pending AIS join timer should do CH_ABORT to FW. + * Without CH_ABORT cmd, FW CNM's FSM would keep in GRANT stage. + * FW's CNM couldn't service any other CH_REQ in GRANT stage. + * As a result, checking the timer in suspend flow. + */ + prAisBssInfo = prAdapter->prAisBssInfo; + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + if (timerPendingTimer(&prAisFsmInfo->rJoinTimeoutTimer)) { + DBGLOG(CNM, STATE, "[AIS] pending rJoinTimeoutTimer\n"); + cnmTimerStopTimer(prAdapter, + &prAisFsmInfo->rJoinTimeoutTimer); + /* Release Channel */ + aisFsmReleaseCh(prAdapter); + prAisFsmInfo->fgIsInfraChannelFinished = TRUE; + } +} + +#if CFG_SUPPORT_RX_DYNAMIC_MCC_PRIORITY +/*----------------------------------------------------------------------------*/ +/*! + * @brief Monitor the RX STA/P2P count and adjust the MCC priority. + * + * @param (none) + * + * @return None + */ +/*----------------------------------------------------------------------------*/ +void cnmRxCntMonitor( + IN struct ADAPTER *prAdapter, + IN unsigned long plParamPtr) +{ + struct GLUE_INFO *prGlueInfo = prAdapter->prGlueInfo; + struct BSS_INFO *prBssInfo; + uint64_t u8StaRxDiff = 0, u8P2pRxDiff = 0; + uint8_t ucBssIdx = 0; + uint16_t u2AIS_ch = 0, u2P2P_ch = 0; + uint16_t u2P2pRole = CFG_MCC_P2PGO_QUOTA_TYPE; + + for (ucBssIdx = 0; ucBssIdx < MAX_BSS_INDEX ; ucBssIdx++) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + + if (!prBssInfo) + continue; + if ((IS_BSS_AIS(prBssInfo)) && + prBssInfo->fgIsNetActive && + (prBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED)) { + u2AIS_ch = wlanGetChannelNumberByNetwork(prAdapter, + ucBssIdx); + } + if ((IS_BSS_P2P(prBssInfo)) && + prBssInfo->fgIsNetActive && + (prBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED)) { + u2P2P_ch = wlanGetChannelNumberByNetwork(prAdapter, + ucBssIdx); + + /*GC check*/ + if (!(prBssInfo->eCurrentOPMode == + OP_MODE_ACCESS_POINT)) + u2P2pRole = CFG_MCC_P2PGC_QUOTA_TYPE; + } + } + DBGLOG(CNM, TRACE, + "Original MCC mode: %d STA:%lu P2P:%lu STAch:%d P2Pch:%d\n", + prAdapter->ucModeMCC, prAdapter->ucModeMCC_STA_time, + prAdapter->ucModeMCC_P2P_time, u2AIS_ch, u2P2P_ch); + + u8StaRxDiff = RX_GET_CNT(&prAdapter->rRxCtrl, + RX_DATA_REORDER_WITHIN_COUNT_STA) - prAdapter->u8StaRxCount; + u8P2pRxDiff = RX_GET_CNT(&prAdapter->rRxCtrl, + RX_DATA_REORDER_WITHIN_COUNT_P2P) - prAdapter->u8P2pRxCount; + DBGLOG(CNM, TRACE, "STA: %llu -> %llu, diff:%llu\n", + prAdapter->u8StaRxCount, + RX_GET_CNT(&prAdapter->rRxCtrl, + RX_DATA_REORDER_WITHIN_COUNT_STA), + u8StaRxDiff); + DBGLOG(CNM, TRACE, "P2P: %llu -> %llu, diff:%llu\n", + prAdapter->u8P2pRxCount, + RX_GET_CNT(&prAdapter->rRxCtrl, + RX_DATA_REORDER_WITHIN_COUNT_P2P), + u8P2pRxDiff); + + + if (u2AIS_ch != 0 && u2P2P_ch != 0 && u2AIS_ch != u2P2P_ch && +#if CFG_SUPPORT_DBDC + (!prAdapter->rWifiVar.fgDbDcModeEn) && +#endif + (u8StaRxDiff >= 0 && u8P2pRxDiff >= 0) && + (prAdapter->ucModeMCC == MCC_FAIR)) { + if (u8StaRxDiff < MCC_RX_CNT_LOW_BOUND && + u8P2pRxDiff > MCC_RX_CNT_HIGH_BOUND) { + DBGLOG(CNM, TRACE, + "Current dynamic MCC priority : P2P Favor\n"); + prAdapter->u4SetStaMccTime = MCC_TIME_3; + prAdapter->u4SetP2pMccTime = MCC_TIME_7; + } else if (u8P2pRxDiff < MCC_RX_CNT_LOW_BOUND && + u8StaRxDiff > MCC_RX_CNT_HIGH_BOUND) { + DBGLOG(CNM, TRACE, + "Current dynamic MCC priority : STA favor\n"); + prAdapter->u4SetStaMccTime = MCC_TIME_7; + prAdapter->u4SetP2pMccTime = MCC_TIME_3; + } else if (u8P2pRxDiff > MCC_RX_CNT_LOW_BOUND && + u8StaRxDiff > MCC_RX_CNT_HIGH_BOUND) { + DBGLOG(CNM, TRACE, + "Current dynamic MCC priority : Fair\n"); + prAdapter->u4SetStaMccTime = MCC_TIME_5; + prAdapter->u4SetP2pMccTime = MCC_TIME_5; + } else { + if (prAdapter->fgMccFirstIn == TRUE) { + DBGLOG(CNM, TRACE, + "First time sets dynamic MCC priority.\n"); + DBGLOG(CNM, TRACE, + "Current dynamic MCC priority : Fair\n"); + prAdapter->u4SetStaMccTime = MCC_TIME_5; + prAdapter->u4SetP2pMccTime = MCC_TIME_5; + prAdapter->fgMccFirstIn = FALSE; + } else { + if (prAdapter->ucModeMCC_STA_time == + MCC_TIME_7) + DBGLOG(CNM, TRACE, + "Stay dynamic MCC priority : STA favor\n"); + else if (prAdapter->ucModeMCC_STA_time == + MCC_TIME_3) + DBGLOG(CNM, TRACE, + "Stay dynamic MCC priority : P2P favor\n"); + else + DBGLOG(CNM, TRACE, + "Stay dynamic MCC priority : Fair\n"); + } + } + } + + if ((u2AIS_ch == 0 || u2P2P_ch == 0) && + prAdapter->ucModeMCC == MCC_FAIR) { + if (prAdapter->ucModeMCC_STA_time != + prAdapter->ucModeMCC_P2P_time) { + DBGLOG(CNM, TRACE, + "Leave the dynamic MCC priority mode\n"); + prAdapter->u4SetStaMccTime = MCC_TIME_5; + prAdapter->u4SetP2pMccTime = MCC_TIME_5; + } + } + + if (prAdapter->ucModeMCC == MCC_FAIR) { + /*Set MCC Time*/ + cnmSetMccTime(prAdapter, + CFG_MCC_AIS_QUOTA_TYPE, + prAdapter->u4SetStaMccTime); + cnmSetMccTime(prAdapter, + u2P2pRole, + prAdapter->u4SetP2pMccTime); + } + DBGLOG(CNM, TRACE, + "Current MCC mode: %d STA:%lu P2P:%lu STAch:%d P2Pch:%d\n", + prAdapter->ucModeMCC, + prAdapter->ucModeMCC_STA_time, + prAdapter->ucModeMCC_P2P_time, + u2AIS_ch, u2P2P_ch); + + prAdapter->u8StaRxCount = RX_GET_CNT(&prAdapter->rRxCtrl, + RX_DATA_REORDER_WITHIN_COUNT_STA); + prAdapter->u8P2pRxCount = RX_GET_CNT(&prAdapter->rRxCtrl, + RX_DATA_REORDER_WITHIN_COUNT_P2P); + + cnmTimerStartTimer(prGlueInfo->prAdapter, + &prGlueInfo->prAdapter->rRxCntMonitorTimer, + SEC_TO_MSEC(MCC_CHECK_TIME)); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Set MCC time of STA and P2P. + * + * @param (none) + * + * @return None + */ +/*----------------------------------------------------------------------------*/ +void cnmSetMccTime( + IN struct ADAPTER *prAdapter, + IN uint8_t ucRole, + IN uint32_t u4StayTime) +{ + struct CMD_CHIP_CONFIG rCmdChipConfig; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + char pcCommand[MCC_CMD_MAX_LEN]; + + kalMemZero(&rCmdChipConfig, sizeof(rCmdChipConfig)); + + if (ucRole == CFG_MCC_AIS_QUOTA_TYPE) { + if (prAdapter->ucModeMCC_STA_time == u4StayTime) + return; + prAdapter->ucModeMCC_STA_time = u4StayTime; + } else if (ucRole == CFG_MCC_P2PGC_QUOTA_TYPE) { + if (prAdapter->ucModeMCC_P2P_time == u4StayTime) + return; + prAdapter->ucModeMCC_P2P_time = u4StayTime; + } else if (ucRole == CFG_MCC_P2PGO_QUOTA_TYPE) { + if (prAdapter->ucModeMCC_P2P_time == u4StayTime) + return; + prAdapter->ucModeMCC_P2P_time = u4StayTime; + } + + snprintf(pcCommand, + MCC_CMD_MAX_LEN, + "mccTime %d %d", ucRole, u4StayTime); + rCmdChipConfig.ucType = CHIP_CONFIG_TYPE_WO_RESPONSE; + rCmdChipConfig.u2MsgSize = kalStrnLen(pcCommand, + MCC_CMD_MAX_LEN); + kalMemCopy(rCmdChipConfig.aucCmd, + pcCommand, + rCmdChipConfig.u2MsgSize); + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_CHIP_CONFIG, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_CHIP_CONFIG), + (uint8_t *) &rCmdChipConfig, + NULL, + 0); +} +#endif /*CFG_SUPPORT_RX_DYNAMIC_MCC_PRIORITY*/ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/cnm_mem.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/cnm_mem.c new file mode 100644 index 0000000000000..8aea93e26a4c3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/cnm_mem.c @@ -0,0 +1,1815 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +static uint8_t *apucStaRecType[STA_TYPE_INDEX_NUM] = { + (uint8_t *) "LEGACY", + (uint8_t *) "P2P", + (uint8_t *) "BOW" +}; + +static uint8_t *apucStaRecRole[STA_ROLE_INDEX_NUM] = { + (uint8_t *) "ADHOC", + (uint8_t *) "CLIENT", + (uint8_t *) "AP", + (uint8_t *) "DLS" +}; + +#if CFG_SUPPORT_TDLS +/* The list of valid data rates. */ +const uint8_t aucValidDataRate[] = { + 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_VHT_PHY, /* RATE_VHT_PHY_INDEX */ + RATE_HT_PHY /* RATE_HT_PHY_INDEX */ +}; +#endif + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +static void cnmStaRoutinesForAbort(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec); + +static void cnmStaRecHandleEventPkt(struct ADAPTER *prAdapter, + struct CMD_INFO *prCmdInfo, uint8_t *pucEventBuf); + +static void +cnmStaSendRemoveCmd(struct ADAPTER *prAdapter, + enum ENUM_STA_REC_CMD_ACTION eActionType, uint8_t ucStaRecIndex, + uint8_t ucBssIndex); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +struct MSDU_INFO *cnmPktAllocWrapper(struct ADAPTER *prAdapter, + uint32_t u4Length, uint8_t *pucStr) +{ + struct MSDU_INFO *prMsduInfo; + + prMsduInfo = cnmPktAlloc(prAdapter, u4Length); + log_dbg(MEM, LOUD, "Alloc MSDU_INFO[0x%p] by [%s]\n", + prMsduInfo, pucStr); + + return prMsduInfo; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void cnmPktFreeWrapper(struct ADAPTER *prAdapter, struct MSDU_INFO *prMsduInfo, + uint8_t *pucStr) +{ + log_dbg(MEM, LOUD, "Free MSDU_INFO[0x%p] by [%s]\n", + prMsduInfo, pucStr); + + cnmPktFree(prAdapter, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +struct MSDU_INFO *cnmPktAlloc(struct ADAPTER *prAdapter, uint32_t u4Length) +{ + struct MSDU_INFO *prMsduInfo; + struct QUE *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, struct MSDU_INFO *); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + + if (prMsduInfo) { + if (u4Length) { + 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; + } + } else { + prMsduInfo->prPacket = NULL; + } + } +#if DBG + if (prMsduInfo == NULL) { + log_dbg(MEM, WARN, "\n"); + log_dbg(MEM, WARN, "MgtDesc#=%ld\n", prQueList->u4NumElem); + +#if CFG_DBG_MGT_BUF + log_dbg(MEM, WARN, "rMgtBufInfo: alloc#=%ld, free#=%ld, null#=%ld\n", + prAdapter->rMgtBufInfo.u4AllocCount, + prAdapter->rMgtBufInfo.u4FreeCount, + prAdapter->rMgtBufInfo.u4AllocNullCount); +#endif + + log_dbg(MEM, WARN, "\n"); + } +#endif + + return prMsduInfo; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void cnmPktFree(struct ADAPTER *prAdapter, struct MSDU_INFO *prMsduInfo) +{ + struct QUE *prQueList; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + if (!prMsduInfo) + return; + + 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(struct ADAPTER *prAdapter) +{ + struct BUF_INFO *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 = (uint32_t) 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 = (uint32_t) 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 + */ +/*----------------------------------------------------------------------------*/ +void *cnmMemAlloc(IN struct ADAPTER *prAdapter, IN enum ENUM_RAM_TYPE eRamType, + IN uint32_t u4Length) +{ + struct BUF_INFO *prBufInfo; + uint32_t rRequiredBitmap; + uint32_t u4BlockNum; + uint32_t i, u4BlkSzInPower; + void *pvMemory; + enum ENUM_SPIN_LOCK_CATEGORY_E eLockBufCat; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + if (u4Length == 0) { + log_dbg(MEM, WARN, + "%s: Length to be allocated is ZERO, skip!\n", + __func__); + return NULL; + } + + if (eRamType == RAM_TYPE_MSG && u4Length <= 256) { + prBufInfo = &prAdapter->rMsgBufInfo; + u4BlkSzInPower = MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2; + + u4BlockNum = (u4Length + MSG_BUF_BLOCK_SIZE - 1) + >> 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; + + u4BlockNum = (u4Length + MGT_BUF_BLOCK_SIZE - 1) + >> MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2; + + ASSERT(u4BlockNum <= MAX_NUM_OF_BUF_BLOCKS); + } + + if (eRamType == RAM_TYPE_MSG) + eLockBufCat = SPIN_LOCK_MSG_BUF; + else + eLockBufCat = SPIN_LOCK_MGT_BUF; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, eLockBufCat); + +#if CFG_DBG_MGT_BUF + prBufInfo->u4AllocCount++; +#endif + + 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] + = (uint8_t) u4BlockNum; + + KAL_RELEASE_SPIN_LOCK(prAdapter, eLockBufCat); + + /* Return the start address of + * allocated memory + */ + return (void *) (prBufInfo->pucBuf + + (i << u4BlkSzInPower)); + } + + rRequiredBitmap <<= 1; + } + } + +#if CFG_DBG_MGT_BUF + prBufInfo->u4AllocNullCount++; +#endif + + /* kalMemAlloc() shall not included in spin_lock */ + KAL_RELEASE_SPIN_LOCK(prAdapter, eLockBufCat); + +#ifdef LINUX + pvMemory = (void *) kalMemAlloc(u4Length, PHY_MEM_TYPE); + if (!pvMemory) + DBGLOG(MEM, WARN, "kmalloc fail: %u\n", u4Length); +#else + pvMemory = (void *) NULL; +#endif + +#if CFG_DBG_MGT_BUF + if (pvMemory) + GLUE_INC_REF_CNT(prAdapter->u4MemAllocDynamicCount); +#endif + + 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 struct ADAPTER *prAdapter, IN void *pvMemory) +{ + struct BUF_INFO *prBufInfo; + uint32_t u4BlockIndex; + uint32_t rAllocatedBlocksBitmap; + enum ENUM_RAM_TYPE eRamType; + enum ENUM_SPIN_LOCK_CATEGORY_E eLockBufCat; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + if (!pvMemory) + return; + + /* Judge it belongs to which RAM type */ + if (((unsigned long) pvMemory + >= (unsigned long)&prAdapter->aucMsgBuf[0]) + && ((unsigned long) pvMemory + <= (unsigned long)&prAdapter->aucMsgBuf[MSG_BUFFER_SIZE - 1])) { + + prBufInfo = &prAdapter->rMsgBufInfo; + u4BlockIndex = ((unsigned long) pvMemory + - (unsigned long) prBufInfo->pucBuf) + >> MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2; + ASSERT(u4BlockIndex < MAX_NUM_OF_BUF_BLOCKS); + eRamType = RAM_TYPE_MSG; + } else if (((unsigned long) pvMemory + >= (unsigned long) prAdapter->pucMgtBufCached) + && ((unsigned long) pvMemory + <= ((unsigned long) prAdapter->pucMgtBufCached + + MGT_BUFFER_SIZE - 1))) { + prBufInfo = &prAdapter->rMgtBufInfo; + u4BlockIndex = ((unsigned long) pvMemory + - (unsigned long) 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, PHY_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; + } + + if (eRamType == RAM_TYPE_MSG) + eLockBufCat = SPIN_LOCK_MSG_BUF; + else + eLockBufCat = SPIN_LOCK_MGT_BUF; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, eLockBufCat); + +#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, eLockBufCat); + + return; + +} /* end of cnmMemFree() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void cnmStaRecInit(struct ADAPTER *prAdapter) +{ + struct STA_RECORD *prStaRec; + uint16_t i; + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + + prStaRec->ucIndex = (uint8_t) i; + prStaRec->fgIsInUse = FALSE; +#if DSCP_SUPPORT + prStaRec->qosMapSet = NULL; +#endif + prStaRec->eapol_re_enqueue_cnt = 0; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +struct STA_RECORD *cnmStaRecAlloc(struct ADAPTER *prAdapter, + enum ENUM_STA_TYPE eStaType, uint8_t ucBssIndex, uint8_t *pucMacAddr) +{ + struct STA_RECORD *prStaRec; + uint16_t i, k; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prStaRec = cnmGetAnyStaRecByAddress(prAdapter, pucMacAddr); + + if (prStaRec != NULL) + disconnect_sta(prAdapter, prStaRec); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_STA_REC); + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + + if (!prStaRec->fgIsInUse) { + kalMemZero(prStaRec, sizeof(struct STA_RECORD)); + prStaRec->ucIndex = (uint8_t) i; + prStaRec->ucBssIndex = ucBssIndex; + prStaRec->fgIsInUse = TRUE; + + prStaRec->eStaType = eStaType; + prStaRec->ucBssIndex = ucBssIndex; + + /* Initialize the SN caches for duplicate detection */ + for (k = 0; k < TID_NUM + 1; k++) { + prStaRec->au2CachedSeqCtrl[k] = 0xFFFF; + prStaRec->afgIsIgnoreAmsduDuplicate[k] = FALSE; + } + + /* Initialize SW TX queues in STA_REC */ + for (k = 0; k < STA_WAIT_QUEUE_NUM; k++) + LINK_INITIALIZE(&prStaRec->arStaWaitQueue[k]); + +#if CFG_ENABLE_PER_STA_STATISTICS && CFG_ENABLE_PKT_LIFETIME_PROFILE + prStaRec->u4TotalTxPktsNumber = 0; + prStaRec->u4TotalTxPktsTime = 0; + prStaRec->u4TotalRxPktsNumber = 0; + prStaRec->u4MaxTxPktsTime = 0; +#endif + + for (k = 0; k < NUM_OF_PER_STA_TX_QUEUES; k++) { + QUEUE_INITIALIZE( + &prStaRec->arTxQueue[k]); + QUEUE_INITIALIZE( + &prStaRec->arPendingTxQueue[k]); + prStaRec->aprTargetQueue[k] + = &prStaRec->arTxQueue[k]; + } + + prStaRec->ucAmsduEnBitmap = 0; + prStaRec->ucMaxMpduCount = 0; + prStaRec->u4MaxMpduLen = 0; + prStaRec->u4MinMpduLen = 0; + + break; + } + } + + /* Sync to chip to allocate WTBL resource */ + if (i < CFG_STA_REC_NUM) { + COPY_MAC_ADDR(prStaRec->aucMacAddr, pucMacAddr); + if (secPrivacySeekForEntry(prAdapter, prStaRec)) + cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); +#if DBG + else { + prStaRec->fgIsInUse = FALSE; + prStaRec = NULL; + ASSERT(FALSE); + } +#endif + } else { + prStaRec = NULL; + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_STA_REC); + /* remove pending msdu when sta_rec alloc */ + if (prStaRec) + nicFreePendingTxMsduInfo(prAdapter, + prStaRec->ucWlanIndex, MSDU_REMOVE_BY_WLAN_INDEX); + + return prStaRec; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void cnmStaRecFree(struct ADAPTER *prAdapter, struct STA_RECORD *prStaRec) +{ + uint8_t ucStaRecIndex, ucBssIndex; + + ASSERT(prAdapter); + + if (!prStaRec) + return; + + log_dbg(RSN, INFO, "cnmStaRecFree %d\n", prStaRec->ucIndex); + + ucStaRecIndex = prStaRec->ucIndex; + ucBssIndex = prStaRec->ucBssIndex; + + cnmStaRoutinesForAbort(prAdapter, prStaRec); + + cnmStaSendRemoveCmd(prAdapter, STA_REC_CMD_ACTION_STA, + ucStaRecIndex, ucBssIndex); +#if DSCP_SUPPORT + if (prStaRec->qosMapSet) { + QosMapSetRelease(prStaRec); + prStaRec->qosMapSet = NULL; + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static void cnmStaRoutinesForAbort(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec) +{ +#if CFG_ENABLE_WIFI_DIRECT + struct BSS_INFO *prBssInfo; +#endif + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + if (!prStaRec) + return; + +#if CFG_ENABLE_WIFI_DIRECT + /* Force remove from sta_list before resource unset */ + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) + bssRemoveClient(prAdapter, prBssInfo, prStaRec); +#endif + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_STA_REC); + + /* To do: free related resources, e.g. timers, buffers, etc */ + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + cnmTimerStopTimer(prAdapter, &prStaRec->rDeauthTxDoneTimer); + 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); + + /* Update the driver part table setting */ + secPrivacyFreeSta(prAdapter, prStaRec); + + prStaRec->fgIsInUse = FALSE; + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_STA_REC); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void cnmStaFreeAllStaByNetwork(struct ADAPTER *prAdapter, uint8_t ucBssIndex, + uint8_t ucStaRecIndexExcluded) +{ +#if CFG_ENABLE_WIFI_DIRECT + struct BSS_INFO *prBssInfo; +#endif + struct STA_RECORD *prStaRec; + uint16_t i; + enum ENUM_STA_REC_CMD_ACTION eAction; + + if (ucBssIndex > prAdapter->ucHwBssIdNum) + return; + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = (struct STA_RECORD *) &prAdapter->arStaRec[i]; + + if (prStaRec->fgIsInUse && prStaRec->ucBssIndex == ucBssIndex + && i != ucStaRecIndexExcluded) + cnmStaRoutinesForAbort(prAdapter, prStaRec); + } /* end of for loop */ + + if (ucStaRecIndexExcluded < CFG_STA_REC_NUM) + eAction = STA_REC_CMD_ACTION_BSS_EXCLUDE_STA; + else + eAction = STA_REC_CMD_ACTION_BSS; + + cnmStaSendRemoveCmd(prAdapter, + eAction, + ucStaRecIndexExcluded, ucBssIndex); + +#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 + */ + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + if (prAdapter->fgIsP2PRegistered + && prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + rlmUpdateParamsForAP(prAdapter, prBssInfo, FALSE); + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +struct STA_RECORD *cnmGetStaRecByIndex(struct ADAPTER *prAdapter, + uint8_t ucIndex) +{ + struct STA_RECORD *prStaRec; + + ASSERT(prAdapter); + + if (ucIndex < CFG_STA_REC_NUM) + prStaRec = &prAdapter->arStaRec[ucIndex]; + else + prStaRec = 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 + */ +/*----------------------------------------------------------------------------*/ +struct STA_RECORD *cnmGetStaRecByAddress(struct ADAPTER *prAdapter, + uint8_t ucBssIndex, uint8_t *pucPeerMacAddr) +{ + struct STA_RECORD *prStaRec; + uint16_t i; + + ASSERT(prAdapter); + + if (!pucPeerMacAddr) + return NULL; + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + + if (prStaRec->fgIsInUse + && prStaRec->ucBssIndex == ucBssIndex + && EQUAL_MAC_ADDR( + prStaRec->aucMacAddr, pucPeerMacAddr)) { + break; + } + } + + return (i < CFG_STA_REC_NUM) ? prStaRec : NULL; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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 +*/ +/*----------------------------------------------------------------------------*/ +struct STA_RECORD *cnmGetAnyStaRecByAddress(struct ADAPTER *prAdapter, + uint8_t *pucPeerMacAddr) +{ + struct STA_RECORD *prStaRec; + uint16_t i; + + if (!prAdapter || !pucPeerMacAddr) + return NULL; + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + + if (prStaRec->fgIsInUse && + EQUAL_MAC_ADDR(prStaRec->aucMacAddr, pucPeerMacAddr)) { + break; + } + } + + return (i < CFG_STA_REC_NUM) ? prStaRec : NULL; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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(struct ADAPTER *prAdapter, struct STA_RECORD *prStaRec + , uint8_t ucNewState) +{ + u_int8_t fgNeedResp; + + if (!prAdapter) + return; + + if (!prStaRec) { + log_dbg(MEM, WARN, "%s: StaRec is NULL, skip!\n", __func__); + return; + } + + if (!prStaRec->fgIsInUse) { + log_dbg(MEM, WARN, "%s: StaRec[%u] is not in use, skip!\n", + __func__, prStaRec->ucIndex); + return; + } + + /* 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; + cnmDumpStaRec(prAdapter, prStaRec->ucIndex); + } + } else { + if (ucNewState != prStaRec->ucStaState + && prStaRec->ucStaState == STA_STATE_3) + qmDeactivateStaRec(prAdapter, prStaRec); + fgNeedResp = FALSE; + } + prStaRec->ucStaState = ucNewState; + + cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, fgNeedResp); + +#if 1 /* Marked for MT6630 */ +#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))) { + struct BSS_INFO *prBssInfo; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) + rlmUpdateParamsForAP(prAdapter, prBssInfo, FALSE); + } +#endif +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param[in] + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +static void cnmStaRecHandleEventPkt(struct ADAPTER *prAdapter, + struct CMD_INFO *prCmdInfo, uint8_t *pucEventBuf) +{ + struct EVENT_ACTIVATE_STA_REC *prEventContent; + struct STA_RECORD *prStaRec; + + prEventContent = (struct EVENT_ACTIVATE_STA_REC *) 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) + */ +/*----------------------------------------------------------------------------*/ +void cnmStaSendUpdateCmd(struct ADAPTER *prAdapter, struct STA_RECORD *prStaRec, + struct TXBF_PFMU_STA_INFO *prTxBfPfmuStaInfo, u_int8_t fgNeedResp) +{ + struct CMD_UPDATE_STA_RECORD *prCmdContent; + uint32_t rStatus; + + if (!prAdapter) + return; + + if (!prStaRec) { + log_dbg(MEM, WARN, "%s: StaRec is NULL, skip!\n", __func__); + return; + } + + if (!prStaRec->fgIsInUse) { + log_dbg(MEM, WARN, "%s: StaRec[%u] is not in use, skip!\n", + __func__, prStaRec->ucIndex); + return; + } + + /* 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(struct CMD_UPDATE_STA_RECORD)); + + /* To do: exception handle */ + if (!prCmdContent) { + log_dbg(MEM, WARN, "%s: CMD_ID_UPDATE_STA_RECORD command allocation failed\n", + __func__); + + return; + } + + /* Reset command buffer */ + kalMemZero(prCmdContent, sizeof(struct CMD_UPDATE_STA_RECORD)); + + if (prTxBfPfmuStaInfo) { + memcpy(&prCmdContent->rTxBfPfmuInfo, prTxBfPfmuStaInfo, + sizeof(struct TXBF_PFMU_STA_INFO)); + } + + prCmdContent->ucStaIndex = prStaRec->ucIndex; + prCmdContent->ucStaType = (uint8_t) prStaRec->eStaType; + kalMemCopy(&prCmdContent->aucMacAddr[0], &prStaRec->aucMacAddr[0], + MAC_ADDR_LEN); + prCmdContent->u2AssocId = prStaRec->u2AssocId; + prCmdContent->u2ListenInterval = prStaRec->u2ListenInterval; + prCmdContent->ucBssIndex = prStaRec->ucBssIndex; + + prCmdContent->ucDesiredPhyTypeSet = prStaRec->ucDesiredPhyTypeSet; + prCmdContent->u2DesiredNonHTRateSet = prStaRec->u2DesiredNonHTRateSet; + prCmdContent->u2BSSBasicRateSet = prStaRec->u2BSSBasicRateSet; + prCmdContent->ucMcsSet = prStaRec->ucMcsSet; + prCmdContent->ucSupMcs32 = (uint8_t) prStaRec->fgSupMcs32; + prCmdContent->u2HwDefaultFixedRateCode + = prStaRec->u2HwDefaultFixedRateCode; + + /* Size is SUP_MCS_RX_BITMASK_OCTET_NUM */ + kalMemCopy(prCmdContent->aucRxMcsBitmask, prStaRec->aucRxMcsBitmask, + sizeof(prCmdContent->aucRxMcsBitmask)); + prCmdContent->u2RxHighestSupportedRate + = prStaRec->u2RxHighestSupportedRate; + prCmdContent->u4TxRateInfo = prStaRec->u4TxRateInfo; + + prCmdContent->u2HtCapInfo = prStaRec->u2HtCapInfo; + prCmdContent->ucNeedResp = (uint8_t) 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->u4VhtCapInfo = prStaRec->u4VhtCapInfo; + prCmdContent->u2VhtRxMcsMap = prStaRec->u2VhtRxMcsMap; + prCmdContent->u2VhtRxHighestSupportedDataRate + = prStaRec->u2VhtRxHighestSupportedDataRate; + prCmdContent->u2VhtTxMcsMap = prStaRec->u2VhtTxMcsMap; + prCmdContent->u2VhtTxHighestSupportedDataRate + = prStaRec->u2VhtTxHighestSupportedDataRate; + prCmdContent->ucVhtOpMode = prStaRec->ucVhtOpMode; + + prCmdContent->ucUapsdAc + = prStaRec->ucBmpTriggerAC | (prStaRec->ucBmpDeliveryAC << 4); + prCmdContent->ucUapsdSp = prStaRec->ucUapsdSp; + + prCmdContent->ucWlanIndex = prStaRec->ucWlanIndex; + prCmdContent->ucBMCWlanIndex = WTBL_RESERVED_ENTRY; + + prCmdContent->ucTrafficDataType = prStaRec->ucTrafficDataType; + prCmdContent->ucTxGfMode = prStaRec->ucTxGfMode; + prCmdContent->ucTxSgiMode = prStaRec->ucTxSgiMode; + prCmdContent->ucTxStbcMode = prStaRec->ucTxStbcMode; + prCmdContent->u4FixedPhyRate = prStaRec->u4FixedPhyRate; + prCmdContent->u2MaxLinkSpeed = prStaRec->u2MaxLinkSpeed; + prCmdContent->u2MinLinkSpeed = prStaRec->u2MinLinkSpeed; + prCmdContent->u4Flags = prStaRec->u4Flags; +#if CFG_SUPPORT_MTK_SYNERGY + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucMtkOui)) { + if (IS_FEATURE_ENABLED( + prAdapter->rWifiVar.ucGbandProbe256QAM)) { + prCmdContent->u4Flags + |= MTK_SYNERGY_CAP_SUPPORT_24G_MCS89_PROBING; + } + } +#endif + prCmdContent->ucTxAmpdu = prAdapter->rWifiVar.ucAmpduTx; + prCmdContent->ucRxAmpdu = prAdapter->rWifiVar.ucAmpduRx; + + /* AMSDU in AMPDU global configuration */ + prCmdContent->ucTxAmsduInAmpdu = prAdapter->rWifiVar.ucAmsduInAmpduTx; + prCmdContent->ucRxAmsduInAmpdu = prAdapter->rWifiVar.ucAmsduInAmpduRx; + if ((prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11AC) || + (prStaRec->u4Flags & MTK_SYNERGY_CAP_SUPPORT_24G_MCS89)) { + /* VHT pear AMSDU in AMPDU configuration */ + prCmdContent->ucTxAmsduInAmpdu + &= prAdapter->rWifiVar.ucVhtAmsduInAmpduTx; + prCmdContent->ucRxAmsduInAmpdu + &= prAdapter->rWifiVar.ucVhtAmsduInAmpduRx; + } else if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11N) { + /* HT peer AMSDU in AMPDU configuration */ + prCmdContent->ucTxAmsduInAmpdu + &= prAdapter->rWifiVar.ucHtAmsduInAmpduTx; + prCmdContent->ucRxAmsduInAmpdu + &= prAdapter->rWifiVar.ucHtAmsduInAmpduRx; + } + + prCmdContent->u4TxMaxAmsduInAmpduLen + = prAdapter->rWifiVar.u4TxMaxAmsduInAmpduLen; + + prCmdContent->ucTxBaSize = prAdapter->rWifiVar.ucTxBaSize; + + if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11AC) + prCmdContent->ucRxBaSize = prAdapter->rWifiVar.ucRxVhtBaSize; + else + prCmdContent->ucRxBaSize = prAdapter->rWifiVar.ucRxHtBaSize; + + /* RTS Policy */ + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucSigTaRts)) { + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucDynBwRts)) + prCmdContent->ucRtsPolicy = RTS_POLICY_DYNAMIC_BW; + else + prCmdContent->ucRtsPolicy = RTS_POLICY_STATIC_BW; + } else + prCmdContent->ucRtsPolicy = RTS_POLICY_LEGACY; + + log_dbg(REQ, TRACE, "Update StaRec[%u] WIDX[%u] State[%u] Type[%u] BssIdx[%u] AID[%u]\n", + prCmdContent->ucStaIndex, + prCmdContent->ucWlanIndex, + prCmdContent->ucStaState, + prCmdContent->ucStaType, + prCmdContent->ucBssIndex, + prCmdContent->u2AssocId); + + log_dbg(REQ, TRACE, "Update StaRec[%u] QoS[%u] UAPSD[%u]\n", + prCmdContent->ucStaIndex, + prCmdContent->ucIsQoS, + prCmdContent->ucIsUapsdSupported); + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_UPDATE_STA_RECORD, /* ucCID */ + TRUE, /* fgSetQuery */ + fgNeedResp, /* fgNeedResp */ + FALSE, /* fgIsOid */ + fgNeedResp ? cnmStaRecHandleEventPkt : NULL, NULL, + /* pfCmdTimeoutHandler */ + sizeof(struct CMD_UPDATE_STA_RECORD), /* u4SetQueryInfoLen */ + (uint8_t *) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + cnmMemFree(prAdapter, prCmdContent); + + if (rStatus != WLAN_STATUS_PENDING) { + log_dbg(MEM, WARN, + "%s: CMD_ID_UPDATE_STA_RECORD result 0x%08x\n", + __func__, rStatus); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param[in] + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +static void +cnmStaSendRemoveCmd(struct ADAPTER *prAdapter, + enum ENUM_STA_REC_CMD_ACTION eActionType, + uint8_t ucStaRecIndex, uint8_t ucBssIndex) +{ + struct CMD_REMOVE_STA_RECORD rCmdContent; + uint32_t rStatus; + + ASSERT(prAdapter); + + rCmdContent.ucActionType = (uint8_t) eActionType; + rCmdContent.ucStaIndex = ucStaRecIndex; + rCmdContent.ucBssIndex = ucBssIndex; + rCmdContent.ucReserved = 0; + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_REMOVE_STA_RECORD, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct CMD_REMOVE_STA_RECORD), /* u4SetQueryInfoLen */ + (uint8_t *) &rCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + log_dbg(MEM, WARN, + "%s: CMD_ID_REMOVE_STA_RECORD result 0x%08x\n", + __func__, rStatus); + } +} + +uint8_t *cnmStaRecGetTypeString(enum ENUM_STA_TYPE eStaType) +{ + uint8_t *pucTypeString = NULL; + + if (eStaType & STA_TYPE_LEGACY_MASK) + pucTypeString = apucStaRecType[STA_TYPE_LEGACY_INDEX]; + if (eStaType & STA_TYPE_P2P_MASK) + pucTypeString = apucStaRecType[STA_TYPE_P2P_INDEX]; + if (eStaType & STA_TYPE_BOW_MASK) + pucTypeString = apucStaRecType[STA_TYPE_BOW_INDEX]; + + return pucTypeString; +} + +uint8_t *cnmStaRecGetRoleString(enum ENUM_STA_TYPE eStaType) +{ + uint8_t *pucRoleString = NULL; + + if (eStaType & STA_TYPE_ADHOC_MASK) { + pucRoleString = apucStaRecRole[ + STA_ROLE_ADHOC_INDEX - STA_ROLE_BASE_INDEX]; + } + if (eStaType & STA_TYPE_CLIENT_MASK) { + pucRoleString = apucStaRecRole[ + STA_ROLE_CLIENT_INDEX - STA_ROLE_BASE_INDEX]; + } + if (eStaType & STA_TYPE_AP_MASK) { + pucRoleString = apucStaRecRole[ + STA_ROLE_AP_INDEX - STA_ROLE_BASE_INDEX]; + } + if (eStaType & STA_TYPE_DLS_MASK) { + pucRoleString = apucStaRecRole[ + STA_ROLE_DLS_INDEX - STA_ROLE_BASE_INDEX]; + } + + return pucRoleString; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param[in] + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void cnmDumpStaRec(IN struct ADAPTER *prAdapter, IN uint8_t ucStaRecIdx) +{ + uint8_t ucWTEntry; + uint32_t i; + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + + DEBUGFUNC("cnmDumpStaRec"); + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIdx); + + if (!prStaRec) { + log_dbg(SW4, INFO, "Invalid StaRec index[%u], skip dump!\n", + ucStaRecIdx); + return; + } + + ucWTEntry = prStaRec->ucWlanIndex; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + ASSERT(prBssInfo); + + log_dbg(SW4, INFO, "============= DUMP STA[%u] ===========\n", + ucStaRecIdx); + /* [1]STA_IDX [2]BSS_IDX + * [3]MAC [4]TYPE + * [5]WTBL [6]USED + * [7]State [8]QoS + * [9]HT/VHT [10]AID + * [11]WMM [12]UAPSD + * [13]SEC [14]PhyTypeSet + * [15]Desired [16]NonHtBasic + * [17]BssBasic [18]Operational + * [19]DesiredNonHT [20]Df FixedRate + * [21]HT Cap [22]ExtCap + * [23]BeemCap [24]MCS + * [25]MCS32 [26]VHT Cap + * [27]TxMCS [28]RxMCS + * [29]VhtOpMode [30]RCPI + * [31]InPS [32]TxAllowed + * [33]KeyRdy [34]AMPDU + * [35]TxQLEN TC [36]BMP AC Delivery/Trigger + * [37]FreeQuota:Total [38]Delivery/NonDelivery + * [39]aucRxMcsBitmask + */ + + log_dbg(SW4, INFO, "[1][%u],[2][%u],[3][" MACSTR + "],[4][%s %s],[5][%u],[6][%u],[7][%u],[8][%u],[9][%u/%u],[10][%u]\n", + prStaRec->ucIndex, + prStaRec->ucBssIndex, + MAC2STR(prStaRec->aucMacAddr), + cnmStaRecGetTypeString(prStaRec->eStaType), + cnmStaRecGetRoleString(prStaRec->eStaType), + ucWTEntry, prStaRec->fgIsInUse, + prStaRec->ucStaState, prStaRec->fgIsQoS, + (prStaRec->ucDesiredPhyTypeSet + & PHY_TYPE_SET_802_11N) ? TRUE : FALSE, + (prStaRec->ucDesiredPhyTypeSet + & PHY_TYPE_SET_802_11AC) ? TRUE : FALSE, + prStaRec->u2AssocId); + + log_dbg(SW4, INFO, "[11][%u],[12][%u],[13][%u],[14][0x%x],[15][0x%x],[16][0x%x],[17][0x%x],[18][0x%x],[19][0x%x],[20][0x%x]\n", + prStaRec->fgIsWmmSupported, + prStaRec->fgIsUapsdSupported, + secIsProtectedBss(prAdapter, prBssInfo), + prBssInfo->ucPhyTypeSet, + prStaRec->ucDesiredPhyTypeSet, + prStaRec->ucNonHTBasicPhyType, + prBssInfo->u2BSSBasicRateSet, + prStaRec->u2OperationalRateSet, + prStaRec->u2DesiredNonHTRateSet, + prStaRec->u2HwDefaultFixedRateCode); + + log_dbg(SW4, INFO, "[21][0x%x],[22][0x%x],[23][0x%x],[24][0x%x],[25][%u],[26][0x%x],[27][0x%x],[28][0x%x],[29][0x%x],[30][%u]\n", + prStaRec->u2HtCapInfo, + prStaRec->u2HtExtendedCap, + prStaRec->u4TxBeamformingCap, + prStaRec->ucMcsSet, + prStaRec->fgSupMcs32, + prStaRec->u4VhtCapInfo, + prStaRec->u2VhtTxMcsMap, + prStaRec->u2VhtRxMcsMap, + prStaRec->ucVhtOpMode, + prStaRec->ucRCPI); + + log_dbg(SW4, INFO, "[31][%u],[32][%u],[33][%u],[34][%u/%u],[35][%u:%u:%u:%u],[36][%x/%x],[37][%u],[38][%u/%u],[39][0x%x][0x%x]\n", + prStaRec->fgIsInPS, + prStaRec->fgIsTxAllowed, + prStaRec->fgIsTxKeyReady, + prStaRec->fgTxAmpduEn, + prStaRec->fgRxAmpduEn, + prStaRec->aprTargetQueue[0]->u4NumElem, + prStaRec->aprTargetQueue[1]->u4NumElem, + prStaRec->aprTargetQueue[2]->u4NumElem, + prStaRec->aprTargetQueue[3]->u4NumElem, + prStaRec->ucBmpDeliveryAC, + prStaRec->ucBmpTriggerAC, + prStaRec->ucFreeQuota, + prStaRec->ucFreeQuotaForDelivery, + prStaRec->ucFreeQuotaForNonDelivery, + prStaRec->aucRxMcsBitmask[0], + prStaRec->aucRxMcsBitmask[1]); + + for (i = 0; i < CFG_RX_MAX_BA_TID_NUM; i++) { + if (prStaRec->aprRxReorderParamRefTbl[i]) { + log_dbg(SW4, INFO, "TID[%u],Valid[%u],WinStart/End[%u/%u],WinSize[%u],ReOrderQueLen[%u],Bubble Exist[%u],SN[%u]\n", + prStaRec->aprRxReorderParamRefTbl[i] + ->ucTid, + prStaRec->aprRxReorderParamRefTbl[i] + ->fgIsValid, + prStaRec->aprRxReorderParamRefTbl[i] + ->u2WinStart, + prStaRec->aprRxReorderParamRefTbl[i] + ->u2WinEnd, + prStaRec->aprRxReorderParamRefTbl[i] + ->u2WinSize, + prStaRec->aprRxReorderParamRefTbl[i] + ->rReOrderQue.u4NumElem, + prStaRec->aprRxReorderParamRefTbl[i] + ->fgHasBubble, + prStaRec->aprRxReorderParamRefTbl[i] + ->u2FirstBubbleSn); + } + } + log_dbg(SW4, INFO, "============= DUMP END ===========\n"); +} + +uint32_t cnmDumpMemoryStatus(IN struct ADAPTER *prAdapter, IN uint8_t *pucBuf, + IN uint32_t u4Max) +{ + uint32_t u4Len = 0; +#if CFG_DBG_MGT_BUF + struct BUF_INFO *prBufInfo; + + LOGBUF(pucBuf, u4Max, u4Len, "\n"); + LOGBUF(pucBuf, u4Max, u4Len, + "============= DUMP Memory Status =============\n"); + + LOGBUF(pucBuf, u4Max, u4Len, + "Dynamic alloc OS memory count: alloc[%u] free[%u]\n", + prAdapter->u4MemAllocDynamicCount, + prAdapter->u4MemFreeDynamicCount); + + prBufInfo = &prAdapter->rMsgBufInfo; + + LOGBUF(pucBuf, u4Max, u4Len, + "MSG memory count: alloc[%u] free[%u] null[%u] bitmap[0x%08x]\n" + , + prBufInfo->u4AllocCount, + prBufInfo->u4FreeCount, + prBufInfo->u4AllocNullCount, + (uint32_t) prBufInfo->rFreeBlocksBitmap); + + prBufInfo = &prAdapter->rMgtBufInfo; + + LOGBUF(pucBuf, u4Max, u4Len, + "MGT memory count: alloc[%u] free[%u] null[%u] bitmap[0x%08x]\n" + , + prBufInfo->u4AllocCount, + prBufInfo->u4FreeCount, + prBufInfo->u4AllocNullCount, + (uint32_t) prBufInfo->rFreeBlocksBitmap); + + LOGBUF(pucBuf, u4Max, u4Len, "============= DUMP END =============\n"); + +#endif + + return u4Len; +} + +#if CFG_SUPPORT_TDLS +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to add a peer record. + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t /* TDLS_STATUS, prStaRec->ucNetTypeIndex */ +cnmPeerAdd(struct ADAPTER *prAdapter, void *pvSetBuffer, + uint32_t u4SetBufferLen, uint32_t *pu4SetInfoLen) +{ + struct CMD_PEER_ADD *prCmd; + struct BSS_INFO *prAisBssInfo; + struct STA_RECORD *prStaRec; + + /* sanity check */ + + if ((prAdapter == NULL) || (pvSetBuffer == NULL) + || (pu4SetInfoLen == NULL)) + return TDLS_STATUS_FAIL; + + /* init */ + *pu4SetInfoLen = sizeof(struct CMD_PEER_ADD); + prCmd = (struct CMD_PEER_ADD *) pvSetBuffer; + + prAisBssInfo = prAdapter->prAisBssInfo; /* for AIS only test */ + if (!prAisBssInfo) + return TDLS_STATUS_FAIL; + + prStaRec = cnmGetStaRecByAddress(prAdapter, + (uint8_t) prAdapter->prAisBssInfo->ucBssIndex, + prCmd->aucPeerMac); + + if (prStaRec == NULL) { + prStaRec = + cnmStaRecAlloc(prAdapter, STA_TYPE_DLS_PEER, + (uint8_t) prAdapter->prAisBssInfo->ucBssIndex, + prCmd->aucPeerMac); + + if (prStaRec == NULL) + return TDLS_STATUS_RESOURCES; + + if (prAisBssInfo->ucBssIndex) + prStaRec->ucBssIndex = prAisBssInfo->ucBssIndex; + + /* init the prStaRec */ + /* prStaRec will be zero first in cnmStaRecAlloc() */ + COPY_MAC_ADDR(prStaRec->aucMacAddr, prCmd->aucPeerMac); + + prStaRec->u2BSSBasicRateSet = prAisBssInfo->u2BSSBasicRateSet; + + prStaRec->u2DesiredNonHTRateSet + = prAdapter->rWifiVar.ucAvailablePhyTypeSet; + + prStaRec->u2OperationalRateSet + = prAisBssInfo->u2OperationalRateSet; + prStaRec->ucPhyTypeSet = prAisBssInfo->ucPhyTypeSet; + prStaRec->eStaType = prCmd->eStaType; + + /* Init lowest rate to prevent CCK in 5G band */ + nicTxUpdateStaRecDefaultRate(prStaRec); + + /* Better to change state here, not at TX Done */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + } else { + if ((prStaRec->ucStaState > STA_STATE_1) + && (IS_DLS_STA(prStaRec))) { + /* TODO: Teardown the peer */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + } + } + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to update a peer record. + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t /* TDLS_STATUS */ +cnmPeerUpdate(struct ADAPTER *prAdapter, void *pvSetBuffer, + uint32_t u4SetBufferLen, uint32_t *pu4SetInfoLen) +{ + + struct CMD_PEER_UPDATE *prCmd; + struct BSS_INFO *prAisBssInfo; + struct STA_RECORD *prStaRec; + uint8_t ucNonHTPhyTypeSet; + + uint16_t u2OperationalRateSet = 0; + + uint8_t ucRate; + uint16_t i, j; + + /* sanity check */ + if ((!prAdapter) || (!pvSetBuffer) || (!pu4SetInfoLen)) + return TDLS_STATUS_FAIL; + + /* init */ + *pu4SetInfoLen = sizeof(struct CMD_PEER_ADD); + prCmd = (struct CMD_PEER_UPDATE *) pvSetBuffer; + + prAisBssInfo = prAdapter->prAisBssInfo; + if (prAisBssInfo == NULL) { + log_dbg(MEM, ERROR, "%s: prAisBssInfo is NULL!\n" + , __func__); + return TDLS_STATUS_FAIL; + } + prStaRec = cnmGetStaRecByAddress(prAdapter, + (uint8_t) prAisBssInfo->ucBssIndex, + prCmd->aucPeerMac); + + if ((!prStaRec) || !(prStaRec->fgIsInUse)) + return TDLS_STATUS_FAIL; + + if (!IS_DLS_STA(prStaRec)) + return TDLS_STATUS_FAIL; + + if (prAisBssInfo) { + if (prAisBssInfo->ucBssIndex) + prStaRec->ucBssIndex = prAisBssInfo->ucBssIndex; + } + + /* update the record join time. */ + GET_CURRENT_SYSTIME(&prStaRec->rUpdateTime); + + /* update Station Record - Status/Reason Code */ + prStaRec->u2StatusCode = prCmd->u2StatusCode; + prStaRec->u2AssocId = 0; /* no use */ + prStaRec->u2ListenInterval = 0; /* unknown */ + prStaRec->fgIsQoS = TRUE; + prStaRec->fgIsUapsdSupported = (prCmd->UapsdBitmap == 0) ? FALSE : TRUE; + prStaRec->u4TxBeamformingCap = 0; /* no use */ + prStaRec->ucAselCap = 0; /* no use */ + prStaRec->ucRCPI = 120; + prStaRec->ucBmpTriggerAC = prCmd->UapsdBitmap; + prStaRec->ucBmpDeliveryAC = prCmd->UapsdBitmap; + prStaRec->ucUapsdSp = prCmd->UapsdMaxSp; + prStaRec->eStaType = prCmd->eStaType; + + /* ++ support rate */ + if (prCmd->u2SupRateLen) { + for (i = 0; i < prCmd->u2SupRateLen; i++) { + if (prCmd->aucSupRate[i]) { + ucRate = prCmd->aucSupRate[i] & RATE_MASK; + /* Search all valid data rates */ + for (j = 0; j < sizeof(aucValidDataRate) + / sizeof(uint8_t); j++) { + if (ucRate == aucValidDataRate[j]) { + u2OperationalRateSet |= BIT(j); + break; + } + } + } + + } + + prStaRec->u2OperationalRateSet = u2OperationalRateSet; + prStaRec->u2BSSBasicRateSet = prAisBssInfo->u2BSSBasicRateSet; + + /* 4 <5> PHY type setting */ + + prStaRec->ucPhyTypeSet = 0; + + if (prAisBssInfo->eBand == BAND_2G4) { + if (prCmd->fgIsSupHt) + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HT; + + /* if not 11n only */ + if (!(prStaRec->u2BSSBasicRateSet + & RATE_SET_BIT_HT_PHY)) { + /* check if support 11g */ + if ((prStaRec->u2OperationalRateSet + & RATE_SET_OFDM)) { + prStaRec->ucPhyTypeSet + |= PHY_TYPE_BIT_ERP; + } + + /* if not 11g only */ + if (!(prStaRec->u2BSSBasicRateSet + & RATE_SET_OFDM)) { + /* check if support 11b */ + if ((prStaRec->u2OperationalRateSet + & RATE_SET_HR_DSSS)) { + prStaRec->ucPhyTypeSet + |= PHY_TYPE_BIT_HR_DSSS; + } + } + } + } else { + if (prCmd->rVHtCap.u2CapInfo) + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_VHT; + + if (prCmd->fgIsSupHt) + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HT; + + /* if not 11n only */ + if (!(prStaRec->u2BSSBasicRateSet + & RATE_SET_BIT_HT_PHY)) { + /* Support 11a definitely */ + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_OFDM; + } + } + + if (IS_STA_IN_AIS(prStaRec)) { + if (!((prAdapter->rWifiVar.rConnSettings + .eEncStatus == ENUM_ENCRYPTION3_ENABLED) + || (prAdapter->rWifiVar.rConnSettings + .eEncStatus == ENUM_ENCRYPTION3_KEY_ABSENT) + || (prAdapter->rWifiVar.rConnSettings + .eEncStatus == ENUM_ENCRYPTION_DISABLED) + || (prAdapter->prGlueInfo->u2WSCAssocInfoIELen) +#if CFG_SUPPORT_WAPI + || (prAdapter->prGlueInfo->u2WapiAssocInfoIESz) +#endif + )) { + + 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 + 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; + } + + } + + /* ++HT capability */ + + if (prCmd->fgIsSupHt) { + prAdapter->rWifiVar.eRateSetting = FIXED_RATE_NONE; + prStaRec->ucDesiredPhyTypeSet |= PHY_TYPE_BIT_HT; + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HT; + prStaRec->u2HtCapInfo = prCmd->rHtCap.u2CapInfo; + prStaRec->ucAmpduParam = prCmd->rHtCap.ucAmpduParamsInfo; + prStaRec->u2HtExtendedCap = prCmd->rHtCap.u2ExtHtCapInfo; + prStaRec->u4TxBeamformingCap = prCmd->rHtCap.u4TxBfCapInfo; + prStaRec->ucAselCap = prCmd->rHtCap.ucAntennaSelInfo; + prStaRec->ucMcsSet = prCmd->rHtCap.rMCS.arRxMask[0]; + if (prCmd->rHtCap.rMCS.arRxMask[32 / 8] & BIT(0)) + prStaRec->fgSupMcs32 = TRUE; + else + prStaRec->fgSupMcs32 = FALSE; + kalMemCopy(prStaRec->aucRxMcsBitmask, + prCmd->rHtCap.rMCS.arRxMask, + sizeof(prStaRec->aucRxMcsBitmask)); + } + /* TODO ++VHT */ + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Get TDLS peer 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 + */ +/*----------------------------------------------------------------------------*/ +struct STA_RECORD *cnmGetTdlsPeerByAddress(struct ADAPTER *prAdapter, + uint8_t ucBssIndex, uint8_t aucPeerMACAddress[]) +{ + struct STA_RECORD *prStaRec; + uint16_t i; + + ASSERT(prAdapter); + ASSERT(aucPeerMACAddress); + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + if (prStaRec) { + if (prStaRec->fgIsInUse + && prStaRec->eStaType == STA_TYPE_DLS_PEER + && EQUAL_MAC_ADDR(prStaRec->aucMacAddr, + aucPeerMACAddress)) { + break; + } + } + } + + return prStaRec; +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/cnm_timer.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/cnm_timer.c new file mode 100644 index 0000000000000..d28d83f354629 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/cnm_timer.c @@ -0,0 +1,539 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/cnm_timer.c#1 + */ + +/*! \file "cnm_timer.c" + * \brief + * + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief 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 u_int8_t cnmTimerSetTimer(IN struct ADAPTER *prAdapter, + IN OS_SYSTIME rTimeout, + IN enum ENUM_TIMER_WAKELOCK_TYPE_T eType) +{ + struct ROOT_TIMER *prRootTimer; + u_int8_t fgNeedWakeLock; + + ASSERT(prAdapter); + + prRootTimer = &prAdapter->rRootTimer; + + kalSetTimer(prAdapter->prGlueInfo, rTimeout); + + if ((eType == TIMER_WAKELOCK_REQUEST) + || (rTimeout <= SEC_TO_SYSTIME(WAKE_LOCK_MAX_TIME) + && (eType == TIMER_WAKELOCK_AUTO))) { + 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 struct ADAPTER *prAdapter) +{ + struct ROOT_TIMER *prRootTimer; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prRootTimer = &prAdapter->rRootTimer; + + /* Note: glue layer have configured timer */ + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + LINK_INITIALIZE(&prRootTimer->rLinkHead); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + + KAL_WAKE_LOCK_INIT(prAdapter, &prRootTimer->rWakeLock, "WLAN Timer"); + prRootTimer->fgWakeLocked = FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routines is called to destroy a root timer. + * When WIFI is off, the token shall be returned back to system. + * + * \param[in] + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void cnmTimerDestroy(IN struct ADAPTER *prAdapter) +{ + struct ROOT_TIMER *prRootTimer; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prRootTimer = &prAdapter->rRootTimer; + + if (prRootTimer->fgWakeLocked) { + KAL_WAKE_UNLOCK(prAdapter, &prRootTimer->rWakeLock); + prRootTimer->fgWakeLocked = FALSE; + } + KAL_WAKE_LOCK_DESTROY(prAdapter, &prRootTimer->rWakeLock); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + LINK_INITIALIZE(&prRootTimer->rLinkHead); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + + /* Note: glue layer will be responsible for timer destruction */ +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routines is called to initialize a timer. + * + * \param[in] prTimer Pointer to a timer structure. + * \param[in] pfnFunc Pointer to the call back function. + * \param[in] u4Data Parameter for call back function. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void +cnmTimerInitTimerOption(IN struct ADAPTER *prAdapter, + IN struct TIMER *prTimer, + IN PFN_MGMT_TIMEOUT_FUNC pfFunc, + IN unsigned long ulDataPtr, + IN enum ENUM_TIMER_WAKELOCK_TYPE_T eType) +{ + ASSERT(prAdapter); + + ASSERT(prTimer); + + ASSERT((eType >= TIMER_WAKELOCK_AUTO) && (eType < TIMER_WAKELOCK_NUM)); + +#if DBG + /* Note: NULL function pointer is permitted for HEM POWER */ + if (pfFunc == NULL) + log_dbg(CNM, WARN, "Init timer with NULL callback function!\n"); + + ASSERT(prAdapter->rRootTimer.rLinkHead.prNext); + { + struct LINK *prTimerList; + struct LINK_ENTRY *prLinkEntry; + struct TIMER *prPendingTimer; + + prTimerList = &(prAdapter->rRootTimer.rLinkHead); + + LINK_FOR_EACH(prLinkEntry, prTimerList) { + prPendingTimer = LINK_ENTRY(prLinkEntry, + struct TIMER, rLinkEntry); + ASSERT(prPendingTimer); + ASSERT(prPendingTimer != prTimer); + } + } +#endif + if (prTimer->pfMgmtTimeOutFunc == pfFunc + && prTimer->rLinkEntry.prNext) { + log_dbg(CNM, WARN, "re-init timer, func %p\n", pfFunc); + kal_show_stack(prAdapter, NULL, NULL); + } + + LINK_ENTRY_INITIALIZE(&prTimer->rLinkEntry); + + prTimer->pfMgmtTimeOutFunc = pfFunc; + prTimer->ulDataPtr = ulDataPtr; + prTimer->eType = eType; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routines is called to stop a timer. + * + * \param[in] prTimer Pointer to a timer structure. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +static void cnmTimerStopTimer_impl(IN struct ADAPTER *prAdapter, + IN struct TIMER *prTimer, IN u_int8_t fgAcquireSpinlock) +{ + struct 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); + + if (LINK_IS_EMPTY(&prRootTimer->rLinkHead)) { + /* kalCancelTimer(prAdapter->prGlueInfo); */ + + /* Violate rule of del_timer_sync which cause DeadLock + * If no pending timer, let the dummpy timeout happen + * It would happen only one time + * Prevent call del_timer_sync with SPIN_LOCK_TIMER hold + * =================================================== + * Function: del_timer_sync + * Note: For !irqsafe timers, you must not hold locks + * that are held in interrupt context while calling + * this function. Even if the lock has nothing to do + * with the timer in question. + * Here's why: + * + * CPU0 CPU1 + * ---- ---- + * + * call_timer_fn(); + * base->running_timer = mytimer; + * spin_lock_irq(somelock); + * + * spin_lock(somelock); + * del_timer_sync(mytimer); + * while (base->running_timer == mytimer); + * ================================================== + */ + + if (fgAcquireSpinlock && prRootTimer->fgWakeLocked) { + KAL_WAKE_UNLOCK(prAdapter, + &prRootTimer->rWakeLock); + prRootTimer->fgWakeLocked = FALSE; + } + } + + /* 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 (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 struct ADAPTER *prAdapter, IN struct TIMER *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 struct ADAPTER *prAdapter, IN struct TIMER *prTimer, + IN uint32_t u4TimeoutMs) +{ + struct ROOT_TIMER *prRootTimer; + struct LINK *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 <= ((uint32_t) 0xFFFF * MSEC_PER_MIN)); + + prTimer->u2Minutes = (uint16_t) (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 < (((uint32_t) 0x80000000 - MSEC_PER_SEC) / KAL_HZ)); + rTimeoutSystime = MSEC_TO_SYSTIME(u4TimeoutMs); + if (rTimeoutSystime == 0) + rTimeoutSystime = 1; + 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, prTimer->eType); + } + + /* Add this timer to checking list */ + prTimer->rExpiredSysTime = rExpiredSysTime; + + if (!timerPendingTimer(prTimer)) + LINK_INSERT_TAIL(prTimerList, &prTimer->rLinkEntry); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routines is called to check the timer list. + * + * \param[in] + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void cnmTimerDoTimeOutCheck(IN struct ADAPTER *prAdapter) +{ + struct ROOT_TIMER *prRootTimer; + struct LINK *prTimerList; + struct LINK_ENTRY *prLinkEntry; + struct TIMER *prTimer; + OS_SYSTIME rCurSysTime; + PFN_MGMT_TIMEOUT_FUNC pfMgmtTimeOutFunc; + unsigned long ulTimeoutDataPtr; + u_int8_t fgNeedWakeLock; + enum ENUM_TIMER_WAKELOCK_TYPE_T eType = TIMER_WAKELOCK_NONE; + + 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) { + if (prLinkEntry == NULL) + break; + + prTimer = LINK_ENTRY(prLinkEntry, struct TIMER, rLinkEntry); + ASSERT(prTimer); + if (prLinkEntry->prNext == NULL) + log_dbg(CNM, WARN, "timer was re-inited, func %p\n", + prTimer->pfMgmtTimeOutFunc); + + /* Check if this entry is timeout. */ + if (!TIME_BEFORE(rCurSysTime, prTimer->rExpiredSysTime)) { + cnmTimerStopTimer_impl(prAdapter, prTimer, FALSE); + + pfMgmtTimeOutFunc = prTimer->pfMgmtTimeOutFunc; + ulTimeoutDataPtr = prTimer->ulDataPtr; + + 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, + ulTimeoutDataPtr); + 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 = (struct LINK_ENTRY *) prTimerList; + + prRootTimer->rNextExpiredSysTime + = rCurSysTime + MGMT_MAX_TIMEOUT_INTERVAL; + } else if (TIME_BEFORE(prTimer->rExpiredSysTime, + prRootTimer->rNextExpiredSysTime)) { + prRootTimer->rNextExpiredSysTime + = prTimer->rExpiredSysTime; + + if (prTimer->eType == TIMER_WAKELOCK_REQUEST) + eType = TIMER_WAKELOCK_REQUEST; + else if ((eType != TIMER_WAKELOCK_REQUEST) + && (prTimer->eType == TIMER_WAKELOCK_AUTO)) + eType = TIMER_WAKELOCK_AUTO; + } + } /* 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)((int32_t) prRootTimer->rNextExpiredSysTime + - (int32_t) rCurSysTime), + eType); + } + + if (prRootTimer->fgWakeLocked && !fgNeedWakeLock) { + KAL_WAKE_UNLOCK(prAdapter, &prRootTimer->rWakeLock); + prRootTimer->fgWakeLocked = FALSE; + } + + /* release spin lock */ + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/hem_mbox.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/hem_mbox.c new file mode 100644 index 0000000000000..cf913905ff977 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/hem_mbox.c @@ -0,0 +1,588 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: mgmt/hem_mbox.c + */ + +/*! \file "hem_mbox.c" + * \brief + * + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +#if DBG +/*lint -save -e64 Type mismatch */ +static uint8_t *apucDebugMsg[] = { + (uint8_t *) DISP_STRING("MID_MNY_CNM_CH_REQ"), + (uint8_t *) DISP_STRING("MID_MNY_CNM_CH_ABORT"), + (uint8_t *) DISP_STRING("MID_CNM_AIS_CH_GRANT"), + (uint8_t *) DISP_STRING("MID_CNM_P2P_CH_GRANT"), + (uint8_t *) DISP_STRING("MID_CNM_BOW_CH_GRANT"), + +#if (CFG_SUPPORT_DFS_MASTER == 1) + (uint8_t *) DISP_STRING("MID_CNM_P2P_RADAR_DETECT"), + (uint8_t *) DISP_STRING("MID_CNM_P2P_CSA_DONE"), +#endif + (uint8_t *) DISP_STRING("MID_AIS_SCN_SCAN_REQ"), + (uint8_t *) DISP_STRING("MID_AIS_SCN_SCAN_REQ_V2"), + (uint8_t *) DISP_STRING("MID_AIS_SCN_SCAN_CANCEL"), + (uint8_t *) DISP_STRING("MID_P2P_SCN_SCAN_REQ"), + (uint8_t *) DISP_STRING("MID_P2P_SCN_SCAN_REQ_V2"), + (uint8_t *) DISP_STRING("MID_P2P_SCN_SCAN_CANCEL"), + (uint8_t *) DISP_STRING("MID_BOW_SCN_SCAN_REQ"), + (uint8_t *) DISP_STRING("MID_BOW_SCN_SCAN_REQ_V2"), + (uint8_t *) DISP_STRING("MID_BOW_SCN_SCAN_CANCEL"), + (uint8_t *) DISP_STRING("MID_RLM_SCN_SCAN_REQ"), + (uint8_t *) DISP_STRING("MID_RLM_SCN_SCAN_REQ_V2"), + (uint8_t *) DISP_STRING("MID_RLM_SCN_SCAN_CANCEL"), + (uint8_t *) DISP_STRING("MID_SCN_AIS_SCAN_DONE"), + (uint8_t *) DISP_STRING("MID_SCN_P2P_SCAN_DONE"), + (uint8_t *) DISP_STRING("MID_SCN_BOW_SCAN_DONE"), + (uint8_t *) DISP_STRING("MID_SCN_RLM_SCAN_DONE"), + + (uint8_t *) DISP_STRING("MID_OID_AIS_FSM_JOIN_REQ"), + (uint8_t *) DISP_STRING("MID_OID_AIS_FSM_ABORT"), + (uint8_t *) DISP_STRING("MID_AIS_SAA_FSM_START"), + (uint8_t *) DISP_STRING("MID_OID_SAA_FSM_CONTINUE"), + (uint8_t *) DISP_STRING("MID_AIS_SAA_FSM_ABORT"), + (uint8_t *) DISP_STRING("MID_SAA_AIS_JOIN_COMPLETE"), + +#if CFG_ENABLE_BT_OVER_WIFI + (uint8_t *) DISP_STRING("MID_BOW_SAA_FSM_START"), + (uint8_t *) DISP_STRING("MID_BOW_SAA_FSM_ABORT"), + (uint8_t *) DISP_STRING("MID_SAA_BOW_JOIN_COMPLETE"), +#endif + +#if CFG_ENABLE_WIFI_DIRECT + (uint8_t *) DISP_STRING("MID_P2P_SAA_FSM_START"), + (uint8_t *) DISP_STRING("MID_P2P_SAA_FSM_ABORT"), + (uint8_t *) DISP_STRING("MID_SAA_P2P_JOIN_COMPLETE"), + + (uint8_t *) DISP_STRING("MID_MNY_P2P_FUN_SWITCH"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_DEVICE_DISCOVERY"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_CONNECTION_REQ"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_CONNECTION_ABORT"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_BEACON_UPDATE"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_STOP_AP"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_CHNL_REQ"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_CHNL_ABORT"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_MGMT_TX"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_GROUP_DISSOLVE"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_MGMT_FRAME_REGISTER"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_NET_DEV_REGISTER"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_START_AP"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_DEL_IFACE"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_MGMT_FRAME_UPDATE"), +#if (CFG_SUPPORT_DFS_MASTER == 1) + (uint8_t *) DISP_STRING("MID_MNY_P2P_DFS_CAC"), + (uint8_t *) DISP_STRING("MID_MNY_P2P_SET_NEW_CHANNEL"), +#endif +#if CFG_SUPPORT_WFD + (uint8_t *) DISP_STRING("MID_MNY_P2P_WFD_CFG_UPDATE"), +#endif + (uint8_t *) DISP_STRING("MID_MNY_P2P_ACTIVE_BSS"), +#endif + +#if CFG_SUPPORT_ADHOC + (uint8_t *) DISP_STRING("MID_SCN_AIS_FOUND_IBSS"), +#endif /* CFG_SUPPORT_ADHOC */ + + (uint8_t *) DISP_STRING("MID_SAA_AIS_FSM_ABORT"), + (uint8_t *) DISP_STRING("MID_MNY_AIS_REMAIN_ON_CHANNEL"), + (uint8_t *) DISP_STRING("MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL"), + (uint8_t *) DISP_STRING("MID_MNY_AIS_MGMT_TX"), + (uint8_t *) DISP_STRING("MID_WNM_AIS_BSS_TRANSITION"), +#if CFG_SUPPORT_NCHO + (uint8_t *) DISP_STRING("MID_MNY_AIS_NCHO_ACTION_FRAME") +#endif +}; + +/*lint -restore */ +#endif /* DBG */ + +/* This message entry will be re-ordered based on the message ID order + * by invoking mboxInitMsgMap() + */ +static struct MSG_HNDL_ENTRY arMsgMapTable[] = { + {MID_MNY_CNM_CH_REQ, cnmChMngrRequestPrivilege}, + {MID_MNY_CNM_CH_ABORT, cnmChMngrAbortPrivilege}, + {MID_CNM_AIS_CH_GRANT, aisFsmRunEventChGrant}, +#if CFG_ENABLE_WIFI_DIRECT + /*set in gl_p2p_init.c */ + {MID_CNM_P2P_CH_GRANT, p2pFsmRunEventChGrant}, +#else + {MID_CNM_P2P_CH_GRANT, mboxDummy}, +#endif + +#if (CFG_SUPPORT_DFS_MASTER == 1) + {MID_CNM_P2P_RADAR_DETECT, p2pRoleFsmRunEventRadarDet}, + {MID_CNM_P2P_CSA_DONE, p2pRoleFsmRunEventCsaDone}, +#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 + /*set in gl_p2p_init.c */ + {MID_SCN_P2P_SCAN_DONE, p2pFsmRunEventScanDone}, +#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_OID_SAA_FSM_CONTINUE, saaFsmRunEventFTContinue}, + {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, p2pRoleFsmRunEventJoinComplete}, /* V */ + + {MID_MNY_P2P_FUN_SWITCH, p2pRoleFsmRunEventSwitchOPMode}, + {MID_MNY_P2P_DEVICE_DISCOVERY, p2pFsmRunEventScanRequest}, /* V */ + {MID_MNY_P2P_CONNECTION_REQ, p2pRoleFsmRunEventConnectionRequest}, + {MID_MNY_P2P_CONNECTION_ABORT, p2pRoleFsmRunEventConnectionAbort}, + {MID_MNY_P2P_BEACON_UPDATE, p2pRoleFsmRunEventBeaconUpdate}, + {MID_MNY_P2P_STOP_AP, p2pRoleFsmRunEventStopAP}, + {MID_MNY_P2P_CHNL_REQ, p2pDevFsmRunEventChannelRequest}, /* V */ + {MID_MNY_P2P_CHNL_ABORT, p2pDevFsmRunEventChannelAbort}, /* V */ + {MID_MNY_P2P_MGMT_TX, p2pDevFsmRunEventMgmtTx}, /* V */ + {MID_MNY_P2P_GROUP_DISSOLVE, p2pRoleFsmRunEventDissolve}, + {MID_MNY_P2P_MGMT_FRAME_REGISTER, + p2pDevFsmRunEventMgmtFrameRegister}, + {MID_MNY_P2P_NET_DEV_REGISTER, p2pFsmRunEventNetDeviceRegister}, + {MID_MNY_P2P_START_AP, p2pRoleFsmRunEventStartAP}, + {MID_MNY_P2P_DEL_IFACE, p2pRoleFsmRunEventDelIface}, + {MID_MNY_P2P_MGMT_FRAME_UPDATE, p2pFsmRunEventUpdateMgmtFrame}, +#if (CFG_SUPPORT_DFS_MASTER == 1) + {MID_MNY_P2P_DFS_CAC, p2pRoleFsmRunEventDfsCac}, + {MID_MNY_P2P_SET_NEW_CHANNEL, p2pRoleFsmRunEventSetNewChannel}, +#endif +#if CFG_SUPPORT_WFD + {MID_MNY_P2P_WFD_CFG_UPDATE, p2pFsmRunEventWfdSettingUpdate}, +#endif + {MID_MNY_P2P_ACTIVE_BSS, p2pDevFsmRunEventActiveDevBss}, +#endif + +#if CFG_SUPPORT_ADHOC + {MID_SCN_AIS_FOUND_IBSS, aisFsmRunEventFoundIBSSPeer}, +#endif /* CFG_SUPPORT_ADHOC */ + + {MID_SAA_AIS_FSM_ABORT, aisFsmRunEventAbort}, + {MID_MNY_AIS_REMAIN_ON_CHANNEL, + aisFsmRunEventRemainOnChannel}, + {MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL, + aisFsmRunEventCancelRemainOnChannel}, + {MID_MNY_AIS_MGMT_TX, aisFsmRunEventMgmtFrameTx}, + {MID_WNM_AIS_BSS_TRANSITION, aisFsmRunEventBssTransition}, + {MID_OID_WMM_TSPEC_OPERATE, wmmRunEventTSOperate}, + {MID_RLM_RM_SCHEDULE, rlmRunEventProcessNextRm}, +#if CFG_SUPPORT_NCHO + {MID_MNY_AIS_NCHO_ACTION_FRAME, + aisFsmRunEventNchoActionFrameTx}, +#endif +}; + +/******************************************************************************* + * 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) +{ + uint32_t i, idx; + struct MSG_HNDL_ENTRY rTempEntry; + + ASSERT((sizeof(arMsgMapTable) / sizeof(struct + MSG_HNDL_ENTRY)) == MID_TOTAL_NUM); + + for (i = 0; i < MID_TOTAL_NUM; i++) { + if (arMsgMapTable[i].eMsgId == (enum ENUM_MSG_ID) i) + continue; + for (idx = i + 1; idx < MID_TOTAL_NUM; idx++) { + if (arMsgMapTable[idx].eMsgId == (enum ENUM_MSG_ID) 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 ENUM_MSG_ID) i); + while (arMsgMapTable[i].eMsgId != (enum ENUM_MSG_ID) i) + ; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void mboxSetup(IN struct ADAPTER *prAdapter, + IN enum ENUM_MBOX_ID eMboxId) +{ + struct MBOX *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 struct ADAPTER *prAdapter, + IN enum ENUM_MBOX_ID eMboxId, IN struct MSG_HDR *prMsg, + IN enum EUNM_MSG_SEND_METHOD eMethod) +{ + struct MBOX *prMbox; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(eMboxId < MBOX_ID_TOTAL_NUM); + ASSERT(prMsg); + if (!prMsg) { + DBGLOG(CNM, ERROR, "prMsg is NULL\n"); + return; + } + + ASSERT(prAdapter); + if (!prAdapter) { + DBGLOG(CNM, ERROR, "prAdapter is NULL\n"); + return; + } + + 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 struct ADAPTER *prAdapter, + enum ENUM_MBOX_ID eMboxId) +{ + struct MBOX *prMbox; + struct MSG_HDR *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, + struct MSG_HDR *); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); + + ASSERT(prMsg); + if (!prMsg) { + DBGLOG(CNM, ERROR, "prMsg is NULL\n"); + continue; + } + MBOX_HNDL_MSG(prAdapter, prMsg); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void mboxInitialize(IN struct ADAPTER *prAdapter) +{ + uint32_t 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 struct ADAPTER *prAdapter) +{ + struct MBOX *prMbox; + struct MSG_HDR *prMsg; + uint8_t 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, + struct MSG_HDR *); + 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 struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + ASSERT(prAdapter); + + cnmMemFree(prAdapter, prMsgHdr); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/hs20.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/hs20.c new file mode 100644 index 0000000000000..a5a6d755985c1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/hs20.c @@ -0,0 +1,655 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/HS2_DEV_SW/ + * MT6620_WIFI_DRIVER_V2_1_HS_2_0/mgmt/hs20.c#2 + */ + +/*! \file "hs20.c" + * \brief This file including the hotspot 2.0 related function. + * + * This file provided the macros and functions library support for the + * protocol layer hotspot 2.0 related function. + * + */ + + +/****************************************************************************** + * C O M P I L E 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_PASSPOINT + +/****************************************************************************** + * C O N S T A N T S + ****************************************************************************** + */ + +/****************************************************************************** + * D A T A T Y P E S + ****************************************************************************** + */ + +/****************************************************************************** + * P U B L I C D A T A + ****************************************************************************** + */ + +/****************************************************************************** + * P R I V A T E D A T A + ****************************************************************************** + */ + +/****************************************************************************** + * M A C R O S + ****************************************************************************** + */ + +/****************************************************************************** + * F U N C T I O N D E C L A R A T I O N S + ****************************************************************************** + */ + +/****************************************************************************** + * F U N C T I O N S + ****************************************************************************** + */ + +/*---------------------------------------------------------------------------*/ +/*! + * \brief This function is called to generate Interworking IE + * for Probe Rsp, Bcn, Assoc Req/Rsp. + * + * \param[in] prAdapter Pointer of ADAPTER_T + * \param[out] prMsduInfo Pointer of the Msdu Info + * + * \return VOID + */ +/*---------------------------------------------------------------------------*/ +void hs20GenerateInterworkingIE(IN struct ADAPTER *prAdapter, + OUT struct MSDU_INFO *prMsduInfo) +{ +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief This function is called to generate Roaming Consortium IE + * for Probe Rsp, Bcn, Assoc Req/Rsp. + * + * \param[in] prAdapter Pointer of ADAPTER_T + * \param[out] prMsduInfo Pointer of the Msdu Info + * + * \return VOID + */ +/*---------------------------------------------------------------------------*/ +void hs20GenerateRoamingConsortiumIE(IN struct ADAPTER *prAdapter, + OUT struct MSDU_INFO *prMsduInfo) +{ +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief This function is called to generate HS2.0 IE + * for Probe Rsp, Bcn, Assoc Req/Rsp. + * + * \param[in] prAdapter Pointer of ADAPTER_T + * \param[out] prMsduInfo Pointer of the Msdu Info + * + * \return VOID + */ +/*---------------------------------------------------------------------------*/ +void hs20GenerateHS20IE(IN struct ADAPTER *prAdapter, + OUT struct MSDU_INFO *prMsduInfo) +{ + uint8_t *pucBuffer; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + if (prMsduInfo->ucBssIndex != KAL_NETWORK_TYPE_AIS_INDEX) { + pr_info("[%s] prMsduInfo->ucBssIndex(%d) is not KAL_NETWORK_TYPE_AIS_INDEX\n", + __func__, prMsduInfo->ucBssIndex); + return; + } + + pucBuffer = (uint8_t *) + ((unsigned long) prMsduInfo->prPacket + + (unsigned long) prMsduInfo->u2FrameLength); + + /* ASSOC INFO IE ID: 221 :0xDD */ + if (prAdapter->prGlueInfo->u2HS20AssocInfoIELen) { + kalMemCopy(pucBuffer, + &prAdapter->prGlueInfo->aucHS20AssocInfoIE, + prAdapter->prGlueInfo->u2HS20AssocInfoIELen); + prMsduInfo->u2FrameLength += + prAdapter->prGlueInfo->u2HS20AssocInfoIELen; + } + +} + +void hs20FillExtCapIE(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, struct MSDU_INFO *prMsduInfo) +{ + struct IE_EXT_CAP *prExtCap; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + /* Add Extended Capabilities IE */ + prExtCap = (struct IE_EXT_CAP *) + (((uint8_t *) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + + prExtCap->ucId = ELEM_ID_EXTENDED_CAP; + if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) + prExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + else + prExtCap->ucLength = 3 - ELEM_HDR_LEN; + + kalMemZero(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP); + + prExtCap->aucCapabilities[0] = ELEM_EXT_CAP_DEFAULT_VAL; + + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + prExtCap->aucCapabilities[0] &= ~ELEM_EXT_CAP_PSMP_CAP; + + if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) { + SET_EXT_CAP(prExtCap->aucCapabilities, + ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_BSS_TRANSITION_BIT); + SET_EXT_CAP(prExtCap->aucCapabilities, + ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_UTC_TSF_OFFSET_BIT); + SET_EXT_CAP(prExtCap->aucCapabilities, + ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_INTERWORKING_BIT); + SET_EXT_CAP(prExtCap->aucCapabilities, + ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_QOSMAPSET_BIT); + + /* For R2 WNM-Notification */ + SET_EXT_CAP(prExtCap->aucCapabilities, + ELEM_MAX_LEN_EXT_CAP, + ELEM_EXT_CAP_WNM_NOTIFICATION_BIT); + } + + pr_info("IE_SIZE(prExtCap) = %d, %d %d\n", + IE_SIZE(prExtCap), ELEM_HDR_LEN, ELEM_MAX_LEN_EXT_CAP); + + ASSERT(IE_SIZE(prExtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP)); + + prMsduInfo->u2FrameLength += IE_SIZE(prExtCap); +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief This function is called to fill up + * the content of Ext Cap IE bit 31. + * + * \param[in] prAdapter Pointer of ADAPTER_T + * \param[out] pucIE Pointer of the IE buffer + * + * \return VOID + */ +/*---------------------------------------------------------------------------*/ +void hs20FillProreqExtCapIE(IN struct ADAPTER *prAdapter, OUT uint8_t *pucIE) +{ + struct IE_EXT_CAP *prExtCap; + + ASSERT(prAdapter); + + /* Add Extended Capabilities IE */ + prExtCap = (struct IE_EXT_CAP *) pucIE; + + prExtCap->ucId = ELEM_ID_EXTENDED_CAP; + if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) + prExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + else + prExtCap->ucLength = 3 - ELEM_HDR_LEN; + + kalMemZero(prExtCap->aucCapabilities, prExtCap->ucLength); + + prExtCap->aucCapabilities[0] = ELEM_EXT_CAP_DEFAULT_VAL; + + if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) { + SET_EXT_CAP(prExtCap->aucCapabilities, + ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_BSS_TRANSITION_BIT); + SET_EXT_CAP(prExtCap->aucCapabilities, + ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_UTC_TSF_OFFSET_BIT); + SET_EXT_CAP(prExtCap->aucCapabilities, + ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_INTERWORKING_BIT); + SET_EXT_CAP(prExtCap->aucCapabilities, + ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_QOSMAPSET_BIT); + + /* For R2 WNM-Notification */ + SET_EXT_CAP(prExtCap->aucCapabilities, + ELEM_MAX_LEN_EXT_CAP, + ELEM_EXT_CAP_WNM_NOTIFICATION_BIT); + } +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief This function is called to fill up the content of HS2.0 IE. + * + * \param[in] prAdapter Pointer of ADAPTER_T + * \param[out] pucIE Pointer of the IE buffer + * + * \return VOID + */ +/*---------------------------------------------------------------------------*/ +void hs20FillHS20IE(IN struct ADAPTER *prAdapter, OUT uint8_t *pucIE) +{ + struct IE_HS20_INDICATION *prHS20IndicationIe; + /* P_HS20_INFO_T prHS20Info; */ + uint8_t aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + + /* prHS20Info = &(prAdapter->rWifiVar.rHS20Info); */ + + prHS20IndicationIe = (struct IE_HS20_INDICATION *) pucIE; + + prHS20IndicationIe->ucId = ELEM_ID_VENDOR; + prHS20IndicationIe->ucLength = + sizeof(struct IE_HS20_INDICATION) - ELEM_HDR_LEN; + prHS20IndicationIe->aucOui[0] = aucWfaOui[0]; + prHS20IndicationIe->aucOui[1] = aucWfaOui[1]; + prHS20IndicationIe->aucOui[2] = aucWfaOui[2]; + prHS20IndicationIe->ucType = VENDOR_OUI_TYPE_HS20; + + /* For PASSPOINT_R1 */ + /* prHS20IndicationIe->ucHotspotConfig = 0x00; */ + + /* For PASSPOINT_R2 */ + prHS20IndicationIe->ucHotspotConfig = 0x10; + +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief This function is called while calculating length of + * hotspot 2.0 indication IE for Probe Request. + * + * \param[in] prAdapter Pointer of ADAPTER_T + * \param[in] pucTargetBSSID Pointer of target HESSID + * + * \return the length of composed HS20 IE + */ +/*---------------------------------------------------------------------------*/ +uint32_t hs20CalculateHS20RelatedIEForProbeReq(IN struct ADAPTER *prAdapter, + IN uint8_t *pucTargetBSSID) +{ + uint32_t u4IeLength; + + if (0) /* Todo:: Not HS20 STA */ + return 0; + + u4IeLength = sizeof(struct IE_HS20_INDICATION) + + /* sizeof(IE_INTERWORKING_T) */ + + (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP); + + if (!pucTargetBSSID) { + /* Todo:: Nothing */ + /* u4IeLength -= MAC_ADDR_LEN; */ + } + + return u4IeLength; +} + +/*---------------------------------------------------------------------------*/ +/*! + * \brief This function is called while composing + * hotspot 2.0 indication IE for Probe Request. + * + * \param[in] prAdapter Pointer of ADAPTER_T + * \param[in] pucTargetBSSID Pointer of target HESSID + * \param[out] prIE Pointer of the IE buffer + * + * \return the wlan status + */ +/*---------------------------------------------------------------------------*/ +uint32_t hs20GenerateHS20RelatedIEForProbeReq(IN struct ADAPTER *prAdapter, + IN uint8_t *pucTargetBSSID, OUT uint8_t *prIE) +{ + if (0) /* Todo:: Not HS20 STA */ + return 0; +#if 0 + struct HS20_INFO *prHS20Info; + + prHS20Info = &(prAdapter->rWifiVar.rHS20Info); + + /* + * Generate 802.11u Interworking IE (107) + */ + hs20FillInterworkingIE(prAdapter, + prHS20Info->ucAccessNetworkOptions, + prHS20Info->ucVenueGroup, + prHS20Info->ucVenueType, + pucTargetBSSID, prIE); + prIE += IE_SIZE(prIE); +#endif + /* + * Generate Ext Cap IE (127) + */ + hs20FillProreqExtCapIE(prAdapter, prIE); + prIE += IE_SIZE(prIE); + + /* + * Generate HS2.0 Indication IE (221) + */ + hs20FillHS20IE(prAdapter, prIE); + prIE += IE_SIZE(prIE); + + return WLAN_STATUS_SUCCESS; +} + +u_int8_t hs20IsGratuitousArp(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prCurrSwRfb) +{ + uint8_t *pucSenderIP = + prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + ARP_SENDER_IP_OFFSET; + uint8_t *pucTargetIP = + prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + ARP_TARGET_IP_OFFSET; + uint8_t *pucSenderMac = ((uint8_t *) + prCurrSwRfb->pvHeader + + ETHER_HEADER_LEN + ARP_SNEDER_MAC_OFFSET); + +#if CFG_HS20_DEBUG && 0 +/* UINT_8 aucIpAllZero[4] = {0,0,0,0}; */ +/* UINT_8 aucMACAllZero[MAC_ADDR_LEN] = {0,0,0,0,0,0}; */ + uint8_t *pucTargetMac = ((uint8_t *) + prCurrSwRfb->pvHeader + + ETHER_HEADER_LEN + ARP_TARGET_MAC_OFFSET); +#endif + +#if CFG_HS20_DEBUG && 0 + uint16_t *pu2ArpOper = (uint16_t *) ((uint8_t *) + prCurrSwRfb->pvHeader + + ETHER_HEADER_LEN + ARP_OPERATION_OFFSET); + + kalPrint("Recv ARP 0x%04X\n", htons(*pu2ArpOper)); + kalPrint("SENDER[" MACSTR "] [%d:%d:%d:%d]\n", + MAC2STR(pucSenderMac), *pucSenderIP, + *(pucSenderIP + 1), *(pucSenderIP + 2), *(pucSenderIP + 3)); + kalPrint("TARGET[" MACSTR "] [%d:%d:%d:%d]\n", + MAC2STR(pucTargetMac), *pucTargetIP, + *(pucTargetIP + 1), *(pucTargetIP + 2), *(pucTargetIP + 3)); +#endif + + /* IsGratuitousArp */ + if (!kalMemCmp(pucSenderIP, pucTargetIP, 4)) { + kalPrint( + "Drop Gratuitous ARP from [" MACSTR "] [%d:%d:%d:%d]\n", + MAC2STR(pucSenderMac), *pucTargetIP, *(pucTargetIP + 1), + *(pucTargetIP + 2), *(pucTargetIP + 3)); + return TRUE; + } + return FALSE; +} + +u_int8_t hs20IsUnsolicitedNeighborAdv(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prCurrSwRfb) +{ + uint8_t *pucIpv6Protocol = ((uint8_t *) + prCurrSwRfb->pvHeader + + ETHER_HEADER_LEN + IPV6_HDR_IP_PROTOCOL_OFFSET); + + /* kalPrint("pucIpv6Protocol [%02X:%02X]\n", + * *pucIpv6Protocol, IPV6_PROTOCOL_ICMPV6); + */ + if (*pucIpv6Protocol == IPV6_PROTOCOL_ICMPV6) { + uint8_t *pucICMPv6Type = + ((uint8_t *) prCurrSwRfb->pvHeader + + ETHER_HEADER_LEN + IPV6_HDR_LEN + ICMPV6_TYPE_OFFSET); + /* kalPrint("pucICMPv6Type [%02X:%02X]\n", + * *pucICMPv6Type, ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT); + */ + if (*pucICMPv6Type == ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT) { + uint8_t *pucICMPv6Flag = + ((uint8_t *) prCurrSwRfb->pvHeader + + ETHER_HEADER_LEN + + IPV6_HDR_LEN + ICMPV6_FLAG_OFFSET); + uint8_t *pucSrcMAC = ((uint8_t *) + prCurrSwRfb->pvHeader + MAC_ADDR_LEN); + +#if CFG_HS20_DEBUG + kalPrint("NAdv Flag [%02X] [R(%d)\\S(%d)\\O(%d)]\n", + *pucICMPv6Flag, + (uint8_t) (*pucICMPv6Flag + & ICMPV6_FLAG_ROUTER_BIT) >> 7, + (uint8_t) (*pucICMPv6Flag + & ICMPV6_FLAG_SOLICITED_BIT) >> 6, + (uint8_t) (*pucICMPv6Flag + & ICMPV6_FLAG_OVERWRITE_BIT) >> 5); +#endif + if (!(*pucICMPv6Flag & ICMPV6_FLAG_SOLICITED_BIT)) { + kalPrint( + "Drop Unsolicited Neighbor Advertisement from [" + MACSTR "]\n", MAC2STR(pucSrcMAC)); + return TRUE; + } + } + } + + return FALSE; +} + +#if CFG_ENABLE_GTK_FRAME_FILTER +u_int8_t hs20IsForgedGTKFrame(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, IN struct SW_RFB *prCurrSwRfb) +{ + struct CONNECTION_SETTINGS *prConnSettings = + &prAdapter->rWifiVar.rConnSettings; + uint8_t *pucEthDestAddr = prCurrSwRfb->pvHeader; + + /* 3 TODO: Need to verify this function before enable it */ + return FALSE; + + if ((prConnSettings->eEncStatus != ENUM_ENCRYPTION_DISABLED) + && IS_BMCAST_MAC_ADDR(pucEthDestAddr)) { + uint8_t ucIdx = 0; + uint32_t *prIpAddr, *prPacketDA; + uint16_t *pu2PktIpVer = + (uint16_t *) ((uint8_t *) + prCurrSwRfb->pvHeader + + (ETHER_HEADER_LEN - ETHER_TYPE_LEN)); + + if (*pu2PktIpVer == htons(ETH_P_IPV4)) { + if (!prBssInfo->prIpV4NetAddrList) + return FALSE; + for (ucIdx = 0; + ucIdx < prBssInfo + ->prIpV4NetAddrList->ucAddrCount; + ucIdx++) { + prIpAddr = (uint32_t *) + &prBssInfo->prIpV4NetAddrList + ->arNetAddr[ucIdx].aucIpAddr[0]; + prPacketDA = + (uint32_t *) ((uint8_t *) + prCurrSwRfb->pvHeader + + ETHER_HEADER_LEN + + IPV4_HDR_IP_DST_ADDR_OFFSET); + + if (kalMemCmp(prIpAddr, prPacketDA, 4) == 0) { + kalPrint("Drop FORGED IPv4 packet\n"); + return TRUE; + } + } + } +#ifdef CONFIG_IPV6 + else if (*pu2PktIpVer == htons(ETH_P_IPV6)) { + uint8_t aucIPv6Mac[MAC_ADDR_LEN]; + uint8_t *pucIdx = + prCurrSwRfb->pvHeader + + ETHER_HEADER_LEN + + IPV6_HDR_IP_DST_ADDR_MAC_HIGH_OFFSET; + + kalMemCopy(&aucIPv6Mac[0], pucIdx, 3); + pucIdx += 5; + kalMemCopy(&aucIPv6Mac[3], pucIdx, 3); + kalPrint( + "Get IPv6 frame Dst IP MAC part " MACSTR "\n", + MAC2STR(aucIPv6Mac)); + + if (EQUAL_MAC_ADDR(aucIPv6Mac, + prBssInfo->aucOwnMacAddr)) { + kalPrint("Drop FORGED IPv6 packet\n"); + return TRUE; + } + } +#endif + } + + return FALSE; +} +#endif + +u_int8_t hs20IsUnsecuredFrame(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, IN struct SW_RFB *prCurrSwRfb) +{ + uint16_t *pu2PktIpVer = (uint16_t *) ((uint8_t *) + prCurrSwRfb->pvHeader + (ETHER_HEADER_LEN - ETHER_TYPE_LEN)); + + /* kalPrint("IPVER 0x%4X\n", htons(*pu2PktIpVer)); */ +#if CFG_HS20_DEBUG & 0 + uint8_t i = 0; + + kalPrint("==============================================="); + for (i = 0; i < 96; i++) { + if (!(i % 16)) + kalPrint("\n"); + kalPrint("%02X ", *((uint8_t *) prCurrSwRfb->pvHeader + i)); + } + kalPrint("\n"); +#endif + +#if CFG_ENABLE_GTK_FRAME_FILTER + if (hs20IsForgedGTKFrame(prAdapter, prBssInfo, prCurrSwRfb)) + return TRUE; +#endif + if (*pu2PktIpVer == htons(ETH_P_ARP)) + return hs20IsGratuitousArp(prAdapter, prCurrSwRfb); + else if (*pu2PktIpVer == htons(ETH_P_IPV6)) + return hs20IsUnsolicitedNeighborAdv(prAdapter, prCurrSwRfb); + + return FALSE; +} + +u_int8_t hs20IsFrameFilterEnabled(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo) +{ +#if 1 + if (prAdapter->prGlueInfo->fgConnectHS20AP) + return TRUE; +#else + struct PARAM_SSID rParamSsid; + struct BSS_DESC *prBssDesc; + + rParamSsid.u4SsidLen = prBssInfo->ucSSIDLen; + COPY_SSID(rParamSsid.aucSsid, + rParamSsid.u4SsidLen, prBssInfo->aucSSID, prBssInfo->ucSSIDLen); + + prBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, + prBssInfo->aucBSSID, TRUE, &rParamSsid); + + if (!prBssDesc) + return FALSE; + + if (prBssDesc->fgIsSupportHS20) { + if (!(prBssDesc->ucHotspotConfig + & ELEM_HS_CONFIG_DGAF_DISABLED_MASK)) + return TRUE; + /* Disable frame filter only if DGAF == 1 */ + return FALSE; + } +#endif + + /* For Now, always return true to run hs20 check even for legacy AP */ + return TRUE; +} + +uint32_t hs20SetBssidPool(IN struct ADAPTER *prAdapter, + IN void *pvBuffer, + IN enum ENUM_KAL_NETWORK_TYPE_INDEX eNetTypeIdx) +{ + struct PARAM_HS20_SET_BSSID_POOL *prParamBssidPool = + (struct PARAM_HS20_SET_BSSID_POOL *) pvBuffer; + struct HS20_INFO *prHS20Info; + uint8_t ucIdx; + + prHS20Info = &(prAdapter->rWifiVar.rHS20Info); + + pr_info("[%s]Set Bssid Pool! enable[%d] num[%d]\n", + __func__, prParamBssidPool->fgIsEnable, + prParamBssidPool->ucNumBssidPool); + + for (ucIdx = 0; ucIdx < prParamBssidPool->ucNumBssidPool; ucIdx++) { + COPY_MAC_ADDR( + prHS20Info->arBssidPool[ucIdx].aucBSSID, + &prParamBssidPool->arBSSID[ucIdx]); + + pr_info("[%s][%d][" MACSTR "]\n", + __func__, ucIdx, + MAC2STR(prHS20Info->arBssidPool[ucIdx].aucBSSID)); + } + prHS20Info->fgIsHS2SigmaMode = prParamBssidPool->fgIsEnable; + prHS20Info->ucNumBssidPoolEntry = prParamBssidPool->ucNumBssidPool; + +#if 0 + wlanClearScanningResult(prAdapter); +#endif + + return WLAN_STATUS_SUCCESS; +} + +#endif /* CFG_SUPPORT_PASSPOINT */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/mib.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/mib.c new file mode 100644 index 0000000000000..33e39063f03ca --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/mib.c @@ -0,0 +1,138 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + +/******************************************************************************* + * C O M P I L E 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 + ******************************************************************************* + */ +const struct NON_HT_PHY_ATTRIBUTE 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) */ +}; + +const struct NON_HT_ATTRIBUTE 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) */ +}; + +const struct NON_HT_ATTRIBUTE rNonHTApModeAttributes[AP_MODE_NUM] = { + {PHY_TYPE_HR_DSSS_INDEX, BASIC_RATE_SET_HR_DSSS} + , /* For AP_MODE_11B(0) */ + {PHY_TYPE_ERP_INDEX, BASIC_RATE_SET_HR_DSSS_ERP} + , /* For AP_MODE_MIXED_11BG(1) */ + {PHY_TYPE_ERP_INDEX, BASIC_RATE_SET_ERP} + , /* For AP_MODE_11G(2) */ + {PHY_TYPE_ERP_P2P_INDEX, BASIC_RATE_SET_ERP_P2P} + , /* For AP_MODE_11G_P2P(3) */ + {PHY_TYPE_OFDM_INDEX, BASIC_RATE_SET_OFDM} + , /* For AP_MODE_11A(4) */ +}; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_assoc.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_assoc.c new file mode 100644 index 0000000000000..861f971ae9eb7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_assoc.c @@ -0,0 +1,143 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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) + */ +/*----------------------------------------------------------------------------*/ +uint8_t *p2pBuildReAssocReqFrameCommonIEs(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN uint8_t *pucBuffer) +{ + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + + /* 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, + prP2pBssInfo->aucSSID, + prP2pBssInfo->ucSSIDLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + return pucBuffer; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_bss.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_bss.c new file mode 100644 index 0000000000000..e6a53df326de8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_bss.c @@ -0,0 +1,109 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: @(#) p2p_bss.c@@ + */ + +/*! \file "p2p_bss.c" + * \brief This file contains the functions for creating p2p BSS(AP). + * + * This file contains the functions for BSS(AP). We may create a BSS + * network, or merge with exist IBSS network and sending Beacon Frame or reply + * the Probe Response Frame for received Probe Request Frame. + */ + +/****************************************************************************** + * C O M P I L E R F L A G S + ****************************************************************************** + */ + +/****************************************************************************** + * E X T E R N A L R E F E R E N C E S + ****************************************************************************** + */ + +#include "precomp.h" + +/****************************************************************************** + * C O N S T A N T S + ****************************************************************************** + */ + +/****************************************************************************** + * D A T A T Y P E S + ****************************************************************************** + */ + +/****************************************************************************** + * P U B L I C D A T A + ****************************************************************************** + */ + +/****************************************************************************** + * P R I V A T E D A T A + ****************************************************************************** + */ + +/****************************************************************************** + * M A C R O S + ****************************************************************************** + */ + +/****************************************************************************** + * F U N C T I O N D E C L A R A T I O N S + ****************************************************************************** + */ + +/****************************************************************************** + * F U N C T I O N S + ****************************************************************************** + */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_dev_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_dev_fsm.c new file mode 100644 index 0000000000000..064d02a01fba8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_dev_fsm.c @@ -0,0 +1,1225 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#include "precomp.h" +#include "p2p_dev_state.h" +#if CFG_ENABLE_WIFI_DIRECT + +#if 1 +/*lint -save -e64 Type mismatch */ +static uint8_t *apucDebugP2pDevState[P2P_DEV_STATE_NUM] = { + (uint8_t *) DISP_STRING("P2P_DEV_STATE_IDLE"), + (uint8_t *) DISP_STRING("P2P_DEV_STATE_SCAN"), + (uint8_t *) DISP_STRING("P2P_DEV_STATE_REQING_CHANNEL"), + (uint8_t *) DISP_STRING("P2P_DEV_STATE_CHNL_ON_HAND"), + (uint8_t *) DISP_STRING("P2P_DEV_STATE_NUM") +}; + +/*lint -restore */ +#endif /* DBG */ + +uint8_t p2pDevFsmInit(IN struct ADAPTER *prAdapter) +{ + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) NULL; + struct P2P_CHNL_REQ_INFO *prP2pChnlReqInfo = + (struct P2P_CHNL_REQ_INFO *) NULL; + struct P2P_MGMT_TX_REQ_INFO *prP2pMgmtTxReqInfo = + (struct P2P_MGMT_TX_REQ_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + ASSERT_BREAK(prP2pDevFsmInfo != NULL); + + kalMemZero(prP2pDevFsmInfo, sizeof(struct P2P_DEV_FSM_INFO)); + + prP2pDevFsmInfo->eCurrentState = P2P_DEV_STATE_IDLE; + + cnmTimerInitTimer(prAdapter, + &(prP2pDevFsmInfo->rP2pFsmTimeoutTimer), + (PFN_MGMT_TIMEOUT_FUNC) p2pDevFsmRunEventTimeout, + (unsigned long) prP2pDevFsmInfo); + + prP2pBssInfo = + cnmGetBssInfoAndInit(prAdapter, NETWORK_TYPE_P2P, TRUE); + + if (prP2pBssInfo != NULL) { + COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, + prAdapter->rMyMacAddr); + /* change to local administrated address */ + prP2pBssInfo->aucOwnMacAddr[0] ^= 0x2; + + prP2pDevFsmInfo->ucBssIndex = prP2pBssInfo->ucBssIndex; + + prP2pBssInfo->eCurrentOPMode = OP_MODE_P2P_DEVICE; + prP2pBssInfo->ucConfigAdHocAPMode = AP_MODE_11G_P2P; + prP2pBssInfo->u2HwDefaultFixedRateCode = RATE_OFDM_6M; + + prP2pBssInfo->eBand = BAND_2G4; +#if (CFG_HW_WMM_BY_BSS == 1) + prP2pBssInfo->ucWmmQueSet = MAX_HW_WMM_INDEX; +#else + if (prAdapter->rWifiVar.eDbdcMode + == ENUM_DBDC_MODE_DISABLED) + prP2pBssInfo->ucWmmQueSet = DBDC_5G_WMM_INDEX; + else + prP2pBssInfo->ucWmmQueSet = DBDC_2G_WMM_INDEX; +#endif + prP2pBssInfo->ucPhyTypeSet = + prAdapter->rWifiVar.ucAvailablePhyTypeSet + & PHY_TYPE_SET_802_11GN; + + prP2pBssInfo->ucNonHTBasicPhyType = (uint8_t) + rNonHTApModeAttributes + [prP2pBssInfo->ucConfigAdHocAPMode] + .ePhyTypeIndex; + + prP2pBssInfo->u2BSSBasicRateSet = + rNonHTApModeAttributes + [prP2pBssInfo->ucConfigAdHocAPMode] + .u2BSSBasicRateSet; + + prP2pBssInfo->u2OperationalRateSet = + rNonHTPhyAttributes + [prP2pBssInfo->ucNonHTBasicPhyType] + .u2SupportedRateSet; + + prP2pBssInfo->u4PrivateData = 0;/* TH3 Huang */ + + rateGetDataRatesFromRateSet( + prP2pBssInfo->u2OperationalRateSet, + prP2pBssInfo->u2BSSBasicRateSet, + prP2pBssInfo->aucAllSupportedRates, + &prP2pBssInfo->ucAllSupportedRatesLen); + } + prP2pChnlReqInfo = &prP2pDevFsmInfo->rChnlReqInfo; + LINK_INITIALIZE(&prP2pChnlReqInfo->rP2pChnlReqLink); + + prP2pMgmtTxReqInfo = &prP2pDevFsmInfo->rMgmtTxInfo; + LINK_INITIALIZE(&prP2pMgmtTxReqInfo->rP2pTxReqLink); + + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, + P2P_DEV_STATE_IDLE); + } while (FALSE); + + if (prP2pBssInfo) + return prP2pBssInfo->ucBssIndex; + else + return prAdapter->ucP2PDevBssIdx + 1; + +#if 0 + 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)); + + prP2pFsmInfo->eCurrentState = + prP2pFsmInfo->ePreviousState = P2P_STATE_IDLE; + + prP2pFsmInfo->prTargetBss = NULL; + + cnmTimerInitTimer(prAdapter, + &(prP2pFsmInfo->rP2pFsmTimeoutTimer), + (PFN_MGMT_TIMEOUT_FUNC) p2pFsmRunEventFsmTimeout, + (unsigned long) 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 = (uint8_t) + 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(struct WLAN_BEACON_FRAME, aucInfoElem[0]) + + MAX_IE_LENGTH); + + if (prP2pBssInfo->prBeacon) { + prP2pBssInfo->prBeacon->eSrc = TX_PACKET_MGMT; + /* NULL STA_REC */ + prP2pBssInfo->prBeacon->ucStaRecIndex = 0xFF; + 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 (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) + 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; +#endif +} /* p2pDevFsmInit */ + +void p2pDevFsmUninit(IN struct ADAPTER *prAdapter) +{ + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + ASSERT_BREAK(prP2pDevFsmInfo != NULL); + + prP2pBssInfo = + prAdapter->aprBssInfo[prP2pDevFsmInfo->ucBssIndex]; + + cnmTimerStopTimer(prAdapter, + &(prP2pDevFsmInfo->rP2pFsmTimeoutTimer)); + + p2pFunCleanQueuedMgmtFrame(prAdapter, + &prP2pDevFsmInfo->rQueuedActionFrame); + + /* Abort device FSM */ + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, + P2P_DEV_STATE_IDLE); + p2pDevFsmRunEventAbort(prAdapter, prP2pDevFsmInfo); + + SET_NET_PWR_STATE_IDLE(prAdapter, prP2pBssInfo->ucBssIndex); + + /* Clear CmdQue */ + kalClearMgmtFramesByBssIdx(prAdapter->prGlueInfo, + prP2pBssInfo->ucBssIndex); + kalClearSecurityFramesByBssIdx(prAdapter->prGlueInfo, + prP2pBssInfo->ucBssIndex); + /* Clear PendingCmdQue */ + wlanReleasePendingCMDbyBssIdx(prAdapter, + prP2pBssInfo->ucBssIndex); + /* Clear PendingTxMsdu */ + nicFreePendingTxMsduInfo(prAdapter, + prP2pBssInfo->ucBssIndex, MSDU_REMOVE_BY_BSS_INDEX); + + /* Deactivate BSS. */ + UNSET_NET_ACTIVE(prAdapter, prP2pBssInfo->ucBssIndex); + + nicDeactivateNetwork(prAdapter, prP2pBssInfo->ucBssIndex); + + cnmFreeBssInfo(prAdapter, prP2pBssInfo); + } while (FALSE); + +#if 0 + struct P2P_FSM_INFO *prP2pFsmInfo = (struct P2P_FSM_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) 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. + */ + kalClearMgmtFramesByBssIdx(prAdapter->prGlueInfo, + NETWORK_TYPE_P2P_INDEX); + + /* Clear PendingCmdQue */ + wlanReleasePendingCMDbyBssIdx(prAdapter, + NETWORK_TYPE_P2P_INDEX); + + if (prP2pBssInfo->prBeacon) { + cnmMgtPktFree(prAdapter, prP2pBssInfo->prBeacon); + prP2pBssInfo->prBeacon = NULL; + } + } while (FALSE); + + return; +#endif +} /* p2pDevFsmUninit */ + +void +p2pDevFsmStateTransition(IN struct ADAPTER *prAdapter, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo, + IN enum ENUM_P2P_DEV_STATE eNextState) +{ + u_int8_t fgIsLeaveState = (u_int8_t) FALSE; + + ASSERT(prP2pDevFsmInfo); + if (!prP2pDevFsmInfo) { + DBGLOG(P2P, ERROR, "prP2pDevFsmInfo is NULL!\n"); + return; + } + + ASSERT(prP2pDevFsmInfo->ucBssIndex == prAdapter->ucP2PDevBssIdx); + if (prP2pDevFsmInfo->ucBssIndex != prAdapter->ucP2PDevBssIdx) { + log_dbg(P2P, ERROR, + "prP2pDevFsmInfo->ucBssIndex %d should be prAdapter->ucP2PDevBssIdx(%d)!\n", + prP2pDevFsmInfo->ucBssIndex, prAdapter->ucP2PDevBssIdx); + return; + } + + do { + if (!IS_BSS_ACTIVE( + prAdapter->aprBssInfo[prP2pDevFsmInfo->ucBssIndex])) { + if (!cnmP2PIsPermitted(prAdapter)) + return; + + SET_NET_ACTIVE(prAdapter, prP2pDevFsmInfo->ucBssIndex); + nicActivateNetwork(prAdapter, + prP2pDevFsmInfo->ucBssIndex); + } + + fgIsLeaveState = fgIsLeaveState ? FALSE : TRUE; + + if (!fgIsLeaveState) { + DBGLOG(P2P, STATE, + "[P2P_DEV]TRANSITION: [%s] -> [%s]\n", + apucDebugP2pDevState[prP2pDevFsmInfo->eCurrentState], + apucDebugP2pDevState[eNextState]); + + /* Transition into current state. */ + prP2pDevFsmInfo->eCurrentState = eNextState; + } + + switch (prP2pDevFsmInfo->eCurrentState) { + case P2P_DEV_STATE_IDLE: + if (!fgIsLeaveState) { + fgIsLeaveState = p2pDevStateInit_IDLE(prAdapter, + &prP2pDevFsmInfo->rChnlReqInfo, + &eNextState); + } else { + p2pDevStateAbort_IDLE(prAdapter); + } + break; + case P2P_DEV_STATE_SCAN: + if (!fgIsLeaveState) { + p2pDevStateInit_SCAN(prAdapter, + prP2pDevFsmInfo->ucBssIndex, + &prP2pDevFsmInfo->rScanReqInfo); + } else { + p2pDevStateAbort_SCAN(prAdapter, + prP2pDevFsmInfo); + } + break; + case P2P_DEV_STATE_REQING_CHANNEL: + if (!fgIsLeaveState) { + fgIsLeaveState = p2pDevStateInit_REQING_CHANNEL( + prAdapter, + prP2pDevFsmInfo->ucBssIndex, + &(prP2pDevFsmInfo->rChnlReqInfo), + &eNextState); + } else { + p2pDevStateAbort_REQING_CHANNEL(prAdapter, + &(prP2pDevFsmInfo->rChnlReqInfo), + eNextState); + } + break; + case P2P_DEV_STATE_CHNL_ON_HAND: + if (!fgIsLeaveState) { + p2pDevStateInit_CHNL_ON_HAND(prAdapter, + prAdapter->aprBssInfo + [prP2pDevFsmInfo->ucBssIndex], + prP2pDevFsmInfo, + &(prP2pDevFsmInfo->rChnlReqInfo)); + } else { + p2pDevStateAbort_CHNL_ON_HAND(prAdapter, + prAdapter->aprBssInfo + [prP2pDevFsmInfo->ucBssIndex], + prP2pDevFsmInfo, + &(prP2pDevFsmInfo->rChnlReqInfo), + eNextState); + } + break; + case P2P_DEV_STATE_OFF_CHNL_TX: + if (!fgIsLeaveState) { + fgIsLeaveState = p2pDevStateInit_OFF_CHNL_TX( + prAdapter, + prP2pDevFsmInfo, + &(prP2pDevFsmInfo->rChnlReqInfo), + &(prP2pDevFsmInfo->rMgmtTxInfo), + &eNextState); + } else { + p2pDevStateAbort_OFF_CHNL_TX( + prAdapter, + &(prP2pDevFsmInfo->rMgmtTxInfo), + &(prP2pDevFsmInfo->rChnlReqInfo), + eNextState); + } + break; + default: + /* Unexpected state. */ + ASSERT(FALSE); + break; + } + } while (fgIsLeaveState); +} /* p2pDevFsmStateTransition */ + +void p2pDevFsmRunEventAbort(IN struct ADAPTER *prAdapter, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo) +{ + do { + ASSERT_BREAK((prAdapter != NULL) + && (prP2pDevFsmInfo != NULL)); + + if (prP2pDevFsmInfo->eCurrentState != P2P_DEV_STATE_IDLE) { + /* Get into IDLE state. */ + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, + P2P_DEV_STATE_IDLE); + } + + /* Abort IDLE. */ + p2pDevStateAbort_IDLE(prAdapter); + } while (FALSE); +} /* p2pDevFsmRunEventAbort */ + +void p2pDevFsmRunEventTimeout(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr) +{ + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) ulParamPtr; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pDevFsmInfo != NULL)); + + switch (prP2pDevFsmInfo->eCurrentState) { + case P2P_DEV_STATE_IDLE: + /* TODO: IDLE timeout for low power mode. */ + break; + case P2P_DEV_STATE_CHNL_ON_HAND: + if (prAdapter->prP2pInfo->ucExtendChanFlag) { + prAdapter->prP2pInfo->ucExtendChanFlag = 0; + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, P2P_DEV_STATE_IDLE); + break; + } + switch (prAdapter->prP2pInfo->eConnState) { + case P2P_CNN_GO_NEG_REQ: + case P2P_CNN_GO_NEG_RESP: + case P2P_CNN_INVITATION_REQ: + case P2P_CNN_DEV_DISC_REQ: + case P2P_CNN_PROV_DISC_REQ: + DBGLOG(P2P, INFO, + "P2P: re-enter CHNL_ON_HAND with state: %d\n", + prAdapter->prP2pInfo->eConnState); + prAdapter->prP2pInfo->ucExtendChanFlag = 1; + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, + P2P_DEV_STATE_CHNL_ON_HAND); + break; + case P2P_CNN_NORMAL: + case P2P_CNN_GO_NEG_CONF: + case P2P_CNN_INVITATION_RESP: + case P2P_CNN_DEV_DISC_RESP: + case P2P_CNN_PROV_DISC_RES: + default: + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, + P2P_DEV_STATE_IDLE); + break; + } + break; + default: + ASSERT(FALSE); + log_dbg(P2P, ERROR, + "Current P2P Dev State %d is unexpected for FSM timeout event.\n", + prP2pDevFsmInfo->eCurrentState); + break; + } + } while (FALSE); +} /* p2pDevFsmRunEventTimeout */ + +/*================ Message Event =================*/ +void p2pDevFsmRunEventScanRequest(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_P2P_SCAN_REQUEST *prP2pScanReqMsg = + (struct MSG_P2P_SCAN_REQUEST *) NULL; + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) NULL; + struct P2P_SCAN_REQ_INFO *prScanReqInfo = + (struct P2P_SCAN_REQ_INFO *) NULL; + uint32_t u4ChnlListSize = 0; + struct P2P_SSID_STRUCT *prP2pSsidStruct = + (struct P2P_SSID_STRUCT *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + if (prP2pDevFsmInfo == NULL) + break; + + if (prP2pDevFsmInfo->eCurrentState != P2P_DEV_STATE_IDLE) + p2pDevFsmRunEventAbort(prAdapter, prP2pDevFsmInfo); + + prP2pScanReqMsg = (struct MSG_P2P_SCAN_REQUEST *) prMsgHdr; + prScanReqInfo = &(prP2pDevFsmInfo->rScanReqInfo); + + DBGLOG(P2P, TRACE, "p2pDevFsmRunEventScanRequest\n"); + + /* Do we need to be in IDLE state? */ + /* p2pDevFsmRunEventAbort(prAdapter, prP2pDevFsmInfo); */ + + ASSERT(prScanReqInfo->fgIsScanRequest == FALSE); + + prScanReqInfo->fgIsAbort = TRUE; + prScanReqInfo->eScanType = prP2pScanReqMsg->eScanType; + prScanReqInfo->u2PassiveDewellTime = 0; + + if (prP2pScanReqMsg->u4NumChannel) { + 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(struct RF_CHANNEL_INFO) + * prScanReqInfo->ucNumChannelList; + kalMemCopy(prScanReqInfo->arScanChannelList, + prP2pScanReqMsg->arChannelListInfo, + u4ChnlListSize); + } else { + /* If channel number is ZERO. + * It means do a FULL channel scan. + */ + prScanReqInfo->eChannelSet = SCAN_CHANNEL_FULL; + } + + /* SSID */ + prP2pSsidStruct = prP2pScanReqMsg->prSSID; + for (prScanReqInfo->ucSsidNum = 0; + prScanReqInfo->ucSsidNum + < prP2pScanReqMsg->i4SsidNum; + prScanReqInfo->ucSsidNum++) { + kalMemCopy( + prScanReqInfo->arSsidStruct + [prScanReqInfo->ucSsidNum].aucSsid, + prP2pSsidStruct->aucSsid, + prP2pSsidStruct->ucSsidLen); + + prScanReqInfo->arSsidStruct + [prScanReqInfo->ucSsidNum].ucSsidLen = + prP2pSsidStruct->ucSsidLen; + + prP2pSsidStruct++; + } + + /* IE Buffer */ + kalMemCopy(prScanReqInfo->aucIEBuf, + prP2pScanReqMsg->pucIEBuf, + prP2pScanReqMsg->u4IELen); + + prScanReqInfo->u4BufLength = prP2pScanReqMsg->u4IELen; + + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, + P2P_DEV_STATE_SCAN); + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventScanRequest */ + +void p2pDevFsmRunEventScanAbort(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) NULL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + DBGLOG(P2P, TRACE, "p2pDevFsmRunEventScanAbort\n"); + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + if (prP2pDevFsmInfo->eCurrentState == P2P_DEV_STATE_SCAN) { + struct P2P_SCAN_REQ_INFO *prScanReqInfo = + &(prP2pDevFsmInfo->rScanReqInfo); + + prScanReqInfo->fgIsAbort = TRUE; + + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, + P2P_DEV_STATE_IDLE); + } + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pDevFsmRunEventScanAbort */ + +void +p2pDevFsmRunEventScanDone(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo) +{ + struct MSG_SCN_SCAN_DONE *prScanDoneMsg = + (struct MSG_SCN_SCAN_DONE *) prMsgHdr; + struct P2P_SCAN_REQ_INFO *prP2pScanReqInfo = + (struct P2P_SCAN_REQ_INFO *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prMsgHdr != NULL) + && (prP2pDevFsmInfo != NULL)); + + if (!prP2pDevFsmInfo) { + DBGLOG(P2P, ERROR, + "prP2pDevFsmInfo is null, maybe remove p2p already\n"); + break; + } + + prP2pScanReqInfo = &(prP2pDevFsmInfo->rScanReqInfo); + + if (prScanDoneMsg->ucSeqNum + != prP2pScanReqInfo->ucSeqNumOfScnMsg) { + DBGLOG(P2P, TRACE, + "P2P Scan Done SeqNum:%d <-> P2P Dev FSM Scan SeqNum:%d", + prScanDoneMsg->ucSeqNum, + prP2pScanReqInfo->ucSeqNumOfScnMsg); + break; + } + + ASSERT_BREAK(prScanDoneMsg->ucBssIndex + == prP2pDevFsmInfo->ucBssIndex); + + prP2pScanReqInfo->fgIsAbort = FALSE; + prP2pScanReqInfo->fgIsScanRequest = FALSE; + + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, + P2P_DEV_STATE_IDLE); + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventScanDone */ + +void p2pDevFsmRunEventChannelRequest(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) NULL; + struct P2P_CHNL_REQ_INFO *prChnlReqInfo = + (struct P2P_CHNL_REQ_INFO *) NULL; + u_int8_t fgIsChnlFound = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + if (prP2pDevFsmInfo == NULL) { + DBGLOG(P2P, WARN, "uninitialized p2p Dev fsm\n"); + break; + } + + prChnlReqInfo = &(prP2pDevFsmInfo->rChnlReqInfo); + + DBGLOG(P2P, TRACE, "p2pDevFsmRunEventChannelRequest\n"); + + if (!LINK_IS_EMPTY(&prChnlReqInfo->rP2pChnlReqLink)) { + struct LINK_ENTRY *prLinkEntry = + (struct LINK_ENTRY *) NULL; + struct MSG_P2P_CHNL_REQUEST *prP2pMsgChnlReq = + (struct MSG_P2P_CHNL_REQUEST *) NULL; + + LINK_FOR_EACH(prLinkEntry, + &prChnlReqInfo->rP2pChnlReqLink) { + + prP2pMsgChnlReq = + (struct MSG_P2P_CHNL_REQUEST *) + LINK_ENTRY(prLinkEntry, + struct MSG_HDR, rLinkEntry); + + if (prP2pMsgChnlReq->eChnlReqType + == CH_REQ_TYPE_P2P_LISTEN) { + LINK_REMOVE_KNOWN_ENTRY( + &prChnlReqInfo->rP2pChnlReqLink, + prLinkEntry); + cnmMemFree(prAdapter, prP2pMsgChnlReq); + /* DBGLOG(P2P, TRACE, */ + /* ("p2pDevFsmRunEventChannelAbort: + * Channel Abort, cookie found:%d\n", + */ + /* prChnlAbortMsg->u8Cookie)); */ + fgIsChnlFound = TRUE; + break; + } + } + } + + /* Queue the channel request. */ + LINK_INSERT_TAIL(&(prChnlReqInfo->rP2pChnlReqLink), + &(prMsgHdr->rLinkEntry)); + prMsgHdr = NULL; + + /* If channel is not requested, + * it may due to channel is released. + */ + if ((!fgIsChnlFound) + && (prChnlReqInfo->eChnlReqType + == CH_REQ_TYPE_P2P_LISTEN) + && (prChnlReqInfo->fgIsChannelRequested)) { + + ASSERT( + (prP2pDevFsmInfo->eCurrentState + == P2P_DEV_STATE_REQING_CHANNEL) || + (prP2pDevFsmInfo->eCurrentState + == P2P_DEV_STATE_CHNL_ON_HAND)); + + p2pDevFsmRunEventAbort(prAdapter, prP2pDevFsmInfo); + + break; + } + + if (prP2pDevFsmInfo->eCurrentState == P2P_DEV_STATE_IDLE) { + /* Re-enter IDLE state would trigger channel request. */ + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, P2P_DEV_STATE_IDLE); + } + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventChannelRequest */ + +void p2pDevFsmRunEventChannelAbort(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) NULL; + struct MSG_P2P_CHNL_ABORT *prChnlAbortMsg = + (struct MSG_P2P_CHNL_ABORT *) NULL; + struct P2P_CHNL_REQ_INFO *prChnlReqInfo = + (struct P2P_CHNL_REQ_INFO *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prChnlAbortMsg = (struct MSG_P2P_CHNL_ABORT *) prMsgHdr; + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + if (prP2pDevFsmInfo == NULL) + break; + + prChnlReqInfo = &(prP2pDevFsmInfo->rChnlReqInfo); + + DBGLOG(P2P, TRACE, "p2pDevFsmRunEventChannelAbort\n"); + + p2pFunCleanQueuedMgmtFrame(prAdapter, + &prP2pDevFsmInfo->rQueuedActionFrame); + + /* If channel is not requested, + * it may due to channel is released. + */ + if ((prChnlAbortMsg->u8Cookie == prChnlReqInfo->u8Cookie) + && (prChnlReqInfo->fgIsChannelRequested)) { + ASSERT( + (prP2pDevFsmInfo->eCurrentState + == P2P_DEV_STATE_REQING_CHANNEL) || + (prP2pDevFsmInfo->eCurrentState + == P2P_DEV_STATE_CHNL_ON_HAND)); + + /* + * If cancel-roc cmd is called from Supplicant + * while driver is waiting for FW's channel grant event, + * roc event must be returned to Supplicant + * first to reset Supplicant's variables + * and then transition to idle state. + */ + if (prP2pDevFsmInfo->eCurrentState + == P2P_DEV_STATE_REQING_CHANNEL) { + kalP2PIndicateChannelReady( + prAdapter->prGlueInfo, + prChnlReqInfo->u8Cookie, + prChnlReqInfo->ucReqChnlNum, + prChnlReqInfo->eBand, + prChnlReqInfo->eChnlSco, + prChnlReqInfo->u4MaxInterval); + kalP2PIndicateChannelExpired( + prAdapter->prGlueInfo, + prChnlReqInfo->u8Cookie, + prChnlReqInfo->ucReqChnlNum, + prChnlReqInfo->eBand, + prChnlReqInfo->eChnlSco); + } + p2pDevFsmRunEventAbort(prAdapter, prP2pDevFsmInfo); + + break; + } else if (!LINK_IS_EMPTY(&prChnlReqInfo->rP2pChnlReqLink)) { + struct LINK_ENTRY *prLinkEntry = + (struct LINK_ENTRY *) NULL; + struct MSG_P2P_CHNL_REQUEST *prP2pMsgChnlReq = + (struct MSG_P2P_CHNL_REQUEST *) NULL; + + LINK_FOR_EACH(prLinkEntry, + &prChnlReqInfo->rP2pChnlReqLink) { + prP2pMsgChnlReq = + (struct MSG_P2P_CHNL_REQUEST *) + LINK_ENTRY(prLinkEntry, + struct MSG_HDR, rLinkEntry); + + if (prP2pMsgChnlReq->u8Cookie + == prChnlAbortMsg->u8Cookie) { + LINK_REMOVE_KNOWN_ENTRY( + &prChnlReqInfo->rP2pChnlReqLink, + prLinkEntry); + log_dbg(P2P, TRACE, + "p2pDevFsmRunEventChannelAbort: Channel Abort, cookie found:0x%llx\n", + prChnlAbortMsg->u8Cookie); + kalP2PIndicateChannelReady( + prAdapter->prGlueInfo, + prP2pMsgChnlReq->u8Cookie, + prP2pMsgChnlReq->rChannelInfo + .ucChannelNum, + prP2pMsgChnlReq->rChannelInfo + .eBand, + prP2pMsgChnlReq->eChnlSco, + prP2pMsgChnlReq->u4Duration); + kalP2PIndicateChannelExpired( + prAdapter->prGlueInfo, + prP2pMsgChnlReq->u8Cookie, + prP2pMsgChnlReq->rChannelInfo + .ucChannelNum, + prP2pMsgChnlReq->rChannelInfo + .eBand, + prP2pMsgChnlReq->eChnlSco); + cnmMemFree(prAdapter, prP2pMsgChnlReq); + break; + } + } + } else { + log_dbg(P2P, WARN, + "p2pDevFsmRunEventChannelAbort: Channel Abort Fail, cookie not found:0x%llx\n", + prChnlAbortMsg->u8Cookie); + } + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventChannelAbort */ + +void +p2pDevFsmRunEventChnlGrant(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo) +{ + struct MSG_CH_GRANT *prMsgChGrant = (struct MSG_CH_GRANT *) NULL; + struct P2P_CHNL_REQ_INFO *prChnlReqInfo = + (struct P2P_CHNL_REQ_INFO *) NULL; + + do { + ASSERT((prAdapter != NULL) + && (prMsgHdr != NULL) + && (prP2pDevFsmInfo != NULL)); + + if ((prAdapter == NULL) + || (prMsgHdr == NULL) + || (prP2pDevFsmInfo == NULL)) + break; + + prMsgChGrant = (struct MSG_CH_GRANT *) prMsgHdr; + prChnlReqInfo = &(prP2pDevFsmInfo->rChnlReqInfo); + + if ((prMsgChGrant->ucTokenID + != prChnlReqInfo->ucSeqNumOfChReq) + || (!prChnlReqInfo->fgIsChannelRequested)) { + break; + } + + ASSERT(prMsgChGrant->ucPrimaryChannel + == prChnlReqInfo->ucReqChnlNum); + ASSERT(prMsgChGrant->eReqType + == prChnlReqInfo->eChnlReqType); + ASSERT(prMsgChGrant->u4GrantInterval + == prChnlReqInfo->u4MaxInterval); + + prChnlReqInfo->u4MaxInterval = prMsgChGrant->u4GrantInterval; + + if (prMsgChGrant->eReqType == CH_REQ_TYPE_P2P_LISTEN) { + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, + P2P_DEV_STATE_CHNL_ON_HAND); + } else { + ASSERT(prMsgChGrant->eReqType + == CH_REQ_TYPE_OFFCHNL_TX); + + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, + P2P_DEV_STATE_OFF_CHNL_TX); + } + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventChnlGrant */ + +void p2pDevFsmRunEventMgmtTx(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) NULL; + struct MSG_P2P_MGMT_TX_REQUEST *prMgmtTxMsg = + (struct MSG_P2P_MGMT_TX_REQUEST *) NULL; + struct P2P_CHNL_REQ_INFO *prP2pChnlReqInfo = + (struct P2P_CHNL_REQ_INFO *) NULL; + struct P2P_MGMT_TX_REQ_INFO *prP2pMgmtTxReqInfo = + (struct P2P_MGMT_TX_REQ_INFO *) NULL; + + prMgmtTxMsg = (struct MSG_P2P_MGMT_TX_REQUEST *) prMsgHdr; + + if ((prMgmtTxMsg->ucBssIdx != prAdapter->ucP2PDevBssIdx) && + (IS_NET_ACTIVE(prAdapter, prMgmtTxMsg->ucBssIdx))) { + DBGLOG(P2P, TRACE, " Role Interface\n"); + p2pFuncTxMgmtFrame(prAdapter, + prMgmtTxMsg->ucBssIdx, + prMgmtTxMsg->prMgmtMsduInfo, + prMgmtTxMsg->fgNoneCckRate); + goto error; + } + + DBGLOG(P2P, TRACE, "p2pDevFsmRunEventMgmtTx with Device Interface\n"); + + prMgmtTxMsg->ucBssIdx = prAdapter->ucP2PDevBssIdx; + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + if (prP2pDevFsmInfo == NULL) { + DBGLOG(P2P, ERROR, "prP2pDevFsmInfo is NULL!\n"); + goto error; + } + + prP2pChnlReqInfo = &(prP2pDevFsmInfo->rChnlReqInfo); + prP2pMgmtTxReqInfo = &(prP2pDevFsmInfo->rMgmtTxInfo); + + if ((!prMgmtTxMsg->fgIsOffChannel) || + ((prP2pDevFsmInfo->eCurrentState == P2P_DEV_STATE_OFF_CHNL_TX) && + (LINK_IS_EMPTY(&prP2pMgmtTxReqInfo->rP2pTxReqLink)))) { + p2pFuncTxMgmtFrame(prAdapter, + prP2pDevFsmInfo->ucBssIndex, + prMgmtTxMsg->prMgmtMsduInfo, + prMgmtTxMsg->fgNoneCckRate); + } else { + struct P2P_OFF_CHNL_TX_REQ_INFO *prOffChnlTxReq = + (struct P2P_OFF_CHNL_TX_REQ_INFO *) NULL; + + prOffChnlTxReq = cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(struct P2P_OFF_CHNL_TX_REQ_INFO)); + + if (prOffChnlTxReq == NULL) { + DBGLOG(P2P, ERROR, + "Can not serve TX request due to MSG buffer not enough\n"); + ASSERT(FALSE); + goto error; + } + + prOffChnlTxReq->prMgmtTxMsdu = prMgmtTxMsg->prMgmtMsduInfo; + prOffChnlTxReq->fgNoneCckRate = prMgmtTxMsg->fgNoneCckRate; + kalMemCopy(&prOffChnlTxReq->rChannelInfo, + &prMgmtTxMsg->rChannelInfo, + sizeof(struct RF_CHANNEL_INFO)); + prOffChnlTxReq->eChnlExt = prMgmtTxMsg->eChnlExt; + prOffChnlTxReq->fgIsWaitRsp = prMgmtTxMsg->fgIsWaitRsp; + + LINK_INSERT_TAIL(&prP2pMgmtTxReqInfo->rP2pTxReqLink, + &prOffChnlTxReq->rLinkEntry); + + /* Channel Request if needed. */ + if (prP2pDevFsmInfo->eCurrentState + != P2P_DEV_STATE_OFF_CHNL_TX) { + + struct MSG_P2P_CHNL_REQUEST *prP2pMsgChnlReq = + (struct MSG_P2P_CHNL_REQUEST *) NULL; + + prP2pMsgChnlReq = cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_P2P_CHNL_REQUEST)); + + if (prP2pMsgChnlReq == NULL) { + cnmMemFree(prAdapter, prOffChnlTxReq); + ASSERT(FALSE); + DBGLOG(P2P, ERROR, + "Not enough MSG buffer for channel request\n"); + goto error; + } + + prP2pMsgChnlReq->eChnlReqType = CH_REQ_TYPE_OFFCHNL_TX; + + /* Not used in TX OFFCHNL REQ fields. */ + prP2pMsgChnlReq->rMsgHdr.eMsgId = MID_MNY_P2P_CHNL_REQ; + prP2pMsgChnlReq->u8Cookie = 0; + prP2pMsgChnlReq->u4Duration = + P2P_OFF_CHNL_TX_DEFAULT_TIME_MS; + + kalMemCopy(&prP2pMsgChnlReq->rChannelInfo, + &prMgmtTxMsg->rChannelInfo, + sizeof(struct RF_CHANNEL_INFO)); + + prP2pMsgChnlReq->eChnlSco = prMgmtTxMsg->eChnlExt; + + p2pDevFsmRunEventChannelRequest(prAdapter, + (struct MSG_HDR *) prP2pMsgChnlReq); + } + } + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventMgmtTx */ + +uint32_t +p2pDevFsmRunEventMgmtFrameTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + u_int8_t fgIsSuccess = FALSE; + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) NULL; + uint64_t *pu8GlCookie = (uint64_t *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + if (!prMsduInfo->prPacket) { + DBGLOG(P2P, WARN, + "Freed Msdu, do not indicate to host\n"); + break; + } + + pu8GlCookie = + (uint64_t *) ((unsigned long) prMsduInfo->prPacket + + (unsigned long) prMsduInfo->u2FrameLength + + MAC_TX_RESERVED_FIELD); + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + /* prP2pDevFsmInfo may be freed. */ + if (prP2pDevFsmInfo && (prP2pDevFsmInfo->eCurrentState == + P2P_DEV_STATE_OFF_CHNL_TX)) + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, + P2P_DEV_STATE_OFF_CHNL_TX); + + if (rTxDoneStatus != TX_RESULT_SUCCESS) { + DBGLOG(P2P, INFO, + "Mgmt Frame TX Fail, Status: %d. cookie: 0x%llx\n", + rTxDoneStatus, *pu8GlCookie); + } else { + fgIsSuccess = TRUE; + DBGLOG(P2P, INFO, + "Mgmt Frame TX Done. cookie: 0x%llx\n", + *pu8GlCookie); + } + + kalP2PIndicateMgmtTxStatus(prAdapter->prGlueInfo, + prMsduInfo, + fgIsSuccess); + } while (FALSE); + + return WLAN_STATUS_SUCCESS; +} /* p2pDevFsmRunEventMgmtFrameTxDone */ + +void p2pDevFsmRunEventMgmtFrameRegister(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + /* TODO: RX Filter Management. */ + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventMgmtFrameRegister */ + +void p2pDevFsmRunEventActiveDevBss(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + if (prP2pDevFsmInfo->eCurrentState + == P2P_DEV_STATE_IDLE) { + /* Get into IDLE state to let BSS be active + * and do not Deactive. + */ + p2pDevFsmStateTransition(prAdapter, + prP2pDevFsmInfo, + P2P_DEV_STATE_IDLE); + } + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventActiveDevBss */ + +void +p2pDevFsmNotifyP2pRx(IN struct ADAPTER *prAdapter, uint8_t p2pFrameType, + u_int8_t *prFgBufferFrame) +{ + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) NULL; + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + if (prP2pDevFsmInfo->eCurrentState != P2P_DEV_STATE_CHNL_ON_HAND) { + switch (p2pFrameType) { + case P2P_INVITATION_REQ: + *prFgBufferFrame = TRUE; + break; + default: + break; + } + return; + } + + if (prAdapter->prP2pInfo->eConnState != P2P_CNN_NORMAL) + return; + + switch (p2pFrameType) { + case P2P_GO_NEG_REQ: + case P2P_GO_NEG_RESP: + case P2P_INVITATION_REQ: + case P2P_DEV_DISC_REQ: + case P2P_PROV_DISC_REQ: + DBGLOG(P2P, INFO, + "Extend channel duration, p2pFrameType: %d.\n", + p2pFrameType); + prAdapter->prP2pInfo->eConnState = p2pFrameType + 1; + break; + default: + break; + } +} + +#endif /* RunEventWfdSettingUpdate */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_dev_state.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_dev_state.c new file mode 100644 index 0000000000000..df1cec7051334 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_dev_state.c @@ -0,0 +1,438 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#include "precomp.h" + +u_int8_t +p2pDevStateInit_IDLE(IN struct ADAPTER *prAdapter, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + OUT enum ENUM_P2P_DEV_STATE *peNextState) +{ + u_int8_t fgIsTransition = FALSE, fgIsShareInterface = TRUE; + uint32_t u4Idx = 0; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prChnlReqInfo) && (peNextState != NULL)); + + if (!LINK_IS_EMPTY(&(prChnlReqInfo->rP2pChnlReqLink))) { + fgIsTransition = TRUE; + *peNextState = P2P_DEV_STATE_REQING_CHANNEL; + break; + } + + /* Check the interface shared by P2P_DEV and P2P_ROLE or not? */ + /* If not shared, we shall let BSSID4 alive + * to receive PROVISION REQUEST from GC + */ + prGlueInfo = prAdapter->prGlueInfo; + if (prGlueInfo) { + for (u4Idx = 0; u4Idx < KAL_P2P_NUM; u4Idx++) { + if ((prGlueInfo->prP2PInfo[u4Idx] != NULL) && + (prGlueInfo->prP2PInfo[u4Idx]->aprRoleHandler + != NULL) && + (prGlueInfo->prP2PInfo[u4Idx]->aprRoleHandler + != + prGlueInfo->prP2PInfo[u4Idx]->prDevHandler)) { + fgIsShareInterface = FALSE; + break; + } + } + } + /************************* End *************************/ + + if (fgIsShareInterface) { + /* Stay in IDLE state. */ + UNSET_NET_ACTIVE(prAdapter, prAdapter->ucP2PDevBssIdx); + nicDeactivateNetwork(prAdapter, + prAdapter->ucP2PDevBssIdx); + } + } while (FALSE); + + return fgIsTransition; +} /* p2pDevStateInit_IDLE */ + +void p2pDevStateAbort_IDLE(IN struct ADAPTER *prAdapter) +{ + /* Currently Aobrt IDLE do nothing. */ +} /* p2pDevStateAbort_IDLE */ + +u_int8_t +p2pDevStateInit_REQING_CHANNEL(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + OUT enum ENUM_P2P_DEV_STATE *peNextState) +{ + u_int8_t fgIsTransition = FALSE; + struct MSG_P2P_CHNL_REQUEST *prP2pMsgChnlReq = + (struct MSG_P2P_CHNL_REQUEST *) NULL; + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; +#if CFG_SUPPORT_DBDC + struct CNM_DBDC_CAP rDbdcCap; +#endif /*CFG_SUPPORT_DBDC*/ + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prChnlReqInfo != NULL) && (peNextState != NULL)); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + + if (LINK_IS_EMPTY(&(prChnlReqInfo->rP2pChnlReqLink))) { + /* NO Channel Request Pending. */ + DBGLOG(P2P, ERROR, + "NO Pending Channel Request, but enter Req Channel State\n"); + fgIsTransition = TRUE; + *peNextState = P2P_DEV_STATE_IDLE; + break; + } + + LINK_REMOVE_HEAD(&(prChnlReqInfo->rP2pChnlReqLink), + prP2pMsgChnlReq, struct MSG_P2P_CHNL_REQUEST *); + + if (!prP2pMsgChnlReq) + break; + + if (prBssInfo->fgIsWmmInited == FALSE) + prBssInfo->ucWmmQueSet = MAX_HW_WMM_INDEX; + prBssInfo->eBand = prP2pMsgChnlReq->rChannelInfo.eBand; + +#if CFG_SUPPORT_DBDC + kalMemZero(&rDbdcCap, sizeof(struct CNM_DBDC_CAP)); + + cnmGetDbdcCapability(prAdapter, + prBssInfo->ucBssIndex, + prP2pMsgChnlReq->rChannelInfo.eBand, + prP2pMsgChnlReq->rChannelInfo.ucChannelNum, + wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex), + &rDbdcCap); + + prBssInfo->ucNss = rDbdcCap.ucNss; +#endif /*CFG_SUPPORT_DBDC*/ + prChnlReqInfo->u4MaxInterval = prP2pMsgChnlReq->u4Duration; + prChnlReqInfo->ucReqChnlNum = + prP2pMsgChnlReq->rChannelInfo.ucChannelNum; + prChnlReqInfo->eChnlSco = prP2pMsgChnlReq->eChnlSco; + prChnlReqInfo->eBand = prP2pMsgChnlReq->rChannelInfo.eBand; + prChnlReqInfo->u8Cookie = prP2pMsgChnlReq->u8Cookie; + prChnlReqInfo->eChnlReqType = prP2pMsgChnlReq->eChnlReqType; + prChnlReqInfo->eChannelWidth = prBssInfo->ucVhtChannelWidth; + prChnlReqInfo->ucCenterFreqS1 = + prBssInfo->ucVhtChannelFrequencyS1; + prChnlReqInfo->ucCenterFreqS2 = + prBssInfo->ucVhtChannelFrequencyS2; + + p2pFuncAcquireCh(prAdapter, ucBssIdx, prChnlReqInfo); + } while (FALSE); + + if (prP2pMsgChnlReq) + cnmMemFree(prAdapter, prP2pMsgChnlReq); + + return fgIsTransition; +} /* p2pDevStateInit_REQING_CHANNEL */ + +void +p2pDevStateAbort_REQING_CHANNEL(IN struct ADAPTER *prAdapter, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN enum ENUM_P2P_DEV_STATE eNextState) +{ + do { + ASSERT_BREAK((prAdapter != NULL) + && (prChnlReqInfo != NULL) + && (eNextState < P2P_DEV_STATE_NUM)); + + switch (eNextState) { + case P2P_DEV_STATE_IDLE: + /* Channel abort case. */ + p2pFuncReleaseCh(prAdapter, + prAdapter->ucP2PDevBssIdx, prChnlReqInfo); + break; + case P2P_DEV_STATE_CHNL_ON_HAND: + /* Channel on hand case. */ + break; + default: + /* Un-expected state transition. */ + DBGLOG(P2P, ERROR, + "Unexpected State Transition(eNextState=%d)\n", + eNextState); + ASSERT(FALSE); + break; + } + } while (FALSE); +} /* p2pDevStateAbort_REQING_CHANNEL */ + +void +p2pDevStateInit_CHNL_ON_HAND(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo) +{ + do { + uint32_t u4TimeoutMs = 0; + + ASSERT_BREAK((prAdapter != NULL) + && (prP2pDevFsmInfo != NULL) + && (prChnlReqInfo != NULL)); + + ASSERT(prChnlReqInfo->eChnlReqType == CH_REQ_TYPE_P2P_LISTEN); + + prChnlReqInfo->ucOriChnlNum = prP2pBssInfo->ucPrimaryChannel; + prChnlReqInfo->eOriBand = prP2pBssInfo->eBand; + prChnlReqInfo->eOriChnlSco = prP2pBssInfo->eBssSCO; + + prP2pBssInfo->ucPrimaryChannel = prChnlReqInfo->ucReqChnlNum; + prP2pBssInfo->eBand = prChnlReqInfo->eBand; + prP2pBssInfo->eBssSCO = prChnlReqInfo->eChnlSco; + + if (prAdapter->prP2pInfo->ucExtendChanFlag) + u4TimeoutMs = P2P_DEV_EXTEND_CHAN_TIME; + else + u4TimeoutMs = prChnlReqInfo->u4MaxInterval; + + log_dbg(P2P, INFO, + "Start channel on hand timer, Cookie: 0x%llx, Interval: %d\n", + prChnlReqInfo->u8Cookie, u4TimeoutMs); + + cnmTimerStartTimer(prAdapter, + &(prP2pDevFsmInfo->rP2pFsmTimeoutTimer), + u4TimeoutMs); + + /* Do NOT report channel ready event again for extension case */ + if (!prAdapter->prP2pInfo->ucExtendChanFlag) { + kalP2PIndicateChannelReady(prAdapter->prGlueInfo, + prChnlReqInfo->u8Cookie, + prChnlReqInfo->ucReqChnlNum, + prChnlReqInfo->eBand, + prChnlReqInfo->eChnlSco, + prChnlReqInfo->u4MaxInterval); + if (prP2pDevFsmInfo->rQueuedActionFrame.u2Length > 0) { + kalP2pIndicateQueuedMgmtFrame( + prAdapter->prGlueInfo, + &prP2pDevFsmInfo->rQueuedActionFrame); + p2pFunCleanQueuedMgmtFrame(prAdapter, + &prP2pDevFsmInfo->rQueuedActionFrame); + } + } + } while (FALSE); +} /* p2pDevStateInit_CHNL_ON_HAND */ + +void +p2pDevStateAbort_CHNL_ON_HAND(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN enum ENUM_P2P_DEV_STATE eNextState) +{ + do { + ASSERT_BREAK((prAdapter != NULL) || (prChnlReqInfo != NULL)); + + cnmTimerStopTimer(prAdapter, + &(prP2pDevFsmInfo->rP2pFsmTimeoutTimer)); + + prP2pBssInfo->ucPrimaryChannel = prChnlReqInfo->ucOriChnlNum; + prP2pBssInfo->eBand = prChnlReqInfo->eOriBand; + prP2pBssInfo->eBssSCO = prChnlReqInfo->eOriChnlSco; + + if (eNextState != P2P_DEV_STATE_CHNL_ON_HAND) { + kalP2PIndicateChannelExpired(prAdapter->prGlueInfo, + prChnlReqInfo->u8Cookie, + prChnlReqInfo->ucReqChnlNum, + prChnlReqInfo->eBand, + prChnlReqInfo->eChnlSco); + + p2pFuncReleaseCh(prAdapter, + prP2pDevFsmInfo->ucBssIndex, prChnlReqInfo); + p2pFunCleanQueuedMgmtFrame(prAdapter, + &prP2pDevFsmInfo->rQueuedActionFrame); + } + } while (FALSE); +} /* p2pDevStateAbort_CHNL_ON_HAND */ + +void p2pDevStateInit_SCAN(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct P2P_SCAN_REQ_INFO *prScanReqInfo) +{ + do { + ASSERT_BREAK((prAdapter != NULL) && (prScanReqInfo != NULL)); + + prScanReqInfo->fgIsScanRequest = TRUE; + + p2pFuncRequestScan(prAdapter, ucBssIndex, prScanReqInfo); + } while (FALSE); +} /* p2pDevStateInit_CHNL_ON_HAND */ + +void p2pDevStateAbort_SCAN(IN struct ADAPTER *prAdapter, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo) +{ + struct P2P_SCAN_REQ_INFO *prScanInfo = + (struct P2P_SCAN_REQ_INFO *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prP2pDevFsmInfo != NULL)); + + prScanInfo = &(prP2pDevFsmInfo->rScanReqInfo); + + p2pFuncCancelScan(prAdapter, + prP2pDevFsmInfo->ucBssIndex, + prScanInfo); + + kalP2PIndicateScanDone(prAdapter->prGlueInfo, + 0xFF, + prScanInfo->fgIsAbort); + } while (FALSE); +} /* p2pDevStateAbort_CHNL_ON_HAND */ + +u_int8_t +p2pDevStateInit_OFF_CHNL_TX(IN struct ADAPTER *prAdapter, + IN struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN struct P2P_MGMT_TX_REQ_INFO *prP2pMgmtTxInfo, + OUT enum ENUM_P2P_DEV_STATE *peNextState) +{ + struct P2P_OFF_CHNL_TX_REQ_INFO *prP2pOffChnlTxPkt = + (struct P2P_OFF_CHNL_TX_REQ_INFO *) NULL; + u_int8_t fgIsTransition = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pMgmtTxInfo != NULL) + && (peNextState != NULL)); + + if (!LINK_IS_EMPTY(&(prP2pMgmtTxInfo->rP2pTxReqLink))) { + prP2pOffChnlTxPkt = + LINK_PEEK_HEAD(&(prP2pMgmtTxInfo->rP2pTxReqLink), + struct P2P_OFF_CHNL_TX_REQ_INFO, rLinkEntry); + + if (prP2pOffChnlTxPkt == NULL) { + DBGLOG(P2P, ERROR, + "Fetal Error, Link not empty but get NULL pointer.\n"); + ASSERT(FALSE); + break; + } + + if (prChnlReqInfo->ucReqChnlNum + != + prP2pOffChnlTxPkt->rChannelInfo.ucChannelNum) { + + prChnlReqInfo->ucReqChnlNum = + prP2pOffChnlTxPkt->rChannelInfo + .ucChannelNum; + prChnlReqInfo->eChnlSco = + prP2pOffChnlTxPkt->eChnlExt; + prChnlReqInfo->eBand = + prP2pOffChnlTxPkt->rChannelInfo.eBand; + prChnlReqInfo->u8Cookie = 0; + prChnlReqInfo->eChannelWidth = CW_20_40MHZ; + prChnlReqInfo->ucCenterFreqS1 = 0; + prChnlReqInfo->ucCenterFreqS2 = 0; + + ASSERT(prChnlReqInfo->eChnlReqType + == CH_REQ_TYPE_OFFCHNL_TX); + + p2pFuncAcquireCh(prAdapter, + prP2pDevFsmInfo->ucBssIndex, + prChnlReqInfo); + } else { + LINK_REMOVE_HEAD( + &(prP2pMgmtTxInfo->rP2pTxReqLink), + prP2pOffChnlTxPkt, + struct P2P_OFF_CHNL_TX_REQ_INFO *); + + p2pFuncTxMgmtFrame(prAdapter, + prP2pDevFsmInfo->ucBssIndex, + prP2pOffChnlTxPkt->prMgmtTxMsdu, + prP2pOffChnlTxPkt->fgNoneCckRate); + + prP2pMgmtTxInfo->prMgmtTxMsdu = + prP2pOffChnlTxPkt->prMgmtTxMsdu; + prP2pMgmtTxInfo->fgIsWaitRsp = + prP2pOffChnlTxPkt->fgIsWaitRsp; + } + } else { + /* Link is empty, return back to IDLE. */ + *peNextState = P2P_DEV_STATE_IDLE; + fgIsTransition = TRUE; + } + } while (FALSE); + + return fgIsTransition; +} /* p2pDevSateInit_OFF_CHNL_TX */ + +void +p2pDevStateAbort_OFF_CHNL_TX(IN struct ADAPTER *prAdapter, + IN struct P2P_MGMT_TX_REQ_INFO *prP2pMgmtTxInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN enum ENUM_P2P_DEV_STATE eNextState) +{ + struct P2P_OFF_CHNL_TX_REQ_INFO *prP2pOffChnlTxPkt = + (struct P2P_OFF_CHNL_TX_REQ_INFO *) NULL; + + if (eNextState != P2P_DEV_STATE_OFF_CHNL_TX) { + while (!LINK_IS_EMPTY(&(prP2pMgmtTxInfo->rP2pTxReqLink))) { + LINK_REMOVE_HEAD(&(prP2pMgmtTxInfo->rP2pTxReqLink), + prP2pOffChnlTxPkt, + struct P2P_OFF_CHNL_TX_REQ_INFO *); + + if (prP2pOffChnlTxPkt) + kalP2PIndicateMgmtTxStatus( + prAdapter->prGlueInfo, + prP2pOffChnlTxPkt->prMgmtTxMsdu, + FALSE); + else + DBGLOG(P2P, INFO, + "No packet for indicating Tx status!\n"); + + p2pFuncReleaseCh(prAdapter, + prAdapter->ucP2PDevBssIdx, + prChnlReqInfo); + } + } +} /* p2pDevSateAbort_OFF_CHNL_TX */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_fsm.c new file mode 100644 index 0000000000000..2838ac8a27c63 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_fsm.c @@ -0,0 +1,383 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + + +/****************************************************************************** + * C O M P I L E 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 + ****************************************************************************** + */ + +/****************************************************************************** + * M A 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 p2pFsmRunEventScanRequest(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_P2P_SCAN_REQUEST *prP2pScanReqMsg = + (struct MSG_P2P_SCAN_REQUEST *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + if ((prAdapter == NULL) || (prMsgHdr == NULL)) + break; + + prP2pScanReqMsg = (struct MSG_P2P_SCAN_REQUEST *) prMsgHdr; + + prAdapter->prP2pInfo->eConnState = P2P_CNN_NORMAL; + + if (prP2pScanReqMsg->ucBssIdx == prAdapter->ucP2PDevBssIdx) + p2pDevFsmRunEventScanRequest(prAdapter, prMsgHdr); + else + p2pRoleFsmRunEventScanRequest(prAdapter, prMsgHdr); + + prMsgHdr = NULL; + /* Both p2pDevFsmRunEventScanRequest and + * p2pRoleFsmRunEventScanRequest + * free prMsgHdr before return, + * so prMsgHdr is needed to be NULL. + */ + } while (FALSE); + + if (prMsgHdr != NULL) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventScanRequest */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_CH_GRANT *prMsgChGrant = (struct MSG_CH_GRANT *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prMsgChGrant = (struct MSG_CH_GRANT *) prMsgHdr; + + prP2pBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, + prMsgChGrant->ucBssIndex); + + prAdapter->prP2pInfo->eConnState = P2P_CNN_NORMAL; + prAdapter->prP2pInfo->ucExtendChanFlag = 0; + + DBGLOG(P2P, TRACE, "P2P Run Event Channel Grant\n"); + +#if CFG_SISO_SW_DEVELOP + /* Driver record granted CH in BSS info */ + prP2pBssInfo->fgIsGranted = TRUE; + prP2pBssInfo->eBandGranted = prMsgChGrant->eRfBand; + prP2pBssInfo->ucPrimaryChannelGranted = + prMsgChGrant->ucPrimaryChannel; +#endif + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_P2P_DEVICE: + ASSERT(prP2pBssInfo->ucBssIndex + == prAdapter->ucP2PDevBssIdx); + + p2pDevFsmRunEventChnlGrant(prAdapter, + prMsgHdr, + prAdapter->rWifiVar.prP2pDevFsmInfo); + break; + case OP_MODE_INFRASTRUCTURE: + case OP_MODE_ACCESS_POINT: + ASSERT(prP2pBssInfo->ucBssIndex + < prAdapter->ucP2PDevBssIdx); + + p2pRoleFsmRunEventChnlGrant(prAdapter, prMsgHdr, + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData)); + break; + default: + ASSERT(FALSE); + break; + } + } while (FALSE); +} /* p2pFsmRunEventChGrant */ + +void p2pFsmRunEventNetDeviceRegister(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_P2P_NETDEV_REGISTER *prNetDevRegisterMsg = + (struct MSG_P2P_NETDEV_REGISTER *) NULL; + + DBGLOG(P2P, TRACE, "p2pFsmRunEventNetDeviceRegister\n"); + + prNetDevRegisterMsg = (struct MSG_P2P_NETDEV_REGISTER *) prMsgHdr; + + if (prNetDevRegisterMsg->fgIsEnable) { + p2pSetMode((prNetDevRegisterMsg->ucMode == 1) ? TRUE : FALSE); + if (p2pLaunch(prAdapter->prGlueInfo)) + ASSERT(prAdapter->fgIsP2PRegistered); + } else { + if (prAdapter->fgIsP2PRegistered) + p2pRemove(prAdapter->prGlueInfo); + } + + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pFsmRunEventNetDeviceRegister */ + +void p2pFsmRunEventUpdateMgmtFrame(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_P2P_MGMT_FRAME_UPDATE *prP2pMgmtFrameUpdateMsg = + (struct MSG_P2P_MGMT_FRAME_UPDATE *) NULL; + + DBGLOG(P2P, TRACE, "p2pFsmRunEventUpdateMgmtFrame\n"); + + prP2pMgmtFrameUpdateMsg = (struct MSG_P2P_MGMT_FRAME_UPDATE *) 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; + } + + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pFsmRunEventUpdateMgmtFrame */ + +#if CFG_SUPPORT_WFD +void p2pFsmRunEventWfdSettingUpdate(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct WFD_CFG_SETTINGS *prWfdCfgSettings = + (struct WFD_CFG_SETTINGS *) NULL; + struct MSG_WFD_CONFIG_SETTINGS_CHANGED *prMsgWfdCfgSettings = + (struct MSG_WFD_CONFIG_SETTINGS_CHANGED *) NULL; + uint32_t i; + + /* WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; */ + + DBGLOG(P2P, INFO, "p2pFsmRunEventWfdSettingUpdate\n"); + + do { + ASSERT_BREAK((prAdapter != NULL)); + + if (prMsgHdr != NULL) { + prMsgWfdCfgSettings = + (struct MSG_WFD_CONFIG_SETTINGS_CHANGED *) + prMsgHdr; + prWfdCfgSettings = + prMsgWfdCfgSettings->prWfdCfgSettings; + } else { + prWfdCfgSettings = + &prAdapter->rWifiVar.rWfdConfigureSettings; + } + + DBGLOG(P2P, INFO, + "WFD Enalbe %x info %x state %x flag %x adv %x\n", + prWfdCfgSettings->ucWfdEnable, + prWfdCfgSettings->u2WfdDevInfo, + (uint32_t) prWfdCfgSettings->u4WfdState, + (uint32_t) prWfdCfgSettings->u4WfdFlag, + (uint32_t) prWfdCfgSettings->u4WfdAdvancedFlag); + + if (prWfdCfgSettings->ucWfdEnable == 0) + for (i = 0; i < KAL_P2P_NUM; i++) { + if (prAdapter->prGlueInfo->prP2PInfo[i]) + prAdapter->prGlueInfo->prP2PInfo[i] + ->u2WFDIELen = 0; + } + +#if CFG_ENABLE_PER_STA_STATISTICS_LOG + if (prAdapter->rWifiVar.aprP2pRoleFsmInfo[0]) { + /* Assume role 0 */ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) + prAdapter->rWifiVar.aprP2pRoleFsmInfo[0]; + + if (prWfdCfgSettings->ucWfdEnable == 1) + cnmTimerStartTimer(prAdapter, + &(prP2pRoleFsmInfo + ->rP2pRoleFsmGetStatisticsTimer), + (3 * P2P_ROLE_GET_STATISTICS_TIME)); + else + cnmTimerStopTimer(prAdapter, + &prP2pRoleFsmInfo + ->rP2pRoleFsmGetStatisticsTimer); + } +#endif + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} + +/* p2pFsmRunEventWfdSettingUpdate */ + +#endif /* CFG_SUPPORT_WFD */ + + +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_SCN_SCAN_DONE *prScanDoneMsg = + (struct MSG_SCN_SCAN_DONE *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + + prScanDoneMsg = (struct MSG_SCN_SCAN_DONE *) prMsgHdr; + + prP2pBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, prScanDoneMsg->ucBssIndex); + + if (prAdapter->fgIsP2PRegistered == FALSE) { + DBGLOG(P2P, TRACE, + "P2P BSS Info is removed, break p2pFsmRunEventScanDone\n"); + + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + DBGLOG(P2P, TRACE, "P2P Scan Done Event\n"); + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_P2P_DEVICE: + ASSERT(prP2pBssInfo->ucBssIndex == prAdapter->ucP2PDevBssIdx); + p2pDevFsmRunEventScanDone(prAdapter, + prMsgHdr, + prAdapter->rWifiVar.prP2pDevFsmInfo); + break; + case OP_MODE_INFRASTRUCTURE: + case OP_MODE_ACCESS_POINT: + ASSERT(prP2pBssInfo->ucBssIndex < prAdapter->ucP2PDevBssIdx); + p2pRoleFsmRunEventScanDone(prAdapter, prMsgHdr, + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData)); + break; + default: + ASSERT(FALSE); + break; + } +} /* p2pFsmRunEventScanDone */ + + + +#endif /* CFG_ENABLE_WIFI_DIRECT */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_func.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_func.c new file mode 100644 index 0000000000000..e47f505dd4e75 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_func.c @@ -0,0 +1,6235 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +#include "precomp.h" + +struct APPEND_VAR_ATTRI_ENTRY 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 */ +}; + +struct APPEND_VAR_IE_ENTRY txProbeRspIETable[] = { + {(ELEM_HDR_LEN + (RATE_NUM_SW - 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 */ +#if CFG_SUPPORT_802_11AC + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP), NULL, + rlmRspGenerateVhtCapIE} /*191 */ + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP), NULL, + rlmRspGenerateVhtOpIE} /*192 */ + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP_MODE_NOTIFICATION), NULL, + rlmRspGenerateVhtOpNotificationIE} /*199 */ +#endif +#if CFG_SUPPORT_MTK_SYNERGY + , {(ELEM_HDR_LEN + ELEM_MIN_LEN_MTK_OUI), NULL, + rlmGenerateMTKOuiIE} /* 221 */ +#endif + +}; + +#if (CFG_SUPPORT_DFS_MASTER == 1) +u_int8_t g_fgManualCac = FALSE; +uint32_t g_u4DriverCacTime; +uint32_t g_u4CacStartBootTime; +uint8_t g_ucRadarDetectMode = FALSE; +struct P2P_RADAR_INFO g_rP2pRadarInfo; +uint8_t g_ucDfsState = DFS_STATE_INACTIVE; +static uint8_t *apucDfsState[DFS_STATE_NUM] = { + (uint8_t *) DISP_STRING("DFS_STATE_INACTIVE"), + (uint8_t *) DISP_STRING("DFS_STATE_CHECKING"), + (uint8_t *) DISP_STRING("DFS_STATE_ACTIVE"), + (uint8_t *) DISP_STRING("DFS_STATE_DETECTED") +}; + +uint8_t *apucW53RadarType[3] = { + (uint8_t *) DISP_STRING("Unknown Type"), + (uint8_t *) DISP_STRING("Type 1 (short pulse)"), + (uint8_t *) DISP_STRING("Type 2 (short pulse)") +}; +uint8_t *apucW56RadarType[12] = { + (uint8_t *) DISP_STRING("Unknown Type"), + (uint8_t *) DISP_STRING("Type 1 (short pulse)"), + (uint8_t *) DISP_STRING("Type 2 (short pulse)"), + (uint8_t *) DISP_STRING("Type 3 (short pulse)"), + (uint8_t *) DISP_STRING("Type 4 (short pulse)"), + (uint8_t *) DISP_STRING("Type 5 (short pulse)"), + (uint8_t *) DISP_STRING("Type 6 (short pulse)"), + (uint8_t *) DISP_STRING("Type 7 (long pulse)"), + (uint8_t *) DISP_STRING("Type 8 (short pulse)"), + (uint8_t *) DISP_STRING("Type 4 or Type 5 or Type 6 (short pulse)"), + (uint8_t *) DISP_STRING("Type 5 or Type 6 or Type 8 (short pulse)"), + (uint8_t *) DISP_STRING("Type 5 or Type 6 (short pulse)") +}; +#endif + +static void +p2pFuncParseBeaconVenderId(IN struct ADAPTER *prAdapter, IN uint8_t *pucIE, + IN struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo, + IN uint8_t ucRoleIndex); +#if 0 +static void +p2pFuncGetAttriListAction(IN struct ADAPTER *prAdapter, + IN struct IE_P2P *prIe, + IN uint8_t ucOuiType, + OUT uint8_t **pucAttriListStart, + OUT uint16_t *u2AttriListLen, + OUT u_int8_t *fgIsAllocMem, + OUT u_int8_t *fgBackupAttributes, + OUT uint16_t *u2BufferSize); +#endif + +static void +p2pFuncProcessP2pProbeRspAction(IN struct ADAPTER *prAdapter, + IN uint8_t *pucIEBuf, IN uint8_t ucElemIdType, + OUT uint8_t *ucBssIdx, OUT struct BSS_INFO **prP2pBssInfo, + OUT u_int8_t *fgIsWSCIE, + OUT u_int8_t *fgIsP2PIE, OUT u_int8_t *fgIsWFDIE); + +static void +p2pFuncGetSpecAttriAction(IN struct IE_P2P *prP2pIE, + IN uint8_t ucOuiType, + IN uint8_t ucAttriID, + OUT struct P2P_ATTRIBUTE **prTargetAttri); + +/*---------------------------------------------------------------------------*/ +/*! + * @brief Function for requesting scan. + * There is an option to do ACTIVE or PASSIVE scan. + * + * @param eScanType - Specify the scan type of the scan request. + * It can be an ACTIVE/PASSIVE + * Scan. + * eChannelSet - Specify the preferred channel set. + * A FULL scan would request a legacy + * full channel normal scan.(usually ACTIVE). + * A P2P_SOCIAL scan would scan + * 1+6+11 channels.(usually ACTIVE) + * A SPECIFIC scan would + * only 1/6/11 channels scan. + * (Passive Listen/Specific Search) + * ucChannelNum - A specific channel number. + * (Only when channel is specified) + * eBand - A specific band. (Only when channel is specified) + * + * + * @return (none) + */ +/*---------------------------------------------------------------------------*/ +void p2pFuncRequestScan(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct P2P_SCAN_REQ_INFO *prScanReqInfo) +{ + struct MSG_SCN_SCAN_REQ_V2 *prScanReqV2 = + (struct MSG_SCN_SCAN_REQ_V2 *) NULL; + +#ifdef CFG_SUPPORT_BEAM_PLUS + /*NFC Beam + Indication */ + struct P2P_FSM_INFO *prP2pFsmInfo = (struct P2P_FSM_INFO *) NULL; +#endif + + 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); + } + + prScanReqV2 = (struct MSG_SCN_SCAN_REQ_V2 *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + (sizeof(struct MSG_SCN_SCAN_REQ_V2) + + (sizeof(struct PARAM_SSID) * + prScanReqInfo->ucSsidNum))); + if (!prScanReqV2) { + ASSERT(0); /* Can't trigger SCAN FSM */ + DBGLOG(P2P, ERROR, + "p2pFuncRequestScan: Memory allocation fail, can not send SCAN MSG to scan module\n"); + break; + } + + prScanReqV2->rMsgHdr.eMsgId = MID_P2P_SCN_SCAN_REQ_V2; + prScanReqV2->ucSeqNum = ++prScanReqInfo->ucSeqNumOfScnMsg; + prScanReqV2->ucBssIndex = ucBssIndex; + prScanReqV2->eScanType = prScanReqInfo->eScanType; + prScanReqV2->eScanChannel = prScanReqInfo->eChannelSet; + prScanReqV2->u2IELen = 0; + prScanReqV2->prSsid = (struct PARAM_SSID *) + ((unsigned long) prScanReqV2 + + sizeof(struct MSG_SCN_SCAN_REQ_V2)); + + /* Copy IE for Probe Request. */ + kalMemCopy(prScanReqV2->aucIE, + prScanReqInfo->aucIEBuf, prScanReqInfo->u4BufLength); + prScanReqV2->u2IELen = (uint16_t) prScanReqInfo->u4BufLength; + + prScanReqV2->u2ChannelDwellTime = + prScanReqInfo->u2PassiveDewellTime; + prScanReqV2->u2ChannelMinDwellTime = + SCAN_CHANNEL_DWELL_TIME_MIN_MSEC; + COPY_MAC_ADDR(prScanReqV2->aucBSSID, + "\xff\xff\xff\xff\xff\xff"); + + prScanReqV2->u2TimeoutValue = 0; + prScanReqV2->u2ProbeDelay = 0; + + switch (prScanReqInfo->eChannelSet) { + case SCAN_CHANNEL_SPECIFIED: + { + uint32_t u4Idx = 0; + struct RF_CHANNEL_INFO *prDomainInfo = + (struct RF_CHANNEL_INFO *) + prScanReqInfo->arScanChannelList; + + if (prScanReqInfo->ucNumChannelList + > MAXIMUM_OPERATION_CHANNEL_LIST) + prScanReqInfo->ucNumChannelList = + MAXIMUM_OPERATION_CHANNEL_LIST; + + for (u4Idx = 0; + u4Idx < prScanReqInfo->ucNumChannelList; + u4Idx++) { + prScanReqV2->arChnlInfoList + [u4Idx].ucChannelNum = + prDomainInfo->ucChannelNum; + prScanReqV2->arChnlInfoList + [u4Idx].eBand = + prDomainInfo->eBand; + prDomainInfo++; + } + + prScanReqV2->ucChannelListNum = + prScanReqInfo->ucNumChannelList; + } + /* fallthrough */ + case SCAN_CHANNEL_FULL: + /* fallthrough */ + case SCAN_CHANNEL_2G4: + /* fallthrough */ + case SCAN_CHANNEL_P2P_SOCIAL: + { + /* UINT_8 aucP2pSsid[] = P2P_WILDCARD_SSID; */ + struct PARAM_SSID *prParamSsid = + (struct PARAM_SSID *) NULL; + + prParamSsid = prScanReqV2->prSsid; + + for (prScanReqV2->ucSSIDNum = 0; + prScanReqV2->ucSSIDNum + < prScanReqInfo->ucSsidNum; + prScanReqV2->ucSSIDNum++) { + + COPY_SSID(prParamSsid->aucSsid, + prParamSsid->u4SsidLen, + prScanReqInfo->arSsidStruct + [prScanReqV2->ucSSIDNum] + .aucSsid, + prScanReqInfo->arSsidStruct + [prScanReqV2->ucSSIDNum] + .ucSsidLen); + + prParamSsid++; + } + + /* For compatible. (in FW?) need to check. */ + if (prScanReqV2->ucSSIDNum == 0) + prScanReqV2->ucSSIDType = + SCAN_REQ_SSID_P2P_WILDCARD; + else + prScanReqV2->ucSSIDType = + SCAN_REQ_SSID_SPECIFIED; + } + break; + default: + /* Currently there is no other scan channel set. */ + ASSERT(FALSE); + break; + } + + prScanReqInfo->fgIsScanRequest = TRUE; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prScanReqV2, + MSG_SEND_METHOD_BUF); + + } while (FALSE); +} /* p2pFuncRequestScan */ + +void p2pFuncCancelScan(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct P2P_SCAN_REQ_INFO *prScanInfo) +{ + struct MSG_SCN_SCAN_CANCEL *prScanCancelMsg = + (struct MSG_SCN_SCAN_CANCEL *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prScanInfo != NULL)); + + if (!prScanInfo->fgIsScanRequest) + break; + + DBGLOG(P2P, TRACE, "P2P Cancel Scan\n"); + + prScanCancelMsg = (struct MSG_SCN_SCAN_CANCEL *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct 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; + } + kalMemZero(prScanCancelMsg, + sizeof(struct MSG_SCN_SCAN_CANCEL)); + + prScanCancelMsg->rMsgHdr.eMsgId = + MID_P2P_SCN_SCAN_CANCEL; + prScanCancelMsg->ucBssIndex = ucBssIndex; + prScanCancelMsg->ucSeqNum = + prScanInfo->ucSeqNumOfScnMsg++; + prScanCancelMsg->fgIsChannelExt = FALSE; + prScanInfo->fgIsScanRequest = FALSE; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prScanCancelMsg, + MSG_SEND_METHOD_BUF); + } while (FALSE); +} /* p2pFuncCancelScan */ + +void p2pFuncGCJoin(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN struct P2P_JOIN_INFO *prP2pJoinInfo) +{ + struct MSG_SAA_FSM_START *prJoinReqMsg = + (struct MSG_SAA_FSM_START *) NULL; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + struct BSS_DESC *prBssDesc = (struct BSS_DESC *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prP2pBssInfo != NULL) + && (prP2pJoinInfo != NULL)); + + prBssDesc = prP2pJoinInfo->prTargetBssDesc; + if ((prBssDesc) == NULL) { + DBGLOG(P2P, ERROR, + "p2pFuncGCJoin: NO Target BSS Descriptor\n"); + ASSERT(FALSE); + break; + } + + if (prBssDesc->ucSSIDLen) { + COPY_SSID(prP2pBssInfo->aucSSID, + prP2pBssInfo->ucSSIDLen, + prBssDesc->aucSSID, + prBssDesc->ucSSIDLen); + } + + /* 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)), + prP2pBssInfo->ucBssIndex, prBssDesc); + + if (prStaRec == NULL) { + DBGLOG(P2P, TRACE, "Create station record fail\n"); + ASSERT(FALSE); + break; + } + + prP2pJoinInfo->prTargetStaRec = prStaRec; + prP2pJoinInfo->fgIsJoinComplete = FALSE; + prP2pJoinInfo->u4BufLength = 0; + + /* 2 <2.1> Sync. to FW domain */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + if (prP2pBssInfo->eConnectionState + == PARAM_MEDIA_STATE_DISCONNECTED) { + prStaRec->fgIsReAssoc = FALSE; + prP2pJoinInfo->ucAvailableAuthTypes = + (uint8_t) AUTH_TYPE_OPEN_SYSTEM; + prStaRec->ucTxAuthAssocRetryLimit = + TX_AUTH_ASSOCI_RETRY_LIMIT; + } else { + DBGLOG(P2P, ERROR, + "JOIN INIT: Join Request when connected.\n"); + /* TODO: Shall we considering ROAMIN case + * for P2P Device?. + */ + break; + } + + /* 2 <4> Use an appropriate Authentication Algorithm Number + * among the ucAvailableAuthTypes. + */ + if (prP2pJoinInfo->ucAvailableAuthTypes + & (uint8_t) AUTH_TYPE_OPEN_SYSTEM) { + + DBGLOG(P2P, TRACE, + "JOIN INIT: Try to do Authentication with AuthType == OPEN_SYSTEM.\n"); + + prP2pJoinInfo->ucAvailableAuthTypes &= + ~(uint8_t) AUTH_TYPE_OPEN_SYSTEM; + + prStaRec->ucAuthAlgNum = + (uint8_t) AUTH_ALGORITHM_NUM_OPEN_SYSTEM; + } else { + DBGLOG(P2P, ERROR, + "JOIN INIT: ucAvailableAuthTypes Error.\n"); + ASSERT(FALSE); + break; + } + + /* 4 <5> Overwrite Connection Setting + * for eConnectionPolicy == ANY (Used by Assoc Req) + */ + + /* 2 <5> Backup desired channel. */ + + /* 2 <6> Send a Msg to trigger SAA to start JOIN process. */ + prJoinReqMsg = (struct MSG_SAA_FSM_START *) + cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(struct MSG_SAA_FSM_START)); + + if (!prJoinReqMsg) { + DBGLOG(P2P, TRACE, "Allocation Join Message Fail\n"); + ASSERT(FALSE); + return; + } + + prJoinReqMsg->rMsgHdr.eMsgId = MID_P2P_SAA_FSM_START; + prJoinReqMsg->ucSeqNum = ++prP2pJoinInfo->ucSeqNumOfReqMsg; + prJoinReqMsg->prStaRec = prStaRec; + + /* TODO: Consider fragmentation info in station record. */ + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prJoinReqMsg, + MSG_SEND_METHOD_BUF); + + } while (FALSE); + +} /* p2pFuncGCJoin */ + +/*---------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc, + IN struct STA_RECORD *prStaRec, + IN struct BSS_INFO *prP2pBssInfo, + IN struct SW_RFB *prAssocRspSwRfb) +{ + struct WLAN_ASSOC_RSP_FRAME *prAssocRspFrame = + (struct WLAN_ASSOC_RSP_FRAME *) NULL; + uint16_t u2IELength; + uint8_t *pucIE; + + DEBUGFUNC("p2pUpdateBssInfoForJOIN()"); + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prStaRec != NULL) + && (prP2pBssInfo != NULL) + && (prAssocRspSwRfb != NULL)); + + prAssocRspFrame = (struct WLAN_ASSOC_RSP_FRAME *) + prAssocRspSwRfb->pvHeader; + + if (prBssDesc == NULL) { + /* Target BSS NULL. */ + DBGLOG(P2P, TRACE, "Target BSS NULL\n"); + break; + } + + 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 */ + ASSERT_BREAK(prP2pBssInfo->eCurrentOPMode + == OP_MODE_INFRASTRUCTURE); + + if (UNEQUAL_MAC_ADDR(prBssDesc->aucBSSID, + prAssocRspFrame->aucBSSID)) + ASSERT(FALSE); + /* 4 <1.2> Setup SSID */ + COPY_SSID(prP2pBssInfo->aucSSID, + prP2pBssInfo->ucSSIDLen, + prBssDesc->aucSSID, + prBssDesc->ucSSIDLen); + + /* 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 */ + /* Use AP's Cap Info as BSS Cap Info */ + prP2pBssInfo->u2CapInfo = prStaRec->u2CapInfo; + + 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; + + nicTxUpdateBssDefaultRate(prP2pBssInfo); + + /* 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 = + (uint16_t) ((prAssocRspSwRfb->u2PacketLen - + prAssocRspSwRfb->u2HeaderLen) - + (OFFSET_OF(struct WLAN_ASSOC_RSP_FRAME, + 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 */ + + 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, prP2pBssInfo->ucBssIndex); + + /* 4 <4.4> *DEFER OPERATION* + * nicPmIndicateBssConnected() will be invoked + * inside scanProcessBeaconAndProbeResp() + * after 1st beacon is received + */ + + } while (FALSE); +} /* end of p2pUpdateBssInfoForJOIN() */ + +uint32_t +p2pFunMgmtFrameTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + u_int8_t fgIsSuccess = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + 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"); + } + + kalP2PIndicateMgmtTxStatus(prAdapter->prGlueInfo, + prMsduInfo, fgIsSuccess); + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; + +} /* p2pFunMgmtFrameTxDone */ +const char * +p2pToString(enum p2p_action_frame_type eP2pAction) +{ + switch (eP2pAction) { + case P2P_GO_NEG_REQ: + return "GO_NEG_REQ"; + case P2P_GO_NEG_RESP: + return "GO_NEG_RESP"; + case P2P_GO_NEG_CONF: + return "GO_NEG_CONF"; + case P2P_INVITATION_REQ: + return "INVITATION_REQ"; + case P2P_INVITATION_RESP: + return "INVITATION_RESP"; + case P2P_DEV_DISC_REQ: + return "DEV_DISC_REQ"; + case P2P_DEV_DISC_RESP: + return "DEV_DISC_RESP"; + case P2P_PROV_DISC_REQ: + return "PROV_DISC_REQ"; + case P2P_PROV_DISC_RESP: + return "PROV_DISC_RESP"; + } + + return "UNKNOWN P2P Public Action"; +} + + +const char * +paToString(int32_t u4PaAction) +{ + switch (u4PaAction) { + case WLAN_PA_20_40_BSS_COEX: + return "PA_20_40_BSS_COEX"; + case WLAN_PA_VENDOR_SPECIFIC: + return "PA_VENDOR_SPECIFIC"; + case WLAN_PA_GAS_INITIAL_REQ: + return "PA_GAS_INITIAL_REQ"; + case WLAN_PA_GAS_INITIAL_RESP: + return "PA_GAS_INITIAL_RESP"; + case WLAN_PA_GAS_COMEBACK_REQ: + return "PA_GAS_COMEBACK_REQ"; + case WLAN_PA_GAS_COMEBACK_RESP: + return "PA_GAS_COMEBACK_RESP"; + case WLAN_TDLS_DISCOVERY_RESPONSE: + return "TDLS_DISCOVERY_RESPONSE"; + } + + return "UNKNOWN Public Action"; +} + + +const char * +actionToString(int32_t u4WlanAction) +{ + switch (u4WlanAction) { + case WLAN_ACTION_SPECTRUM_MGMT: + return "SPECTRUM_MGMT"; + case WLAN_ACTION_QOS: + return "QOS"; + case WLAN_ACTION_DLS: + return "DLS"; + case WLAN_ACTION_BLOCK_ACK: + return "BLOCK_ACK"; + case WLAN_ACTION_PUBLIC: + return "PUBLIC"; + case WLAN_ACTION_RADIO_MEASUREMENT: + return "RADIO_MEASUREMENT"; + case WLAN_ACTION_FT: + return "FT"; + case WLAN_ACTION_HT: + return "HT"; + case WLAN_ACTION_SA_QUERY: + return "SA_QUERY"; + case WLAN_ACTION_PROTECTED_DUAL: + return "PROTECTED_DUAL"; + case WLAN_ACTION_WNM: + return "WNM"; + case WLAN_ACTION_UNPROTECTED_WNM: + return "UNPROTECTED_WNM"; + case WLAN_ACTION_TDLS: + return "TDLS"; + case WLAN_ACTION_SELF_PROTECTED: + return "SELF_PROTECTED"; + case WLAN_ACTION_WMM: + return "WMM"; + case WLAN_ACTION_VENDOR_SPECIFIC: + return "VENDOR_SPECIFIC"; + } + + return "UNKNOWN Action Frame"; +} + + +enum ENUM_P2P_CONNECT_STATE +p2pFuncTagActionActionP2PFrame(IN struct MSDU_INFO *prMgmtTxMsdu, + IN struct WLAN_ACTION_FRAME *prActFrame, + IN uint8_t ucP2pAction, IN uint64_t u8Cookie) +{ + DBGLOG(P2P, INFO, + "Found P2P_%s, SA: " MACSTR + " - DA: " MACSTR ", cookie: 0x%llx, SeqNO: %d\n", + p2pToString(ucP2pAction), + MAC2STR(prActFrame->aucSrcAddr), + MAC2STR(prActFrame->aucDestAddr), + u8Cookie, + prMgmtTxMsdu->ucTxSeqNum); + return ucP2pAction + 1; +} + + +enum ENUM_P2P_CONNECT_STATE +p2pFuncTagActionActionFrame(IN struct MSDU_INFO *prMgmtTxMsdu, + IN struct WLAN_ACTION_FRAME *prActFrame, + IN uint8_t ucAction, IN uint64_t u8Cookie) +{ + uint8_t *pucVendor = NULL; + enum ENUM_P2P_CONNECT_STATE eCNNState = P2P_CNN_NORMAL; + + DBGLOG(P2P, INFO, + "Found WLAN_%s, SA: " MACSTR + " - DA: " MACSTR ", cookie: 0x%llx, SeqNo: %d\n", + paToString(ucAction), + MAC2STR(prActFrame->aucSrcAddr), + MAC2STR(prActFrame->aucDestAddr), + u8Cookie, + prMgmtTxMsdu->ucTxSeqNum); + + if (ucAction != WLAN_PA_VENDOR_SPECIFIC) + return P2P_CNN_NORMAL; + + pucVendor = (uint8_t *)prActFrame + 26; + if (*(pucVendor + 0) == 0x50 && + *(pucVendor + 1) == 0x6f && + *(pucVendor + 2) == 0x9a) { + if (*(pucVendor + 3) == 0x09) + /* found p2p IE */ + eCNNState = p2pFuncTagActionActionP2PFrame(prMgmtTxMsdu, + prActFrame, *(pucVendor + 4), u8Cookie); + else if (*(pucVendor + 3) == 0x0a) + /* found WFD IE */ + DBGLOG(P2P, INFO, "Found WFD IE, SA: " MACSTR + " - DA: " MACSTR "\n", + MAC2STR(prActFrame->aucSrcAddr), + MAC2STR(prActFrame->aucDestAddr)); + else + DBGLOG(P2P, INFO, + "Found Other vendor 0x%x, SA: " MACSTR + " - DA: " MACSTR "\n", + *(pucVendor + 3), + MAC2STR(prActFrame->aucSrcAddr), + MAC2STR(prActFrame->aucDestAddr)); + } + return eCNNState; +} + +enum ENUM_P2P_CONNECT_STATE +p2pFuncTagActionCategoryFrame(IN struct MSDU_INFO *prMgmtTxMsdu, + struct WLAN_ACTION_FRAME *prActFrame, + IN uint8_t ucCategory, + IN uint64_t u8Cookie) +{ + + uint8_t ucAction = 0; + enum ENUM_P2P_CONNECT_STATE eCNNState = P2P_CNN_NORMAL; + + DBGLOG(P2P, TRACE, + "Found WLAN_ACTION_%s, SA: " MACSTR + " BSSID: " MACSTR + " DA: " MACSTR ", u8Cookie: 0x%llx, SeqNO: %d\n", + actionToString(ucCategory), + MAC2STR(prActFrame->aucSrcAddr), + MAC2STR(prActFrame->aucBSSID), + MAC2STR(prActFrame->aucDestAddr), + u8Cookie, + prMgmtTxMsdu->ucTxSeqNum); + + if (ucCategory == WLAN_ACTION_PUBLIC) { + ucAction = prActFrame->ucAction; + eCNNState = p2pFuncTagActionActionFrame(prMgmtTxMsdu, + prActFrame, ucAction, u8Cookie); + } + return eCNNState; +} + +void p2pProcessActionResponse(IN struct ADAPTER *prAdapter, + enum p2p_action_frame_type eType) +{ + u_int8_t fgIdle = FALSE; + + if (!prAdapter || !prAdapter->prP2pInfo) + return; + + switch (prAdapter->prP2pInfo->eConnState) { + case P2P_CNN_GO_NEG_REQ: + if (eType == P2P_GO_NEG_RESP) + fgIdle = TRUE; + break; + case P2P_CNN_GO_NEG_RESP: + if (eType == P2P_GO_NEG_CONF || eType == P2P_GO_NEG_REQ) + fgIdle = TRUE; + break; + case P2P_CNN_INVITATION_REQ: + if (eType == P2P_INVITATION_RESP) + fgIdle = TRUE; + break; + case P2P_CNN_DEV_DISC_REQ: + if (eType == P2P_DEV_DISC_RESP) + fgIdle = TRUE; + break; + case P2P_CNN_PROV_DISC_REQ: + if (eType == P2P_PROV_DISC_RESP) + fgIdle = TRUE; + break; + default: + break; + } + + DBGLOG(P2P, INFO, + "eConnState: %d, eType: %d\n", + prAdapter->prP2pInfo->eConnState, eType); + + if (fgIdle) + prAdapter->prP2pInfo->eConnState = P2P_CNN_NORMAL; +} + +/* + * used to debug p2p mgmt frame: + * GO Nego Req + * GO Nego Res + * GO Nego Confirm + * GO Invite Req + * GO Invite Res + * Device Discoverability Req + * Device Discoverability Res + * Provision Discovery Req + * Provision Discovery Res + */ + +enum ENUM_P2P_CONNECT_STATE +p2pFuncTagMgmtFrame(IN struct MSDU_INFO *prMgmtTxMsdu, + IN uint64_t u8Cookie) +{ + /* P_MSDU_INFO_T prTxMsduInfo = (P_MSDU_INFO_T)NULL; */ + struct WLAN_MAC_HEADER *prWlanHdr = (struct WLAN_MAC_HEADER *) NULL; + struct WLAN_BEACON_FRAME *prProbRspHdr = + (struct WLAN_BEACON_FRAME *)NULL; + uint16_t u2TxFrameCtrl; + struct WLAN_ACTION_FRAME *prActFrame; + uint8_t ucCategory; + enum ENUM_P2P_CONNECT_STATE eCNNState = P2P_CNN_NORMAL; + + prWlanHdr = (struct WLAN_MAC_HEADER *) + ((unsigned long) prMgmtTxMsdu->prPacket + + MAC_TX_RESERVED_FIELD); + /* + * mgmt frame MASK_FC_TYPE = 0 + * use MASK_FRAME_TYPE is oK for frame type/subtype judge + */ + u2TxFrameCtrl = prWlanHdr->u2FrameCtrl & MASK_FRAME_TYPE; + + switch (u2TxFrameCtrl) { + case MAC_FRAME_PROBE_RSP: + prProbRspHdr = (struct WLAN_BEACON_FRAME *) prWlanHdr; + DBGLOG(P2P, INFO, + "TX Probe Response, SA: " MACSTR + " BSSID: " MACSTR + " DA: " MACSTR ", cookie: 0x%llx, seqNo: %d\n", + MAC2STR(prProbRspHdr->aucSrcAddr), + MAC2STR(prProbRspHdr->aucBSSID), + MAC2STR(prProbRspHdr->aucDestAddr), + u8Cookie, + prMgmtTxMsdu->ucTxSeqNum); + + break; + + case MAC_FRAME_ACTION: + prActFrame = (struct WLAN_ACTION_FRAME *)prWlanHdr; + ucCategory = prActFrame->ucCategory; + eCNNState = p2pFuncTagActionCategoryFrame(prMgmtTxMsdu, + prActFrame, ucCategory, u8Cookie); + + break; + default: + DBGLOG(P2P, INFO, + "Untagged frame type: 0x%x, A1: " MACSTR + ", A2: " MACSTR + ", A3: " MACSTR " seqNo: %d\n", + u2TxFrameCtrl, + MAC2STR(prWlanHdr->aucAddr1), + MAC2STR(prWlanHdr->aucAddr2), + MAC2STR(prWlanHdr->aucAddr3), + prMgmtTxMsdu->ucTxSeqNum); + break; + } + return eCNNState; +} + +uint32_t +p2pFuncTxMgmtFrame(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct MSDU_INFO *prMgmtTxMsdu, + IN u_int8_t fgNonCckRate) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + /* P_MSDU_INFO_T prTxMsduInfo = (P_MSDU_INFO_T)NULL; */ + struct WLAN_MAC_HEADER *prWlanHdr = (struct WLAN_MAC_HEADER *) NULL; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + uint8_t ucRetryLimit = 30; /* TX_DESC_TX_COUNT_NO_LIMIT; */ + u_int8_t fgDrop = FALSE; + struct BSS_INFO *prBssInfo; + uint64_t *pu8GlCookie = (uint64_t *) NULL; + uint64_t u8GlCookie; + + do { + ASSERT_BREAK(prAdapter != NULL); + + /* Drop this frame if BSS inactive */ + if (!IS_NET_ACTIVE(prAdapter, ucBssIndex)) { + p2pDevFsmRunEventMgmtFrameTxDone(prAdapter, + prMgmtTxMsdu, TX_RESULT_INACTIVE_BSS); + cnmMgtPktFree(prAdapter, prMgmtTxMsdu); + fgDrop = TRUE; + break; + } + pu8GlCookie = + (uint64_t *) ((unsigned long) prMgmtTxMsdu->prPacket + + (unsigned long) prMgmtTxMsdu->u2FrameLength + + MAC_TX_RESERVED_FIELD); + + u8GlCookie = *pu8GlCookie; + + prWlanHdr = (struct WLAN_MAC_HEADER *) + ((unsigned long) prMgmtTxMsdu->prPacket + + MAC_TX_RESERVED_FIELD); + prStaRec = cnmGetStaRecByAddress(prAdapter, + ucBssIndex, prWlanHdr->aucAddr1); + /* prMgmtTxMsdu->ucBssIndex = ucBssIndex; */ + + switch (prWlanHdr->u2FrameCtrl & MASK_FRAME_TYPE) { + case MAC_FRAME_PROBE_RSP: + DBGLOG(P2P, TRACE, "TX Probe Resposne Frame\n"); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex); + if ((!nicTxIsMgmtResourceEnough(prAdapter)) + || (prBssInfo->fgIsNetAbsent)) { + DBGLOG(P2P, INFO, + "Drop Tx probe response due to resource issue\n"); + fgDrop = TRUE; + + break; + } + prMgmtTxMsdu->ucStaRecIndex = + (prStaRec != NULL) + ? (prStaRec->ucIndex) : (STA_REC_INDEX_NOT_FOUND); + /* Modifiy Lie time to 100 mS due + * to the STA only wait 30-50mS + */ + /* and AP do not need send it after STA left */ + nicTxSetPktLifeTime(prMgmtTxMsdu, 100); + prMgmtTxMsdu = p2pFuncProcessP2pProbeRsp(prAdapter, + ucBssIndex, prMgmtTxMsdu); + + /* + * Not check prMsduInfo sanity + * as p2pFuncProcessP2pProbeRsp will always + * return a MsduInfo + */ + pu8GlCookie = + (uint64_t *) ((unsigned long) + prMgmtTxMsdu->prPacket + + (unsigned long) + prMgmtTxMsdu->u2FrameLength + + MAC_TX_RESERVED_FIELD); + /* Restore cookie as it will be corrupted + * in p2pFuncProcessP2pProbeRsp + */ + *pu8GlCookie = u8GlCookie; + ucRetryLimit = 6; + break; + default: + prMgmtTxMsdu->ucBssIndex = ucBssIndex; + break; + } + + if (fgDrop) { + /* Drop this frame */ + p2pDevFsmRunEventMgmtFrameTxDone(prAdapter, + prMgmtTxMsdu, TX_RESULT_DROPPED_IN_DRIVER); + cnmMgtPktFree(prAdapter, prMgmtTxMsdu); + + break; + } + + TX_SET_MMPDU(prAdapter, + prMgmtTxMsdu, + prMgmtTxMsdu->ucBssIndex, + (prStaRec != NULL) + ? (prStaRec->ucIndex) : (STA_REC_INDEX_NOT_FOUND), + WLAN_MAC_MGMT_HEADER_LEN, + prMgmtTxMsdu->u2FrameLength, + p2pDevFsmRunEventMgmtFrameTxDone, + MSDU_RATE_MODE_AUTO); + + nicTxSetPktRetryLimit(prMgmtTxMsdu, ucRetryLimit); + + /* Bufferable MMPDUs are suggested to be queued */ + /* when GC is sleeping according to SPEC, */ + /* instead of being sent to ALTX Q. */ + + /* GO discoverability REQ needs to be sent to GC */ + /* when GC is awake due to P2P-6.1.10 cert fail */ + if (!p2pFuncIsBufferableMMPDU(prMgmtTxMsdu)) { + nicTxConfigPktControlFlag(prMgmtTxMsdu, + MSDU_CONTROL_FLAG_FORCE_TX, TRUE); + } + + prAdapter->prP2pInfo->eConnState = + p2pFuncTagMgmtFrame(prMgmtTxMsdu, u8GlCookie); + + nicTxEnqueueMsdu(prAdapter, prMgmtTxMsdu); + + + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncTxMgmtFrame */ + +void p2pFuncStopComplete(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo) +{ + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); + + DBGLOG(P2P, TRACE, "p2pFuncStopComplete\n"); + + /* GO: It would stop Beacon TX. + * GC: Stop all BSS related PS function. + */ + nicPmIndicateBssAbort(prAdapter, prP2pBssInfo->ucBssIndex); + /* Reset RLM related field of BSSINFO. */ + rlmBssAborted(prAdapter, prP2pBssInfo); + + UNSET_NET_ACTIVE(prAdapter, prP2pBssInfo->ucBssIndex); + nicDeactivateNetwork(prAdapter, prP2pBssInfo->ucBssIndex); + /* Release CNM channel */ + nicUpdateBss(prAdapter, prP2pBssInfo->ucBssIndex); + + /* Reset current OPMode */ + prP2pBssInfo->eCurrentOPMode = OP_MODE_INFRASTRUCTURE; + + /* Point StaRecOfAP to NULL when GC role stop Complete */ + prP2pBssInfo->prStaRecOfAP = NULL; + } while (FALSE); + +} /* p2pFuncStopComplete */ + +/*---------------------------------------------------------------------------*/ +/*! + * @brief This function will start a P2P Group Owner and send Beacon Frames. + * + * @param (none) + * + * @return (none) + */ +/*---------------------------------------------------------------------------*/ +void +p2pFuncStartGO(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct P2P_CONNECTION_REQ_INFO *prP2pConnReqInfo, + IN struct P2P_CHNL_REQ_INFO *prP2pChnlReqInfo) +{ +#if (CFG_SUPPORT_DFS_MASTER == 1) + struct CMD_RDD_ON_OFF_CTRL *prCmdRddOnOffCtrl; +#endif + +#ifdef CFG_SUPPORT_P2P_OPEN_SECURITY + uint8_t fgIsOpenP2P = TRUE; +#else + uint8_t fgIsOpenP2P = FALSE; +#endif + +#ifdef CFG_SUPPORT_P2P_GO_11B_RATE + uint8_t fgIs11bRate = TRUE; +#else + uint8_t fgIs11bRate = FALSE; +#endif + + + do { + ASSERT_BREAK((prAdapter != NULL) && (prBssInfo != NULL)); + + if (prBssInfo->ucBssIndex >= prAdapter->ucHwBssIdNum) { + DBGLOG(P2P, ERROR, + "P2P BSS exceed the number of P2P interface number."); + ASSERT(FALSE); + break; + } + + DBGLOG(P2P, TRACE, "p2pFuncStartGO:\n"); + +#if (CFG_SUPPORT_DFS_MASTER == 1) + prCmdRddOnOffCtrl = (struct CMD_RDD_ON_OFF_CTRL *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(*prCmdRddOnOffCtrl)); + + if (!prCmdRddOnOffCtrl) { + ASSERT(FALSE); + break; + } + + prCmdRddOnOffCtrl->ucDfsCtrl = RDD_START_TXQ; + + /* + * FIX ME: Mobile driver can't get correct band. + * There is only 5G in DFS channel, + * which is on band_0. So it assigned to ENUM_BAND_0 + * as temp solution. + * Remember to fix it when driver could get + * the correct band from firmware. + */ + prCmdRddOnOffCtrl->ucRddIdx = ENUM_BAND_0; + + DBGLOG(P2P, INFO, + "p2pFuncStartGO: Start TXQ - DFS ctrl: %.d\n", + prCmdRddOnOffCtrl->ucDfsCtrl); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_RDD_ON_OFF_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(*prCmdRddOnOffCtrl), + (uint8_t *) prCmdRddOnOffCtrl, NULL, 0); + + cnmMemFree(prAdapter, prCmdRddOnOffCtrl); +#endif + + /* Re-start AP mode. */ + p2pFuncSwitchOPMode(prAdapter, + prBssInfo, prBssInfo->eIntendOPMode, FALSE); + + prBssInfo->eIntendOPMode = OP_MODE_NUM; + + /* 4 <1.1> Assign SSID */ + COPY_SSID(prBssInfo->aucSSID, + prBssInfo->ucSSIDLen, + prP2pConnReqInfo->rSsidStruct.aucSsid, + prP2pConnReqInfo->rSsidStruct.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 = (struct STA_RECORD *) NULL; + prBssInfo->u2AssocId = 0; + + /* 4 <1.3> Setup Channel, Band and Phy Attributes */ + prBssInfo->ucPrimaryChannel = prP2pChnlReqInfo->ucReqChnlNum; + prBssInfo->eBand = prP2pChnlReqInfo->eBand; + prBssInfo->eBssSCO = prP2pChnlReqInfo->eChnlSco; + + DBGLOG(P2P, TRACE, + "GO Channel:%d\n", + prBssInfo->ucPrimaryChannel); + + if (prBssInfo->eBand == BAND_5G) { + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = + (prAdapter->rWifiVar.ucAvailablePhyTypeSet + & PHY_TYPE_SET_802_11AN); + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_11A; + } else if ((prP2pConnReqInfo->eConnRequest + == P2P_CONNECTION_TYPE_PURE_AP) || + fgIs11bRate) { + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = + (prAdapter->rWifiVar.ucAvailablePhyTypeSet + & PHY_TYPE_SET_802_11BGN); + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; + } else { + ASSERT(prP2pConnReqInfo->eConnRequest + == P2P_CONNECTION_TYPE_GO); + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = + (prAdapter->rWifiVar.ucAvailablePhyTypeSet + & PHY_TYPE_SET_802_11GN); + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_11G_P2P; + } + + /* Overwrite BSS PHY type set by Feature Options */ + bssDetermineApBssInfoPhyTypeSet(prAdapter, + (prP2pConnReqInfo->eConnRequest == + P2P_CONNECTION_TYPE_PURE_AP) ? TRUE : FALSE, prBssInfo); + + prBssInfo->ucNonHTBasicPhyType = (uint8_t) + rNonHTApModeAttributes + [prBssInfo->ucConfigAdHocAPMode] + .ePhyTypeIndex; + prBssInfo->u2BSSBasicRateSet = + rNonHTApModeAttributes + [prBssInfo->ucConfigAdHocAPMode] + .u2BSSBasicRateSet; + prBssInfo->u2OperationalRateSet = + rNonHTPhyAttributes + [prBssInfo->ucNonHTBasicPhyType] + .u2SupportedRateSet; + + if ((prBssInfo->ucAllSupportedRatesLen == 0) + || fgIs11bRate) { + 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 + prBssInfo->fgIsProtection = FALSE; + if (prP2pConnReqInfo->eConnRequest == P2P_CONNECTION_TYPE_GO + && (!fgIsOpenP2P)) { + /* Always enable protection at P2P GO */ + prBssInfo->fgIsProtection = TRUE; + } else { + if (!fgIsOpenP2P) + ASSERT(prP2pConnReqInfo->eConnRequest + == P2P_CONNECTION_TYPE_PURE_AP); + if (kalP2PGetCipher(prAdapter->prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData)) + prBssInfo->fgIsProtection = TRUE; + } + + bssInitForAP(prAdapter, prBssInfo, TRUE); + +#if 0 + if (prBssInfo->ucBMCWlanIndex >= WTBL_SIZE) { + prBssInfo->ucBMCWlanIndex = + secPrivacySeekForBcEntry(prAdapter, + prBssInfo->ucBssIndex, + prBssInfo->aucBSSID, 0xff, + CIPHER_SUITE_NONE, 0xff); + } +#endif + nicQmUpdateWmmParms(prAdapter, prBssInfo->ucBssIndex); +#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, prBssInfo->ucBssIndex); + + /* 4 <3.3> Update Beacon again + * for network phy type confirmed. + */ + bssUpdateBeaconContent(prAdapter, prBssInfo->ucBssIndex); + + /* 4 <3.4> Setup BSSID */ + nicPmIndicateBssCreated(prAdapter, prBssInfo->ucBssIndex); + + } while (FALSE); +} /* p2pFuncStartGO() */ + +void p2pFuncStopGO(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo) +{ + uint32_t u4ClientCount = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); + + DBGLOG(P2P, TRACE, "p2pFuncStopGO\n"); + + u4ClientCount = bssGetClientCount(prAdapter, prP2pBssInfo); + + if ((prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) + && (prP2pBssInfo->eIntendOPMode == OP_MODE_NUM)) { + /* AP is created, Beacon Updated. */ + p2pFuncDissolve(prAdapter, + prP2pBssInfo, TRUE, + REASON_CODE_DEAUTH_LEAVING_BSS); + prP2pBssInfo->eIntendOPMode = OP_MODE_P2P_DEVICE; + } + + /* Do not Deactivate Network if any Client existed, + * we'll deactive it after Deauth Tx done + */ + if (u4ClientCount == 0) { + DBGLOG(P2P, INFO, + "No client! Deactive GO immediately.\n"); + p2pChangeMediaState(prAdapter, + prP2pBssInfo, PARAM_MEDIA_STATE_DISCONNECTED); + p2pFuncStopComplete(prAdapter, prP2pBssInfo); + } + + } while (FALSE); + +} /* p2pFuncStopGO */ + +uint32_t p2pFuncRoleToBssIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucRoleIdx, OUT uint8_t *pucBssIdx) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBssIdx != NULL)); + + if (ucRoleIdx >= BSS_P2P_NUM) { + rWlanStatus = WLAN_STATUS_FAILURE; + break; + } + if (!prAdapter->rWifiVar.aprP2pRoleFsmInfo[ucRoleIdx]) { + DBGLOG(P2P, WARN, + "%s, invalid aprP2pRoleFsmInfo, ignore\n", + __func__); + rWlanStatus = WLAN_STATUS_FAILURE; + } else + *pucBssIdx = prAdapter->rWifiVar + .aprP2pRoleFsmInfo[ucRoleIdx]->ucBssIndex; + + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncRoleToBssIdx */ + +struct P2P_ROLE_FSM_INFO *p2pFuncGetRoleByBssIdx(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + int32_t i = 0; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL)); + + for (i = 0 ; i < BSS_P2P_NUM; i++) { + if (!prAdapter->rWifiVar.aprP2pRoleFsmInfo[i]) + continue; + + if (prAdapter->rWifiVar.aprP2pRoleFsmInfo[i]->ucBssIndex + == ucBssIndex) + break; + } + if (i < BSS_P2P_NUM) + prP2pRoleFsmInfo = + prAdapter->rWifiVar.aprP2pRoleFsmInfo[i]; + + } while (FALSE); + + return prP2pRoleFsmInfo; +} + + +void +p2pFuncSwitchOPMode(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN enum ENUM_OP_MODE eOpMode, + IN u_int8_t 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 will be done + * in p2pFuncStopGO(). + */ + /* p2pFuncDissolve(prAdapter, + * prP2pBssInfo, TRUE, + * REASON_CODE_DEAUTH_LEAVING_BSS); + */ + if (prP2pBssInfo->eIntendOPMode + != OP_MODE_P2P_DEVICE) { + p2pFuncStopGO(prAdapter, prP2pBssInfo); + + SET_NET_PWR_STATE_IDLE(prAdapter, + prP2pBssInfo->ucBssIndex); + } + break; + default: + break; + } + + prP2pBssInfo->eIntendOPMode = eOpMode; + + /* The state is in disconnecting and + * can not change any BSS status + */ + if (IS_NET_PWR_STATE_IDLE(prAdapter, + prP2pBssInfo->ucBssIndex) && + IS_NET_ACTIVE(prAdapter, + prP2pBssInfo->ucBssIndex)) { + DBGLOG(P2P, TRACE, + "under deauth procedure, Quit.\n"); + break; + } + + prP2pBssInfo->eCurrentOPMode = eOpMode; + switch (eOpMode) { + case OP_MODE_INFRASTRUCTURE: + DBGLOG(P2P, TRACE, + "p2pFuncSwitchOPMode: Switch to Client.\n"); + /* fall through */ + case OP_MODE_ACCESS_POINT: + /* Change interface address. */ + if (eOpMode == OP_MODE_ACCESS_POINT) { + DBGLOG(P2P, TRACE, + "p2pFuncSwitchOPMode: Switch to AP.\n"); + prP2pBssInfo->ucSSIDLen = 0; + } + +#if CFG_DUAL_P2PLIKE_INTERFACE + /*avoid ap1 Bss have diff A2 & A3, */ + /*ToDo : fix for P2P case*/ + +#else + COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, + prAdapter->rWifiVar + .aucInterfaceAddress); + COPY_MAC_ADDR(prP2pBssInfo->aucBSSID, + prAdapter->rWifiVar + .aucInterfaceAddress); +#endif + break; + case OP_MODE_P2P_DEVICE: + { + /* Change device address. */ + DBGLOG(P2P, TRACE, + "p2pFuncSwitchOPMode: Switch back to P2P Device.\n"); + + p2pChangeMediaState(prAdapter, + prP2pBssInfo, + PARAM_MEDIA_STATE_DISCONNECTED); + + COPY_MAC_ADDR( + prP2pBssInfo->aucOwnMacAddr, + prAdapter->rWifiVar + .aucDeviceAddress); + COPY_MAC_ADDR( + prP2pBssInfo->aucBSSID, + prAdapter->rWifiVar + .aucDeviceAddress); + + } + break; + default: + ASSERT(FALSE); + break; + } + + if (1) { + struct P2P_DISCONNECT_INFO rP2PDisInfo; + + rP2PDisInfo.ucRole = 2; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_P2P_ABORT, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct P2P_DISCONNECT_INFO), + (uint8_t *) &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, + prP2pBssInfo->ucBssIndex); + } else if (prP2pBssInfo->eCurrentOPMode == eOpMode && + eOpMode == OP_MODE_INFRASTRUCTURE) { + /* + * Sometimes the interface is changed from P2P_CLIENT + * to STATION, but GC's connection flow is still in + * processing. We must force stop previous connection + * request to avoid unexpected behavior. + */ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct P2P_CONNECTION_REQ_INFO *prConnReqInfo = + (struct P2P_CONNECTION_REQ_INFO *) NULL; + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO( + prAdapter, prP2pBssInfo->u4PrivateData); + if (prP2pRoleFsmInfo == NULL) + break; + + prConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + if (prConnReqInfo == NULL) + break; + + if (prConnReqInfo->eConnRequest == + P2P_CONNECTION_TYPE_GC) { + log_dbg(P2P, INFO, "Force stop connection request since mode switch.\n"); + prConnReqInfo->eConnRequest = + P2P_CONNECTION_TYPE_IDLE; + p2pRoleFsmRunEventAbort(prAdapter, + prP2pRoleFsmInfo); + } + } + + } while (FALSE); +} /* p2pFuncSwitchOPMode */ + +/*---------------------------------------------------------------------------*/ +/*! + * \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 struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo) +{ + struct MSG_CH_ABORT *prMsgChRelease = (struct MSG_CH_ABORT *) NULL; + + DEBUGFUNC("p2pFuncReleaseCh()"); + + do { + ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL)); + + if (!prChnlReqInfo->fgIsChannelRequested) + break; + DBGLOG(P2P, TRACE, "P2P Release Channel\n"); + prChnlReqInfo->fgIsChannelRequested = FALSE; + + /* 1. return channel privilege to CNM immediately */ + prMsgChRelease = (struct MSG_CH_ABORT *) + cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(struct MSG_CH_ABORT)); + if (!prMsgChRelease) { + ASSERT(0); /* Can't release Channel to CNM */ + break; + } + + prMsgChRelease->rMsgHdr.eMsgId = MID_MNY_CNM_CH_ABORT; + prMsgChRelease->ucBssIndex = ucBssIdx; + prMsgChRelease->ucTokenID = prChnlReqInfo->ucSeqNumOfChReq++; +#if CFG_SUPPORT_DBDC + prMsgChRelease->eDBDCBand = ENUM_BAND_AUTO; + + DBGLOG(P2P, INFO, + "p2pFuncReleaseCh: P2P abort channel on band %u.\n", + prMsgChRelease->eDBDCBand); +#endif /*CFG_SUPPORT_DBDC*/ + mboxSendMsg(prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prMsgChRelease, + MSG_SEND_METHOD_BUF); + + } while (FALSE); +} /* p2pFuncReleaseCh */ + +/*---------------------------------------------------------------------------*/ +/*! + * @brief Process of CHANNEL_REQ_JOIN Initial. Enter CHANNEL_REQ_JOIN State. + * + * @param (none) + * + * @return (none) + */ +/*---------------------------------------------------------------------------*/ +void p2pFuncAcquireCh(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo) +{ + struct MSG_CH_REQ *prMsgChReq = (struct MSG_CH_REQ *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL)); + + p2pFuncReleaseCh(prAdapter, ucBssIdx, prChnlReqInfo); + + /* send message to CNM for acquiring channel */ + prMsgChReq = (struct MSG_CH_REQ *) + cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(struct MSG_CH_REQ)); + + if (!prMsgChReq) { + /* Can't indicate CNM for channel acquiring */ + ASSERT(0); + break; + } + + prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; + prMsgChReq->ucBssIndex = ucBssIdx; + prMsgChReq->ucTokenID = ++prChnlReqInfo->ucSeqNumOfChReq; + prMsgChReq->eReqType = prChnlReqInfo->eChnlReqType; + prMsgChReq->u4MaxInterval = prChnlReqInfo->u4MaxInterval; + prMsgChReq->ucPrimaryChannel = prChnlReqInfo->ucReqChnlNum; + prMsgChReq->eRfSco = prChnlReqInfo->eChnlSco; + prMsgChReq->eRfBand = prChnlReqInfo->eBand; + prMsgChReq->eRfChannelWidth = prChnlReqInfo->eChannelWidth; + prMsgChReq->ucRfCenterFreqSeg1 = prChnlReqInfo->ucCenterFreqS1; + prMsgChReq->ucRfCenterFreqSeg2 = prChnlReqInfo->ucCenterFreqS2; +#if CFG_SUPPORT_DBDC + prMsgChReq->eDBDCBand = ENUM_BAND_AUTO; + + DBGLOG(P2P, INFO, + "p2pFuncAcquireCh: P2P Request channel on band %u, tokenID: %d, cookie: 0x%llx.\n", + prMsgChReq->eDBDCBand, + prMsgChReq->ucTokenID, + prChnlReqInfo->u8Cookie); + +#endif /*CFG_SUPPORT_DBDC*/ + /* Channel request join BSSID. */ + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prMsgChReq, + MSG_SEND_METHOD_BUF); + + prChnlReqInfo->fgIsChannelRequested = TRUE; + + } while (FALSE); +} /* p2pFuncAcquireCh */ + +#if (CFG_SUPPORT_DFS_MASTER == 1) +void p2pFuncStartRdd(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIdx) +{ + struct CMD_RDD_ON_OFF_CTRL *prCmdRddOnOffCtrl; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + uint8_t ucReqChnlNum; + + DEBUGFUNC("p2pFuncStartRdd()"); + + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prAdapter->aprBssInfo[ucBssIdx]->u4PrivateData); + + ucReqChnlNum = prP2pRoleFsmInfo->rChnlReqInfo.ucReqChnlNum; + + prCmdRddOnOffCtrl = (struct CMD_RDD_ON_OFF_CTRL *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(*prCmdRddOnOffCtrl)); + + if (!prCmdRddOnOffCtrl) { + DBGLOG(P2P, ERROR, + "cnmMemAlloc for prCmdRddOnOffCtrl failed!\n"); + return; + } + + prCmdRddOnOffCtrl->ucDfsCtrl = RDD_START; + + /* + * FIX ME: Mobile driver can't get correct band. + * There is only 5G in DFS channel, + * which is on band_0. So it assigned to ENUM_BAND_0 as temp solution. + * Remember to fix it when driver could get + * the correct band from firmware. + */ + prCmdRddOnOffCtrl->ucRddIdx = ENUM_BAND_0; + + if (rlmDomainGetDfsRegion() == NL80211_DFS_JP) { + if (ucReqChnlNum >= 52 && ucReqChnlNum <= 64) + prCmdRddOnOffCtrl->ucSetVal = REG_JP_53; + else if (ucReqChnlNum >= 100 && ucReqChnlNum <= 140) + prCmdRddOnOffCtrl->ucSetVal = REG_JP_56; + } else { + prCmdRddOnOffCtrl->ucSetVal = REG_DEFAULT; + } + + if (prCmdRddOnOffCtrl->ucRddIdx) + prCmdRddOnOffCtrl->ucRddRxSel = RDD_IN_SEL_1; + else + prCmdRddOnOffCtrl->ucRddRxSel = RDD_IN_SEL_0; + + DBGLOG(P2P, INFO, + "p2pFuncStartRdd: Start Radar detection - DFS ctrl: %d, RDD index: %d\n", + prCmdRddOnOffCtrl->ucDfsCtrl, prCmdRddOnOffCtrl->ucRddIdx); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_RDD_ON_OFF_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(*prCmdRddOnOffCtrl), + (uint8_t *) prCmdRddOnOffCtrl, NULL, 0); + + cnmMemFree(prAdapter, prCmdRddOnOffCtrl); +} /* p2pFuncStartRdd */ + +void p2pFuncStopRdd(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIdx) +{ + struct CMD_RDD_ON_OFF_CTRL *prCmdRddOnOffCtrl; + + DEBUGFUNC("p2pFuncStopRdd()"); + + prCmdRddOnOffCtrl = (struct CMD_RDD_ON_OFF_CTRL *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(*prCmdRddOnOffCtrl)); + + if (!prCmdRddOnOffCtrl) { + DBGLOG(P2P, ERROR, + "cnmMemAlloc for prCmdRddOnOffCtrl failed!\n"); + return; + } + + prCmdRddOnOffCtrl->ucDfsCtrl = RDD_STOP; + + /* + * FIX ME: Mobile driver can't get correct band. + * There is only 5G in DFS channel, + * which is on band_0. So it assigned to ENUM_BAND_0 as temp solution. + * Remember to fix it when driver could get + * the correct band from firmware. + */ + prCmdRddOnOffCtrl->ucRddIdx = ENUM_BAND_0; + + if (prCmdRddOnOffCtrl->ucRddIdx) + prCmdRddOnOffCtrl->ucRddRxSel = RDD_IN_SEL_1; + else + prCmdRddOnOffCtrl->ucRddRxSel = RDD_IN_SEL_0; + + DBGLOG(P2P, INFO, + "p2pFuncStopRdd: Stop Radar detection - DFS ctrl: %d, RDD index: %d\n", + prCmdRddOnOffCtrl->ucDfsCtrl, prCmdRddOnOffCtrl->ucRddIdx); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_RDD_ON_OFF_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(*prCmdRddOnOffCtrl), + (uint8_t *) prCmdRddOnOffCtrl, NULL, 0); + + cnmMemFree(prAdapter, prCmdRddOnOffCtrl); + +} /* p2pFuncStopRdd */ + + +void p2pFuncDfsSwitchCh(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct P2P_CHNL_REQ_INFO rP2pChnlReqInfo) +{ + + struct GLUE_INFO *prGlueInfo; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct CMD_RDD_ON_OFF_CTRL *prCmdRddOnOffCtrl; + struct GL_P2P_INFO *prP2PInfo = NULL; + + DEBUGFUNC("p2pFuncDfsSwitchCh()"); + + if (!prBssInfo) { + DBGLOG(P2P, ERROR, "prBssInfo shouldn't be NULL!\n"); + return; + } + + /* Setup Channel, Band */ + prBssInfo->ucPrimaryChannel = rP2pChnlReqInfo.ucReqChnlNum; + prBssInfo->eBand = rP2pChnlReqInfo.eBand; + prBssInfo->eBssSCO = rP2pChnlReqInfo.eChnlSco; + +/* To Support Cross Band Channel Swtich */ +#if CFG_SUPPORT_IDC_CH_SWITCH + if (prBssInfo->eBand == BAND_5G) { + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = + (prAdapter->rWifiVar.ucAvailablePhyTypeSet + & PHY_TYPE_SET_802_11AN); + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_11A; + } else { /* Only SAP mode should enter this function */ + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = + (prAdapter->rWifiVar.ucAvailablePhyTypeSet + & PHY_TYPE_SET_802_11BGN); + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; + } + + /* Overwrite BSS PHY type set by Feature Options */ + bssDetermineApBssInfoPhyTypeSet(prAdapter, + TRUE, prBssInfo); + + prBssInfo->ucNonHTBasicPhyType = (uint8_t) + rNonHTApModeAttributes + [prBssInfo->ucConfigAdHocAPMode] + .ePhyTypeIndex; + prBssInfo->u2BSSBasicRateSet = + rNonHTApModeAttributes + [prBssInfo->ucConfigAdHocAPMode] + .u2BSSBasicRateSet; + prBssInfo->u2OperationalRateSet = + rNonHTPhyAttributes + [prBssInfo->ucNonHTBasicPhyType] + .u2SupportedRateSet; + kalMemZero(prBssInfo->aucAllSupportedRates, RATE_NUM_SW); + rateGetDataRatesFromRateSet( + prBssInfo->u2OperationalRateSet, + prBssInfo->u2BSSBasicRateSet, + prBssInfo->aucAllSupportedRates, + &prBssInfo->ucAllSupportedRatesLen); +#endif + + /* Setup channel and bandwidth */ + rlmBssInitForAPandIbss(prAdapter, prBssInfo); + + /* Update Beacon again for network phy type confirmed. */ + bssUpdateBeaconContent(prAdapter, prBssInfo->ucBssIndex); + + /* Reset HW TSF Update Mode and Beacon Mode */ + nicUpdateBss(prAdapter, prBssInfo->ucBssIndex); + + prCmdRddOnOffCtrl = (struct CMD_RDD_ON_OFF_CTRL *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(*prCmdRddOnOffCtrl)); + + if (!prCmdRddOnOffCtrl) { + DBGLOG(P2P, ERROR, + "cnmMemAlloc for prCmdRddOnOffCtrl failed!\n"); + return; + } + + prCmdRddOnOffCtrl->ucDfsCtrl = RDD_START_TXQ; + + /* + * FIX ME: Mobile driver can't get correct band. + * There is only 5G in DFS channel, + * which is on band_0. So it assigned to ENUM_BAND_0 + * as temp solution. + * Remember to fix it when driver could get + * the correct band from firmware. + */ + prCmdRddOnOffCtrl->ucRddIdx = ENUM_BAND_0; + + DBGLOG(P2P, INFO, + "p2pFuncDfsSwitchCh: Start TXQ - DFS ctrl: %.d\n", + prCmdRddOnOffCtrl->ucDfsCtrl); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_RDD_ON_OFF_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(*prCmdRddOnOffCtrl), + (uint8_t *) prCmdRddOnOffCtrl, + NULL, 0); + + cnmMemFree(prAdapter, prCmdRddOnOffCtrl); + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prBssInfo->u4PrivateData); + + prGlueInfo = prAdapter->prGlueInfo; + prP2PInfo = (struct GL_P2P_INFO *)prGlueInfo-> + prP2PInfo[prP2pRoleFsmInfo->ucRoleIndex]; + + if (prP2PInfo->chandef) { + if (prP2PInfo->prDevHandler) { + DBGLOG(P2P, INFO, "p2pFuncDfsSwitchCh: Update to OS\n"); + cfg80211_ch_switch_notify( + prP2PInfo->prDevHandler, + prP2PInfo->chandef); + DBGLOG(P2P, INFO, + "p2pFuncDfsSwitchCh: Update to OS Done\n"); + } else + DBGLOG(P2P, ERROR, "NULL prDevHandler\n"); + } else + DBGLOG(P2P, ERROR, "NULL chandef\n"); +} /* p2pFuncDfsSwitchCh */ + +u_int8_t p2pFuncCheckWeatherRadarBand( + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo) +{ + uint8_t ucReqChnlNum; + uint8_t ucCenterFreqS1; + enum ENUM_CHANNEL_WIDTH eChannelWidth; + enum ENUM_CHNL_EXT eChnlSco; + + + ucReqChnlNum = prChnlReqInfo->ucReqChnlNum; + ucCenterFreqS1 = prChnlReqInfo->ucCenterFreqS1; + eChannelWidth = prChnlReqInfo->eChannelWidth; + eChnlSco = prChnlReqInfo->eChnlSco; + + if (rlmDomainGetDfsRegion() == NL80211_DFS_ETSI) { + if (eChannelWidth == VHT_OP_CHANNEL_WIDTH_80) { + if (ucCenterFreqS1 >= 120 && ucCenterFreqS1 <= 128) + return TRUE; + } else { + if ((ucReqChnlNum >= 120 && ucReqChnlNum <= 128)) + return TRUE; + else if (ucReqChnlNum == 116 + && eChnlSco == CHNL_EXT_SCA) + return TRUE; /* ch116, 120 BW40 */ + } + } + + return FALSE; +} + +int32_t p2pFuncSetDriverCacTime(IN uint32_t u4CacTime) +{ + uint32_t i4Status = WLAN_STATUS_SUCCESS; + + g_u4DriverCacTime = u4CacTime; + + DBGLOG(P2P, INFO, + "p2pFuncSetDriverCacTime: g_u4ManualCacTime = %dsec\n", + g_u4DriverCacTime); + + return i4Status; +} + +void p2pFuncEnableManualCac(void) +{ + g_fgManualCac = TRUE; +} + +uint32_t p2pFuncGetDriverCacTime(void) +{ + return g_u4DriverCacTime; +} + +u_int8_t p2pFuncIsManualCac(void) +{ + return g_fgManualCac; +} + +void p2pFuncRadarInfoInit(void) +{ + kalMemZero(&g_rP2pRadarInfo, sizeof(g_rP2pRadarInfo)); +} + +void p2pFuncShowRadarInfo(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIdx) +{ + uint8_t ucCnt = 0; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + uint8_t ucReqChnlNum; + + if (g_rP2pRadarInfo.ucRadarReportMode == 1) { + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prAdapter->aprBssInfo[ucBssIdx]->u4PrivateData); + + ucReqChnlNum = prP2pRoleFsmInfo->rChnlReqInfo.ucReqChnlNum; + + DBGLOG(P2P, INFO, "-----Radar Detected Event-----\n"); + DBGLOG(P2P, INFO, + "Radar detected in DBDC band%d\n", + g_rP2pRadarInfo.ucRddIdx); + + switch (rlmDomainGetDfsRegion()) { + case NL80211_DFS_FCC: + DBGLOG(P2P, INFO, "Regulation domain: FCC\n"); + break; + case NL80211_DFS_ETSI: + DBGLOG(P2P, INFO, "Regulation domain: ETSI\n"); + break; + case NL80211_DFS_JP: + DBGLOG(P2P, INFO, "Regulation domain: JP\n"); + + if (ucReqChnlNum >= 52 && ucReqChnlNum <= 64) + DBGLOG(P2P, INFO, + "Radar type: W53 - %s\n", + p2pFuncJpW53RadarType()); + else if (ucReqChnlNum >= 100 && ucReqChnlNum <= 140) + DBGLOG(P2P, INFO, + "Radar type: W56 - %s\n", + p2pFuncJpW56RadarType()); + break; + default: + break; + } + + DBGLOG(P2P, INFO, "Radar Content:\n"); + + DBGLOG(P2P, INFO, "start time pulse width PRI\n"); + + if (g_rP2pRadarInfo.ucPeriodicDetected) { + DBGLOG(P2P, INFO, "%-10d %-11d -\n" + , g_rP2pRadarInfo.arPpbContent + [ucCnt].u4PeriodicStartTime + , g_rP2pRadarInfo.arPpbContent + [ucCnt].u2PeriodicPulseWidth); + + for (ucCnt = 1; + ucCnt < g_rP2pRadarInfo.ucPPBNum; ucCnt++) { + DBGLOG(P2P, INFO, "%-10d %-11d %d\n" + , g_rP2pRadarInfo.arPpbContent + [ucCnt].u4PeriodicStartTime + , g_rP2pRadarInfo.arPpbContent + [ucCnt].u2PeriodicPulseWidth + , (g_rP2pRadarInfo.arPpbContent + [ucCnt].u4PeriodicStartTime + - g_rP2pRadarInfo.arPpbContent + [ucCnt-1].u4PeriodicStartTime) + * 2 / 5); + } + } else if (g_rP2pRadarInfo.ucLongDetected) { + DBGLOG(P2P, INFO, "%-10d %-11d -\n" + , g_rP2pRadarInfo.arLpbContent + [ucCnt].u4LongStartTime + , g_rP2pRadarInfo.arLpbContent + [ucCnt].u2LongPulseWidth); + + for (ucCnt = 1; + ucCnt < g_rP2pRadarInfo.ucLPBNum; ucCnt++) { + DBGLOG(P2P, INFO, "%-10d %-11d %d\n" + , g_rP2pRadarInfo.arLpbContent + [ucCnt].u4LongStartTime + , g_rP2pRadarInfo.arLpbContent + [ucCnt].u2LongPulseWidth + , (g_rP2pRadarInfo.arLpbContent + [ucCnt].u4LongStartTime + - g_rP2pRadarInfo.arLpbContent + [ucCnt-1].u4LongStartTime) + * 2 / 5); + } + } + } +} + +void p2pFuncGetRadarInfo(IN struct P2P_RADAR_INFO *prP2pRadarInfo) +{ + kalMemCopy(prP2pRadarInfo, &g_rP2pRadarInfo, sizeof(*prP2pRadarInfo)); +} + +uint8_t *p2pFuncJpW53RadarType(void) +{ + uint32_t u4Type1Diff; + uint32_t u4Type2Diff; + + if (g_rP2pRadarInfo.u4PRI1stUs >= 1428) + u4Type1Diff = g_rP2pRadarInfo.u4PRI1stUs - 1428; + else + u4Type1Diff = 1428 - g_rP2pRadarInfo.u4PRI1stUs; + + if (g_rP2pRadarInfo.u4PRI1stUs >= 3846) + u4Type2Diff = g_rP2pRadarInfo.u4PRI1stUs - 3846; + else + u4Type2Diff = 3846 - g_rP2pRadarInfo.u4PRI1stUs; + + if (u4Type1Diff < u4Type2Diff) + return apucW53RadarType[1]; + else + return apucW53RadarType[2]; +} + +uint8_t *p2pFuncJpW56RadarType(void) +{ + uint32_t u4Type1Diff; + uint32_t u4Type2Diff; + + if (g_rP2pRadarInfo.ucLongDetected) + return apucW56RadarType[7]; + + if (g_rP2pRadarInfo.u4PRI1stUs >= 3980 + && g_rP2pRadarInfo.u4PRI1stUs <= 4020) + return apucW56RadarType[3]; + + if (g_rP2pRadarInfo.u4PRI1stUs >= 1368 + && g_rP2pRadarInfo.u4PRI1stUs <= 1448) { + + if (g_rP2pRadarInfo.u4PRI1stUs >= 1388) + u4Type1Diff = g_rP2pRadarInfo.u4PRI1stUs - 1388; + else + u4Type1Diff = 1388 - g_rP2pRadarInfo.u4PRI1stUs; + + if (g_rP2pRadarInfo.u4PRI1stUs >= 1428) + u4Type2Diff = g_rP2pRadarInfo.u4PRI1stUs - 1428; + else + u4Type2Diff = 1428 - g_rP2pRadarInfo.u4PRI1stUs; + + if (u4Type1Diff < u4Type2Diff) + return apucW56RadarType[1]; + else + return apucW56RadarType[2]; + + } + + if (g_rP2pRadarInfo.u4PRI1stUs >= 130 + && g_rP2pRadarInfo.u4PRI1stUs < 200) + return apucW56RadarType[4]; + + if (g_rP2pRadarInfo.u4PRI1stUs >= 200 + && g_rP2pRadarInfo.u4PRI1stUs <= 520) { + + if (g_rP2pRadarInfo.u4PRI1stUs <= 230) + return apucW56RadarType[9]; + + if (g_rP2pRadarInfo.u4PRI1stUs >= 323 + && g_rP2pRadarInfo.u4PRI1stUs <= 343) + return apucW56RadarType[10]; + + return apucW56RadarType[11]; + } + + return apucW56RadarType[0]; +} + +void p2pFuncSetRadarDetectMode(IN uint8_t ucRadarDetectMode) +{ + g_ucRadarDetectMode = ucRadarDetectMode; + + DBGLOG(P2P, INFO, + "p2pFuncSetRadarDetectMode: g_ucRadarDetectMode: %d\n", + g_ucRadarDetectMode); +} + +uint8_t p2pFuncGetRadarDetectMode(void) +{ + return g_ucRadarDetectMode; +} + +void p2pFuncSetDfsState(IN uint8_t ucDfsState) +{ + DBGLOG(P2P, INFO, + "[DFS_STATE] TRANSITION: [%s] -> [%s]\n", + apucDfsState[g_ucDfsState], apucDfsState[ucDfsState]); + + g_ucDfsState = ucDfsState; +} + +uint8_t p2pFuncGetDfsState(void) +{ + return g_ucDfsState; +} + +uint8_t *p2pFuncShowDfsState(void) +{ + return apucDfsState[g_ucDfsState]; +} + +void p2pFuncRecordCacStartBootTime(void) +{ + g_u4CacStartBootTime = kalGetBootTime(); +} + +uint32_t p2pFuncGetCacRemainingTime(void) +{ + uint32_t u4CurrentBootTime; + uint32_t u4CacRemainingTime; + + u4CurrentBootTime = kalGetBootTime(); + + u4CacRemainingTime = g_u4DriverCacTime - + (u4CurrentBootTime - g_u4CacStartBootTime)/1000000; + + return u4CacRemainingTime; +} +#endif + +#if 0 +uint32_t +p2pFuncBeaconUpdate(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBcnHdr, + IN uint32_t u4HdrLen, + IN uint8_t *pucBcnBody, + IN uint32_t u4BodyLen, + IN uint32_t u4DtimPeriod, + IN uint32_t u4BcnInterval) +{ + uint32_t rResultStatus = WLAN_STATUS_INVALID_DATA; + struct WLAN_BEACON_FRAME *prBcnFrame = + (struct WLAN_BEACON_FRAME *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct MSDU_INFO *prBcnMsduInfo = (struct MSDU_INFO *) NULL; + uint8_t *pucTIMBody = (uint8_t *) NULL; + uint16_t u2FrameLength = 0, uint16_t u2OldBodyLen = 0; + uint8_t 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. */ + uint16_t u2IELength = 0, u2Offset = 0; + uint8_t *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 = (uint16_t) ((uint32_t) pucTIMBody - + (uint32_t) prBcnFrame->aucInfoElem); + /* Move body. */ + kalMemCmp(aucIEBuf, pucTIMBody, u2OldBodyLen); + } while (FALSE); + if (pucBcnHdr) { + kalMemCopy(prBcnMsduInfo->prPacket, + pucBcnHdr, u4HdrLen); + pucTIMBody = (uint8_t *) + ((uint32_t) prBcnMsduInfo->prPacket + u4HdrLen); + prBcnMsduInfo->ucMacHeaderLength = + (WLAN_MAC_MGMT_HEADER_LEN + + (TIMESTAMP_FIELD_LEN + + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN)); + /* Header + Partial Body. */ + u2FrameLength = u4HdrLen; + } else { + /* Header not change. */ + u2FrameLength += prBcnMsduInfo->ucMacHeaderLength; + } + + if (pucBcnBody) { + kalMemCopy(pucTIMBody, pucBcnBody, u4BodyLen); + u2FrameLength += (uint16_t) 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 = (uint16_t) u4BcnInterval; + prP2pBssInfo->ucDTIMPeriod = (uint8_t) u4DtimPeriod; + prP2pBssInfo->u2CapInfo = prBcnFrame->u2CapInfo; + prBcnMsduInfo->ucPacketType = 3; + rResultStatus = nicUpdateBeaconIETemplate(prAdapter, + IE_UPD_METHOD_UPDATE_ALL, + NETWORK_TYPE_P2P_INDEX, + prP2pBssInfo->u2CapInfo, + (uint8_t *) prBcnFrame->aucInfoElem, + prBcnMsduInfo->u2FrameLength - + OFFSET_OF(struct WLAN_BEACON_FRAME, 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 +uint32_t +p2pFuncBeaconUpdate(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN struct P2P_BEACON_UPDATE_INFO *prBcnUpdateInfo, + IN uint8_t *pucNewBcnHdr, + IN uint32_t u4NewHdrLen, + IN uint8_t *pucNewBcnBody, + IN uint32_t u4NewBodyLen) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct WLAN_BEACON_FRAME *prBcnFrame = + (struct WLAN_BEACON_FRAME *) NULL; + struct MSDU_INFO *prBcnMsduInfo = (struct MSDU_INFO *) NULL; + uint8_t *pucIEBuf = (uint8_t *) NULL; + uint8_t aucIEBuf[MAX_IE_LENGTH]; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prP2pBssInfo != NULL) + && (prBcnUpdateInfo != NULL)); + + prBcnMsduInfo = prP2pBssInfo->prBeacon; + +#if DBG + if (prBcnUpdateInfo->pucBcnHdr != NULL) { + ASSERT((uint32_t) prBcnUpdateInfo->pucBcnHdr == + ((uint32_t) prBcnMsduInfo->prPacket + + MAC_TX_RESERVED_FIELD)); + } + + if (prBcnUpdateInfo->pucBcnBody != NULL) { + ASSERT((uint32_t) prBcnUpdateInfo->pucBcnBody == + ((uint32_t) prBcnUpdateInfo->pucBcnHdr + + (uint32_t) prBcnUpdateInfo->u4BcnHdrLen)); + } +#endif + prBcnFrame = (struct WLAN_BEACON_FRAME *) + ((unsigned long) 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 = (uint8_t *) prBcnFrame; + prBcnUpdateInfo->u4BcnHdrLen = u4NewHdrLen; + } + + pucIEBuf = (uint8_t *) + ((unsigned long) prBcnUpdateInfo->pucBcnHdr + + (unsigned long) prBcnUpdateInfo->u4BcnHdrLen); + kalMemCopy(pucIEBuf, aucIEBuf, u4NewBodyLen); + prBcnUpdateInfo->pucBcnBody = pucIEBuf; + + /* Frame Length */ + prBcnMsduInfo->u2FrameLength = (uint16_t) + (prBcnUpdateInfo->u4BcnHdrLen + + prBcnUpdateInfo->u4BcnBodyLen); + + prBcnMsduInfo->ucPacketType = TX_PACKET_TYPE_MGMT; + prBcnMsduInfo->fgIs802_11 = TRUE; + prBcnMsduInfo->ucBssIndex = prP2pBssInfo->ucBssIndex; + + /* 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, + (uint8_t *) prBcnFrame->aucInfoElem, + (prBcnMsduInfo->u2FrameLength - + OFFSET_OF(struct WLAN_BEACON_FRAME, aucInfoElem))); + +#if 1 + /* bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_P2P_INDEX); */ +#else + nicUpdateBeaconIETemplate(prAdapter, + IE_UPD_METHOD_UPDATE_ALL, + NETWORK_TYPE_P2P_INDEX, + prBcnFrame->u2CapInfo, + (uint8_t *) prBcnFrame->aucInfoElem, + (prBcnMsduInfo->u2FrameLength - + OFFSET_OF(struct WLAN_BEACON_FRAME, aucInfoElem))); +#endif + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncBeaconUpdate */ + +/*---------------------------------------------------------------------------*/ +/*! + * \brief This function is to update extra IEs (ex: WPS) for assoc resp. + * Caller should sanity check the params. + * + * \param[in] prAdapter Pointer of ADAPTER_T + * \param[in] prP2pBssInfo Pointer to BSS_INFO_T structure + * \param[in] AssocRespIE Pointer to extra IEs for assoc resp + * \param[in] u4AssocRespLen Length of extra IEs for assoc resp + * + * \return WLAN_STATUS + */ +/*---------------------------------------------------------------------------*/ + +uint32_t +p2pFuncAssocRespUpdate(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN uint8_t *AssocRespIE, IN uint32_t u4AssocRespLen) +{ + uint8_t ucOuiType = 0; + uint16_t u2SubTypeVersion = 0; + + if (!rsnParseCheckForWFAInfoElem(prAdapter, + AssocRespIE, &ucOuiType, &u2SubTypeVersion)) + return WLAN_STATUS_FAILURE; + + if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + kalP2PUpdateWSC_IE(prAdapter->prGlueInfo, 3, + (uint8_t *)AssocRespIE, IE_SIZE(AssocRespIE), + (uint8_t) (prP2pBssInfo->u4PrivateData)); + } + + return WLAN_STATUS_SUCCESS; +} + +#endif + +#if 0 +/* TODO: We do not apply IE in deauth frame set from upper layer now. */ +uint32_t +p2pFuncDeauth(IN struct ADAPTER *prAdapter, + IN uint8_t *pucPeerMacAddr, + IN uint16_t u2ReasonCode, + IN uint8_t *pucIEBuf, + IN uint16_t u2IELen, + IN u_int8_t fgSendDeauth) +{ + uint32_t rWlanStatus = WLAN_STATUS_FAILURE; + struct STA_RECORD *prCliStaRec = (struct STA_RECORD *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + u_int8_t 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: + { + struct LINK *prStaRecOfClientList = + (struct LINK *) NULL; + struct LINK_ENTRY *prLinkEntry = + (struct LINK_ENTRY *) NULL; + + prStaRecOfClientList = + &(prP2pBssInfo->rStaRecOfClientList); + + LINK_FOR_EACH(prLinkEntry, + prStaRecOfClientList) { + if ((uint32_t) prCliStaRec + == (uint32_t) 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. */ +uint32_t +p2pFuncDisassoc(IN struct ADAPTER *prAdapter, + IN uint8_t *pucPeerMacAddr, + IN uint16_t u2ReasonCode, + IN uint8_t *pucIEBuf, + IN uint16_t u2IELen, + IN u_int8_t fgSendDisassoc) +{ + uint32_t rWlanStatus = WLAN_STATUS_FAILURE; + struct STA_RECORD *prCliStaRec = (struct STA_RECORD *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + u_int8_t 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: + { + struct LINK *prStaRecOfClientList = + (struct LINK *) NULL; + struct LINK_ENTRY *prLinkEntry = + (struct LINK_ENTRY *) NULL; + + prStaRecOfClientList = + &(prP2pBssInfo->rStaRecOfClientList); + + LINK_FOR_EACH(prLinkEntry, + prStaRecOfClientList) { + if ((uint32_t) prCliStaRec + == (uint32_t) 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); */ + + } + + rWlanStatus = WLAN_STATUS_SUCCESS; + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncDisassoc */ + +#endif + +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP +uint32_t +p2pFuncProbeRespUpdate(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN uint8_t *ProbeRespIE, IN uint32_t u4ProbeRespLen) + +{ + struct MSDU_INFO *prMsduInfo = (struct MSDU_INFO *) NULL; + uint32_t u4IeArraySize = 0, u4Idx = 0; + uint8_t *pucP2pIe = (uint8_t *) NULL; + uint8_t *pucWpsIe = (uint8_t *) NULL; + uint8_t *pucWfdIe = (uint8_t *) NULL; + + if (prP2pBssInfo == NULL) + return WLAN_STATUS_FAILURE; + + /* reuse beacon MsduInfo */ + prMsduInfo = prP2pBssInfo->prBeacon; + + /* beacon prMsduInfo will be NULLify + * once BSS deactivated, so skip if it is + */ + if (!prMsduInfo) + return WLAN_STATUS_SUCCESS; + + if (!ProbeRespIE) { + DBGLOG(BSS, INFO, + "change beacon: has no extra probe response IEs\n"); + return WLAN_STATUS_SUCCESS; + } + if (p2pFuncIsAPMode( + prAdapter->rWifiVar + .prP2PConnSettings[prP2pBssInfo->u4PrivateData])) { + DBGLOG(BSS, INFO, + "change beacon: pure Ap mode do not add extra probe response IEs\n"); + return WLAN_STATUS_SUCCESS; + } + prMsduInfo->u2FrameLength = 0; + + bssBuildBeaconProbeRespFrameCommonIEs(prMsduInfo, + prP2pBssInfo, ProbeRespIE); + + u4IeArraySize = + sizeof(txProbeRspIETable) / sizeof(struct APPEND_VAR_IE_ENTRY); + + for (u4Idx = 0; u4Idx < u4IeArraySize; u4Idx++) { + if (txProbeRspIETable[u4Idx].pfnAppendIE) + txProbeRspIETable[u4Idx] + .pfnAppendIE(prAdapter, prMsduInfo); + } + + /* process probe response IE from supplicant */ + pucP2pIe = (uint8_t *) cfg80211_find_vendor_ie(WLAN_OUI_WFA, + WLAN_OUI_TYPE_WFA_P2P, + ProbeRespIE, + u4ProbeRespLen); + + pucWfdIe = (uint8_t *) cfg80211_find_vendor_ie(WLAN_OUI_WFA, + WLAN_OUI_TYPE_WFA_P2P + 1, + ProbeRespIE, + u4ProbeRespLen); + + pucWpsIe = (uint8_t *) cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, + WLAN_OUI_TYPE_MICROSOFT_WPS, + ProbeRespIE, + u4ProbeRespLen); + + if (pucP2pIe) { + kalMemCopy(prMsduInfo->prPacket + prMsduInfo->u2FrameLength, + pucP2pIe, IE_SIZE(pucP2pIe)); + prMsduInfo->u2FrameLength += IE_SIZE(pucP2pIe); + } + + if (pucWfdIe) { + kalMemCopy(prMsduInfo->prPacket + prMsduInfo->u2FrameLength, + pucWfdIe, IE_SIZE(pucWfdIe)); + prMsduInfo->u2FrameLength += IE_SIZE(pucWfdIe); + } + + if (pucWpsIe) { + kalMemCopy(prMsduInfo->prPacket + prMsduInfo->u2FrameLength, + pucWpsIe, IE_SIZE(pucWpsIe)); + prMsduInfo->u2FrameLength += IE_SIZE(pucWpsIe); + } + + DBGLOG(BSS, INFO, + "update probe response for bss index: %d, IE len: %d\n", + prP2pBssInfo->ucBssIndex, prMsduInfo->u2FrameLength); + /* dumpMemory8(prMsduInfo->prPacket, prMsduInfo->u2FrameLength); */ + + return nicUpdateBeaconIETemplate(prAdapter, + IE_UPD_METHOD_UPDATE_PROBE_RSP, + prP2pBssInfo->ucBssIndex, + prP2pBssInfo->u2CapInfo, + prMsduInfo->prPacket, + prMsduInfo->u2FrameLength); +} +#endif + +/*---------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN u_int8_t fgSendDeauth, + IN uint16_t u2ReasonCode) +{ + struct STA_RECORD *prCurrStaRec, *prStaRecNext; + struct LINK *prClientList; + + DEBUGFUNC("p2pFuncDissolve()"); + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_INFRASTRUCTURE: + /* Reset station record status. */ + if (prP2pBssInfo->prStaRecOfAP) { +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) + kalP2PGCIndicateConnectionStatus( + prAdapter->prGlueInfo, + (uint8_t) prP2pBssInfo->u4PrivateData, + NULL, NULL, 0, + REASON_CODE_DEAUTH_LEAVING_BSS, + WLAN_STATUS_MEDIA_DISCONNECT); +#else + kalP2PGCIndicateConnectionStatus( + prAdapter->prGlueInfo, + (uint8_t) prP2pBssInfo->u4PrivateData, + NULL, NULL, 0, + REASON_CODE_DEAUTH_LEAVING_BSS); +#endif + + /* 2012/02/14 frog: + * After formation before join group, + * prStaRecOfAP is NULL. + */ + p2pFuncDisconnect(prAdapter, + prP2pBssInfo, + prP2pBssInfo->prStaRecOfAP, + fgSendDeauth, + u2ReasonCode); + } + + /* Fix possible KE when RX Beacon & + * call nicPmIndicateBssConnected(). + * hit prStaRecOfAP == NULL. + */ + p2pChangeMediaState(prAdapter, + prP2pBssInfo, + 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. + */ + /* Send deauth. */ + authSendDeauthFrame(prAdapter, + prP2pBssInfo, + NULL, (struct SW_RFB *) NULL, + u2ReasonCode, (PFN_TX_DONE_HANDLER) NULL); + + prClientList = &prP2pBssInfo->rStaRecOfClientList; + + /* This case may let LINK_FOR_EACH_ENTRY_SAFE crash */ + if (prClientList == NULL) + break; + LINK_FOR_EACH_ENTRY_SAFE(prCurrStaRec, prStaRecNext, + prClientList, rLinkEntry, struct STA_RECORD) { + ASSERT(prCurrStaRec); + p2pFuncDisconnect(prAdapter, + prP2pBssInfo, prCurrStaRec, + TRUE, u2ReasonCode); + } + break; + default: + return; /* 20110420 -- alreay in Device Mode. */ + } + + /* Make the deauth frame send to FW ASAP. */ +#if !CFG_SUPPORT_MULTITHREAD + wlanAcquirePowerControl(prAdapter); +#endif + wlanProcessCommandQueue(prAdapter, + &prAdapter->prGlueInfo->rCmdQueue); +#if !CFG_SUPPORT_MULTITHREAD + wlanReleasePowerControl(prAdapter); +#endif + + /*kalMdelay(100);*/ + + /* Change Connection Status. */ + /* 20161025, can not set DISCONNECTED if clientcount > 0 */ + /*p2pChangeMediaState(prAdapter, + * prP2pBssInfo, PARAM_MEDIA_STATE_DISCONNECTED); + */ + + } while (FALSE); +} /* p2pFuncDissolve */ + +/*---------------------------------------------------------------------------*/ +/*! + * @brief This function is called to dissolve from group or one group. + * (Would not change P2P FSM.) + * 1. GC: Disconnect from AP. (Send Deauth) + * 2. GO: Disconnect all STA + * + * @param[in] prAdapter Pointer to the adapter structure. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void +p2pFuncDisconnect(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN struct STA_RECORD *prStaRec, + IN u_int8_t fgSendDeauth, IN uint16_t u2ReasonCode) +{ + enum ENUM_PARAM_MEDIA_STATE eOriMediaStatus; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prStaRec != NULL) && (prP2pBssInfo != NULL)); + + ASSERT_BREAK(prP2pBssInfo->eNetworkType == NETWORK_TYPE_P2P); + + ASSERT_BREAK(prP2pBssInfo->ucBssIndex + < prAdapter->ucP2PDevBssIdx); + + eOriMediaStatus = prP2pBssInfo->eConnectionState; + + /* Indicate disconnect. */ + if (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData); + + kalP2PGOStationUpdate(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, prStaRec, FALSE); + } else { + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData); + + prP2pRoleFsmInfo->rJoinInfo.prTargetBssDesc = NULL; + + scanRemoveConnFlagOfBssDescByBssid(prAdapter, + prP2pBssInfo->aucBSSID); + } + + DBGLOG(P2P, INFO, + "p2pFuncDisconnect(): BssMode: %d, reason: %d, SendDeauth %s\n", + prP2pBssInfo->eCurrentOPMode, u2ReasonCode, + fgSendDeauth == TRUE ? "TRUE" : "FALSE"); + + if (fgSendDeauth) { + /* Send deauth. */ + authSendDeauthFrame(prAdapter, + prP2pBssInfo, + prStaRec, + (struct SW_RFB *) NULL, + u2ReasonCode, + (PFN_TX_DONE_HANDLER) + p2pRoleFsmRunEventDeauthTxDone); + + /* Make the deauth frame send to FW ASAP. */ +#if !CFG_SUPPORT_MULTITHREAD + wlanAcquirePowerControl(prAdapter); +#endif + wlanProcessCommandQueue(prAdapter, + &prAdapter->prGlueInfo->rCmdQueue); +#if !CFG_SUPPORT_MULTITHREAD + wlanReleasePowerControl(prAdapter); +#endif + } else { + /* Change station state. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + /* Reset Station Record Status. */ + p2pFuncResetStaRecStatus(prAdapter, prStaRec); + + cnmStaRecFree(prAdapter, prStaRec); + + if ((prP2pBssInfo->eCurrentOPMode + != OP_MODE_ACCESS_POINT) || + (bssGetClientCount(prAdapter, prP2pBssInfo) == 0)) { + DBGLOG(P2P, TRACE, + "No More Client, Media Status DISCONNECTED\n"); + p2pChangeMediaState(prAdapter, + prP2pBssInfo, + PARAM_MEDIA_STATE_DISCONNECTED); + } + + if (eOriMediaStatus != prP2pBssInfo->eConnectionState) { + /* Update Disconnected state to FW. */ + nicUpdateBss(prAdapter, + prP2pBssInfo->ucBssIndex); + } + + } + } while (FALSE); + + return; + +} /* p2pFuncDisconnect */ + +void p2pFuncSetChannel(IN struct ADAPTER *prAdapter, + IN uint8_t ucRoleIdx, + IN struct RF_CHANNEL_INFO *prRfChannelInfo) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct P2P_CONNECTION_REQ_INFO *prP2pConnReqInfo = + (struct P2P_CONNECTION_REQ_INFO *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prRfChannelInfo != NULL)); + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, ucRoleIdx); + if (!prP2pRoleFsmInfo) + break; + prP2pConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + + prP2pConnReqInfo->rChannelInfo.ucChannelNum = + prRfChannelInfo->ucChannelNum; + prP2pConnReqInfo->rChannelInfo.eBand = prRfChannelInfo->eBand; + prP2pConnReqInfo->eChnlBw = prRfChannelInfo->ucChnlBw; + prP2pConnReqInfo->u2PriChnlFreq = + prRfChannelInfo->u2PriChnlFreq; + prP2pConnReqInfo->u4CenterFreq1 = + prRfChannelInfo->u4CenterFreq1; + prP2pConnReqInfo->u4CenterFreq2 = + prRfChannelInfo->u4CenterFreq2; + + } while (FALSE); +} /* p2pFuncSetChannel */ + +/*---------------------------------------------------------------------------*/ +/*! + * @brief Retry JOIN for AUTH_MODE_AUTO_SWITCH + * + * @param[in] prStaRec Pointer to the STA_RECORD_T + * + * @retval TRUE We will retry JOIN + * @retval FALSE We will not retry JOIN + */ +/*---------------------------------------------------------------------------*/ +u_int8_t p2pFuncRetryJOIN(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct P2P_JOIN_INFO *prJoinInfo) +{ + struct MSG_SAA_FSM_START *prJoinReqMsg = + (struct MSG_SAA_FSM_START *) NULL; + u_int8_t fgRetValue = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prStaRec != NULL) + && (prJoinInfo != NULL)); + + /* Retry other AuthType if possible */ + if (!prJoinInfo->ucAvailableAuthTypes) + break; + + if (prJoinInfo->ucAvailableAuthTypes + & (uint8_t) AUTH_TYPE_SHARED_KEY) { + + DBGLOG(P2P, INFO, + "RETRY JOIN INIT: Retry Authentication with AuthType == SHARED_KEY.\n"); + + prJoinInfo->ucAvailableAuthTypes &= + ~(uint8_t) AUTH_TYPE_SHARED_KEY; + + prStaRec->ucAuthAlgNum = + (uint8_t) AUTH_ALGORITHM_NUM_SHARED_KEY; + } else { + DBGLOG(P2P, ERROR, + "RETRY JOIN INIT: Retry Authentication with Unexpected AuthType.\n"); + ASSERT(0); + break; + } + + /* No more available Auth Types */ + prJoinInfo->ucAvailableAuthTypes = 0; + + /* Trigger SAA to start JOIN process. */ + prJoinReqMsg = (struct MSG_SAA_FSM_START *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_SAA_FSM_START)); + 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, + (struct MSG_HDR *) prJoinReqMsg, + MSG_SEND_METHOD_BUF); + + fgRetValue = TRUE; + } while (FALSE); + + return fgRetValue; + +} /* end of p2pFuncRetryJOIN() */ + +struct BSS_INFO *p2pFuncBSSIDFindBssInfo(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBSSID) +{ + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + uint8_t ucBssIdx = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBSSID != NULL)); + + for (ucBssIdx = 0; + ucBssIdx < prAdapter->ucHwBssIdNum; ucBssIdx++) { + if (!IS_NET_ACTIVE(prAdapter, ucBssIdx)) + continue; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + + if (EQUAL_MAC_ADDR(prBssInfo->aucBSSID, pucBSSID) + && IS_BSS_P2P(prBssInfo)) + break; + + prBssInfo = NULL; + } + + } while (FALSE); + + return prBssInfo; +} /* p2pFuncBSSIDFindBssInfo */ + +/*---------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*---------------------------------------------------------------------------*/ +u_int8_t +p2pFuncValidateAuth(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN struct SW_RFB *prSwRfb, + IN struct STA_RECORD **pprStaRec, + OUT uint16_t *pu2StatusCode) +{ + u_int8_t fgPmfConn = FALSE; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + struct WLAN_AUTH_FRAME *prAuthFrame = (struct WLAN_AUTH_FRAME *) NULL; + + DBGLOG(P2P, TRACE, "p2pValidate Authentication Frame\n"); + + + /* P2P 3.2.8 */ + *pu2StatusCode = STATUS_CODE_REQ_DECLINED; + prAuthFrame = (struct WLAN_AUTH_FRAME *) prSwRfb->pvHeader; + + if ((prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) || + (prP2pBssInfo->eIntendOPMode != OP_MODE_NUM)) { + /* We are not under AP Mode yet. */ + DBGLOG(P2P, WARN, + "Current OP mode is not under AP mode. (%d)\n", + prP2pBssInfo->eCurrentOPMode); + return FALSE; + } + + prStaRec = cnmGetStaRecByAddress(prAdapter, + prP2pBssInfo->ucBssIndex, prAuthFrame->aucSrcAddr); + + if (!prStaRec) { + prStaRec = cnmStaRecAlloc(prAdapter, STA_TYPE_P2P_GC, + prP2pBssInfo->ucBssIndex, + prAuthFrame->aucSrcAddr); + + /* TODO(Kevin): Error handling of allocation of + * struct STA_RECORD for + * exhausted case and do removal of unused struct STA_RECORD. + */ + /* Sent a message event to clean un-used STA_RECORD_T. */ + if (!prStaRec) { + /* Error: Too many auth cause lacking the free StaRec. + * Response the auth with STATUS_CODE_REQ_DECLINED. + */ + DBGLOG(P2P, WARN, + "StaRec Full. (%d)\n", CFG_STA_REC_NUM); + return TRUE; + } + + 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; + + /* Update default Tx rate */ + nicTxUpdateStaRecDefaultRate(prStaRec); + + /* NOTE(Kevin): Better to change state here, not at TX Done */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + } else { +#if CFG_SUPPORT_802_11W + /* AP PMF. if PMF connection, do not reset state & FSM */ + fgPmfConn = rsnCheckBipKeyInstalled(prAdapter, prStaRec); + if (fgPmfConn) { + DBGLOG(P2P, WARN, "PMF Connction, return false\n"); + return FALSE; + } +#endif + + prSwRfb->ucStaRecIdx = prStaRec->ucIndex; + + if ((prStaRec->ucStaState > STA_STATE_1) + && (IS_STA_IN_P2P(prStaRec))) { + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + p2pFuncResetStaRecStatus(prAdapter, prStaRec); + + bssRemoveClient(prAdapter, prP2pBssInfo, prStaRec); + } + + } + + if (bssGetClientCount(prAdapter, prP2pBssInfo) + >= P2P_MAXIMUM_CLIENT_COUNT + || !p2pRoleProcessACLInspection(prAdapter, + prStaRec->aucMacAddr, prP2pBssInfo->ucBssIndex) +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + || kalP2PMaxClients(prAdapter->prGlueInfo, + bssGetClientCount(prAdapter, prP2pBssInfo), + (uint8_t) prP2pBssInfo->u4PrivateData) +#endif + ) { + /* GROUP limit full. */ + /* P2P 3.2.8 */ + DBGLOG(P2P, WARN, + "Group Limit Full. (%d)\n", + bssGetClientCount(prAdapter, prP2pBssInfo)); + cnmStaRecFree(prAdapter, prStaRec); + return TRUE; + } +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + else { + /* Hotspot Blacklist */ + if (kalP2PCmpBlackList(prAdapter->prGlueInfo, + prAuthFrame->aucSrcAddr, + (uint8_t) prP2pBssInfo->u4PrivateData)) { + DBGLOG(P2P, WARN, "in black list.\n"); + return FALSE; + } + + } +#endif + /* prStaRec->eStaType = STA_TYPE_INFRA_CLIENT; */ + prStaRec->eStaType = STA_TYPE_P2P_GC; + + /* Update Station Record - Status/Reason Code */ + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + + prStaRec->ucJoinFailureCount = 0; + + *pprStaRec = prStaRec; + + *pu2StatusCode = STATUS_CODE_SUCCESSFUL; + + + return TRUE; + +} /* p2pFuncValidateAuth */ + +void p2pFuncResetStaRecStatus(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + do { + if ((prAdapter == NULL) || (prStaRec == NULL)) { + ASSERT(FALSE); + break; + } + + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + prStaRec->u2ReasonCode = REASON_CODE_RESERVED; + prStaRec->ucJoinFailureCount = 0; + prStaRec->fgTransmitKeyExist = FALSE; + + prStaRec->fgSetPwrMgtBit = FALSE; + + } while (FALSE); +} /* p2pFuncResetStaRecStatus */ + +/*---------------------------------------------------------------------------*/ +/*! + * @brief The function is used to initialize the value + * of the connection settings for P2P network + * + * @param (none) + * + * @return (none) + */ +/*---------------------------------------------------------------------------*/ +void +p2pFuncInitConnectionSettings(IN struct ADAPTER *prAdapter, + IN struct P2P_CONNECTION_SETTINGS *prP2PConnSettings, + IN u_int8_t fgIsApMode) +{ + struct WIFI_VAR *prWifiVar = NULL; + + ASSERT(prP2PConnSettings); + + prWifiVar = &(prAdapter->rWifiVar); + ASSERT(prWifiVar); + + prP2PConnSettings->fgIsApMode = fgIsApMode; + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + prP2PConnSettings->fgIsWPSMode = prWifiVar->ucApWpsMode; +#endif +} /* p2pFuncInitConnectionSettings */ + +/*---------------------------------------------------------------------------*/ +/*! + * @brief This function will validate the Rx Assoc Req Frame and then return + * the status code to AAA to indicate if need + * to perform following actions + * when the specified conditions were matched. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] prSwRfb Pointer to SW RFB data structure. + * @param[out] pu2StatusCode The Status Code of Validation Result + * + * @retval TRUE Reply the Assoc Resp + * @retval FALSE Don't reply the Assoc Resp + */ +/*---------------------------------------------------------------------------*/ +u_int8_t p2pFuncValidateAssocReq(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + OUT uint16_t *pu2StatusCode) +{ + u_int8_t fgReplyAssocResp = TRUE; + struct WLAN_ASSOC_REQ_FRAME *prAssocReqFrame = + (struct WLAN_ASSOC_REQ_FRAME *) NULL; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + + /* 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; + prAssocReqFrame = + (struct WLAN_ASSOC_REQ_FRAME *) prSwRfb->pvHeader; + + prP2pBssInfo = + p2pFuncBSSIDFindBssInfo(prAdapter, + prAssocReqFrame->aucBSSID); + + if (prP2pBssInfo == NULL) { + DBGLOG(P2P, ERROR, + "RX ASSOC frame without BSS active / BSSID match\n"); + ASSERT(FALSE); + break; + } + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prStaRec == NULL) { + /* Station record should be ready + * while RX AUTH frame. + */ + fgReplyAssocResp = FALSE; + ASSERT(FALSE); + break; + } + ASSERT(prSwRfb->prRxStatusGroup3); + prStaRec->ucRCPI = + nicRxGetRcpiValueFromRxv(RCPI_MODE_MAX, prSwRfb); + + 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; + } + + *pu2StatusCode = STATUS_CODE_SUCCESSFUL; + + } while (FALSE); + + return fgReplyAssocResp; + +} /* p2pFuncValidateAssocReq */ + +/*---------------------------------------------------------------------------*/ +/*! +* @brief This function is used to check the TKIP IE +* +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t p2pFuncParseCheckForTKIPInfoElem(IN uint8_t *pucBuf) +{ + uint8_t aucWfaOui[] = VENDOR_OUI_WFA; + struct WPA_INFO_ELEM *prWpaIE = (struct WPA_INFO_ELEM *) NULL; + uint32_t u4GroupKeyCipher = 0; + + if (pucBuf == NULL) + return FALSE; + + prWpaIE = (struct WPA_INFO_ELEM *) pucBuf; + + if (prWpaIE->ucLength <= ELEM_MIN_LEN_WFA_OUI_TYPE_SUBTYPE) + return FALSE; + + if (kalMemCmp(prWpaIE->aucOui, aucWfaOui, sizeof(aucWfaOui))) + return FALSE; + + WLAN_GET_FIELD_32(&prWpaIE->u4GroupKeyCipherSuite, &u4GroupKeyCipher); + + if (prWpaIE->ucOuiType == VENDOR_OUI_TYPE_WPA && + u4GroupKeyCipher == WPA_CIPHER_SUITE_TKIP) + return TRUE; + else + return FALSE; +} /* p2pFuncParseCheckForP2PInfoElem */ + +/*---------------------------------------------------------------------------*/ +/*! + * @brief This function is used to check the P2P IE + * + * + * @return none + */ +/*---------------------------------------------------------------------------*/ +u_int8_t p2pFuncParseCheckForP2PInfoElem(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, OUT uint8_t *pucOuiType) +{ + uint8_t aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + struct IE_WFA *prWfaIE = (struct IE_WFA *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (pucBuf != NULL) && (pucOuiType != NULL)); + + prWfaIE = (struct IE_WFA *) 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 + */ +/*---------------------------------------------------------------------------*/ +u_int8_t +p2pFuncValidateProbeReq(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + OUT uint32_t *pu4ControlFlags, + IN u_int8_t fgIsDevInterface, + IN uint8_t ucRoleIdx) +{ + u_int8_t fgIsReplyProbeRsp = FALSE; + u_int8_t fgApplyp2PDevFilter = FALSE; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + + DEBUGFUNC("p2pFuncValidateProbeReq"); + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + + prP2pRoleFsmInfo = + prAdapter->rWifiVar.aprP2pRoleFsmInfo[ucRoleIdx]; + + /* Process both cases that with amd without add p2p interface */ + if (fgIsDevInterface) + fgApplyp2PDevFilter = TRUE; + else { + if (prAdapter->prGlueInfo->prP2PInfo[0]->prDevHandler == + prAdapter->prGlueInfo->prP2PInfo + [ucRoleIdx]->aprRoleHandler) + fgApplyp2PDevFilter = TRUE; + else + fgApplyp2PDevFilter = FALSE; + } + /* TODO: */ + if ((fgApplyp2PDevFilter && + (prAdapter->u4OsPacketFilter + & PARAM_PACKET_FILTER_PROBE_REQ)) + || (!fgApplyp2PDevFilter && + (prP2pRoleFsmInfo->u4P2pPacketFilter + & PARAM_PACKET_FILTER_PROBE_REQ))) { + /* Leave the probe response to p2p_supplicant. */ + kalP2PIndicateRxMgmtFrame(prAdapter->prGlueInfo, + prSwRfb, fgIsDevInterface, ucRoleIdx); + } + + } while (FALSE); + + return fgIsReplyProbeRsp; + +} /* end of p2pFuncValidateProbeReq() */ + +static void p2pFunBufferP2pActionFrame(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint8_t ucRoleIdx) +{ + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) NULL; + struct P2P_QUEUED_ACTION_FRAME *prFrame; + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + if (prP2pDevFsmInfo == NULL) + return; + + prFrame = &prP2pDevFsmInfo->rQueuedActionFrame; + + if (prFrame->u2Length > 0) { + DBGLOG(P2P, WARN, "p2p action frames are pending, drop it.\n"); + return; + } + + DBGLOG(P2P, INFO, "Buffer the p2p action frame.\n"); + prFrame->ucRoleIdx = ucRoleIdx; + prFrame->u4Freq = nicChannelNum2Freq( + HAL_RX_STATUS_GET_CHNL_NUM(prSwRfb->prRxStatus)) / 1000; + prFrame->u2Length = prSwRfb->u2PacketLen; + prFrame->prHeader = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, + prSwRfb->u2PacketLen); + if (prFrame->prHeader == NULL) { + DBGLOG(P2P, WARN, "Allocate buffer fail.\n"); + p2pFunCleanQueuedMgmtFrame(prAdapter, prFrame); + return; + } + kalMemCopy(prFrame->prHeader, prSwRfb->pvHeader, prSwRfb->u2PacketLen); +} + +/*---------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, IN u_int8_t fgIsDevInterface, + IN uint8_t ucRoleIdx) +{ + struct WLAN_ACTION_FRAME *prActFrame; + struct WLAN_PUBLIC_VENDOR_ACTION_FRAME *prActPubVenFrame; + uint32_t u4OUI; + u_int8_t fgBufferFrame = FALSE; + + DEBUGFUNC("p2pFuncValidateRxActionFrame"); + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + prActFrame = (struct WLAN_ACTION_FRAME *) prSwRfb->pvHeader; + + switch (prActFrame->ucCategory) { + case CATEGORY_PUBLIC_ACTION: + if (prActFrame->ucAction != 0x9) + break; + WLAN_GET_FIELD_BE32( + prActFrame->ucActionDetails, &u4OUI); + DBGLOG(P2P, TRACE, "Action: oui: 0x%x\n", u4OUI); + if (u4OUI != P2P_IE_VENDOR_TYPE || + prSwRfb->u2PacketLen < + sizeof(struct WLAN_PUBLIC_VENDOR_ACTION_FRAME)) + break; + + prActPubVenFrame = + (struct WLAN_PUBLIC_VENDOR_ACTION_FRAME *) + prActFrame; + p2pProcessActionResponse(prAdapter, + prActPubVenFrame->ucPubSubType); + if (fgIsDevInterface) { + p2pDevFsmNotifyP2pRx(prAdapter, + prActPubVenFrame->ucPubSubType, + &fgBufferFrame); + } + default: + break; + } + + if (fgBufferFrame) { + p2pFunBufferP2pActionFrame(prAdapter, + prSwRfb, + ucRoleIdx); + break; + } + + if (prAdapter->u4OsPacketFilter + & PARAM_PACKET_FILTER_ACTION_FRAME) { + /* Leave the Action frame to p2p_supplicant. */ + kalP2PIndicateRxMgmtFrame(prAdapter->prGlueInfo, + prSwRfb, fgIsDevInterface, ucRoleIdx); + } else { + struct GL_P2P_INFO *prGlueP2pInfo = NULL; + struct net_device *prNetdevice = + (struct net_device *)NULL; + + DBGLOG(P2P, INFO, + "do not indicate action frame as filter closed\n"); + if (ucRoleIdx >= BSS_P2P_NUM) + break; + prGlueP2pInfo = + prAdapter->prGlueInfo->prP2PInfo[ucRoleIdx]; + if (!prGlueP2pInfo) + break; + if (fgIsDevInterface) + prNetdevice = prGlueP2pInfo->prDevHandler; + else + prNetdevice = prGlueP2pInfo->aprRoleHandler; + if (prNetdevice && dev_valid_name(prNetdevice->name)) { + DBGLOG(P2P, WARN, + "[%s] unregistered p2p action packet filter 0x%x\n", + prNetdevice->name, + prAdapter->u4OsPacketFilter); + } + } + + } while (FALSE); + + return; + +} /* p2pFuncValidateRxMgmtFrame */ + +u_int8_t p2pFuncIsAPMode(IN struct P2P_CONNECTION_SETTINGS *prP2pConnSettings) +{ + if (prP2pConnSettings) { + if (prP2pConnSettings->fgIsWPSMode == 1) + return FALSE; + return prP2pConnSettings->fgIsApMode; + } else { + return FALSE; + } +} + +/* p2pFuncIsAPMode */ + +void +p2pFuncParseBeaconContent(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN uint8_t *pucIEInfo, IN uint32_t u4IELen) +{ + uint8_t *pucIE = (uint8_t *) NULL; + uint16_t u2Offset = 0; + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo = + (struct P2P_SPECIFIC_BSS_INFO *) NULL; + uint8_t i = 0; + struct RSN_INFO rRsnIe; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); + + if (u4IELen == 0) + break; + + prP2pSpecificBssInfo = + prAdapter->rWifiVar.prP2pSpecificBssInfo + [prP2pBssInfo->u4PrivateData]; + prP2pSpecificBssInfo->u2AttributeLen = 0; + + ASSERT_BREAK(pucIEInfo != NULL); + + pucIE = pucIEInfo; + + if (prP2pBssInfo->u2CapInfo & CAP_INFO_PRIVACY) + kalP2PSetCipher(prAdapter->prGlueInfo, + IW_AUTH_CIPHER_WEP40, + (uint8_t) prP2pBssInfo->u4PrivateData); + else + kalP2PSetCipher(prAdapter->prGlueInfo, + IW_AUTH_CIPHER_NONE, + (uint8_t) prP2pBssInfo->u4PrivateData); + + prP2pBssInfo->ucCountryIELen = 0; + + IE_FOR_EACH(pucIE, u4IELen, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_SSID: /* 0 *//* V *//* Done */ + { + + /* DBGLOG(P2P, TRACE, ("SSID update\n")); */ + /* SSID is saved when start AP/GO */ + /* SSID IE set in beacon from supplicant + * will not always be + * the true since hidden SSID case + */ +#if 0 + 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); +#endif + + } + break; + case ELEM_ID_SUP_RATES: /* 1 *//* V *//* Done */ + { +#ifndef CFG_SUPPORT_P2P_GO_KEEP_RATE_SETTING + DBGLOG(P2P, TRACE, "Support Rate IE\n"); + if ((SUP_RATES_IE(pucIE)->ucLength) + > ELEM_MAX_LEN_SUP_RATES) + SUP_RATES_IE(pucIE)->ucLength = + ELEM_MAX_LEN_SUP_RATES; + 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); +#endif + } + break; + case ELEM_ID_DS_PARAM_SET: /* 3 *//* V *//* Done */ + { + DBGLOG(P2P, TRACE, + "DS PARAM IE: %d.\n", + DS_PARAM_IE(pucIE)->ucCurrChnl); + + /* prP2pBssInfo->ucPrimaryChannel = + * DS_PARAM_IE(pucIE)->ucCurrChnl; + */ + + /* prP2pBssInfo->eBand = BAND_2G4; */ + } + break; + case ELEM_ID_TIM: /* 5 *//* V */ + TIM_IE(pucIE)->ucDTIMPeriod = + prP2pBssInfo->ucDTIMPeriod; + DBGLOG(P2P, TRACE, + "TIM IE, Len:%d, DTIM:%d\n", + IE_LEN(pucIE), + TIM_IE(pucIE)->ucDTIMPeriod); + break; + case ELEM_ID_COUNTRY_INFO: /* 7 */ + if (COUNTRY_IE(pucIE)->ucLength + >= ELEM_MIN_LEN_COUNTRY_INFO) { + prP2pBssInfo->ucCountryIELen = + COUNTRY_IE(pucIE)->ucLength; + kalMemCopy( + prP2pBssInfo->aucCountryStr, + COUNTRY_IE(pucIE)->aucCountryStr, 3); + kalMemCopy( + prP2pBssInfo->aucSubbandTriplet, + COUNTRY_IE(pucIE)->arCountryStr, + COUNTRY_IE(pucIE)->ucLength - 3); + } + 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:%x, TX Beamforming Cap:%x, Ant Selection Cap:%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", + (uint8_t) + HT_CAP_IE(pucIE)->ucAmpduParam, + (uint8_t) + 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 */ + + DBGLOG(P2P, TRACE, "RSN IE\n"); + kalP2PSetCipher(prAdapter->prGlueInfo, + IW_AUTH_CIPHER_CCMP, + (uint8_t) prP2pBssInfo->u4PrivateData); + + if (rsnParseRsnIE(prAdapter, + RSN_IE(pucIE), &rRsnIe)) { + prP2pBssInfo->u4RsnSelectedGroupCipher = + RSN_CIPHER_SUITE_CCMP; + prP2pBssInfo + ->u4RsnSelectedPairwiseCipher = + RSN_CIPHER_SUITE_CCMP; + prP2pBssInfo->u4RsnSelectedAKMSuite = + RSN_AKM_SUITE_PSK; + prP2pBssInfo->u2RsnSelectedCapInfo = + rRsnIe.u2RsnCap; + DBGLOG(RSN, TRACE, + "RsnIe CAP:0x%x\n", + rRsnIe.u2RsnCap); + } + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + prP2pBssInfo->rApPmfCfg.fgMfpc = + (rRsnIe.u2RsnCap + & ELEM_WPA_CAP_MFPC) ? 1 : 0; + prP2pBssInfo->rApPmfCfg.fgMfpr = + (rRsnIe.u2RsnCap + & ELEM_WPA_CAP_MFPR) ? 1 : 0; + + for (i = 0; + i < rRsnIe.u4AuthKeyMgtSuiteCount; + i++) { + if ((rRsnIe.au4AuthKeyMgtSuite[i] + == RSN_AKM_SUITE_PSK_SHA256) || + (rRsnIe.au4AuthKeyMgtSuite[i] + == RSN_AKM_SUITE_802_1X_SHA256)) { + DBGLOG(RSN, INFO, + "SHA256 support\n"); + /* over-write + * u4RsnSelectedAKMSuite + * by SHA256 AKM + */ + prP2pBssInfo + ->u4RsnSelectedAKMSuite + = rRsnIe.au4AuthKeyMgtSuite[i]; + prP2pBssInfo + ->rApPmfCfg.fgSha256 + = TRUE; + break; + } + } + DBGLOG(RSN, ERROR, + "bcn mfpc:%d, mfpr:%d, sha256:%d\n", + prP2pBssInfo->rApPmfCfg.fgMfpc, + prP2pBssInfo->rApPmfCfg.fgMfpr, + prP2pBssInfo->rApPmfCfg.fgSha256); +#endif + + break; + case ELEM_ID_EXTENDED_SUP_RATES: /* 50 *//* V */ + /* ELEM_ID_SUP_RATES should be placed + * before ELEM_ID_EXTENDED_SUP_RATES. + */ +#ifndef CFG_SUPPORT_P2P_GO_KEEP_RATE_SETTING + 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; +#endif + 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 + uint16_t 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"); + { + p2pFuncParseBeaconVenderId(prAdapter, + pucIE, prP2pSpecificBssInfo, + (uint8_t) + prP2pBssInfo->u4PrivateData); + /* TODO: Store other Vender IE + * except for WMM Param. + */ + } + break; + default: + DBGLOG(P2P, TRACE, + "Unprocessed element ID:%d\n", + IE_ID(pucIE)); + break; + } + } + + } while (FALSE); +} /* p2pFuncParseBeaconContent */ + +/* Code refactoring for AOSP */ +static void +p2pFuncParseBeaconVenderId(IN struct ADAPTER *prAdapter, + IN uint8_t *pucIE, + IN struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo, + IN uint8_t ucRoleIndex) +{ + do { + uint8_t ucOuiType; + uint16_t u2SubTypeVersion; + + if (rsnParseCheckForWFAInfoElem( + prAdapter, pucIE, &ucOuiType, &u2SubTypeVersion)) { + if ((ucOuiType == VENDOR_OUI_TYPE_WPA) + && (u2SubTypeVersion == VERSION_WPA)) { + if (!kalP2PGetCcmpCipher(prAdapter->prGlueInfo, + ucRoleIndex)) + kalP2PSetCipher(prAdapter->prGlueInfo, + IW_AUTH_CIPHER_TKIP, + ucRoleIndex); + kalMemCopy( + prP2pSpecificBssInfo + ->aucWpaIeBuffer, + pucIE, IE_SIZE(pucIE)); + prP2pSpecificBssInfo->u2WpaIeLen = + IE_SIZE(pucIE); + DBGLOG(P2P, TRACE, "WPA IE in supplicant\n"); + } else if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + kalP2PUpdateWSC_IE(prAdapter->prGlueInfo, + 0, pucIE, IE_SIZE(pucIE), ucRoleIndex); + DBGLOG(P2P, TRACE, "WPS IE in supplicant\n"); + } else if (ucOuiType == VENDOR_OUI_TYPE_WMM) { + DBGLOG(P2P, TRACE, "WMM IE in supplicant\n"); + } + /* 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); + DBGLOG(P2P, TRACE, "P2P IE in supplicant\n"); + } else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { + + kalMemCopy(&prP2pSpecificBssInfo + ->aucAttributesCache + [prP2pSpecificBssInfo->u2AttributeLen], + pucIE, IE_SIZE(pucIE)); + + prP2pSpecificBssInfo->u2AttributeLen += + IE_SIZE(pucIE); + } else { + DBGLOG(P2P, TRACE, + "Unknown 50-6F-9A-%d IE.\n", + ucOuiType); + } + } else { + kalMemCopy(&prP2pSpecificBssInfo->aucAttributesCache + [prP2pSpecificBssInfo->u2AttributeLen], + pucIE, IE_SIZE(pucIE)); + + prP2pSpecificBssInfo->u2AttributeLen += + IE_SIZE(pucIE); + DBGLOG(P2P, TRACE, + "Driver unprocessed Vender Specific IE\n"); + } + } while (0); +} + +struct BSS_DESC * +p2pFuncKeepOnConnection(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct P2P_CONNECTION_REQ_INFO *prConnReqInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN struct P2P_SCAN_REQ_INFO *prScanReqInfo) +{ + struct BSS_DESC *prTargetBss = (struct BSS_DESC *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prBssInfo != NULL) && + (prConnReqInfo != NULL) && (prChnlReqInfo != NULL) && + (prScanReqInfo != NULL)); + + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + break; + /* Update connection request information. */ + ASSERT(prConnReqInfo->eConnRequest == P2P_CONNECTION_TYPE_GC); + + /* Find BSS Descriptor first. */ + prTargetBss = scanP2pSearchDesc(prAdapter, prConnReqInfo); + + if (prTargetBss == NULL) { + /* Update scan parameter... to scan target device. */ + /* TODO: Need refine. */ + prScanReqInfo->ucNumChannelList = 1; + prScanReqInfo->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prScanReqInfo->eChannelSet = SCAN_CHANNEL_FULL; + /* Prevent other P2P ID in IE. */ + prScanReqInfo->u4BufLength = 0; + 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->eChnlReqType = CH_REQ_TYPE_JOIN; + + prChnlReqInfo->eChannelWidth = + prTargetBss->eChannelWidth; + prChnlReqInfo->ucCenterFreqS1 = + prTargetBss->ucCenterFreqS1; + prChnlReqInfo->ucCenterFreqS2 = + prTargetBss->ucCenterFreqS2; + } + + } while (FALSE); + + return prTargetBss; +} /* p2pFuncKeepOnConnection */ + +/* Currently Only for ASSOC Response Frame. */ +void p2pFuncStoreAssocRspIEBuffer(IN struct ADAPTER *prAdapter, + IN struct P2P_JOIN_INFO *prP2pJoinInfo, + IN struct SW_RFB *prSwRfb) +{ + struct WLAN_ASSOC_RSP_FRAME *prAssocRspFrame = + (struct WLAN_ASSOC_RSP_FRAME *) NULL; + int16_t i2IELen = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prP2pJoinInfo != NULL) && (prSwRfb != NULL)); + + prAssocRspFrame = + (struct WLAN_ASSOC_RSP_FRAME *) 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; + + prP2pJoinInfo->u4BufLength = (uint32_t) i2IELen; + + kalMemCopy(prP2pJoinInfo->aucIEBuf, + prAssocRspFrame->aucInfoElem, + prP2pJoinInfo->u4BufLength); + + } while (FALSE); +} /* p2pFuncStoreAssocRspIEBuffer */ + +/*---------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to set Packet Filter. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * \param[in] pvSetBuffer Pointer to the buffer + * that holds the data to be set. + * \param[in] u4SetBufferLen The length of the set buffer. + * \param[out] pu4SetInfoLen If the call is successful, returns the number of + * bytes read from the set buffer. If the call failed + * due to invalid length of the set buffer, returns + * the amount of storage needed. + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + * \retval WLAN_STATUS_NOT_SUPPORTED + * \retval WLAN_STATUS_ADAPTER_NOT_READY + */ +/*---------------------------------------------------------------------------*/ +void +p2pFuncMgmtFrameRegister(IN struct ADAPTER *prAdapter, + IN uint16_t u2FrameType, + IN u_int8_t fgIsRegistered, + OUT uint32_t *pu4P2pPacketFilter) +{ + uint32_t u4NewPacketFilter = 0; + struct CMD_RX_PACKET_FILTER rSetRxPacketFilter; + + DEBUGFUNC("p2pFuncMgmtFrameRegister"); + + do { + ASSERT_BREAK(prAdapter != NULL); + + if (pu4P2pPacketFilter) + u4NewPacketFilter = *pu4P2pPacketFilter; + + switch (u2FrameType) { + case MAC_FRAME_PROBE_REQ: + if (fgIsRegistered) { + u4NewPacketFilter |= + PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(P2P, TRACE, + "Open packet filer probe request\n"); + } else { + u4NewPacketFilter &= + ~PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(P2P, TRACE, + "Close packet filer probe request\n"); + } + break; + case MAC_FRAME_ACTION: + if (fgIsRegistered) { + u4NewPacketFilter |= + PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(P2P, TRACE, + "Open packet filer action frame.\n"); + } else { + u4NewPacketFilter &= + ~PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(P2P, TRACE, + "Close packet filer action frame.\n"); + } + break; + default: + DBGLOG(P2P, TRACE, + "Ask frog to add code for mgmt:%x\n", + u2FrameType); + break; + } + + if (pu4P2pPacketFilter) + *pu4P2pPacketFilter = u4NewPacketFilter; + + /* u4NewPacketFilter |= prAdapter->u4OsPacketFilter; */ + + prAdapter->u4OsPacketFilter &= ~PARAM_PACKET_FILTER_P2P_MASK; + prAdapter->u4OsPacketFilter |= u4NewPacketFilter; + + DBGLOG(P2P, TRACE, + "P2P Set PACKET filter:0x%x\n", + prAdapter->u4OsPacketFilter); + + kalMemZero(&rSetRxPacketFilter, sizeof(rSetRxPacketFilter)); + rSetRxPacketFilter.u4RxPacketFilter = + prAdapter->u4OsPacketFilter; + wlanoidSetPacketFilter(prAdapter, + &rSetRxPacketFilter, + FALSE, + &u4NewPacketFilter, + sizeof(u4NewPacketFilter)); + + } while (FALSE); +} /* p2pFuncMgmtFrameRegister */ + +void p2pFuncUpdateMgmtFrameRegister(IN struct ADAPTER *prAdapter, + IN uint32_t u4OsFilter) +{ + struct CMD_RX_PACKET_FILTER rSetRxPacketFilter; + + do { + + /* TODO: Filter need to be done. */ + /* 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); + + kalMemZero(&rSetRxPacketFilter, + sizeof(rSetRxPacketFilter)); + rSetRxPacketFilter.u4RxPacketFilter = + prAdapter->u4OsPacketFilter; + wlanoidSetPacketFilter(prAdapter, + &rSetRxPacketFilter, + FALSE, + &u4OsFilter, + sizeof(u4OsFilter)); + DBGLOG(P2P, TRACE, + "P2P Set PACKET filter:0x%x\n", + prAdapter->u4OsPacketFilter); + } + + } while (FALSE); +} /* p2pFuncUpdateMgmtFrameRegister */ + +void p2pFuncGetStationInfo(IN struct ADAPTER *prAdapter, + IN uint8_t *pucMacAddr, + OUT struct P2P_STATION_INFO *prStaInfo) +{ + + do { + ASSERT_BREAK((prAdapter != NULL) + && (pucMacAddr != NULL) && (prStaInfo != NULL)); + + prStaInfo->u4InactiveTime = 0; + prStaInfo->u4RxBytes = 0; + prStaInfo->u4TxBytes = 0; + prStaInfo->u4RxPackets = 0; + prStaInfo->u4TxPackets = 0; + /* TODO: */ + + } while (FALSE); +} /* p2pFuncGetStationInfo */ + +#if 0 +u_int8_t +p2pFuncGetAttriList(IN struct ADAPTER *prAdapter, + IN uint8_t ucOuiType, + IN uint8_t *pucIE, + IN uint16_t u2IELength, + OUT uint8_t **ppucAttriList, + OUT uint16_t *pu2AttriListLen) +{ + u_int8_t fgIsAllocMem = FALSE; + uint8_t aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + uint16_t u2Offset = 0; + struct IE_P2P *prIe = (struct IE_P2P *) NULL; + uint8_t *pucAttriListStart = (uint8_t *) NULL; + uint16_t u2AttriListLen = 0, u2BufferSize; + u_int8_t fgBackupAttributes = FALSE; + + u2BufferSize = 0; + + 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 (IE_ID(pucIE) == ELEM_ID_VENDOR) { + prIe = (struct IE_P2P *) 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)) { + p2pFuncGetAttriListAction(prAdapter, + prIe, ucOuiType, + &pucAttriListStart, + &u2AttriListLen, + &fgIsAllocMem, + &fgBackupAttributes, + &u2BufferSize); + } /* prIe->aucOui */ + } /* ELEM_ID_VENDOR */ + } /* IE_FOR_EACH */ + + } while (FALSE); + + if (pucAttriListStart) { + uint8_t *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) { + /* Todo:: Nothing */ + } else if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + /* Big Endian: WSC, WFD. */ + WSC_ATTRI_FOR_EACH(pucAttribute, + u2AttriListLen, u2Offset) { + DBGLOG(P2P, LOUD, + "Attribute ID:%d, Length:%d.\n", + WSC_ATTRI_ID(pucAttribute), + WSC_ATTRI_LEN(pucAttribute)); + } + } else { + } + + ASSERT(u2Offset == u2AttriListLen); + + *ppucAttriList = pucAttriListStart; + *pu2AttriListLen = u2AttriListLen; + + } else { + *ppucAttriList = (uint8_t *) NULL; + *pu2AttriListLen = 0; + } + + return fgIsAllocMem; +} /* p2pFuncGetAttriList */ + +/* Code refactoring for AOSP */ +static void +p2pFuncGetAttriListAction(IN struct ADAPTER *prAdapter, + IN struct IE_P2P *prIe, + IN uint8_t ucOuiType, + OUT uint8_t **pucAttriListStart, + OUT uint16_t *u2AttriListLen, + OUT u_int8_t *fgIsAllocMem, + OUT u_int8_t *fgBackupAttributes, + OUT uint16_t *u2BufferSize) +{ + do { + if (!(*pucAttriListStart)) { + *pucAttriListStart = &prIe->aucP2PAttributes[0]; + if (prIe->ucLength > P2P_OUI_TYPE_LEN) + *u2AttriListLen = + (uint16_t) + (prIe->ucLength - P2P_OUI_TYPE_LEN); + else + ASSERT(FALSE); + } else { + /* More than 2 attributes. */ + uint16_t u2CopyLen; + + if (*fgBackupAttributes == FALSE) { + struct P2P_SPECIFIC_BSS_INFO + *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) { + uint8_t *pucTmpBuf = (uint8_t *) NULL; + + pucTmpBuf = (uint8_t *) 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 = + (uint16_t) (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((uint8_t *) + ((unsigned long) (*pucAttriListStart) + + (unsigned long) (*u2AttriListLen)), + &prIe->aucP2PAttributes[0], u2CopyLen); + *u2AttriListLen += u2CopyLen; + } + + } + } while (0); +} +#endif + +struct MSDU_INFO *p2pFuncProcessP2pProbeRsp(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, IN struct MSDU_INFO *prMgmtTxMsdu) +{ + struct MSDU_INFO *prRetMsduInfo = prMgmtTxMsdu; + struct WLAN_BEACON_FRAME *prProbeRspFrame = + (struct WLAN_BEACON_FRAME *) NULL; + uint8_t *pucIEBuf = (uint8_t *) NULL; + uint16_t u2Offset = 0, u2IELength = 0, u2ProbeRspHdrLen = 0; + u_int8_t fgIsWSCIE = FALSE; + u_int8_t fgIsWFDIE = FALSE; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + uint16_t u2EstimateSize = 0, u2EstimatedExtraIELen = 0; + uint32_t u4IeArraySize = 0, u4Idx = 0; + u_int8_t u4P2PIEIdx = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMgmtTxMsdu != NULL)); + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + + /* 3 Make sure this is probe response frame. */ + prProbeRspFrame = (struct WLAN_BEACON_FRAME *) + ((unsigned long) 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[0]->u2VenderIELen = 0; + */ + /* Reset in each time ?? */ + prAdapter->prGlueInfo + ->prP2PInfo[prP2pBssInfo->u4PrivateData] + ->u2WFDIELen = 0; +#endif + + IE_FOR_EACH(pucIEBuf, u2IELength, u2Offset) { + switch (IE_ID(pucIEBuf)) { + case ELEM_ID_SSID: + { + p2pFuncProcessP2pProbeRspAction( + prAdapter, + pucIEBuf, ELEM_ID_SSID, + &ucBssIdx, + &prP2pBssInfo, + &fgIsWSCIE, + &u4P2PIEIdx, + &fgIsWFDIE); + } + break; + case ELEM_ID_VENDOR: + { + p2pFuncProcessP2pProbeRspAction( + prAdapter, + pucIEBuf, ELEM_ID_VENDOR, + &ucBssIdx, + &prP2pBssInfo, + &fgIsWSCIE, + &u4P2PIEIdx, + &fgIsWFDIE); + } + 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(struct APPEND_VAR_IE_ENTRY); + for (u4Idx = 0; u4Idx < u4IeArraySize; u4Idx++) { + if (txProbeRspIETable[u4Idx].u2EstimatedFixedIELen) { + u2EstimatedExtraIELen += + txProbeRspIETable[u4Idx] + .u2EstimatedFixedIELen; + } + + else { + ASSERT(txProbeRspIETable[u4Idx] + .pfnCalculateVariableIELen); + + u2EstimatedExtraIELen += + (uint16_t) ( + txProbeRspIETable[u4Idx] + .pfnCalculateVariableIELen( + prAdapter, + ucBssIdx, NULL)); + } + + } + + if (fgIsWSCIE) + u2EstimatedExtraIELen += + kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 2, + (uint8_t) prP2pBssInfo->u4PrivateData); + + if (u4P2PIEIdx > 0) { + for (u4Idx = 0; u4Idx < u4P2PIEIdx; u4Idx++) + u2EstimatedExtraIELen += + kalP2PCalP2P_IELen( + prAdapter->prGlueInfo, + u4Idx, + (uint8_t) + prP2pBssInfo->u4PrivateData); + u2EstimatedExtraIELen += + p2pFuncCalculateP2P_IE_NoA(prAdapter, + ucBssIdx, NULL); + } +#if CFG_SUPPORT_WFD + ASSERT(sizeof(prAdapter->prGlueInfo + ->prP2PInfo[prP2pBssInfo->u4PrivateData]->aucWFDIE) + >= + prAdapter->prGlueInfo + ->prP2PInfo[prP2pBssInfo->u4PrivateData]->u2WFDIELen); + + if (fgIsWFDIE) + u2EstimatedExtraIELen += + prAdapter->prGlueInfo + ->prP2PInfo[prP2pBssInfo->u4PrivateData] + ->u2WFDIELen; +#if 0 + u2EstimatedExtraIELen += + prAdapter->prGlueInfo->prP2PInfo[0]->u2VenderIELen; +#endif +#endif + + u2EstimateSize += u2EstimatedExtraIELen; + if ((u2EstimateSize) > (prRetMsduInfo->u2FrameLength)) { + /* add sizeof(UINT_64) for Cookie */ + prRetMsduInfo = cnmMgtPktAlloc(prAdapter, + u2EstimateSize + sizeof(uint64_t)); + + if (prRetMsduInfo == NULL) { + DBGLOG(P2P, WARN, + "No packet for sending new probe response, use original one\n"); + prRetMsduInfo = prMgmtTxMsdu; + break; + } + + } + + prRetMsduInfo->ucBssIndex = ucBssIdx; + + /* 3 Compose / Re-compose probe response frame. */ + bssComposeBeaconProbeRespFrameHeaderAndFF((uint8_t *) + ((unsigned long) (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); + + prRetMsduInfo->ucStaRecIndex = prMgmtTxMsdu->ucStaRecIndex; + + for (u4Idx = 0; u4Idx < u4IeArraySize; u4Idx++) { + if (txProbeRspIETable[u4Idx].pfnAppendIE) + txProbeRspIETable[u4Idx] + .pfnAppendIE(prAdapter, prRetMsduInfo); + + } + + if (fgIsWSCIE) { + kalP2PGenWSC_IE(prAdapter->prGlueInfo, + 2, + (uint8_t *) + ((unsigned long) prRetMsduInfo->prPacket + + (unsigned long) prRetMsduInfo->u2FrameLength), + (uint8_t) prP2pBssInfo->u4PrivateData); + + prRetMsduInfo->u2FrameLength += (uint16_t) + kalP2PCalWSC_IELen(prAdapter->prGlueInfo, + 2, + (uint8_t) prP2pBssInfo->u4PrivateData); + } + + if (u4P2PIEIdx > 0) { + for (u4Idx = 0; u4Idx < u4P2PIEIdx; u4Idx++) { + kalP2PGenP2P_IE(prAdapter->prGlueInfo, + u4Idx, + (uint8_t *) + ((unsigned long) + prRetMsduInfo->prPacket + + (unsigned long) + prRetMsduInfo->u2FrameLength), + (uint8_t) prP2pBssInfo->u4PrivateData); + + prRetMsduInfo->u2FrameLength += + (uint16_t) + kalP2PCalP2P_IELen( + prAdapter->prGlueInfo, + u4Idx, + (uint8_t) prP2pBssInfo->u4PrivateData); + } + p2pFuncGenerateP2P_IE_NoA(prAdapter, prRetMsduInfo); + + } +#if CFG_SUPPORT_WFD + + if (fgIsWFDIE > 0) { + ASSERT(prAdapter->prGlueInfo + ->prP2PInfo[prP2pBssInfo->u4PrivateData] + ->u2WFDIELen > 0); + kalMemCopy((uint8_t *) + ((unsigned long) prRetMsduInfo->prPacket + + (unsigned long) prRetMsduInfo->u2FrameLength), + prAdapter->prGlueInfo->prP2PInfo + [prP2pBssInfo->u4PrivateData]->aucWFDIE, + prAdapter->prGlueInfo->prP2PInfo + [prP2pBssInfo->u4PrivateData] + ->u2WFDIELen); + prRetMsduInfo->u2FrameLength += + (uint16_t) prAdapter->prGlueInfo + ->prP2PInfo[prP2pBssInfo->u4PrivateData] + ->u2WFDIELen; + + } +#if 0 + if (prAdapter->prGlueInfo->prP2PInfo[0]->u2VenderIELen > 0) { + kalMemCopy((uint8_t *) + ((uint32_t) prRetMsduInfo->prPacket + + (uint32_t) prRetMsduInfo->u2FrameLength), + prAdapter->prGlueInfo + ->prP2PInfo[0]->aucVenderIE, + prAdapter->prGlueInfo + ->prP2PInfo[0]->u2VenderIELen); + prRetMsduInfo->u2FrameLength += + (uint16_t) prAdapter->prGlueInfo + ->prP2PInfo[0]->u2VenderIELen; + } +#endif +#endif /* CFG_SUPPORT_WFD */ + + } while (FALSE); + + if (prRetMsduInfo != prMgmtTxMsdu) + cnmMgtPktFree(prAdapter, prMgmtTxMsdu); + + return prRetMsduInfo; +} /* p2pFuncProcessP2pProbeRsp */ + +/* Code refactoring for AOSP */ +static void +p2pFuncProcessP2pProbeRspAction(IN struct ADAPTER *prAdapter, + IN uint8_t *pucIEBuf, + IN uint8_t ucElemIdType, + OUT uint8_t *ucBssIdx, + OUT struct BSS_INFO **prP2pBssInfo, + OUT u_int8_t *fgIsWSCIE, + OUT u_int8_t *u4P2PIEIdx, + OUT u_int8_t *fgIsWFDIE) +{ + uint8_t ucOuiType = 0; + uint16_t u2SubTypeVersion = 0; + + switch (ucElemIdType) { + case ELEM_ID_SSID: + { + if (SSID_IE(pucIEBuf)->ucLength > 7) { + for ((*ucBssIdx) = 0; + (*ucBssIdx) < prAdapter->ucHwBssIdNum; + (*ucBssIdx)++) { + *prP2pBssInfo = + GET_BSS_INFO_BY_INDEX( + prAdapter, *ucBssIdx); + if (!(*prP2pBssInfo)) + continue; + if (EQUAL_SSID( + (*prP2pBssInfo)->aucSSID, + (*prP2pBssInfo)->ucSSIDLen, + SSID_IE(pucIEBuf)->aucSSID, + SSID_IE(pucIEBuf)->ucLength)) { + break; + } + } + if ((*ucBssIdx) == prAdapter->ucP2PDevBssIdx) + *prP2pBssInfo = + GET_BSS_INFO_BY_INDEX( + prAdapter, *ucBssIdx); + } else { + *prP2pBssInfo = + GET_BSS_INFO_BY_INDEX( + prAdapter, + prAdapter->ucP2PDevBssIdx); + COPY_SSID( + (*prP2pBssInfo)->aucSSID, + (*prP2pBssInfo)->ucSSIDLen, + SSID_IE(pucIEBuf)->aucSSID, + SSID_IE(pucIEBuf)->ucLength); + + } + } + break; + case ELEM_ID_VENDOR: + if (rsnParseCheckForWFAInfoElem(prAdapter, + pucIEBuf, &ucOuiType, &u2SubTypeVersion)) { + if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + kalP2PUpdateWSC_IE(prAdapter->prGlueInfo, + 2, pucIEBuf, + IE_SIZE(pucIEBuf), + (uint8_t) + ((struct BSS_INFO *)*prP2pBssInfo) + ->u4PrivateData); + *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. + */ + if (*u4P2PIEIdx < MAX_P2P_IE_SIZE) { + kalP2PUpdateP2P_IE( + prAdapter->prGlueInfo, + *u4P2PIEIdx, + pucIEBuf, + IE_SIZE(pucIEBuf), + (uint8_t) + ((struct BSS_INFO *) + *prP2pBssInfo) + ->u4PrivateData); + *u4P2PIEIdx = *u4P2PIEIdx + 1; + } else + DBGLOG(P2P, WARN, + "Too much P2P IE for ProbeResp, skip update\n"); + } +#if CFG_SUPPORT_WFD + else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { + DBGLOG(P2P, INFO, + "WFD IE is found in probe resp (supp). Len %u\n", + IE_SIZE(pucIEBuf)); + if ((sizeof( + prAdapter->prGlueInfo + ->prP2PInfo + [((struct BSS_INFO *)*prP2pBssInfo) + ->u4PrivateData] + ->aucWFDIE) + >= + (prAdapter->prGlueInfo + ->prP2PInfo + [((struct BSS_INFO *)*prP2pBssInfo) + ->u4PrivateData]->u2WFDIELen + + IE_SIZE(pucIEBuf)))) { + *fgIsWFDIE = TRUE; + kalMemCopy(prAdapter->prGlueInfo + ->prP2PInfo + [((struct BSS_INFO *) + *prP2pBssInfo) + ->u4PrivateData]->aucWFDIE, + pucIEBuf, IE_SIZE(pucIEBuf)); + prAdapter->prGlueInfo + ->prP2PInfo + [((struct BSS_INFO *) + *prP2pBssInfo) + ->u4PrivateData]->u2WFDIELen += + IE_SIZE(pucIEBuf); + } + } /* VENDOR_OUI_TYPE_WFD */ +#endif + } else { + DBGLOG(P2P, INFO, + "Other vender IE is found in probe resp (supp). Len %u\n", + IE_SIZE(pucIEBuf)); + } + break; + default: + break; + } +} + +#if 0 /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */ +uint32_t +p2pFuncCalculateExtra_IELenForBeacon(IN struct ADAPTER *prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN struct STA_RECORD *prStaRec) +{ + + struct P2P_SPECIFIC_BSS_INFO *prP2pSpeBssInfo = + (struct P2P_SPECIFIC_BSS_INFO *) NULL; + uint32_t 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 struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct P2P_SPECIFIC_BSS_INFO *prP2pSpeBssInfo = + (struct P2P_SPECIFIC_BSS_INFO *) NULL; + uint8_t *pucIEBuf = (uint8_t *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + prP2pSpeBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) + break; + + pucIEBuf = (uint8_t *) ((uint32_t) prMsduInfo->prPacket + + (uint32_t) prMsduInfo->u2FrameLength); + + kalMemCopy(pucIEBuf, + prP2pSpeBssInfo->aucBeaconIECache, + prP2pSpeBssInfo->u2IELenForBCN); + + prMsduInfo->u2FrameLength += prP2pSpeBssInfo->u2IELenForBCN; + + } while (FALSE); +} /* p2pFuncGenerateExtra_IEForBeacon */ + +#else +uint32_t p2pFuncCalculateP2p_IELenForBeacon(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, IN struct STA_RECORD *prStaRec) +{ + struct P2P_SPECIFIC_BSS_INFO *prP2pSpeBssInfo = + (struct P2P_SPECIFIC_BSS_INFO *) NULL; + uint32_t u4IELen = 0; + struct BSS_INFO *prBssInfo; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (ucBssIdx < prAdapter->ucHwBssIdNum)); + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + if (!prAdapter->fgIsP2PRegistered) + break; + + if (p2pFuncIsAPMode( + prAdapter->rWifiVar.prP2PConnSettings + [prBssInfo->u4PrivateData])) + break; + + prP2pSpeBssInfo = + prAdapter->rWifiVar.prP2pSpecificBssInfo + [prBssInfo->u4PrivateData]; + + u4IELen = prP2pSpeBssInfo->u2AttributeLen; + + } while (FALSE); + + return u4IELen; +} /* p2pFuncCalculateP2p_IELenForBeacon */ + +void p2pFuncGenerateP2p_IEForBeacon(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct P2P_SPECIFIC_BSS_INFO *prP2pSpeBssInfo = + (struct P2P_SPECIFIC_BSS_INFO *) NULL; + uint8_t *pucIEBuf = (uint8_t *) NULL; + struct BSS_INFO *prBssInfo; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + if (!prAdapter->fgIsP2PRegistered) + break; + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + + prP2pSpeBssInfo = + prAdapter->rWifiVar.prP2pSpecificBssInfo + [prBssInfo->u4PrivateData]; + + if (p2pFuncIsAPMode( + prAdapter->rWifiVar.prP2PConnSettings + [prBssInfo->u4PrivateData])) + break; + + pucIEBuf = (uint8_t *) ((unsigned long) prMsduInfo->prPacket + + (unsigned long) prMsduInfo->u2FrameLength); + + kalMemCopy(pucIEBuf, + prP2pSpeBssInfo->aucAttributesCache, + prP2pSpeBssInfo->u2AttributeLen); + + prMsduInfo->u2FrameLength += prP2pSpeBssInfo->u2AttributeLen; + + } while (FALSE); +} /* p2pFuncGenerateP2p_IEForBeacon */ + +uint32_t p2pFuncCalculateWSC_IELenForBeacon(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, IN struct STA_RECORD *prStaRec) +{ + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + + if (prP2pBssInfo->eNetworkType != NETWORK_TYPE_P2P) + return 0; + + return kalP2PCalWSC_IELen(prAdapter->prGlueInfo, + 0, (uint8_t) prP2pBssInfo->u4PrivateData); +} /* p2pFuncCalculateP2p_IELenForBeacon */ + +void p2pFuncGenerateWSC_IEForBeacon(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + uint8_t *pucBuffer; + uint16_t u2IELen = 0; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + + if (prP2pBssInfo->eNetworkType != NETWORK_TYPE_P2P) + return; + + u2IELen = (uint16_t) kalP2PCalWSC_IELen(prAdapter->prGlueInfo, + 0, (uint8_t) prP2pBssInfo->u4PrivateData); + + pucBuffer = (uint8_t *) ((unsigned long) prMsduInfo->prPacket + + (unsigned long) prMsduInfo->u2FrameLength); + + ASSERT(pucBuffer); + + /* TODO: Check P2P FSM State. */ + kalP2PGenWSC_IE(prAdapter->prGlueInfo, + 0, pucBuffer, (uint8_t) prP2pBssInfo->u4PrivateData); + + prMsduInfo->u2FrameLength += u2IELen; +} /* p2pFuncGenerateP2p_IEForBeacon */ + +#endif +/*---------------------------------------------------------------------------*/ +/*! + * @brief This function is used to calculate P2P IE length for Beacon frame. + * + * @param[in] eNetTypeIndex Specify which network + * @param[in] prStaRec Pointer to the STA_RECORD_T + * + * @return The length of P2P IE added + */ +/*---------------------------------------------------------------------------*/ +uint32_t p2pFuncCalculateP2p_IELenForAssocRsp(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, IN struct STA_RECORD *prStaRec) +{ + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (prBssInfo->eNetworkType != NETWORK_TYPE_P2P) + return 0; + + return p2pFuncCalculateP2P_IELen(prAdapter, + ucBssIndex, + prStaRec, + txAssocRspAttributesTable, + sizeof(txAssocRspAttributesTable) / + sizeof(struct APPEND_VAR_ATTRI_ENTRY)); + +} /* 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 struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (!prStaRec) { + DBGLOG(P2P, ERROR, "prStaRec of ucStaRecIndex %d is NULL!\n", + prMsduInfo->ucStaRecIndex); + return; + } + + if (IS_STA_IN_P2P(prStaRec)) { + DBGLOG(P2P, TRACE, "Generate NULL P2P IE for Assoc Rsp.\n"); + + p2pFuncGenerateP2P_IE(prAdapter, + prMsduInfo->ucBssIndex, + TRUE, + &prMsduInfo->u2FrameLength, + prMsduInfo->prPacket, + 1500, + txAssocRspAttributesTable, + sizeof(txAssocRspAttributesTable) / + sizeof(struct APPEND_VAR_ATTRI_ENTRY)); + } else { + + DBGLOG(P2P, TRACE, "Legacy device, no P2P IE.\n"); + } +} /* p2pFuncGenerateP2p_IEForAssocRsp */ + +uint32_t +p2pFuncCalculateP2P_IELen(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct STA_RECORD *prStaRec, + IN struct APPEND_VAR_ATTRI_ENTRY arAppendAttriTable[], + IN uint32_t u4AttriTableSize) +{ + + uint32_t u4OverallAttriLen, u4Dummy; + uint16_t u2EstimatedFixedAttriLen; + uint32_t 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 struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN u_int8_t fgIsAssocFrame, + IN uint16_t *pu2Offset, + IN uint8_t *pucBuf, + IN uint16_t u2BufSize, + IN struct APPEND_VAR_ATTRI_ENTRY arAppendAttriTable[], + IN uint32_t u4AttriTableSize) +{ + uint8_t *pucBuffer = (uint8_t *) NULL; + struct IE_P2P *prIeP2P = (struct IE_P2P *) NULL; + uint32_t u4OverallAttriLen; + uint32_t u4AttriLen; + uint8_t aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + uint8_t aucTempBuffer[P2P_MAXIMUM_ATTRIBUTE_LEN]; + uint32_t i; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL)); + + pucBuffer = (uint8_t *) ((unsigned long) pucBuf + (*pu2Offset)); + + ASSERT_BREAK(pucBuffer != NULL); + + /* Check buffer length is still enough. */ + ASSERT_BREAK((u2BufSize - (*pu2Offset)) >= P2P_IE_OUI_HDR); + + prIeP2P = (struct IE_P2P *) 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, + ucBssIndex, 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 = (uint8_t *) + ((unsigned long) + prIeP2P + + (VENDOR_OUI_TYPE_LEN + + P2P_MAXIMUM_ATTRIBUTE_LEN)); + + prIeP2P = (struct IE_P2P *) + ((unsigned long) 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 = + (uint8_t) (VENDOR_OUI_TYPE_LEN + u4OverallAttriLen); + + } while (FALSE); +} /* p2pFuncGenerateP2P_IE */ + +uint32_t +p2pFuncAppendAttriStatusForAssocRsp(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN u_int8_t fgIsAssocFrame, + IN uint16_t *pu2Offset, + IN uint8_t *pucBuf, + IN uint16_t u2BufSize) +{ + uint8_t *pucBuffer; + struct P2P_ATTRI_STATUS *prAttriStatus; + uint32_t u4AttriLen = 0; + + ASSERT(prAdapter); + ASSERT(pucBuf); + + if (fgIsAssocFrame) + return u4AttriLen; + /* TODO: For assoc request P2P IE check in driver & + * return status in P2P IE. + */ + + pucBuffer = (uint8_t *) + ((unsigned long) pucBuf + + (unsigned long) (*pu2Offset)); + + ASSERT(pucBuffer); + prAttriStatus = (struct P2P_ATTRI_STATUS *) pucBuffer; + + ASSERT(u2BufSize >= ((*pu2Offset) + (uint16_t) u4AttriLen)); + + prAttriStatus->ucId = P2P_ATTRI_ID_STATUS; + WLAN_SET_FIELD_16(&prAttriStatus->u2Length, P2P_ATTRI_MAX_LEN_STATUS); + + prAttriStatus->ucStatusCode = P2P_STATUS_SUCCESS; + + u4AttriLen = (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_STATUS); + + (*pu2Offset) += (uint16_t) u4AttriLen; + + return u4AttriLen; +} /* p2pFuncAppendAttriStatusForAssocRsp */ + +uint32_t +p2pFuncAppendAttriExtListenTiming(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN u_int8_t fgIsAssocFrame, + IN uint16_t *pu2Offset, + IN uint8_t *pucBuf, + IN uint16_t u2BufSize) +{ + uint32_t u4AttriLen = 0; + struct P2P_ATTRI_EXT_LISTEN_TIMING *prP2pExtListenTiming = + (struct P2P_ATTRI_EXT_LISTEN_TIMING *) NULL; + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo = + (struct P2P_SPECIFIC_BSS_INFO *) NULL; + uint8_t *pucBuffer = NULL; + struct BSS_INFO *prBssInfo = NULL; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + ASSERT(prAdapter); + ASSERT(pucBuf); + ASSERT(prBssInfo); + + if (fgIsAssocFrame) + return u4AttriLen; + /* TODO: For extend listen timing. */ + + prP2pSpecificBssInfo = + prAdapter->rWifiVar.prP2pSpecificBssInfo + [prBssInfo->u4PrivateData]; + + u4AttriLen = (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_EXT_LISTEN_TIMING); + + ASSERT(u2BufSize >= ((*pu2Offset) + (uint16_t) u4AttriLen)); + + pucBuffer = (uint8_t *) + ((unsigned long) pucBuf + + (unsigned long) (*pu2Offset)); + + ASSERT(pucBuffer); + + prP2pExtListenTiming = (struct P2P_ATTRI_EXT_LISTEN_TIMING *) 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) += (uint16_t) u4AttriLen; + + return u4AttriLen; +} /* p2pFuncAppendAttriExtListenTiming */ + +struct IE_HDR * +p2pFuncGetSpecIE(IN struct ADAPTER *prAdapter, + IN uint8_t *pucIEBuf, + IN uint16_t u2BufferLen, + IN uint8_t ucElemID, + IN u_int8_t *pfgIsMore) +{ + struct IE_HDR *prTargetIE = (struct IE_HDR *) NULL; + uint8_t *pucIE = (uint8_t *) NULL; + uint16_t u2Offset = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (pucIEBuf != NULL)); + + pucIE = pucIEBuf; + + if (pfgIsMore) + *pfgIsMore = FALSE; + + IE_FOR_EACH(pucIE, u2BufferLen, u2Offset) { + if (IE_ID(pucIE) == ucElemID) { + if ((prTargetIE) && (pfgIsMore)) { + + *pfgIsMore = TRUE; + break; + } + prTargetIE = (struct IE_HDR *) pucIE; + + if (pfgIsMore == NULL) + break; + + } + } + + } while (FALSE); + + return prTargetIE; +} /* p2pFuncGetSpecIE */ + +struct P2P_ATTRIBUTE * +p2pFuncGetSpecAttri(IN struct ADAPTER *prAdapter, + IN uint8_t ucOuiType, + IN uint8_t *pucIEBuf, + IN uint16_t u2BufferLen, + IN uint8_t ucAttriID) +{ + struct IE_P2P *prP2pIE = (struct IE_P2P *) NULL; + struct P2P_ATTRIBUTE *prTargetAttri = (struct P2P_ATTRIBUTE *) NULL; + u_int8_t fgIsMore = FALSE; + uint8_t *pucIE = (uint8_t *) NULL; + uint16_t u2BufferLenLeft = 0; + + DBGLOG(P2P, INFO, + "Check AssocReq Oui type %u attri %u for len %u\n", + ucOuiType, ucAttriID, u2BufferLen); + + do { + ASSERT_BREAK((prAdapter != NULL) + && (pucIEBuf != NULL)); + + u2BufferLenLeft = u2BufferLen; + pucIE = pucIEBuf; + + do { + fgIsMore = FALSE; + prP2pIE = (struct IE_P2P *) p2pFuncGetSpecIE(prAdapter, + pucIE, u2BufferLenLeft, + ELEM_ID_VENDOR, &fgIsMore); + if (prP2pIE) { + ASSERT((unsigned long) prP2pIE + >= (unsigned long) pucIE); + u2BufferLenLeft = u2BufferLen - + (uint16_t) (((unsigned long) prP2pIE) - + ((unsigned long) 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) + p2pFuncGetSpecAttriAction(prP2pIE, + ucOuiType, ucAttriID, + &prTargetAttri); + /* P2P_OUI_TYPE_LEN */ + pucIE = (uint8_t *) + (((unsigned long) prP2pIE) + + IE_SIZE(prP2pIE)); + } + /* prP2pIE */ + } while (prP2pIE && fgIsMore && u2BufferLenLeft); + + } while (FALSE); + + return prTargetAttri; +} + +/* p2pFuncGetSpecAttri */ + +/* Code refactoring for AOSP */ +static void +p2pFuncGetSpecAttriAction(IN struct IE_P2P *prP2pIE, + IN uint8_t ucOuiType, + IN uint8_t ucAttriID, + OUT struct P2P_ATTRIBUTE **prTargetAttri) +{ + uint8_t *pucAttri = (uint8_t *) NULL; + uint16_t u2OffsetAttri = 0; + uint8_t aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + + 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_IE_OUI_HDR), + u2OffsetAttri) { + if (WSC_ATTRI_ID(pucAttri) + == ucAttriID) { + *prTargetAttri = + (struct P2P_ATTRIBUTE *) + pucAttri; + break; + } + + } + + } else if (ucOuiType == VENDOR_OUI_TYPE_P2P) { + P2P_ATTRI_FOR_EACH(pucAttri, + (IE_LEN(prP2pIE) - P2P_IE_OUI_HDR), + u2OffsetAttri) { + if (ATTRI_ID(pucAttri) + == ucAttriID) { + *prTargetAttri = + (struct P2P_ATTRIBUTE *) + pucAttri; + break; + } + } + + } +#if CFG_SUPPORT_WFD + else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { + WFD_ATTRI_FOR_EACH(pucAttri, + (IE_LEN(prP2pIE) - P2P_IE_OUI_HDR), + u2OffsetAttri) { + if (ATTRI_ID(pucAttri) + == (uint8_t) ucAttriID) { + *prTargetAttri = + (struct P2P_ATTRIBUTE *) + pucAttri; + break; + } + } + } +#endif + else { + /* Todo:: Nothing */ + /* Possible or else. */ + } + } + } /* ucOuiType */ +} + +uint32_t +p2pFuncGenerateBeaconProbeRsp(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct MSDU_INFO *prMsduInfo, + IN u_int8_t fgIsProbeRsp) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct WLAN_BEACON_FRAME *prBcnFrame = + (struct WLAN_BEACON_FRAME *) 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 = (struct WLAN_BEACON_FRAME *) prMsduInfo->prPacket; + + return nicUpdateBeaconIETemplate(prAdapter, + IE_UPD_METHOD_UPDATE_ALL, + prBssInfo->ucBssIndex, + prBssInfo->u2CapInfo, + (uint8_t *) prBcnFrame->aucInfoElem, + prMsduInfo->u2FrameLength - + OFFSET_OF(struct WLAN_BEACON_FRAME, aucInfoElem)); + + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncGenerateBeaconProbeRsp */ + +uint32_t +p2pFuncComposeBeaconProbeRspTemplate(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo, + IN uint8_t *pucBcnBuffer, + IN uint32_t u4BcnBufLen, + IN u_int8_t fgIsProbeRsp, + IN struct P2P_PROBE_RSP_UPDATE_INFO *prP2pProbeRspInfo, + IN u_int8_t fgSynToFW) +{ + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + struct MSDU_INFO *prMsduInfo = (struct MSDU_INFO *) NULL; + struct WLAN_MAC_HEADER *prWlanBcnFrame = + (struct WLAN_MAC_HEADER *) NULL; + + uint8_t *pucBuffer = (uint8_t *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (pucBcnBuffer != NULL) + && (prP2pBssInfo != NULL)); + + prWlanBcnFrame = (struct WLAN_MAC_HEADER *) 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; + + if (prMsduInfo == NULL) { + rWlanStatus = WLAN_STATUS_FAILURE; + break; + } + + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucStaRecIndex = 0xFF; + prMsduInfo->ucBssIndex = prP2pBssInfo->ucBssIndex; + + } else { + prMsduInfo = prP2pBssInfo->prBeacon; + + if (prMsduInfo == NULL) { + rWlanStatus = WLAN_STATUS_FAILURE; + break; + } + + if (u4BcnBufLen > + (OFFSET_OF(struct WLAN_BEACON_FRAME, + aucInfoElem[0]) + MAX_IE_LENGTH)) { + /* Unexpected error, buffer overflow. */ + ASSERT(FALSE); + break; + } + + } + + pucBuffer = (uint8_t *) + ((unsigned long) (prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + + kalMemCopy(pucBuffer, pucBcnBuffer, u4BcnBufLen); + + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = (uint16_t) u4BcnBufLen; + + if (fgSynToFW) + rWlanStatus = p2pFuncGenerateBeaconProbeRsp(prAdapter, + prP2pBssInfo, prMsduInfo, fgIsProbeRsp); + + } while (FALSE); + + return rWlanStatus; + +} /* p2pFuncComposeBeaconTemplate */ + +uint32_t wfdFuncCalculateWfdIELenForAssocRsp(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct STA_RECORD *prStaRec) +{ + +#if CFG_SUPPORT_WFD_COMPOSE_IE + uint16_t u2EstimatedExtraIELen = 0; + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (prBssInfo->eNetworkType != NETWORK_TYPE_P2P) + return 0; + + if (!IS_STA_P2P_TYPE(prStaRec)) + return 0; + + u2EstimatedExtraIELen = + prAdapter->prGlueInfo->prP2PInfo[0]->u2WFDIELen; + + if (u2EstimatedExtraIELen < VENDOR_SPECIFIC_IE_LENGTH) + return u2EstimatedExtraIELen; + else + return 0; +#else + return 0; +#endif +} /* wfdFuncCalculateWfdIELenForAssocRsp */ + +void wfdFuncGenerateWfdIEForAssocRsp(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + +#if CFG_SUPPORT_WFD_COMPOSE_IE + struct STA_RECORD *prStaRec; + uint16_t u2EstimatedExtraIELen; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct GLUE_INFO *prGlueInfo; + struct GL_P2P_INFO *prP2PInfo; + + if (!prAdapter) + return; + + if (!prMsduInfo) + return; + + prGlueInfo = prAdapter->prGlueInfo; + if (!prGlueInfo) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + if (!prStaRec) + return; + + if (!IS_STA_P2P_TYPE(prStaRec)) + return; + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + prP2PInfo = prGlueInfo->prP2PInfo[prP2pBssInfo->u4PrivateData]; + if (!prP2PInfo) + return; + + u2EstimatedExtraIELen = prP2PInfo->u2WFDIELen; + if (u2EstimatedExtraIELen > 0 + && u2EstimatedExtraIELen < VENDOR_SPECIFIC_IE_LENGTH) { + kalMemCopy((prMsduInfo->prPacket + prMsduInfo->u2FrameLength), + prP2PInfo->aucWFDIE, u2EstimatedExtraIELen); + prMsduInfo->u2FrameLength += u2EstimatedExtraIELen; + } + + return; +#else + + return; +#endif +} /* wfdFuncGenerateWfdIEForAssocRsp */ + +void +p2pFuncComposeNoaAttribute(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + OUT uint8_t *aucNoaAttrArray, + OUT uint32_t *pu4Len) +{ + struct BSS_INFO *prBssInfo = NULL; + struct P2P_ATTRI_NOA *prNoaAttr = NULL; + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo = NULL; + struct NOA_DESCRIPTOR *prNoaDesc = NULL; + uint32_t u4NumOfNoaDesc = 0; + uint32_t i = 0; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + prP2pSpecificBssInfo = + prAdapter->rWifiVar + .prP2pSpecificBssInfo[prBssInfo->u4PrivateData]; + + prNoaAttr = (struct P2P_ATTRI_NOA *) aucNoaAttrArray; + + prNoaAttr->ucId = P2P_ATTRI_ID_NOTICE_OF_ABSENCE; + prNoaAttr->ucIndex = prP2pSpecificBssInfo->ucNoAIndex; + + if (prP2pSpecificBssInfo->fgEnableOppPS) { + prNoaAttr->ucCTWOppPSParam = + P2P_CTW_OPPPS_PARAM_OPPPS_FIELD | + (prP2pSpecificBssInfo->u2CTWindow & + P2P_CTW_OPPPS_PARAM_CTWINDOW_MASK); + } else { + prNoaAttr->ucCTWOppPSParam = 0; + } + + for (i = 0; i < prP2pSpecificBssInfo->ucNoATimingCount; i++) { + if (prP2pSpecificBssInfo->arNoATiming[i].fgIsInUse) { + prNoaDesc = (struct NOA_DESCRIPTOR *) + &prNoaAttr->aucNoADesc + [i * sizeof(struct NOA_DESCRIPTOR)]; + + prNoaDesc->ucCountType = + prP2pSpecificBssInfo->arNoATiming[i].ucCount; + prNoaDesc->u4Duration = + prP2pSpecificBssInfo->arNoATiming[i].u4Duration; + prNoaDesc->u4Interval = + prP2pSpecificBssInfo->arNoATiming[i].u4Interval; + prNoaDesc->u4StartTime = + prP2pSpecificBssInfo->arNoATiming[i] + .u4StartTime; + + u4NumOfNoaDesc++; + } + } + + /* include "index" + "OppPs Params" + "NOA descriptors" */ + prNoaAttr->u2Length = 2 + + u4NumOfNoaDesc * sizeof(struct NOA_DESCRIPTOR); + + /* include "Attribute ID" + "Length" + "index" + + * "OppPs Params" + "NOA descriptors" + */ + *pu4Len = P2P_ATTRI_HDR_LEN + prNoaAttr->u2Length; +} + +uint32_t p2pFuncCalculateP2P_IE_NoA(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct STA_RECORD *prStaRec) +{ + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo = NULL; + uint8_t ucIdx; + uint32_t u4NumOfNoaDesc = 0; + struct BSS_INFO *prBssInfo; + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + if (p2pFuncIsAPMode( + prAdapter->rWifiVar.prP2PConnSettings + [prBssInfo->u4PrivateData])) + return 0; + + prP2pSpecificBssInfo = + prAdapter->rWifiVar.prP2pSpecificBssInfo + [prBssInfo->u4PrivateData]; + + for (ucIdx = 0; + ucIdx < prP2pSpecificBssInfo->ucNoATimingCount; ucIdx++) { + if (prP2pSpecificBssInfo->arNoATiming[ucIdx].fgIsInUse) + u4NumOfNoaDesc++; + } + + /* include "index" + "OppPs Params" + "NOA descriptors" */ + /* include "Attribute ID" + "Length" + "index" + + * "OppPs Params" + "NOA descriptors" + */ + return P2P_ATTRI_HDR_LEN + 2 + + (u4NumOfNoaDesc * sizeof(struct NOA_DESCRIPTOR)); +} + +void p2pFuncGenerateP2P_IE_NoA(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct IE_P2P *prIeP2P; + uint8_t aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + uint32_t u4AttributeLen; + struct BSS_INFO *prBssInfo; + + prBssInfo = + prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + + if (p2pFuncIsAPMode( + prAdapter->rWifiVar.prP2PConnSettings + [prBssInfo->u4PrivateData])) + return; + + prIeP2P = (struct IE_P2P *) + ((unsigned long) prMsduInfo->prPacket + + (uint32_t) prMsduInfo->u2FrameLength); + + prIeP2P->ucId = ELEM_ID_P2P; + prIeP2P->aucOui[0] = aucWfaOui[0]; + prIeP2P->aucOui[1] = aucWfaOui[1]; + prIeP2P->aucOui[2] = aucWfaOui[2]; + prIeP2P->ucOuiType = VENDOR_OUI_TYPE_P2P; + + /* Compose NoA attribute */ + p2pFuncComposeNoaAttribute(prAdapter, + prMsduInfo->ucBssIndex, + prIeP2P->aucP2PAttributes, + &u4AttributeLen); + + prIeP2P->ucLength = VENDOR_OUI_TYPE_LEN + u4AttributeLen; + + prMsduInfo->u2FrameLength += (ELEM_HDR_LEN + prIeP2P->ucLength); + +} + +void p2pFunCleanQueuedMgmtFrame(IN struct ADAPTER *prAdapter, + IN struct P2P_QUEUED_ACTION_FRAME *prFrame) +{ + if (prAdapter == NULL || prFrame == NULL || prFrame->u2Length == 0 || + prFrame->prHeader == NULL) + return; + + DBGLOG(P2P, INFO, "Clean queued p2p action frame.\n"); + + prFrame->ucRoleIdx = 0; + prFrame->u4Freq = 0; + prFrame->u2Length = 0; + cnmMemFree(prAdapter, prFrame->prHeader); + prFrame->prHeader = NULL; +} + +void p2pFuncClassifyAction(IN struct SW_RFB *prSwRfb) +{ + struct P2P_PUBLIC_ACTION_FRAME *pFrame = + (struct P2P_PUBLIC_ACTION_FRAME *) prSwRfb->pvHeader; + + if ((pFrame->ucCategory == CATEGORY_PUBLIC_ACTION) && + (pFrame->ucAction == ACTION_PUBLIC_WIFI_DIRECT)) { + switch (pFrame->ucOuiSubtype) { + case P2P_PUBLIC_ACTION_GO_NEGO_REQ: + DBGLOG(P2P, WARN, "NEGO Req\n"); + break; + case P2P_PUBLIC_ACTION_GO_NEGO_RSP: + DBGLOG(P2P, WARN, "NEGO Resp\n"); + break; + case P2P_PUBLIC_ACTION_GO_NEGO_CFM: + DBGLOG(P2P, WARN, "NEGO Confirm\n"); + break; + case P2P_PUBLIC_ACTION_INVITATION_REQ: + DBGLOG(P2P, WARN, "Invitation Req\n"); + break; + case P2P_PUBLIC_ACTION_INVITATION_RSP: + DBGLOG(P2P, WARN, "Invitation Resp\n"); + break; + case P2P_PUBLIC_ACTION_DEV_DISCOVER_REQ: + DBGLOG(P2P, WARN, "Discovery Req\n"); + break; + case P2P_PUBLIC_ACTION_DEV_DISCOVER_RSP: + DBGLOG(P2P, WARN, "Discovery Resp\n"); + break; + case P2P_PUBLIC_ACTION_PROV_DISCOVERY_REQ: + DBGLOG(P2P, WARN, "Provision Req\n"); + break; + case P2P_PUBLIC_ACTION_PROV_DISCOVERY_RSP: + DBGLOG(P2P, WARN, "Provision Resp\n"); + break; + default: + DBGLOG(P2P, WARN, "unknown action type %d\n", + pFrame->ucOuiSubtype); + break; + } + } +} + +uint32_t +p2pFunGetPreferredFreqList(IN struct ADAPTER *prAdapter, + IN enum ENUM_IFTYPE eIftype, OUT uint32_t *freq_list, + OUT uint32_t *num_freq_list) +{ + struct BSS_INFO *prAisBssInfo; + uint8_t ucNumOfChannel; + uint32_t i; + struct RF_CHANNEL_INFO *aucChannelList; + + prAisBssInfo = prAdapter->prAisBssInfo; + + aucChannelList = (struct RF_CHANNEL_INFO *) kalMemAlloc( + sizeof(struct RF_CHANNEL_INFO) * MAX_CHN_NUM, + VIR_MEM_TYPE); + if (!aucChannelList) { + DBGLOG(P2P, ERROR, + "Allocate buffer for channel list fail\n"); + return -ENOMEM; + } + kalMemZero(aucChannelList, + sizeof(struct RF_CHANNEL_INFO) * MAX_CHN_NUM); + + DBGLOG(P2P, INFO, "iftype: %d, STA connection state: %d\n", + eIftype, + prAisBssInfo->eConnectionState); + + if (prAisBssInfo->eConnectionState != PARAM_MEDIA_STATE_CONNECTED) { + /* Prefer all support p2p channel if STA is NOT connected */ + rlmDomainGetChnlList(prAdapter, BAND_NUM, TRUE, + MAX_CHN_NUM, &ucNumOfChannel, aucChannelList); + for (i = 0; i < ucNumOfChannel; i++) { + freq_list[i] = nicChannelNum2Freq( + aucChannelList[i].ucChannelNum) / 1000; + (*num_freq_list)++; + } + } else if (prAdapter->rWifiVar.eDbdcMode == + ENUM_DBDC_MODE_DISABLED) { + /* DBDC disabled */ + DBGLOG(P2P, INFO, + "Prefer SCC, STA operating channel: %d, band: %d", + prAisBssInfo->ucPrimaryChannel, + prAisBssInfo->eBand); + freq_list[0] = nicChannelNum2Freq( + prAisBssInfo->ucPrimaryChannel) / 1000; + (*num_freq_list)++; + } else { + /* DBDC enabled */ + DBGLOG(P2P, INFO, "STA operating channel: %d, band: %d", + prAisBssInfo->ucPrimaryChannel, + prAisBssInfo->eBand); + if (prAisBssInfo->eBand == BAND_2G4) { + /* Prefer 5G if STA is connected at 2G band */ + rlmDomainGetChnlList(prAdapter, BAND_5G, TRUE, + MAX_CHN_NUM, + &ucNumOfChannel, + aucChannelList); + for (i = 0; i < ucNumOfChannel; i++) { + freq_list[i] = nicChannelNum2Freq( + aucChannelList[i].ucChannelNum) / 1000; + (*num_freq_list)++; + } + + /* Add SCC channel */ + freq_list[i + 1] = nicChannelNum2Freq( + prAisBssInfo->ucPrimaryChannel) / 1000; + (*num_freq_list)++; + } else { + /* Prefer SCC if STA is connected at 5G band */ + freq_list[0] = nicChannelNum2Freq( + prAisBssInfo->ucPrimaryChannel) / 1000; + (*num_freq_list)++; + + rlmDomainGetChnlList(prAdapter, BAND_2G4, TRUE, + MAX_CHN_NUM, + &ucNumOfChannel, + aucChannelList); + for (i = 0; i < ucNumOfChannel; i++) { + freq_list[i + 1] = nicChannelNum2Freq( + aucChannelList[i].ucChannelNum) / 1000; + (*num_freq_list)++; + } + } + } + + kalMemFree(aucChannelList, VIR_MEM_TYPE, + sizeof(struct RF_CHANNEL_INFO) * MAX_CHN_NUM); + + return WLAN_STATUS_SUCCESS; +} +uint8_t p2pFuncIsBufferableMMPDU(IN struct MSDU_INFO *prMgmtTxMsdu) +{ + struct WLAN_MAC_HEADER *prWlanHdr = (struct WLAN_MAC_HEADER *) NULL; + uint16_t u2TxFrameCtrl; + uint8_t fgIsBufferableMMPDU; + + prWlanHdr = (struct WLAN_MAC_HEADER *) + ((unsigned long) prMgmtTxMsdu->prPacket + + MAC_TX_RESERVED_FIELD); + + if (!prWlanHdr) { + DBGLOG(P2P, ERROR, "prWlanHdr is NULL\n"); + return FALSE; + } + u2TxFrameCtrl = prWlanHdr->u2FrameCtrl & MASK_FRAME_TYPE; + + switch (u2TxFrameCtrl) { + case MAC_FRAME_ACTION: + case MAC_FRAME_DISASSOC: + case MAC_FRAME_DEAUTH: + DBGLOG(P2P, TRACE, "u2TxFrameCtrl = %u\n", u2TxFrameCtrl); + fgIsBufferableMMPDU = TRUE; + break; + default: + fgIsBufferableMMPDU = FALSE; + break; + } + DBGLOG(P2P, TRACE, "fgIsBufferableMMPDU = %u\n", fgIsBufferableMMPDU); + return fgIsBufferableMMPDU; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_ie.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_ie.c new file mode 100644 index 0000000000000..b6613c1092f64 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_ie.c @@ -0,0 +1,223 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#include "precomp.h" + +uint32_t p2pCalculate_IEForAssocReq(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct STA_RECORD *prStaRec) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct P2P_CONNECTION_REQ_INFO *prConnReqInfo = + (struct P2P_CONNECTION_REQ_INFO *) NULL; + uint32_t u4RetValue = 0; + + do { + ASSERT_BREAK((prStaRec != NULL) && (prAdapter != NULL)); + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + (uint8_t) prP2pBssInfo->u4PrivateData); + + prConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + + u4RetValue = prConnReqInfo->u4BufLength; + + /* ADD WMM Information Element */ + u4RetValue += (ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_INFO); + + /* ADD HT Capability */ + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet + & PHY_TYPE_SET_802_11N) + && (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) { + u4RetValue += (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP); + } +#if CFG_SUPPORT_802_11AC + /* ADD VHT Capability */ + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet + & PHY_TYPE_SET_802_11AC) + && (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11AC)) { + u4RetValue += (ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP); + } +#endif + +#if CFG_SUPPORT_MTK_SYNERGY + if (prAdapter->rWifiVar.ucMtkOui == FEATURE_ENABLED) + u4RetValue += (ELEM_HDR_LEN + ELEM_MIN_LEN_MTK_OUI); +#endif + } 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 struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct P2P_CONNECTION_REQ_INFO *prConnReqInfo = + (struct P2P_CONNECTION_REQ_INFO *) NULL; + uint8_t *pucIEBuf = (uint8_t *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + prBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, + prMsduInfo->ucBssIndex); + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + (uint8_t) prBssInfo->u4PrivateData); + + prConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + + pucIEBuf = (uint8_t *) ((unsigned long) prMsduInfo->prPacket + + (unsigned long) prMsduInfo->u2FrameLength); + + kalMemCopy(pucIEBuf, prConnReqInfo->aucIEBuf, + prConnReqInfo->u4BufLength); + + prMsduInfo->u2FrameLength += prConnReqInfo->u4BufLength; + + /* Add WMM IE */ + mqmGenerateWmmInfoIE(prAdapter, prMsduInfo); + + /* Add HT IE */ + rlmReqGenerateHtCapIE(prAdapter, prMsduInfo); + +#if CFG_SUPPORT_802_11AC + /* Add VHT IE */ + rlmReqGenerateVhtCapIE(prAdapter, prMsduInfo); +#endif + +#if CFG_SUPPORT_MTK_SYNERGY + rlmGenerateMTKOuiIE(prAdapter, prMsduInfo); +#endif + } while (FALSE); + + return; + +} /* p2pGenerate_IEForAssocReq */ + +uint32_t +wfdFuncAppendAttriDevInfo(IN struct ADAPTER *prAdapter, + IN u_int8_t fgIsAssocFrame, + IN uint16_t *pu2Offset, + IN uint8_t *pucBuf, + IN uint16_t u2BufSize) +{ + uint32_t u4AttriLen = 0; + uint8_t *pucBuffer = NULL; + struct WFD_DEVICE_INFORMATION_IE *prWfdDevInfo = + (struct WFD_DEVICE_INFORMATION_IE *) NULL; + struct WFD_CFG_SETTINGS *prWfdCfgSettings = + (struct WFD_CFG_SETTINGS *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (pucBuf != NULL) && (pu2Offset != NULL)); + + prWfdCfgSettings = &(prAdapter->rWifiVar.rWfdConfigureSettings); + + ASSERT_BREAK((prWfdCfgSettings != NULL)); + + if ((prWfdCfgSettings->ucWfdEnable == 0) || + ((prWfdCfgSettings->u4WfdFlag + & WFD_FLAGS_DEV_INFO_VALID) == 0)) { + break; + } + + pucBuffer = (uint8_t *) ((unsigned long) pucBuf + + (unsigned long) (*pu2Offset)); + + ASSERT_BREAK(pucBuffer != NULL); + + prWfdDevInfo = (struct WFD_DEVICE_INFORMATION_IE *) 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) += (uint16_t) u4AttriLen; + + return u4AttriLen; +} + +/* wfdFuncAppendAttriDevInfo */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_rlm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_rlm.c new file mode 100644 index 0000000000000..c02652e83583f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_rlm.c @@ -0,0 +1,1368 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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" +#include "rlm.h" + +/****************************************************************************** + * C O N S T A N T S + ****************************************************************************** + */ + +/****************************************************************************** + * D A T A T Y P E S + ****************************************************************************** + */ + +/****************************************************************************** + * P U B L I C D A T A + ****************************************************************************** + */ + +/****************************************************************************** + * P R I V A T E D A T A + ****************************************************************************** + */ + +/****************************************************************************** + * M A C R O S + ****************************************************************************** + */ + +/****************************************************************************** + * F U N C T I O N D E C L A R A T I O N S + ****************************************************************************** + */ + +/****************************************************************************** + * F U N C T I O N S + ****************************************************************************** + */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Init AP Bss + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmBssInitForAP(struct ADAPTER *prAdapter, struct BSS_INFO *prBssInfo) +{ + uint8_t i; + uint8_t ucMaxBw = 0; + + 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; + + /* Check if AP can set its bw to 40MHz + * But if any of BSS is setup in 40MHz, + * the second BSS would prefer to use 20MHz + * in order to remain in SCC case + */ + if (cnmBss40mBwPermitted(prAdapter, prBssInfo->ucBssIndex)) { + + prBssInfo->eBssSCO = rlmGetScoForAP(prAdapter, prBssInfo); + + if (prBssInfo->eBssSCO != CHNL_EXT_SCN) { + prBssInfo->fg40mBwAllowed = TRUE; + prBssInfo->fgAssoc40mBwAllowed = TRUE; + + prBssInfo->ucHtOpInfo1 = (uint8_t) + (((uint32_t) prBssInfo->eBssSCO) + | HT_OP_INFO1_STA_CHNL_WIDTH); + + rlmUpdateBwByChListForAP(prAdapter, prBssInfo); + } + } + + /* Filled the VHT BW/S1/S2 and MCS rate set */ + if (prBssInfo->ucPhyTypeSet & PHY_TYPE_BIT_VHT) { + for (i = 0; i < 8; i++) + prBssInfo->u2VhtBasicMcsSet |= BITS(2 * i, (2 * i + 1)); + prBssInfo->u2VhtBasicMcsSet &= + (VHT_CAP_INFO_MCS_MAP_MCS9 + << VHT_CAP_INFO_MCS_1SS_OFFSET); + + ucMaxBw = cnmGetDbdcBwCapability(prAdapter, + prBssInfo->ucBssIndex); + rlmFillVhtOpInfoByBssOpBw(prBssInfo, ucMaxBw); + + /* If the S1 is invalid, force to change bandwidth */ + if (prBssInfo->ucVhtChannelFrequencyS1 == 0) + prBssInfo->ucVhtChannelWidth = + VHT_OP_CHANNEL_WIDTH_20_40; + } else { + prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_20_40; + prBssInfo->ucVhtChannelFrequencyS1 = 0; + prBssInfo->ucVhtChannelFrequencyS2 = 0; + } + + + /*ERROR HANDLE*/ + if ((prBssInfo->ucVhtChannelWidth == VHT_OP_CHANNEL_WIDTH_80) + || (prBssInfo->ucVhtChannelWidth + == VHT_OP_CHANNEL_WIDTH_160) + || (prBssInfo->ucVhtChannelWidth + == VHT_OP_CHANNEL_WIDTH_80P80)) { + + if (prBssInfo->ucVhtChannelFrequencyS1 == 0) { + DBGLOG(RLM, INFO, + "Wrong AP S1 parameter setting, back to BW20!!!\n"); + + prBssInfo->ucVhtChannelWidth = + VHT_OP_CHANNEL_WIDTH_20_40; + prBssInfo->ucVhtChannelFrequencyS1 = 0; + prBssInfo->ucVhtChannelFrequencyS2 = 0; + } + } + + DBGLOG(RLM, INFO, + "WLAN AP SCO=%d BW=%d S1=%d S2=%d CH=%d Band=%d\n", + prBssInfo->eBssSCO, + prBssInfo->ucVhtChannelWidth, + prBssInfo->ucVhtChannelFrequencyS1, + prBssInfo->ucVhtChannelFrequencyS2, + prBssInfo->ucPrimaryChannel, + prBssInfo->eBand); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief For probe response (GO, IBSS) and association response + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmRspGenerateObssScanIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct IE_OBSS_SCAN_PARAM *prObssScanIe; + struct STA_RECORD *prStaRec = + (struct STA_RECORD *) NULL; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prMsduInfo->ucBssIndex); + + if (!prBssInfo) + return; + + if (!IS_BSS_ACTIVE(prBssInfo)) + return; + + /* !RLM_NET_IS_BOW(prBssInfo) && FIXME. */ + if (RLM_NET_IS_11N(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 = (struct IE_OBSS_SCAN_PARAM *) + (((uint8_t *) prMsduInfo->prPacket) + + prMsduInfo->u2FrameLength); + + /* Add 20/40 BSS coexistence IE */ + prObssScanIe->ucId = ELEM_ID_OBSS_SCAN_PARAMS; + prObssScanIe->ucLength = + sizeof(struct IE_OBSS_SCAN_PARAM) - 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rlmUpdateBwByChListForAP(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo) +{ + uint8_t ucLevel; + u_int8_t 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 != (uint8_t) CHNL_EXT_SCN) { + prBssInfo->ucHtOpInfo1 = (uint8_t) 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(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb) +{ + struct ACTION_20_40_COEXIST_FRAME *prRxFrame; + struct IE_20_40_COEXIST *prCoexist; + struct IE_INTOLERANT_CHNL_REPORT *prChnlReport; + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint8_t *pucIE; + uint16_t u2IELength, u2Offset; + uint8_t i, j; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxFrame = (struct ACTION_20_40_COEXIST_FRAME *) prSwRfb->pvHeader; + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (!(prSwRfb->prStaRec)) { + DBGLOG(P2P, ERROR, "prSwRfb->prStaRec is null.\n"); + return; + } + + if (prRxFrame->ucAction != ACTION_PUBLIC_20_40_COEXIST + || !prStaRec + || prStaRec->ucStaState != STA_STATE_3 + || prSwRfb->u2PacketLen < (WLAN_MAC_MGMT_HEADER_LEN + 5) + || prSwRfb->prStaRec->ucBssIndex != + /* HIF_RX_HDR_GET_NETWORK_IDX(prSwRfb->prHifRxHdr) != */ + prStaRec->ucBssIndex) { + return; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + 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 = (uint8_t *) &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 = + (struct IE_INTOLERANT_CHNL_REPORT *) 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->ucBssIndex); + 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 rlmHandleObssStatusEventPkt(struct ADAPTER *prAdapter, + struct EVENT_AP_OBSS_STATUS *prObssStatus) +{ + struct BSS_INFO *prBssInfo; + + ASSERT(prAdapter); + ASSERT(prObssStatus); + ASSERT(prObssStatus->ucBssIndex + < prAdapter->ucHwBssIdNum); + + prBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, prObssStatus->ucBssIndex); + + if (prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) + return; + + prBssInfo->fgObssErpProtectMode = + (u_int8_t) prObssStatus->ucObssErpProtectMode; + prBssInfo->eObssHtProtectMode = + (enum ENUM_HT_PROTECT_MODE) prObssStatus->ucObssHtProtectMode; + prBssInfo->eObssGfOperationMode = + (enum ENUM_GF_MODE) prObssStatus->ucObssGfOperationMode; + prBssInfo->fgObssRifsOperationMode = + (u_int8_t) prObssStatus->ucObssRifsOperationMode; + prBssInfo->fgObssBeaconForcedTo20M = + (u_int8_t) 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(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + u_int8_t fgUpdateBeacon) +{ + struct LINK *prStaList; + struct STA_RECORD *prStaRec; + u_int8_t fgErpProtectMode, fgSta40mIntolerant; + u_int8_t fgUseShortPreamble, fgUseShortSlotTime; + enum ENUM_HT_PROTECT_MODE eHtProtectMode; + enum ENUM_GF_MODE eGfOperationMode; + uint8_t 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 = (uint8_t) CHNL_EXT_SCN; + + prStaList = &prBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH_ENTRY(prStaRec, + prStaList, rLinkEntry, struct STA_RECORD) { + if (!prStaRec) { + DBGLOG(P2P, WARN, + "NULL STA_REC ptr in BSS client list\n"); + bssDumpClientList(prAdapter, prBssInfo); + break; + } + + if (prStaRec->fgIsInUse + && prStaRec->ucStaState == STA_STATE_3 + && prStaRec->ucBssIndex == prBssInfo->ucBssIndex) { + 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 (prBssInfo->fg40mBwAllowed && + !(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 1 + /* ap mode throughput enhancement + * only 2.4G with B mode client connecion + * use long slot time + */ + if ((!(prStaRec->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME)) + && fgErpProtectMode + && prBssInfo->eBand == BAND_2G4) + fgUseShortSlotTime = FALSE; +#else + if (!(prStaRec->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME)) + fgUseShortSlotTime = FALSE; +#endif + 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 = (uint8_t) + (((uint32_t) 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->ucBssIndex); +} +#if 0 +/*----------------------------------------------------------------------------*/ +/*! + * \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 struct ADAPTER *prAdapter) +{ + struct P2P_CONNECTION_SETTINGS *prP2pConnSetting = + (struct P2P_CONNECTION_SETTINGS *) NULL; + struct DOMAIN_INFO_ENTRY *prDomainInfoEntry = + (struct DOMAIN_INFO_ENTRY *) NULL; + struct DOMAIN_SUBBAND_INFO *prDomainSubBand = + (struct DOMAIN_SUBBAND_INFO *) NULL; + struct CHANNEL_ENTRY_FIELD *prChannelEntryField = + (struct CHANNEL_ENTRY_FIELD *) NULL; + uint32_t u4Idx = 0, u4IdxII = 0; + uint8_t ucBufferSize = P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE; +#if 0 + uint8_t 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 = + (struct CHANNEL_ENTRY_FIELD *) + 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 = + (struct CHANNEL_ENTRY_FIELD *) + ((unsigned long) prChannelEntryField + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (unsigned long) + 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 + /* User not set OPERATE channel. */ + if (prP2pConnSetting->ucOperatingChnl == 0) { + + if (scnQuerySparseChannel(prAdapter, NULL, &ucAutoChnl)) + break; /* while */ + + ucBufferSize = prP2pConnSetting->ucRfChannelListSize; + + prChannelEntryField = + (struct CHANNEL_ENTRY_FIELD *) + prP2pConnSetting->aucChannelEntriesField; + + while (ucBufferSize != 0) { + if (prChannelEntryField + ->ucNumberOfChannels != 0) { + ucAutoChnl = + prChannelEntryField->aucChannelList[0]; + break; /* while */ + } + + else { + prChannelEntryField = + (struct CHANNEL_ENTRY_FIELD *) + ((uint32_t) prChannelEntryField + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (uint32_t) + prChannelEntryField + ->ucNumberOfChannels); + + ucBufferSize -= + (P2P_ATTRI_LEN_CHANNEL_ENTRY + + + prChannelEntryField + ->ucNumberOfChannels); + } + + } + + } +#endif + /* We assume user would not set a channel + * not in the channel list. + * If so, the operating channel still depends + * on target device supporting capability. + */ + + /* TODO: 20110921 frog - */ + /* If the Operating channel is not set, + * a channel from supported channel list is set automatically. + * If there is no supported channel in channel list, + * a DEFAULT channel is set. + */ + + } while (FALSE); + +#if 0 + prP2pConnSetting->ucOperatingChnl = ucAutoChnl; +#endif +} /* rlmFuncInitialChannelList */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Find a common channel list from the local channel list info + * & target channel list info. + * + * \param[in] prAdapter Pointer of ADAPTER_T + * + * \return boolean value if probe response frame is + */ +/*----------------------------------------------------------------------------*/ +void +rlmFuncCommonChannelList(IN struct ADAPTER *prAdapter, + IN struct CHANNEL_ENTRY_FIELD *prChannelEntryII, + IN uint8_t ucChannelListSize) +{ + struct P2P_CONNECTION_SETTINGS *prP2pConnSetting = + (struct P2P_CONNECTION_SETTINGS *) NULL; + struct CHANNEL_ENTRY_FIELD *prChannelEntryI = + (struct CHANNEL_ENTRY_FIELD *) NULL, + prChannelEntryIII = (struct CHANNEL_ENTRY_FIELD *) NULL; + uint8_t aucCommonChannelList[P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE]; + uint8_t ucOriChnlSize = 0, ucNewChnlSize = 0; + + do { + + ASSERT_BREAK(prAdapter != NULL); + + prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings; + + prChannelEntryIII = + (struct CHANNEL_ENTRY_FIELD *) aucCommonChannelList; + + while (ucChannelListSize > 0) { + + prChannelEntryI = + (struct CHANNEL_ENTRY_FIELD *) + 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 = + (struct CHANNEL_ENTRY_FIELD *) + ((unsigned long) + prChannelEntryIII + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (unsigned long) + prChannelEntryIII + ->ucNumberOfChannels); + } + + ucOriChnlSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + + prChannelEntryI->ucNumberOfChannels); + + prChannelEntryI = + (struct CHANNEL_ENTRY_FIELD *) + ((unsigned long) prChannelEntryI + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (unsigned long) + prChannelEntryI->ucNumberOfChannels); + + } + + ucChannelListSize -= + (P2P_ATTRI_LEN_CHANNEL_ENTRY + + prChannelEntryII->ucNumberOfChannels); + + prChannelEntryII = (struct CHANNEL_ENTRY_FIELD *) + ((unsigned long) prChannelEntryII + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (unsigned long) + prChannelEntryII->ucNumberOfChannels); + + } + + kalMemCopy(prP2pConnSetting->aucChannelEntriesField, + aucCommonChannelList, + ucNewChnlSize); + prP2pConnSetting->ucRfChannelListSize = ucNewChnlSize; + + } while (FALSE); +} /* rlmFuncCommonChannelList */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +uint8_t rlmFuncFindOperatingClass(IN struct ADAPTER *prAdapter, + IN uint8_t ucChannelNum) +{ + uint8_t ucRegulatoryClass = 0, ucBufferSize = 0; + struct P2P_CONNECTION_SETTINGS *prP2pConnSetting = + (struct P2P_CONNECTION_SETTINGS *) NULL; + struct CHANNEL_ENTRY_FIELD *prChannelEntryField = + (struct CHANNEL_ENTRY_FIELD *) NULL; + uint32_t u4Idx = 0; + + do { + ASSERT_BREAK(prAdapter != NULL); + + prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings; + ucBufferSize = prP2pConnSetting->ucRfChannelListSize; + prChannelEntryField = + (struct CHANNEL_ENTRY_FIELD *) + prP2pConnSetting->aucChannelEntriesField; + + while (ucBufferSize != 0) { + + for (u4Idx = 0; + u4Idx < prChannelEntryField->ucNumberOfChannels; + u4Idx++) { + if (prChannelEntryField->aucChannelList[u4Idx] + == ucChannelNum) { + ucRegulatoryClass = + prChannelEntryField + ->ucRegulatoryClass; + break; + } + + } + + if (ucRegulatoryClass != 0) + break; /* while */ + + prChannelEntryField = + (struct CHANNEL_ENTRY_FIELD *) + ((unsigned long) prChannelEntryField + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (unsigned long) + prChannelEntryField->ucNumberOfChannels); + + ucBufferSize -= + (P2P_ATTRI_LEN_CHANNEL_ENTRY + + prChannelEntryField->ucNumberOfChannels); + + } + + } while (FALSE); + + return ucRegulatoryClass; +} /* rlmFuncFindOperatingClass */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +u_int8_t +rlmFuncFindAvailableChannel(IN struct ADAPTER *prAdapter, + IN uint8_t ucCheckChnl, + IN uint8_t *pucSuggestChannel, + IN u_int8_t fgIsSocialChannel, + IN u_int8_t fgIsDefaultChannel) +{ + u_int8_t fgIsResultAvailable = FALSE; + struct CHANNEL_ENTRY_FIELD *prChannelEntry = + (struct CHANNEL_ENTRY_FIELD *) NULL; + struct P2P_CONNECTION_SETTINGS *prP2pConnSetting = + (struct P2P_CONNECTION_SETTINGS *) NULL; + uint8_t 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 = + (struct CHANNEL_ENTRY_FIELD *) + 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 = + (struct CHANNEL_ENTRY_FIELD *) + ((unsigned long) prChannelEntry + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (unsigned long) + prChannelEntry->ucNumberOfChannels); + + } + + if ((!fgIsResultAvailable) + && (pucSuggestChannel != NULL)) { + log_dbg(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; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +enum ENUM_CHNL_EXT rlmDecideScoForAP(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo) +{ + struct DOMAIN_SUBBAND_INFO *prSubband; + struct DOMAIN_INFO_ENTRY *prDomainInfo; + uint8_t ucSecondChannel, i, j; + enum ENUM_CHNL_EXT eSCO; + enum ENUM_CHNL_EXT eTempSCO; + /*chip capability*/ + uint8_t ucMaxBandwidth = MAX_BW_80_80_MHZ; + + eSCO = CHNL_EXT_SCN; + eTempSCO = CHNL_EXT_SCN; + + if (prBssInfo->eBand == BAND_2G4) { + if (prBssInfo->ucPrimaryChannel != 14) + eSCO = (prBssInfo->ucPrimaryChannel > 7) + ? CHNL_EXT_SCB : CHNL_EXT_SCA; + } else { + if (regd_is_single_sku_en()) { + if (rlmDomainIsLegalChannel(prAdapter, + prBssInfo->eBand, + prBssInfo->ucPrimaryChannel)) + eSCO = rlmSelectSecondaryChannelType(prAdapter, + prBssInfo->eBand, + prBssInfo->ucPrimaryChannel); + } 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 + CHNL_SPAN_20) + : (prBssInfo->ucPrimaryChannel - CHNL_SPAN_20); + + if (!rlmDomainIsLegalChannel(prAdapter, + prBssInfo->eBand, + ucSecondChannel)) + eSCO = CHNL_EXT_SCN; + } + + /* Overwrite SCO settings by wifi cfg */ + if (IS_BSS_P2P(prBssInfo)) { + /* AP mode */ + if (p2pFuncIsAPMode(prAdapter->rWifiVar + .prP2PConnSettings[prBssInfo->u4PrivateData])) { + if (prAdapter->rWifiVar.ucApSco == CHNL_EXT_SCA + || prAdapter->rWifiVar.ucApSco == CHNL_EXT_SCB) + eTempSCO = + (enum ENUM_CHNL_EXT) + prAdapter->rWifiVar.ucApSco; + } + /* P2P mode */ + else { + if (prAdapter->rWifiVar.ucP2pGoSco == CHNL_EXT_SCA || + prAdapter->rWifiVar.ucP2pGoSco == CHNL_EXT_SCB) { + eTempSCO = + (enum ENUM_CHNL_EXT) + prAdapter->rWifiVar.ucP2pGoSco; + } + } + + /* Check again if it is boundary channel + * and 40MHz BW is permitted + */ + if (eTempSCO != CHNL_EXT_SCN) { + ucSecondChannel = (eTempSCO == CHNL_EXT_SCA) + ? (prBssInfo->ucPrimaryChannel + 4) + : (prBssInfo->ucPrimaryChannel - 4); + if (rlmDomainIsLegalChannel(prAdapter, + prBssInfo->eBand, + ucSecondChannel)) + eSCO = eTempSCO; + } + } + + /* Overwrite SCO settings by wifi cfg bandwidth setting */ + if (IS_BSS_P2P(prBssInfo)) { + /* AP mode */ + if (p2pFuncIsAPMode(prAdapter->rWifiVar + .prP2PConnSettings[prBssInfo->u4PrivateData])) { + if (prBssInfo->eBand == BAND_2G4) + ucMaxBandwidth = + prAdapter->rWifiVar.ucAp2gBandwidth; + else + ucMaxBandwidth = + prAdapter->rWifiVar.ucAp5gBandwidth; + } + /* P2P mode */ + else { + if (prBssInfo->eBand == BAND_2G4) + ucMaxBandwidth = + prAdapter->rWifiVar.ucP2p2gBandwidth; + else + ucMaxBandwidth = + prAdapter->rWifiVar.ucP2p5gBandwidth; + } + + if (ucMaxBandwidth < MAX_BW_40MHZ) + eSCO = CHNL_EXT_SCN; + } + + return eSCO; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief: Get AP secondary channel offset from cfg80211 or wifi.cfg + * + * \param[in] prAdapter Pointer of ADAPTER_T, prBssInfo Pointer of BSS_INFO_T, + * + * \return ENUM_CHNL_EXT_T AP secondary channel offset + */ +/*----------------------------------------------------------------------------*/ +enum ENUM_CHNL_EXT rlmGetScoForAP(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo) +{ + enum ENUM_BAND eBand; + uint8_t ucChannel; + enum ENUM_CHNL_EXT eSCO; + int32_t i4DeltaBw; + uint32_t u4AndOneSCO; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct P2P_CONNECTION_REQ_INFO *prP2pConnReqInfo = + (struct P2P_CONNECTION_REQ_INFO *) NULL; + + prP2pRoleFsmInfo = p2pFuncGetRoleByBssIdx(prAdapter, + prBssInfo->ucBssIndex); + + if (!prAdapter->rWifiVar.ucApChnlDefFromCfg + && prP2pRoleFsmInfo) { + + prP2pConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + eSCO = CHNL_EXT_SCN; + + if (cnmGetBssMaxBw(prAdapter, + prBssInfo->ucBssIndex) == MAX_BW_40MHZ) { + /* If BW 40, compare S0 and primary channel freq */ + if (prP2pConnReqInfo->u4CenterFreq1 + > prP2pConnReqInfo->u2PriChnlFreq) + eSCO = CHNL_EXT_SCA; + else + eSCO = CHNL_EXT_SCB; + } else if (cnmGetBssMaxBw(prAdapter, + prBssInfo->ucBssIndex) > MAX_BW_40MHZ) { + /* P: PriChnlFreq, + * A:CHNL_EXT_SCA, + * B: CHNL_EXT_SCB, -:BW SPAN 5M + */ + /* --|----|--CenterFreq1--|----|-- */ + /* --|----|--CenterFreq1--B----P-- */ + /* --|----|--CenterFreq1--P----A-- */ + i4DeltaBw = prP2pConnReqInfo->u2PriChnlFreq + - prP2pConnReqInfo->u4CenterFreq1; + u4AndOneSCO = CHNL_EXT_SCB; + eSCO = CHNL_EXT_SCA; + if (i4DeltaBw < 0) { + /* --|----|--CenterFreq1--|----|-- */ + /* --P----A--CenterFreq1--|----|-- */ + /* --B----P--CenterFreq1--|----|-- */ + u4AndOneSCO = CHNL_EXT_SCA; + eSCO = CHNL_EXT_SCB; + i4DeltaBw = -i4DeltaBw; + } + i4DeltaBw = i4DeltaBw - (CHANNEL_SPAN_20 >> 1); + if ((i4DeltaBw/CHANNEL_SPAN_20) & 1) + eSCO = u4AndOneSCO; + } + } else { + /* 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)) + eSCO = rlmDecideScoForAP(prAdapter, prBssInfo); + } + return eSCO; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief: Get AP channel number of Channel Center Frequency Segment 0 + * from cfg80211 or wifi.cfg + * + * \param[in] prAdapter Pointer of ADAPTER_T, prBssInfo Pointer of BSS_INFO_T, + * + * \return UINT_8 AP channel number of Channel Center Frequency Segment 0 + */ +/*----------------------------------------------------------------------------*/ +uint8_t rlmGetVhtS1ForAP(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo) +{ + uint32_t ucFreq1Channel; + uint8_t ucPrimaryChannel = prBssInfo->ucPrimaryChannel; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct P2P_CONNECTION_REQ_INFO *prP2pConnReqInfo = + (struct P2P_CONNECTION_REQ_INFO *) NULL; + + prP2pRoleFsmInfo = + p2pFuncGetRoleByBssIdx(prAdapter, prBssInfo->ucBssIndex); + + if (prBssInfo->ucVhtChannelWidth == VHT_OP_CHANNEL_WIDTH_20_40) + return 0; + + if (!prAdapter->rWifiVar.ucApChnlDefFromCfg && prP2pRoleFsmInfo) { + prP2pConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + ucFreq1Channel = + nicFreq2ChannelNum( + prP2pConnReqInfo->u4CenterFreq1 * 1000); + } else + ucFreq1Channel = + nicGetVhtS1(ucPrimaryChannel, + prBssInfo->ucVhtChannelWidth); + + return ucFreq1Channel; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_rlm_obss.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_rlm_obss.c new file mode 100644 index 0000000000000..548c004366396 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_rlm_obss.c @@ -0,0 +1,396 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 uint8_t rlmObssChnlLevelIn2G4(struct BSS_INFO *prBssInfo, + uint8_t ucPriChannel, enum ENUM_CHNL_EXT eExtend); + +static uint8_t rlmObssChnlLevelIn5G(struct BSS_INFO *prBssInfo, + uint8_t ucPriChannel, enum ENUM_CHNL_EXT 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 + */ +/*----------------------------------------------------------------------------*/ +uint8_t rlmObssChnlLevel(struct BSS_INFO *prBssInfo, + enum ENUM_BAND eBand, + uint8_t ucPriChannel, + enum ENUM_CHNL_EXT eExtend) +{ + uint8_t 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 uint8_t rlmObssChnlLevelIn2G4(struct BSS_INFO *prBssInfo, + uint8_t ucPriChannel, + enum ENUM_CHNL_EXT eExtend) +{ + uint8_t i, ucChannelLevel; + uint8_t ucSecChannel, ucCenterChannel; + uint8_t 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 uint8_t rlmObssChnlLevelIn5G(struct BSS_INFO *prBssInfo, + uint8_t ucPriChannel, + enum ENUM_CHNL_EXT eExtend) +{ + uint8_t i, ucChannelLevel; + uint8_t 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(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct SW_RFB *prSwRfb) +{ + struct MSDU_INFO *prMsduInfo; + struct ACTION_20_40_COEXIST_FRAME *prTxFrame; + + /* To do: need an algorithm to do judgement. + * Now always reject request + */ + + prMsduInfo = (struct MSDU_INFO *) + cnmMgtPktAlloc(prAdapter, PUBLIC_ACTION_MAX_LEN); + if (prMsduInfo == NULL) + return; + + DBGLOG(RLM, INFO, "Send 20/40 coexistence rsp frame!\n"); + + prTxFrame = (struct ACTION_20_40_COEXIST_FRAME *) prMsduInfo->prPacket; + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + COPY_MAC_ADDR(prTxFrame->aucDestAddr, + ((struct 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); + + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prBssInfo->ucBssIndex, + prSwRfb->ucStaRecIdx, + WLAN_MAC_MGMT_HEADER_LEN, WLAN_MAC_MGMT_HEADER_HTC_LEN + 5, + NULL, MSDU_RATE_MODE_AUTO); + + /* Send them to HW queue */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_role_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_role_fsm.c new file mode 100644 index 0000000000000..68abd30ae3f4b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_role_fsm.c @@ -0,0 +1,3470 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#include "precomp.h" +#include "p2p_role_state.h" +#include "gl_p2p_os.h" + +#if 1 +/*lint -save -e64 Type mismatch */ +static uint8_t *apucDebugP2pRoleState[P2P_ROLE_STATE_NUM] = { + (uint8_t *) DISP_STRING("P2P_ROLE_STATE_IDLE"), + (uint8_t *) DISP_STRING("P2P_ROLE_STATE_SCAN"), + (uint8_t *) DISP_STRING("P2P_ROLE_STATE_REQING_CHANNEL"), + (uint8_t *) DISP_STRING("P2P_ROLE_STATE_AP_CHNL_DETECTION"), +#if (CFG_SUPPORT_DFS_MASTER == 1) + (uint8_t *) DISP_STRING("P2P_ROLE_STATE_GC_JOIN"), + (uint8_t *) DISP_STRING("P2P_ROLE_STATE_DFS_CAC"), + (uint8_t *) DISP_STRING("P2P_ROLE_STATE_SWITCH_CHANNEL") +#else + (uint8_t *) DISP_STRING("P2P_ROLE_STATE_GC_JOIN") +#endif +}; + +/*lint -restore */ +#endif /* DBG */ + +void +p2pRoleFsmStateTransition(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN enum ENUM_P2P_ROLE_STATE eNextState); + +uint8_t p2pRoleFsmInit(IN struct ADAPTER *prAdapter, + IN uint8_t ucRoleIdx) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct P2P_CHNL_REQ_INFO *prP2pChnlReqInfo = + (struct P2P_CHNL_REQ_INFO *) NULL; + struct GL_P2P_INFO *prP2PInfo = NULL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + ASSERT_BREAK( + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, ucRoleIdx) + == NULL); + + prP2pRoleFsmInfo = kalMemAlloc( + sizeof(struct P2P_ROLE_FSM_INFO), + VIR_MEM_TYPE); + + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, ucRoleIdx) = + prP2pRoleFsmInfo; + + ASSERT_BREAK(prP2pRoleFsmInfo != NULL); + + kalMemZero(prP2pRoleFsmInfo, sizeof(struct P2P_ROLE_FSM_INFO)); + + prP2pRoleFsmInfo->ucRoleIndex = ucRoleIdx; + + prP2pRoleFsmInfo->eCurrentState = P2P_ROLE_STATE_IDLE; + + prP2pRoleFsmInfo->u4P2pPacketFilter = + PARAM_PACKET_FILTER_SUPPORTED; + + prP2pChnlReqInfo = &prP2pRoleFsmInfo->rChnlReqInfo; + LINK_INITIALIZE(&(prP2pChnlReqInfo->rP2pChnlReqLink)); + + cnmTimerInitTimer(prAdapter, + &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer), + (PFN_MGMT_TIMEOUT_FUNC) p2pRoleFsmRunEventTimeout, + (unsigned long) prP2pRoleFsmInfo); + +#if CFG_ENABLE_PER_STA_STATISTICS_LOG + cnmTimerInitTimer(prAdapter, + &(prP2pRoleFsmInfo->rP2pRoleFsmGetStatisticsTimer), + (PFN_MGMT_TIMEOUT_FUNC) p2pRoleFsmGetStaStatistics, + (unsigned long) prP2pRoleFsmInfo); +#endif + +#if (CFG_SUPPORT_DFS_MASTER == 1) + cnmTimerInitTimer(prAdapter, + &(prP2pRoleFsmInfo->rDfsShutDownTimer), + (PFN_MGMT_TIMEOUT_FUNC) + p2pRoleFsmRunEventDfsShutDownTimeout, + (unsigned long) prP2pRoleFsmInfo); +#endif + + prP2pBssInfo = cnmGetBssInfoAndInit(prAdapter, + NETWORK_TYPE_P2P, + FALSE); + + if (!prP2pBssInfo) { + DBGLOG(P2P, ERROR, + "Error allocating BSS Info Structure\n"); + break; + } + + BSS_INFO_INIT(prAdapter, prP2pBssInfo); + prP2pRoleFsmInfo->ucBssIndex = prP2pBssInfo->ucBssIndex; + + /* For state identify, not really used. */ + prP2pBssInfo->eIntendOPMode = OP_MODE_P2P_DEVICE; + + /* glRegisterP2P has setup the mac address */ + /* For wlan0 as AP mode case, this function will be called when + * changing interface type. And the MAC Addr overwrite by Role + * isn't expected. + * Maybe only using ucRoleIdx to calc MAC addr is better than + * using Role type. + */ + prP2PInfo = prAdapter->prGlueInfo->prP2PInfo[ucRoleIdx]; + COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, + prP2PInfo->prDevHandler->dev_addr); + + /* For BSS_INFO back trace to P2P Role & get Role FSM. */ + prP2pBssInfo->u4PrivateData = ucRoleIdx; + + if (p2pFuncIsAPMode( + prAdapter->rWifiVar.prP2PConnSettings[ucRoleIdx])) { + prP2pBssInfo->ucConfigAdHocAPMode = AP_MODE_11G; + prP2pBssInfo->u2HwDefaultFixedRateCode = + RATE_CCK_1M_LONG; + } else { + prP2pBssInfo->ucConfigAdHocAPMode = AP_MODE_11G_P2P; + prP2pBssInfo->u2HwDefaultFixedRateCode = RATE_OFDM_6M; + } + + prP2pBssInfo->ucNonHTBasicPhyType = (uint8_t) + 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(struct WLAN_BEACON_FRAME, aucInfoElem[0]) + + MAX_IE_LENGTH); + + if (prP2pBssInfo->prBeacon) { + prP2pBssInfo->prBeacon->eSrc = TX_PACKET_MGMT; + /* NULL STA_REC */ + prP2pBssInfo->prBeacon->ucStaRecIndex = + STA_REC_INDEX_BMCAST; + prP2pBssInfo->prBeacon->ucBssIndex = + prP2pBssInfo->ucBssIndex; + } else { + /* Out of memory. */ + ASSERT(FALSE); + } + + 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; + prP2pBssInfo->ucNss = wlanGetSupportNss(prAdapter, + prP2pBssInfo->ucBssIndex); +#if (CFG_HW_WMM_BY_BSS == 0) + prP2pBssInfo->ucWmmQueSet = (prAdapter->rWifiVar.eDbdcMode == + ENUM_DBDC_MODE_DISABLED) + ? DBDC_5G_WMM_INDEX + : DBDC_2G_WMM_INDEX; +#endif + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) + prP2pBssInfo->fgIsQBSS = TRUE; + else + prP2pBssInfo->fgIsQBSS = FALSE; + +#if (CFG_SUPPORT_DFS_MASTER == 1) + p2pFuncRadarInfoInit(); +#endif + + /* SET_NET_PWR_STATE_IDLE(prAdapter, + * prP2pBssInfo->ucBssIndex); + */ + + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_IDLE); + + } while (FALSE); + + if (prP2pBssInfo) + return prP2pBssInfo->ucBssIndex; + else + return prAdapter->ucP2PDevBssIdx; +} /* p2pFsmInit */ + +void p2pRoleFsmUninit(IN struct ADAPTER *prAdapter, IN uint8_t ucRoleIdx) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + DEBUGFUNC("p2pRoleFsmUninit()"); + DBGLOG(P2P, INFO, "->p2pRoleFsmUninit()\n"); + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, ucRoleIdx); + + ASSERT_BREAK(prP2pRoleFsmInfo != NULL); + + if (!prP2pRoleFsmInfo) + return; + + prP2pBssInfo = + prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex]; + + p2pFuncDissolve(prAdapter, + prP2pBssInfo, TRUE, + REASON_CODE_DEAUTH_LEAVING_BSS); + + SET_NET_PWR_STATE_IDLE(prAdapter, prP2pBssInfo->ucBssIndex); + + /* Function Dissolve should already enter IDLE state. */ + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_IDLE); + + p2pRoleFsmRunEventAbort(prAdapter, prP2pRoleFsmInfo); + + /* Clear CmdQue */ + kalClearMgmtFramesByBssIdx(prAdapter->prGlueInfo, + prP2pBssInfo->ucBssIndex); + kalClearSecurityFramesByBssIdx(prAdapter->prGlueInfo, + prP2pBssInfo->ucBssIndex); + /* Clear PendingCmdQue */ + wlanReleasePendingCMDbyBssIdx(prAdapter, + prP2pBssInfo->ucBssIndex); + /* Clear PendingTxMsdu */ + nicFreePendingTxMsduInfo(prAdapter, + prP2pBssInfo->ucBssIndex, MSDU_REMOVE_BY_BSS_INDEX); + + /* Deactivate BSS. */ + UNSET_NET_ACTIVE(prAdapter, prP2pRoleFsmInfo->ucBssIndex); + + nicDeactivateNetwork(prAdapter, prP2pRoleFsmInfo->ucBssIndex); + + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, ucRoleIdx) = NULL; + + if (prP2pBssInfo->prBeacon) { + cnmMgtPktFree(prAdapter, prP2pBssInfo->prBeacon); + prP2pBssInfo->prBeacon = NULL; + } + + cnmFreeBssInfo(prAdapter, prP2pBssInfo); + + /* ensure the timer be stopped */ + cnmTimerStopTimer(prAdapter, + &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer)); + +#if CFG_ENABLE_PER_STA_STATISTICS_LOG + cnmTimerStopTimer(prAdapter, + &prP2pRoleFsmInfo->rP2pRoleFsmGetStatisticsTimer); +#endif + +#if (CFG_SUPPORT_DFS_MASTER == 1) + cnmTimerStopTimer(prAdapter, + &(prP2pRoleFsmInfo->rDfsShutDownTimer)); +#endif + + if (prP2pRoleFsmInfo) + kalMemFree(prP2pRoleFsmInfo, VIR_MEM_TYPE, + sizeof(struct P2P_ROLE_FSM_INFO)); + + } while (FALSE); + + return; +#if 0 + struct P2P_FSM_INFO *prP2pFsmInfo = (struct P2P_FSM_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) 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. + */ + kalClearMgmtFramesByBssIdx(prAdapter->prGlueInfo, + NETWORK_TYPE_P2P_INDEX); + + /* Clear PendingCmdQue */ + wlanReleasePendingCMDbyBssIdx(prAdapter, + NETWORK_TYPE_P2P_INDEX); + + if (prP2pBssInfo->prBeacon) { + cnmMgtPktFree(prAdapter, prP2pBssInfo->prBeacon); + prP2pBssInfo->prBeacon = NULL; + } + + } while (FALSE); + + return; +#endif +} /* p2pRoleFsmUninit */ + +void +p2pRoleFsmStateTransition(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN enum ENUM_P2P_ROLE_STATE eNextState) +{ + u_int8_t fgIsTransitionOut = (u_int8_t) FALSE; + struct BSS_INFO *prP2pRoleBssInfo = (struct BSS_INFO *) NULL; + + prP2pRoleBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, prP2pRoleFsmInfo->ucBssIndex); + + do { + if (!IS_BSS_ACTIVE(prP2pRoleBssInfo)) { + if (!cnmP2PIsPermitted(prAdapter)) + return; + + SET_NET_ACTIVE(prAdapter, prP2pRoleBssInfo->ucBssIndex); + nicActivateNetwork(prAdapter, + prP2pRoleBssInfo->ucBssIndex); + } + + fgIsTransitionOut = fgIsTransitionOut ? FALSE : TRUE; + + if (!fgIsTransitionOut) { + DBGLOG(P2P, STATE, + "[P2P_ROLE][%d]TRANSITION(Bss%d): [%s] -> [%s]\n", + prP2pRoleFsmInfo->ucRoleIndex, + prP2pRoleFsmInfo->ucBssIndex, + apucDebugP2pRoleState + [prP2pRoleFsmInfo->eCurrentState], + apucDebugP2pRoleState[eNextState]); + + /* Transition into current state. */ + prP2pRoleFsmInfo->eCurrentState = eNextState; + } + + switch (prP2pRoleFsmInfo->eCurrentState) { + case P2P_ROLE_STATE_IDLE: + if (!fgIsTransitionOut) + p2pRoleStateInit_IDLE(prAdapter, + prP2pRoleFsmInfo, + prP2pRoleBssInfo); + else + p2pRoleStateAbort_IDLE(prAdapter, + prP2pRoleFsmInfo, + &(prP2pRoleFsmInfo->rChnlReqInfo)); + break; + case P2P_ROLE_STATE_SCAN: + if (!fgIsTransitionOut) { + p2pRoleStateInit_SCAN(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rScanReqInfo)); + } else { + p2pRoleStateAbort_SCAN(prAdapter, + prP2pRoleFsmInfo); + } + break; + case P2P_ROLE_STATE_REQING_CHANNEL: + if (!fgIsTransitionOut) { + p2pRoleStateInit_REQING_CHANNEL(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rChnlReqInfo)); + } else { + p2pRoleStateAbort_REQING_CHANNEL(prAdapter, + prP2pRoleBssInfo, + prP2pRoleFsmInfo, eNextState); + } + break; + case P2P_ROLE_STATE_AP_CHNL_DETECTION: + if (!fgIsTransitionOut) { + p2pRoleStateInit_AP_CHNL_DETECTION(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rScanReqInfo), + &(prP2pRoleFsmInfo->rConnReqInfo)); + } else { + p2pRoleStateAbort_AP_CHNL_DETECTION(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rConnReqInfo), + &(prP2pRoleFsmInfo->rChnlReqInfo), + &(prP2pRoleFsmInfo->rScanReqInfo), + eNextState); + } + break; + case P2P_ROLE_STATE_GC_JOIN: + if (!fgIsTransitionOut) { + p2pRoleStateInit_GC_JOIN(prAdapter, + prP2pRoleFsmInfo, + &(prP2pRoleFsmInfo->rChnlReqInfo)); + } else { + p2pRoleStateAbort_GC_JOIN(prAdapter, + prP2pRoleFsmInfo, + &(prP2pRoleFsmInfo->rJoinInfo), + eNextState); + } + break; + +#if (CFG_SUPPORT_DFS_MASTER == 1) + case P2P_ROLE_STATE_DFS_CAC: + if (!fgIsTransitionOut) { + p2pRoleStateInit_DFS_CAC(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rChnlReqInfo)); + } else { + p2pRoleStateAbort_DFS_CAC(prAdapter, + prP2pRoleBssInfo, + prP2pRoleFsmInfo, + eNextState); + } + break; + case P2P_ROLE_STATE_SWITCH_CHANNEL: + if (!fgIsTransitionOut) { + p2pRoleStateInit_SWITCH_CHANNEL(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rChnlReqInfo)); + } else { + p2pRoleStateAbort_SWITCH_CHANNEL(prAdapter, + prP2pRoleBssInfo, + prP2pRoleFsmInfo, + eNextState); + } + break; +#endif + default: + ASSERT(FALSE); + break; + } + } while (fgIsTransitionOut); + +} /* p2pRoleFsmStateTransition */ + +void p2pRoleFsmRunEventTimeout(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) ulParamPtr; + struct P2P_CHNL_REQ_INFO *prP2pChnlReqInfo = + (struct P2P_CHNL_REQ_INFO *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pRoleFsmInfo != NULL)); + + switch (prP2pRoleFsmInfo->eCurrentState) { + case P2P_ROLE_STATE_IDLE: + prP2pChnlReqInfo = &(prP2pRoleFsmInfo->rChnlReqInfo); + if (prP2pChnlReqInfo->fgIsChannelRequested) { + p2pFuncReleaseCh(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + prP2pChnlReqInfo); + if (IS_NET_PWR_STATE_IDLE(prAdapter, + prP2pRoleFsmInfo->ucBssIndex)) + ASSERT(FALSE); + } + + if (IS_NET_PWR_STATE_IDLE(prAdapter, + prP2pRoleFsmInfo->ucBssIndex)) { + DBGLOG(P2P, TRACE, + "Role BSS IDLE, deactive network.\n"); + UNSET_NET_ACTIVE(prAdapter, + prP2pRoleFsmInfo->ucBssIndex); + nicDeactivateNetwork(prAdapter, + prP2pRoleFsmInfo->ucBssIndex); + nicUpdateBss(prAdapter, + prP2pRoleFsmInfo->ucBssIndex); + } + break; + case P2P_ROLE_STATE_GC_JOIN: + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_IDLE); + break; +#if (CFG_SUPPORT_DFS_MASTER == 1) + case P2P_ROLE_STATE_DFS_CAC: + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_IDLE); + kalP2PCacFinishedUpdate(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex); + p2pFuncSetDfsState(DFS_STATE_ACTIVE); + cnmTimerStartTimer(prAdapter, + &(prP2pRoleFsmInfo->rDfsShutDownTimer), + 5000); + break; +#endif + default: + DBGLOG(P2P, ERROR, + "Current P2P Role State %d is unexpected for FSM timeout event.\n", + prP2pRoleFsmInfo->eCurrentState); + ASSERT(FALSE); + break; + } + } while (FALSE); +} /* p2pRoleFsmRunEventTimeout */ + +static void +p2pRoleFsmDeauhComplete(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + enum ENUM_PARAM_MEDIA_STATE eOriMediaStatus; + + if (!prAdapter) { + DBGLOG(P2P, ERROR, "prAdapter shouldn't be NULL!\n"); + return; + } + + if (!prStaRec) { + DBGLOG(P2P, ERROR, "prStaRec shouldn't be NULL!\n"); + return; + } + + DBGLOG(P2P, INFO, "Deauth TX Complete!\n"); + + prP2pBssInfo = prAdapter->aprBssInfo[prStaRec->ucBssIndex]; + ASSERT_BREAK(prP2pBssInfo != NULL); + eOriMediaStatus = prP2pBssInfo->eConnectionState; + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData); + + /* + * After EAP exchange, GO/GC will disconnect + * and re-connect in short time. + * GC's new station record will be removed unexpectedly at GO's side + * if new GC's connection happens + * when previous GO's disconnection flow is + * processing. 4-way handshake will NOT be triggered. + */ + if ((prStaRec->eAuthAssocState == AAA_STATE_SEND_AUTH2 || + prStaRec->eAuthAssocState == AAA_STATE_SEND_ASSOC2) && + (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) && + (p2pFuncIsAPMode(prAdapter->rWifiVar + .prP2PConnSettings[prP2pBssInfo->u4PrivateData]) == FALSE)) { + DBGLOG(P2P, WARN, + "Skip deauth tx done since AAA fsm is in progress.\n"); + return; + } else if (prStaRec->eAuthAssocState == SAA_STATE_SEND_AUTH1 || + prStaRec->eAuthAssocState == SAA_STATE_SEND_ASSOC1) { + DBGLOG(P2P, WARN, + "Skip deauth tx done since SAA fsm is in progress.\n"); + return; + } + + ASSERT_BREAK(prP2pRoleFsmInfo != NULL); + + /* Change station state. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + /* Reset Station Record Status. */ + p2pFuncResetStaRecStatus(prAdapter, prStaRec); + + /* Try to remove StaRec in BSS client list before free it */ + bssRemoveClient(prAdapter, prP2pBssInfo, prStaRec); + + /* STA_RECORD free */ + cnmStaRecFree(prAdapter, prStaRec); + + if ((prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) || + (bssGetClientCount(prAdapter, prP2pBssInfo) == 0)) { + if (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) + DBGLOG(P2P, TRACE, + "No More Client, Media Status DISCONNECTED\n"); + else + DBGLOG(P2P, TRACE, + "Deauth done, Media Status DISCONNECTED\n"); + p2pChangeMediaState(prAdapter, + prP2pBssInfo, + PARAM_MEDIA_STATE_DISCONNECTED); + } + + /* STOP BSS if power is IDLE */ + if (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + if (IS_NET_PWR_STATE_IDLE(prAdapter, + prP2pRoleFsmInfo->ucBssIndex) + && (bssGetClientCount(prAdapter, prP2pBssInfo) == 0)) { + /* All Peer disconnected !! Stop BSS now!! */ + p2pFuncStopComplete(prAdapter, prP2pBssInfo); + } else if (eOriMediaStatus != prP2pBssInfo->eConnectionState) + /* Update the Media State if necessary */ + nicUpdateBss(prAdapter, prP2pBssInfo->ucBssIndex); + } else /* GC : Stop BSS when Deauth done */ + p2pFuncStopComplete(prAdapter, prP2pBssInfo); + +} + +void p2pRoleFsmDeauthTimeout(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr) +{ + struct STA_RECORD *prStaRec = (struct STA_RECORD *) ulParamPtr; + + p2pRoleFsmDeauhComplete(prAdapter, prStaRec); +} /* p2pRoleFsmRunEventTimeout */ + +void p2pRoleFsmRunEventAbort(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo) +{ + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pRoleFsmInfo != NULL)); + + if (prP2pRoleFsmInfo->eCurrentState != P2P_ROLE_STATE_IDLE) { + /* Get into IDLE state. */ + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_IDLE); + } + + /* Abort IDLE. */ + p2pRoleStateAbort_IDLE(prAdapter, + prP2pRoleFsmInfo, + &(prP2pRoleFsmInfo->rChnlReqInfo)); + + } while (FALSE); +} /* p2pRoleFsmRunEventAbort */ + +uint32_t +p2pRoleFsmRunEventDeauthTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + DBGLOG(P2P, INFO, + "Deauth TX Done,rTxDoneStatus = %d\n", + rTxDoneStatus); + + prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + + if (prStaRec == NULL) { + DBGLOG(P2P, TRACE, + "Station Record NULL, Index:%d\n", + prMsduInfo->ucStaRecIndex); + break; + } + /* Avoid re-entry */ + cnmTimerStopTimer(prAdapter, &(prStaRec->rDeauthTxDoneTimer)); + + p2pRoleFsmDeauhComplete(prAdapter, prStaRec); + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; + +} /* p2pRoleFsmRunEventDeauthTxDone */ + +void p2pRoleFsmRunEventRxDeauthentication(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct SW_RFB *prSwRfb) +{ + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + uint16_t u2ReasonCode = 0; + /* flag to send deauth when rx sta disassc/deauth */ + u_int8_t fgSendDeauth = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + + if (prStaRec == NULL) + prStaRec = cnmGetStaRecByIndex(prAdapter, + prSwRfb->ucStaRecIdx); + + if (!prStaRec) + break; + + prP2pBssInfo = prAdapter->aprBssInfo[prStaRec->ucBssIndex]; + + 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) { + struct WLAN_DEAUTH_FRAME *prDeauthFrame = + (struct WLAN_DEAUTH_FRAME *) + prSwRfb->pvHeader; + uint16_t 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); + + +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) +/* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus( + prAdapter->prGlueInfo, + (uint8_t) prP2pBssInfo->u4PrivateData, + NULL, + prDeauthFrame->aucInfoElem, + u2IELength, + u2ReasonCode, + WLAN_STATUS_MEDIA_DISCONNECT); + +#else +/* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus( + prAdapter->prGlueInfo, + (uint8_t) prP2pBssInfo->u4PrivateData, + NULL, + prDeauthFrame->aucInfoElem, + u2IELength, + u2ReasonCode); +#endif + + prP2pBssInfo->prStaRecOfAP = NULL; + + p2pFuncDisconnect(prAdapter, + prP2pBssInfo, + prStaRec, + FALSE, + u2ReasonCode); + + p2pFuncStopComplete(prAdapter, prP2pBssInfo); + + SET_NET_PWR_STATE_IDLE(prAdapter, + prP2pBssInfo->ucBssIndex); + + p2pRoleFsmStateTransition(prAdapter, + P2P_ROLE_INDEX_2_ROLE_FSM_INFO( + prAdapter, + prP2pBssInfo->u4PrivateData), + P2P_ROLE_STATE_IDLE); + } + break; + case OP_MODE_ACCESS_POINT: + /* Delete client from client list. */ + if (authProcessRxDeauthFrame(prSwRfb, + prP2pBssInfo->aucBSSID, + &u2ReasonCode) == WLAN_STATUS_SUCCESS) { +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if (rsnCheckBipKeyInstalled(prAdapter, + prStaRec)) { + if (HAL_RX_STATUS_IS_CIPHER_MISMATCH( + prSwRfb->prRxStatus) || + HAL_RX_STATUS_IS_CLM_ERROR( + prSwRfb->prRxStatus)) { + /* if cipher mismatch, + * or incorrect encrypt, + * just drop + */ + DBGLOG(P2P, ERROR, + "Rx deauth CM/CLM=1\n"); + return; + } + + /* 4.3.3.1 send unprotected deauth + * reason 6/7 + */ + DBGLOG(P2P, INFO, "deauth reason=6\n"); + fgSendDeauth = TRUE; + u2ReasonCode = REASON_CODE_CLASS_2_ERR; + prStaRec->rPmfCfg.fgRxDeauthResp = TRUE; + } +#endif + + if (bssRemoveClient(prAdapter, + prP2pBssInfo, prStaRec)) { + /* Indicate disconnect to Host. */ + p2pFuncDisconnect(prAdapter, + prP2pBssInfo, + prStaRec, + fgSendDeauth, + u2ReasonCode); + /* Deactive BSS + * if PWR is IDLE and no peer + */ + if (IS_NET_PWR_STATE_IDLE(prAdapter, + prP2pBssInfo->ucBssIndex) && + (bssGetClientCount(prAdapter, + prP2pBssInfo) == 0)) { + /* All Peer disconnected !! + * Stop BSS now!! + */ + p2pFuncStopComplete(prAdapter, + prP2pBssInfo); + } + } + } + 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); +} /* p2pRoleFsmRunEventRxDeauthentication */ + +void p2pRoleFsmRunEventRxDisassociation(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct SW_RFB *prSwRfb) +{ + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + uint16_t u2ReasonCode = 0; + /* flag to send deauth when rx sta disassc/deauth */ + u_int8_t fgSendDeauth = FALSE; + + + if (prStaRec == NULL) + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (!prStaRec) { + DBGLOG(P2P, ERROR, + "prStaRec of prSwRfb->ucStaRecIdx %d is NULL!\n", + prSwRfb->ucStaRecIdx); + return; + } + + prP2pBssInfo = prAdapter->aprBssInfo[prStaRec->ucBssIndex]; + + if (prStaRec->ucStaState == STA_STATE_1) + return; + + DBGLOG(P2P, TRACE, "RX Disassoc\n"); + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_INFRASTRUCTURE: + if (assocProcessRxDisassocFrame(prAdapter, + prSwRfb, + prStaRec->aucMacAddr, + &prStaRec->u2ReasonCode) == WLAN_STATUS_SUCCESS) { + + struct WLAN_DISASSOC_FRAME *prDisassocFrame = + (struct WLAN_DISASSOC_FRAME *) + prSwRfb->pvHeader; + uint16_t u2IELength = 0; + + ASSERT(prP2pBssInfo->prStaRecOfAP == prStaRec); + + if (prP2pBssInfo->prStaRecOfAP != prStaRec) + break; + + u2IELength = prSwRfb->u2PacketLen + - (WLAN_MAC_HEADER_LEN + REASON_CODE_FIELD_LEN); + +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) + /* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + (uint8_t) prP2pBssInfo->u4PrivateData, NULL, + prDisassocFrame->aucInfoElem, + u2IELength, prStaRec->u2ReasonCode, + WLAN_STATUS_MEDIA_DISCONNECT); + +#else + /* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + (uint8_t) prP2pBssInfo->u4PrivateData, NULL, + prDisassocFrame->aucInfoElem, + u2IELength, prStaRec->u2ReasonCode); +#endif + + prP2pBssInfo->prStaRecOfAP = NULL; + + p2pFuncDisconnect(prAdapter, + prP2pBssInfo, + prStaRec, + FALSE, + prStaRec->u2ReasonCode); + + p2pFuncStopComplete(prAdapter, prP2pBssInfo); + + SET_NET_PWR_STATE_IDLE(prAdapter, + prP2pBssInfo->ucBssIndex); + + p2pRoleFsmStateTransition(prAdapter, + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData), + P2P_ROLE_STATE_IDLE); + } + break; + case OP_MODE_ACCESS_POINT: + /* Delete client from client list. */ + if (assocProcessRxDisassocFrame(prAdapter, + prSwRfb, + prP2pBssInfo->aucBSSID, + &u2ReasonCode) == WLAN_STATUS_SUCCESS) { + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + if (HAL_RX_STATUS_IS_CIPHER_MISMATCH( + prSwRfb->prRxStatus) || + HAL_RX_STATUS_IS_CLM_ERROR( + prSwRfb->prRxStatus)) { + /* if cipher mismatch, + * or incorrect encrypt, just drop + */ + DBGLOG(P2P, ERROR, + "Rx disassoc CM/CLM=1\n"); + return; + } + + /* 4.3.3.1 send unprotected deauth + * reason 6/7 + */ + DBGLOG(P2P, INFO, "deauth reason=6\n"); + fgSendDeauth = TRUE; + u2ReasonCode = REASON_CODE_CLASS_2_ERR; + prStaRec->rPmfCfg.fgRxDeauthResp = TRUE; + } +#endif + + if (bssRemoveClient(prAdapter, + prP2pBssInfo, prStaRec)) { + /* Indicate disconnect to Host. */ + p2pFuncDisconnect(prAdapter, + prP2pBssInfo, + prStaRec, + fgSendDeauth, + u2ReasonCode); + /* Deactive BSS if PWR is IDLE and no peer */ + if (IS_NET_PWR_STATE_IDLE(prAdapter, + prP2pBssInfo->ucBssIndex) && + (bssGetClientCount(prAdapter, + prP2pBssInfo) == 0)) { + /* All Peer disconnected !! + * Stop BSS now!! + */ + p2pFuncStopComplete(prAdapter, + prP2pBssInfo); + } + + } + } + break; + case OP_MODE_P2P_DEVICE: + default: + ASSERT(FALSE); + break; + } + +} /* p2pRoleFsmRunEventRxDisassociation */ + +void p2pRoleFsmRunEventBeaconTimeout(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pBssInfo) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData); + + /* Only client mode would have beacon lost event. */ + if (prP2pBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) { + DBGLOG(P2P, ERROR, + "Error case, P2P BSS %d not INFRA mode but beacon timeout\n", + prP2pRoleFsmInfo->ucRoleIndex); + break; + } + + DBGLOG(P2P, TRACE, + "p2pFsmRunEventBeaconTimeout: BSS %d Beacon Timeout\n", + prP2pRoleFsmInfo->ucRoleIndex); + + if (prP2pBssInfo->eConnectionState + == PARAM_MEDIA_STATE_CONNECTED) { + +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) + /* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, + NULL, NULL, 0, + REASON_CODE_DEAUTH_LEAVING_BSS, + WLAN_STATUS_MEDIA_DISCONNECT); + + +#else + /* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, + NULL, NULL, 0, + REASON_CODE_DEAUTH_LEAVING_BSS); +#endif + + if (prP2pBssInfo->prStaRecOfAP != NULL) { + struct STA_RECORD *prStaRec = + prP2pBssInfo->prStaRecOfAP; + + prP2pBssInfo->prStaRecOfAP = NULL; + + p2pFuncDisconnect(prAdapter, + prP2pBssInfo, + prStaRec, FALSE, + REASON_CODE_DISASSOC_LEAVING_BSS); + + p2pFuncStopComplete(prAdapter, prP2pBssInfo); + + SET_NET_PWR_STATE_IDLE(prAdapter, + prP2pBssInfo->ucBssIndex); + /* 20120830 moved into p2pFuncDisconnect() */ + /* cnmStaRecFree(prAdapter, + * prP2pBssInfo->prStaRecOfAP); + */ + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_IDLE); + + } + } + } while (FALSE); +} /* p2pFsmRunEventBeaconTimeout */ + +/*================== Message Event ==================*/ +void p2pRoleFsmRunEventStartAP(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct MSG_P2P_START_AP *prP2pStartAPMsg = + (struct MSG_P2P_START_AP *) NULL; + struct P2P_CONNECTION_REQ_INFO *prP2pConnReqInfo = + (struct P2P_CONNECTION_REQ_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo = + (struct P2P_SPECIFIC_BSS_INFO *) NULL; +#if CFG_SUPPORT_DBDC + struct CNM_DBDC_CAP rDbdcCap; +#endif /*CFG_SUPPORT_DBDC*/ + + DBGLOG(P2P, TRACE, "p2pRoleFsmRunEventStartAP\n"); + + prP2pStartAPMsg = (struct MSG_P2P_START_AP *) prMsgHdr; + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pStartAPMsg->ucRoleIdx); + + prAdapter->prP2pInfo->eConnState = P2P_CNN_NORMAL; + + DBGLOG(P2P, TRACE, + "p2pRoleFsmRunEventStartAP with Role(%d)\n", + prP2pStartAPMsg->ucRoleIdx); + + + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, ERROR, + "p2pRoleFsmRunEventStartAP: Corresponding P2P Role FSM empty: %d.\n", + prP2pStartAPMsg->ucRoleIdx); + goto error; + } + + prP2pBssInfo = prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex]; + prP2pSpecificBssInfo = + prAdapter->rWifiVar + .prP2pSpecificBssInfo[prP2pBssInfo->u4PrivateData]; + prP2pConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + + if (prP2pStartAPMsg->u4BcnInterval) { + DBGLOG(P2P, TRACE, + "Beacon interval updated to :%u\n", + prP2pStartAPMsg->u4BcnInterval); + prP2pBssInfo->u2BeaconInterval = + (uint16_t) prP2pStartAPMsg->u4BcnInterval; + } else if (prP2pBssInfo->u2BeaconInterval == 0) { + prP2pBssInfo->u2BeaconInterval = DOT11_BEACON_PERIOD_DEFAULT; + } + + if (prP2pStartAPMsg->u4DtimPeriod) { + DBGLOG(P2P, TRACE, + "DTIM interval updated to :%u\n", + prP2pStartAPMsg->u4DtimPeriod); + prP2pBssInfo->ucDTIMPeriod = + (uint8_t) prP2pStartAPMsg->u4DtimPeriod; + } else if (prP2pBssInfo->ucDTIMPeriod == 0) { + prP2pBssInfo->ucDTIMPeriod = DOT11_DTIM_PERIOD_DEFAULT; + } + + if (prP2pStartAPMsg->u2SsidLen != 0) { + kalMemCopy(prP2pConnReqInfo->rSsidStruct.aucSsid, + prP2pStartAPMsg->aucSsid, + prP2pStartAPMsg->u2SsidLen); + prP2pConnReqInfo->rSsidStruct.ucSsidLen = + prP2pSpecificBssInfo->u2GroupSsidLen = + prP2pStartAPMsg->u2SsidLen; + kalMemCopy(prP2pSpecificBssInfo->aucGroupSsid, + prP2pStartAPMsg->aucSsid, + prP2pStartAPMsg->u2SsidLen); + } + + if (p2pFuncIsAPMode(prAdapter->rWifiVar + .prP2PConnSettings[prP2pStartAPMsg->ucRoleIdx])) { + prP2pConnReqInfo->eConnRequest = P2P_CONNECTION_TYPE_PURE_AP; + + /* Overwrite AP channel */ + if (prAdapter->rWifiVar.ucApChannel && + prAdapter->rWifiVar.ucApChnlDefFromCfg) { + prP2pConnReqInfo->rChannelInfo.ucChannelNum = + prAdapter->rWifiVar.ucApChannel; + + if (prAdapter->rWifiVar.ucApChannel <= 14) + prP2pConnReqInfo->rChannelInfo.eBand = BAND_2G4; + else + prP2pConnReqInfo->rChannelInfo.eBand = BAND_5G; + } + } else { + prP2pConnReqInfo->eConnRequest = P2P_CONNECTION_TYPE_GO; + } + + /* Clear list to ensure no client staRec */ + if (bssGetClientCount(prAdapter, prP2pBssInfo) != 0) { + DBGLOG(P2P, WARN, + "Clear list to ensure no empty/client staRec\n"); + bssInitializeClientList(prAdapter, prP2pBssInfo); + } + + /* The supplicant may start AP + * before rP2pRoleFsmTimeoutTimer is time out + */ + /* We need to make sure the BSS was deactivated + * and all StaRec can be free + */ + if (timerPendingTimer(&(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer))) { + /* call p2pRoleFsmRunEventTimeout() + * to deactive BSS and free channel + */ + p2pRoleFsmRunEventTimeout(prAdapter, + (unsigned long)prP2pRoleFsmInfo); + cnmTimerStopTimer(prAdapter, + &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer)); + } + +#if (CFG_SUPPORT_DFS_MASTER == 1) + if (timerPendingTimer(&(prP2pRoleFsmInfo->rDfsShutDownTimer))) { + DBGLOG(P2P, INFO, + "p2pRoleFsmRunEventStartAP: Stop DFS shut down timer.\n"); + cnmTimerStopTimer(prAdapter, + &(prP2pRoleFsmInfo->rDfsShutDownTimer)); + } +#endif + + prP2pBssInfo->eBand = prP2pConnReqInfo->rChannelInfo.eBand; + if (prP2pBssInfo->fgIsWmmInited == FALSE) + prP2pBssInfo->ucWmmQueSet = cnmWmmIndexDecision(prAdapter, + prP2pBssInfo); +#if CFG_SUPPORT_DBDC + kalMemZero(&rDbdcCap, sizeof(struct CNM_DBDC_CAP)); + cnmDbdcEnableDecision(prAdapter, + prP2pBssInfo->ucBssIndex, + prP2pConnReqInfo->rChannelInfo.eBand, + prP2pConnReqInfo->rChannelInfo.ucChannelNum, + prP2pBssInfo->ucWmmQueSet); + cnmGetDbdcCapability(prAdapter, + prP2pBssInfo->ucBssIndex, + prP2pConnReqInfo->rChannelInfo.eBand, + prP2pConnReqInfo->rChannelInfo.ucChannelNum, + wlanGetSupportNss(prAdapter, prP2pBssInfo->ucBssIndex), + &rDbdcCap); + + DBGLOG(P2P, TRACE, + "p2pRoleFsmRunEventStartAP: start AP at CH %u NSS=%u.\n", + prP2pConnReqInfo->rChannelInfo.ucChannelNum, + rDbdcCap.ucNss); + + prP2pBssInfo->ucNss = rDbdcCap.ucNss; +#endif /*CFG_SUPPORT_DBDC*/ + prP2pBssInfo->eHiddenSsidType = prP2pStartAPMsg->ucHiddenSsidType; + + /* + * beacon content is related with Nss number , + * need to update because of modification + */ + bssUpdateBeaconContent(prAdapter, prP2pBssInfo->ucBssIndex); + + if ((prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) || + (prP2pBssInfo->eIntendOPMode != OP_MODE_NUM)) { + /* 1. No switch to AP mode. + * 2. Not started yet. + */ + + if (prP2pRoleFsmInfo->eCurrentState + != P2P_ROLE_STATE_AP_CHNL_DETECTION + && + prP2pRoleFsmInfo->eCurrentState + != P2P_ROLE_STATE_IDLE) { + /* Make sure the state is in IDLE state. */ + p2pRoleFsmRunEventAbort(prAdapter, prP2pRoleFsmInfo); + } else if (prP2pRoleFsmInfo->eCurrentState + == P2P_ROLE_STATE_AP_CHNL_DETECTION) { + goto error; + } + + /* Leave IDLE state. */ + SET_NET_PWR_STATE_ACTIVE(prAdapter, prP2pBssInfo->ucBssIndex); + + prP2pBssInfo->eIntendOPMode = OP_MODE_ACCESS_POINT; + +#if 0 + prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.ucChannelNum = 8; + prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.eBand = BAND_2G4; + /* prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.ucBandwidth = + * 0; + */ + /* prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.eSCO = + * CHNL_EXT_SCN; + */ +#endif + + if (prP2pRoleFsmInfo->rConnReqInfo + .rChannelInfo.ucChannelNum != 0) { + DBGLOG(P2P, INFO, + "Role(%d) StartAP at CH(%d) NSS = %u\n", + prP2pStartAPMsg->ucRoleIdx, + prP2pRoleFsmInfo->rConnReqInfo + .rChannelInfo.ucChannelNum, + rDbdcCap.ucNss); + + p2pRoleStatePrepare_To_REQING_CHANNEL_STATE( + prAdapter, + GET_BSS_INFO_BY_INDEX(prAdapter, + prP2pRoleFsmInfo->ucBssIndex), + &(prP2pRoleFsmInfo->rConnReqInfo), + &(prP2pRoleFsmInfo->rChnlReqInfo)); + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_REQING_CHANNEL); + } else { + DBGLOG(P2P, INFO, + "Role(%d) StartAP Scan for working channel\n", + prP2pStartAPMsg->ucRoleIdx); + + /* For AP/GO mode with specific channel + * or non-specific channel. + */ + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_AP_CHNL_DETECTION); + } + } + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pRoleFsmRunEventStartAP */ + + +void p2pRoleFsmRunEventDelIface(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct MSG_P2P_DEL_IFACE *prP2pDelIfaceMsg = + (struct MSG_P2P_DEL_IFACE *) NULL; + struct GLUE_INFO *prGlueInfo = (struct GLUE_INFO *) NULL; + uint8_t ucRoleIdx; + struct GL_P2P_INFO *prP2pInfo = (struct GL_P2P_INFO *) NULL; + + + DBGLOG(P2P, INFO, "p2pRoleFsmRunEventDelIface\n"); + + prGlueInfo = prAdapter->prGlueInfo; + if (prGlueInfo == NULL) { + DBGLOG(P2P, ERROR, "prGlueInfo shouldn't be NULL!\n"); + goto error; + } + + prP2pDelIfaceMsg = (struct MSG_P2P_DEL_IFACE *) prMsgHdr; + ucRoleIdx = prP2pDelIfaceMsg->ucRoleIdx; + prAdapter = prGlueInfo->prAdapter; + prP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, ucRoleIdx); + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, ERROR, + "p2pRoleFsmRunEventDelIface: Corresponding P2P Role FSM empty: %d.\n", + prP2pDelIfaceMsg->ucRoleIdx); + goto error; + } + + prP2pBssInfo = prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex]; + + /* The state is in disconnecting and can not change any BSS status */ + if (IS_NET_PWR_STATE_IDLE(prAdapter, prP2pBssInfo->ucBssIndex) && + IS_NET_ACTIVE(prAdapter, prP2pBssInfo->ucBssIndex)) { + DBGLOG(P2P, TRACE, "under deauth procedure, Quit.\n"); + } else { + /*p2pFuncDissolve(prAdapter, + * prP2pBssInfo, TRUE, + * REASON_CODE_DEAUTH_LEAVING_BSS); + */ + + SET_NET_PWR_STATE_IDLE(prAdapter, prP2pBssInfo->ucBssIndex); + + /* Function Dissolve should already enter IDLE state. */ + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_IDLE); + + p2pRoleFsmRunEventAbort(prAdapter, prP2pRoleFsmInfo); + + /* Clear CmdQue */ + kalClearMgmtFramesByBssIdx(prAdapter->prGlueInfo, + prP2pBssInfo->ucBssIndex); + kalClearSecurityFramesByBssIdx(prAdapter->prGlueInfo, + prP2pBssInfo->ucBssIndex); + /* Clear PendingCmdQue */ + wlanReleasePendingCMDbyBssIdx(prAdapter, + prP2pBssInfo->ucBssIndex); + /* Clear PendingTxMsdu */ + nicFreePendingTxMsduInfo(prAdapter, + prP2pBssInfo->ucBssIndex, MSDU_REMOVE_BY_BSS_INDEX); + + /* Deactivate BSS. */ + UNSET_NET_ACTIVE(prAdapter, prP2pRoleFsmInfo->ucBssIndex); + + nicDeactivateNetwork(prAdapter, prP2pRoleFsmInfo->ucBssIndex); + nicUpdateBss(prAdapter, prP2pRoleFsmInfo->ucBssIndex); + } + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pRoleFsmRunEventStartAP */ + + +void p2pRoleFsmRunEventStopAP(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct MSG_P2P_SWITCH_OP_MODE *prP2pSwitchMode = + (struct MSG_P2P_SWITCH_OP_MODE *) NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct STA_RECORD *prCurrStaRec; + struct LINK *prClientList; + + prP2pSwitchMode = (struct MSG_P2P_SWITCH_OP_MODE *) prMsgHdr; + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pSwitchMode->ucRoleIdx); + + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, ERROR, + "p2pRoleFsmRunEventStopAP: Corresponding P2P Role FSM empty: %d.\n", + prP2pSwitchMode->ucRoleIdx); + goto error; + } + + prP2pBssInfo = prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex]; + + if (!prP2pBssInfo) { + DBGLOG(P2P, ERROR, + "prP2pBssInfo of prP2pRoleFsmInfo->ucBssIndex %d is NULL!\n", + prP2pRoleFsmInfo->ucBssIndex); + goto error; + } + +#if (CFG_SUPPORT_DFS_MASTER == 1) + p2pFuncSetDfsState(DFS_STATE_INACTIVE); + p2pFuncStopRdd(prAdapter, prP2pBssInfo->ucBssIndex); +#endif + + if (prP2pRoleFsmInfo->eCurrentState != P2P_ROLE_STATE_REQING_CHANNEL) { + p2pFuncStopGO(prAdapter, prP2pBssInfo); + + /* Start all Deauth done timer for all client */ + prClientList = &prP2pBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH_ENTRY(prCurrStaRec, + prClientList, rLinkEntry, struct STA_RECORD) { + ASSERT(prCurrStaRec); + /* Do not restart timer if the timer is pending, */ + /* (start in p2pRoleFsmRunEventConnectionAbort()) */ + if (!timerPendingTimer( + &(prCurrStaRec->rDeauthTxDoneTimer))) { + cnmTimerInitTimer(prAdapter, + &(prCurrStaRec->rDeauthTxDoneTimer), + (PFN_MGMT_TIMEOUT_FUNC) + p2pRoleFsmDeauthTimeout, + (unsigned long) prCurrStaRec); + + cnmTimerStartTimer(prAdapter, + &(prCurrStaRec->rDeauthTxDoneTimer), + P2P_DEAUTH_TIMEOUT_TIME_MS); + } + } + } + + SET_NET_PWR_STATE_IDLE(prAdapter, prP2pBssInfo->ucBssIndex); + + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_IDLE); + + prAdapter->fgIsStopApDone = TRUE; + +error: + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pRoleFsmRunEventStopAP */ + +#if (CFG_SUPPORT_DFS_MASTER == 1) +void p2pRoleFsmRunEventDfsCac(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct MSG_P2P_DFS_CAC *prP2pDfsCacMsg = + (struct MSG_P2P_DFS_CAC *) NULL; + struct P2P_CONNECTION_REQ_INFO *prP2pConnReqInfo = + (struct P2P_CONNECTION_REQ_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + enum ENUM_CHANNEL_WIDTH rChannelWidth; +#if CFG_SUPPORT_DBDC + struct CNM_DBDC_CAP rDbdcCap; +#endif /*CFG_SUPPORT_DBDC*/ + + + DBGLOG(P2P, INFO, "p2pRoleFsmRunEventDfsCac\n"); + + prP2pDfsCacMsg = (struct MSG_P2P_DFS_CAC *) prMsgHdr; + + rChannelWidth = prP2pDfsCacMsg->eChannelWidth; + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pDfsCacMsg->ucRoleIdx); + + DBGLOG(P2P, INFO, + "p2pRoleFsmRunEventDfsCac with Role(%d)\n", + prP2pDfsCacMsg->ucRoleIdx); + + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, ERROR, + "p2pRoleFsmRunEventDfsCac: Corresponding P2P Role FSM empty: %d.\n", + prP2pDfsCacMsg->ucRoleIdx); + goto error; + } + + if (timerPendingTimer(&(prP2pRoleFsmInfo->rDfsShutDownTimer))) { + DBGLOG(P2P, INFO, + "p2pRoleFsmRunEventDfsCac: Stop DFS shut down timer.\n"); + cnmTimerStopTimer(prAdapter, + &(prP2pRoleFsmInfo->rDfsShutDownTimer)); + } + + prP2pBssInfo = prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex]; + + prP2pConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + + if (p2pFuncIsAPMode(prAdapter->rWifiVar + .prP2PConnSettings[prP2pDfsCacMsg->ucRoleIdx])) + prP2pConnReqInfo->eConnRequest = P2P_CONNECTION_TYPE_PURE_AP; + else + prP2pConnReqInfo->eConnRequest = P2P_CONNECTION_TYPE_GO; + + prP2pBssInfo->eBand = prP2pConnReqInfo->rChannelInfo.eBand; + if (prP2pBssInfo->fgIsWmmInited == FALSE) + prP2pBssInfo->ucWmmQueSet = cnmWmmIndexDecision(prAdapter, + prP2pBssInfo); + +#if CFG_SUPPORT_DBDC + kalMemZero(&rDbdcCap, sizeof(struct CNM_DBDC_CAP)); + cnmDbdcEnableDecision(prAdapter, + prP2pBssInfo->ucBssIndex, + prP2pConnReqInfo->rChannelInfo.eBand, + prP2pConnReqInfo->rChannelInfo.ucChannelNum, + prP2pBssInfo->ucWmmQueSet + ); + cnmGetDbdcCapability(prAdapter, + prP2pBssInfo->ucBssIndex, + prP2pConnReqInfo->rChannelInfo.eBand, + prP2pConnReqInfo->rChannelInfo.ucChannelNum, + prAdapter->rWifiVar.ucNSS, + &rDbdcCap); + + DBGLOG(P2P, INFO, + "p2pRoleFsmRunEventDfsCac: Set channel at CH %u.\n", + prP2pConnReqInfo->rChannelInfo.ucChannelNum); + + prP2pBssInfo->ucNss = rDbdcCap.ucNss; +#endif /*CFG_SUPPORT_DBDC*/ + + if (prP2pRoleFsmInfo->eCurrentState != P2P_ROLE_STATE_IDLE) { + /* Make sure the state is in IDLE state. */ + p2pRoleFsmRunEventAbort(prAdapter, prP2pRoleFsmInfo); + } + + /* Leave IDLE state. */ + SET_NET_PWR_STATE_ACTIVE(prAdapter, prP2pBssInfo->ucBssIndex); + + prP2pBssInfo->eIntendOPMode = OP_MODE_ACCESS_POINT; + prP2pBssInfo->fgIsDfsActive = TRUE; + + if (prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.ucChannelNum != 0) { + DBGLOG(P2P, INFO, "Role(%d) Set channel at CH(%d)\n", + prP2pDfsCacMsg->ucRoleIdx, + prP2pRoleFsmInfo->rConnReqInfo + .rChannelInfo.ucChannelNum); + + p2pRoleStatePrepare_To_DFS_CAC_STATE(prAdapter, + GET_BSS_INFO_BY_INDEX(prAdapter, + prP2pRoleFsmInfo->ucBssIndex), + rChannelWidth, + &(prP2pRoleFsmInfo->rConnReqInfo), + &(prP2pRoleFsmInfo->rChnlReqInfo)); + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_DFS_CAC); + } else { + DBGLOG(P2P, ERROR, + "prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.ucChannelNum shouldn't be 0\n"); + } + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /*p2pRoleFsmRunEventDfsCac*/ + +void p2pRoleFsmRunEventRadarDet(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct MSG_P2P_RADAR_DETECT *prMsgP2pRddDetMsg; + + + DBGLOG(P2P, INFO, "p2pRoleFsmRunEventRadarDet\n"); + + prMsgP2pRddDetMsg = (struct MSG_P2P_RADAR_DETECT *) prMsgHdr; + + prP2pBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, + prMsgP2pRddDetMsg->ucBssIndex); + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData); + + DBGLOG(P2P, INFO, + "p2pRoleFsmRunEventRadarDet with Role(%d)\n", + prP2pRoleFsmInfo->ucRoleIndex); + + if (prP2pRoleFsmInfo->eCurrentState != P2P_ROLE_STATE_DFS_CAC && + prP2pRoleFsmInfo->eCurrentState != P2P_ROLE_STATE_IDLE) { + DBGLOG(P2P, ERROR, + "Wrong prP2pRoleFsmInfo->eCurrentState \"%s\"!", + (prP2pRoleFsmInfo->eCurrentState < P2P_ROLE_STATE_NUM + ? (const char *) + apucDebugP2pRoleState[prP2pRoleFsmInfo->eCurrentState] + : "")); + goto error; + } + + if (p2pFuncGetRadarDetectMode()) { + DBGLOG(P2P, INFO, + "p2pRoleFsmRunEventRadarDet: Ignore radar event\n"); + if (prP2pRoleFsmInfo->eCurrentState == P2P_ROLE_STATE_DFS_CAC) + p2pFuncSetDfsState(DFS_STATE_CHECKING); + else + p2pFuncSetDfsState(DFS_STATE_ACTIVE); + } else { + if (prP2pRoleFsmInfo->eCurrentState == P2P_ROLE_STATE_DFS_CAC) + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_IDLE); + + kalP2PRddDetectUpdate(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex); + cnmTimerStartTimer(prAdapter, + &(prP2pRoleFsmInfo->rDfsShutDownTimer), + 5000); + } + + p2pFuncShowRadarInfo(prAdapter, prMsgP2pRddDetMsg->ucBssIndex); + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /*p2pRoleFsmRunEventRadarDet*/ + +void p2pRoleFsmRunEventSetNewChannel(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct MSG_P2P_SET_NEW_CHANNEL *prMsgP2pSetNewChannelMsg; + + + DBGLOG(P2P, INFO, "p2pRoleFsmRunEventSetNewChannel\n"); + + prMsgP2pSetNewChannelMsg = (struct MSG_P2P_SET_NEW_CHANNEL *) prMsgHdr; + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prMsgP2pSetNewChannelMsg->ucBssIndex); + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prMsgP2pSetNewChannelMsg->ucRoleIdx); + + prP2pRoleFsmInfo->rChnlReqInfo.ucReqChnlNum = + prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.ucChannelNum; + prP2pRoleFsmInfo->rChnlReqInfo.eBand = + prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.eBand; + prP2pRoleFsmInfo->rChnlReqInfo.eChannelWidth = + prMsgP2pSetNewChannelMsg->eChannelWidth; + prP2pBssInfo->ucPrimaryChannel = + prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.ucChannelNum; + + prP2pRoleFsmInfo->rChnlReqInfo.ucCenterFreqS1 = + nicGetVhtS1(prP2pBssInfo->ucPrimaryChannel, + prP2pRoleFsmInfo->rChnlReqInfo.eChannelWidth); + + prP2pRoleFsmInfo->rChnlReqInfo.ucCenterFreqS2 = 0; + + cnmMemFree(prAdapter, prMsgHdr); +} /*p2pRoleFsmRunEventCsaDone*/ + +void p2pRoleFsmRunEventCsaDone(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct MSG_P2P_CSA_DONE *prMsgP2pCsaDoneMsg; + + + DBGLOG(P2P, INFO, "p2pRoleFsmRunEventCsaDone\n"); + + prMsgP2pCsaDoneMsg = (struct MSG_P2P_CSA_DONE *) prMsgHdr; + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prMsgP2pCsaDoneMsg->ucBssIndex); + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData); + + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_SWITCH_CHANNEL); + + cnmMemFree(prAdapter, prMsgHdr); +} /*p2pRoleFsmRunEventCsaDone*/ + +void p2pRoleFsmRunEventDfsShutDownTimeout(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) ulParamPtr; + + DBGLOG(P2P, INFO, + "p2pRoleFsmRunEventDfsShutDownTimeout: DFS shut down.\n"); + + p2pFuncSetDfsState(DFS_STATE_INACTIVE); + p2pFuncStopRdd(prAdapter, prP2pRoleFsmInfo->ucBssIndex); + +} /* p2pRoleFsmRunEventDfsShutDownTimeout */ + +#endif + +void +p2pRoleFsmScanTargetBss(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN uint8_t ucChannelNum, + IN struct P2P_SSID_STRUCT *prSsid) +{ + /* Update scan parameter... to scan target device. */ + struct P2P_SCAN_REQ_INFO *prScanReqInfo = + &(prP2pRoleFsmInfo->rScanReqInfo); + + prScanReqInfo->ucNumChannelList = 1; + prScanReqInfo->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prScanReqInfo->eChannelSet = SCAN_CHANNEL_SPECIFIED; + prScanReqInfo->arScanChannelList[0].ucChannelNum = ucChannelNum; + prScanReqInfo->ucSsidNum = 1; + kalMemCopy(&(prScanReqInfo->arSsidStruct[0]), prSsid, + sizeof(struct P2P_SSID_STRUCT)); + /* Prevent other P2P ID in IE. */ + prScanReqInfo->u4BufLength = 0; + prScanReqInfo->fgIsAbort = TRUE; + + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_SCAN); +} + +void p2pRoleFsmRunEventConnectionRequest(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct MSG_P2P_CONNECTION_REQUEST *prP2pConnReqMsg = + (struct MSG_P2P_CONNECTION_REQUEST *) NULL; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + + struct P2P_CONNECTION_REQ_INFO *prConnReqInfo = + (struct P2P_CONNECTION_REQ_INFO *) NULL; + struct P2P_CHNL_REQ_INFO *prChnlReqInfo = + (struct P2P_CHNL_REQ_INFO *) NULL; + struct P2P_JOIN_INFO *prJoinInfo = (struct P2P_JOIN_INFO *) NULL; +#if CFG_SUPPORT_DBDC + struct CNM_DBDC_CAP rDbdcCap; +#endif /*CFG_SUPPORT_DBDC*/ + uint8_t ucRfBw; + + prP2pConnReqMsg = (struct MSG_P2P_CONNECTION_REQUEST *) prMsgHdr; + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pConnReqMsg->ucRoleIdx); + + prAdapter->prP2pInfo->eConnState = P2P_CNN_NORMAL; + + + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, ERROR, + "Corresponding P2P Role FSM empty: %d.\n", + prP2pConnReqMsg->ucRoleIdx); + goto error; + } + + prP2pBssInfo = prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex]; + + if (!prP2pBssInfo) { + DBGLOG(P2P, ERROR, + "prP2pRoleFsmInfo->ucBssIndex %d of prAdapter->aprBssInfo is NULL!\n", + prP2pRoleFsmInfo->ucBssIndex); + goto error; + } + + prConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + prChnlReqInfo = &(prP2pRoleFsmInfo->rChnlReqInfo); + prJoinInfo = &(prP2pRoleFsmInfo->rJoinInfo); + + DBGLOG(P2P, TRACE, "p2pFsmRunEventConnectionRequest\n"); + + if (prP2pBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + goto error; + + SET_NET_PWR_STATE_ACTIVE(prAdapter, prP2pBssInfo->ucBssIndex); + + /* In P2P GC case, the interval of + * two ASSOC flow could be very short, + * we must start to connect directly before Deauth done + */ + prStaRec = prP2pBssInfo->prStaRecOfAP; + if (prStaRec) { + if (timerPendingTimer(&prStaRec->rDeauthTxDoneTimer)) { + cnmTimerStopTimer(prAdapter, + &(prStaRec->rDeauthTxDoneTimer)); + /* Force to stop */ + p2pRoleFsmDeauhComplete(prAdapter, prStaRec); + } + } + /* Make sure the state is in IDLE state. */ + if (prP2pRoleFsmInfo->eCurrentState != P2P_ROLE_STATE_IDLE) + p2pRoleFsmRunEventAbort(prAdapter, prP2pRoleFsmInfo); + /* Update connection request information. */ + prConnReqInfo->eConnRequest = P2P_CONNECTION_TYPE_GC; + COPY_MAC_ADDR(prConnReqInfo->aucBssid, + prP2pConnReqMsg->aucBssid); + COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, + prP2pConnReqMsg->aucSrcMacAddr); + kalMemCopy(&(prConnReqInfo->rSsidStruct), + &(prP2pConnReqMsg->rSsid), + sizeof(struct P2P_SSID_STRUCT)); + kalMemCopy(prConnReqInfo->aucIEBuf, + prP2pConnReqMsg->aucIEBuf, + prP2pConnReqMsg->u4IELen); + prConnReqInfo->u4BufLength = prP2pConnReqMsg->u4IELen; + + /* Find BSS Descriptor first. */ + prJoinInfo->prTargetBssDesc = + scanP2pSearchDesc(prAdapter, prConnReqInfo); + + if (prJoinInfo->prTargetBssDesc == NULL) { + p2pRoleFsmScanTargetBss(prAdapter, + prP2pRoleFsmInfo, + prP2pConnReqMsg->rChannelInfo.ucChannelNum, + &(prP2pConnReqMsg->rSsid)); + } else { + prChnlReqInfo->u8Cookie = 0; + prChnlReqInfo->ucReqChnlNum = + prP2pConnReqMsg->rChannelInfo.ucChannelNum; + prChnlReqInfo->eBand = prP2pConnReqMsg->rChannelInfo.eBand; + prChnlReqInfo->eChnlSco = prP2pConnReqMsg->eChnlSco; + prChnlReqInfo->u4MaxInterval = AIS_JOIN_CH_REQUEST_INTERVAL; + prChnlReqInfo->eChnlReqType = CH_REQ_TYPE_JOIN; + + rlmReviseMaxBw(prAdapter, + prP2pBssInfo->ucBssIndex, + &prChnlReqInfo->eChnlSco, + (enum ENUM_CHANNEL_WIDTH *) + &prChnlReqInfo->eChannelWidth, + &prChnlReqInfo->ucCenterFreqS1, + &prChnlReqInfo->ucReqChnlNum); + + prP2pBssInfo->eBand = prChnlReqInfo->eBand; + if (prP2pBssInfo->fgIsWmmInited == FALSE) + prP2pBssInfo->ucWmmQueSet = + cnmWmmIndexDecision(prAdapter, prP2pBssInfo); + +#if CFG_SUPPORT_DBDC + kalMemZero(&rDbdcCap, sizeof(struct CNM_DBDC_CAP)); + cnmDbdcEnableDecision(prAdapter, + prP2pBssInfo->ucBssIndex, + prChnlReqInfo->eBand, + prChnlReqInfo->ucReqChnlNum, + prP2pBssInfo->ucWmmQueSet); + cnmGetDbdcCapability(prAdapter, + prP2pBssInfo->ucBssIndex, + prChnlReqInfo->eBand, + prChnlReqInfo->ucReqChnlNum, + wlanGetSupportNss(prAdapter, prP2pBssInfo->ucBssIndex), + &rDbdcCap); + + DBGLOG(P2P, INFO, + "p2pRoleFsmRunEventConnectionRequest: start GC at CH %u, NSS=%u.\n", + prChnlReqInfo->ucReqChnlNum, + rDbdcCap.ucNss); + + prP2pBssInfo->ucNss = rDbdcCap.ucNss; + +#endif + + /* Decide RF BW by own OP and Peer OP BW */ + ucRfBw = cnmGetDbdcBwCapability(prAdapter, + prP2pBssInfo->ucBssIndex); + /* Revise to VHT OP BW */ + ucRfBw = rlmGetVhtOpBwByBssOpBw(ucRfBw); + if (ucRfBw > prJoinInfo->prTargetBssDesc->eChannelWidth) + ucRfBw = prJoinInfo->prTargetBssDesc->eChannelWidth; + + prChnlReqInfo->eChannelWidth = ucRfBw; + /* TODO: BW80+80 support */ + prChnlReqInfo->ucCenterFreqS1 = + nicGetVhtS1(prChnlReqInfo->ucReqChnlNum, + prChnlReqInfo->eChannelWidth); + prChnlReqInfo->ucCenterFreqS2 = 0; + + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_REQING_CHANNEL); + } + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pRoleFsmRunEventConnectionRequest */ + +void p2pRoleFsmRunEventConnectionAbort(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct MSG_P2P_CONNECTION_ABORT *prDisconnMsg = + (struct MSG_P2P_CONNECTION_ABORT *) NULL; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + + + prDisconnMsg = (struct MSG_P2P_CONNECTION_ABORT *) prMsgHdr; + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prDisconnMsg->ucRoleIdx); + + DBGLOG(P2P, TRACE, + "p2pFsmRunEventConnectionAbort: Connection Abort.\n"); + + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, ERROR, + "p2pRoleFsmRunEventConnectionAbort: Corresponding P2P Role FSM empty: %d.\n", + prDisconnMsg->ucRoleIdx); + goto error; + } + + prP2pBssInfo = prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex]; + + if (!prP2pBssInfo) { + DBGLOG(P2P, ERROR, + "prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex(%d)] is NULL!", + prP2pRoleFsmInfo->ucBssIndex); + goto error; + } + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_INFRASTRUCTURE: + { + uint8_t 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; + } + +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, + NULL, NULL, 0, 0, + WLAN_STATUS_MEDIA_DISCONNECT); +#else + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, + NULL, NULL, 0, 0); +#endif + + prStaRec = prP2pBssInfo->prStaRecOfAP; + + /* Stop rejoin timer if it is started. */ + /* TODO: If it has. */ + + p2pFuncDisconnect(prAdapter, prP2pBssInfo, + prStaRec, + prDisconnMsg->fgSendDeauth, + prDisconnMsg->u2ReasonCode); + + cnmTimerStopTimer(prAdapter, + &(prStaRec->rDeauthTxDoneTimer)); + + cnmTimerInitTimer(prAdapter, + &(prStaRec->rDeauthTxDoneTimer), + (PFN_MGMT_TIMEOUT_FUNC) p2pRoleFsmDeauthTimeout, + (unsigned long) prStaRec); + + cnmTimerStartTimer(prAdapter, + &(prStaRec->rDeauthTxDoneTimer), + P2P_DEAUTH_TIMEOUT_TIME_MS); + + SET_NET_PWR_STATE_IDLE(prAdapter, + prP2pBssInfo->ucBssIndex); + + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_IDLE); + } + break; + case OP_MODE_ACCESS_POINT: + { + /* Search specific client device, and disconnect. */ + /* 1. Send deauthentication frame. */ + /* 2. Indication: Device disconnect. */ + struct STA_RECORD *prCurrStaRec = + (struct STA_RECORD *) NULL; + + DBGLOG(P2P, TRACE, + "Disconnecting with Target ID: " MACSTR "\n", + MAC2STR(prDisconnMsg->aucTargetID)); + + prCurrStaRec = bssGetClientByMac(prAdapter, + prP2pBssInfo, + prDisconnMsg->aucTargetID); + + if (prCurrStaRec) { + DBGLOG(P2P, TRACE, + "Disconnecting: " MACSTR "\n", + MAC2STR(prCurrStaRec->aucMacAddr)); + + if (!prDisconnMsg->fgSendDeauth) { + p2pRoleFsmDeauhComplete(prAdapter, + prCurrStaRec); + break; + } + + /* Glue layer indication. */ + /* kalP2PGOStationUpdate(prAdapter->prGlueInfo, + * prCurrStaRec, FALSE); + */ + + /* Send deauth & do indication. */ + p2pFuncDisconnect(prAdapter, + prP2pBssInfo, + prCurrStaRec, + prDisconnMsg->fgSendDeauth, + prDisconnMsg->u2ReasonCode); + + cnmTimerStopTimer(prAdapter, + &(prCurrStaRec->rDeauthTxDoneTimer)); + + cnmTimerInitTimer(prAdapter, + &(prCurrStaRec->rDeauthTxDoneTimer), + (PFN_MGMT_TIMEOUT_FUNC) + p2pRoleFsmDeauthTimeout, + (unsigned long) prCurrStaRec); + + cnmTimerStartTimer(prAdapter, + &(prCurrStaRec->rDeauthTxDoneTimer), + P2P_DEAUTH_TIMEOUT_TIME_MS); + } +#if 0 + LINK_FOR_EACH(prLinkEntry, prStaRecOfClientList) { + prCurrStaRec = LINK_ENTRY(prLinkEntry, + struct STA_RECORD, 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, + prP2pBssInfo, + prCurrStaRec, + prDisconnMsg->fgSendDeauth, + prDisconnMsg->u2ReasonCode); + + /* prTargetStaRec = prCurrStaRec; */ + + break; + } + } +#endif + + } + break; + case OP_MODE_P2P_DEVICE: + default: + ASSERT(FALSE); + break; + } + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pRoleFsmRunEventConnectionAbort */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is called when JOIN complete message event + * is received from SAA. + * + * \param[in] prAdapter Pointer of ADAPTER_T + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void p2pRoleFsmRunEventJoinComplete(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct P2P_JOIN_INFO *prJoinInfo = + (struct P2P_JOIN_INFO *) NULL; + struct MSG_SAA_FSM_COMP *prJoinCompMsg = + (struct MSG_SAA_FSM_COMP *) NULL; + struct SW_RFB *prAssocRspSwRfb = (struct SW_RFB *) NULL; + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + + prJoinCompMsg = (struct MSG_SAA_FSM_COMP *) prMsgHdr; + prStaRec = prJoinCompMsg->prStaRec; + prAssocRspSwRfb = prJoinCompMsg->prSwRfb; + + ASSERT(prStaRec); + if (!prStaRec) { + DBGLOG(P2P, ERROR, "prJoinCompMsg->prStaRec is NULL!\n"); + goto error; + } + + DBGLOG(P2P, INFO, + "P2P BSS %d [" MACSTR "], Join Complete, status: %d\n", + prStaRec->ucBssIndex, + MAC2STR(prStaRec->aucMacAddr), + prJoinCompMsg->rJoinStatus); + + ASSERT(prStaRec->ucBssIndex < prAdapter->ucP2PDevBssIdx); + if (!(prStaRec->ucBssIndex < prAdapter->ucP2PDevBssIdx)) { + DBGLOG(P2P, ERROR, + "prStaRec->ucBssIndex %d should < prAdapter->ucP2PDevBssIdx(%d)!\n", + prStaRec->ucBssIndex, prAdapter->ucP2PDevBssIdx); + goto error; + } + + prP2pBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + ASSERT(prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE); + if (prP2pBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) { + DBGLOG(P2P, ERROR, + "prP2pBssInfo->eCurrentOPMode %d != OP_MODE_INFRASTRUCTURE(%d)!\n", + prP2pBssInfo->eCurrentOPMode, + OP_MODE_INFRASTRUCTURE); + goto error; + } + + ASSERT(prP2pBssInfo->u4PrivateData < BSS_P2P_NUM); + if (!(prP2pBssInfo->u4PrivateData < BSS_P2P_NUM)) { + DBGLOG(P2P, ERROR, + "prP2pBssInfo->u4PrivateData %d should < BSS_P2P_NUM(%d)!\n", + prP2pBssInfo->u4PrivateData, + BSS_P2P_NUM); + goto error; + } + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData); + + prJoinInfo = &(prP2pRoleFsmInfo->rJoinInfo); + + /* 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, + prP2pBssInfo, + 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); + + prP2pBssInfo->prStaRecOfAP = NULL; + } + /* 4 <1.3> Update BSS_INFO_T */ + if (prAssocRspSwRfb) { + p2pFuncUpdateBssInfoForJOIN(prAdapter, + prJoinInfo->prTargetBssDesc, + prStaRec, prP2pBssInfo, prAssocRspSwRfb); + } else { + DBGLOG(P2P, INFO, + "prAssocRspSwRfb is NULL! Skip p2pFuncUpdateBssInfoForJOIN\n"); + } + + /* 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, prP2pBssInfo->ucBssIndex, + (int8_t) (RCPI_TO_dBm(prStaRec->ucRCPI)), 0); +#endif + + /* 4 <1.6> Indicate Connected Event to + * Host immediately. + * Require BSSID, Association ID, Beacon Interval.. + * from AIS_BSS_INFO_T + * p2pIndicationOfMediaStateToHost(prAdapter, + * PARAM_MEDIA_STATE_CONNECTED, + * prStaRec->aucMacAddr); + */ + if (prJoinInfo->prTargetBssDesc) + scanReportBss2Cfg80211(prAdapter, + BSS_TYPE_P2P_DEVICE, + prJoinInfo->prTargetBssDesc); +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, + &prP2pRoleFsmInfo->rConnReqInfo, + prJoinInfo->aucIEBuf, + prJoinInfo->u4BufLength, + prStaRec->u2StatusCode, + WLAN_STATUS_MEDIA_DISCONNECT); +#else + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, + &prP2pRoleFsmInfo->rConnReqInfo, + prJoinInfo->aucIEBuf, + prJoinInfo->u4BufLength, + prStaRec->u2StatusCode); + +#endif + + + + } else { + /* Join Fail */ + /* 4 <2.1> Redo JOIN process + * with other Auth Type if possible + */ + if (p2pFuncRetryJOIN(prAdapter, + prStaRec, prJoinInfo) == FALSE) { + + struct BSS_DESC *prBssDesc; + + /* Increase Failure Count */ + prStaRec->ucJoinFailureCount++; + + prBssDesc = prJoinInfo->prTargetBssDesc; + + ASSERT(prBssDesc); + ASSERT(prBssDesc->fgIsConnecting); + + prBssDesc->fgIsConnecting = FALSE; + + if (prStaRec->ucJoinFailureCount >= + P2P_SAA_RETRY_COUNT) { +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) + kalP2PGCIndicateConnectionStatus( + prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, + &prP2pRoleFsmInfo->rConnReqInfo, + prJoinInfo->aucIEBuf, + prJoinInfo->u4BufLength, + prStaRec->u2StatusCode, + WLAN_STATUS_MEDIA_DISCONNECT); +#else + kalP2PGCIndicateConnectionStatus( + prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, + &prP2pRoleFsmInfo->rConnReqInfo, + prJoinInfo->aucIEBuf, + prJoinInfo->u4BufLength, + prStaRec->u2StatusCode); +#endif + } + + } + + } + } + + if (prP2pRoleFsmInfo->eCurrentState == P2P_ROLE_STATE_GC_JOIN) { + if (prP2pBssInfo->eConnectionState == + PARAM_MEDIA_STATE_CONNECTED) { + /* do nothing & wait for timeout or EAPOL 4/4 TX done */ + } else { + struct BSS_DESC *prBssDesc; + struct P2P_SSID_STRUCT rSsid; + + prBssDesc = prJoinInfo->prTargetBssDesc; + + COPY_SSID(rSsid.aucSsid, + rSsid.ucSsidLen, + prBssDesc->aucSSID, + prBssDesc->ucSSIDLen); + p2pRoleFsmScanTargetBss(prAdapter, + prP2pRoleFsmInfo, + prBssDesc->ucChannelNum, + &rSsid); + } + } + +error: + if (prAssocRspSwRfb) + nicRxReturnRFB(prAdapter, prAssocRspSwRfb); + + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pRoleFsmRunEventJoinComplete */ + +void p2pRoleFsmRunEventScanRequest(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_P2P_SCAN_REQUEST *prP2pScanReqMsg = + (struct MSG_P2P_SCAN_REQUEST *) NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct P2P_SCAN_REQ_INFO *prScanReqInfo = + (struct P2P_SCAN_REQ_INFO *) NULL; + uint32_t u4ChnlListSize = 0; + struct P2P_SSID_STRUCT *prP2pSsidStruct = + (struct P2P_SSID_STRUCT *) NULL; + struct BSS_INFO *prP2pBssInfo = NULL; + + + prP2pScanReqMsg = (struct MSG_P2P_SCAN_REQUEST *) prMsgHdr; + + prP2pBssInfo = prAdapter->aprBssInfo[prP2pScanReqMsg->ucBssIdx]; + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData); + + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, ERROR, "prP2pRoleFsmInfo is NULL!"); + goto error; + } + + prP2pScanReqMsg = (struct MSG_P2P_SCAN_REQUEST *) prMsgHdr; + prScanReqInfo = &(prP2pRoleFsmInfo->rScanReqInfo); + + DBGLOG(P2P, TRACE, "p2pDevFsmRunEventScanRequest\n"); + + /* Do we need to be in IDLE state? */ + /* p2pDevFsmRunEventAbort(prAdapter, prP2pDevFsmInfo); */ + + ASSERT(prScanReqInfo->fgIsScanRequest == FALSE); + + prScanReqInfo->fgIsAbort = TRUE; + prScanReqInfo->eScanType = prP2pScanReqMsg->eScanType; + + if (prP2pScanReqMsg->u4NumChannel) { + 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(struct RF_CHANNEL_INFO) + * prScanReqInfo->ucNumChannelList; + kalMemCopy(prScanReqInfo->arScanChannelList, + prP2pScanReqMsg->arChannelListInfo, u4ChnlListSize); + } else { + /* If channel number is ZERO. + * It means do a FULL channel scan. + */ + prScanReqInfo->eChannelSet = SCAN_CHANNEL_FULL; + } + + /* SSID */ + prP2pSsidStruct = prP2pScanReqMsg->prSSID; + for (prScanReqInfo->ucSsidNum = 0; + prScanReqInfo->ucSsidNum < prP2pScanReqMsg->i4SsidNum; + prScanReqInfo->ucSsidNum++) { + + kalMemCopy( + prScanReqInfo->arSsidStruct[prScanReqInfo->ucSsidNum] + .aucSsid, + prP2pSsidStruct->aucSsid, prP2pSsidStruct->ucSsidLen); + + prScanReqInfo->arSsidStruct[prScanReqInfo->ucSsidNum] + .ucSsidLen = + prP2pSsidStruct->ucSsidLen; + + prP2pSsidStruct++; + } + + /* IE Buffer */ + kalMemCopy(prScanReqInfo->aucIEBuf, + prP2pScanReqMsg->pucIEBuf, + prP2pScanReqMsg->u4IELen); + + prScanReqInfo->u4BufLength = prP2pScanReqMsg->u4IELen; + + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_SCAN); + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventScanRequest */ + +void +p2pRoleFsmRunEventScanDone(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo) +{ + struct MSG_SCN_SCAN_DONE *prScanDoneMsg = + (struct MSG_SCN_SCAN_DONE *) prMsgHdr; + struct P2P_SCAN_REQ_INFO *prScanReqInfo = + (struct P2P_SCAN_REQ_INFO *) NULL; + enum ENUM_P2P_ROLE_STATE eNextState = P2P_ROLE_STATE_NUM; + struct P2P_CONNECTION_REQ_INFO *prConnReqInfo = + &(prP2pRoleFsmInfo->rConnReqInfo); + struct P2P_JOIN_INFO *prP2pJoinInfo = + &(prP2pRoleFsmInfo->rJoinInfo); + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct P2P_CHNL_REQ_INFO *prChnlReqInfo = + (struct P2P_CHNL_REQ_INFO *) NULL; +#if CFG_SUPPORT_DBDC + struct CNM_DBDC_CAP rDbdcCap; +#endif /*CFG_SUPPORT_DBDC*/ + + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, TRACE, "prP2pRoleFsmInfo is NULL\n"); + goto error; + } + + DBGLOG(P2P, TRACE, "P2P Role Scan Done Event\n"); + + prScanReqInfo = &(prP2pRoleFsmInfo->rScanReqInfo); + prScanDoneMsg = (struct 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 Role Scan Don SeqNum Received:%d <-> P2P Role Fsm SCAN Seq Issued:%d\n", + prScanDoneMsg->ucSeqNum, + prScanReqInfo->ucSeqNumOfScnMsg); + + goto error; + } + + switch (prP2pRoleFsmInfo->eCurrentState) { + case P2P_ROLE_STATE_SCAN: + prScanReqInfo->fgIsAbort = FALSE; + + if (prConnReqInfo->eConnRequest == P2P_CONNECTION_TYPE_GC) { + + prP2pJoinInfo->prTargetBssDesc = + p2pFuncKeepOnConnection(prAdapter, + prAdapter->aprBssInfo + [prP2pRoleFsmInfo->ucBssIndex], + prConnReqInfo, + &prP2pRoleFsmInfo->rChnlReqInfo, + &prP2pRoleFsmInfo->rScanReqInfo); + if ((prP2pJoinInfo->prTargetBssDesc) == NULL) { + eNextState = P2P_ROLE_STATE_SCAN; + } else { + prP2pBssInfo = + prAdapter->aprBssInfo + [prP2pRoleFsmInfo->ucBssIndex]; + if (!prP2pBssInfo) + break; + prChnlReqInfo = + &(prP2pRoleFsmInfo->rChnlReqInfo); + if (!prChnlReqInfo) + break; + + prP2pBssInfo->eBand = prChnlReqInfo->eBand; + if (prP2pBssInfo->fgIsWmmInited == FALSE) + prP2pBssInfo->ucWmmQueSet = + cnmWmmIndexDecision(prAdapter, + prP2pBssInfo); +#if CFG_SUPPORT_DBDC + kalMemZero(&rDbdcCap, + sizeof(struct CNM_DBDC_CAP)); + cnmDbdcEnableDecision(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + prChnlReqInfo->eBand, + prChnlReqInfo->ucReqChnlNum, + prP2pBssInfo->ucWmmQueSet); + cnmGetDbdcCapability(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + prChnlReqInfo->eBand, + prChnlReqInfo->ucReqChnlNum, + wlanGetSupportNss(prAdapter, + prP2pRoleFsmInfo->ucBssIndex), + &rDbdcCap); + + DBGLOG(P2P, INFO, + "p2pRoleFsmRunEventScanDone: start GC at CH %u, NSS=%u.\n", + prChnlReqInfo->ucReqChnlNum, + rDbdcCap.ucNss); + + + prP2pBssInfo->ucNss = rDbdcCap.ucNss; +#endif + /* For GC join. */ + eNextState = P2P_ROLE_STATE_REQING_CHANNEL; + } + } else { + eNextState = P2P_ROLE_STATE_IDLE; + } + break; + case P2P_ROLE_STATE_AP_CHNL_DETECTION: + eNextState = P2P_ROLE_STATE_REQING_CHANNEL; + break; + default: + /* Unexpected channel scan done event + * without being chanceled. + */ + ASSERT(FALSE); + break; + } + + prScanReqInfo->fgIsScanRequest = FALSE; + + p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, eNextState); + +error: + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pRoleFsmRunEventScanDone */ + +void +p2pRoleFsmRunEventChnlGrant(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo) +{ + struct P2P_CHNL_REQ_INFO *prChnlReqInfo = + (struct P2P_CHNL_REQ_INFO *) NULL; + struct MSG_CH_GRANT *prMsgChGrant = (struct MSG_CH_GRANT *) NULL; +#if (CFG_SUPPORT_DFS_MASTER == 1) + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + uint32_t u4CacTimeMs; +#endif + uint8_t ucTokenID = 0; + + + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, ERROR, "prP2pRoleFsmInfo is NULL!\n"); + goto error; + } + + DBGLOG(P2P, TRACE, "P2P Run Event Role Channel Grant\n"); + + prMsgChGrant = (struct MSG_CH_GRANT *) prMsgHdr; + ucTokenID = prMsgChGrant->ucTokenID; + prChnlReqInfo = &(prP2pRoleFsmInfo->rChnlReqInfo); + +#if (CFG_SUPPORT_DFS_MASTER == 1) + prP2pBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, + prMsgChGrant->ucBssIndex); +#endif + if (prChnlReqInfo->u4MaxInterval != prMsgChGrant->u4GrantInterval) { + DBGLOG(P2P, WARN, + "P2P Role:%d Request Channel Interval:%d, Grant Interval:%d\n", + prP2pRoleFsmInfo->ucRoleIndex, + prChnlReqInfo->u4MaxInterval, + prMsgChGrant->u4GrantInterval); + prChnlReqInfo->u4MaxInterval = prMsgChGrant->u4GrantInterval; + } + + if (ucTokenID == prChnlReqInfo->ucSeqNumOfChReq) { + enum ENUM_P2P_ROLE_STATE eNextState = P2P_ROLE_STATE_NUM; + + switch (prP2pRoleFsmInfo->eCurrentState) { + case P2P_ROLE_STATE_REQING_CHANNEL: + switch (prChnlReqInfo->eChnlReqType) { + case CH_REQ_TYPE_JOIN: + eNextState = P2P_ROLE_STATE_GC_JOIN; + break; + case CH_REQ_TYPE_GO_START_BSS: + eNextState = P2P_ROLE_STATE_IDLE; + break; + default: + DBGLOG(P2P, WARN, + "p2pRoleFsmRunEventChnlGrant: Invalid Channel Request Type:%d\n", + prChnlReqInfo->eChnlReqType); + ASSERT(FALSE); + break; + } + + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, eNextState); + break; + +#if (CFG_SUPPORT_DFS_MASTER == 1) + case P2P_ROLE_STATE_DFS_CAC: + p2pFuncStartRdd(prAdapter, prMsgChGrant->ucBssIndex); + + if (p2pFuncCheckWeatherRadarBand(prChnlReqInfo)) + u4CacTimeMs = + P2P_AP_CAC_WEATHER_CHNL_HOLD_TIME_MS; + else + u4CacTimeMs = + prP2pRoleFsmInfo->rChnlReqInfo + .u4MaxInterval; + + if (p2pFuncIsManualCac()) + u4CacTimeMs = p2pFuncGetDriverCacTime() * 1000; + else + p2pFuncSetDriverCacTime(u4CacTimeMs/1000); + + cnmTimerStartTimer(prAdapter, + &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer), + u4CacTimeMs); + + p2pFuncRecordCacStartBootTime(); + + p2pFuncSetDfsState(DFS_STATE_CHECKING); + + DBGLOG(P2P, INFO, + "p2pRoleFsmRunEventChnlGrant: CAC time = %ds\n", + u4CacTimeMs/1000); + break; + case P2P_ROLE_STATE_SWITCH_CHANNEL: + p2pFuncDfsSwitchCh(prAdapter, + prP2pBssInfo, + prP2pRoleFsmInfo->rChnlReqInfo); + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_IDLE); + prAdapter->fgIsChSwitchDone = TRUE; + break; +#endif + default: + /* Channel is granted under unexpected state. + * Driver should cancel channel privileagea + * before leaving the states. + */ + if (IS_BSS_ACTIVE( + prAdapter->aprBssInfo + [prP2pRoleFsmInfo->ucBssIndex])) { + DBGLOG(P2P, WARN, + "p2pRoleFsmRunEventChnlGrant: Invalid CurrentState:%d\n", + prP2pRoleFsmInfo->eCurrentState); + ASSERT(FALSE); + } + break; + } + } else { + /* Channel requsted, but released. */ + ASSERT(!prChnlReqInfo->fgIsChannelRequested); + if (prChnlReqInfo->fgIsChannelRequested) + DBGLOG(P2P, ERROR, + "Channel was requested, but released!\n"); + } + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pRoleFsmRunEventChnlGrant */ + +/* ////////////////////////////////////// */ +void p2pRoleFsmRunEventDissolve(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + /* TODO: */ + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pRoleFsmRunEventDissolve */ + +/*----------------------------------------------------------------------------*/ +/*! + * @ This routine update the current MAC table based on the current ACL. + * If ACL change causing an associated STA become un-authorized. This STA + * will be kicked out immediately. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] ucBssIdx Bss index. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void p2pRoleUpdateACLEntry(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIdx) +{ + u_int8_t bMatchACL = FALSE; + int32_t i = 0; + struct LINK *prClientList; + struct STA_RECORD *prCurrStaRec, *prNextStaRec; + struct BSS_INFO *prP2pBssInfo; + + ASSERT(prAdapter); + + if ((!prAdapter) || (ucBssIdx > prAdapter->ucHwBssIdNum)) + return; + + DBGLOG(P2P, TRACE, "Update ACL Entry ucBssIdx = %d\n", ucBssIdx); + prP2pBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + /* ACL is disabled. Do nothing about the MAC table. */ + if (prP2pBssInfo->rACL.ePolicy == PARAM_CUSTOM_ACL_POLICY_DISABLE) + return; + + prClientList = &prP2pBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH_ENTRY_SAFE(prCurrStaRec, + prNextStaRec, prClientList, rLinkEntry, struct STA_RECORD) { + bMatchACL = FALSE; + for (i = 0; i < prP2pBssInfo->rACL.u4Num; i++) { + if (EQUAL_MAC_ADDR(prCurrStaRec->aucMacAddr, + prP2pBssInfo->rACL.rEntry[i].aucAddr)) { + bMatchACL = TRUE; + break; + } + } + + if (((!bMatchACL) && + (prP2pBssInfo->rACL.ePolicy + == PARAM_CUSTOM_ACL_POLICY_ACCEPT)) + || ((bMatchACL) && + (prP2pBssInfo->rACL.ePolicy + == PARAM_CUSTOM_ACL_POLICY_DENY))) { + struct MSG_P2P_CONNECTION_ABORT *prDisconnectMsg = + (struct MSG_P2P_CONNECTION_ABORT *) NULL; + + DBGLOG(P2P, TRACE, + "ucBssIdx=%d, ACL Policy=%d\n", + ucBssIdx, prP2pBssInfo->rACL.ePolicy); + + prDisconnectMsg = + (struct MSG_P2P_CONNECTION_ABORT *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_P2P_CONNECTION_ABORT)); + if (prDisconnectMsg == NULL) + return; + prDisconnectMsg->rMsgHdr.eMsgId + = MID_MNY_P2P_CONNECTION_ABORT; + prDisconnectMsg->ucRoleIdx + = (uint8_t) prP2pBssInfo->u4PrivateData; + COPY_MAC_ADDR(prDisconnectMsg->aucTargetID, + prCurrStaRec->aucMacAddr); + prDisconnectMsg->u2ReasonCode + = STATUS_CODE_REQ_DECLINED; + prDisconnectMsg->fgSendDeauth = TRUE; + mboxSendMsg(prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prDisconnectMsg, + MSG_SEND_METHOD_BUF); + } + } +} /* p2pRoleUpdateACLEntry */ + +/*----------------------------------------------------------------------------*/ +/*! + * @ Check if the specified STA pass the Access Control List inspection. + * If fails to pass the checking, + * then no authentication or association is allowed. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] pMacAddr Pointer to the mac address. + * @param[in] ucBssIdx Bss index. + * + * @return TRUE - pass ACL inspection, FALSE - ACL inspection fail + */ +/*----------------------------------------------------------------------------*/ +u_int8_t p2pRoleProcessACLInspection(IN struct ADAPTER *prAdapter, + IN uint8_t *pMacAddr, + IN uint8_t ucBssIdx) +{ + u_int8_t bPassACL = TRUE; + int32_t i = 0; + struct BSS_INFO *prP2pBssInfo; + + ASSERT(prAdapter); + + if ((!prAdapter) || (!pMacAddr) || (ucBssIdx > prAdapter->ucHwBssIdNum)) + return FALSE; + + prP2pBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + if (prP2pBssInfo->rACL.ePolicy == PARAM_CUSTOM_ACL_POLICY_DISABLE) + return TRUE; + + if (prP2pBssInfo->rACL.ePolicy == PARAM_CUSTOM_ACL_POLICY_ACCEPT) + bPassACL = FALSE; + else + bPassACL = TRUE; + + for (i = 0; i < prP2pBssInfo->rACL.u4Num; i++) { + if (EQUAL_MAC_ADDR(pMacAddr, + prP2pBssInfo->rACL.rEntry[i].aucAddr)) { + bPassACL = !bPassACL; + break; + } + } + + if (bPassACL == FALSE) + DBGLOG(P2P, WARN, + "this mac [" MACSTR "] is fail to pass ACL inspection.\n", + MAC2STR(pMacAddr)); + + return bPassACL; +} /* p2pRoleProcessACLInspection */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will indicate the Event + * of Successful Completion of AAA Module. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] prStaRec Pointer to the STA_RECORD_T + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +uint32_t +p2pRoleFsmRunEventAAAComplete(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct BSS_INFO *prP2pBssInfo) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + enum ENUM_PARAM_MEDIA_STATE eOriMediaState; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prStaRec != NULL) && (prP2pBssInfo != NULL)); + + eOriMediaState = prP2pBssInfo->eConnectionState; + + bssRemoveClient(prAdapter, prP2pBssInfo, prStaRec); + + if (prP2pBssInfo->rStaRecOfClientList.u4NumElem + >= P2P_MAXIMUM_CLIENT_COUNT + || !p2pRoleProcessACLInspection(prAdapter, + prStaRec->aucMacAddr, + prP2pBssInfo->ucBssIndex) +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + || kalP2PMaxClients(prAdapter->prGlueInfo, + prP2pBssInfo->rStaRecOfClientList.u4NumElem, + (uint8_t) prP2pBssInfo->u4PrivateData) +#endif + ) { + rStatus = WLAN_STATUS_RESOURCES; + break; + } + + bssAddClient(prAdapter, prP2pBssInfo, prStaRec); + + prStaRec->u2AssocId = bssAssignAssocID(prStaRec); + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + p2pChangeMediaState(prAdapter, + prP2pBssInfo, + PARAM_MEDIA_STATE_CONNECTED); + + /* Update Connected state to FW. */ + if (eOriMediaState != prP2pBssInfo->eConnectionState) + nicUpdateBss(prAdapter, prP2pBssInfo->ucBssIndex); + + } while (FALSE); + + return rStatus; +} /* p2pRunEventAAAComplete */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will indicate the Event + * of Successful Completion of AAA Module. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] prStaRec Pointer to the STA_RECORD_T + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +uint32_t +p2pRoleFsmRunEventAAASuccess(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct BSS_INFO *prP2pBssInfo) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prStaRec != NULL) && (prP2pBssInfo != NULL)); + + if ((prP2pBssInfo->eNetworkType != NETWORK_TYPE_P2P) + || (prP2pBssInfo->u4PrivateData >= BSS_P2P_NUM)) { + ASSERT(FALSE); + rStatus = WLAN_STATUS_INVALID_DATA; + break; + } + + ASSERT(prP2pBssInfo->ucBssIndex < prAdapter->ucP2PDevBssIdx); + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData); + + /* Glue layer indication. */ + kalP2PGOStationUpdate(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, prStaRec, TRUE); + + } while (FALSE); + + return rStatus; +} /* p2pRoleFsmRunEventAAASuccess */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will indicate the Event + * of Tx Fail of AAA Module. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] prStaRec Pointer to the STA_RECORD_T + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void p2pRoleFsmRunEventAAATxFail(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct BSS_INFO *prP2pBssInfo) +{ + ASSERT(prAdapter); + ASSERT(prStaRec); + + bssRemoveClient(prAdapter, prP2pBssInfo, prStaRec); + + p2pFuncDisconnect(prAdapter, + prP2pBssInfo, prStaRec, FALSE, + prStaRec->eAuthAssocState == AAA_STATE_SEND_AUTH2 + ? STATUS_CODE_AUTH_TIMEOUT + : STATUS_CODE_ASSOC_TIMEOUT); + + /* 20120830 moved into p2puUncDisconnect. */ + /* cnmStaRecFree(prAdapter, prStaRec); */ +} /* p2pRoleFsmRunEventAAATxFail */ + +void p2pRoleFsmRunEventSwitchOPMode(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct MSG_P2P_SWITCH_OP_MODE *prSwitchOpMode = + (struct MSG_P2P_SWITCH_OP_MODE *) prMsgHdr; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct P2P_CONNECTION_REQ_INFO *prConnReqInfo = + (struct P2P_CONNECTION_REQ_INFO *) NULL; + + ASSERT(prSwitchOpMode->ucRoleIdx < BSS_P2P_NUM); + if (!(prSwitchOpMode->ucRoleIdx < BSS_P2P_NUM)) { + DBGLOG(P2P, ERROR, + "prSwitchOpMode->ucRoleIdx %d should < BSS_P2P_NUM(%d)\n", + prSwitchOpMode->ucRoleIdx, BSS_P2P_NUM); + goto error; + } + + prP2pRoleFsmInfo = + prAdapter->rWifiVar + .aprP2pRoleFsmInfo[prSwitchOpMode->ucRoleIdx]; + prConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + + ASSERT(prP2pRoleFsmInfo->ucBssIndex < prAdapter->ucP2PDevBssIdx); + if (!(prP2pRoleFsmInfo->ucBssIndex < prAdapter->ucP2PDevBssIdx)) { + DBGLOG(P2P, ERROR, + "prP2pRoleFsmInfo->ucBssIndex %d should < prAdapter->ucP2PDevBssIdx(%d)\n", + prP2pRoleFsmInfo->ucBssIndex, + prAdapter->ucP2PDevBssIdx); + goto error; + } + + prP2pBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, + prP2pRoleFsmInfo->ucBssIndex); + + if (!(prSwitchOpMode->eOpMode < OP_MODE_NUM)) { + DBGLOG(P2P, ERROR, + "prSwitchOpMode->eOpMode %d should < OP_MODE_NUM(%d)\n", + prSwitchOpMode->eOpMode, OP_MODE_NUM); + goto error; + } + + /* P2P Device / GC. */ + p2pFuncSwitchOPMode(prAdapter, + prP2pBssInfo, + prSwitchOpMode->eOpMode, + TRUE); + + if (prP2pBssInfo->eIftype == IFTYPE_P2P_CLIENT && + prSwitchOpMode->eIftype == IFTYPE_STATION) { + kalP2pUnlinkBss(prAdapter->prGlueInfo, prConnReqInfo->aucBssid); + } + prP2pBssInfo->eIftype = prSwitchOpMode->eIftype; + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pRoleFsmRunEventSwitchOPMode */ + +/* /////////////////////////////// TO BE REFINE //////////////////////////// */ + +void p2pRoleFsmRunEventBeaconUpdate(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct P2P_ROLE_FSM_INFO *prRoleP2pFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + struct MSG_P2P_BEACON_UPDATE *prBcnUpdateMsg = + (struct MSG_P2P_BEACON_UPDATE *) NULL; + struct P2P_BEACON_UPDATE_INFO *prBcnUpdateInfo = + (struct P2P_BEACON_UPDATE_INFO *) NULL; + + + DBGLOG(P2P, TRACE, "p2pRoleFsmRunEventBeaconUpdate\n"); + + prBcnUpdateMsg = (struct MSG_P2P_BEACON_UPDATE *) prMsgHdr; + if (prBcnUpdateMsg->ucRoleIndex >= BSS_P2P_NUM) + goto error; + + prRoleP2pFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prBcnUpdateMsg->ucRoleIndex); + if (!prRoleP2pFsmInfo) + goto error; + + prP2pBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, + prRoleP2pFsmInfo->ucBssIndex); + + prP2pBssInfo->fgIsWepCipherGroup = prBcnUpdateMsg->fgIsWepCipher; + + prBcnUpdateInfo = &(prRoleP2pFsmInfo->rBeaconUpdateInfo); + + p2pFuncBeaconUpdate(prAdapter, + prP2pBssInfo, + prBcnUpdateInfo, + prBcnUpdateMsg->pucBcnHdr, + prBcnUpdateMsg->u4BcnHdrLen, + prBcnUpdateMsg->pucBcnBody, + prBcnUpdateMsg->u4BcnBodyLen); + + if (prBcnUpdateMsg->pucAssocRespIE != NULL + && prBcnUpdateMsg->u4AssocRespLen > 0) { + DBGLOG(P2P, TRACE, + "Copy extra IEs for assoc resp (Length= %d)\n", + prBcnUpdateMsg->u4AssocRespLen); + DBGLOG_MEM8(P2P, INFO, + prBcnUpdateMsg->pucAssocRespIE, + prBcnUpdateMsg->u4AssocRespLen); + + if (p2pFuncAssocRespUpdate(prAdapter, + prP2pBssInfo, + prBcnUpdateMsg->pucAssocRespIE, + prBcnUpdateMsg->u4AssocRespLen) == WLAN_STATUS_FAILURE) + DBGLOG(P2P, ERROR, + "Update extra IEs for asso resp fail!\n"); + } + + + if ((prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) && + (prP2pBssInfo->eIntendOPMode == OP_MODE_NUM)) { + /* AP is created, Beacon Update. */ + /* nicPmIndicateBssAbort(prAdapter, NETWORK_TYPE_P2P_INDEX); */ + + + DBGLOG(P2P, TRACE, + "p2pRoleFsmRunEventBeaconUpdate with Bssidex(%d)\n", + prRoleP2pFsmInfo->ucBssIndex); + + bssUpdateBeaconContent(prAdapter, prRoleP2pFsmInfo->ucBssIndex); + +#if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP + if (p2pFuncProbeRespUpdate(prAdapter, + prP2pBssInfo, + prBcnUpdateMsg->pucProbeRespIE, + prBcnUpdateMsg->u4ProbeRespLen) == WLAN_STATUS_FAILURE) + DBGLOG(P2P, ERROR, + "Update extra IEs for probe resp fail!\n"); +#endif + /* nicPmIndicateBssCreated(prAdapter, + * NETWORK_TYPE_P2P_INDEX); + */ + } +error: + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pRoleFsmRunEventBeaconUpdate */ + +void +p2pProcessEvent_UpdateNOAParam(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct EVENT_UPDATE_NOA_PARAMS *prEventUpdateNoaParam) +{ + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo; + uint32_t i; + u_int8_t fgNoaAttrExisted = FALSE; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + prP2pSpecificBssInfo = + prAdapter->rWifiVar + .prP2pSpecificBssInfo[prBssInfo->u4PrivateData]; + + prP2pSpecificBssInfo->fgEnableOppPS = + prEventUpdateNoaParam->ucEnableOppPS; + 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].ucIsInUse; + /* 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; + + DBGLOG(P2P, INFO, "Update NoA param, count=%d, ucBssIdx=%d\n", + prEventUpdateNoaParam->ucNoATimingCount, + ucBssIdx); + + /* update beacon content by the change */ + bssUpdateBeaconContent(prAdapter, ucBssIdx); +} /* p2pProcessEvent_UpdateNOAParam */ + +#if CFG_ENABLE_PER_STA_STATISTICS_LOG +void +p2pRoleFsmGetStaStatistics(IN struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr) +{ + uint32_t u4BufLen; + struct PARAM_GET_STA_STATISTICS *prQueryStaStatistics; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) ulParamPtr; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + + if ((!prAdapter) || (!prP2pRoleFsmInfo)) { + DBGLOG(P2P, ERROR, "prAdapter=NULL || prP2pRoleFsmInfo=NULL\n"); + return; + } + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prP2pRoleFsmInfo->ucBssIndex); + if (!prP2pBssInfo) { + DBGLOG(P2P, ERROR, "prP2pBssInfo=NULL\n"); + return; + } + + prQueryStaStatistics = + prAdapter->rWifiVar.prP2pQueryStaStatistics + [prP2pRoleFsmInfo->ucRoleIndex]; + if (!prQueryStaStatistics) { + DBGLOG(P2P, ERROR, "prQueryStaStatistics=NULL\n"); + return; + } + + if (prP2pBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + if ((prP2pBssInfo->eCurrentOPMode + != OP_MODE_INFRASTRUCTURE) && + (prP2pBssInfo->eCurrentOPMode + != OP_MODE_ACCESS_POINT)) { + DBGLOG(P2P, ERROR, "Invalid OPMode=%d\n", + prP2pBssInfo->eCurrentOPMode); + return; + } + if (prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE + && prP2pBssInfo->prStaRecOfAP) { + COPY_MAC_ADDR( + prQueryStaStatistics->aucMacAddr, + prP2pBssInfo->prStaRecOfAP->aucMacAddr); + } else if (prP2pBssInfo->eCurrentOPMode + == OP_MODE_ACCESS_POINT) { + struct STA_RECORD *prCurrStaRec; + struct LINK *prClientList = + &prP2pBssInfo->rStaRecOfClientList; + if (!prClientList) { + DBGLOG(P2P, ERROR, "prClientList=NULL\n"); + return; + } + LINK_FOR_EACH_ENTRY(prCurrStaRec, + prClientList, rLinkEntry, struct STA_RECORD) { + COPY_MAC_ADDR( + prQueryStaStatistics->aucMacAddr, + prCurrStaRec->aucMacAddr); + /* break for LINK_FOR_EACH_ENTRY */ + break; + } + } + + prQueryStaStatistics->ucReadClear = TRUE; + wlanQueryStaStatistics(prAdapter, + prQueryStaStatistics, + sizeof(struct PARAM_GET_STA_STATISTICS), + &u4BufLen, + FALSE); + + } + + cnmTimerStartTimer(prAdapter, + &(prP2pRoleFsmInfo->rP2pRoleFsmGetStatisticsTimer), + P2P_ROLE_GET_STATISTICS_TIME); +} +#endif + +void p2pRoleFsmNotifyEapolTxStatus(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN enum ENUM_EAPOL_KEY_TYPE_T rEapolKeyType, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + + if (prAdapter == NULL) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (prBssInfo == NULL || prBssInfo->eNetworkType != NETWORK_TYPE_P2P) + return; + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prBssInfo->u4PrivateData); + + if (prP2pRoleFsmInfo == NULL) + return; + + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + return; + if (prP2pRoleFsmInfo->eCurrentState != P2P_ROLE_STATE_GC_JOIN) + return; + + if (rEapolKeyType == EAPOL_KEY_4_OF_4 && + rTxDoneStatus == TX_RESULT_SUCCESS) { + /* Finish GC connection process. */ + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, + P2P_ROLE_STATE_IDLE); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will clean p2p connection before suspend. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void p2pProcessPreSuspendFlow(IN struct ADAPTER *prAdapter) +{ + uint8_t idx; + struct BSS_INFO *prBssInfo; + uint32_t u4ClientCount = 0; + struct LINK *prClientList; + struct STA_RECORD *prCurrStaRec, *prStaRecNext; + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) NULL; + enum ENUM_OP_MODE eOPMode; + + if (prAdapter == NULL) + return; + + /* This should be cover by USB TX/RX check condition */ + /* + * if (!wlanGetHifState(prAdapter->prGlueInfo)) + * return; + */ + + for (idx = 0; idx < MAX_BSS_INDEX; idx++) { + prBssInfo = prAdapter->aprBssInfo[idx]; + if (!prBssInfo) + continue; + + /* Skip AIS BSS */ + if (prAdapter->prAisBssInfo && + idx == prAdapter->prAisBssInfo->ucBssIndex) + continue; + + if (!IS_BSS_ACTIVE(prBssInfo)) + continue; + + /* Non-P2P network type */ + if (prBssInfo->eNetworkType != NETWORK_TYPE_P2P) { + DBGLOG(P2P, STATE, "[Suspend] eNetworkType %d.\n", + prBssInfo->eNetworkType); + nicPmIndicateBssAbort(prAdapter, idx); + nicDeactivateNetwork(prAdapter, idx); + nicUpdateBss(prAdapter, idx); + } else { + eOPMode = prBssInfo->eCurrentOPMode; + + /* P2P network type. */ + /* Deactive GO/AP bss to let TOP sleep */ + if (eOPMode == OP_MODE_ACCESS_POINT) { + /* Force to deactivate Network of GO case */ + u4ClientCount = bssGetClientCount( + prAdapter, prBssInfo); + if (u4ClientCount != 0) { + prClientList = + &prBssInfo->rStaRecOfClientList; + LINK_FOR_EACH_ENTRY_SAFE(prCurrStaRec, + prStaRecNext, prClientList, rLinkEntry, + struct STA_RECORD) { + p2pFuncDisconnect(prAdapter, + prBssInfo, + prCurrStaRec, FALSE, + REASON_CODE_DEAUTH_LEAVING_BSS + ); + } + } + + DBGLOG(P2P, STATE, "Susp Force Deactive GO\n"); + p2pChangeMediaState(prAdapter, prBssInfo, + PARAM_MEDIA_STATE_DISCONNECTED); + p2pFuncStopComplete(prAdapter, prBssInfo); + } + /* P2P network type. Deactive GC bss to let TOP sleep */ + else if (eOPMode == OP_MODE_INFRASTRUCTURE) { + if (prBssInfo->prStaRecOfAP == NULL) + continue; + + /* Force to deactivate Network of GC case */ + DBGLOG(P2P, STATE, "Susp Force Deactive GC\n"); +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) + kalP2PGCIndicateConnectionStatus( + prAdapter->prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData, NULL, + NULL, 0, 0, WLAN_STATUS_MEDIA_DISCONNECT); +#else + kalP2PGCIndicateConnectionStatus( + prAdapter->prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData, + NULL, NULL, 0, 0); +#endif + + p2pFuncDisconnect(prAdapter, prBssInfo, + prBssInfo->prStaRecOfAP, FALSE, + REASON_CODE_DEAUTH_LEAVING_BSS); + p2pFuncStopComplete(prAdapter, prBssInfo); + } + } + + } + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + if (prP2pDevFsmInfo) { + DBGLOG(P2P, STATE, "Force P2P to IDLE state when suspend\n"); + cnmTimerStopTimer(prAdapter, + &(prP2pDevFsmInfo->rP2pFsmTimeoutTimer)); + + /* Abort device FSM */ + p2pDevFsmStateTransition(prAdapter, prP2pDevFsmInfo, + P2P_DEV_STATE_IDLE); + } +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_role_state.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_role_state.c new file mode 100644 index 0000000000000..d494a2e529ffd --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_role_state.c @@ -0,0 +1,626 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#include "precomp.h" + +void +p2pRoleStateInit_IDLE(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN struct BSS_INFO *prP2pBssInfo) +{ + + cnmTimerStartTimer(prAdapter, + &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer), + P2P_AP_CHNL_HOLD_TIME_MS); +} /* p2pRoleStateInit_IDLE */ + +void +p2pRoleStateAbort_IDLE(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN struct P2P_CHNL_REQ_INFO *prP2pChnlReqInfo) +{ + + /* AP mode channel hold time. */ + if (prP2pChnlReqInfo->fgIsChannelRequested) + p2pFuncReleaseCh(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + prP2pChnlReqInfo); + + cnmTimerStopTimer(prAdapter, + &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer)); +} /* p2pRoleStateAbort_IDLE */ + +void p2pRoleStateInit_SCAN(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct P2P_SCAN_REQ_INFO *prScanReqInfo) +{ + struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = + (struct P2P_DEV_FSM_INFO *) NULL; + struct P2P_SCAN_REQ_INFO *prDevScanReqInfo = NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prScanReqInfo != NULL)); + + prScanReqInfo->fgIsScanRequest = TRUE; + if (prScanReqInfo->u4BufLength == 0) { + /* If we let u4BufLength be zero, + * scan module will copy the IE buf from ScanParam + * Sometime this content is from AIS, + * so we need copy it from P2Pdev + */ + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + if (prP2pDevFsmInfo) { + prDevScanReqInfo = + &(prP2pDevFsmInfo->rScanReqInfo); + if (prDevScanReqInfo->u4BufLength != 0) { + /* IE Buffer */ + kalMemCopy(prScanReqInfo->aucIEBuf, + prDevScanReqInfo->aucIEBuf, + prDevScanReqInfo->u4BufLength); + prScanReqInfo->u4BufLength = + prDevScanReqInfo->u4BufLength; + DBGLOG(P2P, TRACE, + "p2pRoleStateInit_SCAN Copy p2p IE from P2P dev\n"); + } + } else + DBGLOG(P2P, ERROR, "No prP2pDevFsmInfo ptr\n"); + } + p2pFuncRequestScan(prAdapter, ucBssIndex, prScanReqInfo); + } while (FALSE); +} /* p2pRoleStateInit_SCAN */ + +void p2pRoleStateAbort_SCAN(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo) +{ + struct P2P_SCAN_REQ_INFO *prScanInfo = + (struct P2P_SCAN_REQ_INFO *) NULL; + + do { + prScanInfo = &prP2pRoleFsmInfo->rScanReqInfo; + + p2pFuncCancelScan(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + prScanInfo); + + /* TODO: May need indicate port index to upper layer. */ + kalP2PIndicateScanDone(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, + prScanInfo->fgIsAbort); + + } while (FALSE); +} /* p2pRoleStateAbort_SCAN */ + +void +p2pRoleStateInit_REQING_CHANNEL(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo) +{ + + do { + ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL)); + + p2pFuncAcquireCh(prAdapter, ucBssIdx, prChnlReqInfo); + + } while (FALSE); +} /* p2pRoleStateInit_REQING_CHANNEL */ + +void +p2pRoleStateAbort_REQING_CHANNEL(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pRoleBssInfo, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN enum ENUM_P2P_ROLE_STATE eNextState) +{ + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prP2pRoleBssInfo != NULL) + && (prP2pRoleFsmInfo != NULL)); + + if (eNextState == P2P_ROLE_STATE_IDLE) { + if (prP2pRoleBssInfo->eIntendOPMode + == OP_MODE_ACCESS_POINT) { + struct P2P_CHNL_REQ_INFO *prP2pChnlReqInfo = + &(prP2pRoleFsmInfo->rChnlReqInfo); + + if (IS_NET_PWR_STATE_ACTIVE(prAdapter, + prP2pRoleFsmInfo->ucBssIndex)) { + p2pFuncStartGO(prAdapter, + prP2pRoleBssInfo, + &(prP2pRoleFsmInfo->rConnReqInfo), + &(prP2pRoleFsmInfo->rChnlReqInfo)); + prAdapter->fgIsStartApDone = TRUE; + } + else if (prP2pChnlReqInfo->fgIsChannelRequested) + p2pFuncReleaseCh(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + prP2pChnlReqInfo); + } else { + p2pFuncReleaseCh(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rChnlReqInfo)); + } + } + } while (FALSE); +} /* p2pRoleStateAbort_REQING_CHANNEL */ + +void +p2pRoleStateInit_AP_CHNL_DETECTION(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct P2P_SCAN_REQ_INFO *prScanReqInfo, + IN struct P2P_CONNECTION_REQ_INFO *prConnReqInfo) +{ + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo = + (struct P2P_SPECIFIC_BSS_INFO *) NULL; + struct BSS_INFO *prBssInfo = NULL; + uint8_t ucPreferedChnl = 0; + enum ENUM_BAND eBand = BAND_NULL; + enum ENUM_CHNL_EXT eSco = CHNL_EXT_SCN; + + do { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + ASSERT_BREAK((prAdapter != NULL) && (prScanReqInfo != NULL) + && (prConnReqInfo != NULL) && (prBssInfo != NULL)); + + prP2pSpecificBssInfo = + prAdapter->rWifiVar + .prP2pSpecificBssInfo[prBssInfo->u4PrivateData]; + + if ((cnmPreferredChannel(prAdapter, + &eBand, + &ucPreferedChnl, + &eSco) == FALSE) + && (prConnReqInfo->rChannelInfo.ucChannelNum == 0)) { + + /* Sparse channel detection. */ + prP2pSpecificBssInfo->ucPreferredChannel = 0; + + prScanReqInfo->eScanType = SCAN_TYPE_PASSIVE_SCAN; + /* 50ms for passive channel load detection */ + prScanReqInfo->u2PassiveDewellTime = 50; + } else { + /* Active scan to shorten scan time. */ + prScanReqInfo->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prScanReqInfo->u2PassiveDewellTime = 0; + + if (prConnReqInfo->rChannelInfo.ucChannelNum != 0) { + prP2pSpecificBssInfo->ucPreferredChannel = + prConnReqInfo->rChannelInfo + .ucChannelNum; + prP2pSpecificBssInfo->eRfBand = + prConnReqInfo->rChannelInfo + .eBand; + prP2pSpecificBssInfo->eRfSco = CHNL_EXT_SCN; + } else { + prP2pSpecificBssInfo->ucPreferredChannel = + ucPreferedChnl; + prP2pSpecificBssInfo->eRfBand = eBand; + prP2pSpecificBssInfo->eRfSco = eSco; + } + + } + + /* TODO: See if channel set to include 5G or only 2.4G */ + prScanReqInfo->eChannelSet = SCAN_CHANNEL_2G4; + + prScanReqInfo->fgIsAbort = TRUE; + prScanReqInfo->fgIsScanRequest = TRUE; + prScanReqInfo->ucNumChannelList = 0; + prScanReqInfo->u4BufLength = 0; + prScanReqInfo->ucSsidNum = 1; + prScanReqInfo->arSsidStruct[0].ucSsidLen = 0; + + p2pFuncRequestScan(prAdapter, ucBssIndex, prScanReqInfo); + + } while (FALSE); + + return; + +} /* p2pRoleStateInit_AP_CHNL_DETECTION */ + +void +p2pRoleStateAbort_AP_CHNL_DETECTION(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN struct P2P_CONNECTION_REQ_INFO *prP2pConnReqInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, + IN struct P2P_SCAN_REQ_INFO *prP2pScanReqInfo, + IN enum ENUM_P2P_ROLE_STATE eNextState) +{ + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo = + (struct P2P_SPECIFIC_BSS_INFO *) NULL; + struct BSS_INFO *prBssInfo = NULL; + + do { + if (eNextState == P2P_ROLE_STATE_REQING_CHANNEL) { + prBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + prP2pSpecificBssInfo = + prAdapter->rWifiVar + .prP2pSpecificBssInfo[prBssInfo->u4PrivateData]; + + if (prP2pSpecificBssInfo->ucPreferredChannel == 0) { + if (scnQuerySparseChannel(prAdapter, + &prP2pSpecificBssInfo + ->eRfBand, + &prP2pSpecificBssInfo + ->ucPreferredChannel)) { + prP2pSpecificBssInfo->eRfSco = + CHNL_EXT_SCN; + } else { + DBGLOG(P2P, ERROR, + "Sparse Channel Error, use default settings\n"); + /* Sparse channel false. */ + prP2pSpecificBssInfo->ucPreferredChannel + = P2P_DEFAULT_LISTEN_CHANNEL; + prP2pSpecificBssInfo->eRfBand + = BAND_2G4; + prP2pSpecificBssInfo->eRfSco + = CHNL_EXT_SCN; + } + } + + prChnlReqInfo->u8Cookie = 0; + prChnlReqInfo->ucReqChnlNum = + prP2pSpecificBssInfo->ucPreferredChannel; + prChnlReqInfo->eBand = prP2pSpecificBssInfo->eRfBand; + prChnlReqInfo->eChnlSco = prP2pSpecificBssInfo->eRfSco; + prChnlReqInfo->u4MaxInterval = P2P_AP_CHNL_HOLD_TIME_MS; + prChnlReqInfo->eChnlReqType = CH_REQ_TYPE_GO_START_BSS; + + prChnlReqInfo->eChannelWidth = CW_20_40MHZ; + prChnlReqInfo->ucCenterFreqS1 = 0; + prChnlReqInfo->ucCenterFreqS2 = 0; + + } else { + p2pFuncCancelScan(prAdapter, + ucBssIndex, + prP2pScanReqInfo); + } + } while (FALSE); +} + +void +p2pRoleStateInit_GC_JOIN(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo) +{ + /* P_MSG_JOIN_REQ_T prJoinReqMsg = (P_MSG_JOIN_REQ_T)NULL; */ + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (prP2pRoleFsmInfo != NULL) + && (prChnlReqInfo != NULL)); + + prP2pBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, + prP2pRoleFsmInfo->ucBssIndex); + + /* Setup a join timer. */ + DBGLOG(P2P, TRACE, "Start a join init timer\n"); + cnmTimerStartTimer(prAdapter, + &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer), + (prChnlReqInfo->u4MaxInterval + - AIS_JOIN_CH_GRANT_THRESHOLD)); + + p2pFuncGCJoin(prAdapter, + prP2pBssInfo, + &(prP2pRoleFsmInfo->rJoinInfo)); + + } while (FALSE); +} /* p2pRoleStateInit_GC_JOIN */ + +void +p2pRoleStateAbort_GC_JOIN(IN struct ADAPTER *prAdapter, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN struct P2P_JOIN_INFO *prJoinInfo, + IN enum ENUM_P2P_ROLE_STATE eNextState) +{ + do { + + if (prJoinInfo->fgIsJoinComplete == FALSE) { + struct MSG_SAA_FSM_ABORT *prJoinAbortMsg = + (struct MSG_SAA_FSM_ABORT *) NULL; + struct BSS_DESC *prBssDesc = + (struct BSS_DESC *) NULL; + + prJoinAbortMsg = + (struct MSG_SAA_FSM_ABORT *) cnmMemAlloc( + prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_SAA_FSM_ABORT)); + 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; + + /* Reset the flag to clear target BSS state */ + prBssDesc = prJoinInfo->prTargetBssDesc; + if (prBssDesc != NULL) { + prBssDesc->fgIsConnecting = FALSE; + } + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (struct MSG_HDR *) prJoinAbortMsg, + MSG_SEND_METHOD_BUF); + + } + + /* Stop Join Timer. */ + cnmTimerStopTimer(prAdapter, + &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer)); + + /* Release channel requested. */ + p2pFuncReleaseCh(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rChnlReqInfo)); + + } while (FALSE); +} + +#if (CFG_SUPPORT_DFS_MASTER == 1) +void +p2pRoleStateInit_DFS_CAC(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo) +{ + + do { + ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL)); + + p2pFuncAcquireCh(prAdapter, ucBssIdx, prChnlReqInfo); + } while (FALSE); +} /* p2pRoleStateInit_DFS_CAC */ + +void +p2pRoleStateAbort_DFS_CAC(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pRoleBssInfo, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN enum ENUM_P2P_ROLE_STATE eNextState) +{ + do { + cnmTimerStopTimer(prAdapter, + &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer)); + + p2pFuncReleaseCh(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rChnlReqInfo)); + + } while (FALSE); +} /* p2pRoleStateAbort_DFS_CAC */ + +void +p2pRoleStateInit_SWITCH_CHANNEL(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, + IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo) +{ + + do { + ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL)); + + p2pFuncAcquireCh(prAdapter, ucBssIdx, prChnlReqInfo); + } while (FALSE); +} /* p2pRoleStateInit_SWITCH_CHANNEL */ + +void +p2pRoleStateAbort_SWITCH_CHANNEL(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prP2pRoleBssInfo, + IN struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo, + IN enum ENUM_P2P_ROLE_STATE eNextState) +{ + do { + p2pFuncReleaseCh(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rChnlReqInfo)); + } while (FALSE); +} /* p2pRoleStateAbort_SWITCH_CHANNEL */ +#endif + +void +p2pRoleStatePrepare_To_REQING_CHANNEL_STATE(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN struct P2P_CONNECTION_REQ_INFO *prConnReqInfo, + OUT struct P2P_CHNL_REQ_INFO *prChnlReqInfo) +{ + enum ENUM_BAND eBandBackup; + uint8_t ucChannelBackup; + enum ENUM_CHNL_EXT eSCOBackup; + uint8_t ucRfBw; + + do { + /* P2P BSS info is for temporarily use + * Request a 80MHz channel before starting AP/GO + * to prevent from STA/GC connected too early (before CH abort) + * Therefore, STA/GC Rate will drop during DHCP exchange packets + */ + + /* Previous issue: + * Always request 20MHz channel, + * but carry 40MHz HT cap/80MHz VHT cap, + * then if GC/STA connected before CH abort, + * GO/AP cannot listen to GC/STA's 40MHz/80MHz packets. + */ + + eBandBackup = prBssInfo->eBand; + ucChannelBackup = prBssInfo->ucPrimaryChannel; + eSCOBackup = prBssInfo->eBssSCO; + + prBssInfo->ucPrimaryChannel = + prConnReqInfo->rChannelInfo.ucChannelNum; + prBssInfo->eBand = prConnReqInfo->rChannelInfo.eBand; + + prBssInfo->eBssSCO = rlmGetScoForAP(prAdapter, prBssInfo); + + ASSERT_BREAK((prAdapter != NULL) + && (prConnReqInfo != NULL) + && (prChnlReqInfo != NULL)); + + prChnlReqInfo->u8Cookie = 0; + prChnlReqInfo->ucReqChnlNum = + prConnReqInfo->rChannelInfo.ucChannelNum; + prChnlReqInfo->eBand = prConnReqInfo->rChannelInfo.eBand; + prChnlReqInfo->eChnlSco = prBssInfo->eBssSCO; + prChnlReqInfo->u4MaxInterval = P2P_AP_CHNL_HOLD_TIME_MS; + prChnlReqInfo->eChnlReqType = CH_REQ_TYPE_GO_START_BSS; + + if (prBssInfo->eBand == BAND_5G) { + /* Decide RF BW by own OP BW */ + ucRfBw = cnmGetDbdcBwCapability(prAdapter, + prBssInfo->ucBssIndex); + /* Revise to VHT OP BW */ + ucRfBw = rlmGetVhtOpBwByBssOpBw(ucRfBw); + prChnlReqInfo->eChannelWidth = ucRfBw; + } else + prChnlReqInfo->eChannelWidth = CW_20_40MHZ; + + /* TODO: BW80+80 support */ + prChnlReqInfo->ucCenterFreqS1 = + nicGetVhtS1(prBssInfo->ucPrimaryChannel, + prChnlReqInfo->eChannelWidth); + prChnlReqInfo->ucCenterFreqS2 = 0; + + /* If the S1 is invalid, force to change bandwidth */ + if ((prBssInfo->eBand == BAND_5G) && + (prChnlReqInfo->ucCenterFreqS1 == 0)) + prChnlReqInfo->eChannelWidth = + VHT_OP_CHANNEL_WIDTH_20_40; + + DBGLOG(P2P, TRACE, + "p2pRoleStatePrepare_To_REQING_CHANNEL_STATE\n"); + + /* Reset */ + prBssInfo->ucPrimaryChannel = ucChannelBackup; + prBssInfo->eBand = eBandBackup; + prBssInfo->eBssSCO = eSCOBackup; + } while (FALSE); +} + +#if (CFG_SUPPORT_DFS_MASTER == 1) +void +p2pRoleStatePrepare_To_DFS_CAC_STATE(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, + IN enum ENUM_CHANNEL_WIDTH rChannelWidth, + IN struct P2P_CONNECTION_REQ_INFO *prConnReqInfo, + OUT struct P2P_CHNL_REQ_INFO *prChnlReqInfo) +{ + enum ENUM_BAND eBandBackup; + uint8_t ucChannelBackup; + enum ENUM_CHNL_EXT eSCOBackup; + struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = + (struct P2P_ROLE_FSM_INFO *) NULL; + + do { + + eBandBackup = prBssInfo->eBand; + ucChannelBackup = prBssInfo->ucPrimaryChannel; + eSCOBackup = prBssInfo->eBssSCO; + + prBssInfo->ucPrimaryChannel = + prConnReqInfo->rChannelInfo.ucChannelNum; + prBssInfo->eBand = prConnReqInfo->rChannelInfo.eBand; + + prBssInfo->eBssSCO = rlmGetScoForAP(prAdapter, prBssInfo); + + prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prBssInfo->u4PrivateData); + + ASSERT_BREAK((prAdapter != NULL) + && (prConnReqInfo != NULL) + && (prChnlReqInfo != NULL)); + + prChnlReqInfo->u8Cookie = 0; + prChnlReqInfo->ucReqChnlNum = + prConnReqInfo->rChannelInfo.ucChannelNum; + prChnlReqInfo->eBand = prConnReqInfo->rChannelInfo.eBand; + prChnlReqInfo->eChnlSco = prBssInfo->eBssSCO; + prChnlReqInfo->u4MaxInterval = + prAdapter->prGlueInfo + ->prP2PInfo[prP2pRoleFsmInfo->ucRoleIndex] + ->cac_time_ms; + prChnlReqInfo->eChnlReqType = CH_REQ_TYPE_DFS_CAC; + + prBssInfo->ucVhtChannelWidth = + cnmGetBssMaxBwToChnlBW(prAdapter, + prBssInfo->ucBssIndex); + prChnlReqInfo->eChannelWidth = prBssInfo->ucVhtChannelWidth; + + if (prChnlReqInfo->eChannelWidth + == VHT_OP_CHANNEL_WIDTH_80P80) { + /* TODO: BW80+80 support */ + log_dbg(RLM, WARN, "BW80+80 not support. Fallback to VHT_OP_CHANNEL_WIDTH_20_40\n"); + prChnlReqInfo->eChannelWidth = + VHT_OP_CHANNEL_WIDTH_20_40; + prChnlReqInfo->ucCenterFreqS1 = 0; + prChnlReqInfo->ucCenterFreqS2 = 0; + } else { + prChnlReqInfo->ucCenterFreqS1 = + rlmGetVhtS1ForAP(prAdapter, prBssInfo); + prChnlReqInfo->ucCenterFreqS2 = 0; + } + + DBGLOG(P2P, TRACE, + "p2pRoleStatePrepare_To_REQING_CHANNEL_STATE\n"); + + /* Reset */ + prBssInfo->ucPrimaryChannel = ucChannelBackup; + prBssInfo->eBand = eBandBackup; + prBssInfo->eBssSCO = eSCOBackup; + } while (FALSE); +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_scan.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_scan.c new file mode 100644 index 0000000000000..353d0570e94a9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/p2p_scan.c @@ -0,0 +1,343 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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 + ****************************************************************************** + */ + +void +scanP2pProcessBeaconAndProbeResp(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN uint32_t *prStatus, + IN struct BSS_DESC *prBssDesc, + IN struct WLAN_BEACON_FRAME *prWlanBeaconFrame) +{ + u_int8_t fgIsBeacon = FALSE; + u_int8_t fgIsSkipThisBeacon = FALSE; + + /* Indicate network to kernel for P2P interface when: + * 1. This is P2P network + * 2. Driver is configured to report all bss networks + */ + if (!prBssDesc->fgIsP2PPresent && + !prAdapter->p2p_scan_report_all_bss) + return; + + fgIsBeacon = (prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) == + MAC_FRAME_BEACON; + + if (prBssDesc->fgIsConnected && fgIsBeacon) { + uint32_t u4Idx = 0; + struct BSS_INFO *prP2pBssInfo = + (struct BSS_INFO *) NULL; + + for (u4Idx = 0; u4Idx < prAdapter->ucHwBssIdNum; u4Idx++) { + /* Check BSS for P2P. */ + /* Check BSSID. */ + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + (uint8_t) u4Idx); + + if (!IS_BSS_ACTIVE(prP2pBssInfo)) + continue; + + if ((prP2pBssInfo->eNetworkType != NETWORK_TYPE_P2P) || + (UNEQUAL_MAC_ADDR(prP2pBssInfo->aucBSSID, + prBssDesc->aucBSSID) || + (!EQUAL_SSID(prP2pBssInfo->aucSSID, + prP2pBssInfo->ucSSIDLen, + prBssDesc->aucSSID, + prBssDesc->ucSSIDLen)))) { + continue; + } + /* P2P GC */ + /* Connected */ + if ((prP2pBssInfo->eCurrentOPMode == + OP_MODE_INFRASTRUCTURE) && + (prP2pBssInfo->eConnectionState == + PARAM_MEDIA_STATE_CONNECTED)) { + fgIsSkipThisBeacon = TRUE; + /* First Time. */ + if ((!prP2pBssInfo->ucDTIMPeriod)) { + prP2pBssInfo->ucDTIMPeriod = + prBssDesc->ucDTIMPeriod; + nicPmIndicateBssConnected( + prAdapter, + prP2pBssInfo->ucBssIndex); + } + } + + } + + } + + /* Skip report beacon to upper layer if no p2p scan */ + if (prAdapter->prGlueInfo->prP2PDevInfo->prScanRequest == NULL && + fgIsBeacon) + fgIsSkipThisBeacon = TRUE; + + if (fgIsBeacon && fgIsSkipThisBeacon) { + /* Only report Probe Response frame + * to supplicant except passive scan. + */ + /* Probe response collect + * much more information. + */ + DBGLOG(P2P, TRACE, "Skip beacon [" MACSTR "][%s][ch %d]\n", + MAC2STR(prWlanBeaconFrame->aucBSSID), + prBssDesc->aucSSID, + prBssDesc->ucChannelNum); + return; + } + + do { + struct RF_CHANNEL_INFO rChannelInfo; + + ASSERT_BREAK((prSwRfb != NULL) && (prBssDesc != NULL)); + + rChannelInfo.ucChannelNum = prBssDesc->ucChannelNum; + rChannelInfo.eBand = prBssDesc->eBand; + prBssDesc->fgIsP2PReport = TRUE; + + DBGLOG(P2P, INFO, + "indicate [" MACSTR "][%s][%s][ch %d][r %d][t %u]\n", + MAC2STR(prWlanBeaconFrame->aucBSSID), + fgIsBeacon ? "Beacon" : "Probe Response", + prBssDesc->aucSSID, + prBssDesc->ucChannelNum, + prBssDesc->ucRCPI, + prBssDesc->rUpdateTime); + + kalP2PIndicateBssInfo(prAdapter->prGlueInfo, + (uint8_t *) prSwRfb->pvHeader, + (uint32_t) prSwRfb->u2PacketLen, + &rChannelInfo, + RCPI_TO_dBm(prBssDesc->ucRCPI)); + + } while (FALSE); +} + +void scnEventReturnChannel(IN struct ADAPTER *prAdapter, + IN uint8_t ucScnSeqNum) +{ + + struct CMD_SCAN_CANCEL rCmdScanCancel; + + /* send cancel message to firmware domain */ + rCmdScanCancel.ucSeqNum = ucScnSeqNum; + rCmdScanCancel.ucIsExtChannel = (uint8_t) FALSE; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SCAN_CANCEL, + TRUE, + FALSE, FALSE, NULL, NULL, + sizeof(struct CMD_SCAN_CANCEL), + (uint8_t *)&rCmdScanCancel, NULL, 0); +} /* scnEventReturnChannel */ + +void scanRemoveAllP2pBssDesc(IN struct ADAPTER *prAdapter) +{ + struct LINK *prBSSDescList; + struct BSS_DESC *prBssDesc; + struct BSS_DESC *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, struct BSS_DESC) { + scanRemoveP2pBssDesc(prAdapter, prBssDesc); + } +} /* scanRemoveAllP2pBssDesc */ + +void scanRemoveP2pBssDesc(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc) +{ +} /* scanRemoveP2pBssDesc */ + +struct BSS_DESC *scanP2pSearchDesc(IN struct ADAPTER *prAdapter, + IN struct P2P_CONNECTION_REQ_INFO *prConnReqInfo) +{ + struct BSS_DESC *prCandidateBssDesc = (struct BSS_DESC *) NULL, + *prBssDesc = (struct BSS_DESC *) NULL; + struct LINK *prBssDescList = (struct LINK *) NULL; + + do { + if ((prAdapter == 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, struct BSS_DESC) { + 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); *//*let p2p re-scan again */ + continue; + } + + if (!prBssDesc->fgIsP2PPresent) { + DBGLOG(P2P, ERROR, + "SSID, BSSID, BSSTYPE match, but no P2P IE present.\n"); + continue; + } + + /* Final decision. */ + prCandidateBssDesc = prBssDesc; + break; + } + + } while (FALSE); + + return prCandidateBssDesc; +} /* scanP2pSearchDesc */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/privacy.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/privacy.c new file mode 100644 index 0000000000000..de1751a7101ca --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/privacy.c @@ -0,0 +1,1423 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: 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 + * + */ + +/******************************************************************************* + * C O M P I L E 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 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 struct ADAPTER *prAdapter, IN uint8_t ucBssIndex) +{ + uint8_t i; + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_INFO *prBssInfo; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecBssInfo; + + DEBUGFUNC("secInit"); + + ASSERT(prAdapter); + + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + prBssInfo->u4RsnSelectedGroupCipher = 0; + prBssInfo->u4RsnSelectedPairwiseCipher = 0; + prBssInfo->u4RsnSelectedAKMSuite = 0; + +#if 0 /* CFG_ENABLE_WIFI_DIRECT */ + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P]; + + prBssInfo->u4RsnSelectedGroupCipher = RSN_CIPHER_SUITE_CCMP; + prBssInfo->u4RsnSelectedPairwiseCipher = RSN_CIPHER_SUITE_CCMP; + prBssInfo->u4RsnSelectedAKMSuite = RSN_AKM_SUITE_PSK; +#endif + +#if 0 /* CFG_ENABLE_BT_OVER_WIFI */ + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW]; + + 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; + prAdapter->rMib. + dot11RSNAConfigPairwiseCiphersTable[8].dot11RSNAConfigPairwiseCipher + = RSN_CIPHER_SUITE_GROUP_NOT_USED; +#if CFG_SUPPORT_CFG80211_AUTH + prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[9] + .dot11RSNAConfigPairwiseCipher = RSN_CIPHER_SUITE_GCMP_256; +#endif + + 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; + + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable + [6].dot11RSNAConfigAuthenticationSuite = RSN_AKM_SUITE_FT_802_1X; + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable + [7].dot11RSNAConfigAuthenticationSuite = RSN_AKM_SUITE_FT_PSK; + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable + [8].dot11RSNAConfigAuthenticationSuite = WFA_AKM_SUITE_OSEN; + +#if CFG_SUPPORT_802_11W + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable + [9].dot11RSNAConfigAuthenticationSuite = + RSN_AKM_SUITE_802_1X_SHA256; + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable + [10].dot11RSNAConfigAuthenticationSuite = RSN_AKM_SUITE_PSK_SHA256; +#endif +#if CFG_SUPPORT_CFG80211_AUTH + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[11] + .dot11RSNAConfigAuthenticationSuite + = RSN_AKM_SUITE_8021X_SUITE_B; + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[12] + .dot11RSNAConfigAuthenticationSuite + = RSN_AKM_SUITE_8021X_SUITE_B_192; + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[13] + .dot11RSNAConfigAuthenticationSuite + = RSN_AKM_SUITE_SAE; + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[14] + .dot11RSNAConfigAuthenticationSuite + = RSN_AKM_SUITE_OWE; +#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, + (unsigned long)NULL); + +#if CFG_SUPPORT_802_11W + cnmTimerInitTimer(prAdapter, + &prAisSpecBssInfo->rSaQueryTimer, + (PFN_MGMT_TIMEOUT_FUNC) rsnStartSaQueryTimer, + (unsigned long)NULL); +#endif + + prAisSpecBssInfo->fgCounterMeasure = FALSE; + prAdapter->prAisBssInfo->ucBcDefaultKeyIdx = 0xff; + prAdapter->prAisBssInfo->fgBcDefaultKeyExist = FALSE; + +#if 0 + for (i = 0; i < WTBL_SIZE; i++) { + g_prWifiVar->arWtbl[i].ucUsed = FALSE; + g_prWifiVar->arWtbl[i].prSta = NULL; + g_prWifiVar->arWtbl[i].ucNetTypeIdx = NETWORK_TYPE_INDEX_NUM; + + } + nicPrivacyInitialize((uint8_t) 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t secCheckClassError(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN struct STA_RECORD *prStaRec) +{ + struct HW_MAC_RX_DESC *prRxStatus; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxStatus = prSwRfb->prRxStatus; + + if (((prRxStatus->u2StatusFlag & RXS_DW2_RX_CLASSERR_BITMAP) + == RXS_DW2_RX_CLASSERR_VALUE) + || (IS_STA_IN_AIS(prStaRec) + && prAdapter->prAisBssInfo->eConnectionState == + PARAM_MEDIA_STATE_DISCONNECTED)) { + + DBGLOG(RSN, ERROR, + "RX_CLASSERR: prStaRec=%p StatusFlag=0x%x, PktTYpe=0x%x, WlanIdx=%d, StaRecIdx=%d, eDst=%d, prStaRec->eStaType=%d\n", + prStaRec, prRxStatus->u2StatusFlag, + prRxStatus->u2PktTYpe, prSwRfb->ucWlanIdx, + prSwRfb->ucStaRecIdx, prSwRfb->eDst, prStaRec->eStaType); + + DBGLOG_MEM8(RX, WARN, prSwRfb->pucRecvBuff, + (prSwRfb->prRxStatus->u2RxByteCount > 64) ? 64 : + prSwRfb->prRxStatus->u2RxByteCount); + + /* if (IS_NET_ACTIVE(prAdapter, ucBssIndex)) { */ + authSendDeauthFrame(prAdapter, + NULL, NULL, prSwRfb, + REASON_CODE_CLASS_3_ERR, + (PFN_TX_DONE_HANDLER) NULL); + return FALSE; + /* } */ + } + + return TRUE; + +} /* 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 struct ADAPTER *prAdapter, + IN struct STA_RECORD *prSta, IN u_int8_t fgPortBlock) +{ +#if 0 /* Marked for MT6630 */ + if (prSta == NULL) + return; + + prSta->fgPortBlock = fgPortBlock; + + DBGLOG(RSN, TRACE, + "The STA " MACSTR " port %s\n", MAC2STR(prSta->aucMacAddr), + fgPortBlock == TRUE ? "BLOCK" : " OPEN"); +#endif +} + +#if 0 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + * + */ +/*----------------------------------------------------------------------------*/ +u_int8_t secGetPortStatus(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prSta, + OUT u_int8_t *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 + * + */ +/*----------------------------------------------------------------------------*/ +u_int8_t /* ENUM_PORT_CONTROL_RESULT */ +secTxPortControlCheck(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN struct STA_RECORD *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; +} +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t secRxPortControlCheck(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSWRfb) +{ + ASSERT(prSWRfb); + + 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 struct ADAPTER *prAdapter, + IN uint32_t u4CipherSuitesFlags) +{ + + uint32_t i; + struct DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY *prEntry; + struct IEEE_802_11_MIB *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) { +#if CFG_SUPPORT_SUITB + case RSN_CIPHER_SUITE_GCMP_256: + if (u4CipherSuitesFlags & CIPHER_FLAG_GCMP256) + prEntry->dot11RSNAConfigPairwiseCipherEnabled + = TRUE; + else + prEntry->dot11RSNAConfigPairwiseCipherEnabled + = FALSE; + break; +#endif + 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 if (rsnSearchSupportedCipher(prAdapter, + RSN_CIPHER_SUITE_GROUP_NOT_USED, &i)) + prMib->dot11RSNAConfigGroupCipher = + RSN_CIPHER_SUITE_GROUP_NOT_USED; +#if CFG_SUPPORT_SUITB + else if (rsnSearchSupportedCipher(prAdapter, + RSN_CIPHER_SUITE_GCMP_256, &i)) + prMib->dot11RSNAConfigGroupCipher = + RSN_CIPHER_SUITE_GCMP_256; +#endif + else + prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_NONE; + +} /* secSetCipherSuite */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to initialize the pmkid parameters. + * + * \param[in] prAdapter Pointer to the Adapter structure + * + * \retval NONE + */ +/*----------------------------------------------------------------------------*/ +void secClearPmkid(IN struct ADAPTER *prAdapter) +{ + struct AIS_SPECIFIC_BSS_INFO *prAisSpecBssInfo; + + DEBUGFUNC("secClearPmkid"); + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + DBGLOG(RSN, TRACE, "secClearPmkid\n"); + prAisSpecBssInfo->u4PmkidCandicateCount = 0; + prAisSpecBssInfo->u4PmkidCacheCount = 0; + kalMemZero((void *)prAisSpecBssInfo->arPmkidCandicate, + sizeof(struct PMKID_CANDICATE) * CFG_MAX_PMKID_CACHE); + kalMemZero((void *)prAisSpecBssInfo->arPmkidCache, + sizeof(struct PMKID_ENTRY) * CFG_MAX_PMKID_CACHE); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Whether 802.11 privacy is enabled. + * + * \param[in] prAdapter Pointer to the Adapter structure + * + * \retval BOOLEAN + */ +/*----------------------------------------------------------------------------*/ +u_int8_t secEnabledInAis(IN struct ADAPTER *prAdapter) +{ + DEBUGFUNC("secEnabledInAis"); + + ASSERT(prAdapter->rWifiVar.rConnSettings.eEncStatus < + ENUM_ENCRYPTION_NUM); + + if ((prAdapter->rWifiVar.rConnSettings.eEncStatus + == ENUM_ENCRYPTION1_ENABLED) + || (prAdapter->rWifiVar.rConnSettings.eEncStatus + == ENUM_ENCRYPTION2_ENABLED) + || (prAdapter->rWifiVar.rConnSettings.eEncStatus + == ENUM_ENCRYPTION3_ENABLED) +#if CFG_SUPPORT_SUITB + || (prAdapter->rWifiVar.rConnSettings.eEncStatus + == ENUM_ENCRYPTION4_ENABLED) +#endif + ) + return TRUE; + else if (prAdapter->rWifiVar.rConnSettings.eEncStatus + == ENUM_ENCRYPTION_DISABLED) + DBGLOG(RSN, TRACE, "Unknown encryption setting %d\n", + prAdapter->rWifiVar.rConnSettings.eEncStatus); + return FALSE; + +} /* secEnabledInAis */ + +u_int8_t secIsProtected1xFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + struct BSS_INFO *prBssInfo; + + ASSERT(prAdapter); + + if (prStaRec) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + if (prBssInfo && prBssInfo->eNetworkType == NETWORK_TYPE_AIS) { +#if CFG_SUPPORT_WAPI + if (wlanQueryWapiMode(prAdapter)) + return FALSE; +#endif + } + + return prStaRec->fgTransmitKeyExist; + } + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t secIsProtectedFrame(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsdu, + IN struct STA_RECORD *prStaRec) +{ + /* P_BSS_INFO_T prBssInfo; */ + + ASSERT(prAdapter); + ASSERT(prMsdu); + /* ASSERT(prStaRec); */ + +#if CFG_SUPPORT_802_11W + if (prMsdu->ucPacketType == TX_PACKET_TYPE_MGMT) + return FALSE; + +#else + if (prMsdu->ucPacketType == TX_PACKET_TYPE_MGMT) + return FALSE; +#endif + + return secIsProtectedBss(prAdapter, + GET_BSS_INFO_BY_INDEX(prAdapter, + prMsdu->ucBssIndex)); +} + +u_int8_t secIsProtectedBss(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo) +{ + ASSERT(prBssInfo); + + if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) { +#if CFG_SUPPORT_WAPI + if (wlanQueryWapiMode(prAdapter)) + return TRUE; +#endif + return secEnabledInAis(prAdapter); + } +#if CFG_ENABLE_WIFI_DIRECT + else if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) + return kalP2PGetCipher(prAdapter->prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData); +#endif + else if (prBssInfo->eNetworkType == NETWORK_TYPE_BOW) + return TRUE; + + ASSERT(FALSE); + return FALSE; +} + +u_int8_t secIsWepBss(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo) +{ + ASSERT(prBssInfo); + + if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) { + if (prAdapter->rWifiVar.rConnSettings.eEncStatus == + ENUM_ENCRYPTION1_ENABLED) + return TRUE; + } +#if CFG_ENABLE_WIFI_DIRECT + else if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) + return kalP2PGetWepCipher(prAdapter->prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData); +#endif + + return FALSE; +} + +u_int8_t secIsUsedByStaRecEntry(IN struct ADAPTER *prAdapter, IN u_int8_t Index) +{ + struct STA_RECORD *prStaRec = NULL; + u_int8_t i = 0; + u_int8_t fgIsUsed = FALSE; + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + if (prStaRec->fgIsInUse && prStaRec->ucWlanIndex == Index) { + fgIsUsed = TRUE; + DBGLOG(RSN, INFO, + "[Wlan index]: Duplicated entry #%d\n", Index); + break; + } + } + return fgIsUsed; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used before add/update a WLAN entry. + * Info the WLAN Table has available entry for this request + * + * \param[in] prAdapter Pointer to the Adapter structure + * \param[in] prSta the P_STA_RECORD_T for store + * + * \return TRUE Free Wlan table is reserved for this request + * FALSE No free entry for this request + * + * \note + */ +/*----------------------------------------------------------------------------*/ +u_int8_t secPrivacySeekForEntry( + IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prSta) +{ + struct BSS_INFO *prP2pBssInfo; + uint8_t ucEntry = WTBL_RESERVED_ENTRY; + uint8_t i; + uint8_t ucStartIDX = 0, ucMaxIDX = 0; + struct WLAN_TABLE *prWtbl; + uint8_t ucRoleIdx = 0; + + ASSERT(prSta); + + if (!prSta->fgIsInUse) + ASSERT(FALSE); + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prSta->ucBssIndex); + ucRoleIdx = prP2pBssInfo->u4PrivateData; + + prWtbl = prAdapter->rWifiVar.arWtbl; + + ucStartIDX = 0; + ucMaxIDX = prAdapter->ucTxDefaultWlanIndex - 1; + + DBGLOG(RSN, INFO, "secPrivacySeekForEntry\n"); + + for (i = ucStartIDX; i <= ucMaxIDX; i++) { + if (prWtbl[i].ucUsed + && EQUAL_MAC_ADDR(prSta->aucMacAddr, prWtbl[i].aucMacAddr) + && prWtbl[i].ucPairwise + /* This function for ucPairwise only */) { + ucEntry = i; + DBGLOG(RSN, TRACE, + "[Wlan index]: Reuse entry #%d\n", i); + break; + } + } + + if (i == (ucMaxIDX + 1)) { + for (i = ucStartIDX; i <= ucMaxIDX; i++) { + if (prWtbl[i].ucUsed == FALSE) { + if (!secIsUsedByStaRecEntry(prAdapter, i)) { + ucEntry = i; + DBGLOG(RSN, TRACE, + "[Wlan index]: Assign entry #%d\n", i); + break; + } + } + } + } + + /* Save to the driver maintain table */ + if (ucEntry < prAdapter->ucTxDefaultWlanIndex) { + + prWtbl[ucEntry].ucUsed = TRUE; + prWtbl[ucEntry].ucBssIndex = prSta->ucBssIndex; + prWtbl[ucEntry].ucKeyId = 0xFF; + prWtbl[ucEntry].ucPairwise = 1; + COPY_MAC_ADDR(prWtbl[ucEntry].aucMacAddr, prSta->aucMacAddr); + prWtbl[ucEntry].ucStaIndex = prSta->ucIndex; + + prSta->ucWlanIndex = ucEntry; + + { + struct BSS_INFO *prBssInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, prSta->ucBssIndex); + /* for AP mode , if wep key exist, peer sta should also + * fgTransmitKeyExist + */ + if (IS_BSS_P2P(prBssInfo) + && kalP2PGetRole(prAdapter->prGlueInfo, + ucRoleIdx) == 2) { + if (prBssInfo->fgBcDefaultKeyExist + && + !(kalP2PGetCcmpCipher + (prAdapter->prGlueInfo, ucRoleIdx) + || + kalP2PGetTkipCipher(prAdapter->prGlueInfo, + ucRoleIdx))) { + prSta->fgTransmitKeyExist = TRUE; + prWtbl[ucEntry].ucKeyId = + prBssInfo->ucBcDefaultKeyIdx; + DBGLOG(RSN, INFO, + "peer sta set fgTransmitKeyExist\n"); + } + } + } + + DBGLOG(RSN, INFO, + "[Wlan index] BSS#%d keyid#%d P=%d use WlanIndex#%d STAIdx=%d " + MACSTR + " staType=%x\n", prSta->ucBssIndex, 0, + prWtbl[ucEntry].ucPairwise, ucEntry, + prSta->ucIndex, MAC2STR(prSta->aucMacAddr), + prSta->eStaType); +#if 1 /* DBG */ + secCheckWTBLAssign(prAdapter); +#endif + return TRUE; + } +#if DBG + secCheckWTBLAssign(prAdapter); +#endif + DBGLOG(RSN, WARN, + "[Wlan index] No more wlan table entry available!!!!\n"); + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used free a WLAN entry. + * + * \param[in] prAdapter Pointer to the Adapter structure + * \param[in] ucEntry the wlan table index to free + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void secPrivacyFreeForEntry(IN struct ADAPTER *prAdapter, IN uint8_t ucEntry) +{ + struct WLAN_TABLE *prWtbl; + + ASSERT(prAdapter); + + if (ucEntry >= WTBL_SIZE) + return; + + DBGLOG(RSN, TRACE, "secPrivacyFreeForEntry %d", ucEntry); + + prWtbl = prAdapter->rWifiVar.arWtbl; + + if (prWtbl[ucEntry].ucUsed) { + prWtbl[ucEntry].ucUsed = FALSE; + prWtbl[ucEntry].ucKeyId = 0xff; + prWtbl[ucEntry].ucBssIndex = prAdapter->ucHwBssIdNum + 1; + prWtbl[ucEntry].ucPairwise = 0; + kalMemZero(prWtbl[ucEntry].aucMacAddr, MAC_ADDR_LEN); + prWtbl[ucEntry].ucStaIndex = STA_REC_INDEX_NOT_FOUND; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used free a STA WLAN entry. + * + * \param[in] prAdapter Pointer to the Adapter structure + * \param[in] prStaRec the sta which want to free + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void secPrivacyFreeSta(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + uint32_t entry; + struct WLAN_TABLE *prWtbl; + + if (!prStaRec) + return; + + prWtbl = prAdapter->rWifiVar.arWtbl; + + for (entry = 0; entry < WTBL_SIZE; entry++) { + /* Consider GTK case !! */ + if (prWtbl[entry].ucUsed && + EQUAL_MAC_ADDR(prStaRec->aucMacAddr, + prWtbl[entry].aucMacAddr) + && prWtbl[entry].ucPairwise) { +#if 1 /* DBG */ + DBGLOG(RSN, INFO, "Free STA entry (%d)!\n", entry); +#endif + secPrivacyFreeForEntry(prAdapter, entry); + prStaRec->ucWlanIndex = WTBL_RESERVED_ENTRY; + /* prStaRec->ucBMCWlanIndex = WTBL_RESERVED_ENTRY; */ + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used for remove the BC entry of the BSS + * + * \param[in] prAdapter Pointer to the Adapter structure + * \param[in] ucBssIndex The BSS index + * + * \note + */ +/*----------------------------------------------------------------------------*/ +void secRemoveBssBcEntry(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo, IN u_int8_t fgRoam) +{ + int i; + struct CONNECTION_SETTINGS *prConnSettings = & + (prAdapter->rWifiVar.rConnSettings); + + if (!prBssInfo) + return; + + DBGLOG(RSN, INFO, "remove all the key related with BSS!"); + + if (fgRoam) { + if (IS_BSS_AIS(prBssInfo) && + prBssInfo->prStaRecOfAP + && (prConnSettings->eAuthMode >= AUTH_MODE_WPA && + prConnSettings->eAuthMode != AUTH_MODE_WPA_NONE)) { + + for (i = 0; i < MAX_KEY_NUM; i++) { + if (prBssInfo->ucBMCWlanIndexSUsed[i]) + secPrivacyFreeForEntry(prAdapter, + prBssInfo->ucBMCWlanIndexS[i]); +#if 0 + /* move to cfg delete cb function for sync. */ + prBssInfo->ucBMCWlanIndexSUsed[i] = FALSE; + prBssInfo->ucBMCWlanIndexS[i] = WTBL_RESERVED_ENTRY; +#endif + } + + prBssInfo->fgBcDefaultKeyExist = FALSE; + prBssInfo->ucBcDefaultKeyIdx = 0xff; + } + } else { + /* According to discussion, it's ok to change to + * reserved_entry here so that the entry is _NOT_ freed at all. + * In this way, the same BSS(ucBssIndex) could reuse the same + * entry next time in secPrivacySeekForBcEntry(), and we could + * see the following log: "[Wlan index]: Reuse entry ...". + */ + prBssInfo->ucBMCWlanIndex = WTBL_RESERVED_ENTRY; + secPrivacyFreeForEntry(prAdapter, prBssInfo->ucBMCWlanIndex); + +#if 0 + /* Not to remove BMC WTBL entries to sync with + * FW's behavior. + */ + for (i = 0; i < MAX_KEY_NUM; i++) { + if (prBssInfo->ucBMCWlanIndexSUsed[i]) + secPrivacyFreeForEntry(prAdapter, + prBssInfo->ucBMCWlanIndexS[i]); + } +#endif + for (i = 0; i < MAX_KEY_NUM; i++) { + if (prBssInfo->wepkeyUsed[i]) + secPrivacyFreeForEntry(prAdapter, + prBssInfo->wepkeyWlanIdx); + prBssInfo->wepkeyUsed[i] = FALSE; + } + prBssInfo->wepkeyWlanIdx = WTBL_RESERVED_ENTRY; + prBssInfo->fgBcDefaultKeyExist = FALSE; + prBssInfo->ucBcDefaultKeyIdx = 0xff; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used for adding the broadcast key used, to assign + * a wlan table entry for reserved the specific entry for these key for + * + * \param[in] prAdapter Pointer to the Adapter structure + * \param[in] ucBssIndex The BSS index + * \param[in] ucNetTypeIdx The Network index + * \param[in] ucAlg the entry assign related with algorithm + * \param[in] ucKeyId The key id + * \param[in] ucTxRx The Type of the key + * + * \return ucEntryIndex The entry to be used, WTBL_ALLOC_FAIL for allocation + * fail + * + * \note + */ +/*----------------------------------------------------------------------------*/ +uint8_t +secPrivacySeekForBcEntry(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, + IN uint8_t *pucAddr, IN uint8_t ucStaIdx, + IN uint8_t ucAlg, IN uint8_t ucKeyId) +{ + uint8_t ucEntry = WTBL_ALLOC_FAIL; + uint8_t ucStartIDX = 0, ucMaxIDX = 0; + uint8_t i; + u_int8_t fgCheckKeyId = TRUE; + struct WLAN_TABLE *prWtbl; + struct BSS_INFO *prBSSInfo = + GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + prWtbl = prAdapter->rWifiVar.arWtbl; + ASSERT(prAdapter); + ASSERT(pucAddr); + + if (ucAlg == CIPHER_SUITE_WPI || /* CIPHER_SUITE_GCM_WPI || */ + ucAlg == CIPHER_SUITE_WEP40 || + ucAlg == CIPHER_SUITE_WEP104 + || ucAlg == CIPHER_SUITE_WEP128 || ucAlg == CIPHER_SUITE_NONE) + fgCheckKeyId = FALSE; + + if (ucKeyId == 0xFF || ucAlg == CIPHER_SUITE_BIP) + fgCheckKeyId = FALSE; + + if (prBSSInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) + fgCheckKeyId = FALSE; + + if (prBSSInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE && + prBSSInfo->eNetworkType == NETWORK_TYPE_AIS) + fgCheckKeyId = FALSE; + + ucStartIDX = 0; + ucMaxIDX = prAdapter->ucTxDefaultWlanIndex - 1; + + DBGLOG(INIT, INFO, "secPrivacySeekForBcEntry\n"); + DBGLOG(INIT, INFO, "OpMode:%d, NetworkType:%d, CheckKeyId:%d\n", + prBSSInfo->eCurrentOPMode, prBSSInfo->eNetworkType, + fgCheckKeyId); + + for (i = ucStartIDX; i <= ucMaxIDX; i++) { + + if (prWtbl[i].ucUsed && !prWtbl[i].ucPairwise + && prWtbl[i].ucBssIndex == ucBssIndex) { + + if (!fgCheckKeyId) { + ucEntry = i; + DBGLOG(RSN, TRACE, + "[Wlan index]: Reuse entry #%d for open/wep/wpi\n", + i); + break; + } + + if (fgCheckKeyId && (prWtbl[i].ucKeyId == ucKeyId + || prWtbl[i].ucKeyId == 0xFF)) { + ucEntry = i; + DBGLOG(RSN, TRACE, + "[Wlan index]: Reuse entry #%d\n", i); + break; + } + } + } + + if (i == (ucMaxIDX + 1)) { + for (i = ucStartIDX; i <= ucMaxIDX; i++) { + if (prWtbl[i].ucUsed == FALSE) { + ucEntry = i; + DBGLOG(RSN, TRACE, + "[Wlan index]: Assign entry #%d\n", i); + break; + } + } + } + + if (ucEntry < prAdapter->ucTxDefaultWlanIndex) { + if (ucAlg != CIPHER_SUITE_BIP) { + prWtbl[ucEntry].ucUsed = TRUE; + prWtbl[ucEntry].ucKeyId = ucKeyId; + prWtbl[ucEntry].ucBssIndex = ucBssIndex; + prWtbl[ucEntry].ucPairwise = 0; + kalMemCopy(prWtbl[ucEntry].aucMacAddr, pucAddr, + MAC_ADDR_LEN); + prWtbl[ucEntry].ucStaIndex = ucStaIdx; + } else { + /* BIP no need to dump secCheckWTBLAssign */ + return ucEntry; + } + + DBGLOG(RSN, INFO, + "[Wlan index] BSS#%d keyid#%d P=%d use WlanIndex#%d STAIdx=%d " + MACSTR + "\n", ucBssIndex, ucKeyId, prWtbl[ucEntry].ucPairwise, + ucEntry, ucStaIdx, MAC2STR(pucAddr)); + + /* DBG */ + secCheckWTBLAssign(prAdapter); + + } else { + secCheckWTBLAssign(prAdapter); + DBGLOG(RSN, ERROR, + "[Wlan index] No more wlan entry available!!!!\n"); + } + + return ucEntry; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] prAdapter Pointer to the Adapter structure + * + * \return ucEntryIndex The entry to be used, WTBL_ALLOC_FAIL for allocation + * fail + * + * \note + */ +/*----------------------------------------------------------------------------*/ +u_int8_t secCheckWTBLAssign(IN struct ADAPTER *prAdapter) +{ + u_int8_t fgCheckFail = FALSE; + + secPrivacyDumpWTBL(prAdapter); + + /* AIS STA should just has max 2 entry */ + /* Max STA check */ + if (fgCheckFail) + ASSERT(FALSE); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Got the STA record index by wlan index + * + * \param[in] prAdapter Pointer to the Adapter structure + * \param[in] ucWlanIdx The Rx wlan index + * + * \return The STA record index, 0xff for invalid sta index + */ +/*----------------------------------------------------------------------------*/ +uint8_t secGetStaIdxByWlanIdx(struct ADAPTER *prAdapter, uint8_t ucWlanIdx) +{ + struct WLAN_TABLE *prWtbl; + + ASSERT(prAdapter); + + if (ucWlanIdx >= WTBL_SIZE) + return STA_REC_INDEX_NOT_FOUND; + + prWtbl = prAdapter->rWifiVar.arWtbl; + + /* DBGLOG(RSN, TRACE, ("secGetStaIdxByWlanIdx=%d "MACSTR" used=%d\n", + * ucWlanIdx, MAC2STR(prWtbl[ucWlanIdx].aucMacAddr), + * prWtbl[ucWlanIdx].ucUsed)); + */ + + if (prWtbl[ucWlanIdx].ucUsed) + return prWtbl[ucWlanIdx].ucStaIndex; + else + return STA_REC_INDEX_NOT_FOUND; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief At Sw wlan table, got the BSS index by wlan index + * + * \param[in] prAdapter Pointer to the Adapter structure + * \param[in] ucWlanIdx The Rx wlan index + * + * \return The BSS index, 0xff for invalid bss index + */ +/*----------------------------------------------------------------------------*/ +uint8_t secGetBssIdxByWlanIdx(struct ADAPTER *prAdapter, uint8_t ucWlanIdx) +{ + struct WLAN_TABLE *prWtbl; + + ASSERT(prAdapter); + + if (ucWlanIdx >= WTBL_SIZE) + return WTBL_RESERVED_ENTRY; + + prWtbl = prAdapter->rWifiVar.arWtbl; + + if (prWtbl[ucWlanIdx].ucUsed) + return prWtbl[ucWlanIdx].ucBssIndex; + else + return WTBL_RESERVED_ENTRY; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Got the STA record index by mac addr + * + * \param[in] prAdapter Pointer to the Adapter structure + * \param[in] pucMacAddress MAC Addr + * + * \return The STA record index, 0xff for invalid sta index + */ +/*----------------------------------------------------------------------------*/ +uint8_t secLookupStaRecIndexFromTA( + struct ADAPTER *prAdapter, uint8_t *pucMacAddress) +{ + int i; + struct WLAN_TABLE *prWtbl; + + ASSERT(prAdapter); + prWtbl = prAdapter->rWifiVar.arWtbl; + + for (i = 0; i < WTBL_SIZE; i++) { + if (prWtbl[i].ucUsed) { + if (EQUAL_MAC_ADDR(pucMacAddress, prWtbl[i].aucMacAddr) + && prWtbl[i].ucPairwise) + return prWtbl[i].ucStaIndex; + } + } + + return STA_REC_INDEX_NOT_FOUND; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] prAdapter Pointer to the Adapter structure + * + * \note + */ +/*----------------------------------------------------------------------------*/ +void secPrivacyDumpWTBL(IN struct ADAPTER *prAdapter) +{ + struct WLAN_TABLE *prWtbl; + uint8_t i; + + prWtbl = prAdapter->rWifiVar.arWtbl; + + DBGLOG(RSN, INFO, "The Wlan index\n"); + + for (i = 0; i < WTBL_SIZE; i++) { + if (prWtbl[i].ucUsed) + DBGLOG(RSN, TRACE, + "#%d Used=%d BSSIdx=%d keyid=%d P=%d STA=%d Addr=" + MACSTR "\n", i, prWtbl[i].ucUsed, + prWtbl[i].ucBssIndex, prWtbl[i].ucKeyId, + prWtbl[i].ucPairwise, prWtbl[i].ucStaIndex, + MAC2STR(prWtbl[i].aucMacAddr)); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Assin the wlan table with the join AP info + * + * \param[in] prAdapter Pointer to the Adapter structure + * + * \note + */ +/*----------------------------------------------------------------------------*/ +void secPostUpdateAddr(IN struct ADAPTER *prAdapter, + IN struct BSS_INFO *prBssInfo) +{ + struct CONNECTION_SETTINGS *prConnSettings = & + (prAdapter->rWifiVar.rConnSettings); + struct WLAN_TABLE *prWtbl; + + if (IS_BSS_AIS(prBssInfo) && prBssInfo->prStaRecOfAP) { + + if (prConnSettings->eEncStatus == ENUM_ENCRYPTION1_ENABLED) { + + if (prBssInfo->fgBcDefaultKeyExist) { + + prWtbl = + &prAdapter->rWifiVar. + arWtbl[prBssInfo->wepkeyWlanIdx]; + + kalMemCopy(prWtbl->aucMacAddr, + prBssInfo->prStaRecOfAP->aucMacAddr, + MAC_ADDR_LEN); + prWtbl->ucStaIndex = + prBssInfo->prStaRecOfAP->ucIndex; + DBGLOG(RSN, INFO, + "secPostUpdateAddr at [%d] " MACSTR + "= STA Index=%d\n", + prBssInfo->wepkeyWlanIdx, + MAC2STR(prWtbl->aucMacAddr), + prBssInfo->prStaRecOfAP->ucIndex); + + /* Update the wlan table of the prStaRecOfAP */ + prWtbl = + &prAdapter->rWifiVar.arWtbl + [prBssInfo->prStaRecOfAP->ucWlanIndex]; + prWtbl->ucKeyId = prBssInfo->ucBcDefaultKeyIdx; + prBssInfo->prStaRecOfAP->fgTransmitKeyExist = + TRUE; + } + } + if (prConnSettings->eEncStatus == ENUM_ENCRYPTION_DISABLED) { + prWtbl = + &prAdapter->rWifiVar. + arWtbl[prBssInfo->ucBMCWlanIndex]; + + kalMemCopy(prWtbl->aucMacAddr, + prBssInfo->prStaRecOfAP->aucMacAddr, + MAC_ADDR_LEN); + prWtbl->ucStaIndex = prBssInfo->prStaRecOfAP->ucIndex; + DBGLOG(RSN, INFO, "secPostUpdateAddr at [%d] " MACSTR + "= STA Index=%d\n", + prBssInfo->ucBMCWlanIndex, + MAC2STR(prWtbl->aucMacAddr), + prBssInfo->prStaRecOfAP->ucIndex); + } + } +} + +/* return the type of Eapol frame. */ +enum ENUM_EAPOL_KEY_TYPE_T secGetEapolKeyType(uint8_t *pucPkt) +{ + uint8_t *pucEthBody = NULL; + uint8_t ucEapolType; + uint16_t u2EtherTypeLen; + uint8_t ucEthTypeLenOffset = ETHER_HEADER_LEN - ETHER_TYPE_LEN; + uint16_t u2KeyInfo = 0; + + do { + ASSERT_BREAK(pucPkt != NULL); + WLAN_GET_FIELD_BE16(&pucPkt[ucEthTypeLenOffset], + &u2EtherTypeLen); + if (u2EtherTypeLen == ETH_P_VLAN) { + ucEthTypeLenOffset += ETH_802_1Q_HEADER_LEN; + WLAN_GET_FIELD_BE16(&pucPkt[ucEthTypeLenOffset], + &u2EtherTypeLen); + } + if (u2EtherTypeLen != ETH_P_1X) + break; + pucEthBody = &pucPkt[ucEthTypeLenOffset + ETHER_TYPE_LEN]; + ucEapolType = pucEthBody[1]; + if (ucEapolType != 3) /* eapol key type */ + break; + u2KeyInfo = *((uint16_t *) (&pucEthBody[5])); + switch (u2KeyInfo) { + case 0x8a00: + return EAPOL_KEY_1_OF_4; + case 0x0a01: + return EAPOL_KEY_2_OF_4; + case 0xca13: + return EAPOL_KEY_3_OF_4; + case 0x0a03: + return EAPOL_KEY_4_OF_4; + } + } while (FALSE); + + return EAPOL_KEY_NOT_KEY; +} + +void secHandleRxEapolPacket(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prRetSwRfb, + IN struct STA_RECORD *prStaRec) +{ + struct BSS_INFO *prBssInfo = (struct BSS_INFO *)NULL; + + do { + if (!prStaRec) + break; + if (prRetSwRfb->u2PacketLen <= ETHER_HEADER_LEN) + break; + prBssInfo = prAdapter->aprBssInfo[prStaRec->ucBssIndex]; + if (secGetEapolKeyType((uint8_t *) prRetSwRfb->pvHeader) != + EAPOL_KEY_3_OF_4) + break; + prBssInfo->eKeyAction = SEC_QUEUE_KEY_COMMAND; + } while (FALSE); +} + +void secHandleEapolTxStatus(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + struct BSS_INFO *prBssInfo = (struct BSS_INFO *)NULL; + + do { + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + break; + if (prMsduInfo->eEapolKeyType != EAPOL_KEY_4_OF_4) + break; + if (rTxDoneStatus == TX_RESULT_SUCCESS) + prBssInfo->eKeyAction = SEC_TX_KEY_COMMAND; + else + prBssInfo->eKeyAction = SEC_DROP_KEY_COMMAND; + kalSetEvent(prAdapter->prGlueInfo); + } while (FALSE); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/qosmap.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/qosmap.c new file mode 100644 index 0000000000000..2381ef26f4ef1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/qosmap.c @@ -0,0 +1,300 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "qosmap.c" + * \brief This file including the qosmap related function. + * + * This file provided the macros and functions library support for the + * protocol layer qosmap related function. + * + */ + +/******************************************************************************* + * C O M P I L E 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_PPR2 + +/******************************************************************************* + * 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 process the qos category action frame. + * + * + * \note + * Called by: Handle Rx mgmt request + */ +/*----------------------------------------------------------------------------*/ +static struct _QOS_MAP_SET *QosMapSetMalloc(IN uint8_t dscpExcNum) +{ + if (dscpExcNum) + return (struct _QOS_MAP_SET *) + kalMemAlloc((sizeof(struct _QOS_MAP_SET) + + ((dscpExcNum - 1) * + sizeof(struct _DSCP_EXCEPTION))), + VIR_MEM_TYPE); + else + return (struct _QOS_MAP_SET *) + kalMemAlloc(sizeof(struct _QOS_MAP_SET), VIR_MEM_TYPE); + +} + +static void QosMapSetFree(IN struct STA_RECORD *prStaRec) +{ + if (prStaRec && prStaRec->qosMapSet) { + if (prStaRec->qosMapSet->dscpExceptionNum) { + kalMemFree(prStaRec->qosMapSet, VIR_MEM_TYPE, + (sizeof(struct _QOS_MAP_SET) + + ((prStaRec->qosMapSet->dscpExceptionNum - 1) * + sizeof(struct _DSCP_EXCEPTION)))); + } else + kalMemFree(prStaRec->qosMapSet, + VIR_MEM_TYPE, sizeof(struct _QOS_MAP_SET)); + } +} + +void QosMapSetRelease(IN struct STA_RECORD *prStaRec) +{ + QosMapSetFree(prStaRec); +} + +void handleQosMapConf(IN struct ADAPTER *prAdapter, IN struct SW_RFB *prSwRfb) +{ + struct WLAN_ACTION_FRAME *prRxFrame; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxFrame = (struct WLAN_ACTION_FRAME *) prSwRfb->pvHeader; + + switch (prRxFrame->ucAction) { + case ACTION_ADDTS_REQ: + case ACTION_ADDTS_RSP: + case ACTION_SCHEDULE: + log_dbg(INIT, INFO, "qos action frame received, action: %d\n", + prRxFrame->ucAction); + break; + case ACTION_QOS_MAP_CONFIGURE: + qosHandleQosMapConfigure(prAdapter, prSwRfb); + log_dbg(INIT, INFO, "qos map configure frame received, action: %d\n", + prRxFrame->ucAction); + break; + default: + log_dbg(INIT, INFO, "qos action frame: %d, try to send to supplicant\n", + prRxFrame->ucAction); + break; + } +} + +int qosHandleQosMapConfigure(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct _ACTION_QOS_MAP_CONFIGURE_FRAME *prRxFrame = NULL; + struct STA_RECORD *prStaRec; + + prRxFrame = + (struct _ACTION_QOS_MAP_CONFIGURE_FRAME *) prSwRfb->pvHeader; + if (!prRxFrame) + return -1; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if ((!prStaRec) || (!prStaRec->fgIsInUse)) + return -1; + + log_dbg(INIT, INFO, + "IEEE 802.11: Received Qos Map Configure Frame from " MACSTR "\n", + MAC2STR(prStaRec->aucMacAddr)); + + if (prStaRec->qosMapSet) + QosMapSetFree(prStaRec); + prStaRec->qosMapSet = + qosParseQosMapSet(prAdapter, prRxFrame->qosMapSet); + + return 0; +} + +struct _QOS_MAP_SET *qosParseQosMapSet(IN struct ADAPTER *prAdapter, + IN uint8_t *qosMapSet) +{ + uint8_t dscpExcNum = 0; + struct _QOS_MAP_SET *prQos = NULL; + int i, j = 0; + uint8_t *tempq = qosMapSet + 2; + + if (IE_ID(qosMapSet) != ELEM_ID_QOS_MAP_SET) { + DBGLOG(INIT, WARN, + "Wrong QosMapSet IE ID: %d\n", IE_ID(qosMapSet)); + return NULL; + } + if ((IE_LEN(qosMapSet) < 16) || (IE_LEN(qosMapSet) > 58)) { + DBGLOG(INIT, WARN, + "Error in QosMapSet IE len: %d\n", IE_LEN(qosMapSet)); + return NULL; + } + dscpExcNum = (IE_LEN(qosMapSet) - 16) / 2; + + prQos = QosMapSetMalloc(dscpExcNum); + if (!prQos) { + DBGLOG(INIT, WARN, "can't alloc qosmap\n"); + return NULL; + } + + prQos->dscpExceptionNum = dscpExcNum; + for (i = 0; i < dscpExcNum; i++) { + prQos->dscpException[i].dscp = *tempq; + tempq++; + prQos->dscpException[i].userPriority = *tempq; + tempq++; + } + for (j = 0; j < 8; j++) { + prQos->dscpRange[j].lDscp = *tempq; + tempq++; + prQos->dscpRange[j].hDscp = *tempq; + tempq++; + if (prQos->dscpRange[j].hDscp < prQos->dscpRange[j].lDscp) + log_dbg(INIT, WARN, "CHECK: dscp h val should larger than dscp l val, i: %d\n", + j); + /* TODO: Here skip the overlap check */ + } + /* + * kalMemCopy(prQos->dscpException, + * qosMapSet + 2, dscpExcNum * 2); + * kalMemCopy(prQos->dscpRange, + * qosMapSet + 2 * dscpExcNum + 2, 16); + */ + + DBGLOG(INIT, INFO, "QosMapSet DSCP Exception number: %d\n", dscpExcNum); + + return prQos; +} + +uint8_t getUpFromDscp(IN struct GLUE_INFO *prGlueInfo, IN int type, IN int dscp) +{ + struct BSS_INFO *prAisBssInfo; + struct STA_RECORD *prStaRec; + + int i, j = 0; + + prAisBssInfo = prGlueInfo->prAdapter->prAisBssInfo; + if (prAisBssInfo) + prStaRec = prAisBssInfo->prStaRecOfAP; + else { + /* DBGLOG(INIT, WARN, "qosmap type: %d\n", type); */ + return 0xFF; + } + + prStaRec = prAisBssInfo->prStaRecOfAP; + + if (prStaRec && prStaRec->qosMapSet) { + for (i = 0; i < prStaRec->qosMapSet->dscpExceptionNum; i++) { + if (dscp == prStaRec->qosMapSet->dscpException[i].dscp) + return prStaRec->qosMapSet->dscpException[i]. + userPriority; + } + for (j = 0; j < 8; j++) { + if (prStaRec->qosMapSet->dscpRange[j].lDscp == 255 && + prStaRec->qosMapSet->dscpRange[j].hDscp == 255) + continue; + if (dscp >= prStaRec->qosMapSet->dscpRange[j].lDscp && + dscp >= prStaRec->qosMapSet->dscpRange[j].hDscp) + return j; + } + /* qosMapSet info error */ + DBGLOG(INIT, WARN, "WRONG QosMapSet info, cant get UP\n"); + return 0xFF; + } + return 0xFF; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/rate.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/rate.c new file mode 100644 index 0000000000000..c2f957299e0f5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/rate.c @@ -0,0 +1,375 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + +/******************************************************************************* + * C O M P I L E 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 uint8_t 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_VHT_PHY, /* RATE_VHT_PHY_INDEX */ + RATE_HT_PHY /* RATE_HT_PHY_INDEX */ +}; + +static const uint8_t aucDefaultAckCtsRateIndex[RATE_NUM_SW] = { + RATE_1M_SW_INDEX, /* RATE_1M_SW_INDEX = 0 */ + RATE_2M_SW_INDEX, /* RATE_2M_SW_INDEX */ + RATE_5_5M_SW_INDEX, /* RATE_5_5M_SW_INDEX */ + RATE_11M_SW_INDEX, /* RATE_11M_SW_INDEX */ + RATE_1M_SW_INDEX, /* RATE_22M_SW_INDEX - Not supported */ + RATE_1M_SW_INDEX, /* RATE_33M_SW_INDEX - Not supported */ + RATE_6M_SW_INDEX, /* RATE_6M_SW_INDEX */ + RATE_6M_SW_INDEX, /* RATE_9M_SW_INDEX */ + RATE_12M_SW_INDEX, /* RATE_12M_SW_INDEX */ + RATE_12M_SW_INDEX, /* RATE_18M_SW_INDEX */ + RATE_24M_SW_INDEX, /* RATE_24M_SW_INDEX */ + RATE_24M_SW_INDEX, /* RATE_36M_SW_INDEX */ + RATE_24M_SW_INDEX, /* RATE_48M_SW_INDEX */ + RATE_24M_SW_INDEX /* RATE_54M_SW_INDEX */ +}; + +const u_int8_t afgIsOFDMRate[RATE_NUM_SW] = { + 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 struct IE_SUPPORTED_RATE *prIeSupportedRate, + IN struct IE_EXT_SUPPORTED_RATE *prIeExtSupportedRate, + OUT uint16_t *pu2OperationalRateSet, + OUT uint16_t *pu2BSSBasicRateSet, + OUT u_int8_t *pfgIsUnknownBSSBasicRate) +{ + uint16_t u2OperationalRateSet = 0; + uint16_t u2BSSBasicRateSet = 0; + u_int8_t fgIsUnknownBSSBasicRate = FALSE; + uint8_t ucRate; + uint32_t 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_SW); + + 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(uint8_t); + j++) { + if (ucRate == aucDataRate[j]) { + u2OperationalRateSet |= BIT(j); + + if (prIeSupportedRate->aucSupportedRates + [i] & RATE_BASIC_BIT) + u2BSSBasicRateSet |= BIT(j); + + break; + } + } + + if ((j == sizeof(aucDataRate) / sizeof(uint8_t)) && + (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(uint8_t); + j++) { + if (ucRate == aucDataRate[j]) { + u2OperationalRateSet |= BIT(j); + + if (prIeExtSupportedRate-> + aucExtSupportedRates[i] + & RATE_BASIC_BIT) + u2BSSBasicRateSet |= BIT(j); + + break; + } + } + + if ((j == sizeof(aucDataRate) / sizeof(uint8_t)) && + (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 uint16_t u2OperationalRateSet, + IN uint16_t u2BSSBasicRateSet, + OUT uint8_t *pucDataRates, + OUT uint8_t *pucDataRatesLen) +{ + uint32_t i, j; + + ASSERT(pucDataRates); + ASSERT(pucDataRatesLen); + + ASSERT(u2BSSBasicRateSet == (u2OperationalRateSet & u2BSSBasicRateSet)); + + for (i = RATE_1M_SW_INDEX, j = 0; i < RATE_NUM_SW; i++) { + if (u2OperationalRateSet & BIT(i)) { + + *(pucDataRates + j) = aucDataRate[i]; + + if (u2BSSBasicRateSet & BIT(i)) + *(pucDataRates + j) |= RATE_BASIC_BIT; + + j++; + } + } + + *pucDataRatesLen = (uint8_t) 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rateGetHighestRateIndexFromRateSet(IN uint16_t u2RateSet, + OUT uint8_t *pucHighestRateIndex) +{ + int32_t i; + + ASSERT(pucHighestRateIndex); + + for (i = RATE_54M_SW_INDEX; i >= RATE_1M_SW_INDEX; i--) { + if (u2RateSet & BIT(i)) { + *pucHighestRateIndex = (uint8_t) 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rateGetLowestRateIndexFromRateSet(IN uint16_t u2RateSet, + OUT uint8_t *pucLowestRateIndex) +{ + uint32_t i; + + ASSERT(pucLowestRateIndex); + + for (i = RATE_1M_SW_INDEX; i <= RATE_54M_SW_INDEX; i++) { + if (u2RateSet & BIT(i)) { + *pucLowestRateIndex = (uint8_t) i; + return TRUE; + } + } + + return FALSE; + +} /* end of rateGetLowestRateIndexFromRateSet() */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/reg_rule.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/reg_rule.c new file mode 100644 index 0000000000000..9e14e7eaa0233 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/reg_rule.c @@ -0,0 +1,388 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/******************************************************************************* + * C O M P I L E 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_SINGLE_SKU == 1) +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) +#include "rlm_domain.h" + +#if 0 +/** + * enum ieee80211_channel_flags - channel flags + * + * Channel flags set by the regulatory control code. + * + * @IEEE80211_CHAN_DISABLED: This channel is disabled. + * @IEEE80211_CHAN_NO_IR: do not initiate radiation, this includes + * sending probe requests or beaconing. + * @IEEE80211_CHAN_RADAR: Radar detection is required on this channel. + * @IEEE80211_CHAN_NO_HT40PLUS: extension channel above this channel + * is not permitted. + * @IEEE80211_CHAN_NO_HT40MINUS: extension channel below this channel + * is not permitted. + * @IEEE80211_CHAN_NO_OFDM: OFDM is not allowed on this channel. + * @IEEE80211_CHAN_NO_80MHZ: If the driver supports 80 MHz on the band, + * this flag indicates that an 80 MHz channel cannot use this + * channel as the control or any of the secondary channels. + * This may be due to the driver or due to regulatory bandwidth + * restrictions. + * @IEEE80211_CHAN_NO_160MHZ: If the driver supports 160 MHz on the band, + * this flag indicates that an 160 MHz channel cannot use this + * channel as the control or any of the secondary channels. + * This may be due to the driver or due to regulatory bandwidth + * restrictions. + * @IEEE80211_CHAN_INDOOR_ONLY: see %NL80211_FREQUENCY_ATTR_INDOOR_ONLY + * @IEEE80211_CHAN_GO_CONCURRENT: see %NL80211_FREQUENCY_ATTR_GO_CONCURRENT + * @IEEE80211_CHAN_NO_20MHZ: 20 MHz bandwidth is not permitted + * on this channel. + * @IEEE80211_CHAN_NO_10MHZ: 10 MHz bandwidth is not permitted + * on this channel. + * + */ +enum ieee80211_channel_flags { + IEEE80211_CHAN_DISABLED = 1<<0, + IEEE80211_CHAN_NO_IR = 1<<1, + /* hole at 1<<2 */ + IEEE80211_CHAN_RADAR = 1<<3, + IEEE80211_CHAN_NO_HT40PLUS = 1<<4, + IEEE80211_CHAN_NO_HT40MINUS = 1<<5, + IEEE80211_CHAN_NO_OFDM = 1<<6, + IEEE80211_CHAN_NO_80MHZ = 1<<7, + IEEE80211_CHAN_NO_160MHZ = 1<<8, + IEEE80211_CHAN_INDOOR_ONLY = 1<<9, + IEEE80211_CHAN_GO_CONCURRENT = 1<<10, + IEEE80211_CHAN_NO_20MHZ = 1<<11, + IEEE80211_CHAN_NO_10MHZ = 1<<12, +}; + +#define IEEE80211_CHAN_NO_HT40 \ + (IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS) + + +struct ieee80211_freq_range { + u32 start_freq_khz; + u32 end_freq_khz; + u32 max_bandwidth_khz; +}; + +struct ieee80211_power_rule { + u32 max_antenna_gain; + u32 max_eirp; +}; + +/** + * enum reg_flags (the same as nl80211_reg_rule_flags) - regulatory rule flags + * + * @NL80211_RRF_NO_OFDM: OFDM modulation not allowed + * @NL80211_RRF_NO_CCK: CCK modulation not allowed + * @NL80211_RRF_NO_INDOOR: indoor operation not allowed + * @NL80211_RRF_NO_OUTDOOR: outdoor operation not allowed + * @NL80211_RRF_DFS: DFS support is required to be used + * @NL80211_RRF_PTP_ONLY: this is only for Point To Point links + * @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links + * @NL80211_RRF_NO_IR: no mechanisms that initiate radiation are allowed, + * this includes probe requests or modes of operation that + * require beaconing. + * @NL80211_RRF_AUTO_BW: maximum available bandwidth should be calculated + * base on contiguous rules and wider channels will be + * allowed to cross multiple contiguous/overlapping + * frequency ranges. + * @NL80211_RRF_IR_CONCURRENT: See &NL80211_FREQUENCY_ATTR_IR_CONCURRENT + * @NL80211_RRF_NO_HT40MINUS: channels can't be used in HT40- operation + * @NL80211_RRF_NO_HT40PLUS: channels can't be used in HT40+ operation + * @NL80211_RRF_NO_80MHZ: 80MHz operation not allowed + * @NL80211_RRF_NO_160MHZ: 160MHz operation not allowed + */ +enum reg_flags { + NL80211_RRF_NO_OFDM = 1<<0, + NL80211_RRF_NO_CCK = 1<<1, + NL80211_RRF_NO_INDOOR = 1<<2, + NL80211_RRF_NO_OUTDOOR = 1<<3, + NL80211_RRF_DFS = 1<<4, + NL80211_RRF_PTP_ONLY = 1<<5, + NL80211_RRF_PTMP_ONLY = 1<<6, + NL80211_RRF_NO_IR = 1<<7, + NL80211_RRF_NO_IBSS = 1<<8, + NL80211_RRF_AUTO_BW = 1<<11, + NL80211_RRF_IR_CONCURRENT = 1<<12, + NL80211_RRF_NO_HT40MINUS = 1<<13, + NL80211_RRF_NO_HT40PLUS = 1<<14, + NL80211_RRF_NO_80MHZ = 1<<15, + NL80211_RRF_NO_160MHZ = 1<<16, +}; + +#define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR +#define NL80211_RRF_NO_IBSS NL80211_RRF_NO_IR +#define NL80211_RRF_NO_IR NL80211_RRF_NO_IR +#define NL80211_RRF_NO_HT40 (NL80211_RRF_NO_HT40MINUS | \ + NL80211_RRF_NO_HT40PLUS) +#define NL80211_RRF_GO_CONCURRENT NL80211_RRF_IR_CONCURRENT + +/* For backport compatibility with older userspace */ +#define NL80211_RRF_NO_IR_ALL (NL80211_RRF_NO_IR | \ + __NL80211_RRF_NO_IBSS) + +struct ieee80211_reg_rule { + struct ieee80211_freq_range freq_range; + struct ieee80211_power_rule power_rule; + u32 reg_flags; /*enum reg_flags*/ + u32 dfs_cac_ms; +}; + +#define MAX_NUMER_REG_RULES 6 + +struct ieee80211_regdomain { + char alpha2[3]; + u32 n_reg_rules; + enum nl80211_dfs_regions dfs_region; + struct ieee80211_reg_rule reg_rules[MAX_NUMER_REG_RULES]; +}; + + +#define MHZ_TO_KHZ(freq) ((freq) * 1000) +#define KHZ_TO_MHZ(freq) ((freq) / 1000) +#define DBI_TO_MBI(gain) ((gain) * 100) +#define MBI_TO_DBI(gain) ((gain) / 100) +#define DBM_TO_MBM(gain) ((gain) * 100) +#define MBM_TO_DBM(gain) ((gain) / 100) + +#define REG_RULE_EXT(start, end, bw, gain, eirp, dfs_cac, reg_flags) \ +{ \ + .freq_range.start_freq_khz = MHZ_TO_KHZ(start), \ + .freq_range.end_freq_khz = MHZ_TO_KHZ(end), \ + .freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw), \ + .power_rule.max_eirp = DBM_TO_MBM(eirp), \ + .flags = reg_flags, \ + .dfs_cac_ms = dfs_cac, \ +} + +#define REG_RULE(start, end, bw, gain, eirp, reg_flags) \ +{ \ + .freq_range.start_freq_khz = MHZ_TO_KHZ(start), \ + .freq_range.end_freq_khz = MHZ_TO_KHZ(end), \ + .freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw), \ + .power_rule.max_antenna_gain = DBI_TO_MBI(gain),\ + .power_rule.max_eirp = DBM_TO_MBM(eirp), \ + .flags = reg_flags, \ +} +#endif + +/*************************************************** + * Here to describe the regulatory rules of yours. + *************************************************** + */ + +/* + * Step1. Decclare struct ieee80211_regdomain + */ +const struct ieee80211_regdomain regdom_us01 = { + .n_reg_rules = 6, + .reg_rules = { + /* channels 1..11 */ + REG_RULE_LIGHT(2412-10, 2462+10, 40, 0), + /* channels 36..48 */ + REG_RULE_LIGHT(5180-10, 5240+10, 40, 0), + /* channels 56..64 */ + REG_RULE_LIGHT(5260-10, 5320+10, 40, KAL_RRF_DFS), + /* channels 100..118 */ + REG_RULE_LIGHT(5500-10, 5590+10, 40, KAL_RRF_DFS), + /* channels 132..140 */ + REG_RULE_LIGHT(5660-10, 5700+10, 40, KAL_RRF_DFS), + /* channels 149..165 */ + REG_RULE_LIGHT(5745-10, 5825+10, 40, 0) } +}; + +const struct ieee80211_regdomain regdom_us = { + .n_reg_rules = 5, + .dfs_region = NL80211_DFS_FCC, + .reg_rules = { + /* channels 1..11 */ + REG_RULE_LIGHT(2412-10, 2462+10, 40, 0), + /* channels 36..48 */ + REG_RULE_LIGHT(5180-10, 5240+10, 80, KAL_RRF_AUTO_BW), + /* channels 52..64 */ + REG_RULE_LIGHT(5260-10, 5320+10, 80, KAL_RRF_DFS | KAL_RRF_AUTO_BW), + /* channels 100..140 */ + REG_RULE_LIGHT(5500-10, 5720+10, 160, KAL_RRF_DFS), + /* channels 149..165 */ + REG_RULE_LIGHT(5745-10, 5825+10, 80, 0) } +}; + +const struct ieee80211_regdomain regdom_cn = { + .n_reg_rules = 4, + .dfs_region = NL80211_DFS_FCC, + .reg_rules = { + /* channels 1..13 */ + REG_RULE_LIGHT(2412-10, 2472+10, 40, 0), + /* channels 36..48 */ + REG_RULE_LIGHT(5180-10, 5240+10, 80, KAL_RRF_AUTO_BW), + /* channels 52..64 */ + REG_RULE_LIGHT(5260-10, 5320+10, 80, KAL_RRF_DFS | KAL_RRF_AUTO_BW), + /* channels 149..165 */ + REG_RULE_LIGHT(5745-10, 5825+10, 80, 0) } +}; + +const struct ieee80211_regdomain regdom_cz_nl = { + .n_reg_rules = 5, + .reg_rules = { + /* channels 1..11 */ + REG_RULE_LIGHT(2412-10, 2462+10, 40, 0), + /* channels 12,13 */ + REG_RULE_LIGHT(2467-10, 2472+10, 40, 0), + /* channels 36..48 */ + REG_RULE_LIGHT(5180-10, 5240+10, 80, 0), + /* channels 52..64 */ + REG_RULE_LIGHT(5260-10, 5320+10, 80, KAL_RRF_DFS), + /* channels 100..140 */ + REG_RULE_LIGHT(5500-10, 5700+10, 160, KAL_RRF_DFS) } +}; + +const struct ieee80211_regdomain regdom_jp = { + .n_reg_rules = 7, + .dfs_region = NL80211_DFS_JP, + .reg_rules = { + /* channels 1..13 */ + REG_RULE_LIGHT(2412-10, 2472+10, 40, 0), + /* channels 14 */ + REG_RULE_LIGHT(2484-10, 2484+10, 20, KAL_RRF_NO_OFDM), + /* channels 184..196 */ + REG_RULE_LIGHT(4920-10, 4980+10, 40, 0), + /* channels 8..16 */ + REG_RULE_LIGHT(5040-10, 5080+10, 40, 0), + /* channels 36..48 */ + REG_RULE_LIGHT(5180-10, 5240+10, 80, KAL_RRF_AUTO_BW), + /* channels 52..64 */ + REG_RULE_LIGHT(5260-10, 5320+10, 80, KAL_RRF_DFS | KAL_RRF_AUTO_BW), + /* channels 100..140 */ + REG_RULE_LIGHT(5500-10, 5700+10, 160, KAL_RRF_DFS) } +}; + +const struct ieee80211_regdomain regdom_tr = { + .n_reg_rules = 4, + .dfs_region = NL80211_DFS_ETSI, + .reg_rules = { + /* channels 1..13 */ + REG_RULE_LIGHT(2412-10, 2472+10, 40, 0), + /* channels 36..48 */ + REG_RULE_LIGHT(5180-10, 5240+10, 80, KAL_RRF_AUTO_BW), + /* channels 52..64 */ + REG_RULE_LIGHT(5260-10, 5320+10, 80, KAL_RRF_DFS | KAL_RRF_AUTO_BW), + /* channels 100..140 */ + REG_RULE_LIGHT(5500-10, 5700+10, 160, KAL_RRF_DFS) } +}; + +/* + * Step2. Decclare struct mtk_regdomain + */ +const struct mtk_regdomain my_regdom_us01 = { + .country_code = "US01", + .prRegdRules = ®dom_us01 +}; + +const struct mtk_regdomain my_regdom_us = { + .country_code = "US", + .prRegdRules = ®dom_us +}; + +const struct mtk_regdomain my_regdom_cn = { + .country_code = "CN", + .prRegdRules = ®dom_cn +}; + +const struct mtk_regdomain my_regdom_nl = { + .country_code = "NL", + .prRegdRules = ®dom_cz_nl +}; + +const struct mtk_regdomain my_regdom_cz = { + .country_code = "CZ", + .prRegdRules = ®dom_cz_nl +}; + +const struct mtk_regdomain my_regdom_jp = { + .country_code = "JP", + .prRegdRules = ®dom_jp +}; + +const struct mtk_regdomain my_regdom_tr = { + .country_code = "TR", + .prRegdRules = ®dom_tr +}; + +/* + * Step3. Register to table + */ +const struct mtk_regdomain *g_prRegRuleTable[] = { + &my_regdom_us01, + &my_regdom_us, + &my_regdom_cn, + &my_regdom_nl, + &my_regdom_cz, + &my_regdom_jp, + &my_regdom_tr, + NULL /* this NULL SHOULD be at the end of the array */ +}; + +#endif +#endif + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/rlm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/rlm.c new file mode 100644 index 0000000000000..8d393c437af67 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/rlm.c @@ -0,0 +1,7822 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rlm.c#3 + */ + +/*! \file "rlm.c" + * \brief + * + */ + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/* Retry limit of sending operation notification frame */ +#define OPERATION_NOTICATION_TX_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 + ******************************************************************************* + */ +/* +** Should Not Force to BW 20 after Channel Switch. +** Enable for DFS Certification +*/ +#ifdef CFG_DFS_CHSW_FORCE_BW20 +u_int8_t g_fgHasChannelSwitchIE = FALSE; +#endif +u_int8_t g_fgHasStopTx = FALSE; +u_int8_t g_fgFowardBcn2Supplicant = FALSE; + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +struct RLM_CAL_RESULT_ALL_V2 g_rBackupCalDataAllV2; +#endif + +struct TIMER rBeaconReqTimer; + +struct REF_TSF { + uint32_t au4Tsf[2]; + OS_SYSTIME rTime; +}; +static struct REF_TSF rTsf; +/******************************************************************************* + * M A 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(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct MSDU_INFO *prMsduInfo); + +static void rlmFillExtCapIE(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct MSDU_INFO *prMsduInfo); + +static void rlmFillHtOpIE(struct ADAPTER *prAdapter, struct BSS_INFO *prBssInfo, + struct MSDU_INFO *prMsduInfo); + +static uint8_t rlmRecIeInfoForClient(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, uint8_t *pucIE, + uint16_t u2IELength); + +static u_int8_t rlmRecBcnFromNeighborForClient(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct SW_RFB *prSwRfb, + uint8_t *pucIE, + uint16_t u2IELength); + +static u_int8_t rlmRecBcnInfoForClient(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct SW_RFB *prSwRfb, uint8_t *pucIE, + uint16_t u2IELength); + +static void rlmBssReset(struct ADAPTER *prAdapter, struct BSS_INFO *prBssInfo); + +#if CFG_SUPPORT_802_11AC +static void rlmFillVhtCapIE(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct MSDU_INFO *prMsduInfo); +static void rlmFillVhtOpNotificationIE(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct MSDU_INFO *prMsduInfo, + u_int8_t fgIsMaxCap); + +#endif + +/* Operating BW/Nss change and notification */ +static void rlmOpModeTxDoneHandler(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + uint8_t ucOpChangeType, + u_int8_t fgIsSuccess); +static void rlmChangeOwnOpInfo(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo); +static void rlmCompleteOpModeChange(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + u_int8_t fgIsSuccess); +static void rlmRollbackOpChangeParam(struct BSS_INFO *prBssInfo, + u_int8_t fgIsRollbackBw, + u_int8_t fgIsRollbackNss); +static uint8_t rlmGetOpModeBwByVhtAndHtOpInfo(struct BSS_INFO *prBssInfo); +static u_int8_t rlmCheckOpChangeParamValid(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + uint8_t ucChannelWidth, + uint8_t ucNss); +static void rlmRecOpModeBwForClient(uint8_t ucVhtOpModeChannelWidth, + struct BSS_INFO *prBssInfo); + +/* 11K */ +static u_int8_t +rlmAllMeasurementIssued(struct RADIO_MEASUREMENT_REQ_PARAMS *prReq); + +static void rlmCalibrateRepetions(struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq); + +static void rlmCollectBeaconReport(IN struct ADAPTER *prAdapter, + uint8_t *pucIEBuf, uint16_t u2IELength, + uint8_t *pucBssid, + struct RM_BEACON_REPORT_PARAMS *prRepParams); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmFsmEventInit(struct ADAPTER *prAdapter) +{ + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReqParam = + &prAdapter->rWifiVar.rRmReqParams; + struct RADIO_MEASUREMENT_REPORT_PARAMS *prRmRepParam = + &prAdapter->rWifiVar.rRmRepParams; + + ASSERT(prAdapter); + + /* Note: assume struct TIMER structures are reset to zero or stopped + * before invoking this function. + */ + + /* Initialize OBSS FSM */ + rlmObssInit(prAdapter); + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + rlmDomainCheckCountryPowerLimitTable(prAdapter); +#endif + +#ifdef CFG_DFS_CHSW_FORCE_BW20 + g_fgHasChannelSwitchIE = FALSE; +#endif + + kalMemZero(prRmRepParam, sizeof(*prRmRepParam)); + kalMemZero(prRmReqParam, sizeof(*prRmReqParam)); + prRmReqParam->rBcnRmParam.eState = RM_NO_REQUEST; + prRmReqParam->fgRmIsOngoing = FALSE; + LINK_INITIALIZE(&prRmRepParam->rFreeReportLink); + LINK_INITIALIZE(&prRmRepParam->rReportLink); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmFsmEventUninit(struct ADAPTER *prAdapter) +{ + struct BSS_INFO *prBssInfo; + uint8_t i; + + ASSERT(prAdapter); + + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + + /* Note: all RLM timers will also be stopped. + * Now only one OBSS scan timer. + */ + rlmBssReset(prAdapter, prBssInfo); + } + rlmFreeMeasurementResources(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief For association request, power capability + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmReqGeneratePowerCapIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + uint8_t *pucBuffer; + struct BSS_INFO *prBssInfo; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + + /* We should add power capability IE in assoc/reassoc req if + * the spectrum management bit is set to 1 in Capability Info + * field, or the connection will be rejected by Marvell APs in + * some TGn items. (e.g. 5.2.32). Spectrum management related + * feature (802.11h) is for 5G band. + */ + if (!prBssInfo || prBssInfo->eBand != BAND_5G) + return; + + pucBuffer = + (uint8_t *)(prMsduInfo->prPacket + prMsduInfo->u2FrameLength); + + POWER_CAP_IE(pucBuffer)->ucId = ELEM_ID_PWR_CAP; + POWER_CAP_IE(pucBuffer)->ucLength = ELEM_MAX_LEN_POWER_CAP; + POWER_CAP_IE(pucBuffer)->cMinTxPowerCap = 15; + POWER_CAP_IE(pucBuffer)->cMaxTxPowerCap = 20; + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief For association request, supported channels + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmReqGenerateSupportedChIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + uint8_t *pucBuffer; + struct BSS_INFO *prBssInfo; + struct RF_CHANNEL_INFO auc2gChannelList[MAX_2G_BAND_CHN_NUM]; + struct RF_CHANNEL_INFO auc5gChannelList[MAX_5G_BAND_CHN_NUM]; + uint8_t ucNumOf2gChannel = 0; + uint8_t ucNumOf5gChannel = 0; + uint8_t ucChIdx = 0; + uint8_t ucIdx = 0; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + + /* We should add supported channels IE in assoc/reassoc request + * if the spectrum management bit is set to 1 in Capability Info + * field, or the connection will be rejected by Marvell APs in + * some TGn items. (e.g. 5.2.3). Spectrum management related + * feature (802.11h) is for 5G band. + */ + if (!prBssInfo || prBssInfo->eBand != BAND_5G) + return; + + pucBuffer = + (uint8_t *)(prMsduInfo->prPacket + prMsduInfo->u2FrameLength); + + rlmDomainGetChnlList(prAdapter, BAND_2G4, TRUE, MAX_2G_BAND_CHN_NUM, + &ucNumOf2gChannel, auc2gChannelList); + rlmDomainGetChnlList(prAdapter, BAND_5G, TRUE, MAX_5G_BAND_CHN_NUM, + &ucNumOf5gChannel, auc5gChannelList); + + SUP_CH_IE(pucBuffer)->ucId = ELEM_ID_SUP_CHS; + SUP_CH_IE(pucBuffer)->ucLength = + (ucNumOf2gChannel + ucNumOf5gChannel) * 2; + + for (ucIdx = 0; ucIdx < ucNumOf2gChannel; ucIdx++, ucChIdx += 2) { + SUP_CH_IE(pucBuffer)->ucChannelNum[ucChIdx] = + auc2gChannelList[ucIdx].ucChannelNum; + SUP_CH_IE(pucBuffer)->ucChannelNum[ucChIdx + 1] = 1; + } + + for (ucIdx = 0; ucIdx < ucNumOf5gChannel; ucIdx++, ucChIdx += 2) { + SUP_CH_IE(pucBuffer)->ucChannelNum[ucChIdx] = + auc5gChannelList[ucIdx].ucChannelNum; + SUP_CH_IE(pucBuffer)->ucChannelNum[ucChIdx + 1] = 1; + } + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief For probe request, association request + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmReqGenerateHtCapIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + 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(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & + PHY_TYPE_SET_802_11N) && + (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N))) + rlmFillExtCapIE(prAdapter, prBssInfo, prMsduInfo); +#if CFG_SUPPORT_PASSPOINT + else if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) + hs20FillExtCapIE(prAdapter, prBssInfo, prMsduInfo); +#endif /* CFG_SUPPORT_PASSPOINT */ +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief For probe response (GO, IBSS) and association response + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmRspGenerateHtCapIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint8_t ucPhyTypeSet; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + if (!IS_BSS_ACTIVE(prBssInfo)) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + /* Decide PHY type set source */ + if (prStaRec) { + /* Get PHY type set from target STA */ + ucPhyTypeSet = prStaRec->ucPhyTypeSet; + } else { + /* Get PHY type set from current BSS */ + ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + } + + if (RLM_NET_IS_11N(prBssInfo) && + (ucPhyTypeSet & PHY_TYPE_SET_802_11N) && + (!prBssInfo->fgIsWepCipherGroup)) + rlmFillHtCapIE(prAdapter, prBssInfo, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief For probe response (GO, IBSS) and association response + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmRspGenerateExtCapIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint8_t ucPhyTypeSet; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + if (!IS_BSS_ACTIVE(prBssInfo)) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + /* Decide PHY type set source */ + if (prStaRec) { + /* Get PHY type set from target STA */ + ucPhyTypeSet = prStaRec->ucPhyTypeSet; + } else { + /* Get PHY type set from current BSS */ + ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + } + + if (RLM_NET_IS_11N(prBssInfo) && (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(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint8_t ucPhyTypeSet; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + if (!IS_BSS_ACTIVE(prBssInfo)) + return; + + /* Decide PHY type set source */ + if (prStaRec) { + /* Get PHY type set from target STA */ + ucPhyTypeSet = prStaRec->ucPhyTypeSet; + } else { + /* Get PHY type set from current BSS */ + ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + } + + if (RLM_NET_IS_11N(prBssInfo) && + (ucPhyTypeSet & PHY_TYPE_SET_802_11N) && + (!prBssInfo->fgIsWepCipherGroup)) + rlmFillHtOpIE(prAdapter, prBssInfo, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief For probe response (GO, IBSS) and association response + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmRspGenerateErpIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + struct IE_ERP *prErpIe; + uint8_t ucPhyTypeSet; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + if (!IS_BSS_ACTIVE(prBssInfo)) + return; + + /* Decide PHY type set source */ + if (prStaRec) { + /* Get PHY type set from target STA */ + ucPhyTypeSet = prStaRec->ucPhyTypeSet; + } else { + /* Get PHY type set from current BSS */ + ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + } + + if (RLM_NET_IS_11GN(prBssInfo) && prBssInfo->eBand == BAND_2G4 && + (ucPhyTypeSet & PHY_TYPE_SET_802_11GN)) { + prErpIe = (struct IE_ERP *)(((uint8_t *)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); + } +} + +#if CFG_SUPPORT_MTK_SYNERGY +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is used to generate MTK Vendor Specific OUI + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmGenerateMTKOuiIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + uint8_t *pucBuffer; + uint8_t aucMtkOui[] = VENDOR_OUI_MTK; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + if (prAdapter->rWifiVar.ucMtkOui == FEATURE_DISABLED) + return; + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + pucBuffer = (uint8_t *)((unsigned long)prMsduInfo->prPacket + + (unsigned long)prMsduInfo->u2FrameLength); + + MTK_OUI_IE(pucBuffer)->ucId = ELEM_ID_VENDOR; + MTK_OUI_IE(pucBuffer)->ucLength = ELEM_MIN_LEN_MTK_OUI; + MTK_OUI_IE(pucBuffer)->aucOui[0] = aucMtkOui[0]; + MTK_OUI_IE(pucBuffer)->aucOui[1] = aucMtkOui[1]; + MTK_OUI_IE(pucBuffer)->aucOui[2] = aucMtkOui[2]; + MTK_OUI_IE(pucBuffer)->aucCapability[0] = + MTK_SYNERGY_CAP0 & (prAdapter->rWifiVar.aucMtkFeature[0]); + MTK_OUI_IE(pucBuffer)->aucCapability[1] = + MTK_SYNERGY_CAP1 & (prAdapter->rWifiVar.aucMtkFeature[1]); + MTK_OUI_IE(pucBuffer)->aucCapability[2] = + MTK_SYNERGY_CAP2 & (prAdapter->rWifiVar.aucMtkFeature[2]); + MTK_OUI_IE(pucBuffer)->aucCapability[3] = + MTK_SYNERGY_CAP3 & (prAdapter->rWifiVar.aucMtkFeature[3]); + + /* Disable the 2.4G 256QAM feature bit if chip doesn't support AC*/ + if (prAdapter->rWifiVar.ucHwNotSupportAC) { + MTK_OUI_IE(pucBuffer)->aucCapability[0] &= + ~(MTK_SYNERGY_CAP_SUPPORT_24G_MCS89); + DBGLOG(INIT, WARN, + "Disable 2.4G 256QAM support if N only chip\n"); + } + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); +} /* rlmGenerateMTKOuiIE */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is used to check MTK Vendor Specific OUI + * + * + * @return true: correct MTK OUI + * false: incorrect MTK OUI + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rlmParseCheckMTKOuiIE(IN struct ADAPTER *prAdapter, IN uint8_t *pucBuf, + IN uint32_t *pu4Cap) +{ + uint8_t aucMtkOui[] = VENDOR_OUI_MTK; + struct IE_MTK_OUI *prMtkOuiIE = (struct IE_MTK_OUI *)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL)); + + prMtkOuiIE = (struct IE_MTK_OUI *)pucBuf; + + if (prAdapter->rWifiVar.ucMtkOui == FEATURE_DISABLED) + break; + else if (IE_LEN(pucBuf) < ELEM_MIN_LEN_MTK_OUI) + break; + else if (prMtkOuiIE->aucOui[0] != aucMtkOui[0] || + prMtkOuiIE->aucOui[1] != aucMtkOui[1] || + prMtkOuiIE->aucOui[2] != aucMtkOui[2]) + break; + /* apply NvRam setting */ + prMtkOuiIE->aucCapability[0] = + prMtkOuiIE->aucCapability[0] & + (prAdapter->rWifiVar.aucMtkFeature[0]); + prMtkOuiIE->aucCapability[1] = + prMtkOuiIE->aucCapability[1] & + (prAdapter->rWifiVar.aucMtkFeature[1]); + prMtkOuiIE->aucCapability[2] = + prMtkOuiIE->aucCapability[2] & + (prAdapter->rWifiVar.aucMtkFeature[2]); + prMtkOuiIE->aucCapability[3] = + prMtkOuiIE->aucCapability[3] & + (prAdapter->rWifiVar.aucMtkFeature[3]); + + /* Disable the 2.4G 256QAM feature bit if chip doesn't support + * AC. Otherwise, FW would choose wrong max rate of auto rate. + */ + if (prAdapter->rWifiVar.ucHwNotSupportAC) { + prMtkOuiIE->aucCapability[0] &= + ~(MTK_SYNERGY_CAP_SUPPORT_24G_MCS89); + DBGLOG(INIT, WARN, + "Disable 2.4G 256QAM support if N only chip\n"); + } + + kalMemCopy(pu4Cap, prMtkOuiIE->aucCapability, sizeof(uint32_t)); + + return TRUE; + } while (FALSE); + + return FALSE; +} /* rlmParseCheckMTKOuiIE */ + +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmGenerateCsaIE(struct ADAPTER *prAdapter, struct MSDU_INFO *prMsduInfo) +{ + uint8_t *pucBuffer; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + if (prAdapter->rWifiVar.fgCsaInProgress) { + + pucBuffer = + (uint8_t *)((unsigned long)prMsduInfo->prPacket + + (unsigned long)prMsduInfo->u2FrameLength); + + CSA_IE(pucBuffer)->ucId = ELEM_ID_CH_SW_ANNOUNCEMENT; + CSA_IE(pucBuffer)->ucLength = ELEM_MIN_LEN_CSA; + CSA_IE(pucBuffer)->ucChannelSwitchMode = + prAdapter->rWifiVar.ucChannelSwitchMode; + CSA_IE(pucBuffer)->ucNewChannelNum = + prAdapter->rWifiVar.ucNewChannelNumber; + CSA_IE(pucBuffer)->ucChannelSwitchCount = + prAdapter->rWifiVar.ucChannelSwitchCount; + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static void rlmFillHtCapIE(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct MSDU_INFO *prMsduInfo) +{ + struct IE_HT_CAP *prHtCap; + struct SUP_MCS_SET_FIELD *prSupMcsSet; + u_int8_t fg40mAllowed; + uint8_t ucIdx; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(prMsduInfo); + + fg40mAllowed = prBssInfo->fgAssoc40mBwAllowed; + + prHtCap = (struct IE_HT_CAP *)(((uint8_t *)prMsduInfo->prPacket) + + prMsduInfo->u2FrameLength); + + /* Add HT capabilities IE */ + prHtCap->ucId = ELEM_ID_HT_CAP; + prHtCap->ucLength = sizeof(struct IE_HT_CAP) - ELEM_HDR_LEN; + + prHtCap->u2HtCapInfo = HT_CAP_INFO_DEFAULT_VAL; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxShortGI)) + prHtCap->u2HtCapInfo |= + (HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxLdpc)) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_LDPC_CAP; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucTxStbc)) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_TX_STBC; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxStbc)) { + + uint8_t tempRxStbcNss; + + tempRxStbcNss = prAdapter->rWifiVar.ucRxStbcNss; + tempRxStbcNss = + (tempRxStbcNss > + wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex)) + ? wlanGetSupportNss(prAdapter, + prBssInfo->ucBssIndex) + : (tempRxStbcNss); + if (tempRxStbcNss != prAdapter->rWifiVar.ucRxStbcNss) { + DBGLOG(RLM, WARN, "Apply Nss:%d as RxStbcNss in HT Cap", + wlanGetSupportNss(prAdapter, + prBssInfo->ucBssIndex)); + DBGLOG(RLM, WARN, + " due to set RxStbcNss more than Nss is not appropriate.\n"); + } + if (tempRxStbcNss == 1) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_RX_STBC_1_SS; + else if (tempRxStbcNss == 2) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_RX_STBC_2_SS; + else if (tempRxStbcNss >= 3) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_RX_STBC_3_SS; + } + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxGf)) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + + if (prAdapter->rWifiVar.ucRxMaxMpduLen > VHT_CAP_INFO_MAX_MPDU_LEN_3K) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_MAX_AMSDU_LEN; + + if (!fg40mAllowed) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | + HT_CAP_INFO_SHORT_GI_40M | + HT_CAP_INFO_DSSS_CCK_IN_40M); + + /* SM power saving */ /* TH3_Huang */ + if (prBssInfo->ucNss < + wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex)) + prHtCap->u2HtCapInfo &= + ~HT_CAP_INFO_SM_POWER_SAVE; /*Set as static power save*/ + + prHtCap->ucAmpduParam = AMPDU_PARAM_DEFAULT_VAL; + + prSupMcsSet = &prHtCap->rSupMcsSet; + kalMemZero((void *)&prSupMcsSet->aucRxMcsBitmask[0], + SUP_MCS_RX_BITMASK_OCTET_NUM); + + for (ucIdx = 0; + ucIdx < wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex); + ucIdx++) + prSupMcsSet->aucRxMcsBitmask[ucIdx] = BITS(0, 7); + + /* prSupMcsSet->aucRxMcsBitmask[0] = BITS(0, 7); */ + + if (fg40mAllowed && IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucMCS32)) + 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; + if ((prAdapter->rWifiVar.eDbdcMode == ENUM_DBDC_MODE_DISABLED) || + (prBssInfo->eBand == BAND_5G)) { + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaHtBfee)) + prHtCap->u4TxBeamformingCap = TX_BEAMFORMING_CAP_BFEE; + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaHtBfer)) + prHtCap->u4TxBeamformingCap |= TX_BEAMFORMING_CAP_BFER; + } + + 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(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct MSDU_INFO *prMsduInfo) +{ +#if CFG_SUPPORT_PASSPOINT + struct IE_HS20_EXT_CAP_T *prHsExtCap; +#else + struct IE_EXT_CAP *prExtCap; +#endif + u_int8_t fg40mAllowed, fgAppendVhtCap; + struct STA_RECORD *prStaRec; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + fg40mAllowed = prBssInfo->fgAssoc40mBwAllowed; + +#if CFG_SUPPORT_PASSPOINT + prHsExtCap = + (struct IE_HS20_EXT_CAP_T *)(((uint8_t *)prMsduInfo->prPacket) + + prMsduInfo->u2FrameLength); + prHsExtCap->ucId = ELEM_ID_EXTENDED_CAP; + + if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) + prHsExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + else + prHsExtCap->ucLength = 3 - ELEM_HDR_LEN; + + kalMemZero(prHsExtCap->aucCapabilities, + sizeof(prHsExtCap->aucCapabilities)); + + prHsExtCap->aucCapabilities[0] = ELEM_EXT_CAP_DEFAULT_VAL; + + if (!fg40mAllowed) + prHsExtCap->aucCapabilities[0] &= + ~ELEM_EXT_CAP_20_40_COEXIST_SUPPORT; + + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + prHsExtCap->aucCapabilities[0] &= ~ELEM_EXT_CAP_PSMP_CAP; + +#if CFG_SUPPORT_802_11AC + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + fgAppendVhtCap = FALSE; + + /* Check append rule */ + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet + & PHY_TYPE_SET_802_11AC) { + /* Note: For AIS connecting state, + * structure in BSS_INFO will not be inited + * So, we check StaRec instead of BssInfo + */ + if (prStaRec) { + if (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11AC) + fgAppendVhtCap = TRUE; + } else if (RLM_NET_IS_11AC(prBssInfo) && + ((prBssInfo->eCurrentOPMode == + OP_MODE_INFRASTRUCTURE) || + (prBssInfo->eCurrentOPMode == + OP_MODE_ACCESS_POINT))) { + fgAppendVhtCap = TRUE; + } + + } + + if (fgAppendVhtCap) { + if (prHsExtCap->ucLength < ELEM_MAX_LEN_EXT_CAP) + prHsExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + + SET_EXT_CAP(prHsExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, + ELEM_EXT_CAP_OP_MODE_NOTIFICATION_BIT); + } +#endif + + if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) { + SET_EXT_CAP(prHsExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, + ELEM_EXT_CAP_INTERWORKING_BIT); + SET_EXT_CAP(prHsExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, + ELEM_EXT_CAP_QOSMAPSET_BIT); + SET_EXT_CAP(prHsExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, + ELEM_EXT_CAP_BSS_TRANSITION_BIT); + /* For R2 WNM-Notification */ + SET_EXT_CAP(prHsExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, + ELEM_EXT_CAP_WNM_NOTIFICATION_BIT); + } + +#if CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT + prHsExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + SET_EXT_CAP(prHsExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, + ELEM_EXT_CAP_BSS_TRANSITION_BIT); +#endif + + ASSERT(IE_SIZE(prHsExtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP)); + + prMsduInfo->u2FrameLength += IE_SIZE(prHsExtCap); + +#else + /* Add Extended Capabilities IE */ + prExtCap = (struct IE_EXT_CAP *)(((uint8_t *)prMsduInfo->prPacket) + + prMsduInfo->u2FrameLength); + + prExtCap->ucId = ELEM_ID_EXTENDED_CAP; + + prExtCap->ucLength = 3 - ELEM_HDR_LEN; + kalMemZero(prExtCap->aucCapabilities, + sizeof(prExtCap->aucCapabilities)); + + prExtCap->aucCapabilities[0] = ELEM_EXT_CAP_DEFAULT_VAL; + + if (!fg40mAllowed) + prExtCap->aucCapabilities[0] &= + ~ELEM_EXT_CAP_20_40_COEXIST_SUPPORT; + + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + prExtCap->aucCapabilities[0] &= ~ELEM_EXT_CAP_PSMP_CAP; + +#if CFG_SUPPORT_802_11AC + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + fgAppendVhtCap = FALSE; + + /* Check append rule */ + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet + & PHY_TYPE_SET_802_11AC) { + /* Note: For AIS connecting state, + * structure in BSS_INFO will not be inited + * So, we check StaRec instead of BssInfo + */ + if (prStaRec) { + if (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11AC) + fgAppendVhtCap = TRUE; + } else if (RLM_NET_IS_11AC(prBssInfo) && + ((prBssInfo->eCurrentOPMode == + OP_MODE_INFRASTRUCTURE) || + (prBssInfo->eCurrentOPMode == + OP_MODE_ACCESS_POINT))) { + fgAppendVhtCap = TRUE; + } + } + + if (fgAppendVhtCap) { + if (prExtCap->ucLength < ELEM_MAX_LEN_EXT_CAP) + prExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, + ELEM_EXT_CAP_OP_MODE_NOTIFICATION_BIT); + } +#endif + +#if CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT + prExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, + ELEM_EXT_CAP_BSS_TRANSITION_BIT); +#endif + + ASSERT(IE_SIZE(prExtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP)); + + prMsduInfo->u2FrameLength += IE_SIZE(prExtCap); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static void rlmFillHtOpIE(struct ADAPTER *prAdapter, struct BSS_INFO *prBssInfo, + struct MSDU_INFO *prMsduInfo) +{ + struct IE_HT_OP *prHtOp; + uint16_t i; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(prMsduInfo); + + prHtOp = (struct IE_HT_OP *)(((uint8_t *)prMsduInfo->prPacket) + + prMsduInfo->u2FrameLength); + + /* Add HT operation IE */ + prHtOp->ucId = ELEM_ID_HT_OP; + prHtOp->ucLength = sizeof(struct IE_HT_OP) - 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 = (uint8_t)HT_PROTECT_MODE_NON_HT; + else if (prBssInfo->eObssHtProtectMode == HT_PROTECT_MODE_NON_MEMBER) + prHtOp->u2Info2 = (uint8_t)HT_PROTECT_MODE_NON_MEMBER; + else { + /* It may be SYS_PROTECT_MODE_NONE or SYS_PROTECT_MODE_20M */ + prHtOp->u2Info2 = (uint8_t)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); +} + +#if CFG_SUPPORT_802_11AC + +/*----------------------------------------------------------------------------*/ +/*! + * \brief For probe request, association request + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmReqGenerateVhtCapIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; +#if CFG_SUPPORT_VHT_IE_IN_2G + struct BSS_DESC *prBssDesc = NULL; + u_int8_t fgIsVHTPresent = FALSE; +#endif + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + if (prAdapter) { + prBssDesc = prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc; + if (prBssDesc) { + fgIsVHTPresent = prBssDesc->fgIsVHTPresent; + DBGLOG(RLM, TRACE, "fgIsVHTPresent=%d", fgIsVHTPresent); + } + } else { + DBGLOG(RLM, ERROR, "prAdapter is NULL, return!"); + return; + } + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) { + DBGLOG(RLM, ERROR, "prBssInfo is NULL, return!"); + return; + } + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + if (!prStaRec) { + DBGLOG(RLM, ERROR, "prStaRec is NULL, return!"); + return; + } + + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AC) + && (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11AC)) + rlmFillVhtCapIE(prAdapter, prBssInfo, prMsduInfo); +#if CFG_SUPPORT_VHT_IE_IN_2G + else if ((prBssInfo->eBand == BAND_2G4) && + (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N) && + ((prAdapter->rWifiVar.ucVhtIeIn2g + == FEATURE_FORCE_ENABLED) || + ((prAdapter->rWifiVar.ucVhtIeIn2g + == FEATURE_ENABLED) && fgIsVHTPresent))) { + rlmFillVhtCapIE(prAdapter, prBssInfo, prMsduInfo); + DBGLOG(RLM, TRACE, "Add VHT IE in 2.4G, ucPhyTypeSet=%02x", + prStaRec->ucPhyTypeSet); + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief For probe response (GO, IBSS) and association response + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmRspGenerateVhtCapIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint8_t ucPhyTypeSet; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + if (!IS_BSS_ACTIVE(prBssInfo)) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + /* Decide PHY type set source */ + if (prStaRec) { + /* Get PHY type set from target STA */ + ucPhyTypeSet = prStaRec->ucPhyTypeSet; + } else { + /* Get PHY type set from current BSS */ + ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + } + + if (RLM_NET_IS_11AC(prBssInfo) && + (ucPhyTypeSet & PHY_TYPE_SET_802_11AC)) + rlmFillVhtCapIE(prAdapter, prBssInfo, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmRspGenerateVhtOpIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint8_t ucPhyTypeSet; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + if (!IS_BSS_ACTIVE(prBssInfo)) + return; + + /* Decide PHY type set source */ + if (prStaRec) { + /* Get PHY type set from target STA */ + ucPhyTypeSet = prStaRec->ucPhyTypeSet; + } else { + /* Get PHY type set from current BSS */ + ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + } + + if (RLM_NET_IS_11AC(prBssInfo) && + (ucPhyTypeSet & PHY_TYPE_SET_802_11AC)) + rlmFillVhtOpIE(prAdapter, prBssInfo, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief For probe request, association request + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmReqGenerateVhtOpNotificationIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & + PHY_TYPE_SET_802_11AC) && + (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11AC))) { + /* Fill own capability in channel width field in OP mode element + * since we haven't filled in channel width info in BssInfo at + * current state + */ + rlmFillVhtOpNotificationIE(prAdapter, prBssInfo, prMsduInfo, + TRUE); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmRspGenerateVhtOpNotificationIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint8_t ucPhyTypeSet; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + if (!IS_BSS_ACTIVE(prBssInfo)) + return; + + /* Decide PHY type set source */ + if (prStaRec) { + /* Get PHY type set from target STA */ + ucPhyTypeSet = prStaRec->ucPhyTypeSet; + } else { + /* Get PHY type set from current BSS */ + ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + } + + if (RLM_NET_IS_11AC(prBssInfo) && + (ucPhyTypeSet & PHY_TYPE_SET_802_11AC)) + rlmFillVhtOpNotificationIE(prAdapter, prBssInfo, prMsduInfo, + FALSE); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * add VHT operation notification IE for VHT-BW40 case specific + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static void rlmFillVhtOpNotificationIE(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct MSDU_INFO *prMsduInfo, + u_int8_t fgIsOwnCap) +{ + struct IE_VHT_OP_MODE_NOTIFICATION *prVhtOpMode; + uint8_t ucOpModeBw = VHT_OP_MODE_CHANNEL_WIDTH_20; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(prMsduInfo); + + prVhtOpMode = (struct IE_VHT_OP_MODE_NOTIFICATION + *)(((uint8_t *)prMsduInfo->prPacket) + + prMsduInfo->u2FrameLength); + + kalMemZero((void *)prVhtOpMode, + sizeof(struct IE_VHT_OP_MODE_NOTIFICATION)); + + prVhtOpMode->ucId = ELEM_ID_OP_MODE; + prVhtOpMode->ucLength = + sizeof(struct IE_VHT_OP_MODE_NOTIFICATION) - ELEM_HDR_LEN; + + DBGLOG(RLM, TRACE, "rlmFillVhtOpNotificationIE(%d) %u %u\n", + prBssInfo->ucBssIndex, fgIsOwnCap, prBssInfo->ucNss); + + if (fgIsOwnCap) { + ucOpModeBw = cnmGetDbdcBwCapability(prAdapter, + prBssInfo->ucBssIndex); + + /*handle 80P80 case*/ + if (ucOpModeBw >= MAX_BW_160MHZ) + ucOpModeBw = VHT_OP_MODE_CHANNEL_WIDTH_160_80P80; + + prVhtOpMode->ucOperatingMode |= ucOpModeBw; + prVhtOpMode->ucOperatingMode |= + (((prBssInfo->ucNss - 1) << VHT_OP_MODE_RX_NSS_OFFSET) & + VHT_OP_MODE_RX_NSS); + + } else { + + ucOpModeBw = rlmGetOpModeBwByVhtAndHtOpInfo(prBssInfo); + + prVhtOpMode->ucOperatingMode |= ucOpModeBw; + prVhtOpMode->ucOperatingMode |= + (((prBssInfo->ucNss - 1) << VHT_OP_MODE_RX_NSS_OFFSET) & + VHT_OP_MODE_RX_NSS); + } + + prMsduInfo->u2FrameLength += IE_SIZE(prVhtOpMode); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static void rlmFillVhtCapIE(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct MSDU_INFO *prMsduInfo) +{ + struct IE_VHT_CAP *prVhtCap; + struct VHT_SUPPORTED_MCS_FIELD *prVhtSupportedMcsSet; + uint8_t i; + uint8_t ucMaxBw; + struct STA_RECORD *prStaRec; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(prMsduInfo); + + prVhtCap = (struct IE_VHT_CAP *)(((uint8_t *)prMsduInfo->prPacket) + + prMsduInfo->u2FrameLength); + + prVhtCap->ucId = ELEM_ID_VHT_CAP; + prVhtCap->ucLength = sizeof(struct IE_VHT_CAP) - ELEM_HDR_LEN; + prVhtCap->u4VhtCapInfo = VHT_CAP_INFO_DEFAULT_VAL; + + ucMaxBw = cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex); + + prVhtCap->u4VhtCapInfo |= (prAdapter->rWifiVar.ucRxMaxMpduLen & + VHT_CAP_INFO_MAX_MPDU_LEN_MASK); +#if CFG_SUPPORT_VHT_IE_IN_2G + if (prBssInfo->eBand == BAND_2G4) { + prVhtCap->u4VhtCapInfo |= + VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_SET_NONE; + } else { +#endif + if (ucMaxBw == MAX_BW_160MHZ) + prVhtCap->u4VhtCapInfo |= + VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_SET_160; + else if (ucMaxBw == MAX_BW_80_80_MHZ) + prVhtCap->u4VhtCapInfo |= + VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_SET_160_80P80; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaVhtBfee)) { + prVhtCap->u4VhtCapInfo |= FIELD_VHT_CAP_INFO_BFEE; +#if CFG_SUPPORT_BFEE + prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + + if (prStaRec && + (prStaRec->ucVhtCapNumSoundingDimensions == 0x2) && + !prAdapter->rWifiVar.fgForceSTSNum) { + /* For the compatibility with netgear R7000 AP */ + prVhtCap->u4VhtCapInfo |= + (((uint32_t)prStaRec->ucVhtCapNumSoundingDimensions) +<< VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF_BEAMFORMER_ANTENNAS_SUP_OFF); + DBGLOG(RLM, INFO, "Set VHT Cap BFEE STS CAP=%d\n", + prStaRec->ucVhtCapNumSoundingDimensions); + } else { + /* For 11ac cert. VHT-5.2.63C MU-BFee step3, + * it requires STAUT to set its maximum STS capability here + */ + prVhtCap->u4VhtCapInfo |= +VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF_BEAMFORMER_ANTENNAS_4_SUP; + DBGLOG(RLM, TRACE, "Set VHT Cap BFEE STS CAP=%d\n", + VHT_CAP_INFO_BEAMFORMEE_STS_CAP_MAX); + } +/* DBGLOG(RLM, INFO, "VhtCapInfo=%x\n", prVhtCap->u4VhtCapInfo); */ +#endif + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaVhtMuBfee)) + prVhtCap->u4VhtCapInfo |= + VHT_CAP_INFO_MU_BEAMFOMEE_CAPABLE; + } + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaVhtBfer)) + prVhtCap->u4VhtCapInfo |= FIELD_VHT_CAP_INFO_BFER; +#if CFG_SUPPORT_VHT_IE_IN_2G + } +#endif + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxShortGI)) { + if (ucMaxBw >= MAX_BW_80MHZ) + prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_SHORT_GI_80; + + if (ucMaxBw >= MAX_BW_160MHZ) + prVhtCap->u4VhtCapInfo |= + VHT_CAP_INFO_SHORT_GI_160_80P80; + } + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxLdpc)) + prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_RX_LDPC; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxStbc)) { + uint8_t tempRxStbcNss; + + if (prAdapter->rWifiVar.u4SwTestMode == + ENUM_SW_TEST_MODE_SIGMA_AC) { + tempRxStbcNss = 1; + DBGLOG(RLM, INFO, + "Set RxStbcNss to 1 for 11ac certification.\n"); + } else { + tempRxStbcNss = prAdapter->rWifiVar.ucRxStbcNss; + tempRxStbcNss = + (tempRxStbcNss > + wlanGetSupportNss(prAdapter, + prBssInfo->ucBssIndex)) + ? wlanGetSupportNss( + prAdapter, + prBssInfo->ucBssIndex) + : (tempRxStbcNss); + if (tempRxStbcNss != prAdapter->rWifiVar.ucRxStbcNss) { + DBGLOG(RLM, WARN, + "Apply Nss:%d as RxStbcNss in VHT Cap", + wlanGetSupportNss( + prAdapter, + prBssInfo->ucBssIndex)); + DBGLOG(RLM, WARN, + "due to set RxStbcNss more than Nss is not appropriate.\n"); + } + } + prVhtCap->u4VhtCapInfo |= + ((tempRxStbcNss << VHT_CAP_INFO_RX_STBC_OFFSET) & + VHT_CAP_INFO_RX_STBC_MASK); + } + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucTxStbc)) + prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_TX_STBC; + + /*set MCS map */ + prVhtSupportedMcsSet = &prVhtCap->rVhtSupportedMcsSet; + kalMemZero((void *)prVhtSupportedMcsSet, + sizeof(struct VHT_SUPPORTED_MCS_FIELD)); + + for (i = 0; i < 8; i++) { + uint8_t ucOffset = i * 2; + uint8_t ucMcsMap; + + if (i < wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex)) + ucMcsMap = VHT_CAP_INFO_MCS_MAP_MCS9; + else + ucMcsMap = VHT_CAP_INFO_MCS_NOT_SUPPORTED; + + prVhtSupportedMcsSet->u2RxMcsMap |= (ucMcsMap << ucOffset); + prVhtSupportedMcsSet->u2TxMcsMap |= (ucMcsMap << ucOffset); + } + +#if 0 + for (i = 0; i < wlanGetSupportNss(prAdapter, + prBssInfo->ucBssIndex); i++) { + uint8_t ucOffset = i * 2; + + prVhtSupportedMcsSet->u2RxMcsMap &= + ((VHT_CAP_INFO_MCS_MAP_MCS9 << ucOffset) & + BITS(ucOffset, ucOffset + 1)); + prVhtSupportedMcsSet->u2TxMcsMap &= + ((VHT_CAP_INFO_MCS_MAP_MCS9 << ucOffset) & + BITS(ucOffset, ucOffset + 1)); + } +#endif + + prVhtSupportedMcsSet->u2RxHighestSupportedDataRate = + VHT_CAP_INFO_DEFAULT_HIGHEST_DATA_RATE; + prVhtSupportedMcsSet->u2TxHighestSupportedDataRate = + VHT_CAP_INFO_DEFAULT_HIGHEST_DATA_RATE; + + ASSERT(IE_SIZE(prVhtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP)); + + prMsduInfo->u2FrameLength += IE_SIZE(prVhtCap); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmFillVhtOpIE(struct ADAPTER *prAdapter, struct BSS_INFO *prBssInfo, + struct MSDU_INFO *prMsduInfo) +{ + struct IE_VHT_OP *prVhtOp; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(prMsduInfo); + + prVhtOp = (struct IE_VHT_OP *)(((uint8_t *)prMsduInfo->prPacket) + + prMsduInfo->u2FrameLength); + + /* Add HT operation IE */ + prVhtOp->ucId = ELEM_ID_VHT_OP; + prVhtOp->ucLength = sizeof(struct IE_VHT_OP) - ELEM_HDR_LEN; + + ASSERT(IE_SIZE(prVhtOp) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP)); + + /* (UINT8)VHT_OP_CHANNEL_WIDTH_80; */ + prVhtOp->ucVhtOperation[0] = prBssInfo->ucVhtChannelWidth; + prVhtOp->ucVhtOperation[1] = prBssInfo->ucVhtChannelFrequencyS1; + prVhtOp->ucVhtOperation[2] = prBssInfo->ucVhtChannelFrequencyS2; + +#if 0 + if (cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex) < MAX_BW_80MHZ) { + prVhtOp->ucVhtOperation[0] = VHT_OP_CHANNEL_WIDTH_20_40; + prVhtOp->ucVhtOperation[1] = 0; + prVhtOp->ucVhtOperation[2] = 0; + } else if (cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex) == + MAX_BW_80MHZ) { + prVhtOp->ucVhtOperation[0] = VHT_OP_CHANNEL_WIDTH_80; + prVhtOp->ucVhtOperation[1] = + nicGetVhtS1(prBssInfo->ucPrimaryChannel); + prVhtOp->ucVhtOperation[2] = 0; + } else { + /* TODO: BW80 + 80/160 support */ + } +#endif + + prVhtOp->u2VhtBasicMcsSet = prBssInfo->u2VhtBasicMcsSet; + + prMsduInfo->u2FrameLength += IE_SIZE(prVhtOp); +} + +#endif + + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmGenerateCountryIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct BSS_INFO *prBssInfo = + prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + unsigned char *pucBuf = + (((unsigned char *) prMsduInfo->prPacket) + + prMsduInfo->u2FrameLength); + + if (prBssInfo->aucCountryStr[0] == 0) + return; + + COUNTRY_IE(pucBuf)->ucId = ELEM_ID_COUNTRY_INFO; + COUNTRY_IE(pucBuf)->ucLength = prBssInfo->ucCountryIELen; + COUNTRY_IE(pucBuf)->aucCountryStr[0] = prBssInfo->aucCountryStr[0]; + COUNTRY_IE(pucBuf)->aucCountryStr[1] = prBssInfo->aucCountryStr[1]; + COUNTRY_IE(pucBuf)->aucCountryStr[2] = prBssInfo->aucCountryStr[2]; + kalMemCopy(COUNTRY_IE(pucBuf)->arCountryStr, + prBssInfo->aucSubbandTriplet, + prBssInfo->ucCountryIELen - 3); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuf); +} + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +uint32_t rlmCalBackup(struct ADAPTER *prAdapter, uint8_t ucReason, + uint8_t ucAction, uint8_t ucRomRam) +{ + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct GLUE_INFO *prGlueInfo = NULL; + struct PARAM_CAL_BACKUP_STRUCT_V2 rCalBackupDataV2; + uint32_t u4BufLen = 0; + + ASSERT(prAdapter); + ASSERT(prAdapter->prGlueInfo); + + prGlueInfo = prAdapter->prGlueInfo; + + rCalBackupDataV2.ucReason = ucReason; + rCalBackupDataV2.ucAction = ucAction; + rCalBackupDataV2.ucNeedResp = 1; + rCalBackupDataV2.ucFragNum = 0; + rCalBackupDataV2.ucRomRam = ucRomRam; + rCalBackupDataV2.u4ThermalValue = 0; + rCalBackupDataV2.u4Address = 0; + rCalBackupDataV2.u4Length = 0; + rCalBackupDataV2.u4RemainLength = 0; + + if (ucReason == 0 && ucAction == 0) { + DBGLOG(RFTEST, INFO, "RLM CMD : Get Thermal Temp from FW.\n"); + /* Step 1 : Get Thermal Temp from FW */ + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryCalBackupV2, + &rCalBackupDataV2, + sizeof(struct PARAM_CAL_BACKUP_STRUCT_V2), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Get Thermal Temp from FW Return Fail (0x%08x)!!!!!!!!!!!\n", + rStatus); + return rStatus; + } + + DBGLOG(RFTEST, INFO, + "CMD : Get Thermal Temp (%d) from FW. Finish!!!!!!!!!!!\n", + rCalBackupDataV2.u4ThermalValue); + } else if (ucReason == 1 && ucAction == 2) { + DBGLOG(RFTEST, INFO, "RLM CMD : Trigger FW Do All Cal.\n"); + /* Step 2 : Trigger All Cal Function */ + + rStatus = kalIoctl(prGlueInfo, wlanoidSetCalBackup, + &rCalBackupDataV2, + sizeof(struct PARAM_CAL_BACKUP_STRUCT_V2), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Trigger FW Do All Cal Return Fail (0x%08x)!!!!!!!!!!!\n", + rStatus); + return rStatus; + } + + DBGLOG(RFTEST, INFO, + "CMD : Trigger FW Do All Cal. Finish!!!!!!!!!!!\n"); + } else if (ucReason == 0 && ucAction == 1) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Get Cal Data (%s) Size from FW.\n", + ucRomRam == 0 ? "ROM" : "RAM"); + /* Step 3 : Get Cal Data Size from FW */ + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryCalBackupV2, + &rCalBackupDataV2, + sizeof(struct PARAM_CAL_BACKUP_STRUCT_V2), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Get Cal Data (%s) Size from FW Return Fail (0x%08x)!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM", rStatus); + return rStatus; + } + + DBGLOG(RFTEST, INFO, + "CMD : Get Cal Data (%s) Size from FW. Finish!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM"); + } else if (ucReason == 2 && ucAction == 4) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Get Cal Data from FW (%s). Start!!!!!!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM"); + DBGLOG(RFTEST, INFO, "Thermal Temp = %d\n", + g_rBackupCalDataAllV2.u4ThermalInfo); + /* Step 4 : Get Cal Data from FW */ + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryCalBackupV2, + &rCalBackupDataV2, + sizeof(struct PARAM_CAL_BACKUP_STRUCT_V2), + TRUE, TRUE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Get Cal Data (%s) Size from FW Return Fail (0x%08x)!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM", rStatus); + return rStatus; + } + + DBGLOG(RFTEST, INFO, + "CMD : Get Cal Data from FW (%s). Finish!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM"); + + if (ucRomRam == 0) { + DBGLOG(RFTEST, INFO, + "Check some of elements (0x%08x), (0x%08x), (0x%08x), (0x%08x), (0x%08x)\n", + g_rBackupCalDataAllV2.au4RomCalData[670], + g_rBackupCalDataAllV2.au4RomCalData[671], + g_rBackupCalDataAllV2.au4RomCalData[672], + g_rBackupCalDataAllV2.au4RomCalData[673], + g_rBackupCalDataAllV2.au4RomCalData[674]); + DBGLOG(RFTEST, INFO, + "Check some of elements (0x%08x), (0x%08x), (0x%08x), (0x%08x), (0x%08x)\n", + g_rBackupCalDataAllV2.au4RomCalData[675], + g_rBackupCalDataAllV2.au4RomCalData[676], + g_rBackupCalDataAllV2.au4RomCalData[677], + g_rBackupCalDataAllV2.au4RomCalData[678], + g_rBackupCalDataAllV2.au4RomCalData[679]); + } + } else if (ucReason == 4 && ucAction == 6) { + DBGLOG(RFTEST, INFO, "RLM CMD : Print Cal Data in FW (%s).\n", + ucRomRam == 0 ? "ROM" : "RAM"); + /* Debug Use : Print Cal Data in FW */ + + rStatus = kalIoctl(prGlueInfo, wlanoidSetCalBackup, + &rCalBackupDataV2, + sizeof(struct PARAM_CAL_BACKUP_STRUCT_V2), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Print Cal Data in FW (%s) Return Fail (0x%08x)!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM", rStatus); + return rStatus; + } + + DBGLOG(RFTEST, INFO, + "CMD : Print Cal Data in FW (%s). Finish!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM"); + } else if (ucReason == 3 && ucAction == 5) { + DBGLOG(RFTEST, INFO, "RLM CMD : Send Cal Data to FW (%s).\n", + ucRomRam == 0 ? "ROM" : "RAM"); + /* Send Cal Data to FW */ + + rStatus = kalIoctl(prGlueInfo, wlanoidSetCalBackup, + &rCalBackupDataV2, + sizeof(struct PARAM_CAL_BACKUP_STRUCT_V2), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Send Cal Data to FW (%s) Return Fail (0x%08x)!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM", rStatus); + return rStatus; + } + + DBGLOG(RFTEST, INFO, + "CMD : Send Cal Data to FW (%s). Finish!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM"); + } else { + DBGLOG(RFTEST, INFO, + "CMD : Undefined Reason (%d) and Action (%d) for Cal Backup in Host Side!\n", + ucReason, ucAction); + + return rStatus; + } + + return rStatus; +} + +uint32_t rlmTriggerCalBackup(struct ADAPTER *prAdapter, + u_int8_t fgIsCalDataBackuped) +{ + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + if (!fgIsCalDataBackuped) { + DBGLOG(RFTEST, INFO, + "======== Boot Time Wi-Fi Enable........\n"); + DBGLOG(RFTEST, INFO, + "Step 0 : Reset All Cal Data in Driver.\n"); + memset(&g_rBackupCalDataAllV2, 1, + sizeof(struct RLM_CAL_RESULT_ALL_V2)); + g_rBackupCalDataAllV2.u4MagicNum1 = 6632; + g_rBackupCalDataAllV2.u4MagicNum2 = 6632; + + DBGLOG(RFTEST, INFO, "Step 1 : Get Thermal Temp from FW.\n"); + if (rlmCalBackup(prAdapter, 0, 0, 0) == WLAN_STATUS_FAILURE) { + DBGLOG(RFTEST, INFO, "Step 1 : Return Failure.\n"); + return WLAN_STATUS_FAILURE; + } + + DBGLOG(RFTEST, INFO, + "Step 2 : Get Rom Cal Data Size from FW.\n"); + if (rlmCalBackup(prAdapter, 0, 1, 0) == WLAN_STATUS_FAILURE) { + DBGLOG(RFTEST, INFO, "Step 2 : Return Failure.\n"); + return WLAN_STATUS_FAILURE; + } + + DBGLOG(RFTEST, INFO, + "Step 3 : Get Ram Cal Data Size from FW.\n"); + if (rlmCalBackup(prAdapter, 0, 1, 1) == WLAN_STATUS_FAILURE) { + DBGLOG(RFTEST, INFO, "Step 3 : Return Failure.\n"); + return WLAN_STATUS_FAILURE; + } + + DBGLOG(RFTEST, INFO, "Step 4 : Trigger FW Do Full Cal.\n"); + if (rlmCalBackup(prAdapter, 1, 2, 0) == WLAN_STATUS_FAILURE) { + DBGLOG(RFTEST, INFO, "Step 4 : Return Failure.\n"); + return WLAN_STATUS_FAILURE; + } + } else { + DBGLOG(RFTEST, INFO, "======== Normal Wi-Fi Enable........\n"); + DBGLOG(RFTEST, INFO, "Step 0 : Sent Rom Cal data to FW.\n"); + if (rlmCalBackup(prAdapter, 3, 5, 0) == WLAN_STATUS_FAILURE) { + DBGLOG(RFTEST, INFO, "Step 0 : Return Failure.\n"); + return WLAN_STATUS_FAILURE; + } + + DBGLOG(RFTEST, INFO, "Step 1 : Sent Ram Cal data to FW.\n"); + if (rlmCalBackup(prAdapter, 3, 5, 1) == WLAN_STATUS_FAILURE) { + DBGLOG(RFTEST, INFO, "Step 1 : Return Failure.\n"); + return WLAN_STATUS_FAILURE; + } + } + + return rStatus; +} +#endif + +void rlmModifyVhtBwPara(uint8_t *pucVhtChannelFrequencyS1, + uint8_t *pucVhtChannelFrequencyS2, + uint8_t *pucVhtChannelWidth) +{ + uint8_t i = 0, ucTempS = 0; + + if ((*pucVhtChannelFrequencyS1 != 0) && + (*pucVhtChannelFrequencyS2 != 0)) { + + uint8_t ucBW160Inteval = 8; + + if (((*pucVhtChannelFrequencyS2 - *pucVhtChannelFrequencyS1) == + ucBW160Inteval) || + ((*pucVhtChannelFrequencyS1 - *pucVhtChannelFrequencyS2) == + ucBW160Inteval)) { + /*C160 case*/ + + /* NEW spec should set central ch of bw80 at S1, + * set central ch of bw160 at S2 + */ + for (i = 0; i < 2; i++) { + + if (i == 0) + ucTempS = *pucVhtChannelFrequencyS1; + else + ucTempS = *pucVhtChannelFrequencyS2; + + if ((ucTempS == 50) || (ucTempS == 82) || + (ucTempS == 114) || (ucTempS == 163)) + break; + } + + if (ucTempS == 0) { + DBGLOG(RLM, WARN, + "please check BW160 setting, find central freq fail\n"); + return; + } + + *pucVhtChannelFrequencyS1 = ucTempS; + *pucVhtChannelFrequencyS2 = 0; + *pucVhtChannelWidth = CW_160MHZ; + } else { + /*real 80P80 case*/ + } + } +} + +static void rlmRevisePreferBandwidthNss(struct ADAPTER *prAdapter, + uint8_t ucBssIndex, + struct STA_RECORD *prStaRec) +{ + enum ENUM_CHANNEL_WIDTH eChannelWidth = CW_20_40MHZ; + struct BSS_INFO *prBssInfo; + +#define VHT_MCS_TX_RX_MAX_2SS BITS(2, 3) +#define VHT_MCS_TX_RX_MAX_2SS_SHIFT 2 + +#define AR_STA_2AC_MCS(prStaRec) \ + (((prStaRec)->u2VhtRxMcsMap & VHT_MCS_TX_RX_MAX_2SS) >> \ + VHT_MCS_TX_RX_MAX_2SS_SHIFT) + +#define AR_IS_STA_2SS_AC(prStaRec) ((AR_STA_2AC_MCS(prStaRec) != BITS(0, 1))) + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + eChannelWidth = prBssInfo->ucVhtChannelWidth; + + /* + * Prefer setting modification + * 80+80 1x1 and 80 2x2 have the same phy rate, choose the 80 2x2 + */ + + if (AR_IS_STA_2SS_AC(prStaRec)) { + /* + * DBGLOG(RLM, WARN, "support 2ss\n"); + */ + + if ((eChannelWidth == CW_80P80MHZ && + prBssInfo->ucVhtChannelFrequencyS2 != 0)) { + DBGLOG(RLM, WARN, "support (2Nss) and (80+80)\n"); + DBGLOG(RLM, WARN, + "choose (2Nss) and (80) for Bss_info\n"); + prBssInfo->ucVhtChannelWidth = CW_80MHZ; + prBssInfo->ucVhtChannelFrequencyS2 = 0; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Revise operating BW by own maximum bandwidth capability + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmReviseMaxBw(struct ADAPTER *prAdapter, uint8_t ucBssIndex, + enum ENUM_CHNL_EXT *peExtend, + enum ENUM_CHANNEL_WIDTH *peChannelWidth, uint8_t *pucS1, + uint8_t *pucPrimaryCh) +{ + uint8_t ucMaxBandwidth = MAX_BW_80MHZ; + uint8_t ucCurrentBandwidth = MAX_BW_20MHZ; + uint8_t ucOffset = (MAX_BW_80MHZ - CW_80MHZ); + + ucMaxBandwidth = cnmGetDbdcBwCapability(prAdapter, ucBssIndex); + + if (*peChannelWidth > CW_20_40MHZ) { + /*case BW > 80 , 160 80P80 */ + ucCurrentBandwidth = (uint8_t)*peChannelWidth + ucOffset; + } else { + /*case BW20 BW40 */ + if (*peExtend != CHNL_EXT_SCN) { + /*case BW40 */ + ucCurrentBandwidth = MAX_BW_40MHZ; + } + } + + if (ucCurrentBandwidth > ucMaxBandwidth) { + DBGLOG(RLM, INFO, "Decreasse the BW to (%d)\n", ucMaxBandwidth); + + if (ucMaxBandwidth <= MAX_BW_40MHZ) { + /*BW20 * BW40*/ + *peChannelWidth = CW_20_40MHZ; + + if (ucMaxBandwidth == MAX_BW_20MHZ) + *peExtend = CHNL_EXT_SCN; + } else { + /* BW80, BW160, BW80P80 + * ucMaxBandwidth Must be + * MAX_BW_80MHZ,MAX_BW_160MHZ,MAX_BW_80MHZ + * peExtend should not change + */ + *peChannelWidth = (ucMaxBandwidth - ucOffset); + + if (ucMaxBandwidth == MAX_BW_80MHZ) { + /* modify S1 for Bandwidth 160 downgrade 80 case + */ + if (ucCurrentBandwidth == MAX_BW_160MHZ) { + if ((*pucPrimaryCh >= 36) && + (*pucPrimaryCh <= 48)) + *pucS1 = 42; + else if ((*pucPrimaryCh >= 52) && + (*pucPrimaryCh <= 64)) + *pucS1 = 58; + else if ((*pucPrimaryCh >= 100) && + (*pucPrimaryCh <= 112)) + *pucS1 = 106; + else if ((*pucPrimaryCh >= 116) && + (*pucPrimaryCh <= 128)) + *pucS1 = 122; + else if ((*pucPrimaryCh >= 132) && + (*pucPrimaryCh <= 144)) + /* 160 downgrade should not in + * this case + */ + *pucS1 = 138; + else if ((*pucPrimaryCh >= 149) && + (*pucPrimaryCh <= 161)) + /* 160 downgrade should not in + * this case + */ + *pucS1 = 155; + else + DBGLOG(RLM, INFO, + "Check connect 160 downgrde (%d) case\n", + ucMaxBandwidth); + + DBGLOG(RLM, INFO, + "Decreasse the BW160 to BW80, shift S1 to (%d)\n", + *pucS1); + } + } + } + + DBGLOG(RLM, INFO, "Modify ChannelWidth (%d) and Extend (%d)\n", + *peChannelWidth, *peExtend); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Fill VHT Operation Information(VHT BW, S1, S2) by BSS operating + * channel width + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmFillVhtOpInfoByBssOpBw(struct BSS_INFO *prBssInfo, uint8_t ucBssOpBw) +{ + ASSERT(prBssInfo); + + if (ucBssOpBw < MAX_BW_80MHZ || prBssInfo->eBand == BAND_2G4) { + prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_20_40; + prBssInfo->ucVhtChannelFrequencyS1 = 0; + prBssInfo->ucVhtChannelFrequencyS2 = 0; + } else if (ucBssOpBw == MAX_BW_80MHZ) { + prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_80; + prBssInfo->ucVhtChannelFrequencyS1 = nicGetVhtS1( + prBssInfo->ucPrimaryChannel, VHT_OP_CHANNEL_WIDTH_80); + prBssInfo->ucVhtChannelFrequencyS2 = 0; + } else if (ucBssOpBw == MAX_BW_160MHZ) { + prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_160; + prBssInfo->ucVhtChannelFrequencyS1 = nicGetVhtS1( + prBssInfo->ucPrimaryChannel, VHT_OP_CHANNEL_WIDTH_160); + prBssInfo->ucVhtChannelFrequencyS2 = 0; + } else { + /* 4 TODO: / BW80+80 support */ + DBGLOG(RLM, INFO, "Unsupport BW setting, back to VHT20_40\n"); + + prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_20_40; + prBssInfo->ucVhtChannelFrequencyS1 = 0; + prBssInfo->ucVhtChannelFrequencyS2 = 0; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function should be invoked to update parameters of associated AP. + * (Association response and Beacon) + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static uint8_t rlmRecIeInfoForClient(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, uint8_t *pucIE, + uint16_t u2IELength) +{ + uint16_t u2Offset; + struct STA_RECORD *prStaRec; + struct IE_HT_CAP *prHtCap; + struct IE_HT_OP *prHtOp; + struct IE_OBSS_SCAN_PARAM *prObssScnParam; + uint8_t ucERP, ucPrimaryChannel; + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; + u_int8_t fgHasQuietIE = FALSE; + u_int8_t IsfgHtCapChange = FALSE; + +#if CFG_SUPPORT_802_11AC + struct IE_VHT_OP *prVhtOp; + struct IE_VHT_CAP *prVhtCap; + struct IE_OP_MODE_NOTIFICATION + *prOPModeNotification; /* Operation Mode Notification */ + u_int8_t fgHasOPModeIE = FALSE; + uint8_t ucVhtOpModeChannelWidth = 0; + uint8_t ucVhtOpModeRxNss = 0; + uint8_t ucMaxBwAllowed; + uint8_t ucInitVhtOpMode = 0; +#endif + +#if CFG_SUPPORT_DFS + u_int8_t fgHasWideBandIE = FALSE; + u_int8_t fgHasSCOIE = FALSE; + u_int8_t fgHasChannelSwitchIE = FALSE; + u_int8_t fgNeedSwitchChannel = FALSE; + uint8_t ucChannelAnnouncePri; + enum ENUM_CHNL_EXT eChannelAnnounceSco; + uint8_t ucChannelAnnounceChannelS1 = 0; + uint8_t ucChannelAnnounceChannelS2 = 0; + uint8_t ucChannelAnnounceVhtBw; + struct IE_CHANNEL_SWITCH *prChannelSwitchAnnounceIE; + struct IE_SECONDARY_OFFSET *prSecondaryOffsetIE; + struct IE_WIDE_BAND_CHANNEL *prWideBandChannelIE; +#endif + uint8_t *pucDumpIE; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(pucIE); + + prStaRec = prBssInfo->prStaRecOfAP; + ASSERT(prStaRec); + if (!prStaRec) + return 0; + + prBssInfo->fgUseShortPreamble = prBssInfo->fgIsShortPreambleAllowed; + ucPrimaryChannel = 0; + prObssScnParam = NULL; + ucMaxBwAllowed = cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex); + pucDumpIE = pucIE; + + /* Note: HT-related members in staRec may not be zero before, so + * if following IE does not exist, they are still not zero. + * These HT-related parameters are valid only when the + * corresponding + * BssInfo supports 802.11n, i.e., RLM_NET_IS_11N() + */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) + { + switch (IE_ID(pucIE)) { + case ELEM_ID_HT_CAP: + if (!RLM_NET_IS_11N(prBssInfo) || + IE_LEN(pucIE) != (sizeof(struct IE_HT_CAP) - 2)) + break; + prHtCap = (struct IE_HT_CAP *)pucIE; + prStaRec->ucMcsSet = + prHtCap->rSupMcsSet.aucRxMcsBitmask[0]; + prStaRec->fgSupMcs32 = + (prHtCap->rSupMcsSet.aucRxMcsBitmask[32 / 8] & + BIT(0)) + ? TRUE + : FALSE; + + kalMemCopy( + prStaRec->aucRxMcsBitmask, + prHtCap->rSupMcsSet.aucRxMcsBitmask, + /*SUP_MCS_RX_BITMASK_OCTET_NUM */ + sizeof(prStaRec->aucRxMcsBitmask)); + + prStaRec->u2RxHighestSupportedRate = + prHtCap->rSupMcsSet.u2RxHighestSupportedRate; + prStaRec->u4TxRateInfo = + prHtCap->rSupMcsSet.u4TxRateInfo; + + if ((prStaRec->u2HtCapInfo & + HT_CAP_INFO_SM_POWER_SAVE) != + (prHtCap->u2HtCapInfo & HT_CAP_INFO_SM_POWER_SAVE)) + /* Purpose : To detect SMPS change */ + IsfgHtCapChange = TRUE; + + prStaRec->u2HtCapInfo = prHtCap->u2HtCapInfo; + /* Set LDPC Tx capability */ + if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxLdpc)) + prStaRec->u2HtCapInfo |= HT_CAP_INFO_LDPC_CAP; + else if (IS_FEATURE_DISABLED(prWifiVar->ucTxLdpc)) + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_LDPC_CAP; + + /* Set STBC Tx capability */ + if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxStbc)) + prStaRec->u2HtCapInfo |= HT_CAP_INFO_RX_STBC; + else if (IS_FEATURE_DISABLED(prWifiVar->ucTxStbc)) + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_RX_STBC; + + /* Set Short GI Tx capability */ + if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxShortGI)) { + prStaRec->u2HtCapInfo |= + HT_CAP_INFO_SHORT_GI_20M; + prStaRec->u2HtCapInfo |= + HT_CAP_INFO_SHORT_GI_40M; + } else if (IS_FEATURE_DISABLED( + prWifiVar->ucTxShortGI)) { + prStaRec->u2HtCapInfo &= + ~HT_CAP_INFO_SHORT_GI_20M; + prStaRec->u2HtCapInfo &= + ~HT_CAP_INFO_SHORT_GI_40M; + } + + /* Set HT Greenfield Tx capability */ + if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxGf)) + prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + else if (IS_FEATURE_DISABLED(prWifiVar->ucTxGf)) + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_HT_GF; + + 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(struct IE_HT_OP) - 2)) + break; + prHtOp = (struct IE_HT_OP *)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; + + /*Backup peer HT OP Info*/ + prStaRec->ucHtPeerOpInfo1 = prHtOp->ucInfo1; + + 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 ENUM_CHNL_EXT)( + prBssInfo->ucHtOpInfo1 & + HT_OP_INFO1_SCO); + + /* Revise by own OP BW */ + if (prBssInfo->fgIsOpChangeChannelWidth && + prBssInfo->ucOpChangeChannelWidth == MAX_BW_20MHZ) { + prBssInfo->ucHtOpInfo1 &= + ~(HT_OP_INFO1_SCO | + HT_OP_INFO1_STA_CHNL_WIDTH); + prBssInfo->eBssSCO = CHNL_EXT_SCN; + } + + prBssInfo->eHtProtectMode = (enum ENUM_HT_PROTECT_MODE)( + 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; + +#if CFG_SUPPORT_802_11AC + case ELEM_ID_VHT_CAP: + if (!RLM_NET_IS_11AC(prBssInfo) || + IE_LEN(pucIE) != (sizeof(struct IE_VHT_CAP) - 2)) + break; + + prVhtCap = (struct IE_VHT_CAP *)pucIE; + + prStaRec->u4VhtCapInfo = prVhtCap->u4VhtCapInfo; + /* Set Tx LDPC capability */ + if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxLdpc)) + prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_RX_LDPC; + else if (IS_FEATURE_DISABLED(prWifiVar->ucTxLdpc)) + prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_RX_LDPC; + + /* Set Tx STBC capability */ + if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxStbc)) + prStaRec->u4VhtCapInfo |= + VHT_CAP_INFO_RX_STBC_MASK; + else if (IS_FEATURE_DISABLED(prWifiVar->ucTxStbc)) + prStaRec->u4VhtCapInfo &= + ~VHT_CAP_INFO_RX_STBC_MASK; + + /* Set Tx TXOP PS capability */ + if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxopPsTx)) + prStaRec->u4VhtCapInfo |= + VHT_CAP_INFO_VHT_TXOP_PS; + else if (IS_FEATURE_DISABLED(prWifiVar->ucTxopPsTx)) + prStaRec->u4VhtCapInfo &= + ~VHT_CAP_INFO_VHT_TXOP_PS; + + /* Set Tx Short GI capability */ + if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxShortGI)) { + prStaRec->u4VhtCapInfo |= + VHT_CAP_INFO_SHORT_GI_80; + prStaRec->u4VhtCapInfo |= + VHT_CAP_INFO_SHORT_GI_160_80P80; + } else if (IS_FEATURE_DISABLED( + prWifiVar->ucTxShortGI)) { + prStaRec->u4VhtCapInfo &= + ~VHT_CAP_INFO_SHORT_GI_80; + prStaRec->u4VhtCapInfo &= + ~VHT_CAP_INFO_SHORT_GI_160_80P80; + } + + prStaRec->u2VhtRxMcsMap = + prVhtCap->rVhtSupportedMcsSet.u2RxMcsMap; + + prStaRec->u2VhtRxHighestSupportedDataRate = + prVhtCap->rVhtSupportedMcsSet + .u2RxHighestSupportedDataRate; + prStaRec->u2VhtTxMcsMap = + prVhtCap->rVhtSupportedMcsSet.u2TxMcsMap; + prStaRec->u2VhtTxHighestSupportedDataRate = + prVhtCap->rVhtSupportedMcsSet + .u2TxHighestSupportedDataRate; + + break; + + case ELEM_ID_VHT_OP: + if (!RLM_NET_IS_11AC(prBssInfo) || + IE_LEN(pucIE) != (sizeof(struct IE_VHT_OP) - 2)) + break; + + prVhtOp = (struct IE_VHT_OP *)pucIE; + + /*Backup peer VHT OpInfo*/ + prStaRec->ucVhtOpChannelWidth = + prVhtOp->ucVhtOperation[0]; + prStaRec->ucVhtOpChannelFrequencyS1 = + prVhtOp->ucVhtOperation[1]; + prStaRec->ucVhtOpChannelFrequencyS2 = + prVhtOp->ucVhtOperation[2]; + + rlmModifyVhtBwPara(&prStaRec->ucVhtOpChannelFrequencyS1, + &prStaRec->ucVhtOpChannelFrequencyS2, + &prStaRec->ucVhtOpChannelWidth); + + prBssInfo->ucVhtChannelWidth = + prVhtOp->ucVhtOperation[0]; + prBssInfo->ucVhtChannelFrequencyS1 = + prVhtOp->ucVhtOperation[1]; + prBssInfo->ucVhtChannelFrequencyS2 = + prVhtOp->ucVhtOperation[2]; + prBssInfo->u2VhtBasicMcsSet = prVhtOp->u2VhtBasicMcsSet; + + rlmModifyVhtBwPara(&prBssInfo->ucVhtChannelFrequencyS1, + &prBssInfo->ucVhtChannelFrequencyS2, + &prBssInfo->ucVhtChannelWidth); + + /* Set initial value of VHT OP mode */ + ucInitVhtOpMode = 0; + ucInitVhtOpMode |= + rlmGetOpModeBwByVhtAndHtOpInfo(prBssInfo); + ucInitVhtOpMode |= ((prBssInfo->ucNss - 1) + << VHT_OP_MODE_RX_NSS_OFFSET) & + VHT_OP_MODE_RX_NSS; + + /* Revise by own OP BW if needed */ + if ((prBssInfo->fgIsOpChangeChannelWidth) && + (rlmGetVhtOpBwByBssOpBw( + prBssInfo->ucOpChangeChannelWidth) < + prBssInfo->ucVhtChannelWidth)) { + rlmFillVhtOpInfoByBssOpBw( + prBssInfo, + prBssInfo->ucOpChangeChannelWidth); + } + + break; + case ELEM_ID_OP_MODE: + if (!RLM_NET_IS_11AC(prBssInfo) || + IE_LEN(pucIE) != + (sizeof(struct IE_OP_MODE_NOTIFICATION) - + 2)) + break; + prOPModeNotification = + (struct IE_OP_MODE_NOTIFICATION *)pucIE; + + if ((prOPModeNotification->ucOpMode & + VHT_OP_MODE_RX_NSS_TYPE) != + VHT_OP_MODE_RX_NSS_TYPE) { + if (prStaRec->ucVhtOpMode != + prOPModeNotification->ucOpMode) { + prStaRec->ucVhtOpMode = + prOPModeNotification->ucOpMode; + fgHasOPModeIE = TRUE; + ucVhtOpModeChannelWidth = + ((prOPModeNotification + ->ucOpMode) & + VHT_OP_MODE_CHANNEL_WIDTH); + ucVhtOpModeRxNss = + ((prOPModeNotification + ->ucOpMode) & + VHT_OP_MODE_RX_NSS) >> + VHT_OP_MODE_RX_NSS_OFFSET; + } else + /* Let the further flow not to update + * VhtOpMode + */ + ucInitVhtOpMode = prStaRec->ucVhtOpMode; + } + + break; +#if CFG_SUPPORT_DFS + case ELEM_ID_WIDE_BAND_CHANNEL_SWITCH: + if (!RLM_NET_IS_11AC(prBssInfo) || + IE_LEN(pucIE) != + (sizeof(struct IE_WIDE_BAND_CHANNEL) - 2)) + break; + DBGLOG(RLM, INFO, + "[Channel Switch] ELEM_ID_WIDE_BAND_CHANNEL_SWITCH, 11AC\n"); + prWideBandChannelIE = + (struct IE_WIDE_BAND_CHANNEL *)pucIE; + ucChannelAnnounceVhtBw = + prWideBandChannelIE->ucNewChannelWidth; + ucChannelAnnounceChannelS1 = + prWideBandChannelIE->ucChannelS1; + ucChannelAnnounceChannelS2 = + prWideBandChannelIE->ucChannelS2; + fgHasWideBandIE = TRUE; + DBGLOG(RLM, INFO, "[Ch] BW=%d, s1=%d, s2=%d\n", + ucChannelAnnounceVhtBw, + ucChannelAnnounceChannelS1, + ucChannelAnnounceChannelS2); + break; +#endif + +#endif + 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(struct IE_OBSS_SCAN_PARAM) - 2)) + break; + /* Store OBSS parameters to BssInfo */ + prObssScnParam = (struct IE_OBSS_SCAN_PARAM *)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(struct IE_ERP) - 2) || + prBssInfo->eBand != BAND_2G4) + break; + ucERP = ERP_INFO_IE(pucIE)->ucERP; + prBssInfo->fgErpProtectMode = + (ucERP & ERP_INFO_USE_PROTECTION) ? TRUE + : FALSE; + + if (ucERP & ERP_INFO_BARKER_PREAMBLE_MODE) + prBssInfo->fgUseShortPreamble = FALSE; + break; + + case ELEM_ID_DS_PARAM_SET: + if (IE_LEN(pucIE) == ELEM_MAX_LEN_DS_PARAMETER_SET) + ucPrimaryChannel = + DS_PARAM_IE(pucIE)->ucCurrChnl; + break; +#if CFG_SUPPORT_DFS + case ELEM_ID_CH_SW_ANNOUNCEMENT: + if (IE_LEN(pucIE) != + (sizeof(struct IE_CHANNEL_SWITCH) - 2)) + break; + + prChannelSwitchAnnounceIE = + (struct IE_CHANNEL_SWITCH *)pucIE; + + DBGLOG(RLM, INFO, "[Ch] Count=%d\n", + prChannelSwitchAnnounceIE->ucChannelSwitchCount); + + if (prChannelSwitchAnnounceIE + ->ucChannelSwitchMode == 1) { + /* Need to stop data transmission immediately */ + fgHasChannelSwitchIE = TRUE; + if (!g_fgHasStopTx) { + g_fgHasStopTx = TRUE; +#if CFG_SUPPORT_TDLS + /* TDLS peers */ + TdlsTxCtrl(prAdapter, + prBssInfo, + FALSE); +#endif + /* AP */ + qmSetStaRecTxAllowed(prAdapter, + prStaRec, + FALSE); + DBGLOG(RLM, EVENT, + "[Ch] TxAllowed = FALSE\n"); + } + + if (prChannelSwitchAnnounceIE + ->ucChannelSwitchCount <= 3) { + DBGLOG(RLM, INFO, + "[Ch] switch channel [%d]->[%d]\n", + prBssInfo->ucPrimaryChannel, + prChannelSwitchAnnounceIE + ->ucNewChannelNum); + ucChannelAnnouncePri = + prChannelSwitchAnnounceIE + ->ucNewChannelNum; + fgNeedSwitchChannel = TRUE; +#ifdef CFG_DFS_CHSW_FORCE_BW20 + g_fgHasChannelSwitchIE = TRUE; + } + if (RLM_NET_IS_11AC(prBssInfo)) { + DBGLOG(RLM, INFO, + "Send Operation Action Frame"); + rlmSendOpModeNotificationFrame( + prAdapter, prStaRec, + VHT_OP_MODE_CHANNEL_WIDTH_20, + 1); + } else { + DBGLOG(RLM, INFO, + "Skip Send Operation Action Frame"); + } +#else + } +#endif + } + + break; + case ELEM_ID_SCO: + if (IE_LEN(pucIE) != + (sizeof(struct IE_SECONDARY_OFFSET) - 2)) + break; + + prSecondaryOffsetIE = + (struct IE_SECONDARY_OFFSET *)pucIE; + DBGLOG(RLM, INFO, "[Channel Switch] SCO [%d]->[%d]\n", + prBssInfo->eBssSCO, + prSecondaryOffsetIE->ucSecondaryOffset); + eChannelAnnounceSco = + (enum ENUM_CHNL_EXT) + prSecondaryOffsetIE->ucSecondaryOffset; + fgHasSCOIE = TRUE; + break; +#endif + + /* 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: +#if CFG_SUPPORT_QUIET && 0 + rrmQuietHandleQuietIE(prBssInfo, + (struct IE_QUIET *)pucIE); +#endif + fgHasQuietIE = TRUE; + break; + default: + break; + } /* end of switch */ + } /* end of IE_FOR_EACH */ + + if (IsfgHtCapChange && (prStaRec->ucStaState == STA_STATE_3)) + cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); + + /* 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_802_11AC + /* Check whether the Operation Mode IE is exist or not. + * If exists, then the channel bandwidth of VHT operation field is + * changed + * with the channel bandwidth setting of Operation Mode field. + * The channel bandwidth of OP Mode IE is 0, represent as 20MHz. + * The channel bandwidth of OP Mode IE is 1, represent as 40MHz. + * The channel bandwidth of OP Mode IE is 2, represent as 80MHz. + * The channel bandwidth of OP Mode IE is 3, represent as + * 160/80+80MHz. + */ + if (fgHasOPModeIE == TRUE) { + if (prStaRec->ucStaState == STA_STATE_3) { + /* 1. Modify channel width parameters */ + rlmRecOpModeBwForClient(ucVhtOpModeChannelWidth, + prBssInfo); + + /* 2. Update StaRec to FW (BssInfo will be updated after + * return from this function) + */ + DBGLOG(RLM, INFO, + "Update OpMode to 0x%x, to FW due to OpMode Notificaition", + prStaRec->ucVhtOpMode); + cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); + + /* 3. Revise by own OP BW if needed */ + if ((prBssInfo->fgIsOpChangeChannelWidth)) { + /* VHT */ + if (rlmGetVhtOpBwByBssOpBw( + prBssInfo->ucOpChangeChannelWidth) < + prBssInfo->ucVhtChannelWidth) + rlmFillVhtOpInfoByBssOpBw( + prBssInfo, + prBssInfo->ucOpChangeChannelWidth); + /* HT */ + if (prBssInfo->fgIsOpChangeChannelWidth && + prBssInfo->ucOpChangeChannelWidth == + MAX_BW_20MHZ) { + prBssInfo->ucHtOpInfo1 &= + ~(HT_OP_INFO1_SCO | + HT_OP_INFO1_STA_CHNL_WIDTH); + prBssInfo->eBssSCO = CHNL_EXT_SCN; + } + } + } + } else { /* Set Default if the VHT OP mode field is not present */ + if ((prStaRec->ucVhtOpMode != ucInitVhtOpMode) && + (prStaRec->ucStaState == STA_STATE_3)) { + prStaRec->ucVhtOpMode = ucInitVhtOpMode; + DBGLOG(RLM, INFO, "Update OpMode to 0x%x", + prStaRec->ucVhtOpMode); + DBGLOG(RLM, INFO, + "to FW due to NO OpMode Notificaition\n"); + cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); + } else + prStaRec->ucVhtOpMode = ucInitVhtOpMode; + } +#endif + +#if CFG_SUPPORT_DFS + /* Check whether Channel Announcement IE, Secondary Offset IE & + * Wide Bandwidth Channel Switch IE exist or not. If exist, the + * priority is + * the highest. + */ + + if (fgNeedSwitchChannel) { + struct BSS_DESC *prBssDesc = NULL; + struct PARAM_SSID rSsid; + + prBssInfo->ucPrimaryChannel = ucChannelAnnouncePri; + /* Change to BW20 for certification issue due to signal sidelope + * leakage + */ + prBssInfo->ucVhtChannelWidth = 0; + prBssInfo->ucVhtChannelFrequencyS1 = 0; + prBssInfo->ucVhtChannelFrequencyS2 = 0; + prBssInfo->eBssSCO = 0; + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, prBssInfo->aucSSID, + prBssInfo->ucSSIDLen); + prBssDesc = scanSearchBssDescByBssidAndSsid( + prAdapter, prBssInfo->aucBSSID, TRUE, &rSsid); + + if (prBssDesc) { + DBGLOG(RLM, INFO, + "DFS: BSS: " MACSTR + " Desc found, channel from %u to %u\n ", + MAC2STR(prBssInfo->aucBSSID), + prBssDesc->ucChannelNum, ucChannelAnnouncePri); + prBssDesc->ucChannelNum = ucChannelAnnouncePri; + } else { + DBGLOG(RLM, INFO, + "DFS: BSS: " MACSTR " Desc is not found\n ", + MAC2STR(prBssInfo->aucBSSID)); + } + + if (fgHasWideBandIE != FALSE) { + prBssInfo->ucVhtChannelWidth = ucChannelAnnounceVhtBw; + prBssInfo->ucVhtChannelFrequencyS1 = + ucChannelAnnounceChannelS1; + prBssInfo->ucVhtChannelFrequencyS2 = + ucChannelAnnounceChannelS2; + + /* Revise by own OP BW if needed */ + if ((prBssInfo->fgIsOpChangeChannelWidth) && + (rlmGetVhtOpBwByBssOpBw( + prBssInfo->ucOpChangeChannelWidth) < + prBssInfo->ucVhtChannelWidth)) { + + DBGLOG(RLM, LOUD, + "Change to w:%d s1:%d s2:%d since own changed BW < peer's WideBand BW", + prBssInfo->ucVhtChannelWidth, + prBssInfo->ucVhtChannelFrequencyS1, + prBssInfo->ucVhtChannelFrequencyS2); + rlmFillVhtOpInfoByBssOpBw( + prBssInfo, + prBssInfo->ucOpChangeChannelWidth); + } + } + if (fgHasSCOIE != FALSE) + prBssInfo->eBssSCO = eChannelAnnounceSco; + + if (prBssDesc) { + kalIndicateChannelSwitch(prAdapter->prGlueInfo, + prBssInfo->eBssSCO, + prBssDesc->ucChannelNum); + } + } + + if (!fgHasChannelSwitchIE && g_fgHasStopTx) { +#if CFG_SUPPORT_TDLS + /* TDLS peers */ + TdlsTxCtrl(prAdapter, prBssInfo, TRUE); +#endif + /* AP */ + qmSetStaRecTxAllowed(prAdapter, prStaRec, TRUE); + + DBGLOG(RLM, EVENT, "[Ch] TxAllowed = TRUE\n"); + g_fgHasStopTx = FALSE; + } + +#ifdef CFG_DFS_CHSW_FORCE_BW20 + /*DFS Certification for Channel Bandwidth 20MHz */ + DBGLOG(RLM, INFO, "Ch : SwitchIE = %d\n", g_fgHasChannelSwitchIE); + if (g_fgHasChannelSwitchIE == TRUE) { + prBssInfo->eBssSCO = CHNL_EXT_SCN; + prBssInfo->ucVhtChannelWidth = CW_20_40MHZ; + prBssInfo->ucVhtChannelFrequencyS1 = 0; + prBssInfo->ucVhtChannelFrequencyS2 = 255; + prBssInfo->ucHtOpInfo1 &= + ~(HT_OP_INFO1_SCO | HT_OP_INFO1_STA_CHNL_WIDTH); + DBGLOG(RLM, INFO, "Ch : DFS has Appeared\n"); + } +#endif +#endif + rlmReviseMaxBw(prAdapter, prBssInfo->ucBssIndex, &prBssInfo->eBssSCO, + (enum ENUM_CHANNEL_WIDTH *)&prBssInfo->ucVhtChannelWidth, + &prBssInfo->ucVhtChannelFrequencyS1, + &prBssInfo->ucPrimaryChannel); + + rlmRevisePreferBandwidthNss(prAdapter, prBssInfo->ucBssIndex, prStaRec); + + if (!rlmDomainIsValidRfSetting( + prAdapter, prBssInfo->eBand, prBssInfo->ucPrimaryChannel, + prBssInfo->eBssSCO, prBssInfo->ucVhtChannelWidth, + prBssInfo->ucVhtChannelFrequencyS1, + prBssInfo->ucVhtChannelFrequencyS2)) { + + /*Dump IE Inforamtion */ + DBGLOG(RLM, WARN, "rlmRecIeInfoForClient IE Information\n"); + DBGLOG(RLM, WARN, "IE Length = %d\n", u2IELength); + DBGLOG_MEM8(RLM, WARN, pucDumpIE, u2IELength); + + /*Error Handling for Non-predicted IE - Fixed to set 20MHz */ + prBssInfo->ucVhtChannelWidth = CW_20_40MHZ; + prBssInfo->ucVhtChannelFrequencyS1 = 0; + prBssInfo->ucVhtChannelFrequencyS2 = 0; + prBssInfo->eBssSCO = CHNL_EXT_SCN; + prBssInfo->ucHtOpInfo1 &= + ~(HT_OP_INFO1_SCO | HT_OP_INFO1_STA_CHNL_WIDTH); + } +#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); + } + } + +#if CFG_SUPPORT_DFS + g_fgFowardBcn2Supplicant = + fgHasQuietIE | + fgHasChannelSwitchIE | + fgHasWideBandIE; +#endif + + return ucPrimaryChannel; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Update parameters from channel width field in OP Mode IE/action frame + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static void rlmRecOpModeBwForClient(uint8_t ucVhtOpModeChannelWidth, + struct BSS_INFO *prBssInfo) +{ + + struct STA_RECORD *prStaRec = NULL; + + if (!prBssInfo) + return; + + prStaRec = prBssInfo->prStaRecOfAP; + if (!prStaRec) + return; + + switch (ucVhtOpModeChannelWidth) { + case VHT_OP_MODE_CHANNEL_WIDTH_20: + prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_20_40; + prBssInfo->ucHtOpInfo1 &= ~HT_OP_INFO1_STA_CHNL_WIDTH; + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SUP_CHNL_WIDTH; + +#if CFG_OPMODE_CONFLICT_OPINFO + if (prBssInfo->eBssSCO != CHNL_EXT_SCN) { + DBGLOG(RLM, WARN, + "HT_OP_Info != OPmode_Notifify, follow OPmode_Notify to BW20.\n"); + prBssInfo->eBssSCO = CHNL_EXT_SCN; + } +#endif + break; + case VHT_OP_MODE_CHANNEL_WIDTH_40: + prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_20_40; + prBssInfo->ucHtOpInfo1 |= HT_OP_INFO1_STA_CHNL_WIDTH; + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; + +#if CFG_OPMODE_CONFLICT_OPINFO + if (prBssInfo->eBssSCO == CHNL_EXT_SCN) { + prBssInfo->ucHtOpInfo1 &= ~HT_OP_INFO1_STA_CHNL_WIDTH; + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SUP_CHNL_WIDTH; + DBGLOG(RLM, WARN, + "HT_OP_Info != OPmode_Notifify, follow HT_OP_Info to BW20.\n"); + } +#endif + break; + case VHT_OP_MODE_CHANNEL_WIDTH_80: +#if CFG_OPMODE_CONFLICT_OPINFO + if (prBssInfo->ucVhtChannelWidth != + VHT_OP_MODE_CHANNEL_WIDTH_80) { + DBGLOG(RLM, WARN, + "VHT_OP != OPmode:%d, follow VHT_OP to VHT_OP:%d HT_OP:%d\n", + ucVhtOpModeChannelWidth, + prBssInfo->ucVhtChannelWidth, + (uint8_t)(prBssInfo->ucHtOpInfo1 & + HT_OP_INFO1_STA_CHNL_WIDTH) >> + HT_OP_INFO1_STA_CHNL_WIDTH_OFFSET); + } else +#endif + { + prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_80; + prBssInfo->ucHtOpInfo1 |= HT_OP_INFO1_STA_CHNL_WIDTH; + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; + } + break; + case VHT_OP_MODE_CHANNEL_WIDTH_160_80P80: +/* Determine BW160 or BW80+BW80 by VHT OP Info */ +#if CFG_OPMODE_CONFLICT_OPINFO + if ((prBssInfo->ucVhtChannelWidth != + VHT_OP_CHANNEL_WIDTH_160) && + (prBssInfo->ucVhtChannelWidth != + VHT_OP_CHANNEL_WIDTH_80P80)) { + DBGLOG(RLM, WARN, + "VHT_OP != OPmode:%d, follow VHT_OP to VHT_OP:%d HT_OP:%d\n", + ucVhtOpModeChannelWidth, + prBssInfo->ucVhtChannelWidth, + (uint8_t)(prBssInfo->ucHtOpInfo1 & + HT_OP_INFO1_STA_CHNL_WIDTH) >> + HT_OP_INFO1_STA_CHNL_WIDTH_OFFSET); + } else +#endif + { + prBssInfo->ucHtOpInfo1 |= HT_OP_INFO1_STA_CHNL_WIDTH; + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; + } + break; + default: + break; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Update parameters from Association Response frame + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static void rlmRecAssocRespIeInfoForClient(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + uint8_t *pucIE, uint16_t u2IELength) +{ + uint16_t u2Offset; + struct STA_RECORD *prStaRec; + u_int8_t fgIsHasHtCap = FALSE; + u_int8_t fgIsHasVhtCap = FALSE; + struct BSS_DESC *prBssDesc; + struct PARAM_SSID rSsid; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(pucIE); + + prStaRec = prBssInfo->prStaRecOfAP; + + ASSERT(prStaRec); + if (!prStaRec) + return; + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, prBssInfo->aucSSID, + prBssInfo->ucSSIDLen); + prBssDesc = scanSearchBssDescByBssidAndSsid( + prAdapter, prStaRec->aucMacAddr, TRUE, &rSsid); + + 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(struct IE_HT_CAP) - 2)) + break; + fgIsHasHtCap = TRUE; + break; +#if CFG_SUPPORT_802_11AC + case ELEM_ID_VHT_CAP: + if (!RLM_NET_IS_11AC(prBssInfo) || + IE_LEN(pucIE) != (sizeof(struct IE_VHT_CAP) - 2)) + break; + fgIsHasVhtCap = TRUE; + break; +#endif + default: + break; + } /* end of switch */ + } /* end of IE_FOR_EACH */ + + if (!fgIsHasHtCap) { + prStaRec->ucDesiredPhyTypeSet &= ~PHY_TYPE_BIT_HT; + if (prBssDesc) { + if (prBssDesc->ucPhyTypeSet & PHY_TYPE_BIT_HT) { + DBGLOG(RLM, WARN, + "PhyTypeSet in Beacon and AssocResp are unsync. "); + DBGLOG(RLM, WARN, + "Follow AssocResp to disable HT.\n"); + } + } + } + if (!fgIsHasVhtCap) { + prStaRec->ucDesiredPhyTypeSet &= ~PHY_TYPE_BIT_VHT; + if (prBssDesc) { + if (prBssDesc->ucPhyTypeSet & PHY_TYPE_BIT_VHT) { + DBGLOG(RLM, WARN, + "PhyTypeSet in Beacon and AssocResp are unsync. "); + DBGLOG(RLM, WARN, + "Follow AssocResp to disable VHT.\n"); + } + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief AIS or P2P GC. + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static u_int8_t rlmRecBcnFromNeighborForClient(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct SW_RFB *prSwRfb, + uint8_t *pucIE, + uint16_t u2IELength) +{ + uint16_t u2Offset, i; + uint8_t ucPriChannel, ucSecChannel; + enum ENUM_CHNL_EXT eSCO; + u_int8_t 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: { + struct IE_HT_CAP *prHtCap; + + if (IE_LEN(pucIE) != (sizeof(struct IE_HT_CAP) - 2)) + break; + + prHtCap = (struct IE_HT_CAP *)pucIE; + if (prHtCap->u2HtCapInfo & HT_CAP_INFO_40M_INTOLERANT) + fg20mReq = TRUE; + fgHtBss = TRUE; + break; + } + case ELEM_ID_HT_OP: { + struct IE_HT_OP *prHtOp; + + if (IE_LEN(pucIE) != (sizeof(struct IE_HT_OP) - 2)) + break; + + prHtOp = (struct IE_HT_OP *)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 ENUM_CHNL_EXT)(prHtOp->ucInfo1 & + HT_OP_INFO1_SCO); + break; + } + case ELEM_ID_20_40_BSS_COEXISTENCE: { + struct IE_20_40_COEXIST *prCoexist; + + if (IE_LEN(pucIE) != + (sizeof(struct IE_20_40_COEXIST) - 2)) + break; + + prCoexist = (struct IE_20_40_COEXIST *)pucIE; + if (prCoexist->ucData & BSS_COEXIST_40M_INTOLERANT) + fg20mReq = TRUE; + break; + } + case ELEM_ID_DS_PARAM_SET: + if (IE_LEN(pucIE) != + (sizeof(struct IE_DS_PARAM_SET) - 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 (HAL_RX_STATUS_GET_RF_BAND(prSwRfb->prRxStatus) != BAND_2G4) + return FALSE; + + if (ucPriChannel == 0 || ucPriChannel > 14) + ucPriChannel = HAL_RX_STATUS_GET_CHNL_NUM(prSwRfb->prRxStatus); + + 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 u_int8_t rlmRecBcnInfoForClient(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct SW_RFB *prSwRfb, uint8_t *pucIE, + uint16_t u2IELength) +{ + /* For checking if syncing params are different from + * last syncing and need to sync again + */ + struct CMD_SET_BSS_RLM_PARAM rBssRlmParam; + u_int8_t fgNewParameter = FALSE; + + 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 = + ((struct WLAN_BEACON_FRAME *)(prSwRfb->pvHeader))->u2CapInfo; + prBssInfo->fgUseShortSlotTime = + ((prBssInfo->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME) || + (prBssInfo->eBand != BAND_2G4)) + ? TRUE + : FALSE; + + /* Check if syncing params are different from last syncing and need to + * sync again + * If yes, return TRUE and sync with FW; Otherwise, return FALSE. + */ + rBssRlmParam.ucRfBand = (u_int8_t)prBssInfo->eBand; + rBssRlmParam.ucPrimaryChannel = prBssInfo->ucPrimaryChannel; + rBssRlmParam.ucRfSco = (u_int8_t)prBssInfo->eBssSCO; + rBssRlmParam.ucErpProtectMode = (u_int8_t)prBssInfo->fgErpProtectMode; + rBssRlmParam.ucHtProtectMode = (u_int8_t)prBssInfo->eHtProtectMode; + rBssRlmParam.ucGfOperationMode = (u_int8_t)prBssInfo->eGfOperationMode; + rBssRlmParam.ucTxRifsMode = (u_int8_t)prBssInfo->eRifsOperationMode; + rBssRlmParam.u2HtOpInfo3 = prBssInfo->u2HtOpInfo3; + rBssRlmParam.u2HtOpInfo2 = prBssInfo->u2HtOpInfo2; + rBssRlmParam.ucHtOpInfo1 = prBssInfo->ucHtOpInfo1; + rBssRlmParam.ucUseShortPreamble = prBssInfo->fgUseShortPreamble; + rBssRlmParam.ucUseShortSlotTime = prBssInfo->fgUseShortSlotTime; + rBssRlmParam.ucVhtChannelWidth = prBssInfo->ucVhtChannelWidth; + rBssRlmParam.ucVhtChannelFrequencyS1 = + prBssInfo->ucVhtChannelFrequencyS1; + rBssRlmParam.ucVhtChannelFrequencyS2 = + prBssInfo->ucVhtChannelFrequencyS2; + rBssRlmParam.u2VhtBasicMcsSet = prBssInfo->u2VhtBasicMcsSet; + rBssRlmParam.ucNss = prBssInfo->ucNss; + + rlmRecIeInfoForClient(prAdapter, prBssInfo, pucIE, u2IELength); + + if (g_fgFowardBcn2Supplicant) { + kalIndicateRxMgmtFrame(prAdapter->prGlueInfo, prSwRfb); + g_fgFowardBcn2Supplicant = FALSE; + } + + if (rBssRlmParam.ucRfBand != prBssInfo->eBand || + rBssRlmParam.ucPrimaryChannel != prBssInfo->ucPrimaryChannel || + rBssRlmParam.ucRfSco != prBssInfo->eBssSCO || + rBssRlmParam.ucErpProtectMode != prBssInfo->fgErpProtectMode || + rBssRlmParam.ucHtProtectMode != prBssInfo->eHtProtectMode || + rBssRlmParam.ucGfOperationMode != prBssInfo->eGfOperationMode || + rBssRlmParam.ucTxRifsMode != prBssInfo->eRifsOperationMode || + rBssRlmParam.u2HtOpInfo3 != prBssInfo->u2HtOpInfo3 || + rBssRlmParam.u2HtOpInfo2 != prBssInfo->u2HtOpInfo2 || + rBssRlmParam.ucHtOpInfo1 != prBssInfo->ucHtOpInfo1 || + rBssRlmParam.ucUseShortPreamble != prBssInfo->fgUseShortPreamble || + rBssRlmParam.ucUseShortSlotTime != prBssInfo->fgUseShortSlotTime || + rBssRlmParam.ucVhtChannelWidth != prBssInfo->ucVhtChannelWidth || + rBssRlmParam.ucVhtChannelFrequencyS1 != + prBssInfo->ucVhtChannelFrequencyS1 || + rBssRlmParam.ucVhtChannelFrequencyS2 != + prBssInfo->ucVhtChannelFrequencyS2 || + rBssRlmParam.u2VhtBasicMcsSet != prBssInfo->u2VhtBasicMcsSet || + rBssRlmParam.ucNss != prBssInfo->ucNss) + fgNewParameter = TRUE; + else { + DBGLOG(RLM, TRACE, + "prBssInfo's params are all the same! not to sync!\n"); + fgNewParameter = FALSE; + } + + return fgNewParameter; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmProcessBcn(struct ADAPTER *prAdapter, struct SW_RFB *prSwRfb, + uint8_t *pucIE, uint16_t u2IELength) +{ + struct BSS_INFO *prBssInfo; + u_int8_t fgNewParameter; + uint8_t i; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + ASSERT(pucIE); + + fgNewParameter = FALSE; + + /* When concurrent networks exist, GO shall have the same handle as + * the other BSS, so the Beacon shall be processed for bandwidth and + * protection mechanism. + * Note1: we do not have 2 AP (GO) cases simultaneously now. + * Note2: If we are GO, concurrent AIS AP should detect it and reflect + * action in its Beacon, so AIS STA just follows Beacon from AP. + */ + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + + if (IS_BSS_BOW(prBssInfo)) + continue; + + 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, + ((struct WLAN_MAC_MGMT_HEADER + *)(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: Nothing */ + /* To do: Ad-hoc */ + } + + /* Appy new parameters if necessary */ + if (fgNewParameter) { + rlmSyncOperationParams(prAdapter, prBssInfo); + fgNewParameter = FALSE; + } + } /* end of IS_BSS_ACTIVE() */ + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function should be invoked after judging successful association. + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmProcessAssocRsp(struct ADAPTER *prAdapter, struct SW_RFB *prSwRfb, + uint8_t *pucIE, uint16_t u2IELength) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint8_t ucPriChannel; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + ASSERT(pucIE); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (!prStaRec) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + if (!prBssInfo) + return; + + if (prStaRec != prBssInfo->prStaRecOfAP) + return; + + /* 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) || + (prBssInfo->eBand != BAND_2G4)) + ? TRUE + : FALSE; + ucPriChannel = + rlmRecIeInfoForClient(prAdapter, prBssInfo, pucIE, u2IELength); + + /*Update the parameters from Association Response only, + *if the parameters need to be updated by both Beacon and Association + *Response, + *user should use another function, rlmRecIeInfoForClient() + */ + rlmRecAssocRespIeInfoForClient(prAdapter, prBssInfo, pucIE, u2IELength); + + if (prBssInfo->ucPrimaryChannel != ucPriChannel) { + DBGLOG(RLM, INFO, + "Use RF pri channel[%u].Pri channel in HT OP IE is :[%u]\n", + prBssInfo->ucPrimaryChannel, ucPriChannel); + } + /* Avoid wrong primary channel info in HT operation + * IE info when accept association response + */ +#if 0 + if (ucPriChannel > 0) + prBssInfo->ucPrimaryChannel = ucPriChannel; +#endif + + 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 + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmProcessHtAction(struct ADAPTER *prAdapter, struct SW_RFB *prSwRfb) +{ + struct ACTION_NOTIFY_CHNL_WIDTH_FRAME *prRxFrame; + struct ACTION_SM_POWER_SAVE_FRAME *prRxSmpsFrame; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + uint16_t u2HtCapInfoBitmask = 0; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxFrame = (struct ACTION_NOTIFY_CHNL_WIDTH_FRAME *)prSwRfb->pvHeader; + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (!prStaRec) + return; + + switch (prRxFrame->ucAction) { + case ACTION_HT_NOTIFY_CHANNEL_WIDTH: + if (prStaRec->ucStaState != STA_STATE_3 || + prSwRfb->u2PacketLen < + sizeof(struct 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 + */ + /* 1. Update StaRec for AP/STA mode */ + if (prRxFrame->ucChannelWidth == HT_NOTIFY_CHANNEL_WIDTH_20) + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SUP_CHNL_WIDTH; + else if (prRxFrame->ucChannelWidth == + HT_NOTIFY_CHANNEL_WIDTH_ANY_SUPPORT_CAHNNAEL_WIDTH) + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; + + cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); + + /* 2. Update BssInfo for STA mode */ + prBssInfo = prAdapter->aprBssInfo[prStaRec->ucBssIndex]; + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + if (prRxFrame->ucChannelWidth == + HT_NOTIFY_CHANNEL_WIDTH_20) { + prBssInfo->ucHtOpInfo1 &= + ~HT_OP_INFO1_STA_CHNL_WIDTH; + prBssInfo->eBssSCO = CHNL_EXT_SCN; + } else if ( + prRxFrame->ucChannelWidth == + HT_NOTIFY_CHANNEL_WIDTH_ANY_SUPPORT_CAHNNAEL_WIDTH) + prBssInfo->ucHtOpInfo1 |= + HT_OP_INFO1_STA_CHNL_WIDTH; + + /* Revise by own OP BW if needed */ + if (prBssInfo->fgIsOpChangeChannelWidth && + prBssInfo->ucOpChangeChannelWidth == MAX_BW_20MHZ) { + prBssInfo->ucHtOpInfo1 &= + ~(HT_OP_INFO1_SCO | + HT_OP_INFO1_STA_CHNL_WIDTH); + prBssInfo->eBssSCO = CHNL_EXT_SCN; + } + + /* 3. Update OP BW to FW */ + rlmSyncOperationParams(prAdapter, prBssInfo); + } + break; + /* Support SM power save */ /* TH3_Huang */ + case ACTION_HT_SM_POWER_SAVE: + prRxSmpsFrame = + (struct ACTION_SM_POWER_SAVE_FRAME *)prSwRfb->pvHeader; + if (prStaRec->ucStaState != STA_STATE_3 || + prSwRfb->u2PacketLen < + sizeof(struct ACTION_SM_POWER_SAVE_FRAME)) { + return; + } + + /* The SM power enable bit is different definition in HtCap and + * SMpower IE field + */ + if (!(prRxSmpsFrame->ucSmPowerCtrl & + (HT_SM_POWER_SAVE_CONTROL_ENABLED | + HT_SM_POWER_SAVE_CONTROL_SM_MODE))) + u2HtCapInfoBitmask |= HT_CAP_INFO_SM_POWER_SAVE; + + /* Support SMPS action frame, TH3_Huang */ + /* Update StaRec if SM power state changed */ + if ((prStaRec->u2HtCapInfo & HT_CAP_INFO_SM_POWER_SAVE) != + u2HtCapInfoBitmask) { + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SM_POWER_SAVE; + prStaRec->u2HtCapInfo |= u2HtCapInfoBitmask; + DBGLOG(RLM, INFO, + "rlmProcessHtAction -- SMPS change u2HtCapInfo to (%x)\n", + prStaRec->u2HtCapInfo); + cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); + } + break; + default: + break; + } +} + +#if CFG_SUPPORT_802_11AC +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmProcessVhtAction(struct ADAPTER *prAdapter, struct SW_RFB *prSwRfb) +{ + struct ACTION_OP_MODE_NOTIFICATION_FRAME *prRxFrame; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + uint8_t ucVhtOpModeChannelWidth = 0; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxFrame = + (struct ACTION_OP_MODE_NOTIFICATION_FRAME *)prSwRfb->pvHeader; + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (!prStaRec) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + if (!prBssInfo) + return; + + switch (prRxFrame->ucAction) { + /* Support Operating mode notification action frame, TH3_Huang */ + case ACTION_OPERATING_MODE_NOTIFICATION: + if (prStaRec->ucStaState != STA_STATE_3 || + prSwRfb->u2PacketLen < + sizeof(struct ACTION_OP_MODE_NOTIFICATION_FRAME)) { + return; + } + + if (((prRxFrame->ucOperatingMode & VHT_OP_MODE_RX_NSS_TYPE) != + VHT_OP_MODE_RX_NSS_TYPE) && + (prStaRec->ucVhtOpMode != prRxFrame->ucOperatingMode)) { + /* 1. Fill OP mode notification info */ + prStaRec->ucVhtOpMode = prRxFrame->ucOperatingMode; + DBGLOG(RLM, INFO, + "rlmProcessVhtAction -- Update ucVhtOpMode to 0x%x\n", + prStaRec->ucVhtOpMode); + + /* 2. Modify channel width parameters */ + ucVhtOpModeChannelWidth = prRxFrame->ucOperatingMode & + VHT_OP_MODE_CHANNEL_WIDTH; + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + if (ucVhtOpModeChannelWidth == + VHT_OP_MODE_CHANNEL_WIDTH_20) + prStaRec->u2HtCapInfo &= + ~HT_CAP_INFO_SUP_CHNL_WIDTH; + else /* for other 3 VHT cases: 40/80/160 */ + prStaRec->u2HtCapInfo |= + HT_CAP_INFO_SUP_CHNL_WIDTH; + } else if (prBssInfo->eCurrentOPMode == + OP_MODE_INFRASTRUCTURE) + rlmRecOpModeBwForClient(ucVhtOpModeChannelWidth, + prBssInfo); + + /* 3. Update StaRec to FW */ + cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); + + /* 4. Update BW parameters in BssInfo for STA mode only + */ + if (prBssInfo->eCurrentOPMode == + OP_MODE_INFRASTRUCTURE) { + /* 4.1 Revise by own OP BW if needed for STA + * mode only + */ + if (prBssInfo->fgIsOpChangeChannelWidth) { + /* VHT */ + if (rlmGetVhtOpBwByBssOpBw( + prBssInfo->ucOpChangeChannelWidth) < + prBssInfo->ucVhtChannelWidth) + rlmFillVhtOpInfoByBssOpBw( + prBssInfo, + prBssInfo->ucOpChangeChannelWidth); + /* HT */ + if (prBssInfo + ->fgIsOpChangeChannelWidth && + prBssInfo->ucOpChangeChannelWidth == + MAX_BW_20MHZ) { + prBssInfo->ucHtOpInfo1 &= ~( + HT_OP_INFO1_SCO | + HT_OP_INFO1_STA_CHNL_WIDTH); + prBssInfo->eBssSCO = + CHNL_EXT_SCN; + } + } + + /* 4.2 Check if OP BW parameter valid */ + if (!rlmDomainIsValidRfSetting( + prAdapter, prBssInfo->eBand, + prBssInfo->ucPrimaryChannel, + prBssInfo->eBssSCO, + prBssInfo->ucVhtChannelWidth, + prBssInfo->ucVhtChannelFrequencyS1, + prBssInfo->ucVhtChannelFrequencyS2)) { + + DBGLOG(RLM, WARN, + "rlmProcessVhtAction invalid RF settings\n"); + + /* Error Handling for Non-predicted IE - + * Fixed to set 20MHz + */ + prBssInfo->ucVhtChannelWidth = + CW_20_40MHZ; + prBssInfo->ucVhtChannelFrequencyS1 = 0; + prBssInfo->ucVhtChannelFrequencyS2 = 0; + prBssInfo->eBssSCO = CHNL_EXT_SCN; + prBssInfo->ucHtOpInfo1 &= + ~(HT_OP_INFO1_SCO | + HT_OP_INFO1_STA_CHNL_WIDTH); + } + + /* 4.3 Update BSS OP BW to FW for STA mode only + */ + rlmSyncOperationParams(prAdapter, prBssInfo); + } + } + break; + default: + break; + } +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function should be invoked after judging successful association. + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmFillSyncCmdParam(struct CMD_SET_BSS_RLM_PARAM *prCmdBody, + struct BSS_INFO *prBssInfo) +{ + ASSERT(prCmdBody && prBssInfo); + if (!prCmdBody || !prBssInfo) + return; + + prCmdBody->ucBssIndex = prBssInfo->ucBssIndex; + prCmdBody->ucRfBand = (uint8_t)prBssInfo->eBand; + prCmdBody->ucPrimaryChannel = prBssInfo->ucPrimaryChannel; + prCmdBody->ucRfSco = (uint8_t)prBssInfo->eBssSCO; + prCmdBody->ucErpProtectMode = (uint8_t)prBssInfo->fgErpProtectMode; + prCmdBody->ucHtProtectMode = (uint8_t)prBssInfo->eHtProtectMode; + prCmdBody->ucGfOperationMode = (uint8_t)prBssInfo->eGfOperationMode; + prCmdBody->ucTxRifsMode = (uint8_t)prBssInfo->eRifsOperationMode; + prCmdBody->u2HtOpInfo3 = prBssInfo->u2HtOpInfo3; + prCmdBody->u2HtOpInfo2 = prBssInfo->u2HtOpInfo2; + prCmdBody->ucHtOpInfo1 = prBssInfo->ucHtOpInfo1; + prCmdBody->ucUseShortPreamble = prBssInfo->fgUseShortPreamble; + prCmdBody->ucUseShortSlotTime = prBssInfo->fgUseShortSlotTime; + prCmdBody->ucVhtChannelWidth = prBssInfo->ucVhtChannelWidth; + prCmdBody->ucVhtChannelFrequencyS1 = prBssInfo->ucVhtChannelFrequencyS1; + prCmdBody->ucVhtChannelFrequencyS2 = prBssInfo->ucVhtChannelFrequencyS2; + prCmdBody->u2VhtBasicMcsSet = prBssInfo->u2BSSBasicRateSet; + prCmdBody->ucNss = prBssInfo->ucNss; + + 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 w=%d s1=%d s2=%d n=%d\n", + prCmdBody->ucBssIndex, prCmdBody->ucRfBand, + prCmdBody->ucPrimaryChannel, prCmdBody->ucRfSco, + prCmdBody->ucErpProtectMode, prCmdBody->ucHtProtectMode, + prCmdBody->ucHtOpInfo1, prCmdBody->ucUseShortSlotTime, + prCmdBody->ucUseShortPreamble, + prCmdBody->ucVhtChannelWidth, + prCmdBody->ucVhtChannelFrequencyS1, + prCmdBody->ucVhtChannelFrequencyS2, prCmdBody->ucNss); + } else { + DBGLOG(RLM, INFO, "N=%d closed\n", prCmdBody->ucBssIndex); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo) +{ + struct CMD_SET_BSS_RLM_PARAM *prCmdBody; + uint32_t rStatus; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + + prCmdBody = (struct CMD_SET_BSS_RLM_PARAM *)cnmMemAlloc( + prAdapter, RAM_TYPE_BUF, sizeof(struct CMD_SET_BSS_RLM_PARAM)); + + /* ASSERT(prCmdBody); */ + /* To do: exception handle */ + if (!prCmdBody) { + DBGLOG(RLM, WARN, "No buf for sync RLM params (Net=%d)\n", + prBssInfo->ucBssIndex); + 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(struct CMD_SET_BSS_RLM_PARAM), /* u4SetQueryInfoLen */ + (uint8_t *)prCmdBody, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + /* ASSERT(rStatus == WLAN_STATUS_PENDING); */ + if (rStatus != WLAN_STATUS_PENDING) + DBGLOG(RLM, WARN, "rlmSyncOperationParams set cmd fail\n"); + + cnmMemFree(prAdapter, prCmdBody); +} + +#if CFG_SUPPORT_AAA +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function should be invoked after judging successful association. + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmProcessAssocReq(struct ADAPTER *prAdapter, struct SW_RFB *prSwRfb, + uint8_t *pucIE, uint16_t u2IELength) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec; + uint16_t u2Offset; + struct IE_HT_CAP *prHtCap; +#if CFG_SUPPORT_802_11AC + struct IE_VHT_CAP *prVhtCap; + struct IE_OP_MODE_NOTIFICATION + *prOPModeNotification; /* Operation Mode Notification */ + u_int8_t fgHasOPModeIE = FALSE; +#endif + + ASSERT(prAdapter); + ASSERT(prSwRfb); + ASSERT(pucIE); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (!prStaRec) + return; + ASSERT(prStaRec->ucBssIndex <= prAdapter->ucHwBssIdNum); + + prBssInfo = prAdapter->aprBssInfo[prStaRec->ucBssIndex]; + + 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(struct IE_HT_CAP) - 2)) + break; + prHtCap = (struct IE_HT_CAP *)pucIE; + prStaRec->ucMcsSet = + prHtCap->rSupMcsSet.aucRxMcsBitmask[0]; + prStaRec->fgSupMcs32 = + (prHtCap->rSupMcsSet.aucRxMcsBitmask[32 / 8] & + BIT(0)) + ? TRUE + : FALSE; + + kalMemCopy( + prStaRec->aucRxMcsBitmask, + prHtCap->rSupMcsSet.aucRxMcsBitmask, + /*SUP_MCS_RX_BITMASK_OCTET_NUM */ + sizeof(prStaRec->aucRxMcsBitmask)); + + prStaRec->u2HtCapInfo = prHtCap->u2HtCapInfo; + + /* Set Short LDPC Tx capability */ + if (IS_FEATURE_FORCE_ENABLED( + prAdapter->rWifiVar.ucTxLdpc)) + prStaRec->u2HtCapInfo |= HT_CAP_INFO_LDPC_CAP; + else if (IS_FEATURE_DISABLED( + prAdapter->rWifiVar.ucTxLdpc)) + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_LDPC_CAP; + + /* Set STBC Tx capability */ + if (IS_FEATURE_FORCE_ENABLED( + prAdapter->rWifiVar.ucTxStbc)) + prStaRec->u2HtCapInfo |= HT_CAP_INFO_TX_STBC; + else if (IS_FEATURE_DISABLED( + prAdapter->rWifiVar.ucTxStbc)) + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_TX_STBC; + /* Set Short GI Tx capability */ + if (IS_FEATURE_FORCE_ENABLED( + prAdapter->rWifiVar.ucTxShortGI)) { + prStaRec->u2HtCapInfo |= + HT_CAP_INFO_SHORT_GI_20M; + prStaRec->u2HtCapInfo |= + HT_CAP_INFO_SHORT_GI_40M; + } else if (IS_FEATURE_DISABLED( + prAdapter->rWifiVar.ucTxShortGI)) { + prStaRec->u2HtCapInfo &= + ~HT_CAP_INFO_SHORT_GI_20M; + prStaRec->u2HtCapInfo &= + ~HT_CAP_INFO_SHORT_GI_40M; + } + + /* Set HT Greenfield Tx capability */ + if (IS_FEATURE_FORCE_ENABLED( + prAdapter->rWifiVar.ucTxGf)) + prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + else if (IS_FEATURE_DISABLED( + prAdapter->rWifiVar.ucTxGf)) + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_HT_GF; + + prStaRec->ucAmpduParam = prHtCap->ucAmpduParam; + prStaRec->u2HtExtendedCap = prHtCap->u2HtExtendedCap; + prStaRec->u4TxBeamformingCap = + prHtCap->u4TxBeamformingCap; + prStaRec->ucAselCap = prHtCap->ucAselCap; + break; + +#if CFG_SUPPORT_802_11AC + case ELEM_ID_VHT_CAP: + if (!RLM_NET_IS_11AC(prBssInfo) || + IE_LEN(pucIE) != (sizeof(struct IE_VHT_CAP) - 2)) + break; + + prVhtCap = (struct IE_VHT_CAP *)pucIE; + + prStaRec->u4VhtCapInfo = prVhtCap->u4VhtCapInfo; + + /* Set Tx LDPC capability */ + if (IS_FEATURE_FORCE_ENABLED( + prAdapter->rWifiVar.ucTxLdpc)) + prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_RX_LDPC; + else if (IS_FEATURE_DISABLED( + prAdapter->rWifiVar.ucTxLdpc)) + prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_RX_LDPC; + + /* Set Tx STBC capability */ + if (IS_FEATURE_FORCE_ENABLED( + prAdapter->rWifiVar.ucTxStbc)) + prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_TX_STBC; + else if (IS_FEATURE_DISABLED( + prAdapter->rWifiVar.ucTxStbc)) + prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_TX_STBC; + + /* Set Tx TXOP PS capability */ + if (IS_FEATURE_FORCE_ENABLED( + prAdapter->rWifiVar.ucTxopPsTx)) + prStaRec->u4VhtCapInfo |= + VHT_CAP_INFO_VHT_TXOP_PS; + else if (IS_FEATURE_DISABLED( + prAdapter->rWifiVar.ucTxopPsTx)) + prStaRec->u4VhtCapInfo &= + ~VHT_CAP_INFO_VHT_TXOP_PS; + + /* Set Tx Short GI capability */ + if (IS_FEATURE_FORCE_ENABLED( + prAdapter->rWifiVar.ucTxShortGI)) { + prStaRec->u4VhtCapInfo |= + VHT_CAP_INFO_SHORT_GI_80; + prStaRec->u4VhtCapInfo |= + VHT_CAP_INFO_SHORT_GI_160_80P80; + } else if (IS_FEATURE_DISABLED( + prAdapter->rWifiVar.ucTxShortGI)) { + prStaRec->u4VhtCapInfo &= + ~VHT_CAP_INFO_SHORT_GI_80; + prStaRec->u4VhtCapInfo &= + ~VHT_CAP_INFO_SHORT_GI_160_80P80; + } + + prStaRec->u2VhtRxMcsMap = + prVhtCap->rVhtSupportedMcsSet.u2RxMcsMap; + + prStaRec->u2VhtRxHighestSupportedDataRate = + prVhtCap->rVhtSupportedMcsSet + .u2RxHighestSupportedDataRate; + prStaRec->u2VhtTxMcsMap = + prVhtCap->rVhtSupportedMcsSet.u2TxMcsMap; + prStaRec->u2VhtTxHighestSupportedDataRate = + prVhtCap->rVhtSupportedMcsSet + .u2TxHighestSupportedDataRate; + + /* Set initial value of VHT OP mode */ + prStaRec->ucVhtOpMode = 0; + prStaRec->ucVhtOpMode |= + rlmGetOpModeBwByVhtAndHtOpInfo(prBssInfo); + prStaRec->ucVhtOpMode |= + ((prBssInfo->ucNss - 1) + << VHT_OP_MODE_RX_NSS_OFFSET) & + VHT_OP_MODE_RX_NSS; + + break; + case ELEM_ID_OP_MODE: + if (!RLM_NET_IS_11AC(prBssInfo) || + IE_LEN(pucIE) != + (sizeof(struct IE_OP_MODE_NOTIFICATION) - + 2)) + break; + prOPModeNotification = + (struct IE_OP_MODE_NOTIFICATION *)pucIE; + + if ((prOPModeNotification->ucOpMode & + VHT_OP_MODE_RX_NSS_TYPE) != + VHT_OP_MODE_RX_NSS_TYPE) { + fgHasOPModeIE = TRUE; + } + + break; + +#endif + + default: + break; + } /* end of switch */ + } /* end of IE_FOR_EACH */ +#if CFG_SUPPORT_802_11AC + /*Fill by OP Mode IE after completing parsing all IE to make sure it + * won't be overwrite + */ + if (fgHasOPModeIE == TRUE) + prStaRec->ucVhtOpMode = prOPModeNotification->ucOpMode; +#endif +} +#endif /* CFG_SUPPORT_AAA */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief It is for both STA and AP modes + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmBssInitForAPandIbss(struct ADAPTER *prAdapter, + struct BSS_INFO *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(struct ADAPTER *prAdapter, struct BSS_INFO *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(struct ADAPTER *prAdapter, struct BSS_INFO *prBssInfo) +{ + ASSERT(prAdapter); + ASSERT(prBssInfo); + + /* HT related parameters */ + prBssInfo->ucHtOpInfo1 = 0; /* RIFS disabled. 20MHz */ + prBssInfo->u2HtOpInfo2 = 0; + prBssInfo->u2HtOpInfo3 = 0; + +#if CFG_SUPPORT_802_11AC + prBssInfo->ucVhtChannelWidth = 0; /* VHT_OP_CHANNEL_WIDTH_80; */ + prBssInfo->ucVhtChannelFrequencyS1 = 0; /* 42; */ + prBssInfo->ucVhtChannelFrequencyS2 = 0; + prBssInfo->u2VhtBasicMcsSet = 0; /* 0xFFFF; */ +#endif + + 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 */ + + /* OP mode change control parameters */ + prBssInfo->fgIsOpChangeChannelWidth = FALSE; + prBssInfo->fgIsOpChangeNss = FALSE; + +#ifdef CFG_DFS_CHSW_FORCE_BW20 + g_fgHasChannelSwitchIE = FALSE; +#endif +} + +#if CFG_SUPPORT_TDLS +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +uint32_t rlmFillVhtCapIEByAdapter(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, uint8_t *pOutBuf) +{ + struct IE_VHT_CAP *prVhtCap; + struct VHT_SUPPORTED_MCS_FIELD *prVhtSupportedMcsSet; + uint8_t i; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + /* ASSERT(prMsduInfo); */ + + prVhtCap = (struct IE_VHT_CAP *)pOutBuf; + + prVhtCap->ucId = ELEM_ID_VHT_CAP; + prVhtCap->ucLength = sizeof(struct IE_VHT_CAP) - ELEM_HDR_LEN; + prVhtCap->u4VhtCapInfo = VHT_CAP_INFO_DEFAULT_VAL; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxShortGI)) + prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_SHORT_GI_80; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxLdpc)) + prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_RX_LDPC; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxStbc)) + prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_RX_STBC_ONE_STREAM; + + /*set MCS map */ + prVhtSupportedMcsSet = &prVhtCap->rVhtSupportedMcsSet; + kalMemZero((void *)prVhtSupportedMcsSet, + sizeof(struct VHT_SUPPORTED_MCS_FIELD)); + + for (i = 0; i < 8; i++) { + prVhtSupportedMcsSet->u2RxMcsMap |= BITS(2 * i, (2 * i + 1)); + prVhtSupportedMcsSet->u2TxMcsMap |= BITS(2 * i, (2 * i + 1)); + } + + prVhtSupportedMcsSet->u2RxMcsMap &= + (VHT_CAP_INFO_MCS_MAP_MCS9 << VHT_CAP_INFO_MCS_1SS_OFFSET); + prVhtSupportedMcsSet->u2TxMcsMap &= + (VHT_CAP_INFO_MCS_MAP_MCS9 << VHT_CAP_INFO_MCS_1SS_OFFSET); + prVhtSupportedMcsSet->u2RxHighestSupportedDataRate = + VHT_CAP_INFO_DEFAULT_HIGHEST_DATA_RATE; + prVhtSupportedMcsSet->u2TxHighestSupportedDataRate = + VHT_CAP_INFO_DEFAULT_HIGHEST_DATA_RATE; + + ASSERT(IE_SIZE(prVhtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP)); + + return IE_SIZE(prVhtCap); +} +#endif + +#if CFG_SUPPORT_TDLS +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +uint32_t rlmFillHtCapIEByParams(u_int8_t fg40mAllowed, + u_int8_t fgShortGIDisabled, + uint8_t u8SupportRxSgi20, + uint8_t u8SupportRxSgi40, uint8_t u8SupportRxGf, + enum ENUM_OP_MODE eCurrentOPMode, + uint8_t *pOutBuf) +{ + struct IE_HT_CAP *prHtCap; + struct SUP_MCS_SET_FIELD *prSupMcsSet; + + ASSERT(pOutBuf); + + prHtCap = (struct IE_HT_CAP *)pOutBuf; + + /* Add HT capabilities IE */ + prHtCap->ucId = ELEM_ID_HT_CAP; + prHtCap->ucLength = sizeof(struct IE_HT_CAP) - ELEM_HDR_LEN; + + prHtCap->u2HtCapInfo = HT_CAP_INFO_DEFAULT_VAL; + if (!fg40mAllowed) { + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | + HT_CAP_INFO_SHORT_GI_40M | + HT_CAP_INFO_DSSS_CCK_IN_40M); + } + if (fgShortGIDisabled) + prHtCap->u2HtCapInfo &= + ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); + + if (u8SupportRxSgi20 == 2) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_20M); + if (u8SupportRxSgi40 == 2) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_40M); + if (u8SupportRxGf == 2) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_HT_GF); + + prHtCap->ucAmpduParam = AMPDU_PARAM_DEFAULT_VAL; + + prSupMcsSet = &prHtCap->rSupMcsSet; + kalMemZero((void *)&prSupMcsSet->aucRxMcsBitmask[0], + SUP_MCS_RX_BITMASK_OCTET_NUM); + + prSupMcsSet->aucRxMcsBitmask[0] = BITS(0, 7); + + if (fg40mAllowed) + prSupMcsSet->aucRxMcsBitmask[32 / 8] = BIT(0); /* MCS32 */ + prSupMcsSet->u2RxHighestSupportedRate = SUP_MCS_RX_DEFAULT_HIGHEST_RATE; + prSupMcsSet->u4TxRateInfo = SUP_MCS_TX_DEFAULT_VAL; + + prHtCap->u2HtExtendedCap = HT_EXT_CAP_DEFAULT_VAL; + if (!fg40mAllowed || eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + prHtCap->u2HtExtendedCap &= + ~(HT_EXT_CAP_PCO | HT_EXT_CAP_PCO_TRANS_TIME_NONE); + + prHtCap->u4TxBeamformingCap = TX_BEAMFORMING_CAP_DEFAULT_VAL; + + prHtCap->ucAselCap = ASEL_CAP_DEFAULT_VAL; + + ASSERT(IE_SIZE(prHtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP)); + + return IE_SIZE(prHtCap); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +uint32_t rlmFillHtCapIEByAdapter(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, uint8_t *pOutBuf) +{ + struct IE_HT_CAP *prHtCap; + struct SUP_MCS_SET_FIELD *prSupMcsSet; + u_int8_t fg40mAllowed; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(pOutBuf); + + fg40mAllowed = prBssInfo->fgAssoc40mBwAllowed; + + prHtCap = (struct IE_HT_CAP *)pOutBuf; + + /* Add HT capabilities IE */ + prHtCap->ucId = ELEM_ID_HT_CAP; + prHtCap->ucLength = sizeof(struct IE_HT_CAP) - 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 (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxShortGI)) + prHtCap->u2HtCapInfo |= + (HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxLdpc)) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_LDPC_CAP; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxStbc)) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_RX_STBC_1_SS; + + prHtCap->ucAmpduParam = AMPDU_PARAM_DEFAULT_VAL; + + prSupMcsSet = &prHtCap->rSupMcsSet; + kalMemZero((void *)&prSupMcsSet->aucRxMcsBitmask[0], + SUP_MCS_RX_BITMASK_OCTET_NUM); + + prSupMcsSet->aucRxMcsBitmask[0] = BITS(0, 7); + + if (fg40mAllowed && IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucMCS32)) + 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)); + + return IE_SIZE(prHtCap); +} + +#endif + +#if CFG_SUPPORT_DFS +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will compose the TPC Report frame. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] prStaRec Pointer to the STA_RECORD_T. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +static void tpcComposeReportFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + struct MSDU_INFO *prMsduInfo; + struct BSS_INFO *prBssInfo; + struct ACTION_TPC_REPORT_FRAME *prTxFrame; + uint16_t u2PayloadLen; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + prBssInfo = &prAdapter->rWifiVar.arBssInfoPool[prStaRec->ucBssIndex]; + ASSERT(prBssInfo); + + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc( + prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + prTxFrame = (struct ACTION_TPC_REPORT_FRAME + *)((unsigned long)(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_SPEC_MGT; + prTxFrame->ucAction = ACTION_TPC_REPORT; + + /* 3 Compose the frame body's frame. */ + prTxFrame->ucDialogToken = prStaRec->ucSmDialogToken; + prTxFrame->ucElemId = ELEM_ID_TPC_REPORT; + prTxFrame->ucLength = + sizeof(prTxFrame->ucLinkMargin) + sizeof(prTxFrame->ucTransPwr); + prTxFrame->ucTransPwr = prAdapter->u4GetTxPower; + prTxFrame->ucLinkMargin = + prAdapter->rLinkQuality.cRssi - (0 - MIN_RCV_PWR); + + u2PayloadLen = ACTION_SM_TPC_REPORT_LEN; + + /* 4 Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, prMsduInfo, prStaRec->ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, pfTxDoneHandler, + MSDU_RATE_MODE_AUTO); + + DBGLOG(RLM, TRACE, "ucDialogToken %d ucTransPwr %d ucLinkMargin %d\n", + prTxFrame->ucDialogToken, prTxFrame->ucTransPwr, + prTxFrame->ucLinkMargin); + + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return; + +} /* end of tpcComposeReportFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will compose the Measurement Report frame. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] prStaRec Pointer to the STA_RECORD_T. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +static void msmtComposeReportFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + struct MSDU_INFO *prMsduInfo; + struct BSS_INFO *prBssInfo; + struct ACTION_SM_REQ_FRAME *prTxFrame; + struct IE_MEASUREMENT_REPORT *prMeasurementRepIE; + uint8_t *pucIE; + uint16_t u2PayloadLen; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + prBssInfo = &prAdapter->rWifiVar.arBssInfoPool[prStaRec->ucBssIndex]; + ASSERT(prBssInfo); + + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc( + prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + prTxFrame = (struct ACTION_SM_REQ_FRAME + *)((unsigned long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + pucIE = prTxFrame->aucInfoElem; + prMeasurementRepIE = SM_MEASUREMENT_REP_IE(pucIE); + + 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_SPEC_MGT; + prTxFrame->ucAction = ACTION_MEASUREMENT_REPORT; + + /* 3 Compose the frame body's frame. */ + prTxFrame->ucDialogToken = prStaRec->ucSmDialogToken; + prMeasurementRepIE->ucId = ELEM_ID_MEASUREMENT_REPORT; + +#if 0 + if (prStaRec->ucSmMsmtRequestMode == ELEM_RM_TYPE_BASIC_REQ) { + prMeasurementRepIE->ucLength = + sizeof(struct SM_BASIC_REPORT) + 3; + u2PayloadLen = ACTION_SM_MEASURE_REPORT_LEN+ + ACTION_SM_BASIC_REPORT_LEN; + } else if (prStaRec->ucSmMsmtRequestMode == ELEM_RM_TYPE_CCA_REQ) { + prMeasurementRepIE->ucLength = sizeof(struct SM_CCA_REPORT) + 3; + u2PayloadLen = ACTION_SM_MEASURE_REPORT_LEN+ + ACTION_SM_CCA_REPORT_LEN; + } else if (prStaRec->ucSmMsmtRequestMode == + ELEM_RM_TYPE_RPI_HISTOGRAM_REQ) { + prMeasurementRepIE->ucLength = sizeof(struct SM_RPI_REPORT) + 3; + u2PayloadLen = ACTION_SM_MEASURE_REPORT_LEN+ + ACTION_SM_PRI_REPORT_LEN; + } else { + prMeasurementRepIE->ucLength = 3; + u2PayloadLen = ACTION_SM_MEASURE_REPORT_LEN; + } +#else + prMeasurementRepIE->ucLength = 3; + u2PayloadLen = ACTION_SM_MEASURE_REPORT_LEN; + prMeasurementRepIE->ucToken = prStaRec->ucSmMsmtToken; + prMeasurementRepIE->ucReportMode = BIT(1); + prMeasurementRepIE->ucMeasurementType = prStaRec->ucSmMsmtRequestMode; +#endif + + /* 4 Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, prMsduInfo, prStaRec->ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, pfTxDoneHandler, + MSDU_RATE_MODE_AUTO); + + DBGLOG(RLM, TRACE, + "ucDialogToken %d ucToken %d ucReportMode %d ucMeasurementType %d\n", + prTxFrame->ucDialogToken, prMeasurementRepIE->ucToken, + prMeasurementRepIE->ucReportMode, + prMeasurementRepIE->ucMeasurementType); + + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return; + +} /* end of msmtComposeReportFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function handle spectrum management action frame + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmProcessSpecMgtAction(struct ADAPTER *prAdapter, struct SW_RFB *prSwRfb) +{ + uint8_t *pucIE; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + uint16_t u2IELength; + uint16_t u2Offset = 0; + struct IE_CHANNEL_SWITCH *prChannelSwitchAnnounceIE; + struct IE_SECONDARY_OFFSET *prSecondaryOffsetIE; + struct IE_WIDE_BAND_CHANNEL *prWideBandChannelIE; + struct IE_TPC_REQ *prTpcReqIE; + struct IE_TPC_REPORT *prTpcRepIE; + struct IE_MEASUREMENT_REQ *prMeasurementReqIE; + struct IE_MEASUREMENT_REPORT *prMeasurementRepIE; + struct ACTION_SM_REQ_FRAME *prRxFrame; + u_int8_t fgHasWideBandIE = FALSE; + u_int8_t fgHasSCOIE = FALSE; + u_int8_t fgHasChannelSwitchIE = FALSE; + bool fgNeedSwitchChannel = FALSE; + + DBGLOG(RLM, INFO, "[Mgt Action]rlmProcessSpecMgtAction\n"); + ASSERT(prAdapter); + ASSERT(prSwRfb); + + u2IELength = + prSwRfb->u2PacketLen - + (uint16_t)OFFSET_OF(struct ACTION_SM_REQ_FRAME, aucInfoElem[0]); + + prRxFrame = (struct ACTION_SM_REQ_FRAME *)prSwRfb->pvHeader; + pucIE = prRxFrame->aucInfoElem; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (!prStaRec) + return; + + if (prStaRec->ucBssIndex > prAdapter->ucHwBssIdNum) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + prStaRec->ucSmDialogToken = prRxFrame->ucDialogToken; + + DBGLOG_MEM8(RLM, INFO, pucIE, u2IELength); + switch (prRxFrame->ucAction) { + case ACTION_MEASUREMENT_REQ: + DBGLOG(RLM, INFO, "[Mgt Action] Measure Request\n"); + prMeasurementReqIE = SM_MEASUREMENT_REQ_IE(pucIE); + if (prMeasurementReqIE->ucId == ELEM_ID_MEASUREMENT_REQ) { + prStaRec->ucSmMsmtRequestMode = + prMeasurementReqIE->ucRequestMode; + prStaRec->ucSmMsmtToken = prMeasurementReqIE->ucToken; + msmtComposeReportFrame(prAdapter, prStaRec, NULL); + } + + break; + case ACTION_MEASUREMENT_REPORT: + DBGLOG(RLM, INFO, "[Mgt Action] Measure Report\n"); + prMeasurementRepIE = SM_MEASUREMENT_REP_IE(pucIE); + if (prMeasurementRepIE->ucId == ELEM_ID_MEASUREMENT_REPORT) + DBGLOG(RLM, TRACE, + "[Mgt Action] Correct Measurement report IE !!\n"); + break; + case ACTION_TPC_REQ: + DBGLOG(RLM, INFO, "[Mgt Action] TPC Request\n"); + prTpcReqIE = SM_TPC_REQ_IE(pucIE); + + if (prTpcReqIE->ucId == ELEM_ID_TPC_REQ) + tpcComposeReportFrame(prAdapter, prStaRec, NULL); + + break; + case ACTION_TPC_REPORT: + DBGLOG(RLM, INFO, "[Mgt Action] TPC Report\n"); + prTpcRepIE = SM_TPC_REP_IE(pucIE); + + if (prTpcRepIE->ucId == ELEM_ID_TPC_REPORT) + DBGLOG(RLM, TRACE, + "[Mgt Action] Correct TPC report IE !!\n"); + + break; + case ACTION_CHNL_SWITCH: + IE_FOR_EACH(pucIE, u2IELength, u2Offset) + { + switch (IE_ID(pucIE)) { + + case ELEM_ID_WIDE_BAND_CHANNEL_SWITCH: + if (!RLM_NET_IS_11AC(prBssInfo) || + IE_LEN(pucIE) != + (sizeof(struct + IE_WIDE_BAND_CHANNEL) - + 2)) { + DBGLOG(RLM, INFO, + "[Mgt Action] ELEM_ID_WIDE_BAND_CHANNEL_SWITCH, Length\n"); + break; + } + DBGLOG(RLM, INFO, + "[Mgt Action] ELEM_ID_WIDE_BAND_CHANNEL_SWITCH, 11AC\n"); + prWideBandChannelIE = + (struct IE_WIDE_BAND_CHANNEL *)pucIE; + prBssInfo->ucVhtChannelWidth = + prWideBandChannelIE->ucNewChannelWidth; + prBssInfo->ucVhtChannelFrequencyS1 = + prWideBandChannelIE->ucChannelS1; + prBssInfo->ucVhtChannelFrequencyS2 = + prWideBandChannelIE->ucChannelS2; + + /* Revise by own OP BW if needed */ + if ((prBssInfo->fgIsOpChangeChannelWidth) && + (rlmGetVhtOpBwByBssOpBw( + prBssInfo + ->ucOpChangeChannelWidth) < + prBssInfo->ucVhtChannelWidth)) { + + DBGLOG(RLM, LOUD, + "Change to w:%d s1:%d s2:%d since own changed BW < peer's WideBand BW", + prBssInfo->ucVhtChannelWidth, + prBssInfo->ucVhtChannelFrequencyS1, + prBssInfo->ucVhtChannelFrequencyS2); + rlmFillVhtOpInfoByBssOpBw( + prBssInfo, + prBssInfo + ->ucOpChangeChannelWidth); + } + + fgHasWideBandIE = TRUE; + break; + + case ELEM_ID_CH_SW_ANNOUNCEMENT: + if (IE_LEN(pucIE) != + (sizeof(struct IE_CHANNEL_SWITCH) - 2)) { + DBGLOG(RLM, INFO, + "[Mgt Action] ELEM_ID_CH_SW_ANNOUNCEMENT, Length\n"); + break; + } + + prChannelSwitchAnnounceIE = + (struct IE_CHANNEL_SWITCH *)pucIE; + + if (prChannelSwitchAnnounceIE + ->ucChannelSwitchMode == 1) { + /* Need to stop data + * transmission immediately + */ + if (!g_fgHasStopTx) { + g_fgHasStopTx = TRUE; +#if CFG_SUPPORT_TDLS + /* TDLS peers */ + TdlsTxCtrl(prAdapter, + prBssInfo, + FALSE); +#endif + /* AP */ + qmSetStaRecTxAllowed(prAdapter, + prStaRec, + FALSE); + DBGLOG(RLM, EVENT, + "[Ch] TxAllowed = FALSE\n"); + } + + if (prChannelSwitchAnnounceIE + ->ucChannelSwitchCount <= 3) { + DBGLOG(RLM, INFO, + "[Mgt Action] switch channel [%d]->[%d]\n", + prBssInfo->ucPrimaryChannel, + prChannelSwitchAnnounceIE + ->ucNewChannelNum); + prBssInfo->ucPrimaryChannel = + prChannelSwitchAnnounceIE + ->ucNewChannelNum; + fgNeedSwitchChannel = TRUE; + } + } else { + DBGLOG(RLM, INFO, + "[Mgt Action] ucChannelSwitchMode = 0\n"); + } + + fgHasChannelSwitchIE = TRUE; + break; + case ELEM_ID_SCO: + if (IE_LEN(pucIE) != + (sizeof(struct IE_SECONDARY_OFFSET) - 2)) { + DBGLOG(RLM, INFO, + "[Mgt Action] ELEM_ID_SCO, Length\n"); + break; + } + prSecondaryOffsetIE = + (struct IE_SECONDARY_OFFSET *)pucIE; + DBGLOG(RLM, INFO, + "[Mgt Action] SCO [%d]->[%d]\n", + prBssInfo->eBssSCO, + prSecondaryOffsetIE->ucSecondaryOffset); + prBssInfo->eBssSCO = + prSecondaryOffsetIE->ucSecondaryOffset; + fgHasSCOIE = TRUE; + break; + default: + break; + } /*end of switch IE_ID */ + } /*end of IE_FOR_EACH */ + if (fgHasChannelSwitchIE != FALSE) { + if (fgHasWideBandIE == FALSE) { + prBssInfo->ucVhtChannelWidth = 0; + prBssInfo->ucVhtChannelFrequencyS1 = + prBssInfo->ucPrimaryChannel; + prBssInfo->ucVhtChannelFrequencyS2 = 0; + } + if (fgHasSCOIE == FALSE) + prBssInfo->eBssSCO = CHNL_EXT_SCN; + if (fgNeedSwitchChannel) + kalIndicateChannelSwitch( + prAdapter->prGlueInfo, + prBssInfo->eBssSCO, + prBssInfo->ucPrimaryChannel); + } + nicUpdateBss(prAdapter, prBssInfo->ucBssIndex); + break; + default: + break; + } +} + +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Send OpMode Norification frame (VHT action frame) + * + * \param[in] ucChannelWidth 0:20MHz, 1:40MHz, 2:80MHz, 3:160MHz or 80+80MHz + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmSendOpModeNotificationFrame(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t ucChannelWidth, uint8_t ucNss) +{ + + struct MSDU_INFO *prMsduInfo; + struct ACTION_OP_MODE_NOTIFICATION_FRAME *prTxFrame; + struct BSS_INFO *prBssInfo; + uint16_t u2EstimatedFrameLen; + PFN_TX_DONE_HANDLER pfTxDoneHandler = (PFN_TX_DONE_HANDLER)NULL; + + /* Sanity Check */ + if (!prStaRec) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + if (!prBssInfo) + return; + + /* Calculate MSDU buffer length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + + sizeof(struct ACTION_OP_MODE_NOTIFICATION_FRAME); + + /* Alloc MSDU_INFO */ + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc(prAdapter, + u2EstimatedFrameLen); + + if (!prMsduInfo) + return; + + kalMemZero(prMsduInfo->prPacket, u2EstimatedFrameLen); + + prTxFrame = prMsduInfo->prPacket; + + /* Fill frame ctrl */ + 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); + + /* 3 Compose the frame body's frame */ + prTxFrame->ucCategory = CATEGORY_VHT_ACTION; + prTxFrame->ucAction = ACTION_OPERATING_MODE_NOTIFICATION; + + prTxFrame->ucOperatingMode |= + (ucChannelWidth & VHT_OP_MODE_CHANNEL_WIDTH); + + if (ucNss == 0) + ucNss = 1; + prTxFrame->ucOperatingMode |= (((ucNss - 1) << 4) & VHT_OP_MODE_RX_NSS); + prTxFrame->ucOperatingMode &= ~VHT_OP_MODE_RX_NSS_TYPE; + + if (prBssInfo->pfOpChangeHandler) + pfTxDoneHandler = rlmNotifyVhtOpModeTxDone; + + /* 4 Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, prMsduInfo, prBssInfo->ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_MGMT_HEADER_LEN, + sizeof(struct ACTION_OP_MODE_NOTIFICATION_FRAME), + pfTxDoneHandler, MSDU_RATE_MODE_AUTO); + + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Send SM Power Save frame (HT action frame) + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmSendSmPowerSaveFrame(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, uint8_t ucNss) +{ + struct MSDU_INFO *prMsduInfo; + struct ACTION_SM_POWER_SAVE_FRAME *prTxFrame; + struct BSS_INFO *prBssInfo; + uint16_t u2EstimatedFrameLen; + PFN_TX_DONE_HANDLER pfTxDoneHandler = (PFN_TX_DONE_HANDLER)NULL; + + /* Sanity Check */ + if (!prStaRec) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + if (!prBssInfo) + return; + + /* Calculate MSDU buffer length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + + sizeof(struct ACTION_SM_POWER_SAVE_FRAME); + + /* Alloc MSDU_INFO */ + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc(prAdapter, + u2EstimatedFrameLen); + + if (!prMsduInfo) + return; + + kalMemZero(prMsduInfo->prPacket, u2EstimatedFrameLen); + + prTxFrame = prMsduInfo->prPacket; + + /* Fill frame ctrl */ + 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); + + /* 3 Compose the frame body's frame */ + prTxFrame->ucCategory = CATEGORY_HT_ACTION; + prTxFrame->ucAction = ACTION_HT_SM_POWER_SAVE; + + if (ucNss == 1) + prTxFrame->ucSmPowerCtrl |= HT_SM_POWER_SAVE_CONTROL_ENABLED; + else if (ucNss == 2) + prTxFrame->ucSmPowerCtrl &= ~HT_SM_POWER_SAVE_CONTROL_ENABLED; + else { + DBGLOG(RLM, WARN, + "Can't switch to Nss = %d since we don't support.\n", + ucNss); + return; + } + + /* Static SM power save mode */ + prTxFrame->ucSmPowerCtrl &= + (~HT_SM_POWER_SAVE_CONTROL_SM_MODE); + + if (prBssInfo->pfOpChangeHandler) + pfTxDoneHandler = rlmSmPowerSaveTxDone; + + /* 4 Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, prMsduInfo, prBssInfo->ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_MGMT_HEADER_LEN, + sizeof(struct ACTION_SM_POWER_SAVE_FRAME), pfTxDoneHandler, + MSDU_RATE_MODE_AUTO); + + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Send Notify Channel Width frame (HT action frame) + * + * \param[in] ucChannelWidth 0:20MHz, 1:Any channel width + * in the STAs Supported Channel Width Set subfield + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmSendNotifyChannelWidthFrame(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t ucChannelWidth) +{ + struct MSDU_INFO *prMsduInfo; + struct ACTION_NOTIFY_CHANNEL_WIDTH_FRAME *prTxFrame; + struct BSS_INFO *prBssInfo; + uint16_t u2EstimatedFrameLen; + PFN_TX_DONE_HANDLER pfTxDoneHandler = (PFN_TX_DONE_HANDLER)NULL; + + /* Sanity Check */ + if (!prStaRec) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + if (!prBssInfo) + return; + + /* Calculate MSDU buffer length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + + sizeof(struct ACTION_NOTIFY_CHANNEL_WIDTH_FRAME); + + /* Alloc MSDU_INFO */ + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc(prAdapter, + u2EstimatedFrameLen); + + if (!prMsduInfo) + return; + + kalMemZero(prMsduInfo->prPacket, u2EstimatedFrameLen); + + prTxFrame = prMsduInfo->prPacket; + + /* Fill frame ctrl */ + 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); + + /* 3 Compose the frame body's frame */ + prTxFrame->ucCategory = CATEGORY_HT_ACTION; + prTxFrame->ucAction = ACTION_HT_NOTIFY_CHANNEL_WIDTH; + + prTxFrame->ucChannelWidth = ucChannelWidth; + + if (prBssInfo->pfOpChangeHandler) + pfTxDoneHandler = rlmNotifyChannelWidthtTxDone; + + /* 4 Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, prMsduInfo, prBssInfo->ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_MGMT_HEADER_LEN, + sizeof(struct ACTION_NOTIFY_CHANNEL_WIDTH_FRAME), + pfTxDoneHandler, MSDU_RATE_MODE_AUTO); + + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + * + */ +/*----------------------------------------------------------------------------*/ +uint32_t rlmNotifyVhtOpModeTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + u_int8_t fgIsSuccess = FALSE; + + do { + ASSERT((prAdapter != NULL) && (prMsduInfo != NULL)); + + if (rTxDoneStatus == TX_RESULT_SUCCESS) + fgIsSuccess = TRUE; + + } while (FALSE); + + rlmOpModeTxDoneHandler(prAdapter, prMsduInfo, OP_NOTIFY_TYPE_VHT_NSS_BW, + fgIsSuccess); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +uint32_t rlmSmPowerSaveTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + u_int8_t fgIsSuccess = FALSE; + + do { + ASSERT((prAdapter != NULL) && (prMsduInfo != NULL)); + + if (rTxDoneStatus == TX_RESULT_SUCCESS) + fgIsSuccess = TRUE; + + } while (FALSE); + + rlmOpModeTxDoneHandler(prAdapter, prMsduInfo, OP_NOTIFY_TYPE_HT_NSS, + fgIsSuccess); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +uint32_t rlmNotifyChannelWidthtTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + u_int8_t fgIsSuccess = FALSE; + + do { + ASSERT((prAdapter != NULL) && (prMsduInfo != NULL)); + + if (rTxDoneStatus == TX_RESULT_SUCCESS) + fgIsSuccess = TRUE; + + } while (FALSE); + + rlmOpModeTxDoneHandler(prAdapter, prMsduInfo, OP_NOTIFY_TYPE_HT_BW, + fgIsSuccess); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Handle TX done for OP mode noritfication frame + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static void rlmOpModeTxDoneHandler(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN uint8_t ucOpChangeType, + IN u_int8_t fgIsSuccess) +{ + struct BSS_INFO *prBssInfo = NULL; + struct STA_RECORD *prStaRec = NULL; + u_int8_t fgIsOpModeChangeSuccess = FALSE; /* OP change result */ + uint8_t ucRelatedFrameType = + OP_NOTIFY_TYPE_NUM; /* Used for HT notification frame */ + enum ENUM_OP_NOTIFY_STATE_T + *pucCurrOpState = NULL, + *pucRelatedOpState = NULL; /* Used for HT notification frame */ + + /* Sanity check */ + ASSERT((prAdapter != NULL) && (prMsduInfo != NULL)); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + + ASSERT(prBssInfo); + + prStaRec = prBssInfo->prStaRecOfAP; + + ASSERT(prStaRec); + + DBGLOG(RLM, INFO, + "OP notification Tx done: BSS[%d] Type[%d] Status[%d] IsSuccess[%d]\n", + prBssInfo->ucBssIndex, ucOpChangeType, + prBssInfo->aucOpModeChangeState[ucOpChangeType], fgIsSuccess); + + do { + /* <1>handle abnormal case */ + if ((prBssInfo->aucOpModeChangeState[ucOpChangeType] != + OP_NOTIFY_STATE_KEEP) && + (prBssInfo->aucOpModeChangeState[ucOpChangeType] != + OP_NOTIFY_STATE_SENDING)) { + DBGLOG(RLM, WARN, + "Unexpected BSS[%d] OpModeChangeState[%d]\n", + prBssInfo->ucBssIndex, + prBssInfo->aucOpModeChangeState[ucOpChangeType]); + rlmRollbackOpChangeParam(prBssInfo, TRUE, TRUE); + fgIsOpModeChangeSuccess = FALSE; + break; + } + + if (ucOpChangeType >= OP_NOTIFY_TYPE_NUM) { + DBGLOG(RLM, WARN, + "Uxexpected Bss[%d] OpChangeType[%d]\n", + prMsduInfo->ucBssIndex, ucOpChangeType); + rlmRollbackOpChangeParam(prBssInfo, TRUE, TRUE); + fgIsOpModeChangeSuccess = FALSE; + break; + } + + /* <2>Assign Op notification Type/State for HT notification + * frame + */ + if ((ucOpChangeType == OP_NOTIFY_TYPE_HT_BW) || + (ucOpChangeType == OP_NOTIFY_TYPE_HT_NSS)) { + + ucRelatedFrameType = + (ucOpChangeType == OP_NOTIFY_TYPE_HT_BW) + ? OP_NOTIFY_TYPE_HT_NSS + : OP_NOTIFY_TYPE_HT_BW; + + pucCurrOpState = + (enum ENUM_OP_NOTIFY_STATE_T *)&prBssInfo + ->aucOpModeChangeState[ucOpChangeType]; + pucRelatedOpState = + (enum ENUM_OP_NOTIFY_STATE_T *)&prBssInfo + ->aucOpModeChangeState + [ucRelatedFrameType]; + } + + /* <3.1>handle TX done - SUCCESS */ + if (fgIsSuccess == TRUE) { + + /* Clear retry count */ + prBssInfo->aucOpModeChangeRetryCnt[ucOpChangeType] = 0; + + if (ucOpChangeType == OP_NOTIFY_TYPE_VHT_NSS_BW) { + /* VHT notification frame sent */ + fgIsOpModeChangeSuccess = TRUE; + break; + } + + /* HT notification frame sent */ + if (*pucCurrOpState == + OP_NOTIFY_STATE_SENDING) { /* Change OpMode */ + + *pucCurrOpState = OP_NOTIFY_STATE_SUCCESS; + + /* Case1: Wait for both HT BW/Nss notification + * frame TX done + */ + if (*pucRelatedOpState == + OP_NOTIFY_STATE_SENDING) + return; + + /* Case2: Both BW and Nss notification TX done + * or only change either BW or Nss + */ + if ((*pucRelatedOpState == + OP_NOTIFY_STATE_KEEP) || + (*pucRelatedOpState == + OP_NOTIFY_STATE_SUCCESS)) { + fgIsOpModeChangeSuccess = TRUE; + + /* Case3: One of the notification TX + * failed, + * re-send a notification frame to + * rollback the successful one + */ + } else if (*pucRelatedOpState == + OP_NOTIFY_STATE_FAIL) { + /*Rollback to keep the original BW/Nss + */ + *pucCurrOpState = OP_NOTIFY_STATE_KEEP; + if (ucOpChangeType == + OP_NOTIFY_TYPE_HT_BW) + rlmSendNotifyChannelWidthFrame( + prAdapter, prStaRec, + rlmGetBssOpBwByVhtAndHtOpInfo( + prBssInfo)); + else if (ucOpChangeType == + OP_NOTIFY_TYPE_HT_NSS) + rlmSendSmPowerSaveFrame( + prAdapter, prStaRec, + prBssInfo->ucNss); + + DBGLOG(RLM, INFO, + "Bss[%d] OpType[%d] Tx Failed, send OpType[%d] for roll back to BW[%d] Nss[%d]\n", + prMsduInfo->ucBssIndex, + ucRelatedFrameType, + ucOpChangeType, + rlmGetBssOpBwByVhtAndHtOpInfo( + prBssInfo), + prBssInfo->ucNss); + + return; + } + } else if (*pucCurrOpState == + OP_NOTIFY_STATE_KEEP) { /* Rollback OpMode */ + + /* Case4: Rollback success, keep original OP + * BW/Nss + */ + if (ucOpChangeType == OP_NOTIFY_TYPE_HT_BW) + rlmRollbackOpChangeParam(prBssInfo, + TRUE, FALSE); + else if (ucOpChangeType == + OP_NOTIFY_TYPE_HT_NSS) + rlmRollbackOpChangeParam(prBssInfo, + FALSE, TRUE); + + fgIsOpModeChangeSuccess = FALSE; + } + } /* End of processing TX success */ + /* <3.2>handle TX done - FAIL */ + else { + prBssInfo->aucOpModeChangeRetryCnt[ucOpChangeType]++; + + /* Re-send notification frame */ + if (prBssInfo + ->aucOpModeChangeRetryCnt[ucOpChangeType] <= + OPERATION_NOTICATION_TX_LIMIT) { + if (ucOpChangeType == OP_NOTIFY_TYPE_VHT_NSS_BW) + rlmSendOpModeNotificationFrame( + prAdapter, prStaRec, + prBssInfo->ucOpChangeChannelWidth, + prBssInfo->ucOpChangeNss); + else if (ucOpChangeType == + OP_NOTIFY_TYPE_HT_NSS) + rlmSendSmPowerSaveFrame( + prAdapter, prStaRec, + prBssInfo->ucOpChangeNss); + else if (ucOpChangeType == OP_NOTIFY_TYPE_HT_BW) + rlmSendNotifyChannelWidthFrame( + prAdapter, prStaRec, + prBssInfo->ucOpChangeChannelWidth); + return; + } + + /* Clear retry count when retry count > TX limit */ + prBssInfo->aucOpModeChangeRetryCnt[ucOpChangeType] = 0; + + /* VHT notification frame sent */ + if (ucOpChangeType == + OP_NOTIFY_TYPE_VHT_NSS_BW) { + /* Change failed, keep original OP BW/Nss */ + rlmRollbackOpChangeParam(prBssInfo, TRUE, TRUE); + fgIsOpModeChangeSuccess = FALSE; + break; + } + + /* HT notification frame sent */ + if (*pucCurrOpState == + OP_NOTIFY_STATE_SENDING) { /* Change OpMode */ + *pucCurrOpState = OP_NOTIFY_STATE_FAIL; + + /* Change failed, keep original OP BW/Nss */ + if (ucOpChangeType == OP_NOTIFY_TYPE_HT_BW) + rlmRollbackOpChangeParam(prBssInfo, + TRUE, FALSE); + else if (ucOpChangeType == + OP_NOTIFY_TYPE_HT_NSS) + rlmRollbackOpChangeParam(prBssInfo, + FALSE, TRUE); + + /* Case1: Wait for both HT BW/Nss notification + * frame TX done + */ + if (*pucRelatedOpState == + OP_NOTIFY_STATE_SENDING) { + return; + + /* Case2: Both BW and Nss notification + * TX done + * or only change either BW or Nss + */ + } else if ((*pucRelatedOpState == + OP_NOTIFY_STATE_KEEP) || + (*pucRelatedOpState == + OP_NOTIFY_STATE_FAIL)) { + fgIsOpModeChangeSuccess = FALSE; + + /* Case3: One of the notification TX + * failed, + * re-send a notification frame to + * rollback the successful one + */ + } else if (*pucRelatedOpState == + OP_NOTIFY_STATE_SUCCESS) { + /*Rollback to keep the original BW/Nss + */ + *pucRelatedOpState = + OP_NOTIFY_STATE_KEEP; + + if (ucRelatedFrameType == + OP_NOTIFY_TYPE_HT_BW) { + rlmSendNotifyChannelWidthFrame( + prAdapter, prStaRec, + rlmGetBssOpBwByVhtAndHtOpInfo( + prBssInfo)); + } else if (ucRelatedFrameType == + OP_NOTIFY_TYPE_HT_NSS) + rlmSendSmPowerSaveFrame( + prAdapter, prStaRec, + prBssInfo->ucNss); + + DBGLOG(RLM, INFO, + "Bss[%d] OpType[%d] Tx Failed, send a OpType[%d] for roll back to BW[%d] Nss[%d]\n", + prMsduInfo->ucBssIndex, + ucOpChangeType, + ucRelatedFrameType, + rlmGetBssOpBwByVhtAndHtOpInfo( + prBssInfo), + prBssInfo->ucNss); + + return; + } + } else if (*pucCurrOpState == + OP_NOTIFY_STATE_KEEP) /* Rollback OpMode */ + /* Case4: Rollback failed, keep changing OP + * BW/Nss + */ + fgIsOpModeChangeSuccess = FALSE; + } /* End of processing TX failed */ + + } while (FALSE); + + /* <4>Change own OP info */ + rlmCompleteOpModeChange(prAdapter, prBssInfo, fgIsOpModeChangeSuccess); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static void rlmRollbackOpChangeParam(struct BSS_INFO *prBssInfo, + u_int8_t fgIsRollbackBw, + u_int8_t fgIsRollbackNss) +{ + + ASSERT(prBssInfo); + + if (fgIsRollbackBw == TRUE) { + prBssInfo->fgIsOpChangeChannelWidth = FALSE; + prBssInfo->ucOpChangeChannelWidth = + rlmGetBssOpBwByVhtAndHtOpInfo(prBssInfo); + } + + if (fgIsRollbackNss == TRUE) { + prBssInfo->fgIsOpChangeNss = FALSE; + prBssInfo->ucOpChangeNss = prBssInfo->ucNss; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Get BSS operating channel width by VHT and HT OP Info + * + * \param[in] + * + * \return ucBssOpBw 0:20MHz, 1:40MHz, 2:80MHz, 3:160MHz 4:80+80MHz + * + */ +/*----------------------------------------------------------------------------*/ +uint8_t rlmGetBssOpBwByVhtAndHtOpInfo(struct BSS_INFO *prBssInfo) +{ + + uint8_t ucBssOpBw = MAX_BW_20MHZ; + + ASSERT(prBssInfo); + + switch (prBssInfo->ucVhtChannelWidth) { + case VHT_OP_CHANNEL_WIDTH_80P80: + ucBssOpBw = MAX_BW_80_80_MHZ; + break; + + case VHT_OP_CHANNEL_WIDTH_160: + ucBssOpBw = MAX_BW_160MHZ; + break; + + case VHT_OP_CHANNEL_WIDTH_80: + ucBssOpBw = MAX_BW_80MHZ; + break; + + case VHT_OP_CHANNEL_WIDTH_20_40: + if (prBssInfo->eBssSCO != CHNL_EXT_SCN) + ucBssOpBw = MAX_BW_40MHZ; + break; + default: + DBGLOG(RLM, WARN, "%s: unexpected VHT channel width: %d\n", + __func__, prBssInfo->ucVhtChannelWidth); +#if CFG_SUPPORT_802_11AC + if (RLM_NET_IS_11AC(prBssInfo)) + /*VHT default should support BW 80*/ + ucBssOpBw = MAX_BW_80MHZ; +#endif + break; + } + + return ucBssOpBw; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return ucVhtOpBw 0:20M/40Hz, 1:80MHz, 2:160MHz, 3:80+80MHz + * + */ +/*----------------------------------------------------------------------------*/ +uint8_t rlmGetVhtOpBwByBssOpBw(uint8_t ucBssOpBw) +{ + uint8_t ucVhtOpBw = + VHT_OP_CHANNEL_WIDTH_80; /*VHT default should support BW 80*/ + + switch (ucBssOpBw) { + case MAX_BW_20MHZ: + case MAX_BW_40MHZ: + ucVhtOpBw = VHT_OP_CHANNEL_WIDTH_20_40; + break; + + case MAX_BW_80MHZ: + ucVhtOpBw = VHT_OP_CHANNEL_WIDTH_80; + break; + + case MAX_BW_160MHZ: + ucVhtOpBw = VHT_OP_CHANNEL_WIDTH_160; + break; + + case MAX_BW_80_80_MHZ: + ucVhtOpBw = VHT_OP_CHANNEL_WIDTH_80P80; + break; + default: + DBGLOG(RLM, WARN, "%s: unexpected Bss OP BW: %d\n", __func__, + ucBssOpBw); + break; + } + + return ucVhtOpBw; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Get operating notification channel width by VHT and HT operating Info + * + * \param[in] + * + * \return ucOpModeBw 0:20MHz, 1:40MHz, 2:80MHz, 3:160MHz/80+80MHz + * + */ +/*----------------------------------------------------------------------------*/ +static uint8_t rlmGetOpModeBwByVhtAndHtOpInfo(struct BSS_INFO *prBssInfo) +{ + uint8_t ucOpModeBw = VHT_OP_MODE_CHANNEL_WIDTH_20; + + ASSERT(prBssInfo); + + switch (prBssInfo->ucVhtChannelWidth) { + case VHT_OP_CHANNEL_WIDTH_20_40: + if (prBssInfo->eBssSCO != CHNL_EXT_SCN) + ucOpModeBw = VHT_OP_MODE_CHANNEL_WIDTH_40; + break; + case VHT_OP_CHANNEL_WIDTH_80: + ucOpModeBw = VHT_OP_MODE_CHANNEL_WIDTH_80; + break; + case VHT_OP_CHANNEL_WIDTH_160: + case VHT_OP_CHANNEL_WIDTH_80P80: + ucOpModeBw = VHT_OP_MODE_CHANNEL_WIDTH_160_80P80; + break; + default: + DBGLOG(RLM, WARN, "%s: unexpected VHT channel width: %d\n", + __func__, prBssInfo->ucVhtChannelWidth); + /*VHT default IE should support BW 80*/ + ucOpModeBw = VHT_OP_MODE_CHANNEL_WIDTH_80; + break; + } + + return ucOpModeBw; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static void rlmChangeOwnOpInfo(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo) +{ + struct STA_RECORD *prStaRec; + + ASSERT((prAdapter != NULL) && (prBssInfo != NULL)); + + /* Update own operating channel Width */ + if (prBssInfo->fgIsOpChangeChannelWidth) { + if (prBssInfo->ucPhyTypeSet & PHY_TYPE_BIT_HT) { +#if CFG_SUPPORT_802_11AC + /* Update VHT OP Info*/ + if (prBssInfo->ucPhyTypeSet & PHY_TYPE_BIT_VHT) { + rlmFillVhtOpInfoByBssOpBw( + prBssInfo, + prBssInfo->ucOpChangeChannelWidth); + + DBGLOG(RLM, INFO, + "Update BSS[%d] VHT Channel Width Info to w=%d s1=%d s2=%d\n", + prBssInfo->ucBssIndex, + prBssInfo->ucVhtChannelWidth, + prBssInfo->ucVhtChannelFrequencyS1, + prBssInfo->ucVhtChannelFrequencyS2); + } +#endif + + /* Update HT OP Info*/ + if (prBssInfo->ucOpChangeChannelWidth == MAX_BW_20MHZ) { + prBssInfo->ucHtOpInfo1 &= + ~HT_OP_INFO1_STA_CHNL_WIDTH; + prBssInfo->eBssSCO = CHNL_EXT_SCN; + } else { + prBssInfo->ucHtOpInfo1 |= + HT_OP_INFO1_STA_CHNL_WIDTH; + + if (prBssInfo->eCurrentOPMode == + OP_MODE_INFRASTRUCTURE) { + prStaRec = prBssInfo->prStaRecOfAP; + if (!prStaRec) + return; + + if ((prStaRec->ucHtPeerOpInfo1 & + HT_OP_INFO1_SCO) != CHNL_EXT_RES) + prBssInfo->eBssSCO = + (enum ENUM_CHNL_EXT)( + prStaRec->ucHtPeerOpInfo1 & + HT_OP_INFO1_SCO); + } else if (prBssInfo->eCurrentOPMode == + OP_MODE_ACCESS_POINT) { + prBssInfo->eBssSCO = rlmDecideScoForAP( + prAdapter, prBssInfo); + } + } + + DBGLOG(RLM, INFO, + "Update BSS[%d] HT Channel Width Info to bw=%d sco=%d\n", + prBssInfo->ucBssIndex, + (uint8_t)((prBssInfo->ucHtOpInfo1 & + HT_OP_INFO1_STA_CHNL_WIDTH) >> + HT_OP_INFO1_STA_CHNL_WIDTH_OFFSET), + prBssInfo->eBssSCO); + } + } + + /* Update own operating Nss */ + if (prBssInfo->fgIsOpChangeNss) { + prBssInfo->ucNss = prBssInfo->ucOpChangeNss; + DBGLOG(RLM, INFO, "Update OP Nss = %d\n", prBssInfo->ucNss); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static void rlmCompleteOpModeChange(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + u_int8_t fgIsSuccess) +{ + + ASSERT((prAdapter != NULL) && (prBssInfo != NULL)); + + if ((prBssInfo->fgIsOpChangeChannelWidth) || + (prBssInfo->fgIsOpChangeNss)) { + + /* <1> Update own OP BW/Nss */ + rlmChangeOwnOpInfo(prAdapter, prBssInfo); + + /* <2> Update OP BW/Nss to FW */ + rlmSyncOperationParams(prAdapter, prBssInfo); + + /* <3> Update BCN/Probe Resp IE to notify peers our OP info is + * changed (AP mode) + */ + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) + bssUpdateBeaconContent(prAdapter, + prBssInfo->ucBssIndex); + } + + DBGLOG(RLM, INFO, "Complete BSS[%d] OP Mode change to BW[%d] Nss[%d]\n", + prBssInfo->ucBssIndex, rlmGetBssOpBwByVhtAndHtOpInfo(prBssInfo), + prBssInfo->ucNss); + + /* <4> Tell OpMode change caller the change result */ + if (prBssInfo->pfOpChangeHandler) { + prBssInfo->pfOpChangeHandler(prAdapter, prBssInfo->ucBssIndex, + fgIsSuccess); + /* Clear to NULL when handling OP Mode change request done */ + prBssInfo->pfOpChangeHandler = NULL; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Change OpMode Nss/Channel Width + * + * \param[in] ucChannelWidth 0:20MHz, 1:40MHz, 2:80MHz, 3:160MHz 4:80+80MHz + * + * \return fgIsChangeOpMode + * TRUE: Can change/Don't need to change operation mode + * FALSE: Can't change operation mode + */ +/*----------------------------------------------------------------------------*/ +enum ENUM_OP_CHANGE_STATUS_T +rlmChangeOperationMode(struct ADAPTER *prAdapter, uint8_t ucBssIndex, + uint8_t ucChannelWidth, uint8_t ucNss, + PFN_OPMODE_NOTIFY_DONE_FUNC pfOpChangeHandler) +{ + struct BSS_INFO *prBssInfo; + struct STA_RECORD *prStaRec = (struct STA_RECORD *)NULL; + u_int8_t fgIsChangeBw = TRUE, + fgIsChangeNss = TRUE; /* Indicate if need to change */ + uint8_t i; + + /* Sanity check */ + if (ucBssIndex >= prAdapter->ucHwBssIdNum) + return OP_CHANGE_STATUS_INVALID; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (!prBssInfo) + return OP_CHANGE_STATUS_INVALID; + + /* <1>Check if OP change parameter is valid */ + if (rlmCheckOpChangeParamValid(prAdapter, prBssInfo, ucChannelWidth, + ucNss) == FALSE) + return OP_CHANGE_STATUS_INVALID; + + /* <2>Check if OpMode notification is ongoing, if not, register the call + * back function + */ + if (prBssInfo->pfOpChangeHandler) { + DBGLOG(RLM, INFO, + "BSS[%d] OpMode change notification is ongoing\n", + ucBssIndex); + return OP_CHANGE_STATUS_INVALID; + } + + prBssInfo->pfOpChangeHandler = pfOpChangeHandler; + + /* <3>Check if the current operating BW/Nss is the same as the target + * one + */ + if (ucChannelWidth == rlmGetBssOpBwByVhtAndHtOpInfo(prBssInfo)) + fgIsChangeBw = FALSE; + + if (ucNss == prBssInfo->ucNss) + fgIsChangeNss = FALSE; + + if ((!fgIsChangeBw) && (!fgIsChangeNss)) { + if (prBssInfo->pfOpChangeHandler) { + /* (1) Don't need to call callback at no need to change + * OP mode case + * (2) Clear callback to NULL when handling OP Mode + * change request done + */ + prBssInfo->pfOpChangeHandler = NULL; + } + + DBGLOG(RLM, INFO, + "BSS[%d] target OpMode BW[%d] Nss[%d] is the same as cuurent\n", + ucBssIndex, ucChannelWidth, ucNss); + return OP_CHANGE_STATUS_VALID_NO_CHANGE; + } + + DBGLOG(RLM, INFO, + "Intend to change BSS[%d] OP Mode to BW[%d] Nss[%d]\n", + ucBssIndex, ucChannelWidth, ucNss); + + /* <4> Fill OP Change Info into BssInfo*/ + if (fgIsChangeBw) { + prBssInfo->ucOpChangeChannelWidth = ucChannelWidth; + prBssInfo->fgIsOpChangeChannelWidth = TRUE; + DBGLOG(RLM, INFO, "Intend to change BSS[%d] to BW[%d]\n", + ucBssIndex, ucChannelWidth); + } + if (fgIsChangeNss) { + prBssInfo->ucOpChangeNss = ucNss; + prBssInfo->fgIsOpChangeNss = TRUE; + DBGLOG(RLM, INFO, "Intend to change BSS[%d] to Nss[%d]\n", + ucBssIndex, ucNss); + } + + /* <5>Handling OP Info change for STA/GC */ + if ((prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) && + (prBssInfo->prStaRecOfAP)) { + prStaRec = prBssInfo->prStaRecOfAP; + + /* <5.1>Initialize OP mode change parameters related to + * notification Tx done handler (STA mode) + */ + if (prBssInfo->pfOpChangeHandler) { + for (i = 0; i < OP_NOTIFY_TYPE_NUM; i++) { + prBssInfo->aucOpModeChangeState[i] = + OP_NOTIFY_STATE_KEEP; + prBssInfo->aucOpModeChangeRetryCnt[i] = 0; + } + } + +/* <5.2> Send operating mode notification frame (STA mode) */ +#if CFG_SUPPORT_802_11AC + if (RLM_NET_IS_11AC(prBssInfo)) { + if (prBssInfo->pfOpChangeHandler) + prBssInfo->aucOpModeChangeState + [OP_NOTIFY_TYPE_VHT_NSS_BW] = + OP_NOTIFY_STATE_SENDING; + + DBGLOG(RLM, INFO, + "Send VHT OP notification frame: BSS[%d] BW[%d] Nss[%d]\n", + ucBssIndex, ucChannelWidth, ucNss); + + rlmSendOpModeNotificationFrame(prAdapter, prStaRec, + ucChannelWidth, ucNss); + } else +#endif + { + if (RLM_NET_IS_11N(prBssInfo)) { + if (prBssInfo->pfOpChangeHandler) { + if (fgIsChangeNss) + prBssInfo->aucOpModeChangeState + [OP_NOTIFY_TYPE_HT_NSS] = + OP_NOTIFY_STATE_SENDING; + if (fgIsChangeBw) + prBssInfo->aucOpModeChangeState + [OP_NOTIFY_TYPE_HT_BW] = + OP_NOTIFY_STATE_SENDING; + } + + if (fgIsChangeNss) { + rlmSendSmPowerSaveFrame( + prAdapter, prStaRec, ucNss); + DBGLOG(RLM, INFO, + "Send HT SM Power Save frame: BSS[%d] Nss[%d]\n", + ucBssIndex, ucNss); + } + + if (fgIsChangeBw) { + rlmSendNotifyChannelWidthFrame( + prAdapter, prStaRec, + ucChannelWidth); + DBGLOG(RLM, INFO, + "Send HT Notify Channel Width frame: BSS[%d] BW[%d]\n", + ucBssIndex, ucChannelWidth); + } + } + } + + /* <5.3> Change OP Info w/o waiting for notification Tx done */ + if (prBssInfo->pfOpChangeHandler == NULL) { + rlmCompleteOpModeChange(prAdapter, prBssInfo, TRUE); + /* No callback */ + return OP_CHANGE_STATUS_VALID_CHANGE_CALLBACK_DONE; + } + } + /* <6>Handling OP Info change for AP/GO */ + else if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + /* Complete OP Info change after notifying client by beacon */ + rlmCompleteOpModeChange(prAdapter, prBssInfo, TRUE); + return OP_CHANGE_STATUS_VALID_CHANGE_CALLBACK_DONE; + } + + return OP_CHANGE_STATUS_VALID_CHANGE_CALLBACK_WAIT; +} + +static u_int8_t rlmCheckOpChangeParamForClient(struct BSS_INFO *prBssInfo, + uint8_t ucChannelWidth, + uint8_t ucNss) +{ + struct STA_RECORD *prStaRec; + + prStaRec = prBssInfo->prStaRecOfAP; + + if (!prStaRec) + return FALSE; + +#if CFG_SUPPORT_802_11AC + if (RLM_NET_IS_11AC(prBssInfo)) { /* VHT */ + /* Check peer OP Channel Width */ + switch (ucChannelWidth) { + case MAX_BW_80_80_MHZ: + if (prStaRec->ucVhtOpChannelWidth != + VHT_OP_CHANNEL_WIDTH_80P80) { + DBGLOG(RLM, INFO, + "Can't change BSS[%d] OP BW to:%d for peer VHT OP BW is:%d\n", + prBssInfo->ucBssIndex, ucChannelWidth, + prStaRec->ucVhtOpChannelWidth); + return FALSE; + } + break; + case MAX_BW_160MHZ: + if (prStaRec->ucVhtOpChannelWidth != + VHT_OP_CHANNEL_WIDTH_160) { + DBGLOG(RLM, INFO, + "Can't change BSS[%d] OP BW to:%d for peer VHT OP BW is:%d\n", + prBssInfo->ucBssIndex, ucChannelWidth, + prStaRec->ucVhtOpChannelWidth); + return FALSE; + } + break; + case MAX_BW_80MHZ: + if (prStaRec->ucVhtOpChannelWidth < + VHT_OP_CHANNEL_WIDTH_80) { + DBGLOG(RLM, INFO, + "Can't change BSS[%d] OP BW to:%d for peer VHT OP BW is:%d\n", + prBssInfo->ucBssIndex, ucChannelWidth, + prStaRec->ucVhtOpChannelWidth); + return FALSE; + } + break; + case MAX_BW_40MHZ: + if (!(prStaRec->ucHtPeerOpInfo1 & + HT_OP_INFO1_STA_CHNL_WIDTH) || + (!prBssInfo->fg40mBwAllowed)) { + DBGLOG(RLM, INFO, + "Can't change BSS[%d] OP BW to:%d for PeerOpBw:%d fg40mBwAllowed:%d\n", + prBssInfo->ucBssIndex, ucChannelWidth, + (uint8_t)(prStaRec->ucHtPeerOpInfo1 & + HT_OP_INFO1_STA_CHNL_WIDTH), + prBssInfo->fg40mBwAllowed); + return FALSE; + } + break; + case MAX_BW_20MHZ: + break; + default: + DBGLOG(RLM, WARN, + "BSS[%d] target OP BW:%d is invalid for VHT OpMode change\n", + prBssInfo->ucBssIndex, ucChannelWidth); + return FALSE; + } + + /* Check peer Rx Nss Cap */ + if (ucNss == 2 && + ((prStaRec->u2VhtRxMcsMap & VHT_CAP_INFO_MCS_2SS_MASK) >> + VHT_CAP_INFO_MCS_2SS_OFFSET) == + VHT_CAP_INFO_MCS_NOT_SUPPORTED) { + DBGLOG(RLM, INFO, + "Don't change Nss since VHT peer doesn't support 2ss\n"); + return FALSE; + } + + } else +#endif + { + if (RLM_NET_IS_11N(prBssInfo)) { /* HT */ + /* Check peer Channel Width */ + if (ucChannelWidth >= MAX_BW_80MHZ) { + DBGLOG(RLM, WARN, + "BSS[%d] target OP BW:%d is invalid for HT OpMode change\n", + prBssInfo->ucBssIndex, ucChannelWidth); + return FALSE; + } else if (ucChannelWidth == + MAX_BW_40MHZ) { + if (!(prStaRec->ucHtPeerOpInfo1 & + HT_OP_INFO1_STA_CHNL_WIDTH) || + (!prBssInfo->fg40mBwAllowed)) { + DBGLOG(RLM, INFO, + "Can't change BSS[%d] OP BW to:%d for PeerOpBw:%d fg40mBwAllowed:%d\n", + prBssInfo->ucBssIndex, + ucChannelWidth, + (uint8_t)( + prStaRec->ucHtPeerOpInfo1 & + HT_OP_INFO1_STA_CHNL_WIDTH), + prBssInfo->fg40mBwAllowed); + return FALSE; + } + } + + /* Check peer Rx Nss Cap */ + if (ucNss == 2 && (prStaRec->aucRxMcsBitmask[1] == 0)) { + DBGLOG(RLM, INFO, + "Don't change Nss since HT peer doesn't support 2ss\n"); + return FALSE; + } + } + } + return TRUE; +} + +static u_int8_t rlmCheckOpChangeParamValid(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + uint8_t ucChannelWidth, + uint8_t ucNss) +{ + + ASSERT(prBssInfo); + + /* <1>Check if BSS PHY type is legacy mode */ + if (!RLM_NET_IS_11N(prBssInfo)) { + DBGLOG(RLM, WARN, + "Can't change BSS[%d] OP info for legacy BSS\n", + prBssInfo->ucBssIndex); + return FALSE; + } + + /* <2>Check network type */ + if ((prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) && + (prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT)) { + DBGLOG(RLM, WARN, + "Can't change BSS[%d] OP info for OpMode:%d\n", + prBssInfo->ucBssIndex, prBssInfo->eCurrentOPMode); + return FALSE; + } + + /* <3>Check if target OP BW/Nss <= Own Cap BW/Nss */ + if (ucNss > wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex)) { + DBGLOG(RLM, WARN, + "Can't change BSS[%d] OP Nss to:%d since own Cap Nss is:%d\n", + prBssInfo->ucBssIndex, ucNss, + wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex)); + return FALSE; + } + + if (ucChannelWidth > cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex)) { + DBGLOG(RLM, WARN, + "Can't change BSS[%d] OP BW to:%d since own Cap BW is:%d\n", + prBssInfo->ucBssIndex, ucChannelWidth, + cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex)); + return FALSE; + } + + /* <4>Check if target OP BW is valid for band and primary channel of + * current BSS + */ + if (prBssInfo->eBand == BAND_2G4) { + if ((ucChannelWidth != MAX_BW_20MHZ) && + (ucChannelWidth != MAX_BW_40MHZ)) { + DBGLOG(RLM, WARN, + "Can't change BSS[%d] OP BW to:%d for 2.4G\n", + prBssInfo->ucBssIndex, ucChannelWidth); + return FALSE; + } + } else { + if (prBssInfo->ucPrimaryChannel == + 165) { /*It can only use BW20 for CH165*/ + DBGLOG(RLM, WARN, + "Can't change BSS[%d] OP BW for CH165\n", + prBssInfo->ucBssIndex); + return FALSE; + } + + if ((ucChannelWidth == MAX_BW_160MHZ) && + ((prBssInfo->ucPrimaryChannel < 36) || + ((prBssInfo->ucPrimaryChannel > 64) && + (prBssInfo->ucPrimaryChannel < 100)) || + (prBssInfo->ucPrimaryChannel > 128))) { + DBGLOG(RLM, WARN, + "Can't change BSS[%d] to OP BW160 for primary CH%d\n", + prBssInfo->ucBssIndex, + prBssInfo->ucPrimaryChannel); + return FALSE; + } + } + + /* <5>Check if target OP BW/Nss <= peer's BW/Nss (STA mode) */ + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + if (rlmCheckOpChangeParamForClient(prBssInfo, ucChannelWidth, + ucNss) == FALSE) + return FALSE; + } + + return TRUE; +} + +void rlmDummyChangeOpHandler(struct ADAPTER *prAdapter, uint8_t ucBssIndex, + u_int8_t fgIsChangeSuccess) +{ + DBGLOG(RLM, INFO, "OP change done for BSS[%d] IsSuccess[%d]\n", + ucBssIndex, fgIsChangeSuccess); +} + +/* 11K */ +void rlmProcessNeighborReportResonse(struct ADAPTER *prAdapter, + struct WLAN_ACTION_FRAME *prAction, + uint16_t u2PacketLen) +{ + struct ACTION_NEIGHBOR_REPORT_FRAME *prNeighborResponse = + (struct ACTION_NEIGHBOR_REPORT_FRAME *)prAction; + + ASSERT(prAdapter); + ASSERT(prNeighborResponse); + DBGLOG(RLM, INFO, "Neighbor Resp From " MACSTR ", DialogToken %d\n", + MAC2STR(prNeighborResponse->aucSrcAddr), + prNeighborResponse->ucDialogToken); + aisCollectNeighborAP( + prAdapter, &prNeighborResponse->aucInfoElem[0], + u2PacketLen - OFFSET_OF(struct ACTION_NEIGHBOR_REPORT_FRAME, + aucInfoElem), + 0); +} + +void rlmTxNeighborReportRequest(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + struct SUB_ELEMENT_LIST *prSubIEs) +{ + static uint8_t ucDialogToken = 1; + struct MSDU_INFO *prMsduInfo = NULL; + struct BSS_INFO *prBssInfo = NULL; + uint8_t *pucPayload = NULL; + struct ACTION_NEIGHBOR_REPORT_FRAME *prTxFrame = NULL; + uint16_t u2TxFrameLen = 500; + uint16_t u2FrameLen = 0; + + if (!prStaRec) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + ASSERT(prBssInfo); + /* 1 Allocate MSDU Info */ + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc( + prAdapter, MAC_TX_RESERVED_FIELD + u2TxFrameLen); + if (!prMsduInfo) + return; + prTxFrame = (struct ACTION_NEIGHBOR_REPORT_FRAME + *)((unsigned long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + + /* 2 Compose The Mac Header. */ + 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_RM_ACTION; + prTxFrame->ucAction = RM_ACTION_NEIGHBOR_REQUEST; + u2FrameLen = + OFFSET_OF(struct ACTION_NEIGHBOR_REPORT_FRAME, aucInfoElem); + /* 3 Compose the frame body's frame. */ + prTxFrame->ucDialogToken = ucDialogToken++; + u2TxFrameLen -= sizeof(*prTxFrame) - 1; + pucPayload = &prTxFrame->aucInfoElem[0]; + while (prSubIEs && u2TxFrameLen >= (prSubIEs->rSubIE.ucLength + 2)) { + kalMemCopy(pucPayload, &prSubIEs->rSubIE, + prSubIEs->rSubIE.ucLength + 2); + pucPayload += prSubIEs->rSubIE.ucLength + 2; + u2FrameLen += prSubIEs->rSubIE.ucLength + 2; + prSubIEs = prSubIEs->prNext; + } + nicTxSetMngPacket(prAdapter, prMsduInfo, prStaRec->ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_MGMT_HEADER_LEN, + u2FrameLen, NULL, MSDU_RATE_MODE_AUTO); + + /* 5 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); +} + +void rlmComposeEmptyBeaconReport(struct ADAPTER *prAdapter) +{ + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq = + &prAdapter->rWifiVar.rRmReqParams; + struct RADIO_MEASUREMENT_REPORT_PARAMS *prRmRep = + &prAdapter->rWifiVar.rRmRepParams; + uint8_t *pucReportFrame = + prRmRep->pucReportFrameBuff + prRmRep->u2ReportFrameLen; + struct IE_MEASUREMENT_REPORT *prRepIE = + (struct IE_MEASUREMENT_REPORT *)pucReportFrame; + struct RM_BCN_REPORT *prBcnReport = + (struct RM_BCN_REPORT *)prRepIE->aucReportFields; + + /* fill in basic content of Measurement report IE */ + prRepIE->ucId = ELEM_ID_MEASUREMENT_REPORT; + prRepIE->ucToken = prRmReq->prCurrMeasElem->ucToken; + prRepIE->ucMeasurementType = prRmReq->prCurrMeasElem->ucMeasurementType; + prRepIE->ucReportMode = 0; + prRepIE->ucLength = 3 + OFFSET_OF(struct RM_BCN_REPORT, aucOptElem); + kalMemZero(prBcnReport, OFFSET_OF(struct RM_BCN_REPORT, aucOptElem)); + prBcnReport->ucRegulatoryClass = + 255; /* 255 means reglatory is not available */ + prBcnReport->ucChannel = 255; /* 255 means channel is not available */ + prBcnReport->ucReportInfo = + 255; /* 255 means report frame info is not available */ + prBcnReport->ucRSNI = 255; /* 255 means RSNI is not available */ + prBcnReport->ucAntennaID = 1; + + prRmRep->u2ReportFrameLen += IE_SIZE(&prRepIE); +} + +void rlmFreeMeasurementResources(struct ADAPTER *prAdapter) +{ + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq = + &prAdapter->rWifiVar.rRmReqParams; + struct RADIO_MEASUREMENT_REPORT_PARAMS *prRmRep = + &prAdapter->rWifiVar.rRmRepParams; + struct RM_MEASURE_REPORT_ENTRY *prReportEntry = NULL; + struct LINK *prReportLink = &prRmRep->rReportLink; + struct LINK *prFreeReportLink = &prRmRep->rFreeReportLink; + u_int8_t fgHasBcnReqTimer = timerPendingTimer(&rBeaconReqTimer); + + DBGLOG(RLM, TRACE, "RRM: Free measurement, Beacon Req timer is %d\n", + fgHasBcnReqTimer); + if (fgHasBcnReqTimer) + cnmTimerStopTimer(prAdapter, &rBeaconReqTimer); + + kalMemFree(prRmReq->pucReqIeBuf, VIR_MEM_TYPE, prRmReq->u2ReqIeBufLen); + kalMemFree(prRmRep->pucReportFrameBuff, VIR_MEM_TYPE, + RM_REPORT_FRAME_MAX_LENGTH); + while (!LINK_IS_EMPTY(prReportLink)) { + LINK_REMOVE_HEAD(prReportLink, prReportEntry, + struct RM_MEASURE_REPORT_ENTRY *); + kalMemFree(prReportEntry, VIR_MEM_TYPE, sizeof(*prReportEntry)); + } + while (!LINK_IS_EMPTY(prFreeReportLink)) { + LINK_REMOVE_HEAD(prFreeReportLink, prReportEntry, + struct RM_MEASURE_REPORT_ENTRY *); + kalMemFree(prReportEntry, VIR_MEM_TYPE, sizeof(*prReportEntry)); + } + kalMemZero(prRmReq, sizeof(*prRmReq)); + kalMemZero(prRmRep, sizeof(*prRmRep)); + prRmReq->rBcnRmParam.eState = RM_NO_REQUEST; + prRmReq->fgRmIsOngoing = FALSE; + LINK_INITIALIZE(&prRmRep->rFreeReportLink); + LINK_INITIALIZE(&prRmRep->rReportLink); +} + +/* purpose: check if Radio Measurement is done */ +static u_int8_t +rlmAllMeasurementIssued(struct RADIO_MEASUREMENT_REQ_PARAMS *prReq) +{ + return prReq->u2RemainReqLen > IE_SIZE(prReq->prCurrMeasElem) ? FALSE + : TRUE; +} + +void rlmComposeIncapableRmRep(struct RADIO_MEASUREMENT_REPORT_PARAMS *prRep, + uint8_t ucToken, uint8_t ucMeasType) +{ + struct IE_MEASUREMENT_REPORT *prRepIE = + (struct IE_MEASUREMENT_REPORT *)(prRep->pucReportFrameBuff + + prRep->u2ReportFrameLen); + + prRepIE->ucId = ELEM_ID_MEASUREMENT_REPORT; + prRepIE->ucToken = ucToken; + prRepIE->ucMeasurementType = ucMeasType; + prRepIE->ucLength = 3; + prRepIE->ucReportMode = RM_REP_MODE_INCAPABLE; + prRep->u2ReportFrameLen += 5; +} +/* Purpose: Interative processing Measurement Request Element. If it is not the + ** first element, + ** will copy all collected report element to the report frame buffer. and + ** may tx the radio report frame. + ** prAdapter: pointer to the Adapter + ** fgNewStarted: if it is the first element in measurement request frame + */ +void rlmStartNextMeasurement(struct ADAPTER *prAdapter, u_int8_t fgNewStarted) +{ + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq = + &prAdapter->rWifiVar.rRmReqParams; + struct RADIO_MEASUREMENT_REPORT_PARAMS *prRmRep = + &prAdapter->rWifiVar.rRmRepParams; + struct IE_MEASUREMENT_REQ *prCurrReq = prRmReq->prCurrMeasElem; + uint16_t u2RandomTime = 0; + +schedule_next: + if (!prRmReq->fgRmIsOngoing) { + DBGLOG(RLM, INFO, "RRM: Rm has been stopped\n"); + return; + } + /* we don't support parallel measurement now */ + if (prCurrReq->ucRequestMode & RM_REQ_MODE_PARALLEL_BIT) { + DBGLOG(RLM, WARN, + "RRM: Parallel request, compose incapable report\n"); + if (prRmRep->u2ReportFrameLen + 5 > RM_REPORT_FRAME_MAX_LENGTH) + rlmTxRadioMeasurementReport(prAdapter); + rlmComposeIncapableRmRep(prRmRep, prCurrReq->ucToken, + prCurrReq->ucMeasurementType); + if (rlmAllMeasurementIssued(prRmReq)) { + if (prRmReq->rBcnRmParam.fgExistBcnReq && + RM_EXIST_REPORT(prRmRep)) + rlmComposeEmptyBeaconReport(prAdapter); + rlmTxRadioMeasurementReport(prAdapter); + + /* repeat measurement if repetitions is required and not + * only parallel measurements. + * otherwise, no need to repeat, it is not make sense to + * do that. + */ + if (prRmReq->u2Repetitions > 0) { + prRmReq->fgInitialLoop = FALSE; + prRmReq->u2Repetitions--; + prCurrReq = prRmReq->prCurrMeasElem = + (struct IE_MEASUREMENT_REQ *) + prRmReq->pucReqIeBuf; + prRmReq->u2RemainReqLen = + prRmReq->u2ReqIeBufLen; + } else { + rlmFreeMeasurementResources(prAdapter); + DBGLOG(RLM, INFO, + "RRM: Radio Measurement done\n"); + return; + } + } else { + uint16_t u2IeSize = IE_SIZE(prRmReq->prCurrMeasElem); + + prCurrReq = prRmReq->prCurrMeasElem = + (struct IE_MEASUREMENT_REQ + *)((uint8_t *)prRmReq->prCurrMeasElem + + u2IeSize); + prRmReq->u2RemainReqLen -= u2IeSize; + } + fgNewStarted = FALSE; + goto schedule_next; + } + /* copy collected measurement report for specific measurement type */ + if (!fgNewStarted) { + struct RM_MEASURE_REPORT_ENTRY *prReportEntry = NULL; + struct LINK *prReportLink = &prRmRep->rReportLink; + struct LINK *prFreeReportLink = &prRmRep->rFreeReportLink; + uint8_t *pucReportFrame = + prRmRep->pucReportFrameBuff + prRmRep->u2ReportFrameLen; + uint16_t u2IeSize = 0; + u_int8_t fgNewLoop = FALSE; + + DBGLOG(RLM, INFO, + "RRM: total %u report element for current request\n", + prReportLink->u4NumElem); + /* copy collected report into the Measurement Report Frame + ** Buffer. + */ + while (1) { + LINK_REMOVE_HEAD(prReportLink, prReportEntry, + struct RM_MEASURE_REPORT_ENTRY *); + if (!prReportEntry) + break; + u2IeSize = IE_SIZE(prReportEntry->aucMeasReport); + /* if reach the max length of a MMPDU size, send a Rm + ** report first + */ + if (u2IeSize + prRmRep->u2ReportFrameLen > + RM_REPORT_FRAME_MAX_LENGTH) { + rlmTxRadioMeasurementReport(prAdapter); + pucReportFrame = prRmRep->pucReportFrameBuff + + prRmRep->u2ReportFrameLen; + } + kalMemCopy(pucReportFrame, prReportEntry->aucMeasReport, + u2IeSize); + pucReportFrame += u2IeSize; + prRmRep->u2ReportFrameLen += u2IeSize; + LINK_INSERT_TAIL(prFreeReportLink, + &prReportEntry->rLinkEntry); + } + /* if Measurement is done, free report element memory */ + if (rlmAllMeasurementIssued(prRmReq)) { + if (prRmReq->rBcnRmParam.fgExistBcnReq && + RM_EXIST_REPORT(prRmRep)) + rlmComposeEmptyBeaconReport(prAdapter); + rlmTxRadioMeasurementReport(prAdapter); + + /* repeat measurement if repetitions is required */ + if (prRmReq->u2Repetitions > 0) { + fgNewLoop = TRUE; + prRmReq->fgInitialLoop = FALSE; + prRmReq->u2Repetitions--; + prRmReq->prCurrMeasElem = + (struct IE_MEASUREMENT_REQ *) + prRmReq->pucReqIeBuf; + prRmReq->u2RemainReqLen = + prRmReq->u2ReqIeBufLen; + } else { + /* don't free radio measurement resource due to + ** TSM is running + */ + if (!wmmTsmIsOngoing(prAdapter)) { + rlmFreeMeasurementResources(prAdapter); + DBGLOG(RLM, INFO, + "RRM: Radio Measurement done\n"); + } + return; + } + } + if (!fgNewLoop) { + u2IeSize = IE_SIZE(prRmReq->prCurrMeasElem); + prCurrReq = prRmReq->prCurrMeasElem = + (struct IE_MEASUREMENT_REQ + *)((uint8_t *)prRmReq->prCurrMeasElem + + u2IeSize); + prRmReq->u2RemainReqLen -= u2IeSize; + } + } + + /* do specific measurement */ + switch (prCurrReq->ucMeasurementType) { + case ELEM_RM_TYPE_BEACON_REQ: { + struct RM_BCN_REQ *prBeaconReq = + (struct RM_BCN_REQ *)&prCurrReq->aucRequestFields[0]; + + if (!prRmReq->fgInitialLoop) { + /* If this is the repeating measurement, then wait next + ** scan done + */ + prRmReq->rBcnRmParam.eState = RM_WAITING; + break; + } + if (prBeaconReq->u2RandomInterval == 0) + rlmDoBeaconMeasurement(prAdapter, 0); + else { + get_random_bytes(&u2RandomTime, 2); + u2RandomTime = + (u2RandomTime * prBeaconReq->u2RandomInterval) / + 65535; + u2RandomTime = TU_TO_MSEC(u2RandomTime); + if (u2RandomTime > 0) { + cnmTimerStopTimer(prAdapter, &rBeaconReqTimer); + cnmTimerInitTimer(prAdapter, &rBeaconReqTimer, + rlmDoBeaconMeasurement, 0); + cnmTimerStartTimer(prAdapter, &rBeaconReqTimer, + u2RandomTime); + } else + rlmDoBeaconMeasurement(prAdapter, 0); + } + break; + } +#if 0 + case ELEM_RM_TYPE_TSM_REQ: + { + struct RM_TS_MEASURE_REQ *prTsmReqIE = + (struct RM_TS_MEASURE_REQ *) + &prCurrReq->aucRequestFields[0]; + struct RM_TSM_REQ *prTsmReq = NULL; + uint16_t u2OffSet = 0; + uint8_t *pucIE = prTsmReqIE->aucSubElements; + struct ACTION_RM_REPORT_FRAME *prReportFrame = NULL; + + /* In case of repeating measurement, no need to start + ** triggered measurement again. According to current + ** specification of Radio Measurement, only TSM has the + ** triggered type of measurement. + */ + if ((prCurrReq->ucRequestMode & RM_REQ_MODE_ENABLE_BIT) && + !prRmReq->fgInitialLoop) + goto schedule_next; + + /* if enable bit is 1 and report bit is 0, need to stop all + ** triggered TSM measurement + */ + if ((prCurrReq->ucRequestMode & + (RM_REQ_MODE_ENABLE_BIT|RM_REQ_MODE_REPORT_BIT)) == + RM_REQ_MODE_ENABLE_BIT) { + wmmRemoveAllTsmMeasurement(prAdapter, TRUE); + break; + } + prTsmReq = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, + sizeof(struct RM_TSM_REQ)); + if (!prTsmReq) { + DBGLOG(RLM, ERROR, "No memory\n"); + break; + } + prTsmReq->ucToken = prCurrReq->ucToken; + prTsmReq->u2Duration = prTsmReqIE->u2Duration; + prTsmReq->ucTID = (prTsmReqIE->ucTrafficID & 0xf0) >> 4; + prTsmReq->ucB0Range = prTsmReqIE->ucBin0Range; + prReportFrame = (struct ACTION_RM_REPORT_FRAME *) + prRmRep->pucReportFrameBuff; + COPY_MAC_ADDR(prTsmReq->aucPeerAddr, + prReportFrame->aucDestAddr); + IE_FOR_EACH(pucIE, prCurrReq->ucLength - 3, u2OffSet) { + switch (IE_ID(pucIE)) { + case 1: /* Triggered Reporting */ + kalMemCopy(&prTsmReq->rTriggerCond, + pucIE+2, IE_LEN(pucIE)); + break; + case 221: /* Vendor Specified */ + break; /* No vendor IE now */ + default: + break; + } + } + if (!prTsmReqIE->u2RandomInterval) { + wmmStartTsmMeasurement(prAdapter, + (unsigned long)prTsmReq); + break; + } + get_random_bytes(&u2RandomTime, 2); + u2RandomTime = + (u2RandomTime * prTsmReqIE->u2RandomInterval) / 65535; + u2RandomTime = TU_TO_MSEC(u2RandomTime); + cnmTimerStopTimer(prAdapter, &rTSMReqTimer); + cnmTimerInitTimer(prAdapter, &rTSMReqTimer, + wmmStartTsmMeasurement, (unsigned long)prTsmReq); + cnmTimerStartTimer(prAdapter, &rTSMReqTimer, u2RandomTime); + break; + } +#endif + default: { + if (prRmRep->u2ReportFrameLen + 5 > RM_REPORT_FRAME_MAX_LENGTH) + rlmTxRadioMeasurementReport(prAdapter); + rlmComposeIncapableRmRep(prRmRep, prCurrReq->ucToken, + prCurrReq->ucMeasurementType); + fgNewStarted = FALSE; + DBGLOG(RLM, INFO, + "RRM: RM type %d is not supported on this chip\n", + prCurrReq->ucMeasurementType); + goto schedule_next; + } + } +} + +u_int8_t rlmBcnRmRunning(struct ADAPTER *prAdapter) +{ + return prAdapter->rWifiVar.rRmReqParams.rBcnRmParam.eState == + RM_ON_GOING; +} + +u_int8_t rlmFillScanMsg(struct ADAPTER *prAdapter, + struct MSG_SCN_SCAN_REQ_V2 *prMsg) +{ + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq = + &prAdapter->rWifiVar.rRmReqParams; + struct IE_MEASUREMENT_REQ *prCurrReq = NULL; + struct RM_BCN_REQ *prBeaconReq = NULL; + uint16_t u2RemainLen = 0; + uint8_t *pucSubIE = NULL; + + static struct PARAM_SSID rBcnReqSsid; + + if (prRmReq->rBcnRmParam.eState != RM_ON_GOING || !prMsg) + return FALSE; + + prCurrReq = prRmReq->prCurrMeasElem; + prBeaconReq = (struct RM_BCN_REQ *)&prCurrReq->aucRequestFields[0]; + prMsg->ucSSIDType = SCAN_REQ_SSID_WILDCARD; + switch (prBeaconReq->ucMeasurementMode) { + case RM_BCN_REQ_PASSIVE_MODE: + prMsg->eScanType = SCAN_TYPE_PASSIVE_SCAN; + break; + case RM_BCN_REQ_ACTIVE_MODE: + prMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; + break; + default: + DBGLOG(RLM, WARN, + "BCN REQ: Unexpect measure mode %d, use active mode as default\n", + prBeaconReq->ucMeasurementMode); + prMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; + break; + } + + WLAN_GET_FIELD_16(&prBeaconReq->u2Duration, &prMsg->u2ChannelDwellTime); + + COPY_MAC_ADDR(prMsg->aucBSSID, prBeaconReq->aucBssid); + + prMsg->u2ProbeDelay = 0; + prMsg->u2TimeoutValue = 0; + prMsg->ucSSIDNum = 0; + prMsg->u2IELen = 0; + /* if mandatory bit is set, we should do */ + if (prCurrReq->ucRequestMode & RM_REQ_MODE_DURATION_MANDATORY_BIT) + prMsg->u2ChannelMinDwellTime = prMsg->u2ChannelDwellTime; + else + prMsg->u2ChannelMinDwellTime = + (prMsg->u2ChannelDwellTime * 2) / 3; + if (prBeaconReq->ucChannel == 0) + prMsg->eScanChannel = SCAN_CHANNEL_FULL; + else if (prBeaconReq->ucChannel == 255) { /* latest Ap Channel Report */ + struct BSS_DESC *prBssDesc = + prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc; + uint8_t *pucChnl = NULL; + uint8_t ucChnlNum = 0; + uint8_t ucIndex = 0; + struct RF_CHANNEL_INFO *prChnlInfo = prMsg->arChnlInfoList; + + prMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; + prMsg->ucChannelListNum = 0; + if (prBssDesc) { + uint8_t *pucIE = NULL; + uint16_t u2IELength = 0; + uint16_t u2Offset = 0; + + pucIE = prBssDesc->aucIEBuf; + u2IELength = prBssDesc->u2IELength; + IE_FOR_EACH(pucIE, u2IELength, u2Offset) + { + if (IE_ID(pucIE) != ELEM_ID_AP_CHANNEL_REPORT) + continue; + pucChnl = ((struct IE_AP_CHNL_REPORT *)pucIE) + ->aucChnlList; + ucChnlNum = pucIE[1] - 1; + DBGLOG(RLM, INFO, + "BCN REQ: Channel number in latest AP channel report %d\n", + ucChnlNum); + while (ucIndex < ucChnlNum && + prMsg->ucChannelListNum < + MAXIMUM_OPERATION_CHANNEL_LIST) { + if (pucChnl[ucIndex] <= 14) + prChnlInfo + [prMsg->ucChannelListNum] + .eBand = + BAND_2G4; + else + prChnlInfo + [prMsg->ucChannelListNum] + .eBand = + BAND_5G; + prChnlInfo[prMsg->ucChannelListNum] + .ucChannelNum = + pucChnl[ucIndex]; + prMsg->ucChannelListNum++; + ucIndex++; + } + } + } + } else { + prMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; + prMsg->ucChannelListNum = 1; + prMsg->arChnlInfoList[0].ucChannelNum = prBeaconReq->ucChannel; + if (prBeaconReq->ucChannel <= 14) + prMsg->arChnlInfoList[0].eBand = BAND_2G4; + else + prMsg->arChnlInfoList[0].eBand = BAND_5G; + } + u2RemainLen = prCurrReq->ucLength - 3 - + OFFSET_OF(struct RM_BCN_REQ, aucSubElements); + pucSubIE = &prBeaconReq->aucSubElements[0]; + while (u2RemainLen > 0) { + if (IE_SIZE(pucSubIE) > u2RemainLen) + break; + switch (pucSubIE[0]) { + case 0: /* SSID */ + /* length of sub-element ssid is 0 or first byte is 0, + ** means wildcard ssid matching + */ + if (!IE_LEN(pucSubIE) || !pucSubIE[2]) + break; + prMsg->ucSSIDNum = 1; + prMsg->prSsid = &rBcnReqSsid; + COPY_SSID(&rBcnReqSsid.aucSsid[0], + rBcnReqSsid.u4SsidLen, &pucSubIE[2], + pucSubIE[1]); + prMsg->ucSSIDType = SCAN_REQ_SSID_SPECIFIED_ONLY; + break; + case 51: /* AP channel report */ + { + struct IE_AP_CHNL_REPORT *prApChnl = + (struct IE_AP_CHNL_REPORT *)pucSubIE; + uint8_t ucChannelCnt = prApChnl->ucLength - 1; + uint8_t ucIndex = 0; + + if (prBeaconReq->ucChannel == 0) + break; + prMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; + DBGLOG(RLM, INFO, + "BCN REQ: Channel number in measurement AP channel report %d\n", + ucChannelCnt); + while (ucIndex < ucChannelCnt && + prMsg->ucChannelListNum < + MAXIMUM_OPERATION_CHANNEL_LIST) { + if (prApChnl->aucChnlList[ucIndex] <= 14) + prMsg->arChnlInfoList + [prMsg->ucChannelListNum] + .eBand = BAND_2G4; + else + prMsg->arChnlInfoList + [prMsg->ucChannelListNum] + .eBand = BAND_5G; + prMsg->arChnlInfoList[prMsg->ucChannelListNum] + .ucChannelNum = + prApChnl->aucChnlList[ucIndex]; + prMsg->ucChannelListNum++; + ucIndex++; + } + break; + } + } + u2RemainLen -= IE_SIZE(pucSubIE); + pucSubIE += IE_SIZE(pucSubIE); + } + DBGLOG(RLM, INFO, + "BCN REQ: SSIDtype %d, ScanType %d, Dwell %d, MinDwell %d, ChnlType %d, ChnlNum %d\n", + prMsg->ucSSIDType, prMsg->eScanType, prMsg->u2ChannelDwellTime, + prMsg->u2ChannelMinDwellTime, prMsg->eScanChannel, + prMsg->ucChannelListNum); + return TRUE; +} + +void rlmDoBeaconMeasurement(struct ADAPTER *prAdapter, unsigned long ulParam) +{ + struct CONNECTION_SETTINGS *prConnSettings = + &(prAdapter->rWifiVar.rConnSettings); + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq = + &prAdapter->rWifiVar.rRmReqParams; + struct RM_BCN_REQ *prBcnReq = + (struct RM_BCN_REQ *)&prRmReq->prCurrMeasElem + ->aucRequestFields[0]; + + if (prBcnReq->ucMeasurementMode == RM_BCN_REQ_TABLE_MODE) { + struct LINK *prBSSDescList = + &prAdapter->rWifiVar.rScanInfo.rBSSDescList; + struct BSS_DESC *prBssDesc = NULL; + struct RM_BEACON_REPORT_PARAMS rRepParams; + uint16_t *pu2BcnInterval = + (uint16_t *)&rRepParams.aucBcnFixedField[8]; + uint16_t *pu2CapInfo = + (uint16_t *)&rRepParams.aucBcnFixedField[10]; + + kalMemZero(&rRepParams, sizeof(rRepParams)); + /* if this is a one antenna only device, the antenna id is + ** always 1. 7.3.2.40 + */ + rRepParams.ucAntennaID = 1; + rRepParams.ucRSNI = + 255; /* 255 means RSNI not available. see 7.3.2.41 */ + rRepParams.ucFrameInfo = 255; + + prRmReq->rBcnRmParam.eState = RM_ON_GOING; + prBcnReq->ucChannel = 0; + DBGLOG(RLM, INFO, + "BCN REQ: Beacon Table Mode, Beacon Table Num %u\n", + prBSSDescList->u4NumElem); + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, + struct BSS_DESC) + { + rRepParams.ucRCPI = prBssDesc->ucRCPI; + rRepParams.ucChannel = prBssDesc->ucChannelNum; + kalMemCopy(&rRepParams.aucBcnFixedField, + &prBssDesc->u8TimeStamp, 8); + *pu2BcnInterval = prBssDesc->u2BeaconInterval; + *pu2CapInfo = prBssDesc->u2CapInfo; + rlmCollectBeaconReport(prAdapter, prBssDesc->aucIEBuf, + prBssDesc->u2IELength, + prBssDesc->aucBSSID, + &rRepParams); + } + rlmStartNextMeasurement(prAdapter, FALSE); + return; + } + if (prConnSettings->fgIsScanReqIssued) { + prRmReq->rBcnRmParam.eState = RM_WAITING; + } else { + prRmReq->rBcnRmParam.eState = RM_ON_GOING; + GET_CURRENT_SYSTIME(&prRmReq->rStartTime); + aisFsmScanRequest(prAdapter, NULL, NULL, 0); + } +} + +/* + */ +static u_int8_t rlmRmFrameIsValid(struct SW_RFB *prSwRfb) +{ + uint16_t u2ElemLen = 0; + uint16_t u2Offset = + (uint16_t)OFFSET_OF(struct ACTION_RM_REQ_FRAME, aucInfoElem); + uint8_t *pucIE = (uint8_t *)prSwRfb->pvHeader; + struct IE_MEASUREMENT_REQ *prCurrMeasElem = NULL; + uint16_t u2CalcIELen = 0; + uint16_t u2IELen = 0; + + if (prSwRfb->u2PacketLen <= u2Offset) { + DBGLOG(RLM, ERROR, "RRM: Rm Packet length %d is too short\n", + prSwRfb->u2PacketLen); + return FALSE; + } + pucIE += u2Offset; + u2ElemLen = prSwRfb->u2PacketLen - u2Offset; + IE_FOR_EACH(pucIE, u2ElemLen, u2Offset) + { + u2IELen = IE_LEN(pucIE); + + /* The minimum value of the Length field is 3 (based on a + ** minimum length for the Measurement Request field + ** of 0 octets + */ + if (u2IELen <= 3) { + DBGLOG(RLM, ERROR, "RRM: Abnormal RM IE length is %d\n", + u2IELen); + return FALSE; + } + + /* Check whether the length of each measurment request element + ** is reasonable + */ + prCurrMeasElem = (struct IE_MEASUREMENT_REQ *)pucIE; + switch (prCurrMeasElem->ucMeasurementType) { + case ELEM_RM_TYPE_BEACON_REQ: + if (u2IELen < (3 + OFFSET_OF(struct RM_BCN_REQ, + aucSubElements))) { + DBGLOG(RLM, ERROR, + "RRM: Abnormal Becaon Req IE length is %d\n", + u2IELen); + return FALSE; + } + break; + case ELEM_RM_TYPE_TSM_REQ: + if (u2IELen < (3 + OFFSET_OF(struct RM_TS_MEASURE_REQ, + aucSubElements))) { + DBGLOG(RLM, ERROR, + "RRM: Abnormal TSM Req IE length is %d\n", + u2IELen); + return FALSE; + } + break; + default: + DBGLOG(RLM, ERROR, + "RRM: Not support: MeasurementType is %d, IE length is %d\n", + prCurrMeasElem->ucMeasurementType, u2IELen); + return FALSE; + } + + u2CalcIELen += IE_SIZE(pucIE); + } + if (u2CalcIELen != u2ElemLen) { + DBGLOG(RLM, ERROR, + "RRM: Calculated Total IE len is not equal to received length\n"); + return FALSE; + } + return TRUE; +} +/* + */ +void rlmProcessRadioMeasurementRequest(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb) +{ + struct ACTION_RM_REQ_FRAME *prRmReqFrame = NULL; + struct ACTION_RM_REPORT_FRAME *prReportFrame = NULL; + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReqParam = NULL; + struct RADIO_MEASUREMENT_REPORT_PARAMS *prRmRepParam = NULL; + enum RM_REQ_PRIORITY eNewPriority; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + if (prAdapter->prAisBssInfo == NULL) { + DBGLOG(RLM, INFO, "Ignored due to AIS isn't created\n"); + return; + } + prRmReqFrame = (struct ACTION_RM_REQ_FRAME *)prSwRfb->pvHeader; + prRmReqParam = &prAdapter->rWifiVar.rRmReqParams; + prRmRepParam = &prAdapter->rWifiVar.rRmRepParams; + + if (!rlmRmFrameIsValid(prSwRfb)) + return; + DBGLOG(RLM, INFO, "RRM: RM Request From %pM, DialogToken %d\n", + prRmReqFrame->aucSrcAddr, prRmReqFrame->ucDialogToken); + eNewPriority = rlmGetRmRequestPriority(prRmReqFrame->aucDestAddr); + if (prRmReqParam->ePriority > eNewPriority) { + DBGLOG(RLM, INFO, "RRM: ignore lower precedence rm request\n"); + return; + } + prRmReqParam->ePriority = eNewPriority; + /* */ + if (prRmReqParam->fgRmIsOngoing) { + DBGLOG(RLM, INFO, "RRM: Old RM is on-going, cancel it first\n"); + rlmTxRadioMeasurementReport(prAdapter); + wmmRemoveAllTsmMeasurement(prAdapter, FALSE); + rlmFreeMeasurementResources(prAdapter); + } + prRmReqParam->fgRmIsOngoing = TRUE; + /* Step1: Save Measurement Request Params */ + prRmReqParam->u2ReqIeBufLen = prRmReqParam->u2RemainReqLen = + prSwRfb->u2PacketLen - + OFFSET_OF(struct ACTION_RM_REQ_FRAME, aucInfoElem); + if (prRmReqParam->u2RemainReqLen <= sizeof(struct IE_MEASUREMENT_REQ)) { + DBGLOG(RLM, ERROR, + "RRM: empty Radio Measurement Request Frame, Elem Len %d\n", + prRmReqParam->u2RemainReqLen); + return; + } + WLAN_GET_FIELD_BE16(&prRmReqFrame->u2Repetitions, + &prRmReqParam->u2Repetitions); + prRmReqParam->pucReqIeBuf = + kalMemAlloc(prRmReqParam->u2RemainReqLen, VIR_MEM_TYPE); + if (!prRmReqParam->pucReqIeBuf) { + DBGLOG(RLM, ERROR, + "RRM: Alloc %d bytes Req IE Buffer failed, No Memory\n", + prRmReqParam->u2RemainReqLen); + return; + } + kalMemCopy(prRmReqParam->pucReqIeBuf, &prRmReqFrame->aucInfoElem[0], + prRmReqParam->u2RemainReqLen); + prRmReqParam->prCurrMeasElem = + (struct IE_MEASUREMENT_REQ *)prRmReqParam->pucReqIeBuf; + prRmReqParam->fgInitialLoop = TRUE; + + /* Step2: Prepare Report Frame and fill in Frame Header */ + prRmRepParam->pucReportFrameBuff = + kalMemAlloc(RM_REPORT_FRAME_MAX_LENGTH, VIR_MEM_TYPE); + if (!prRmRepParam->pucReportFrameBuff) { + DBGLOG(RLM, ERROR, + "RRM: Alloc Memory for Measurement Report Frame buffer failed\n"); + return; + } + kalMemZero(prRmRepParam->pucReportFrameBuff, + RM_REPORT_FRAME_MAX_LENGTH); + prReportFrame = (struct ACTION_RM_REPORT_FRAME *) + prRmRepParam->pucReportFrameBuff; + prReportFrame->u2FrameCtrl = MAC_FRAME_ACTION; + COPY_MAC_ADDR(prReportFrame->aucDestAddr, prRmReqFrame->aucSrcAddr); + COPY_MAC_ADDR(prReportFrame->aucSrcAddr, + prAdapter->prAisBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prReportFrame->aucBSSID, prRmReqFrame->aucBSSID); + prReportFrame->ucCategory = CATEGORY_RM_ACTION; + prReportFrame->ucAction = RM_ACTION_RM_REPORT; + prReportFrame->ucDialogToken = prRmReqFrame->ucDialogToken; + prRmRepParam->u2ReportFrameLen = + OFFSET_OF(struct ACTION_RM_REPORT_FRAME, aucInfoElem); + rlmCalibrateRepetions(prRmReqParam); + /* Step3: Start to process Measurement Request Element */ + rlmStartNextMeasurement(prAdapter, TRUE); +} + +void rlmTxRadioMeasurementReport(struct ADAPTER *prAdapter) +{ + struct MSDU_INFO *prMsduInfo = NULL; + struct RADIO_MEASUREMENT_REPORT_PARAMS *prRmRepParam = + &prAdapter->rWifiVar.rRmRepParams; + struct STA_RECORD *prStaRec = NULL; + + if (prRmRepParam->u2ReportFrameLen <= + OFFSET_OF(struct ACTION_RM_REPORT_FRAME, aucInfoElem)) { + DBGLOG(RLM, INFO, "RRM: report frame length is too short, %d\n", + prRmRepParam->u2ReportFrameLen); + return; + } + if (!prAdapter->prAisBssInfo) { + DBGLOG(RLM, INFO, "RRM: ais bss info is NULL\n"); + return; + } + prStaRec = prAdapter->prAisBssInfo->prStaRecOfAP; + if (!prStaRec) { + DBGLOG(RLM, INFO, "RRM: StaRec of Ais is NULL\n"); + return; + } + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc( + prAdapter, prRmRepParam->u2ReportFrameLen); + if (!prMsduInfo) { + DBGLOG(RLM, INFO, + "RRM: Alloc MSDU Info failed, frame length %d\n", + prRmRepParam->u2ReportFrameLen); + return; + } + DBGLOG(RLM, INFO, "RRM: frame length %d\n", + prRmRepParam->u2ReportFrameLen); + kalMemCopy(prMsduInfo->prPacket, prRmRepParam->pucReportFrameBuff, + prRmRepParam->u2ReportFrameLen); + + /* 2 Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, prMsduInfo, prStaRec->ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_MGMT_HEADER_LEN, + prRmRepParam->u2ReportFrameLen, NULL, MSDU_RATE_MODE_AUTO); + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + /* reset u2ReportFrameLen after tx frame */ + prRmRepParam->u2ReportFrameLen = + OFFSET_OF(struct ACTION_RM_REPORT_FRAME, aucInfoElem); +} + +void rlmGenerateRRMEnabledCapIE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct IE_RRM_ENABLED_CAP *prRrmEnabledCap = NULL; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prRrmEnabledCap = (struct IE_RRM_ENABLED_CAP *) + (((uint8_t *) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + prRrmEnabledCap->ucId = ELEM_ID_RRM_ENABLED_CAP; + prRrmEnabledCap->ucLength = ELEM_MAX_LEN_RRM_CAP; + kalMemZero(&prRrmEnabledCap->aucCap[0], ELEM_MAX_LEN_RRM_CAP); + rlmFillRrmCapa(&prRrmEnabledCap->aucCap[0]); + prMsduInfo->u2FrameLength += IE_SIZE(prRrmEnabledCap); +} + +void rlmFillRrmCapa(uint8_t *pucCapa) +{ + uint8_t ucIndex = 0; + uint8_t aucEnabledBits[] = {RRM_CAP_INFO_LINK_MEASURE_BIT, + RRM_CAP_INFO_NEIGHBOR_REPORT_BIT, + RRM_CAP_INFO_REPEATED_MEASUREMENT, + RRM_CAP_INFO_BEACON_PASSIVE_MEASURE_BIT, + RRM_CAP_INFO_BEACON_ACTIVE_MEASURE_BIT, + RRM_CAP_INFO_BEACON_TABLE_BIT, + RRM_CAP_INFO_RRM_BIT}; + + for (; ucIndex < sizeof(aucEnabledBits); ucIndex++) + SET_EXT_CAP(pucCapa, ELEM_MAX_LEN_RRM_CAP, + aucEnabledBits[ucIndex]); +} + +void rlmGeneratePowerCapIE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + struct IE_POWER_CAP *prPwrCap = NULL; + uint8_t ucChannel = 0; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + ucChannel = + prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc->ucChannelNum; + prPwrCap = (struct IE_POWER_CAP *)(((uint8_t *)prMsduInfo->prPacket) + + prMsduInfo->u2FrameLength); + prPwrCap->ucId = ELEM_ID_PWR_CAP; + prPwrCap->ucLength = 2; + prPwrCap->cMaxTxPowerCap = RLM_MAX_TX_PWR; + prPwrCap->cMinTxPowerCap = RLM_MIN_TX_PWR; + prMsduInfo->u2FrameLength += IE_SIZE(prPwrCap); +} + +void rlmSetMaxTxPwrLimit(IN struct ADAPTER *prAdapter, int8_t cLimit, + uint8_t ucEnable) +{ + struct CMD_SET_AP_CONSTRAINT_PWR_LIMIT rTxPwrLimit; + + kalMemZero(&rTxPwrLimit, sizeof(rTxPwrLimit)); + rTxPwrLimit.ucCmdVer = 0x1; + rTxPwrLimit.ucPwrSetEnable = ucEnable; + if (ucEnable) { + if (cLimit > RLM_MAX_TX_PWR) { + DBGLOG(RLM, INFO, + "LM: Target MaxPwr %d Higher than Capability, reset to capability\n", + cLimit); + cLimit = RLM_MAX_TX_PWR; + } + if (cLimit < RLM_MIN_TX_PWR) { + DBGLOG(RLM, INFO, + "LM: Target MinPwr %d Lower than Capability, reset to capability\n", + cLimit); + cLimit = RLM_MIN_TX_PWR; + } + DBGLOG(RLM, INFO, + "LM: Set Max Tx Power Limit %d, Min Limit %d\n", cLimit, + RLM_MIN_TX_PWR); + rTxPwrLimit.cMaxTxPwr = + cLimit * 2; /* unit of cMaxTxPwr is 0.5 dBm */ + rTxPwrLimit.cMinTxPwr = RLM_MIN_TX_PWR * 2; + } else + DBGLOG(RLM, TRACE, "LM: Disable Tx Power Limit\n"); + wlanSendSetQueryCmd(prAdapter, CMD_ID_SET_AP_CONSTRAINT_PWR_LIMIT, TRUE, + FALSE, FALSE, nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_SET_AP_CONSTRAINT_PWR_LIMIT), + (uint8_t *)&rTxPwrLimit, NULL, 0); +} + +enum RM_REQ_PRIORITY rlmGetRmRequestPriority(uint8_t *pucDestAddr) +{ + if (IS_UCAST_MAC_ADDR(pucDestAddr)) + return RM_PRI_UNICAST; + else if (EQUAL_MAC_ADDR(pucDestAddr, "\xff\xff\xff\xff\xff\xff")) + return RM_PRI_BROADCAST; + return RM_PRI_MULTICAST; +} + +static void rlmCalibrateRepetions(struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq) +{ + uint16_t u2IeSize = 0; + uint16_t u2RemainReqLen = prRmReq->u2ReqIeBufLen; + struct IE_MEASUREMENT_REQ *prCurrReq = + (struct IE_MEASUREMENT_REQ *)prRmReq->prCurrMeasElem; + + if (prRmReq->u2Repetitions == 0) + return; + + u2IeSize = IE_SIZE(prCurrReq); + while (u2RemainReqLen >= u2IeSize) { + /* 1. If all measurement request has enable bit, no need to + ** repeat + ** see 11.10.6 Measurement request elements with the enable bit + ** set to 1 shall be processed once + ** regardless of the value in the number of repetitions in the + ** measurement request. + ** 2. Due to we don't support parallel measurement, if all + ** request has parallel bit, no need to repeat + ** measurement, to avoid frequent composing incapable response + ** IE and exhauste CPU resource + ** and then cause watch dog timeout. + ** 3. if all measurements are not supported, no need to repeat. + ** currently we only support Beacon request + ** on this chip. + */ + if (!(prCurrReq->ucRequestMode & + (RM_REQ_MODE_ENABLE_BIT | RM_REQ_MODE_PARALLEL_BIT))) { + if (prCurrReq->ucMeasurementType == + ELEM_RM_TYPE_BEACON_REQ) + return; + } + u2RemainReqLen -= u2IeSize; + prCurrReq = (struct IE_MEASUREMENT_REQ *)((uint8_t *)prCurrReq + + u2IeSize); + u2IeSize = IE_SIZE(prCurrReq); + } + DBGLOG(RLM, INFO, + "RRM: All Measurement has set enable bit, or all are parallel or not supported, don't repeat\n"); + prRmReq->u2Repetitions = 0; +} + +void rlmRunEventProcessNextRm(struct ADAPTER *prAdapter, + struct MSG_HDR *prMsgHdr) +{ + cnmMemFree(prAdapter, prMsgHdr); + rlmStartNextMeasurement(prAdapter, FALSE); +} + +void rlmScheduleNextRm(struct ADAPTER *prAdapter) +{ + struct MSG_HDR *prMsg = NULL; + + prMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(*prMsg)); + if (!prMsg) { + DBGLOG(RLM, ERROR, "[RRM] No memory\n"); + return; + } + prMsg->eMsgId = MID_RLM_RM_SCHEDULE; + mboxSendMsg(prAdapter, MBOX_ID_0, prMsg, MSG_SEND_METHOD_BUF); +} + +static void rlmCollectBeaconReport(IN struct ADAPTER *prAdapter, + uint8_t *pucIEBuf, uint16_t u2IELength, + uint8_t *pucBssid, + struct RM_BEACON_REPORT_PARAMS *prRepParams) +{ +#define BEACON_FIXED_FIELD_LENGTH 12 + struct RADIO_MEASUREMENT_REQ_PARAMS *prRmReq = + &prAdapter->rWifiVar.rRmReqParams; + struct RADIO_MEASUREMENT_REPORT_PARAMS *prRmRep = + &prAdapter->rWifiVar.rRmRepParams; + struct RM_BCN_REQ *prBcnReq = + (struct RM_BCN_REQ *)&prRmReq->prCurrMeasElem + ->aucRequestFields[0]; + struct IE_MEASUREMENT_REPORT *prMeasReport = NULL; + /* Variables to process Beacon IE */ + uint8_t *pucIE; + uint16_t u2Offset = 0; + + /* Variables to collect report */ + uint8_t ucRSSI = 0; + uint8_t *pucSubIE = NULL; + uint8_t ucCondition = 0; + uint8_t ucRefValue = 0; + uint8_t ucReportDetail = 0; + uint8_t *pucReportIeIds = NULL; + uint8_t ucReportIeIdsLen = 0; + struct RM_BCN_REPORT *prBcnReport = NULL; + uint8_t ucBcnReportLen = 0; + struct RM_MEASURE_REPORT_ENTRY *prReportEntry = NULL; + uint16_t u2RemainLen = 0; + u_int8_t fgValidChannel = FALSE; + uint16_t u2IeSize = 0; + + if (!EQUAL_MAC_ADDR(prBcnReq->aucBssid, "\xff\xff\xff\xff\xff\xff") && + !EQUAL_MAC_ADDR(prBcnReq->aucBssid, pucBssid)) { + DBGLOG(RLM, INFO, + "BCN REQ: bssid mismatch, req %pM, actual %pM\n", + prBcnReq->aucBssid, pucBssid); + return; + } + + pucIE = pucIEBuf; + /* Step1: parsing Beacon Request sub element field to get Report + ** controlling information if match the channel that is in fixed + ** field, no need to check AP channel report + */ + if (prBcnReq->ucChannel == prRepParams->ucChannel) + fgValidChannel = TRUE; + + u2RemainLen = prRmReq->prCurrMeasElem->ucLength - 3 - + OFFSET_OF(struct RM_BCN_REQ, aucSubElements); + pucSubIE = &prBcnReq->aucSubElements[0]; + while (u2RemainLen > 0) { + u2IeSize = IE_SIZE(pucSubIE); + if (u2IeSize > u2RemainLen) + break; + switch (pucSubIE[0]) { + case 0: + /* checking if SSID is matched + ** length of sub-element ssid is 0 or first byte is 0, + ** means wildcard ssid matching + */ + if (!IE_LEN(pucSubIE) || !pucSubIE[2]) + break; + IE_FOR_EACH(pucIE, u2IELength, u2Offset) + { + if (IE_ID(pucIE) == ELEM_ID_SSID) + break; + } + if (EQUAL_SSID(&pucIE[2], pucIE[1], &pucSubIE[2], + pucSubIE[1])) + break; + { + uint8_t aucReqSsid[33] = {0}; + uint8_t aucBcnSsid[33] = {0}; + uint8_t ucReqSsidLen = + pucSubIE[1] <= 32 ? pucSubIE[1] : 32; + uint8_t ucBcnSsidLen = + pucIE[1] <= 32 ? pucIE[1] : 32; + + kalMemCopy(aucReqSsid, &pucSubIE[2], + ucReqSsidLen); + kalMemCopy(aucBcnSsid, &pucIE[2], ucBcnSsidLen); + DBGLOG(RLM, TRACE, + "BCN REQ: SSID mismatch, req(len %d, %s), bcn(id %d, len %d, %s)\n", + ucReqSsidLen, aucReqSsid, pucIE[0], + ucBcnSsidLen, aucBcnSsid); + } + return; /* don't match SSID, don't report it */ + case 1: /* Beacon Reporting Information */ + ucCondition = pucSubIE[3]; + ucRefValue = pucSubIE[4]; + break; + case 2: /* Reporting Detail Element */ + ucReportDetail = pucSubIE[2]; + break; + case 10: /* Request Elements */ + { + struct IE_REQUEST *prIe = (struct IE_REQUEST *)pucSubIE; + + pucReportIeIds = prIe->aucReqIds; + ucReportIeIdsLen = prIe->ucLength; + break; + } + case 51: /* AP CHANNEL REPORT Element */ + { + /* channel info is starting with the fourth byte */ + uint8_t ucNumChannels = 3; + + if (fgValidChannel) + break; + /* try to match with AP channel report */ + while (ucNumChannels < u2IeSize) { + if (prRepParams->ucChannel == + pucSubIE[ucNumChannels]) { + fgValidChannel = TRUE; + break; + } + ucNumChannels++; + } + } + } + u2RemainLen -= u2IeSize; + pucSubIE += u2IeSize; + } + if (!fgValidChannel && prBcnReq->ucChannel > 0 && + prBcnReq->ucChannel < 255) { + DBGLOG(RLM, INFO, "BCN REQ: channel %d, valid %d\n", + prBcnReq->ucChannel, fgValidChannel); + return; + } + + /* Step2: check report condition */ + ucRSSI = RCPI_TO_dBm(prRepParams->ucRCPI); + switch (ucCondition) { + case 1: + if (ucRSSI <= ucRefValue/2) + return; + break; + case 2: + if (ucRSSI >= ucRefValue/2) + return; + break; + case 3: + break; + } + /* Step3: Compose Beacon Report in a temp buffer search in saved + ** reported link, check if we have saved a report for this AP + */ + LINK_FOR_EACH_ENTRY(prReportEntry, &prRmRep->rReportLink, rLinkEntry, + struct RM_MEASURE_REPORT_ENTRY) + { + struct IE_MEASUREMENT_REPORT *prReportElem = + (struct IE_MEASUREMENT_REPORT *) + prReportEntry->aucMeasReport; + + prBcnReport = + (struct RM_BCN_REPORT *)prReportElem->aucReportFields; + if (EQUAL_MAC_ADDR(prBcnReport->aucBSSID, pucBssid)) + break; + prBcnReport = NULL; + } + /* not found a entry in collected report link */ + if (!prBcnReport) { + LINK_REMOVE_HEAD(&prRmRep->rFreeReportLink, prReportEntry, + struct RM_MEASURE_REPORT_ENTRY *); + /* not found a entry in free report link */ + if (!prReportEntry) { + prReportEntry = kalMemAlloc(sizeof(*prReportEntry), + VIR_MEM_TYPE); + if (!prReportEntry)/* no memory to allocate in OS */ { + DBGLOG(RLM, ERROR, + "BCN REQ: Alloc Measurement Report Entry failed, No Memory\n"); + return; + } + } + DBGLOG(RLM, INFO, + "BCN REQ: allocate entry for Bss %pM, total entry %u\n", + pucBssid, prRmRep->rReportLink.u4NumElem); + LINK_INSERT_TAIL(&prRmRep->rReportLink, + &prReportEntry->rLinkEntry); + } + kalMemZero(prReportEntry->aucMeasReport, + sizeof(prReportEntry->aucMeasReport)); + prMeasReport = + (struct IE_MEASUREMENT_REPORT *)prReportEntry->aucMeasReport; + prBcnReport = (struct RM_BCN_REPORT *)prMeasReport->aucReportFields; + /* Fixed length field */ + prBcnReport->ucRegulatoryClass = prBcnReq->ucRegulatoryClass; + prBcnReport->ucChannel = prRepParams->ucChannel; + prBcnReport->u2Duration = prBcnReq->u2Duration; + /* ucReportInfo: Bit 0 is the type of frame, 0 means beacon/probe + ** response, bit 1~7 means phy type + */ + prBcnReport->ucReportInfo = prRepParams->ucFrameInfo; + prBcnReport->ucRCPI = ucRSSI; + prBcnReport->ucRSNI = + prRepParams->ucRSNI; /* ToDo: no RSNI is supported now */ + COPY_MAC_ADDR(prBcnReport->aucBSSID, pucBssid); + prBcnReport->ucAntennaID = + prRepParams->ucAntennaID; /* only one Antenna now */ + { + OS_SYSTIME rCurrent; + uint64_t u8Tsf = *(uint64_t *)&rTsf.au4Tsf[0]; + + GET_CURRENT_SYSTIME(&rCurrent); + if (prRmReq->rStartTime >= rTsf.rTime) + u8Tsf += prRmReq->rStartTime - rTsf.rTime; + else + u8Tsf += rTsf.rTime - prRmReq->rStartTime; + kalMemCopy(prBcnReport->aucStartTime, &u8Tsf, + 8); /* ToDo: start time is not supported now */ + u8Tsf = *(uint64_t *)&rTsf.au4Tsf[0] + rCurrent - rTsf.rTime; + kalMemCopy(prBcnReport->aucParentTSF, &u8Tsf, + 4); /* low part of TSF */ + } + ucBcnReportLen = 0; + /* Optional Subelement Field all fixed length fields and IEs + ** in Request Sub Elements should be reported + */ + if (ucReportDetail == 1 && ucReportIeIdsLen > 0) { + pucSubIE = &prBcnReport->aucOptElem[2]; + kalMemCopy(pucSubIE, prRepParams->aucBcnFixedField, + BEACON_FIXED_FIELD_LENGTH); + pucSubIE += BEACON_FIXED_FIELD_LENGTH; + ucBcnReportLen += BEACON_FIXED_FIELD_LENGTH; + pucIE = pucIEBuf; + IE_FOR_EACH(pucIE, u2IELength, u2Offset) + { + uint16_t i = 0; + uint8_t ucIncludedIESize = 0; + + for (; i < ucReportIeIdsLen; i++) + if (pucIE[0] == pucReportIeIds[i]) { + ucIncludedIESize = IE_SIZE(pucIE); + break; + } + /* the length of sub-element should less than 225, + ** and the included IE should be a complete one + */ + if (ucBcnReportLen + ucIncludedIESize > + RM_BCN_REPORT_SUB_ELEM_MAX_LENGTH) + break; + if (ucIncludedIESize == 0) + continue; + ucBcnReportLen += ucIncludedIESize; + kalMemCopy(pucSubIE, pucIE, ucIncludedIESize); + pucSubIE += ucIncludedIESize; + } + prBcnReport->aucOptElem[0] = + 1; /* sub-element id for reported frame body */ + prBcnReport->aucOptElem[1] = + ucBcnReportLen; /* length of the sub-element */ + ucBcnReportLen += 2; + } else if (ucReportDetail == + 2) { /* all fixed length fields and IEs should be reported */ + ucBcnReportLen += BEACON_FIXED_FIELD_LENGTH; + pucIE = pucIEBuf; + /* the length of sub-element should less than 225, and the + ** included IE should be a complete one + */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) + { + if (ucBcnReportLen + IE_SIZE(pucIE) > + RM_BCN_REPORT_SUB_ELEM_MAX_LENGTH) + break; + ucBcnReportLen += IE_SIZE(pucIE); + } + prBcnReport->aucOptElem[0] = + 1; /* sub-element id for reported frame body */ + prBcnReport->aucOptElem[1] = + ucBcnReportLen; /* length of the sub-element */ + pucIE = &prBcnReport->aucOptElem[2]; + kalMemCopy(pucIE, prRepParams->aucBcnFixedField, + BEACON_FIXED_FIELD_LENGTH); + pucIE += BEACON_FIXED_FIELD_LENGTH; + kalMemCopy(pucIE, pucIEBuf, + ucBcnReportLen - BEACON_FIXED_FIELD_LENGTH); + ucBcnReportLen += 2; + } + ucBcnReportLen += OFFSET_OF(struct RM_BCN_REPORT, aucOptElem); + /* Step4: fill in basic content of Measurement report IE */ + prMeasReport->ucId = ELEM_ID_MEASUREMENT_REPORT; + prMeasReport->ucToken = prRmReq->prCurrMeasElem->ucToken; + prMeasReport->ucMeasurementType = ELEM_RM_TYPE_BEACON_REPORT; + prMeasReport->ucReportMode = 0; + prMeasReport->ucLength = 3 + ucBcnReportLen; + DBGLOG(RLM, INFO, + "BCN REQ: Bss %pM, ReportDeail %d, IncludeIE Num %d, chnl %d\n", + pucBssid, ucReportDetail, ucReportIeIdsLen, + prRepParams->ucChannel); +} + +static uint8_t rlmGetChannel(struct HW_MAC_RX_DESC *prRxStatus, uint8_t *pucIE, + uint16_t u2IELen) +{ + uint8_t ucDsChannel = 0; + uint8_t ucHtChannel = 0; + uint8_t ucHwChannel = HAL_RX_STATUS_GET_CHNL_NUM(prRxStatus); + uint16_t u2Offset = 0; + enum ENUM_BAND eBand = HAL_RX_STATUS_GET_RF_BAND(prRxStatus); + + IE_FOR_EACH(pucIE, u2IELen, u2Offset) + { + switch (IE_ID(pucIE)) { + case ELEM_ID_DS_PARAM_SET: + if (IE_LEN(pucIE) == ELEM_MAX_LEN_DS_PARAMETER_SET) + ucDsChannel = DS_PARAM_IE(pucIE)->ucCurrChnl; + break; + case ELEM_ID_HT_OP: + if (IE_LEN(pucIE) == (sizeof(struct IE_HT_OP) - 2)) + ucHtChannel = ((struct IE_HT_OP *)pucIE) + ->ucPrimaryChannel; + break; + } + } + DBGLOG(RLM, INFO, "BCN REQ: band %d, hw channel %d, ds %d, ht %d\n", + eBand, ucHwChannel, ucDsChannel, ucHtChannel); + if (eBand == BAND_2G4) { + if (ucDsChannel >= 1 && ucDsChannel <= 14) + return ucDsChannel; + return (ucHtChannel >= 1 && ucHtChannel <= 14) ? ucHtChannel + : ucHwChannel; + } + return (ucHtChannel >= 1 && ucHtChannel < 200) ? ucHtChannel + : ucHwChannel; +} + +void rlmProcessBeaconAndProbeResp(struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct RM_BEACON_REPORT_PARAMS rRepParams; + struct WLAN_BEACON_FRAME *prWlanBeacon = + (struct WLAN_BEACON_FRAME *)prSwRfb->pvHeader; + uint16_t u2IELen = prSwRfb->u2PacketLen - + OFFSET_OF(struct WLAN_BEACON_FRAME, aucInfoElem); + + kalMemZero(&rRepParams, sizeof(rRepParams)); + if (u2IELen > CFG_IE_BUFFER_SIZE) + u2IELen = CFG_IE_BUFFER_SIZE; + + /* if this is a one antenna only device, the antenna id is always 1. + ** 7.3.2.40 + */ + rRepParams.ucAntennaID = 1; + rRepParams.ucChannel = rlmGetChannel( + prSwRfb->prRxStatus, prWlanBeacon->aucInfoElem, u2IELen); + ASSERT(prSwRfb->prRxStatusGroup3); + rRepParams.ucRCPI = nicRxGetRcpiValueFromRxv(RCPI_MODE_MAX, prSwRfb); + rRepParams.ucRSNI = + 255; /* 255 means RSNI not available. see 7.3.2.41 */ + rRepParams.ucFrameInfo = 0; + DBGLOG_MEM8(SW4, INFO, (uint8_t *)prWlanBeacon, + OFFSET_OF(struct WLAN_BEACON_FRAME, aucInfoElem)); + WLAN_GET_FIELD_64(&prWlanBeacon->au4Timestamp[0], + &rRepParams.aucBcnFixedField); + WLAN_GET_FIELD_16(&prWlanBeacon->u2BeaconInterval, + &rRepParams.aucBcnFixedField[8]); + WLAN_GET_FIELD_16(&prWlanBeacon->u2CapInfo, + &rRepParams.aucBcnFixedField[10]); + rlmCollectBeaconReport(prAdapter, prWlanBeacon->aucInfoElem, u2IELen, + prWlanBeacon->aucBSSID, &rRepParams); +} + +void rlmUpdateBssTimeTsf(struct ADAPTER *prAdapter, struct BSS_DESC *prBssDesc) +{ + ASSERT(prAdapter); + ASSERT(prBssDesc); + + rTsf.rTime = prBssDesc->rUpdateTime; + kalMemCopy(&rTsf.au4Tsf[0], &prBssDesc->u8TimeStamp, 8); +} + +#if CFG_SUPPORT_BFER +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +void rlmBfStaRecPfmuUpdate(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec) +{ + uint8_t ucBFerMaxNr, ucBFeeMaxNr, ucMode; + struct BSS_INFO *prBssInfo; + struct CMD_STAREC_BF *prStaRecBF; + struct CMD_STAREC_UPDATE *prStaRecUpdateInfo; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + uint32_t u4SetBufferLen = sizeof(struct CMD_STAREC_BF); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + ASSERT(prBssInfo); + + if (RLM_NET_IS_11AC(prBssInfo) && + IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaVhtBfer)) + ucMode = MODE_VHT; + else if (RLM_NET_IS_11N(prBssInfo) && + IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaHtBfer)) + ucMode = MODE_HT; + else + ucMode = MODE_LEGACY; + + prStaRecBF = + (struct CMD_STAREC_BF *) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, u4SetBufferLen); + + if (!prStaRecBF) { + DBGLOG(RLM, ERROR, "STA Rec memory alloc fail\n"); + return; + } + + prStaRecUpdateInfo = + (struct CMD_STAREC_UPDATE *) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, (CMD_STAREC_UPDATE_HDR_SIZE + u4SetBufferLen)); + + if (!prStaRecUpdateInfo) { + cnmMemFree(prAdapter, prStaRecBF); + DBGLOG(RLM, ERROR, "STA Rec Update Info memory alloc fail\n"); + return; + } + + prStaRec->rTxBfPfmuStaInfo.u2PfmuId = 0xFFFF; + + switch (ucMode) { + case MODE_VHT: + prStaRec->rTxBfPfmuStaInfo.fgSU_MU = FALSE; + prStaRec->rTxBfPfmuStaInfo.fgETxBfCap = + rlmClientSupportsVhtETxBF(prStaRec); + + if (prStaRec->rTxBfPfmuStaInfo.fgETxBfCap) { + /* OFDM, NDPA/Report Poll/CTS2Self tx mode */ + prStaRec->rTxBfPfmuStaInfo.ucSoundingPhy = + TX_RATE_MODE_OFDM; + + /* 9: OFDM 24M */ + prStaRec->rTxBfPfmuStaInfo.ucNdpaRate = PHY_RATE_24M; + + /* VHT mode, NDP tx mode */ + prStaRec->rTxBfPfmuStaInfo.ucTxMode = TX_RATE_MODE_VHT; + + /* 0: MCS0 */ + prStaRec->rTxBfPfmuStaInfo.ucNdpRate = PHY_RATE_MCS0; + + switch (prBssInfo->ucVhtChannelWidth) { + case VHT_OP_CHANNEL_WIDTH_80: + prStaRec->rTxBfPfmuStaInfo.ucCBW = MAX_BW_80MHZ; + break; + + case VHT_OP_CHANNEL_WIDTH_20_40: + default: + prStaRec->rTxBfPfmuStaInfo.ucCBW = MAX_BW_20MHZ; + if (prBssInfo->eBssSCO != CHNL_EXT_SCN) + prStaRec->rTxBfPfmuStaInfo.ucCBW = + MAX_BW_40MHZ; + break; + } + + ucBFerMaxNr = 1; /* 7668 is 2x2 */ + ucBFeeMaxNr = rlmClientSupportsVhtBfeeStsCap(prStaRec); + prStaRec->rTxBfPfmuStaInfo.ucNr = + (ucBFerMaxNr < ucBFeeMaxNr) ? + ucBFerMaxNr : ucBFeeMaxNr; + prStaRec->rTxBfPfmuStaInfo.ucNc = + ((prStaRec->u2VhtRxMcsMap & + VHT_CAP_INFO_MCS_2SS_MASK) != + BITS(2, 3)) ? 1 : 0; + } + break; + + case MODE_HT: + prStaRec->rTxBfPfmuStaInfo.fgSU_MU = FALSE; + prStaRec->rTxBfPfmuStaInfo.fgETxBfCap = + rlmClientSupportsHtETxBF(prStaRec); + + if (prStaRec->rTxBfPfmuStaInfo.fgETxBfCap) { + /* HT mode, NDPA/NDP tx mode */ + prStaRec->rTxBfPfmuStaInfo.ucTxMode = + TX_RATE_MODE_HTMIX; + + /* 0: HT MCS0 */ + prStaRec->rTxBfPfmuStaInfo.ucNdpaRate = PHY_RATE_MCS0; + + prStaRec->rTxBfPfmuStaInfo.ucCBW = MAX_BW_20MHZ; + if (prBssInfo->eBssSCO != CHNL_EXT_SCN) + prStaRec->rTxBfPfmuStaInfo.ucCBW = MAX_BW_40MHZ; + + ucBFerMaxNr = 1; /* 7668 is 2x2 */ + ucBFeeMaxNr = + (prStaRec->u4TxBeamformingCap & + TXBF_COMPRESSED_TX_ANTENNANUM_SUPPORTED) >> + TXBF_COMPRESSED_TX_ANTENNANUM_SUPPORTED_OFFSET; + prStaRec->rTxBfPfmuStaInfo.ucNr = + (ucBFerMaxNr < ucBFeeMaxNr) ? + ucBFerMaxNr : ucBFeeMaxNr; + prStaRec->rTxBfPfmuStaInfo.ucNc = + (prStaRec->aucRxMcsBitmask[1] > 0) ? 1 : 0; + prStaRec->rTxBfPfmuStaInfo.ucNdpRate = + prStaRec->rTxBfPfmuStaInfo.ucNr * 8; + } + break; + default: + break; + } + + DBGLOG(RLM, INFO, "ucMode=%d\n", ucMode); + DBGLOG(RLM, INFO, "rlmClientSupportsVhtETxBF(prStaRec)=%d\n", + rlmClientSupportsVhtETxBF(prStaRec)); + DBGLOG(RLM, INFO, "rlmClientSupportsVhtBfeeStsCap(prStaRec)=%d\n", + rlmClientSupportsVhtBfeeStsCap(prStaRec)); + DBGLOG(RLM, INFO, "prStaRec->u2VhtRxMcsMap=%x\n", + prStaRec->u2VhtRxMcsMap); + + DBGLOG(RLM, INFO, + "====================== BF StaRec Info =====================\n"); + DBGLOG(RLM, INFO, "u2PfmuId =%d\n", + prStaRec->rTxBfPfmuStaInfo.u2PfmuId); + DBGLOG(RLM, INFO, "fgSU_MU =%d\n", + prStaRec->rTxBfPfmuStaInfo.fgSU_MU); + DBGLOG(RLM, INFO, "fgETxBfCap =%d\n", + prStaRec->rTxBfPfmuStaInfo.fgETxBfCap); + DBGLOG(RLM, INFO, "ucSoundingPhy =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucSoundingPhy); + DBGLOG(RLM, INFO, "ucNdpaRate =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucNdpaRate); + DBGLOG(RLM, INFO, "ucNdpRate =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucNdpRate); + DBGLOG(RLM, INFO, "ucReptPollRate =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucReptPollRate); + DBGLOG(RLM, INFO, "ucTxMode =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucTxMode); + DBGLOG(RLM, INFO, "ucNc =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucNc); + DBGLOG(RLM, INFO, "ucNr =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucNr); + DBGLOG(RLM, INFO, "ucCBW =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucCBW); + DBGLOG(RLM, INFO, "ucTotMemRequire=%d\n", + prStaRec->rTxBfPfmuStaInfo.ucTotMemRequire); + DBGLOG(RLM, INFO, "ucMemRequire20M=%d\n", + prStaRec->rTxBfPfmuStaInfo.ucMemRequire20M); + DBGLOG(RLM, INFO, "ucMemRow0 =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucMemRow0); + DBGLOG(RLM, INFO, "ucMemCol0 =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucMemCol0); + DBGLOG(RLM, INFO, "ucMemRow1 =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucMemRow1); + DBGLOG(RLM, INFO, "ucMemCol1 =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucMemCol1); + DBGLOG(RLM, INFO, "ucMemRow2 =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucMemRow2); + DBGLOG(RLM, INFO, "ucMemCol2 =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucMemCol2); + DBGLOG(RLM, INFO, "ucMemRow3 =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucMemRow3); + DBGLOG(RLM, INFO, "ucMemCol3 =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucMemCol3); + DBGLOG(RLM, INFO, + "===========================================================\n"); + + + + prStaRecBF->u2Tag = STA_REC_BF; + prStaRecBF->u2Length = u4SetBufferLen; + kalMemCopy(&prStaRecBF->rTxBfPfmuInfo, + &prStaRec->rTxBfPfmuStaInfo, sizeof(struct TXBF_PFMU_STA_INFO)); + + + prStaRecUpdateInfo->ucBssIndex = prStaRec->ucBssIndex; + prStaRecUpdateInfo->ucWlanIdx = prStaRec->ucWlanIndex; + prStaRecUpdateInfo->u2TotalElementNum = 1; + kalMemCopy(prStaRecUpdateInfo->aucBuffer, prStaRecBF, u4SetBufferLen); + + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_STAREC_UPDATE, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + (CMD_STAREC_UPDATE_HDR_SIZE + u4SetBufferLen), + (uint8_t *) prStaRecUpdateInfo, NULL, 0); + + if (rWlanStatus == WLAN_STATUS_FAILURE) + DBGLOG(RLM, ERROR, "Send BF sounding cmd fail\n"); + + cnmMemFree(prAdapter, prStaRecBF); + cnmMemFree(prAdapter, prStaRecUpdateInfo); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +void rlmETxBfTriggerPeriodicSounding(struct ADAPTER *prAdapter) +{ + uint32_t u4SetBufferLen = sizeof(union PARAM_CUSTOM_TXBF_ACTION_STRUCT); + union PARAM_CUSTOM_TXBF_ACTION_STRUCT rTxBfActionInfo; + union CMD_TXBF_ACTION rCmdTxBfActionInfo; + uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; + + DBGLOG(RLM, INFO, "rlmETxBfTriggerPeriodicSounding\n"); + + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding. + rExtCmdExtBfSndPeriodicTriggerCtrl.ucCmdCategoryID = + BF_SOUNDING_ON; + + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding. + rExtCmdExtBfSndPeriodicTriggerCtrl.ucSuMuSndMode = + AUTO_SU_PERIODIC_SOUNDING; + + kalMemCopy(&rCmdTxBfActionInfo, &rTxBfActionInfo, + sizeof(union CMD_TXBF_ACTION)); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_BF_ACTION, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(union CMD_TXBF_ACTION), + (uint8_t *) &rCmdTxBfActionInfo, + &rTxBfActionInfo, u4SetBufferLen); + + if (rWlanStatus == WLAN_STATUS_FAILURE) + DBGLOG(RLM, ERROR, "Send BF sounding cmd fail\n"); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +bool +rlmClientSupportsVhtETxBF(struct STA_RECORD *prStaRec) +{ + uint8_t ucVhtCapSuBfeeCap; + + ucVhtCapSuBfeeCap = + (prStaRec->u4VhtCapInfo & VHT_CAP_INFO_SU_BEAMFORMEE_CAPABLE) + >> VHT_CAP_INFO_SU_BEAMFORMEE_CAPABLE_OFFSET; + + return (ucVhtCapSuBfeeCap) ? TRUE : FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +uint8_t +rlmClientSupportsVhtBfeeStsCap(struct STA_RECORD *prStaRec) +{ + uint8_t ucVhtCapBfeeStsCap; + + ucVhtCapBfeeStsCap = + (prStaRec->u4VhtCapInfo & +VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF_BEAMFORMER_ANTENNAS_SUP) >> +VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF_BEAMFORMER_ANTENNAS_SUP_OFF; + + return ucVhtCapBfeeStsCap; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +bool +rlmClientSupportsHtETxBF(struct STA_RECORD *prStaRec) +{ + uint32_t u4RxNDPCap, u4ComBfFbkCap; + + u4RxNDPCap = (prStaRec->u4TxBeamformingCap & TXBF_RX_NDP_CAPABLE) + >> TXBF_RX_NDP_CAPABLE_OFFSET; + /* Support compress feedback */ + u4ComBfFbkCap = (prStaRec->u4TxBeamformingCap & + TXBF_EXPLICIT_COMPRESSED_FEEDBACK_IMMEDIATE_CAPABLE) + >> TXBF_EXPLICIT_COMPRESSED_FEEDBACK_CAPABLE_OFFSET; + + return (u4RxNDPCap == 1) && (u4ComBfFbkCap > 0); +} + +#endif + +#if CFG_SUPPORT_WAC +uint32_t rlmCalculateWAC_IELen(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIdx, IN struct STA_RECORD *prStaRec) +{ + uint32_t u4IELen = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && + (ucBssIdx < BSS_DEFAULT_NUM)); + + if (!prAdapter->rWifiVar.fgEnableWACIE) { + DBGLOG(RLM, ERROR, "WAC IE disabled, return len=0.\n"); + return 0; + } + + if (!prAdapter->fgIsP2PRegistered) + break; + + /*WAC IE exist in Beacon or Pro Resp Frame */ + if (!p2pFuncIsAPMode((struct P2P_CONNECTION_SETTINGS *) + prAdapter->rWifiVar.prP2PConnSettings)) + break; + + u4IELen = prAdapter->rWifiVar.u2WACIELen; + } while (FALSE); + + DBGLOG(RLM, ERROR, "WAC IE len=%d.\n"); + return u4IELen; +} + +void rlmGenerateWAC_IE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + uint8_t *pucIEBuf = (uint8_t *) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + if (!prAdapter->rWifiVar.fgEnableWACIE) { + DBGLOG(RLM, ERROR, "WAC IE disabled, return null.\n"); + return; + } + + DBGLOG(RLM, ERROR, "Generate WAC IE: len=%d\n", + prAdapter->rWifiVar.u2WACIELen); + pucIEBuf = (uint8_t *) ((unsigned long) prMsduInfo->prPacket + + (unsigned long) prMsduInfo->u2FrameLength); + kalMemCopy(pucIEBuf, prAdapter->rWifiVar.aucWACIECache, + prAdapter->rWifiVar.u2WACIELen); + prMsduInfo->u2FrameLength += prAdapter->rWifiVar.u2WACIELen; + } while (FALSE); +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/rlm_domain.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/rlm_domain.c new file mode 100644 index 0000000000000..0d046b3124126 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/rlm_domain.c @@ -0,0 +1,3917 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rlm_domain.c#2 +*/ + +/*! \file "rlm_domain.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" +#include "rlm_txpwr_init.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/* The following country or domain shall be set from host driver. + * And host driver should pass specified DOMAIN_INFO_ENTRY to MT6620 as + * the channel list of being a STA to do scanning/searching AP or being an + * AP to choose an adequate channel if auto-channel is set. + */ + +/* Define mapping tables between country code and its channel set + */ +static const uint16_t g_u2CountryGroup0[] = { + COUNTRY_CODE_AO, COUNTRY_CODE_BZ, COUNTRY_CODE_BJ, COUNTRY_CODE_BT, + COUNTRY_CODE_BO, COUNTRY_CODE_BI, COUNTRY_CODE_CM, COUNTRY_CODE_CF, + COUNTRY_CODE_TD, COUNTRY_CODE_KM, COUNTRY_CODE_CD, COUNTRY_CODE_CG, + COUNTRY_CODE_CI, COUNTRY_CODE_DJ, COUNTRY_CODE_GQ, COUNTRY_CODE_ER, + COUNTRY_CODE_FJ, COUNTRY_CODE_GA, COUNTRY_CODE_GM, COUNTRY_CODE_GN, + COUNTRY_CODE_GW, COUNTRY_CODE_RKS, COUNTRY_CODE_KG, COUNTRY_CODE_LY, + COUNTRY_CODE_MG, COUNTRY_CODE_ML, COUNTRY_CODE_NR, COUNTRY_CODE_NC, + COUNTRY_CODE_ST, COUNTRY_CODE_SC, COUNTRY_CODE_SL, COUNTRY_CODE_SB, + COUNTRY_CODE_SO, COUNTRY_CODE_SR, COUNTRY_CODE_SZ, COUNTRY_CODE_TJ, + COUNTRY_CODE_TG, COUNTRY_CODE_TO, COUNTRY_CODE_TM, COUNTRY_CODE_TV, + COUNTRY_CODE_VU, COUNTRY_CODE_YE +}; + +static const uint16_t g_u2CountryGroup1[] = { + COUNTRY_CODE_AS, COUNTRY_CODE_AI, COUNTRY_CODE_BM, COUNTRY_CODE_KY, + COUNTRY_CODE_GU, COUNTRY_CODE_FM, COUNTRY_CODE_PR, COUNTRY_CODE_US, + COUNTRY_CODE_VI +}; + +static const uint16_t g_u2CountryGroup2[] = { + COUNTRY_CODE_AR, COUNTRY_CODE_AU, COUNTRY_CODE_AZ, COUNTRY_CODE_BW, + COUNTRY_CODE_CX, COUNTRY_CODE_CO, COUNTRY_CODE_CR, COUNTRY_CODE_EC, + COUNTRY_CODE_GD, COUNTRY_CODE_GT, COUNTRY_CODE_HK, COUNTRY_CODE_KH, + COUNTRY_CODE_KI, COUNTRY_CODE_KR, COUNTRY_CODE_LB, COUNTRY_CODE_LR, + COUNTRY_CODE_MN, COUNTRY_CODE_AN, COUNTRY_CODE_NZ, COUNTRY_CODE_NI, + COUNTRY_CODE_PW, COUNTRY_CODE_PY, COUNTRY_CODE_PE, COUNTRY_CODE_PH, + COUNTRY_CODE_WS, COUNTRY_CODE_SG, COUNTRY_CODE_LK, COUNTRY_CODE_TH, + COUNTRY_CODE_TT, COUNTRY_CODE_UY, COUNTRY_CODE_VN +}; + +static const uint16_t g_u2CountryGroup3[] = { + COUNTRY_CODE_AW, COUNTRY_CODE_LA, COUNTRY_CODE_SA, COUNTRY_CODE_AE, + COUNTRY_CODE_UG +}; + +static const uint16_t g_u2CountryGroup4[] = { COUNTRY_CODE_MM }; + +static const uint16_t g_u2CountryGroup5[] = { + COUNTRY_CODE_AL, COUNTRY_CODE_DZ, COUNTRY_CODE_AD, COUNTRY_CODE_AT, + COUNTRY_CODE_BY, COUNTRY_CODE_BE, COUNTRY_CODE_BA, COUNTRY_CODE_VG, + COUNTRY_CODE_BG, COUNTRY_CODE_CV, COUNTRY_CODE_HR, COUNTRY_CODE_CY, + COUNTRY_CODE_CZ, COUNTRY_CODE_DK, COUNTRY_CODE_EE, COUNTRY_CODE_ET, + COUNTRY_CODE_FI, COUNTRY_CODE_FR, COUNTRY_CODE_GF, COUNTRY_CODE_PF, + COUNTRY_CODE_TF, COUNTRY_CODE_GE, COUNTRY_CODE_DE, COUNTRY_CODE_GH, + COUNTRY_CODE_GR, COUNTRY_CODE_GP, COUNTRY_CODE_HU, COUNTRY_CODE_IS, + COUNTRY_CODE_IQ, COUNTRY_CODE_IE, COUNTRY_CODE_IT, COUNTRY_CODE_KE, + COUNTRY_CODE_LV, COUNTRY_CODE_LS, COUNTRY_CODE_LI, COUNTRY_CODE_LT, + COUNTRY_CODE_LU, COUNTRY_CODE_MK, COUNTRY_CODE_MT, COUNTRY_CODE_MQ, + COUNTRY_CODE_MR, COUNTRY_CODE_MU, COUNTRY_CODE_YT, COUNTRY_CODE_MD, + COUNTRY_CODE_MC, COUNTRY_CODE_ME, COUNTRY_CODE_MS, COUNTRY_CODE_NL, + COUNTRY_CODE_NO, COUNTRY_CODE_OM, COUNTRY_CODE_PL, COUNTRY_CODE_PT, + COUNTRY_CODE_RE, COUNTRY_CODE_RO, COUNTRY_CODE_MF, COUNTRY_CODE_SM, + COUNTRY_CODE_SN, COUNTRY_CODE_RS, COUNTRY_CODE_SK, COUNTRY_CODE_SI, + COUNTRY_CODE_ZA, COUNTRY_CODE_ES, COUNTRY_CODE_SE, COUNTRY_CODE_CH, + COUNTRY_CODE_TR, COUNTRY_CODE_TC, COUNTRY_CODE_GB, COUNTRY_CODE_VA, + COUNTRY_CODE_EU +}; + +static const uint16_t g_u2CountryGroup6[] = { COUNTRY_CODE_JP }; + +static const uint16_t g_u2CountryGroup7[] = { + COUNTRY_CODE_AM, COUNTRY_CODE_IL, COUNTRY_CODE_KW, COUNTRY_CODE_MA, + COUNTRY_CODE_NE, COUNTRY_CODE_TN, +}; + +static const uint16_t g_u2CountryGroup8[] = { COUNTRY_CODE_NP }; + +static const uint16_t g_u2CountryGroup9[] = { COUNTRY_CODE_AF }; + +static const uint16_t g_u2CountryGroup10[] = { + COUNTRY_CODE_AG, COUNTRY_CODE_BS, COUNTRY_CODE_BH, COUNTRY_CODE_BB, + COUNTRY_CODE_BN, COUNTRY_CODE_CL, COUNTRY_CODE_CN, COUNTRY_CODE_EG, + COUNTRY_CODE_SV, COUNTRY_CODE_IN, COUNTRY_CODE_MY, COUNTRY_CODE_MV, + COUNTRY_CODE_PA, COUNTRY_CODE_VE, COUNTRY_CODE_ZM +}; + +static const uint16_t g_u2CountryGroup11[] = { COUNTRY_CODE_JO, COUNTRY_CODE_PG }; + +static const uint16_t g_u2CountryGroup12[] = { + COUNTRY_CODE_BF, COUNTRY_CODE_GY, COUNTRY_CODE_HT, COUNTRY_CODE_HN, + COUNTRY_CODE_JM, COUNTRY_CODE_MO, COUNTRY_CODE_MW, COUNTRY_CODE_PK, + COUNTRY_CODE_QA, COUNTRY_CODE_RW, COUNTRY_CODE_KN, COUNTRY_CODE_TZ +}; + +static const uint16_t g_u2CountryGroup13[] = { COUNTRY_CODE_ID }; + +static const uint16_t g_u2CountryGroup14[] = { COUNTRY_CODE_NG }; + +static const uint16_t g_u2CountryGroup15[] = { + COUNTRY_CODE_BD, COUNTRY_CODE_BR, COUNTRY_CODE_DM, COUNTRY_CODE_DO, + COUNTRY_CODE_FK, COUNTRY_CODE_KZ, COUNTRY_CODE_MX, COUNTRY_CODE_MZ, + COUNTRY_CODE_NA, COUNTRY_CODE_RU, COUNTRY_CODE_LC, COUNTRY_CODE_VC, + COUNTRY_CODE_UA, COUNTRY_CODE_UZ, COUNTRY_CODE_ZW +}; + +static const uint16_t g_u2CountryGroup16[] = { COUNTRY_CODE_MP }; + +static const uint16_t g_u2CountryGroup17[] = { COUNTRY_CODE_TW }; + +static const uint16_t g_u2CountryGroup18[] = { COUNTRY_CODE_CA }; + +static const uint16_t g_u2CountryGroup19[] = { + COUNTRY_CODE_CK, COUNTRY_CODE_CU, COUNTRY_CODE_TL, COUNTRY_CODE_FO, + COUNTRY_CODE_GI, COUNTRY_CODE_GG, COUNTRY_CODE_IR, COUNTRY_CODE_IM, + COUNTRY_CODE_JE, COUNTRY_CODE_KP, COUNTRY_CODE_MH, COUNTRY_CODE_NU, + COUNTRY_CODE_NF, COUNTRY_CODE_PS, COUNTRY_CODE_PN, COUNTRY_CODE_PM, + COUNTRY_CODE_SS, COUNTRY_CODE_SD, COUNTRY_CODE_SY +}; + +static const uint16_t g_u2CountryGroup20[] = { + COUNTRY_CODE_DF + /* When country code is not found and no matched NVRAM setting, + * the default group will be used. + */ +}; + +#if (CFG_SUPPORT_SINGLE_SKU == 1) +struct mtk_regd_control g_mtk_regd_control = { + .en = FALSE, + .state = REGD_STATE_UNDEFINED +}; + +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) +const struct ieee80211_regdomain default_regdom_ww = { + .n_reg_rules = 6, + .alpha2 = "99", + .reg_rules = { + /* channels 1..13 */ + REG_RULE_LIGHT(2412-10, 2472+10, 40, 0), + /* channels 14 */ + REG_RULE_LIGHT(2484-10, 2484+10, 20, 0), + /* channel 36..48 */ + REG_RULE_LIGHT(5180-10, 5240+10, 80, 0), + /* channel 52..64 */ + REG_RULE_LIGHT(5260-10, 5320+10, 80, KAL_RRF_DFS), + /* channel 100..144*/ + REG_RULE_LIGHT(5500-10, 5720+10, 80, KAL_RRF_DFS), + /* channel 149..165 */ + REG_RULE_LIGHT(5745-10, 5825+10, 80, 0), + } +}; +#endif + +struct TX_PWR_LIMIT_SECTION { + uint8_t ucSectionNum; + const char *arSectionNames[TX_PWR_LIMIT_SECTION_NUM]; +} gTx_Pwr_Limit_Section[] = { + {5, + {"legacy", "ht20", "ht40", "vht20", "offset"} + }, + {9, + {"cck", "ofdm", "ht20", "ht40", "vht20", "vht40", + "vht80", "vht160", "txbf_backoff"} + }, +}; + + +const u8 gTx_Pwr_Limit_Element_Num[][TX_PWR_LIMIT_SECTION_NUM] = { + {7, 6, 7, 7, 5}, + {POWER_LIMIT_SKU_CCK_NUM, POWER_LIMIT_SKU_OFDM_NUM, + POWER_LIMIT_SKU_HT20_NUM, POWER_LIMIT_SKU_HT40_NUM, + POWER_LIMIT_SKU_VHT20_NUM, POWER_LIMIT_SKU_VHT40_NUM, + POWER_LIMIT_SKU_VHT80_NUM, POWER_LIMIT_SKU_VHT160_NUM, + POWER_LIMIT_TXBF_BACKOFF_PARAM_NUM}, +}; + +const char *gTx_Pwr_Limit_Element[] + [TX_PWR_LIMIT_SECTION_NUM] + [TX_PWR_LIMIT_ELEMENT_NUM] = { + { + {"cck1_2", "cck_5_11", "ofdm6_9", "ofdm12_18", "ofdm24_36", + "ofdm48", "ofdm54"}, + {"mcs0_8", "mcs1_2_9_10", "mcs3_4_11_12", "mcs5_13", "mcs6_14", + "mcs7_15"}, + {"mcs0_8", "mcs1_2_9_10", "mcs3_4_11_12", "mcs5_13", "mcs6_14", + "mcs7_15", "mcs32"}, + {"mcs0", "mcs1_2", "mcs3_4", "mcs5_6", "mcs7", "mcs8", "mcs9"}, + {"lg40", "lg80", "vht40", "vht80", "vht160nc"}, + }, + { + {"c1", "c2", "c5", "c11"}, + {"o6", "o9", "o12", "o18", + "o24", "o36", "o48", "o54"}, + {"m0", "m1", "m2", "m3", "m4", "m5", "m6", "m7"}, + {"m0", "m1", "m2", "m3", "m4", "m5", "m6", "m7", "m32"}, + {"m0", "m1", "m2", "m3", "m4", "m5", "m6", "m7", "m8", "m9"}, + {"m0", "m1", "m2", "m3", "m4", "m5", "m6", "m7", "m8", "m9"}, + {"m0", "m1", "m2", "m3", "m4", "m5", "m6", "m7", "m8", "m9"}, + {"m0", "m1", "m2", "m3", "m4", "m5", "m6", "m7", "m8", "m9"}, + {"2to1"}, + }, +}; + +static const int8_t gTx_Pwr_Limit_2g_Ch[] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; +static const int8_t gTx_Pwr_Limit_5g_Ch[] = { + 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 100, 102, + 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 132, + 134, 136, 138, 140, 142, 144, 149, 151, 153, 155, 157, 159, 161, 165}; + +#define TX_PWR_LIMIT_2G_CH_NUM (ARRAY_SIZE(gTx_Pwr_Limit_2g_Ch)) +#define TX_PWR_LIMIT_5G_CH_NUM (ARRAY_SIZE(gTx_Pwr_Limit_5g_Ch)) + +u_int8_t g_bTxBfBackoffExists = FALSE; + +#endif + +struct DOMAIN_INFO_ENTRY arSupportedRegDomains[] = { + { + (uint16_t *) g_u2CountryGroup0, sizeof(g_u2CountryGroup0) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_LOW_NA */ + {118, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_MID_NA */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup1, sizeof(g_u2CountryGroup1) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 11, FALSE} + , /* CH_SET_2G4_1_11 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup2, sizeof(g_u2CountryGroup2) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup3, sizeof(g_u2CountryGroup3) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE} + , /* CH_SET_UNII_UPPER_149_161 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup4, sizeof(g_u2CountryGroup4) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup5, sizeof(g_u2CountryGroup5) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup6, sizeof(g_u2CountryGroup6) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + {82, BAND_2G4, CHNL_SPAN_5, 14, 1, FALSE} + , /* CH_SET_2G4_14_14 */ + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + } + } + , + { + (uint16_t *) g_u2CountryGroup7, sizeof(g_u2CountryGroup7) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup8, sizeof(g_u2CountryGroup8) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE} + , /* CH_SET_UNII_UPPER_149_161 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup9, sizeof(g_u2CountryGroup9) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_MID_NA */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup10, sizeof(g_u2CountryGroup10) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup11, sizeof(g_u2CountryGroup11) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_MID_NA */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup12, sizeof(g_u2CountryGroup12) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_LOW_NA */ + {118, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_MID_NA */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup13, sizeof(g_u2CountryGroup13) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_LOW_NA */ + {118, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_MID_NA */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE} + , /* CH_SET_UNII_UPPER_149_161 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup14, sizeof(g_u2CountryGroup14) / 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, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup15, sizeof(g_u2CountryGroup15) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, TRUE} + , /* CH_SET_UNII_LOW_36_48 */ /* Indoor */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ /* Indoor */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup16, sizeof(g_u2CountryGroup16) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 11, FALSE} + , /* CH_SET_2G4_1_11 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup17, sizeof(g_u2CountryGroup17) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 11, FALSE} + , /* CH_SET_2G4_1_11 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ /* Indoor */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (uint16_t *) g_u2CountryGroup18, sizeof(g_u2CountryGroup18) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 11, FALSE} + , /* CH_SET_2G4_1_11 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 5, TRUE} + , /* CH_SET_UNII_WW_100_116 */ + {121, BAND_5G, CHNL_SPAN_20, 132, 4, TRUE} + , /* CH_SET_UNII_WW_132_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + /* CH_SET_UNII_UPPER_149_165 */ + } + } + , + { + (uint16_t *) g_u2CountryGroup19, sizeof(g_u2CountryGroup19) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + /* Note: Default group if no matched country code */ + (uint16_t *) g_u2CountryGroup20, sizeof(g_u2CountryGroup20) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } +}; + +static const uint16_t g_u2CountryGroup0_Passive[] = { + COUNTRY_CODE_TW +}; + +struct DOMAIN_INFO_ENTRY arSupportedRegDomains_Passive[] = { + { + (uint16_t *) g_u2CountryGroup0_Passive, sizeof(g_u2CountryGroup0_Passive) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 0, FALSE} + , /* CH_SET_2G4_1_14_NA */ + {82, BAND_2G4, CHNL_SPAN_5, 14, 0, FALSE} + , + + {115, BAND_5G, CHNL_SPAN_20, 36, 0, FALSE} + , /* CH_SET_UNII_LOW_NA */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + } + } + , + { + /* Default passive scan channel table: ch52~64, ch100~144 */ + NULL, 0, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 0, FALSE} + , /* CH_SET_2G4_1_14_NA */ + {82, BAND_2G4, CHNL_SPAN_5, 14, 0, FALSE} + , + + {115, BAND_5G, CHNL_SPAN_20, 36, 0, FALSE} + , /* CH_SET_UNII_LOW_NA */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + } + } +}; + +struct SUBBAND_CHANNEL g_rRlmSubBand[] = { + + {BAND_2G4_LOWER_BOUND, BAND_2G4_UPPER_BOUND, 1, 0} + , /* 2.4G */ + {UNII1_LOWER_BOUND, UNII1_UPPER_BOUND, 2, 0} + , /* ch36,38,40,..,48 */ + {UNII2A_LOWER_BOUND, UNII2A_UPPER_BOUND, 2, 0} + , /* ch52,54,56,..,64 */ + {UNII2C_LOWER_BOUND, UNII2C_UPPER_BOUND, 2, 0} + , /* ch100,102,104,...,144 */ + {UNII3_LOWER_BOUND, UNII3_UPPER_BOUND, 2, 0} + /* ch149,151,153,....,165 */ +}; + +/******************************************************************************* +* 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 +*/ +/*----------------------------------------------------------------------------*/ +struct DOMAIN_INFO_ENTRY *rlmDomainGetDomainInfo(struct ADAPTER *prAdapter) +{ +#define REG_DOMAIN_DEF_IDX 20 /* Default regulatory domain */ +#define REG_DOMAIN_GROUP_NUM \ + (sizeof(arSupportedRegDomains) / sizeof(struct DOMAIN_INFO_ENTRY)) + + struct DOMAIN_INFO_ENTRY *prDomainInfo; + struct REG_INFO *prRegInfo; + uint16_t u2TargetCountryCode; + uint16_t i, j; + + ASSERT(prAdapter); + + if (prAdapter->prDomainInfo) + return prAdapter->prDomainInfo; + + prRegInfo = &prAdapter->prGlueInfo->rRegInfo; + + DBGLOG(RLM, TRACE, "eRegChannelListMap=%d, u2CountryCode=0x%04x\n", + prRegInfo->eRegChannelListMap, + prAdapter->rWifiVar.rConnSettings.u2CountryCode); + + /* + * Domain info can be specified by given idx of arSupportedRegDomains table, + * customized, or searched by country code, + * only one is set among these three methods in NVRAM. + */ + if (prRegInfo->eRegChannelListMap == REG_CH_MAP_TBL_IDX && + prRegInfo->ucRegChannelListIndex < REG_DOMAIN_GROUP_NUM) { + /* by given table idx */ + DBGLOG(RLM, TRACE, "ucRegChannelListIndex=%d\n", prRegInfo->ucRegChannelListIndex); + prDomainInfo = &arSupportedRegDomains[prRegInfo->ucRegChannelListIndex]; + } else if (prRegInfo->eRegChannelListMap == REG_CH_MAP_CUSTOMIZED) { + /* by customized */ + prDomainInfo = &prRegInfo->rDomainInfo; + } else { + /* by country code */ + u2TargetCountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode; + + for (i = 0; i < REG_DOMAIN_GROUP_NUM; i++) { + prDomainInfo = &arSupportedRegDomains[i]; + + if ((prDomainInfo->u4CountryNum && prDomainInfo->pu2CountryGroup) || + prDomainInfo->u4CountryNum == 0) { + for (j = 0; j < prDomainInfo->u4CountryNum; j++) { + if (prDomainInfo->pu2CountryGroup[j] == u2TargetCountryCode) + break; + } + if (j < prDomainInfo->u4CountryNum) + break; /* Found */ + } + } + + /* If no matched country code, use the default regulatory domain */ + if (i >= REG_DOMAIN_GROUP_NUM) { + DBGLOG(RLM, INFO, "No matched country code, use the default regulatory domain\n"); + prDomainInfo = &arSupportedRegDomains[REG_DOMAIN_DEF_IDX]; + } + } + + prAdapter->prDomainInfo = prDomainInfo; + return prDomainInfo; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Retrieve the supported channel list of specified band +* +* \param[in/out] eSpecificBand: BAND_2G4, BAND_5G or BAND_NULL (both 2.4G and 5G) +* fgNoDfs: whether to exculde DFS channels +* ucMaxChannelNum: max array size +* pucNumOfChannel: pointer to returned channel number +* paucChannelList: pointer to returned channel list array +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +void +rlmDomainGetChnlList_V2(struct ADAPTER *prAdapter, + enum ENUM_BAND eSpecificBand, u_int8_t fgNoDfs, + uint8_t ucMaxChannelNum, uint8_t *pucNumOfChannel, struct RF_CHANNEL_INFO *paucChannelList) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + enum ENUM_BAND band; + uint8_t max_count, i, ucNum; + struct channel *prCh; + + if (eSpecificBand == BAND_2G4) { + i = 0; + max_count = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + } else if (eSpecificBand == BAND_5G) { + i = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + max_count = rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ) + + rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + } else { + i = 0; + max_count = rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ) + + rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + } + + ucNum = 0; + for (; i < max_count; i++) { + prCh = rlmDomainGetActiveChannels() + i; + if (fgNoDfs && (prCh->flags & IEEE80211_CHAN_RADAR)) + continue; /*not match*/ + + if (i < rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ)) + band = BAND_2G4; + else + band = BAND_5G; + + paucChannelList[ucNum].eBand = band; + paucChannelList[ucNum].ucChannelNum = prCh->chNum; + + ucNum++; + if (ucMaxChannelNum == ucNum) + break; + } + + *pucNumOfChannel = ucNum; +#else + *pucNumOfChannel = 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Retrieve the supported channel list of specified band +* +* \param[in/out] eSpecificBand: BAND_2G4, BAND_5G or BAND_NULL (both 2.4G and 5G) +* fgNoDfs: whether to exculde DFS channels +* ucMaxChannelNum: max array size +* pucNumOfChannel: pointer to returned channel number +* paucChannelList: pointer to returned channel list array +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +void +rlmDomainGetChnlList(struct ADAPTER *prAdapter, + enum ENUM_BAND eSpecificBand, u_int8_t fgNoDfs, + uint8_t ucMaxChannelNum, uint8_t *pucNumOfChannel, struct RF_CHANNEL_INFO *paucChannelList) +{ + uint8_t i, j, ucNum; + struct DOMAIN_SUBBAND_INFO *prSubband; + struct DOMAIN_INFO_ENTRY *prDomainInfo; + + ASSERT(prAdapter); + ASSERT(paucChannelList); + ASSERT(pucNumOfChannel); + + if (regd_is_single_sku_en()) + return rlmDomainGetChnlList_V2(prAdapter, eSpecificBand, + fgNoDfs, ucMaxChannelNum, + pucNumOfChannel, paucChannelList); + + /* 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; + + /*repoert to upper layer only non-DFS channel for ap mode usage*/ + if (fgNoDfs == TRUE && prSubband->fgDfs == TRUE) + continue; + + if (eSpecificBand == BAND_NULL || prSubband->ucBand == eSpecificBand) { + for (j = 0; j < prSubband->ucNumChannels; j++) { + if (ucNum >= ucMaxChannelNum) + break; + paucChannelList[ucNum].eBand = prSubband->ucBand; + paucChannelList[ucNum].ucChannelNum = + prSubband->ucFirstChannelNum + j * prSubband->ucChannelSpan; + ucNum++; + } + } + } + + *pucNumOfChannel = ucNum; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Retrieve DFS channels from 5G band + * + * \param[in/out] ucMaxChannelNum: max array size + * pucNumOfChannel: pointer to returned channel number + * paucChannelList: pointer to returned channel list array + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmDomainGetDfsChnls(struct ADAPTER *prAdapter, + uint8_t ucMaxChannelNum, uint8_t *pucNumOfChannel, + struct RF_CHANNEL_INFO *paucChannelList) +{ + uint8_t i, j, ucNum; + struct DOMAIN_SUBBAND_INFO *prSubband; + struct DOMAIN_INFO_ENTRY *prDomainInfo; + + ASSERT(prAdapter); + ASSERT(paucChannelList); + ASSERT(pucNumOfChannel); + + prDomainInfo = rlmDomainGetDomainInfo(prAdapter); + ASSERT(prDomainInfo); + + ucNum = 0; + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubband = &prDomainInfo->rSubBand[i]; + + if (prSubband->ucBand == BAND_5G) { + if (!prAdapter->fgEnable5GBand) + continue; + + if (prSubband->fgDfs == TRUE) { + 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(struct ADAPTER *prAdapter) +{ + if (!regd_is_single_sku_en()) + rlmDomainSendPassiveScanInfoCmd(prAdapter); + rlmDomainSendDomainInfoCmd(prAdapter); +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + rlmDomainSendPwrLimitCmd(prAdapter); +#endif +} +static bool isEUCountry(struct ADAPTER *prAdapter, uint32_t u4CountryCode) +{ + uint16_t i; + uint16_t u2TargetCountryCode = 0; + + ASSERT(prAdapter); + u2TargetCountryCode = + ((u4CountryCode & 0xff) << 8) | ((u4CountryCode & 0xff00) >> 8); + DBGLOG(RLM, INFO, " Target country code=0x%4x\n", u2TargetCountryCode); + for (i = 0; i < (sizeof(g_u2CountryGroup5) / sizeof(uint16_t)); i++) { + if (g_u2CountryGroup5[i] == u2TargetCountryCode) + return TRUE; + } + return FALSE; +} + +static void rlmSetEd_EU(struct ADAPTER *prAdapter, uint32_t u4CountryCode) +{ + struct WIFI_VAR *prWifiVar = &prAdapter->rWifiVar; + + if (isEUCountry(prAdapter, u4CountryCode)) { + if ((prWifiVar->ucEd2GEU != 0) && (prWifiVar->ucEd5GEU != 0)) { + wlanSetEd(prAdapter, prWifiVar->ucEd2GEU, + prWifiVar->ucEd5GEU, 1); + DBGLOG(RLM, INFO, "Ed 2G for EU=%d, Ed 5G for EU=%d\n", + prWifiVar->ucEd2GEU, prWifiVar->ucEd5GEU); + } + } else { + if ((prWifiVar->ucEd2GNonEU != 0) && + (prWifiVar->ucEd5GNonEU != 0)) { + wlanSetEd(prAdapter, prWifiVar->ucEd2GNonEU, + prWifiVar->ucEd5GNonEU, 1); + DBGLOG(RLM, INFO, + "Ed 2G for non EU=%d, Ed 5G for non EU=%d\n", + prWifiVar->ucEd2GNonEU, prWifiVar->ucEd5GNonEU); + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void rlmDomainSendDomainInfoCmd_V2(struct ADAPTER *prAdapter) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + u8 max_channel_count = 0; + u32 buff_max_size, buff_valid_size; + struct CMD_SET_DOMAIN_INFO_V2 *prCmd; + struct acctive_channel_list *prChs; + struct wiphy *pWiphy; + + + pWiphy = priv_to_wiphy(prAdapter->prGlueInfo); + if (pWiphy->bands[KAL_BAND_2GHZ] != NULL) + max_channel_count += pWiphy->bands[KAL_BAND_2GHZ]->n_channels; + if (pWiphy->bands[KAL_BAND_5GHZ] != NULL) + max_channel_count += pWiphy->bands[KAL_BAND_5GHZ]->n_channels; + + if (max_channel_count == 0) { + DBGLOG(RLM, ERROR, "%s, invalid channel count.\n", __func__); + ASSERT(0); + } + + + buff_max_size = sizeof(struct CMD_SET_DOMAIN_INFO_V2) + + max_channel_count * sizeof(struct channel); + + prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, buff_max_size); + prChs = &(prCmd->active_chs); + + + + /* + * Fill in the active channels + */ + rlmExtractChannelInfo(max_channel_count, prChs); + + prCmd->u4CountryCode = rlmDomainGetCountryCode(); + prCmd->uc2G4Bandwidth = prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode; + prCmd->uc5GBandwidth = prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode; + prCmd->aucReserved[0] = 0; + prCmd->aucReserved[1] = 0; + + buff_valid_size = sizeof(struct CMD_SET_DOMAIN_INFO_V2) + + (prChs->n_channels_2g + prChs->n_channels_5g) * + sizeof(struct channel); + + DBGLOG(RLM, INFO, "rlmDomainSendDomainInfoCmd_V2(), buff_valid_size = 0x%x\n", buff_valid_size); + + + /* Set domain info to chip */ + wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_DOMAIN_INFO, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + buff_valid_size, + (uint8_t *) prCmd, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + rlmSetEd_EU(prAdapter, prCmd->u4CountryCode); + cnmMemFree(prAdapter, prCmd); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void rlmDomainSendDomainInfoCmd(struct ADAPTER *prAdapter) +{ + struct DOMAIN_INFO_ENTRY *prDomainInfo; + struct CMD_SET_DOMAIN_INFO *prCmd; + struct DOMAIN_SUBBAND_INFO *prSubBand; + uint8_t i; + + if (regd_is_single_sku_en()) + return rlmDomainSendDomainInfoCmd_V2(prAdapter); + + + prDomainInfo = rlmDomainGetDomainInfo(prAdapter); + ASSERT(prDomainInfo); + + prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(struct CMD_SET_DOMAIN_INFO)); + if (!prCmd) { + DBGLOG(RLM, ERROR, "Alloc cmd buffer failed\n"); + return; + } + kalMemZero(prCmd, sizeof(struct CMD_SET_DOMAIN_INFO)); + + prCmd->u2CountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode; + prCmd->u2IsSetPassiveScan = 0; + prCmd->uc2G4Bandwidth = prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode; + prCmd->uc5GBandwidth = prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode; + prCmd->aucReserved[0] = 0; + prCmd->aucReserved[1] = 0; + + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubBand = &prDomainInfo->rSubBand[i]; + + prCmd->rSubBand[i].ucRegClass = prSubBand->ucRegClass; + prCmd->rSubBand[i].ucBand = prSubBand->ucBand; + + if (prSubBand->ucBand != BAND_NULL && prSubBand->ucBand < BAND_NUM) { + prCmd->rSubBand[i].ucChannelSpan = prSubBand->ucChannelSpan; + prCmd->rSubBand[i].ucFirstChannelNum = prSubBand->ucFirstChannelNum; + prCmd->rSubBand[i].ucNumChannels = prSubBand->ucNumChannels; + } + } + + /* Set domain info to chip */ + wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_DOMAIN_INFO, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct CMD_SET_DOMAIN_INFO), /* u4SetQueryInfoLen */ + (uint8_t *) prCmd, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + rlmSetEd_EU(prAdapter, prCmd->u2CountryCode); + cnmMemFree(prAdapter, prCmd); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void rlmDomainSendPassiveScanInfoCmd(struct ADAPTER *prAdapter) +{ +#define REG_DOMAIN_PASSIVE_DEF_IDX 1 +#define REG_DOMAIN_PASSIVE_GROUP_NUM \ + (sizeof(arSupportedRegDomains_Passive) / sizeof(struct DOMAIN_INFO_ENTRY)) + + struct DOMAIN_INFO_ENTRY *prDomainInfo; + struct CMD_SET_DOMAIN_INFO *prCmd; + struct DOMAIN_SUBBAND_INFO *prSubBand; + uint16_t u2TargetCountryCode; + uint8_t i, j; + + prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(struct CMD_SET_DOMAIN_INFO)); + if (!prCmd) { + DBGLOG(RLM, ERROR, "Alloc cmd buffer failed\n"); + return; + } + kalMemZero(prCmd, sizeof(struct CMD_SET_DOMAIN_INFO)); + + prCmd->u2CountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode; + prCmd->u2IsSetPassiveScan = 1; + prCmd->uc2G4Bandwidth = prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode; + prCmd->uc5GBandwidth = prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode; + prCmd->aucReserved[0] = 0; + prCmd->aucReserved[1] = 0; + + DBGLOG(RLM, TRACE, "u2CountryCode=0x%04x\n", prAdapter->rWifiVar.rConnSettings.u2CountryCode); + + u2TargetCountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode; + + for (i = 0; i < REG_DOMAIN_PASSIVE_GROUP_NUM; i++) { + prDomainInfo = &arSupportedRegDomains_Passive[i]; + + for (j = 0; j < prDomainInfo->u4CountryNum; j++) { + if (prDomainInfo->pu2CountryGroup[j] == u2TargetCountryCode) + break; + } + if (j < prDomainInfo->u4CountryNum) + break; /* Found */ + } + + if (i >= REG_DOMAIN_PASSIVE_GROUP_NUM) + prDomainInfo = &arSupportedRegDomains_Passive[REG_DOMAIN_PASSIVE_DEF_IDX]; + + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubBand = &prDomainInfo->rSubBand[i]; + + prCmd->rSubBand[i].ucRegClass = prSubBand->ucRegClass; + prCmd->rSubBand[i].ucBand = prSubBand->ucBand; + + if (prSubBand->ucBand != BAND_NULL && prSubBand->ucBand < BAND_NUM) { + prCmd->rSubBand[i].ucChannelSpan = prSubBand->ucChannelSpan; + prCmd->rSubBand[i].ucFirstChannelNum = prSubBand->ucFirstChannelNum; + prCmd->rSubBand[i].ucNumChannels = prSubBand->ucNumChannels; + } + } + + /* Set passive scan channel info to chip */ + wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_DOMAIN_INFO, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct CMD_SET_DOMAIN_INFO), /* u4SetQueryInfoLen */ + (uint8_t *) prCmd, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + rlmSetEd_EU(prAdapter, prCmd->u2CountryCode); + cnmMemFree(prAdapter, prCmd); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in/out] +* +* \return TRUE Legal channel +* FALSE Illegal channel for current regulatory domain +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t rlmDomainIsLegalChannel_V2(struct ADAPTER *prAdapter, enum ENUM_BAND eBand, uint8_t ucChannel) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + uint8_t idx, start_idx, end_idx; + struct channel *prCh; + + if (eBand == BAND_2G4) { + start_idx = 0; + end_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + } else { + start_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + end_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ) + + rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ); + } + + for (idx = start_idx; idx < end_idx; idx++) { + prCh = rlmDomainGetActiveChannels() + idx; + + if (prCh->chNum == ucChannel) + return TRUE; + } + + return FALSE; +#else + return FALSE; +#endif +} + +u_int8_t rlmDomainIsLegalChannel(struct ADAPTER *prAdapter, enum ENUM_BAND eBand, uint8_t ucChannel) +{ + uint8_t i, j; + struct DOMAIN_SUBBAND_INFO *prSubband; + struct DOMAIN_INFO_ENTRY *prDomainInfo; + + if (regd_is_single_sku_en()) + return rlmDomainIsLegalChannel_V2(prAdapter, eBand, ucChannel); + + + prDomainInfo = rlmDomainGetDomainInfo(prAdapter); + ASSERT(prDomainInfo); + + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubband = &prDomainInfo->rSubBand[i]; + + if (prSubband->ucBand == BAND_5G && !prAdapter->fgEnable5GBand) + continue; + + if (prSubband->ucBand == eBand) { + for (j = 0; j < prSubband->ucNumChannels; j++) { + if ((prSubband->ucFirstChannelNum + j * prSubband->ucChannelSpan) + == ucChannel) { + return TRUE; + } + } + } + } + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in/out] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ + +uint32_t rlmDomainSupOperatingClassIeFill(uint8_t *pBuf) +{ + /* + * The Country element should only be included for Status Code 0 (Successful). + */ + uint32_t u4IeLen; + uint8_t aucClass[12] = { 0x01, 0x02, 0x03, 0x05, 0x16, 0x17, 0x19, 0x1b, + 0x1c, 0x1e, 0x20, 0x21 + }; + + /* + * The Supported Operating Classes element is used by a STA to advertise the + * operating classes that it is capable of operating with in this country. + * + * The Country element (see 8.4.2.10) allows a STA to configure its PHY and MAC + * for operation when the operating triplet of Operating Extension Identifier, + * Operating Class, and Coverage Class fields is present. + */ + SUP_OPERATING_CLASS_IE(pBuf)->ucId = ELEM_ID_SUP_OPERATING_CLASS; + SUP_OPERATING_CLASS_IE(pBuf)->ucLength = 1 + sizeof(aucClass); + SUP_OPERATING_CLASS_IE(pBuf)->ucCur = 0x0c; /* 0x51 */ + kalMemCopy(SUP_OPERATING_CLASS_IE(pBuf)->ucSup, aucClass, sizeof(aucClass)); + u4IeLen = (SUP_OPERATING_CLASS_IE(pBuf)->ucLength + 2); + pBuf += u4IeLen; + + COUNTRY_IE(pBuf)->ucId = ELEM_ID_COUNTRY_INFO; + COUNTRY_IE(pBuf)->ucLength = 6; + COUNTRY_IE(pBuf)->aucCountryStr[0] = 0x55; + COUNTRY_IE(pBuf)->aucCountryStr[1] = 0x53; + COUNTRY_IE(pBuf)->aucCountryStr[2] = 0x20; + COUNTRY_IE(pBuf)->arCountryStr[0].ucFirstChnlNum = 1; + COUNTRY_IE(pBuf)->arCountryStr[0].ucNumOfChnl = 11; + COUNTRY_IE(pBuf)->arCountryStr[0].cMaxTxPwrLv = 0x1e; + u4IeLen += (COUNTRY_IE(pBuf)->ucLength + 2); + + return u4IeLen; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (fgValid) : 0 -> inValid, 1 -> Valid +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t rlmDomainCheckChannelEntryValid(struct ADAPTER *prAdapter, uint8_t ucCentralCh) +{ + u_int8_t fgValid = FALSE; + uint8_t ucTemp = 0xff; + uint8_t i; + /*Check Power limit table channel efficient or not */ + + /* CH50 is not located in any FCC subbands but it's a valid central channel for 160C*/ + if (ucCentralCh == 50) { + fgValid = TRUE; + return fgValid; + } + + for (i = POWER_LIMIT_2G4; i < POWER_LIMIT_SUBAND_NUM; i++) { + if ((ucCentralCh >= g_rRlmSubBand[i].ucStartCh) && (ucCentralCh <= g_rRlmSubBand[i].ucEndCh)) + ucTemp = (ucCentralCh - g_rRlmSubBand[i].ucStartCh) % g_rRlmSubBand[i].ucInterval; + } + + if (ucTemp == 0) + fgValid = TRUE; + return fgValid; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return +*/ +/*----------------------------------------------------------------------------*/ +uint8_t rlmDomainGetCenterChannel(enum ENUM_BAND eBand, uint8_t ucPriChannel, enum ENUM_CHNL_EXT eExtend) +{ + uint8_t ucCenterChannel; + + if (eExtend == CHNL_EXT_SCA) + ucCenterChannel = ucPriChannel + 2; + else if (eExtend == CHNL_EXT_SCB) + ucCenterChannel = ucPriChannel - 2; + else + ucCenterChannel = ucPriChannel; + + return ucCenterChannel; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t +rlmDomainIsValidRfSetting(struct ADAPTER *prAdapter, + enum ENUM_BAND eBand, + uint8_t ucPriChannel, + enum ENUM_CHNL_EXT eExtend, + enum ENUM_CHANNEL_WIDTH eChannelWidth, uint8_t ucChannelS1, uint8_t ucChannelS2) +{ + uint8_t ucCenterChannel = 0; + uint8_t ucUpperChannel; + uint8_t ucLowerChannel; + u_int8_t fgValidChannel = TRUE; + u_int8_t fgUpperChannel = TRUE; + u_int8_t fgLowerChannel = TRUE; + u_int8_t fgValidBW = TRUE; + u_int8_t fgValidRfSetting = TRUE; + uint32_t u4PrimaryOffset; + + /*DBG msg for Channel InValid */ + if (eChannelWidth == CW_20_40MHZ) { + ucCenterChannel = rlmDomainGetCenterChannel(eBand, ucPriChannel, eExtend); + + /* Check Central Channel Valid or Not */ + fgValidChannel = rlmDomainCheckChannelEntryValid(prAdapter, ucCenterChannel); + if (fgValidChannel == FALSE) + DBGLOG(RLM, WARN, "Rf20: CentralCh=%d\n", ucCenterChannel); + + /* Check Upper Channel and Lower Channel */ + switch (eExtend) { + case CHNL_EXT_SCA: + ucUpperChannel = ucPriChannel + 4; + ucLowerChannel = ucPriChannel; + break; + case CHNL_EXT_SCB: + ucUpperChannel = ucPriChannel; + ucLowerChannel = ucPriChannel - 4; + break; + default: + ucUpperChannel = ucPriChannel; + ucLowerChannel = ucPriChannel; + break; + } + + fgUpperChannel = rlmDomainCheckChannelEntryValid(prAdapter, ucUpperChannel); + if (fgUpperChannel == FALSE) + DBGLOG(RLM, WARN, "Rf20: UpperCh=%d\n", ucUpperChannel); + + fgLowerChannel = rlmDomainCheckChannelEntryValid(prAdapter, ucLowerChannel); + if (fgLowerChannel == FALSE) + DBGLOG(RLM, WARN, "Rf20: LowerCh=%d\n", ucLowerChannel); + + } else if ((eChannelWidth == CW_80MHZ) || (eChannelWidth == CW_160MHZ)) { + ucCenterChannel = ucChannelS1; + + /* Check Central Channel Valid or Not */ + if (eChannelWidth != CW_160MHZ) { + /*BW not check , ex: primary 36 and central channel 50 will fail the check*/ + fgValidChannel = rlmDomainCheckChannelEntryValid(prAdapter, ucCenterChannel); + } + + if (fgValidChannel == FALSE) + DBGLOG(RLM, WARN, "Rf80/160C: CentralCh=%d\n", ucCenterChannel); + } else if (eChannelWidth == CW_80P80MHZ) { + ucCenterChannel = ucChannelS1; + + fgValidChannel = rlmDomainCheckChannelEntryValid(prAdapter, ucCenterChannel); + + if (fgValidChannel == FALSE) + DBGLOG(RLM, WARN, "Rf160NC: CentralCh1=%d\n", ucCenterChannel); + + ucCenterChannel = ucChannelS2; + + fgValidChannel = rlmDomainCheckChannelEntryValid(prAdapter, ucCenterChannel); + + if (fgValidChannel == FALSE) + DBGLOG(RLM, WARN, "Rf160NC: CentralCh2=%d\n", ucCenterChannel); + + /* Check Central Channel Valid or Not */ + } else { + DBGLOG(RLM, ERROR, "Wrong BW =%d\n", eChannelWidth); + fgValidChannel = FALSE; + } + + /* Check BW Setting Correct or Not */ + if (eBand == BAND_2G4) { + if (eChannelWidth != CW_20_40MHZ) { + fgValidBW = FALSE; + DBGLOG(RLM, WARN, "Rf: B=%d, W=%d\n", eBand, eChannelWidth); + } + } else { + if ((eChannelWidth == CW_80MHZ) || (eChannelWidth == CW_80P80MHZ)) { + u4PrimaryOffset = CAL_CH_OFFSET_80M(ucPriChannel, ucChannelS1); + if (u4PrimaryOffset >= 4) { + fgValidBW = FALSE; + DBGLOG(RLM, WARN, "Rf: PriOffSet=%d, W=%d\n", u4PrimaryOffset, eChannelWidth); + } + if (ucPriChannel == 165) { + fgValidBW = FALSE; + DBGLOG(RLM, WARN, "Rf: PriOffSet=%d, W=%d C=%d\n", + u4PrimaryOffset, eChannelWidth, ucPriChannel); + } + } else if (eChannelWidth == CW_160MHZ) { + u4PrimaryOffset = CAL_CH_OFFSET_160M(ucPriChannel, ucCenterChannel); + if (u4PrimaryOffset >= 8) { + fgValidBW = FALSE; + DBGLOG(RLM, WARN, "Rf: PriOffSet=%d, W=%d\n", u4PrimaryOffset, eChannelWidth); + } + } + } + + if ((fgValidBW == FALSE) || (fgValidChannel == FALSE) || (fgUpperChannel == FALSE) || (fgLowerChannel == FALSE)) + fgValidRfSetting = FALSE; + + return fgValidRfSetting; + +} + +#if (CFG_SUPPORT_SINGLE_SKU == 1) +/* + * This function coverts country code from alphabet chars to u32, + * the caller need to pass country code chars and do size check + */ +uint32_t rlmDomainAlpha2ToU32(uint8_t *pcAlpha2, uint8_t ucAlpha2Size) +{ + uint8_t ucIdx; + uint32_t u4CountryCode = 0; + + if (ucAlpha2Size > TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN) { + DBGLOG(RLM, ERROR, "alpha2 size %d is invalid!(max: %d)\n", + ucAlpha2Size, TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN); + ucAlpha2Size = TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN; + } + + for (ucIdx = 0; ucIdx < ucAlpha2Size; ucIdx++) + u4CountryCode |= (pcAlpha2[ucIdx] << (ucIdx * 8)); + + return u4CountryCode; +} + +uint8_t rlmDomainTxPwrLimitGetTableVersion( + uint8_t *pucBuf, uint32_t u4BufLen) +{ +#define TX_PWR_LIMIT_VERSION_STR_LEN 7 +#define TX_PWR_LIMIT_MAX_VERSION 1 + uint32_t u4TmpPos = 0; + uint8_t ucVersion = 0; + + while (u4TmpPos < u4BufLen && pucBuf[u4TmpPos] != '<') + u4TmpPos++; + + if (u4TmpPos >= (u4BufLen - TX_PWR_LIMIT_VERSION_STR_LEN)) + return ucVersion; + + if (kalStrnCmp(&pucBuf[u4TmpPos + 1], "Ver:", 4) == 0) { + ucVersion = (pucBuf[u4TmpPos + 5] - '0') * 10 + + (pucBuf[u4TmpPos + 6] - '0'); + } + + if (ucVersion > TX_PWR_LIMIT_MAX_VERSION) + ucVersion = 0; + + return ucVersion; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Search the tx power limit setting range of the specified in the text +* file +* +* \param[IN] u4CountryCode The u32 type of the specified country. +* \param[IN] pucBuf The content of the text file. +* \param[IN] u4cBufLen End boundary of the text file. +* \param[OUT] pu4CountryStart Store the start position of the desired country +* settings. +* \param[OUT] pu4CountryEnd Store the end position of the desired country +* settings. +* +* \retval TRUE Success. +* \retval FALSE Failure. +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t rlmDomainTxPwrLimitGetCountryRange( + uint32_t u4CountryCode, uint8_t *pucBuf, uint32_t u4BufLen, + uint32_t *pu4CountryStart, uint32_t *pu4CountryEnd) +{ + uint32_t u4TmpPos = 0; + char pcrCountryStr[TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN + 1] = {0}; + uint8_t cIdx = 0; + int8_t search_next = FALSE; + + while (1) { + if (!search_next) { + /* Search country code entry */ + while (u4TmpPos < u4BufLen && pucBuf[u4TmpPos] != '[') + u4TmpPos++; + + /* skip the '[' char */ + u4TmpPos++; + } + + cIdx = 0; + while ((u4TmpPos < u4BufLen) && + (cIdx < TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN) && + (pucBuf[u4TmpPos] != ']') + && (pucBuf[u4TmpPos] != ',')) { + pcrCountryStr[cIdx++] = pucBuf[u4TmpPos]; + u4TmpPos++; + } + + if (pucBuf[u4TmpPos] == ',') + search_next = TRUE; + else + search_next = FALSE; + /* skip the ']' or ',' char */ + u4TmpPos++; + + if ((u4TmpPos >= u4BufLen) || + (cIdx > TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN)) + return FALSE; + + if (u4CountryCode == + rlmDomainAlpha2ToU32(pcrCountryStr, cIdx)) { + DBGLOG(RLM, INFO, + "Found TxPwrLimit table for CountryCode \"%s\"\n", + pcrCountryStr); + /* the location after char ']' or ',' */ + *pu4CountryStart = u4TmpPos; + break; + } + } + + while (u4TmpPos < u4BufLen && pucBuf[u4TmpPos] != '[') + u4TmpPos++; + + *pu4CountryEnd = u4TmpPos; + + return TRUE; +} + +u_int8_t rlmDomainTxPwrLimitSearchSection(const char *pSectionName, + uint8_t *pucBuf, uint32_t *pu4Pos, uint32_t u4BufEnd) +{ + uint32_t u4TmpPos = *pu4Pos; + uint8_t uSectionNameLen = kalStrLen(pSectionName); + + while (1) { + while (u4TmpPos < u4BufEnd && pucBuf[u4TmpPos] != '<') + u4TmpPos++; + + u4TmpPos++; /* skip char '<' */ + + if (u4TmpPos + uSectionNameLen >= u4BufEnd) + return FALSE; + + if (kalStrnCmp(&pucBuf[u4TmpPos], + pSectionName, uSectionNameLen) == 0) { + + /* Go to the end of section header line */ + while ((u4TmpPos < u4BufEnd) && + (pucBuf[u4TmpPos] != '\n')) + u4TmpPos++; + + *pu4Pos = u4TmpPos; + + break; + } + } + + return TRUE; +} + +u_int8_t rlmDomainTxPwrLimitSectionEnd(uint8_t *pucBuf, + const char *pSectionName, uint32_t *pu4Pos, uint32_t u4BufEnd) +{ + uint32_t u4TmpPos = *pu4Pos; + char cTmpChar = 0; + uint8_t uSectionNameLen = kalStrLen(pSectionName); + + while (u4TmpPos < u4BufEnd) { + cTmpChar = pucBuf[u4TmpPos]; + + /* skip blank lines */ + if (cTmpChar == ' ' || cTmpChar == '\t' || + cTmpChar == '\n' || cTmpChar == '\r') { + u4TmpPos++; + continue; + } + + break; + } + + /* 2 means '/' and '>' */ + if (u4TmpPos + uSectionNameLen + 2 >= u4BufEnd) { + *pu4Pos = u4BufEnd; + return FALSE; + } + + if (pucBuf[u4TmpPos] != '<') + return FALSE; + + if (pucBuf[u4TmpPos + 1] != '/' || + pucBuf[u4TmpPos + 2 + uSectionNameLen] != '>' || + kalStrnCmp(&pucBuf[u4TmpPos + 2], + pSectionName, uSectionNameLen)) { + + *pu4Pos = u4TmpPos + uSectionNameLen + 2; + return FALSE; + } + + /* 3 means go to the location after '>' */ + *pu4Pos = u4TmpPos + uSectionNameLen + 3; + return TRUE; +} + +int8_t rlmDomainTxPwrLimitGetChIdx( + struct TX_PWR_LIMIT_DATA *pTxPwrLimit, uint8_t ucChannel) +{ + int8_t cIdx = 0; + + for (cIdx = 0; cIdx < pTxPwrLimit->ucChNum; cIdx++) + if (ucChannel == + pTxPwrLimit->rChannelTxPwrLimit[cIdx].ucChannel) + return cIdx; + + DBGLOG(RLM, ERROR, + "Can't find idx of channel %d in TxPwrLimit data\n", + ucChannel); + + return -1; +} + +u_int8_t rlmDomainTxPwrLimitIsTxBfBackoffSection( + uint8_t ucVersion, uint8_t ucSectionIdx) +{ + if (ucVersion == 1 && ucSectionIdx == 8) + return TRUE; + + return FALSE; +} +u_int8_t rlmDomainTxPwrLimitLoadChannelSetting( + uint8_t ucVersion, uint8_t *pucBuf, uint32_t *pu4Pos, uint32_t u4BufEnd, + struct TX_PWR_LIMIT_DATA *pTxPwrLimit, uint8_t ucSectionIdx) +{ + uint32_t u4TmpPos = *pu4Pos; + char cTmpChar = 0; + struct CHANNEL_TX_PWR_LIMIT *prChTxPwrLimit = NULL; + u_int8_t bNeg = FALSE; + int8_t cLimitValue = 0, cChIdx = 0; + uint8_t ucIdx = 0, ucChannel = 0; + uint8_t ucElementNum = + gTx_Pwr_Limit_Element_Num[ucVersion][ucSectionIdx]; + + /* skip blank lines */ + while (u4TmpPos < u4BufEnd) { + cTmpChar = pucBuf[u4TmpPos]; + + if (cTmpChar == ' ' || cTmpChar == '\t' || + cTmpChar == '\n' || cTmpChar == '\r') { + u4TmpPos++; + continue; + } + + break; + } + + /* current is at the location of 'c', + * check remaining buf length for 'chxxx' + */ + if (u4TmpPos + 5 >= u4BufEnd) { + DBGLOG(RLM, ERROR, + "Invalid location of ch setting: %u/%u\n", + u4TmpPos, u4BufEnd); + return FALSE; + } + + if (pucBuf[u4TmpPos] == 'c' && pucBuf[u4TmpPos + 1] == 'h') { + ucChannel = (pucBuf[u4TmpPos + 2] - '0') * 100 + + (pucBuf[u4TmpPos + 3] - '0') * 10 + + (pucBuf[u4TmpPos + 4] - '0'); + } else { /* invalid format */ + *pu4Pos = u4TmpPos; + DBGLOG(RLM, ERROR, + "Invalid ch setting starting chars: %c%c\n", + pucBuf[u4TmpPos], pucBuf[u4TmpPos + 1]); + + /* goto next line */ + while (*pu4Pos < u4BufEnd && pucBuf[*pu4Pos] != '\n') + (*pu4Pos)++; + + return TRUE; + } + + cChIdx = rlmDomainTxPwrLimitGetChIdx(pTxPwrLimit, ucChannel); + + if (cChIdx == -1) { + *pu4Pos = u4TmpPos; + DBGLOG(RLM, ERROR, "Invalid ch %u %c%c%c\n", ucChannel, + pucBuf[u4TmpPos + 2], + pucBuf[u4TmpPos + 3], pucBuf[u4TmpPos + 4]); + + /* goto next line */ + while (*pu4Pos < u4BufEnd && pucBuf[*pu4Pos] != '\n') + (*pu4Pos)++; + + return TRUE; + } + + u4TmpPos += 5; + + prChTxPwrLimit = &pTxPwrLimit->rChannelTxPwrLimit[cChIdx]; + + /* read the channel TxPwrLimit settings */ + for (ucIdx = 0; ucIdx < ucElementNum; ucIdx++) { + + /* skip blank and comma */ + while (u4TmpPos < u4BufEnd) { + cTmpChar = pucBuf[u4TmpPos]; + + if ((cTmpChar == ' ') || + (cTmpChar == '\t') || + (cTmpChar == ',')) { + u4TmpPos++; + continue; + } + break; + } + + if (u4TmpPos >= u4BufEnd) { + *pu4Pos = u4BufEnd; + DBGLOG(RLM, ERROR, + "Invalid location of ch tx pwr limit val: %u/%u\n", + u4TmpPos, u4BufEnd); + return FALSE; + } + + bNeg = FALSE; + + cTmpChar = pucBuf[u4TmpPos]; + + if (cTmpChar == '-') { + bNeg = TRUE; + u4TmpPos++; + } else { + if (cTmpChar == 'x') { + if (!rlmDomainTxPwrLimitIsTxBfBackoffSection( + ucVersion, ucSectionIdx)) { + prChTxPwrLimit-> + rTxPwrLimitValue + [ucSectionIdx][ucIdx] = + TX_PWR_LIMIT_MAX_VAL; + } else { + prChTxPwrLimit->rTxBfBackoff[ucIdx] = + TX_PWR_LIMIT_MAX_VAL; + } + u4TmpPos++; + continue; + } + } + + cLimitValue = 0; + while (u4TmpPos < u4BufEnd) { + cTmpChar = pucBuf[u4TmpPos]; + + if (cTmpChar < '0' || cTmpChar > '9') + break; + + cLimitValue = (cLimitValue * 10) + (cTmpChar - '0'); + u4TmpPos++; + } + + if (bNeg) + cLimitValue = -cLimitValue; + if (!rlmDomainTxPwrLimitIsTxBfBackoffSection( + ucVersion, ucSectionIdx)) { + prChTxPwrLimit->rTxPwrLimitValue[ucSectionIdx][ucIdx] = + cLimitValue; + } else { + prChTxPwrLimit->rTxBfBackoff[ucIdx] = + cLimitValue; + } + } + + *pu4Pos = u4TmpPos; + return TRUE; +} + +void rlmDomainTxPwrLimitRemoveComments( + uint8_t *pucBuf, uint32_t u4BufLen) +{ + uint32_t u4TmpPos = 0; + char cTmpChar = 0; + + while (u4TmpPos < u4BufLen) { + cTmpChar = pucBuf[u4TmpPos]; + + if (cTmpChar == '#') { + while (cTmpChar != '\n') { + pucBuf[u4TmpPos] = ' '; + + u4TmpPos++; + if (u4TmpPos >= u4BufLen) + break; + + cTmpChar = pucBuf[u4TmpPos]; + } + } + u4TmpPos++; + } +} + +u_int8_t rlmDomainTxPwrLimitLoad( + struct ADAPTER *prAdapter, uint8_t *pucBuf, uint32_t u4BufLen, + uint8_t ucVersion, uint32_t u4CountryCode, + struct TX_PWR_LIMIT_DATA *pTxPwrLimitData) +{ + uint8_t uSecIdx = 0; + uint8_t ucSecNum = gTx_Pwr_Limit_Section[ucVersion].ucSectionNum; + uint32_t u4CountryStart = 0, u4CountryEnd = 0, u4Pos = 0; + struct TX_PWR_LIMIT_SECTION *prSection = + &gTx_Pwr_Limit_Section[ucVersion]; + uint8_t *prFileName = prAdapter->chip_info->prTxPwrLimitFile; + + + if (!rlmDomainTxPwrLimitGetCountryRange(u4CountryCode, pucBuf, + u4BufLen, &u4CountryStart, &u4CountryEnd)) { + DBGLOG(RLM, ERROR, "Can't find specified table in %s\n", + prFileName); + + /* Use WW as default country */ + if (!rlmDomainTxPwrLimitGetCountryRange(COUNTRY_CODE_WW, pucBuf, + u4BufLen, &u4CountryStart, &u4CountryEnd)) { + DBGLOG(RLM, ERROR, + "Can't find default table (WW) in %s\n", + prFileName); + return FALSE; + } + } + u4Pos = u4CountryStart; + + for (uSecIdx = 0; uSecIdx < ucSecNum; uSecIdx++) { + const uint8_t *pSecName = prSection->arSectionNames[uSecIdx]; + if (!rlmDomainTxPwrLimitSearchSection( + pSecName, pucBuf, &u4Pos, + u4CountryEnd)) { + DBGLOG(RLM, ERROR, + "Can't find specified section %s in %s\n", + pSecName, + prFileName); + continue; + } + + DBGLOG(RLM, INFO, "Find specified section %s in %s\n", + pSecName, + prFileName); + + while (!rlmDomainTxPwrLimitSectionEnd(pucBuf, + pSecName, + &u4Pos, u4CountryEnd) && + u4Pos < u4CountryEnd) { + if (!rlmDomainTxPwrLimitLoadChannelSetting( + ucVersion, pucBuf, &u4Pos, u4CountryEnd, + pTxPwrLimitData, uSecIdx)) + return FALSE; + if (rlmDomainTxPwrLimitIsTxBfBackoffSection( + ucVersion, uSecIdx)) + g_bTxBfBackoffExists = TRUE; + } + } + + DBGLOG(RLM, INFO, "Load %s finished\n", prFileName); + return TRUE; +} + +void rlmDomainTxPwrLimitSetChValues( + uint8_t ucVersion, + struct CMD_CHANNEL_POWER_LIMIT_V2 *pCmd, + struct CHANNEL_TX_PWR_LIMIT *pChTxPwrLimit) +{ + uint8_t section = 0, e = 0; + uint8_t ucElementNum = 0; + + pCmd->tx_pwr_dsss_cck = pChTxPwrLimit->rTxPwrLimitValue[0][0]; + pCmd->tx_pwr_dsss_bpsk = pChTxPwrLimit->rTxPwrLimitValue[0][1]; + + /* 6M, 9M */ + pCmd->tx_pwr_ofdm_bpsk = pChTxPwrLimit->rTxPwrLimitValue[0][2]; + /* 12M, 18M */ + pCmd->tx_pwr_ofdm_qpsk = pChTxPwrLimit->rTxPwrLimitValue[0][3]; + /* 24M, 36M */ + pCmd->tx_pwr_ofdm_16qam = pChTxPwrLimit->rTxPwrLimitValue[0][4]; + pCmd->tx_pwr_ofdm_48m = pChTxPwrLimit->rTxPwrLimitValue[0][5]; + pCmd->tx_pwr_ofdm_54m = pChTxPwrLimit->rTxPwrLimitValue[0][6]; + + /* MCS0*/ + pCmd->tx_pwr_ht20_bpsk = pChTxPwrLimit->rTxPwrLimitValue[1][0]; + /* MCS1, MCS2*/ + pCmd->tx_pwr_ht20_qpsk = pChTxPwrLimit->rTxPwrLimitValue[1][1]; + /* MCS3, MCS4*/ + pCmd->tx_pwr_ht20_16qam = pChTxPwrLimit->rTxPwrLimitValue[1][2]; + /* MCS5*/ + pCmd->tx_pwr_ht20_mcs5 = pChTxPwrLimit->rTxPwrLimitValue[1][3]; + /* MCS6*/ + pCmd->tx_pwr_ht20_mcs6 = pChTxPwrLimit->rTxPwrLimitValue[1][4]; + /* MCS7*/ + pCmd->tx_pwr_ht20_mcs7 = pChTxPwrLimit->rTxPwrLimitValue[1][5]; + + /* MCS0*/ + pCmd->tx_pwr_ht40_bpsk = pChTxPwrLimit->rTxPwrLimitValue[2][0]; + /* MCS1, MCS2*/ + pCmd->tx_pwr_ht40_qpsk = pChTxPwrLimit->rTxPwrLimitValue[2][1]; + /* MCS3, MCS4*/ + pCmd->tx_pwr_ht40_16qam = pChTxPwrLimit->rTxPwrLimitValue[2][2]; + /* MCS5*/ + pCmd->tx_pwr_ht40_mcs5 = pChTxPwrLimit->rTxPwrLimitValue[2][3]; + /* MCS6*/ + pCmd->tx_pwr_ht40_mcs6 = pChTxPwrLimit->rTxPwrLimitValue[2][4]; + /* MCS7*/ + pCmd->tx_pwr_ht40_mcs7 = pChTxPwrLimit->rTxPwrLimitValue[2][5]; + /* MCS32*/ + pCmd->tx_pwr_ht40_mcs32 = pChTxPwrLimit->rTxPwrLimitValue[2][6]; + + /* MCS0*/ + pCmd->tx_pwr_vht20_bpsk = pChTxPwrLimit->rTxPwrLimitValue[3][0]; + /* MCS1, MCS2*/ + pCmd->tx_pwr_vht20_qpsk = pChTxPwrLimit->rTxPwrLimitValue[3][1]; + /* MCS3, MCS4*/ + pCmd->tx_pwr_vht20_16qam = pChTxPwrLimit->rTxPwrLimitValue[3][2]; + /* MCS5, MCS6*/ + pCmd->tx_pwr_vht20_64qam = pChTxPwrLimit->rTxPwrLimitValue[3][3]; + pCmd->tx_pwr_vht20_mcs7 = pChTxPwrLimit->rTxPwrLimitValue[3][4]; + pCmd->tx_pwr_vht20_mcs8 = pChTxPwrLimit->rTxPwrLimitValue[3][5]; + pCmd->tx_pwr_vht20_mcs9 = pChTxPwrLimit->rTxPwrLimitValue[3][6]; + + pCmd->tx_pwr_vht_40 = pChTxPwrLimit->rTxPwrLimitValue[4][2]; + pCmd->tx_pwr_vht_80 = pChTxPwrLimit->rTxPwrLimitValue[4][3]; + pCmd->tx_pwr_vht_160c = pChTxPwrLimit->rTxPwrLimitValue[4][5]; + pCmd->tx_pwr_vht_160nc = pChTxPwrLimit->rTxPwrLimitValue[4][4]; + pCmd->tx_pwr_lg_40 = pChTxPwrLimit->rTxPwrLimitValue[4][0]; + pCmd->tx_pwr_lg_80 = pChTxPwrLimit->rTxPwrLimitValue[4][1]; + + + DBGLOG(RLM, TRACE, "ch %d\n", pCmd->ucCentralCh); + for (section = 0; section < TX_PWR_LIMIT_SECTION_NUM; section++) { + struct TX_PWR_LIMIT_SECTION *pSection = + &gTx_Pwr_Limit_Section[ucVersion]; + ucElementNum = gTx_Pwr_Limit_Element_Num[ucVersion][section]; + for (e = 0; e < ucElementNum; e++) + DBGLOG(RLM, TRACE, "TxPwrLimit[%s][%s]= %d\n", + pSection->arSectionNames[section], + gTx_Pwr_Limit_Element[ucVersion][section][e], + pChTxPwrLimit->rTxPwrLimitValue[section][e]); + } +} + +void rlmDomainTxPwrLimitPerRateSetChValues( + uint8_t ucVersion, + struct CHANNEL_POWER_LIMIT_PER_RATE *pCmd, + struct CHANNEL_TX_PWR_LIMIT *pChTxPwrLimit) +{ + uint8_t section = 0, e = 0, count = 0; + uint8_t ucElementNum = 0; + + for (section = 0; section < TX_PWR_LIMIT_SECTION_NUM; section++) { + if (rlmDomainTxPwrLimitIsTxBfBackoffSection(ucVersion, section)) + continue; + ucElementNum = gTx_Pwr_Limit_Element_Num[ucVersion][section]; + for (e = 0; e < ucElementNum; e++) { + pCmd->aucTxPwrLimit.i1PwrLimit[count] = + pChTxPwrLimit->rTxPwrLimitValue[section][e]; + count++; + } + } + + DBGLOG(RLM, TRACE, "ch %d\n", pCmd->ucCentralCh); + count = 0; + for (section = 0; section < TX_PWR_LIMIT_SECTION_NUM; section++) { + struct TX_PWR_LIMIT_SECTION *pSection = + &gTx_Pwr_Limit_Section[ucVersion]; + if (rlmDomainTxPwrLimitIsTxBfBackoffSection(ucVersion, section)) + continue; + ucElementNum = gTx_Pwr_Limit_Element_Num[ucVersion][section]; + for (e = 0; e < ucElementNum; e++) { + DBGLOG(RLM, TRACE, "TxPwrLimit[%s][%s]= %d\n", + pSection->arSectionNames[section], + gTx_Pwr_Limit_Element[ucVersion][section][e], + pCmd->aucTxPwrLimit.i1PwrLimit[count]); + count++; + } + } +} + +void rlmDomainTxPwrLimitSetValues( + uint8_t ucVersion, + struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2 *pSetCmd, + struct TX_PWR_LIMIT_DATA *pTxPwrLimit) +{ + uint8_t ucIdx = 0; + int8_t cChIdx = 0; + struct CMD_CHANNEL_POWER_LIMIT_V2 *pCmd = NULL; + struct CHANNEL_TX_PWR_LIMIT *pChTxPwrLimit = NULL; + + if (!pSetCmd || !pTxPwrLimit) { + DBGLOG(RLM, ERROR, "Invalid TxPwrLimit request\n"); + return; + } + + for (ucIdx = 0; ucIdx < pSetCmd->ucNum; ucIdx++) { + pCmd = &(pSetCmd->rChannelPowerLimit[ucIdx]); + cChIdx = rlmDomainTxPwrLimitGetChIdx(pTxPwrLimit, + pCmd->ucCentralCh); + if (cChIdx == -1) { + DBGLOG(RLM, ERROR, + "Invalid ch idx found while assigning values\n"); + continue; + } + pChTxPwrLimit = &pTxPwrLimit->rChannelTxPwrLimit[cChIdx]; + rlmDomainTxPwrLimitSetChValues(ucVersion, pCmd, pChTxPwrLimit); + } +} + +void rlmDomainTxPwrLimitPerRateSetValues( + uint8_t ucVersion, + struct CMD_SET_COUNTRY_TX_POWER_LIMIT_PER_RATE *pSetCmd, + struct TX_PWR_LIMIT_DATA *pTxPwrLimit) +{ + uint8_t ucIdx = 0; + int8_t cChIdx = 0; + struct CHANNEL_POWER_LIMIT_PER_RATE *pChPwrLimit = NULL; + struct CHANNEL_TX_PWR_LIMIT *pChTxPwrLimit = NULL; + + if (pSetCmd == NULL) + return; + + for (ucIdx = 0; ucIdx < pSetCmd->ucNum; ucIdx++) { + pChPwrLimit = &(pSetCmd->rChannelPowerLimit[ucIdx]); + cChIdx = rlmDomainTxPwrLimitGetChIdx(pTxPwrLimit, + pChPwrLimit->ucCentralCh); + + if (cChIdx == -1) { + DBGLOG(RLM, ERROR, + "Invalid ch idx found while assigning values\n"); + continue; + } + pChTxPwrLimit = &pTxPwrLimit->rChannelTxPwrLimit[cChIdx]; + rlmDomainTxPwrLimitPerRateSetChValues(ucVersion, + pChPwrLimit, pChTxPwrLimit); + } +} + +u_int8_t rlmDomainTxPwrLimitLoadFromFile( + struct ADAPTER *prAdapter, + uint8_t *pucConfigBuf, uint32_t *pu4ConfigReadLen) +{ +#define TXPWRLIMIT_FILE_LEN 64 + u_int8_t bRet = TRUE; + uint8_t *prFileName = prAdapter->chip_info->prTxPwrLimitFile; + uint8_t aucPath[4][TXPWRLIMIT_FILE_LEN]; + + kalMemZero(aucPath, sizeof(aucPath)); + kalSnprintf(aucPath[0], TXPWRLIMIT_FILE_LEN, "%s", prFileName); + kalSnprintf(aucPath[1], TXPWRLIMIT_FILE_LEN, + "/data/misc/%s", prFileName); + kalSnprintf(aucPath[2], TXPWRLIMIT_FILE_LEN, + "/data/misc/wifi/%s", prFileName); + kalSnprintf(aucPath[3], TXPWRLIMIT_FILE_LEN, + "/storage/sdcard0/%s", prFileName); + + kalMemZero(pucConfigBuf, WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE); + *pu4ConfigReadLen = 0; + + if (wlanGetFileContent( + prAdapter, + aucPath[0], + pucConfigBuf, + WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE, + pu4ConfigReadLen, TRUE) == 0) { + /* ToDo:: Nothing */ + } else if (wlanGetFileContent( + prAdapter, + aucPath[1], + pucConfigBuf, + WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE, + pu4ConfigReadLen, FALSE) == 0) { + /* ToDo:: Nothing */ + } else if (wlanGetFileContent( + prAdapter, + aucPath[2], + pucConfigBuf, + WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE, + pu4ConfigReadLen, FALSE) == 0) { + /* ToDo:: Nothing */ + } else if (wlanGetFileContent( + prAdapter, + aucPath[3], + pucConfigBuf, + WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE, + pu4ConfigReadLen, FALSE) == 0) { + /* ToDo:: Nothing */ + } else { + bRet = FALSE; + goto error; + } + + if (pucConfigBuf[0] == '\0' || *pu4ConfigReadLen == 0) { + bRet = FALSE; + goto error; + } + +error: + + return bRet; +} + +u_int8_t rlmDomainGetTxPwrLimit( + uint32_t country_code, + uint8_t *pucVersion, + struct GLUE_INFO *prGlueInfo, + struct TX_PWR_LIMIT_DATA *pTxPwrLimitData) +{ + u_int8_t bRet = TRUE; + uint8_t *pucConfigBuf = NULL; + uint32_t u4ConfigReadLen = 0; + + pucConfigBuf = (uint8_t *) kalMemAlloc( + WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE, VIR_MEM_TYPE); + + if (!pucConfigBuf) + return FALSE; + + bRet = rlmDomainTxPwrLimitLoadFromFile(prGlueInfo->prAdapter, + pucConfigBuf, &u4ConfigReadLen); + + rlmDomainTxPwrLimitRemoveComments(pucConfigBuf, u4ConfigReadLen); + *pucVersion = rlmDomainTxPwrLimitGetTableVersion(pucConfigBuf, + u4ConfigReadLen); + + if (!rlmDomainTxPwrLimitLoad(prGlueInfo->prAdapter, + pucConfigBuf, u4ConfigReadLen, *pucVersion, + country_code, pTxPwrLimitData)) { + bRet = FALSE; + goto error; + } + +error: + + kalMemFree(pucConfigBuf, + VIR_MEM_TYPE, WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE); + + return bRet; +} + +#endif + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Check if power limit setting is in the range [MIN_TX_POWER, MAX_TX_POWER] +* +* @param[in] +* +* @return (fgValid) : 0 -> inValid, 1 -> Valid +*/ +/*----------------------------------------------------------------------------*/ +u_int8_t +rlmDomainCheckPowerLimitValid(struct ADAPTER *prAdapter, + struct COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION rPowerLimitTableConfiguration, + uint8_t ucPwrLimitNum) +{ + uint8_t i; + u_int8_t fgValid = TRUE; + int8_t *prPwrLimit; + + prPwrLimit = &rPowerLimitTableConfiguration.aucPwrLimit[0]; + + for (i = 0; i < ucPwrLimitNum; i++, prPwrLimit++) { + if (*prPwrLimit > MAX_TX_POWER || *prPwrLimit < MIN_TX_POWER) { + fgValid = FALSE; + break; /*Find out Wrong Power limit */ + } + } + return fgValid; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief 1.Check if power limit configuration table valid(channel intervel) +* 2.Check if power limit configuration/default table entry repeat +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void rlmDomainCheckCountryPowerLimitTable(struct ADAPTER *prAdapter) +{ + uint8_t i, j; + uint16_t u2CountryCodeTable, u2CountryCodeCheck; + u_int8_t fgChannelValid = FALSE; + u_int8_t fgPowerLimitValid = FALSE; + u_int8_t fgEntryRepetetion = FALSE; + u_int8_t fgTableValid = TRUE; + + /*1.Configuration Table Check */ + for (i = 0; i < sizeof(g_rRlmPowerLimitConfiguration) / sizeof(struct COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION); i++) { + /*Table Country Code */ + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitConfiguration[i].aucCountryCode[0], &u2CountryCodeTable); + + /*<1>Repetition Entry Check */ + for (j = i + 1; + j < sizeof(g_rRlmPowerLimitConfiguration) / sizeof(struct COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION); + j++) { + + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitConfiguration[j].aucCountryCode[0], &u2CountryCodeCheck); + if (((g_rRlmPowerLimitConfiguration[i].ucCentralCh) == + g_rRlmPowerLimitConfiguration[j].ucCentralCh) + && (u2CountryCodeTable == u2CountryCodeCheck)) { + fgEntryRepetetion = TRUE; + DBGLOG(RLM, LOUD, "Domain: Configuration Repetition CC=%c%c, Ch=%d\n", + g_rRlmPowerLimitConfiguration[i].aucCountryCode[0], + g_rRlmPowerLimitConfiguration[i].aucCountryCode[1], + g_rRlmPowerLimitConfiguration[i].ucCentralCh); + } + } + + /*<2>Channel Number Interval Check */ + fgChannelValid = + rlmDomainCheckChannelEntryValid(prAdapter, g_rRlmPowerLimitConfiguration[i].ucCentralCh); + + /*<3>Power Limit Range Check */ + fgPowerLimitValid = + rlmDomainCheckPowerLimitValid(prAdapter, g_rRlmPowerLimitConfiguration[i], PWR_LIMIT_NUM); + + if (fgChannelValid == FALSE || fgPowerLimitValid == FALSE) { + fgTableValid = FALSE; + DBGLOG(RLM, LOUD, + "Domain: CC=%c%c, Ch=%d, Limit: %d,%d,%d,%d,%d,%d,%d,%d,%d, Valid:%d,%d\n", + g_rRlmPowerLimitConfiguration[i].aucCountryCode[0], + g_rRlmPowerLimitConfiguration[i].aucCountryCode[1], + g_rRlmPowerLimitConfiguration[i].ucCentralCh, + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_CCK], + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_20M_L], + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_20M_H], + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_40M_L], + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_40M_H], + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_80M_L], + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_80M_H], + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_160M_L], + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_160M_H], + fgChannelValid, + fgPowerLimitValid); + } + + if (u2CountryCodeTable == COUNTRY_CODE_NULL) { + DBGLOG(RLM, LOUD, "Domain: Full search down\n"); + break; /*End of country table entry */ + } + + } + + if (fgEntryRepetetion == FALSE) + DBGLOG(RLM, TRACE, "Domain: Configuration Table no Repetiton.\n"); + + /*Configuration Table no error */ + if (fgTableValid == TRUE) + prAdapter->fgIsPowerLimitTableValid = TRUE; + else + prAdapter->fgIsPowerLimitTableValid = FALSE; + + /*2.Default Table Repetition Entry Check */ + fgEntryRepetetion = FALSE; + for (i = 0; i < sizeof(g_rRlmPowerLimitDefault) / sizeof(struct COUNTRY_POWER_LIMIT_TABLE_DEFAULT); i++) { + + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[i].aucCountryCode[0], &u2CountryCodeTable); + + for (j = i + 1; j < sizeof(g_rRlmPowerLimitDefault) / sizeof(struct COUNTRY_POWER_LIMIT_TABLE_DEFAULT); j++) { + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[j].aucCountryCode[0], &u2CountryCodeCheck); + if (u2CountryCodeTable == u2CountryCodeCheck) { + fgEntryRepetetion = TRUE; + DBGLOG(RLM, LOUD, + "Domain: Default Repetition CC=%c%c\n", + g_rRlmPowerLimitDefault[j].aucCountryCode[0], + g_rRlmPowerLimitDefault[j].aucCountryCode[1]); + } + } + } + if (fgEntryRepetetion == FALSE) + DBGLOG(RLM, TRACE, "Domain: Default Table no Repetiton.\n"); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (u2TableIndex) : if 0xFFFF -> No Table Match +*/ +/*----------------------------------------------------------------------------*/ +uint16_t rlmDomainPwrLimitDefaultTableDecision(struct ADAPTER *prAdapter, uint16_t u2CountryCode) +{ + + uint16_t i; + uint16_t u2CountryCodeTable = COUNTRY_CODE_NULL; + uint16_t u2TableIndex = POWER_LIMIT_TABLE_NULL; /* No Table Match */ + + /*Default Table Index */ + for (i = 0; i < sizeof(g_rRlmPowerLimitDefault) / sizeof(struct COUNTRY_POWER_LIMIT_TABLE_DEFAULT); i++) { + + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[i].aucCountryCode[0], &u2CountryCodeTable); + + if (u2CountryCodeTable == u2CountryCode) { + u2TableIndex = i; + break; /*match country code */ + } else if (u2CountryCodeTable == COUNTRY_CODE_NULL) { + u2TableIndex = i; + break; /*find last one country- Default */ + } + } + + return u2TableIndex; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Fill power limit CMD by Power Limit Default Table(regulation) +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +void rlmDomainBuildCmdByDefaultTable(struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT *prCmd, uint16_t u2DefaultTableIndex) +{ + uint8_t i, k; + struct COUNTRY_POWER_LIMIT_TABLE_DEFAULT *prPwrLimitSubBand; + struct CMD_CHANNEL_POWER_LIMIT *prCmdPwrLimit; + + prCmdPwrLimit = &prCmd->rChannelPowerLimit[0]; + prPwrLimitSubBand = &g_rRlmPowerLimitDefault[u2DefaultTableIndex]; + + /*Build power limit cmd by default table information */ + + for (i = POWER_LIMIT_2G4; i < POWER_LIMIT_SUBAND_NUM; i++) { + if (prPwrLimitSubBand->aucPwrLimitSubBand[i] < MAX_TX_POWER) { + for (k = g_rRlmSubBand[i].ucStartCh; k <= g_rRlmSubBand[i].ucEndCh; + k += g_rRlmSubBand[i].ucInterval) { + if ((prPwrLimitSubBand->ucPwrUnit & BIT(i)) == 0) { + prCmdPwrLimit->ucCentralCh = k; + kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, + prPwrLimitSubBand->aucPwrLimitSubBand[i], PWR_LIMIT_NUM); + } else { + /* ex: 40MHz power limit(mW\MHz) = 20MHz power limit(mW\MHz) * 2 + * ---> 40MHz power limit(dBm) = 20MHz power limit(dBm) + 6; + */ + prCmdPwrLimit->ucCentralCh = k; + /* BW20 */ + prCmdPwrLimit->cPwrLimitCCK = prPwrLimitSubBand->aucPwrLimitSubBand[i]; + prCmdPwrLimit->cPwrLimit20L = prPwrLimitSubBand->aucPwrLimitSubBand[i]; + prCmdPwrLimit->cPwrLimit20H = prPwrLimitSubBand->aucPwrLimitSubBand[i]; + + /* BW40 */ + if (prPwrLimitSubBand->aucPwrLimitSubBand[i] + 6 > MAX_TX_POWER) { + prCmdPwrLimit->cPwrLimit40L = MAX_TX_POWER; + prCmdPwrLimit->cPwrLimit40H = MAX_TX_POWER; + } else { + prCmdPwrLimit->cPwrLimit40L = + prPwrLimitSubBand->aucPwrLimitSubBand[i] + 6; + prCmdPwrLimit->cPwrLimit40H = + prPwrLimitSubBand->aucPwrLimitSubBand[i] + 6; + } + + /* BW80 */ + if (prPwrLimitSubBand->aucPwrLimitSubBand[i] + 12 > MAX_TX_POWER) { + prCmdPwrLimit->cPwrLimit80L = MAX_TX_POWER; + prCmdPwrLimit->cPwrLimit80H = MAX_TX_POWER; + } else { + prCmdPwrLimit->cPwrLimit80L = + prPwrLimitSubBand->aucPwrLimitSubBand[i] + 12; + prCmdPwrLimit->cPwrLimit80H = + prPwrLimitSubBand->aucPwrLimitSubBand[i] + 12; + } + + /* BW160 */ + if (prPwrLimitSubBand->aucPwrLimitSubBand[i] + 18 > MAX_TX_POWER) { + prCmdPwrLimit->cPwrLimit160L = MAX_TX_POWER; + prCmdPwrLimit->cPwrLimit160H = MAX_TX_POWER; + } else { + prCmdPwrLimit->cPwrLimit160L = + prPwrLimitSubBand->aucPwrLimitSubBand[i] + 18; + prCmdPwrLimit->cPwrLimit160H = + prPwrLimitSubBand->aucPwrLimitSubBand[i] + 18; + } + + } + prCmdPwrLimit++; /* save to power limit array per subband channel */ + prCmd->ucNum++; + } + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Fill power limit CMD by Power Limit Configurartion Table(Bandedge and Customization) +* +* @param[in] +* +* @return (none) +*/ + /*----------------------------------------------------------------------------*/ +void rlmDomainBuildCmdByConfigTable(struct ADAPTER *prAdapter, struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT *prCmd) +{ + uint8_t i, k; + uint16_t u2CountryCodeTable = COUNTRY_CODE_NULL; + struct CMD_CHANNEL_POWER_LIMIT *prCmdPwrLimit; + u_int8_t fgChannelValid; + + /*Build power limit cmd by configuration table information */ + + for (i = 0; i < sizeof(g_rRlmPowerLimitConfiguration) / sizeof(struct COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION); i++) { + + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitConfiguration[i].aucCountryCode[0], &u2CountryCodeTable); + + fgChannelValid = + rlmDomainCheckChannelEntryValid(prAdapter, g_rRlmPowerLimitConfiguration[i].ucCentralCh); + + if (u2CountryCodeTable == COUNTRY_CODE_NULL) { + break; /*end of configuration table */ + } else if ((u2CountryCodeTable == prCmd->u2CountryCode) && (fgChannelValid == TRUE)) { + + prCmdPwrLimit = &prCmd->rChannelPowerLimit[0]; + + if (prCmd->ucNum != 0) { + for (k = 0; k < prCmd->ucNum; k++) { + if (prCmdPwrLimit->ucCentralCh == + g_rRlmPowerLimitConfiguration[i].ucCentralCh) { + + /*Cmd setting (Default table information) and + * Configuration table has repetition channel entry, + * ex : Default table (ex: 2.4G, limit = 20dBm) --> + * ch1~14 limit =20dBm, + * Configuration table (ex: ch1, limit = 22dBm) --> + * ch 1 = 22 dBm + * Cmd final setting --> ch1 = 22dBm, ch2~14 = 20dBm + */ + kalMemCopy(&prCmdPwrLimit->cPwrLimitCCK, + &g_rRlmPowerLimitConfiguration[i].aucPwrLimit, + PWR_LIMIT_NUM); + + DBGLOG(RLM, LOUD, + "Domain: CC=%c%c,ReplaceCh=%d,Limit=%d,%d,%d,%d,%d,%d,%d,%d,%d,Fg=%d\n", + ((prCmd->u2CountryCode & 0xff00) >> 8), + (prCmd->u2CountryCode & 0x00ff), prCmdPwrLimit->ucCentralCh, + prCmdPwrLimit->cPwrLimitCCK, + prCmdPwrLimit->cPwrLimit20L, prCmdPwrLimit->cPwrLimit20H, + prCmdPwrLimit->cPwrLimit40L, prCmdPwrLimit->cPwrLimit40H, + prCmdPwrLimit->cPwrLimit80L, prCmdPwrLimit->cPwrLimit80H, + prCmdPwrLimit->cPwrLimit160L, prCmdPwrLimit->cPwrLimit160H, + prCmdPwrLimit->ucFlag); + + break; + } + prCmdPwrLimit++; /* To search next entry in rChannelPowerLimit[k]*/ + } + if (k == prCmd->ucNum) { + + /*Full search cmd (Default table setting) no match channel, + * ex : Default table (ex: 2.4G, limit = 20dBm) --> + * ch1~14 limit =20dBm, + * Configuration table (ex: ch36, limit = 22dBm) --> + * ch 36 = 22 dBm + * Cmd final setting --> ch1~14 = 20dBm, ch36 = 22dBm + */ + prCmdPwrLimit->ucCentralCh = g_rRlmPowerLimitConfiguration[i].ucCentralCh; + kalMemCopy(&prCmdPwrLimit->cPwrLimitCCK, + &g_rRlmPowerLimitConfiguration[i].aucPwrLimit, PWR_LIMIT_NUM); + prCmd->ucNum++; /*Add this channel setting in rChannelPowerLimit[k]*/ + + DBGLOG(RLM, LOUD, + "Domain: CC=%c%c,AddCh=%d,Limit=%d,%d,%d,%d,%d,%d,%d,%d,%d,Fg=%d\n", + ((prCmd->u2CountryCode & 0xff00) >> 8), (prCmd->u2CountryCode & 0x00ff), + prCmdPwrLimit->ucCentralCh, prCmdPwrLimit->cPwrLimitCCK, + prCmdPwrLimit->cPwrLimit20L, prCmdPwrLimit->cPwrLimit20H, + prCmdPwrLimit->cPwrLimit40L, prCmdPwrLimit->cPwrLimit40H, + prCmdPwrLimit->cPwrLimit80L, prCmdPwrLimit->cPwrLimit80H, + prCmdPwrLimit->cPwrLimit160L, prCmdPwrLimit->cPwrLimit160H, + prCmdPwrLimit->ucFlag); + + } + } else { + + /*Default table power limit value are max on all subbands --> cmd table no channel entry + * ex : Default table (ex: 2.4G, limit = 63dBm) --> + * no channel entry in cmd, + * Configuration table (ex: ch36, limit = 22dBm) --> + * ch 36 = 22 dBm + * Cmd final setting --> ch36 = 22dBm + */ + prCmdPwrLimit->ucCentralCh = g_rRlmPowerLimitConfiguration[i].ucCentralCh; + kalMemCopy(&prCmdPwrLimit->cPwrLimitCCK, &g_rRlmPowerLimitConfiguration[i].aucPwrLimit, + PWR_LIMIT_NUM); + prCmd->ucNum++; /*Add this channel setting in rChannelPowerLimit[k]*/ + + DBGLOG(RLM, LOUD, "Domain: Default table power limit value are max on all subbands.\n"); + DBGLOG(RLM, LOUD, + "Domain: CC=%c%c,AddCh=%d,Limit=%d,%d,%d,%d,%d,%d,%d,%d,%d,Fg=%d\n", + ((prCmd->u2CountryCode & 0xff00) >> 8), (prCmd->u2CountryCode & 0x00ff), + prCmdPwrLimit->ucCentralCh, prCmdPwrLimit->cPwrLimitCCK, + prCmdPwrLimit->cPwrLimit20L, prCmdPwrLimit->cPwrLimit20H, + prCmdPwrLimit->cPwrLimit40L, prCmdPwrLimit->cPwrLimit40H, + prCmdPwrLimit->cPwrLimit80L, prCmdPwrLimit->cPwrLimit80H, + prCmdPwrLimit->cPwrLimit160L, prCmdPwrLimit->cPwrLimit160H, + prCmdPwrLimit->ucFlag); + } + } + } +} + +struct TX_PWR_LIMIT_DATA * +rlmDomainInitTxPwrLimitData(struct ADAPTER *prAdapter) +{ + uint8_t ch_cnt = 0; + uint8_t ch_idx = 0; + uint8_t band_idx = 0; + uint8_t ch_num = 0; + struct wiphy *wiphy; + const int8_t *prChannelList = NULL; + struct TX_PWR_LIMIT_DATA *pTxPwrLimitData = NULL; + struct CHANNEL_TX_PWR_LIMIT *prChTxPwrLimit = NULL; + + pTxPwrLimitData = + (struct TX_PWR_LIMIT_DATA *) + kalMemAlloc(sizeof(struct TX_PWR_LIMIT_DATA), + VIR_MEM_TYPE); + + if (!pTxPwrLimitData) { + DBGLOG(RLM, ERROR, + "Alloc buffer for TxPwrLimit main struct failed\n"); + return NULL; + } + + pTxPwrLimitData->ucChNum = + TX_PWR_LIMIT_2G_CH_NUM + TX_PWR_LIMIT_5G_CH_NUM; + + pTxPwrLimitData->rChannelTxPwrLimit = + (struct CHANNEL_TX_PWR_LIMIT *) + kalMemAlloc(sizeof(struct CHANNEL_TX_PWR_LIMIT) * + (pTxPwrLimitData->ucChNum), VIR_MEM_TYPE); + + if (!pTxPwrLimitData->rChannelTxPwrLimit) { + DBGLOG(RLM, ERROR, + "Alloc buffer for TxPwrLimit ch values failed\n"); + + kalMemFree(pTxPwrLimitData, VIR_MEM_TYPE, + sizeof(struct TX_PWR_LIMIT_DATA)); + return NULL; + } + + for (ch_idx = 0; ch_idx < pTxPwrLimitData->ucChNum; ch_idx++) { + prChTxPwrLimit = + &(pTxPwrLimitData->rChannelTxPwrLimit[ch_idx]); + kalMemSet(prChTxPwrLimit->rTxPwrLimitValue, + MAX_TX_POWER, + sizeof(prChTxPwrLimit->rTxPwrLimitValue)); + kalMemSet(prChTxPwrLimit->rTxBfBackoff, + MAX_TX_POWER, + sizeof(prChTxPwrLimit->rTxBfBackoff)); + } + + wiphy = priv_to_wiphy(prAdapter->prGlueInfo); + ch_cnt = 0; + for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { + if (band_idx != KAL_BAND_2GHZ && band_idx != KAL_BAND_5GHZ) + continue; + + prChannelList = (band_idx == KAL_BAND_2GHZ) ? + gTx_Pwr_Limit_2g_Ch : gTx_Pwr_Limit_5g_Ch; + + ch_num = + (band_idx == KAL_BAND_2GHZ) ? + TX_PWR_LIMIT_2G_CH_NUM : + TX_PWR_LIMIT_5G_CH_NUM; + + for (ch_idx = 0; ch_idx < ch_num; ch_idx++) { + pTxPwrLimitData->rChannelTxPwrLimit[ch_cnt].ucChannel = + prChannelList[ch_idx]; + ++ch_cnt; + } + } + + return pTxPwrLimitData; +} + +void +rlmDomainSendTxPwrLimitCmd(struct ADAPTER *prAdapter, + uint8_t ucVersion, + struct TX_PWR_LIMIT_DATA *pTxPwrLimitData) +{ + uint8_t ch_cnt = 0; + uint8_t ch_idx = 0; + uint8_t band_idx = 0; + const int8_t *prChannelList = NULL; + uint32_t rStatus; + uint32_t u4SetQueryInfoLen; + uint32_t u4SetCmdTableMaxSize[KAL_NUM_BANDS] = {0}; + struct wiphy *wiphy; + struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2 + *prCmd[KAL_NUM_BANDS] = {0}; + struct CMD_CHANNEL_POWER_LIMIT_V2 *prCmdChPwrLimitV2 = NULL; + uint32_t u4SetCountryCmdSize = + sizeof(struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2); + uint32_t u4ChPwrLimitV2Size = sizeof(struct CMD_CHANNEL_POWER_LIMIT_V2); + const uint8_t ucCmdBatchSize = + prAdapter->chip_info->ucTxPwrLimitBatchSize; + + wiphy = priv_to_wiphy(prAdapter->prGlueInfo); + for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { + if (band_idx != KAL_BAND_2GHZ && band_idx != KAL_BAND_5GHZ) + continue; + + prChannelList = (band_idx == KAL_BAND_2GHZ) ? + gTx_Pwr_Limit_2g_Ch : gTx_Pwr_Limit_5g_Ch; + + ch_cnt = (band_idx == KAL_BAND_2GHZ) ? TX_PWR_LIMIT_2G_CH_NUM : + TX_PWR_LIMIT_5G_CH_NUM; + + if (!ch_cnt) + continue; + + u4SetCmdTableMaxSize[band_idx] = u4SetCountryCmdSize + + ch_cnt * u4ChPwrLimitV2Size; + + prCmd[band_idx] = cnmMemAlloc(prAdapter, + RAM_TYPE_BUF, u4SetCmdTableMaxSize[band_idx]); + + if (!prCmd[band_idx]) { + DBGLOG(RLM, ERROR, "Domain: no buf to send cmd\n"); + goto error; + } + + /*initialize tw pwr table*/ + kalMemSet(prCmd[band_idx], MAX_TX_POWER, + u4SetCmdTableMaxSize[band_idx]); + + prCmd[band_idx]->ucNum = ch_cnt; + prCmd[band_idx]->eband = + (band_idx == KAL_BAND_2GHZ) ? + BAND_2G4 : BAND_5G; + prCmd[band_idx]->countryCode = rlmDomainGetCountryCode(); + + DBGLOG(RLM, INFO, + "%s, active n_channels=%d, band=%d\n", + __func__, ch_cnt, prCmd[band_idx]->eband); + + for (ch_idx = 0; ch_idx < ch_cnt; ch_idx++) { + prCmdChPwrLimitV2 = + &(prCmd[band_idx]->rChannelPowerLimit[ch_idx]); + prCmdChPwrLimitV2->ucCentralCh = + prChannelList[ch_idx]; + } + } + + rlmDomainTxPwrLimitSetValues(ucVersion, + prCmd[KAL_BAND_2GHZ], pTxPwrLimitData); + rlmDomainTxPwrLimitSetValues(ucVersion, + prCmd[KAL_BAND_5GHZ], pTxPwrLimitData); + + for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { + uint8_t ucRemainChNum, i, ucTempChNum, prCmdBatchNum; + uint32_t u4BufSize = 0; + struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2 *prTempCmd = NULL; + enum ENUM_BAND eBand = (band_idx == KAL_BAND_2GHZ) ? + BAND_2G4 : BAND_5G; + uint16_t u2ChIdx = 0; + + if (!prCmd[band_idx]) + continue; + + ucRemainChNum = prCmd[band_idx]->ucNum; + prCmdBatchNum = (ucRemainChNum + + ucCmdBatchSize - 1) / + ucCmdBatchSize; + + for (i = 0; i < prCmdBatchNum; i++) { + if (i == prCmdBatchNum - 1) + ucTempChNum = ucRemainChNum; + else + ucTempChNum = ucCmdBatchSize; + + u4BufSize = u4SetCountryCmdSize + + ucTempChNum * u4ChPwrLimitV2Size; + + prTempCmd = + cnmMemAlloc(prAdapter, + RAM_TYPE_BUF, u4BufSize); + + if (!prTempCmd) { + DBGLOG(RLM, ERROR, + "Domain: no buf to send cmd\n"); + goto error; + } + + /*copy partial tx pwr limit*/ + prTempCmd->ucNum = ucTempChNum; + prTempCmd->eband = eBand; + prTempCmd->countryCode = rlmDomainGetCountryCode(); + u2ChIdx = i * ucCmdBatchSize; + kalMemCopy(&prTempCmd->rChannelPowerLimit[0], + &prCmd[band_idx]->rChannelPowerLimit[u2ChIdx], + ucTempChNum * u4ChPwrLimitV2Size); + + u4SetQueryInfoLen = u4BufSize; + /* Update tx max. power info to chip */ + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_COUNTRY_POWER_LIMIT, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + u4SetQueryInfoLen, + (uint8_t *) prTempCmd, + NULL, + 0); + + cnmMemFree(prAdapter, prTempCmd); + + ucRemainChNum -= ucTempChNum; + } + } + +error: + for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { + if (prCmd[band_idx]) + cnmMemFree(prAdapter, prCmd[band_idx]); + } +} + +u_int32_t rlmDomainInitTxPwrLimitPerRateCmd( + struct ADAPTER *prAdapter, + struct wiphy *prWiphy, + struct CMD_SET_COUNTRY_TX_POWER_LIMIT_PER_RATE *prCmd[]) +{ + uint8_t ch_cnt = 0; + uint8_t ch_idx = 0; + uint8_t band_idx = 0; + const int8_t *prChannelList = NULL; + uint32_t u4SetCmdTableMaxSize[KAL_NUM_BANDS] = {0}; + uint32_t u4SetCountryTxPwrLimitCmdSize = + sizeof(struct CMD_SET_COUNTRY_TX_POWER_LIMIT_PER_RATE); + uint32_t u4ChPwrLimitSize = sizeof(struct CHANNEL_POWER_LIMIT_PER_RATE); + struct CHANNEL_POWER_LIMIT_PER_RATE *prChPwrLimit = NULL; + + + for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { + if (band_idx != KAL_BAND_2GHZ && band_idx != KAL_BAND_5GHZ) + continue; + + prChannelList = (band_idx == KAL_BAND_2GHZ) ? + gTx_Pwr_Limit_2g_Ch : gTx_Pwr_Limit_5g_Ch; + + ch_cnt = (band_idx == KAL_BAND_2GHZ) ? TX_PWR_LIMIT_2G_CH_NUM : + TX_PWR_LIMIT_5G_CH_NUM; + + if (!ch_cnt) + continue; + + u4SetCmdTableMaxSize[band_idx] = u4SetCountryTxPwrLimitCmdSize + + ch_cnt * u4ChPwrLimitSize; + + prCmd[band_idx] = cnmMemAlloc(prAdapter, + RAM_TYPE_BUF, u4SetCmdTableMaxSize[band_idx]); + + if (!prCmd[band_idx]) { + DBGLOG(RLM, ERROR, "Domain: no buf to send cmd\n"); + return WLAN_STATUS_RESOURCES; + } + + /*initialize tx pwr table*/ + kalMemSet(prCmd[band_idx]->rChannelPowerLimit, MAX_TX_POWER, + ch_cnt * u4ChPwrLimitSize); + + prCmd[band_idx]->ucNum = ch_cnt; + prCmd[band_idx]->eBand = + (band_idx == KAL_BAND_2GHZ) ? + BAND_2G4 : BAND_5G; + prCmd[band_idx]->countryCode = rlmDomainGetCountryCode(); + + DBGLOG(RLM, INFO, + "%s, active n_channels=%d, band=%d\n", + __func__, ch_cnt, prCmd[band_idx]->eBand); + + for (ch_idx = 0; ch_idx < ch_cnt; ch_idx++) { + prChPwrLimit = + &(prCmd[band_idx]-> + rChannelPowerLimit[ch_idx]); + prChPwrLimit->ucCentralCh = prChannelList[ch_idx]; + } + + } + + return WLAN_STATUS_SUCCESS; +} + +void rlmDomainTxPwrLimitSendPerRateCmd( + struct ADAPTER *prAdapter, + struct CMD_SET_COUNTRY_TX_POWER_LIMIT_PER_RATE *prCmd[] +) +{ + uint32_t rStatus; + uint32_t u4SetQueryInfoLen; + uint8_t band_idx = 0; + uint32_t u4SetCountryTxPwrLimitCmdSize = + sizeof(struct CMD_SET_COUNTRY_TX_POWER_LIMIT_PER_RATE); + uint32_t u4ChPwrLimitSize = sizeof(struct CHANNEL_POWER_LIMIT_PER_RATE); + const uint8_t ucCmdBatchSize = + prAdapter->chip_info->ucTxPwrLimitBatchSize; + + for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { + uint8_t ucRemainChNum, i, ucTempChNum, prCmdBatchNum; + uint32_t u4BufSize = 0; + struct CMD_SET_COUNTRY_TX_POWER_LIMIT_PER_RATE + *prTempCmd = NULL; + enum ENUM_BAND eBand = (band_idx == KAL_BAND_2GHZ) ? + BAND_2G4 : BAND_5G; + uint16_t u2ChIdx = 0; + u_int8_t bCmdFinished = FALSE; + + if (!prCmd[band_idx]) + continue; + + ucRemainChNum = prCmd[band_idx]->ucNum; + prCmdBatchNum = (ucRemainChNum + + ucCmdBatchSize - 1) / + ucCmdBatchSize; + + for (i = 0; i < prCmdBatchNum; i++) { + if (i == prCmdBatchNum - 1) { + ucTempChNum = ucRemainChNum; + bCmdFinished = TRUE; + } else { + ucTempChNum = ucCmdBatchSize; + } + + u4BufSize = u4SetCountryTxPwrLimitCmdSize + + ucTempChNum * u4ChPwrLimitSize; + + prTempCmd = + cnmMemAlloc(prAdapter, + RAM_TYPE_BUF, u4BufSize); + + if (!prTempCmd) { + DBGLOG(RLM, ERROR, + "Domain: no buf to send cmd\n"); + return; + } + + /*copy partial tx pwr limit*/ + prTempCmd->ucNum = ucTempChNum; + prTempCmd->eBand = eBand; + prTempCmd->countryCode = + rlmDomainGetCountryCode(); + prTempCmd->bCmdFinished = bCmdFinished; + u2ChIdx = i * ucCmdBatchSize; + kalMemCopy( + &prTempCmd->rChannelPowerLimit[0], + &prCmd[band_idx]-> + rChannelPowerLimit[u2ChIdx], + ucTempChNum * u4ChPwrLimitSize); + + u4SetQueryInfoLen = u4BufSize; + /* Update tx max. power info to chip */ + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_COUNTRY_POWER_LIMIT_PER_RATE, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + u4SetQueryInfoLen, + (uint8_t *) prTempCmd, + NULL, + 0); + + cnmMemFree(prAdapter, prTempCmd); + + ucRemainChNum -= ucTempChNum; + } + } +} + +u_int32_t rlmDomainInitTxBfBackoffCmd( + struct ADAPTER *prAdapter, + struct wiphy *prWiphy, + struct CMD_TXPWR_TXBF_SET_BACKOFF **prCmd +) +{ + uint8_t ucChNum = TX_PWR_LIMIT_2G_CH_NUM + TX_PWR_LIMIT_5G_CH_NUM; + uint8_t ucChIdx = 0; + uint8_t ucChCnt = 0; + uint8_t ucBandIdx = 0; + uint8_t ucCnt = 0; + const int8_t *prChannelList = NULL; + uint32_t u4SetCmdSize = sizeof(struct CMD_TXPWR_TXBF_SET_BACKOFF); + struct CMD_TXPWR_TXBF_CHANNEL_BACKOFF *prChTxBfBackoff = NULL; + + if (ucChNum >= CMD_POWER_LIMIT_TABLE_SUPPORT_CHANNEL_NUM) { + DBGLOG(RLM, ERROR, "ChNum %d should <= %d\n", + ucChNum, CMD_POWER_LIMIT_TABLE_SUPPORT_CHANNEL_NUM); + return WLAN_STATUS_FAILURE; + } + + *prCmd = cnmMemAlloc(prAdapter, + RAM_TYPE_BUF, u4SetCmdSize); + + if (!*prCmd) { + DBGLOG(RLM, ERROR, "Domain: no buf to send cmd\n"); + return WLAN_STATUS_RESOURCES; + } + + /*initialize backoff table*/ + kalMemSet((*prCmd)->rChannelTxBfBackoff, MAX_TX_POWER, + sizeof((*prCmd)->rChannelTxBfBackoff)); + + (*prCmd)->ucNum = ucChNum; + (*prCmd)->ucBssIdx = prAdapter->prAisBssInfo->ucBssIndex; + + for (ucBandIdx = 0; ucBandIdx < KAL_NUM_BANDS; ucBandIdx++) { + if (ucBandIdx != KAL_BAND_2GHZ && ucBandIdx != KAL_BAND_5GHZ) + continue; + + prChannelList = (ucBandIdx == KAL_BAND_2GHZ) ? + gTx_Pwr_Limit_2g_Ch : gTx_Pwr_Limit_5g_Ch; + ucChCnt = (ucBandIdx == KAL_BAND_2GHZ) ? + TX_PWR_LIMIT_2G_CH_NUM : TX_PWR_LIMIT_5G_CH_NUM; + + for (ucChIdx = 0; ucChIdx < ucChCnt; ucChIdx++) { + prChTxBfBackoff = + &((*prCmd)->rChannelTxBfBackoff[ucCnt++]); + prChTxBfBackoff->ucCentralCh = prChannelList[ucChIdx]; + } + } + + return WLAN_STATUS_SUCCESS; +} + +void rlmDomainTxPwrTxBfBackoffSetValues( + uint8_t ucVersion, + struct CMD_TXPWR_TXBF_SET_BACKOFF *prTxBfBackoffCmd, + struct TX_PWR_LIMIT_DATA *pTxPwrLimitData) +{ + uint8_t ucIdx = 0; + int8_t cChIdx = 0; + struct CMD_TXPWR_TXBF_CHANNEL_BACKOFF *pChTxBfBackoff = NULL; + struct CHANNEL_TX_PWR_LIMIT *pChTxPwrLimit = NULL; + + if (prTxBfBackoffCmd == NULL || + pTxPwrLimitData == NULL) + return; + + for (ucIdx = 0; ucIdx < prTxBfBackoffCmd->ucNum; ucIdx++) { + pChTxBfBackoff = + &(prTxBfBackoffCmd->rChannelTxBfBackoff[ucIdx]); + cChIdx = rlmDomainTxPwrLimitGetChIdx(pTxPwrLimitData, + pChTxBfBackoff->ucCentralCh); + + if (cChIdx == -1) { + DBGLOG(RLM, ERROR, + "Invalid ch idx found while assigning values\n"); + return; + } + pChTxPwrLimit = &pTxPwrLimitData->rChannelTxPwrLimit[cChIdx]; + + kalMemCopy(&pChTxBfBackoff->aucTxBfBackoff, + pChTxPwrLimit->rTxBfBackoff, + sizeof(pChTxBfBackoff->aucTxBfBackoff)); + } + + for (ucIdx = 0; ucIdx < prTxBfBackoffCmd->ucNum; ucIdx++) { + pChTxBfBackoff = + &(prTxBfBackoffCmd->rChannelTxBfBackoff[ucIdx]); + + DBGLOG(RLM, ERROR, + "ch %d TxBf backoff 2to1 %d\n", + pChTxBfBackoff->ucCentralCh, + pChTxBfBackoff->aucTxBfBackoff[0]); + + } + +} + +void rlmDomainTxPwrSendTxBfBackoffCmd( + struct ADAPTER *prAdapter, + struct CMD_TXPWR_TXBF_SET_BACKOFF *prCmd) +{ + uint32_t rStatus; + uint32_t u4SetQueryInfoLen; + uint32_t u4SetCmdSize = sizeof(struct CMD_TXPWR_TXBF_SET_BACKOFF); + + u4SetQueryInfoLen = u4SetCmdSize; + /* Update tx max. power info to chip */ + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_TXBF_BACKOFF, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + u4SetQueryInfoLen, + (uint8_t *) prCmd, + NULL, + 0); + +} + +void +rlmDomainSendTxPwrLimitPerRateCmd(struct ADAPTER *prAdapter, + uint8_t ucVersion, + struct TX_PWR_LIMIT_DATA *pTxPwrLimitData) +{ + struct wiphy *wiphy; + uint8_t band_idx = 0; + struct CMD_SET_COUNTRY_TX_POWER_LIMIT_PER_RATE + *prTxPwrLimitPerRateCmd[KAL_NUM_BANDS] = {0}; + + wiphy = priv_to_wiphy(prAdapter->prGlueInfo); + if (rlmDomainInitTxPwrLimitPerRateCmd( + prAdapter, wiphy, prTxPwrLimitPerRateCmd) != + WLAN_STATUS_SUCCESS) + goto error; + + rlmDomainTxPwrLimitPerRateSetValues(ucVersion, + prTxPwrLimitPerRateCmd[KAL_BAND_2GHZ], pTxPwrLimitData); + rlmDomainTxPwrLimitPerRateSetValues(ucVersion, + prTxPwrLimitPerRateCmd[KAL_BAND_5GHZ], pTxPwrLimitData); + rlmDomainTxPwrLimitSendPerRateCmd(prAdapter, prTxPwrLimitPerRateCmd); + +error: + for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) + if (prTxPwrLimitPerRateCmd[band_idx]) + cnmMemFree(prAdapter, prTxPwrLimitPerRateCmd[band_idx]); +} + +void +rlmDomainSendTxBfBackoffCmd(struct ADAPTER *prAdapter, + uint8_t ucVersion, + struct TX_PWR_LIMIT_DATA *pTxPwrLimitData) +{ + struct wiphy *wiphy; + struct CMD_TXPWR_TXBF_SET_BACKOFF + *prTxBfBackoffCmd = NULL; + + wiphy = priv_to_wiphy(prAdapter->prGlueInfo); + + if (rlmDomainInitTxBfBackoffCmd( + prAdapter, wiphy, &prTxBfBackoffCmd) != + WLAN_STATUS_SUCCESS) + goto error; + + rlmDomainTxPwrTxBfBackoffSetValues( + ucVersion, prTxBfBackoffCmd, pTxPwrLimitData); + rlmDomainTxPwrSendTxBfBackoffCmd(prAdapter, prTxBfBackoffCmd); + +error: + + if (prTxBfBackoffCmd) + cnmMemFree(prAdapter, prTxBfBackoffCmd); +} + +void rlmDomainSendPwrLimitCmd_V2(struct ADAPTER *prAdapter) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + uint8_t ucVersion = 0; + struct TX_PWR_LIMIT_DATA *pTxPwrLimitData = NULL; + + DBGLOG(RLM, INFO, "rlmDomainSendPwrLimitCmd()\n"); + pTxPwrLimitData = rlmDomainInitTxPwrLimitData(prAdapter); + + if (!pTxPwrLimitData) { + DBGLOG(RLM, ERROR, + "Init TxPwrLimitData failed\n"); + goto error; + } + + /* + * Get Max Tx Power from MT_TxPwrLimit.dat + */ + rlmDomainGetTxPwrLimit(rlmDomainGetCountryCode(), + &ucVersion, + prAdapter->prGlueInfo, + pTxPwrLimitData); + + /* Prepare to send CMD to FW */ + if (ucVersion == 0) { + rlmDomainSendTxPwrLimitCmd(prAdapter, + ucVersion, pTxPwrLimitData); + } else if (ucVersion == 1) { + rlmDomainSendTxPwrLimitPerRateCmd(prAdapter, + ucVersion, pTxPwrLimitData); + + if (g_bTxBfBackoffExists) + rlmDomainSendTxBfBackoffCmd(prAdapter, + ucVersion, pTxPwrLimitData); + + } else { + DBGLOG(RLM, WARN, "Unsupported TxPwrLimit dat version %u\n", + ucVersion); + } + +error: + if (pTxPwrLimitData && pTxPwrLimitData->rChannelTxPwrLimit) + kalMemFree(pTxPwrLimitData->rChannelTxPwrLimit, VIR_MEM_TYPE, + sizeof(struct CHANNEL_TX_PWR_LIMIT) * + pTxPwrLimitData->ucChNum); + + if (pTxPwrLimitData) + kalMemFree(pTxPwrLimitData, VIR_MEM_TYPE, + sizeof(struct TX_PWR_LIMIT_DATA)); +#endif +} + +void rlmDomainSendPwrLimitCmd(struct ADAPTER *prAdapter) +{ + struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT *prCmd; + uint32_t rStatus; + uint8_t i; + uint16_t u2DefaultTableIndex; + uint32_t u4SetCmdTableMaxSize; + uint32_t u4SetQueryInfoLen; + struct CMD_CHANNEL_POWER_LIMIT *prCmdPwrLimit; /* for print usage */ + + if (regd_is_single_sku_en()) + return rlmDomainSendPwrLimitCmd_V2(prAdapter); + + + u4SetCmdTableMaxSize = + sizeof(struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT) + + MAX_CMD_SUPPORT_CHANNEL_NUM * sizeof(struct CMD_CHANNEL_POWER_LIMIT); + + prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4SetCmdTableMaxSize); + if (!prCmd) { + DBGLOG(RLM, ERROR, "Domain: Alloc cmd buffer failed\n"); + return; + } + kalMemZero(prCmd, u4SetCmdTableMaxSize); + + u2DefaultTableIndex = + rlmDomainPwrLimitDefaultTableDecision(prAdapter, prAdapter->rWifiVar.rConnSettings.u2CountryCode); + + if (u2DefaultTableIndex != POWER_LIMIT_TABLE_NULL) { + + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[u2DefaultTableIndex].aucCountryCode[0], + &prCmd->u2CountryCode); + + /* Initialize channel number */ + prCmd->ucNum = 0; + + if (prCmd->u2CountryCode != COUNTRY_CODE_NULL) { + /*<1>Command - default table information, fill all subband */ + rlmDomainBuildCmdByDefaultTable(prCmd, u2DefaultTableIndex); + + /*<2>Command - configuration table information, replace specified channel*/ + rlmDomainBuildCmdByConfigTable(prAdapter, prCmd); + } + } + + DBGLOG(RLM, INFO, "Domain: ValidCC=%c%c, PwrLimitCC=%c%c, PwrLimitChNum=%d\n", + (prAdapter->rWifiVar.rConnSettings.u2CountryCode & 0xff00) >> 8, + (prAdapter->rWifiVar.rConnSettings.u2CountryCode & 0x00ff), + ((prCmd->u2CountryCode & 0xff00) >> 8), (prCmd->u2CountryCode & 0x00ff), + prCmd->ucNum); + + prCmdPwrLimit = &prCmd->rChannelPowerLimit[0]; + + for (i = 0; i < prCmd->ucNum; i++) { + DBGLOG(RLM, TRACE, "Domain: Ch=%d,Limit=%d,%d,%d,%d,%d,%d,%d,%d,%d,Fg=%d\n", + prCmdPwrLimit->ucCentralCh, prCmdPwrLimit->cPwrLimitCCK, + prCmdPwrLimit->cPwrLimit20L, prCmdPwrLimit->cPwrLimit20H, + prCmdPwrLimit->cPwrLimit40L, prCmdPwrLimit->cPwrLimit40H, + prCmdPwrLimit->cPwrLimit80L, prCmdPwrLimit->cPwrLimit80H, + prCmdPwrLimit->cPwrLimit160L, prCmdPwrLimit->cPwrLimit160H, + prCmdPwrLimit->ucFlag); + + prCmdPwrLimit++; + } + + u4SetQueryInfoLen = + (sizeof(struct CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT) + (prCmd->ucNum) * sizeof(struct CMD_CHANNEL_POWER_LIMIT)); + + /* Update domain info to chip */ + if (prCmd->ucNum <= MAX_CMD_SUPPORT_CHANNEL_NUM) { + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_COUNTRY_POWER_LIMIT, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + u4SetQueryInfoLen, /* u4SetQueryInfoLen */ + (uint8_t *) prCmd, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + } else { + DBGLOG(RLM, ERROR, "Domain: illegal power limit table\n"); + } + + /* ASSERT(rStatus == WLAN_STATUS_PENDING); */ + + cnmMemFree(prAdapter, prCmd); + +} +#endif +u_int8_t regd_is_single_sku_en(void) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + return g_mtk_regd_control.en; +#else + return FALSE; +#endif +} + +#if (CFG_SUPPORT_SINGLE_SKU == 1) +u_int8_t rlmDomainIsCtrlStateEqualTo(enum regd_state state) +{ + return (g_mtk_regd_control.state == state) ? TRUE : FALSE; +} + +enum regd_state rlmDomainGetCtrlState(void) +{ + return g_mtk_regd_control.state; +} + + +void rlmDomainResetActiveChannel(void) +{ + g_mtk_regd_control.n_channel_active_2g = 0; + g_mtk_regd_control.n_channel_active_5g = 0; +} + +void rlmDomainAddActiveChannel(u8 band) + +{ + if (band == KAL_BAND_2GHZ) + g_mtk_regd_control.n_channel_active_2g += 1; + else if (band == KAL_BAND_5GHZ) + g_mtk_regd_control.n_channel_active_5g += 1; +} + +u8 rlmDomainGetActiveChannelCount(u8 band) +{ + if (band == KAL_BAND_2GHZ) + return g_mtk_regd_control.n_channel_active_2g; + else if (band == KAL_BAND_5GHZ) + return g_mtk_regd_control.n_channel_active_5g; + else + return 0; +} + +struct channel *rlmDomainGetActiveChannels(void) +{ + return g_mtk_regd_control.channels; +} + +void rlmDomainSetDefaultCountryCode(void) +{ + g_mtk_regd_control.alpha2 = COUNTRY_CODE_WW; +} + +void rlmDomainResetCtrlInfo(u_int8_t force) +{ + if ((g_mtk_regd_control.state == REGD_STATE_UNDEFINED) || + (force == TRUE)) { + memset(&g_mtk_regd_control, 0, sizeof(struct mtk_regd_control)); + + g_mtk_regd_control.state = REGD_STATE_INIT; + + rlmDomainSetDefaultCountryCode(); + +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) + g_mtk_regd_control.flag |= REGD_CTRL_FLAG_SUPPORT_LOCAL_REGD_DB; +#endif + } +} + +u_int8_t rlmDomainIsUsingLocalRegDomainDataBase(void) +{ +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) + return (g_mtk_regd_control.flag & REGD_CTRL_FLAG_SUPPORT_LOCAL_REGD_DB) ? TRUE : FALSE; +#else + return FALSE; +#endif +} + +bool rlmDomainIsSameCountryCode(char *alpha2, u8 size_of_alpha2) +{ + u8 idx; + u32 alpha2_hex = 0; + + for (idx = 0; idx < size_of_alpha2; idx++) + alpha2_hex |= (alpha2[idx] << (idx * 8)); + + return (rlmDomainGetCountryCode() == alpha2_hex) ? TRUE : FALSE; +} + +void rlmDomainSetCountryCode(char *alpha2, u8 size_of_alpha2) +{ + u8 max; + u8 buf_size; + + buf_size = sizeof(g_mtk_regd_control.alpha2); + max = (buf_size < size_of_alpha2) ? buf_size : size_of_alpha2; + + g_mtk_regd_control.alpha2 = rlmDomainAlpha2ToU32(alpha2, max); +} +void rlmDomainSetDfsRegion(enum nl80211_dfs_regions dfs_region) +{ + g_mtk_regd_control.dfs_region = dfs_region; +} + +enum nl80211_dfs_regions rlmDomainGetDfsRegion(void) +{ + return g_mtk_regd_control.dfs_region; +} + +void rlmDomainSetTempCountryCode(char *alpha2, u8 size_of_alpha2) +{ + u8 idx, max; + u8 buf_size; + + buf_size = sizeof(g_mtk_regd_control.tmp_alpha2); + max = (buf_size < size_of_alpha2) ? buf_size : size_of_alpha2; + + g_mtk_regd_control.tmp_alpha2 = 0; + + for (idx = 0; idx < max; idx++) + g_mtk_regd_control.tmp_alpha2 |= (alpha2[idx] << (idx * 8)); + +} + +enum regd_state rlmDomainStateTransition(enum regd_state request_state, struct regulatory_request *pRequest) +{ + enum regd_state next_state, old_state; + bool the_same = 0; + + old_state = g_mtk_regd_control.state; + next_state = REGD_STATE_INVALID; + + if (old_state == REGD_STATE_INVALID) + DBGLOG(RLM, ERROR, "%s(): invalid state. trasntion is not allowed.\n", __func__); + + switch (request_state) { + case REGD_STATE_SET_WW_CORE: + if ((old_state == REGD_STATE_SET_WW_CORE) || + (old_state == REGD_STATE_INIT) || + (old_state == REGD_STATE_SET_COUNTRY_USER) || + (old_state == REGD_STATE_SET_COUNTRY_IE)) + next_state = request_state; + break; + case REGD_STATE_SET_COUNTRY_USER: + /* Allow user to set multiple times */ + if ((old_state == REGD_STATE_SET_WW_CORE) || + (old_state == REGD_STATE_INIT) || + (old_state == REGD_STATE_SET_COUNTRY_USER) || + (old_state == REGD_STATE_SET_COUNTRY_IE)) + next_state = request_state; + else + DBGLOG(RLM, ERROR, "Invalid old state = %d\n", old_state); + break; + case REGD_STATE_SET_COUNTRY_DRIVER: + if (old_state == REGD_STATE_SET_COUNTRY_USER) { + /* + * Error. + * Mixing using set_country_by_user and set_country_by_driver + * is not allowed. + */ + break; + } + + next_state = request_state; + break; + case REGD_STATE_SET_COUNTRY_IE: + next_state = request_state; + break; + default: + break; + } + + if (next_state == REGD_STATE_INVALID) { + DBGLOG(RLM, ERROR, "%s(): ERROR. trasntion to invalid state. o=%x, r=%x, s=%x\n", + __func__, old_state, request_state, the_same); + } else + DBGLOG(RLM, INFO, "%s(): trasntion to state = %x (old = %x)\n", + __func__, next_state, g_mtk_regd_control.state); + + g_mtk_regd_control.state = next_state; + + return g_mtk_regd_control.state; +} + +/** + * rlmDomainChannelFlagString - Transform channel flags to readable string + * + * @ flags: the ieee80211_channel->flags for a channel + * @ buf: string buffer to put the transformed string + * @ buf_size: size of the buf + **/ +void rlmDomainChannelFlagString(u32 flags, char *buf, size_t buf_size) +{ + int32_t buf_written = 0; + + if (!flags || !buf || !buf_size) + return; + + if (flags & IEEE80211_CHAN_DISABLED) { + LOGBUF(buf, ((int32_t)buf_size), buf_written, "DISABLED "); + /* If DISABLED, don't need to check other flags */ + return; + } + if (flags & IEEE80211_CHAN_PASSIVE_FLAG) + LOGBUF(buf, ((int32_t)buf_size), buf_written, IEEE80211_CHAN_PASSIVE_STR " "); + if (flags & IEEE80211_CHAN_RADAR) + LOGBUF(buf, ((int32_t)buf_size), buf_written, "RADAR "); + if (flags & IEEE80211_CHAN_NO_HT40PLUS) + LOGBUF(buf, ((int32_t)buf_size), buf_written, "NO_HT40PLUS "); + if (flags & IEEE80211_CHAN_NO_HT40MINUS) + LOGBUF(buf, ((int32_t)buf_size), buf_written, "NO_HT40MINUS "); + if (flags & IEEE80211_CHAN_NO_80MHZ) + LOGBUF(buf, ((int32_t)buf_size), buf_written, "NO_80MHZ "); + if (flags & IEEE80211_CHAN_NO_160MHZ) + LOGBUF(buf, ((int32_t)buf_size), buf_written, "NO_160MHZ "); +} + +void rlmDomainParsingChannel(IN struct wiphy *pWiphy) +{ + u32 band_idx, ch_idx; + u32 ch_count; + struct ieee80211_supported_band *sband; + struct ieee80211_channel *chan; + struct channel *pCh; + char chan_flag_string[64] = {0}; + struct GLUE_INFO *prGlueInfo; + bool fgDisconnection = FALSE; + uint8_t ucChannelNum = 0; + uint32_t rStatus, u4BufLen; + + if (!pWiphy) { + DBGLOG(RLM, ERROR, "%s(): ERROR. pWiphy = NULL.\n", __func__); + ASSERT(0); + return; + } + + /* Retrieve connected channel */ + prGlueInfo = rlmDomainGetGlueInfo(); + if (prGlueInfo && kalGetMediaStateIndicated(prGlueInfo) == + PARAM_MEDIA_STATE_CONNECTED) { + ucChannelNum = + wlanGetChannelNumberByNetwork(prGlueInfo->prAdapter, + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex); + } + + /* + * Ready to parse the channel for bands + */ + + rlmDomainResetActiveChannel(); + + ch_count = 0; + for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { + sband = pWiphy->bands[band_idx]; + if (!sband) + continue; + + for (ch_idx = 0; ch_idx < sband->n_channels; ch_idx++) { + chan = &sband->channels[ch_idx]; + pCh = (rlmDomainGetActiveChannels() + ch_count); + /* Parse flags and get readable string */ + rlmDomainChannelFlagString(chan->flags, chan_flag_string, sizeof(chan_flag_string)); + + if (chan->flags & IEEE80211_CHAN_DISABLED) { + DBGLOG(RLM, INFO, "channels[%d][%d]: ch%d (freq = %d) flags=0x%x [ %s]\n", + band_idx, ch_idx, chan->hw_value, chan->center_freq, chan->flags, + chan_flag_string); + + /* Disconnect AP in the end of this function*/ + if (chan->hw_value == ucChannelNum) + fgDisconnection = TRUE; + + continue; + } + + /* Allowable channel */ + if (ch_count == MAX_SUPPORTED_CH_COUNT) { + DBGLOG(RLM, ERROR, "%s(): no buffer to store channel information.\n", __func__); + break; + } + + rlmDomainAddActiveChannel(band_idx); + + DBGLOG(RLM, INFO, "channels[%d][%d]: ch%d (freq = %d) flgs=0x%x [ %s]\n", + band_idx, ch_idx, chan->hw_value, chan->center_freq, chan->flags, + chan_flag_string); + + pCh->chNum = chan->hw_value; + pCh->flags = chan->flags; + + ch_count += 1; + } + + } + + /* Disconnect with AP if connected channel is disabled in new country */ + if (fgDisconnection) { + DBGLOG(RLM, STATE, "%s(): Disconnect! CH%d is DISABLED\n", + __func__, ucChannelNum); + rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, + NULL, 0, FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(RLM, WARN, "disassociate error:%lx\n", rStatus); + } + +} +void rlmExtractChannelInfo(u32 max_ch_count, struct acctive_channel_list *prBuff) +{ + u32 ch_count, idx; + struct channel *pCh; + + prBuff->n_channels_2g = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + prBuff->n_channels_5g = rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ); + ch_count = prBuff->n_channels_2g + prBuff->n_channels_5g; + + if (ch_count > max_ch_count) { + ch_count = max_ch_count; + DBGLOG(RLM, WARN, "%s(); active channel list is not a complete one.\n", __func__); + } + + for (idx = 0; idx < ch_count; idx++) { + pCh = &(prBuff->channels[idx]); + + pCh->chNum = (rlmDomainGetActiveChannels() + idx)->chNum; + pCh->flags = (rlmDomainGetActiveChannels() + idx)->flags; + } + +} + +const struct ieee80211_regdomain *rlmDomainSearchRegdomainFromLocalDataBase(char *alpha2) +{ +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) + u8 idx; + const struct mtk_regdomain *prRegd; + + idx = 0; + while (g_prRegRuleTable[idx]) { + prRegd = g_prRegRuleTable[idx]; + + if ((prRegd->country_code[0] == alpha2[0]) && + (prRegd->country_code[1] == alpha2[1]) && + (prRegd->country_code[2] == alpha2[2]) && + (prRegd->country_code[3] == alpha2[3])) + return prRegd->prRegdRules; + + idx++; + } + + DBGLOG(RLM, ERROR, "%s(): Error, Cannot find the correct RegDomain. country = %s.\n", + __func__, alpha2); + DBGLOG(RLM, INFO, " Set as default WW.\n"); + + return &default_regdom_ww; /*default world wide*/ +#else + return NULL; +#endif +} + + +const struct ieee80211_regdomain *rlmDomainGetLocalDefaultRegd(void) +{ +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) + return &default_regdom_ww; +#else + return NULL; +#endif +} +struct GLUE_INFO *rlmDomainGetGlueInfo(void) +{ + return g_mtk_regd_control.pGlueInfo; +} + +bool rlmDomainIsEfuseUsed(void) +{ + return g_mtk_regd_control.isEfuseCountryCodeUsed; +} + +uint8_t rlmDomainGetChannelBw(uint8_t channelNum) +{ + uint32_t ch_idx = 0, start_idx = 0, end_idx = 0; + uint8_t channelBw = MAX_BW_80_80_MHZ; + struct channel *pCh; + + end_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ) + + rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ); + + for (ch_idx = start_idx; ch_idx < end_idx; ch_idx++) { + pCh = (rlmDomainGetActiveChannels() + ch_idx); + + if (pCh->chNum != channelNum) + continue; + + /* Max BW */ + if ((pCh->flags & IEEE80211_CHAN_NO_160MHZ) + == IEEE80211_CHAN_NO_160MHZ) + channelBw = MAX_BW_80MHZ; + if ((pCh->flags & IEEE80211_CHAN_NO_80MHZ) + == IEEE80211_CHAN_NO_80MHZ) + channelBw = MAX_BW_40MHZ; + if ((pCh->flags & IEEE80211_CHAN_NO_HT40) + == IEEE80211_CHAN_NO_HT40) + channelBw = MAX_BW_20MHZ; + } + + DBGLOG(RLM, INFO, "ch=%d, BW=%d\n", channelNum, channelBw); + return channelBw; +} +#endif + +uint32_t rlmDomainExtractSingleSkuInfoFromFirmware(IN struct ADAPTER *prAdapter, IN uint8_t *pucEventBuf) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + struct SINGLE_SKU_INFO *prSkuInfo = (struct SINGLE_SKU_INFO *)pucEventBuf; + + g_mtk_regd_control.en = TRUE; + + if (prSkuInfo->isEfuseValid) { + if (!rlmDomainIsUsingLocalRegDomainDataBase()) { + + DBGLOG(RLM, ERROR, "%s(): Error. In efuse mode, must use local data base.\n", __func__); + + ASSERT(0); + return WLAN_STATUS_NOT_SUPPORTED; /*force using local db if getting country code from efuse*/ + } + + rlmDomainSetCountryCode((char *)&prSkuInfo->u4EfuseCountryCode, sizeof(prSkuInfo->u4EfuseCountryCode)); + g_mtk_regd_control.isEfuseCountryCodeUsed = TRUE; + + } +#endif + + return WLAN_STATUS_SUCCESS; +} + +void rlmDomainSendInfoToFirmware(IN struct ADAPTER *prAdapter) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + struct regulatory_request request; + struct regulatory_request *prReq = NULL; + + if (!regd_is_single_sku_en()) + return; /*not support single sku*/ + + if (g_mtk_regd_control.isEfuseCountryCodeUsed) { + request.initiator = NL80211_REGDOM_SET_BY_DRIVER; + prReq = &request; + } + + g_mtk_regd_control.pGlueInfo = prAdapter->prGlueInfo; + mtk_reg_notify(priv_to_wiphy(prAdapter->prGlueInfo), prReq); +#endif +} + +enum ENUM_CHNL_EXT rlmSelectSecondaryChannelType(struct ADAPTER *prAdapter, enum ENUM_BAND band, u8 primary_ch) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + u8 below_ch, above_ch; + + below_ch = primary_ch - CHNL_SPAN_20; + above_ch = primary_ch + CHNL_SPAN_20; + + if (rlmDomainIsLegalChannel(prAdapter, band, above_ch)) + return CHNL_EXT_SCA; + + if (rlmDomainIsLegalChannel(prAdapter, band, below_ch)) + return CHNL_EXT_SCB; + +#endif + + return CHNL_EXT_SCN; +} + +void rlmDomainOidSetCountry(IN struct ADAPTER *prAdapter, char *country, u8 size_of_country) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + struct regulatory_request request; + + kalMemZero(&request, sizeof(request)); + if (rlmDomainIsUsingLocalRegDomainDataBase()) { + rlmDomainSetTempCountryCode(country, size_of_country); + request.initiator = NL80211_REGDOM_SET_BY_DRIVER; + mtk_reg_notify(priv_to_wiphy(prAdapter->prGlueInfo), &request); + } else { + DBGLOG(RLM, INFO, "%s(): Using driver hint to query CRDA getting regd.\n", __func__); + regulatory_hint(priv_to_wiphy(prAdapter->prGlueInfo), country); + } +#endif +} + +u32 rlmDomainGetCountryCode(void) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + return g_mtk_regd_control.alpha2; +#else + return 0; +#endif +} + +u32 rlmDomainGetTempCountryCode(void) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + return g_mtk_regd_control.tmp_alpha2; +#else + return 0; +#endif +} + +void rlmDomainAssert(u_int8_t cond) +{ + /* bypass this check because single sku is not enable */ + if (!regd_is_single_sku_en()) + return; + + if (!cond) { + WARN_ON(1); + DBGLOG(RLM, ERROR, "[WARNING!!] RLM unexpected case.\n"); + } + +} + + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/rlm_obss.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/rlm_obss.c new file mode 100644 index 0000000000000..6e5571456d38e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/rlm_obss.c @@ -0,0 +1,400 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rlm_obss.c#2 + */ + +/*! \file "rlm_obss.c" + * \brief + * + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +static void rlmObssScanTimeout(struct ADAPTER *prAdapter, + unsigned long ulParamPtr); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmObssInit(struct ADAPTER *prAdapter) +{ + struct BSS_INFO *prBssInfo; + uint8_t i; + + ASSERT(prAdapter); + + for (i = 0; i < prAdapter->ucHwBssIdNum; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + + cnmTimerInitTimer(prAdapter, &prBssInfo->rObssScanTimer, + (PFN_MGMT_TIMEOUT_FUNC) rlmObssScanTimeout, + (unsigned long) prBssInfo); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rlmObssUpdateChnlLists(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb) +{ + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmObssScanDone(struct ADAPTER *prAdapter, struct MSG_HDR *prMsgHdr) +{ + struct MSG_SCN_SCAN_DONE *prScanDoneMsg; + struct BSS_INFO *prBssInfo; + struct MSDU_INFO *prMsduInfo; + struct ACTION_20_40_COEXIST_FRAME *prTxFrame; + uint16_t i, u2PayloadLen; + + ASSERT(prMsgHdr); + + prScanDoneMsg = (struct MSG_SCN_SCAN_DONE *) prMsgHdr; + prBssInfo = prAdapter->aprBssInfo[prScanDoneMsg->ucBssIndex]; + ASSERT(prBssInfo); + + DBGLOG(RLM, INFO, "OBSS Scan Done (NetIdx=%d, Mode=%d)\n", + prScanDoneMsg->ucBssIndex, prBssInfo->eCurrentOPMode); + + cnmMemFree(prAdapter, prMsgHdr); + +#if CFG_ENABLE_WIFI_DIRECT + /* AP mode */ + if ((prAdapter->fgIsP2PRegistered) && + (IS_NET_ACTIVE(prAdapter, prBssInfo->ucBssIndex)) && + (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->ucBssIndex); + 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) { + + DBGLOG(RLM, INFO, + "Send 20/40 coexistence mgmt(20mReq=%d, NonHt=%d)\n", + prBssInfo->auc2G_20mReqChnlList[0], + prBssInfo->auc2G_NonHtChnlList[0]); + + prMsduInfo = (struct MSDU_INFO *) cnmMgtPktAlloc(prAdapter, + MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + + if (prMsduInfo) { + prTxFrame = (struct ACTION_20_40_COEXIST_FRAME *) + ((unsigned long) (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; + /* 2.4GHz, ch1~13 */ + prTxFrame->rChnlReport.ucRegulatoryClass = 81; + 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 */ + + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prBssInfo->ucBssIndex, + prBssInfo->prStaRecOfAP->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, + NULL, MSDU_RATE_MODE_AUTO); + + /* 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->ucBssIndex, prBssInfo->u2ObssScanInterval); + + cnmTimerStartTimer(prAdapter, &prBssInfo->rObssScanTimer, + prBssInfo-> + u2ObssScanInterval * MSEC_PER_SEC); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +static void rlmObssScanTimeout(struct ADAPTER *prAdapter, + unsigned long ulParamPtr) +{ + struct BSS_INFO *prBssInfo; + + prBssInfo = (struct BSS_INFO *) ulParamPtr; + ASSERT(prBssInfo); + +#if CFG_ENABLE_WIFI_DIRECT + /* AP mode */ + if (prAdapter->fgIsP2PRegistered && + (IS_NET_ACTIVE(prAdapter, prBssInfo->ucBssIndex)) && + (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { + + prBssInfo->fgObssActionForcedTo20M = FALSE; + + /* Check if Beacon content need to be updated */ + rlmUpdateParamsForAP(prAdapter, prBssInfo, FALSE); + + return; + } +#if CFG_SUPPORT_WFD + /* WFD streaming */ + else { + struct WFD_CFG_SETTINGS *prWfdCfgSettings = + &prAdapter->rWifiVar.rWfdConfigureSettings; + + /* If WFD is enabled & connected */ + if (prWfdCfgSettings->ucWfdEnable) { + + /* Skip OBSS scan */ + prBssInfo->u2ObssScanInterval = 0; + DBGLOG(RLM, INFO, "WFD is running. Stop OBSS scan.\n"); + return; + } /* WFD is enabled */ + } +#endif +#endif /* end of CFG_ENABLE_WIFI_DIRECT */ + + /* STA mode */ + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE || + !RLM_NET_PARAM_VALID(prBssInfo) || + prBssInfo->u2ObssScanInterval == 0) { + DBGLOG(RLM, WARN, + "OBSS Scan timeout (NetIdx=%d) -- Aborted!!\n", + prBssInfo->ucBssIndex); + return; + } + + rlmObssTriggerScan(prAdapter, prBssInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rlmObssTriggerScan(struct ADAPTER *prAdapter, struct BSS_INFO *prBssInfo) +{ + struct MSG_SCN_SCAN_REQ_V2 *prScanReqMsg; + + ASSERT(prBssInfo); + + prScanReqMsg = (struct MSG_SCN_SCAN_REQ_V2 *) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_SCN_SCAN_REQ_V2)); + ASSERT(prScanReqMsg); + + if (!prScanReqMsg) { + DBGLOG(RLM, WARN, "No buf for OBSS scan (NetIdx=%d)!!\n", + prBssInfo->ucBssIndex); + + 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 + */ + kalMemZero(prScanReqMsg, sizeof(struct MSG_SCN_SCAN_REQ_V2)); + prScanReqMsg->rMsgHdr.eMsgId = MID_RLM_SCN_SCAN_REQ_V2; + prScanReqMsg->ucSeqNum = 0x33; + prScanReqMsg->ucBssIndex = prBssInfo->ucBssIndex; + prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_WILDCARD; + prScanReqMsg->ucSSIDNum = 0; + prScanReqMsg->eScanChannel = SCAN_CHANNEL_2G4; + prScanReqMsg->u2IELen = 0; + + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *) prScanReqMsg, + MSG_SEND_METHOD_BUF); + + DBGLOG(RLM, INFO, "Timeout to trigger OBSS scan (NetIdx=%d)!!\n", + prBssInfo->ucBssIndex); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/rlm_protection.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/rlm_protection.c new file mode 100644 index 0000000000000..b6375a44c5abc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/rlm_protection.c @@ -0,0 +1,105 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/ + * rlm_protection.c#1 + */ + +/*! \file "rlm_protection.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 + ******************************************************************************* + */ + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/roaming_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/roaming_fsm.c new file mode 100644 index 0000000000000..e55fe8168aabf --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/roaming_fsm.c @@ -0,0 +1,796 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: + */ + +/*! \file "roaming_fsm.c" + * \brief This file defines the FSM for Roaming MODULE. + * + * This file defines the FSM for Roaming MODULE. + */ + + +/******************************************************************************* + * C O M P I L E 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 + ******************************************************************************* + */ +static uint8_t *apucDebugRoamingState[ROAMING_STATE_NUM] = { + (uint8_t *) DISP_STRING("IDLE"), + (uint8_t *) DISP_STRING("DECISION"), + (uint8_t *) DISP_STRING("DISCOVERY"), + (uint8_t *) DISP_STRING("REQ_CAND_LIST"), + (uint8_t *) DISP_STRING("ROAM") +}; + + +/******************************************************************************* + * M A 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 void roamingWaitCandidateTimeout(IN struct ADAPTER *prAdapter, + unsigned long ulParamPtr) +{ + DBGLOG(ROAMING, INFO, + "Time out, Waiting for neighbor response"); + + roamingFsmSteps(prAdapter, ROAMING_STATE_DISCOVERY); +} +/*----------------------------------------------------------------------------*/ +/*! + * @brief Initialize the value in ROAMING_FSM_INFO_T for ROAMING FSM operation + * + * @param [IN P_ADAPTER_T] prAdapter + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void roamingFsmInit(IN struct ADAPTER *prAdapter) +{ + struct ROAMING_INFO *prRoamingFsmInfo; + struct CONNECTION_SETTINGS *prConnSettings; + + DBGLOG(ROAMING, LOUD, + "->roamingFsmInit(): Current Time = %d\n", + kalGetTimeTick()); + + prRoamingFsmInfo = (struct ROAMING_INFO *) & + (prAdapter->rWifiVar.rRoamingInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* 4 <1> Initiate FSM */ + prRoamingFsmInfo->fgIsEnableRoaming = + prConnSettings->fgIsEnableRoaming; + prRoamingFsmInfo->eCurrentState = ROAMING_STATE_IDLE; + prRoamingFsmInfo->rRoamingDiscoveryUpdateTime = 0; + prRoamingFsmInfo->fgDrvRoamingAllow = TRUE; + cnmTimerInitTimer(prAdapter, &prRoamingFsmInfo->rWaitCandidateTimer, + (PFN_MGMT_TIMEOUT_FUNC)roamingWaitCandidateTimeout, + (unsigned long)NULL); +} /* 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 struct ADAPTER *prAdapter) +{ + struct ROAMING_INFO *prRoamingFsmInfo; + + DBGLOG(ROAMING, LOUD, + "->roamingFsmUninit(): Current Time = %d\n", + kalGetTimeTick()); + + prRoamingFsmInfo = (struct ROAMING_INFO *) & + (prAdapter->rWifiVar.rRoamingInfo); + + prRoamingFsmInfo->eCurrentState = ROAMING_STATE_IDLE; + cnmTimerStopTimer(prAdapter, &prRoamingFsmInfo->rWaitCandidateTimer); +} /* 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 struct ADAPTER *prAdapter, + IN struct CMD_ROAMING_TRANSIT *prTransit) +{ + struct ROAMING_INFO *prRoamingFsmInfo; + uint32_t rStatus; + + DBGLOG(ROAMING, LOUD, + "->roamingFsmSendCmd(): Current Time = %d\n", + kalGetTimeTick()); + + prRoamingFsmInfo = (struct ROAMING_INFO *) & + (prAdapter->rWifiVar.rRoamingInfo); + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_ROAMING_TRANSIT, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(struct CMD_ROAMING_TRANSIT), + /* u4SetQueryInfoLen */ + (uint8_t *)prTransit, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + /* ASSERT(rStatus == WLAN_STATUS_PENDING); */ +} /* end of roamingFsmSendCmd() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Update the recent time when ScanDone occurred + * + * @param [IN P_ADAPTER_T] prAdapter + * + * @return none + */ +/*----------------------------------------------------------------------------*/ +void roamingFsmScanResultsUpdate(IN struct ADAPTER + *prAdapter) +{ + struct ROAMING_INFO *prRoamingFsmInfo; + + prRoamingFsmInfo = (struct ROAMING_INFO *) & + (prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + + DBGLOG(ROAMING, LOUD, + "->roamingFsmScanResultsUpdate(): Current Time = %d\n", + kalGetTimeTick()); + + GET_CURRENT_SYSTIME( + &prRoamingFsmInfo->rRoamingDiscoveryUpdateTime); +} /* end of roamingFsmScanResultsUpdate() */ + +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP +/*----------------------------------------------------------------------------*/ +/* + * @brief Check if need to do scan for roaming + * + * @param[out] fgIsNeedScan Set to TRUE if need to scan since + * there is roaming candidate in current scan result + * or skip roaming times > limit times + * @return + */ +/*----------------------------------------------------------------------------*/ +static u_int8_t roamingFsmIsNeedScan(IN struct ADAPTER + *prAdapter) +{ + struct SCAN_INFO *prScanInfo; + struct LINK *prRoamBSSDescList; + struct ROAM_BSS_DESC *prRoamBssDesc; + struct BSS_INFO *prAisBssInfo; + struct BSS_DESC *prBssDesc; + /*CMD_SW_DBG_CTRL_T rCmdSwCtrl;*/ + struct CMD_ROAMING_SKIP_ONE_AP rCmdRoamingSkipOneAP; + u_int8_t fgIsNeedScan, fgIsRoamingSSID; + + fgIsNeedScan = FALSE; + + /*Whether there's roaming candidate in RoamBssDescList*/ + fgIsRoamingSSID = FALSE; + + kalMemZero(&rCmdRoamingSkipOneAP, + sizeof(struct CMD_ROAMING_SKIP_ONE_AP)); + + prAisBssInfo = prAdapter->prAisBssInfo; + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prRoamBSSDescList = &prScanInfo->rRoamBSSDescList; + /* <1> Count same BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prRoamBssDesc, prRoamBSSDescList, + rLinkEntry, struct ROAM_BSS_DESC) { + if (EQUAL_SSID(prRoamBssDesc->aucSSID, + prRoamBssDesc->ucSSIDLen, + prAisBssInfo->aucSSID, + prAisBssInfo->ucSSIDLen)) { + fgIsRoamingSSID = TRUE; + fgIsNeedScan = TRUE; + DBGLOG(ROAMING, INFO, + "roamingFsmSteps: IsRoamingSSID:%d\n", + fgIsRoamingSSID); + break; + } + } + + /* <2> Start skip roaming scan mechanism + * if there is no candidate in current SCAN result list + */ + if (!fgIsRoamingSSID) { + /* Get current BssDesc */ + prBssDesc = prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc; + if (prBssDesc) { + + /*rCmdSwCtrl.u4Id = 0xa0280000;*/ + /*rCmdSwCtrl.u4Data = 0x1;*/ + rCmdRoamingSkipOneAP.fgIsRoamingSkipOneAP = 1; + + DBGLOG(ROAMING, INFO, + "roamingFsmSteps: RCPI:%d RoamSkipTimes:%d\n", + prBssDesc->ucRCPI, + prAisBssInfo->ucRoamSkipTimes); + if (prBssDesc->ucRCPI > + 90) { /* Set parameters related to Good Area */ + prAisBssInfo->ucRoamSkipTimes = 3; + prAisBssInfo->fgGoodRcpiArea = TRUE; + prAisBssInfo->fgPoorRcpiArea = FALSE; + } else { + if (prAisBssInfo->fgGoodRcpiArea) { + prAisBssInfo->ucRoamSkipTimes--; + } else if (prBssDesc->ucRCPI > 67) { + if (!prAisBssInfo->fgPoorRcpiArea) { + /*Set parameters related to Poor Area*/ + prAisBssInfo->ucRoamSkipTimes + = 2; + prAisBssInfo->fgPoorRcpiArea + = TRUE; + prAisBssInfo->fgGoodRcpiArea + = FALSE; + } else { + prAisBssInfo->ucRoamSkipTimes--; + } + } else { + prAisBssInfo->fgPoorRcpiArea = FALSE; + prAisBssInfo->fgGoodRcpiArea = FALSE; + prAisBssInfo->ucRoamSkipTimes--; + } + } + + if (prAisBssInfo->ucRoamSkipTimes == 0) { + prAisBssInfo->ucRoamSkipTimes = 3; + prAisBssInfo->fgPoorRcpiArea = FALSE; + prAisBssInfo->fgGoodRcpiArea = FALSE; + DBGLOG(ROAMING, INFO, + "roamingFsmSteps: Need Scan\n"); + fgIsNeedScan = TRUE; + } else + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_ROAMING_SKIP, + TRUE, + FALSE, + FALSE, NULL, NULL, + sizeof(struct CMD_ROAMING_SKIP_ONE_AP), + (uint8_t *)&rCmdRoamingSkipOneAP, NULL, 0); + } else + DBGLOG(ROAMING, WARN, + "Target BssDesc in AisFsmInfo is NULL\n"); + } + + return fgIsNeedScan; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN enum ENUM_ROAMING_STATE eNextState) +{ + struct ROAMING_INFO *prRoamingFsmInfo; + enum ENUM_ROAMING_STATE ePreviousState; + u_int8_t fgIsTransition = (u_int8_t) FALSE; + u_int8_t fgIsNeedScan = FALSE; +#if CFG_SUPPORT_NCHO + uint32_t u4ScnResultsTimeout = + ROAMING_DISCOVERY_TIMEOUT_SEC; + uint32_t u4ReqScan = FALSE; +#endif + + prRoamingFsmInfo = (struct ROAMING_INFO *) & + (prAdapter->rWifiVar.rRoamingInfo); + + do { + + /* Do entering Next State */ + DBGLOG(ROAMING, STATE, + "[ROAMING]TRANSITION: [%s] -> [%s]\n", + apucDebugRoamingState[prRoamingFsmInfo->eCurrentState], + apucDebugRoamingState[eNextState]); + + /* NOTE(Kevin): This is the only place to + * change the eCurrentState(except initial) + */ + ePreviousState = prRoamingFsmInfo->eCurrentState; + prRoamingFsmInfo->eCurrentState = eNextState; + + fgIsTransition = (u_int8_t) 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: { +#if CFG_SUPPORT_NCHO + if (prAdapter->rNchoInfo.fgECHOEnabled == TRUE) { + u4ScnResultsTimeout = + prAdapter->rNchoInfo.u4RoamScanPeriod; + DBGLOG(ROAMING, TRACE, + "NCHO u4ScnResultsTimeout is %d\n", + u4ScnResultsTimeout); + } + + if (CHECK_FOR_TIMEOUT(kalGetTimeTick(), + prRoamingFsmInfo->rRoamingDiscoveryUpdateTime, + SEC_TO_SYSTIME(u4ScnResultsTimeout))) { + DBGLOG(ROAMING, LOUD, + "DiscoveryUpdateTime Timeout"); + u4ReqScan = TRUE; + } else { + DBGLOG(ROAMING, LOUD, + "DiscoveryUpdateTime Updated"); + u4ReqScan = FALSE; + } + aisFsmRunEventRoamingDiscovery(prAdapter, u4ReqScan); +#else + OS_SYSTIME rCurrentTime; +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + fgIsNeedScan = roamingFsmIsNeedScan(prAdapter); +#else + fgIsNeedScan = TRUE; +#endif + + cnmTimerStopTimer( + prAdapter, + &prRoamingFsmInfo->rWaitCandidateTimer); + + GET_CURRENT_SYSTIME(&rCurrentTime); + if (CHECK_FOR_TIMEOUT(rCurrentTime, + prRoamingFsmInfo->rRoamingDiscoveryUpdateTime, + SEC_TO_SYSTIME(ROAMING_DISCOVERY_TIMEOUT_SEC)) + && fgIsNeedScan) { + DBGLOG(ROAMING, LOUD, + "roamingFsmSteps: DiscoveryUpdateTime Timeout\n"); + aisFsmRunEventRoamingDiscovery(prAdapter, + TRUE); + } else { + DBGLOG(ROAMING, LOUD, + "roamingFsmSteps: DiscoveryUpdateTime Updated\n"); + aisFsmRunEventRoamingDiscovery(prAdapter, + FALSE); + } +#endif /* CFG_SUPPORT_NCHO */ + } + break; + case ROAMING_STATE_REQ_CAND_LIST: + { +#if CFG_SUPPORT_802_11K + struct BSS_INFO *prBssInfo = prAdapter->prAisBssInfo; + struct BSS_DESC *prBssDesc = + prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc; + /* if AP supports Neighbor AP report, then it can used + ** to assist roaming candicate selection + */ + if (prBssInfo && prBssInfo->prStaRecOfAP) { + if (prBssDesc && + (prBssDesc->aucRrmCap[0] & + BIT(RRM_CAP_INFO_NEIGHBOR_REPORT_BIT))) { + aisSendNeighborRequest(prAdapter); + cnmTimerStartTimer( + prAdapter, + &prRoamingFsmInfo + ->rWaitCandidateTimer, + 100); + } + } +#endif + fgIsTransition = TRUE; + eNextState = ROAMING_STATE_DISCOVERY; + 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 struct ADAPTER *prAdapter) +{ + struct ROAMING_INFO *prRoamingFsmInfo; + enum ENUM_ROAMING_STATE eNextState; + struct BSS_INFO *prAisBssInfo; + struct CMD_ROAMING_TRANSIT rTransit; + + prRoamingFsmInfo = (struct ROAMING_INFO *) & + (prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + + prAisBssInfo = prAdapter->prAisBssInfo; + if (prAisBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + return; + + DBGLOG(ROAMING, EVENT, + "EVENT-ROAMING START: Current Time = %d\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) { + rTransit.u2Event = ROAMING_EVENT_START; + rTransit.u2Data = prAisBssInfo->ucBssIndex; + roamingFsmSendCmd(prAdapter, + (struct CMD_ROAMING_TRANSIT *) &rTransit); + + /* Step to next state */ + roamingFsmSteps(prAdapter, eNextState); + } +} /* end of roamingFsmRunEventStart() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Transit to Discovery state when deciding to find a candidate + * + * @param [IN P_ADAPTER_T] prAdapter + * + * @return none + */ +/*----------------------------------------------------------------------------*/ +void roamingFsmRunEventDiscovery(IN struct ADAPTER *prAdapter, + IN struct CMD_ROAMING_TRANSIT *prTransit) +{ + struct ROAMING_INFO *prRoamingFsmInfo; + enum ENUM_ROAMING_STATE eNextState; + + prRoamingFsmInfo = (struct ROAMING_INFO *) & + (prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + DBGLOG(ROAMING, EVENT, + "EVENT-ROAMING DISCOVERY: Current Time = %d\n", + kalGetTimeTick()); + + /* DECISION -> DISCOVERY */ + /* Errors as IDLE, DISCOVERY, ROAM -> DISCOVERY */ + if (prRoamingFsmInfo->eCurrentState != + ROAMING_STATE_DECISION) + return; + + eNextState = ROAMING_STATE_REQ_CAND_LIST; + /* DECISION -> DISCOVERY */ + if (eNextState != prRoamingFsmInfo->eCurrentState) { + struct BSS_INFO *prAisBssInfo; + struct BSS_DESC *prBssDesc; + uint8_t arBssid[PARAM_MAC_ADDR_LEN]; + struct PARAM_SSID rSsid; + struct AIS_FSM_INFO *prAisFsmInfo; + struct CONNECTION_SETTINGS *prConnSettings; + + kalMemZero(&rSsid, sizeof(struct PARAM_SSID)); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* sync. rcpi with firmware */ + prAisBssInfo = + &(prAdapter->rWifiVar.arBssInfoPool[NETWORK_TYPE_AIS]); + prBssDesc = prAisFsmInfo->prTargetBssDesc; + if (prBssDesc) { + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + COPY_MAC_ADDR(arBssid, prBssDesc->aucBSSID); + } else { + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, + prConnSettings->aucSSID, + prConnSettings->ucSSIDLen); + COPY_MAC_ADDR(arBssid, prConnSettings->aucBSSID); + } + prBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, + arBssid, TRUE, &rSsid); + if (prBssDesc) { + prBssDesc->ucRCPI = (uint8_t)(prTransit->u2Data & 0xff); + DBGLOG(ROAMING, INFO, "ucRCPI %u\n", + prBssDesc->ucRCPI); + } + roamingFsmSteps(prAdapter, eNextState); + } +} /* end of roamingFsmRunEventDiscovery() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Transit to Roam state after Scan Done + * + * @param [IN P_ADAPTER_T] prAdapter + * + * @return none + */ +/*----------------------------------------------------------------------------*/ +void roamingFsmRunEventRoam(IN struct ADAPTER *prAdapter) +{ + struct ROAMING_INFO *prRoamingFsmInfo; + enum ENUM_ROAMING_STATE eNextState; + struct CMD_ROAMING_TRANSIT rTransit; + + prRoamingFsmInfo = (struct ROAMING_INFO *) & + (prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + + DBGLOG(ROAMING, EVENT, + "EVENT-ROAMING ROAM: Current Time = %d\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) { + rTransit.u2Event = ROAMING_EVENT_ROAM; + roamingFsmSendCmd(prAdapter, + (struct CMD_ROAMING_TRANSIT *) &rTransit); + + /* Step to next state */ + roamingFsmSteps(prAdapter, eNextState); + } +} /* end of roamingFsmRunEventRoam() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Transit to Decision state as being failed to find out any candidate + * + * @param [IN P_ADAPTER_T] prAdapter + * + * @return none + */ +/*----------------------------------------------------------------------------*/ +void roamingFsmRunEventFail(IN struct ADAPTER *prAdapter, + IN uint32_t u4Param) +{ + struct ROAMING_INFO *prRoamingFsmInfo; + enum ENUM_ROAMING_STATE eNextState; + struct CMD_ROAMING_TRANSIT rTransit; + + prRoamingFsmInfo = (struct ROAMING_INFO *) & + (prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + + DBGLOG(ROAMING, STATE, + "EVENT-ROAMING FAIL: reason %x Current Time = %d\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) { + rTransit.u2Event = ROAMING_EVENT_FAIL; + rTransit.u2Data = (uint16_t) (u4Param & 0xffff); + roamingFsmSendCmd(prAdapter, + (struct CMD_ROAMING_TRANSIT *) &rTransit); + + /* Step to next state */ + roamingFsmSteps(prAdapter, eNextState); + } +} /* end of roamingFsmRunEventFail() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Transit to Idle state as beging aborted by other moduels, AIS + * + * @param [IN P_ADAPTER_T] prAdapter + * + * @return none + */ +/*----------------------------------------------------------------------------*/ +void roamingFsmRunEventAbort(IN struct ADAPTER *prAdapter) +{ + struct ROAMING_INFO *prRoamingFsmInfo; + enum ENUM_ROAMING_STATE eNextState; + struct CMD_ROAMING_TRANSIT rTransit; + + prRoamingFsmInfo = (struct ROAMING_INFO *) & + (prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + + DBGLOG(ROAMING, EVENT, + "EVENT-ROAMING ABORT: Current Time = %d\n", + kalGetTimeTick()); + + eNextState = ROAMING_STATE_IDLE; + /* IDLE, DECISION, DISCOVERY, ROAM -> IDLE */ + if (eNextState != prRoamingFsmInfo->eCurrentState) { + rTransit.u2Event = ROAMING_EVENT_ABORT; + roamingFsmSendCmd(prAdapter, + (struct CMD_ROAMING_TRANSIT *) &rTransit); + + /* Step to next state */ + roamingFsmSteps(prAdapter, eNextState); + } +} /* end of roamingFsmRunEventAbort() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Process events from firmware + * + * @param [IN P_ADAPTER_T] prAdapter + * [IN P_ROAMING_PARAM_T] prParam + * + * @return none + */ +/*----------------------------------------------------------------------------*/ +uint32_t roamingFsmProcessEvent(IN struct ADAPTER *prAdapter, + IN struct CMD_ROAMING_TRANSIT *prTransit) +{ + DBGLOG(ROAMING, LOUD, + "ROAMING Process Events: Current Time = %d\n", + kalGetTimeTick()); + + if (prTransit->u2Event == ROAMING_EVENT_DISCOVERY) { + roamingFsmRunEventDiscovery(prAdapter, prTransit); + +#if 0 + DBGLOG(ROAMING, INFO, + "RX ROAMING_EVENT_DISCOVERY RCPI[%d] Thr[%d] Reason[%d] Time[%ld]\n", + prTransit->u2Data, + prTransit->u2RcpiLowThreshold, + prTransit->eReason, + prTransit->u4RoamingTriggerTime); +#endif + } + + return WLAN_STATUS_SUCCESS; +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/rsn.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/rsn.c new file mode 100644 index 0000000000000..d30f12e867dc6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/rsn.c @@ -0,0 +1,4021 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: mgmt/rsn.c#3 + */ + +/*! \file "rsn.c" + * \brief This file including the 802.11i, wpa and wpa2(rsn) related function. + * + * This file provided the macros and functions library to support + * the wpa/rsn ie parsing, cipher and AKM check to help the AP seleced + * deciding, tkip mic error handler and rsn PMKID support. + */ + +/******************************************************************************* + * C O M P I L E 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 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rsnParseRsnIE(IN struct ADAPTER *prAdapter, + IN struct RSN_INFO_ELEM *prInfoElem, + OUT struct RSN_INFO *prRsnInfo) +{ + uint32_t i; + int32_t u4RemainRsnIeLen; + uint16_t u2Version; + uint16_t u2Cap = 0; + uint32_t u4GroupSuite = RSN_CIPHER_SUITE_CCMP; + uint32_t u4GroupMgmtSuite = 0; + uint16_t u2PairSuiteCount = 0; + uint16_t u2AuthSuiteCount = 0; + uint8_t *pucPairSuite = NULL; + uint8_t *pucAuthSuite = NULL; + uint8_t *cp; +#if CFG_SUPPORT_CFG80211_AUTH + uint16_t u2DesiredPmkidCnt = 0; + uint16_t u2SupportedPmkidCnt = 0; +#endif + + 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 = (uint8_t *) &prInfoElem->u4GroupKeyCipherSuite; + u4RemainRsnIeLen = (int32_t) 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 = (uint32_t) u2PairSuiteCount * 4; + if (u4RemainRsnIeLen < (int32_t) 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 -= (int32_t) 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 = (uint32_t) u2AuthSuiteCount * 4; + if (u4RemainRsnIeLen < (int32_t) 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 -= (int32_t) 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); + cp += 2; + u4RemainRsnIeLen -= 2; + + if (u4RemainRsnIeLen == 0) + break; +#if CFG_SUPPORT_CFG80211_AUTH + /* 9.4.2.25.5 PMKID + * The PMKID Count and List fields are used only in + * the RSNE in the (Re)Association Request frame to an AP + * and in FT authentication sequence frames. + */ + /* Parse PMKID count field */ + if (u4RemainRsnIeLen < 2) { + DBGLOG(RSN, TRACE, + "Fail to parse RSN IE in PMKID (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + WLAN_GET_FIELD_16(cp, &u2DesiredPmkidCnt); + cp += 2; + u4RemainRsnIeLen -= 2; + + if (u2DesiredPmkidCnt > MAX_NUM_SUPPORTED_PMKID) { + u2SupportedPmkidCnt = MAX_NUM_SUPPORTED_PMKID; + DBGLOG(RSN, WARN, + "Support maximum PMKID Cnt = %d with desired PMKID Cnt = %d\n", + MAX_NUM_SUPPORTED_PMKID, u2DesiredPmkidCnt); + } else + u2SupportedPmkidCnt = u2DesiredPmkidCnt; + + /* Parse PMKID List field */ + i = (uint32_t) u2DesiredPmkidCnt * RSN_PMKID_LEN; + if (u4RemainRsnIeLen < (int32_t) i) { + DBGLOG(RSN, TRACE, + "Fail to parse RSN IE in pairwise cipher suite list (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + if (u2SupportedPmkidCnt > 0) { + kalMemCopy(prRsnInfo->aucPmkidList, cp, + (u2SupportedPmkidCnt * RSN_PMKID_LEN)); + + DBGLOG(RSN, INFO, "== Dump cached PMKIDs ==\n"); + DBGLOG_MEM8(RSN, INFO, prRsnInfo->aucPmkidList, + (u2SupportedPmkidCnt * RSN_PMKID_LEN)); + } + cp += u2DesiredPmkidCnt * RSN_PMKID_LEN; + u4RemainRsnIeLen -= + (int32_t)(u2DesiredPmkidCnt * RSN_PMKID_LEN); + + if (u4RemainRsnIeLen == 0) + break; +#endif + + /* Parse Group Mgmt Cipher Suite field */ + if (u4RemainRsnIeLen < 4) { + DBGLOG(RSN, TRACE, + "Fail to parse RSN IE in GroupMgmtCipher (IELen: %d)\n", + prInfoElem->ucLength); + /* Continued to connect + * when PMKID List field is truncated. + */ + break; + } + WLAN_GET_FIELD_32(cp, &u4GroupMgmtSuite); + } while (FALSE); + + /* Save the RSN information for the BSS. */ + prRsnInfo->ucElemId = ELEM_ID_RSN; + + prRsnInfo->ucRsneLen = prInfoElem->ucLength; + + prRsnInfo->u2Version = u2Version; + + prRsnInfo->u4GroupKeyCipherSuite = u4GroupSuite; + + prRsnInfo->u4GroupMgmtKeyCipherSuite = u4GroupMgmtSuite; + +#if CFG_SUPPORT_CFG80211_AUTH + prRsnInfo->u2PmkidCnt = u2SupportedPmkidCnt; +#endif + + DBGLOG(RSN, LOUD, + "RSN: version %d, group mgmt key cipher suite %02x-%02x-%02x-%02x\n", + u2Version, (uint8_t) (u4GroupMgmtSuite & 0x000000FF), + (uint8_t) ((u4GroupMgmtSuite >> 8) & 0x000000FF), + (uint8_t) ((u4GroupMgmtSuite >> 16) & 0x000000FF), + (uint8_t) ((u4GroupMgmtSuite >> 24) & 0x000000FF)); + + DBGLOG(RSN, LOUD, + "RSN: version %d, group key cipher suite %02x-%02x-%02x-%02x\n", + u2Version, (uint8_t) (u4GroupSuite & 0x000000FF), + (uint8_t) ((u4GroupSuite >> 8) & 0x000000FF), + (uint8_t) ((u4GroupSuite >> 16) & 0x000000FF), + (uint8_t) ((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 = + (uint32_t) u2PairSuiteCount; + + for (i = 0; i < (uint32_t) 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", + (uint8_t) i, + (uint8_t) (prRsnInfo->au4PairwiseKeyCipherSuite + [i] + & 0x000000FF), + (uint8_t) ((prRsnInfo->au4PairwiseKeyCipherSuite + [i] >> 8) + & 0x000000FF), + (uint8_t) ((prRsnInfo->au4PairwiseKeyCipherSuite + [i] >> 16) + & 0x000000FF), + (uint8_t) ((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", + (uint8_t) (prRsnInfo->au4PairwiseKeyCipherSuite[0] + & 0x000000FF), + (uint8_t) ((prRsnInfo->au4PairwiseKeyCipherSuite[0] >> 8) + & 0x000000FF), + (uint8_t) ((prRsnInfo->au4PairwiseKeyCipherSuite[0] >> + 16) + & 0x000000FF), + (uint8_t) ((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 = (uint32_t) + u2AuthSuiteCount; + + for (i = 0; i < (uint32_t) u2AuthSuiteCount; i++) { + WLAN_GET_FIELD_32(pucAuthSuite, + &prRsnInfo->au4AuthKeyMgtSuite[i]); + pucAuthSuite += 4; + + DBGLOG(RSN, LOUD, + "RSN: AKM suite [%d]: %02x-%02x-%02x-%02x\n", + (uint8_t) i, + (uint8_t) (prRsnInfo->au4AuthKeyMgtSuite[i] + & 0x000000FF), + (uint8_t) ((prRsnInfo->au4AuthKeyMgtSuite[i] >> + 8) + & 0x000000FF), + (uint8_t) ((prRsnInfo->au4AuthKeyMgtSuite[i] >> + 16) + & 0x000000FF), + (uint8_t) ((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", + (uint8_t) (prRsnInfo->au4AuthKeyMgtSuite[0] & + 0x000000FF), + (uint8_t) ((prRsnInfo->au4AuthKeyMgtSuite[0] >> 8) + & 0x000000FF), + (uint8_t) ((prRsnInfo->au4AuthKeyMgtSuite[0] >> 16) + & 0x000000FF), + (uint8_t) ((prRsnInfo->au4AuthKeyMgtSuite[0] >> 24) + & 0x000000FF)); + } + + prRsnInfo->u2RsnCap = u2Cap; + prRsnInfo->fgRsnCapPresent = TRUE; + 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. + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rsnParseWpaIE(IN struct ADAPTER *prAdapter, + IN struct WPA_INFO_ELEM *prInfoElem, + OUT struct RSN_INFO *prWpaInfo) +{ + uint32_t i; + int32_t u4RemainWpaIeLen; + uint16_t u2Version; + uint16_t u2Cap = 0; + uint32_t u4GroupSuite = WPA_CIPHER_SUITE_TKIP; + uint16_t u2PairSuiteCount = 0; + uint16_t u2AuthSuiteCount = 0; + uint8_t *pucPairSuite = NULL; + uint8_t *pucAuthSuite = NULL; + uint8_t *cp; + u_int8_t 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 = (uint8_t *) &prInfoElem->u4GroupKeyCipherSuite; + u4RemainWpaIeLen = (int32_t) 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 = (uint32_t) u2PairSuiteCount * 4; + if (u4RemainWpaIeLen < (int32_t) 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 -= (int32_t) 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 = (uint32_t) u2AuthSuiteCount * 4; + if (u4RemainWpaIeLen < (int32_t) 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 -= (int32_t) 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, (uint8_t) (u4GroupSuite & 0x000000FF), + (uint8_t) ((u4GroupSuite >> 8) & 0x000000FF), + (uint8_t) ((u4GroupSuite >> 16) & 0x000000FF), + (uint8_t) ((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 = + (uint32_t) u2PairSuiteCount; + + for (i = 0; i < (uint32_t) 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", + (uint8_t) i, + (uint8_t) (prWpaInfo->au4PairwiseKeyCipherSuite + [i] + & 0x000000FF), + (uint8_t) ((prWpaInfo->au4PairwiseKeyCipherSuite + [i] >> 8) + & 0x000000FF), + (uint8_t) ((prWpaInfo->au4PairwiseKeyCipherSuite + [i] >> 16) + & 0x000000FF), + (uint8_t) ((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", + (uint8_t) (prWpaInfo->au4PairwiseKeyCipherSuite[0] + & 0x000000FF), + (uint8_t) ((prWpaInfo->au4PairwiseKeyCipherSuite[0] >> 8) + & 0x000000FF), + (uint8_t) ((prWpaInfo->au4PairwiseKeyCipherSuite[0] >> + 16) + & 0x000000FF), + (uint8_t) ((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 = (uint32_t) + u2AuthSuiteCount; + + for (i = 0; i < (uint32_t) u2AuthSuiteCount; i++) { + WLAN_GET_FIELD_32(pucAuthSuite, + &prWpaInfo->au4AuthKeyMgtSuite[i]); + pucAuthSuite += 4; + + DBGLOG(RSN, LOUD, + "WPA: AKM suite [%d]: %02x-%02x-%02x-%02x\n", + (uint8_t) i, + (uint8_t)(prWpaInfo->au4AuthKeyMgtSuite[i] + & 0x000000FF), + (uint8_t)((prWpaInfo->au4AuthKeyMgtSuite[i]>>8) + & 0x000000FF), + (uint8_t)((prWpaInfo->au4AuthKeyMgtSuite[i]>>16) + & 0x000000FF), + (uint8_t)((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", + (uint8_t)(prWpaInfo->au4AuthKeyMgtSuite[0] + & 0x000000FF), + (uint8_t)((prWpaInfo->au4AuthKeyMgtSuite[0]>>8) + & 0x000000FF), + (uint8_t)((prWpaInfo->au4AuthKeyMgtSuite[0]>>16) + & 0x000000FF), + (uint8_t)((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. + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rsnSearchSupportedCipher(IN struct ADAPTER *prAdapter, + IN uint32_t u4Cipher, OUT uint32_t *pu4Index) +{ + uint8_t i; + struct 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rsnIsSuitableBSS(IN struct ADAPTER *prAdapter, + IN struct RSN_INFO *prBssRsnInfo) +{ + uint8_t i = 0; + + DEBUGFUNC("rsnIsSuitableBSS"); + + if ((prAdapter->rWifiVar.rConnSettings.rRsnInfo.u4GroupKeyCipherSuite + & 0x000000FF) != + GET_SELECTOR_TYPE(prBssRsnInfo->u4GroupKeyCipherSuite)) { + DBGLOG(RSN, WARN, "Break by GroupKeyCipherSuite\n"); + return FALSE; + } + + for (i = 0; i < prBssRsnInfo->u4PairwiseKeyCipherSuiteCount; + i++) { + if ((prAdapter->rWifiVar.rConnSettings. + rRsnInfo.au4PairwiseKeyCipherSuite[0] + & 0x000000FF) == + GET_SELECTOR_TYPE( + prBssRsnInfo->au4PairwiseKeyCipherSuite[i])) { + break; + } else if (i == + prBssRsnInfo->u4PairwiseKeyCipherSuiteCount - 1) { + DBGLOG(RSN, WARN, "Break by PairwiseKeyCipherSuite\n"); + return FALSE; + } + } + + for (i = 0; i < prBssRsnInfo->u4AuthKeyMgtSuiteCount; i++) { + if ((prAdapter->rWifiVar.rConnSettings. + rRsnInfo.au4AuthKeyMgtSuite[0] + & 0x000000FF) == + GET_SELECTOR_TYPE( + prBssRsnInfo->au4AuthKeyMgtSuite[i])) { + break; + } else if (i == prBssRsnInfo->u4AuthKeyMgtSuiteCount - 1) { + DBGLOG(RSN, WARN, "Break by AuthKeyMgtSuite\n"); + return FALSE; + } + } + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * + * \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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rsnSearchAKMSuite(IN struct ADAPTER *prAdapter, + IN uint32_t u4AkmSuite, OUT uint32_t *pu4Index) +{ + uint8_t i; + struct 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. + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rsnPerformPolicySelection( + IN struct ADAPTER *prAdapter, IN struct BSS_DESC *prBss) +{ +#if CFG_SUPPORT_802_11W + int32_t i; + uint32_t j; +#else + uint32_t i, j; +#endif + u_int8_t fgSuiteSupported; + uint32_t u4PairwiseCipher = 0; + uint32_t u4GroupCipher = 0; + uint32_t u4AkmSuite = 0; + struct RSN_INFO *prBssRsnInfo; + uint8_t ucBssIndex; + u_int8_t fgIsWpsActive = (u_int8_t) FALSE; + + DEBUGFUNC("rsnPerformPolicySelection"); + + ASSERT(prBss); + + DBGLOG(RSN, TRACE, "rsnPerformPolicySelection\n"); + /* Todo:: */ + ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + + prBss->u4RsnSelectedPairwiseCipher = 0; + prBss->u4RsnSelectedGroupCipher = 0; + prBss->u4RsnSelectedAKMSuite = 0; + prBss->ucEncLevel = 0; + + prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = FALSE; + +#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, INFO, "-- 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, INFO, "-- No Protected BSS\n"); + return TRUE; + } + DBGLOG(RSN, INFO, "-- Protected BSS but No need\n"); + return FALSE; + } + + /* Protection is required in this BSS. */ + if ((prBss->u2CapInfo & CAP_INFO_PRIVACY) != 0) { + if (secEnabledInAis(prAdapter) == FALSE) { + DBGLOG(RSN, INFO, "-- 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, INFO, + "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 || + prAdapter->rWifiVar.rConnSettings.eAuthMode == + AUTH_MODE_WPA2_FT_PSK || + prAdapter->rWifiVar.rConnSettings.eAuthMode == + AUTH_MODE_WPA2_FT +#if CFG_SUPPORT_SAE + || prAdapter->rWifiVar.rConnSettings.eAuthMode + == AUTH_MODE_WPA2_SAE +#endif + ) { + if (prBss->fgIERSN) { + prBssRsnInfo = &prBss->rRSNInfo; + } else { + DBGLOG(RSN, INFO, + "RSN Information Element does not exist.\n"); + return FALSE; + } +#if CFG_SUPPORT_PASSPOINT + } else if (prAdapter->rWifiVar.rConnSettings.eAuthMode == + AUTH_MODE_WPA_OSEN) { + /* OSEN is mutual exclusion with RSN, + * so we can reuse RSN's flag and variables + */ + if (prBss->fgIEOsen) { + prBssRsnInfo = &prBss->rRSNInfo; + } else { + DBGLOG(RSN, WARN, + "OSEN Information Element does not exist.\n"); + return FALSE; + } +#endif + } else if (prAdapter->rWifiVar.rConnSettings.eEncStatus != + ENUM_ENCRYPTION1_ENABLED) { + /* If the driver is configured to use WEP only, + * ignore this BSS. + */ + DBGLOG(RSN, INFO, "-- 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, INFO, "-- WEP-only legacy BSS\n"); + return TRUE; + } + + if (!rsnIsSuitableBSS(prAdapter, prBssRsnInfo)) { + /* Support AP Selection */ + DBGLOG(RSN, WARN, "RSN info check no matched,RSN Score [%d]\n", + CFG_SUPPORT_RSN_SCORE); +#if CFG_SUPPORT_RSN_SCORE + prBss->fgIsRSNSuitableBss = FALSE; + } else + prBss->fgIsRSNSuitableBss = TRUE; +#else + + return FALSE; + } +#endif + /* end Support AP Selection */ + + 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) { +#if CFG_SUPPORT_SUITB + case RSN_CIPHER_SUITE_GCMP_256: + if (prAdapter->rWifiVar.rConnSettings.eEncStatus == + ENUM_ENCRYPTION4_ENABLED) + fgSuiteSupported = TRUE; + break; +#endif + 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%08x\n", + prAdapter->rWifiVar.rConnSettings.eEncStatus, + prBssRsnInfo->u4PairwiseKeyCipherSuiteCount, + prBssRsnInfo->au4PairwiseKeyCipherSuite[0]); + /* Select pairwise/group ciphers */ + switch (prAdapter->rWifiVar.rConnSettings.eEncStatus) { +#if CFG_SUPPORT_SUITB + case ENUM_ENCRYPTION4_ENABLED: + for (i = 0; + i < prBssRsnInfo->u4PairwiseKeyCipherSuiteCount; + i++) { + /* TODO: WTBL cipher filed cannot 1-1 mapping + * to spec cipher suite number + */ + if (prBssRsnInfo->au4PairwiseKeyCipherSuite[i] + == RSN_CIPHER_SUITE_GCMP_256) + u4PairwiseCipher = prBssRsnInfo + ->au4PairwiseKeyCipherSuite[i]; + } + u4GroupCipher = prBssRsnInfo->u4GroupKeyCipherSuite; + break; +#endif + case ENUM_ENCRYPTION3_ENABLED: + for (i = 0; i < prBssRsnInfo-> + u4PairwiseKeyCipherSuiteCount; i++) { + if (GET_SELECTOR_TYPE( + prBssRsnInfo-> + au4PairwiseKeyCipherSuite[i]) + == CIPHER_SUITE_CCMP) { + u4PairwiseCipher = + prBssRsnInfo-> + au4PairwiseKeyCipherSuite[i]; + } + } + u4GroupCipher = prBssRsnInfo->u4GroupKeyCipherSuite; + break; + + case ENUM_ENCRYPTION2_ENABLED: + for (i = 0; + i < prBssRsnInfo->u4PairwiseKeyCipherSuiteCount; + i++) { + if (GET_SELECTOR_TYPE + (prBssRsnInfo->au4PairwiseKeyCipherSuite[i]) + == CIPHER_SUITE_TKIP) { + u4PairwiseCipher = + prBssRsnInfo-> + au4PairwiseKeyCipherSuite[i]; + } + } + if (GET_SELECTOR_TYPE + (prBssRsnInfo->u4GroupKeyCipherSuite) + == CIPHER_SUITE_CCMP) + DBGLOG(RSN, TRACE, "Cannot join CCMP BSS\n"); + else + u4GroupCipher = + prBssRsnInfo->u4GroupKeyCipherSuite; + break; + + case ENUM_ENCRYPTION1_ENABLED: + for (i = 0; + i < prBssRsnInfo-> + u4PairwiseKeyCipherSuiteCount; + i++) { + if (GET_SELECTOR_TYPE( + prBssRsnInfo-> + au4PairwiseKeyCipherSuite[i]) + == CIPHER_SUITE_WEP40 || + GET_SELECTOR_TYPE( + prBssRsnInfo-> + au4PairwiseKeyCipherSuite[i]) + == CIPHER_SUITE_WEP104) { + u4PairwiseCipher = prBssRsnInfo-> + au4PairwiseKeyCipherSuite[i]; + } + } + if (GET_SELECTOR_TYPE(prBssRsnInfo-> + u4GroupKeyCipherSuite) + == CIPHER_SUITE_CCMP || + GET_SELECTOR_TYPE(prBssRsnInfo-> + u4GroupKeyCipherSuite) == CIPHER_SUITE_TKIP) { + DBGLOG(RSN, TRACE, + "Cannot join CCMP/TKIP BSS\n"); + } else { + u4GroupCipher = + prBssRsnInfo->u4GroupKeyCipherSuite; + } + break; + + default: + break; + } + } + + /* Exception handler */ + /* If we cannot find proper pairwise and group cipher suites + * to join the BSS, do not check the supported AKM suites. + */ + if (u4PairwiseCipher == 0 || u4GroupCipher == 0) { + DBGLOG(RSN, TRACE, + "Failed to select pairwise/group cipher (0x%08x/0x%08x)\n", + u4PairwiseCipher, u4GroupCipher); + return FALSE; + } +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && + (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType == NETWORK_TYPE_P2P)) { + if (u4PairwiseCipher != RSN_CIPHER_SUITE_CCMP || + u4GroupCipher != RSN_CIPHER_SUITE_CCMP + || u4AkmSuite != RSN_AKM_SUITE_PSK) { + DBGLOG(RSN, TRACE, + "Failed to select pairwise/group cipher for P2P network (0x%08x/0x%08x)\n", + u4PairwiseCipher, u4GroupCipher); + return FALSE; + } + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + if (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType == NETWORK_TYPE_BOW) { + 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%08x/0x%08x)\n", + u4PairwiseCipher, u4GroupCipher); + return FALSE; + } + } +#endif + + /* Verify if selected pairwisse cipher is supported */ + fgSuiteSupported = rsnSearchSupportedCipher(prAdapter, + u4PairwiseCipher, &i); + + /* Verify if selected group cipher is supported */ + if (fgSuiteSupported) + fgSuiteSupported = rsnSearchSupportedCipher(prAdapter, + u4GroupCipher, &i); + + if (!fgSuiteSupported) { + DBGLOG(RSN, TRACE, + "Failed to support selected pairwise/group cipher (0x%08x/0x%08x)\n", + u4PairwiseCipher, u4GroupCipher); + return FALSE; + } + + /* Select AKM */ + /* If the driver cannot support any authentication suites advertised in + * the given BSS, we fail to perform RSNA policy selection. + */ + /* Attempt to find any overlapping supported AKM suite. */ + if (prAdapter->rWifiVar.rConnSettings.eAuthMode == + AUTH_MODE_WPA2_FT_PSK && + rsnSearchAKMSuite(prAdapter, RSN_AKM_SUITE_FT_PSK, &j)) + u4AkmSuite = RSN_AKM_SUITE_FT_PSK; + else if (prAdapter->rWifiVar.rConnSettings.eAuthMode == + AUTH_MODE_WPA2_FT && + rsnSearchAKMSuite(prAdapter, + RSN_AKM_SUITE_FT_802_1X, &j)) + u4AkmSuite = RSN_AKM_SUITE_FT_802_1X; + else +#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", + (uint8_t) (u4PairwiseCipher & 0x000000FF), + (uint8_t) ((u4PairwiseCipher >> 8) & 0x000000FF), + (uint8_t) ((u4PairwiseCipher >> 16) & 0x000000FF), + (uint8_t) ((u4PairwiseCipher >> 24) & 0x000000FF), + (uint8_t) (u4GroupCipher & 0x000000FF), + (uint8_t) ((u4GroupCipher >> 8) & 0x000000FF), + (uint8_t) ((u4GroupCipher >> 16) & 0x000000FF), + (uint8_t) ((u4GroupCipher >> 24) & 0x000000FF)); + + DBGLOG(RSN, TRACE, + "Selected AKM suite: %02x-%02x-%02x-%02x\n", + (uint8_t) (u4AkmSuite & 0x000000FF), + (uint8_t) ((u4AkmSuite >> 8) & 0x000000FF), + (uint8_t) ((u4AkmSuite >> 16) & 0x000000FF), + (uint8_t) ((u4AkmSuite >> 24) & 0x000000FF)); + +#if CFG_SUPPORT_802_11W + DBGLOG(RSN, TRACE, "[MFP] MFP setting = %d\n ", + kalGetMfpSetting(prAdapter->prGlueInfo)); + + if (kalGetMfpSetting(prAdapter->prGlueInfo) == + RSN_AUTH_MFP_REQUIRED) { + if (!prBssRsnInfo->fgRsnCapPresent) { + DBGLOG(RSN, TRACE, + "[MFP] Skip RSN IE, No MFP Required Capability.\n"); + return FALSE; + } else if (!(prBssRsnInfo->u2RsnCap & ELEM_WPA_CAP_MFPC)) { + DBGLOG(RSN, WARN, + "[MFP] 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 & (ELEM_WPA_CAP_MFPR | + ELEM_WPA_CAP_MFPC)) + prAdapter->rWifiVar.rAisSpecificBssInfo. + fgMgmtProtection = TRUE; + } else { + if ((prBssRsnInfo->fgRsnCapPresent) && + (prBssRsnInfo->u2RsnCap & ELEM_WPA_CAP_MFPR)) { + DBGLOG(RSN, INFO, + "[MFP] Skip RSN IE, No MFP Required Capability\n"); + return FALSE; + } + } + + DBGLOG(RSN, INFO, + "setting=%d, Cap=%d, CapPresent=%d, MgmtProtection = %d\n", + kalGetMfpSetting(prAdapter->prGlueInfo), + prBssRsnInfo->u2RsnCap, + prBssRsnInfo->fgRsnCapPresent, + prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection); +#endif + + if (GET_SELECTOR_TYPE(u4GroupCipher) == CIPHER_SUITE_CCMP) { + prBss->ucEncLevel = 3; +#if CFG_SUPPORT_SUITB + } else if (u4GroupCipher == RSN_CIPHER_SUITE_GCMP_256) { + prBss->ucEncLevel = 4; +#endif + } 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 struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + uint32_t i; + struct WPA_INFO_ELEM *prWpaIE; + uint32_t u4Suite; + uint16_t u2SuiteCount; + uint8_t *cp, *cp2; + uint8_t ucExpendedLen = 0; + uint8_t *pucBuffer; + uint8_t ucBssIndex; + + DEBUGFUNC("rsnGenerateWpaNoneIE"); + + ASSERT(prMsduInfo); + + if (prAdapter->rWifiVar.rConnSettings.eAuthMode != AUTH_MODE_WPA_NONE) + return; + + ucBssIndex = prMsduInfo->ucBssIndex; + + if (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType != NETWORK_TYPE_AIS) + return; + + pucBuffer = (uint8_t *) ((unsigned long) + prMsduInfo->prPacket + (unsigned long) + prMsduInfo->u2FrameLength); + + ASSERT(pucBuffer); + + prWpaIE = (struct WPA_INFO_ELEM *)(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 = (uint8_t *) &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 = pucBuffer + sizeof(struct WPA_INFO_ELEM); + + /* Fill the Group Key Cipher Suite field as + * the same in pair-wise key. + */ + WLAN_SET_FIELD_32(&prWpaIE->u4GroupKeyCipherSuite, u4Suite); + ucExpendedLen += 4; + + /* Fill the Pairwise Key Cipher Suite Count field. */ + WLAN_SET_FIELD_16(&prWpaIE->u2PairwiseKeyCipherSuiteCount, + u2SuiteCount); + ucExpendedLen += 2; + + cp2 = cp; + + /* Fill the Authentication and Key Management Suite + * List field. + */ + u2SuiteCount = 0; + cp += 2; + + if (rsnSearchAKMSuite(prAdapter, WPA_AKM_SUITE_802_1X, &i)) + u4Suite = WPA_AKM_SUITE_802_1X; + else if (rsnSearchAKMSuite(prAdapter, WPA_AKM_SUITE_PSK, &i)) + u4Suite = WPA_AKM_SUITE_PSK; + else + u4Suite = WPA_AKM_SUITE_NONE; + + /* This shall be the only available value for current implementation */ + ASSERT(u4Suite == WPA_AKM_SUITE_NONE); + + WLAN_SET_FIELD_32(cp, u4Suite); + u2SuiteCount++; + ucExpendedLen += 4; + cp += 4; + + /* Fill the Authentication and Key Management Suite Count field. */ + WLAN_SET_FIELD_16(cp2, u2SuiteCount); + ucExpendedLen += 2; + + /* Fill the Length field. */ + prWpaIE->ucLength = (uint8_t) 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 struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + uint8_t *cp; + uint8_t *pucBuffer; + uint8_t ucBssIndex; + struct BSS_INFO *prBssInfo; + struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo; + + DEBUGFUNC("rsnGenerateWPAIE"); + + ASSERT(prMsduInfo); + + pucBuffer = (uint8_t *) ((unsigned long) + prMsduInfo->prPacket + (unsigned long) + prMsduInfo->u2FrameLength); + + ASSERT(pucBuffer); + + ucBssIndex = prMsduInfo->ucBssIndex; + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + prP2pSpecificBssInfo = + prAdapter->rWifiVar. + prP2pSpecificBssInfo[prBssInfo->u4PrivateData]; + + /* if (eNetworkId != NETWORK_TYPE_AIS_INDEX) */ + /* return; */ + +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered && + GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)-> + eNetworkType == NETWORK_TYPE_P2P && + kalP2PGetTkipCipher(prAdapter->prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData)) || + (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)-> + eNetworkType == NETWORK_TYPE_AIS && + (prAdapter->rWifiVar.rConnSettings.eAuthMode == + AUTH_MODE_WPA || + prAdapter->rWifiVar.rConnSettings.eAuthMode == + AUTH_MODE_WPA_PSK))) { +#else + if (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)-> + eNetworkType == NETWORK_TYPE_AIS && + (prAdapter->rWifiVar.rConnSettings.eAuthMode == + AUTH_MODE_WPA || + prAdapter->rWifiVar.rConnSettings.eAuthMode == + AUTH_MODE_WPA_PSK)) { +#endif + if (prAdapter->fgIsP2PRegistered && prP2pSpecificBssInfo + && (prP2pSpecificBssInfo->u2WpaIeLen != 0)) { + kalMemCopy(pucBuffer, + prP2pSpecificBssInfo->aucWpaIeBuffer, + prP2pSpecificBssInfo->u2WpaIeLen); + prMsduInfo->u2FrameLength += + prP2pSpecificBssInfo->u2WpaIeLen; + return; + } + /* Construct a WPA IE for association request frame. */ + WPA_IE(pucBuffer)->ucElemId = ELEM_ID_WPA; + WPA_IE(pucBuffer)->ucLength = ELEM_ID_WPA_LEN_FIXED; + WPA_IE(pucBuffer)->aucOui[0] = 0x00; + WPA_IE(pucBuffer)->aucOui[1] = 0x50; + WPA_IE(pucBuffer)->aucOui[2] = 0xF2; + WPA_IE(pucBuffer)->ucOuiType = VENDOR_OUI_TYPE_WPA; + WLAN_SET_FIELD_16(&WPA_IE(pucBuffer)->u2Version, 1); + +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered + && GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType == NETWORK_TYPE_P2P) { + WLAN_SET_FIELD_32( + &WPA_IE(pucBuffer)->u4GroupKeyCipherSuite, + WPA_CIPHER_SUITE_TKIP); + } else +#endif + WLAN_SET_FIELD_32( + &WPA_IE(pucBuffer)->u4GroupKeyCipherSuite, + prAdapter->prAisBssInfo-> + u4RsnSelectedGroupCipher); + + cp = (uint8_t *) & + WPA_IE(pucBuffer)->aucPairwiseKeyCipherSuite1[0]; + + WLAN_SET_FIELD_16(&WPA_IE(pucBuffer)-> + u2PairwiseKeyCipherSuiteCount, 1); +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered + && GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)-> + eNetworkType == NETWORK_TYPE_P2P) { + WLAN_SET_FIELD_32(cp, WPA_CIPHER_SUITE_TKIP); + } else +#endif + WLAN_SET_FIELD_32(cp, prAdapter->prAisBssInfo + ->u4RsnSelectedPairwiseCipher); + + cp = pucBuffer + sizeof(struct WPA_INFO_ELEM); + + WLAN_SET_FIELD_16(cp, 1); + cp += 2; +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered + && GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)-> + eNetworkType == NETWORK_TYPE_P2P) { + WLAN_SET_FIELD_32(cp, WPA_AKM_SUITE_PSK); + } else +#endif + WLAN_SET_FIELD_32(cp, prAdapter->prAisBssInfo + ->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 struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + uint8_t *cp; + /* UINT_8 ucExpendedLen = 0; */ + uint8_t *pucBuffer; + uint8_t ucBssIndex; + struct BSS_INFO *prBssInfo; +#if !CFG_SUPPORT_CFG80211_AUTH + uint32_t u4Entry; + struct STA_RECORD *prStaRec; + uint8_t fgPmkCacheExist = FALSE; +#endif +#if CFG_SUPPORT_CFG80211_AUTH + uint32_t u4GroupMgmt = 0; + struct CONNECTION_SETTINGS *prConnSettings = NULL; + + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + + ASSERT(prConnSettings); +#endif + + + DEBUGFUNC("rsnGenerateRSNIE"); + + ASSERT(prMsduInfo); + + pucBuffer = (uint8_t *) ((unsigned long) + prMsduInfo->prPacket + (unsigned long) + prMsduInfo->u2FrameLength); + + ASSERT(pucBuffer); + + /* Todo:: network id */ + ucBssIndex = prMsduInfo->ucBssIndex; + /* for Fast Bss Transition, we reuse the RSN Element composed in + * userspace + */ + if ((prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2_FT || + prAdapter->rWifiVar.rConnSettings.eAuthMode == + AUTH_MODE_WPA2_FT_PSK) && + prAdapter->prGlueInfo->rFtIeForTx.prRsnIE) { + authAddRSNIE(prAdapter, prMsduInfo); + return; + } + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + ASSERT(prBssInfo); + + if ( +#if CFG_ENABLE_WIFI_DIRECT + ((prAdapter->fgIsP2PRegistered) && + (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType == NETWORK_TYPE_P2P) + && (kalP2PGetCcmpCipher(prAdapter->prGlueInfo, + (uint8_t) prBssInfo->u4PrivateData))) || +#endif +#if CFG_ENABLE_BT_OVER_WIFI + (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType == NETWORK_TYPE_BOW) + || +#endif + (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType == + NETWORK_TYPE_AIS /* prCurrentBss->fgIERSN */ && + ((prAdapter->rWifiVar.rConnSettings.eAuthMode == + AUTH_MODE_WPA2) + || (prAdapter->rWifiVar.rConnSettings.eAuthMode == + AUTH_MODE_WPA2_PSK) + || (prAdapter->rWifiVar.rConnSettings.eAuthMode == + AUTH_MODE_WPA2_FT_PSK) + || (prAdapter->rWifiVar.rConnSettings.eAuthMode == + AUTH_MODE_WPA2_FT) +#if CFG_SUPPORT_CFG80211_AUTH + || (prAdapter->rWifiVar.rConnSettings.eAuthMode == + AUTH_MODE_WPA2_SAE) +#endif + ))) { + /* Construct a RSN IE for association request frame. */ + RSN_IE(pucBuffer)->ucElemId = ELEM_ID_RSN; +#if CFG_SUPPORT_CFG80211_AUTH + RSN_IE(pucBuffer)->ucLength = + prAdapter->prGlueInfo->rWpaInfo.ucRsneLen; + if (RSN_IE(pucBuffer)->ucLength < 2) { + if ((prBssInfo->eCurrentOPMode == + OP_MODE_ACCESS_POINT) || + (prBssInfo->eNetworkType == NETWORK_TYPE_P2P)) { + RSN_IE(pucBuffer)->ucLength = + ELEM_ID_RSN_LEN_FIXED; + } else { + DBGLOG(RSN, WARN, + "Desired RSN IE from upper is too short (length=%d)\n", + RSN_IE(pucBuffer)->ucLength); + return; + } + } +#else + RSN_IE(pucBuffer)->ucLength = ELEM_ID_RSN_LEN_FIXED; +#endif + /* Version */ + WLAN_SET_FIELD_16(&RSN_IE(pucBuffer)->u2Version, 1); + WLAN_SET_FIELD_32(&RSN_IE(pucBuffer)->u4GroupKeyCipherSuite, + GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)-> + u4RsnSelectedGroupCipher); + /* Group key suite */ + cp = (uint8_t *) &RSN_IE( + pucBuffer)->aucPairwiseKeyCipherSuite1[0]; + WLAN_SET_FIELD_16(&RSN_IE( + pucBuffer)->u2PairwiseKeyCipherSuiteCount, 1); + WLAN_SET_FIELD_32(cp, GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->u4RsnSelectedPairwiseCipher); + + cp = pucBuffer + sizeof(struct RSN_INFO_ELEM); + + WLAN_SET_FIELD_16(cp, 1); /* AKM suite count */ + cp += 2; + /* AKM suite */ + WLAN_SET_FIELD_32(cp, GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->u4RsnSelectedAKMSuite); + cp += 4; + + /* Capabilities */ + WLAN_SET_FIELD_16(cp, GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->u2RsnSelectedCapInfo); + DBGLOG(RSN, TRACE, + "Gen RSN IE = %x\n", GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->u2RsnSelectedCapInfo); + #if CFG_SUPPORT_802_11W + if (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType == NETWORK_TYPE_AIS) { + if (kalGetRsnIeMfpCap(prAdapter->prGlueInfo) == + RSN_AUTH_MFP_REQUIRED) { + WLAN_SET_FIELD_16(cp, + ELEM_WPA_CAP_MFPC | ELEM_WPA_CAP_MFPR); + /* Capabilities */ + DBGLOG(RSN, TRACE, + "RSN_AUTH_MFP - MFPC & MFPR\n"); + } else if (kalGetRsnIeMfpCap(prAdapter->prGlueInfo) == + RSN_AUTH_MFP_OPTIONAL) { + WLAN_SET_FIELD_16(cp, ELEM_WPA_CAP_MFPC); + /* Capabilities */ + DBGLOG(RSN, TRACE, "RSN_AUTH_MFP - MFPC\n"); + } else { + DBGLOG(RSN, TRACE, + "!RSN_AUTH_MFP - No MFPC!\n"); + } + } else if ((GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)-> + eNetworkType == NETWORK_TYPE_P2P) && + (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eCurrentOPMode == + (uint8_t) OP_MODE_ACCESS_POINT)) { + /* AP PMF */ + /* for AP mode, keep origin RSN IE content w/o update */ + } +#endif + cp += 2; + +#if CFG_SUPPORT_CFG80211_AUTH + /*Fill PMKID and Group Management Cipher for AIS */ + if (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType + == NETWORK_TYPE_AIS) { + /* Fill PMKID Count field */ + WLAN_SET_FIELD_16(cp, + prConnSettings->rRsnInfo.u2PmkidCnt); + cp += 2; + + /* Fill PMKID List field */ + if (prConnSettings->rRsnInfo.u2PmkidCnt > 0) { + kalMemCopy(cp, + &prConnSettings->rRsnInfo.aucPmkidList, + (prConnSettings + ->rRsnInfo.u2PmkidCnt * RSN_PMKID_LEN)); + DBGLOG(RSN, INFO, + "Dump PMDID when gen rsn ie & len:%d\n", + RSN_IE(pucBuffer)->ucLength); + DBGLOG_MEM8(RSN, INFO, cp, + (prConnSettings + ->rRsnInfo.u2PmkidCnt * RSN_PMKID_LEN)); + } + + cp += (prConnSettings + ->rRsnInfo.u2PmkidCnt * RSN_PMKID_LEN); +#if CFG_SUPPORT_802_11W + /* Fill Group Management Cipher field */ + u4GroupMgmt = + prAdapter->prGlueInfo->rWpaInfo.u4CipherGroupMgmt; + WLAN_SET_FIELD_32(cp, u4GroupMgmt); +#endif + } +#else + /* Fill PMKID and Group Management Cipher for AIS */ + if (GET_BSS_INFO_BY_INDEX(prAdapter, + ucBssIndex)->eNetworkType == NETWORK_TYPE_AIS) { + prStaRec = cnmGetStaRecByIndex(prAdapter, + prMsduInfo->ucStaRecIndex); + + if (rsnSearchPmkidEntry(prAdapter, + prStaRec->aucMacAddr, &u4Entry)) { + if (prAdapter->rWifiVar. + rAisSpecificBssInfo. + arPmkidCache[u4Entry].fgPmkidExist) + fgPmkCacheExist = TRUE; + } + + /* Fill PMKID Count and List field */ + if (fgPmkCacheExist) { + RSN_IE(pucBuffer)->ucLength = 38; + /* Fill PMKID Count field */ + WLAN_SET_FIELD_16(cp, 1); + 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)); + /* Fill PMKID List field */ + kalMemCopy(cp, + (void *) prAdapter->rWifiVar. + rAisSpecificBssInfo. + arPmkidCache[u4Entry]. + rBssidInfo.arPMKID, + (sizeof(uint8_t) * 16)); + cp += 16; + } +#if CFG_SUPPORT_802_11W + else { + /* Follow supplicant flow to + * fill PMKID Count field = 0 only when + * Group Management Cipher field + * need to be filled + */ + if (prAdapter->rWifiVar. + rAisSpecificBssInfo.fgMgmtProtection) { + WLAN_SET_FIELD_16(cp, 0) + + cp += 2; + RSN_IE(pucBuffer)->ucLength += 2; + } + } + + /* Fill Group Management Cipher field */ + if (prAdapter->rWifiVar. + rAisSpecificBssInfo.fgMgmtProtection) { + WLAN_SET_FIELD_32(cp, + RSN_CIPHER_SUITE_AES_128_CMAC); + cp += 4; + RSN_IE(pucBuffer)->ucLength += 4; + } +#endif + } +#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 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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t +rsnParseCheckForWFAInfoElem(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBuf, OUT uint8_t *pucOuiType, + OUT uint16_t *pu2SubTypeVersion) +{ + uint8_t aucWfaOui[] = VENDOR_OUI_WFA; + struct IE_WFA *prWfaIE; + + ASSERT(pucBuf); + ASSERT(pucOuiType); + ASSERT(pu2SubTypeVersion); + prWfaIE = (struct IE_WFA *)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(struct ADAPTER *prAdapter, + struct RSN_INFO_ELEM *prIe, + struct STA_RECORD *prStaRec, + uint16_t *pu2StatusCode) +{ + + struct RSN_INFO rRsnIe; + struct BSS_INFO *prBssInfo; + uint8_t i; + uint16_t statusCode; + + ASSERT(prAdapter); + ASSERT(prIe); + ASSERT(prStaRec); + 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; + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + /* 1st check: if already PMF connection, reject assoc req: + * error 30 ASSOC_REJECTED_TEMPORARILY + */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + *pu2StatusCode = STATUS_CODE_ASSOC_REJECTED_TEMPORARILY; + return; + } + + /* if RSN capability not exist, just return */ + if (!rRsnIe.fgRsnCapPresent) { + *pu2StatusCode = WLAN_STATUS_SUCCESS; + return; + } + + prStaRec->rPmfCfg.fgMfpc = (rRsnIe.u2RsnCap & + ELEM_WPA_CAP_MFPC) ? 1 : 0; + prStaRec->rPmfCfg.fgMfpr = (rRsnIe.u2RsnCap & + ELEM_WPA_CAP_MFPR) ? 1 : 0; + + for (i = 0; i < rRsnIe.u4AuthKeyMgtSuiteCount; i++) { + if ((rRsnIe.au4AuthKeyMgtSuite[i] == + RSN_AKM_SUITE_802_1X_SHA256) || + (rRsnIe.au4AuthKeyMgtSuite[i] == + RSN_AKM_SUITE_PSK_SHA256)) { + DBGLOG(RSN, INFO, "STA SHA256 support\n"); + prStaRec->rPmfCfg.fgSha256 = TRUE; + break; + } + } + + DBGLOG(RSN, INFO, + "STA Assoc req mfpc:%d, mfpr:%d, sha256:%d, bssIndex:%d, applyPmf:%d\n", + prStaRec->rPmfCfg.fgMfpc, prStaRec->rPmfCfg.fgMfpr, + prStaRec->rPmfCfg.fgSha256, prStaRec->ucBssIndex, + prStaRec->rPmfCfg.fgApplyPmf); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + /* if PMF validation fail, return success as legacy association + */ + statusCode = rsnPmfCapableValidation(prAdapter, prBssInfo, + prStaRec); + *pu2StatusCode = statusCode; +#endif + } + +} +#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 struct ADAPTER *prAdapter, IN u_int8_t fgFlags) +{ + struct PARAM_AUTH_EVENT *prAuthEvent; + + DEBUGFUNC("rsnGenMicErrorEvent"); + + prAuthEvent = (struct PARAM_AUTH_EVENT *) + prAdapter->aucIndicationEventBuffer; + + /* Status type: Authentication Event */ + prAuthEvent->rStatus.eStatusType = ENUM_STATUS_TYPE_AUTHENTICATION; + + /* Authentication request */ + prAuthEvent->arRequest[0].u4Length = sizeof(struct PARAM_AUTH_REQUEST); + kalMemCopy((void *)prAuthEvent->arRequest[0].arBssid, + (void *)prAdapter->prAisBssInfo->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, + (void *) prAuthEvent, + sizeof(struct PARAM_STATUS_INDICATION) + + sizeof(struct PARAM_AUTH_REQUEST)); + +} /* 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 struct ADAPTER *prAdapter, + IN struct STA_RECORD *prSta, + IN u_int8_t 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 struct ADAPTER + *prAdapter, IN struct BSS_DESC *prBssDesc) +{ + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_INFO *prAisBssInfo; + + DEBUGFUNC("rsnSelectPmkidCandidateList"); + + ASSERT(prBssDesc); + + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + prAisBssInfo = prAdapter->prAisBssInfo; + + /* 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; + } + + 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 struct ADAPTER + *prAdapter, IN struct BSS_DESC *prBssDesc) +{ + uint32_t i; + struct CONNECTION_SETTINGS *prConnSettings; + struct AIS_SPECIFIC_BSS_INFO *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((void *) + prAisSpecBssInfo->arPmkidCandicate[i].aucBssid, + (void *)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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rsnSearchPmkidEntry(IN struct ADAPTER *prAdapter, + IN uint8_t *pucBssid, + OUT uint32_t *pu4EntryIndex) +{ + uint32_t i; + struct AIS_SPECIFIC_BSS_INFO *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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t rsnCheckPmkidCandicate(IN struct ADAPTER *prAdapter) +{ + struct AIS_SPECIFIC_BSS_INFO *prAisSpecBssInfo; + uint32_t i; /* Index for PMKID candicate */ + uint32_t j; /* Indix for PMKID cache */ + u_int8_t 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((void *) prAisSpecBssInfo-> + arPmkidCache[prAisSpecBssInfo-> + u4PmkidCacheCount].rBssidInfo.arBSSID, + (void *) 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 struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr) +{ + 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->prAisBssInfo->eConnectionState == + PARAM_MEDIA_STATE_CONNECTED && + prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) { + rsnGeneratePmkidIndication(prAdapter); + } +} /* end of rsnIndicatePmkidCand() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to check the BSS Desc at scan result + * with pre-auth cap at wpa2 mode. If there + * is candicate that no cache entry is available, then + * add a new entry for the new candicate in the PMKID cache + * and set the PMKID indication flag to TRUE. + * + * \param[in] prBss The BSS Desc at scan result + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void rsnCheckPmkidCache(IN struct ADAPTER *prAdapter, IN struct BSS_DESC *prBss) +{ + struct BSS_INFO *prAisBssInfo; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecBssInfo; + struct CONNECTION_SETTINGS *prConnSettings; + + DEBUGFUNC("rsnCheckPmkidCandicate"); + + ASSERT(prBss); + + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + prAisBssInfo = prAdapter->prAisBssInfo; + 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 struct ADAPTER + *prAdapter) +{ + struct PARAM_STATUS_INDICATION *prStatusEvent; + struct PARAM_PMKID_CANDIDATE_LIST *prPmkidEvent; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecificBssInfo; + uint8_t i, j = 0, count = 0; + uint32_t u4LenOfUsedBuffer; + + DEBUGFUNC("rsnGeneratePmkidIndication"); + + ASSERT(prAdapter); + + prStatusEvent = (struct PARAM_STATUS_INDICATION *) + prAdapter->aucIndicationEventBuffer; + + /* Status type: PMKID Candidatelist Event */ + prStatusEvent->eStatusType = ENUM_STATUS_TYPE_CANDIDATE_LIST; + ASSERT(prStatusEvent); + + prPmkidEvent = + (struct PARAM_PMKID_CANDIDATE_LIST *)(&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((void *) + prPmkidEvent->arCandidateList[count].arBSSID, + (void *) prAisSpecificBssInfo-> + arPmkidCandicate[i].aucBssid, + PARAM_MAC_ADDR_LEN); + prPmkidEvent->arCandidateList[count].u4Flags = + prAisSpecificBssInfo->arPmkidCandicate[i]. + u4PreAuthFlags; + DBGLOG(RSN, TRACE, + MACSTR " %x\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 ENUM_STATUS_TYPE) + + (2 * sizeof(uint32_t)) + + (count * sizeof(struct PARAM_PMKID_CANDIDATE)); + /* dumpMemory8((uint8_t *)prAdapter->aucIndicationEventBuffer, + * u4LenOfUsedBuffer); + */ + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (void *) prAdapter->aucIndicationEventBuffer, + u4LenOfUsedBuffer); + +} /* rsnGeneratePmkidIndication */ + +#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 struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + uint8_t *pucBuffer; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + if (prMsduInfo->ucBssIndex != prAdapter->prAisBssInfo->ucBssIndex) + return; + + pucBuffer = (uint8_t *) ((unsigned long) + prMsduInfo->prPacket + (unsigned long) + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t rsnCheckBipKeyInstalled(IN struct ADAPTER + *prAdapter, IN struct STA_RECORD *prStaRec) +{ + /* caution: prStaRec might be null ! */ + if (prStaRec) { + if (GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex) + ->eNetworkType == (uint8_t) NETWORK_TYPE_AIS) { + return prAdapter->rWifiVar.rAisSpecificBssInfo. + fgBipKeyInstalled; + } else if ((GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex) + ->eNetworkType == NETWORK_TYPE_P2P) + && + (GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex) + ->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { + DBGLOG(RSN, INFO, "AP-STA PMF capable:%d\n", + prStaRec->rPmfCfg.fgApplyPmf); + return prStaRec->rPmfCfg.fgApplyPmf; + } else { + return FALSE; + } + } else + return FALSE; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * + * \brief This routine is called to check the Sa query timeout. + * + * + * \note + * Called by: AIS module, Handle by Sa Quert timeout + */ +/*----------------------------------------------------------------------------*/ +uint8_t rsnCheckSaQueryTimeout(IN struct ADAPTER *prAdapter) +{ + struct AIS_SPECIFIC_BSS_INFO *prBssSpecInfo; + uint32_t now; + + prBssSpecInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + ASSERT(prBssSpecInfo); + + GET_CURRENT_SYSTIME(&now); + + if (CHECK_FOR_TIMEOUT(now, prBssSpecInfo->u4SaQueryStart, + TU_TO_MSEC(1000))) { + DBGLOG(RSN, INFO, "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); +#if 1 + if (prAdapter->prAisBssInfo->eConnectionState == + PARAM_MEDIA_STATE_CONNECTED) { + struct MSG_AIS_ABORT *prAisAbortMsg; + + prAisAbortMsg = + (struct MSG_AIS_ABORT *) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_AIS_ABORT)); + if (!prAisAbortMsg) + return 0; + prAisAbortMsg->rMsgHdr.eMsgId = MID_SAA_AIS_FSM_ABORT; + prAisAbortMsg->ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_DISASSOCIATED; + prAisAbortMsg->fgDelayIndication = FALSE; + +#if CFG_DISCONN_DEBUG_FEATURE + g_rDisconnInfoTemp.ucTrigger = + DISCONNECT_TRIGGER_ACTIVE; +#endif + + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prAisAbortMsg, + MSG_SEND_METHOD_BUF); + } +#else + /* Re-connect */ + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); +#endif + 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 struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr) +{ + struct BSS_INFO *prBssInfo; + struct AIS_SPECIFIC_BSS_INFO *prBssSpecInfo; + struct MSDU_INFO *prMsduInfo; + struct ACTION_SA_QUERY_FRAME *prTxFrame; + uint16_t u2PayloadLen; + uint8_t *pucTmp = NULL; + uint8_t ucTransId[ACTION_SA_QUERY_TR_ID_LEN]; + + prBssInfo = prAdapter->prAisBssInfo; + ASSERT(prBssInfo); + + prBssSpecInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + ASSERT(prBssSpecInfo); + + DBGLOG(RSN, INFO, "MFP: Start Sa Query\n"); + + if (prBssInfo->prStaRecOfAP == NULL) { + if (prBssSpecInfo->u4SaQueryCount > 0) + rsnStopSaQuery(prAdapter); + DBGLOG(RSN, INFO, "MFP: unassociated AP!\n"); + return; + } + + if (prBssSpecInfo->u4SaQueryCount > 0 + && rsnCheckSaQueryTimeout(prAdapter)) { + DBGLOG(RSN, INFO, "MFP: u4SaQueryCount count =%d\n", + prBssSpecInfo->u4SaQueryCount); + return; + } + + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc(prAdapter, + MAC_TX_RESERVED_FIELD + + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + prTxFrame = (struct ACTION_SA_QUERY_FRAME *) + ((unsigned long)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + if (rsnCheckBipKeyInstalled(prAdapter, prBssInfo->prStaRecOfAP)) + 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_QUERY_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"); + cnmMgtPktFree(prAdapter, prMsduInfo); + 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] = (uint8_t) (kalRandomNumber() & 0xFF); + ucTransId[1] = (uint8_t) (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) { + kalMemFree(pucTmp, VIR_MEM_TYPE, + (prBssSpecInfo->u4SaQueryCount - 1) * + ACTION_SA_QUERY_TR_ID_LEN); + DBGLOG(RSN, INFO, + "MFP: Fail to alloc buffer for sa query id list\n"); + cnmMgtPktFree(prAdapter, prMsduInfo); + 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 <3> Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prBssInfo->prStaRecOfAP->ucBssIndex, + prBssInfo->prStaRecOfAP->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, NULL, + MSDU_RATE_MODE_AUTO); + + if (rsnCheckBipKeyInstalled(prAdapter, + prBssInfo->prStaRecOfAP)) { + DBGLOG(RSN, INFO, "Set MSDU_OPT_PROTECTED_FRAME"); + nicTxConfigPktOption(prMsduInfo, MSDU_OPT_PROTECTED_FRAME, + TRUE); + } + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + DBGLOG(RSN, INFO, "Set SA Query timer %d (%d Tu)", + prBssSpecInfo->u4SaQueryCount, 201); + + 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 struct ADAPTER *prAdapter) +{ + struct AIS_SPECIFIC_BSS_INFO *prBssSpecInfo; + + prBssSpecInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + ASSERT(prBssSpecInfo); + DBGLOG(RSN, INFO, "prBssSpecInfo->u4SaQueryCount %d\n", + prBssSpecInfo->u4SaQueryCount); + + if (prBssSpecInfo->u4SaQueryCount == 0) + rsnStartSaQueryTimer(prAdapter, (unsigned long)NULL); +} + +/*----------------------------------------------------------------------------*/ +/*! + * + * \brief This routine is called to stop the 802.11w sa query. + * + * + * \note + * Called by: AIS module, Handle Rx mgmt request + */ +/*----------------------------------------------------------------------------*/ +void rsnStopSaQuery(IN struct ADAPTER *prAdapter) +{ + struct AIS_SPECIFIC_BSS_INFO *prBssSpecInfo; + + prBssSpecInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + ASSERT(prBssSpecInfo); + + cnmTimerStopTimer(prAdapter, &prBssSpecInfo->rSaQueryTimer); + + if (prBssSpecInfo->pucSaQueryTransId) { + 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 struct ADAPTER *prAdapter, IN struct SW_RFB *prSwRfb) +{ + struct BSS_INFO *prBssInfo; + struct MSDU_INFO *prMsduInfo; + struct ACTION_SA_QUERY_FRAME *prRxFrame = NULL; + uint16_t u2PayloadLen; + struct STA_RECORD *prStaRec; + struct ACTION_SA_QUERY_FRAME *prTxFrame; + + prBssInfo = prAdapter->prAisBssInfo; + ASSERT(prBssInfo); + + if (!prSwRfb) + return; + + prRxFrame = (struct ACTION_SA_QUERY_FRAME *) + prSwRfb->pvHeader; + if (!prRxFrame) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (!prStaRec) /* Todo:: for not AIS check */ + return; + + DBGLOG(RSN, INFO, + "IEEE 802.11: Received SA Query Request from " MACSTR "\n", + MAC2STR(prStaRec->aucMacAddr)); + + DBGLOG_MEM8(RSN, INFO, prRxFrame->ucTransId, ACTION_SA_QUERY_TR_ID_LEN); + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == + PARAM_MEDIA_STATE_DISCONNECTED) { + DBGLOG(RSN, INFO, + "IEEE 802.11: Ignore SA Query Request from unassociated STA " + MACSTR "\n", MAC2STR(prStaRec->aucMacAddr)); + return; + } + + DBGLOG(RSN, INFO, + "IEEE 802.11: Sending SA Query Response to " MACSTR "\n", + MAC2STR(prStaRec->aucMacAddr)); + + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc(prAdapter, + MAC_TX_RESERVED_FIELD + + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + prTxFrame = (struct ACTION_SA_QUERY_FRAME *) + ((unsigned long)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + if (rsnCheckBipKeyInstalled(prAdapter, prBssInfo->prStaRecOfAP)) + 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_QUERY_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 <3> Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prBssInfo->prStaRecOfAP->ucBssIndex, + prBssInfo->prStaRecOfAP->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, NULL, + MSDU_RATE_MODE_AUTO); + + if (rsnCheckBipKeyInstalled(prAdapter, prBssInfo->prStaRecOfAP)) { + DBGLOG(RSN, INFO, "Set MSDU_OPT_PROTECTED_FRAME\n"); + nicTxConfigPktOption(prMsduInfo, MSDU_OPT_PROTECTED_FRAME, + TRUE); + } +#if 0 + /* 4 Update information of MSDU_INFO_T */ + /* Management frame */ + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + 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->ucPID = nicAssignPID(prAdapter); + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->fgIsBasicRate = FALSE; +#endif + /* 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 struct ADAPTER *prAdapter, IN struct SW_RFB *prSwRfb) +{ + struct AIS_SPECIFIC_BSS_INFO *prBssSpecInfo; + struct ACTION_SA_QUERY_FRAME *prRxFrame; + struct STA_RECORD *prStaRec; + uint32_t i; + + prBssSpecInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + ASSERT(prBssSpecInfo); + + prRxFrame = (struct ACTION_SA_QUERY_FRAME *) + prSwRfb->pvHeader; + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prSwRfb->u2PacketLen < ACTION_SA_QUERY_TR_ID_LEN) { + DBGLOG(RSN, INFO, + "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, INFO, + "IEEE 802.11: Unexpected SA Query Action %d\n", + prRxFrame->ucAction); + return; + } + + DBGLOG(RSN, INFO, + "IEEE 802.11: Received SA Query Response from " MACSTR "\n", + MAC2STR(prStaRec->aucMacAddr)); + + DBGLOG_MEM8(RSN, INFO, 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, INFO, + "IEEE 802.11: No matching SA Query transaction identifier found\n"); + return; + } + + DBGLOG(RSN, INFO, "Reply to pending SA Query received\n"); + + rsnStopSaQuery(prAdapter); +} +#endif + +static u_int8_t rsnCheckWpaRsnInfo(struct BSS_INFO *prBss, + struct RSN_INFO *prWpaRsnInfo) +{ + uint32_t i = 0; + + if (prWpaRsnInfo->u4GroupKeyCipherSuite != + prBss->u4RsnSelectedGroupCipher) { + DBGLOG(RSN, INFO, + "GroupCipherSuite change, old=0x%04x, new=0x%04x\n", + prBss->u4RsnSelectedGroupCipher, + prWpaRsnInfo->u4GroupKeyCipherSuite); + return TRUE; + } + for (; i < prWpaRsnInfo->u4AuthKeyMgtSuiteCount; i++) + if (prBss->u4RsnSelectedAKMSuite == + prWpaRsnInfo->au4AuthKeyMgtSuite[i]) + break; + if (i == prWpaRsnInfo->u4AuthKeyMgtSuiteCount) { + DBGLOG(RSN, INFO, + "KeyMgmt change, not find 0x%04x in new beacon\n", + prBss->u4RsnSelectedAKMSuite); + return TRUE; + } + + for (i = 0; i < prWpaRsnInfo->u4PairwiseKeyCipherSuiteCount; i++) + if (prBss->u4RsnSelectedPairwiseCipher == + prWpaRsnInfo->au4PairwiseKeyCipherSuite[i]) + break; + if (i == prWpaRsnInfo->u4PairwiseKeyCipherSuiteCount) { + DBGLOG(RSN, INFO, + "Pairwise Cipher change, not find 0x%04x in new beacon\n", + prBss->u4RsnSelectedPairwiseCipher); + return TRUE; + } + + return FALSE; +} + +u_int8_t rsnCheckSecurityModeChanged( + struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, + struct BSS_DESC *prBssDesc) +{ + enum ENUM_PARAM_AUTH_MODE eAuthMode = + prAdapter->rWifiVar.rConnSettings.eAuthMode; + + switch (eAuthMode) { + case AUTH_MODE_OPEN: /* original is open system */ + case AUTH_MODE_NON_RSN_FT: + if ((prBssDesc->u2CapInfo & CAP_INFO_PRIVACY) && + !prAdapter->prGlueInfo->rWpaInfo.fgPrivacyInvoke && + !secIsWepBss(prAdapter, prBssInfo)) { + DBGLOG(RSN, INFO, "security change, open->privacy\n"); + return TRUE; + } + break; + case AUTH_MODE_SHARED: /* original is WEP */ + case AUTH_MODE_AUTO_SWITCH: + if ((prBssDesc->u2CapInfo & CAP_INFO_PRIVACY) == 0) { + DBGLOG(RSN, INFO, "security change, WEP->open\n"); + return TRUE; + } else if (prBssDesc->fgIERSN || prBssDesc->fgIEWPA) { + DBGLOG(RSN, INFO, "security change, WEP->WPA/WPA2\n"); + return TRUE; + } + break; + case AUTH_MODE_WPA: /*original is WPA */ + case AUTH_MODE_WPA_PSK: + case AUTH_MODE_WPA_NONE: + if (prBssDesc->fgIEWPA) + return rsnCheckWpaRsnInfo(prBssInfo, + &prBssDesc->rWPAInfo); + DBGLOG(RSN, INFO, "security change, WPA->%s\n", + prBssDesc->fgIERSN ? "WPA2" : + (prBssDesc->u2CapInfo & CAP_INFO_PRIVACY ? + "WEP" : "OPEN")); + return TRUE; + break; + case AUTH_MODE_WPA2: /*original is WPA2 */ + case AUTH_MODE_WPA2_PSK: + case AUTH_MODE_WPA2_FT: + case AUTH_MODE_WPA2_FT_PSK: +#if CFG_SUPPORT_CFG80211_AUTH + case AUTH_MODE_WPA2_SAE: +#endif + if (prBssDesc->fgIERSN) + return rsnCheckWpaRsnInfo(prBssInfo, + &prBssDesc->rRSNInfo); + DBGLOG(RSN, INFO, "security change, WPA2->%s\n", + prBssDesc->fgIEWPA ? "WPA" : + (prBssDesc->u2CapInfo & CAP_INFO_PRIVACY ? + "WEP" : "OPEN")); + return TRUE; + break; + default: + DBGLOG(RSN, WARN, "unknowned eAuthMode=%d\n", eAuthMode); + break; + } + return FALSE; +} + +#if CFG_SUPPORT_AAA +#define WPS_DEV_OUI_WFA 0x0050f204 +#define ATTR_RESPONSE_TYPE 0x103b + +#define ATTR_VERSION 0x104a +#define ATTR_VENDOR_EXT 0x1049 +#define WPS_VENDOR_ID_WFA 14122 + +void rsnGenerateWSCIEForAssocRsp(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct WIFI_VAR *prWifiVar = NULL; + struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *)NULL; + uint16_t u2IELen = 0; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + ASSERT(IS_NET_ACTIVE(prAdapter, prMsduInfo->ucBssIndex)); + + prWifiVar = &(prAdapter->rWifiVar); + ASSERT(prWifiVar); + + DBGLOG(RSN, TRACE, "WPS: Building WPS IE for (Re)Association Response"); + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + + if (prP2pBssInfo->eNetworkType != NETWORK_TYPE_P2P) + return; + + u2IELen = kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 3, + (uint8_t) prP2pBssInfo->u4PrivateData); + + kalP2PGenWSC_IE(prAdapter->prGlueInfo, + 3, + (uint8_t *) ((unsigned long) prMsduInfo->prPacket + + (unsigned long) prMsduInfo->u2FrameLength), + (uint8_t) prP2pBssInfo->u4PrivateData); + prMsduInfo->u2FrameLength += (uint16_t) kalP2PCalWSC_IELen( + prAdapter->prGlueInfo, 3, + (uint8_t) prP2pBssInfo->u4PrivateData); +} + +#endif + +#if CFG_SUPPORT_802_11W +/* AP PMF */ +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to validate setting if PMF connection capable + * or not. If AP MFPC=1, and STA MFPC=1, we let this as PMF connection + * + * + * \return status code + */ +/*----------------------------------------------------------------------------*/ +uint16_t rsnPmfCapableValidation(IN struct ADAPTER + *prAdapter, IN struct BSS_INFO *prBssInfo, + IN struct STA_RECORD *prStaRec) +{ + u_int8_t selfMfpc, selfMfpr, peerMfpc, peerMfpr; + + selfMfpc = prBssInfo->rApPmfCfg.fgMfpc; + selfMfpr = prBssInfo->rApPmfCfg.fgMfpr; + peerMfpc = prStaRec->rPmfCfg.fgMfpc; + peerMfpr = prStaRec->rPmfCfg.fgMfpr; + + DBGLOG(RSN, INFO, + "AP mfpc:%d, mfpr:%d / STA mfpc:%d, mfpr:%d\n", + selfMfpc, selfMfpr, peerMfpc, peerMfpr); + + if ((selfMfpc == TRUE) && (peerMfpc == FALSE)) { + if ((selfMfpr == TRUE) && (peerMfpr == FALSE)) { + DBGLOG(RSN, ERROR, + "PMF policy violation for case 4\n"); + return STATUS_CODE_ROBUST_MGMT_FRAME_POLICY_VIOLATION; + } + + if (peerMfpr == TRUE) { + DBGLOG(RSN, ERROR, + "PMF policy violation for case 7\n"); + return STATUS_CODE_ROBUST_MGMT_FRAME_POLICY_VIOLATION; + } + } + + if ((selfMfpc == TRUE) && (peerMfpc == TRUE)) { + DBGLOG(RSN, ERROR, "PMF Connection\n"); + prStaRec->rPmfCfg.fgApplyPmf = TRUE; + } + + return STATUS_CODE_SUCCESSFUL; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to generate TIMEOUT INTERVAL IE + * for association resp. + * Add Timeout interval IE (56) when PMF invalid association. + * + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void rsnPmfGenerateTimeoutIE(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo) +{ + struct IE_TIMEOUT_INTERVAL *prTimeout; + struct STA_RECORD *prStaRec = NULL; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (!prStaRec) + return; + + prTimeout = (struct IE_TIMEOUT_INTERVAL *) + (((uint8_t *) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + + /* only when PMF connection, and association error code is 30 */ + if ((rsnCheckBipKeyInstalled(prAdapter, prStaRec) == TRUE) + && + (prStaRec->u2StatusCode == + STATUS_CODE_ASSOC_REJECTED_TEMPORARILY)) { + + DBGLOG(RSN, INFO, "rsnPmfGenerateTimeoutIE TRUE\n"); + prTimeout->ucId = ELEM_ID_TIMEOUT_INTERVAL; + prTimeout->ucLength = ELEM_MAX_LEN_TIMEOUT_IE; + prTimeout->ucType = IE_TIMEOUT_INTERVAL_TYPE_ASSOC_COMEBACK; + prTimeout->u4Value = 1 << 10; + prMsduInfo->u2FrameLength += IE_SIZE(prTimeout); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * + * \brief This routine is called to check the Sa query timeout. + * check if total retry time is greater than 1000ms + * + * \retval 1: retry max timeout. 0: not timeout + * \note + * Called by: AAA module, Handle by Sa Query timeout + */ +/*----------------------------------------------------------------------------*/ +uint8_t rsnApCheckSaQueryTimeout(IN struct ADAPTER + *prAdapter, IN struct STA_RECORD *prStaRec) +{ + struct BSS_INFO *prBssInfo; + uint32_t now; + + GET_CURRENT_SYSTIME(&now); + + if (CHECK_FOR_TIMEOUT(now, prStaRec->rPmfCfg.u4SAQueryStart, + TU_TO_MSEC(1000))) { + DBGLOG(RSN, INFO, "association SA Query timed out\n"); + + /* XXX PMF TODO how to report STA REC disconnect?? */ + /* when SAQ retry count timeout, clear this STA */ + prStaRec->rPmfCfg.ucSAQueryTimedOut = 1; + prStaRec->rPmfCfg.u2TransactionID = 0; + prStaRec->rPmfCfg.u4SAQueryCount = 0; + cnmTimerStopTimer(prAdapter, &prStaRec->rPmfCfg.rSAQueryTimer); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + /* refer to p2pRoleFsmRunEventRxDeauthentication */ + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + if (bssRemoveClient(prAdapter, prBssInfo, prStaRec)) { + /* Indicate disconnect to Host. */ + p2pFuncDisconnect(prAdapter, prBssInfo, + prStaRec, FALSE, 0); + /* Deactive BSS if PWR is IDLE and no peer */ + if (IS_NET_PWR_STATE_IDLE(prAdapter, + prBssInfo->ucBssIndex) + && + (bssGetClientCount(prAdapter, prBssInfo) + == 0)) { + /* All Peer disconnected !! + * Stop BSS now!! + */ + p2pFuncStopComplete(prAdapter, + prBssInfo); + } + } + } + + return 1; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * + * \brief This routine is called to start the 802.11w sa query timer. + * This routine is triggered every 201ms, and every time enter function, + * check max timeout + * + * \note + * Called by: AAA module, Handle TX SAQ request + */ +/*----------------------------------------------------------------------------*/ +void rsnApStartSaQueryTimer(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN unsigned long ulParamPtr) +{ + struct BSS_INFO *prBssInfo; + struct MSDU_INFO *prMsduInfo; + struct ACTION_SA_QUERY_FRAME *prTxFrame; + uint16_t u2PayloadLen; + + ASSERT(prStaRec); + + DBGLOG(RSN, INFO, "MFP: AP Start Sa Query timer\n"); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + if (prStaRec->rPmfCfg.u4SAQueryCount > 0 + && rsnApCheckSaQueryTimeout(prAdapter, prStaRec)) { + DBGLOG(RSN, INFO, + "MFP: retry max timeout, u4SaQueryCount count =%d\n", + prStaRec->rPmfCfg.u4SAQueryCount); + return; + } + + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc(prAdapter, + MAC_TX_RESERVED_FIELD + + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + prTxFrame = (struct ACTION_SA_QUERY_FRAME *) + ((unsigned long)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) + prTxFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + COPY_MAC_ADDR(prTxFrame->aucDestAddr, prStaRec->aucMacAddr); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucBSSID); + COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); + + prTxFrame->ucCategory = CATEGORY_SA_QUERY_ACTION; + prTxFrame->ucAction = ACTION_SA_QUERY_REQUEST; + + if (prStaRec->rPmfCfg.u4SAQueryCount == 0) + GET_CURRENT_SYSTIME(&prStaRec->rPmfCfg.u4SAQueryStart); + + /* if retry, transcation id ++ */ + if (prStaRec->rPmfCfg.u4SAQueryCount) { + prStaRec->rPmfCfg.u2TransactionID++; + } else { + /* if first SAQ request, random pick transaction id */ + prStaRec->rPmfCfg.u2TransactionID = + (uint16_t) (kalRandomNumber() & 0xFFFF); + } + + DBGLOG(RSN, INFO, "SAQ transaction id:%d\n", + prStaRec->rPmfCfg.u2TransactionID); + + /* trnsform U16 to U8 array */ + prTxFrame->ucTransId[0] = ((prStaRec->rPmfCfg.u2TransactionID + & 0xff00) >> 8); + prTxFrame->ucTransId[1] = ((prStaRec->rPmfCfg.u2TransactionID + & 0x00ff) >> 0); + + prStaRec->rPmfCfg.u4SAQueryCount++; + + u2PayloadLen = 2 + ACTION_SA_QUERY_TR_ID_LEN; + + /* 4 <3> Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, NULL, + MSDU_RATE_MODE_AUTO); + + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(RSN, INFO, "SAQ Set MSDU_OPT_PROTECTED_FRAME\n"); + nicTxConfigPktOption(prMsduInfo, MSDU_OPT_PROTECTED_FRAME, + TRUE); + } + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + DBGLOG(RSN, INFO, "AP Set SA Query timer %d (%d Tu)\n", + prStaRec->rPmfCfg.u4SAQueryCount, 201); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rPmfCfg.rSAQueryTimer, TU_TO_MSEC(201)); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * + * \brief This routine is called to start the 802.11w TX SA query. + * + * + * \note + * Called by: AAA module, Handle Tx action frame request + */ +/*----------------------------------------------------------------------------*/ +void rsnApStartSaQuery(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + if (!prStaRec) + return; + + DBGLOG(RSN, INFO, "rsnApStartSaQuery\n"); + + cnmTimerStopTimer(prAdapter, + &prStaRec->rPmfCfg.rSAQueryTimer); + cnmTimerInitTimer(prAdapter, + &prStaRec->rPmfCfg.rSAQueryTimer, + (PFN_MGMT_TIMEOUT_FUNC)rsnApStartSaQueryTimer, + (unsigned long) prStaRec); + + if (prStaRec->rPmfCfg.u4SAQueryCount == 0) + rsnApStartSaQueryTimer(prAdapter, prStaRec, + (unsigned long)NULL); +} + +/*----------------------------------------------------------------------------*/ +/*! + * + * \brief This routine is called to stop the 802.11w SA query. + * + * + * \note + * Called by: AAA module, stop TX SAQ if receive correct SAQ response + */ +/*----------------------------------------------------------------------------*/ +void rsnApStopSaQuery(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + ASSERT(prStaRec); + + cnmTimerStopTimer(prAdapter, &prStaRec->rPmfCfg.rSAQueryTimer); + prStaRec->rPmfCfg.u2TransactionID = 0; + prStaRec->rPmfCfg.u4SAQueryCount = 0; + prStaRec->rPmfCfg.ucSAQueryTimedOut = 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * + * \brief This routine is called to process the 802.11w sa query action frame. + * + * + * \note + * Called by: AAA module, Handle Rx action request + */ +/*----------------------------------------------------------------------------*/ +void rsnApSaQueryRequest(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct BSS_INFO *prBssInfo; + struct MSDU_INFO *prMsduInfo; + struct ACTION_SA_QUERY_FRAME *prRxFrame = NULL; + uint16_t u2PayloadLen; + struct STA_RECORD *prStaRec; + struct ACTION_SA_QUERY_FRAME *prTxFrame; + + if (!prSwRfb) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (!prStaRec) /* Todo:: for not AIS check */ + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + ASSERT(prBssInfo); + + prRxFrame = (struct ACTION_SA_QUERY_FRAME *) + prSwRfb->pvHeader; + if (!prRxFrame) + return; + + DBGLOG(RSN, INFO, + "IEEE 802.11: AP Received SA Query Request from " MACSTR + "\n", MAC2STR(prStaRec->aucMacAddr)); + + DBGLOG_MEM8(RSN, INFO, prRxFrame->ucTransId, ACTION_SA_QUERY_TR_ID_LEN); + + if (!rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(RSN, INFO, + "IEEE 802.11: AP Ignore SA Query Request non-PMF STA " + MACSTR "\n", MAC2STR(prStaRec->aucMacAddr)); + return; + } + + DBGLOG(RSN, INFO, + "IEEE 802.11: Sending SA Query Response to " MACSTR "\n", + MAC2STR(prStaRec->aucMacAddr)); + + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc(prAdapter, + MAC_TX_RESERVED_FIELD + + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + /* drop cipher mismatch */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + if (HAL_RX_STATUS_IS_CIPHER_MISMATCH(prSwRfb->prRxStatus) || + HAL_RX_STATUS_IS_CLM_ERROR(prSwRfb->prRxStatus)) { + /* if cipher mismatch, or incorrect encrypt, + * just drop + */ + DBGLOG(RSN, ERROR, "drop SAQ req CM/CLM=1\n"); + return; + } + } + + prTxFrame = (struct ACTION_SA_QUERY_FRAME *) + ((unsigned long)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + prTxFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + DBGLOG(RSN, INFO, "AP SAQ resp set FC PF bit\n"); + } + COPY_MAC_ADDR(prTxFrame->aucDestAddr, prStaRec->aucMacAddr); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucBSSID); + COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); + + prTxFrame->ucCategory = CATEGORY_SA_QUERY_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 <3> Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, NULL, + MSDU_RATE_MODE_AUTO); + + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(RSN, INFO, "AP SAQ resp set MSDU_OPT_PROTECTED_FRAME\n"); + nicTxConfigPktOption(prMsduInfo, MSDU_OPT_PROTECTED_FRAME, + TRUE); + } + + /* 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: AAA module, Handle Rx action request + */ +/*----------------------------------------------------------------------------*/ +void rsnApSaQueryAction(IN struct ADAPTER *prAdapter, IN struct SW_RFB *prSwRfb) +{ + struct ACTION_SA_QUERY_FRAME *prRxFrame; + struct STA_RECORD *prStaRec; + uint16_t u2SwapTrID; + + prRxFrame = (struct ACTION_SA_QUERY_FRAME *) + prSwRfb->pvHeader; + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prStaRec == NULL) { + DBGLOG(RSN, INFO, "rsnApSaQueryAction: prStaRec is NULL"); + return; + } + + DBGLOG(RSN, TRACE, + "AP PMF SAQ action enter from " MACSTR "\n", + MAC2STR(prStaRec->aucMacAddr)); + if (prSwRfb->u2PacketLen < ACTION_SA_QUERY_TR_ID_LEN) { + DBGLOG(RSN, INFO, + "IEEE 802.11: Too short SA Query Action frame (len=%lu)\n", + (unsigned long)prSwRfb->u2PacketLen); + return; + } + + if (prRxFrame->ucAction == ACTION_SA_QUERY_REQUEST) { + rsnApSaQueryRequest(prAdapter, prSwRfb); + return; + } + + if (prRxFrame->ucAction != ACTION_SA_QUERY_RESPONSE) { + DBGLOG(RSN, INFO, + "IEEE 802.11: Unexpected SA Query Action %d\n", + prRxFrame->ucAction); + return; + } + + DBGLOG(RSN, INFO, + "IEEE 802.11: Received SA Query Response from " MACSTR "\n", + MAC2STR(prStaRec->aucMacAddr)); + + DBGLOG_MEM8(RSN, INFO, prRxFrame->ucTransId, ACTION_SA_QUERY_TR_ID_LEN); + + /* MLME-SAQuery.confirm */ + /* transform to network byte order */ + u2SwapTrID = htons(prStaRec->rPmfCfg.u2TransactionID); + if (kalMemCmp((uint8_t *) &u2SwapTrID, prRxFrame->ucTransId, + ACTION_SA_QUERY_TR_ID_LEN) == 0) { + DBGLOG(RSN, INFO, "AP Reply to SA Query received\n"); + rsnApStopSaQuery(prAdapter, prStaRec); + } else { + DBGLOG(RSN, INFO, + "IEEE 802.11: AP No matching SA Query transaction identifier found\n"); + } + +} + +#endif /* CFG_SUPPORT_802_11W */ + +#if CFG_SUPPORT_PASSPOINT +u_int8_t rsnParseOsenIE(struct ADAPTER *prAdapter, + struct IE_WFA_OSEN *prInfoElem, + struct RSN_INFO *prOsenInfo) +{ + uint32_t i; + int32_t u4RemainRsnIeLen; + uint16_t u2Version = 0; + uint16_t u2Cap = 0; + uint32_t u4GroupSuite = RSN_CIPHER_SUITE_CCMP; + uint16_t u2PairSuiteCount = 0; + uint16_t u2AuthSuiteCount = 0; + uint8_t *pucPairSuite = NULL; + uint8_t *pucAuthSuite = NULL; + uint8_t *cp; + + ASSERT(prOsenInfo); + + cp = ((uint8_t *) prInfoElem) + 6; + u4RemainRsnIeLen = (int32_t) prInfoElem->ucLength - 4; + do { + if (u4RemainRsnIeLen == 0) + break; + + /* Parse the Group Key Cipher Suite field. */ + if (u4RemainRsnIeLen < 4) { + DBGLOG(RSN, WARN, + "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, WARN, + "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 = (uint32_t) u2PairSuiteCount * 4; + if (u4RemainRsnIeLen < (int32_t) i) { + DBGLOG(RSN, WARN, + "Fail to parse RSN IE in pairwise cipher suite list (IE len: %d, Remain %u, Cnt %d GS %x)\n", + prInfoElem->ucLength, u4RemainRsnIeLen, + u2PairSuiteCount, u4GroupSuite); + return FALSE; + } + + pucPairSuite = cp; + + cp += i; + u4RemainRsnIeLen -= (int32_t) i; + + if (u4RemainRsnIeLen == 0) + break; + + /* Parse the Authentication and Key Management Cipher Suite + * Count field. + */ + if (u4RemainRsnIeLen < 2) { + DBGLOG(RSN, WARN, + "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 = (uint32_t) u2AuthSuiteCount * 4; + if (u4RemainRsnIeLen < (int32_t) i) { + DBGLOG(RSN, WARN, + "Fail to parse RSN IE in auth & key mgt suite list (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + pucAuthSuite = cp; + + cp += i; + u4RemainRsnIeLen -= (int32_t) i; + + if (u4RemainRsnIeLen == 0) + break; + + /* Parse the RSN u2Capabilities field. */ + if (u4RemainRsnIeLen < 2) { + DBGLOG(RSN, WARN, + "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. */ + prOsenInfo->ucElemId = ELEM_ID_VENDOR; + + prOsenInfo->u2Version = 0; + + prOsenInfo->u4GroupKeyCipherSuite = u4GroupSuite; + + DBGLOG(RSN, TRACE, + "RSN: version %d, group key cipher suite %02x-%02x-%02x-%02x\n", + u2Version, (uint8_t) (u4GroupSuite & 0x000000FF), + (uint8_t) ((u4GroupSuite >> 8) & 0x000000FF), + (uint8_t) ((u4GroupSuite >> 16) & 0x000000FF), + (uint8_t) ((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; + + prOsenInfo->u4PairwiseKeyCipherSuiteCount = + (uint32_t) u2PairSuiteCount; + + for (i = 0; i < (uint32_t) u2PairSuiteCount; i++) { + WLAN_GET_FIELD_32(pucPairSuite, + &prOsenInfo->au4PairwiseKeyCipherSuite[i]); + pucPairSuite += 4; + + DBGLOG(RSN, TRACE, + "RSN: pairwise key cipher suite [%d]: %02x-%02x-%02x-%02x\n", + (uint8_t) i, (uint8_t) ( + prOsenInfo->au4PairwiseKeyCipherSuite[i] + & 0x000000FF), + (uint8_t) + ((prOsenInfo->au4PairwiseKeyCipherSuite[i] >> 8) + & 0x000000FF), + (uint8_t) + ((prOsenInfo->au4PairwiseKeyCipherSuite[i] >> 16) + & 0x000000FF), + (uint8_t) + ((prOsenInfo->au4PairwiseKeyCipherSuite[i] >> 24) + & 0x000000FF)); + } + } else { + /* The information about the pairwise key cipher suites + * is not present. Use the default chipher suite for RSN: CCMP + */ + + prOsenInfo->u4PairwiseKeyCipherSuiteCount = 1; + prOsenInfo->au4PairwiseKeyCipherSuite[0] = + RSN_CIPHER_SUITE_CCMP; + + DBGLOG(RSN, WARN, + "No Pairwise Cipher Suite found, using default (CCMP)\n"); + } + + 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; + + prOsenInfo->u4AuthKeyMgtSuiteCount = (uint32_t) + u2AuthSuiteCount; + + for (i = 0; i < (uint32_t) u2AuthSuiteCount; i++) { + WLAN_GET_FIELD_32(pucAuthSuite, + &prOsenInfo->au4AuthKeyMgtSuite[i]); + pucAuthSuite += 4; + + DBGLOG(RSN, TRACE, + "RSN: AKM suite [%d]: %02x-%02x-%02x-%02x\n", + (uint8_t) i, + (uint8_t) (prOsenInfo->au4AuthKeyMgtSuite[i] + & 0x000000FF), + (uint8_t) + ((prOsenInfo->au4AuthKeyMgtSuite[i] >> 8) + & 0x000000FF), + (uint8_t) + ((prOsenInfo->au4AuthKeyMgtSuite[i] >> 16) + & 0x000000FF), + (uint8_t) + ((prOsenInfo->au4AuthKeyMgtSuite[i] >> 24) + & 0x000000FF)); + } + } else { + /* The information about the authentication and + * key management suites is not present. + * Use the default AKM suite for RSN. + */ + prOsenInfo->u4AuthKeyMgtSuiteCount = 1; + prOsenInfo->au4AuthKeyMgtSuite[0] = RSN_AKM_SUITE_802_1X; + + DBGLOG(RSN, WARN, "No AKM found, using default (802.1X)\n"); + } + + prOsenInfo->u2RsnCap = u2Cap; +#if CFG_SUPPORT_802_11W + prOsenInfo->fgRsnCapPresent = TRUE; +#endif + DBGLOG(RSN, TRACE, "RSN cap: 0x%04x\n", prOsenInfo->u2RsnCap); + + return TRUE; +} +#endif /* CFG_SUPPORT_PASSPOINT */ + +uint32_t rsnCalculateFTIELen(struct ADAPTER *prAdapter, uint8_t ucBssIdx, + struct STA_RECORD *prStaRec) +{ + enum ENUM_PARAM_AUTH_MODE eAuthMode = + prAdapter->rWifiVar.rConnSettings.eAuthMode; + struct FT_IES *prFtIEs = &prAdapter->prGlueInfo->rFtIeForTx; + + if (!IS_BSS_INDEX_VALID(ucBssIdx) || + !IS_BSS_AIS(GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx)) || + !prFtIEs->prFTIE || (eAuthMode != AUTH_MODE_WPA2_FT && + eAuthMode != AUTH_MODE_WPA2_FT_PSK)) + return 0; + return IE_SIZE(prFtIEs->prFTIE); +} + +void rsnGenerateFTIE(IN struct ADAPTER *prAdapter, + IN OUT struct MSDU_INFO *prMsduInfo) +{ + enum ENUM_PARAM_AUTH_MODE eAuthMode = + prAdapter->rWifiVar.rConnSettings.eAuthMode; + struct FT_IES *prFtIEs = &prAdapter->prGlueInfo->rFtIeForTx; + uint8_t *pucBuffer = + (uint8_t *)prMsduInfo->prPacket + prMsduInfo->u2FrameLength; + uint32_t ucFtIeSize = 0; + uint8_t ucBssIdx = prMsduInfo->ucBssIndex; + + if (!IS_BSS_INDEX_VALID(ucBssIdx) || + !IS_BSS_AIS(GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx)) || + !prFtIEs->prFTIE || (eAuthMode != AUTH_MODE_WPA2_FT && + eAuthMode != AUTH_MODE_WPA2_FT_PSK)) + return; + ucFtIeSize = IE_SIZE(prFtIEs->prFTIE); + prMsduInfo->u2FrameLength += ucFtIeSize; + kalMemCopy(pucBuffer, prFtIEs->prFTIE, ucFtIeSize); +} + +#if CFG_SUPPORT_OWE +/*----------------------------------------------------------------------------*/ +/*! + * + * \brief This routine is called to generate OWE IE for + * associate request frame. + * + * \param[in] prAdapter The Selected BSS description + * \param[in] prMsduInfo MSDU packet buffer + * + * \retval N/A + * + * \note + * Called by: AIS module, Associate request + */ +/*----------------------------------------------------------------------------*/ +void rsnGenerateOWEIE(IN struct ADAPTER *prAdapter, + IN OUT struct MSDU_INFO *prMsduInfo) +{ + uint8_t *pucBuffer = NULL; + struct CONNECTION_SETTINGS *prConnSettings = NULL; + uint8_t ucLength = 0; + + DBGLOG(RSN, INFO, "rsnGenerateOWEIE\n"); + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + + if (prConnSettings->rOweInfo.ucLength == 0) + return; + ucLength = prConnSettings->rOweInfo.ucLength + 2; + ASSERT(prMsduInfo); + + pucBuffer = (uint8_t *) ((unsigned long) + prMsduInfo->prPacket + (unsigned long) + prMsduInfo->u2FrameLength); + ASSERT(pucBuffer); + + /* if (eNetworkId != NETWORK_TYPE_AIS_INDEX) */ + /* return; */ + kalMemCopy(pucBuffer, &(prAdapter->rWifiVar.rConnSettings.rOweInfo), + ucLength); + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + DBGLOG_MEM8(RSN, INFO, pucBuffer, IE_SIZE(pucBuffer)); +} + +/*----------------------------------------------------------------------------*/ +/*! + * + * \brief This routine is called to calculate OWE IE length for + * associate request frame. + * + * \param[in] prAdapter Major data structure for driver operation + * \param[in] ucBssIndex unused for this function + * \param[in] prStaRec unused for this function + * + * \retval The append WPA IE length + * + * \note + * Called by: AIS module, Associate request + */ +/*----------------------------------------------------------------------------*/ +uint32_t rsnCalOweIELen(IN struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex, struct STA_RECORD *prStaRec) +{ + if (prAdapter->rWifiVar.rConnSettings.rOweInfo.ucLength != 0) + return prAdapter->rWifiVar.rConnSettings.rOweInfo.ucLength + 2; + else + return 0; +} +#endif + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/saa_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/saa_fsm.c new file mode 100644 index 0000000000000..20279a3897491 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/saa_fsm.c @@ -0,0 +1,2918 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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. + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +static uint8_t *apucDebugAAState[AA_STATE_NUM] = { + (uint8_t *) DISP_STRING("AA_IDLE"), + (uint8_t *) DISP_STRING("SAA_SEND_AUTH1"), + (uint8_t *) DISP_STRING("SAA_WAIT_AUTH2"), + (uint8_t *) DISP_STRING("SAA_SEND_AUTH3"), + (uint8_t *) DISP_STRING("SAA_WAIT_AUTH4"), + (uint8_t *) DISP_STRING("SAA_SEND_ASSOC1"), + (uint8_t *) DISP_STRING("SAA_WAIT_ASSOC2"), + (uint8_t *) DISP_STRING("AAA_SEND_AUTH2"), + (uint8_t *) DISP_STRING("AAA_SEND_AUTH4"), + (uint8_t *) DISP_STRING("AAA_SEND_ASSOC2"), + (uint8_t *) DISP_STRING("AA_RESOURCE") +}; + +/******************************************************************************* + * M A 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_SUPPORT_CFG80211_AUTH +/*------------------------------------------------------------*/ +/* + * @brief prepare to send authentication or association frame + * + * @param[in] prStaRec Pointer to the STA_RECORD_T + * + * @return (none) + */ +/*------------------------------------------------------------*/ +void saaSendAuthAssoc(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + /* This function do the things like + * "case SAA_STATE_SEND_AUTH1/ASSOC1" in SAA FSM steps + */ + + uint32_t rStatus = WLAN_STATUS_FAILURE; + struct CONNECTION_SETTINGS *prConnSettings = NULL; + /* default for OPEN */ + uint16_t u2AuthTransSN = AUTH_TRANSACTION_SEQ_1; + struct BSS_DESC *prBssDesc = NULL; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecBssInfo = NULL; + struct PARAM_SSID rSsid; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + DBGLOG(SAA, INFO, "[SAA]saaSendAuthAssoc, StaState:%d\n", + prStaRec->ucStaState); + + if (prStaRec->ucTxAuthAssocRetryCount >= + prStaRec->ucTxAuthAssocRetryLimit) { + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = + (prConnSettings->fgIsSendAssoc) ? + STATUS_CODE_ASSOC_TIMEOUT + : STATUS_CODE_AUTH_TIMEOUT; + + if (saaFsmSendEventJoinComplete(prAdapter, + WLAN_STATUS_FAILURE, + prStaRec, NULL) == + WLAN_STATUS_RESOURCES) { + /* can set a timer and retry later */ + DBGLOG(SAA, WARN, + "[SAA]can't alloc msg for inform AIS join complete\n"); + } + } else { + prStaRec->ucTxAuthAssocRetryCount++; + /* Prepare to send authentication frame */ + if (!prConnSettings->fgIsSendAssoc) { + if (!prConnSettings->fgIsP2pConn) { + /* Fill authentication transaction + * sequence number + * depends on auth type + */ + if (((prAdapter->prGlueInfo + ->rWpaInfo.u4AuthAlg & + AUTH_TYPE_SAE) || + (prAdapter->prGlueInfo + ->rWpaInfo.u4AuthAlg & + AUTH_TYPE_SHARED_KEY)) && + prConnSettings->ucAuthDataLen) { + kalMemCopy(&u2AuthTransSN, + prConnSettings->aucAuthData, + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN); + DBGLOG(SAA, INFO, + "[SAA]Get auth SN = %d from Conn Settings\n", + u2AuthTransSN); + } + } + /* Update Station Record - Class 1 Flag */ + if (prStaRec->ucStaState != STA_STATE_1) { + DBGLOG(SAA, WARN, + "[SAA]Rx send auth CMD at unexpect state:%d\n", + prStaRec->ucStaState); + cnmStaRecChangeState(prAdapter, + prStaRec, STA_STATE_1); + } +#if !CFG_SUPPORT_AAA + rStatus = authSendAuthFrame(prAdapter, + prStaRec, u2AuthTransSN); +#else + rStatus = authSendAuthFrame(prAdapter, + prStaRec, + prStaRec->ucBssIndex, + NULL, + u2AuthTransSN, + STATUS_CODE_RESERVED); +#endif /* CFG_SUPPORT_AAA */ + prStaRec->eAuthAssocSent = u2AuthTransSN; + } else { + /* Prepare to send association frame */ + /* Fill Cipher/AKM before + * sending association request, + * copy fro m AIS search step + */ + kalMemZero(&rSsid, + sizeof(struct PARAM_SSID)); + + if (prConnSettings->ucSSIDLen) { + COPY_SSID(rSsid.aucSsid, + rSsid.u4SsidLen, + prConnSettings->aucSSID, + prConnSettings->ucSSIDLen); + + prBssDesc = + scanSearchBssDescByBssidAndSsid( + prAdapter, + prStaRec->aucMacAddr, + TRUE, + &rSsid); + DBGLOG(RSN, INFO, "[RSN] prBssDesc[" + MACSTR" ,%s] Searched by BSSID[" + MACSTR"] & SSID %s.\n", + MAC2STR(prBssDesc->aucBSSID), + prBssDesc->aucSSID, + MAC2STR(prStaRec->aucMacAddr), + prConnSettings->aucSSID); + } else { + prBssDesc = + scanSearchBssDescByBssidAndChanNum( + prAdapter, + prStaRec->aucMacAddr, + TRUE, + prConnSettings->ucChannelNum); + DBGLOG(RSN, INFO, "[RSN] prBssDesc[" + MACSTR" ,%s] Searched by BSSID[" + MACSTR"] & ChanNum %d.\n", + MAC2STR(prBssDesc->aucBSSID), + prBssDesc->aucSSID, + MAC2STR(prStaRec->aucMacAddr), + prConnSettings->ucChannelNum); + } + + prAisSpecBssInfo = + &(prAdapter->rWifiVar.rAisSpecificBssInfo); + if (rsnPerformPolicySelection(prAdapter, + prBssDesc)) { + if (prAisSpecBssInfo->fgCounterMeasure) + DBGLOG(RSN, WARN, + "Skip whle at counter measure perid\n"); + else { + DBGLOG(RSN, INFO, + "Bss RSN matched!\n"); + prAdapter->prAisBssInfo + ->u4RsnSelectedGroupCipher + = prBssDesc + ->u4RsnSelectedGroupCipher; + prAdapter->prAisBssInfo + ->u4RsnSelectedPairwiseCipher + = prBssDesc + ->u4RsnSelectedPairwiseCipher; + prAdapter->prAisBssInfo + ->u4RsnSelectedAKMSuite + = prBssDesc + ->u4RsnSelectedAKMSuite; + } + } else + DBGLOG(RSN, WARN, "Bss fail for RSN check\n"); + if (prStaRec->ucStaState == STA_STATE_1) { + /* don't change to state + * for reassociation + */ + /* Update Station + * Record - Class 2 Flag + */ + cnmStaRecChangeState(prAdapter, + prStaRec, STA_STATE_2); + } + + rStatus = + assocSendReAssocReqFrame(prAdapter, + prStaRec); + prStaRec->eAuthAssocSent = AA_SENT_ASSOC1; + } + + if (rStatus != WLAN_STATUS_SUCCESS) { + /* maybe can't alloc msdu info, + * retry after timeout + */ + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC) + saaFsmRunEventTxReqTimeOut, + (unsigned long) prStaRec); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC( + TX_AUTHENTICATION_RETRY_TIMEOUT_TU)); + } + + } +} + +void saaSendAuthSeq3(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + uint32_t rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + DBGLOG(SAA, INFO, "[SAA]send auth 3\n"); + + if (prStaRec->ucTxAuthAssocRetryCount >= + prStaRec->ucTxAuthAssocRetryLimit) { + /* Record the Status Code of Auth Request */ + prStaRec->u2StatusCode = + STATUS_CODE_AUTH_TIMEOUT; + } else { + prStaRec->ucTxAuthAssocRetryCount++; + prStaRec->ucAuthTranNum = + AUTH_TRANSACTION_SEQ_3; + +#if !CFG_SUPPORT_AAA + rStatus = authSendAuthFrame(prAdapter, + prStaRec, + AUTH_TRANSACTION_SEQ_3); +#else + rStatus = authSendAuthFrame(prAdapter, + prStaRec, + prStaRec->ucBssIndex, + NULL, + AUTH_TRANSACTION_SEQ_3, + STATUS_CODE_RESERVED); +#endif /* CFG_SUPPORT_AAA */ + + prStaRec->eAuthAssocSent = AA_SENT_AUTH3; + + if (rStatus != WLAN_STATUS_SUCCESS) { + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC) + saaFsmRunEventTxReqTimeOut, + (unsigned long) prStaRec); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC( + TX_AUTHENTICATION_RETRY_TIMEOUT_TU)); + } + } +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, IN enum ENUM_AA_STATE eNextState, + IN struct SW_RFB *prRetainedSwRfb) +{ + uint32_t rStatus = WLAN_STATUS_FAILURE; + enum ENUM_AA_STATE ePreviousState; + u_int8_t fgIsTransition; + + ASSERT(prStaRec); + if (!prStaRec) + return; + + if (prAdapter->prGlueInfo->u4ReadyFlag == 0) { + DBGLOG(SAA, ERROR, + "Adapter is not ready, SKIP TRANSITION: [%s] -> [%s]\n", + apucDebugAAState[prStaRec->eAuthAssocState], + apucDebugAAState[eNextState]); + return; + } + + do { + + DBGLOG(SAA, STATE, "[SAA]TRANSITION: [%s] -> [%s]\n", + apucDebugAAState[prStaRec->eAuthAssocState], + apucDebugAAState[eNextState]); + + ePreviousState = prStaRec->eAuthAssocState; + + /* NOTE(Kevin): This is the only place to change the + * eAuthAssocState(except initial) + */ + prStaRec->eAuthAssocState = eNextState; + + fgIsTransition = (u_int8_t) FALSE; + switch (prStaRec->eAuthAssocState) { + case AA_STATE_IDLE: + DBGLOG(SAA, TRACE, + "FT: authAlgNum %d, AuthTranNum %d\n", + prStaRec->ucAuthAlgNum, + prStaRec->ucAuthTranNum); + if (prStaRec->ucAuthAlgNum == + AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION && + prStaRec->ucAuthTranNum == + AUTH_TRANSACTION_SEQ_2 && + prStaRec->ucStaState == STA_STATE_1) { + struct PARAM_STATUS_INDICATION rStatus = { + .eStatusType = + ENUM_STATUS_TYPE_FT_AUTH_STATUS}; + struct cfg80211_ft_event_params *prFtEvent = + &prAdapter->prGlueInfo->rFtEventParam; + + prFtEvent->target_ap = prStaRec->aucMacAddr; + /* now, we don't support RIC first */ + prFtEvent->ric_ies = NULL; + prFtEvent->ric_ies_len = 0; + DBGLOG(SAA, INFO, + "FT: notify supplicant to update FT IEs\n"); + kalIndicateStatusAndComplete( + prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + &rStatus, sizeof(rStatus)); + break; + /* wait supplicant update ft ies and then + * continue to send assoc 1 + */ + } + + /* Only trigger this event once */ + if (ePreviousState != prStaRec->eAuthAssocState) { + + if (prRetainedSwRfb) { + if (saaFsmSendEventJoinComplete( + prAdapter, + WLAN_STATUS_SUCCESS, + prStaRec, + prRetainedSwRfb) == + WLAN_STATUS_SUCCESS) { + /* ToDo:: Nothing */ + } else { + eNextState = AA_STATE_RESOURCE; + fgIsTransition = TRUE; + } + } else { + if (saaFsmSendEventJoinComplete( + prAdapter, + WLAN_STATUS_FAILURE, + prStaRec, NULL) == + WLAN_STATUS_RESOURCES) { + eNextState = AA_STATE_RESOURCE; + fgIsTransition = TRUE; + } + } + + } + + /* Free allocated TCM memory */ + if (prStaRec->prChallengeText) { + cnmMemFree(prAdapter, + prStaRec->prChallengeText); + prStaRec->prChallengeText = + (struct IE_CHALLENGE_TEXT *) NULL; + } + + break; + + case SAA_STATE_SEND_AUTH1: + + /* Do tasks in INIT STATE */ + if (prStaRec->ucTxAuthAssocRetryCount >= + prStaRec->ucTxAuthAssocRetryLimit) { + + /* Record the Status Code of Auth Request */ + prStaRec->u2StatusCode = + STATUS_CODE_AUTH_TIMEOUT; + + eNextState = AA_STATE_IDLE; + fgIsTransition = TRUE; + } else { + prStaRec->ucTxAuthAssocRetryCount++; + prStaRec->ucAuthTranNum = + AUTH_TRANSACTION_SEQ_1; + /* Update Station Record - Class 1 Flag */ + cnmStaRecChangeState(prAdapter, prStaRec, + STA_STATE_1); + +#if !CFG_SUPPORT_AAA + rStatus = authSendAuthFrame(prAdapter, prStaRec, + AUTH_TRANSACTION_SEQ_1); +#else + rStatus = authSendAuthFrame(prAdapter, + prStaRec, + prStaRec->ucBssIndex, + NULL, + AUTH_TRANSACTION_SEQ_1, + STATUS_CODE_RESERVED); +#endif /* CFG_SUPPORT_AAA */ + if (rStatus != WLAN_STATUS_SUCCESS) { + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC) + saaFsmRunEventTxReqTimeOut, + (unsigned long) 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 Auth Request */ + prStaRec->u2StatusCode = + STATUS_CODE_AUTH_TIMEOUT; + + eNextState = AA_STATE_IDLE; + fgIsTransition = TRUE; + } else { + prStaRec->ucTxAuthAssocRetryCount++; + prStaRec->ucAuthTranNum = + AUTH_TRANSACTION_SEQ_3; + +#if !CFG_SUPPORT_AAA + rStatus = authSendAuthFrame(prAdapter, + prStaRec, + AUTH_TRANSACTION_SEQ_3); +#else + rStatus = authSendAuthFrame(prAdapter, + prStaRec, + prStaRec->ucBssIndex, + NULL, + AUTH_TRANSACTION_SEQ_3, + STATUS_CODE_RESERVED); +#endif /* CFG_SUPPORT_AAA */ + if (rStatus != WLAN_STATUS_SUCCESS) { + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC) + saaFsmRunEventTxReqTimeOut, + (unsigned long) 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 Auth Request */ + prStaRec->u2StatusCode = + STATUS_CODE_ASSOC_TIMEOUT; + + eNextState = AA_STATE_IDLE; + fgIsTransition = TRUE; + } else { + prStaRec->ucTxAuthAssocRetryCount++; + + rStatus = assocSendReAssocReqFrame(prAdapter, + prStaRec); + if (rStatus != WLAN_STATUS_SUCCESS) { + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC) + saaFsmRunEventTxReqTimeOut, + (unsigned long) 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) + */ +/*----------------------------------------------------------------------------*/ +uint32_t +saaFsmSendEventJoinComplete(IN struct ADAPTER *prAdapter, + IN uint32_t rJoinStatus, + IN struct STA_RECORD *prStaRec, + IN struct SW_RFB *prSwRfb) +{ + struct BSS_INFO *prBssInfo; + + ASSERT(prStaRec); + if (!prStaRec) { + DBGLOG(SAA, ERROR, "[%s]prStaRec is NULL\n", __func__); + return WLAN_STATUS_INVALID_PACKET; + } + if (!prAdapter) { + DBGLOG(SAA, ERROR, "[%s]prAdapter is NULL\n", __func__); + return WLAN_STATUS_INVALID_PACKET; + } + + /* Store limitation about 40Mhz bandwidth capability during + * association. + */ + if (prStaRec->ucBssIndex < prAdapter->ucHwBssIdNum) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + if (prBssInfo != NULL) { + if (rJoinStatus == WLAN_STATUS_SUCCESS) { + prBssInfo->fg40mBwAllowed = + prBssInfo->fgAssoc40mBwAllowed; + /* reset add key action */ + prBssInfo->eKeyAction = SEC_TX_KEY_COMMAND; + } + prBssInfo->fgAssoc40mBwAllowed = FALSE; + } + } + + /* For wlan0 (AP) + p2p0, don't check the prAisBssInfo for the P2P. */ +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) { + struct MSG_SAA_FSM_COMP *prSaaFsmCompMsg; + + prSaaFsmCompMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_SAA_FSM_COMP)); + if (!prSaaFsmCompMsg) + return WLAN_STATUS_RESOURCES; + + if (rJoinStatus == WLAN_STATUS_SUCCESS) + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + + 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, + (struct MSG_HDR *) prSaaFsmCompMsg, + MSG_SEND_METHOD_UNBUF); + + return WLAN_STATUS_SUCCESS; + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + + if (!prAdapter->prAisBssInfo) { + DBGLOG(SAA, ERROR, "prAdapter->prAisBssInfo is NULL\n"); + return WLAN_STATUS_INVALID_PACKET; + } + + if (prStaRec->ucBssIndex == prAdapter->prAisBssInfo->ucBssIndex) { + struct MSG_SAA_FSM_COMP *prSaaFsmCompMsg; + + prSaaFsmCompMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_SAA_FSM_COMP)); + if (!prSaaFsmCompMsg) + return WLAN_STATUS_RESOURCES; + + if (rJoinStatus == WLAN_STATUS_SUCCESS) + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + + 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, + (struct MSG_HDR *) prSaaFsmCompMsg, + MSG_SEND_METHOD_UNBUF); + + return WLAN_STATUS_SUCCESS; + } +#if CFG_ENABLE_BT_OVER_WIFI + else if (IS_STA_BOW_TYPE(prStaRec)) { + /* @TODO: BOW handler */ + + struct MSG_SAA_FSM_COMP *prSaaFsmCompMsg; + + prSaaFsmCompMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_SAA_FSM_COMP)); + 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, + (struct MSG_HDR *) prSaaFsmCompMsg, + MSG_SEND_METHOD_UNBUF); + + return WLAN_STATUS_SUCCESS; + } +#endif + else { + DBGLOG(SAA, ERROR, "Invalid case in %s.\n", __func__); + 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 struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_SAA_FSM_START *prSaaFsmStartMsg; + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prSaaFsmStartMsg = (struct MSG_SAA_FSM_START *) 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); + if (prStaRec->ucAuthAlgNum == AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION && + prStaRec->ucAuthTranNum == AUTH_TRANSACTION_SEQ_2) { + DBGLOG(SAA, ERROR, + "FT: current is waiting FT auth, don't reentry\n"); + return; + } + + /* 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 */ +#if CFG_SUPPORT_CFG80211_AUTH + prStaRec->u2StatusCode = STATUS_CODE_UNSPECIFIED_FAILURE; +#else + prStaRec->u2StatusCode = STATUS_CODE_UNSPECIFIED_FAILURE; +#endif + /* Update the record join time. */ + GET_CURRENT_SYSTIME(&prStaRec->rLastJoinTime); + + prStaRec->ucTxAuthAssocRetryCount = 0; + + if (prStaRec->prChallengeText) { + cnmMemFree(prAdapter, prStaRec->prChallengeText); + prStaRec->prChallengeText = (struct IE_CHALLENGE_TEXT *) NULL; + } + + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + + /* 4 <4> Init the sec fsm */ + /* secFsmInit(prAdapter, prStaRec); */ + + /* 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 struct STA_RECORD 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->ucBssIndex < prAdapter->ucHwBssIdNum) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & + PHY_TYPE_SET_802_11N) && + (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) { + prBssInfo->fgAssoc40mBwAllowed = + cnmBss40mBwPermitted(prAdapter, + prBssInfo->ucBssIndex); + } else { + prBssInfo->fgAssoc40mBwAllowed = FALSE; + } + DBGLOG(RLM, TRACE, "STA 40mAllowed=%d\n", + prBssInfo->fgAssoc40mBwAllowed); + } + +#if CFG_SUPPORT_CFG80211_AUTH + /* skip SAA FSM */ + prStaRec->eAuthAssocSent = AA_SENT_NONE; + saaSendAuthAssoc(prAdapter, prStaRec); +#else + /* 4 <7> Trigger SAA FSM */ + if (prStaRec->ucStaState == STA_STATE_1) + saaFsmSteps(prAdapter, prStaRec, SAA_STATE_SEND_AUTH1, + (struct SW_RFB *) NULL); + else if (prStaRec->ucStaState == STA_STATE_2 || + prStaRec->ucStaState == STA_STATE_3) + saaFsmSteps(prAdapter, prStaRec, + SAA_STATE_SEND_ASSOC1, (struct SW_RFB *) NULL); +#endif +} /* end of saaFsmRunEventStart() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will handle the Continue Event to SAA FSM. + * + * @param[in] prMsgHdr Message of Join Request for a particular STA. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void saaFsmRunEventFTContinue(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_SAA_FT_CONTINUE *prSaaFsmMsg = NULL; + struct STA_RECORD *prStaRec; + u_int8_t fgFtRicRequest = FALSE; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prSaaFsmMsg = (struct MSG_SAA_FT_CONTINUE *)prMsgHdr; + prStaRec = prSaaFsmMsg->prStaRec; + fgFtRicRequest = prSaaFsmMsg->fgFTRicRequest; + cnmMemFree(prAdapter, prMsgHdr); + if ((!prStaRec) || (prStaRec->fgIsInUse == FALSE)) { + DBGLOG(SAA, ERROR, "No Sta Record or it is not in use\n"); + return; + } + if (prStaRec->eAuthAssocState != AA_STATE_IDLE) { + DBGLOG(SAA, ERROR, + "FT: Wrong SAA FSM state %d to continue auth/assoc\n", + prStaRec->eAuthAssocState); + return; + } + DBGLOG(SAA, TRACE, "Continue to do auth/assoc\n"); + if (fgFtRicRequest) + saaFsmSteps(prAdapter, prStaRec, SAA_STATE_SEND_AUTH3, + (struct SW_RFB *)NULL); + else { + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + saaFsmSteps(prAdapter, prStaRec, SAA_STATE_SEND_ASSOC1, + (struct SW_RFB *)NULL); + } +} /* end of saaFsmRunEventFTContinue() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t +saaFsmRunEventTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + + struct STA_RECORD *prStaRec; +#if !CFG_SUPPORT_CFG80211_AUTH + enum ENUM_AA_STATE eNextState; +#endif + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (!prStaRec) + return WLAN_STATUS_INVALID_PACKET; + + ASSERT(prStaRec); + + if (rTxDoneStatus) + DBGLOG(SAA, INFO, + "EVENT-TX DONE [status: %d][seq: %d]: Current Time = %d\n", + rTxDoneStatus, prMsduInfo->ucTxSeqNum, kalGetTimeTick()); + + /* Trigger statistics log if Auth/Assoc Tx failed */ + if (rTxDoneStatus != TX_RESULT_SUCCESS) + wlanTriggerStatsLog(prAdapter, + prAdapter->rWifiVar.u4StatsLogDuration); + +#if CFG_SUPPORT_CFG80211_AUTH + /* check the outgoing frame is matched with + * the last sent frame, ignore the unmatched txdone + */ + if ((prStaRec->eAuthAssocSent >= AA_SENT_AUTH1) && + (prStaRec->eAuthAssocSent <= AA_SENT_AUTH4)) { + if (authCheckTxAuthFrame(prAdapter, prMsduInfo, + prStaRec->eAuthAssocSent) != + WLAN_STATUS_SUCCESS) + return WLAN_STATUS_SUCCESS; + } else if (prStaRec->eAuthAssocSent == AA_SENT_ASSOC1) { + if (assocCheckTxReAssocReqFrame(prAdapter, + prMsduInfo) != WLAN_STATUS_SUCCESS) + return WLAN_STATUS_SUCCESS; + } else + DBGLOG(SAA, WARN, "unexpected sent frame = %d\n", + prStaRec->eAuthAssocSent); + + cnmTimerStopTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer); + + if (rTxDoneStatus == TX_RESULT_SUCCESS) { + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC) + saaFsmRunEventRxRespTimeOut, + (unsigned long) prStaRec); +#if CFG_SUPPORT_CFG80211_AUTH + if (prAdapter->prGlueInfo->rWpaInfo.u4AuthAlg & + AUTH_TYPE_SAE) + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC( + DOT11_RSNA_SAE_RETRANS_PERIOD_TU)); + else +#if CFG_SUPPORT_802_11R + if (prAdapter->prGlueInfo->rWpaInfo.u4AuthAlg & + (AUTH_TYPE_FAST_BSS_TRANSITION)) + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC( + DOT11_11R_AUTHENTICATION_RESPONSE_TIMEOUT_TU)); + else +#endif +#endif + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC( + DOT11_AUTHENTICATION_RESPONSE_TIMEOUT_TU)); + } else {/* Tx failed, do retry if possible */ + if (prStaRec->eAuthAssocSent == AA_SENT_AUTH3) + saaSendAuthSeq3(prAdapter, prStaRec); + else + saaSendAuthAssoc(prAdapter, prStaRec); + } +#else + 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, + (unsigned long) prStaRec); +#if CFG_SUPPORT_CFG80211_AUTH + if (prAdapter->prGlueInfo + ->rWpaInfo.u4AuthAlg & AUTH_TYPE_SAE) + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC( + DOT11_RSNA_SAE_RETRANS_PERIOD_TU)); + else +#endif + 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, + (struct SW_RFB *) 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, + (unsigned long) 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, + (struct SW_RFB *) 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, + (unsigned long) 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, + (struct SW_RFB *) NULL); + } + break; + + default: + break; /* Ignore other cases */ + } +#endif + 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 struct ADAPTER *prAdapter, + IN unsigned long plParamPtr) +{ + struct STA_RECORD *prStaRec = (struct STA_RECORD *) plParamPtr; + + ASSERT(prStaRec); + if (!prStaRec) + return; + + DBGLOG(SAA, LOUD, "EVENT-TIMER: TX REQ TIMEOUT, Current Time = %d\n", + kalGetTimeTick()); + + /* Trigger statistics log if Auth/Assoc Tx timeout */ + wlanTriggerStatsLog(prAdapter, prAdapter->rWifiVar.u4StatsLogDuration); +#if CFG_SUPPORT_CFG80211_AUTH + saaSendAuthAssoc(prAdapter, prStaRec); +#else + switch (prStaRec->eAuthAssocState) { + case SAA_STATE_SEND_AUTH1: + case SAA_STATE_SEND_AUTH3: + case SAA_STATE_SEND_ASSOC1: + saaFsmSteps(prAdapter, prStaRec, + prStaRec->eAuthAssocState, (struct SW_RFB *) NULL); + break; + + default: + return; + } +#endif +} /* 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 struct ADAPTER *prAdapter, + IN unsigned long ulParamPtr) +{ + struct STA_RECORD *prStaRec = (struct STA_RECORD *) ulParamPtr; +#if !CFG_SUPPORT_CFG80211_AUTH + enum ENUM_AA_STATE eNextState; +#endif + DBGLOG(SAA, LOUD, "EVENT-TIMER: RX RESP TIMEOUT, Current Time = %d\n", + kalGetTimeTick()); + + ASSERT(prStaRec); + if (!prStaRec) + return; +#if CFG_SUPPORT_CFG80211_AUTH + /* Retry the last sent frame if possible */ + saaSendAuthAssoc(prAdapter, prStaRec); +#else + 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, + (struct SW_RFB *) NULL); +#endif +} /* 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 struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct STA_RECORD *prStaRec; + uint16_t u2StatusCode; +#if !CFG_SUPPORT_CFG80211_AUTH + enum ENUM_AA_STATE eNextState; +#endif + uint8_t ucWlanIdx; +#if CFG_SUPPORT_CFG80211_AUTH + struct GLUE_INFO *prGlueInfo = NULL; + struct WLAN_AUTH_FRAME *prAuthFrame = + (struct WLAN_AUTH_FRAME *) NULL; + struct net_device *prNetDev = NULL; + struct BSS_INFO *prBssInfo = NULL; + uint8_t ucRoleIdx = 0; +#endif + + + ASSERT(prSwRfb); + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ucWlanIdx = (uint8_t) HAL_RX_STATUS_GET_WLAN_IDX(prSwRfb->prRxStatus); +#if CFG_SUPPORT_CFG80211_AUTH + prGlueInfo = prAdapter->prGlueInfo; + if (!prGlueInfo) { + DBGLOG(SAA, INFO, "No glue info in saaFsmRunEventRxAuth()\n"); + return; + } +#endif + + /* We should have the corresponding Sta Record. */ + if (!prStaRec) { + DBGLOG(SAA, WARN, + "Received a AuthResp: wlanIdx[%d] w/o corresponding staRec\n", + ucWlanIdx); + return; + } + + if (!IS_AP_STA(prStaRec)) + return; + +#if CFG_SUPPORT_CFG80211_AUTH + /* check received auth frame */ + if (authCheckRxAuthFrameStatus(prAdapter, prSwRfb, + prStaRec->eAuthAssocSent, &u2StatusCode) == + WLAN_STATUS_SUCCESS) { + + cnmTimerStopTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer); + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = u2StatusCode; + + /*Report Rx auth frame to upper layer*/ + prAuthFrame = (struct WLAN_AUTH_FRAME *) prSwRfb->pvHeader; + + DBGLOG(INIT, INFO, "Dump rx auth data\n"); + DBGLOG_MEM8(REQ, INFO, prAuthFrame, prSwRfb->u2PacketLen); + + /*add for WEP */ + if ((prAuthFrame->u2AuthAlgNum == + AUTH_ALGORITHM_NUM_SHARED_KEY) && + (prAuthFrame->aucAuthData[0] == + AUTH_TRANSACTION_SEQ_2)) { + /* Reset Send Auth/(Re)Assoc Frame Count */ + prStaRec->ucTxAuthAssocRetryCount = 0; + if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + + authProcessRxAuth2_Auth4Frame( + prAdapter, prSwRfb); + saaSendAuthSeq3(prAdapter, prStaRec); + return; + } + } else { + DBGLOG(SAA, INFO, + "Report RX auth to upper layer with alg:%d, SN:%d, status:%d\n", + prAuthFrame->u2AuthAlgNum, prAuthFrame->aucAuthData[0], + prAuthFrame->aucAuthData[2]); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + if (prAdapter->fgIsP2PRegistered && + IS_STA_IN_P2P(prStaRec)) { + + ucRoleIdx = (uint8_t)prBssInfo->u4PrivateData; + cfg80211_rx_mlme_mgmt( + prGlueInfo->prP2PInfo[ucRoleIdx] + ->aprRoleHandler, + (const u8 *)prAuthFrame, + (size_t)prSwRfb->u2PacketLen); + + prNetDev = prGlueInfo->prP2PInfo[ucRoleIdx] + ->aprRoleHandler; + DBGLOG(SAA, INFO, + "ucRoleIdx %d, name %s, ifindex %d, dev_addr" + MACSTR"\n", + ucRoleIdx, prNetDev->name, + prNetDev->ifindex, + MAC2STR(prNetDev->dev_addr)); + } else { + cfg80211_rx_mlme_mgmt(prGlueInfo->prDevHandler, + (const u8 *)prAuthFrame, + (size_t)prSwRfb->u2PacketLen); + DBGLOG(SAA, INFO, + "name %s, ifindex %d, dev_addr" + MACSTR"\n", + prGlueInfo->prDevHandler->name, + prGlueInfo->prDevHandler->ifindex, + MAC2STR(prGlueInfo->prDevHandler + ->dev_addr)); + } + DBGLOG(SAA, INFO, + "notification of RX Authentication Done\n"); + } + + /* Reset Send Auth/(Re)Assoc Frame Count */ + prStaRec->ucTxAuthAssocRetryCount = 0; + if (u2StatusCode != STATUS_CODE_SUCCESSFUL) { + DBGLOG(SAA, INFO, + "Auth Req was rejected by [" MACSTR + "], Status Code = %d\n", + MAC2STR(prStaRec->aucMacAddr), u2StatusCode); + + /* AIS retry JOIN or indicate JOIN + * FAILURE to upper layer + */ + if (saaFsmSendEventJoinComplete(prAdapter, + WLAN_STATUS_FAILURE, prStaRec, NULL) == + WLAN_STATUS_RESOURCES) { + /* can set a timer and retry later */ + DBGLOG(SAA, WARN, + "[SAA]can't alloc msg for inform AIS join complete\n"); + } + } + } + +#else + 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); + + prStaRec->ucAuthTranNum = + AUTH_TRANSACTION_SEQ_2; + /* after received Auth2 for FT, should indicate + * to supplicant + * and wait response from supplicant + */ + if (prStaRec->ucAuthAlgNum == + AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION) + eNextState = AA_STATE_IDLE; + else if ( + prStaRec->ucAuthAlgNum == + (uint8_t) + AUTH_ALGORITHM_NUM_SHARED_KEY) { + + eNextState = SAA_STATE_SEND_AUTH3; + } else { + /* Update Station Record - Class 2 */ + 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, + (struct SW_RFB *) 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) { + + /* Add for 802.11r handling */ + uint32_t rStatus = + authProcessRxAuth2_Auth4Frame(prAdapter, + prSwRfb); + + prStaRec->ucAuthTranNum = + AUTH_TRANSACTION_SEQ_4; + /* if Auth4 check is failed(check mic in Auth + * ack frame), should disconnect + */ + if (prStaRec->ucAuthAlgNum == + AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION && + rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(SAA, INFO, + "Check Rx Auth4 Frame failed, may be MIC error, %pM, status %d\n", + (prStaRec->aucMacAddr), + u2StatusCode); + /* Reset Send Auth/(Re)Assoc Frame Count + */ + prStaRec->ucTxAuthAssocRetryCount = 0; + saaFsmSteps(prAdapter, prStaRec, + AA_STATE_IDLE, + (struct SW_RFB *)NULL); + break; + } + + /* 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, (struct SW_RFB *) NULL); + } + break; + + default: + break; /* Ignore other cases */ + } +#endif +} /* 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t saaFsmRunEventRxAssoc(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct STA_RECORD *prStaRec; + uint16_t u2StatusCode; +#if !CFG_SUPPORT_CFG80211_AUTH + enum ENUM_AA_STATE eNextState; + struct SW_RFB *prRetainedSwRfb = (struct SW_RFB *) NULL; +#endif + uint32_t rStatus = WLAN_STATUS_SUCCESS; + uint8_t ucWlanIdx; +#if CFG_SUPPORT_CFG80211_AUTH + struct GLUE_INFO *prGlueInfo = NULL; + struct WLAN_ASSOC_RSP_FRAME *prAssocRspFrame = NULL; + struct CONNECTION_SETTINGS *prConnSettings = NULL; + struct BSS_INFO *prBssInfo = NULL; + uint8_t ucRoleIdx = 0; +#endif + + ASSERT(prSwRfb); + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ucWlanIdx = (uint8_t) HAL_RX_STATUS_GET_WLAN_IDX(prSwRfb->prRxStatus); +#if CFG_SUPPORT_CFG80211_AUTH + prGlueInfo = prAdapter->prGlueInfo; + if (!prGlueInfo) { + DBGLOG(SAA, INFO, "No glue info in saaFsmRunEventRxAssoc()\n"); + return WLAN_STATUS_FAILURE; + } + prConnSettings = &prGlueInfo->prAdapter->rWifiVar.rConnSettings; +#endif + DBGLOG(SAA, INFO, "RX Assoc Resp\n"); + + /* We should have the corresponding Sta Record. */ + if (!prStaRec) { + /* ASSERT(0); */ + DBGLOG(SAA, WARN, + "Received a AssocResp: wlanIdx[%d] w/o corresponding staRec\n", + ucWlanIdx); + return rStatus; + } + + if (!IS_AP_STA(prStaRec)) + return rStatus; + +#if CFG_SUPPORT_CFG80211_AUTH + /* 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; + + /*Report Rx assoc frame to upper layer*/ + prAssocRspFrame = + (struct WLAN_ASSOC_RSP_FRAME *) + prSwRfb->pvHeader; + + /* The BSS from cfg80211_ops.assoc must give back to + * cfg80211_send_rx_assoc() or + * to cfg80211_assoc_timeout(). + * To ensure proper refcounting, + * new association requests + * while already associating must be rejected. + */ + DBGLOG(SAA, INFO, + "Report RX Assoc to upper layer, %s\n", + prConnSettings->bss ? "DO IT" : "Oops"); + if (prConnSettings->bss) { +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE + /* [TODO] Set uapsd_queues field to zero first, + * fill it if needed + */ + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { + ucRoleIdx = (uint8_t)prBssInfo->u4PrivateData; + cfg80211_rx_assoc_resp( + prGlueInfo->prP2PInfo[ucRoleIdx] + ->aprRoleHandler, + prConnSettings->bss, + (const u8 *)prAssocRspFrame, + (size_t)prSwRfb->u2PacketLen, 0); + } else { + cfg80211_rx_assoc_resp(prGlueInfo->prDevHandler, + prConnSettings->bss, + (const u8 *)prAssocRspFrame, + (size_t)prSwRfb->u2PacketLen, 0); + } +#else + if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { + ucRoleIdx = (uint8_t)prBssInfo->u4PrivateData; + cfg80211_rx_assoc_resp( + prGlueInfo->prP2PInfo[ucRoleIdx] + ->aprRoleHandler, + prConnSettings->bss, + (const u8 *)prAssocRspFrame, + (size_t)prSwRfb->u2PacketLen); + } else { + cfg80211_rx_assoc_resp(prGlueInfo->prDevHandler, + prConnSettings->bss, + (const u8 *)prAssocRspFrame, + (size_t)prSwRfb->u2PacketLen); + } +#endif + DBGLOG(SAA, INFO, + "Report RX Assoc to upper layer, Done\n"); + prConnSettings->bss = NULL; + } else + DBGLOG(SAA, WARN, + "Rx Assoc Resp without specific BSS\n"); + /* Reset Send Auth/(Re)Assoc Frame Count */ + prStaRec->ucTxAuthAssocRetryCount = 0; + + /* update RCPI */ + ASSERT(prSwRfb->prRxStatusGroup3); + prStaRec->ucRCPI = + nicRxGetRcpiValueFromRxv( + RCPI_MODE_WF0, prSwRfb); + + if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + + /* Update Station Record - Class 3 Flag */ + /* NOTE(Kevin): Moved to AIS FSM + * for roaming issue + * We should deactivate the struct STA_RECORD of + * previous AP before + * activate new one in Driver. + */ + /* cnmStaRecChangeState( + * prStaRec, STA_STATE_3); + */ + /* Clear history. */ + prStaRec->ucJoinFailureCount = 0; + + if (saaFsmSendEventJoinComplete(prAdapter, + WLAN_STATUS_SUCCESS, + prStaRec, prSwRfb) == + WLAN_STATUS_RESOURCES) { + /* can set a timer and retry later */ + DBGLOG(SAA, WARN, + "[SAA]can't alloc msg for inform AIS join complete\n"); + } + + rStatus = WLAN_STATUS_PENDING; + } else { + DBGLOG(SAA, INFO, + "Assoc Req was rejected by [" MACSTR + "], Status Code = %d\n", + MAC2STR(prStaRec->aucMacAddr), + u2StatusCode); + + if (saaFsmSendEventJoinComplete(prAdapter, + WLAN_STATUS_FAILURE, + prStaRec, NULL) == + WLAN_STATUS_RESOURCES) { + /* can set a timer and retry later */ + DBGLOG(SAA, WARN, + "[SAA]can't alloc msg for inform AIS join complete\n"); + } + } + } +#else + 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 struct + * STA_RECORD of previous AP before activate + * new one in Driver. + */ + /* cnmStaRecChangeState(prStaRec, + * STA_STATE_3); + */ + + /* Clear history. */ + prStaRec->ucJoinFailureCount = 0; + + 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 */ + ASSERT(prSwRfb->prRxStatusGroup3); + prStaRec->ucRCPI = + nicRxGetRcpiValueFromRxv(RCPI_MODE_MAX, prSwRfb); + + eNextState = AA_STATE_IDLE; + + saaFsmSteps(prAdapter, prStaRec, + eNextState, prRetainedSwRfb); + } + break; + + default: + break; /* Ignore other cases */ + } +#endif + 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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t saaFsmRunEventRxDeauth(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct STA_RECORD *prStaRec; + struct WLAN_DEAUTH_FRAME *prDeauthFrame; + uint8_t ucWlanIdx; +#if CFG_SUPPORT_CFG80211_AUTH + struct GLUE_INFO *prGlueInfo = NULL; + struct BSS_INFO *prBssInfo = NULL; + struct net_device *prNetDev = NULL; + uint8_t ucRoleIdx = 0; + struct CONNECTION_SETTINGS *prConnSettings = NULL; +#endif + + ASSERT(prSwRfb); +#if CFG_SUPPORT_CFG80211_AUTH + prGlueInfo = prAdapter->prGlueInfo; + if (!prGlueInfo) { + DBGLOG(SAA, INFO, "No glue info in saaFsmRunEventRxDeauth()\n"); + return WLAN_STATUS_FAILURE; + } +#endif + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + prDeauthFrame = (struct WLAN_DEAUTH_FRAME *) prSwRfb->pvHeader; + ucWlanIdx = (uint8_t) HAL_RX_STATUS_GET_WLAN_IDX(prSwRfb->prRxStatus); + + DBGLOG(SAA, WARN, "Rx Deauth frame ,DA[" MACSTR "] SA[" MACSTR + "] BSSID[" MACSTR "] ReasonCode[0x%x]\n", + MAC2STR(prDeauthFrame->aucDestAddr), + MAC2STR(prDeauthFrame->aucSrcAddr), + MAC2STR(prDeauthFrame->aucBSSID), prDeauthFrame->u2ReasonCode); + + do { + + /* We should have the corresponding Sta Record. */ + if (!prStaRec) { + DBGLOG(SAA, WARN, + "Received a Deauth: wlanIdx[%d] w/o corresponding staRec\n", + ucWlanIdx); + break; + } + + if (IS_STA_IN_AIS(prStaRec)) { + struct BSS_INFO *prAisBssInfo; + + if (!IS_AP_STA(prStaRec)) + break; + + /* if state != CONNECTED, don't do disconnect again */ + if (prAdapter->prGlueInfo->eParamMediaStateIndicated != + PARAM_MEDIA_STATE_CONNECTED) + break; + + prAisBssInfo = prAdapter->prAisBssInfo; + + 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 CFG_SUPPORT_802_11W + struct AIS_SPECIFIC_BSS_INFO + *prAisSpecBssInfo; + + prAisSpecBssInfo = + &(prAdapter->rWifiVar. + rAisSpecificBssInfo); + + DBGLOG(RSN, INFO, + "QM RX MGT: Deauth frame, P=%d Sec=%d CM=%d BC=%d fc=%02x\n", + prAisSpecBssInfo-> + fgMgmtProtection, (uint8_t) + HAL_RX_STATUS_GET_SEC_MODE + (prSwRfb->prRxStatus), + HAL_RX_STATUS_IS_CIPHER_MISMATCH + (prSwRfb->prRxStatus), + IS_BMCAST_MAC_ADDR + (prDeauthFrame->aucDestAddr), + prDeauthFrame->u2FrameCtrl); + if (prAisSpecBssInfo->fgMgmtProtection + && HAL_RX_STATUS_IS_CIPHER_MISMATCH + (prSwRfb->prRxStatus) + /* HAL_RX_STATUS_GET_SEC_MODE + * (prSwRfb->prRxStatus) != + * CIPHER_SUITE_BIP + */ + ) { + saaChkDeauthfrmParamHandler( + prAdapter, prSwRfb, + prStaRec); + return WLAN_STATUS_SUCCESS; + } +#endif +#if CFG_SUPPORT_CFG80211_AUTH + DBGLOG(SAA, INFO, + "notification of RX deauthentication %d\n", + prSwRfb->u2PacketLen); + + cfg80211_rx_mlme_mgmt( + prGlueInfo->prDevHandler, + (uint8_t *)prDeauthFrame, + (size_t)prSwRfb->u2PacketLen); + DBGLOG(SAA, INFO, + "notification of RX deauthentication Done\n"); +#endif +#if CFG_DISCONN_DEBUG_FEATURE + g_rDisconnInfoTemp.u2DisassocSeqNum = + (prDeauthFrame->u2SeqCtrl & + MASK_SC_SEQ_NUM) >> + MASK_SC_SEQ_NUM_OFFSET; +#endif + saaSendDisconnectMsgHandler(prAdapter, + prStaRec, + prAisBssInfo, + FRM_DEAUTH); + } + } + } +#if CFG_ENABLE_WIFI_DIRECT + else if (prAdapter->fgIsP2PRegistered && + IS_STA_IN_P2P(prStaRec)) { +#if CFG_SUPPORT_CFG80211_AUTH + DBGLOG(SAA, INFO, + "notification of RX deauthentication %d\n", + prSwRfb->u2PacketLen); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + ucRoleIdx = (uint8_t)prBssInfo->u4PrivateData; + cfg80211_rx_mlme_mgmt( + prGlueInfo->prP2PInfo[ucRoleIdx] + ->aprRoleHandler, + (uint8_t *)prDeauthFrame, + (size_t)prSwRfb->u2PacketLen); + + DBGLOG(SAA, INFO, + "notification of RX deauthentication Done\n"); + + prConnSettings = &prGlueInfo->prAdapter + ->rWifiVar.rConnSettings; + prConnSettings->fgIsP2pConn = FALSE; + prNetDev = prGlueInfo + ->prP2PInfo[ucRoleIdx]->aprRoleHandler; + DBGLOG(SAA, INFO, + "ucRoleIdx %d, name %s, ifindex %d, dev_addr" + MACSTR"\n", + ucRoleIdx, prNetDev->name, + prNetDev->ifindex, + MAC2STR(prNetDev->dev_addr)); +#endif + /* TODO(Kevin) */ + p2pRoleFsmRunEventRxDeauthentication(prAdapter, + prStaRec, + prSwRfb); + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (IS_STA_BOW_TYPE(prStaRec)) { +#if CFG_SUPPORT_CFG80211_AUTH + DBGLOG(SAA, INFO, + "notification of RX deauthentication %d\n", + prSwRfb->u2PacketLen); + cfg80211_rx_mlme_mgmt( + prAdapter->prGlueInfo->prDevHandler, + (uint8_t *)prDeauthFrame, + (size_t)prSwRfb->u2PacketLen); + DBGLOG(SAA, INFO, + "notification of RX deauthentication Done\n"); +#endif + bowRunEventRxDeAuth(prAdapter, prStaRec, prSwRfb); + } +#endif + else + ASSERT(0); + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; + +} /* end of saaFsmRunEventRxDeauth() */ + +/* for AOSP */ +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will check param of deauth frame and reson code for + * deauth. + * + * @param[in] + * + * @retval + */ +/*----------------------------------------------------------------------------*/ + +void saaChkDeauthfrmParamHandler(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb, + IN struct STA_RECORD *prStaRec) +{ + struct WLAN_DEAUTH_FRAME *prDeauthFrame; + + do { + prDeauthFrame = (struct WLAN_DEAUTH_FRAME *) prSwRfb->pvHeader; + if (!IS_BMCAST_MAC_ADDR(prDeauthFrame->aucDestAddr) && + (prStaRec->u2ReasonCode == REASON_CODE_CLASS_2_ERR + || prStaRec->u2ReasonCode == REASON_CODE_CLASS_3_ERR)) { + DBGLOG(RSN, INFO, "QM RX MGT: rsnStartSaQuery\n"); + /* MFP test plan 5.3.3.5 */ + rsnStartSaQuery(prAdapter); + } else { + DBGLOG(RSN, INFO, "RXM: Drop unprotected Mgmt frame\n"); + DBGLOG(RSN, INFO, + "RXM: (MAC RX Done) RX (u2StatusFlag=0x%x) (ucKIdxSecMode=0x%x) (ucWlanIdx=0x%x)\n", + prSwRfb->prRxStatus->u2StatusFlag, + prSwRfb->prRxStatus->ucTidSecMode, + prSwRfb->prRxStatus->ucWlanIdx); + } + } while (0); +} + +/* for AOSP */ +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will check and send disconnect message to AIS module + * + * @param[in] + * + * @retval + */ +/*----------------------------------------------------------------------------*/ +void +saaSendDisconnectMsgHandler(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN struct BSS_INFO *prAisBssInfo, + IN enum ENUM_AA_FRM_TYPE eFrmType) +{ + do { + if (eFrmType == FRM_DEAUTH) { + if (prStaRec->ucStaState == STA_STATE_3) { + struct MSG_AIS_ABORT *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 = + (struct MSG_AIS_ABORT *) + cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_AIS_ABORT)); + 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, + (struct MSG_HDR *) prAisAbortMsg, + MSG_SEND_METHOD_BUF); + } else { + /* TODO(Kevin): Joining Abort */ + } + } else { /* FRM_DISASSOC */ + if (prStaRec->ucStaState == STA_STATE_3) { + struct MSG_AIS_ABORT *prAisAbortMsg; + + prAisAbortMsg = (struct MSG_AIS_ABORT *) + cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(struct MSG_AIS_ABORT)); + 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, + (struct MSG_HDR *) prAisAbortMsg, + MSG_SEND_METHOD_BUF); + } else { + /* TODO(Kevin): Joining Abort */ + } + } + if (prAisBssInfo) + prAisBssInfo->u2DeauthReason = prStaRec->u2ReasonCode; +#if CFG_DISCONN_DEBUG_FEATURE + g_rDisconnInfoTemp.ucTrigger = + DISCONNECT_TRIGGER_PASSIVE; + g_rDisconnInfoTemp.ucDisassocReason = + prStaRec->u2ReasonCode; +#endif + } while (0); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t saaFsmRunEventRxDisassoc(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct STA_RECORD *prStaRec; + struct WLAN_DISASSOC_FRAME *prDisassocFrame; + uint8_t ucWlanIdx; +#if CFG_SUPPORT_CFG80211_AUTH + struct GLUE_INFO *prGlueInfo = NULL; + struct wireless_dev *wdev = NULL; + struct BSS_INFO *prBssInfo = NULL; + struct net_device *prNetDev = NULL; + uint8_t ucRoleIdx = 0; + struct CONNECTION_SETTINGS *prConnSettings = NULL; +#endif + + ASSERT(prSwRfb); +#if CFG_SUPPORT_CFG80211_AUTH + prGlueInfo = prAdapter->prGlueInfo; + if (!prGlueInfo) { + DBGLOG(SAA, INFO, + "No glue info in saaFsmRunEventRxDisassoc()\n"); + return WLAN_STATUS_FAILURE; + } + wdev = prAdapter->prGlueInfo->prDevHandler->ieee80211_ptr; +#endif + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + prDisassocFrame = (struct WLAN_DISASSOC_FRAME *) prSwRfb->pvHeader; + ucWlanIdx = (uint8_t) HAL_RX_STATUS_GET_WLAN_IDX(prSwRfb->prRxStatus); + + DBGLOG(SAA, INFO, + "Rx Disassoc frame from BSSID[" MACSTR "] DA[" MACSTR + "] ReasonCode[0x%x]\n", + MAC2STR(prDisassocFrame->aucBSSID), + MAC2STR(prDisassocFrame->aucDestAddr), + prDisassocFrame->u2ReasonCode); + + do { + + /* We should have the corresponding Sta Record. */ + if (!prStaRec) { + DBGLOG(SAA, WARN, + "Received a DisAssoc: wlanIdx[%d] w/o corresponding staRec\n", + ucWlanIdx); + break; + } + + if (IS_STA_IN_AIS(prStaRec)) { + struct BSS_INFO *prAisBssInfo; + + if (!IS_AP_STA(prStaRec)) + break; + + prAisBssInfo = prAdapter->prAisBssInfo; + + 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 CFG_SUPPORT_802_11W + struct AIS_SPECIFIC_BSS_INFO + *prAisSpecBssInfo; + + prAisSpecBssInfo = + &(prAdapter->rWifiVar. + rAisSpecificBssInfo); + + DBGLOG(RSN, INFO, + "QM RX MGT: Disassoc frame, P=%d Sec=%d CM=%d BC=%d fc=%02x\n", + prAisSpecBssInfo-> + fgMgmtProtection, (uint8_t) + HAL_RX_STATUS_GET_SEC_MODE + (prSwRfb->prRxStatus), + HAL_RX_STATUS_IS_CIPHER_MISMATCH + (prSwRfb->prRxStatus), + IS_BMCAST_MAC_ADDR + (prDisassocFrame->aucDestAddr), + prDisassocFrame->u2FrameCtrl); + if (IS_STA_IN_AIS(prStaRec) && + prAisSpecBssInfo->fgMgmtProtection + && HAL_RX_STATUS_IS_CIPHER_MISMATCH + (prSwRfb->prRxStatus) + /* HAL_RX_STATUS_GET_SEC_MODE( + * prSwRfb->prRxStatus) != + * CIPHER_SUITE_CCMP + */ + ) { + /* prDisassocFrame = + * (P_WLAN_DISASSOC_FRAME_T) + * prSwRfb->pvHeader; + */ + saaChkDisassocfrmParamHandler( + prAdapter, + prDisassocFrame, prStaRec, + prSwRfb); + return WLAN_STATUS_SUCCESS; + } +#endif +#if CFG_SUPPORT_CFG80211_AUTH + DBGLOG(SAA, INFO, + "notification of RX disassociation %d\n", + prSwRfb->u2PacketLen); + if (wdev->current_bss) + cfg80211_rx_mlme_mgmt( + prGlueInfo->prDevHandler, + (uint8_t *)prDisassocFrame, + (size_t)prSwRfb->u2PacketLen); + prAdapter->rWifiVar. + rConnSettings.bss = NULL; + DBGLOG(SAA, INFO, + "notification of RX disassociation Done\n"); +#endif +#if CFG_DISCONN_DEBUG_FEATURE + g_rDisconnInfoTemp.u2DisassocSeqNum = + (prDisassocFrame->u2SeqCtrl & + MASK_SC_SEQ_NUM) >> + MASK_SC_SEQ_NUM_OFFSET; +#endif + saaSendDisconnectMsgHandler(prAdapter, + prStaRec, + prAisBssInfo, + FRM_DISASSOC); + } + } + } +#if CFG_ENABLE_WIFI_DIRECT + else if (prAdapter->fgIsP2PRegistered && + (IS_STA_IN_P2P(prStaRec))) { + /* TODO(Kevin) */ +#if CFG_SUPPORT_CFG80211_AUTH + DBGLOG(SAA, INFO, + "notification of RX disassociation %d\n", + prSwRfb->u2PacketLen); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prStaRec->ucBssIndex); + ucRoleIdx = (uint8_t)prBssInfo->u4PrivateData; + wdev = prAdapter->prGlueInfo->prP2PInfo[ucRoleIdx] + ->aprRoleHandler->ieee80211_ptr; + + if (wdev->current_bss) + cfg80211_rx_mlme_mgmt( + prGlueInfo->prP2PInfo[ucRoleIdx] + ->aprRoleHandler, + (uint8_t *)prDisassocFrame, + (size_t)prSwRfb->u2PacketLen); + DBGLOG(SAA, INFO, + "notification of RX disassociation Done\n"); + prConnSettings = &prGlueInfo->prAdapter + ->rWifiVar.rConnSettings; + prConnSettings->fgIsP2pConn = FALSE; + prNetDev = prGlueInfo + ->prP2PInfo[ucRoleIdx]->aprRoleHandler; + DBGLOG(SAA, INFO, + "ucRoleIdx %d, name %s, ifindex %d, dev_addr" + MACSTR"\n", + ucRoleIdx, + prNetDev->name, + prNetDev->ifindex, + MAC2STR(prNetDev->dev_addr)); +#endif + p2pRoleFsmRunEventRxDisassociation(prAdapter, + prStaRec, prSwRfb); + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (IS_STA_BOW_TYPE(prStaRec)) { + /* ToDo:: nothing */ + /* TODO(Kevin) */ +#if CFG_SUPPORT_CFG80211_AUTH + DBGLOG(SAA, INFO, + "notification of RX disassociation %d\n", + prSwRfb->u2PacketLen); + if (wdev->current_bss) + cfg80211_rx_mlme_mgmt( + prAdapter->prGlueInfo->prDevHandler, + (uint8_t *)prDisassocFrame, + (size_t)prSwRfb->u2PacketLen); + DBGLOG(SAA, INFO, + "notification of RX disassociation Done\n"); +#endif + + } +#endif + else + ASSERT(0); + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; + +} /* end of saaFsmRunEventRxDisassoc() */ + +/* for AOSP */ +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will check param of Disassoc frame and reson code for + * Disassoc. + * + * @param[in] + * + * @retval + */ +/*----------------------------------------------------------------------------*/ + +void +saaChkDisassocfrmParamHandler(IN struct ADAPTER *prAdapter, + IN struct WLAN_DISASSOC_FRAME *prDisassocFrame, + IN struct STA_RECORD *prStaRec, + IN struct SW_RFB *prSwRfb) +{ + if (!IS_BMCAST_MAC_ADDR(prDisassocFrame->aucDestAddr) && + (prStaRec->u2ReasonCode == REASON_CODE_CLASS_2_ERR || + prStaRec->u2ReasonCode == REASON_CODE_CLASS_3_ERR)) { + /* MFP test plan 5.3.3.5 */ + DBGLOG(RSN, INFO, "QM RX MGT: rsnStartSaQuery\n"); + rsnStartSaQuery(prAdapter); + } else { + DBGLOG(RSN, INFO, "RXM: Drop unprotected Mgmt frame\n"); + DBGLOG(RSN, INFO, + "RXM: (MAC RX Done) RX (u2StatusFlag=0x%x) (ucKIdxSecMode=0x%x) (ucWlanIdx=0x%x)\n", + prSwRfb->prRxStatus->u2StatusFlag, + prSwRfb->prRxStatus->ucTidSecMode, + prSwRfb->prRxStatus->ucWlanIdx); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_SAA_FSM_ABORT *prSaaFsmAbortMsg; + struct STA_RECORD *prStaRec; + + ASSERT(prMsgHdr); + + prSaaFsmAbortMsg = (struct MSG_SAA_FSM_ABORT *) 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) { + DBGLOG(SAA, LOUD, + "EVENT-ABORT: Previous Auth/Assoc State == %s.\n", + apucDebugAAState[prStaRec->eAuthAssocState]); + } +#if 0 + /* For the Auth/Assoc State to IDLE */ + prStaRec->eAuthAssocState = AA_STATE_IDLE; +#else + /* Free this StaRec */ + cnmStaRecFree(prAdapter, prStaRec); +#endif +} /* end of saaFsmRunEventAbort() */ + +/* TODO(Kevin): following code will be modified and move to AIS FSM */ +#if 0 +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will send Join Timeout Event to JOIN FSM. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * + * \retval WLAN_STATUS_FAILURE Fail because of Join Timeout + */ +/*----------------------------------------------------------------------------*/ +uint32_t joinFsmRunEventJoinTimeOut(IN struct ADAPTER *prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + struct STA_RECORD *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 struct ADAPTER *prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + struct BSS_DESC *prBssDesc; + + DEBUGFUNC("joinAdoptParametersFromPeerBss"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + prBssDesc = prJoinInfo->prBssDesc; + + /* 4 <1> Adopt Peer BSS' PHY TYPE */ + prAdapter->eCurrentPhyType = prBssDesc->ePhyType; + + DBGLOG(JOIN, INFO, "Target BSS[%s]'s PhyType = %s\n", + prBssDesc->aucSSID, (prBssDesc->ePhyType == PHY_TYPE_ERP_INDEX) ? + "ERP" : "HR_DSSS"); + + /* 4 <2> Adopt Peer BSS' Frequency(Band/Channel) */ + DBGLOG(JOIN, INFO, "Target BSS's Channel = %d, Band = %d\n", + prBssDesc->ucChannelNum, prBssDesc->eBand); + + nicSwitchChannel(prAdapter, prBssDesc->eBand, + prBssDesc->ucChannelNum, 10); + + prJoinInfo->fgIsParameterAdopted = TRUE; +} /* end of joinAdoptParametersFromPeerBss() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will adopt the parameters from current associated BSS. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void joinAdoptParametersFromCurrentBss(IN struct ADAPTER *prAdapter) +{ + /* P_JOIN_INFO_T prJoinInfo = &prAdapter->rJoinInfo; */ + struct BSS_INFO *prBssInfo; + + ASSERT(prAdapter); + prBssInfo = &prAdapter->rBssInfo; + + /* 4 <1> Adopt current BSS' PHY TYPE */ + prAdapter->eCurrentPhyType = prBssInfo->ePhyType; + + /* 4 <2> Adopt current BSS' Frequency(Band/Channel) */ + DBGLOG(JOIN, INFO, "Current BSS's Channel = %d, Band = %d\n", + prBssInfo->ucChnl, prBssInfo->eBand); + + nicSwitchChannel(prAdapter, prBssInfo->eBand, prBssInfo->ucChnl, 10); +} /* end of joinAdoptParametersFromCurrentBss() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will update all the SW variables and HW MCR registers + * after the association with target BSS. + * + * \param[in] prAdapter Pointer to the Adapter structure. + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void joinComplete(IN struct ADAPTER *prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + struct BSS_DESC *prBssDesc; + P_PEER_BSS_INFO_T prPeerBssInfo; + struct BSS_INFO *prBssInfo; + struct CONNECTION_SETTINGS *prConnSettings; + struct STA_RECORD *prStaRec; + struct TX_CTRL *prTxCtrl; +#if CFG_SUPPORT_802_11D + struct IE_COUNTRY *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 */ + /* Our BSS's PHY_TYPE is ERP now. */ + if ((prBssInfo->ePhyType == PHY_TYPE_ERP_INDEX) && + (prBssDesc->fgIsERPPresent)) { + + prBssInfo->fgIsERPPresent = TRUE; + /* Save the ERP for later check */ + prBssInfo->ucERP = prBssDesc->ucERP; + } 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) { + struct DOMAIN_INFO_ENTRY rDomainInfo; + + if (domainGetDomainInfoByScanResult(prAdapter, &rDomainInfo)) { + if (prBssDesc->prIECountry) { + prIECountry = prBssDesc->prIECountry; + + domainParseCountryInfoElem(prIECountry, + &prBssInfo->rDomainInfo); + + /* use the domain get from the BSS info */ + prBssInfo->fgIsCountryInfoPresent = TRUE; + nicSetupOpChnlList(prAdapter, + prBssInfo->rDomainInfo.u2CountryCode, FALSE); + } else { + /* use the domain get from the scan result */ + prBssInfo->fgIsCountryInfoPresent = TRUE; + nicSetupOpChnlList(prAdapter, + rDomainInfo.u2CountryCode, + FALSE); + } + } + } +#endif + + /* 4 <2.K> Signal Power of the associated AP */ + prBssInfo->rRcpi = prBssDesc->rRcpi; + prBssInfo->rRssi = RCPI_TO_dBm(prBssInfo->rRcpi); + GET_CURRENT_SYSTIME(&prBssInfo->rRssiLastUpdateTime); + + /* 4 <2.L> Capability Field of the associated AP */ + prBssInfo->u2CapInfo = prBssDesc->u2CapInfo; + + DBGLOG(JOIN, INFO, + "prBssInfo-> fgIsERPPresent = %d, ucERP = %02x, rRcpi = %d, rRssi = %ld\n", + prBssInfo->fgIsERPPresent, prBssInfo->ucERP, + prBssInfo->rRcpi, prBssInfo->rRssi); + +/* 4 <3> Update BSS_INFO_T from PEER_BSS_INFO_T & NIC RATE FUNC */ + /* 4 <3.A> Association ID */ + prBssInfo->u2AssocId = prPeerBssInfo->u2AssocId; + + /* 4 <3.B> WMM Information */ + if (prAdapter->fgIsEnableWMM && + (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_SUPPORT_WMM)) { + + prBssInfo->fgIsWmmAssoc = TRUE; + prTxCtrl->rTxQForVoipAccess = TXQ_AC3; + + qosWmmInfoInit(&prBssInfo->rWmmInfo, + (prBssInfo->ePhyType == PHY_TYPE_HR_DSSS_INDEX) + ? TRUE : FALSE); + + if (prPeerBssInfo->rWmmInfo.ucWmmFlag & + WMM_FLAG_AC_PARAM_PRESENT) { + kalMemCopy(&prBssInfo->rWmmInfo, + &prPeerBssInfo->rWmmInfo, + sizeof(WMM_INFO_T)); + } else { + kalMemCopy(&prBssInfo->rWmmInfo, + &prPeerBssInfo->rWmmInfo, + sizeof(WMM_INFO_T) - + sizeof(prPeerBssInfo-> + rWmmInfo.arWmmAcParams)); + } + } else { + prBssInfo->fgIsWmmAssoc = FALSE; + prTxCtrl->rTxQForVoipAccess = TXQ_AC1; + + kalMemZero(&prBssInfo->rWmmInfo, sizeof(WMM_INFO_T)); + } + + /* 4 <3.C> Operational Rate Set & BSS Basic Rate Set */ + prBssInfo->u2OperationalRateSet = prPeerBssInfo->u2OperationalRateSet; + prBssInfo->u2BSSBasicRateSet = prPeerBssInfo->u2BSSBasicRateSet; + + /* 4 <3.D> Short Preamble */ + if (prBssInfo->fgIsERPPresent) { + + /* NOTE(Kevin 2007/12/24): Truth Table. + * Short Preamble Bit in + * Final Drv Set + * TRUE FALSE FALSE FALSE(#1) + * TRUE FALSE TRUE FALSE + * FALSE FALSE FALSE FALSE(#1) + * FALSE FALSE TRUE FALSE + * TRUE TRUE FALSE TRUE(#2) + * TRUE TRUE TRUE FALSE(#2) + * FALSE TRUE FALSE FALSE(#3) + * FALSE TRUE TRUE FALSE(#4) + * #1: shouldn't have such case, use the AssocResp + * #2: follow ERP + * #3: shouldn't have such case, and we should set to FALSE + * #4: we should set to FALSE + */ + if ((prPeerBssInfo->fgIsShortPreambleAllowed) && + ((prConnSettings->ePreambleType == PREAMBLE_TYPE_SHORT) || + /* Short Preamble Option Enable is TRUE */ + ((prConnSettings->ePreambleType == PREAMBLE_TYPE_AUTO) && + (prBssDesc->u2CapInfo & CAP_INFO_SHORT_PREAMBLE)))) { + + prBssInfo->fgIsShortPreambleAllowed = TRUE; + + if (prBssInfo->ucERP & ERP_INFO_BARKER_PREAMBLE_MODE) + prBssInfo->fgUseShortPreamble = FALSE; + else + prBssInfo->fgUseShortPreamble = TRUE; + } else { + prBssInfo->fgIsShortPreambleAllowed = FALSE; + prBssInfo->fgUseShortPreamble = FALSE; + } + } else { + /* NOTE(Kevin 2007/12/24): Truth Table. + * Short Preamble Bit in + * Final Driver Setting(Short) + * TRUE FALSE FALSE + * FALSE FALSE FALSE + * TRUE TRUE TRUE + * FALSE TRUE(status success) TRUE + * --> Honor the result of prPeerBssInfo. + */ + + prBssInfo->fgIsShortPreambleAllowed = + prBssInfo->fgUseShortPreamble = + prPeerBssInfo->fgIsShortPreambleAllowed; + } + + DBGLOG(JOIN, INFO, + "prBssInfo->fgIsShortPreambleAllowed = %d, prBssInfo->fgUseShortPreamble = %d\n", + prBssInfo->fgIsShortPreambleAllowed, + prBssInfo->fgUseShortPreamble); + + /* 4 <3.E> Short Slot Time */ + /* AP support Short Slot Time */ + prBssInfo->fgUseShortSlotTime = prPeerBssInfo->fgUseShortSlotTime; + + 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) { + uint16_t 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, (uint8_t) TXQ_DATA_MASK, + (uint8_t) 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, + (void *) NULL, 0); +} /* end of joinComplete() */ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/scan.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/scan.c new file mode 100644 index 0000000000000..8d229bb8d19d9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/scan.c @@ -0,0 +1,4373 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + + +/******************************************************************************* + * C O M P I L E 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_STRENGTH_THRESHOLD (32) +#define ROAMING_NO_SWING_RCPI_STEP (10) +#define REPLICATED_BEACON_FRESH_PERIOD (10000) +#define REPLICATED_BEACON_TIME_THRESHOLD (3000) + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +/* The order of aucScanLogPrefix should be aligned the order + * of enum ENUM_SCAN_LOG_PREFIX + */ +const char aucScanLogPrefix[][SCAN_LOG_PREFIX_MAX_LEN] = { + /* Scan */ + "[SCN:100:K2D]", /* LOG_SCAN_REQ_K2D */ + "[SCN:200:D2F]", /* LOG_SCAN_REQ_D2F */ + "[SCN:300:F2D]", /* LOG_SCAN_RESULT_F2D */ + "[SCN:400:D2K]", /* LOG_SCAN_RESULT_D2K */ + "[SCN:500:F2D]", /* LOG_SCAN_DONE_F2D */ + "[SCN:600:D2K]", /* LOG_SCAN_DONE_D2K */ + + /* Sched scan */ + "[SCN:700:K2D]", /* LOG_SCHED_SCAN_REQ_START_K2D */ + "[SCN:800:D2F]", /* LOG_SCHED_SCAN_REQ_START_D2F */ + "[SCN:750:K2D]", /* LOG_SCHED_SCAN_REQ_STOP_K2D */ + "[SCN:850:D2F]", /* LOG_SCHED_SCAN_REQ_STOP_D2F */ + "[SCN:900:F2D]", /* LOG_SCHED_SCAN_DONE_F2D */ + "[SCN:1000:D2K]", /* LOG_SCHED_SCAN_DONE_D2K */ + + /* Scan abort */ + "[SCN:1100:K2D]", /* LOG_SCAN_ABORT_REQ_K2D */ + "[SCN:1200:D2F]", /* LOG_SCAN_ABORT_REQ_D2F */ + "[SCN:1300:D2K]", /* LOG_SCAN_ABORT_DONE_D2K */ + + /* Driver only */ + "[SCN:0:D2D]", /* LOG_SCAN_D2D */ + + /* Last one */ + "" /* LOG_SCAN_MAX */ +}; + +/******************************************************************************* + * 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 struct ADAPTER *prAdapter) +{ + struct SCAN_INFO *prScanInfo; + struct BSS_DESC *prBSSDesc; + uint8_t *pucBSSBuff; + uint32_t i; +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + struct ROAM_BSS_DESC *prRoamBSSDesc; + uint8_t *pucRoamBSSBuff; +#endif + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + pucBSSBuff = &prScanInfo->aucScanBuffer[0]; +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + pucRoamBSSBuff = &prScanInfo->aucScanRoamBuffer[0]; +#endif + + log_dbg(SCN, TRACE, "->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((void *) pucBSSBuff, SCN_MAX_BUFFER_SIZE); +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + kalMemZero((void *) pucRoamBSSBuff, SCN_ROAM_MAX_BUFFER_SIZE); +#endif + + LINK_INITIALIZE(&prScanInfo->rFreeBSSDescList); + LINK_INITIALIZE(&prScanInfo->rBSSDescList); +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + LINK_INITIALIZE(&prScanInfo->rRoamFreeBSSDescList); + LINK_INITIALIZE(&prScanInfo->rRoamBSSDescList); +#endif + + for (i = 0; i < CFG_MAX_NUM_BSS_LIST; i++) { + + prBSSDesc = (struct BSS_DESC *) pucBSSBuff; + + LINK_INSERT_TAIL(&prScanInfo->rFreeBSSDescList, + &prBSSDesc->rLinkEntry); + + pucBSSBuff += ALIGN_4(sizeof(struct BSS_DESC)); + } + /* Check if the memory allocation consist with + * this initialization function + */ + ASSERT(((unsigned long) pucBSSBuff + - (unsigned long)&prScanInfo->aucScanBuffer[0]) + == SCN_MAX_BUFFER_SIZE); + +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + for (i = 0; i < CFG_MAX_NUM_ROAM_BSS_LIST; i++) { + prRoamBSSDesc = (struct ROAM_BSS_DESC *) pucRoamBSSBuff; + + LINK_INSERT_TAIL(&prScanInfo->rRoamFreeBSSDescList, + &prRoamBSSDesc->rLinkEntry); + + pucRoamBSSBuff += ALIGN_4(sizeof(struct ROAM_BSS_DESC)); + } + ASSERT(((unsigned long) pucRoamBSSBuff + - (unsigned long)&prScanInfo->aucScanRoamBuffer[0]) + == SCN_ROAM_MAX_BUFFER_SIZE); +#endif + /* reset freest channel information */ + prScanInfo->fgIsSparseChannelValid = FALSE; + + prScanInfo->fgIsScanForFull2Partial = FALSE; + + /* reset Sched scan state */ + prScanInfo->fgSchedScanning = FALSE; + /*Support AP Selection */ + prScanInfo->u4ScanUpdateIdx = 0; +} /* end of scnInit() */ + +void scnFreeAllPendingScanRquests(IN struct ADAPTER *prAdapter) +{ + struct SCAN_INFO *prScanInfo; + struct MSG_HDR *prMsgHdr; + struct MSG_SCN_SCAN_REQ *prScanReqMsg; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + /* check for pending scanning requests */ + while (!LINK_IS_EMPTY(&(prScanInfo->rPendingMsgList))) { + + /* load next message from pending list as scan parameters */ + LINK_REMOVE_HEAD(&(prScanInfo->rPendingMsgList), + prMsgHdr, struct MSG_HDR *); + if (prMsgHdr) { + prScanReqMsg = (struct MSG_SCN_SCAN_REQ *) prMsgHdr; + + log_dbg(SCN, INFO, "Free scan request eMsgId[%d] ucSeqNum [%d] BSSID[%d]!!\n", + prMsgHdr->eMsgId, + prScanReqMsg->ucSeqNum, + prScanReqMsg->ucBssIndex); + + cnmMemFree(prAdapter, prMsgHdr); + } else { + /* should not deliver to this function */ + ASSERT(0); + } + /* switch to next state */ + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function is used by SCN to uninitialize its variables + * + * @param (none) + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void scnUninit(IN struct ADAPTER *prAdapter) +{ + struct SCAN_INFO *prScanInfo; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + log_dbg(SCN, INFO, "%s()\n", __func__); + + scnFreeAllPendingScanRquests(prAdapter); + + /* 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); +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + LINK_INITIALIZE(&prScanInfo->rRoamFreeBSSDescList); + LINK_INITIALIZE(&prScanInfo->rRoamBSSDescList); +#endif +} /* 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 + */ +/*----------------------------------------------------------------------------*/ +struct BSS_DESC *scanSearchBssDescByBssid(IN struct ADAPTER *prAdapter, + IN uint8_t aucBSSID[]) +{ + return scanSearchBssDescByBssidAndSsid(prAdapter, aucBSSID, + FALSE, NULL); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Check if the bit of the given bitmap is set + * The bitmap should be unsigned int based, which means that this function + * doesn't support other format bitmap, e.g. char array or short array + * + * @param[in] bit which bit to check. + * @param[in] bitMap bitmap array + * @param[in] bitMapSize bytes of bitmap + * + * @return TRUE if the bit of the given bitmap is set, FALSE otherwise + */ +/*----------------------------------------------------------------------------*/ +u_int8_t scanIsBitSet(IN uint32_t bit, IN uint32_t bitMap[], + IN uint32_t bitMapSize) +{ + if (bit >= bitMapSize * BITS_OF_BYTE) { + log_dbg(SCN, WARN, "bit %u is out of array range(%u bits)\n", + bit, bitMapSize * BITS_OF_BYTE); + return FALSE; + } else { + return (bitMap[bit/BITS_OF_UINT] & + (1 << (bit % BITS_OF_UINT))) ? TRUE : FALSE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Set the bit of the given bitmap. + * The bitmap should be unsigned int based, which means that this function + * doesn't support other format bitmap, e.g. char array or short array + * + * @param[in] bit which bit to set. + * @param[out] bitMap bitmap array + * @param[in] bitMapSize bytes of bitmap + * + * @return void + */ +/*----------------------------------------------------------------------------*/ +void scanSetBit(IN uint32_t bit, OUT uint32_t bitMap[], IN uint32_t bitMapSize) +{ + if (bit >= bitMapSize * BITS_OF_BYTE) { + log_dbg(SCN, WARN, "set bit %u to array(%u bits) failed\n", + bit, bitMapSize * BITS_OF_BYTE); + } else + bitMap[bit/BITS_OF_UINT] |= 1 << (bit % BITS_OF_UINT); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Return number of bit which is set to 1 in the given bitmap. + * The bitmap should be unsigned int based, which means that this function + * doesn't support other format bitmap, e.g. char array or short array + * + * @param[in] bitMap bitmap array + * @param[in] bitMapSize bytes of bitmap + * + * @return number of bit which is set to 1 + */ +/*----------------------------------------------------------------------------*/ + +uint32_t scanCountBits(IN uint32_t bitMap[], IN uint32_t bitMapSize) +{ + uint32_t count = 0; + uint32_t value; + int32_t arrayLen = bitMapSize/sizeof(uint32_t); + int32_t i; + + for (i = arrayLen - 1; i >= 0; i--) { + value = bitMap[i]; + log_dbg(SCN, TRACE, "array[%d]:%08X\n", i, value); + while (value) { + count += (value & 1); + value >>= 1; + } + } + return count; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Set scan channel to scanReqMsg. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] u4ScanChannelNum number of input channels + * @param[in] arChannel channel list + * @param[in] fgIsOnlineScan online scan or not + * @param[out] prScanReqMsg scan request msg. Set channel number and + * channel list for output + * + * @return + */ +/*----------------------------------------------------------------------------*/ +void scanSetRequestChannel(IN struct ADAPTER *prAdapter, + IN uint32_t u4ScanChannelNum, + IN struct RF_CHANNEL_INFO arChannel[], + IN uint8_t fgIsOnlineScan, + OUT struct MSG_SCN_SCAN_REQ_V2 *prScanReqMsg) +{ + uint32_t i, u4Channel, eBand, u4Index; + /*print channel info for debugging */ + uint32_t au4ChannelBitMap[SCAN_CHANNEL_BITMAP_ARRAY_LEN]; +#if CFG_SUPPORT_FULL2PARTIAL_SCAN + uint8_t fgIsFull2Partial = FALSE; +#endif /* CFG_SUPPORT_FULL2PARTIAL_SCAN */ + struct SCAN_INFO *prScanInfo; + + ASSERT(u4ScanChannelNum <= MAXIMUM_OPERATION_CHANNEL_LIST); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + i = u4Index = 0; + kalMemZero(au4ChannelBitMap, sizeof(au4ChannelBitMap)); + +#if CFG_SUPPORT_FULL2PARTIAL_SCAN + /* fgIsCheckingFull2Partial should be true if it's an online scan. + * Next, enable full2partial if channel number to scan is + * larger than SCAN_FULL2PARTIAL_CHANNEL_NUM + */ + if (fgIsOnlineScan && (u4ScanChannelNum == 0 || + u4ScanChannelNum > SCAN_FULL2PARTIAL_CHANNEL_NUM)) { + OS_SYSTIME rCurrentTime; + + GET_CURRENT_SYSTIME(&rCurrentTime); + + if (((prScanInfo->u4LastFullScanTime == 0) || + (CHECK_FOR_TIMEOUT(rCurrentTime, + prScanInfo->u4LastFullScanTime, + SEC_TO_SYSTIME(CFG_SCAN_FULL2PARTIAL_PERIOD))))) { + prScanInfo->fgIsScanForFull2Partial = TRUE; + prScanInfo->ucFull2PartialSeq = prScanReqMsg->ucSeqNum; + prScanInfo->u4LastFullScanTime = rCurrentTime; + kalMemZero(prScanInfo->au4ChannelBitMap, + sizeof(prScanInfo->au4ChannelBitMap)); + log_dbg(SCN, INFO, + "Full2partial: 1st full scan start\n"); + } else { + log_dbg(SCN, INFO, + "Full2partial: enable full2partial\n"); + fgIsFull2Partial = TRUE; + } + } + + if (fgIsFull2Partial && u4ScanChannelNum == 0) { + /* We don't have channel info when u4ScanChannelNum is 0. + * check full2partial bitmap and set scan channels + */ + uint32_t start = 1; + uint32_t end = HW_CHNL_NUM_MAX_4G_5G; + + if (prScanReqMsg->eScanChannel == SCAN_CHANNEL_2G4) + end = HW_CHNL_NUM_MAX_2G4; + else if (prScanReqMsg->eScanChannel == SCAN_CHANNEL_5G) + start = HW_CHNL_NUM_MAX_2G4 + 1; + + u4Index = 0; + for (u4Channel = start; u4Channel <= end; u4Channel++) { + if (scanIsBitSet(u4Channel, + prScanInfo->au4ChannelBitMap, + sizeof(prScanInfo->au4ChannelBitMap))) { + eBand = (u4Channel <= HW_CHNL_NUM_MAX_2G4) ? + BAND_2G4 : BAND_5G; + prScanReqMsg->arChnlInfoList[u4Index]. + ucChannelNum = u4Channel; + prScanReqMsg->arChnlInfoList[u4Index]. + eBand = eBand; + scanSetBit(u4Channel, au4ChannelBitMap, + sizeof(au4ChannelBitMap)); + u4Index++; + } + } + + prScanReqMsg->ucChannelListNum = u4Index; + prScanReqMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; + } else +#endif /* CFG_SUPPORT_FULL2PARTIAL_SCAN */ + if (u4ScanChannelNum == 0) { + prScanReqMsg->ucChannelListNum = 0; + } else { + u4Index = 0; + for (i = 0; i < u4ScanChannelNum; i++) { + u4Channel = arChannel[i].ucChannelNum; + eBand = arChannel[i].eBand; + if (prScanReqMsg->eScanChannel == SCAN_CHANNEL_2G4 && + eBand != BAND_2G4) + continue; + else if (prScanReqMsg->eScanChannel == + SCAN_CHANNEL_5G && eBand != BAND_5G) + continue; +#if CFG_SUPPORT_FULL2PARTIAL_SCAN + if (fgIsFull2Partial && !scanIsBitSet(u4Channel, + prScanInfo->au4ChannelBitMap, + sizeof(prScanInfo->au4ChannelBitMap))) + continue; +#endif /* CFG_SUPPORT_FULL2PARTIAL_SCAN */ + kalMemCopy(&prScanReqMsg->arChnlInfoList[u4Index], + &arChannel[i], + sizeof(struct RF_CHANNEL_INFO)); + scanSetBit(u4Channel, au4ChannelBitMap, + sizeof(au4ChannelBitMap)); + + u4Index++; + } + if (u4Index == 0) { + log_dbg(SCN, WARN, "No channel to scan\n"); + prScanReqMsg->ucChannelListNum = 0; + } else { + prScanReqMsg->ucChannelListNum = u4Index; + prScanReqMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; + } + } + + log_dbg(SCN, INFO, + "channel num(%u=>%u) %08X %08X %08X %08X %08X %08X %08X %08X\n", + u4ScanChannelNum, prScanReqMsg->ucChannelListNum, + au4ChannelBitMap[7], au4ChannelBitMap[6], + au4ChannelBitMap[5], au4ChannelBitMap[4], + au4ChannelBitMap[3], au4ChannelBitMap[2], + au4ChannelBitMap[1], au4ChannelBitMap[0]); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Find the corresponding BSS Descriptor according to given BSSID + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] aucBSSID Given BSSID. + * @param[in] fgCheckSsid Need to check SSID or not. (for multiple SSID + * with single BSSID cases) + * @param[in] prSsid Specified SSID + * + * @return Pointer to BSS Descriptor, if found. NULL, if not found + */ +/*----------------------------------------------------------------------------*/ +struct BSS_DESC * +scanSearchBssDescByBssidAndSsid(IN struct ADAPTER *prAdapter, + IN uint8_t aucBSSID[], + IN u_int8_t fgCheckSsid, + IN struct PARAM_SSID *prSsid) +{ + struct SCAN_INFO *prScanInfo; + struct LINK *prBSSDescList; + struct BSS_DESC *prBssDesc; + struct BSS_DESC *prDstBssDesc = (struct BSS_DESC *) 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, struct BSS_DESC) { + + if (!(EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID))) + continue; + if (fgCheckSsid == FALSE || prSsid == NULL) + return prBssDesc; + if (EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, + prSsid->aucSsid, prSsid->u4SsidLen)) { + return prBssDesc; + } + if (prDstBssDesc == NULL && prBssDesc->fgIsHiddenSSID == TRUE) { + prDstBssDesc = prBssDesc; + continue; + } + if (prBssDesc->eBSSType == BSS_TYPE_P2P_DEVICE) { + /* 20120206 frog: Equal BSSID but not SSID, + * SSID not hidden, SSID must be updated. + */ + COPY_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, + prSsid->aucSsid, (uint8_t) (prSsid->u4SsidLen)); + return prBssDesc; + } + } + + return prDstBssDesc; + +} /* end of scanSearchBssDescByBssid() */ + +#if CFG_SUPPORT_CFG80211_AUTH +/*----------------------------------------------------------------------------*/ +/*! +* @brief Find the corresponding BSS Descriptor +* according to given BSSID & ChanNum +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] aucBSSID Given BSSID. +* @param[in] fgCheckChanNum Need to check ChanNum or not. +* @param[in] ucChannelNum Specified Channel Num +* +* @return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +struct BSS_DESC * +scanSearchBssDescByBssidAndChanNum(IN struct ADAPTER *prAdapter, + IN uint8_t aucBSSID[], + IN u_int8_t fgCheckChanNum, + IN uint8_t ucChannelNum) +{ + struct SCAN_INFO *prScanInfo; + struct LINK *prBSSDescList; + struct BSS_DESC *prBssDesc = NULL; + + ASSERT(prAdapter); + ASSERT(aucBSSID); + ASSERT(ucChannelNum); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, + rLinkEntry, struct BSS_DESC) { + if (!(EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID))) + continue; + if (fgCheckChanNum == FALSE || ucChannelNum == 0) + return prBssDesc; + if (prBssDesc->ucChannelNum == ucChannelNum) + return prBssDesc; + } + + return prBssDesc; +} +#endif + + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +struct BSS_DESC *scanSearchBssDescByTA(IN struct ADAPTER *prAdapter, + IN uint8_t 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 + */ +/*----------------------------------------------------------------------------*/ +struct BSS_DESC * +scanSearchBssDescByTAAndSsid(IN struct ADAPTER *prAdapter, + IN uint8_t aucSrcAddr[], + IN u_int8_t fgCheckSsid, + IN struct PARAM_SSID *prSsid) +{ + struct SCAN_INFO *prScanInfo; + struct LINK *prBSSDescList; + struct BSS_DESC *prBssDesc; + struct BSS_DESC *prDstBssDesc = (struct BSS_DESC *) 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, struct BSS_DESC) { + + if (EQUAL_MAC_ADDR(prBssDesc->aucSrcAddr, aucSrcAddr)) { + if (fgCheckSsid == FALSE || prSsid == NULL) + return prBssDesc; + if (EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, + prSsid->aucSsid, prSsid->u4SsidLen)) { + return prBssDesc; + } else if (prDstBssDesc == NULL + && prBssDesc->fgIsHiddenSSID == TRUE) { + prDstBssDesc = prBssDesc; + } + } + } + + return prDstBssDesc; + +} /* end of scanSearchBssDescByTA() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +struct BSS_DESC * +scanSearchExistingBssDesc(IN struct ADAPTER *prAdapter, + IN enum ENUM_BSS_TYPE eBSSType, + IN uint8_t aucBSSID[], + IN uint8_t aucSrcAddr[]) +{ + return scanSearchExistingBssDescWithSsid(prAdapter, eBSSType, aucBSSID, + aucSrcAddr, FALSE, NULL); +} + +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param + * + * @return + */ +/*----------------------------------------------------------------------------*/ +void scanRemoveRoamBssDescsByTime(IN struct ADAPTER *prAdapter, + IN uint32_t u4RemoveTime) +{ + struct SCAN_INFO *prScanInfo; + struct LINK *prRoamBSSDescList; + struct LINK *prRoamFreeBSSDescList; + struct ROAM_BSS_DESC *prRoamBssDesc; + struct ROAM_BSS_DESC *prRoamBSSDescNext; + OS_SYSTIME rCurrentTime; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prRoamBSSDescList = &prScanInfo->rRoamBSSDescList; + prRoamFreeBSSDescList = &prScanInfo->rRoamFreeBSSDescList; + + GET_CURRENT_SYSTIME(&rCurrentTime); + + LINK_FOR_EACH_ENTRY_SAFE(prRoamBssDesc, prRoamBSSDescNext, + prRoamBSSDescList, rLinkEntry, struct ROAM_BSS_DESC) { + + if (CHECK_FOR_TIMEOUT(rCurrentTime, prRoamBssDesc->rUpdateTime, + SEC_TO_SYSTIME(u4RemoveTime))) { + + LINK_REMOVE_KNOWN_ENTRY(prRoamBSSDescList, + prRoamBssDesc); + LINK_INSERT_TAIL(prRoamFreeBSSDescList, + &prRoamBssDesc->rLinkEntry); + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param + * + * @return + */ +/*----------------------------------------------------------------------------*/ +struct ROAM_BSS_DESC * +scanSearchRoamBssDescBySsid(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc) +{ + struct SCAN_INFO *prScanInfo; + struct LINK *prRoamBSSDescList; + struct ROAM_BSS_DESC *prRoamBssDesc; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prRoamBSSDescList = &prScanInfo->rRoamBSSDescList; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prRoamBssDesc, prRoamBSSDescList, + rLinkEntry, struct ROAM_BSS_DESC) { + if (EQUAL_SSID(prRoamBssDesc->aucSSID, prRoamBssDesc->ucSSIDLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen)) { + return prRoamBssDesc; + } + } + + return NULL; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param + * + * @return + */ +/*----------------------------------------------------------------------------*/ +struct ROAM_BSS_DESC *scanAllocateRoamBssDesc(IN struct ADAPTER *prAdapter) +{ + struct SCAN_INFO *prScanInfo; + struct LINK *prRoamFreeBSSDescList; + struct ROAM_BSS_DESC *prRoamBssDesc = NULL; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prRoamFreeBSSDescList = &prScanInfo->rRoamFreeBSSDescList; + + LINK_REMOVE_HEAD(prRoamFreeBSSDescList, prRoamBssDesc, + struct ROAM_BSS_DESC *); + + if (prRoamBssDesc) { + struct LINK *prRoamBSSDescList; + + kalMemZero(prRoamBssDesc, sizeof(struct ROAM_BSS_DESC)); + + prRoamBSSDescList = &prScanInfo->rRoamBSSDescList; + + LINK_INSERT_HEAD(prRoamBSSDescList, &prRoamBssDesc->rLinkEntry); + } + + return prRoamBssDesc; +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param + * + * @return + */ +/*----------------------------------------------------------------------------*/ +void scanAddToRoamBssDesc(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc) +{ + struct ROAM_BSS_DESC *prRoamBssDesc; + + prRoamBssDesc = scanSearchRoamBssDescBySsid(prAdapter, prBssDesc); + + if (prRoamBssDesc == NULL) { + uint32_t u4RemoveTime = REMOVE_TIMEOUT_TWO_DAY; + + do { + prRoamBssDesc = scanAllocateRoamBssDesc(prAdapter); + if (prRoamBssDesc) + break; + scanRemoveRoamBssDescsByTime(prAdapter, u4RemoveTime); + u4RemoveTime = u4RemoveTime / 2; + } while (u4RemoveTime > 0); + + if (prRoamBssDesc != NULL) { + COPY_SSID(prRoamBssDesc->aucSSID, + prRoamBssDesc->ucSSIDLen, + prBssDesc->aucSSID, + prBssDesc->ucSSIDLen); + } + } + + if (prRoamBssDesc != NULL) + GET_CURRENT_SYSTIME(&prRoamBssDesc->rUpdateTime); +} + + +/*----------------------------------------------------------------------------*/ +/*! + * @brief + * + * @param + * + * @return + */ +/*----------------------------------------------------------------------------*/ +void scanSearchBssDescOfRoamSsid(IN struct ADAPTER *prAdapter) +{ + +/* If only exist one same ssid AP, avoid unnecessary scan */ +#define SSID_ONLY_EXIST_ONE_AP 1 + + struct SCAN_INFO *prScanInfo; + struct LINK *prBSSDescList; + struct BSS_DESC *prBssDesc; + struct BSS_INFO *prAisBssInfo; + uint32_t u4SameSSIDCount = 0; + + prAisBssInfo = prAdapter->prAisBssInfo; + + /* XXX: wlan0(AP mode) + p2p0 occurs exception. */ + if (prAisBssInfo == NULL) + return; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + + if (prAisBssInfo->eConnectionState != PARAM_MEDIA_STATE_CONNECTED) + return; + + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, + rLinkEntry, struct BSS_DESC) { + if (EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, + prAisBssInfo->aucSSID, prAisBssInfo->ucSSIDLen)) { + u4SameSSIDCount++; + if (u4SameSSIDCount > SSID_ONLY_EXIST_ONE_AP) { + scanAddToRoamBssDesc(prAdapter, prBssDesc); + break; + } + } + } +} + +#endif /* CFG_SUPPORT_ROAMING_SKIP_ONE_AP */ + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +struct BSS_DESC * +scanSearchExistingBssDescWithSsid(IN struct ADAPTER *prAdapter, + IN enum ENUM_BSS_TYPE eBSSType, + IN uint8_t aucBSSID[], + IN uint8_t aucSrcAddr[], + IN u_int8_t fgCheckSsid, + IN struct PARAM_SSID *prSsid) +{ + struct SCAN_INFO *prScanInfo; + struct BSS_DESC *prBssDesc, *prIBSSBssDesc; + /* CASE III */ + struct LINK *prBSSDescList; + struct LINK *prFreeBSSDescList; + + ASSERT(prAdapter); + ASSERT(aucSrcAddr); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + switch (eBSSType) { + case BSS_TYPE_P2P_DEVICE: + fgCheckSsid = FALSE; + /* fall through */ + case BSS_TYPE_INFRASTRUCTURE: +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + scanSearchBssDescOfRoamSsid(prAdapter); + /* fall through */ +#endif + 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; + } + + + 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 (struct BSS_DESC *) 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 struct ADAPTER *prAdapter, + IN uint32_t u4RemovePolicy) +{ + struct CONNECTION_SETTINGS *prConnSettings; + struct SCAN_INFO *prScanInfo; + struct LINK *prBSSDescList; + struct LINK *prFreeBSSDescList; + struct BSS_DESC *prBssDesc; + /* Support AP Selection*/ + struct LINK *prEssList; + + ASSERT(prAdapter); + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; + /* Support AP Selection*/ + prEssList = &prAdapter->rWifiVar.rAisSpecificBssInfo.rCurEssLink; + +#if 0 /* TODO: Remove this */ + log_dbg(SCN, TRACE, ("Before Remove - Number Of SCAN Result = %ld\n", + prBSSDescList->u4NumElem)); +#endif + + if (u4RemovePolicy & SCN_RM_POLICY_TIMEOUT) { + struct BSS_DESC *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, struct BSS_DESC) { + + 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))) { + +#if 0 /* TODO: Remove this */ + log_dbg(SCN, TRACE, "Remove TIMEOUT BSS DESC(%#x):MAC: " + MACSTR + ", Current Time = %08lx, Update Time = %08lx\n", + prBssDesc, + MAC2STR(prBssDesc->aucBSSID), + rCurrentTime, prBssDesc->rUpdateTime)); +#endif + /* Support AP Selection */ + if (!prBssDesc->prBlack) + aisQueryBlackList(prAdapter, prBssDesc); + if (prBssDesc->prBlack) + prBssDesc->prBlack->u4DisapperTime = + (uint32_t)kalGetBootTime(); + /* end Support AP Selection */ + + /* Remove this BSS Desc from + * the BSS Desc list + */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, + prBssDesc); + + /* Support AP Selection */ + /* Remove this BSS Desc from the Ess Desc List + */ + if (LINK_ENTRY_IS_VALID + (&prBssDesc->rLinkEntryEss)) + LINK_REMOVE_KNOWN_ENTRY(prEssList, + &prBssDesc->rLinkEntryEss); + /* end Support AP Selection */ + + /* Return this BSS Desc to the + * free BSS Desc list. + */ + LINK_INSERT_TAIL(prFreeBSSDescList, + &prBssDesc->rLinkEntry); + } + } + } + if (u4RemovePolicy & SCN_RM_POLICY_OLDEST_HIDDEN) { + struct BSS_DESC *prBssDescOldest = (struct BSS_DESC *) NULL; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, + rLinkEntry, struct BSS_DESC) { + + 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) { +#if 0 /* TODO: Remove this */ + log_dbg(SCN, TRACE, "Remove OLDEST HIDDEN BSS DESC(%#x): MAC: " + MACSTR + ", Update Time = %08lx\n", + prBssDescOldest, + MAC2STR(prBssDescOldest->aucBSSID), + prBssDescOldest->rUpdateTime); +#endif + /* Support AP Selection */ + if (!prBssDescOldest->prBlack) + aisQueryBlackList(prAdapter, prBssDescOldest); + if (prBssDescOldest->prBlack) + prBssDescOldest->prBlack->u4DisapperTime = + (uint32_t)kalGetBootTime(); + /* end Support AP Selection */ + + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDescOldest); + + /* Support AP Selection */ + /* Remove this BSS Desc from the Ess Desc List */ + if (LINK_ENTRY_IS_VALID + (&prBssDescOldest->rLinkEntryEss)) + LINK_REMOVE_KNOWN_ENTRY(prEssList, + &prBssDescOldest->rLinkEntryEss); + /* end Support AP Selection */ + + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, + &prBssDescOldest->rLinkEntry); + } + } + if (u4RemovePolicy & SCN_RM_POLICY_SMART_WEAKEST) { + struct BSS_DESC *prBssDescWeakest = (struct BSS_DESC *) NULL; + struct BSS_DESC *prBssDescWeakestSameSSID + = (struct BSS_DESC *) NULL; + uint32_t u4SameSSIDCount = 0; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, + rLinkEntry, struct BSS_DESC) { + + 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 (u4SameSSIDCount + < SCN_BSS_DESC_SAME_SSID_THRESHOLD) + continue; + } + + 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) { +#if 0 /* TODO: Remove this */ + log_dbg(SCN, TRACE, "Remove WEAKEST BSS DESC(%#x): MAC: " + MACSTR + ", Update Time = %08lx\n", + prBssDescOldest, + MAC2STR(prBssDescOldest->aucBSSID), + prBssDescOldest->rUpdateTime); +#endif + + /* Support AP Selection */ + if (!prBssDescWeakest->prBlack) + aisQueryBlackList(prAdapter, prBssDescWeakest); + if (prBssDescWeakest->prBlack) + prBssDescWeakest->prBlack->u4DisapperTime = + (uint32_t)kalGetBootTime(); + /* end Support AP Selection */ + + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, + prBssDescWeakest); + + /* Support AP Selection */ + /* Remove this BSS Desc from the Ess Desc List */ + if (LINK_ENTRY_IS_VALID + (&prBssDescWeakest->rLinkEntryEss)) + LINK_REMOVE_KNOWN_ENTRY(prEssList, + &prBssDescWeakest->rLinkEntryEss); + /* end Support AP Selection */ + + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, + &prBssDescWeakest->rLinkEntry); + } + } + if (u4RemovePolicy & SCN_RM_POLICY_ENTIRE) { + struct BSS_DESC *prBSSDescNext; + /* Support AP Selection */ + uint32_t u4Current = (uint32_t)kalGetBootTime(); + + LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, + prBSSDescList, rLinkEntry, struct BSS_DESC) { + + if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) + && (prBssDesc->fgIsConnected + || prBssDesc->fgIsConnecting)) { + /* Don't remove the one currently + * we are connected. + */ + continue; + } + /* Support AP Selection */ + if (!prBssDesc->prBlack) + aisQueryBlackList(prAdapter, prBssDesc); + if (prBssDesc->prBlack) + prBssDesc->prBlack->u4DisapperTime = u4Current; + /* end Support AP Selection */ + + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); + + /* Support AP Selection */ + /* Remove this BSS Desc from the Ess Desc List */ + if (LINK_ENTRY_IS_VALID(&prBssDesc->rLinkEntryEss)) + LINK_REMOVE_KNOWN_ENTRY(prEssList, + &prBssDesc->rLinkEntryEss); + /* end Support AP Selection */ + + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, + &prBssDesc->rLinkEntry); + } + + } +} /* 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 struct ADAPTER *prAdapter, + IN uint8_t aucBSSID[]) +{ + struct SCAN_INFO *prScanInfo; + struct LINK *prBSSDescList; + struct LINK *prFreeBSSDescList; + struct BSS_DESC *prBssDesc = (struct BSS_DESC *) NULL; + struct BSS_DESC *prBSSDescNext; + /* Support AP Selection */ + struct LINK *prEssList = NULL; + + ASSERT(prAdapter); + ASSERT(aucBSSID); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; + /* Support AP Selection */ + prEssList = &prAdapter->rWifiVar.rAisSpecificBssInfo.rCurEssLink; + + /* Check if such BSS Descriptor exists in a valid list */ + LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, + rLinkEntry, struct BSS_DESC) { + + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { + /* Support AP Selection */ + if (!prBssDesc->prBlack) + aisQueryBlackList(prAdapter, prBssDesc); + if (prBssDesc->prBlack) + prBssDesc->prBlack->u4DisapperTime = + (uint32_t)kalGetBootTime(); + + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); + + /* Remove this BSS Desc from the Ess Desc List */ + if (LINK_ENTRY_IS_VALID(&prBssDesc->rLinkEntryEss)) + LINK_REMOVE_KNOWN_ENTRY(prEssList, + &prBssDesc->rLinkEntryEss); + + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, + &prBssDesc->rLinkEntry); + + /* BSSID is not unique, so need to traverse + * whols link-list + */ + } + } +} /* end of scanRemoveBssDescByBssid() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Delete BSS Descriptors from current list according to given + * band configuration + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] eBand Given band + * @param[in] ucBssIndex AIS - Remove IBSS/Infrastructure BSS + * BOW - Remove BOW BSS + * P2P - Remove P2P BSS + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void scanRemoveBssDescByBandAndNetwork(IN struct ADAPTER *prAdapter, + IN enum ENUM_BAND eBand, + IN uint8_t ucBssIndex) +{ + struct SCAN_INFO *prScanInfo; + struct LINK *prBSSDescList; + struct LINK *prFreeBSSDescList; + struct BSS_DESC *prBssDesc = (struct BSS_DESC *) NULL; + struct BSS_DESC *prBSSDescNext; + u_int8_t fgToRemove; + + ASSERT(prAdapter); + ASSERT(eBand <= BAND_NUM); + ASSERT(ucBssIndex <= prAdapter->ucHwBssIdNum); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; + + if (eBand == BAND_NULL) { + /* no need to do anything, keep all scan result */ + return; + } + + /* Check if such BSS Descriptor exists in a valid list */ + LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, + rLinkEntry, struct BSS_DESC) { + fgToRemove = FALSE; + + if (prBssDesc->eBand == eBand) { + switch (GET_BSS_INFO_BY_INDEX( + prAdapter, ucBssIndex)->eNetworkType) { + case NETWORK_TYPE_AIS: + if ((prBssDesc->eBSSType + == BSS_TYPE_INFRASTRUCTURE) + || (prBssDesc->eBSSType == BSS_TYPE_IBSS)) { + fgToRemove = TRUE; + } + break; + + case NETWORK_TYPE_P2P: + if (prBssDesc->eBSSType == BSS_TYPE_P2P_DEVICE) + fgToRemove = TRUE; + break; + + case NETWORK_TYPE_BOW: + if (prBssDesc->eBSSType == BSS_TYPE_BOW_DEVICE) + fgToRemove = TRUE; + break; + + default: + ASSERT(0); + break; + } + } + + if (fgToRemove == TRUE) { + /* Support AP Selection */ + struct LINK *prEssList = + &prAdapter->rWifiVar. + rAisSpecificBssInfo.rCurEssLink; + + if (!prBssDesc->prBlack) + aisQueryBlackList(prAdapter, prBssDesc); + if (prBssDesc->prBlack) + prBssDesc->prBlack->u4DisapperTime = + (uint32_t)kalGetBootTime(); + + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); + + /* Remove this BSS Desc from the Ess Desc List */ + if (LINK_ENTRY_IS_VALID(&prBssDesc->rLinkEntryEss)) + LINK_REMOVE_KNOWN_ENTRY(prEssList, + &prBssDesc->rLinkEntryEss); + + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, + &prBssDesc->rLinkEntry); + } + } +} /* end of scanRemoveBssDescByBand() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Clear the CONNECTION FLAG of a specified BSS Descriptor. + * + * @param[in] aucBSSID Given BSSID. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void scanRemoveConnFlagOfBssDescByBssid(IN struct ADAPTER *prAdapter, + IN uint8_t aucBSSID[]) +{ + struct SCAN_INFO *prScanInfo; + struct LINK *prBSSDescList; + struct BSS_DESC *prBssDesc = (struct BSS_DESC *) 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, struct BSS_DESC) { + + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { + prBssDesc->fgIsConnected = FALSE; + prBssDesc->fgIsConnecting = FALSE; + + /* BSSID is not unique, so need to + * traverse whols link-list + */ + } + } +} /* end of scanRemoveConnectionFlagOfBssDescByBssid() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief Allocate new BSS_DESC structure + * + * @param[in] prAdapter Pointer to the Adapter structure. + * + * @return Pointer to BSS Descriptor, if has + * free space. NULL, if has no space. + */ +/*----------------------------------------------------------------------------*/ +struct BSS_DESC *scanAllocateBssDesc(IN struct ADAPTER *prAdapter) +{ + struct SCAN_INFO *prScanInfo; + struct LINK *prFreeBSSDescList; + struct BSS_DESC *prBssDesc; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; + + LINK_REMOVE_HEAD(prFreeBSSDescList, prBssDesc, struct BSS_DESC *); + + if (prBssDesc) { + struct LINK *prBSSDescList; + + kalMemZero(prBssDesc, sizeof(struct BSS_DESC)); + +#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 + * struct BSS_DESC 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 structure 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 + */ +/*----------------------------------------------------------------------------*/ +struct BSS_DESC *scanAddToBssDesc(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct BSS_DESC *prBssDesc = NULL; + uint16_t u2CapInfo; + enum ENUM_BSS_TYPE eBSSType = BSS_TYPE_INFRASTRUCTURE; + + uint8_t *pucIE; + uint16_t u2IELength; + uint16_t u2Offset = 0; + + struct WLAN_BEACON_FRAME *prWlanBeaconFrame + = (struct WLAN_BEACON_FRAME *) NULL; + struct IE_SSID *prIeSsid = (struct IE_SSID *) NULL; + struct IE_SUPPORTED_RATE *prIeSupportedRate + = (struct IE_SUPPORTED_RATE *) NULL; + struct IE_EXT_SUPPORTED_RATE *prIeExtSupportedRate + = (struct IE_EXT_SUPPORTED_RATE *) NULL; + uint8_t ucHwChannelNum = 0; + uint8_t ucIeDsChannelNum = 0; + uint8_t ucIeHtChannelNum = 0; + u_int8_t fgIsValidSsid = FALSE; + struct PARAM_SSID rSsid; + uint64_t u8Timestamp; + u_int8_t fgIsNewBssDesc = FALSE; + + uint32_t i; + uint8_t ucSSIDChar; + /* PUINT_8 pucDumpIE; */ + enum ENUM_BAND eHwBand = BAND_NULL; + u_int8_t fgBandMismatch = FALSE; + uint8_t ucSubtype; + u_int8_t fgIsProbeResp = FALSE; + u_int8_t ucPowerConstraint = 0; + struct IE_COUNTRY *prCountryIE = NULL; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + eHwBand = HAL_RX_STATUS_GET_RF_BAND(prSwRfb->prRxStatus); + prWlanBeaconFrame = (struct WLAN_BEACON_FRAME *) prSwRfb->pvHeader; + ucSubtype = (*(uint8_t *) (prSwRfb->pvHeader) & + MASK_FC_SUBTYPE) >> OFFSET_OF_FC_SUBTYPE; + + 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: + log_dbg(SCN, WARN, "Skip unknown bss type(%u)\n", u2CapInfo); + return NULL; + } + + /* 4 <1.1> Pre-parse SSID IE and channel info */ + pucIE = prWlanBeaconFrame->aucInfoElem; + u2IELength = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - + (uint16_t) OFFSET_OF(struct WLAN_BEACON_FRAME_BODY, aucInfoElem[0]); + + if (u2IELength > CFG_IE_BUFFER_SIZE) { + /* Give an warning msg when IE is going to be + * truncated. + */ + DBGLOG(SCN, ERROR, + "IE len(%u) > Max IE buffer size(%u), truncate IE!\n", + u2IELength, CFG_IE_BUFFER_SIZE); + u2IELength = CFG_IE_BUFFER_SIZE; + } + kalMemZero(&rSsid, sizeof(rSsid)); + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_SSID: + if (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID) { + ucSSIDChar = '\0'; + + /* D-Link DWL-900AP+ */ + if (IE_LEN(pucIE) == 0) + fgIsValidSsid = FALSE; + /* Cisco AP1230A - + * (IE_LEN(pucIE) == 1) + * && (SSID_IE(pucIE)->aucSSID[0] == '\0') + */ + /* Linksys WRK54G/WL520g - + * (IE_LEN(pucIE) == n) + * && (SSID_IE(pucIE)->aucSSID[0~(n-1)] == '\0') + */ + else { + for (i = 0; i < IE_LEN(pucIE); i++) { + ucSSIDChar + |= SSID_IE(pucIE) + ->aucSSID[i]; + } + + if (ucSSIDChar) + fgIsValidSsid = TRUE; + } + + /* Update SSID to BSS Descriptor only if + * SSID is not hidden. + */ + if (fgIsValidSsid == TRUE) { + COPY_SSID(rSsid.aucSsid, + rSsid.u4SsidLen, + SSID_IE(pucIE)->aucSSID, + SSID_IE(pucIE)->ucLength); + } + } + 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_HT_OP: + if (IE_LEN(pucIE) == (sizeof(struct IE_HT_OP) - 2)) + ucIeHtChannelNum = ((struct IE_HT_OP *) pucIE) + ->ucPrimaryChannel; + break; + default: + break; + } + } + + /** + * Set band mismatch flag if we receive Beacon/ProbeResp in 2.4G band, + * but the channel num in IE info is 5G, and vice versa + * We can get channel num from different IE info, we select + * ELEM_ID_DS_PARAM_SET first, and then ELEM_ID_HT_OP + * If we don't have any channel info, we set it as HW channel, which is + * the channel we get this Beacon/ProbeResp from. + */ + if (ucIeDsChannelNum > 0) { + if (ucIeDsChannelNum <= HW_CHNL_NUM_MAX_2G4) + fgBandMismatch = (eHwBand != BAND_2G4); + else if (ucIeDsChannelNum < HW_CHNL_NUM_MAX_4G_5G) + fgBandMismatch = (eHwBand != BAND_5G); + } else if (ucIeHtChannelNum > 0) { + if (ucIeHtChannelNum <= HW_CHNL_NUM_MAX_2G4) + fgBandMismatch = (eHwBand != BAND_2G4); + else if (ucIeHtChannelNum < HW_CHNL_NUM_MAX_4G_5G) + fgBandMismatch = (eHwBand != BAND_5G); + } + + if (fgBandMismatch) { + log_dbg(SCN, INFO, MACSTR "Band mismatch, HW band %d, DS chnl %d, HT chnl %d\n", + MAC2STR(prWlanBeaconFrame->aucBSSID), eHwBand, + ucIeDsChannelNum, ucIeHtChannelNum); + return NULL; + } + + /* 4 <1.2> Replace existing BSS_DESC structure or allocate a new one */ + prBssDesc = scanSearchExistingBssDescWithSsid( + prAdapter, + eBSSType, + (uint8_t *) prWlanBeaconFrame->aucBSSID, + (uint8_t *) prWlanBeaconFrame->aucSrcAddr, + fgIsValidSsid, fgIsValidSsid == TRUE ? &rSsid : NULL); + + log_dbg(SCN, TRACE, "Receive type %u in chnl %u %u %u (" MACSTR + ") valid(%u) found(%u)\n", + ucSubtype, ucIeDsChannelNum, ucIeHtChannelNum, + HAL_RX_STATUS_GET_CHNL_NUM(prSwRfb->prRxStatus), + MAC2STR((uint8_t *)prWlanBeaconFrame->aucBSSID), fgIsValidSsid, + (prBssDesc != NULL) ? 1 : 0); + + if ((prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) + == MAC_FRAME_PROBE_RSP) + fgIsProbeResp = TRUE; + + if (prBssDesc == (struct BSS_DESC *) NULL) { + fgIsNewBssDesc = TRUE; + + do { + /* check if it is a beacon frame */ + if (!fgIsProbeResp && !fgIsValidSsid) { + log_dbg(SCN, LOUD, "scanAddToBssDescssid is NULL Beacon, don't add hidden BSS(" + MACSTR ")\n", + MAC2STR((uint8_t *) + prWlanBeaconFrame->aucBSSID)); + return NULL; + } + /* 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 + | SCN_RM_POLICY_TIMEOUT)); + + /* 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 */ + log_limited_dbg(SCN, WARN, "alloc new BssDesc for " + MACSTR " failed\n", + MAC2STR((uint8_t *) + prWlanBeaconFrame->aucBSSID)); + 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); + + ASSERT(prSwRfb->prRxStatusGroup3); + + if (prBssDesc->eBSSType != eBSSType) { + prBssDesc->eBSSType = eBSSType; + } else if (HAL_RX_STATUS_GET_CHNL_NUM(prSwRfb->prRxStatus) != + prBssDesc->ucChannelNum + && prBssDesc->ucRCPI + > nicRxGetRcpiValueFromRxv(RCPI_MODE_MAX, prSwRfb)) { + uint8_t ucRcpi = 0; + + /* for signal strength is too much weaker and + * previous beacon is not stale + */ + ASSERT(prSwRfb->prRxStatusGroup3); + ucRcpi = nicRxGetRcpiValueFromRxv(RCPI_MODE_MAX, + prSwRfb); + if ((prBssDesc->ucRCPI - ucRcpi) + >= REPLICATED_BEACON_STRENGTH_THRESHOLD + && rCurrentTime - prBssDesc->rUpdateTime + <= REPLICATED_BEACON_FRESH_PERIOD) { + log_dbg(SCN, TRACE, "rssi(%u) is too much weaker and previous one(%u) is fresh\n", + ucRcpi, prBssDesc->ucRCPI); + return prBssDesc; + } + /* for received beacons too close in time domain */ + else if (rCurrentTime - prBssDesc->rUpdateTime + <= REPLICATED_BEACON_TIME_THRESHOLD) { + log_dbg(SCN, TRACE, "receive beacon/probe responses too soon(%u:%u)\n", + prBssDesc->rUpdateTime, rCurrentTime); + 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) { + u_int8_t 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) { + log_dbg(SCN, WARN, "Realloc BssDesc for " + MACSTR " failed\n", + MAC2STR((uint8_t *) + prWlanBeaconFrame->aucBSSID)); + return NULL; + } + + /* restore */ + prBssDesc->fgIsConnected = fgIsConnected; + prBssDesc->fgIsConnecting = fgIsConnecting; + } + } + + prBssDesc->fgIsValidSSID = fgIsValidSsid; + prBssDesc->u2RawLength = prSwRfb->u2PacketLen; + if (prBssDesc->u2RawLength > CFG_RAW_BUFFER_SIZE) { + prBssDesc->u2RawLength = CFG_RAW_BUFFER_SIZE; + /* Give an warning msg when content is going to be + * truncated. + */ + DBGLOG(SCN, WARN, + "Pkt len(%u) > Max RAW buffer size(%u), truncate it!\n", + prSwRfb->u2PacketLen, CFG_RAW_BUFFER_SIZE); +} + if (fgIsProbeResp || fgIsValidSsid) { + kalMemCopy(prBssDesc->aucRawBuf, prWlanBeaconFrame, + prBssDesc->u2RawLength); + } + + /* NOTE: Keep consistency of Scan Record during JOIN process */ + if (fgIsNewBssDesc == FALSE && prBssDesc->fgIsConnecting) { + log_dbg(SCN, TRACE, "we're connecting this BSS(" + MACSTR ") now, don't update it\n", + MAC2STR(prBssDesc->aucBSSID)); + return prBssDesc; + } + /* 4 <2> Get information from Fixed Fields */ + /* Update the latest BSS type information. */ + prBssDesc->eBSSType = eBSSType; + + 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) - + (uint16_t) OFFSET_OF(struct WLAN_BEACON_FRAME_BODY, aucInfoElem[0]); + + if (u2IELength > CFG_IE_BUFFER_SIZE) { + u2IELength = CFG_IE_BUFFER_SIZE; + prBssDesc->fgIsIEOverflow = TRUE; + DBGLOG(SCN, WARN, "IE is truncated!\n"); + } else { + prBssDesc->fgIsIEOverflow = FALSE; + } + prBssDesc->u2IELength = u2IELength; + + if (fgIsProbeResp || fgIsValidSsid) { + 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->fgIsVHTPresent = FALSE; + prBssDesc->eSco = CHNL_EXT_SCN; + prBssDesc->fgIEWAPI = FALSE; + prBssDesc->fgIERSN = FALSE; + prBssDesc->fgIEWPA = FALSE; + + /*Reset VHT OP IE relative settings */ + prBssDesc->eChannelWidth = CW_20_40MHZ; + + prBssDesc->ucCenterFreqS1 = 0; + prBssDesc->ucCenterFreqS2 = 0; + + /* Support AP Selection */ + prBssDesc->fgExsitBssLoadIE = FALSE; + prBssDesc->fgMultiAnttenaAndSTBC = FALSE; + + if (fgIsProbeResp == FALSE) { + /* Probe response doesn't have TIM IE. Thus, we should + * reset TIM when handling beacon frame only. + */ + prBssDesc->fgTIMPresent = FALSE; + prBssDesc->ucDTIMPeriod = 0; + } + + /* 4 <3.1> Full IE parsing on SW_RFB_T */ + pucIE = prWlanBeaconFrame->aucInfoElem; + /* pucDumpIE = pucIE; */ + + 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)) { + u_int8_t fgIsHiddenSSID = FALSE; + + ucSSIDChar = '\0'; + + prIeSsid = (struct IE_SSID *) pucIE; + + /* D-Link DWL-900AP+ */ + if (IE_LEN(pucIE) == 0) + fgIsHiddenSSID = TRUE; + /* Cisco AP1230A - + * (IE_LEN(pucIE) == 1) + * && (SSID_IE(pucIE)->aucSSID[0] == '\0') + */ + /* Linksys WRK54G/WL520g - + * (IE_LEN(pucIE) == n) + * && (SSID_IE(pucIE)->aucSSID[0~(n-1)] == '\0') + */ + else { + for (i = 0; i < IE_LEN(pucIE); i++) { + ucSSIDChar + |= SSID_IE(pucIE) + ->aucSSID[i]; + } + + if (!ucSSIDChar) + fgIsHiddenSSID = TRUE; + } + + /* Update SSID to BSS Descriptor only if + * SSID is not hidden. + */ + if (!fgIsHiddenSSID) { + COPY_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, + SSID_IE(pucIE)->aucSSID, + SSID_IE(pucIE)->ucLength); + } else if (fgIsProbeResp) { + /* SSID should be updated + * if it is ProbeResp + */ + kalMemZero(prBssDesc->aucSSID, + sizeof(prBssDesc->aucSSID)); + prBssDesc->ucSSIDLen = 0; + } + + } + 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_SW)) + prIeSupportedRate = SUP_RATES_IE(pucIE); + break; + + case ELEM_ID_TIM: + if (IE_LEN(pucIE) <= ELEM_MAX_LEN_TIM) { + prBssDesc->fgTIMPresent = TRUE; + 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; + + case ELEM_ID_COUNTRY_INFO: + prCountryIE = (struct IE_COUNTRY *) pucIE; + break; + + 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; + + 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; + + case ELEM_ID_HT_CAP: + { + /* Support AP Selection */ + struct IE_HT_CAP *prHtCap = (struct IE_HT_CAP *)pucIE; + uint8_t ucSpatial = 0; + uint8_t i = 0; + /* end Support AP Selection */ + + prBssDesc->fgIsHTPresent = TRUE; + + /* Support AP Selection */ + if (prBssDesc->fgMultiAnttenaAndSTBC) + break; + + for (; i < 4; i++) { + if (prHtCap->rSupMcsSet.aucRxMcsBitmask[i] > 0) + ucSpatial++; + } + + prBssDesc->fgMultiAnttenaAndSTBC = + ((ucSpatial > 1) && + (prHtCap->u2HtCapInfo & HT_CAP_INFO_TX_STBC)); + /* end Support AP Selection */ + + break; + } + case ELEM_ID_HT_OP: + if (IE_LEN(pucIE) != (sizeof(struct IE_HT_OP) - 2)) + break; + + if ((((struct IE_HT_OP *) pucIE)->ucInfo1 + & HT_OP_INFO1_SCO) != CHNL_EXT_RES) { + prBssDesc->eSco = (enum ENUM_CHNL_EXT) + (((struct IE_HT_OP *) pucIE)->ucInfo1 + & HT_OP_INFO1_SCO); + } + break; + case ELEM_ID_VHT_CAP: + { + /* Support AP Selection*/ + struct IE_VHT_CAP *prVhtCap = + (struct IE_VHT_CAP *)pucIE; + uint16_t u2TxMcsSet = + prVhtCap->rVhtSupportedMcsSet.u2TxMcsMap; + uint8_t ucSpatial = 0; + uint8_t i = 0; + /* end Support AP Selection */ + prBssDesc->fgIsVHTPresent = TRUE; +#if CFG_SUPPORT_BFEE +#define __LOCAL_VAR__ \ +VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS_OFFSET + + prBssDesc->ucVhtCapNumSoundingDimensions = + ((((struct IE_VHT_CAP *) pucIE)->u4VhtCapInfo) + & VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS) + >> __LOCAL_VAR__; +#undef __LOCAL_VAR__ +#endif + /* Support AP Selection*/ + if (prBssDesc->fgMultiAnttenaAndSTBC) + break; + for (; i < 8; i++) { + if ((u2TxMcsSet & BITS(2*i, 2*i+1)) != 3) + ucSpatial++; + } + prBssDesc->fgMultiAnttenaAndSTBC = + ((ucSpatial > 1) && (prVhtCap->u4VhtCapInfo & + VHT_CAP_INFO_TX_STBC)); + /* end Support AP Selection */ + break; + } + case ELEM_ID_VHT_OP: + if (IE_LEN(pucIE) != (sizeof(struct IE_VHT_OP) - 2)) + break; + + prBssDesc->eChannelWidth = (enum ENUM_CHANNEL_WIDTH) + (((struct IE_VHT_OP *) pucIE) + ->ucVhtOperation[0]); + prBssDesc->ucCenterFreqS1 = (enum ENUM_CHANNEL_WIDTH) + (((struct IE_VHT_OP *) pucIE) + ->ucVhtOperation[1]); + prBssDesc->ucCenterFreqS2 = (enum ENUM_CHANNEL_WIDTH) + (((struct IE_VHT_OP *) pucIE) + ->ucVhtOperation[2]); + + /*add IEEE BW160 patch*/ + rlmModifyVhtBwPara(&prBssDesc->ucCenterFreqS1, + &prBssDesc->ucCenterFreqS2, + (uint8_t *)&prBssDesc->eChannelWidth); + + + + break; +#if CFG_SUPPORT_WAPI + case ELEM_ID_WAPI: + if (wapiParseWapiIE(WAPI_IE(pucIE), + &prBssDesc->rIEWAPI)) + prBssDesc->fgIEWAPI = TRUE; + break; +#endif + /* Support AP Selection */ + case ELEM_ID_BSS_LOAD: + { + struct IE_BSS_LOAD *prBssLoad = + (struct IE_BSS_LOAD *)pucIE; + + prBssDesc->u2StaCnt = prBssLoad->u2StaCnt; + prBssDesc->ucChnlUtilization = + prBssLoad->ucChnlUtilizaion; + prBssDesc->u2AvaliableAC = prBssLoad->u2AvailabeAC; + prBssDesc->fgExsitBssLoadIE = TRUE; + break; + } + /* end Support AP Selection */ + + case ELEM_ID_VENDOR: /* ELEM_ID_P2P, ELEM_ID_WMM */ + { + uint8_t ucOuiType; + uint16_t u2SubTypeVersion; + + if (rsnParseCheckForWFAInfoElem(prAdapter, + pucIE, &ucOuiType, &u2SubTypeVersion)) { + if ((ucOuiType == VENDOR_OUI_TYPE_WPA) + && (u2SubTypeVersion + == VERSION_WPA) + && (rsnParseWpaIE(prAdapter, + WPA_IE(pucIE), + &prBssDesc + ->rWPAInfo))) { + prBssDesc->fgIEWPA = TRUE; + } + } +#if CFG_SUPPORT_PASSPOINT + /* since OSEN is mutual exclusion with RSN, so + * we reuse RSN here + */ + if ((pucIE[1] >= 10) + && (kalMemCmp(pucIE+2, + "\x50\x6f\x9a\x12", 4) == 0) + && (rsnParseOsenIE(prAdapter, + (struct IE_WFA_OSEN *)pucIE, + &prBssDesc->rRSNInfo))) + prBssDesc->fgIEOsen = TRUE; +#endif +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { + if ((p2pFuncParseCheckForP2PInfoElem( + prAdapter, pucIE, &ucOuiType)) + && (ucOuiType + == VENDOR_OUI_TYPE_P2P)) { + prBssDesc->fgIsP2PPresent + = TRUE; + } + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + } + break; + case ELEM_ID_PWR_CONSTRAINT: + { + struct IE_POWER_CONSTRAINT *prPwrConstraint = + (struct IE_POWER_CONSTRAINT *)pucIE; + + if (IE_LEN(pucIE) != 1) + break; + ucPowerConstraint = + prPwrConstraint->ucLocalPowerConstraint; + break; + } + case ELEM_ID_RRM_ENABLED_CAP: + /* RRM Capability IE is always in length 5 bytes */ + kalMemZero(prBssDesc->aucRrmCap, + sizeof(prBssDesc->aucRrmCap)); + kalMemCopy(prBssDesc->aucRrmCap, pucIE + 2, + sizeof(prBssDesc->aucRrmCap)); + 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 */ + { + struct HW_MAC_RX_DESC *prRxStatus; + uint8_t ucRxRCPI; + uint8_t ucRxRCPI0; + uint8_t ucRxRCPI1; + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + /* 4 <4.1> Get TSF comparison result */ + prBssDesc->fgIsLargerTSF = HAL_RX_STATUS_GET_TCL(prRxStatus); + + /* 4 <4.2> Get Band information */ + prBssDesc->eBand = eHwBand; + + /* 4 <4.2> Get channel and RCPI information */ + ucHwChannelNum = HAL_RX_STATUS_GET_CHNL_NUM(prRxStatus); + + ASSERT(prSwRfb->prRxStatusGroup3); + ucRxRCPI = nicRxGetRcpiValueFromRxv(RCPI_MODE_MAX, prSwRfb); + ucRxRCPI0 = nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0, prSwRfb); + ucRxRCPI1 = nicRxGetRcpiValueFromRxv(RCPI_MODE_WF1, prSwRfb); + if (prBssDesc->eBand == BAND_2G4) { + + /* Update RCPI if in right channel */ + + if (ucIeDsChannelNum >= 1 && ucIeDsChannelNum <= 14) { + + /* Receive Beacon/ProbeResp frame + * from adjacent channel. + */ + if ((ucIeDsChannelNum == ucHwChannelNum) + || (ucRxRCPI > prBssDesc->ucRCPI)) { + prBssDesc->ucRCPI = ucRxRCPI; + prBssDesc->ucRCPI0 = ucRxRCPI0; + prBssDesc->ucRCPI1 = ucRxRCPI1; + } + /* 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) + || (ucRxRCPI > prBssDesc->ucRCPI)) { + prBssDesc->ucRCPI = ucRxRCPI; + prBssDesc->ucRCPI0 = ucRxRCPI0; + prBssDesc->ucRCPI1 = ucRxRCPI1; + } + /* trust channel information brought by IE */ + prBssDesc->ucChannelNum = ucIeHtChannelNum; + } else { + prBssDesc->ucRCPI = ucRxRCPI; + prBssDesc->ucRCPI0 = ucRxRCPI0; + prBssDesc->ucRCPI1 = ucRxRCPI1; + + prBssDesc->ucChannelNum = ucHwChannelNum; + } + } + /* 5G Band */ + else { + if (ucIeHtChannelNum >= 1 && ucIeHtChannelNum < 200) { + /* Receive Beacon/ProbeResp frame + * from adjacent channel. + */ + if ((ucIeHtChannelNum == ucHwChannelNum) + || (ucRxRCPI > prBssDesc->ucRCPI)) { + prBssDesc->ucRCPI = ucRxRCPI; + prBssDesc->ucRCPI0 = ucRxRCPI0; + prBssDesc->ucRCPI1 = ucRxRCPI1; + } + /* trust channel information brought by IE */ + prBssDesc->ucChannelNum = ucIeHtChannelNum; + } else { + /* Always update RCPI */ + prBssDesc->ucRCPI = ucRxRCPI; + prBssDesc->ucRCPI0 = ucRxRCPI0; + prBssDesc->ucRCPI1 = ucRxRCPI1; + + prBssDesc->ucChannelNum = ucHwChannelNum; + } + } + } + + /* 4 <5> Check IE information corret or not */ + if (!rlmDomainIsValidRfSetting(prAdapter, prBssDesc->eBand, + prBssDesc->ucChannelNum, prBssDesc->eSco, + prBssDesc->eChannelWidth, + prBssDesc->ucCenterFreqS1, + prBssDesc->ucCenterFreqS2)) { +#if 0 /* TODO: Remove this */ + /* Dump IE Inforamtion */ + log_dbg(RLM, WARN, "ScanAddToBssDesc IE Information\n"); + log_dbg(RLM, WARN, "IE Length = %d\n", u2IELength); + log_mem8_dbg(RLM, WARN, pucDumpIE, u2IELength); +#endif + + /* Error Handling for Non-predicted IE - Fixed to set 20MHz */ + prBssDesc->eChannelWidth = CW_20_40MHZ; + prBssDesc->ucCenterFreqS1 = 0; + prBssDesc->ucCenterFreqS2 = 0; + prBssDesc->eSco = CHNL_EXT_SCN; + } +#if CFG_SUPPORT_802_11K + if (prCountryIE) { + uint8_t ucRemainLen = prCountryIE->ucLength - 3; + struct COUNTRY_INFO_SUBBAND_TRIPLET *prSubBand = + &prCountryIE->arCountryStr[0]; + const uint8_t ucSubBandSize = + (uint8_t)sizeof(struct COUNTRY_INFO_SUBBAND_TRIPLET); + int8_t cNewPwrLimit = RLM_INVALID_POWER_LIMIT; + + /* Try to find a country subband base on our channel */ + while (ucRemainLen >= ucSubBandSize) { + if (prSubBand->ucFirstChnlNum < 201 && + prBssDesc->ucChannelNum >= + prSubBand->ucFirstChnlNum && + prBssDesc->ucChannelNum <= + (prSubBand->ucFirstChnlNum + + prSubBand->ucNumOfChnl - 1)) + break; + ucRemainLen -= ucSubBandSize; + prSubBand++; + } + /* Found a right country band */ + if (ucRemainLen >= ucSubBandSize) { + cNewPwrLimit = + prSubBand->cMaxTxPwrLv - ucPowerConstraint; + /* Limit Tx power changed */ + if (prBssDesc->cPowerLimit != cNewPwrLimit) { + prBssDesc->cPowerLimit = cNewPwrLimit; + DBGLOG(SCN, TRACE, + "LM: Old TxPwrLimit %d,New: CountryMax %d, Constraint %d\n", + prBssDesc->cPowerLimit, + prSubBand->cMaxTxPwrLv, + ucPowerConstraint); + /* should tell firmware to restrict tx power if + ** connected a BSS + */ + if (prBssDesc->fgIsConnected) { + if (prBssDesc->cPowerLimit != + RLM_INVALID_POWER_LIMIT) + rlmSetMaxTxPwrLimit( + prAdapter, + prBssDesc->cPowerLimit, + 1); + else + rlmSetMaxTxPwrLimit(prAdapter, + 0, 0); + } + } + } else if (prBssDesc->cPowerLimit != RLM_INVALID_POWER_LIMIT) { + prBssDesc->cPowerLimit = RLM_INVALID_POWER_LIMIT; + rlmSetMaxTxPwrLimit(prAdapter, 0, 0); + } + } else if (prBssDesc->cPowerLimit != RLM_INVALID_POWER_LIMIT) { + prBssDesc->cPowerLimit = RLM_INVALID_POWER_LIMIT; + rlmSetMaxTxPwrLimit(prAdapter, 0, 0); + } +#endif + + /* 4 <6> PHY type setting */ + prBssDesc->ucPhyTypeSet = 0; + + if (prBssDesc->eBand == BAND_2G4) { + /* 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->fgIsVHTPresent) + prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_VHT; + + 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; + +#if 0 /* TODO: Remove this */ + ASSERT(!(prBssDesc->u2OperationalRateSet + & RATE_SET_HR_DSSS)); +#endif + } + } + + /* Support AP Selection */ + /* update update-index and reset seen-probe-response */ + if (prBssDesc->u4UpdateIdx != + prAdapter->rWifiVar.rScanInfo.u4ScanUpdateIdx) { + prBssDesc->fgSeenProbeResp = FALSE; + prBssDesc->u4UpdateIdx = + prAdapter->rWifiVar.rScanInfo.u4ScanUpdateIdx; + } + + /* check if it is a probe response frame */ + if (fgIsProbeResp) + prBssDesc->fgSeenProbeResp = TRUE; + /* end Support AP Selection */ + /* 4 <7> Update BSS_DESC_T's Last Update TimeStamp. */ + if (fgIsProbeResp || fgIsValidSsid) + GET_CURRENT_SYSTIME(&prBssDesc->rUpdateTime); + +#if CFG_SUPPORT_802_11K + if (prBssDesc->fgIsConnected) + rlmUpdateBssTimeTsf(prAdapter, prBssDesc); +#endif + + return prBssDesc; +} + +/* clear all ESS scan result */ +void scanInitEssResult(struct ADAPTER *prAdapter) +{ + prAdapter->rWlanInfo.u4ScanResultEssNum = 0; + prAdapter->rWlanInfo.u4ScanDbgTimes1 = 0; + prAdapter->rWlanInfo.u4ScanDbgTimes2 = 0; + prAdapter->rWlanInfo.u4ScanDbgTimes3 = 0; + prAdapter->rWlanInfo.u4ScanDbgTimes4 = 0; + kalMemZero(prAdapter->rWlanInfo.arScanResultEss, + sizeof(prAdapter->rWlanInfo.arScanResultEss)); +} +/* print all ESS into log system once scan done + * it is useful to log that, otherwise, we have no information to + * identify if hardware has seen a specific AP, + * if user complained some AP were not found in scan result list + */ +void scanLogEssResult(struct ADAPTER *prAdapter) +{ +#define NUMBER_SSID_PER_LINE 16 + struct ESS_SCAN_RESULT_T *prEssResult + = &prAdapter->rWlanInfo.arScanResultEss[0]; + uint32_t u4ResultNum = prAdapter->rWlanInfo.u4ScanResultEssNum; + uint32_t u4Index = 0; + + if (u4ResultNum == 0) { + scanlog_dbg(LOG_SCAN_DONE_D2K, INFO, "0 Bss is found, %d, %d, %d, %d\n", + prAdapter->rWlanInfo.u4ScanDbgTimes1, + prAdapter->rWlanInfo.u4ScanDbgTimes2, + prAdapter->rWlanInfo.u4ScanDbgTimes3, + prAdapter->rWlanInfo.u4ScanDbgTimes4); + return; + } + + scanlog_dbg(LOG_SCAN_DONE_D2K, INFO, "Total:%u/%u; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s\n", + u4ResultNum, prAdapter->rWlanInfo.u4ScanResultNum, + prEssResult[0].aucSSID, prEssResult[1].aucSSID, + prEssResult[2].aucSSID, prEssResult[3].aucSSID, + prEssResult[4].aucSSID, prEssResult[5].aucSSID, + prEssResult[6].aucSSID, prEssResult[7].aucSSID, + prEssResult[8].aucSSID, prEssResult[9].aucSSID, + prEssResult[10].aucSSID, prEssResult[11].aucSSID, + prEssResult[12].aucSSID, prEssResult[13].aucSSID, + prEssResult[14].aucSSID, prEssResult[15].aucSSID); + + if (u4ResultNum <= NUMBER_SSID_PER_LINE) + return; + + u4ResultNum = u4ResultNum / NUMBER_SSID_PER_LINE; + if ((u4ResultNum % NUMBER_SSID_PER_LINE) != 0) + u4ResultNum++; + for (u4Index = 1; u4Index < u4ResultNum; u4Index++) { + struct ESS_SCAN_RESULT_T *prEss + = &prEssResult[NUMBER_SSID_PER_LINE*u4Index]; + + scanlog_dbg(LOG_SCAN_DONE_D2K, INFO, "%s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s\n", + prEss[0].aucSSID, prEss[1].aucSSID, + prEss[2].aucSSID, prEss[3].aucSSID, + prEss[4].aucSSID, prEss[5].aucSSID, + prEss[6].aucSSID, prEss[7].aucSSID, + prEss[8].aucSSID, prEss[9].aucSSID, + prEss[10].aucSSID, prEss[11].aucSSID, + prEss[12].aucSSID, prEss[13].aucSSID, + prEss[14].aucSSID, prEss[15].aucSSID); + } +} + +/* record all Scanned ESS, only one BSS was saved for each ESS, and AP who + * is hidden ssid was excluded. + */ +/* maximum we only support record 64 ESSes */ +static void scanAddEssResult(struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc) +{ + struct ESS_SCAN_RESULT_T *prEssResult + = &prAdapter->rWlanInfo.arScanResultEss[0]; + uint32_t u4Index = 0; + + if (prBssDesc->fgIsHiddenSSID) + return; + if (prAdapter->rWlanInfo.u4ScanResultEssNum >= CFG_MAX_NUM_BSS_LIST) + return; + for (; u4Index < prAdapter->rWlanInfo.u4ScanResultEssNum; u4Index++) { + if (EQUAL_SSID(prEssResult[u4Index].aucSSID, + (uint8_t)prEssResult[u4Index].u2SSIDLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen)) + return; + } + + COPY_SSID(prEssResult[u4Index].aucSSID, prEssResult[u4Index].u2SSIDLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + COPY_MAC_ADDR(prEssResult[u4Index].aucBSSID, prBssDesc->aucBSSID); + prAdapter->rWlanInfo.u4ScanResultEssNum++; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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. + */ +/*----------------------------------------------------------------------------*/ +uint32_t scanAddScanResult(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBssDesc, + IN struct SW_RFB *prSwRfb) +{ + struct SCAN_INFO *prScanInfo; + uint8_t aucRatesEx[PARAM_MAX_LEN_RATES_EX]; + struct WLAN_BEACON_FRAME *prWlanBeaconFrame; + uint8_t rMacAddr[PARAM_MAC_ADDR_LEN]; + struct PARAM_SSID rSsid; + enum ENUM_PARAM_NETWORK_TYPE eNetworkType; + struct PARAM_802_11_CONFIG rConfiguration; + enum ENUM_PARAM_OP_MODE eOpMode; + uint8_t ucRateLen = 0; + uint32_t 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) */ + log_dbg(SCN, INFO, "Bss Desc type is P2P\n"); + return WLAN_STATUS_FAILURE; + } + + prWlanBeaconFrame = (struct WLAN_BEACON_FRAME *) prSwRfb->pvHeader; + COPY_MAC_ADDR(rMacAddr, prWlanBeaconFrame->aucBSSID); + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + + rConfiguration.u4Length = sizeof(struct PARAM_802_11_CONFIG); + rConfiguration.u4BeaconPeriod + = (uint32_t) prWlanBeaconFrame->u2BeaconInterval; + rConfiguration.u4ATIMWindow = prBssDesc->u2ATIMWindow; + rConfiguration.u4DSConfig = nicChannelNum2Freq(prBssDesc->ucChannelNum); + rConfiguration.rFHConfig.u4Length + = sizeof(struct PARAM_802_11_CONFIG_FH); + + 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 < ARRAY_SIZE(aucRatesEx); 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; + } + + log_dbg(SCN, TRACE, "ind %s %d %d\n", prBssDesc->aucSSID, + prBssDesc->ucChannelNum, prBssDesc->ucRCPI); + + scanAddEssResult(prAdapter, prBssDesc); + if (prAdapter->rWifiVar.rScanInfo.fgSchedScanning && + test_bit(SUSPEND_FLAG_CLEAR_WHEN_RESUME, + &prAdapter->ulSuspendFlag)) { + uint8_t i = 0; + struct BSS_DESC **pprPendBssDesc + = &prScanInfo->rSchedScanParam. + aprPendingBssDescToInd[0]; + + for (; i < SCN_SSID_MATCH_MAX_NUM; i++) { + if (pprPendBssDesc[i]) + continue; + log_dbg(SCN, INFO, "indicate bss[" + MACSTR + "] before wiphy resume, need to indicate again after wiphy resume\n", + MAC2STR(prBssDesc->aucBSSID)); + pprPendBssDesc[i] = prBssDesc; + break; + } + } + + if (prBssDesc->fgIsValidSSID) { + kalIndicateBssInfo(prAdapter->prGlueInfo, + (uint8_t *) prSwRfb->pvHeader, + prSwRfb->u2PacketLen, + prBssDesc->ucChannelNum, + RCPI_TO_dBm(prBssDesc->ucRCPI)); + } + + nicAddScanResult(prAdapter, + rMacAddr, + &rSsid, + prWlanBeaconFrame->u2CapInfo, + RCPI_TO_dBm(prBssDesc->ucRCPI), + eNetworkType, + &rConfiguration, + eOpMode, + aucRatesEx, + prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen, + (uint8_t *) ((unsigned long) (prSwRfb->pvHeader) + + WLAN_MAC_MGMT_HEADER_LEN)); + + return WLAN_STATUS_SUCCESS; + +} /* end of scanAddScanResult() */ + +u_int8_t scanCheckBssIsLegal(IN struct ADAPTER *prAdapter, + struct BSS_DESC *prBssDesc) +{ + u_int8_t fgAddToScanResult = FALSE; + enum ENUM_BAND eBand; + uint8_t ucChannel; + + ASSERT(prAdapter); + /* check the channel is in the legal doamin */ + if (rlmDomainIsLegalChannel(prAdapter, prBssDesc->eBand, + prBssDesc->ucChannelNum) == TRUE) { + /* check ucChannelNum/eBand for adjacement channel filtering */ + if (cnmAisInfraChannelFixed(prAdapter, + &eBand, &ucChannel) == TRUE && + (eBand != prBssDesc->eBand + || ucChannel != prBssDesc->ucChannelNum)) { + fgAddToScanResult = FALSE; + } else { + fgAddToScanResult = TRUE; + } + } + + return fgAddToScanResult; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +uint32_t scanProcessBeaconAndProbeResp(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct SCAN_INFO *prScanInfo; + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_DESC *prBssDesc = (struct BSS_DESC *) NULL; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + struct BSS_INFO *prAisBssInfo; + struct WLAN_BEACON_FRAME *prWlanBeaconFrame + = (struct WLAN_BEACON_FRAME *) NULL; +#if CFG_SLT_SUPPORT + struct SLT_INFO *prSltInfo = (struct SLT_INFO *) NULL; +#endif + + ASSERT(prAdapter); + ASSERT(prSwRfb); + +#if CFG_SUPPORT_802_11K + /* if beacon request measurement is on-going, collect Beacon Report */ + if (rlmBcnRmRunning(prAdapter)) { + rlmProcessBeaconAndProbeResp(prAdapter, prSwRfb); + return WLAN_STATUS_SUCCESS; + } +#endif + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + /* 4 <0> Ignore invalid Beacon Frame */ + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < + (TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + + CAP_INFO_FIELD_LEN)) { + log_dbg(SCN, ERROR, "Ignore invalid Beacon Frame\n"); + return rStatus; + } + + scanResultLog(prAdapter, prSwRfb); + +#if CFG_SLT_SUPPORT + prSltInfo = &prAdapter->rWifiVar.rSltInfo; + + if (prSltInfo->fgIsDUT) { + log_dbg(P2P, INFO, "\n\rBCN: RX\n"); + prSltInfo->u4BeaconReceiveCnt++; + return WLAN_STATUS_SUCCESS; + } else { + return WLAN_STATUS_SUCCESS; + } +#endif + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prAisBssInfo = prAdapter->prAisBssInfo; + prWlanBeaconFrame = (struct WLAN_BEACON_FRAME *) prSwRfb->pvHeader; + + /* 4 <1> Parse and add into BSS_DESC_T */ + prBssDesc = scanAddToBssDesc(prAdapter, prSwRfb); + prAdapter->rWlanInfo.u4ScanDbgTimes1++; + + if (prBssDesc) { + /* Full2Partial: save channel info for later scan */ + if (prScanInfo->fgIsScanForFull2Partial) { + log_dbg(SCN, TRACE, "Full2Partial: set channel=%d\n", + prBssDesc->ucChannelNum); + scanSetBit(prBssDesc->ucChannelNum, + prScanInfo->au4ChannelBitMap, + sizeof(prScanInfo->au4ChannelBitMap)); + } + + /* 4 <1.1> Beacon Change Detection for Connected BSS */ + if ((prAisBssInfo != NULL) && + (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)) { +#if CFG_SUPPORT_BEACON_CHANGE_DETECTION + u_int8_t fgNeedDisconnect = FALSE; + + /* <1.1.2> check if supported rate differs */ + if (prAisBssInfo->u2OperationalRateSet + != prBssDesc->u2OperationalRateSet) + fgNeedDisconnect = TRUE; +#endif + if (rsnCheckSecurityModeChanged(prAdapter, + prAisBssInfo, prBssDesc) +#if CFG_SUPPORT_WAPI + || (prAdapter->rWifiVar.rConnSettings + .fgWapiMode == TRUE && + !wapiPerformPolicySelection(prAdapter, + prBssDesc)) +#endif + ) { + + log_dbg(SCN, INFO, "Beacon security mode change detected\n"); + log_mem8_dbg(SCN, INFO, + prSwRfb->pvHeader, + prSwRfb->u2PacketLen); +#if CFG_SUPPORT_BEACON_CHANGE_DETECTION + fgNeedDisconnect = FALSE; +#endif + if (!prConnSettings + ->fgSecModeChangeStartTimer) { + cnmTimerStartTimer(prAdapter, + &prAdapter->rWifiVar + .rAisFsmInfo + .rSecModeChangeTimer, + SEC_TO_MSEC(3)); + prConnSettings + ->fgSecModeChangeStartTimer + = TRUE; + } + } else { + if (prConnSettings->fgSecModeChangeStartTimer) { + cnmTimerStopTimer(prAdapter, + &prAdapter->rWifiVar + .rAisFsmInfo + .rSecModeChangeTimer); + prConnSettings + ->fgSecModeChangeStartTimer + = FALSE; + } + } + +#if CFG_SUPPORT_BEACON_CHANGE_DETECTION + /* <1.1.3> beacon content change detected, + * disconnect immediately + */ + if (fgNeedDisconnect == TRUE) + aisBssBeaconTimeout(prAdapter); +#endif + } + /* 4 <1.1> Update AIS_BSS_INFO */ + if ((prAisBssInfo != NULL) && + ((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 + */ + log_dbg(SCN, TRACE, "DTIMPeriod[%u] Present[%u] BSSID[" + MACSTR "]\n", + prAisBssInfo->ucDTIMPeriod, + prAisBssInfo->fgTIMPresent, + MAC2STR(prBssDesc->aucBSSID)); + if ((!prAisBssInfo->ucDTIMPeriod) && + prAisBssInfo->fgTIMPresent && + EQUAL_MAC_ADDR(prBssDesc->aucBSSID, + prAisBssInfo->aucBSSID) && + (prAisBssInfo->eCurrentOPMode + == OP_MODE_INFRASTRUCTURE) && + ((prWlanBeaconFrame->u2FrameCtrl + & MASK_FRAME_TYPE) + == MAC_FRAME_BEACON)) { + prAisBssInfo->ucDTIMPeriod + = prBssDesc->ucDTIMPeriod; + prAisBssInfo->fgTIMPresent + = prBssDesc->fgTIMPresent; + + /* Handle No TIM IE information case */ + if (!prAisBssInfo->fgTIMPresent) { + enum PARAM_POWER_MODE ePwrMode + = Param_PowerModeCAM; + + log_dbg(SCN, WARN, "IE TIM absence, set to CAM mode!\n"); + nicConfigPowerSaveProfile( + prAdapter, + prAisBssInfo-> + ucBssIndex, ePwrMode, + FALSE, + PS_CALLER_NO_TIM); + } + /* sync with firmware for + * beacon information + */ + nicPmIndicateBssConnected(prAdapter, + prAisBssInfo->ucBssIndex); + } + } +#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)) { + + ASSERT(prSwRfb->prRxStatusGroup3); + + ibssProcessMatchedBeacon(prAdapter, + prAisBssInfo, + prBssDesc, + nicRxGetRcpiValueFromRxv(RCPI_MODE_MAX, + prSwRfb)); + } +#endif /* CFG_SUPPORT_ADHOC */ + } + + rlmProcessBcn(prAdapter, + prSwRfb, + ((struct WLAN_BEACON_FRAME *) (prSwRfb->pvHeader)) + ->aucInfoElem, + (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - + (uint16_t) (OFFSET_OF(struct WLAN_BEACON_FRAME_BODY, + aucInfoElem[0]))); + + mqmProcessBcn(prAdapter, + prSwRfb, + ((struct WLAN_BEACON_FRAME *) (prSwRfb->pvHeader)) + ->aucInfoElem, + (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - + (uint16_t) (OFFSET_OF(struct WLAN_BEACON_FRAME_BODY, + aucInfoElem[0]))); + + prAdapter->rWlanInfo.u4ScanDbgTimes2++; + + /* 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) { + u_int8_t fgAddToScanResult = FALSE; + + /* for AIS, send to host */ + prAdapter->rWlanInfo.u4ScanDbgTimes3++; + if (prConnSettings->fgIsScanReqIssued + || prScanInfo->fgSchedScanning) { + fgAddToScanResult + = scanCheckBssIsLegal(prAdapter, + prBssDesc); + prAdapter->rWlanInfo.u4ScanDbgTimes4++; + + if (fgAddToScanResult == TRUE) { + rStatus = scanAddScanResult(prAdapter, + prBssDesc, prSwRfb); + } + } + if (fgAddToScanResult == FALSE) { + kalMemZero(prBssDesc->aucRawBuf, + CFG_RAW_BUFFER_SIZE); + prBssDesc->u2RawLength = 0; + } + } +#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 + */ +/*----------------------------------------------------------------------------*/ +struct BSS_DESC *scanSearchBssDescByPolicy( + IN struct ADAPTER *prAdapter, IN uint8_t ucBssIndex) +{ + struct CONNECTION_SETTINGS *prConnSettings; + struct BSS_INFO *prBssInfo; + struct AIS_SPECIFIC_BSS_INFO *prAisSpecBssInfo; + struct SCAN_INFO *prScanInfo; + + struct LINK *prBSSDescList; + + struct BSS_DESC *prBssDesc = (struct BSS_DESC *) NULL; + struct BSS_DESC *prPrimaryBssDesc = (struct BSS_DESC *) NULL; + struct BSS_DESC *prCandidateBssDesc = (struct BSS_DESC *) NULL; + + struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; + struct STA_RECORD *prPrimaryStaRec; + struct STA_RECORD *prCandidateStaRec = (struct STA_RECORD *) NULL; + + OS_SYSTIME rCurrentTime; + + /* The first one reach the check point will be our candidate */ + u_int8_t fgIsFindFirst = (u_int8_t) FALSE; + + u_int8_t fgIsFindBestRSSI = (u_int8_t) FALSE; +#if !CFG_SUPPORT_CFG80211_AUTH + u_int8_t fgIsFindBestEncryptionLevel = (u_int8_t) FALSE; +#endif + /* u_int8_t fgIsFindMinChannelLoad = (u_int8_t) FALSE; */ + + /* TODO(Kevin): Support Min Channel Load */ + /* uint8_t aucChannelLoad[CHANNEL_NUM] = {0}; */ + + u_int8_t fgIsFixedChannel = (u_int8_t) FALSE; + enum ENUM_BAND eBand = BAND_2G4; + uint8_t ucChannel = 0; + uint32_t u4ScnAdhocBssDescTimeout = 0; +#if CFG_SUPPORT_NCHO + uint8_t ucRCPIStep = ROAMING_NO_SWING_RCPI_STEP; +#endif + + ASSERT(prAdapter); + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + prAisSpecBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + + GET_CURRENT_SYSTIME(&rCurrentTime); + + /* check for fixed channel operation */ + if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) { +#if CFG_SUPPORT_CHNL_CONFLICT_REVISE + fgIsFixedChannel = + cnmAisDetectP2PChannel(prAdapter, &eBand, &ucChannel); +#else + fgIsFixedChannel = + cnmAisInfraChannelFixed(prAdapter, &eBand, &ucChannel); +#endif + } else + fgIsFixedChannel = FALSE; + +#if DBG + if (prConnSettings->ucSSIDLen < ELEM_MAX_LEN_SSID) + prConnSettings->aucSSID[prConnSettings->ucSSIDLen] = '\0'; +#endif + + log_dbg(SCN, INFO, "SEARCH: Bss Num: %d, Look for SSID: %s, " + MACSTR " Band=%d, channel=%d\n", + (uint32_t) prBSSDescList->u4NumElem, prConnSettings->aucSSID, + MAC2STR(prConnSettings->aucBSSID), eBand, ucChannel); + + /* 4 <1> The outer loop to search for a candidate. */ + LINK_FOR_EACH_ENTRY( + prBssDesc, prBSSDescList, rLinkEntry, struct BSS_DESC) { + + /* TODO(Kevin): Update Minimum Channel Load Information here */ + +#if 0 + log_dbg(SCN, INFO, "SEARCH: [" MACSTR "], SSID:%s\n", + MAC2STR(prBssDesc->aucBSSID), prBssDesc->aucSSID); +#endif + + /* 4 <2> Check PHY Type and attributes */ + /* 4 <2.1> Check Unsupported BSS PHY Type */ + if (!(prBssDesc->ucPhyTypeSet + & (prAdapter->rWifiVar.ucAvailablePhyTypeSet))) { + log_dbg(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) { + log_dbg(SCN, LOUD, "SEARCH: Ignore Unknown Bss Basic Rate\n"); + continue; + } + /* 4 <2.3> Check if fixed operation cases should be aware */ + if (fgIsFixedChannel == TRUE + && (prBssDesc->eBand != eBand + || prBssDesc->ucChannelNum != ucChannel)) { + log_dbg(SCN, LOUD, "SEARCH: Ignore BssBand[%d] != FixBand[%d] or BssCH[%d] != FixCH[%d]\n", + 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) { + log_dbg(SCN, LOUD, "SEARCH: Ignore illegal CH Band[%d] CH[%d]\n", + prBssDesc->eBand, prBssDesc->ucChannelNum); + continue; + } + /* 4 <2.5> Check if this BSS_DESC_T is stale */ + u4ScnAdhocBssDescTimeout = SCN_BSS_DESC_STALE_SEC; +#if CFG_ENABLE_WIFI_DIRECT +#if CFG_SUPPORT_WFD + if (prAdapter->rWifiVar.rWfdConfigureSettings.ucWfdEnable) + u4ScnAdhocBssDescTimeout = SCN_BSS_DESC_STALE_SEC_WFD; +#endif +#endif + if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, + SEC_TO_SYSTIME(u4ScnAdhocBssDescTimeout))) { + log_dbg(SCN, LOUD, "SEARCH: Ignore stale Bss, CurrTime[%u] BssUpdateTime[%u]\n", + rCurrentTime, prBssDesc->rUpdateTime); + continue; + } + /* 4 <3> Check if reach the excessive join retry limit */ + /* NOTE(Kevin): STA_RECORD_T is recorded by TA. */ + prStaRec = cnmGetStaRecByAddress( + prAdapter, ucBssIndex, prBssDesc->aucSrcAddr); + + /* 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 + && prStaRec->u2ReasonCode != REASON_CODE_RESERVED) { + log_dbg(SCN, INFO, "SEARCH: Ignore BSS with previous Reason Code = %d\n", + prStaRec->u2ReasonCode); + continue; + } else +#endif + if (prStaRec + && 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; + } + + log_dbg(SCN, INFO, "SEARCH:Try to join BSS again,Status Code=%u(Curr=%u/Last Join=%u)\n", + prStaRec->u2StatusCode, rCurrentTime, + prStaRec->rLastJoinTime); + } else { + log_dbg(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 (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) { + enum ENUM_BSS_TYPE eBSSType = + prBssDesc->eBSSType; + enum ENUM_PARAM_OP_MODE eOPMode = + prConnSettings->eOPMode; + /* 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 (eOPMode == NET_TYPE_INFRA + && eBSSType != BSS_TYPE_INFRASTRUCTURE) { + log_dbg(SCN, INFO, "SEARCH: Ignore eBSSType = IBSS\n"); + continue; + } + if ((eOPMode == NET_TYPE_IBSS + || eOPMode == NET_TYPE_DEDICATED_IBSS) + && eBSSType != BSS_TYPE_IBSS) { + log_dbg(SCN, INFO, "SEARCH: Ignore eBSSType = INFRASTRUCTURE\n"); + continue; + } + /* 4 <4.2> Check AP's BSSID if OID_802_11_BSSID has been + * set. + */ + if (prConnSettings->fgIsConnByBssidIssued && + eBSSType == BSS_TYPE_INFRASTRUCTURE) { + if (UNEQUAL_MAC_ADDR(prConnSettings->aucBSSID, + prBssDesc->aucBSSID)) { + log_dbg(SCN, TRACE, "SEARCH: Ignore due to BSSID was not matched!\n"); + continue; + } + } +#if CFG_SUPPORT_ADHOC + /* 4 <4.3> Check for AdHoc Mode */ + if (eBSSType == BSS_TYPE_IBSS) { + OS_SYSTIME rCurrentTime; + + u4ScnAdhocBssDescTimeout = + SCN_ADHOC_BSS_DESC_TIMEOUT_SEC; + + /* 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 CFG_ENABLE_WIFI_DIRECT +#if CFG_SUPPORT_WFD + if (prAdapter->rWifiVar + .rWfdConfigureSettings.ucWfdEnable) { +#define __LOCAL_VAR__ SCN_ADHOC_BSS_DESC_TIMEOUT_SEC_WFD + u4ScnAdhocBssDescTimeout + = __LOCAL_VAR__; +#undef __LOCAL_VAR__ + } +#endif +#endif + if (CHECK_FOR_TIMEOUT(rCurrentTime, + prBssDesc->rUpdateTime, + SEC_TO_SYSTIME( + u4ScnAdhocBssDescTimeout))) { + log_dbg(SCN, LOUD, "SEARCH: Now(%u) Skip old record of BSS Descriptor(%u) - BSSID:[" + MACSTR "]\n", + rCurrentTime, + prBssDesc->rUpdateTime, + MAC2STR(prBssDesc->aucBSSID)); + continue; + } + + /* 4 <4.3.2> Check Peer's capability */ + if (ibssCheckCapabilityForAdHocMode(prAdapter, + prBssDesc) == WLAN_STATUS_FAILURE) { + + log_dbg(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)) { + + log_dbg(SCN, LOUD, "SEARCH: prBssDesc->fgIsLargerTSF = %d\n", + prBssDesc->fgIsLargerTSF); + + if (!prBssDesc->fgIsLargerTSF) { + log_dbg(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) + )){ + log_dbg(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))) { + log_dbg(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) { + + log_dbg(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); + + log_dbg(SCAN, TRACE, "\n\nCurrent TSF : %08lx-%08lx\n\n", + rCurrentTsf.u.HighPart, + rCurrentTsf.u.LowPart); + } + + if (rCurrentTsf.QuadPart + > prPrimaryBssDesc + ->u8TimeStamp.QuadPart) { + log_dbg(SCAN, TRACE, "Ignore BSS DESC MAC: [" + MACSTR"], Current BSSID: [" + MACSTR "].\n", + MAC2STR(prPrimaryBssDesc + ->aucBSSID), + MAC2STR(prBssInfo->aucBSSID)); + + log_dbg(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 = (struct BSS_DESC *) 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; + + log_dbg(SCN, LOUD, "SEARCH: Found BSS by SSID, [" + MACSTR "], SSID:%s\n", + MAC2STR(prBssDesc->aucBSSID), + prBssDesc->aucSSID); + } + 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 struct BSS_DESC + * 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)) { + + /* Make sure to match with SSID if supplied. + * Some old dualband APs share a single BSSID + * among different BSSes. + */ + if ((prBssDesc->ucSSIDLen > 0 && + prConnSettings->ucSSIDLen > 0 && + EQUAL_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, + prConnSettings->aucSSID, + prConnSettings->ucSSIDLen)) || + prConnSettings->ucSSIDLen == 0) { + log_dbg(SCN, LOUD, "%s: BSSID/SSID pair matched\n", + __func__); +#if CFG_SUPPORT_CFG80211_AUTH + if (prBssDesc->ucChannelNum == + prConnSettings->ucChannelNum) { + prPrimaryBssDesc = prBssDesc; + fgIsFindFirst = TRUE; + } +#else + prPrimaryBssDesc = prBssDesc; +#endif + } else + log_dbg(SCN, ERROR, "%s: BSSID/SSID pair unmatched (" + MACSTR + ")\n", __func__, + MAC2STR(prBssDesc->aucBSSID)); + } + 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_CFG80211_AUTH +#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 + */ + log_dbg(RSN, INFO, "Ignore BSS can't pass WAPI policy selection\n"); + continue; + } + } else +#endif + if (rsnPerformPolicySelection(prAdapter, + prPrimaryBssDesc)) { + if (prAisSpecBssInfo->fgCounterMeasure) { + log_dbg(RSN, INFO, "Skip while at counter measure period!!!\n"); + continue; + } + + if (prPrimaryBssDesc->ucEncLevel > 0) { + fgIsFindBestEncryptionLevel = TRUE; + + fgIsFindFirst = FALSE; + } + } else { + /* Can't pass the Encryption Status Check, + * get next one + */ + log_dbg(RSN, INFO, "Ignore BSS can't pass Encryption Status Check\n"); + 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 { + /* 4 <6D> Condition - Visible SSID win Hidden SSID. */ + if (prCandidateBssDesc->fgIsHiddenSSID) { + if (!prPrimaryBssDesc->fgIsHiddenSSID) { + /* The non Hidden SSID win. */ + prCandidateBssDesc = prPrimaryBssDesc; + + 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. + */ + log_dbg(SCN, TRACE, "Candidate [" + MACSTR + "]: uint8_t = %d, joinFailCnt=%d, Primary [" + MACSTR "]: uint8_t = %d, joinFailCnt=%d\n", + MAC2STR(prCandidateBssDesc->aucBSSID), + prCandidateBssDesc->ucRCPI, + prCandidateBssDesc->ucJoinFailureCount, + MAC2STR(prPrimaryBssDesc->aucBSSID), + prPrimaryBssDesc->ucRCPI, + prPrimaryBssDesc->ucJoinFailureCount); + + ASSERT(!(prCandidateBssDesc->fgIsConnected + && prPrimaryBssDesc->fgIsConnected)); + if (prPrimaryBssDesc->ucJoinFailureCount + > SCN_BSS_JOIN_FAIL_THRESOLD) { + /* give a chance to do join if join + * fail before + * SCN_BSS_DECRASE_JOIN_FAIL_CNT_SEC + * seconds + */ +#define __LOCAL_VAR__ \ +SCN_BSS_JOIN_FAIL_CNT_RESET_SEC + if (CHECK_FOR_TIMEOUT(rCurrentTime, + prBssDesc->rJoinFailTime, + SEC_TO_SYSTIME( + __LOCAL_VAR__))) { +#define __LOCAL_VAR2__ \ +SCN_BSS_JOIN_FAIL_RESET_STEP + + prBssDesc->ucJoinFailureCount + -= __LOCAL_VAR2__; +#undef __LOCAL_VAR2__ + + log_dbg(AIS, INFO, "decrease join fail count for Bss " + MACSTR + " to %u, timeout second %d\n", + MAC2STR( + prBssDesc->aucBSSID), + prBssDesc + ->ucJoinFailureCount, + __LOCAL_VAR__); + } +#undef __LOCAL_VAR__ + } + /* NOTE: To prevent SWING, we do roaming only + * if target AP has at least 5dBm larger + * than us. + */ +#if CFG_SUPPORT_NCHO + if (prAdapter->rNchoInfo.fgECHOEnabled + == TRUE) { + ucRCPIStep = 2 * prAdapter + ->rNchoInfo.i4RoamDelta; + } +#endif + if (prCandidateBssDesc->fgIsConnected) { + if ((prCandidateBssDesc->ucRCPI + + ROAMING_NO_SWING_RCPI_STEP <= + prPrimaryBssDesc->ucRCPI) + && prPrimaryBssDesc + ->ucJoinFailureCount + <= SCN_BSS_JOIN_FAIL_THRESOLD) { + + prCandidateBssDesc + = prPrimaryBssDesc; + prCandidateStaRec + = prPrimaryStaRec; + continue; + } + } else if (prPrimaryBssDesc->fgIsConnected) { + if ((prCandidateBssDesc->ucRCPI < + prPrimaryBssDesc->ucRCPI + + ROAMING_NO_SWING_RCPI_STEP) + || (prCandidateBssDesc + ->ucJoinFailureCount + > SCN_BSS_JOIN_FAIL_THRESOLD)) { + + prCandidateBssDesc + = prPrimaryBssDesc; + prCandidateStaRec + = prPrimaryStaRec; + continue; + } + } else if (prPrimaryBssDesc + ->ucJoinFailureCount + > SCN_BSS_JOIN_FAIL_THRESOLD) + continue; + else if (prCandidateBssDesc + ->ucJoinFailureCount + > SCN_BSS_JOIN_FAIL_THRESOLD || + prCandidateBssDesc->ucRCPI + < prPrimaryBssDesc->ucRCPI) { + + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } +#if 0 + /* If reach here, that means they have the same + * Encryption Score, and both RSSI value are close too. + */ + /* 4 <6F> Seek the minimum Channel Load for less + * interference. + */ + if (fgIsFindMinChannelLoad) { + /* ToDo:: Nothing */ + /* TODO(Kevin): Check which one has minimum + * channel load in its channel + */ + } +#endif + } + } + + return prCandidateBssDesc; + +} /* end of scanSearchBssDescByPolicy() */ + +void scanReportBss2Cfg80211(IN struct ADAPTER *prAdapter, + IN enum ENUM_BSS_TYPE eBSSType, + IN struct BSS_DESC *SpecificprBssDesc) +{ + struct SCAN_INFO *prScanInfo = NULL; + struct LINK *prBSSDescList = NULL; + struct BSS_DESC *prBssDesc = NULL; + struct RF_CHANNEL_INFO rChannelInfo; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prBSSDescList = &prScanInfo->rBSSDescList; + + log_dbg(SCN, TRACE, "eBSSType: %d\n", eBSSType); + + if (SpecificprBssDesc) { + { + /* check BSSID is legal channel */ + if (!scanCheckBssIsLegal(prAdapter, + SpecificprBssDesc)) { + log_dbg(SCN, TRACE, + "Remove specific SSID[%s %d]\n", + SpecificprBssDesc->aucSSID, + SpecificprBssDesc->ucChannelNum); + return; + } + + log_dbg(SCN, TRACE, "Report specific SSID[%s] ValidSSID[%u]\n", + SpecificprBssDesc->aucSSID, + SpecificprBssDesc->fgIsValidSSID); + + if (eBSSType == BSS_TYPE_INFRASTRUCTURE) { + if (SpecificprBssDesc->fgIsValidSSID) { + kalIndicateBssInfo( + prAdapter->prGlueInfo, + (uint8_t *) + SpecificprBssDesc->aucRawBuf, + SpecificprBssDesc->u2RawLength, + SpecificprBssDesc->ucChannelNum, + RCPI_TO_dBm( + SpecificprBssDesc->ucRCPI)); + } + } else { + + rChannelInfo.ucChannelNum + = SpecificprBssDesc->ucChannelNum; + rChannelInfo.eBand = SpecificprBssDesc->eBand; + kalP2PIndicateBssInfo(prAdapter->prGlueInfo, + (uint8_t *) + SpecificprBssDesc->aucRawBuf, + SpecificprBssDesc->u2RawLength, + &rChannelInfo, + RCPI_TO_dBm(SpecificprBssDesc->ucRCPI)); + + } + +#if CFG_ENABLE_WIFI_DIRECT + SpecificprBssDesc->fgIsP2PReport = FALSE; +#endif + } + } else { + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + /* Clear old ACS data (APNum, Dirtiness, ...) + * and initialize the ch number + */ + kalMemZero(&(prAdapter->rWifiVar.rChnLoadInfo), + sizeof(prAdapter->rWifiVar.rChnLoadInfo)); + wlanInitChnLoadInfoChannelList(prAdapter); +#endif + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, + rLinkEntry, struct BSS_DESC) { +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + /* Record channel loading with channel's AP number */ + uint8_t ucIdx + = wlanGetChannelIndex(prBssDesc->ucChannelNum); + + if (ucIdx < MAX_CHN_NUM) + prAdapter->rWifiVar + .rChnLoadInfo + .rEachChnLoad[ucIdx].u2APNum++; +#endif + + /* check BSSID is legal channel */ + if (!scanCheckBssIsLegal(prAdapter, prBssDesc)) { + log_dbg(SCN, TRACE, "Remove SSID[%s %d]\n", + prBssDesc->aucSSID, + prBssDesc->ucChannelNum); + continue; + } + + if ((prBssDesc->eBSSType == eBSSType) +#if CFG_ENABLE_WIFI_DIRECT + || ((eBSSType == BSS_TYPE_P2P_DEVICE) + && (prBssDesc->fgIsP2PReport == TRUE + && prAdapter->p2p_scan_report_all_bss)) +#endif + ) { + + log_dbg(SCN, TRACE, "Report " MACSTR " SSID[%s %u] eBSSType[%d] ValidSSID[%u] u2RawLength[%d] fgIsP2PReport[%d]\n", + MAC2STR(prBssDesc->aucBSSID), + prBssDesc->aucSSID, + prBssDesc->ucChannelNum, + prBssDesc->eBSSType, + prBssDesc->fgIsValidSSID, + prBssDesc->u2RawLength, + prBssDesc->fgIsP2PReport); + + if (eBSSType == BSS_TYPE_INFRASTRUCTURE) { + if (prBssDesc->u2RawLength != 0 && + prBssDesc->fgIsValidSSID) { + kalIndicateBssInfo( + prAdapter->prGlueInfo, + (uint8_t *) + prBssDesc->aucRawBuf, + prBssDesc->u2RawLength, + prBssDesc->ucChannelNum, + RCPI_TO_dBm( + prBssDesc->ucRCPI)); + } + kalMemZero(prBssDesc->aucRawBuf, + CFG_RAW_BUFFER_SIZE); + prBssDesc->u2RawLength = 0; +#if CFG_ENABLE_WIFI_DIRECT + prBssDesc->fgIsP2PReport = FALSE; +#endif + } else { +#if CFG_ENABLE_WIFI_DIRECT + if ((prBssDesc->fgIsP2PReport == TRUE && + prAdapter->p2p_scan_report_all_bss) + && prBssDesc->u2RawLength != 0) { +#endif + rChannelInfo.ucChannelNum + = prBssDesc + ->ucChannelNum; + rChannelInfo.eBand + = prBssDesc->eBand; + + kalP2PIndicateBssInfo( + prAdapter->prGlueInfo, + (uint8_t *) + prBssDesc->aucRawBuf, + prBssDesc->u2RawLength, + &rChannelInfo, + RCPI_TO_dBm( + prBssDesc->ucRCPI)); + + /* do not clear it then we can + * pass the bss in + * Specific report + */ +#if 0 /* TODO: Remove this */ + kalMemZero(prBssDesc->aucRawBuf, + CFG_RAW_BUFFER_SIZE); +#endif + + /* the BSS entry will not be + * cleared after scan done. + * So if we dont receive the BSS + * in next scan, we cannot pass + * it. We use u2RawLength for + * the purpose. + */ +#if 0 + prBssDesc->u2RawLength = 0; +#endif + +#if CFG_ENABLE_WIFI_DIRECT + prBssDesc->fgIsP2PReport + = FALSE; + } +#endif + } + } + + } +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + wlanCalculateAllChannelDirtiness(prAdapter); + wlanSortChannel(prAdapter); + + prAdapter->rWifiVar.rChnLoadInfo.fgDataReadyBit = TRUE; +#endif + + } + +} + +#if CFG_SUPPORT_PASSPOINT +/*----------------------------------------------------------------------------*/ +/*! + * @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 + */ +/*----------------------------------------------------------------------------*/ +struct BSS_DESC *scanSearchBssDescByBssidAndLatestUpdateTime( + IN struct ADAPTER *prAdapter, IN uint8_t aucBSSID[]) +{ + struct SCAN_INFO *prScanInfo; + struct LINK *prBSSDescList; + struct BSS_DESC *prBssDesc; + struct BSS_DESC *prDstBssDesc = (struct BSS_DESC *) NULL; + OS_SYSTIME rLatestUpdateTime = 0; + + ASSERT(prAdapter); + ASSERT(aucBSSID); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prBSSDescList = &prScanInfo->rBSSDescList; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY( + prBssDesc, prBSSDescList, rLinkEntry, struct BSS_DESC) { + + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { + if (!rLatestUpdateTime + || CHECK_FOR_EXPIRATION(prBssDesc->rUpdateTime, + rLatestUpdateTime)) { + prDstBssDesc = prBssDesc; + COPY_SYSTIME(rLatestUpdateTime, + prBssDesc->rUpdateTime); + } + } + } + + return prDstBssDesc; + +} /* end of scanSearchBssDescByBssid() */ + +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_AGPS_ASSIST +void scanReportScanResultToAgps(struct ADAPTER *prAdapter) +{ + struct LINK *prBSSDescList = + &prAdapter->rWifiVar.rScanInfo.rBSSDescList; + struct BSS_DESC *prBssDesc = NULL; + struct AGPS_AP_LIST *prAgpsApList = + kalMemAlloc(sizeof(struct AGPS_AP_LIST), VIR_MEM_TYPE); + struct AGPS_AP_INFO *prAgpsInfo = &prAgpsApList->arApInfo[0]; + struct SCAN_INFO *prScanInfo = &prAdapter->rWifiVar.rScanInfo; + uint8_t ucIndex = 0; + + LINK_FOR_EACH_ENTRY( + prBssDesc, prBSSDescList, rLinkEntry, struct BSS_DESC) { + + if (prBssDesc->rUpdateTime < prScanInfo->rLastScanCompletedTime) + continue; + COPY_MAC_ADDR(prAgpsInfo->aucBSSID, prBssDesc->aucBSSID); + prAgpsInfo->ePhyType = AGPS_PHY_G; + prAgpsInfo->u2Channel = prBssDesc->ucChannelNum; + prAgpsInfo->i2ApRssi = RCPI_TO_dBm(prBssDesc->ucRCPI); + prAgpsInfo++; + ucIndex++; + if (ucIndex == SCN_AGPS_AP_LIST_MAX_NUM) + break; + } + prAgpsApList->ucNum = ucIndex; + GET_CURRENT_SYSTIME(&prScanInfo->rLastScanCompletedTime); + /* log_dbg(SCN, INFO, ("num of scan list:%d\n", ucIndex)); */ + kalIndicateAgpsNotify(prAdapter, AGPS_EVENT_WLAN_AP_LIST, + (uint8_t *) prAgpsApList, sizeof(struct AGPS_AP_LIST)); + kalMemFree(prAgpsApList, VIR_MEM_TYPE, sizeof(struct AGPS_AP_LIST)); +} +#endif /* CFG_SUPPORT_AGPS_ASSIST */ + +void scanReqLog(struct CMD_SCAN_REQ_V2 *prCmdScanReq) +{ + char *scanType; + char *ssidType; + char *channelType; + + switch (prCmdScanReq->ucScanType) { + case SCAN_TYPE_PASSIVE_SCAN: + scanType = "Passive"; + break; + case SCAN_TYPE_ACTIVE_SCAN: + scanType = "Active"; + break; + default: + scanType = "Uknown"; + } + + switch (prCmdScanReq->ucSSIDType) { + case SCAN_REQ_SSID_WILDCARD: + ssidType = "Wildcard"; + break; + case SCAN_REQ_SSID_P2P_WILDCARD: + ssidType = "P2PWildcard"; + break; + case SCAN_REQ_SSID_SPECIFIED: + ssidType = "Specified"; + break; + case SCAN_REQ_SSID_SPECIFIED_ONLY: + ssidType = "SpecifiedOnly"; + break; + default: + ssidType = "Uknown"; + } + + switch (prCmdScanReq->ucChannelType) { + case SCAN_CHANNEL_FULL: + channelType = "full"; + break; + case SCAN_CHANNEL_2G4: + channelType = "2G"; + break; + case SCAN_CHANNEL_5G: + channelType = "5G"; + break; + case SCAN_CHANNEL_P2P_SOCIAL: + channelType = "P2PSocial"; + break; + case SCAN_CHANNEL_SPECIFIED: + channelType = "Sepcified"; + break; + default: + channelType = "Uknown"; + } + + scanlog_dbg(LOG_SCAN_REQ_D2F, INFO, "Scan#%u to Q:[Scan]%s:0x%x[SSID]%s:0x%x Num=%u ExtNum=%u[Ch]%s:0x%x Num=%u ExtNum=%u DW=%u minDW=%u[Ver%u]", + prCmdScanReq->ucSeqNum, + scanType, + prCmdScanReq->ucScanType, + ssidType, + prCmdScanReq->ucSSIDType, + prCmdScanReq->ucSSIDNum, + prCmdScanReq->ucSSIDExtNum, + channelType, + prCmdScanReq->ucChannelType, + prCmdScanReq->ucChannelListNum, + prCmdScanReq->ucChannelListExtNum, + prCmdScanReq->u2ChannelDwellTime, + prCmdScanReq->u2ChannelMinDwellTime, + prCmdScanReq->auVersion[0]); + if (prCmdScanReq->ucSSIDNum || prCmdScanReq->ucSSIDExtNum) + scanReqSsidLog(prCmdScanReq, SCAN_LOG_MSG_MAX_LEN); + if (prCmdScanReq->ucChannelListNum || prCmdScanReq->ucChannelListExtNum) + scanReqChannelLog(prCmdScanReq, SCAN_LOG_MSG_MAX_LEN); +} + +void scanReqSsidLog(struct CMD_SCAN_REQ_V2 *prCmdScanReq, + const uint16_t logBufLen) +{ + char logBuf[logBufLen]; + uint32_t idx = 0; + int i = 0; + u_int8_t ext = FALSE; + uint8_t ssidNum = 0; + struct PARAM_SSID *ssid = NULL; + + while (1) { + if (ext == FALSE) { + ssidNum = prCmdScanReq->ucSSIDNum; + ssid = prCmdScanReq->arSSID; + } else { + ssidNum = prCmdScanReq->ucSSIDExtNum; + ssid = prCmdScanReq->arSSIDExtend; + } + for (i = 0; i < ssidNum; ++i) { + uint8_t len = (uint8_t) ssid[i].u4SsidLen; + + if (len == 0) { + continue; + } else if (len+1+1 > logBufLen) { + scanlog_dbg(LOG_SCAN_REQ_D2F, INFO, "Need more buffer: %u\n", + len+1+1); + break; + } else if (idx+len+1+1 > logBufLen) { + logBuf[idx] = 0; /* terminating null byte */ + if (ext == FALSE) { + scanlog_dbg(LOG_SCAN_REQ_D2F, INFO, "Ssid: %s\n", + logBuf); + } else { + scanlog_dbg(LOG_SCAN_REQ_D2F, INFO, "Ext Ssid: %s\n", + logBuf); + } + idx = 0; + } + + kalStrnCpy(logBuf+idx, ssid[i].aucSsid, len); + idx = idx + len; + + kalMemCopy(logBuf+idx, " ", 1); + idx = idx + 1; + } + if (idx != 0) { + logBuf[idx] = 0; /* terminating null byte */ + if (ext == FALSE) { + scanlog_dbg(LOG_SCAN_REQ_D2F, INFO, "Ssid: %s\n", + logBuf); + } else { + scanlog_dbg(LOG_SCAN_REQ_D2F, INFO, "Ext Ssid: %s\n", + logBuf); + } + idx = 0; + } + + if (ext == FALSE) + ext = TRUE; + else + break; + } +} + +void scanReqChannelLog(struct CMD_SCAN_REQ_V2 *prCmdScanReq, + const uint16_t logBufLen) +{ + char logBuf[logBufLen]; + uint32_t idx = 0; + uint32_t i = 0; + u_int8_t ext = FALSE; + uint8_t chNum = 0; + struct CHANNEL_INFO *ch = NULL; + /* the decimal value could 0 ~ 255 */ + const uint8_t dataLen = 4; + + while (1) { + if (ext == FALSE) { + chNum = prCmdScanReq->ucChannelListNum; + ch = prCmdScanReq->arChannelList; + } else { + chNum = prCmdScanReq->ucChannelListExtNum; + ch = prCmdScanReq->arChannelListExtend; + } + for (i = 0; i < chNum; ++i) { + if (dataLen+1 > logBufLen) { + scanlog_dbg(LOG_SCAN_REQ_D2F, INFO, "Need buffer size %u for log\n", + dataLen+1); + break; + } else if (idx+dataLen+1 > logBufLen) { + logBuf[idx] = 0; /* terminating null byte */ + if (ext == FALSE) { + scanlog_dbg(LOG_SCAN_REQ_D2F, INFO, "Ch: %s\n", + logBuf); + } else { + scanlog_dbg(LOG_SCAN_REQ_D2F, INFO, "Ext Ch: %s\n", + logBuf); + } + idx = 0; + } + + /* number + terminating null byte + a space */ + idx += kalSnprintf(logBuf+idx, dataLen+1, "%u ", + ch[i].ucChannelNum); + } + if (idx != 0) { + logBuf[idx] = 0; /* terminating null byte */ + if (ext == FALSE) { + scanlog_dbg(LOG_SCAN_REQ_D2F, INFO, "Ch: %s\n", + logBuf); + } else { + scanlog_dbg(LOG_SCAN_REQ_D2F, INFO, "Ext Ch: %s\n", + logBuf); + } + idx = 0; + } + if (ext == FALSE) + ext = TRUE; + else + break; + } +} + +void scanResultLog(struct ADAPTER *prAdapter, + struct SW_RFB *prSwRfb) +{ + struct WLAN_BEACON_FRAME *pFrame = + (struct WLAN_BEACON_FRAME *) prSwRfb->pvHeader; + + scanLogCacheAddBSS( + &(prAdapter->rWifiVar.rScanInfo.rScanLogCache.rBSSListFW), + prAdapter->rWifiVar.rScanInfo.rScanLogCache.arBSSListBufFW, + LOG_SCAN_RESULT_F2D, + pFrame->aucBSSID, + pFrame->u2SeqCtrl); +} + +void scanLogCacheAddBSS(struct LINK *prList, + struct SCAN_LOG_ELEM_BSS *prListBuf, + enum ENUM_SCAN_LOG_PREFIX prefix, + uint8_t bssId[], uint16_t seq) +{ + struct SCAN_LOG_ELEM_BSS *pSavedBss = NULL; + struct SCAN_LOG_ELEM_BSS *pBss = NULL; + + if (LINK_IS_INVALID(prList)) { + LINK_INITIALIZE(prList); + scanlog_dbg(prefix, INFO, "Init scan log cache\n"); + } + + LINK_FOR_EACH_ENTRY(pSavedBss, prList, + rLinkEntry, struct SCAN_LOG_ELEM_BSS) { + if (EQUAL_MAC_ADDR(pSavedBss->aucBSSID, bssId)) + return; + } + + if (prList->u4NumElem < SCAN_LOG_BUFF_SIZE) { + if (prListBuf != NULL) { + pBss = &(prListBuf[prList->u4NumElem]); + } else { + scanlog_dbg(prefix, INFO, "Buffer is NULL\n"); + return; + } + } else { +#if SCAN_LOG_DYN_ALLOC_MEM + pBss = kalMemAlloc(sizeof(struct SCAN_LOG_ELEM_BSS), + VIR_MEM_TYPE); + if (pBss == NULL) { + scanlog_dbg(prefix, INFO, "Cannot allocate memory for scan log\n"); + return; + } +#else + scanlog_dbg(prefix, INFO, "Need more buffer\n"); + return; +#endif + } + kalMemZero(pBss, sizeof(struct SCAN_LOG_ELEM_BSS)); + + COPY_MAC_ADDR(pBss->aucBSSID, bssId); + pBss->u2SeqCtrl = seq; + + LINK_INSERT_HEAD(prList, &(pBss->rLinkEntry)); +} + +void scanLogCacheFlushBSS(struct LINK *prList, enum ENUM_SCAN_LOG_PREFIX prefix, + const uint16_t logBufLen) +{ + char logBuf[logBufLen]; + uint32_t idx = 0; + struct SCAN_LOG_ELEM_BSS *pBss = NULL; +#if CFG_SHOW_FULL_MACADDR + /* XXXXXXXXXXXX */ + const uint8_t dataLen = 12; +#else + /* XXXXsumXX */ + const uint8_t dataLen = 9; +#endif + + if (LINK_IS_INVALID(prList)) { + LINK_INITIALIZE(prList); + scanlog_dbg(prefix, INFO, "Init scan log cache\n"); + } + + if (LINK_IS_EMPTY(prList)) + return; + + /* The maximum characters of uint32_t could be 10. Thus, the + * mininum size should be 10+3 for the format "%u: ". + */ + if (logBufLen < 13 || dataLen+1 > logBufLen) { + scanlog_dbg(prefix, INFO, "Scan log buffer is too small.\n"); + while (!LINK_IS_EMPTY(prList)) { + LINK_REMOVE_HEAD(prList, + pBss, struct SCAN_LOG_ELEM_BSS *); +#if SCAN_LOG_DYN_ALLOC_MEM + if (prList->u4NumElem >= SCAN_LOG_BUFF_SIZE) { + kalMemFree(pBss, VIR_MEM_TYPE, + sizeof(struct SCAN_LOG_ELEM_BSS)); + } +#endif + } + return; + } + idx += kalSnprintf(logBuf, sizeof(logBuf), "%u: ", prList->u4NumElem); + + while (!LINK_IS_EMPTY(prList)) { + if (idx+dataLen+1 > logBufLen) { + logBuf[idx] = 0; /* terminating null byte */ + scanlog_dbg(prefix, INFO, "%s\n", + logBuf); + idx = 0; + } + + LINK_REMOVE_HEAD(prList, + pBss, struct SCAN_LOG_ELEM_BSS *); + +#if CFG_SHOW_FULL_MACADDR + idx += kalSnprintf(logBuf+idx, dataLen+1, + "%02x%02x%02x%02x%02x%02x", + ((uint8_t *)pBss->aucBSSID)[0], + ((uint8_t *)pBss->aucBSSID)[1], + ((uint8_t *)pBss->aucBSSID)[2], + ((uint8_t *)pBss->aucBSSID)[3], + ((uint8_t *)pBss->aucBSSID)[4], + ((uint8_t *)pBss->aucBSSID)[5]); +#else + idx += kalSnprintf(logBuf+idx, dataLen+1, + "%02x%02x%03x%02x", + ((uint8_t *)pBss->aucBSSID)[0], + ((uint8_t *)pBss->aucBSSID)[1], + ((uint8_t *)pBss->aucBSSID)[2] + + ((uint8_t *)pBss->aucBSSID)[3] + + ((uint8_t *)pBss->aucBSSID)[4], + ((uint8_t *)pBss->aucBSSID)[5]); +#endif + +#if SCAN_LOG_DYN_ALLOC_MEM + if (prList->u4NumElem >= SCAN_LOG_BUFF_SIZE) { + kalMemFree(pBss, VIR_MEM_TYPE, + sizeof(struct SCAN_LOG_ELEM_BSS)); + } +#endif + } + if (idx != 0) { + logBuf[idx] = 0; /* terminating null byte */ + scanlog_dbg(prefix, INFO, "%s\n", + logBuf); + idx = 0; + } +} + +void scanLogCacheFlushAll(struct SCAN_LOG_CACHE *prScanLogCache, + enum ENUM_SCAN_LOG_PREFIX prefix, const uint16_t logBufLen) +{ + scanLogCacheFlushBSS(&(prScanLogCache->rBSSListFW), + prefix, logBufLen); + scanLogCacheFlushBSS(&(prScanLogCache->rBSSListCFG), + prefix, logBufLen); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/scan_cache.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/scan_cache.c new file mode 100644 index 0000000000000..95daea7b0aa7c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/scan_cache.c @@ -0,0 +1,234 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/******************************************************************************* + * C O M P I L E 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_SCAN_CACHE_RESULT +/******************************************************************************* + * 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 OS_SYSTIME getCurrentScanTime(void); + +static OS_SYSTIME getLastScanTime(struct GL_SCAN_CACHE_INFO *prScanCache); + +static void setLastScanTime(struct GL_SCAN_CACHE_INFO *prScanCache, + OS_SYSTIME rCurrentTime); + +static uint32_t getNumberOfScanChannels(struct GL_SCAN_CACHE_INFO *prScanCache); + +static u_int8_t isMediaConnected(struct GL_SCAN_CACHE_INFO *prScanCache); + +static u_int8_t isScanCacheChannels(struct GL_SCAN_CACHE_INFO *prScanCache); + +static u_int8_t isScanCacheTimeReady(struct GL_SCAN_CACHE_INFO *prScanCache); + +static u_int8_t isScanCacheTimeOverflow(struct GL_SCAN_CACHE_INFO *prScanCache, + OS_SYSTIME rCurrentTime); + +static u_int8_t doScanCache(struct GL_SCAN_CACHE_INFO *prScanCache); + +static void updateScanCacheLastScanTime(struct GL_SCAN_CACHE_INFO *prScanCache, + OS_SYSTIME rCurrentTime); + +static void resetScanCacheLastScanTime(struct GL_SCAN_CACHE_INFO *prScanCache); + +static u_int8_t inScanCachePeriod(struct GL_SCAN_CACHE_INFO *prScanCache, + OS_SYSTIME rCurrentTime); + +static u_int8_t matchScanCache(struct GL_SCAN_CACHE_INFO *prScanCache, + OS_SYSTIME rCurrentTime); + +static u_int8_t matchLastScanTimeUpdate(struct GL_SCAN_CACHE_INFO *prScanCache, + OS_SYSTIME rCurrentTime); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************* + */ +static OS_SYSTIME getCurrentScanTime(void) +{ + OS_SYSTIME rCurrentTime = 0; + + GET_CURRENT_SYSTIME(&rCurrentTime); + return rCurrentTime; +} + +static OS_SYSTIME getLastScanTime(struct GL_SCAN_CACHE_INFO *prScanCache) +{ + return prScanCache->u4LastScanTime; +} + +static void setLastScanTime(struct GL_SCAN_CACHE_INFO *prScanCache, + OS_SYSTIME rCurrentTime) +{ + prScanCache->u4LastScanTime = rCurrentTime; +} + +static uint32_t getNumberOfScanChannels(struct GL_SCAN_CACHE_INFO *prScanCache) +{ + return (uint32_t) prScanCache->n_channels; +} + +static u_int8_t isMediaConnected(struct GL_SCAN_CACHE_INFO *prScanCache) +{ + return PARAM_MEDIA_STATE_CONNECTED == + kalGetMediaStateIndicated(prScanCache->prGlueInfo); +} + +static u_int8_t isScanCacheChannels(struct GL_SCAN_CACHE_INFO *prScanCache) +{ + return getNumberOfScanChannels(prScanCache) >= + CFG_SCAN_CACHE_MIN_CHANNEL_NUM; +} + +static u_int8_t isScanCacheTimeReady(struct GL_SCAN_CACHE_INFO *prScanCache) +{ + return prScanCache->u4LastScanTime != 0; +} + +static u_int8_t isScanCacheTimeOverflow(struct GL_SCAN_CACHE_INFO *prScanCache, + OS_SYSTIME rCurrentTime) +{ + return getLastScanTime(prScanCache) > rCurrentTime; +} + +static u_int8_t doScanCache(struct GL_SCAN_CACHE_INFO *prScanCache) +{ + GLUE_SPIN_LOCK_DECLARATION(); + + kalUpdateBssTimestamp(prScanCache->prGlueInfo); + GLUE_ACQUIRE_SPIN_LOCK(prScanCache->prGlueInfo, SPIN_LOCK_NET_DEV); + kalCfg80211ScanDone(prScanCache->prRequest, FALSE); + GLUE_RELEASE_SPIN_LOCK(prScanCache->prGlueInfo, SPIN_LOCK_NET_DEV); + return TRUE; +} + +static void updateScanCacheLastScanTime(struct GL_SCAN_CACHE_INFO *prScanCache, + OS_SYSTIME rCurrentTime) +{ + setLastScanTime(prScanCache, rCurrentTime); +} + +static void resetScanCacheLastScanTime(struct GL_SCAN_CACHE_INFO *prScanCache) +{ + setLastScanTime(prScanCache, 0); +} + +static u_int8_t inScanCachePeriod(struct GL_SCAN_CACHE_INFO *prScanCache, + OS_SYSTIME rCurrentTime) +{ + if (isScanCacheTimeReady(prScanCache) == FALSE) + return FALSE; + + if (isScanCacheTimeOverflow(prScanCache, rCurrentTime) == TRUE) + return FALSE; + + if (CHECK_FOR_TIMEOUT(rCurrentTime, getLastScanTime(prScanCache), + CFG_SCAN_CACHE_RESULT_PERIOD) == FALSE) + return TRUE; + + return FALSE; +} + +static u_int8_t matchScanCache(struct GL_SCAN_CACHE_INFO *prScanCache, + OS_SYSTIME rCurrentTime) +{ + if (isMediaConnected(prScanCache) == TRUE && + inScanCachePeriod(prScanCache, rCurrentTime) == TRUE && + isScanCacheChannels(prScanCache) == TRUE) + return TRUE; + + return FALSE; +} + +static u_int8_t matchLastScanTimeUpdate(struct GL_SCAN_CACHE_INFO *prScanCache, + OS_SYSTIME rCurrentTime) +{ + if (isMediaConnected(prScanCache) == TRUE && + inScanCachePeriod(prScanCache, rCurrentTime) == FALSE && + isScanCacheChannels(prScanCache) == TRUE) + return TRUE; + + return FALSE; +} + +/* + * @brief This routine is responsible for checking scan cache + * + * @param prScanCache - pointer of struct GL_SCAN_CACHE_INFO + * + * @retval TRUE: do scan cache successful + * FALSE: didn't report scan cache + */ +u_int8_t isScanCacheDone(struct GL_SCAN_CACHE_INFO *prScanCache) +{ + OS_SYSTIME rCurrentTime = getCurrentScanTime(); + + if (matchScanCache(prScanCache, rCurrentTime) == TRUE) { + log_limited_dbg(REQ, INFO, "SCAN_CACHE: Skip scan too frequently(%u, %u). Call cfg80211_scan_done directly\n", + rCurrentTime, + getLastScanTime(prScanCache)); + + return doScanCache(prScanCache); + } + + if (matchLastScanTimeUpdate(prScanCache, rCurrentTime) == TRUE) { + log_dbg(REQ, INFO, "SCAN_CACHE: set scan cache time (%u)->(%u)\n", + getLastScanTime(prScanCache), + rCurrentTime); + + updateScanCacheLastScanTime(prScanCache, rCurrentTime); + } + + if (isMediaConnected(prScanCache) == FALSE) { + log_dbg(REQ, TRACE, "SCAN_CACHE: reset scan cache time (%u)->(0)\n", + getLastScanTime(prScanCache)); + + resetScanCacheLastScanTime(prScanCache); + } + return FALSE; +} +#endif /* CFG_SUPPORT_SCAN_CACHE_RESULT */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/scan_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/scan_fsm.c new file mode 100644 index 0000000000000..2a8310dd1c9ef --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/scan_fsm.c @@ -0,0 +1,1405 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/scan_fsm.c#2 + */ + +/*! \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. + */ + + +/******************************************************************************* + * C O M P I L E 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 + ******************************************************************************* + */ +uint8_t g_aucScanChannelNum[SCN_SCAN_DONE_PRINT_BUFFER_LENGTH]; +uint8_t g_aucScanChannelIdleTime[SCN_SCAN_DONE_PRINT_BUFFER_LENGTH]; +uint8_t g_aucScanChannelMDRDY[SCN_SCAN_DONE_PRINT_BUFFER_LENGTH]; +uint8_t g_aucScanChannelBeacon[SCN_SCAN_DONE_PRINT_BUFFER_LENGTH]; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +static uint8_t *apucDebugScanState[SCAN_STATE_NUM] = { + (uint8_t *) DISP_STRING("IDLE"), + (uint8_t *) DISP_STRING("SCANNING"), +}; + +/******************************************************************************* + * M A 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 struct ADAPTER *prAdapter, + IN enum ENUM_SCAN_STATE eNextState) +{ + struct SCAN_INFO *prScanInfo; + struct SCAN_PARAM *prScanParam; + struct MSG_HDR *prMsgHdr; + + u_int8_t fgIsTransition = (u_int8_t) FALSE; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + do { + log_dbg(SCN, STATE, "[SCAN]TRANSITION: [%s] -> [%s]\n", + apucDebugScanState[prScanInfo->eCurrentState], + apucDebugScanState[eNextState]); + + /* NOTE(Kevin): This is the only place to change the + * eCurrentState(except initial) + */ + prScanInfo->eCurrentState = eNextState; + + fgIsTransition = (u_int8_t) 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, struct MSG_HDR *); + +#define __MSG_ID__ prMsgHdr->eMsgId + if (__MSG_ID__ == MID_AIS_SCN_SCAN_REQ + || __MSG_ID__ == MID_BOW_SCN_SCAN_REQ + || __MSG_ID__ == MID_P2P_SCN_SCAN_REQ + || __MSG_ID__ == MID_RLM_SCN_SCAN_REQ) { + scnFsmHandleScanMsg(prAdapter, + (struct MSG_SCN_SCAN_REQ *) + prMsgHdr); + + eNextState = SCAN_STATE_SCANNING; + fgIsTransition = TRUE; + } else if (__MSG_ID__ == MID_AIS_SCN_SCAN_REQ_V2 + || __MSG_ID__ == MID_BOW_SCN_SCAN_REQ_V2 + || __MSG_ID__ == MID_P2P_SCN_SCAN_REQ_V2 + || __MSG_ID__ == MID_RLM_SCN_SCAN_REQ_V2 + ) { + scnFsmHandleScanMsgV2(prAdapter, + (struct MSG_SCN_SCAN_REQ_V2 *) + prMsgHdr); + + eNextState = SCAN_STATE_SCANNING; + fgIsTransition = TRUE; + } else { + /* should not happen */ + ASSERT(0); + } +#undef __MSG_ID__ + + /* switch to next state */ + cnmMemFree(prAdapter, prMsgHdr); + } + break; + + case SCAN_STATE_SCANNING: + /* Support AP Selection */ + prScanInfo->u4ScanUpdateIdx++; + if (prScanParam->fgIsScanV2 == FALSE) + scnSendScanReq(prAdapter); + else + scnSendScanReqV2(prAdapter); + break; + + default: + ASSERT(0); + break; + + } + } while (fgIsTransition); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Generate CMD_ID_SCAN_REQ command + * + * Because CMD_ID_SCAN_REQ is deprecated, + * wrap this command to CMD_ID_SCAN_REQ_V2 + * + * \param[in] prAdapter adapter + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void scnSendScanReq(IN struct ADAPTER *prAdapter) +{ + log_dbg(SCN, WARN, + "CMD_ID_SCAN_REQ is deprecated, use CMD_ID_SCAN_REQ_V2\n"); + scnSendScanReqV2(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Generate CMD_ID_SCAN_REQ_V2 command + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void scnSendScanReqV2(IN struct ADAPTER *prAdapter) +{ + struct SCAN_INFO *prScanInfo; + struct SCAN_PARAM *prScanParam; + /* CMD_SCAN_REQ_V2 rCmdScanReq; */ + struct CMD_SCAN_REQ_V2 *prCmdScanReq; + uint32_t i; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &(prScanInfo->rScanParam); + + prCmdScanReq = kalMemAlloc( + sizeof(struct CMD_SCAN_REQ_V2), VIR_MEM_TYPE); + if (!prCmdScanReq) { + log_dbg(SCN, ERROR, "alloc CmdScanReq V2 fail\n"); + return; + } + /* send command packet for scan */ + kalMemZero(prCmdScanReq, sizeof(struct CMD_SCAN_REQ_V2)); + /* Modify channelList number from 32 to 54 */ + COPY_MAC_ADDR(prCmdScanReq->aucBSSID, prScanParam->aucBSSID); + if (!EQUAL_MAC_ADDR(prCmdScanReq->aucBSSID, "\xff\xff\xff\xff\xff\xff")) + DBGLOG(SCN, INFO, "Include BSSID %pM in probe request\n", + prCmdScanReq->aucBSSID); + + prCmdScanReq->ucSeqNum = prScanParam->ucSeqNum; + prCmdScanReq->ucBssIndex = prScanParam->ucBssIndex; + prCmdScanReq->ucScanType = (uint8_t) prScanParam->eScanType; + prCmdScanReq->ucSSIDType = prScanParam->ucSSIDType; + prCmdScanReq->auVersion[0] = 1; + prCmdScanReq->ucScnFuncMask |= prScanParam->ucScnFuncMask; + if (kalIsValidMacAddr(prScanParam->aucRandomMac)) { + prCmdScanReq->ucScnFuncMask |= ENUM_SCN_RANDOM_MAC_EN; + kalMemCopy(prCmdScanReq->aucRandomMac, + prScanParam->aucRandomMac, MAC_ADDR_LEN); + } + + /* Set SSID to scan request */ + if (prScanParam->ucSSIDNum <= SCAN_CMD_SSID_NUM) { + prCmdScanReq->ucSSIDNum = prScanParam->ucSSIDNum; + prCmdScanReq->ucSSIDExtNum = 0; + } else if (prScanParam->ucSSIDNum <= CFG_SCAN_SSID_MAX_NUM) { + prCmdScanReq->ucSSIDNum = SCAN_CMD_SSID_NUM; + prCmdScanReq->ucSSIDExtNum = prScanParam->ucSSIDNum + - SCAN_CMD_SSID_NUM; + } else { + log_dbg(SCN, WARN, "Too many SSID %u\n", + prScanParam->ucSSIDNum); + prCmdScanReq->ucSSIDNum = SCAN_CMD_SSID_NUM; + prCmdScanReq->ucSSIDExtNum = SCAN_CMD_EXT_SSID_NUM; + } + + for (i = 0; i < prCmdScanReq->ucSSIDNum; i++) { + COPY_SSID(prCmdScanReq->arSSID[i].aucSsid, + prCmdScanReq->arSSID[i].u4SsidLen, + prScanParam->aucSpecifiedSSID[i], + prScanParam->ucSpecifiedSSIDLen[i]); + log_dbg(SCN, TRACE, + "Ssid=%s, SsidLen=%d\n", + prCmdScanReq->arSSID[i].aucSsid, + prCmdScanReq->arSSID[i].u4SsidLen); + } + for (i = 0; i < prCmdScanReq->ucSSIDExtNum; i++) { + COPY_SSID(prCmdScanReq->arSSIDExtend[i].aucSsid, + prCmdScanReq->arSSIDExtend[i].u4SsidLen, + prScanParam->aucSpecifiedSSID + [prCmdScanReq->ucSSIDNum+i], + prScanParam->ucSpecifiedSSIDLen + [prCmdScanReq->ucSSIDNum+i]); + log_dbg(SCN, TRACE, + "Ssid=%s, SsidLen=%d\n", + prCmdScanReq->arSSIDExtend[i].aucSsid, + prCmdScanReq->arSSIDExtend[i].u4SsidLen); + } + + prCmdScanReq->u2ProbeDelayTime + = (uint8_t) prScanParam->u2ProbeDelayTime; + prCmdScanReq->ucChannelType + = (uint8_t) prScanParam->eScanChannel; + + /* Set channel info to scan request */ + if (prScanParam->eScanChannel == SCAN_CHANNEL_SPECIFIED) { + if (prScanParam->ucChannelListNum <= SCAN_CMD_CHNL_NUM) { + prCmdScanReq->ucChannelListNum = + prScanParam->ucChannelListNum; + prCmdScanReq->ucChannelListExtNum = 0; + } else if (prScanParam->ucChannelListNum <= + MAXIMUM_OPERATION_CHANNEL_LIST) { + prCmdScanReq->ucChannelListNum = + SCAN_CMD_CHNL_NUM; + prCmdScanReq->ucChannelListExtNum = + prScanParam->ucChannelListNum - + SCAN_CMD_CHNL_NUM; + } else { + log_dbg(SCN, WARN, "Too many Channel %u\n", + prScanParam->ucChannelListNum); + prCmdScanReq->ucChannelListNum = 0; + prCmdScanReq->ucChannelListExtNum = 0; + prCmdScanReq->ucChannelType = SCAN_CHANNEL_FULL; + } + + for (i = 0; i < prCmdScanReq->ucChannelListNum; i++) { + prCmdScanReq->arChannelList[i].ucBand + = (uint8_t) prScanParam->arChnlInfoList[i] + .eBand; + + prCmdScanReq->arChannelList[i].ucChannelNum + = (uint8_t) prScanParam->arChnlInfoList[i] + .ucChannelNum; + } + for (i = 0; i < prCmdScanReq->ucChannelListExtNum; i++) { + prCmdScanReq->arChannelListExtend[i].ucBand + = (uint8_t)prScanParam + ->arChnlInfoList + [prCmdScanReq->ucChannelListNum+i] + .eBand; + + prCmdScanReq->arChannelListExtend[i].ucChannelNum + = (uint8_t) prScanParam + ->arChnlInfoList + [prCmdScanReq->ucChannelListNum+i] + .ucChannelNum; + } + } + + prCmdScanReq->u2ChannelDwellTime = prScanParam->u2ChannelDwellTime; + prCmdScanReq->u2ChannelMinDwellTime = + prScanParam->u2ChannelMinDwellTime; + prCmdScanReq->u2TimeoutValue = prScanParam->u2TimeoutValue; + + if (prScanParam->u2IELen <= MAX_IE_LENGTH) + prCmdScanReq->u2IELen = prScanParam->u2IELen; + else + prCmdScanReq->u2IELen = MAX_IE_LENGTH; + + if (prScanParam->u2IELen) + kalMemCopy(prCmdScanReq->aucIE, prScanParam->aucIE, + sizeof(uint8_t) * prCmdScanReq->u2IELen); + + log_dbg(SCN, INFO, "ScanReqV2: ScanType=%d,SSIDType=%d,Num=%u,Ext=%u,ChannelType=%d,Num=%d,Ext=%u,Seq=%u,Ver=%u,Dw=%u,Min=%u,Func=0x%X,Mac=" + MACSTR "\n", + prCmdScanReq->ucScanType, + prCmdScanReq->ucSSIDType, + prCmdScanReq->ucSSIDNum, + prCmdScanReq->ucSSIDExtNum, + prCmdScanReq->ucChannelType, + prCmdScanReq->ucChannelListNum, + prCmdScanReq->ucChannelListExtNum, + prCmdScanReq->ucSeqNum, prCmdScanReq->auVersion[0], + prCmdScanReq->u2ChannelDwellTime, + prCmdScanReq->u2ChannelMinDwellTime, + prCmdScanReq->ucScnFuncMask, + prCmdScanReq->aucRandomMac); + + scanLogCacheFlushAll(&(prScanInfo->rScanLogCache), + LOG_SCAN_REQ_D2F, SCAN_LOG_MSG_MAX_LEN); + scanReqLog(prCmdScanReq); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SCAN_REQ_V2, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_SCAN_REQ_V2), + (uint8_t *)prCmdScanReq, NULL, 0); + log_dbg(SCN, TRACE, "Send %zu bytes\n", sizeof(struct CMD_SCAN_REQ_V2)); + + + kalMemFree(prCmdScanReq, VIR_MEM_TYPE, sizeof(struct CMD_SCAN_REQ_V2)); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void scnFsmMsgStart(IN struct ADAPTER *prAdapter, IN struct MSG_HDR *prMsgHdr) +{ + struct SCAN_INFO *prScanInfo; + struct SCAN_PARAM *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, + (struct 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, + (struct MSG_SCN_SCAN_REQ_V2 *) prMsgHdr); + } else { + /* should not deliver to this function */ + ASSERT(0); + } + + cnmMemFree(prAdapter, prMsgHdr); + scnFsmSteps(prAdapter, SCAN_STATE_SCANNING); + } else { + LINK_INSERT_TAIL(&prScanInfo->rPendingMsgList, + &prMsgHdr->rLinkEntry); + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void scnFsmMsgAbort(IN struct ADAPTER *prAdapter, IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_SCN_SCAN_CANCEL *prScanCancel; + struct SCAN_INFO *prScanInfo; + struct SCAN_PARAM *prScanParam; + struct CMD_SCAN_CANCEL rCmdScanCancel; + + ASSERT(prMsgHdr); + + prScanCancel = (struct MSG_SCN_SCAN_CANCEL *) prMsgHdr; + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + if (prScanInfo->eCurrentState != SCAN_STATE_IDLE) { + if (prScanCancel->ucSeqNum == prScanParam->ucSeqNum && + prScanCancel->ucBssIndex == prScanParam->ucBssIndex) { + enum ENUM_SCAN_STATUS eStatus = SCAN_STATUS_DONE; + + /* send cancel message to firmware domain */ + rCmdScanCancel.ucSeqNum = prScanParam->ucSeqNum; + rCmdScanCancel.ucIsExtChannel + = (uint8_t) prScanCancel->fgIsChannelExt; + + scanlog_dbg(LOG_SCAN_ABORT_REQ_D2F, INFO, "Scan Abort#%u to Q: isExtCh=%u", + rCmdScanCancel.ucSeqNum, + rCmdScanCancel.ucIsExtChannel); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SCAN_CANCEL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_SCAN_CANCEL), + (uint8_t *) &rCmdScanCancel, + NULL, + 0); + + /* Full2Partial: ignore this statistics */ + if (prScanInfo->fgIsScanForFull2Partial) { + prScanInfo->fgIsScanForFull2Partial = FALSE; + prScanInfo->u4LastFullScanTime = 0; + log_dbg(SCN, INFO, + "Full2Partial: scan canceled(%u)\n", + prScanParam->ucSeqNum); + } + + /* generate scan-done event for caller */ + if (prScanCancel->fgIsOidRequest) + eStatus = SCAN_STATUS_CANCELLED; + else + eStatus = SCAN_STATUS_DONE; + scnFsmGenerateScanDoneMsg(prAdapter, + prScanParam->ucSeqNum, + prScanParam->ucBssIndex, + eStatus); + + /* switch to next pending scan */ + scnFsmSteps(prAdapter, SCAN_STATE_IDLE); + } else { + scnFsmRemovePendingMsg(prAdapter, + prScanCancel->ucSeqNum, + prScanCancel->ucBssIndex); + } + } + + cnmMemFree(prAdapter, prMsgHdr); +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Scan Message Parsing (Legacy) + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void scnFsmHandleScanMsg(IN struct ADAPTER *prAdapter, + IN struct MSG_SCN_SCAN_REQ *prScanReqMsg) +{ + struct SCAN_INFO *prScanInfo; + struct SCAN_PARAM *prScanParam; + uint32_t i; + + ASSERT(prAdapter); + ASSERT(prScanReqMsg); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + kalMemZero(prScanParam, sizeof(*prScanParam)); + prScanParam->eScanType = prScanReqMsg->eScanType; + prScanParam->ucBssIndex = prScanReqMsg->ucBssIndex; + 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(struct RF_CHANNEL_INFO) + * 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); + } + + prScanParam->u2ChannelDwellTime = prScanReqMsg->u2ChannelDwellTime; + prScanParam->u2TimeoutValue = prScanReqMsg->u2TimeoutValue; + prScanParam->ucSeqNum = prScanReqMsg->ucSeqNum; + + if (prScanReqMsg->rMsgHdr.eMsgId == MID_RLM_SCN_SCAN_REQ) + prScanParam->fgIsObssScan = TRUE; + else + prScanParam->fgIsObssScan = FALSE; + + prScanParam->fgIsScanV2 = FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Scan Message Parsing - V2 with multiple SSID support + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void scnFsmHandleScanMsgV2(IN struct ADAPTER *prAdapter, + IN struct MSG_SCN_SCAN_REQ_V2 *prScanReqMsg) +{ + struct SCAN_INFO *prScanInfo; + struct SCAN_PARAM *prScanParam; + uint32_t i; + + ASSERT(prAdapter); + ASSERT(prScanReqMsg); + ASSERT(prScanReqMsg->ucSSIDNum <= SCN_SSID_MAX_NUM); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + kalMemZero(prScanParam, sizeof(*prScanParam)); + prScanParam->eScanType = prScanReqMsg->eScanType; + prScanParam->ucBssIndex = prScanReqMsg->ucBssIndex; + prScanParam->ucSSIDType = prScanReqMsg->ucSSIDType; + prScanParam->ucSSIDNum = prScanReqMsg->ucSSIDNum; + prScanParam->ucScnFuncMask |= prScanReqMsg->ucScnFuncMask; + kalMemCopy(prScanParam->aucRandomMac, prScanReqMsg->aucRandomMac, + MAC_ADDR_LEN); + + if (prScanParam->ucSSIDType & SCAN_REQ_SSID_SPECIFIED_ONLY) { + prScanParam->ucSSIDNum = 1; + kalMemZero(prScanParam->ucSpecifiedSSIDLen, + sizeof(prScanParam->ucSpecifiedSSIDLen)); + COPY_SSID(prScanParam->aucSpecifiedSSID[0], + prScanParam->ucSpecifiedSSIDLen[0], + &prScanReqMsg->prSsid[0].aucSsid[0], + prScanReqMsg->prSsid[0].u4SsidLen); + } else { + for (i = 0; i < prScanReqMsg->ucSSIDNum; i++) { + COPY_SSID(prScanParam->aucSpecifiedSSID[i], + prScanParam->ucSpecifiedSSIDLen[i], + prScanReqMsg->prSsid[i].aucSsid, + (uint8_t) 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(struct RF_CHANNEL_INFO) + * 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); + } + + prScanParam->u2ChannelDwellTime = prScanReqMsg->u2ChannelDwellTime; + prScanParam->u2ChannelMinDwellTime = + prScanReqMsg->u2ChannelMinDwellTime; + prScanParam->u2TimeoutValue = prScanReqMsg->u2TimeoutValue; + prScanParam->ucSeqNum = prScanReqMsg->ucSeqNum; + + if (prScanReqMsg->rMsgHdr.eMsgId == MID_RLM_SCN_SCAN_REQ_V2) + prScanParam->fgIsObssScan = TRUE; + else + prScanParam->fgIsObssScan = FALSE; + + prScanParam->fgIsScanV2 = TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Remove pending scan request + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void scnFsmRemovePendingMsg(IN struct ADAPTER *prAdapter, IN uint8_t ucSeqNum, + IN uint8_t ucBssIndex) +{ + struct SCAN_INFO *prScanInfo; + struct SCAN_PARAM *prScanParam; + struct MSG_HDR *prPendingMsgHdr = NULL; + struct MSG_HDR *prPendingMsgHdrNext = NULL; + struct MSG_HDR *prRemoveMsgHdr = NULL; + struct LINK_ENTRY *prRemoveLinkEntry = NULL; + u_int8_t fgIsRemovingScan = FALSE; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + /* traverse through rPendingMsgList for removal */ + LINK_FOR_EACH_ENTRY_SAFE(prPendingMsgHdr, + prPendingMsgHdrNext, &(prScanInfo->rPendingMsgList), + rLinkEntry, struct MSG_HDR) { + +#define __MSG_ID__ prPendingMsgHdr->eMsgId + if (__MSG_ID__ == MID_AIS_SCN_SCAN_REQ + || __MSG_ID__ == MID_BOW_SCN_SCAN_REQ + || __MSG_ID__ == MID_P2P_SCN_SCAN_REQ + || __MSG_ID__ == MID_RLM_SCN_SCAN_REQ) { + struct MSG_SCN_SCAN_REQ *prScanReqMsg + = (struct MSG_SCN_SCAN_REQ *) + prPendingMsgHdr; + + if (ucSeqNum == prScanReqMsg->ucSeqNum + && ucBssIndex == prScanReqMsg->ucBssIndex) { + prRemoveLinkEntry + = &(prScanReqMsg->rMsgHdr.rLinkEntry); + prRemoveMsgHdr = prPendingMsgHdr; + fgIsRemovingScan = TRUE; + } + } else if (__MSG_ID__ == MID_AIS_SCN_SCAN_REQ_V2 + || __MSG_ID__ == MID_BOW_SCN_SCAN_REQ_V2 + || __MSG_ID__ == MID_P2P_SCN_SCAN_REQ_V2 + || __MSG_ID__ == MID_RLM_SCN_SCAN_REQ_V2) { + struct MSG_SCN_SCAN_REQ_V2 *prScanReqMsgV2 + = (struct MSG_SCN_SCAN_REQ_V2 *) + prPendingMsgHdr; + + if (ucSeqNum == prScanReqMsgV2->ucSeqNum + && ucBssIndex == prScanReqMsgV2->ucBssIndex) { + prRemoveLinkEntry + = &(prScanReqMsgV2->rMsgHdr.rLinkEntry); + prRemoveMsgHdr = prPendingMsgHdr; + fgIsRemovingScan = TRUE; + } + } +#undef __MSG_ID__ + + if (prRemoveLinkEntry) { + if (fgIsRemovingScan == TRUE) { + /* generate scan-done event for caller */ + scnFsmGenerateScanDoneMsg(prAdapter, ucSeqNum, + ucBssIndex, SCAN_STATUS_CANCELLED); + } + + /* remove from pending list */ + LINK_REMOVE_KNOWN_ENTRY(&(prScanInfo->rPendingMsgList), + prRemoveLinkEntry); + cnmMemFree(prAdapter, prRemoveMsgHdr); + + break; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void scnEventScanDone(IN struct ADAPTER *prAdapter, + IN struct EVENT_SCAN_DONE *prScanDone, u_int8_t fgIsNewVersion) +{ + struct SCAN_INFO *prScanInfo; + struct SCAN_PARAM *prScanParam; + uint32_t u4ChCnt; + uint32_t u4PrintfIdx = 0; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + +#define __LOCAL_VAR__ SCN_SCAN_DONE_PRINT_BUFFER_LENGTH + kalMemZero(g_aucScanChannelNum, __LOCAL_VAR__); + kalMemZero(g_aucScanChannelIdleTime, __LOCAL_VAR__); + kalMemZero(g_aucScanChannelMDRDY, __LOCAL_VAR__); + kalMemZero(g_aucScanChannelBeacon, __LOCAL_VAR__); +#undef __LOCAL_VAR__ + + if (fgIsNewVersion) { + scanlog_dbg(LOG_SCAN_DONE_F2D, INFO, "scnEventScanDone Version%u!size of ScanDone%zu,ucCompleteChanCount[%u],ucCurrentState%u, u4ScanDurBcnCnt[%u],Seq[%u]\n", + prScanDone->ucScanDoneVersion, + sizeof(struct EVENT_SCAN_DONE), + prScanDone->ucCompleteChanCount, + prScanDone->ucCurrentState, + prScanDone->u4ScanDurBcnCnt, + prScanDone->ucSeqNum); + + scanLogCacheFlushBSS(&(prScanInfo->rScanLogCache.rBSSListFW), + LOG_SCAN_DONE_F2D, SCAN_LOG_MSG_MAX_LEN); + + if (prScanDone->ucCurrentState != FW_SCAN_STATE_SCAN_DONE) { + log_dbg(SCN, INFO, "FW Scan timeout!generate ScanDone event at State%d complete chan count%d ucChannelListNum%d\n", + prScanDone->ucCurrentState, + prScanDone->ucCompleteChanCount, + prScanParam->ucChannelListNum); + + } else { + log_dbg(SCN, TRACE, " scnEventScanDone at FW_SCAN_STATE_SCAN_DONE state\n"); + } + } else { + scanlog_dbg(LOG_SCAN_DONE_F2D, INFO, "Old scnEventScanDone Version\n"); + } + + /* buffer empty channel information */ + if (prScanDone->ucSparseChannelValid) { + prScanInfo->fgIsSparseChannelValid = TRUE; + prScanInfo->rSparseChannel.eBand + = (enum ENUM_BAND) prScanDone->rSparseChannel.ucBand; + prScanInfo->rSparseChannel.ucChannelNum + = prScanDone->rSparseChannel.ucChannelNum; + prScanInfo->ucSparseChannelArrayValidNum + = prScanDone->ucSparseChannelArrayValidNum; + log_dbg(SCN, INFO, "Country Code = %c%c, Detected_Channel_Num = %d\n", + ((prAdapter->rWifiVar.rConnSettings + .u2CountryCode & 0xff00) >> 8), + (prAdapter->rWifiVar.rConnSettings + .u2CountryCode & 0x00ff), + prScanInfo->ucSparseChannelArrayValidNum); + + if (prScanInfo->ucSparseChannelArrayValidNum > + EVENT_SCAN_DONE_CHANNEL_NUM_MAX) { + DBGLOG(SCN, ERROR, + "%s ucSparseChannelArrayValidNum out of bound: %u\n", + __func__, + prScanInfo->ucSparseChannelArrayValidNum); + return; + } + + for (u4ChCnt = 0; u4ChCnt < prScanInfo + ->ucSparseChannelArrayValidNum; u4ChCnt++) { + prScanInfo->aucChannelNum[u4ChCnt] + = prScanDone->aucChannelNum[u4ChCnt]; + prScanInfo->au2ChannelIdleTime[u4ChCnt] + = prScanDone->au2ChannelIdleTime[u4ChCnt]; + prScanInfo->aucChannelMDRDYCnt[u4ChCnt] + = prScanDone->aucChannelMDRDYCnt[u4ChCnt]; + prScanInfo->aucChannelBAndPCnt[u4ChCnt] + = prScanDone->aucChannelBAndPCnt[u4ChCnt]; + + if (u4PrintfIdx % 10 == 0 && u4PrintfIdx != 0) { + log_fw_dbg(SCN, INFO, "Channel : %s\n", + g_aucScanChannelNum); + log_fw_dbg(SCN, LOUD, "IdleTime : %s\n", + g_aucScanChannelIdleTime); + log_fw_dbg(SCN, LOUD, "MdrdyCnt : %s\n", + g_aucScanChannelMDRDY); + log_fw_dbg(SCN, INFO, "BAndPCnt : %s\n", + g_aucScanChannelBeacon); + log_fw_dbg(SCN, INFO, "==================================================================================\n"); + +#define __LOCAL_VAR__ SCN_SCAN_DONE_PRINT_BUFFER_LENGTH + kalMemZero(g_aucScanChannelNum, __LOCAL_VAR__); + kalMemZero(g_aucScanChannelIdleTime, + __LOCAL_VAR__); + kalMemZero(g_aucScanChannelMDRDY, + __LOCAL_VAR__); + kalMemZero(g_aucScanChannelBeacon, + __LOCAL_VAR__); +#undef __LOCAL_VAR__ + u4PrintfIdx = 0; + } + kalSnprintf(g_aucScanChannelNum + u4PrintfIdx*7, + sizeof(g_aucScanChannelNum) - u4PrintfIdx*7, + "%7d", prScanInfo->aucChannelNum[u4ChCnt]); + kalSnprintf(g_aucScanChannelIdleTime + u4PrintfIdx*7, + sizeof(g_aucScanChannelIdleTime) - + u4PrintfIdx*7, "%7d", + prScanInfo->au2ChannelIdleTime[u4ChCnt]); + kalSnprintf(g_aucScanChannelMDRDY + u4PrintfIdx*7, + sizeof(g_aucScanChannelMDRDY) - u4PrintfIdx*7, + "%7d", + prScanInfo->aucChannelMDRDYCnt[u4ChCnt]); + kalSnprintf(g_aucScanChannelBeacon + u4PrintfIdx*7, + sizeof(g_aucScanChannelBeacon) - u4PrintfIdx*7, + "%7d", + prScanInfo->aucChannelBAndPCnt[u4ChCnt]); + u4PrintfIdx++; + } + + log_fw_dbg(SCN, INFO, "Channel : %s\n", + g_aucScanChannelNum); + log_fw_dbg(SCN, LOUD, "IdleTime : %s\n", + g_aucScanChannelIdleTime); + log_fw_dbg(SCN, LOUD, "MdrdyCnt : %s\n", + g_aucScanChannelMDRDY); + log_fw_dbg(SCN, INFO, "BAndPCnt : %s\n", + g_aucScanChannelBeacon); + } else { + prScanInfo->fgIsSparseChannelValid = FALSE; + } + + /* Full2Partial */ + if (prScanInfo->fgIsScanForFull2Partial && + prScanInfo->ucFull2PartialSeq == prScanDone->ucSeqNum) { + uint32_t *pu4BitMap = &(prScanInfo->au4ChannelBitMap[0]); + + log_dbg(SCN, INFO, + "Full2Partial(%u):%08X %08X %08X %08X %08X %08X %08X %08X\n", + scanCountBits(prScanInfo->au4ChannelBitMap, + sizeof(prScanInfo->au4ChannelBitMap)), + pu4BitMap[7], pu4BitMap[6], pu4BitMap[5], pu4BitMap[4], + pu4BitMap[3], pu4BitMap[2], pu4BitMap[1], pu4BitMap[0]); + + prScanInfo->fgIsScanForFull2Partial = FALSE; + } + + if (prScanInfo->eCurrentState == SCAN_STATE_SCANNING + && prScanDone->ucSeqNum == prScanParam->ucSeqNum) { + /* generate scan-done event for caller */ + scnFsmGenerateScanDoneMsg(prAdapter, prScanParam->ucSeqNum, + prScanParam->ucBssIndex, SCAN_STATUS_DONE); + + /* switch to next pending scan */ + scnFsmSteps(prAdapter, SCAN_STATE_IDLE); + } else { + log_dbg(SCN, INFO, "Unexpected SCAN-DONE event: SeqNum = %d, Current State = %d\n", + prScanDone->ucSeqNum, + prScanInfo->eCurrentState); + } +} /* end of scnEventScanDone */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void +scnFsmGenerateScanDoneMsg(IN struct ADAPTER *prAdapter, + IN uint8_t ucSeqNum, IN uint8_t ucBssIndex, + IN enum ENUM_SCAN_STATUS eScanStatus) +{ + struct SCAN_INFO *prScanInfo; + struct SCAN_PARAM *prScanParam; + struct MSG_SCN_SCAN_DONE *prScanDoneMsg; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + prScanDoneMsg = (struct MSG_SCN_SCAN_DONE *) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(struct 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 (GET_BSS_INFO_BY_INDEX( + prAdapter, ucBssIndex)->eNetworkType) { + case NETWORK_TYPE_AIS: + prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_AIS_SCAN_DONE; + break; + + case NETWORK_TYPE_P2P: + prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_P2P_SCAN_DONE; + break; + + case NETWORK_TYPE_BOW: + prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_BOW_SCAN_DONE; + break; + + default: + log_dbg(SCN, LOUD, + "Unexpected Network Type: %d\n", + GET_BSS_INFO_BY_INDEX( + prAdapter, ucBssIndex)->eNetworkType); + ASSERT(0); + break; + } + } + + prScanDoneMsg->ucSeqNum = ucSeqNum; + prScanDoneMsg->ucBssIndex = ucBssIndex; + prScanDoneMsg->eScanStatus = eScanStatus; + + mboxSendMsg(prAdapter, MBOX_ID_0, + (struct MSG_HDR *) prScanDoneMsg, MSG_SEND_METHOD_BUF); + +} /* end of scnFsmGenerateScanDoneMsg() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Query for most sparse channel + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +u_int8_t scnQuerySparseChannel(IN struct ADAPTER *prAdapter, + enum ENUM_BAND *prSparseBand, uint8_t *pucSparseChannel) +{ + struct SCAN_INFO *prScanInfo; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + if (prScanInfo->fgIsSparseChannelValid == TRUE) { + if (prSparseBand) + *prSparseBand = prScanInfo->rSparseChannel.eBand; + + if (pucSparseChannel) { + *pucSparseChannel + = prScanInfo->rSparseChannel.ucChannelNum; + } + + return TRUE; + } else { + return FALSE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Event handler for schedule scan done event + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +void scnEventSchedScanDone(IN struct ADAPTER *prAdapter, + IN struct EVENT_SCHED_SCAN_DONE *prSchedScanDone) +{ + struct SCAN_INFO *prScanInfo; + struct SCHED_SCAN_PARAM *prSchedScanParam; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prSchedScanParam = &prScanInfo->rSchedScanParam; + + if (prScanInfo->fgSchedScanning == TRUE) { + + scanlog_dbg(LOG_SCHED_SCAN_DONE_F2D, INFO, "scnEventSchedScanDone seq %u\n", + prSchedScanDone->ucSeqNum); + + kalSchedScanResults(prAdapter->prGlueInfo); + + if (prSchedScanParam->fgStopAfterIndication == TRUE) { +#if CFG_SUPPORT_PNO + prAdapter->prAisBssInfo->fgIsPNOEnable = FALSE; +#endif + prScanInfo->fgSchedScanning = FALSE; + } + } else { + scanlog_dbg(LOG_SCHED_SCAN_DONE_F2D, INFO, "Unexpected SCHEDSCANDONE event: Seq = %u, Current State = %d\n", + prSchedScanDone->ucSeqNum, prScanInfo->eCurrentState); + } +} + +#if CFG_SUPPORT_SCHED_SCAN +/*----------------------------------------------------------------------------*/ +/*! + * \brief handler for starting schedule scan + * + * \param[in] + * + * \return TRUE if send sched scan successfully. FALSE otherwise + */ +/*----------------------------------------------------------------------------*/ +u_int8_t +scnFsmSchedScanRequest(IN struct ADAPTER *prAdapter, + IN struct PARAM_SCHED_SCAN_REQUEST *prRequest) +{ + struct SCAN_INFO *prScanInfo; + struct SCHED_SCAN_PARAM *prSchedScanParam; + struct CMD_SCHED_SCAN_REQ *prSchedScanCmd = NULL; + struct SSID_MATCH_SETS *prMatchSets = NULL; + struct PARAM_SSID *prSsid = NULL; + uint32_t i; + uint16_t u2IeLen; + enum ENUM_BAND ePreferedChnl = BAND_NULL; + u_int8_t fgRet = TRUE; + + ASSERT(prAdapter); + ASSERT(prRequest); + ASSERT(prRequest->u4SsidNum <= CFG_SCAN_HIDDEN_SSID_MAX_NUM); + ASSERT(prRequest->u4MatchSsidNum <= CFG_SCAN_SSID_MATCH_MAX_NUM); + log_dbg(SCN, TRACE, "scnFsmSchedScanRequest\n"); + + if (prAdapter->prAisBssInfo == NULL) { + log_dbg(SCN, WARN, "prAisBssInfo is NULL\n"); + return FALSE; + } + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prSchedScanParam = &prScanInfo->rSchedScanParam; + + if (prScanInfo->fgSchedScanning) { + log_dbg(SCN, WARN, "prScanInfo->fgSchedScanning = TRUE already scanning\n"); + + return FALSE; + } + + /* 0. allocate memory for schedule scan command */ + if (prRequest->u4IELength <= MAX_IE_LENGTH) + u2IeLen = (uint16_t)prRequest->u4IELength; + else + u2IeLen = MAX_IE_LENGTH; + + prSchedScanCmd = (struct CMD_SCHED_SCAN_REQ *) cnmMemAlloc(prAdapter, + RAM_TYPE_BUF, sizeof(struct CMD_SCHED_SCAN_REQ) + u2IeLen); + if (!prSchedScanCmd) { + log_dbg(SCN, ERROR, "alloc CMD_SCHED_SCAN_REQ (%zu+%u) fail\n", + sizeof(struct CMD_SCHED_SCAN_REQ), u2IeLen); + return FALSE; + } + kalMemZero(prSchedScanCmd, sizeof(struct CMD_SCHED_SCAN_REQ) + u2IeLen); + prMatchSets = &(prSchedScanCmd->auMatchSsid[0]); + prSsid = &(prSchedScanCmd->auSsid[0]); + + /* 1 Set Sched scan param parameters */ + prSchedScanParam->ucSeqNum++; + prSchedScanParam->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + prSchedScanParam->fgStopAfterIndication = FALSE; + + if (!IS_NET_ACTIVE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex)) { + SET_NET_ACTIVE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + /* sync with firmware */ + nicActivateNetwork(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex); + } + + /* 2.1 Prepare command. Set FW struct SSID_MATCH_SETS */ + /* ssid in ssid list will be send in probe request in advance */ + prSchedScanCmd->ucSsidNum = prRequest->u4SsidNum; + for (i = 0; i < prSchedScanCmd->ucSsidNum; i++) { + kalMemCopy(&(prSsid[i]), &(prRequest->arSsid[i]), + sizeof(struct PARAM_SSID)); + log_dbg(SCN, TRACE, "ssid set(%d) %s\n", i, prSsid[i].aucSsid); + } + + prSchedScanCmd->ucMatchSsidNum = prRequest->u4MatchSsidNum; + for (i = 0; i < prSchedScanCmd->ucMatchSsidNum; i++) { + COPY_SSID(prMatchSets[i].aucSsid, prMatchSets[i].ucSsidLen, + prRequest->arMatchSsid[i].aucSsid, + prRequest->arMatchSsid[i].u4SsidLen); + prMatchSets[i].i4RssiThresold = prRequest->ai4RssiThold[i]; + log_dbg(SCN, TRACE, "Match set(%d) %s, rssi>%d\n", + i, prMatchSets[i].aucSsid, + prMatchSets[i].i4RssiThresold); + } + + /* 2.2 Prepare command. Set channel */ + + ePreferedChnl + = prAdapter->aePreferBand[prAdapter->prAisBssInfo->ucBssIndex]; + if (ePreferedChnl == BAND_2G4) { + prSchedScanCmd->ucChannelType = + SCHED_SCAN_CHANNEL_TYPE_2G4_ONLY; + prSchedScanCmd->ucChnlNum = 0; + } else if (ePreferedChnl == BAND_5G) { + prSchedScanCmd->ucChannelType = + SCHED_SCAN_CHANNEL_TYPE_5G_ONLY; + prSchedScanCmd->ucChnlNum = 0; + } else if (prRequest->ucChnlNum > 0 && + prRequest->ucChnlNum <= MAXIMUM_OPERATION_CHANNEL_LIST) { + prSchedScanCmd->ucChannelType = + SCHED_SCAN_CHANNEL_TYPE_SPECIFIED; + prSchedScanCmd->ucChnlNum = prRequest->ucChnlNum; + for (i = 0; i < prRequest->ucChnlNum; i++) { + prSchedScanCmd->aucChannel[i].ucChannelNum = + prRequest->pucChannels[i]; + prSchedScanCmd->aucChannel[i].ucBand = + (prSchedScanCmd->aucChannel[i].ucChannelNum <= + HW_CHNL_NUM_MAX_2G4) ? BAND_2G4 : BAND_5G; + } + } else { + prSchedScanCmd->ucChnlNum = 0; + prSchedScanCmd->ucChannelType = + SCHED_SCAN_CHANNEL_TYPE_DUAL_BAND; + } + + prSchedScanCmd->ucSeqNum = prSchedScanParam->ucSeqNum; + prSchedScanCmd->fgStopAfterIndication = + prSchedScanParam->fgStopAfterIndication; + prSchedScanCmd->u2IELen = u2IeLen; + prSchedScanCmd->ucVersion = SCHED_SCAN_CMD_VERSION; + if (prSchedScanCmd->u2IELen) { + kalMemCopy(prSchedScanCmd->aucIE, prRequest->pucIE, + prSchedScanCmd->u2IELen); + } + + prSchedScanCmd->ucScnFuncMask |= prRequest->ucScnFuncMask; + + scnSetSchedScanPlan(prAdapter, prSchedScanCmd); + + log_dbg(SCN, INFO, "V(%u)seq(%u)sz(%zu)chT(%u)chN(%u)ssid(%u)match(%u)IE(%u=>%u)MSP(%u)Func(0x%X)\n", + prSchedScanCmd->ucVersion, + prSchedScanCmd->ucSeqNum, sizeof(struct CMD_SCHED_SCAN_REQ), + prSchedScanCmd->ucChannelType, prSchedScanCmd->ucChnlNum, + prSchedScanCmd->ucSsidNum, prSchedScanCmd->ucMatchSsidNum, + prRequest->u4IELength, prSchedScanCmd->u2IELen, + prSchedScanCmd->ucMspEntryNum, + prSchedScanCmd->ucScnFuncMask); + + /* 3. send command packet to FW */ + do { + if (!scnFsmSchedScanSetCmd(prAdapter, prSchedScanCmd)) { + log_dbg(SCN, TRACE, "scnFsmSchedScanSetCmd failed\n"); + fgRet = FALSE; + break; + } + if (!scnFsmSchedScanSetAction(prAdapter, + SCHED_SCAN_ACT_ENABLE)) { + log_dbg(SCN, TRACE, "scnFsmSchedScanSetAction failed\n"); + fgRet = FALSE; + break; + } +#if CFG_SUPPORT_PNO + prAdapter->prAisBssInfo->fgIsPNOEnable = TRUE; +#endif + prScanInfo->fgSchedScanning = TRUE; + } while (0); + + cnmMemFree(prAdapter, (void *) prSchedScanCmd); + + return fgRet; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief handler for stopping scheduled scan + * + * \param[in] + * + * \return TRUE if send stop command successfully. FALSE otherwise + */ +/*----------------------------------------------------------------------------*/ +u_int8_t scnFsmSchedScanStopRequest(IN struct ADAPTER *prAdapter) +{ + ASSERT(prAdapter); + log_dbg(SCN, INFO, "scnFsmSchedScanStopRequest\n"); + + if (prAdapter->prAisBssInfo == NULL) { + log_dbg(SCN, WARN, "prAisBssInfo is NULL\n"); + return FALSE; + } + + if (!scnFsmSchedScanSetAction(prAdapter, SCHED_SCAN_ACT_DISABLE)) { + log_dbg(SCN, TRACE, "scnFsmSchedScanSetAction failed\n"); + return FALSE; + } +#if CFG_SUPPORT_PNO + prAdapter->prAisBssInfo->fgIsPNOEnable = FALSE; +#endif + prAdapter->rWifiVar.rScanInfo.fgSchedScanning = FALSE; + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief handler for setting schedule scan action + * \param prAdapter adapter + * \param ucSchedScanAct schedule scan action. set enable/disable to FW + * + * \return TRUE if send query command successfully. FALSE otherwise + */ +/*----------------------------------------------------------------------------*/ +u_int8_t +scnFsmSchedScanSetAction(IN struct ADAPTER *prAdapter, + IN enum ENUM_SCHED_SCAN_ACT ucSchedScanAct) +{ + struct CMD_SET_SCHED_SCAN_ENABLE rCmdSchedScanAction; + uint32_t rStatus; + + ASSERT(prAdapter); + + kalMemZero(&rCmdSchedScanAction, + sizeof(struct CMD_SET_SCHED_SCAN_ENABLE)); + + /* 0:enable, 1:disable */ + rCmdSchedScanAction.ucSchedScanAct = ucSchedScanAct; + + if (ucSchedScanAct == SCHED_SCAN_ACT_ENABLE) { + scanlog_dbg(LOG_SCHED_SCAN_REQ_START_D2F, INFO, "sched scan action = %d\n", + rCmdSchedScanAction.ucSchedScanAct); + } else { + scanlog_dbg(LOG_SCHED_SCAN_REQ_STOP_D2F, INFO, "sched scan action = %d\n", + rCmdSchedScanAction.ucSchedScanAct); + } + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_SCHED_SCAN_ENABLE, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_SET_SCHED_SCAN_ENABLE), + (uint8_t *)&rCmdSchedScanAction, NULL, 0); + + return (rStatus != WLAN_STATUS_FAILURE) ? TRUE : FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief handler for setting schedule scan command + * \param prAdapter adapter + * \param prSchedScanCmd schedule scan command + * + * \return TRUE if send query command successfully. + * FAIL otherwise + */ +/*----------------------------------------------------------------------------*/ +u_int8_t +scnFsmSchedScanSetCmd(IN struct ADAPTER *prAdapter, + IN struct CMD_SCHED_SCAN_REQ *prSchedScanCmd) +{ + uint16_t u2IeSize = 0; + uint32_t rStatus; + + ASSERT(prAdapter); + + log_dbg(SCN, TRACE, "--> %s()\n", __func__); + + if (prSchedScanCmd) + u2IeSize = prSchedScanCmd->u2IELen; + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_SCHED_SCAN_REQ, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_SCHED_SCAN_REQ) + u2IeSize, + (uint8_t *) prSchedScanCmd, NULL, 0); + + return (rStatus != WLAN_STATUS_FAILURE) ? TRUE : FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Set schedule scan multiple scan plan (scan interval) + * \param prAdapter adapter + * \param prSchedScanCmd schedule scan command request + * + * \return void + */ +/*----------------------------------------------------------------------------*/ +void +scnSetSchedScanPlan(IN struct ADAPTER *prAdapter, + IN struct CMD_SCHED_SCAN_REQ *prSchedScanCmd) +{ + /* Set Multiple Scan Plan here */ + log_dbg(SCN, TRACE, "--> %s()\n", __func__); + + ASSERT(prAdapter); + + prSchedScanCmd->ucMspEntryNum = 0; + kalMemZero(prSchedScanCmd->au2MspList, + sizeof(prSchedScanCmd->au2MspList)); +} + +#endif /* CFG_SUPPORT_SCHED_SCAN */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/stats.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/stats.c new file mode 100644 index 0000000000000..5d8397eb3d565 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/stats.c @@ -0,0 +1,597 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License version 2 as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. + * If not, see . + */ + +/******************************************************************************* + * C O M P I L E 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_STATISTICS == 1) + +enum EVENT_TYPE { + EVENT_RX, + EVENT_TX, +}; +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ + +/******************************************************************************* + * P R I V A T E F U N C T I O N S + ******************************************************************************* + */ + +uint32_t u4TotalTx; +uint32_t u4NoDelayTx; +uint32_t u4TotalRx; +uint32_t u4NoDelayRx; + +static uint8_t g_ucTxRxFlag; +static uint8_t g_ucTxIpProto; +static uint16_t g_u2TxUdpPort; +static uint32_t g_u4TxDelayThreshold; +static uint8_t g_ucRxIpProto; +static uint16_t g_u2RxUdpPort; +static uint32_t g_u4RxDelayThreshold; + +void StatsResetTxRx(void) +{ + u4TotalRx = 0; + u4TotalTx = 0; + u4NoDelayRx = 0; + u4NoDelayTx = 0; +} + +uint64_t StatsEnvTimeGet(void) +{ + uint64_t u8Clk; + + u8Clk = sched_clock(); /* unit: naro seconds */ + + return (uint64_t) u8Clk; /* sched_clock *//* jiffies size = 4B */ +} + +void StatsEnvGetPktDelay(OUT uint8_t *pucTxRxFlag, + OUT uint8_t *pucTxIpProto, OUT uint16_t *pu2TxUdpPort, + OUT uint32_t *pu4TxDelayThreshold, OUT uint8_t *pucRxIpProto, + OUT uint16_t *pu2RxUdpPort, OUT uint32_t *pu4RxDelayThreshold) +{ + *pucTxRxFlag = g_ucTxRxFlag; + *pucTxIpProto = g_ucTxIpProto; + *pu2TxUdpPort = g_u2TxUdpPort; + *pu4TxDelayThreshold = g_u4TxDelayThreshold; + *pucRxIpProto = g_ucRxIpProto; + *pu2RxUdpPort = g_u2RxUdpPort; + *pu4RxDelayThreshold = g_u4RxDelayThreshold; +} + +void StatsEnvSetPktDelay(IN uint8_t ucTxOrRx, IN uint8_t ucIpProto, + IN uint16_t u2UdpPort, uint32_t u4DelayThreshold) +{ +#define MODULE_RESET 0 +#define MODULE_TX 1 +#define MODULE_RX 2 + + if (ucTxOrRx == MODULE_TX) { + g_ucTxRxFlag |= BIT(0); + g_ucTxIpProto = ucIpProto; + g_u2TxUdpPort = u2UdpPort; + g_u4TxDelayThreshold = u4DelayThreshold; + } else if (ucTxOrRx == MODULE_RX) { + g_ucTxRxFlag |= BIT(1); + g_ucRxIpProto = ucIpProto; + g_u2RxUdpPort = u2UdpPort; + g_u4RxDelayThreshold = u4DelayThreshold; + } else if (ucTxOrRx == MODULE_RESET) { + g_ucTxRxFlag = 0; + g_ucTxIpProto = 0; + g_u2TxUdpPort = 0; + g_u4TxDelayThreshold = 0; + g_ucRxIpProto = 0; + g_u2RxUdpPort = 0; + g_u4RxDelayThreshold = 0; + } +} + +void StatsEnvRxTime2Host(IN struct ADAPTER *prAdapter, struct sk_buff *prSkb) +{ + uint8_t *pucEth = prSkb->data; + uint16_t u2EthType = 0; + uint8_t ucIpVersion = 0; + uint8_t ucIpProto = 0; + uint16_t u2IPID = 0; + uint16_t u2UdpDstPort = 0; + uint16_t u2UdpSrcPort = 0; + uint64_t u8IntTime = 0; + uint64_t u8RxTime = 0; + uint32_t u4Delay = 0; + struct timeval tval; + struct rtc_time tm; + + if ((g_ucTxRxFlag & BIT(1)) == 0) + return; + + if (prSkb->len <= 24 + ETH_HLEN) + return; + u2EthType = (pucEth[ETH_TYPE_LEN_OFFSET] << 8) + | (pucEth[ETH_TYPE_LEN_OFFSET + 1]); + pucEth += ETH_HLEN; + if (u2EthType != ETH_P_IPV4) + return; + ucIpProto = pucEth[9]; + if (g_ucRxIpProto && (ucIpProto != g_ucRxIpProto)) + return; + ucIpVersion = (pucEth[0] & IPVH_VERSION_MASK) >> IPVH_VERSION_OFFSET; + if (ucIpVersion != IPVERSION) + return; + u2IPID = pucEth[4] << 8 | pucEth[5]; + u8IntTime = GLUE_RX_GET_PKT_INT_TIME(prSkb); + u4Delay = ((uint32_t)(sched_clock() - u8IntTime))/NSEC_PER_USEC; + u8RxTime = GLUE_RX_GET_PKT_RX_TIME(prSkb); + do_gettimeofday(&tval); + rtc_time_to_tm(tval.tv_sec, &tm); + + switch (ucIpProto) { + case IP_PRO_TCP: + case IP_PRO_UDP: + u2UdpSrcPort = (pucEth[20] << 8) | pucEth[21]; + u2UdpDstPort = (pucEth[22] << 8) | pucEth[23]; + if (g_u2RxUdpPort && (u2UdpSrcPort != g_u2RxUdpPort)) + break; + case IP_PRO_ICMP: + u4TotalRx++; + if (g_u4RxDelayThreshold && (u4Delay <= g_u4RxDelayThreshold)) { + u4NoDelayRx++; + break; + } + DBGLOG(RX, INFO, + "IPID 0x%04x src %d dst %d UP %d,delay %u us,int2rx %lu us,IntTime %llu,%u/%u,leave at %02d:%02d:%02d.%06ld\n", + u2IPID, u2UdpSrcPort, u2UdpDstPort, + ((pucEth[1] & IPTOS_PREC_MASK) >> IPTOS_PREC_OFFSET), + u4Delay, + ((uint32_t)(u8RxTime - u8IntTime))/NSEC_PER_USEC, + u8IntTime, u4NoDelayRx, u4TotalRx, + tm.tm_hour, tm.tm_min, tm.tm_sec, tval.tv_usec); + break; + default: + break; + } +} + +void StatsEnvTxTime2Hif(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + uint64_t u8SysTime, u8SysTimeIn; + uint32_t u4TimeDiff; + uint8_t *pucEth = ((struct sk_buff *)prMsduInfo->prPacket)->data; + uint32_t u4PacketLen = ((struct sk_buff *)prMsduInfo->prPacket)->len; + uint8_t ucIpVersion = 0; + uint8_t ucIpProto = 0; + uint8_t *pucEthBody = NULL; + uint16_t u2EthType = 0; + uint8_t *pucAheadBuf = NULL; + uint16_t u2IPID = 0; + uint16_t u2UdpDstPort = 0; + uint16_t u2UdpSrcPort = 0; + + u8SysTime = StatsEnvTimeGet(); + u8SysTimeIn = GLUE_GET_PKT_XTIME(prMsduInfo->prPacket); + + if ((g_ucTxRxFlag & BIT(0)) == 0) + return; + + if ((u8SysTimeIn == 0) || (u8SysTime <= u8SysTimeIn)) + return; + + /* units of u4TimeDiff is micro seconds (us) */ + if (u4PacketLen < 24 + ETH_HLEN) + return; + pucAheadBuf = &pucEth[76]; + u2EthType = (pucAheadBuf[ETH_TYPE_LEN_OFFSET] << 8) + | (pucAheadBuf[ETH_TYPE_LEN_OFFSET + 1]); + pucEthBody = &pucAheadBuf[ETH_HLEN]; + if (u2EthType != ETH_P_IPV4) + return; + ucIpProto = pucEthBody[9]; + if (g_ucTxIpProto && (ucIpProto != g_ucTxIpProto)) + return; + ucIpVersion = (pucEthBody[0] & IPVH_VERSION_MASK) + >> IPVH_VERSION_OFFSET; + if (ucIpVersion != IPVERSION) + return; + u2IPID = pucEthBody[4]<<8 | pucEthBody[5]; + u8SysTime = u8SysTime - u8SysTimeIn; + u4TimeDiff = (uint32_t) u8SysTime; + u4TimeDiff = u4TimeDiff / 1000; /* ns to us */ + + switch (ucIpProto) { + case IP_PRO_TCP: + case IP_PRO_UDP: + u2UdpDstPort = (pucEthBody[22] << 8) | pucEthBody[23]; + u2UdpSrcPort = (pucEthBody[20] << 8) | pucEthBody[21]; + if (g_u2TxUdpPort && (u2UdpDstPort != g_u2TxUdpPort)) + break; + case IP_PRO_ICMP: + u4TotalTx++; + if (g_u4TxDelayThreshold + && (u4TimeDiff <= g_u4TxDelayThreshold)) { + u4NoDelayTx++; + break; + } + DBGLOG(TX, INFO, + "IPID 0x%04x src %d dst %d UP %d,delay %u us,u8SysTimeIn %llu, %u/%u\n", + u2IPID, u2UdpSrcPort, u2UdpDstPort, + ((pucEthBody[1] & IPTOS_PREC_MASK) + >> IPTOS_PREC_OFFSET), + u4TimeDiff, u8SysTimeIn, u4NoDelayTx, u4TotalTx); + break; + default: + break; + } +} + +static void statsParsePktInfo(uint8_t *pucPkt, struct sk_buff *skb, + uint8_t status, uint8_t eventType) +{ + /* get ethernet protocol */ + uint16_t u2EtherType = + (pucPkt[ETH_TYPE_LEN_OFFSET] << 8) + | (pucPkt[ETH_TYPE_LEN_OFFSET + 1]); + uint8_t *pucEthBody = &pucPkt[ETH_HLEN]; + + switch (u2EtherType) { + case ETH_P_ARP: + { + uint16_t u2OpCode = (pucEthBody[6] << 8) | pucEthBody[7]; + + switch (eventType) { + case EVENT_RX: + if (u2OpCode == ARP_PRO_REQ) + DBGLOG_LIMITED(RX, TRACE, + " Arp Req From IP: %d.%d.%d.%d\n", + pucEthBody[14], pucEthBody[15], + pucEthBody[16], pucEthBody[17]); + else if (u2OpCode == ARP_PRO_RSP) + DBGLOG_LIMITED(RX, TRACE, + " Arp Rsp from IP: %d.%d.%d.%d\n", + pucEthBody[14], pucEthBody[15], + pucEthBody[16], pucEthBody[17]); + break; + case EVENT_TX: + if (u2OpCode == ARP_PRO_REQ) + DBGLOG_LIMITED(TX, TRACE, + " Arp Req to IP: %d.%d.%d.%d\n", + pucEthBody[24], pucEthBody[25], + pucEthBody[26], pucEthBody[27]); + else if (u2OpCode == ARP_PRO_RSP) + DBGLOG_LIMITED(TX, TRACE, + " Arp Rsp to IP: %d.%d.%d.%d\n", + pucEthBody[24], pucEthBody[25], + pucEthBody[26], pucEthBody[27]); + break; + } + break; + } + case ETH_P_IPV4: + { + /* IP header without options */ + uint8_t ucIpProto = pucEthBody[9]; + uint8_t ucIpVersion = + (pucEthBody[0] & IPVH_VERSION_MASK) + >> IPVH_VERSION_OFFSET; + uint16_t u2IpId = *(uint16_t *) &pucEthBody[4]; + + if (ucIpVersion != IPVERSION) + break; + switch (ucIpProto) { + case IP_PRO_ICMP: + { + /* the number of ICMP packets is seldom + * so we print log here + */ + uint8_t ucIcmpType; + uint16_t u2IcmpId, u2IcmpSeq; + uint8_t *pucIcmp = &pucEthBody[20]; + + ucIcmpType = pucIcmp[0]; + /* don't log network unreachable packet */ + if (ucIcmpType == 3) + break; + u2IcmpId = *(uint16_t *) &pucIcmp[4]; + u2IcmpSeq = *(uint16_t *) &pucIcmp[6]; + switch (eventType) { + case EVENT_RX: + DBGLOG_LIMITED(RX, TRACE, + " ICMP: Type %d, Id BE 0x%04x, Seq BE 0x%04x\n", + ucIcmpType, u2IcmpId, u2IcmpSeq); + break; + case EVENT_TX: + DBGLOG_LIMITED(TX, TRACE, + " ICMP: Type %d, Id 0x%04x, Seq BE 0x%04x\n", + ucIcmpType, u2IcmpId, u2IcmpSeq); + break; + } + break; + } + case IP_PRO_UDP: + { + /* the number of DHCP packets is seldom + * so we print log here + */ + uint8_t *pucUdp = &pucEthBody[20]; + uint8_t *pucBootp = &pucUdp[UDP_HDR_LEN]; + struct BOOTP_PROTOCOL *prBootp; + uint16_t u2UdpDstPort; + uint16_t u2UdpSrcPort; + uint32_t u4TransID; + prBootp = + (struct BOOTP_PROTOCOL *) &pucUdp[UDP_HDR_LEN]; + + u2UdpDstPort = (pucUdp[2] << 8) | pucUdp[3]; + u2UdpSrcPort = (pucUdp[0] << 8) | pucUdp[1]; + if ((u2UdpDstPort == UDP_PORT_DHCPS) + || (u2UdpDstPort == UDP_PORT_DHCPC)) { + WLAN_GET_FIELD_BE32( + &prBootp->u4TransId, &u4TransID); + switch (eventType) { + case EVENT_RX: + DBGLOG_LIMITED(RX, INFO, + " DHCP: IPID 0x%02x, MsgType 0x%x, TransID 0x%04x\n", + u2IpId, prBootp->aucOptions[6], + u4TransID); + break; + case EVENT_TX: + DBGLOG_LIMITED(TX, INFO, + " DHCP: IPID 0x%02x, MsgType 0x%x, TransID 0x%04x\n", + u2IpId, prBootp->aucOptions[6], + u4TransID); + break; + } + } else if (u2UdpSrcPort == UDP_PORT_DNS) { /* tx dns */ + uint16_t u2TransId = + (pucBootp[0] << 8) | pucBootp[1]; + + if (eventType == EVENT_RX) + DBGLOG_LIMITED(RX, INFO, + " DNS: IPID 0x%02x, TransID 0x%04x\n", + u2IpId, u2TransId); + } + break; + } + } + break; + } + case ETH_P_IPV6: + { + /* IPv6 header without options */ + uint8_t ucIpv6Proto = + pucEthBody[IPV6_HDR_LEN]; + uint8_t ucIpVersion = + (pucEthBody[0] & IPVH_VERSION_MASK) + >> IPVH_VERSION_OFFSET; + + if (ucIpVersion != IP_VERSION_6) + break; + switch (ucIpv6Proto) { + case 0x85: + switch (eventType) { + case EVENT_RX: + DBGLOG_LIMITED(RX, INFO, + " Router Solicitation\n"); + break; + case EVENT_TX: + DBGLOG_LIMITED(TX, INFO, + " Router Solicitation\n"); + break; + } + break; + case 0x86: + switch (eventType) { + case EVENT_RX: + DBGLOG_LIMITED(RX, INFO, + " Router Advertisement\n"); + break; + case EVENT_TX: + DBGLOG_LIMITED(TX, INFO, + " Router Advertisement\n"); + break; + } + break; + case ICMPV6_TYPE_NEIGHBOR_SOLICITATION: + switch (eventType) { + case EVENT_RX: + DBGLOG_LIMITED(RX, INFO, + " Neighbor Solicitation\n"); + break; + case EVENT_TX: + DBGLOG_LIMITED(TX, INFO, + " Neighbor Solicitation\n"); + break; + } + break; + case ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT: + switch (eventType) { + case EVENT_RX: + DBGLOG_LIMITED(RX, INFO, + " Neighbor Advertisement\n"); + break; + case EVENT_TX: + DBGLOG_LIMITED(TX, INFO, + " Neighbor Advertisement\n"); + break; + } + break; + } + break; + } + case ETH_P_1X: + { + uint8_t *pucEapol = pucEthBody; + uint8_t ucEapolType = pucEapol[1]; + + switch (ucEapolType) { + case 0: /* eap packet */ + switch (eventType) { + case EVENT_RX: + DBGLOG_LIMITED(RX, INFO, + " EAP Packet: code %d, id %d, type %d\n", + pucEapol[4], pucEapol[5], pucEapol[7]); + break; + case EVENT_TX: + DBGLOG_LIMITED(TX, INFO, + " EAP Packet: code %d, id %d, type %d\n", + pucEapol[4], pucEapol[5], + pucEapol[7]); + break; + } + break; + case 1: /* eapol start */ + switch (eventType) { + case EVENT_RX: + DBGLOG_LIMITED(RX, INFO, " EAPOL: start\n"); + break; + case EVENT_TX: + DBGLOG_LIMITED(TX, INFO, " EAPOL: start\n"); + break; + } + break; + case 3: /* key */ + switch (eventType) { + case EVENT_RX: + DBGLOG_LIMITED(RX, INFO, + " EAPOL: key, KeyInfo 0x%04x\n", + *((uint16_t *)(&pucEapol[5]))); + break; + case EVENT_TX: + DBGLOG_LIMITED(TX, INFO, + " EAPOL: key, KeyInfo 0x%04x\n", + *((uint16_t *)(&pucEapol[5]))); + break; + } + + break; + } + break; + } +#if CFG_SUPPORT_WAPI + case ETH_WPI_1X: + { + uint8_t ucSubType = pucEthBody[3]; /* sub type filed*/ + uint16_t u2Length = *(uint16_t *)&pucEthBody[6]; + uint16_t u2Seq = *(uint16_t *)&pucEthBody[8]; + + switch (eventType) { + case EVENT_RX: + DBGLOG_LIMITED(RX, INFO, + " WAPI: subType %d, Len %d, Seq %d\n", + ucSubType, u2Length, u2Seq); + break; + case EVENT_TX: + DBGLOG_LIMITED(TX, INFO, + " WAPI: subType %d, Len %d, Seq %d\n", + ucSubType, u2Length, u2Seq); + break; + } + break; + } +#endif + case ETH_PRO_TDLS: + switch (eventType) { + case EVENT_RX: + DBGLOG_LIMITED(RX, INFO, + " TDLS type %d, category %d, Action %d, Token %d\n", + pucEthBody[0], pucEthBody[1], + pucEthBody[2], pucEthBody[3]); + break; + case EVENT_TX: + DBGLOG_LIMITED(TX, INFO, + " TDLS type %d, category %d, Action %d, Token %d\n", + pucEthBody[0], pucEthBody[1], + pucEthBody[2], pucEthBody[3]); + break; + } + break; + } +} +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to display rx packet information. + * + * \param[in] pPkt Pointer to the packet + * \param[out] None + * + * \retval None + */ +/*----------------------------------------------------------------------------*/ +void StatsRxPktInfoDisplay(struct SW_RFB *prSwRfb) +{ + uint8_t *pPkt = NULL; + struct sk_buff *skb = NULL; + + if (prSwRfb->u2PacketLen <= ETHER_HEADER_LEN) + return; + + pPkt = prSwRfb->pvHeader; + if (!pPkt) + return; + + skb = (struct sk_buff *)(prSwRfb->pvPacket); + if (!skb) + return; + + statsParsePktInfo(pPkt, skb, 0, EVENT_RX); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to display tx packet information. + * + * \param[in] pPkt Pointer to the packet + * \param[out] None + * + * \retval None + */ +/*----------------------------------------------------------------------------*/ +void StatsTxPktInfoDisplay(uint8_t *pPkt) +{ + uint16_t u2EtherTypeLen; + + u2EtherTypeLen = + (pPkt[ETH_TYPE_LEN_OFFSET] << 8) + | (pPkt[ETH_TYPE_LEN_OFFSET + 1]); + statsParsePktInfo(pPkt, NULL, 0, EVENT_TX); +} + +#endif /* CFG_SUPPORT_STATISTICS */ + +/* End of stats.c */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/swcr.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/swcr.c new file mode 100644 index 0000000000000..05b4cf0d7d4f0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/swcr.c @@ -0,0 +1,1469 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/swcr.c#1 + */ + +/*! \file "swcr.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" +#include "swcr.h" + +#if CFG_SUPPORT_SWCR + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************* + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +uint32_t g_au4SwCr[SWCR_CR_NUM]; /*: 0: command other: data */ + +/* JB mDNS Filter*/ +uint32_t g_u4RXFilter; /* [31] 0: stop 1: start, [3] IPv6 [2] IPv4 */ + +static struct TIMER g_rSwcrDebugTimer; +static u_int8_t g_fgSwcrDebugTimer = FALSE; +static uint32_t g_u4SwcrDebugCheckTimeout; +static enum ENUM_SWCR_DBG_TYPE g_ucSwcrDebugCheckType; +static uint32_t g_u4SwcrDebugFrameDumpType; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +static const PFN_CMD_RW_T g_arSwCtrlCmd[] = { + swCtrlCmdCategory0, + swCtrlCmdCategory1 +#if TEST_PS + , testPsCmdCategory0, testPsCmdCategory1 +#endif +#if CFG_SUPPORT_802_11V +#if (CFG_SUPPORT_802_11V_TIMING_MEASUREMENT == 1) && (WNM_UNIT_TEST == 1) + , testWNMCmdCategory0 +#endif +#endif +}; + +const PFN_SWCR_RW_T g_arSwCrModHandle[] = { + swCtrlSwCr, + NULL +}; + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +enum { + SWCTRL_MAGIC, + SWCTRL_DEBUG, + SWCTRL_WIFI_VAR, + SWCTRL_ENABLE_INT, + SWCTRL_DISABLE_INT, + SWCTRL_TXM_INFO, + SWCTRL_RXM_INFO, + SWCTRL_DUMP_BSS, + SWCTRL_QM_INFO, + SWCTRL_DUMP_ALL_QUEUE_LEN, + SWCTRL_DUMP_MEM, + SWCTRL_TX_CTRL_INFO, + SWCTRL_DUMP_QUEUE, + SWCTRL_DUMP_QM_DBG_CNT, + SWCTRL_QM_DBG_CNT, + SWCTRL_RX_PKTS_DUMP, + SWCTRL_RX_FILTER, +#if CFG_INIT_ENABLE_PATTERN_FILTER_ARP + SWCTRL_RX_ARP_OFFLOAD, +#endif + SWCTRL_PS_DTIM_SKIP, + SWCTRL_ROAMING, + SWCTRL_CATA0_INDEX_NUM +}; + +enum { + SWCTRL_STA_INFO, + SWCTRL_DUMP_STA, + SWCTRL_STA_QUE_INFO, + SWCTRL_CATA1_INDEX_NUM +}; + +/* JB mDNS Filter*/ +#define RX_FILTER_START (1<<31) +#define RX_FILTER_IPV4 (1<<2) +#define RX_FILTER_IPV6 (1<<3) +enum ENUM_SWCR_RX_FILTER_CMD { + SWCR_RX_FILTER_CMD_STOP = 0, + SWCR_RX_FILTER_CMD_START, + SWCR_RX_FILTER_CMD_ADD, + SWCR_RX_FILTER_CMD_REMOVE, + SWCR_RX_FILTER_NUM +}; + +#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(struct ADAPTER *prAdapter) +{ + + struct TX_CTRL *prTxCtrl; + struct QUE_MGT *prQM; + struct GLUE_INFO *prGlueInfo; + uint32_t i; + uint32_t j; + + DEBUGFUNC("dumpQueue"); + + prTxCtrl = &prAdapter->rTxCtrl; + prQM = &prAdapter->rQM; + prGlueInfo = prAdapter->prGlueInfo; +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + for (i = TC0_INDEX; i < TC_NUM; i++) { + DBGLOG(SW4, INFO, "TC %u\n", i); + DBGLOG(SW4, INFO, "Max %u Free %u\n", + prTxCtrl->rTc.au4MaxNumOfBuffer[i], + prTxCtrl->rTc.au4FreeBufferCount[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]); + + } +#endif + +#if QM_FORWARDING_FAIRNESS + 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->au4ResourceUsedCount[i]); + } +#endif + + 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(struct ADAPTER *prAdapter, struct STA_RECORD *prStaRec) +{ + uint8_t ucWTEntry; + uint32_t i; + struct BSS_INFO *prBssInfo; + + DEBUGFUNC("dumpSTA"); + + ASSERT(prStaRec); + ucWTEntry = prStaRec->ucWlanIndex; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + 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->aprTargetQueue[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(struct ADAPTER *prAdapter, + struct BSS_INFO *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, "eNetworkType %u\n", + prBssInfo->eNetworkType); + DBGLOG(SW4, INFO, "ucBssIndex %u\n", prBssInfo->ucBssIndex); + 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(struct ADAPTER *prAdapter, + uint8_t ucCate, uint8_t ucAction, uint8_t ucOpt0, + uint8_t ucOpt1) +{ + uint8_t ucIndex, ucRead; + uint32_t i; + struct CMD_RX_PACKET_FILTER rSetRxPacketFilter; + + 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: + 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: + prAdapter->rRxCtrl.u4RxPktsDumpTypeMask = g_au4SwCr[1]; + break; +#endif + case SWCTRL_RX_FILTER: { + uint32_t u4rxfilter; + u_int8_t fgUpdate = FALSE; + uint32_t rStatus = WLAN_STATUS_SUCCESS; + + if (ucOpt0 == SWCR_RX_FILTER_CMD_STOP) { + g_u4RXFilter &= ~(RX_FILTER_START); + /* changed by jeffrey to align + * Android behavior + */ +#if 0 + if (prAdapter->fgAllMulicastFilter == FALSE) + prAdapter->u4OsPacketFilter &= + ~PARAM_PACKET_FILTER_ALL_MULTICAST; +#endif + prAdapter->u4OsPacketFilter &= + ~PARAM_PACKET_FILTER_MULTICAST; + u4rxfilter = prAdapter->u4OsPacketFilter; + fgUpdate = TRUE; + } else if (ucOpt0 == SWCR_RX_FILTER_CMD_START) { + g_u4RXFilter |= (RX_FILTER_START); + + if ((g_u4RXFilter & RX_FILTER_IPV4) + || (g_u4RXFilter & RX_FILTER_IPV6)) { +#if 0 + prAdapter->u4OsPacketFilter |= + PARAM_PACKET_FILTER_ALL_MULTICAST; +#endif + prAdapter->u4OsPacketFilter |= + PARAM_PACKET_FILTER_MULTICAST; + } + u4rxfilter = prAdapter->u4OsPacketFilter; + fgUpdate = TRUE; + } else if (ucOpt0 == SWCR_RX_FILTER_CMD_ADD) { + if (ucOpt1 < 31) + g_u4RXFilter |= (1 << ucOpt1); + } else if (ucOpt0 == SWCR_RX_FILTER_CMD_REMOVE) { + if (ucOpt1 < 31) + g_u4RXFilter &= ~(1 << ucOpt1); + } + + if (fgUpdate == TRUE) { + rSetRxPacketFilter. + u4RxPacketFilter = u4rxfilter; + rStatus = + wlanoidSetPacketFilter( + prAdapter, &rSetRxPacketFilter, + FALSE, NULL, 0); + } + /* DBGLOG(SW4, INFO,("SWCTRL_RX_FILTER: + * g_u4RXFilter %x ucOpt0 %x ucOpt1 %x fgUpdate %x + * u4rxfilter %x, rStatus %x\n", + * g_u4RXFilter, ucOpt0, ucOpt1, + * fgUpdate, u4rxfilter, rStatus)); + */ + } + break; + +#if CFG_INIT_ENABLE_PATTERN_FILTER_ARP + case SWCTRL_RX_ARP_OFFLOAD: { + uint32_t rStatus = WLAN_STATUS_FAILURE; + uint32_t u4SetInfoLen = 0; + uint32_t u4Len = OFFSET_OF(struct + PARAM_NETWORK_ADDRESS_LIST, arAddress); + uint32_t u4NumIPv4 = 0, u4NumIPv6 = 0; + uint32_t i = 0; + uint8_t *pucBufIpAddr = NULL; + struct PARAM_NETWORK_ADDRESS_LIST *prParamNetAddrList = + NULL; + struct PARAM_NETWORK_ADDRESS_IP *prParamIpAddr = NULL; + uint8_t *pucIp = NULL; + /* PUINT_8 pucIpv6 = NULL; */ + uint32_t bufSize = + u4Len + (OFFSET_OF(struct PARAM_NETWORK_ADDRESS, + aucAddress) + + sizeof( + struct PARAM_NETWORK_ADDRESS_IP)) * 3; + struct PARAM_NETWORK_ADDRESS *prParamNetAddr = NULL; + + /* <1> allocate IP address buffer */ + pucBufIpAddr = kalMemAlloc(bufSize, VIR_MEM_TYPE); + /* TODO: replace 3 to macro */ + pucIp = kalMemAlloc(3 * 4, VIR_MEM_TYPE); + + prParamNetAddrList = + (struct PARAM_NETWORK_ADDRESS_LIST *) + pucBufIpAddr; + prParamNetAddr = prParamNetAddrList->arAddress; + /* <2> clear IP address buffer */ + kalMemZero(pucBufIpAddr, bufSize); + kalMemZero(pucIp, 3 * 4); + + /* <3> setup the number of IP address */ + if (ucOpt1 == 1) { + /* TODO: repleace 3 to macro */ + if (wlanGetIPV4Address( + prAdapter->prGlueInfo, pucIp, + &u4NumIPv4) && u4NumIPv4 > 3) + u4NumIPv4 = 3; + } else if (ucOpt1 == 0) { + u4NumIPv4 = u4NumIPv6 = 0; + } + DBGLOG(INIT, INFO, "u4Len:%d bufSize:%d u4NumIPv4:%d\n", + u4Len, bufSize, u4NumIPv4); + + prParamNetAddrList->u4AddressCount = + u4NumIPv6 + u4NumIPv4; + prParamNetAddrList->u2AddressType = + PARAM_PROTOCOL_ID_TCP_IP; + + for (i = 0; i < u4NumIPv4; i++) { + prParamNetAddr->u2AddressLength = sizeof(struct + PARAM_NETWORK_ADDRESS_IP); + prParamNetAddr->u2AddressType = + PARAM_PROTOCOL_ID_TCP_IP; + prParamIpAddr = + (struct PARAM_NETWORK_ADDRESS_IP *) + prParamNetAddr->aucAddress; + kalMemCopy(&prParamIpAddr->in_addr, + pucIp + (i * 4), 4); + prParamNetAddr = + (struct PARAM_NETWORK_ADDRESS *) + ((uint32_t) prParamNetAddr + + OFFSET_OF + (struct + PARAM_NETWORK_ADDRESS, + aucAddress) + + sizeof( + struct + PARAM_NETWORK_ADDRESS_IP + )); + u4Len += + OFFSET_OF(struct PARAM_NETWORK_ADDRESS, + aucAddress) + + sizeof( + struct + PARAM_NETWORK_ADDRESS_IP); + } + +#if 0 +#ifdef CONFIG_IPV6 + if (!wlanGetIPV6Address(prAdapter->prGlueInfo, pucIp, + &u4NumIPv6) + || (u4NumIPv6 + u4NumIPv4) > 3) { + goto bailout; + } + + pucIpv6 = kalMemAlloc(u4NumIPv6 * 16, VIR_MEM_TYPE); + + for (i = 0; i < u4NumIPv6; i++) { + prParamNetAddr->u2AddressLength = 6; + prParamNetAddr->u2AddressType = + PARAM_PROTOCOL_ID_TCP_IP; + kalMemCopy(prParamNetAddr->aucAddress, + pucIpv6 + (i * 16), + 16); + prParamNetAddr = + (struct PARAM_NETWORK_ADDRESS *) + ((uint32_t) prParamNetAddr + + sizeof(ip6)); + u4Len += OFFSET_OF(struct PARAM_NETWORK_ADDRESS, + aucAddress) + sizeof(ip6); + } +#endif +#endif + + ASSERT(u4Len <= bufSize); + + rStatus = wlanoidSetNetworkAddress(prAdapter, + (void *) prParamNetAddrList, + u4Len, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, + "set HW packet filter fail 0x%1x\n", + rStatus); + + /* TODO: replace 3 to marco */ + if (pucIp) + kalMemFree(pucIp, VIR_MEM_TYPE, 3 * 4); + if (pucBufIpAddr) + kalMemFree(pucBufIpAddr, VIR_MEM_TYPE, bufSize); + + } + break; +#endif + case SWCTRL_PS_DTIM_SKIP: + break; + case SWCTRL_ROAMING: + break; + default: + break; + } + } else { + switch (ucIndex) { + case SWCTRL_DEBUG: + break; + case SWCTRL_MAGIC: + g_au4SwCr[1] = _SWCTRL_MAGIC; + break; + case SWCTRL_QM_INFO: { + struct QUE_MGT *prQM = &prAdapter->rQM; + + switch (ucOpt0) { + case 0: +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + 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]; +#endif + break; + + case 1: +#if QM_FORWARDING_FAIRNESS + g_au4SwCr[1] = + prQM->au4ResourceUsedCount[ucOpt1]; + g_au4SwCr[2] = prQM->au4HeadStaRecIndex[ucOpt1]; +#endif + break; + + case 2: + /* only one */ + g_au4SwCr[1] = + prQM->arTxQueue[ucOpt1].u4NumElem; + + break; + } + } + break; + case SWCTRL_TX_CTRL_INFO: { + struct TX_CTRL *prTxCtrl; + + prTxCtrl = &prAdapter->rTxCtrl; + switch (ucOpt0) { + case 0: + g_au4SwCr[1] = + prAdapter->rTxCtrl.rTc. + au4FreeBufferCount[ucOpt1]; + g_au4SwCr[2] = + prAdapter->rTxCtrl.rTc. + au4MaxNumOfBuffer[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, GET_BSS_INFO_BY_INDEX(prAdapter, + ucOpt0)); + } + break; + + default: + break; + } + + } +} + +void swCtrlCmdCategory1(struct ADAPTER *prAdapter, + uint8_t ucCate, uint8_t ucAction, uint8_t ucOpt0, + uint8_t ucOpt1) +{ + uint8_t ucIndex, ucRead; + uint8_t ucWTEntry; + struct STA_RECORD *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->ucWlanIndex; + if (ucRead == SWCR_WRITE) { + /* ToDo:: Nothing */ + } else { + /* Read */ + switch (ucIndex) { + case SWCTRL_STA_QUE_INFO: { + g_au4SwCr[1] = prStaRec->arTxQueue[ucOpt1].u4NumElem; + } + break; + case SWCTRL_STA_INFO: + switch (ucOpt1) { + case 0: + g_au4SwCr[1] = prStaRec->fgIsInPS; + break; + } + + break; + + case SWCTRL_DUMP_STA: { + dumpSTA(prAdapter, prStaRec); + } + break; + + default: + + break; + } + } + +} + +#if TEST_PS + +void +testPsSendQoSNullFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN uint8_t ucUP, + IN uint8_t ucBssIndex, + IN u_int8_t fgBMC, + IN u_int8_t fgIsBurstEnd, IN u_int8_t ucPacketType, + IN u_int8_t ucPsSessionID, IN u_int8_t fgSetEOSP) +{ + struct MSDU_INFO *prMsduInfo; + uint16_t u2EstimatedFrameLen; + struct WLAN_MAC_HEADER_QOS *prQoSNullFrame; + + DEBUGFUNC("testPsSendQoSNullFrame"); + DBGLOG(SW4, LOUD, "\n"); + + /* 4 <1> Allocate a PKT_INFO_T for Null Frame */ + /* Init with MGMT Header Length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + + WLAN_MAC_HEADER_QOS_LEN; + + /* Allocate a MSDU_INFO_T */ + + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + + if (prMsduInfo == NULL) { + DBGLOG(SW4, WARN, + "No PKT_INFO_T for sending Null Frame.\n"); + return; + } + /* 4 <2> Compose Null frame in MSDU_INfO_T. */ + bssComposeQoSNullFrame(prAdapter, + (uint8_t *) ((unsigned long) (prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD), + prStaRec, ucUP, fgSetEOSP); + + TX_SET_MMPDU(prAdapter, + prMsduInfo, + ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_HEADER_QOS_LEN, + WLAN_MAC_HEADER_QOS_LEN, NULL, MSDU_RATE_MODE_AUTO); + + prMsduInfo->ucUserPriority = ucUP; + prMsduInfo->ucPacketType = ucPacketType; + + prQoSNullFrame = (struct WLAN_MAC_HEADER_QOS *) ((uint8_t *) + ((unsigned long) (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 struct ADAPTER *prAdapter, + IN uint8_t ucBssIndex) +{ + struct BSS_INFO *prBssInfo; + uint8_t _aucZeroMacAddr[] = NULL_MAC_ADDR; + + DEBUGFUNC("testPsSetupBss()"); + DBGLOG(SW4, INFO, "index %d\n", ucBssIndex); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + /* 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, prBssInfo); + + prBssInfo->eConnectionState = + PARAM_MEDIA_STATE_DISCONNECTED; + prBssInfo->eConnectionStateIndicated = + PARAM_MEDIA_STATE_DISCONNECTED; + prBssInfo->eCurrentOPMode = OP_MODE_ACCESS_POINT; + prBssInfo->fgIsNetActive = TRUE; + prBssInfo->ucBssIndex = ucBssIndex; + prBssInfo->ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_RESERVED; + + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = + PHY_TYPE_SET_802_11BG; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = + AP_MODE_MIXED_11BG; + 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->u2HwDefaultFixedRateCode = 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 = (struct STA_RECORD *) NULL; + + /* prBssInfo->fgErpProtectMode = eErpProectMode; */ + /* prBssInfo->eHtProtectMode = eHtProtectMode; */ + /* prBssInfo->eGfOperationMode = eGfOperationMode; */ + + /* 4 <4> Allocate MSDU_INFO_T for Beacon */ + prBssInfo->prBeacon = cnmMgtPktAlloc(prAdapter, + OFFSET_OF(struct WLAN_BEACON_FRAME, + aucInfoElem[0]) + MAX_IE_LENGTH); + + if (prBssInfo->prBeacon) { + prBssInfo->prBeacon->eSrc = TX_PACKET_MGMT; + prBssInfo->prBeacon->ucBssIndex = ucBssIndex; + } 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 = + (uint8_t) prAdapter->u4UapsdAcBmp; + prBssInfo->rPmProfSetupInfo.ucBmpTriggerAC = + (uint8_t) prAdapter->u4UapsdAcBmp; + prBssInfo->rPmProfSetupInfo.ucUapsdSp = (uint8_t) + prAdapter->u4MaxSpLen; +#endif + +#if 0 + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + + prBssInfo->arACQueParms[eAci].ucIsACMSet = FALSE; + prBssInfo->arACQueParms[eAci].u2Aifsn = (uint16_t) 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].ucIsACMSet, + prBssInfo->arACQueParms[eAci].u2Aifsn, + prBssInfo->arACQueParms[eAci].u2CWmin, + prBssInfo->arACQueParms[eAci].u2CWmax, + prBssInfo->arACQueParms[eAci].u2TxopLimit); + + } +#endif + + DBGLOG(SW4, INFO, + "[2] ucBmpDeliveryAC:0x%x, ucBmpTriggerAC:0x%x, ucUapsdSp:0x%x", + prBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC, + prBssInfo->rPmProfSetupInfo.ucBmpTriggerAC, + prBssInfo->rPmProfSetupInfo.ucUapsdSp); +} + +void testPsCmdCategory0(struct ADAPTER *prAdapter, + uint8_t ucCate, uint8_t ucAction, uint8_t ucOpt0, + uint8_t ucOpt1) +{ + uint8_t ucIndex, ucRead; + struct STA_RECORD *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, + /* UP */ + (uint8_t) (g_au4SwCr[1] & 0xFF), + /* BMC */ + ucOpt0, (u_int8_t) ((g_au4SwCr[1] >> 8) & 0xFF), + /* BurstEnd */ + (u_int8_t) ((g_au4SwCr[1] >> 16) & 0xFF), + /* Packet type */ + (u_int8_t) ((g_au4SwCr[1] >> 24) & 0xFF), + /* PS sesson ID 7: NOACK */ + (uint8_t) ((g_au4SwCr[2]) & 0xFF), + /* EOSP */ + FALSE + ); + } + break; + case TEST_PS_BUFFER_BMC: + 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(struct ADAPTER *prAdapter, + uint8_t ucCate, uint8_t ucAction, uint8_t ucOpt0, + uint8_t ucOpt1) +{ + uint8_t ucIndex, ucRead; + uint8_t ucWTEntry; + struct STA_RECORD *prStaRec; + + DEBUGFUNC("testPsCmdCategory1"); + + SWCR_GET_RW_INDEX(ucAction, ucRead, ucIndex); + + if (ucOpt0 >= CFG_STA_REC_NUM) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucOpt0); + + if (!prStaRec) { + DBGLOG(SW4, INFO, "prStaRec is NULL, ucOpt0:%d\n", ucOpt0); + return; + } + + ucWTEntry = prStaRec->ucWlanIndex; + if (ucRead == SWCR_WRITE) { + + switch (ucIndex) { + case TEST_PS_STA_PS: + prStaRec->fgIsInPS = (u_int8_t) (g_au4SwCr[1] & 0x1); + prStaRec->fgIsQoS = + (u_int8_t) (g_au4SwCr[1] >> 8 & 0xFF); + prStaRec->fgIsUapsdSupported = + (u_int8_t) (g_au4SwCr[1] >> 16 & 0xFF); + prStaRec->ucBmpDeliveryAC = + (u_int8_t) (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(struct ADAPTER *prAdapter, + uint8_t ucCate, uint8_t ucAction, uint8_t ucOpt0, + uint8_t ucOpt1) +{ + uint8_t ucIndex, ucRead; + struct STA_RECORD *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(struct ADAPTER *prAdapter, uint8_t ucRead, + uint16_t u2Addr, uint32_t *pu4Data) +{ + /* According other register STAIDX */ + uint8_t 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 */ + uint8_t ucCate; + uint32_t u4Cmd; + + u4Cmd = g_au4SwCr[0]; + ucCate = (uint8_t) (u4Cmd >> 24); + if (ucCate < ARRAY_SIZE(g_arSwCtrlCmd)) { + if (g_arSwCtrlCmd[ucCate] != NULL) { + g_arSwCtrlCmd[ucCate] ( + prAdapter, ucCate, + (uint8_t) (u4Cmd >> 16 & 0xFF), + (uint8_t) ((u4Cmd >> 8) & 0xFF), + (uint8_t) (u4Cmd & 0xFF)); + } + } + } + } else { + *pu4Data = g_au4SwCr[ucOffset]; + } +} + +void swCrReadWriteCmd(struct ADAPTER *prAdapter, + uint8_t ucRead, uint16_t u2Addr, uint32_t *pu4Data) +{ + uint8_t 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 < (ARRAY_SIZE(g_arSwCrModHandle))) { + + if (g_arSwCrModHandle[ucMod] != NULL) + g_arSwCrModHandle[ucMod] (prAdapter, ucRead, u2Addr, + pu4Data); + } /* ucMod */ +} + +/* Debug Support */ +void swCrFrameCheckEnable(struct ADAPTER *prAdapter, + uint32_t u4DumpType) +{ + g_u4SwcrDebugFrameDumpType = u4DumpType; +#if CFG_RX_PKTS_DUMP + prAdapter->rRxCtrl.u4RxPktsDumpTypeMask = u4DumpType; +#endif +} + +void swCrDebugInit(struct ADAPTER *prAdapter) +{ + /* frame dump */ + if (g_u4SwcrDebugFrameDumpType) + swCrFrameCheckEnable(prAdapter, g_u4SwcrDebugFrameDumpType); + /* debug counter */ + g_fgSwcrDebugTimer = FALSE; + + cnmTimerInitTimer(prAdapter, &g_rSwcrDebugTimer, + (PFN_MGMT_TIMEOUT_FUNC) swCrDebugCheckTimeout, + (unsigned long) NULL); + + if (g_u4SwcrDebugCheckTimeout) + swCrDebugCheckEnable(prAdapter, TRUE, + g_ucSwcrDebugCheckType, g_u4SwcrDebugCheckTimeout); +} + +void swCrDebugUninit(struct ADAPTER *prAdapter) +{ + cnmTimerStopTimer(prAdapter, &g_rSwcrDebugTimer); + + g_fgSwcrDebugTimer = FALSE; +} + +void swCrDebugCheckEnable(struct ADAPTER *prAdapter, + u_int8_t fgIsEnable, uint8_t ucType, uint32_t 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(struct ADAPTER *prAdapter, + struct CMD_SW_DBG_CTRL *prCmdSwCtrl) +{ + struct RX_CTRL *prRxCtrl; + struct TX_CTRL *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", + (uint32_t) TX_GET_CNT(prTxCtrl, + TX_INACTIVE_BSS_DROP), + (uint32_t) TX_GET_CNT(prTxCtrl, + TX_INACTIVE_STA_DROP), + (uint32_t) TX_GET_CNT(prTxCtrl, + TX_FORWARD_OVERFLOW_DROP), + (uint32_t) 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", + (uint32_t) RX_GET_CNT(prRxCtrl, + RX_MPDU_TOTAL_COUNT), + (uint32_t) RX_GET_CNT(prRxCtrl, + RX_DATA_INDICATION_COUNT), + (uint32_t) RX_GET_CNT(prRxCtrl, + RX_DATA_RETURNED_COUNT), + (uint32_t) RX_GET_CNT(prRxCtrl, + RX_DATA_RETAINED_COUNT), + (uint32_t) RX_GET_CNT(prRxCtrl, + RX_DROP_TOTAL_COUNT), + (uint32_t) RX_GET_CNT(prRxCtrl, + RX_TYPE_ERR_DROP_COUNT), + (uint32_t) RX_GET_CNT(prRxCtrl, + RX_CLASS_ERR_DROP_COUNT), + (uint32_t) 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 struct ADAPTER *prAdapter, + unsigned long ulParamPtr) +{ + struct CMD_SW_DBG_CTRL rCmdSwCtrl; + uint32_t 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(struct CMD_SW_DBG_CTRL), /* u4SetQueryInfoLen */ + (uint8_t *) &rCmdSwCtrl, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); +} + +void swCrDebugQuery(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo, IN uint8_t *pucEventBuf) +{ + ASSERT(prAdapter); + + swCrDebugCheck(prAdapter, + (struct CMD_SW_DBG_CTRL *) (pucEventBuf)); +} + +void swCrDebugQueryTimeout(IN struct ADAPTER *prAdapter, + IN struct CMD_INFO *prCmdInfo) +{ + ASSERT(prAdapter); + + swCrDebugCheck(prAdapter, NULL); +} + +#endif /* CFG_SUPPORT_SWCR */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/tdls.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/tdls.c new file mode 100644 index 0000000000000..9e8da301add4a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/tdls.c @@ -0,0 +1,1593 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: tdls.c#1 + */ + +/*! \file tdls.c + * \brief This file includes IEEE802.11z TDLS support. + */ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************* + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************* + */ +#include "precomp.h" + +#if CFG_SUPPORT_TDLS +#include "tdls.h" +#include "gl_cfg80211.h" +#include "queue.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 + ******************************************************************************* + */ +uint8_t g_arTdlsLink[MAXNUM_TDLS_PEER] = { + 0, + 0, + 0, + 0 + }; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************* + */ +static u_int8_t fgIsPtiTimeoutSkip = FALSE; + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ +#define ELEM_ID_LINK_IDENTIFIER_LENGTH 16 + +#define TDLS_KEY_TIMEOUT_INTERVAL 43200 + +#define UNREACH_ABLE 25 +#define TDLS_REASON_CODE_UNREACHABLE 25 +#define TDLS_REASON_CODE_UNSPECIFIED 26 + +#define WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE 25 +#define WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED 26 + +/******************************************************************************* + * 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 hadel TDLS link oper from nl80211. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[in] + * \param[in] + * \param[in] buf includes RSN IE + FT IE + Lifetimeout IE + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t TdlsexLinkMgt(struct ADAPTER *prAdapter, + void *pvSetBuffer, uint32_t u4SetBufferLen, + uint32_t *pu4SetInfoLen) +{ + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + + struct STA_RECORD *prStaRec; + struct BSS_INFO *prBssInfo; + struct TDLS_CMD_LINK_MGT *prCmd; + + prCmd = (struct TDLS_CMD_LINK_MGT *) pvSetBuffer; + prBssInfo = prAdapter->prAisBssInfo; + + DBGLOG(TDLS, INFO, "u4SetBufferLen=%d", u4SetBufferLen); + +#if 1 + /* AIS only */ + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + prStaRec = prBssInfo->prStaRecOfAP; + if (prStaRec == NULL) + return 0; + } else { + return -EINVAL; + } +#endif + + DBGLOG(TDLS, INFO, "prCmd->ucActionCode=%d, prCmd->ucDialogToken=%d", + prCmd->ucActionCode, prCmd->ucDialogToken); + + prStaRec = prBssInfo->prStaRecOfAP; + + switch (prCmd->ucActionCode) { + + case TDLS_FRM_ACTION_DISCOVERY_REQ: + if (prStaRec == NULL) + return 0; + if (TdlsDataFrameSend_DISCOVERY_REQ(prAdapter, + prStaRec, + prCmd->aucPeer, + prCmd->ucActionCode, + prCmd->ucDialogToken, + prCmd->u2StatusCode, + (uint8_t *) (prCmd->aucSecBuf), + prCmd->u4SecBufLen) + != TDLS_STATUS_SUCCESS) { + return -1; + } + + break; + + case TDLS_FRM_ACTION_SETUP_REQ: + if (prStaRec == NULL) + return 0; + prStaRec = cnmGetTdlsPeerByAddress(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, + prCmd->aucPeer); + g_arTdlsLink[prStaRec->ucTdlsIndex] = 0; + if (TdlsDataFrameSend_SETUP_REQ(prAdapter, + prStaRec, + prCmd->aucPeer, + prCmd->ucActionCode, + prCmd->ucDialogToken, + prCmd->u2StatusCode, + (uint8_t *) (prCmd->aucSecBuf), + prCmd->u4SecBufLen) + != TDLS_STATUS_SUCCESS) { + return -1; + } + + break; + + case TDLS_FRM_ACTION_SETUP_RSP: + /* fix sigma bug 5.2.4.2, 5.2.4.7, we sent Status code decline, + * but the sigma recogniezis it as scucess, and it will fail + */ + /* if(prCmd->u2StatusCode != 0) */ + if (prBssInfo->fgTdlsIsProhibited) + return 0; + + if (TdlsDataFrameSend_SETUP_RSP(prAdapter, + prStaRec, + prCmd->aucPeer, + prCmd->ucActionCode, + prCmd->ucDialogToken, + prCmd->u2StatusCode, + (uint8_t *) (prCmd->aucSecBuf), + prCmd->u4SecBufLen) + != TDLS_STATUS_SUCCESS) { + return -1; + } + + break; + + case TDLS_FRM_ACTION_DISCOVERY_RSP: + if (TdlsDataFrameSend_DISCOVERY_RSP(prAdapter, + prStaRec, + prCmd->aucPeer, + prCmd->ucActionCode, + prCmd->ucDialogToken, + prCmd->u2StatusCode, + (uint8_t *) (prCmd->aucSecBuf), + prCmd->u4SecBufLen) + != TDLS_STATUS_SUCCESS) { + return -1; + } + + break; + + case TDLS_FRM_ACTION_CONFIRM: + if (TdlsDataFrameSend_CONFIRM(prAdapter, + prStaRec, + prCmd->aucPeer, + prCmd->ucActionCode, + prCmd->ucDialogToken, + prCmd->u2StatusCode, + (uint8_t *) (prCmd->aucSecBuf), + prCmd->u4SecBufLen) + != TDLS_STATUS_SUCCESS) { + return -1; + } + break; + + case TDLS_FRM_ACTION_TEARDOWN: + + prStaRec = cnmGetTdlsPeerByAddress(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, + prCmd->aucPeer); + if (prCmd->u2StatusCode == TDLS_REASON_CODE_UNREACHABLE) + g_arTdlsLink[prStaRec->ucTdlsIndex] = 0; + + if (TdlsDataFrameSend_TearDown(prAdapter, + prStaRec, + prCmd->aucPeer, + prCmd->ucActionCode, + prCmd->ucDialogToken, + prCmd->u2StatusCode, + (uint8_t *) (prCmd->aucSecBuf), + prCmd->u4SecBufLen) + != TDLS_STATUS_SUCCESS) { + return -1; + } + break; + + default: + return -EINVAL; + } + + return 0; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to hadel TDLS link mgt from nl80211. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[in] + * \param[in] + * \param[in] buf includes RSN IE + FT IE + Lifetimeout IE + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t TdlsexLinkOper(struct ADAPTER *prAdapter, + void *pvSetBuffer, uint32_t u4SetBufferLen, + uint32_t *pu4SetInfoLen) +{ + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + uint16_t i; + struct STA_RECORD *prStaRec; + + struct TDLS_CMD_LINK_OPER *prCmd; + + prCmd = (struct TDLS_CMD_LINK_OPER *) pvSetBuffer; + + DBGLOG(TDLS, INFO, "prCmd->oper=%d, u4SetBufferLen=%d", + prCmd->oper, u4SetBufferLen); + + switch (prCmd->oper) { + + case TDLS_ENABLE_LINK: + + for (i = 0; i < MAXNUM_TDLS_PEER; i++) { + if (!g_arTdlsLink[i]) { + g_arTdlsLink[i] = 1; + prStaRec = + cnmGetTdlsPeerByAddress(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, + prCmd->aucPeerMac); + prStaRec->ucTdlsIndex = i; + break; + } + } + + break; + case TDLS_DISABLE_LINK: + + prStaRec = cnmGetTdlsPeerByAddress(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, + prCmd->aucPeerMac); + + g_arTdlsLink[prStaRec->ucTdlsIndex] = 0; + if (IS_DLS_STA(prStaRec)) + cnmStaRecFree(prAdapter, prStaRec); + + break; + default: + return 0; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is called to append general IEs. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[in] + * + * \retval append length + */ +/*----------------------------------------------------------------------------*/ +uint32_t TdlsFrameGeneralIeAppend(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, uint8_t *pPkt) +{ + struct GLUE_INFO *prGlueInfo; + struct BSS_INFO *prBssInfo; + struct PM_PROFILE_SETUP_INFO *prPmProfSetupInfo; + uint32_t u4NonHTPhyType; + uint16_t u2SupportedRateSet; + uint8_t aucAllSupportedRates[RATE_NUM_SW] = { 0 }; + uint8_t ucAllSupportedRatesLen; + uint8_t ucSupRatesLen; + uint8_t ucExtSupRatesLen; + uint32_t u4PktLen, u4IeLen; + + /* init */ + prGlueInfo = (struct GLUE_INFO *) prAdapter->prGlueInfo; + prBssInfo = prAdapter->prAisBssInfo; /* AIS only */ + + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + + /* 3. Frame Formation - (5) Supported Rates element */ + /* use all sup rate we can support */ + u4NonHTPhyType = prStaRec->ucNonHTBasicPhyType; + u2SupportedRateSet = + rNonHTPhyAttributes[u4NonHTPhyType].u2SupportedRateSet; + rateGetDataRatesFromRateSet(u2SupportedRateSet, 0, + aucAllSupportedRates, + &ucAllSupportedRatesLen); + + ucSupRatesLen = ((ucAllSupportedRatesLen > + ELEM_MAX_LEN_SUP_RATES) ? + ELEM_MAX_LEN_SUP_RATES : ucAllSupportedRatesLen); + + ucExtSupRatesLen = ucAllSupportedRatesLen - ucSupRatesLen; + + if (ucSupRatesLen) { + SUP_RATES_IE(pPkt)->ucId = ELEM_ID_SUP_RATES; + SUP_RATES_IE(pPkt)->ucLength = ucSupRatesLen; + kalMemCopy(SUP_RATES_IE(pPkt)->aucSupportedRates, + aucAllSupportedRates, ucSupRatesLen); + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + } + + /* 3. Frame Formation - (7) Extended sup rates element */ + if (ucExtSupRatesLen) { + + EXT_SUP_RATES_IE(pPkt)->ucId = ELEM_ID_EXTENDED_SUP_RATES; + EXT_SUP_RATES_IE(pPkt)->ucLength = ucExtSupRatesLen; + + kalMemCopy(EXT_SUP_RATES_IE(pPkt)->aucExtSupportedRates, + &aucAllSupportedRates[ucSupRatesLen], + ucExtSupRatesLen); + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + } + + /* 3. Frame Formation - (8) Supported channels element */ + SUPPORTED_CHANNELS_IE(pPkt)->ucId = ELEM_ID_SUP_CHS; + SUPPORTED_CHANNELS_IE(pPkt)->ucLength = 2; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[0] = 1; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[1] = 13; + + if (prAdapter->fgEnable5GBand == TRUE) { + SUPPORTED_CHANNELS_IE(pPkt)->ucLength = 10; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[2] = 36; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[3] = 4; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[4] = 52; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[5] = 4; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[6] = 149; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[7] = 4; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[8] = 165; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[9] = 1; + } + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + + return u4PktLen; +} + +/*! + * \brief This routine is called to transmit a TDLS data frame. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[in] + * \param[in] + * \param[in] buf includes RSN IE + FT IE + Lifetimeout IE + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t +TdlsDataFrameSend_TearDown(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t *pPeerMac, + uint8_t ucActionCode, + uint8_t ucDialogToken, uint16_t u2StatusCode, + uint8_t *pAppendIe, uint32_t AppendIeLen) +{ + + struct GLUE_INFO *prGlueInfo; + struct BSS_INFO *prBssInfo; + struct PM_PROFILE_SETUP_INFO *prPmProfSetupInfo; + struct sk_buff *prMsduInfo; + uint8_t *pPkt; + uint32_t u4PktLen, u4IeLen; + uint16_t ReasonCode; + + /* allocate/init packet */ + prGlueInfo = (struct GLUE_INFO *) prAdapter->prGlueInfo; + prBssInfo = prAdapter->prAisBssInfo; /* AIS only */ + + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + + prMsduInfo = kalPacketAllocWithHeadroom(prGlueInfo, 1600, + &pPkt); + if (prMsduInfo == NULL) + return TDLS_STATUS_RESOURCES; + + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + kalPacketFree(prGlueInfo, prMsduInfo); + return TDLS_STATUS_FAIL; + } + + /* make up frame content */ + /* 1. 802.3 header */ + kalMemCopy(pPkt, pPeerMac, TDLS_FME_MAC_ADDR_LEN); + pPkt += TDLS_FME_MAC_ADDR_LEN; + kalMemCopy(pPkt, prAdapter->rMyMacAddr, + TDLS_FME_MAC_ADDR_LEN); + pPkt += TDLS_FME_MAC_ADDR_LEN; + *(uint16_t *) pPkt = htons(TDLS_FRM_PROT_TYPE); + pPkt += 2; + u4PktLen += TDLS_FME_MAC_ADDR_LEN * 2 + 2; + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + pPkt++; + u4PktLen++; + + /* 3. Frame Formation - (1) Category */ + *pPkt = TDLS_FRM_CATEGORY; + pPkt++; + u4PktLen++; + + /* 3. Frame Formation - (2) Action */ + *pPkt = ucActionCode; + pPkt++; + u4PktLen++; + + /* 3. Frame Formation - status code */ + + ReasonCode = u2StatusCode; + + + kalMemCopy(pPkt, &ReasonCode, 2); + pPkt = pPkt + 2; + u4PktLen = u4PktLen + 2; + + if (pAppendIe != NULL) { + if ((ucActionCode != TDLS_FRM_ACTION_TEARDOWN) || + ((ucActionCode == TDLS_FRM_ACTION_TEARDOWN) + && (prStaRec != NULL))) { + kalMemCopy(pPkt, pAppendIe, AppendIeLen); + LR_TDLS_FME_FIELD_FILL(AppendIeLen); + } + } + + /* 7. Append Supported Operating Classes IE */ + if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { + /* Note: if we do not put the IE, Marvell STA will + * decline our TDLS setup request + */ + u4IeLen = rlmDomainSupOperatingClassIeFill(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } + + /* 3. Frame Formation - (16) Link identifier element */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = + ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, + prBssInfo->aucBSSID, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, + prAdapter->rMyMacAddr, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, + pPeerMac, 6); + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + + /* 5. Update packet length */ + prMsduInfo->len = u4PktLen; + + /* if(u2StatusCode == UNREACH_ABLE ){ */ + /* g_arTdlsLink[prStaRec->ucTdlsIndex] = FALSE; */ + /* } */ + + + /* 5. send the data frame */ + wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); + + return TDLS_STATUS_SUCCESS; +} + +/*! + * \brief This routine is called to transmit a TDLS data frame. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[in] + * \param[in] + * \param[in] buf includes RSN IE + FT IE + Lifetimeout IE + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t /* TDLS_STATUS */ +TdlsDataFrameSend_SETUP_REQ(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t *pPeerMac, + uint8_t ucActionCode, + uint8_t ucDialogToken, uint16_t u2StatusCode, + uint8_t *pAppendIe, uint32_t AppendIeLen) +{ + + struct GLUE_INFO *prGlueInfo; + struct BSS_INFO *prBssInfo; + struct PM_PROFILE_SETUP_INFO *prPmProfSetupInfo; + struct sk_buff *prMsduInfo; + uint8_t *pPkt; + uint32_t u4PktLen, u4IeLen; + uint16_t u2CapInfo; + + /* allocate/init packet */ + prGlueInfo = (struct GLUE_INFO *) prAdapter->prGlueInfo; + prBssInfo = prAdapter->prAisBssInfo; + + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + + if (prStaRec == NULL) + return TDLS_STATUS_FAIL; + + prMsduInfo = kalPacketAllocWithHeadroom(prGlueInfo, 512, &pPkt); + if (prMsduInfo == NULL) + return TDLS_STATUS_RESOURCES; + + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + kalPacketFree(prGlueInfo, prMsduInfo); + return TDLS_STATUS_FAIL; + } + + /* make up frame content */ + /* 1. 802.3 header */ + kalMemCopy(pPkt, pPeerMac, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(pPkt, prBssInfo->aucOwnMacAddr, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + *(uint16_t *) pPkt = htons(TDLS_FRM_PROT_TYPE); + LR_TDLS_FME_FIELD_FILL(2); + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + LR_TDLS_FME_FIELD_FILL(1); + + /* + * 3.1 Category + * 3.2 Action + * 3.3 Dialog Token + * 3.4 Capability + * 3.5 Supported rates + * 3.6 Country + * 3.7 Extended supported rates + * 3.8 Supported Channels (optional) + * 3.9 RSNIE (optional) + * 3.10 Extended Capabilities + * 3.11 QoS Capability + * 3.12 FTIE (optional) + * 3.13 Timeout Interval (optional) + * 3.14 Supported Regulatory Classes (optional) + * 3.15 HT Capabilities + * 3.16 20/40 BSS Coexistence + * 3.17 Link Identifier + */ + + /* 3.1 Category */ + *pPkt = TDLS_FRM_CATEGORY; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3.2 Action */ + *pPkt = ucActionCode; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3.3 Dialog Token */ + *pPkt = ucDialogToken; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3.4 Capability */ + u2CapInfo = assocBuildCapabilityInfo(prAdapter, prStaRec); + WLAN_SET_FIELD_16(pPkt, u2CapInfo); + LR_TDLS_FME_FIELD_FILL(2); + + /* + * 3.5 Supported rates + * 3.7 Extended supported rates + * 3.8 Supported Channels (optional) + */ + u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, prStaRec, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3.6 Country */ + /* 3.14 Supported Regulatory Classes (optional) */ + /* Note: if we do not put the IE, Marvell STA will decline + * our TDLS setup request + */ + u4IeLen = rlmDomainSupOperatingClassIeFill(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3.10 Extended Capabilities */ + EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP; + EXT_CAP_IE(pPkt)->ucLength = 5; + + EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */ + EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */ + EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */ + + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24)); + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24)); + EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32)); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* Append extra IEs */ + /* + * 3.9 RSNIE (optional) + * 3.12 FTIE (optional) + * 3.13 Timeout Interval (optional) + */ + if (pAppendIe != NULL) { + kalMemCopy(pPkt, pAppendIe, AppendIeLen); + LR_TDLS_FME_FIELD_FILL(AppendIeLen); + } + + /* 3.11 QoS Capability */ + /* HT WMM IE append */ + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) { + u4IeLen = mqmGenerateWmmInfoIEByStaRec(prAdapter, prBssInfo, + prStaRec, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + u4IeLen = mqmGenerateWmmParamIEByParam(prAdapter, prBssInfo, + pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } + + /* 3.15 HT Capabilities */ + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & + PHY_TYPE_SET_802_11N)) { + u4IeLen = rlmFillHtCapIEByAdapter(prAdapter, prBssInfo, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } +#if CFG_SUPPORT_802_11AC + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & + PHY_TYPE_SET_802_11AC) { + u4IeLen = rlmFillVhtCapIEByAdapter(prAdapter, prBssInfo, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } +#endif + + /* 3.16 20/40 BSS Coexistence */ + BSS_20_40_COEXIST_IE(pPkt)->ucId = ELEM_ID_20_40_BSS_COEXISTENCE; + BSS_20_40_COEXIST_IE(pPkt)->ucLength = 1; + BSS_20_40_COEXIST_IE(pPkt)->ucData = 0x01; + LR_TDLS_FME_FIELD_FILL(3); + + /* 3.17 Link Identifier */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, + prBssInfo->aucBSSID, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, + prAdapter->rMyMacAddr, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, + pPeerMac, 6); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 4. Update packet length */ + prMsduInfo->len = u4PktLen; + + DBGLOG(TDLS, INFO, "wlanHardStartXmit, u4PktLen=%d", u4PktLen); + + /* 5. send the data frame */ + wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); + + return TDLS_STATUS_SUCCESS; +} + +uint32_t +TdlsDataFrameSend_SETUP_RSP(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t *pPeerMac, + uint8_t ucActionCode, + uint8_t ucDialogToken, uint16_t u2StatusCode, + uint8_t *pAppendIe, uint32_t AppendIeLen) +{ + struct GLUE_INFO *prGlueInfo; + struct BSS_INFO *prBssInfo; + struct PM_PROFILE_SETUP_INFO *prPmProfSetupInfo; + struct sk_buff *prMsduInfo; + uint8_t *pPkt; + uint32_t u4PktLen, u4IeLen; + uint16_t u2CapInfo; + + /* allocate/init packet */ + prGlueInfo = (struct GLUE_INFO *) prAdapter->prGlueInfo; + prBssInfo = prAdapter->prAisBssInfo; + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + + if (prStaRec == NULL) + return TDLS_STATUS_FAIL; + + prMsduInfo = kalPacketAllocWithHeadroom(prGlueInfo, 512, &pPkt); + if (prMsduInfo == NULL) + return TDLS_STATUS_RESOURCES; + + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + kalPacketFree(prGlueInfo, prMsduInfo); + return TDLS_STATUS_FAIL; + } + + /* make up frame content */ + /* 1. 802.3 header */ + kalMemCopy(pPkt, pPeerMac, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(pPkt, prBssInfo->aucOwnMacAddr, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + *(uint16_t *) pPkt = htons(TDLS_FRM_PROT_TYPE); + LR_TDLS_FME_FIELD_FILL(2); + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + LR_TDLS_FME_FIELD_FILL(1); + + /* + * 3.1 Category + * 3.2 Action + * 3.3 Status Code + * 3.4 Dialog Token + *** Below IE should be only included for Status Code=0 (Successful) + * 3.5 Capability + * 3.6 Supported rates + * 3.7 Country + * 3.8 Extended supported rates + * 3.9 Supported Channels (optional) + * 3.10 RSNIE (optional) + * 3.11 Extended Capabilities + * 3.12 QoS Capability + * 3.13 FTIE (optional) + * 3.14 Timeout Interval (optional) + * 3.15 Supported Regulatory Classes (optional) + * 3.16 HT Capabilities + * 3.17 20/40 BSS Coexistence + * 3.18 Link Identifier + */ + + /* 3.1 Category */ + *pPkt = TDLS_FRM_CATEGORY; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3.2 Action */ + *pPkt = ucActionCode; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3.3 Status Code */ + kalMemCopy(pPkt, &u2StatusCode, 2); + LR_TDLS_FME_FIELD_FILL(2); + + /* 3.4 Dialog Token */ + *pPkt = ucDialogToken; + LR_TDLS_FME_FIELD_FILL(1); + + if (u2StatusCode == 0) { + /* 3.5 Capability */ + u2CapInfo = assocBuildCapabilityInfo(prAdapter, prStaRec); + WLAN_SET_FIELD_16(pPkt, u2CapInfo); + LR_TDLS_FME_FIELD_FILL(2); + + /* + * 3.6 Supported rates + * 3.8 Extended supported rates + * 3.9 Supported Channels (optional) + */ + u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, prStaRec, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3.7 Country */ + /* 3.15 Supported Regulatory Classes (optional) */ + /* Note: if we do not put the IE, Marvell STA will decline + * our TDLS setup request + */ + u4IeLen = rlmDomainSupOperatingClassIeFill(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3.11 Extended Capabilities */ + EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP; + EXT_CAP_IE(pPkt)->ucLength = 5; + + EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */ + EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */ + EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */ + + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24)); + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24)); + EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32)); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3.12 QoS Capability */ + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) { + /* Add WMM IE *//* try to reuse p2p path */ + u4IeLen = mqmGenerateWmmInfoIEByStaRec(prAdapter, + prBssInfo, prStaRec, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + u4IeLen = mqmGenerateWmmParamIEByParam(prAdapter, + prBssInfo, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } + + /* 3.16 HT Capabilities */ + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & + PHY_TYPE_SET_802_11N) { + u4IeLen = rlmFillHtCapIEByAdapter(prAdapter, prBssInfo, + pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } +#if CFG_SUPPORT_802_11AC + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & + PHY_TYPE_SET_802_11AC) { + u4IeLen = rlmFillVhtCapIEByAdapter(prAdapter, prBssInfo, + pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } +#endif + + /* 3.17 20/40 BSS Coexistence */ + BSS_20_40_COEXIST_IE(pPkt)->ucId = + ELEM_ID_20_40_BSS_COEXISTENCE; + BSS_20_40_COEXIST_IE(pPkt)->ucLength = 1; + BSS_20_40_COEXIST_IE(pPkt)->ucData = 0x01; + LR_TDLS_FME_FIELD_FILL(3); + + /* 3.18 Link Identifier */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, + prBssInfo->aucBSSID, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, + pPeerMac, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, + prAdapter->rMyMacAddr, 6); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* Append extra IEs */ + /* + * 3.10 RSNIE (optional) + * 3.13 FTIE (optional) + * 3.14 Timeout Interval (optional) + */ + if (pAppendIe != NULL) { + kalMemCopy(pPkt, pAppendIe, AppendIeLen); + LR_TDLS_FME_FIELD_FILL(AppendIeLen); + } + } + + /* 4. Update packet length */ + prMsduInfo->len = u4PktLen; + + /* 5. send the data frame */ + wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); + + return TDLS_STATUS_SUCCESS; +} + +uint32_t +TdlsDataFrameSend_CONFIRM(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t *pPeerMac, + uint8_t ucActionCode, + uint8_t ucDialogToken, uint16_t u2StatusCode, + uint8_t *pAppendIe, uint32_t AppendIeLen) +{ + + struct GLUE_INFO *prGlueInfo; + struct BSS_INFO *prBssInfo; + struct PM_PROFILE_SETUP_INFO *prPmProfSetupInfo; + struct sk_buff *prMsduInfo; + uint8_t *pPkt; + uint32_t u4PktLen, u4IeLen; + + /* allocate/init packet */ + prGlueInfo = (struct GLUE_INFO *) prAdapter->prGlueInfo; + prBssInfo = prAdapter->prAisBssInfo; + + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + + prMsduInfo = kalPacketAllocWithHeadroom(prGlueInfo, 512, &pPkt); + if (prMsduInfo == NULL) + return TDLS_STATUS_RESOURCES; + + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + kalPacketFree(prGlueInfo, prMsduInfo); + return TDLS_STATUS_FAIL; + } + + /* make up frame content */ + /* 1. 802.3 header */ + kalMemCopy(pPkt, pPeerMac, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(pPkt, prBssInfo->aucOwnMacAddr, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + *(uint16_t *) pPkt = htons(TDLS_FRM_PROT_TYPE); + LR_TDLS_FME_FIELD_FILL(2); + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + LR_TDLS_FME_FIELD_FILL(1); + + /* + * 3.1 Category + * 3.2 Action + * 3.3 Status Code + * 3.4 Dialog Token + *** 3.5 - 3.9 should be only included for Status Code=0 (Successful) + * 3.5 RSNIE (optional) + * 3.6 EDCA Parameter Set + * 3.7 FTIE (optional) + * 3.8 Timeout Interval (optional) + * 3.9 HT Operation (optional) + * 3.10 Link Identifier + */ + + /* 3.1 Category */ + *pPkt = TDLS_FRM_CATEGORY; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3.2 Action */ + *pPkt = ucActionCode; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3.3 Status Code */ + kalMemCopy(pPkt, &u2StatusCode, 2); + LR_TDLS_FME_FIELD_FILL(2); + + /* 3.4 Dialog Token */ + *pPkt = ucDialogToken; + LR_TDLS_FME_FIELD_FILL(1); + + if (u2StatusCode == 0) { + /* + * 3.5 RSNIE (optional) + * 3.7 FTIE (optional) + * 3.8 Timeout Interval (optional) + */ + if (pAppendIe) { + kalMemCopy(pPkt, pAppendIe, AppendIeLen); + LR_TDLS_FME_FIELD_FILL(AppendIeLen); + } + + /* 3.6 EDCA Parameter Set */ + /* HT WMM IE append */ + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) { + u4IeLen = mqmGenerateWmmInfoIEByStaRec(prAdapter, + prBssInfo, prStaRec, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + u4IeLen = mqmGenerateWmmParamIEByParam(prAdapter, + prBssInfo, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } + } + + /* 3.10 Link Identifier */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, + prBssInfo->aucBSSID, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, + prAdapter->rMyMacAddr, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, + pPeerMac, 6); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 4. Update packet length */ + prMsduInfo->len = u4PktLen; + + /* 5. send the data frame */ + wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); + + return TDLS_STATUS_SUCCESS; +} + +/* + * \brief This routine is called to transmit a TDLS data frame. + * + * \param[in] pvAdapter Pointer to the Adapter structure. + * \param[in] + * \param[in] + * \param[in] buf includes RSN IE + FT IE + Lifetimeout IE + * + * \retval WLAN_STATUS_SUCCESS + * \retval WLAN_STATUS_INVALID_LENGTH + */ +/*----------------------------------------------------------------------------*/ +uint32_t /* TDLS_STATUS */ +TdlsDataFrameSend_DISCOVERY_REQ(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t *pPeerMac, + uint8_t ucActionCode, + uint8_t ucDialogToken, uint16_t u2StatusCode, + uint8_t *pAppendIe, uint32_t AppendIeLen) +{ + struct GLUE_INFO *prGlueInfo; + struct BSS_INFO *prBssInfo; + struct PM_PROFILE_SETUP_INFO *prPmProfSetupInfo; + struct sk_buff *prMsduInfo; + struct MSDU_INFO *prMsduInfoMgmt; + uint8_t *pPkt, *pucInitiator, *pucResponder; + uint32_t u4PktLen, u4IeLen; + + prGlueInfo = (struct GLUE_INFO *) prAdapter->prGlueInfo; + + if (prStaRec != NULL) + prBssInfo = prAdapter->prAisBssInfo; + else + return TDLS_STATUS_FAIL; + + /* allocate/init packet */ + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + prMsduInfo = NULL; + prMsduInfoMgmt = NULL; + + /* make up frame content */ + prMsduInfo = kalPacketAllocWithHeadroom(prGlueInfo, 512, &pPkt); + if (prMsduInfo == NULL) + return TDLS_STATUS_RESOURCES; + + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + kalPacketFree(prGlueInfo, prMsduInfo); + return TDLS_STATUS_FAIL; + } + + /* 1. 802.3 header */ + kalMemCopy(pPkt, pPeerMac, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(pPkt, prBssInfo->aucOwnMacAddr, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + *(uint16_t *) pPkt = htons(TDLS_FRM_PROT_TYPE); + LR_TDLS_FME_FIELD_FILL(2); + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + LR_TDLS_FME_FIELD_FILL(1); + + /* + * 3.1 Category + * 3.2 Action + * 3.3 Dialog Token + * 3.4 Link Identifier + */ + + /* 3.1 Category */ + *pPkt = TDLS_FRM_CATEGORY; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3.2 Action */ + *pPkt = ucActionCode; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3.3 Dialog Token */ + *pPkt = ucDialogToken; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3.4 Link Identifier */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, + prBssInfo->aucBSSID, 6); + pucInitiator = prBssInfo->aucOwnMacAddr; + pucResponder = pPeerMac; + prStaRec->flgTdlsIsInitiator = TRUE; + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, pucInitiator, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, pucResponder, 6); + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 4. Update packet length */ + prMsduInfo->len = u4PktLen; + + /* 5. send the data frame */ + wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); + + return TDLS_STATUS_SUCCESS; +} + +uint32_t +TdlsDataFrameSend_DISCOVERY_RSP(struct ADAPTER *prAdapter, + struct STA_RECORD *prStaRec, + uint8_t *pPeerMac, + uint8_t ucActionCode, + uint8_t ucDialogToken, uint16_t u2StatusCode, + uint8_t *pAppendIe, uint32_t AppendIeLen) +{ + struct GLUE_INFO *prGlueInfo; + struct BSS_INFO *prBssInfo; + struct PM_PROFILE_SETUP_INFO *prPmProfSetupInfo; + struct MSDU_INFO *prMsduInfoMgmt; + uint8_t *pPkt, *pucInitiator, *pucResponder; + uint32_t u4PktLen, u4IeLen; + uint16_t u2CapInfo; + struct WLAN_MAC_HEADER *prHdr; + + prGlueInfo = (struct GLUE_INFO *) prAdapter->prGlueInfo; + + /* sanity check */ + if (prStaRec != NULL) + prBssInfo = prAdapter->prAisBssInfo; + else + return TDLS_STATUS_FAIL; + + /* allocate/init packet */ + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + prMsduInfoMgmt = NULL; + + /* make up frame content */ + prMsduInfoMgmt = (struct MSDU_INFO *) cnmMgtPktAlloc(prAdapter, + PUBLIC_ACTION_MAX_LEN); + if (prMsduInfoMgmt == NULL) + return TDLS_STATUS_RESOURCES; + + pPkt = (uint8_t *) prMsduInfoMgmt->prPacket; + prHdr = (struct WLAN_MAC_HEADER *) pPkt; + + /* 1. 802.11 header */ + prHdr->u2FrameCtrl = MAC_FRAME_ACTION; + prHdr->u2DurationID = 0; + kalMemCopy(prHdr->aucAddr1, pPeerMac, TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(prHdr->aucAddr2, prBssInfo->aucOwnMacAddr, + TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(prHdr->aucAddr3, prBssInfo->aucBSSID, TDLS_FME_MAC_ADDR_LEN); + prHdr->u2SeqCtrl = 0; + LR_TDLS_FME_FIELD_FILL(sizeof(struct WLAN_MAC_HEADER)); + + + /* + * 3.1 Category + * 3.2 Action + * 3.3 Dialog Token + * 3.4 Capability + * 3.5 Supported rates + * 3.6 Extended supported rates + * 3.7 Supported Channels (optional) + * 3.8 RSNIE + * 3.9 Extended Capabilities + * 3.10 FTIE + * 3.11 Timeout Interval (optional) + * 3.12 Supported Regulatory Classes (optional) + * 3.13 HT Capabilities + * 3.14 20/40 BSS Coexistence + * 3.15 Link Identifier + */ + + /* 3.1 Category */ + *pPkt = CATEGORY_PUBLIC_ACTION; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3.2 Action */ + *pPkt = ucActionCode; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3.3 Dialog Token */ + *pPkt = ucDialogToken; + LR_TDLS_FME_FIELD_FILL(1); + + + /* 3.4 Capability */ + u2CapInfo = assocBuildCapabilityInfo(prAdapter, prStaRec); + WLAN_SET_FIELD_16(pPkt, u2CapInfo); + LR_TDLS_FME_FIELD_FILL(2); + + /* + * 3.5 Supported rates + * 3.6 Extended supported rates + * 3.7 Supported Channels (optional) + */ + u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, prStaRec, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3.9 Extended Capabilities */ + EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP; + EXT_CAP_IE(pPkt)->ucLength = 5; + + EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */ + EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */ + EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */ + + /* bit 28 TDLS_EX_CAP_PEER_UAPSD */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24)); + /* bit 30 TDLS_EX_CAP_CHAN_SWITCH */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24)); + /* bit 37 TDLS_EX_CAP_TDLS */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32)); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* + * 3.8 RSNIE + * 3.10 FTIE + * 3.11 Timeout Interval (optional) + */ + if (pAppendIe != NULL) { + kalMemCopy(pPkt, pAppendIe, AppendIeLen); + LR_TDLS_FME_FIELD_FILL(AppendIeLen); + } + + /* 3.12 Supported Regulatory Classes (optional) */ + /* Note: if we do not put the IE, Marvell STA will + * decline our TDLS setup request + */ + u4IeLen = rlmDomainSupOperatingClassIeFill(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3.13 HT Capabilities */ + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) { + u4IeLen = rlmFillHtCapIEByAdapter(prAdapter, prBssInfo, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } +#if CFG_SUPPORT_802_11AC + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AC) { + u4IeLen = rlmFillVhtCapIEByAdapter(prAdapter, prBssInfo, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } +#endif + + /* 3.14 20/40 BSS Coexistence */ + BSS_20_40_COEXIST_IE(pPkt)->ucId = ELEM_ID_20_40_BSS_COEXISTENCE; + BSS_20_40_COEXIST_IE(pPkt)->ucLength = 1; + BSS_20_40_COEXIST_IE(pPkt)->ucData = 0x01; + LR_TDLS_FME_FIELD_FILL(3); + + /* 3.15 Link Identifier */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, + prBssInfo->aucBSSID, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, + pPeerMac, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, + prAdapter->rMyMacAddr, 6); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + pucInitiator = pPeerMac; + pucResponder = prBssInfo->aucOwnMacAddr; + if (prStaRec != NULL) + prStaRec->flgTdlsIsInitiator = FALSE; + + if (prMsduInfoMgmt != NULL) { + prMsduInfoMgmt->ucPacketType = TX_PACKET_TYPE_MGMT; + prMsduInfoMgmt->ucStaRecIndex = + prBssInfo->prStaRecOfAP->ucIndex; + prMsduInfoMgmt->ucBssIndex = prBssInfo->ucBssIndex; + prMsduInfoMgmt->ucMacHeaderLength = + WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfoMgmt->fgIs802_1x = FALSE; + prMsduInfoMgmt->fgIs802_11 = TRUE; + prMsduInfoMgmt->u2FrameLength = u4PktLen; + prMsduInfoMgmt->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfoMgmt->pfTxDoneHandler = NULL; + + /* Send them to HW queue */ + nicTxEnqueueMsdu(prAdapter, prMsduInfoMgmt); + } + + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to send a command to TDLS module. + * + * \param[in] prGlueInfo Pointer to the Adapter structure + * \param[in] prInBuf A pointer to the command string buffer + * \param[in] u4InBufLen The length of the buffer + * \param[out] None + * + * \retval None + */ +/*----------------------------------------------------------------------------*/ +void TdlsexEventHandle(struct GLUE_INFO *prGlueInfo, + uint8_t *prInBuf, uint32_t u4InBufLen) +{ + uint32_t u4EventId; + + DBGLOG(TDLS, INFO, "TdlsexEventHandle\n"); + + /* sanity check */ + if ((prGlueInfo == NULL) || (prInBuf == NULL)) + return; /* shall not be here */ + + /* handle */ + u4EventId = *(uint32_t *) prInBuf; + u4InBufLen -= 4; + + switch (u4EventId) { + case TDLS_HOST_EVENT_TEAR_DOWN: + DBGLOG(TDLS, INFO, "TDLS_HOST_EVENT_TEAR_DOWN\n"); + TdlsEventTearDown(prGlueInfo, prInBuf + 4, u4InBufLen); + break; + + case TDLS_HOST_EVENT_TX_DONE: + + break; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to do tear down. + * + * \param[in] prGlueInfo Pointer to the Adapter structure + * \param[in] prInBuf A pointer to the command string buffer, + * from u4EventSubId + * \param[in] u4InBufLen The length of the buffer + * \param[out] None + * + * \retval None + * + */ +/*----------------------------------------------------------------------------*/ +void TdlsEventTearDown(struct GLUE_INFO *prGlueInfo, + uint8_t *prInBuf, uint32_t u4InBufLen) +{ + struct STA_RECORD *prStaRec; + uint16_t u2ReasonCode = TDLS_REASON_CODE_NONE; + uint32_t u4TearDownSubId; + uint8_t *pMac, aucZeroMac[6]; + + /* init */ + u4TearDownSubId = *(uint32_t *) prInBuf; + kalMemZero(aucZeroMac, sizeof(aucZeroMac)); + pMac = aucZeroMac; + + prStaRec = cnmGetStaRecByIndex(prGlueInfo->prAdapter, + *(prInBuf + 4)); + + /* sanity check */ + if (prStaRec == NULL) + return; + + pMac = prStaRec->aucMacAddr; + + if (fgIsPtiTimeoutSkip == TRUE) { + /* skip PTI timeout event */ + if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_TIMEOUT) + return; + } + + if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_TIMEOUT) { + DBGLOG(TDLS, INFO, + "TDLS_HOST_EVENT_TD_PTI_TIMEOUT TDLS_REASON_CODE_UNSPECIFIED\n"); + u2ReasonCode = TDLS_REASON_CODE_UNSPECIFIED; + + cfg80211_tdls_oper_request(prGlueInfo->prDevHandler, + prStaRec->aucMacAddr, + NL80211_TDLS_TEARDOWN, + WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE, + GFP_ATOMIC); + } + + if (u4TearDownSubId == TDLS_HOST_EVENT_TD_AGE_TIMEOUT) { + DBGLOG(TDLS, INFO, + "TDLS_HOST_EVENT_TD_AGE_TIMEOUT TDLS_REASON_CODE_UNREACHABLE\n"); + u2ReasonCode = TDLS_REASON_CODE_UNREACHABLE; + + cfg80211_tdls_oper_request(prGlueInfo->prDevHandler, + prStaRec->aucMacAddr, NL80211_TDLS_TEARDOWN, + WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE, + GFP_ATOMIC); + + } + + DBGLOG(TDLS, INFO, "\n\n u2ReasonCode = %u\n\n", + u2ReasonCode); +} + +void TdlsBssExtCapParse(struct STA_RECORD *prStaRec, + uint8_t *pucIE) +{ + uint8_t *pucIeExtCap; + + /* sanity check */ + if ((prStaRec == NULL) || (pucIE == NULL)) + return; + + if (IE_ID(pucIE) != ELEM_ID_EXTENDED_CAP) + return; + + /* + * from bit0 ~ + * bit 38: TDLS Prohibited + * The TDLS Prohibited subfield indicates whether the use of TDLS is + * prohibited. + * The field is set to 1 to indicate that TDLS is prohibited + * and to 0 to indicate that TDLS is allowed. + */ + if (IE_LEN(pucIE) < 5) + return; /* we need 39/8 = 5 bytes */ + + /* init */ + prStaRec->fgTdlsIsProhibited = FALSE; + prStaRec->fgTdlsIsChSwProhibited = FALSE; + + /* parse */ + pucIeExtCap = pucIE + 2; + pucIeExtCap += 4; /* shift to the byte we care about */ + + if ((*pucIeExtCap) & BIT(38 - 32)) + prStaRec->fgTdlsIsProhibited = TRUE; + if ((*pucIeExtCap) & BIT(39 - 32)) + prStaRec->fgTdlsIsChSwProhibited = TRUE; + +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Generate CMD_ID_SET_TDLS_CH_SW command + * + * \param[in] + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +uint32_t +TdlsSendChSwControlCmd(struct ADAPTER *prAdapter, + void *pvSetBuffer, uint32_t u4SetBufferLen, + uint32_t *pu4SetInfoLen) +{ + + struct CMD_TDLS_CH_SW rCmdTdlsChSwCtrl; + + ASSERT(prAdapter); + + /* send command packet for scan */ + kalMemZero(&rCmdTdlsChSwCtrl, + sizeof(struct CMD_TDLS_CH_SW)); + + rCmdTdlsChSwCtrl.fgIsTDLSChSwProhibit = + prAdapter->prAisBssInfo->fgTdlsIsChSwProhibited; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_TDLS_CH_SW, + TRUE, + FALSE, FALSE, NULL, NULL, + sizeof(struct CMD_TDLS_CH_SW), + (uint8_t *)&rCmdTdlsChSwCtrl, NULL, 0); + return TDLS_STATUS_SUCCESS; +} + +uint32_t +TdlsTxCtrl(struct ADAPTER *prAdapter, + struct BSS_INFO *prBssInfo, u_int8_t fgEnable) +{ + int i; + struct STA_RECORD *prStaRec; + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + + if (prStaRec->eStaType != STA_TYPE_DLS_PEER) + continue; + + if (prStaRec->fgIsInUse && prStaRec->ucBssIndex + == prBssInfo->ucBssIndex) { + qmSetStaRecTxAllowed(prAdapter, prStaRec, fgEnable); + DBGLOG(TDLS, EVENT, "TDLS STA[%d], TX ctrl=%d\n", + i, fgEnable); + } + } + + return TDLS_STATUS_SUCCESS; +} +#endif /* CFG_SUPPORT_TDLS */ + +/* End of tdls.c */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/tkip_mic.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/tkip_mic.c new file mode 100644 index 0000000000000..e6957a75bd7e8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/tkip_mic.c @@ -0,0 +1,590 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Id: //Department/DaVinci/TRUNK/MT6620_WiFi_Firmware/ + * mcu/wifi/mgmt/tkip_mic.c#7 + */ + +/*! \file tkip_sw.c + * \brief This file include the tkip encrypted / decrypted mic function. + */ +/******************************************************************************* + * Copyright (c) 2003-2004 Inprocomm, 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 + * Inprocomm, Inc. + ******************************************************************************* + */ + +/******************************************************************************* + * C O M P I L E 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 + ******************************************************************************* + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/* length of TKIP and CCMP MIC field */ +#define WLAN_MAC_MIC_LEN 8 + +#define MK16_TKIP(x, y) (((uint16_t) (x) << 8) | (uint16_t) (y)) + +/* obtain low 8-bit from 16-bit value */ +#define LO_8BITS(x) ((x) & 0x00ff) + +/* obtain high 8-bit from 16-bit value */ +#define HI_8BITS(x) ((x) >> 8) + +#define ROTR32(x, y) (((x) >> (y)) | ((x) << (32 - (y)))) +#define ROTL32(x, y) (((x) << (y)) | ((x) >> (32 - (y)))) +#define ROTR16(x, y) (((x) >> (y)) | ((x) << (16 - (y)))) +#define ROTL16(x, y) (((x) << (y)) | ((x) >> (16 - (y)))) + +#define XSWAP32(x) ((((x) & 0xFF00FF00) >> 8) | (((x) & 0x00FF00FF) << 8)) + +/* obtain 16-bit entries SBOX form two 8-bit entries SBOX1 and SBOX2 */ +#define SBOX(x) (tkipSBOX1[LO_8BITS(x)] ^ tkipSBOX2[HI_8BITS(x)]) + + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************* + */ +const uint16_t tkipSBOX1[256] = { + 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, + 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A, + 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B, + 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B, + 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F, + 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F, + 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5, + 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F, + 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB, + 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397, + 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED, + 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A, + 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194, + 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3, + 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104, + 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D, + 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39, + 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695, + 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83, + 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76, + 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4, + 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B, + 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0, + 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018, + 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751, + 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85, + 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12, + 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9, + 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7, + 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A, + 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8, + 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A +}; + +const uint16_t tkipSBOX2[256] = { + 0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491, + 0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC, + 0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB, + 0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B, + 0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83, + 0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A, + 0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F, + 0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA, + 0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B, + 0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713, + 0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6, + 0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85, + 0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411, + 0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B, + 0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1, + 0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF, + 0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E, + 0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6, + 0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B, + 0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD, + 0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8, + 0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2, + 0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049, + 0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810, + 0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197, + 0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F, + 0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C, + 0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927, + 0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733, + 0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5, + 0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0, + 0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C +}; + +/******************************************************************************* + * 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 + ******************************************************************************* + */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief TKIP Michael block function + * + * \param[in][out] pu4L - pointer to left value + * \param[in][out] pu4PR - pointer to right value + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void tkipMicB(IN OUT uint32_t *pu4L, IN OUT uint32_t *pu4R) +{ + ASSERT(pu4L); + ASSERT(pu4R); + + *pu4R = *pu4R ^ ROTL32(*pu4L, 17); /* r <- r ^ (l<<<17) */ + *pu4L = (*pu4L + *pu4R); /* l <- (l+r) mod 2^32 */ + *pu4R = *pu4R ^ XSWAP32(*pu4L); /* r <- r ^ XSWAP(l) */ + *pu4L = (*pu4L + *pu4R); /* l <- (l+r) mod 2^32 */ + *pu4R = *pu4R ^ ROTL32(*pu4L, 3); /* r <- r ^ (l<<<3) */ + *pu4L = (*pu4L + *pu4R); /* l <- (l+r) mod 2^32 */ + *pu4R = *pu4R ^ ROTR32(*pu4L, 2); /* r <- r ^ (l>>>2) */ + *pu4L = (*pu4L + *pu4R); /* l <- (l+r) mod 2^32 */ +} /* tkipMicB */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief TKIP Michael generation function + * + * \param[in] pucMickey Pointer to MIC key + * \param[in] pucData Pointer to message + * \param[in] u4DataLen Message length, in byte(s) + * \param[in] pucSa Pointer to source address SA + * \param[in] pucDa Pointer to destination address DA + * \param[in] ucPriority Priority of IEEE 802.11 traffic class + * \param[out] pucMic Pointer to 64-bit MIC + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void +tkipMicGen(IN uint8_t *pucMickey, + IN uint8_t *pucData, + IN uint32_t u4DataLen, IN uint8_t *pucSa, IN uint8_t *pucDa, + IN uint8_t ucPriority, OUT uint8_t *pucMic) +{ + + uint32_t i; + uint32_t l, r; + uint32_t au4Msg[3]; + + ASSERT(pucMickey); + ASSERT(pucData); + ASSERT(pucSa); + ASSERT(pucDa); + ASSERT(pucMic); + + WLAN_GET_FIELD_32(pucMickey, &l); + WLAN_GET_FIELD_32(pucMickey + 4, &r); + + /* Michael message processing for DA and SA. */ + WLAN_GET_FIELD_32(pucDa, &au4Msg[0]); + au4Msg[1] = ((uint32_t) pucDa[4]) | ((uint32_t) pucDa[5] << + 8) | + ((uint32_t) pucSa[0] << 16) | ((uint32_t) pucSa[1] << 24); + WLAN_GET_FIELD_32(pucSa + 2, &au4Msg[2]); + + for (i = 0; i < 3; i++) { + l = l ^ au4Msg[i]; + tkipMicB(&l, &r); + } + + /* Michael message processing for priority. */ + au4Msg[0] = (uint32_t) ucPriority; + + l = l ^ au4Msg[0]; + tkipMicB(&l, &r); + + /* Michael message processing for MSDU data playload except + * the last octets which cannot be partitioned into a 32-bit word. + */ + for (i = 0; i < (uint32_t) u4DataLen / 4; i++) { + WLAN_GET_FIELD_32(pucData + i * 4, &au4Msg[0]); + l = l ^ au4Msg[0]; + tkipMicB(&l, &r); + } + + /* Michael message processing for the last uncomplete octets, + * if present, and the padding. + */ + switch (u4DataLen & 3) { + case 1: + au4Msg[0] = ((uint32_t) pucData[u4DataLen - 1]) | + 0x00005A00; + break; + + case 2: + au4Msg[0] = ((uint32_t) pucData[u4DataLen - 2]) | (( + uint32_t) pucData[u4DataLen - 1] << 8) | 0x005A0000; + break; + + case 3: + au4Msg[0] = ((uint32_t) pucData[u4DataLen - 3]) | + ((uint32_t) pucData[u4DataLen - 2] << 8) | (( + uint32_t) pucData[u4DataLen - 1] << 16) | 0x5A000000; + break; + + default: + au4Msg[0] = 0x0000005A; + } + au4Msg[1] = 0; + for (i = 0; i < 2; i++) { + l = l ^ au4Msg[i]; + tkipMicB(&l, &r); + } + + /* return ( l, r ), i.e. MIC */ + WLAN_SET_FIELD_32(pucMic, l); + WLAN_SET_FIELD_32(pucMic + 4, r); + +} /* tkipMicGen */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief this function decapsulate MSDU frame body( with MIC ) according + * to IEEE 802.11i TKIP sepcification. + * + * \param[in] prAdapter Pointer to the adapter object data area. + * \param[in] pucDa Pointer to destination address DA + * \param[in] pucSa Pointer to source address SA + * \param[in] ucPriority Priority of IEEE 802.11 traffic class + * \param[in] pucPayload Pointer to message + * \param[in] u2PayloadLen Message length, in byte(s) + * \param[out] pucMic Pointer to 64-bit MIC + * + * \retval NONE + */ +/*----------------------------------------------------------------------------*/ +void +tkipMicEncapsulate(IN uint8_t *pucDa, + IN uint8_t *pucSa, + IN uint8_t ucPriority, + IN uint16_t u2PayloadLen, IN uint8_t *pucPayload, + IN uint8_t *pucMic, IN uint8_t *pucMicKey) +{ + uint8_t aucMic[8]; /* MIC' */ + + DEBUGFUNC("tkipSwMsduEncapsulate"); + + ASSERT(pucDa); + ASSERT(pucSa); + ASSERT(pucPayload); + ASSERT(pucMic); + ASSERT(pucMicKey); + + DBGLOG(RSN, LOUD, + "MIC key %02x-%02x-%02x-%02x %02x-%02x-%02x-%02x\n", + pucMicKey[0], pucMicKey[1], pucMicKey[2], pucMicKey[3], + pucMicKey[4], pucMicKey[5], pucMicKey[6], pucMicKey[7]); + + tkipMicGen(pucMicKey, (uint8_t *) pucPayload, u2PayloadLen, + pucSa, pucDa, ucPriority, aucMic); + + kalMemCopy((uint8_t *) pucMic, &aucMic[0], + WLAN_MAC_MIC_LEN); + + DBGLOG(RSN, LOUD, + "Mic %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n", + pucMic[0], pucMic[1], pucMic[2], pucMic[3], pucMic[4], + pucMic[5], pucMic[6], pucMic[7]); + +} /* tkipSwMsduEncapsulate */ + +/*----------------------------------------------------------------------------*/ +u_int8_t tkipMicDecapsulate(IN struct SW_RFB *prSwRfb, + IN uint8_t *pucMicKey) +{ + uint8_t *pucMic1; /* MIC */ + uint8_t aucMic2[8]; /* MIC' */ + uint8_t ucPriority; + u_int8_t fgStatus; + uint8_t *pucSa, *pucDa; + /* PUCHAR pucMickey; */ + uint8_t *pucFrameBody; + uint16_t u2FrameBodyLen; + struct WLAN_MAC_HEADER *prMacHeader; + + DEBUGFUNC("tkipMicDecapsulate"); + + ASSERT(prSwRfb); + ASSERT(pucMicKey); + + /* prRxStatus = prSwRfb->prRxStatus; */ + pucFrameBody = prSwRfb->pucPayload; + u2FrameBodyLen = prSwRfb->u2PayloadLength; + + if (!pucFrameBody) { + DBGLOG(RSN, INFO, "pucPayload is NULL, drop this packet"); + return FALSE; + } + + DBGLOG(RSN, LOUD, "Before TKIP MSDU Decapsulate:\n"); + DBGLOG(RSN, LOUD, "MIC key:\n"); + /* DBGLOG_MEM8(RSN, LOUD, pucMicKey, 8); */ + + prMacHeader = (struct WLAN_MAC_HEADER *) prSwRfb->pvHeader; + ASSERT(prMacHeader); + + pucDa = prMacHeader->aucAddr1; + pucSa = prMacHeader->aucAddr3; + + switch (prMacHeader->u2FrameCtrl & MASK_TO_DS_FROM_DS) { + case 0: + pucDa = prMacHeader->aucAddr1; + pucSa = prMacHeader->aucAddr2; + break; + case MASK_FC_FROM_DS: + pucDa = prMacHeader->aucAddr1; + pucSa = prMacHeader->aucAddr3; + break; + default: + ASSERT((prMacHeader->u2FrameCtrl & MASK_FC_TO_DS) == 0); + return TRUE; + } + + if (RXM_IS_QOS_DATA_FRAME(prSwRfb->u2FrameCtrl)) + ucPriority = (uint8_t) ((((struct WLAN_MAC_HEADER_QOS *) + prSwRfb->pvHeader)->u2QosCtrl) & MASK_QC_TID); + else + ucPriority = 0; + + /* generate MIC' */ + tkipMicGen(pucMicKey, pucFrameBody, + u2FrameBodyLen - WLAN_MAC_MIC_LEN, pucSa, pucDa, ucPriority, + aucMic2); + + /* verify MIC and MIC' */ + pucMic1 = &pucFrameBody[u2FrameBodyLen - WLAN_MAC_MIC_LEN]; + if (pucMic1[0] == aucMic2[0] && pucMic1[1] == aucMic2[1] && + pucMic1[2] == aucMic2[2] && pucMic1[3] == aucMic2[3] && + pucMic1[4] == aucMic2[4] && pucMic1[5] == aucMic2[5] && + pucMic1[6] == aucMic2[6] && pucMic1[7] == aucMic2[7]) { + u2FrameBodyLen -= WLAN_MAC_MIC_LEN; + fgStatus = TRUE; + } else { + fgStatus = FALSE; + } + + /* DBGLOG(RSN, LOUD, ("TKIP MIC:\n")); */ + /* DBGLOG_MEM8(RSN, LOUD, pucMic1, 8); */ + /* DBGLOG(RSN, LOUD, ("TKIP MIC':\n")); */ + /* DBGLOG_MEM8(RSN, LOUD, aucMic2, 8); */ + + prSwRfb->u2PayloadLength = u2FrameBodyLen; + + DBGLOG(RSN, LOUD, "After TKIP MSDU Decapsulate:\n"); + DBGLOG(RSN, LOUD, "Frame body: (length = %u)\n", + u2FrameBodyLen); + /* DBGLOG_MEM8(RSN, LOUD, pucFrameBody, u2FrameBodyLen); */ + + return fgStatus; + +} /* tkipMicDecapsulate */ + + +/*----------------------------------------------------------------------------*/ +u_int8_t tkipMicDecapsulateInRxHdrTransMode( + IN struct SW_RFB *prSwRfb, IN uint8_t *pucMicKey) +{ + uint8_t *pucMic1; /* MIC */ + uint8_t aucMic2[8]; /* MIC' */ + u_int8_t fgStatus = FALSE; + /* PUCHAR pucMickey; */ + uint8_t *pucFrameBody; + uint16_t u2FrameBodyLen; + struct sk_buff *prSkb = NULL; +#if 0 + struct WLAN_MAC_HEADER *prMacHeader; + uint8_t *pucSa, *pucDa; + uint8_t ucPriority; + uint8_t aucDA[6]; + uint8_t aucSA[6]; + uint8_t aucType[2]; +#endif + + DEBUGFUNC("tkipMicDecapsulateInRxHdrTransMode"); + + ASSERT(prSwRfb); + ASSERT(pucMicKey); + + /* prRxStatus = prSwRfb->prRxStatus; */ + pucFrameBody = prSwRfb->pucPayload; + u2FrameBodyLen = prSwRfb->u2PayloadLength; + + DBGLOG(RSN, LOUD, "Before TKIP MSDU Decapsulate:\n"); + DBGLOG(RSN, LOUD, "MIC key:\n"); + /* DBGLOG_MEM8(RSN, LOUD, pucMicKey, 8); */ + + prSkb = dev_alloc_skb(u2FrameBodyLen + ETHERNET_HEADER_SZ * + 4); + if (prSkb) { + /* copy to etherhdr + payload to skb data */ + kalMemCopy(prSkb->data, prSwRfb->pvHeader, + u2FrameBodyLen + ETHERNET_HEADER_SZ); + *(prSkb->data + 6) = ETH_LLC_DSAP_SNAP; + *(prSkb->data + 7) = ETH_LLC_SSAP_SNAP; + *(prSkb->data + 8) = ETH_LLC_CONTROL_UNNUMBERED_INFORMATION; + *(prSkb->data + 9) = 0x00; + *(prSkb->data + 10) = 0x00; + *(prSkb->data + 11) = 0x00; + *(prSkb->data + 12) = *(uint8_t *)(prSwRfb->pvHeader + 12); + *(prSkb->data + 13) = *(uint8_t *)(prSwRfb->pvHeader + 13); + + tkipMicGen(pucMicKey, + prSkb->data + 6, + u2FrameBodyLen - WLAN_MAC_MIC_LEN + 8, + prSwRfb->pvHeader + 6, + prSwRfb->pvHeader, + prSwRfb->ucTid, aucMic2); + + if (prSkb) + kfree_skb((struct sk_buff *)prSkb); + } else { + DBGLOG(RX, ERROR, "MIC SW DEC1\n"); + return fgStatus; + } + + + /* verify MIC and MIC' */ + pucMic1 = &pucFrameBody[u2FrameBodyLen - WLAN_MAC_MIC_LEN]; + if (pucMic1[0] == aucMic2[0] && pucMic1[1] == aucMic2[1] && + pucMic1[2] == aucMic2[2] && pucMic1[3] == aucMic2[3] && + pucMic1[4] == aucMic2[4] && pucMic1[5] == aucMic2[5] && + pucMic1[6] == aucMic2[6] && pucMic1[7] == aucMic2[7]) { + u2FrameBodyLen -= WLAN_MAC_MIC_LEN; + fgStatus = TRUE; + } else { + fgStatus = FALSE; + DBGLOG(RX, ERROR, "MIC SW DEC2\n"); + } + +#if 0 + /* perform header transfer for tkip defragment frame, + * if receiving 802.11 pkt + */ + if (fgStatus == TRUE) { + /* reassign payload address */ + prSwRfb->pucPayload += (ETH_LLC_LEN + ETH_SNAP_LEN); + + /* reassign payload length */ + u2FrameBodyLen -= (ETH_LLC_LEN + ETH_SNAP_LEN); + + prSwRfb->pvHeader = prSwRfb->pucPayload - + (ETHERNET_HEADER_SZ); + + kalMemCopy(&aucDA[0], pucDa, MAC_ADDR_LEN); + kalMemCopy(&aucSA[0], pucSa, MAC_ADDR_LEN); + kalMemCopy(&aucType[0], prSwRfb->pucPayload - 2, 2); + + kalMemCopy(prSwRfb->pvHeader, &aucDA[0], MAC_ADDR_LEN); + kalMemCopy(prSwRfb->pvHeader + MAC_ADDR_LEN, &aucSA[0], + MAC_ADDR_LEN); + kalMemCopy(prSwRfb->pvHeader + MAC_ADDR_LEN + 2, + &aucType[0], 2); + + prSwRfb->u2HeaderLen = ETHERNET_HEADER_SZ; + } +#endif + + /* DBGLOG(RSN, LOUD, ("TKIP MIC:\n")); */ + /* DBGLOG_MEM8(RSN, LOUD, pucMic1, 8); */ + /* DBGLOG(RSN, LOUD, ("TKIP MIC':\n")); */ + /* DBGLOG_MEM8(RSN, LOUD, aucMic2, 8); */ + + prSwRfb->u2PayloadLength = u2FrameBodyLen; + + DBGLOG(RSN, LOUD, "After TKIP MSDU Decapsulate:\n"); + DBGLOG(RSN, LOUD, "Frame body: (length = %u)\n", + u2FrameBodyLen); + /* DBGLOG_MEM8(RSN, LOUD, pucFrameBody, u2FrameBodyLen); */ + + return fgStatus; + +} /* tkipMicDecapsulate */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/wapi.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/wapi.c new file mode 100644 index 0000000000000..0fc47fb136d95 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/wapi.c @@ -0,0 +1,527 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * 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 + */ + +/****************************************************************************** + * C O M P I L E 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 struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo) +{ + uint8_t *pucBuffer; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + if (prMsduInfo->ucBssIndex != prAdapter->prAisBssInfo->ucBssIndex) + return; + + pucBuffer = + (uint8_t *) ((unsigned long)prMsduInfo->prPacket + + (unsigned long)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 + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wapiParseWapiIE(IN struct WAPI_INFO_ELEM *prInfoElem, + OUT struct WAPI_INFO *prWapiInfo) +{ + uint32_t i; + int32_t u4RemainWapiIeLen; + uint16_t u2Version; + uint16_t u2Cap = 0; + uint32_t u4GroupSuite = WAPI_CIPHER_SUITE_WPI; + uint16_t u2PairSuiteCount = 0; + uint16_t u2AuthSuiteCount = 0; + uint8_t *pucPairSuite = NULL; + uint8_t *pucAuthSuite = NULL; + uint8_t *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 = (uint8_t *) &prInfoElem->u2AuthKeyMgtSuiteCount; + u4RemainWapiIeLen = (int32_t) 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 = (uint32_t) u2AuthSuiteCount * 4; + if (u4RemainWapiIeLen < (int32_t) 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 -= (int32_t) 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 = (uint32_t) u2PairSuiteCount * 4; + if (u4RemainWapiIeLen < (int32_t) 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 -= (int32_t) 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, (uint8_t) (u4GroupSuite & 0x000000FF), + (uint8_t) ((u4GroupSuite >> 8) & 0x000000FF), + (uint8_t) ((u4GroupSuite >> 16) & 0x000000FF), + (uint8_t) ((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 = + (uint32_t) u2PairSuiteCount; + + for (i = 0; i < (uint32_t) 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", + (uint8_t) i, + (uint8_t) (prWapiInfo->au4PairwiseKeyCipherSuite + [i] & 0x000000FF), + (uint8_t) ((prWapiInfo->au4PairwiseKeyCipherSuite + [i] >> 8) & 0x000000FF), + (uint8_t) ((prWapiInfo->au4PairwiseKeyCipherSuite + [i] >> 16) & 0x000000FF), + (uint8_t) ((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", + (uint8_t) (prWapiInfo->au4PairwiseKeyCipherSuite[0] & + 0x000000FF), + (uint8_t) ((prWapiInfo->au4PairwiseKeyCipherSuite[0] >> + 8) & 0x000000FF), + (uint8_t) ((prWapiInfo->au4PairwiseKeyCipherSuite[0] >> + 16) & 0x000000FF), + (uint8_t) ((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 = + (uint32_t) u2AuthSuiteCount; + + for (i = 0; i < (uint32_t) u2AuthSuiteCount; i++) { + WLAN_GET_FIELD_32(pucAuthSuite, + &prWapiInfo->au4AuthKeyMgtSuite[i]); + pucAuthSuite += 4; + + DBGLOG(SEC, LOUD, + "WAPI: AKM suite [%d]: %02x-%02x-%02x-%02x\n", + (uint8_t) i, + (uint8_t) (prWapiInfo->au4AuthKeyMgtSuite[i] & + 0x000000FF), + (uint8_t) ((prWapiInfo->au4AuthKeyMgtSuite[i] >> + 8) & 0x000000FF), + (uint8_t) ((prWapiInfo->au4AuthKeyMgtSuite[i] >> + 16) & 0x000000FF), + (uint8_t) ((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", + (uint8_t) (prWapiInfo->au4AuthKeyMgtSuite[0] & + 0x000000FF), + (uint8_t) ((prWapiInfo->au4AuthKeyMgtSuite[0] >> 8) & + 0x000000FF), + (uint8_t) ((prWapiInfo->au4AuthKeyMgtSuite[0] >> 16) & + 0x000000FF), + (uint8_t) ((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. + */ +/*----------------------------------------------------------------------------*/ +u_int8_t wapiPerformPolicySelection(IN struct ADAPTER *prAdapter, + IN struct BSS_DESC *prBss) +{ + uint32_t i; + uint32_t u4PairwiseCipher = 0; + uint32_t u4GroupCipher = 0; + uint32_t u4AkmSuite = 0; + struct WAPI_INFO *prBssWapiInfo; + struct WLAN_INFO *prWlanInfo; + + DEBUGFUNC("wapiPerformPolicySelection"); + + ASSERT(prBss); + + /* Notice!!!! WAPI AP not set the privacy bit for WAI + * and WAI-PSK at WZC configuration mode + */ + prWlanInfo = &prAdapter->rWlanInfo; + + if (prBss->fgIEWAPI) { + prBssWapiInfo = &prBss->rIEWAPI; + } else { + if (prAdapter->rWifiVar.rConnSettings.fgWapiMode == FALSE) { + DBGLOG(SEC, TRACE, "-- No Protected BSS\n"); + return TRUE; + } + DBGLOG(SEC, TRACE, + "WAPI Information Element does not exist.\n"); + return FALSE; + } + + /* Select pairwise/group ciphers */ + for (i = 0; i < prBssWapiInfo->u4PairwiseKeyCipherSuiteCount; i++) { + if (prBssWapiInfo->au4PairwiseKeyCipherSuite[i] == + prAdapter->rWifiVar. + rConnSettings.u4WapiSelectedPairwiseCipher) { + u4PairwiseCipher = + prBssWapiInfo->au4PairwiseKeyCipherSuite[i]; + } + } + if (prBssWapiInfo->u4GroupKeyCipherSuite == + prAdapter->rWifiVar.rConnSettings.u4WapiSelectedGroupCipher) + u4GroupCipher = prBssWapiInfo->u4GroupKeyCipherSuite; + + /* Exception handler */ + /* If we cannot find proper pairwise and group cipher suites to join the + * BSS, do not check the supported AKM suites. + */ + if (u4PairwiseCipher == 0 || u4GroupCipher == 0) { + DBGLOG(SEC, TRACE, + "Failed to select pairwise/group cipher (0x%08x/0x%08x)\n", + u4PairwiseCipher, u4GroupCipher); + return FALSE; + } + + /* Select AKM */ + /* If the driver cannot support any authentication suites advertised in + * the given BSS, we fail to perform RSNA policy selection. + */ + /* Attempt to find any overlapping supported AKM suite. */ + for (i = 0; i < prBssWapiInfo->u4AuthKeyMgtSuiteCount; i++) { + if (prBssWapiInfo->au4AuthKeyMgtSuite[i] == + prAdapter->rWifiVar.rConnSettings.u4WapiSelectedAKMSuite) { + u4AkmSuite = prBssWapiInfo->au4AuthKeyMgtSuite[i]; + break; + } + } + + if (u4AkmSuite == 0) { + DBGLOG(SEC, TRACE, "Cannot support any AKM suites\n"); + return FALSE; + } + + DBGLOG(SEC, TRACE, + "Selected pairwise/group cipher: %02x-%02x-%02x-%02x/%02x-%02x-%02x-%02x\n", + (uint8_t) (u4PairwiseCipher & 0x000000FF), + (uint8_t) ((u4PairwiseCipher >> 8) & 0x000000FF), + (uint8_t) ((u4PairwiseCipher >> 16) & 0x000000FF), + (uint8_t) ((u4PairwiseCipher >> 24) & 0x000000FF), + (uint8_t) (u4GroupCipher & 0x000000FF), + (uint8_t) ((u4GroupCipher >> 8) & 0x000000FF), + (uint8_t) ((u4GroupCipher >> 16) & 0x000000FF), + (uint8_t) ((u4GroupCipher >> 24) & 0x000000FF)); + + DBGLOG(SEC, TRACE, "Selected AKM suite: %02x-%02x-%02x-%02x\n", + (uint8_t) (u4AkmSuite & 0x000000FF), + (uint8_t) ((u4AkmSuite >> 8) & 0x000000FF), + (uint8_t) ((u4AkmSuite >> 16) & 0x000000FF), + (uint8_t) ((u4AkmSuite >> 24) & 0x000000FF)); + + return TRUE; +} /* wapiPerformPolicySelection */ + + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/wmm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/wmm.c new file mode 100644 index 0000000000000..f8e1d1ab40775 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/wmm.c @@ -0,0 +1,1724 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. + * If not, see . + */ + +#include "precomp.h" + +static void wmmTxTspecFrame(struct ADAPTER *prAdapter, uint8_t ucTid, + enum TSPEC_OP_CODE eOpCode, + struct PARAM_QOS_TSPEC *prTsParam); +static void wmmSyncAcParamWithFw(struct ADAPTER *prAdapter, uint8_t ucAc, + uint16_t u2MediumTime, uint32_t u4PhyRate); + +static void wmmGetTsmRptTimeout(struct ADAPTER *prAdapter, + unsigned long ulParam); + +static void wmmQueryTsmResult(struct ADAPTER *prAdapter, unsigned long ulParam); +static void wmmRemoveTSM(struct ADAPTER *prAdapter, + struct ACTIVE_RM_TSM_REQ *prActiveTsm, + u_int8_t fgNeedStop); +static struct ACTIVE_RM_TSM_REQ *wmmGetActiveTsmReq(struct ADAPTER *prAdapter, + uint8_t ucTid, + u_int8_t fgTriggered, + u_int8_t fgAllocIfNotExist); +static uint32_t wmmRunEventActionTxDone(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + enum ENUM_TX_RESULT_CODE rTxDoneStatus); +static void wmmMayDoTsReplacement(struct ADAPTER *prAdapter, uint8_t ucNewTid); + +#if 0 +static void DumpData(PUINT8 prAddr, UINT8 uLen, char *tag); +#endif + +#if CFG_SUPPORT_SOFT_ACM +static uint16_t wmmAcmTxTimeCal(uint16_t u2SecExtra, uint16_t u2EthBodyLen, + uint16_t u2DataRate, uint16_t u2BasicRate, + uint8_t ucFlags); + +static uint16_t wmmAcmTxTimeHtCal(uint16_t u2SecExtra, uint16_t u2EthBodyLen, + uint8_t ucMcsId, uint8_t ucFlags); + +static void wmmAcmDequeueTimeOut(IN struct ADAPTER *prAdapter, + unsigned long ulParamPtr); + +#define FLAG_S_PREAMBLE BIT(0) +#define FLAG_CTS_SELF BIT(1) +#define FLAG_RTS_CTS BIT(2) +#define FLAG_G_MODE BIT(3) +#define FLAG_SHORT_GI BIT(4) +#define FLAG_40M_BW BIT(5) +#define FLAG_GF_HT BIT(6) +#define FLAG_ONLY_DATA BIT(7) + +#define TIME_LONG_PREAMBLE 192 +#define TIME_SHORT_PREAMBLE 96 +#define TIME_SIFSG 0x10 +#define TIME_SIFS 0x0A +#define FRM_LENGTH_BLOCK_ACK 30 +#define TIME_SIFSGx2 0x20 /* support Clause 18 STA exists */ +#define TIME_SIFSx2 0x14 +#define FRM_LENGTH_RTS 0x14 +#define FRM_LENGTH_ACK 0x0E +/* aggregation related */ +#define FRM_LENGTH_AGG_AMSDU_HDR 17 +#define FRM_LENGTH_AGG_RAILNK_HDR 14 + +#define LMR_PREAMBL_TIME(__fgIsGmode, __fgIsSpreamble) \ + ({ \ + uint8_t ucTime; \ + if (__fgIsGmode) \ + ucTime = 20; \ + else \ + ucTime = __fgIsSpreamble ? TIME_SHORT_PREAMBLE \ + : TIME_LONG_PREAMBLE; \ + ucTime; \ + }) +#endif + +uint8_t const aucUp2ACIMap[8] = {ACI_BE, ACI_BK, ACI_BK, ACI_BE, + ACI_VI, ACI_VI, ACI_VO, ACI_VO}; + +void wmmInit(IN struct ADAPTER *prAdapter) +{ + struct WMM_INFO *prWmmInfo = &prAdapter->rWifiVar.rWmmInfo; + struct TSPEC_INFO *prTspecInfo = &prWmmInfo->arTsInfo[0]; + uint8_t ucTid = 0; + + for (ucTid = 0; ucTid < WMM_TSPEC_ID_NUM; ucTid++, prTspecInfo++) + cnmTimerInitTimer(prAdapter, &prTspecInfo->rAddTsTimer, + (PFN_MGMT_TIMEOUT_FUNC)wmmSetupTspecTimeOut, + (unsigned long)ucTid); +#if CFG_SUPPORT_SOFT_ACM + cnmTimerInitTimer(prAdapter, &prWmmInfo->rAcmDeqTimer, + wmmAcmDequeueTimeOut, 0); + kalMemZero(&prAdapter->rWifiVar.rWmmInfo.arAcmCtrl[0], + sizeof(prAdapter->rWifiVar.rWmmInfo.arAcmCtrl)); +#endif + LINK_INITIALIZE(&prWmmInfo->rActiveTsmReq); + prWmmInfo->rTriggeredTsmRptTime = 0; + DBGLOG(WMM, TRACE, "wmm init done\n"); +} + +void wmmUnInit(IN struct ADAPTER *prAdapter) +{ + struct WMM_INFO *prWmmInfo = &prAdapter->rWifiVar.rWmmInfo; + struct TSPEC_INFO *prTspecInfo = &prWmmInfo->arTsInfo[0]; + uint8_t ucTid = 0; + + for (ucTid = 0; ucTid < WMM_TSPEC_ID_NUM; ucTid++, prTspecInfo++) + cnmTimerStopTimer(prAdapter, &prTspecInfo->rAddTsTimer); +#if CFG_SUPPORT_SOFT_ACM + cnmTimerStopTimer(prAdapter, &prWmmInfo->rAcmDeqTimer); +#endif + wmmRemoveAllTsmMeasurement(prAdapter, FALSE); + DBGLOG(WMM, TRACE, "wmm uninit done\n"); +} + +void wmmFillTsinfo(struct PARAM_QOS_TSINFO *prTsInfo, uint8_t *pucTsInfo) +{ + uint32_t u4TsInfoValue = 0; + /* | 0 |1-4 | 5-6 | 7-8 | 9 | + *10 | 11-13 | 14-23 | + ** Traffic Type|TSID| Dir |Access Policy|Reserved | PSB| UP + *|reserved| + */ + + u4TsInfoValue = prTsInfo->ucTrafficType & 0x1; + u4TsInfoValue |= (prTsInfo->ucTid & 0xf) << 1; + u4TsInfoValue |= (prTsInfo->ucDirection & 0x3) << 5; + u4TsInfoValue |= (prTsInfo->ucAccessPolicy & 0x3) << 7; + u4TsInfoValue |= (prTsInfo->ucApsd & 0x1) << 10; + u4TsInfoValue |= (prTsInfo->ucuserPriority) << 11; + u4TsInfoValue |= BIT(7); /* Fixed bit in spec */ + + pucTsInfo[0] = u4TsInfoValue & 0xFF; + pucTsInfo[1] = (u4TsInfoValue >> 8) & 0xff; + pucTsInfo[2] = (u4TsInfoValue >> 16) & 0xff; +} + +void wmmComposeTspecIE(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + struct PARAM_QOS_TSPEC *prParamQosTspec) +{ + struct IE_WMM_TSPEC *prIeWmmTspec = NULL; + uint8_t *pucTemp = NULL; + uint8_t aucWfaOui[] = VENDOR_OUI_WFA; + + prIeWmmTspec = (struct IE_WMM_TSPEC *)((uint8_t *)prMsduInfo->prPacket + + prMsduInfo->u2FrameLength); + pucTemp = prIeWmmTspec->aucTspecBodyPart; + + /*fill WMM head*/ + prIeWmmTspec->ucId = ELEM_ID_VENDOR; + prIeWmmTspec->ucLength = ELEM_MAX_LEN_WMM_TSPEC; + kalMemCopy(prIeWmmTspec->aucOui, aucWfaOui, sizeof(aucWfaOui)); + prIeWmmTspec->ucOuiType = VENDOR_OUI_TYPE_WMM; + prIeWmmTspec->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_TSPEC; + prIeWmmTspec->ucVersion = VERSION_WMM; + + /*fill tsinfo*/ + wmmFillTsinfo(&prParamQosTspec->rTsInfo, prIeWmmTspec->aucTsInfo); + /*1.2 BODY*/ + /*nominal size*/ + /* DumpData(prParamQosTspec, sizeof(struct PARAM_QOS_TSPEC), + ** "QosTspc"); + */ + WLAN_SET_FIELD_16(pucTemp, prParamQosTspec->u2NominalMSDUSize); + pucTemp += 2; + WLAN_SET_FIELD_16(pucTemp, prParamQosTspec->u2MaxMSDUsize); + pucTemp += 2; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4MinSvcIntv); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4MaxSvcIntv); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4InactIntv); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4SpsIntv); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4SvcStartTime); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4MinDataRate); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4MeanDataRate); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4PeakDataRate); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4MaxBurstSize); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4DelayBound); + pucTemp += 4; + WLAN_SET_FIELD_32(pucTemp, prParamQosTspec->u4MinPHYRate); + pucTemp += 4; + WLAN_SET_FIELD_16(pucTemp, prParamQosTspec->u2Sba); + pucTemp += 2; + WLAN_SET_FIELD_16(pucTemp, prParamQosTspec->u2MediumTime); + /*DumpData(prIeWmmTspec->aucTsInfo, 55, "tspec ie");*/ + + prMsduInfo->u2FrameLength += IE_SIZE(prIeWmmTspec); +} + +static uint8_t wmmNewDlgToken(void) +{ + static uint8_t sWmmDlgToken; + + return sWmmDlgToken++; +} + +/* follow WMM spec, send add/del tspec request frame */ +static void wmmTxTspecFrame(struct ADAPTER *prAdapter, uint8_t ucTid, + enum TSPEC_OP_CODE eOpCode, + struct PARAM_QOS_TSPEC *prTsParam) +{ + struct BSS_INFO *prBssInfo = prAdapter->prAisBssInfo; + uint16_t u2PayLoadLen = WLAN_MAC_HEADER_LEN + 4; /*exclude TSPEC IE*/ + struct STA_RECORD *prStaRec = + prAdapter->rWifiVar.rAisFsmInfo.prTargetStaRec; + struct MSDU_INFO *prMsduInfo = NULL; + struct WMM_ACTION_TSPEC_FRAME *prActionFrame = NULL; + uint16_t u2FrameCtrl = MAC_FRAME_ACTION; + + if (!prStaRec || !prTsParam || !prBssInfo) { + DBGLOG(WMM, ERROR, "prStaRec NULL %d, prTsParam NULL %d\n", + !prStaRec, !prTsParam); + return; + } + /*build ADDTS for TID*/ + /*1 compose Action frame Fix field*/ + DBGLOG(WMM, INFO, "Tspec Action to AP=" MACSTR "\n", + MAC2STR(prStaRec->aucMacAddr)); + + prMsduInfo = cnmMgtPktAlloc(prAdapter, ACTION_ADDTS_REQ_FRAME_LEN); + if (!prMsduInfo) { + DBGLOG(WMM, ERROR, "Failed to allocate msdu info\n"); + return; + } + TX_SET_MMPDU(prAdapter, prMsduInfo, prStaRec->ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_MGMT_HEADER_LEN, u2PayLoadLen, + wmmRunEventActionTxDone, MSDU_RATE_MODE_AUTO); + + kalMemZero(prMsduInfo->prPacket, ACTION_ADDTS_REQ_FRAME_LEN); + + prActionFrame = (struct WMM_ACTION_TSPEC_FRAME *)prMsduInfo->prPacket; + + /*********frame header**********************/ + WLAN_SET_FIELD_16(&prActionFrame->u2FrameCtrl, u2FrameCtrl); + COPY_MAC_ADDR(prActionFrame->aucDestAddr, prStaRec->aucMacAddr); + COPY_MAC_ADDR(prActionFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prActionFrame->aucBSSID, prStaRec->aucMacAddr); + prActionFrame->u2SeqCtrl = 0; + + /********Frame body*************/ + prActionFrame->ucCategory = + CATEGORY_WME_MGT_NOTIFICATION; /*CATEGORY_QOS_ACTION;*/ + if (eOpCode == TX_ADDTS_REQ) { + prActionFrame->ucAction = ACTION_ADDTS_REQ; + prActionFrame->ucDlgToken = (prTsParam->ucDialogToken == 0) + ? wmmNewDlgToken() + : prTsParam->ucDialogToken; + } else if (eOpCode == TX_DELTS_REQ) { + prActionFrame->ucAction = ACTION_DELTS; + prActionFrame->ucDlgToken = + 0; /* dialog token should be always 0 in delts frame */ + } + + /* this field only meanful in ADD TS response, otherwise set to 0 */ + prActionFrame->ucStatusCode = 0; + + /*DumpData((PUINT_8)prMsduInfo->prPacket,u2PayLoadLen, "ADDTS-FF");*/ + + /********Information Element *************/ + wmmComposeTspecIE(prAdapter, prMsduInfo, prTsParam); + + /******** Insert into Msdu Queue *************/ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); +#if 0 + DumpData(((uint8_t *)prMsduInfo->prPacket) + u2PayLoadLen, + prMsduInfo->u2FrameLength - u2PayLoadLen, "TSPEC-IE"); +#endif +} + +void wmmSetupTspecTimeOut(struct ADAPTER *prAdapter, unsigned long ulParam) +{ + struct TSPEC_INFO *prTsInfo = NULL; + uint8_t ucTimeoutTid = (uint8_t)ulParam; + + if (ulParam >= WMM_TSPEC_ID_NUM) { + DBGLOG(WMM, INFO, "Wrong TS ID %d\n", ucTimeoutTid); + return; + } + prTsInfo = &prAdapter->rWifiVar.rWmmInfo.arTsInfo[ucTimeoutTid]; + switch (prTsInfo->eState) { + case QOS_TS_ACTIVE: + DBGLOG(WMM, INFO, "Update TS TIMEOUT for TID %d\n", + ucTimeoutTid); + break; + case QOS_TS_SETUPING: + DBGLOG(WMM, INFO, "ADD TS TIMEOUT for TID %d\n", ucTimeoutTid); + prTsInfo->eState = QOS_TS_INACTIVE; + break; + default: + DBGLOG(WMM, INFO, + "Shouldn't start this timer when Ts %d in state %d\n", + ucTimeoutTid, prTsInfo->eState); + break; + } +} + +uint8_t wmmCalculateUapsdSetting(struct ADAPTER *prAdapter) +{ + struct PM_PROFILE_SETUP_INFO *prPmProf = NULL; + struct TSPEC_INFO *prCurTs = &prAdapter->rWifiVar.rWmmInfo.arTsInfo[0]; + uint8_t ucTid = 0; + uint8_t ucFinalSetting = 0; + + ASSERT(prAdapter->prAisBssInfo); + prPmProf = &prAdapter->prAisBssInfo->rPmProfSetupInfo; + ucFinalSetting = + (prPmProf->ucBmpDeliveryAC << 4) | prPmProf->ucBmpTriggerAC; + for (ucTid = 0; ucTid < WMM_TSPEC_ID_NUM; ucTid++, prCurTs++) { + uint8_t ucPsd = 0; + + if (prCurTs->eState != QOS_TS_ACTIVE) + continue; + switch (prCurTs->eDir) { + case UPLINK_TS: + ucPsd = BIT(prCurTs->eAC); + break; + case DOWNLINK_TS: + ucPsd = BIT(prCurTs->eAC + 4); + break; + case BI_DIR_TS: + ucPsd = BIT(prCurTs->eAC) | BIT(prCurTs->eAC + 4); + break; + } + if (prCurTs->fgUapsd) + ucFinalSetting |= ucPsd; + else + ucFinalSetting &= ~ucPsd; + } + return ucFinalSetting; +} + +void wmmSyncAcParamWithFw(struct ADAPTER *prAdapter, uint8_t ucAc, + uint16_t u2MediumTime, uint32_t u4PhyRate) +{ + struct CMD_SET_WMM_PS_TEST_STRUCT rSetWmmPsTestParam; +#if CFG_SUPPORT_SOFT_ACM + struct SOFT_ACM_CTRL *prAcmCtrl = NULL; +#endif + struct CMD_UPDATE_AC_PARAMS rCmdUpdateAcParam; + + ASSERT(prAdapter->prAisBssInfo); +#if CFG_SUPPORT_SOFT_ACM + prAcmCtrl = &prAdapter->rWifiVar.rWmmInfo.arAcmCtrl[ucAc]; +/* admitted time is in unit 32-us */ +#if 0 /* UT/IT code */ + if (u2MediumTime) + u2MediumTime = 153; +#endif + prAcmCtrl->u4AdmittedTime = u2MediumTime * 32; + prAcmCtrl->u4IntervalEndSec = 0; +#endif + kalMemZero(&rCmdUpdateAcParam, sizeof(rCmdUpdateAcParam)); + rCmdUpdateAcParam.ucAcIndex = ucAc; + rCmdUpdateAcParam.ucBssIdx = prAdapter->prAisBssInfo->ucBssIndex; + rCmdUpdateAcParam.u2MediumTime = u2MediumTime; + rCmdUpdateAcParam.u4PhyRate = u4PhyRate; + wlanSendSetQueryCmd(prAdapter, CMD_ID_UPDATE_AC_PARMS, TRUE, FALSE, + FALSE, NULL, NULL, sizeof(struct CMD_UPDATE_AC_PARAMS), + (uint8_t *)&rCmdUpdateAcParam, NULL, 0); + kalMemZero(&rSetWmmPsTestParam, sizeof(rSetWmmPsTestParam)); + rSetWmmPsTestParam.ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + rSetWmmPsTestParam.bmfgApsdEnAc = wmmCalculateUapsdSetting(prAdapter); + wlanSendSetQueryCmd(prAdapter, CMD_ID_SET_WMM_PS_TEST_PARMS, TRUE, + FALSE, FALSE, NULL, NULL, + sizeof(struct CMD_SET_WMM_PS_TEST_STRUCT), + (uint8_t *)&rSetWmmPsTestParam, NULL, 0); + + DBGLOG(WMM, INFO, "Ac=%d, MediumTime=%d PhyRate=%u Uapsd 0x%02x\n", + ucAc, u2MediumTime, u4PhyRate, rSetWmmPsTestParam.bmfgApsdEnAc); +} + +/* Return: AC List in bit map if this ac has active tspec */ +uint8_t wmmHasActiveTspec(struct WMM_INFO *prWmmInfo) +{ + uint8_t ucTid = 0; + uint8_t ucACList = 0; + + /* if any tspec is active, it means */ + for (; ucTid < WMM_TSPEC_ID_NUM; ucTid++) + if (prWmmInfo->arTsInfo[ucTid].eState == QOS_TS_ACTIVE) + ucACList |= 1 << prWmmInfo->arTsInfo[ucTid].eAC; + return ucACList; +} + +void wmmRunEventTSOperate(IN struct ADAPTER *prAdapter, + IN struct MSG_HDR *prMsgHdr) +{ + struct MSG_TS_OPERATE *prMsgTsOperate = + (struct MSG_TS_OPERATE *)prMsgHdr; + + wmmTspecSteps(prAdapter, prMsgTsOperate->ucTid, prMsgTsOperate->eOpCode, + (void *)&prMsgTsOperate->rTspecParam); + cnmMemFree(prAdapter, prMsgHdr); +} + +void wmmTspecSteps(struct ADAPTER *prAdapter, uint8_t ucTid, + enum TSPEC_OP_CODE eOpCode, void *prStepParams) +{ + struct AIS_FSM_INFO *prAisFsmInfo = &prAdapter->rWifiVar.rAisFsmInfo; + struct WMM_INFO *prWmmInfo = &prAdapter->rWifiVar.rWmmInfo; + struct TSPEC_INFO *prCurTs = NULL; + + ASSERT(prAdapter->prAisBssInfo); + if (prAdapter->prAisBssInfo->eConnectionState != + PARAM_MEDIA_STATE_CONNECTED || + prAisFsmInfo->eCurrentState == AIS_STATE_DISCONNECTING) { + DBGLOG(WMM, INFO, + "ignore OP code %d when medium disconnected\n", eOpCode); + return; + } + + if (ucTid >= WMM_TSPEC_ID_NUM) { + DBGLOG(WMM, INFO, "Invalid TID %d\n", ucTid); + return; + } + + prCurTs = &prWmmInfo->arTsInfo[ucTid]; + DBGLOG(WMM, TRACE, "TID %d, State %d, Oper %d\n", ucTid, + prCurTs->eState, eOpCode); + + switch (prCurTs->eState) { + case QOS_TS_INACTIVE: { + struct PARAM_QOS_TSPEC *prQosTspec = + (struct PARAM_QOS_TSPEC *)prStepParams; + + if (eOpCode != TX_ADDTS_REQ) + break; + if (!prQosTspec) { + DBGLOG(WMM, INFO, "Lack of Tspec Param\n"); + break; + } + /*Send ADDTS req Frame*/ + wmmTxTspecFrame(prAdapter, ucTid, TX_ADDTS_REQ, prQosTspec); + + /*start ADDTS timer*/ + cnmTimerStartTimer(prAdapter, &prCurTs->rAddTsTimer, 1000); + prCurTs->eState = QOS_TS_SETUPING; + prCurTs->eAC = aucUp2ACIMap[prQosTspec->rTsInfo.ucuserPriority]; + prCurTs->ucToken = prQosTspec->ucDialogToken; + break; + } + case QOS_TS_SETUPING: { + struct WMM_ADDTS_RSP_STEP_PARAM *prParam = + (struct WMM_ADDTS_RSP_STEP_PARAM *)prStepParams; + + if (eOpCode == TX_DELTS_REQ || eOpCode == RX_DELTS_REQ || + eOpCode == DISC_DELTS_REQ) { + cnmTimerStopTimer(prAdapter, &prCurTs->rAddTsTimer); + prCurTs->eState = QOS_TS_INACTIVE; + DBGLOG(WMM, INFO, "Del Ts %d in setuping state\n", + ucTid); + break; + } else if (eOpCode != RX_ADDTS_RSP || + prParam->ucDlgToken != + prWmmInfo->arTsInfo[ucTid].ucToken) + break; + + cnmTimerStopTimer(prAdapter, &prCurTs->rAddTsTimer); + if (prParam->ucStatusCode == WMM_TS_STATUS_ADMISSION_ACCEPTED) { + struct ACTIVE_RM_TSM_REQ *prActiveTsmReq = NULL; + + prCurTs->eState = QOS_TS_ACTIVE; + prCurTs->eDir = prParam->eDir; + prCurTs->fgUapsd = !!prParam->ucApsd; + prCurTs->u2MediumTime = prParam->u2MediumTime; + prCurTs->u4PhyRate = prParam->u4PhyRate; + wmmSyncAcParamWithFw(prAdapter, prCurTs->eAC, + prParam->u2MediumTime, + prParam->u4PhyRate); + wmmMayDoTsReplacement(prAdapter, ucTid); + /* start pending TSM if it was requested before admitted + */ + prActiveTsmReq = wmmGetActiveTsmReq(prAdapter, ucTid, + TRUE, FALSE); + if (prActiveTsmReq) + wmmStartTsmMeasurement( + prAdapter, (unsigned long)prActiveTsmReq + ->prTsmReq); + prActiveTsmReq = wmmGetActiveTsmReq(prAdapter, ucTid, + FALSE, FALSE); + if (prActiveTsmReq) + wmmStartTsmMeasurement( + prAdapter, (unsigned long)prActiveTsmReq + ->prTsmReq); + + /* nicTxChangeDataPortByAc( + ** prAdapter->prAisBssInfo->prStaRecOfAP, + ** prCurTs->eAC, TRUE); + */ + } else { + prCurTs->eState = QOS_TS_INACTIVE; + DBGLOG(WMM, ERROR, "ADD TS is rejected, status=%d\n", + prParam->ucStatusCode); + } + break; + } + case QOS_TS_ACTIVE: { + struct ACTIVE_RM_TSM_REQ *prActiveTsm = NULL; + + switch (eOpCode) { + case TX_DELTS_REQ: + case RX_DELTS_REQ: + case DISC_DELTS_REQ: + prActiveTsm = wmmGetActiveTsmReq(prAdapter, ucTid, TRUE, + FALSE); + if (prActiveTsm) + wmmRemoveTSM(prAdapter, prActiveTsm, TRUE); + prActiveTsm = wmmGetActiveTsmReq(prAdapter, ucTid, + FALSE, FALSE); + if (prActiveTsm) + wmmRemoveTSM(prAdapter, prActiveTsm, TRUE); + prCurTs->eState = QOS_TS_INACTIVE; +#if CFG_SUPPORT_SOFT_ACM + /* Need to change tx queue, due to we do soft ACM */ + qmHandleDelTspec(prAdapter, + prAisFsmInfo->prTargetStaRec, + prCurTs->eAC); +#endif + wmmSyncAcParamWithFw(prAdapter, prCurTs->eAC, 0, 0); + wmmDumpActiveTspecs(prAdapter, NULL, 0); + if (eOpCode == TX_DELTS_REQ) + wmmTxTspecFrame( + prAdapter, ucTid, TX_DELTS_REQ, + (struct PARAM_QOS_TSPEC *)prStepParams); + break; + case TX_ADDTS_REQ: + /*Send ADDTS req Frame*/ + wmmTxTspecFrame(prAdapter, ucTid, TX_ADDTS_REQ, + (struct PARAM_QOS_TSPEC *)prStepParams); + prCurTs->eAC = + aucUp2ACIMap[((struct PARAM_QOS_TSPEC *) + prStepParams) + ->rTsInfo.ucuserPriority]; + prCurTs->ucToken = + ((struct PARAM_QOS_TSPEC *)prStepParams) + ->ucDialogToken; + /*start ADDTS timer*/ + cnmTimerStartTimer(prAdapter, &prCurTs->rAddTsTimer, + 1000); + break; + /* for case: TS of tid N has existed, then setup TS with this + ** tid again. + */ + case RX_ADDTS_RSP: { + struct WMM_ADDTS_RSP_STEP_PARAM *prParam = + (struct WMM_ADDTS_RSP_STEP_PARAM *)prStepParams; + + if (prParam->ucStatusCode != + WMM_TS_STATUS_ADMISSION_ACCEPTED) { + DBGLOG(WMM, INFO, + "Update TS %d request was rejected by BSS\n", + ucTid); + break; + } + prCurTs->eDir = prParam->eDir; + prCurTs->fgUapsd = !!prParam->ucApsd; + prCurTs->u2MediumTime = prParam->u2MediumTime; + prCurTs->u4PhyRate = prParam->u4PhyRate; + wmmSyncAcParamWithFw(prAdapter, prCurTs->eAC, + prParam->u2MediumTime, + prParam->u4PhyRate); + wmmMayDoTsReplacement(prAdapter, ucTid); + break; + } + default: + break; + } + break; + } + default: + break; + } +} + +static uint32_t wmmRunEventActionTxDone(struct ADAPTER *prAdapter, + struct MSDU_INFO *prMsduInfo, + enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + DBGLOG(WMM, INFO, "Status %d\n", rTxDoneStatus); + return WLAN_STATUS_SUCCESS; +} + +void DumpData(uint8_t *prAddr, uint8_t uLen, char *tag) +{ + uint16_t k = 0; + char buf[16 * 3 + 1]; + uint16_t loop = 0; + uint8_t *p = prAddr; + static char const charmap[16] = {'0', '1', '2', '3', '4', '5', + '6', '7', '8', '9', 'A', 'B', + 'C', 'D', 'E', 'F'}; + + uLen = (uLen > 128) ? 128 : uLen; + loop = uLen / 16; + if (tag) + DBGLOG(WMM, INFO, "++++++++ dump data \"%s\" p=%p len=%d\n", + tag, prAddr, uLen); + else + DBGLOG(WMM, INFO, "++++++ dump data p=%p, len=%d\n", prAddr, + uLen); + + while (loop) { + for (k = 0; k < 16; k++) { + buf[k * 3] = charmap[((*(p + k) & 0xF0) >> 4)]; + buf[k * 3 + 1] = charmap[(*(p + k) & 0x0F)]; + buf[k * 3 + 2] = ' '; + } + buf[16 * 3] = 0; + DBGLOG(WMM, INFO, "%s\n", buf); + loop--; + p += 16; + } + uLen = uLen % 16; + k = 0; + while (uLen) { + buf[k * 3] = charmap[((*(p + k) & 0xF0) >> 4)]; + buf[k * 3 + 1] = charmap[(*(p + k) & 0x0F)]; + buf[k * 3 + 2] = ' '; + k++; + uLen--; + } + buf[k * 3] = 0; + DBGLOG(WMM, INFO, "%s\n", buf); + DBGLOG(WMM, INFO, "====== end dump data\n"); +} + +/* TSM related */ + +static void wmmQueryTsmResult(struct ADAPTER *prAdapter, unsigned long ulParam) +{ + struct RM_TSM_REQ *prTsmReq = + ((struct ACTIVE_RM_TSM_REQ *)ulParam)->prTsmReq; + struct WMM_INFO *prWmmInfo = &prAdapter->rWifiVar.rWmmInfo; + struct CMD_GET_TSM_STATISTICS rGetTsmStatistics; + + DBGLOG(WMM, INFO, "Query TSM statistics, tid = %d\n", prTsmReq->ucTID); + DBGLOG(WMM, INFO, "%p , aci %d, duration %d\n", prTsmReq, + prTsmReq->ucACI, prTsmReq->u2Duration); + rGetTsmStatistics.ucBssIdx = prAdapter->prAisBssInfo->ucBssIndex; + rGetTsmStatistics.ucAcIndex = prTsmReq->ucACI; + rGetTsmStatistics.ucTid = prTsmReq->ucTID; + COPY_MAC_ADDR(rGetTsmStatistics.aucPeerAddr, prTsmReq->aucPeerAddr); + + wlanSendSetQueryCmd(prAdapter, CMD_ID_GET_TSM_STATISTICS, FALSE, TRUE, + FALSE, wmmComposeTsmRpt, NULL, + sizeof(struct CMD_GET_TSM_STATISTICS), + (uint8_t *)&rGetTsmStatistics, NULL, 0); + cnmTimerInitTimer(prAdapter, &prWmmInfo->rTsmTimer, wmmGetTsmRptTimeout, + ulParam); + cnmTimerStartTimer(prAdapter, &prWmmInfo->rTsmTimer, 2000); +} + +static struct ACTIVE_RM_TSM_REQ *wmmGetActiveTsmReq(struct ADAPTER *prAdapter, + uint8_t ucTid, + u_int8_t fgTriggered, + u_int8_t fgAllocIfNotExist) +{ + struct WMM_INFO *prWMMInfo = &prAdapter->rWifiVar.rWmmInfo; + struct ACTIVE_RM_TSM_REQ *prActiveReq = NULL; + u_int8_t fgFound = FALSE; + + LINK_FOR_EACH_ENTRY(prActiveReq, &prWMMInfo->rActiveTsmReq, rLinkEntry, + struct ACTIVE_RM_TSM_REQ) + { + if ((!!prActiveReq->prTsmReq->u2Duration) == fgTriggered && + ucTid == prActiveReq->prTsmReq->ucTID) { + fgFound = TRUE; + break; + } + } + if (!fgFound && fgAllocIfNotExist) { + fgFound = TRUE; + prActiveReq = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, + sizeof(struct ACTIVE_RM_TSM_REQ)); + LINK_INSERT_TAIL(&prWMMInfo->rActiveTsmReq, + &prActiveReq->rLinkEntry); + } + return fgFound ? prActiveReq : NULL; +} + +static void wmmRemoveTSM(struct ADAPTER *prAdapter, + struct ACTIVE_RM_TSM_REQ *prActiveTsm, + u_int8_t fgNeedStop) +{ + struct WMM_INFO *prWMMInfo = &prAdapter->rWifiVar.rWmmInfo; + struct LINK *prActiveTsmLink = &prWMMInfo->rActiveTsmReq; + + LINK_REMOVE_KNOWN_ENTRY(prActiveTsmLink, prActiveTsm); + if (fgNeedStop) { + struct CMD_SET_TSM_STATISTICS_REQUEST rTsmStatistics; + struct STA_RECORD *prStaRec = NULL; + + if (!prAdapter->prAisBssInfo) { + DBGLOG(WMM, ERROR, "prAisBssInfo is NULL\n"); + return; + } + prStaRec = prAdapter->prAisBssInfo->prStaRecOfAP; + nicTxChangeDataPortByAc(prStaRec, prActiveTsm->prTsmReq->ucACI, + FALSE); + rTsmStatistics.ucBssIdx = prAdapter->prAisBssInfo->ucBssIndex; + rTsmStatistics.ucEnabled = FALSE; + rTsmStatistics.ucAcIndex = prActiveTsm->prTsmReq->ucACI; + rTsmStatistics.ucTid = prActiveTsm->prTsmReq->ucTID; + COPY_MAC_ADDR(rTsmStatistics.aucPeerAddr, + prActiveTsm->prTsmReq->aucPeerAddr); + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_TSM_STATISTICS_REQUEST, TRUE, + FALSE, FALSE, NULL, NULL, + sizeof(struct CMD_SET_TSM_STATISTICS_REQUEST), + (uint8_t *)&rTsmStatistics, NULL, 0); + } + cnmMemFree(prAdapter, prActiveTsm->prTsmReq); + cnmMemFree(prAdapter, prActiveTsm); +} + +void wmmStartTsmMeasurement(struct ADAPTER *prAdapter, unsigned long ulParam) +{ + struct WMM_INFO *prWMMInfo = &prAdapter->rWifiVar.rWmmInfo; + struct CMD_SET_TSM_STATISTICS_REQUEST rTsmStatistics; + struct RM_TSM_REQ *prTsmReq = (struct RM_TSM_REQ *)ulParam; + uint8_t ucTid = prTsmReq->ucTID; + struct ACTIVE_RM_TSM_REQ *prActiveTsmReq = NULL; + struct STA_RECORD *prStaRec = NULL; + struct TSPEC_INFO *prCurTs = NULL; + + ASSERT(prAdapter->prAisBssInfo); + if (!prTsmReq->u2Duration && + !(prTsmReq->rTriggerCond.ucCondition & TSM_TRIGGER_CONDITION_ALL)) { + DBGLOG(WMM, WARN, "Duration is %d, Trigger Condition %d\n", + prTsmReq->u2Duration, + prTsmReq->rTriggerCond.ucCondition); + cnmMemFree(prAdapter, prTsmReq); + rlmScheduleNextRm(prAdapter); + return; + } + prStaRec = prAdapter->prAisBssInfo->prStaRecOfAP; + if (!prStaRec) { + DBGLOG(WMM, INFO, "No station record found for %pM\n", + prTsmReq->aucPeerAddr); + cnmMemFree(prAdapter, prTsmReq); + rlmScheduleNextRm(prAdapter); + return; + } + /* if there's a active tspec, then TID means TS ID */ + prCurTs = &prWMMInfo->arTsInfo[ucTid]; + if (prCurTs->eState == QOS_TS_ACTIVE) + prTsmReq->ucACI = prCurTs->eAC; + else { /* otherwise TID means TC ID */ + uint8_t ucTsAcs = wmmHasActiveTspec(prWMMInfo); + + prTsmReq->ucACI = aucUp2ACIMap[ucTid]; + /* if current TID is not admitted, don't start measurement, only + ** save this requirement + */ + if (prStaRec->afgAcmRequired[prTsmReq->ucACI] && + !(ucTsAcs & BIT(prTsmReq->ucACI))) { + DBGLOG(WMM, INFO, + "ACM is set for UP %d, but No tspec is setup\n", + ucTid); + rlmScheduleNextRm(prAdapter); + return; + } + } + + kalMemZero(&rTsmStatistics, sizeof(rTsmStatistics)); + if (prTsmReq->u2Duration) { + /* If a non-AP QoS STa receives a Transmit Stream/Category + *Measurement Request for a TC, or + ** TS that is already being measured using a triggered transmit + *stream/category measurement, + ** the triggered traffic stream measurement shall be suspended + *for the duration of the requested + ** traffic stream measurement. When triggered measurement + *resumes, the traffic stream metrics + ** shall be reset. See end part of 802.11k 11.10.8.8 + **/ + LINK_FOR_EACH_ENTRY(prActiveTsmReq, &prWMMInfo->rActiveTsmReq, + rLinkEntry, struct ACTIVE_RM_TSM_REQ) + { + if (prActiveTsmReq->prTsmReq->u2Duration || + prActiveTsmReq->prTsmReq->ucACI != prTsmReq->ucACI) + continue; + nicTxChangeDataPortByAc(prStaRec, prTsmReq->ucACI, + FALSE); + rTsmStatistics.ucBssIdx = + prAdapter->prAisBssInfo->ucBssIndex; + rTsmStatistics.ucEnabled = FALSE; + rTsmStatistics.ucAcIndex = prTsmReq->ucACI; + rTsmStatistics.ucTid = prActiveTsmReq->prTsmReq->ucTID; + COPY_MAC_ADDR(rTsmStatistics.aucPeerAddr, + prActiveTsmReq->prTsmReq->aucPeerAddr); + wlanSendSetQueryCmd( + prAdapter, CMD_ID_SET_TSM_STATISTICS_REQUEST, + TRUE, FALSE, FALSE, NULL, NULL, + sizeof(struct CMD_SET_TSM_STATISTICS_REQUEST), + (uint8_t *)&rTsmStatistics, NULL, 0); + } + prActiveTsmReq = wmmGetActiveTsmReq( + prAdapter, ucTid, !!prTsmReq->u2Duration, TRUE); + /* if exist normal tsm on the same ts, replace it */ + if (prActiveTsmReq->prTsmReq) + cnmMemFree(prAdapter, prActiveTsmReq->prTsmReq); + DBGLOG(WMM, INFO, "%p tid %d, aci %d, duration %d\n", prTsmReq, + prTsmReq->ucTID, prTsmReq->ucACI, prTsmReq->u2Duration); + cnmTimerInitTimer(prAdapter, &prWMMInfo->rTsmTimer, + wmmQueryTsmResult, + (unsigned long)prActiveTsmReq); + cnmTimerStartTimer(prAdapter, &prWMMInfo->rTsmTimer, + TU_TO_MSEC(prTsmReq->u2Duration)); + } else { + prActiveTsmReq = wmmGetActiveTsmReq( + prAdapter, ucTid, !prTsmReq->u2Duration, TRUE); + /* if exist triggered tsm on the same ts, replace it */ + if (prActiveTsmReq->prTsmReq) { + cnmTimerStopTimer(prAdapter, + &prActiveTsmReq->rTsmTimer); + cnmMemFree(prAdapter, prActiveTsmReq->prTsmReq); + } + rTsmStatistics.ucTriggerCondition = + prTsmReq->rTriggerCond.ucCondition; + rTsmStatistics.ucMeasureCount = + prTsmReq->rTriggerCond.ucMeasureCount; + rTsmStatistics.ucTriggerTimeout = + prTsmReq->rTriggerCond.ucTriggerTimeout; + rTsmStatistics.ucAvgErrThreshold = + prTsmReq->rTriggerCond.ucAvgErrThreshold; + rTsmStatistics.ucConsecutiveErrThreshold = + prTsmReq->rTriggerCond.ucConsecutiveErr; + rTsmStatistics.ucDelayThreshold = + prTsmReq->rTriggerCond.ucDelayThreshold; + rTsmStatistics.ucBin0Range = prTsmReq->ucB0Range; + } + nicTxChangeDataPortByAc(prStaRec, prTsmReq->ucACI, TRUE); + prActiveTsmReq->prTsmReq = prTsmReq; + rTsmStatistics.ucBssIdx = prAdapter->prAisBssInfo->ucBssIndex; + rTsmStatistics.ucAcIndex = prTsmReq->ucACI; + rTsmStatistics.ucTid = prTsmReq->ucTID; + rTsmStatistics.ucEnabled = TRUE; + COPY_MAC_ADDR(rTsmStatistics.aucPeerAddr, prTsmReq->aucPeerAddr); + DBGLOG(WMM, INFO, "enabled=%d, tid=%d\n", rTsmStatistics.ucEnabled, + ucTid); + wlanSendSetQueryCmd(prAdapter, CMD_ID_SET_TSM_STATISTICS_REQUEST, TRUE, + FALSE, FALSE, NULL, NULL, + sizeof(struct CMD_SET_TSM_STATISTICS_REQUEST), + (uint8_t *)&rTsmStatistics, NULL, 0); +} + +void wmmRemoveAllTsmMeasurement(struct ADAPTER *prAdapter, + u_int8_t fgOnlyTriggered) +{ + struct LINK *prActiveTsmLink = + &prAdapter->rWifiVar.rWmmInfo.rActiveTsmReq; + struct ACTIVE_RM_TSM_REQ *prActiveTsm = NULL; + struct ACTIVE_RM_TSM_REQ *prHead = LINK_PEEK_HEAD( + prActiveTsmLink, struct ACTIVE_RM_TSM_REQ, rLinkEntry); + u_int8_t fgFinished = FALSE; + + if (!fgOnlyTriggered) + cnmTimerStopTimer(prAdapter, + &prAdapter->rWifiVar.rWmmInfo.rTsmTimer); + do { + prActiveTsm = LINK_PEEK_TAIL( + prActiveTsmLink, struct ACTIVE_RM_TSM_REQ, rLinkEntry); + if (!prActiveTsm) + break; + if (prActiveTsm == prHead) + fgFinished = TRUE; + if (fgOnlyTriggered && prActiveTsm->prTsmReq->u2Duration) + continue; + wmmRemoveTSM(prAdapter, prActiveTsm, TRUE); + } while (!fgFinished); + prAdapter->rWifiVar.rWmmInfo.rTriggeredTsmRptTime = 0; +} + +u_int8_t wmmParseQosAction(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct WLAN_ACTION_FRAME *prWlanActionFrame = NULL; + uint8_t *pucIE = NULL; + struct PARAM_QOS_TSPEC rTspec; + uint16_t u2Offset = 0; + uint16_t u2IEsBufLen = 0; + uint8_t ucTid = WMM_TSPEC_ID_NUM; + struct WMM_ADDTS_RSP_STEP_PARAM rStepParam; + u_int8_t ret = FALSE; + + prWlanActionFrame = (struct WLAN_ACTION_FRAME *)prSwRfb->pvHeader; + DBGLOG(WMM, INFO, "Action=%d\n", prWlanActionFrame->ucAction); + switch (prWlanActionFrame->ucAction) { + case ACTION_ADDTS_RSP: { + kalMemZero(&rStepParam, sizeof(rStepParam)); + if (prWlanActionFrame->ucCategory == + CATEGORY_WME_MGT_NOTIFICATION) { + struct WMM_ACTION_TSPEC_FRAME *prAddTsRsp = + (struct WMM_ACTION_TSPEC_FRAME *) + prWlanActionFrame; + + rStepParam.ucDlgToken = prAddTsRsp->ucDlgToken; + rStepParam.ucStatusCode = prAddTsRsp->ucStatusCode; + pucIE = (uint8_t *)prAddTsRsp->aucInfoElem; + } else if (prWlanActionFrame->ucCategory == + CATEGORY_QOS_ACTION) { + struct ACTION_ADDTS_RSP_FRAME *prAddTsRsp = + (struct ACTION_ADDTS_RSP_FRAME *) + prWlanActionFrame; + + rStepParam.ucDlgToken = prAddTsRsp->ucDialogToken; + rStepParam.ucStatusCode = prAddTsRsp->ucStatusCode; + pucIE = (uint8_t *)prAddTsRsp->aucInfoElem; + } else { + DBGLOG(WMM, INFO, + "Not supported category %d for action %d\n", + prWlanActionFrame->ucCategory, + prWlanActionFrame->ucAction); + break; + } + + /*for each IE*/ + u2IEsBufLen = + prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen - + (uint16_t)(OFFSET_OF(struct ACTION_ADDTS_RSP_FRAME, + aucInfoElem) - + WLAN_MAC_HEADER_LEN); + + kalMemZero(&rTspec, sizeof(rTspec)); + IE_FOR_EACH(pucIE, u2IEsBufLen, u2Offset) + { + switch (IE_ID(pucIE)) { + case ELEM_ID_TSPEC: + case ELEM_ID_VENDOR: + if (wmmParseTspecIE(prAdapter, pucIE, + &rTspec)) { + rStepParam.u2MediumTime = + rTspec.u2MediumTime; + ucTid = rTspec.rTsInfo.ucTid; + rStepParam.eDir = + rTspec.rTsInfo.ucDirection; + rStepParam.u4PhyRate = + rTspec.u4MinPHYRate; + rStepParam.ucApsd = + rTspec.rTsInfo.ucApsd; + } else { + DBGLOG(WMM, INFO, + "can't parse Tspec IE?!\n"); + ASSERT(FALSE); + } + break; + default: + break; + } + } + wmmTspecSteps(prAdapter, ucTid, RX_ADDTS_RSP, &rStepParam); + ret = TRUE; + break; + } + case ACTION_DELTS: { + if (prWlanActionFrame->ucCategory == + CATEGORY_WME_MGT_NOTIFICATION) { + /* wmm Tspec */ + struct WMM_ACTION_TSPEC_FRAME *prDelTs = + (struct WMM_ACTION_TSPEC_FRAME *) + prWlanActionFrame; + + u2IEsBufLen = prSwRfb->u2PacketLen - + (uint16_t)OFFSET_OF( + struct WMM_ACTION_TSPEC_FRAME, + aucInfoElem); + u2Offset = 0; + pucIE = prDelTs->aucInfoElem; + IE_FOR_EACH(pucIE, u2IEsBufLen, u2Offset) + { + if (!wmmParseTspecIE(prAdapter, pucIE, &rTspec)) + continue; + ucTid = rTspec.rTsInfo.ucTid; + break; + } + } else if (prWlanActionFrame->ucCategory == + CATEGORY_QOS_ACTION) { + /* IEEE 802.11 Tspec */ + struct ACTION_DELTS_FRAME *prDelTs = + (struct ACTION_DELTS_FRAME *)prWlanActionFrame; + + ucTid = WMM_TSINFO_TSID(prDelTs->aucTsInfo[0]); + } + + wmmTspecSteps(prAdapter, ucTid, RX_DELTS_REQ, NULL); + ret = TRUE; + break; + } + default: + break; + } + return ret; +} + +u_int8_t wmmParseTspecIE(struct ADAPTER *prAdapter, uint8_t *pucIE, + struct PARAM_QOS_TSPEC *prTspec) +{ + uint32_t u4TsInfoValue = 0; + uint8_t *pucTemp = NULL; + + if (IE_ID(pucIE) == ELEM_ID_TSPEC) { + DBGLOG(WMM, INFO, "found 802.11 Tspec Information Element\n"); + /* todo: implement 802.11 Tspec here, assign value to + ** u4TsInfoValue and pucTemp + */ + u4TsInfoValue = 0; + pucTemp = NULL; + return FALSE; /* we didn't support IEEE 802.11 Tspec now */ + } + { + struct IE_WMM_TSPEC *prIeWmmTspec = + (struct IE_WMM_TSPEC *)pucIE; + uint8_t aucWfaOui[] = VENDOR_OUI_WFA; + + if (prIeWmmTspec->ucId != ELEM_ID_VENDOR || + kalMemCmp(prIeWmmTspec->aucOui, aucWfaOui, + sizeof(aucWfaOui)) || + prIeWmmTspec->ucOuiType != VENDOR_OUI_TYPE_WMM || + prIeWmmTspec->ucOuiSubtype != + VENDOR_OUI_SUBTYPE_WMM_TSPEC) { + return FALSE; + } + u4TsInfoValue |= prIeWmmTspec->aucTsInfo[0]; + u4TsInfoValue |= (prIeWmmTspec->aucTsInfo[1] << 8); + u4TsInfoValue |= (prIeWmmTspec->aucTsInfo[2] << 16); + pucTemp = prIeWmmTspec->aucTspecBodyPart; + } + + prTspec->rTsInfo.ucTrafficType = WMM_TSINFO_TRAFFIC_TYPE(u4TsInfoValue); + prTspec->rTsInfo.ucTid = WMM_TSINFO_TSID(u4TsInfoValue); + prTspec->rTsInfo.ucDirection = WMM_TSINFO_DIR(u4TsInfoValue); + prTspec->rTsInfo.ucAccessPolicy = WMM_TSINFO_AC(u4TsInfoValue); + prTspec->rTsInfo.ucApsd = WMM_TSINFO_PSB(u4TsInfoValue); + prTspec->rTsInfo.ucuserPriority = WMM_TSINFO_UP(u4TsInfoValue); + + /* nominal size*/ + WLAN_GET_FIELD_16(pucTemp, &prTspec->u2NominalMSDUSize); + pucTemp += 2; + WLAN_GET_FIELD_16(pucTemp, &prTspec->u2MaxMSDUsize); + pucTemp += 2; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4MinSvcIntv); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4MaxSvcIntv); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4InactIntv); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4SpsIntv); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4SvcStartTime); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4MinDataRate); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4MeanDataRate); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4PeakDataRate); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4MaxBurstSize); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4DelayBound); + pucTemp += 4; + WLAN_GET_FIELD_32(pucTemp, &prTspec->u4MinPHYRate); + pucTemp += 4; + WLAN_GET_FIELD_16(pucTemp, &prTspec->u2Sba); + pucTemp += 2; + WLAN_GET_FIELD_16(pucTemp, &prTspec->u2MediumTime); + pucTemp += 2; + ASSERT((pucTemp == (IE_SIZE(pucIE) + pucIE))); + DBGLOG(WMM, INFO, "TsId=%d, TrafficType=%d, PSB=%d, MediumTime=%d\n", + prTspec->rTsInfo.ucTid, prTspec->rTsInfo.ucTrafficType, + prTspec->rTsInfo.ucApsd, prTspec->u2MediumTime); + return TRUE; +} + +static void wmmGetTsmRptTimeout(struct ADAPTER *prAdapter, + unsigned long ulParam) +{ + DBGLOG(WMM, ERROR, "timeout to get Tsm Rpt from firmware\n"); + wlanReleasePendingCmdById(prAdapter, CMD_ID_GET_TSM_STATISTICS); + wmmRemoveTSM(prAdapter, (struct ACTIVE_RM_TSM_REQ *)ulParam, TRUE); + /* schedule next measurement after a duration based TSM done */ + rlmStartNextMeasurement(prAdapter, FALSE); +} + +void wmmComposeTsmRpt(struct ADAPTER *prAdapter, struct CMD_INFO *prCmdInfo, + uint8_t *pucEventBuf) +{ + struct RADIO_MEASUREMENT_REPORT_PARAMS *prRmRep = + &prAdapter->rWifiVar.rRmRepParams; + struct IE_MEASUREMENT_REPORT *prTsmRpt = NULL; + struct RM_TSM_REPORT *prTsmRptField = NULL; + struct CMD_GET_TSM_STATISTICS *prTsmStatistic = + (struct CMD_GET_TSM_STATISTICS *)pucEventBuf; + uint16_t u2IeSize = + OFFSET_OF(struct IE_MEASUREMENT_REPORT, aucReportFields) + + sizeof(*prTsmRptField); + struct ACTIVE_RM_TSM_REQ *prCurrentTsmReq = NULL; + struct WMM_INFO *prWMMInfo = &prAdapter->rWifiVar.rWmmInfo; + + if (!prAdapter->prAisBssInfo) { + DBGLOG(WMM, ERROR, "prAisBssInfo is NULL\n"); + return; + } + prCurrentTsmReq = + wmmGetActiveTsmReq(prAdapter, prTsmStatistic->ucTid, + !prTsmStatistic->ucReportReason, FALSE); + /* prCmdInfo is not NULL or report reason is 0 means it is a command + ** reply, so we need to stop the timer + */ + if (prCmdInfo || !prTsmStatistic->ucReportReason) + cnmTimerStopTimer(prAdapter, &prWMMInfo->rTsmTimer); + if (!prCurrentTsmReq) { + DBGLOG(WMM, ERROR, "unexpected Tsm statistic event, tid %d\n", + prTsmStatistic->ucTid); + /* schedule next measurement after a duration based TSM done */ + rlmScheduleNextRm(prAdapter); + return; + } + + /* Put the report IE into report frame */ + if (u2IeSize + prRmRep->u2ReportFrameLen > RM_REPORT_FRAME_MAX_LENGTH) + rlmTxRadioMeasurementReport(prAdapter); + + DBGLOG(WMM, INFO, "tid %d, aci %d\n", prCurrentTsmReq->prTsmReq->ucTID, + prCurrentTsmReq->prTsmReq->ucACI); + prTsmRpt = + (struct IE_MEASUREMENT_REPORT *)(prRmRep->pucReportFrameBuff + + prRmRep->u2ReportFrameLen); + prTsmRpt->ucId = ELEM_ID_MEASUREMENT_REPORT; + prTsmRpt->ucToken = prCurrentTsmReq->prTsmReq->ucToken; + prTsmRpt->ucMeasurementType = ELEM_RM_TYPE_TSM_REPORT; + prTsmRpt->ucReportMode = 0; + prTsmRpt->ucLength = u2IeSize - 2; + prTsmRptField = (struct RM_TSM_REPORT *)&prTsmRpt->aucReportFields[0]; + prTsmRptField->u8ActualStartTime = prTsmStatistic->u8StartTime; + prTsmRptField->u2Duration = prCurrentTsmReq->prTsmReq->u2Duration; + COPY_MAC_ADDR(prTsmRptField->aucPeerAddress, + prTsmStatistic->aucPeerAddr); + /* TID filed: bit0~bit3 reserved, bit4~bit7: real tid */ + prTsmRptField->ucTID = (prCurrentTsmReq->prTsmReq->ucTID & 0xf) << 4; + prTsmRptField->ucReason = prTsmStatistic->ucReportReason; + prTsmRptField->u4TransmittedMsduCnt = prTsmStatistic->u4PktTxDoneOK; + prTsmRptField->u4DiscardedMsduCnt = prTsmStatistic->u4PktDiscard; + prTsmRptField->u4FailedMsduCnt = prTsmStatistic->u4PktFail; + prTsmRptField->u4MultiRetryCnt = prTsmStatistic->u4PktRetryTxDoneOK; + prTsmRptField->u4CfPollLostCnt = prTsmStatistic->u4PktQosCfPollLost; + prTsmRptField->u4AvgQueDelay = prTsmStatistic->u4AvgPktQueueDelay; + prTsmRptField->u4AvgDelay = prTsmStatistic->u4AvgPktTxDelay; + prTsmRptField->ucBin0Range = prCurrentTsmReq->prTsmReq->ucB0Range; + kalMemCopy(&prTsmRptField->u4Bin[0], &prTsmStatistic->au4PktCntBin[0], + sizeof(prTsmStatistic->au4PktCntBin)); + prRmRep->u2ReportFrameLen += u2IeSize; + /* For normal TSM, only once measurement */ + if (prCurrentTsmReq->prTsmReq->u2Duration) { + struct RM_TSM_REQ *prTsmReq = NULL; + struct CMD_SET_TSM_STATISTICS_REQUEST rTsmStatistics; + + wmmRemoveTSM(prAdapter, prCurrentTsmReq, FALSE); + /* Resume all triggered tsm whose TC is same with this normal + ** tsm + */ + LINK_FOR_EACH_ENTRY(prCurrentTsmReq, &prWMMInfo->rActiveTsmReq, + rLinkEntry, struct ACTIVE_RM_TSM_REQ) + { + prTsmReq = prCurrentTsmReq->prTsmReq; + if (prTsmReq->u2Duration || + prTsmReq->ucACI != prTsmStatistic->ucAcIndex) + continue; + + nicTxChangeDataPortByAc( + prAdapter->prAisBssInfo->prStaRecOfAP, + prTsmReq->ucACI, TRUE); + kalMemZero(&rTsmStatistics, sizeof(rTsmStatistics)); + rTsmStatistics.ucBssIdx = + prAdapter->prAisBssInfo->ucBssIndex; + rTsmStatistics.ucEnabled = TRUE; + rTsmStatistics.ucAcIndex = prTsmReq->ucACI; + rTsmStatistics.ucTid = prTsmReq->ucTID; + COPY_MAC_ADDR(rTsmStatistics.aucPeerAddr, + prTsmReq->aucPeerAddr); + rTsmStatistics.ucTriggerCondition = + prTsmReq->rTriggerCond.ucCondition; + rTsmStatistics.ucMeasureCount = + prTsmReq->rTriggerCond.ucMeasureCount; + rTsmStatistics.ucTriggerTimeout = + prTsmReq->rTriggerCond.ucTriggerTimeout; + rTsmStatistics.ucAvgErrThreshold = + prTsmReq->rTriggerCond.ucAvgErrThreshold; + rTsmStatistics.ucConsecutiveErrThreshold = + prTsmReq->rTriggerCond.ucConsecutiveErr; + rTsmStatistics.ucDelayThreshold = + prTsmReq->rTriggerCond.ucDelayThreshold; + rTsmStatistics.ucBin0Range = prTsmReq->ucB0Range; + wlanSendSetQueryCmd( + prAdapter, CMD_ID_SET_TSM_STATISTICS_REQUEST, + TRUE, FALSE, FALSE, NULL, NULL, + sizeof(rTsmStatistics), + (uint8_t *)&rTsmStatistics, NULL, 0); + } + /* schedule next measurement after a duration based TSM done */ + rlmScheduleNextRm(prAdapter); + } else { + /* Triggered TSM, we should send TSM report to peer if the first + ** report time to now more than 10 second + */ + OS_SYSTIME rCurrent = kalGetTimeTick(); + + if (prWMMInfo->rTriggeredTsmRptTime == 0) + prWMMInfo->rTriggeredTsmRptTime = rCurrent; + else if (CHECK_FOR_TIMEOUT(rCurrent, + prWMMInfo->rTriggeredTsmRptTime, + 10000)) { + rlmTxRadioMeasurementReport(prAdapter); + prWMMInfo->rTriggeredTsmRptTime = 0; + } + } +} + +void wmmNotifyDisconnected(struct ADAPTER *prAdapter) +{ + uint8_t ucTid = 0; + + for (; ucTid < WMM_TSPEC_ID_NUM; ucTid++) + wmmTspecSteps(prAdapter, ucTid, DISC_DELTS_REQ, NULL); + wmmRemoveAllTsmMeasurement(prAdapter, FALSE); +#if CFG_SUPPORT_SOFT_ACM + kalMemZero(&prAdapter->rWifiVar.rWmmInfo.arAcmCtrl[0], + sizeof(prAdapter->rWifiVar.rWmmInfo.arAcmCtrl)); +#endif +} + +u_int8_t wmmTsmIsOngoing(struct ADAPTER *prAdapter) +{ + return !LINK_IS_EMPTY(&prAdapter->rWifiVar.rWmmInfo.rActiveTsmReq); +} + +/* This function implements TS replacement rule + ** Replace case base on same AC: + ** 1. old: Uni-dir; New: Bi-dir or same dir with old + ** 2. old: Bi-dir; New: Bi-dir or Uni-dir + ** 3. old: two diff Uni-dir; New: Bi-dir + ** for detail, see WMM spec V1.2.0, section 3.5 + */ +static void wmmMayDoTsReplacement(struct ADAPTER *prAdapter, uint8_t ucNewTid) +{ + struct TSPEC_INFO *prTspec = &prAdapter->rWifiVar.rWmmInfo.arTsInfo[0]; + uint8_t ucTid = 0; + + for (; ucTid < WMM_TSPEC_ID_NUM; ucTid++) { + if (ucTid == ucNewTid) + continue; + if (prTspec[ucTid].eState != QOS_TS_ACTIVE || + prTspec[ucTid].eAC != prTspec[ucNewTid].eAC) + continue; + if (prTspec[ucNewTid].eDir != prTspec[ucTid].eDir && + prTspec[ucNewTid].eDir < BI_DIR_TS && + prTspec[ucTid].eDir < BI_DIR_TS) + continue; + prTspec[ucTid].eAC = ACI_NUM; + prTspec[ucTid].eState = QOS_TS_INACTIVE; + } + wmmDumpActiveTspecs(prAdapter, NULL, 0); +} + +uint32_t wmmDumpActiveTspecs(struct ADAPTER *prAdapter, uint8_t *pucBuffer, + uint16_t u2BufferLen) +{ + uint8_t ucTid = 0; + int32_t i4BytesWritten = 0; + struct TSPEC_INFO *prTspec = &prAdapter->rWifiVar.rWmmInfo.arTsInfo[0]; + + for (; ucTid < WMM_TSPEC_ID_NUM; ucTid++, prTspec++) { + if (prTspec->eState != QOS_TS_ACTIVE) + continue; + if (u2BufferLen > 0 && pucBuffer) { + i4BytesWritten += kalSnprintf( + pucBuffer + i4BytesWritten, u2BufferLen, + "Tid %d, AC %d, Dir %d, Uapsd %d, MediumTime %d, PhyRate %u\n", + ucTid, prTspec->eAC, prTspec->eDir, + prTspec->fgUapsd, prTspec->u2MediumTime, + prTspec->u4PhyRate); + if (i4BytesWritten <= 0) + break; + u2BufferLen -= (uint16_t)i4BytesWritten; + } else + DBGLOG(WMM, INFO, + "Tid %d, AC %d, Dir %d, Uapsd %d, MediumTime %d, PhyRate %u\n", + ucTid, prTspec->eAC, prTspec->eDir, + prTspec->fgUapsd, prTspec->u2MediumTime, + prTspec->u4PhyRate); + } + if (u2BufferLen > 0 && pucBuffer) { + struct STA_RECORD *prStaRec = NULL; + + if (prAdapter->prAisBssInfo && + prAdapter->prAisBssInfo->prStaRecOfAP) { + prStaRec = prAdapter->prAisBssInfo->prStaRecOfAP; + i4BytesWritten += kalSnprintf( + pucBuffer + i4BytesWritten, u2BufferLen, + "\nACM status for AP %pM:\nBE %d; BK %d; VI %d; VO %d\n", + prStaRec->aucMacAddr, + prStaRec->afgAcmRequired[ACI_BE], + prStaRec->afgAcmRequired[ACI_BK], + prStaRec->afgAcmRequired[ACI_VI], + prStaRec->afgAcmRequired[ACI_VO]); + } else + i4BytesWritten += kalSnprintf( + pucBuffer + i4BytesWritten, u2BufferLen, "%s\n", + "Didn't connect to a AP"); + } + return (uint32_t)i4BytesWritten; +} + +#if CFG_SUPPORT_SOFT_ACM +/* u2PktLen: Ethernet payload length, exclude eth header. + ** Return value: estimated tx time in unit us. + */ +uint32_t wmmCalculatePktUsedTime(struct BSS_INFO *prBssInfo, + struct STA_RECORD *prStaRec, uint16_t u2PktLen) +{ + uint8_t ucSecurityPadding = 0; + int8_t i = 0; + uint32_t u4TxTime = 0; + uint8_t ucFlags = 0; + + ASSERT(prBssInfo); + ASSERT(prStaRec); + switch (prBssInfo->u4RsnSelectedPairwiseCipher) { + case RSN_CIPHER_SUITE_CCMP: + ucSecurityPadding = 16; + break; + case RSN_CIPHER_SUITE_TKIP: + ucSecurityPadding = 20; + break; + case RSN_CIPHER_SUITE_WEP104: + case RSN_CIPHER_SUITE_WEP40: + ucSecurityPadding = 8; + break; + default: + ucSecurityPadding = 0; + break; + } + /* ToDo: 802.11AC? WMM-AC didn't support 802.11AC now */ + if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11N) { + if (prBssInfo->fg40mBwAllowed) { + if (prStaRec->u2HtCapInfo & HT_CAP_INFO_SHORT_GI_40M) + ucFlags |= FLAG_SHORT_GI; + ucFlags |= FLAG_40M_BW; + } else if (prStaRec->u2HtCapInfo & HT_CAP_INFO_SHORT_GI_20M) + ucFlags |= FLAG_SHORT_GI; + + u4TxTime = wmmAcmTxTimeHtCal(ucSecurityPadding, u2PktLen, 7, + ucFlags); + DBGLOG(WMM, INFO, + "MCS 7, Tx %d bytes, SecExtra %d bytes, Flags %02x, Time %u us\n", + u2PktLen, ucSecurityPadding, ucFlags, u4TxTime); + } else { + uint16_t u2DataRate = RATE_54M; + + if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_802_11G) { + u2DataRate = RATE_54M; + for (i = 13; i >= 4; i--) { + if ((prStaRec->u2BSSBasicRateSet & BIT(i)) && + aucDataRate[i] <= u2DataRate) + break; + } + ucFlags |= FLAG_G_MODE; + } else if (prStaRec->ucDesiredPhyTypeSet & + (PHY_TYPE_802_11B | PHY_CONFIG_802_11A)) { + u2DataRate = RATE_11M; + for (i = 3; i >= 0; i--) { + if ((prStaRec->u2BSSBasicRateSet & BIT(i)) && + aucDataRate[i] <= u2DataRate) + break; + } + } + if (prBssInfo->fgUseShortPreamble) + ucFlags |= FLAG_S_PREAMBLE; + u4TxTime = wmmAcmTxTimeCal(ucSecurityPadding, u2PktLen, + u2DataRate, aucDataRate[i], ucFlags); + DBGLOG(WMM, INFO, + "DataRate %d, BasicRate %d, Tx %d bytes, SecExtra %d bytes, Flags %02x, Time %u us\n", + u2DataRate, aucDataRate[i], u2PktLen, ucSecurityPadding, + ucFlags, u4TxTime); + } + return u4TxTime; +} + +/* 1. u4PktTxTime is 0, this function give a fast check if remain medium time is + *enough to Deq + ** 2. u4PktTxTime is not 0, if remain medium time is greater than u4PktTxTime, + *statistic deq number + ** and remain time. Otherwise, start a timer to schedule next dequeue + *interval + ** return value: + ** TRUE: Can dequeue + ** FALSE: No time to dequeue + */ +u_int8_t wmmAcmCanDequeue(struct ADAPTER *prAdapter, uint8_t ucAc, + uint32_t u4PktTxTime) +{ + struct SOFT_ACM_CTRL *prAcmCtrl = NULL; + struct WMM_INFO *prWmmInfo = &prAdapter->rWifiVar.rWmmInfo; + uint32_t u4CurTime = 0; + struct timespec ts; + + prAcmCtrl = &prWmmInfo->arAcmCtrl[ucAc]; + if (!prAcmCtrl->u4AdmittedTime) + return FALSE; + get_monotonic_boottime(&ts); + u4CurTime = ts.tv_sec; + if (!TIME_BEFORE(u4CurTime, prAcmCtrl->u4IntervalEndSec)) { + u4CurTime++; + DBGLOG(WMM, INFO, + "AC %d, Admitted %u, LastEnd %u, NextEnd %u, LastUsed %u, LastDeq %d\n", + ucAc, prAcmCtrl->u4AdmittedTime, + prAcmCtrl->u4IntervalEndSec, u4CurTime, + prAcmCtrl->u4AdmittedTime - prAcmCtrl->u4RemainTime, + prAcmCtrl->u2DeqNum); + prAcmCtrl->u4IntervalEndSec = u4CurTime; + prAcmCtrl->u4RemainTime = prAcmCtrl->u4AdmittedTime; + prAcmCtrl->u2DeqNum = 0; + /* Stop the next dequeue timer due to we will dequeue right now. + */ + if (timerPendingTimer(&prWmmInfo->rAcmDeqTimer)) + cnmTimerStopTimer(prAdapter, &prWmmInfo->rAcmDeqTimer); + } + if (!u4PktTxTime) { + DBGLOG(WMM, TRACE, "AC %d, can dq %d\n", ucAc, + (prAcmCtrl->u4RemainTime > 0)); + return (prAcmCtrl->u4RemainTime > 0); + } + /* If QM request to dequeue, and have enough medium time, then dequeue + */ + if (prAcmCtrl->u4RemainTime >= u4PktTxTime) { + prAcmCtrl->u2DeqNum++; + prAcmCtrl->u4RemainTime -= u4PktTxTime; + DBGLOG(WMM, INFO, "AC %d, Remain %u, DeqNum %d\n", ucAc, + prAcmCtrl->u4RemainTime, prAcmCtrl->u2DeqNum); + if (prAcmCtrl->u4RemainTime > 0) + return TRUE; + } + /* If not enough medium time to dequeue next packet, should start a + * timer to schedue next dequeue + * We didn't consider the case u4RemainTime is enough to dequeue + * packets except the head of the + * station tx queue, because it is too complex to implement dequeue + * routine. + * We should reset u4RemainTime to 0, used to skip next dequeue request + * if still in this deq interval. + * the dequeue interval is 1 second according to WMM-AC specification. + */ + prAcmCtrl->u4RemainTime = 0; + /* Start a timer to schedule next dequeue interval, since application + * may stop sending data to driver, + * but driver still pending some data to dequeue + */ + if (!timerPendingTimer(&prWmmInfo->rAcmDeqTimer)) { + uint32_t u4EndMsec = prAcmCtrl->u4IntervalEndSec * 1000; + + get_monotonic_boottime(&ts); + u4CurTime = ts.tv_sec * MSEC_PER_SEC; + u4CurTime += ts.tv_nsec / NSEC_PER_MSEC; + /* It is impossible that u4EndMsec is less than u4CurTime */ + u4EndMsec = u4EndMsec - u4CurTime + + 20; /* the timeout duration at least 2 jiffies */ + cnmTimerStartTimer(prAdapter, &prWmmInfo->rAcmDeqTimer, + u4EndMsec); + DBGLOG(WMM, INFO, + "AC %d, will start next deq interval after %u ms\n", + ucAc, u4EndMsec); + } + return FALSE; +} + +static uint16_t wmmAcmTxTimePLCPCal(uint16_t u2Length, uint16_t u2Rate, + uint8_t FlgIsGmode) +{ + uint16_t u2PLCP; + + if (FlgIsGmode) { + u2Rate <<= 1; + /* EX1: BodyLen = 30B and rate = 54Mbps, + * 1. additional 22 bit in PSDU + * PLCP = 30*8 + 22 = 262 bits + * 2. round_up{X / 4} * 4 means OFDM symbol is in unit of 4 + * usec + * PLCP = (262/54) = 4.8xxx us + * 4.8xxx / 4 = 1.2xxx + * 3. PLCP = round up(1.2xxx) * 4 = 2 * 4 = 8 us + * EX2: BodyLen = 14B and rate = 6Mbps, + * 1. additional 22 bit in PSDU + * PLCP = 14*8 + 22 = 134 bits + * 2. round_up{X / 4} * 4 means OFDM symbol is in unit of 4 + * usec + * PLCP = (134/6) = 22.3xxx us + * 22.3xxx / 4 = 5.583xxx + * 3. PLCP = round up(5.583xxx) * 4 = 6 * 4 = 24 us + */ + u2PLCP = (u2Length << 3) + 22; /* need to add 22 bits in 11g */ + u2PLCP = (u2PLCP % u2Rate) ? (u2PLCP / u2Rate) + 1 + : (u2PLCP / u2Rate); + return u2PLCP << 2; + } + + /* ex: BodyLen = 30B and rate = 11Mbps, PLCP = 30 * 8 / 11 = 22us */ + return (u2Length << 4) / u2Rate; +} + +/* For G mode, no long or short preamble time, only long (20us) or short slot + ** time (9us). + */ +static uint16_t wmmAcmTxTimeCal(uint16_t u2SecExtra, uint16_t u2EthBodyLen, + uint16_t u2DataRate, uint16_t u2BasicRate, + uint8_t ucFlags) +{ + uint16_t u2TxTime = 0; + uint16_t u2PreambleTime = 0; + u_int8_t fgIsGMode = !!(ucFlags & FLAG_G_MODE); + + u2PreambleTime = + LMR_PREAMBL_TIME(fgIsGMode, !!(ucFlags & FLAG_S_PREAMBLE)); + + /* CTS-self */ + if (ucFlags & FLAG_CTS_SELF) { + u2TxTime = u2PreambleTime + TIME_SIFSG; + u2TxTime += wmmAcmTxTimePLCPCal(FRM_LENGTH_ACK, u2BasicRate, + fgIsGMode); + } else if (ucFlags & FLAG_RTS_CTS) { /* CTS + RTS */ + u2TxTime = 2 * u2PreambleTime + + (fgIsGMode ? TIME_SIFSGx2 : TIME_SIFSx2); + u2TxTime += wmmAcmTxTimePLCPCal(FRM_LENGTH_RTS + FRM_LENGTH_ACK, + u2BasicRate, fgIsGMode); + } + /* Data Pkt Preamble Time + RTS/CTS time + 802.11 QoS hdr + LLC header + + ** Ethernet Payload + sec extra + FCS + */ + u2TxTime += u2PreambleTime + + wmmAcmTxTimePLCPCal(WLAN_MAC_HEADER_QOS_LEN + 8 + + u2EthBodyLen + u2SecExtra + 4, + u2DataRate, fgIsGMode); + /* Ack frame for data packet. Preamble + Ack + SIFS */ + u2TxTime += + wmmAcmTxTimePLCPCal(FRM_LENGTH_ACK, u2BasicRate, fgIsGMode) + + (fgIsGMode ? TIME_SIFSG : TIME_SIFS) + u2PreambleTime; + return u2TxTime; +} + +/* Reference to Draft802.11n_D3.07, Transmission Time = + ** 1. Mix mode, short GI + ** TXTIME = T_LEG_PREAMBLE + T_L_SIG + T_HT_PREAMBLE + T_HT_SIG + + ** T_SYM * Ceiling{T_SYMS * N_SYM / T_SYM} + ** 2. Mix mode, regular GI + ** TXTIME = T_LEG_PREAMBLE + T_L_SIG + T_HT_PREAMBLE + T_HT_SIG + + ** T_SYM * N_SYM + ** 3. GreenField mode, short GI + ** TXTIME = T_GF_HT_PREAMBLE + T_HT_SIG + T_SYMS * N_SYM + ** 4. GreenField mode, regular GI + ** TXTIME = T_GF_HT_PREAMBLE + T_HT_SIG + T_SYM * N_SYM + ** Where + ** (1) T_LEG_PREAMBLE = T_L_STF + T_L_LTF = 8 + 8 = 16 us + ** (2) T_L_SIG = 4 us + ** (3) T_HT_PREAMBLE = T_HT_STF + T_HT_LTF1 + (N_LTF - 1) * T_HT_LTFS + ** = 4 + 4 + ((N_DLTF + N_ELTF) - 1) * 4 + ** EX: Nss = 2, N_DLTF = 2, Ness = 0, N_ELTF = 0, T_HT_PREAMBLE = 12 us + ** (4) T_HT_SIG = 8 us + ** (5) T_SYM = 4 us + ** (6) T_SYMS = 3.6 us + ** (7) N_SYM = mSTBC * Ceil((8*len+16+6*N_ES)/(mSTBC * + *N_DBPS)) + ** (8) T_GF_HT_PREAMBLE= T_HT_GF_STF + T_HT_LTF1 + (N_LTF - 1) * T_HT_LTFS + ** = 8 + 4 + ((N_DLTF + N_ELTF) - 1) * 4 + */ +static uint16_t wmmAcmTxTimeHtPLCPCal(uint16_t u2Length, uint8_t ucMcsId, + uint8_t ucNess, uint8_t ucFlags) +{ + uint32_t T_LEG_PREAMBLE, T_L_SIG, T_HT_PREAMBLE, T_HT_SIG; + uint32_t T_SYM, T_SYMS, N_SYM; + uint32_t T_GF_HT_PREAMBLE; + uint32_t TxTime; + uint32_t N_DLTF[5] = {1, 1, 2, 4, 4}; + uint32_t N_ELTF[4] = {0, 1, 2, 4}; + uint32_t N_SYM_1_NUM; /* numerator of N_SYM */ + uint8_t ucBwId = (ucFlags & FLAG_40M_BW) ? 1 : 0; + uint8_t ucNss = 0; + static const uint16_t gAcmRateNdbps[2][32] = { + /* MCS0 ~ MCS31 */ + /* 20MHz */ + {26, 52, 78, 104, 156, 208, 234, 260, 52, 104, 156, + 208, 312, 416, 468, 520, 78, 156, 234, 312, 468, 624, + 702, 780, 104, 208, 312, 416, 624, 832, 936, 1040}, + + /* MCS0 ~ MCS31 */ + /* 40MHz */ + {54, 108, 162, 216, 324, 432, 486, 540, 108, 216, 324, + 432, 648, 864, 972, 1080, 162, 324, 486, 648, 972, 1296, + 1458, 1620, 216, 432, 648, 864, 1296, 1728, 1944, 2160}, + }; + + /* init */ + T_LEG_PREAMBLE = 16; + T_L_SIG = 4; + T_HT_SIG = 8; + T_SYM = 4; + T_SYMS = 36; /* unit: 0.1us */ + TxTime = 0; + + if (ucMcsId < 8) + ucNss = 1; + else if (ucMcsId < 16) + ucNss = 2; + else if (ucMcsId < 24) + ucNss = 3; + else if (ucMcsId < 32) + ucNss = 4; + else { + ucMcsId = 31; + ucNss = 1; + } + /* calculate N_SYM */ + /* ex: 1538B, 1st MPDU of AMPDU, (1538 * 8 + 22)/1080 + 1 = 12 */ + /* STBC is not used, BCC is used */ + N_SYM = ((u2Length << 3) + 16 + 6) / gAcmRateNdbps[ucBwId][ucMcsId] + 1; + + /* calculate transmission time */ + if (!(ucFlags & FLAG_GF_HT)) { + /* ex: 1538B, 1st MPDU of AMPDU, 4 + 4 + 2*4 = 16us */ + T_HT_PREAMBLE = + 4 + 4 + ((N_DLTF[ucNss] + N_ELTF[ucNess] - 1) << 2); + + /* ex: 1538B, 1st MPDU of AMPDU, 16 + 4 + 16 + 8 = 44us */ + if (!(ucFlags & FLAG_ONLY_DATA)) + TxTime = T_LEG_PREAMBLE + T_L_SIG + T_HT_PREAMBLE + + T_HT_SIG; + + /* End of if */ + + /* ex: 1538B, 1st MPDU of AMPDU, 4 * 12 = 48us */ + if (!(ucFlags & FLAG_SHORT_GI)) + TxTime += T_SYM * N_SYM; + else { + N_SYM_1_NUM = (T_SYMS * N_SYM) / (T_SYM * 10); + + if ((T_SYMS * N_SYM) % (T_SYM * 10)) + N_SYM_1_NUM++; + + TxTime += T_SYM * N_SYM_1_NUM; + } /* End of if */ + } else { + T_GF_HT_PREAMBLE = + 8 + 4 + ((N_DLTF[ucNss] + N_ELTF[ucNess] - 1) << 2); + + if (!(ucFlags & FLAG_ONLY_DATA)) + TxTime = T_GF_HT_PREAMBLE + T_HT_SIG; + + TxTime += (ucFlags & FLAG_SHORT_GI) ? ((T_SYMS * N_SYM) / 10) + : (T_SYM * N_SYM); + } /* End of if */ + + return TxTime; +} /* End of ACM_TX_TimePlcpCalHT */ + +static uint16_t wmmAcmTxTimeHtCal(uint16_t u2SecExtra, uint16_t u2EthBodyLen, + uint8_t ucMcsId, uint8_t ucFlags) +{ + uint16_t u2PreambleTime = 0; + uint16_t u2TxTime = 0; + + u2PreambleTime = LMR_PREAMBL_TIME(TRUE, !!(ucFlags & FLAG_S_PREAMBLE)); + if (ucFlags & FLAG_RTS_CTS) { + /* add RTS/CTS 24Mbps time */ + u2TxTime += 2 * u2PreambleTime + TIME_SIFSGx2; + u2TxTime += wmmAcmTxTimePLCPCal(FRM_LENGTH_RTS + FRM_LENGTH_ACK, + RATE_24M, TRUE); + } + /* SIFS + ACK, always use G mode to calculate preamble */ + + u2TxTime += TIME_SIFSG + u2PreambleTime; + /* always use block ack to calculate ack time */ + u2TxTime += wmmAcmTxTimePLCPCal(FRM_LENGTH_BLOCK_ACK, RATE_24M, TRUE); + + /* Data Pkt Preamble Time + RTS/CTS time + 802.11 QoS hdr + LLC header + + ** Ethernet Payload + sec extra + FCS + ** Nss always set to 1 due to only + */ + u2TxTime += wmmAcmTxTimeHtPLCPCal(WLAN_MAC_HEADER_QOS_LEN + 8 + + u2EthBodyLen + u2SecExtra + 4, + ucMcsId, 0, ucFlags); + + return u2TxTime; +} /* End of ACM_TX_TimeCalHT */ + +static void wmmAcmDequeueTimeOut(IN struct ADAPTER *prAdapter, + unsigned long ulParamPtr) +{ + DBGLOG(WMM, INFO, "Timeout, trigger to do ACM dequeue\n"); + kalSetEvent(prAdapter->prGlueInfo); +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/wnm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/wnm.c new file mode 100644 index 0000000000000..dc5ae3a30218b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7663/mgmt/wnm.c @@ -0,0 +1,642 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + ** 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. + */ + +/******************************************************************************* + * C O M P I L E 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 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 + ******************************************************************************* + */ +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT +static uint8_t ucTimingMeasToken; +#endif +static uint8_t ucBtmMgtToken = 1; + +/******************************************************************************* + * M A C R O S + ******************************************************************************* + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************* + */ +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT +static uint32_t +wnmRunEventTimgingMeasTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus); + +static void wnmComposeTimingMeasFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler); + +static void wnmTimingMeasRequest(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb); +#endif +/******************************************************************************* + * 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 struct ADAPTER *prAdapter, IN struct SW_RFB *prSwRfb) +{ + struct WLAN_ACTION_FRAME *prRxFrame; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxFrame = (struct WLAN_ACTION_FRAME *)prSwRfb->pvHeader; + + DBGLOG(WNM, TRACE, "WNM action frame: %d from " MACSTR "\n", + prRxFrame->ucAction, MAC2STR(prRxFrame->aucSrcAddr)); + + switch (prRxFrame->ucAction) { +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT + case ACTION_WNM_TIMING_MEASUREMENT_REQUEST: + wnmTimingMeasRequest(prAdapter, prSwRfb); + break; +#endif +#if CFG_SUPPORT_802_11V_BSS_TRANSITION_MGT + case ACTION_WNM_BSS_TRANSITION_MANAGEMENT_REQ: +#endif + case ACTION_WNM_NOTIFICATION_REQUEST: + default: + DBGLOG(RX, INFO, + "WNM: action frame %d, try to send to supplicant\n", + prRxFrame->ucAction); + aisFuncValidateRxActionFrame(prAdapter, prSwRfb); + break; + } +} + +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT +/*----------------------------------------------------------------------------*/ +/*! + * + * \brief This routine is called to report timing measurement data. + * + */ +/*----------------------------------------------------------------------------*/ +void wnmReportTimingMeas(IN struct ADAPTER *prAdapter, IN uint8_t ucStaRecIndex, + IN uint32_t u4ToD, IN uint32_t u4ToA) +{ + struct STA_RECORD *prStaRec; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIndex); + + if ((!prStaRec) || (!prStaRec->fgIsInUse)) + return; + + DBGLOG(WNM, TRACE, "WNM: 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 + */ +/*----------------------------------------------------------------------------*/ +static uint32_t +wnmRunEventTimgingMeasTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + struct STA_RECORD *prStaRec; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + DBGLOG(WNM, LOUD, "WNM: 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, + "WNM: 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) + */ +/*----------------------------------------------------------------------------*/ +static void wnmComposeTimingMeasFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + struct MSDU_INFO *prMsduInfo; + struct BSS_INFO *prBssInfo; + struct ACTION_UNPROTECTED_WNM_TIMING_MEAS_FRAME *prTxFrame; + uint16_t u2PayloadLen; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; + ASSERT(prBssInfo); + + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc( + prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + prTxFrame = (struct ACTION_UNPROTECTED_WNM_TIMING_MEAS_FRAME + *)((uint32_t)(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 */ + TX_SET_MMPDU(prAdapter, prMsduInfo, prStaRec->ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, pfTxDoneHandler, + MSDU_RATE_MODE_AUTO); + + DBGLOG(WNM, TRACE, + "WNM: 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 + */ +/*----------------------------------------------------------------------------*/ +static void wnmTimingMeasRequest(IN struct ADAPTER *prAdapter, + IN struct SW_RFB *prSwRfb) +{ + struct ACTION_WNM_TIMING_MEAS_REQ_FRAME *prRxFrame = NULL; + struct STA_RECORD *prStaRec; + + prRxFrame = + (struct ACTION_WNM_TIMING_MEAS_REQ_FRAME *)prSwRfb->pvHeader; + if (!prRxFrame) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if ((!prStaRec) || (!prStaRec->fgIsInUse)) + return; + + DBGLOG(WNM, TRACE, + "WNM: 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(struct ADAPTER *prAdapter, uint8_t ucStaRecIndex) +{ + struct STA_RECORD *prStaRec; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIndex); + if ((!prStaRec) || (!prStaRec->fgIsInUse)) + return; + DBGLOG(WNM, INFO, + "WNM: 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 */ + +uint8_t wnmGetBtmToken(void) +{ + return ucBtmMgtToken++; +} + +static uint32_t wnmBTMQueryTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + DBGLOG(WNM, INFO, "BTM: Query Frame Tx Done, Status %d\n", + rTxDoneStatus); + return WLAN_STATUS_SUCCESS; +} + +static uint32_t wnmBTMResponseTxDone(IN struct ADAPTER *prAdapter, + IN struct MSDU_INFO *prMsduInfo, + IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) +{ + struct BSS_TRANSITION_MGT_PARAM_T *prBtm = + &prAdapter->rWifiVar.rAisSpecificBssInfo.rBTMParam; + struct AIS_FSM_INFO *prAisFsmInfo = &prAdapter->rWifiVar.rAisFsmInfo; + + DBGLOG(WNM, INFO, "BTM: Response Frame Tx Done Status %d\n", + rTxDoneStatus); + if (prBtm->fgPendingResponse && + prAisFsmInfo->eCurrentState == AIS_STATE_SEARCH) { + prBtm->fgPendingResponse = FALSE; + aisFsmSteps(prAdapter, AIS_STATE_REQ_CHANNEL_JOIN); + } + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will compose the BTM Response frame. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] prStaRec Pointer to the STA_RECORD_T. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void wnmSendBTMResponseFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + struct MSDU_INFO *prMsduInfo = NULL; + struct BSS_INFO *prBssInfo = NULL; + struct ACTION_BTM_RSP_FRAME *prTxFrame = NULL; + uint16_t u2PayloadLen = 0; + struct BSS_TRANSITION_MGT_PARAM_T *prBtmParam = + &prAdapter->rWifiVar.rAisSpecificBssInfo.rBTMParam; + uint8_t *pucOptInfo = NULL; + + if (!prStaRec) { + DBGLOG(WNM, INFO, "BTM: No station record found\n"); + return; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + ASSERT(prBssInfo); + + /* 1 Allocate MSDU Info */ + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc( + prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + if (!prMsduInfo) + return; + prTxFrame = (struct ACTION_BTM_RSP_FRAME + *)((unsigned long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + + /* 2 Compose The Mac Header. */ + 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_WNM_ACTION; + prTxFrame->ucAction = ACTION_WNM_BSS_TRANSITION_MANAGEMENT_RSP; + + /* 3 Compose the frame body's frame. */ + prTxFrame->ucDialogToken = prBtmParam->ucDialogToken; + prBtmParam->ucDialogToken = 0; /* reset dialog token */ + prTxFrame->ucStatusCode = prBtmParam->ucStatusCode; + prTxFrame->ucBssTermDelay = prBtmParam->ucTermDelay; + pucOptInfo = &prTxFrame->aucOptInfo[0]; + if (prBtmParam->ucStatusCode == BSS_TRANSITION_MGT_STATUS_ACCEPT) { + COPY_MAC_ADDR(pucOptInfo, prBtmParam->aucTargetBssid); + pucOptInfo += MAC_ADDR_LEN; + u2PayloadLen += MAC_ADDR_LEN; + } + if (prBtmParam->u2OurNeighborBssLen > 0) { + kalMemCopy(pucOptInfo, prBtmParam->pucOurNeighborBss, + prBtmParam->u2OurNeighborBssLen); + kalMemFree(prBtmParam->pucOurNeighborBss, VIR_MEM_TYPE, + prBtmParam->u2OurNeighborBssLen); + prBtmParam->u2OurNeighborBssLen = 0; + u2PayloadLen += prBtmParam->u2OurNeighborBssLen; + } + + /* 4 Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, prMsduInfo, prStaRec->ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_MGMT_HEADER_LEN, + OFFSET_OF(struct ACTION_BTM_RSP_FRAME, aucOptInfo) + + u2PayloadLen, + wnmBTMResponseTxDone, MSDU_RATE_MODE_AUTO); + + /* 5 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); +} /* end of wnmComposeBTMResponseFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This function will compose the BTM Query frame. + * + * @param[in] prAdapter Pointer to the Adapter structure. + * @param[in] prStaRec Pointer to the STA_RECORD_T. + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void wnmSendBTMQueryFrame(IN struct ADAPTER *prAdapter, + IN struct STA_RECORD *prStaRec) +{ + struct MSDU_INFO *prMsduInfo = NULL; + struct BSS_INFO *prBssInfo = NULL; + struct ACTION_BTM_QUERY_FRAME *prTxFrame = NULL; + struct BSS_TRANSITION_MGT_PARAM_T *prBtmParam = + &prAdapter->rWifiVar.rAisSpecificBssInfo.rBTMParam; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + ASSERT(prBssInfo); + + /* 1 Allocate MSDU Info */ + prMsduInfo = (struct MSDU_INFO *)cnmMgtPktAlloc( + prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + if (!prMsduInfo) + return; + prTxFrame = (struct ACTION_BTM_QUERY_FRAME + *)((unsigned long)(prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + + /* 2 Compose The Mac Header. */ + 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_WNM_ACTION; + prTxFrame->ucAction = ACTION_WNM_BSS_TRANSITION_MANAGEMENT_QUERY; + + /* 3 Compose the frame body's frame. */ + prTxFrame->ucDialogToken = prBtmParam->ucDialogToken; + prTxFrame->ucQueryReason = prBtmParam->ucQueryReason; + if (prBtmParam->u2OurNeighborBssLen > 0) { + kalMemCopy(prTxFrame->pucNeighborBss, + prBtmParam->pucOurNeighborBss, + prBtmParam->u2OurNeighborBssLen); + kalMemFree(prBtmParam->pucOurNeighborBss, VIR_MEM_TYPE, + prBtmParam->u2OurNeighborBssLen); + prBtmParam->u2OurNeighborBssLen = 0; + } + + /* 4 Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, prMsduInfo, prStaRec->ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + 4 + + prBtmParam->u2OurNeighborBssLen, + wnmBTMQueryTxDone, MSDU_RATE_MODE_AUTO); + + /* 5 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); +} /* end of wnmComposeBTMQueryFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! + * + * \brief This routine is called to process the 802.11v BTM request. + * + * + * \note + * Handle Rx mgmt request + */ +/*----------------------------------------------------------------------------*/ +void wnmRecvBTMRequest(IN struct ADAPTER *prAdapter, IN struct SW_RFB *prSwRfb) +{ + struct ACTION_BTM_REQ_FRAME *prRxFrame = NULL; + struct BSS_TRANSITION_MGT_PARAM_T *prBtmParam = + &prAdapter->rWifiVar.rAisSpecificBssInfo.rBTMParam; + uint8_t *pucOptInfo = NULL; + uint8_t ucRequestMode = 0; + uint16_t u2TmpLen = 0; + struct MSG_AIS_BSS_TRANSITION_T *prMsg = NULL; + enum WNM_AIS_BSS_TRANSITION eTransType = BSS_TRANSITION_NO_MORE_ACTION; + + prRxFrame = (struct ACTION_BTM_REQ_FRAME *) prSwRfb->pvHeader; + if (!prRxFrame) + return; + if (prSwRfb->u2PacketLen < + OFFSET_OF(struct ACTION_BTM_REQ_FRAME, aucOptInfo)) { + DBGLOG(WNM, WARN, + "BTM: Request frame length is less than a standard BTM frame\n"); + return; + } + prMsg = (struct MSG_AIS_BSS_TRANSITION_T *)cnmMemAlloc( + prAdapter, RAM_TYPE_MSG, + sizeof(struct MSG_AIS_BSS_TRANSITION_T)); + if (!prMsg) { + DBGLOG(WNM, WARN, "BTM: Msg Hdr is NULL\n"); + return; + } + kalMemZero(prMsg, sizeof(*prMsg)); + prBtmParam->ucRequestMode = prRxFrame->ucRequestMode; + prMsg->ucToken = prRxFrame->ucDialogToken; + prBtmParam->u2DisassocTimer = prRxFrame->u2DisassocTimer; + prBtmParam->ucDialogToken = prRxFrame->ucDialogToken; + pucOptInfo = &prRxFrame->aucOptInfo[0]; + ucRequestMode = prBtmParam->ucRequestMode; + u2TmpLen = OFFSET_OF(struct ACTION_BTM_REQ_FRAME, aucOptInfo); + if (ucRequestMode & BTM_REQ_MODE_DISC_IMM) + eTransType = BSS_TRANSITION_REQ_ROAMING; + if (ucRequestMode & BTM_REQ_MODE_BSS_TERM_INCLUDE) { + struct SUB_IE_BSS_TERM_DURATION *prBssTermDuration = + (struct SUB_IE_BSS_TERM_DURATION *)pucOptInfo; + + prBtmParam->u2TermDuration = prBssTermDuration->u2Duration; + kalMemCopy(prBtmParam->aucTermTsf, + prBssTermDuration->aucTermTsf, 8); + pucOptInfo += sizeof(*prBssTermDuration); + u2TmpLen += sizeof(*prBssTermDuration); + eTransType = BSS_TRANSITION_REQ_ROAMING; + } + if (ucRequestMode & BTM_REQ_MODE_ESS_DISC_IMM) { + kalMemCopy(prBtmParam->aucSessionURL, &pucOptInfo[1], + pucOptInfo[0]); + prBtmParam->ucSessionURLLen = pucOptInfo[0]; + u2TmpLen += pucOptInfo[0]; + pucOptInfo += pucOptInfo[0] + 1; + eTransType = BSS_TRANSITION_DISASSOC; + } + if (ucRequestMode & BTM_REQ_MODE_CAND_INCLUDED_BIT) { + if (!(ucRequestMode & BTM_REQ_MODE_ESS_DISC_IMM)) + eTransType = BSS_TRANSITION_REQ_ROAMING; + if (prSwRfb->u2PacketLen > u2TmpLen) { + prMsg->u2CandListLen = prSwRfb->u2PacketLen - u2TmpLen; + prMsg->pucCandList = pucOptInfo; + prMsg->ucValidityInterval = + prRxFrame->ucValidityInterval; + } else + DBGLOG(WNM, WARN, + "BTM: Candidate Include bit is set, but no candidate list\n"); + } + + DBGLOG(WNM, INFO, + "BTM: Req %d, VInt %d, DiscTimer %d, Token %d, TransType %d\n", + prBtmParam->ucRequestMode, prRxFrame->ucValidityInterval, + prBtmParam->u2DisassocTimer, prMsg->ucToken, eTransType); + + prMsg->eTransitionType = eTransType; + prMsg->rMsgHdr.eMsgId = MID_WNM_AIS_BSS_TRANSITION; + /* if BTM Request is dest for broadcast, don't send BTM Response */ + if (kalMemCmp(prRxFrame->aucDestAddr, "\xff\xff\xff\xff\xff\xff", + MAC_ADDR_LEN)) + prMsg->fgNeedResponse = TRUE; + else + prMsg->fgNeedResponse = FALSE; + mboxSendMsg(prAdapter, MBOX_ID_0, (struct MSG_HDR *)prMsg, + MSG_SEND_METHOD_BUF); +} From e7229aa3e68188dc8f7f59451cb52b2d7339586e Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 22:23:48 +0800 Subject: [PATCH 29/32] Add files via upload --- .../wlan/core/gen4-mt7668/Android.mk | 41 + .../wlan/core/gen4-mt7668/Makefile | 320 + .../connectivity/wlan/core/gen4-mt7668/README | 2 + .../wlan/core/gen4-mt7668/chips/mt6632.c | 104 + .../wlan/core/gen4-mt7668/chips/mt7668.c | 144 + .../wlan/core/gen4-mt7668/common/dump.c | 368 + .../wlan/core/gen4-mt7668/common/wlan_bow.c | 3218 ++++ .../wlan/core/gen4-mt7668/common/wlan_lib.c | 10482 +++++++++++++ .../wlan/core/gen4-mt7668/common/wlan_oid.c | 12671 ++++++++++++++++ .../wlan/core/gen4-mt7668/common/wlan_p2p.c | 1512 ++ .../core/gen4-mt7668/init.wlan_mt7668_drv.rc | 2 + .../wlan/core/gen4-mt7668/nic/cmd_buf.c | 239 + .../wlan/core/gen4-mt7668/nic/nic.c | 3712 +++++ .../wlan/core/gen4-mt7668/nic/nic_cmd_event.c | 3978 +++++ .../wlan/core/gen4-mt7668/nic/nic_pwr_mgt.c | 391 + .../wlan/core/gen4-mt7668/nic/nic_rate.c | 445 + .../wlan/core/gen4-mt7668/nic/nic_rx.c | 3570 +++++ .../wlan/core/gen4-mt7668/nic/nic_tx.c | 3934 +++++ .../wlan/core/gen4-mt7668/nic/nic_umac.c | 390 + .../wlan/core/gen4-mt7668/nic/p2p_nic.c | 242 + .../wlan/core/gen4-mt7668/nic/que_mgt.c | 6281 ++++++++ .../core/gen4-mt7668/os/linux/gl_ate_agent.c | 2200 +++ .../wlan/core/gen4-mt7668/os/linux/gl_bow.c | 1169 ++ .../core/gen4-mt7668/os/linux/gl_cfg80211.c | 5108 +++++++ .../core/gen4-mt7668/os/linux/gl_hook_api.c | 3582 +++++ .../wlan/core/gen4-mt7668/os/linux/gl_init.c | 3256 ++++ .../wlan/core/gen4-mt7668/os/linux/gl_kal.c | 5827 +++++++ .../wlan/core/gen4-mt7668/os/linux/gl_p2p.c | 1937 +++ .../gen4-mt7668/os/linux/gl_p2p_cfg80211.c | 3977 +++++ .../core/gen4-mt7668/os/linux/gl_p2p_init.c | 254 + .../core/gen4-mt7668/os/linux/gl_p2p_kal.c | 1692 +++ .../wlan/core/gen4-mt7668/os/linux/gl_proc.c | 2633 ++++ .../core/gen4-mt7668/os/linux/gl_qa_agent.c | 7838 ++++++++++ .../wlan/core/gen4-mt7668/os/linux/gl_rst.c | 672 + .../core/gen4-mt7668/os/linux/gl_vendor.c | 1378 ++ .../wlan/core/gen4-mt7668/os/linux/gl_wext.c | 3910 +++++ .../core/gen4-mt7668/os/linux/gl_wext_priv.c | 11628 ++++++++++++++ .../core/gen4-mt7668/os/linux/hif/ehpi/arm.c | 534 + .../gen4-mt7668/os/linux/hif/ehpi/colibri.c | 534 + .../core/gen4-mt7668/os/linux/hif/ehpi/ehpi.c | 414 + .../os/linux/hif/ehpi/include/colibri.h | 190 + .../os/linux/hif/ehpi/include/hif.h | 138 + .../core/gen4-mt7668/os/linux/hif/pcie/arm.c | 62 + .../gen4-mt7668/os/linux/hif/pcie/hal_api.c | 1737 +++ .../os/linux/hif/pcie/include/hif.h | 242 + .../os/linux/hif/pcie/include/hif_pci.h | 241 + .../os/linux/hif/pcie/include/mtk_porting.h | 92 + .../core/gen4-mt7668/os/linux/hif/pcie/pcie.c | 1165 ++ .../core/gen4-mt7668/os/linux/hif/pcie/x86.c | 62 + .../core/gen4-mt7668/os/linux/hif/sdio/arm.c | 62 + .../gen4-mt7668/os/linux/hif/sdio/hal_api.c | 2227 +++ .../os/linux/hif/sdio/include/hif.h | 336 + .../os/linux/hif/sdio/include/hif_sdio.h | 259 + .../os/linux/hif/sdio/include/mtk_porting.h | 92 + .../core/gen4-mt7668/os/linux/hif/sdio/sdio.c | 1698 +++ .../core/gen4-mt7668/os/linux/hif/sdio/x86.c | 62 + .../gen4-mt7668/os/linux/hif/usb/hal_api.c | 1582 ++ .../os/linux/hif/usb/include/cust_usb_id.h | 116 + .../os/linux/hif/usb/include/hif.h | 419 + .../os/linux/hif/usb/include/hif_usb.h | 131 + .../core/gen4-mt7668/os/linux/hif/usb/usb.c | 1693 +++ .../os/linux/include/gl_ate_agent.h | 199 + .../os/linux/include/gl_cfg80211.h | 351 + .../os/linux/include/gl_hook_api.h | 230 + .../gen4-mt7668/os/linux/include/gl_kal.h | 1289 ++ .../core/gen4-mt7668/os/linux/include/gl_os.h | 1114 ++ .../os/linux/include/gl_p2p_ioctl.h | 720 + .../gen4-mt7668/os/linux/include/gl_p2p_kal.h | 288 + .../gen4-mt7668/os/linux/include/gl_p2p_os.h | 338 + .../os/linux/include/gl_qa_agent.h | 273 + .../gen4-mt7668/os/linux/include/gl_rst.h | 143 + .../gen4-mt7668/os/linux/include/gl_sec.h | 72 + .../gen4-mt7668/os/linux/include/gl_typedef.h | 279 + .../gen4-mt7668/os/linux/include/gl_vendor.h | 758 + .../gen4-mt7668/os/linux/include/gl_wext.h | 366 + .../os/linux/include/gl_wext_priv.h | 437 + .../wlan/core/gen4-mt7668/os/linux/platform.c | 479 + .../wlan/core/gen4-mt7668/os/version.h | 140 + .../gen4-mt7668/prealloc/include/prealloc.h | 62 + .../wlan/core/gen4-mt7668/prealloc/prealloc.c | 246 + 80 files changed, 130979 insertions(+) create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/Android.mk create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/Makefile create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/README create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/chips/mt6632.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/chips/mt7668.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/common/dump.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/common/wlan_bow.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/common/wlan_lib.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/common/wlan_oid.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/common/wlan_p2p.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/init.wlan_mt7668_drv.rc create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/cmd_buf.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic_cmd_event.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic_pwr_mgt.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic_rate.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic_rx.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic_tx.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic_umac.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/p2p_nic.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/que_mgt.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_ate_agent.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_bow.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_cfg80211.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_hook_api.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_init.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_kal.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_p2p.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_p2p_cfg80211.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_p2p_init.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_p2p_kal.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_proc.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_qa_agent.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_rst.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_vendor.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_wext.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_wext_priv.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/ehpi/arm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/ehpi/colibri.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/ehpi/ehpi.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/ehpi/include/colibri.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/ehpi/include/hif.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/pcie/arm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/pcie/hal_api.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/pcie/include/hif.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/pcie/include/hif_pci.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/pcie/include/mtk_porting.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/pcie/pcie.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/pcie/x86.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/arm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/hal_api.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/include/hif.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/include/hif_sdio.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/include/mtk_porting.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/sdio.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/x86.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/usb/hal_api.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/usb/include/cust_usb_id.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/usb/include/hif.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/usb/include/hif_usb.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/usb/usb.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_ate_agent.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_cfg80211.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_hook_api.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_kal.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_os.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_p2p_ioctl.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_p2p_kal.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_p2p_os.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_qa_agent.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_rst.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_sec.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_typedef.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_vendor.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_wext.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_wext_priv.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/platform.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/version.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/prealloc/include/prealloc.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/prealloc/prealloc.c diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/Android.mk b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/Android.mk new file mode 100644 index 0000000000000..c2b5137c0930b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/Android.mk @@ -0,0 +1,41 @@ +LOCAL_PATH := $(call my-dir) +ifeq ($(MTK_WLAN_SUPPORT), yes) +ifneq (true,$(strip $(TARGET_NO_KERNEL))) +ifeq (MT7668,$(strip $(MTK_COMBO_CHIP))) + +include $(CLEAR_VARS) +LOCAL_MODULE := wlan_drv_gen4_mt7668_prealloc.ko +LOCAL_PROPRIETARY_MODULE := true +LOCAL_MODULE_OWNER := mtk +LOCAL_INIT_RC := init.wlan_mt7668_drv.rc +LOCAL_SRC_FILES := $(patsubst $(LOCAL_PATH)/%,%,$(shell find $(LOCAL_PATH) -type f -name '*.[cho]')) Makefile +include $(MTK_KERNEL_MODULE) + +WIFI_OPTS := MTK_COMBO_HIF=$(MTK_COMBO_IF) +$(linked_module): OPTS += $(WIFI_OPTS) + +include $(CLEAR_VARS) +LOCAL_MODULE := wlan_drv_gen4_mt7668.ko +LOCAL_PROPRIETARY_MODULE := true +LOCAL_MODULE_OWNER := mtk +LOCAL_INIT_RC := init.wlan_mt7668_drv.rc +LOCAL_SRC_FILES := $(patsubst $(LOCAL_PATH)/%,%,$(shell find $(LOCAL_PATH) -type f -name '*.[cho]')) Makefile +#LOCAL_REQUIRED_MODULES := wmt_chrdev_wifi.ko +include $(MTK_KERNEL_MODULE) + + +WIFI_OPTS := MTK_COMBO_HIF=$(MTK_COMBO_IF) +$(linked_module): OPTS += $(WIFI_OPTS) + +### Copy Module.symvers from $(LOCAL_REQUIRED_MODULES) to this module ####### +### For symbol link (when CONFIG_MODVERSIONS is defined) +#LOCAL_SRC_EXPORT_SYMBOL := $(subst $(LOCAL_MODULE),$(LOCAL_REQUIRED_MODULES),$(intermediates)/LINKED)/Module.symvers +#$(LOCAL_SRC_EXPORT_SYMBOL): $(subst $(LOCAL_MODULE),$(LOCAL_REQUIRED_MODULES),$(linked_module)) +#LOCAL_EXPORT_SYMBOL := $(intermediates)/LINKED/Module.symvers +#$(LOCAL_EXPORT_SYMBOL): $(intermediates)/LINKED/% : $(LOCAL_SRC_EXPORT_SYMBOL) +# $(copy-file-to-target) +#$(linked_module): $(LOCAL_EXPORT_SYMBOL) $(LOCAL_SRC_EXPORT_SYMBOL) $(AUTO_CONF) $(AUTOCONF_H) +endif +endif +endif + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/Makefile b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/Makefile new file mode 100644 index 0000000000000..76885eb320d93 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/Makefile @@ -0,0 +1,320 @@ +# --------------------------------------------------- +# Compile Options +# --------------------------------------------------- +WLAN_CHIP_LIST:=-UMT6620 -UMT6628 -UMT5931 -UMT6630 -UMT6632 +ccflags-y += $(WLAN_CHIP_LIST) + +############################################################## +# Common settings +############################################################## +export MTK_COMBO_CHIP=MT7668 +export CONFIG_MTK_COMBO_WIFI=m +export HIF=sdio +export CONFIG_MTK_COMBO_COMM_SDIO=y +#WIFI_TARGET := mt76x8 + +ifeq ($(HIF),) + HIF=sdio +endif + +export CONFIG_MTK_PREALLOC_MEMORY=y + +export CONFIG_MTK_COMBO_WIFI_HIF=$(HIF) +#MODULE_NAME := wlan_$(WIFI_TARGET)_$(HIF) +#WLAN_CHIP_ID=$(MTK_COMBO_CHIP) +ifeq ($(WLAN_CHIP_ID),) + WLAN_CHIP_ID := MT7668 +endif + +ccflags-y += -DCFG_SUPPORT_DEBUG_FS=0 +ccflags-y += -DWLAN_INCLUDE_PROC +ccflags-y += -DCFG_SUPPORT_AGPS_ASSIST=1 +ccflags-y += -DCFG_SUPPORT_TSF_USING_BOOTTIME=1 +ccflags-y += -Werror +ccflags-y:=$(filter-out -U$(WLAN_CHIP_ID),$(ccflags-y)) +ccflags-y += -DLINUX -D$(WLAN_CHIP_ID) + + + +#define log level +CFG_DEFAULT_DBG_LEVEL=0x7 +CONFIG_MTK_WIFI_MCC_SUPPORT=y +# Define maximum different channels supported for ieee80211_iface_combination setting. +CFG_NUM_DIFFERENT_CHANNELS_STA=1 +CFG_NUM_DIFFERENT_CHANNELS_P2P=1 + +# Define initial driver running mode. +# 0=RUNNING_P2P_MODE, 1=RUNNING_AP_MODE, 2=RUNNING_DUAL_AP_MODE, 3=RUNNING_P2P_AP_MODE +CFG_DRIVER_INITIAL_RUNNING_MODE=0 +ifeq ($(CONFIG_MTK_WIFI_MCC_SUPPORT), y) + ccflags-y += -DCFG_SUPPORT_CHNL_CONFLICT_REVISE=0 + $(info DCFG_SUPPORT_CHNL_CONFLICT_REVISE=0) +else + ccflags-y += -DCFG_SUPPORT_CHNL_CONFLICT_REVISE=1 +endif +ifneq ($(CFG_NUM_DIFFERENT_CHANNELS_STA),) +ccflags-y += -DCFG_NUM_DIFFERENT_CHANNELS_STA=$(CFG_NUM_DIFFERENT_CHANNELS_STA) +endif + +ifneq ($(CFG_NUM_DIFFERENT_CHANNELS_P2P),) +ccflags-y += -DCFG_NUM_DIFFERENT_CHANNELS_P2P=$(CFG_NUM_DIFFERENT_CHANNELS_P2P) +endif + +ifneq ($(CFG_DRIVER_INITIAL_RUNNING_MODE),) +ccflags-y += -DCFG_DRIVER_INITIAL_RUNNING_MODE=$(CFG_DRIVER_INITIAL_RUNNING_MODE) +endif + +ifeq ($(CONFIG_MTK_AEE_FEATURE), y) + ccflags-y += -DCFG_SUPPORT_AEE=1 + $(info DCFG_SUPPORT_AEE=1) +else + ccflags-y += -DCFG_SUPPORT_AEE=0 + $(info DCFG_SUPPORT_AEE=0) +endif + +ifeq ($(CONFIG_MTK_WPA3_SUPPORT), y) + ccflags-y += -DCFG_SUPPORT_CFG80211_AUTH=1 + ccflags-y += -DCFG_SUPPORT_SAE=1 + ccflags-y += -DCFG_SUPPORT_OWE=1 + ccflags-y += -DCFG_SUPPORT_SUITB=1 +else + ccflags-y += -DCFG_SUPPORT_CFG80211_AUTH=0 + ccflags-y += -DCFG_SUPPORT_SAE=0 + ccflags-y += -DCFG_SUPPORT_OWE=0 + ccflags-y += -DCFG_SUPPORT_SUITB=0 +endif + +# Disable ASSERT() for user load, enable for others +ifneq ($(TARGET_BUILD_VARIANT),user) + ccflags-y += -DBUILD_QA_DBG=1 +else + ccflags-y += -DBUILD_QA_DBG=0 +endif + +ifeq ($(CONFIG_MTK_COMBO_WIFI),y) +# ccflags-y += -DCFG_BUILT_IN_DRIVER=1 + ccflags-y += -DCFG_WPS_DISCONNECT=1 +else + ccflags-y += -DCFG_BUILT_IN_DRIVER=0 +endif + +ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), sdio) + ccflags-y += -D_HIF_SDIO=1 +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), pcie) + ccflags-y += -D_HIF_PCIE=1 +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), usb) + ccflags-y += -D_HIF_USB=1 +else + $(error Unsuppoted HIF=$(CONFIG_MTK_COMBO_WIFI_HIF)!!) +endif + +ifneq ($(CFG_CFG80211_VERSION),) +VERSION_STR = $(subst ",,$(subst ., , $(subst -, ,$(subst v,,$(CFG_CFG80211_VERSION))))) +$(info VERSION_STR=$(VERSION_STR)) +X = $(firstword $(VERSION_STR)) +Y = $(word 2 ,$(VERSION_STR)) +Z = $(word 3 ,$(VERSION_STR)) +VERSION := $(shell echo "$$(( $X * 65536 + $Y * 256 + $Z))" ) +ccflags-y += -DCFG_CFG80211_VERSION=$(VERSION) +$(info DCFG_CFG80211_VERSION=$(VERSION)) +endif + +$(info HIF=$(CONFIG_MTK_COMBO_WIFI_HIF)) + +ifeq ($(CONFIG_MTK_PASSPOINT_R1_SUPPORT), y) + ccflags-y += -DCFG_SUPPORT_PASSPOINT=1 + ccflags-y += -DCFG_HS20_DEBUG=1 + ccflags-y += -DCFG_ENABLE_GTK_FRAME_FILTER=1 +else ifeq ($(CONFIG_MTK_PASSPOINT_R2_SUPPORT), y) + ccflags-y += -DCFG_SUPPORT_PASSPOINT=1 + ccflags-y += -DCFG_HS20_DEBUG=1 + ccflags-y += -DCFG_ENABLE_GTK_FRAME_FILTER=1 +else + ccflags-y += -DCFG_SUPPORT_PASSPOINT=0 + ccflags-y += -DCFG_HS20_DEBUG=0 + ccflags-y += -DCFG_ENABLE_GTK_FRAME_FILTER=0 +endif + +MTK_MET_PROFILING_SUPPORT = yes +ifeq ($(MTK_MET_PROFILING_SUPPORT), yes) + ccflags-y += -DCFG_MET_PACKET_TRACE_SUPPORT=1 +else + ccflags-y += -DCFG_MET_PACKET_TRACE_SUPPORT=0 +endif + +MTK_MET_TAG_SUPPORT = no +ifeq ($(MTK_MET_TAG_SUPPORT), yes) + ccflags-y += -DMET_USER_EVENT_SUPPORT + ccflags-y += -DCFG_MET_TAG_SUPPORT=1 +else + ccflags-y += -DCFG_MET_TAG_SUPPORT=0 +endif + +#ifeq ($(MODULE_NAME),) +# MODULE_NAME := wlan_$(shell echo $(strip $(WLAN_CHIP_ID)) | tr A-Z a-z)_$(CONFIG_MTK_COMBO_WIFI_HIF) +#endif + +ccflags-y += -DDBG=0 +ccflags-y += -I$(src)/os -I$(src)/os/linux/include +ccflags-y += -I$(src)/include -I$(src)/include/nic -I$(src)/include/mgmt -I$(src)/include/chips +ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), sdio) +ccflags-y += -I$(src)/os/linux/hif/sdio/include +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), pcie) +ccflags-y += -I$(src)/os/linux/hif/pcie/include +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), usb) +ccflags-y += -I$(src)/os/linux/hif/usb/include +endif + +ifneq ($(PLATFORM_FLAGS), ) + ccflags-y += $(PLATFORM_FLAGS) +endif + +#ifeq ($(CONFIG_MTK_WIFI_ONLY),$(filter $(CONFIG_MTK_WIFI_ONLY),m y)) +#obj-$(CONFIG_MTK_WIFI_ONLY) += $(MODULE_NAME).o +#else +#obj-$(CONFIG_MTK_COMBO_WIFI) += $(MODULE_NAME).o +#obj-y += $(MODULE_NAME).o +#endif +MODULE_NAME := wlan_drv_gen4_mt7668 +obj-m += $(MODULE_NAME).o + +# --------------------------------------------------- +# Directory List +# --------------------------------------------------- +COMMON_DIR := common/ +OS_DIR := os/linux/ +ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), sdio) +HIF_DIR := os/linux/hif/sdio/ +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), pcie) +HIF_DIR := os/linux/hif/pcie/ +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), usb) +HIF_DIR := os/linux/hif/usb/ +endif +NIC_DIR := nic/ +MGMT_DIR := mgmt/ +CHIPS := chips/ + + +# --------------------------------------------------- +# 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)nic_rate.o \ + $(NIC_DIR)cmd_buf.o \ + $(NIC_DIR)que_mgt.o \ + $(NIC_DIR)nic_cmd_event.o \ + $(NIC_DIR)nic_umac.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_ate_agent.o \ + $(OS_DIR)gl_qa_agent.o \ + $(OS_DIR)gl_hook_api.o \ + $(OS_DIR)gl_rst.o \ + $(OS_DIR)gl_cfg80211.o \ + $(OS_DIR)gl_proc.o \ + $(OS_DIR)gl_vendor.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)reg_rule.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)swcr.o \ + $(MGMT_DIR)roaming_fsm.o \ + $(MGMT_DIR)tkip_mic.o \ + $(MGMT_DIR)hs20.o \ + $(MGMT_DIR)tdls.o + +CHIPS_OBJS := $(CHIPS)mt6632.o \ + $(CHIPS)mt7668.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_dev_fsm.o\ + $(MGMT_DIR)p2p_dev_state.o\ + $(MGMT_DIR)p2p_role_fsm.o\ + $(MGMT_DIR)p2p_role_state.o\ + $(MGMT_DIR)p2p_func.o\ + $(MGMT_DIR)p2p_scan.o\ + $(MGMT_DIR)p2p_ie.o\ + $(MGMT_DIR)p2p_rlm.o\ + $(MGMT_DIR)p2p_assoc.o\ + $(MGMT_DIR)p2p_bss.o\ + $(MGMT_DIR)p2p_rlm_obss.o\ + $(MGMT_DIR)p2p_fsm.o + +MGMT_OBJS += $(MGMT_DIR)wapi.o + +ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), sdio) +HIF_OBJS := $(HIF_DIR)arm.o \ + $(HIF_DIR)sdio.o +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), pcie) +HIF_OBJS := $(HIF_DIR)arm.o \ + $(HIF_DIR)pcie.o +else ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF), usb) +HIF_OBJS := $(HIF_DIR)usb.o +endif + +HIF_OBJS += $(HIF_DIR)hal_api.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) +$(MODULE_NAME)-objs += $(CHIPS_OBJS) + +# +# mtprealloc +# +ifeq ($(CONFIG_MTK_PREALLOC_MEMORY), y) +ccflags-y += -DCFG_PREALLOC_MEMORY +ccflags-y += -I$(src)/prealloc/include +MODULE_NAME_PREALLOC = $(MODULE_NAME)_prealloc +PREALLOC_OBJS := prealloc/prealloc.o +$(MODULE_NAME_PREALLOC)-objs += $(PREALLOC_OBJS) +obj-m += $(MODULE_NAME_PREALLOC).o +endif + +DRIVER_BUILD_DATE=$(shell date +%Y%m%d%H%M%S) +ccflags-y += -DDRIVER_BUILD_DATE='"$(DRIVER_BUILD_DATE)"' diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/README b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/README new file mode 100644 index 0000000000000..a093821236bb9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/README @@ -0,0 +1,2 @@ +Wlan gen4 driver for MT7668 - kernel modules move out of kernel tree + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/chips/mt6632.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/chips/mt6632.c new file mode 100644 index 0000000000000..938fae62055ae --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/chips/mt6632.c @@ -0,0 +1,104 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file mt6632.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. +*/ + +/******************************************************************************* +* C O M P I L E 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 "mt6632.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +ECO_INFO_T mt6632_eco_table[] = { + /* HW version, ROM version, Factory version, Eco version */ + {0x00, 0x00, 0xA, 0x1}, /* E1 */ + {0x00, 0x00, 0xA, 0x2}, /* E2 */ + {0x10, 0x10, 0xA, 0x3}, /* E3 */ + + {0x00, 0x00, 0x0, 0x0} /* End of table */ +}; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/* Litien code refine to support multi chip */ +struct mt66xx_chip_info mt66xx_chip_info_mt6632 = { + .chip_id = MT6632_CHIP_ID, + .sw_sync0 = MT6632_SW_SYNC0, + .sw_ready_bit_offset = MT6632_SW_SYNC0_RDY_OFFSET, + .patch_addr = MT6632_PATCH_START_ADDR, + .is_pcie_32dw_read = MT6632_IS_PCIE_32DW_READ, /* Litien */ + .eco_info = mt6632_eco_table, + .features = 0, +}; + +struct mt66xx_hif_driver_data mt66xx_driver_data_mt6632 = { + .chip_info = &mt66xx_chip_info_mt6632, +}; diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/chips/mt7668.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/chips/mt7668.c new file mode 100644 index 0000000000000..3b0b9c71c2073 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/chips/mt7668.c @@ -0,0 +1,144 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file mt7668.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. +*/ + +/******************************************************************************* +* C O M P I L E 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 "mt7668.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +ECO_INFO_T mt7668_eco_table[] = { + /* HW version, ROM version, Factory version, Eco version */ + {0x00, 0x00, 0xA, 0x1}, /* E1 */ + {0x10, 0x01, 0xB, 0x2}, /* E2 */ + {0x11, 0x01, 0xB, 0x2}, /* E2 */ + {0x00, 0x00, 0x0, 0x0} /* End of table */ +}; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +VOID +mt7668ConstructFirmwarePrio(P_GLUE_INFO_T prGlueInfo, PPUINT_8 apucNameTable, +PPUINT_8 apucName, PUINT_8 pucNameIdx, UINT_8 ucMaxNameIdx) +{ + struct mt66xx_chip_info *prChipInfo = prGlueInfo->prAdapter->chip_info; + UINT_32 chip_id = prChipInfo->chip_id; + UINT_8 sub_idx = 0; + + for (sub_idx = 0; apucNameTable[sub_idx]; sub_idx++) { + if (((*pucNameIdx) + 3) < ucMaxNameIdx) { + /* Type 1. WIFI_RAM_CODE_MTxxxx.bin */ + snprintf(*(apucName + (*pucNameIdx)), CFG_FW_NAME_MAX_LEN, "%s%x.bin", + apucNameTable[sub_idx], chip_id); + (*pucNameIdx) += 1; + + /* Type 2. WIFI_RAM_CODE_MTxxxx */ + snprintf(*(apucName + (*pucNameIdx)), CFG_FW_NAME_MAX_LEN, "%s%x", + apucNameTable[sub_idx], chip_id); + (*pucNameIdx) += 1; + + /* Type 3. WIFI_RAM_CODE_MTxxxx_Ex.bin */ + snprintf(*(apucName + (*pucNameIdx)), CFG_FW_NAME_MAX_LEN, "%s%x_E%u.bin", + apucNameTable[sub_idx], chip_id, + wlanGetEcoVersion(prGlueInfo->prAdapter)); + (*pucNameIdx) += 1; + + /* Type 4. WIFI_RAM_CODE_MTxxxx_Ex */ + snprintf(*(apucName + (*pucNameIdx)), CFG_FW_NAME_MAX_LEN, "%s%x_E%u", + apucNameTable[sub_idx], chip_id, + wlanGetEcoVersion(prGlueInfo->prAdapter)); + (*pucNameIdx) += 1; + } else { + /* the table is not large enough */ + DBGLOG(INIT, ERROR, "kalFirmwareImageMapping >> file name array is not enough.\n"); + ASSERT(0); + } + } +} + +/* Litien code refine to support multi chip */ +struct mt66xx_chip_info mt66xx_chip_info_mt7668 = { + .chip_id = MT7668_CHIP_ID, + .sw_sync0 = MT7668_SW_SYNC0, + .sw_ready_bit_offset = MT7668_SW_SYNC0_RDY_OFFSET, + .patch_addr = MT7668_PATCH_START_ADDR, + .is_pcie_32dw_read = MT7668_IS_PCIE_32DW_READ, /* Litien */ + .eco_info = mt7668_eco_table, + .constructFirmwarePrio = mt7668ConstructFirmwarePrio, + .features = 0, +}; + +struct mt66xx_hif_driver_data mt66xx_driver_data_mt7668 = { + .chip_info = &mt66xx_chip_info_mt7668, +}; + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/common/dump.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/common/dump.c new file mode 100644 index 0000000000000..c99d50d4bca93 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/common/dump.c @@ -0,0 +1,368 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to dump a segment of memory in bytes. +* +* \param[in] pucStartAddr Pointer to the starting address of the memory to be dumped. +* \param[in] u4Length Length of the memory to be dumped. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID dumpMemory8(IN PUINT_8 pucStartAddr, IN UINT_32 u4Length) +{ + ASSERT(pucStartAddr); + + LOG_FUNC("DUMP8 ADDRESS: %p, Length: %d\n", pucStartAddr, u4Length); + + while (u4Length > 0) { + if (u4Length >= 16) { + LOG_FUNC( + "(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x %02x %02x %02x\n", + pucStartAddr, pucStartAddr[0], pucStartAddr[1], + pucStartAddr[2], pucStartAddr[3], pucStartAddr[4], pucStartAddr[5], + pucStartAddr[6], pucStartAddr[7], pucStartAddr[8], pucStartAddr[9], + pucStartAddr[10], pucStartAddr[11], pucStartAddr[12], + pucStartAddr[13], pucStartAddr[14], pucStartAddr[15]); + u4Length -= 16; + pucStartAddr += 16; + } else { + switch (u4Length) { + case 1: + LOG_FUNC("(%p) %02x\n", pucStartAddr, pucStartAddr[0]); + break; + case 2: + LOG_FUNC("(%p) %02x %02x\n", pucStartAddr, pucStartAddr[0], pucStartAddr[1]); + break; + case 3: + LOG_FUNC("(%p) %02x %02x %02x\n", + pucStartAddr, pucStartAddr[0], pucStartAddr[1], pucStartAddr[2]); + break; + case 4: + LOG_FUNC("(%p) %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3]); + break; + case 5: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4]); + break; + case 6: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5]); + break; + case 7: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6]); + break; + case 8: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7]); + break; + case 9: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8]); + break; + case 10: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8], pucStartAddr[9]); + break; + case 11: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8], pucStartAddr[9], pucStartAddr[10]); + break; + case 12: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8], pucStartAddr[9], pucStartAddr[10], pucStartAddr[11]); + break; + case 13: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8], pucStartAddr[9], pucStartAddr[10], pucStartAddr[11], + pucStartAddr[12]); + break; + case 14: + LOG_FUNC( + "(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8], pucStartAddr[9], pucStartAddr[10], pucStartAddr[11], + pucStartAddr[12], pucStartAddr[13]); + break; + case 15: + default: + LOG_FUNC( + "(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8], pucStartAddr[9], pucStartAddr[10], pucStartAddr[11], + pucStartAddr[12], pucStartAddr[13], pucStartAddr[14]); + break; + } + u4Length = 0; + } + } + + LOG_FUNC("\n"); +} /* end of dumpMemory8() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to dump a segment of memory in double words. +* +* \param[in] pucStartAddr Pointer to the starting address of the memory to be dumped. +* \param[in] u4Length Length of the memory to be dumped. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID dumpMemory32(IN PUINT_32 pu4StartAddr, IN UINT_32 u4Length) +{ + PUINT_8 pucAddr; + + ASSERT(pu4StartAddr); + + LOG_FUNC("DUMP32 ADDRESS: %p, Length: %d\n", pu4StartAddr, u4Length); + + if (IS_NOT_ALIGN_4((ULONG) pu4StartAddr)) { + UINT_32 u4ProtrudeLen = sizeof(UINT_32) - ((ULONG) pu4StartAddr % 4); + + u4ProtrudeLen = ((u4Length < u4ProtrudeLen) ? u4Length : u4ProtrudeLen); + LOG_FUNC("pu4StartAddr is not at DW boundary.\n"); + pucAddr = (PUINT_8) &pu4StartAddr[0]; + + switch (u4ProtrudeLen) { + case 1: + LOG_FUNC("(%p) %02x------\n", pu4StartAddr, pucAddr[0]); + break; + case 2: + LOG_FUNC("(%p) %02x%02x----\n", pu4StartAddr, pucAddr[1], pucAddr[0]); + break; + case 3: + LOG_FUNC("(%p) %02x%02x%02x--\n", pu4StartAddr, pucAddr[2], pucAddr[1], pucAddr[0]); + break; + default: + break; + } + + u4Length -= u4ProtrudeLen; + pu4StartAddr = (PUINT_32) ((ULONG) pu4StartAddr + u4ProtrudeLen); + } + + while (u4Length > 0) { + if (u4Length >= 16) { + LOG_FUNC("(%p) %08x %08x %08x %08x\n", + pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2], pu4StartAddr[3]); + pu4StartAddr += 4; + u4Length -= 16; + } else { + switch (u4Length) { + case 1: + pucAddr = (PUINT_8) &pu4StartAddr[0]; + LOG_FUNC("(%p) ------%02x\n", pu4StartAddr, pucAddr[0]); + break; + case 2: + pucAddr = (PUINT_8) &pu4StartAddr[0]; + LOG_FUNC("(%p) ----%02x%02x\n", pu4StartAddr, pucAddr[1], pucAddr[0]); + break; + case 3: + pucAddr = (PUINT_8) &pu4StartAddr[0]; + LOG_FUNC("(%p) --%02x%02x%02x\n", pu4StartAddr, pucAddr[2], pucAddr[1], pucAddr[0]); + break; + case 4: + LOG_FUNC("(%p) %08x\n", pu4StartAddr, pu4StartAddr[0]); + break; + case 5: + pucAddr = (PUINT_8) &pu4StartAddr[1]; + LOG_FUNC("(%p) %08x ------%02x\n", pu4StartAddr, pu4StartAddr[0], pucAddr[0]); + break; + case 6: + pucAddr = (PUINT_8) &pu4StartAddr[1]; + LOG_FUNC("(%p) %08x ----%02x%02x\n", + pu4StartAddr, pu4StartAddr[0], pucAddr[1], pucAddr[0]); + break; + case 7: + pucAddr = (PUINT_8) &pu4StartAddr[1]; + LOG_FUNC("(%p) %08x --%02x%02x%02x\n", + pu4StartAddr, pu4StartAddr[0], pucAddr[2], pucAddr[1], pucAddr[0]); + break; + case 8: + LOG_FUNC("(%p) %08x %08x\n", pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1]); + break; + case 9: + pucAddr = (PUINT_8) &pu4StartAddr[2]; + LOG_FUNC("(%p) %08x %08x ------%02x\n", + pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1], pucAddr[0]); + break; + case 10: + pucAddr = (PUINT_8) &pu4StartAddr[2]; + LOG_FUNC("(%p) %08x %08x ----%02x%02x\n", + pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1], pucAddr[1], pucAddr[0]); + break; + case 11: + pucAddr = (PUINT_8) &pu4StartAddr[2]; + LOG_FUNC("(%p) %08x %08x --%02x%02x%02x\n", + pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], pucAddr[2], pucAddr[1], pucAddr[0]); + break; + case 12: + LOG_FUNC("(%p) %08x %08x %08x\n", + pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2]); + break; + case 13: + pucAddr = (PUINT_8) &pu4StartAddr[3]; + LOG_FUNC("(%p) %08x %08x %08x ------%02x\n", + pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2], pucAddr[0]); + break; + case 14: + pucAddr = (PUINT_8) &pu4StartAddr[3]; + LOG_FUNC("(%p) %08x %08x %08x ----%02x%02x\n", + pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2], pucAddr[1], pucAddr[0]); + break; + case 15: + default: + pucAddr = (PUINT_8) &pu4StartAddr[3]; + LOG_FUNC("(%p) %08x %08x %08x --%02x%02x%02x\n", + pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2], + pucAddr[2], pucAddr[1], pucAddr[0]); + break; + } + u4Length = 0; + } + } +} /* end of dumpMemory32() */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/common/wlan_bow.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/common/wlan_bow.c new file mode 100644 index 0000000000000..094e8caf4e258 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/common/wlan_bow.c @@ -0,0 +1,3218 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + +/****************************************************************************** +* C O M P I L E R F L A G S +******************************************************************************* +*/ + +/****************************************************************************** +* E X T E R N A L R E F E R E N C E S +******************************************************************************* +*/ +#include "precomp.h" + +#if CFG_ENABLE_BT_OVER_WIFI + +/****************************************************************************** +* C O N S T A N T S +******************************************************************************* +*/ + +/****************************************************************************** +* D A T A T Y P E S +******************************************************************************* +*/ + +/****************************************************************************** +* P U B L I C D A T A +******************************************************************************* +*/ + +#if 1 /* Marked for MT6630 */ +static UINT_32 g_u4LinkCount; +static UINT_32 g_u4Beaconing; +static BOW_TABLE_T arBowTable[CFG_BOW_PHYSICAL_LINK_NUM]; +#endif + +/****************************************************************************** +* 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 +******************************************************************************* +*/ + +#if 1 /* Marked for MT6630 */ +/*----------------------------------------------------------------------------*/ +/*! +* \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 UINT_8 ucBssIdx, + 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->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->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 = 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; +} + +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ +#if 1 /* Marked for MT6630 */ + 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; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ +#if 1 /* Marked for MT6630 */ + 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)) { + DBGLOG(BOW, EVENT, "bowCmdGetMacStatus, Get preferred channel.\n"); + + prMacStatus->ucNumOfChannel = 1; + prMacStatus->arChannelList[0].ucChannelBand = eBand; + prMacStatus->arChannelList[0].ucChannelNum = ucPrimaryChannel; + } else { + DBGLOG(BOW, EVENT, + "bowCmdGetMacStatus, Get channel list. Current number of channel, %d.\n", ucNumOfChannel); + + rlmDomainGetChnlList(prAdapter, BAND_2G4, FALSE, 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, FALSE, + 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; + + } + } + + 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, %x, %x.\n", + prMacStatus->ucNumOfChannel, prMacStatus->arChannelList[0].ucChannelBand); + DBGLOG(BOW, EVENT, + "prMacStatus->arChannelList, %x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x.\n", + prMacStatus->arChannelList[0].ucChannelNum, + prMacStatus->arChannelList[1].ucChannelNum, + prMacStatus->arChannelList[2].ucChannelNum, + prMacStatus->arChannelList[3].ucChannelNum, + prMacStatus->arChannelList[4].ucChannelNum, + prMacStatus->arChannelList[5].ucChannelNum, + prMacStatus->arChannelList[6].ucChannelNum, + prMacStatus->arChannelList[7].ucChannelNum, + prMacStatus->arChannelList[8].ucChannelNum, + prMacStatus->arChannelList[9].ucChannelNum, + prMacStatus->arChannelList[10].ucChannelNum, + prMacStatus->arChannelList[11].ucChannelNum, + prMacStatus->arChannelList[12].ucChannelNum, + prMacStatus->arChannelList[13].ucChannelNum, + prMacStatus->arChannelList[14].ucChannelNum, + prMacStatus->arChannelList[15].ucChannelNum, + prMacStatus->arChannelList[16].ucChannelNum, prMacStatus->arChannelList[17].ucChannelNum); + + DBGLOG(BOW, 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]); + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_MAC_STATUS))); + + return WLAN_STATUS_SUCCESS; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ +#if 1 /* Marked for MT6630 */ + 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; + + 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); + + /* 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.eState = BOW_DEVICE_STATE_NUM; /* Just initiate */ + 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); + + DBGLOG(BOW, EVENT, "bowStarting, g_u4LinkCount, %x.\n", g_u4LinkCount); + + if (g_u4LinkCount == 1) { + DBGLOG(BOW, EVENT, "bowStarting, cnmTimerInitTimer.\n"); + DBGLOG(BOW, EVENT, "prBowFsmInfo->u2BeaconInterval, %d.\n", prBowFsmInfo->u2BeaconInterval); + + cnmTimerInitTimer(prAdapter, + &prBowFsmInfo->rStartingBeaconTimer, + (PFN_MGMT_TIMEOUT_FUNC) bowSendBeacon, (ULONG) NULL); + + cnmTimerInitTimer(prAdapter, + &prBowFsmInfo->rChGrantedTimer, + (PFN_MGMT_TIMEOUT_FUNC) bowChGrantedTimeout, (ULONG) NULL); + + /* Reset Global Variable */ + g_u4Beaconing = 0; + + DBGLOG(BOW, EVENT, "bowCmdSetupConnection, g_u4LinkCount, %x.\n", g_u4LinkCount); + DBGLOG(BOW, EVENT, "kalInitBowDevice, bow0\n"); + +#if CFG_BOW_SEPARATE_DATA_PATH + kalInitBowDevice(prAdapter->prGlueInfo, BOWDEVNAME); +#endif + + /*Active BoW Network */ + SET_NET_ACTIVE(prAdapter, prBowFsmInfo->ucBssIndex); + SET_NET_PWR_STATE_ACTIVE(prAdapter, prBowFsmInfo->ucBssIndex); + nicActivateNetwork(prAdapter, prBowFsmInfo->ucBssIndex); + + } + + 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; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ +#if 1 /* Marked for MT6630 */ + P_BOW_DESTROY_CONNECTION prBowDestroyConnection; + CMD_BT_OVER_WIFI rCmdBtOverWifi; + P_BOW_FSM_INFO_T prBowFsmInfo; + + UINT_8 ucIdx; + + 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)) { + DBGLOG(BOW, EVENT, "bowCmdDestroyConnection, bowCheckIfVaild, not accepted.\n"); + return WLAN_STATUS_NOT_ACCEPTED; + } + + 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]); + + /* fill CMD_BT_OVER_WIFI */ + rCmdBtOverWifi.ucAction = 2; + COPY_MAC_ADDR(rCmdBtOverWifi.rPeerAddr, prBowDestroyConnection->aucPeerAddress); + COPY_MAC_ADDR(prBowFsmInfo->aucPeerAddress, prBowDestroyConnection->aucPeerAddress); + + 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]); + + 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]); + } + + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_SUCCESS); + + return wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + prBowFsmInfo->ucBssIndex, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, + sizeof(CMD_BT_OVER_WIFI), + (PUINT_8)&rCmdBtOverWifi, prCmd->rHeader.ucSeqNumber); + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ +#if 1 /* Marked for MT6630 */ + P_BOW_SET_PTK prBowSetPTK; + CMD_802_11_KEY rCmdKey; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_STA_RECORD_T prStaRec = NULL; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + /* parameter size check */ + if (prCmd->rHeader.u2PayloadLength != sizeof(BOW_SET_PTK)) + return WLAN_STATUS_INVALID_LENGTH; + + prBowSetPTK = (P_BOW_SET_PTK) &(prCmd->aucPayload[0]); + + 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)); + + 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.ucBssIdx = prBowFsmInfo->ucBssIndex; /* BT Over Wi-Fi */ + rCmdKey.ucAlgorithmId = CIPHER_SUITE_CCMP; /* AES */ + rCmdKey.ucKeyId = 0; + rCmdKey.ucKeyLen = 16; /* AES = 128bit */ + kalMemCopy(rCmdKey.aucKeyMaterial, prBowSetPTK->aucTemporalKey, 16); + + /* BT Over Wi-Fi */ + prStaRec = cnmGetStaRecByAddress(prAdapter, prBowFsmInfo->ucBssIndex, prBowSetPTK->aucPeerAddress); + rCmdKey.ucWlanIndex = prStaRec->ucWlanIndex; + + 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]); + + return wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_ADD_REMOVE_KEY, + prBowFsmInfo->ucBssIndex, + TRUE, + FALSE, + wlanbowCmdEventSetCommon, + wlanbowCmdTimeoutHandler, + sizeof(CMD_802_11_KEY), (PUINT_8)&rCmdKey, prCmd->rHeader.ucSeqNumber); +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ +#if 1 /* Marked for MT6630 */ + P_BOW_READ_RSSI prBowReadRSSI; + P_BOW_FSM_INFO_T prBowFsmInfo; + + ASSERT(prAdapter); + + if (prAdapter->fgIsEnableLpdvt) + return WLAN_STATUS_NOT_SUPPORTED; + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + /* 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, + prBowFsmInfo->ucBssIndex, + FALSE, + TRUE, + wlanbowCmdEventReadRssi, + wlanbowCmdTimeoutHandler, 0, NULL, prCmd->rHeader.ucSeqNumber); + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ +#if 1 /* Marked for MT6630 */ + P_BOW_READ_LINK_QUALITY prBowReadLinkQuality; + P_BOW_FSM_INFO_T prBowFsmInfo; + + ASSERT(prAdapter); + + if (prAdapter->fgIsEnableLpdvt) + return WLAN_STATUS_NOT_SUPPORTED; + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + /* 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, + prBowFsmInfo->ucBssIndex, + FALSE, + TRUE, + wlanbowCmdEventReadLinkQuality, + wlanbowCmdTimeoutHandler, 0, NULL, prCmd->rHeader.ucSeqNumber); + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ +#if 1 /* Marked for MT6630 */ + P_BOW_SHORT_RANGE_MODE prBowShortRangeMode; + CMD_TX_PWR_T rTxPwrParam; + + ASSERT(prAdapter); + + DBGLOG(BOW, EVENT, "bowCmdShortRangeMode.\n"); + + 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; + } + + 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]); + + 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) { + DBGLOG(BOW, EVENT, "bowCmdShortRangeMode, %x.\n", WLAN_STATUS_SUCCESS); + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_SUCCESS); + return WLAN_STATUS_SUCCESS; + } + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_FAILURE); + return WLAN_STATUS_FAILURE; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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; +} + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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 = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + /* 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); + + 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); + + /*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); + + 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); + + /*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, prBowFsmInfo->ucBssIndex, 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; + DBGLOG(BOW, EVENT, + "wlanbowCmdEventLinkDisconnected, bowGetBowTableState, %x.\n", + bowGetBowTableState(prAdapter, prBowLinkDisconnected->aucPeerAddress)); + authSendDeauthFrame(prAdapter, NULL, 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; + rBowTable.ucAcquireID = 0; /* Just initiate */ + 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))); + +} + +/* Bruce, 20140224 */ +UINT_8 bowInit(IN P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prBowBssInfo; + P_BOW_FSM_INFO_T prBowFsmInfo; + + ASSERT(prAdapter); + + prBowBssInfo = cnmGetBssInfoAndInit(prAdapter, NETWORK_TYPE_BOW, TRUE); + + /*Initiate BSS_INFO_T - common part -move from bowstarting */ + BSS_INFO_INIT(prAdapter, prBowBssInfo); + + prBowBssInfo->eCurrentOPMode = OP_MODE_BOW; + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowFsmInfo->ucBssIndex = prBowBssInfo->ucBssIndex; + + /* Setup Own MAC & BSSID */ + COPY_MAC_ADDR(prBowBssInfo->aucOwnMacAddr, prAdapter->rWifiVar.aucDeviceAddress); + COPY_MAC_ADDR(prBowBssInfo->aucBSSID, prAdapter->rWifiVar.aucDeviceAddress); + + return prBowBssInfo->ucBssIndex; +} + +/* Bruce, 20140224 */ +VOID bowUninit(IN P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prBowBssInfo; + P_BOW_FSM_INFO_T prBowFsmInfo; + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + cnmFreeBssInfo(prAdapter, prBowBssInfo); +} + +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 = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + 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]); + DBGLOG(BOW, EVENT, "BoW Stoping,[%d,%d]\n", g_u4LinkCount, g_u4Beaconing); + + if (g_u4LinkCount == 0) { + /*Stop beaconing */ + GLUE_DEC_REF_CNT(g_u4Beaconing); + + /*Deactive BoW network */ + /* prBowBssInfo->fgIsNetActive = FALSE; */ + /* prBowBssInfo->fgIsBeaconActivated = FALSE; */ + nicPmIndicateBssAbort(prAdapter, prBowBssInfo->ucBssIndex); + bowChangeMediaState(prBowBssInfo, PARAM_MEDIA_STATE_DISCONNECTED); + nicUpdateBss(prAdapter, prBowBssInfo->ucBssIndex); + /*temp solution for FW hal_pwr_mgt.c#3037 ASSERT */ + nicDeactivateNetwork(prAdapter, prBowBssInfo->ucBssIndex); + SET_NET_PWR_STATE_IDLE(prAdapter, prBowBssInfo->ucBssIndex); + UNSET_NET_ACTIVE(prAdapter, prBowBssInfo->ucBssIndex); + + } + +} + +VOID bowStarting(IN P_ADAPTER_T prAdapter) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if (g_u4LinkCount == 1) { + DBGLOG(BOW, EVENT, "BoW Starting.\n"); + DBGLOG(BOW, EVENT, "BoW channel granted.\n"); + + /* 3 <1> Update BSS_INFO_T per Network Basis */ + /* 4 <1.1> Setup Operation Mode */ + + /* Bruce, 20140224 */ + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + /* 4 <1.2> Setup SSID */ + prBssInfo->ucSSIDLen = BOW_SSID_LEN; + bowAssignSsid(prBssInfo->aucSSID, prBssInfo->aucOwnMacAddr); + + 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]); + + /* 4 <1.3> Clear current AP's STA_RECORD_T and current AID */ + prBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; + prBssInfo->u2AssocId = 0; + + /* 4 <1.4> Setup Channel, Band and Phy Attributes */ + prBssInfo->ucPrimaryChannel = prBowFsmInfo->ucPrimaryChannel; + if (prBowFsmInfo->eBand == BAND_2G4) + prBssInfo->eBand = BAND_2G4; + else + prBssInfo->eBand = BAND_5G; + +#if CFG_BOW_SUPPORT_11N + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11BGN; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; + + prBssInfo->ucNonHTBasicPhyType = (UINT_8) + rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].ePhyTypeIndex; + prBssInfo->u2BSSBasicRateSet = rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].u2BSSBasicRateSet; + + prBssInfo->u2OperationalRateSet = + rNonHTPhyAttributes[prBssInfo->ucNonHTBasicPhyType].u2SupportedRateSet; + + rateGetDataRatesFromRateSet(prBssInfo->u2OperationalRateSet, + prBssInfo->u2BSSBasicRateSet, + prBssInfo->aucAllSupportedRates, &prBssInfo->ucAllSupportedRatesLen); + +#else + if (prBssInfo->eBand == BAND_2G4) { + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11BG; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; + + /* RATE_SET_ERP; */ + prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_ERP; + prBssInfo->u2OperationalRateSet = RATE_SET_ERP; + prBssInfo->ucNonHTBasicPhyType = PHY_TYPE_ERP_INDEX; + } else { + /* Depend on eBand */ + /* prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11BG; */ + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + /* prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; */ + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11A; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_11A; + + /* RATE_SET_ERP; */ + /* prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_ERP; */ + /* prBssInfo->u2OperationalRateSet = RATE_SET_ERP; */ + + /* RATE_SET_ERP; */ + prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_OFDM; + prBssInfo->u2OperationalRateSet = RATE_SET_OFDM; + prBssInfo->ucNonHTBasicPhyType = PHY_TYPE_OFDM_INDEX; + } + +#endif + prBssInfo->fgErpProtectMode = FALSE; + + /* 4 <1.5> Setup MIB for current BSS */ + prBssInfo->u2BeaconInterval = prBowFsmInfo->u2BeaconInterval; + prBssInfo->ucDTIMPeriod = DOT11_DTIM_PERIOD_DEFAULT; + prBssInfo->u2ATIMWindow = 0; + prBssInfo->ucBeaconTimeoutCount = 0; + if (prBowFsmInfo->fgSupportQoS) { + prAdapter->rWifiVar.ucQoS = TRUE; + prBssInfo->fgIsQBSS = TRUE; + } + + /* 3 <2> Update BSS_INFO_T common part */ +#if CFG_SUPPORT_AAA + bssInitForAP(prAdapter, prBssInfo, TRUE); + nicQmUpdateWmmParms(prAdapter, prBssInfo->ucBssIndex); +#endif /* CFG_SUPPORT_AAA */ + prBssInfo->fgIsNetActive = TRUE; + prBssInfo->fgIsBeaconActivated = TRUE; + + /* 3 <3> Set MAC HW */ + + 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]); + + /* 4 <3.1> use command packets to inform firmware */ + rlmBssInitForAPandIbss(prAdapter, prBssInfo); + nicUpdateBss(prAdapter, prBssInfo->ucBssIndex); + + /* 4 <3.2> Update AdHoc PM parameter */ + nicPmIndicateBssCreated(prAdapter, prBssInfo->ucBssIndex); + + /* 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); + + DBGLOG(BOW, EVENT, "BoW Starting,[%d,%d]\n", g_u4LinkCount, g_u4Beaconing); + DBGLOG(BOW, EVENT, "bowStarting, g_u4LinkCount, %x.\n", g_u4LinkCount); + + /*Start beaconing */ + if (g_u4Beaconing < 1) { + GLUE_INC_REF_CNT(g_u4Beaconing); + bssSendBeaconProbeResponse(prAdapter, prBssInfo->ucBssIndex, NULL, 0); + cnmTimerStartTimer(prAdapter, &prBowFsmInfo->rStartingBeaconTimer, prBowFsmInfo->u2BeaconInterval); + } +#if 0 + /*Responder: Start to scan Initiator */ + if (prBowFsmInfo->ucRole == BOW_RESPONDER) { + DBGLOG(BOW, EVENT, "bowStarting responder, start scan result searching.\n"); + cnmTimerStopTimer(prAdapter, &prBowFsmInfo->rChGrantedTimer); + bowReleaseCh(prAdapter); + bowResponderScan(prAdapter); + } + /*Initiator: Request channel, wait for responder */ + /* else + * bowRequestCh(prAdapter); + */ +#endif + + /* wlanBindBssIdxToNetInterface(prAdapter->prGlueInfo, NET_DEV_BOW_IDX, prBssInfo->ucBssIndex); */ + +} + +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; + } + +} + +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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) +{ +#if 1 /* Marked for MT6630 */ + + 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); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + +#if 0 + DBGLOG(BOW, EVENT, "bowValidateProbeReq.\n"); +#endif + + /* 4 <1> Parse Probe Req IE and Get IE ptr (SSID, Supported Rate IE, ...) */ + prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T) prSwRfb->pvHeader; + + u2IELength = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen; + pucIE = (PUINT_8) (((ULONG) prSwRfb->pvHeader) + prSwRfb->u2HeaderLen); + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (IE_ID(pucIE) == ELEM_ID_SSID) { + 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 (IE_ID(pucIE) == ELEM_ID_SSID) { + 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; +#else + return 0; +#endif +} + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Media Disconnect" to HOST +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bowSendBeacon(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr) +{ + 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, prBowFsmInfo->ucBssIndex, NULL, 0); + cnmTimerStartTimer(prAdapter, &prBowFsmInfo->rStartingBeaconTimer, prBowFsmInfo->u2BeaconInterval); + } else { + DBGLOG(BOW, EVENT, "BoW Send Beacon,[%d,%d]\n", g_u4LinkCount, g_u4Beaconing); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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 = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + DBGLOG(BOW, EVENT, "bowResponderScan.\n"); + DBGLOG(BOW, EVENT, "BOW SCAN [REQ:%d]\n", prBowFsmInfo->ucSeqNumOfScanReq + 1); + + 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->ucBssIndex = prBowFsmInfo->ucBssIndex; + 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 */ + +} + +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID bowResponderScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ +#if 1 /* Marked for MT6630 */ + 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); + + ucSeqNumOfCompMsg = prScanDoneMsg->ucSeqNum; + eScanStatus = prScanDoneMsg->eScanStatus; + + cnmMemFree(prAdapter, prMsgHdr); + + DBGLOG(BOW, EVENT, "bowResponderScanDone.\n"); + DBGLOG(BOW, EVENT, "BOW SCAN [DONE:%d]\n", ucSeqNumOfCompMsg); + + if (eScanStatus == SCAN_STATUS_CANCELLED) { + DBGLOG(BOW, EVENT, "BOW SCAN [CANCELLED:%d]\n", ucSeqNumOfCompMsg); + if (eFsmState == BOW_DEVICE_STATE_DISCONNECTING) { + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + prBowFsmInfo->ucBssIndex, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, 0, NULL, 0); + } + return; + } else if (eFsmState == BOW_DEVICE_STATE_DISCONNECTED) { + /* bowDisconnectLink(prAdapter, NULL, TX_RESULT_SUCCESS); */ + return; + } else if (ucSeqNumOfCompMsg != prBowFsmInfo->ucSeqNumOfScanReq) { + DBGLOG(BOW, EVENT, "Sequence no. of BOW Responder scan done is not matched.\n"); + return; + } + prConnSettings->fgIsScanReqIssued = FALSE; + prBssDesc = scanSearchBssDescByBssid(prAdapter, prBowFsmInfo->aucPeerAddress); + DBGLOG(BOW, EVENT, "End scan result searching.\n"); + DBGLOG(BOW, EVENT, "prBowFsmInfo->aucPeerAddress: [" MACSTR "]\n", MAC2STR(prBowFsmInfo->aucPeerAddress)); + + /*Initiator is FOUND */ + if (prBssDesc != NULL) { /* (prBssDesc->aucBSSID != NULL)) */ + 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"); + + /*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; +#endif /* Marked for MT6630 */ +} + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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) { + DBGLOG(BOW, EVENT, "BOW SCAN [CANCEL:%d]\n", prBowFsmInfo->ucSeqNumOfScanReq); + + /* There is a channel privilege on hand. */ + + DBGLOG(BOW, 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(BOW, TRACE, "Buffer not enough, can not cancel scan.\n"); + ASSERT(FALSE); + break; + } + + prScanCancel->rMsgHdr.eMsgId = MID_BOW_SCN_SCAN_CANCEL; + prScanCancel->ucBssIndex = prBowFsmInfo->ucBssIndex; + 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 = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + 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, prBssInfo->ucBssIndex, 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); + DBGLOG(BOW, EVENT, "bowResponderJoin, SSID %s.\n", prBssDesc->aucSSID); + DBGLOG(BOW, EVENT, "bowResponderJoin, SSID %s.\n", prConnSettings->aucSSID); + } + /* 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; + + DBGLOG(BOW, EVENT, "prStaRec->eStaType, %x.\n", prStaRec->eStaType); + DBGLOG(BOW, EVENT, "BoW trigger SAA [" MACSTR "]\n", MAC2STR(prStaRec->aucMacAddr)); + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinReqMsg, MSG_SEND_METHOD_BUF); + +} + +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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) +{ +#if 1 /* Marked for MT6630 */ + + P_MSG_JOIN_COMP_T prJoinCompMsg; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_STA_RECORD_T prStaRec; + P_SW_RFB_T prAssocRspSwRfb; + 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; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + prJoinCompMsg = (P_MSG_JOIN_COMP_T) prMsgHdr; + prStaRec = prJoinCompMsg->prStaRec; + + 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); + + 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; + + u2IELength = + (UINT_16) ((prAssocRspSwRfb->u2PacketLen - + prAssocRspSwRfb->u2HeaderLen) - + (OFFSET_OF(WLAN_ASSOC_RSP_FRAME_T, aucInfoElem[0]) - WLAN_MAC_MGMT_HEADER_LEN)); + pucIE = prAssocRspFrame->aucInfoElem; + + prStaRec->eStaType = STA_TYPE_BOW_AP; + prStaRec->u2DesiredNonHTRateSet &= prBowBssInfo->u2OperationalRateSet; + prStaRec->ucDesiredPhyTypeSet = prStaRec->ucPhyTypeSet & prBowBssInfo->ucPhyTypeSet; +#if CFG_BOW_RATE_LIMITATION + /* 4 <1.2>Update Rate Set */ + /*Limit Rate Set to 24M, 48M, 54M */ + prStaRec->u2DesiredNonHTRateSet &= (RATE_SET_BIT_24M | RATE_SET_BIT_48M | RATE_SET_BIT_54M); + /*If peer cannot support the above rate set, fix on the available highest rate */ + if (prStaRec->u2DesiredNonHTRateSet == 0) { + UINT_8 ucHighestRateIndex; + + if (rateGetHighestRateIndexFromRateSet + (prBowBssInfo->u2OperationalRateSet, &ucHighestRateIndex)) { + prStaRec->u2DesiredNonHTRateSet = BIT(ucHighestRateIndex); + } + } +#endif + + /* 4 <1.1> Change FW's Media State immediately. */ + bowChangeMediaState(prBowBssInfo, 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, prBowBssInfo->ucBssIndex); + DBGLOG(BOW, EVENT, "Finish bowUpdateBssInfoForJOIN.\n"); + + /* 4 <1.4> Activate current AP's STA_RECORD_T in Driver. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + DBGLOG(BOW, EVENT, "bowFsmRunEventJoinComplete, qmActivateStaRec.\n"); + + /* 4 <1.7> Set the Next State of BOW FSM */ + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + prBowFsmInfo->ucBssIndex, + 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 + DBGLOG(BOW, EVENT, "Start bowfsmRunEventJoinComplete -- Join failed.\n"); + DBGLOG(BOW, EVENT, "BoW trigger SAA REJOIN\n"); + } + } + + cnmMemFree(prAdapter, prMsgHdr); + +#endif /* Marked for MT6630 */ +} + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + /* 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 { + + rEventConnStatus.ucReasonOfDisconnect = prBssInfo->ucReasonOfDisconnect; + + } + + /* 4 <2> Indication */ + nicMediaStateChange(prAdapter, prBssInfo->ucBssIndex, &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)); + } + +} + +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Event of Tx Fail of AAA Module. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bowRunEventAAATxFail(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ +#if 1 /* Marked for MT6630 */ + P_BSS_INFO_T prBssInfo; + P_BOW_FSM_INFO_T prBowFsmInfo; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + DBGLOG(BOW, EVENT, "bowRunEventAAATxFail , bssRemoveStaRecFromClientList.\n"); + DBGLOG(BOW, EVENT, "BoW AAA TxFail, target state %d\n", prStaRec->ucStaState + 1); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + bssRemoveClient(prAdapter, prBssInfo, prStaRec); + + return; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Event of Successful Completion of AAA Module. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS bowRunEventAAAComplete(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ +#if 1 /* Marked for MT6630 */ + P_BSS_INFO_T prBssInfo; + P_BOW_FSM_INFO_T prBowFsmInfo; + + ASSERT(prStaRec); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + DBGLOG(BOW, STATE, "bowRunEventAAAComplete, cnmStaRecChangeState, STA_STATE_3.\n"); + DBGLOG(BOW, EVENT, "BoW AAA complete [" MACSTR "]\n", MAC2STR(prStaRec->aucMacAddr)); + + /*Update BssInfo to connected */ + bowChangeMediaState(prBssInfo, PARAM_MEDIA_STATE_CONNECTED); + nicUpdateBss(prAdapter, prBowFsmInfo->ucBssIndex); + + /*Update StaRec to State3 */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + /*Connected */ + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + prBowFsmInfo->ucBssIndex, + TRUE, FALSE, wlanbowCmdEventLinkConnected, wlanbowCmdTimeoutHandler, 0, NULL, 0); + + return WLAN_STATUS_SUCCESS; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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) +{ +#if 1 /* Marked for MT6630 */ + P_BSS_INFO_T prBowBssInfo; + P_BOW_FSM_INFO_T prBowFsmInfo; + ENUM_BOW_DEVICE_STATE eFsmState; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + if (!IS_STA_BOW_TYPE(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 (prStaRec->ucStaState == STA_STATE_3) { + /* 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, + prBowFsmInfo->ucBssIndex, + TRUE, + FALSE, wlanbowCmdEventLinkDisconnected, wlanbowCmdTimeoutHandler, 0, NULL, 0); + + return WLAN_STATUS_SUCCESS; + } + + return WLAN_STATUS_NOT_ACCEPTED; + +#else + return 0; +#endif +} + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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); */ + 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 + if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) + wlanLoadManufactureData(prAdapter, kalGetConfiguration(prAdapter->prGlueInfo)); + else + DBGLOG(REQ, WARN, "%s: load manufacture data fail\n", __func__); + +#endif + /*Uninit BoW Interface */ +#if CFG_BOW_SEPARATE_DATA_PATH + kalUninitBowDevice(prAdapter->prGlueInfo); +#endif + } +} + +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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) +{ +#if 1 /* Marked for MT6630 */ + + BOOLEAN fgReplyAssocResp = FALSE; + P_BSS_INFO_T prBowBssInfo; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_WLAN_ASSOC_REQ_FRAME_T prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) NULL; + OS_SYSTIME rCurrentTime; + static OS_SYSTIME rLastRejectAssocTime; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) prSwRfb->pvHeader; + *pu2StatusCode = STATUS_CODE_REQ_DECLINED; + + 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]); + + /*Assoc Accept */ + while (EQUAL_MAC_ADDR(prAssocReqFrame->aucSrcAddr, prBowFsmInfo->aucPeerAddress)) { + DBGLOG(BOW, EVENT, "bowValidateAssocReq, return wlanbowCmdEventLinkConnected.\n"); + + /*Update StaRec */ + prStaRec = cnmGetStaRecByAddress(prAdapter, prBowFsmInfo->ucBssIndex, 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 available highest rate */ + if (prStaRec->u2DesiredNonHTRateSet == 0) { + UINT_8 ucHighestRateIndex; + + if (rateGetHighestRateIndexFromRateSet(prBowBssInfo->u2OperationalRateSet, &ucHighestRateIndex)) + prStaRec->u2DesiredNonHTRateSet = BIT(ucHighestRateIndex); + else { + /*If no available rate is found, DECLINE the association */ + *pu2StatusCode = STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED; + break; + } + } +#endif + + /*Update BssInfo to FW */ + bowChangeMediaState(prBowBssInfo, PARAM_MEDIA_STATE_CONNECTED); + nicUpdateBss(prAdapter, prStaRec->ucBssIndex); + + /*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; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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) +{ +#if 1 /* Marked for MT6630 */ + BOOLEAN fgReplyAuth = FALSE; + P_BSS_INFO_T prBowBssInfo; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_WLAN_AUTH_FRAME_T prAuthFrame = (P_WLAN_AUTH_FRAME_T) NULL; + OS_SYSTIME rCurrentTime; + static OS_SYSTIME rLastRejectAuthTime; + + /* TODO(Kevin): Call BoW functions to check .. + * 1. Check we are BoW now. + * 2. Check we can accept connection from thsi peer + * 3. Check Black List here. + */ + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; + + 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]); + + prStaRec = cnmGetStaRecByAddress(prAdapter, prBowFsmInfo->ucBssIndex, prAuthFrame->aucSrcAddr); + if (!prStaRec) { + DBGLOG(BOW, EVENT, "bowValidateAuth, cnmStaRecAlloc.\n"); + prStaRec = cnmStaRecAlloc(prAdapter, + STA_TYPE_BOW_CLIENT, prBowFsmInfo->ucBssIndex, prAuthFrame->aucSrcAddr); + + /* 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); + DBGLOG(BOW, EVENT, "bowValidateAuth, cnmStaRecChangeState.\n"); + } else { + prSwRfb->ucStaRecIdx = prStaRec->ucIndex; + DBGLOG(BOW, EVENT, "bowValidateAuth, prStaRec->ucIndex, %x.\n", prStaRec->ucIndex); + bssRemoveClient(prAdapter, prBowBssInfo, prStaRec); + } + + if (EQUAL_MAC_ADDR(prAuthFrame->aucSrcAddr, prBowFsmInfo->aucPeerAddress)) { + DBGLOG(BOW, EVENT, "bowValidateAuth, prStaRec->eStaType, %x.\n", prStaRec->eStaType); + DBGLOG(BOW, EVENT, "bowValidateAuth, prStaRec->ucBssIndex, %x.\n", prStaRec->ucBssIndex); + + /* 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); + *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; + } + } + + DBGLOG(BOW, EVENT, "bowValidateAuth, fgReplyAuth, %x.\n", fgReplyAuth); + return fgReplyAuth; + +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ +#if 1 /* Marked for MT6630 */ + 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); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + prMsgChGrant = (P_MSG_CH_GRANT_T) prMsgHdr; + ucTokenID = prMsgChGrant->ucTokenID; + u4GrantInterval = prMsgChGrant->u4GrantInterval; + + /* 1. free message */ + cnmMemFree(prAdapter, prMsgHdr); + prBowFsmInfo->fgIsChannelGranted = TRUE; + + DBGLOG(BOW, EVENT, "Entering bowRunEventChGrant.\n"); + + eFsmState = bowGetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress); + + /*Release channel */ + if ((!prBowFsmInfo->fgIsChannelRequested) || + (prBowFsmInfo->ucSeqNumOfChReq != ucTokenID) || + (eFsmState == BOW_DEVICE_STATE_DISCONNECTED) || (eFsmState == BOW_DEVICE_STATE_DISCONNECTING)) { + DBGLOG(BOW, EVENT, "BoW Channel [GIVE UP:%d]\n", ucTokenID); + DBGLOG(BOW, EVENT, "[Requested:%d][ucSeqNumOfChReq:%d][eFsmState:%d]\n", + prBowFsmInfo->fgIsChannelRequested, prBowFsmInfo->ucSeqNumOfChReq, eFsmState); + 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 */ + + DBGLOG(BOW, EVENT, "BoW Channel [GRANTED:%d].\n", ucTokenID); + + 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, prBowFsmInfo->ucBssIndex); + bowReleaseCh(prAdapter); + } + + return; +#endif /* Marked for MT6630 */ +} /* end of aisFsmRunEventChGrant() */ + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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) { + + DBGLOG(BOW, EVENT, "BoW channel [REQUEST:%d], %d, %d.\n", + prBowFsmInfo->ucSeqNumOfChReq + 1, prBowFsmInfo->ucPrimaryChannel, prBowFsmInfo->eBand); + + 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->ucBssIndex = prBowFsmInfo->ucBssIndex; + prMsgChReq->ucTokenID = ++prBowFsmInfo->ucSeqNumOfChReq; + prMsgChReq->eReqType = CH_REQ_TYPE_JOIN; +#if 0 + prMsgChReq->u4MaxInterval = BOW_JOIN_CH_REQUEST_INTERVAL; +#else + prMsgChReq->u4MaxInterval = 1; +#endif + /* prBowFsmInfo->prTargetBssDesc->ucChannelNum; */ + prMsgChReq->ucPrimaryChannel = prBowFsmInfo->ucPrimaryChannel; + /* prBowFsmInfo->prTargetBssDesc->eSco; */ + prMsgChReq->eRfSco = CHNL_EXT_SCN; + /* prBowFsmInfo->prTargetBssDesc->eBand; */ + prMsgChReq->eRfBand = prBowFsmInfo->eBand; + + /* FIXME : where to call cnmGetDbdcCapability in BOW? */ + /*prMsgChReq->eDBDCBand = (prAdapter->aprBssInfo[prMsgChReq->ucBssIndex])->eDBDCBand;*/ + prMsgChReq->eDBDCBand = ENUM_BAND_0; + + /* To do: check if 80/160MHz bandwidth is needed here */ + prMsgChReq->eRfChannelWidth = 0; + prMsgChReq->ucRfCenterFreqSeg1 = 0; + prMsgChReq->ucRfCenterFreqSeg2 = 0; + + 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) { + DBGLOG(BOW, EVENT, + "BoW channel [RELEASE:%d] %d, %d.\n", prBowFsmInfo->ucSeqNumOfChReq, + prBowFsmInfo->ucPrimaryChannel, prBowFsmInfo->eBand); + + 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->ucBssIndex = prBowFsmInfo->ucBssIndex; + prMsgChAbort->ucTokenID = prBowFsmInfo->ucSeqNumOfChReq; + + /* FIXME : where to call cnmGetDbdcCapability in BOW? */ + /*prMsgChAbort->eDBDCBand = (prAdapter->aprBssInfo[prMsgChAbort->ucBssIndex])->eDBDCBand;*/ + prMsgChAbort->eDBDCBand = ENUM_BAND_0; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChAbort, MSG_SEND_METHOD_BUF); + } + +} /* end of aisFsmReleaseCh() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Media Disconnect" to HOST +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bowChGrantedTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + ENUM_BOW_DEVICE_STATE eFsmState; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + DBGLOG(BOW, EVENT, "BoW Channel [TIMEOUT]\n"); + +#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 +} + +#endif /* Marked for MT6630 */ + +BOOLEAN bowNotifyAllLinkDisconnected(IN P_ADAPTER_T prAdapter) +{ +#if 1 /* Marked for MT6630 */ + + UINT_8 ucBowTableIdx = 0; + CMD_INFO_T rCmdInfo; + P_BOW_FSM_INFO_T prBowFsmInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + 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); + 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); +#if 1 + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + prBowFsmInfo->ucBssIndex, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, 0, NULL, 0); +#else + wlanbowCmdEventLinkDisconnected(prAdapter, &rCmdInfo, NULL); +#endif + } + + ucBowTableIdx += 1; + } + + return TRUE; + +#else + return 0; +#endif +} + +#if 1 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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)) { + + 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); + + 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) { + + DBGLOG(BOW, EVENT, + "bowGetBowTableContent, arBowTable[idx].fgIsValid, %x, %x.\n", + ucBowTableIdx, arBowTable[ucBowTableIdx].fgIsValid); + DBGLOG(BOW, EVENT, "GET State [%d]\n", arBowTable[ucBowTableIdx].eState); + 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); */ + + DBGLOG(BOW, EVENT, "SET State [%d]\n", arBowTable[ucBowTableIdx].eState); + DBGLOG(BOW, EVENT, + "kalCheckBowifVaild, arBowTable[ucBowTableIdx].fgIsValid, %x, %x.\n", ucBowTableIdx, + arBowTable[ucBowTableIdx].fgIsValid); + + 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)) { + + 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); + 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) { + DBGLOG(BOW, EVENT, + "bowGetBowTableFreeEntry, arBowTable[idx].fgIsValid, %x, %x.\n", + idx, arBowTable[idx].fgIsValid); + *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)) { + DBGLOG(BOW, EVENT, + "bowGetState, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, + aucPeerAddress[0], aucPeerAddress[1], aucPeerAddress[2], + aucPeerAddress[3], aucPeerAddress[4], aucPeerAddress[5]); + DBGLOG(BOW, EVENT, + "bowGetState, arBowTable[idx].aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", + idx, arBowTable[idx].aucPeerAddress[0], + arBowTable[idx].aucPeerAddress[1], + arBowTable[idx].aucPeerAddress[2], + arBowTable[idx].aucPeerAddress[3], + arBowTable[idx].aucPeerAddress[4], arBowTable[idx].aucPeerAddress[5]); + DBGLOG(BOW, EVENT, + "bowGetState, arBowTable[idx].fgIsValid, %x, %x.\n", idx, arBowTable[idx].fgIsValid); + DBGLOG(BOW, EVENT, + "bowGetState, arBowTable[idx].eState;, %x, %x.\n", idx, arBowTable[idx].eState); + DBGLOG(BOW, EVENT, "GET State [%d]\n", arBowTable[idx].eState); + + 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; + DBGLOG(BOW, EVENT, "SET State [%d]\n", eState); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + kalSetBowState(prAdapter->prGlueInfo, eState, aucPeerAddress); + return TRUE; + } + return FALSE; +} + +#endif + +#endif /* Marked for MT6630 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/common/wlan_lib.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/common/wlan_lib.c new file mode 100644 index 0000000000000..a4fc7437cb2ee --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/common/wlan_lib.c @@ -0,0 +1,10482 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \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. +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" +#include "mgmt/ais_fsm.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* 6.1.1.2 Interpretation of priority parameter in MAC service primitives */ +/* Static convert the Priority Parameter/TID(User Priority/TS Identifier) to Traffic Class */ +const UINT_8 aucPriorityParam2TC[] = { + TC1_INDEX, + TC0_INDEX, + TC0_INDEX, + TC1_INDEX, + TC2_INDEX, + TC2_INDEX, + TC3_INDEX, + TC3_INDEX +}; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef struct _CODE_MAPPING_T { + UINT_32 u4RegisterValue; + INT_32 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, +}; +#if CFG_SUPPORT_COMPRESSION_FW_OPTION +#define COMPRESSION_OPTION_OFFSET 4 +#define COMPRESSION_OPTION_MASK BIT(4) +#endif + + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* 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, FALSE); + +} /* 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)); + + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + UINT_32 i; + + ASSERT(prAdapter); + + DEBUGFUNC("wlanAdapterStart"); + + /* 4 <0> Reset variables in ADAPTER_T */ + /* prAdapter->fgIsFwOwn = TRUE; */ + prAdapter->fgIsEnterD3ReqIssued = FALSE; + + prAdapter->u4OwnFailedCount = 0; + prAdapter->u4OwnFailedLogCount = 0; + + QUEUE_INITIALIZE(&(prAdapter->rPendingCmdQueue)); +#if CFG_SUPPORT_MULTITHREAD + QUEUE_INITIALIZE(&prAdapter->rTxCmdQueue); + QUEUE_INITIALIZE(&prAdapter->rTxCmdDoneQueue); +#if CFG_FIX_2_TX_PORT + QUEUE_INITIALIZE(&prAdapter->rTxP0Queue); + QUEUE_INITIALIZE(&prAdapter->rTxP1Queue); +#else + for (i = 0; i < TX_PORT_NUM; i++) + QUEUE_INITIALIZE(&prAdapter->rTxPQueue[i]); +#endif + QUEUE_INITIALIZE(&prAdapter->rRxQueue); + QUEUE_INITIALIZE(&prAdapter->rTxDataDoneQueue); +#endif + + /* Initialize rWlanInfo */ + kalMemSet(&(prAdapter->rWlanInfo), 0, sizeof(WLAN_INFO_T)); + + /* Initialize aprBssInfo[]. + * Important: index shall be same when mapping between aprBssInfo[] + * and arBssInfoPool[]. rP2pDevInfo is indexed to final one. + */ + for (i = 0; i < BSS_INFO_NUM; i++) + prAdapter->aprBssInfo[i] = &prAdapter->rWifiVar.arBssInfoPool[i]; + prAdapter->aprBssInfo[P2P_DEV_BSS_INDEX] = &prAdapter->rWifiVar.rP2pDevInfo; + + /* 4 <0.1> reset fgIsBusAccessFailed */ + fgIsBusAccessFailed = FALSE; + + do { + u4Status = nicAllocateAdapterMemory(prAdapter); + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "nicAllocateAdapterMemory Error!\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } + + prAdapter->u4OsPacketFilter = PARAM_PACKET_FILTER_SUPPORTED; + + DBGLOG(INIT, INFO, "wlanAdapterStart(): Acquiring LP-OWN\n"); + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + DBGLOG(INIT, INFO, "wlanAdapterStart(): Acquiring LP-OWN-end\n"); + +#if (CFG_ENABLE_FULL_PM == 0) + nicpmSetDriverOwn(prAdapter); + if (prAdapter->fgIsFwOwn == TRUE) { + DBGLOG(INIT, ERROR, "nicpmSetDriverOwn() failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } +#endif + + /* 4 <1> Initialize the Adapter */ + u4Status = nicInitializeAdapter(prAdapter); + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "nicInitializeAdapter failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } + + /* 4 <2.1> Initialize System Service (MGMT Memory pool and STA_REC) */ + nicInitSystemService(prAdapter); + + /* 4 <2.2> Initialize Feature Options */ + wlanInitFeatureOption(prAdapter); +#if CFG_SUPPORT_MTK_SYNERGY + if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) { + if (prRegInfo->prNvramSettings->u2FeatureReserved & BIT(MTK_FEATURE_2G_256QAM_DISABLED)) + prAdapter->rWifiVar.aucMtkFeature[0] &= ~(MTK_SYNERGY_CAP_SUPPORT_24G_MCS89); + } +#endif + + /* 4 <2.3> Overwrite debug level settings */ + wlanCfgSetDebugLevel(prAdapter); + + /* 4 <3> Initialize Tx */ + nicTxInitialize(prAdapter); + wlanDefTxPowerCfg(prAdapter); + + /* 4 <4> Initialize Rx */ + nicRxInitialize(prAdapter); + + /* 4 <5> HIF SW info initialize */ + halHifSwInfoInit(prAdapter); + + /* 4 <6> Enable HIF cut-through to N9 mode, not visiting CR4 */ + u4Status = wlanWakeUpWiFi(prAdapter); + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "wlanWakeUpWiFi failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } + HAL_ENABLE_FWDL(prAdapter, TRUE); + + /* 4 <7> Get ECO Version */ + u4Status = wlanSetChipEcoInfo(prAdapter); + + if (u4Status != WLAN_STATUS_SUCCESS) + break; + +#if CFG_ENABLE_FW_DOWNLOAD + /* 4 <8> FW/patch download */ + + /* 1. disable interrupt, download is done by polling mode only */ + nicDisableInterrupt(prAdapter); + + /* 2. Initialize Tx Resource to fw download state */ + nicTxInitResetResource(prAdapter); + + u4Status = wlanDownloadFW(prAdapter); + + if (u4Status != WLAN_STATUS_SUCCESS) + break; +#endif + + DBGLOG(INIT, INFO, "Waiting for Ready bit..\n"); + + /* 4 <9> check Wi-Fi FW asserts ready bit */ + u4Status = wlanCheckWifiFunc(prAdapter, TRUE); + + if (u4Status == WLAN_STATUS_SUCCESS) { +#if defined(_HIF_SDIO) + PUINT_32 pu4WHISR = NULL; + UINT_16 au2TxCount[16]; + + pu4WHISR = (PUINT_32)kalMemAlloc(sizeof(UINT_32), + PHY_MEM_TYPE); + if (!pu4WHISR) { + DBGLOG(INIT, ERROR, + "Allocate pu4WHISR fail\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } + /* 1. reset interrupt status */ + HAL_READ_INTR_STATUS(prAdapter, sizeof(UINT_32), + (PUINT_8)pu4WHISR); + if (HAL_IS_TX_DONE_INTR(*pu4WHISR)) + HAL_READ_TX_RELEASED_COUNT(prAdapter, + au2TxCount); + + if (pu4WHISR) + kalMemFree(pu4WHISR, PHY_MEM_TYPE, + sizeof(UINT_32)); +#endif + /* Set FW download success flag */ + prAdapter->fgIsFwDownloaded = TRUE; + + /* 2. query & reset TX Resource for normal operation */ + wlanQueryNicResourceInformation(prAdapter); + +#if (CFG_SUPPORT_NIC_CAPABILITY == 1) + + /* 2.9 Workaround for Capability CMD packet lost issue */ + DBGLOG(INIT, WARN, "Send a Dummy CMD as workaround\n"); + wlanSendDummyCmd(prAdapter, TRUE); + + /* 3. query for NIC capability */ + wlanQueryNicCapability(prAdapter); + + /* 4. query for NIC capability V2 */ + wlanQueryNicCapabilityV2(prAdapter); + + /* 5. reset TX Resource for normal operation + * based on the information reported from CMD_NicCapabilityV2 + */ + wlanUpdateNicResourceInformation(prAdapter); + + wlanPrintVersion(prAdapter); +#endif + + /* 6. update basic configuration */ + wlanUpdateBasicConfig(prAdapter); + + /* 7. Override network address */ + wlanUpdateNetworkAddress(prAdapter); + + /* 8. Apply Network Address */ + nicApplyNetworkAddress(prAdapter); + + /* 9. 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, (ULONG) NULL); + + prAdapter->ucOidTimeoutCount = 0; + prAdapter->fgIsChipNoAck = FALSE; + + /* Return Indicated Rfb list timer */ + cnmTimerInitTimer(prAdapter, + &prAdapter->rPacketDelaySetupTimer, + (PFN_MGMT_TIMEOUT_FUNC) wlanReturnPacketDelaySetupTimeout, (ULONG) NULL); + + /* Power state initialization */ + prAdapter->fgWiFiInSleepyState = FALSE; + prAdapter->rAcpiState = ACPI_STATE_D0; + +#if 0 + /* 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; +#else + if (prAdapter->rWifiVar.fgDisOnlineScan == 0) + prAdapter->fgEnOnlineScan = TRUE; + else + prAdapter->fgEnOnlineScan = FALSE; + + /* Beacon lost detection option */ + if (prAdapter->rWifiVar.fgDisBcnLostDetection != 0) + prAdapter->fgDisBcnLostDetection = TRUE; +#endif + + /* 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->u4PsCurrentMeasureEn = prRegInfo->u4PsCurrentMeasureEn; +#if 0 + prAdapter->fgEnArpFilter = prRegInfo->fgEnArpFilter; + prAdapter->u4UapsdAcBmp = prRegInfo->u4UapsdAcBmp; + prAdapter->u4MaxSpLen = prRegInfo->u4MaxSpLen; +#else + prAdapter->fgEnArpFilter = prAdapter->rWifiVar.fgEnArpFilter; + prAdapter->u4UapsdAcBmp = prAdapter->rWifiVar.u4UapsdAcBmp; + prAdapter->u4MaxSpLen = prAdapter->rWifiVar.u4MaxSpLen; +#endif + 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 0 /* Marked for MT6630 */ +#if 1 /* set PM parameters */ + { +#if CFG_SUPPORT_PWR_MGT + prAdapter->u4PowerMode = prRegInfo->u4PowerMode; +#if CFG_ENABLE_WIFI_DIRECT + prAdapter->rWlanInfo.arPowerSaveMode[NETWORK_TYPE_P2P_INDEX].ucNetTypeIndex = + NETWORK_TYPE_P2P_INDEX; + prAdapter->rWlanInfo.arPowerSaveMode[NETWORK_TYPE_P2P_INDEX].ucPsProfile = ENUM_PSP_FAST_SWITCH; +#endif +#else + prAdapter->u4PowerMode = ENUM_PSP_CONTINUOUS_ACTIVE; +#endif + + nicConfigPowerSaveProfile(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, prAdapter->u4PowerMode, FALSE); + } + +#endif +#endif + /* Check if it is disabled by hardware */ + if (prAdapter->fgIsHw5GBandDisabled) + prAdapter->fgEnable5GBand = FALSE; + else + prAdapter->fgEnable5GBand = TRUE; + +#if CFG_SUPPORT_NVRAM + /* load manufacture data */ + if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) + wlanLoadManufactureData(prAdapter, prRegInfo); + else + DBGLOG(INIT, WARN, "%s: load manufacture data fail\n", __func__); +#endif + +#if 0 + /* Update Auto rate parameters in FW */ + nicRlmArUpdateParms(prAdapter, + prRegInfo->u4ArSysParam0, + prRegInfo->u4ArSysParam1, prRegInfo->u4ArSysParam2, prRegInfo->u4ArSysParam3); +#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) +{ + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + + /* MGMT - unitialization */ + nicUninitMGMT(prAdapter); + + /* Release all CMD/MGMT/SEC frame in command queue */ + kalClearCommandQueue(prAdapter->prGlueInfo); + +#if CFG_SUPPORT_MULTITHREAD + + /* Flush all items in queues for multi-thread */ + wlanClearTxCommandQueue(prAdapter); + + wlanClearTxCommandDoneQueue(prAdapter); + + wlanClearDataQueue(prAdapter); + + wlanClearRxToOsQueue(prAdapter); + +#endif +/* Hif power off wifi */ +#if 1 + wlanPowerOffWifi(prAdapter); +#else + if (prAdapter->rAcpiState == ACPI_STATE_D0 && + !wlanIsChipNoAck(prAdapter) && !kalIsCardRemoved(prAdapter->prGlueInfo)) { + /* 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) { + UINT_32 i; + /* 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 */ + wlanCheckWifiFunc(prAdapter, FALSE); + } +#if !CFG_ENABLE_FULL_PM + /* 4. Set Onwership to F/W */ + nicpmSetFWOwn(prAdapter, FALSE); +#endif + +#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); + } +#endif + + nicRxUninitialize(prAdapter); + + nicTxRelease(prAdapter, FALSE); + + /* 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) +{ + UINT_32 u4Status = WLAN_STATUS_SUCCESS; + ASSERT(prAdapter); + + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + u4Status = nicProcessIST(prAdapter); + if (u4Status != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, INFO, "Fail in nicProcessIST! status [%x]\n", + u4Status); + +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + if (KAL_WAKE_LOCK_ACTIVE(prAdapter, &prAdapter->prGlueInfo->rIntrWakeLock)) + KAL_WAKE_UNLOCK(prAdapter, &prAdapter->prGlueInfo->rIntrWakeLock); +#endif + nicEnableInterrupt(prAdapter); + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + + +} + +VOID wlanClearPendingInterrupt(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i; + + i = 0; + while (i < CFG_IST_LOOP_COUNT && nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) { + i++; + }; +} + +WLAN_STATUS wlanCheckWifiFunc(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgRdyChk) +{ + BOOLEAN fgResult, fgTimeout; + UINT_32 u4Result, u4Status, u4StartTime, u4CurTime; + + u4StartTime = kalGetTimeTick(); + fgTimeout = FALSE; + +#if defined(_HIF_USB) + if (prAdapter->prGlueInfo->rHifInfo.state == USB_STATE_LINK_DOWN) + return WLAN_STATUS_FAILURE; +#endif + + while (TRUE) { + if (fgRdyChk) + HAL_WIFI_FUNC_READY_CHECK(prAdapter, WIFI_FUNC_READY_BITS, &fgResult); + else { + HAL_WIFI_FUNC_OFF_CHECK(prAdapter, WIFI_FUNC_READY_BITS, &fgResult); + + if (nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) + DBGLOG(INIT, INFO, "Handle pending interrupt\n"); + } + u4CurTime = kalGetTimeTick(); + + if (CHECK_FOR_TIMEOUT(u4CurTime, u4StartTime, + CFG_RESPONSE_POLLING_TIMEOUT * CFG_RESPONSE_POLLING_DELAY)) { + + fgTimeout = TRUE; + } + + if (fgResult) { + if (fgRdyChk) + DBGLOG(INIT, INFO, "Ready bit asserted\n"); + else + DBGLOG(INIT, INFO, "Wi-Fi power off done!\n"); + + u4Status = WLAN_STATUS_SUCCESS; + + break; + } else if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + + break; + } else if (fgTimeout) { + HAL_WIFI_FUNC_GET_STATUS(prAdapter, u4Result); + DBGLOG(INIT, ERROR, "Waiting for %s: Timeout, Status=0x%08x\n", + fgRdyChk ? "ready bit" : "power off", u4Result); + + u4Status = WLAN_STATUS_FAILURE; + + break; + } + kalMsleep(CFG_RESPONSE_POLLING_DELAY); + + } + + return u4Status; +} + +WLAN_STATUS wlanPowerOffWifi(IN P_ADAPTER_T prAdapter) +{ + WLAN_STATUS rStatus; + /* Hif power off wifi */ + rStatus = halHifPowerOffWifi(prAdapter); + prAdapter->fgIsCr4FwDownloaded = FALSE; + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 */ + prMsduInfo = prCmdInfo->prMsduInfo; + + eFrameAction = qmGetFrameAction(prAdapter, prMsduInfo->ucBssIndex, + prMsduInfo->ucStaRecIndex, NULL, FRAME_TYPE_802_1X, + prCmdInfo->u2InfoBufLen); + break; + + case COMMAND_TYPE_MANAGEMENT_FRAME: + /* inquire with QM */ + prMsduInfo = prCmdInfo->prMsduInfo; + + eFrameAction = qmGetFrameAction(prAdapter, prMsduInfo->ucBssIndex, + prMsduInfo->ucStaRecIndex, prMsduInfo, FRAME_TYPE_MMPDU, + prMsduInfo->u2FrameLength); + break; + + default: + ASSERT(0); + break; + } + + /* 4 <3> handling upon dequeue result */ + if (eFrameAction == FRAME_ACTION_DROP_PKT) { + DBGLOG(INIT, INFO, "DROP CMD TYPE[%u] ID[0x%02X] SEQ[%u]\n", + prCmdInfo->eCmdType, prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + wlanReleaseCommand(prAdapter, prCmdInfo, TX_RESULT_DROPPED_IN_DRIVER); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } else if (eFrameAction == FRAME_ACTION_QUEUE_PKT) { + DBGLOG(INIT, TRACE, "QUE back CMD TYPE[%u] ID[0x%02X] SEQ[%u]\n", + prCmdInfo->eCmdType, prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + + QUEUE_INSERT_TAIL(prMergeCmdQue, prQueueEntry); + } else if (eFrameAction == FRAME_ACTION_TX_PKT) { + /* 4 <4> Send the command */ +#if CFG_SUPPORT_MULTITHREAD + rStatus = wlanSendCommandMthread(prAdapter, prCmdInfo); + + if (rStatus == WLAN_STATUS_RESOURCES) { + /* no more TC4 resource for further transmission */ + DBGLOG(INIT, WARN, "NO Res CMD TYPE[%u] ID[0x%02X] SEQ[%u]\n", + prCmdInfo->eCmdType, prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + + set_bit(GLUE_FLAG_HIF_PRT_HIF_DBG_INFO_BIT, &(prAdapter->prGlueInfo->ulFlag)); + + QUEUE_INSERT_TAIL(prMergeCmdQue, prQueueEntry); + break; + } else if (rStatus == WLAN_STATUS_PENDING) { + /* Do nothing */ + /* Do nothing */ + } else if (rStatus == WLAN_STATUS_SUCCESS) { + /* Do nothing */ + /* Do nothing */ + } else { + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + if (prCmdInfo->fgIsOid) { + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, + prCmdInfo->u4SetInfoLen, rStatus); + } + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + +#else + rStatus = wlanSendCommand(prAdapter, prCmdInfo); + + if (rStatus == WLAN_STATUS_RESOURCES) { + /* no more TC4 resource for further transmission */ + + DBGLOG(INIT, WARN, "NO Resource for CMD TYPE[%u] ID[0x%02X] SEQ[%u]\n", + prCmdInfo->eCmdType, prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + + 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); + } +#endif + } 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); + +#if CFG_SUPPORT_MULTITHREAD + kalSetTxCmdEvent2Hif(prAdapter->prGlueInfo); +#endif + + return WLAN_STATUS_SUCCESS; +} /* end of wlanProcessCommandQueue() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will take CMD_INFO_T which carry some information of +* incoming OID and notify the NIC_TX to send CMD. +* +* \param prAdapter Pointer of Adapter Data Structure +* \param prCmdInfo Pointer of P_CMD_INFO_T +* +* \retval WLAN_STATUS_SUCCESS : CMD was written to HIF and be freed(CMD Done) immediately. +* \retval WLAN_STATUS_RESOURCE : No resource for current command, need to wait for previous +* frame finishing their transmission. +* \retval WLAN_STATUS_FAILURE : Get failure while access HIF or been rejected. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanSendCommand(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + P_TX_CTRL_T prTxCtrl; + UINT_8 ucTC; /* "Traffic Class" SW(Driver) resource classification */ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + prTxCtrl = &prAdapter->rTxCtrl; + + do { + /* <0> card removal check */ + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + rStatus = WLAN_STATUS_FAILURE; + break; + } + + /* <1.1> Assign Traffic Class(TC) */ + ucTC = nicTxGetCmdResourceType(prCmdInfo); + + /* <1.2> Check if pending packet or resource was exhausted */ + rStatus = nicTxAcquireResource(prAdapter, ucTC, nicTxGetCmdPageCount(prCmdInfo), TRUE); + if (rStatus == WLAN_STATUS_RESOURCES) { + DBGLOG(INIT, INFO, "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; + } + + } while (FALSE); + + return rStatus; +} /* end of wlanSendCommand() */ + +#if CFG_SUPPORT_MULTITHREAD + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will take CMD_INFO_T which carry some information of +* incoming OID and notify the NIC_TX to send CMD. +* +* \param prAdapter Pointer of Adapter Data Structure +* \param prCmdInfo Pointer of P_CMD_INFO_T +* +* \retval WLAN_STATUS_SUCCESS : CMD was written to HIF and be freed(CMD Done) immediately. +* \retval WLAN_STATUS_RESOURCE : No resource for current command, need to wait for previous +* frame finishing their transmission. +* \retval WLAN_STATUS_FAILURE : Get failure while access HIF or been rejected. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanSendCommandMthread(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; + + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + prTxCtrl = &prAdapter->rTxCtrl; + + prTempCmdQue = &rTempCmdQue; + QUEUE_INITIALIZE(prTempCmdQue); + + do { + /* <0> card removal check */ + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + rStatus = WLAN_STATUS_FAILURE; + break; + } + /* <1> Normal case of sending CMD Packet */ + /* <1.1> Assign Traffic Class(TC) */ + ucTC = nicTxGetCmdResourceType(prCmdInfo); + + /* <1.2> Check if pending packet or resource was exhausted */ + rStatus = nicTxAcquireResource(prAdapter, ucTC, nicTxGetCmdPageCount(prCmdInfo), TRUE); + if (rStatus == WLAN_STATUS_RESOURCES) { +#if 0 + DBGLOG(INIT, WARN, "%s: NO Resource for CMD TYPE[%u] ID[0x%02X] SEQ[%u] TC[%u]\n", + __func__, prCmdInfo->eCmdType, prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum, ucTC); +#endif + break; + } + + /* Process to pending command queue firest */ + if ((!prCmdInfo->fgSetQuery) || (prCmdInfo->fgNeedResp)) { + /* command packet which needs further handling upon response */ + /* + * KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + * QUEUE_INSERT_TAIL(&(prAdapter->rPendingCmdQueue), (P_QUE_ENTRY_T)prCmdInfo); + * KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + */ + } + QUEUE_INSERT_TAIL(prTempCmdQue, (P_QUE_ENTRY_T) prCmdInfo); + + /* <1.4> Set Pending in response to Query Command/Need Response */ + if (rStatus == WLAN_STATUS_SUCCESS) { + if ((!prCmdInfo->fgSetQuery) || + (prCmdInfo->fgNeedResp) || (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME)) { + rStatus = WLAN_STATUS_PENDING; + } + } + } while (FALSE); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); + QUEUE_CONCATENATE_QUEUES(&(prAdapter->rTxCmdQueue), prTempCmdQue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); + + return rStatus; +} /* end of wlanSendCommandMthread() */ + +VOID wlanTxCmdDoneCb(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + + KAL_SPIN_LOCK_DECLARATION(); + + if ((!prCmdInfo->fgSetQuery) || (prCmdInfo->fgNeedResp)) { +#if 0 + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + QUEUE_INSERT_TAIL(&prAdapter->rPendingCmdQueue, (P_QUE_ENTRY_T) prCmdInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); +#endif + } else { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); + QUEUE_INSERT_TAIL(&prAdapter->rTxCmdDoneQueue, (P_QUE_ENTRY_T) prCmdInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); + } + + /* call tx thread to work */ + set_bit(GLUE_FLAG_TX_CMD_DONE_BIT, &prAdapter->prGlueInfo->ulFlag); + wake_up_interruptible(&prAdapter->prGlueInfo->waitq); +} + +WLAN_STATUS wlanTxCmdMthread(IN P_ADAPTER_T prAdapter) +{ + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue; + QUE_T rTempCmdDoneQue; + P_QUE_T prTempCmdDoneQue; + P_QUE_ENTRY_T prQueueEntry; + P_CMD_INFO_T prCmdInfo; +/* P_CMD_ACCESS_REG prCmdAccessReg; +* P_CMD_ACCESS_REG prEventAccessReg; +* UINT_32 u4Address; +*/ + UINT_32 u4TxDoneQueueSize; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prTempCmdQue = &rTempCmdQue; + QUEUE_INITIALIZE(prTempCmdQue); + + prTempCmdDoneQue = &rTempCmdDoneQue; + QUEUE_INITIALIZE(prTempCmdDoneQue); + + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_TX_CMD_CLEAR); + + /* TX Command Queue */ + /* 4 <1> Move whole list of CMD_INFO to temp queue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, &prAdapter->rTxCmdQueue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_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; + prCmdInfo->pfHifTxCmdDoneCb = wlanTxCmdDoneCb; + + if ((!prCmdInfo->fgSetQuery) || (prCmdInfo->fgNeedResp)) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + QUEUE_INSERT_TAIL(&(prAdapter->rPendingCmdQueue), (P_QUE_ENTRY_T) prCmdInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + } else { + QUEUE_INSERT_TAIL(prTempCmdDoneQue, prQueueEntry); + } + + nicTxCmd(prAdapter, prCmdInfo, TC4_INDEX); + + /* DBGLOG(INIT, INFO, + * ("==> TX CMD QID: %d (Q:%d)\n", prCmdInfo->ucCID, prTempCmdQue->u4NumElem)); + */ + + GLUE_DEC_REF_CNT(prAdapter->prGlueInfo->i4TxPendingCmdNum); + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); + QUEUE_CONCATENATE_QUEUES(&prAdapter->rTxCmdDoneQueue, prTempCmdDoneQue); + u4TxDoneQueueSize = prAdapter->rTxCmdDoneQueue.u4NumElem; + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); + + KAL_RELEASE_MUTEX(prAdapter, MUTEX_TX_CMD_CLEAR); + + if (u4TxDoneQueueSize > 0) { + /* call tx thread to work */ + set_bit(GLUE_FLAG_TX_CMD_DONE_BIT, &prAdapter->prGlueInfo->ulFlag); + wake_up_interruptible(&prAdapter->prGlueInfo->waitq); + } + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS wlanTxCmdDoneMthread(IN P_ADAPTER_T prAdapter) +{ + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue; + P_QUE_ENTRY_T prQueueEntry; + P_CMD_INFO_T prCmdInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prTempCmdQue = &rTempCmdQue; + QUEUE_INITIALIZE(prTempCmdQue); + + /* 4 <1> Move whole list of CMD_INFO to temp queue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, &prAdapter->rTxCmdDoneQueue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_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; + + if (prCmdInfo->pfCmdDoneHandler) + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prCmdInfo->pucInfoBuffer); + /* Not pending cmd, free it after TX succeed! */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to clear all commands in TX command queue +* \param prAdapter Pointer of Adapter Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanClearTxCommandQueue(IN P_ADAPTER_T prAdapter) +{ + 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(); + QUEUE_INITIALIZE(prTempCmdQue); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, &prAdapter->rTxCmdQueue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + if (prCmdInfo->pfCmdTimeoutHandler) + prCmdInfo->pfCmdTimeoutHandler(prAdapter, prCmdInfo); + else + wlanReleaseCommand(prAdapter, prCmdInfo, + TX_RESULT_QUEUE_CLEARANCE); + + /* Release Tx resource for CMD which resource is allocated but not used */ + nicTxReleaseResource(prAdapter, nicTxGetCmdResourceType(prCmdInfo), + nicTxGetCmdPageCount(prCmdInfo), TRUE); + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to clear OID commands in TX command queue +* \param prAdapter Pointer of Adapter Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanClearTxOidCommand(IN P_ADAPTER_T prAdapter) +{ + 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(); + QUEUE_INITIALIZE(prTempCmdQue); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); + + QUEUE_MOVE_ALL(prTempCmdQue, &prAdapter->rTxCmdQueue); + + 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 + wlanReleaseCommand(prAdapter, prCmdInfo, TX_RESULT_QUEUE_CLEARANCE); + + /* Release Tx resource for CMD which resource is allocated but not used */ + nicTxReleaseResource(prAdapter, nicTxGetCmdResourceType(prCmdInfo), + nicTxGetCmdPageCount(prCmdInfo), TRUE); + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + } else { + QUEUE_INSERT_TAIL(&prAdapter->rTxCmdQueue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to clear all commands in TX command done queue +* \param prAdapter Pointer of Adapter Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanClearTxCommandDoneQueue(IN P_ADAPTER_T prAdapter) +{ + QUE_T rTempCmdDoneQue; + P_QUE_T prTempCmdDoneQue = &rTempCmdDoneQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + QUEUE_INITIALIZE(prTempCmdDoneQue); + + /* 4 <1> Move whole list of CMD_INFO to temp queue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); + QUEUE_MOVE_ALL(prTempCmdDoneQue, &prAdapter->rTxCmdDoneQueue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); + + /* 4 <2> Dequeue from head and check it is able to be sent */ + QUEUE_REMOVE_HEAD(prTempCmdDoneQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + if (prCmdInfo->pfCmdDoneHandler) + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prCmdInfo->pucInfoBuffer); + /* Not pending cmd, free it after TX succeed! */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + QUEUE_REMOVE_HEAD(prTempCmdDoneQue, prQueueEntry, P_QUE_ENTRY_T); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to clear all buffer in port 0/1 queue +* \param prAdapter Pointer of Adapter Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanClearDataQueue(IN P_ADAPTER_T prAdapter) +{ + if (HAL_IS_TX_DIRECT()) + nicTxDirectClearHifQ(prAdapter); + else { +#if CFG_FIX_2_TX_PORT + QUE_T qDataPort0, qDataPort1; + P_QUE_T prDataPort0, prDataPort1; + P_MSDU_INFO_T prMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + prDataPort0 = &qDataPort0; + prDataPort1 = &qDataPort1; + + QUEUE_INITIALIZE(prDataPort0); + QUEUE_INITIALIZE(prDataPort1); + + /* <1> Move whole list of CMD_INFO to temp queue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + QUEUE_MOVE_ALL(prDataPort0, &prAdapter->rTxP0Queue); + QUEUE_MOVE_ALL(prDataPort1, &prAdapter->rTxP1Queue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + + /* <2> Release Tx resource */ + nicTxReleaseMsduResource(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(prDataPort0)); + nicTxReleaseMsduResource(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(prDataPort1)); + + /* <3> Return sk buffer */ + nicTxReturnMsduInfo(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(prDataPort0)); + nicTxReturnMsduInfo(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(prDataPort1)); + + /* <4> Clear pending MSDU info in data done queue */ + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); + while (QUEUE_IS_NOT_EMPTY(&prAdapter->rTxDataDoneQueue)) { + QUEUE_REMOVE_HEAD(&prAdapter->rTxDataDoneQueue, prMsduInfo, P_MSDU_INFO_T); + + nicTxFreePacket(prAdapter, prMsduInfo, FALSE); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } + KAL_RELEASE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); +#else + + QUE_T qDataPort[TX_PORT_NUM]; + P_QUE_T prDataPort[TX_PORT_NUM]; + P_MSDU_INFO_T prMsduInfo; + INT_32 i; + + KAL_SPIN_LOCK_DECLARATION(); + + for (i = 0; i < TX_PORT_NUM; i++) { + prDataPort[i] = &qDataPort[i]; + QUEUE_INITIALIZE(prDataPort[i]); + } + + /* <1> Move whole list of CMD_INFO to temp queue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + for (i = 0; i < TX_PORT_NUM; i++) + QUEUE_MOVE_ALL(prDataPort[i], &prAdapter->rTxPQueue[i]); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + + /* <2> Return sk buffer */ + for (i = 0; i < TX_PORT_NUM; i++) { + nicTxReleaseMsduResource(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(prDataPort[i])); + nicTxReturnMsduInfo(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(prDataPort[i])); + } + + /* <3> Clear pending MSDU info in data done queue */ + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); + while (QUEUE_IS_NOT_EMPTY(&prAdapter->rTxDataDoneQueue)) { + QUEUE_REMOVE_HEAD(&prAdapter->rTxDataDoneQueue, prMsduInfo, P_MSDU_INFO_T); + + nicTxFreePacket(prAdapter, prMsduInfo, FALSE); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } + KAL_RELEASE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); +#endif + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to clear all buffer in port 0/1 queue +* \param prAdapter Pointer of Adapter Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanClearRxToOsQueue(IN P_ADAPTER_T prAdapter) +{ + QUE_T rTempRxQue; + P_QUE_T prTempRxQue = &rTempRxQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + QUEUE_INITIALIZE(prTempRxQue); + + /* 4 <1> Move whole list of CMD_INFO to temp queue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); + QUEUE_MOVE_ALL(prTempRxQue, &prAdapter->rRxQueue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); + + /* 4 <2> Remove all skbuf */ + QUEUE_REMOVE_HEAD(prTempRxQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + kalRxIndicateOnePkt(prAdapter->prGlueInfo, (PVOID) GLUE_GET_PKT_DESCRIPTOR(prQueueEntry)); + QUEUE_REMOVE_HEAD(prTempRxQue, prQueueEntry, P_QUE_ENTRY_T); + } + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \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 + * \param rTxDoneStatus Tx done status + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +VOID wlanReleaseCommand(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + 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: + DBGLOG(INIT, INFO, "Free CMD: ID[0x%x] SeqNum[%u] OID[%u]\n", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum, prCmdInfo->fgIsOid); + + if (prCmdInfo->fgIsOid) { + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, WLAN_STATUS_FAILURE); + } + break; + + case COMMAND_TYPE_SECURITY_FRAME: + case COMMAND_TYPE_MANAGEMENT_FRAME: + prMsduInfo = prCmdInfo->prMsduInfo; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) { + kalSecurityFrameSendComplete(prAdapter->prGlueInfo, prCmdInfo->prPacket, WLAN_STATUS_FAILURE); + /* Avoid skb multiple free */ + prMsduInfo->prPacket = NULL; + } + + DBGLOG(INIT, INFO, + "Free %s Frame: BSS[%u] WIDX:PID[%u:%u] SEQ[%u] STA[%u] RSP[%u] CMDSeq[%u]\n", + prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME ? "SEC" : "MGMT", + prMsduInfo->ucBssIndex, + prMsduInfo->ucWlanIndex, + prMsduInfo->ucPID, + prMsduInfo->ucTxSeqNum, + prMsduInfo->ucStaRecIndex, prMsduInfo->pfTxDoneHandler ? TRUE : FALSE, prCmdInfo->ucCmdSeqNum); + + /* invoke callbacks */ + if (prMsduInfo->pfTxDoneHandler != NULL) + prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, rTxDoneStatus); + + if (prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) + GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum); + + cnmMgtPktFree(prAdapter, prMsduInfo); + break; + + default: + ASSERT(0); + break; + } + +} /* end of wlanReleaseCommand() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will search the CMD Queue to look for the pending OID and +* compelete it immediately when system request a reset. +* +* \param prAdapter ointer of Adapter Data Structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanReleasePendingOid(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr) +{ + 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); + + if (prAdapter->prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(OID, TRACE, "%s stopped! Releasing pending OIDs ..\n", KAL_GET_CURRENT_THREAD_NAME()); + } else { + DBGLOG(OID, ERROR, "OID Timeout! Releasing pending OIDs ..\n"); + prAdapter->ucOidTimeoutCount++; + + if (prAdapter->ucOidTimeoutCount >= WLAN_OID_NO_ACK_THRESHOLD) { + if (!prAdapter->fgIsChipNoAck) { + DBGLOG(INIT, WARN, + "No response from chip for %u times, set NoAck flag!\n", + prAdapter->ucOidTimeoutCount); + } + + prAdapter->fgIsChipNoAck = TRUE; +#if CFG_CHIP_RESET_SUPPORT + DBGLOG(HAL, ERROR, "fgIsChipNoAck = %d\n", + prAdapter->fgIsChipNoAck); + glResetTrigger(prAdapter); +#endif + } + set_bit(GLUE_FLAG_HIF_PRT_HIF_DBG_INFO_BIT, &(prAdapter->prGlueInfo->ulFlag)); + } + + do { +#if CFG_SUPPORT_MULTITHREAD + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_TX_CMD_CLEAR); +#endif + + /* 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) { + DBGLOG(OID, INFO, "Clear pending OID CMD ID[0x%02X] SEQ[%u] buf[0x%p]\n", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum, prCmdInfo->pucInfoBuffer); + + if (prCmdInfo->pfCmdTimeoutHandler) { + prCmdInfo->pfCmdTimeoutHandler(prAdapter, prCmdInfo); + } else { + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, 0, WLAN_STATUS_FAILURE); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + nicTxCancelSendingCmd(prAdapter, prCmdInfo); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + + 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); + +#if CFG_SUPPORT_MULTITHREAD + /* Clear pending OID in main_thread to hif_thread command queue */ + wlanClearTxOidCommand(prAdapter); +#endif + + /* 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); + +#if CFG_SUPPORT_MULTITHREAD + KAL_RELEASE_MUTEX(prAdapter, MUTEX_TX_CMD_CLEAR); +#endif + } while (FALSE); + + DBGLOG(OID, INFO, "End of Release pending OID\n"); + + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 wlanReleasePendingCMDbyBssIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex) +{ +#if 0 + + 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 BSS:%d\n", prCmdInfo->ucBssIndex); + + if (prCmdInfo->ucBssIndex == ucBssIndex) { + if (prCmdInfo->pfCmdTimeoutHandler) { + prCmdInfo->pfCmdTimeoutHandler(prAdapter, prCmdInfo); + } else if (prCmdInfo->fgIsOid) { + 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); +#endif + + +} /* wlanReleasePendingCMDbyBssIdx */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Return the indicated packet buffer and reallocate one to the RFB +* +* \param prAdapter Pointer of Adapter Data Structure +* \param pvPacket Pointer of returned packet +* +* \retval WLAN_STATUS_SUCCESS: Success +* \retval WLAN_STATUS_FAILURE: Failed +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanReturnPacketDelaySetupTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr) +{ + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = NULL; + + KAL_SPIN_LOCK_DECLARATION(); + WLAN_STATUS status = WLAN_STATUS_SUCCESS; + P_QUE_T prQueList; + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + prQueList = &prRxCtrl->rIndicatedRfbList; + DBGLOG(RX, WARN, "%s: IndicatedRfbList num = %u\n", __func__, prQueList->u4NumElem); + + while (QUEUE_IS_NOT_EMPTY(&prRxCtrl->rIndicatedRfbList)) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rIndicatedRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + status = nicRxSetupRFB(prAdapter, prSwRfb); + nicRxReturnRFB(prAdapter, prSwRfb); + + if (status != WLAN_STATUS_SUCCESS) + break; + } + + if (status != WLAN_STATUS_SUCCESS) { + DBGLOG(RX, WARN, "Restart ReturnIndicatedRfb Timer (%u)\n", RX_RETURN_INDICATED_RFB_TIMEOUT_SEC); + /* restart timer */ + cnmTimerStartTimer(prAdapter, + &prAdapter->rPacketDelaySetupTimer, + SEC_TO_MSEC(RX_RETURN_INDICATED_RFB_TIMEOUT_SEC)); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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)) { + /*Todo:: nothing */ + /*Todo:: nothing */ + } +#endif + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rIndicatedRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + if (!prSwRfb) { + DBGLOG(RX, WARN, "No free SwRfb!\n"); + return; + } + + if (nicRxSetupRFB(prAdapter, prSwRfb)) { + DBGLOG(RX, WARN, "Cannot allocate packet buffer for SwRfb!\n"); + if (!timerPendingTimer(&prAdapter->rPacketDelaySetupTimer)) { + DBGLOG(RX, WARN, "Start ReturnIndicatedRfb Timer (%u)\n", RX_RETURN_INDICATED_RFB_TIMEOUT_SEC); + cnmTimerStartTimer(prAdapter, &prAdapter->rPacketDelaySetupTimer, + SEC_TO_MSEC(RX_RETURN_INDICATED_RFB_TIMEOUT_SEC)); + } + } + 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)) { + /* note: return WLAN_STATUS_FAILURE or + * WLAN_STATUS_SUCCESS for blocking OIDs during current measurement ?? + */ + return WLAN_STATUS_SUCCESS; + } +#if 1 + /* most OID handler will just queue a command packet */ + status = pfnOidQryHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4QryInfoLen); +#else + if (wlanIsHandlerNeedHwAccess(pfnOidQryHandler, FALSE)) { + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + /* Reset sleepy state */ + if (prAdapter->fgWiFiInSleepyState == TRUE) + prAdapter->fgWiFiInSleepyState = FALSE; + + status = pfnOidQryHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4QryInfoLen); + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + } else + status = pfnOidQryHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4QryInfoLen); +#endif + + return status; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a required function that allows bound protocol drivers, +* or NDIS, to request changes in the state information that the miniport +* maintains for particular object identifiers, such as changes in multicast +* addresses. +* +* \param[IN] prAdapter Pointer to the Glue info structure. +* \param[IN] pfnOidSetHandler Points to the OID set handlers. +* \param[IN] pvInfoBuf Points to a buffer containing the OID-specific data for the set. +* \param[IN] u4InfoBufLen Specifies the number of bytes at prSetBuffer. +* \param[OUT] pu4SetInfoLen Points to the number of bytes it read or is needed. +* +* \retval WLAN_STATUS_xxx Different WLAN_STATUS code returned by different handlers. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanSetInformation(IN P_ADAPTER_T prAdapter, + IN PFN_OID_HANDLER_FUNC pfnOidSetHandler, + IN PVOID pvInfoBuf, IN UINT_32 u4InfoBufLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS status = WLAN_STATUS_FAILURE; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* ignore any OID request after connected, under PS current measurement mode */ + if (prAdapter->u4PsCurrentMeasureEn && + (prAdapter->prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_CONNECTED)) { + /* note: return WLAN_STATUS_FAILURE or WLAN_STATUS_SUCCESS + * for blocking OIDs during current measurement ?? + */ + return WLAN_STATUS_SUCCESS; + } +#if 1 + /* most OID handler will just queue a command packet + * for power state transition OIDs, handler will acquire power control by itself + */ + status = pfnOidSetHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4SetInfoLen); +#else + if (wlanIsHandlerNeedHwAccess(pfnOidSetHandler, TRUE)) { + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + /* Reset sleepy state */ + if (prAdapter->fgWiFiInSleepyState == TRUE) + prAdapter->fgWiFiInSleepyState = FALSE; + + status = pfnOidSetHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4SetInfoLen); + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + } else { + status = pfnOidSetHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4SetInfoLen); + } +#endif + + return status; +} + +#if CFG_SUPPORT_WAPI +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a used to query driver's config wapi mode or not +* +* \param[IN] prAdapter Pointer to the Glue info structure. +* +* \retval TRUE for use wapi mode +* +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanQueryWapiMode(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + return prAdapter->rWifiVar.rConnSettings.fgWapiMode; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to set RX filter to Promiscuous Mode. +* +* \param[IN] prAdapter Pointer to the Adapter structure. +* \param[IN] fgEnablePromiscuousMode Enable/ disable RX Promiscuous Mode. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanSetPromiscuousMode(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnablePromiscuousMode) +{ + ASSERT(prAdapter); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to set RX filter to allow to receive +* broadcast address packets. +* +* \param[IN] prAdapter Pointer to the Adapter structure. +* \param[IN] fgEnableBroadcast Enable/ disable broadcast packet to be received. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanRxSetBroadcast(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnableBroadcast) +{ + ASSERT(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to send out CMD_ID_DUMMY command packet +* +* \param[IN] prAdapter Pointer to the Adapter structure. +* +* \return WLAN_STATUS_SUCCESS +* \return WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanSendDummyCmd(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsReqTxRsrc) +{ + WLAN_STATUS status = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = (UINT_16) CMD_HDR_SIZE; + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->pfCmdTimeoutHandler = NULL; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_DUMMY_RSV; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->ucCmdSeqNum = 0; + prCmdInfo->u4SetInfoLen = 0; + + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + if (fgIsReqTxRsrc) { + if (wlanSendCommand(prAdapter, prCmdInfo) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "Fail to transmit CMD_ID_DUMMY command\n"); + status = WLAN_STATUS_FAILURE; + } + } else { + if (nicTxCmd(prAdapter, prCmdInfo, TC4_INDEX) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "Fail to transmit CMD_ID_DUMMY command\n"); + status = WLAN_STATUS_FAILURE; + } + } + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(CMD_NIC_POWER_CTRL); + + /* 2.3 Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + 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, nicTxGetCmdPageCount(prCmdInfo), TRUE) + == 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; + prAdapter->fgIsChipNoAck = TRUE; +#if CFG_CHIP_RESET_SUPPORT + DBGLOG(HAL, ERROR, "fgIsChipNoAck = %d\n", + prAdapter->fgIsChipNoAck); + glResetTrigger(prAdapter); +#endif + break; + } + continue; + } + break; + }; + + /* 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; + } + + /* 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 set g_fgKeepFullPwr flag in firmware +* +* \param[IN] prAdapter Pointer to the Adapter structure. +* \param[IN] fgEnable Boolean of enable +* True: wlan stays awake and keeps working in full power state +* False: wlan may go to sleep and consumes less power. +* +* \return WLAN_STATUS_SUCCESS +* \return WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanKeepFullPwr(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnable) +{ + struct CMD_KEEP_FULL_PWR_T rCmdKeepFullPwr; + + ASSERT(prAdapter); + + rCmdKeepFullPwr.ucEnable = fgEnable; + DBGLOG(HAL, STATE, "KeepFullPwr: %d\n", rCmdKeepFullPwr.ucEnable); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_KEEP_FULL_PWR, TRUE, FALSE, FALSE, NULL, NULL, + sizeof(struct CMD_KEEP_FULL_PWR_T), (PUINT_8)&rCmdKeepFullPwr, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +VOID wlanImageSectionGetFwInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvFwImageMapFile, IN UINT_32 u4FwImageFileLength, + IN UINT_8 ucTotSecNum, IN UINT_8 ucCurSecNum, IN ENUM_IMG_DL_IDX_T eDlIdx, + OUT PUINT_32 pu4StartOffset, OUT PUINT_32 pu4Addr, OUT PUINT_32 pu4Len, + OUT PUINT_32 pu4DataMode) +{ + UINT_32 u4DataMode = 0; + fw_image_tailer_t *prFwHead; + tailer_format_t *prTailer; + + prFwHead = (fw_image_tailer_t *) (pvFwImageMapFile + u4FwImageFileLength - sizeof(fw_image_tailer_t)); + if (ucTotSecNum == 1) + prTailer = &prFwHead->dlm_info; + else + prTailer = &prFwHead->ilm_info; + + + prTailer = &prTailer[ucCurSecNum]; + + *pu4StartOffset = 0; + *pu4Addr = prTailer->addr; + *pu4Len = (prTailer->len + LEN_4_BYTE_CRC); + if (prTailer->feature_set & DOWNLOAD_CONFIG_ENCRYPTION_MODE) { + u4DataMode |= DOWNLOAD_CONFIG_RESET_OPTION; + u4DataMode |= (prTailer->feature_set & DOWNLOAD_CONFIG_KEY_INDEX_MASK); + u4DataMode |= DOWNLOAD_CONFIG_ENCRYPTION_MODE; + } + + if (eDlIdx == IMG_DL_IDX_CR4_FW) + u4DataMode |= DOWNLOAD_CONFIG_WORKING_PDA_OPTION; + +#if CFG_ENABLE_FW_DOWNLOAD_ACK + u4DataMode |= DOWNLOAD_CONFIG_ACK_OPTION; /* ACK needed */ +#endif + + *pu4DataMode = u4DataMode; + + /* Dump image information */ + if (ucCurSecNum == 0) { + DBGLOG(INIT, INFO, "%s INFO: chip_info[%u:E%u] feature[0x%02X]\n", + (eDlIdx == IMG_DL_IDX_N9_FW) ? "N9" : "CR4", prTailer->chip_info, + prTailer->eco_code + 1, prTailer->feature_set); + DBGLOG(INIT, INFO, "date[%s] version[%c%c%c%c%c%c%c%c%c%c]\n", + prTailer->ram_built_date, + prTailer->ram_version[0], prTailer->ram_version[1], + prTailer->ram_version[2], prTailer->ram_version[3], + prTailer->ram_version[4], prTailer->ram_version[5], + prTailer->ram_version[6], prTailer->ram_version[7], + prTailer->ram_version[8], prTailer->ram_version[9]); + } + + /* Backup to FW version info */ + if (eDlIdx == IMG_DL_IDX_N9_FW) + kalMemCopy(&prAdapter->rVerInfo.rN9tailer, prTailer, sizeof(tailer_format_t)); + else + kalMemCopy(&prAdapter->rVerInfo.rCR4tailer, prTailer, sizeof(tailer_format_t)); +} +#if CFG_SUPPORT_COMPRESSION_FW_OPTION +VOID wlanImageSectionGetCompressFwInfo(IN P_ADAPTER_T prAdapter, +IN PVOID pvFwImageMapFile, IN UINT_32 u4FwImageFileLength, IN UINT_8 ucTotSecNum, IN UINT_8 ucCurSecNum, +IN ENUM_IMG_DL_IDX_T eDlIdx, OUT PUINT_32 pu4StartOffset, OUT PUINT_32 pu4Addr, OUT PUINT_32 pu4Len, +OUT PUINT_32 pu4DataMode, OUT PUINT_32 pu4BlockSize, OUT PUINT_32 pu4CRC, OUT PUINT_32 pu4UncompressedLength) +{ + UINT_32 u4DataMode = 0; + fw_image_tailer_t_2 *prFwHead; + tailer_format_t_2 *prTailer; + + prFwHead = (fw_image_tailer_t_2 *) (pvFwImageMapFile + u4FwImageFileLength - sizeof(fw_image_tailer_t_2)); + if (ucTotSecNum == 1) + prTailer = &prFwHead->dlm_info; + else + prTailer = &prFwHead->ilm_info; + + prTailer = &prTailer[ucCurSecNum]; + + *pu4StartOffset = 0; + *pu4Addr = prTailer->addr; + *pu4Len = (prTailer->len); + *pu4BlockSize = (prTailer->block_size); + *pu4CRC = (prTailer->crc); + *pu4UncompressedLength = (prTailer->real_size); + if (prTailer->feature_set & DOWNLOAD_CONFIG_ENCRYPTION_MODE) { + u4DataMode |= DOWNLOAD_CONFIG_RESET_OPTION; + u4DataMode |= (prTailer->feature_set & DOWNLOAD_CONFIG_KEY_INDEX_MASK); + u4DataMode |= DOWNLOAD_CONFIG_ENCRYPTION_MODE; + } + if (eDlIdx == IMG_DL_IDX_CR4_FW) + u4DataMode |= DOWNLOAD_CONFIG_WORKING_PDA_OPTION; + +#if CFG_ENABLE_FW_DOWNLOAD_ACK + u4DataMode |= DOWNLOAD_CONFIG_ACK_OPTION; /* ACK needed */ +#endif + + *pu4DataMode = u4DataMode; + + /* Dump image information */ + if (ucCurSecNum == 0) { + DBGLOG(INIT, INFO, "%s INFO: chip_info[%u:E%u] feature[0x%02X]\n", + (eDlIdx == IMG_DL_IDX_N9_FW) ? "N9" : "CR4", prTailer->chip_info, + prTailer->eco_code, prTailer->feature_set); + DBGLOG(INIT, INFO, "date[%s] version[%c%c%c%c%c%c%c%c%c%c]\n", prTailer->ram_built_date, + prTailer->ram_version[0], prTailer->ram_version[1], + prTailer->ram_version[2], prTailer->ram_version[3], + prTailer->ram_version[4], prTailer->ram_version[5], + prTailer->ram_version[6], prTailer->ram_version[7], + prTailer->ram_version[8], prTailer->ram_version[9]); + } + /* Backup to FW version info */ + if (eDlIdx == IMG_DL_IDX_N9_FW) { + kalMemCopy(&prAdapter->rVerInfo.rN9Compressedtailer, prTailer, sizeof(tailer_format_t_2)); + prAdapter->rVerInfo.fgIsN9CompressedFW = TRUE; + } else { + kalMemCopy(&prAdapter->rVerInfo.rCR4Compressedtailer, prTailer, sizeof(tailer_format_t_2)); + prAdapter->rVerInfo.fgIsCR4CompressedFW = TRUE; + } +} +#endif +VOID wlanImageSectionGetPatchInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvFwImageMapFile, IN UINT_32 u4FwImageFileLength, + IN UINT_8 ucTotSecNum, IN UINT_8 ucCurSecNum, IN ENUM_IMG_DL_IDX_T eDlIdx, + OUT PUINT_32 pu4StartOffset, OUT PUINT_32 pu4Addr, OUT PUINT_32 pu4Len, + OUT PUINT_32 pu4DataMode) +{ + P_PATCH_FORMAT_T prPatchFormat; + UINT_32 u4DataMode = 0; + UINT_8 aucBuffer[32]; + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + + prPatchFormat = (P_PATCH_FORMAT_T) pvFwImageMapFile; + + *pu4StartOffset = offsetof(PATCH_FORMAT_T, ucPatchImage); + *pu4Addr = prChipInfo->patch_addr; + *pu4Len = u4FwImageFileLength - offsetof(PATCH_FORMAT_T, ucPatchImage); + +#if CFG_ENABLE_FW_DOWNLOAD_ACK + u4DataMode |= DOWNLOAD_CONFIG_ACK_OPTION; /* ACK needed */ +#endif + *pu4DataMode = u4DataMode; + + /* Dump image information */ + kalStrnCpy(aucBuffer, prPatchFormat->aucPlatform, 4); + aucBuffer[4] = '\0'; + DBGLOG(INIT, INFO, "PATCH INFO: platform[%s] HW/SW ver[0x%04X] ver[0x%04X]\n", + aucBuffer, prPatchFormat->u4SwHwVersion, prPatchFormat->u4PatchVersion); + + kalStrnCpy(aucBuffer, prPatchFormat->aucBuildDate, 16); + aucBuffer[16] = '\0'; + DBGLOG(INIT, INFO, "date[%s]\n", aucBuffer); + + /* Backup to FW version info */ + kalMemCopy(&prAdapter->rVerInfo.rPatchHeader, prPatchFormat, sizeof(PATCH_FORMAT_T)); +} + +VOID wlanImageSectionGetInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvFwImageMapFile, IN UINT_32 u4FwImageFileLength, + IN UINT_8 ucTotSecNum, IN UINT_8 ucCurSecNum, IN ENUM_IMG_DL_IDX_T eDlIdx, + OUT PUINT_32 pu4StartOffset, OUT PUINT_32 pu4Addr, OUT PUINT_32 pu4Len, + OUT PUINT_32 pu4DataMode) +{ + if (eDlIdx == IMG_DL_IDX_PATCH) { + wlanImageSectionGetPatchInfo(prAdapter, pvFwImageMapFile, u4FwImageFileLength, + ucTotSecNum, ucCurSecNum, eDlIdx, pu4StartOffset, pu4Addr, pu4Len, + pu4DataMode); + } else { + wlanImageSectionGetFwInfo(prAdapter, pvFwImageMapFile, u4FwImageFileLength, + ucTotSecNum, ucCurSecNum, eDlIdx, pu4StartOffset, pu4Addr, pu4Len, + pu4DataMode); + } +} +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + +BOOLEAN wlanImageSectionCheckFwCompressInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvFwImageMapFile, IN UINT_32 u4FwImageFileLength, IN ENUM_IMG_DL_IDX_T eDlIdx) { + UINT_8 ucCompression; + fw_image_tailer_check *prCheckInfo; + + if (eDlIdx == IMG_DL_IDX_PATCH) + return FALSE; + + prCheckInfo = (fw_image_tailer_check *) + (pvFwImageMapFile + u4FwImageFileLength - sizeof(fw_image_tailer_check)); + DBGLOG(INIT, INFO, "feature_set %d\n", prCheckInfo->feature_set); + ucCompression = (UINT_8)((prCheckInfo->feature_set & COMPRESSION_OPTION_MASK) + >> COMPRESSION_OPTION_OFFSET); + DBGLOG(INIT, INFO, "Compressed Check INFORMATION %d\n", ucCompression); + if (ucCompression == 1) { + DBGLOG(INIT, INFO, "Compressed FW\n"); + return TRUE; + } + return FALSE; +} + + +WLAN_STATUS wlanImageSectionDownloadStage(IN P_ADAPTER_T prAdapter, IN PVOID pvFwImageMapFile, + IN UINT_32 u4FwImageFileLength, IN UINT_8 ucSectionNumber, IN ENUM_IMG_DL_IDX_T eDlIdx, + OUT PUINT_8 pucIsCompressed, OUT P_INIT_CMD_WIFI_DECOMPRESSION_START prFwImageInFo) +{ + UINT_32 u4ImgSecSize; + UINT_32 j, i; + INT_32 i4TotalLen; + UINT_32 u4FileOffset = 0; + UINT_32 u4StartOffset = 0; + UINT_32 u4DataMode = 0; + UINT_32 u4Addr, u4Len, u4BlockSize, u4CRC, u4UnCompressedLength; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + PUINT_8 pucSecBuf, pucStartPtr; + UINT_32 u4offset = 0, u4ChunkSize; + /* 3a. parse file header for decision of divided firmware download or not */ + for (i = 0; i < ucSectionNumber; ++i) { + if (wlanImageSectionCheckFwCompressInfo(prAdapter, pvFwImageMapFile, + u4FwImageFileLength, eDlIdx) == TRUE){ + wlanImageSectionGetCompressFwInfo(prAdapter, pvFwImageMapFile, + u4FwImageFileLength, ucSectionNumber, i, eDlIdx, + &u4StartOffset, &u4Addr, &u4Len, &u4DataMode, + &u4BlockSize, &u4CRC, &u4UnCompressedLength); + u4offset = 0; + if (i == 0) { + prFwImageInFo->u4BlockSize = u4BlockSize; + prFwImageInFo->u4Region1Address = u4Addr; + prFwImageInFo->u4Region1CRC = u4CRC; + prFwImageInFo->u4Region1length = u4UnCompressedLength; + } else { + prFwImageInFo->u4Region2Address = u4Addr; + prFwImageInFo->u4Region2CRC = u4CRC; + prFwImageInFo->u4Region2length = u4UnCompressedLength; + } + i4TotalLen = u4Len; + DBGLOG(INIT, INFO, "DL Offset[%u] addr[0x%08x] len[%u] datamode[0x%08x]\n", + u4FileOffset, u4Addr, u4Len, u4DataMode); + DBGLOG(INIT, INFO, "DL BLOCK[%u] COMlen[%u] CRC[%u]\n", + u4BlockSize, u4UnCompressedLength, u4CRC); + pucStartPtr = (PUINT_8)pvFwImageMapFile + u4StartOffset; + while (i4TotalLen) { + u4ChunkSize = *((unsigned int *)(pucStartPtr+u4FileOffset)); + u4FileOffset += 4; + DBGLOG(INIT, INFO, "Downloaded Length %d! Addr %x\n", i4TotalLen, u4Addr + u4offset); + DBGLOG(INIT, INFO, "u4ChunkSize Length %d!\n", u4ChunkSize); + if (wlanImageSectionConfig(prAdapter, (u4Addr + u4offset), u4ChunkSize, + u4DataMode, eDlIdx) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "Firmware download configuration failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } + for (j = 0; j < u4ChunkSize; j += CMD_PKT_SIZE_FOR_IMAGE) { + if (j + CMD_PKT_SIZE_FOR_IMAGE < u4ChunkSize) + u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; + else + u4ImgSecSize = u4ChunkSize - j; + pucSecBuf = (PUINT_8)pucStartPtr + u4FileOffset + j; + if (wlanImageSectionDownload(prAdapter, u4ImgSecSize, pucSecBuf) + != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "Firmware scatter download failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } + } +/* escape from loop if any pending error occurs */ + if (u4Status == WLAN_STATUS_FAILURE) + break; + i4TotalLen -= u4ChunkSize; + u4offset += u4BlockSize; + u4FileOffset += u4ChunkSize; + if (i4TotalLen < 0) { + DBGLOG(INIT, ERROR, "Firmware scatter download failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } + } + *pucIsCompressed = TRUE; + } else { + wlanImageSectionGetInfo(prAdapter, pvFwImageMapFile, + u4FwImageFileLength, ucSectionNumber, i, eDlIdx, + &u4StartOffset, &u4Addr, &u4Len, &u4DataMode); + pucStartPtr = (PUINT_8)pvFwImageMapFile + u4StartOffset; + + DBGLOG(INIT, INFO, "DL Offset[%u] addr[0x%08x] len[%u] datamode[0x%08x]\n", + u4FileOffset, u4Addr, u4Len, u4DataMode); + + if (wlanImageSectionConfig(prAdapter, u4Addr, u4Len, u4DataMode, eDlIdx) + != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "Firmware download configuration failed!\n"); + + u4Status = WLAN_STATUS_FAILURE; + break; + } + for (j = 0; j < u4Len; j += CMD_PKT_SIZE_FOR_IMAGE) { + if (j + CMD_PKT_SIZE_FOR_IMAGE < u4Len) + u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; + else + u4ImgSecSize = u4Len - j; + + pucSecBuf = (PUINT_8)pucStartPtr + u4FileOffset + j; + if (wlanImageSectionDownload(prAdapter, u4ImgSecSize, pucSecBuf) + != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "Firmware scatter download failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } + } + + /* escape from loop if any pending error occurs */ + if (u4Status == WLAN_STATUS_FAILURE) + break; + u4FileOffset += u4Len; + *pucIsCompressed = FALSE; + } + } + return u4Status; +} +#else +WLAN_STATUS wlanImageSectionDownloadStage(IN P_ADAPTER_T prAdapter, + IN PVOID pvFwImageMapFile, IN UINT_32 u4FwImageFileLength, + IN UINT_8 ucSectionNumber, IN ENUM_IMG_DL_IDX_T eDlIdx) +{ + UINT_32 u4ImgSecSize; + UINT_32 j, i; + UINT_32 u4FileOffset = 0; + UINT_32 u4StartOffset = 0; + UINT_32 u4DataMode = 0; + UINT_32 u4Addr, u4Len; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + PUINT_8 pucSecBuf, pucStartPtr; + + /* 3a. parse file header for decision of divided firmware download or not */ + for (i = 0; i < ucSectionNumber; ++i) { + wlanImageSectionGetInfo(prAdapter, pvFwImageMapFile, + u4FwImageFileLength, ucSectionNumber, i, eDlIdx, + &u4StartOffset, &u4Addr, &u4Len, &u4DataMode); + + pucStartPtr = (PUINT_8) pvFwImageMapFile + u4StartOffset; + + DBGLOG(INIT, INFO, "DL Offset[%u] addr[0x%08x] len[%u] datamode[0x%08x]\n", + u4FileOffset, u4Addr, u4Len, u4DataMode); + + if (wlanImageSectionConfig(prAdapter, u4Addr, u4Len, u4DataMode, eDlIdx) + != WLAN_STATUS_SUCCESS) { + + DBGLOG(INIT, ERROR, "Firmware download configuration failed!\n"); + + u4Status = WLAN_STATUS_FAILURE; + break; + } + + for (j = 0; j < u4Len; j += CMD_PKT_SIZE_FOR_IMAGE) { + if (j + CMD_PKT_SIZE_FOR_IMAGE < u4Len) + u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; + else + u4ImgSecSize = u4Len - j; + + pucSecBuf = (PUINT_8) pucStartPtr + u4FileOffset + j; + if (wlanImageSectionDownload(prAdapter, u4ImgSecSize, pucSecBuf) + != WLAN_STATUS_SUCCESS) { + + DBGLOG(INIT, ERROR, "Firmware scatter download failed!\n"); + + u4Status = WLAN_STATUS_FAILURE; + break; + } + kalMdelay(1); + } + + /* escape from loop if any pending error occurs */ + if (u4Status == WLAN_STATUS_FAILURE) + break; + + + u4FileOffset += u4Len; + } + + return u4Status; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to confirm the status of +* previously patch semaphore control +* +* @param prAdapter Pointer to the Adapter structure. +* ucCmdSeqNum Sequence number of previous firmware scatter +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanPatchRecvSemaResp(IN P_ADAPTER_T prAdapter, IN UINT_8 ucCmdSeqNum, OUT PUINT_8 pucPatchStatus) +{ + 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; + + ASSERT(prAdapter); + + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) + return WLAN_STATUS_FAILURE; + + + if (nicRxWaitResponse(prAdapter, 0, aucBuffer, + sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_EVENT_CMD_RESULT), + &u4RxPktLength) != WLAN_STATUS_SUCCESS) { + + DBGLOG(INIT, WARN, "Wait patch semaphore response fail\n"); + return WLAN_STATUS_FAILURE; + } + + prInitHifRxHeader = (P_INIT_HIF_RX_HEADER_T) aucBuffer; + if (prInitHifRxHeader->rInitWifiEvent.ucEID != INIT_EVENT_ID_PATCH_SEMA_CTRL) { + DBGLOG(INIT, WARN, "Unexpected EVENT ID, get 0x%0x\n", prInitHifRxHeader->rInitWifiEvent.ucEID); + return WLAN_STATUS_FAILURE; + } + + if (prInitHifRxHeader->rInitWifiEvent.ucSeqNum != ucCmdSeqNum) { + DBGLOG(INIT, WARN, "Unexpected SeqNum %d, %d\n", ucCmdSeqNum, + prInitHifRxHeader->rInitWifiEvent.ucSeqNum); + return WLAN_STATUS_FAILURE; + } + + prEventCmdResult = (P_INIT_EVENT_CMD_RESULT) (prInitHifRxHeader->rInitWifiEvent.aucBuffer); + + *pucPatchStatus = prEventCmdResult->ucStatus; + +#if 0 + if (prEventCmdResult->ucStatus != PATCH_STATUS_GET_SEMA_NEED_PATCH) { + DBGLOG(INIT, INFO, "Patch status[%d], skip patch\n", prEventCmdResult->ucStatus); + return WLAN_STATUS_FAILURE; + } + DBGLOG(INIT, INFO, "Status[%d], ready to patch\n", prEventCmdResult->ucStatus); + return WLAN_STATUS_SUCCESS; + +#endif + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to check the patch semaphore control. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanPatchSendSemaControl(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucSeqNum) +{ + P_CMD_INFO_T prCmdInfo; + P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + P_INIT_CMD_PATCH_SEMA_CONTROL prPatchSemaControl; + + ASSERT(prAdapter); + + DEBUGFUNC("wlanImagePatchSemaphoreCheck"); + + /* 1. Allocate CMD Info Packet and its Buffer. */ + prCmdInfo = + cmdBufAllocateCmdInfo(prAdapter, sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_PATCH_SEMA_CONTROL)); + + /* DBGLOG(INIT, ERROR, "sizeof INIT_HIF_TX_HEADER_T = %d\n", sizeof(INIT_HIF_TX_HEADER_T)); */ + 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_PATCH_SEMA_CONTROL); + + /* 2. Setup common CMD Info Packet */ + prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prInitHifTxHeader->u2PQ_ID = INIT_CMD_PQ_ID; + prInitHifTxHeader->ucHeaderFormat = INIT_CMD_PACKET_TYPE_ID; + prInitHifTxHeader->ucPktFt = INIT_PKT_FT_CMD; + + prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_PATCH_SEMAPHORE_CONTROL; + prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = INIT_CMD_PDA_PACKET_TYPE_ID; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + *pucSeqNum = prInitHifTxHeader->rInitWifiCmd.ucSeqNum; + + /* 3. Setup DOWNLOAD_BUF */ + prPatchSemaControl = (P_INIT_CMD_PATCH_SEMA_CONTROL) prInitHifTxHeader->rInitWifiCmd.aucBuffer; + kalMemZero(prPatchSemaControl, sizeof(INIT_CMD_PATCH_SEMA_CONTROL)); + prPatchSemaControl->ucGetSemaphore = PATCH_GET_SEMA_CONTROL; + + /* 4. Send FW_Download command */ + if (nicTxInitCmd(prAdapter, prCmdInfo) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to transmit image download command\n"); + } + /* 5. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + +BOOLEAN wlanPatchIsDownloaded(IN P_ADAPTER_T prAdapter) +{ + UINT_8 ucSeqNum, ucPatchStatus; + WLAN_STATUS rStatus; + UINT_32 u4Count; + + ucPatchStatus = PATCH_STATUS_NO_SEMA_NEED_PATCH; + u4Count = 0; + + while (ucPatchStatus == PATCH_STATUS_NO_SEMA_NEED_PATCH) { + + if (u4Count) + kalMdelay(100); + + + rStatus = wlanPatchSendSemaControl(prAdapter, &ucSeqNum); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, WARN, "Send patch SEMA control CMD failed!!\n"); + break; + } + + rStatus = wlanPatchRecvSemaResp(prAdapter, ucSeqNum, &ucPatchStatus); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, WARN, "Recv patch SEMA control EVT failed!!\n"); + break; + } + + u4Count++; + + if (u4Count > 50) { + DBGLOG(INIT, WARN, "Patch status check timeout!!\n"); + break; + } + } + + if (ucPatchStatus == PATCH_STATUS_NO_NEED_TO_PATCH) + return TRUE; + else + return FALSE; + +} + +WLAN_STATUS wlanPatchSendComplete(IN P_ADAPTER_T prAdapter) +{ + P_CMD_INFO_T prCmdInfo; + P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; + UINT_8 ucTC, ucCmdSeqNum; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + + /* 1. Allocate CMD Info Packet and its 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->pucInfoBuffer, sizeof(INIT_HIF_TX_HEADER_T)); + prCmdInfo->u2InfoBufLen = sizeof(INIT_HIF_TX_HEADER_T); + +#if (CFG_USE_TC4_RESOURCE_FOR_INIT_CMD == 1) + /* 2. Always use TC4 (TC4 as CPU) */ + ucTC = TC4_INDEX; +#else + /* 2. Use TC0's resource to send patch finish command. + * Only TC0 is allowed because SDIO HW always reports + * MCU's TXQ_CNT at TXQ0_CNT in CR4 architecutre) + */ + ucTC = TC0_INDEX; +#endif + + /* 3. increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* 4. Setup common CMD Info Packet */ + prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prInitHifTxHeader->u2PQ_ID = INIT_CMD_PQ_ID; + prInitHifTxHeader->ucPktFt = INIT_PKT_FT_CMD; + + prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_PATCH_FINISH; + prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = INIT_CMD_PACKET_TYPE_ID; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + /* 5. Seend WIFI start command */ + while (1) { + /* 5.1 Acquire TX Resource */ + if (nicTxAcquireResource(prAdapter, ucTC, nicTxGetPageCount(prCmdInfo->u2InfoBufLen, TRUE), TRUE) + == 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"); + goto exit; + } + continue; + } + /* 5.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to transmit WIFI start command\n"); + goto exit; + } + + break; + }; + + DBGLOG(INIT, INFO, "PATCH FINISH CMD send, waiting for RSP\n"); + + /* kalMdelay(10000); */ + + u4Status = wlanConfigWifiFuncStatus(prAdapter, ucCmdSeqNum); + + if (u4Status != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "PATCH FINISH EVT failed\n"); + else + DBGLOG(INIT, INFO, "PATCH FINISH EVT success!!\n"); + +exit: + /* 6. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to configure FWDL parameters +* +* @param prAdapter Pointer to the Adapter structure. +* u4DestAddr Address of destination address +* u4ImgSecSize Length of the firmware block +* fgReset should be set to TRUE if this is the 1st configuration +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanImageSectionConfig(IN P_ADAPTER_T prAdapter, + IN UINT_32 u4DestAddr, IN UINT_32 u4ImgSecSize, IN UINT_32 u4DataMode, + IN ENUM_IMG_DL_IDX_T eDlIdx) +{ + P_CMD_INFO_T prCmdInfo; + P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; + P_INIT_CMD_DOWNLOAD_CONFIG prInitCmdDownloadConfig; + UINT_8 ucTC, ucCmdSeqNum; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + + DEBUGFUNC("wlanImageSectionConfig"); + + 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_CONFIG)); + + 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_CONFIG); + +#if (CFG_USE_TC4_RESOURCE_FOR_INIT_CMD == 1) + /* 2. Use TC4's resource to download image. (TC4 as CPU) */ + ucTC = TC4_INDEX; +#else + /* 2. Use TC0's resource to send init_cmd. + * Only TC0 is allowed because SDIO HW always reports + * MCU's TXQ_CNT at TXQ0_CNT in CR4 architecutre) + */ + ucTC = TC0_INDEX; +#endif + + /* 3. increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* 4. Setup common CMD Info Packet */ + prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prInitHifTxHeader->u2PQ_ID = INIT_CMD_PQ_ID; + prInitHifTxHeader->ucHeaderFormat = INIT_CMD_PACKET_TYPE_ID; + prInitHifTxHeader->ucPktFt = INIT_PKT_FT_CMD; + + if (eDlIdx == IMG_DL_IDX_PATCH) + prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_PATCH_START; + else + prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_DOWNLOAD_CONFIG; + + + prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = INIT_CMD_PACKET_TYPE_ID; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + /* 5. Setup CMD_DOWNLOAD_CONFIG */ + prInitCmdDownloadConfig = (P_INIT_CMD_DOWNLOAD_CONFIG) (prInitHifTxHeader->rInitWifiCmd.aucBuffer); + prInitCmdDownloadConfig->u4Address = u4DestAddr; + prInitCmdDownloadConfig->u4Length = u4ImgSecSize; + prInitCmdDownloadConfig->u4DataMode = u4DataMode; + + /* 6. Send FW_Download command */ + while (1) { + /* 6.1 Acquire TX Resource */ + if (nicTxAcquireResource(prAdapter, ucTC, nicTxGetPageCount(prCmdInfo->u2InfoBufLen, TRUE), TRUE) + == 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"); + goto exit; + } + continue; + } + /* 6.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to transmit image download command\n"); + goto exit; + } + + break; + }; + +#if CFG_ENABLE_FW_DOWNLOAD_ACK + /* 7. Wait for INIT_EVENT_ID_CMD_RESULT */ + u4Status = wlanImageSectionDownloadStatus(prAdapter, ucCmdSeqNum); +#endif + +exit: + /* 8. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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 u4ImgSecSize, IN PUINT_8 pucImgSecBuf) +{ + P_CMD_INFO_T prCmdInfo; + P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; + 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) + u4ImgSecSize); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prCmdInfo->u2InfoBufLen = sizeof(INIT_HIF_TX_HEADER_T) + (UINT_16) u4ImgSecSize; + + /* 2. Setup common CMD Info Packet */ + prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prInitHifTxHeader->u2PQ_ID = INIT_CMD_PDA_PQ_ID; + prInitHifTxHeader->ucHeaderFormat = INIT_CMD_PDA_PACKET_TYPE_ID; + prInitHifTxHeader->ucPktFt = INIT_PKT_FT_PDA_FWDL; + + prInitHifTxHeader->rInitWifiCmd.ucCID = 0; + prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = INIT_CMD_PDA_PACKET_TYPE_ID; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = 0; + + /* 3. Setup DOWNLOAD_BUF */ + kalMemCopy(prInitHifTxHeader->rInitWifiCmd.aucBuffer, pucImgSecBuf, u4ImgSecSize); + + /* 4. Send FW_Download command */ + if (nicTxInitCmd(prAdapter, prCmdInfo) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to transmit image download command\n"); + } + /* 5. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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->pucInfoBuffer, sizeof(INIT_HIF_TX_HEADER_T)); + prCmdInfo->u2InfoBufLen = sizeof(INIT_HIF_TX_HEADER_T); + +#if (CFG_USE_TC4_RESOURCE_FOR_INIT_CMD == 1) + /* 2. Always use TC4 */ + ucTC = TC4_INDEX; +#else + /* 2. Use TC0's resource to send init_cmd + * Only TC0 is allowed because SDIO HW always reports + * CPU's TXQ_CNT at TXQ0_CNT in CR4 architecutre) + */ + ucTC = TC0_INDEX; +#endif + + /* 3. increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* 4. Setup common CMD Info Packet */ + prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); + + prInitHifTxHeader->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prInitHifTxHeader->u2PQ_ID = INIT_CMD_PQ_ID; + + prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_QUERY_PENDING_ERROR; + prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = INIT_CMD_PACKET_TYPE_ID; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + /* 5. Send command */ + while (1) { + /* 5.1 Acquire TX Resource */ + if (nicTxAcquireResource(prAdapter, ucTC, nicTxGetPageCount(prCmdInfo->u2InfoBufLen, TRUE), TRUE) + == WLAN_STATUS_RESOURCES) { + if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); + break; + } + continue; + + } + /* 5.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to transmit image download command\n"); + } + + break; + }; + + /* 6. Wait for INIT_EVENT_ID_PENDING_ERROR */ + do { + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + } else if (nicRxWaitResponse(prAdapter, + 0, + aucBuffer, + sizeof(INIT_HIF_RX_HEADER_T) + + sizeof(INIT_EVENT_PENDING_ERROR), &u4RxPktLength) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + } else { + prInitHifRxHeader = (P_INIT_HIF_RX_HEADER_T) aucBuffer; + + /* EID / SeqNum check */ + if (prInitHifRxHeader->rInitWifiEvent.ucEID != INIT_EVENT_ID_PENDING_ERROR) { + u4Status = WLAN_STATUS_FAILURE; + } else if (prInitHifRxHeader->rInitWifiEvent.ucSeqNum != ucCmdSeqNum) { + u4Status = WLAN_STATUS_FAILURE; + } else { + prEventPendingError = + (P_INIT_EVENT_PENDING_ERROR) (prInitHifRxHeader->rInitWifiEvent.aucBuffer); + if (prEventPendingError->ucStatus != 0) { /* 0 for download success */ + u4Status = WLAN_STATUS_FAILURE; + } else { + u4Status = WLAN_STATUS_SUCCESS; + } + } + } + } while (FALSE); + + /* 7. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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; + + UINT_8 ucPortIdx = IMG_DL_STATUS_PORT_IDX; + + ASSERT(prAdapter); + + do { + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + } else if (nicRxWaitResponse(prAdapter, + ucPortIdx, + aucBuffer, + sizeof(INIT_HIF_RX_HEADER_T) + + sizeof(INIT_EVENT_CMD_RESULT), &u4RxPktLength) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + } else { + prInitHifRxHeader = (P_INIT_HIF_RX_HEADER_T) aucBuffer; + + /* EID / SeqNum check */ + if (prInitHifRxHeader->rInitWifiEvent.ucEID != INIT_EVENT_ID_CMD_RESULT) { + u4Status = WLAN_STATUS_FAILURE; + } else if (prInitHifRxHeader->rInitWifiEvent.ucSeqNum != ucCmdSeqNum) { + u4Status = WLAN_STATUS_FAILURE; + } else { + prEventCmdResult = + (P_INIT_EVENT_CMD_RESULT) (prInitHifRxHeader->rInitWifiEvent.aucBuffer); + if (prEventCmdResult->ucStatus != 0) { /* 0 for download success */ + DBGLOG(INIT, ERROR, "Start CMD failed, status[%u]\n", + prEventCmdResult->ucStatus); +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + if (prEventCmdResult->ucStatus == WIFI_FW_DECOMPRESSION_FAILED) + DBGLOG(INIT, ERROR, "Start Decompression CMD failed, status[%u]\n", + prEventCmdResult->ucStatus); +#endif + u4Status = WLAN_STATUS_FAILURE; + } else { + u4Status = WLAN_STATUS_SUCCESS; + } + } + } + } while (FALSE); + + return u4Status; +} + +WLAN_STATUS wlanConfigWifiFunc(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgEnable, IN UINT_32 u4StartAddress, IN UINT_8 ucPDA) +{ + P_CMD_INFO_T prCmdInfo; + P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; + P_INIT_CMD_WIFI_START prInitCmdWifiStart; + UINT_8 ucTC, ucCmdSeqNum; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + + DEBUGFUNC("wlanConfigWifiFunc"); + + /* 1. Allocate CMD Info Packet and its Buffer. */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_WIFI_START)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + kalMemZero(prCmdInfo->pucInfoBuffer, sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_WIFI_START)); + prCmdInfo->u2InfoBufLen = sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_WIFI_START); + +#if (CFG_USE_TC4_RESOURCE_FOR_INIT_CMD == 1) + /* 2. Always use TC4 (TC4 as CPU) */ + ucTC = TC4_INDEX; +#else + /* 2. Use TC0's resource to send init_cmd. + * Only TC0 is allowed because SDIO HW always reports + * CPU's TXQ_CNT at TXQ0_CNT in CR4 architecutre) + */ + ucTC = TC0_INDEX; +#endif + + /* 3. increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* 4. Setup common CMD Info Packet */ + prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prInitHifTxHeader->u2PQ_ID = INIT_CMD_PQ_ID; + prInitHifTxHeader->ucPktFt = INIT_PKT_FT_CMD; + + prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_WIFI_START; + prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = INIT_CMD_PACKET_TYPE_ID; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + prInitCmdWifiStart = (P_INIT_CMD_WIFI_START) (prInitHifTxHeader->rInitWifiCmd.aucBuffer); + prInitCmdWifiStart->u4Override = 0; + if (fgEnable) + prInitCmdWifiStart->u4Override |= START_OVERRIDE_START_ADDRESS; + + /* 5G cal until send efuse buffer mode CMD */ +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1) + if (prAdapter->fgIsSupportDelayCal == TRUE) + prInitCmdWifiStart->u4Override |= START_DELAY_CALIBRATION; +#endif + + if (ucPDA == PDA_CR4) + prInitCmdWifiStart->u4Override |= START_WORKING_PDA_OPTION; + + prInitCmdWifiStart->u4Address = u4StartAddress; + + /* 5. Seend WIFI start command */ + while (1) { + /* 5.1 Acquire TX Resource */ + if (nicTxAcquireResource(prAdapter, ucTC, nicTxGetPageCount(prCmdInfo->u2InfoBufLen, TRUE), TRUE) + == 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"); + goto exit; + } + continue; + } + /* 5.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to transmit WIFI start command\n"); + goto exit; + } + + break; + }; + + DBGLOG(INIT, INFO, "FW_START CMD send, waiting for RSP\n"); + + u4Status = wlanConfigWifiFuncStatus(prAdapter, ucCmdSeqNum); + + if (u4Status != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "FW_START EVT failed\n"); + else + DBGLOG(INIT, INFO, "FW_START EVT success!!\n"); + +exit: + /* 6. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} +#if CFG_SUPPORT_COMPRESSION_FW_OPTION +WLAN_STATUS +wlanCompressedFWConfigWifiFunc(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnable, + IN UINT_32 u4StartAddress, IN UINT_8 ucPDA, IN P_INIT_CMD_WIFI_DECOMPRESSION_START prFwImageInFo) +{ + P_CMD_INFO_T prCmdInfo; + P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; + P_INIT_CMD_WIFI_DECOMPRESSION_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_DECOMPRESSION_START)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + kalMemZero(prCmdInfo->pucInfoBuffer, + sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_WIFI_DECOMPRESSION_START)); + prCmdInfo->u2InfoBufLen = + sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_WIFI_DECOMPRESSION_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->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prInitHifTxHeader->u2PQ_ID = INIT_CMD_PQ_ID; + prInitHifTxHeader->ucPktFt = INIT_PKT_FT_CMD; + prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_DECOMPRESSED_WIFI_START; + prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = INIT_CMD_PACKET_TYPE_ID; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + prInitCmdWifiStart = (P_INIT_CMD_WIFI_DECOMPRESSION_START) (prInitHifTxHeader->rInitWifiCmd.aucBuffer); + prInitCmdWifiStart->u4Override = 0; + if (fgEnable) + prInitCmdWifiStart->u4Override |= START_OVERRIDE_START_ADDRESS; + + /* 5G cal until send efuse buffer mode CMD */ +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1) + if (prAdapter->fgIsSupportDelayCal == TRUE) + prInitCmdWifiStart->u4Override |= START_DELAY_CALIBRATION; +#endif + if (ucPDA == PDA_CR4) + prInitCmdWifiStart->u4Override |= START_WORKING_PDA_OPTION; + +#if CFG_COMPRESSION_DEBUG + prInitCmdWifiStart->u4Override |= START_CRC_CHECK; +#endif +#if CFG_DECOMPRESSION_TMP_ADDRESS + prInitCmdWifiStart->u4Override |= CHANGE_DECOMPRESSION_TMP_ADDRESS; + prInitCmdWifiStart->u4DecompressTmpAddress = 0xE6000; +#endif + prInitCmdWifiStart->u4Address = u4StartAddress; + prInitCmdWifiStart->u4Region1Address = prFwImageInFo->u4Region1Address; + prInitCmdWifiStart->u4Region1CRC = prFwImageInFo->u4Region1CRC; + prInitCmdWifiStart->u4BlockSize = prFwImageInFo->u4BlockSize; + prInitCmdWifiStart->u4Region1length = prFwImageInFo->u4Region1length; + prInitCmdWifiStart->u4Region2Address = prFwImageInFo->u4Region2Address; + prInitCmdWifiStart->u4Region2CRC = prFwImageInFo->u4Region2CRC; + prInitCmdWifiStart->u4Region2length = prFwImageInFo->u4Region2length; + + while (1) { + /* 5.1 Acquire TX Resource */ + if (nicTxAcquireResource(prAdapter, ucTC, nicTxGetPageCount(prCmdInfo->u2InfoBufLen, TRUE), TRUE) + == WLAN_STATUS_RESOURCES) { + if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); + break; + } + continue; + + } + /* 5.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to transmit WIFI start command\n"); + } + + break; + }; + + DBGLOG(INIT, INFO, "FW_START CMD send, waiting for RSP\n"); + + u4Status = wlanConfigWifiFuncStatus(prAdapter, ucCmdSeqNum); + + if (u4Status != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "FW_START EVT failed\n"); + else + DBGLOG(INIT, INFO, "FW_START EVT success!!\n"); + + + /* 6. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} +#endif +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* @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 + +WLAN_STATUS wlanDownloadFW(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4FwSize = 0; + PVOID prFwBuffer = NULL; + BOOLEAN fgReady; + WLAN_STATUS rDlStatus = 0; + WLAN_STATUS rCfgStatus = 0; +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + BOOLEAN fgIsCompressed = FALSE; + INIT_CMD_WIFI_DECOMPRESSION_START rFwImageInFo; + +#endif + + if (!prAdapter) + return WLAN_STATUS_FAILURE; + + + HAL_WIFI_FUNC_READY_CHECK(prAdapter, WIFI_FUNC_READY_BITS, &fgReady); + + if (fgReady) { + DBGLOG(INIT, INFO, "Wi-Fi is already ON!, turn off before FW DL!\n"); + + if (wlanPowerOffWifi(prAdapter) != WLAN_STATUS_SUCCESS) + return WLAN_STATUS_FAILURE; + + nicpmWakeUpWiFi(prAdapter); + HAL_HIF_INIT(prAdapter); + } + + HAL_ENABLE_FWDL(prAdapter, TRUE); + +#if (MTK_WCN_HIF_SDIO == 0) + wlanDownloadPatch(prAdapter); +#endif + + DBGLOG(INIT, INFO, "FW download Start\n"); + + do { + /* N9 ILM+DLM */ + kalFirmwareImageMapping(prAdapter->prGlueInfo, &prFwBuffer, &u4FwSize, IMG_DL_IDX_N9_FW); + if (prFwBuffer == NULL) { + DBGLOG(INIT, WARN, "FW[%u] load error!\n", IMG_DL_IDX_N9_FW); + break; + } +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + rDlStatus = wlanImageSectionDownloadStage(prAdapter, prFwBuffer, u4FwSize, 2, + IMG_DL_IDX_N9_FW, &fgIsCompressed, &rFwImageInFo); + if (fgIsCompressed == TRUE) + rCfgStatus = wlanCompressedFWConfigWifiFunc(prAdapter, FALSE, 0, PDA_N9, &rFwImageInFo); + else + rCfgStatus = wlanConfigWifiFunc(prAdapter, FALSE, 0, PDA_N9); + +#else + rDlStatus = wlanImageSectionDownloadStage(prAdapter, prFwBuffer, u4FwSize, 2, IMG_DL_IDX_N9_FW); + rCfgStatus = wlanConfigWifiFunc(prAdapter, FALSE, 0, PDA_N9); +#endif + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, NULL, prFwBuffer); + + if ((rDlStatus != WLAN_STATUS_SUCCESS) || (rCfgStatus != WLAN_STATUS_SUCCESS)) + break; + /* wlanCheckWifiN9Func(prAdapter); */ + + /* CR4 bin */ + kalFirmwareImageMapping(prAdapter->prGlueInfo, &prFwBuffer, &u4FwSize, IMG_DL_IDX_CR4_FW); + if (prFwBuffer == NULL) { + DBGLOG(INIT, WARN, "FW[%u] load error!\n", IMG_DL_IDX_CR4_FW); + break; + } +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + rDlStatus = wlanImageSectionDownloadStage(prAdapter, prFwBuffer, + u4FwSize, CR4_FWDL_SECTION_NUM, IMG_DL_IDX_CR4_FW, &fgIsCompressed, &rFwImageInFo); + prAdapter->fgIsCr4FwDownloaded = TRUE; + if (fgIsCompressed == TRUE) + rCfgStatus = wlanCompressedFWConfigWifiFunc(prAdapter, FALSE, 0, PDA_CR4, &rFwImageInFo); + else + rCfgStatus = wlanConfigWifiFunc(prAdapter, FALSE, 0, PDA_CR4); + +#else + rDlStatus = wlanImageSectionDownloadStage(prAdapter, prFwBuffer, + u4FwSize, CR4_FWDL_SECTION_NUM, IMG_DL_IDX_CR4_FW); + prAdapter->fgIsCr4FwDownloaded = TRUE; + rCfgStatus = wlanConfigWifiFunc(prAdapter, FALSE, 0, PDA_CR4); +#endif + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, NULL, prFwBuffer); + + if ((rDlStatus != WLAN_STATUS_SUCCESS) || (rCfgStatus != WLAN_STATUS_SUCCESS)) + break; + + } while (0); + DBGLOG(INIT, INFO, "FW download End\n"); + + HAL_ENABLE_FWDL(prAdapter, FALSE); + + if ((rDlStatus != WLAN_STATUS_SUCCESS) || (rCfgStatus != WLAN_STATUS_SUCCESS)) + return WLAN_STATUS_FAILURE; + else + return WLAN_STATUS_SUCCESS; + +} + +WLAN_STATUS wlanWakeUpWiFi(IN P_ADAPTER_T prAdapter) +{ + BOOLEAN fgReady; + + if (!prAdapter) + return WLAN_STATUS_FAILURE; + + HAL_WIFI_FUNC_READY_CHECK(prAdapter, WIFI_FUNC_READY_BITS, &fgReady); + if (fgReady) { + DBGLOG(INIT, WARN, + "Wi-Fi is already ON!, turn off before FW DL!\n"); +#if defined(_HIF_USB) + wlanSendDummyCmd(prAdapter, FALSE); /* for deep sleep mode */ + nicEnableInterrupt(prAdapter); /* clear USB EPIN FIFO */ +#endif + if (wlanPowerOffWifi(prAdapter) != WLAN_STATUS_SUCCESS) + return WLAN_STATUS_FAILURE; + } + nicpmWakeUpWiFi(prAdapter); + HAL_HIF_INIT(prAdapter); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS wlanDownloadPatch(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4FwSize = 0; + PVOID prFwBuffer = NULL; +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + UINT_8 ucIsCompressed; +#endif + if (!prAdapter) + return WLAN_STATUS_FAILURE; + + + DBGLOG(INIT, INFO, "Patch download Start\n"); + + prAdapter->rVerInfo.fgPatchIsDlByDrv = FALSE; + + kalFirmwareImageMapping(prAdapter->prGlueInfo, &prFwBuffer, &u4FwSize, IMG_DL_IDX_PATCH); + if (prFwBuffer == NULL) { + DBGLOG(INIT, WARN, "FW[%u] load error!\n", IMG_DL_IDX_PATCH); + return WLAN_STATUS_FAILURE; + } + + if (wlanPatchIsDownloaded(prAdapter)) { + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, NULL, prFwBuffer); + DBGLOG(INIT, INFO, "No need to DL patch\n"); + return WLAN_STATUS_SUCCESS; + } + + /* Patch DL */ + do { +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + wlanImageSectionDownloadStage(prAdapter, prFwBuffer, u4FwSize, 1, IMG_DL_IDX_PATCH, + &ucIsCompressed, NULL); +#else + wlanImageSectionDownloadStage(prAdapter, prFwBuffer, u4FwSize, 1, IMG_DL_IDX_PATCH); +#endif + wlanPatchSendComplete(prAdapter); + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, NULL, prFwBuffer); + + prAdapter->rVerInfo.fgPatchIsDlByDrv = TRUE; + } while (0); + + DBGLOG(INIT, INFO, "Patch download End\n"); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS wlanGetPatchInfo(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4FwSize = 0; + PVOID prFwBuffer = NULL; + UINT_32 u4StartOffset, u4Addr, u4Len, u4DataMode; + + if (!prAdapter) + return WLAN_STATUS_FAILURE; + + kalFirmwareImageMapping(prAdapter->prGlueInfo, &prFwBuffer, &u4FwSize, IMG_DL_IDX_PATCH); + if (prFwBuffer == NULL) { + DBGLOG(INIT, WARN, "FW[%u] load error!\n", IMG_DL_IDX_PATCH); + return WLAN_STATUS_FAILURE; + } + + wlanImageSectionGetInfo(prAdapter, prFwBuffer, u4FwSize, 1, 1, IMG_DL_IDX_PATCH, + &u4StartOffset, &u4Addr, &u4Len, &u4DataMode); + + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, NULL, prFwBuffer); + + return WLAN_STATUS_SUCCESS; +} + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to get the chip information +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS wlanSetChipEcoInfo(IN P_ADAPTER_T prAdapter) +{ + UINT_32 hw_version, sw_version = 0; + struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; + UINT_32 chip_id = prChipInfo->chip_id; + /* WLAN_STATUS status; */ + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanSetChipEcoInfo.\n"); + + if (wlanAccessRegister(prAdapter, TOP_HVR, &hw_version, 0, 0) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "wlanSetChipEcoInfo >> get TOP_HVR failed.\n"); + u4Status = WLAN_STATUS_FAILURE; + } else if (wlanAccessRegister(prAdapter, TOP_FVR, &sw_version, 0, 0) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "wlanSetChipEcoInfo >> get TOP_FVR failed.\n"); + u4Status = WLAN_STATUS_FAILURE; + } else { + /* success */ + nicSetChipHwVer((UINT_8)(GET_HW_VER(hw_version) & 0xFF)); + nicSetChipFactoryVer((UINT_8)((GET_HW_VER(hw_version) >> 8) & 0xF)); + nicSetChipSwVer((UINT_8)GET_FW_VER(sw_version)); + + /* Assign current chip version */ + prAdapter->chip_info->eco_ver = nicGetChipEcoVer(prAdapter); + } + + DBGLOG(INIT, INFO, "Chip ID[%04X] Version[E%u] HW[0x%08x] SW[0x%08x]\n", + chip_id, prAdapter->chip_info->eco_ver, hw_version, sw_version); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to read/write a certain N9 +* register by inband command in blocking mode in ROM code stage +* +* @param prAdapter Pointer to the Adapter structure. +* u4DestAddr Address of destination address +* u4ImgSecSize Length of the firmware block +* fgReset should be set to TRUE if this is the 1st configuration +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanAccessRegister(IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Addr, IN UINT_32 *pru4Result, IN UINT_32 u4Data, + IN UINT_8 ucSetQuery) +{ + P_CMD_INFO_T prCmdInfo; + P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; + P_INIT_HIF_RX_HEADER_T prInitHifRxHeader; + P_INIT_CMD_ACCESS_REG prInitCmdAccessReg; + P_INIT_EVENT_ACCESS_REG prInitEventAccessReg; + UINT_8 ucTC, ucCmdSeqNum; + UINT_16 cmd_size; + UINT_8 aucBuffer[sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_EVENT_ACCESS_REG)]; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + + DEBUGFUNC("wlanAccessRegister"); + + + /* 1. Allocate CMD Info Packet and its Buffer. */ + cmd_size = sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_ACCESS_REG); + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, cmd_size); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prCmdInfo->u2InfoBufLen = cmd_size; + +#if (CFG_USE_TC4_RESOURCE_FOR_INIT_CMD == 1) + /* 2. Use TC4's resource to download image. (TC4 as CPU) */ + ucTC = TC4_INDEX; +#else + /* 2. Use TC0's resource to download image. + * Only TC0 is allowed because SDIO HW always reports + * MCU's TXQ_CNT at TXQ0_CNT in CR4 architecutre) + */ + ucTC = TC0_INDEX; +#endif + + /* 3. increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* 4. Setup common CMD Info Packet */ + prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prInitHifTxHeader->u2PQ_ID = INIT_CMD_PQ_ID; + prInitHifTxHeader->ucHeaderFormat = INIT_CMD_PACKET_TYPE_ID; + prInitHifTxHeader->ucPktFt = INIT_PKT_FT_CMD; + + prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_ACCESS_REG; + + prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = INIT_CMD_PACKET_TYPE_ID; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + /* 5. Setup CMD_ACCESS_REG */ + prInitCmdAccessReg = (P_INIT_CMD_ACCESS_REG) (prInitHifTxHeader->rInitWifiCmd.aucBuffer); + prInitCmdAccessReg->ucSetQuery = ucSetQuery; + prInitCmdAccessReg->u4Address = u4Addr; + prInitCmdAccessReg->u4Data = u4Data; + + /* 6. Send CMD_ACCESS_REG command */ + while (1) { + /* 6.1 Acquire TX Resource */ + if (nicTxAcquireResource + (prAdapter, ucTC, nicTxGetPageCount(prCmdInfo->u2InfoBufLen, TRUE), TRUE) + == 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"); + goto exit; + } + continue; + } + /* 6.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to transmit image download command\n"); + goto exit; + } + + break; + }; + + /* 7. Wait for INIT_EVENT_ID_CMD_RESULT */ + u4Status = wlanAccessRegisterStatus(prAdapter, ucCmdSeqNum, ucSetQuery, aucBuffer, sizeof(aucBuffer)); + if (ucSetQuery == 0) { + prInitHifRxHeader = (P_INIT_HIF_RX_HEADER_T)aucBuffer; + prInitEventAccessReg = (P_INIT_EVENT_ACCESS_REG)prInitHifRxHeader->rInitWifiEvent.aucBuffer; + + if (prInitEventAccessReg->u4Address != u4Addr) { + DBGLOG(INIT, ERROR, "Event reports address incorrect. 0x%08x, 0x%08x.\n", + u4Addr, prInitEventAccessReg->u4Address); + u4Status = WLAN_STATUS_FAILURE; + } + *pru4Result = prInitEventAccessReg->u4Data; + } + +exit: + /* 8. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to get the response of INIT_CMD_ACCESS_REG +* +* @param prAdapter Pointer to the Adapter structure. +* ucCmdSeqNum Sequence number of previous firmware scatter +* ucSetQuery Read or write +* prEvent the pointer of buffer to store the response +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanAccessRegisterStatus(IN P_ADAPTER_T prAdapter, IN UINT_8 ucCmdSeqNum, + IN UINT_8 ucSetQuery, IN PVOID prEvent, + IN UINT_32 u4EventLen) +{ + /* UINT_8 aucBuffer[sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_CMD_ACCESS_REG)]; */ + P_INIT_HIF_RX_HEADER_T prInitHifRxHeader; +/* P_INIT_EVENT_CMD_RESULT prEventCmdResult; +* P_INIT_CMD_ACCESS_REG prEventCmdAccessReg; +*/ + UINT_32 u4RxPktLength; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + UINT_8 ucPortIdx = IMG_DL_STATUS_PORT_IDX; + + ASSERT(prAdapter); + + do { + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + } else if (nicRxWaitResponse(prAdapter, + ucPortIdx, + prEvent, + u4EventLen, &u4RxPktLength) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + } else { + prInitHifRxHeader = (P_INIT_HIF_RX_HEADER_T) prEvent; + + /* EID / SeqNum check */ + if (((prInitHifRxHeader->rInitWifiEvent.ucEID != INIT_EVENT_ID_CMD_RESULT) + && (ucSetQuery == 1)) || + ((prInitHifRxHeader->rInitWifiEvent.ucEID != INIT_EVENT_ID_ACCESS_REG) + && (ucSetQuery == 0))) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "wlanAccessRegisterStatus: incorrect ucEID. ucSetQuery = 0x%x\n", ucSetQuery); + } else if (prInitHifRxHeader->rInitWifiEvent.ucSeqNum != ucCmdSeqNum) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, + "wlanAccessRegisterStatus: incorrect ucCmdSeqNum. = 0x%x\n", ucCmdSeqNum); + } else { + } + } + } while (FALSE); + + return u4Status; +} +/*----------------------------------------------------------------------------*/ +/*! +* @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, IN UINT_32 u4Timeout) +{ + PFN_OID_HANDLER_FUNC *apfnOidHandlerWOTimeoutCheck; + UINT_32 i; + UINT_32 u4NumOfElem; + UINT_32 u4OidTimeout; + + apfnOidHandlerWOTimeoutCheck = apfnOidWOTimeoutCheck; + u4NumOfElem = sizeof(apfnOidWOTimeoutCheck) / sizeof(PFN_OID_HANDLER_FUNC); + + for (i = 0; i < u4NumOfElem; i++) { + if (apfnOidHandlerWOTimeoutCheck[i] == pfnOidHandler) + return FALSE; + } + + /* Decrease OID timeout threshold if chip NoAck/resetting */ + if (wlanIsChipNoAck(prAdapter)) { + u4OidTimeout = WLAN_OID_TIMEOUT_THRESHOLD_IN_RESETTING; + DBGLOG(INIT, INFO, "Decrease OID timeout to %ums due to NoACK/CHIP-RESET\n", u4OidTimeout); + } else { + u4OidTimeout = u4Timeout; + } + + /* Set OID timer for timeout check */ + cnmTimerStartTimer(prAdapter, &(prAdapter->rOidTimeoutTimer), u4OidTimeout); + + 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 override network address +* if NVRAM has a valid value +* +* @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_32 u4SysTime; + + DEBUGFUNC("wlanUpdateNetworkAddress"); + + ASSERT(prAdapter); + + if (kalRetrieveNetworkAddress(prAdapter->prGlueInfo, &rMacAddr) == FALSE || IS_BMCAST_MAC_ADDR(rMacAddr) + || EQUAL_MAC_ADDR(aucZeroMacAddr, rMacAddr)) { + /* eFUSE has a valid address, don't do anything */ + if (prAdapter->fgIsEmbbededMacAddrValid == TRUE) { +#if CFG_SHOW_MACADDR_SOURCE + DBGLOG(INIT, INFO, "Using embedded MAC address"); +#endif + return WLAN_STATUS_SUCCESS; + } +#if CFG_SHOW_MACADDR_SOURCE + DBGLOG(INIT, 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 + } + + COPY_MAC_ADDR(prAdapter->rWifiVar.aucMacAddress, rMacAddr); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to update basic configuration into 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 wlanUpdateBasicConfig(IN P_ADAPTER_T prAdapter) +{ + UINT_8 ucCmdSeqNum; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_CMD_BASIC_CONFIG_T prCmdBasicConfig; + P_PSE_CMD_HDR_T prPseCmdHdr; + WLAN_STATUS rResult; + P_WIFI_VAR_T prWifiVar = &prAdapter->rWifiVar; + + DEBUGFUNC("wlanUpdateBasicConfig"); + + ASSERT(prAdapter); + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE + sizeof(CMD_BASIC_CONFIG_T)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_BUILD_CONNECTION cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_BASIC_CONFIG_T); + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->pfCmdTimeoutHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_BASIC_CONFIG; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(CMD_BASIC_CONFIG_T); + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prPseCmdHdr = (P_PSE_CMD_HDR_T) (prCmdInfo->pucInfoBuffer); + prPseCmdHdr->u2Qidx = TXD_Q_IDX_MCU_RQ0; + prPseCmdHdr->u2Pidx = TXD_P_IDX_MCU; + prPseCmdHdr->u2Hf = TXD_HF_CMD; + prPseCmdHdr->u2Ft = TXD_FT_LONG_FORMAT; + prPseCmdHdr->u2PktFt = TXD_PKT_FT_CMD; + + prWifiCmd->u2Length = prWifiCmd->u2TxByteCount - sizeof(PSE_CMD_HDR_T); + + /* configure CMD_BASIC_CONFIG */ + + prCmdBasicConfig = (P_CMD_BASIC_CONFIG_T) (prWifiCmd->aucBuffer); + kalMemZero(prCmdBasicConfig, sizeof(CMD_BASIC_CONFIG_T)); + prCmdBasicConfig->ucNative80211 = 0; + prCmdBasicConfig->rCsumOffload.u2RxChecksum = 0; + prCmdBasicConfig->rCsumOffload.u2TxChecksum = 0; + prCmdBasicConfig->ucCtrlFlagAssertPath = prWifiVar->ucCtrlFlagAssertPath; + prCmdBasicConfig->ucCtrlFlagDebugLevel = prWifiVar->ucCtrlFlagDebugLevel; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + if (prAdapter->fgIsSupportCsumOffload) { + 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 + + rResult = wlanSendCommand(prAdapter, prCmdInfo); + + if (rResult != WLAN_STATUS_SUCCESS) { + kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + return WLAN_STATUS_PENDING; + } + 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; +} + +BOOLEAN wlanProcessTxFrame(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prPacket) +{ + UINT_32 u4SysTime; + UINT_8 ucMacHeaderLen; + TX_PACKET_INFO rTxPacketInfo; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + ASSERT(prPacket); + prChipInfo = prAdapter->chip_info; + + if (kalQoSFrameClassifierAndPacketInfo(prAdapter->prGlueInfo, prPacket, &rTxPacketInfo)) { + + /* Save the value of Priority Parameter */ + GLUE_SET_PKT_TID(prPacket, rTxPacketInfo.ucPriorityParam); + +#if 1 + if (rTxPacketInfo.u2Flag) { + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_1X)) { + P_STA_RECORD_T prStaRec; + + DBGLOG(RSN, INFO, "T1X len=%d\n", rTxPacketInfo.u4PacketLen); + + prStaRec = cnmGetStaRecByAddress(prAdapter, + GLUE_GET_PKT_BSS_IDX(prPacket), + rTxPacketInfo.aucEthDestAddr); + + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_1X); +/* +* if (secIsProtected1xFrame(prAdapter, prStaRec) && !kalIs24Of4Packet(prPacket)) +* GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_PROTECTED_1X); +*/ + } + + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_NON_PROTECTED_1X)) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_NON_PROTECTED_1X); + + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_802_3)) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_802_3); + + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_VLAN_EXIST) + && FEAT_SUP_LLC_VLAN_TX(prChipInfo)) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_VLAN_EXIST); + + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_DHCP)) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_DHCP); + + if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_ARP)) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_ARP); + } +#else + if (rTxPacketInfo.fgIs1X) { + P_STA_RECORD_T prStaRec; + + DBGLOG(RSN, INFO, "T1X len=%d\n", rTxPacketInfo.u4PacketLen); + + prStaRec = cnmGetStaRecByAddress(prAdapter, + GLUE_GET_PKT_BSS_IDX(prPacket), rTxPacketInfo.aucEthDestAddr); + + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_1X); + + if (secIsProtected1xFrame(prAdapter, prStaRec)) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_PROTECTED_1X); + } + + if (rTxPacketInfo.fgIs802_3) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_802_3); + + if (rTxPacketInfo.fgIsVlanExists) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_VLAN_EXIST); + + if (rTxPacketInfo.fgIsDhcp) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_DHCP); + + if (rTxPacketInfo.fgIsArp) + GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_ARP); +#endif + + ucMacHeaderLen = ETHER_HEADER_LEN; + + /* 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) rTxPacketInfo.u4PacketLen); + + /* Save the value of Arrival Time */ + u4SysTime = (OS_SYSTIME) kalGetTimeTick(); + GLUE_SET_PKT_ARRIVAL_TIME(prPacket, u4SysTime); + + return TRUE; + } + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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) +{ + P_CMD_INFO_T prCmdInfo; + P_STA_RECORD_T prStaRec; + UINT_8 ucBssIndex; + UINT_32 u4PacketLen; + UINT_8 aucEthDestAddr[PARAM_MAC_ADDR_LEN]; + P_MSDU_INFO_T prMsduInfo; + UINT_8 ucStaRecIndex; + + ASSERT(prAdapter); + ASSERT(prPacket); + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, 0); + + /* Get MSDU_INFO for TxDone */ + prMsduInfo = cnmPktAlloc(prAdapter, 0); + + u4PacketLen = (UINT_32) GLUE_GET_PKT_FRAME_LEN(prPacket); + + if (prCmdInfo && prMsduInfo) { + ucBssIndex = GLUE_GET_PKT_BSS_IDX(prPacket); + + kalGetEthDestAddr(prAdapter->prGlueInfo, prPacket, aucEthDestAddr); + + prStaRec = cnmGetStaRecByAddress(prAdapter, ucBssIndex, aucEthDestAddr); + + prCmdInfo->eCmdType = COMMAND_TYPE_SECURITY_FRAME; + prCmdInfo->u2InfoBufLen = (UINT_16) u4PacketLen; + prCmdInfo->prPacket = prPacket; + prCmdInfo->prMsduInfo = prMsduInfo; + prCmdInfo->pfCmdDoneHandler = wlanSecurityFrameTxDone; + prCmdInfo->pfCmdTimeoutHandler = wlanSecurityFrameTxTimeout; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + + if (prStaRec) + ucStaRecIndex = prStaRec->ucIndex; + else + ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; + + /* Fill-up MSDU_INFO */ + nicTxSetDataPacket(prAdapter, prMsduInfo, ucBssIndex, + ucStaRecIndex, 0, u4PacketLen, nicTxDummyTxDone, + MSDU_RATE_MODE_AUTO, TX_PACKET_OS, 0, FALSE, TRUE); + + prMsduInfo->prPacket = prPacket; + /* No Tx descriptor template for MMPDU */ + prMsduInfo->fgIsTXDTemplateValid = FALSE; + + if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_PROTECTED_1X)) + nicTxConfigPktOption(prMsduInfo, MSDU_OPT_PROTECTED_FRAME, TRUE); +#if CFG_SUPPORT_MULTITHREAD + nicTxComposeSecurityFrameDesc(prAdapter, prCmdInfo, prMsduInfo->aucTxDescBuffer, NULL); +#endif + + kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + GLUE_SET_EVENT(prAdapter->prGlueInfo); + + return TRUE; + } + DBGLOG(RSN, INFO, "Failed to alloc CMD/MGMT INFO for 1X frame!!\n"); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + cnmPktFree(prAdapter, prMsduInfo); + + + 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) +{ + P_MSDU_INFO_T prMsduInfo = prCmdInfo->prMsduInfo; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex)->eNetworkType == + NETWORK_TYPE_AIS && prAdapter->rWifiVar.rAisSpecificBssInfo.fgCounterMeasure) { + P_STA_RECORD_T prSta = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucBssIndex); + + if (prSta) { + kalMsleep(10); + if (authSendDeauthFrame(prAdapter, + GET_BSS_INFO_BY_INDEX(prAdapter, + prMsduInfo->ucBssIndex), prSta, + (P_SW_RFB_T) NULL, REASON_CODE_MIC_FAILURE, (PFN_TX_DONE_HANDLER) NULL + /* secFsmEventDeauthTxDone left upper layer handle the 60 timer */ + ) != WLAN_STATUS_SUCCESS) { + ASSERT(FALSE); + } + /* 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; + } + + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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 - + (((ULONG) pucIEPtr) + u4IELength - + ((ULONG) (&(prAdapter->rWlanInfo.aucScanIEBuf[0])))); + + kalMemCopy(pucIEPtr, (PUINT_8) (((ULONG) pucIEPtr) + u4IELength), u4IEMoveLength); + + prAdapter->rWlanInfo.u4ScanIEBufferUsage -= u4IELength; + + /* correction of pointers to IE buffer */ + for (j = 0; j < prAdapter->rWlanInfo.u4ScanResultNum; j++) { + if (prAdapter->rWlanInfo.apucScanResultIEs[j] > pucIEPtr) { + prAdapter->rWlanInfo.apucScanResultIEs[j] = + (PUINT_8) ((ULONG) (prAdapter->rWlanInfo.apucScanResultIEs[j]) - + u4IELength); + } + } + } + } + + i++; + } + +} + +#if CFG_TEST_WIFI_DIRECT_GO +VOID wlanEnableP2pFunction(IN P_ADAPTER_T prAdapter) +{ +#if 0 + P_MSG_P2P_FUNCTION_SWITCH_T prMsgFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) NULL; + + prMsgFuncSwitch = + (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_FUNCTION_SWITCH_T)); + if (!prMsgFuncSwitch) { + ASSERT(FALSE); + return; + } + + prMsgFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; + prMsgFuncSwitch->fgIsFuncOn = TRUE; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgFuncSwitch, MSG_SEND_METHOD_BUF); +#endif + +} + +VOID wlanEnableATGO(IN P_ADAPTER_T prAdapter) +{ + + P_MSG_P2P_CONNECTION_REQUEST_T prMsgConnReq = (P_MSG_P2P_CONNECTION_REQUEST_T) NULL; + UINT_8 aucTargetDeviceID[MAC_ADDR_LEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + + prMsgConnReq = + (P_MSG_P2P_CONNECTION_REQUEST_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_CONNECTION_REQUEST_T)); + if (!prMsgConnReq) { + ASSERT(FALSE); + return; + } + + prMsgConnReq->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_REQ; + + /*=====Param Modified for test=====*/ + COPY_MAC_ADDR(prMsgConnReq->aucDeviceID, aucTargetDeviceID); + prMsgConnReq->fgIsTobeGO = TRUE; + prMsgConnReq->fgIsPersistentGroup = FALSE; + + /*=====Param Modified for test=====*/ + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgConnReq, MSG_SEND_METHOD_BUF); + +} +#endif + +VOID wlanPrintVersion(IN P_ADAPTER_T prAdapter) +{ + P_WIFI_VER_INFO_T prVerInfo = &prAdapter->rVerInfo; + tailer_format_t *prTailer; + UINT_8 aucBuf[32], aucDate[32]; + + kalMemCopy(aucBuf, prVerInfo->aucFwBranchInfo, 4); + aucBuf[4] = '\0'; + DBGLOG(SW4, INFO, "N9 FW version %s-%u.%u.%u[DEC] (%s)\n", + aucBuf, (UINT_32)(prVerInfo->u2FwOwnVersion >> 8), + (UINT_32)(prVerInfo->u2FwOwnVersion & BITS(0, 7)), + prVerInfo->ucFwBuildNumber, prVerInfo->aucFwDateCode); +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + if (prVerInfo->fgIsN9CompressedFW) { + tailer_format_t_2 *prTailer; + + prTailer = &prVerInfo->rN9Compressedtailer; + kalMemCopy(aucBuf, prTailer->ram_version, 10); + aucBuf[10] = '\0'; + DBGLOG(SW4, INFO, "N9 tailer version %s (%s) info %u:E%u\n", + aucBuf, prTailer->ram_built_date, prTailer->chip_info, + prTailer->eco_code + 1); + } else { + prTailer = &prVerInfo->rN9tailer; + kalMemCopy(aucBuf, prTailer->ram_version, 10); + aucBuf[10] = '\0'; + DBGLOG(SW4, INFO, "N9 tailer version %s (%s) info %u:E%u\n", + aucBuf, prTailer->ram_built_date, prTailer->chip_info, + prTailer->eco_code + 1); + } + if (prVerInfo->fgIsCR4CompressedFW) { + tailer_format_t_2 *prTailer; + + prTailer = &prVerInfo->rCR4Compressedtailer; + kalMemCopy(aucBuf, prTailer->ram_version, 10); + aucBuf[10] = '\0'; + DBGLOG(SW4, INFO, "CR4 tailer version %s (%s) info %u:E%u\n", + aucBuf, prTailer->ram_built_date, prTailer->chip_info, + prTailer->eco_code + 1); + } else { + prTailer = &prVerInfo->rCR4tailer; + kalMemCopy(aucBuf, prTailer->ram_version, 10); + aucBuf[10] = '\0'; + DBGLOG(SW4, INFO, "CR4 tailer version %s (%s) info %u:E%u\n", + aucBuf, prTailer->ram_built_date, prTailer->chip_info, + prTailer->eco_code + 1); + } +#else + prTailer = &prVerInfo->rN9tailer; + kalMemCopy(aucBuf, prTailer->ram_version, 10); + aucBuf[10] = '\0'; + DBGLOG(SW4, INFO, "N9 tailer version %s (%s) info %u:E%u\n", + aucBuf, prTailer->ram_built_date, prTailer->chip_info, + prTailer->eco_code + 1); + + prTailer = &prVerInfo->rCR4tailer; + kalMemCopy(aucBuf, prTailer->ram_version, 10); + aucBuf[10] = '\0'; + DBGLOG(SW4, INFO, "CR4 tailer version %s (%s) info %u:E%u\n", + aucBuf, prTailer->ram_built_date, prTailer->chip_info, + prTailer->eco_code + 1); +#endif + if (!prVerInfo->fgPatchIsDlByDrv) { + DBGLOG(SW4, INFO, "Patch is not downloaded by driver, read patch binary\n"); + wlanGetPatchInfo(prAdapter); + } + + kalStrnCpy(aucBuf, prVerInfo->rPatchHeader.aucPlatform, 4); + aucBuf[4] = '\0'; + kalStrnCpy(aucDate, prVerInfo->rPatchHeader.aucBuildDate, 16); + aucDate[16] = '\0'; + DBGLOG(SW4, INFO, "Patch platform %s version 0x%04X %s\n", + aucBuf, prVerInfo->rPatchHeader.u4PatchVersion, aucDate); + + DBGLOG(SW4, INFO, "Drv version %u.%u[DEC]\n", + (UINT_32)(prVerInfo->u2FwPeerVersion >> 8), + (UINT_32)(prVerInfo->u2FwPeerVersion & BITS(0, 7))); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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 aucZeroMacAddr[] = NULL_MAC_ADDR; + 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_T)]; + P_HW_MAC_RX_DESC_T prRxStatus; + P_WIFI_EVENT_T prEvent; + P_EVENT_NIC_CAPABILITY_T prEventNicCapability; + P_PSE_CMD_HDR_T prPseCmdHdr; + + ASSERT(prAdapter); + + DEBUGFUNC("wlanQueryNicCapability"); + + /* 1. Allocate CMD Info Packet and its Buffer */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE + sizeof(EVENT_NIC_CAPABILITY_T)); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_BUILD_CONNECTION cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(EVENT_NIC_CAPABILITY_T); + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_GET_NIC_CAPABILITY; + prCmdInfo->fgSetQuery = FALSE; + prCmdInfo->fgNeedResp = TRUE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = 0; + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prPseCmdHdr = (P_PSE_CMD_HDR_T) (prCmdInfo->pucInfoBuffer); + prPseCmdHdr->u2Qidx = TXD_Q_IDX_MCU_RQ0; + prPseCmdHdr->u2Pidx = TXD_P_IDX_MCU; + prPseCmdHdr->u2Hf = TXD_HF_CMD; + prPseCmdHdr->u2Ft = TXD_FT_LONG_FORMAT; + prPseCmdHdr->u2PktFt = TXD_PKT_FT_CMD; + + prWifiCmd->u2Length = prWifiCmd->u2TxByteCount - sizeof(PSE_CMD_HDR_T); + + wlanSendCommand(prAdapter, prCmdInfo); + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + while (TRUE) { + if (nicRxWaitResponse(prAdapter, 1, aucBuffer, + sizeof(WIFI_EVENT_T) + sizeof(EVENT_NIC_CAPABILITY_T), &u4RxPktLength) != WLAN_STATUS_SUCCESS) { + + DBGLOG(INIT, WARN, "%s: wait for event failed!\n", __func__); + return WLAN_STATUS_FAILURE; + } + /* header checking .. */ + prRxStatus = (P_HW_MAC_RX_DESC_T) aucBuffer; + if (prRxStatus->u2PktTYpe != RXM_RXD_PKT_TYPE_SW_EVENT) { + DBGLOG(INIT, WARN, "%s: skip unexpected Rx pkt type[0x%04x]\n", __func__, + prRxStatus->u2PktTYpe); + continue; + } + + prEvent = (P_WIFI_EVENT_T) aucBuffer; + if (prEvent->ucEID != EVENT_ID_NIC_CAPABILITY) { + DBGLOG(INIT, WARN, "%s: skip unexpected event ID[0x%02x]\n", __func__, prEvent->ucEID); + continue; + } else { + break; + } + } + + prEventNicCapability = (P_EVENT_NIC_CAPABILITY_T) (prEvent->aucBuffer); + + prAdapter->rVerInfo.u2FwProductID = prEventNicCapability->u2ProductID; + kalMemCopy(prAdapter->rVerInfo.aucFwBranchInfo, prEventNicCapability->aucBranchInfo, 4); + prAdapter->rVerInfo.u2FwOwnVersion = prEventNicCapability->u2FwVersion; + prAdapter->rVerInfo.ucFwBuildNumber = prEventNicCapability->ucFwBuildNumber; + kalMemCopy(prAdapter->rVerInfo.aucFwDateCode, prEventNicCapability->aucDateCode, 16); + prAdapter->rVerInfo.u2FwPeerVersion = prEventNicCapability->u2DriverVersion; + prAdapter->fgIsHw5GBandDisabled = (BOOLEAN) prEventNicCapability->ucHw5GBandDisabled; + prAdapter->fgIsEepromUsed = (BOOLEAN) prEventNicCapability->ucEepromUsed; + prAdapter->fgIsEmbbededMacAddrValid = (BOOLEAN) + (!IS_BMCAST_MAC_ADDR(prEventNicCapability->aucMacAddr) && + !EQUAL_MAC_ADDR(aucZeroMacAddr, prEventNicCapability->aucMacAddr)); + + COPY_MAC_ADDR(prAdapter->rWifiVar.aucPermanentAddress, prEventNicCapability->aucMacAddr); + COPY_MAC_ADDR(prAdapter->rWifiVar.aucMacAddress, prEventNicCapability->aucMacAddr); + + prAdapter->rWifiVar.ucStaVht &= (!(prEventNicCapability->ucHwNotSupportAC)); + prAdapter->rWifiVar.ucApVht &= (!(prEventNicCapability->ucHwNotSupportAC)); + prAdapter->rWifiVar.ucP2pGoVht &= (!(prEventNicCapability->ucHwNotSupportAC)); + prAdapter->rWifiVar.ucP2pGcVht &= (!(prEventNicCapability->ucHwNotSupportAC)); + + prAdapter->rWifiVar.ucStaVhtBfee &= (!(prEventNicCapability->ucHwNotSupportAC)); + prAdapter->rWifiVar.ucStaVhtMuBfee &= (!(prEventNicCapability->ucHwNotSupportAC)); + prAdapter->rWifiVar.ucStaVhtBfer &= (!(prEventNicCapability->ucHwNotSupportAC)); + + prAdapter->rWifiVar.ucVhtAmsduInAmpduRx &= (!(prEventNicCapability->ucHwNotSupportAC)); + prAdapter->rWifiVar.ucVhtAmsduInAmpduTx &= (!(prEventNicCapability->ucHwNotSupportAC)); + + if (prEventNicCapability->ucHwNotSupportAC) { + prAdapter->rWifiVar.ucStaBandwidth = MAX_BW_40MHZ; + prAdapter->rWifiVar.ucSta5gBandwidth = MAX_BW_40MHZ; + prAdapter->rWifiVar.ucP2p5gBandwidth = MAX_BW_40MHZ; + prAdapter->rWifiVar.ucApBandwidth = MAX_BW_40MHZ; + prAdapter->rWifiVar.ucAp5gBandwidth = MAX_BW_40MHZ; +#if CFG_SUPPORT_MTK_SYNERGY + /* Disable the 2.4G 256QAM feature bit if N only chip*/ + prAdapter->rWifiVar.aucMtkFeature[0] &= + ~(MTK_SYNERGY_CAP_SUPPORT_24G_MCS89); + DBGLOG(INIT, WARN, + "Disable 2.4G 256QAM support if N only chip\n"); +#endif + } + + prAdapter->u4FwCompileFlag0 = prEventNicCapability->u4CompileFlag0; + prAdapter->u4FwCompileFlag1 = prEventNicCapability->u4CompileFlag1; + prAdapter->u4FwFeatureFlag0 = prEventNicCapability->u4FeatureFlag0; + prAdapter->u4FwFeatureFlag1 = prEventNicCapability->u4FeatureFlag1; + + if (prEventNicCapability->ucHwSetNss1x1) + prAdapter->rWifiVar.ucNSS = 1; + +#if CFG_SUPPORT_DBDC + if (prEventNicCapability->ucHwNotSupportDBDC) + prAdapter->rWifiVar.ucDbdcMode = DBDC_MODE_DISABLED; +#endif + +#if CFG_ENABLE_CAL_LOG + DBGLOG(INIT, TRACE, "RF CAL FAIL = (%d),BB CAL FAIL = (%d)\n", + prEventNicCapability->ucRfCalFail, prEventNicCapability->ucBbCalFail); +#endif + +#if CFG_SISO_SW_DEVELOP + if ((!prEventNicCapability->ucHwNotSupportDBDC) && + (!prEventNicCapability->ucHwSetNss1x1) && + (!prEventNicCapability->ucHwWiFiZeroOnly)) { + prAdapter->rWifiFemCfg.u2WifiPath = + (WLAN_FLAG_2G4_WF0 | WLAN_FLAG_5G_WF0 | WLAN_FLAG_2G4_WF1 | WLAN_FLAG_5G_WF1); + } else if ((!prEventNicCapability->ucHwNotSupportDBDC) && + (prEventNicCapability->ucHwSetNss1x1) && + (!prEventNicCapability->ucHwWiFiZeroOnly)) { + prAdapter->rWifiFemCfg.u2WifiPath = + (WLAN_FLAG_5G_WF0 | WLAN_FLAG_2G4_WF1); + } else if ((prEventNicCapability->ucHwNotSupportDBDC) && + (prEventNicCapability->ucHwSetNss1x1) && + (!prEventNicCapability->ucHwWiFiZeroOnly)) { + prAdapter->rWifiFemCfg.u2WifiPath = + (WLAN_FLAG_5G_WF0 | WLAN_FLAG_2G4_WF1); + } else if ((prEventNicCapability->ucHwNotSupportDBDC) && + (!prEventNicCapability->ucHwSetNss1x1) && + (!prEventNicCapability->ucHwWiFiZeroOnly)) { + prAdapter->rWifiFemCfg.u2WifiPath = + (WLAN_FLAG_2G4_WF0 | WLAN_FLAG_5G_WF0 | WLAN_FLAG_2G4_WF1 | WLAN_FLAG_5G_WF1); + } else if ((prEventNicCapability->ucHwNotSupportDBDC) && + (prEventNicCapability->ucHwSetNss1x1) && + (prEventNicCapability->ucHwWiFiZeroOnly)) { + prAdapter->rWifiFemCfg.u2WifiPath = + (WLAN_FLAG_2G4_WF0 | WLAN_FLAG_5G_WF0); + } else { + DBGLOG(INIT, ERROR, "ucHwNotSupportDBDC = %d\n", prEventNicCapability->ucHwNotSupportDBDC); + DBGLOG(INIT, ERROR, "ucHwSetNss1x1 = %d\n", prEventNicCapability->ucHwSetNss1x1); + DBGLOG(INIT, ERROR, "ucHwWiFiZeroOnly = %d\n", prEventNicCapability->ucHwWiFiZeroOnly); + ASSERT(0); + } + + DBGLOG(INIT, INFO, "wifi path = %8x\n", prAdapter->rWifiFemCfg.u2WifiPath); +#endif + + return WLAN_STATUS_SUCCESS; +} + +#if TXPWR_USE_PDSLOPE + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanQueryPdMcr(IN P_ADAPTER_T prAdapter, P_PARAM_MCR_RW_STRUCT_T prMcrRdInfo) +{ + UINT_8 ucCmdSeqNum; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_32 u4RxPktLength; + UINT_8 aucBuffer[sizeof(WIFI_EVENT_T) + sizeof(CMD_ACCESS_REG)]; + P_HW_MAC_RX_DESC_T prRxStatus; + 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->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(CMD_ACCESS_REG); + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + 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 .. */ + prRxStatus = (P_HW_MAC_RX_DESC_T) aucBuffer; + if (prRxStatus->u2PktTYpe != RXM_RXD_PKT_TYPE_SW_EVENT) + return WLAN_STATUS_FAILURE; + + prEvent = (P_WIFI_EVENT_T) aucBuffer; + + if (prEvent->ucEID != EVENT_ID_ACCESS_REG) + return WLAN_STATUS_FAILURE; + + prCmdMcrQuery = (P_CMD_ACCESS_REG) (prEvent->aucBuffer); + prMcrRdInfo->u4McrOffset = prCmdMcrQuery->u4Address; + prMcrRdInfo->u4McrData = prCmdMcrQuery->u4Data; + + return WLAN_STATUS_SUCCESS; +} + +static INT_32 wlanIntRound(INT_32 au4Input) +{ + + if (au4Input >= 0) { + if ((au4Input % 10) == 5) { + au4Input = au4Input + 5; + return au4Input; + } + } + + if (au4Input < 0) { + if ((au4Input % 10) == -5) { + au4Input = au4Input - 5; + return au4Input; + } + } + + return au4Input; +} + +static INT_32 wlanCal6628EfuseForm(IN P_ADAPTER_T prAdapter, INT_32 au4Input) +{ + + PARAM_MCR_RW_STRUCT_T rMcrRdInfo; + INT_32 au4PdSlope, au4TxPwrOffset, au4TxPwrOffset_Round; + INT_8 auTxPwrOffset_Round; + + rMcrRdInfo.u4McrOffset = 0x60205c68; + rMcrRdInfo.u4McrData = 0; + au4TxPwrOffset = au4Input; + wlanQueryPdMcr(prAdapter, &rMcrRdInfo); + + au4PdSlope = (rMcrRdInfo.u4McrData) & BITS(0, 6); + au4TxPwrOffset_Round = wlanIntRound((au4TxPwrOffset * au4PdSlope)) / 10; + + au4TxPwrOffset_Round = -au4TxPwrOffset_Round; + + if (au4TxPwrOffset_Round < -128) + au4TxPwrOffset_Round = 128; + else if (au4TxPwrOffset_Round < 0) + au4TxPwrOffset_Round += 256; + else if (au4TxPwrOffset_Round > 127) + au4TxPwrOffset_Round = 127; + + auTxPwrOffset_Round = (UINT_8) au4TxPwrOffset_Round; + + return au4TxPwrOffset_Round; +} + +#endif + +#if CFG_SUPPORT_NVRAM_5G +WLAN_STATUS wlanLoadManufactureData_5G(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo) +{ + + P_BANDEDGE_5G_T pr5GBandEdge; + + ASSERT(prAdapter); + + pr5GBandEdge = &prRegInfo->prOldEfuseMapping->r5GBandEdgePwr; + + /* 1. set band edge tx power if available */ + if (pr5GBandEdge->uc5GBandEdgePwrUsed != 0) { + CMD_EDGE_TXPWR_LIMIT_T rCmdEdgeTxPwrLimit; + + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrCCK = 0; + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM20 = pr5GBandEdge->c5GBandEdgeMaxPwrOFDM20; + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM40 = pr5GBandEdge->c5GBandEdgeMaxPwrOFDM40; + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM80 = pr5GBandEdge->c5GBandEdgeMaxPwrOFDM80; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_EDGE_TXPWR_LIMIT_5G, + TRUE, + FALSE, + FALSE, + NULL, + NULL, sizeof(CMD_EDGE_TXPWR_LIMIT_T), (PUINT_8) &rCmdEdgeTxPwrLimit, NULL, 0); + + /* dumpMemory8(&rCmdEdgeTxPwrLimit,4); */ + } + + DEBUGFUNC("wlanLoadManufactureData_5G"); + + /*2.set channel offset for 8 sub-band */ + if (prRegInfo->prOldEfuseMapping->uc5GChannelOffsetVaild) { + CMD_POWER_OFFSET_T rCmdPowerOffset; + UINT_8 i; + + rCmdPowerOffset.ucBand = BAND_5G; + for (i = 0; i < MAX_SUBBAND_NUM_5G; i++) + rCmdPowerOffset.ucSubBandOffset[i] = prRegInfo->prOldEfuseMapping->auc5GChOffset[i]; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_CHANNEL_PWR_OFFSET, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(rCmdPowerOffset), (PUINT_8) &rCmdPowerOffset, NULL, 0); + /* dumpMemory8(&rCmdPowerOffset,9); */ + } + + /*3.set 5G AC power */ + if (prRegInfo->prOldEfuseMapping->uc11AcTxPwrValid) { + + CMD_TX_AC_PWR_T rCmdAcPwr; + + kalMemCopy(&rCmdAcPwr.rAcPwr, &prRegInfo->prOldEfuseMapping->r11AcTxPwr, sizeof(AC_PWR_SETTING_STRUCT)); + rCmdAcPwr.ucBand = BAND_5G; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_80211AC_TX_PWR, + TRUE, + FALSE, FALSE, NULL, NULL, sizeof(CMD_TX_AC_PWR_T), (PUINT_8) &rCmdAcPwr, NULL, 0); + /* dumpMemory8(&rCmdAcPwr,9); */ + } + + return WLAN_STATUS_SUCCESS; +} +#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 + CMD_NVRAM_SETTING_T rCmdNvramSettings; + + 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 (prAdapter->rVerInfo.u2Part1CfgPeerVersion > CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part2CfgPeerVersion > CFG_DRV_OWN_VERSION + || 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))); + } + } + + /* Todo : Temp Open 20150806 Sam */ + prRegInfo->ucEnable5GBand = 1; + prRegInfo->ucSupport5GBand = 1; + + /* 3. Check if needs to support 5GHz */ + if (prRegInfo->ucEnable5GBand) { +#if CFG_SUPPORT_NVRAM_5G + wlanLoadManufactureData_5G(prAdapter, prRegInfo); +#endif + /* 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 CFG_SUPPORT_NVRAM_5G + /* If NvRAM read failed, this pointer will be NULL */ + if (prRegInfo->prOldEfuseMapping) { + /*2.set channel offset for 3 sub-band */ + if (prRegInfo->prOldEfuseMapping->ucChannelOffsetVaild) { + CMD_POWER_OFFSET_T rCmdPowerOffset; + UINT_8 i; + + rCmdPowerOffset.ucBand = BAND_2G4; + for (i = 0; i < 3; i++) + rCmdPowerOffset.ucSubBandOffset[i] = prRegInfo->prOldEfuseMapping->aucChOffset[i]; + rCmdPowerOffset.ucSubBandOffset[i] = prRegInfo->prOldEfuseMapping->acAllChannelOffset; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_CHANNEL_PWR_OFFSET, + TRUE, + FALSE, + FALSE, + NULL, NULL, sizeof(rCmdPowerOffset), (PUINT_8) &rCmdPowerOffset, NULL, 0); + /* dumpMemory8(&rCmdPowerOffset,9); */ + } + } +#else + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_PHY_PARAM, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_PHY_PARAM_T), (PUINT_8) (prRegInfo->aucEFUSE), NULL, 0); + +#endif + /*RSSI path compasation */ + if (prRegInfo->ucRssiPathCompasationUsed) { + CMD_RSSI_PATH_COMPASATION_T rCmdRssiPathCompasation; + + rCmdRssiPathCompasation.c2GRssiCompensation = prRegInfo->rRssiPathCompasation.c2GRssiCompensation; + rCmdRssiPathCompasation.c5GRssiCompensation = prRegInfo->rRssiPathCompasation.c5GRssiCompensation; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_PATH_COMPASATION, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(rCmdRssiPathCompasation), (PUINT_8) &rCmdRssiPathCompasation, 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); + + /* Update supported channel list in channel table */ + wlanUpdateChannelTable(prAdapter->prGlueInfo); + + + /* 7. set band edge tx power if available */ + if (prRegInfo->fg2G4BandEdgePwrUsed) { + CMD_EDGE_TXPWR_LIMIT_T rCmdEdgeTxPwrLimit; + + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrCCK = prRegInfo->cBandEdgeMaxPwrCCK; + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM20 = prRegInfo->cBandEdgeMaxPwrOFDM20; + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM40 = prRegInfo->cBandEdgeMaxPwrOFDM40; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_EDGE_TXPWR_LIMIT, + TRUE, + FALSE, + FALSE, + NULL, + NULL, sizeof(CMD_EDGE_TXPWR_LIMIT_T), (PUINT_8) &rCmdEdgeTxPwrLimit, NULL, 0); + } + /*8. Set 2.4G AC power */ + if (prRegInfo->prOldEfuseMapping && prRegInfo->prOldEfuseMapping->uc11AcTxPwrValid2G) { + + CMD_TX_AC_PWR_T rCmdAcPwr; + + kalMemCopy(&rCmdAcPwr.rAcPwr, &prRegInfo->prOldEfuseMapping->r11AcTxPwr2G, + sizeof(AC_PWR_SETTING_STRUCT)); + rCmdAcPwr.ucBand = BAND_2G4; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_80211AC_TX_PWR, + TRUE, + FALSE, FALSE, NULL, NULL, sizeof(CMD_TX_AC_PWR_T), (PUINT_8) &rCmdAcPwr, NULL, 0); + /* dumpMemory8(&rCmdAcPwr,9); */ + } + /* 9. Send the full Parameters of NVRAM to FW */ + + kalMemCopy(&rCmdNvramSettings.rNvramSettings, + &prRegInfo->prNvramSettings->u2Part1OwnVersion, sizeof(WIFI_CFG_PARAM_STRUCT)); + ASSERT(sizeof(WIFI_CFG_PARAM_STRUCT) == 512); + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_NVRAM_SETTINGS, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(rCmdNvramSettings), (PUINT_8) &rCmdNvramSettings, 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; + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + + prMsduInfo = cnmPktAlloc(prAdapter, 0); + + if (!prMsduInfo) + return WLAN_STATUS_RESOURCES; + + if (nicTxFillMsduInfo(prAdapter, prMsduInfo, prNativePacket)) { + /* prMsduInfo->eSrc = TX_PACKET_OS; */ + + /* Tx profiling */ + wlanTxProfilingTagMsdu(prAdapter, prMsduInfo, TX_PROF_TAG_DRV_ENQUE); + + /* enqueue to QM */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; + } + kalSendComplete(prAdapter->prGlueInfo, prNativePacket, WLAN_STATUS_INVALID_PACKET); + + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + + return WLAN_STATUS_INVALID_PACKET; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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; + +#if !CFG_SUPPORT_MULTITHREAD + ASSERT(pfgHwAccess); +#endif + + /* <1> dequeue packet by txDequeuTxPackets() */ +#if CFG_SUPPORT_MULTITHREAD + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + prMsduInfo = qmDequeueTxPacketsMthread(prAdapter, &prTxCtrl->rTc); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); +#else + 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); +#endif + if (prMsduInfo != NULL) { + if (kalIsCardRemoved(prAdapter->prGlueInfo) == FALSE) { +#if !CFG_SUPPORT_MULTITHREAD + /* <2> Acquire LP-OWN if necessary */ + if (*pfgHwAccess == FALSE) { + *pfgHwAccess = TRUE; + + wlanAcquirePowerControl(prAdapter); + } +#endif + /* <3> send packets */ +#if CFG_SUPPORT_MULTITHREAD + nicTxMsduInfoListMthread(prAdapter, prMsduInfo); +#else + nicTxMsduInfoList(prAdapter, prMsduInfo); +#endif + /* <4> update TC by txAdjustTcQuotas() */ + nicTxAdjustTcq(prAdapter); + } else + wlanProcessQueuedMsduInfo(prAdapter, prMsduInfo); + } + + 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); + + /* DBGLOG(INIT, INFO, ("Acquire Power Ctrl\n")); */ + + 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); + + /* DBGLOG(INIT, INFO, ("Release Power Ctrl\n")); */ + + 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) GLUE_GET_REF_CNT(prTxCtrl->i4PendingFwdFrameCount); + + return u4Num; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to report current ACPI state +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return ACPI_STATE_D0 Normal Operation Mode +* ACPI_STATE_D3 Suspend Mode +*/ +/*----------------------------------------------------------------------------*/ +ENUM_ACPI_STATE_T wlanGetAcpiState(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + return prAdapter->rAcpiState; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to update current ACPI state only +* +* @param prAdapter Pointer of Adapter Data Structure +* @param ePowerState ACPI_STATE_D0 Normal Operation Mode +* ACPI_STATE_D3 Suspend Mode +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanSetAcpiState(IN P_ADAPTER_T prAdapter, IN ENUM_ACPI_STATE_T ePowerState) +{ + ASSERT(prAdapter); + ASSERT(ePowerState <= ACPI_STATE_D3); + + prAdapter->rAcpiState = ePowerState; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to query ECO version from HIFSYS CR +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return zero Unable to retrieve ECO version information +* non-zero ECO version (1-based) +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 wlanGetEcoVersion(IN P_ADAPTER_T prAdapter) +{ + UINT_8 ucEcoVersion; + + ASSERT(prAdapter); + +#if CFG_MULTI_ECOVER_SUPPORT + ucEcoVersion = nicGetChipEcoVer(prAdapter); + DBGLOG(INIT, TRACE, "%s: %u\n", __func__, ucEcoVersion); + return ucEcoVersion; +#else + if (nicVerifyChipID(prAdapter) == TRUE) + return prAdapter->ucRevID + 1; + else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to query ROM version from HIFSYS CR +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return zero Unable to retrieve ROM version information +* non-zero ROM version (1-based) +*/ +/*----------------------------------------------------------------------------*/ +uint8_t wlanGetRomVersion(IN P_ADAPTER_T prAdapter) +{ + uint8_t ucRomVersion; + + ASSERT(prAdapter); + + ucRomVersion = nicGetChipSwVer(); + DBGLOG(INIT, TRACE, "%s: %u\n", __func__, ucRomVersion); + return ucRomVersion; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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 ucBssIndex BSS Info Index +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanSetPreferBandByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_BAND_T eBand, IN UINT_8 ucBssIndex) +{ + ASSERT(prAdapter); + ASSERT(eBand <= BAND_NUM); + ASSERT(ucBssIndex <= MAX_BSS_INDEX); + + + /* 1. set prefer band according to network type */ + prAdapter->aePreferBand[ucBssIndex] = eBand; + + /* 2. remove buffered BSS descriptors correspondingly */ + if (eBand == BAND_2G4) + scanRemoveBssDescByBandAndNetwork(prAdapter, BAND_5G, ucBssIndex); + else if (eBand == BAND_5G) + scanRemoveBssDescByBandAndNetwork(prAdapter, BAND_2G4, ucBssIndex); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to +* get channel information corresponding to specified network type +* +* @param prAdapter Pointer of Adapter Data Structure +* @param ucBssIndex BSS Info Index +* +* @return channel number +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 wlanGetChannelNumberByNetwork(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex) +{ + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= MAX_BSS_INDEX); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + return prBssInfo->ucPrimaryChannel; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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; + BOOLEAN fgIsConfExist = TRUE; + BOOLEAN fgGenErrMsg = FALSE; + P_REG_INFO_T prRegInfo = NULL; +#if 0 + const UINT_8 aucBCAddr[] = BC_MAC_ADDR; + 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 +#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 (CFG_SUPPORT_PWR_LIMIT_COUNTRY == 1) + if (fgIsConfExist == TRUE && (prAdapter->rVerInfo.u2Part1CfgPeerVersion > CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part2CfgPeerVersion > CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part1CfgOwnVersion < CFG_DRV_PEER_VERSION + || prAdapter->rVerInfo.u2Part2CfgOwnVersion < CFG_DRV_PEER_VERSION/* NVRAM */ + || prAdapter->rVerInfo.u2FwPeerVersion > CFG_DRV_OWN_VERSION + || 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 + || prAdapter->fgIsPowerLimitTableValid == FALSE)) + fgGenErrMsg = TRUE; +#else + if (fgIsConfExist == TRUE && (prAdapter->rVerInfo.u2Part1CfgPeerVersion > CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part2CfgPeerVersion > CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part1CfgOwnVersion < CFG_DRV_PEER_VERSION + || prAdapter->rVerInfo.u2Part2CfgOwnVersion < CFG_DRV_PEER_VERSION/* NVRAM */ + || prAdapter->rVerInfo.u2FwPeerVersion > CFG_DRV_OWN_VERSION + || 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 +#endif +#if 0/* remove NVRAM WARNING in scan result */ + 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, (UINT_8) (strlen(NVRAM_ERR_MSG))); + + kalIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) prBeacon, + OFFSET_OF(WLAN_BEACON_FRAME_T, + aucInfoElem) + OFFSET_OF(IE_SSID_T, aucSSID) + prSsid->ucLength, 1, 0); + + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, NVRAM_ERR_MSG, strlen(NVRAM_ERR_MSG)); + nicAddScanResult(prAdapter, + prBeacon->aucBSSID, + &rSsid, + 0, + 0, + PARAM_NETWORK_TYPE_FH, + &rConfiguration, + NET_TYPE_INFRA, + rSupportedRates, + OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem) + OFFSET_OF(IE_SSID_T, + aucSSID) + + prSsid->ucLength - WLAN_MAC_MGMT_HEADER_LEN, + (PUINT_8) ((ULONG) (prBeacon) + WLAN_MAC_MGMT_HEADER_LEN)); + } +#endif + +#if (CFG_SW_NVRAM_VERSION_CHECK == 1) +#define VER_ERR_MSG "NVRAM WARNING: Err = 0x%02X" + if (fgIsConfExist == TRUE) { + if ((prAdapter->rVerInfo.u2Part1CfgPeerVersion > CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part2CfgPeerVersion > CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2Part1CfgOwnVersion < CFG_DRV_PEER_VERSION + || prAdapter->rVerInfo.u2Part2CfgOwnVersion < CFG_DRV_PEER_VERSION /* NVRAM */ + || prAdapter->rVerInfo.u2FwPeerVersion > CFG_DRV_OWN_VERSION + || prAdapter->rVerInfo.u2FwOwnVersion < CFG_DRV_PEER_VERSION)) + u4ErrCode |= NVRAM_ERROR_VERSION_MISMATCH; + + if (prRegInfo->ucTxPwrValid == 0) + u4ErrCode |= NVRAM_ERROR_INVALID_TXPWR; + + if (prAdapter->fgIsEmbbededMacAddrValid == FALSE && (IS_BMCAST_MAC_ADDR(prRegInfo->aucMacAddr) + || EQUAL_MAC_ADDR(aucZeroMacAddr, + prRegInfo->aucMacAddr))) { + u4ErrCode |= NVRAM_ERROR_INVALID_MAC_ADDR; + } +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + if (prAdapter->fgIsPowerLimitTableValid == FALSE) + u4ErrCode |= NVRAM_POWER_LIMIT_TABLE_INVALID; +#endif + if (u4ErrCode != 0) { + sprintf(aucErrMsg, VER_ERR_MSG, (unsigned int)u4ErrCode); + COPY_SSID(prSsid->aucSSID, prSsid->ucLength, aucErrMsg, (UINT_8) (strlen(aucErrMsg))); + + kalIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) prBeacon, + OFFSET_OF(WLAN_BEACON_FRAME_T, + aucInfoElem) + OFFSET_OF(IE_SSID_T, + aucSSID) + prSsid->ucLength, 1, 0); + + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, NVRAM_ERR_MSG, strlen(NVRAM_ERR_MSG)); + nicAddScanResult(prAdapter, prBeacon->aucBSSID, &rSsid, 0, 0, + PARAM_NETWORK_TYPE_FH, &rConfiguration, NET_TYPE_INFRA, + rSupportedRates, OFFSET_OF(WLAN_BEACON_FRAME_T, + aucInfoElem) + + OFFSET_OF(IE_SSID_T, + aucSSID) + prSsid->ucLength - + WLAN_MAC_MGMT_HEADER_LEN, + (PUINT_8) ((ULONG) (prBeacon) + WLAN_MAC_MGMT_HEADER_LEN)); + } + } +#endif + + if (fgGenErrMsg == TRUE) + cnmMemFree(prAdapter, prBeacon); +#endif + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidQueryBssStatistics(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_GET_BSS_STATISTICS prQueryBssStatistics; + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + WLAN_STATUS rResult = WLAN_STATUS_FAILURE; + UINT_8 ucBssIndex; + ENUM_WMM_ACI_T eAci; + + DEBUGFUNC("wlanoidQueryBssStatistics"); + + do { + ASSERT(pvQueryBuffer); + + /* 4 1. Sanity test */ + if ((prAdapter == NULL) || (pu4QueryInfoLen == NULL)) + break; + + if ((u4QueryBufferLen) && (pvQueryBuffer == NULL)) + break; + + if (u4QueryBufferLen < sizeof(P_PARAM_GET_BSS_STATISTICS)) { + *pu4QueryInfoLen = sizeof(P_PARAM_GET_BSS_STATISTICS); + rResult = WLAN_STATUS_BUFFER_TOO_SHORT; + break; + } + + prQueryBssStatistics = (P_PARAM_GET_BSS_STATISTICS) pvQueryBuffer; + *pu4QueryInfoLen = sizeof(PARAM_GET_BSS_STATISTICS); + + ucBssIndex = prQueryBssStatistics->ucBssIndex; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (prBssInfo) { /*AIS*/ + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + prStaRec = prBssInfo->prStaRecOfAP; + if (prStaRec) { + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prQueryBssStatistics->arLinkStatistics[eAci].u4TxMsdu = + prStaRec->arLinkStatistics[eAci].u4TxMsdu; + prQueryBssStatistics->arLinkStatistics[eAci].u4RxMsdu = + prStaRec->arLinkStatistics[eAci].u4RxMsdu; + prQueryBssStatistics->arLinkStatistics[eAci].u4TxDropMsdu = + prStaRec->arLinkStatistics[eAci].u4TxDropMsdu + + prBssInfo->arLinkStatistics[eAci].u4TxDropMsdu; + prQueryBssStatistics->arLinkStatistics[eAci].u4TxFailMsdu = + prStaRec->arLinkStatistics[eAci].u4TxFailMsdu; + prQueryBssStatistics->arLinkStatistics[eAci].u4TxRetryMsdu = + prStaRec->arLinkStatistics[eAci].u4TxRetryMsdu; + } + } + } + rResult = WLAN_STATUS_SUCCESS; + + /*P2P */ + /* TODO */ + + /*BOW*/ + /* TODO */ + } + + } while (FALSE); + + return rResult; + +} + +VOID wlanDumpBssStatistics(IN P_ADAPTER_T prAdapter, UINT_8 ucBssIdx) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + ENUM_WMM_ACI_T eAci; + WIFI_WMM_AC_STAT_T arLLStats[WMM_AC_INDEX_NUM]; + UINT_8 ucIdx; + + if (ucBssIdx > MAX_BSS_INDEX) { + DBGLOG(SW4, INFO, "Invalid BssInfo index[%u], skip dump!\n", ucBssIdx); + return; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + if (!prBssInfo) { + DBGLOG(SW4, INFO, "Invalid BssInfo index[%u], skip dump!\n", ucBssIdx); + return; + } + /* <1> fill per-BSS statistics */ +#if 0 + /*AIS*/ if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + prStaRec = prBssInfo->prStaRecOfAP; + if (prStaRec) { + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prBssInfo->arLinkStatistics[eAci].u4TxMsdu = prStaRec->arLinkStatistics[eAci].u4TxMsdu; + prBssInfo->arLinkStatistics[eAci].u4RxMsdu = prStaRec->arLinkStatistics[eAci].u4RxMsdu; + prBssInfo->arLinkStatistics[eAci].u4TxDropMsdu += + prStaRec->arLinkStatistics[eAci].u4TxDropMsdu; + prBssInfo->arLinkStatistics[eAci].u4TxFailMsdu = + prStaRec->arLinkStatistics[eAci].u4TxFailMsdu; + prBssInfo->arLinkStatistics[eAci].u4TxRetryMsdu = + prStaRec->arLinkStatistics[eAci].u4TxRetryMsdu; + } + } + } +#else + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + arLLStats[eAci].u4TxMsdu = prBssInfo->arLinkStatistics[eAci].u4TxMsdu; + arLLStats[eAci].u4RxMsdu = prBssInfo->arLinkStatistics[eAci].u4RxMsdu; + arLLStats[eAci].u4TxDropMsdu = prBssInfo->arLinkStatistics[eAci].u4TxDropMsdu; + arLLStats[eAci].u4TxFailMsdu = prBssInfo->arLinkStatistics[eAci].u4TxFailMsdu; + arLLStats[eAci].u4TxRetryMsdu = prBssInfo->arLinkStatistics[eAci].u4TxRetryMsdu; + } + + for (ucIdx = 0; ucIdx < CFG_STA_REC_NUM; ucIdx++) { + prStaRec = cnmGetStaRecByIndex(prAdapter, ucIdx); + if (!prStaRec) + continue; + if (prStaRec->ucBssIndex != ucBssIdx) + continue; + /* now the valid sta_rec is valid */ + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + arLLStats[eAci].u4TxMsdu += prStaRec->arLinkStatistics[eAci].u4TxMsdu; + arLLStats[eAci].u4RxMsdu += prStaRec->arLinkStatistics[eAci].u4RxMsdu; + arLLStats[eAci].u4TxDropMsdu += prStaRec->arLinkStatistics[eAci].u4TxDropMsdu; + arLLStats[eAci].u4TxFailMsdu += prStaRec->arLinkStatistics[eAci].u4TxFailMsdu; + arLLStats[eAci].u4TxRetryMsdu += prStaRec->arLinkStatistics[eAci].u4TxRetryMsdu; + } + } +#endif + + /* <2>Dump BSS statistics */ + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + DBGLOG(SW4, INFO, "LLS BSS[%u] %s: T[%06u] R[%06u] T_D[%06u] T_F[%06u]\n", + prBssInfo->ucBssIndex, apucACI2Str[eAci], arLLStats[eAci].u4TxMsdu, + arLLStats[eAci].u4RxMsdu, arLLStats[eAci].u4TxDropMsdu, arLLStats[eAci].u4TxFailMsdu); + } +} + +VOID wlanDumpAllBssStatistics(IN P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prBssInfo; + /* ENUM_WMM_ACI_T eAci; */ + UINT_32 ucIdx; + + /* wlanUpdateAllBssStatistics(prAdapter); */ + + for (ucIdx = 0; ucIdx < BSS_INFO_NUM; ucIdx++) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucIdx); + if (!IS_BSS_ACTIVE(prBssInfo)) { + DBGLOG(SW4, TRACE, "Invalid BssInfo index[%u], skip dump!\n", ucIdx); + continue; + } + + wlanDumpBssStatistics(prAdapter, ucIdx); + } +} + +WLAN_STATUS +wlanoidQueryStaStatistics(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + return _wlanoidQueryStaStatistics(prAdapter, + pvQueryBuffer, + u4QueryBufferLen, + pu4QueryInfoLen, + g_fgIsOid); +} /* wlanoidQueryStaStatistics */ + +WLAN_STATUS +_wlanoidQueryStaStatistics(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen, IN BOOLEAN fgIsOid) +{ + WLAN_STATUS rResult = WLAN_STATUS_FAILURE; + P_STA_RECORD_T prStaRec, prTempStaRec; + P_PARAM_GET_STA_STATISTICS prQueryStaStatistics; + UINT_8 ucStaRecIdx; + P_QUE_MGT_T prQM; + CMD_GET_STA_STATISTICS_T rQueryCmdStaStatistics; + UINT_8 ucIdx; + ENUM_WMM_ACI_T eAci; + + DEBUGFUNC("wlanoidQueryStaStatistics"); + + if (prAdapter == NULL) + return WLAN_STATUS_FAILURE; + prQM = &prAdapter->rQM; + + if (prAdapter->fgIsEnableLpdvt) + return WLAN_STATUS_NOT_SUPPORTED; + + do { + ASSERT(pvQueryBuffer); + + /* 4 1. Sanity test */ + if (pu4QueryInfoLen == NULL) + break; + + if ((u4QueryBufferLen) && (pvQueryBuffer == NULL)) + break; + + if (u4QueryBufferLen < sizeof(PARAM_GET_STA_STA_STATISTICS)) { + *pu4QueryInfoLen = sizeof(PARAM_GET_STA_STA_STATISTICS); + rResult = WLAN_STATUS_BUFFER_TOO_SHORT; + break; + } + + prQueryStaStatistics = (P_PARAM_GET_STA_STATISTICS) pvQueryBuffer; + *pu4QueryInfoLen = sizeof(PARAM_GET_STA_STA_STATISTICS); + + /* 4 5. Get driver global QM counter */ +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + for (ucIdx = TC0_INDEX; ucIdx <= TC3_INDEX; ucIdx++) { + prQueryStaStatistics->au4TcAverageQueLen[ucIdx] = prQM->au4AverageQueLen[ucIdx]; + prQueryStaStatistics->au4TcCurrentQueLen[ucIdx] = prQM->au4CurrentTcResource[ucIdx]; + } +#endif + + /* 4 2. Get StaRec by MAC address */ + prStaRec = NULL; + + for (ucStaRecIdx = 0; ucStaRecIdx < CFG_STA_REC_NUM; ucStaRecIdx++) { + prTempStaRec = &(prAdapter->arStaRec[ucStaRecIdx]); + if (prTempStaRec->fgIsValid && prTempStaRec->fgIsInUse) { + if (EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, prQueryStaStatistics->aucMacAddr)) { + prStaRec = prTempStaRec; + break; + } + } + } + + if (!prStaRec) { + rResult = WLAN_STATUS_INVALID_DATA; + break; + } + + prQueryStaStatistics->u4Flag |= BIT(0); + +#if CFG_ENABLE_PER_STA_STATISTICS + /* 4 3. Get driver statistics */ + prQueryStaStatistics->u4TxTotalCount = prStaRec->u4TotalTxPktsNumber; + prQueryStaStatistics->u4RxTotalCount = prStaRec->u4TotalRxPktsNumber; + prQueryStaStatistics->u4TxExceedThresholdCount = prStaRec->u4ThresholdCounter; + prQueryStaStatistics->u4TxMaxTime = prStaRec->u4MaxTxPktsTime; + if (prStaRec->u4TotalTxPktsNumber) { + prQueryStaStatistics->u4TxAverageProcessTime = + (prStaRec->u4TotalTxPktsTime / prStaRec->u4TotalTxPktsNumber); + } else + prQueryStaStatistics->u4TxAverageProcessTime = 0; + + /*link layer statistics */ + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prQueryStaStatistics->arLinkStatistics[eAci].u4TxMsdu = + prStaRec->arLinkStatistics[eAci].u4TxMsdu; + prQueryStaStatistics->arLinkStatistics[eAci].u4RxMsdu = + prStaRec->arLinkStatistics[eAci].u4RxMsdu; + prQueryStaStatistics->arLinkStatistics[eAci].u4TxDropMsdu = + prStaRec->arLinkStatistics[eAci].u4TxDropMsdu; + } + + for (ucIdx = TC0_INDEX; ucIdx <= TC3_INDEX; ucIdx++) { + prQueryStaStatistics->au4TcResourceEmptyCount[ucIdx] = + prQM->au4QmTcResourceEmptyCounter[prStaRec->ucBssIndex][ucIdx]; + /* Reset */ + prQM->au4QmTcResourceEmptyCounter[prStaRec->ucBssIndex][ucIdx] = 0; + } + + /* 4 4.1 Reset statistics */ + if (prQueryStaStatistics->ucReadClear) { + prStaRec->u4ThresholdCounter = 0; + prStaRec->u4TotalTxPktsNumber = 0; + prStaRec->u4TotalTxPktsTime = 0; + prStaRec->u4TotalRxPktsNumber = 0; + prStaRec->u4MaxTxPktsTime = 0; + } + /*link layer statistics */ + if (prQueryStaStatistics->ucLlsReadClear) { + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prStaRec->arLinkStatistics[eAci].u4TxMsdu = 0; + prStaRec->arLinkStatistics[eAci].u4RxMsdu = 0; + prStaRec->arLinkStatistics[eAci].u4TxDropMsdu = 0; + } + } +#endif + + for (ucIdx = TC0_INDEX; ucIdx <= TC3_INDEX; ucIdx++) + prQueryStaStatistics->au4TcQueLen[ucIdx] = prStaRec->aprTargetQueue[ucIdx]->u4NumElem; + + rResult = WLAN_STATUS_SUCCESS; + + /* 4 6. Ensure FW supports get station link status */ + if (prAdapter->u4FwCompileFlag0 & COMPILE_FLAG0_GET_STA_LINK_STATUS) { + + DBGLOG(REQ, LOUD, "%s index[%x]\n", __func__, prStaRec->ucIndex); + rQueryCmdStaStatistics.ucIndex = prStaRec->ucIndex; + COPY_MAC_ADDR(rQueryCmdStaStatistics.aucMacAddr, prQueryStaStatistics->aucMacAddr); + rQueryCmdStaStatistics.ucReadClear = prQueryStaStatistics->ucReadClear; + rQueryCmdStaStatistics.ucLlsReadClear = prQueryStaStatistics->ucLlsReadClear; + rQueryCmdStaStatistics.ucResetCounter = prQueryStaStatistics->ucResetCounter; + + rResult = wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STA_STATISTICS, + FALSE, + TRUE, + fgIsOid, + nicCmdEventQueryStaStatistics, + nicOidCmdTimeoutCommon, + sizeof(CMD_GET_STA_STATISTICS_T), + (PUINT_8) &rQueryCmdStaStatistics, + pvQueryBuffer, u4QueryBufferLen); + + prQueryStaStatistics->u4Flag |= BIT(1); + } else { + rResult = WLAN_STATUS_NOT_SUPPORTED; + } + + } while (FALSE); + + return rResult; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to query Nic resource information +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanQueryNicResourceInformation(IN P_ADAPTER_T prAdapter) +{ + /* 3 1. Get Nic resource information from FW */ + + /* 3 2. Setup resource parameter */ + + /* 3 3. Reset Tx resource */ + nicTxResetResource(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to query Nic resource information +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ + + +WLAN_STATUS wlanQueryNicCapabilityV2(IN P_ADAPTER_T prAdapter) +{ + UINT_8 ucCmdSeqNum; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_32 u4RxPktLength; + P_UINT_8 prEventBuff; + P_HW_MAC_RX_DESC_T prRxStatus; + P_WIFI_EVENT_T prEvent; + struct mt66xx_chip_info *prChipInfo; + UINT_32 chip_id; + + prChipInfo = prAdapter->chip_info; + chip_id = prChipInfo->chip_id; + + + ASSERT(prAdapter); + + /* Get Nic resource information from FW */ + if (prAdapter->u4FwFeatureFlag0 & FEATURE_FLAG0_NIC_CAPABILITY_V2) { + + DBGLOG(INIT, INFO, "Support NIC_CAPABILITY_V2 feature\n"); + + /* + * send NIC_CAPABILITY_V2 query cmd + */ + + /* 1. Allocate CMD Info Packet and its Buffer */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_BUILD_CONNECTION cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE; + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_GET_NIC_CAPABILITY_V2; + prCmdInfo->fgSetQuery = FALSE; + prCmdInfo->fgNeedResp = TRUE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = 0; + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prWifiCmd->u2Length = prCmdInfo->u2InfoBufLen - (UINT_16) OFFSET_OF(WIFI_CMD_T, u2Length); + + wlanSendCommand(prAdapter, prCmdInfo); + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + /* + * receive nic_capability_v2 event + */ + + + /* allocate event buffer */ + prEventBuff = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, CFG_RX_MAX_PKT_SIZE); + if (!prEventBuff) { + DBGLOG(INIT, WARN, "%s: event buffer alloc failed!\n", __func__); + return WLAN_STATUS_FAILURE; + } + + /* get event */ + while (TRUE) { + if (nicRxWaitResponse(prAdapter, + 1, + prEventBuff, + CFG_RX_MAX_PKT_SIZE, + &u4RxPktLength) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, WARN, "%s: wait for event failed!\n", __func__); + + /* free event buffer */ + cnmMemFree(prAdapter, prEventBuff); + + return WLAN_STATUS_FAILURE; + } + + /* header checking .. */ + prRxStatus = (P_HW_MAC_RX_DESC_T) prEventBuff; + if ((prRxStatus->u2PktTYpe & RXM_RXD_PKT_TYPE_SW_BITMAP) != RXM_RXD_PKT_TYPE_SW_EVENT) { + + DBGLOG(INIT, WARN, "%s: skip unexpected Rx pkt type[0x%04x]\n", __func__, + prRxStatus->u2PktTYpe); + + continue; + } + + prEvent = (P_WIFI_EVENT_T) prEventBuff; + if (prEvent->ucEID != EVENT_ID_NIC_CAPABILITY_V2) { + DBGLOG(INIT, WARN, "%s: skip unexpected event ID[0x%02x]\n", __func__, prEvent->ucEID); + + continue; + } else { + /* hit */ + break; + } + } + + /* + * parsing elemens + */ + + nicCmdEventQueryNicCapabilityV2(prAdapter, prEvent->aucBuffer); + +#if CFG_SUPPORT_BFER + if (prAdapter->ucRModeOnlyFlag) + prAdapter->fgIsHwSupportBfer = FALSE; + else + prAdapter->fgIsHwSupportBfer = TRUE; +#endif + + /* + * free event buffer + */ + cnmMemFree(prAdapter, prEventBuff); + } + + /* Fill capability for different Chip version */ + if (chip_id == HQA_CHIP_ID_6632) { + /* 6632 only */ + prAdapter->fgIsSupportBufferBinSize16Byte = TRUE; + prAdapter->fgIsSupportDelayCal = FALSE; + prAdapter->fgIsSupportGetFreeEfuseBlockCount = FALSE; + prAdapter->fgIsSupportQAAccessEfuse = FALSE; + prAdapter->fgIsSupportPowerOnSendBufferModeCMD = FALSE; + prAdapter->fgIsSupportGetTxPower = FALSE; + } else { + prAdapter->fgIsSupportBufferBinSize16Byte = FALSE; + prAdapter->fgIsSupportDelayCal = TRUE; + prAdapter->fgIsSupportGetFreeEfuseBlockCount = TRUE; + prAdapter->fgIsSupportQAAccessEfuse = TRUE; + prAdapter->fgIsSupportPowerOnSendBufferModeCMD = TRUE; + prAdapter->fgIsSupportGetTxPower = TRUE; + } + + return WLAN_STATUS_SUCCESS; +} + +VOID wlanSetNicResourceParameters(IN P_ADAPTER_T prAdapter) +{ + UINT_8 string[128], idx; + UINT_32 u4share; + P_WIFI_VAR_T prWifiVar = &prAdapter->rWifiVar; +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + P_QUE_MGT_T prQM = &prAdapter->rQM; +#endif + + /* + * Use the settings in config file first, + * else, use the settings reported from firmware. + */ + + + /* + * 1. assign free page count for each TC + */ + + /* 1 1. update free page count in TC control: MCU and LMAC */ + prWifiVar->au4TcPageCount[TC4_INDEX] = + prAdapter->nicTxReousrce.u4McuTotalResource * NIC_TX_MAX_PAGE_PER_FRAME; /* MCU */ + + u4share = prAdapter->nicTxReousrce.u4LmacTotalResource/(TC_NUM - 1); /* LMAC. Except TC_4, which is MCU */ + for (idx = TC0_INDEX; idx < TC_NUM; idx++) { + if (idx != TC4_INDEX) + prWifiVar->au4TcPageCount[idx] = u4share * NIC_TX_MAX_PAGE_PER_FRAME; + } + + /* 1 2. if there is remaings, give them to TC_3, which is VO */ + prWifiVar->au4TcPageCount[TC3_INDEX] += + (prAdapter->nicTxReousrce.u4LmacTotalResource%(TC_NUM - 1)) * NIC_TX_MAX_PAGE_PER_FRAME; + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + /* + * 2. assign guaranteed page count for each TC + */ + + /* 2 1. update guaranteed page count in QM */ + for (idx = 0; idx < TC_NUM; idx++) + prQM->au4GuaranteedTcResource[idx] = prWifiVar->au4TcPageCount[idx]; +#endif + + +#if CFG_SUPPORT_CFG_FILE + /* + * 3. Use the settings in config file first, + * else, use the settings reported from firmware. + */ + + /* 3 1. update for free page count */ + for (idx = 0; idx < TC_NUM; idx++) { + + /* construct prefix: Tc0Page, Tc1Page... */ + memset(string, 0, sizeof(string)/sizeof(UINT_8)); + snprintf(string, sizeof(string)/sizeof(UINT_8), "Tc%xPage", idx); + + /* update the final value */ + prWifiVar->au4TcPageCount[idx] = + (UINT_32) wlanCfgGetUint32(prAdapter, + string, prWifiVar->au4TcPageCount[idx]); + } + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + /* 3 2. update for guaranteed page count */ + for (idx = 0; idx < TC_NUM; idx++) { + + /* construct prefix: Tc0Grt, Tc1Grt... */ + memset(string, 0, sizeof(string)/sizeof(UINT_8)); + snprintf(string, sizeof(string)/sizeof(UINT_8), "Tc%xGrt", idx); + + /* update the final value */ + prQM->au4GuaranteedTcResource[idx] = + (UINT_32) wlanCfgGetUint32(prAdapter, + string, prQM->au4GuaranteedTcResource[idx]); + } +#endif /* end of #if QM_ADAPTIVE_TC_RESOURCE_CTRL */ + +#endif /* end of #if CFG_SUPPORT_CFG_FILE */ +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to query Nic resource information +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanUpdateNicResourceInformation(IN P_ADAPTER_T prAdapter) +{ + /* + * 3 1. Query TX resource + */ + + /* information is not got from firmware, use default value */ + if (prAdapter->fgIsNicTxReousrceValid != TRUE) + return; + + /* 3 2. Setup resource parameters */ + wlanSetNicResourceParameters(prAdapter); + + /* 3 3. Reset Tx resource */ + nicTxResetResource(prAdapter); + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + /* 3 4. Reset QM resource */ + qmResetTcControlResource(prAdapter); +#endif + + halTxResourceResetHwTQCounter(prAdapter); +} + + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to SET network interface index for a network interface. +* A network interface is a TX/RX data port hooked to OS. +* +* @param prGlueInfo Pointer of prGlueInfo Data Structure +* @param ucNetInterfaceIndex Index of network interface +* @param ucBssIndex Index of BSS +* +* @return VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanBindNetInterface(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucNetInterfaceIndex, IN PVOID pvNetInterface) +{ + P_NET_INTERFACE_INFO_T prNetIfInfo; + + prNetIfInfo = &prGlueInfo->arNetInterfaceInfo[ucNetInterfaceIndex]; + + prNetIfInfo->pvNetInterface = pvNetInterface; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to SET BSS index for a network interface. +* A network interface is a TX/RX data port hooked to OS. +* +* @param prGlueInfo Pointer of prGlueInfo Data Structure +* @param ucNetInterfaceIndex Index of network interface +* @param ucBssIndex Index of BSS +* +* @return VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanBindBssIdxToNetInterface(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucBssIndex, IN PVOID pvNetInterface) +{ + P_NET_INTERFACE_INFO_T prNetIfInfo; + + if (ucBssIndex >= ARRAY_SIZE(prGlueInfo->arNetInterfaceInfo)) { + DBGLOG(INIT, ERROR, "Array index out of bound, ucBssIndex=%u\n", ucBssIndex); + return; + } + + prNetIfInfo = &prGlueInfo->arNetInterfaceInfo[ucBssIndex]; + + prNetIfInfo->ucBssIndex = ucBssIndex; + prNetIfInfo->pvNetInterface = pvNetInterface; + /* prGlueInfo->aprBssIdxToNetInterfaceInfo[ucBssIndex] = prNetIfInfo; */ +} + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to GET BSS index for a network interface. +* A network interface is a TX/RX data port hooked to OS. +* +* @param prGlueInfo Pointer of prGlueInfo Data Structure +* @param ucNetInterfaceIndex Index of network interface +* +* @return UINT_8 Index of BSS +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 wlanGetBssIdxByNetInterface(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvNetInterface) +{ + UINT_8 ucIdx = 0; + + for (ucIdx = 0; ucIdx < HW_BSSID_NUM; ucIdx++) { + if (prGlueInfo->arNetInterfaceInfo[ucIdx].pvNetInterface == pvNetInterface) + break; + } + + return ucIdx; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to GET network interface for a BSS. +* A network interface is a TX/RX data port hooked to OS. +* +* @param prGlueInfo Pointer of prGlueInfo Data Structure +* @param ucBssIndex Index of BSS +* +* @return PVOID pointer of network interface structure +*/ +/*----------------------------------------------------------------------------*/ +PVOID wlanGetNetInterfaceByBssIdx(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucBssIndex) +{ + return prGlueInfo->arNetInterfaceInfo[ucBssIndex].pvNetInterface; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to get BSS-INDEX for AIS network. +* +* @param prAdapter Pointer of ADAPTER_T +* +* @return value, as corresponding index of BSS +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 wlanGetAisBssIndex(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + ASSERT(prAdapter->prAisBssInfo); + + return prAdapter->prAisBssInfo->ucBssIndex; +} +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to initialize WLAN feature options +* +* @param prAdapter Pointer of ADAPTER_T +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanInitFeatureOption(IN P_ADAPTER_T prAdapter) +{ + P_WIFI_VAR_T prWifiVar = &prAdapter->rWifiVar; +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + P_QUE_MGT_T prQM = &prAdapter->rQM; +#endif + + /* Feature options will be filled by config file */ + + prWifiVar->ucQoS = (UINT_8) wlanCfgGetUint32(prAdapter, "Qos", FEATURE_ENABLED); + + prWifiVar->ucStaHt = (UINT_8) wlanCfgGetUint32(prAdapter, "StaHT", FEATURE_ENABLED); + prWifiVar->ucStaVht = (UINT_8) wlanCfgGetUint32(prAdapter, "StaVHT", FEATURE_ENABLED); + + prWifiVar->ucApHt = (UINT_8) wlanCfgGetUint32(prAdapter, "ApHT", FEATURE_ENABLED); + prWifiVar->ucApVht = (UINT_8) wlanCfgGetUint32(prAdapter, "ApVHT", FEATURE_ENABLED); + + prWifiVar->ucP2pGoHt = (UINT_8) wlanCfgGetUint32(prAdapter, "P2pGoHT", FEATURE_ENABLED); + prWifiVar->ucP2pGoVht = (UINT_8) wlanCfgGetUint32(prAdapter, "P2pGoVHT", FEATURE_ENABLED); + + prWifiVar->ucP2pGcHt = (UINT_8) wlanCfgGetUint32(prAdapter, "P2pGcHT", FEATURE_ENABLED); + prWifiVar->ucP2pGcVht = (UINT_8) wlanCfgGetUint32(prAdapter, "P2pGcVHT", FEATURE_ENABLED); + + prWifiVar->ucAmpduRx = (UINT_8) wlanCfgGetUint32(prAdapter, "AmpduRx", FEATURE_ENABLED); + prWifiVar->ucAmpduTx = (UINT_8) wlanCfgGetUint32(prAdapter, "AmpduTx", FEATURE_ENABLED); + + prWifiVar->ucAmsduInAmpduRx = (UINT_8) wlanCfgGetUint32(prAdapter, "AmsduInAmpduRx", FEATURE_ENABLED); + prWifiVar->ucAmsduInAmpduTx = (UINT_8) wlanCfgGetUint32(prAdapter, "AmsduInAmpduTx", FEATURE_ENABLED); + prWifiVar->ucHtAmsduInAmpduRx = (UINT_8) wlanCfgGetUint32(prAdapter, "HtAmsduInAmpduRx", FEATURE_DISABLED); + prWifiVar->ucHtAmsduInAmpduTx = (UINT_8) wlanCfgGetUint32(prAdapter, "HtAmsduInAmpduTx", FEATURE_DISABLED); + prWifiVar->ucVhtAmsduInAmpduRx = (UINT_8) wlanCfgGetUint32(prAdapter, "VhtAmsduInAmpduRx", FEATURE_ENABLED); + prWifiVar->ucVhtAmsduInAmpduTx = (UINT_8) wlanCfgGetUint32(prAdapter, "VhtAmsduInAmpduTx", FEATURE_ENABLED); + + prWifiVar->ucTspec = (UINT_8) wlanCfgGetUint32(prAdapter, "Tspec", FEATURE_DISABLED); + + prWifiVar->ucUapsd = (UINT_8) wlanCfgGetUint32(prAdapter, "Uapsd", FEATURE_ENABLED); + prWifiVar->ucStaUapsd = (UINT_8) wlanCfgGetUint32(prAdapter, "StaUapsd", FEATURE_DISABLED); + prWifiVar->ucApUapsd = (UINT_8) wlanCfgGetUint32(prAdapter, "ApUapsd", FEATURE_DISABLED); + prWifiVar->ucP2pUapsd = (UINT_8) wlanCfgGetUint32(prAdapter, "P2pUapsd", FEATURE_ENABLED); + prWifiVar->u4RegP2pIfAtProbe = (UINT_8) wlanCfgGetUint32(prAdapter, "RegP2pIfAtProbe", FEATURE_DISABLED); + prWifiVar->ucP2pShareMacAddr = (UINT_8) wlanCfgGetUint32(prAdapter, "P2pShareMacAddr", FEATURE_DISABLED); + + prWifiVar->ucTxShortGI = (UINT_8) wlanCfgGetUint32(prAdapter, "SgiTx", FEATURE_ENABLED); + prWifiVar->ucRxShortGI = (UINT_8) wlanCfgGetUint32(prAdapter, "SgiRx", FEATURE_ENABLED); + + prWifiVar->ucTxLdpc = (UINT_8) wlanCfgGetUint32(prAdapter, "LdpcTx", FEATURE_ENABLED); + prWifiVar->ucRxLdpc = (UINT_8) wlanCfgGetUint32(prAdapter, "LdpcRx", FEATURE_ENABLED); + + prWifiVar->ucTxStbc = (UINT_8) wlanCfgGetUint32(prAdapter, "StbcTx", FEATURE_ENABLED); + prWifiVar->ucRxStbc = (UINT_8) wlanCfgGetUint32(prAdapter, "StbcRx", FEATURE_ENABLED); + prWifiVar->ucRxStbcNss = (UINT_8) wlanCfgGetUint32(prAdapter, "StbcRxNss", 1); + + prWifiVar->ucTxGf = (UINT_8) wlanCfgGetUint32(prAdapter, "GfTx", FEATURE_ENABLED); + prWifiVar->ucRxGf = (UINT_8) wlanCfgGetUint32(prAdapter, "GfRx", FEATURE_ENABLED); + + prWifiVar->ucMCS32 = (UINT_8) wlanCfgGetUint32(prAdapter, "MCS32", FEATURE_DISABLED); + + prWifiVar->ucSigTaRts = (UINT_8) wlanCfgGetUint32(prAdapter, "SigTaRts", FEATURE_DISABLED); + prWifiVar->ucDynBwRts = (UINT_8) wlanCfgGetUint32(prAdapter, "DynBwRts", FEATURE_DISABLED); + prWifiVar->ucTxopPsTx = (UINT_8) wlanCfgGetUint32(prAdapter, "TxopPsTx", FEATURE_DISABLED); + + prWifiVar->ucStaHtBfee = (UINT_8) wlanCfgGetUint32(prAdapter, + "StaHTBfee", FEATURE_DISABLED); + prWifiVar->ucStaVhtBfee = (UINT_8) wlanCfgGetUint32(prAdapter, "StaVHTBfee", FEATURE_ENABLED); + prWifiVar->ucStaVhtMuBfee = (UINT_8)wlanCfgGetUint32(prAdapter, "StaVHTMuBfee", FEATURE_ENABLED); + prWifiVar->ucStaHtBfer = (UINT_8) wlanCfgGetUint32(prAdapter, "StaHTBfer", FEATURE_DISABLED); + prWifiVar->ucStaVhtBfer = (UINT_8) wlanCfgGetUint32(prAdapter, "StaVHTBfer", FEATURE_DISABLED); + + /* 0: disabled + * 1: Tx done event to driver + * 2: Tx status to FW only + */ + prWifiVar->ucDataTxDone = (UINT_8) wlanCfgGetUint32(prAdapter, "DataTxDone", 0); + prWifiVar->ucDataTxRateMode = (UINT_8) wlanCfgGetUint32(prAdapter, "DataTxRateMode", DATA_RATE_MODE_AUTO); + prWifiVar->u4DataTxRateCode = wlanCfgGetUint32(prAdapter, "DataTxRateCode", 0x0); + + prWifiVar->ucApWpsMode = (UINT_8) wlanCfgGetUint32(prAdapter, "ApWpsMode", 0); + DBGLOG(INIT, INFO, "ucApWpsMode = %u\n", prWifiVar->ucApWpsMode); + + prWifiVar->ucThreadScheduling = (UINT_8) wlanCfgGetUint32(prAdapter, "ThreadSched", 0); + prWifiVar->ucThreadPriority = (UINT_8) wlanCfgGetUint32(prAdapter, "ThreadPriority", WLAN_THREAD_TASK_PRIORITY); + prWifiVar->cThreadNice = (INT_8) wlanCfgGetInt32(prAdapter, "ThreadNice", WLAN_THREAD_TASK_NICE); + + prAdapter->rQM.u4MaxForwardBufferCount = + (UINT_32) wlanCfgGetUint32(prAdapter, "ApForwardBufferCnt", QM_FWD_PKT_QUE_THRESHOLD); + + /* AP channel setting + * 0: auto + */ + prWifiVar->ucApChannel = (UINT_8) wlanCfgGetUint32(prAdapter, "ApChannel", 0); + + /* + * 0: SCN + * 1: SCA + * 2: RES + * 3: SCB + */ + prWifiVar->ucApSco = (UINT_8) wlanCfgGetUint32(prAdapter, "ApSco", 0); + prWifiVar->ucP2pGoSco = (UINT_8) wlanCfgGetUint32(prAdapter, "P2pGoSco", 0); + + /* Max bandwidth setting + * 0: 20Mhz + * 1: 40Mhz + * 2: 80Mhz + * 3: 160Mhz + * 4: 80+80Mhz + * Note: For VHT STA, BW 80Mhz is a must! + */ + prWifiVar->ucStaBandwidth = (UINT_8) wlanCfgGetUint32(prAdapter, "StaBw", MAX_BW_160MHZ); + prWifiVar->ucSta2gBandwidth = (UINT_8) wlanCfgGetUint32(prAdapter, "Sta2gBw", MAX_BW_20MHZ); + prWifiVar->ucSta5gBandwidth = (UINT_8) wlanCfgGetUint32(prAdapter, "Sta5gBw", MAX_BW_80MHZ); + prWifiVar->ucP2p2gBandwidth = (UINT_8) wlanCfgGetUint32(prAdapter, "P2p2gBw", MAX_BW_40MHZ); + prWifiVar->ucP2p5gBandwidth = (UINT_8) wlanCfgGetUint32(prAdapter, "P2p5gBw", MAX_BW_80MHZ); + prWifiVar->ucApBandwidth = (UINT_8) wlanCfgGetUint32(prAdapter, "ApBw", MAX_BW_160MHZ); + prWifiVar->ucAp2gBandwidth = (UINT_8) wlanCfgGetUint32(prAdapter, "Ap2gBw", MAX_BW_40MHZ); + prWifiVar->ucAp5gBandwidth = (UINT_8) wlanCfgGetUint32(prAdapter, "Ap5gBw", MAX_BW_80MHZ); + prWifiVar->ucApChnlDefFromCfg = (UINT_8) wlanCfgGetUint32(prAdapter, "ApChnlDefFromCfg", FEATURE_ENABLED); + prWifiVar->ucApAllowHtVhtTkip = + (UINT_8) wlanCfgGetUint32(prAdapter, + "ApAllowHtVhtTkip", FEATURE_DISABLED); + + prWifiVar->ucNSS = (UINT_8) wlanCfgGetUint32(prAdapter, "Nss", 2); + + /* Max Rx MPDU length setting + * 0: 3k + * 1: 8k + * 2: 11k + */ + prWifiVar->ucRxMaxMpduLen = (UINT_8) wlanCfgGetUint32(prAdapter, "RxMaxMpduLen", VHT_CAP_INFO_MAX_MPDU_LEN_3K); + /* Max Tx AMSDU in AMPDU length *in BYTES* */ + prWifiVar->u4TxMaxAmsduInAmpduLen = wlanCfgGetUint32(prAdapter, "TxMaxAmsduInAmpduLen", 4096); + + prWifiVar->ucStaDisconnectDetectTh = (UINT_8) wlanCfgGetUint32(prAdapter, "StaDisconnectDetectTh", 0); + prWifiVar->ucApDisconnectDetectTh = (UINT_8) wlanCfgGetUint32(prAdapter, "ApDisconnectDetectTh", 0); + prWifiVar->ucP2pDisconnectDetectTh = (UINT_8) wlanCfgGetUint32(prAdapter, "P2pDisconnectDetectTh", 0); + + prWifiVar->ucTcRestrict = (UINT_8) wlanCfgGetUint32(prAdapter, "TcRestrict", 0xFF); + /* Max Tx dequeue limit: 0 => auto */ + prWifiVar->u4MaxTxDeQLimit = (UINT_32) wlanCfgGetUint32(prAdapter, "MaxTxDeQLimit", 0x0); + prWifiVar->ucAlwaysResetUsedRes = (UINT_32) wlanCfgGetUint32(prAdapter, "AlwaysResetUsedRes", 0x0); + +#if CFG_SUPPORT_MTK_SYNERGY + prWifiVar->ucMtkOui = (UINT_8) wlanCfgGetUint32(prAdapter, "MtkOui", FEATURE_ENABLED); + prWifiVar->u4MtkOuiCap = (UINT_32) wlanCfgGetUint32(prAdapter, "MtkOuiCap", 0); + prWifiVar->aucMtkFeature[0] = 0xff; + prWifiVar->aucMtkFeature[1] = 0xff; + prWifiVar->aucMtkFeature[2] = 0xff; + prWifiVar->aucMtkFeature[3] = 0xff; +#endif + + prWifiVar->ucCmdRsvResource = (UINT_8) wlanCfgGetUint32(prAdapter, "TxCmdRsv", QM_CMD_RESERVED_THRESHOLD); + prWifiVar->u4MgmtQueueDelayTimeout = + (UINT_32) wlanCfgGetUint32(prAdapter, "TxMgmtQueTO", QM_MGMT_QUEUED_TIMEOUT); /* ms */ + + /* Performance related */ + prWifiVar->u4HifIstLoopCount = (UINT_32) wlanCfgGetUint32(prAdapter, "IstLoop", CFG_IST_LOOP_COUNT); + prWifiVar->u4Rx2OsLoopCount = (UINT_32) wlanCfgGetUint32(prAdapter, "Rx2OsLoop", 4); + prWifiVar->u4HifTxloopCount = (UINT_32) wlanCfgGetUint32(prAdapter, "HifTxLoop", 1); + prWifiVar->u4TxFromOsLoopCount = (UINT_32) wlanCfgGetUint32(prAdapter, "OsTxLoop", 1); + prWifiVar->u4TxRxLoopCount = (UINT_32) wlanCfgGetUint32(prAdapter, "Rx2ReorderLoop", 1); + prWifiVar->u4TxIntThCount = (UINT_32) wlanCfgGetUint32(prAdapter, "IstTxTh", HIF_IST_TX_THRESHOLD); + + prWifiVar->u4NetifStopTh = + (UINT_32) wlanCfgGetUint32(prAdapter, "NetifStopTh", CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD); + prWifiVar->u4NetifStartTh = + (UINT_32) wlanCfgGetUint32(prAdapter, "NetifStartTh", CFG_TX_START_NETIF_PER_QUEUE_THRESHOLD); + prWifiVar->ucTxBaSize = (UINT_8) wlanCfgGetUint32(prAdapter, "TxBaSize", 64); + prWifiVar->ucRxHtBaSize = (UINT_8) wlanCfgGetUint32(prAdapter, "RxHtBaSize", 64); + prWifiVar->ucRxVhtBaSize = (UINT_8) wlanCfgGetUint32(prAdapter, "RxVhtBaSize", 64); + + /* Tx Buffer Management */ + prWifiVar->ucExtraTxDone = (UINT_32) wlanCfgGetUint32(prAdapter, "ExtraTxDone", 1); + prWifiVar->ucTxDbg = (UINT_32) wlanCfgGetUint32(prAdapter, "TxDbg", 0); + + kalMemZero(prWifiVar->au4TcPageCount, sizeof(prWifiVar->au4TcPageCount)); + + prWifiVar->au4TcPageCount[TC0_INDEX] = (UINT_32) wlanCfgGetUint32(prAdapter, "Tc0Page", NIC_TX_PAGE_COUNT_TC0); + prWifiVar->au4TcPageCount[TC1_INDEX] = (UINT_32) wlanCfgGetUint32(prAdapter, "Tc1Page", NIC_TX_PAGE_COUNT_TC1); + prWifiVar->au4TcPageCount[TC2_INDEX] = (UINT_32) wlanCfgGetUint32(prAdapter, "Tc2Page", NIC_TX_PAGE_COUNT_TC2); + prWifiVar->au4TcPageCount[TC3_INDEX] = (UINT_32) wlanCfgGetUint32(prAdapter, "Tc3Page", NIC_TX_PAGE_COUNT_TC3); + prWifiVar->au4TcPageCount[TC4_INDEX] = (UINT_32) wlanCfgGetUint32(prAdapter, "Tc4Page", NIC_TX_PAGE_COUNT_TC4); + prWifiVar->au4TcPageCount[TC5_INDEX] = (UINT_32) wlanCfgGetUint32(prAdapter, "Tc5Page", NIC_TX_PAGE_COUNT_TC5); + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + prQM->au4MinReservedTcResource[TC0_INDEX] = + (UINT_32) wlanCfgGetUint32(prAdapter, "Tc0MinRsv", QM_MIN_RESERVED_TC0_RESOURCE); + prQM->au4MinReservedTcResource[TC1_INDEX] = + (UINT_32) wlanCfgGetUint32(prAdapter, "Tc1MinRsv", QM_MIN_RESERVED_TC1_RESOURCE); + prQM->au4MinReservedTcResource[TC2_INDEX] = + (UINT_32) wlanCfgGetUint32(prAdapter, "Tc2MinRsv", QM_MIN_RESERVED_TC2_RESOURCE); + prQM->au4MinReservedTcResource[TC3_INDEX] = + (UINT_32) wlanCfgGetUint32(prAdapter, "Tc3MinRsv", QM_MIN_RESERVED_TC3_RESOURCE); + prQM->au4MinReservedTcResource[TC4_INDEX] = + (UINT_32) wlanCfgGetUint32(prAdapter, "Tc4MinRsv", QM_MIN_RESERVED_TC4_RESOURCE); + prQM->au4MinReservedTcResource[TC5_INDEX] = + (UINT_32) wlanCfgGetUint32(prAdapter, "Tc5MinRsv", QM_MIN_RESERVED_TC5_RESOURCE); + + prQM->au4GuaranteedTcResource[TC0_INDEX] = + (UINT_32) wlanCfgGetUint32(prAdapter, "Tc0Grt", QM_GUARANTEED_TC0_RESOURCE); + prQM->au4GuaranteedTcResource[TC1_INDEX] = + (UINT_32) wlanCfgGetUint32(prAdapter, "Tc1Grt", QM_GUARANTEED_TC1_RESOURCE); + prQM->au4GuaranteedTcResource[TC2_INDEX] = + (UINT_32) wlanCfgGetUint32(prAdapter, "Tc2Grt", QM_GUARANTEED_TC2_RESOURCE); + prQM->au4GuaranteedTcResource[TC3_INDEX] = + (UINT_32) wlanCfgGetUint32(prAdapter, "Tc3Grt", QM_GUARANTEED_TC3_RESOURCE); + prQM->au4GuaranteedTcResource[TC4_INDEX] = + (UINT_32) wlanCfgGetUint32(prAdapter, "Tc4Grt", QM_GUARANTEED_TC4_RESOURCE); + prQM->au4GuaranteedTcResource[TC5_INDEX] = + (UINT_32) wlanCfgGetUint32(prAdapter, "Tc5Grt", QM_GUARANTEED_TC5_RESOURCE); + + prQM->u4TimeToAdjustTcResource = + (UINT_32) wlanCfgGetUint32(prAdapter, "TcAdjustTime", QM_INIT_TIME_TO_ADJUST_TC_RSC); + prQM->u4TimeToUpdateQueLen = + (UINT_32) wlanCfgGetUint32(prAdapter, "QueLenUpdateTime", QM_INIT_TIME_TO_UPDATE_QUE_LEN); + prQM->u4QueLenMovingAverage = + (UINT_32) wlanCfgGetUint32(prAdapter, "QueLenMovingAvg", QM_QUE_LEN_MOVING_AVE_FACTOR); + prQM->u4ExtraReservedTcResource = + (UINT_32) wlanCfgGetUint32(prAdapter, "TcExtraRsv", QM_EXTRA_RESERVED_RESOURCE_WHEN_BUSY); +#endif + + /* Stats log */ + prWifiVar->u4StatsLogTimeout = (UINT_32) wlanCfgGetUint32(prAdapter, "StatsLogTO", WLAN_TX_STATS_LOG_TIMEOUT); + prWifiVar->u4StatsLogDuration = + (UINT_32) wlanCfgGetUint32(prAdapter, "StatsLogDur", WLAN_TX_STATS_LOG_DURATION); + + prWifiVar->ucDhcpTxDone = (UINT_8) wlanCfgGetUint32(prAdapter, "DhcpTxDone", 1); + prWifiVar->ucArpTxDone = (UINT_8) wlanCfgGetUint32(prAdapter, "ArpTxDone", 1); + + prWifiVar->ucMacAddrOverride = (UINT_8) wlanCfgGetInt32(prAdapter, "MacOverride", 0); + if (wlanCfgGet(prAdapter, "MacAddr", prWifiVar->aucMacAddrStr, "00:0c:e7:66:32:e1", 0)) + DBGLOG(INIT, INFO, "get MacAddr fail, use defaul\n"); + + prWifiVar->ucCtiaMode = (UINT_8) wlanCfgGetUint32(prAdapter, "CtiaMode", 0); + + /* Combine ucTpTestMode and ucSigmaTestMode in one flag */ + /* ucTpTestMode == 0, for normal driver */ + /* ucTpTestMode == 1, for pure throughput test mode (ex: RvR) */ + /* ucTpTestMode == 2, for sigma TGn/TGac/PMF */ + /* ucTpTestMode == 3, for sigma WMM PS */ + prWifiVar->ucTpTestMode = (UINT_8) wlanCfgGetUint32(prAdapter, "TpTestMode", 0); + +#if 0 + prWifiVar->ucSigmaTestMode = (UINT_8) wlanCfgGetUint32(prAdapter, "SigmaTestMode", 0); +#endif + +#if CFG_SUPPORT_DBDC + prWifiVar->ucDbdcMode = (UINT_8) wlanCfgGetUint32(prAdapter, "DbdcMode", DBDC_MODE_DYNAMIC); +#endif /*CFG_SUPPORT_DBDC*/ +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1) + prWifiVar->ucEfuseBufferModeCal = (UINT_8) wlanCfgGetUint32(prAdapter, "EfuseBufferModeCal", 0); +#endif + prWifiVar->ucCalTimingCtrl = (UINT_8) wlanCfgGetUint32(prAdapter, "CalTimingCtrl", 0 /* power on full cal */); + prWifiVar->ucWow = (UINT_8) wlanCfgGetUint32(prAdapter, "Wow", FEATURE_DISABLED); + prWifiVar->ucOffload = (UINT_8) wlanCfgGetUint32(prAdapter, "Offload", FEATURE_DISABLED); + prWifiVar->ucAdvPws = (UINT_8) wlanCfgGetUint32(prAdapter, + "AdvPws", FEATURE_DISABLED); + prWifiVar->ucWowOnMdtim = (UINT_8) wlanCfgGetUint32(prAdapter, "WowOnMdtim", 1); + prWifiVar->ucWowOffMdtim = (UINT_8) wlanCfgGetUint32(prAdapter, "WowOffMdtim", 3); + prWifiVar->ucWowPwsMode = (UINT_8) wlanCfgGetUint32(prAdapter, "WowPwsMode", Param_PowerModeFast_PSP); + prWifiVar->ucListenDtimInterval = + (UINT_8) wlanCfgGetUint32(prAdapter, "ListenDtimInt", DEFAULT_LISTEN_INTERVAL_BY_DTIM_PERIOD); + /* prWifiVar->ucEapolOffload = (UINT_8) wlanCfgGetUint32(prAdapter, "EapolOffload", FEATURE_ENABLED); */ + + /* ucEapolOffload: only offload eapol rekey as suspen/resume case. */ + prWifiVar->ucEapolOffload = FEATURE_DISABLED; + +#if CFG_SUPPORT_REPLAY_DETECTION + prWifiVar->ucRpyDetectOffload = (UINT_8) wlanCfgGetUint32(prAdapter, "rpydetectoffload", FEATURE_ENABLED); +#endif + +#if CFG_WOW_SUPPORT + prAdapter->rWowCtrl.fgWowEnable = (UINT_8) wlanCfgGetUint32(prAdapter, "WowEnable", FEATURE_ENABLED); + prAdapter->rWowCtrl.ucScenarioId = (UINT_8) wlanCfgGetUint32(prAdapter, "WowScenarioId", 0); + prAdapter->rWowCtrl.ucBlockCount = (UINT_8) wlanCfgGetUint32(prAdapter, "WowPinCnt", 1); + prAdapter->rWowCtrl.astWakeHif[0].ucWakeupHif = + (UINT_8) wlanCfgGetUint32(prAdapter, "WowHif", ENUM_HIF_TYPE_GPIO); + prAdapter->rWowCtrl.astWakeHif[0].ucGpioPin = (UINT_8) wlanCfgGetUint32(prAdapter, "WowGpioPin", 0xFF); + prAdapter->rWowCtrl.astWakeHif[0].ucTriggerLvl = (UINT_8) wlanCfgGetUint32(prAdapter, "WowTriggerLevel", 3); + prAdapter->rWowCtrl.astWakeHif[0].u4GpioInterval = wlanCfgGetUint32(prAdapter, "GpioInterval", 0); +#endif + + /* SW Test Mode: Mainly used for Sigma */ + prWifiVar->u4SwTestMode = (UINT_8) wlanCfgGetUint32(prAdapter, "Sigma", ENUM_SW_TEST_MODE_NONE); + prWifiVar->ucCtrlFlagAssertPath = + (UINT_8) wlanCfgGetUint32(prAdapter, "AssertPath", DBG_ASSERT_PATH_DEFAULT); + prWifiVar->ucCtrlFlagDebugLevel = + (UINT_8) wlanCfgGetUint32(prAdapter, "AssertLevel", DBG_ASSERT_CTRL_LEVEL_DEFAULT); + prWifiVar->u4ScanCtrl = + (UINT_8) wlanCfgGetUint32(prAdapter, "ScanCtrl", SCN_CTRL_DEFAULT_SCAN_CTRL); + prWifiVar->ucScanChannelListenTime = + (UINT_8) wlanCfgGetUint32(prAdapter, "ScnChListenTime", 0); + + /* Wake lock related configuration */ + prWifiVar->u4WakeLockRxTimeout = + wlanCfgGetUint32(prAdapter, "WakeLockRxTO", WAKE_LOCK_RX_TIMEOUT); + prWifiVar->u4WakeLockThreadWakeup = + wlanCfgGetUint32(prAdapter, "WakeLockThreadTO", WAKE_LOCK_THREAD_WAKEUP_TIMEOUT); + + prWifiVar->ucSmartRTS = (UINT_8) wlanCfgGetUint32(prAdapter, "SmartRTS", 0); +#if 1 + /* add more cfg from RegInfo */ + prWifiVar->u4UapsdAcBmp = (UINT_32) wlanCfgGetUint32(prAdapter, "UapsdAcBmp", 0); + prWifiVar->u4MaxSpLen = (UINT_32) wlanCfgGetUint32(prAdapter, "MaxSpLen", 0); + prWifiVar->fgDisOnlineScan = (UINT_32) wlanCfgGetUint32(prAdapter, "DisOnlineScan", 0); + prWifiVar->fgDisBcnLostDetection = (UINT_32) wlanCfgGetUint32(prAdapter, "DisBcnLostDetection", 0); + prWifiVar->fgDisRoaming = (UINT_32) wlanCfgGetUint32(prAdapter, "DisRoaming", 0); + prWifiVar->fgEnArpFilter = (UINT_32) wlanCfgGetUint32(prAdapter, "EnArpFilter", FEATURE_ENABLED); +#endif + + /* Driver Flow Control Dequeue Quota. Now is only used by DBDC */ + prWifiVar->uDeQuePercentEnable = + (UINT_8) wlanCfgGetUint32(prAdapter, "DeQuePercentEnable", 1); + prWifiVar->u4DeQuePercentVHT80Nss1 = + (UINT_32) wlanCfgGetUint32(prAdapter, "DeQuePercentVHT80NSS1", QM_DEQUE_PERCENT_VHT80_NSS1); + prWifiVar->u4DeQuePercentVHT40Nss1 = + (UINT_32) wlanCfgGetUint32(prAdapter, "DeQuePercentVHT40NSS1", QM_DEQUE_PERCENT_VHT40_NSS1); + prWifiVar->u4DeQuePercentVHT20Nss1 = + (UINT_32) wlanCfgGetUint32(prAdapter, "DeQuePercentVHT20NSS1", QM_DEQUE_PERCENT_VHT20_NSS1); + prWifiVar->u4DeQuePercentHT40Nss1 = + (UINT_32) wlanCfgGetUint32(prAdapter, "DeQuePercentHT40NSS1", QM_DEQUE_PERCENT_HT40_NSS1); + prWifiVar->u4DeQuePercentHT20Nss1 = + (UINT_32) wlanCfgGetUint32(prAdapter, "DeQuePercentHT20NSS1", QM_DEQUE_PERCENT_HT20_NSS1); + + /* Support TDLS 5.5.4.2 optional case */ + prWifiVar->fgTdlsBufferSTASleep = (BOOLEAN) wlanCfgGetUint32(prAdapter, "TdlsBufferSTASleep", FEATURE_DISABLED); + /* Support USB Whole chip reset recover */ + prWifiVar->fgChipResetRecover = (BOOLEAN) wlanCfgGetUint32(prAdapter, "ChipResetRecover", FEATURE_ENABLED); + +#if CFG_SUPPORT_ANT_SELECT + prWifiVar->ucSpeIdxCtrl = (UINT_8) wlanCfgGetUint32(prAdapter, "SpeIdxCtrl", 2); +#endif + +#ifdef CFG_SUPPORT_ADJUST_JOIN_CH_REQ_INTERVAL + prWifiVar->u4AisJoinChReqIntervel = + (UINT_32) wlanCfgGetUint32(prAdapter, "AisJoinChReqIntervel", + AIS_JOIN_CH_REQUEST_INTERVAL); + if (AIS_JOIN_CH_REQUEST_MAX_INTERVAL < + prWifiVar->u4AisJoinChReqIntervel) + prWifiVar->u4AisJoinChReqIntervel = + AIS_JOIN_CH_REQUEST_MAX_INTERVAL; +#endif +} + +VOID wlanCfgSetSwCtrl(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i = 0; + CHAR aucKey[WLAN_CFG_VALUE_LEN_MAX]; + CHAR aucValue[WLAN_CFG_VALUE_LEN_MAX]; + + const CHAR acDelim[] = " "; + CHAR *pcPtr = NULL; + CHAR *pcDupValue = NULL; + UINT_32 au4Values[2]; + UINT_32 u4TokenCount = 0; + UINT_32 u4BufLen = 0; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo; + INT_32 u4Ret = 0; + + for (i = 0; i < WLAN_CFG_SET_SW_CTRL_LEN_MAX; i++) { + kalMemZero(aucValue, WLAN_CFG_VALUE_LEN_MAX); + kalMemZero(aucKey, WLAN_CFG_VALUE_LEN_MAX); + kalSnprintf(aucKey, sizeof(aucKey), "SwCtrl%d", i); + + /* get nothing */ + if (wlanCfgGet(prAdapter, aucKey, aucValue, "", 0) != WLAN_STATUS_SUCCESS) + continue; + if (!kalStrCmp(aucValue, "")) + continue; + + pcDupValue = aucValue; + u4TokenCount = 0; + + while ((pcPtr = kalStrSep((char **)(&pcDupValue), acDelim)) != NULL) { + + if (!kalStrCmp(pcPtr, "")) + continue; + + /* au4Values[u4TokenCount] = kalStrtoul(pcPtr, NULL, 0); */ + u4Ret = kalkStrtou32(pcPtr, 0, &(au4Values[u4TokenCount])); + if (u4Ret) + DBGLOG(INIT, LOUD, "parse au4Values error u4Ret=%d\n", u4Ret); + u4TokenCount++; + + /* Only need 2 tokens */ + if (u4TokenCount >= 2) + break; + } + + if (u4TokenCount != 2) + continue; + + rSwCtrlInfo.u4Id = au4Values[0]; + rSwCtrlInfo.u4Data = au4Values[1]; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), FALSE, FALSE, TRUE, &u4BufLen); + + } +} + +VOID wlanCfgSetChip(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i = 0; + CHAR aucKey[WLAN_CFG_VALUE_LEN_MAX]; + CHAR aucValue[WLAN_CFG_VALUE_LEN_MAX]; + + UINT_32 u4BufLen = 0; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T rChipConfigInfo; + + for (i = 0; i < WLAN_CFG_SET_CHIP_LEN_MAX; i++) { + kalMemZero(aucValue, WLAN_CFG_VALUE_LEN_MAX); + kalMemZero(aucKey, WLAN_CFG_VALUE_LEN_MAX); + kalSnprintf(aucKey, sizeof(aucKey), "SetChip%d", i); + + /* get nothing */ + if (wlanCfgGet(prAdapter, aucKey, aucValue, "", 0) != WLAN_STATUS_SUCCESS) + continue; + if (!kalStrCmp(aucValue, "")) + continue; + + kalMemZero(&rChipConfigInfo, sizeof(rChipConfigInfo)); + + rChipConfigInfo.ucType = CHIP_CONFIG_TYPE_WO_RESPONSE; + rChipConfigInfo.u2MsgSize = kalStrnLen(aucValue, WLAN_CFG_VALUE_LEN_MAX); + kalStrnCpy(rChipConfigInfo.aucCmd, aucValue, CHIP_CONFIG_RESP_SIZE); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetChipConfig, + &rChipConfigInfo, sizeof(rChipConfigInfo), FALSE, FALSE, TRUE, &u4BufLen); + } + +} + +VOID wlanCfgSetDebugLevel(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i = 0; + CHAR aucKey[WLAN_CFG_VALUE_LEN_MAX]; + CHAR aucValue[WLAN_CFG_VALUE_LEN_MAX]; + const CHAR acDelim[] = " "; + CHAR *pcDupValue; + CHAR *pcPtr = NULL; + + UINT_32 au4Values[2]; + UINT_32 u4TokenCount = 0; + UINT_32 u4DbgIdx = 0; + UINT_32 u4DbgMask = 0; + INT_32 u4Ret = 0; + + for (i = 0; i < WLAN_CFG_SET_DEBUG_LEVEL_LEN_MAX; i++) { + kalMemZero(aucValue, WLAN_CFG_VALUE_LEN_MAX); + kalMemZero(aucKey, WLAN_CFG_VALUE_LEN_MAX); + kalSnprintf(aucKey, sizeof(aucKey), "DbgLevel%d", i); + + /* get nothing */ + if (wlanCfgGet(prAdapter, aucKey, aucValue, "", 0) != WLAN_STATUS_SUCCESS) + continue; + if (!kalStrCmp(aucValue, "")) + continue; + + pcDupValue = aucValue; + u4TokenCount = 0; + + while ((pcPtr = kalStrSep((char **)(&pcDupValue), acDelim)) != NULL) { + + if (!kalStrCmp(pcPtr, "")) + continue; + + /* au4Values[u4TokenCount] = kalStrtoul(pcPtr, NULL, 0); */ + u4Ret = kalkStrtou32(pcPtr, 0, &(au4Values[u4TokenCount])); + if (u4Ret) + DBGLOG(INIT, LOUD, "parse au4Values error u4Ret=%d\n", u4Ret); + u4TokenCount++; + + /* Only need 2 tokens */ + if (u4TokenCount >= 2) + break; + } + + if (u4TokenCount != 2) + continue; + + u4DbgIdx = au4Values[0]; + u4DbgMask = au4Values[1]; + + /* DBG level special control */ + if (u4DbgIdx == 0xFFFFFFFF) { + wlanSetDebugLevel(DBG_ALL_MODULE_IDX, u4DbgMask); + DBGLOG(INIT, INFO, "Set ALL DBG module log level to [0x%02x]!", (UINT_8) u4DbgMask); + } else if (u4DbgIdx == 0xFFFFFFFE) { + wlanDebugInit(); + DBGLOG(INIT, INFO, "Reset ALL DBG module log level to DEFAULT!"); + } else if (u4DbgIdx < DBG_MODULE_NUM) { + wlanSetDebugLevel(u4DbgIdx, u4DbgMask); + DBGLOG(INIT, INFO, + "Set DBG module[%u] log level to [0x%02x]!", + u4DbgIdx, (UINT_8) u4DbgMask); + } + } + +} + +VOID wlanCfgSetCountryCode(IN P_ADAPTER_T prAdapter) +{ + CHAR aucValue[WLAN_CFG_VALUE_LEN_MAX]; + + /* Apply COUNTRY Config */ + if (wlanCfgGet(prAdapter, "Country", aucValue, "", 0) == WLAN_STATUS_SUCCESS) { + prAdapter->rWifiVar.rConnSettings.u2CountryCode = + (((UINT_16) aucValue[0]) << 8) | ((UINT_16) aucValue[1]); + + DBGLOG(INIT, TRACE, "u2CountryCode=0x%04x\n", + prAdapter->rWifiVar.rConnSettings.u2CountryCode); + + if (regd_is_single_sku_en()) { + rlmDomainOidSetCountry(prAdapter, aucValue, 2); + return; + } + + /* Force to re-search country code in country domains */ + prAdapter->prDomainInfo = NULL; + rlmDomainSendCmd(prAdapter, TRUE); + + /* Update supported channel list in channel table based on current country domain */ + wlanUpdateChannelTable(prAdapter->prGlueInfo); + } +} + +#if CFG_SUPPORT_CFG_FILE + +P_WLAN_CFG_ENTRY_T wlanCfgGetEntry(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, BOOLEAN fgGetCfgRec) +{ + + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + P_WLAN_CFG_T prWlanCfg = NULL; + P_WLAN_CFG_REC_T prWlanCfgRec = NULL; + UINT_32 i, u32MaxNum; + + if (fgGetCfgRec) { + prWlanCfgRec = prAdapter->prWlanCfgRec; + u32MaxNum = WLAN_CFG_REC_ENTRY_NUM_MAX; + ASSERT(prWlanCfgRec); + } else { + prWlanCfg = prAdapter->prWlanCfg; + u32MaxNum = WLAN_CFG_ENTRY_NUM_MAX; + ASSERT(prWlanCfg); + } + + + ASSERT(pucKey); + + prWlanCfgEntry = NULL; + + for (i = 0; i < u32MaxNum; i++) { + if (fgGetCfgRec) + prWlanCfgEntry = &prWlanCfgRec->arWlanCfgBuf[i]; + else + prWlanCfgEntry = &prWlanCfg->arWlanCfgBuf[i]; + + if (prWlanCfgEntry->aucKey[0] != '\0') { + DBGLOG(INIT, LOUD, "compare key %s saved key %s\n", pucKey, prWlanCfgEntry->aucKey); + if (kalStrnCmp(pucKey, prWlanCfgEntry->aucKey, WLAN_CFG_KEY_LEN_MAX - 1) == 0) + return prWlanCfgEntry; + } + } + + DBGLOG(INIT, TRACE, "wifi config there is no entry \'%s\'\n", pucKey); + return NULL; + +} + + +P_WLAN_CFG_ENTRY_T wlanCfgGetEntryByIndex(IN P_ADAPTER_T prAdapter, const UINT_8 ucIdx, UINT_32 flag) +{ + + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + P_WLAN_CFG_T prWlanCfg; + P_WLAN_CFG_REC_T prWlanCfgRec; + + + prWlanCfg = prAdapter->prWlanCfg; + prWlanCfgRec = prAdapter->prWlanCfgRec; + + ASSERT(prWlanCfg); + ASSERT(prWlanCfgRec); + + + prWlanCfgEntry = NULL; + + if (flag & WLAN_CFG_REC_FLAG_BIT) + prWlanCfgEntry = &prWlanCfgRec->arWlanCfgBuf[ucIdx]; + else + prWlanCfgEntry = &prWlanCfg->arWlanCfgBuf[ucIdx]; + + if (prWlanCfgEntry->aucKey[0] != '\0') { + DBGLOG(INIT, LOUD, "get Index(%d) saved key %s\n", ucIdx, prWlanCfgEntry->aucKey); + return prWlanCfgEntry; + } + + DBGLOG(INIT, TRACE, "wifi config there is no entry at index(%d)\n", ucIdx); + return NULL; + +} + + + +WLAN_STATUS wlanCfgGet(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, PCHAR pucValue, PCHAR pucValueDef, UINT_32 u4Flags) +{ + + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + P_WLAN_CFG_T prWlanCfg; + + prWlanCfg = prAdapter->prWlanCfg; + + ASSERT(prWlanCfg); + ASSERT(pucValue); + + /* Find the exist */ + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey, FALSE); + + if (prWlanCfgEntry) { + kalStrnCpy(pucValue, prWlanCfgEntry->aucValue, WLAN_CFG_VALUE_LEN_MAX - 1); + return WLAN_STATUS_SUCCESS; + } + if (pucValueDef) + kalStrnCpy(pucValue, pucValueDef, WLAN_CFG_VALUE_LEN_MAX - 1); + return WLAN_STATUS_FAILURE; + + +} + +VOID wlanCfgRecordValue(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, UINT_32 u4Value) +{ + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + UINT_8 aucBuf[WLAN_CFG_VALUE_LEN_MAX]; + + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey, TRUE); + + kalMemZero(aucBuf, sizeof(aucBuf)); + + kalSnprintf(aucBuf, WLAN_CFG_VALUE_LEN_MAX, "0x%x", (unsigned int)u4Value); + + wlanCfgSet(prAdapter, pucKey, aucBuf, 1); +} + + + +UINT_32 wlanCfgGetUint32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, UINT_32 u4ValueDef) +{ + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + P_WLAN_CFG_T prWlanCfg; + UINT_32 u4Value; + INT_32 u4Ret; + + prWlanCfg = prAdapter->prWlanCfg; + + ASSERT(prWlanCfg); + + u4Value = u4ValueDef; + /* Find the exist */ + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey, FALSE); + + if (prWlanCfgEntry) { + /* u4Ret = kalStrtoul(prWlanCfgEntry->aucValue, NULL, 0); */ + u4Ret = kalkStrtou32(prWlanCfgEntry->aucValue, 0, &u4Value); + if (u4Ret) + DBGLOG(INIT, LOUD, "parse aucValue error u4Ret=%d\n", u4Ret); + } + + wlanCfgRecordValue(prAdapter, pucKey, u4Value); + + return u4Value; +} + +INT_32 wlanCfgGetInt32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, INT_32 i4ValueDef) +{ + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + P_WLAN_CFG_T prWlanCfg; + INT_32 i4Value = 0; + INT_32 i4Ret = 0; + + prWlanCfg = prAdapter->prWlanCfg; + + ASSERT(prWlanCfg); + + i4Value = i4ValueDef; + /* Find the exist */ + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey, FALSE); + + if (prWlanCfgEntry) { + /* i4Ret = kalStrtol(prWlanCfgEntry->aucValue, NULL, 0); */ + i4Ret = kalkStrtos32(prWlanCfgEntry->aucValue, 0, &i4Value); + if (i4Ret) + DBGLOG(INIT, LOUD, "parse aucValue error i4Ret=%d\n", i4Ret); + } + + wlanCfgRecordValue(prAdapter, pucKey, (UINT_32)i4Value); + + return i4Value; +} + +WLAN_STATUS wlanCfgSet(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, PCHAR pucValue, UINT_32 u4Flags) +{ + + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + P_WLAN_CFG_T prWlanCfg = NULL; + P_WLAN_CFG_REC_T prWlanCfgRec = NULL; + UINT_32 u4EntryIndex; + UINT_32 i; + UINT_8 ucExist; + BOOLEAN fgGetCfgRec = FALSE; + + + fgGetCfgRec = u4Flags & WLAN_CFG_REC_FLAG_BIT; + + ASSERT(pucKey); + + /* Find the exist */ + ucExist = 0; + if (fgGetCfgRec) { + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey, TRUE); + prWlanCfgRec = prAdapter->prWlanCfgRec; + ASSERT(prWlanCfgRec); + } else { + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey, FALSE); + prWlanCfg = prAdapter->prWlanCfg; + ASSERT(prWlanCfg); + } + + if (!prWlanCfgEntry) { + /* Find the empty */ + for (i = 0; i < WLAN_CFG_ENTRY_NUM_MAX; i++) { + if (fgGetCfgRec) + prWlanCfgEntry = &prWlanCfgRec->arWlanCfgBuf[i]; + else + prWlanCfgEntry = &prWlanCfg->arWlanCfgBuf[i]; + if (prWlanCfgEntry->aucKey[0] == '\0') + break; + } + + u4EntryIndex = i; + if (u4EntryIndex < WLAN_CFG_ENTRY_NUM_MAX) { + if (fgGetCfgRec) + prWlanCfgEntry = &prWlanCfgRec->arWlanCfgBuf[u4EntryIndex]; + else + prWlanCfgEntry = &prWlanCfg->arWlanCfgBuf[u4EntryIndex]; + kalMemZero(prWlanCfgEntry, sizeof(WLAN_CFG_ENTRY_T)); + } else { + prWlanCfgEntry = NULL; + DBGLOG(INIT, ERROR, "wifi config there is no empty entry\n"); + } + } /* !prWlanCfgEntry */ + else + ucExist = 1; + + if (prWlanCfgEntry) { + if (ucExist == 0) { + kalStrnCpy(prWlanCfgEntry->aucKey, pucKey, WLAN_CFG_KEY_LEN_MAX - 1); + prWlanCfgEntry->aucKey[WLAN_CFG_KEY_LEN_MAX - 1] = '\0'; + } + + if (pucValue && pucValue[0] != '\0') { + kalStrnCpy(prWlanCfgEntry->aucValue, pucValue, WLAN_CFG_VALUE_LEN_MAX - 1); + prWlanCfgEntry->aucValue[WLAN_CFG_VALUE_LEN_MAX - 1] = '\0'; + + if (ucExist) { + if (prWlanCfgEntry->pfSetCb) + prWlanCfgEntry->pfSetCb(prAdapter, + prWlanCfgEntry->aucKey, + prWlanCfgEntry->aucValue, prWlanCfgEntry->pPrivate, 0); + } + } else { + /* Call the pfSetCb if value is empty ? */ + /* remove the entry if value is empty */ + kalMemZero(prWlanCfgEntry, sizeof(WLAN_CFG_ENTRY_T)); + } + + } + /* prWlanCfgEntry */ + if (prWlanCfgEntry) { + /* this will lead the log too much ,and modify the log level*/ + DBGLOG(INIT, TRACE, "Set wifi config exist %u \'%s\' \'%s\'\n", + ucExist, prWlanCfgEntry->aucKey, prWlanCfgEntry->aucValue); + return WLAN_STATUS_SUCCESS; + } + if (pucKey) + DBGLOG(INIT, ERROR, "Set wifi config error key \'%s\'\n", pucKey); + + if (pucValue) + DBGLOG(INIT, ERROR, "Set wifi config error value \'%s\'\n", pucValue); + + return WLAN_STATUS_FAILURE; + + +} + +WLAN_STATUS +wlanCfgSetCb(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, WLAN_CFG_SET_CB pfSetCb, void *pPrivate, UINT_32 u4Flags) +{ + + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + P_WLAN_CFG_T prWlanCfg; + + prWlanCfg = prAdapter->prWlanCfg; + ASSERT(prWlanCfg); + + /* Find the exist */ + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey, FALSE); + + if (prWlanCfgEntry) { + prWlanCfgEntry->pfSetCb = pfSetCb; + prWlanCfgEntry->pPrivate = pPrivate; + } + + if (prWlanCfgEntry) + return WLAN_STATUS_SUCCESS; + else + return WLAN_STATUS_FAILURE; + +} + +WLAN_STATUS wlanCfgSetUint32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, UINT_32 u4Value) +{ + + P_WLAN_CFG_T prWlanCfg; + UINT_8 aucBuf[WLAN_CFG_VALUE_LEN_MAX]; + + prWlanCfg = prAdapter->prWlanCfg; + + ASSERT(prWlanCfg); + + kalMemZero(aucBuf, sizeof(aucBuf)); + + kalSnprintf(aucBuf, WLAN_CFG_VALUE_LEN_MAX, "0x%x", (unsigned int)u4Value); + + return wlanCfgSet(prAdapter, pucKey, aucBuf, 0); +} + +enum { + STATE_EOF = 0, + STATE_TEXT = 1, + STATE_NEWLINE = 2 +}; + +struct WLAN_CFG_PARSE_STATE_S { + CHAR *ptr; + CHAR *text; +#if CFG_SUPPORT_EASY_DEBUG + UINT_32 textsize; +#endif + INT_32 nexttoken; + UINT_32 maxSize; +}; + +INT_32 wlanCfgFindNextToken(struct WLAN_CFG_PARSE_STATE_S *state) +{ + CHAR *x = state->ptr; + CHAR *s; + + if (state->nexttoken) { + INT_32 t = state->nexttoken; + + state->nexttoken = 0; + return t; + } + + for (;;) { + switch (*x) { + case 0: + state->ptr = x; + return STATE_EOF; + case '\n': + x++; + state->ptr = x; + return STATE_NEWLINE; + case ' ': + case ',': + /*case ':': should not including : , mac addr would be fail*/ + case '\t': + case '\r': + x++; + continue; + case '#': + while (*x && (*x != '\n')) + x++; + if (*x == '\n') { + state->ptr = x + 1; + return STATE_NEWLINE; + } + state->ptr = x; + return STATE_EOF; + + default: + goto text; + } + } + +textdone: + state->ptr = x; + *s = 0; + return STATE_TEXT; +text: + state->text = s = x; +textresume: + for (;;) { + switch (*x) { + case 0: + goto textdone; + case ' ': + case ',': + /*case ':': + */ + case '\t': + case '\r': + x++; + goto textdone; + case '\n': + state->nexttoken = STATE_NEWLINE; + x++; + goto textdone; + case '"': + x++; + for (;;) { + switch (*x) { + case 0: + /* unterminated quoted thing */ + state->ptr = x; + return STATE_EOF; + case '"': + x++; + goto textresume; + default: + *s++ = *x++; + } + } + break; + case '\\': + x++; + switch (*x) { + case 0: + goto textdone; + case 'n': + *s++ = '\n'; + break; + case 'r': + *s++ = '\r'; + break; + case 't': + *s++ = '\t'; + break; + case '\\': + *s++ = '\\'; + break; + case '\r': + /* \ -> line continuation */ + if (x[1] != '\n') { + x++; + continue; + } + case '\n': + /* \ -> line continuation */ + x++; + /* eat any extra whitespace */ + while ((*x == ' ') || (*x == '\t')) + x++; + continue; + default: + /* unknown escape -- just copy */ + *s++ = *x++; + } + continue; + default: + *s++ = *x++; +#if CFG_SUPPORT_EASY_DEBUG + state->textsize++; +#endif + } + } + return STATE_EOF; +} + +WLAN_STATUS wlanCfgParseArgument(CHAR *cmdLine, INT_32 *argc, CHAR *argv[]) +{ + struct WLAN_CFG_PARSE_STATE_S state; + CHAR **args; + INT_32 nargs; + + if (cmdLine == NULL || argc == NULL || argv == NULL) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + args = argv; + nargs = 0; + state.ptr = cmdLine; + state.nexttoken = 0; + state.maxSize = 0; +#if CFG_SUPPORT_EASY_DEBUG + state.textsize = 0; +#endif + + if (kalStrnLen(cmdLine, 512) >= 512) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + for (;;) { + switch (wlanCfgFindNextToken(&state)) { + case STATE_EOF: + goto exit; + case STATE_NEWLINE: + goto exit; + case STATE_TEXT: + if (nargs < WLAN_CFG_ARGV_MAX) + args[nargs++] = state.text; + break; + } + } + +exit: + *argc = nargs; + return WLAN_STATUS_SUCCESS; +} + +#if CFG_WOW_SUPPORT +WLAN_STATUS wlanCfgParseArgumentLong(CHAR *cmdLine, INT_32 *argc, CHAR *argv[]) +{ + struct WLAN_CFG_PARSE_STATE_S state; + CHAR **args; + INT_32 nargs; + + if (cmdLine == NULL || argc == NULL || argv == NULL) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + args = argv; + nargs = 0; + state.ptr = cmdLine; + state.nexttoken = 0; + state.maxSize = 0; +#if CFG_SUPPORT_EASY_DEBUG + state.textsize = 0; +#endif + + if (kalStrnLen(cmdLine, 512) >= 512) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + for (;;) { + switch (wlanCfgFindNextToken(&state)) { + case STATE_EOF: + goto exit; + case STATE_NEWLINE: + goto exit; + case STATE_TEXT: + if (nargs < WLAN_CFG_ARGV_MAX_LONG) + args[nargs++] = state.text; + break; + } + } + +exit: + *argc = nargs; + return WLAN_STATUS_SUCCESS; +} +#endif + +WLAN_STATUS +wlanCfgParseAddEntry(IN P_ADAPTER_T prAdapter, + PUINT_8 pucKeyHead, PUINT_8 pucKeyTail, PUINT_8 pucValueHead, PUINT_8 pucValueTail) +{ + + UINT_8 aucKey[WLAN_CFG_KEY_LEN_MAX]; + UINT_8 aucValue[WLAN_CFG_VALUE_LEN_MAX]; + UINT_32 u4Len; + + kalMemZero(aucKey, sizeof(aucKey)); + kalMemZero(aucValue, sizeof(aucValue)); + + if ((pucKeyHead == NULL) + || (pucValueHead == NULL) + ) + return WLAN_STATUS_FAILURE; + + if (pucKeyTail) { + if (pucKeyHead > pucKeyTail) + return WLAN_STATUS_FAILURE; + u4Len = pucKeyTail - pucKeyHead + 1; + } else + u4Len = kalStrnLen(pucKeyHead, WLAN_CFG_KEY_LEN_MAX - 1); + + if (u4Len >= WLAN_CFG_KEY_LEN_MAX) + u4Len = WLAN_CFG_KEY_LEN_MAX - 1; + + kalStrnCpy(aucKey, pucKeyHead, u4Len); + + if (pucValueTail) { + if (pucValueHead > pucValueTail) + return WLAN_STATUS_FAILURE; + u4Len = pucValueTail - pucValueHead + 1; + } else + u4Len = kalStrnLen(pucValueHead, WLAN_CFG_VALUE_LEN_MAX - 1); + + if (u4Len >= WLAN_CFG_VALUE_LEN_MAX) + u4Len = WLAN_CFG_VALUE_LEN_MAX - 1; + + kalStrnCpy(aucValue, pucValueHead, u4Len); + + return wlanCfgSet(prAdapter, aucKey, aucValue, 0); +} + +enum { + WAIT_KEY_HEAD = 0, + WAIT_KEY_TAIL, + WAIT_VALUE_HEAD, + WAIT_VALUE_TAIL, + WAIT_COMMENT_TAIL +}; + +#if CFG_SUPPORT_EASY_DEBUG + +INT_8 atoi(UCHAR ch) +{ + if (ch >= 'a' && ch <= 'f') + return ch - 87; + else if (ch >= 'A' && ch <= 'F') + return ch - 55; + else if (ch >= '0' && ch <= '9') + return ch - 48; + + return 0; +} + +WLAN_STATUS wlanCfgParseToFW(PCHAR *args, PCHAR args_size, UCHAR nargs, PCHAR buffer, UCHAR times) +{ + PUCHAR data = NULL; + char ch; + INT_32 i = 0, j = 0; + UINT_32 bufferindex = 0, base = 0; + UINT_32 sum = 0, startOffset = 0; + CMD_FORMAT_V1_T cmd_v1; + + memset(&cmd_v1, 0, sizeof(CMD_FORMAT_V1_T)); + +#if 0 + cmd_v1.itemType = atoi(*args[ED_ITEMTYPE_SITE]); +#else + cmd_v1.itemType = ITEM_TYPE_DEC; +#endif + if (buffer == NULL || + args_size[ED_STRING_SITE] == 0 || + args_size[ED_VALUE_SITE] == 0 || + (cmd_v1.itemType < ITEM_TYPE_DEC || cmd_v1.itemType > ITEM_TYPE_STR)) { + DBGLOG(INIT, ERROR, "cfg args wrong\n"); + return WLAN_STATUS_FAILURE; + } + + cmd_v1.itemStringLength = args_size[ED_STRING_SITE]; + strncpy(cmd_v1.itemString, args[ED_STRING_SITE], cmd_v1.itemStringLength); + DBGLOG(INIT, INFO, "itemString:"); + for (i = 0; i < cmd_v1.itemStringLength; i++) + DBGLOG(INIT, INFO, "%c", cmd_v1.itemString[i]); + DBGLOG(INIT, INFO, "\n"); + + DBGLOG(INIT, INFO, "cmd_v1.itemType = %d\n", cmd_v1.itemType); + if (cmd_v1.itemType == ITEM_TYPE_DEC || cmd_v1.itemType == ITEM_TYPE_HEX) { + data = args[ED_VALUE_SITE]; + + switch (cmd_v1.itemType) { + case ITEM_TYPE_DEC: + base = 10; + startOffset = 0; + break; + case ITEM_TYPE_HEX: + ch = *data; + if (args_size[ED_VALUE_SITE] < 3 || ch != '0') { + DBGLOG(INIT, WARN, "Hex args must have prefix '0x'\n"); + return WLAN_STATUS_FAILURE; + } + + data++; + ch = *data; + if (ch != 'x' && ch != 'X') { + DBGLOG(INIT, WARN, "Hex args must have prefix '0x'\n"); + return WLAN_STATUS_FAILURE; + } + data++; + base = 16; + startOffset = 2; + break; + } + + for (j = args_size[ED_VALUE_SITE] - 1 - startOffset; j >= 0; j--) { + sum = sum * base + atoi(*data); + DBGLOG(INIT, WARN, "size:%d data[%d]=%u, sum=%u\n", + args_size[ED_VALUE_SITE], j, atoi(*data), sum); + + data++; + } + + bufferindex = 0; + do { + cmd_v1.itemValue[bufferindex++] = sum & 0xFF; + sum = sum >> 8; + } while (sum > 0); + cmd_v1.itemValueLength = bufferindex; + } else if (cmd_v1.itemType == ITEM_TYPE_STR) { + cmd_v1.itemValueLength = args_size[ED_VALUE_SITE]; + strncpy(cmd_v1.itemValue, args[ED_VALUE_SITE], cmd_v1.itemValueLength); + } + + DBGLOG(INIT, INFO, "Length = %d itemValue:", cmd_v1.itemValueLength); + for (i = cmd_v1.itemValueLength - 1; i >= 0; i--) + DBGLOG(INIT, ERROR, "%d,", cmd_v1.itemValue[i]); + DBGLOG(INIT, INFO, "\n"); + memcpy(((P_CMD_FORMAT_V1_T)buffer)+times, &cmd_v1, sizeof(CMD_FORMAT_V1_T)); + + return WLAN_STATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to send WLAN feature options to firmware +* +* @param prAdapter Pointer of ADAPTER_T +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanFeatureToFw(IN P_ADAPTER_T prAdapter) +{ + + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + UINT_32 i; + CMD_HEADER_T rCmdV1Header; + WLAN_STATUS rStatus; + CMD_FORMAT_V1_T rCmd_v1; + UCHAR ucTimes = 0; + + + + rCmdV1Header.cmdType = CMD_TYPE_SET; + rCmdV1Header.cmdVersion = CMD_VER_1; + rCmdV1Header.cmdBufferLen = 0; + rCmdV1Header.itemNum = 0; + + kalMemSet(rCmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); + kalMemSet(&rCmd_v1, 0, sizeof(CMD_FORMAT_V1_T)); + + + prWlanCfgEntry = NULL; + + for (i = 0; i < WLAN_CFG_ENTRY_NUM_MAX; i++) { + + prWlanCfgEntry = wlanCfgGetEntryByIndex(prAdapter, i, 0); + + if (prWlanCfgEntry) { + + rCmd_v1.itemType = ITEM_TYPE_STR; + + + /*send string format to firmware */ + rCmd_v1.itemStringLength = kalStrLen(prWlanCfgEntry->aucKey); + kalMemZero(rCmd_v1.itemString, MAX_CMD_NAME_MAX_LENGTH); + kalMemCopy(rCmd_v1.itemString, prWlanCfgEntry->aucKey, rCmd_v1.itemStringLength); + + + rCmd_v1.itemValueLength = kalStrLen(prWlanCfgEntry->aucValue); + kalMemZero(rCmd_v1.itemValue, MAX_CMD_VALUE_MAX_LENGTH); + kalMemCopy(rCmd_v1.itemValue, prWlanCfgEntry->aucValue, rCmd_v1.itemValueLength); + + + + DBGLOG(INIT, INFO, "Send key word (%s) WITH (%s) to firmware\n", + rCmd_v1.itemString, rCmd_v1.itemValue); + + kalMemCopy(((P_CMD_FORMAT_V1_T)rCmdV1Header.buffer)+ucTimes, + &rCmd_v1, sizeof(CMD_FORMAT_V1_T)); + + + ucTimes++; + rCmdV1Header.cmdBufferLen += sizeof(CMD_FORMAT_V1_T); + rCmdV1Header.itemNum += ucTimes; + + + if (ucTimes == MAX_CMD_ITEM_MAX) { + /* Send to FW */ + rCmdV1Header.itemNum = ucTimes; + + rStatus = wlanSendSetQueryCmd( + prAdapter, /* prAdapter */ + CMD_ID_GET_SET_CUSTOMER_CFG, /* 0x70 */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler*/ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_HEADER_T), /* u4SetQueryInfoLen */ + (PUINT_8)&rCmdV1Header, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus == WLAN_STATUS_FAILURE) + DBGLOG(INIT, INFO, "[Fail]kalIoctl wifiSefCFG fail 0x%x\n", rStatus); + + DBGLOG(INIT, INFO, "kalIoctl wifiSefCFG num:%d\n", ucTimes); + kalMemSet(rCmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); + rCmdV1Header.cmdBufferLen = 0; + ucTimes = 0; + } + + + } else { + break; + } + } + + + if (ucTimes != 0) { + /* Send to FW */ + rCmdV1Header.itemNum = ucTimes; + + DBGLOG(INIT, INFO, "cmdV1Header.itemNum:%d\n", rCmdV1Header.itemNum); + + rStatus = wlanSendSetQueryCmd( + prAdapter, /* prAdapter */ + CMD_ID_GET_SET_CUSTOMER_CFG, /* 0x70 */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler*/ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_HEADER_T), /* u4SetQueryInfoLen */ + (PUINT_8)&rCmdV1Header, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus == WLAN_STATUS_FAILURE) + DBGLOG(INIT, INFO, "[Fail]kalIoctl wifiSefCFG fail 0x%x\n", rStatus); + + DBGLOG(INIT, INFO, "kalIoctl wifiSefCFG num:%d\n", ucTimes); + kalMemSet(rCmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); + rCmdV1Header.cmdBufferLen = 0; + ucTimes = 0; + } + +} + + + +WLAN_STATUS wlanCfgParse(IN P_ADAPTER_T prAdapter, PUINT_8 pucConfigBuf, UINT_32 u4ConfigBufLen, BOOLEAN isFwConfig) +{ + struct WLAN_CFG_PARSE_STATE_S state; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + PPCHAR ppcArgs; + INT_32 i4Nargs; + CHAR arcArgv_size[WLAN_CFG_ARGV_MAX]; + UCHAR ucTimes = 0; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + CMD_HEADER_T rCmdV1Header; + CHAR ucTmp[WLAN_CFG_VALUE_LEN_MAX]; + UINT_8 i; + + PUINT_8 pucCurrBuf = ucTmp; + UINT_32 u4CurrSize = ARRAY_SIZE(ucTmp); + UINT_32 u4RetSize = 0; + + rCmdV1Header.cmdType = CMD_TYPE_SET; + rCmdV1Header.cmdVersion = CMD_VER_1; + rCmdV1Header.cmdBufferLen = 0; + kalMemSet(rCmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); + + if (pucConfigBuf == NULL) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + if (kalStrnLen(pucConfigBuf, 4000) >= 4000) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + if (u4ConfigBufLen == 0) + return WLAN_STATUS_FAILURE; + + ppcArgs = apcArgv; + i4Nargs = 0; + state.ptr = pucConfigBuf; + state.nexttoken = 0; + state.textsize = 0; + state.maxSize = u4ConfigBufLen; + DBGLOG(INIT, INFO, "wlanCfgParse()\n"); + + for (;;) { + switch (wlanCfgFindNextToken(&state)) { + case STATE_EOF: + if (i4Nargs < 2) + goto exit; + + DBGLOG(INIT, INFO, "STATE_EOF\n"); + + /*3 parmeter mode transforation */ + if (i4Nargs == 3 && !isFwConfig && + arcArgv_size[0] == 1) { + + /*parsing and transfer the format + *Format 1:Dec 2.Hex 3.String + */ + + kalMemZero(ucTmp, WLAN_CFG_VALUE_LEN_MAX); + pucCurrBuf = ucTmp; + u4CurrSize = ARRAY_SIZE(ucTmp); + + if ((*ppcArgs[0] == '2') && (*(ppcArgs[2]) != '0') && (*(ppcArgs[2]+1) != 'x')) { + DBGLOG(INIT, WARN, "config file got a hex format\n"); + kalSnprintf(pucCurrBuf, u4CurrSize, "0x%s", ppcArgs[2]); + } else { + kalSnprintf(pucCurrBuf, u4CurrSize, "%s", ppcArgs[2]); + } + DBGLOG(INIT, WARN, "[3 parameter mode][%s],[%s],[%s]\n", ppcArgs[0], ppcArgs[1], ucTmp); + wlanCfgParseAddEntry(prAdapter, ppcArgs[1], NULL, ucTmp, NULL); + kalMemSet(arcArgv_size, 0, WLAN_CFG_ARGV_MAX); + kalMemSet(apcArgv, 0, + WLAN_CFG_ARGV_MAX * sizeof(int8_t *)); + i4Nargs = 0; + goto exit; + + } + + wlanCfgParseAddEntry(prAdapter, ppcArgs[0], NULL, ppcArgs[1], NULL); + + if (isFwConfig) { + + WLAN_STATUS ret; + + + ret = wlanCfgParseToFW(ppcArgs, arcArgv_size, i4Nargs, rCmdV1Header.buffer, ucTimes); + if (ret == WLAN_STATUS_SUCCESS) { + ucTimes++; + rCmdV1Header.cmdBufferLen += sizeof(CMD_FORMAT_V1_T); + } + } + + goto exit; + + + case STATE_NEWLINE: + if (i4Nargs < 2) + break; + + DBGLOG(INIT, INFO, "STATE_NEWLINE\n"); +#if 1 + /*3 parmeter mode transforation */ + if (i4Nargs == 3 && !isFwConfig && + arcArgv_size[0] == 1) { + + /*parsing and transfer the format + *Format 1:Dec 2.Hex 3.String + */ + kalMemZero(ucTmp, WLAN_CFG_VALUE_LEN_MAX); + pucCurrBuf = ucTmp; + u4CurrSize = ARRAY_SIZE(ucTmp); + + if ((*ppcArgs[0] == '2') && (*(ppcArgs[2]) != '0') && (*(ppcArgs[2]+1) != 'x')) { + DBGLOG(INIT, WARN, "config file got a hex format\n"); + kalSnprintf(pucCurrBuf, u4CurrSize, "0x%s", ppcArgs[2]); + + } else { + kalSnprintf(pucCurrBuf, u4CurrSize, "%s", ppcArgs[2]); + } + + + DBGLOG(INIT, WARN, "[3 parameter mode][%s],[%s],[%s]\n", ppcArgs[0], ppcArgs[1], ucTmp); + wlanCfgParseAddEntry(prAdapter, ppcArgs[1], NULL, ucTmp, NULL); + kalMemSet(arcArgv_size, 0, WLAN_CFG_ARGV_MAX); + kalMemSet(apcArgv, 0, + WLAN_CFG_ARGV_MAX * sizeof(int8_t *)); + i4Nargs = 0; + break; + + } +#if 1 + /*combine the argument to save in temp*/ + pucCurrBuf = ucTmp; + u4CurrSize = ARRAY_SIZE(ucTmp); + + kalMemZero(ucTmp, WLAN_CFG_VALUE_LEN_MAX); + + if (i4Nargs == 2) { + /*no space for it, driver can't accept space in the end of the line*/ + /*ToDo: skip the space when parsing*/ + kalSnprintf(pucCurrBuf, u4CurrSize, "%s", ppcArgs[1]); + } else { + for (i = 1; i < i4Nargs; i++) { + if (u4CurrSize <= 1) { + DBGLOG(INIT, ERROR, "write to pucCurrBuf out of bound, i=%d\n", i); + break; + } + u4RetSize = scnprintf(pucCurrBuf, u4CurrSize, "%s ", ppcArgs[i]); + pucCurrBuf += u4RetSize; + u4CurrSize -= u4RetSize; + } + } + + DBGLOG(INIT, INFO, "Save to driver temp buffer as [%s]\n", ucTmp); + wlanCfgParseAddEntry(prAdapter, ppcArgs[0], NULL, ucTmp, NULL); +#else + wlanCfgParseAddEntry(prAdapter, ppcArgs[0], NULL, ppcArgs[1], NULL); +#endif + + if (isFwConfig) { + + WLAN_STATUS ret; + + ret = wlanCfgParseToFW(ppcArgs, arcArgv_size, i4Nargs, rCmdV1Header.buffer, ucTimes); + if (ret == WLAN_STATUS_SUCCESS) { + ucTimes++; + rCmdV1Header.cmdBufferLen += sizeof(CMD_FORMAT_V1_T); + } + + if (ucTimes == MAX_CMD_ITEM_MAX) { + /* Send to FW */ + rCmdV1Header.itemNum = ucTimes; + rStatus = wlanSendSetQueryCmd( + prAdapter, /* prAdapter */ + CMD_ID_GET_SET_CUSTOMER_CFG, /* 0x70 */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler*/ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_HEADER_T), /* u4SetQueryInfoLen */ + (PUINT_8) &rCmdV1Header, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus == WLAN_STATUS_FAILURE) + DBGLOG(INIT, INFO, "kalIoctl wifiSefCFG fail 0x%x\n", rStatus); + DBGLOG(INIT, INFO, "kalIoctl wifiSefCFG num:%d X\n", ucTimes); + kalMemSet(rCmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); + rCmdV1Header.cmdBufferLen = 0; + ucTimes = 0; + } + + } + +#endif + kalMemSet(arcArgv_size, 0, WLAN_CFG_ARGV_MAX); + kalMemSet(apcArgv, 0, + WLAN_CFG_ARGV_MAX * sizeof(int8_t *)); + i4Nargs = 0; + break; + + case STATE_TEXT: + if (i4Nargs < WLAN_CFG_ARGV_MAX) { + ppcArgs[i4Nargs++] = state.text; + arcArgv_size[i4Nargs-1] = state.textsize; + state.textsize = 0; + DBGLOG(INIT, INFO, " nargs= %d STATE_TEXT = %s, SIZE = %d\n", + i4Nargs-1, ppcArgs[i4Nargs-1], arcArgv_size[i4Nargs-1]); + } + break; + } + } + +exit: + if (ucTimes != 0 && isFwConfig) { + /* Send to FW */ + rCmdV1Header.itemNum = ucTimes; + + DBGLOG(INIT, INFO, "cmdV1Header.itemNum:%d\n", rCmdV1Header.itemNum); + rStatus = wlanSendSetQueryCmd( + prAdapter, /* prAdapter */ + CMD_ID_GET_SET_CUSTOMER_CFG, /* 0x70 */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler*/ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_HEADER_T), /* u4SetQueryInfoLen */ + (PUINT_8) &rCmdV1Header, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus == WLAN_STATUS_FAILURE) + DBGLOG(INIT, WARN, "kalIoctl wifiSefCFG fail 0x%x\n", rStatus); + + DBGLOG(INIT, WARN, "kalIoctl wifiSefCFG num:%d X\n", ucTimes); + kalMemSet(rCmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); + rCmdV1Header.cmdBufferLen = 0; + ucTimes = 0; + } + return WLAN_STATUS_SUCCESS; +} + +#else +WLAN_STATUS wlanCfgParse(IN P_ADAPTER_T prAdapter, PUINT_8 pucConfigBuf, UINT_32 u4ConfigBufLen) +{ + + struct WLAN_CFG_PARSE_STATE_S state; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + CHAR **args; + INT_32 nargs; + + if (pucConfigBuf == NULL) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + if (kalStrnLen(pucConfigBuf, 4000) >= 4000) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + if (u4ConfigBufLen == 0) + return WLAN_STATUS_FAILURE; + args = apcArgv; + nargs = 0; + state.ptr = pucConfigBuf; + state.nexttoken = 0; + state.maxSize = u4ConfigBufLen; + + for (;;) { + switch (wlanCfgFindNextToken(&state)) { + case STATE_EOF: + if (nargs > 1) + wlanCfgParseAddEntry(prAdapter, args[0], NULL, args[1], NULL); + goto exit; + case STATE_NEWLINE: + if (nargs > 1) + wlanCfgParseAddEntry(prAdapter, args[0], NULL, args[1], NULL); + /*args[0] is parameter, args[1] is the value*/ + nargs = 0; + break; + case STATE_TEXT: + if (nargs < WLAN_CFG_ARGV_MAX) + args[nargs++] = state.text; + break; + } + } + +exit: + return WLAN_STATUS_SUCCESS; + +#if 0 + /* Old version */ + UINT_32 i; + UINT_8 c; + PUINT_8 pbuf; + UINT_8 ucState; + PUINT_8 pucKeyTail = NULL; + PUINT_8 pucKeyHead = NULL; + PUINT_8 pucValueHead = NULL; + PUINT_8 pucValueTail = NULL; + + ucState = WAIT_KEY_HEAD; + pbuf = pucConfigBuf; + + for (i = 0; i < u4ConfigBufLen; i++) { + c = pbuf[i]; + if (c == '\r' || c == '\n') { + + if (ucState == WAIT_VALUE_TAIL) { + /* Entry found */ + if (pucValueHead) + wlanCfgParseAddEntry(prAdapter, pucKeyHead, pucKeyTail, + pucValueHead, pucValueTail); + } + ucState = WAIT_KEY_HEAD; + pucKeyTail = NULL; + pucKeyHead = NULL; + pucValueHead = NULL; + pucValueTail = NULL; + + } else if (c == '=') { + if (ucState == WAIT_KEY_TAIL) { + pucKeyTail = &pbuf[i - 1]; + ucState = WAIT_VALUE_HEAD; + } + } else if (c == ' ' || c == '\t') { + if (ucState == WAIT_KEY_TAIL) { + pucKeyTail = &pbuf[i - 1]; + ucState = WAIT_VALUE_HEAD; + } + } else { + + if (c == '#') { + /* comments */ + if (ucState == WAIT_KEY_HEAD) + ucState = WAIT_COMMENT_TAIL; + else if (ucState == WAIT_VALUE_TAIL) + pucValueTail = &pbuf[i]; + + } else { + if (ucState == WAIT_KEY_HEAD) { + pucKeyHead = &pbuf[i]; + pucKeyTail = &pbuf[i]; + ucState = WAIT_KEY_TAIL; + } else if (ucState == WAIT_VALUE_HEAD) { + pucValueHead = &pbuf[i]; + pucValueTail = &pbuf[i]; + ucState = WAIT_VALUE_TAIL; + } else if (ucState == WAIT_VALUE_TAIL) + pucValueTail = &pbuf[i]; + } + } + + } /* for */ + + if (ucState == WAIT_VALUE_TAIL) { + /* Entry found */ + if (pucValueTail) + wlanCfgParseAddEntry(prAdapter, pucKeyHead, pucKeyTail, pucValueHead, pucValueTail); + } +#endif + + return WLAN_STATUS_SUCCESS; +} +#endif + + +WLAN_STATUS wlanCfgInit(IN P_ADAPTER_T prAdapter, PUINT_8 pucConfigBuf, UINT_32 u4ConfigBufLen, UINT_32 u4Flags) +{ + P_WLAN_CFG_T prWlanCfg; + P_WLAN_CFG_REC_T prWlanCfgRec; + /* P_WLAN_CFG_ENTRY_T prWlanCfgEntry; */ + prAdapter->prWlanCfg = &prAdapter->rWlanCfg; + prWlanCfg = prAdapter->prWlanCfg; + + prAdapter->prWlanCfgRec = &prAdapter->rWlanCfgRec; + prWlanCfgRec = prAdapter->prWlanCfgRec; + + kalMemZero(prWlanCfg, sizeof(WLAN_CFG_T)); + ASSERT(prWlanCfg); + prWlanCfg->u4WlanCfgEntryNumMax = WLAN_CFG_ENTRY_NUM_MAX; + prWlanCfg->u4WlanCfgKeyLenMax = WLAN_CFG_KEY_LEN_MAX; + prWlanCfg->u4WlanCfgValueLenMax = WLAN_CFG_VALUE_LEN_MAX; + + prWlanCfgRec->u4WlanCfgEntryNumMax = WLAN_CFG_REC_ENTRY_NUM_MAX; + prWlanCfgRec->u4WlanCfgKeyLenMax = WLAN_CFG_REC_ENTRY_NUM_MAX; + prWlanCfgRec->u4WlanCfgValueLenMax = WLAN_CFG_REC_ENTRY_NUM_MAX; + + DBGLOG(INIT, INFO, "Init wifi config len %u max entry %u\n", u4ConfigBufLen, prWlanCfg->u4WlanCfgEntryNumMax); +#if DBG + /* self test */ + wlanCfgSet(prAdapter, "ConfigValid", "0x123", 0); + if (wlanCfgGetUint32(prAdapter, "ConfigValid", 0) != 0x123) + DBGLOG(INIT, INFO, "wifi config error %u\n", __LINE__); + + wlanCfgSet(prAdapter, "ConfigValid", "1", 0); + if (wlanCfgGetUint32(prAdapter, "ConfigValid", 0) != 1) + DBGLOG(INIT, INFO, "wifi config error %u\n", __LINE__); + +#endif + /*load default value because kalMemZero in this function*/ + wlanLoadDefaultCustomerSetting(prAdapter); + + /* Parse the pucConfigBuff */ + + if (pucConfigBuf && (u4ConfigBufLen > 0)) +#if CFG_SUPPORT_EASY_DEBUG + wlanCfgParse(prAdapter, pucConfigBuf, u4ConfigBufLen, FALSE); +#else + wlanCfgParse(prAdapter, pucConfigBuf, u4ConfigBufLen); +#endif + return WLAN_STATUS_SUCCESS; +} + +#endif /* CFG_SUPPORT_CFG_FILE */ + +INT_32 wlanHexToNum(CHAR c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; +} + +INT_32 wlanHexToByte(PCHAR hex) +{ + INT_32 a, b; + + a = wlanHexToNum(*hex++); + if (a < 0) + return -1; + b = wlanHexToNum(*hex++); + if (b < 0) + return -1; + return (a << 4) | b; +} + +INT_32 wlanHwAddrToBin(PCHAR txt, UINT_8 *addr) +{ + INT_32 i; + PCHAR pos = txt; + + for (i = 0; i < 6; i++) { + INT_32 a, b; + + while (*pos == ':' || *pos == '.' || *pos == '-') + pos++; + + a = wlanHexToNum(*pos++); + if (a < 0) + return -1; + b = wlanHexToNum(*pos++); + if (b < 0) + return -1; + *addr++ = (a << 4) | b; + } + + return pos - txt; +} + +BOOLEAN wlanIsChipNoAck(IN P_ADAPTER_T prAdapter) +{ + BOOLEAN fgIsNoAck; + + fgIsNoAck = prAdapter->fgIsChipNoAck +#if CFG_CHIP_RESET_SUPPORT + || kalIsResetting() +#endif + || fgIsBusAccessFailed; + + return fgIsNoAck; +} + +BOOLEAN wlanIsChipRstRecEnabled(IN P_ADAPTER_T prAdapter) +{ + return prAdapter->rWifiVar.fgChipResetRecover; +} + +BOOLEAN wlanIsChipAssert(IN P_ADAPTER_T prAdapter) +{ + if (prAdapter == NULL) + return TRUE; + return prAdapter->rWifiVar.fgChipResetRecover && prAdapter->fgIsChipAssert; +} + +VOID wlanChipRstPreAct(IN P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; + INT_32 i4BssIdx; + UINT_32 u4ClientCount = 0; + P_STA_RECORD_T prCurrStaRec = (P_STA_RECORD_T) NULL; + P_STA_RECORD_T prNextCurrStaRec = (P_STA_RECORD_T) NULL; + P_LINK_T prClientList; + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + + spin_lock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_CHIP_RST]); + if (prAdapter->fgIsChipAssert) { + spin_unlock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_CHIP_RST]); + return; + } + prAdapter->fgIsChipAssert = TRUE; + spin_unlock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_CHIP_RST]); + + for (i4BssIdx = 0; i4BssIdx < HW_BSSID_NUM; i4BssIdx++) { + prBssInfo = prAdapter->aprBssInfo[i4BssIdx]; + + if (!prBssInfo->fgIsInUse) + continue; + + if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) { + + if (prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_CONNECTED) + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + } else if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) { + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + u4ClientCount = bssGetClientCount(prAdapter, prBssInfo); + + if (u4ClientCount == 0) + continue; + + prClientList = &prBssInfo->rStaRecOfClientList; + LINK_FOR_EACH_ENTRY_SAFE(prCurrStaRec, prNextCurrStaRec, + prClientList, rLinkEntry, STA_RECORD_T) { + kalP2PGOStationUpdate(prAdapter->prGlueInfo, + (UINT_8) prBssInfo->u4PrivateData, prCurrStaRec, FALSE); + LINK_REMOVE_KNOWN_ENTRY(prClientList, &prCurrStaRec->rLinkEntry); + } + } else if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + if (prBssInfo->prStaRecOfAP == NULL) + continue; +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) + kalP2PGCIndicateConnectionStatus(prGlueInfo, + (UINT_8) prBssInfo->u4PrivateData, + NULL, NULL, 0, 0, + WLAN_STATUS_MEDIA_DISCONNECT); +#else + kalP2PGCIndicateConnectionStatus(prGlueInfo, + (UINT_8) prBssInfo->u4PrivateData, NULL, NULL, 0, 0); +#endif + prBssInfo->prStaRecOfAP = NULL; + + } + } + } +} + +#if CFG_ENABLE_PER_STA_STATISTICS +VOID wlanTxLifetimeUpdateStaStats(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_STA_RECORD_T prStaRec; + UINT_32 u4DeltaTime; + P_PKT_PROFILE_T prPktProfile = &prMsduInfo->rPktProfile; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (prStaRec) { + u4DeltaTime = (UINT_32) (prPktProfile->rHifTxDoneTimestamp - prPktProfile->rHardXmitArrivalTimestamp); + + /* Update StaRec statistics */ + prStaRec->u4TotalTxPktsNumber++; + prStaRec->u4TotalTxPktsTime += u4DeltaTime; + + if (u4DeltaTime > prStaRec->u4MaxTxPktsTime) + prStaRec->u4MaxTxPktsTime = u4DeltaTime; + if (u4DeltaTime >= NIC_TX_TIME_THRESHOLD) + prStaRec->u4ThresholdCounter++; + } +} +#endif + +BOOLEAN wlanTxLifetimeIsProfilingEnabled(IN P_ADAPTER_T prAdapter) +{ + BOOLEAN fgEnabled = FALSE; +#if CFG_SUPPORT_WFD + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + + prWfdCfgSettings = &prAdapter->rWifiVar.rWfdConfigureSettings; + + if (prWfdCfgSettings->ucWfdEnable > 0) + fgEnabled = TRUE; +#endif + + return fgEnabled; +} + +BOOLEAN wlanTxLifetimeIsTargetMsdu(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + BOOLEAN fgResult = TRUE; + +#if 0 + switch (prMsduInfo->ucTID) { + /* BK */ + case 1: + case 2: + + /* BE */ + case 0: + case 3: + fgResult = FALSE; + break; + /* VI */ + case 4: + case 5: + + /* VO */ + case 6: + case 7: + fgResult = TRUE; + break; + default: + break; + } +#endif + return fgResult; +} + +VOID wlanTxLifetimeTagPacket(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_PROFILING_TAG_T eTag) +{ + P_PKT_PROFILE_T prPktProfile = &prMsduInfo->rPktProfile; + + if (!wlanTxLifetimeIsProfilingEnabled(prAdapter)) + return; + + switch (eTag) { + case TX_PROF_TAG_OS_TO_DRV: + /* arrival time is tagged in wlanProcessTxFrame */ + break; + + case TX_PROF_TAG_DRV_ENQUE: + /* Reset packet profile */ + prPktProfile->fgIsValid = FALSE; + if (wlanTxLifetimeIsTargetMsdu(prAdapter, prMsduInfo)) { + /* Enable packet lifetime profiling */ + prPktProfile->fgIsValid = TRUE; + + /* Packet arrival time at kernel Hard Xmit */ + prPktProfile->rHardXmitArrivalTimestamp = GLUE_GET_PKT_ARRIVAL_TIME(prMsduInfo->prPacket); + + /* Packet enqueue time */ + prPktProfile->rEnqueueTimestamp = (OS_SYSTIME) kalGetTimeTick(); + } + break; + + case TX_PROF_TAG_DRV_DEQUE: + if (prPktProfile->fgIsValid) + prPktProfile->rDequeueTimestamp = (OS_SYSTIME) kalGetTimeTick(); + break; + + case TX_PROF_TAG_DRV_TX_DONE: + if (prPktProfile->fgIsValid) { + prPktProfile->rHifTxDoneTimestamp = (OS_SYSTIME) kalGetTimeTick(); + +#if CFG_ENABLE_PER_STA_STATISTICS + wlanTxLifetimeUpdateStaStats(prAdapter, prMsduInfo); +#endif + } + break; + + case TX_PROF_TAG_MAC_TX_DONE: + break; + + default: + break; + } +} + +VOID wlanTxProfilingTagPacket(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prPacket, IN ENUM_TX_PROFILING_TAG_T eTag) +{ +#if CFG_MET_PACKET_TRACE_SUPPORT + kalMetTagPacket(prAdapter->prGlueInfo, prPacket, eTag); +#endif +} + +VOID wlanTxProfilingTagMsdu(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_PROFILING_TAG_T eTag) +{ + wlanTxLifetimeTagPacket(prAdapter, prMsduInfo, eTag); + + wlanTxProfilingTagPacket(prAdapter, prMsduInfo->prPacket, eTag); +} + +VOID wlanUpdateTxStatistics(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN BOOLEAN fgTxDrop) +{ + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prBssInfo; + ENUM_WMM_ACI_T eAci = WMM_AC_BE_INDEX; + P_QUE_MGT_T prQM = &prAdapter->rQM; + OS_SYSTIME rCurTime; + + eAci = aucTid2ACI[prMsduInfo->ucUserPriority]; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (prStaRec) { + if (fgTxDrop) + prStaRec->arLinkStatistics[eAci].u4TxDropMsdu++; + else + prStaRec->arLinkStatistics[eAci].u4TxMsdu++; + } else { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + + if (fgTxDrop) + prBssInfo->arLinkStatistics[eAci].u4TxDropMsdu++; + else + prBssInfo->arLinkStatistics[eAci].u4TxMsdu++; + } + + /* Trigger FW stats log every 20s */ + rCurTime = (OS_SYSTIME) kalGetTimeTick(); + + DBGLOG(INIT, LOUD, "CUR[%u] LAST[%u] TO[%u]\n", rCurTime, + prQM->rLastTxPktDumpTime, CHECK_FOR_TIMEOUT(rCurTime, + prQM->rLastTxPktDumpTime, + MSEC_TO_SYSTIME(prAdapter->rWifiVar.u4StatsLogTimeout))); + + if (CHECK_FOR_TIMEOUT(rCurTime, prQM->rLastTxPktDumpTime, + MSEC_TO_SYSTIME(prAdapter->rWifiVar.u4StatsLogTimeout))) { + + wlanTriggerStatsLog(prAdapter, prAdapter->rWifiVar.u4StatsLogDuration); + wlanDumpAllBssStatistics(prAdapter); + + prQM->rLastTxPktDumpTime = rCurTime; + } +} + +VOID wlanUpdateRxStatistics(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_STA_RECORD_T prStaRec; + ENUM_WMM_ACI_T eAci = WMM_AC_BE_INDEX; + + eAci = aucTid2ACI[prSwRfb->ucTid]; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (prStaRec) + prStaRec->arLinkStatistics[eAci].u4RxMsdu++; +} + +WLAN_STATUS wlanTriggerStatsLog(IN P_ADAPTER_T prAdapter, IN UINT_32 u4DurationInMs) +{ + CMD_STATS_LOG_T rStatsLogCmd; + WLAN_STATUS rResult; + + if (prAdapter->fgIsEnableLpdvt) + return WLAN_STATUS_NOT_SUPPORTED; + + kalMemZero(&rStatsLogCmd, sizeof(CMD_STATS_LOG_T)); + + rStatsLogCmd.u4DurationInMs = u4DurationInMs; + + rResult = wlanSendSetQueryCmd(prAdapter, CMD_ID_STATS_LOG, TRUE, FALSE, + FALSE, nicCmdEventSetCommon, nicOidCmdTimeoutCommon, + sizeof(CMD_STATS_LOG_T), (PUINT_8) &rStatsLogCmd, NULL, 0); + + return rResult; +} + +WLAN_STATUS +wlanDhcpTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + DBGLOG(SW4, INFO, "DHCP PKT[0x%08x] WIDX:PID[%u:%u] Status[%u]\n", + prMsduInfo->u4TxDoneTag, prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, rTxDoneStatus); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS wlanArpTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + DBGLOG(SW4, INFO, "ARP PKT[0x%08x] WIDX:PID[%u:%u] Status[%u]\n", + prMsduInfo->u4TxDoneTag, prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, rTxDoneStatus); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS wlan1xTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + DBGLOG(SW4, INFO, "1x PKT[0x%08x] WIDX:PID[%u:%u] Status[%u]\n", + prMsduInfo->u4TxDoneTag, prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, rTxDoneStatus); + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_ASSERT_DUMP +VOID wlanCorDumpTimerReset(IN P_ADAPTER_T prAdapter, BOOLEAN fgIsResetN9) +{ + + if (prAdapter->fgN9AssertDumpOngoing || prAdapter->fgCr4AssertDumpOngoing) { + + if (fgIsResetN9) { + cnmTimerStopTimer(prAdapter, &prAdapter->rN9CorDumpTimer); + cnmTimerStartTimer(prAdapter, &prAdapter->rN9CorDumpTimer, 5000); + } else { + cnmTimerStopTimer(prAdapter, &prAdapter->rCr4CorDumpTimer); + cnmTimerStartTimer(prAdapter, &prAdapter->rCr4CorDumpTimer, 5000); + } + } else { + DBGLOG(INIT, INFO, "Cr4, N9 CorDump Is not ongoing, ignore timer reset\n"); + } +} + +VOID wlanN9CorDumpTimeOut(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr) +{ + + if (prAdapter->fgN9CorDumpFileOpend) { + DBGLOG(INIT, INFO, "\n[DUMP_N9]====N9 ASSERT_END====\n"); + prAdapter->fgN9AssertDumpOngoing = FALSE; + kalCloseCorDumpFile(TRUE); + prAdapter->fgN9CorDumpFileOpend = FALSE; + } +} + +VOID wlanCr4CorDumpTimeOut(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr) +{ + + if (prAdapter->fgCr4CorDumpFileOpend) { + DBGLOG(INIT, INFO, "\n[DUMP_Cr4]====Cr4 ASSERT_END====\n"); + prAdapter->fgCr4AssertDumpOngoing = FALSE; + kalCloseCorDumpFile(FALSE); + prAdapter->fgCr4CorDumpFileOpend = FALSE; + } +} +#endif + +BOOL +wlanGetWlanIdxByAddress(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucAddr, OUT PUINT_8 pucIndex) +{ + UINT_8 ucStaRecIdx; + P_STA_RECORD_T prTempStaRec; + + for (ucStaRecIdx = 0; ucStaRecIdx < CFG_STA_REC_NUM; ucStaRecIdx++) { + prTempStaRec = &(prAdapter->arStaRec[ucStaRecIdx]); + if (pucAddr) { + if (prTempStaRec->fgIsInUse && EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, pucAddr)) { + *pucIndex = prTempStaRec->ucWlanIndex; + return TRUE; + } + } else { + if (prTempStaRec->fgIsInUse && prTempStaRec->ucStaState == STA_STATE_3) { + *pucIndex = prTempStaRec->ucWlanIndex; + return TRUE; + } + } + } + return FALSE; +} + + +PUINT_8 +wlanGetStaAddrByWlanIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucIndex) +{ + P_WLAN_TABLE_T prWtbl; + + if (!prAdapter || ucIndex >= WTBL_SIZE) + return NULL; + + prWtbl = prAdapter->rWifiVar.arWtbl; + if (prWtbl[ucIndex].ucUsed && prWtbl[ucIndex].ucPairwise) + return &prWtbl[ucIndex].aucMacAddr[0]; + + return NULL; +} + +VOID +wlanNotifyFwSuspend(P_GLUE_INFO_T prGlueInfo, struct net_device *prDev, BOOLEAN fgSuspend) +{ + WLAN_STATUS rStatus; + UINT_32 u4SetInfoLen; + P_NETDEV_PRIVATE_GLUE_INFO prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) NULL; + CMD_SUSPEND_MODE_SETTING_T rSuspendCmd; + + prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(prDev); + + if (prNetDevPrivate->prGlueInfo != prGlueInfo) + DBGLOG(REQ, WARN, "%s: unexpected prGlueInfo(0x%p)!\n", __func__, prNetDevPrivate->prGlueInfo); + + rSuspendCmd.ucBssIndex = prNetDevPrivate->ucBssIdx; + rSuspendCmd.ucEnableSuspendMode = fgSuspend; + + if (prGlueInfo->prAdapter->rWifiVar.ucWow && prGlueInfo->prAdapter->rWowCtrl.fgWowEnable) { + /* cfg enable + wow enable => Wow On mdtim*/ + rSuspendCmd.ucMdtim = prGlueInfo->prAdapter->rWifiVar.ucWowOnMdtim; + DBGLOG(REQ, INFO, "mdtim [1]\n"); + } else if (prGlueInfo->prAdapter->rWifiVar.ucWow && !prGlueInfo->prAdapter->rWowCtrl.fgWowEnable) { + if (prGlueInfo->prAdapter->rWifiVar.ucAdvPws) { + /* cfg enable + wow disable + adv pws enable => Wow Off mdtim */ + rSuspendCmd.ucMdtim = prGlueInfo->prAdapter->rWifiVar.ucWowOffMdtim; + DBGLOG(REQ, INFO, "mdtim [2]\n"); + } else { + rSuspendCmd.ucMdtim = prGlueInfo->prAdapter->rWifiVar.ucWowOnMdtim; + } + } else if (!prGlueInfo->prAdapter->rWifiVar.ucWow) { + if (prGlueInfo->prAdapter->rWifiVar.ucAdvPws) { + /* cfg disable + adv pws enable => MT6632 case => Wow Off mdtim */ + rSuspendCmd.ucMdtim = prGlueInfo->prAdapter->rWifiVar.ucWowOffMdtim; + DBGLOG(REQ, INFO, "mdtim [3]\n"); + } else { + rSuspendCmd.ucMdtim = prGlueInfo->prAdapter->rWifiVar.ucWowOnMdtim; + } + } + + /* When FW receive command, it check connection state to decide apply setting or not */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidNotifyFwSuspend, + (PVOID)&rSuspendCmd, + sizeof(rSuspendCmd), + FALSE, + FALSE, + TRUE, + &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, INFO, "wlanNotifyFwSuspend fail\n"); +} + +WLAN_STATUS +wlanGetStaIdxByWlanIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucIndex, OUT PUINT_8 pucStaIdx) +{ + P_WLAN_TABLE_T prWtbl; + + if (!prAdapter || ucIndex >= WTBL_SIZE) + return WLAN_STATUS_FAILURE; + + prWtbl = prAdapter->rWifiVar.arWtbl; + + if (prWtbl[ucIndex].ucUsed && prWtbl[ucIndex].ucPairwise) { + *pucStaIdx = prWtbl[ucIndex].ucStaIndex; + return WLAN_STATUS_SUCCESS; + } + + return WLAN_STATUS_FAILURE; +} + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query LTE safe channels. +* +* \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_PENDING +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryLteSafeChannel(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + WLAN_STATUS rResult = WLAN_STATUS_FAILURE; + CMD_GET_LTE_SAFE_CHN_T rQuery_LTE_SAFE_CHN; + + do { + /* Sanity test */ + if ((prAdapter == NULL) || (pu4QueryInfoLen == NULL)) + break; + if ((pvQueryBuffer == NULL) || (u4QueryBufferLen == 0)) + break; + + /* Get LTE safe channel list */ + rResult = wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LTE_CHN, + FALSE, + TRUE, + g_fgIsOid, /* Query ID */ + nicCmdEventQueryLteSafeChn, /* The handler to receive firmware notification */ + nicOidCmdTimeoutCommon, + sizeof(CMD_GET_LTE_SAFE_CHN_T), + (PUINT_8)&rQuery_LTE_SAFE_CHN, + pvQueryBuffer, + u4QueryBufferLen); + DBGLOG(P2P, INFO, "[ACS] Get safe LTE Channels\n"); + } while (FALSE); + + return rResult; +} /* wlanoidQueryLteSafeChannel */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Add dirtiness to neighbor channels of a BSS to estimate channel quality. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prBssDesc Pointer to the BSS description. +* \param[in] u4Dirtiness Expected dirtiness value. +* \param[in] ucCentralChannel Central channel of the given BSS. +* \param[in] ucCoveredRange With ucCoveredRange and ucCentralChannel, +* all the affected channels can be enumerated. +*/ +/*----------------------------------------------------------------------------*/ +static VOID +wlanAddDirtinessToAffectedChannels(P_ADAPTER_T prAdapter, + P_BSS_DESC_T prBssDesc, UINT_32 u4Dirtiness, UINT_8 ucCentralChannel, + UINT_8 ucCoveredRange) +{ + UINT_8 ucIdx, ucStart, ucEnd; + BOOL bIs5GChl = ucCentralChannel > 14; + UINT_8 ucLeftNeighborChannel, ucRightNeighborChannel, + ucLeftNeighborChannel2 = 0, ucRightNeighborChannel2 = 0, + ucLeftestCoveredChannel, ucRightestCoveredChannel; + P_PARAM_GET_CHN_INFO prGetChnLoad = &(prAdapter->rWifiVar.rChnLoadInfo); + + ucLeftestCoveredChannel = ucCentralChannel > ucCoveredRange ? + ucCentralChannel - ucCoveredRange : 1; + + ucLeftNeighborChannel = ucLeftestCoveredChannel ? + ucLeftestCoveredChannel - 1 : 0; + + /* align leftest covered ch and left neighbor ch to valid 5g ch */ + if (bIs5GChl) { + ucLeftestCoveredChannel += 2; + ucLeftNeighborChannel -= 1; + } else { + /* we select the nearest 2 ch to the leftest covered ch as left neighbor chs */ + ucLeftNeighborChannel2 = + ucLeftNeighborChannel > 1 ? ucLeftNeighborChannel - 1 : 0; + } + + /* handle corner cases of 5g ch*/ + if (ucLeftestCoveredChannel > 14 && ucLeftestCoveredChannel <= 36) { + ucLeftestCoveredChannel = 36; + ucLeftNeighborChannel = 0; + } else if (ucLeftestCoveredChannel > 64 && ucLeftestCoveredChannel <= 100) { + ucLeftestCoveredChannel = 100; + ucLeftNeighborChannel = 0; + } else if (ucLeftestCoveredChannel > 140 && ucLeftestCoveredChannel <= 149) { + ucLeftestCoveredChannel = 149; + ucLeftNeighborChannel = 0; + } else if (ucLeftestCoveredChannel > 173 && ucLeftestCoveredChannel <= 184) { + ucLeftestCoveredChannel = 184; + ucLeftNeighborChannel = 0; + } + + /* + * because ch 14 is 12MHz away to ch13, we must shift the leftest covered ch and + * left neighbor ch when central ch is ch 14 + */ + if (ucCentralChannel == 14) { + ucLeftestCoveredChannel = 13; + ucLeftNeighborChannel = 12; + ucLeftNeighborChannel2 = 11; + } + + ucRightestCoveredChannel = ucCentralChannel + ucCoveredRange; + ucRightNeighborChannel = ucRightestCoveredChannel + 1; + + /* align rightest covered ch and right neighbor ch to valid 5g ch */ + if (bIs5GChl) { + ucRightestCoveredChannel -= 2; + ucRightNeighborChannel += 1; + } else { + /* we select the nearest 2 ch to the rightest covered ch as right neighbor ch */ + ucRightNeighborChannel2 = + ucRightNeighborChannel < 13 ? ucRightNeighborChannel + 1 : 0; + } + + /* handle corner cases */ + if (ucRightestCoveredChannel >= 14 && ucRightestCoveredChannel < 36) { + if (ucRightestCoveredChannel == 14) { + ucRightestCoveredChannel = 13; + ucRightNeighborChannel = 14; + } else { + ucRightestCoveredChannel = 14; + ucRightNeighborChannel = 0; + } + + ucRightNeighborChannel2 = 0; + } else if (ucRightestCoveredChannel >= 64 && ucRightestCoveredChannel < 100) { + ucRightestCoveredChannel = 64; + ucRightNeighborChannel = 0; + } else if (ucRightestCoveredChannel >= 140 && ucRightestCoveredChannel < 149) { + ucRightestCoveredChannel = 140; + ucRightNeighborChannel = 0; + } else if (ucRightestCoveredChannel >= 173 && ucRightestCoveredChannel < 184) { + ucRightestCoveredChannel = 173; + ucRightNeighborChannel = 0; + } + + DBGLOG(SCN, TRACE, "central ch %d\n", ucCentralChannel); + + ucStart = wlanGetChannelIndex(ucLeftestCoveredChannel); + ucEnd = wlanGetChannelIndex(ucRightestCoveredChannel); + + for (ucIdx = ucStart; ucIdx <= ucEnd; ucIdx++) { + prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtiness += u4Dirtiness; + DBGLOG(SCN, TRACE, "Add dirtiness %d, to covered ch %d\n", + u4Dirtiness, prGetChnLoad->rEachChnLoad[ucIdx].ucChannel); + } + + if (ucLeftNeighborChannel != 0) { + ucIdx = wlanGetChannelIndex(ucLeftNeighborChannel); + prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtiness += (u4Dirtiness >> 1); + DBGLOG(SCN, TRACE, "Add dirtiness %d, to neighbor ch %d\n", + u4Dirtiness >> 1, prGetChnLoad->rEachChnLoad[ucIdx].ucChannel); + } + + if (ucRightNeighborChannel != 0) { + ucIdx = wlanGetChannelIndex(ucRightNeighborChannel); + prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtiness += (u4Dirtiness >> 1); + DBGLOG(SCN, TRACE, "Add dirtiness %d, to neighbor ch %d\n", + u4Dirtiness >> 1, prGetChnLoad->rEachChnLoad[ucIdx].ucChannel); + } + + if (!bIs5GChl) { + if (ucLeftNeighborChannel2 != 0) { + ucIdx = wlanGetChannelIndex(ucLeftNeighborChannel2); + prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtiness += (u4Dirtiness >> 1); + DBGLOG(SCN, TRACE, "Add dirtiness %d, to neighbor ch %d\n", + u4Dirtiness >> 1, prGetChnLoad->rEachChnLoad[ucIdx].ucChannel); + } + + if (ucRightNeighborChannel2 != 0) { + ucIdx = wlanGetChannelIndex(ucRightNeighborChannel2); + prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtiness += (u4Dirtiness >> 1); + DBGLOG(SCN, TRACE, "Add dirtiness %d, to neighbor ch %d\n", + u4Dirtiness >> 1, prGetChnLoad->rEachChnLoad[ucIdx].ucChannel); + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief For a scanned BSS, add dirtiness to the channels 1)around its primary +* channels and 2) in its working BW to represent the quality degrade. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prBssDesc Pointer to the BSS description. +* \param[in] u4Dirtiness Expected dirtiness value. +* \param[in] bIsIndexOne True means index 1, False means index 2. +*/ +/*----------------------------------------------------------------------------*/ +static VOID +wlanCalculateChannelDirtiness(IN P_ADAPTER_T prAdapter, + P_BSS_DESC_T prBssDesc, UINT_32 u4Dirtiness, BOOL bIsIndexOne) +{ + UINT_8 ucCoveredRange = 0, ucCentralChannel = 0, ucCentralChannel2 = 0; + + if (bIsIndexOne) { + DBGLOG(SCN, TRACE, "Process dirtiness index 1\n"); + ucCentralChannel = prBssDesc->ucChannelNum; + ucCoveredRange = 2; + } else { + DBGLOG(SCN, TRACE, "Process dirtiness index 2, "); + switch (prBssDesc->eChannelWidth) { + case CW_20_40MHZ: + if (prBssDesc->eSco == CHNL_EXT_SCA) { + DBGLOG(SCN, TRACE, "BW40\n"); + ucCentralChannel = prBssDesc->ucChannelNum + 2; + ucCoveredRange = 4; + } else if (prBssDesc->eSco == CHNL_EXT_SCB) { + DBGLOG(SCN, TRACE, "BW40\n"); + ucCentralChannel = prBssDesc->ucChannelNum - 2; + ucCoveredRange = 4; + } else { + DBGLOG(SCN, TRACE, "BW20\n"); + ucCentralChannel = prBssDesc->ucChannelNum; + ucCoveredRange = 2; + } + break; + case CW_80MHZ: + DBGLOG(SCN, TRACE, "BW80\n"); + ucCentralChannel = prBssDesc->ucCenterFreqS1; + ucCoveredRange = 8; + break; + case CW_160MHZ: + DBGLOG(SCN, TRACE, "BW160\n"); + ucCentralChannel = prBssDesc->ucCenterFreqS1; + ucCoveredRange = 16; + break; + case CW_80P80MHZ: + DBGLOG(SCN, TRACE, "BW8080\n"); + ucCentralChannel = prBssDesc->ucCenterFreqS1; + ucCentralChannel2 = prBssDesc->ucCenterFreqS2; + ucCoveredRange = 8; + break; + default: + ucCentralChannel = prBssDesc->ucChannelNum; + ucCoveredRange = 2; + break; + }; + } + + wlanAddDirtinessToAffectedChannels(prAdapter, prBssDesc, u4Dirtiness, + ucCentralChannel, ucCoveredRange); + + /* 80 + 80 secondary 80 case */ + if (bIsIndexOne || ucCentralChannel2 == 0) + return; + + wlanAddDirtinessToAffectedChannels(prAdapter, prBssDesc, u4Dirtiness, + ucCentralChannel2, ucCoveredRange); +} + +VOID +wlanInitChnLoadInfoChannelList(IN P_ADAPTER_T prAdapter) +{ + UINT_8 ucIdx = 0; + P_PARAM_GET_CHN_INFO prGetChnLoad = &(prAdapter->rWifiVar.rChnLoadInfo); + + for (ucIdx = 0; ucIdx < MAX_CHN_NUM; ucIdx++) + prGetChnLoad->rEachChnLoad[ucIdx].ucChannel = + wlanGetChannelNumFromIndex(ucIdx); +} + +WLAN_STATUS +wlanCalculateAllChannelDirtiness(IN P_ADAPTER_T prAdapter) +{ + WLAN_STATUS rResult = WLAN_STATUS_SUCCESS; + PARAM_RSSI i4Rssi = 0; + P_BSS_DESC_T prBssDesc = NULL; + UINT_32 u4Dirtiness = 0; + P_LINK_T prBSSDescList = &(prAdapter->rWifiVar.rScanInfo.rBSSDescList); + + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + i4Rssi = RCPI_TO_dBm(prBssDesc->ucRCPI); + + if (i4Rssi >= ACS_AP_RSSI_LEVEL_HIGH) + u4Dirtiness = ACS_DIRTINESS_LEVEL_HIGH; + else if (i4Rssi >= ACS_AP_RSSI_LEVEL_LOW) + u4Dirtiness = ACS_DIRTINESS_LEVEL_MID; + else + u4Dirtiness = ACS_DIRTINESS_LEVEL_LOW; + + DBGLOG(SCN, TRACE, "Found an AP(%s), primary ch %d\n", + prBssDesc->aucSSID, prBssDesc->ucChannelNum); + + /* dirtiness index1 */ + wlanCalculateChannelDirtiness(prAdapter, prBssDesc, u4Dirtiness, TRUE); + + /* dirtiness index2 */ + wlanCalculateChannelDirtiness(prAdapter, prBssDesc, + u4Dirtiness >> 1, FALSE); + } + + return rResult; +} + +UINT_8 +wlanGetChannelIndex(IN UINT_8 channel) +{ + UINT_8 ucIdx = 1; + + if (channel <= 14) + ucIdx = channel - 1; + else if (channel >= 36 && channel <= 64) + ucIdx = 14 + (channel - 36) / 4; + else if (channel >= 100 && channel <= 140) + ucIdx = 14 + 8 + (channel - 100) / 4; + else if (channel >= 149 && channel <= 173) + ucIdx = 14 + 8 + 11 + (channel - 149) / 4; + else if (channel >= 184 && channel <= 216) + ucIdx = 14 + 8 + 11 + 7 + (channel - 184) / 4; + else + DBGLOG(SCN, ERROR, "Invalid ch %u\n", channel); + + return ucIdx; +} + +/*---------------------------------------------------------------------*/ +/*! +* \brief Get ch index by the given ch num; the reverse function of +* wlanGetChannelIndex +* +* \param[in] ucIdx Channel index +* \param[out] ucChannel Channel number +*/ +/*---------------------------------------------------------------------*/ + +UINT_8 +wlanGetChannelNumFromIndex(IN UINT_8 ucIdx) +{ + UINT_8 ucChannel = 0; + + if (ucIdx >= 40) + ucChannel = ((ucIdx - 40) << 2) + 184; + else if (ucIdx >= 33) + ucChannel = ((ucIdx - 33) << 2) + 149; + else if (ucIdx >= 22) + ucChannel = ((ucIdx - 22) << 2) + 100; + else if (ucIdx >= 14) + ucChannel = ((ucIdx - 14) << 2) + 36; + else + ucChannel = ucIdx + 1; + + return ucChannel; +} + +VOID +wlanSortChannel(IN P_ADAPTER_T prAdapter) +{ + P_PARAM_GET_CHN_INFO prChnLoadInfo = &(prAdapter->rWifiVar.rChnLoadInfo); + INT_8 ucIdx = 0, ucRoot = 0, ucChild = 0; + PARAM_CHN_RANK_INFO rChnRankInfo; + + /* prepare unsorted ch rank list */ + for (ucIdx = 0; ucIdx < MAX_CHN_NUM; ++ucIdx) { + prChnLoadInfo->rChnRankList[ucIdx].ucChannel = + prChnLoadInfo->rEachChnLoad[ucIdx].ucChannel; + prChnLoadInfo->rChnRankList[ucIdx].u4Dirtiness = + prChnLoadInfo->rEachChnLoad[ucIdx].u4Dirtiness; + } + + /* heapify ch rank list */ + for (ucIdx = MAX_CHN_NUM / 2 - 1; ucIdx >= 0; --ucIdx) { + for (ucRoot = ucIdx; ucRoot * 2 + 1 < MAX_CHN_NUM; + ucRoot = ucChild) { + + ucChild = ucRoot * 2 + 1; + if (ucChild < MAX_CHN_NUM - 1 && + prChnLoadInfo->rChnRankList[ucChild + 1].u4Dirtiness > + prChnLoadInfo->rChnRankList[ucChild].u4Dirtiness) + ucChild += 1; + + if (prChnLoadInfo->rChnRankList[ucChild].u4Dirtiness <= + prChnLoadInfo->rChnRankList[ucRoot].u4Dirtiness) + break; + + rChnRankInfo = prChnLoadInfo->rChnRankList[ucChild]; + prChnLoadInfo->rChnRankList[ucChild] = prChnLoadInfo->rChnRankList[ucRoot]; + prChnLoadInfo->rChnRankList[ucRoot] = rChnRankInfo; + } + } + + /* sort ch rank list */ + for (ucIdx = MAX_CHN_NUM - 1; ucIdx > 0; ucIdx--) { + rChnRankInfo = prChnLoadInfo->rChnRankList[0]; + prChnLoadInfo->rChnRankList[0] = prChnLoadInfo->rChnRankList[ucIdx]; + prChnLoadInfo->rChnRankList[ucIdx] = rChnRankInfo; + + for (ucRoot = 0; ucRoot * 2 + 1 < ucIdx; ucRoot = ucChild) { + ucChild = ucRoot * 2 + 1; + if (ucChild < ucIdx - 1 && + prChnLoadInfo->rChnRankList[ucChild + 1].u4Dirtiness > + prChnLoadInfo->rChnRankList[ucChild].u4Dirtiness) + ucChild += 1; + + if (prChnLoadInfo->rChnRankList[ucChild].u4Dirtiness <= + prChnLoadInfo->rChnRankList[ucRoot].u4Dirtiness) + break; + + rChnRankInfo = prChnLoadInfo->rChnRankList[ucChild]; + prChnLoadInfo->rChnRankList[ucChild] = prChnLoadInfo->rChnRankList[ucRoot]; + prChnLoadInfo->rChnRankList[ucRoot] = rChnRankInfo; + } + } + + for (ucIdx = 0; ucIdx < MAX_CHN_NUM; ++ucIdx) + DBGLOG(SCN, INFO, "[ACS]channel=%d, dirtiness=%d\n", + prChnLoadInfo->rChnRankList[ucIdx].ucChannel, + prChnLoadInfo->rChnRankList[ucIdx].u4Dirtiness); + +} +#endif + +UINT_8 wlanGetAntPathType( + IN P_ADAPTER_T prAdapter, + IN enum ENUM_WF_PATH_FAVOR_T eWfPathFavor + ) +{ + UINT_8 ucFianlWfPathType = eWfPathFavor; +#if CFG_SUPPORT_ANT_SELECT + UINT_8 ucNss = prAdapter->rWifiVar.ucNSS; + UINT_8 ucSpeIdxCtrl = prAdapter->rWifiVar.ucSpeIdxCtrl; + + if (ucSpeIdxCtrl == 0) + ucFianlWfPathType = ENUM_WF_0_ONE_STREAM_PATH_FAVOR; + else if (ucSpeIdxCtrl == 1) + ucFianlWfPathType = ENUM_WF_1_ONE_STREAM_PATH_FAVOR; + else if (ucSpeIdxCtrl == 2) { + if (ucNss > 1) + ucFianlWfPathType = ENUM_WF_0_1_DUP_STREAM_PATH_FAVOR; + else + ucFianlWfPathType = ENUM_WF_NON_FAVOR; + } else + ucFianlWfPathType = ENUM_WF_NON_FAVOR; +#endif + return ucFianlWfPathType; +} + +#if ((CFG_SISO_SW_DEVELOP == 1) || (CFG_SUPPORT_ANT_SELECT == 1)) +UINT_8 +wlanAntPathFavorSelect( + enum ENUM_WF_PATH_FAVOR_T eWfPathFavor + ) +{ + UINT_8 ucRetValSpeIdx = 0; + + if ((eWfPathFavor == ENUM_WF_NON_FAVOR) || + (eWfPathFavor == ENUM_WF_0_ONE_STREAM_PATH_FAVOR) || + (eWfPathFavor == ENUM_WF_0_1_TWO_STREAM_PATH_FAVOR)) + ucRetValSpeIdx = ANTENNA_WF0; + else if (eWfPathFavor == ENUM_WF_0_1_DUP_STREAM_PATH_FAVOR) + ucRetValSpeIdx = 0x18; + else if (eWfPathFavor == ENUM_WF_1_ONE_STREAM_PATH_FAVOR) + ucRetValSpeIdx = ANTENNA_WF1; + else + ucRetValSpeIdx = ANTENNA_WF0; + + return ucRetValSpeIdx; +} +#endif + +UINT_8 +wlanGetSpeIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN enum ENUM_WF_PATH_FAVOR_T eWfPathFavor) +{ + UINT_8 ucRetValSpeIdx = 0; +#if ((CFG_SISO_SW_DEVELOP == 1) || (CFG_SUPPORT_ANT_SELECT == 1)) + P_BSS_INFO_T prBssInfo; + ENUM_BAND_T eBand = BAND_NULL; + + if (ucBssIndex > MAX_BSS_INDEX) { + DBGLOG(SW4, ERROR, "Invalid BssInfo index[%u], skip dump!\n", + ucBssIndex); + return ucRetValSpeIdx; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + /* + * if DBDC enable return 0, else depend 2.4G/5G & support WF path + * retrun accurate value + */ + if (!prAdapter->rWifiVar.fgDbDcModeEn) { + if (prBssInfo->fgIsGranted) + eBand = prBssInfo->eBandGranted; + else + eBand = prBssInfo->eBand; + + if (eBand == BAND_2G4) { + if (IS_WIFI_2G4_SISO(prAdapter)) { + if (IS_WIFI_2G4_WF0_SUPPORT(prAdapter)) + ucRetValSpeIdx = ANTENNA_WF0; + else + ucRetValSpeIdx = ANTENNA_WF1; + } else + ucRetValSpeIdx = wlanAntPathFavorSelect(eWfPathFavor); + } else if (eBand == BAND_5G) { + if (IS_WIFI_5G_SISO(prAdapter)) { + if (IS_WIFI_5G_WF0_SUPPORT(prAdapter)) + ucRetValSpeIdx = ANTENNA_WF0; + else + ucRetValSpeIdx = ANTENNA_WF1; + } else + ucRetValSpeIdx = wlanAntPathFavorSelect(eWfPathFavor); + } else + ucRetValSpeIdx = wlanAntPathFavorSelect(eWfPathFavor); + } + DBGLOG(INIT, INFO, "SpeIdx:%d,D:%d,G=%d,B=%d,Bss=%d\n", + ucRetValSpeIdx, prAdapter->rWifiVar.fgDbDcModeEn, + prBssInfo->fgIsGranted, eBand, ucBssIndex); +#endif + return ucRetValSpeIdx; +} + +UINT_8 +wlanGetSupportNss(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex) +{ + UINT_8 ucRetValNss = prAdapter->rWifiVar.ucNSS; +#if CFG_SISO_SW_DEVELOP + P_BSS_INFO_T prBssInfo; + ENUM_BAND_T eBand = BAND_NULL; + + if (ucBssIndex > MAX_BSS_INDEX) { + DBGLOG(SW4, ERROR, "Invalid BssInfo index[%u], skip dump!\n", + ucBssIndex); + return ucRetValNss; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + /* + * depend 2.4G/5G support SISO/MIMO + * retrun accurate value + */ + if (prBssInfo->fgIsGranted) + eBand = prBssInfo->eBandGranted; + else + eBand = prBssInfo->eBand; + + if ((eBand == BAND_2G4) && IS_WIFI_2G4_SISO(prAdapter)) + ucRetValNss = 1; + else if ((eBand == BAND_5G) && IS_WIFI_5G_SISO(prAdapter)) + ucRetValNss = 1; + DBGLOG(INIT, INFO, "Nss=%d,G=%d,B=%d,Bss=%d\n", + ucRetValNss, prBssInfo->fgIsGranted, eBand, ucBssIndex); +#endif + return ucRetValNss; +} + +INT_32 wlanGetFileContent(P_ADAPTER_T prAdapter, + const PUINT_8 pcFileName, PUINT_8 pucBuf, + UINT_32 u4MaxFileLen, PUINT_32 pu4ReadFileLen, BOOL bReqFw) +{ + if (bReqFw) + return kalRequestFirmware(pcFileName, pucBuf, + u4MaxFileLen, pu4ReadFileLen, + prAdapter->prGlueInfo->prDev); + + return kalReadToFile(pcFileName, pucBuf, + u4MaxFileLen, pu4ReadFileLen); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to update some info before connected, +* some decision need some info before bss info update +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +#if CFG_SUPPORT_ANT_SELECT +WLAN_STATUS wlanUpdateExtInfo(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo; + + rSwCtrlInfo.u4Id = 0xa0640001; + rSwCtrlInfo.u4Data = prAdapter->rWifiVar.ucNSS; + + return kalIoctl(prGlueInfo, + wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + FALSE, FALSE, TRUE, &u4BufLen); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is a wrapper to send eapol offload (rekey) command +* +* @param prGlueInfo Pointer of prGlueInfo Data Structure +* +* @return VOID +*/ +/*----------------------------------------------------------------------------*/ +int wlanSuspendRekeyOffload(P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRekeyMode) +{ + UINT_32 u4BufLen; + P_PARAM_GTK_REKEY_DATA prGtkData; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + INT_32 i4Rslt = -EINVAL; +#if CFG_SUPPORT_REPLAY_DETECTION + P_BSS_INFO_T prBssInfo = NULL; + struct SEC_DETECT_REPLAY_INFO *prDetRplyInfo = NULL; + UINT_8 ucCurKeyId; + UINT_8 ucRpyOffload; +#endif + + ASSERT(prGlueInfo); + +#if CFG_SUPPORT_REPLAY_DETECTION + ucRpyOffload = prGlueInfo->prAdapter->rWifiVar.ucRpyDetectOffload; + + if ((ucRekeyMode == GTK_REKEY_CMD_MODE_SET_BCMC_PN) && + (ucRpyOffload == FALSE)) { + DBGLOG(RSN, INFO, "Set PN to fw, but feature off. no action\n"); + return WLAN_STATUS_SUCCESS; + } + + if ((ucRekeyMode == GTK_REKEY_CMD_MODE_GET_BCMC_PN) && + (ucRpyOffload == FALSE)) { + DBGLOG(RSN, INFO, "Get PN from fw, but feature off. no action\n"); + return WLAN_STATUS_SUCCESS; + } +#endif + + prGtkData = + (P_PARAM_GTK_REKEY_DATA) kalMemAlloc(sizeof(PARAM_GTK_REKEY_DATA), VIR_MEM_TYPE); + + if (!prGtkData) + return WLAN_STATUS_SUCCESS; + + kalMemZero(prGtkData, sizeof(PARAM_GTK_REKEY_DATA)); + + /* if enable => enable FW rekey offload. if disable, let rekey back to supplicant */ + prGtkData->ucRekeyMode = ucRekeyMode; + DBGLOG(RSN, INFO, "GTK Rekey ucRekeyMode = %d\n", ucRekeyMode); + + if (ucRekeyMode == GTK_REKEY_CMD_MODE_OFFLOAD_ON) { + DBGLOG(RSN, INFO, "kek\n"); + DBGLOG_MEM8(RSN, ERROR, (PUINT_8)prGlueInfo->rWpaInfo.aucKek, NL80211_KEK_LEN); + DBGLOG(RSN, INFO, "kck\n"); + DBGLOG_MEM8(RSN, ERROR, (PUINT_8)prGlueInfo->rWpaInfo.aucKck, NL80211_KCK_LEN); + DBGLOG(RSN, INFO, "replay count\n"); + DBGLOG_MEM8(RSN, ERROR, (PUINT_8)prGlueInfo->rWpaInfo.aucReplayCtr, NL80211_REPLAY_CTR_LEN); + + kalMemCopy(prGtkData->aucKek, prGlueInfo->rWpaInfo.aucKek, NL80211_KEK_LEN); + kalMemCopy(prGtkData->aucKck, prGlueInfo->rWpaInfo.aucKck, NL80211_KCK_LEN); + kalMemCopy(prGtkData->aucReplayCtr, prGlueInfo->rWpaInfo.aucReplayCtr, NL80211_REPLAY_CTR_LEN); + + prGtkData->ucBssIndex = prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + + prGtkData->u4Proto = NL80211_WPA_VERSION_2; + if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA) + prGtkData->u4Proto = NL80211_WPA_VERSION_1; + + if (prGlueInfo->rWpaInfo.u4CipherPairwise == IW_AUTH_CIPHER_TKIP) + prGtkData->u4PairwiseCipher = BIT(3); + else if (prGlueInfo->rWpaInfo.u4CipherPairwise == IW_AUTH_CIPHER_CCMP) + prGtkData->u4PairwiseCipher = BIT(4); + else { + kalMemFree(prGtkData, VIR_MEM_TYPE, sizeof(PARAM_GTK_REKEY_DATA)); + return WLAN_STATUS_SUCCESS; + } + + if (prGlueInfo->rWpaInfo.u4CipherGroup == IW_AUTH_CIPHER_TKIP) + prGtkData->u4GroupCipher = BIT(3); + else if (prGlueInfo->rWpaInfo.u4CipherGroup == IW_AUTH_CIPHER_CCMP) + prGtkData->u4GroupCipher = BIT(4); + else { + kalMemFree(prGtkData, VIR_MEM_TYPE, sizeof(PARAM_GTK_REKEY_DATA)); + return WLAN_STATUS_SUCCESS; + } + + prGtkData->u4KeyMgmt = prGlueInfo->rWpaInfo.u4KeyMgmt; + prGtkData->u4MgmtGroupCipher = 0; + + } + + if (ucRekeyMode == GTK_REKEY_CMD_MODE_OFLOAD_OFF) { + /* inform FW disable EAPOL offload */ + DBGLOG(RSN, INFO, "Disable EAPOL offload\n"); + } + +#if CFG_SUPPORT_REPLAY_DETECTION + if (ucRekeyMode == GTK_REKEY_CMD_MODE_RPY_OFFLOAD_ON) + DBGLOG(RSN, INFO, "ucRekeyMode(rpy rekey offload on): %d\n", ucRekeyMode); + + if (ucRekeyMode == GTK_REKEY_CMD_MODE_RPY_OFFLOAD_OFF) + DBGLOG(RSN, INFO, "ucRekeyMode(rpy rekey offload off): %d\n", ucRekeyMode); + + if ((ucRekeyMode == GTK_REKEY_CMD_MODE_SET_BCMC_PN) && + (ucRpyOffload == TRUE)) { + prGtkData->ucBssIndex = prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + prBssInfo = GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex); + prDetRplyInfo = &prBssInfo->rDetRplyInfo; + ucCurKeyId = prDetRplyInfo->ucCurKeyId; + prGtkData->ucCurKeyId = ucCurKeyId; + DBGLOG_MEM8(RSN, INFO, (PUINT_8)prGtkData->aucReplayCtr, NL80211_REPLAY_CTR_LEN); + kalMemCopy(prGtkData->aucReplayCtr, + prDetRplyInfo->arReplayPNInfo[ucCurKeyId].auPN, + NL80211_REPLAY_CTR_LEN); + + /* set bc/mc PN zero before suspend */ + kalMemZero(prDetRplyInfo->arReplayPNInfo[ucCurKeyId].auPN, NL80211_REPLAY_CTR_LEN); + } + + if ((ucRekeyMode == GTK_REKEY_CMD_MODE_GET_BCMC_PN) && + (ucRpyOffload == TRUE)) { + prGtkData->ucBssIndex = prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + } +#endif + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetGtkRekeyData, + prGtkData, sizeof(PARAM_GTK_REKEY_DATA), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "Suspend GTK rekey data error:%x\n", + rStatus); + else + i4Rslt = 0; + + kalMemFree(prGtkData, VIR_MEM_TYPE, sizeof(PARAM_GTK_REKEY_DATA)); + + return i4Rslt; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is a wrapper to send power-saving mode command +* when AIS enter wow, and send WOW command +* Also let GC/GO/AP enter deactivate state to enter TOP sleep +* +* @param prGlueInfo Pointer of prGlueInfo Data Structure +* +* @return VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanSuspendPmHandle(P_GLUE_INFO_T prGlueInfo) +{ + UINT_8 idx; + PARAM_POWER_MODE ePwrMode; + P_BSS_INFO_T prBssInfo; + UINT_8 ucKekZeroCnt = 0; + UINT_8 ucKckZeroCnt = 0; + UINT_8 ucGtkOffload = TRUE; + UINT_8 i = 0; +#if CFG_SUPPORT_REPLAY_DETECTION + struct SEC_DETECT_REPLAY_INFO *prDetRplyInfo = NULL; + UINT_8 ucIdx = 0; + UINT_8 ucKeyIdx = 0; + UINT_8 ucRpyOffload = 0; +#endif + P_STA_RECORD_T prStaRec; + P_RX_BA_ENTRY_T prRxBaEntry; + + if (prGlueInfo->prAdapter->u4IsKeepFullPwrBitmap) + wlanKeepFullPwr(prGlueInfo->prAdapter, FALSE); + + /* if wifi.cfg EAPOL offload is 0, we set rekey offload when enter wow */ + if (!prGlueInfo->prAdapter->rWifiVar.ucEapolOffload) { + + /* + * check if KCK, KEK not sync from supplicant. + * if no these info updated from supplicant, + *disable GTK offload feature. + */ + for (i = 0; i < NL80211_KEK_LEN; i++) { + if (prGlueInfo->rWpaInfo.aucKek[i] == 0x00) + ucKekZeroCnt++; + } + + for (i = 0; i < NL80211_KCK_LEN; i++) { + if (prGlueInfo->rWpaInfo.aucKck[i] == 0x00) + ucKckZeroCnt++; + } + + if ((ucKekZeroCnt == NL80211_KCK_LEN) || + (ucKckZeroCnt == NL80211_KCK_LEN)) { + DBGLOG(RSN, INFO, "no rekey offload, due to no KCK/KEK from cfg80211\n"); + + prGlueInfo->prAdapter->rWifiVar.ucRpyDetectOffload = FEATURE_DISABLED; + + ucGtkOffload = FALSE; + /* set bc/mc replay detection off to fw */ + wlanSuspendRekeyOffload(prGlueInfo, + GTK_REKEY_CMD_MODE_RPY_OFFLOAD_OFF); + } + + +#if CFG_SUPPORT_REPLAY_DETECTION + ucRpyOffload = prGlueInfo->prAdapter->rWifiVar.ucRpyDetectOffload; + + if (ucRpyOffload && ucGtkOffload) + wlanSuspendRekeyOffload(prGlueInfo, GTK_REKEY_CMD_MODE_SET_BCMC_PN); +#endif + if (ucGtkOffload) + wlanSuspendRekeyOffload(prGlueInfo, GTK_REKEY_CMD_MODE_OFFLOAD_ON); + +#if CFG_SUPPORT_REPLAY_DETECTION + + prBssInfo = GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex); + prDetRplyInfo = &prBssInfo->rDetRplyInfo; + + for (ucKeyIdx = 0; ucKeyIdx < 4; ucKeyIdx++) { + for (ucIdx = 0; ucIdx < 6; ucIdx++) + prDetRplyInfo->arReplayPNInfo[ucKeyIdx].auPN[ucIdx] = 0x0; + } +#endif + DBGLOG(HAL, STATE, "Suspend rekey offload\n"); + } + + + /* Abort Obss scan if the scan FSM is not IDLE for all HIF*/ + rlmObssAbortScan(prGlueInfo->prAdapter); + + /* Pending Timer related to CNM need to check and + * perform corresponding timeout handler. Without it, + * Might happen CNM abnormal after resume or during suspend. + */ + cnmCheckPendingTimer(prGlueInfo->prAdapter); + + /* 1) wifi cfg "Wow" is true, 2) wow or AdvPws is enable + * 3) WIfI connected => execute WOW flow + * Send power-saving cmd when enter wow state, even w/o cfg80211 support + */ + if (prGlueInfo->prAdapter->rWifiVar.ucWow + && (prGlueInfo->prAdapter->rWowCtrl.fgWowEnable + || prGlueInfo->prAdapter->rWifiVar.ucAdvPws)) { + if (kalGetMediaStateIndicated(prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + /* AIS bss enter wow power mode, default fast power-saving */ + ePwrMode = prGlueInfo->prAdapter->rWifiVar.ucWowPwsMode; + idx = prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + nicConfigPowerSaveWowProfile(prGlueInfo->prAdapter, idx, ePwrMode, FALSE, TRUE); + DBGLOG(HAL, STATE, "Suspend wow power save idx:%d, mode:%d\n", idx, ePwrMode); + + DBGLOG(HAL, STATE, "enter WOW flow\n"); + kalWowProcess(prGlueInfo, TRUE); + } + } + + /* After resuming, WinStart will unsync with AP's SN. + * Set fgFirstSnToWinStart for all valid BA entry before suspend. + */ + for (idx = 0; idx < CFG_STA_REC_NUM; idx++) { + prStaRec = cnmGetStaRecByIndex(prGlueInfo->prAdapter, idx); + if (!prStaRec) + continue; + + for (i = 0; i < CFG_RX_MAX_BA_TID_NUM; i++) { + prRxBaEntry = prStaRec->aprRxReorderParamRefTbl[i]; + if (!prRxBaEntry || !(prRxBaEntry->fgIsValid)) + continue; + + prRxBaEntry->fgFirstSnToWinStart = TRUE; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to restore power-saving mode command when AIS leave wow +* But ignore GC/GO/AP role +* +* @param prGlueInfo Pointer of prGlueInfo Data Structure +* +* @return VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanResumePmHandle(P_GLUE_INFO_T prGlueInfo) +{ + PARAM_POWER_MODE ePwrMode = Param_PowerModeCAM; + UINT_8 ucKekZeroCnt = 0; + UINT_8 ucKckZeroCnt = 0; + UINT_8 ucGtkOffload = TRUE; + UINT_8 i = 0; +#if CFG_SUPPORT_REPLAY_DETECTION + struct SEC_DETECT_REPLAY_INFO *prDetRplyInfo = NULL; + P_BSS_INFO_T prBssInfo = NULL; + UINT_8 ucIdx = 0; + UINT_8 ucKeyIdx = 0; + UINT_8 ucRpyOffload = 0; +#endif + + /* if wifi.cfg EAPOL offload is disble, we disable FW offload when leave wow */ + if (!prGlueInfo->prAdapter->rWifiVar.ucEapolOffload) { + + /* + * check if KCK, KEK not sync from supplicant. + * if no these info updated from supplicant, + *disable GTK offload feature. + */ + for (i = 0; i < NL80211_KEK_LEN; i++) { + if (prGlueInfo->rWpaInfo.aucKek[i] == 0x00) + ucKekZeroCnt++; + } + + for (i = 0; i < NL80211_KCK_LEN; i++) { + if (prGlueInfo->rWpaInfo.aucKck[i] == 0x00) + ucKckZeroCnt++; + } + + if ((ucKekZeroCnt == NL80211_KCK_LEN) || + (ucKckZeroCnt == NL80211_KCK_LEN)) { + + DBGLOG(RSN, INFO, "no rekey offload, due to no KCK/KEK from cfg80211\n"); + + prGlueInfo->prAdapter->rWifiVar.ucRpyDetectOffload = FEATURE_DISABLED; + + ucGtkOffload = FALSE; + /* set bc/mc replay detection off to fw */ + wlanSuspendRekeyOffload(prGlueInfo, + GTK_REKEY_CMD_MODE_RPY_OFFLOAD_OFF); + + } + +#if CFG_SUPPORT_REPLAY_DETECTION + prBssInfo = GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex); + prDetRplyInfo = &prBssInfo->rDetRplyInfo; + + /* as resume performed, reset BC/MC KeyRSC, to prevent incorrect replay detection. */ + for (ucKeyIdx = 0; ucKeyIdx < 4; ucKeyIdx++) { + for (ucIdx = 0; ucIdx < NL80211_KEYRSC_LEN; ucIdx++) + prDetRplyInfo->arReplayPNInfo[ucKeyIdx].auPN[ucIdx] = 0x0; + } + + ucRpyOffload = prGlueInfo->prAdapter->rWifiVar.ucRpyDetectOffload; + + /* sync BC/MC PN */ + if (ucRpyOffload && ucGtkOffload) + wlanSuspendRekeyOffload(prGlueInfo, GTK_REKEY_CMD_MODE_GET_BCMC_PN); +#endif + + if (ucGtkOffload) { + wlanSuspendRekeyOffload(prGlueInfo, GTK_REKEY_CMD_MODE_OFLOAD_OFF); + DBGLOG(HAL, STATE, "Resume rekey offload disable\n"); + } + } + + if (prGlueInfo->prAdapter->rWifiVar.ucWow + && (prGlueInfo->prAdapter->rWowCtrl.fgWowEnable + || prGlueInfo->prAdapter->rWifiVar.ucAdvPws)) { + if (kalGetMediaStateIndicated(prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + DBGLOG(HAL, STATE, "leave WOW flow. AIS BssIndex:%d\n", + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex); + kalWowProcess(prGlueInfo, FALSE); + + /* resume AIS power-saving cmd when leave wow state, ignore ePwrMode input */ + nicConfigPowerSaveWowProfile(prGlueInfo->prAdapter, + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex, ePwrMode, FALSE, FALSE); + } + } + + if (prGlueInfo->prAdapter->u4IsKeepFullPwrBitmap) + wlanKeepFullPwr(prGlueInfo->prAdapter, TRUE); +} + +void disconnect_sta(P_ADAPTER_T prAdapter, P_STA_RECORD_T sta_rec) +{ + P_GLUE_INFO_T glue_info; + P_MSG_AIS_ABORT_T ais_abort_msg = NULL; + P_MSG_P2P_CONNECTION_ABORT_T p2p_abot_msg = NULL; + P_BSS_INFO_T p2p_bss_info = NULL; + unsigned char role_idx = 0; + + + if (!prAdapter) { + DBGLOG(MEM, ERROR, "prAdapter is NULL\n"); + return; + } + if (!sta_rec) { + DBGLOG(MEM, ERROR, "sta_rec is NULL\n"); + return; + } + + glue_info = prAdapter->prGlueInfo; + + switch (sta_rec->eStaType) { + case STA_TYPE_LEGACY_AP: + if (prAdapter->rAcpiState == ACPI_STATE_D3) + return; + /* prepare message to AIS */ + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = FALSE; + /* Send AIS Abort Message */ + ais_abort_msg = + (P_MSG_AIS_ABORT_T)cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(MSG_AIS_ABORT_T)); + if (ais_abort_msg) { + ais_abort_msg->rMsgHdr.eMsgId = + MID_OID_AIS_FSM_JOIN_REQ; + ais_abort_msg->ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_DISASSOCIATED; + ais_abort_msg->fgDelayIndication = FALSE; + + DBGLOG(AIS, INFO, + "Disconnect STA["MACSTR"] type:0x%x\n", + MAC2STR(sta_rec->aucMacAddr), sta_rec->eStaType); + + mboxSendMsg(prAdapter, MBOX_ID_0, + (P_MSG_HDR_T) ais_abort_msg, + MSG_SEND_METHOD_UNBUF); +#define DISCONNECT_STATUS WLAN_STATUS_MEDIA_DISCONNECT + /* indicate for disconnection */ + if (kalGetMediaStateIndicated(glue_info) == + PARAM_MEDIA_STATE_CONNECTED) { + kalIndicateStatusAndComplete(glue_info, + DISCONNECT_STATUS, + NULL, + 0); + } +#undef DISCONNECT_STATUS + } + break; + case STA_TYPE_LEGACY_CLIENT: + case STA_TYPE_P2P_GC: + case STA_TYPE_P2P_GO: + p2p_abot_msg = + (P_MSG_P2P_CONNECTION_ABORT_T) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(MSG_P2P_CONNECTION_ABORT_T)); + + if (p2p_abot_msg) { + p2p_bss_info = + GET_BSS_INFO_BY_INDEX(prAdapter, + sta_rec->ucBssIndex); + role_idx = p2p_bss_info->u4PrivateData; + p2p_abot_msg->rMsgHdr.eMsgId = + MID_MNY_P2P_CONNECTION_ABORT; + COPY_MAC_ADDR(p2p_abot_msg->aucTargetID, + sta_rec->aucMacAddr); + + p2p_abot_msg->u2ReasonCode = REASON_CODE_UNSPECIFIED; + p2p_abot_msg->ucRoleIdx = role_idx; + p2p_abot_msg->fgSendDeauth = FALSE; + + DBGLOG(P2P, INFO, + "Disconnect STA["MACSTR"] type:0x%x\n", + MAC2STR(sta_rec->aucMacAddr), sta_rec->eStaType); + + mboxSendMsg(prAdapter, MBOX_ID_0, + (P_MSG_HDR_T)p2p_abot_msg, + MSG_SEND_METHOD_UNBUF); + } + break; + default: + break; + } +} + +#if CFG_SUPPORT_CSI +bool wlanPushCSIData(P_ADAPTER_T prAdapter, struct CSI_DATA_T *prCSIData) +{ + struct CSI_INFO_T *prCSIInfo = &(prAdapter->rCSIInfo); + + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_CSI_BUFFER); + + /* Put the CSI data into CSI event queue */ + if (prCSIInfo->u4CSIBufferUsed != 0) { + prCSIInfo->u4CSIBufferTail++; + prCSIInfo->u4CSIBufferTail %= CSI_RING_SIZE; + } + + kalMemCopy(&(prCSIInfo->arCSIBuffer[prCSIInfo->u4CSIBufferTail]), + prCSIData, sizeof(struct CSI_DATA_T)); + + if (prCSIInfo->u4CSIBufferUsed < CSI_RING_SIZE) { + prCSIInfo->u4CSIBufferUsed++; + } else { + /* + * While new CSI event comes and the ring buffer is + * already full, the new coming CSI event will + * overwrite the oldest one in the ring buffer. + * Thus, the Head pointer which points to * the + * oldest CSI event in the buffer should be moved too. + */ + prCSIInfo->u4CSIBufferHead++; + prCSIInfo->u4CSIBufferHead %= CSI_RING_SIZE; + } + + KAL_RELEASE_MUTEX(prAdapter, MUTEX_CSI_BUFFER); + + return TRUE; +} + +bool wlanPopCSIData(P_ADAPTER_T prAdapter, struct CSI_DATA_T *prCSIData) +{ + struct CSI_INFO_T *prCSIInfo = &(prAdapter->rCSIInfo); + + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_CSI_BUFFER); + + /* No CSI data in the ring buffer */ + if (prCSIInfo->u4CSIBufferUsed == 0) { + KAL_RELEASE_MUTEX(prAdapter, MUTEX_CSI_BUFFER); + return FALSE; + } + + kalMemCopy(prCSIData, + &(prCSIInfo->arCSIBuffer[prCSIInfo->u4CSIBufferHead]), + sizeof(struct CSI_DATA_T)); + + prCSIInfo->u4CSIBufferUsed--; + if (prCSIInfo->u4CSIBufferUsed != 0) { + prCSIInfo->u4CSIBufferHead++; + prCSIInfo->u4CSIBufferHead %= CSI_RING_SIZE; + } + KAL_RELEASE_MUTEX(prAdapter, MUTEX_CSI_BUFFER); + + return TRUE; +} + +VOID +wlanApplyCSIToneMask( + UINT_8 ucRxMode, + UINT_8 ucCBW, + UINT_8 ucDBW, + UINT_8 ucPrimaryChIdx, + INT_16 *ai2IData, + INT_16 *ai2QData) +{ + UINT_8 ucSize = sizeof(INT_16); + +#define ZERO(index) \ +{ ai2IData[index] = 0; ai2QData[index] = 0; } + +#define ZERO_RANGE(start, end) \ +{\ + kalMemZero(&ai2IData[start], ucSize * (end - start + 1));\ + kalMemZero(&ai2QData[start], ucSize * (end - start + 1));\ +} + + if (ucRxMode == RX_VT_LEGACY_OFDM) { + if (ucCBW == RX_VT_FR_MODE_20) { + ZERO(0); + ZERO_RANGE(27, 37); + } else if (ucCBW == RX_VT_FR_MODE_40) { + if (ucDBW == RX_VT_FR_MODE_40) { + ZERO(32); ZERO(96); + ZERO_RANGE(0, 5); + ZERO_RANGE(59, 69); + ZERO_RANGE(123, 127); + } else if (ucDBW == RX_VT_FR_MODE_20) { + if (ucPrimaryChIdx == 0) { + ZERO(96); + ZERO_RANGE(0, 69); + ZERO_RANGE(123, 127); + } else { + ZERO(32); + ZERO_RANGE(0, 5); + ZERO_RANGE(59, 127); + } + } + } else if (ucCBW == RX_VT_FR_MODE_80) { + if (ucDBW == RX_VT_FR_MODE_80) { + ZERO(32); ZERO(96); + ZERO(160); ZERO(224); + ZERO_RANGE(0, 5); + ZERO_RANGE(59, 69); + ZERO_RANGE(123, 133); + ZERO_RANGE(187, 197); + ZERO_RANGE(251, 255); + } else if (ucDBW == RX_VT_FR_MODE_40) { + if (ucPrimaryChIdx <= 1) { + ZERO(160); ZERO(224); + ZERO_RANGE(0, 133); + ZERO_RANGE(187, 197); + ZERO_RANGE(251, 255); + } else { + ZERO(32); ZERO(96); + ZERO_RANGE(0, 5); + ZERO_RANGE(59, 69); + ZERO_RANGE(123, 255); + } + } else if (ucDBW == RX_VT_FR_MODE_20) { + if (ucPrimaryChIdx == 0) { + ZERO(160); + ZERO_RANGE(0, 133); + ZERO_RANGE(187, 255); + } else if (ucPrimaryChIdx == 1) { + ZERO(224); + ZERO_RANGE(0, 197); + ZERO_RANGE(251, 255); + } else if (ucPrimaryChIdx == 2) { + ZERO(32); + ZERO_RANGE(0, 5); + ZERO_RANGE(59, 255); + } else { + ZERO(96); + ZERO_RANGE(0, 69); + ZERO_RANGE(123, 255); + } + } + } + } else if (ucRxMode == RX_VT_MIXED_MODE || + ucRxMode == RX_VT_GREEN_MODE || + ucRxMode == RX_VT_VHT_MODE) { + if (ucCBW == RX_VT_FR_MODE_20) { + ZERO(0); + ZERO_RANGE(29, 35); + } else if (ucCBW == RX_VT_FR_MODE_40) { + if (ucDBW == RX_VT_FR_MODE_40) { + ZERO(0); ZERO(1); ZERO(127); + ZERO_RANGE(59, 69); + } else if (ucDBW == RX_VT_FR_MODE_20) { + if (ucPrimaryChIdx == 0) { + ZERO(96); + ZERO_RANGE(0, 67); + ZERO_RANGE(125, 127); + } else { + ZERO(32); + ZERO_RANGE(0, 3); + ZERO_RANGE(61, 127); + } + } + } else if (ucCBW == RX_VT_FR_MODE_80) { + if (ucDBW == RX_VT_FR_MODE_80) { + ZERO(0); ZERO(1); ZERO(255); + ZERO_RANGE(123, 133); + } else if (ucDBW == RX_VT_FR_MODE_40) { + if (ucPrimaryChIdx <= 1) { + ZERO_RANGE(0, 133); + ZERO_RANGE(191, 193); + ZERO_RANGE(251, 255); + } else { + ZERO_RANGE(0, 5); + ZERO_RANGE(63, 65); + ZERO_RANGE(123, 127); + } + } else if (ucDBW == RX_VT_FR_MODE_20) { + if (ucPrimaryChIdx == 0) { + ZERO(160); + ZERO_RANGE(0, 131); + ZERO_RANGE(189, 255); + } else if (ucPrimaryChIdx == 1) { + ZERO(224); + ZERO_RANGE(0, 195); + ZERO_RANGE(253, 255); + } else if (ucPrimaryChIdx == 2) { + ZERO(32); + ZERO_RANGE(0, 3); + ZERO_RANGE(61, 255); + } else { + ZERO(96); + ZERO_RANGE(0, 67); + ZERO_RANGE(125, 255); + } + } + } + } + + /* Mask the VHT Pilots */ + if (ucRxMode == RX_VT_VHT_MODE) { + if (ucCBW == RX_VT_FR_MODE_20) { + ZERO(7); ZERO(21); ZERO(43); ZERO(57); + } else if (ucCBW == RX_VT_FR_MODE_40) { + if (ucDBW == RX_VT_FR_MODE_40) { + ZERO(11); ZERO(25); ZERO(53); + ZERO(75); ZERO(103); ZERO(117); + } else if (ucDBW == RX_VT_FR_MODE_20) { + if (ucPrimaryChIdx == 0) { + ZERO(75); ZERO(89); + ZERO(103); ZERO(117); + } else { + ZERO(11); ZERO(25); + ZERO(39); ZERO(53); + } + } + } else if (ucCBW == RX_VT_FR_MODE_80) { + if (ucDBW == RX_VT_FR_MODE_80) { + ZERO(11); ZERO(39); ZERO(75); ZERO(103); + ZERO(153); ZERO(181); ZERO(217); ZERO(245); + } else if (ucDBW == RX_VT_FR_MODE_40) { + if (ucPrimaryChIdx <= 1) { + ZERO(139); ZERO(167); ZERO(181); + ZERO(203); ZERO(217); ZERO(245); + } else { + ZERO(11); ZERO(39); ZERO(53); + ZERO(75); ZERO(89); ZERO(117); + } + } else if (ucDBW == RX_VT_FR_MODE_20) { + if (ucPrimaryChIdx == 0) { + ZERO(139); ZERO(153); + ZERO(167); ZERO(181); + } else if (ucPrimaryChIdx == 1) { + ZERO(203); ZERO(217); + ZERO(231); ZERO(245); + } else if (ucPrimaryChIdx == 2) { + ZERO(11); ZERO(25); + ZERO(39); ZERO(53); + } else { + ZERO(75); ZERO(89); + ZERO(103); ZERO(117); + } + } + } + } +} + + +VOID +wlanShiftCSI( + UINT_8 ucRxMode, + UINT_8 ucCBW, + UINT_8 ucDBW, + UINT_8 ucPrimaryChIdx, + INT_16 *ai2IData, + INT_16 *ai2QData, + INT_16 *ai2ShiftIData, + INT_16 *ai2ShiftQData) +{ + UINT_8 ucSize = sizeof(INT_16); +#define COPY_RANGE(dest, start, end) \ +{\ + kalMemCopy(&ai2ShiftIData[dest], \ + &ai2IData[start], ucSize * (end - start + 1)); \ + kalMemCopy(&ai2ShiftQData[dest], \ + &ai2QData[start], ucSize * (end - start + 1)); \ +} + +#define COPY(dest, src) \ +{ ai2ShiftIData[dest] = ai2IData[src]; ai2ShiftQData[dest] = ai2QData[src]; } + + if (ucRxMode == RX_VT_LEGACY_OFDM) { + if (ucCBW == RX_VT_FR_MODE_20) { + COPY_RANGE(0, 0, 63); + } else if (ucCBW == RX_VT_FR_MODE_40) { + if (ucDBW == RX_VT_FR_MODE_40) { + COPY_RANGE(0, 0, 127); + } else if (ucDBW == RX_VT_FR_MODE_20) { + if (ucPrimaryChIdx == 0) { + COPY(0, 96); + COPY_RANGE(38, 70, 95); + COPY_RANGE(1, 97, 122); + } else { + COPY(0, 32); + COPY_RANGE(38, 6, 31); + COPY_RANGE(1, 33, 58); + } + } + } else if (ucCBW == RX_VT_FR_MODE_80) { + if (ucDBW == RX_VT_FR_MODE_80) { + COPY_RANGE(0, 0, 255); + } else if (ucDBW == RX_VT_FR_MODE_40) { + if (ucPrimaryChIdx <= 1) { + COPY(0, 192); + COPY_RANGE(2, 198, 250); + COPY_RANGE(74, 134, 186); + } else { + COPY(0, 64); + COPY_RANGE(2, 70, 122); + COPY_RANGE(74, 6, 58); + } + } else if (ucDBW == RX_VT_FR_MODE_20) { + if (ucPrimaryChIdx == 0) { + COPY(0, 160); + COPY_RANGE(1, 161, 186); + COPY_RANGE(38, 134, 159); + } else if (ucPrimaryChIdx == 1) { + COPY(0, 224); + COPY_RANGE(1, 225, 250); + COPY_RANGE(38, 198, 223); + } else if (ucPrimaryChIdx == 2) { + COPY(0, 32); + COPY_RANGE(1, 33, 58); + COPY_RANGE(38, 6, 31); + } else { + COPY(0, 96); + COPY_RANGE(1, 97, 122); + COPY_RANGE(38, 70, 95); + } + } + } + } else if (ucRxMode == RX_VT_MIXED_MODE || + ucRxMode == RX_VT_GREEN_MODE || + ucRxMode == RX_VT_VHT_MODE) { + if (ucCBW == RX_VT_FR_MODE_20) { + COPY_RANGE(0, 0, 63); + } else if (ucCBW == RX_VT_FR_MODE_40) { + if (ucDBW == RX_VT_FR_MODE_40) { + COPY_RANGE(0, 0, 127); + } else if (ucDBW == RX_VT_FR_MODE_20) { + if (ucPrimaryChIdx == 0) { + COPY(0, 96); + COPY_RANGE(36, 68, 95); + COPY_RANGE(1, 97, 124); + } else { + COPY(0, 32); + COPY_RANGE(36, 4, 31); + COPY_RANGE(1, 33, 60); + } + } + } else if (ucCBW == RX_VT_FR_MODE_80) { + if (ucDBW == RX_VT_FR_MODE_80) { + COPY_RANGE(0, 0, 255); + } else if (ucDBW == RX_VT_FR_MODE_40) { + if (ucPrimaryChIdx <= 1) { + COPY(0, 192); + COPY_RANGE(2, 194, 250); + COPY_RANGE(70, 134, 190); + } else { + COPY(0, 64); + COPY_RANGE(2, 66, 122); + COPY_RANGE(70, 6, 62); + } + } else if (ucDBW == RX_VT_FR_MODE_20) { + if (ucPrimaryChIdx == 0) { + COPY(0, 160); + COPY_RANGE(1, 161, 188); + COPY_RANGE(36, 132, 159); + } else if (ucPrimaryChIdx == 1) { + COPY(0, 224); + COPY_RANGE(1, 225, 252); + COPY_RANGE(36, 196, 223); + } else if (ucPrimaryChIdx == 2) { + COPY(0, 32); + COPY_RANGE(1, 33, 60); + COPY_RANGE(36, 4, 31); + } else { + COPY(0, 96); + COPY_RANGE(1, 97, 124); + COPY_RANGE(36, 68, 95); + } + } + } + } +} +#endif + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/common/wlan_oid.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/common/wlan_oid.c new file mode 100644 index 0000000000000..2ee049c77ea7e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/common/wlan_oid.c @@ -0,0 +1,12671 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/common/wlan_oid.c#11 +*/ + +/*! \file wlanoid.c + * \brief This file contains the WLAN OID processing routines of Windows 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" +#include "mgmt/rsn.h" +#include "gl_wext.h" +#include "gl_vendor.h" +#include "debug.h" +#include + +/****************************************************************************** +* C O N S T A N T S +******************************************************************************* +*/ + +/****************************************************************************** +* D A T A T Y P E S +******************************************************************************* +*/ + +/****************************************************************************** +* P U B L I C D A T A +******************************************************************************* +*/ + +PARAM_CUSTOM_KEY_CFG_STRUCT_T g_rDefaulteSetting[] = { + /*format : + *: {"firmware config parameter", "firmware config value"} + */ + {"AdapScan", "0x0"} +}; + + +/****************************************************************************** +* P R I V A T E D A T A +******************************************************************************* +*/ + +/****************************************************************************** +* M A C R O S +******************************************************************************* +*/ + +/****************************************************************************** +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************* +*/ +#if DBG && 0 +static VOID SetRCID(BOOLEAN fgOneTb3, BOOL *fgRCID); +#endif + +#if CFG_SLT_SUPPORT +static VOID SetTestChannel(UINT_8 *pucPrimaryChannel); +#endif + +/****************************************************************************** +* 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 + +#if DBG && 0 +static VOID SetRCID(BOOLEAN fgOneTb3, BOOL *fgRCID) +{ + if (fgOneTb3) + *fgRCID = 0; + else + *fgRCID = 1; +} +#endif + +#if CFG_SLT_SUPPORT +static VOID SetTestChannel(UINT_8 *pucPrimaryChannel) +{ + if (*pucPrimaryChannel < 5) + *pucPrimaryChannel = 8; + else if (*pucPrimaryChannel > 10) + *pucPrimaryChannel = 3; +} +#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: %u\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 + return WLAN_STATUS_FAILURE; + } else + return WLAN_STATUS_FAILURE; + } else +#endif + { + if (prAdapter->fgEnOnlineScan == TRUE) + aisFsmScanRequest(prAdapter, prSsid, NULL, 0); + else if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) + aisFsmScanRequest(prAdapter, prSsid, NULL, 0); + else + return WLAN_STATUS_FAILURE; + } + + cnmTimerStartTimer(prAdapter, + &prAdapter->rWifiVar.rAisFsmInfo.rScanDoneTimer, + SEC_TO_MSEC(AIS_SCN_DONE_TIMEOUT_SEC)); + + 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; + } + DBGLOG(AIS, INFO, "ScanEX\n"); + 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 + return WLAN_STATUS_FAILURE; + } else + return WLAN_STATUS_FAILURE; + } else +#endif + { + if (prAdapter->fgEnOnlineScan == TRUE) + aisFsmScanRequest(prAdapter, prSsid, pucIe, u4IeLength); + else if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) + aisFsmScanRequest(prAdapter, prSsid, pucIe, u4IeLength); + else + return WLAN_STATUS_FAILURE; + } + + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetBssidListScanWithIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request the driver to perform +* scanning with attaching information elements(IEs) specified from user space +* and multiple SSID +* +* \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 +wlanoidSetBssidListScanAdv(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_SCAN_REQUEST_ADV_T prScanRequest; + PARAM_SSID_T rSsid[CFG_SCAN_SSID_MAX_NUM]; + PUINT_8 pucIe; + UINT_8 ucSsidNum; + UINT_32 i, u4IeLength; + + DEBUGFUNC("wlanoidSetBssidListScanAdv()"); + + 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_ADV_T)) + return WLAN_STATUS_INVALID_LENGTH; + else if (pvSetBuffer == NULL) + return WLAN_STATUS_INVALID_DATA; + + 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; + } + + prScanRequest = (P_PARAM_SCAN_REQUEST_ADV_T) pvSetBuffer; + + ucSsidNum = (UINT_8) (prScanRequest->u4SsidNum); + for (i = 0; i < prScanRequest->u4SsidNum; i++) { + if (prScanRequest->rSsid[i].u4SsidLen > ELEM_MAX_LEN_SSID) { + DBGLOG(REQ, ERROR, + "[%s] SSID(%s) Length(%d) is over than ELEM_MAX_LEN_SSID(%d)\n", + __func__, prScanRequest->rSsid[i].aucSsid, + prScanRequest->rSsid[i].u4SsidLen, ELEM_MAX_LEN_SSID); + DBGLOG_MEM8(REQ, ERROR, prScanRequest, sizeof(PARAM_SCAN_REQUEST_ADV_T)); + + } + COPY_SSID(rSsid[i].aucSsid, + rSsid[i].u4SsidLen, prScanRequest->rSsid[i].aucSsid, prScanRequest->rSsid[i].u4SsidLen); + } + + pucIe = prScanRequest->pucIE; + u4IeLength = prScanRequest->u4IELength; + +#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) +#if CFG_SCAN_CHANNEL_SPECIFIED + aisFsmScanRequestAdv(prAdapter, ucSsidNum, rSsid, + prScanRequest->ucChannelListNum, prScanRequest->arChnlInfoList, + pucIe, u4IeLength); +#else + aisFsmScanRequestAdv(prAdapter, ucSsidNum, rSsid, 0, NULL, pucIe, u4IeLength); +#endif + else + return WLAN_STATUS_FAILURE; + } else + return WLAN_STATUS_FAILURE; + } else +#endif + { + if (prAdapter->fgEnOnlineScan == TRUE) +#if CFG_SCAN_CHANNEL_SPECIFIED + aisFsmScanRequestAdv(prAdapter, ucSsidNum, rSsid, + prScanRequest->ucChannelListNum, prScanRequest->arChnlInfoList, + pucIe, u4IeLength); +#else + aisFsmScanRequestAdv(prAdapter, ucSsidNum, rSsid, 0, NULL, pucIe, u4IeLength); +#endif + else if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) +#if CFG_SCAN_CHANNEL_SPECIFIED + aisFsmScanRequestAdv(prAdapter, ucSsidNum, rSsid, + prScanRequest->ucChannelListNum, prScanRequest->arChnlInfoList, + pucIe, u4IeLength); +#else + aisFsmScanRequestAdv(prAdapter, ucSsidNum, rSsid, 0, NULL, pucIe, u4IeLength); +#endif + else + return WLAN_STATUS_FAILURE; + } + cnmTimerStartTimer(prAdapter, &prAdapter->rWifiVar.rAisFsmInfo.rScanDoneTimer, + SEC_TO_MSEC(AIS_SCN_DONE_TIMEOUT_SEC)); + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetBssidListScanAdv */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine will initiate the join procedure to attempt to associate +* with the specified BSSID. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBssid(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + P_UINT_8 pAddr; + UINT_32 i; + INT_32 i4Idx = -1; + P_MSG_AIS_ABORT_T prAisAbortMsg; + UINT_8 ucReasonOfDisconnect; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = MAC_ADDR_LEN; + if (u4SetBufferLen != MAC_ADDR_LEN) { + *pu4SetInfoLen = MAC_ADDR_LEN; + return WLAN_STATUS_INVALID_LENGTH; + } else if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(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); + ucReasonOfDisconnect = DISCONNECT_REASON_CODE_REASSOCIATION; + } else { + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; + } + } else { + ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; + } + + /* check if any scanned result matchs with the BSSID */ + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.arScanResult[i].arMacAddress, pAddr)) { + i4Idx = (INT_32) i; + break; + } + } + + /* prepare message to AIS */ + if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_IBSS + || prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_DEDICATED_IBSS) { + /* IBSS *//* beacon period */ + prAdapter->rWifiVar.rConnSettings.u2BeaconPeriod = prAdapter->rWlanInfo.u2BeaconPeriod; + prAdapter->rWifiVar.rConnSettings.u2AtimWindow = prAdapter->rWlanInfo.u2AtimWindow; + } + + /* Set Connection Request Issued Flag */ + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = TRUE; + prAdapter->rWifiVar.rConnSettings.eConnectionPolicy = CONNECT_BY_BSSID; + + /* Send AIS Abort Message */ + prAisAbortMsg = (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); + if (!prAisAbortMsg) { + DBGLOG(REQ, ERROR, "Fail in allocating AisAbortMsg.\n"); + return WLAN_STATUS_FAILURE; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; + prAisAbortMsg->ucReasonOfDisconnect = ucReasonOfDisconnect; + + /* Update the information to CONNECTION_SETTINGS_T */ + prAdapter->rWifiVar.rConnSettings.ucSSIDLen = 0; + prAdapter->rWifiVar.rConnSettings.aucSSID[0] = '\0'; + COPY_MAC_ADDR(prAdapter->rWifiVar.rConnSettings.aucBSSID, pAddr); + + if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, pAddr)) + prAisAbortMsg->fgDelayIndication = TRUE; + else + prAisAbortMsg->fgDelayIndication = FALSE; + +#if CFG_DISCONN_DEBUG_FEATURE + /* used to disconnect debug capability */ + g_rDisconnInfoTemp.ucTrigger = DISCONNECT_TRIGGER_ACTIVE; +#endif + + 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 (!((pParamSsid->aucSsid[i] > 0) + && (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) { + DBGLOG(REQ, ERROR, "Fail in allocating AisAbortMsg.\n"); + return WLAN_STATUS_FAILURE; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; + COPY_SSID(prAdapter->rWifiVar.rConnSettings.aucSSID, + prAdapter->rWifiVar.rConnSettings.ucSSIDLen, pParamSsid->aucSsid, (UINT_8) pParamSsid->u4SsidLen); + + if (EQUAL_SSID(prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, + prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen, pParamSsid->aucSsid, pParamSsid->u4SsidLen)) { + prAisAbortMsg->fgDelayIndication = TRUE; + } else { + /* Update the information to CONNECTION_SETTINGS_T */ + prAisAbortMsg->fgDelayIndication = FALSE; + } + DBGLOG(SCN, INFO, "SSID %s\n", prAdapter->rWifiVar.rConnSettings.aucSSID); + +#if CFG_DISCONN_DEBUG_FEATURE + /* used to disconnect debug capability */ + g_rDisconnInfoTemp.ucTrigger = DISCONNECT_TRIGGER_ACTIVE; +#endif + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); + + return WLAN_STATUS_SUCCESS; + +} /* end of wlanoidSetSsid() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine will initiate the join procedure to attempt +* to associate with the new BSS, base on given SSID, BSSID, and freqency. +* If the target connecting BSS is in the same ESS as current connected BSS, roaming +* will be performed. +* +* \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 +wlanoidSetConnect(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + P_PARAM_CONNECT_T pParamConn; + P_CONNECTION_SETTINGS_T prConnSettings; + UINT_32 i; + P_MSG_AIS_ABORT_T prAisAbortMsg; + BOOLEAN fgIsValidSsid = TRUE; + BOOLEAN fgEqualSsid = FALSE; + BOOLEAN fgEqualBssid = FALSE; + const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* MSDN: + * Powering on the radio if the radio is powered off through a setting of OID_802_11_DISASSOCIATE + */ + if (prAdapter->fgIsRadioOff == TRUE) + prAdapter->fgIsRadioOff = FALSE; + + if (u4SetBufferLen != sizeof(PARAM_CONNECT_T)) + return WLAN_STATUS_INVALID_LENGTH; + else if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(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; + } + prAisAbortMsg = (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); + if (!prAisAbortMsg) { + DBGLOG(REQ, ERROR, "Fail in allocating AisAbortMsg.\n"); + return WLAN_STATUS_FAILURE; + } + prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; + + pParamConn = (P_PARAM_CONNECT_T) pvSetBuffer; + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + + if (pParamConn->u4SsidLen > 32) { + cnmMemFree(prAdapter, prAisAbortMsg); + DBGLOG(OID, WARN, "SsidLen [%d] is invalid!\n", + pParamConn->u4SsidLen); + return WLAN_STATUS_INVALID_LENGTH; + } else if (!pParamConn->pucBssid && !pParamConn->pucSsid) { + cnmMemFree(prAdapter, prAisAbortMsg); + DBGLOG(OID, WARN, "Bssid or ssid is invalid!\n"); + return WLAN_STATUS_INVALID_LENGTH; + } + + prGlueInfo = prAdapter->prGlueInfo; + kalMemZero(prConnSettings->aucSSID, sizeof(prConnSettings->aucSSID)); + prConnSettings->ucSSIDLen = 0; + kalMemZero(prConnSettings->aucBSSID, sizeof(prConnSettings->aucBSSID)); + prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_ANY; + prConnSettings->fgIsConnByBssidIssued = FALSE; + + if (pParamConn->pucSsid) { + prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_BEST_RSSI; + COPY_SSID(prConnSettings->aucSSID, + prConnSettings->ucSSIDLen, pParamConn->pucSsid, (UINT_8) pParamConn->u4SsidLen); + if (EQUAL_SSID(prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, + prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen, + pParamConn->pucSsid, pParamConn->u4SsidLen)) + fgEqualSsid = TRUE; + } + if (pParamConn->pucBssid) { + if (!EQUAL_MAC_ADDR(aucZeroMacAddr, pParamConn->pucBssid) && IS_UCAST_MAC_ADDR(pParamConn->pucBssid)) { + prConnSettings->eConnectionPolicy = CONNECT_BY_BSSID; + prConnSettings->fgIsConnByBssidIssued = TRUE; + COPY_MAC_ADDR(prConnSettings->aucBSSID, pParamConn->pucBssid); + if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, pParamConn->pucBssid)) + fgEqualBssid = TRUE; + } else + DBGLOG(INIT, INFO, "wrong bssid " MACSTR "to connect\n", MAC2STR(pParamConn->pucBssid)); + } else + DBGLOG(INIT, INFO, "No Bssid set\n"); + prConnSettings->u4FreqInKHz = pParamConn->u4CenterFreq; + + /* prepare for CMD_BUILD_CONNECTION & CMD_GET_CONNECTION_STATUS */ + /* re-association check */ + if (kalGetMediaStateIndicated(prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + if (fgEqualSsid) { + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_REASSOCIATION; + if (fgEqualBssid) + kalSetMediaStateIndicated(prGlueInfo, PARAM_MEDIA_STATE_TO_BE_INDICATED); + } else { + DBGLOG(INIT, INFO, "DisBySsid\n"); + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; + } + } else + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; + +#if 0 + /* check if any scanned result matchs with the SSID */ + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + PUINT_8 aucSsid = prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid; + UINT_8 ucSsidLength = (UINT_8) prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen; + INT_32 i4RSSI = prAdapter->rWlanInfo.arScanResult[i].rRssi; + + if (EQUAL_SSID(aucSsid, ucSsidLength, pParamConn->pucSsid, pParamConn->u4SsidLen) && + i4RSSI >= i4MaxRSSI) { + i4Idx = (INT_32) i; + i4MaxRSSI = i4RSSI; + } + if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.arScanResult[i].arMacAddress, pAddr)) { + i4Idx = (INT_32) i; + break; + } + } +#endif + /* prepare message to AIS */ + if (prConnSettings->eOPMode == NET_TYPE_IBSS || prConnSettings->eOPMode == NET_TYPE_DEDICATED_IBSS) { + /* IBSS *//* beacon period */ + prConnSettings->u2BeaconPeriod = prAdapter->rWlanInfo.u2BeaconPeriod; + prConnSettings->u2AtimWindow = prAdapter->rWlanInfo.u2AtimWindow; + } + + if (prAdapter->rWifiVar.fgSupportWZCDisassociation) { + if (pParamConn->u4SsidLen == ELEM_MAX_LEN_SSID) { + fgIsValidSsid = FALSE; + + if (pParamConn->pucSsid) { + for (i = 0; i < ELEM_MAX_LEN_SSID; i++) { + if (!((pParamConn->pucSsid[i] > 0) && (pParamConn->pucSsid[i] <= 0x1F))) { + fgIsValidSsid = TRUE; + break; + } + } + } else { + DBGLOG(INIT, ERROR, "pParamConn->pucSsid is NULL\n"); + } + } + } + + /* Set Connection Request Issued Flag */ + if (fgIsValidSsid) + prConnSettings->fgIsConnReqIssued = TRUE; + else + prConnSettings->fgIsConnReqIssued = FALSE; + + if (fgEqualSsid || fgEqualBssid) + prAisAbortMsg->fgDelayIndication = TRUE; + else + /* Update the information to CONNECTION_SETTINGS_T */ + prAisAbortMsg->fgDelayIndication = FALSE; + +#if CFG_DISCONN_DEBUG_FEATURE + /* used to disconnect debug capability */ + g_rDisconnInfoTemp.ucTrigger = DISCONNECT_TRIGGER_ACTIVE; +#endif + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); + + DBGLOG(INIT, INFO, "ssid %s, bssid " MACSTR ", conn policy %d, disc reason %d\n", + prConnSettings->aucSSID, MAC2STR(prConnSettings->aucBSSID), + prConnSettings->eConnectionPolicy, prAisAbortMsg->ucReasonOfDisconnect); + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetConnect */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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 %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prAssociatedSsid = (P_PARAM_SSID_T) pvQueryBuffer; + + kalMemZero(prAssociatedSsid->aucSsid, sizeof(prAssociatedSsid->aucSsid)); + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + prAssociatedSsid->u4SsidLen = prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen; + + if (prAssociatedSsid->u4SsidLen) { + kalMemCopy(prAssociatedSsid->aucSsid, + prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, prAssociatedSsid->u4SsidLen); + } + } else { + prAssociatedSsid->u4SsidLen = 0; + + DBGLOG(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; +/* P_WLAN_TABLE_T prWlanTable; */ +#if CFG_SUPPORT_802_11W +/* P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; */ +#endif +/* P_BSS_INFO_T prBssInfo; */ +/* UINT_8 i; */ + + 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; + + 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 + +#if 0 /* STA record remove at AIS_ABORT nicUpdateBss and DISCONNECT */ + for (i = 0; i < BSS_INFO_NUM; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) + cnmStaFreeAllStaByNetwork(prAdapter, prBssInfo->ucBssIndex, 0); + } +#endif + + /* Clean up the Tx key flag */ + prAdapter->prAisBssInfo->fgBcDefaultKeyExist = FALSE; + prAdapter->prAisBssInfo->ucBcDefaultKeyIdx = 0xFF; + + /* prWlanTable = prAdapter->rWifiVar.arWtbl; */ + /* prWlanTable[prAdapter->prAisBssInfo->ucBMCWlanIndex].ucKeyId = 0; */ + +#if DBG + DBGLOG(RSN, TRACE, "wlanoidSetInfrastructureMode\n"); +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_INFRASTRUCTURE, + TRUE, + FALSE, + g_fgIsOid, + 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; + +#if CFG_SUPPORT_CFG80211_AUTH + case AUTH_MODE_WPA2_SAE: + DBGLOG(REQ, INFO, "Current auth mode: SAE\n"); + break; +#endif + + default: + DBGLOG(REQ, INFO, "Current auth mode: %d\n", *(P_ENUM_PARAM_AUTH_MODE_T) pvQueryBuffer); + break; + } +#endif + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryAuthMode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the IEEE 802.11 authentication mode +* to the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_NOT_ACCEPTED +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAuthMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + /* UINT_32 i, u4AkmSuite; */ + /* P_DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY prEntry; */ + + DEBUGFUNC("wlanoidSetAuthMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + prGlueInfo = prAdapter->prGlueInfo; + + *pu4SetInfoLen = sizeof(ENUM_PARAM_AUTH_MODE_T); + + if (u4SetBufferLen < sizeof(ENUM_PARAM_AUTH_MODE_T)) + return WLAN_STATUS_INVALID_LENGTH; + + /* RF Test */ + /* if (IS_ARB_IN_RFTEST_STATE(prAdapter)) { */ + /* return WLAN_STATUS_SUCCESS; */ + /* } */ + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(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: + break; + } + + /* Save the new authentication mode. */ + prAdapter->rWifiVar.rConnSettings.eAuthMode = *(P_ENUM_PARAM_AUTH_MODE_T) pvSetBuffer; + +#if 1 /* 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; +#if CFG_SUPPORT_SAE + case AUTH_MODE_WPA2_SAE: + DBGLOG(RSN, INFO, "New auth mode: SAE\n"); + break; +#endif + default: + DBGLOG(RSN, TRACE, "New auth mode: unknown (%d)\n", prAdapter->rWifiVar.rConnSettings.eAuthMode); + } +#endif + +#if 0 + 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 + } +#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; + /* ENUM_ENCRYPTION_DISABLED; */ + prAdapter->rWifiVar.rConnSettings.eEncStatus = ENUM_ENCRYPTION1_KEY_ABSENT; + { + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_CMD_802_11_KEY prCmdKey; + UINT_8 aucBCAddr[] = BC_MAC_ADDR; + + prGlueInfo = prAdapter->prGlueInfo; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_802_11_KEY))); + + if (!prCmdInfo) { + DBGLOG(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->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->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 = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + 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->ucBssIdx = prAdapter->prAisBssInfo->ucBssIndex; + + if (prParamKey->u4KeyLength == WEP_40_LEN) + prParamKey->ucCipher = CIPHER_SUITE_WEP40; + else if (prParamKey->u4KeyLength == WEP_104_LEN) + prParamKey->ucCipher = CIPHER_SUITE_WEP104; + else if (prParamKey->u4KeyLength == WEP_128_LEN) + prParamKey->ucCipher = CIPHER_SUITE_WEP128; + + 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 : %u\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: %u\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 %u\n", u4KeyId); + return WLAN_STATUS_INVALID_DATA; + } + + rRemoveKey.u4Length = sizeof(PARAM_REMOVE_KEY_T); + rRemoveKey.u4KeyIndex = *(PUINT_32) pvSetBuffer; + + kalMemCopy(rRemoveKey.arBSSID, aucBCAddr, MAC_ADDR_LEN); + + wlanoidSetRemoveKey(prAdapter, (PVOID)&rRemoveKey, sizeof(PARAM_REMOVE_KEY_T), &u4SetLen); + + return WLAN_STATUS_PENDING; +} /* wlanoidSetRemoveWep */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a key to the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer PARAM_KEY_T, which is set by NDIS, is unpacked. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAddKey(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, 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; + P_BSS_INFO_T prBssInfo; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + P_STA_RECORD_T prStaRec = NULL; + BOOL fgNoHandshakeSec = FALSE; +#if CFG_SUPPORT_TDLS + P_STA_RECORD_T prTmpStaRec; +#endif + + DEBUGFUNC("wlanoidSetAddKey"); + DBGLOG(REQ, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + DBGLOG(RSN, INFO, "wlanoidSetAddKey\n"); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(RSN, 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(RSN, 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(RSN, 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(RSN, INFO, "Set: Dump PARAM_KEY content\n"); + DBGLOG(RSN, INFO, "Length : 0x%08x\n", prNewKey->u4Length); + DBGLOG(RSN, INFO, "Key Index : 0x%08x\n", prNewKey->u4KeyIndex); + DBGLOG(RSN, INFO, "Key Length: 0x%08x\n", prNewKey->u4KeyLength); + DBGLOG(RSN, INFO, "BSSID:\n"); + DBGLOG(RSN, INFO, MACSTR "\n", MAC2STR(prNewKey->arBSSID)); + DBGLOG(RSN, INFO, "Cipher : %d\n", prNewKey->ucCipher); + DBGLOG(RSN, TRACE, "Key RSC:\n"); + DBGLOG_MEM8(RSN, TRACE, &prNewKey->rKeyRSC, sizeof(PARAM_KEY_RSC)); + DBGLOG(RSN, INFO, "Key Material:\n"); + DBGLOG_MEM8(RSN, INFO, prNewKey->aucKeyMaterial, prNewKey->u4KeyLength); + + prGlueInfo = prAdapter->prGlueInfo; + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prNewKey->ucBssIdx); + + if (!prBssInfo) { + DBGLOG(REQ, INFO, "BSS Info not exist !!\n"); + return WLAN_STATUS_SUCCESS; + } + + /* Tx Rx KeyType addr + * STA, GC: + * case1: 1 1 0 BC addr (no sta record of AP at this moment) WEP, + * notice: tx at default key setting WEP key now save to BSS_INFO + * case2: 0 1 0 BSSID (sta record of AP) RSN BC key + * case3: 1 1 1 AP addr (sta record of AP) RSN STA key + * + * GO: + * case1: 1 1 0 BSSID (no sta record) WEP -- Not support + * case2: 1 0 0 BSSID (no sta record) RSN BC key + * case3: 1 1 1 STA addr STA key + */ + + if (prNewKey->ucCipher == CIPHER_SUITE_WEP40 || + prNewKey->ucCipher == CIPHER_SUITE_WEP104 || prNewKey->ucCipher == CIPHER_SUITE_WEP128) { + /* check if the key no need handshake, then save to bss wep key for global usage */ + fgNoHandshakeSec = TRUE; + } + + if (fgNoHandshakeSec) { +#if DBG + if (IS_BSS_AIS(prBssInfo)) { + if (prAdapter->rWifiVar.rConnSettings.eAuthMode >= AUTH_MODE_WPA + && prAdapter->rWifiVar.rConnSettings.eAuthMode != AUTH_MODE_WPA_NONE) { + DBGLOG(RSN, WARN, "Set wep at not open/shared setting\n"); + return WLAN_STATUS_SUCCESS; + } + } +#endif + } + + if ((prNewKey->u4KeyIndex & IS_UNICAST_KEY) == IS_UNICAST_KEY) { + prStaRec = cnmGetStaRecByAddress(prAdapter, prBssInfo->ucBssIndex, prNewKey->arBSSID); + if (!prStaRec) { /* Already disconnected ? */ + DBGLOG(REQ, INFO, "[wlan] Not set the peer key while disconnect\n"); + return WLAN_STATUS_SUCCESS; + } + } + + 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->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_802_11_KEY); +#if CFG_SUPPORT_REPLAY_DETECTION + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetAddKey; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutSetAddKey; +#else + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; +#endif + prCmdInfo->fgIsOid = g_fgIsOid; + prCmdInfo->ucCID = CMD_ID_ADD_REMOVE_KEY; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = 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 = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + 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; + + /* Copy the addr of the key */ + if ((prNewKey->u4KeyIndex & IS_UNICAST_KEY) == IS_UNICAST_KEY) { + if (prStaRec) { + /* Overwrite the fgNoHandshakeSec in case */ + fgNoHandshakeSec = FALSE; /* Legacy 802.1x wep case ? */ + /* ASSERT(FALSE); */ + } + } else { + if (!IS_BSS_ACTIVE(prBssInfo)) + DBGLOG(REQ, INFO, "[wlan] BSS info (%d) not active yet!", prNewKey->ucBssIdx); + + } + + prCmdKey->ucBssIdx = prBssInfo->ucBssIndex; + prCmdKey->ucKeyId = (UINT_8) (prNewKey->u4KeyIndex & 0xff); + + /* Note: the key length may not correct for WPA-None */ + prCmdKey->ucKeyLen = (UINT_8) prNewKey->u4KeyLength; + + kalMemCopy(prCmdKey->aucKeyMaterial, (PUINT_8) prNewKey->aucKeyMaterial, prCmdKey->ucKeyLen); + + if (prNewKey->ucCipher) { + prCmdKey->ucAlgorithmId = prNewKey->ucCipher; + if (IS_BSS_AIS(prBssInfo)) { +#if CFG_SUPPORT_802_11W + if (prCmdKey->ucAlgorithmId == CIPHER_SUITE_BIP) { + if (prCmdKey->ucKeyId >= 4) { + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + prAisSpecBssInfo->fgBipKeyInstalled = TRUE; + } + } +#endif + if ((prCmdKey->ucAlgorithmId == CIPHER_SUITE_CCMP) && rsnCheckPmkidCandicate(prAdapter)) { + 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)); + } + if (prCmdKey->ucAlgorithmId == CIPHER_SUITE_TKIP) { + /* Todo:: Support AP mode defragment */ + /* for pairwise key only */ + if ((prNewKey->u4KeyIndex & BITS(30, 31)) == ((IS_UNICAST_KEY) | (IS_TRANSMIT_KEY))) { + kalMemCopy(prAdapter->rWifiVar.rAisSpecificBssInfo.aucRxMicKey, + &prCmdKey->aucKeyMaterial[16], MIC_KEY_LEN); + kalMemCopy(prAdapter->rWifiVar.rAisSpecificBssInfo.aucTxMicKey, + &prCmdKey->aucKeyMaterial[24], MIC_KEY_LEN); + } + } + } else { +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if ((prCmdKey->ucKeyId >= 4 && prCmdKey->ucKeyId <= 5) && + (prCmdKey->ucAlgorithmId == CIPHER_SUITE_BIP)) { + DBGLOG(RSN, INFO, "AP mode set BIP\n"); + prBssInfo->rApPmfCfg.fgBipKeyInstalled = TRUE; + } +#endif + } + } else { /* Legacy windows NDIS no cipher info */ +#if 0 + 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 (IS_BSS_AIS(prBssInfo)) { +#if CFG_SUPPORT_802_11W + if (prCmdKey->ucKeyId >= 4) { + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + prCmdKey->ucAlgorithmId = CIPHER_SUITE_BIP; + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + prAisSpecBssInfo->fgBipKeyInstalled = TRUE; + } else +#endif + { + prCmdKey->ucAlgorithmId = CIPHER_SUITE_CCMP; + if (rsnCheckPmkidCandicate(prAdapter)) { + + DBGLOG(RSN, TRACE, + ("Add key: Prepare a timer to indicate candidate PMKID\n")); + cnmTimerStopTimer(prAdapter, + &prAisSpecBssInfo->rPreauthenticationTimer); + cnmTimerStartTimer(prAdapter, + &prAisSpecBssInfo->rPreauthenticationTimer, + SEC_TO_MSEC + (WAIT_TIME_IND_PMKID_CANDICATE_SEC)); + } + } + } + } + } else if (prNewKey->u4KeyLength == 32) { + if (IS_BSS_AIS(prBssInfo)) { + if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA_NONE) { + if (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION2_ENABLED) { + prCmdKey->ucAlgorithmId = CIPHER_SUITE_TKIP; + } else if (prAdapter->rWifiVar.rConnSettings.eEncStatus == + ENUM_ENCRYPTION3_ENABLED) { + prCmdKey->ucAlgorithmId = CIPHER_SUITE_CCMP; + prCmdKey->ucKeyLen = CCMP_KEY_LEN; + } + } else { + prCmdKey->ucAlgorithmId = CIPHER_SUITE_TKIP; + kalMemCopy(prAdapter->rWifiVar.rAisSpecificBssInfo.aucRxMicKey, + &prCmdKey->aucKeyMaterial[16], MIC_KEY_LEN); + kalMemCopy(prAdapter->rWifiVar.rAisSpecificBssInfo.aucTxMicKey, + &prCmdKey->aucKeyMaterial[24], MIC_KEY_LEN); + if (0 /* Todo::GCMP & GCMP-BIP ? */) { + if (rsnCheckPmkidCandicate(prAdapter)) { + + DBGLOG(RSN, TRACE, + ("Add key: Prepare a timer to indicate candidate PMKID\n")); + cnmTimerStopTimer(prAdapter, + &prAisSpecBssInfo->rPreauthenticationTimer); + cnmTimerStartTimer(prAdapter, + &prAisSpecBssInfo->rPreauthenticationTimer, + SEC_TO_MSEC + (WAIT_TIME_IND_PMKID_CANDICATE_SEC)); + } + } else { + prCmdKey->ucAlgorithmId = CIPHER_SUITE_TKIP; + } + } +} +#endif + } + + { +#if CFG_SUPPORT_TDLS + prTmpStaRec = cnmGetStaRecByAddress(prAdapter, prBssInfo->ucBssIndex, prNewKey->arBSSID); + if (prTmpStaRec) { + if (IS_DLS_STA(prTmpStaRec)) { + prStaRec = prTmpStaRec; + prCmdKey->ucAlgorithmId = CIPHER_SUITE_CCMP; /*128 ,TODO GCMP 256 */ + kalMemCopy(prCmdKey->aucPeerAddr, prStaRec->aucMacAddr, MAC_ADDR_LEN); + } + } +#endif + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if (prCmdKey->ucAlgorithmId == CIPHER_SUITE_BIP) { + if (prCmdKey->ucIsAuthenticator) { + DBGLOG(RSN, INFO, "Authenticator BIP bssid:%d\n", prBssInfo->ucBssIndex); + + prCmdKey->ucWlanIndex = + secPrivacySeekForBcEntry(prAdapter, + prBssInfo->ucBssIndex, + prBssInfo->aucOwnMacAddr, + STA_REC_INDEX_NOT_FOUND, + prCmdKey->ucAlgorithmId, prCmdKey->ucKeyId); + } else { + prCmdKey->ucWlanIndex = + secPrivacySeekForBcEntry(prAdapter, + prBssInfo->ucBssIndex, + prBssInfo->prStaRecOfAP->aucMacAddr, + prBssInfo->prStaRecOfAP->ucIndex, + prCmdKey->ucAlgorithmId, prCmdKey->ucKeyId); + } + + DBGLOG(RSN, INFO, "BIP BC wtbl index:%d\n", prCmdKey->ucWlanIndex); + } else +#endif + if (1) { + if (prStaRec) { + if (prCmdKey->ucKeyType) { /* RSN STA */ + P_WLAN_TABLE_T prWtbl; + + prWtbl = prAdapter->rWifiVar.arWtbl; + prWtbl[prStaRec->ucWlanIndex].ucKeyId = prCmdKey->ucKeyId; + + prCmdKey->ucWlanIndex = prStaRec->ucWlanIndex; + prStaRec->fgTransmitKeyExist = TRUE; /* wait for CMD Done ? */ + kalMemCopy(prCmdKey->aucPeerAddr, prNewKey->arBSSID, MAC_ADDR_LEN); +#if CFG_SUPPORT_802_11W + /* AP PMF */ + DBGLOG(RSN, INFO, "Assign client PMF flag = %d\n", + prStaRec->rPmfCfg.fgApplyPmf); + prCmdKey->ucMgmtProtection = prStaRec->rPmfCfg.fgApplyPmf; +#endif + } else { + ASSERT(FALSE); + } + } else { /* Overwrite the old one for AP and STA WEP */ + if (prBssInfo->prStaRecOfAP) { + DBGLOG(RSN, INFO, "AP REC\n"); + prCmdKey->ucWlanIndex = + secPrivacySeekForBcEntry(prAdapter, + prBssInfo->ucBssIndex, + prBssInfo->prStaRecOfAP->aucMacAddr, + prBssInfo->prStaRecOfAP->ucIndex, + prCmdKey->ucAlgorithmId, prCmdKey->ucKeyId); + + kalMemCopy(prCmdKey->aucPeerAddr, + prBssInfo->prStaRecOfAP->aucMacAddr, MAC_ADDR_LEN); + } else { + DBGLOG(RSN, INFO, "!AP && !STA REC\n"); + prCmdKey->ucWlanIndex = + secPrivacySeekForBcEntry(prAdapter, + prBssInfo->ucBssIndex, + prBssInfo->aucOwnMacAddr, /* Should replace by BSSID later */ + STA_REC_INDEX_NOT_FOUND, + prCmdKey->ucAlgorithmId, + prCmdKey->ucKeyId); + kalMemCopy(prCmdKey->aucPeerAddr, prBssInfo->aucOwnMacAddr, MAC_ADDR_LEN); + } + + /* overflow check */ + if (prCmdKey->ucKeyId >= MAX_KEY_NUM) { + DBGLOG(RSN, ERROR, "invalid keyId: %d\n", prCmdKey->ucKeyId); + prCmdKey->ucKeyId &= 0x3; + } + + if (fgNoHandshakeSec) { /* WEP: STA and AP */ + prBssInfo->wepkeyWlanIdx = prCmdKey->ucWlanIndex; + prBssInfo->wepkeyUsed[prCmdKey->ucKeyId] = TRUE; + } else if (!prBssInfo->prStaRecOfAP) { /* AP WPA/RSN */ + prBssInfo->ucBMCWlanIndexS[prCmdKey->ucKeyId] = prCmdKey->ucWlanIndex; + prBssInfo->ucBMCWlanIndexSUsed[prCmdKey->ucKeyId] = TRUE; + } else { /* STA WPA/RSN, should not have tx but no sta record */ + prBssInfo->ucBMCWlanIndexS[prCmdKey->ucKeyId] = prCmdKey->ucWlanIndex; + prBssInfo->ucBMCWlanIndexSUsed[prCmdKey->ucKeyId] = TRUE; + DBGLOG(RSN, INFO, "BMCWlanIndex kid = %d, index = %d\n", prCmdKey->ucKeyId, + prCmdKey->ucWlanIndex); + } + + if (prCmdKey->ucTxKey) { /* */ + prBssInfo->fgBcDefaultKeyExist = TRUE; + prBssInfo->ucBcDefaultKeyIdx = prCmdKey->ucKeyId; + } + } + } + } + +#if DBG + DBGLOG(RSN, INFO, "Add key cmd to wlan index %d:", prCmdKey->ucWlanIndex); + DBGLOG(RSN, INFO, "(BSS = %d) " MACSTR "\n", prCmdKey->ucBssIdx, MAC2STR(prCmdKey->aucPeerAddr)); + DBGLOG(RSN, INFO, "Tx = %d type = %d Auth = %d\n", prCmdKey->ucTxKey, prCmdKey->ucKeyType, + prCmdKey->ucIsAuthenticator); + DBGLOG(RSN, INFO, "cipher = %d keyid = %d keylen = %d\n", prCmdKey->ucAlgorithmId, prCmdKey->ucKeyId, + prCmdKey->ucKeyLen); + DBGLOG_MEM8(RSN, INFO, prCmdKey->aucKeyMaterial, prCmdKey->ucKeyLen); + + DBGLOG(RSN, INFO, "wepkeyUsed = %d\n", prBssInfo->wepkeyUsed[prCmdKey->ucKeyId]); + DBGLOG(RSN, INFO, "wepkeyWlanIdx = %d:", prBssInfo->wepkeyWlanIdx); + DBGLOG(RSN, INFO, "ucBMCWlanIndexSUsed = %d\n", prBssInfo->ucBMCWlanIndexSUsed[prCmdKey->ucKeyId]); + DBGLOG(RSN, INFO, "ucBMCWlanIndexS = %d:", prBssInfo->ucBMCWlanIndexS[prCmdKey->ucKeyId]); +#endif + + /* 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; + P_WLAN_TABLE_T prWlanTable; + P_STA_RECORD_T prStaRec = NULL; + P_BSS_INFO_T prBssInfo; + /* UINT_8 i = 0; */ + BOOL fgRemoveWepKey = FALSE; + BOOL fgRemoveBCKey = FALSE; + UINT_32 ucRemoveBCKeyAtIdx = WTBL_RESERVED_ENTRY; + UINT_32 u4KeyIndex; + + DEBUGFUNC("wlanoidSetRemoveKey"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + DBGLOG(RSN, INFO, "wlanoidSetRemoveKey\n"); + + prWlanTable = prAdapter->rWifiVar.arWtbl; + + *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(RSN, INFO, "Set: Dump PARAM_REMOVE_KEY content\n"); + DBGLOG(RSN, INFO, "Length : 0x%08x\n", prRemovedKey->u4Length); + DBGLOG(RSN, INFO, "Key Index : 0x%08x\n", prRemovedKey->u4KeyIndex); + DBGLOG(RSN, INFO, "BSS_INDEX : %d\n", prRemovedKey->ucBssIdx); + DBGLOG(RSN, INFO, "BSSID:\n"); + DBGLOG_MEM8(RSN, INFO, prRemovedKey->arBSSID, MAC_ADDR_LEN); + + prGlueInfo = prAdapter->prGlueInfo; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prRemovedKey->ucBssIdx); + ASSERT(prBssInfo); + + u4KeyIndex = prRemovedKey->u4KeyIndex & 0x000000FF; +#if CFG_SUPPORT_802_11W + ASSERT(u4KeyIndex < MAX_KEY_NUM + 2); +#else + /* ASSERT(prCmdKey->ucKeyId < MAX_KEY_NUM); */ +#endif + + if (u4KeyIndex >= 4) { + DBGLOG(RSN, INFO, "Remove bip key Index : 0x%08x\n", + u4KeyIndex); + return WLAN_STATUS_SUCCESS; + } + + /* Clean up the Tx key flag */ + if (prRemovedKey->u4KeyIndex & IS_UNICAST_KEY) { + prStaRec = cnmGetStaRecByAddress(prAdapter, prRemovedKey->ucBssIdx, prRemovedKey->arBSSID); + if (!prStaRec) + return WLAN_STATUS_SUCCESS; + } else { + if (u4KeyIndex == prBssInfo->ucBcDefaultKeyIdx) + prBssInfo->fgBcDefaultKeyExist = FALSE; + } + + if (!prStaRec) { + if (prBssInfo->wepkeyUsed[u4KeyIndex] == TRUE) + fgRemoveWepKey = TRUE; + + if (fgRemoveWepKey) { + DBGLOG(RSN, INFO, "Remove wep key id = %d", u4KeyIndex); + prBssInfo->wepkeyUsed[u4KeyIndex] = FALSE; + if (prBssInfo->fgBcDefaultKeyExist && + prBssInfo->ucBcDefaultKeyIdx == u4KeyIndex) { + prBssInfo->fgBcDefaultKeyExist = FALSE; + prBssInfo->ucBcDefaultKeyIdx = 0xff; + } + ASSERT(prBssInfo->wepkeyWlanIdx < WTBL_SIZE); + ucRemoveBCKeyAtIdx = prBssInfo->wepkeyWlanIdx; + fgRemoveBCKey = TRUE; + } else { + DBGLOG(RSN, INFO, "Remove group key id = %d", u4KeyIndex); + + if (prBssInfo->ucBMCWlanIndexSUsed[u4KeyIndex]) { + + if (prBssInfo->fgBcDefaultKeyExist && + prBssInfo->ucBcDefaultKeyIdx == u4KeyIndex) { + prBssInfo->fgBcDefaultKeyExist = FALSE; + prBssInfo->ucBcDefaultKeyIdx = 0xff; + } + if (u4KeyIndex != 0) + ASSERT(prBssInfo->ucBMCWlanIndexS[u4KeyIndex] < WTBL_SIZE); + ucRemoveBCKeyAtIdx = prBssInfo->ucBMCWlanIndexS[u4KeyIndex]; + + prBssInfo->ucBMCWlanIndexSUsed[u4KeyIndex] + = FALSE; + prBssInfo->ucBMCWlanIndexS[u4KeyIndex] + = WTBL_RESERVED_ENTRY; + fgRemoveBCKey = TRUE; + } + } + /* Change the wtbl to not used state */ + if (fgRemoveBCKey) + prWlanTable[ucRemoveBCKeyAtIdx].ucUsed = FALSE; + + DBGLOG(RSN, INFO, "ucRemoveBCKeyAtIdx = %d", ucRemoveBCKeyAtIdx); + + if (ucRemoveBCKeyAtIdx >= WTBL_SIZE) + return WLAN_STATUS_SUCCESS; + } + + 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; + } + + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prRemovedKey->ucBssIdx); + + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_802_11_KEY cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + /* prCmdInfo->ucBssIndex = prRemovedKey->ucBssIdx; */ + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_802_11_KEY); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = g_fgIsOid; + 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 = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + 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) u4KeyIndex; + kalMemCopy(prCmdKey->aucPeerAddr, (PUINT_8) prRemovedKey->arBSSID, MAC_ADDR_LEN); + prCmdKey->ucBssIdx = prRemovedKey->ucBssIdx; + + if (prStaRec) { + prCmdKey->ucKeyType = 1; + prCmdKey->ucWlanIndex = prStaRec->ucWlanIndex; + prStaRec->fgTransmitKeyExist = FALSE; + } else if (ucRemoveBCKeyAtIdx < WTBL_SIZE) { + prCmdKey->ucWlanIndex = ucRemoveBCKeyAtIdx; + } else { + ASSERT(FALSE); + } + + /* 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 set the default key +* +* \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 +wlanoidSetDefaultKey(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_DEFAULT_KEY_T prDefaultKey; + P_CMD_DEFAULT_KEY prCmdDefaultKey; + UINT_8 ucCmdSeqNum; + P_BSS_INFO_T prBssInfo; + BOOL fgSetWepKey = FALSE; + UINT_8 ucWlanIndex = WTBL_RESERVED_ENTRY; + + DEBUGFUNC("wlanoidSetDefaultKey"); + 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; + } + + prDefaultKey = (P_PARAM_DEFAULT_KEY_T) pvSetBuffer; + + *pu4SetInfoLen = u4SetBufferLen; + + /* Dump PARAM_DEFAULT_KEY_T content. */ + DBGLOG(RSN, INFO, "Key Index : %d\n", prDefaultKey->ucKeyID); + DBGLOG(RSN, INFO, "Unicast Key : %d\n", prDefaultKey->ucUnicast); + DBGLOG(RSN, INFO, "Multicast Key : %d\n", prDefaultKey->ucMulticast); + + /* prWlanTable = prAdapter->rWifiVar.arWtbl; */ + prGlueInfo = prAdapter->prGlueInfo; + + if (prDefaultKey->ucBssIdx > HW_BSSID_NUM) + return WLAN_STATUS_FAILURE; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prDefaultKey->ucBssIdx); + + DBGLOG(RSN, INFO, "WlanIdx = %d\n", prBssInfo->wepkeyWlanIdx); + + if (prDefaultKey->ucMulticast) { + if (prBssInfo->prStaRecOfAP) { /* Actually GC not have wep */ + if (prBssInfo->wepkeyUsed[prDefaultKey->ucKeyID]) { + prBssInfo->ucBcDefaultKeyIdx = prDefaultKey->ucKeyID; + prBssInfo->fgBcDefaultKeyExist = TRUE; + ucWlanIndex = prBssInfo->wepkeyWlanIdx; + } else { + DBGLOG(RSN, ERROR, "WPA encryption should retrun"); + return WLAN_STATUS_SUCCESS; + } + } else { /* For AP mode only */ + + if (prBssInfo->wepkeyUsed[prDefaultKey->ucKeyID] == TRUE) + fgSetWepKey = TRUE; + + if (fgSetWepKey) { + ucWlanIndex = prBssInfo->wepkeyWlanIdx; + } else { + if (!prBssInfo->ucBMCWlanIndexSUsed[prDefaultKey->ucKeyID]) { + DBGLOG(RSN, ERROR, "Set AP wep default but key not exist!"); + return WLAN_STATUS_SUCCESS; + } + ucWlanIndex = prBssInfo->ucBMCWlanIndexS[prDefaultKey->ucKeyID]; + } + prBssInfo->ucBcDefaultKeyIdx = prDefaultKey->ucKeyID; + prBssInfo->fgBcDefaultKeyExist = TRUE; + } + if (ucWlanIndex > WTBL_SIZE) + ASSERT(FALSE); + + } else { + DBGLOG(RSN, ERROR, "Check the case set unicast default key!"); + ASSERT(FALSE); + } + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_DEFAULT_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->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_DEFAULT_KEY); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = g_fgIsOid; + prCmdInfo->ucCID = CMD_ID_DEFAULT_KEY_ID; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = 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 = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prCmdDefaultKey = (P_CMD_DEFAULT_KEY) (prWifiCmd->aucBuffer); + + kalMemZero(prCmdDefaultKey, sizeof(CMD_DEFAULT_KEY)); + + prCmdDefaultKey->ucBssIdx = prDefaultKey->ucBssIdx; + prCmdDefaultKey->ucKeyId = prDefaultKey->ucKeyID; + prCmdDefaultKey->ucWlanIndex = ucWlanIndex; + prCmdDefaultKey->ucMulticast = prDefaultKey->ucMulticast; + + DBGLOG(RSN, INFO, "CMD_ID_DEFAULT_KEY_ID (%d) with wlan idx = %d\n", prDefaultKey->ucKeyID, ucWlanIndex); + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; +} /* wlanoidSetDefaultKey */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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->prAisBssInfo->fgBcDefaultKeyExist; + + switch (prAdapter->rWifiVar.rConnSettings.eEncStatus) { + case ENUM_ENCRYPTION3_ENABLED: + if (fgTransmitKeyAvailable) + eEncStatus = ENUM_ENCRYPTION3_ENABLED; + else + eEncStatus = ENUM_ENCRYPTION3_KEY_ABSENT; + break; + + case ENUM_ENCRYPTION2_ENABLED: + if (fgTransmitKeyAvailable) { + eEncStatus = ENUM_ENCRYPTION2_ENABLED; + break; + } + eEncStatus = ENUM_ENCRYPTION2_KEY_ABSENT; + break; + + case ENUM_ENCRYPTION1_ENABLED: + if (fgTransmitKeyAvailable) + eEncStatus = ENUM_ENCRYPTION1_ENABLED; + else + eEncStatus = ENUM_ENCRYPTION1_KEY_ABSENT; + break; + + case ENUM_ENCRYPTION_DISABLED: + eEncStatus = ENUM_ENCRYPTION_DISABLED; + break; + + default: + DBGLOG(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, INFO, "ENCRYPTION_STATUS %d\n", eEewEncrypt); + + switch (eEewEncrypt) { + case ENUM_ENCRYPTION_DISABLED: /* Disable WEP, TKIP, AES */ + DBGLOG(RSN, INFO, "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, INFO, "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, INFO, "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, INFO, "Enable Encryption3\n"); + break; +#if CFG_SUPPORT_SUITB + case ENUM_ENCRYPTION4_ENABLED: /* Eanble GCMP256 */ + secSetCipherSuite(prAdapter, CIPHER_FLAG_GCMP256); + DBGLOG(RSN, INFO, "Enable Encryption4\n"); + break; +#endif + default: + DBGLOG(RSN, INFO, "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 %u\n", prTest->u4Type); + + switch (prTest->u4Type) { + case 1: /* Type 1: generate an authentication event */ + pvTestData = (PVOID) &prTest->u.AuthenticationEvent; + pvStatusBuffer = (PVOID) prAdapter->aucIndicationEventBuffer; + u4StatusBufferSize = prTest->u4Length - 8; + if (u4StatusBufferSize > sizeof(prTest->u.AuthenticationEvent)) + return WLAN_STATUS_INVALID_LENGTH; + 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; + } + + /* 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"); + + DBGLOG(REQ, INFO, "wlanoidSetPmkid\n"); + + 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 %u\n", prPmkid->u4BSSIDInfoCount); + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + /* This OID replace everything in the PMKID cache. */ + if (prPmkid->u4BSSIDInfoCount == 0) { + prAisSpecBssInfo->u4PmkidCacheCount = 0; + kalMemZero(prAisSpecBssInfo->arPmkidCache, sizeof(PMKID_ENTRY_T) * CFG_MAX_PMKID_CACHE); + } + if ((prAisSpecBssInfo->u4PmkidCacheCount + prPmkid->u4BSSIDInfoCount > CFG_MAX_PMKID_CACHE)) { + prAisSpecBssInfo->u4PmkidCacheCount = 0; + kalMemZero(prAisSpecBssInfo->arPmkidCache, sizeof(PMKID_ENTRY_T) * CFG_MAX_PMKID_CACHE); + } + + /* + * The driver can only clear its PMKID cache whenever it make a media disconnect + * indication. Otherwise, it must change the PMKID cache only when set through this OID. + */ + 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=%u PMKID value " MACSTR "\n", + MAC2STR(prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arBSSID), j, + MAC2STR(prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arPMKID)); + prAisSpecBssInfo->arPmkidCache[j].fgPmkidExist = TRUE; + } + } + + 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 %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + kalMemCopy(pvQueryBuffer, (PVOID) &eRate, sizeof(PARAM_RATES)); + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidQuerySupportedRates() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query current desired rates. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryDesiredRates(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryDesiredRates"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_RATES_EX); + + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + kalMemCopy(pvQueryBuffer, (PVOID) &(prAdapter->rWlanInfo.eDesiredRates), sizeof(PARAM_RATES)); + + return WLAN_STATUS_SUCCESS; + +} /* end of wlanoidQueryDesiredRates() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set the desired rates. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetDesiredRates(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + UINT_32 i; + + DEBUGFUNC("wlanoidSetDesiredRates"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(PARAM_RATES)) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = sizeof(PARAM_RATES); + + if (u4SetBufferLen < sizeof(PARAM_RATES)) + return WLAN_STATUS_INVALID_LENGTH; + + kalMemCopy((PVOID) &(prAdapter->rWlanInfo.eDesiredRates), pvSetBuffer, sizeof(PARAM_RATES)); + + prAdapter->rWlanInfo.eLinkAttr.ucDesiredRateLen = PARAM_MAX_LEN_RATES; + for (i = 0; i < PARAM_MAX_LEN_RATES; i++) + prAdapter->rWlanInfo.eLinkAttr.u2DesiredRate[i] = (UINT_16) (prAdapter->rWlanInfo.eDesiredRates[i]); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_LINK_ATTRIB, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_LINK_ATTRIB), + (PUINT_8) &(prAdapter->rWlanInfo.eLinkAttr), pvSetBuffer, u4SetBufferLen); + +} /* end of wlanoidSetDesiredRates() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the maximum frame size in bytes, +* not including the header. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the +* call failed due to invalid length of the query +* buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMaxFrameSize(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryMaxFrameSize"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_INVALID_LENGTH; + } + + *(PUINT_32) pvQueryBuffer = ETHERNET_MAX_PKT_SZ - ETHERNET_HEADER_SZ; + *pu4QueryInfoLen = sizeof(UINT_32); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryMaxFrameSize */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the maximum total packet length +* in bytes. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMaxTotalSize(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryMaxTotalSize"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_INVALID_LENGTH; + } + + *(PUINT_32) pvQueryBuffer = ETHERNET_MAX_PKT_SZ; + *pu4QueryInfoLen = sizeof(UINT_32); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryMaxTotalSize */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the vendor ID of the NIC. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryVendorId(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ +#if DBG + PUINT_8 cp; +#endif + DEBUGFUNC("wlanoidQueryVendorId"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_INVALID_LENGTH; + } + + kalMemCopy(pvQueryBuffer, prAdapter->aucMacAddress, 3); + *((PUINT_8) pvQueryBuffer + 3) = 1; + *pu4QueryInfoLen = sizeof(UINT_32); + +#if DBG + cp = (PUINT_8) pvQueryBuffer; + DBGLOG(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) +{ + return _wlanoidQueryRssi(prAdapter, + pvQueryBuffer, + u4QueryBufferLen, + pu4QueryInfoLen, + g_fgIsOid); +} + +WLAN_STATUS +_wlanoidQueryRssi(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen, IN BOOLEAN fgIsOid) +{ + DEBUGFUNC("wlanoidQueryRssi"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (prAdapter->fgIsEnableLpdvt) + return WLAN_STATUS_NOT_SUPPORTED; + + *pu4QueryInfoLen = sizeof(PARAM_RSSI); + + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(REQ, WARN, "Too short length %u\n", u4QueryBufferLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + if (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, + fgIsOid, + nicCmdEventQueryLinkQuality, + nicOidCmdTimeoutCommon, + *pu4QueryInfoLen, pvQueryBuffer, pvQueryBuffer, u4QueryBufferLen); +#else + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + fgIsOid, + 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 %u\n", u4QueryBufferLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + *(PARAM_RSSI *) pvQueryBuffer = prAdapter->rWlanInfo.rRssiTriggerValue; + DBGLOG(REQ, INFO, "RSSI trigger: %d dBm\n", + *(PARAM_RSSI *) pvQueryBuffer); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryRssiTrigger */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a trigger value of the RSSI event. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns the +* amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetRssiTrigger(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PARAM_RSSI rRssiTriggerValue; + + DEBUGFUNC("wlanoidSetRssiTrigger"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_RSSI); + rRssiTriggerValue = *(PARAM_RSSI *) pvSetBuffer; + + if (rRssiTriggerValue > PARAM_WHQL_RSSI_MAX_DBM || rRssiTriggerValue < PARAM_WHQL_RSSI_MIN_DBM) + return + /* Save the RSSI trigger value to the Adapter structure */ + prAdapter->rWlanInfo.rRssiTriggerValue = rRssiTriggerValue; + + /* If the RSSI trigger value is equal to the current RSSI value, the + * indication triggers immediately. We need to indicate the protocol + * that an RSSI status indication event triggers. + */ + if (rRssiTriggerValue == (PARAM_RSSI) (prAdapter->rLinkQuality.cRssi)) { + prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_TRIGGERED; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID) &prAdapter->rWlanInfo.rRssiTriggerValue, sizeof(PARAM_RSSI)); + } else if (rRssiTriggerValue < (PARAM_RSSI) (prAdapter->rLinkQuality.cRssi)) + prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_GREATER; + else if (rRssiTriggerValue > (PARAM_RSSI) (prAdapter->rLinkQuality.cRssi)) + prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_LESS; + + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetRssiTrigger */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a suggested value for the number of +* bytes of received packet data that will be indicated to the protocol +* driver. We just accept the set and ignore this value. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetCurrentLookahead(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + DEBUGFUNC("wlanoidSetCurrentLookahead"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(UINT_32)) { + *pu4SetInfoLen = sizeof(UINT_32); + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = sizeof(UINT_32); + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetCurrentLookahead */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of frames that the driver +* receives but does not indicate to the protocols due to errors. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRcvError(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryRcvError"); + DBGLOG(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; + } +#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; + } +#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; + } +#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) +{ + PARAM_802_11_STATISTICS_STRUCT_T rStatistics; + + 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 %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + P_PARAM_802_11_STATISTICS_STRUCT_T prStatistics; + + *pu4QueryInfoLen = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + prStatistics = (P_PARAM_802_11_STATISTICS_STRUCT_T) pvQueryBuffer; + + prStatistics->u4Length = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + prStatistics->rTransmittedFragmentCount = prAdapter->rStatStruct.rTransmittedFragmentCount; + prStatistics->rMulticastTransmittedFrameCount = prAdapter->rStatStruct.rMulticastTransmittedFrameCount; + prStatistics->rFailedCount = prAdapter->rStatStruct.rFailedCount; + prStatistics->rRetryCount = prAdapter->rStatStruct.rRetryCount; + prStatistics->rMultipleRetryCount = prAdapter->rStatStruct.rMultipleRetryCount; + prStatistics->rRTSSuccessCount = prAdapter->rStatStruct.rRTSSuccessCount; + prStatistics->rRTSFailureCount = prAdapter->rStatStruct.rRTSFailureCount; + prStatistics->rACKFailureCount = prAdapter->rStatStruct.rACKFailureCount; + prStatistics->rFrameDuplicateCount = prAdapter->rStatStruct.rFrameDuplicateCount; + prStatistics->rReceivedFragmentCount = prAdapter->rStatStruct.rReceivedFragmentCount; + prStatistics->rMulticastReceivedFrameCount = prAdapter->rStatStruct.rMulticastReceivedFrameCount; + prStatistics->rFCSErrorCount = prAdapter->rStatStruct.rFCSErrorCount; + prStatistics->rTKIPLocalMICFailures.QuadPart = 0; + prStatistics->rTKIPICVErrors.QuadPart = 0; + prStatistics->rTKIPCounterMeasuresInvoked.QuadPart = 0; + prStatistics->rTKIPReplays.QuadPart = 0; + prStatistics->rCCMPFormatErrors.QuadPart = 0; + prStatistics->rCCMPReplays.QuadPart = 0; + prStatistics->rCCMPDecryptErrors.QuadPart = 0; + prStatistics->rFourWayHandshakeFailures.QuadPart = 0; + prStatistics->rWEPUndecryptableCount.QuadPart = 0; + prStatistics->rWEPICVErrorCount.QuadPart = 0; + prStatistics->rDecryptSuccessCount.QuadPart = 0; + prStatistics->rDecryptFailureCount.QuadPart = 0; + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventQueryStatistics, + nicOidCmdTimeoutCommon, + sizeof(PARAM_802_11_STATISTICS_STRUCT_T), (PUINT_8)&rStatistics, + 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 %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + *(P_ENUM_MEDIA_STREAM_MODE) pvQueryBuffer = + prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode == 0 ? ENUM_MEDIA_STREAM_OFF : ENUM_MEDIA_STREAM_ON; + + return WLAN_STATUS_SUCCESS; + +} /* wlanoidQueryMediaStreamMode */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to enter media streaming mode or exit media streaming mode +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetMediaStreamMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + ENUM_MEDIA_STREAM_MODE eStreamMode; + + DEBUGFUNC("wlanoidSetMediaStreamMode"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(ENUM_MEDIA_STREAM_MODE)) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = sizeof(ENUM_MEDIA_STREAM_MODE); + + eStreamMode = *(P_ENUM_MEDIA_STREAM_MODE) pvSetBuffer; + + if (eStreamMode == ENUM_MEDIA_STREAM_OFF) + prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode = 0; + else + prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode = 1; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_LINK_ATTRIB, + TRUE, + FALSE, + TRUE, + nicCmdEventSetMediaStreamMode, + nicOidCmdTimeoutCommon, + sizeof(CMD_LINK_ATTRIB), + (PUINT_8) &(prAdapter->rWlanInfo.eLinkAttr), pvSetBuffer, u4SetBufferLen); +} /* wlanoidSetMediaStreamMode */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the permanent MAC address of the NIC. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryPermanentAddr(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryPermanentAddr"); + DBGLOG(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) +{ + 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; + + COPY_MAC_ADDR(pvQueryBuffer, prAdapter->rWifiVar.aucMacAddress); + *pu4QueryInfoLen = MAC_ADDR_LEN; + + return WLAN_STATUS_SUCCESS; +} /* 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); + + if (prAdapter->fgIsEnableLpdvt) + return WLAN_STATUS_NOT_SUPPORTED; + + *pu4QueryInfoLen = sizeof(UINT_32); + + if (u4QueryBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) { + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (prAdapter->fgIsLinkRateValid == TRUE && + (kalGetTimeTick() - prAdapter->rLinkRateUpdateTime) <= CFG_LINK_QUALITY_VALID_PERIOD) { + *(PUINT_32) pvQueryBuffer = prAdapter->rLinkQuality.u2LinkSpeed * 5000; /* change to unit of 100bps */ + return WLAN_STATUS_SUCCESS; + } else { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventQueryLinkSpeed, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + } +} /* end of wlanoidQueryLinkSpeed() */ + +#if CFG_SUPPORT_QA_TOOL +#if CFG_SUPPORT_BUFFER_MODE +WLAN_STATUS +wlanoidSetEfusBufferMode(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_EFUSE_BUFFER_MODE_T prSetEfuseBufModeInfo; + CMD_EFUSE_BUFFER_MODE_T *prCmdSetEfuseBufModeInfo = NULL; + PFN_CMD_DONE_HANDLER pfCmdDoneHandler; + UINT_32 u4EfuseContentSize, u4QueryInfoLen; + BOOLEAN fgSetQuery, fgNeedResp; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidSetEfusBufferMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + /* get the buffer mode info */ + prSetEfuseBufModeInfo = (P_PARAM_CUSTOM_EFUSE_BUFFER_MODE_T) pvSetBuffer; + + /* copy command header */ + prCmdSetEfuseBufModeInfo = + (CMD_EFUSE_BUFFER_MODE_T *) kalMemAlloc(sizeof(CMD_EFUSE_BUFFER_MODE_T), VIR_MEM_TYPE); + if (prCmdSetEfuseBufModeInfo == NULL) + return WLAN_STATUS_FAILURE; + kalMemZero(prCmdSetEfuseBufModeInfo, sizeof(CMD_EFUSE_BUFFER_MODE_T)); + prCmdSetEfuseBufModeInfo->ucSourceMode = prSetEfuseBufModeInfo->ucSourceMode; + prCmdSetEfuseBufModeInfo->ucCount = prSetEfuseBufModeInfo->ucCount; + prCmdSetEfuseBufModeInfo->ucCmdType = prSetEfuseBufModeInfo->ucCmdType; + prCmdSetEfuseBufModeInfo->ucReserved = prSetEfuseBufModeInfo->ucReserved; + + /* decide content size and SetQuery / NeedResp flag */ + if (prAdapter->fgIsSupportBufferBinSize16Byte == TRUE) { + u4EfuseContentSize = sizeof(BIN_CONTENT_T) * EFUSE_CONTENT_SIZE; + pfCmdDoneHandler = nicCmdEventSetCommon; + fgSetQuery = TRUE; + fgNeedResp = FALSE; + } else { +#if (CFG_FW_Report_Efuse_Address == 1) + u4EfuseContentSize = (prAdapter->u4EfuseEndAddress) - (prAdapter->u4EfuseStartAddress) + 1; +#else + u4EfuseContentSize = EFUSE_CONTENT_BUFFER_SIZE; +#endif + pfCmdDoneHandler = NULL; + fgSetQuery = FALSE; + fgNeedResp = TRUE; + } + + u4QueryInfoLen = OFFSET_OF(CMD_EFUSE_BUFFER_MODE_T, aBinContent) + u4EfuseContentSize; + + if (u4SetBufferLen < u4QueryInfoLen) { + kalMemFree(prCmdSetEfuseBufModeInfo, VIR_MEM_TYPE, sizeof(CMD_EFUSE_BUFFER_MODE_T)); + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = u4QueryInfoLen; + kalMemCopy(prCmdSetEfuseBufModeInfo->aBinContent, prSetEfuseBufModeInfo->aBinContent, + u4EfuseContentSize); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_EFUSE_BUFFER_MODE, + fgSetQuery, + fgNeedResp, + g_fgIsOid, + pfCmdDoneHandler, + nicOidCmdTimeoutCommon, + u4QueryInfoLen, + (PUINT_8) (prCmdSetEfuseBufModeInfo), + pvSetBuffer, u4SetBufferLen); + + kalMemFree(prCmdSetEfuseBufModeInfo, VIR_MEM_TYPE, sizeof(CMD_EFUSE_BUFFER_MODE_T)); + + return rWlanStatus; +} + +/*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to read efuse content. +* +* \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 +wlanoidQueryProcessAccessEfuseRead(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_ACCESS_EFUSE_T prSetAccessEfuseInfo; + CMD_ACCESS_EFUSE_T rCmdSetAccessEfuse; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryProcessAccessEfuseRead"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prSetAccessEfuseInfo = (P_PARAM_CUSTOM_ACCESS_EFUSE_T) pvSetBuffer; + + kalMemSet(&rCmdSetAccessEfuse, 0, sizeof(CMD_ACCESS_EFUSE_T)); + + rCmdSetAccessEfuse.u4Address = prSetAccessEfuseInfo->u4Address; + rCmdSetAccessEfuse.u4Valid = prSetAccessEfuseInfo->u4Valid; + + + DBGLOG(INIT, INFO, "MT6632 : wlanoidQueryProcessAccessEfuseRead, address=%d\n", rCmdSetAccessEfuse.u4Address); + + kalMemCopy(rCmdSetAccessEfuse.aucData, prSetAccessEfuseInfo->aucData, + sizeof(UINT_8) * 16); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_EFUSE_ACCESS, + FALSE, /* Query Bit: True->write False->read*/ + TRUE, + g_fgIsOid, + NULL, /* No Tx done function wait until fw ack */ + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_EFUSE_T), + (PUINT_8) (&rCmdSetAccessEfuse), pvSetBuffer, u4SetBufferLen); + + return rWlanStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to write efuse content. +* +* \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 +wlanoidQueryProcessAccessEfuseWrite(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_ACCESS_EFUSE_T prSetAccessEfuseInfo; + CMD_ACCESS_EFUSE_T rCmdSetAccessEfuse; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryProcessAccessEfuseWrite"); + DBGLOG(INIT, INFO, "MT6632 : wlanoidQueryProcessAccessEfuseWrite\n"); + + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prSetAccessEfuseInfo = (P_PARAM_CUSTOM_ACCESS_EFUSE_T) pvSetBuffer; + + kalMemSet(&rCmdSetAccessEfuse, 0, sizeof(CMD_ACCESS_EFUSE_T)); + + rCmdSetAccessEfuse.u4Address = prSetAccessEfuseInfo->u4Address; + rCmdSetAccessEfuse.u4Valid = prSetAccessEfuseInfo->u4Valid; + + DBGLOG(INIT, INFO, "MT6632 : wlanoidQueryProcessAccessEfuseWrite, address=%d\n", rCmdSetAccessEfuse.u4Address); + + + kalMemCopy(rCmdSetAccessEfuse.aucData, prSetAccessEfuseInfo->aucData, + sizeof(UINT_8) * 16); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_EFUSE_ACCESS, + TRUE, /* Query Bit: True->write False->read*/ + TRUE, + g_fgIsOid, + NULL, /* No Tx done function wait until fw ack */ + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_EFUSE_T), + (PUINT_8) (&rCmdSetAccessEfuse), pvSetBuffer, u4SetBufferLen); + + return rWlanStatus; +} + + + + +WLAN_STATUS +wlanoidQueryEfuseFreeBlock(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_EFUSE_FREE_BLOCK_T prGetEfuseFreeBlockInfo; + CMD_EFUSE_FREE_BLOCK_T rCmdGetEfuseFreeBlock; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryEfuseFreeBlock"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_EFUSE_FREE_BLOCK_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_EFUSE_FREE_BLOCK_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prGetEfuseFreeBlockInfo = (P_PARAM_CUSTOM_EFUSE_FREE_BLOCK_T) pvSetBuffer; + + kalMemSet(&rCmdGetEfuseFreeBlock, 0, sizeof(CMD_EFUSE_FREE_BLOCK_T)); + + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_EFUSE_FREE_BLOCK, + FALSE, /* Query Bit: True->write False->read*/ + TRUE, + g_fgIsOid, + NULL, /* No Tx done function wait until fw ack */ + nicOidCmdTimeoutCommon, + sizeof(CMD_EFUSE_FREE_BLOCK_T), + (PUINT_8) (&rCmdGetEfuseFreeBlock), pvSetBuffer, u4SetBufferLen); + + return rWlanStatus; +} + +WLAN_STATUS +wlanoidQueryGetTxPower(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_GET_TX_POWER_T prGetTxPowerInfo; + CMD_GET_TX_POWER_T rCmdGetTxPower; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryGetTxPower"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(P_PARAM_CUSTOM_GET_TX_POWER_T); + + if (u4SetBufferLen < sizeof(P_PARAM_CUSTOM_GET_TX_POWER_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prGetTxPowerInfo = (P_PARAM_CUSTOM_GET_TX_POWER_T) pvSetBuffer; + + kalMemSet(&rCmdGetTxPower, 0, sizeof(CMD_GET_TX_POWER_T)); + + rCmdGetTxPower.ucTxPwrType = EXT_EVENT_TARGET_TX_POWER; + rCmdGetTxPower.ucCenterChannel = prGetTxPowerInfo->ucCenterChannel; + rCmdGetTxPower.ucDbdcIdx = prGetTxPowerInfo->ucDbdcIdx; + rCmdGetTxPower.ucBand = prGetTxPowerInfo->ucBand; + + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_GET_TX_POWER, + FALSE, /* Query Bit: True->write False->read*/ + TRUE, + g_fgIsOid, + NULL, /* No Tx done function wait until fw ack */ + nicOidCmdTimeoutCommon, + sizeof(CMD_GET_TX_POWER_T), + (PUINT_8) (&rCmdGetTxPower), pvSetBuffer, u4SetBufferLen); + + return rWlanStatus; +} + + +/*#endif*/ + +#endif /* CFG_SUPPORT_BUFFER_MODE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query RX statistics. +* +* \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 +wlanoidQueryRxStatistics(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_CUSTOM_ACCESS_RX_STAT prRxStatistics; + P_CMD_ACCESS_RX_STAT prCmdAccessRxStat; + CMD_ACCESS_RX_STAT rCmdAccessRxStat; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; +/* UINT_32 u4MemSize = PARAM_MEM_DUMP_MAX_SIZE; */ + UINT_32 u4SeqNum = 0; + UINT_32 u4TotalNum = 0; + + prCmdAccessRxStat = &rCmdAccessRxStat; + + DEBUGFUNC("wlanoidQueryRxStatistics"); + DBGLOG(INIT, LOUD, "\n"); + + DBGLOG(INIT, ERROR, "MT6632 : wlanoidQueryRxStatistics\n"); + + prRxStatistics = (P_PARAM_CUSTOM_ACCESS_RX_STAT) pvQueryBuffer; + + *pu4QueryInfoLen = 8 + prRxStatistics->u4TotalNum; + + u4SeqNum = prRxStatistics->u4SeqNum; + u4TotalNum = prRxStatistics->u4TotalNum; + + do { + prCmdAccessRxStat->u4SeqNum = u4SeqNum; + prCmdAccessRxStat->u4TotalNum = u4TotalNum; + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_RX_STAT, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventQueryRxStatistics, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_RX_STAT), + (PUINT_8) prCmdAccessRxStat, pvQueryBuffer, u4QueryBufferLen); + } while (FALSE); + + return rStatus; +} + +#if CFG_SUPPORT_TX_BF + +WLAN_STATUS +wlanoidStaRecUpdate(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_CMD_STAREC_UPDATE_T prStaRecUpdateInfo; + P_CMD_STAREC_COMMON_T prStaRecCmm; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidStaRecUpdate"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(CMD_STAREC_COMMON_T); + if (u4SetBufferLen < sizeof(CMD_STAREC_COMMON_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prStaRecUpdateInfo = + (P_CMD_STAREC_UPDATE_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, (CMD_STAREC_UPDATE_HDR_SIZE + u4SetBufferLen)); + if (!prStaRecUpdateInfo) { + DBGLOG(INIT, ERROR, "Allocate P_CMD_DEV_INFO_UPDATE_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* fix me: configurable ucBssIndex */ + prStaRecCmm = (P_CMD_STAREC_COMMON_T) pvSetBuffer; + prStaRecUpdateInfo->ucBssIndex = 0; + prStaRecUpdateInfo->ucWlanIdx = prStaRecCmm->u2Reserve1; + prStaRecUpdateInfo->u2TotalElementNum = 1; + kalMemCopy(prStaRecUpdateInfo->aucBuffer, pvSetBuffer, u4SetBufferLen); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_STAREC_UPDATE, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + (CMD_STAREC_UPDATE_HDR_SIZE + u4SetBufferLen), + (PUINT_8) prStaRecUpdateInfo, NULL, 0); + + cnmMemFree(prAdapter, prStaRecUpdateInfo); + + return rWlanStatus; +} + +WLAN_STATUS +wlanoidStaRecBFUpdate(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_CMD_STAREC_UPDATE_T prStaRecUpdateInfo; + P_CMD_STAREC_BF prStaRecBF; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidStaRecBFUpdate"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(CMD_STAREC_BF); + if (u4SetBufferLen < sizeof(CMD_STAREC_BF)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prStaRecUpdateInfo = + (P_CMD_STAREC_UPDATE_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, (CMD_STAREC_UPDATE_HDR_SIZE + u4SetBufferLen)); + if (!prStaRecUpdateInfo) { + DBGLOG(INIT, ERROR, "Allocate P_CMD_DEV_INFO_UPDATE_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* fix me: configurable ucBssIndex */ + prStaRecBF = (P_CMD_STAREC_BF) pvSetBuffer; + prStaRecUpdateInfo->ucBssIndex = prStaRecBF->ucReserved[0]; + prStaRecUpdateInfo->ucWlanIdx = prStaRecBF->ucReserved[1]; + prStaRecUpdateInfo->u2TotalElementNum = 1; + kalMemCopy(prStaRecUpdateInfo->aucBuffer, pvSetBuffer, u4SetBufferLen); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_STAREC_UPDATE, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + (CMD_STAREC_UPDATE_HDR_SIZE + u4SetBufferLen), + (PUINT_8) prStaRecUpdateInfo, NULL, 0); + + cnmMemFree(prAdapter, prStaRecUpdateInfo); + + return rWlanStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief extend command packet generation utility +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] ucCID Command ID +* \param[in] ucExtCID Extend 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 +wlanSendSetQueryExtCmd(IN P_ADAPTER_T prAdapter, + UINT_8 ucCID, + UINT_8 ucExtCID, + 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->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->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 = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->u2Length = prCmdInfo->u2InfoBufLen - (UINT_16) OFFSET_OF(WIFI_CMD_T, u2Length); + prWifiCmd->u2PqId = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucExtenCID = ucExtCID; + 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; +} + +WLAN_STATUS +wlanoidBssInfoBasic(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_CMD_BSS_INFO_UPDATE_T prBssInfoUpdateBasic; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidManualAssoc"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(CMD_BSSINFO_BASIC_T); + if (u4SetBufferLen < sizeof(CMD_BSSINFO_BASIC_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prBssInfoUpdateBasic = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, (CMD_BSSINFO_UPDATE_HDR_SIZE + u4SetBufferLen)); + if (!prBssInfoUpdateBasic) { + DBGLOG(INIT, ERROR, "Allocate P_CMD_DEV_INFO_UPDATE_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* fix me: configurable ucBssIndex */ + prBssInfoUpdateBasic->ucBssIndex = 0; + prBssInfoUpdateBasic->u2TotalElementNum = 1; + kalMemCopy(prBssInfoUpdateBasic->aucBuffer, pvSetBuffer, u4SetBufferLen); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_BSSINFO_UPDATE, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + (CMD_BSSINFO_UPDATE_HDR_SIZE + u4SetBufferLen), + (PUINT_8) prBssInfoUpdateBasic, NULL, 0); + + cnmMemFree(prAdapter, prBssInfoUpdateBasic); + + return rWlanStatus; +} + +WLAN_STATUS +wlanoidDevInfoActive(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_CMD_DEV_INFO_UPDATE_T prDevInfoUpdateActive; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidManualAssoc"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(CMD_DEVINFO_ACTIVE_T); + if (u4SetBufferLen < sizeof(CMD_DEVINFO_ACTIVE_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prDevInfoUpdateActive = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, (CMD_DEVINFO_UPDATE_HDR_SIZE + u4SetBufferLen)); + if (!prDevInfoUpdateActive) { + DBGLOG(INIT, ERROR, "Allocate P_CMD_DEV_INFO_UPDATE_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* fix me: configurable ucOwnMacIdx */ + prDevInfoUpdateActive->ucOwnMacIdx = 0; + prDevInfoUpdateActive->ucAppendCmdTLV = 0; + prDevInfoUpdateActive->u2TotalElementNum = 1; + kalMemCopy(prDevInfoUpdateActive->aucBuffer, pvSetBuffer, u4SetBufferLen); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_DEVINFO_UPDATE, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + (CMD_DEVINFO_UPDATE_HDR_SIZE + u4SetBufferLen), + (PUINT_8) prDevInfoUpdateActive, NULL, 0); + + cnmMemFree(prAdapter, prDevInfoUpdateActive); + + return rWlanStatus; +} + +WLAN_STATUS +wlanoidManualAssoc(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_CMD_STAREC_UPDATE_T prStaRecManualAssoc; + P_CMD_MANUAL_ASSOC_STRUCT_T prManualAssoc; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidManualAssoc"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(CMD_STAREC_UPDATE_T); + if (u4SetBufferLen < sizeof(CMD_STAREC_UPDATE_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prStaRecManualAssoc = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, (CMD_STAREC_UPDATE_HDR_SIZE + u4SetBufferLen)); + if (!prStaRecManualAssoc) { + DBGLOG(INIT, ERROR, "Allocate P_CMD_STAREC_UPDATE_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prManualAssoc = (P_CMD_MANUAL_ASSOC_STRUCT_T) pvSetBuffer; + prStaRecManualAssoc->ucWlanIdx = prManualAssoc->ucWtbl; + prStaRecManualAssoc->ucBssIndex = prManualAssoc->ucOwnmac; + prStaRecManualAssoc->u2TotalElementNum = 1; + kalMemCopy(prStaRecManualAssoc->aucBuffer, pvSetBuffer, u4SetBufferLen); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_STAREC_UPDATE, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + (CMD_STAREC_UPDATE_HDR_SIZE + u4SetBufferLen), + (PUINT_8) prStaRecManualAssoc, NULL, 0); + + cnmMemFree(prAdapter, prStaRecManualAssoc); + + return rWlanStatus; +} + +typedef struct _TXBF_CMD_DONE_HANDLER_T { + UINT_32 u4TxBfCmdId; + VOID (*pFunc)(P_ADAPTER_T, P_CMD_INFO_T, PUINT_8); +} TXBF_CMD_DONE_HANDLER_T, *P_TXBF_CMD_DONE_HANDLER_T; + +TXBF_CMD_DONE_HANDLER_T rTxBfCmdDoneHandler[] = { + {BF_SOUNDING_OFF, nicCmdEventSetCommon}, + {BF_SOUNDING_ON, nicCmdEventSetCommon}, + {BF_HW_CTRL, nicCmdEventSetCommon}, + {BF_DATA_PACKET_APPLY, nicCmdEventSetCommon}, + {BF_PFMU_MEM_ALLOCATE, nicCmdEventSetCommon}, + {BF_PFMU_MEM_RELEASE, nicCmdEventSetCommon}, + {BF_PFMU_TAG_READ, nicCmdEventPfmuTagRead}, + {BF_PFMU_TAG_WRITE, nicCmdEventSetCommon}, + {BF_PROFILE_READ, nicCmdEventPfmuDataRead}, + {BF_PROFILE_WRITE, nicCmdEventSetCommon}, + {BF_PN_READ, nicCmdEventSetCommon}, + {BF_PN_WRITE, nicCmdEventSetCommon}, + {BF_PFMU_MEM_ALLOC_MAP_READ, nicCmdEventSetCommon} +}; + +WLAN_STATUS +wlanoidTxBfAction(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_TXBF_ACTION_STRUCT_T prTxBfActionInfo; + CMD_TXBF_ACTION_T rCmdTxBfActionInfo; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + BOOLEAN fgSetQuery, fgNeedResp; + UINT_32 u4TxBfCmdId; + + DEBUGFUNC("wlanoidTxBfAction"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_TXBF_ACTION_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_TXBF_ACTION_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prTxBfActionInfo = (P_PARAM_CUSTOM_TXBF_ACTION_STRUCT_T) pvSetBuffer; + + memcpy(&rCmdTxBfActionInfo, prTxBfActionInfo, sizeof(CMD_TXBF_ACTION_T)); + + u4TxBfCmdId = rCmdTxBfActionInfo.rProfileTagRead.ucTxBfCategory; + if (TXBF_CMD_NEED_TO_RESPONSE(u4TxBfCmdId) == 0) { /* don't need response */ + fgSetQuery = TRUE; + fgNeedResp = FALSE; + } else { + fgSetQuery = FALSE; + fgNeedResp = TRUE; + } + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_BF_ACTION, + fgSetQuery, + fgNeedResp, + g_fgIsOid, + rTxBfCmdDoneHandler[u4TxBfCmdId].pFunc, + nicOidCmdTimeoutCommon, + sizeof(CMD_TXBF_ACTION_T), + (PUINT_8) &rCmdTxBfActionInfo, pvSetBuffer, u4SetBufferLen); + + return rWlanStatus; +} + +#if CFG_SUPPORT_MU_MIMO +WLAN_STATUS +wlanoidMuMimoAction(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T prMuMimoActionInfo; + CMD_MUMIMO_ACTION_T rCmdMuMimoActionInfo; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + BOOLEAN fgSetQuery, fgNeedResp; + UINT_32 u4MuMimoCmdId; + VOID (*pFunc)(P_ADAPTER_T, P_CMD_INFO_T, PUINT_8); + + DEBUGFUNC("wlanoidMuMimoAction"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prMuMimoActionInfo = (P_PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T) pvSetBuffer; + + memcpy(&rCmdMuMimoActionInfo, prMuMimoActionInfo, sizeof(CMD_MUMIMO_ACTION_T)); + + u4MuMimoCmdId = rCmdMuMimoActionInfo.ucMuMimoCategory; + if (MU_CMD_NEED_TO_RESPONSE(u4MuMimoCmdId) == 0) { + fgSetQuery = TRUE; + fgNeedResp = FALSE; + } else { + fgSetQuery = FALSE; + fgNeedResp = TRUE; + } + + pFunc = nicCmdEventSetCommon; + if (u4MuMimoCmdId == MU_HQA_GET_QD) + pFunc = nicCmdEventGetQd; + else if (u4MuMimoCmdId == MU_HQA_GET_CALC_LQ) + pFunc = nicCmdEventGetCalcLq; + else if (u4MuMimoCmdId == MU_GET_CALC_INIT_MCS) + pFunc = nicCmdEventGetCalcInitMcs; + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_MU_CTRL, + fgSetQuery, + fgNeedResp, + g_fgIsOid, + pFunc, + nicOidCmdTimeoutCommon, + sizeof(CMD_MUMIMO_ACTION_T), + (PUINT_8) &rCmdMuMimoActionInfo, pvSetBuffer, u4SetBufferLen); + + return rWlanStatus; +} +#endif /* CFG_SUPPORT_MU_MIMO */ +#endif /* CFG_SUPPORT_TX_BF */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Trigger FW Cal for Backup Cal Data to Host Side. +* +* \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 +wlanoidSetCalBackup(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_PARAM_CAL_BACKUP_STRUCT_V2_T prCalBackupDataV2Info; + + DBGLOG(RFTEST, INFO, "%s\n", __func__); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CAL_BACKUP_STRUCT_V2_T); + + if (u4SetBufferLen < sizeof(PARAM_CAL_BACKUP_STRUCT_V2_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prCalBackupDataV2Info = (P_PARAM_CAL_BACKUP_STRUCT_V2_T) pvSetBuffer; + + if (prCalBackupDataV2Info->ucReason == 1 && prCalBackupDataV2Info->ucAction == 2) { + /* Trigger All Cal Function */ + return wlanoidSendCalBackupV2Cmd(prAdapter, pvSetBuffer, u4SetBufferLen); + } else if (prCalBackupDataV2Info->ucReason == 4 && prCalBackupDataV2Info->ucAction == 6) { + /* For Debug Use, Tell FW Print Cal Data (Rom or Ram) */ + return wlanoidSendCalBackupV2Cmd(prAdapter, pvSetBuffer, u4SetBufferLen); + } else if (prCalBackupDataV2Info->ucReason == 3 && prCalBackupDataV2Info->ucAction == 5) { + /* Send Cal Data to FW */ + if (prCalBackupDataV2Info->ucRomRam == 0) + prCalBackupDataV2Info->u4RemainLength = g_rBackupCalDataAllV2.u4ValidRomCalDataLength; + else if (prCalBackupDataV2Info->ucRomRam == 1) + prCalBackupDataV2Info->u4RemainLength = g_rBackupCalDataAllV2.u4ValidRamCalDataLength; + + return wlanoidSendCalBackupV2Cmd(prAdapter, pvSetBuffer, u4SetBufferLen); + } + + return rWlanStatus; +} + +WLAN_STATUS wlanoidSendCalBackupV2Cmd(IN P_ADAPTER_T prAdapter, IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_PARAM_CAL_BACKUP_STRUCT_V2_T prCalBackupDataV2Info; + P_CMD_CAL_BACKUP_STRUCT_V2_T prCmdCalBackupDataV2; + UINT_8 ucReason, ucAction, ucNeedResp, ucFragNum, ucRomRam; + UINT_32 u4DumpMaxSize = PARAM_CAL_DATA_DUMP_MAX_SIZE; + UINT_32 u4RemainLength, u4CurrAddr, u4CurrLen; + + DBGLOG(RFTEST, INFO, "%s\n", __func__); + + prCmdCalBackupDataV2 = + (P_CMD_CAL_BACKUP_STRUCT_V2_T) kalMemAlloc(sizeof(CMD_CAL_BACKUP_STRUCT_V2_T), VIR_MEM_TYPE); + + prCalBackupDataV2Info = (P_PARAM_CAL_BACKUP_STRUCT_V2_T) pvQueryBuffer; + + ucReason = prCalBackupDataV2Info->ucReason; + ucAction = prCalBackupDataV2Info->ucAction; + ucNeedResp = prCalBackupDataV2Info->ucNeedResp; + ucRomRam = prCalBackupDataV2Info->ucRomRam; + + if (ucAction == 2) { + /* Trigger All Cal Function */ + prCmdCalBackupDataV2->ucReason = ucReason; + prCmdCalBackupDataV2->ucAction = ucAction; + prCmdCalBackupDataV2->ucNeedResp = ucNeedResp; + prCmdCalBackupDataV2->ucFragNum = prCalBackupDataV2Info->ucFragNum; + prCmdCalBackupDataV2->ucRomRam = ucRomRam; + prCmdCalBackupDataV2->u4ThermalValue = prCalBackupDataV2Info->u4ThermalValue; + prCmdCalBackupDataV2->u4Address = prCalBackupDataV2Info->u4Address; + prCmdCalBackupDataV2->u4Length = prCalBackupDataV2Info->u4Length; + prCmdCalBackupDataV2->u4RemainLength = prCalBackupDataV2Info->u4RemainLength; +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST_DBGLOG + DBGLOG(RFTEST, INFO, "=========== Driver Send Query CMD#0 or CMD#1 (Info) ===========\n"); + DBGLOG(RFTEST, INFO, "Reason = %d\n", prCmdCalBackupDataV2->ucReason); + DBGLOG(RFTEST, INFO, "Action = %d\n", prCmdCalBackupDataV2->ucAction); + DBGLOG(RFTEST, INFO, "NeedResp = %d\n", prCmdCalBackupDataV2->ucNeedResp); + DBGLOG(RFTEST, INFO, "FragNum = %d\n", prCmdCalBackupDataV2->ucFragNum); + DBGLOG(RFTEST, INFO, "RomRam = %d\n", prCmdCalBackupDataV2->ucRomRam); + DBGLOG(RFTEST, INFO, "ThermalValue = %d\n", prCmdCalBackupDataV2->u4ThermalValue); + DBGLOG(RFTEST, INFO, "Address = 0x%08x\n", prCmdCalBackupDataV2->u4Address); + DBGLOG(RFTEST, INFO, "Length = %d\n", prCmdCalBackupDataV2->u4Length); + DBGLOG(RFTEST, INFO, "RemainLength = %d\n", prCmdCalBackupDataV2->u4RemainLength); + DBGLOG(RFTEST, INFO, "================================================================\n"); +#endif + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_CAL_BACKUP_IN_HOST_V2, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + NULL, + sizeof(CMD_CAL_BACKUP_STRUCT_V2_T), + (PUINT_8) prCmdCalBackupDataV2, pvQueryBuffer, u4QueryBufferLen); + + kalMemFree(prCmdCalBackupDataV2, VIR_MEM_TYPE, sizeof(CMD_CAL_BACKUP_STRUCT_V2_T)); + } else if (ucAction == 0 || ucAction == 1 || ucAction == 6) { + /* Query CMD#0 and CMD#1. */ + /* For Thermal Value and Total Cal Data Length. */ + prCmdCalBackupDataV2->ucReason = ucReason; + prCmdCalBackupDataV2->ucAction = ucAction; + prCmdCalBackupDataV2->ucNeedResp = ucNeedResp; + prCmdCalBackupDataV2->ucFragNum = prCalBackupDataV2Info->ucFragNum; + prCmdCalBackupDataV2->ucRomRam = ucRomRam; + prCmdCalBackupDataV2->u4ThermalValue = prCalBackupDataV2Info->u4ThermalValue; + prCmdCalBackupDataV2->u4Address = prCalBackupDataV2Info->u4Address; + prCmdCalBackupDataV2->u4Length = prCalBackupDataV2Info->u4Length; + prCmdCalBackupDataV2->u4RemainLength = prCalBackupDataV2Info->u4RemainLength; +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST_DBGLOG + DBGLOG(RFTEST, INFO, "=========== Driver Send Query CMD#0 or CMD#1 (Info) ===========\n"); + DBGLOG(RFTEST, INFO, "Reason = %d\n", prCmdCalBackupDataV2->ucReason); + DBGLOG(RFTEST, INFO, "Action = %d\n", prCmdCalBackupDataV2->ucAction); + DBGLOG(RFTEST, INFO, "NeedResp = %d\n", prCmdCalBackupDataV2->ucNeedResp); + DBGLOG(RFTEST, INFO, "FragNum = %d\n", prCmdCalBackupDataV2->ucFragNum); + DBGLOG(RFTEST, INFO, "RomRam = %d\n", prCmdCalBackupDataV2->ucRomRam); + DBGLOG(RFTEST, INFO, "ThermalValue = %d\n", prCmdCalBackupDataV2->u4ThermalValue); + DBGLOG(RFTEST, INFO, "Address = 0x%08x\n", prCmdCalBackupDataV2->u4Address); + DBGLOG(RFTEST, INFO, "Length = %d\n", prCmdCalBackupDataV2->u4Length); + DBGLOG(RFTEST, INFO, "RemainLength = %d\n", prCmdCalBackupDataV2->u4RemainLength); + DBGLOG(RFTEST, INFO, "================================================================\n"); +#endif + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_CAL_BACKUP_IN_HOST_V2, + FALSE, + TRUE, + FALSE, + nicCmdEventQueryCalBackupV2, + NULL, + sizeof(CMD_CAL_BACKUP_STRUCT_V2_T), + (PUINT_8) prCmdCalBackupDataV2, pvQueryBuffer, u4QueryBufferLen); + + kalMemFree(prCmdCalBackupDataV2, VIR_MEM_TYPE, sizeof(CMD_CAL_BACKUP_STRUCT_V2_T)); + } else if (ucAction == 4) { + /* Query All Cal Data from FW (Rom or Ram). */ + u4RemainLength = prCalBackupDataV2Info->u4RemainLength; + u4CurrAddr = prCalBackupDataV2Info->u4Address + prCalBackupDataV2Info->u4Length; + ucFragNum = prCalBackupDataV2Info->ucFragNum + 1; + + if (u4RemainLength > u4DumpMaxSize) { + u4CurrLen = u4DumpMaxSize; + u4RemainLength -= u4DumpMaxSize; + } else { + u4CurrLen = u4RemainLength; + u4RemainLength = 0; + } + + prCmdCalBackupDataV2->ucReason = ucReason; + prCmdCalBackupDataV2->ucAction = ucAction; + prCmdCalBackupDataV2->ucNeedResp = ucNeedResp; + prCmdCalBackupDataV2->ucFragNum = ucFragNum; + prCmdCalBackupDataV2->ucRomRam = ucRomRam; + prCmdCalBackupDataV2->u4ThermalValue = prCalBackupDataV2Info->u4ThermalValue; + prCmdCalBackupDataV2->u4Address = u4CurrAddr; + prCmdCalBackupDataV2->u4Length = u4CurrLen; + prCmdCalBackupDataV2->u4RemainLength = u4RemainLength; +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST_DBGLOG + DBGLOG(RFTEST, INFO, "========= Driver Send Query All Cal Data from FW (Info) =========\n"); + DBGLOG(RFTEST, INFO, "Reason = %d\n", prCmdCalBackupDataV2->ucReason); + DBGLOG(RFTEST, INFO, "Action = %d\n", prCmdCalBackupDataV2->ucAction); + DBGLOG(RFTEST, INFO, "NeedResp = %d\n", prCmdCalBackupDataV2->ucNeedResp); + DBGLOG(RFTEST, INFO, "FragNum = %d\n", prCmdCalBackupDataV2->ucFragNum); + DBGLOG(RFTEST, INFO, "RomRam = %d\n", prCmdCalBackupDataV2->ucRomRam); + DBGLOG(RFTEST, INFO, "ThermalValue = %d\n", prCmdCalBackupDataV2->u4ThermalValue); + DBGLOG(RFTEST, INFO, "Address = 0x%08x\n", prCmdCalBackupDataV2->u4Address); + DBGLOG(RFTEST, INFO, "Length = %d\n", prCmdCalBackupDataV2->u4Length); + DBGLOG(RFTEST, INFO, "RemainLength = %d\n", prCmdCalBackupDataV2->u4RemainLength); + DBGLOG(RFTEST, INFO, "=================================================================\n"); +#endif + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_CAL_BACKUP_IN_HOST_V2, + FALSE, + TRUE, + FALSE, + nicCmdEventQueryCalBackupV2, + NULL, + sizeof(CMD_CAL_BACKUP_STRUCT_V2_T), + (PUINT_8) prCmdCalBackupDataV2, pvQueryBuffer, u4QueryBufferLen); + + kalMemFree(prCmdCalBackupDataV2, VIR_MEM_TYPE, sizeof(CMD_CAL_BACKUP_STRUCT_V2_T)); + } else if (ucAction == 5) { + /* Send All Cal Data to FW (Rom or Ram). */ + u4RemainLength = prCalBackupDataV2Info->u4RemainLength; + u4CurrAddr = prCalBackupDataV2Info->u4Address + prCalBackupDataV2Info->u4Length; + ucFragNum = prCalBackupDataV2Info->ucFragNum + 1; + + if (u4RemainLength > u4DumpMaxSize) { + u4CurrLen = u4DumpMaxSize; + u4RemainLength -= u4DumpMaxSize; + } else { + u4CurrLen = u4RemainLength; + u4RemainLength = 0; + } + + prCmdCalBackupDataV2->ucReason = ucReason; + prCmdCalBackupDataV2->ucAction = ucAction; + prCmdCalBackupDataV2->ucNeedResp = ucNeedResp; + prCmdCalBackupDataV2->ucFragNum = ucFragNum; + prCmdCalBackupDataV2->ucRomRam = ucRomRam; + prCmdCalBackupDataV2->u4ThermalValue = prCalBackupDataV2Info->u4ThermalValue; + prCmdCalBackupDataV2->u4Address = u4CurrAddr; + prCmdCalBackupDataV2->u4Length = u4CurrLen; + prCmdCalBackupDataV2->u4RemainLength = u4RemainLength; +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST_DBGLOG + DBGLOG(RFTEST, INFO, "========= Driver Send All Cal Data to FW (Info) =========\n"); + DBGLOG(RFTEST, INFO, "Reason = %d\n", prCmdCalBackupDataV2->ucReason); + DBGLOG(RFTEST, INFO, "Action = %d\n", prCmdCalBackupDataV2->ucAction); + DBGLOG(RFTEST, INFO, "NeedResp = %d\n", prCmdCalBackupDataV2->ucNeedResp); + DBGLOG(RFTEST, INFO, "FragNum = %d\n", prCmdCalBackupDataV2->ucFragNum); + DBGLOG(RFTEST, INFO, "RomRam = %d\n", prCmdCalBackupDataV2->ucRomRam); + DBGLOG(RFTEST, INFO, "ThermalValue = %d\n", prCmdCalBackupDataV2->u4ThermalValue); + DBGLOG(RFTEST, INFO, "Address = 0x%08x\n", prCmdCalBackupDataV2->u4Address); + DBGLOG(RFTEST, INFO, "Length = %d\n", prCmdCalBackupDataV2->u4Length); + DBGLOG(RFTEST, INFO, "RemainLength = %d\n", prCmdCalBackupDataV2->u4RemainLength); +#endif + /* Copy Cal Data From Driver to FW */ + if (prCmdCalBackupDataV2->ucRomRam == 0) + kalMemCopy((PUINT_8)(prCmdCalBackupDataV2->au4Buffer), + (PUINT_8)(g_rBackupCalDataAllV2.au4RomCalData) + prCmdCalBackupDataV2->u4Address, + prCmdCalBackupDataV2->u4Length); + else if (prCmdCalBackupDataV2->ucRomRam == 1) + kalMemCopy((PUINT_8)(prCmdCalBackupDataV2->au4Buffer), + (PUINT_8)(g_rBackupCalDataAllV2.au4RamCalData) + prCmdCalBackupDataV2->u4Address, + prCmdCalBackupDataV2->u4Length); +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST_DBGLOG + DBGLOG(RFTEST, INFO, "Check some of elements (0x%08x), (0x%08x), (0x%08x), (0x%08x), (0x%08x)\n", + prCmdCalBackupDataV2->au4Buffer[0], prCmdCalBackupDataV2->au4Buffer[1], + prCmdCalBackupDataV2->au4Buffer[2], prCmdCalBackupDataV2->au4Buffer[3], + prCmdCalBackupDataV2->au4Buffer[4]); + DBGLOG(RFTEST, INFO, "Check some of elements (0x%08x), (0x%08x), (0x%08x), (0x%08x), (0x%08x)\n", + prCmdCalBackupDataV2->au4Buffer[(prCmdCalBackupDataV2->u4Length/sizeof(UINT_32)) - 5], + prCmdCalBackupDataV2->au4Buffer[(prCmdCalBackupDataV2->u4Length/sizeof(UINT_32)) - 4], + prCmdCalBackupDataV2->au4Buffer[(prCmdCalBackupDataV2->u4Length/sizeof(UINT_32)) - 3], + prCmdCalBackupDataV2->au4Buffer[(prCmdCalBackupDataV2->u4Length/sizeof(UINT_32)) - 2], + prCmdCalBackupDataV2->au4Buffer[(prCmdCalBackupDataV2->u4Length/sizeof(UINT_32)) - 1]); + + DBGLOG(RFTEST, INFO, "=================================================================\n"); +#endif + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_CAL_BACKUP_IN_HOST_V2, + FALSE, + TRUE, + FALSE, + nicCmdEventQueryCalBackupV2, + NULL, + sizeof(CMD_CAL_BACKUP_STRUCT_V2_T), + (PUINT_8) prCmdCalBackupDataV2, pvQueryBuffer, u4QueryBufferLen); + + kalMemFree(prCmdCalBackupDataV2, VIR_MEM_TYPE, sizeof(CMD_CAL_BACKUP_STRUCT_V2_T)); + } + + return rWlanStatus; +} + +WLAN_STATUS +wlanoidQueryCalBackupV2(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_PARAM_CAL_BACKUP_STRUCT_V2_T prCalBackupDataV2Info; + + DBGLOG(RFTEST, INFO, "%s\n", __func__); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(CMD_CAL_BACKUP_STRUCT_V2_T); + + prCalBackupDataV2Info = (P_PARAM_CAL_BACKUP_STRUCT_V2_T) pvQueryBuffer; + + if (prCalBackupDataV2Info->ucReason == 0 && prCalBackupDataV2Info->ucAction == 0) { + /* Get Thermal Temp from FW */ + return wlanoidSendCalBackupV2Cmd(prAdapter, pvQueryBuffer, u4QueryBufferLen); + } else if (prCalBackupDataV2Info->ucReason == 0 && prCalBackupDataV2Info->ucAction == 1) { + /* Get Cal Data Size from FW */ + return wlanoidSendCalBackupV2Cmd(prAdapter, pvQueryBuffer, u4QueryBufferLen); + } else if (prCalBackupDataV2Info->ucReason == 2 && prCalBackupDataV2Info->ucAction == 4) { + /* Get Cal Data from FW */ + if (prCalBackupDataV2Info->ucRomRam == 0) + prCalBackupDataV2Info->u4RemainLength = g_rBackupCalDataAllV2.u4ValidRomCalDataLength; + else if (prCalBackupDataV2Info->ucRomRam == 1) + prCalBackupDataV2Info->u4RemainLength = g_rBackupCalDataAllV2.u4ValidRamCalDataLength; + + return wlanoidSendCalBackupV2Cmd(prAdapter, pvQueryBuffer, u4QueryBufferLen); + } else { + return rWlanStatus; + } +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to do Coex Isolation Detection. + +* \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 +wlanoidQueryCoexIso(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + struct PARAM_COEX_CTRL *prParaCoexCtrl; + struct PARAM_COEX_ISO_DETECT *prParaCoexIsoDetect; + struct CMD_COEX_CTRL rCmdCoexCtrl; + struct CMD_COEX_ISO_DETECT rCmdCoexIsoDetect; + + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct PARAM_COEX_CTRL); + + if (u4QueryBufferLen < sizeof(struct PARAM_COEX_CTRL)) + return WLAN_STATUS_INVALID_LENGTH; + + prParaCoexCtrl = (struct PARAM_COEX_CTRL *) pvQueryBuffer; + prParaCoexIsoDetect = (struct PARAM_COEX_ISO_DETECT *) &prParaCoexCtrl->aucBuffer[0]; + + rCmdCoexIsoDetect.u4Channel = prParaCoexIsoDetect->u4Channel; + /*rCmdCoexIsoDetect.u4Band = prParaCoexIsoDetect->u4Band;*/ + rCmdCoexIsoDetect.u4IsoPath = prParaCoexIsoDetect->u4IsoPath; + rCmdCoexIsoDetect.u4Isolation = prParaCoexIsoDetect->u4Isolation; + + rCmdCoexCtrl.u4SubCmd = prParaCoexCtrl->u4SubCmd; + + /* Copy Memory */ + kalMemCopy(rCmdCoexCtrl.aucBuffer, &rCmdCoexIsoDetect, sizeof(rCmdCoexIsoDetect)); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_COEX_CTRL, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventQueryCoexIso, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_COEX_CTRL), + (unsigned char *) &rCmdCoexCtrl, + pvQueryBuffer, + u4QueryBufferLen); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get coex information. + +* \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 +wlanoidQueryCoexGetInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + struct PARAM_COEX_CTRL *prParaCoexCtrl; + struct PARAM_COEX_GET_INFO *prParaCoexGetInfo; + struct CMD_COEX_CTRL rCmdCoexCtrl; + struct CMD_COEX_GET_INFO rCmdCoexGetInfo; + + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(struct PARAM_COEX_CTRL); + + if (u4QueryBufferLen < sizeof(struct PARAM_COEX_CTRL)) + return WLAN_STATUS_INVALID_LENGTH; + + prParaCoexCtrl = (struct PARAM_COEX_CTRL *) pvQueryBuffer; + prParaCoexGetInfo = (struct PARAM_COEX_GET_INFO *) &prParaCoexCtrl->aucBuffer[0]; + + kalMemZero(rCmdCoexGetInfo.u4CoexInfo, sizeof(rCmdCoexGetInfo.u4CoexInfo)); + + rCmdCoexCtrl.u4SubCmd = prParaCoexCtrl->u4SubCmd; + + /* Copy Memory */ + kalMemCopy(rCmdCoexCtrl.aucBuffer, &rCmdCoexGetInfo, sizeof(rCmdCoexGetInfo)); + DBGLOG(REQ, INFO, "wlanoidQueryCoexGetInfo end\n"); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_COEX_CTRL, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventQueryCoexGetInfo, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_COEX_CTRL), + (unsigned char *) &rCmdCoexCtrl, + pvQueryBuffer, + u4QueryBufferLen); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query MCR value. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMcrRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_CUSTOM_MCR_RW_STRUCT_T prMcrRdInfo; + CMD_ACCESS_REG rCmdAccessReg; + + DEBUGFUNC("wlanoidQueryMcrRead"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T); + + if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + prMcrRdInfo = (P_PARAM_CUSTOM_MCR_RW_STRUCT_T) pvQueryBuffer; + + /* 0x9000 - 0x9EFF reserved for FW */ +#if CFG_SUPPORT_SWCR + if ((prMcrRdInfo->u4McrOffset >> 16) == 0x9F00) { + swCrReadWriteCmd(prAdapter, + SWCR_READ, + (UINT_16) (prMcrRdInfo->u4McrOffset & BITS(0, 15)), &prMcrRdInfo->u4McrData); + return WLAN_STATUS_SUCCESS; + } +#endif /* CFG_SUPPORT_SWCR */ + + /* Check if access F/W Domain MCR (due to WiFiSYS is placed from 0x6000-0000 */ + if (prMcrRdInfo->u4McrOffset & 0xFFFF0000) { + /* fill command */ + rCmdAccessReg.u4Address = prMcrRdInfo->u4McrOffset; + rCmdAccessReg.u4Data = 0; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + FALSE, + TRUE, + g_fgIsOid, + 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 = %#08x, Data = %#08x\n", + prMcrRdInfo->u4McrOffset, prMcrRdInfo->u4McrData); + return WLAN_STATUS_SUCCESS; + } +} /* end of wlanoidQueryMcrRead() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to write MCR and enable specific function. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetMcrWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_MCR_RW_STRUCT_T prMcrWrInfo; + CMD_ACCESS_REG rCmdAccessReg; + +#if CFG_STRESS_TEST_SUPPORT + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prBssInfo = prAdapter->prAisBssInfo; + 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_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prMcrWrInfo = (P_PARAM_CUSTOM_MCR_RW_STRUCT_T) pvSetBuffer; + + /* 0x9000 - 0x9EFF reserved for FW */ + /* 0xFFFE reserved for FW */ + + /* -- Puff Stress Test Begin */ +#if CFG_STRESS_TEST_SUPPORT + + /* 0xFFFFFFFE for Control Rate */ + if (prMcrWrInfo->u4McrOffset == 0xFFFFFFFE) { + if (prMcrWrInfo->u4McrData < FIXED_RATE_NUM && prMcrWrInfo->u4McrData > 0) + prAdapter->rWifiVar.eRateSetting = (ENUM_REGISTRY_FIXED_RATE_T) (prMcrWrInfo->u4McrData); + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + DEBUGFUNC("[Stress Test]Complete Rate is Changed...\n"); + DBGLOG(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 */ + } + } + + 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, + g_fgIsOid, + 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, + g_fgIsOid, + 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, + g_fgIsOid, + 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, + g_fgIsOid, + 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, + g_fgIsOid, + 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, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); + } +#endif + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN + if (prMcrWrInfo->u4McrOffset == 0x22220000) { + /* read test mode */ + kalSetSdioTestPattern(prAdapter->prGlueInfo, TRUE, TRUE); + + return WLAN_STATUS_SUCCESS; + } + + if (prMcrWrInfo->u4McrOffset == 0x22220001) { + /* write test mode */ + kalSetSdioTestPattern(prAdapter->prGlueInfo, TRUE, FALSE); + + return WLAN_STATUS_SUCCESS; + } + + if (prMcrWrInfo->u4McrOffset == 0x22220002) { + /* leave from test mode */ + kalSetSdioTestPattern(prAdapter->prGlueInfo, FALSE, FALSE); + + return WLAN_STATUS_SUCCESS; + } +#endif + + /* fill command */ + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + TRUE, + FALSE, + g_fgIsOid, + 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 = %#08x, Data = %#08x\n", + prMcrWrInfo->u4McrOffset, prMcrWrInfo->u4McrData); + + return WLAN_STATUS_SUCCESS; + } +} /* wlanoidSetMcrWrite */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query driver 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 +wlanoidQueryDrvMcrRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_CUSTOM_MCR_RW_STRUCT_T prMcrRdInfo; + /* CMD_ACCESS_REG rCmdAccessReg; */ + + DEBUGFUNC("wlanoidQueryMcrRead"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T); + + if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + prMcrRdInfo = (P_PARAM_CUSTOM_MCR_RW_STRUCT_T) pvQueryBuffer; + + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + HAL_MCR_RD(prAdapter, (prMcrRdInfo->u4McrOffset & BITS(2, 31)), &prMcrRdInfo->u4McrData); + + DBGLOG(INIT, TRACE, "DRV MCR Read: Offset = %#08x, Data = %#08x\n", + prMcrRdInfo->u4McrOffset, prMcrRdInfo->u4McrData); + + return WLAN_STATUS_SUCCESS; + +} /* end of wlanoidQueryMcrRead() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to write MCR and enable specific function. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetDrvMcrWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_MCR_RW_STRUCT_T prMcrWrInfo; + /* CMD_ACCESS_REG rCmdAccessReg; */ + + DEBUGFUNC("wlanoidSetMcrWrite"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prMcrWrInfo = (P_PARAM_CUSTOM_MCR_RW_STRUCT_T) pvSetBuffer; + + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + HAL_MCR_WR(prAdapter, (prMcrWrInfo->u4McrOffset & BITS(2, 31)), prMcrWrInfo->u4McrData); + + DBGLOG(INIT, TRACE, "DRV MCR Write: Offset = %#08x, Data = %#08x\n", + prMcrWrInfo->u4McrOffset, prMcrWrInfo->u4McrData); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetMcrWrite */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query SW CTRL +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQuerySwCtrlRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_CUSTOM_SW_CTRL_STRUCT_T prSwCtrlInfo; + WLAN_STATUS rWlanStatus; + UINT_16 u2Id, u2SubId; + UINT_32 u4Data; + + CMD_SW_DBG_CTRL_T rCmdSwCtrl; + + DEBUGFUNC("wlanoidQuerySwCtrlRead"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T); + + if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + prSwCtrlInfo = (P_PARAM_CUSTOM_SW_CTRL_STRUCT_T) pvQueryBuffer; + + u2Id = (UINT_16) (prSwCtrlInfo->u4Id >> 16); + u2SubId = (UINT_16) (prSwCtrlInfo->u4Id & BITS(0, 15)); + u4Data = 0; + rWlanStatus = WLAN_STATUS_SUCCESS; + + switch (u2Id) { + /* 0x9000 - 0x9EFF reserved for FW */ + /* 0xFFFE reserved for FW */ + +#if CFG_SUPPORT_SWCR + case 0x9F00: + swCrReadWriteCmd(prAdapter, SWCR_READ /* Read */, + (UINT_16) u2SubId, &u4Data); + break; +#endif /* CFG_SUPPORT_SWCR */ + + case 0xFFFF: + { + u4Data = 0x5AA56620; + } + break; + + case 0xBABA: + switch ((u2SubId >> 8) & BITS(0, 7)) { + case 0x00: + /* Dump Tx resource and queue status */ + qmDumpQueueStatus(prAdapter, NULL, 0); + cnmDumpMemoryStatus(prAdapter, NULL, 0); + break; + + case 0x01: + /* Dump StaRec info by index */ + cnmDumpStaRec(prAdapter, (UINT_8) (u2SubId & BITS(0, 7))); + break; + + case 0x02: + /* Dump BSS info by index */ + bssDumpBssInfo(prAdapter, (UINT_8) (u2SubId & BITS(0, 7))); + break; + + case 0x03: + /*Dump BSS statistics by index */ + wlanDumpBssStatistics(prAdapter, (UINT_8) (u2SubId & BITS(0, 7))); + break; + + case 0x04: + halDumpHifStatus(prAdapter, NULL, 0); + break; + + default: + break; + } + + u4Data = 0xBABABABA; + break; + + case 0x9000: + default: + { + rCmdSwCtrl.u4Id = prSwCtrlInfo->u4Id; + rCmdSwCtrl.u4Data = 0; + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventQuerySwCtrlRead, + nicOidCmdTimeoutCommon, + sizeof(CMD_SW_DBG_CTRL_T), + (PUINT_8) &rCmdSwCtrl, pvQueryBuffer, u4QueryBufferLen); + return rWlanStatus; + } + } /* switch(u2Id) */ + + prSwCtrlInfo->u4Data = u4Data; + + return rWlanStatus; + +} + + /* end of wlanoidQuerySwCtrlRead() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to write SW CTRL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetSwCtrlWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_SW_CTRL_STRUCT_T prSwCtrlInfo; + CMD_SW_DBG_CTRL_T rCmdSwCtrl; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + UINT_16 u2Id, u2SubId; + UINT_32 u4Data; + UINT_8 ucNss; + UINT_8 ucChannelWidth; + UINT_8 ucBssIndex; + + DEBUGFUNC("wlanoidSetSwCtrlWrite"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prSwCtrlInfo = (P_PARAM_CUSTOM_SW_CTRL_STRUCT_T) pvSetBuffer; + + u2Id = (UINT_16) (prSwCtrlInfo->u4Id >> 16); + u2SubId = (UINT_16) (prSwCtrlInfo->u4Id & BITS(0, 15)); + u4Data = prSwCtrlInfo->u4Data; + + 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 0x2222: + ucNss = (UINT_8)(u4Data & BITS(0, 3)); + ucChannelWidth = (UINT_8)((u4Data & BITS(4, 7)) >> 4); + ucBssIndex = (UINT_8) u2SubId; + + /* ucChannelWidth 0:20MHz, 1:40MHz, 2:80MHz, 3:160MHz 4:80+80MHz */ + DBGLOG(REQ, INFO, "Change BSS[%d] OpMode to BW[%d] Nss[%d]\n", + ucBssIndex, ucChannelWidth, ucNss); + rlmChangeOperationMode(prAdapter, ucBssIndex, ucChannelWidth, ucNss); + break; + + 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, + prAdapter->prAisBssInfo->ucBssIndex, + ePowerMode, g_fgIsOid); + } + } + break; + case 0x1001: + if (u2SubId == 0x0) + prAdapter->fgEnOnlineScan = (BOOLEAN) u4Data; + else if (u2SubId == 0x1) + prAdapter->fgDisBcnLostDetection = (BOOLEAN) u4Data; + else if (u2SubId == 0x2) + prAdapter->rWifiVar.ucUapsd = (BOOLEAN) u4Data; + else if (u2SubId == 0x3) { + prAdapter->u4UapsdAcBmp = u4Data & BITS(0, 15); + GET_BSS_INFO_BY_INDEX(prAdapter, + u4Data >> 16)->rPmProfSetupInfo.ucBmpDeliveryAC = + (UINT_8) prAdapter->u4UapsdAcBmp; + GET_BSS_INFO_BY_INDEX(prAdapter, + u4Data >> 16)->rPmProfSetupInfo.ucBmpTriggerAC = + (UINT_8) prAdapter->u4UapsdAcBmp; + } else if (u2SubId == 0x4) + prAdapter->fgDisStaAgingTimeoutDetection = (BOOLEAN) u4Data; + else if (u2SubId == 0x5) + prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode = (UINT_8) u4Data; + else if (u2SubId == 0x0100) { + if (u4Data == 2) + prAdapter->rWifiVar.ucRxGf = FEATURE_DISABLED; + else + prAdapter->rWifiVar.ucRxGf = FEATURE_ENABLED; + } else if (u2SubId == 0x0101) + prAdapter->rWifiVar.ucRxShortGI = (UINT_8) u4Data; + else if (u2SubId == 0x0110) { + prAdapter->fgIsEnableLpdvt = (BOOLEAN) u4Data; + prAdapter->fgEnOnlineScan = (BOOLEAN) u4Data; + DBGLOG(INIT, INFO, "--- Enable LPDVT [%d] ---\n", prAdapter->fgIsEnableLpdvt); + } + + break; + +#if CFG_SUPPORT_SWCR + case 0x1002: +#if CFG_RX_PKTS_DUMP + if (u2SubId == 0x0) { + if (u4Data) + u4Data = BIT(HIF_RX_PKT_TYPE_MANAGEMENT); + swCrFrameCheckEnable(prAdapter, u4Data); + } +#endif + 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->prAisBssInfo; + + authSendDeauthFrame(prAdapter, prBssInfo, 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: %u\n", + u4Data); + + if ((ENUM_REGISTRY_FIXED_RATE_T) (u4Data) < FIXED_RATE_NUM) + prAdapter->rWifiVar.eRateSetting = (ENUM_REGISTRY_FIXED_RATE_T) (u4Data); + else + prAdapter->rWifiVar.eRateSetting = FIXED_RATE_NONE; + + if (prAdapter->rWifiVar.eRateSetting == FIXED_RATE_NONE) + /* Enable Auto (Long/Short) Preamble */ + prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_AUTO; + else if ((prAdapter->rWifiVar.eRateSetting >= FIXED_RATE_MCS0_20M_400NS && + prAdapter->rWifiVar.eRateSetting <= FIXED_RATE_MCS7_20M_400NS) + || (prAdapter->rWifiVar.eRateSetting >= FIXED_RATE_MCS0_40M_400NS && + prAdapter->rWifiVar.eRateSetting <= FIXED_RATE_MCS32_400NS)) + /* Force Short Preamble */ + prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_SHORT; + else + /* Force Long Preamble */ + prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_LONG; + + /* abort to re-connect */ +#if 1 + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); +#else + aisBssBeaconTimeout(prAdapter); +#endif + + return WLAN_STATUS_SUCCESS; + + } else if (u2SubId == 0x1234) { + /* 1. Disable On-Lin Scan */ + /* 3. Disable FIFO FULL no ack */ + /* 4. Disable Roaming */ + /* Disalbe auto tx power */ + /* 2. Keep at CAM mode */ + /* 5. Disable Beacon Timeout Detection */ + rWlanStatus = nicEnterCtiaMode(prAdapter, TRUE, TRUE); + } else if (u2SubId == 0x1235) { + /* 1. Enaable On-Lin Scan */ + /* 3. Enable FIFO FULL no ack */ + /* 4. Enable Roaming */ + /* Enable auto tx power */ + /* 2. Keep at Fast PS */ + /* 5. Enable Beacon Timeout Detection */ + rWlanStatus = nicEnterCtiaMode(prAdapter, FALSE, TRUE); + } +#endif +#if CFG_MTK_STAGE_SCAN + else if (u2SubId == 0x1250) + prAdapter->aePreferBand[KAL_NETWORK_TYPE_AIS_INDEX] = BAND_NULL; + else if (u2SubId == 0x1251) + prAdapter->aePreferBand[KAL_NETWORK_TYPE_AIS_INDEX] = BAND_2G4; + else if (u2SubId == 0x1252) { + if (prAdapter->fgEnable5GBand) + prAdapter->aePreferBand[KAL_NETWORK_TYPE_AIS_INDEX] = BAND_5G; + else + /* Skip this setting if 5G band is disabled */ + DBGLOG(SCN, INFO, "Skip 5G stage scan request due to 5G is disabled\n"); + } +#endif + } + break; + + case 0x9000: + default: + { + rCmdSwCtrl.u4Id = prSwCtrlInfo->u4Id; + rCmdSwCtrl.u4Data = prSwCtrlInfo->u4Data; + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_SW_DBG_CTRL_T), + (PUINT_8) &rCmdSwCtrl, pvSetBuffer, u4SetBufferLen); + } + } /* switch(u2Id) */ + + return rWlanStatus; +} /* wlanoidSetSwCtrlWrite */ + +WLAN_STATUS +wlanoidQueryChipConfig(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T prChipConfigInfo; + CMD_CHIP_CONFIG_T rCmdChipConfig; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQuerySwCtrlRead"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T); + + if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + prChipConfigInfo = (P_PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T) pvQueryBuffer; + kalMemZero(&rCmdChipConfig, sizeof(rCmdChipConfig)); + + rCmdChipConfig.u2Id = prChipConfigInfo->u2Id; + rCmdChipConfig.ucType = prChipConfigInfo->ucType; + rCmdChipConfig.ucRespType = prChipConfigInfo->ucRespType; + rCmdChipConfig.u2MsgSize = prChipConfigInfo->u2MsgSize; + if (rCmdChipConfig.u2MsgSize > CHIP_CONFIG_RESP_SIZE) { + DBGLOG(REQ, INFO, "Chip config Msg Size %u is not valid (query)\n", rCmdChipConfig.u2MsgSize); + rCmdChipConfig.u2MsgSize = CHIP_CONFIG_RESP_SIZE; + } + kalMemCopy(rCmdChipConfig.aucCmd, prChipConfigInfo->aucCmd, rCmdChipConfig.u2MsgSize); + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_CHIP_CONFIG, FALSE, + TRUE, g_fgIsOid, + /*nicCmdEventQuerySwCtrlRead, */ + nicCmdEventQueryChipConfig, + nicOidCmdTimeoutCommon, + sizeof(CMD_CHIP_CONFIG_T), + (PUINT_8) &rCmdChipConfig, pvQueryBuffer, u4QueryBufferLen); + + return rWlanStatus; + +} + + /* end of wlanoidQueryChipConfig() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set chip +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetChipConfig(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T prChipConfigInfo; + CMD_CHIP_CONFIG_T rCmdChipConfig; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DATA_STRUCT_INSPECTING_ASSERT(sizeof(prChipConfigInfo->aucCmd) == CHIP_CONFIG_RESP_SIZE); + DEBUGFUNC("wlanoidSetChipConfig"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prChipConfigInfo = (P_PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T) pvSetBuffer; + kalMemZero(&rCmdChipConfig, sizeof(rCmdChipConfig)); + + rCmdChipConfig.u2Id = prChipConfigInfo->u2Id; + rCmdChipConfig.ucType = prChipConfigInfo->ucType; + rCmdChipConfig.ucRespType = prChipConfigInfo->ucRespType; + rCmdChipConfig.u2MsgSize = prChipConfigInfo->u2MsgSize; + if (rCmdChipConfig.u2MsgSize > CHIP_CONFIG_RESP_SIZE) { + DBGLOG(REQ, INFO, "Chip config Msg Size %u is not valid (set)\n", rCmdChipConfig.u2MsgSize); + rCmdChipConfig.u2MsgSize = CHIP_CONFIG_RESP_SIZE; + } + kalMemCopy(rCmdChipConfig.aucCmd, prChipConfigInfo->aucCmd, rCmdChipConfig.u2MsgSize); + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_CHIP_CONFIG, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CHIP_CONFIG_T), + (PUINT_8) &rCmdChipConfig, pvSetBuffer, u4SetBufferLen); + + return rWlanStatus; +} /* wlanoidSetChipConfig */ + + + + + + +VOID +wlanLoadDefaultCustomerSetting(IN P_ADAPTER_T prAdapter) { + + UINT_8 ucItemNum, i; + + + ucItemNum = (sizeof(g_rDefaulteSetting) / sizeof(PARAM_CUSTOM_KEY_CFG_STRUCT_T)); + DBGLOG(INIT, INFO, "[wlanLoadDefaultCustomerSetting] default firmware setting %d item\n", ucItemNum); + + + for (i = 0; i < ucItemNum; i++) { + wlanCfgSet(prAdapter, g_rDefaulteSetting[i].aucKey, g_rDefaulteSetting[i].aucValue, 0); + DBGLOG(INIT, INFO, "%s with %s\n", g_rDefaulteSetting[i].aucKey, g_rDefaulteSetting[i].aucValue); + } + +#if 1 + /*If need to re-parsing , included wlanInitFeatureOption*/ + wlanInitFeatureOption(prAdapter); +#endif + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set cfg and callback +* +* \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 +wlanoidSetKeyCfg(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_PARAM_CUSTOM_KEY_CFG_STRUCT_T prKeyCfgInfo; + + DEBUGFUNC("wlanoidSetKeyCfg"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_KEY_CFG_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_KEY_CFG_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + prKeyCfgInfo = (P_PARAM_CUSTOM_KEY_CFG_STRUCT_T) pvSetBuffer; + + if (kalMemCmp(prKeyCfgInfo->aucKey, "reload", 6) == 0) + wlanGetConfig(prAdapter); /* Reload config file */ + else + wlanCfgSet(prAdapter, prKeyCfgInfo->aucKey, prKeyCfgInfo->aucValue, 0); + + wlanInitFeatureOption(prAdapter); +#if CFG_SUPPORT_EASY_DEBUG + wlanFeatureToFw(prAdapter); +#endif + + return rWlanStatus; +} + + /* wlanoidSetSwCtrlWrite */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query EEPROM value. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryEepromRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T prEepromRwInfo; + CMD_ACCESS_EEPROM rCmdAccessEeprom; + + DEBUGFUNC("wlanoidQueryEepromRead"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T); + + if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + prEepromRwInfo = (P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T) pvQueryBuffer; + + kalMemZero(&rCmdAccessEeprom, sizeof(CMD_ACCESS_EEPROM)); + rCmdAccessEeprom.u2Offset = prEepromRwInfo->ucEepromIndex; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_EEPROM, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventQueryEepromRead, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_EEPROM), + (PUINT_8) &rCmdAccessEeprom, pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryEepromRead */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to write EEPROM value. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetEepromWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T prEepromRwInfo; + CMD_ACCESS_EEPROM rCmdAccessEeprom; + + DEBUGFUNC("wlanoidSetEepromWrite"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prEepromRwInfo = (P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T) pvSetBuffer; + + kalMemZero(&rCmdAccessEeprom, sizeof(CMD_ACCESS_EEPROM)); + rCmdAccessEeprom.u2Offset = prEepromRwInfo->ucEepromIndex; + rCmdAccessEeprom.u2Data = prEepromRwInfo->u2EepromData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_EEPROM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_EEPROM), + (PUINT_8) &rCmdAccessEeprom, pvSetBuffer, u4SetBufferLen); + +} /* wlanoidSetEepromWrite */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of the successfully transmitted +* packets. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryXmitOk(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryXmitOk"); + DBGLOG(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; + } +#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; + } +#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; + } +#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; + } +#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; + } +#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; + } +#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: %#08X\n", + *(PUINT_32) pvQueryBuffer); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryOidInterfaceVersion */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query current Multicast Address List. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMulticastList(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ +#ifndef LINUX + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_MAC_MCAST_ADDR, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryMcastAddr, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); +#else + return WLAN_STATUS_SUCCESS; +#endif +} /* end of wlanoidQueryMulticastList() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set Multicast Address List. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetMulticastList(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + CMD_MAC_MCAST_ADDR rCmdMacMcastAddr; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* The data must be a multiple of the Ethernet address size. */ + if ((u4SetBufferLen % MAC_ADDR_LEN)) { + DBGLOG(REQ, WARN, + "Invalid MC list length %u\n", u4SetBufferLen); + + *pu4SetInfoLen = (((u4SetBufferLen + MAC_ADDR_LEN) - 1) / MAC_ADDR_LEN) * MAC_ADDR_LEN; + + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = u4SetBufferLen; + + /* Verify if we can support so many multicast addresses. */ + if (u4SetBufferLen > MAX_NUM_GROUP_ADDR * MAC_ADDR_LEN) { + 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.ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + kalMemCopy(rCmdMacMcastAddr.arAddress, pvSetBuffer, u4SetBufferLen); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_MAC_MCAST_ADDR, + TRUE, + FALSE, + g_fgIsOid, + 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; + WLAN_STATUS rResult = WLAN_STATUS_FAILURE; + CMD_RX_PACKET_FILTER rSetRxPacketFilter; + + DBGLOG(REQ, INFO, "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: %#08x\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; + DBGLOG(REQ, WARN, "some flags we don't support\n"); + 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 + + prAdapter->fgAllMulicastFilter = FALSE; + if (u4NewPacketFilter & PARAM_PACKET_FILTER_ALL_MULTICAST) + prAdapter->fgAllMulicastFilter = TRUE; + } while (FALSE); + + if (rStatus == WLAN_STATUS_SUCCESS) { + /* Store the packet filter */ + + prAdapter->u4OsPacketFilter &= PARAM_PACKET_FILTER_P2P_MASK; + prAdapter->u4OsPacketFilter |= u4NewPacketFilter; + + rSetRxPacketFilter.u4RxPacketFilter = prAdapter->u4OsPacketFilter; + + rResult = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RX_FILTER, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_RX_PACKET_FILTER), + (PUINT_8) &rSetRxPacketFilter, pvSetBuffer, u4SetBufferLen); + prAdapter->u4OsPacketFilter = rSetRxPacketFilter.u4RxPacketFilter; + return rResult; + } 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 %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prRtsThreshold = (PARAM_RTS_THRESHOLD *) pvSetBuffer; + *prRtsThreshold = prAdapter->rWlanInfo.eRtsThreshold; + + return WLAN_STATUS_SUCCESS; + +} /* wlanoidSetRtsThreshold */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to turn radio off. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetDisassociate(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_MSG_AIS_ABORT_T prAisAbortMsg; + + DEBUGFUNC("wlanoidSetDisassociate"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 0; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(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) { + DBGLOG(REQ, ERROR, "Fail in creating AisAbortMsg.\n"); + return WLAN_STATUS_FAILURE; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; + prAisAbortMsg->fgDelayIndication = FALSE; + +#if CFG_DISCONN_DEBUG_FEATURE + /* used to disconnect debug capability */ + g_rDisconnInfoTemp.ucTrigger = DISCONNECT_TRIGGER_ACTIVE; +#endif + + 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_LOCALLY, NULL, 0); +#if !defined(LINUX) + prAdapter->fgIsRadioOff = TRUE; +#endif + + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetDisassociate */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to query the power save profile. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQuery802dot11PowerSaveProfile(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQuery802dot11PowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen != 0) { + ASSERT(pvQueryBuffer); + +/* *(PPARAM_POWER_MODE) pvQueryBuffer = (PARAM_POWER_MODE)(prAdapter->rWlanInfo.ePowerSaveMode.ucPsProfile); */ + *(PPARAM_POWER_MODE) pvQueryBuffer = + (PARAM_POWER_MODE) (prAdapter->rWlanInfo.arPowerSaveMode[prAdapter->prAisBssInfo->ucBssIndex]. + 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; + P_PARAM_POWER_MODE_T prPowerMode; + P_BSS_INFO_T prBssInfo; + + const PUINT_8 apucPsMode[Param_PowerModeMax] = { + (PUINT_8) "CAM", + (PUINT_8) "MAX PS", + (PUINT_8) "FAST PS" + }; + + DEBUGFUNC("wlanoidSet802dot11PowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_POWER_MODE_T); + prPowerMode = (P_PARAM_POWER_MODE_T) pvSetBuffer; + + if (u4SetBufferLen < sizeof(PARAM_POWER_MODE_T)) { + DBGLOG(REQ, WARN, + "Set power mode error: Invalid length %u\n", + u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } else if (prPowerMode->ePowerMode >= Param_PowerModeMax) { + DBGLOG(REQ, WARN, "Set power mode error: Invalid power mode(%u)\n", prPowerMode->ePowerMode); + return WLAN_STATUS_INVALID_DATA; + } else if (prPowerMode->ucBssIdx >= BSS_INFO_NUM) { + DBGLOG(REQ, WARN, "Set power mode error: Invalid BSS index(%u)\n", prPowerMode->ucBssIdx); + return WLAN_STATUS_INVALID_DATA; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prPowerMode->ucBssIdx); + + if (prAdapter->fgEnCtiaPowerMode) { + if (prPowerMode->ePowerMode != Param_PowerModeCAM) { + /* User setting to PS mode (Param_PowerModeMAX_PSP or Param_PowerModeFast_PSP) */ + + if (prAdapter->u4CtiaPowerMode == 0) + /* force to keep in CAM mode */ + prPowerMode->ePowerMode = Param_PowerModeCAM; + else if (prAdapter->u4CtiaPowerMode == 1) + prPowerMode->ePowerMode = Param_PowerModeMAX_PSP; + else if (prAdapter->u4CtiaPowerMode == 2) + prPowerMode->ePowerMode = Param_PowerModeFast_PSP; + } + } + + /* only CAM mode allowed when TP/Sigma on */ + if ((prAdapter->rWifiVar.ucTpTestMode == ENUM_TP_TEST_MODE_THROUGHPUT) || + (prAdapter->rWifiVar.ucTpTestMode == ENUM_TP_TEST_MODE_SIGMA_AC_N_PMF)) + prPowerMode->ePowerMode = Param_PowerModeCAM; + + /* for WMM PS Sigma certification, keep WiFi in ps mode continuously */ + /* force PS == Param_PowerModeMAX_PSP */ + if ((prAdapter->rWifiVar.ucTpTestMode == ENUM_TP_TEST_MODE_SIGMA_WMM_PS) && + (prPowerMode->ePowerMode >= Param_PowerModeMAX_PSP)) + prPowerMode->ePowerMode = Param_PowerModeMAX_PSP; + + status = nicConfigPowerSaveProfile(prAdapter, + prPowerMode->ucBssIdx, prPowerMode->ePowerMode, g_fgIsOid); + + if (prPowerMode->ePowerMode < Param_PowerModeMax) { + DBGLOG(INIT, INFO, "Set %s Network BSS(%u) PS mode to %s (%d)\n", + apucNetworkType[prBssInfo->eNetworkType], + prPowerMode->ucBssIdx, apucPsMode[prPowerMode->ePowerMode], prPowerMode->ePowerMode); + } else { + DBGLOG(INIT, INFO, "Invalid PS mode setting (%d) for %s Network BSS(%u)\n", + prPowerMode->ePowerMode, apucNetworkType[prBssInfo->eNetworkType], prPowerMode->ucBssIdx); + } + + 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->prAisBssInfo->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 = %u\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 u4CSUMFlags; + CMD_BASIC_CONFIG_T rCmdBasicConfig; + P_WIFI_VAR_T prWifiVar = &prAdapter->rWifiVar; + + 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_T)); + + 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; + rCmdBasicConfig.ucCtrlFlagAssertPath = prWifiVar->ucCtrlFlagAssertPath; + rCmdBasicConfig.ucCtrlFlagDebugLevel = prWifiVar->ucCtrlFlagDebugLevel; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_BASIC_CONFIG, + TRUE, + FALSE, + g_fgIsOid, + NULL, + nicOidCmdTimeoutCommon, + sizeof(CMD_BASIC_CONFIG_T), + (PUINT_8) &rCmdBasicConfig, pvSetBuffer, u4SetBufferLen); + + return WLAN_STATUS_SUCCESS; +} +#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, u4IPv4AddrIdx; + P_CMD_SET_NETWORK_ADDRESS_LIST prCmdNetworkAddressList; + P_PARAM_NETWORK_ADDRESS_LIST prNetworkAddressList = (P_PARAM_NETWORK_ADDRESS_LIST) pvSetBuffer; + P_PARAM_NETWORK_ADDRESS prNetworkAddress; + UINT_32 u4IPv4AddrCount, u4CmdSize; +#if CFG_ENABLE_GTK_FRAME_FILTER + UINT_32 u4IpV4AddrListSize; + P_BSS_INFO_T prBssInfo = &prAdapter->rWifiVar.arBssInfoPool[KAL_NETWORK_TYPE_AIS_INDEX]; +#endif + + DEBUGFUNC("wlanoidSetNetworkAddress"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 4; + + if (u4SetBufferLen < OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress)) + return WLAN_STATUS_INVALID_DATA; + + *pu4SetInfoLen = 0; + u4IPv4AddrCount = 0; + + /* 4 <1.1> Get IPv4 address count */ + /* We only suppot IPv4 address setting */ + prNetworkAddress = prNetworkAddressList->arAddress; + for (i = 0; i < prNetworkAddressList->u4AddressCount; i++) { + if ((prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP) && + (prNetworkAddress->u2AddressLength == IPV4_ADDR_LEN)) { + u4IPv4AddrCount++; + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prNetworkAddress + + (ULONG) (prNetworkAddress->u2AddressLength + + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + + /* 4 <2> Calculate command buffer size */ + /* construct payload of command packet */ + if (u4IPv4AddrCount == 0) + u4CmdSize = sizeof(CMD_SET_NETWORK_ADDRESS_LIST); + else + u4CmdSize = OFFSET_OF(CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress) + + (sizeof(IPV4_NETWORK_ADDRESS) * u4IPv4AddrCount); + + /* 4 <3> Allocate command buffer */ + prCmdNetworkAddressList = (P_CMD_SET_NETWORK_ADDRESS_LIST) kalMemAlloc(u4CmdSize, VIR_MEM_TYPE); + + if (prCmdNetworkAddressList == NULL) + return WLAN_STATUS_FAILURE; + +#if CFG_ENABLE_GTK_FRAME_FILTER + u4IpV4AddrListSize = OFFSET_OF(IPV4_NETWORK_ADDRESS_LIST, arNetAddr) + + (u4IPv4AddrCount * sizeof(IPV4_NETWORK_ADDRESS)); + if (prBssInfo->prIpV4NetAddrList) + FREE_IPV4_NETWORK_ADDR_LIST(prBssInfo->prIpV4NetAddrList); + prBssInfo->prIpV4NetAddrList = (P_IPV4_NETWORK_ADDRESS_LIST) kalMemAlloc(u4IpV4AddrListSize, VIR_MEM_TYPE); + prBssInfo->prIpV4NetAddrList->ucAddrCount = (UINT_8) u4IPv4AddrCount; +#endif + + /* 4 <4> Fill P_CMD_SET_NETWORK_ADDRESS_LIST */ + prCmdNetworkAddressList->ucBssIndex = prNetworkAddressList->ucBssIdx; + + /* only to set IP address to FW once ARP filter is enabled */ + if (prAdapter->fgEnArpFilter) { + prCmdNetworkAddressList->ucAddressCount = (UINT_8) u4IPv4AddrCount; + prNetworkAddress = prNetworkAddressList->arAddress; + + /* DBGLOG(INIT, INFO, ("%s: u4IPv4AddrCount (%lu)\n", __FUNCTION__, u4IPv4AddrCount)); */ + + for (i = 0, u4IPv4AddrIdx = 0; i < prNetworkAddressList->u4AddressCount; i++) { + if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == IPV4_ADDR_LEN) { + + kalMemCopy(prCmdNetworkAddressList->arNetAddress[u4IPv4AddrIdx].aucIpAddr, + prNetworkAddress->aucAddress, sizeof(UINT_32)); + +#if CFG_ENABLE_GTK_FRAME_FILTER + kalMemCopy(prBssInfo->prIpV4NetAddrList->arNetAddr[u4IPv4AddrIdx].aucIpAddr, + prNetworkAddress->aucAddress, sizeof(UINT_32)); +#endif + + DBGLOG(INIT, INFO, + "%s: IPv4 Addr [%u][" IPV4STR "]\n", __func__, + u4IPv4AddrIdx, IPV4TOSTR(prNetworkAddress->aucAddress)); + + u4IPv4AddrIdx++; + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prNetworkAddress + + (ULONG) (prNetworkAddress->u2AddressLength + + OFFSET_OF(PARAM_NETWORK_ADDRESS, + aucAddress))); + } + + } else { + prCmdNetworkAddressList->ucAddressCount = 0; + } + + DBGLOG(INIT, INFO, + "%s: Set %u IPv4 address for BSS[%u]\n", + __func__, u4IPv4AddrCount, + prCmdNetworkAddressList->ucBssIndex); + + /* 4 <5> Send command */ + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_IP_ADDRESS, + TRUE, + FALSE, + g_fgIsOid, + 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(pu4SetInfoLen); + + *pu4SetInfoLen = 0; + + if (u4SetBufferLen == 0) { + if ((prAdapter->fgTestMode == FALSE) + || (prAdapter->fgIcapMode == TRUE)) { + /* switch to RF Test mode */ + rCmdTestCtrl.ucAction = 0; /* Switch mode */ + rCmdTestCtrl.u.u4OpMode = 1; /* RF test mode */ + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_TEST_CTRL, + TRUE, + FALSE, + g_fgIsOid, + 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 RF test ICAP 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 +wlanoidRftestSetTestIcapMode(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("wlanoidRftestSetTestIcapMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 0; + + if (u4SetBufferLen == 0) { + if (prAdapter->fgIcapMode == FALSE) { + /* switch to RF Test mode */ + rCmdTestCtrl.ucAction = 0; /* Switch mode */ + rCmdTestCtrl.u.u4OpMode = 2; /* RF test mode */ + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_TEST_CTRL, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventEnterRfTest, + nicOidCmdEnterRFTestTimeout, + sizeof(CMD_TEST_CTRL_T), + (PUINT_8) &rCmdTestCtrl, pvSetBuffer, u4SetBufferLen); + } else { + /* already in ICAP 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("wlanoidRftestSetAbortTestMode"); + + ASSERT(prAdapter); + 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_CTRL, + TRUE, + FALSE, + g_fgIsOid, + 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_STRUCT_T prRfATInfo; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidRftestQueryAutoTest"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(PARAM_MTK_WIFI_TEST_STRUCT_T); + + if (u4QueryBufferLen != sizeof(PARAM_MTK_WIFI_TEST_STRUCT_T)) { + DBGLOG(REQ, ERROR, "Invalid data. QueryBufferLen: %u.\n", + u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prRfATInfo = (P_PARAM_MTK_WIFI_TEST_STRUCT_T) pvQueryBuffer; + rStatus = rftestQueryATInfo(prAdapter, + prRfATInfo->u4FuncIndex, prRfATInfo->u4FuncData, pvQueryBuffer, u4QueryBufferLen); + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set RF test parameter +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +* \return WLAN_STATUS_ADAPTER_NOT_READY +* \return WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidRftestSetAutoTest(IN P_ADAPTER_T prAdapter, + OUT PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_MTK_WIFI_TEST_STRUCT_T prRfATInfo; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidRftestSetAutoTest"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_MTK_WIFI_TEST_STRUCT_T); + + if (u4SetBufferLen != sizeof(PARAM_MTK_WIFI_TEST_STRUCT_T)) { + DBGLOG(REQ, ERROR, "Invalid data. SetBufferLen: %u.\n", + u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prRfATInfo = (P_PARAM_MTK_WIFI_TEST_STRUCT_T) pvSetBuffer; + rStatus = rftestSetATInfo(prAdapter, prRfATInfo->u4FuncIndex, prRfATInfo->u4FuncData); + + return rStatus; +} + +/* RF test OID set handler */ +WLAN_STATUS rftestSetATInfo(IN P_ADAPTER_T prAdapter, UINT_32 u4FuncIndex, UINT_32 u4FuncData) +{ + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_CMD_TEST_CTRL_T pCmdTestCtrl; + UINT_8 ucCmdSeqNum; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_TEST_CTRL_T))); + + if (!prCmdInfo) { + DBGLOG(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 = g_fgIsOid; + prCmdInfo->ucCID = CMD_ID_TEST_CTRL; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = 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 = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + 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; + + if ((u4FuncIndex == RF_AT_FUNCID_COMMAND) && (u4FuncData == RF_AT_COMMAND_ICAP)) { + g_bIcapEnable = TRUE; + g_bCaptureDone = FALSE; + } + /* ICAP dump name Reset */ + if ((u4FuncIndex == RF_AT_FUNCID_COMMAND) && (u4FuncData == RF_AT_COMMAND_RESET_DUMP_NAME)) + g_u2DumpIndex = 0; + /* 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 if (u4FuncIndex == RF_AT_FUNCID_QUERY_ICAP_DUMP_FILE) { + /* driver implementation */ + prTestStatus = (P_EVENT_TEST_STATUS) pvQueryBuffer; + + prTestStatus->rATInfo.u4FuncData = g_u2DumpIndex; + u4QueryBufferLen = sizeof(EVENT_TEST_STATUS); + + return WLAN_STATUS_SUCCESS; + } + 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 = g_fgIsOid; + prCmdInfo->ucCID = CMD_ID_TEST_CTRL; + prCmdInfo->fgSetQuery = FALSE; + prCmdInfo->fgNeedResp = TRUE; + 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 = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + 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_CTRL, + 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->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->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 = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->u2Length = prCmdInfo->u2InfoBufLen - (UINT_16) OFFSET_OF(WIFI_CMD_T, u2Length); + prWifiCmd->u2PqId = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + 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->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + 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 = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + 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; + UINT_16 u2IeLength = 0; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + DEBUGFUNC("wlanoidSetWapiAssocInfo"); + DBGLOG(REQ, LOUD, "\r\n"); + + prAdapter->rWifiVar.rConnSettings.fgWapiMode = FALSE; + + if (u4SetBufferLen < 20 /* From EID to Group cipher */) + return WLAN_STATUS_INVALID_LENGTH; + + if (!wextSrchDesiredWAPIIE((PUINT_8) pvSetBuffer, u4SetBufferLen, (PUINT_8 *) &prWapiInfo)) + return WLAN_STATUS_INVALID_LENGTH; + + if (!prWapiInfo || prWapiInfo->ucLength < 18) + return WLAN_STATUS_INVALID_LENGTH; + + u2IeLength = prWapiInfo->ucLength + 2; + + /* 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, prWapiInfo, u2IeLength); + prAdapter->prGlueInfo->u2WapiAssocInfoIESz = u2IeLength; + DBGLOG(SEC, TRACE, "Assoc Info IE sz %u\n", u2IeLength); + + prAdapter->rWifiVar.rConnSettings.fgWapiMode = TRUE; + + 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; + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prBssInfo; + + 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; + + /* Todo:: WAPI AP mode !!!!! */ + prBssInfo = prAdapter->prAisBssInfo; + + prNewKey->ucKeyID = prNewKey->ucKeyID & BIT(0); + + /* 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->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_802_11_KEY); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = g_fgIsOid; + prCmdInfo->ucCID = CMD_ID_ADD_REMOVE_KEY; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = 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 = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + 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); + if ((prCmdKey->aucPeerAddr[0] & prCmdKey->aucPeerAddr[1] & prCmdKey->aucPeerAddr[2] & + prCmdKey->aucPeerAddr[3] & prCmdKey->aucPeerAddr[4] & prCmdKey->aucPeerAddr[5]) == 0xFF) { + prStaRec = cnmGetStaRecByAddress(prAdapter, prBssInfo->ucBssIndex, prBssInfo->aucBSSID); + ASSERT(prStaRec); /* AIS RSN Group key, addr is BC addr */ + kalMemCopy(prCmdKey->aucPeerAddr, prStaRec->aucMacAddr, MAC_ADDR_LEN); + } else { + prStaRec = cnmGetStaRecByAddress(prAdapter, prBssInfo->ucBssIndex, prCmdKey->aucPeerAddr); + } + + prCmdKey->ucBssIdx = prAdapter->prAisBssInfo->ucBssIndex; /* 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); + + if (prCmdKey->ucTxKey) { + if (prStaRec) { + if (prCmdKey->ucKeyType) { /* AIS RSN STA */ + prCmdKey->ucWlanIndex = prStaRec->ucWlanIndex; + prStaRec->fgTransmitKeyExist = TRUE; /* wait for CMD Done ? */ + } else { + ASSERT(FALSE); + } + } +#if 0 + if (fgAddTxBcKey || !prStaRec) { + + if ((prCmdKey->aucPeerAddr[0] & prCmdKey->aucPeerAddr[1] & prCmdKey-> + aucPeerAddr[2] & prCmdKey->aucPeerAddr[3] & prCmdKey->aucPeerAddr[4] & prCmdKey-> + aucPeerAddr[5]) == 0xFF) { + prCmdKey->ucWlanIndex = 255; /* AIS WEP Tx key */ + } else { /* Exist this case ? */ + ASSERT(FALSE); + /* prCmdKey->ucWlanIndex = */ + /* secPrivacySeekForBcEntry(prAdapter, */ + /* prBssInfo->ucBssIndex, */ + /* NETWORK_TYPE_AIS, */ + /* prCmdKey->aucPeerAddr, */ + /* prCmdKey->ucAlgorithmId, */ + /* prCmdKey->ucKeyId, */ + } + + prBssInfo->fgBcDefaultKeyExist = TRUE; + prBssInfo->ucBMCWlanIndex = prCmdKey->ucWlanIndex; /* Saved for AIS WEP */ + prBssInfo->ucTxBcDefaultIdx = prCmdKey->ucKeyId; + } +#endif + } else { + /* Including IBSS RSN Rx BC key ? */ + if ((prCmdKey->aucPeerAddr[0] & prCmdKey->aucPeerAddr[1] & + prCmdKey->aucPeerAddr[2] & prCmdKey->aucPeerAddr[3] & + prCmdKey->aucPeerAddr[4] & prCmdKey->aucPeerAddr[5]) == 0xFF) { + prCmdKey->ucWlanIndex = WTBL_RESERVED_ENTRY; /* AIS WEP, should not have this case!! */ + } else { + if (prStaRec) { /* AIS RSN Group key but addr is BSSID */ + /* ASSERT(prStaRec->ucBMCWlanIndex < WTBL_SIZE) */ + prCmdKey->ucWlanIndex = + secPrivacySeekForBcEntry(prAdapter, prStaRec->ucBssIndex, + prStaRec->aucMacAddr, + prStaRec->ucIndex, + prCmdKey->ucAlgorithmId, prCmdKey->ucKeyId); + prStaRec->ucWlanIndex = prCmdKey->ucWlanIndex; + } else { /* Exist this case ? */ + ASSERT(FALSE); + /* prCmdKey->ucWlanIndex = */ + /* secPrivacySeekForBcEntry(prAdapter, */ + /* prBssInfo->ucBssIndex, */ + /* NETWORK_TYPE_AIS, */ + /* prCmdKey->aucPeerAddr, */ + /* prCmdKey->ucAlgorithmId, */ + /* prCmdKey->ucKeyId, */ + } + } + } + + /* 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 %u\n", u4SetBufferLen); + + return WLAN_STATUS_SUCCESS; + +} +#endif + +#if CFG_ENABLE_WAKEUP_ON_LAN +WLAN_STATUS +wlanoidSetAddWakeupPattern(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_PM_PACKET_PATTERN prPacketPattern; + + DEBUGFUNC("wlanoidSetAddWakeupPattern"); + DBGLOG(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_STRUCT_T prWmmPsTestInfo; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + CMD_SET_WMM_PS_TEST_STRUCT_T rSetWmmPsTestParam; + UINT_16 u2CmdBufLen; + P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo; + P_BSS_INFO_T prBssInfo; + + DEBUGFUNC("wlanoidSetWiFiWmmPsTest"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T); + + prWmmPsTestInfo = (P_PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T) pvSetBuffer; + + rSetWmmPsTestParam.ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + rSetWmmPsTestParam.bmfgApsdEnAc = prWmmPsTestInfo->bmfgApsdEnAc; + rSetWmmPsTestParam.ucIsEnterPsAtOnce = prWmmPsTestInfo->ucIsEnterPsAtOnce; + rSetWmmPsTestParam.ucIsDisableUcTrigger = prWmmPsTestInfo->ucIsDisableUcTrigger; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, rSetWmmPsTestParam.ucBssIndex); + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + prPmProfSetupInfo->ucBmpDeliveryAC = (rSetWmmPsTestParam.bmfgApsdEnAc >> 4) & BITS(0, 3); + prPmProfSetupInfo->ucBmpTriggerAC = rSetWmmPsTestParam.bmfgApsdEnAc & BITS(0, 3); + + u2CmdBufLen = sizeof(CMD_SET_WMM_PS_TEST_STRUCT_T); + +#if 0 + /* it will apply the disable trig or not immediately */ + if (prPmInfo->ucWmmPsDisableUcPoll && prPmInfo->ucWmmPsConnWithTrig) + NIC_PM_WMM_PS_DISABLE_UC_TRIG(prAdapter, TRUE); + else + NIC_PM_WMM_PS_DISABLE_UC_TRIG(prAdapter, FALSE); +#endif + + rStatus = wlanSendSetQueryCmd(prAdapter, CMD_ID_SET_WMM_PS_TEST_PARMS, + TRUE, FALSE, g_fgIsOid, + nicCmdEventSetCommon,/* TODO? */ + nicCmdTimeoutCommon, u2CmdBufLen, + (PUINT_8)(&rSetWmmPsTestParam), NULL, 0); + + return rStatus; +} /* wlanoidSetWiFiWmmPsTest */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to configure enable/disable TX A-MPDU feature. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetTxAmpdu(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + CMD_TX_AMPDU_T rTxAmpdu; + UINT_16 u2CmdBufLen; + PBOOLEAN pfgEnable; + + DEBUGFUNC("wlanoidSetTxAmpdu"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(BOOLEAN); + + pfgEnable = (PBOOLEAN) pvSetBuffer; + + rTxAmpdu.fgEnable = *pfgEnable; + + u2CmdBufLen = sizeof(CMD_TX_AMPDU_T); + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_TX_AMPDU, + TRUE, FALSE, TRUE, NULL, NULL, u2CmdBufLen, (PUINT_8) &rTxAmpdu, NULL, 0); + + return rStatus; +} /* wlanoidSetTxAmpdu */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to configure reject/accept ADDBA Request. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAddbaReject(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + CMD_ADDBA_REJECT_T rAddbaReject; + UINT_16 u2CmdBufLen; + PBOOLEAN pfgEnable; + + DEBUGFUNC("wlanoidSetAddbaReject"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(BOOLEAN); + + pfgEnable = (PBOOLEAN) pvSetBuffer; + + rAddbaReject.fgEnable = *pfgEnable; + + u2CmdBufLen = sizeof(CMD_ADDBA_REJECT_T); + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_ADDBA_REJECT, + TRUE, FALSE, TRUE, NULL, NULL, u2CmdBufLen, (PUINT_8) &rAddbaReject, NULL, 0); + + return rStatus; +} /* wlanoidSetAddbaReject */ + +#if CFG_SLT_SUPPORT + +WLAN_STATUS +wlanoidQuerySLTStatus(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_PARAM_MTK_SLT_TEST_STRUCT_T prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUCT_T) NULL; + P_SLT_INFO_T prSltInfo = (P_SLT_INFO_T) NULL; + + DEBUGFUNC("wlanoidQuerySLTStatus"); + DBGLOG(REQ, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(PARAM_MTK_SLT_TEST_STRUCT_T); + + if (u4QueryBufferLen < sizeof(PARAM_MTK_SLT_TEST_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvQueryBuffer); + + prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUCT_T) pvQueryBuffer; + + prSltInfo = &(prAdapter->rWifiVar.rSltInfo); + + switch (prMtkSltInfo->rSltFuncIdx) { + case ENUM_MTK_SLT_FUNC_LP_SET: + { + P_PARAM_MTK_SLT_LP_TEST_STRUCT_T prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUCT_T) NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_LP_TEST_STRUCT_T)); + + prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUCT_T) &prMtkSltInfo->unFuncInfoContent; + + prLpSetting->u4BcnRcvNum = prSltInfo->u4BeaconReceiveCnt; + } + break; + default: + /* TBD... */ + break; + } + + return rWlanStatus; +} /* wlanoidQuerySLTStatus */ + +WLAN_STATUS +wlanoidUpdateSLTMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_PARAM_MTK_SLT_TEST_STRUCT_T prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUCT_T) NULL; + P_SLT_INFO_T prSltInfo = (P_SLT_INFO_T) NULL; + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; + + /* 1. Action: Update or Initial Set + * 2. Role. + * 3. Target MAC address. + * 4. RF BW & Rate Settings + */ + + DEBUGFUNC("wlanoidUpdateSLTMode"); + DBGLOG(REQ, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_MTK_SLT_TEST_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_MTK_SLT_TEST_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUCT_T) pvSetBuffer; + + prSltInfo = &(prAdapter->rWifiVar.rSltInfo); + prBssInfo = prAdapter->prAisBssInfo; + + switch (prMtkSltInfo->rSltFuncIdx) { + case ENUM_MTK_SLT_FUNC_INITIAL: /* Initialize */ + { + P_PARAM_MTK_SLT_INITIAL_STRUCT_T prMtkSltInit = (P_PARAM_MTK_SLT_INITIAL_STRUCT_T) NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_INITIAL_STRUCT_T)); + + prMtkSltInit = (P_PARAM_MTK_SLT_INITIAL_STRUCT_T) &prMtkSltInfo->unFuncInfoContent; + + if (prSltInfo->prPseudoStaRec != NULL) { + /* The driver has been initialized. */ + prSltInfo->prPseudoStaRec = NULL; + } + + prSltInfo->prPseudoBssDesc = scanSearchExistingBssDesc(prAdapter, + BSS_TYPE_IBSS, + prMtkSltInit->aucTargetMacAddr, + prMtkSltInit->aucTargetMacAddr); + + prSltInfo->u2SiteID = prMtkSltInit->u2SiteID; + + /* Bandwidth 2.4G: Channel 1~14 + * Bandwidth 5G: *36, 40, 44, 48, 52, 56, 60, 64, + * *100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, + * 149, 153, *157, 161, + * 184, 188, 192, 196, 200, 204, 208, 212, *216 + */ + prSltInfo->ucChannel2G4 = 1 + (prSltInfo->u2SiteID % 4) * 5; + + switch (prSltInfo->ucChannel2G4) { + case 1: + prSltInfo->ucChannel5G = 36; + break; + case 6: + prSltInfo->ucChannel5G = 52; + break; + case 11: + prSltInfo->ucChannel5G = 104; + break; + case 16: + prSltInfo->ucChannel2G4 = 14; + prSltInfo->ucChannel5G = 161; + break; + default: + ASSERT(FALSE); + } + + if (prSltInfo->prPseudoBssDesc == NULL) { + do { + prSltInfo->prPseudoBssDesc = scanAllocateBssDesc(prAdapter); + + if (prSltInfo->prPseudoBssDesc == NULL) { + rWlanStatus = WLAN_STATUS_FAILURE; + break; + } + prBssDesc = prSltInfo->prPseudoBssDesc; + + } while (FALSE); + } else { + prBssDesc = prSltInfo->prPseudoBssDesc; + } + + if (prBssDesc) { + prBssDesc->eBSSType = BSS_TYPE_IBSS; + + COPY_MAC_ADDR(prBssDesc->aucSrcAddr, prMtkSltInit->aucTargetMacAddr); + COPY_MAC_ADDR(prBssDesc->aucBSSID, prBssInfo->aucOwnMacAddr); + + prBssDesc->u2BeaconInterval = 100; + prBssDesc->u2ATIMWindow = 0; + prBssDesc->ucDTIMPeriod = 1; + + prBssDesc->u2IELength = 0; + + prBssDesc->fgIsERPPresent = TRUE; + prBssDesc->fgIsHTPresent = TRUE; + + prBssDesc->u2OperationalRateSet = BIT(RATE_36M_INDEX); + prBssDesc->u2BSSBasicRateSet = BIT(RATE_36M_INDEX); + prBssDesc->fgIsUnknownBssBasicRate = FALSE; + + prBssDesc->fgIsLargerTSF = TRUE; + + prBssDesc->eBand = BAND_2G4; + + prBssDesc->ucChannelNum = prSltInfo->ucChannel2G4; + + prBssDesc->ucPhyTypeSet = PHY_TYPE_SET_802_11ABGN; + + GET_CURRENT_SYSTIME(&prBssDesc->rUpdateTime); + } + } + break; + case ENUM_MTK_SLT_FUNC_RATE_SET: /* Update RF Settings. */ + if (prSltInfo->prPseudoStaRec == NULL) { + rWlanStatus = WLAN_STATUS_FAILURE; + } else { + P_PARAM_MTK_SLT_TR_TEST_STRUCT_T prTRSetting = (P_PARAM_MTK_SLT_TR_TEST_STRUCT_T) NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_TR_TEST_STRUCT_T)); + + prStaRec = prSltInfo->prPseudoStaRec; + prTRSetting = (P_PARAM_MTK_SLT_TR_TEST_STRUCT_T) &prMtkSltInfo->unFuncInfoContent; + + if (prTRSetting->rNetworkType == PARAM_NETWORK_TYPE_OFDM5) { + prBssInfo->eBand = BAND_5G; + prBssInfo->ucPrimaryChannel = prSltInfo->ucChannel5G; + } + if (prTRSetting->rNetworkType == PARAM_NETWORK_TYPE_OFDM24) { + prBssInfo->eBand = BAND_2G4; + prBssInfo->ucPrimaryChannel = prSltInfo->ucChannel2G4; + } + + if ((prTRSetting->u4FixedRate & FIXED_BW_DL40) != 0) { + /* RF 40 */ + /* It would controls RFBW capability in WTBL. */ + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; + /* This controls RF BW, RF BW would be 40 only if + * 1. PHY_TYPE_BIT_HT is TRUE. + * 2. SCO is SCA/SCB. + */ + prStaRec->ucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + + /* U20/L20 Control. */ + switch (prTRSetting->u4FixedRate & 0xC000) { + case FIXED_EXT_CHNL_U20: + prBssInfo->eBssSCO = CHNL_EXT_SCB; /* +2 */ + if (prTRSetting->rNetworkType == PARAM_NETWORK_TYPE_OFDM5) { + prBssInfo->ucPrimaryChannel += 2; + } else { + /* For channel 1, testing L20 at channel 8. AOSP */ + SetTestChannel(&prBssInfo->ucPrimaryChannel); + } + break; + case FIXED_EXT_CHNL_L20: + default: /* 40M */ + prBssInfo->eBssSCO = CHNL_EXT_SCA; /* -2 */ + if (prTRSetting->rNetworkType == PARAM_NETWORK_TYPE_OFDM5) { + prBssInfo->ucPrimaryChannel -= 2; + } else { + /* For channel 11 / 14. testing U20 at channel 3. AOSP */ + SetTestChannel(&prBssInfo->ucPrimaryChannel); + } + 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_SW_INDEX); + break; + case RATE_OFDM_48M: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_48M_SW_INDEX); + break; + case RATE_OFDM_36M: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_36M_SW_INDEX); + break; + case RATE_OFDM_24M: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_24M_SW_INDEX); + break; + case RATE_OFDM_6M: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_6M_SW_INDEX); + break; + case RATE_CCK_11M_LONG: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_11M_SW_INDEX); + break; + case RATE_CCK_1M_LONG: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_1M_SW_INDEX); + break; + case RATE_GF_MCS_0: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_HT_PHY_SW_INDEX); + prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + break; + case RATE_MM_MCS_7: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_HT_PHY_SW_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_SW_INDEX); + prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + break; + default: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_36M_SW_INDEX); + break; + } + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + } + break; + case ENUM_MTK_SLT_FUNC_LP_SET: /* Reset LP Test Result. */ + { + P_PARAM_MTK_SLT_LP_TEST_STRUCT_T prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUCT_T) NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_LP_TEST_STRUCT_T)); + + prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUCT_T) &prMtkSltInfo->unFuncInfoContent; + + if (prSltInfo->prPseudoBssDesc == NULL) { + /* Please initial SLT Mode first. */ + break; + } + prBssDesc = prSltInfo->prPseudoBssDesc; + + switch (prLpSetting->rLpTestMode) { + case ENUM_MTK_LP_TEST_NORMAL: + /* In normal mode, we would use target MAC address to be the BSSID. */ + COPY_MAC_ADDR(prBssDesc->aucBSSID, prBssInfo->aucOwnMacAddr); + prSltInfo->fgIsDUT = FALSE; + break; + case ENUM_MTK_LP_TEST_GOLDEN_SAMPLE: + /* 1. Lower AIFS of BCN queue. + * 2. Fixed Random Number tobe 0. + */ + prSltInfo->fgIsDUT = FALSE; + /* In LP test mode, we would use MAC address of Golden Sample to be the BSSID. */ + COPY_MAC_ADDR(prBssDesc->aucBSSID, prBssInfo->aucOwnMacAddr); + break; + case ENUM_MTK_LP_TEST_DUT: + /* 1. Enter Sleep Mode. + * 2. Fix random number a large value & enlarge AIFN of BCN queue. + */ + COPY_MAC_ADDR(prBssDesc->aucBSSID, prBssDesc->aucSrcAddr); + prSltInfo->u4BeaconReceiveCnt = 0; + prSltInfo->fgIsDUT = TRUE; + break; + } + + } + + break; + default: + break; + } + + return WLAN_STATUS_FAILURE; + + return rWlanStatus; +} /* wlanoidUpdateSLTMode */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query NVRAM value. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryNvramRead(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T prNvramRwInfo; + UINT_16 u2Data; + BOOLEAN fgStatus; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryNvramRead"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_NVRAM_RW_STRUCT_T); + + if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_NVRAM_RW_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + prNvramRwInfo = (P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T) pvQueryBuffer; + + if (prNvramRwInfo->ucEepromMethod == PARAM_EEPROM_READ_METHOD_READ) { + 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_STRUCT_T); + + return rStatus; +} /* wlanoidQueryNvramRead */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to write NVRAM value. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetNvramWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T prNvramRwInfo; + BOOLEAN fgStatus; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidSetNvramWrite"); + DBGLOG(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); + + if (regd_is_single_sku_en()) { + rlmDomainOidSetCountry(prAdapter, pvSetBuffer, u4SetBufferLen); + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_SUCCESS; + } + + ASSERT(u4SetBufferLen == 2); + + *pu4SetInfoLen = 2; + + pucCountry = pvSetBuffer; + + prAdapter->rWifiVar.rConnSettings.u2CountryCode = (((UINT_16) pucCountry[0]) << 8) | ((UINT_16) pucCountry[1]); + + /* Force to re-search country code in country domains */ + prAdapter->prDomainInfo = NULL; + rlmDomainSendCmd(prAdapter, TRUE); + + /* Update supported channel list in channel table based on current country domain */ + wlanUpdateChannelTable(prAdapter->prGlueInfo); + + return WLAN_STATUS_SUCCESS; +} + +#if 0 +WLAN_STATUS +wlanoidSetNoaParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T prNoaParam; + CMD_CUSTOM_NOA_PARAM_STRUCT_T rCmdNoaParam; + + DEBUGFUNC("wlanoidSetNoaParam"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_NOA_PARAM_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_NOA_PARAM_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prNoaParam = (P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T) pvSetBuffer; + + kalMemZero(&rCmdNoaParam, sizeof(CMD_CUSTOM_NOA_PARAM_STRUCT_T)); + rCmdNoaParam.u4NoaDurationMs = prNoaParam->u4NoaDurationMs; + rCmdNoaParam.u4NoaIntervalMs = prNoaParam->u4NoaIntervalMs; + rCmdNoaParam.u4NoaCount = prNoaParam->u4NoaCount; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_NOA_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_NOA_PARAM_STRUCT_T), + (PUINT_8) &rCmdNoaParam, pvSetBuffer, u4SetBufferLen); +} + +WLAN_STATUS +wlanoidSetOppPsParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T prOppPsParam; + CMD_CUSTOM_OPPPS_PARAM_STRUCT_T rCmdOppPsParam; + + DEBUGFUNC("wlanoidSetOppPsParam"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prOppPsParam = (P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T) pvSetBuffer; + + kalMemZero(&rCmdOppPsParam, sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T)); + rCmdOppPsParam.u4CTwindowMs = prOppPsParam->u4CTwindowMs; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_OPPPS_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T), + (PUINT_8) &rCmdOppPsParam, pvSetBuffer, u4SetBufferLen); +} + +WLAN_STATUS +wlanoidSetUApsdParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T prUapsdParam; + CMD_CUSTOM_UAPSD_PARAM_STRUCT_T rCmdUapsdParam; + P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo; + P_BSS_INFO_T prBssInfo; + + DEBUGFUNC("wlanoidSetUApsdParam"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + + prUapsdParam = (P_PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T) pvSetBuffer; + + kalMemZero(&rCmdUapsdParam, sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T)); + rCmdUapsdParam.fgEnAPSD = prUapsdParam->fgEnAPSD; + prAdapter->rWifiVar.fgSupportUAPSD = prUapsdParam->fgEnAPSD; + + rCmdUapsdParam.fgEnAPSD_AcBe = prUapsdParam->fgEnAPSD_AcBe; + rCmdUapsdParam.fgEnAPSD_AcBk = prUapsdParam->fgEnAPSD_AcBk; + rCmdUapsdParam.fgEnAPSD_AcVo = prUapsdParam->fgEnAPSD_AcVo; + rCmdUapsdParam.fgEnAPSD_AcVi = prUapsdParam->fgEnAPSD_AcVi; + prPmProfSetupInfo->ucBmpDeliveryAC = + ((prUapsdParam->fgEnAPSD_AcBe << 0) | + (prUapsdParam->fgEnAPSD_AcBk << 1) | + (prUapsdParam->fgEnAPSD_AcVi << 2) | (prUapsdParam->fgEnAPSD_AcVo << 3)); + prPmProfSetupInfo->ucBmpTriggerAC = + ((prUapsdParam->fgEnAPSD_AcBe << 0) | + (prUapsdParam->fgEnAPSD_AcBk << 1) | + (prUapsdParam->fgEnAPSD_AcVi << 2) | (prUapsdParam->fgEnAPSD_AcVo << 3)); + + rCmdUapsdParam.ucMaxSpLen = prUapsdParam->ucMaxSpLen; + prPmProfSetupInfo->ucUapsdSp = prUapsdParam->ucMaxSpLen; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_UAPSD_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T), + (PUINT_8) &rCmdUapsdParam, pvSetBuffer, u4SetBufferLen); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set BT profile or BT information and the +* driver will set the built-in PTA configuration into chip. +* +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBT(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + + P_PTA_IPC_T prPtaIpc; + + DEBUGFUNC("wlanoidSetBT.\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PTA_IPC_T); + if (u4SetBufferLen != sizeof(PTA_IPC_T)) { + /* WARNLOG(("Invalid length %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 + DBGLOG(INIT, INFO, "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]); + + DBGLOG(INIT, INFO, + "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 %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvQueryBuffer); +/* prPtaIpc = (P_PTA_IPC_T)pvQueryBuffer; */ +/* prPtaIpc->ucCmd = BT_CMD_PROFILE; */ +/* prPtaIpc->ucLen = sizeof(prPtaIpc->u); */ +/* nicPtaGetProfile(prAdapter, (PUINT_8)&prPtaIpc->u, &u4QueryBuffLen); */ + + return WLAN_STATUS_SUCCESS; +} + +#if 0 +WLAN_STATUS +wlanoidQueryBtSingleAntenna(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PTA_INFO_T prPtaInfo; + PUINT_32 pu4SingleAntenna; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(UINT_32); + + /* Check for query buffer length */ + if (u4QueryBufferLen != sizeof(UINT_32)) { + DBGLOG(REQ, WARN, "Invalid length %lu\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvQueryBuffer); + + prPtaInfo = &prAdapter->rPtaInfo; + pu4SingleAntenna = (PUINT_32) pvQueryBuffer; + + if (prPtaInfo->fgSingleAntenna) { + /* DBGLOG(INIT, INFO, (KERN_WARNING DRV_NAME"Q Single Ant = 1\r\n")); */ + *pu4SingleAntenna = 1; + } else { + /* DBGLOG(INIT, INFO, (KERN_WARNING DRV_NAME"Q Single Ant = 0\r\n")); */ + *pu4SingleAntenna = 0; + } + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidSetBtSingleAntenna(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + + PUINT_32 pu4SingleAntenna; + UINT_32 u4SingleAntenna; + P_PTA_INFO_T prPtaInfo; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + prPtaInfo = &prAdapter->rPtaInfo; + + *pu4SetInfoLen = sizeof(UINT_32); + if (u4SetBufferLen != sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + if (IS_ARB_IN_RFTEST_STATE(prAdapter)) + return WLAN_STATUS_SUCCESS; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(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) { + /* DBGLOG(INIT, INFO, (KERN_WARNING DRV_NAME"Set Single Ant = 0\r\n")); */ + prPtaInfo->fgSingleAntenna = FALSE; + } else { + /* DBGLOG(INIT, INFO, (KERN_WARNING DRV_NAME"Set Single Ant = 1\r\n")); */ + prPtaInfo->fgSingleAntenna = TRUE; + } + ptaFsmRunEventSetConfig(prAdapter, &prPtaInfo->rPtaParam); + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS +WLAN_STATUS +wlanoidQueryPta(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PTA_INFO_T prPtaInfo; + PUINT_32 pu4Pta; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(UINT_32); + + /* Check for query buffer length */ + if (u4QueryBufferLen != sizeof(UINT_32)) { + DBGLOG(REQ, WARN, "Invalid length %lu\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvQueryBuffer); + + prPtaInfo = &prAdapter->rPtaInfo; + pu4Pta = (PUINT_32) pvQueryBuffer; + + if (prPtaInfo->fgEnabled) { + /* DBGLOG(INIT, INFO, (KERN_WARNING DRV_NAME"PTA = 1\r\n")); */ + *pu4Pta = 1; + } else { + /* DBGLOG(INIT, INFO, (KERN_WARNING DRV_NAME"PTA = 0\r\n")); */ + *pu4Pta = 0; + } + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidSetPta(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PUINT_32 pu4PtaCtrl; + UINT_32 u4PtaCtrl; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(UINT_32); + if (u4SetBufferLen != sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + if (IS_ARB_IN_RFTEST_STATE(prAdapter)) + return WLAN_STATUS_SUCCESS; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(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) { + /* DBGLOG(INIT, INFO, (KERN_WARNING DRV_NAME"Set Pta= 0\r\n")); */ + nicPtaSetFunc(prAdapter, FALSE); + } else { + /* DBGLOG(INIT, INFO, (KERN_WARNING DRV_NAME"Set Pta= 1\r\n")); */ + nicPtaSetFunc(prAdapter, TRUE); + } + + return WLAN_STATUS_SUCCESS; +} +#endif + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set Tx power profile. +* +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetTxPower(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_SET_TXPWR_CTRL_T pTxPwr = (P_SET_TXPWR_CTRL_T) pvSetBuffer; + P_SET_TXPWR_CTRL_T prCmd; + UINT_32 i; + WLAN_STATUS rStatus; + + DEBUGFUNC("wlanoidSetTxPower"); + DBGLOG(REQ, LOUD, "\r\n"); + + prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(SET_TXPWR_CTRL_T)); + kalMemZero(prCmd, sizeof(SET_TXPWR_CTRL_T)); + prCmd->c2GLegacyStaPwrOffset = pTxPwr->c2GLegacyStaPwrOffset; + prCmd->c2GHotspotPwrOffset = pTxPwr->c2GHotspotPwrOffset; + prCmd->c2GP2pPwrOffset = pTxPwr->c2GP2pPwrOffset; + prCmd->c2GBowPwrOffset = pTxPwr->c2GBowPwrOffset; + prCmd->c5GLegacyStaPwrOffset = pTxPwr->c5GLegacyStaPwrOffset; + prCmd->c5GHotspotPwrOffset = pTxPwr->c5GHotspotPwrOffset; + prCmd->c5GP2pPwrOffset = pTxPwr->c5GP2pPwrOffset; + prCmd->c5GBowPwrOffset = pTxPwr->c5GBowPwrOffset; + prCmd->ucConcurrencePolicy = pTxPwr->ucConcurrencePolicy; + for (i = 0; i < 14; i++) + prCmd->acTxPwrLimit2G[i] = pTxPwr->acTxPwrLimit2G[i]; + + for (i = 0; i < 4; i++) + prCmd->acTxPwrLimit5G[i] = pTxPwr->acTxPwrLimit5G[i]; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + +#if 0 + DBGLOG(INIT, INFO, "c2GLegacyStaPwrOffset=%d\n", pTxPwr->c2GLegacyStaPwrOffset); + DBGLOG(INIT, INFO, "c2GHotspotPwrOffset=%d\n", pTxPwr->c2GHotspotPwrOffset); + DBGLOG(INIT, INFO, "c2GP2pPwrOffset=%d\n", pTxPwr->c2GP2pPwrOffset); + DBGLOG(INIT, INFO, "c2GBowPwrOffset=%d\n", pTxPwr->c2GBowPwrOffset); + DBGLOG(INIT, INFO, "c5GLegacyStaPwrOffset=%d\n", pTxPwr->c5GLegacyStaPwrOffset); + DBGLOG(INIT, INFO, "c5GHotspotPwrOffset=%d\n", pTxPwr->c5GHotspotPwrOffset); + DBGLOG(INIT, INFO, "c5GP2pPwrOffset=%d\n", pTxPwr->c5GP2pPwrOffset); + DBGLOG(INIT, INFO, "c5GBowPwrOffset=%d\n", pTxPwr->c5GBowPwrOffset); + DBGLOG(INIT, INFO, "ucConcurrencePolicy=%d\n", pTxPwr->ucConcurrencePolicy); + + for (i = 0; i < 14; i++) + DBGLOG(INIT, INFO, "acTxPwrLimit2G[%d]=%d\n", i, pTxPwr->acTxPwrLimit2G[i]); + + for (i = 0; i < 4; i++) + DBGLOG(INIT, INFO, "acTxPwrLimit5G[%d]=%d\n", i, pTxPwr->acTxPwrLimit5G[i]); +#endif + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_TXPWR_CTRL, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + g_fgIsOid, /* fgIsOid */ + nicCmdEventSetCommon, nicOidCmdTimeoutCommon, + sizeof(SET_TXPWR_CTRL_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmd, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + /* ASSERT(rStatus == WLAN_STATUS_PENDING); */ + cnmMemFree(prAdapter, prCmd); + + return rStatus; + +} + +WLAN_STATUS wlanSendMemDumpCmd(IN P_ADAPTER_T prAdapter, IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen) +{ + P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T prMemDumpInfo; + P_CMD_DUMP_MEM prCmdDumpMem; + CMD_DUMP_MEM rCmdDumpMem; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4MemSize = PARAM_MEM_DUMP_MAX_SIZE; + + UINT_32 u4RemainLeng = 0; + UINT_32 u4CurAddr = 0; + UINT_8 ucFragNum = 0; + + prCmdDumpMem = &rCmdDumpMem; + prMemDumpInfo = (P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T) pvQueryBuffer; + + u4RemainLeng = prMemDumpInfo->u4RemainLength; + u4CurAddr = prMemDumpInfo->u4Address + prMemDumpInfo->u4Length; + ucFragNum = prMemDumpInfo->ucFragNum + 1; + + /* Query. If request length is larger than max length, do it as ping pong. + * Send a command and wait for a event. Send next command while the event is received. + * + */ + do { + UINT_32 u4CurLeng = 0; + + if (u4RemainLeng > u4MemSize) { + u4CurLeng = u4MemSize; + u4RemainLeng -= u4MemSize; + } else { + u4CurLeng = u4RemainLeng; + u4RemainLeng = 0; + } + + prCmdDumpMem->u4Address = u4CurAddr; + prCmdDumpMem->u4Length = u4CurLeng; + prCmdDumpMem->u4RemainLength = u4RemainLeng; + prCmdDumpMem->ucFragNum = ucFragNum; +#if CFG_SUPPORT_QA_TOOL + prCmdDumpMem->u4IcapContent = prMemDumpInfo->u4IcapContent; +#endif /* CFG_SUPPORT_QA_TOOL */ + + DBGLOG(REQ, TRACE, "[%d] 0x%X, len %u, remain len %u\n", + ucFragNum, prCmdDumpMem->u4Address, prCmdDumpMem->u4Length, prCmdDumpMem->u4RemainLength); + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_DUMP_MEM, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryMemDump, + nicOidCmdTimeoutCommon, + sizeof(CMD_DUMP_MEM), + (PUINT_8) prCmdDumpMem, pvQueryBuffer, u4QueryBufferLen); + + } while (FALSE); + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to dump memory. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMemDump(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T prMemDumpInfo; + + DEBUGFUNC("wlanoidQueryMemDump"); + DBGLOG(INIT, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(UINT_32); + + prMemDumpInfo = (P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T) pvQueryBuffer; + DBGLOG(REQ, TRACE, "Dump 0x%X, len %u\n", + prMemDumpInfo->u4Address, prMemDumpInfo->u4Length); + + prMemDumpInfo->u4RemainLength = prMemDumpInfo->u4Length; + prMemDumpInfo->u4Length = 0; + prMemDumpInfo->ucFragNum = 0; + + return wlanSendMemDumpCmd(prAdapter, pvQueryBuffer, u4QueryBufferLen); + +} /* end of wlanoidQueryMcrRead() */ + +#if CFG_ENABLE_WIFI_DIRECT +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to set the p2p mode. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2pMode(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS status = WLAN_STATUS_SUCCESS; + P_PARAM_CUSTOM_P2P_SET_STRUCT_T prSetP2P = (P_PARAM_CUSTOM_P2P_SET_STRUCT_T) NULL; + /* P_MSG_P2P_NETDEV_REGISTER_T prP2pNetdevRegMsg = (P_MSG_P2P_NETDEV_REGISTER_T)NULL; */ + DEBUGFUNC("wlanoidSetP2pMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_P2P_SET_STRUCT_T); + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_P2P_SET_STRUCT_T)) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prSetP2P = (P_PARAM_CUSTOM_P2P_SET_STRUCT_T) pvSetBuffer; + + DBGLOG(P2P, INFO, "Set P2P enable[%d] mode[%d]\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 + * enable = 1, mode = 2 => init dual Soft AP network + * enable = 1, mode = 3 => init AP+P2P network + */ + + + DBGLOG(P2P, INFO, "P2P Compile as (%d)p2p-like interface\n", KAL_P2P_NUM); + + if (prSetP2P->u4Mode >= RUNNING_P2P_MODE_NUM) { + DBGLOG(P2P, ERROR, "P2P interface mode(%d) is wrong\n", prSetP2P->u4Mode); + ASSERT(0); + } + + if (prSetP2P->u4Enable) { + p2pSetMode(prSetP2P->u4Mode); + + if (p2pLaunch(prAdapter->prGlueInfo)) { + /* ToDo:: ASSERT */ + ASSERT(prAdapter->fgIsP2PRegistered); + } else { + status = WLAN_STATUS_FAILURE; + } + + } 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 + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the GTK rekey data +* +* \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 +wlanoidSetGtkRekeyData(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; + UINT_8 ucCmdSeqNum; + P_BSS_INFO_T prBssInfo; + + DBGLOG(REQ, INFO, "wlanoidSetGtkRekeyData\n"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(RSN, WARN, "Fail in set rekey! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + prBssInfo = prAdapter->prAisBssInfo; + + *pu4SetInfoLen = u4SetBufferLen; + + prGlueInfo = prAdapter->prGlueInfo; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(PARAM_GTK_REKEY_DATA))); + + 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 PARAM_GTK_REKEY_DATA cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(PARAM_GTK_REKEY_DATA); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = g_fgIsOid; + prCmdInfo->ucCID = CMD_ID_SET_GTK_REKEY_DATA; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = 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 = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + kalMemCopy(prWifiCmd->aucBuffer, (PUINT_8) pvSetBuffer, u4SetBufferLen); + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; + +} /* wlanoidSetGtkRekeyData */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request starting of schedule scan +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetStartSchedScan(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_SCHED_SCAN_REQUEST prSchedScanRequest; + + DEBUGFUNC("wlanoidSetStartSchedScan()"); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, + "Fail in set scheduled scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pu4SetInfoLen); + *pu4SetInfoLen = 0; + + if (u4SetBufferLen != sizeof(PARAM_SCHED_SCAN_REQUEST)) + return WLAN_STATUS_INVALID_LENGTH; + else if (pvSetBuffer == NULL) + return WLAN_STATUS_INVALID_DATA; + else if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED + && prAdapter->fgEnOnlineScan == FALSE) + return WLAN_STATUS_FAILURE; + + if (prAdapter->fgIsRadioOff) { + DBGLOG(REQ, WARN, "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + prSchedScanRequest = (P_PARAM_SCHED_SCAN_REQUEST) pvSetBuffer; + + if (scnFsmSchedScanRequest(prAdapter, + (UINT_8) (prSchedScanRequest->u4SsidNum), + prSchedScanRequest->arSsid, + prSchedScanRequest->u4IELength, + prSchedScanRequest->pucIE, prSchedScanRequest->u2ScanInterval) == TRUE) + return WLAN_STATUS_PENDING; + else + return WLAN_STATUS_FAILURE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request termination of schedule scan +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetStopSchedScan(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + ASSERT(prAdapter); + + /* ask SCN module to stop scan request */ + if (scnFsmSchedScanStopRequest(prAdapter) == TRUE) + return WLAN_STATUS_PENDING; + else + return WLAN_STATUS_FAILURE; +} + +#if CFG_M0VE_BA_TO_DRIVER +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to reset BA scoreboard. +* +* +* \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 wlanoidResetBAScoreboard(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen) +{ + WLAN_STATUS rStatus; + + DEBUGFUNC("wlanoidResetBAScoreboard"); + DBGLOG(REQ, WARN, "[Puff]wlanoidResetBAScoreboard\n"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_RESET_BA_SCOREBOARD, /* 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; + +} + +#endif + +#if CFG_SUPPORT_BATCH_SCAN + +#define CMD_WLS_BATCHING "WLS_BATCHING" + +#define BATCHING_SET "SET" +#define BATCHING_GET "GET" +#define BATCHING_STOP "STOP" + +#define PARAM_SCANFREQ "SCANFREQ" +#define PARAM_MSCAN "MSCAN" +#define PARAM_BESTN "BESTN" +#define PARAM_CHANNEL "CHANNEL" +#define PARAM_RTT "RTT" + +WLAN_STATUS +batchSetCmd(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4WritenLen) +{ + P_CHANNEL_INFO_T prRfChannelInfo; + CMD_BATCH_REQ_T rCmdBatchReq; + + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + PCHAR head, p, p2; + UINT_32 tokens; + INT_32 scanfreq, mscan, bestn, rtt; + char *pcTemp; + /* CHAR c_scanfreq[4], c_mscan[4], c_bestn[4], c_rtt[4], c_channel[100]; */ + /* INT32 ch_type; */ + UINT_32 u4Value = 0; + INT_32 i4Ret = 0; + + DBGLOG(SCN, TRACE, "[BATCH] command=%s, len=%u\n", + (char *)pvSetBuffer, u4SetBufferLen); + + if (!pu4WritenLen) + return -EINVAL; + *pu4WritenLen = 0; + + if (u4SetBufferLen < kalStrLen(CMD_WLS_BATCHING)) { + DBGLOG(SCN, TRACE, "[BATCH] invalid len %d\n", u4SetBufferLen); + return -EINVAL; + } + + head = pvSetBuffer + kalStrLen(CMD_WLS_BATCHING) + 1; + kalMemSet(&rCmdBatchReq, 0, sizeof(CMD_BATCH_REQ_T)); + + if (!kalStrnCmp(head, BATCHING_SET, kalStrLen(BATCHING_SET))) { + + DBGLOG(SCN, TRACE, "XXX Start Batch Scan XXX\n"); + + head += kalStrLen(BATCHING_SET) + 1; + + /* SCANFREQ, MSCAN, BESTN */ + tokens = sscanf(head, "SCANFREQ=%d MSCAN=%d BESTN=%d", + &scanfreq, &mscan, &bestn); + if (tokens != 3) { + DBGLOG(SCN, TRACE, + "[BATCH] Parse fail: tokens=%d, SCANFREQ=%d MSCAN=%d BESTN=%d\n", + tokens, scanfreq, mscan, bestn); + return -EINVAL; + } + /* RTT */ + p = kalStrStr(head, PARAM_RTT); + if (!p) { + DBGLOG(SCN, TRACE, "[BATCH] Parse RTT fail. head=%s\n", head); + return -EINVAL; + } + tokens = sscanf(p, "RTT=%d", &rtt); + if (tokens != 1) { + DBGLOG(SCN, TRACE, "[BATCH] Parse fail: tokens=%d, rtt=%d\n", tokens, rtt); + return -EINVAL; + } + /* CHANNEL */ + p = kalStrStr(head, PARAM_CHANNEL); + if (!p) { + DBGLOG(SCN, TRACE, "[BATCH] Parse CHANNEL fail(1)\n"); + return -EINVAL; + } + head = p; + p = kalStrChr(head, '>'); + if (!p) { + DBGLOG(SCN, TRACE, "[BATCH] Parse CHANNEL fail(2)\n"); + return -EINVAL; + } + /* else { + *p = '.'; // remove '>' because sscanf can not parse <%s> + *} + */ + /*tokens = sscanf(head, "CHANNEL=<%s", c_channel); + * if (tokens != 1) { + * DBGLOG(SCN, TRACE, "[BATCH] Parse fail: tokens=%d, CHANNEL=<%s>\n", + * tokens, c_channel); + * return -EINVAL; + * } + */ + rCmdBatchReq.ucChannelType = SCAN_CHANNEL_SPECIFIED; + rCmdBatchReq.ucChannelListNum = 0; + prRfChannelInfo = &rCmdBatchReq.arChannelList[0]; + p = head + kalStrLen(PARAM_CHANNEL) + 2; /* c_channel; */ + pcTemp = (char *)p; + while ((p2 = kalStrSep(&pcTemp, ",")) != NULL) { + if (p2 == NULL || *p2 == 0) + break; + if (*p2 == '\0') + continue; + if (*p2 == 'A') { + rCmdBatchReq.ucChannelType = + rCmdBatchReq.ucChannelType == + SCAN_CHANNEL_2G4 ? SCAN_CHANNEL_FULL : SCAN_CHANNEL_5G; + } else if (*p2 == 'B') { + rCmdBatchReq.ucChannelType = + rCmdBatchReq.ucChannelType == + SCAN_CHANNEL_5G ? SCAN_CHANNEL_FULL : SCAN_CHANNEL_2G4; + } else { + + /* Translate Freq from MHz to channel number. */ + /* prRfChannelInfo->ucChannelNum = kalStrtol(p2, NULL, 0); */ + i4Ret = kalkStrtou32(p2, 0, &u4Value); + if (i4Ret) + DBGLOG(SCN, TRACE, "parse ucChannelNum error i4Ret=%d\n", i4Ret); + prRfChannelInfo->ucChannelNum = (UINT_8) u4Value; + DBGLOG(SCN, TRACE, "Scanning Channel:%d, freq: %d\n", + prRfChannelInfo->ucChannelNum, + nicChannelNum2Freq(prRfChannelInfo->ucChannelNum)); + prRfChannelInfo->ucBand = prRfChannelInfo->ucChannelNum < 15 ? BAND_2G4 : BAND_5G; + + rCmdBatchReq.ucChannelListNum++; + if (rCmdBatchReq.ucChannelListNum >= 32) + break; + prRfChannelInfo++; + } + } + + /* set channel for test */ +#if 0 + rCmdBatchReq.ucChannelType = 4; /* SCAN_CHANNEL_SPECIFIED; */ + rCmdBatchReq.ucChannelListNum = 0; + prRfChannelInfo = &rCmdBatchReq.arChannelList[0]; + for (i = 1; i <= 14; i++) { + + /* filter out some */ + if (i == 1 || i == 5 || i == 11) + continue; + + /* Translate Freq from MHz to channel number. */ + prRfChannelInfo->ucChannelNum = i; + DBGLOG(SCN, TRACE, "Scanning Channel:%d, freq: %d\n", + prRfChannelInfo->ucChannelNum, nicChannelNum2Freq(prRfChannelInfo->ucChannelNum)); + prRfChannelInfo->ucBand = BAND_2G4; + + rCmdBatchReq.ucChannelListNum++; + prRfChannelInfo++; + } +#endif +#if 0 + rCmdBatchReq.ucChannelType = 0; /* SCAN_CHANNEL_FULL; */ +#endif + + rCmdBatchReq.u4Scanfreq = scanfreq; + rCmdBatchReq.ucMScan = mscan > CFG_BATCH_MAX_MSCAN ? CFG_BATCH_MAX_MSCAN : mscan; + rCmdBatchReq.ucBestn = bestn; + rCmdBatchReq.ucRtt = rtt; + DBGLOG(SCN, TRACE, "[BATCH] SCANFREQ=%d MSCAN=%d BESTN=%d RTT=%d\n", + rCmdBatchReq.u4Scanfreq, rCmdBatchReq.ucMScan, rCmdBatchReq.ucBestn, rCmdBatchReq.ucRtt); + + if (rCmdBatchReq.ucChannelType != SCAN_CHANNEL_SPECIFIED) { + DBGLOG(SCN, TRACE, "[BATCH] CHANNELS = %s\n", + rCmdBatchReq.ucChannelType == + SCAN_CHANNEL_FULL ? "FULL" : rCmdBatchReq.ucChannelType == + SCAN_CHANNEL_2G4 ? "2.4G all" : "5G all"); + } else { + DBGLOG(SCN, TRACE, "[BATCH] CHANNEL list\n"); + prRfChannelInfo = &rCmdBatchReq.arChannelList[0]; + for (tokens = 0; tokens < rCmdBatchReq.ucChannelListNum; tokens++) { + DBGLOG(SCN, TRACE, "[BATCH] %s, %d\n", + prRfChannelInfo->ucBand == + BAND_2G4 ? "2.4G" : "5G", prRfChannelInfo->ucChannelNum); + prRfChannelInfo++; + } + } + + rCmdBatchReq.ucSeqNum = 1; + rCmdBatchReq.ucNetTypeIndex = KAL_NETWORK_TYPE_AIS_INDEX; + rCmdBatchReq.ucCmd = SCAN_BATCH_REQ_START; + + *pu4WritenLen = kalSnprintf(pvSetBuffer, 3, "%d", rCmdBatchReq.ucMScan); + + } else if (!kalStrnCmp(head, BATCHING_STOP, kalStrLen(BATCHING_STOP))) { + + DBGLOG(SCN, TRACE, "XXX Stop Batch Scan XXX\n"); + + rCmdBatchReq.ucSeqNum = 1; + rCmdBatchReq.ucNetTypeIndex = KAL_NETWORK_TYPE_AIS_INDEX; + rCmdBatchReq.ucCmd = SCAN_BATCH_REQ_STOP; + } else { + return -EINVAL; + } + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_BATCH_REQ, + TRUE, FALSE, g_fgIsOid, NULL, NULL, + sizeof(CMD_BATCH_REQ_T), + (PUINT_8)(&rCmdBatchReq), NULL, 0); + + /* kalMemSet(pvSetBuffer, 0, u4SetBufferLen); */ + /* rStatus = kalSnprintf(pvSetBuffer, 2, "%s", "OK"); */ + +/* exit: */ + return rStatus; +} + +WLAN_STATUS +batchGetCmd(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + CMD_BATCH_REQ_T rCmdBatchReq; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_EVENT_BATCH_RESULT_T prEventBatchResult; + /* UINT_32 i; */ + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + prEventBatchResult = (P_EVENT_BATCH_RESULT_T) pvQueryBuffer; + + DBGLOG(SCN, TRACE, "XXX Get Batch Scan Result (%d) XXX\n", prEventBatchResult->ucScanCount); + + *pu4QueryInfoLen = sizeof(EVENT_BATCH_RESULT_T); + + rCmdBatchReq.ucSeqNum = 2; + rCmdBatchReq.ucCmd = SCAN_BATCH_REQ_RESULT; + rCmdBatchReq.ucMScan = prEventBatchResult->ucScanCount; /* Get which round result */ + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_BATCH_REQ, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventBatchScanResult, + nicOidCmdTimeoutCommon, + sizeof(CMD_BATCH_REQ_T), + (PUINT_8) &rCmdBatchReq, (PVOID) pvQueryBuffer, u4QueryBufferLen); + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. +* \retval WLAN_STATUS_INVALID_LENGTH +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBatchScanReq(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + return batchSetCmd(prAdapter, pvSetBuffer, u4SetBufferLen, pu4SetInfoLen); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryBatchScanResult(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + return batchGetCmd(prAdapter, pvQueryBuffer, u4QueryBufferLen, pu4QueryInfoLen); + +} /* end of wlanoidQueryBatchScanResult() */ + +#endif /* CFG_SUPPORT_BATCH_SCAN */ + +#if CFG_SUPPORT_PASSPOINT +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called by HS2.0 to set the assoc info, which is needed to add to +* Association request frame while join HS2.0 AP. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. +* \retval WLAN_STATUS_INVALID_LENGTH +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetHS20Info(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_IE_HS20_INDICATION_T prHS20IndicationIe; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + DEBUGFUNC("wlanoidSetHS20AssocInfo"); + DBGLOG(REQ, LOUD, "\r\n"); + + if (u4SetBufferLen == 0) + return WLAN_STATUS_INVALID_LENGTH; + + *pu4SetInfoLen = u4SetBufferLen; + + prHS20IndicationIe = (P_IE_HS20_INDICATION_T) pvSetBuffer; + + prAdapter->prGlueInfo->ucHotspotConfig = prHS20IndicationIe->ucHotspotConfig; + prAdapter->prGlueInfo->fgConnectHS20AP = TRUE; + + DBGLOG(SEC, TRACE, "HS20 IE sz %ld\n", u4SetBufferLen); + + kalMemCopy(prAdapter->prGlueInfo->aucHS20AssocInfoIE, pvSetBuffer, u4SetBufferLen); + prAdapter->prGlueInfo->u2HS20AssocInfoIELen = (UINT_16) u4SetBufferLen; + DBGLOG(SEC, TRACE, "HS20 Assoc Info IE sz %ld\n", u4SetBufferLen); + + return WLAN_STATUS_SUCCESS; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called by WSC to set the assoc info, which is needed to add to +* Association request frame while join WPS AP. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. +* \retval WLAN_STATUS_INVALID_LENGTH +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetInterworkingInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ +#if 0 + P_HS20_INFO_T prHS20Info = NULL; + P_IE_INTERWORKING_T prInterWorkingIe; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prHS20Info = &(prAdapter->rWifiVar.rHS20Info); + + DEBUGFUNC("wlanoidSetInterworkingInfo"); + DBGLOG(REQ, TRACE, "\r\n"); + + if (u4SetBufferLen == 0) + return WLAN_STATUS_INVALID_LENGTH; + + *pu4SetInfoLen = u4SetBufferLen; + prInterWorkingIe = (P_IE_INTERWORKING_T) pvSetBuffer; + + prHS20Info->ucAccessNetworkOptions = prInterWorkingIe->ucAccNetOpt; + prHS20Info->ucVenueGroup = prInterWorkingIe->ucVenueGroup; + prHS20Info->ucVenueType = prInterWorkingIe->ucVenueType; + COPY_MAC_ADDR(prHS20Info->aucHESSID, prInterWorkingIe->aucHESSID); + + DBGLOG(SEC, TRACE, "IW IE sz %ld\n", u4SetBufferLen); +#endif + return WLAN_STATUS_SUCCESS; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called by WSC to set the Roaming Consortium IE info, which is needed to +* add to Association request frame while join WPS AP. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. +* \retval WLAN_STATUS_INVALID_LENGTH +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetRoamingConsortiumIEInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ +#if 0 + P_HS20_INFO_T prHS20Info = NULL; + P_PARAM_HS20_ROAMING_CONSORTIUM_INFO prRCInfo; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prHS20Info = &(prAdapter->rWifiVar.rHS20Info); + + /* DEBUGFUNC("wlanoidSetRoamingConsortiumInfo"); */ + /* DBGLOG(HS2, TRACE, ("\r\n")); */ + + if (u4SetBufferLen == 0) + return WLAN_STATUS_INVALID_LENGTH; + + *pu4SetInfoLen = u4SetBufferLen; + prRCInfo = (P_PARAM_HS20_ROAMING_CONSORTIUM_INFO) pvSetBuffer; + + kalMemCopy(&(prHS20Info->rRCInfo), prRCInfo, sizeof(PARAM_HS20_ROAMING_CONSORTIUM_INFO)); + + /* DBGLOG(HS2, TRACE, ("RoamingConsortium IE sz %ld\n", u4SetBufferLen)); */ +#endif + return WLAN_STATUS_SUCCESS; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set_bssid_pool +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetHS20BssidPool(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (u4SetBufferLen < sizeof(PARAM_HS20_SET_BSSID_POOL)) { + *pu4SetInfoLen = sizeof(PARAM_HS20_SET_BSSID_POOL); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + rWlanStatus = hs20SetBssidPool(prAdapter, pvSetBuffer, KAL_NETWORK_TYPE_AIS_INDEX); + + return rWlanStatus; +} /* end of wlanoidSendHS20GASRequest() */ + +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_SNIFFER +WLAN_STATUS +wlanoidSetMonitor(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_MONITOR_SET_STRUCT_T prMonitorSetInfo; + CMD_MONITOR_SET_INFO_T rCmdMonitorSetInfo; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidSetMonitor"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_MONITOR_SET_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_MONITOR_SET_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prMonitorSetInfo = (P_PARAM_CUSTOM_MONITOR_SET_STRUCT_T) pvSetBuffer; + + rCmdMonitorSetInfo.ucEnable = prMonitorSetInfo->ucEnable; + rCmdMonitorSetInfo.ucBand = prMonitorSetInfo->ucBand; + rCmdMonitorSetInfo.ucPriChannel = prMonitorSetInfo->ucPriChannel; + rCmdMonitorSetInfo.ucSco = prMonitorSetInfo->ucSco; + rCmdMonitorSetInfo.ucChannelWidth = prMonitorSetInfo->ucChannelWidth; + rCmdMonitorSetInfo.ucChannelS1 = prMonitorSetInfo->ucChannelS1; + rCmdMonitorSetInfo.ucChannelS2 = prMonitorSetInfo->ucChannelS2; + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_MONITOR, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_MONITOR_SET_INFO_T), + (PUINT_8) &rCmdMonitorSetInfo, pvSetBuffer, u4SetBufferLen); + + return rWlanStatus; +} +#endif + +#if CFG_SUPPORT_ADVANCE_CONTROL +WLAN_STATUS +wlanoidAdvCtrl(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + return _wlanoidAdvCtrl(prAdapter, + pvQueryBuffer, + u4QueryBufferLen, + pu4QueryInfoLen, + g_fgIsOid); +} + +WLAN_STATUS +_wlanoidAdvCtrl(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen, IN BOOLEAN fgIsOid) +{ + P_CMD_ADV_CONFIG_HEADER_T cmd; + UINT_16 type = 0; + UINT_32 len; + BOOLEAN fgSetQuery = FALSE; + BOOLEAN fgNeedResp = TRUE; + + DBGLOG(REQ, LOUD, "%s>\n", __func__); + + 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(*cmd)) { + DBGLOG(REQ, WARN, "Too short length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + cmd = (P_CMD_ADV_CONFIG_HEADER_T)pvQueryBuffer; + + if (cmd->u2Type & CMD_ADV_CONTROL_SET) { + fgSetQuery = TRUE; + fgNeedResp = FALSE; + } + + type = cmd->u2Type; + type &= ~CMD_ADV_CONTROL_SET; + DBGLOG(RSN, INFO, "%s cmd type %d\n", __func__, cmd->u2Type); + switch (type) { + case CMD_PTA_CONFIG_TYPE: + *pu4QueryInfoLen = sizeof(CMD_PTA_CONFIG_T); + len = sizeof(CMD_PTA_CONFIG_T); + break; + case CMD_GET_REPORT_TYPE: + *pu4QueryInfoLen = sizeof(struct CMD_GET_TRAFFIC_REPORT); + len = sizeof(struct CMD_GET_TRAFFIC_REPORT); + break; + case CMD_NOISE_HISTOGRAM_TYPE: + *pu4QueryInfoLen = sizeof(struct CMD_NOISE_HISTOGRAM_REPORT); + len = sizeof(struct CMD_NOISE_HISTOGRAM_REPORT); + break; + default: + return WLAN_STATUS_INVALID_LENGTH; + } + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ADV_CONTROL, + fgSetQuery, + fgNeedResp, + fgIsOid, + nicCmdEventQueryAdvCtrl, + nicOidCmdTimeoutCommon, + len, (PUINT_8)cmd, + pvQueryBuffer, u4QueryBufferLen); +} +#endif + +#if CFG_SUPPORT_MSP +WLAN_STATUS +wlanoidQueryWlanInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + return _wlanoidQueryWlanInfo(prAdapter, + pvQueryBuffer, + u4QueryBufferLen, + pu4QueryInfoLen, + g_fgIsOid); +} + +WLAN_STATUS +_wlanoidQueryWlanInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen, IN BOOLEAN fgIsOid) +{ + P_PARAM_HW_WLAN_INFO_T prHwWlanInfo; + + DEBUGFUNC("wlanoidQueryWlanInfo"); + DBGLOG(REQ, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(PARAM_HW_WLAN_INFO_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_HW_WLAN_INFO_T)) { + DBGLOG(REQ, WARN, "Too short length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prHwWlanInfo = (P_PARAM_HW_WLAN_INFO_T)pvQueryBuffer; + DBGLOG(RSN, INFO, "MT6632 : wlanoidQueryWlanInfo index = %d\n", prHwWlanInfo->u4Index); + + /* *pu4QueryInfoLen = 8 + prRxStatistics->u4TotalNum; */ + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_WLAN_INFO, + FALSE, + TRUE, + fgIsOid, + nicCmdEventQueryWlanInfo, + nicOidCmdTimeoutCommon, + sizeof(PARAM_HW_WLAN_INFO_T), (PUINT_8)prHwWlanInfo, + pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryWlanInfo */ + + +WLAN_STATUS +wlanoidQueryMibInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_HW_MIB_INFO_T prHwMibInfo; + + DEBUGFUNC("wlanoidQueryMibInfo"); + DBGLOG(REQ, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(PARAM_HW_MIB_INFO_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_HW_MIB_INFO_T)) { + DBGLOG(REQ, WARN, "Too short length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prHwMibInfo = (P_PARAM_HW_MIB_INFO_T)pvQueryBuffer; + DBGLOG(RSN, INFO, "MT6632 : wlanoidQueryMibInfo index = %d\n", prHwMibInfo->u4Index); + + /* *pu4QueryInfoLen = 8 + prRxStatistics->u4TotalNum; */ + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_MIB_INFO, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventQueryMibInfo, + nicOidCmdTimeoutCommon, + sizeof(PARAM_HW_MIB_INFO_T), (PUINT_8)prHwMibInfo, + pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryMibInfo */ +#endif + +#if CFG_SUPPORT_LAST_SEC_MCS_INFO +WLAN_STATUS +wlanoidTxMcsInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + struct PARAM_TX_MCS_INFO *prMcsInfo; + + DEBUGFUNC("wlanoidQueryWlanInfo"); + DBGLOG(REQ, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(struct PARAM_TX_MCS_INFO); + + 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(struct PARAM_TX_MCS_INFO)) { + DBGLOG(REQ, WARN, "Too short length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prMcsInfo = (struct PARAM_TX_MCS_INFO *)pvQueryBuffer; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_TX_MCS_INFO, + FALSE, + TRUE, + TRUE, + nicCmdEventTxMcsInfo, + nicOidCmdTimeoutCommon, + sizeof(struct PARAM_TX_MCS_INFO), (PUINT_8)prMcsInfo, + pvQueryBuffer, u4QueryBufferLen); + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set FW log to Host. +* +* \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 +wlanoidSetFwLog2Host( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + P_CMD_FW_LOG_2_HOST_CTRL_T prFwLog2HostCtrl; + UINT_64 ts = KAL_GET_HOST_CLOCK(); + + DEBUGFUNC("wlanoidSetFwLog2Host"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(CMD_FW_LOG_2_HOST_CTRL_T); + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, + "Fail in set FW log to Host! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4SetBufferLen < sizeof(CMD_FW_LOG_2_HOST_CTRL_T)) { + DBGLOG(REQ, WARN, "Too short length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prFwLog2HostCtrl = (P_CMD_FW_LOG_2_HOST_CTRL_T)pvSetBuffer; + prFwLog2HostCtrl->u4HostTimeMSec = (UINT_32)(do_div(ts, 1000000000) / 1000); + prFwLog2HostCtrl->u4HostTimeSec = (UINT_32)ts; + +#if CFG_SUPPORT_FW_DBG_LEVEL_CTRL + DBGLOG(REQ, INFO, "McuDest %d, LogType %d, (FwLogLevel %d)\n", prFwLog2HostCtrl->ucMcuDest, + prFwLog2HostCtrl->ucFwLog2HostCtrl, prFwLog2HostCtrl->ucFwLogLevel); +#else + DBGLOG(REQ, INFO, "McuDest %d, LogType %d\n", prFwLog2HostCtrl->ucMcuDest, + prFwLog2HostCtrl->ucFwLog2HostCtrl); +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_FW_LOG_2_HOST, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_FW_LOG_2_HOST_CTRL_T), + (PUINT_8)prFwLog2HostCtrl, pvSetBuffer, u4SetBufferLen); +} + +WLAN_STATUS +wlanoidNotifyFwSuspend( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + P_CMD_SUSPEND_MODE_SETTING_T prSuspendCmd; + + if (!prAdapter || !pvSetBuffer) + return WLAN_STATUS_INVALID_DATA; + + prSuspendCmd = (P_CMD_SUSPEND_MODE_SETTING_T)pvSetBuffer; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_SUSPEND_MODE, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_SUSPEND_MODE_SETTING_T), + (PUINT_8)prSuspendCmd, + NULL, + 0); +} +#if CFG_SUPPORT_DBDC +WLAN_STATUS +wlanoidSetDbdcEnable( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + UINT_8 ucDBDCEnable; + + if (!prAdapter || !pvSetBuffer) + return WLAN_STATUS_INVALID_DATA; + + kalMemCopy(&ucDBDCEnable, pvSetBuffer, 1); + cnmUpdateDbdcSetting(prAdapter, ucDBDCEnable); + + return WLAN_STATUS_SUCCESS; +} +#endif /*#if CFG_SUPPORT_DBDC*/ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set tx target power base. +* +* \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 +wlanoidQuerySetTxTargetPower(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_SET_TX_TARGET_POWER_T prSetTxTargetPowerInfo; + CMD_SET_TX_TARGET_POWER_T rCmdSetTxTargetPower; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQuerySetTxTargetPower"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(P_PARAM_CUSTOM_SET_TX_TARGET_POWER_T); + + if (u4SetBufferLen < sizeof(P_PARAM_CUSTOM_SET_TX_TARGET_POWER_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prSetTxTargetPowerInfo = (P_PARAM_CUSTOM_SET_TX_TARGET_POWER_T) pvSetBuffer; + + kalMemSet(&rCmdSetTxTargetPower, 0, sizeof(CMD_SET_TX_TARGET_POWER_T)); + + rCmdSetTxTargetPower.ucTxTargetPwr = prSetTxTargetPowerInfo->ucTxTargetPwr; + + DBGLOG(INIT, INFO, "MT6632 : wlanoidQuerySetTxTargetPower =%x dbm\n", rCmdSetTxTargetPower.ucTxTargetPwr); + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_TX_PWR, + TRUE, /* fgSetQuery Bit: True->write False->read*/ + FALSE, /* fgNeedResp */ + g_fgIsOid, /* fgIsOid*/ + nicCmdEventSetCommon, /* REF: wlanoidSetDbdcEnable */ + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_EFUSE_T), + (PUINT_8) (&rCmdSetTxTargetPower), pvSetBuffer, u4SetBufferLen); + + return rWlanStatus; +} + +#if (CFG_SUPPORT_DFS_MASTER == 1) +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set rdd report. +* +* \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 +wlanoidQuerySetRddReport(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_SET_RDD_REPORT_T prSetRddReport; + P_CMD_RDD_ON_OFF_CTRL_T prCmdRddOnOffCtrl; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQuerySetRddReport"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(P_PARAM_CUSTOM_SET_RDD_REPORT_T); + + ASSERT(pvSetBuffer); + + prSetRddReport = (P_PARAM_CUSTOM_SET_RDD_REPORT_T) pvSetBuffer; + + prCmdRddOnOffCtrl = (P_CMD_RDD_ON_OFF_CTRL_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(*prCmdRddOnOffCtrl)); + + ASSERT(prCmdRddOnOffCtrl); + if (prCmdRddOnOffCtrl == NULL) { + DBGLOG(INIT, ERROR, "prCmdRddOnOffCtrl is NULL"); + return WLAN_STATUS_FAILURE; + } + + prCmdRddOnOffCtrl->ucDfsCtrl = RDD_RADAR_EMULATE; + + prCmdRddOnOffCtrl->ucRddIdx = prSetRddReport->ucDbdcIdx; + + if (prCmdRddOnOffCtrl->ucRddIdx) + prCmdRddOnOffCtrl->ucRddInSel = RDD_IN_SEL_1; + else + prCmdRddOnOffCtrl->ucRddInSel = RDD_IN_SEL_0; + + DBGLOG(INIT, INFO, "MT6632 : wlanoidQuerySetRddReport - DFS ctrl: %.d, RDD index: %d\n", + prCmdRddOnOffCtrl->ucDfsCtrl, prCmdRddOnOffCtrl->ucRddIdx); + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_RDD_ON_OFF_CTRL, + TRUE, /* fgSetQuery Bit: True->write False->read*/ + FALSE, /* fgNeedResp */ + g_fgIsOid, /* fgIsOid*/ + nicCmdEventSetCommon, /* REF: wlanoidSetDbdcEnable */ + nicOidCmdTimeoutCommon, + sizeof(*prCmdRddOnOffCtrl), + (PUINT_8) (prCmdRddOnOffCtrl), pvSetBuffer, u4SetBufferLen); + + cnmMemFree(prAdapter, prCmdRddOnOffCtrl); + + return rWlanStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set rdd report. +* +* \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 +wlanoidQuerySetRadarDetectMode(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + struct PARAM_CUSTOM_SET_RADAR_DETECT_MODE *prSetRadarDetectMode; + P_CMD_RDD_ON_OFF_CTRL_T prCmdRddOnOffCtrl; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQuerySetRadarDetectMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(struct PARAM_CUSTOM_SET_RADAR_DETECT_MODE *); + + ASSERT(pvSetBuffer); + + prSetRadarDetectMode = (struct PARAM_CUSTOM_SET_RADAR_DETECT_MODE *) pvSetBuffer; + + prCmdRddOnOffCtrl = (P_CMD_RDD_ON_OFF_CTRL_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(*prCmdRddOnOffCtrl)); + + ASSERT(prCmdRddOnOffCtrl); + if (prCmdRddOnOffCtrl == NULL) { + DBGLOG(INIT, ERROR, "prCmdRddOnOffCtrl is NULL"); + return WLAN_STATUS_FAILURE; + } + + prCmdRddOnOffCtrl->ucDfsCtrl = RDD_DET_MODE; + + prCmdRddOnOffCtrl->ucRadarDetectMode = prSetRadarDetectMode->ucRadarDetectMode; + + DBGLOG(INIT, INFO, "MT6632 : wlanoidQuerySetRadarDetectMode - DFS ctrl: %.d, Radar Detect Mode: %d\n", + prCmdRddOnOffCtrl->ucDfsCtrl, prCmdRddOnOffCtrl->ucRadarDetectMode); + + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_RDD_ON_OFF_CTRL, + TRUE, /* fgSetQuery Bit: True->write False->read*/ + FALSE, /* fgNeedResp */ + g_fgIsOid, /* fgIsOid*/ + nicCmdEventSetCommon, /* REF: wlanoidSetDbdcEnable */ + nicOidCmdTimeoutCommon, + sizeof(*prCmdRddOnOffCtrl), + (PUINT_8) (prCmdRddOnOffCtrl), pvSetBuffer, u4SetBufferLen); + + cnmMemFree(prAdapter, prCmdRddOnOffCtrl); + + return rWlanStatus; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +wlanoidLinkDown(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + DEBUGFUNC("wlanoidSetDisassociate"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 0; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, + "Fail in set link down! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + aisBssLinkDown(prAdapter); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetDisassociate */ + +#if CFG_SUPPORT_CSI +WLAN_STATUS +wlanoidSetCSIControl( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + struct CMD_CSI_CONTROL_T *pCSICtrl; + + DEBUGFUNC("wlanoidSetCSIControl"); + + *pu4SetInfoLen = sizeof(struct CMD_CSI_CONTROL_T); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, + "Fail in set CSI control! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4SetBufferLen < sizeof(struct CMD_CSI_CONTROL_T)) { + DBGLOG(REQ, WARN, "Too short length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + pCSICtrl = (struct CMD_CSI_CONTROL_T *)pvSetBuffer; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_CSI_CONTROL, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_CSI_CONTROL_T), + (PUINT_8)pCSICtrl, pvSetBuffer, u4SetBufferLen); +} +#endif + +WLAN_STATUS +wlanoidGetTxPwrTbl(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen) +{ + struct CMD_GET_TXPWR_TBL CmdPwrTbl; + struct PARAM_CMD_GET_TXPWR_TBL *prPwrTbl = NULL; + + DEBUGFUNC("wlanoidGetTxPwrTbl"); + DBGLOG(REQ, LOUD, "\n"); + + if (!prAdapter || (!pvQueryBuffer && u4QueryBufferLen) || + !pu4QueryInfoLen) + return WLAN_STATUS_INVALID_DATA; + + *pu4QueryInfoLen = sizeof(struct PARAM_CMD_GET_TXPWR_TBL); + + 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(struct PARAM_CMD_GET_TXPWR_TBL)) { + DBGLOG(REQ, WARN, "Too short length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prPwrTbl = (struct PARAM_CMD_GET_TXPWR_TBL *)pvQueryBuffer; + CmdPwrTbl.ucDbdcIdx = prPwrTbl->ucDbdcIdx; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_TXPWR_TBL, + FALSE, + TRUE, + g_fgIsOid, + nicCmdEventGetTxPwrTbl, + nicOidCmdTimeoutCommon, + sizeof(struct CMD_GET_TXPWR_TBL), + (PUINT_8)&CmdPwrTbl, + pvQueryBuffer, + u4QueryBufferLen); + +} + +WLAN_STATUS +wlanoidEnableRoaming(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + DBGLOG(OID, INFO, "enable roaming\n"); + + aisRemoveBlacklistBySource(prAdapter, AIS_BLACK_LIST_FROM_FWK); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidConfigRoaming(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + struct nlattr *attrlist; + struct AIS_BLACKLIST_ITEM *prBlackList; + UINT_32 len_shift = 0; + UINT_32 numOfList[2] = { 0 }; + int i; + + attrlist = (struct nlattr *)pvSetBuffer; + + /* get the number of blacklist and copy those mac addresses from HAL */ + if (attrlist->nla_type == WIFI_ATTRIBUTE_ROAMING_BLACKLIST_NUM) { + numOfList[0] = nla_get_u32(attrlist); + len_shift += NLA_ALIGN(attrlist->nla_len); + } + DBGLOG(REQ, INFO, "Get the number of blacklist=%d\n", numOfList[0]); + + if (numOfList[0] >= 0 && numOfList[0] + <= MAX_FW_ROAMING_BLACKLIST_SIZE) { + /*Refresh all the FWKBlacklist */ + aisRemoveBlacklistBySource(prAdapter, AIS_BLACK_LIST_FROM_FWK); + + /* Start to receive blacklist mac addresses + * and set to FWK blacklist + */ + attrlist = (struct nlattr *)((UINT_8 *) pvSetBuffer + + len_shift); + for (i = 0; i < numOfList[0]; i++) { + if (attrlist->nla_type + == WIFI_ATTRIBUTE_ROAMING_BLACKLIST_BSSID) + prBlackList = + aisAddBlacklistByBssid(prAdapter, + nla_data(attrlist), + AIS_BLACK_LIST_FROM_FWK); + len_shift += NLA_ALIGN(attrlist->nla_len); + attrlist = (struct nlattr *)((UINT_8 *) pvSetBuffer + + len_shift); + } + } + + return WLAN_STATUS_SUCCESS; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/common/wlan_p2p.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/common/wlan_p2p.c new file mode 100644 index 0000000000000..25b837b2117c4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/common/wlan_p2p.c @@ -0,0 +1,1512 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +/****************************************************************************** +* C O M P I L E R F L A G S +******************************************************************************* +*/ + +/****************************************************************************** +* E X T E R N A L R E F E R E N C E S +******************************************************************************* +*/ +#include "precomp.h" +#include "gl_p2p_ioctl.h" + +/****************************************************************************** +* C O N S T A N T S +******************************************************************************* +*/ + +/****************************************************************************** +* D A T A T Y P E S +******************************************************************************* +*/ + +/****************************************************************************** +* P U B L I C D A T A +******************************************************************************* +*/ + +/****************************************************************************** +* P R I V A T E D A T A +******************************************************************************* +*/ + +/****************************************************************************** +* M A C R O S +******************************************************************************* +*/ + +/****************************************************************************** +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************* +*/ + +/****************************************************************************** +* F U N C T I O N S +******************************************************************************* +*/ +/*----------------------------------------------------------------------------*/ +/*! +* \brief command packet generation utility +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] ucCID Command ID +* \param[in] fgSetQuery Set or Query +* \param[in] fgNeedResp Need for response +* \param[in] pfCmdDoneHandler Function pointer when command is done +* \param[in] u4SetQueryInfoLen The length of the set/query buffer +* \param[in] pucInfoBuffer Pointer to set/query buffer +* +* +* \retval WLAN_STATUS_PENDING +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendSetQueryP2PCmd(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucCID, + IN UINT_8 ucBssIdx, + IN BOOLEAN fgSetQuery, + IN BOOLEAN fgNeedResp, + IN BOOLEAN fgIsOid, + IN PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + IN PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + IN UINT_32 u4SetQueryInfoLen, + IN 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->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->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 = 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 +*/ +/*----------------------------------------------------------------------------*/ +#if 0 +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; + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + + 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; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prNewKey->ucBssIdx); + ASSERT(prBssInfo); +#if 0 + if (prBssInfo->ucBMCWlanIndex >= WTBL_SIZE) { + prBssInfo->ucBMCWlanIndex = + secPrivacySeekForBcEntry(prAdapter, prBssInfo->ucBssIndex, prBssInfo->aucBSSID, + 0xff, CIPHER_SUITE_NONE, 0xff); + } +#endif + /* 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 0 + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { /* group client */ +#else + if (kalP2PGetRole(prAdapter->prGlueInfo) == 1) { /* group client */ +#endif + + rCmdKey.ucIsAuthenticator = 0; + } else { /* group owner */ + rCmdKey.ucIsAuthenticator = 1; + /* Force to set GO/AP Tx */ + rCmdKey.ucTxKey = 1; + } + + COPY_MAC_ADDR(rCmdKey.aucPeerAddr, prNewKey->arBSSID); + rCmdKey.ucBssIdx = prNewKey->ucBssIdx; + 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 */ + else if (prNewKey->u4KeyLength == WEP_40_LEN) + rCmdKey.ucAlgorithmId = CIPHER_SUITE_WEP40; /* WEP 40 */ + else if (prNewKey->u4KeyLength == WEP_104_LEN) + rCmdKey.ucAlgorithmId = CIPHER_SUITE_WEP104; /* WEP 104 */ + else + ASSERT(FALSE); + rCmdKey.ucKeyId = (UINT_8) (prNewKey->u4KeyIndex & 0xff); + rCmdKey.ucKeyLen = (UINT_8) prNewKey->u4KeyLength; + kalMemCopy(rCmdKey.aucKeyMaterial, (PUINT_8) prNewKey->aucKeyMaterial, rCmdKey.ucKeyLen); + + if ((rCmdKey.aucPeerAddr[0] & rCmdKey.aucPeerAddr[1] & rCmdKey.aucPeerAddr[2] & + rCmdKey.aucPeerAddr[3] & rCmdKey.aucPeerAddr[4] & rCmdKey.aucPeerAddr[5]) == 0xFF) { + kalMemCopy(rCmdKey.aucPeerAddr, prBssInfo->aucBSSID, MAC_ADDR_LEN); + if (!rCmdKey.ucIsAuthenticator) { + prStaRec = cnmGetStaRecByAddress(prAdapter, rCmdKey.ucBssIdx, rCmdKey.aucPeerAddr); + if (!prStaRec) + ASSERT(FALSE); + } + } else { + prStaRec = cnmGetStaRecByAddress(prAdapter, rCmdKey.ucBssIdx, rCmdKey.aucPeerAddr); + } + + if (rCmdKey.ucTxKey) { + if (prStaRec) { + if (rCmdKey.ucKeyType) { /* RSN STA */ + ASSERT(prStaRec->ucWlanIndex < WTBL_SIZE); + rCmdKey.ucWlanIndex = prStaRec->ucWlanIndex; + prStaRec->fgTransmitKeyExist = TRUE; /* wait for CMD Done ? */ + } else { + ASSERT(FALSE); + } + } else { + if (prBssInfo) { /* GO/AP Tx BC */ + ASSERT(prBssInfo->ucBMCWlanIndex < WTBL_SIZE); + rCmdKey.ucWlanIndex = prBssInfo->ucBMCWlanIndex; + prBssInfo->fgBcDefaultKeyExist = TRUE; + prBssInfo->ucTxDefaultKeyID = rCmdKey.ucKeyId; + } else { + rCmdKey.ucWlanIndex = 255; /* GC WEP Tx key ? */ + ASSERT(FALSE); + } + } + } else { + if (((rCmdKey.aucPeerAddr[0] & rCmdKey.aucPeerAddr[1] & rCmdKey.aucPeerAddr[2] & + rCmdKey.aucPeerAddr[3] & rCmdKey.aucPeerAddr[4] & rCmdKey.aucPeerAddr[5]) == 0xFF) + || + ((rCmdKey.aucPeerAddr[0] | rCmdKey.aucPeerAddr[1] | rCmdKey. + aucPeerAddr[2] | rCmdKey.aucPeerAddr[3] | rCmdKey.aucPeerAddr[4] | rCmdKey.aucPeerAddr[5]) == + 0x00)) { + rCmdKey.ucWlanIndex = 255; /* GC WEP ? */ + ASSERT(FALSE); + } else { + if (prStaRec) { /* GC Rx RSN Group key */ + rCmdKey.ucWlanIndex = + secPrivacySeekForBcEntry(prAdapter, prStaRec->ucBssIndex, + prStaRec->aucMacAddr, + prStaRec->ucIndex, rCmdKey.ucAlgorithmId, rCmdKey.ucKeyId); + prStaRec->ucBMCWlanIndex = rCmdKey.ucWlanIndex; + ASSERT(prStaRec->ucBMCWlanIndex < WTBL_SIZE); + } else { /* Exist this case ? */ + ASSERT(FALSE); + } + } + } + + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_ADD_REMOVE_KEY, + prNewKey->ucBssIdx, + 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; + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + + 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; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prRemovedKey->ucBssIdx); + + kalMemZero((PUINT_8)&rCmdKey, sizeof(CMD_802_11_KEY)); + + rCmdKey.ucAddRemove = 0; /* remove */ + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { /* group client */ + rCmdKey.ucIsAuthenticator = 0; + } else { /* group owner */ + rCmdKey.ucIsAuthenticator = 1; + } + kalMemCopy(rCmdKey.aucPeerAddr, (PUINT_8) prRemovedKey->arBSSID, MAC_ADDR_LEN); + rCmdKey.ucBssIdx = prRemovedKey->ucBssIdx; + rCmdKey.ucKeyId = (UINT_8) (prRemovedKey->u4KeyIndex & 0x000000ff); + + /* Clean up the Tx key flag */ + prStaRec = cnmGetStaRecByAddress(prAdapter, prRemovedKey->ucBssIdx, prRemovedKey->arBSSID); + + /* mark for MR1 to avoid remove-key, but remove the wlan_tbl0 at the same time */ + if (1 /*prRemovedKey->u4KeyIndex & IS_UNICAST_KEY */) { + if (prStaRec) { + rCmdKey.ucKeyType = 1; + rCmdKey.ucWlanIndex = prStaRec->ucWlanIndex; + prStaRec->fgTransmitKeyExist = FALSE; + } else if (rCmdKey.ucIsAuthenticator) + prBssInfo->fgBcDefaultKeyExist = FALSE; + } else { + if (rCmdKey.ucIsAuthenticator) + prBssInfo->fgBcDefaultKeyExist = FALSE; + } + + if (!prStaRec) { + if (prAdapter->rWifiVar.rConnSettings.eAuthMode < AUTH_MODE_WPA + && prAdapter->rWifiVar.rConnSettings.eEncStatus != ENUM_ENCRYPTION_DISABLED) { + rCmdKey.ucWlanIndex = prBssInfo->ucBMCWlanIndex; + } else { + rCmdKey.ucWlanIndex = WTBL_RESERVED_ENTRY; + return WLAN_STATUS_SUCCESS; + } + } + + /* mark for MR1 to avoid remove-key, but remove the wlan_tbl0 at the same time */ + /* secPrivacyFreeForEntry(prAdapter, rCmdKey.ucWlanIndex); */ + + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_ADD_REMOVE_KEY, + prRemovedKey->ucBssIdx, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + NULL, + sizeof(CMD_802_11_KEY), (PUINT_8)&rCmdKey, pvSetBuffer, u4SetBufferLen); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \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) ((ULONG) prNetworkAddress + + (ULONG) (prNetworkAddress->u2AddressLength + + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + + /* construct payload of command packet */ + u4CmdSize = OFFSET_OF(CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress) + + sizeof(IPV4_NETWORK_ADDRESS) * u4IpAddressCount; + + prCmdNetworkAddressList = (P_CMD_SET_NETWORK_ADDRESS_LIST) kalMemAlloc(u4CmdSize, VIR_MEM_TYPE); + + if (prCmdNetworkAddressList == NULL) + return WLAN_STATUS_FAILURE; + + /* fill P_CMD_SET_NETWORK_ADDRESS_LIST */ + prCmdNetworkAddressList->ucBssIndex = prNetworkAddressList->ucBssIdx; + prCmdNetworkAddressList->ucAddressCount = (UINT_8) u4IpAddressCount; + prNetworkAddress = prNetworkAddressList->arAddress; + for (i = 0, j = 0; i < prNetworkAddressList->u4AddressCount; i++) { + if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { + prNetAddrIp = (P_PARAM_NETWORK_ADDRESS_IP) prNetworkAddress->aucAddress; + + kalMemCopy(prCmdNetworkAddressList->arNetAddress[j].aucIpAddr, + &(prNetAddrIp->in_addr), sizeof(UINT_32)); + + j++; + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prNetworkAddress + + (ULONG) (prNetworkAddress->u2AddressLength + + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_IP_ADDRESS, + TRUE, + FALSE, + TRUE, + nicCmdEventSetIpAddress, + nicOidCmdTimeoutCommon, + u4CmdSize, (PUINT_8) prCmdNetworkAddressList, pvSetBuffer, u4SetBufferLen); + + kalMemFree(prCmdNetworkAddressList, VIR_MEM_TYPE, u4CmdSize); + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to query the power save profile. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryP2pPowerSaveProfile(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryP2pPowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen != 0) { + ASSERT(pvQueryBuffer); + /* TODO: FIXME */ + /* *(PPARAM_POWER_MODE) pvQueryBuffer = + * (PARAM_POWER_MODE)(prAdapter->rWlanInfo.arPowerSaveMode[P2P_DEV_BSS_INDEX].ucPsProfile); + */ + /* *pu4QueryInfoLen = sizeof(PARAM_POWER_MODE); */ + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to set the power save profile. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2pPowerSaveProfile(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS status; + PARAM_POWER_MODE ePowerMode; + + DEBUGFUNC("wlanoidSetP2pPowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_POWER_MODE); + if (u4SetBufferLen < sizeof(PARAM_POWER_MODE)) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } else if (*(PPARAM_POWER_MODE) pvSetBuffer >= Param_PowerModeMax) { + DBGLOG(REQ, WARN, "Invalid power mode %d\n", *(PPARAM_POWER_MODE) pvSetBuffer); + return WLAN_STATUS_INVALID_DATA; + } + + ePowerMode = *(PPARAM_POWER_MODE) pvSetBuffer; + + if (prAdapter->fgEnCtiaPowerMode) { + if (ePowerMode == Param_PowerModeCAM) { + /*Todo:: Nothing */ + /*Todo:: Nothing */ + } else { + /* User setting to PS mode (Param_PowerModeMAX_PSP or Param_PowerModeFast_PSP) */ + + if (prAdapter->u4CtiaPowerMode == 0) { + /* force to keep in CAM mode */ + ePowerMode = Param_PowerModeCAM; + } else if (prAdapter->u4CtiaPowerMode == 1) { + ePowerMode = Param_PowerModeMAX_PSP; + } else if (prAdapter->u4CtiaPowerMode == 2) { + ePowerMode = Param_PowerModeFast_PSP; + } + } + } + + status = nicConfigPowerSaveProfile(prAdapter, P2P_DEV_BSS_INDEX, /* TODO: FIXME */ + 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"); + DBGLOG(INIT, INFO, "wlanoidSetP2pSetNetworkAddress (%d)\n", (INT_16) u4SetBufferLen); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 4; + + if (u4SetBufferLen < sizeof(PARAM_NETWORK_ADDRESS_LIST)) + return WLAN_STATUS_INVALID_DATA; + + *pu4SetInfoLen = 0; + u4IpAddressCount = 0; + + prNetworkAddress = prNetworkAddressList->arAddress; + for (i = 0; i < prNetworkAddressList->u4AddressCount; i++) { + if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { + u4IpAddressCount++; + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prNetworkAddress + + (ULONG) (prNetworkAddress->u2AddressLength + + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + + /* construct payload of command packet */ + u4CmdSize = OFFSET_OF(CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress) + + sizeof(IPV4_NETWORK_ADDRESS) * u4IpAddressCount; + + if (u4IpAddressCount == 0) + u4CmdSize = sizeof(CMD_SET_NETWORK_ADDRESS_LIST); + + prCmdNetworkAddressList = (P_CMD_SET_NETWORK_ADDRESS_LIST) kalMemAlloc(u4CmdSize, VIR_MEM_TYPE); + + if (prCmdNetworkAddressList == NULL) + return WLAN_STATUS_FAILURE; + + /* fill P_CMD_SET_NETWORK_ADDRESS_LIST */ + prCmdNetworkAddressList->ucBssIndex = prNetworkAddressList->ucBssIdx; + + /* only to set IP address to FW once ARP filter is enabled */ + if (prAdapter->fgEnArpFilter) { + prCmdNetworkAddressList->ucAddressCount = (UINT_8) u4IpAddressCount; + prNetworkAddress = prNetworkAddressList->arAddress; + + DBGLOG(INIT, INFO, "u4IpAddressCount (%u)\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; + DBGLOG(INIT, INFO, "prNetAddrIp->in_addr:%d:%d:%d:%d\n", + (UINT_8) pucBuf[0], (UINT_8) pucBuf[1], (UINT_8) pucBuf[2], (UINT_8) pucBuf[3]); + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prNetworkAddress + + (ULONG) (prNetworkAddress->u2AddressLength + + OFFSET_OF + (PARAM_NETWORK_ADDRESS, aucAddress))); + } + + } else { + prCmdNetworkAddressList->ucAddressCount = 0; + } + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_IP_ADDRESS, + TRUE, + FALSE, + TRUE, + nicCmdEventSetIpAddress, + nicOidCmdTimeoutCommon, + u4CmdSize, (PUINT_8) prCmdNetworkAddressList, pvSetBuffer, u4SetBufferLen); + + kalMemFree(prCmdNetworkAddressList, VIR_MEM_TYPE, u4CmdSize); + return rStatus; +} /* end of wlanoidSetP2pSetNetworkAddress() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set Multicast Address List. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2PMulticastList(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + CMD_MAC_MCAST_ADDR rCmdMacMcastAddr; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* The data must be a multiple of the Ethernet address size. */ + if ((u4SetBufferLen % MAC_ADDR_LEN)) { + DBGLOG(REQ, WARN, "Invalid MC list length %u\n", + u4SetBufferLen); + + *pu4SetInfoLen = (((u4SetBufferLen + MAC_ADDR_LEN) - 1) / MAC_ADDR_LEN) * MAC_ADDR_LEN; + + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = u4SetBufferLen; + + /* Verify if we can support so many multicast addresses. */ + if (u4SetBufferLen > MAX_NUM_GROUP_ADDR * MAC_ADDR_LEN) { + 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.ucBssIndex = P2P_DEV_BSS_INDEX; /* TODO: */ + kalMemCopy(rCmdMacMcastAddr.arAddress, pvSetBuffer, u4SetBufferLen); + + return wlanoidSendSetQueryP2PCmd(prAdapter, CMD_ID_MAC_MCAST_ADDR, P2P_DEV_BSS_INDEX, + /* TODO: */ + /* This CMD response is no need to complete the OID. Or the event would unsync. */ + TRUE, FALSE, FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_MAC_MCAST_ADDR), + (PUINT_8) &rCmdMacMcastAddr, pvSetBuffer, u4SetBufferLen); + +} /* end of wlanoidSetP2PMulticastList() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to send GAS frame for P2P Service Discovery Request +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendP2PSDRequest(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (u4SetBufferLen < sizeof(PARAM_P2P_SEND_SD_REQUEST)) { + *pu4SetInfoLen = sizeof(PARAM_P2P_SEND_SD_REQUEST); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } +/* rWlanStatus = p2pFsmRunEventSDRequest(prAdapter, (P_PARAM_P2P_SEND_SD_REQUEST)pvSetBuffer); */ + + return rWlanStatus; +} /* end of wlanoidSendP2PSDRequest() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to send GAS frame for P2P Service Discovery Response +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendP2PSDResponse(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (u4SetBufferLen < sizeof(PARAM_P2P_SEND_SD_RESPONSE)) { + *pu4SetInfoLen = sizeof(PARAM_P2P_SEND_SD_RESPONSE); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } +/* rWlanStatus = p2pFsmRunEventSDResponse(prAdapter, (P_PARAM_P2P_SEND_SD_RESPONSE)pvSetBuffer); */ + + return rWlanStatus; +} /* end of wlanoidGetP2PSDRequest() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get GAS frame for P2P Service Discovery Request +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidGetP2PSDRequest(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; +/* PUINT_8 pucChannelNum = NULL; */ +/* 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"); + + *pu4QueryInfoLen = 0; + 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; + /* UINT_8 ucSeqNum = 0, */ + + 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"); + + *pu4QueryInfoLen = 0; + 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); + +#if 0 /* Comment it because CMD_ID_SEC_CHECK is not defined */ + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SEC_CHECK, + P2P_DEV_BSS_INDEX, + FALSE, + TRUE, + TRUE, + NULL, + nicOidCmdTimeoutCommon, + u4SetBufferLen, (PUINT_8) pvSetBuffer, pvSetBuffer, u4SetBufferLen); +#else + return WLAN_STATUS_NOT_SUPPORTED; +#endif +} /* end of wlanoidSetSecCheckRequest() */ + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \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[0]->aucSecCheckRsp, u4QueryBufferLen); +#endif + kalMemCopy((PUINT_8) (pvQueryBuffer + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer)), + prGlueInfo->prP2PInfo[0]->aucSecCheckRsp, u4QueryBufferLen); + + return rWlanStatus; +} /* end of wlanoidGetSecCheckResponse() */ +#endif +#endif + +WLAN_STATUS +wlanoidSetNoaParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T prNoaParam; + CMD_CUSTOM_NOA_PARAM_STRUCT_T rCmdNoaParam; + + DEBUGFUNC("wlanoidSetNoaParam"); + DBGLOG(INIT, TRACE, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_NOA_PARAM_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_NOA_PARAM_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prNoaParam = (P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T) pvSetBuffer; + + kalMemZero(&rCmdNoaParam, sizeof(CMD_CUSTOM_NOA_PARAM_STRUCT_T)); + rCmdNoaParam.u4NoaDurationMs = prNoaParam->u4NoaDurationMs; + rCmdNoaParam.u4NoaIntervalMs = prNoaParam->u4NoaIntervalMs; + rCmdNoaParam.u4NoaCount = prNoaParam->u4NoaCount; + +#if 0 + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_NOA_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_NOA_PARAM_STRUCT_T), + (PUINT_8) &rCmdNoaParam, pvSetBuffer, u4SetBufferLen); +#else + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_NOA_PARAM, + prNoaParam->ucBssIdx, + TRUE, + FALSE, + g_fgIsOid, + NULL, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_NOA_PARAM_STRUCT_T), + (PUINT_8) &rCmdNoaParam, pvSetBuffer, u4SetBufferLen); + +#endif + +} + +WLAN_STATUS +wlanoidSetOppPsParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T prOppPsParam; + CMD_CUSTOM_OPPPS_PARAM_STRUCT_T rCmdOppPsParam; + + DEBUGFUNC("wlanoidSetOppPsParam"); + DBGLOG(INIT, TRACE, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prOppPsParam = (P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T) pvSetBuffer; + + kalMemZero(&rCmdOppPsParam, sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T)); + + rCmdOppPsParam.ucBssIdx = prOppPsParam->ucBssIdx; + + if (prOppPsParam->ucOppPs) { + /* [spec. 3.3.2] CTWindow should be at least 10 TU */ + if (prOppPsParam->u4CTwindowMs < 10) + rCmdOppPsParam.u4CTwindowMs = 10; + else + rCmdOppPsParam.u4CTwindowMs = prOppPsParam->u4CTwindowMs; + } else + rCmdOppPsParam.u4CTwindowMs = 0;/* Set 0 means disable OppPs */ + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_OPPPS_PARAM, + TRUE, + FALSE, + g_fgIsOid, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T), + (PUINT_8)&rCmdOppPsParam, pvSetBuffer, u4SetBufferLen); +} + +WLAN_STATUS +wlanoidSetUApsdParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T prUapsdParam; + CMD_CUSTOM_UAPSD_PARAM_STRUCT_T rCmdUapsdParam; + P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo; + P_BSS_INFO_T prBssInfo; + + DEBUGFUNC("wlanoidSetUApsdParam"); + DBGLOG(INIT, TRACE, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prUapsdParam = (P_PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T) pvSetBuffer; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prUapsdParam->ucBssIdx); + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + + kalMemZero(&rCmdUapsdParam, sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T)); + rCmdUapsdParam.fgEnAPSD = prUapsdParam->fgEnAPSD; + + rCmdUapsdParam.fgEnAPSD_AcBe = prUapsdParam->fgEnAPSD_AcBe; + rCmdUapsdParam.fgEnAPSD_AcBk = prUapsdParam->fgEnAPSD_AcBk; + rCmdUapsdParam.fgEnAPSD_AcVo = prUapsdParam->fgEnAPSD_AcVo; + rCmdUapsdParam.fgEnAPSD_AcVi = prUapsdParam->fgEnAPSD_AcVi; + prPmProfSetupInfo->ucBmpDeliveryAC = + ((prUapsdParam->fgEnAPSD_AcBe << 0) | + (prUapsdParam->fgEnAPSD_AcBk << 1) | + (prUapsdParam->fgEnAPSD_AcVi << 2) | (prUapsdParam->fgEnAPSD_AcVo << 3)); + prPmProfSetupInfo->ucBmpTriggerAC = + ((prUapsdParam->fgEnAPSD_AcBe << 0) | + (prUapsdParam->fgEnAPSD_AcBk << 1) | + (prUapsdParam->fgEnAPSD_AcVi << 2) | (prUapsdParam->fgEnAPSD_AcVo << 3)); + + rCmdUapsdParam.ucMaxSpLen = prUapsdParam->ucMaxSpLen; + prPmProfSetupInfo->ucUapsdSp = prUapsdParam->ucMaxSpLen; + +#if 0 + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_UAPSD_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T), + (PUINT_8) &rCmdUapsdParam, pvSetBuffer, u4SetBufferLen); +#else + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_UAPSD_PARAM, + prBssInfo->ucBssIndex, + TRUE, + FALSE, + TRUE, + NULL, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T), + (PUINT_8) &rCmdUapsdParam, pvSetBuffer, u4SetBufferLen); + +#endif +} + +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 */ + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to set the WPS mode. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2pWPSmode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS status; + UINT_32 u4IsWPSmode = 0; + int i = 0; + + DEBUGFUNC("wlanoidSetP2pWPSmode"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (pvSetBuffer) + u4IsWPSmode = *(PUINT_32) pvSetBuffer; + else + u4IsWPSmode = 0; + + for (i = 0; i < KAL_P2P_NUM; i++)/* set all Role to the same value */ + if (u4IsWPSmode) + prAdapter->rWifiVar.prP2PConnSettings[i]->fgIsWPSMode = 1; + else + prAdapter->rWifiVar.prP2PConnSettings[i]->fgIsWPSMode = 0; + + status = nicUpdateBss(prAdapter, P2P_DEV_BSS_INDEX); + + return status; +} /* end of wlanoidSetP2pWPSmode() */ + +#endif + +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); + + if (prAdapter->fgIsEnableLpdvt) + return WLAN_STATUS_NOT_SUPPORTED; + + *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/misc/mediatek/connectivity/wlan/core/gen4-mt7668/init.wlan_mt7668_drv.rc b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/init.wlan_mt7668_drv.rc new file mode 100644 index 0000000000000..16b220b7b22ae --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/init.wlan_mt7668_drv.rc @@ -0,0 +1,2 @@ +on boot + insmod /vendor/lib/modules/wlan_drv_gen4_mt7668_prealloc.ko \ No newline at end of file diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/cmd_buf.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/cmd_buf.c new file mode 100644 index 0000000000000..bec4c664dcd71 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/cmd_buf.c @@ -0,0 +1,239 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +/******************************************************************************* +* C O M P I L E 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 */ + prCmdInfo->u2InfoBufLen = 0; + prCmdInfo->fgIsOid = FALSE; + + if (u4Length) { + /* Start address of allocated memory */ + u4Length = TFCB_FRAME_PAD_TO_DW(u4Length); + + 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 { + kalMemZero(prCmdInfo->pucInfoBuffer, u4Length); + } + } else { + prCmdInfo->pucInfoBuffer = NULL; + } + } + + if (prCmdInfo) { + DBGLOG(MEM, LOUD, "CMD[0x%p] allocated! LEN[%04u], Rest[%u]\n", + prCmdInfo, u4Length, prAdapter->rFreeCmdList.u4NumElem); + } else { + DBGLOG(MEM, WARN, + "CMD allocation failed! LEN[%04u], Rest[%u]\n", + u4Length, prAdapter->rFreeCmdList.u4NumElem); + } + + 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); + + 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); + } + + if (prCmdInfo) + DBGLOG(MEM, LOUD, "CMD[0x%p] freed! Rest[%u]\n", prCmdInfo, prAdapter->rFreeCmdList.u4NumElem); + + return; + +} /* end of cmdBufFreeCmdPacket() */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic.c new file mode 100644 index 0000000000000..b47ddc7fb609b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic.c @@ -0,0 +1,3712 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic.c#4 +*/ + +/*! \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. +*/ + + +/******************************************************************************* +* C O M P I L E 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 */ + PHY_TYPE_SET_802_11AC, + PHY_TYPE_SET_802_11ANAC, + PHY_TYPE_SET_802_11ABGNAC +}; + +/******************************************************************************* +* 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 */ +}; + +ECO_INFO_T g_eco_info = {0xFF}; +/******************************************************************************* +* 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 %u bytes for %s.\n", \ + u4Size, (char *)pucComment); \ + pucMem = (PUINT_8)kalMemAlloc(u4Size, eMemType); \ + if (pucMem == (PUINT_8)NULL) { \ + DBGLOG(INIT, ERROR, \ + "Could not allocate %u bytes for %s.\n", \ + u4Size, (char *)pucComment); \ + break; \ + } \ + ASSERT(((ULONG)pucMem % 4) == 0); \ + DBGLOG(INIT, INFO, "Virtual Address = 0x%p for %s.\n", \ + (void *)pucMem, (char *)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; + + /* 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; + +#ifdef CFG_PREALLOC_MEMORY + prAdapter->pucMgtBufCached = preallocGetMem(MEM_ID_NIC_ADAPTER); +#else + LOCAL_NIC_ALLOCATE_MEMORY(prAdapter->pucMgtBufCached, + prAdapter->u4MgtBufCachedSize, PHY_MEM_TYPE, "COMMON MGMT MEMORY POOL"); +#endif + + /* 4 <2> Memory for RX Descriptor */ + /* Initialize the number of rx buffers we will have in our queue. */ + /* We may setup ucRxPacketDescriptors by GLUE Layer, and using + * this variable directly. + */ + /* Allocate memory for the SW receive structures. */ + prRxCtrl->u4RxCachedSize = CFG_RX_MAX_PKT_NUM * ALIGN_4(sizeof(SW_RFB_T)); + + LOCAL_NIC_ALLOCATE_MEMORY(prRxCtrl->pucRxCached, prRxCtrl->u4RxCachedSize, VIR_MEM_TYPE, "SW_RFB_T"); + + /* 4 <3> Memory for TX DEscriptor */ + prTxCtrl->u4TxCachedSize = CFG_TX_MAX_PKT_NUM * ALIGN_4(sizeof(MSDU_INFO_T)); + + LOCAL_NIC_ALLOCATE_MEMORY(prTxCtrl->pucTxCached, prTxCtrl->u4TxCachedSize, VIR_MEM_TYPE, "MSDU_INFO_T"); + + /* 4 <4> Memory for Common Coalescing Buffer */ + + /* Get valid buffer size based on config & host capability */ + prAdapter->u4CoalescingBufCachedSize = halGetValidCoalescingBufSize(prAdapter); + + /* Allocate memory for the common coalescing buffer. */ +#ifdef CFG_PREALLOC_MEMORY + prAdapter->pucCoalescingBufCached = + preallocGetMem(MEM_ID_IO_BUFFER); +#else + prAdapter->pucCoalescingBufCached = kalAllocateIOBuffer(prAdapter->u4CoalescingBufCachedSize); +#endif + + if (prAdapter->pucCoalescingBufCached == NULL) { + DBGLOG(INIT, ERROR, + "Could not allocate %u bytes for coalescing buffer.\n", + prAdapter->u4CoalescingBufCachedSize); + break; + } + + /* <5> Memory for HIF */ + if (halAllocateIOBuffer(prAdapter) != WLAN_STATUS_SUCCESS) + 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; + UINT_32 u4Idx; + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + + /* 4 <5> Memory for HIF */ + halReleaseIOBuffer(prAdapter); + + /* 4 <4> Memory for Common Coalescing Buffer */ + if (prAdapter->pucCoalescingBufCached) { +#ifndef CFG_PREALLOC_MEMORY + kalReleaseIOBuffer((PVOID) prAdapter->pucCoalescingBufCached, prAdapter->u4CoalescingBufCachedSize); +#endif + prAdapter->pucCoalescingBufCached = (PUINT_8) NULL; + } + + /* 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) { +#ifndef CFG_PREALLOC_MEMORY + kalMemFree((PVOID) prAdapter->pucMgtBufCached, PHY_MEM_TYPE, prAdapter->u4MgtBufCachedSize); +#endif + prAdapter->pucMgtBufCached = (PUINT_8) NULL; + } + + /* Memory for TX Desc Template */ + for (u4Idx = 0; u4Idx < CFG_STA_REC_NUM; u4Idx++) + nicTxFreeDescTemplate(prAdapter, &prAdapter->arStaRec[u4Idx]); + +#if CFG_DBG_MGT_BUF + do { + BOOLEAN fgUnfreedMem = FALSE; + P_BUF_INFO_T prBufInfo; + + /* Dynamic allocated memory from OS */ + if (prAdapter->u4MemFreeDynamicCount != prAdapter->u4MemAllocDynamicCount) + fgUnfreedMem = TRUE; + + /* MSG buffer */ + prBufInfo = &prAdapter->rMsgBufInfo; + if (prBufInfo->u4AllocCount != (prBufInfo->u4FreeCount + prBufInfo->u4AllocNullCount)) + fgUnfreedMem = TRUE; + + /* MGT buffer */ + prBufInfo = &prAdapter->rMgtBufInfo; + if (prBufInfo->u4AllocCount != (prBufInfo->u4FreeCount + prBufInfo->u4AllocNullCount)) + fgUnfreedMem = TRUE; + + /* Check if all allocated memories are free */ + if (fgUnfreedMem) { + DBGLOG(MEM, ERROR, "Unequal memory alloc/free count!\n"); + + qmDumpQueueStatus(prAdapter, NULL, 0); + cnmDumpMemoryStatus(prAdapter, NULL, 0); + } + + if (!wlanIsChipNoAck(prAdapter)) { + /* Skip this ASSERT if chip is no ACK */ + ASSERT(prAdapter->u4MemFreeDynamicCount == prAdapter->u4MemAllocDynamicCount); + } + } while (FALSE); +#endif + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief disable global interrupt +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicDisableInterrupt(IN P_ADAPTER_T prAdapter) +{ + halDisableInterrupt(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief enable global interrupt +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicEnableInterrupt(IN P_ADAPTER_T prAdapter) +{ + halEnableInterrupt(prAdapter); + +} /* end of nicEnableInterrupt() */ + +#if 0 /* CFG_SDIO_INTR_ENHANCE */ +/*----------------------------------------------------------------------------*/ +/*! +* @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->rTxInfo.au4WTSR[2] + | prSDIOCtrl->rTxInfo.au4WTSR[3] + | prSDIOCtrl->rTxInfo.au4WTSR[4] + | prSDIOCtrl->rTxInfo.au4WTSR[5] + | prSDIOCtrl->rTxInfo.au4WTSR[6] + | prSDIOCtrl->rTxInfo.au4WTSR[7])) { + prSDIOCtrl->u4WHISR |= WHISR_TX_DONE_INT; + } + + if ((prSDIOCtrl->u4WHISR & BIT(31)) == 0 && + HAL_GET_MAILBOX_READ_CLEAR(prAdapter) == TRUE && + (prSDIOCtrl->u4RcvMailbox0 != 0 || prSDIOCtrl->u4RcvMailbox1 != 0)) { + prSDIOCtrl->u4WHISR |= BIT(31); + } + + *pu4IntStatus = prSDIOCtrl->u4WHISR; + +} /* end of nicSDIOReadIntStatus() */ +#endif + +#if 0 /*defined(_HIF_PCIE) */ +VOID nicPCIEReadIntStatus(IN P_ADAPTER_T prAdapter, OUT PUINT_32 pu4IntStatus) +{ + UINT_32 u4RegValue; + + *pu4IntStatus = 0; + + HAL_MCR_RD(prAdapter, WPDMA_INT_STA, &u4RegValue); + + if (HAL_IS_RX_DONE_INTR(u4RegValue)) + *pu4IntStatus |= WHISR_RX0_DONE_INT; + + if (HAL_IS_TX_DONE_INTR(u4RegValue)) + *pu4IntStatus |= WHISR_TX_DONE_INT; + + /* clear interrupt */ + HAL_MCR_WR(prAdapter, WPDMA_INT_STA, u4RegValue); + +} +#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; + + 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; + } + + for (i = 0; i < prAdapter->rWifiVar.u4HifIstLoopCount; i++) { + + HAL_READ_INT_STATUS(prAdapter, &u4IntStatus); + /* DBGLOG(INIT, TRACE, ("u4IntStatus: 0x%x\n", u4IntStatus)); */ + + if (u4IntStatus == 0) { + if (i == 0) + u4Status = WLAN_STATUS_NOT_INDICATING; + break; + } + + nicProcessIST_impl(prAdapter, u4IntStatus); + + /* Have to TX now. Skip RX polling ASAP */ + if (test_bit(GLUE_FLAG_HIF_TX_CMD_BIT, &prAdapter->prGlueInfo->ulFlag) + || test_bit(GLUE_FLAG_HIF_TX_BIT, &prAdapter->prGlueInfo->ulFlag)) { + i *= 2; + } + } + + 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 (0/*prIntEventMap->u4Event == INT_EVENT_RX && prAdapter->fgIsEnterD3ReqIssued == TRUE*/) { + /* ignore */ + } else if (apfnEventFuncTable[prIntEventMap->u4Event] != NULL) { + apfnEventFuncTable[prIntEventMap->u4Event] (prAdapter); + } else { + DBGLOG(INTR, WARN, + "Empty INTR handler! ISAR bit#: %u, event:%u, func: 0x%p\n", + prIntEventMap->u4Int, prIntEventMap->u4Event, + apfnEventFuncTable[prIntEventMap->u4Event]); + + ASSERT(0); /* to trap any NULL interrupt handler */ + } + prAdapter->u4IntStatus &= ~prIntEventMap->u4Int; + } + } + + return WLAN_STATUS_SUCCESS; +} /* end of nicProcessIST_impl() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Verify the CHIP ID +* +* @param prAdapter a pointer to adapter private data structure. +* +* +* @retval TRUE CHIP ID is the same as the setting compiled +* @retval FALSE CHIP ID is different from the setting compiled +*/ +/*----------------------------------------------------------------------------*/ +BOOL nicVerifyChipID(IN P_ADAPTER_T prAdapter) +{ + return halVerifyChipID(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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; + prAdapter->fgIsReadRevID = FALSE; + +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1) + prAdapter->fgIsBufferBinExtract = FALSE; + + prAdapter->u4EfuseMacAddrOffset = DEFAULT_EFUSE_MACADDR_OFFSET; +#endif + + do { + if (!nicVerifyChipID(prAdapter)) { + u4Status = WLAN_STATUS_FAILURE; + break; + } + /* 4 <1> MCR init */ + nicMCRInit(prAdapter); + + HAL_HIF_INIT(prAdapter); + + /* 4 <2> init FW HIF */ + nicHifInit(prAdapter); + } while (FALSE); + + return u4Status; +} + +#if defined(_HIF_SPI) +/*----------------------------------------------------------------------------*/ +/*! +* \brief Restore the SPI Mode Select to default mode, +* this is important while driver is unload, and this must be last mcr +* since the operation will let the hif use 8bit mode access +* +* \param[in] prAdapter a pointer to adapter private data structure. +* \param[in] eGPIO2_Mode GPIO2 operation mode +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void nicRestoreSpiDefMode(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + HAL_MCR_WR(prAdapter, MCR_WCSR, SPICSR_8BIT_MODE_DATA); + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process rx interrupt. When the rx +* Interrupt is asserted, it means there are frames in queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicProcessAbnormalInterrupt(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4Value = 0; + + HAL_MCR_RD(prAdapter, MCR_WASR, &u4Value); + DBGLOG(REQ, WARN, "MCR_WASR: 0x%x\n", u4Value); +#if CFG_CHIP_RESET_SUPPORT + glResetTrigger(prAdapter); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief . +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicProcessFwOwnBackInterrupt(IN P_ADAPTER_T prAdapter) +{ + +} /* end of nicProcessFwOwnBackInterrupt() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief . +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicProcessSoftwareInterrupt(IN P_ADAPTER_T prAdapter) +{ + halProcessSoftwareInterrupt(prAdapter); +} /* end of nicProcessSoftwareInterrupt() */ + +VOID nicSetSwIntr(IN P_ADAPTER_T prAdapter, IN UINT_32 u4SwIntrBitmap) +{ + /* NOTE: + * SW interrupt in HW bit 16 is mapping to SW bit 0 (shift 16bit in HW transparancy) + * SW interrupt valid from b0~b15 + */ + ASSERT((u4SwIntrBitmap & BITS(0, 15)) == 0); +/* DBGLOG(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; + + 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 ucWlanIndex, IN UINT_8 ucPID) +{ + 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->ucPID == ucPID) && (prMsduInfo->ucWlanIndex == ucWlanIndex)) + break; + + QUEUE_INSERT_TAIL(prTxingQue, prQueueEntry); + + prMsduInfo = NULL; + + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); + } + QUEUE_CONCATENATE_QUEUES(prTxingQue, prTempQue); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + if (prMsduInfo) { + DBGLOG(TX, TRACE, "Get Msdu WIDX:PID[%u:%u] SEQ[%u] from Pending Q\n", + prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, prMsduInfo->ucTxSeqNum); + } else { + DBGLOG(TX, WARN, "Cannot get Target Msdu WIDX:PID[%u:%u] from Pending Q\n", ucWlanIndex, ucPID); + } + + return prMsduInfo; +} + +VOID nicFreePendingTxMsduInfoByBssIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex) +{ + 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 (prMsduInfo->ucBssIndex == ucBssIndex) { + DBGLOG(TX, TRACE, "%s: Get Msdu WIDX:PID[%u:%u] SEQ[%u] from Pending Q\n", + __func__, prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, prMsduInfo->ucTxSeqNum); + + 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); + nicTxReturnMsduInfo(prAdapter, prMsduInfoListHead); + } + + return; + +} /* end of nicFreePendingTxMsduInfoByBssIdx() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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); + + ucRetval = prAdapter->ucTxSeqNum; + + 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 UINT_8 ucBssIndex, IN P_EVENT_CONNECTION_STATUS prConnectionStatus) +{ + P_GLUE_INFO_T prGlueInfo; + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + + switch (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType) { + case NETWORK_TYPE_AIS: + 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: + break; +#endif + +#if CFG_ENABLE_WIFI_DIRECT + case NETWORK_TYPE_P2P: + break; +#endif + default: + ASSERT(0); + } + + return WLAN_STATUS_SUCCESS; +} /* nicMediaStateChange */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to generate a join failure event to OS +* +* @param +* +* @retval +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicMediaJoinFailure(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN WLAN_STATUS rStatus) +{ + P_GLUE_INFO_T prGlueInfo; + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + + switch (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType) { + case NETWORK_TYPE_AIS: + kalIndicateStatusAndComplete(prGlueInfo, rStatus, NULL, 0); + + break; + + case NETWORK_TYPE_BOW: + case NETWORK_TYPE_P2P: + default: + break; + } + + return WLAN_STATUS_SUCCESS; +} /* end of nicMediaJoinFailure() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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 <= 181) || (u4ChannelNum == 16)) + u4ChannelInMHz = 5000 + u4ChannelNum * 5; + else if (u4ChannelNum >= 182 && u4ChannelNum <= 196) + u4ChannelInMHz = 4000 + u4ChannelNum * 5; + else if (u4ChannelNum == 201) + u4ChannelInMHz = 2730; + else if (u4ChannelNum == 202) + u4ChannelInMHz = 2498; + 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 5310000: + return 62; + case 5320000: + return 64; + case 5500000: + return 100; + case 5510000: + return 102; + case 5520000: + return 104; + case 5530000: + return 106; + case 5540000: + return 108; + case 5550000: + return 110; + case 5560000: + return 112; + case 5570000: + return 114; + case 5580000: + return 116; + case 5590000: + return 118; + case 5600000: + return 120; + case 5610000: + return 122; + case 5620000: + return 124; + case 5630000: + return 126; + case 5640000: + return 128; + case 5660000: + return 132; + case 5670000: + return 134; + case 5680000: + return 136; + case 5690000: + return 138; + case 5700000: + return 140; + case 5710000: + return 142; + case 5720000: + return 144; + case 5745000: + return 149; + case 5755000: + return 151; + case 5765000: + return 153; + case 5775000: + return 155; + case 5785000: + return 157; + case 5795000: + return 159; + case 5805000: + return 161; + case 5825000: + return 165; + case 5845000: + return 169; + case 5865000: + return 173; + default: + DBGLOG(BSS, INFO, "Return Invalid Channelnum = 0.\n"); + return 0; + } +} + +UINT_8 nicGetVhtS1(UINT_8 ucPrimaryChannel, UINT_8 ucBandwidth) +{ + /* find S1 (central channel 42, 58, 106, 122, and 155) */ + + if ((ucBandwidth == VHT_OP_CHANNEL_WIDTH_80) || (ucBandwidth == VHT_OP_CHANNEL_WIDTH_80P80)) { + + if (ucPrimaryChannel >= 36 && ucPrimaryChannel <= 48) + return 42; + else if (ucPrimaryChannel >= 52 && ucPrimaryChannel <= 64) + return 58; + else if (ucPrimaryChannel >= 100 && ucPrimaryChannel <= 112) + return 106; + else if (ucPrimaryChannel >= 116 && ucPrimaryChannel <= 128) + return 122; + else if (ucPrimaryChannel >= 132 && ucPrimaryChannel <= 144) + return 138; + else if (ucPrimaryChannel >= 149 && ucPrimaryChannel <= 161) + return 155; + + } else if (ucBandwidth == VHT_OP_CHANNEL_WIDTH_160) { + + if (ucPrimaryChannel >= 36 && ucPrimaryChannel <= 64) + return 50; + else if (ucPrimaryChannel >= 100 && ucPrimaryChannel <= 128) + return 114; + + } else { + + return 0; + } + + 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 UINT_8 ucBssIndex) +{ + CMD_BSS_ACTIVATE_CTRL rCmdActivateCtrl; + P_BSS_INFO_T prBssInfo; +/* const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; */ + + ASSERT(prAdapter); + ASSERT(IS_BSS_INDEX_VALID(ucBssIndex)); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + prBssInfo->fg40mBwAllowed = FALSE; + prBssInfo->fgAssoc40mBwAllowed = FALSE; + + rCmdActivateCtrl.ucBssIndex = ucBssIndex; + rCmdActivateCtrl.ucActive = 1; + rCmdActivateCtrl.ucNetworkType = (UINT_8) prBssInfo->eNetworkType; + rCmdActivateCtrl.ucOwnMacAddrIndex = prBssInfo->ucOwnMacIndex; + COPY_MAC_ADDR(rCmdActivateCtrl.aucBssMacAddr, prBssInfo->aucOwnMacAddr); + + prBssInfo->ucBMCWlanIndex = + secPrivacySeekForBcEntry(prAdapter, prBssInfo->ucBssIndex, + prBssInfo->aucOwnMacAddr, STA_REC_INDEX_NOT_FOUND, CIPHER_SUITE_NONE, 0xFF); + rCmdActivateCtrl.ucBMCWlanIndex = prBssInfo->ucBMCWlanIndex; + + kalMemZero(&rCmdActivateCtrl.ucReserved, sizeof(rCmdActivateCtrl.ucReserved)); + +#if 1 /* DBG */ + DBGLOG(RSN, INFO, "[wlan index][Network]=%d activate=%d\n", ucBssIndex, 1); + DBGLOG(RSN, INFO, + "[wlan index][Network] OwnMac=" MACSTR " BSSID=" MACSTR " BMCIndex = %d NetType=%d\n", + MAC2STR(prBssInfo->aucOwnMacAddr), MAC2STR(prBssInfo->aucBSSID), + prBssInfo->ucBMCWlanIndex, prBssInfo->eNetworkType); +#endif + + 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 UINT_8 ucBssIndex) +{ + WLAN_STATUS u4Status; + CMD_BSS_ACTIVATE_CTRL rCmdActivateCtrl; + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(IS_BSS_INDEX_VALID(ucBssIndex)); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + kalMemZero(&rCmdActivateCtrl, sizeof(CMD_BSS_ACTIVATE_CTRL)); + + rCmdActivateCtrl.ucBssIndex = ucBssIndex; + rCmdActivateCtrl.ucActive = 0; + +#if 1 /* DBG */ + DBGLOG(RSN, INFO, "[wlan index][Network]=%d activate=%d\n", ucBssIndex, 0); + DBGLOG(RSN, INFO, + "[wlan index][Network] OwnMac=" MACSTR " BSSID=" MACSTR " BMCIndex = %d\n", + MAC2STR(prBssInfo->aucOwnMacAddr), MAC2STR(prBssInfo->aucBSSID), prBssInfo->ucBMCWlanIndex); +#endif + rCmdActivateCtrl.ucOwnMacAddrIndex = prBssInfo->ucOwnMacIndex; + /* 20170628, if deactive bssid, do not reset NetworkType, otherwise we cannot free bcn */ + rCmdActivateCtrl.ucNetworkType = (UINT_8) prBssInfo->eNetworkType; + + u4Status = wlanSendSetQueryCmd(prAdapter, + CMD_ID_BSS_ACTIVATE_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, sizeof(CMD_BSS_ACTIVATE_CTRL), (PUINT_8)&rCmdActivateCtrl, NULL, 0); + + secRemoveBssBcEntry(prAdapter, prBssInfo, FALSE); + + /* free all correlated station records */ + cnmStaFreeAllStaByNetwork(prAdapter, ucBssIndex, STA_REC_EXCLUDE_NONE); + if (HAL_IS_TX_DIRECT(prAdapter)) + nicTxDirectClearBssAbsentQ(prAdapter, ucBssIndex); + else + qmFreeAllByBssIdx(prAdapter, ucBssIndex); + nicFreePendingTxMsduInfoByBssIdx(prAdapter, ucBssIndex); + kalClearSecurityFramesByBssIdx(prAdapter->prGlueInfo, ucBssIndex); +#if (CFG_HW_WMM_BY_BSS == 1) + cnmFreeWmmIndex(prAdapter, prBssInfo); +#endif + 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 +* ucBssIndex Index of BSS-INFO +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicUpdateBss(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex) +{ + WLAN_STATUS u4Status = WLAN_STATUS_NOT_ACCEPTED; + P_BSS_INFO_T prBssInfo; + CMD_SET_BSS_INFO rCmdSetBssInfo; + P_WIFI_VAR_T prWifiVar = &prAdapter->rWifiVar; + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= MAX_BSS_INDEX); + + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + + if ((prBssInfo->eDBDCBand != ENUM_BAND_0) && (prBssInfo->eDBDCBand != ENUM_BAND_1)) { + DBGLOG(BSS, ERROR, "Wrong eDBDCBand - [%u]\n", prBssInfo->eDBDCBand); + prBssInfo->eDBDCBand = ENUM_BAND_0; /* Work around : temp solution */ + /*ASSERT(0);*/ /* FATAL ERROR */ + } + + kalMemZero(&rCmdSetBssInfo, sizeof(CMD_SET_BSS_INFO)); + + rCmdSetBssInfo.ucBssIndex = ucBssIndex; + 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.u2HwDefaultFixedRateCode = prBssInfo->u2HwDefaultFixedRateCode; + rCmdSetBssInfo.ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + rCmdSetBssInfo.u4PrivateData = prBssInfo->u4PrivateData; +#if CFG_SUPPORT_DBDC + rCmdSetBssInfo.ucDBDCBand = prBssInfo->eDBDCBand; +#endif + rCmdSetBssInfo.ucWmmSet = prBssInfo->ucWmmQueSet; + rCmdSetBssInfo.ucNss = prBssInfo->ucNss; + + if (prBssInfo->fgBcDefaultKeyExist) { + if (prBssInfo->wepkeyUsed[prBssInfo->ucBcDefaultKeyIdx] && + prBssInfo->wepkeyWlanIdx < NIC_TX_DEFAULT_WLAN_INDEX) + rCmdSetBssInfo.ucBMCWlanIndex = prBssInfo->wepkeyWlanIdx; + else if (prBssInfo->ucBMCWlanIndexSUsed[prBssInfo->ucBcDefaultKeyIdx]) + rCmdSetBssInfo.ucBMCWlanIndex = prBssInfo->ucBMCWlanIndexS[prBssInfo->ucBcDefaultKeyIdx]; + } else + rCmdSetBssInfo.ucBMCWlanIndex = prBssInfo->ucBMCWlanIndex; + DBGLOG(RSN, TRACE, "Update BSS BMC WlanIdx %u\n", rCmdSetBssInfo.ucBMCWlanIndex); + + +#ifdef CFG_ENABLE_WIFI_DIRECT + rCmdSetBssInfo.ucHiddenSsidMode = prBssInfo->eHiddenSsidType; +#endif + rlmFillSyncCmdParam(&rCmdSetBssInfo.rBssRlmParam, prBssInfo); + + rCmdSetBssInfo.ucWapiMode = (UINT_8) FALSE; + + if (rCmdSetBssInfo.ucBssIndex == prAdapter->prAisBssInfo->ucBssIndex) { + P_CONNECTION_SETTINGS_T prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + rCmdSetBssInfo.ucAuthMode = (UINT_8) prConnSettings->eAuthMode; + rCmdSetBssInfo.ucEncStatus = (UINT_8) prConnSettings->eEncStatus; + rCmdSetBssInfo.ucWapiMode = (UINT_8) prConnSettings->fgWapiMode; + rCmdSetBssInfo.ucDisconnectDetectTh = prWifiVar->ucStaDisconnectDetectTh; + } +#if CFG_ENABLE_BT_OVER_WIFI + else if (IS_BSS_BOW(prBssInfo)) { + 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 CFG_SUPPORT_SUITB + if (kalP2PGetGcmp256Cipher(prAdapter->prGlueInfo, + (UINT_8) prBssInfo->u4PrivateData)) { + rCmdSetBssInfo.ucAuthMode = + (UINT_8) AUTH_MODE_WPA2_PSK; + rCmdSetBssInfo.ucEncStatus = + (UINT_8) ENUM_ENCRYPTION4_ENABLED; + } else +#endif + if (kalP2PGetCcmpCipher(prAdapter->prGlueInfo, + (UINT_8) prBssInfo->u4PrivateData)) { + rCmdSetBssInfo.ucAuthMode = (UINT_8) AUTH_MODE_WPA2_PSK; + rCmdSetBssInfo.ucEncStatus = (UINT_8) ENUM_ENCRYPTION3_ENABLED; + } else if (kalP2PGetTkipCipher(prAdapter->prGlueInfo, (UINT_8) prBssInfo->u4PrivateData)) { + rCmdSetBssInfo.ucAuthMode = (UINT_8) AUTH_MODE_WPA_PSK; + rCmdSetBssInfo.ucEncStatus = (UINT_8) ENUM_ENCRYPTION2_ENABLED; + } else if (kalP2PGetWepCipher(prAdapter->prGlueInfo, (UINT_8) prBssInfo->u4PrivateData)) { + rCmdSetBssInfo.ucAuthMode = (UINT_8) AUTH_MODE_OPEN; + rCmdSetBssInfo.ucEncStatus = (UINT_8) ENUM_ENCRYPTION1_ENABLED; + } 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.ucIsApMode = + p2pFuncIsAPMode(prAdapter->rWifiVar.prP2PConnSettings[prBssInfo->u4PrivateData]); + + if (rCmdSetBssInfo.ucIsApMode) + rCmdSetBssInfo.ucDisconnectDetectTh = prWifiVar->ucApDisconnectDetectTh; + else + rCmdSetBssInfo.ucDisconnectDetectTh = prWifiVar->ucP2pDisconnectDetectTh; + } +#else + rCmdSetBssInfo.ucAuthMode = (UINT_8) AUTH_MODE_WPA2_PSK; + rCmdSetBssInfo.ucEncStatus = (UINT_8) ENUM_ENCRYPTION3_KEY_ABSENT; +#endif + } + + if (ucBssIndex == prAdapter->prAisBssInfo->ucBssIndex && + prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE && prBssInfo->prStaRecOfAP != NULL) { + rCmdSetBssInfo.ucStaRecIdxOfAP = prBssInfo->prStaRecOfAP->ucIndex; + + cnmAisInfraConnectNotify(prAdapter); + } +#if CFG_ENABLE_WIFI_DIRECT + else if ((prAdapter->fgIsP2PRegistered) && + (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) && + (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) && (prBssInfo->prStaRecOfAP != NULL)) { + rCmdSetBssInfo.ucStaRecIdxOfAP = prBssInfo->prStaRecOfAP->ucIndex; + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI /* disabled for BOW to finish ucBssIndex migration */ + else if (prBssInfo->eNetworkType == NETWORK_TYPE_BOW && + prBssInfo->eCurrentOPMode == OP_MODE_BOW && prBssInfo->prStaRecOfAP != NULL) { + rCmdSetBssInfo.ucStaRecIdxOfAP = prBssInfo->prStaRecOfAP->ucIndex; + } +#endif + else + rCmdSetBssInfo.ucStaRecIdxOfAP = STA_REC_INDEX_NOT_FOUND; + + DBGLOG(BSS, INFO, + "Update Bss[%u] ConnState[%u] OPmode[%u] BSSID[" MACSTR + "] AuthMode[%u] EncStatus[%u]\n", ucBssIndex, prBssInfo->eConnectionState, + prBssInfo->eCurrentOPMode, MAC2STR(prBssInfo->aucBSSID), rCmdSetBssInfo.ucAuthMode, + rCmdSetBssInfo.ucEncStatus); + + 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 */ + bssInitializeClientList(prAdapter, prBssInfo); + +#if DBG + DBGLOG(BSS, TRACE, "nicUpdateBss for disconnect state\n"); +#endif + /* free all correlated station records */ + cnmStaFreeAllStaByNetwork(prAdapter, ucBssIndex, STA_REC_EXCLUDE_NONE); + if (HAL_IS_TX_DIRECT(prAdapter)) + nicTxDirectClearBssAbsentQ(prAdapter, ucBssIndex); + else + qmFreeAllByBssIdx(prAdapter, ucBssIndex); + kalClearSecurityFramesByBssIdx(prAdapter->prGlueInfo, ucBssIndex); +#if CFG_ENABLE_GTK_FRAME_FILTER + if (prBssInfo->prIpV4NetAddrList) + FREE_IPV4_NETWORK_ADDR_LIST(prBssInfo->prIpV4NetAddrList); +#endif +#if CFG_SUPPORT_DBDC + cnmDbdcDisableDecision(prAdapter, ucBssIndex); +#endif + } + + return u4Status; +} + +/* BSS-INFO Indication (PM) */ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to indicate PM that +* a BSS has been created. (for AdHoc / P2P-GO) +* +* @param prAdapter Pointer of ADAPTER_T +* ucBssIndex Index of BSS-INFO +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicPmIndicateBssCreated(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex) +{ + P_BSS_INFO_T prBssInfo; + CMD_INDICATE_PM_BSS_CREATED rCmdIndicatePmBssCreated; + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= MAX_BSS_INDEX); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + rCmdIndicatePmBssCreated.ucBssIndex = ucBssIndex; + 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 UINT_8 ucBssIndex) +{ + P_BSS_INFO_T prBssInfo; + CMD_INDICATE_PM_BSS_CONNECTED rCmdIndicatePmBssConnected; + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= MAX_BSS_INDEX); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + rCmdIndicatePmBssConnected.ucBssIndex = ucBssIndex; + 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 ((GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType == NETWORK_TYPE_AIS) +#if CFG_ENABLE_WIFI_DIRECT + || ((GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType == NETWORK_TYPE_P2P) + && (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 +* ucBssIndex Index of BSS-INFO +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicPmIndicateBssAbort(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex) +{ + CMD_INDICATE_PM_BSS_ABORT rCmdIndicatePmBssAbort; + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= MAX_BSS_INDEX); + + rCmdIndicatePmBssAbort.ucBssIndex = ucBssIndex; + + 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, + IN UINT_8 ucBssIndex, IN PARAM_POWER_MODE ePwrMode, IN BOOLEAN fgEnCmdEvent) +{ + DEBUGFUNC("nicConfigPowerSaveProfile"); + DBGLOG(INIT, TRACE, "ucBssIndex:%d, ePwrMode:%d, fgEnCmdEvent:%d\n", ucBssIndex, ePwrMode, fgEnCmdEvent); + + ASSERT(prAdapter); + + if (ucBssIndex >= BSS_INFO_NUM) { + ASSERT(0); + return WLAN_STATUS_NOT_SUPPORTED; + } +/* prAdapter->rWlanInfo.ePowerSaveMode.ucNetTypeIndex = eNetTypeIndex; */ +/* prAdapter->rWlanInfo.ePowerSaveMode.ucPsProfile = (UINT_8)ePwrMode; */ + prAdapter->rWlanInfo.arPowerSaveMode[ucBssIndex].ucBssIndex = ucBssIndex; + prAdapter->rWlanInfo.arPowerSaveMode[ucBssIndex].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[ucBssIndex]), + NULL, sizeof(PARAM_POWER_MODE) + ); + +} /* end of wlanoidSetAcpiDevicePowerStateMode() */ + +WLAN_STATUS +nicConfigPowerSaveWowProfile(IN P_ADAPTER_T prAdapter, UINT_8 ucBssIndex, PARAM_POWER_MODE ePwrMode, + BOOLEAN fgEnCmdEvent, BOOLEAN fgSuspend) { + + CMD_PS_PROFILE_T rPowerSaveMode; + + if (fgSuspend) { + + rPowerSaveMode.ucBssIndex = ucBssIndex; + rPowerSaveMode.ucPsProfile = ePwrMode; + + /* if suspend, config power save mode w/o update arPowerSaveMode[ucBssIndex] */ + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_POWER_SAVE_MODE, + TRUE, + FALSE, + TRUE, + (fgEnCmdEvent ? nicCmdEventSetCommon : NULL), + (fgEnCmdEvent ? nicOidCmdTimeoutCommon : NULL), + sizeof(CMD_PS_PROFILE_T), + (PUINT_8)&rPowerSaveMode, + NULL, sizeof(PARAM_POWER_MODE) + ); + + } else { + + /* if resume, restore power save profile */ + 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[ucBssIndex]), + NULL, sizeof(PARAM_POWER_MODE) + ); + } +} + +WLAN_STATUS nicEnterCtiaMode(IN P_ADAPTER_T prAdapter, BOOLEAN fgEnterCtia, BOOLEAN fgEnCmdEvent) +{ + CMD_SW_DBG_CTRL_T rCmdSwCtrl; + /* CMD_ACCESS_REG rCmdAccessReg; */ + WLAN_STATUS rWlanStatus; + + DEBUGFUNC("nicEnterCtiaMode"); + DBGLOG(INIT, TRACE, "nicEnterCtiaMode: %d\n", fgEnterCtia); + + ASSERT(prAdapter); + + rWlanStatus = WLAN_STATUS_SUCCESS; + + if (fgEnterCtia) { + /* 1. Disable On-Lin Scan */ + prAdapter->fgEnOnlineScan = FALSE; + + /* 2. Disable FIFO FULL no ack */ + /* 3. Disable Roaming */ + /* 4. Disalbe auto tx power */ + rCmdSwCtrl.u4Id = 0xa0100003; + rCmdSwCtrl.u4Data = 0x0; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); + + /* 2. Keep at CAM mode */ + { + PARAM_POWER_MODE ePowerMode; + + prAdapter->u4CtiaPowerMode = 0; + prAdapter->fgEnCtiaPowerMode = TRUE; + + ePowerMode = Param_PowerModeCAM; + rWlanStatus = nicConfigPowerSaveProfile(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, + ePowerMode, fgEnCmdEvent); + } + + /* 5. Disable Beacon Timeout Detection */ + prAdapter->fgDisBcnLostDetection = TRUE; + } else { + /* 1. Enaable On-Lin Scan */ + prAdapter->fgEnOnlineScan = TRUE; + + /* 2. Enable FIFO FULL no ack */ + /* 3. Enable Roaming */ + /* 4. Enable auto tx power */ + /* */ + + rCmdSwCtrl.u4Id = 0xa0100003; + rCmdSwCtrl.u4Data = 0x1; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); + + /* 2. Keep at Fast PS */ + { + PARAM_POWER_MODE ePowerMode; + + prAdapter->u4CtiaPowerMode = 2; + prAdapter->fgEnCtiaPowerMode = TRUE; + + ePowerMode = Param_PowerModeFast_PSP; + rWlanStatus = nicConfigPowerSaveProfile(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, + ePowerMode, fgEnCmdEvent); + } + + /* 5. Enable Beacon Timeout Detection */ + prAdapter->fgDisBcnLostDetection = FALSE; + + } + + return rWlanStatus; +} /* end of nicEnterCtiaMode() */ + +WLAN_STATUS nicEnterTPTestMode(IN P_ADAPTER_T prAdapter, IN UINT_8 ucFuncMask) +{ + CMD_SW_DBG_CTRL_T rCmdSwCtrl; + WLAN_STATUS rWlanStatus; + UINT_8 ucBssIdx; + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + + rWlanStatus = WLAN_STATUS_SUCCESS; + + if (ucFuncMask) { + /* 1. Disable On-Lin Scan */ + if (ucFuncMask & TEST_MODE_DISABLE_ONLINE_SCAN) + prAdapter->fgEnOnlineScan = FALSE; + + /* 2. Disable Roaming */ + if (ucFuncMask & TEST_MODE_DISABLE_ROAMING) { + rCmdSwCtrl.u4Id = 0xa0210000; + rCmdSwCtrl.u4Data = 0x0; + wlanSendSetQueryCmd(prAdapter, CMD_ID_SW_DBG_CTRL, TRUE, FALSE, FALSE, + NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); + } + /* 3. Keep at CAM mode */ + if (ucFuncMask & TEST_MODE_FIXED_CAM_MODE) + for (ucBssIdx = 0; ucBssIdx < BSS_INFO_NUM; ucBssIdx++) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + if (prBssInfo->fgIsInUse && (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE)) + nicConfigPowerSaveProfile(prAdapter, ucBssIdx, Param_PowerModeCAM, FALSE); + } + + /* 4. Disable Beacon Timeout Detection */ + if (ucFuncMask & TEST_MODE_DISABLE_BCN_LOST_DET) + prAdapter->fgDisBcnLostDetection = TRUE; + } else { + /* 1. Enaable On-Lin Scan */ + prAdapter->fgEnOnlineScan = TRUE; + + /* 2. Enable Roaming */ + rCmdSwCtrl.u4Id = 0xa0210000; + rCmdSwCtrl.u4Data = 0x1; + wlanSendSetQueryCmd(prAdapter, CMD_ID_SW_DBG_CTRL, TRUE, FALSE, FALSE, + NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); + + /* 3. Keep at Fast PS */ + for (ucBssIdx = 0; ucBssIdx < BSS_INFO_NUM; ucBssIdx++) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + if (prBssInfo->fgIsInUse && (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE)) + nicConfigPowerSaveProfile(prAdapter, ucBssIdx, Param_PowerModeFast_PSP, FALSE); + } + + /* 4. Enable Beacon Timeout Detection */ + prAdapter->fgDisBcnLostDetection = FALSE; + } + + return rWlanStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to indicate firmware domain +* for beacon generation parameters +* +* @param prAdapter Pointer of ADAPTER_T +* eIeUpdMethod, Update Method +* ucBssIndex Index of BSS-INFO +* 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 UINT_8 ucBssIndex, 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"); + + 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 { + DBGLOG(INIT, ERROR, "Unknown IeUpdMethod.\n"); + 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"); + 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->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->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 = prCmdInfo->u2InfoBufLen; + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + 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->ucBssIndex = ucBssIndex; + prCmdBcnUpdate->u2Capability = u2Capability; + prCmdBcnUpdate->u2IELen = u2IELen; + if (u2IELen > 0) + kalMemCopy(prCmdBcnUpdate->aucIE, aucIe, u2IELen); + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + return WLAN_STATUS_PENDING; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to initialization PHY related +* varaibles +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicSetAvailablePhyTypeSet(IN P_ADAPTER_T prAdapter) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + + ASSERT(prAdapter); + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + if (prConnSettings->eDesiredPhyConfig >= PHY_CONFIG_NUM) { + ASSERT(0); + return; + } + + prAdapter->rWifiVar.ucAvailablePhyTypeSet = aucPhyCfg2PhyTypeSet[prConnSettings->eDesiredPhyConfig]; + + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_BIT_ERP) + prAdapter->rWifiVar.eNonHTBasicPhyType2G4 = PHY_TYPE_ERP_INDEX; + /* NOTE(Kevin): Because we don't have N only mode, TBD */ + else /* if (ucNonHTPhyTypeSet & PHY_TYPE_HR_DSSS_INDEX) */ + prAdapter->rWifiVar.eNonHTBasicPhyType2G4 = PHY_TYPE_HR_DSSS_INDEX; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update WMM Parms +* +* @param prAdapter Pointer of ADAPTER_T +* ucBssIndex Index of BSS-INFO +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicQmUpdateWmmParms(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex) +{ + P_BSS_INFO_T prBssInfo; + CMD_UPDATE_WMM_PARMS_T rCmdUpdateWmmParms; + + ASSERT(prAdapter); + + DBGLOG(QM, INFO, "Update WMM parameters for BSS[%u]\n", ucBssIndex); + + DBGLOG(QM, EVENT, "sizeof(AC_QUE_PARMS_T): %zu\n", + sizeof(AC_QUE_PARMS_T)); + DBGLOG(QM, EVENT, "sizeof(CMD_UPDATE_WMM_PARMS): %zu\n", + sizeof(CMD_UPDATE_WMM_PARMS_T)); + DBGLOG(QM, EVENT, "sizeof(WIFI_CMD_T): %zu\n", sizeof(WIFI_CMD_T)); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + rCmdUpdateWmmParms.ucBssIndex = (UINT_8) ucBssIndex; + kalMemCopy(&rCmdUpdateWmmParms.arACQueParms[0], &prBssInfo->arACQueParms[0], (sizeof(AC_QUE_PARMS_T) * AC_NUM)); + + rCmdUpdateWmmParms.fgIsQBSS = prBssInfo->fgIsQBSS; + rCmdUpdateWmmParms.ucWmmSet = (UINT_8) prBssInfo->ucWmmQueSet; + + 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) +{ +#if 0 /* It is not needed anymore */ + 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); +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update DPD calibration result +* +* @param prAdapter Pointer of ADAPTER_T +* pr5GPwrOffset Pointer of parameter for DPD calibration result +* +* @retval WLAN_STATUS_PENDING +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicUpdateDPD(IN P_ADAPTER_T prAdapter, IN P_CMD_PWR_PARAM_T prDpdCalResult) +{ + DEBUGFUNC("nicUpdateDPD"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_PWR_PARAM, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_PWR_PARAM_T), (PUINT_8) prDpdCalResult, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function starts system service such as timer and +* memory pools +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicInitSystemService(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + /* <1> Initialize MGMT Memory pool and STA_REC */ + cnmMemInit(prAdapter); + cnmStaRecInit(prAdapter); + cmdBufInitialize(prAdapter); + + /* <2> Mailbox Initialization */ + mboxInitialize(prAdapter); + + /* <3> Timer Initialization */ + cnmTimerInitialize(prAdapter); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function reset some specific system service, +* such as STA-REC +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicResetSystemService(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update WMM Parms +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicUninitSystemService(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + /* Timer Destruction */ + cnmTimerDestroy(prAdapter); + + /* Mailbox Destruction */ + mboxDestroy(prAdapter); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update WMM Parms +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicInitMGMT(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo) +{ + ASSERT(prAdapter); + + /* CNM Module - initialization */ + cnmInit(prAdapter); + + /* RLM Module - initialization */ + rlmFsmEventInit(prAdapter); + + /* SCN Module - initialization */ + scnInit(prAdapter); + + /* AIS Module - intiailization */ + aisFsmInit(prAdapter); + aisInitializeConnectionSettings(prAdapter, prRegInfo); + +#if CFG_SUPPORT_ROAMING + /* Roaming Module - intiailization */ + roamingFsmInit(prAdapter); +#endif /* CFG_SUPPORT_ROAMING */ + +#if CFG_SUPPORT_SWCR + swCrDebugInit(prAdapter); +#endif /* CFG_SUPPORT_SWCR */ + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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 = ARRAY_SIZE(prAdapter->rWlanInfo.aucScanIEBuf); + + bReplace = FALSE; + + /* decide to replace or add */ + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + /* find weakest entry && not connected one */ + if (UNEQUAL_MAC_ADDR + (prAdapter->rWlanInfo.arScanResult[i].arMacAddress, prAdapter->rWlanInfo.rCurrBssId.arMacAddress) + && prAdapter->rWlanInfo.arScanResult[i].rRssi < rWeakestRssi) { + u4IdxWeakest = i; + rWeakestRssi = prAdapter->rWlanInfo.arScanResult[i].rRssi; + } + + if (prAdapter->rWlanInfo.arScanResult[i].eOpMode == eOpMode && + EQUAL_MAC_ADDR(&(prAdapter->rWlanInfo.arScanResult[i].arMacAddress), rMacAddr) + && + (EQUAL_SSID + (prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid, + prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen, prSsid->aucSsid, prSsid->u4SsidLen) + || prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen == 0)) { + /* replace entry */ + bReplace = TRUE; + + /* free IE buffer then zero */ + nicFreeScanResultIE(prAdapter, i); + kalMemZero(&(prAdapter->rWlanInfo.arScanResult[i]), OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); + + /* then fill buffer */ + prAdapter->rWlanInfo.arScanResult[i].u4Length = + OFFSET_OF(PARAM_BSSID_EX_T, aucIEs) + u2IELength; + COPY_MAC_ADDR(prAdapter->rWlanInfo.arScanResult[i].arMacAddress, rMacAddr); + COPY_SSID(prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid, + prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen, + prSsid->aucSsid, prSsid->u4SsidLen); + prAdapter->rWlanInfo.arScanResult[i].u4Privacy = u4Privacy; + prAdapter->rWlanInfo.arScanResult[i].rRssi = rRssi; + prAdapter->rWlanInfo.arScanResult[i].eNetworkTypeInUse = eNetworkType; + kalMemCopy(&(prAdapter->rWlanInfo.arScanResult[i].rConfiguration), + prConfiguration, sizeof(PARAM_802_11_CONFIG_T)); + prAdapter->rWlanInfo.arScanResult[i].eOpMode = eOpMode; + kalMemCopy((prAdapter->rWlanInfo.arScanResult[i].rSupportedRates), + rSupportedRates, sizeof(PARAM_RATES_EX)); + prAdapter->rWlanInfo.arScanResult[i].u4IELength = (UINT_32) u2IELength; + + /* IE - allocate buffer and update pointer */ + if (u2IELength > 0) { + if (ALIGN_4(u2IELength) + prAdapter->rWlanInfo.u4ScanIEBufferUsage <= u4BufferSize) { + kalMemCopy(& + (prAdapter->rWlanInfo. + aucScanIEBuf[prAdapter->rWlanInfo.u4ScanIEBufferUsage]), pucIEBuf, + u2IELength); + + prAdapter->rWlanInfo.apucScanResultIEs[i] = + &(prAdapter->rWlanInfo. + aucScanIEBuf[prAdapter->rWlanInfo.u4ScanIEBufferUsage]); + + prAdapter->rWlanInfo.u4ScanIEBufferUsage += ALIGN_4(u2IELength); + } else { + /* buffer is not enough */ + prAdapter->rWlanInfo.arScanResult[i].u4Length -= u2IELength; + prAdapter->rWlanInfo.arScanResult[i].u4IELength = 0; + prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; + } + } else { + prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; + } + + break; + } + } + + if (bReplace == FALSE) { + if (prAdapter->rWlanInfo.u4ScanResultNum < (CFG_MAX_NUM_BSS_LIST - 1)) { + i = prAdapter->rWlanInfo.u4ScanResultNum; + + /* zero */ + kalMemZero(&(prAdapter->rWlanInfo.arScanResult[i]), OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); + + /* then fill buffer */ + prAdapter->rWlanInfo.arScanResult[i].u4Length = + OFFSET_OF(PARAM_BSSID_EX_T, aucIEs) + u2IELength; + COPY_MAC_ADDR(prAdapter->rWlanInfo.arScanResult[i].arMacAddress, rMacAddr); + COPY_SSID(prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid, + prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen, + prSsid->aucSsid, prSsid->u4SsidLen); + prAdapter->rWlanInfo.arScanResult[i].u4Privacy = u4Privacy; + prAdapter->rWlanInfo.arScanResult[i].rRssi = rRssi; + prAdapter->rWlanInfo.arScanResult[i].eNetworkTypeInUse = eNetworkType; + kalMemCopy(&(prAdapter->rWlanInfo.arScanResult[i].rConfiguration), + prConfiguration, sizeof(PARAM_802_11_CONFIG_T)); + prAdapter->rWlanInfo.arScanResult[i].eOpMode = eOpMode; + kalMemCopy((prAdapter->rWlanInfo.arScanResult[i].rSupportedRates), + rSupportedRates, sizeof(PARAM_RATES_EX)); + prAdapter->rWlanInfo.arScanResult[i].u4IELength = (UINT_32) u2IELength; + + /* IE - allocate buffer and update pointer */ + if (u2IELength > 0) { + if (ALIGN_4(u2IELength) + prAdapter->rWlanInfo.u4ScanIEBufferUsage <= u4BufferSize) { + kalMemCopy(& + (prAdapter->rWlanInfo. + aucScanIEBuf[prAdapter->rWlanInfo.u4ScanIEBufferUsage]), pucIEBuf, + u2IELength); + + prAdapter->rWlanInfo.apucScanResultIEs[i] = + &(prAdapter->rWlanInfo. + aucScanIEBuf[prAdapter->rWlanInfo.u4ScanIEBufferUsage]); + + prAdapter->rWlanInfo.u4ScanIEBufferUsage += ALIGN_4(u2IELength); + } else { + /* buffer is not enough */ + prAdapter->rWlanInfo.arScanResult[i].u4Length -= u2IELength; + prAdapter->rWlanInfo.arScanResult[i].u4IELength = 0; + prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; + } + } else { + prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; + } + + prAdapter->rWlanInfo.u4ScanResultNum++; + } else if (rWeakestRssi != (PARAM_RSSI) INT_MAX) { + /* replace weakest one */ + i = u4IdxWeakest; + + /* free IE buffer then zero */ + nicFreeScanResultIE(prAdapter, i); + kalMemZero(&(prAdapter->rWlanInfo.arScanResult[i]), OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); + + /* then fill buffer */ + prAdapter->rWlanInfo.arScanResult[i].u4Length = + OFFSET_OF(PARAM_BSSID_EX_T, aucIEs) + u2IELength; + COPY_MAC_ADDR(prAdapter->rWlanInfo.arScanResult[i].arMacAddress, rMacAddr); + COPY_SSID(prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid, + prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen, + prSsid->aucSsid, prSsid->u4SsidLen); + prAdapter->rWlanInfo.arScanResult[i].u4Privacy = u4Privacy; + prAdapter->rWlanInfo.arScanResult[i].rRssi = rRssi; + prAdapter->rWlanInfo.arScanResult[i].eNetworkTypeInUse = eNetworkType; + kalMemCopy(&(prAdapter->rWlanInfo.arScanResult[i].rConfiguration), + prConfiguration, sizeof(PARAM_802_11_CONFIG_T)); + prAdapter->rWlanInfo.arScanResult[i].eOpMode = eOpMode; + kalMemCopy((prAdapter->rWlanInfo.arScanResult[i].rSupportedRates), + rSupportedRates, sizeof(PARAM_RATES_EX)); + prAdapter->rWlanInfo.arScanResult[i].u4IELength = (UINT_32) u2IELength; + + if (u2IELength > 0) { + /* IE - allocate buffer and update pointer */ + if (ALIGN_4(u2IELength) + prAdapter->rWlanInfo.u4ScanIEBufferUsage <= u4BufferSize) { + kalMemCopy(& + (prAdapter->rWlanInfo. + aucScanIEBuf[prAdapter->rWlanInfo.u4ScanIEBufferUsage]), pucIEBuf, + u2IELength); + + prAdapter->rWlanInfo.apucScanResultIEs[i] = + &(prAdapter->rWlanInfo. + aucScanIEBuf[prAdapter->rWlanInfo.u4ScanIEBufferUsage]); + + prAdapter->rWlanInfo.u4ScanIEBufferUsage += ALIGN_4(u2IELength); + } else { + /* buffer is not enough */ + prAdapter->rWlanInfo.arScanResult[i].u4Length -= u2IELength; + prAdapter->rWlanInfo.arScanResult[i].u4IELength = 0; + prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; + } + } else { + prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; + } + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is invoked to free IE buffer for dedicated scan result +* +* @param prAdapter Pointer to the Adapter structure. +* @param u4Idx Index of Scan Result +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicFreeScanResultIE(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Idx) +{ + UINT_32 i; + PUINT_8 pucPivot, pucMovePivot; + UINT_32 u4MoveSize, u4FreeSize, u4ReserveSize; + + ASSERT(prAdapter); + ASSERT(u4Idx < CFG_MAX_NUM_BSS_LIST); + + if (prAdapter->rWlanInfo.arScanResult[u4Idx].u4IELength == 0 + || prAdapter->rWlanInfo.apucScanResultIEs[u4Idx] == NULL) { + return; + } + + u4FreeSize = ALIGN_4(prAdapter->rWlanInfo.arScanResult[u4Idx].u4IELength); + + pucPivot = prAdapter->rWlanInfo.apucScanResultIEs[u4Idx]; + pucMovePivot = (PUINT_8) ((ULONG) (prAdapter->rWlanInfo.apucScanResultIEs[u4Idx]) + u4FreeSize); + + u4ReserveSize = ((ULONG) pucPivot) - (ULONG) (&(prAdapter->rWlanInfo.aucScanIEBuf[0])); + u4MoveSize = prAdapter->rWlanInfo.u4ScanIEBufferUsage - u4ReserveSize - u4FreeSize; + + /* 1. rest of buffer to move forward */ + kalMemCopy(pucPivot, pucMovePivot, u4MoveSize); + + /* 1.1 modify pointers */ + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + if (i != u4Idx) { + if (prAdapter->rWlanInfo.apucScanResultIEs[i] >= pucMovePivot) { + prAdapter->rWlanInfo.apucScanResultIEs[i] = + (PUINT_8) ((ULONG) (prAdapter->rWlanInfo.apucScanResultIEs[i]) + - u4FreeSize); + } + } + } + + /* 1.2 reset the freed one */ + prAdapter->rWlanInfo.arScanResult[u4Idx].u4IELength = 0; + prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; + + /* 2. reduce IE buffer usage */ + prAdapter->rWlanInfo.u4ScanIEBufferUsage -= u4FreeSize; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to hack parameters for WLAN TABLE for +* fixed rate settings +* +* @param prAdapter Pointer to the Adapter structure. +* @param eRateSetting +* @param pu2DesiredNonHTRateSet, +* @param pu2BSSBasicRateSet, +* @param pucMcsSet +* @param pucSupMcs32 +* @param pu2HtCapInfo +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicUpdateRateParams(IN P_ADAPTER_T prAdapter, + IN ENUM_REGISTRY_FIXED_RATE_T eRateSetting, + IN PUINT_8 pucDesiredPhyTypeSet, + IN PUINT_16 pu2DesiredNonHTRateSet, + IN PUINT_16 pu2BSSBasicRateSet, + IN PUINT_8 pucMcsSet, IN PUINT_8 pucSupMcs32, IN PUINT_16 pu2HtCapInfo) +{ + ASSERT(prAdapter); + ASSERT(eRateSetting > FIXED_RATE_NONE && eRateSetting < FIXED_RATE_NUM); + + switch (prAdapter->rWifiVar.eRateSetting) { + case FIXED_RATE_1M: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HR_DSSS; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_1M; + *pu2BSSBasicRateSet = RATE_SET_BIT_1M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_2M: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HR_DSSS; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_2M; + *pu2BSSBasicRateSet = RATE_SET_BIT_2M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_5_5M: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HR_DSSS; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_5_5M; + *pu2BSSBasicRateSet = RATE_SET_BIT_5_5M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_11M: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HR_DSSS; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_11M; + *pu2BSSBasicRateSet = RATE_SET_BIT_11M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_6M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_6M; + *pu2BSSBasicRateSet = RATE_SET_BIT_6M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_9M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_9M; + *pu2BSSBasicRateSet = RATE_SET_BIT_9M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_12M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_12M; + *pu2BSSBasicRateSet = RATE_SET_BIT_12M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_18M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_18M; + *pu2BSSBasicRateSet = RATE_SET_BIT_18M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_24M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_24M; + *pu2BSSBasicRateSet = RATE_SET_BIT_24M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_36M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_36M; + *pu2BSSBasicRateSet = RATE_SET_BIT_36M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_48M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_48M; + *pu2BSSBasicRateSet = RATE_SET_BIT_48M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_54M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_54M; + *pu2BSSBasicRateSet = RATE_SET_BIT_54M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_MCS0_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = BIT(HT_RATE_MCS0_INDEX-1); + *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 = BIT(HT_RATE_MCS1_INDEX-1); + *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 = BIT(HT_RATE_MCS2_INDEX-1); + *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 = BIT(HT_RATE_MCS3_INDEX-1); + *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 = BIT(HT_RATE_MCS4_INDEX-1); + *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 = BIT(HT_RATE_MCS5_INDEX-1); + *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 = BIT(HT_RATE_MCS6_INDEX-1); + *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 = BIT(HT_RATE_MCS7_INDEX-1); + *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 = BIT(HT_RATE_MCS0_INDEX-1); + *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 = BIT(HT_RATE_MCS1_INDEX-1); + *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 = BIT(HT_RATE_MCS2_INDEX-1); + *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 = BIT(HT_RATE_MCS3_INDEX-1); + *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 = BIT(HT_RATE_MCS4_INDEX-1); + *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 = BIT(HT_RATE_MCS5_INDEX-1); + *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 = BIT(HT_RATE_MCS6_INDEX-1); + *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 = BIT(HT_RATE_MCS7_INDEX-1); + *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 = BIT(HT_RATE_MCS0_INDEX-1); + *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 = BIT(HT_RATE_MCS1_INDEX-1); + *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 = BIT(HT_RATE_MCS2_INDEX-1); + *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 = BIT(HT_RATE_MCS3_INDEX-1); + *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 = BIT(HT_RATE_MCS4_INDEX-1); + *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 = BIT(HT_RATE_MCS5_INDEX-1); + *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 = BIT(HT_RATE_MCS6_INDEX-1); + *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 = BIT(HT_RATE_MCS7_INDEX-1); + *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 = 0; + *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 = BIT(HT_RATE_MCS0_INDEX-1); + *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 = BIT(HT_RATE_MCS1_INDEX-1); + *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 = BIT(HT_RATE_MCS2_INDEX-1); + *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 = BIT(HT_RATE_MCS3_INDEX-1); + *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 = BIT(HT_RATE_MCS4_INDEX-1); + *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 = BIT(HT_RATE_MCS5_INDEX-1); + *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 = BIT(HT_RATE_MCS6_INDEX-1); + *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 = BIT(HT_RATE_MCS7_INDEX-1); + *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 = 0; + *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 This function is called to update Link Quality information +* +* @param prAdapter Pointer of Adapter Data Structure +* ucBssIndex +* prEventLinkQuality +* cRssi +* cLinkQuality +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicUpdateLinkQuality(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN P_EVENT_LINK_QUALITY_V2 prEventLinkQuality) +{ + INT_8 cRssi; + UINT_16 u2AdjustRssi = 10; + + ASSERT(prAdapter); + ASSERT(ucBssIndex <= MAX_BSS_INDEX); + ASSERT(prEventLinkQuality); + + switch (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType) { + case NETWORK_TYPE_AIS: + if (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->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) { + /* ranged from (-128 ~ 30) in unit of dBm */ + cRssi = prEventLinkQuality->rLq[ucBssIndex].cRssi; + cRssi = (INT_8) (((INT_16) (cRssi) * u2AdjustRssi) / 10); + DBGLOG(RLM, INFO, + "Rssi=%d, NewRssi=%d\n", prEventLinkQuality->rLq[ucBssIndex].cRssi, cRssi); + nicUpdateRSSI(prAdapter, ucBssIndex, cRssi, + prEventLinkQuality->rLq[ucBssIndex].cLinkQuality); + } + + if (prAdapter->fgIsLinkRateValid == FALSE + || (kalGetTimeTick() - prAdapter->rLinkRateUpdateTime) > CFG_LINK_QUALITY_VALID_PERIOD) { + nicUpdateLinkSpeed(prAdapter, ucBssIndex, + prEventLinkQuality->rLq[ucBssIndex].u2LinkSpeed); + } + + } + break; + +#if 0 /* #if CFG_ENABLE_WIFI_DIRECT && CFG_SUPPORT_P2P_RSSI_QUERY */ + case NETWORK_TYPE_P2P: + 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, ucBssIndex, prEventLQEx->cRssiP2P, prEventLQEx->cLinkQualityP2P); + } + break; +#endif + default: + break; + + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to update RSSI and Link Quality information +* +* @param prAdapter Pointer of Adapter Data Structure +* ucBssIndex +* cRssi +* cLinkQuality +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicUpdateRSSI(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN INT_8 cRssi, IN INT_8 cLinkQuality) +{ + ASSERT(prAdapter); + ASSERT(ucBssIndex <= MAX_BSS_INDEX); + + switch (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType) { + case NETWORK_TYPE_AIS: + if (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->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 && CFG_SUPPORT_P2P_RSSI_QUERY + case NETWORK_TYPE_P2P: + 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 + default: + break; + + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to update Link Quality information +* +* @param prAdapter Pointer of Adapter Data Structure +* ucBssIndex +* prEventLinkQuality +* cRssi +* cLinkQuality +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicUpdateLinkSpeed(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN UINT_16 u2LinkSpeed) +{ + ASSERT(prAdapter); + ASSERT(ucBssIndex <= MAX_BSS_INDEX); + + switch (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType) { + case NETWORK_TYPE_AIS: + if (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + /* buffer statistics for further query */ + prAdapter->fgIsLinkRateValid = TRUE; + prAdapter->rLinkRateUpdateTime = kalGetTimeTick(); + + prAdapter->rLinkQuality.u2LinkSpeed = u2LinkSpeed; + } + break; + + default: + break; + + } + +} + +#if CFG_SUPPORT_RDD_TEST_MODE +WLAN_STATUS nicUpdateRddTestMode(IN P_ADAPTER_T prAdapter, IN P_CMD_RDD_CH_T prRddChParam) +{ + DEBUGFUNC("nicUpdateRddTestMode.\n"); + + ASSERT(prAdapter); + +/* aisFsmScanRequest(prAdapter, NULL); */ + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RDD_CH, + TRUE, + FALSE, FALSE, NULL, NULL, sizeof(CMD_RDD_CH_T), (PUINT_8) prRddChParam, NULL, 0); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to apply network address setting to +* both OS side and firmware domain +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS nicApplyNetworkAddress(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i; + + ASSERT(prAdapter); + + /* copy to adapter */ + COPY_MAC_ADDR(prAdapter->rMyMacAddr, prAdapter->rWifiVar.aucMacAddress); + + /* 4 <3> Update new MAC address to all 3 networks */ + 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; + +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { + for (i = 0; i < BSS_INFO_NUM; i++) { + if (prAdapter->rWifiVar.arBssInfoPool[i].eNetworkType == NETWORK_TYPE_P2P) { + COPY_MAC_ADDR(prAdapter->rWifiVar.arBssInfoPool[i].aucOwnMacAddr, + prAdapter->rWifiVar.aucDeviceAddress); + } + } + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + for (i = 0; i < BSS_INFO_NUM; i++) { + if (prAdapter->rWifiVar.arBssInfoPool[i].eNetworkType == NETWORK_TYPE_BOW) { + COPY_MAC_ADDR(prAdapter->rWifiVar.arBssInfoPool[i].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 WLAN_STATUS_SUCCESS; +} + +#if 1 +UINT_8 nicGetChipHwVer(VOID) +{ + return g_eco_info.ucHwVer; +} + +UINT_8 nicGetChipSwVer(VOID) +{ + return g_eco_info.ucRomVer; +} + +UINT_8 nicGetChipFactoryVer(VOID) +{ + return g_eco_info.ucFactoryVer; +} + +UINT_8 nicSetChipHwVer(UINT_8 value) +{ + g_eco_info.ucHwVer = value; + return 0; +} + +UINT_8 nicSetChipSwVer(UINT_8 value) +{ + g_eco_info.ucRomVer = value; + return 0; +} + +UINT_8 nicSetChipFactoryVer(UINT_8 value) +{ + g_eco_info.ucFactoryVer = value; + return 0; +} + +#else +UINT_8 nicGetChipHwVer(VOID) +{ + return mtk_wcn_wmt_ic_info_get(WMTCHIN_HWVER) & BITS(0, 7); +} + +UINT_8 nicGetChipSwVer(VOID) +{ + return mtk_wcn_wmt_ic_info_get(WMTCHIN_FWVER) & BITS(0, 7); +} + +UINT_8 nicGetChipFactoryVer(VOID) +{ + return (mtk_wcn_wmt_ic_info_get(WMTCHIN_FWVER) & BITS(8, 11)) >> 8; +} +#endif + +UINT_8 nicGetChipEcoVer(IN P_ADAPTER_T prAdapter) +{ + P_ECO_INFO_T prEcoInfo; + UINT_8 ucEcoVer; + UINT_8 ucCurSwVer, ucCurHwVer, ucCurFactoryVer; + + ucCurSwVer = nicGetChipSwVer(); + ucCurHwVer = nicGetChipHwVer(); + ucCurFactoryVer = nicGetChipFactoryVer(); + + ucEcoVer = 0; + + while (TRUE) { + /* Get ECO info from table */ + prEcoInfo = (P_ECO_INFO_T) &(prAdapter->chip_info->eco_info[ucEcoVer]); + + if ((prEcoInfo->ucRomVer == 0) && + (prEcoInfo->ucHwVer == 0) && + (prEcoInfo->ucFactoryVer == 0)) { + + /* End of table */ + break; + } + + if ((prEcoInfo->ucRomVer == ucCurSwVer) && + (prEcoInfo->ucHwVer == ucCurHwVer) && + (prEcoInfo->ucFactoryVer == ucCurFactoryVer)) { + break; + } + + ucEcoVer++; + } + +#if 0 + DBGLOG(INIT, INFO, + "Cannot get ECO version for SwVer[0x%02x]HwVer[0x%02x]FactoryVer[0x%1x],recognize as latest version[E%u]\n", + ucCurSwVer, ucCurHwVer, ucCurFactoryVer, prAdapter->chip_info->eco_info[ucEcoVer].ucEcoVer); +#endif + return prAdapter->chip_info->eco_info[ucEcoVer].ucEcoVer; +} + +BOOLEAN nicIsEcoVerEqualTo(IN P_ADAPTER_T prAdapter, UINT_8 ucEcoVer) +{ + if (ucEcoVer == prAdapter->chip_info->eco_ver) + return TRUE; + else + return FALSE; +} + +BOOLEAN nicIsEcoVerEqualOrLaterTo(IN P_ADAPTER_T prAdapter, UINT_8 ucEcoVer) +{ + if (ucEcoVer <= prAdapter->chip_info->eco_ver) + return TRUE; + else + return FALSE; +} + +VOID nicSerStopTxRx(IN P_ADAPTER_T prAdapter) +{ + DBGLOG(NIC, WARN, "SER: Stop HIF Tx/Rx!\n"); + + prAdapter->ucSerState = SER_STOP_HOST_TX_RX; + + /* Force own to FW as ACK and stop HIF */ + prAdapter->fgWiFiInSleepyState = TRUE; +} + +VOID nicSerStopTx(IN P_ADAPTER_T prAdapter) +{ + DBGLOG(NIC, WARN, "SER: Stop HIF Tx!\n"); + + prAdapter->ucSerState = SER_STOP_HOST_TX; +} + +VOID nicSerStartTxRx(IN P_ADAPTER_T prAdapter) +{ + DBGLOG(NIC, WARN, "SER: Start HIF T/R!\n"); + + halSerHifReset(prAdapter); + prAdapter->ucSerState = SER_IDLE_DONE; +} + +BOOLEAN nicSerIsWaitingReset(IN P_ADAPTER_T prAdapter) +{ + if (prAdapter->ucSerState == SER_STOP_HOST_TX_RX) + return TRUE; + else + return FALSE; +} + +BOOLEAN nicSerIsTxStop(IN P_ADAPTER_T prAdapter) +{ + switch (prAdapter->ucSerState) { + case SER_STOP_HOST_TX: + case SER_STOP_HOST_TX_RX: + case SER_REINIT_HIF: + return TRUE; + + case SER_IDLE_DONE: + default: + return FALSE; + } +} + +BOOLEAN nicSerIsRxStop(IN P_ADAPTER_T prAdapter) +{ + switch (prAdapter->ucSerState) { + case SER_STOP_HOST_TX_RX: + case SER_REINIT_HIF: + return TRUE; + + case SER_STOP_HOST_TX: + case SER_IDLE_DONE: + default: + return FALSE; + } +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic_cmd_event.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic_cmd_event.c new file mode 100644 index 0000000000000..8632be3f2848a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic_cmd_event.c @@ -0,0 +1,3978 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_cmd_event.c#3 +*/ + +/*! \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. +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" +#include "gl_ate_agent.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +const NIC_CAPABILITY_V2_REF_TABLE_T gNicCapabilityV2InfoTable[] = { + {TAG_CAP_TX_RESOURCE, nicCmdEventQueryNicTxResource}, + {TAG_CAP_TX_EFUSEADDRESS, nicCmdEventQueryNicEfuseAddr}, + {TAG_CAP_COEX_FEATURE, nicCmdEventQueryNicCoexFeature}, + {TAG_CAP_SINGLE_SKU, rlmDomainExtractSingleSkuInfoFromFirmware}, +#if CFG_TCP_IP_CHKSUM_OFFLOAD + {TAG_CAP_CSUM_OFFLOAD, nicCmdEventQueryNicCsumOffload}, +#endif + {TAG_CAP_MAC_EFUSE_OFFSET, nicCmdEventQueryEfuseOffset}, + {TAG_CAP_R_MODE_CAP, nicCmdEventQueryRModeCapability} +}; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D A T A +******************************************************************************** +*/ +VOID nicCmdEventQueryMcrRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_PARAM_CUSTOM_MCR_RW_STRUCT_T prMcrRdInfo; + P_GLUE_INFO_T prGlueInfo; + P_CMD_ACCESS_REG prCmdAccessReg; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prCmdAccessReg = (P_CMD_ACCESS_REG) (pucEventBuf); + + u4QueryInfoLen = sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T); + + prMcrRdInfo = (P_PARAM_CUSTOM_MCR_RW_STRUCT_T) prCmdInfo->pvInformationBuffer; + prMcrRdInfo->u4McrOffset = prCmdAccessReg->u4Address; + prMcrRdInfo->u4McrData = prCmdAccessReg->u4Data; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + + return; + +} + +VOID nicCmdEventQueryCoexGetInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_GLUE_INFO_T prGlueInfo; + + struct CMD_COEX_CTRL *prCmdCoexCtrl; + struct CMD_COEX_GET_INFO *prCmdCoexGetInfo; + struct PARAM_COEX_CTRL *prCoexCtrl; + struct PARAM_COEX_GET_INFO *prCoexGetInfo; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prCmdCoexCtrl = (struct CMD_COEX_CTRL *) (pucEventBuf); + u4QueryInfoLen = sizeof(struct PARAM_COEX_CTRL); + prCmdCoexGetInfo = (struct CMD_COEX_GET_INFO *) &prCmdCoexCtrl->aucBuffer[0]; + + prCoexCtrl = (struct PARAM_COEX_CTRL *) prCmdInfo->pvInformationBuffer; + prCoexGetInfo = (struct PARAM_COEX_GET_INFO *) &prCoexCtrl->aucBuffer[0]; + + kalMemCopy(prCoexGetInfo->u4CoexInfo, prCmdCoexGetInfo->u4CoexInfo, + sizeof(prCmdCoexGetInfo->u4CoexInfo)); + DBGLOG(REQ, INFO, "nicCmdEventQueryCoexGetInfo!!\n"); + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} + +VOID nicCmdEventQueryCoexIso(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_GLUE_INFO_T prGlueInfo; + + struct CMD_COEX_CTRL *prCmdCoexCtrl; + struct CMD_COEX_ISO_DETECT *prCmdCoexIsoDetect; + struct PARAM_COEX_CTRL *prCoexCtrl; + struct PARAM_COEX_ISO_DETECT *prCoexIsoDetect; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prCmdCoexCtrl = (struct CMD_COEX_CTRL *) (pucEventBuf); + u4QueryInfoLen = sizeof(struct PARAM_COEX_CTRL); + prCmdCoexIsoDetect = (struct CMD_COEX_ISO_DETECT *) &prCmdCoexCtrl->aucBuffer[0]; + + prCoexCtrl = (struct PARAM_COEX_CTRL *) prCmdInfo->pvInformationBuffer; + prCoexIsoDetect = (struct PARAM_COEX_ISO_DETECT *) &prCoexCtrl->aucBuffer[0]; + prCoexIsoDetect->u4IsoPath = prCmdCoexIsoDetect->u4IsoPath; + prCoexIsoDetect->u4Channel = prCmdCoexIsoDetect->u4Channel; + /*prCoexIsoDetect->u4Band = prCmdCoexIsoDetect->u4Band;*/ + prCoexIsoDetect->u4Isolation = prCmdCoexIsoDetect->u4Isolation; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} + +#if CFG_SUPPORT_QA_TOOL +VOID nicCmdEventQueryRxStatistics(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_PARAM_CUSTOM_ACCESS_RX_STAT prRxStatistics; + P_EVENT_ACCESS_RX_STAT prEventAccessRxStat; + UINT_32 u4QueryInfoLen, i; + P_GLUE_INFO_T prGlueInfo; + PUINT_32 prElement; + UINT_32 u4Temp; + /* P_CMD_ACCESS_RX_STAT prCmdRxStat, prRxStat; */ + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventAccessRxStat = (P_EVENT_ACCESS_RX_STAT) (pucEventBuf); + + prRxStatistics = (P_PARAM_CUSTOM_ACCESS_RX_STAT) prCmdInfo->pvInformationBuffer; + prRxStatistics->u4SeqNum = prEventAccessRxStat->u4SeqNum; + prRxStatistics->u4TotalNum = prEventAccessRxStat->u4TotalNum; + + u4QueryInfoLen = sizeof(CMD_ACCESS_RX_STAT); + + if (prRxStatistics->u4SeqNum == u4RxStatSeqNum) { + prElement = &g_HqaRxStat.MAC_FCS_Err; + for (i = 0; i < HQA_RX_STATISTIC_NUM; i++) { + u4Temp = ntohl(prEventAccessRxStat->au4Buffer[i]); + kalMemCopy(prElement, &u4Temp, 4); + + if (i < (HQA_RX_STATISTIC_NUM - 1)) + prElement++; + } + + g_HqaRxStat.AllMacMdrdy0 = ntohl(prEventAccessRxStat->au4Buffer[i]); + i++; + g_HqaRxStat.AllMacMdrdy1 = ntohl(prEventAccessRxStat->au4Buffer[i]); + /* i++; */ + /* g_HqaRxStat.AllFCSErr0 = ntohl(prEventAccessRxStat->au4Buffer[i]); */ + /* i++; */ + /* g_HqaRxStat.AllFCSErr1 = ntohl(prEventAccessRxStat->au4Buffer[i]); */ + } + + DBGLOG(INIT, ERROR, + "MT6632 : RX Statistics Test SeqNum = %d, TotalNum = %d\n", + (unsigned int)prEventAccessRxStat->u4SeqNum, (unsigned int)prEventAccessRxStat->u4TotalNum); + + DBGLOG(INIT, ERROR, "MAC_FCS_ERR = %d, MAC_MDRDY = %d, MU_RX_CNT = %d, RX_FIFO_FULL = %d\n", + (unsigned int)prEventAccessRxStat->au4Buffer[0], + (unsigned int)prEventAccessRxStat->au4Buffer[1], + (unsigned int)prEventAccessRxStat->au4Buffer[65], + (unsigned int)prEventAccessRxStat->au4Buffer[22]); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} + +#if CFG_SUPPORT_TX_BF +VOID nicCmdEventPfmuDataRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_GLUE_INFO_T prGlueInfo; + P_PFMU_DATA prEventPfmuDataRead = NULL; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventPfmuDataRead = (P_PFMU_DATA) (pucEventBuf); + + u4QueryInfoLen = sizeof(PFMU_DATA); + + g_rPfmuData = *prEventPfmuDataRead; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + + DBGLOG(INIT, INFO, "=========== Before ===========\n"); + if (prEventPfmuDataRead != NULL) { + DBGLOG(INIT, INFO, "u2Phi11 = 0x%x\n", prEventPfmuDataRead->rField.u2Phi11); + DBGLOG(INIT, INFO, "ucPsi21 = 0x%x\n", prEventPfmuDataRead->rField.ucPsi21); + DBGLOG(INIT, INFO, "u2Phi21 = 0x%x\n", prEventPfmuDataRead->rField.u2Phi21); + DBGLOG(INIT, INFO, "ucPsi31 = 0x%x\n", prEventPfmuDataRead->rField.ucPsi31); + DBGLOG(INIT, INFO, "u2Phi31 = 0x%x\n", prEventPfmuDataRead->rField.u2Phi31); + DBGLOG(INIT, INFO, "ucPsi41 = 0x%x\n", prEventPfmuDataRead->rField.ucPsi41); + DBGLOG(INIT, INFO, "u2Phi22 = 0x%x\n", prEventPfmuDataRead->rField.u2Phi22); + DBGLOG(INIT, INFO, "ucPsi32 = 0x%x\n", prEventPfmuDataRead->rField.ucPsi32); + DBGLOG(INIT, INFO, "u2Phi32 = 0x%x\n", prEventPfmuDataRead->rField.u2Phi32); + DBGLOG(INIT, INFO, "ucPsi42 = 0x%x\n", prEventPfmuDataRead->rField.ucPsi42); + DBGLOG(INIT, INFO, "u2Phi33 = 0x%x\n", prEventPfmuDataRead->rField.u2Phi33); + DBGLOG(INIT, INFO, "ucPsi43 = 0x%x\n", prEventPfmuDataRead->rField.ucPsi43); + DBGLOG(INIT, INFO, "u2dSNR00 = 0x%x\n", prEventPfmuDataRead->rField.u2dSNR00); + DBGLOG(INIT, INFO, "u2dSNR01 = 0x%x\n", prEventPfmuDataRead->rField.u2dSNR01); + DBGLOG(INIT, INFO, "u2dSNR02 = 0x%x\n", prEventPfmuDataRead->rField.u2dSNR02); + DBGLOG(INIT, INFO, "u2dSNR03 = 0x%x\n", prEventPfmuDataRead->rField.u2dSNR03); + } +} + +VOID nicCmdEventPfmuTagRead(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_PFMU_TAG_READ_T prEventPfmuTagRead = NULL; + P_PARAM_CUSTOM_PFMU_TAG_READ_STRUCT_T prPfumTagRead = NULL; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + if (!pucEventBuf) { + DBGLOG(INIT, ERROR, "pucEventBuf is NULL.\n"); + return; + } + if (!prCmdInfo->pvInformationBuffer) { + DBGLOG(INIT, ERROR, "prCmdInfo->pvInformationBuffer is NULL.\n"); + return; + } + /* 4 <2> Update information of OID */ + if (!prCmdInfo->fgIsOid) { + DBGLOG(INIT, ERROR, "cmd %u seq #%u not oid!", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + return; + } + prGlueInfo = prAdapter->prGlueInfo; + prEventPfmuTagRead = (P_EVENT_PFMU_TAG_READ_T) (pucEventBuf); + + prPfumTagRead = (P_PARAM_CUSTOM_PFMU_TAG_READ_STRUCT_T) prCmdInfo->pvInformationBuffer; + + kalMemCopy(prPfumTagRead, prEventPfmuTagRead, sizeof(EVENT_PFMU_TAG_READ_T)); + + u4QueryInfoLen = sizeof(CMD_TXBF_ACTION_T); + + g_rPfmuTag1 = prPfumTagRead->ru4TxBfPFMUTag1; + g_rPfmuTag2 = prPfumTagRead->ru4TxBfPFMUTag2; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + + DBGLOG(INIT, INFO, "========================== (R)Tag1 info ==========================\n"); + + DBGLOG(INIT, INFO, " Row data0 : %x, Row data1 : %x, Row data2 : %x, Row data3 : %x\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.au4RawData[0], + prEventPfmuTagRead->ru4TxBfPFMUTag1.au4RawData[1], + prEventPfmuTagRead->ru4TxBfPFMUTag1.au4RawData[2], prEventPfmuTagRead->ru4TxBfPFMUTag1.au4RawData[3]); + DBGLOG(INIT, INFO, "ProfileID = %d Invalid status = %d\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucProfileID, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucInvalidProf); + DBGLOG(INIT, INFO, "0:iBF / 1:eBF = %d\n", prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucTxBf); + DBGLOG(INIT, INFO, "0:SU / 1:MU = %d\n", prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucSU_MU); + DBGLOG(INIT, INFO, "DBW(0/1/2/3 BW20/40/80/160NC) = %d\n", prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucDBW); + DBGLOG(INIT, INFO, "RMSD = %d\n", prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucRMSD); + DBGLOG(INIT, INFO, "Nrow = %d, Ncol = %d, Ng = %d, LM = %d\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucNrow, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucNcol, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucNgroup, prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucLM); + DBGLOG(INIT, INFO, "Mem1(%d, %d), Mem2(%d, %d), Mem3(%d, %d), Mem4(%d, %d)\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr1ColIdx, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr1RowIdx, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr2ColIdx, + (prEventPfmuTagRead->ru4TxBfPFMUTag1. + rField.ucMemAddr2RowIdx | (prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr2RowIdxMsb << 5)), + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr3ColIdx, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr3RowIdx, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr4ColIdx, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucMemAddr4RowIdx); + DBGLOG(INIT, INFO, "SNR STS0=0x%x, SNR STS1=0x%x, SNR STS2=0x%x, SNR STS3=0x%x\n", + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucSNR_STS0, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucSNR_STS1, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucSNR_STS2, + prEventPfmuTagRead->ru4TxBfPFMUTag1.rField.ucSNR_STS3); + DBGLOG(INIT, INFO, "===============================================================\n"); + + DBGLOG(INIT, INFO, "========================== (R)Tag2 info ==========================\n"); + DBGLOG(INIT, INFO, " Row data0 : %x, Row data1 : %x, Row data2 : %x\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.au4RawData[0], + prEventPfmuTagRead->ru4TxBfPFMUTag2.au4RawData[1], prEventPfmuTagRead->ru4TxBfPFMUTag2.au4RawData[2]); + DBGLOG(INIT, INFO, "Smart Ant Cfg = %d\n", prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.u2SmartAnt); + DBGLOG(INIT, INFO, "SE index = %d\n", prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucSEIdx); + DBGLOG(INIT, INFO, "RMSD Threshold = %d\n", prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucRMSDThd); + DBGLOG(INIT, INFO, "MCS TH L1SS = %d, S1SS = %d, L2SS = %d, S2SS = %d\n" + "L3SS = %d, S3SS = %d\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucMCSThL1SS, + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucMCSThS1SS, + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucMCSThL2SS, + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucMCSThS2SS, + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucMCSThL3SS, + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.ucMCSThS3SS); + DBGLOG(INIT, INFO, "iBF lifetime limit(unit:4ms) = 0x%x\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.uciBfTimeOut); + DBGLOG(INIT, INFO, "iBF desired DBW = %d\n 0/1/2/3 : BW20/40/80/160NC\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.uciBfDBW); + DBGLOG(INIT, INFO, "iBF desired Ncol = %d\n 0/1/2 : Ncol = 1 ~ 3\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.uciBfNcol); + DBGLOG(INIT, INFO, "iBF desired Nrow = %d\n 0/1/2/3 : Nrow = 1 ~ 4\n", + prEventPfmuTagRead->ru4TxBfPFMUTag2.rField.uciBfNrow); + DBGLOG(INIT, INFO, "===============================================================\n"); + +} + +#endif /* CFG_SUPPORT_TX_BF */ +#if CFG_SUPPORT_MU_MIMO +VOID nicCmdEventGetQd(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_HQA_GET_QD prEventHqaGetQd; + UINT_32 i; + + P_PARAM_CUSTOM_GET_QD_STRUCT_T prGetQd = NULL; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + if (!pucEventBuf) { + DBGLOG(INIT, ERROR, "pucEventBuf is NULL.\n"); + return; + } + if (!prCmdInfo->pvInformationBuffer) { + DBGLOG(INIT, ERROR, "prCmdInfo->pvInformationBuffer is NULL.\n"); + return; + } + /* 4 <2> Update information of OID */ + if (!prCmdInfo->fgIsOid) { + DBGLOG(INIT, ERROR, "cmd %u seq #%u not oid!\n", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + return; + } + prGlueInfo = prAdapter->prGlueInfo; + prEventHqaGetQd = (P_EVENT_HQA_GET_QD) (pucEventBuf); + + prGetQd = (P_PARAM_CUSTOM_GET_QD_STRUCT_T) prCmdInfo->pvInformationBuffer; + + kalMemCopy(prGetQd, prEventHqaGetQd, sizeof(EVENT_HQA_GET_QD)); + + u4QueryInfoLen = sizeof(CMD_MUMIMO_ACTION_T); + + /* g_rPfmuTag1 = prPfumTagRead->ru4TxBfPFMUTag1; */ + /* g_rPfmuTag2 = prPfumTagRead->ru4TxBfPFMUTag2; */ + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + + DBGLOG(INIT, INFO, " event id : %x\n", prGetQd->u4EventId); + for (i = 0; i < 14; i++) + DBGLOG(INIT, INFO, "au4RawData[%d]: %x\n", i, prGetQd->au4RawData[i]); + +} + +VOID nicCmdEventGetCalcLq(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_HQA_GET_MU_CALC_LQ prEventHqaGetMuCalcLq; + UINT_32 i, j; + + P_PARAM_CUSTOM_GET_MU_CALC_LQ_STRUCT_T prGetMuCalcLq = NULL; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + if (!pucEventBuf) { + DBGLOG(INIT, ERROR, "pucEventBuf is NULL.\n"); + return; + } + if (!prCmdInfo->pvInformationBuffer) { + DBGLOG(INIT, ERROR, "prCmdInfo->pvInformationBuffer is NULL.\n"); + return; + } + /* 4 <2> Update information of OID */ + if (!prCmdInfo->fgIsOid) { + DBGLOG(INIT, ERROR, "cmd %u seq #%u not oid!\n", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + return; + } + prGlueInfo = prAdapter->prGlueInfo; + prEventHqaGetMuCalcLq = (P_EVENT_HQA_GET_MU_CALC_LQ) (pucEventBuf); + + prGetMuCalcLq = (P_PARAM_CUSTOM_GET_MU_CALC_LQ_STRUCT_T) prCmdInfo->pvInformationBuffer; + + kalMemCopy(prGetMuCalcLq, prEventHqaGetMuCalcLq, sizeof(EVENT_HQA_GET_MU_CALC_LQ)); + + u4QueryInfoLen = sizeof(CMD_MUMIMO_ACTION_T); + + /* g_rPfmuTag1 = prPfumTagRead->ru4TxBfPFMUTag1; */ + /* g_rPfmuTag2 = prPfumTagRead->ru4TxBfPFMUTag2; */ + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + + + DBGLOG(INIT, INFO, " event id : %x\n", prGetMuCalcLq->u4EventId); + for (i = 0; i < NUM_OF_USER; i++) + for (j = 0; j < NUM_OF_MODUL; j++) + DBGLOG(INIT, INFO, " lq_report[%d][%d]: %x\n", i, j, prGetMuCalcLq->rEntry.lq_report[i][j]); + +} + +VOID nicCmdEventGetCalcInitMcs(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_SHOW_GROUP_TBL_ENTRY prEventShowGroupTblEntry = NULL; + + P_PARAM_CUSTOM_SHOW_GROUP_TBL_ENTRY_STRUCT_T prShowGroupTbl; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + if (!pucEventBuf) { + DBGLOG(INIT, ERROR, "pucEventBuf is NULL.\n"); + return; + } + if (!prCmdInfo->pvInformationBuffer) { + DBGLOG(INIT, ERROR, "prCmdInfo->pvInformationBuffer is NULL.\n"); + return; + } + /* 4 <2> Update information of OID */ + if (!prCmdInfo->fgIsOid) { + DBGLOG(INIT, ERROR, "cmd %u seq #%u not oid!\n", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + return; + } + prGlueInfo = prAdapter->prGlueInfo; + prEventShowGroupTblEntry = (P_EVENT_SHOW_GROUP_TBL_ENTRY) (pucEventBuf); + + prShowGroupTbl = (P_PARAM_CUSTOM_SHOW_GROUP_TBL_ENTRY_STRUCT_T) prCmdInfo->pvInformationBuffer; + + kalMemCopy(prShowGroupTbl, prEventShowGroupTblEntry, sizeof(EVENT_SHOW_GROUP_TBL_ENTRY)); + + u4QueryInfoLen = sizeof(CMD_MUMIMO_ACTION_T); + + /* g_rPfmuTag1 = prPfumTagRead->ru4TxBfPFMUTag1; */ + /* g_rPfmuTag2 = prPfumTagRead->ru4TxBfPFMUTag2; */ + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + + + DBGLOG(INIT, INFO, "========================== (R)Group table info ==========================\n"); + DBGLOG(INIT, INFO, " event id : %x\n", prEventShowGroupTblEntry->u4EventId); + DBGLOG(INIT, INFO, "index = %x numUser = %x\n", prEventShowGroupTblEntry->index, + prEventShowGroupTblEntry->numUser); + DBGLOG(INIT, INFO, "BW = %x NS0/1/ = %x/%x\n", prEventShowGroupTblEntry->BW, prEventShowGroupTblEntry->NS0, + prEventShowGroupTblEntry->NS1); + DBGLOG(INIT, INFO, "PFIDUser0/1 = %x/%x\n", prEventShowGroupTblEntry->PFIDUser0, + prEventShowGroupTblEntry->PFIDUser1); + DBGLOG(INIT, INFO, "fgIsShortGI = %x, fgIsUsed = %x, fgIsDisable = %x\n", prEventShowGroupTblEntry->fgIsShortGI, + prEventShowGroupTblEntry->fgIsUsed, prEventShowGroupTblEntry->fgIsDisable); + DBGLOG(INIT, INFO, "initMcsUser0/1 = %x/%x\n", prEventShowGroupTblEntry->initMcsUser0, + prEventShowGroupTblEntry->initMcsUser1); + DBGLOG(INIT, INFO, "dMcsUser0: 0/1/ = %x/%x\n", prEventShowGroupTblEntry->dMcsUser0, + prEventShowGroupTblEntry->dMcsUser1); + +} +#endif /* CFG_SUPPORT_MU_MIMO */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +VOID nicCmdEventQuerySwCtrlRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_PARAM_CUSTOM_SW_CTRL_STRUCT_T prSwCtrlInfo; + P_GLUE_INFO_T prGlueInfo; + P_CMD_SW_DBG_CTRL_T prCmdSwCtrl; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prCmdSwCtrl = (P_CMD_SW_DBG_CTRL_T) (pucEventBuf); + + u4QueryInfoLen = sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T); + + prSwCtrlInfo = (P_PARAM_CUSTOM_SW_CTRL_STRUCT_T) prCmdInfo->pvInformationBuffer; + prSwCtrlInfo->u4Id = prCmdSwCtrl->u4Id; + prSwCtrlInfo->u4Data = prCmdSwCtrl->u4Data; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} + +VOID nicCmdEventQueryChipConfig(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T prChipConfigInfo; + P_GLUE_INFO_T prGlueInfo; + P_CMD_CHIP_CONFIG_T prCmdChipConfig; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prCmdChipConfig = (P_CMD_CHIP_CONFIG_T) (pucEventBuf); + + u4QueryInfoLen = sizeof(PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T); + + if (prCmdInfo->u4InformationBufferLength < sizeof(PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T)) { + DBGLOG(REQ, INFO, + "Chip config u4InformationBufferLength %u is not valid (event)\n", + prCmdInfo->u4InformationBufferLength); + } + prChipConfigInfo = (P_PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T) prCmdInfo->pvInformationBuffer; + prChipConfigInfo->ucRespType = prCmdChipConfig->ucRespType; + prChipConfigInfo->u2MsgSize = prCmdChipConfig->u2MsgSize; + DBGLOG(REQ, INFO, "%s: RespTyep %u\n", __func__, prChipConfigInfo->ucRespType); + DBGLOG(REQ, INFO, "%s: u2MsgSize %u\n", __func__, prChipConfigInfo->u2MsgSize); + +#if 0 + if (prChipConfigInfo->u2MsgSize > CHIP_CONFIG_RESP_SIZE) { + DBGLOG(REQ, INFO, + "Chip config Msg Size %u is not valid (event)\n", prChipConfigInfo->u2MsgSize); + prChipConfigInfo->u2MsgSize = CHIP_CONFIG_RESP_SIZE; + } +#endif + kalMemCopy(prChipConfigInfo->aucCmd, prCmdChipConfig->aucCmd, prChipConfigInfo->u2MsgSize); + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} + +VOID nicCmdEventSetCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, + prCmdInfo->u4InformationBufferLength, WLAN_STATUS_SUCCESS); + } + +} + +VOID nicCmdEventSetDisassociate(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); + } + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + +#if !defined(LINUX) + prAdapter->fgIsRadioOff = TRUE; +#endif + +} + +VOID nicCmdEventSetIpAddress(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4Count; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + u4Count = (prCmdInfo->u4SetInfoLen - OFFSET_OF(CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress)) + / sizeof(IPV4_NETWORK_ADDRESS); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress) + u4Count * + (OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + + sizeof(PARAM_NETWORK_ADDRESS_IP)), WLAN_STATUS_SUCCESS); + } + +} + +VOID nicCmdEventQueryRfTestATInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_TEST_STATUS prTestStatus, prQueryBuffer; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prTestStatus = (P_EVENT_TEST_STATUS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prQueryBuffer = (P_EVENT_TEST_STATUS) prCmdInfo->pvInformationBuffer; + + kalMemCopy(prQueryBuffer, prTestStatus, sizeof(EVENT_TEST_STATUS)); + + u4QueryInfoLen = sizeof(EVENT_TEST_STATUS); + + /* Update Query Information Length */ + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} + +VOID nicCmdEventQueryLinkQuality(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + PARAM_RSSI rRssi, *prRssi; + P_EVENT_LINK_QUALITY prLinkQuality; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prLinkQuality = (P_EVENT_LINK_QUALITY) pucEventBuf; + + rRssi = (PARAM_RSSI) prLinkQuality->cRssi; /* ranged from (-128 ~ 30) in unit of dBm */ + + if (prAdapter->prAisBssInfo->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; + } + + prGlueInfo = prAdapter->prGlueInfo; + prRssi = (PARAM_RSSI *) prCmdInfo->pvInformationBuffer; + + kalMemCopy(prRssi, &rRssi, sizeof(PARAM_RSSI)); + u4QueryInfoLen = sizeof(PARAM_RSSI); + + if (prCmdInfo->fgIsOid) + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This routine is in response of OID_GEN_LINK_SPEED query request +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the pending command info +* @param pucEventBuf +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicCmdEventQueryLinkSpeed(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_LINK_QUALITY prLinkQuality; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4LinkSpeed; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prLinkQuality = (P_EVENT_LINK_QUALITY) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + pu4LinkSpeed = (PUINT_32) (prCmdInfo->pvInformationBuffer); + + *pu4LinkSpeed = prLinkQuality->u2LinkSpeed * 5000; + + u4QueryInfoLen = sizeof(UINT_32); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +VOID nicCmdEventQueryStatistics(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_PARAM_802_11_STATISTICS_STRUCT_T prStatistics; + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + u4QueryInfoLen = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + prStatistics = (P_PARAM_802_11_STATISTICS_STRUCT_T) prCmdInfo->pvInformationBuffer; + + prStatistics->u4Length = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + prStatistics->rTransmittedFragmentCount = prEventStatistics->rTransmittedFragmentCount; + prStatistics->rMulticastTransmittedFrameCount = prEventStatistics->rMulticastTransmittedFrameCount; + prStatistics->rFailedCount = prEventStatistics->rFailedCount; + prStatistics->rRetryCount = prEventStatistics->rRetryCount; + prStatistics->rMultipleRetryCount = prEventStatistics->rMultipleRetryCount; + prStatistics->rRTSSuccessCount = prEventStatistics->rRTSSuccessCount; + prStatistics->rRTSFailureCount = prEventStatistics->rRTSFailureCount; + prStatistics->rACKFailureCount = prEventStatistics->rACKFailureCount; + prStatistics->rFrameDuplicateCount = prEventStatistics->rFrameDuplicateCount; + prStatistics->rReceivedFragmentCount = prEventStatistics->rReceivedFragmentCount; + prStatistics->rMulticastReceivedFrameCount = prEventStatistics->rMulticastReceivedFrameCount; + prStatistics->rFCSErrorCount = prEventStatistics->rFCSErrorCount; + prStatistics->rTKIPLocalMICFailures.QuadPart = 0; + prStatistics->rTKIPICVErrors.QuadPart = 0; + prStatistics->rTKIPCounterMeasuresInvoked.QuadPart = 0; + prStatistics->rTKIPReplays.QuadPart = 0; + prStatistics->rCCMPFormatErrors.QuadPart = 0; + prStatistics->rCCMPReplays.QuadPart = 0; + prStatistics->rCCMPDecryptErrors.QuadPart = 0; + prStatistics->rFourWayHandshakeFailures.QuadPart = 0; + prStatistics->rWEPUndecryptableCount.QuadPart = 0; + prStatistics->rWEPICVErrorCount.QuadPart = 0; + prStatistics->rDecryptSuccessCount.QuadPart = 0; + prStatistics->rDecryptFailureCount.QuadPart = 0; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +VOID nicCmdEventEnterRfTest(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + /* [driver-land] */ + /* prAdapter->fgTestMode = TRUE; */ + if (prAdapter->fgTestMode) + prAdapter->fgTestMode = FALSE; + else + 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, TRUE); + + /* 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); + +#if defined(_HIF_SDIO) && 0 + /* 3. Disable Interrupt */ + HAL_INTR_DISABLE(prAdapter); + + /* 4. Block til firmware completed entering into RF test mode */ + kalMsleep(500); + while (1) { + UINT_32 u4Value; + + 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 Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4SetInfoLen, WLAN_STATUS_NOT_SUPPORTED); + + } + return; + } + kalMsleep(10); + } + + /* 5. Clear Interrupt Status */ + { + UINT_32 u4WHISR = 0; + UINT_16 au2TxCount[16]; + + HAL_READ_INTR_STATUS(prAdapter, 4, (PUINT_8)&u4WHISR); + if (HAL_IS_TX_DONE_INTR(u4WHISR)) + HAL_READ_TX_RELEASED_COUNT(prAdapter, au2TxCount); + } + /* 6. Reset TX Counter */ + nicTxResetResource(prAdapter); + + /* 7. Re-enable Interrupt */ + HAL_INTR_ENABLE(prAdapter); +#endif + + /* 8. completion indication */ + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, WLAN_STATUS_SUCCESS); + } +#if CFG_SUPPORT_NVRAM + /* 9. load manufacture data */ + if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) + wlanLoadManufactureData(prAdapter, kalGetConfiguration(prAdapter->prGlueInfo)); + else + DBGLOG(REQ, WARN, "%s: load manufacture data fail\n", __func__); +#endif + +} + +VOID nicCmdEventLeaveRfTest(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ +#if defined(_HIF_SDIO) && 0 + UINT_32 u4WHISR = 0; + UINT_16 au2TxCount[16]; + UINT_32 u4Value; + + /* 1. Disable Interrupt */ + HAL_INTR_DISABLE(prAdapter); + + /* 2. Block until 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 Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4SetInfoLen, WLAN_STATUS_NOT_SUPPORTED); + + } + return; + } + 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, au2TxCount); + /* 4. Reset TX Counter */ + nicTxResetResource(prAdapter); + + /* 5. Re-enable Interrupt */ + HAL_INTR_ENABLE(prAdapter); +#endif + + /* 6. set driver-land variable */ + prAdapter->fgTestMode = FALSE; + prAdapter->fgIcapMode = FALSE; + + /* 7. completion indication */ + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, WLAN_STATUS_SUCCESS); + } + + /* 8. Indicate as disconnected */ + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_DISCONNECTED) { + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + + prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); + } +#if CFG_SUPPORT_NVRAM + /* 9. load manufacture data */ + if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) + wlanLoadManufactureData(prAdapter, kalGetConfiguration(prAdapter->prGlueInfo)); + else + DBGLOG(REQ, WARN, "%s: load manufacture data fail\n", __func__); +#endif + + /* 10. Override network address */ + wlanUpdateNetworkAddress(prAdapter); + +} + +VOID nicCmdEventQueryMcastAddr(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_GLUE_INFO_T prGlueInfo; + P_EVENT_MAC_MCAST_ADDR prEventMacMcastAddr; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventMacMcastAddr = (P_EVENT_MAC_MCAST_ADDR) (pucEventBuf); + + u4QueryInfoLen = prEventMacMcastAddr->u4NumOfGroupAddr * MAC_ADDR_LEN; + + /* buffer length check */ + if (prCmdInfo->u4InformationBufferLength < u4QueryInfoLen) { + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_BUFFER_TOO_SHORT); + } else { + kalMemCopy(prCmdInfo->pvInformationBuffer, + prEventMacMcastAddr->arAddress, + prEventMacMcastAddr->u4NumOfGroupAddr * MAC_ADDR_LEN); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + } +} + +VOID nicCmdEventQueryEepromRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T prEepromRdInfo; + P_GLUE_INFO_T prGlueInfo; + P_EVENT_ACCESS_EEPROM prEventAccessEeprom; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventAccessEeprom = (P_EVENT_ACCESS_EEPROM) (pucEventBuf); + + u4QueryInfoLen = sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T); + + prEepromRdInfo = (P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T) prCmdInfo->pvInformationBuffer; + prEepromRdInfo->ucEepromIndex = (UINT_8) (prEventAccessEeprom->u2Offset); + prEepromRdInfo->u2EepromData = prEventAccessEeprom->u2Data; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} + +VOID nicCmdEventSetMediaStreamMode(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + PARAM_MEDIA_STREAMING_INDICATION rParamMediaStreamIndication; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, WLAN_STATUS_SUCCESS); + } + + rParamMediaStreamIndication.rStatus.eStatusType = ENUM_STATUS_TYPE_MEDIA_STREAM_MODE; + rParamMediaStreamIndication.eMediaStreamMode = + prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode == 0 ? ENUM_MEDIA_STREAM_OFF : ENUM_MEDIA_STREAM_ON; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID)&rParamMediaStreamIndication, sizeof(PARAM_MEDIA_STREAMING_INDICATION)); +} + +VOID nicCmdEventSetStopSchedScan(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + /* + * DBGLOG(SCN, INFO, "--->nicCmdEventSetStopSchedScan\n" )); + */ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + /* + * DBGLOG(SCN, INFO, "<--kalSchedScanStopped\n" ); + */ + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4InformationBufferLength, WLAN_STATUS_SUCCESS); + } + + DBGLOG(SCN, INFO, "nicCmdEventSetStopSchedScan OID done, release lock and send event to uplayer\n"); + /*Due to dead lock issue, need to release the IO control before calling kernel APIs */ + kalSchedScanStopped(prAdapter->prGlueInfo); + +} + +/* 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); + + if (prCmdInfo->fgIsOid) + 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, TRUE); + + /* 1.1 clear pending Security / Management Frames */ + kalClearSecurityFrames(prAdapter->prGlueInfo); + kalClearMgmtFrames(prAdapter->prGlueInfo); + + /* 1.2 clear pending TX packet queued in glue layer */ + kalFlushPendingTxPackets(prAdapter->prGlueInfo); + + /* 2. indicate for OID failure */ + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_FAILURE); +} + +#if CFG_SUPPORT_QA_TOOL +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when received dump memory event packet. +* transfer the memory data to the IQ format data and write into file +* +* @param prIQAry Pointer to the array store I or Q data. +* prDataLen The return data length - bytes +* u4IQ 0: get I data +* 1 : get Q data +* +* @return -1: open file error +* +*/ +/*----------------------------------------------------------------------------*/ +INT_32 GetIQData(INT_32 **prIQAry, UINT_32 *prDataLen, UINT_32 u4IQ, UINT_32 u4GetWf1) +{ + UINT_8 aucPath[50]; /* the path for iq data dump out */ + UINT_8 aucData[50]; /* iq data in string format */ + UINT_32 i = 0, j = 0, count = 0; + INT_32 ret = -1; + INT_32 rv; + struct file *file = NULL; + + *prIQAry = g_au4IQData; + + /* sprintf(aucPath, "/pattern.txt"); // CSD's Pattern */ + snprintf(aucPath, + sizeof(aucPath), "/tmp/dump_out_%05hu_WF%d.txt", + (g_u2DumpIndex - 1), u4GetWf1); + if (kalCheckPath(aucPath) == -1) + snprintf(aucPath, + sizeof(aucPath), "/data/dump_out_%05hu_WF%d.txt", + (g_u2DumpIndex - 1), u4GetWf1); + + DBGLOG(INIT, INFO, + "iCap Read Dump File dump_out_%05hu_WF%u.txt\n", + (g_u2DumpIndex - 1), u4GetWf1); + + file = kalFileOpen(aucPath, O_RDONLY, 0); + + if ((file != NULL) && !IS_ERR(file)) { + /* read 1K data per time */ + for (i = 0; i < RTN_IQ_DATA_LEN / sizeof(UINT_32); + i++, g_au4Offset[u4GetWf1][u4IQ] += IQ_FILE_LINE_OFFSET) { + if (kalFileRead(file, g_au4Offset[u4GetWf1][u4IQ], aucData, IQ_FILE_IQ_STR_LEN) == 0) + break; + + count = 0; + + for (j = 0; j < 8; j++) { + if (aucData[j] != ' ') + aucData[count++] = aucData[j]; + } + + aucData[count] = '\0'; + + rv = kstrtoint(aucData, 0, &g_au4IQData[i]); /* transfer data format (string to int) */ + } + *prDataLen = i * sizeof(UINT_32); + kalFileClose(file); + ret = 0; + } + + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT GetIQData prDataLen = %d\n", *prDataLen); + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT GetIQData i = %d\n", i); + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when received dump memory event packet. +* transfer the memory data to the IQ format data and write into file +* +* @param prEventDumpMem Pointer to the event dump memory structure. +* +* @return 0: SUCCESS, -1: FAIL +* +*/ +/*----------------------------------------------------------------------------*/ + +UINT_32 TsfRawData2IqFmt(P_EVENT_DUMP_MEM_T prEventDumpMem) +{ + static UINT_8 aucPathWF0[40]; /* the path for iq data dump out */ + static UINT_8 aucPathWF1[40]; /* the path for iq data dump out */ + static UINT_8 aucPathRAWWF0[40]; /* the path for iq data dump out */ + static UINT_8 aucPathRAWWF1[40]; /* the path for iq data dump out */ + PUINT_8 pucDataWF0 = NULL; /* the data write into file */ + PUINT_8 pucDataWF1 = NULL; /* the data write into file */ + PUINT_8 pucDataRAWWF0 = NULL; /* the data write into file */ + PUINT_8 pucDataRAWWF1 = NULL; /* the data write into file */ + UINT_32 u4SrcOffset; /* record the buffer offset */ + UINT_32 u4FmtLen = 0; /* bus format length */ + UINT_32 u4CpyLen = 0; + UINT_32 u4RemainByte; + UINT_32 u4DataWBufSize = 150; + UINT_32 u4DataRAWWBufSize = 150; + UINT_32 u4DataWLenF0 = 0; + UINT_32 u4DataWLenF1 = 0; + UINT_32 u4DataRAWWLenF0 = 0; + UINT_32 u4DataRAWWLenF1 = 0; + + BOOLEAN fgAppend; + INT_32 u4Iqc160WF0Q0, u4Iqc160WF1I1; + + static UINT_8 ucDstOffset; /* for alignment. bcs we send 2KB data per packet,*/ + /*the data will not align in 12 bytes case. */ + static UINT_32 u4CurTimeTick; + + static ICAP_BUS_FMT icapBusData; + UINT_32 *ptr; + + pucDataWF0 = kmalloc(u4DataWBufSize, GFP_KERNEL); + pucDataWF1 = kmalloc(u4DataWBufSize, GFP_KERNEL); + pucDataRAWWF0 = kmalloc(u4DataRAWWBufSize, GFP_KERNEL); + pucDataRAWWF1 = kmalloc(u4DataRAWWBufSize, GFP_KERNEL); + + + if ((!pucDataWF0) || (!pucDataWF1) || (!pucDataRAWWF0) || (!pucDataRAWWF1)) { + DBGLOG(INIT, ERROR, "kmalloc failed.\n"); + kfree(pucDataWF0); + kfree(pucDataWF1); + kfree(pucDataRAWWF0); + kfree(pucDataRAWWF1); + ASSERT(-1); + return -1; + } + + fgAppend = TRUE; + if (prEventDumpMem->ucFragNum == 1) { + + u4CurTimeTick = kalGetTimeTick(); + /* Store memory dump into sdcard, + * path /sdcard/dump___.hex + */ +#if defined(LINUX) + + /*if blbist mkdir undre /data/blbist, the dump files wouls put on it */ + scnprintf(aucPathWF0, + sizeof(aucPathWF0), "/tmp/dump_out_%05hu_WF0.txt", + g_u2DumpIndex); + scnprintf(aucPathWF1, + sizeof(aucPathWF1), "/tmp/dump_out_%05hu_WF1.txt", + g_u2DumpIndex); + if (kalCheckPath(aucPathWF0) == -1) { + kalMemSet(aucPathWF0, 0x00, sizeof(aucPathWF0)); + scnprintf(aucPathWF0, + sizeof(aucPathWF0), + "/data/dump_out_%05hu_WF0.txt", + g_u2DumpIndex); + } else + kalTrunkPath(aucPathWF0); + + if (kalCheckPath(aucPathWF1) == -1) { + kalMemSet(aucPathWF1, 0x00, sizeof(aucPathWF1)); + scnprintf(aucPathWF1, + sizeof(aucPathWF1), + "/data/dump_out_%05hu_WF1.txt", + g_u2DumpIndex); + } else + kalTrunkPath(aucPathWF1); + + scnprintf(aucPathRAWWF0, + sizeof(aucPathRAWWF0), "/dump_RAW_%05hu_WF0.txt", + g_u2DumpIndex); + scnprintf(aucPathRAWWF1, + sizeof(aucPathRAWWF1), "/dump_RAW_%05hu_WF1.txt", + g_u2DumpIndex); + if (kalCheckPath(aucPathRAWWF0) == -1) { + kalMemSet(aucPathRAWWF0, 0x00, sizeof(aucPathRAWWF0)); + scnprintf(aucPathRAWWF0, + sizeof(aucPathRAWWF0), + "/data/dump_RAW_%05hu_WF0.txt", + g_u2DumpIndex); + } else + kalTrunkPath(aucPathRAWWF0); + + if (kalCheckPath(aucPathRAWWF1) == -1) { + kalMemSet(aucPathRAWWF1, 0x00, sizeof(aucPathRAWWF1)); + scnprintf(aucPathRAWWF1, sizeof(aucPathRAWWF1), + "/data/dump_RAW_%05hu_WF1.txt", g_u2DumpIndex); + } else + kalTrunkPath(aucPathRAWWF1); + +#else + kal_sprintf_ddk(aucPathWF0, sizeof(aucPathWF0), + u4CurTimeTick, + prEventDumpMem->u4Address, prEventDumpMem->u4Length + prEventDumpMem->u4RemainLength); + kal_sprintf_ddk(aucPathWF1, sizeof(aucPathWF1), + u4CurTimeTick, + prEventDumpMem->u4Address, prEventDumpMem->u4Length + prEventDumpMem->u4RemainLength); +#endif + /* fgAppend = FALSE; */ + } + + ptr = (PUINT_32)(&prEventDumpMem->aucBuffer[0]); + /*DBGLOG(INIT, INFO, ": ==> (prEventDumpMem = %08x %08x %08x)\n", *(ptr), *(ptr + 4), *(ptr + 8));*/ + /*DBGLOG(INIT, INFO, ": ==> (prEventDumpMem->eIcapContent = %x)\n", prEventDumpMem->eIcapContent);*/ + + for (u4SrcOffset = 0, u4RemainByte = prEventDumpMem->u4Length; u4RemainByte > 0;) { + u4FmtLen = +(prEventDumpMem->eIcapContent == ICAP_CONTENT_SPECTRUM) ? sizeof(SPECTRUM_BUS_FMT_T) : sizeof(ICAP_BUS_FMT); + /* 4 bytes : 12 bytes */ + u4CpyLen = (u4RemainByte - u4FmtLen >= 0) ? u4FmtLen : u4RemainByte; + + if ((ucDstOffset + u4CpyLen) > sizeof(icapBusData)) { + DBGLOG(INIT, ERROR, + "ucDstOffset(%u) + u4CpyLen(%u) exceed bound of icapBusData\n", + ucDstOffset, u4CpyLen); + kfree(pucDataWF0); + kfree(pucDataWF1); + kfree(pucDataRAWWF0); + kfree(pucDataRAWWF1); + ASSERT(-1); + return -1; + } + memcpy((UINT_8 *)&icapBusData + ucDstOffset, &prEventDumpMem->aucBuffer[0] + u4SrcOffset, u4CpyLen); +#if 0 + if (prEventDumpMem->eIcapContent == ICAP_CONTENT_ADC) { + sprintf(aucDataWF0, "%8d,%8d\n", icapBusData.rAdcBusData.u4Dcoc0I, + icapBusData.rAdcBusData.u4Dcoc0Q); + sprintf(aucDataWF1, "%8d,%8d\n", icapBusData.rAdcBusData.u4Dcoc1I, + icapBusData.rAdcBusData.u4Dcoc1Q); + } +#endif + if (prEventDumpMem->eIcapContent == ICAP_CONTENT_FIIQ || + prEventDumpMem->eIcapContent == ICAP_CONTENT_FDIQ) { + u4DataWLenF0 = scnprintf(pucDataWF0, u4DataWBufSize, "%8d,%8d\n", + icapBusData.rIqcBusData.u4Iqc0I, + icapBusData.rIqcBusData.u4Iqc0Q); + u4DataWLenF1 = scnprintf(pucDataWF1, u4DataWBufSize, "%8d,%8d\n", + icapBusData.rIqcBusData.u4Iqc1I, + icapBusData.rIqcBusData.u4Iqc1Q); + } else if (prEventDumpMem->eIcapContent - 1000 == ICAP_CONTENT_FIIQ + || prEventDumpMem->eIcapContent - 1000 == ICAP_CONTENT_FDIQ) { + u4Iqc160WF0Q0 = + icapBusData.rIqc160BusData.u4Iqc0Q0P1 | (icapBusData.rIqc160BusData.u4Iqc0Q0P2 << 8); + u4Iqc160WF1I1 = + icapBusData.rIqc160BusData.u4Iqc1I1P1 | (icapBusData.rIqc160BusData.u4Iqc1I1P2 << 4); + + u4DataWLenF0 = scnprintf(pucDataWF0, u4DataWBufSize, "%8d,%8d\n%8d,%8d\n", + icapBusData.rIqc160BusData.u4Iqc0I0, u4Iqc160WF0Q0, + icapBusData.rIqc160BusData.u4Iqc0I1, + icapBusData.rIqc160BusData.u4Iqc0Q1); + + u4DataWLenF1 = scnprintf(pucDataWF1, u4DataWBufSize, "%8d,%8d\n%8d,%8d\n", + icapBusData.rIqc160BusData.u4Iqc1I0, + icapBusData.rIqc160BusData.u4Iqc1Q0, u4Iqc160WF1I1, + icapBusData.rIqc160BusData.u4Iqc1Q1); + + } else if (prEventDumpMem->eIcapContent == ICAP_CONTENT_SPECTRUM) { + u4DataWLenF0 = scnprintf(pucDataWF0, u4DataWBufSize, "%8d,%8d\n", + icapBusData.rSpectrumBusData.u4DcocI, + icapBusData.rSpectrumBusData.u4DcocQ); + } else if (prEventDumpMem->eIcapContent == ICAP_CONTENT_ADC) { + u4DataWLenF0 = scnprintf(pucDataWF0, u4DataWBufSize, + "%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n", + icapBusData.rPackedAdcBusData.u4AdcI0T0, + icapBusData.rPackedAdcBusData.u4AdcQ0T0, + icapBusData.rPackedAdcBusData.u4AdcI0T1, + icapBusData.rPackedAdcBusData.u4AdcQ0T1, + icapBusData.rPackedAdcBusData.u4AdcI0T2, + icapBusData.rPackedAdcBusData.u4AdcQ0T2, + icapBusData.rPackedAdcBusData.u4AdcI0T3, + icapBusData.rPackedAdcBusData.u4AdcQ0T3, + icapBusData.rPackedAdcBusData.u4AdcI0T4, + icapBusData.rPackedAdcBusData.u4AdcQ0T4, + icapBusData.rPackedAdcBusData.u4AdcI0T5, + icapBusData.rPackedAdcBusData.u4AdcQ0T5); + + u4DataWLenF1 = scnprintf(pucDataWF1, u4DataWBufSize, + "%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n%8d,%8d\n", + icapBusData.rPackedAdcBusData.u4AdcI1T0, + icapBusData.rPackedAdcBusData.u4AdcQ1T0, + icapBusData.rPackedAdcBusData.u4AdcI1T1, + icapBusData.rPackedAdcBusData.u4AdcQ1T1, + icapBusData.rPackedAdcBusData.u4AdcI1T2, + icapBusData.rPackedAdcBusData.u4AdcQ1T2, + icapBusData.rPackedAdcBusData.u4AdcI1T3, + icapBusData.rPackedAdcBusData.u4AdcQ1T3, + icapBusData.rPackedAdcBusData.u4AdcI1T4, + icapBusData.rPackedAdcBusData.u4AdcQ1T4, + icapBusData.rPackedAdcBusData.u4AdcI1T5, + icapBusData.rPackedAdcBusData.u4AdcQ1T5); + } else if (prEventDumpMem->eIcapContent - 2000 == ICAP_CONTENT_ADC) { + u4DataWLenF0 = scnprintf(pucDataWF0, u4DataWBufSize, "%8d,%8d\n%8d,%8d\n%8d,%8d\n", + icapBusData.rPackedAdcBusData.u4AdcI0T0, + icapBusData.rPackedAdcBusData.u4AdcQ0T0, + icapBusData.rPackedAdcBusData.u4AdcI0T1, + icapBusData.rPackedAdcBusData.u4AdcQ0T1, + icapBusData.rPackedAdcBusData.u4AdcI0T2, + icapBusData.rPackedAdcBusData.u4AdcQ0T2); + + u4DataWLenF1 = scnprintf(pucDataWF1, u4DataWBufSize, "%8d,%8d\n%8d,%8d\n%8d,%8d\n", + icapBusData.rPackedAdcBusData.u4AdcI1T0, + icapBusData.rPackedAdcBusData.u4AdcQ1T0, + icapBusData.rPackedAdcBusData.u4AdcI1T1, + icapBusData.rPackedAdcBusData.u4AdcQ1T1, + icapBusData.rPackedAdcBusData.u4AdcI1T2, + icapBusData.rPackedAdcBusData.u4AdcQ1T2); + } else if (prEventDumpMem->eIcapContent == ICAP_CONTENT_TOAE) { + /* actually, this is DCOC. we take TOAE as DCOC */ + u4DataWLenF0 = scnprintf(pucDataWF0, u4DataWBufSize, "%8d,%8d\n", + icapBusData.rAdcBusData.u4Dcoc0I, icapBusData.rAdcBusData.u4Dcoc0Q); + u4DataWLenF1 = scnprintf(pucDataWF1, u4DataWBufSize, "%8d,%8d\n", + icapBusData.rAdcBusData.u4Dcoc1I, icapBusData.rAdcBusData.u4Dcoc1Q); + } + if (u4CpyLen == u4FmtLen) { /* the data format is complete */ + kalWriteToFile(aucPathWF0, fgAppend, pucDataWF0, u4DataWLenF0); + kalWriteToFile(aucPathWF1, fgAppend, pucDataWF1, u4DataWLenF1); + } + ptr = (PUINT_32)(&prEventDumpMem->aucBuffer[0] + u4SrcOffset); + u4DataRAWWLenF0 = scnprintf(pucDataRAWWF0, u4DataWBufSize, "%08x%08x%08x\n", + *(ptr + 2), *(ptr + 1), *ptr); + kalWriteToFile(aucPathRAWWF0, fgAppend, pucDataRAWWF0, u4DataRAWWLenF0); + kalWriteToFile(aucPathRAWWF1, fgAppend, pucDataRAWWF1, u4DataRAWWLenF1); + + u4RemainByte -= u4CpyLen; + u4SrcOffset += u4CpyLen; /* shift offset */ + ucDstOffset = 0; /* only use ucDstOffset at first packet for align 2KB */ + } + /* if this is a last packet, we can't transfer the remain data. + * bcs we can't guarantee the data is complete align data format + */ + if (u4CpyLen != u4FmtLen) { /* the data format is complete */ + ucDstOffset = u4CpyLen; /* not align 2KB, keep the data and next packet data will append it */ + } + + kfree(pucDataWF0); + kfree(pucDataWF1); + kfree(pucDataRAWWF0); + kfree(pucDataRAWWF1); + + if (u4RemainByte < 0) { + ASSERT(-1); + return -1; + } + + return 0; +} +#endif /* CFG_SUPPORT_QA_TOOL */ + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +VOID nicCmdEventQueryCalBackupV2(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_PARAM_CAL_BACKUP_STRUCT_V2_T prCalBackupDataV2Info; + P_CMD_CAL_BACKUP_STRUCT_V2_T prEventCalBackupDataV2; + UINT_32 u4QueryInfoLen, u4QueryInfo, u4TempAddress; + P_GLUE_INFO_T prGlueInfo; + + DBGLOG(RFTEST, INFO, "%s\n", __func__); + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + + prGlueInfo = prAdapter->prGlueInfo; + prEventCalBackupDataV2 = (P_CMD_CAL_BACKUP_STRUCT_V2_T) (pucEventBuf); + + u4QueryInfoLen = sizeof(CMD_CAL_BACKUP_STRUCT_V2_T); + + prCalBackupDataV2Info = (P_PARAM_CAL_BACKUP_STRUCT_V2_T) prCmdInfo->pvInformationBuffer; +#if 0 + DBGLOG(RFTEST, INFO, "============ Receive a Cal Data EVENT (Info) ============\n"); + DBGLOG(RFTEST, INFO, "Reason = %d\n", prEventCalBackupDataV2->ucReason); + DBGLOG(RFTEST, INFO, "Action = %d\n", prEventCalBackupDataV2->ucAction); + DBGLOG(RFTEST, INFO, "NeedResp = %d\n", prEventCalBackupDataV2->ucNeedResp); + DBGLOG(RFTEST, INFO, "FragNum = %d\n", prEventCalBackupDataV2->ucFragNum); + DBGLOG(RFTEST, INFO, "RomRam = %d\n", prEventCalBackupDataV2->ucRomRam); + DBGLOG(RFTEST, INFO, "ThermalValue = %d\n", prEventCalBackupDataV2->u4ThermalValue); + DBGLOG(RFTEST, INFO, "Address = 0x%08x\n", prEventCalBackupDataV2->u4Address); + DBGLOG(RFTEST, INFO, "Length = %d\n", prEventCalBackupDataV2->u4Length); + DBGLOG(RFTEST, INFO, "RemainLength = %d\n", prEventCalBackupDataV2->u4RemainLength); + DBGLOG(RFTEST, INFO, "=========================================================\n"); +#endif + + if (prEventCalBackupDataV2->ucReason == 0 && prEventCalBackupDataV2->ucAction == 0) { + DBGLOG(RFTEST, INFO, "Received an EVENT for Query Thermal Temp.\n"); + prCalBackupDataV2Info->u4ThermalValue = prEventCalBackupDataV2->u4ThermalValue; + g_rBackupCalDataAllV2.u4ThermalInfo = prEventCalBackupDataV2->u4ThermalValue; + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } else if (prEventCalBackupDataV2->ucReason == 0 && prEventCalBackupDataV2->ucAction == 1) { + DBGLOG(RFTEST, INFO, "Received an EVENT for Query Total Cal Data Length.\n"); + prCalBackupDataV2Info->u4Length = prEventCalBackupDataV2->u4Length; + + if (prEventCalBackupDataV2->ucRomRam == 0) + g_rBackupCalDataAllV2.u4ValidRomCalDataLength = prEventCalBackupDataV2->u4Length; + else if (prEventCalBackupDataV2->ucRomRam == 1) + g_rBackupCalDataAllV2.u4ValidRamCalDataLength = prEventCalBackupDataV2->u4Length; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } else if (prEventCalBackupDataV2->ucReason == 2 && prEventCalBackupDataV2->ucAction == 4) { + DBGLOG(RFTEST, INFO, "Received an EVENT for Query All Cal (%s) Data. FragNum = %d\n", + prCalBackupDataV2Info->ucRomRam == 0 ? "ROM" : "RAM", + prEventCalBackupDataV2->ucFragNum); + prCalBackupDataV2Info->u4Address = prEventCalBackupDataV2->u4Address; + prCalBackupDataV2Info->u4Length = prEventCalBackupDataV2->u4Length; + prCalBackupDataV2Info->u4RemainLength = prEventCalBackupDataV2->u4RemainLength; + prCalBackupDataV2Info->ucFragNum = prEventCalBackupDataV2->ucFragNum; + + /* Copy Cal Data From FW to Driver Array */ + if (prEventCalBackupDataV2->ucRomRam == 0) { + u4TempAddress = prEventCalBackupDataV2->u4Address; + kalMemCopy((PUINT_8)(g_rBackupCalDataAllV2.au4RomCalData) + u4TempAddress, + (PUINT_8)(prEventCalBackupDataV2->au4Buffer), + prEventCalBackupDataV2->u4Length); + } else if (prEventCalBackupDataV2->ucRomRam == 1) { + u4TempAddress = prEventCalBackupDataV2->u4Address; + kalMemCopy((PUINT_8)(g_rBackupCalDataAllV2.au4RamCalData) + u4TempAddress, + (PUINT_8)(prEventCalBackupDataV2->au4Buffer), + prEventCalBackupDataV2->u4Length); + } + + if (prEventCalBackupDataV2->u4Address == 0xFFFFFFFF) { + DBGLOG(RFTEST, INFO, "RLM CMD : Address Error!!!!!!!!!!!\n"); + } else if (prEventCalBackupDataV2->u4RemainLength == 0 + && prEventCalBackupDataV2->ucRomRam == 1) { + DBGLOG(RFTEST, INFO, "RLM CMD : Get Cal Data from FW (%s). Finish!!!!!!!!!!!\n", + prCalBackupDataV2Info->ucRomRam == 0 ? "ROM" : "RAM"); + } else if (prEventCalBackupDataV2->u4RemainLength == 0 + && prEventCalBackupDataV2->ucRomRam == 0) { + DBGLOG(RFTEST, INFO, "RLM CMD : Get Cal Data from FW (%s). Finish!!!!!!!!!!!\n", + prCalBackupDataV2Info->ucRomRam == 0 ? "ROM" : "RAM"); + prCalBackupDataV2Info->ucFragNum = 0; + prCalBackupDataV2Info->ucRomRam = 1; + prCalBackupDataV2Info->u4ThermalValue = 0; + prCalBackupDataV2Info->u4Address = 0; + prCalBackupDataV2Info->u4Length = 0; + prCalBackupDataV2Info->u4RemainLength = 0; + DBGLOG(RFTEST, INFO, "RLM CMD : Get Cal Data from FW (%s). Start!!!!!!!!!!!!!!!!\n", + prCalBackupDataV2Info->ucRomRam == 0 ? "ROM" : "RAM"); + DBGLOG(RFTEST, INFO, "Thermal Temp = %d\n", g_rBackupCalDataAllV2.u4ThermalInfo); + wlanoidQueryCalBackupV2(prAdapter, + prCalBackupDataV2Info, + sizeof(PARAM_CAL_BACKUP_STRUCT_V2_T), + &u4QueryInfo); + } else { + wlanoidSendCalBackupV2Cmd(prAdapter, + prCmdInfo->pvInformationBuffer, prCmdInfo->u4InformationBufferLength); + } + } else if (prEventCalBackupDataV2->ucReason == 3 && prEventCalBackupDataV2->ucAction == 5) { + DBGLOG(RFTEST, INFO, + "Received an EVENT for Send All Cal Data. FragNum = %d\n", + prEventCalBackupDataV2->ucFragNum); + prCalBackupDataV2Info->u4Address = prEventCalBackupDataV2->u4Address; + prCalBackupDataV2Info->u4Length = prEventCalBackupDataV2->u4Length; + prCalBackupDataV2Info->u4RemainLength = prEventCalBackupDataV2->u4RemainLength; + prCalBackupDataV2Info->ucFragNum = prEventCalBackupDataV2->ucFragNum; + + if (prEventCalBackupDataV2->u4RemainLength == 0 + || prEventCalBackupDataV2->u4Address == 0xFFFFFFFF) { + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } else { + wlanoidSendCalBackupV2Cmd(prAdapter, + prCmdInfo->pvInformationBuffer, prCmdInfo->u4InformationBufferLength); + } + } else { + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to handle dump burst event +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* @param pucEventBuf Pointer to event buffer +* +* @return none +* +*/ +/*----------------------------------------------------------------------------*/ + +VOID nicEventQueryMemDump(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEventBuf) +{ + P_EVENT_DUMP_MEM_T prEventDumpMem; + static UINT_8 aucPath[256]; + static UINT_8 aucPath_done[300]; + static UINT_32 u4CurTimeTick; + + ASSERT(prAdapter); + ASSERT(pucEventBuf); + + snprintf(aucPath, sizeof(aucPath), "/dump_%05hu.hex", g_u2DumpIndex); + + prEventDumpMem = (P_EVENT_DUMP_MEM_T) (pucEventBuf); + + if (kalCheckPath(aucPath) == -1) { + kalMemSet(aucPath, 0x00, 256); + snprintf(aucPath, sizeof(aucPath), + "/data/dump_%05hu.hex", g_u2DumpIndex); + } + + if (prEventDumpMem->ucFragNum == 1) { + /* Store memory dump into sdcard, + * path /sdcard/dump___.hex + */ + u4CurTimeTick = kalGetTimeTick(); +#if defined(LINUX) + + /*if blbist mkdir undre /data/blbist, the dump files wouls put on it */ + snprintf(aucPath, sizeof(aucPath), + "/dump_%05hu.hex", g_u2DumpIndex); + if (kalCheckPath(aucPath) == -1) { + kalMemSet(aucPath, 0x00, 256); + snprintf(aucPath, sizeof(aucPath), + "/data/dump_%05hu.hex", g_u2DumpIndex); + } +#else + kal_sprintf_ddk(aucPath, sizeof(aucPath), + u4CurTimeTick, + prEventDumpMem->u4Address, prEventDumpMem->u4Length + prEventDumpMem->u4RemainLength); +#endif + 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 CFG_SUPPORT_QA_TOOL + TsfRawData2IqFmt(prEventDumpMem); +#endif /* CFG_SUPPORT_QA_TOOL */ + DBGLOG(INIT, INFO, + "iCap : ==> (u4RemainLength = %x, u4Address=%x )\n", prEventDumpMem->u4RemainLength, + prEventDumpMem->u4Address); + + if (prEventDumpMem->u4RemainLength == 0 || prEventDumpMem->u4Address == 0xFFFFFFFF) { + + /* The request is finished or firmware response a error */ + /* Reply time tick to iwpriv */ + + g_bIcapEnable = FALSE; + g_bCaptureDone = TRUE; + + snprintf(aucPath_done, sizeof(aucPath_done), "/file_dump_done.txt"); + if (kalCheckPath(aucPath_done) == -1) { + kalMemSet(aucPath_done, 0x00, 256); + snprintf(aucPath_done, sizeof(aucPath_done), "/data/file_dump_done.txt"); + } + DBGLOG(INIT, INFO, ": ==> gen done_file\n"); + kalWriteToFile(aucPath_done, FALSE, aucPath_done, sizeof(aucPath_done)); +#if CFG_SUPPORT_QA_TOOL + g_au4Offset[0][0] = 0; + g_au4Offset[0][1] = 9; + g_au4Offset[1][0] = 0; + g_au4Offset[1][1] = 9; +#endif /* CFG_SUPPORT_QA_TOOL */ + + g_u2DumpIndex++; + + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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_GLUE_INFO_T prGlueInfo; + P_EVENT_DUMP_MEM_T prEventDumpMem; + static UINT_8 aucPath[256]; +/* static UINT_8 aucPath_done[300]; */ + static UINT_32 u4CurTimeTick; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (1) { + prGlueInfo = prAdapter->prGlueInfo; + prEventDumpMem = (P_EVENT_DUMP_MEM_T) (pucEventBuf); + + u4QueryInfoLen = sizeof(P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T); + + if (prEventDumpMem->ucFragNum == 1) { + /* Store memory dump into sdcard, + * path /sdcard/dump___.hex + */ + u4CurTimeTick = kalGetTimeTick(); +#if defined(LINUX) + + /* PeiHsuan add for avoiding out of memory 20160801 */ + if (g_u2DumpIndex >= 20) + g_u2DumpIndex = 0; + + /*if blbist mkdir undre /data/blbist, the dump files wouls put on it */ + snprintf(aucPath, sizeof(aucPath), + "/dump_%05hu.hex", g_u2DumpIndex); + if (kalCheckPath(aucPath) == -1) { + kalMemSet(aucPath, 0x00, 256); + snprintf(aucPath, sizeof(aucPath), + "/data/dump_%05hu.hex", g_u2DumpIndex); + } else + kalTrunkPath(aucPath); + + DBGLOG(INIT, INFO, + "iCap Create New Dump File dump_%05hu.hex\n", + g_u2DumpIndex); +#else + kal_sprintf_ddk(aucPath, sizeof(aucPath), + u4CurTimeTick, + prEventDumpMem->u4Address, + prEventDumpMem->u4Length + prEventDumpMem->u4RemainLength); + /* strcpy(aucPath, "dump.hex"); */ +#endif + 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 CFG_SUPPORT_QA_TOOL + TsfRawData2IqFmt(prEventDumpMem); +#endif /* CFG_SUPPORT_QA_TOOL */ + if (prEventDumpMem->u4RemainLength == 0 || prEventDumpMem->u4Address == 0xFFFFFFFF) { + /* The request is finished or firmware response a error */ + /* Reply time tick to iwpriv */ + if (prCmdInfo->fgIsOid) { + + /* the oid would be complete only in oid-trigger mode, + * that is no need to if the event-trigger + */ + if (g_bIcapEnable == FALSE) { + *((PUINT_32) prCmdInfo->pvInformationBuffer) = u4CurTimeTick; + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + } + g_bIcapEnable = FALSE; + g_bCaptureDone = TRUE; +#if defined(LINUX) + + g_u2DumpIndex++; + +#else + kal_sprintf_done_ddk(aucPath_done, sizeof(aucPath_done)); + kalWriteToFile(aucPath_done, FALSE, aucPath_done, sizeof(aucPath_done)); +#endif + } else { +#if defined(LINUX) + +#else /* 2013/05/26 fw would try to send the buffer successfully */ + /* The memory dump request is not finished, Send next command */ + wlanSendMemDumpCmd(prAdapter, + prCmdInfo->pvInformationBuffer, prCmdInfo->u4InformationBufferLength); +#endif + } + } + + return; + +} + +#if CFG_SUPPORT_BATCH_SCAN +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when event for SUPPORT_BATCH_SCAN +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* @param pucEventBuf Pointer to the event buffer +* +* @return none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicCmdEventBatchScanResult(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_EVENT_BATCH_RESULT_T prEventBatchResult; + P_GLUE_INFO_T prGlueInfo; + + DBGLOG(SCN, TRACE, "nicCmdEventBatchScanResult"); + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventBatchResult = (P_EVENT_BATCH_RESULT_T) pucEventBuf; + + u4QueryInfoLen = sizeof(EVENT_BATCH_RESULT_T); + kalMemCopy(prCmdInfo->pvInformationBuffer, prEventBatchResult, sizeof(EVENT_BATCH_RESULT_T)); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} +#endif + +VOID nicEventHifCtrl(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ +#if defined(_HIF_USB) + P_EVENT_HIF_CTRL_T prEventHifCtrl; + + prEventHifCtrl = (P_EVENT_HIF_CTRL_T) (prEvent->aucBuffer); + + DBGLOG(HAL, INFO, "%s: EVENT_ID_HIF_CTRL\n", __func__); + DBGLOG(HAL, INFO, "prEventHifCtrl->ucHifType = %hhu\n", prEventHifCtrl->ucHifType); + DBGLOG(HAL, INFO, "prEventHifCtrl->ucHifTxTrafficStatus, prEventHifCtrl->ucHifRxTrafficStatus = %hhu, %hhu\n", + prEventHifCtrl->ucHifTxTrafficStatus, prEventHifCtrl->ucHifRxTrafficStatus); + + if (prEventHifCtrl->ucHifTxTrafficStatus == ENUM_HIF_TRAFFIC_IDLE && + prEventHifCtrl->ucHifRxTrafficStatus == ENUM_HIF_TRAFFIC_IDLE) { /* success */ + halUSBPreSuspendDone(prAdapter, NULL, prEvent->aucBuffer); + } else if (prEventHifCtrl->ucHifTxTrafficStatus == ENUM_HIF_TRAFFIC_BUSY || + prEventHifCtrl->ucHifRxTrafficStatus == ENUM_HIF_TRAFFIC_BUSY) { /* busy */ + halUSBPreSuspendTimeout(prAdapter, NULL); + } else if (prEventHifCtrl->ucHifTxTrafficStatus == ENUM_HIF_TRAFFIC_INVALID || + prEventHifCtrl->ucHifRxTrafficStatus == ENUM_HIF_TRAFFIC_INVALID) { /* invalid */ + halUSBPreSuspendTimeout(prAdapter, NULL); + } +#endif +} + +#if CFG_SUPPORT_BUILD_DATE_CODE +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when event for build date code information +* has been retrieved +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* @param pucEventBuf Pointer to the event buffer +* +* @return none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicCmdEventBuildDateCode(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_EVENT_BUILD_DATE_CODE prEvent; + P_GLUE_INFO_T prGlueInfo; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEvent = (P_EVENT_BUILD_DATE_CODE) pucEventBuf; + + u4QueryInfoLen = sizeof(UINT_8) * 16; + kalMemCopy(prCmdInfo->pvInformationBuffer, prEvent->aucDateCode, sizeof(UINT_8) * 16); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when event for query STA link status +* has been retrieved +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* @param pucEventBuf Pointer to the event buffer +* +* @return none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicCmdEventQueryStaStatistics(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_EVENT_STA_STATISTICS_T prEvent; + P_GLUE_INFO_T prGlueInfo; + P_PARAM_GET_STA_STATISTICS prStaStatistics; + ENUM_WMM_ACI_T eAci; + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + ASSERT(prCmdInfo->pvInformationBuffer); + + + prGlueInfo = prAdapter->prGlueInfo; + prEvent = (P_EVENT_STA_STATISTICS_T) pucEventBuf; + prStaStatistics = + (P_PARAM_GET_STA_STATISTICS) prCmdInfo->pvInformationBuffer; + + u4QueryInfoLen = sizeof(PARAM_GET_STA_STA_STATISTICS); + + /* Statistics from FW is valid */ + if (prEvent->u4Flags & BIT(0)) { + prStaStatistics->ucPer = prEvent->ucPer; + prStaStatistics->ucRcpi = prEvent->ucRcpi; + prStaStatistics->u4PhyMode = prEvent->u4PhyMode; + prStaStatistics->u2LinkSpeed = prEvent->u2LinkSpeed; + + prStaStatistics->u4TxFailCount = prEvent->u4TxFailCount; + prStaStatistics->u4TxLifeTimeoutCount = + prEvent->u4TxLifeTimeoutCount; + prStaStatistics->u4TransmitCount = prEvent->u4TransmitCount; + prStaStatistics->u4TransmitFailCount = + prEvent->u4TransmitFailCount; + prStaStatistics->u4Rate1TxCnt = prEvent->u4Rate1TxCnt; + prStaStatistics->u4Rate1FailCnt = prEvent->u4Rate1FailCnt; + + prStaStatistics->ucTemperature = prEvent->ucTemperature; + prStaStatistics->ucSkipAr = prEvent->ucSkipAr; + prStaStatistics->ucArTableIdx = prEvent->ucArTableIdx; + prStaStatistics->ucRateEntryIdx = prEvent->ucRateEntryIdx; + prStaStatistics->ucRateEntryIdxPrev = + prEvent->ucRateEntryIdxPrev; + prStaStatistics->ucTxSgiDetectPassCnt = + prEvent->ucTxSgiDetectPassCnt; + prStaStatistics->ucAvePer = prEvent->ucAvePer; + kalMemCopy(prStaStatistics->aucArRatePer, prEvent->aucArRatePer, + sizeof(prEvent->aucArRatePer)); + kalMemCopy(prStaStatistics->aucRateEntryIndex, + prEvent->aucRateEntryIndex, + sizeof(prEvent->aucRateEntryIndex)); + prStaStatistics->ucArStateCurr = prEvent->ucArStateCurr; + prStaStatistics->ucArStatePrev = prEvent->ucArStatePrev; + prStaStatistics->ucArActionType = prEvent->ucArActionType; + prStaStatistics->ucHighestRateCnt = prEvent->ucHighestRateCnt; + prStaStatistics->ucLowestRateCnt = prEvent->ucLowestRateCnt; + prStaStatistics->u2TrainUp = prEvent->u2TrainUp; + prStaStatistics->u2TrainDown = prEvent->u2TrainDown; + kalMemCopy(&prStaStatistics->rTxVector, &prEvent->rTxVector, + sizeof(prEvent->rTxVector)); + kalMemCopy(&prStaStatistics->rMibInfo, &prEvent->rMibInfo, + sizeof(prEvent->rMibInfo)); + prStaStatistics->fgIsForceTxStream = prEvent->fgIsForceTxStream; + prStaStatistics->fgIsForceSeOff = prEvent->fgIsForceSeOff; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prEvent->ucStaRecIdx); + + if (prStaRec) { + /*link layer statistics */ + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prStaStatistics->arLinkStatistics[eAci]. + u4TxFailMsdu = + prEvent->arLinkStatistics[eAci].u4TxFailMsdu; + + prStaStatistics->arLinkStatistics[eAci]. + u4TxRetryMsdu = + prEvent->arLinkStatistics[eAci].u4TxRetryMsdu; + + /*for dump bss statistics */ + prStaRec->arLinkStatistics[eAci].u4TxFailMsdu = + prEvent->arLinkStatistics[eAci].u4TxFailMsdu; + prStaRec->arLinkStatistics[eAci].u4TxRetryMsdu = + prEvent->arLinkStatistics[eAci].u4TxRetryMsdu; + } + } + if (prEvent->u4TxCount) { + UINT_32 u4TxDoneAirTimeMs = + USEC_TO_MSEC(prEvent->u4TxDoneAirTime * 32); + + prStaStatistics->u4TxAverageAirTime = + (u4TxDoneAirTimeMs / prEvent->u4TxCount); + } else { + prStaStatistics->u4TxAverageAirTime = 0; + } + } + + if (prCmdInfo->fgIsOid) + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); +} + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when event for query LTE safe channels +* has been retrieved +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* @param pucEventBuf Pointer to the event buffer +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicCmdEventQueryLteSafeChn(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_EVENT_LTE_SAFE_CHN_T prEvent; + P_GLUE_INFO_T prGlueInfo; + P_PARAM_GET_CHN_INFO prLteSafeChnInfo; + UINT_8 ucIdx = 0; + + if ((prAdapter == NULL) + || (prCmdInfo == NULL) + || (pucEventBuf == NULL) + || (prCmdInfo->pvInformationBuffer == NULL)) { + ASSERT(FALSE); + return; + } + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEvent = (P_EVENT_LTE_SAFE_CHN_T) pucEventBuf; /* FW responsed data */ + + prLteSafeChnInfo = (P_PARAM_GET_CHN_INFO) prCmdInfo->pvInformationBuffer; + + u4QueryInfoLen = sizeof(PARAM_GET_CHN_INFO); + + /* Statistics from FW is valid */ + if (prEvent->u4Flags & BIT(0)) { + for (ucIdx = 0; ucIdx < NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_MAX; ucIdx++) { + prLteSafeChnInfo->rLteSafeChnList.au4SafeChannelBitmask[ucIdx] = + prEvent->rLteSafeChn.au4SafeChannelBitmask[ucIdx]; + + DBGLOG(P2P, INFO, + "[ACS]LTE safe channels[%d]=0x%08x\n", ucIdx, + prLteSafeChnInfo->rLteSafeChnList.au4SafeChannelBitmask[ucIdx]); + } + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} +#endif + +VOID nicEventRddPulseDump(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEventBuf) +{ + UINT_16 u2Idx, u2PulseCnt; + P_EVENT_WIFI_RDD_TEST_T prRddPulseEvent; + + ASSERT(prAdapter); + ASSERT(pucEventBuf); + + prRddPulseEvent = (P_EVENT_WIFI_RDD_TEST_T) (pucEventBuf); + + u2PulseCnt = (prRddPulseEvent->u4FuncLength - RDD_EVENT_HDR_SIZE) / RDD_ONEPLUSE_SIZE; + + DBGLOG(INIT, INFO, "[RDD]0x%08x %08d[RDD%d]\n", prRddPulseEvent->u4Prefix + , prRddPulseEvent->u4Count, prRddPulseEvent->ucRddIdx); + + for (u2Idx = 0; u2Idx < u2PulseCnt; u2Idx++) { + DBGLOG(INIT, INFO, "[RDD]0x%02x%02x%02x%02x %02x%02x%02x%02x[RDD%d]\n" + , prRddPulseEvent->aucBuffer[RDD_ONEPLUSE_SIZE*u2Idx+RDD_PULSE_OFFSET3] + , prRddPulseEvent->aucBuffer[RDD_ONEPLUSE_SIZE*u2Idx+RDD_PULSE_OFFSET2] + , prRddPulseEvent->aucBuffer[RDD_ONEPLUSE_SIZE*u2Idx+RDD_PULSE_OFFSET1] + , prRddPulseEvent->aucBuffer[RDD_ONEPLUSE_SIZE*u2Idx+RDD_PULSE_OFFSET0] + , prRddPulseEvent->aucBuffer[RDD_ONEPLUSE_SIZE*u2Idx+RDD_PULSE_OFFSET7] + , prRddPulseEvent->aucBuffer[RDD_ONEPLUSE_SIZE*u2Idx+RDD_PULSE_OFFSET6] + , prRddPulseEvent->aucBuffer[RDD_ONEPLUSE_SIZE*u2Idx+RDD_PULSE_OFFSET5] + , prRddPulseEvent->aucBuffer[RDD_ONEPLUSE_SIZE*u2Idx+RDD_PULSE_OFFSET4] + , prRddPulseEvent->ucRddIdx + ); + } + + DBGLOG(INIT, INFO, "[RDD]0x%08x %08x[RDD%d]\n", prRddPulseEvent->u4SubBandRssi0 + , prRddPulseEvent->u4SubBandRssi1, prRddPulseEvent->ucRddIdx); + +} + + +#if CFG_SUPPORT_ADVANCE_CONTROL +VOID nicCmdEventQueryAdvCtrl(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + PUINT_8 query; + P_GLUE_INFO_T prGlueInfo; + UINT_32 query_len; + P_CMD_ADV_CONFIG_HEADER_T hdr; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (!pucEventBuf) { + DBGLOG(REQ, ERROR, "pucEventBuf is null.\n"); + return; + } + hdr = (P_CMD_ADV_CONFIG_HEADER_T) pucEventBuf; + DBGLOG(REQ, LOUD, "%s type %x len %d>\n", __func__, hdr->u2Type, hdr->u2Len); + + prGlueInfo = prAdapter->prGlueInfo; + query_len = hdr->u2Len; + query = prCmdInfo->pvInformationBuffer; + if (query && (query_len == prCmdInfo->u4InformationBufferLength)) + kalMemCopy(query, hdr, query_len); + else + DBGLOG(REQ, LOUD, "%s type %x, len %d != buflen %d>\n", + __func__, hdr->u2Type, hdr->u2Len, + prCmdInfo->u4InformationBufferLength); + + if (prCmdInfo->fgIsOid) + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + query_len, WLAN_STATUS_SUCCESS); +} +#endif + +#if CFG_SUPPORT_MSP +VOID nicCmdEventQueryWlanInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_PARAM_HW_WLAN_INFO_T prWlanInfo; + P_EVENT_WLAN_INFO prEventWlanInfo; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventWlanInfo = (P_EVENT_WLAN_INFO) pucEventBuf; + + DBGLOG(RSN, INFO, "MT6632 : nicCmdEventQueryWlanInfo\n"); + + prGlueInfo = prAdapter->prGlueInfo; + + u4QueryInfoLen = sizeof(PARAM_HW_WLAN_INFO_T); + prWlanInfo = (P_PARAM_HW_WLAN_INFO_T) prCmdInfo->pvInformationBuffer; + + /* prWlanInfo->u4Length = sizeof(PARAM_HW_WLAN_INFO_T); */ + if (prEventWlanInfo && prWlanInfo) { + kalMemCopy(&prWlanInfo->rWtblTxConfig, + &prEventWlanInfo->rWtblTxConfig, + sizeof(PARAM_TX_CONFIG_T)); + kalMemCopy(&prWlanInfo->rWtblSecConfig, + &prEventWlanInfo->rWtblSecConfig, + sizeof(PARAM_SEC_CONFIG_T)); + kalMemCopy(&prWlanInfo->rWtblKeyConfig, + &prEventWlanInfo->rWtblKeyConfig, + sizeof(PARAM_KEY_CONFIG_T)); + kalMemCopy(&prWlanInfo->rWtblRateInfo, + &prEventWlanInfo->rWtblRateInfo, + sizeof(PARAM_PEER_RATE_INFO_T)); + kalMemCopy(&prWlanInfo->rWtblBaConfig, + &prEventWlanInfo->rWtblBaConfig, + sizeof(PARAM_PEER_BA_CONFIG_T)); + kalMemCopy(&prWlanInfo->rWtblPeerCap, + &prEventWlanInfo->rWtblPeerCap, + sizeof(PARAM_PEER_CAP_T)); + kalMemCopy(&prWlanInfo->rWtblRxCounter, + &prEventWlanInfo->rWtblRxCounter, + sizeof(PARAM_PEER_RX_COUNTER_ALL_T)); + kalMemCopy(&prWlanInfo->rWtblTxCounter, + &prEventWlanInfo->rWtblTxCounter, + sizeof(PARAM_PEER_TX_COUNTER_ALL_T)); + } + + if (prCmdInfo->fgIsOid) + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); +} + + +VOID nicCmdEventQueryMibInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_PARAM_HW_MIB_INFO_T prMibInfo; + P_EVENT_MIB_INFO prEventMibInfo; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventMibInfo = (P_EVENT_MIB_INFO) pucEventBuf; + + DBGLOG(RSN, INFO, "MT6632 : nicCmdEventQueryMibInfo\n"); + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + u4QueryInfoLen = sizeof(PARAM_HW_MIB_INFO_T); + prMibInfo = (P_PARAM_HW_MIB_INFO_T) prCmdInfo->pvInformationBuffer; + if (prEventMibInfo && prMibInfo) { + kalMemCopy(&prMibInfo->rHwMibCnt, + &prEventMibInfo->rHwMibCnt, + sizeof(HW_MIB_COUNTER_T)); + kalMemCopy(&prMibInfo->rHwMib2Cnt, + &prEventMibInfo->rHwMib2Cnt, + sizeof(HW_MIB2_COUNTER_T)); + kalMemCopy(&prMibInfo->rHwTxAmpduMts, + &prEventMibInfo->rHwTxAmpduMts, + sizeof(HW_TX_AMPDU_METRICS_T)); + } + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} +#endif + +#if CFG_SUPPORT_LAST_SEC_MCS_INFO +VOID nicCmdEventTxMcsInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_GLUE_INFO_T prGlueInfo; + struct EVENT_TX_MCS_INFO *prTxMcsEvent; + struct PARAM_TX_MCS_INFO *prTxMcsInfo; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + ASSERT(prCmdInfo->pvInformationBuffer); + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prTxMcsEvent = (struct EVENT_TX_MCS_INFO *) pucEventBuf; + prTxMcsInfo = (struct PARAM_TX_MCS_INFO *) prCmdInfo->pvInformationBuffer; + + u4QueryInfoLen = sizeof(struct EVENT_TX_MCS_INFO); + + kalMemCopy(prTxMcsInfo->au2TxRateCode, prTxMcsEvent->au2TxRateCode, + sizeof(prTxMcsEvent->au2TxRateCode)); + kalMemCopy(prTxMcsInfo->aucTxRatePer, prTxMcsEvent->aucTxRatePer, + sizeof(prTxMcsEvent->aucTxRatePer)); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} +#endif + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +WLAN_STATUS nicCmdEventQueryNicCsumOffload(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEventBuf) +{ + P_NIC_CSUM_OFFLOAD_T prChecksumOffload = (P_NIC_CSUM_OFFLOAD_T)pucEventBuf; + + prAdapter->fgIsSupportCsumOffload = prChecksumOffload->ucIsSupportCsumOffload; + + DBGLOG(INIT, INFO, "nicCmdEventQueryNicCsumOffload: ucIsSupportCsumOffload = %x\n", + prAdapter->fgIsSupportCsumOffload); + + return WLAN_STATUS_SUCCESS; +} +#endif + +WLAN_STATUS nicCmdEventQueryNicCoexFeature(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEventBuf) +{ + P_NIC_COEX_FEATURE_T prCoexFeature = (P_NIC_COEX_FEATURE_T)pucEventBuf; + + prAdapter->u4FddMode = prCoexFeature->u4FddMode; + + DBGLOG(INIT, INFO, "nicCmdEventQueryNicCoexFeature: u4FddMode = %x\n", + prAdapter->u4FddMode); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS nicCmdEventQueryNicEfuseAddr(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEventBuf) +{ + P_NIC_EFUSE_ADDRESS_T prTxResource = (P_NIC_EFUSE_ADDRESS_T)pucEventBuf; + + prAdapter->u4EfuseStartAddress = prTxResource->u4EfuseStartAddress; + prAdapter->u4EfuseEndAddress = prTxResource->u4EfuseEndAddress; + + DBGLOG(INIT, INFO, "nicCmdEventQueryNicEfuseAddr: u4EfuseStartAddress = %x\n", + prAdapter->u4EfuseStartAddress); + DBGLOG(INIT, INFO, "nicCmdEventQueryNicEfuseAddr: u4EfuseEndAddress = %x\n", + prAdapter->u4EfuseEndAddress); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS nicCmdEventQueryEfuseOffset(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEventBuf) +{ + struct _NIC_EFUSE_OFFSET_T *prEfuseOffset = (struct _NIC_EFUSE_OFFSET_T *)pucEventBuf; + + if (prEfuseOffset->u4TotalItem > 0) + prAdapter->u4EfuseMacAddrOffset = prEfuseOffset->u4WlanMacAddr; + + return WLAN_STATUS_SUCCESS; +} + + +WLAN_STATUS nicCmdEventQueryRModeCapability(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEventBuf) +{ + struct _CAP_R_MODE_CAP_T *prRModeOffset = (struct _CAP_R_MODE_CAP_T *)pucEventBuf; + + prAdapter->ucRModeOnlyFlag = prRModeOffset->ucRModeOnlyFlag; + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS nicCmdEventQueryNicTxResource(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEventBuf) +{ + P_NIC_TX_RESOURCE_T prTxResource = (P_NIC_TX_RESOURCE_T)pucEventBuf; + + prAdapter->fgIsNicTxReousrceValid = TRUE; + prAdapter->nicTxReousrce.u4McuTotalResource = prTxResource->u4McuTotalResource; + prAdapter->nicTxReousrce.u4McuResourceUnit = prTxResource->u4McuResourceUnit; + prAdapter->nicTxReousrce.u4LmacTotalResource = prTxResource->u4LmacTotalResource; + prAdapter->nicTxReousrce.u4LmacResourceUnit = prTxResource->u4LmacResourceUnit; + + DBGLOG(INIT, INFO, "nicCmdEventQueryNicTxResource: u4McuTotalResource = %x\n", + prAdapter->nicTxReousrce.u4McuTotalResource); + DBGLOG(INIT, INFO, "nicCmdEventQueryNicTxResource: u4McuResourceUnit = %x\n", + prAdapter->nicTxReousrce.u4McuResourceUnit); + DBGLOG(INIT, INFO, "nicCmdEventQueryNicTxResource: u4LmacTotalResource = %x\n", + prAdapter->nicTxReousrce.u4LmacTotalResource); + DBGLOG(INIT, INFO, "nicCmdEventQueryNicTxResource: u4LmacResourceUnit = %x\n", + prAdapter->nicTxReousrce.u4LmacResourceUnit); + + return WLAN_STATUS_SUCCESS; +} + +VOID nicCmdEventQueryNicCapabilityV2(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEventBuf) +{ + P_EVENT_NIC_CAPABILITY_V2_T prEventNicV2 = (P_EVENT_NIC_CAPABILITY_V2_T)pucEventBuf; + P_NIC_CAPABILITY_V2_ELEMENT prElement; + UINT_32 tag_idx, table_idx, offset; + + offset = 0; + + /* process each element */ + for (tag_idx = 0; tag_idx < prEventNicV2->u2TotalElementNum; tag_idx++) { + + prElement = (P_NIC_CAPABILITY_V2_ELEMENT)(prEventNicV2->aucBuffer + offset); + + for (table_idx = 0; + table_idx < (sizeof(gNicCapabilityV2InfoTable)/sizeof(NIC_CAPABILITY_V2_REF_TABLE_T)); + table_idx++) { + + /* find the corresponding tag's handler */ + if (gNicCapabilityV2InfoTable[table_idx].tag_type == prElement->tag_type) { + gNicCapabilityV2InfoTable[table_idx].hdlr(prAdapter, prElement->aucbody); + break; + } + } + + /* move to the next tag */ + offset += prElement->body_len + (UINT_16) OFFSET_OF(NIC_CAPABILITY_V2_ELEMENT, aucbody); + } + +} + +VOID nicEventLinkQuality(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_CMD_INFO_T prCmdInfo; + +#if CFG_ENABLE_WIFI_DIRECT && CFG_SUPPORT_P2P_RSSI_QUERY + if (prEvent->u2PacketLen == EVENT_HDR_WITHOUT_RXD_SIZE + sizeof(EVENT_LINK_QUALITY_EX)) { + P_EVENT_LINK_QUALITY_EX prLqEx = (P_EVENT_LINK_QUALITY_EX) (prEvent->aucBuffer); + + if (prLqEx->ucIsLQ0Rdy) + nicUpdateLinkQuality(prAdapter, 0, (P_EVENT_LINK_QUALITY) prLqEx); + if (prLqEx->ucIsLQ1Rdy) + nicUpdateLinkQuality(prAdapter, 1, (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, 0, (P_EVENT_LINK_QUALITY) (prEvent->aucBuffer)); + } +#else + /*only support ais query */ + { + UINT_8 ucBssIndex; + P_BSS_INFO_T prBssInfo; + + for (ucBssIndex = 0; ucBssIndex < BSS_INFO_NUM; ucBssIndex++) { + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + + if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS && prBssInfo->fgIsInUse) + break; + } + + if (ucBssIndex >= BSS_INFO_NUM) + ucBssIndex = 1; /* No hit(bss1 for default ais network) */ + /* printk("=======> rssi with bss%d ,%d\n",ucBssIndex, + * ((P_EVENT_LINK_QUALITY_V2)(prEvent->aucBuffer))->rLq[ucBssIndex].cRssi); + */ + nicUpdateLinkQuality(prAdapter, ucBssIndex, (P_EVENT_LINK_QUALITY_V2) (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(prAdapter->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(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID)&(prAdapter->rWlanInfo.rRssiTriggerValue), sizeof(PARAM_RSSI)); + } +#endif +} + +VOID nicEventLayer0ExtMagic(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + UINT_32 u4QueryInfoLen; + P_CMD_INFO_T prCmdInfo; + P_EVENT_ACCESS_EFUSE prEventEfuseAccess; + P_EVENT_EFUSE_FREE_BLOCK_T prEventGetFreeBlock; + P_EVENT_GET_TX_POWER_T prEventGetTXPower; + + if ((prEvent->ucExtenEID) == EXT_EVENT_ID_CMD_RESULT) { + + u4QueryInfoLen = sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T); + + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + if ((prCmdInfo->fgIsOid) != 0) { + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + } + } else if ((prEvent->ucExtenEID) == EXT_EVENT_ID_CMD_EFUSE_ACCESS) { + u4QueryInfoLen = sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T); + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + prEventEfuseAccess = (P_EVENT_ACCESS_EFUSE) (prEvent->aucBuffer); + + /* Efuse block size 16 */ + kalMemCopy(prAdapter->aucEepromVaule, prEventEfuseAccess->aucData, 16); + + if (prCmdInfo != NULL) { + if ((prCmdInfo->fgIsOid) != 0) { + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + } + } + } else if ((prEvent->ucExtenEID) == EXT_EVENT_ID_EFUSE_FREE_BLOCK) { + u4QueryInfoLen = sizeof(PARAM_CUSTOM_EFUSE_FREE_BLOCK_T); + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + prEventGetFreeBlock = (P_EVENT_EFUSE_FREE_BLOCK_T) (prEvent->aucBuffer); + prAdapter->u4FreeBlockNum = prEventGetFreeBlock->u2FreeBlockNum; + + if (prCmdInfo != NULL) { + if ((prCmdInfo->fgIsOid) != 0) { + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + } + } else if ((prEvent->ucExtenEID) == EXT_EVENT_ID_GET_TX_POWER) { + u4QueryInfoLen = sizeof(PARAM_CUSTOM_GET_TX_POWER_T); + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + prEventGetTXPower = (P_EVENT_GET_TX_POWER_T) (prEvent->aucBuffer); + + prAdapter->u4GetTxPower = prEventGetTXPower->ucTx0TargetPower; + + if (prCmdInfo != NULL) { + if ((prCmdInfo->fgIsOid) != 0) { + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + } + } + } +} + +VOID nicEventMicErrorInfo(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + 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, prAdapter->prAisBssInfo->ucBssIndex, + 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 +} + +VOID nicEventScanDone(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + scnEventScanDone(prAdapter, (P_EVENT_SCAN_DONE) (prEvent->aucBuffer), TRUE); +} + +VOID nicEventNloDone(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + DBGLOG(INIT, INFO, "EVENT_ID_NLO_DONE\n"); + scnEventNloDone(prAdapter, (P_EVENT_NLO_DONE_T) (prEvent->aucBuffer)); +#if CFG_SUPPORT_PNO + prAdapter->prAisBssInfo->fgIsPNOEnable = FALSE; + if (prAdapter->prAisBssInfo->fgIsNetRequestInActive && prAdapter->prAisBssInfo->fgIsPNOEnable) { + UNSET_NET_ACTIVE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + DBGLOG(INIT, INFO, "INACTIVE AIS from ACTIVEto disable PNO\n"); + /* sync with firmware */ + nicDeactivateNetwork(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + } +#endif +} + +VOID nicEventSleepyNotify(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ +#if !defined(_HIF_USB) + P_EVENT_SLEEPY_INFO_T prEventSleepyNotify; + + prEventSleepyNotify = (P_EVENT_SLEEPY_INFO_T) (prEvent->aucBuffer); + + /* DBGLOG(RX, INFO, ("ucSleepyState = %d\n", prEventSleepyNotify->ucSleepyState)); */ + + prAdapter->fgWiFiInSleepyState = (BOOLEAN) (prEventSleepyNotify->ucSleepyState); + +#if CFG_SUPPORT_MULTITHREAD + if (prEventSleepyNotify->ucSleepyState) + kalSetFwOwnEvent2Hif(prAdapter->prGlueInfo); +#endif +#endif +} + +VOID nicEventBtOverWifi(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ +#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); + } +#endif +} + +VOID nicEventStatistics(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_CMD_INFO_T prCmdInfo; + + /* 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); + } +} +VOID nicEventWlanInfo(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_CMD_INFO_T prCmdInfo; + + /* buffer statistics for further query */ + prAdapter->fgIsStatValid = TRUE; + prAdapter->rStatUpdateTime = kalGetTimeTick(); + kalMemCopy(&prAdapter->rEventWlanInfo, prEvent->aucBuffer, sizeof(EVENT_WLAN_INFO)); + + DBGLOG(RSN, INFO, "EVENT_ID_WLAN_INFO"); + /* 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); + } +} + +VOID nicEventMibInfo(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_CMD_INFO_T prCmdInfo; + + + /* buffer statistics for further query */ + prAdapter->fgIsStatValid = TRUE; + prAdapter->rStatUpdateTime = kalGetTimeTick(); + + DBGLOG(RSN, INFO, "EVENT_ID_MIB_INFO"); + /* 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); + } + +} + +#if CFG_SUPPORT_LAST_SEC_MCS_INFO +VOID nicEventTxMcsInfo(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_CMD_INFO_T prCmdInfo; + + DBGLOG(RSN, INFO, "EVENT_ID_TX_MCS_INFO"); + /* 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); + } + +} +#endif + +VOID nicEventBeaconTimeout(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + DBGLOG(NIC, INFO, "EVENT_ID_BSS_BEACON_TIMEOUT\n"); + + if (prAdapter->fgDisBcnLostDetection == FALSE) { + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; + P_EVENT_BSS_BEACON_TIMEOUT_T prEventBssBeaconTimeout; + + prEventBssBeaconTimeout = (P_EVENT_BSS_BEACON_TIMEOUT_T) (prEvent->aucBuffer); + + if (prEventBssBeaconTimeout->ucBssIndex >= MAX_BSS_INDEX) + return; + + DBGLOG(NIC, INFO, "Reason code: %d\n", prEventBssBeaconTimeout->ucReasonCode); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prEventBssBeaconTimeout->ucBssIndex); + + if (prEventBssBeaconTimeout->ucBssIndex == + prAdapter->prAisBssInfo->ucBssIndex) { +#if CFG_DISCONN_DEBUG_FEATURE + g_rDisconnInfoTemp.ucBcnTimeoutReason = + prEventBssBeaconTimeout->ucReasonCode; +#endif + aisBssBeaconTimeout(prAdapter); + } +#if CFG_ENABLE_WIFI_DIRECT + else if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) + p2pRoleFsmRunEventBeaconTimeout(prAdapter, prBssInfo); +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (GET_BSS_INFO_BY_INDEX(prAdapter, prEventBssBeaconTimeout->ucBssIndex)->eNetworkType == + NETWORK_TYPE_BOW) { + /* ToDo:: Nothing */ + } +#endif + else { + DBGLOG(RX, ERROR, "EVENT_ID_BSS_BEACON_TIMEOUT: (ucBssIndex = %d)\n", + prEventBssBeaconTimeout->ucBssIndex); + } + } + +} + +VOID nicEventUpdateNoaParams(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ +#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 (GET_BSS_INFO_BY_INDEX(prAdapter, prEventUpdateNoaParam->ucBssIndex)->eNetworkType == + NETWORK_TYPE_P2P) { + + p2pProcessEvent_UpdateNOAParam(prAdapter, prEventUpdateNoaParam->ucBssIndex, + prEventUpdateNoaParam); + } else { + ASSERT(0); + } + } +#else + ASSERT(0); +#endif +} + +VOID nicEventStaAgingTimeout(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + 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) + return; + + DBGLOG(NIC, INFO, "EVENT_ID_STA_AGING_TIMEOUT %u " MACSTR "\n", + prEventStaAgingTimeout->ucStaRecIdx, MAC2STR(prStaRec->aucMacAddr)); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + bssRemoveClient(prAdapter, prBssInfo, prStaRec); + + /* Call False Auth */ + if (prAdapter->fgIsP2PRegistered) { + p2pFuncDisconnect(prAdapter, prBssInfo, prStaRec, TRUE, + REASON_CODE_DISASSOC_INACTIVITY); + } + + } + /* gDisStaAgingTimeoutDetection */ +} + +VOID nicEventApObssStatus(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) + rlmHandleObssStatusEventPkt(prAdapter, (P_EVENT_AP_OBSS_STATUS_T) prEvent->aucBuffer); +#endif +} + +VOID nicEventRoamingStatus(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ +#if CFG_SUPPORT_ROAMING + P_CMD_ROAMING_TRANSIT_T prTransit; + + prTransit = (P_CMD_ROAMING_TRANSIT_T) (prEvent->aucBuffer); + + roamingFsmProcessEvent(prAdapter, prTransit); +#endif /* CFG_SUPPORT_ROAMING */ +} + +VOID nicEventSendDeauth(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + SW_RFB_T rSwRfb; + +#if DBG + P_WLAN_MAC_HEADER_T prWlanMacHeader; + + prWlanMacHeader = (P_WLAN_MAC_HEADER_T) &prEvent->aucBuffer[0]; + DBGLOG(RX, TRACE, "nicRx: aucAddr1: " MACSTR "\n", MAC2STR(prWlanMacHeader->aucAddr1)); + DBGLOG(RX, TRACE, "nicRx: aucAddr2: " MACSTR "\n", MAC2STR(prWlanMacHeader->aucAddr2)); +#endif + + /* receive packets without StaRec */ + rSwRfb.pvHeader = (P_WLAN_MAC_HEADER_T) &prEvent->aucBuffer[0]; + if (authSendDeauthFrame(prAdapter, NULL, NULL, &rSwRfb, REASON_CODE_CLASS_3_ERR, + (PFN_TX_DONE_HANDLER) NULL) == WLAN_STATUS_SUCCESS) { + + DBGLOG(RX, TRACE, "Send Deauth Error\n"); + } +} + +VOID nicEventUpdateRddStatus(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ +#if CFG_SUPPORT_RDD_TEST_MODE + P_EVENT_RDD_STATUS_T prEventRddStatus; + + prEventRddStatus = (P_EVENT_RDD_STATUS_T) (prEvent->aucBuffer); + + prAdapter->ucRddStatus = prEventRddStatus->ucRddStatus; +#endif +} + +VOID nicEventUpdateBwcsStatus(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_PTA_IPC_T prEventBwcsStatus; + + prEventBwcsStatus = (P_PTA_IPC_T) (prEvent->aucBuffer); + +#if CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(RSN, EVENT, "BCM BWCS Event: %02x%02x%02x%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)); +} + +VOID nicEventUpdateBcmDebug(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_PTA_IPC_T prEventBwcsStatus; + + prEventBwcsStatus = (P_PTA_IPC_T) (prEvent->aucBuffer); + +#if CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(RSN, EVENT, "BCM FW status: %02x%02x%02x%02x\n", + prEventBwcsStatus->u.aucBTPParams[0], + prEventBwcsStatus->u.aucBTPParams[1], + prEventBwcsStatus->u.aucBTPParams[2], prEventBwcsStatus->u.aucBTPParams[3]); +#endif +} + +VOID nicEventAddPkeyDone(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_EVENT_ADD_KEY_DONE_INFO prAddKeyDone; + P_STA_RECORD_T prStaRec; + + prAddKeyDone = (P_EVENT_ADD_KEY_DONE_INFO) (prEvent->aucBuffer); + + DBGLOG(RSN, EVENT, "EVENT_ID_ADD_PKEY_DONE BSSIDX=%d " MACSTR "\n", + prAddKeyDone->ucBSSIndex, MAC2STR(prAddKeyDone->aucStaAddr)); + + prStaRec = cnmGetStaRecByAddress(prAdapter, prAddKeyDone->ucBSSIndex, prAddKeyDone->aucStaAddr); + + if (prStaRec) { + DBGLOG(RSN, EVENT, "STA " MACSTR " Add Key Done!!\n", MAC2STR(prStaRec->aucMacAddr)); + prStaRec->fgIsTxKeyReady = TRUE; + qmUpdateStaRec(prAdapter, prStaRec); + } +} + +VOID nicEventIcapDone(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_EVENT_ICAP_STATUS_T prEventIcapStatus; + PARAM_CUSTOM_MEM_DUMP_STRUCT_T rMemDumpInfo; + UINT_32 u4QueryInfo; + + prEventIcapStatus = (P_EVENT_ICAP_STATUS_T) (prEvent->aucBuffer); + + rMemDumpInfo.u4Address = prEventIcapStatus->u4StartAddress; + rMemDumpInfo.u4Length = prEventIcapStatus->u4IcapSieze; +#if CFG_SUPPORT_QA_TOOL + rMemDumpInfo.u4IcapContent = prEventIcapStatus->u4IcapContent; +#endif + + wlanoidQueryMemDump(prAdapter, &rMemDumpInfo, sizeof(rMemDumpInfo), &u4QueryInfo); +} + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +PARAM_CAL_BACKUP_STRUCT_V2_T g_rCalBackupDataV2; + +VOID nicEventCalAllDone(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_CMD_CAL_BACKUP_STRUCT_V2_T prEventCalBackupDataV2; + UINT_32 u4QueryInfo; + + DBGLOG(RFTEST, INFO, "%s\n", __func__); + + memset(&g_rCalBackupDataV2, 0, sizeof(PARAM_CAL_BACKUP_STRUCT_V2_T)); + + prEventCalBackupDataV2 = (P_CMD_CAL_BACKUP_STRUCT_V2_T) (prEvent->aucBuffer); + + if (prEventCalBackupDataV2->ucReason == 1 && prEventCalBackupDataV2->ucAction == 2) { + DBGLOG(RFTEST, INFO, "Received an EVENT for Trigger Do All Cal Function.\n"); + + g_rCalBackupDataV2.ucReason = 2; + g_rCalBackupDataV2.ucAction = 4; + g_rCalBackupDataV2.ucNeedResp = 1; + g_rCalBackupDataV2.ucFragNum = 0; + g_rCalBackupDataV2.ucRomRam = 0; + g_rCalBackupDataV2.u4ThermalValue = 0; + g_rCalBackupDataV2.u4Address = 0; + g_rCalBackupDataV2.u4Length = 0; + g_rCalBackupDataV2.u4RemainLength = 0; + + DBGLOG(RFTEST, INFO, "RLM CMD : Get Cal Data from FW (%s). Start!!!!!!!!!!!!!!!!\n", + g_rCalBackupDataV2.ucRomRam == 0 ? "ROM" : "RAM"); + DBGLOG(RFTEST, INFO, "Thermal Temp = %d\n", g_rBackupCalDataAllV2.u4ThermalInfo); + wlanoidQueryCalBackupV2(prAdapter, + &g_rCalBackupDataV2, + sizeof(PARAM_CAL_BACKUP_STRUCT_V2_T), + &u4QueryInfo); + } + +} +#endif + +VOID nicEventDebugMsg(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_EVENT_DEBUG_MSG_T prEventDebugMsg; + UINT_16 u2DebugMsgId; + UINT_8 ucMsgType; + UINT_8 ucFlags; + UINT_32 u4Value; + UINT_16 u2MsgSize; + P_UINT_8 pucMsg; + + prEventDebugMsg = (P_EVENT_DEBUG_MSG_T) (prEvent->aucBuffer); + + u2DebugMsgId = prEventDebugMsg->u2DebugMsgId; + ucMsgType = prEventDebugMsg->ucMsgType; + ucFlags = prEventDebugMsg->ucFlags; + u4Value = prEventDebugMsg->u4Value; + u2MsgSize = prEventDebugMsg->u2MsgSize; + pucMsg = prEventDebugMsg->aucMsg; + + DBGLOG(SW4, TRACE, "DEBUG_MSG Id %u Type %u Fg 0x%x Val 0x%x Size %u\n", + u2DebugMsgId, ucMsgType, ucFlags, u4Value, u2MsgSize); + + if (u2MsgSize <= DEBUG_MSG_SIZE_MAX) { + if (ucMsgType >= DEBUG_MSG_TYPE_END) + ucMsgType = DEBUG_MSG_TYPE_MEM32; + + if (ucMsgType == DEBUG_MSG_TYPE_ASCII) { + PUINT_8 pucChr; + + pucMsg[u2MsgSize] = '\0'; + + /* skip newline */ + pucChr = kalStrChr(pucMsg, '\0'); + if (*(pucChr - 1) == '\n') + *(pucChr - 1) = '\0'; + + DBGLOG(SW4, EVENT, "%s\n", pucMsg); + } else if (ucMsgType == DEBUG_MSG_TYPE_MEM8) { + DBGLOG(SW4, INFO, "Dump MEM8\n"); + DBGLOG_MEM8(SW4, INFO, pucMsg, u2MsgSize); + } else { + DBGLOG(SW4, INFO, "Dump MEM32\n"); + DBGLOG_MEM32(SW4, INFO, pucMsg, u2MsgSize); + } + } /* DEBUG_MSG_SIZE_MAX */ + else + DBGLOG(SW4, INFO, "Debug msg size %u is too large.\n", u2MsgSize); +} + +VOID nicEventTdls(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ +#if CFG_SUPPORT_TDLS + TdlsexEventHandle(prAdapter->prGlueInfo, (PUINT_8)prEvent->aucBuffer, + (UINT_32)(prEvent->u2PacketLength - 8)); +#endif +} + +VOID nicEventDumpMem(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_CMD_INFO_T prCmdInfo; + + DBGLOG(SW4, INFO, "%s: EVENT_ID_DUMP_MEM\n", __func__); + + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + DBGLOG(NIC, INFO, ": ==> 1\n"); + 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); + } else { + /* Burst mode */ + DBGLOG(NIC, INFO, ": ==> 2\n"); + nicEventQueryMemDump(prAdapter, prEvent->aucBuffer); + } +} + +VOID nicEventAssertDump(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + + if (wlanIsChipRstRecEnabled(prAdapter)) + wlanChipRstPreAct(prAdapter); + + if (prEvent->ucS2DIndex == S2D_INDEX_EVENT_N2H) { + if (!prAdapter->fgN9AssertDumpOngoing) { + DBGLOG(NIC, ERROR, "%s: EVENT_ID_ASSERT_DUMP\n", __func__); + DBGLOG(NIC, ERROR, "\n[DUMP_N9]====N9 ASSERT_DUMPSTART====\n"); + prAdapter->fgKeepPrintCoreDump = TRUE; + if (kalOpenCorDumpFile(TRUE) != WLAN_STATUS_SUCCESS) + DBGLOG(NIC, ERROR, "kalOpenCorDumpFile fail\n"); + else + prAdapter->fgN9CorDumpFileOpend = TRUE; + + prAdapter->fgN9AssertDumpOngoing = TRUE; + } + if (prAdapter->fgN9AssertDumpOngoing) { + + if (prAdapter->fgKeepPrintCoreDump) + DBGLOG(NIC, ERROR, "[DUMP_N9]%s:\n", prEvent->aucBuffer); + if (!kalStrnCmp(prEvent->aucBuffer, ";more log added here", 5) + || !kalStrnCmp(prEvent->aucBuffer, ";[core dump start]", 5)) + prAdapter->fgKeepPrintCoreDump = FALSE; + + if (prAdapter->fgN9CorDumpFileOpend) { + if (kalWriteCorDumpFile(prEvent->aucBuffer, + prEvent->u2PacketLength - EVENT_HDR_WITHOUT_RXD_SIZE, TRUE) != + WLAN_STATUS_SUCCESS) { + DBGLOG(NIC, INFO, "kalWriteN9CorDumpFile fail\n"); + } + } + wlanCorDumpTimerReset(prAdapter, TRUE); + } + } else { + /* prEvent->ucS2DIndex == S2D_INDEX_EVENT_C2H */ + if (!prAdapter->fgCr4AssertDumpOngoing) { + DBGLOG(NIC, ERROR, "%s: EVENT_ID_ASSERT_DUMP\n", __func__); + DBGLOG(NIC, ERROR, "\n[DUMP_Cr4]====CR4 ASSERT_DUMPSTART====\n"); + prAdapter->fgKeepPrintCoreDump = TRUE; + if (kalOpenCorDumpFile(FALSE) != WLAN_STATUS_SUCCESS) + DBGLOG(NIC, ERROR, "kalOpenCorDumpFile fail\n"); + else + prAdapter->fgCr4CorDumpFileOpend = TRUE; + + prAdapter->fgCr4AssertDumpOngoing = TRUE; + } + if (prAdapter->fgCr4AssertDumpOngoing) { + if (prAdapter->fgKeepPrintCoreDump) + DBGLOG(NIC, ERROR, "[DUMP_CR4]%s:\n", prEvent->aucBuffer); + if (!kalStrnCmp(prEvent->aucBuffer, ";more log added here", 5)) + prAdapter->fgKeepPrintCoreDump = FALSE; + + if (prAdapter->fgCr4CorDumpFileOpend) { + if (kalWriteCorDumpFile(prEvent->aucBuffer, + prEvent->u2PacketLength - EVENT_HDR_WITHOUT_RXD_SIZE, FALSE) != + WLAN_STATUS_SUCCESS) { + DBGLOG(NIC, ERROR, "kalWriteN9CorDumpFile fail\n"); + } + } + wlanCorDumpTimerReset(prAdapter, FALSE); + } + } +} + +VOID nicEventRddSendPulse(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + DBGLOG(RLM, INFO, "%s: EVENT_ID_RDD_SEND_PULSE\n", __func__); + + nicEventRddPulseDump(prAdapter, prEvent->aucBuffer); +} + +VOID nicEventUpdateCoexPhyrate(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + UINT_8 i; + P_EVENT_UPDATE_COEX_PHYRATE_T prEventUpdateCoexPhyrate; + + DBGLOG(NIC, LOUD, "%s\n", __func__); + + prEventUpdateCoexPhyrate = (P_EVENT_UPDATE_COEX_PHYRATE_T)(prEvent->aucBuffer); + + for (i = 0; i < (HW_BSSID_NUM+1); i++) { + prAdapter->aprBssInfo[i]->u4CoexPhyRateLimit = prEventUpdateCoexPhyrate->au4PhyRateLimit[i]; + DBGLOG(NIC, INFO, "Coex:BSS[%d]R:%d\n", i, prAdapter->aprBssInfo[i]->u4CoexPhyRateLimit); + } +} + +#if (CFG_WOW_SUPPORT == 1) +VOID nicEventWakeUpReason(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + struct _EVENT_WAKEUP_REASON_INFO *prWakeUpReason; + P_GLUE_INFO_T prGlueInfo; + + DBGLOG(NIC, INFO, "nicEventWakeUpReason\n"); + prGlueInfo = prAdapter->prGlueInfo; + + /* Driver receives EVENT_ID_WOW_WAKEUP_REASON after firmware wake up host + * The possible Wakeup Reason define in FW as following + * 0: MAGIC PACKET + * 1: BITMAP + * 2: ARPNS + * 3: GTK_REKEY + * 4: COALESCING_FILTER + * 5: HW_GLOBAL_ENABLE + * 6: TCP_SYN PACKET + * 7: TDLS + * 8: DISCONNECT + * 9: IPV4_UDP PACKET + * 10: IPV4_TCP PACKET + * 11: IPV6_UDP PACKET + * 12: IPV6_TCP PACKET + */ + prWakeUpReason = (struct _EVENT_WAKEUP_REASON_INFO *) (prEvent->aucBuffer); + prGlueInfo->prAdapter->rWowCtrl.ucReason = prWakeUpReason->reason; + DBGLOG(NIC, INFO, "nicEventWakeUpReason:%d\n", prGlueInfo->prAdapter->rWowCtrl.ucReason); +} +#endif + +#if CFG_SUPPORT_CSI +VOID nicEventCSIData(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + struct TLV_ELEMENT *prCSITlvData; + INT_32 i4EventLen = + prEvent->u2PacketLength - EVENT_HDR_WITHOUT_RXD_SIZE; + INT_16 i2Idx = 0; + PINT_8 prBuf = NULL; + UINT_32 u4IsCck = 0; + PUINT_16 pru2Tmp = NULL; + struct CSI_DATA_T *prCSIData = NULL; + struct CSI_INFO_T *prCSIInfo = &(prAdapter->rCSIInfo); + /* u2Offset is 8 bytes currently, tag 4 bytes + length 4 bytes */ + UINT_16 u2Offset = OFFSET_OF(struct TLV_ELEMENT, aucbody); + +#define CSI_EVENT_MAX_SIZE 1500 + + DBGLOG(NIC, INFO, "nicEventCSIData\n"); + + if (i4EventLen > CSI_EVENT_MAX_SIZE) { + DBGLOG(NIC, WARN, "Invalid CSI event size %u\n", + i4EventLen); + return; + } + prCSIData = kalMemAlloc(sizeof(struct CSI_DATA_T), VIR_MEM_TYPE); + + if (!prCSIData) { + DBGLOG(NIC, WARN, "Alloc prCSIData failed!"); + return; + } + + prCSIData->u8TimeStamp = kalDivU64(kalGetBootTime(), USEC_PER_MSEC); + + prBuf = (PINT_8) (prEvent->aucBuffer); + + while (i4EventLen >= u2Offset) { + prCSITlvData = (struct TLV_ELEMENT *) prBuf; + + switch (prCSITlvData->tag_type) { + case CSI_EVENT_IS_CCK: + if (prCSITlvData->body_len != sizeof(UINT_32)) { + DBGLOG(NIC, WARN, + "Invalid IS_CCK len %u", + prCSITlvData->body_len); + goto out; + } + + u4IsCck = + le32_to_cpup((PUINT_32) prCSITlvData->aucbody); + prCSIData->bIsCck = (u4IsCck) ? TRUE : FALSE; + break; + case CSI_EVENT_CBW: + if (prCSITlvData->body_len != sizeof(UINT_32)) { + DBGLOG(NIC, WARN, + "Invalid CBW len %u", + prCSITlvData->body_len); + goto out; + } + + prCSIData->ucBw = + le32_to_cpup((PUINT_32) prCSITlvData->aucbody); + break; + case CSI_EVENT_RSSI: + if (prCSITlvData->body_len != sizeof(UINT_32)) { + DBGLOG(NIC, WARN, + "Invalid RSSI len %u", + prCSITlvData->body_len); + goto out; + } + + prCSIData->cRssi = + le32_to_cpup((PUINT_32) prCSITlvData->aucbody); + break; + case CSI_EVENT_SNR: + if (prCSITlvData->body_len != sizeof(UINT_32)) { + DBGLOG(NIC, WARN, + "Invalid SNR len %u", + prCSITlvData->body_len); + goto out; + } + + prCSIData->ucSNR = + le32_to_cpup((PUINT_32) prCSITlvData->aucbody); + break; + case CSI_EVENT_BAND: + if (prCSITlvData->body_len != sizeof(UINT_32)) { + DBGLOG(NIC, WARN, + "Invalid BAND len %u", + prCSITlvData->body_len); + goto out; + } + + prCSIData->ucDbdcIdx = + le32_to_cpup((PUINT_32) prCSITlvData->aucbody); + break; + case CSI_EVENT_CSI_NUM: + if (prCSITlvData->body_len != sizeof(UINT_32)) { + DBGLOG(NIC, WARN, + "Invalid CSI num len %u", + prCSITlvData->body_len); + goto out; + } + + prCSIData->u2DataCount = + le32_to_cpup((PUINT_32) prCSITlvData->aucbody); + break; + case CSI_EVENT_CSI_I_DATA: + if (prCSIData->u2DataCount > CSI_MAX_DATA_COUNT) { + DBGLOG(NIC, WARN, + "Invalid CSI count %u\n", + prCSIData->u2DataCount); + goto out; + } + + if (prCSITlvData->body_len != + sizeof(INT_16) * CSI_MAX_DATA_COUNT) { + DBGLOG(NIC, WARN, + "Invalid CSI num len %u", + prCSITlvData->body_len); + goto out; + } + + kalMemZero(prCSIData->ac2IData, + sizeof(prCSIData->ac2IData)); + + pru2Tmp = (PINT_16) prCSITlvData->aucbody; + for (i2Idx = 0; i2Idx < prCSIData->u2DataCount; i2Idx++) + prCSIData->ac2IData[i2Idx] = + le16_to_cpup(pru2Tmp + i2Idx); + break; + case CSI_EVENT_CSI_Q_DATA: + if (prCSIData->u2DataCount > CSI_MAX_DATA_COUNT) { + DBGLOG(NIC, WARN, + "Invalid CSI count %u\n", + prCSIData->u2DataCount); + goto out; + } + + if (prCSITlvData->body_len != + sizeof(INT_16) * CSI_MAX_DATA_COUNT) { + DBGLOG(NIC, WARN, + "Invalid CSI num len %u", + prCSITlvData->body_len); + goto out; + } + + kalMemZero(prCSIData->ac2QData, + sizeof(prCSIData->ac2QData)); + + pru2Tmp = (PINT_16) prCSITlvData->aucbody; + for (i2Idx = 0; i2Idx < prCSIData->u2DataCount; i2Idx++) + prCSIData->ac2QData[i2Idx] = + le16_to_cpup(pru2Tmp + i2Idx); + break; + case CSI_EVENT_DBW: + if (prCSITlvData->body_len != sizeof(UINT_32)) { + DBGLOG(NIC, WARN, + "Invalid DBW len %u", + prCSITlvData->body_len); + goto out; + } + + prCSIData->ucDataBw = + le32_to_cpup((PINT_32) prCSITlvData->aucbody); + break; + case CSI_EVENT_CH_IDX: + if (prCSITlvData->body_len != sizeof(UINT_32)) { + DBGLOG(NIC, WARN, + "Invalid CH IDX len %u", + prCSITlvData->body_len); + goto out; + } + + prCSIData->ucPrimaryChIdx = + le32_to_cpup((PINT_32) prCSITlvData->aucbody); + break; + case CSI_EVENT_TA: + /* + * TA length is 8-byte long (MAC addr 6 bytes + + * 2 bytes padding), the 2-byte padding keeps + * the next Tag at a 4-byte aligned address. + */ + if (prCSITlvData->body_len != + ALIGN_4(sizeof(prCSIData->aucTA))) { + DBGLOG(NIC, WARN, + "Invalid TA len %u", + prCSITlvData->body_len); + goto out; + } + kalMemCopy(prCSIData->aucTA, prCSITlvData->aucbody, + sizeof(prCSIData->aucTA)); + break; + case CSI_EVENT_EXTRA_INFO: + if (prCSITlvData->body_len != sizeof(UINT_32)) { + DBGLOG(NIC, WARN, + "Invalid Error len %u", + prCSITlvData->body_len); + goto out; + } + prCSIData->u4ExtraInfo = + le32_to_cpup((PINT_32) prCSITlvData->aucbody); + break; + case CSI_EVENT_RX_MODE: + if (prCSITlvData->body_len != sizeof(UINT_32)) { + DBGLOG(NIC, WARN, + "Invalid Rx Mode len %u", + prCSITlvData->body_len); + goto out; + } + + prCSIData->ucRxMode = + le32_to_cpup((PINT_32) prCSITlvData->aucbody); + break; + case CSI_EVENT_RSVD1: + if (prCSITlvData->body_len > + sizeof(INT_32) * CSI_MAX_RSVD1_COUNT) { + DBGLOG(NIC, WARN, + "Invalid RSVD1 len %u", + prCSITlvData->body_len); + goto out; + } + + kalMemCopy(prCSIData->ai4Rsvd1, + prCSITlvData->aucbody, + prCSITlvData->body_len); + + prCSIData->ucRsvd1Cnt = + prCSITlvData->body_len / sizeof(INT_32); + break; + case CSI_EVENT_RSVD2: + if (prCSITlvData->body_len > + sizeof(INT_32) * CSI_MAX_RSVD1_COUNT) { + DBGLOG(NIC, WARN, + "Invalid RSVD2 len %u", + prCSITlvData->body_len); + goto out; + } + + kalMemCopy(prCSIData->au4Rsvd2, + prCSITlvData->aucbody, + prCSITlvData->body_len); + + prCSIData->ucRsvd1Cnt = + prCSITlvData->body_len / sizeof(INT_32); + break; + case CSI_EVENT_RSVD3: + if (prCSITlvData->body_len != sizeof(UINT_32)) { + DBGLOG(NIC, WARN, + "Invalid RSVD3 len %u", + prCSITlvData->body_len); + goto out; + } + + prCSIData->i4Rsvd3 = + le32_to_cpup((PINT_32) prCSITlvData->aucbody); + break; + case CSI_EVENT_RSVD4: + if (prCSITlvData->body_len != sizeof(UINT_32)) { + DBGLOG(NIC, WARN, + "Invalid RSVD4 len %u", + prCSITlvData->body_len); + goto out; + } + + prCSIData->ucRsvd4 = + le32_to_cpup((PUINT_32) prCSITlvData->aucbody); + break; + default: + DBGLOG(NIC, INFO, "Unsupported CSI tag %d\n", + prCSITlvData->tag_type); + }; + + i4EventLen -= (u2Offset + prCSITlvData->body_len); + + if (i4EventLen >= u2Offset) + prBuf += (u2Offset + prCSITlvData->body_len); + } + + if ((prCSIInfo->ucValue1[CSI_CONFIG_OUTPUT_FORMAT] == + CSI_OUTPUT_TONE_MASKED || + prCSIInfo->ucValue1[CSI_CONFIG_OUTPUT_FORMAT] == + CSI_OUTPUT_TONE_MASKED_SHIFTED) && + !prCSIData->bIsCck) { + wlanApplyCSIToneMask(prCSIData->ucRxMode, + prCSIData->ucBw, prCSIData->ucDataBw, + prCSIData->ucPrimaryChIdx, + prCSIData->ac2IData, prCSIData->ac2QData); + } + if (prCSIInfo->ucValue1[CSI_CONFIG_OUTPUT_FORMAT] == + CSI_OUTPUT_TONE_MASKED_SHIFTED && + !prCSIData->bIsCck) { + kalMemCopy(prCSIInfo->ai2TempIData, + prCSIData->ac2IData, + sizeof(INT_16) * prCSIData->u2DataCount); + kalMemCopy(prCSIInfo->ai2TempQData, + prCSIData->ac2QData, + sizeof(INT_16) * prCSIData->u2DataCount); + wlanShiftCSI(prCSIData->ucRxMode, + prCSIData->ucBw, prCSIData->ucDataBw, + prCSIData->ucPrimaryChIdx, + prCSIInfo->ai2TempIData, + prCSIInfo->ai2TempQData, + prCSIData->ac2IData, + prCSIData->ac2QData); + + if (prCSIData->ucDataBw == RX_VT_FR_MODE_20) + prCSIData->u2DataCount = 64; + else if (prCSIData->ucDataBw == RX_VT_FR_MODE_40) + prCSIData->u2DataCount = 128; + else + prCSIData->u2DataCount = 256; + } + + wlanPushCSIData(prAdapter, prCSIData); + wake_up_interruptible(&(prAdapter->rCSIInfo.waitq)); + +out: + kalMemFree(prCSIData, VIR_MEM_TYPE, sizeof(struct CSI_DATA_T)); +} +#endif + +#if CFG_SUPPORT_REPLAY_DETECTION +VOID nicCmdEventSetAddKey(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_WIFI_CMD_T prWifiCmd = NULL; + P_CMD_802_11_KEY prCmdKey = NULL; + struct SEC_DETECT_REPLAY_INFO *prDetRplyInfo = NULL; + UINT_8 ucBssIndex = 0; + P_BSS_INFO_T prBssInfo = NULL; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4InformationBufferLength, WLAN_STATUS_SUCCESS); + } + + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prCmdKey = (P_CMD_802_11_KEY) (prWifiCmd->aucBuffer); + ucBssIndex = prCmdKey->ucBssIdx; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + ASSERT(prBssInfo); + + prDetRplyInfo = &prBssInfo->rDetRplyInfo; + + if (pucEventBuf) { + prWifiCmd = (P_WIFI_CMD_T) (pucEventBuf); + prCmdKey = (P_CMD_802_11_KEY) (prWifiCmd->aucBuffer); + if (!prCmdKey->ucKeyType) { + prDetRplyInfo->ucCurKeyId = prCmdKey->ucKeyId; + prDetRplyInfo->ucKeyType = prCmdKey->ucKeyType; + prDetRplyInfo->arReplayPNInfo[prCmdKey->ucKeyId].fgRekey = TRUE; + prDetRplyInfo->arReplayPNInfo[prCmdKey->ucKeyId].fgFirstPkt = TRUE; + DBGLOG(NIC, TRACE, "Keyid is %d, ucKeyType is %d\n", + prCmdKey->ucKeyId, prCmdKey->ucKeyType); + } + } +} + +VOID nicOidCmdTimeoutSetAddKey(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + ASSERT(prAdapter); + + DBGLOG(NIC, WARN, "Wlan setaddkey timeout.\n"); + if (prCmdInfo->fgIsOid) + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_FAILURE); +} + + +VOID nicEventGetGtkDataSync(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_PARAM_GTK_REKEY_DATA prGtkData = NULL; + struct SEC_DETECT_REPLAY_INFO *prDetRplyInfo = NULL; + P_BSS_INFO_T prBssInfo = NULL; + UINT_8 ucCurKeyId; + + prGtkData = (P_PARAM_GTK_REKEY_DATA) (prEvent->aucBuffer); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex); + + prDetRplyInfo = &prBssInfo->rDetRplyInfo; + prDetRplyInfo->ucCurKeyId = prGtkData->ucCurKeyId; + ucCurKeyId = prDetRplyInfo->ucCurKeyId; + + kalMemZero(prDetRplyInfo->arReplayPNInfo[ucCurKeyId].auPN, NL80211_REPLAY_CTR_LEN); + +#if 0 + /* if Drv alread rx a new PN value large than fw PN, then skip PN update */ + if (qmRxDetectReplay(prGtkData->aucReplayCtr, + prDetRplyInfo->arReplayPNInfo[ucCurKeyId].auPN)) + return; +#endif + + kalMemCopy(prDetRplyInfo->arReplayPNInfo[ucCurKeyId].auPN, + prGtkData->aucReplayCtr, 6); + + DBGLOG(RSN, INFO, "Get BC/MC PN update from fw.\n"); + + DBGLOG_MEM8(RSN, INFO, (PUINT_8)prDetRplyInfo->arReplayPNInfo[ucCurKeyId].auPN, NL80211_REPLAY_CTR_LEN); +} + +#endif + +VOID nicCmdEventGetTxPwrTbl(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_GLUE_INFO_T prGlueInfo; + struct EVENT_GET_TXPWR_TBL *prTxPwrTblEvent = NULL; + struct PARAM_CMD_GET_TXPWR_TBL *prTxPwrTbl = NULL; + void *info_buf = NULL; + + if (!prAdapter) { + DBGLOG(NIC, ERROR, "NULL prAdapter!\n"); + return; + } + + if (!prCmdInfo) { + DBGLOG(NIC, ERROR, "NULL prCmdInfo!\n"); + return; + } + + if (!pucEventBuf || !prCmdInfo->pvInformationBuffer) { + if (prCmdInfo->fgIsOid) { + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + 0, + WLAN_STATUS_FAILURE); + } + + if (!pucEventBuf) + DBGLOG(NIC, WARN, "NULL pucEventBuf!\n"); + + if (!prCmdInfo->pvInformationBuffer) + DBGLOG(NIC, WARN, "NULL pvInformationBuffer!\n"); + + return; + } + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + info_buf = prCmdInfo->pvInformationBuffer; + prTxPwrTblEvent = (struct EVENT_GET_TXPWR_TBL *) pucEventBuf; + prTxPwrTbl = (struct PARAM_CMD_GET_TXPWR_TBL *) info_buf; + + u4QueryInfoLen = sizeof(struct PARAM_CMD_GET_TXPWR_TBL); + + prTxPwrTbl->ucCenterCh = prTxPwrTblEvent->ucCenterCh; + + kalMemCopy(prTxPwrTbl->tx_pwr_tbl, + prTxPwrTblEvent->tx_pwr_tbl, + sizeof(prTxPwrTblEvent->tx_pwr_tbl)); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, + u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic_pwr_mgt.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic_pwr_mgt.c new file mode 100644 index 0000000000000..f1f663deee0a2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic_pwr_mgt.c @@ -0,0 +1,391 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +/******************************************************************************* +* C O M P I L E 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 +******************************************************************************** +*/ + +VOID nicpmWakeUpWiFi(IN P_ADAPTER_T prAdapter) +{ + if (!nicVerifyChipID(prAdapter)) { + DBGLOG(INIT, ERROR, "Chip id verify error!\n"); + return; + } + HAL_WAKE_UP_WIFI(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ + halSetFWOwn(prAdapter, fgEnableGlobalInt); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ + return halSetDriverOwn(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ + +#if 0 + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + UINT_32 u4Value = 0, u4WHISR = 0; + UINT_16 au2TxCount[16]; + UINT_32 i; +#if CFG_ENABLE_FW_DOWNLOAD + UINT_32 u4FwImgLength, u4FwLoadAddr, u4Cr4FwImgLength; + PVOID prFwMappingHandle; + PVOID pvFwImageMapFile = NULL; + PVOID pvCr4FwImageMapFile = NULL; +#if CFG_ENABLE_FW_DIVIDED_DOWNLOAD + P_FIRMWARE_DIVIDED_DOWNLOAD_T prFwHead; + BOOLEAN fgValidHead = TRUE; + /* 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(MT6630) + /* 1. Request Ownership to enter F/W download state */ + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); +#if !CFG_ENABLE_FULL_PM + nicpmSetDriverOwn(prAdapter); +#endif + + /* 2. Initialize the Adapter */ + u4Status = nicInitializeAdapter(prAdapter); + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "nicInitializeAdapter failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } +#endif + +#if CFG_ENABLE_FW_DOWNLOAD + prFwMappingHandle = + kalFirmwareImageMapping(prAdapter->prGlueInfo, &pvFwImageMapFile, &u4FwImgLength, + &pvCr4FwImageMapFile, &u4Cr4FwImgLength); + if (!prFwMappingHandle) { + DBGLOG(INIT, ERROR, "Fail to load FW image from file!\n"); + pvFwImageMapFile = NULL; + } +#if defined(MT6630) + 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) ((PUINT_8) pvFwImageMapFile + u4FwImgLength - + (2 * sizeof(FWDL_SECTION_INFO_T))); +#if 0 + if (prFwHead->u4Signature == MTK_WIFI_SIGNATURE && + prFwHead->u4CRC == wlanCRC32((PUINT_8) pvFwImageMapFile + u4CRCOffset, + u4FwImgLength - u4CRCOffset)) { + fgValidHead = TRUE; + } else { + fgValidHead = FALSE; + } +#endif + /* 3b. engage divided firmware downloading */ + if (fgValidHead == TRUE) { + wlanFwDvdDwnloadHandler(prAdapter, prFwHead, pvFwImageMapFile, &u4Status); + } else +#endif + { + if (wlanImageSectionConfig(prAdapter, + u4FwLoadAddr, u4FwImgLength, TRUE) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "Firmware download configuration failed!\n"); + + u4Status = WLAN_STATUS_FAILURE; + break; + } + wlanFwDwnloadHandler(prAdapter, u4FwImgLength, pvFwImageMapFile, &u4Status); + } + /* escape to top */ + if (u4Status != WLAN_STATUS_SUCCESS) { + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, prFwMappingHandle, pvFwImageMapFile, + pvCr4FwImageMapFile); + 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, + pvCr4FwImageMapFile); + u4Status = WLAN_STATUS_FAILURE; + break; + } +#endif + + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, prFwMappingHandle, pvFwImageMapFile, + pvCr4FwImageMapFile); + } 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 +#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; + } + i++; + kalMsleep(10); + } + + if (u4Status == WLAN_STATUS_SUCCESS) { + /* 6.1 reset interrupt status */ + HAL_READ_INTR_STATUS(prAdapter, 4, (PUINT_8)&u4WHISR); + if (HAL_IS_TX_DONE_INTR(u4WHISR)) + HAL_READ_TX_RELEASED_COUNT(prAdapter, au2TxCount); + + /* 6.2 reset TX Resource for normal operation */ + nicTxResetResource(prAdapter); + + /* 6.3 Enable interrupt */ + nicEnableInterrupt(prAdapter); + + /* 6.4 Update basic configuration */ + wlanUpdateBasicConfig(prAdapter); + + /* 6.5 Apply Network Address */ + nicApplyNetworkAddress(prAdapter); + + /* 6.6 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; +#else + return TRUE; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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); + +#if 0 + /* 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, TRUE); + + /* 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; +#endif + return TRUE; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic_rate.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic_rate.c new file mode 100644 index 0000000000000..938a3edafcf86 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic_rate.c @@ -0,0 +1,445 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** +*/ + +/*! \file "nic_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. +*/ + + +/******************************************************************************* +* C O M P I L E 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_16 au2RateCCKLong[CCK_RATE_NUM] = { + 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 */ +}; + +const UINT_16 au2RateCCKShort[CCK_RATE_NUM] = { + 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 */ +}; + +const UINT_16 au2RateOFDM[OFDM_RATE_NUM] = { + 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 */ +}; + +const UINT_16 au2RateHTMixed[HT_RATE_NUM] = { + RATE_MM_MCS_32, /* RATE_MCS32_INDEX, */ + 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, */ +}; + +const UINT_16 au2RateHTGreenField[HT_RATE_NUM] = { + RATE_GF_MCS_32, /* RATE_MCS32_INDEX, */ + 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, */ +}; + +const UINT_16 au2RateVHT[VHT_RATE_NUM] = { + RATE_VHT_MCS_0, /* RATE_MCS0_INDEX, */ + RATE_VHT_MCS_1, /* RATE_MCS1_INDEX, */ + RATE_VHT_MCS_2, /* RATE_MCS2_INDEX, */ + RATE_VHT_MCS_3, /* RATE_MCS3_INDEX, */ + RATE_VHT_MCS_4, /* RATE_MCS4_INDEX, */ + RATE_VHT_MCS_5, /* RATE_MCS5_INDEX, */ + RATE_VHT_MCS_6, /* RATE_MCS6_INDEX, */ + RATE_VHT_MCS_7, /* RATE_MCS7_INDEX, */ + RATE_VHT_MCS_8, /* RATE_MCS8_INDEX, */ + RATE_VHT_MCS_9 /* RATE_MCS9_INDEX, */ +}; + +/* in unit of 100kb/s */ +const EMU_MAC_RATE_INFO_T arMcsRate2PhyRate[] = { + /* Phy Rate Code, BW20, BW20 SGI, BW40, BW40 SGI, BW80, BW80 SGI, BW160, BW160 SGI */ + RATE_INFO(PHY_RATE_MCS0, 65, 72, 135, 150, 293, 325, 585, 650), + RATE_INFO(PHY_RATE_MCS1, 130, 144, 270, 300, 585, 650, 1170, 1300), + RATE_INFO(PHY_RATE_MCS2, 195, 217, 405, 450, 878, 975, 1755, 1950), + RATE_INFO(PHY_RATE_MCS3, 260, 289, 540, 600, 1170, 1300, 2340, 2600), + RATE_INFO(PHY_RATE_MCS4, 390, 433, 810, 900, 1755, 1950, 3510, 3900), + RATE_INFO(PHY_RATE_MCS5, 520, 578, 1080, 1200, 2340, 2600, 4680, 5200), + RATE_INFO(PHY_RATE_MCS6, 585, 650, 1215, 1350, 2633, 2925, 5265, 5850), + RATE_INFO(PHY_RATE_MCS7, 650, 722, 1350, 1500, 2925, 3250, 5850, 6500), + RATE_INFO(PHY_RATE_MCS8, 780, 867, 1620, 1800, 3510, 3900, 7020, 7800), + RATE_INFO(PHY_RATE_MCS9, 0, 0, 1800, 2000, 3900, 4333, 7800, 8667), + RATE_INFO(PHY_RATE_MCS32, 0, 0, 60, 67, 0, 0, 0, 0) +}; + +/* in uint of 500kb/s */ +const UINT_8 aucHwRate2PhyRate[] = { + RATE_1M, /*1M long */ + RATE_2M, /*2M long */ + RATE_5_5M, /*5.5M long */ + RATE_11M, /*11M long */ + RATE_1M, /*1M short invalid */ + RATE_2M, /*2M short */ + RATE_5_5M, /*5.5M short */ + RATE_11M, /*11M short */ + RATE_48M, /*48M */ + RATE_24M, /*24M */ + RATE_12M, /*12M */ + RATE_6M, /*6M */ + RATE_54M, /*54M */ + RATE_36M, /*36M */ + RATE_18M, /*18M */ + RATE_9M /*9M */ +}; +/******************************************************************************* +* 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 +******************************************************************************** +*/ +UINT_32 +nicGetPhyRateByMcsRate( + IN UINT_8 ucIdx, + IN UINT_8 ucBw, + IN UINT_8 ucGI) +{ + return arMcsRate2PhyRate[ucIdx].u4PhyRate[ucBw][ucGI]; +} + +UINT_32 +nicGetHwRateByPhyRate( + IN UINT_8 ucIdx) +{ + return aucHwRate2PhyRate[ucIdx]; /* uint : 500 kbps */ +} + +WLAN_STATUS +nicSwIndex2RateIndex( + IN UINT_8 ucRateSwIndex, + OUT PUINT_8 pucRateIndex, + OUT PUINT_8 pucPreambleOption + ) +{ + ASSERT(pucRateIndex); + ASSERT(pucPreambleOption); + + if (ucRateSwIndex >= RATE_6M_SW_INDEX) { + *pucRateIndex = ucRateSwIndex - RATE_6M_SW_INDEX; + *pucPreambleOption = PREAMBLE_OFDM_MODE; + } else { + *pucRateIndex = ucRateSwIndex; + *pucPreambleOption = PREAMBLE_DEFAULT_LONG_NONE; + } + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS nicRateIndex2RateCode(IN UINT_8 ucPreambleOption, IN UINT_8 ucRateIndex, OUT PUINT_16 pu2RateCode) +{ + switch (ucPreambleOption) { + case PREAMBLE_DEFAULT_LONG_NONE: + if (ucRateIndex >= CCK_RATE_NUM) + return WLAN_STATUS_INVALID_DATA; + *pu2RateCode = au2RateCCKLong[ucRateIndex]; + break; + + case PREAMBLE_OPTION_SHORT: + if (ucRateIndex >= CCK_RATE_NUM) + return WLAN_STATUS_INVALID_DATA; + *pu2RateCode = au2RateCCKShort[ucRateIndex]; + break; + + case PREAMBLE_OFDM_MODE: + if (ucRateIndex >= OFDM_RATE_NUM) + return WLAN_STATUS_INVALID_DATA; + *pu2RateCode = au2RateOFDM[ucRateIndex]; + break; + + case PREAMBLE_HT_MIXED_MODE: + if (ucRateIndex >= HT_RATE_NUM) + return WLAN_STATUS_INVALID_DATA; + *pu2RateCode = au2RateHTMixed[ucRateIndex]; + break; + + case PREAMBLE_HT_GREEN_FIELD: + if (ucRateIndex >= HT_RATE_NUM) + return WLAN_STATUS_INVALID_DATA; + *pu2RateCode = au2RateHTGreenField[ucRateIndex]; + break; + + case PREAMBLE_VHT_FIELD: + if (ucRateIndex >= VHT_RATE_NUM) + return WLAN_STATUS_INVALID_DATA; + *pu2RateCode = au2RateVHT[ucRateIndex]; + break; + + default: + return WLAN_STATUS_INVALID_DATA; + } + + return WLAN_STATUS_SUCCESS; +} + +UINT_32 +nicRateCode2PhyRate( + IN UINT_16 u2RateCode, + IN UINT_8 ucBandwidth, + IN UINT_8 ucGI, + IN UINT_8 ucRateNss) +{ + UINT_8 ucPhyRate; + UINT_16 u2TxMode; + UINT_32 u4PhyRateBy1SS, u4PhyRateIn100Kbps = 0; + + ucPhyRate = RATE_CODE_GET_PHY_RATE(u2RateCode); + u2TxMode = u2RateCode & RATE_TX_MODE_MASK; + ucRateNss = ucRateNss + AR_SS_1; /* change to be base=1 */ + + if ((u2TxMode == TX_MODE_HT_GF) || (u2TxMode == TX_MODE_HT_MM)) { + + if (ucPhyRate > PHY_RATE_MCS7) + u2RateCode = u2RateCode - HT_RATE_MCS7_INDEX; + else + ucRateNss = AR_SS_1; + + } else if ((u2TxMode == TX_MODE_OFDM) || (u2TxMode == TX_MODE_CCK)) { + ucRateNss = AR_SS_1; + } + DBGLOG(NIC, LOUD, "Coex:nicRateCode2PhyRate,RC:%x,B:%d,I:%d\n", + u2RateCode, ucBandwidth, ucGI); + + u4PhyRateBy1SS = nicRateCode2DataRate(u2RateCode, ucBandwidth, ucGI); + u4PhyRateIn100Kbps = u4PhyRateBy1SS * ucRateNss; + + DBGLOG(NIC, LOUD, "Coex:nicRateCode2PhyRate,1ss R:%d,PHY R:%d\n", + u4PhyRateBy1SS, u4PhyRateIn100Kbps); + + return u4PhyRateIn100Kbps; +} + +UINT_32 +nicRateCode2DataRate( + IN UINT_16 u2RateCode, + IN UINT_8 ucBandwidth, + IN UINT_8 ucGI) +{ + UINT_8 ucPhyRate, ucIdx, ucBw = 0; + UINT_32 u4PhyRateIn100Kbps = 0; + UINT_16 u2TxMode; + + if ((ucBandwidth == FIX_BW_NO_FIXED) || (ucBandwidth == FIX_BW_20)) + ucBw = MAC_BW_20; + else if (ucBandwidth == FIX_BW_40) + ucBw = MAC_BW_40; + else if (ucBandwidth == FIX_BW_80) + ucBw = MAC_BW_80; + else if (ucBandwidth == FIX_BW_160) + ucBw = MAC_BW_160; + + ucPhyRate = RATE_CODE_GET_PHY_RATE(u2RateCode); + u2TxMode = u2RateCode & RATE_TX_MODE_MASK; + /* Set MMSS parameter if HT/VHT rate */ + if ((u2TxMode == TX_MODE_HT_GF) || + (u2TxMode == TX_MODE_HT_MM) || + (u2TxMode == TX_MODE_VHT)) { + /* No SGI Greenfield for 1T */ + /* Refer to section 20.3.11.11.6 of IEEE802.11-2012 */ + if (u2TxMode == TX_MODE_HT_GF) + ucGI = MAC_GI_NORMAL; + + ucIdx = ucPhyRate; + + if (ucIdx == PHY_RATE_MCS32) + ucIdx = 10; + + u4PhyRateIn100Kbps = nicGetPhyRateByMcsRate(ucIdx, ucBw, ucGI); + } else if ((u2TxMode == TX_MODE_OFDM) || + (u2TxMode == TX_MODE_CCK)) { + u4PhyRateIn100Kbps = (nicGetHwRateByPhyRate(ucPhyRate & BITS(0, 3)))*5; + } else { + ASSERT(FALSE); + } + return u4PhyRateIn100Kbps; +} + +BOOLEAN +nicGetRateIndexFromRateSetWithLimit( + IN UINT_16 u2RateSet, + IN UINT_32 u4PhyRateLimit, + IN BOOLEAN fgGetLowest, + OUT PUINT_8 pucRateSwIndex) +{ + UINT_32 i; + UINT_32 u4CurPhyRate, u4TarPhyRate, u4HighestPhyRate, u4LowestPhyRate; + UINT_8 ucRateIndex, ucRatePreamble, ucTarRateSwIndex, ucHighestPhyRateSwIdx, ucLowestPhyRateSwIdx; + UINT_16 u2CurRateCode; + UINT_32 u4Status; + + /* Set init value */ + if (fgGetLowest) { + u4TarPhyRate = 0xFFFFFFFF; + u4HighestPhyRate = 0; + ucHighestPhyRateSwIdx = RATE_NUM_SW; + } else { + u4TarPhyRate = 0; + u4LowestPhyRate = 0xFFFFFFFF; + ucLowestPhyRateSwIdx = RATE_NUM_SW; + } + + ucTarRateSwIndex = RATE_NUM_SW; + + /* Find SW rate index by limitation */ + for (i = RATE_1M_SW_INDEX; i <= RATE_54M_SW_INDEX; i++) { + if (u2RateSet & BIT(i)) { + + /* Convert SW rate index to phy rate in 100kbps */ + nicSwIndex2RateIndex(i, &ucRateIndex, &ucRatePreamble); + u4Status = nicRateIndex2RateCode(ucRatePreamble, ucRateIndex, &u2CurRateCode); + + if (u4Status != WLAN_STATUS_SUCCESS) + continue; + + u4CurPhyRate = + nicRateCode2DataRate(u2CurRateCode, MAC_BW_20, MAC_GI_NORMAL); + + /* Compare */ + if (fgGetLowest) { + if (u4HighestPhyRate < u4CurPhyRate) { + u4HighestPhyRate = u4CurPhyRate; + ucHighestPhyRateSwIdx = i; + } + if ((u4CurPhyRate >= u4PhyRateLimit) && (u4CurPhyRate <= u4TarPhyRate)) { + u4TarPhyRate = u4CurPhyRate; + ucTarRateSwIndex = i; + } + } else { + if (u4LowestPhyRate > u4CurPhyRate) { + u4LowestPhyRate = u4CurPhyRate; + ucLowestPhyRateSwIdx = i; + } + if ((u4CurPhyRate <= u4PhyRateLimit) && (u4CurPhyRate >= u4TarPhyRate)) { + u4TarPhyRate = u4CurPhyRate; + ucTarRateSwIndex = i; + } + } + } + } + + /* Return target SW rate index */ + if (ucTarRateSwIndex < RATE_NUM_SW) { + *pucRateSwIndex = ucTarRateSwIndex; + } else { + if (fgGetLowest) + *pucRateSwIndex = ucHighestPhyRateSwIdx; + else + *pucRateSwIndex = ucLowestPhyRateSwIdx; + } + return TRUE; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic_rx.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic_rx.c new file mode 100644 index 0000000000000..0272037ffed38 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic_rx.c @@ -0,0 +1,3570 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_rx.c#5 +*/ + +/*! \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. +*/ + + +/******************************************************************************* +* C O M P I L E 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 "que_mgt.h" + +#ifndef LINUX +#include +#else +#include +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +#if CFG_MGMT_FRAME_HANDLING +static PROCESS_RX_MGT_FUNCTION apfnProcessRxMgtFrame[MAX_NUM_OF_FC_SUBTYPES] = { +#if CFG_SUPPORT_AAA + aaaFsmRunEventRxAssoc, /* subtype 0000: Association request */ +#else + NULL, /* subtype 0000: Association request */ +#endif /* CFG_SUPPORT_AAA */ + saaFsmRunEventRxAssoc, /* subtype 0001: Association response */ +#if CFG_SUPPORT_AAA + aaaFsmRunEventRxAssoc, /* subtype 0010: Reassociation request */ +#else + NULL, /* subtype 0010: Reassociation request */ +#endif /* CFG_SUPPORT_AAA */ + saaFsmRunEventRxAssoc, /* subtype 0011: Reassociation response */ +#if CFG_SUPPORT_ADHOC || CFG_ENABLE_WIFI_DIRECT + 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 + +static RX_EVENT_HANDLER_T arEventTable[] = { + {EVENT_ID_RX_ADDBA, qmHandleEventRxAddBa}, + {EVENT_ID_RX_DELBA, qmHandleEventRxDelBa}, + {EVENT_ID_CHECK_REORDER_BUBBLE, qmHandleEventCheckReorderBubble}, + {EVENT_ID_LINK_QUALITY, nicEventLinkQuality}, + {EVENT_ID_LAYER_0_EXT_MAGIC_NUM, nicEventLayer0ExtMagic}, + {EVENT_ID_MIC_ERR_INFO, nicEventMicErrorInfo}, + {EVENT_ID_SCAN_DONE, nicEventScanDone}, + {EVENT_ID_NLO_DONE, nicEventNloDone}, + {EVENT_ID_TX_DONE, nicTxProcessTxDoneEvent}, + {EVENT_ID_SLEEPY_INFO, nicEventSleepyNotify}, +#if CFG_ENABLE_BT_OVER_WIFI + {EVENT_ID_BT_OVER_WIFI, nicEventBtOverWifi}, +#endif + {EVENT_ID_STATISTICS, nicEventStatistics}, + {EVENT_ID_WLAN_INFO, nicEventWlanInfo}, + {EVENT_ID_MIB_INFO, nicEventMibInfo}, +#if CFG_SUPPORT_LAST_SEC_MCS_INFO + {EVENT_ID_TX_MCS_INFO, nicEventTxMcsInfo}, +#endif + {EVENT_ID_CH_PRIVILEGE, cnmChMngrHandleChEvent}, + {EVENT_ID_BSS_ABSENCE_PRESENCE, qmHandleEventBssAbsencePresence}, + {EVENT_ID_STA_CHANGE_PS_MODE, qmHandleEventStaChangePsMode}, + {EVENT_ID_STA_UPDATE_FREE_QUOTA, qmHandleEventStaUpdateFreeQuota}, + {EVENT_ID_BSS_BEACON_TIMEOUT, nicEventBeaconTimeout}, + {EVENT_ID_UPDATE_NOA_PARAMS, nicEventUpdateNoaParams}, + {EVENT_ID_STA_AGING_TIMEOUT, nicEventStaAgingTimeout}, + {EVENT_ID_AP_OBSS_STATUS, nicEventApObssStatus}, + {EVENT_ID_ROAMING_STATUS, nicEventRoamingStatus}, + {EVENT_ID_SEND_DEAUTH, nicEventSendDeauth}, + {EVENT_ID_UPDATE_RDD_STATUS, nicEventUpdateRddStatus}, + {EVENT_ID_UPDATE_BWCS_STATUS, nicEventUpdateBwcsStatus}, + {EVENT_ID_UPDATE_BCM_DEBUG, nicEventUpdateBcmDebug}, + {EVENT_ID_ADD_PKEY_DONE, nicEventAddPkeyDone}, + {EVENT_ID_ICAP_DONE, nicEventIcapDone}, + {EVENT_ID_DEBUG_MSG, nicEventDebugMsg}, + {EVENT_ID_TDLS, nicEventTdls}, + {EVENT_ID_DUMP_MEM, nicEventDumpMem}, +#if CFG_ASSERT_DUMP + {EVENT_ID_ASSERT_DUMP, nicEventAssertDump}, +#endif +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST + {EVENT_ID_CAL_ALL_DONE, nicEventCalAllDone}, +#endif + {EVENT_ID_HIF_CTRL, nicEventHifCtrl}, + {EVENT_ID_RDD_SEND_PULSE, nicEventRddSendPulse}, +#if (CFG_SUPPORT_DFS_MASTER == 1) + {EVENT_ID_UPDATE_COEX_PHYRATE, nicEventUpdateCoexPhyrate}, + {EVENT_ID_RDD_REPORT, cnmRadarDetectEvent}, + {EVENT_ID_CSA_DONE, cnmCsaDoneEvent}, +#else + {EVENT_ID_UPDATE_COEX_PHYRATE, nicEventUpdateCoexPhyrate}, +#endif +#if (CFG_WOW_SUPPORT == 1) + {EVENT_ID_WOW_WAKEUP_REASON, nicEventWakeUpReason}, +#endif +#if CFG_SUPPORT_CSI + {EVENT_ID_CSI_DATA, nicEventCSIData}, +#endif +#if CFG_SUPPORT_REPLAY_DETECTION + {EVENT_ID_GET_GTK_REKEY_DATA, nicEventGetGtkDataSync}, +#endif +}; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define MAX_EAPOL_REQUE 50 +/******************************************************************************* +* 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; + + if (nicRxSetupRFB(prAdapter, prSwRfb)) { + DBGLOG(RX, ERROR, "nicRxInitialize failed: Cannot allocate packet buffer for SwRfb!\n"); + return; + } + 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); + + prRxCtrl->pucRxCoalescingBufPtr = prAdapter->pucCoalescingBufCached; + +#if CFG_HIF_STATISTICS + prRxCtrl->u4TotalRxAccessNum = 0; + prRxCtrl->u4TotalRxPacketNum = 0; +#endif + +#if CFG_HIF_RX_STARVATION_WARNING + prRxCtrl->u4QueuedCnt = 0; + prRxCtrl->u4DequeuedCnt = 0; +#endif + +} /* end of nicRxInitialize() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Uninitialize the RFBs +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxUninitialize(IN P_ADAPTER_T prAdapter) +{ + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + nicRxFlush(prAdapter); + + do { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rReceivedRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + if (prSwRfb) { + if (prSwRfb->pvPacket) + kalPacketFree(prAdapter->prGlueInfo, prSwRfb->pvPacket); + prSwRfb->pvPacket = NULL; + } else { + break; + } + } while (TRUE); + + do { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + if (prSwRfb) { + if (prSwRfb->pvPacket) + kalPacketFree(prAdapter->prGlueInfo, prSwRfb->pvPacket); + prSwRfb->pvPacket = NULL; + } else { + break; + } + } while (TRUE); + +} /* end of nicRxUninitialize() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Fill RFB +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb specify the RFB to receive rx data +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxFillRFB(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) +{ + P_HW_MAC_RX_DESC_T prRxStatus; + + UINT_32 u4PktLen = 0; + /* UINT_32 u4MacHeaderLen; */ + UINT_32 u4HeaderOffset; + UINT_16 u2RxStatusOffset; + + DEBUGFUNC("nicRxFillRFB"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + u4PktLen = (UINT_32) HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus); + u4HeaderOffset = (UINT_32) (HAL_RX_STATUS_GET_HEADER_OFFSET(prRxStatus)); + /* u4MacHeaderLen = (UINT_32)(HAL_RX_STATUS_GET_HEADER_LEN(prRxStatus)); */ + + /* DBGLOG(RX, TRACE, ("u4HeaderOffset = %d, u4MacHeaderLen = %d\n", */ + /* u4HeaderOffset, u4MacHeaderLen)); */ + u2RxStatusOffset = sizeof(HW_MAC_RX_DESC_T); + prSwRfb->ucGroupVLD = (UINT_8) HAL_RX_STATUS_GET_GROUP_VLD(prRxStatus); + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_4)) { + prSwRfb->prRxStatusGroup4 = (P_HW_MAC_RX_STS_GROUP_4_T) ((P_UINT_8) prRxStatus + u2RxStatusOffset); + u2RxStatusOffset += sizeof(HW_MAC_RX_STS_GROUP_4_T); + /* Fill out the TID and SSN */ + prSwRfb->ucTid = (UINT_8) (HAL_RX_STATUS_GET_TID(prRxStatus)); + prSwRfb->u2SSN = HAL_RX_STATUS_GET_SEQFrag_NUM( + prSwRfb->prRxStatusGroup4) >> RX_STATUS_SEQ_NUM_OFFSET; + } + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_1)) { + prSwRfb->prRxStatusGroup1 = (P_HW_MAC_RX_STS_GROUP_1_T) ((P_UINT_8) prRxStatus + u2RxStatusOffset); + u2RxStatusOffset += sizeof(HW_MAC_RX_STS_GROUP_1_T); + + } + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_2)) { + prSwRfb->prRxStatusGroup2 = (P_HW_MAC_RX_STS_GROUP_2_T) ((P_UINT_8) prRxStatus + u2RxStatusOffset); + u2RxStatusOffset += sizeof(HW_MAC_RX_STS_GROUP_2_T); + + } + if (prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_3)) { + prSwRfb->prRxStatusGroup3 = (P_HW_MAC_RX_STS_GROUP_3_T) ((P_UINT_8) prRxStatus + u2RxStatusOffset); + u2RxStatusOffset += sizeof(HW_MAC_RX_STS_GROUP_3_T); + } + + prSwRfb->u2RxStatusOffst = u2RxStatusOffset; + prSwRfb->pvHeader = (PUINT_8) prRxStatus + u2RxStatusOffset + u4HeaderOffset; + prSwRfb->u2PacketLen = (UINT_16) (u4PktLen - (u2RxStatusOffset + u4HeaderOffset)); + prSwRfb->u2HeaderLen = (UINT_16) HAL_RX_STATUS_GET_HEADER_LEN(prRxStatus); + prSwRfb->ucWlanIdx = (UINT_8) HAL_RX_STATUS_GET_WLAN_IDX(prRxStatus); + prSwRfb->ucStaRecIdx = secGetStaIdxByWlanIdx(prAdapter, (UINT_8) HAL_RX_STATUS_GET_WLAN_IDX(prRxStatus)); + prSwRfb->prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + /* 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 rxDefragMPDU() is used to defragment the incoming packets. +* +* \param[in] prSWRfb The RFB which is being processed. +* \param[in] UINT_16 u2FrameCtrl +* +* \retval NOT NULL Receive the last fragment data +* \retval NULL Receive the fragment packet which is not the last +*/ +/*----------------------------------------------------------------------------*/ +P_SW_RFB_T incRxDefragMPDU(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSWRfb, OUT P_QUE_T prReturnedQue) +{ + + P_SW_RFB_T prOutputSwRfb = (P_SW_RFB_T) NULL; +#if 1 + P_RX_CTRL_T prRxCtrl; + P_FRAG_INFO_T prFragInfo; + UINT_32 i = 0, j; + UINT_16 u2SeqCtrl, u2FrameCtrl; + UINT_8 ucFragNum; + BOOLEAN fgFirst = FALSE; + BOOLEAN fgLast = FALSE; + OS_SYSTIME rCurrentTime; + P_WLAN_MAC_HEADER_T prWlanHeader = NULL; + P_HW_MAC_RX_DESC_T prRxStatus = NULL; + P_HW_MAC_RX_STS_GROUP_4_T prRxStatusGroup4 = NULL; + + DEBUGFUNC("nicRx: rxmDefragMPDU\n"); + + ASSERT(prSWRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + + prRxStatus = prSWRfb->prRxStatus; + ASSERT(prRxStatus); + + if (HAL_RX_STATUS_IS_HEADER_TRAN(prRxStatus) == FALSE) { + prWlanHeader = (P_WLAN_MAC_HEADER_T) prSWRfb->pvHeader; + prSWRfb->u2SequenceControl = prWlanHeader->u2SeqCtrl; + u2FrameCtrl = prWlanHeader->u2FrameCtrl; + } else { + prRxStatusGroup4 = prSWRfb->prRxStatusGroup4; + prSWRfb->u2SequenceControl = HAL_RX_STATUS_GET_SEQFrag_NUM(prRxStatusGroup4); + u2FrameCtrl = HAL_RX_STATUS_GET_FRAME_CTL_FIELD(prRxStatusGroup4); + } + u2SeqCtrl = prSWRfb->u2SequenceControl; + ucFragNum = (UINT_8) (u2SeqCtrl & MASK_SC_FRAG_NUM); + prSWRfb->u2FrameCtrl = u2FrameCtrl; + + if (!(u2FrameCtrl & MASK_FC_MORE_FRAG)) { + /* The last fragment frame */ + if (ucFragNum) { + DBGLOG(RX, LOUD, + "FC %04x M %04x SQ %04x\n", + u2FrameCtrl, + (UINT_16)(u2FrameCtrl & MASK_FC_MORE_FRAG), + u2SeqCtrl); + fgLast = TRUE; + } + /* Non-fragment frame */ + else + return prSWRfb; + } + /* The fragment frame except the last one */ + else { + if (ucFragNum == 0) { + DBGLOG(RX, LOUD, + "FC %04x M %04x SQ %04x\n", + u2FrameCtrl, + (UINT_16)(u2FrameCtrl & MASK_FC_MORE_FRAG), + u2SeqCtrl); + fgFirst = TRUE; + } else { + DBGLOG(RX, LOUD, + "FC %04x M %04x SQ %04x\n", + u2FrameCtrl, + (UINT_16)(u2FrameCtrl & MASK_FC_MORE_FRAG), + u2SeqCtrl); + } + } + + GET_CURRENT_SYSTIME(&rCurrentTime); + + for (j = 0; j < MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS; j++) { + prFragInfo = &prSWRfb->prStaRec->rFragInfo[j]; + if (prFragInfo->pr1stFrag) { + /* I. If the receive timer for the MSDU or MMPDU that is stored in the + * fragments queue exceeds dot11MaxReceiveLifetime, we discard the + * uncompleted fragments. + * II. If we didn't receive the last MPDU for a period, we use + * this function for remove frames. + */ + if (CHECK_FOR_EXPIRATION(rCurrentTime, prFragInfo->rReceiveLifetimeLimit)) { + + /* cnmPktFree((P_PKT_INFO_T)prFragInfo->pr1stFrag, TRUE); */ + prFragInfo->pr1stFrag->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prFragInfo->pr1stFrag); + + prFragInfo->pr1stFrag = (P_SW_RFB_T) NULL; + } + } + } + + for (i = 0; i < MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS; i++) { + + prFragInfo = &prSWRfb->prStaRec->rFragInfo[i]; + + if (fgFirst) { /* looking for timed-out frag buffer */ + + if (prFragInfo->pr1stFrag == (P_SW_RFB_T) NULL) /* find a free frag buffer */ + break; + } else { /* looking for a buffer with desired next seqctrl */ + + if (prFragInfo->pr1stFrag == (P_SW_RFB_T) NULL) + continue; + + if (RXM_IS_QOS_DATA_FRAME(u2FrameCtrl)) { + if (RXM_IS_QOS_DATA_FRAME(prFragInfo->pr1stFrag->u2FrameCtrl)) { + if (u2SeqCtrl == prFragInfo->u2NextFragSeqCtrl) + break; + } + } else { + if (!RXM_IS_QOS_DATA_FRAME(prFragInfo->pr1stFrag->u2FrameCtrl)) { + if (u2SeqCtrl == prFragInfo->u2NextFragSeqCtrl) + break; + } + } + } + } + + if (i >= MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS) { + + /* Can't find a proper FRAG_INFO_T. + * I. 1st Fragment MPDU, all of the FragInfo are exhausted + * II. 2nd ~ (n-1)th Fragment MPDU, can't find the right FragInfo for defragment. + * Because we won't process fragment frame outside this function, so + * we should free it right away. + */ + nicRxReturnRFB(prAdapter, prSWRfb); + + return (P_SW_RFB_T) NULL; + } + + ASSERT(prFragInfo); + + /* retrieve Rx payload */ + prSWRfb->u2HeaderLen = HAL_RX_STATUS_GET_HEADER_LEN(prRxStatus); + prSWRfb->pucPayload = (PUINT_8) (((ULONG) prSWRfb->pvHeader) + prSWRfb->u2HeaderLen); + prSWRfb->u2PayloadLength = + (UINT_16) (HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus) - ((ULONG) prSWRfb->pucPayload - (ULONG) prRxStatus)); + + if (fgFirst) { + DBGLOG(RX, LOUD, "rxDefragMPDU first\n"); + + SET_EXPIRATION_TIME(prFragInfo->rReceiveLifetimeLimit, + TU_TO_SYSTIME(DOT11_RECEIVE_LIFETIME_TU_DEFAULT)); + + prFragInfo->pr1stFrag = prSWRfb; + + prFragInfo->pucNextFragStart = + (PUINT_8) prSWRfb->pucRecvBuff + HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus); + + prFragInfo->u2NextFragSeqCtrl = u2SeqCtrl + 1; + DBGLOG(RX, LOUD, "First: nextFragmentSeqCtrl = %04x, u2SeqCtrl = %04x\n", + prFragInfo->u2NextFragSeqCtrl, u2SeqCtrl); + + /* prSWRfb->fgFragmented = TRUE; */ + /* whsu: todo for checksum */ + } else { + prFragInfo->pr1stFrag->prRxStatus->u2RxByteCount += prSWRfb->u2PayloadLength; + + if (prFragInfo->pr1stFrag->prRxStatus->u2RxByteCount > CFG_RX_MAX_PKT_SIZE) { + + prFragInfo->pr1stFrag->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prFragInfo->pr1stFrag); + + prFragInfo->pr1stFrag = (P_SW_RFB_T) NULL; + + nicRxReturnRFB(prAdapter, prSWRfb); + } else { + kalMemCopy(prFragInfo->pucNextFragStart, prSWRfb->pucPayload, prSWRfb->u2PayloadLength); + /* [6630] update rx byte count and packet length */ + prFragInfo->pr1stFrag->u2PacketLen += prSWRfb->u2PayloadLength; + prFragInfo->pr1stFrag->u2PayloadLength += prSWRfb->u2PayloadLength; + + if (fgLast) { /* The last one, free the buffer */ + DBGLOG(RX, LOUD, "Defrag: finished\n"); + + prOutputSwRfb = prFragInfo->pr1stFrag; + + prFragInfo->pr1stFrag = (P_SW_RFB_T) NULL; + } else { + DBGLOG(RX, LOUD, "Defrag: mid fraged\n"); + + prFragInfo->pucNextFragStart += prSWRfb->u2PayloadLength; + + prFragInfo->u2NextFragSeqCtrl++; + } + + nicRxReturnRFB(prAdapter, prSWRfb); + } + } + + /* DBGLOG_MEM8(RXM, INFO, */ + /* prFragInfo->pr1stFrag->pucPayload, */ + /* prFragInfo->pr1stFrag->u2PayloadLength); */ +#endif + return prOutputSwRfb; +} /* end of rxmDefragMPDU() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Do duplicate detection +* +* @param prSwRfb Pointer to the RX packet +* +* @return TRUE: a duplicate, FALSE: not a duplicate +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN nicRxIsDuplicateFrame(IN OUT P_SW_RFB_T prSwRfb) +{ + + /* Non-QoS Unicast Data or Unicast MMPDU: SC Cache #4; + * QoS Unicast Data: SC Cache #0~3; + * Broadcast/Multicast: RetryBit == 0 + */ + UINT_32 u4SeqCtrlCacheIdx; + UINT_16 u2SequenceControl, u2FrameCtrl; + BOOLEAN fgIsDuplicate = FALSE, fgIsAmsduSubframe = FALSE; + P_WLAN_MAC_HEADER_T prWlanHeader = NULL; + P_HW_MAC_RX_DESC_T prRxStatus = NULL; + P_HW_MAC_RX_STS_GROUP_4_T prRxStatusGroup4 = NULL; + + DEBUGFUNC("nicRx: Enter rxmIsDuplicateFrame()\n"); + + ASSERT(prSwRfb); + + /* Situations in which the STC_REC is missing include: + * (1) Probe Request (2) (Re)Association Request (3) IBSS data frames (4) Probe Response + */ + if (!prSwRfb->prStaRec) + return FALSE; + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + fgIsAmsduSubframe = HAL_RX_STATUS_GET_PAYLOAD_FORMAT(prRxStatus); + if (HAL_RX_STATUS_IS_HEADER_TRAN(prRxStatus) == FALSE) { + prWlanHeader = (P_WLAN_MAC_HEADER_T) prSwRfb->pvHeader; + u2SequenceControl = prWlanHeader->u2SeqCtrl; + u2FrameCtrl = prWlanHeader->u2FrameCtrl; + } else { + prRxStatusGroup4 = prSwRfb->prRxStatusGroup4; + u2SequenceControl = HAL_RX_STATUS_GET_SEQFrag_NUM(prRxStatusGroup4); + u2FrameCtrl = HAL_RX_STATUS_GET_FRAME_CTL_FIELD(prRxStatusGroup4); + } + prSwRfb->u2SequenceControl = u2SequenceControl; + + /* Case 1: Unicast QoS data */ + if (RXM_IS_QOS_DATA_FRAME(u2FrameCtrl)) { /* WLAN header shall exist when doing duplicate detection */ + if (prSwRfb->prStaRec->aprRxReorderParamRefTbl[prSwRfb->ucTid]) { + + /* QoS data with an RX BA agreement + * Case 1: The packet is not an AMPDU subframe, so the RetryBit may be set to 1 (TBC). + * Case 2: The RX BA agreement was just established. Some enqueued packets may not be + * sent with aggregation. + */ + + DBGLOG(RX, LOUD, "RX: SC=0x%X (BA Entry present)\n", u2SequenceControl); + + /* Update the SN cache in order to ensure the correctness of duplicate + * removal in case the BA agreement is deleted + */ + prSwRfb->prStaRec->au2CachedSeqCtrl[prSwRfb->ucTid] = u2SequenceControl; + + /* debug */ +#if 0 + DBGLOG(RXM, LOUD, "RXM: SC= 0x%X (Cache[%d] updated) with BA\n", + u2SequenceControl, prSwRfb->ucTID); + + if (g_prMqm->arRxBaTable[prSwRfb->prStaRec->aucRxBaTable[prSwRfb->ucTID]].ucStatus == + BA_ENTRY_STATUS_DELETING) { + DBGLOG(RXM, LOUD, + "RXM: SC= 0x%X (Cache[%d] updated) with DELETING BA ****************\n", + u2SequenceControl, prSwRfb->ucTID); + } +#endif + + /* HW scoreboard shall take care Case 1. Let the layer layer handle Case 2. */ + return FALSE; /* Not a duplicate */ + } + + if (prSwRfb->prStaRec->ucDesiredPhyTypeSet & (PHY_TYPE_BIT_HT | PHY_TYPE_BIT_VHT)) { + u4SeqCtrlCacheIdx = prSwRfb->ucTid; + } else { + if (prSwRfb->ucTid < 8) { /* UP = 0~7 */ + u4SeqCtrlCacheIdx = aucTid2ACI[prSwRfb->ucTid]; + } else { + DBGLOG(RX, WARN, + "RXM: (Warning) Unknown QoS Data with TID=%d\n", prSwRfb->ucTid); + + return TRUE; /* Will be dropped */ + } + } + } + /* Case 2: Unicast non-QoS data or MMPDUs */ + else + u4SeqCtrlCacheIdx = TID_NUM; + + /* If this is a retransmission */ + if (u2FrameCtrl & MASK_FC_RETRY) { + if (u2SequenceControl != prSwRfb->prStaRec->au2CachedSeqCtrl[u4SeqCtrlCacheIdx]) { + prSwRfb->prStaRec->au2CachedSeqCtrl[u4SeqCtrlCacheIdx] = u2SequenceControl; + if (fgIsAmsduSubframe == RX_PAYLOAD_FORMAT_FIRST_SUB_AMSDU) + prSwRfb->prStaRec->afgIsIgnoreAmsduDuplicate[u4SeqCtrlCacheIdx] = TRUE; + DBGLOG(RX, LOUD, + "RXM: SC= 0x%X (Cache[%u] updated)\n", + u2SequenceControl, u4SeqCtrlCacheIdx); + } else { + /* A duplicate. */ + if (prSwRfb->prStaRec->afgIsIgnoreAmsduDuplicate[u4SeqCtrlCacheIdx]) { + if (fgIsAmsduSubframe == RX_PAYLOAD_FORMAT_LAST_SUB_AMSDU) + prSwRfb->prStaRec->afgIsIgnoreAmsduDuplicate[u4SeqCtrlCacheIdx] = FALSE; + } else { + fgIsDuplicate = TRUE; + DBGLOG(RX, LOUD, + "RXM: SC= 0x%X (Cache[%u] duplicate)\n", + u2SequenceControl, u4SeqCtrlCacheIdx); + } + } + } + + /* Not a retransmission */ + else { + + prSwRfb->prStaRec->au2CachedSeqCtrl[u4SeqCtrlCacheIdx] = u2SequenceControl; + prSwRfb->prStaRec->afgIsIgnoreAmsduDuplicate[u4SeqCtrlCacheIdx] = FALSE; + + DBGLOG(RX, LOUD, + "RXM: SC= 0x%X (Cache[%u] updated)\n", + u2SequenceControl, u4SeqCtrlCacheIdx); + } + + return fgIsDuplicate; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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; + KAL_SPIN_LOCK_DECLARATION(); + /* P_STA_RECORD_T prStaRec = (P_STA_RECORD_T)NULL; */ + + DEBUGFUNC("nicRxProcessPktWithoutReorder"); + /* DBGLOG(RX, TRACE, ("\n")); */ + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + u4CurrentRxBufferCount = prRxCtrl->rFreeSwRfbList.u4NumElem; + /* QM USED = $A, AVAILABLE COUNT = $B, INDICATED TO OS = $C + * TOTAL = $A + $B + $C + * + * Case #1 (Retain) + * ------------------------------------------------------- + * $A + $B < THRESHOLD := $A + $B + $C < THRESHOLD + $C := $TOTAL - THRESHOLD < $C + * => $C used too much, retain + * + * Case #2 (Non-Retain) + * ------------------------------------------------------- + * $A + $B > THRESHOLD := $A + $B + $C > THRESHOLD + $C := $TOTAL - THRESHOLD > $C + * => still available for $C to use + * + */ + +#if defined(LINUX) + fgIsRetained = FALSE; +#else + fgIsRetained = (((u4CurrentRxBufferCount + + qmGetRxReorderQueuedBufferCount(prAdapter) + + prTxCtrl->i4PendingFwdFrameCount) < CFG_RX_RETAINED_PKT_THRESHOLD) ? TRUE : FALSE); +#endif + + /* DBGLOG(RX, INFO, ("fgIsRetained = %d\n", fgIsRetained)); */ +#if CFG_ENABLE_PER_STA_STATISTICS + if (prSwRfb->prStaRec && (prAdapter->rWifiVar.rWfdConfigureSettings.ucWfdEnable > 0)) + prSwRfb->prStaRec->u4TotalRxPktsNumber++; +#endif + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); + if (kalProcessRxPacket(prAdapter->prGlueInfo, + prSwRfb->pvPacket, + prSwRfb->pvHeader, + (UINT_32) prSwRfb->u2PacketLen, fgIsRetained, prSwRfb->aeCSUM) != WLAN_STATUS_SUCCESS) { + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); + DBGLOG(RX, ERROR, "kalProcessRxPacket return value != WLAN_STATUS_SUCCESS\n"); + ASSERT(0); + + nicRxReturnRFB(prAdapter, prSwRfb); + return; + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); + +#if CFG_SUPPORT_MULTITHREAD + if (HAL_IS_RX_DIRECT(prAdapter)) { + kalRxIndicateOnePkt(prAdapter->prGlueInfo, + (PVOID) GLUE_GET_PKT_DESCRIPTOR(GLUE_GET_PKT_QUEUE_ENTRY(prSwRfb->pvPacket))); + RX_ADD_CNT(prRxCtrl, RX_DATA_INDICATION_COUNT, 1); + if (fgIsRetained) + RX_ADD_CNT(prRxCtrl, RX_DATA_RETAINED_COUNT, 1); + } else { + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); + QUEUE_INSERT_TAIL(&(prAdapter->rRxQueue), (P_QUE_ENTRY_T) GLUE_GET_PKT_QUEUE_ENTRY(prSwRfb->pvPacket)); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); + + prRxCtrl->ucNumIndPacket++; + kalSetTxEvent2Rx(prAdapter->prGlueInfo); + } +#else + prRxCtrl->apvIndPacket[prRxCtrl->ucNumIndPacket] = prSwRfb->pvPacket; + prRxCtrl->ucNumIndPacket++; +#endif + +#ifndef LINUX + if (fgIsRetained) { + prRxCtrl->apvRetainedPacket[prRxCtrl->ucNumRetainedPacket] = prSwRfb->pvPacket; + prRxCtrl->ucNumRetainedPacket++; + } else +#endif + prSwRfb->pvPacket = NULL; + + + /* Return RFB */ + if ((!timerPendingTimer(&prAdapter->rPacketDelaySetupTimer)) + && nicRxSetupRFB(prAdapter, prSwRfb)) { + DBGLOG(RX, WARN, + "Allocate buf failed, Start IndicatedRfb Timer (%u)\n", + RX_RETURN_INDICATED_RFB_TIMEOUT_SEC); + cnmTimerStartTimer(prAdapter, + &prAdapter->rPacketDelaySetupTimer, + SEC_TO_MSEC(RX_RETURN_INDICATED_RFB_TIMEOUT_SEC)); + } + 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; + + prMsduInfo = cnmPktAlloc(prAdapter, 0); + + 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) { + + /* parsing forward frame */ + wlanProcessTxFrame(prAdapter, (P_NATIVE_PACKET) (prSwRfb->pvPacket)); + /* pack into MSDU_INFO_T */ + nicTxFillMsduInfo(prAdapter, prMsduInfo, (P_NATIVE_PACKET) (prSwRfb->pvPacket)); + + prMsduInfo->eSrc = TX_PACKET_FORWARDING; + prMsduInfo->ucBssIndex = secGetBssIdxByWlanIdx(prAdapter, prSwRfb->ucWlanIdx); + + /* 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 */ + DBGLOG(QM, INFO, "No Tx MSDU_INFO for forwarding frames\n"); + nicRxReturnRFB(prAdapter, prSwRfb); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process broadcast data packet for both host and forwarding +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxProcessGOBroadcastPkt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_SW_RFB_T prSwRfbDuplicated; + P_TX_CTRL_T prTxCtrl; + P_RX_CTRL_T prRxCtrl; + P_HW_MAC_RX_DESC_T prRxStatus; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxProcessGOBroadcastPkt"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prTxCtrl = &prAdapter->rTxCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + 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_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfbDuplicated, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + if (prSwRfbDuplicated) { + kalMemCopy(prSwRfbDuplicated->pucRecvBuff, + prSwRfb->pucRecvBuff, ALIGN_4(prRxStatus->u2RxByteCount + HIF_RX_HW_APPENDED_LEN)); + + prSwRfbDuplicated->ucPacketType = RX_PKT_TYPE_RX_DATA; + prSwRfbDuplicated->ucStaRecIdx = prSwRfb->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); + +} + +#if CFG_SUPPORT_SNIFFER +VOID nicRxFillRadiotapMCS(IN OUT P_MONITOR_RADIOTAP_T prMonitorRadiotap, IN P_HW_MAC_RX_STS_GROUP_3_T prRxStatusGroup3) +{ + UINT_8 ucFrMode; + UINT_8 ucShortGI; + UINT_8 ucRxMode; + UINT_8 ucLDPC; + UINT_8 ucSTBC; + UINT_8 ucNess; + + ucFrMode = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET); + /* VHTA1 B0-B1 */ + ucShortGI = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_SHORT_GI) ? 1 : 0; /* HT_shortgi */ + ucRxMode = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_RX_MODE_MASK) >> RX_VT_RX_MODE_OFFSET); + ucLDPC = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_LDPC) ? 1 : 0; /* HT_adcode */ + ucSTBC = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_STBC_MASK) >> RX_VT_STBC_OFFSET); /* HT_stbc */ + ucNess = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_NESS_MASK) >> RX_VT_NESS_OFFSET); /* HT_extltf */ + + prMonitorRadiotap->ucMcsKnown = (BITS(0, 6) | (((ucNess & BIT(1)) >> 1) << 7)); + + prMonitorRadiotap->ucMcsFlags = ((ucFrMode) | + (ucShortGI << 2) | + ((ucRxMode & BIT(0)) << 3) | + (ucLDPC << 4) | (ucSTBC << 5) | ((ucNess & BIT(0)) << 7)); + /* Bit[6:0] for 802.11n, mcs0 ~ mcs7 */ + prMonitorRadiotap->ucMcsMcs = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_RX_RATE_MASK); +} + +VOID nicRxFillRadiotapVHT(IN OUT P_MONITOR_RADIOTAP_T prMonitorRadiotap, IN P_HW_MAC_RX_STS_GROUP_3_T prRxStatusGroup3) +{ + UINT_8 ucSTBC; + UINT_8 ucTxopPsNotAllow; + UINT_8 ucShortGI; + UINT_8 ucNsym; + UINT_8 ucLdpcExtraOfdmSym; + UINT_8 ucBeamFormed; + UINT_8 ucFrMode; + UINT_8 ucNsts; + UINT_8 ucMcs; + + prMonitorRadiotap->u2VhtKnown = RADIOTAP_VHT_ALL_KNOWN; + prMonitorRadiotap->u2VhtKnown &= ~RADIOTAP_VHT_SHORT_GI_NSYM_KNOWN; + + ucSTBC = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_STBC_MASK) >> RX_VT_STBC_OFFSET); /* BIT[7]: VHTA1 B3 */ + ucTxopPsNotAllow = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_TXOP_PS_NOT_ALLOWED) ? 1 : 0; /* VHTA1 B22 */ + /* + *ucNsym = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_SHORT_GI_NSYM) ? 1 : 0; //VHTA2 B1 + */ + ucNsym = 0; /* Invalid in MT6632*/ + ucShortGI = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_SHORT_GI) ? 1 : 0; /* VHTA2 B0 */ + ucLdpcExtraOfdmSym = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_LDPC_EXTRA_OFDM_SYM) ? 1 : 0; /* VHTA2 B3 */ + ucBeamFormed = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_BEAMFORMED) ? 1 : 0; /* VHTA2 B8 */ + prMonitorRadiotap->ucVhtFlags = ((ucSTBC) | + (ucTxopPsNotAllow << 1) | + (ucShortGI << 2) | (ucNsym << 3) | (ucLdpcExtraOfdmSym << 4) | (ucBeamFormed << 5)); + + ucFrMode = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET); + /* VHTA1 B0-B1 */ + switch (ucFrMode) { + case RX_VT_FR_MODE_20: + prMonitorRadiotap->ucVhtBandwidth = 0; + break; + case RX_VT_FR_MODE_40: + prMonitorRadiotap->ucVhtBandwidth = 1; + break; + case RX_VT_FR_MODE_80: + prMonitorRadiotap->ucVhtBandwidth = 4; + break; + case RX_VT_FR_MODE_160: + prMonitorRadiotap->ucVhtBandwidth = 11; + break; + default: + prMonitorRadiotap->ucVhtBandwidth = 0; + } + + /* Set to 0~7 for 1~8 space time streams */ + ucNsts = (((prRxStatusGroup3)->u4RxVector[1] & RX_VT_NSTS_MASK) >> RX_VT_NSTS_OFFSET) + 1; + /* VHTA1 B10-B12 */ + + /* Bit[3:0] for 802.11ac, mcs0 ~ mcs9 */ + ucMcs = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_RX_RATE_AC_MASK); + + prMonitorRadiotap->aucVhtMcsNss[0] = ((ucMcs << 4) | (ucNsts - ucSTBC)); /* STBC = Nsts - Nss */ + + /* + *prMonitorRadiotap->ucVhtCoding = + * (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_CODING_MASK) >> RX_VT_CODING_OFFSET); + */ + prMonitorRadiotap->ucVhtCoding = 0; /* Invalid in MT6632*/ + + /* VHTA2 B2-B3 */ + + prMonitorRadiotap->ucVhtGroupId = + (((((prRxStatusGroup3)->u4RxVector[1] & RX_VT_GROUPID_1_MASK) >> RX_VT_GROUPID_1_OFFSET) << 2) | + (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_GROUPID_0_MASK) >> RX_VT_GROUPID_0_OFFSET)); + /* VHTA1 B4-B9 */ + /* VHTA1 B13-B21 */ + prMonitorRadiotap->u2VhtPartialAid = ((((prRxStatusGroup3)->u4RxVector[2] & RX_VT_AID_1_MASK) << 4) | + (((prRxStatusGroup3)->u4RxVector[1] & RX_VT_AID_0_MASK) >> + RX_VT_AID_0_OFFSET)); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process HIF monitor packet +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxProcessMonitorPacket(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) +{ + struct sk_buff *prSkb = NULL; + P_RX_CTRL_T prRxCtrl; + P_HW_MAC_RX_DESC_T prRxStatus; + P_HW_MAC_RX_STS_GROUP_2_T prRxStatusGroup2; + P_HW_MAC_RX_STS_GROUP_3_T prRxStatusGroup3; + MONITOR_RADIOTAP_T rMonitorRadiotap; + RADIOTAP_FIELD_VENDOR_T rRadiotapFieldVendor; + PUINT_8 prVendorNsOffset; + UINT_32 u4VendorNsLen; + UINT_32 u4RadiotapLen; + UINT_32 u4ItPresent; + UINT_8 aucMtkOui[] = VENDOR_OUI_MTK; + UINT_8 ucRxRate; + UINT_8 ucRxMode; + UINT_8 ucChanNum; + UINT_8 ucMcs; + UINT_8 ucFrMode; + UINT_8 ucShortGI; + UINT_32 u4PhyRate; + +#if CFG_SUPPORT_MULTITHREAD + KAL_SPIN_LOCK_DECLARATION(); +#endif + + DEBUGFUNC("nicRxProcessMonitorPacket"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + + nicRxFillRFB(prAdapter, prSwRfb); + + /* can't parse radiotap info if no rx vector */ + if (((prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_2)) == 0) || ((prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_3)) == 0)) { + nicRxReturnRFB(prAdapter, prSwRfb); + return; + } + + prRxStatus = prSwRfb->prRxStatus; + prRxStatusGroup2 = prSwRfb->prRxStatusGroup2; + prRxStatusGroup3 = prSwRfb->prRxStatusGroup3; + + /* Bit Number 30 Vendor Namespace */ + u4VendorNsLen = sizeof(RADIOTAP_FIELD_VENDOR_T); + rRadiotapFieldVendor.aucOUI[0] = aucMtkOui[0]; + rRadiotapFieldVendor.aucOUI[1] = aucMtkOui[1]; + rRadiotapFieldVendor.aucOUI[2] = aucMtkOui[2]; + rRadiotapFieldVendor.ucSubNamespace = 0; + rRadiotapFieldVendor.u2DataLen = u4VendorNsLen - 6; + /* VHTA1 B0-B1 */ + rRadiotapFieldVendor.ucData = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_FR_MODE_MASK) >> + RX_VT_FR_MODE_OFFSET); + + ucRxMode = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_RX_MODE_MASK) >> RX_VT_RX_MODE_OFFSET); + + if (ucRxMode == RX_VT_VHT_MODE) { + u4RadiotapLen = RADIOTAP_LEN_VHT; + u4ItPresent = RADIOTAP_FIELDS_VHT; + } else if ((ucRxMode == RX_VT_MIXED_MODE) || (ucRxMode == RX_VT_GREEN_MODE)) { + u4RadiotapLen = RADIOTAP_LEN_HT; + u4ItPresent = RADIOTAP_FIELDS_HT; + } else { + u4RadiotapLen = RADIOTAP_LEN_LEGACY; + u4ItPresent = RADIOTAP_FIELDS_LEGACY; + } + + /* Radiotap Header & Bit Number 30 Vendor Namespace */ + prVendorNsOffset = (PUINT_8) &rMonitorRadiotap + u4RadiotapLen; + u4RadiotapLen += u4VendorNsLen; + kalMemSet(&rMonitorRadiotap, 0, sizeof(MONITOR_RADIOTAP_T)); + kalMemCopy(prVendorNsOffset, (PUINT_8) &rRadiotapFieldVendor, u4VendorNsLen); + rMonitorRadiotap.u2ItLen = cpu_to_le16(u4RadiotapLen); + rMonitorRadiotap.u4ItPresent = u4ItPresent; + + /* Bit Number 0 TSFT */ + rMonitorRadiotap.u8MacTime = (prRxStatusGroup2->u4Timestamp); + + /* Bit Number 1 FLAGS */ + if (HAL_RX_STATUS_IS_FRAG(prRxStatus) == TRUE) + rMonitorRadiotap.ucFlags |= BIT(3); + + if (HAL_RX_STATUS_IS_FCS_ERROR(prRxStatus) == TRUE) + rMonitorRadiotap.ucFlags |= BIT(6); + + /* Bit Number 2 RATE */ + if ((ucRxMode == RX_VT_LEGACY_CCK) || (ucRxMode == RX_VT_LEGACY_OFDM)) { + /* Bit[2:0] for Legacy CCK, Bit[3:0] for Legacy OFDM */ + ucRxRate = ((prRxStatusGroup3)->u4RxVector[0] & BITS(0, 3)); + rMonitorRadiotap.ucRate = nicGetHwRateByPhyRate(ucRxRate); + } else { + ucMcs = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_RX_RATE_AC_MASK); + /* VHTA1 B0-B1 */ + ucFrMode = (((prRxStatusGroup3)->u4RxVector[0] & RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET); + ucShortGI = ((prRxStatusGroup3)->u4RxVector[0] & RX_VT_SHORT_GI) ? 1 : 0; /* VHTA2 B0 */ + + /* ucRate(500kbs) = u4PhyRate(100kbps) / 5, max ucRate = 0xFF */ + u4PhyRate = nicGetPhyRateByMcsRate(ucMcs, ucFrMode, ucShortGI); + if (u4PhyRate > 1275) + rMonitorRadiotap.ucRate = 0xFF; + else + rMonitorRadiotap.ucRate = u4PhyRate / 5; + } + + /* Bit Number 3 CHANNEL */ + if (ucRxMode == RX_VT_LEGACY_CCK) + rMonitorRadiotap.u2ChFlags |= BIT(5); + else /* OFDM */ + rMonitorRadiotap.u2ChFlags |= BIT(6); + + ucChanNum = HAL_RX_STATUS_GET_CHNL_NUM(prRxStatus); + if (HAL_RX_STATUS_GET_RF_BAND(prRxStatus) == BAND_2G4) { + rMonitorRadiotap.u2ChFlags |= BIT(7); + rMonitorRadiotap.u2ChFrequency = (ucChanNum * 5 + 2407); + } else { /* BAND_5G */ + rMonitorRadiotap.u2ChFlags |= BIT(8); + rMonitorRadiotap.u2ChFrequency = (ucChanNum * 5 + 5000); + } + + /* Bit Number 5 ANT SIGNAL */ + rMonitorRadiotap.ucAntennaSignal = RCPI_TO_dBm(HAL_RX_STATUS_GET_RCPI0(prSwRfb->prRxStatusGroup3)); + + /* Bit Number 6 ANT NOISE */ + rMonitorRadiotap.ucAntennaNoise = ((((prRxStatusGroup3)->u4RxVector[5] & RX_VT_NF0_MASK) >> 1) + 128); + + /* Bit Number 11 ANT, Invalid for MT6632 and MT7615 */ + rMonitorRadiotap.ucAntenna = ((prRxStatusGroup3)->u4RxVector[2] & RX_VT_SEL_ANT) ? 1 : 0; + + /* Bit Number 19 MCS */ + if ((u4ItPresent & RADIOTAP_FIELD_MCS)) + nicRxFillRadiotapMCS(&rMonitorRadiotap, prRxStatusGroup3); + + /* Bit Number 20 AMPDU */ + if (HAL_RX_STATUS_IS_AMPDU_SUB_FRAME(prRxStatus)) { + if (HAL_RX_STATUS_GET_RXV_SEQ_NO(prRxStatus)) + ++prRxCtrl->u4AmpduRefNum; + rMonitorRadiotap.u4AmpduRefNum = prRxCtrl->u4AmpduRefNum; + } + + /* Bit Number 21 VHT */ + if ((u4ItPresent & RADIOTAP_FIELD_VHT)) + nicRxFillRadiotapVHT(&rMonitorRadiotap, prRxStatusGroup3); + + prSwRfb->pvHeader -= u4RadiotapLen; + kalMemCopy(prSwRfb->pvHeader, &rMonitorRadiotap, u4RadiotapLen); + + prSkb = (struct sk_buff *)(prSwRfb->pvPacket); + prSkb->data = (unsigned char *)(prSwRfb->pvHeader); + + skb_reset_tail_pointer(prSkb); + skb_trim(prSkb, 0); + skb_put(prSkb, (u4RadiotapLen + prSwRfb->u2PacketLen)); + +#if CFG_SUPPORT_MULTITHREAD + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); + QUEUE_INSERT_TAIL(&(prAdapter->rRxQueue), (P_QUE_ENTRY_T) GLUE_GET_PKT_QUEUE_ENTRY(prSwRfb->pvPacket)); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); + + prRxCtrl->ucNumIndPacket++; + kalSetTxEvent2Rx(prAdapter->prGlueInfo); +#else + prRxCtrl->apvIndPacket[prRxCtrl->ucNumIndPacket] = prSwRfb->pvPacket; + prRxCtrl->ucNumIndPacket++; +#endif + + prSwRfb->pvPacket = NULL; + /* Return RFB */ + if (nicRxSetupRFB(prAdapter, prSwRfb)) { + DBGLOG(RX, WARN, "Cannot allocate packet buffer for SwRfb!\n"); + if (!timerPendingTimer(&prAdapter->rPacketDelaySetupTimer)) { + DBGLOG(RX, WARN, "Start ReturnIndicatedRfb Timer (%u)\n", RX_RETURN_INDICATED_RFB_TIMEOUT_SEC); + cnmTimerStartTimer(prAdapter, &prAdapter->rPacketDelaySetupTimer, + SEC_TO_MSEC(RX_RETURN_INDICATED_RFB_TIMEOUT_SEC)); + } + } + nicRxReturnRFB(prAdapter, prSwRfb); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @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_HW_MAC_RX_DESC_T prRxStatus; + BOOLEAN fgDrop; + struct mt66xx_chip_info *prChipInfo; + + DEBUGFUNC("nicRxProcessDataPacket"); + /* DBGLOG(INIT, TRACE, ("\n")); */ + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + fgDrop = FALSE; + + prRxStatus = prSwRfb->prRxStatus; + prRxCtrl = &prAdapter->rRxCtrl; + prChipInfo = prAdapter->chip_info; + + /* Check AMPDU_nERR_Bitmap */ + prSwRfb->fgDataFrame = TRUE; + prSwRfb->fgFragFrame = FALSE; + prSwRfb->fgReorderBuffer = FALSE; + + /* BA session */ + if ((prRxStatus->u2StatusFlag & RXS_DW2_AMPDU_nERR_BITMAP) == RXS_DW2_AMPDU_nERR_VALUE) + prSwRfb->fgReorderBuffer = TRUE; + /* non BA session */ + else if ((prRxStatus->u2StatusFlag & RXS_DW2_RX_nERR_BITMAP) == RXS_DW2_RX_nERR_VALUE) { + if ((prRxStatus->u2StatusFlag & RXS_DW2_RX_nDATA_BITMAP) == RXS_DW2_RX_nDATA_VALUE) + prSwRfb->fgDataFrame = FALSE; + + if ((prRxStatus->u2StatusFlag & RXS_DW2_RX_FRAG_BITMAP) == RXS_DW2_RX_FRAG_VALUE) + prSwRfb->fgFragFrame = TRUE; + + } else { + fgDrop = TRUE; + if (!HAL_RX_STATUS_IS_ICV_ERROR(prRxStatus) + && HAL_RX_STATUS_IS_TKIP_MIC_ERROR(prRxStatus)) { + P_STA_RECORD_T prStaRec; + + prStaRec = cnmGetStaRecByAddress(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, + prAdapter->rWlanInfo.rCurrBssId.arMacAddress); + if (prStaRec) { + DBGLOG(RSN, EVENT, "MIC_ERR_PKT\n"); + rsnTkipHandleMICFailure(prAdapter, prStaRec, 0); + } + } +#if UNIFIED_MAC_RX_FORMAT + else if (HAL_RX_STATUS_IS_LLC_MIS(prRxStatus) + && !HAL_RX_STATUS_IS_ERROR(prRxStatus) + && !FEAT_SUP_LLC_VLAN_RX(prChipInfo)) { + PUINT_16 pu2EtherType; + + nicRxFillRFB(prAdapter, prSwRfb); + + pu2EtherType = (PUINT_16)((PUINT_8)prSwRfb->pvHeader + 2*MAC_ADDR_LEN); + + /* If ethernet type is VLAN, do not drop it. Pass up to driver process */ + if (prSwRfb->u2HeaderLen >= ETH_HLEN + && *pu2EtherType == NTOHS(ETH_P_VLAN)) + fgDrop = FALSE; + } +#else + else if (HAL_RX_STATUS_IS_LLC_MIS(prRxStatus)) { + DBGLOG(RSN, EVENT, ("LLC_MIS_ERR\n")); + fgDrop = FALSE; /* Drop after send de-auth */ + } +#endif + } + +#if 0 /* Check 1x Pkt */ + if (prSwRfb->u2PacketLen > 14) { + PUINT_8 pc = (PUINT_8) prSwRfb->pvHeader; + UINT_16 u2Etype = 0; + + u2Etype = (pc[ETHER_TYPE_LEN_OFFSET] << 8) | (pc[ETHER_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 + if (prAdapter->fgIsSupportCsumOffload && fgDrop == FALSE) { + UINT_32 u4TcpUdpIpCksStatus; + PUINT_32 pu4Temp; + + pu4Temp = (PUINT_32) prRxStatus; + u4TcpUdpIpCksStatus = *(pu4Temp + (ALIGN_4(prRxStatus->u2RxByteCount) >> 2)); + nicRxFillChksumStatus(prAdapter, prSwRfb, u4TcpUdpIpCksStatus); + } +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + /* if(secCheckClassError(prAdapter, prSwRfb, prStaRec) == TRUE && */ + if (prAdapter->fgTestMode == FALSE && fgDrop == FALSE) { + PUINT_16 pu2EtherType; + P_STA_RECORD_T prStaRec; +#if CFG_HIF_RX_STARVATION_WARNING + prRxCtrl->u4QueuedCnt++; +#endif + nicRxFillRFB(prAdapter, prSwRfb); + GLUE_SET_PKT_BSS_IDX(prSwRfb->pvPacket, secGetBssIdxByWlanIdx(prAdapter, prSwRfb->ucWlanIdx)); + pu2EtherType = + (PUINT_16)((PUINT_8)prSwRfb->pvHeader + 2*MAC_ADDR_LEN); + prStaRec = prSwRfb->prStaRec; + + /* If receive EAPOL frames of sta record != STA_STATE_3 + * Re-enqueu it of MAX_EAPOL_RE_ENQUEUE_CNT times + * Otherwise, the EAPOL frames might drop in the wpa_supp + */ + if (prSwRfb->u2HeaderLen >= ETH_HLEN + && *pu2EtherType == NTOHS(ETH_P_1X) + && prStaRec != NULL + && prStaRec->ucStaState != STA_STATE_3 + && prStaRec->eapol_re_enqueue_cnt++ < MAX_EAPOL_REQUE) { + KAL_SPIN_LOCK_DECLARATION(); + DBGLOG(RSN, WARN, + "Re-enqueue EAPOL frame: State[%u], retry[%d]\n", + prStaRec->ucStaState, + prStaRec->eapol_re_enqueue_cnt); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_INSERT_TAIL(&prAdapter->rRxCtrl.rReceivedRfbList, + &prSwRfb->rQueEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + /* Wake up Rx handling thread */ + set_bit(GLUE_FLAG_RX_BIT, + &(prAdapter->prGlueInfo->ulFlag)); + wake_up_interruptible(&(prAdapter->prGlueInfo->waitq)); + return; + } + + if ((prSwRfb->prStaRec != NULL) + && (prSwRfb->ucStaRecIdx < CFG_STA_REC_NUM) + && (prSwRfb->prStaRec->ucStaState < STA_STATE_3)) { + nicRxReturnRFB(prAdapter, prSwRfb); + RX_INC_CNT(prRxCtrl, RX_CLASS_ERR_DROP_COUNT); + RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); + DBGLOG(RX, ERROR, "staRec < state3 [%d] drop\n", + prSwRfb->prStaRec->ucStaState); + return; + } + + prRetSwRfb = qmHandleRxPackets(prAdapter, prSwRfb); + if (prRetSwRfb != NULL) { + do { +#if CFG_SUPPORT_MSP + if (prRetSwRfb->ucGroupVLD & + BIT(RX_GROUP_VLD_3) && + (prRetSwRfb->ucStaRecIdx < + CFG_STA_REC_NUM)) { + prAdapter->arStaRec + [prRetSwRfb->ucStaRecIdx]. + u4RxVector0 = + HAL_RX_VECTOR_GET_RX_VECTOR + (prRetSwRfb-> + prRxStatusGroup3, 0); + + prAdapter->arStaRec + [prRetSwRfb->ucStaRecIdx]. + u4RxVector1 = + HAL_RX_VECTOR_GET_RX_VECTOR + (prRetSwRfb-> + prRxStatusGroup3, 1); + + prAdapter->arStaRec + [prRetSwRfb->ucStaRecIdx]. + u4RxVector2 = + HAL_RX_VECTOR_GET_RX_VECTOR + (prRetSwRfb-> + prRxStatusGroup3, 2); + + prAdapter->arStaRec + [prRetSwRfb->ucStaRecIdx]. + u4RxVector3 = + HAL_RX_VECTOR_GET_RX_VECTOR + (prRetSwRfb-> + prRxStatusGroup3, 3); + + prAdapter->arStaRec + [prRetSwRfb->ucStaRecIdx]. + u4RxVector4 = + HAL_RX_VECTOR_GET_RX_VECTOR + (prRetSwRfb-> + prRxStatusGroup3, 4); + } +#endif + /* 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); + } +} + +#if 1 +VOID nicRxProcessEventPacket(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) +{ + P_CMD_INFO_T prCmdInfo; + P_WIFI_EVENT_T prEvent; + UINT_32 u4Idx, u4Size; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prEvent = (P_WIFI_EVENT_T) prSwRfb->pucRecvBuff; + + if (prEvent->ucEID != EVENT_ID_DEBUG_MSG && prEvent->ucEID != EVENT_ID_ASSERT_DUMP) { + DBGLOG(NIC, INFO, "RX EVENT: ID[0x%02X] SEQ[%u] LEN[%u]\n", + prEvent->ucEID, prEvent->ucSeqNum, prEvent->u2PacketLength); + } + + /* Event handler table */ + u4Size = sizeof(arEventTable) / sizeof(RX_EVENT_HANDLER_T); + + for (u4Idx = 0; u4Idx < u4Size; u4Idx++) { + if (prEvent->ucEID == arEventTable[u4Idx].eEID) { + arEventTable[u4Idx].pfnHandler(prAdapter, prEvent); + + break; + } + } + + /* Event cannot be found in event handler table, use default action */ + if (u4Idx >= u4Size) { + 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); + } else { + DBGLOG(RX, WARN, "UNHANDLED RX EVENT: ID[0x%02X] SEQ[%u] LEN[%u]\n", + prEvent->ucEID, prEvent->ucSeqNum, prEvent->u2PacketLength); + } + } + + /* Reset Chip NoAck flag */ + if (prAdapter->fgIsChipNoAck) { + DBGLOG(RX, WARN, "Got response from chip, clear NoAck flag!\n"); + WARN_ON(TRUE); + } + prAdapter->ucOidTimeoutCount = 0; + prAdapter->fgIsChipNoAck = FALSE; + + nicRxReturnRFB(prAdapter, prSwRfb); +} +#else +BOOLEAN fgKeepPrintCoreDump = FALSE; +/*----------------------------------------------------------------------------*/ +/*! +* @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; + BOOLEAN fgIsNewVersion; +/*#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1)*/ + UINT_32 u4QueryInfoLen; +/*#endif*/ +/*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ + P_EVENT_ACCESS_EFUSE prEventEfuseAccess; + P_EVENT_EFUSE_FREE_BLOCK_T prEventGetFreeBlock; +/*#endif*/ + DEBUGFUNC("nicRxProcessEventPacket"); + /* DBGLOG(INIT, TRACE, ("\n")); */ + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prEvent = (P_WIFI_EVENT_T) prSwRfb->pucRecvBuff; + prGlueInfo = prAdapter->prGlueInfo; + + if (prEvent->ucEID != EVENT_ID_DEBUG_MSG +#if CFG_ASSERT_DUMP + && prEvent->ucEID != EVENT_ID_ASSERT_DUMP +#endif + ) { + DBGLOG(INIT, INFO, "RX EVENT: ID[0x%02X] SEQ[%u] LEN[%u]\n", + prEvent->ucEID, prEvent->ucSeqNum, prEvent->u2PacketLength); + } + + /* Event Handling */ + switch (prEvent->ucEID) { +#if 0 /* It is removed now */ + 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; +#endif + +#if 0 + case EVENT_ID_CONNECTION_STATUS: + /* OBSELETE */ + { + P_EVENT_CONNECTION_STATUS prConnectionStatus; + + prConnectionStatus = (P_EVENT_CONNECTION_STATUS) (prEvent->aucBuffer); + + DbgPrint("RX EVENT: EVENT_ID_CONNECTION_STATUS = %d\n", prConnectionStatus->ucMediaStatus); + if (prConnectionStatus->ucMediaStatus == PARAM_MEDIA_STATE_DISCONNECTED) { + /* disconnected */ + if (kalGetMediaStateIndicated(prGlueInfo) != PARAM_MEDIA_STATE_DISCONNECTED) { + + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + + prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); + } + } else if (prConnectionStatus->ucMediaStatus == PARAM_MEDIA_STATE_CONNECTED) { /* connected */ + prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); + + /* fill information for association result */ + prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen = prConnectionStatus->ucSsidLen; + kalMemCopy(prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, + prConnectionStatus->aucSsid, prConnectionStatus->ucSsidLen); + + kalMemCopy(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, + prConnectionStatus->aucBssid, MAC_ADDR_LEN); + /* @FIXME */ + prAdapter->rWlanInfo.rCurrBssId.u4Privacy = prConnectionStatus->ucEncryptStatus; + prAdapter->rWlanInfo.rCurrBssId.rRssi = 0; /* @FIXME */ + /* @FIXME */ + prAdapter->rWlanInfo.rCurrBssId.eNetworkTypeInUse = PARAM_NETWORK_TYPE_AUTOMODE; + prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4BeaconPeriod + = prConnectionStatus->u2BeaconPeriod; + prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4ATIMWindow + = prConnectionStatus->u2ATIMWindow; + prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4DSConfig + = prConnectionStatus->u4FreqInKHz; + prAdapter->rWlanInfo.ucNetworkType = prConnectionStatus->ucNetworkType; + + switch (prConnectionStatus->ucInfraMode) { + case 0: + prAdapter->rWlanInfo.rCurrBssId.eOpMode = NET_TYPE_IBSS; + break; + case 1: + prAdapter->rWlanInfo.rCurrBssId.eOpMode = NET_TYPE_INFRA; + break; + case 2: + default: + prAdapter->rWlanInfo.rCurrBssId.eOpMode = NET_TYPE_AUTO_SWITCH; + break; + } + /* always indicate to OS according to MSDN (re-association/roaming) */ + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_CONNECT, NULL, 0); + } + } + break; + + case EVENT_ID_SCAN_RESULT: + /* OBSELETE */ + break; +#endif + + case EVENT_ID_RX_ADDBA: + /* The FW indicates that an RX BA agreement will be established */ + qmHandleEventRxAddBa(prAdapter, prEvent); + break; + + case EVENT_ID_RX_DELBA: + /* The FW indicates that an RX BA agreement has been deleted */ + qmHandleEventRxDelBa(prAdapter, prEvent); + break; + + case EVENT_ID_CHECK_REORDER_BUBBLE: + qmHandleEventCheckReorderBubble(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, 0, (P_EVENT_LINK_QUALITY) prLqEx); + if (prLqEx->ucIsLQ1Rdy) + nicUpdateLinkQuality(prAdapter, 1, (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, 0, (P_EVENT_LINK_QUALITY) (prEvent->aucBuffer)); + } +#else + /*only support ais query */ + { + UINT_8 ucBssIndex; + P_BSS_INFO_T prBssInfo; + + for (ucBssIndex = 0; ucBssIndex < BSS_INFO_NUM; ucBssIndex++) { + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + + if ((prBssInfo->eNetworkType == NETWORK_TYPE_AIS) + && (prBssInfo->fgIsInUse)) + break; + } + + if (ucBssIndex >= BSS_INFO_NUM) + ucBssIndex = 1; /* No hit(bss1 for default ais network) */ + /* printk("=======> rssi with bss%d ,%d\n",ucBssIndex, + * ((P_EVENT_LINK_QUALITY_V2)(prEvent->aucBuffer))->rLq[ucBssIndex].cRssi); + */ + nicUpdateLinkQuality(prAdapter, ucBssIndex, (P_EVENT_LINK_QUALITY_V2) (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; + +/*#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1)*/ + case EVENT_ID_LAYER_0_EXT_MAGIC_NUM: + if ((prEvent->ucExtenEID) == EXT_EVENT_ID_CMD_RESULT) { + + u4QueryInfoLen = sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T); + + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + if ((prCmdInfo->fgIsOid) != 0) { + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + } + } +/*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ + + else if ((prEvent->ucExtenEID) == EXT_EVENT_ID_CMD_EFUSE_ACCESS) { + u4QueryInfoLen = sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T); + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + prEventEfuseAccess = (P_EVENT_ACCESS_EFUSE) (prEvent->aucBuffer); + + /* Efuse block size 16 */ + kalMemCopy(prAdapter->aucEepromVaule, prEventEfuseAccess->aucData, 16); + + if (prCmdInfo != NULL) { + if ((prCmdInfo->fgIsOid) != 0) { + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + } + } + } + + else if ((prEvent->ucExtenEID) == EXT_EVENT_ID_EFUSE_FREE_BLOCK) { + u4QueryInfoLen = sizeof(PARAM_CUSTOM_EFUSE_FREE_BLOCK_T); + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + prEventGetFreeBlock = (P_EVENT_EFUSE_FREE_BLOCK_T) (prEvent->aucBuffer); + prAdapter->u4FreeBlockNum = prEventGetFreeBlock->u2FreeBlockNum; + + if (prCmdInfo != NULL) { + if ((prCmdInfo->fgIsOid) != 0) { + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + u4QueryInfoLen, + WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + } + } +/*#endif*/ + break; +/*#endif*/ + + 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, + prAdapter->prAisBssInfo->ucBssIndex, + 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; + +#if 0 /* Marked for MT6630 */ + 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->u2PacketLength - 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->u2PacketLength - 8); + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID) prAuthEvent, + sizeof(PARAM_STATUS_INDICATION_T) + u4LenOfUsedBuffer); + } + break; +#endif + +#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: + fgIsNewVersion = TRUE; + scnEventScanDone(prAdapter, (P_EVENT_SCAN_DONE) (prEvent->aucBuffer), fgIsNewVersion); + break; + + case EVENT_ID_NLO_DONE: + DBGLOG(INIT, INFO, "EVENT_ID_NLO_DONE\n"); + scnEventNloDone(prAdapter, (P_EVENT_NLO_DONE_T) (prEvent->aucBuffer)); +#if CFG_SUPPORT_PNO + prAdapter->prAisBssInfo->fgIsPNOEnable = FALSE; + if (prAdapter->prAisBssInfo->fgIsNetRequestInActive && prAdapter->prAisBssInfo->fgIsPNOEnable) { + UNSET_NET_ACTIVE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + DBGLOG(INIT, INFO, "INACTIVE AIS from ACTIVEto disable PNO\n"); + /* sync with firmware */ + nicDeactivateNetwork(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + } +#endif + break; + + case EVENT_ID_TX_DONE: +#if 1 + nicTxProcessTxDoneEvent(prAdapter, prEvent); +#else + { + P_EVENT_TX_DONE_T prTxDone; + + prTxDone = (P_EVENT_TX_DONE_T) (prEvent->aucBuffer); + + DBGLOG(INIT, INFO, "EVENT_ID_TX_DONE WIDX:PID[%u:%u] Status[%u] SN[%u]\n", + prTxDone->ucWlanIndex, prTxDone->ucPacketSeq, prTxDone->ucStatus, + prTxDone->u2SequenceNumber); + + /* call related TX Done Handler */ + prMsduInfo = nicGetPendingTxMsduInfo(prAdapter, prTxDone->ucWlanIndex, 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)); + + if (prMsduInfo->eSrc == TX_PACKET_MGMT) + cnmMgtPktFree(prAdapter, prMsduInfo); + else + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } + } +#endif + break; + + case EVENT_ID_SLEEPY_INFO: +#if defined(_HIF_USB) +#else + { + P_EVENT_SLEEPY_INFO_T prEventSleepyNotify; + + prEventSleepyNotify = (P_EVENT_SLEEPY_INFO_T) (prEvent->aucBuffer); + + /* DBGLOG(RX, INFO, ("ucSleepyState = %d\n", prEventSleepyNotify->ucSleepyState)); */ + + prAdapter->fgWiFiInSleepyState = (BOOLEAN) (prEventSleepyNotify->ucSleepyState); + +#if CFG_SUPPORT_MULTITHREAD + if (prEventSleepyNotify->ucSleepyState) + kalSetFwOwnEvent2Hif(prGlueInfo); +#endif + } +#endif + 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; + +#if CFG_SUPPORT_MSP + case EVENT_ID_WLAN_INFO: + /* buffer statistics for further query */ + prAdapter->fgIsStatValid = TRUE; + prAdapter->rStatUpdateTime = kalGetTimeTick(); + kalMemCopy(&prAdapter->rEventWlanInfo, prEvent->aucBuffer, sizeof(EVENT_WLAN_INFO)); + + DBGLOG(RSN, INFO, "EVENT_ID_WLAN_INFO"); + /* 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_MIB_INFO: + /* buffer statistics for further query */ + prAdapter->fgIsStatValid = TRUE; + prAdapter->rStatUpdateTime = kalGetTimeTick(); + + DBGLOG(RSN, INFO, "EVENT_ID_MIB_INFO"); + /* command response handling */ + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + if (prCmdInfo->pfCmdDoneHandler) + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); + else if (prCmdInfo->fgIsOid) + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + + break; +#endif + 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_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; + P_EVENT_BSS_BEACON_TIMEOUT_T prEventBssBeaconTimeout; + + prEventBssBeaconTimeout = (P_EVENT_BSS_BEACON_TIMEOUT_T) (prEvent->aucBuffer); + + if (prEventBssBeaconTimeout->ucBssIndex >= BSS_INFO_NUM) + break; + + DBGLOG(INIT, INFO, "Reason code: %d\n", prEventBssBeaconTimeout->ucReasonCode); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prEventBssBeaconTimeout->ucBssIndex); + + if (prEventBssBeaconTimeout->ucBssIndex == prAdapter->prAisBssInfo->ucBssIndex) + aisBssBeaconTimeout(prAdapter); +#if CFG_ENABLE_WIFI_DIRECT + else if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) + p2pRoleFsmRunEventBeaconTimeout(prAdapter, prBssInfo); +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (GET_BSS_INFO_BY_INDEX(prAdapter, prEventBssBeaconTimeout->ucBssIndex)->eNetworkType == + NETWORK_TYPE_BOW) { + /* ToDo:: Nothing */ + } +#endif + else { + DBGLOG(RX, ERROR, + "EVENT_ID_BSS_BEACON_TIMEOUT: (ucBssIndex = %d)\n", + prEventBssBeaconTimeout->ucBssIndex); + } + } + + 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 (GET_BSS_INFO_BY_INDEX(prAdapter, prEventUpdateNoaParam->ucBssIndex)->eNetworkType == + NETWORK_TYPE_P2P) { + p2pProcessEvent_UpdateNOAParam(prAdapter, prEventUpdateNoaParam->ucBssIndex, + 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 = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + bssRemoveClient(prAdapter, prBssInfo, prStaRec); + + /* Call False Auth */ + if (prAdapter->fgIsP2PRegistered) { + p2pFuncDisconnect(prAdapter, prBssInfo, 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_CMD_ROAMING_TRANSIT_T prTransit; + + prTransit = (P_CMD_ROAMING_TRANSIT_T) (prEvent->aucBuffer); + roamingFsmProcessEvent(prAdapter, prTransit); + } +#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 (authSendDeauthFrame(prAdapter, + NULL, + NULL, + prSwRfb, + REASON_CODE_CLASS_3_ERR, + (PFN_TX_DONE_HANDLER) NULL) == WLAN_STATUS_SUCCESS) { + 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 + DBGLOG(RSN, EVENT, "BCM BWCS Event: %02x%02x%02x%02x\n", + prEventBwcsStatus->u.aucBTPParams[0], + prEventBwcsStatus->u.aucBTPParams[1], + prEventBwcsStatus->u.aucBTPParams[2], prEventBwcsStatus->u.aucBTPParams[3]); +#endif + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_BWCS_UPDATE, + (PVOID) prEventBwcsStatus, sizeof(PTA_IPC_T)); + } + + break; + + case EVENT_ID_UPDATE_BCM_DEBUG: + { + P_PTA_IPC_T prEventBwcsStatus; + + prEventBwcsStatus = (P_PTA_IPC_T) (prEvent->aucBuffer); + +#if CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(RSN, EVENT, "BCM FW status: %02x%02x%02x%02x\n", + prEventBwcsStatus->u.aucBTPParams[0], + prEventBwcsStatus->u.aucBTPParams[1], + prEventBwcsStatus->u.aucBTPParams[2], prEventBwcsStatus->u.aucBTPParams[3]); +#endif + } + + break; +#endif + case EVENT_ID_ADD_PKEY_DONE: + { + P_EVENT_ADD_KEY_DONE_INFO prAddKeyDone; + P_STA_RECORD_T prStaRec; + + prAddKeyDone = (P_EVENT_ADD_KEY_DONE_INFO) (prEvent->aucBuffer); + + DBGLOG(RSN, EVENT, + "EVENT_ID_ADD_PKEY_DONE BSSIDX=%d " MACSTR "\n", + prAddKeyDone->ucBSSIndex, MAC2STR(prAddKeyDone->aucStaAddr)); + + prStaRec = cnmGetStaRecByAddress(prAdapter, prAddKeyDone->ucBSSIndex, prAddKeyDone->aucStaAddr); + + if (prStaRec) { + DBGLOG(RSN, EVENT, "STA " MACSTR " Add Key Done!!\n", MAC2STR(prStaRec->aucMacAddr)); + prStaRec->fgIsTxKeyReady = TRUE; + qmUpdateStaRec(prAdapter, prStaRec); + } + } + break; + case EVENT_ID_ICAP_DONE: + { + P_EVENT_ICAP_STATUS_T prEventIcapStatus; + PARAM_CUSTOM_MEM_DUMP_STRUCT_T rMemDumpInfo; + UINT_32 u4QueryInfo; + + prEventIcapStatus = (P_EVENT_ICAP_STATUS_T) (prEvent->aucBuffer); + + rMemDumpInfo.u4Address = prEventIcapStatus->u4StartAddress; + rMemDumpInfo.u4Length = prEventIcapStatus->u4IcapSieze; +#if CFG_SUPPORT_QA_TOOL + rMemDumpInfo.u4IcapContent = prEventIcapStatus->u4IcapContent; +#endif + + wlanoidQueryMemDump(prAdapter, &rMemDumpInfo, sizeof(rMemDumpInfo), &u4QueryInfo); + + } + + break; + case EVENT_ID_DEBUG_MSG: + { + P_EVENT_DEBUG_MSG_T prEventDebugMsg; + UINT_16 u2DebugMsgId; + UINT_8 ucMsgType; + UINT_8 ucFlags; + UINT_32 u4Value; + UINT_16 u2MsgSize; + P_UINT_8 pucMsg; + + prEventDebugMsg = (P_EVENT_DEBUG_MSG_T) (prEvent->aucBuffer); + + u2DebugMsgId = prEventDebugMsg->u2DebugMsgId; + ucMsgType = prEventDebugMsg->ucMsgType; + ucFlags = prEventDebugMsg->ucFlags; + u4Value = prEventDebugMsg->u4Value; + u2MsgSize = prEventDebugMsg->u2MsgSize; + pucMsg = prEventDebugMsg->aucMsg; + + DBGLOG(SW4, TRACE, "DEBUG_MSG Id %u Type %u Fg 0x%x Val 0x%x Size %u\n", + u2DebugMsgId, ucMsgType, ucFlags, u4Value, u2MsgSize); + + if (u2MsgSize <= DEBUG_MSG_SIZE_MAX) { + if (ucMsgType >= DEBUG_MSG_TYPE_END) + ucMsgType = DEBUG_MSG_TYPE_MEM32; + + if (ucMsgType == DEBUG_MSG_TYPE_ASCII) { + PUINT_8 pucChr; + + pucMsg[u2MsgSize] = '\0'; + + /* skip newline */ + pucChr = kalStrChr(pucMsg, '\0'); + if (*(pucChr - 1) == '\n') + *(pucChr - 1) = '\0'; + + DBGLOG(SW4, INFO, "%s\n", pucMsg); + } else if (ucMsgType == DEBUG_MSG_TYPE_MEM8) { + DBGLOG(SW4, INFO, "Dump MEM8\n"); + DBGLOG_MEM8(SW4, INFO, pucMsg, u2MsgSize); + } else { + DBGLOG(SW4, INFO, "Dump MEM32\n"); + DBGLOG_MEM32(SW4, INFO, pucMsg, u2MsgSize); + } + } /* DEBUG_MSG_SIZE_MAX */ + else + DBGLOG(SW4, INFO, "Debug msg size %u is too large.\n", u2MsgSize); + } + break; + +#if CFG_SUPPORT_BATCH_SCAN + case EVENT_ID_BATCH_RESULT: + DBGLOG(SCN, TRACE, "Got EVENT_ID_BATCH_RESULT"); + + /* command response handling */ + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + if (prCmdInfo->pfCmdDoneHandler) + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); + else if (prCmdInfo->fgIsOid) + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + + break; +#endif /* CFG_SUPPORT_BATCH_SCAN */ + +#if CFG_SUPPORT_TDLS + case EVENT_ID_TDLS: + + TdlsexEventHandle(prAdapter->prGlueInfo, + (UINT_8 *) prEvent->aucBuffer, (UINT_32) (prEvent->u2PacketLength - 8)); + break; +#endif /* CFG_SUPPORT_TDLS */ + + case EVENT_ID_DUMP_MEM: + DBGLOG(INIT, INFO, "%s: EVENT_ID_DUMP_MEM\n", __func__); + + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + DBGLOG(INIT, INFO, ": ==> 1\n"); + 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); + } else { + /* Burst mode */ + DBGLOG(INIT, INFO, ": ==> 2\n"); + nicEventQueryMemDump(prAdapter, prEvent->aucBuffer); + } + break; +#if CFG_ASSERT_DUMP + case EVENT_ID_ASSERT_DUMP: + + if (prEvent->ucS2DIndex == S2D_INDEX_EVENT_N2H) { + if (!prAdapter->fgN9AssertDumpOngoing) { + DBGLOG(INIT, INFO, "%s: EVENT_ID_ASSERT_DUMP\n", __func__); + DBGLOG(INIT, INFO, "\n[DUMP_N9]====N9 ASSERT_DUMPSTART====\n"); + fgKeepPrintCoreDump = TRUE; + if (kalOpenCorDumpFile(TRUE) != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "kalOpenCorDumpFile fail\n"); + else + prAdapter->fgN9CorDumpFileOpend = TRUE; + + prAdapter->fgN9AssertDumpOngoing = TRUE; + } else if (prAdapter->fgN9AssertDumpOngoing) { + + if (fgKeepPrintCoreDump) + DBGLOG(INIT, INFO, "[DUMP_N9]%s:\n", prEvent->aucBuffer); + if (!kalStrnCmp(prEvent->aucBuffer, ";more log added here", 5) + || !kalStrnCmp(prEvent->aucBuffer, ";[core dump start]", 5)) + fgKeepPrintCoreDump = FALSE; + + if (prAdapter->fgN9CorDumpFileOpend) { + if (kalWriteCorDumpFile(prEvent->aucBuffer, prEvent->u2PacketLength, TRUE) != + WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "kalWriteN9CorDumpFile fail\n"); + } + } + wlanCorDumpTimerReset(prAdapter, TRUE); + } + } else { + /* prEvent->ucS2DIndex == S2D_INDEX_EVENT_C2H */ + if (!prAdapter->fgCr4AssertDumpOngoing) { + DBGLOG(INIT, INFO, "%s: EVENT_ID_ASSERT_DUMP\n", __func__); + DBGLOG(INIT, INFO, "\n[DUMP_Cr4]====CR4 ASSERT_DUMPSTART====\n"); + fgKeepPrintCoreDump = TRUE; + if (kalOpenCorDumpFile(FALSE) != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "kalOpenCorDumpFile fail\n"); + else + prAdapter->fgCr4CorDumpFileOpend = TRUE; + + prAdapter->fgCr4AssertDumpOngoing = TRUE; + } else if (prAdapter->fgCr4AssertDumpOngoing) { + if (fgKeepPrintCoreDump) + DBGLOG(INIT, INFO, "[DUMP_CR4]%s:\n", prEvent->aucBuffer); + if (!kalStrnCmp(prEvent->aucBuffer, ";more log added here", 5)) + fgKeepPrintCoreDump = FALSE; + + if (prAdapter->fgCr4CorDumpFileOpend) { + if (kalWriteCorDumpFile(prEvent->aucBuffer, prEvent->u2PacketLength, FALSE) != + WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "kalWriteN9CorDumpFile fail\n"); + } + } + wlanCorDumpTimerReset(prAdapter, FALSE); + } + } + break; + +#endif + + case EVENT_ID_RDD_SEND_PULSE: + DBGLOG(INIT, INFO, "%s: EVENT_ID_RDD_SEND_PULSE\n", __func__); + + nicEventRddPulseDump(prAdapter, prEvent->aucBuffer); + break; + + case EVENT_ID_ACCESS_RX_STAT: + case EVENT_ID_ACCESS_REG: + case EVENT_ID_NIC_CAPABILITY: + /* 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; + } + + /* Reset Chip NoAck flag */ + if (prGlueInfo->prAdapter->fgIsChipNoAck) { + DBGLOG(INIT, WARN, "Got response from chip, clear NoAck flag!\n"); + WARN_ON(TRUE); + } + prGlueInfo->prAdapter->ucOidTimeoutCount = 0; + prGlueInfo->prAdapter->fgIsChipNoAck = FALSE; + + nicRxReturnRFB(prAdapter, prSwRfb); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @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) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + 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_WLAN_MAC_MGMT_HEADER_T prWlanMgmtHeader; + UINT_16 u2TxFrameCtrl; + + 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) { + + prWlanMgmtHeader = (P_WLAN_MAC_MGMT_HEADER_T) (prSwRfb->pvHeader); + + DBGLOG(SW4, INFO, + "QM RX MGT: net %u sta idx %u wlan idx %u ssn %u ptype %u subtype %u 11 %u\n", + prSwRfb->prStaRec->ucBssIndex, prSwRfb->ucStaRecIdx, + prSwRfb->ucWlanIdx, prWlanMgmtHeader->u2SeqCtrl, + /* 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 CFG_SUPPORT_802_11W + if (HAL_RX_STATUS_IS_ICV_ERROR(prSwRfb->prRxStatus)) { + if (HAL_RX_STATUS_GET_SEC_MODE(prSwRfb->prRxStatus) == CIPHER_SUITE_BIP) + DBGLOG(RSN, INFO, "[MFP] RX with BIP ICV ERROR\n"); + else + DBGLOG(RSN, INFO, "[MFP] RX with ICV ERROR\n"); + + nicRxReturnRFB(prAdapter, prSwRfb); + RX_INC_CNT(&prAdapter->rRxCtrl, RX_DROP_TOTAL_COUNT); + return; + } +#endif + + if (prAdapter->fgTestMode == FALSE) { +#if CFG_MGMT_FRAME_HANDLING + prGlueInfo = prAdapter->prGlueInfo; + if ((prGlueInfo == NULL) || (prGlueInfo->u4ReadyFlag == 0)) { + DBGLOG(RX, WARN, + "Bypass this mgmt frame without wlanProbe done\n"); + } else 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); +} + +VOID nicRxProcessMsduReport(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) +{ + halRxProcessMsduReport(prAdapter, prSwRfb); + + 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; + QUE_T rTempRfbList; + P_QUE_T prTempRfbList = &rTempRfbList; + UINT_32 u4RxLoopCount; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxProcessRFBs"); + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + prRxCtrl->ucNumIndPacket = 0; + prRxCtrl->ucNumRetainedPacket = 0; + u4RxLoopCount = prAdapter->rWifiVar.u4TxRxLoopCount; + + QUEUE_INITIALIZE(prTempRfbList); + + while (u4RxLoopCount--) { + while (QUEUE_IS_NOT_EMPTY(&prRxCtrl->rReceivedRfbList)) { + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_MOVE_ALL(prTempRfbList, &prRxCtrl->rReceivedRfbList); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + while (QUEUE_IS_NOT_EMPTY(prTempRfbList)) { + QUEUE_REMOVE_HEAD(prTempRfbList, prSwRfb, P_SW_RFB_T); + + switch (prSwRfb->ucPacketType) { + case RX_PKT_TYPE_RX_DATA: +#if CFG_SUPPORT_SNIFFER + if (prAdapter->prGlueInfo->fgIsEnableMon && HAL_IS_RX_DIRECT(prAdapter)) { + nicRxProcessMonitorPacket(prAdapter, prSwRfb); + break; + } else if (prAdapter->prGlueInfo->fgIsEnableMon) { + nicRxProcessMonitorPacket(prAdapter, prSwRfb); + break; + } +#endif + nicRxProcessDataPacket( + prAdapter, prSwRfb); + break; + + case RX_PKT_TYPE_SW_DEFINED: + /* HIF_RX_PKT_TYPE_EVENT */ + if ((prSwRfb->prRxStatus->u2PktTYpe & RXM_RXD_PKT_TYPE_SW_BITMAP) == + RXM_RXD_PKT_TYPE_SW_EVENT) { + nicRxProcessEventPacket(prAdapter, prSwRfb); + } + /* case HIF_RX_PKT_TYPE_MANAGEMENT: */ + else if ((prSwRfb->prRxStatus->u2PktTYpe & RXM_RXD_PKT_TYPE_SW_BITMAP) == + RXM_RXD_PKT_TYPE_SW_FRAME) { + nicRxProcessMgmtPacket(prAdapter, prSwRfb); + } else if (prSwRfb->pvHeader == NULL) { + DBGLOG(RX, ERROR, + "Rcv Pkt format wrong.!!!\n"); + nicRxReturnRFB(prAdapter, + prSwRfb); + RX_INC_CNT(prRxCtrl, + RX_TYPE_ERR_DROP_COUNT); + RX_INC_CNT(prRxCtrl, + RX_DROP_TOTAL_COUNT); + } else { + DBGLOG(RX, ERROR, "u2PktTYpe(0x%04X) is OUT OF DEF.!!!\n", + prSwRfb->prRxStatus->u2PktTYpe); + DBGLOG_MEM8(RX, ERROR, (PUINT_8) prSwRfb->pvHeader, + prSwRfb->u2PacketLen); + + /*ASSERT(0);*/ + nicRxReturnRFB(prAdapter, prSwRfb); + RX_INC_CNT(prRxCtrl, RX_TYPE_ERR_DROP_COUNT); + RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); + + } + break; + + case RX_PKT_TYPE_MSDU_REPORT: + nicRxProcessMsduReport(prAdapter, prSwRfb); + break; + + /* case HIF_RX_PKT_TYPE_TX_LOOPBACK: */ + /* case HIF_RX_PKT_TYPE_MANAGEMENT: */ + case RX_PKT_TYPE_TX_STATUS: + case RX_PKT_TYPE_RX_VECTOR: + case RX_PKT_TYPE_TM_REPORT: + default: + nicRxReturnRFB(prAdapter, prSwRfb); + 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; + } + + } + + if (prRxCtrl->ucNumIndPacket > 0) { + RX_ADD_CNT(prRxCtrl, RX_DATA_INDICATION_COUNT, prRxCtrl->ucNumIndPacket); + RX_ADD_CNT(prRxCtrl, RX_DATA_RETAINED_COUNT, prRxCtrl->ucNumRetainedPacket); +#if !CFG_SUPPORT_MULTITHREAD + /* 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 +#endif + } + } + } +} /* end of nicRxProcessRFBs() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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, prRxStatus)), + (sizeof(SW_RFB_T) - OFFSET_OF(SW_RFB_T, prRxStatus))); + } + + /* ToDo: remove prHifRxHdr */ + /* prSwRfb->prHifRxHdr = (P_HIF_RX_HEADER_T)(prSwRfb->pucRecvBuff); */ + prSwRfb->prRxStatus = (P_HW_MAC_RX_DESC_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_FREE_QUE); + + if (prSwRfb->pvPacket) { + /* QUEUE_INSERT_TAIL */ + QUEUE_INSERT_TAIL(&prRxCtrl->rFreeSwRfbList, prQueEntry); + } else { + /* QUEUE_INSERT_TAIL */ + QUEUE_INSERT_TAIL(&prRxCtrl->rIndicatedRfbList, prQueEntry); + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + /* Trigger Rx if there are free SwRfb */ + if (halIsPendingRx(prAdapter) && (prRxCtrl->rFreeSwRfbList.u4NumElem > 0)) + kalSetIntEvent(prAdapter->prGlueInfo); +} /* 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); + + /* SER break point */ + if (nicSerIsRxStop(prAdapter)) { + /* Skip following Rx handling */ + return; + } + + halProcessRxInterrupt(prAdapter); + +#if CFG_SUPPORT_MULTITHREAD + set_bit(GLUE_FLAG_RX_BIT, &(prAdapter->prGlueInfo->ulFlag)); + wake_up_interruptible(&(prAdapter->prGlueInfo->waitq)); +#else + nicRxProcessRFBs(prAdapter); +#endif + + 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)) { + /* count success num */ + RX_INC_CNT(prRxCtrl, RX_CSUM_IP_SUCCESS_COUNT); + } else if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_FAILED) || (aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_FAILED)) { + RX_INC_CNT(prRxCtrl, RX_CSUM_IP_FAILED_COUNT); + } else if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_NONE) && (aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_NONE)) { + RX_INC_CNT(prRxCtrl, RX_CSUM_UNKNOWN_L3_PKT_COUNT); + } else { + ASSERT(0); + } + + if (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_SUCCESS) { + /* count success num */ + RX_INC_CNT(prRxCtrl, RX_CSUM_TCP_SUCCESS_COUNT); + } else if (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_FAILED) { + RX_INC_CNT(prRxCtrl, RX_CSUM_TCP_FAILED_COUNT); + } else if (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_SUCCESS) { + RX_INC_CNT(prRxCtrl, RX_CSUM_UDP_SUCCESS_COUNT); + } else if (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_FAILED) { + RX_INC_CNT(prRxCtrl, RX_CSUM_UDP_FAILED_COUNT); + } else if ((aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_NONE) && (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_NONE)) { + RX_INC_CNT(prRxCtrl, RX_CSUM_UNKNOWN_L4_PKT_COUNT); + } else { + ASSERT(0); + } + +} /* end of nicRxUpdateCSUMStatistics() */ +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to query current status of RX Module. +* +* @param prAdapter Pointer to the Adapter structure. +* @param pucBuffer Pointer to the message buffer. +* @param pu4Count Pointer to the buffer of message length count. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxQueryStatus(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuffer, OUT PUINT_32 pu4Count) +{ + P_RX_CTRL_T prRxCtrl; + PUINT_8 pucCurrBuf = pucBuffer; + UINT_32 u4CurrCount; + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + /* if (pucBuffer) {} *//* For Windows, we'll print directly instead of sprintf() */ + ASSERT(pu4Count); + +#define SPRINTF_RX_QSTATUS(arg) \ + { \ + u4CurrCount = scnprintf(pucCurrBuf, *pu4Count, PRINTF_ARG arg); \ + pucCurrBuf += (UINT_8)u4CurrCount; \ + *pu4Count -= u4CurrCount; \ + } + + + SPRINTF_RX_QSTATUS(("\n\nRX CTRL STATUS:")); + SPRINTF_RX_QSTATUS(("\n===============")); + SPRINTF_RX_QSTATUS(("\nFREE RFB w/i BUF LIST :%9u", + prRxCtrl->rFreeSwRfbList.u4NumElem)); + SPRINTF_RX_QSTATUS(("\nFREE RFB w/o BUF LIST :%9u", + prRxCtrl->rIndicatedRfbList.u4NumElem)); + SPRINTF_RX_QSTATUS(("\nRECEIVED RFB LIST :%9u", + prRxCtrl->rReceivedRfbList.u4NumElem)); + + SPRINTF_RX_QSTATUS(("\n\n")); + + /* *pu4Count = (UINT_32)((UINT_32)pucCurrBuf - (UINT_32)pucBuffer); */ + +} /* end of nicRxQueryStatus() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Clear RX related counters +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return - (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxClearStatistics(IN P_ADAPTER_T prAdapter) +{ + P_RX_CTRL_T prRxCtrl; + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + RX_RESET_ALL_CNTS(prRxCtrl); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to query current statistics of RX Module. +* +* @param prAdapter Pointer to the Adapter structure. +* @param pucBuffer Pointer to the message buffer. +* @param pu4Count Pointer to the buffer of message length count. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxQueryStatistics(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuffer, OUT PUINT_32 pu4Count) +{ + P_RX_CTRL_T prRxCtrl; + PUINT_8 pucCurrBuf = pucBuffer; + UINT_32 u4CurrCount; + + 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) \ + { \ + u4CurrCount = scnprintf(pucCurrBuf, *pu4Count, "%-30s : %u\n", \ + #eCounter, (UINT_32)prRxCtrl->au8Statistics[eCounter]); \ + pucCurrBuf += (UINT_8)u4CurrCount; \ + *pu4Count -= u4CurrCount; \ + } + + SPRINTF_RX_COUNTER(RX_MPDU_TOTAL_COUNT); + SPRINTF_RX_COUNTER(RX_SIZE_ERR_DROP_COUNT); + SPRINTF_RX_COUNTER(RX_DATA_INDICATION_COUNT); + SPRINTF_RX_COUNTER(RX_DATA_RETURNED_COUNT); + SPRINTF_RX_COUNTER(RX_DATA_RETAINED_COUNT); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD || CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 + SPRINTF_RX_COUNTER(RX_CSUM_TCP_FAILED_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_UDP_FAILED_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_IP_FAILED_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_TCP_SUCCESS_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_UDP_SUCCESS_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_IP_SUCCESS_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_UNKNOWN_L4_PKT_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_UNKNOWN_L3_PKT_COUNT); + SPRINTF_RX_COUNTER(RX_IP_V6_PKT_CCOUNT); +#endif + + /* *pu4Count = (UINT_32)(pucCurrBuf - pucBuffer); */ + + nicRxClearStatistics(prAdapter); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read the Response data from data port +* +* @param prAdapter pointer to the Adapter handler +* @param pucRspBuffer pointer to the Response buffer +* +* @retval WLAN_STATUS_SUCCESS: Response packet has been read +* @retval WLAN_STATUS_FAILURE: Read Response packet timeout or error occurred +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicRxWaitResponse(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucPortIdx, OUT PUINT_8 pucRspBuffer, IN UINT_32 u4MaxRespBufferLen, OUT PUINT_32 pu4Length) +{ + P_WIFI_EVENT_T prEvent; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + u4Status = halRxWaitResponse(prAdapter, ucPortIdx, pucRspBuffer, u4MaxRespBufferLen, pu4Length); + if (u4Status == WLAN_STATUS_SUCCESS) { + DBGLOG(RX, TRACE, + "Dump Response buffer, length = %u\n", + *pu4Length); + DBGLOG_MEM8(RX, TRACE, pucRspBuffer, *pu4Length); + + prEvent = (P_WIFI_EVENT_T) pucRspBuffer; + DBGLOG(INIT, TRACE, "RX EVENT: ID[0x%02X] SEQ[%u] LEN[%u]\n", + prEvent->ucEID, prEvent->ucSeqNum, prEvent->u2PacketLength); + } else { + DBGLOG(RX, ERROR, "halRxWaitResponse fail!\n"); + } + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Set filter to enable Promiscuous Mode +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxEnablePromiscuousMode(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + +} /* end of nicRxEnablePromiscuousMode() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Set filter to disable Promiscuous Mode +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxDisablePromiscuousMode(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + +} /* end of nicRxDisablePromiscuousMode() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief this function flushes all packets queued in reordering module +* +* @param prAdapter Pointer to the Adapter structure. +* +* @retval WLAN_STATUS_SUCCESS Flushed successfully +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicRxFlush(IN P_ADAPTER_T prAdapter) +{ + P_SW_RFB_T prSwRfb; + + ASSERT(prAdapter); + prSwRfb = qmFlushRxQueues(prAdapter); + if (prSwRfb != NULL) { + do { + P_SW_RFB_T prNextSwRfb; + + /* save next first */ + prNextSwRfb = (P_SW_RFB_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prSwRfb); + + /* free */ + nicRxReturnRFB(prAdapter, prSwRfb); + + prSwRfb = prNextSwRfb; + } while (prSwRfb); + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param +* +* @retval +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicRxProcessActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_WLAN_ACTION_FRAME prActFrame; + P_BSS_INFO_T prBssInfo = NULL; +#if CFG_SUPPORT_802_11W + BOOL fgRobustAction = FALSE; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; +#endif + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + DBGLOG(RSN, TRACE, "[Rx] nicRxProcessActionFrame\n"); + + if (prSwRfb->u2PacketLen < sizeof(WLAN_ACTION_FRAME) - 1) + return WLAN_STATUS_INVALID_PACKET; + prActFrame = (P_WLAN_ACTION_FRAME) prSwRfb->pvHeader; + + DBGLOG(RSN, INFO, "Action frame category=%d\n", prActFrame->ucCategory); + +#if CFG_SUPPORT_802_11W + if ((prActFrame->ucCategory <= CATEGORY_PROTECTED_DUAL_OF_PUBLIC_ACTION && + prActFrame->ucCategory != CATEGORY_PUBLIC_ACTION && + prActFrame->ucCategory != CATEGORY_HT_ACTION) /* At 11W spec Code 7 is reserved */ || + (prActFrame->ucCategory == CATEGORY_VENDOR_SPECIFIC_ACTION_PROTECTED)) { + fgRobustAction = TRUE; + } + /* DBGLOG(RSN, TRACE, ("[Rx] fgRobustAction=%d\n", fgRobustAction)); */ + + if (fgRobustAction && prSwRfb->prStaRec && + GET_BSS_INFO_BY_INDEX(prAdapter, prSwRfb->prStaRec->ucBssIndex)->eNetworkType == NETWORK_TYPE_AIS) { + prAisSpecBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); + + DBGLOG(RSN, INFO, + "[Rx]RobustAction %x %x %x\n", prSwRfb->prRxStatus->u2StatusFlag, + prSwRfb->prRxStatus->ucWlanIdx, prSwRfb->prRxStatus->ucTidSecMode); + + if (prAisSpecBssInfo->fgMgmtProtection && (!(prActFrame->u2FrameCtrl & MASK_FC_PROTECTED_FRAME) + && (HAL_RX_STATUS_GET_SEC_MODE(prSwRfb->prRxStatus) == + CIPHER_SUITE_CCMP))) { + DBGLOG(RSN, INFO, "[MFP] Not handle and drop un-protected robust action frame!!\n"); + return WLAN_STATUS_INVALID_PACKET; + } + } + /* DBGLOG(RSN, INFO, "[Rx] pre check done, handle cateory %d\n", prActFrame->ucCategory); */ +#endif + + if (prSwRfb->prStaRec) + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prSwRfb->prStaRec->ucBssIndex); + + switch (prActFrame->ucCategory) { +#if CFG_M0VE_BA_TO_DRIVER + case CATEGORY_BLOCK_ACK_ACTION: + DBGLOG(RX, WARN, "[Puff][%s] Rx CATEGORY_BLOCK_ACK_ACTION\n", __func__); + + if (prSwRfb->prStaRec) + mqmHandleBaActionFrame(prAdapter, prSwRfb); + + break; +#endif + case CATEGORY_PUBLIC_ACTION: +#if 0 /* CFG_SUPPORT_802_11W */ +/* Sigma */ +#else + if (prAdapter->prGlueInfo && + prAdapter->prGlueInfo->fgIsRegistered && + prAdapter->prAisBssInfo && + prSwRfb->prStaRec && + prSwRfb->prStaRec->ucBssIndex == + prAdapter->prAisBssInfo->ucBssIndex) { + aisFuncValidateRxActionFrame(prAdapter, prSwRfb); + } +#endif + if (prAdapter->prGlueInfo && + prAdapter->prGlueInfo->fgIsRegistered && + prAdapter->prAisBssInfo && + prAdapter->prAisBssInfo->ucBssIndex == + KAL_NETWORK_TYPE_AIS_INDEX) + aisFuncValidateRxActionFrame(prAdapter, prSwRfb); + +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered + && (prAdapter->rP2PNetRegState + == ENUM_NET_REG_STATE_REGISTERED)) { + rlmProcessPublicAction(prAdapter, prSwRfb); + if (prBssInfo) + p2pFuncValidateRxActionFrame(prAdapter, prSwRfb, + (prBssInfo->ucBssIndex == P2P_DEV_BSS_INDEX), (UINT_8) prBssInfo->u4PrivateData); + else + p2pFuncValidateRxActionFrame(prAdapter, prSwRfb, TRUE, 0); + } +#endif + break; + + case CATEGORY_HT_ACTION: + rlmProcessHtAction(prAdapter, prSwRfb); + break; + case CATEGORY_VENDOR_SPECIFIC_ACTION: +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered + && (prAdapter->rP2PNetRegState + == ENUM_NET_REG_STATE_REGISTERED)) { + if (prBssInfo) + p2pFuncValidateRxActionFrame(prAdapter, prSwRfb, + (prBssInfo->ucBssIndex == P2P_DEV_BSS_INDEX), (UINT_8) prBssInfo->u4PrivateData); + else + p2pFuncValidateRxActionFrame(prAdapter, prSwRfb, TRUE, 0); + } +#endif + break; +#if CFG_SUPPORT_802_11W + case CATEGORY_SA_QUERY_ACTION: + { + P_BSS_INFO_T prBssInfo; + + if (prSwRfb->prStaRec) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prSwRfb->prStaRec->ucBssIndex); + ASSERT(prBssInfo); + if ((prBssInfo->eNetworkType == NETWORK_TYPE_AIS) && + prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection /* Use MFP */) { + /* MFP test plan 5.3.3.4 */ + rsnSaQueryAction(prAdapter, prSwRfb); + } else if ((prBssInfo->eNetworkType == NETWORK_TYPE_P2P) && + (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { + /* AP PMF */ + DBGLOG(RSN, INFO, "[Rx] nicRx AP PMF SAQ action\n"); + if (rsnCheckBipKeyInstalled(prAdapter, prSwRfb->prStaRec)) { + /* MFP test plan 4.3.3.4 */ + rsnApSaQueryAction(prAdapter, prSwRfb); + } + } + } + } + break; +#endif +#if CFG_SUPPORT_802_11V + case CATEGORY_WNM_ACTION: + { + wnmWNMAction(prAdapter, prSwRfb); + } + break; +#endif + +#if CFG_SUPPORT_DFS + case CATEGORY_SPEC_MGT: + { + if (prAdapter->fgEnable5GBand) { + DBGLOG(RLM, INFO, "[Channel Switch]nicRxProcessActionFrame\n"); + rlmProcessSpecMgtAction(prAdapter, prSwRfb); + } + } + break; +#endif + +#if CFG_SUPPORT_802_11AC + case CATEGORY_VHT_ACTION: + rlmProcessVhtAction(prAdapter, prSwRfb); + break; +#endif + + default: + break; + } /* end of switch case */ + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param +* +* @retval +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 +nicRxGetRcpiValueFromRxv(IN UINT_8 ucRcpiMode, IN P_SW_RFB_T prSwRfb) +{ + UINT_8 ucRcpi0, ucRcpi1; + UINT_8 ucRcpiValue = 0; + UINT_8 ucRxNum; + + ASSERT(prSwRfb); + + if (ucRcpiMode >= RCPI_MODE_NUM) { + DBGLOG(RX, WARN, "Rcpi Mode = %d is invalid for getting RCPI value from RXV\n", ucRcpiMode); + return 0; + } + + ucRcpi0 = HAL_RX_STATUS_GET_RCPI0(prSwRfb->prRxStatusGroup3); + ucRcpi1 = HAL_RX_STATUS_GET_RCPI1(prSwRfb->prRxStatusGroup3); + ucRxNum = HAL_RX_STATUS_GET_RX_NUM(prSwRfb->prRxStatusGroup3); + + if (ucRxNum == 0) + ucRcpiValue = ucRcpi0; /*0:1R, BBP always report RCPI0 at 1R mode*/ + + else if (ucRxNum == 1) { + switch (ucRcpiMode) { + case RCPI_MODE_WF0: + ucRcpiValue = ucRcpi0; + break; + + case RCPI_MODE_WF1: + ucRcpiValue = ucRcpi1; + break; + + case RCPI_MODE_WF2: + case RCPI_MODE_WF3: + DBGLOG(RX, WARN, "Rcpi Mode = %d is invalid for device with only 2 antenna\n", ucRcpiMode); + break; + + case RCPI_MODE_AVG: /*Not recommended for CBW80+80*/ + ucRcpiValue = (ucRcpi0 + ucRcpi1) / 2; + break; + + case RCPI_MODE_MAX: + ucRcpiValue = (ucRcpi0 > ucRcpi1) ? (ucRcpi0) : (ucRcpi1); + break; + + case RCPI_MODE_MIN: + ucRcpiValue = (ucRcpi0 < ucRcpi1) ? (ucRcpi0) : (ucRcpi1); + break; + + default: + break; + } + } else { + DBGLOG(RX, WARN, "RX_NUM = %d is invalid for getting RCPI value from RXV\n", ucRxNum); + return 0; + } + + return ucRcpiValue; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic_tx.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic_tx.c new file mode 100644 index 0000000000000..a80e18b40e728 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic_tx.c @@ -0,0 +1,3934 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_tx.c#2 +*/ + +/*! \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. +*/ + + +/******************************************************************************* +* C O M P I L E 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 "que_mgt.h" + +#ifdef UDP_SKT_WIFI +#include +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +PFN_TX_DATA_DONE_CB g_pfTxDataDoneCb = nicTxMsduDoneCb; + +static const TX_RESOURCE_CONTROL_T arTcResourceControl[TC_NUM] = { + /* dest port index, dest queue index, HIF TX queue index */ + /* First HW queue */ + {PORT_INDEX_LMAC, MAC_TXQ_AC0_INDEX, HIF_TX_AC0_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC1_INDEX, HIF_TX_AC1_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC2_INDEX, HIF_TX_AC2_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC3_INDEX, HIF_TX_AC3_INDEX}, + {PORT_INDEX_MCU, MCU_Q1_INDEX, HIF_TX_CPU_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC1_INDEX, HIF_TX_AC1_INDEX}, + + /* Second HW queue */ +#if NIC_TX_ENABLE_SECOND_HW_QUEUE + {PORT_INDEX_LMAC, MAC_TXQ_AC10_INDEX, HIF_TX_AC10_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC11_INDEX, HIF_TX_AC11_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC12_INDEX, HIF_TX_AC12_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC13_INDEX, HIF_TX_AC13_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC11_INDEX, HIF_TX_AC11_INDEX}, +#endif +}; + +/* Traffic settings per TC */ +static const TX_TC_TRAFFIC_SETTING_T arTcTrafficSettings[NET_TC_NUM] = { + /* Tx desc template format, Remaining Tx time, Retry count */ + /* For Data frame with StaRec, set Long Format to enable the following settings */ + {NIC_TX_DESC_LONG_FORMAT_LENGTH, NIC_TX_AC_BE_REMAINING_TX_TIME, + NIC_TX_DATA_DEFAULT_RETRY_COUNT_LIMIT}, + {NIC_TX_DESC_LONG_FORMAT_LENGTH, NIC_TX_AC_BK_REMAINING_TX_TIME, + NIC_TX_DATA_DEFAULT_RETRY_COUNT_LIMIT}, + {NIC_TX_DESC_LONG_FORMAT_LENGTH, NIC_TX_AC_VI_REMAINING_TX_TIME, + NIC_TX_DATA_DEFAULT_RETRY_COUNT_LIMIT}, + {NIC_TX_DESC_LONG_FORMAT_LENGTH, NIC_TX_AC_VO_REMAINING_TX_TIME, + NIC_TX_DATA_DEFAULT_RETRY_COUNT_LIMIT}, + + /* MGMT frame */ + {NIC_TX_DESC_LONG_FORMAT_LENGTH, NIC_TX_MGMT_REMAINING_TX_TIME, + NIC_TX_MGMT_DEFAULT_RETRY_COUNT_LIMIT}, + + /* non-StaRec frame (BMC, etc...) */ + {NIC_TX_DESC_LONG_FORMAT_LENGTH, NIC_TX_BMC_REMAINING_TX_TIME, + NIC_TX_DATA_DEFAULT_RETRY_COUNT_LIMIT}, +}; + +/******************************************************************************* +* 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); + + prTxCtrl->pucTxCoalescingBufPtr = prAdapter->pucCoalescingBufCached; + + prTxCtrl->u4WrIdx = 0; + + /* 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; + + /* Assign init value */ + /* Tx sequence number */ + prAdapter->ucTxSeqNum = 0; + /* PID pool */ + for (i = 0; i < WTBL_SIZE; i++) + prAdapter->aucPidPool[i] = NIC_TX_DESC_DRIVER_PID_MIN; + + prTxCtrl->u4PageSize = NIC_TX_PAGE_SIZE; + + /* enable/disable TX resource control */ + prTxCtrl->fgIsTxResourceCtrl = NIC_TX_RESOURCE_CTRL; + + qmInit(prAdapter, halIsTxResourceControlEn(prAdapter)); + + TX_RESET_ALL_CNTS(prTxCtrl); + +} /* end of nicTxInitialize() */ + +BOOLEAN nicTxSanityCheckResource(IN P_ADAPTER_T prAdapter) +{ + P_TX_CTRL_T prTxCtrl; + UINT_8 ucTC; + UINT_32 ucTotalMaxResource = 0; + UINT_32 ucTotalFreeResource = 0; + BOOLEAN fgError = FALSE; + + if (prAdapter->rWifiVar.ucTxDbg & BIT(0)) { + prTxCtrl = &prAdapter->rTxCtrl; + + for (ucTC = TC0_INDEX; ucTC < TC_NUM; ucTC++) { + ucTotalMaxResource += prTxCtrl->rTc.au4MaxNumOfPage[ucTC]; + ucTotalFreeResource += prTxCtrl->rTc.au4FreePageCount[ucTC]; + + if (prTxCtrl->rTc.au4FreePageCount[ucTC] > prTxCtrl->u4TotalPageNum) { + DBGLOG(TX, ERROR, "%s:%u\n error\n", __func__, __LINE__); + fgError = TRUE; + } + + if (prTxCtrl->rTc.au4MaxNumOfPage[ucTC] > prTxCtrl->u4TotalPageNum) { + DBGLOG(TX, ERROR, "%s:%u\n error\n", __func__, __LINE__); + fgError = TRUE; + } + + if (prTxCtrl->rTc.au4FreePageCount[ucTC] > prTxCtrl->rTc.au4MaxNumOfPage[ucTC]) { + DBGLOG(TX, ERROR, "%s:%u\n error\n", __func__, __LINE__); + fgError = TRUE; + } + } + + if (ucTotalMaxResource != prTxCtrl->u4TotalPageNum) { + DBGLOG(TX, ERROR, "%s:%u\n error\n", __func__, __LINE__); + fgError = TRUE; + } + + if (ucTotalMaxResource < ucTotalFreeResource) { + DBGLOG(TX, ERROR, "%s:%u\n error\n", __func__, __LINE__); + fgError = TRUE; + } + + if (ucTotalFreeResource > prTxCtrl->u4TotalPageNum) { + DBGLOG(TX, ERROR, "%s:%u\n error\n", __func__, __LINE__); + fgError = TRUE; + } + + if (fgError) { + DBGLOG(TX, ERROR, "Total resource[%u]\n", prTxCtrl->u4TotalPageNum); + qmDumpQueueStatus(prAdapter, NULL, 0); + } + } + + return !fgError; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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, IN UINT_32 u4PageCount, + IN BOOLEAN fgReqLock) +{ + P_TX_CTRL_T prTxCtrl; + P_TX_TCQ_STATUS_T prTc; + WLAN_STATUS u4Status = WLAN_STATUS_RESOURCES; + + KAL_SPIN_LOCK_DECLARATION(); + + /* enable/disable TX resource control */ + if (!prAdapter->rTxCtrl.fgIsTxResourceCtrl) + return WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + prTc = &prTxCtrl->rTc; + + if (fgReqLock) + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); +#if 1 + if (prTc->au4FreePageCount[ucTC] >= u4PageCount) { + prTc->au4FreePageCount[ucTC] -= u4PageCount; + prTc->au4FreeBufferCount[ucTC] = (prTc->au4FreePageCount[ucTC] / NIC_TX_MAX_PAGE_PER_FRAME); + + DBGLOG(TX, LOUD, "Acquire: TC%d AcquirePageCnt[%u] FreeBufferCnt[%u] FreePageCnt[%u]\n", + ucTC, u4PageCount, prTc->au4FreeBufferCount[ucTC], prTc->au4FreePageCount[ucTC]); + + u4Status = WLAN_STATUS_SUCCESS; + } +#else + if (prTxCtrl->rTc.au4FreePageCount[ucTC] > 0) { + + prTxCtrl->rTc.au4FreePageCount[ucTC] -= 1; + + u4Status = WLAN_STATUS_SUCCESS; + } +#endif + if (fgReqLock) + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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[8];*/ + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + if (ucTC >= TC_NUM) + return WLAN_STATUS_FAILURE; + + if (prTxCtrl->rTc.au4FreeBufferCount[ucTC] > 0) + return WLAN_STATUS_SUCCESS; + + while (i-- > 0) { +#if 1 + u4Status = halTxPollingResource(prAdapter, ucTC); + if (u4Status == WLAN_STATUS_RESOURCES) + kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC); + else + break; +#else + HAL_READ_TX_RELEASED_COUNT(prAdapter, au4WTSR); + + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + break; + } else if (halTxReleaseResource(prAdapter, (PUINT_16) au4WTSR)) { + if (prTxCtrl->rTc.au4FreeBufferCount[ucTC] > 0) { + u4Status = WLAN_STATUS_SUCCESS; + break; + } + kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC); + } else { + kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC); + } +#endif + } + +#if DBG + { + INT_32 i4Times = NIC_TX_RESOURCE_POLLING_TIMEOUT - (i + 1); + + if (i4Times) { + DBGLOG(TX, TRACE, "Polling MCR_WTSR delay %ld times, %ld 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. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN nicTxReleaseResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTc, IN UINT_32 u4PageCount, + IN BOOLEAN fgReqLock) +{ + P_TX_TCQ_STATUS_T prTcqStatus; + BOOLEAN bStatus = FALSE; + + KAL_SPIN_LOCK_DECLARATION(); + + /* enable/disable TX resource control */ + if (!prAdapter->rTxCtrl.fgIsTxResourceCtrl) + return TRUE; + + ASSERT(prAdapter); + prTcqStatus = &prAdapter->rTxCtrl.rTc; + + /* Return free Tc page count */ + if (fgReqLock) + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + prTcqStatus->au4FreePageCount[ucTc] += u4PageCount; + prTcqStatus->au4FreeBufferCount[ucTc] = (prTcqStatus->au4FreePageCount[ucTc] / NIC_TX_MAX_PAGE_PER_FRAME); + + if (fgReqLock) + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + bStatus = TRUE; + + return bStatus; +} /* end of nicTxReleaseResource() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Driver maintain a variable that is synchronous with the usage of individual +* TC Buffer Count. This function will release TC Buffer count for resource +* allocated but un-Tx MSDU_INFO +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicTxReleaseMsduResource(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead) +{ + P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead, prNextMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + while (prMsduInfo) { + prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); + + nicTxReleaseResource(prAdapter, prMsduInfo->ucTC, + nicTxGetPageCount(prMsduInfo->u2FrameLength, FALSE), FALSE); + + prMsduInfo = prNextMsduInfo; + }; + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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; + UINT_8 ucIdx; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicTxResetResource"); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + /* Delta page count */ + kalMemZero(prTxCtrl->rTc.au4TxDonePageCount, sizeof(prTxCtrl->rTc.au4TxDonePageCount)); + kalMemZero(prTxCtrl->rTc.au4PreUsedPageCount, sizeof(prTxCtrl->rTc.au4PreUsedPageCount)); + + prTxCtrl->rTc.ucNextTcIdx = TC0_INDEX; + prTxCtrl->rTc.u4AvaliablePageCount = 0; + + DBGLOG(TX, TRACE, "Default TCQ free resource [%u %u %u %u %u %u]\n", + prAdapter->rWifiVar.au4TcPageCount[TC0_INDEX], + prAdapter->rWifiVar.au4TcPageCount[TC1_INDEX], + prAdapter->rWifiVar.au4TcPageCount[TC2_INDEX], + prAdapter->rWifiVar.au4TcPageCount[TC3_INDEX], + prAdapter->rWifiVar.au4TcPageCount[TC4_INDEX], prAdapter->rWifiVar.au4TcPageCount[TC5_INDEX]); + + prAdapter->rTxCtrl.u4TotalPageNum = 0; + prAdapter->rTxCtrl.u4TotalTxRsvPageNum = 0; + + for (ucIdx = TC0_INDEX; ucIdx < TC_NUM; ucIdx++) { + /* Page Count */ + prTxCtrl->rTc.au4MaxNumOfPage[ucIdx] = prAdapter->rWifiVar.au4TcPageCount[ucIdx]; + prTxCtrl->rTc.au4FreePageCount[ucIdx] = prAdapter->rWifiVar.au4TcPageCount[ucIdx]; + + DBGLOG(TX, TRACE, "Set TC%u Default[%u] Max[%u] Free[%u]\n", + ucIdx, + prAdapter->rWifiVar.au4TcPageCount[ucIdx], + prTxCtrl->rTc.au4MaxNumOfPage[ucIdx], prTxCtrl->rTc.au4FreePageCount[ucIdx]); + + /* Buffer count */ + prTxCtrl->rTc.au4MaxNumOfBuffer[ucIdx] = + (prTxCtrl->rTc.au4MaxNumOfPage[ucIdx] / NIC_TX_MAX_PAGE_PER_FRAME); + prTxCtrl->rTc.au4FreeBufferCount[ucIdx] = + (prTxCtrl->rTc.au4FreePageCount[ucIdx] / NIC_TX_MAX_PAGE_PER_FRAME); + + DBGLOG(TX, TRACE, "Set TC%u Default[%u] Buffer Max[%u] Free[%u]\n", + ucIdx, + prAdapter->rWifiVar.au4TcPageCount[ucIdx], + prTxCtrl->rTc.au4MaxNumOfBuffer[ucIdx], prTxCtrl->rTc.au4FreeBufferCount[ucIdx]); + + prAdapter->rTxCtrl.u4TotalPageNum += prTxCtrl->rTc.au4MaxNumOfPage[ucIdx]; + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + DBGLOG(TX, TRACE, "Reset TCQ free resource to Page:Buf [%u:%u %u:%u %u:%u %u:%u %u:%u %u:%u ]\n", + prTxCtrl->rTc.au4FreePageCount[TC0_INDEX], + prTxCtrl->rTc.au4FreeBufferCount[TC0_INDEX], + prTxCtrl->rTc.au4FreePageCount[TC1_INDEX], + prTxCtrl->rTc.au4FreeBufferCount[TC1_INDEX], + prTxCtrl->rTc.au4FreePageCount[TC2_INDEX], + prTxCtrl->rTc.au4FreeBufferCount[TC2_INDEX], + prTxCtrl->rTc.au4FreePageCount[TC3_INDEX], + prTxCtrl->rTc.au4FreeBufferCount[TC3_INDEX], + prTxCtrl->rTc.au4FreePageCount[TC4_INDEX], + prTxCtrl->rTc.au4FreeBufferCount[TC4_INDEX], + prTxCtrl->rTc.au4FreePageCount[TC5_INDEX], prTxCtrl->rTc.au4FreeBufferCount[TC5_INDEX]); + + DBGLOG(TX, TRACE, "Reset TCQ MAX resource to Page:Buf [%u:%u %u:%u %u:%u %u:%u %u:%u %u:%u]\n", + prTxCtrl->rTc.au4MaxNumOfPage[TC0_INDEX], + prTxCtrl->rTc.au4MaxNumOfBuffer[TC0_INDEX], + prTxCtrl->rTc.au4MaxNumOfPage[TC1_INDEX], + prTxCtrl->rTc.au4MaxNumOfBuffer[TC1_INDEX], + prTxCtrl->rTc.au4MaxNumOfPage[TC2_INDEX], + prTxCtrl->rTc.au4MaxNumOfBuffer[TC2_INDEX], + prTxCtrl->rTc.au4MaxNumOfPage[TC3_INDEX], + prTxCtrl->rTc.au4MaxNumOfBuffer[TC3_INDEX], + prTxCtrl->rTc.au4MaxNumOfPage[TC4_INDEX], + prTxCtrl->rTc.au4MaxNumOfBuffer[TC4_INDEX], + prTxCtrl->rTc.au4MaxNumOfPage[TC5_INDEX], prTxCtrl->rTc.au4MaxNumOfBuffer[TC5_INDEX]); + + return WLAN_STATUS_SUCCESS; +} + + +#if QM_FAST_TC_RESOURCE_CTRL +UINT_32 +nicTxGetAdjustableResourceCnt(IN P_ADAPTER_T prAdapter) +{ + P_TX_CTRL_T prTxCtrl; + UINT_8 ucIdx; + UINT_32 u4TotAdjCnt = 0; + UINT_32 u4AdjCnt; + P_QUE_MGT_T prQm = NULL; + + prQm = &prAdapter->rQM; + prTxCtrl = &prAdapter->rTxCtrl; + + for (ucIdx = TC0_INDEX; ucIdx < TC_NUM; ucIdx++) { + if (ucIdx == TC4_INDEX) + continue; + + if (prTxCtrl->rTc.au4FreeBufferCount[ucIdx] > prQm->au4MinReservedTcResource[ucIdx]) + u4AdjCnt = prTxCtrl->rTc.au4FreeBufferCount[ucIdx] - prQm->au4MinReservedTcResource[ucIdx]; + else + u4AdjCnt = 0; + + u4TotAdjCnt += u4AdjCnt; + } + + return u4TotAdjCnt; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @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_16 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.au4FreePageCount[ucTC]; +} + +UINT_8 nicTxGetFrameResourceType(IN UINT_8 eFrameType, IN P_MSDU_INFO_T prMsduInfo) +{ + UINT_8 ucTC; + + switch (eFrameType) { + case FRAME_TYPE_802_1X: + ucTC = TC4_INDEX; + break; + + case FRAME_TYPE_MMPDU: + if (prMsduInfo) + ucTC = prMsduInfo->ucTC; + else + ucTC = TC4_INDEX; + break; + + default: + DBGLOG(INIT, WARN, "Undefined Frame Type(%u)\n", eFrameType); + ucTC = TC4_INDEX; + break; + } + + return ucTC; +} + +UINT_8 nicTxGetCmdResourceType(IN P_CMD_INFO_T prCmdInfo) +{ + UINT_8 ucTC; + + switch (prCmdInfo->eCmdType) { + case COMMAND_TYPE_NETWORK_IOCTL: + case COMMAND_TYPE_GENERAL_IOCTL: + ucTC = TC4_INDEX; + break; + + case COMMAND_TYPE_SECURITY_FRAME: + ucTC = nicTxGetFrameResourceType(FRAME_TYPE_802_1X, NULL); + break; + + case COMMAND_TYPE_MANAGEMENT_FRAME: + ucTC = nicTxGetFrameResourceType(FRAME_TYPE_MMPDU, prCmdInfo->prMsduInfo); + break; + + default: + DBGLOG(INIT, WARN, "Undefined CMD Type(%u)\n", prCmdInfo->eCmdType); + ucTC = TC4_INDEX; + break; + } + + return ucTC; +} + +UINT_8 nicTxGetTxQByTc(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTc) +{ + return arTcResourceControl[ucTc].ucHifTxQIndex; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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; + P_QUE_T prDataPort0, prDataPort1; + WLAN_STATUS status; + + ASSERT(prAdapter); + ASSERT(prMsduInfoListHead); + + prMsduInfo = prMsduInfoListHead; + + prDataPort0 = &qDataPort0; + prDataPort1 = &qDataPort1; + + QUEUE_INITIALIZE(prDataPort0); + QUEUE_INITIALIZE(prDataPort1); + + /* 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); + + 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(prDataPort0, (P_QUE_ENTRY_T) prMsduInfo); + status = nicTxAcquireResource(prAdapter, prMsduInfo->ucTC, + nicTxGetPageCount(prMsduInfo->u2FrameLength, FALSE), TRUE); + ASSERT(status == WLAN_STATUS_SUCCESS); + + break; + + case TC4_INDEX: /* Management packets */ + QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo) = NULL; + QUEUE_INSERT_TAIL(prDataPort1, (P_QUE_ENTRY_T) prMsduInfo); + + status = nicTxAcquireResource(prAdapter, prMsduInfo->ucTC, + nicTxGetPageCount(prMsduInfo->u2FrameLength, FALSE), TRUE); + ASSERT(status == WLAN_STATUS_SUCCESS); + + break; + + default: + ASSERT(0); + break; + } + + prMsduInfo = prNextMsduInfo; + } + + if (prDataPort0->u4NumElem > 0) + nicTxMsduQueue(prAdapter, 0, prDataPort0); + + if (prDataPort1->u4NumElem > 0) + nicTxMsduQueue(prAdapter, 1, prDataPort1); + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_SUPPORT_MULTITHREAD +/*----------------------------------------------------------------------------*/ +/*! +* @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 nicTxMsduInfoListMthread(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead) +{ +#if CFG_FIX_2_TX_PORT + P_MSDU_INFO_T prMsduInfo, prNextMsduInfo; + QUE_T qDataPort0, qDataPort1; + P_QUE_T prDataPort0, prDataPort1; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prMsduInfoListHead); + + prMsduInfo = prMsduInfoListHead; + + prDataPort0 = &qDataPort0; + prDataPort1 = &qDataPort1; + + QUEUE_INITIALIZE(prDataPort0); + QUEUE_INITIALIZE(prDataPort1); + + /* 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); + + 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(prDataPort0, (P_QUE_ENTRY_T) prMsduInfo); + break; + + case TC4_INDEX: /* Management packets */ + QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo) = NULL; + QUEUE_INSERT_TAIL(prDataPort1, (P_QUE_ENTRY_T) prMsduInfo); + break; + + default: + ASSERT(0); + break; + } + + nicTxFillDataDesc(prAdapter, prMsduInfo); + + prMsduInfo = prNextMsduInfo; + } + + if (prDataPort0->u4NumElem > 0 || prDataPort1->u4NumElem > 0) { + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + QUEUE_CONCATENATE_QUEUES((&(prAdapter->rTxP0Queue)), (prDataPort0)); + QUEUE_CONCATENATE_QUEUES((&(prAdapter->rTxP1Queue)), (prDataPort1)); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + + kalSetTxEvent2Hif(prAdapter->prGlueInfo); + } +#else + + P_MSDU_INFO_T prMsduInfo, prNextMsduInfo; + QUE_T qDataPort[TX_PORT_NUM]; + P_QUE_T prDataPort[TX_PORT_NUM]; + INT_32 i; + BOOLEAN fgSetTx2Hif = FALSE; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prMsduInfoListHead); + + prMsduInfo = prMsduInfoListHead; + + for (i = 0; i < TX_PORT_NUM; i++) { + prDataPort[i] = &qDataPort[i]; + QUEUE_INITIALIZE(prDataPort[i]); + } + + /* Separate MSDU_INFO_T lists into 2 categories: for Port#0 & Port#1 */ + while (prMsduInfo) { + + fgSetTx2Hif = TRUE; + prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); + + if (prMsduInfo->ucWmmQueSet != DBDC_5G_WMM_INDEX) { + QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo) = NULL; + QUEUE_INSERT_TAIL(prDataPort[TX_2G_WMM_PORT_NUM], (P_QUE_ENTRY_T) prMsduInfo); + } else { + if (prMsduInfo->ucTC >= 0 && + prMsduInfo->ucTC < TC_NUM) { + QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo) = NULL; + QUEUE_INSERT_TAIL(prDataPort[prMsduInfo->ucTC], (P_QUE_ENTRY_T) prMsduInfo); + } else + ASSERT(0); + } + nicTxFillDataDesc(prAdapter, prMsduInfo); + + prMsduInfo = prNextMsduInfo; + } + + if (fgSetTx2Hif) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + for (i = 0; i < TX_PORT_NUM; i++) + QUEUE_CONCATENATE_QUEUES((&(prAdapter->rTxPQueue[i])), (prDataPort[i])); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + kalSetTxEvent2Hif(prAdapter->prGlueInfo); + } + +#endif + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief In this function, we'll write frame(PACKET_INFO_T) into HIF when apply multithread. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @retval WLAN_STATUS_SUCCESS Bus access ok. +* @retval WLAN_STATUS_FAILURE Bus access fail. +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 nicTxMsduQueueMthread(IN P_ADAPTER_T prAdapter) +{ +#if CFG_FIX_2_TX_PORT + QUE_T qDataPort0, qDataPort1; + P_QUE_T prDataPort0, prDataPort1; + UINT_32 u4TxLoopCount; + + KAL_SPIN_LOCK_DECLARATION(); + + prDataPort0 = &qDataPort0; + prDataPort1 = &qDataPort1; + + QUEUE_INITIALIZE(prDataPort0); + QUEUE_INITIALIZE(prDataPort1); + + u4TxLoopCount = prAdapter->rWifiVar.u4HifTxloopCount; + + while (u4TxLoopCount--) { + while (QUEUE_IS_NOT_EMPTY(&(prAdapter->rTxP0Queue))) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + QUEUE_MOVE_ALL(prDataPort0, &(prAdapter->rTxP0Queue)); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + + nicTxMsduQueue(prAdapter, 0, prDataPort0); + + if (QUEUE_IS_NOT_EMPTY(prDataPort0)) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(&(prAdapter->rTxP0Queue), prDataPort0); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + + break; + } + } + + while (QUEUE_IS_NOT_EMPTY(&(prAdapter->rTxP1Queue))) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + QUEUE_MOVE_ALL(prDataPort1, &(prAdapter->rTxP1Queue)); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + + nicTxMsduQueue(prAdapter, 1, prDataPort1); + + if (QUEUE_IS_NOT_EMPTY(prDataPort1)) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(&(prAdapter->rTxP1Queue), prDataPort1); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + + break; + } + } + } +#else + + UINT_32 u4TxLoopCount; + QUE_T qDataPort[TX_PORT_NUM]; + P_QUE_T prDataPort[TX_PORT_NUM]; + INT_32 i; + + KAL_SPIN_LOCK_DECLARATION(); + + for (i = 0; i < TX_PORT_NUM; i++) { + prDataPort[i] = &qDataPort[i]; + QUEUE_INITIALIZE(prDataPort[i]); + } + + u4TxLoopCount = prAdapter->rWifiVar.u4HifTxloopCount; + + while (u4TxLoopCount--) { + for (i = TC_NUM; i >= 0; i--) { + while (QUEUE_IS_NOT_EMPTY(&(prAdapter->rTxPQueue[i]))) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + QUEUE_MOVE_ALL(prDataPort[i], &(prAdapter->rTxPQueue[i])); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + + nicTxMsduQueue(prAdapter, 0, prDataPort[i]); + + if (QUEUE_IS_NOT_EMPTY(prDataPort[i])) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(&(prAdapter->rTxPQueue[i]), prDataPort[i]); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); + + break; + } + } + } + } +#endif + return WLAN_STATUS_SUCCESS; +} + +UINT_32 nicTxGetMsduPendingCnt(IN P_ADAPTER_T prAdapter) +{ +#if CFG_FIX_2_TX_PORT + return prAdapter->rTxP0Queue.u4NumElem + prAdapter->rTxP1Queue.u4NumElem; +#else + INT_32 i; + UINT_32 retValue = 0; + + for (i = 0; i < TX_PORT_NUM; i++) + retValue += prAdapter->rTxPQueue[i].u4NumElem; + return retValue; +#endif +} + +#endif + +VOID nicTxComposeDescAppend(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, + OUT PUINT_8 prTxDescBuffer) +{ + P_HW_MAC_TX_DESC_APPEND_T prHwTxDescAppend; + + /* Fill TxD append */ + prHwTxDescAppend = (P_HW_MAC_TX_DESC_APPEND_T)prTxDescBuffer; + kalMemZero(prHwTxDescAppend, HW_MAC_TX_DESC_APPEND_T_LENGTH); + prHwTxDescAppend->u2PktFlags = HIT_PKT_FLAGS_CT_WITH_TXD; + prHwTxDescAppend->ucBssIndex = prMsduInfo->ucBssIndex; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief In this function, we'll compose the Tx descriptor of the MSDU. +* +* @param prAdapter Pointer to the Adapter structure. +* @param prMsduInfo Pointer to the Msdu info +* @param prTxDesc Pointer to the Tx descriptor buffer +* +* @retval VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicTxComposeDesc(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, + IN UINT_32 u4TxDescLength, IN BOOLEAN fgIsTemplate, OUT PUINT_8 prTxDescBuffer) +{ + P_HW_MAC_TX_DESC_T prTxDesc; + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prBssInfo; + UINT_8 ucEtherTypeOffsetInWord; + UINT_32 u4TxDescAndPaddingLength; + UINT_8 ucTarPort, ucTarQueue; +#if ((CFG_SISO_SW_DEVELOP == 1) || (CFG_SUPPORT_ANT_SELECT == 1)) + enum ENUM_WF_PATH_FAVOR_T eWfPathFavor; +#endif + + prTxDesc = (P_HW_MAC_TX_DESC_T) prTxDescBuffer; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + u4TxDescAndPaddingLength = u4TxDescLength + NIC_TX_DESC_PADDING_LENGTH; + + kalMemZero(prTxDesc, u4TxDescAndPaddingLength); + + /* Move to nicTxFillDesc */ + /* Tx byte count */ + /* HAL_MAC_TX_DESC_SET_TX_BYTE_COUNT(prTxDesc, ucTxDescAndPaddingLength + prMsduInfo->u2FrameLength); */ + + /* Ether-type offset */ + if (prMsduInfo->fgIs802_11) { + ucEtherTypeOffsetInWord = + (NIC_TX_PSE_HEADER_LENGTH + prMsduInfo->ucMacHeaderLength + prMsduInfo->ucLlcLength) >> 1; + } else { + ucEtherTypeOffsetInWord = ((ETHER_HEADER_LEN - ETHER_TYPE_LEN) + NIC_TX_PSE_HEADER_LENGTH) >> 1; + } + HAL_MAC_TX_DESC_SET_ETHER_TYPE_OFFSET(prTxDesc, ucEtherTypeOffsetInWord); + + /* Port index / queue index */ + ucTarPort = arTcResourceControl[prMsduInfo->ucTC].ucDestPortIndex; + HAL_MAC_TX_DESC_SET_PORT_INDEX(prTxDesc, ucTarPort); + + ucTarQueue = arTcResourceControl[prMsduInfo->ucTC].ucDestQueueIndex; + if (ucTarPort == PORT_INDEX_LMAC) + ucTarQueue += (prBssInfo->ucWmmQueSet * WMM_AC_INDEX_NUM); + + HAL_MAC_TX_DESC_SET_QUEUE_INDEX(prTxDesc, ucTarQueue); + + /* BMC packet */ + if (prMsduInfo->ucStaRecIndex == STA_REC_INDEX_BMCAST) { + HAL_MAC_TX_DESC_SET_BMC(prTxDesc); + + /* Must set No ACK to mask retry bit in FC */ + HAL_MAC_TX_DESC_SET_NO_ACK(prTxDesc); + } + /* WLAN index */ + prMsduInfo->ucWlanIndex = nicTxGetWlanIdx(prAdapter, prMsduInfo->ucBssIndex, prMsduInfo->ucStaRecIndex); + +#if 0 /* DBG */ + DBGLOG(RSN, INFO, + "Tx WlanIndex = %d eAuthMode = %d\n", prMsduInfo->ucWlanIndex, + prAdapter->rWifiVar.rConnSettings.eAuthMode); +#endif + HAL_MAC_TX_DESC_SET_WLAN_INDEX(prTxDesc, prMsduInfo->ucWlanIndex); + + /* Header format */ + if (prMsduInfo->fgIs802_11) { + HAL_MAC_TX_DESC_SET_HEADER_FORMAT(prTxDesc, HEADER_FORMAT_802_11_NORMAL_MODE); + HAL_MAC_TX_DESC_SET_802_11_HEADER_LENGTH(prTxDesc, (prMsduInfo->ucMacHeaderLength >> 1)); + } else { + HAL_MAC_TX_DESC_SET_HEADER_FORMAT(prTxDesc, HEADER_FORMAT_NON_802_11); + HAL_MAC_TX_DESC_SET_ETHERNET_II(prTxDesc); + } + + /* Header Padding */ + HAL_MAC_TX_DESC_SET_HEADER_PADDING(prTxDesc, NIC_TX_DESC_HEADER_PADDING_LENGTH); + + /* TID */ + HAL_MAC_TX_DESC_SET_TID(prTxDesc, prMsduInfo->ucUserPriority); + + /* Protection */ + if (secIsProtectedFrame(prAdapter, prMsduInfo, prStaRec)) { + /* Update Packet option, PF bit will be set in nicTxFillDescByPktOption() */ + if ((prStaRec && prStaRec->fgTransmitKeyExist) || fgIsTemplate) { + nicTxConfigPktOption(prMsduInfo, MSDU_OPT_PROTECTED_FRAME, TRUE); + + if (prMsduInfo->fgIs802_1x_NonProtected) { + nicTxConfigPktOption(prMsduInfo, MSDU_OPT_PROTECTED_FRAME, FALSE); + DBGLOG(RSN, LOUD, "Pairwise EAPoL not protect!\n"); + } + } else if (prMsduInfo->ucStaRecIndex == STA_REC_INDEX_BMCAST) {/* BMC packet */ + nicTxConfigPktOption(prMsduInfo, MSDU_OPT_PROTECTED_FRAME, TRUE); + DBGLOG(RSN, LOUD, "Protect BMC frame!\n"); + } + } +#if (UNIFIED_MAC_TX_FORMAT == 1) + /* Packet Format */ + if (prMsduInfo->eSrc == TX_PACKET_MGMT) + HAL_MAC_TX_DESC_SET_PKT_FORMAT(prTxDesc, TXD_PKT_FORMAT_COMMAND); + +#endif + + /* Own MAC */ + HAL_MAC_TX_DESC_SET_OWN_MAC_INDEX(prTxDesc, prBssInfo->ucOwnMacIndex); + + if (u4TxDescLength == NIC_TX_DESC_SHORT_FORMAT_LENGTH) { + HAL_MAC_TX_DESC_SET_SHORT_FORMAT(prTxDesc); + + /* Update Packet option */ + nicTxFillDescByPktOption(prMsduInfo, prTxDesc); + + /* Short format, Skip DW 2~6 */ + return; + } + HAL_MAC_TX_DESC_SET_LONG_FORMAT(prTxDesc); + + /* Update Packet option */ + nicTxFillDescByPktOption(prMsduInfo, prTxDesc); + + nicTxFillDescByPktControl(prMsduInfo, prTxDesc); + + /* Type */ + if (prMsduInfo->fgIs802_11) { + P_WLAN_MAC_HEADER_T prWlanHeader = + (P_WLAN_MAC_HEADER_T) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + HAL_MAC_TX_DESC_SET_TYPE(prTxDesc, (prWlanHeader->u2FrameCtrl & MASK_FC_TYPE) >> 2); + HAL_MAC_TX_DESC_SET_SUB_TYPE(prTxDesc, + (prWlanHeader->u2FrameCtrl & MASK_FC_SUBTYPE) >> OFFSET_OF_FC_SUBTYPE); + } + /* PID */ + if (prMsduInfo->pfTxDoneHandler) { + prMsduInfo->ucPID = nicTxAssignPID(prAdapter, prMsduInfo->ucWlanIndex); + HAL_MAC_TX_DESC_SET_PID(prTxDesc, prMsduInfo->ucPID); + HAL_MAC_TX_DESC_SET_TXS_TO_MCU(prTxDesc); + } else if (prAdapter->rWifiVar.ucDataTxDone == 2) { + /* Log mode: only TxS to FW, no event to driver */ + HAL_MAC_TX_DESC_SET_PID(prTxDesc, NIC_TX_DESC_PID_RESERVED); + HAL_MAC_TX_DESC_SET_TXS_TO_MCU(prTxDesc); + } + + /* Remaining TX time */ + if (!(prMsduInfo->u4Option & MSDU_OPT_MANUAL_LIFE_TIME)) + prMsduInfo->u4RemainingLifetime = arTcTrafficSettings[prMsduInfo->ucTC].u4RemainingTxTime; + HAL_MAC_TX_DESC_SET_REMAINING_LIFE_TIME_IN_MS(prTxDesc, prMsduInfo->u4RemainingLifetime); + + /* Tx count limit */ + if (!(prMsduInfo->u4Option & MSDU_OPT_MANUAL_RETRY_LIMIT)) { + /* Note: BMC packet retry limit is set to unlimited */ + prMsduInfo->ucRetryLimit = arTcTrafficSettings[prMsduInfo->ucTC].ucTxCountLimit; + } + HAL_MAC_TX_DESC_SET_REMAINING_TX_COUNT(prTxDesc, prMsduInfo->ucRetryLimit); + + /* Power Offset */ + HAL_MAC_TX_DESC_SET_POWER_OFFSET(prTxDesc, prMsduInfo->cPowerOffset); + + /* Fix rate */ + switch (prMsduInfo->ucRateMode) { + case MSDU_RATE_MODE_MANUAL_DESC: + HAL_MAC_TX_DESC_SET_DW(prTxDesc, 6, 1, &prMsduInfo->u4FixedRateOption); +#if ((CFG_SISO_SW_DEVELOP == 1) || (CFG_SUPPORT_ANT_SELECT == 1)) + /* Update spatial extension index setting */ + eWfPathFavor = wlanGetAntPathType(prAdapter, ENUM_WF_NON_FAVOR); + HAL_MAC_TX_DESC_SET_SPE_IDX(prTxDesc, wlanGetSpeIdx(prAdapter, prBssInfo->ucBssIndex, eWfPathFavor)); +#endif + HAL_MAC_TX_DESC_SET_FIXED_RATE_MODE_TO_DESC(prTxDesc); + HAL_MAC_TX_DESC_SET_FIXED_RATE_ENABLE(prTxDesc); + break; + + case MSDU_RATE_MODE_MANUAL_CR: + +#if ((CFG_SISO_SW_DEVELOP == 1) || (CFG_SUPPORT_ANT_SELECT == 1)) + /* Update spatial extension index setting */ + eWfPathFavor = wlanGetAntPathType(prAdapter, ENUM_WF_NON_FAVOR); + HAL_MAC_TX_DESC_SET_SPE_IDX(prTxDesc, wlanGetSpeIdx(prAdapter, prBssInfo->ucBssIndex, eWfPathFavor)); +#endif + HAL_MAC_TX_DESC_SET_FIXED_RATE_MODE_TO_CR(prTxDesc); + HAL_MAC_TX_DESC_SET_FIXED_RATE_ENABLE(prTxDesc); + break; + + case MSDU_RATE_MODE_AUTO: + default: + break; + } + +} + +VOID +nicTxComposeSecurityFrameDesc(IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, OUT PUINT_8 prTxDescBuffer, OUT PUINT_8 pucTxDescLength) +{ + P_HW_MAC_TX_DESC_T prTxDesc = (P_HW_MAC_TX_DESC_T) prTxDescBuffer; + UINT_8 ucTxDescAndPaddingLength = NIC_TX_DESC_LONG_FORMAT_LENGTH + NIC_TX_DESC_PADDING_LENGTH; + /* P_STA_RECORD_T prStaRec = cnmGetStaRecByIndex(prAdapter, prCmdInfo->ucStaRecIndex); */ + P_BSS_INFO_T prBssInfo; + UINT_8 ucTid = 0; + UINT_8 ucTempTC = TC4_INDEX; + P_NATIVE_PACKET prNativePacket; + UINT_8 ucEtherTypeOffsetInWord; + P_MSDU_INFO_T prMsduInfo; + + prMsduInfo = prCmdInfo->prMsduInfo; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + prNativePacket = prMsduInfo->prPacket; + + ASSERT(prNativePacket); + + kalMemZero(prTxDesc, ucTxDescAndPaddingLength); + + /* WLAN index */ + prMsduInfo->ucWlanIndex = nicTxGetWlanIdx(prAdapter, prMsduInfo->ucBssIndex, prMsduInfo->ucStaRecIndex); + + /* UC to a connected peer */ + HAL_MAC_TX_DESC_SET_WLAN_INDEX(prTxDesc, prMsduInfo->ucWlanIndex); + /* Redirect Security frame to TID0 */ + /* ucTempTC = arNetwork2TcResource[prStaRec->ucBssIndex][aucTid2ACI[ucTid]]; */ + + /* Tx byte count */ + HAL_MAC_TX_DESC_SET_TX_BYTE_COUNT(prTxDesc, ucTxDescAndPaddingLength + prCmdInfo->u2InfoBufLen); + + /* Ether-type offset */ + ucEtherTypeOffsetInWord = ((ETHER_HEADER_LEN - ETHER_TYPE_LEN) + NIC_TX_PSE_HEADER_LENGTH) >> 1; + HAL_MAC_TX_DESC_SET_ETHER_TYPE_OFFSET(prTxDesc, ucEtherTypeOffsetInWord); + + /* Port index / queue index */ + HAL_MAC_TX_DESC_SET_PORT_INDEX(prTxDesc, arTcResourceControl[ucTempTC].ucDestPortIndex); + HAL_MAC_TX_DESC_SET_QUEUE_INDEX(prTxDesc, arTcResourceControl[ucTempTC].ucDestQueueIndex); + + /* Header format */ + HAL_MAC_TX_DESC_SET_HEADER_FORMAT(prTxDesc, HEADER_FORMAT_NON_802_11); + + /* Long Format */ + HAL_MAC_TX_DESC_SET_LONG_FORMAT(prTxDesc); + + /* Update Packet option */ + nicTxFillDescByPktOption(prMsduInfo, prTxDesc); + + if (!GLUE_TEST_PKT_FLAG(prNativePacket, ENUM_PKT_802_3)) { + /* Set EthernetII */ + HAL_MAC_TX_DESC_SET_ETHERNET_II(prTxDesc); + } + /* Header Padding */ + HAL_MAC_TX_DESC_SET_HEADER_PADDING(prTxDesc, NIC_TX_DESC_HEADER_PADDING_LENGTH); + + /* TID */ + HAL_MAC_TX_DESC_SET_TID(prTxDesc, ucTid); + + /* Remaining TX time */ + HAL_MAC_TX_DESC_SET_REMAINING_LIFE_TIME_IN_MS(prTxDesc, arTcTrafficSettings[ucTempTC].u4RemainingTxTime); + + /* Tx count limit */ + HAL_MAC_TX_DESC_SET_REMAINING_TX_COUNT(prTxDesc, arTcTrafficSettings[ucTempTC].ucTxCountLimit); + + /* Set lowest BSS basic rate */ + HAL_MAC_TX_DESC_SET_FR_RATE(prTxDesc, prBssInfo->u2HwDefaultFixedRateCode); + HAL_MAC_TX_DESC_SET_FIXED_RATE_MODE_TO_DESC(prTxDesc); + HAL_MAC_TX_DESC_SET_FIXED_RATE_ENABLE(prTxDesc); + + /* Packet Format */ + HAL_MAC_TX_DESC_SET_PKT_FORMAT(prTxDesc, TXD_PKT_FORMAT_COMMAND); + + /* Own MAC */ + HAL_MAC_TX_DESC_SET_OWN_MAC_INDEX(prTxDesc, prBssInfo->ucOwnMacIndex); + + /* PID */ + if (prMsduInfo->pfTxDoneHandler) { + prMsduInfo->ucPID = nicTxAssignPID(prAdapter, prMsduInfo->ucWlanIndex); + HAL_MAC_TX_DESC_SET_PID(prTxDesc, prMsduInfo->ucPID); + HAL_MAC_TX_DESC_SET_TXS_TO_MCU(prTxDesc); + } + + if (pucTxDescLength) + *pucTxDescLength = ucTxDescAndPaddingLength; +} + +BOOLEAN nicTxIsTXDTemplateAllowed(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN P_STA_RECORD_T prStaRec) +{ + if (prMsduInfo->fgIsTXDTemplateValid) { + if (prMsduInfo->fgIs802_1x) + return FALSE; + + if (prMsduInfo->ucRateMode != MSDU_RATE_MODE_AUTO) + return FALSE; + + if (!prStaRec) + return FALSE; + + if (prMsduInfo->ucControlFlag) + return FALSE; + + if (prMsduInfo->pfTxDoneHandler) + return FALSE; + + if (prAdapter->rWifiVar.ucDataTxRateMode) + return FALSE; + + return TRUE; + } + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief In this function, we'll compose the Tx descriptor of the MSDU. +* +* @param prAdapter Pointer to the Adapter structure. +* @param prMsduInfo Pointer to the Msdu info +* @param prTxDesc Pointer to the Tx descriptor buffer +* +* @retval VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicTxFillDesc(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, + OUT PUINT_8 prTxDescBuffer, OUT PUINT_32 pu4TxDescLength) +{ + P_HW_MAC_TX_DESC_T prTxDesc = (P_HW_MAC_TX_DESC_T) prTxDescBuffer; + P_HW_MAC_TX_DESC_T prTxDescTemplate = NULL; + P_STA_RECORD_T prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + UINT_32 u4TxDescLength, u4TxDescAppendLength; +#if CFG_TCP_IP_CHKSUM_OFFLOAD + UINT_8 ucChksumFlag = 0; +#endif + + /* This is to lock the process to preventing */ + /* nicTxFreeDescTemplate while Filling it */ + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_DESC); + +/* +*------------------------------------------------------------------------------ +* Fill up common fileds +*------------------------------------------------------------------------------ +*/ + /* Decide TxD append length */ + if (prMsduInfo->ucPacketType == TX_PACKET_TYPE_DATA) + u4TxDescAppendLength = HW_MAC_TX_DESC_APPEND_T_LENGTH; + else + u4TxDescAppendLength = 0; + + /* Get TXD from pre-allocated template */ + if (nicTxIsTXDTemplateAllowed(prAdapter, prMsduInfo, prStaRec) && + prStaRec->aprTxDescTemplate[prMsduInfo->ucUserPriority]) { + prTxDescTemplate = prStaRec->aprTxDescTemplate[prMsduInfo->ucUserPriority]; +#if 1 + u4TxDescLength = NIC_TX_DESC_LONG_FORMAT_LENGTH; +#else + if (HAL_MAC_TX_DESC_IS_LONG_FORMAT(prTxDescTemplate)) + u4TxDescLength = NIC_TX_DESC_LONG_FORMAT_LENGTH; + else + u4TxDescLength = NIC_TX_DESC_SHORT_FORMAT_LENGTH; +#endif + + kalMemCopy(prTxDesc, prTxDescTemplate, u4TxDescLength + u4TxDescAppendLength); + + /* Overwrite fields for EOSP or More data */ + nicTxFillDescByPktOption(prMsduInfo, prTxDesc); + } + /* Compose TXD by Msdu info */ + else { + u4TxDescLength = NIC_TX_DESC_LONG_FORMAT_LENGTH; + nicTxComposeDesc(prAdapter, prMsduInfo, u4TxDescLength, FALSE, prTxDescBuffer); + + /* Compose TxD append */ + if (prMsduInfo->ucPacketType == TX_PACKET_TYPE_DATA) + nicTxComposeDescAppend(prAdapter, prMsduInfo, prTxDescBuffer + u4TxDescLength); + } + +/* +*------------------------------------------------------------------------------ +* Fill up remaining parts, per-packet variant fields +*------------------------------------------------------------------------------ +*/ + /* Calculate Tx byte count */ + HAL_MAC_TX_DESC_SET_TX_BYTE_COUNT(prTxDesc, u4TxDescLength + u4TxDescAppendLength + prMsduInfo->u2FrameLength); + + /* Checksum offload */ +#if CFG_TCP_IP_CHKSUM_OFFLOAD + if (prAdapter->fgIsSupportCsumOffload && prMsduInfo->eSrc == TX_PACKET_OS) { + if (prAdapter->u4CSUMFlags & + (CSUM_OFFLOAD_EN_TX_TCP | CSUM_OFFLOAD_EN_TX_UDP | CSUM_OFFLOAD_EN_TX_IP)) { + ASSERT(prMsduInfo->prPacket); + kalQueryTxChksumOffloadParam(prMsduInfo->prPacket, &ucChksumFlag); + if ((ucChksumFlag & TX_CS_IP_GEN)) + HAL_MAC_TX_DESC_SET_IP_CHKSUM(prTxDesc); + if ((ucChksumFlag & TX_CS_TCP_UDP_GEN)) + HAL_MAC_TX_DESC_SET_TCP_UDP_CHKSUM(prTxDesc); + } + } +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + /* Set EtherType & VLAN for non 802.11 frame */ + if (!prMsduInfo->fgIs802_11) { + if (prMsduInfo->fgIs802_3) + HAL_MAC_TX_DESC_UNSET_ETHERNET_II(prTxDesc); + if (prMsduInfo->fgIsVlanExists) + HAL_MAC_TX_DESC_SET_VLAN(prTxDesc); + } + + if (pu4TxDescLength) + *pu4TxDescLength = u4TxDescLength; + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_DESC); +} + +VOID +nicTxFillDataDesc(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + PUINT_8 pucOutputBuf; + + pucOutputBuf = skb_push((struct sk_buff *)prMsduInfo->prPacket, NIC_TX_HEAD_ROOM); + + nicTxFillDesc(prAdapter, prMsduInfo, pucOutputBuf, NULL); +} + +VOID +nicTxCopyDesc(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucTarTxDesc, IN PUINT_8 pucSrcTxDesc, OUT PUINT_8 pucTxDescLength) +{ + UINT_8 ucTxDescLength; + + if (HAL_MAC_TX_DESC_IS_LONG_FORMAT((P_HW_MAC_TX_DESC_T) pucSrcTxDesc)) + ucTxDescLength = NIC_TX_DESC_LONG_FORMAT_LENGTH; + else + ucTxDescLength = NIC_TX_DESC_SHORT_FORMAT_LENGTH; + + kalMemCopy(pucTarTxDesc, pucSrcTxDesc, ucTxDescLength); + + if (pucTxDescLength) + *pucTxDescLength = ucTxDescLength; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief In this function, we'll generate Tx descriptor template for each TID. +* +* @param prAdapter Pointer to the Adapter structure. +* @param prStaRec Pointer to the StaRec structure. +* +* @retval VOID +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicTxGenerateDescTemplate(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + UINT_8 ucTid; + UINT_8 ucTc; + UINT_32 u4TxDescSize, u4TxDescAppendSize; + P_HW_MAC_TX_DESC_T prTxDesc; + P_MSDU_INFO_T prMsduInfo; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + + /* Free previous template, first */ + /* nicTxFreeDescTemplate(prAdapter, prStaRec); */ + for (ucTid = 0; ucTid < TX_DESC_TID_NUM; ucTid++) + prStaRec->aprTxDescTemplate[ucTid] = NULL; + + prMsduInfo = cnmPktAlloc(prAdapter, 0); + + if (!prMsduInfo) + return WLAN_STATUS_RESOURCES; + + /* Fill up MsduInfo template */ + prMsduInfo->eSrc = TX_PACKET_OS; + prMsduInfo->fgIs802_11 = FALSE; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_1x_NonProtected = FALSE; + prMsduInfo->fgIs802_3 = FALSE; + prMsduInfo->fgIsVlanExists = FALSE; + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->prPacket = NULL; + prMsduInfo->u2FrameLength = 0; + prMsduInfo->u4Option = 0; + prMsduInfo->u4FixedRateOption = 0; + prMsduInfo->ucRateMode = MSDU_RATE_MODE_AUTO; + prMsduInfo->ucBssIndex = prStaRec->ucBssIndex; + prMsduInfo->ucPacketType = TX_PACKET_TYPE_DATA; + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucPID = NIC_TX_DESC_PID_RESERVED; + + u4TxDescSize = NIC_TX_DESC_LONG_FORMAT_LENGTH; + u4TxDescAppendSize = HW_MAC_TX_DESC_APPEND_T_LENGTH; + + DBGLOG(QM, INFO, "Generate TXD template for STA[%u] QoS[%u]\n", prStaRec->ucIndex, prStaRec->fgIsQoS); + + /* Generate new template */ + if (prStaRec->fgIsQoS) { + /* For QoS STA, generate 8 TXD template (TID0~TID7) */ + for (ucTid = 0; ucTid < TX_DESC_TID_NUM; ucTid++) { + + if (prAdapter->rWifiVar.ucTcRestrict < TC_NUM) + ucTc = prAdapter->rWifiVar.ucTcRestrict; + else + ucTc = arNetwork2TcResource[prStaRec->ucBssIndex][aucTid2ACI[ucTid]]; + u4TxDescSize = arTcTrafficSettings[ucTc].u4TxDescLength; + + /* Include TxD append */ + prTxDesc = kalMemAlloc(u4TxDescSize + u4TxDescAppendSize, VIR_MEM_TYPE); + DBGLOG(QM, TRACE, "STA[%u] TID[%u] TxDTemp[0x%p]\n", prStaRec->ucIndex, ucTid, prTxDesc); + if (!prTxDesc) { + rStatus = WLAN_STATUS_RESOURCES; + break; + } + + /* Update MsduInfo TID & TC */ + prMsduInfo->ucUserPriority = ucTid; + prMsduInfo->ucTC = ucTc; + + /* Compose Tx desc template */ + nicTxComposeDesc(prAdapter, prMsduInfo, u4TxDescSize, TRUE, (PUINT_8) prTxDesc); + + /* Fill TxD append */ + nicTxComposeDescAppend(prAdapter, prMsduInfo, ((PUINT_8)prTxDesc + u4TxDescSize)); + + prStaRec->aprTxDescTemplate[ucTid] = prTxDesc; + } + } else { + /* For non-QoS STA, generate 1 TXD template (TID0) */ + do { + if (prAdapter->rWifiVar.ucTcRestrict < TC_NUM) + ucTc = prAdapter->rWifiVar.ucTcRestrict; + else + ucTc = arNetwork2TcResource[prStaRec->ucBssIndex][NET_TC_WMM_AC_BE_INDEX]; + + /* ucTxDescSize = arTcTrafficSettings[ucTc].ucTxDescLength; */ + u4TxDescSize = NIC_TX_DESC_LONG_FORMAT_LENGTH; + + prTxDesc = kalMemAlloc(u4TxDescSize + u4TxDescAppendSize, VIR_MEM_TYPE); + if (!prTxDesc) { + rStatus = WLAN_STATUS_RESOURCES; + break; + } + /* Update MsduInfo TID & TC */ + prMsduInfo->ucUserPriority = 0; + prMsduInfo->ucTC = ucTc; + + /* Compose Tx desc template */ + nicTxComposeDesc(prAdapter, prMsduInfo, u4TxDescSize, TRUE, (PUINT_8) prTxDesc); + + /* Fill TxD append */ + nicTxComposeDescAppend(prAdapter, prMsduInfo, ((PUINT_8)prTxDesc + u4TxDescSize)); + + for (ucTid = 0; ucTid < TX_DESC_TID_NUM; ucTid++) { + prStaRec->aprTxDescTemplate[ucTid] = prTxDesc; + DBGLOG(QM, TRACE, + "TXD template: TID[%u] Ptr[0x%p]\n", + ucTid, prTxDesc); + } + } while (FALSE); + } + + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief In this function, we'll free Tx descriptor template for each TID. +* +* @param prAdapter Pointer to the Adapter structure. +* @param prStaRec Pointer to the StaRec structure. +* +* @retval VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID nicTxFreeDescTemplate(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + UINT_8 ucTid; + UINT_8 ucTxDescSize; + P_HW_MAC_TX_DESC_T prTxDesc; + + /* This is to lock the process to preventing */ + /* nicTxFreeDescTemplate while Filling it */ + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_DESC); + + DBGLOG(QM, INFO, "Free TXD template for STA[%u] QoS[%u]\n", prStaRec->ucIndex, prStaRec->fgIsQoS); + + if (prStaRec->fgIsQoS) { + for (ucTid = 0; ucTid < TX_DESC_TID_NUM; ucTid++) { + prTxDesc = (P_HW_MAC_TX_DESC_T) prStaRec->aprTxDescTemplate[ucTid]; + + if (prTxDesc) { + if (HAL_MAC_TX_DESC_IS_LONG_FORMAT(prTxDesc)) + ucTxDescSize = NIC_TX_DESC_LONG_FORMAT_LENGTH; + else + ucTxDescSize = NIC_TX_DESC_SHORT_FORMAT_LENGTH; + + kalMemFree(prTxDesc, VIR_MEM_TYPE, ucTxDescSize); + prTxDesc = prStaRec->aprTxDescTemplate[ucTid] = NULL; + } + } + } else { + prTxDesc = (P_HW_MAC_TX_DESC_T) prStaRec->aprTxDescTemplate[0]; + if (prTxDesc) { + if (HAL_MAC_TX_DESC_IS_LONG_FORMAT(prTxDesc)) + ucTxDescSize = NIC_TX_DESC_LONG_FORMAT_LENGTH; + else + ucTxDescSize = NIC_TX_DESC_SHORT_FORMAT_LENGTH; + + kalMemFree(prTxDesc, VIR_MEM_TYPE, ucTxDescSize); + prTxDesc = NULL; + } + for (ucTid = 0; ucTid < TX_DESC_TID_NUM; ucTid++) + prStaRec->aprTxDescTemplate[ucTid] = NULL; + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_DESC); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write data to device done +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] prQue msdu info que to be free +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +void nicTxMsduDoneCb(IN P_GLUE_INFO_T prGlueInfo, IN P_QUE_T prQue) +{ + P_MSDU_INFO_T prMsduInfo, prNextMsduInfo; + QUE_T rFreeQueue; + P_QUE_T prFreeQueue; + /* P_NATIVE_PACKET prNativePacket; */ + P_TX_CTRL_T prTxCtrl; + P_ADAPTER_T prAdapter = prGlueInfo->prAdapter; + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + prFreeQueue = &rFreeQueue; + QUEUE_INITIALIZE(prFreeQueue); + + if (prQue && prQue->u4NumElem > 0) { + prMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_HEAD(prQue); + + while (prMsduInfo) { + prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY(&prMsduInfo->rQueEntry); + +#if 1 + nicTxFreePacket(prAdapter, prMsduInfo, FALSE); +#else + prNativePacket = prMsduInfo->prPacket; + + /* Free MSDU_INFO */ + if (prMsduInfo->eSrc == TX_PACKET_OS) { + wlanTxProfilingTagMsdu(prAdapter, prMsduInfo, TX_PROF_TAG_DRV_TX_DONE); + kalSendComplete(prAdapter->prGlueInfo, prNativePacket, WLAN_STATUS_SUCCESS); + prMsduInfo->prPacket = NULL; + } else if (prMsduInfo->eSrc == TX_PACKET_FORWARDING) { + GLUE_DEC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount); + } +#endif + + if (!prMsduInfo->pfTxDoneHandler) + QUEUE_INSERT_TAIL(prFreeQueue, (P_QUE_ENTRY_T) prMsduInfo); + + prMsduInfo = prNextMsduInfo; + } + nicTxReturnMsduInfo(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(&rFreeQueue)); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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; + P_TX_CTRL_T prTxCtrl; + + ASSERT(prAdapter); + ASSERT(prQue); + + prTxCtrl = &prAdapter->rTxCtrl; + +#if CFG_HIF_STATISTICS + prTxCtrl->u4TotalTxAccessNum++; + prTxCtrl->u4TotalTxPacketNum += prQue->u4NumElem; +#endif + + while (QUEUE_IS_NOT_EMPTY(prQue)) { + QUEUE_REMOVE_HEAD(prQue, prMsduInfo, P_MSDU_INFO_T); + + if (!halTxIsDataBufEnough(prAdapter, prMsduInfo)) { + QUEUE_INSERT_HEAD(prQue, (P_QUE_ENTRY_T) prMsduInfo); + break; + } + +#if !CFG_SUPPORT_MULTITHREAD + nicTxFillDataDesc(prAdapter, prMsduInfo); +#endif + + if (prMsduInfo->pfTxDoneHandler) { + KAL_SPIN_LOCK_DECLARATION(); + + /* Record native packet pointer for Tx done log */ + WLAN_GET_FIELD_32(&prMsduInfo->prPacket, &prMsduInfo->u4TxDoneTag); + + 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); + } + + HAL_WRITE_TX_DATA(prAdapter, prMsduInfo); + } + + HAL_KICK_TX_DATA(prAdapter); + + 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; + P_MSDU_INFO_T prMsduInfo; + P_TX_CTRL_T prTxCtrl; + struct sk_buff *skb; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prTxCtrl = &prAdapter->rTxCtrl; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) { + prMsduInfo = prCmdInfo->prMsduInfo; + + prCmdInfo->pucTxd = prMsduInfo->aucTxDescBuffer; + if (HAL_MAC_TX_DESC_IS_LONG_FORMAT((P_HW_MAC_TX_DESC_T) prMsduInfo->aucTxDescBuffer)) + prCmdInfo->u4TxdLen = NIC_TX_DESC_LONG_FORMAT_LENGTH; + else + prCmdInfo->u4TxdLen = NIC_TX_DESC_SHORT_FORMAT_LENGTH; + + skb = (struct sk_buff *)prMsduInfo->prPacket; + prCmdInfo->pucTxp = skb->data; + prCmdInfo->u4TxpLen = skb->len; + + HAL_WRITE_TX_CMD(prAdapter, prCmdInfo, ucTC); + + prMsduInfo->prPacket = NULL; + + if (prMsduInfo->pfTxDoneHandler) { + /* 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 { + /* Only return MSDU_INFO */ + /* NativePacket will be freed at SEC frame CMD callback */ + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } + + } else if (prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) { + prMsduInfo = prCmdInfo->prMsduInfo; + + ASSERT(prMsduInfo->fgIs802_11 == TRUE); + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + + prCmdInfo->pucTxd = prMsduInfo->aucTxDescBuffer; + if (HAL_MAC_TX_DESC_IS_LONG_FORMAT((P_HW_MAC_TX_DESC_T) prMsduInfo->aucTxDescBuffer)) + prCmdInfo->u4TxdLen = NIC_TX_DESC_LONG_FORMAT_LENGTH; + else + prCmdInfo->u4TxdLen = NIC_TX_DESC_SHORT_FORMAT_LENGTH; + + prCmdInfo->pucTxp = prMsduInfo->prPacket; + prCmdInfo->u4TxpLen = prMsduInfo->u2FrameLength; + + HAL_WRITE_TX_CMD(prAdapter, prCmdInfo, ucTC); + /* <4> Management Frame Post-Processing */ + GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum); + + DBGLOG(INIT, INFO, "TX MGMT Frame: BSS[%u] WIDX:PID[%u:%u] SEQ[%u] STA[%u] RSP[%u]\n", + prMsduInfo->ucBssIndex, prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, + prMsduInfo->ucTxSeqNum, prMsduInfo->ucStaRecIndex, prMsduInfo->pfTxDoneHandler ? TRUE : FALSE); + + if (prMsduInfo->pfTxDoneHandler) { + /* 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 { + cnmMgtPktFree(prAdapter, prMsduInfo); + } + + } else { + P_PSE_CMD_HDR_T prPseCmdHdr; + + prWifiCmd = (P_WIFI_CMD_T) prCmdInfo->pucInfoBuffer; + + prPseCmdHdr = (P_PSE_CMD_HDR_T) (prCmdInfo->pucInfoBuffer); + prPseCmdHdr->u2Qidx = TXD_Q_IDX_MCU_RQ0; + prPseCmdHdr->u2Pidx = TXD_P_IDX_MCU; + prPseCmdHdr->u2Hf = TXD_HF_CMD; + prPseCmdHdr->u2Ft = TXD_FT_LONG_FORMAT; + prPseCmdHdr->u2PktFt = TXD_PKT_FT_CMD; + + prWifiCmd->u2Length = prWifiCmd->u2TxByteCount - sizeof(PSE_CMD_HDR_T); + +#if (CFG_UMAC_GENERATION >= 0x20) + /* TODO ? */ + /* prWifiCmd->prPseCmd.u2TxByteCount = u2OverallBufferLength; */ + /* prWifiCmd->u2TxByteCount = u2OverallBufferLength - sizeof(PSE_CMD_HDR_T); */ +#else + prWifiCmd->u2TxByteCount = + TFCB_FRAME_PAD_TO_DW((prCmdInfo->u2InfoBufLen) & (UINT_16) HIF_TX_HDR_TX_BYTE_COUNT_MASK); +#endif + prWifiCmd->u2PQ_ID = CMD_PQ_ID; + prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; + prWifiCmd->ucS2DIndex = S2D_INDEX_CMD_H2N_H2C; + prCmdInfo->pucTxd = prCmdInfo->pucInfoBuffer; + prCmdInfo->u4TxdLen = prCmdInfo->u2InfoBufLen; + prCmdInfo->pucTxp = NULL; + prCmdInfo->u4TxpLen = 0; + + HAL_WRITE_TX_CMD(prAdapter, prCmdInfo, ucTC); + + DBGLOG(INIT, INFO, "TX CMD: ID[0x%02X] SEQ[%u] SET[%u] LEN[%u]\n", + prWifiCmd->ucCID, prWifiCmd->ucSeqNum, prWifiCmd->ucSetQuery, prWifiCmd->u2Length); + } + + 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, IN BOOLEAN fgProcTxDoneHandler) +{ + 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) { + DBGLOG(TX, TRACE, "%s: Get Msdu WIDX:PID[%u:%u] SEQ[%u] from Pending Q\n", + __func__, prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, prMsduInfo->ucTxSeqNum); + + /* invoke done handler */ + if (prMsduInfo->pfTxDoneHandler && fgProcTxDoneHandler) + prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_DROPPED_IN_DRIVER); + + nicTxFreeMsduInfoPacket(prAdapter, prMsduInfo); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } else { + break; + } + } while (TRUE); + +} /* end of nicTxRelease() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process the TX Done interrupt and pull in more pending frames in SW +* Queues for transmission. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicProcessTxInterrupt(IN P_ADAPTER_T prAdapter) +{ + P_WIFI_VAR_T prWifiVar = &prAdapter->rWifiVar; + + halProcessTxInterrupt(prAdapter); + + /* Indicate Service Thread */ + if (kalGetTxPendingCmdCount(prAdapter->prGlueInfo) > 0 || wlanGetTxPendingFrameCount(prAdapter) > 0) + kalSetEvent(prAdapter->prGlueInfo); + + /* SER break point */ + if (nicSerIsTxStop(prAdapter)) { + /* Skip following Tx handling */ + return; + } + + /* TX Commands */ + if (kalGetTxPendingCmdCount(prAdapter->prGlueInfo)) + wlanTxCmdMthread(prAdapter); + + /* Process TX data packet to HIF */ + if (nicTxGetMsduPendingCnt(prAdapter) >= prWifiVar->u4TxIntThCount) + nicTxMsduQueueMthread(prAdapter); +} /* end of nicProcessTxInterrupt() */ + +VOID nicTxFreePacket(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN BOOLEAN fgDrop) +{ + P_NATIVE_PACKET prNativePacket; + P_TX_CTRL_T prTxCtrl; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + + prNativePacket = prMsduInfo->prPacket; + + if (fgDrop) + rStatus = WLAN_STATUS_FAILURE; + + if (prMsduInfo->eSrc == TX_PACKET_OS) { + if (prNativePacket) + kalSendComplete(prAdapter->prGlueInfo, prNativePacket, rStatus); + if (fgDrop) + wlanUpdateTxStatistics(prAdapter, prMsduInfo, TRUE); /*get per-AC Tx drop packets */ + } else if (prMsduInfo->eSrc == TX_PACKET_MGMT) { + if (prMsduInfo->pfTxDoneHandler) + prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_DROPPED_IN_DRIVER); + if (prNativePacket) + cnmMemFree(prAdapter, prNativePacket); + } else if (prMsduInfo->eSrc == TX_PACKET_FORWARDING) { + GLUE_DEC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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 1 + nicTxFreePacket(prAdapter, prMsduInfo, TRUE); +#else + if (prMsduInfo->eSrc == TX_PACKET_OS) { + if (prNativePacket) + kalSendComplete(prAdapter->prGlueInfo, prNativePacket, WLAN_STATUS_FAILURE); + /*get per-AC Tx drop packets */ + wlanUpdateTxStatistics(prAdapter, prMsduInfo, TRUE); + } else if (prMsduInfo->eSrc == TX_PACKET_MGMT) { + if (prMsduInfo->pfTxDoneHandler) + prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_DROPPED_IN_DRIVER); + if (prNativePacket) + cnmMemFree(prAdapter, prNativePacket); + } else if (prMsduInfo->eSrc == TX_PACKET_FORWARDING) { + GLUE_DEC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount); + } +#endif + prMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief this function returns P_MSDU_INFO_T of MsduInfoList to TxCtrl->rfreeMsduInfoList +* +* @param prAdapter Pointer to the Adapter structure. +* @param prMsduInfoList a link list of P_MSDU_INFO_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicTxReturnMsduInfo(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead) +{ + P_TX_CTRL_T prTxCtrl; + P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead, prNextMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + while (prMsduInfo) { + prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); + + switch (prMsduInfo->eSrc) { + case TX_PACKET_FORWARDING: + wlanReturnPacket(prAdapter, prMsduInfo->prPacket); + break; + case TX_PACKET_OS: + case TX_PACKET_OS_OID: + case TX_PACKET_MGMT: + default: + break; + } + + /* Reset MSDU_INFO fields */ + kalMemZero(prMsduInfo, sizeof(MSDU_INFO_T)); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + QUEUE_INSERT_TAIL(&prTxCtrl->rFreeMsduInfoList, (P_QUE_ENTRY_T) prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + prMsduInfo = prNextMsduInfo; + }; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief this function fills packet information to P_MSDU_INFO_T +* +* @param prAdapter Pointer to the Adapter structure. +* @param prMsduInfo P_MSDU_INFO_T +* @param prPacket P_NATIVE_PACKET +* +* @retval TRUE Success to extract information +* @retval FALSE Fail to extract correct information +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN nicTxFillMsduInfo(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN P_NATIVE_PACKET prPacket) +{ + P_GLUE_INFO_T prGlueInfo; + + ASSERT(prAdapter); + + kalMemZero(prMsduInfo, sizeof(MSDU_INFO_T)); + + prGlueInfo = prAdapter->prGlueInfo; + ASSERT(prGlueInfo); + + kalGetEthDestAddr(prAdapter->prGlueInfo, prPacket, prMsduInfo->aucEthDestAddr); + + prMsduInfo->prPacket = prPacket; + prMsduInfo->ucBssIndex = GLUE_GET_PKT_BSS_IDX(prPacket); + prMsduInfo->ucUserPriority = GLUE_GET_PKT_TID(prPacket); + prMsduInfo->ucMacHeaderLength = GLUE_GET_PKT_HEADER_LEN(prPacket); + prMsduInfo->u2FrameLength = (UINT_16) GLUE_GET_PKT_FRAME_LEN(prPacket); + prMsduInfo->u4PageCount = nicTxGetPageCount(prMsduInfo->u2FrameLength, FALSE); + + if (GLUE_IS_PKT_FLAG_SET(prPacket)) { + prMsduInfo->fgIs802_1x = GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_1X) ? TRUE:FALSE; + prMsduInfo->fgIs802_1x_NonProtected = + GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_NON_PROTECTED_1X) ? TRUE:FALSE; + prMsduInfo->fgIs802_3 = GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_802_3) ? TRUE:FALSE; + prMsduInfo->fgIsVlanExists = GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_VLAN_EXIST) ? TRUE:FALSE; + + if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_DHCP) && prAdapter->rWifiVar.ucDhcpTxDone) + prMsduInfo->pfTxDoneHandler = wlanDhcpTxDone; + else if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_ARP) && prAdapter->rWifiVar.ucArpTxDone) + prMsduInfo->pfTxDoneHandler = wlanArpTxDone; + else if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_1X)) + prMsduInfo->pfTxDoneHandler = wlan1xTxDone; + + if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_DHCP) || + GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_ARP) || + GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_1X)) { + /* Set BSS/STA lowest basic rate */ + prMsduInfo->ucRateMode = MSDU_RATE_MODE_LOWEST_RATE; + + /* Set higher priority */ + prMsduInfo->ucUserPriority = NIC_TX_CRITICAL_DATA_TID; + } + } + + /* Add dummy Tx done */ + if ((prAdapter->rWifiVar.ucDataTxDone == 1) && (prMsduInfo->pfTxDoneHandler == NULL)) + prMsduInfo->pfTxDoneHandler = nicTxDummyTxDone; + + 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) +{ +#if CFG_SUPPORT_MULTITHREAD + TX_TCQ_ADJUST_T rTcqAdjust; + P_TX_CTRL_T prTxCtrl; + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + qmAdjustTcQuotasMthread(prAdapter, &rTcqAdjust, &prTxCtrl->rTc); + +#else + + UINT_32 u4Num; + TX_TCQ_ADJUST_T rTcqAdjust; + P_TX_CTRL_T prTxCtrl; + P_TX_TCQ_STATUS_T prTcqStatus; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + prTcqStatus = &prAdapter->rTxCtrl.rTc; + ASSERT(prTxCtrl); + + if (qmAdjustTcQuotas(prAdapter, &rTcqAdjust, &prTxCtrl->rTc)) { + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + for (u4Num = 0; u4Num < TC_NUM; u4Num++) { + /* Page count */ + prTxCtrl->rTc.au4FreePageCount[u4Num] += + (rTcqAdjust.ai4Variation[u4Num] * NIC_TX_MAX_PAGE_PER_FRAME); + prTxCtrl->rTc.au4MaxNumOfPage[u4Num] += + (rTcqAdjust.ai4Variation[u4Num] * NIC_TX_MAX_PAGE_PER_FRAME); + + /* Buffer count */ + prTxCtrl->rTc.au4FreeBufferCount[u4Num] += rTcqAdjust.ai4Variation[u4Num]; + prTxCtrl->rTc.au4MaxNumOfBuffer[u4Num] += rTcqAdjust.ai4Variation[u4Num]; + + ASSERT(prTxCtrl->rTc.au4FreeBufferCount[u4Num] >= 0); + ASSERT(prTxCtrl->rTc.au4MaxNumOfBuffer[u4Num] >= 0); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); +#if 0 + DBGLOG(TX, LOUD, + "TCQ Status Free Page:Buf[%03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u]\n", + prTcqStatus->au4FreePageCount[TC0_INDEX], + prTcqStatus->au4FreeBufferCount[TC0_INDEX], + prTcqStatus->au4FreePageCount[TC1_INDEX], + prTcqStatus->au4FreeBufferCount[TC1_INDEX], + prTcqStatus->au4FreePageCount[TC2_INDEX], + prTcqStatus->au4FreeBufferCount[TC2_INDEX], + prTcqStatus->au4FreePageCount[TC3_INDEX], + prTcqStatus->au4FreeBufferCount[TC3_INDEX], + prTcqStatus->au4FreePageCount[TC4_INDEX], + prTcqStatus->au4FreeBufferCount[TC4_INDEX], + prTcqStatus->au4FreePageCount[TC5_INDEX], prTcqStatus->au4FreeBufferCount[TC5_INDEX]); +#endif + DBGLOG(TX, LOUD, + "TCQ Status Max Page:Buf[%03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u, %03u:%02u]\n", + prTcqStatus->au4MaxNumOfPage[TC0_INDEX], + prTcqStatus->au4MaxNumOfBuffer[TC0_INDEX], + prTcqStatus->au4MaxNumOfPage[TC1_INDEX], + prTcqStatus->au4MaxNumOfBuffer[TC1_INDEX], + prTcqStatus->au4MaxNumOfPage[TC2_INDEX], + prTcqStatus->au4MaxNumOfBuffer[TC2_INDEX], + prTcqStatus->au4MaxNumOfPage[TC3_INDEX], + prTcqStatus->au4MaxNumOfBuffer[TC3_INDEX], + prTcqStatus->au4MaxNumOfPage[TC4_INDEX], + prTcqStatus->au4MaxNumOfBuffer[TC4_INDEX], + prTcqStatus->au4MaxNumOfPage[TC5_INDEX], prTcqStatus->au4MaxNumOfBuffer[TC5_INDEX]); + + } +#endif + 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); + + if (HAL_IS_TX_DIRECT(prAdapter)) { + nicTxDirectClearAllStaPsQ(prAdapter); + } else { + /* ask Per STA/AC queue to be fllushed and return all queued packets */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + prMsduInfo = qmFlushTxQueues(prAdapter); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + + if (prMsduInfo != NULL) { + nicTxFreeMsduInfoPacket(prAdapter, prMsduInfo); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } + } + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_ENABLE_FW_DOWNLOAD +/*----------------------------------------------------------------------------*/ +/*! +* \brief In this function, we'll write Command(CMD_INFO_T) into HIF. +* However this function is used for INIT_CMD. +* +* In order to avoid further maintenance issues, these 2 functions are separated +* +* @param prAdapter Pointer to the Adapter structure. +* @param prPacketInfo Pointer of CMD_INFO_T +* @param ucTC Specify the resource of TC +* +* @retval WLAN_STATUS_SUCCESS Bus access ok. +* @retval WLAN_STATUS_FAILURE Bus access fail. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicTxInitCmd(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + UINT_16 u2OverallBufferLength; + PUINT_8 pucOutputBuf = (PUINT_8) NULL; /* Pointer to Transmit Data Structure Frame */ + P_TX_CTRL_T prTxCtrl; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prTxCtrl = &prAdapter->rTxCtrl; + pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; + u2OverallBufferLength = TFCB_FRAME_PAD_TO_DW((prCmdInfo->u2InfoBufLen) & (UINT_16) + HIF_TX_HDR_TX_BYTE_COUNT_MASK); + + /* <1> Copy CMD Header to command buffer (by using pucCoalescingBufCached) */ + kalMemCopy((PVOID)&pucOutputBuf[0], (PVOID) prCmdInfo->pucInfoBuffer, prCmdInfo->u2InfoBufLen); + + ASSERT(u2OverallBufferLength <= prAdapter->u4CoalescingBufCachedSize); + + /* <2> Write frame to data port */ + HAL_WRITE_TX_PORT(prAdapter, NIC_TX_INIT_CMD_PORT, + (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; + UINT_8 ucIdx; + + DEBUGFUNC("nicTxInitResetResource"); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + /* Delta page count */ + kalMemZero(prTxCtrl->rTc.au4TxDonePageCount, sizeof(prTxCtrl->rTc.au4TxDonePageCount)); + kalMemZero(prTxCtrl->rTc.au4PreUsedPageCount, sizeof(prTxCtrl->rTc.au4PreUsedPageCount)); + prTxCtrl->rTc.ucNextTcIdx = TC0_INDEX; + prTxCtrl->rTc.u4AvaliablePageCount = 0; + + /* Page count */ + prTxCtrl->rTc.au4MaxNumOfPage[TC0_INDEX] = NIC_TX_INIT_PAGE_COUNT_TC0; + prTxCtrl->rTc.au4FreePageCount[TC0_INDEX] = NIC_TX_INIT_PAGE_COUNT_TC0; + + prTxCtrl->rTc.au4MaxNumOfPage[TC1_INDEX] = NIC_TX_INIT_PAGE_COUNT_TC1; + prTxCtrl->rTc.au4FreePageCount[TC1_INDEX] = NIC_TX_INIT_PAGE_COUNT_TC1; + + prTxCtrl->rTc.au4MaxNumOfPage[TC2_INDEX] = NIC_TX_INIT_PAGE_COUNT_TC2; + prTxCtrl->rTc.au4FreePageCount[TC2_INDEX] = NIC_TX_INIT_PAGE_COUNT_TC2; + + prTxCtrl->rTc.au4MaxNumOfPage[TC3_INDEX] = NIC_TX_INIT_PAGE_COUNT_TC3; + prTxCtrl->rTc.au4FreePageCount[TC3_INDEX] = NIC_TX_INIT_PAGE_COUNT_TC3; + + prTxCtrl->rTc.au4MaxNumOfPage[TC4_INDEX] = NIC_TX_INIT_PAGE_COUNT_TC4; + prTxCtrl->rTc.au4FreePageCount[TC4_INDEX] = NIC_TX_INIT_PAGE_COUNT_TC4; + + prTxCtrl->rTc.au4MaxNumOfPage[TC5_INDEX] = NIC_TX_INIT_PAGE_COUNT_TC5; + prTxCtrl->rTc.au4FreePageCount[TC5_INDEX] = NIC_TX_INIT_PAGE_COUNT_TC5; + + /* Buffer count */ + for (ucIdx = TC0_INDEX; ucIdx < TC_NUM; ucIdx++) { + prTxCtrl->rTc.au4MaxNumOfBuffer[ucIdx] = + prTxCtrl->rTc.au4MaxNumOfPage[ucIdx] / NIC_TX_MAX_PAGE_PER_FRAME; + prTxCtrl->rTc.au4FreeBufferCount[ucIdx] = + prTxCtrl->rTc.au4FreePageCount[ucIdx] / NIC_TX_MAX_PAGE_PER_FRAME; + } + + return WLAN_STATUS_SUCCESS; + +} + +#endif + +BOOLEAN nicTxProcessMngPacket(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ +#if 0 + UINT_16 u2RateCode; +#endif + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + + if (prMsduInfo->eSrc != TX_PACKET_MGMT) + return FALSE; + + /* Sanity check */ + if (!prMsduInfo->prPacket) + return FALSE; + + if (!prMsduInfo->u2FrameLength) + return FALSE; + + if (!prMsduInfo->ucMacHeaderLength) + return FALSE; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + /* MMPDU: force stick to TC4 */ + prMsduInfo->ucTC = TC4_INDEX; + + /* No Tx descriptor template for MMPDU */ + prMsduInfo->fgIsTXDTemplateValid = FALSE; + + /* Fixed Rate */ + if (prMsduInfo->ucRateMode == MSDU_RATE_MODE_AUTO) { +#if 0 + prMsduInfo->ucRateMode = MSDU_RATE_MODE_MANUAL_DESC; + + if (prStaRec) + u2RateCode = prStaRec->u2HwDefaultFixedRateCode; + else + u2RateCode = prBssInfo->u2HwDefaultFixedRateCode; + + nicTxSetPktFixedRateOption(prMsduInfo, u2RateCode, FIX_BW_NO_FIXED, FALSE, FALSE); +#else + nicTxSetPktLowestFixedRate(prAdapter, prMsduInfo); +#endif + } +#if CFG_SUPPORT_MULTITHREAD + nicTxFillDesc(prAdapter, prMsduInfo, prMsduInfo->aucTxDescBuffer, NULL); +#endif + + return TRUE; +} + +VOID nicTxProcessTxDoneEvent(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_EVENT_TX_DONE_T prTxDone; + P_MSDU_INFO_T prMsduInfo; + PUINT_8 apucBandwidt[4] = {(PUINT_8)"20", (PUINT_8)"40", (PUINT_8)"80", (PUINT_8)"160/80+80"}; + + prTxDone = (P_EVENT_TX_DONE_T) (prEvent->aucBuffer); + + if (prTxDone->ucFlag & BIT(TXS_WITH_ADVANCED_INFO)) { + /* Tx Done with advanced info */ + DBGLOG(NIC, INFO, "EVENT_ID_TX_DONE WIDX:PID[%u:%u] Status[%u] TID[%u] SN[%u] CNT[%u] RATE[0x%04x]\n", + prTxDone->ucWlanIndex, prTxDone->ucPacketSeq, prTxDone->ucStatus, prTxDone->ucTid, + prTxDone->u2SequenceNumber, prTxDone->ucTxCount, prTxDone->u2TxRate); + + if (prTxDone->ucFlag & BIT(TXS_IS_EXIST)) { + UINT_8 ucNss, ucStbc; + INT_8 icTxPwr; + + ucNss = (prTxDone->u2TxRate & TX_DESC_NSTS_MASK) >> TX_DESC_NSTS_OFFSET; + ucNss += 1; + ucStbc = (prTxDone->u2TxRate & TX_DESC_STBC) ? TRUE:FALSE; + + if (ucStbc) + ucNss /= 2; + + DBGLOG(NIC, INFO, "||BW[%s] NSS[%u] ArIdx[%u] RspRate[0x%02x]\n", + apucBandwidt[prTxDone->ucBandwidth], ucNss, prTxDone->ucRateTableIdx, + prTxDone->ucRspRate); + + icTxPwr = (INT_8)prTxDone->ucTxPower; + if (icTxPwr & BIT(6)) + icTxPwr |= BIT(7); + + DBGLOG(NIC, INFO, "||AMPDU[%u] PS[%u] IBF[%u] EBF[%u] TxPwr[%d%sdBm] TSF[%u] TxDelay[%uus]\n", + prTxDone->u4AppliedFlag & BIT(TX_FRAME_IN_AMPDU_FORMAT) ? TRUE:FALSE, + prTxDone->u4AppliedFlag & BIT(TX_FRAME_PS_BIT) ? TRUE:FALSE, + prTxDone->u4AppliedFlag & BIT(TX_FRAME_IMP_BF) ? TRUE:FALSE, + prTxDone->u4AppliedFlag & BIT(TX_FRAME_EXP_BF) ? TRUE:FALSE, + icTxPwr / 2, icTxPwr & BIT(0) ? ".5" : "", + prTxDone->u4Timestamp, prTxDone->u4TxDelay); + } + } else { + DBGLOG(NIC, INFO, "EVENT_ID_TX_DONE WIDX:PID[%u:%u] Status[%u] SN[%u]\n", + prTxDone->ucWlanIndex, prTxDone->ucPacketSeq, prTxDone->ucStatus, prTxDone->u2SequenceNumber); + } + + /* call related TX Done Handler */ + prMsduInfo = nicGetPendingTxMsduInfo(prAdapter, prTxDone->ucWlanIndex, prTxDone->ucPacketSeq); + +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT + DBGLOG(NIC, 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)); + + if (prMsduInfo->eSrc == TX_PACKET_MGMT) + cnmMgtPktFree(prAdapter, prMsduInfo); +#if defined(_HIF_PCIE) + else if (prMsduInfo->prToken) + prMsduInfo->pfTxDoneHandler = NULL; +#endif + else { + nicTxFreePacket(prAdapter, prMsduInfo, FALSE); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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_QUE_T prDataPort0, prDataPort1; + P_CMD_INFO_T prCmdInfo; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + prDataPort0 = &qDataPort0; + prDataPort1 = &qDataPort1; + + QUEUE_INITIALIZE(prDataPort0); + QUEUE_INITIALIZE(prDataPort1); + + /* 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) { + if (nicTxProcessMngPacket(prAdapter, prMsduInfo)) { + /* Valid MGMT */ + QUEUE_INSERT_TAIL(prDataPort1, (P_QUE_ENTRY_T) prMsduInfo); + } else { + /* Invalid MGMT */ + DBGLOG(TX, WARN, "Invalid MGMT[0x%p] BSS[%u] STA[%u],free it\n", + prMsduInfo, prMsduInfo->ucBssIndex, prMsduInfo->ucStaRecIndex); + + cnmMgtPktFree(prAdapter, prMsduInfo); + } + } else { + QUEUE_INSERT_TAIL(prDataPort0, (P_QUE_ENTRY_T) prMsduInfo); + } + + prMsduInfo = prNextMsduInfo; + } + + if (prDataPort0->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(prDataPort0)); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + + /* post-process for dropped packets */ + if (prRetMsduInfo) { /* unable to enqueue */ + nicTxFreeMsduInfoPacket(prAdapter, prRetMsduInfo); + nicTxReturnMsduInfo(prAdapter, prRetMsduInfo); + } + } + + if (prDataPort1->u4NumElem) { + prMsduInfoHead = (P_MSDU_INFO_T) QUEUE_GET_HEAD(prDataPort1); + + if (nicTxGetFreeCmdCount(prAdapter) < NIC_TX_CMD_INFO_RESERVED_COUNT) { + /* 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)); + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + /* Tag MGMT enqueue time */ + GET_CURRENT_SYSTIME(&prMsduInfoHead->rPktProfile.rEnqueueTimestamp); +#endif + prCmdInfo->eCmdType = COMMAND_TYPE_MANAGEMENT_FRAME; + prCmdInfo->u2InfoBufLen = prMsduInfoHead->u2FrameLength; + prCmdInfo->pucInfoBuffer = NULL; + prCmdInfo->prMsduInfo = prMsduInfoHead; + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->pfCmdTimeoutHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->ucCmdSeqNum = prMsduInfoHead->ucTxSeqNum; + + DBGLOG(TX, TRACE, "%s: EN-Q MSDU[0x%p] SEQ[%u] BSS[%u] STA[%u] to CMD Q\n", + __func__, prMsduInfoHead, + prMsduInfoHead->ucTxSeqNum, prMsduInfoHead->ucBssIndex, + prMsduInfoHead->ucStaRecIndex); + + kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + } else { + /* Cmd free count is larger than expected, but allocation fail. */ + u4Status = WLAN_STATUS_FAILURE; + + if (prMsduInfoHead->pfTxDoneHandler != NULL) { + prMsduInfoHead->pfTxDoneHandler(prAdapter, + prMsduInfoHead, + TX_RESULT_DROPPED_IN_DRIVER); + } + + 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 WLAN index +* +* @param prAdapter Pointer to the Adapter structure. +* +* @retval +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 nicTxGetWlanIdx(P_ADAPTER_T prAdapter, UINT_8 ucBssIdx, UINT_8 ucStaRecIdx) +{ + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prBssInfo; + UINT_8 ucWlanIndex = NIC_TX_DEFAULT_WLAN_INDEX; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIdx); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + + if (prStaRec) + ucWlanIndex = prStaRec->ucWlanIndex; + else if ((ucStaRecIdx == STA_REC_INDEX_BMCAST) && prBssInfo->fgIsInUse) { + if (prBssInfo->fgBcDefaultKeyExist) { + if (prBssInfo->wepkeyUsed[prBssInfo->ucBcDefaultKeyIdx] && + prBssInfo->wepkeyWlanIdx < NIC_TX_DEFAULT_WLAN_INDEX) + ucWlanIndex = prBssInfo->wepkeyWlanIdx; + else if (prBssInfo->ucBMCWlanIndexSUsed[prBssInfo->ucBcDefaultKeyIdx]) + ucWlanIndex = prBssInfo->ucBMCWlanIndexS[prBssInfo->ucBcDefaultKeyIdx]; + } else + ucWlanIndex = prBssInfo->ucBMCWlanIndex; + } + + if (ucWlanIndex >= WTBL_SIZE) { + DBGLOG(TX, WARN, + "Unexpected WIDX[%u] BSS[%u] STA[%u], set WIDX to default value[%u]\n", + ucWlanIndex, ucBssIdx, ucStaRecIdx, + NIC_TX_DEFAULT_WLAN_INDEX); + + ucWlanIndex = NIC_TX_DEFAULT_WLAN_INDEX; + } + + return ucWlanIndex; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* @param prAdapter Pointer to the Adapter structure. +* +* @retval +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN nicTxIsMgmtResourceEnough(IN P_ADAPTER_T prAdapter) +{ + if (nicTxGetFreeCmdCount(prAdapter) > (CFG_TX_MAX_CMD_PKT_NUM / 2)) + return TRUE; + else + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief this function returns page count of frame +* +* @param u4FrameLength frame length +* +* @retval page count of this frame +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 nicTxGetPageCount(IN UINT_32 u4FrameLength, IN BOOLEAN fgIncludeDesc) +{ + return halTxGetPageCount(u4FrameLength, fgIncludeDesc); +} + +UINT_32 nicTxGetCmdPageCount(IN P_CMD_INFO_T prCmdInfo) +{ + UINT_32 u4PageCount; + + switch (prCmdInfo->eCmdType) { + case COMMAND_TYPE_NETWORK_IOCTL: + case COMMAND_TYPE_GENERAL_IOCTL: + u4PageCount = nicTxGetPageCount(prCmdInfo->u2InfoBufLen, TRUE); + break; + + case COMMAND_TYPE_SECURITY_FRAME: + case COMMAND_TYPE_MANAGEMENT_FRAME: + /* No TxD append field for management packet */ + u4PageCount = nicTxGetPageCount(prCmdInfo->u2InfoBufLen + NIC_TX_DESC_LONG_FORMAT_LENGTH, TRUE); + break; + + default: + DBGLOG(INIT, WARN, "Undefined CMD Type(%u)\n", prCmdInfo->eCmdType); + u4PageCount = nicTxGetPageCount(prCmdInfo->u2InfoBufLen, FALSE); + break; + } + + return u4PageCount; +} + +VOID nicTxSetMngPacket(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo, + UINT_8 ucBssIndex, UINT_8 ucStaRecIndex, UINT_8 ucMacHeaderLength, + UINT_16 u2FrameLength, PFN_TX_DONE_HANDLER pfTxDoneHandler, UINT_8 ucRateMode) +{ + ASSERT(prMsduInfo); + + prMsduInfo->ucBssIndex = ucBssIndex; + prMsduInfo->ucStaRecIndex = ucStaRecIndex; + prMsduInfo->ucMacHeaderLength = ucMacHeaderLength; + prMsduInfo->u2FrameLength = u2FrameLength; + prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; + prMsduInfo->ucRateMode = ucRateMode; + + /* Reset default value for MMPDU */ + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_1x_NonProtected = TRUE; /*For data frame only, no sense for management frame*/ + prMsduInfo->u4FixedRateOption = 0; + prMsduInfo->cPowerOffset = 0; + prMsduInfo->u4Option = 0; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->ucPID = NIC_TX_DESC_PID_RESERVED; + prMsduInfo->ucPacketType = TX_PACKET_TYPE_MGMT; + prMsduInfo->ucUserPriority = 0; + prMsduInfo->eSrc = TX_PACKET_MGMT; +} + +VOID nicTxSetDataPacket(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo, + UINT_8 ucBssIndex, UINT_8 ucStaRecIndex, UINT_8 ucMacHeaderLength, + UINT_16 u2FrameLength, PFN_TX_DONE_HANDLER pfTxDoneHandler, + UINT_8 ucRateMode, ENUM_TX_PACKET_SRC_T eSrc, UINT_8 ucTID, + BOOLEAN fgIs802_11Frame, BOOLEAN fgIs1xFrame) +{ + ASSERT(prMsduInfo); + + prMsduInfo->ucBssIndex = ucBssIndex; + prMsduInfo->ucStaRecIndex = ucStaRecIndex; + prMsduInfo->ucMacHeaderLength = ucMacHeaderLength; + prMsduInfo->u2FrameLength = u2FrameLength; + prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; + prMsduInfo->ucRateMode = ucRateMode; + prMsduInfo->ucUserPriority = ucTID; + prMsduInfo->fgIs802_11 = fgIs802_11Frame; + prMsduInfo->eSrc = eSrc; + prMsduInfo->fgIs802_1x = fgIs1xFrame; + + /* Reset default value for data packet */ + prMsduInfo->u4FixedRateOption = 0; + prMsduInfo->cPowerOffset = 0; + prMsduInfo->u4Option = 0; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->ucPID = NIC_TX_DESC_PID_RESERVED; + prMsduInfo->ucPacketType = TX_PACKET_TYPE_DATA; +} + +VOID nicTxFillDescByPktOption(P_MSDU_INFO_T prMsduInfo, P_HW_MAC_TX_DESC_T prTxDesc) +{ + UINT_32 u4PktOption = prMsduInfo->u4Option; + BOOLEAN fgIsLongFormat; + BOOLEAN fgProtected = FALSE; + + /* Skip this function if no options is set */ + if (!u4PktOption) + return; + + fgIsLongFormat = HAL_MAC_TX_DESC_IS_LONG_FORMAT(prTxDesc); + + /* Fields in DW0 and DW1 (Short Format) */ + if (u4PktOption & MSDU_OPT_NO_ACK) + HAL_MAC_TX_DESC_SET_NO_ACK(prTxDesc); + + if (u4PktOption & MSDU_OPT_PROTECTED_FRAME) { + /* DBGLOG(RSN, INFO, "MSDU_OPT_PROTECTED_FRAME\n"); */ + HAL_MAC_TX_DESC_SET_PROTECTION(prTxDesc); + fgProtected = TRUE; + } + + switch (HAL_MAC_TX_DESC_GET_HEADER_FORMAT(prTxDesc)) { + case HEADER_FORMAT_802_11_ENHANCE_MODE: + if (u4PktOption & MSDU_OPT_EOSP) + HAL_MAC_TX_DESC_SET_EOSP(prTxDesc); + + if (u4PktOption & MSDU_OPT_AMSDU) + HAL_MAC_TX_DESC_SET_AMSDU(prTxDesc); + break; + + case HEADER_FORMAT_NON_802_11: + if (u4PktOption & MSDU_OPT_EOSP) + HAL_MAC_TX_DESC_SET_EOSP(prTxDesc); + + if (u4PktOption & MSDU_OPT_MORE_DATA) + HAL_MAC_TX_DESC_SET_MORE_DATA(prTxDesc); + + if (u4PktOption & MSDU_OPT_REMOVE_VLAN) + HAL_MAC_TX_DESC_SET_REMOVE_VLAN(prTxDesc); + break; + + case HEADER_FORMAT_802_11_NORMAL_MODE: + if (fgProtected && prMsduInfo->prPacket) { + P_WLAN_MAC_HEADER_T prWlanHeader = + (P_WLAN_MAC_HEADER_T) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prWlanHeader->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + } + break; + + default: + break; + } + + if (!fgIsLongFormat) + return; + + /* Fields in DW2~6 (Long Format) */ + if (u4PktOption & MSDU_OPT_NO_AGGREGATE) + HAL_MAC_TX_DESC_SET_BA_DISABLE(prTxDesc); + + if (u4PktOption & MSDU_OPT_TIMING_MEASURE) + HAL_MAC_TX_DESC_SET_TIMING_MEASUREMENT(prTxDesc); + + if (u4PktOption & MSDU_OPT_NDP) + HAL_MAC_TX_DESC_SET_NDP(prTxDesc); + + if (u4PktOption & MSDU_OPT_NDPA) + HAL_MAC_TX_DESC_SET_NDPA(prTxDesc); + + if (u4PktOption & MSDU_OPT_SOUNDING) + HAL_MAC_TX_DESC_SET_SOUNDING_FRAME(prTxDesc); + + if (u4PktOption & MSDU_OPT_FORCE_RTS) + HAL_MAC_TX_DESC_SET_FORCE_RTS_CTS(prTxDesc); + + if (u4PktOption & MSDU_OPT_BIP) + HAL_MAC_TX_DESC_SET_BIP(prTxDesc); + + /* SW field */ + if (u4PktOption & MSDU_OPT_SW_DURATION) + HAL_MAC_TX_DESC_SET_DURATION_CONTROL_BY_SW(prTxDesc); + + if (u4PktOption & MSDU_OPT_SW_PS_BIT) + HAL_MAC_TX_DESC_SET_SW_PM_CONTROL(prTxDesc); + + if (u4PktOption & MSDU_OPT_SW_HTC) + HAL_MAC_TX_DESC_SET_HTC_EXIST(prTxDesc); +#if 0 + if (u4PktOption & MSDU_OPT_SW_BAR_SN) + HAL_MAC_TX_DESC_SET_SW_BAR_SSN(prTxDesc); +#endif + if (u4PktOption & MSDU_OPT_MANUAL_SN) { + HAL_MAC_TX_DESC_SET_TXD_SN_VALID(prTxDesc); + HAL_MAC_TX_DESC_SET_SEQUENCE_NUMBER(prTxDesc, prMsduInfo->u2SwSN); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Extra configuration for Tx packet +* +* @retval +*/ +/*----------------------------------------------------------------------------*/ +VOID nicTxConfigPktOption(P_MSDU_INFO_T prMsduInfo, UINT_32 u4OptionMask, BOOLEAN fgSetOption) +{ + if (fgSetOption) + prMsduInfo->u4Option |= u4OptionMask; + else + prMsduInfo->u4Option &= ~u4OptionMask; +} + +VOID nicTxFillDescByPktControl(P_MSDU_INFO_T prMsduInfo, P_HW_MAC_TX_DESC_T prTxDesc) +{ + UINT_8 ucPktControl = prMsduInfo->ucControlFlag; + UINT_8 ucSwReserved; + + /* Skip this function if no options is set */ + if (!ucPktControl) + return; + + if (HAL_MAC_TX_DESC_IS_LONG_FORMAT(prTxDesc)) { + ucSwReserved = HAL_MAC_TX_DESC_GET_SW_RESERVED(prTxDesc); + + if (ucPktControl & MSDU_CONTROL_FLAG_FORCE_TX) + ucSwReserved |= MSDU_CONTROL_FLAG_FORCE_TX; + + HAL_MAC_TX_DESC_SET_SW_RESERVED(prTxDesc, ucSwReserved); + } +} + +VOID nicTxConfigPktControlFlag(P_MSDU_INFO_T prMsduInfo, UINT_8 ucControlFlagMask, BOOLEAN fgSetFlag) +{ + /* Set control flag */ + if (fgSetFlag) + prMsduInfo->ucControlFlag |= ucControlFlagMask; + else + prMsduInfo->ucControlFlag &= ~ucControlFlagMask; /* Clear control flag */ +} + +VOID nicTxSetPktLifeTime(P_MSDU_INFO_T prMsduInfo, UINT_32 u4TxLifeTimeInMs) +{ + prMsduInfo->u4RemainingLifetime = u4TxLifeTimeInMs; + prMsduInfo->u4Option |= MSDU_OPT_MANUAL_LIFE_TIME; +} + +VOID nicTxSetPktRetryLimit(P_MSDU_INFO_T prMsduInfo, UINT_8 ucRetryLimit) +{ + prMsduInfo->ucRetryLimit = ucRetryLimit; + prMsduInfo->u4Option |= MSDU_OPT_MANUAL_RETRY_LIMIT; +} + +VOID nicTxSetPktPowerOffset(P_MSDU_INFO_T prMsduInfo, INT_8 cPowerOffset) +{ + prMsduInfo->cPowerOffset = cPowerOffset; + prMsduInfo->u4Option |= MSDU_OPT_MANUAL_POWER_OFFSET; +} + +VOID nicTxSetPktSequenceNumber(P_MSDU_INFO_T prMsduInfo, UINT_16 u2SN) +{ + prMsduInfo->u2SwSN = u2SN; + prMsduInfo->u4Option |= MSDU_OPT_MANUAL_SN; +} + +VOID nicTxSetPktMacTxQue(P_MSDU_INFO_T prMsduInfo, UINT_8 ucMacTxQue) +{ + UINT_8 ucTcIdx; + + for (ucTcIdx = TC0_INDEX; ucTcIdx < TC_NUM; ucTcIdx++) { + if (arTcResourceControl[ucTcIdx].ucDestQueueIndex == ucMacTxQue) + break; + } + + if (ucTcIdx < TC_NUM) { + prMsduInfo->ucTC = ucTcIdx; + prMsduInfo->u4Option |= MSDU_OPT_MANUAL_TX_QUE; + } +} + +VOID nicTxSetPktFixedRateOptionFull(P_MSDU_INFO_T prMsduInfo, + UINT_16 u2RateCode, + UINT_8 ucBandwidth, + BOOLEAN fgShortGI, + BOOLEAN fgLDPC, + BOOLEAN fgDynamicBwRts, BOOLEAN fgBeamforming, UINT_8 ucAntennaIndex) +{ + HW_MAC_TX_DESC_T rTxDesc; + P_HW_MAC_TX_DESC_T prTxDesc = &rTxDesc; + + kalMemZero(prTxDesc, NIC_TX_DESC_LONG_FORMAT_LENGTH); + + /* Follow the format of Tx descriptor DW 6 */ + HAL_MAC_TX_DESC_SET_FR_RATE(prTxDesc, u2RateCode); + + if (ucBandwidth) + HAL_MAC_TX_DESC_SET_FR_BW(prTxDesc, ucBandwidth); + + if (fgBeamforming) + HAL_MAC_TX_DESC_SET_FR_BF(prTxDesc); + + if (fgShortGI) + HAL_MAC_TX_DESC_SET_FR_SHORT_GI(prTxDesc); + + if (fgLDPC) + HAL_MAC_TX_DESC_SET_FR_LDPC(prTxDesc); + + if (fgDynamicBwRts) + HAL_MAC_TX_DESC_SET_FR_DYNAMIC_BW_RTS(prTxDesc); + + HAL_MAC_TX_DESC_SET_FR_ANTENNA_ID(prTxDesc, ucAntennaIndex); + + /* Write back to RateOption of MSDU_INFO */ + HAL_MAC_TX_DESC_GET_DW(prTxDesc, 6, 1, &prMsduInfo->u4FixedRateOption); + + prMsduInfo->ucRateMode = MSDU_RATE_MODE_MANUAL_DESC; + +} + +VOID nicTxSetPktFixedRateOption(P_MSDU_INFO_T prMsduInfo, + UINT_16 u2RateCode, UINT_8 ucBandwidth, BOOLEAN fgShortGI, BOOLEAN fgDynamicBwRts) +{ + HW_MAC_TX_DESC_T rTxDesc; + P_HW_MAC_TX_DESC_T prTxDesc = &rTxDesc; + + kalMemZero(prTxDesc, NIC_TX_DESC_LONG_FORMAT_LENGTH); + + /* Follow the format of Tx descriptor DW 6 */ + HAL_MAC_TX_DESC_SET_FR_RATE(prTxDesc, u2RateCode); + + if (ucBandwidth) + HAL_MAC_TX_DESC_SET_FR_BW(prTxDesc, ucBandwidth); + + if (fgShortGI) + HAL_MAC_TX_DESC_SET_FR_SHORT_GI(prTxDesc); + + if (fgDynamicBwRts) + HAL_MAC_TX_DESC_SET_FR_DYNAMIC_BW_RTS(prTxDesc); + + /* Write back to RateOption of MSDU_INFO */ + HAL_MAC_TX_DESC_GET_DW(prTxDesc, 6, 1, &prMsduInfo->u4FixedRateOption); + + prMsduInfo->ucRateMode = MSDU_RATE_MODE_MANUAL_DESC; + +} + +VOID nicTxSetPktLowestFixedRate(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_BSS_INFO_T prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + P_STA_RECORD_T prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + UINT_8 ucRateSwIndex, ucRateIndex, ucRatePreamble; + UINT_16 u2RateCode, u2RateCodeLimit, u2OperationalRateSet; + UINT_32 u4CurrentPhyRate, u4Status; + + /* Not to use TxD template for fixed rate */ + prMsduInfo->fgIsTXDTemplateValid = FALSE; + + /* Fixed Rate */ + prMsduInfo->ucRateMode = MSDU_RATE_MODE_MANUAL_DESC; + + if (prStaRec) { + u2RateCode = prStaRec->u2HwDefaultFixedRateCode; + u2OperationalRateSet = prStaRec->u2OperationalRateSet; + } else { + u2RateCode = prBssInfo->u2HwDefaultFixedRateCode; + u2OperationalRateSet = prBssInfo->u2OperationalRateSet; + } + + /* CoexPhyRateLimit is 0 means phy rate is unlimited */ + if (prBssInfo->u4CoexPhyRateLimit != 0) { + + u4CurrentPhyRate = nicRateCode2PhyRate(u2RateCode, FIX_BW_NO_FIXED, MAC_GI_NORMAL, AR_SS_NULL); + + if (prBssInfo->u4CoexPhyRateLimit > u4CurrentPhyRate) { + nicGetRateIndexFromRateSetWithLimit( + u2OperationalRateSet, + prBssInfo->u4CoexPhyRateLimit, TRUE, &ucRateSwIndex); + + /* Convert SW rate index to rate code */ + nicSwIndex2RateIndex(ucRateSwIndex, &ucRateIndex, &ucRatePreamble); + u4Status = nicRateIndex2RateCode(ucRatePreamble, ucRateIndex, &u2RateCodeLimit); + if (u4Status == WLAN_STATUS_SUCCESS) { + /* Replace by limitation rate */ + u2RateCode = u2RateCodeLimit; + DBGLOG(NIC, INFO, "Coex RatePreamble=%d, R_SW_IDX:%d, R_CODE:0x%x\n", + ucRatePreamble, ucRateIndex, u2RateCode); + } + } + } + nicTxSetPktFixedRateOption(prMsduInfo, u2RateCode, FIX_BW_NO_FIXED, FALSE, FALSE); +} + +VOID nicTxSetPktMoreData(P_MSDU_INFO_T prCurrentMsduInfo, BOOLEAN fgSetMoreDataBit) +{ + P_WLAN_MAC_HEADER_T prWlanMacHeader = NULL; + + if (prCurrentMsduInfo->fgIs802_11) { + prWlanMacHeader = + (P_WLAN_MAC_HEADER_T) (((PUINT_8) (prCurrentMsduInfo->prPacket)) + MAC_TX_RESERVED_FIELD); + } + + if (fgSetMoreDataBit) { + if (!prCurrentMsduInfo->fgIs802_11) + prCurrentMsduInfo->u4Option |= MSDU_OPT_MORE_DATA; + else + prWlanMacHeader->u2FrameCtrl |= MASK_FC_MORE_DATA; + } else { + if (!prCurrentMsduInfo->fgIs802_11) + prCurrentMsduInfo->u4Option &= ~MSDU_OPT_MORE_DATA; + else + prWlanMacHeader->u2FrameCtrl &= ~MASK_FC_MORE_DATA; + } +} + +UINT_8 nicTxAssignPID(IN P_ADAPTER_T prAdapter, IN UINT_8 ucWlanIndex) +{ + UINT_8 ucRetval; + PUINT_8 pucPidPool; + + ASSERT(prAdapter); + + pucPidPool = &prAdapter->aucPidPool[ucWlanIndex]; + + ucRetval = *pucPidPool; + + /* Driver side Tx Sequence number: 1~127 */ + (*pucPidPool)++; + + if (*pucPidPool > NIC_TX_DESC_DRIVER_PID_MAX) + *pucPidPool = NIC_TX_DESC_DRIVER_PID_MIN; + + return ucRetval; +} + +VOID nicTxSetPktEOSP(P_MSDU_INFO_T prCurrentMsduInfo, BOOLEAN fgSetEOSPBit) +{ + P_WLAN_MAC_HEADER_QOS_T prWlanMacHeader = NULL; + BOOLEAN fgWriteToDesc = TRUE; + + if (prCurrentMsduInfo->fgIs802_11) { + prWlanMacHeader = + (P_WLAN_MAC_HEADER_QOS_T) (((PUINT_8) (prCurrentMsduInfo->prPacket)) + MAC_TX_RESERVED_FIELD); + fgWriteToDesc = FALSE; + } + + if (fgSetEOSPBit) { + if (fgWriteToDesc) + prCurrentMsduInfo->u4Option |= MSDU_OPT_EOSP; + else + prWlanMacHeader->u2QosCtrl |= MASK_QC_EOSP; + } else { + if (fgWriteToDesc) + prCurrentMsduInfo->u4Option &= ~MSDU_OPT_EOSP; + else + prWlanMacHeader->u2QosCtrl &= ~MASK_QC_EOSP; + } +} + +WLAN_STATUS +nicTxDummyTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + DBGLOG(TX, TRACE, "Msdu WIDX:PID[%u:%u] SEQ[%u] Tx Status[%u]\n", + prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, prMsduInfo->ucTxSeqNum, rTxDoneStatus); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Update BSS Tx Params +* +* @param prStaRec The peer +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicTxUpdateBssDefaultRate(P_BSS_INFO_T prBssInfo) +{ + UINT_8 ucLowestBasicRateIndex; + + prBssInfo->u2HwDefaultFixedRateCode = RATE_OFDM_6M; + + /* 4 <1> Find Lowest Basic Rate Index for default TX Rate of MMPDU */ + if (rateGetLowestRateIndexFromRateSet(prBssInfo->u2BSSBasicRateSet, &ucLowestBasicRateIndex)) { + nicRateIndex2RateCode(PREAMBLE_DEFAULT_LONG_NONE, ucLowestBasicRateIndex, + &prBssInfo->u2HwDefaultFixedRateCode); + } else { + switch (prBssInfo->ucNonHTBasicPhyType) { + case PHY_TYPE_ERP_INDEX: + case PHY_TYPE_OFDM_INDEX: + prBssInfo->u2HwDefaultFixedRateCode = RATE_OFDM_6M; + break; + + default: + prBssInfo->u2HwDefaultFixedRateCode = RATE_CCK_1M_LONG; + break; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Update StaRec Tx parameters +* +* @param prStaRec The peer +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicTxUpdateStaRecDefaultRate(P_STA_RECORD_T prStaRec) +{ + UINT_8 ucLowestBasicRateIndex; + + prStaRec->u2HwDefaultFixedRateCode = RATE_OFDM_6M; + + /* 4 <1> Find Lowest Basic Rate Index for default TX Rate of MMPDU */ + if (rateGetLowestRateIndexFromRateSet(prStaRec->u2BSSBasicRateSet, &ucLowestBasicRateIndex)) { + nicRateIndex2RateCode(PREAMBLE_DEFAULT_LONG_NONE, + ucLowestBasicRateIndex, &prStaRec->u2HwDefaultFixedRateCode); + } else { + if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11B) + prStaRec->u2HwDefaultFixedRateCode = RATE_CCK_1M_LONG; + else if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11G) + prStaRec->u2HwDefaultFixedRateCode = RATE_OFDM_6M; + else if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11A) + prStaRec->u2HwDefaultFixedRateCode = RATE_OFDM_6M; + else if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11N) + prStaRec->u2HwDefaultFixedRateCode = RATE_MM_MCS_0; + } +} + +VOID nicTxCancelSendingCmd(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + halTxCancelSendingCmd(prAdapter, prCmdInfo); +} + +/* TX Direct functions : BEGIN */ + +/*----------------------------------------------------------------------------*/ +/* +* \brief This function is to start rTxDirectHifTimer to try to send out packets in +* rStaPsQueue[], rBssAbsentQueue[], rTxDirectHifQueue[]. +* +* \param[in] prAdapter Pointer of Adapter +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicTxDirectStartCheckQTimer(IN P_ADAPTER_T prAdapter) +{ + mod_timer(&prAdapter->rTxDirectHifTimer, jiffies + 1); +} + +VOID nicTxDirectClearSkbQ(IN P_ADAPTER_T prAdapter) +{ + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + struct sk_buff *prSkb; + + while (TRUE) { + spin_lock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + prSkb = skb_dequeue(&prAdapter->rTxDirectSkbQueue); + spin_unlock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + if (prSkb == NULL) + break; + + kalSendComplete(prGlueInfo, prSkb, WLAN_STATUS_NOT_ACCEPTED); + } +} + +VOID nicTxDirectClearHifQ(IN P_ADAPTER_T prAdapter) +{ + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + UINT_8 ucHifTc = 0; + QUE_T rNeedToFreeQue; + P_QUE_T prNeedToFreeQue = &rNeedToFreeQue; + + QUEUE_INITIALIZE(prNeedToFreeQue); + + for (ucHifTc = 0; ucHifTc < TX_PORT_NUM; ucHifTc++) { + spin_lock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + if (QUEUE_IS_NOT_EMPTY(&prAdapter->rTxDirectHifQueue[ucHifTc])) { + QUEUE_MOVE_ALL(prNeedToFreeQue, &prAdapter->rTxDirectHifQueue[ucHifTc]); + spin_unlock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + + wlanProcessQueuedMsduInfo(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(prNeedToFreeQue)); + } else { + spin_unlock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + } + } +} + +VOID nicTxDirectClearStaPsQ(IN P_ADAPTER_T prAdapter, UINT_8 ucStaRecIndex) +{ + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + QUE_T rNeedToFreeQue; + P_QUE_T prNeedToFreeQue = &rNeedToFreeQue; + + QUEUE_INITIALIZE(prNeedToFreeQue); + spin_lock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + if (QUEUE_IS_NOT_EMPTY(&prAdapter->rStaPsQueue[ucStaRecIndex])) { + QUEUE_MOVE_ALL(prNeedToFreeQue, &prAdapter->rStaPsQueue[ucStaRecIndex]); + spin_unlock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + + wlanProcessQueuedMsduInfo(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(prNeedToFreeQue)); + } else { + spin_unlock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + } +} + +VOID nicTxDirectClearBssAbsentQ(IN P_ADAPTER_T prAdapter, UINT_8 ucBssIndex) +{ + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + QUE_T rNeedToFreeQue; + P_QUE_T prNeedToFreeQue = &rNeedToFreeQue; + + QUEUE_INITIALIZE(prNeedToFreeQue); + spin_lock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + if (QUEUE_IS_NOT_EMPTY(&prAdapter->rBssAbsentQueue[ucBssIndex])) { + QUEUE_MOVE_ALL(prNeedToFreeQue, &prAdapter->rBssAbsentQueue[ucBssIndex]); + spin_unlock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + + wlanProcessQueuedMsduInfo(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(prNeedToFreeQue)); + } else { + spin_unlock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + } +} + +VOID nicTxDirectClearAllStaPsQ(IN P_ADAPTER_T prAdapter) +{ + UINT_8 ucStaRecIndex; + UINT_32 u4StaPsBitmap; + + u4StaPsBitmap = prAdapter->u4StaPsBitmap; + if (!u4StaPsBitmap) + return; + + for (ucStaRecIndex = 0; ucStaRecIndex < CFG_STA_REC_NUM; ++ucStaRecIndex) { + if (QUEUE_IS_NOT_EMPTY(&prAdapter->rStaPsQueue[ucStaRecIndex])) { + nicTxDirectClearStaPsQ(prAdapter, ucStaRecIndex); + u4StaPsBitmap &= ~BIT(ucStaRecIndex); + } + if (u4StaPsBitmap == 0) + break; + } +} + +/*----------------------------------------------------------------------------*/ +/* +* \brief This function is to check the StaRec is in Ps or not, +* and store MsduInfo(s) or sent MsduInfo(s) to the next stage respectively. +* +* \param[in] prAdapter Pointer of Adapter +* \param[in] ucStaRecIndex Indictate which StaRec to be checked +* \param[in] prQue Pointer of MsduInfo queue which to be processed +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +static VOID nicTxDirectCheckStaPsQ(IN P_ADAPTER_T prAdapter, UINT_8 ucStaRecIndex, P_QUE_T prQue) +{ + P_STA_RECORD_T prStaRec; /* The current focused STA */ + P_MSDU_INFO_T prMsduInfo; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + BOOLEAN fgReturnStaPsQ = FALSE; + + if (ucStaRecIndex >= CFG_STA_REC_NUM) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIndex); + if (!prStaRec) { + DBGLOG(TX, WARN, "prStaRec is NULL!\n"); + return; + } + + QUEUE_CONCATENATE_QUEUES(&prAdapter->rStaPsQueue[ucStaRecIndex], prQue); + QUEUE_REMOVE_HEAD(&prAdapter->rStaPsQueue[ucStaRecIndex], prQueueEntry, P_QUE_ENTRY_T); + prMsduInfo = (P_MSDU_INFO_T) prQueueEntry; + + if (prMsduInfo == NULL) { + DBGLOG(TX, INFO, "prMsduInfo empty\n"); + return; + } + + if (prStaRec->fgIsInPS) { + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + DBGLOG(TX, INFO, "fgIsInPS!\n"); + while (1) { + if (prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported && + (prStaRec->ucBmpTriggerAC & BIT(prMsduInfo->ucTC))) { + if (prStaRec->ucFreeQuotaForDelivery > 0) { + prStaRec->ucFreeQuotaForDelivery--; + QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prMsduInfo); + } else { + fgReturnStaPsQ = TRUE; + break; + } + } else { + if (prStaRec->ucFreeQuotaForNonDelivery > 0) { + prStaRec->ucFreeQuotaForNonDelivery--; + QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prMsduInfo); + } else { + fgReturnStaPsQ = TRUE; + break; + } + } + if (QUEUE_IS_NOT_EMPTY(&prAdapter->rStaPsQueue[ucStaRecIndex])) { + QUEUE_REMOVE_HEAD(&prAdapter->rStaPsQueue[ucStaRecIndex], prQueueEntry, P_QUE_ENTRY_T); + prMsduInfo = (P_MSDU_INFO_T) prQueueEntry; + } else { + break; + } + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + if (fgReturnStaPsQ) { + QUEUE_INSERT_HEAD(&prAdapter->rStaPsQueue[ucStaRecIndex], (P_QUE_ENTRY_T) prMsduInfo); + prAdapter->u4StaPsBitmap |= BIT(ucStaRecIndex); + return; + } + } else { + QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prMsduInfo); + if (QUEUE_IS_NOT_EMPTY(&prAdapter->rStaPsQueue[ucStaRecIndex])) + QUEUE_CONCATENATE_QUEUES(prQue, &prAdapter->rStaPsQueue[ucStaRecIndex]); + } + prAdapter->u4StaPsBitmap &= ~BIT(ucStaRecIndex); +} + +/*----------------------------------------------------------------------------*/ +/* +* \brief This function is to check the Bss is net absent or not, +* and store MsduInfo(s) or sent MsduInfo(s) to the next stage respectively. +* +* \param[in] prAdapter Pointer of Adapter +* \param[in] ucBssIndex Indictate which Bss to be checked +* \param[in] prQue Pointer of MsduInfo queue which to be processed +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +static VOID nicTxDirectCheckBssAbsentQ(IN P_ADAPTER_T prAdapter, UINT_8 ucBssIndex, P_QUE_T prQue) +{ + P_BSS_INFO_T prBssInfo; + P_MSDU_INFO_T prMsduInfo; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + BOOLEAN fgReturnBssAbsentQ = FALSE; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + QUEUE_CONCATENATE_QUEUES(&prAdapter->rBssAbsentQueue[ucBssIndex], prQue); + QUEUE_REMOVE_HEAD(&prAdapter->rBssAbsentQueue[ucBssIndex], prQueueEntry, P_QUE_ENTRY_T); + prMsduInfo = (P_MSDU_INFO_T) prQueueEntry; + + if (prMsduInfo == NULL) { + DBGLOG(TX, INFO, "prMsduInfo empty\n"); + return; + } + + if (prBssInfo->fgIsNetAbsent) { + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + DBGLOG(TX, INFO, "fgIsNetAbsent!\n"); + while (1) { + if (prBssInfo->ucBssFreeQuota > 0) { + prBssInfo->ucBssFreeQuota--; + QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prMsduInfo); + DBGLOG(TX, INFO, "fgIsNetAbsent Quota Availalbe\n"); + } else { + fgReturnBssAbsentQ = TRUE; + DBGLOG(TX, INFO, "fgIsNetAbsent NoQuota\n"); + break; + } + if (QUEUE_IS_NOT_EMPTY(&prAdapter->rBssAbsentQueue[ucBssIndex])) { + QUEUE_REMOVE_HEAD(&prAdapter->rBssAbsentQueue[ucBssIndex], + prQueueEntry, P_QUE_ENTRY_T); + prMsduInfo = (P_MSDU_INFO_T) prQueueEntry; + } else { + break; + } + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + if (fgReturnBssAbsentQ) { + QUEUE_INSERT_HEAD(&prAdapter->rBssAbsentQueue[ucBssIndex], (P_QUE_ENTRY_T) prMsduInfo); + prAdapter->u4BssAbsentBitmap |= BIT(ucBssIndex); + return; + } + } else { + if (prAdapter->u4BssAbsentBitmap) + DBGLOG(TX, INFO, "fgIsNetAbsent END!\n"); + QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prMsduInfo); + if (QUEUE_IS_NOT_EMPTY(&prAdapter->rBssAbsentQueue[ucBssIndex])) + QUEUE_CONCATENATE_QUEUES(prQue, &prAdapter->rBssAbsentQueue[ucBssIndex]); + } + prAdapter->u4BssAbsentBitmap &= ~BIT(ucBssIndex); +} + +/*----------------------------------------------------------------------------*/ +/* +* \brief Get Tc for hif port mapping. +* +* \param[in] prMsduInfo Pointer of the MsduInfo +* +* \retval Tc which maps to hif port. +*/ +/*----------------------------------------------------------------------------*/ +static UINT_8 nicTxDirectGetHifTc(P_MSDU_INFO_T prMsduInfo) +{ + UINT_8 ucHifTc = 0; + + if (prMsduInfo->ucWmmQueSet != DBDC_5G_WMM_INDEX) { + ucHifTc = TX_2G_WMM_PORT_NUM; + } else { + if (prMsduInfo->ucTC >= 0 && prMsduInfo->ucTC < TC_NUM) + ucHifTc = prMsduInfo->ucTC; + else + ASSERT(0); + } + return ucHifTc; +} + +/*----------------------------------------------------------------------------*/ +/* +* \brief This function is called by nicTxDirectStartXmit() and nicTxDirectTimerCheckHifQ(). +* It is the main function to send skb out on HIF bus. +* +* \param[in] prSkb Pointer of the sk_buff to be sent +* \param[in] prMsduInfo Pointer of the MsduInfo +* \param[in] prAdapter Pointer of Adapter +* \param[in] ucCheckTc Indictate which Tc HifQ to be checked +* \param[in] ucStaRecIndex Indictate which StaPsQ to be checked +* \param[in] ucBssIndex Indictate which BssAbsentQ to be checked +* +* \retval WLAN_STATUS +*/ +/*----------------------------------------------------------------------------*/ +static WLAN_STATUS nicTxDirectStartXmitMain(struct sk_buff *prSkb, P_MSDU_INFO_T prMsduInfo, P_ADAPTER_T prAdapter, + UINT_8 ucCheckTc, UINT_8 ucStaRecIndex, UINT_8 ucBssIndex) +{ + P_STA_RECORD_T prStaRec; /* The current focused STA */ + P_BSS_INFO_T prBssInfo; + UINT_8 ucTC = 0, ucHifTc = 0; + P_QUE_T prTxQue; + BOOLEAN fgDropPacket = FALSE; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + QUE_T rProcessingQue; + P_QUE_T prProcessingQue = &rProcessingQue; + + QUEUE_INITIALIZE(prProcessingQue); + + if (prSkb) { + nicTxFillMsduInfo(prAdapter, prMsduInfo, prSkb); + + /* Tx profiling */ + wlanTxProfilingTagMsdu(prAdapter, prMsduInfo, TX_PROF_TAG_DRV_ENQUE); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + + if (!prBssInfo) { + /* No BSS_INFO */ + fgDropPacket = TRUE; + } else if (IS_BSS_ACTIVE(prBssInfo)) { + /* BSS active */ + fgDropPacket = FALSE; + } else { + /* BSS inactive */ + fgDropPacket = TRUE; + } + + if (fgDropPacket) { + DBGLOG(QM, TRACE, "Drop the Packet for inactive Bss %u\n", prMsduInfo->ucBssIndex); + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_31); + TX_INC_CNT(&prAdapter->rTxCtrl, TX_INACTIVE_BSS_DROP); + + wlanProcessQueuedMsduInfo(prAdapter, prMsduInfo); + return WLAN_STATUS_FAILURE; + } + + qmDetermineStaRecIndex(prAdapter, prMsduInfo); + + wlanUpdateTxStatistics(prAdapter, prMsduInfo, FALSE); /*get per-AC Tx packets */ + + switch (prMsduInfo->ucStaRecIndex) { + case STA_REC_INDEX_BMCAST: + ucTC = arNetwork2TcResource[prMsduInfo->ucBssIndex][NET_TC_BMC_INDEX]; + + /* Always set BMC packet retry limit to unlimited */ + if (!(prMsduInfo->u4Option & MSDU_OPT_MANUAL_RETRY_LIMIT)) + nicTxSetPktRetryLimit(prMsduInfo, TX_DESC_TX_COUNT_NO_LIMIT); + + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_23); + break; + case STA_REC_INDEX_NOT_FOUND: + /* Drop packet if no STA_REC is found */ + DBGLOG(QM, TRACE, "Drop the Packet for no STA_REC\n"); + + TX_INC_CNT(&prAdapter->rTxCtrl, TX_INACTIVE_STA_DROP); + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_24); + wlanProcessQueuedMsduInfo(prAdapter, prMsduInfo); + return WLAN_STATUS_FAILURE; + default: + prTxQue = qmDetermineStaTxQueue(prAdapter, prMsduInfo, &ucTC); + break; /*default */ + } /* switch (prMsduInfo->ucStaRecIndex) */ + + prMsduInfo->ucTC = ucTC; + prMsduInfo->ucWmmQueSet = prBssInfo->ucWmmQueSet; /* to record WMM Set */ + + /* Check the Tx descriptor template is valid */ + qmSetTxPacketDescTemplate(prAdapter, prMsduInfo); + + /* Set Tx rate */ + switch (prAdapter->rWifiVar.ucDataTxRateMode) { + case DATA_RATE_MODE_BSS_LOWEST: + nicTxSetPktLowestFixedRate(prAdapter, prMsduInfo); + break; + + case DATA_RATE_MODE_MANUAL: + prMsduInfo->u4FixedRateOption = prAdapter->rWifiVar.u4DataTxRateCode; + + prMsduInfo->ucRateMode = MSDU_RATE_MODE_MANUAL_DESC; + break; + + case DATA_RATE_MODE_AUTO: + default: + if (prMsduInfo->ucRateMode == MSDU_RATE_MODE_LOWEST_RATE) + nicTxSetPktLowestFixedRate(prAdapter, prMsduInfo); + break; + } + + /* BMC pkt need limited rate according to coex report*/ + if (prMsduInfo->ucStaRecIndex == STA_REC_INDEX_BMCAST) + nicTxSetPktLowestFixedRate(prAdapter, prMsduInfo); + + nicTxFillDataDesc(prAdapter, prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + QUEUE_INSERT_TAIL(prProcessingQue, (P_QUE_ENTRY_T) prMsduInfo); + + /* Power-save STA handling */ + nicTxDirectCheckStaPsQ(prAdapter, prMsduInfo->ucStaRecIndex, prProcessingQue); + + /* Absent BSS handling */ + nicTxDirectCheckBssAbsentQ(prAdapter, prMsduInfo->ucBssIndex, prProcessingQue); + + if (QUEUE_IS_EMPTY(prProcessingQue)) + return WLAN_STATUS_SUCCESS; + + if (prProcessingQue->u4NumElem != 1) { + while (1) { + QUEUE_REMOVE_HEAD(prProcessingQue, prQueueEntry, P_QUE_ENTRY_T); + if (prQueueEntry == NULL) + break; + prMsduInfo = (P_MSDU_INFO_T) prQueueEntry; + ucHifTc = nicTxDirectGetHifTc(prMsduInfo); + QUEUE_INSERT_TAIL(&prAdapter->rTxDirectHifQueue[ucHifTc], (P_QUE_ENTRY_T) prMsduInfo); + } + nicTxDirectStartCheckQTimer(prAdapter); + return WLAN_STATUS_SUCCESS; + } + + QUEUE_REMOVE_HEAD(prProcessingQue, prQueueEntry, P_QUE_ENTRY_T); + prMsduInfo = (P_MSDU_INFO_T) prQueueEntry; + ucHifTc = nicTxDirectGetHifTc(prMsduInfo); + + if (QUEUE_IS_NOT_EMPTY(&prAdapter->rTxDirectHifQueue[ucHifTc])) { + QUEUE_INSERT_TAIL(&prAdapter->rTxDirectHifQueue[ucHifTc], (P_QUE_ENTRY_T) prMsduInfo); + QUEUE_REMOVE_HEAD(&prAdapter->rTxDirectHifQueue[ucHifTc], prQueueEntry, P_QUE_ENTRY_T); + prMsduInfo = (P_MSDU_INFO_T) prQueueEntry; + } + } else { + if (ucStaRecIndex != 0xff || ucBssIndex != 0xff) { + /* Power-save STA handling */ + if (ucStaRecIndex != 0xff) + nicTxDirectCheckStaPsQ(prAdapter, ucStaRecIndex, prProcessingQue); + + /* Absent BSS handling */ + if (ucBssIndex != 0xff) + nicTxDirectCheckBssAbsentQ(prAdapter, ucBssIndex, prProcessingQue); + + if (QUEUE_IS_EMPTY(prProcessingQue)) + return WLAN_STATUS_SUCCESS; + + if (prProcessingQue->u4NumElem != 1) { + while (1) { + QUEUE_REMOVE_HEAD(prProcessingQue, prQueueEntry, P_QUE_ENTRY_T); + if (prQueueEntry == NULL) + break; + prMsduInfo = (P_MSDU_INFO_T) prQueueEntry; + ucHifTc = nicTxDirectGetHifTc(prMsduInfo); + QUEUE_INSERT_TAIL(&prAdapter->rTxDirectHifQueue[ucHifTc], + (P_QUE_ENTRY_T) prMsduInfo); + } + nicTxDirectStartCheckQTimer(prAdapter); + return WLAN_STATUS_SUCCESS; + } + + QUEUE_REMOVE_HEAD(prProcessingQue, prQueueEntry, P_QUE_ENTRY_T); + prMsduInfo = (P_MSDU_INFO_T) prQueueEntry; + ucHifTc = nicTxDirectGetHifTc(prMsduInfo); + } else { + if (ucCheckTc != 0xff) + ucHifTc = ucCheckTc; + + if (QUEUE_IS_EMPTY(&prAdapter->rTxDirectHifQueue[ucHifTc])) { + DBGLOG(TX, INFO, "ERROR: no rTxDirectHifQueue (%u)\n", ucHifTc); + return WLAN_STATUS_FAILURE; + } + QUEUE_REMOVE_HEAD(&prAdapter->rTxDirectHifQueue[ucHifTc], prQueueEntry, P_QUE_ENTRY_T); + prMsduInfo = (P_MSDU_INFO_T) prQueueEntry; + } + } + + while (1) { + if (!halTxIsDataBufEnough(prAdapter, prMsduInfo)) { + QUEUE_INSERT_HEAD(&prAdapter->rTxDirectHifQueue[ucHifTc], + (P_QUE_ENTRY_T) prMsduInfo); + mod_timer(&prAdapter->rTxDirectHifTimer, jiffies + TX_DIRECT_CHECK_INTERVAL); + + return WLAN_STATUS_SUCCESS; + } + + if (prMsduInfo->pfTxDoneHandler) { + KAL_SPIN_LOCK_DECLARATION(); + + /* Record native packet pointer for Tx done log */ + WLAN_GET_FIELD_32(&prMsduInfo->prPacket, &prMsduInfo->u4TxDoneTag); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + QUEUE_INSERT_TAIL(&(prAdapter->rTxCtrl.rTxMgmtTxingQueue), (P_QUE_ENTRY_T) prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + } + HAL_WRITE_TX_DATA(prAdapter, prMsduInfo); + + if (QUEUE_IS_NOT_EMPTY(&prAdapter->rTxDirectHifQueue[ucHifTc])) { + QUEUE_REMOVE_HEAD(&prAdapter->rTxDirectHifQueue[ucHifTc], prQueueEntry, P_QUE_ENTRY_T); + prMsduInfo = (P_MSDU_INFO_T) prQueueEntry; + } else { + break; + } + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/* +* \brief This function is the timeout function of timer rTxDirectSkbTimer. +* The purpose is to check if rTxDirectSkbQueue has any skb to be sent. +* +* \param[in] data Pointer of GlueInfo +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE +void nicTxDirectTimerCheckSkbQ(struct timer_list *timer) +#else +void nicTxDirectTimerCheckSkbQ(unsigned long data) +#endif +{ +#if KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE + struct _ADAPTER_T *prAdapter = + from_timer(prAdapter, timer, rTxDirectSkbTimer); + struct _GLUE_INFO_T *prGlueInfo = prAdapter->prGlueInfo; +#else + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)data; + P_ADAPTER_T prAdapter = prGlueInfo->prAdapter; +#endif + if (skb_queue_len(&prAdapter->rTxDirectSkbQueue)) + nicTxDirectStartXmit(NULL, prGlueInfo); + else + DBGLOG(TX, INFO, "fgHasNoMsdu FALSE\n"); +} + +/*----------------------------------------------------------------------------*/ +/* +* \brief This function is the timeout function of timer rTxDirectHifTimer. +* The purpose is to check if rStaPsQueue, rBssAbsentQueue, and rTxDirectHifQueue has any MsduInfo to be sent. +* +* \param[in] data Pointer of GlueInfo +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE +void nicTxDirectTimerCheckHifQ(struct timer_list *timer) +#else +void nicTxDirectTimerCheckHifQ(unsigned long data) +#endif +{ +#if KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE + struct _ADAPTER_T *prAdapter = + from_timer(prAdapter, timer, rTxDirectHifTimer); + struct _GLUE_INFO_T *prGlueInfo = prAdapter->prGlueInfo; +#else + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)data; + P_ADAPTER_T prAdapter = prGlueInfo->prAdapter; +#endif + UINT_8 ucHifTc = 0; + UINT_32 u4StaPsBitmap, u4BssAbsentBitmap; + UINT_8 ucStaRecIndex, ucBssIndex; + + spin_lock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + + u4StaPsBitmap = prAdapter->u4StaPsBitmap; + u4BssAbsentBitmap = prAdapter->u4BssAbsentBitmap; + + if (u4StaPsBitmap) + for (ucStaRecIndex = 0; ucStaRecIndex < CFG_STA_REC_NUM; ++ucStaRecIndex) { + if (QUEUE_IS_NOT_EMPTY(&prAdapter->rStaPsQueue[ucStaRecIndex])) { + nicTxDirectStartXmitMain(NULL, NULL, prAdapter, 0xff, ucStaRecIndex, 0xff); + u4StaPsBitmap &= ~BIT(ucStaRecIndex); + DBGLOG(TX, INFO, "ucStaRecIndex: %u\n", ucStaRecIndex); + } + if (u4StaPsBitmap == 0) + break; + } + + if (u4BssAbsentBitmap) + for (ucBssIndex = 0; ucBssIndex < HW_BSSID_NUM + 1; ++ucBssIndex) { + if (QUEUE_IS_NOT_EMPTY(&prAdapter->rBssAbsentQueue[ucBssIndex])) { + nicTxDirectStartXmitMain(NULL, NULL, prAdapter, 0xff, 0xff, ucBssIndex); + u4BssAbsentBitmap &= ~BIT(ucBssIndex); + DBGLOG(TX, INFO, "ucBssIndex: %u\n", ucBssIndex); + } + if (u4BssAbsentBitmap == 0) + break; + } + + + for (ucHifTc = 0; ucHifTc < TX_PORT_NUM; ucHifTc++) + if (QUEUE_IS_NOT_EMPTY(&prAdapter->rTxDirectHifQueue[ucHifTc])) + nicTxDirectStartXmitMain(NULL, NULL, prAdapter, ucHifTc, 0xff, 0xff); + + spin_unlock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); +} + +/*----------------------------------------------------------------------------*/ +/* +* \brief This function is have to called by kalHardStartXmit(). The purpose is +* to let as many as possible TX processing in softirq instead of in +* kernel thread to reduce TX CPU usage. +* NOTE: Currently only USB interface can use this function. +* +* \param[in] prSkb Pointer of the sk_buff to be sent +* \param[in] prGlueInfo Pointer of prGlueInfo +* +* \retval WLAN_STATUS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicTxDirectStartXmit(struct sk_buff *prSkb, P_GLUE_INFO_T prGlueInfo) +{ + P_ADAPTER_T prAdapter = prGlueInfo->prAdapter; + P_MSDU_INFO_T prMsduInfo; + WLAN_STATUS ret = WLAN_STATUS_SUCCESS; + + spin_lock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + + if (prSkb) { + prMsduInfo = cnmPktAlloc(prAdapter, 0); + + if (prMsduInfo == NULL) { + DBGLOG(TX, INFO, "cnmPktAlloc NULL\n"); + skb_queue_tail(&prAdapter->rTxDirectSkbQueue, prSkb); + + ret = WLAN_STATUS_SUCCESS; + goto end; + } + if (skb_queue_len(&prAdapter->rTxDirectSkbQueue)) { + skb_queue_tail(&prAdapter->rTxDirectSkbQueue, prSkb); + prSkb = skb_dequeue(&prAdapter->rTxDirectSkbQueue); + } + } else { + prMsduInfo = cnmPktAlloc(prAdapter, 0); + if (prMsduInfo != NULL) { + prSkb = skb_dequeue(&prAdapter->rTxDirectSkbQueue); + if (prSkb == NULL) { + DBGLOG(TX, INFO, "ERROR: no rTxDirectSkbQueue\n"); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + ret = WLAN_STATUS_FAILURE; + goto end; + } + } else { + ret = WLAN_STATUS_FAILURE; + goto end; + } + } + + while (1) { + nicTxDirectStartXmitMain(prSkb, prMsduInfo, prAdapter, 0xff, 0xff, 0xff); + prSkb = skb_dequeue(&prAdapter->rTxDirectSkbQueue); + if (prSkb != NULL) { + prMsduInfo = cnmPktAlloc(prAdapter, 0); + if (prMsduInfo == NULL) { + skb_queue_head(&prAdapter->rTxDirectSkbQueue, prSkb); + break; + } + } else { + break; + } + } + +end: + if (skb_queue_len(&prAdapter->rTxDirectSkbQueue)) + mod_timer(&prAdapter->rTxDirectSkbTimer, jiffies + TX_DIRECT_CHECK_INTERVAL); + spin_unlock_bh(&prGlueInfo->rSpinLock[SPIN_LOCK_TX_DIRECT]); + return ret; +} +/* TX Direct functions : END */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic_umac.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic_umac.c new file mode 100644 index 0000000000000..5ddfda3d355c9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/nic_umac.c @@ -0,0 +1,390 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_umac.c#5 +*/ + +/*! \file nic_umac.c +* \brief Functions that used for debug UMAC +* +* This file includes the functions used do umac debug +* +*/ + +/******************************************************************************* +* C O M P I L E 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 "que_mgt.h" + +#ifndef LINUX +#include +#else +#include +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef struct _UMAC_PG_INFO_AND_RESERVE_CNT_CR_OFFSET_MAP_T { + UINT_8 ucGroupID; + UINT_32 u4PgReservePageCntRegOffset; + UINT_32 u4PgInfoRegOffset; +} UMAC_PG_INFO_AND_RESERVE_CNT_CR_OFFSET_MAP_T, *P_UMAC_PG_INFO_AND_RESERVE_CNT_CR_OFFSET_MAP_T; + +typedef struct _UMAC_PG_MAX_MIN_QUOTA_SET_T { + UINT_8 ucPageGroupID; + UINT_16 u2MaxPageQuota; + UINT_16 u2MinPageQuota; +} UMAC_PG_MAX_MIN_QUOTA_SET_T, *P_UMAC_PG_MAX_MIN_QUOTA_SET_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +const UMAC_PG_INFO_AND_RESERVE_CNT_CR_OFFSET_MAP_T g_arPlePgInfoAndReserveCrOffsetMap[] = { + { UMAC_PG_HIF0_GROUP_0, + UMAC_PG_HIF0_GROUP(UMAC_PLE_CFG_POOL_INDEX), + UMAC_HIF0_PG_INFO(UMAC_PLE_CFG_POOL_INDEX) }, + { UMAC_PG_HIF0_GROUP_0, + UMAC_PG_HIF0_GROUP(UMAC_PLE_CFG_POOL_INDEX), + UMAC_HIF0_PG_INFO(UMAC_PLE_CFG_POOL_INDEX) }, + { UMAC_PG_CPU_GROUP_2, + UMAC_PG_CPU_GROUP(UMAC_PLE_CFG_POOL_INDEX), + UMAC_CPU_PG_INFO(UMAC_PLE_CFG_POOL_INDEX) }, +}; + +const UMAC_PG_INFO_AND_RESERVE_CNT_CR_OFFSET_MAP_T g_arPsePgInfoAndReserveCrOffsetMap[] = { + { UMAC_PG_HIF0_GROUP_0, + UMAC_PG_HIF0_GROUP(UMAC_PSE_CFG_POOL_INDEX), + UMAC_HIF0_PG_INFO(UMAC_PSE_CFG_POOL_INDEX) }, + { UMAC_PG_HIF1_GROUP_1, + UMAC_PG_HIF1_GROUP(UMAC_PSE_CFG_POOL_INDEX), + UMAC_HIF1_PG_INFO(UMAC_PSE_CFG_POOL_INDEX) }, + { UMAC_PG_CPU_GROUP_2, + UMAC_PG_CPU_GROUP(UMAC_PSE_CFG_POOL_INDEX), + UMAC_CPU_PG_INFO(UMAC_PSE_CFG_POOL_INDEX) }, + { UMAC_PG_LMAC0_GROUP_3, + UMAC_PG_LMAC0_GROUP(UMAC_PSE_CFG_POOL_INDEX), + UMAC_LMAC0_PG_INFO(UMAC_PSE_CFG_POOL_INDEX) }, + { UMAC_PG_LMAC1_GROUP_4, + UMAC_PG_LMAC1_GROUP(UMAC_PSE_CFG_POOL_INDEX), + UMAC_LMAC1_PG_INFO(UMAC_PSE_CFG_POOL_INDEX) }, + { UMAC_PG_LMAC2_GROUP_5, + UMAC_PG_LMAC2_GROUP(UMAC_PSE_CFG_POOL_INDEX), + UMAC_LMAC2_PG_INFO(UMAC_PSE_CFG_POOL_INDEX) }, + { UMAC_PG_PLE_GROUP_6, + UMAC_PG_PLE_GROUP(UMAC_PSE_CFG_POOL_INDEX), + UMAC_PLE_PG_INFO(UMAC_PSE_CFG_POOL_INDEX) }, +}; + +/******************************************************************************* +* M A 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 halUmacWrapSourcePortSanityCheck: +* +* @param IN BOOLEAN fgPsePleFlag, +* IN UINT_8 ucPageGroupID +* @return TRUE/FALSE +*/ +/*----------------------------------------------------------------------------*/ + +OUT BOOLEAN halUmacWrapSourcePortSanityCheck(IN BOOLEAN fgPsePleFlag, IN UINT_8 ucPageGroupID) +{ + + if (fgPsePleFlag == UMAC_PSE_CFG_POOL_INDEX) { + if (ucPageGroupID > UMAC_PG_PLE_GROUP_6) + return FALSE; + } else if (fgPsePleFlag == UMAC_PLE_CFG_POOL_INDEX) { + if ((ucPageGroupID != UMAC_PG_HIF0_GROUP_0) && (ucPageGroupID != UMAC_PG_CPU_GROUP_2)) + return FALSE; + } else + return FALSE; + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief halUmacWrapRsvPgCnt: +* +* @param IN P_ADAPTER_T prAdapter +* IN BOOLEAN fgPsePleFlag, +* IN UINT_8 ucPageGroupID +* @return UINT_16 +*/ +/*----------------------------------------------------------------------------*/ + +OUT UINT_16 halUmacWrapRsvPgCnt(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgPsePleFlag, IN UINT_8 ucPageGroupID) +{ + UINT_32 u4RegAddr = 0; + UINT_32 u4Value = 0; + + if (halUmacWrapSourcePortSanityCheck(fgPsePleFlag, ucPageGroupID) == FALSE) + return UMAC_FID_FAULT; + + if (fgPsePleFlag == UMAC_PSE_CFG_POOL_INDEX) + u4RegAddr = g_arPsePgInfoAndReserveCrOffsetMap[ucPageGroupID].u4PgInfoRegOffset; + else if (fgPsePleFlag == UMAC_PLE_CFG_POOL_INDEX) + u4RegAddr = g_arPlePgInfoAndReserveCrOffsetMap[ucPageGroupID].u4PgInfoRegOffset; + + HAL_MCR_RD(prAdapter, u4RegAddr, &u4Value); + + return (UINT_16) (u4Value & BITS(0, 11)); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief halUmacWrapSrcPgCnt: +* +* @param IN P_ADAPTER_T prAdapter +* IN BOOLEAN fgPsePleFlag, +* IN UINT_8 ucPageGroupID +* @return UINT_16 +*/ +/*----------------------------------------------------------------------------*/ + +OUT UINT_16 halUmacWrapSrcPgCnt(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgPsePleFlag, IN UINT_8 ucPageGroupID) +{ + UINT_32 u4RegAddr = 0; + UINT_32 u4Value = 0; + + if (halUmacWrapSourcePortSanityCheck(fgPsePleFlag, ucPageGroupID) == FALSE) + return UMAC_FID_FAULT; + + if (fgPsePleFlag == UMAC_PSE_CFG_POOL_INDEX) + u4RegAddr = g_arPsePgInfoAndReserveCrOffsetMap[ucPageGroupID].u4PgInfoRegOffset; + else if (fgPsePleFlag == UMAC_PLE_CFG_POOL_INDEX) + u4RegAddr = g_arPlePgInfoAndReserveCrOffsetMap[ucPageGroupID].u4PgInfoRegOffset; + + HAL_MCR_RD(prAdapter, u4RegAddr, &u4Value); + + return (UINT_16) ((u4Value & BITS(16, 27)) >> 16); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief halUmacPbufCtrlTotalPageNum: +* +* @param IN P_ADAPTER_T prAdapter +* IN BOOLEAN fgPsePleFlag, +* @return UINT_16 +*/ +/*----------------------------------------------------------------------------*/ + +OUT UINT_16 halUmacPbufCtrlTotalPageNum(IN P_ADAPTER_T prAdapter, IN UINT_16 fgPsePleFlag) +{ + UINT_32 u4Value = 0; + + HAL_MCR_RD(prAdapter, UMAC_PBUF_CTRL(fgPsePleFlag), &u4Value); + + return (UINT_16) (u4Value & UMAC_PBUF_CTRL_TOTAL_PAGE_NUM_MASK); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief halUmacWrapFrePageCnt: +* +* @param IN P_ADAPTER_T prAdapter +* IN BOOLEAN fgPsePleFlag, +* @return UINT_16 +*/ +/*----------------------------------------------------------------------------*/ + +OUT UINT_16 halUmacWrapFrePageCnt(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgPsePleFlag) +{ + UINT_32 u4Value = 0; + + HAL_MCR_RD(prAdapter, UMAC_FREEPG_CNT(fgPsePleFlag), &u4Value); + return (u4Value & UMAC_FREEPG_CNT_FREEPAGE_CNT_MASK) >> UMAC_FREEPG_CNT_FREEPAGE_CNT_OFFSET; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief halUmacWrapFfaCnt: +* +* @param IN P_ADAPTER_T prAdapter +* IN BOOLEAN fgPsePleFlag, +* @return UINT_16 +*/ +/*----------------------------------------------------------------------------*/ + +OUT UINT_16 halUmacWrapFfaCnt(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgPsePleFlag) +{ + UINT_32 u4Value = 0; + + HAL_MCR_RD(prAdapter, UMAC_FREEPG_CNT(fgPsePleFlag), &u4Value); + return (u4Value & UMAC_FREEPG_CNT_FFA_CNT_MASK) >> UMAC_FREEPG_CNT_FFA_CNT_OFFSET; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief halUmacInfoGetMiscStatus: +* +* @param IN P_ADAPTER_T prAdapter +* IN P_UMAC_STAT2_GET_T pUmacStat2Get, +* @return UINT_16 +*/ +/*----------------------------------------------------------------------------*/ + + +OUT BOOLEAN halUmacInfoGetMiscStatus(IN P_ADAPTER_T prAdapter, IN P_UMAC_STAT2_GET_T pUmacStat2Get) +{ + pUmacStat2Get->u2PleRevPgHif0Group0 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PLE_CFG_POOL_INDEX, UMAC_PG_HIF0_GROUP_0); + + pUmacStat2Get->u2PleRevPgCpuGroup2 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PLE_CFG_POOL_INDEX, UMAC_PG_CPU_GROUP_2); + + pUmacStat2Get->u2PseRevPgHif0Group0 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, UMAC_PG_HIF0_GROUP_0); + + pUmacStat2Get->u2PseRevPgHif1Group1 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, UMAC_PG_HIF1_GROUP_1); + + pUmacStat2Get->u2PseRevPgCpuGroup2 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, UMAC_PG_CPU_GROUP_2); + + pUmacStat2Get->u2PseRevPgLmac0Group3 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, UMAC_PG_LMAC0_GROUP_3); + + pUmacStat2Get->u2PseRevPgLmac1Group4 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, UMAC_PG_LMAC1_GROUP_4); + + pUmacStat2Get->u2PseRevPgLmac2Group5 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, UMAC_PG_LMAC2_GROUP_5); + + pUmacStat2Get->u2PseRevPgPleGroup6 = + halUmacWrapRsvPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, UMAC_PG_PLE_GROUP_6); + + pUmacStat2Get->u2PleSrvPgHif0Group0 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PLE_CFG_POOL_INDEX, UMAC_PG_HIF0_GROUP_0); + + pUmacStat2Get->u2PleSrvPgCpuGroup2 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PLE_CFG_POOL_INDEX, UMAC_PG_CPU_GROUP_2); + + pUmacStat2Get->u2PseSrvPgHif0Group0 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, UMAC_PG_HIF0_GROUP_0); + + pUmacStat2Get->u2PseSrvPgHif1Group1 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, UMAC_PG_HIF1_GROUP_1); + + pUmacStat2Get->u2PseSrvPgCpuGroup2 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, UMAC_PG_CPU_GROUP_2); + + pUmacStat2Get->u2PseSrvPgLmac0Group3 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, UMAC_PG_LMAC0_GROUP_3); + + pUmacStat2Get->u2PseSrvPgLmac1Group4 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, UMAC_PG_LMAC1_GROUP_4); + + pUmacStat2Get->u2PseSrvPgLmac2Group5 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, UMAC_PG_LMAC2_GROUP_5); + + pUmacStat2Get->u2PseSrvPgPleGroup6 = + halUmacWrapSrcPgCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX, UMAC_PG_PLE_GROUP_6); + + + pUmacStat2Get->u2PleTotalPageNum = halUmacPbufCtrlTotalPageNum(prAdapter, UMAC_PLE_CFG_POOL_INDEX); + + pUmacStat2Get->u2PseTotalPageNum = halUmacPbufCtrlTotalPageNum(prAdapter, UMAC_PSE_CFG_POOL_INDEX); + + pUmacStat2Get->u2PleFreePageNum = halUmacWrapFrePageCnt(prAdapter, UMAC_PLE_CFG_POOL_INDEX); + + pUmacStat2Get->u2PseFreePageNum = halUmacWrapFrePageCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX); + + pUmacStat2Get->u2PleFfaNum = halUmacWrapFfaCnt(prAdapter, UMAC_PLE_CFG_POOL_INDEX); + + pUmacStat2Get->u2PseFfaNum = halUmacWrapFfaCnt(prAdapter, UMAC_PSE_CFG_POOL_INDEX); + + return TRUE; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/p2p_nic.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/p2p_nic.c new file mode 100644 index 0000000000000..5fd0a3e3cd4d2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/p2p_nic.c @@ -0,0 +1,242 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: @(#) p2p_nic.c@@ +*/ + +/*! \file p2p_nic.c +* \brief Wi-Fi Direct Functions that provide operation in NIC's (Network Interface Card) point of view. +* +* This file includes functions which unite multiple hal(Hardware) operations +* and also take the responsibility of Software Resource Management in order +* to keep the synchronization with Hardware Manipulation. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief When Probe Rsp & Beacon frame is received and decide a P2P device, +* this function will be invoked to buffer scan result +* +* @param prAdapter Pointer to the Adapter structure. +* @param prEventScanResult Pointer of EVENT_SCAN_RESULT_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxAddP2pDevice(IN P_ADAPTER_T prAdapter, + IN P_EVENT_P2P_DEV_DISCOVER_RESULT_T prP2pResult, IN PUINT_8 pucRxIEBuf, IN UINT_16 u2RxIELength) +{ + P_P2P_INFO_T prP2pInfo = (P_P2P_INFO_T) NULL; + P_EVENT_P2P_DEV_DISCOVER_RESULT_T prTargetResult = (P_EVENT_P2P_DEV_DISCOVER_RESULT_T) NULL; + UINT_32 u4Idx = 0; + BOOLEAN bUpdate = FALSE; + + PUINT_8 pucIeBuf = (PUINT_8) NULL; + UINT_16 u2IELength = 0; + UINT_8 zeroMac[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; + + ASSERT(prAdapter); + + prP2pInfo = prAdapter->prP2pInfo; + + for (u4Idx = 0; u4Idx < prP2pInfo->u4DeviceNum; u4Idx++) { + prTargetResult = &prP2pInfo->arP2pDiscoverResult[u4Idx]; + + if (EQUAL_MAC_ADDR(prTargetResult->aucDeviceAddr, prP2pResult->aucDeviceAddr)) { + bUpdate = TRUE; + + /* Backup OLD buffer result. */ + pucIeBuf = prTargetResult->pucIeBuf; + u2IELength = prTargetResult->u2IELength; + + /* Update Device Info. */ + /* zero */ + kalMemZero(prTargetResult, sizeof(EVENT_P2P_DEV_DISCOVER_RESULT_T)); + + /* then buffer */ + kalMemCopy(prTargetResult, (PVOID) prP2pResult, sizeof(EVENT_P2P_DEV_DISCOVER_RESULT_T)); + + /* See if new IE length is longer or not. */ + if ((u2RxIELength > u2IELength) && (u2IELength != 0)) { + /* Buffer is not enough. */ + u2RxIELength = u2IELength; + } else if ((u2IELength == 0) && (u2RxIELength != 0)) { + /* RX new IE buf. */ + ASSERT(pucIeBuf == NULL); + pucIeBuf = prP2pInfo->pucCurrIePtr; + + if (((ULONG) prP2pInfo->pucCurrIePtr + (ULONG) u2RxIELength) > + (ULONG)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN]) { + /* Common Buffer is no enough. */ + u2RxIELength = + (UINT_16) ((ULONG)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN] - + (ULONG) prP2pInfo->pucCurrIePtr); + } + + /* Step to next buffer address. */ + prP2pInfo->pucCurrIePtr = + (PUINT_8) ((ULONG) prP2pInfo->pucCurrIePtr + (ULONG) u2RxIELength); + } + + /* Restore buffer pointer. */ + prTargetResult->pucIeBuf = pucIeBuf; + + if (pucRxIEBuf) { + /* If new received IE is available. + * Replace the old one & update new IE length. + */ + kalMemCopy(pucIeBuf, pucRxIEBuf, u2RxIELength); + prTargetResult->u2IELength = u2RxIELength; + } else { + /* There is no new IE information, keep the old one. */ + prTargetResult->u2IELength = u2IELength; + } + } + } + + if (!bUpdate) { + /* We would flush the whole scan result after each scan request is issued. + * If P2P device is too many, it may over the scan list. + */ + if ((u4Idx < CFG_MAX_NUM_BSS_LIST) && (UNEQUAL_MAC_ADDR(zeroMac, prP2pResult->aucDeviceAddr))) { + 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 (((ULONG) prP2pInfo->pucCurrIePtr + (ULONG) u2RxIELength) > + (ULONG)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN]) { + /* Common Buffer is no enough. */ + u2IELength = + (UINT_16) ((ULONG)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN] - + (ULONG) prP2pInfo->pucCurrIePtr); + } else { + u2IELength = u2RxIELength; + } + + prP2pInfo->pucCurrIePtr = + (PUINT_8) ((ULONG) prP2pInfo->pucCurrIePtr + (ULONG) u2IELength); + + kalMemCopy((PVOID) prTargetResult->pucIeBuf, (PVOID) pucRxIEBuf, (UINT_32) u2IELength); + prTargetResult->u2IELength = u2IELength; + } else { + prTargetResult->pucIeBuf = NULL; + prTargetResult->u2IELength = 0; + } + + prP2pInfo->u4DeviceNum++; + + } else { + /* TODO: Fixme to replace an old one. (?) */ + ASSERT(FALSE); + } + } +} /* nicRxAddP2pDevice */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/que_mgt.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/que_mgt.c new file mode 100644 index 0000000000000..9e0871cb0880b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/nic/que_mgt.c @@ -0,0 +1,6281 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/que_mgt.c#3 +*/ + +/*! \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. +*/ + + +/******************************************************************************* +* C O M P I L E 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 "queue.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]; + +const UINT_8 aucTid2ACI[TX_DESC_TID_NUM] = { + WMM_AC_BE_INDEX, /* TID0 */ + WMM_AC_BK_INDEX, /* TID1 */ + WMM_AC_BK_INDEX, /* TID2 */ + WMM_AC_BE_INDEX, /* TID3 */ + WMM_AC_VI_INDEX, /* TID4 */ + WMM_AC_VI_INDEX, /* TID5 */ + WMM_AC_VO_INDEX, /* TID6 */ + WMM_AC_VO_INDEX /* TID7 */ +}; + +const UINT_8 aucACI2TxQIdx[WMM_AC_INDEX_NUM] = { + TX_QUEUE_INDEX_AC1, /* WMM_AC_BE_INDEX */ + TX_QUEUE_INDEX_AC0, /* WMM_AC_BK_INDEX */ + TX_QUEUE_INDEX_AC2, /* WMM_AC_VI_INDEX */ + TX_QUEUE_INDEX_AC3 /* WMM_AC_VO_INDEX */ +}; + +const PUINT_8 apucACI2Str[WMM_AC_INDEX_NUM] = { + "BE", "BK", "VI", "VO" +}; + +const UINT_8 arNetwork2TcResource[HW_BSSID_NUM + 1][NET_TC_NUM] = { + /* HW Queue Set 1 */ + /* AC_BE, AC_BK, AC_VI, AC_VO, MGMT, BMC */ + {TC1_INDEX, TC0_INDEX, TC2_INDEX, TC3_INDEX, TC4_INDEX, BMC_TC_INDEX}, /* AIS */ + {TC1_INDEX, TC0_INDEX, TC2_INDEX, TC3_INDEX, TC4_INDEX, BMC_TC_INDEX}, /* P2P/BoW */ + {TC1_INDEX, TC0_INDEX, TC2_INDEX, TC3_INDEX, TC4_INDEX, BMC_TC_INDEX}, /* P2P/BoW */ + {TC1_INDEX, TC0_INDEX, TC2_INDEX, TC3_INDEX, TC4_INDEX, BMC_TC_INDEX}, /* P2P/BoW */ + {TC1_INDEX, TC0_INDEX, TC2_INDEX, TC3_INDEX, TC4_INDEX, BMC_TC_INDEX}, /* P2P_DEV */ + + + /* HW Queue Set 2 */ + /* {TC7_INDEX, TC6_INDEX, TC8_INDEX, TC9_INDEX, TC4_INDEX, TC10_INDEX}, */ +}; + +const UINT_8 aucWmmAC2TcResourceSet1[WMM_AC_INDEX_NUM] = { + TC1_INDEX, + TC0_INDEX, + TC2_INDEX, + TC3_INDEX +}; + +#if NIC_TX_ENABLE_SECOND_HW_QUEUE +const UINT_8 aucWmmAC2TcResourceSet2[WMM_AC_INDEX_NUM] = { + TC7_INDEX, + TC6_INDEX, + TC8_INDEX, + TC9_INDEX +}; +#endif +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#if CFG_RX_REORDERING_ENABLED +#define qmHandleRxPackets_AOSP_1 \ +do { \ + /* ToDo[6630]: duplicate removal */ \ + if (!fgIsBMC && nicRxIsDuplicateFrame(prCurrSwRfb) == TRUE) { \ + DBGLOG(QM, TRACE, "Duplicated packet is detected\n"); \ + RX_INC_CNT(&prAdapter->rRxCtrl, RX_DUPICATE_DROP_COUNT); \ + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; \ + } \ + /* ToDo[6630]: defragmentation */ \ + if (prCurrSwRfb->fgFragFrame) { \ + prCurrSwRfb = incRxDefragMPDU(prAdapter, prCurrSwRfb, prReturnedQue); \ + if (prCurrSwRfb) { \ + prRxStatus = prCurrSwRfb->prRxStatus; \ + DBGLOG(QM, TRACE, "defragmentation RxStatus=%p\n", \ + prRxStatus); \ + } \ + } \ + if (prCurrSwRfb) { \ + fgMicErr = FALSE; \ + if (HAL_RX_STATUS_GET_SEC_MODE(prRxStatus) == CIPHER_SUITE_TKIP_WO_MIC) { \ + if (prCurrSwRfb->prStaRec) { \ + UINT_8 ucBssIndex; \ + P_BSS_INFO_T prBssInfo = NULL; \ + PUINT_8 pucMicKey = NULL; \ + ucBssIndex = prCurrSwRfb->prStaRec->ucBssIndex; \ + ASSERT(ucBssIndex < BSS_INFO_NUM); \ + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); \ + ASSERT(prBssInfo); \ + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { \ + pucMicKey = &(prAdapter->rWifiVar.rAisSpecificBssInfo.aucRxMicKey[0]); \ + prCurrSwRfb->ucTid = (UINT_8) (HAL_RX_STATUS_GET_TID(prRxStatus)); \ + } \ + else { \ + ASSERT(FALSE); \ + /* pucMicKey = &prCurrSwRfb->prStaRec->aucRxMicKey[0]; */ \ + } \ + /* SW TKIP MIC verify, adopt new function call for MIC calculation */ \ + /* TODO:[6630] Need to Check Header Translation Case */ \ + if (pucMicKey == NULL) { \ + DBGLOG(RX, ERROR, "Mark NULL the Packet for TKIP Key Error\n"); \ + fgMicErr = TRUE; \ + } \ + else if (tkipMicDecapsulateInRxHdrTransMode(prCurrSwRfb, pucMicKey) == FALSE) { \ + fgMicErr = TRUE; \ + } \ + } \ + if (fgMicErr) { \ + /* bypass tkip frag */ \ + if (!prCurrSwRfb->fgFragFrame) { \ + DBGLOG(RX, ERROR, "Mark NULL the Packet for TKIP Mic Error\n"); \ + RX_INC_CNT(&prAdapter->rRxCtrl, RX_MIC_ERROR_DROP_COUNT); \ + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; \ + } \ + } \ + } \ + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T)prCurrSwRfb); \ + } \ +} while (0) +#endif + +#define RX_DIRECT_REORDER_LOCK(pad, dbg) \ +do { \ + P_GLUE_INFO_T _glue = pad->prGlueInfo; \ + if (!HAL_IS_RX_DIRECT(pad) || !_glue) \ + break; \ + if (dbg) \ + DBGLOG(QM, EVENT, "RX_DIRECT_REORDER_LOCK %d\n", __LINE__); \ + spin_lock_bh(&_glue->rSpinLock[SPIN_LOCK_RX_DIRECT_REORDER]);\ +} while (0) + +#define RX_DIRECT_REORDER_UNLOCK(pad, dbg) \ +do { \ + P_GLUE_INFO_T _glue = pad->prGlueInfo; \ + if (!HAL_IS_RX_DIRECT(pad) || !_glue) \ + break; \ + if (dbg) \ + DBGLOG(QM, EVENT, "RX_DIRECT_REORDER_UNLOCK %u\n", __LINE__); \ + spin_unlock_bh(&_glue->rSpinLock[SPIN_LOCK_RX_DIRECT_REORDER]); \ +} while (0) + +/******************************************************************************* +* 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 Queue Management for TX +* +* \param[in] (none) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmInit(IN P_ADAPTER_T prAdapter, IN BOOLEAN isTxResrouceControlEn) +{ + UINT_32 u4Idx; +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + UINT_32 u4TotalMinReservedTcResource = 0; + UINT_32 u4TotalTcResource = 0; + UINT_32 u4TotalGurantedTcResource = 0; +#endif + + P_QUE_MGT_T prQM = &prAdapter->rQM; + + /* DbgPrint("QM: Enter qmInit()\n"); */ + + /* 4 <2> Initialize other TX queues (queues not in STA_RECs) */ + for (u4Idx = 0; u4Idx < NUM_OF_PER_TYPE_TX_QUEUES; u4Idx++) + QUEUE_INITIALIZE(&(prQM->arTxQueue[u4Idx])); + + /* 4 <3> Initialize the RX BA table and RX queues */ + /* Initialize the RX Reordering Parameters and Queues */ + for (u4Idx = 0; u4Idx < CFG_NUM_OF_RX_BA_AGREEMENTS; u4Idx++) { + prQM->arRxBaTable[u4Idx].fgIsValid = FALSE; + QUEUE_INITIALIZE(&(prQM->arRxBaTable[u4Idx].rReOrderQue)); + prQM->arRxBaTable[u4Idx].u2WinStart = 0xFFFF; + prQM->arRxBaTable[u4Idx].u2WinEnd = 0xFFFF; + + prQM->arRxBaTable[u4Idx].fgIsWaitingForPktWithSsn = FALSE; + prQM->arRxBaTable[u4Idx].fgHasBubble = FALSE; +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + prQM->arRxBaTable[u4Idx].u8LastAmsduSubIdx = RX_PAYLOAD_FORMAT_MSDU; + prQM->arRxBaTable[u4Idx].fgAmsduNeedLastFrame = FALSE; + prQM->arRxBaTable[u4Idx].fgIsAmsduDuplicated = FALSE; +#endif + prQM->arRxBaTable[u4Idx].fgFirstSnToWinStart = FALSE; + cnmTimerInitTimer(prAdapter, + &(prQM->arRxBaTable[u4Idx].rReorderBubbleTimer), + (PFN_MGMT_TIMEOUT_FUNC) qmHandleReorderBubbleTimeout, + (ULONG) (&prQM->arRxBaTable[u4Idx])); + + } + prQM->ucRxBaCount = 0; + + kalMemSet(&g_arMissTimeout, 0, sizeof(g_arMissTimeout)); + + prQM->fgIsTxResrouceControlEn = isTxResrouceControlEn; + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + /* 4 <4> Initialize TC resource control variables */ + for (u4Idx = 0; u4Idx < TC_NUM; u4Idx++) + prQM->au4AverageQueLen[u4Idx] = 0; + + ASSERT(prQM->u4TimeToAdjustTcResource && prQM->u4TimeToUpdateQueLen); + + for (u4Idx = 0; u4Idx < TC_NUM; u4Idx++) { + prQM->au4CurrentTcResource[u4Idx] = prAdapter->rTxCtrl.rTc.au4MaxNumOfBuffer[u4Idx]; + + if (u4Idx != TC4_INDEX) { + u4TotalTcResource += prQM->au4CurrentTcResource[u4Idx]; + u4TotalGurantedTcResource += prQM->au4GuaranteedTcResource[u4Idx]; + u4TotalMinReservedTcResource += prQM->au4MinReservedTcResource[u4Idx]; + } + } + + /* Sanity Check */ + if (u4TotalMinReservedTcResource > u4TotalTcResource) + kalMemZero(prQM->au4MinReservedTcResource, sizeof(prQM->au4MinReservedTcResource)); + + if (u4TotalGurantedTcResource > u4TotalTcResource) + kalMemZero(prQM->au4GuaranteedTcResource, sizeof(prQM->au4GuaranteedTcResource)); + + u4TotalGurantedTcResource = 0; + + /* Initialize Residual TC resource */ + for (u4Idx = 0; u4Idx < TC_NUM; u4Idx++) { + if (prQM->au4GuaranteedTcResource[u4Idx] < prQM->au4MinReservedTcResource[u4Idx]) + prQM->au4GuaranteedTcResource[u4Idx] = prQM->au4MinReservedTcResource[u4Idx]; + + if (u4Idx != TC4_INDEX) + u4TotalGurantedTcResource += prQM->au4GuaranteedTcResource[u4Idx]; + } + + prQM->u4ResidualTcResource = u4TotalTcResource - u4TotalGurantedTcResource; + + prQM->fgTcResourcePostAnnealing = FALSE; + +#if QM_FAST_TC_RESOURCE_CTRL + prQM->fgTcResourceFastReaction = FALSE; +#endif + +#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->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + COPY_MAC_ADDR((prStaRec)->aucMacAddr, aucMacAddr); + + } + +#endif + +#endif + +#if QM_FORWARDING_FAIRNESS + for (u4Idx = 0; u4Idx < NUM_OF_PER_STA_TX_QUEUES; u4Idx++) { + prQM->au4ResourceUsedCount[u4Idx] = 0; + prQM->au4HeadStaRecIndex[u4Idx] = 0; + } + + prQM->u4GlobalResourceUsedCount = 0; +#endif + + prQM->u4TxAllowedStaCount = 0; + + prQM->rLastTxPktDumpTime = (OS_SYSTIME) kalGetTimeTick(); + +} + +#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, &prAdapter->arStaRec[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 Update a STA_REC +* +* \param[in] prAdapter Pointer to the Adapter instance +* \param[in] prStaRec The pointer of the STA_REC +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmUpdateStaRec(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + P_BSS_INFO_T prBssInfo; + BOOLEAN fgIsTxAllowed = FALSE; + + if (!prStaRec) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + /* 4 <1> Ensure STA is valid */ + if (prStaRec->fgIsValid) { + /* 4 <2.1> STA/BSS is protected */ + if (secIsProtectedBss(prAdapter, prBssInfo)) { + if (prStaRec->fgIsTxKeyReady) + fgIsTxAllowed = TRUE; + else /* whsu test for 1x */ + fgIsTxAllowed = FALSE; + } + /* 4 <2.2> OPEN security */ + else + fgIsTxAllowed = TRUE; + } + /* 4 Update StaRec */ + qmSetStaRecTxAllowed(prAdapter, prStaRec, fgIsTxAllowed); + +#if CFG_SUPPORT_BFER + if ((IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaVhtBfer) || + IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaHtBfer)) && + prAdapter->fgIsHwSupportBfer && fgIsTxAllowed && + (prStaRec->ucStaState == STA_STATE_3)) { + rlmBfStaRecPfmuUpdate(prAdapter, prStaRec); + rlmETxBfTriggerPeriodicSounding(prAdapter); + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Activate a STA_REC +* +* \param[in] prAdapter Pointer to the Adapter instance +* \param[in] prStaRec The pointer of the STA_REC +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmActivateStaRec(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + /* 4 <1> Deactivate first */ + if (!prStaRec) + return; + + 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); /* To flush TX/RX queues and del RX BA agreements */ + } + /* 4 <2> Activate the STA_REC */ + /* Reset buffer count */ + prStaRec->ucFreeQuota = 0; + prStaRec->ucFreeQuotaForDelivery = 0; + prStaRec->ucFreeQuotaForNonDelivery = 0; + + /* Init the STA_REC */ + prStaRec->fgIsValid = TRUE; + prStaRec->fgIsInPS = FALSE; + + /* Default setting of TX/RX AMPDU */ + prStaRec->fgTxAmpduEn = IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucAmpduTx); + prStaRec->fgRxAmpduEn = IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucAmpduRx); + + nicTxGenerateDescTemplate(prAdapter, prStaRec); + + qmUpdateStaRec(prAdapter, prStaRec); + + /* 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[%d]\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 P_STA_RECORD_T prStaRec) +{ + UINT_32 i; + + if (!prStaRec) + return; + /* 4 <1> Flush TX queues */ + if (HAL_IS_TX_DIRECT(prAdapter)) { + nicTxDirectClearStaPsQ(prAdapter, prStaRec->ucIndex); + } else { + P_MSDU_INFO_T prFlushedTxPacketList = NULL; + + prFlushedTxPacketList = qmFlushStaTxQueues(prAdapter, prStaRec->ucIndex); + + 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, prStaRec->ucIndex, (UINT_8) i, FALSE); + } + + /* 4 <3> Deactivate the STA_REC */ + prStaRec->fgIsValid = FALSE; + prStaRec->fgIsInPS = FALSE; + prStaRec->fgIsTxKeyReady = FALSE; + + /* Reset buffer count */ + prStaRec->ucFreeQuota = 0; + prStaRec->ucFreeQuotaForDelivery = 0; + prStaRec->ucFreeQuotaForNonDelivery = 0; + + nicTxFreeDescTemplate(prAdapter, prStaRec); + + qmUpdateStaRec(prAdapter, prStaRec); + + DBGLOG(QM, INFO, "QM: -STA[%u]\n", prStaRec->ucIndex); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Deactivate a STA_REC +* +* \param[in] prAdapter Pointer to the Adapter instance +* \param[in] ucBssIndex The index of the BSS +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmFreeAllByBssIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex) +{ + + 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->ucBssIndex == ucBssIndex) { + /* QUEUE_INSERT_TAIL */ + QUEUE_INSERT_TAIL(prNeedToFreeQue, (P_QUE_ENTRY_T) prMsduInfo); + } else { + /* QUEUE_INSERT_TAIL */ + QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prMsduInfo); + } + + QUEUE_REMOVE_HEAD(prTempQue, prMsduInfo, P_MSDU_INFO_T); + } + if (QUEUE_IS_NOT_EMPTY(prNeedToFreeQue)) + wlanProcessQueuedMsduInfo(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(prNeedToFreeQue)); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Flush all TX queues +* +* \param[in] (none) +* +* \return The flushed packets (in a list of MSDU_INFOs) +*/ +/*----------------------------------------------------------------------------*/ +P_MSDU_INFO_T qmFlushTxQueues(IN P_ADAPTER_T prAdapter) +{ + UINT_8 ucStaArrayIdx; + UINT_8 ucQueArrayIdx; + + P_QUE_MGT_T prQM = &prAdapter->rQM; + + QUE_T rTempQue; + P_QUE_T prTempQue = &rTempQue; + P_QUE_T prQue; + + DBGLOG(QM, TRACE, "QM: Enter qmFlushTxQueues()\n"); + + QUEUE_INITIALIZE(prTempQue); + + /* Concatenate all MSDU_INFOs in per-STA queues */ + for (ucStaArrayIdx = 0; ucStaArrayIdx < CFG_STA_REC_NUM; ucStaArrayIdx++) { + for (ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_STA_TX_QUEUES; ucQueArrayIdx++) { + prQue = &(prAdapter->arStaRec[ucStaArrayIdx].arPendingTxQueue[ucQueArrayIdx]); + QUEUE_CONCATENATE_QUEUES(prTempQue, prQue); + prQue = &(prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]); + QUEUE_CONCATENATE_QUEUES(prTempQue, prQue); + } + } + + /* Flush per-Type queues */ + for (ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_TYPE_TX_QUEUES; ucQueArrayIdx++) { + prQue = &(prQM->arTxQueue[ucQueArrayIdx]); + QUEUE_CONCATENATE_QUEUES(prTempQue, prQue); + } + + return (P_MSDU_INFO_T)QUEUE_GET_HEAD(prTempQue); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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_STA_RECORD_T prStaRec; + P_QUE_T prQue; + QUE_T rTempQue; + P_QUE_T prTempQue = &rTempQue; + + DBGLOG(QM, TRACE, "QM: Enter qmFlushStaTxQueues(%u)\n", u4StaRecIdx); + + ASSERT(u4StaRecIdx < CFG_STA_REC_NUM); + + prStaRec = &prAdapter->arStaRec[u4StaRecIdx]; + ASSERT(prStaRec); + + QUEUE_INITIALIZE(prTempQue); + + /* Concatenate all MSDU_INFOs in TX queues of this STA_REC */ + for (ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_STA_TX_QUEUES; ucQueArrayIdx++) { + prQue = &(prStaRec->arPendingTxQueue[ucQueArrayIdx]); + QUEUE_CONCATENATE_QUEUES(prTempQue, prQue); + prQue = &(prStaRec->arTxQueue[ucQueArrayIdx]); + QUEUE_CONCATENATE_QUEUES(prTempQue, prQue); + } + + return (P_MSDU_INFO_T)QUEUE_GET_HEAD(prTempQue); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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"); + + RX_DIRECT_REORDER_LOCK(prAdapter, 0); + 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)); + if (QM_RX_GET_NEXT_SW_RFB(prSwRfbListTail)) { + DBGLOG(QM, ERROR, + "QM: non-null tail->next at arRxBaTable[%u]\n", + i); + } + } else { + continue; + } + } + RX_DIRECT_REORDER_UNLOCK(prAdapter, 0); + + if (prSwRfbListTail) { + /* Terminate the MSDU_INFO list with a NULL pointer */ + QM_TX_SET_NEXT_SW_RFB(prSwRfbListTail, NULL); + } + return prSwRfbListHead; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Flush RX packets with respect to a particular STA +* +* \param[in] u4StaRecIdx STA_REC index +* \param[in] u4Tid TID +* +* \return The flushed packets (in a list of SW_RFBs) +*/ +/*----------------------------------------------------------------------------*/ +P_SW_RFB_T qmFlushStaRxQueue(IN P_ADAPTER_T prAdapter, IN UINT_32 u4StaRecIdx, IN UINT_32 u4Tid) +{ + /* UINT_32 i; */ + P_SW_RFB_T prSwRfbListHead; + P_SW_RFB_T prSwRfbListTail; + P_RX_BA_ENTRY_T prReorderQueParm; + P_STA_RECORD_T prStaRec; + + DBGLOG(QM, TRACE, "QM: Enter qmFlushStaRxQueues(%u)\n", u4StaRecIdx); + + prSwRfbListHead = prSwRfbListTail = NULL; + + prStaRec = &prAdapter->arStaRec[u4StaRecIdx]; + ASSERT(prStaRec); + + /* No matter whether this is an activated STA_REC, do flush */ +#if 0 + if (!prStaRec->fgIsValid) + return NULL; +#endif + + /* Obtain the RX BA Entry pointer */ + prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[u4Tid]); + + /* Note: For each queued packet, prCurrSwRfb->eDst equals RX_PKT_DESTINATION_HOST */ + if (prReorderQueParm) { + RX_DIRECT_REORDER_LOCK(prAdapter, 0); + 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)); + } + RX_DIRECT_REORDER_UNLOCK(prAdapter, 0); + } + + if (prSwRfbListTail) { + if (QM_RX_GET_NEXT_SW_RFB(prSwRfbListTail)) { + DBGLOG(QM, ERROR, + "QM: non-empty tail->next at STA %u TID %u\n", + u4StaRecIdx, u4Tid); + } + + /* Terminate the MSDU_INFO list with a NULL pointer */ + QM_TX_SET_NEXT_SW_RFB(prSwRfbListTail, NULL); + } + return prSwRfbListHead; + +} + +P_QUE_T qmDetermineStaTxQueue(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, OUT PUINT_8 pucTC) +{ + P_QUE_T prTxQue = NULL; + P_STA_RECORD_T prStaRec; + ENUM_WMM_ACI_T eAci = WMM_AC_BE_INDEX; + BOOLEAN fgCheckACMAgain; + UINT_8 ucTC, ucQueIdx = WMM_AC_BE_INDEX; + P_BSS_INFO_T prBssInfo; + UINT_8 aucNextUP[WMM_AC_INDEX_NUM] = { 1 /* BEtoBK */, + 1 /* na */, + 0 /* VItoBE */, + 4 /* VOtoVI */ + }; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prMsduInfo->ucStaRecIndex); + + if (!prStaRec) { + DBGLOG(QM, ERROR, "prStaRec is null.\n"); + return NULL; + } + if (prMsduInfo->ucUserPriority < 8) { + QM_DBG_CNT_INC(&prAdapter->rQM, prMsduInfo->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) { + if (prMsduInfo->ucUserPriority < TX_DESC_TID_NUM) { + eAci = aucTid2ACI[prMsduInfo->ucUserPriority]; + ucQueIdx = aucACI2TxQIdx[eAci]; + ucTC = arNetwork2TcResource[prMsduInfo->ucBssIndex][eAci]; + } else { + ucQueIdx = TX_QUEUE_INDEX_AC1; + ucTC = TC1_INDEX; + eAci = WMM_AC_BE_INDEX; + DBGLOG(QM, WARN, "Packet TID is not in [0~7]\n"); + ASSERT(0); + } + if ((prBssInfo->arACQueParms[eAci].ucIsACMSet) && (eAci != WMM_AC_BK_INDEX)) { + prMsduInfo->ucUserPriority = aucNextUP[eAci]; + fgCheckACMAgain = TRUE; + } + } else { + ucQueIdx = TX_QUEUE_INDEX_NON_QOS; + ucTC = arNetwork2TcResource[prMsduInfo->ucBssIndex][NET_TC_WMM_AC_BE_INDEX]; + } + + if (prAdapter->rWifiVar.ucTcRestrict < TC_NUM) { + ucTC = prAdapter->rWifiVar.ucTcRestrict; + ucQueIdx = ucTC; + } + + } while (fgCheckACMAgain); + + if (ucQueIdx >= NUM_OF_PER_STA_TX_QUEUES) { + DBGLOG(QM, ERROR, + "ucQueIdx = %u, needs 0~3 to avoid out-of-bounds.\n", ucQueIdx); + return NULL; + } + if (prStaRec->fgIsTxAllowed) { + /* non protected BSS or protected BSS with key set */ + prTxQue = prStaRec->aprTargetQueue[ucQueIdx]; + } else if (secIsProtectedBss(prAdapter, prBssInfo) && prMsduInfo->fgIs802_1x + && prMsduInfo->fgIs802_1x_NonProtected) { + /* protected BSS without key set */ + /* Tx pairwise EAPOL 1x packet (non-protected frame) */ + prTxQue = &prStaRec->arTxQueue[ucQueIdx]; + } else { + /* protected BSS without key set */ + /* Enqueue protected frame into pending queue */ + prTxQue = prStaRec->aprTargetQueue[ucQueIdx]; + } + + *pucTC = ucTC; + + return prTxQue; +} + +VOID qmSetTxPacketDescTemplate(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_STA_RECORD_T prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prMsduInfo->ucStaRecIndex); + + /* Check the Tx descriptor template is valid */ + if (prStaRec && prStaRec->aprTxDescTemplate[prMsduInfo->ucUserPriority]) { + prMsduInfo->fgIsTXDTemplateValid = TRUE; + } else { + if (prStaRec) { + DBGLOG(QM, TRACE, + "Cannot get TXD template for STA[%u] QoS[%u] MSDU UP[%u]\n", + prStaRec->ucIndex, prStaRec->fgIsQoS, prMsduInfo->ucUserPriority); + } + prMsduInfo->fgIsTXDTemplateValid = FALSE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief : To StaRec, function to stop TX +* +* \param[in] : +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID qmSetStaRecTxAllowed(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN BOOLEAN fgIsTxAllowed) +{ + UINT_8 ucIdx; + P_QUE_T prSrcQ, prDstQ; + + /* Update Tx queue */ + for (ucIdx = 0; ucIdx < NUM_OF_PER_STA_TX_QUEUES; ucIdx++) { + if (fgIsTxAllowed) { + prSrcQ = &prStaRec->arPendingTxQueue[ucIdx]; + prDstQ = &prStaRec->arTxQueue[ucIdx]; + } else { + prSrcQ = &prStaRec->arTxQueue[ucIdx]; + prDstQ = &prStaRec->arPendingTxQueue[ucIdx]; + } + + QUEUE_CONCATENATE_QUEUES_HEAD(prDstQ, prSrcQ); + prStaRec->aprTargetQueue[ucIdx] = prDstQ; + } + + if (prStaRec->fgIsTxAllowed != fgIsTxAllowed) { + if (fgIsTxAllowed) + prAdapter->rQM.u4TxAllowedStaCount++; + else + prAdapter->rQM.u4TxAllowedStaCount--; + } + prStaRec->fgIsTxAllowed = fgIsTxAllowed; + + DBGLOG(QM, INFO, "Set Sta[%u] TxAllowed[%u] %s TxQ\n", prStaRec->ucIndex, fgIsTxAllowed, + fgIsTxAllowed ? "normal":"pending"); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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_QUE_T prTxQue; + QUE_T rNotEnqueuedQue; + + UINT_8 ucTC; + P_QUE_MGT_T prQM = &prAdapter->rQM; + P_BSS_INFO_T prBssInfo; + BOOLEAN fgDropPacket; + + DBGLOG(QM, LOUD, "Enter qmEnqueueTxPackets\n"); + + ASSERT(prMsduInfoListHead); + + prMsduInfoReleaseList = NULL; + prCurrentMsduInfo = NULL; + QUEUE_INITIALIZE(&rNotEnqueuedQue); + prNextMsduInfo = prMsduInfoListHead; + + do { + prCurrentMsduInfo = prNextMsduInfo; + prNextMsduInfo = QM_TX_GET_NEXT_MSDU_INFO(prCurrentMsduInfo); + ucTC = TC1_INDEX; + + /* 4 <0> Sanity check of BSS_INFO */ + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prCurrentMsduInfo->ucBssIndex); + + if (!prBssInfo) { + /* No BSS_INFO */ + fgDropPacket = TRUE; + } else if (IS_BSS_ACTIVE(prBssInfo)) { + /* BSS active */ + fgDropPacket = FALSE; + } else { + /* BSS inactive */ + fgDropPacket = TRUE; + } + + if (!fgDropPacket) { + /* 4 <1> Lookup the STA_REC index */ + /* The ucStaRecIndex will be set in this function */ + qmDetermineStaRecIndex(prAdapter, prCurrentMsduInfo); + + wlanUpdateTxStatistics(prAdapter, prCurrentMsduInfo, FALSE); /*get per-AC Tx packets */ + + DBGLOG(QM, LOUD, "Enqueue MSDU by StaRec[%u]!\n", prCurrentMsduInfo->ucStaRecIndex); + + switch (prCurrentMsduInfo->ucStaRecIndex) { + case STA_REC_INDEX_BMCAST: + prTxQue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST]; + ucTC = arNetwork2TcResource[prCurrentMsduInfo->ucBssIndex][NET_TC_BMC_INDEX]; + + /* Always set BMC packet retry limit to unlimited */ + if (!(prCurrentMsduInfo->u4Option & MSDU_OPT_MANUAL_RETRY_LIMIT)) + nicTxSetPktRetryLimit(prCurrentMsduInfo, TX_DESC_TX_COUNT_NO_LIMIT); + + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_23); + break; + + case STA_REC_INDEX_NOT_FOUND: + /* Drop packet if no STA_REC is found */ + DBGLOG(QM, TRACE, "Drop the Packet for no STA_REC\n"); + + prTxQue = &rNotEnqueuedQue; + + TX_INC_CNT(&prAdapter->rTxCtrl, TX_INACTIVE_STA_DROP); + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_24); + break; + + default: + prTxQue = qmDetermineStaTxQueue(prAdapter, prCurrentMsduInfo, &ucTC); + break; /*default */ + } /* switch (prCurrentMsduInfo->ucStaRecIndex) */ + + if (prCurrentMsduInfo->eSrc == TX_PACKET_FORWARDING) { + DBGLOG(QM, TRACE, "Forward Pkt to STA[%u] BSS[%u]\n", + prCurrentMsduInfo->ucStaRecIndex, prCurrentMsduInfo->ucBssIndex); + + if (prTxQue->u4NumElem >= prQM->u4MaxForwardBufferCount) { + DBGLOG(QM, INFO, + "Drop the Packet for full Tx queue (forwarding) Bss %u\n", + prCurrentMsduInfo->ucBssIndex); + prTxQue = &rNotEnqueuedQue; + TX_INC_CNT(&prAdapter->rTxCtrl, TX_FORWARD_OVERFLOW_DROP); + } + } + + } else { + DBGLOG(QM, TRACE, "Drop the Packet for inactive Bss %u\n", prCurrentMsduInfo->ucBssIndex); + 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 */ + /* Note that the BSS Index and STA_REC index are determined in + * qmDetermineStaRecIndex(prCurrentMsduInfo). + */ + prCurrentMsduInfo->ucTC = ucTC; + + /* Check the Tx descriptor template is valid */ + qmSetTxPacketDescTemplate(prAdapter, prCurrentMsduInfo); + + /* Set Tx rate */ + switch (prAdapter->rWifiVar.ucDataTxRateMode) { + case DATA_RATE_MODE_BSS_LOWEST: + nicTxSetPktLowestFixedRate(prAdapter, prCurrentMsduInfo); + break; + + case DATA_RATE_MODE_MANUAL: + prCurrentMsduInfo->u4FixedRateOption = prAdapter->rWifiVar.u4DataTxRateCode; + + prCurrentMsduInfo->ucRateMode = MSDU_RATE_MODE_MANUAL_DESC; + break; + + case DATA_RATE_MODE_AUTO: + default: + if (prCurrentMsduInfo->ucRateMode == MSDU_RATE_MODE_LOWEST_RATE) + nicTxSetPktLowestFixedRate(prAdapter, prCurrentMsduInfo); + break; + } + + /* BMC pkt need limited rate according to coex report*/ + if (prCurrentMsduInfo->ucStaRecIndex == STA_REC_INDEX_BMCAST) + nicTxSetPktLowestFixedRate(prAdapter, + prCurrentMsduInfo); + + /* 4 <4> Enqueue the packet */ + QUEUE_INSERT_TAIL(prTxQue, (P_QUE_ENTRY_T) prCurrentMsduInfo); + +#if QM_FAST_TC_RESOURCE_CTRL && QM_ADAPTIVE_TC_RESOURCE_CTRL + if (prTxQue != &rNotEnqueuedQue) { + /* Check and trigger fast TC resource adjustment for queued packets */ + qmCheckForFastTcResourceCtrl(prAdapter, ucTC); + } +#endif + +#if QM_TEST_MODE + if (++prQM->u4PktCount == QM_TEST_TRIGGER_TX_COUNT) { + prQM->u4PktCount = 0; + qmTestCases(prAdapter); + } +#endif + + DBGLOG(QM, LOUD, "Current queue length = %u\n", prTxQue->u4NumElem); + } while (prNextMsduInfo); + + if (QUEUE_IS_NOT_EMPTY(&rNotEnqueuedQue)) { + QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T) QUEUE_GET_TAIL(&rNotEnqueuedQue), NULL); + prMsduInfoReleaseList = (P_MSDU_INFO_T) QUEUE_GET_HEAD(&rNotEnqueuedQue); + } +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + /* 4 Update TC resource control related variables */ + /* Keep track of the queue length */ + qmDoAdaptiveTcResourceCtrl(prAdapter); +#endif + + return prMsduInfoReleaseList; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Determine the STA_REC index for a packet +* +* \param[in] prMsduInfo Pointer to the packet +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmDetermineStaRecIndex(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + UINT_32 i; + + P_STA_RECORD_T prTempStaRec; + P_BSS_INFO_T prBssInfo; + + GLUE_SPIN_LOCK_DECLARATION(); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + prTempStaRec = NULL; + + ASSERT(prMsduInfo); + + DBGLOG(QM, LOUD, "Msdu BSS Idx[%u] OpMode[%u] StaRecOfApExist[%u]\n", + prMsduInfo->ucBssIndex, prBssInfo->eCurrentOPMode, prBssInfo->prStaRecOfAP ? TRUE : FALSE); + + switch (prBssInfo->eCurrentOPMode) { + case OP_MODE_IBSS: + case OP_MODE_ACCESS_POINT: + /* 4 <1> DA = BMCAST */ + if (IS_BMCAST_MAC_ADDR(prMsduInfo->aucEthDestAddr)) { + prMsduInfo->ucStaRecIndex = STA_REC_INDEX_BMCAST; + DBGLOG(QM, LOUD, "TX with DA = BMCAST\n"); + return; + } + break; + + /* Infra Client/GC */ + case OP_MODE_INFRASTRUCTURE: + case OP_MODE_BOW: + if (prBssInfo->prStaRecOfAP) { +#if CFG_SUPPORT_TDLS + + prTempStaRec = + cnmGetTdlsPeerByAddress(prAdapter, prBssInfo->ucBssIndex, prMsduInfo->aucEthDestAddr); + if (IS_DLS_STA(prTempStaRec) && prTempStaRec->ucStaState == STA_STATE_3) { + if (g_arTdlsLink[prTempStaRec->ucTdlsIndex]) { + prMsduInfo->ucStaRecIndex = prTempStaRec->ucIndex; + return; + } + } +#endif + /* 4 <2> Check if an AP STA is present */ + GLUE_ACQUIRE_SPIN_LOCK(prAdapter->prGlueInfo, + SPIN_LOCK_STA_RECOFAP); + prTempStaRec = prBssInfo->prStaRecOfAP; + + DBGLOG(QM, LOUD, + "StaOfAp Idx[%u] WIDX[%u] Valid[%u] TxAllowed[%u] InUse[%u] Type[%u]\n", + prTempStaRec->ucIndex, prTempStaRec->ucWlanIndex, + prTempStaRec->fgIsValid, prTempStaRec->fgIsTxAllowed, + prTempStaRec->fgIsInUse, prTempStaRec->eStaType); + + if (prTempStaRec && prTempStaRec->fgIsInUse) { + prMsduInfo->ucStaRecIndex = prTempStaRec->ucIndex; + GLUE_RELEASE_SPIN_LOCK(prAdapter->prGlueInfo, + SPIN_LOCK_STA_RECOFAP); + DBGLOG(QM, LOUD, "TX with AP_STA[%u]\n", prTempStaRec->ucIndex); + return; + } + GLUE_RELEASE_SPIN_LOCK(prAdapter->prGlueInfo, + SPIN_LOCK_STA_RECOFAP); + } + break; + + case OP_MODE_P2P_DEVICE: + break; + + default: + break; + } + + /* 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_STA_REC_NUM; i++) { + prTempStaRec = &(prAdapter->arStaRec[i]); + if (prTempStaRec->fgIsInUse) { + if (EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, prMsduInfo->aucEthDestAddr)) { + prMsduInfo->ucStaRecIndex = prTempStaRec->ucIndex; + DBGLOG(QM, LOUD, "TX with STA[%u]\n", 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 +} + +P_STA_RECORD_T qmDetermineStaToBeDequeued(IN P_ADAPTER_T prAdapter, IN UINT_32 u4StartStaRecIndex) +{ + + return NULL; +} + +P_QUE_T qmDequeueStaTxPackets(IN P_ADAPTER_T prAdapter) +{ + + return NULL; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +qmDequeueTxPacketsFromPerStaQueues(IN P_ADAPTER_T prAdapter, OUT P_QUE_T prQue, + IN UINT_8 ucTC, IN UINT_32 u4CurrentQuota, IN UINT_32 u4TotalQuota) +{ + UINT_32 ucLoop; /* Loop for */ + + UINT_32 u4CurStaIndex = 0; + UINT_32 u4CurStaUsedResource = 0; + + 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 u4CurStaForwardFrameCount; /* To remember the total forwarded packets for a STA */ + UINT_32 u4MaxForwardFrameCountLimit; /* The maximum number of packets a STA can forward */ + UINT_32 u4AvaliableResource; /* The TX resource amount */ + UINT_32 u4MaxResourceLimit; + + BOOLEAN fgEndThisRound; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + PUINT_8 pucPsStaFreeQuota; + + /* Sanity Check */ + if (!u4CurrentQuota) { + DBGLOG(TX, LOUD, "(Fairness) Skip TC = %u u4CurrentQuota = %u\n", ucTC, u4CurrentQuota); + return u4CurrentQuota; + } + /* 4 <1> Assign init value */ + u4AvaliableResource = u4CurrentQuota; + u4MaxResourceLimit = u4TotalQuota; + +#if QM_FORWARDING_FAIRNESS + u4CurStaIndex = prQM->au4HeadStaRecIndex[ucTC]; + u4CurStaUsedResource = prQM->au4ResourceUsedCount[ucTC]; +#endif + + fgEndThisRound = FALSE; + ucLoop = 0; + u4CurStaForwardFrameCount = 0; + + DBGLOG(QM, LOUD, "(Fairness) TC[%u] Init Head STA[%u] Resource[%u]\n", + ucTC, u4CurStaIndex, u4AvaliableResource); + + /* 4 <2> Traverse STA array from Head STA */ + /* From STA[x] to STA[x+1] to STA[x+2] to ... to STA[x] */ + while (ucLoop < CFG_STA_REC_NUM) { + prStaRec = &prAdapter->arStaRec[u4CurStaIndex]; + prCurrQueue = &prStaRec->arTxQueue[ucTC]; + + /* 4 <2.1> Find a Tx allowed STA */ + /* Only Data frame will be queued in */ + /* if (prStaRec->fgIsTxAllowed) { */ + if (QUEUE_IS_NOT_EMPTY(prCurrQueue)) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + /* prCurrQueue = &prStaRec->aprTxQueue[ucTC]; */ + prDequeuedPkt = NULL; + pucPsStaFreeQuota = NULL; + /* Set default forward count limit to unlimited */ + u4MaxForwardFrameCountLimit = QM_STA_FORWARD_COUNT_UNLIMITED; + + /* 4 <2.2> Update forward frame/page count limit for this STA */ + /* AP mode: STA in PS buffer handling */ + if (prStaRec->fgIsInPS) { + if (prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported && + (prStaRec->ucBmpTriggerAC & BIT(ucTC))) { + u4MaxForwardFrameCountLimit = prStaRec->ucFreeQuotaForDelivery; + pucPsStaFreeQuota = &prStaRec->ucFreeQuotaForDelivery; + } else { + /* ASSERT(prStaRec->ucFreeQuotaForDelivery == 0); */ + u4MaxForwardFrameCountLimit = prStaRec->ucFreeQuotaForNonDelivery; + pucPsStaFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery; + } + } + + /* fgIsInPS */ + /* Absent BSS handling */ + if (prBssInfo->fgIsNetAbsent) { + if (u4MaxForwardFrameCountLimit > prBssInfo->ucBssFreeQuota) + u4MaxForwardFrameCountLimit = prBssInfo->ucBssFreeQuota; + } + +#if CFG_SUPPORT_DBDC + if (prAdapter->rWifiVar.fgDbDcModeEn) + u4MaxResourceLimit = gmGetDequeueQuota(prAdapter, prStaRec, prBssInfo, u4TotalQuota); +#endif + + /* 4 <2.3> Dequeue packet */ + /* Three cases to break: (1) No resource (2) No packets (3) Fairness */ + while (!QUEUE_IS_EMPTY(prCurrQueue)) { + prDequeuedPkt = (P_MSDU_INFO_T) QUEUE_GET_HEAD(prCurrQueue); + + if ((u4CurStaForwardFrameCount >= u4MaxForwardFrameCountLimit) || + (u4CurStaUsedResource >= u4MaxResourceLimit)) { + /* Exceeds Limit */ + + break; + } else if (prDequeuedPkt->u4PageCount > u4AvaliableResource) { + /* Available Resource is not enough */ + if (!(prAdapter->rWifiVar.ucAlwaysResetUsedRes & BIT(0))) + fgEndThisRound = TRUE; + break; + } else if (!prStaRec->fgIsValid) { + /* In roaming, if the sta_rec doesn't + * active by event 0x0C, it can't + * dequeue data. + */ + DBGLOG(QM, WARN, + "sta_rec is not valid\n"); + break; + } + /* Available to be Tx */ + + QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T); + + if (!QUEUE_IS_EMPTY(prCurrQueue)) { + /* XXX: check all queues for STA */ + prDequeuedPkt->ucPsForwardingType = PS_FORWARDING_MORE_DATA_ENABLED; + } + prDequeuedPkt->ucWmmQueSet = prBssInfo->ucWmmQueSet; /* to record WMM Set */ + QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prDequeuedPkt); + + u4AvaliableResource -= prDequeuedPkt->u4PageCount; + u4CurStaUsedResource += prDequeuedPkt->u4PageCount; + u4CurStaForwardFrameCount++; + } + + /* AP mode: Update STA in PS Free quota */ + if (prStaRec->fgIsInPS && pucPsStaFreeQuota) { + if ((*pucPsStaFreeQuota) >= u4CurStaForwardFrameCount) + (*pucPsStaFreeQuota) -= u4CurStaForwardFrameCount; + else + (*pucPsStaFreeQuota) = 0; + } + + if (prBssInfo->fgIsNetAbsent) { + if (prBssInfo->ucBssFreeQuota >= u4CurStaForwardFrameCount) + prBssInfo->ucBssFreeQuota -= u4CurStaForwardFrameCount; + else + prBssInfo->ucBssFreeQuota = 0; + } + } + + if (fgEndThisRound) { + /* End this round */ + break; + } + + /* Prepare for next STA */ + ucLoop++; + u4CurStaIndex++; + u4CurStaIndex %= CFG_STA_REC_NUM; + u4CurStaUsedResource = 0; + u4CurStaForwardFrameCount = 0; + } + + /* 4 <3> Store Head Sta information to QM */ + /* No need to count used resource if thers is only one STA */ + if ((prQM->u4TxAllowedStaCount == 1) || (prAdapter->rWifiVar.ucAlwaysResetUsedRes & BIT(1))) + u4CurStaUsedResource = 0; + +#if QM_FORWARDING_FAIRNESS + prQM->au4HeadStaRecIndex[ucTC] = u4CurStaIndex; + prQM->au4ResourceUsedCount[ucTC] = u4CurStaUsedResource; +#endif + + DBGLOG(QM, LOUD, "(Fairness) TC[%u] Scheduled Head STA[%u] Left Resource[%u]\n", + ucTC, u4CurStaIndex, u4AvaliableResource); + + return u4AvaliableResource; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 available resource +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +qmDequeueTxPacketsFromPerTypeQueues(IN P_ADAPTER_T prAdapter, OUT P_QUE_T prQue, + IN UINT_8 ucTC, IN UINT_32 u4CurrentQuota, IN UINT_32 u4TotalQuota) +{ + UINT_32 u4AvaliableResource, u4LeftResource; + UINT_32 u4MaxResourceLimit; + UINT_32 u4TotalUsedResource = 0; + P_QUE_MGT_T prQM; + PFN_DEQUEUE_FUNCTION pfnDeQFunc[2]; + BOOLEAN fgChangeDeQFunc = TRUE; + BOOLEAN fgGlobalQueFirst = TRUE; + + DBGLOG(QM, LOUD, "Enter %s (TC = %d, quota = %u)\n", __func__, ucTC, u4CurrentQuota); + + /* Broadcast/Multicast data packets */ + if (u4CurrentQuota == 0) + return; + + prQM = &prAdapter->rQM; + + u4AvaliableResource = u4CurrentQuota; + u4MaxResourceLimit = u4TotalQuota; +#if QM_FORWARDING_FAIRNESS + u4TotalUsedResource = prQM->u4GlobalResourceUsedCount; + fgGlobalQueFirst = prQM->fgGlobalQFirst; +#endif + + /* Dequeue function selection */ + if (fgGlobalQueFirst) { + pfnDeQFunc[0] = qmDequeueTxPacketsFromGlobalQueue; + pfnDeQFunc[1] = qmDequeueTxPacketsFromPerStaQueues; + } else { + pfnDeQFunc[0] = qmDequeueTxPacketsFromPerStaQueues; + pfnDeQFunc[1] = qmDequeueTxPacketsFromGlobalQueue; + } + + /* 1st dequeue function */ + u4LeftResource = pfnDeQFunc[0](prAdapter, prQue, ucTC, u4AvaliableResource, + (u4MaxResourceLimit - u4TotalUsedResource)); + + /* dequeue function comsumes no resource, change */ + if ((u4LeftResource >= u4AvaliableResource) && (u4AvaliableResource >= NIC_TX_MAX_PAGE_PER_FRAME)) { + fgChangeDeQFunc = TRUE; + } else { + u4TotalUsedResource += (u4AvaliableResource - u4LeftResource); + /* Used resource exceeds limit, change */ + if (u4TotalUsedResource >= u4MaxResourceLimit) + fgChangeDeQFunc = TRUE; + } + + if (fgChangeDeQFunc) { + fgGlobalQueFirst = !fgGlobalQueFirst; + u4TotalUsedResource = 0; + } + + /* 2nd dequeue function */ + u4LeftResource = pfnDeQFunc[1](prAdapter, prQue, ucTC, u4LeftResource, u4MaxResourceLimit); + +#if QM_FORWARDING_FAIRNESS + prQM->fgGlobalQFirst = fgGlobalQueFirst; + prQM->u4GlobalResourceUsedCount = u4TotalUsedResource; +#endif + +} /* qmDequeueTxPacketsFromPerTypeQueues */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Dequeue TX packets from a QM global 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 available resource +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +qmDequeueTxPacketsFromGlobalQueue(IN P_ADAPTER_T prAdapter, OUT P_QUE_T prQue, + IN UINT_8 ucTC, IN UINT_32 u4CurrentQuota, IN UINT_32 u4TotalQuota) +{ + P_BSS_INFO_T prBssInfo; + P_QUE_T prCurrQueue; + UINT_32 u4AvaliableResource; + 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 %s (TC = %d, quota = %u)\n", __func__, ucTC, u4CurrentQuota); + + /* Broadcast/Multicast data packets */ + if (u4CurrentQuota == 0) + return u4CurrentQuota; + + prQM = &prAdapter->rQM; + + /* 4 <1> Determine the queue */ + prCurrQueue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST]; + u4AvaliableResource = u4CurrentQuota; + prDequeuedPkt = NULL; + prBurstEndPkt = NULL; + + QUEUE_INITIALIZE(&rMergeQue); + prMergeQue = &rMergeQue; + + /* 4 <2> Dequeue packets */ + while (!QUEUE_IS_EMPTY(prCurrQueue)) { + prDequeuedPkt = (P_MSDU_INFO_T) QUEUE_GET_HEAD(prCurrQueue); + if (prDequeuedPkt->u4PageCount > u4AvaliableResource) + break; + + QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prDequeuedPkt->ucBssIndex); + + if (IS_BSS_ACTIVE(prBssInfo)) { + if (!prBssInfo->fgIsNetAbsent) { + prDequeuedPkt->ucWmmQueSet = prBssInfo->ucWmmQueSet; /* to record WMM Set */ + QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prDequeuedPkt); + prBurstEndPkt = prDequeuedPkt; + u4AvaliableResource -= prDequeuedPkt->u4PageCount; + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_26); + } 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); + } + + return u4AvaliableResource; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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; + UINT_32 u4MaxQuotaLimit; + + DBGLOG(QM, LOUD, "Enter qmDequeueTxPackets\n"); + + QUEUE_INITIALIZE(&rReturnedQue); + + prReturnedPacketListHead = NULL; + + /* TC0 to TC3: AC0~AC3 (commands packets are not handled by QM) */ + for (i = TC3_INDEX; i >= TC0_INDEX; i--) { + DBGLOG(QM, LOUD, "Dequeue packets from Per-STA queue[%u]\n", i); + + /* If only one STA is Tx allowed, no need to restrict Max quota */ + if (prAdapter->rWifiVar.u4MaxTxDeQLimit) + u4MaxQuotaLimit = prAdapter->rWifiVar.u4MaxTxDeQLimit; + else if (prAdapter->rQM.u4TxAllowedStaCount == 1) + u4MaxQuotaLimit = QM_STA_FORWARD_COUNT_UNLIMITED; + else + u4MaxQuotaLimit = (UINT_32) prTcqStatus->au4MaxNumOfPage[i]; + + if (i == BMC_TC_INDEX) + qmDequeueTxPacketsFromPerTypeQueues(prAdapter, &rReturnedQue, (UINT_8)i, + prTcqStatus->au4FreePageCount[i], u4MaxQuotaLimit); + else + qmDequeueTxPacketsFromPerStaQueues(prAdapter, &rReturnedQue, (UINT_8)i, + prTcqStatus->au4FreePageCount[i], u4MaxQuotaLimit); + + /* The aggregate number of dequeued packets */ + DBGLOG(QM, LOUD, "DQA)[%u](%u)\n", i, 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; +} + +#if CFG_SUPPORT_MULTITHREAD +/*----------------------------------------------------------------------------*/ +/*! +* \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 qmDequeueTxPacketsMthread(IN P_ADAPTER_T prAdapter, IN P_TX_TCQ_STATUS_T prTcqStatus) +{ + + /* INT_32 i; */ + P_MSDU_INFO_T prReturnedPacketListHead; + /* QUE_T rReturnedQue; */ + /* UINT_32 u4MaxQuotaLimit; */ + P_MSDU_INFO_T prMsduInfo, prNextMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + prReturnedPacketListHead = qmDequeueTxPackets(prAdapter, prTcqStatus); + + /* require the resource first to prevent from unsync */ + prMsduInfo = prReturnedPacketListHead; + while (prMsduInfo) { + prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); + nicTxAcquireResource(prAdapter, prMsduInfo->ucTC, + nicTxGetPageCount(prMsduInfo->u2FrameLength, FALSE), FALSE); + prMsduInfo = prNextMsduInfo; + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + 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) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +qmAdjustTcQuotasMthread(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; + + KAL_SPIN_LOCK_DECLARATION(); + + /* Must initialize */ + for (i = 0; i < QM_ACTIVE_TC_NUM; i++) + prTcqAdjust->ai4Variation[i] = 0; + + /* 4 <1> If TC resource is not just adjusted, exit directly */ + if (!prQM->fgTcResourcePostAnnealing) + return FALSE; + /* 4 <2> Adjust TcqStatus according to the updated prQM->au4CurrentTcResource */ + else { + INT_32 i4TotalExtraQuota = 0; + INT_32 ai4ExtraQuota[QM_ACTIVE_TC_NUM]; + BOOLEAN fgResourceRedistributed = TRUE; + + /* Must initialize */ + for (i = 0; i < TC_NUM; i++) + prTcqAdjust->ai4Variation[i] = 0; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + /* Obtain the free-to-distribute resource */ + for (i = 0; i < QM_ACTIVE_TC_NUM; i++) { + ai4ExtraQuota[i] = + (INT_32) prTcqStatus->au4MaxNumOfBuffer[i] - (INT_32) prQM->au4CurrentTcResource[i]; + + if (ai4ExtraQuota[i] > 0) { /* The resource shall be reallocated to other TCs */ + if (ai4ExtraQuota[i] > prTcqStatus->au4FreeBufferCount[i]) { + ai4ExtraQuota[i] = prTcqStatus->au4FreeBufferCount[i]; + fgResourceRedistributed = FALSE; + } + + i4TotalExtraQuota += ai4ExtraQuota[i]; + prTcqAdjust->ai4Variation[i] = (-ai4ExtraQuota[i]); + } + } + + /* Distribute quotas to TCs which need extra resource according to prQM->au4CurrentTcResource */ + for (i = 0; i < QM_ACTIVE_TC_NUM; i++) { + if (ai4ExtraQuota[i] < 0) { + if ((-ai4ExtraQuota[i]) > i4TotalExtraQuota) { + ai4ExtraQuota[i] = (-i4TotalExtraQuota); + fgResourceRedistributed = FALSE; + } + + i4TotalExtraQuota += ai4ExtraQuota[i]; + prTcqAdjust->ai4Variation[i] = (-ai4ExtraQuota[i]); + } + } + + /* In case some TC is waiting for TX Done, continue to adjust TC quotas upon TX Done */ + prQM->fgTcResourcePostAnnealing = (!fgResourceRedistributed); + + for (i = 0; i < TC_NUM; i++) { + prTcqStatus->au4FreePageCount[i] += (prTcqAdjust->ai4Variation[i] * NIC_TX_MAX_PAGE_PER_FRAME); + prTcqStatus->au4MaxNumOfPage[i] += (prTcqAdjust->ai4Variation[i] * NIC_TX_MAX_PAGE_PER_FRAME); + + prTcqStatus->au4FreeBufferCount[i] += prTcqAdjust->ai4Variation[i]; + prTcqStatus->au4MaxNumOfBuffer[i] += prTcqAdjust->ai4Variation[i]; + + ASSERT(prTcqStatus->au4FreeBufferCount[i] >= 0); + ASSERT(prTcqStatus->au4MaxNumOfBuffer[i] >= 0); + } + +#if QM_FAST_TC_RESOURCE_CTRL + prQM->fgTcResourceFastReaction = FALSE; +#endif + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + } + + return TRUE; +#else + return FALSE; +#endif +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN 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 < QM_ACTIVE_TC_NUM; i++) + prTcqAdjust->ai4Variation[i] = 0; + + /* 4 <1> If TC resource is not just adjusted, exit directly */ + if (!prQM->fgTcResourcePostAnnealing) + return FALSE; + /* 4 <2> Adjust TcqStatus according to the updated prQM->au4CurrentTcResource */ + else { + INT_32 i4TotalExtraQuota = 0; + INT_32 ai4ExtraQuota[QM_ACTIVE_TC_NUM]; + BOOLEAN fgResourceRedistributed = TRUE; + + /* Obtain the free-to-distribute resource */ + for (i = 0; i < QM_ACTIVE_TC_NUM; i++) { + ai4ExtraQuota[i] = + (INT_32) prTcqStatus->au4MaxNumOfBuffer[i] - (INT_32) prQM->au4CurrentTcResource[i]; + + if (ai4ExtraQuota[i] > 0) { /* The resource shall be reallocated to other TCs */ + if (ai4ExtraQuota[i] > prTcqStatus->au4FreeBufferCount[i]) { + ai4ExtraQuota[i] = prTcqStatus->au4FreeBufferCount[i]; + fgResourceRedistributed = FALSE; + } + + i4TotalExtraQuota += ai4ExtraQuota[i]; + prTcqAdjust->ai4Variation[i] = (-ai4ExtraQuota[i]); + } + } + + /* Distribute quotas to TCs which need extra resource according to prQM->au4CurrentTcResource */ + for (i = 0; i < QM_ACTIVE_TC_NUM; i++) { + if (ai4ExtraQuota[i] < 0) { + if ((-ai4ExtraQuota[i]) > i4TotalExtraQuota) { + ai4ExtraQuota[i] = (-i4TotalExtraQuota); + fgResourceRedistributed = FALSE; + } + + i4TotalExtraQuota += ai4ExtraQuota[i]; + prTcqAdjust->ai4Variation[i] = (-ai4ExtraQuota[i]); + } + } + + /* In case some TC is waiting for TX Done, continue to adjust TC quotas upon TX Done */ + prQM->fgTcResourcePostAnnealing = (!fgResourceRedistributed); + +#if QM_FAST_TC_RESOURCE_CTRL + prQM->fgTcResourceFastReaction = FALSE; +#endif + +#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->au4FreeBufferCount[0], + prTcqStatus->au4FreeBufferCount[1], + prTcqStatus->au4FreeBufferCount[2], + prTcqStatus->au4FreeBufferCount[3], + prTcqStatus->au4FreeBufferCount[4], prTcqStatus->au4FreeBufferCount[5]); +#endif + } + + return TRUE; +#else + return FALSE; +#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, u4Tc, u4StaRecIdx; + P_STA_RECORD_T prStaRec; + P_QUE_MGT_T prQM = &prAdapter->rQM; + P_BSS_INFO_T prBssInfo; + + /* 4 <1> Update the queue lengths for TC0 to TC3 (skip TC4) and TC5 */ + for (u4Tc = 0; u4Tc < QM_ACTIVE_TC_NUM; u4Tc++) { + u4CurrQueLen = 0; + + /* Calculate per-STA queue length */ + if (u4Tc < NUM_OF_PER_STA_TX_QUEUES) { + for (u4StaRecIdx = 0; u4StaRecIdx < CFG_STA_REC_NUM; u4StaRecIdx++) { + prStaRec = cnmGetStaRecByIndex(prAdapter, u4StaRecIdx); + if (prStaRec) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + /* If the STA is activated, get the queue length */ + if ((prStaRec->fgIsValid) && (!prBssInfo->fgIsNetAbsent)) + u4CurrQueLen += (prStaRec->arTxQueue[u4Tc].u4NumElem); + } + } + } + + if (u4Tc == BMC_TC_INDEX) { + /* Update the queue length for (BMCAST) */ + u4CurrQueLen += prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST].u4NumElem; + } + + if (prQM->au4AverageQueLen[u4Tc] == 0) { + prQM->au4AverageQueLen[u4Tc] = (u4CurrQueLen << prQM->u4QueLenMovingAverage); + } else { + prQM->au4AverageQueLen[u4Tc] -= (prQM->au4AverageQueLen[u4Tc] >> prQM->u4QueLenMovingAverage); + prQM->au4AverageQueLen[u4Tc] += (u4CurrQueLen); + } + } +#if 0 + /* Update the queue length for TC5 (BMCAST) */ + u4CurrQueLen = prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST].u4NumElem; + + if (prQM->au4AverageQueLen[TC5_INDEX] == 0) { + prQM->au4AverageQueLen[TC5_INDEX] = (u4CurrQueLen << QM_QUE_LEN_MOVING_AVE_FACTOR); + } else { + prQM->au4AverageQueLen[TC5_INDEX] -= + (prQM->au4AverageQueLen[TC5_INDEX] >> QM_QUE_LEN_MOVING_AVE_FACTOR); + prQM->au4AverageQueLen[TC5_INDEX] += (u4CurrQueLen); + } +#endif +} + +VOID qmAllocateResidualTcResource(IN P_ADAPTER_T prAdapter, IN PINT_32 ai4TcResDemand, + IN PUINT_32 pu4ResidualResource, IN PUINT_32 pu4ShareCount) +{ + P_QUE_MGT_T prQM = &prAdapter->rQM; + UINT_32 u4Share = 0; + UINT_32 u4TcIdx; + UINT_8 ucIdx; + UINT_32 au4AdjTc[] = { TC3_INDEX, TC2_INDEX, TC5_INDEX, TC1_INDEX, TC0_INDEX }; + UINT_32 u4AdjTcSize = (sizeof(au4AdjTc) / sizeof(UINT_32)); + UINT_32 u4ResidualResource = *pu4ResidualResource; + UINT_32 u4ShareCount = *pu4ShareCount; + + /* If there is no resource left, exit directly */ + if (u4ResidualResource == 0) + return; + + /* This shall not happen */ + if (u4ShareCount == 0) { + prQM->au4CurrentTcResource[TC1_INDEX] += u4ResidualResource; + DBGLOG(QM, ERROR, "QM: (Error) u4ShareCount = 0\n"); + return; + } + + /* Share the residual resource evenly */ + u4Share = (u4ResidualResource / u4ShareCount); + if (u4Share) { + for (u4TcIdx = 0; u4TcIdx < QM_ACTIVE_TC_NUM; u4TcIdx++) { + /* Skip TC4 (not adjustable) */ + if (u4TcIdx == TC4_INDEX) + continue; + + if (ai4TcResDemand[u4TcIdx] > 0) { + if (ai4TcResDemand[u4TcIdx] > u4Share) { + prQM->au4CurrentTcResource[u4TcIdx] += u4Share; + u4ResidualResource -= u4Share; + ai4TcResDemand[u4TcIdx] -= u4Share; + } else { + prQM->au4CurrentTcResource[u4TcIdx] += ai4TcResDemand[u4TcIdx]; + u4ResidualResource -= ai4TcResDemand[u4TcIdx]; + ai4TcResDemand[u4TcIdx] = 0; + } + } + } + } + + /* By priority, allocate the left resource that is not divisible by u4Share */ + ucIdx = 0; + while (u4ResidualResource) { + u4TcIdx = au4AdjTc[ucIdx]; + + if (ai4TcResDemand[u4TcIdx]) { + prQM->au4CurrentTcResource[u4TcIdx]++; + u4ResidualResource--; + ai4TcResDemand[u4TcIdx]--; + + if (ai4TcResDemand[u4TcIdx] == 0) + u4ShareCount--; + } + + if (u4ShareCount <= 0) + break; + + ucIdx++; + ucIdx %= u4AdjTcSize; + } + + /* Allocate the left resource */ + prQM->au4CurrentTcResource[TC3_INDEX] += u4ResidualResource; + + *pu4ResidualResource = u4ResidualResource; + *pu4ShareCount = u4ShareCount; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 u4TcIdx; + INT_32 ai4TcResDemand[QM_ACTIVE_TC_NUM]; + UINT_32 u4ShareCount = 0; + UINT_32 u4Share = 0; + P_QUE_MGT_T prQM = &prAdapter->rQM; + UINT_32 u4ActiveTcCount = 0; + UINT_32 u4LastActiveTcIdx = TC3_INDEX; + + /* 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 (u4TcIdx = 0; u4TcIdx < QM_ACTIVE_TC_NUM; u4TcIdx++) { + /* Skip TC4, which is not adjustable */ + if (u4TcIdx == TC4_INDEX) + continue; + + /* Define: extra_demand = que_length + min_reserved_quota - current_quota */ + ai4TcResDemand[u4TcIdx] = ((INT_32)(QM_GET_TX_QUEUE_LEN(prAdapter, u4TcIdx) + + prQM->au4MinReservedTcResource[u4TcIdx]) - (INT_32)prQM->au4CurrentTcResource[u4TcIdx]); + + /* If there are queued packets, allocate extra resource for the TC (for TCP consideration) */ + if (QM_GET_TX_QUEUE_LEN(prAdapter, u4TcIdx)) { + ai4TcResDemand[u4TcIdx] += prQM->u4ExtraReservedTcResource; + u4ActiveTcCount++; + } + + i4TotalResourceDemand += ai4TcResDemand[u4TcIdx]; + } + + /* 4 <2> Case 1: Demand <= Total Resource */ + if (i4TotalResourceDemand <= 0) { + + /* 4 <2.1> Calculate the residual resource evenly */ + if (u4ActiveTcCount == 0) + u4ShareCount = (QM_ACTIVE_TC_NUM - 1); /* excluding TC4 */ + else + u4ShareCount = u4ActiveTcCount; + u4ResidualResource = (UINT_32) (-i4TotalResourceDemand); + u4Share = (u4ResidualResource / u4ShareCount); + + /* 4 <2.2> Satisfy every TC and share the residual resource evenly */ + for (u4TcIdx = 0; u4TcIdx < QM_ACTIVE_TC_NUM; u4TcIdx++) { + /* Skip TC4 (not adjustable) */ + if (u4TcIdx == TC4_INDEX) + continue; + + prQM->au4CurrentTcResource[u4TcIdx] += ai4TcResDemand[u4TcIdx]; + + /* Every TC is fully satisfied */ + ai4TcResDemand[u4TcIdx] = 0; + + /* The left resource will be allocated */ + if (QM_GET_TX_QUEUE_LEN(prAdapter, u4TcIdx) || (u4ActiveTcCount == 0)) { + prQM->au4CurrentTcResource[u4TcIdx] += u4Share; + u4ResidualResource -= u4Share; + u4LastActiveTcIdx = u4TcIdx; + } + } + + /* 4 <2.3> Allocate the left resource to last active TC */ + prQM->au4CurrentTcResource[u4LastActiveTcIdx] += (u4ResidualResource); + + } + /* 4 <3> Case 2: Demand > Total Resource --> Guarantee a minimum amount of resource for each TC */ + else { + u4ShareCount = 0; + u4ResidualResource = prQM->u4ResidualTcResource; + + /* 4 <3.1> Allocated resouce amount = minimum of (guaranteed, total demand) */ + for (u4TcIdx = 0; u4TcIdx < QM_ACTIVE_TC_NUM; u4TcIdx++) { + /* Skip TC4 (not adjustable) */ + if (u4TcIdx == TC4_INDEX) + continue; + + /* The demand can be fulfilled with the guaranteed resource amount */ + if ((prQM->au4CurrentTcResource[u4TcIdx] + ai4TcResDemand[u4TcIdx]) <= + prQM->au4GuaranteedTcResource[u4TcIdx]) { + + prQM->au4CurrentTcResource[u4TcIdx] += ai4TcResDemand[u4TcIdx]; + u4ResidualResource += + (prQM->au4GuaranteedTcResource[u4TcIdx] - prQM->au4CurrentTcResource[u4TcIdx]); + ai4TcResDemand[u4TcIdx] = 0; + } + + /* The demand can not be fulfilled with the guaranteed resource amount */ + else { + ai4TcResDemand[u4TcIdx] -= + (prQM->au4GuaranteedTcResource[u4TcIdx] - prQM->au4CurrentTcResource[u4TcIdx]); + + prQM->au4CurrentTcResource[u4TcIdx] = prQM->au4GuaranteedTcResource[u4TcIdx]; + u4ShareCount++; + } + } + + /* 4 <3.2> Allocate the residual resource */ + qmAllocateResidualTcResource(prAdapter, ai4TcResDemand, &u4ResidualResource, &u4ShareCount); + } + + prQM->fgTcResourcePostAnnealing = TRUE; + +#if QM_PRINT_TC_RESOURCE_CTRL + /* Debug print */ + DBGLOG(QM, INFO, "QM: TC Rsc adjust to [%03u:%03u:%03u:%03u:%03u:%03u]\n", + prQM->au4CurrentTcResource[0], prQM->au4CurrentTcResource[1], + prQM->au4CurrentTcResource[2], prQM->au4CurrentTcResource[3], + prQM->au4CurrentTcResource[4], prQM->au4CurrentTcResource[5]); +#endif + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Adjust TX resource for each TC according to TX queue length and current assignment +* +* \param (none) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmDoAdaptiveTcResourceCtrl(IN P_ADAPTER_T prAdapter) +{ + P_QUE_MGT_T prQM = &prAdapter->rQM; + + /* 4 <0> Check to update queue length or not */ + if (--prQM->u4TimeToUpdateQueLen) + return; + /* 4 <1> Update TC queue length */ + prQM->u4TimeToUpdateQueLen = QM_INIT_TIME_TO_UPDATE_QUE_LEN; + qmUpdateAverageTxQueLen(prAdapter); + + /* 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); +#if QM_FAST_TC_RESOURCE_CTRL + if (prQM->fgTcResourceFastReaction) { + prQM->fgTcResourceFastReaction = FALSE; + nicTxAdjustTcq(prAdapter); + } +#endif + } + } + + /* Debug */ +#if QM_PRINT_TC_RESOURCE_CTRL + do { + UINT_32 u4Tc; + + for (u4Tc = 0; u4Tc < QM_ACTIVE_TC_NUM; u4Tc++) { + if (QM_GET_TX_QUEUE_LEN(prAdapter, u4Tc) >= 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; + } + } + } while (FALSE); +#endif + +} + +#if QM_FAST_TC_RESOURCE_CTRL +VOID qmCheckForFastTcResourceCtrl(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTc) +{ + P_QUE_MGT_T prQM = &prAdapter->rQM; + BOOLEAN fgTrigger = FALSE; + + /* Trigger TC resource adjustment if there is a requirement coming for a empty TC */ + if (!prAdapter->rTxCtrl.rTc.au4FreeBufferCount[ucTc]) { + if (!prQM->au4CurrentTcResource[ucTc] || + nicTxGetAdjustableResourceCnt(prAdapter)) + fgTrigger = TRUE; + } + + if (fgTrigger) { + prQM->u4TimeToUpdateQueLen = 1; + prQM->u4TimeToAdjustTcResource = 1; + prQM->fgTcResourceFastReaction = TRUE; + + DBGLOG(QM, LOUD, "Trigger TC Resource adjustment for TC[%u]\n", ucTc); + } +} +#endif + +#endif + +UINT_32 +gmGetDequeueQuota( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN P_BSS_INFO_T prBssInfo, + IN UINT_32 u4TotalQuota + ) +{ + UINT_32 u4Weight = 100; + UINT_32 u4Quota; + + P_QUE_MGT_T prQM = &prAdapter->rQM; + + if ((prAdapter->rWifiVar.uDeQuePercentEnable == FALSE) || + (prQM->fgIsTxResrouceControlEn == FALSE)) + return u4TotalQuota; + + if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_VHT) { + if (prBssInfo->ucVhtChannelWidth > VHT_OP_CHANNEL_WIDTH_20_40) { + /* BW80 NSS1 rate: MCS9 433 Mbps */ + u4Weight = prAdapter->rWifiVar.u4DeQuePercentVHT80Nss1; + } else if (prBssInfo->eBssSCO != CHNL_EXT_SCN) { + /* BW40 NSS1 Max rate: 200 Mbps */ + u4Weight = prAdapter->rWifiVar.u4DeQuePercentVHT40Nss1; + } else { + /* BW20 NSS1 Max rate: 72.2Mbps (MCS8 86.7Mbps) */ + u4Weight = prAdapter->rWifiVar.u4DeQuePercentVHT20Nss1; + } + } else if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_HT) { + if (prBssInfo->ucHtOpInfo1 & HT_OP_INFO1_STA_CHNL_WIDTH) { + /* BW40 NSS1 Max rate: 150 Mbps (MCS9 200Mbps)*/ + u4Weight = prAdapter->rWifiVar.u4DeQuePercentHT40Nss1; + } else { + /* BW20 NSS1 Max rate: 72.2Mbps (MCS8 86.7Mbps)*/ + u4Weight = prAdapter->rWifiVar.u4DeQuePercentHT20Nss1; + } + } + + u4Quota = u4TotalQuota * u4Weight / 100; + + if (u4Quota > u4TotalQuota || u4Quota <= 0) + return u4TotalQuota; + + return u4Quota; +} + +/*----------------------------------------------------------------------------*/ +/* RX-Related Queue Management */ +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +/*! +* \brief Init Queue Management for RX +* +* \param[in] (none) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmInitRxQueues(IN P_ADAPTER_T prAdapter) +{ + /* DbgPrint("QM: Enter qmInitRxQueues()\n"); */ + /* TODO */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Handle RX packets (buffer reordering) +* +* \param[in] prSwRfbListHead The list of RX packets +* +* \return The list of packets which are not buffered for reordering +*/ +/*----------------------------------------------------------------------------*/ +P_SW_RFB_T qmHandleRxPackets(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfbListHead) +{ + +#if CFG_RX_REORDERING_ENABLED + /* UINT_32 i; */ + P_SW_RFB_T prCurrSwRfb; + P_SW_RFB_T prNextSwRfb; + P_HW_MAC_RX_DESC_T prRxStatus; + QUE_T rReturnedQue; + P_QUE_T prReturnedQue; + PUINT_8 pucEthDestAddr; + BOOLEAN fgIsBMC, fgIsHTran; + BOOLEAN fgMicErr; +#if CFG_SUPPORT_REPLAY_DETECTION + UINT_8 ucBssIndexRly = 0; + P_BSS_INFO_T prBssInfoRly = NULL; +#endif + + /* DbgPrint("QM: Enter qmHandleRxPackets()\n"); */ + + DEBUGFUNC("qmHandleRxPackets"); + + ASSERT(prSwRfbListHead); + + prReturnedQue = &rReturnedQue; + + QUEUE_INITIALIZE(prReturnedQue); + prNextSwRfb = prSwRfbListHead; + + do { + prCurrSwRfb = prNextSwRfb; + prNextSwRfb = QM_RX_GET_NEXT_SW_RFB(prCurrSwRfb); + + /* prHifRxHdr = prCurrSwRfb->prHifRxHdr; // TODO: (Tehuang) Use macro to obtain the pointer */ + prRxStatus = prCurrSwRfb->prRxStatus; + + /* 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), */ + prCurrSwRfb->ucStaRecIdx, prRxStatus->ucWlanIdx, + /* HIF_RX_HDR_GET_SN(prHifRxHdr), *//* The new SN of the frame */ + HAL_RX_STATUS_GET_TID(prRxStatus), + prCurrSwRfb->ucPacketType, prCurrSwRfb->fgReorderBuffer); + + DBGLOG_MEM8(SW4, TRACE, (PUINT_8) prCurrSwRfb->pvHeader, prCurrSwRfb->u2PacketLen); + } +#endif + + fgIsBMC = HAL_RX_STATUS_IS_BC(prRxStatus) | HAL_RX_STATUS_IS_MC(prRxStatus); + fgIsHTran = FALSE; + if (HAL_RX_STATUS_GET_HEADER_TRAN(prRxStatus) == TRUE) { + /* (!HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)){ */ + + UINT_8 ucBssIndex; + P_BSS_INFO_T prBssInfo; + UINT_8 aucTaAddr[MAC_ADDR_LEN]; + + fgIsHTran = TRUE; + pucEthDestAddr = prCurrSwRfb->pvHeader; + + if (prCurrSwRfb->prRxStatusGroup4 == NULL) { + DBGLOG(QM, ERROR, "RxStatusGroup4 is NULL!!\n"); + DBGLOG_MEM8(QM, ERROR, prCurrSwRfb->pucRecvBuff, + HAL_RX_STATUS_GET_RX_BYTE_CNT( + prRxStatus)); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, + (P_QUE_ENTRY_T) prCurrSwRfb); + DBGLOG_MEM8(RX, WARN, (uint8_t *) prRxStatus, + sizeof(*prRxStatus)); + if (prCurrSwRfb->pvHeader) + DBGLOG_MEM8(RX, WARN, + prCurrSwRfb->pvHeader, + prCurrSwRfb->u2PacketLen > + 32 ? 32 : + prCurrSwRfb->u2PacketLen); + continue; + } + + if (prCurrSwRfb->prStaRec == NULL) { + /* Workaround WTBL Issue */ + + HAL_RX_STATUS_GET_TA(prCurrSwRfb->prRxStatusGroup4, aucTaAddr); + prCurrSwRfb->ucStaRecIdx = secLookupStaRecIndexFromTA(prAdapter, aucTaAddr); + if (prCurrSwRfb->ucStaRecIdx < CFG_STA_REC_NUM) { + prCurrSwRfb->prStaRec = + cnmGetStaRecByIndex(prAdapter, prCurrSwRfb->ucStaRecIdx); + DBGLOG(QM, TRACE, + "Re-search the staRec = %d, mac = " MACSTR ", byteCnt= %d\n", + prCurrSwRfb->ucStaRecIdx, MAC2STR(aucTaAddr), prRxStatus->u2RxByteCount); + } + + if (prCurrSwRfb->prStaRec == NULL) { + DBGLOG(QM, TRACE, + "Mark NULL Packet,StaRec=NULL,wlanIdx:%d,but via Header Translation\n", + prRxStatus->ucWlanIdx); + /* DBGLOG_MEM8(SW4, TRACE, (PUINT_8)prRxStatus, prRxStatus->u2RxByteCount); */ + RX_INC_CNT(&prAdapter->rRxCtrl, RX_NO_STA_DROP_COUNT); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + continue; + } + + prCurrSwRfb->ucWlanIdx = prCurrSwRfb->prStaRec->ucWlanIndex; + GLUE_SET_PKT_BSS_IDX(prCurrSwRfb->pvPacket, + secGetBssIdxByWlanIdx(prAdapter, prCurrSwRfb->ucWlanIdx)); + } + /* ASSERT(prAdapter->rWifiVar.arWtbl[prCurrSwRfb->ucWlanIdx].ucUsed); */ + if (prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem + > (CFG_RX_MAX_PKT_NUM - CFG_NUM_OF_QM_RX_PKT_NUM) || TRUE) { + + ucBssIndex = prCurrSwRfb->prStaRec->ucBssIndex; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + /* DBGLOG_MEM8(QM, TRACE,prCurrSwRfb->pvHeader, 16); */ + /* */ + + /* if ((OP_MODE_ACCESS_POINT != prBssInfo->eCurrentOPMode)) { */ + /* fgIsBMC = HAL_RX_STATUS_IS_BC(prRxStatus) | HAL_RX_STATUS_IS_MC(prRxStatus); */ + /* } */ + + if (!IS_BSS_ACTIVE(prBssInfo)) { + DBGLOG(QM, TRACE, "Mark NULL the Packet for inactive Bss %u\n", ucBssIndex); + RX_INC_CNT(&prAdapter->rRxCtrl, RX_INACTIVE_BSS_DROP_COUNT); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + continue; + } + + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + if (IS_BMCAST_MAC_ADDR(pucEthDestAddr)) { + prCurrSwRfb->eDst = RX_PKT_DESTINATION_HOST_WITH_FORWARD; + } else if (secLookupStaRecIndexFromTA(prAdapter, pucEthDestAddr) + != STA_REC_INDEX_NOT_FOUND) { + + 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 */ + } + } +#if CFG_SUPPORT_PASSPOINT + else if (hs20IsFrameFilterEnabled(prAdapter, prBssInfo) && + hs20IsUnsecuredFrame(prAdapter, prBssInfo, prCurrSwRfb)) { + DBGLOG(QM, WARN, "Mark NULL the Packet for Dropped Packet %u\n", ucBssIndex); + RX_INC_CNT(&prAdapter->rRxCtrl, RX_HS20_DROP_COUNT); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + continue; + } +#endif /* CFG_SUPPORT_PASSPOINT */ + + } else { + /* Dont not occupy other SW RFB */ + DBGLOG(QM, TRACE, "Mark NULL the Packet for less Free Sw Rfb\n"); + RX_INC_CNT(&prAdapter->rRxCtrl, RX_LESS_SW_RFB_DROP_COUNT); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + continue; + } + + } + +#if CFG_SUPPORT_WAPI + if (prCurrSwRfb->u2PacketLen > ETHER_HEADER_LEN) { + PUINT_8 pc = (PUINT_8) prCurrSwRfb->pvHeader; + UINT_16 u2Etype = 0; + + u2Etype = (pc[ETHER_TYPE_LEN_OFFSET] << 8) | (pc[ETHER_TYPE_LEN_OFFSET + 1]); + /* for wapi integrity test. WPI_1x packet should be always in non-encrypted mode. + * if we received any WPI(0x88b4) packet that is encrypted, drop here. + */ + if (u2Etype == ETH_WPI_1X && + HAL_RX_STATUS_GET_SEC_MODE(prRxStatus) != 0 && + HAL_RX_STATUS_IS_CIPHER_MISMATCH(prRxStatus) == 0) { + DBGLOG(QM, INFO, "drop wpi packet with sec mode\n"); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + continue; + } + } +#endif + + + /* Todo:: Move the data class error check here */ + +#if CFG_SUPPORT_REPLAY_DETECTION + if (prCurrSwRfb->prStaRec) { + ucBssIndexRly = prCurrSwRfb->prStaRec->ucBssIndex; + prBssInfoRly = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndexRly); + if (!IS_BSS_ACTIVE(prBssInfoRly)) { + DBGLOG(QM, INFO, + "Mark NULL the Packet for inactive Bss %u\n", + ucBssIndexRly); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + continue; + } + if (fgIsBMC + && prBssInfoRly + && (IS_BSS_AIS(prBssInfoRly) || IS_BSS_P2P(prBssInfoRly)) + && qmHandleRxReplay(prAdapter, prCurrSwRfb)) { + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + continue; + } + } +#endif + + if (prCurrSwRfb->fgReorderBuffer && !fgIsBMC && fgIsHTran) { + /* 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, prReturnedQue); + + } else if (prCurrSwRfb->fgDataFrame) { + /* Check Class Error */ + if (secCheckClassError(prAdapter, prCurrSwRfb, prCurrSwRfb->prStaRec) == TRUE) { + P_RX_BA_ENTRY_T prReorderQueParm = NULL; + + /* Invalid BA aggrement */ + if (fgIsHTran) { + UINT_16 u2FrameCtrl = 0; + + u2FrameCtrl = HAL_RX_STATUS_GET_FRAME_CTL_FIELD(prCurrSwRfb->prRxStatusGroup4); + /* Check FC type, if DATA, then no-reordering */ + if ((u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_DATA) { + DBGLOG(QM, TRACE, "FC [0x%04X], no-reordering...\n", u2FrameCtrl); + } else { + prReorderQueParm = + ((prCurrSwRfb->prStaRec-> + aprRxReorderParamRefTbl)[prCurrSwRfb->ucTid]); + } + } + + if (prReorderQueParm && prReorderQueParm->fgIsValid && !fgIsBMC) + qmProcessPktWithReordering(prAdapter, prCurrSwRfb, prReturnedQue); + else + qmHandleRxPackets_AOSP_1; + } else { + DBGLOG(QM, TRACE, "Mark NULL the Packet for class error\n"); + RX_INC_CNT(&prAdapter->rRxCtrl, RX_CLASS_ERR_DROP_COUNT); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + } + } else { + P_WLAN_MAC_HEADER_T prWlanMacHeader; + + ASSERT(prCurrSwRfb->pvHeader); + + prWlanMacHeader = (P_WLAN_MAC_HEADER_T) prCurrSwRfb->pvHeader; + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + + switch (prWlanMacHeader->u2FrameCtrl & MASK_FRAME_TYPE) { + /* BAR frame */ + case MAC_FRAME_BLOCK_ACK_REQ: + qmProcessBarFrame(prAdapter, prCurrSwRfb, prReturnedQue); + RX_INC_CNT(&prAdapter->rRxCtrl, RX_BAR_DROP_COUNT); + break; + default: + DBGLOG(QM, TRACE, "Mark NULL the Packet for non-interesting type\n"); + RX_INC_CNT(&prAdapter->rRxCtrl, RX_NO_INTEREST_DROP_COUNT); + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + break; + } + } + + } while (prNextSwRfb); + + /* The returned list of SW_RFBs must end with a NULL pointer */ + if (QUEUE_IS_NOT_EMPTY(prReturnedQue)) + QM_TX_SET_NEXT_MSDU_INFO((P_SW_RFB_T) QUEUE_GET_TAIL(prReturnedQue), NULL); + + return (P_SW_RFB_T) QUEUE_GET_HEAD(prReturnedQue); + +#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_HW_MAC_RX_DESC_T prRxStatus; + P_RX_BA_ENTRY_T prReorderQueParm; + + /* P_SW_RFB_T prReorderedSwRfb; */ +#if CFG_SUPPORT_RX_AMSDU + UINT_8 u8AmsduSubframeIdx; + UINT_32 u4SeqNo; +#endif + DEBUGFUNC("qmProcessPktWithReordering"); + + ASSERT(prSwRfb); + ASSERT(prReturnedQue); + ASSERT(prSwRfb->prRxStatus); + + /* Incorrect STA_REC index */ + if (prSwRfb->ucStaRecIdx >= CFG_STA_REC_NUM) { + RX_INC_CNT(&prAdapter->rRxCtrl, RX_NO_STA_DROP_COUNT); + 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); + authSendDeauthFrame(prAdapter, NULL, NULL, prSwRfb, REASON_CODE_CLASS_3_ERR, + (PFN_TX_DONE_HANDLER)NULL); + /* ASSERT(0); */ + return; + } + + /* Check whether the STA_REC is activated */ + prStaRec = prSwRfb->prStaRec; + ASSERT(prStaRec); + + prRxStatus = prSwRfb->prRxStatus; + /* prSwRfb->eDst = RX_PKT_DESTINATION_HOST; */ + +#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 + + RX_INC_CNT(&prAdapter->rRxCtrl, RX_DATA_REORDER_TOTAL_COUINT); + + /* Check whether the BA agreement exists */ + prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[prSwRfb->ucTid]); + if (!prReorderQueParm || !(prReorderQueParm->fgIsValid)) { + /* TODO: (Tehuang) Handle the Host-FW sync issue. */ + prSwRfb->eDst = RX_PKT_DESTINATION_HOST; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); + DBGLOG(QM, TRACE, "Reordering for a NULL ReorderQueParm\n"); + return; + } + +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + /* QUEUE_INITIALIZE(&prSwRfb->rAmsduQue); */ + + u8AmsduSubframeIdx = HAL_RX_STATUS_GET_PAYLOAD_FORMAT(prRxStatus); + + /* prMpduSwRfb = prReorderQueParm->prMpduSwRfb; */ + u4SeqNo = (UINT_32)prSwRfb->u2SSN; + + switch (u8AmsduSubframeIdx) { + case RX_PAYLOAD_FORMAT_FIRST_SUB_AMSDU: + if (prReorderQueParm->fgAmsduNeedLastFrame) { + RX_INC_CNT(&prAdapter->rRxCtrl, RX_DATA_AMSDU_MISS_COUNT); + prReorderQueParm->fgAmsduNeedLastFrame = FALSE; + } + RX_INC_CNT(&prAdapter->rRxCtrl, RX_DATA_MSDU_IN_AMSDU_COUNT); + RX_INC_CNT(&prAdapter->rRxCtrl, RX_DATA_AMSDU_COUNT); + break; + + case RX_PAYLOAD_FORMAT_MIDDLE_SUB_AMSDU: + prReorderQueParm->fgAmsduNeedLastFrame = TRUE; + RX_INC_CNT(&prAdapter->rRxCtrl, RX_DATA_MSDU_IN_AMSDU_COUNT); + if (prReorderQueParm->u4SeqNo != u4SeqNo) { + RX_INC_CNT(&prAdapter->rRxCtrl, RX_DATA_AMSDU_MISS_COUNT); + RX_INC_CNT(&prAdapter->rRxCtrl, RX_DATA_AMSDU_COUNT); + } + break; + case RX_PAYLOAD_FORMAT_LAST_SUB_AMSDU: + prReorderQueParm->fgAmsduNeedLastFrame = FALSE; + RX_INC_CNT(&prAdapter->rRxCtrl, RX_DATA_MSDU_IN_AMSDU_COUNT); + if (prReorderQueParm->u4SeqNo != u4SeqNo) { + RX_INC_CNT(&prAdapter->rRxCtrl, RX_DATA_AMSDU_MISS_COUNT); + RX_INC_CNT(&prAdapter->rRxCtrl, RX_DATA_AMSDU_COUNT); + } + break; + + case RX_PAYLOAD_FORMAT_MSDU: + if (prReorderQueParm->fgAmsduNeedLastFrame) { + RX_INC_CNT(&prAdapter->rRxCtrl, RX_DATA_AMSDU_MISS_COUNT); + prReorderQueParm->fgAmsduNeedLastFrame = FALSE; + } + break; + default: + break; + } + + prReorderQueParm->u4SeqNo = u4SeqNo; +#endif + + RX_DIRECT_REORDER_LOCK(prAdapter, 0); + /* After resuming, WinStart and WinEnd are obsolete and unsync + * with AP's SN. So assign the SN of first packet to WinStart + * as "Fall Within" case. + */ + if (prReorderQueParm->fgFirstSnToWinStart) { + DBGLOG(QM, INFO, + "[%u] First resumed SN(%u) reset Window{%u,%u}\n", + prSwRfb->ucTid, prSwRfb->u2SSN, + prReorderQueParm->u2WinStart, + prReorderQueParm->u2WinEnd); + + prReorderQueParm->u2WinStart = prSwRfb->u2SSN; + prReorderQueParm->u2WinEnd = + ((prReorderQueParm->u2WinStart) + + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT; + prReorderQueParm->fgFirstSnToWinStart = FALSE; + } + + /* Insert reorder packet */ + qmInsertReorderPkt(prAdapter, prSwRfb, prReorderQueParm, prReturnedQue); + RX_DIRECT_REORDER_UNLOCK(prAdapter, 0); +} + +VOID qmProcessBarFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT P_QUE_T prReturnedQue) +{ + + P_STA_RECORD_T prStaRec; + P_HW_MAC_RX_DESC_T prRxStatus; + P_RX_BA_ENTRY_T prReorderQueParm; + P_CTRL_BAR_FRAME_T prBarCtrlFrame; + + UINT_32 u4SSN; + UINT_32 u4WinStart; + UINT_32 u4WinEnd; + + ASSERT(prSwRfb); + ASSERT(prReturnedQue); + ASSERT(prSwRfb->prRxStatus); + ASSERT(prSwRfb->pvHeader); + + prRxStatus = prSwRfb->prRxStatus; + + prBarCtrlFrame = (P_CTRL_BAR_FRAME_T) prSwRfb->pvHeader; + + prSwRfb->ucTid = + (*((PUINT_16) ((PUINT_8) prBarCtrlFrame + CTRL_BAR_BAR_CONTROL_OFFSET))) >> BAR_CONTROL_TID_INFO_OFFSET; + prSwRfb->u2SSN = + (*((PUINT_16) ((PUINT_8) prBarCtrlFrame + CTRL_BAR_BAR_INFORMATION_OFFSET))) >> OFFSET_BAR_SSC_SN; + + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); + + /* Incorrect STA_REC index */ + prSwRfb->ucStaRecIdx = secLookupStaRecIndexFromTA(prAdapter, prBarCtrlFrame->aucSrcAddr); + if (prSwRfb->ucStaRecIdx >= CFG_STA_REC_NUM) { + 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 */ + prSwRfb->prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + prStaRec = prSwRfb->prStaRec; + if (prStaRec == NULL) { + /* ASSERT(prStaRec); */ + return; + } +#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; + } + + RX_DIRECT_REORDER_LOCK(prAdapter, 0); + + u4SSN = (UINT_32) (prSwRfb->u2SSN); + 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; +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + prReorderQueParm->u8LastAmsduSubIdx = RX_PAYLOAD_FORMAT_MSDU; +#endif + DBGLOG(QM, TRACE, "QM:(BAR)[%u](%u){%u,%u}\n", prSwRfb->ucTid, + u4SSN, prReorderQueParm->u2WinStart, + prReorderQueParm->u2WinEnd); + qmPopOutDueToFallAhead(prAdapter, prReorderQueParm, prReturnedQue); + } else { + DBGLOG(QM, TRACE, "QM:(BAR)(%u)(%u){%u,%u}\n", prSwRfb->ucTid, + u4SSN, u4WinStart, u4WinEnd); + } + RX_DIRECT_REORDER_UNLOCK(prAdapter, 0); +} + +VOID qmInsertReorderPkt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, + IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue) +{ + UINT_32 u4SeqNo; + UINT_32 u4WinStart; + UINT_32 u4WinEnd; + + /* Start to reorder packets */ + u4SeqNo = (UINT_32) (prSwRfb->u2SSN); + u4WinStart = (UINT_32) (prReorderQueParm->u2WinStart); + u4WinEnd = (UINT_32) (prReorderQueParm->u2WinEnd); + + /* Debug */ + DBGLOG(QM, LOUD, "QM:(R)[%u](%u){%u,%u}\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(prAdapter, 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)[%u](%u){%u,%u}\n", + prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); + + prReorderQueParm->u2WinStart = (UINT_16) u4SeqNo; + prReorderQueParm->u2WinEnd = + ((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT; + prReorderQueParm->fgIsWaitingForPktWithSsn = FALSE; +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + prReorderQueParm->u8LastAmsduSubIdx = RX_PAYLOAD_FORMAT_MSDU; +#endif + } +#endif + + qmPopOutDueToFallWithin(prAdapter, 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)))) { + + UINT_16 u2Delta, u2BeforeWinEnd; + UINT_32 u4BeforeCount, u4MissingCount; + +#if QM_RX_WIN_SSN_AUTO_ADVANCING + if (prReorderQueParm->fgIsWaitingForPktWithSsn) + prReorderQueParm->fgIsWaitingForPktWithSsn = FALSE; +#endif + + qmInsertFallAheadReorderPkt(prAdapter, prSwRfb, prReorderQueParm, prReturnedQue); + + u2BeforeWinEnd = prReorderQueParm->u2WinEnd; + + /* Advance the window after inserting a new tail */ + prReorderQueParm->u2WinEnd = (UINT_16) u4SeqNo; + prReorderQueParm->u2WinStart = + (prReorderQueParm->u2WinEnd + MAX_SEQ_NO_COUNT - + prReorderQueParm->u2WinSize + 1) % MAX_SEQ_NO_COUNT; +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + prReorderQueParm->u8LastAmsduSubIdx = RX_PAYLOAD_FORMAT_MSDU; +#endif + u4BeforeCount = prReorderQueParm->rReOrderQue.u4NumElem; + qmPopOutDueToFallAhead(prAdapter, prReorderQueParm, prReturnedQue); + + if (prReorderQueParm->u2WinEnd >= u2BeforeWinEnd) + u2Delta = prReorderQueParm->u2WinEnd - u2BeforeWinEnd; + else + u2Delta = MAX_SEQ_NO_COUNT - (u2BeforeWinEnd - prReorderQueParm->u2WinEnd); + + u4MissingCount = u2Delta - (u4BeforeCount - prReorderQueParm->rReOrderQue.u4NumElem); + + RX_ADD_CNT(&prAdapter->rRxCtrl, RX_DATA_REORDER_MISS_COUNT, u4MissingCount); + } + /* Case 3: Fall behind */ + else { +#if QM_RX_WIN_SSN_AUTO_ADVANCING && QM_RX_INIT_FALL_BEHIND_PASS + if (prReorderQueParm->fgIsWaitingForPktWithSsn) { + DBGLOG(QM, LOUD, "QM:(P)[%u](%u){%u,%u}\n", + prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); + qmPopOutReorderPkt(prAdapter, prSwRfb, prReturnedQue, + RX_DATA_REORDER_BEHIND_COUNT); + return; + } +#endif + + /* An erroneous packet */ + DBGLOG(QM, LOUD, "QM:(D)[%u](%u){%u,%u}\n", prSwRfb->ucTid, + u4SeqNo, u4WinStart, u4WinEnd); + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + qmPopOutReorderPkt(prAdapter, prSwRfb, prReturnedQue, + RX_DATA_REORDER_BEHIND_COUNT); + return; + } +} + +VOID qmInsertFallWithinReorderPkt(IN P_ADAPTER_T prAdapter, 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; + P_HW_MAC_RX_DESC_T prRxStatus; + UINT_8 u8AmsduSubframeIdx; /* RX reorder for one MSDU in AMSDU issue */ + + ASSERT(prSwRfb); + ASSERT(prReorderQueParm); + ASSERT(prReturnedQue); + + prReorderQue = &(prReorderQueParm->rReOrderQue); + prExaminedQueuedSwRfb = (P_SW_RFB_T) QUEUE_GET_HEAD(prReorderQue); + + prRxStatus = prSwRfb->prRxStatus; + u8AmsduSubframeIdx = HAL_RX_STATUS_GET_PAYLOAD_FORMAT(prRxStatus); + + /* 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)) { +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + /* if middle or last and first is not duplicated, not a duplicat packet */ + if (!prReorderQueParm->fgIsAmsduDuplicated && + (u8AmsduSubframeIdx == RX_PAYLOAD_FORMAT_MIDDLE_SUB_AMSDU || + u8AmsduSubframeIdx == RX_PAYLOAD_FORMAT_LAST_SUB_AMSDU)) { + + prExaminedQueuedSwRfb = + (P_SW_RFB_T) (((P_QUE_ENTRY_T) prExaminedQueuedSwRfb)->prNext); + while (prExaminedQueuedSwRfb && + ((prExaminedQueuedSwRfb->u2SSN) == (prSwRfb->u2SSN))) + prExaminedQueuedSwRfb = + (P_SW_RFB_T) (((P_QUE_ENTRY_T) prExaminedQueuedSwRfb)->prNext); + + break; + } + /* if first is duplicated, drop subsequent middle and last frames */ + if (u8AmsduSubframeIdx == RX_PAYLOAD_FORMAT_FIRST_SUB_AMSDU) + prReorderQueParm->fgIsAmsduDuplicated = TRUE; +#endif + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + qmPopOutReorderPkt(prAdapter, prSwRfb, prReturnedQue, RX_DUPICATE_DROP_COUNT); + 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); +#if CFG_SUPPORT_RX_AMSDU + prReorderQueParm->fgIsAmsduDuplicated = FALSE; +#endif + + /* 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_ADAPTER_T prAdapter, 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); +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + prReorderQueParm->fgIsAmsduDuplicated = FALSE; +#endif + 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 qmPopOutReorderPkt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT P_QUE_T prReturnedQue, + IN ENUM_RX_STATISTIC_COUNTER_T eRxCounter) +{ + UINT_32 u4PktCnt = 0; + /* RX reorder for one MSDU in AMSDU issue */ +#if 0 + P_SW_RFB_T prAmsduSwRfb; +#endif + + u4PktCnt++; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T)prSwRfb); + +#if 0 + u4PktCnt += prSwRfb->rAmsduQue.u4NumElem; + QUEUE_REMOVE_HEAD(&prSwRfb->rAmsduQue, prAmsduSwRfb, P_SW_RFB_T); + while (prAmsduSwRfb) { + /* Update MSDU destination of AMSDU */ + prAmsduSwRfb->eDst = prSwRfb->eDst; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T)prAmsduSwRfb); + QUEUE_REMOVE_HEAD(&prSwRfb->rAmsduQue, prAmsduSwRfb, P_SW_RFB_T); + } +#endif + + RX_ADD_CNT(&prAdapter->rRxCtrl, eRxCounter, u4PktCnt); +} + +VOID qmPopOutDueToFallWithin(IN P_ADAPTER_T prAdapter, 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; + P_HW_MAC_RX_DESC_T prRxStatus; + UINT_8 fgIsAmsduSubframe;/* RX reorder for one MSDU in AMSDU issue */ + + 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; + + /* RX reorder for one MSDU in AMSDU issue */ + prRxStatus = prReorderedSwRfb->prRxStatus; + fgIsAmsduSubframe = HAL_RX_STATUS_GET_PAYLOAD_FORMAT(prRxStatus); +#if CFG_SUPPORT_RX_AMSDU + /* If SN + 1 come and last frame is first or middle, update winstart */ + if ((qmCompareSnIsLessThan((prReorderQueParm->u2WinStart), (prReorderedSwRfb->u2SSN))) + && (prReorderQueParm->u4SeqNo != prReorderQueParm->u2WinStart)) { + if (prReorderQueParm->u8LastAmsduSubIdx == RX_PAYLOAD_FORMAT_FIRST_SUB_AMSDU + || prReorderQueParm->u8LastAmsduSubIdx == RX_PAYLOAD_FORMAT_MIDDLE_SUB_AMSDU) { + + prReorderQueParm->u2WinStart = + (((prReorderQueParm->u2WinStart) + 1) % MAX_SEQ_NO_COUNT); + prReorderQueParm->u8LastAmsduSubIdx = RX_PAYLOAD_FORMAT_MSDU; + } + } +#endif + /* SN == WinStart, so the head packet shall be indicated (advance the window) */ + if ((prReorderedSwRfb->u2SSN) == (prReorderQueParm->u2WinStart)) { + + fgDequeuHead = TRUE; + /* RX reorder for one MSDU in AMSDU issue */ + /* if last frame, winstart++. Otherwise, keep winstart */ + if (fgIsAmsduSubframe == RX_PAYLOAD_FORMAT_LAST_SUB_AMSDU + || fgIsAmsduSubframe == RX_PAYLOAD_FORMAT_MSDU) + prReorderQueParm->u2WinStart = (((prReorderedSwRfb->u2SSN) + 1) % MAX_SEQ_NO_COUNT); +#if CFG_SUPPORT_RX_AMSDU + prReorderQueParm->u8LastAmsduSubIdx = fgIsAmsduSubframe; +#endif + } + /* SN > WinStart, break to update WinEnd */ + else { + /* Start bubble timer */ + if (!prReorderQueParm->fgHasBubble) { + cnmTimerStartTimer(prAdapter, &(prReorderQueParm->rReorderBubbleTimer), + QM_RX_BA_ENTRY_MISS_TIMEOUT_MS); + prReorderQueParm->fgHasBubble = TRUE; + prReorderQueParm->u2FirstBubbleSn = prReorderQueParm->u2WinStart; + + DBGLOG(QM, TRACE, + "QM:(Bub Timer) STA[%u] TID[%u] BubSN[%u] Win{%u, %u}\n", + prReorderQueParm->ucStaRecIdx, + prReorderedSwRfb->ucTid, + prReorderQueParm->u2FirstBubbleSn, + prReorderQueParm->u2WinStart, + prReorderQueParm->u2WinEnd); + } + + if (fgMissing && CHECK_FOR_TIMEOUT(rCurrentTime, *prMissTimeout, + MSEC_TO_SYSTIME(QM_RX_BA_ENTRY_MISS_TIMEOUT_MS))) { + + DBGLOG(QM, TRACE, + "QM:RX BA Timout Next Tid %u SSN %u\n", + prReorderQueParm->ucTid, + prReorderedSwRfb->u2SSN); + fgDequeuHead = TRUE; + prReorderQueParm->u2WinStart = (((prReorderedSwRfb->u2SSN) + 1) % MAX_SEQ_NO_COUNT); +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + prReorderQueParm->u8LastAmsduSubIdx = RX_PAYLOAD_FORMAT_MSDU; +#endif + 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--; + DBGLOG(QM, LOUD, "QM: [%u] %u (%u)\n", + prReorderQueParm->ucTid, + prReorderedSwRfb->u2PacketLen, + prReorderedSwRfb->u2SSN); + qmPopOutReorderPkt(prAdapter, prReorderedSwRfb, prReturnedQue, RX_DATA_REORDER_WITHIN_COUNT); + } + } + + 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_ADAPTER_T prAdapter, IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue) +{ + P_SW_RFB_T prReorderedSwRfb; + P_QUE_T prReorderQue; + BOOLEAN fgDequeuHead; + P_HW_MAC_RX_DESC_T prRxStatus; + UINT_8 fgIsAmsduSubframe;/* RX reorder for one MSDU in AMSDU issue */ + + 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; + + /* RX reorder for one MSDU in AMSDU issue */ + prRxStatus = prReorderedSwRfb->prRxStatus; + fgIsAmsduSubframe = HAL_RX_STATUS_GET_PAYLOAD_FORMAT(prRxStatus); +#if CFG_SUPPORT_RX_AMSDU + /* If SN + 1 come and last frame is first or middle, update winstart */ + if ((qmCompareSnIsLessThan((prReorderQueParm->u2WinStart), (prReorderedSwRfb->u2SSN))) + && (prReorderQueParm->u4SeqNo != prReorderQueParm->u2WinStart)) { + if (prReorderQueParm->u8LastAmsduSubIdx == RX_PAYLOAD_FORMAT_FIRST_SUB_AMSDU + || prReorderQueParm->u8LastAmsduSubIdx == RX_PAYLOAD_FORMAT_MIDDLE_SUB_AMSDU) { + + prReorderQueParm->u2WinStart = + (((prReorderQueParm->u2WinStart) + 1) % MAX_SEQ_NO_COUNT); + prReorderQueParm->u8LastAmsduSubIdx = RX_PAYLOAD_FORMAT_MSDU; + } + } +#endif + /* SN == WinStart, so the head packet shall be indicated (advance the window) */ + if ((prReorderedSwRfb->u2SSN) == (prReorderQueParm->u2WinStart)) { + + fgDequeuHead = TRUE; + /* RX reorder for one MSDU in AMSDU issue */ + /* if last frame, winstart++. Otherwise, keep winstart */ + if (fgIsAmsduSubframe == RX_PAYLOAD_FORMAT_LAST_SUB_AMSDU + || fgIsAmsduSubframe == RX_PAYLOAD_FORMAT_MSDU) + prReorderQueParm->u2WinStart = (((prReorderedSwRfb->u2SSN) + 1) % MAX_SEQ_NO_COUNT); +#if CFG_SUPPORT_RX_AMSDU + prReorderQueParm->u8LastAmsduSubIdx = fgIsAmsduSubframe; +#endif + } + + /* 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 { + /* Start bubble timer */ + if (!prReorderQueParm->fgHasBubble) { + cnmTimerStartTimer(prAdapter, &(prReorderQueParm->rReorderBubbleTimer), + QM_RX_BA_ENTRY_MISS_TIMEOUT_MS); + prReorderQueParm->fgHasBubble = TRUE; + prReorderQueParm->u2FirstBubbleSn = prReorderQueParm->u2WinStart; + + DBGLOG(QM, TRACE, + "QM:(Bub Timer) STA[%u] TID[%u] BubSN[%u] Win{%u,%u}\n", + prReorderQueParm->ucStaRecIdx, + prReorderedSwRfb->ucTid, + prReorderQueParm->u2FirstBubbleSn, + prReorderQueParm->u2WinStart, + prReorderQueParm->u2WinEnd); + } + 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--; + DBGLOG(QM, TRACE, "QM: [%u] %u (%u)\n", + prReorderQueParm->ucTid, + prReorderedSwRfb->u2PacketLen, + prReorderedSwRfb->u2SSN); + + qmPopOutReorderPkt(prAdapter, prReorderedSwRfb, prReturnedQue, RX_DATA_REORDER_AHEAD_COUNT); + } + } + + /* After WinStart has been determined, update the WinEnd */ + prReorderQueParm->u2WinEnd = + (((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT); + +} + +VOID qmHandleReorderBubbleTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr) +{ + P_RX_BA_ENTRY_T prReorderQueParm = (P_RX_BA_ENTRY_T) ulParamPtr; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; + P_WIFI_EVENT_T prEvent = NULL; + P_EVENT_CHECK_REORDER_BUBBLE_T prCheckReorderEvent; + + KAL_SPIN_LOCK_DECLARATION(); + + if (!prReorderQueParm->fgIsValid) { + DBGLOG(QM, TRACE, "QM:(Bub Check Cancel) STA[%u] TID[%u], No Rx BA entry\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + return; + } + + if (!prReorderQueParm->fgHasBubble) { + DBGLOG(QM, TRACE, + "QM:(Bub Check Cancel) STA[%u] TID[%u], Bubble has been filled\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + return; + } + + DBGLOG(QM, TRACE, "QM:(Bub Timeout) STA[%u] TID[%u] BubSN[%u]\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid, prReorderQueParm->u2FirstBubbleSn); + + /* Generate a self-inited event to Rx path */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_REMOVE_HEAD(&prAdapter->rRxCtrl.rFreeSwRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + if (prSwRfb) { + prEvent = (P_WIFI_EVENT_T) (prSwRfb->pucRecvBuff); + prEvent->ucEID = EVENT_ID_CHECK_REORDER_BUBBLE; + prEvent->ucSeqNum = 0; + prEvent->u2PacketLength = sizeof(WIFI_EVENT_T) + sizeof(EVENT_CHECK_REORDER_BUBBLE_T); + + prCheckReorderEvent = (P_EVENT_CHECK_REORDER_BUBBLE_T) prEvent->aucBuffer; + prCheckReorderEvent->ucStaRecIdx = prReorderQueParm->ucStaRecIdx; + prCheckReorderEvent->ucTid = prReorderQueParm->ucTid; + + prSwRfb->ucPacketType = RX_PKT_TYPE_SW_DEFINED; + prSwRfb->prRxStatus->u2PktTYpe = RXM_RXD_PKT_TYPE_SW_EVENT; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_INSERT_TAIL(&prAdapter->rRxCtrl.rReceivedRfbList, &prSwRfb->rQueEntry); + RX_INC_CNT(&prAdapter->rRxCtrl, RX_MPDU_TOTAL_COUNT); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + DBGLOG(QM, LOUD, "QM:(Bub Check Event Sent) STA[%u] TID[%u]\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + + nicRxProcessRFBs(prAdapter); + + DBGLOG(QM, LOUD, "QM:(Bub Check Event Handled) STA[%u] TID[%u]\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + } else { + DBGLOG(QM, TRACE, + "QM:(Bub Check Cancel) STA[%u] TID[%u], Bub check event alloc failed\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + + cnmTimerStartTimer(prAdapter, &(prReorderQueParm->rReorderBubbleTimer), QM_RX_BA_ENTRY_MISS_TIMEOUT_MS); + + DBGLOG(QM, TRACE, + "QM:(Bub Timer Restart) STA[%u] TID[%u] BubSN[%u] Win{%u,%u}\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid, + prReorderQueParm->u2FirstBubbleSn, + prReorderQueParm->u2WinStart, + prReorderQueParm->u2WinEnd); + } + +} + +VOID qmHandleEventCheckReorderBubble(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_EVENT_CHECK_REORDER_BUBBLE_T prCheckReorderEvent; + P_RX_BA_ENTRY_T prReorderQueParm; + P_QUE_T prReorderQue; + QUE_T rReturnedQue; + P_QUE_T prReturnedQue = &rReturnedQue; + P_SW_RFB_T prReorderedSwRfb, prSwRfb; + OS_SYSTIME *prMissTimeout; + + prCheckReorderEvent = (P_EVENT_CHECK_REORDER_BUBBLE_T) (prEvent->aucBuffer); + + QUEUE_INITIALIZE(prReturnedQue); + + /* Get target Rx BA entry */ + prReorderQueParm = qmLookupRxBaEntry(prAdapter, prCheckReorderEvent->ucStaRecIdx, prCheckReorderEvent->ucTid); + + /* Sanity Check */ + if (!prReorderQueParm) { + DBGLOG(QM, TRACE, "QM:(Bub Check Cancel) STA[%u] TID[%u], No Rx BA entry\n", + prCheckReorderEvent->ucStaRecIdx, prCheckReorderEvent->ucTid); + return; + } + + if (!prReorderQueParm->fgIsValid) { + DBGLOG(QM, TRACE, "QM:(Bub Check Cancel) STA[%u] TID[%u], No Rx BA entry\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + return; + } + + if (!prReorderQueParm->fgHasBubble) { + DBGLOG(QM, TRACE, + "QM:(Bub Check Cancel) STA[%u] TID[%u], Bubble has been filled\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + return; + } + + prReorderQue = &(prReorderQueParm->rReOrderQue); + + RX_DIRECT_REORDER_LOCK(prAdapter, 0); + + if (QUEUE_IS_EMPTY(prReorderQue)) { + prReorderQueParm->fgHasBubble = FALSE; + + DBGLOG(QM, TRACE, + "QM:(Bub Check Cancel) STA[%u] TID[%u], Bubble has been filled\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + RX_DIRECT_REORDER_UNLOCK(prAdapter, 0); + return; + } + + DBGLOG(QM, TRACE, "QM:(Bub Check Event Got) STA[%u] TID[%u]\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + + /* Expected bubble timeout => pop out packets before win_end */ + if (prReorderQueParm->u2FirstBubbleSn == prReorderQueParm->u2WinStart) { + prReorderedSwRfb = (P_SW_RFB_T)QUEUE_GET_TAIL(prReorderQue); + + prReorderQueParm->u2WinStart = prReorderedSwRfb->u2SSN + 1; + if (prReorderQueParm->u2WinStart >= MAX_SEQ_NO_COUNT) + prReorderQueParm->u2WinStart %= MAX_SEQ_NO_COUNT; + + prReorderQueParm->u2WinEnd = + ((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT; +#if CFG_SUPPORT_RX_AMSDU + prReorderQueParm->u8LastAmsduSubIdx = RX_PAYLOAD_FORMAT_MSDU; +#endif + qmPopOutDueToFallAhead(prAdapter, prReorderQueParm, prReturnedQue); + + DBGLOG(QM, TRACE, + "QM:(Bub Flush) STA[%u] TID[%u] BubSN[%u] Win{%u,%u}\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid, + prReorderQueParm->u2FirstBubbleSn, + prReorderQueParm->u2WinStart, + prReorderQueParm->u2WinEnd); + + prReorderQueParm->fgHasBubble = FALSE; + RX_DIRECT_REORDER_UNLOCK(prAdapter, 0); + + /* process prReturnedQue after unlock prReturnedQue */ + if (QUEUE_IS_NOT_EMPTY(prReturnedQue)) { + P_QUE_ENTRY_T prTail = QUEUE_GET_TAIL(prReturnedQue); + + QM_RX_SET_NEXT_SW_RFB((P_SW_RFB_T)prTail, NULL); + + prSwRfb = (P_SW_RFB_T) QUEUE_GET_HEAD(prReturnedQue); + while (prSwRfb) { + DBGLOG(QM, TRACE, + "QM:(Bub Flush) STA[%u] TID[%u] Pop Out SN[%u]\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid, prSwRfb->u2SSN); + + prSwRfb = (P_SW_RFB_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prSwRfb); + } + + wlanProcessQueuedSwRfb(prAdapter, (P_SW_RFB_T) QUEUE_GET_HEAD(prReturnedQue)); + } else { + DBGLOG(QM, TRACE, "QM:(Bub Flush) STA[%u] TID[%u] Pop Out 0 packet\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid); + } + } + /* First bubble has been filled but others exist */ + else { + prReorderQueParm->u2FirstBubbleSn = prReorderQueParm->u2WinStart; + DBGLOG(QM, TRACE, + "QM:(Bub Timer) STA[%u] TID[%u] BubSN[%u] Win{%u,%u}\n", + prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid, + prReorderQueParm->u2FirstBubbleSn, + prReorderQueParm->u2WinStart, + prReorderQueParm->u2WinEnd); + RX_DIRECT_REORDER_UNLOCK(prAdapter, 0); + + cnmTimerStartTimer(prAdapter, + &(prReorderQueParm->rReorderBubbleTimer), + QM_RX_BA_ENTRY_MISS_TIMEOUT_MS); + } + + prMissTimeout = &g_arMissTimeout[prReorderQueParm->ucStaRecIdx][prReorderQueParm->ucTid]; + if (QUEUE_IS_EMPTY(prReorderQue)) { + DBGLOG(QM, TRACE, "QM:(Bub Check) Reset prMissTimeout to zero\n"); + *prMissTimeout = 0; + } else { + DBGLOG(QM, TRACE, "QM:(Bub Check) Reset prMissTimeout to current time\n"); + GET_CURRENT_SYSTIME(prMissTimeout); + } +} + +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->aucBuffer); + 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->aucBuffer); + 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_STA_REC_NUM); + + if (ucStaRecIdx >= CFG_STA_REC_NUM) { + /* Invalid STA_REC index, discard the event packet */ + DBGLOG(QM, WARN, "QM: (WARNING) RX ADDBA Event for a invalid ucStaRecIdx = %d\n", ucStaRecIdx); + return FALSE; + } + + prStaRec = &prAdapter->arStaRec[ucStaRecIdx]; + ASSERT(prStaRec); + + /* if(!(prStaRec->fgIsValid)){ */ + /* DbgPrint("QM: (WARNING) Invalid STA when adding an RX BA\n"); */ + /* return FALSE; */ + /* } */ + + /* 4 <1> Delete before adding */ + /* Remove the BA entry for the same (STA, TID) tuple if it exists */ + if (qmLookupRxBaEntry(prAdapter, ucStaRecIdx, ucTid)) + qmDelRxBaEntry(prAdapter, ucStaRecIdx, ucTid, TRUE); /* prQM->ucRxBaCount-- */ + /* 4 <2> Add a new BA entry */ + /* No available entry to store the BA agreement info. Retrun FALSE. */ + if (prQM->ucRxBaCount >= CFG_NUM_OF_RX_BA_AGREEMENTS) { + DBGLOG(QM, ERROR, "QM: **failure** (limited resource, ucRxBaCount=%d)\n", prQM->ucRxBaCount); + return FALSE; + } + /* Find the free-to-use BA entry */ + for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) { + if (!prQM->arRxBaTable[i].fgIsValid) { + prRxBaEntry = &(prQM->arRxBaTable[i]); + prQM->ucRxBaCount++; + DBGLOG(QM, LOUD, "QM: ucRxBaCount=%d\n", prQM->ucRxBaCount); + break; + } + } + + /* If a free-to-use entry is found, configure it and associate it with the STA_REC */ + u2WinSize += CFG_RX_BA_INC_SIZE; + if (prRxBaEntry) { + prRxBaEntry->ucStaRecIdx = ucStaRecIdx; + prRxBaEntry->ucTid = ucTid; + prRxBaEntry->u2WinStart = u2WinStart; + prRxBaEntry->u2WinSize = u2WinSize; + prRxBaEntry->u2WinEnd = ((u2WinStart + u2WinSize - 1) % MAX_SEQ_NO_COUNT); +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + prRxBaEntry->u8LastAmsduSubIdx = RX_PAYLOAD_FORMAT_MSDU; + prRxBaEntry->fgAmsduNeedLastFrame = FALSE; + prRxBaEntry->fgIsAmsduDuplicated = FALSE; +#endif + prRxBaEntry->fgIsValid = TRUE; + prRxBaEntry->fgIsWaitingForPktWithSsn = TRUE; + prRxBaEntry->fgHasBubble = FALSE; + + g_arMissTimeout[ucStaRecIdx][ucTid] = 0; + + DBGLOG(QM, INFO, + "QM: +RxBA(STA=%u TID=%u WinStart=%u WinEnd=%u WinSize=%u)\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_STA_REC_NUM); + + 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 (prRxBaEntry->fgHasBubble) { + DBGLOG(QM, TRACE, "QM:(Bub Check Cancel) STA[%u] TID[%u], DELBA\n", + prRxBaEntry->ucStaRecIdx, prRxBaEntry->ucTid); + + cnmTimerStopTimer(prAdapter, &prRxBaEntry->rReorderBubbleTimer); + prRxBaEntry->fgHasBubble = FALSE; + } +#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 +} + +VOID mqmParseAssocReqWmmIe(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucIE, IN P_STA_RECORD_T prStaRec) +{ + P_IE_WMM_INFO_T prIeWmmInfo; + UINT_8 ucQosInfo; + UINT_8 ucQosInfoAC; + UINT_8 ucBmpAC; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + + if ((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) && (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) { + + switch (WMM_IE_OUI_SUBTYPE(pucIE)) { + case VENDOR_OUI_SUBTYPE_WMM_INFO: + if (IE_LEN(pucIE) != 7) + break; /* WMM Info IE with a wrong length */ + + prStaRec->fgIsQoS = TRUE; + prStaRec->fgIsWmmSupported = TRUE; + + prIeWmmInfo = (P_IE_WMM_INFO_T) pucIE; + ucQosInfo = prIeWmmInfo->ucQosInfo; + ucQosInfoAC = ucQosInfo & BITS(0, 3); + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucUapsd)) + prStaRec->fgIsUapsdSupported = (ucQosInfoAC) ? TRUE : FALSE; + else + prStaRec->fgIsUapsdSupported = FALSE; + + 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; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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_32 u4Flags; + + 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 (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS)) + return; + + /* Determine whether QoS is enabled with the association */ + else { + prStaRec->u4Flags = 0; + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_VENDOR: + mqmParseAssocReqWmmIe(prAdapter, pucIE, prStaRec); + +#if CFG_SUPPORT_MTK_SYNERGY + if (rlmParseCheckMTKOuiIE(prAdapter, pucIE, &u4Flags)) + prStaRec->u4Flags = u4Flags; +#endif + + 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); + + } +} + +VOID mqmParseAssocRspWmmIe(IN PUINT_8 pucIE, IN P_STA_RECORD_T prStaRec) +{ + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + + 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; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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_32 u4Flags; + + 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.ucQoS); + + /* If the device does not support QoS or if WMM is not supported by the peer, exit. */ + /* if((!prAdapter->rWifiVar.fgSupportQoS) || (!prStaRec->fgIsWmmSupported)) */ + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS)) + return; + + /* Determine whether QoS is enabled with the association */ + else { + prStaRec->u4Flags = 0; + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_VENDOR: + /* Process WMM related IE */ + mqmParseAssocRspWmmIe(pucIE, prStaRec); + +#if CFG_SUPPORT_MTK_SYNERGY + if (rlmParseCheckMTKOuiIE(prAdapter, pucIE, &u4Flags)) + prStaRec->u4Flags = u4Flags; +#endif + + 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->ucBssIndex); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mqmProcessBcn(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength) +{ + P_BSS_INFO_T prBssInfo; + BOOLEAN fgNewParameter; + UINT_8 i; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + ASSERT(pucIE); + + DBGLOG(QM, TRACE, "Enter %s\n", __func__); + + fgNewParameter = FALSE; + + for (i = 0; i < BSS_INFO_NUM; i++) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, i); + + 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 = mqmParseEdcaParameters(prAdapter, + prSwRfb, pucIE, u2IELength, FALSE); + } + } + + /* Appy new parameters if necessary */ + if (fgNewParameter) { + /* DBGLOG(QM, INFO, ("Update EDCA parameter for BSS[%u]\n", prBssInfo->ucBssIndex)); */ + nicQmUpdateWmmParms(prAdapter, prBssInfo->ucBssIndex); + fgNewParameter = FALSE; + } + } /* end of IS_BSS_ACTIVE() */ + } +} + +BOOLEAN mqmUpdateEdcaParameters(IN P_BSS_INFO_T prBssInfo, IN PUINT_8 pucIE, IN BOOLEAN fgForceOverride) +{ + P_AC_QUE_PARMS_T prAcQueParams; + P_IE_WMM_PARAM_T prIeWmmParam; + ENUM_WMM_ACI_T eAci; + BOOLEAN fgNewParameter = FALSE; + + do { + if (IE_LEN(pucIE) != 24) + break; /* WMM Param IE with a wrong length */ + + prIeWmmParam = (P_IE_WMM_PARAM_T) pucIE; + + /* Check the Parameter Set Count to determine whether EDCA parameters have been changed */ + if (!fgForceOverride) { + if (mqmCompareEdcaParameters(prIeWmmParam, prBssInfo)) { + fgNewParameter = FALSE; + break; + } + } + + fgNewParameter = TRUE; + /* Update Parameter Set Count */ + prBssInfo->ucWmmParamSetCount = (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); + DBGLOG(QM, INFO, + "BSS[%u]: eAci[%d] ACM[%d] Aifsn[%d] CWmin/max[%d/%d] TxopLimit[%d] NewParameter[%d]\n", + prBssInfo->ucBssIndex, eAci, prAcQueParams->ucIsACMSet, + prAcQueParams->u2Aifsn, prAcQueParams->u2CWmin, prAcQueParams->u2CWmax, + prAcQueParams->u2TxopLimit, fgNewParameter); + } + } while (FALSE); + + return fgNewParameter; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +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; + BOOLEAN fgNewParameter = FALSE; + + DEBUGFUNC("mqmParseEdcaParameters"); + + if (!prSwRfb) + return FALSE; + + if (!pucIE) + return FALSE; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + /* ASSERT(prStaRec); */ + + if (prStaRec == NULL) + return FALSE; + + DBGLOG(QM, TRACE, "QM: (fgIsWmmSupported=%d, fgIsQoS=%d)\n", prStaRec->fgIsWmmSupported, prStaRec->fgIsQoS); + + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS) || (!prStaRec->fgIsWmmSupported) + || (!prStaRec->fgIsQoS)) + return FALSE; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + /* Goal: Obtain the EDCA parameters */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_WMM: + if (!((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) && + (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3)))) + break; + + switch (WMM_IE_OUI_SUBTYPE(pucIE)) { + case VENDOR_OUI_SUBTYPE_WMM_PARAM: + fgNewParameter = mqmUpdateEdcaParameters(prBssInfo, pucIE, fgForceOverride); + break; + + default: + /* Other WMM QoS IEs. Ignore */ + break; + } + + /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS, ... (not cared) */ + break; + default: + break; + } + } + + return fgNewParameter; +} + +BOOLEAN mqmCompareEdcaParameters(IN P_IE_WMM_PARAM_T prIeWmmParam, IN P_BSS_INFO_T prBssInfo) +{ + P_AC_QUE_PARMS_T prAcQueParams; + P_WMM_AC_PARAM_T prWmmAcParams; + ENUM_WMM_ACI_T eAci; + + /* return FALSE; */ + + /* Check Set Count */ + if (prBssInfo->ucWmmParamSetCount != (prIeWmmParam->ucQosInfo & WMM_QOS_INFO_PARAM_SET_CNT)) + return FALSE; + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prAcQueParams = &prBssInfo->arACQueParms[eAci]; + prWmmAcParams = &prIeWmmParam->arAcParam[eAci]; + + /* ACM */ + if (prAcQueParams->ucIsACMSet != ((prWmmAcParams->ucAciAifsn & WMM_ACIAIFSN_ACM) ? TRUE : FALSE)) + return FALSE; + + /* AIFSN */ + if (prAcQueParams->u2Aifsn != (prWmmAcParams->ucAciAifsn & WMM_ACIAIFSN_AIFSN)) + return FALSE; + + /* CW Max */ + if (prAcQueParams->u2CWmax != + (BIT((prWmmAcParams->ucEcw & WMM_ECW_WMAX_MASK) >> WMM_ECW_WMAX_OFFSET) - 1)) + return FALSE; + + /* CW Min */ + if (prAcQueParams->u2CWmin != (BIT(prWmmAcParams->ucEcw & WMM_ECW_WMIN_MASK) - 1)) + return FALSE; + + if (prAcQueParams->u2TxopLimit != prWmmAcParams->u2TxopLimit) + return FALSE; + } + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ + P_WMM_AC_PARAM_T prAcParam = &prIeWmmParam->arAcParam[u4AcOffset]; + + prAcQueParams->ucIsACMSet = (prAcParam->ucAciAifsn & WMM_ACIAIFSN_ACM) ? TRUE : FALSE; + + prAcQueParams->u2Aifsn = (prAcParam->ucAciAifsn & WMM_ACIAIFSN_AIFSN); + + prAcQueParams->u2CWmax = BIT((prAcParam->ucEcw & WMM_ECW_WMAX_MASK) >> WMM_ECW_WMAX_OFFSET) - 1; + + prAcQueParams->u2CWmin = BIT(prAcParam->ucEcw & WMM_ECW_WMIN_MASK) - 1; + + WLAN_GET_FIELD_16(&prAcParam->u2TxopLimit, &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; + BOOLEAN fgIsHtVht; + + DEBUGFUNC("mqmProcessScanResult"); + + ASSERT(prScanResult); + ASSERT(prStaRec); + + /* Reset the flag before parsing */ + prStaRec->fgIsWmmSupported = FALSE; + prStaRec->fgIsUapsdSupported = FALSE; + prStaRec->fgIsQoS = FALSE; + + fgIsHtVht = FALSE; + + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS)) + return; + + u2IELength = prScanResult->u2IELength; + pucIE = prScanResult->aucIEBuf; + + /* <1> Determine whether the peer supports WMM/QoS and UAPSDU */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + + case ELEM_ID_EXTENDED_CAP: +#if CFG_SUPPORT_TDLS + TdlsBssExtCapParse(prStaRec, pucIE); +#endif /* CFG_SUPPORT_TDLS */ + break; + + case ELEM_ID_WMM: + if ((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) && + (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) { + + switch (WMM_IE_OUI_SUBTYPE(pucIE)) { + case VENDOR_OUI_SUBTYPE_WMM_PARAM: + if (IE_LEN(pucIE) != 24) + break; /* WMM Param IE with a wrong length */ + + prStaRec->fgIsWmmSupported = TRUE; + prStaRec->fgIsUapsdSupported = + ((((P_IE_WMM_PARAM_T) pucIE)->ucQosInfo) + & WMM_QOS_INFO_UAPSD) ? TRUE : FALSE; + break; + + case VENDOR_OUI_SUBTYPE_WMM_INFO: + if (IE_LEN(pucIE) != 7) + break; /* WMM Info IE with a wrong length */ + + prStaRec->fgIsWmmSupported = TRUE; + prStaRec->fgIsUapsdSupported = + ((((P_IE_WMM_INFO_T) pucIE)->ucQosInfo) + & WMM_QOS_INFO_UAPSD) ? TRUE : FALSE; + break; + + default: + /* A WMM QoS IE that doesn't matter. Ignore it. */ + break; + } + } + /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS, ... (not cared) */ + + break; + + default: + /* A WMM IE that doesn't matter. Ignore it. */ + break; + } + } + + /* <1> Determine QoS */ + if (prStaRec->ucDesiredPhyTypeSet & (PHY_TYPE_SET_802_11N | PHY_TYPE_SET_802_11AC)) + fgIsHtVht = TRUE; + + if (fgIsHtVht || prStaRec->fgIsWmmSupported) + prStaRec->fgIsQoS = TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Generate the WMM Info IE by Param +* +* \param[in] prAdapter Adapter pointer +* @param prMsduInfo The TX MMPDU +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +mqmFillWmmInfoIE(P_UINT_8 pucOutBuf, + BOOLEAN fgSupportUAPSD, UINT_8 ucBmpDeliveryAC, UINT_8 ucBmpTriggerAC, UINT_8 ucUapsdSp) +{ + P_IE_WMM_INFO_T prIeWmmInfo; + UINT_32 ucUapsd[] = { + WMM_QOS_INFO_BE_UAPSD, + WMM_QOS_INFO_BK_UAPSD, + WMM_QOS_INFO_VI_UAPSD, + WMM_QOS_INFO_VO_UAPSD + }; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + + ASSERT(pucOutBuf); + + prIeWmmInfo = (P_IE_WMM_INFO_T) pucOutBuf; + + prIeWmmInfo->ucId = ELEM_ID_WMM; + prIeWmmInfo->ucLength = ELEM_MAX_LEN_WMM_INFO; + + /* WMM-2.2.1 WMM Information Element Field Values */ + prIeWmmInfo->aucOui[0] = aucWfaOui[0]; + prIeWmmInfo->aucOui[1] = aucWfaOui[1]; + prIeWmmInfo->aucOui[2] = aucWfaOui[2]; + prIeWmmInfo->ucOuiType = VENDOR_OUI_TYPE_WMM; + prIeWmmInfo->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_INFO; + + prIeWmmInfo->ucVersion = VERSION_WMM; + prIeWmmInfo->ucQosInfo = 0; + + /* UAPSD initial queue configurations (delivery and trigger enabled) */ + if (fgSupportUAPSD) { + UINT_8 ucQosInfo = 0; + UINT_8 i; + + /* Static U-APSD setting */ + for (i = ACI_BE; i <= ACI_VO; i++) { + if (ucBmpDeliveryAC & ucBmpTriggerAC & BIT(i)) + ucQosInfo |= (UINT_8) ucUapsd[i]; + } + + if (ucBmpDeliveryAC & ucBmpTriggerAC) { + switch (ucUapsdSp) { + case WMM_MAX_SP_LENGTH_ALL: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_ALL; + break; + + case WMM_MAX_SP_LENGTH_2: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_2; + break; + + case WMM_MAX_SP_LENGTH_4: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_4; + break; + + case WMM_MAX_SP_LENGTH_6: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_6; + break; + + default: + DBGLOG(QM, 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. */ + return IE_SIZE(prIeWmmInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Generate the WMM Info IE +* +* \param[in] prAdapter Adapter pointer +* @param prMsduInfo The TX MMPDU +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +mqmGenerateWmmInfoIEByStaRec(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_STA_RECORD_T prStaRec, P_UINT_8 pucOutBuf) +{ + P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo; + BOOLEAN fgSupportUapsd; + + ASSERT(pucOutBuf); + + /* In case QoS is not turned off, exit directly */ + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS)) + return 0; + + if (prStaRec == NULL) + return 0; + + if (!prStaRec->fgIsWmmSupported) + return 0; + + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + + fgSupportUapsd = (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucUapsd) + && prStaRec->fgIsUapsdSupported); + + return mqmFillWmmInfoIE(pucOutBuf, + fgSupportUapsd, + prPmProfSetupInfo->ucBmpDeliveryAC, + prPmProfSetupInfo->ucBmpTriggerAC, prPmProfSetupInfo->ucUapsdSp); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + UINT_32 u4Length; + + DEBUGFUNC("mqmGenerateWmmInfoIE"); + + ASSERT(prMsduInfo); + + /* In case QoS is not turned off, exit directly */ + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS)) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + if (prStaRec == NULL) + return; + + if (!prStaRec->fgIsWmmSupported) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + u4Length = mqmGenerateWmmInfoIEByStaRec(prAdapter, + prBssInfo, + prStaRec, ((PUINT_8) prMsduInfo->prPacket + prMsduInfo->u2FrameLength)); + + prMsduInfo->u2FrameLength += u4Length; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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; + P_WMM_AC_PARAM_T prAcParam; + + DEBUGFUNC("mqmGenerateWmmParamIE"); + DBGLOG(QM, LOUD, "\n"); + + ASSERT(prMsduInfo); + + /* In case QoS is not turned off, exit directly */ + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS)) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (prStaRec) { + if (!prStaRec->fgIsQoS) + return; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + + if (!prBssInfo->fgIsQBSS) + return; + + 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 initial queue configurations (delivery and trigger enabled) */ + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucUapsd)) + prIeWmmParam->ucQosInfo |= WMM_QOS_INFO_UAPSD; + + /* EDCA parameter */ + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prAcParam = &prIeWmmParam->arAcParam[eAci]; + + /* DBGLOG(QM, LOUD, ("MQM: eAci=%d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", */ + /* eAci,prBssInfo->arACQueParmsForBcast[eAci].ucIsACMSet , */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn, */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmin, */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmax, */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit)); */ + + /* ACI */ + prAcParam->ucAciAifsn = aucACI[eAci]; + /* ACM */ + if (prBssInfo->arACQueParmsForBcast[eAci].ucIsACMSet) + prAcParam->ucAciAifsn |= WMM_ACIAIFSN_ACM; + /* AIFSN */ + prAcParam->ucAciAifsn |= (prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn & WMM_ACIAIFSN_AIFSN); + + /* ECW Min */ + prAcParam->ucEcw = (prBssInfo->aucCWminLog2ForBcast[eAci] & WMM_ECW_WMIN_MASK); + /* ECW Max */ + prAcParam->ucEcw |= + ((prBssInfo->aucCWmaxLog2ForBcast[eAci] << WMM_ECW_WMAX_OFFSET) & WMM_ECW_WMAX_MASK); + + /* Txop limit */ + WLAN_SET_FIELD_16(&prAcParam->u2TxopLimit, prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit); + + } + + /* Increment the total IE length for the Element ID and Length fields. */ + prMsduInfo->u2FrameLength += IE_SIZE(prIeWmmParam); + +} + +#if CFG_SUPPORT_TDLS +/*----------------------------------------------------------------------------*/ +/*! +* @brief Generate the WMM Param IE +* +* \param[in] prAdapter Adapter pointer +* @param prMsduInfo The TX MMPDU +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 mqmGenerateWmmParamIEByParam(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, PUINT_8 pOutBuf) +{ + 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_AC_QUE_PARMS_T prACQueParms; + 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 */ + + ENUM_WMM_ACI_T eAci; + P_WMM_AC_PARAM_T prAcParam; + + DEBUGFUNC("mqmGenerateWmmParamIE"); + DBGLOG(QM, LOUD, "\n"); + + ASSERT(pOutBuf); + + /* In case QoS is not turned off, exit directly */ + if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucQoS)) + return WLAN_STATUS_SUCCESS; + + if (!prBssInfo->fgIsQBSS) + return WLAN_STATUS_SUCCESS; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.fgTdlsBufferSTASleep)) { + prACQueParms = prBssInfo->arACQueParmsForBcast; + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prACQueParms[eAci].ucIsACMSet = 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]; + + /* used to send WMM IE */ + prBssInfo->aucCWminLog2ForBcast[eAci] = auCWminLog2ForBcast[eAci]; + prBssInfo->aucCWmaxLog2ForBcast[eAci] = auCWmaxLog2ForBcast[eAci]; + + /* DBGLOG(TDLS, INFO, "eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, + * TxopLimit = %d\n", + * eAci, prACQueParms[eAci].ucIsACMSet, prACQueParms[eAci].u2Aifsn, + * prACQueParms[eAci].u2CWmin, prACQueParms[eAci].u2CWmax, prACQueParms[eAci].u2TxopLimit); + */ + } + } + + prIeWmmParam = (P_IE_WMM_PARAM_T) pOutBuf; + + prIeWmmParam->ucId = ELEM_ID_WMM; + prIeWmmParam->ucLength = ELEM_MAX_LEN_WMM_PARAM; + + /* WMM-2.2.1 WMM Information Element Field Values */ + prIeWmmParam->aucOui[0] = aucWfaOui[0]; + prIeWmmParam->aucOui[1] = aucWfaOui[1]; + prIeWmmParam->aucOui[2] = aucWfaOui[2]; + prIeWmmParam->ucOuiType = VENDOR_OUI_TYPE_WMM; + prIeWmmParam->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_PARAM; + + prIeWmmParam->ucVersion = VERSION_WMM; + /* STAUT Buffer STA, also sleeps (optional) + * The STAUT sends a TDLS Setup/Response/Confirm Frame, to STA 2, via the AP, + * with all four AC flags set to 1 in QoS Info Field + */ + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.fgTdlsBufferSTASleep)) + prIeWmmParam->ucQosInfo = (0x0F & WMM_QOS_INFO_PARAM_SET_CNT); + else + prIeWmmParam->ucQosInfo = (prBssInfo->ucWmmParamSetCount & WMM_QOS_INFO_PARAM_SET_CNT); + + /* UAPSD initial queue configurations (delivery and trigger enabled) */ + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucUapsd)) + prIeWmmParam->ucQosInfo |= WMM_QOS_INFO_UAPSD; + + /* EDCA parameter */ + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + prAcParam = &prIeWmmParam->arAcParam[eAci]; + + /* DBGLOG(QM, LOUD, ("MQM: eAci=%d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", */ + /* eAci,prBssInfo->arACQueParmsForBcast[eAci].ucIsACMSet , */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn, */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmin, */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmax, */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit)); */ + + /* ACI */ + prAcParam->ucAciAifsn = aucACI[eAci]; + + if (IS_FEATURE_ENABLED( + prAdapter->rWifiVar.fgTdlsBufferSTASleep)) { + /* ACM */ + if (prBssInfo->arACQueParmsForBcast[eAci].ucIsACMSet) + prAcParam->ucAciAifsn |= WMM_ACIAIFSN_ACM; + /* AIFSN */ + prAcParam->ucAciAifsn |= + (prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn + & WMM_ACIAIFSN_AIFSN); + + /* ECW Min */ + prAcParam->ucEcw = + (prBssInfo->aucCWminLog2ForBcast[eAci] + & WMM_ECW_WMIN_MASK); + /* ECW Max */ + prAcParam->ucEcw |= + ((prBssInfo->aucCWmaxLog2ForBcast[eAci] + << WMM_ECW_WMAX_OFFSET) & WMM_ECW_WMAX_MASK); + + /* Txop limit */ + WLAN_SET_FIELD_16(&prAcParam->u2TxopLimit, + prBssInfo->arACQueParmsForBcast[eAci]. + u2TxopLimit); + } else { + /* ACM */ + if (prBssInfo->arACQueParms[eAci].ucIsACMSet) + prAcParam->ucAciAifsn |= WMM_ACIAIFSN_ACM; + /* AIFSN */ + prAcParam->ucAciAifsn |= + (prBssInfo->arACQueParms[eAci].u2Aifsn + & WMM_ACIAIFSN_AIFSN); + + /* ECW Min */ + prAcParam->ucEcw = + (prBssInfo->arACQueParms[eAci].u2CWmin + & WMM_ECW_WMIN_MASK); + /* ECW Max */ + prAcParam->ucEcw |= + ((prBssInfo->arACQueParms[eAci].u2CWmax + << WMM_ECW_WMAX_OFFSET) & WMM_ECW_WMAX_MASK); + + /* Txop limit */ + WLAN_SET_FIELD_16(&prAcParam->u2TxopLimit, + prBssInfo->arACQueParms[eAci].u2TxopLimit); + } + } + + /* Increment the total IE length for the Element ID and Length fields. */ + return IE_SIZE(prIeWmmParam); + +} + +#endif + +BOOLEAN isProbeResponse(IN P_MSDU_INFO_T prMgmtTxMsdu) +{ + P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T) NULL; + + prWlanHdr = (P_WLAN_MAC_HEADER_T) ((ULONG) prMgmtTxMsdu->prPacket + + MAC_TX_RESERVED_FIELD); + + return (prWlanHdr->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_PROBE_RSP ? + TRUE : FALSE; +} + + +ENUM_FRAME_ACTION_T +qmGetFrameAction(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, + IN UINT_8 ucStaRecIdx, IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_FRAME_TYPE_IN_CMD_Q_T eFrameType, IN UINT_16 u2FrameLength) +{ + ENUM_FRAME_ACTION_T eFrameAction = FRAME_ACTION_TX_PKT; + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + UINT_8 ucTC = nicTxGetFrameResourceType(eFrameType, prMsduInfo); + UINT_16 u2FreeResource = nicTxGetResource(prAdapter, ucTC); + UINT_8 ucReqResource; + P_WIFI_VAR_T prWifiVar = &prAdapter->rWifiVar; + + DEBUGFUNC("qmGetFrameAction"); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, ucStaRecIdx); + + do { + /* 4 <1> Tx, if FORCE_TX is set */ + if (prMsduInfo) { + if (prMsduInfo->ucControlFlag & MSDU_CONTROL_FLAG_FORCE_TX) { + eFrameAction = FRAME_ACTION_TX_PKT; + break; + } + } + /* 4 <2> Drop, if BSS is inactive */ + if (!IS_BSS_ACTIVE(prBssInfo)) { + DBGLOG(QM, TRACE, "Drop packets (BSS[%u] is INACTIVE)\n", prBssInfo->ucBssIndex); + eFrameAction = FRAME_ACTION_DROP_PKT; + break; + } + + /* 4 <3> Queue, if BSS is absent, drop probe response */ + if (prBssInfo->fgIsNetAbsent) { + if (prMsduInfo && isProbeResponse(prMsduInfo)) { + DBGLOG(TX, TRACE, "Drop probe response (BSS[%u] Absent)\n", + prBssInfo->ucBssIndex); + + eFrameAction = FRAME_ACTION_DROP_PKT; + } else { + DBGLOG(TX, TRACE, "Queue packets (BSS[%u] Absent)\n", + prBssInfo->ucBssIndex); + eFrameAction = FRAME_ACTION_QUEUE_PKT; + } + break; + } + + /* 4 <4> Check based on StaRec */ + if (prStaRec) { + /* 4 <4.1> Drop, if StaRec is not in use */ + if (!prStaRec->fgIsInUse) { + DBGLOG(QM, TRACE, "Drop packets (Sta[%u] not in USE)\n", prStaRec->ucIndex); + eFrameAction = FRAME_ACTION_DROP_PKT; + break; + } + /* 4 <4.2> Sta in PS */ + if (prStaRec->fgIsInPS) { + ucReqResource = nicTxGetPageCount(u2FrameLength, FALSE) + + prWifiVar->ucCmdRsvResource + QM_MGMT_QUEUED_THRESHOLD; + + /* 4 <4.2.1> Tx, if resource is enough */ + if (u2FreeResource > ucReqResource) { + eFrameAction = FRAME_ACTION_TX_PKT; + break; + } + /* 4 <4.2.2> Queue, if resource is not enough */ + else { + DBGLOG(QM, INFO, "Queue packets (Sta[%u] in PS)\n", prStaRec->ucIndex); + eFrameAction = FRAME_ACTION_QUEUE_PKT; + break; + } + } + } + + } while (FALSE); + + /* <5> Resource CHECK! */ + /* <5.1> Reserve resource for CMD & 1X */ + if (eFrameType == FRAME_TYPE_MMPDU) { + ucReqResource = nicTxGetPageCount(u2FrameLength, FALSE) + prWifiVar->ucCmdRsvResource; + + if (u2FreeResource < ucReqResource) { + eFrameAction = FRAME_ACTION_QUEUE_PKT; + DBGLOG(QM, INFO, "Queue MGMT (MSDU[0x%p] Req/Rsv/Free[%u/%u/%u])\n", + prMsduInfo, + nicTxGetPageCount(u2FrameLength, FALSE), prWifiVar->ucCmdRsvResource, u2FreeResource); + } + + /* <6> Timeout check! */ +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + if ((eFrameAction == FRAME_ACTION_QUEUE_PKT) && prMsduInfo) { + OS_SYSTIME rCurrentTime, rEnqTime; + + GET_CURRENT_SYSTIME(&rCurrentTime); + rEnqTime = prMsduInfo->rPktProfile.rEnqueueTimestamp; + + if (CHECK_FOR_TIMEOUT(rCurrentTime, rEnqTime, + MSEC_TO_SYSTIME(prWifiVar->u4MgmtQueueDelayTimeout))) { + eFrameAction = FRAME_ACTION_DROP_PKT; + DBGLOG(QM, INFO, "Drop MGMT (MSDU[0x%p] timeout[%ums])\n", + prMsduInfo, prWifiVar->u4MgmtQueueDelayTimeout); + } + } +#endif + } + + return eFrameAction; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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; +#if (CFG_SUPPORT_DFS_MASTER == 1) + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; +#endif + prEventBssStatus = (P_EVENT_BSS_ABSENCE_PRESENCE_T) (prEvent->aucBuffer); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prEventBssStatus->ucBssIndex); + fgIsNetAbsentOld = prBssInfo->fgIsNetAbsent; + prBssInfo->fgIsNetAbsent = prEventBssStatus->ucIsAbsent; + prBssInfo->ucBssFreeQuota = prEventBssStatus->ucBssFreeQuota; +#if (CFG_SUPPORT_DFS_MASTER == 1) + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prBssInfo->u4PrivateData); +#endif + /* DBGLOG(QM, TRACE, ("qmHandleEventBssAbsencePresence (ucNetTypeIdx=%d, fgIsAbsent=%d, FreeQuota=%d)\n", */ + /* prEventBssStatus->ucNetTypeIdx, prBssInfo->fgIsNetAbsent, prBssInfo->ucBssFreeQuota)); */ + + DBGLOG(QM, INFO, "NAF=%d,%d,%d\n", + prEventBssStatus->ucBssIndex, prBssInfo->fgIsNetAbsent, prBssInfo->ucBssFreeQuota); + + if (!prBssInfo->fgIsNetAbsent) { + /* ToDo:: QM_DBG_CNT_INC */ + QM_DBG_CNT_INC(&(prAdapter->rQM), QM_DBG_CNT_27); + } else { + /* ToDo:: QM_DBG_CNT_INC */ + QM_DBG_CNT_INC(&(prAdapter->rQM), QM_DBG_CNT_28); + } + /* From Absent to Present */ + if ((fgIsNetAbsentOld) && (!prBssInfo->fgIsNetAbsent)) { + if (HAL_IS_TX_DIRECT(prAdapter)) + nicTxDirectStartCheckQTimer(prAdapter); + else + kalSetEvent(prAdapter->prGlueInfo); +#if (CFG_SUPPORT_DFS_MASTER == 1) + if (prP2pRoleFsmInfo && prAdapter->prGlueInfo-> + prP2PInfo[prP2pRoleFsmInfo->ucRoleIndex] + ->fgIsNetDevDetach) { + netif_device_attach(prAdapter->prGlueInfo-> + prP2PInfo[prP2pRoleFsmInfo->ucRoleIndex] + ->prDevHandler); + prAdapter->prGlueInfo + ->prP2PInfo[prP2pRoleFsmInfo->ucRoleIndex] + ->fgIsNetDevDetach = FALSE; + } +#endif + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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->aucBuffer); + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventStaChangePsMode->ucStaRecIdx); + /* ASSERT(prStaRec); */ + + if (prStaRec) { + + fgIsInPSOld = prStaRec->fgIsInPS; + prStaRec->fgIsInPS = prEventStaChangePsMode->ucIsInPs; + + qmUpdateFreeQuota(prAdapter, + prStaRec, prEventStaChangePsMode->ucUpdateMode, prEventStaChangePsMode->ucFreeQuota); + + /* DBGLOG(QM, TRACE, ("qmHandleEventStaChangePsMode (ucStaRecIdx=%d, fgIsInPs=%d)\n", */ + /* prEventStaChangePsMode->ucStaRecIdx, prStaRec->fgIsInPS)); */ + + DBGLOG(QM, INFO, "PS=%d,%d\n", prEventStaChangePsMode->ucStaRecIdx, prStaRec->fgIsInPS); + + /* From PS to Awake */ + if ((fgIsInPSOld) && (!prStaRec->fgIsInPS)) { + if (HAL_IS_TX_DIRECT(prAdapter)) + nicTxDirectStartCheckQTimer(prAdapter); + else + 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->aucBuffer); + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventStaUpdateFreeQuota->ucStaRecIdx); + /* 2013/08/30 + * Station Record possible been freed. + */ + /* ASSERT(prStaRec); */ + + if (prStaRec) { + if (prStaRec->fgIsInPS) { + qmUpdateFreeQuota(prAdapter, + prStaRec, + prEventStaUpdateFreeQuota->ucUpdateMode, + prEventStaUpdateFreeQuota->ucFreeQuota); + + if (HAL_IS_TX_DIRECT(prAdapter)) + nicTxDirectStartCheckQTimer(prAdapter); + else + 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; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Dump current queue status +* +* \param[in] (none) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 qmDumpQueueStatus(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuf, IN UINT_32 u4Max) +{ + P_TX_CTRL_T prTxCtrl; + P_QUE_MGT_T prQM; + P_GLUE_INFO_T prGlueInfo; + UINT_32 i, u4TotalBufferCount, u4TotalPageCount; + UINT_32 u4CurBufferCount, u4CurPageCount; + UINT_32 u4Len = 0; + + DEBUGFUNC(("%s", __func__)); + + prTxCtrl = &prAdapter->rTxCtrl; + prQM = &prAdapter->rQM; + prGlueInfo = prAdapter->prGlueInfo; + u4TotalBufferCount = 0; + u4TotalPageCount = 0; + u4CurBufferCount = 0; + u4CurPageCount = 0; + + LOGBUF(pucBuf, u4Max, u4Len, "\n"); + LOGBUF(pucBuf, u4Max, u4Len, "------------\n"); + + for (i = TC0_INDEX; i < TC_NUM; i++) { + LOGBUF(pucBuf, u4Max, u4Len, "TC%u ResCount: Max[%02u/%03u] Free[%02u/%03u] PreUsed[%03u]\n", + i, prTxCtrl->rTc.au4MaxNumOfBuffer[i], prTxCtrl->rTc.au4MaxNumOfPage[i], + prTxCtrl->rTc.au4FreeBufferCount[i], prTxCtrl->rTc.au4FreePageCount[i], + prTxCtrl->rTc.au4PreUsedPageCount[i]); + + u4TotalBufferCount += prTxCtrl->rTc.au4MaxNumOfBuffer[i]; + u4TotalPageCount += prTxCtrl->rTc.au4MaxNumOfPage[i]; + u4CurBufferCount += prTxCtrl->rTc.au4FreeBufferCount[i]; + u4CurPageCount += prTxCtrl->rTc.au4FreePageCount[i]; + } + + LOGBUF(pucBuf, u4Max, u4Len, "ToT ResCount: Max[%02u/%03u] Free[%02u/%03u]\n", + u4TotalBufferCount, u4TotalPageCount, u4CurBufferCount, u4CurPageCount); + + LOGBUF(pucBuf, u4Max, u4Len, "---------------------------------\n"); + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + for (i = TC0_INDEX; i < TC_NUM; i++) { + LOGBUF(pucBuf, u4Max, u4Len, "TC%u AvgQLen[%04u] minRsv[%02u] CurTcRes[%02u] GrtdTcRes[%02u]\n", + i, QM_GET_TX_QUEUE_LEN(prAdapter, i), prQM->au4MinReservedTcResource[i], + prQM->au4CurrentTcResource[i], prQM->au4GuaranteedTcResource[i]); + } + + LOGBUF(pucBuf, u4Max, u4Len, "Resource Residual[%u] ExtraRsv[%u]\n", + prQM->u4ResidualTcResource, prQM->u4ExtraReservedTcResource); + LOGBUF(pucBuf, u4Max, u4Len, "QueLenMovingAvg[%u] Time2AdjResource[%u] Time2UpdateQLen[%u]\n", + prQM->u4QueLenMovingAverage, prQM->u4TimeToAdjustTcResource, prQM->u4TimeToUpdateQueLen); +#endif + + DBGLOG(SW4, INFO, "---------------------------------\n"); + +#if QM_FORWARDING_FAIRNESS + for (i = 0; i < NUM_OF_PER_STA_TX_QUEUES; i++) { + LOGBUF(pucBuf, u4Max, u4Len, "TC%u HeadSta[%u] ResourceUsedCount[%u]\n", + i, prQM->au4HeadStaRecIndex[i], prQM->au4ResourceUsedCount[i]); + } +#endif + + LOGBUF(pucBuf, u4Max, u4Len, "BMC or unknown TxQueue Len[%u]\n", prQM->arTxQueue[0].u4NumElem); + LOGBUF(pucBuf, u4Max, u4Len, "Pending QLen Normal[%u] Sec[%u] Cmd[%u]\n", + GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum), + GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum), + GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingCmdNum)); + +#if defined(LINUX) + for (i = 0; i < HW_BSSID_NUM; i++) { + LOGBUF(pucBuf, u4Max, u4Len, "Pending BSS[%u] QLen[%u:%u:%u:%u]\n", i, + prGlueInfo->ai4TxPendingFrameNumPerQueue[i][0], + prGlueInfo->ai4TxPendingFrameNumPerQueue[i][1], + prGlueInfo->ai4TxPendingFrameNumPerQueue[i][2], + prGlueInfo->ai4TxPendingFrameNumPerQueue[i][3]); + } +#endif + LOGBUF(pucBuf, u4Max, u4Len, "Pending FWD CNT[%d]\n", prTxCtrl->i4PendingFwdFrameCount); + LOGBUF(pucBuf, u4Max, u4Len, "Pending MGMT CNT[%d]\n", prTxCtrl->i4TxMgmtPendingNum); + + LOGBUF(pucBuf, u4Max, u4Len, "---------------------------------\n"); + + LOGBUF(pucBuf, u4Max, u4Len, "Total RFB[%u]\n", CFG_RX_MAX_PKT_NUM); + LOGBUF(pucBuf, u4Max, u4Len, "rFreeSwRfbList[%u]\n", prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem); + LOGBUF(pucBuf, u4Max, u4Len, "rReceivedRfbList[%u]\n", prAdapter->rRxCtrl.rReceivedRfbList.u4NumElem); + LOGBUF(pucBuf, u4Max, u4Len, "rIndicatedRfbList[%u]\n", prAdapter->rRxCtrl.rIndicatedRfbList.u4NumElem); + LOGBUF(pucBuf, u4Max, u4Len, "ucNumIndPacket[%u]\n", prAdapter->rRxCtrl.ucNumIndPacket); + LOGBUF(pucBuf, u4Max, u4Len, "ucNumRetainedPacket[%u]\n", prAdapter->rRxCtrl.ucNumRetainedPacket); + + LOGBUF(pucBuf, u4Max, u4Len, "---------------------------------\n"); + LOGBUF(pucBuf, u4Max, u4Len, "CMD: Free[%u/%u] Cmd[%u] ToTx[%u]\n", + prAdapter->rFreeCmdList.u4NumElem, CFG_TX_MAX_CMD_PKT_NUM, + prAdapter->rPendingCmdQueue.u4NumElem, prGlueInfo->rCmdQueue.u4NumElem); + LOGBUF(pucBuf, u4Max, u4Len, "MSDU: Free[%u/%u] Pending[%u] Done[%u]\n", + prAdapter->rTxCtrl.rFreeMsduInfoList.u4NumElem, CFG_TX_MAX_PKT_NUM, + prAdapter->rTxCtrl.rTxMgmtTxingQueue.u4NumElem, + prAdapter->rTxDataDoneQueue.u4NumElem); + + LOGBUF(pucBuf, u4Max, u4Len, "---------------------------------\n"); + + return u4Len; +} + +#if CFG_M0VE_BA_TO_DRIVER +/*----------------------------------------------------------------------------*/ +/*! +* @brief Send DELBA Action frame +* +* @param fgIsInitiator DELBA_ROLE_INITIATOR or DELBA_ROLE_RECIPIENT +* @param prStaRec Pointer to the STA_REC of the receiving peer +* @param u4Tid TID of the BA entry +* @param u4ReasonCode The reason code carried in the Action frame +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +mqmSendDelBaFrame(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsInitiator, IN P_STA_RECORD_T prStaRec, IN UINT_32 u4Tid, IN UINT_32 u4ReasonCode) +{ + + P_MSDU_INFO_T prTxMsduInfo; + P_ACTION_DELBA_FRAME_T prDelBaFrame; + P_BSS_INFO_T prBssInfo; + + DBGLOG(QM, WARN, "[Puff]: Enter mqmSendDelBaFrame()\n"); + + ASSERT(prStaRec); + + /* 3 <1> Block the message in case of invalid STA */ + if (!prStaRec->fgIsInUse) { + DBGLOG(QM, WARN, "[Puff][%s]: (Warning) sta_rec is not inuse\n", __func__); + return; + } + /* Check HT-capabale STA */ + if (!(prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_HT)) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) sta is NOT HT-capable(0x%08X)\n", __func__, + prStaRec->ucDesiredPhyTypeSet); + return; + } + /* 4 <2> Construct the DELBA frame */ + prTxMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, ACTION_DELBA_FRAME_LEN); + + if (!prTxMsduInfo) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) DELBA for TID=%ld was not sent (MSDU_INFO alloc failure)\n", + __func__, u4Tid); + return; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + /* Fill the Action frame */ + prDelBaFrame = (P_ACTION_DELBA_FRAME_T) ((UINT_32) (prTxMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + prDelBaFrame->u2FrameCtrl = MAC_FRAME_ACTION; +#if CFG_SUPPORT_802_11W + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(QM, WARN, "[Puff][%s]: (Warning) DELBA is 80211w enabled\n", __func__); + prDelBaFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + } +#endif + + prDelBaFrame->u2DurationID = 0; + prDelBaFrame->ucCategory = CATEGORY_BLOCK_ACK_ACTION; + prDelBaFrame->ucAction = ACTION_DELBA; + + prDelBaFrame->u2DelBaParameterSet = 0; + prDelBaFrame->u2DelBaParameterSet |= ((fgIsInitiator ? ACTION_DELBA_INITIATOR_MASK : 0)); + prDelBaFrame->u2DelBaParameterSet |= ((u4Tid << ACTION_DELBA_TID_OFFSET) & ACTION_DELBA_TID_MASK); + prDelBaFrame->u2ReasonCode = u4ReasonCode; + + COPY_MAC_ADDR(prDelBaFrame->aucDestAddr, prStaRec->aucMacAddr); + COPY_MAC_ADDR(prDelBaFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prDelBaFrame->aucBSSID, prBssInfo->aucBSSID); + + /* 4 <3> Configure the MSDU_INFO and forward it to TXM */ + TX_SET_MMPDU(prAdapter, + prTxMsduInfo, + prStaRec->ucBssIndex, + (prStaRec != NULL) ? (prStaRec->ucIndex) : (STA_REC_INDEX_NOT_FOUND), + WLAN_MAC_HEADER_LEN, ACTION_DELBA_FRAME_LEN, NULL, MSDU_RATE_MODE_AUTO); + +#if CFG_SUPPORT_802_11W + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(RSN, INFO, "Set MSDU_OPT_PROTECTED_FRAME\n"); + nicTxConfigPktOption(prTxMsduInfo, MSDU_OPT_PROTECTED_FRAME, TRUE); + } +#endif + + /* TID and fgIsInitiator are needed when processing TX Done of the DELBA frame */ + prTxMsduInfo->ucTID = (UINT_8) u4Tid; + prTxMsduInfo->ucControlFlag = (fgIsInitiator ? 1 : 0); + + nicTxEnqueueMsdu(prAdapter, prTxMsduInfo); + + DBGLOG(QM, WARN, "[Puff][%s]: Send DELBA for TID=%ld Initiator=%d\n", __func__, u4Tid, fgIsInitiator); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Callback function for the TX Done event for an ADDBA_RSP +* +* @param prMsduInfo The TX packet +* @param rWlanStatus WLAN_STATUS_SUCCESS if TX is successful +* +* @return WLAN_STATUS_BUFFER_RETAINED is returned if the buffer shall not be freed by TXM +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +mqmCallbackAddBaRspSent(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + P_RX_BA_ENTRY_T prRxBaEntry; + P_STA_RECORD_T prStaRec; + P_QUE_MGT_T prQM; + + UINT_32 u4Tid = 0; + + /* ASSERT(prMsduInfo); */ + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + prQM = &prAdapter->rQM; + + DBGLOG(QM, WARN, "[Puff]: Enter mqmCallbackAddBaRspSent()\n"); + + /* 4 <0> Check STA_REC status */ + /* Check STA_REC is inuse */ + if (!prStaRec->fgIsInUse) { + DBGLOG(QM, WARN, "[Puff][%s]: (Warning) sta_rec is not inuse\n", __func__); + return WLAN_STATUS_SUCCESS; + } + /* Check HT-capabale STA */ + if (!(prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_HT)) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) sta is NOT HT-capable(0x%08X)\n", __func__, + prStaRec->ucDesiredPhyTypeSet); + return WLAN_STATUS_SUCCESS; /* To free the received ADDBA_REQ directly */ + } + /* 4 <1> Find the corresponding BA entry */ + u4Tid = prMsduInfo->ucTID; /* TID is stored in MSDU_INFO when composing the ADDBA_RSP frame */ + prRxBaEntry = &prQM->arRxBaTable[u4Tid]; + + /* Note: Due to some reason, for example, receiving a DELBA, the BA entry may not be in state NEGO */ + /* 4 <2> INVALID state */ + if (!prRxBaEntry) { + DBGLOG(QM, WARN, + "[Puff][%s]: (RX_BA) ADDBA_RSP ---> peer (STA=%d TID=%d)(TX successful)(invalid BA)\n", + __func__, prStaRec->ucIndex, u4Tid); + } + /* 4 <3> NEGO, ACTIVE, or DELETING state */ + else { + switch (rTxDoneStatus) { + /* 4 TX Success */ + case TX_RESULT_SUCCESS: + + DBGLOG(QM, WARN, + "[Puff][%s]: (RX_BA) ADDBA_RSP ---> peer (STA=%d TID=%d)(TX successful)\n", + __func__, prStaRec->ucIndex, u4Tid); + + /* 4 NEGO or ACTIVE state */ + if (prRxBaEntry->ucStatus != BA_ENTRY_STATUS_DELETING) + mqmRxModifyBaEntryStatus(prAdapter, prRxBaEntry, BA_ENTRY_STATUS_ACTIVE); + /* 4 DELETING state */ + /* else */ + /* Deleting is on-going, so do nothing and wait for TX done of the DELBA frame */ + + break; + + /* 4 TX Failure */ + default: + + DBGLOG(QM, WARN, + "[Puff][%s]: (RX_BA) ADDBA_RSP ---> peer (STA=%d TID=%ld Entry_Status=%d)(TX failed)\n", + __func__, prStaRec->ucIndex, u4Tid, prRxBaEntry->ucStatus); + + /* 4 NEGO or ACTIVE state */ + /* Notify the host to delete the agreement */ + if (prRxBaEntry->ucStatus != BA_ENTRY_STATUS_DELETING) { + mqmRxModifyBaEntryStatus(prAdapter, prRxBaEntry, BA_ENTRY_STATUS_DELETING); + + /* Send DELBA to the peer to ensure the BA state is synchronized */ + mqmSendDelBaFrame(prAdapter, DELBA_ROLE_RECIPIENT, prStaRec, u4Tid, + STATUS_CODE_UNSPECIFIED_FAILURE); + } + /* 4 DELETING state */ + /* else */ + /* Deleting is on-going, so do nothing and wait for the TX done of the DELBA frame */ + + break; + } + + } + + return WLAN_STATUS_SUCCESS; /* TXM shall release the packet */ + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Check if there is any idle RX BA +* +* @param u4Param (not used) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID mqmTimeoutCheckIdleRxBa(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr) +{ + INT_8 i; + P_RX_BA_ENTRY_T prRxBa; + UINT_32 u4IdleCountThreshold = 0; + P_STA_RECORD_T prStaRec; + P_QUE_MGT_T prQM; + + DBGLOG(QM, WARN, "[Puff]: Enter mqmTimeoutIdleRxBaDetection()\n"); + + prQM = &prAdapter->rQM; + + /* 4 <1> Restart the timer */ + cnmTimerStopTimer(prAdapter, &prAdapter->rMqmIdleRxBaDetectionTimer); + cnmTimerStartTimer(prAdapter, &prAdapter->rMqmIdleRxBaDetectionTimer, MQM_IDLE_RX_BA_CHECK_INTERVAL); + + /* 4 <2> Increment the idle count for each idle BA */ + for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) { + + prRxBa = &prQM->arRxBaTable[i]; + + if (prRxBa->ucStatus == BA_ENTRY_STATUS_ACTIVE) { + + prStaRec = cnmGetStaRecByIndex(prAdapter, prRxBa->ucStaRecIdx); + + if (!prStaRec->fgIsInUse) { + DBGLOG(QM, WARN, "[Puff][%s]: (Warning) sta_rec is not inuse\n", __func__); + ASSERT(0); + } + /* Check HT-capabale STA */ + if (!(prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_HT)) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) sta is NOT HT-capable(0x%08X)\n", + __func__, prStaRec->ucDesiredPhyTypeSet); + ASSERT(0); + } + /* 4 <2.1> Idle detected, increment idle count and see if a DELBA should be sent */ + if (prRxBa->u2SnapShotSN == prStaRec->au2CachedSeqCtrl[prRxBa->ucTid]) { + + prRxBa->ucIdleCount++; + + ASSERT(prRxBa->ucTid < 8); + switch (aucTid2ACI[prRxBa->ucTid]) { + case 0: /* BK */ + u4IdleCountThreshold = MQM_DEL_IDLE_RXBA_THRESHOLD_BK; + break; + case 1: /* BE */ + u4IdleCountThreshold = MQM_DEL_IDLE_RXBA_THRESHOLD_BE; + break; + case 2: /* VI */ + u4IdleCountThreshold = MQM_DEL_IDLE_RXBA_THRESHOLD_VI; + break; + case 3: /* VO */ + u4IdleCountThreshold = MQM_DEL_IDLE_RXBA_THRESHOLD_VO; + break; + } + + if (prRxBa->ucIdleCount >= u4IdleCountThreshold) { + mqmRxModifyBaEntryStatus(prAdapter, prRxBa, BA_ENTRY_STATUS_INVALID); + mqmSendDelBaFrame(prAdapter, DELBA_ROLE_RECIPIENT, prStaRec, + (UINT_32) prRxBa->ucTid, REASON_CODE_PEER_TIME_OUT); + qmDelRxBaEntry(prAdapter, prStaRec->ucIndex, prRxBa->ucTid, TRUE); + } + } + /* 4 <2.2> Activity detected */ + else { + prRxBa->u2SnapShotSN = prStaRec->au2CachedSeqCtrl[prRxBa->ucTid]; + prRxBa->ucIdleCount = 0; + continue; /* check the next BA entry */ + } + } + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Do RX BA entry state transition +* +* @param prRxBaEntry The BA entry pointer +* @param eStatus The state to transition to +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +mqmRxModifyBaEntryStatus(IN P_ADAPTER_T prAdapter, IN P_RX_BA_ENTRY_T prRxBaEntry, IN ENUM_BA_ENTRY_STATUS_T eStatus) +{ + P_STA_RECORD_T prStaRec; + P_QUE_MGT_T prQM; + + BOOLEAN fgResetScoreBoard = FALSE; + + ASSERT(prRxBaEntry); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prRxBaEntry->ucStaRecIdx); + ASSERT(prStaRec); + prQM = &prAdapter->rQM; + + if (prRxBaEntry->ucStatus == (UINT_8) eStatus) { + DBGLOG(QM, WARN, "[Puff][%s]: eStatus are identical...\n", __func__, prRxBaEntry->ucStatus); + return; + } + /* 4 <1> State transition from state X */ + switch (prRxBaEntry->ucStatus) { + + /* 4 <1.1> From (X = INVALID) to (ACTIVE or NEGO or DELETING) */ + case BA_ENTRY_STATUS_INVALID: + + /* Associate the BA entry with the STA_REC when leaving INVALID state */ + kalMemCopy(&prQM->arRxBaTable[prRxBaEntry->ucTid], prRxBaEntry, sizeof(RX_BA_ENTRY_T)); + + /* Increment the RX BA counter */ + prQM->ucRxBaCount++; + ASSERT(prQM->ucRxBaCount <= CFG_NUM_OF_RX_BA_AGREEMENTS); + + /* Since AMPDU may be received during INVALID state */ + fgResetScoreBoard = TRUE; + + /* Reset Idle Count since this BA entry is being activated now. + * Note: If there is no ACTIVE entry, the idle detection timer will not be started. + */ + prRxBaEntry->ucIdleCount = 0; + break; + + /* 4 <1.2> Other cases */ + default: + break; + } + + /* 4 <2> State trasition to state Y */ + switch (eStatus) { + + /* 4 <2.1> From (NEGO, ACTIVE, DELETING) to (Y=INVALID) */ + case BA_ENTRY_STATUS_INVALID: + + /* Disassociate the BA entry with the STA_REC */ + kalMemZero(&prQM->arRxBaTable[prRxBaEntry->ucTid], sizeof(RX_BA_ENTRY_T)); + + /* Decrement the RX BA counter */ + prQM->ucRxBaCount--; + ASSERT(prQM->ucRxBaCount < CFG_NUM_OF_RX_BA_AGREEMENTS); + + /* (TBC) */ + fgResetScoreBoard = TRUE; + + /* If there is not any BA agreement, stop doing idle detection */ + if (prQM->ucRxBaCount == 0) { + if (MQM_CHECK_FLAG(prAdapter->u4FlagBitmap, MQM_FLAG_IDLE_RX_BA_TIMER_STARTED)) { + cnmTimerStopTimer(prAdapter, &prAdapter->rMqmIdleRxBaDetectionTimer); + MQM_CLEAR_FLAG(prAdapter->u4FlagBitmap, MQM_FLAG_IDLE_RX_BA_TIMER_STARTED); + } + } + + break; + + /* 4 <2.2> From (any) to (Y=ACTIVE) */ + case BA_ENTRY_STATUS_ACTIVE: + + /* If there is at least one BA going into ACTIVE, start idle detection */ + if (!MQM_CHECK_FLAG(prAdapter->u4FlagBitmap, MQM_FLAG_IDLE_RX_BA_TIMER_STARTED)) { + cnmTimerInitTimer(prAdapter, &prAdapter->rMqmIdleRxBaDetectionTimer, + (PFN_MGMT_TIMEOUT_FUNC) mqmTimeoutCheckIdleRxBa, (ULONG) NULL); + /* No parameter */ + + cnmTimerStopTimer(prAdapter, &prAdapter->rMqmIdleRxBaDetectionTimer); + +#if MQM_IDLE_RX_BA_DETECTION + cnmTimerStartTimer(prAdapter, &prAdapter->rMqmIdleRxBaDetectionTimer, + MQM_IDLE_RX_BA_CHECK_INTERVAL); + MQM_SET_FLAG(prAdapter->u4FlagBitmap, MQM_FLAG_IDLE_RX_BA_TIMER_STARTED); +#endif + } + + break; + + case BA_ENTRY_STATUS_NEGO: + default: + break; + } + + if (fgResetScoreBoard) { + P_CMD_RESET_BA_SCOREBOARD_T prCmdBody; + + prCmdBody = (P_CMD_RESET_BA_SCOREBOARD_T) + cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_RESET_BA_SCOREBOARD_T)); + ASSERT(prCmdBody); + + prCmdBody->ucflag = MAC_ADDR_TID_MATCH; + prCmdBody->ucTID = prRxBaEntry->ucTid; + kalMemCopy(prCmdBody->aucMacAddr, prStaRec->aucMacAddr, PARAM_MAC_ADDR_LEN); + + wlanoidResetBAScoreboard(prAdapter, prCmdBody, sizeof(CMD_RESET_BA_SCOREBOARD_T)); + + } + + DBGLOG(QM, WARN, "[Puff]QM: (RX_BA) [STA=%d TID=%d] status from %d to %d\n", + prRxBaEntry->ucStaRecIdx, prRxBaEntry->ucTid, prRxBaEntry->ucStatus, eStatus); + + prRxBaEntry->ucStatus = (UINT_8) eStatus; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mqmHandleAddBaReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prBssInfo; + P_ACTION_ADDBA_REQ_FRAME_T prAddBaReq; + ACTION_ADDBA_REQ_BODY_T rAddBaReqBody; + P_ACTION_ADDBA_RSP_FRAME_T prAddBaRsp; + ACTION_ADDBA_RSP_BODY_T rAddBaRspBody; + P_RX_BA_ENTRY_T prRxBaEntry; + P_MSDU_INFO_T prTxMsduInfo; + P_QUE_MGT_T prQM; + + BOOLEAN fgIsReqAccepted = TRUE; /* Reject or accept the ADDBA_REQ */ + BOOLEAN fgIsNewEntryAdded = FALSE; /* Indicator: Whether a new RX BA entry will be added */ + + UINT_32 u4Tid; + UINT_32 u4StaRecIdx; + UINT_16 u2WinStart; + UINT_16 u2WinSize; + UINT_32 u4BuffSize; + +#if CFG_SUPPORT_BCM + UINT_32 u4BuffSizeBT; +#endif + + ASSERT(prSwRfb); + + prStaRec = prSwRfb->prStaRec; + prQM = &prAdapter->rQM; + + do { + + /* 4 <0> Check if this is an active HT-capable STA */ + /* Check STA_REC is inuse */ + if (!prStaRec->fgIsInUse) { + DBGLOG(QM, WARN, "[Puff][%s]: (Warning) sta_rec is not inuse\n", __func__); + break; + } + /* Check HT-capabale STA */ + if (!(prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_HT)) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) sta is NOT HT-capable(0x%08X)\n", __func__, + prStaRec->ucDesiredPhyTypeSet); + break; /* To free the received ADDBA_REQ directly */ + } + /* 4 <1> Check user configurations and HW capabilities */ + /* Check configurations (QoS support, AMPDU RX support) */ + if ((!prAdapter->rWifiVar.fgSupportQoS) || + (!prAdapter->rWifiVar.fgSupportAmpduRx) || (!prStaRec->fgRxAmpduEn)) { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) BA ACK Policy not supported fgSupportQoS(%d)", + __func__, prAdapter->rWifiVar.fgSupportQoS); + DBGLOG(QM, WARN, + "fgSupportAmpduRx(%d), fgRxAmpduEn(%d)\n", + prAdapter->rWifiVar.fgSupportAmpduRx, prStaRec->fgRxAmpduEn); + fgIsReqAccepted = FALSE; /* Will send an ADDBA_RSP with DECLINED */ + } + /* Check capability */ + prAddBaReq = ((P_ACTION_ADDBA_REQ_FRAME_T) (prSwRfb->pvHeader)); + kalMemCopy((PUINT_8) (&rAddBaReqBody), (PUINT_8) (&(prAddBaReq->aucBAParameterSet[0])), 6); + if ((((rAddBaReqBody.u2BAParameterSet) & BA_PARAM_SET_ACK_POLICY_MASK) >> + BA_PARAM_SET_ACK_POLICY_MASK_OFFSET) + != BA_PARAM_SET_ACK_POLICY_IMMEDIATE_BA) { /* Only Immediate_BA is supported */ + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) BA ACK Policy not supported (0x%08X)\n", + __func__, rAddBaReqBody.u2BAParameterSet); + fgIsReqAccepted = FALSE; /* Will send an ADDBA_RSP with DECLINED */ + } + + /* 4 <2> Determine the RX BA entry (existing or to be added) */ + /* Note: BA entry index = (TID, STA_REC index) */ + u4Tid = (((rAddBaReqBody.u2BAParameterSet) & BA_PARAM_SET_TID_MASK) >> BA_PARAM_SET_TID_MASK_OFFSET); + u4StaRecIdx = prStaRec->ucIndex; + DBGLOG(QM, WARN, + "[Puff][%s]: BA entry index = [TID(%d), STA_REC index(%d)]\n", __func__, u4Tid, u4StaRecIdx); + + u2WinStart = ((rAddBaReqBody.u2BAStartSeqCtrl) >> OFFSET_BAR_SSC_SN); + u2WinSize = (((rAddBaReqBody.u2BAParameterSet) & BA_PARAM_SET_BUFFER_SIZE_MASK) + >> BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET); + DBGLOG(QM, WARN, + "[Puff][%s]: BA entry info = [WinStart(%d), WinSize(%d)]\n", __func__, u2WinStart, u2WinSize); + + if (fgIsReqAccepted) { + + prRxBaEntry = &prQM->arRxBaTable[u4Tid]; + + if (!prRxBaEntry) { + + /* 4 INVALID state && BA entry available --> Add a new entry and accept */ + if (prQM->ucRxBaCount < CFG_NUM_OF_RX_BA_AGREEMENTS) { + + fgIsNewEntryAdded = qmAddRxBaEntry(prAdapter, + (UINT_8) u4StaRecIdx, + (UINT_8) u4Tid, u2WinStart, u2WinSize); + + if (!fgIsNewEntryAdded) { + DBGLOG(QM, ERROR, + "[Puff][%s]: (Error) Free RX BA entry alloc failure\n"); + fgIsReqAccepted = FALSE; + } else { + DBGLOG(QM, WARN, "[Puff][%s]: Create a new BA Entry\n"); + } + } + /* 4 INVALID state && BA entry unavailable --> Reject the ADDBA_REQ */ + else { + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) Free RX BA entry unavailable(req: %d)\n", + __func__, prQM->ucRxBaCount); + fgIsReqAccepted = FALSE; /* Will send an ADDBA_RSP with DECLINED */ + } + } else { + + /* 4 NEGO or DELETING state --> Ignore the ADDBA_REQ */ + /* For NEGO: do nothing. Wait for TX Done of ADDBA_RSP */ + /* For DELETING: do nothing. Wait for TX Done of DELBA */ + if (prRxBaEntry->ucStatus != BA_ENTRY_STATUS_ACTIVE) { + DBGLOG(QM, WARN, + "[Puff][%s]:(Warning)ADDBA_REQ for TID=%ld is received, status:%d)\n", + __func__, u4Tid, prRxBaEntry->ucStatus); + break; /* Ignore the ADDBA_REQ since the current state is NEGO */ + } + /* 4 ACTIVE state --> Accept */ + /* Send an ADDBA_RSP to accept the request again */ + /* else */ + } + } + /* 4 <3> Construct the ADDBA_RSP frame */ + prTxMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, ACTION_ADDBA_RSP_FRAME_LEN); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + if (!prTxMsduInfo) { + + /* The peer may send an ADDBA_REQ message later. + * Do nothing to the BA entry. No DELBA will be sent (because cnmMgtPktAlloc() may fail again). + * No BA deletion event will be sent to the host (because cnmMgtPktAlloc() may fail again). + */ + DBGLOG(QM, WARN, "[Puff][%s]: (Warning) ADDBA_RSP alloc failure\n", __func__); + + if (fgIsNewEntryAdded) { + /* If a new entry has been created due to this ADDBA_REQ, delete it */ + ASSERT(prRxBaEntry); + mqmRxModifyBaEntryStatus(prAdapter, prRxBaEntry, BA_ENTRY_STATUS_INVALID); + } + + break; /* Exit directly to free the ADDBA_REQ */ + } + + /* Fill the ADDBA_RSP message */ + prAddBaRsp = (P_ACTION_ADDBA_RSP_FRAME_T) ((UINT_32) (prTxMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + prAddBaRsp->u2FrameCtrl = MAC_FRAME_ACTION; + +#if CFG_SUPPORT_802_11W + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(QM, WARN, "[Puff][%s]: (Warning) ADDBA_RSP is 80211w enabled\n", __func__); + prAddBaReq->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + } +#endif + prAddBaRsp->u2DurationID = 0; + prAddBaRsp->ucCategory = CATEGORY_BLOCK_ACK_ACTION; + prAddBaRsp->ucAction = ACTION_ADDBA_RSP; + prAddBaRsp->ucDialogToken = prAddBaReq->ucDialogToken; + + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) ADDBA_RSP DurationID(%d) Category(%d) Action(%d) DialogToken(%d)\n", + __func__, prAddBaRsp->u2DurationID, prAddBaRsp->ucCategory, + prAddBaRsp->ucAction, prAddBaRsp->ucDialogToken); + + if (fgIsReqAccepted) + rAddBaRspBody.u2StatusCode = STATUS_CODE_SUCCESSFUL; + else + rAddBaRspBody.u2StatusCode = STATUS_CODE_REQ_DECLINED; + + /* WinSize = min(WinSize in ADDBA_REQ, CFG_RX_BA_MAX_WINSIZE) */ + u4BuffSize = (((rAddBaReqBody.u2BAParameterSet) & BA_PARAM_SET_BUFFER_SIZE_MASK) + >> BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET); + + /*If ADDBA req WinSize<=0 => use default WinSize(16) */ + if ((u4BuffSize > CFG_RX_BA_MAX_WINSIZE) || (u4BuffSize <= 0)) + u4BuffSize = CFG_RX_BA_MAX_WINSIZE; +#if CFG_SUPPORT_BCM + /* TODO: Call BT coexistence function to limit the winsize */ + u4BuffSizeBT = bcmRequestBaWinSize(); + DBGLOG(QM, WARN, "[Puff][%s]: (Warning) bcmRequestBaWinSize(%d)\n", __func__, u4BuffSizeBT); + + if (u4BuffSize > u4BuffSizeBT) + u4BuffSize = u4BuffSizeBT; +#endif /* CFG_SUPPORT_BCM */ + + rAddBaRspBody.u2BAParameterSet = (BA_POLICY_IMMEDIATE | + (u4Tid << BA_PARAM_SET_TID_MASK_OFFSET) | + (u4BuffSize << BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET)); + + /* TODO: Determine the BA timeout value according to the default preference */ + rAddBaRspBody.u2BATimeoutValue = rAddBaReqBody.u2BATimeoutValue; + + DBGLOG(QM, WARN, + "[Puff][%s]: (Warning) ADDBA_RSP u4BuffSize(%d) StatusCode(%d)", + __func__, u4BuffSize, rAddBaRspBody.u2StatusCode); + DBGLOG(QM, WARN, + "BAParameterSet(0x%08X) BATimeoutValue(%d)\n", + rAddBaRspBody.u2BAParameterSet, rAddBaRspBody.u2BATimeoutValue); + kalMemCopy((PUINT_8) (&(prAddBaRsp->aucStatusCode[0])), (PUINT_8) (&rAddBaRspBody), 6); + + COPY_MAC_ADDR(prAddBaRsp->aucDestAddr, prStaRec->aucMacAddr); + COPY_MAC_ADDR(prAddBaRsp->aucSrcAddr, prBssInfo->aucOwnMacAddr); + /* COPY_MAC_ADDR(prAddBaRsp->aucBSSID,g_aprBssInfo[prStaRec->ucNetTypeIndex]->aucBSSID); */ + COPY_MAC_ADDR(prAddBaRsp->aucBSSID, prAddBaReq->aucBSSID); + + /* 4 <4> Forward the ADDBA_RSP to TXM */ + TX_SET_MMPDU(prAdapter, + prTxMsduInfo, + prStaRec->ucBssIndex, + (prStaRec != NULL) ? (prStaRec->ucIndex) : (STA_REC_INDEX_NOT_FOUND), + WLAN_MAC_HEADER_LEN, + ACTION_ADDBA_RSP_FRAME_LEN, mqmCallbackAddBaRspSent, MSDU_RATE_MODE_AUTO); + +#if CFG_SUPPORT_802_11W + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(RSN, INFO, "Set MSDU_OPT_PROTECTED_FRAME\n"); + nicTxConfigPktOption(prTxMsduInfo, MSDU_OPT_PROTECTED_FRAME, TRUE); + } +#endif + + /* Note: prTxMsduInfo->ucTID is not used for transmitting the ADDBA_RSP. + * However, when processing TX Done of this ADDBA_RSP, the TID value is needed, so + * store the TID value in advance to prevent parsing the ADDBA_RSP frame + */ + prTxMsduInfo->ucTID = (UINT_8) u4Tid; + + nicTxEnqueueMsdu(prAdapter, prTxMsduInfo); + + DBGLOG(QM, WARN, + "[Puff][%s]: (RX_BA) ADDBA_RSP ---> peer (STA=%d TID=%ld)\n", __func__, + prStaRec->ucIndex, u4Tid); + +#if 0 + /* 4 <5> Notify the host to start buffer reordering */ + if (fgIsNewEntryAdded) { /* Only when a new BA entry is indeed added will the host be notified */ + ASSERT(fgIsReqAccepted); + + prSwRfbEventToHost = (P_SW_RFB_T) cnmMgtPktAlloc(EVENT_RX_ADDBA_PACKET_LEN); + + if (!prSwRfbEventToHost) { + + /* Note: DELBA will not be sent since cnmMgtPktAlloc() may fail again. However, + * it does not matter because upon receipt of AMPDUs without a RX BA agreement, + * MQM will send DELBA frames + */ + + DBGLOG(MQM, WARN, "MQM: (Warning) EVENT packet alloc failed\n"); + + /* Ensure that host and FW are synchronized */ + mqmRxModifyBaEntryStatus(prRxBaEntry, BA_ENTRY_STATUS_INVALID); + + break; /* Free the received ADDBA_REQ */ + } + prEventRxAddBa = (P_EVENT_RX_ADDBA_T) prSwRfbEventToHost->pucBuffer; + prEventRxAddBa->ucStaRecIdx = (UINT_8) u4StaRecIdx; + prEventRxAddBa->u2Length = EVENT_RX_ADDBA_PACKET_LEN; + prEventRxAddBa->ucEID = EVENT_ID_RX_ADDBA; + prEventRxAddBa->ucSeqNum = 0; /* Unsolicited event packet */ + prEventRxAddBa->u2BAParameterSet = rAddBaRspBody.u2BAParameterSet; + prEventRxAddBa->u2BAStartSeqCtrl = rAddBaReqBody.u2BAStartSeqCtrl; + prEventRxAddBa->u2BATimeoutValue = rAddBaReqBody.u2BATimeoutValue; + prEventRxAddBa->ucDialogToken = prAddBaReq->ucDialogToken; + + DBGLOG(MQM, INFO, + "MQM: (RX_BA) Event ADDBA ---> driver (STA=%ld TID=%ld WinStart=%d)\n", + u4StaRecIdx, u4Tid, (prEventRxAddBa->u2BAStartSeqCtrl >> 4)); + + /* Configure the SW_RFB for the Event packet */ + RXM_SET_EVENT_PACKET( + /* P_SW_RFB_T */ (P_SW_RFB_T) + prSwRfbEventToHost, + /* HIF RX Packet pointer */ + (PUINT_8) prEventRxAddBa, + /* HIF RX port number */ HIF_RX0_INDEX + ); + + rxmSendEventToHost(prSwRfbEventToHost); + + + } +#endif + + } while (FALSE); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mqmHandleAddBaRsp(IN P_SW_RFB_T prSwRfb) +{ + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mqmHandleDelBa(IN P_SW_RFB_T prSwRfb) +{ + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mqmHandleBaActionFrame(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; + DBGLOG(RLM, WARN, "[Puff][%s] Action(%d)\n", __func__, prRxFrame->ucAction); + + switch (prRxFrame->ucAction) { + + case ACTION_ADDBA_REQ: + DBGLOG(RLM, WARN, "[Puff][%s] (RX_BA) ADDBA_REQ <--- peer\n", __func__); + mqmHandleAddBaReq(prAdapter, prSwRfb); + break; + + case ACTION_ADDBA_RSP: + DBGLOG(RLM, WARN, "[Puff][%s] (RX_BA) ADDBA_RSP <--- peer\n", __func__); + mqmHandleAddBaRsp(prSwRfb); + break; + + case ACTION_DELBA: + DBGLOG(RLM, WARN, "[Puff][%s] (RX_BA) DELBA <--- peer\n", __func__); + mqmHandleDelBa(prSwRfb); + break; + + default: + DBGLOG(RLM, WARN, "[Puff][%s] Unknown BA Action Frame\n", __func__); + break; + } + +} + +#endif + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL +VOID qmResetTcControlResource(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4Idx; + UINT_32 u4TotalMinReservedTcResource = 0; + UINT_32 u4TotalTcResource = 0; + UINT_32 u4TotalGurantedTcResource = 0; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + /* Initialize TC resource control variables */ + for (u4Idx = 0; u4Idx < TC_NUM; u4Idx++) + prQM->au4AverageQueLen[u4Idx] = 0; + + ASSERT(prQM->u4TimeToAdjustTcResource && prQM->u4TimeToUpdateQueLen); + + for (u4Idx = 0; u4Idx < TC_NUM; u4Idx++) { + prQM->au4CurrentTcResource[u4Idx] = prAdapter->rTxCtrl.rTc.au4MaxNumOfBuffer[u4Idx]; + + if (u4Idx != TC4_INDEX) { + u4TotalTcResource += prQM->au4CurrentTcResource[u4Idx]; + u4TotalGurantedTcResource += prQM->au4GuaranteedTcResource[u4Idx]; + u4TotalMinReservedTcResource += prQM->au4MinReservedTcResource[u4Idx]; + } + } + + /* Sanity Check */ + if (u4TotalMinReservedTcResource > u4TotalTcResource) + kalMemZero(prQM->au4MinReservedTcResource, sizeof(prQM->au4MinReservedTcResource)); + + if (u4TotalGurantedTcResource > u4TotalTcResource) + kalMemZero(prQM->au4GuaranteedTcResource, sizeof(prQM->au4GuaranteedTcResource)); + + u4TotalGurantedTcResource = 0; + + /* Initialize Residual TC resource */ + for (u4Idx = 0; u4Idx < TC_NUM; u4Idx++) { + if (prQM->au4GuaranteedTcResource[u4Idx] < prQM->au4MinReservedTcResource[u4Idx]) + prQM->au4GuaranteedTcResource[u4Idx] = prQM->au4MinReservedTcResource[u4Idx]; + + if (u4Idx != TC4_INDEX) + u4TotalGurantedTcResource += prQM->au4GuaranteedTcResource[u4Idx]; + } + + prQM->u4ResidualTcResource = u4TotalTcResource - u4TotalGurantedTcResource; + +} +#endif + + +#if CFG_SUPPORT_REPLAY_DETECTION +/* To change PN number to UINT64 */ +#define CCMPTSCPNNUM 6 +BOOLEAN qmRxPNtoU64(PUINT_8 pucPN, UINT_8 uPNNum, PUINT_64 pu8Rets) +{ + UINT_8 ucCount = 0; + UINT_64 u8Data = 0; + UINT_64 ucTmp = 0; + + if (!pu8Rets) { + DBGLOG(QM, ERROR, "Please input valid pu8Rets\n"); + return FALSE; + } + + if (uPNNum > CCMPTSCPNNUM) { + DBGLOG(QM, ERROR, "Please input valid uPNNum:%d\n", uPNNum); + return FALSE; + } + + *pu8Rets = 0; + for (; ucCount < uPNNum; ucCount++) { + ucTmp = pucPN[ucCount]; + u8Data = ucTmp << 8*ucCount; + *pu8Rets += u8Data; + } + return TRUE; +} + +/* To check PN/TSC between RxStatus and local record. return TRUE if PNS is not bigger than PNT */ +BOOLEAN qmRxDetectReplay(PUINT_8 pucPNS, PUINT_8 pucPNT) +{ + UINT_64 u8RxNum = 0; + UINT_64 u8LocalRec = 0; + + if (!pucPNS || !pucPNT) { + DBGLOG(QM, ERROR, "Please input valid PNS:%p and PNT:%p\n", pucPNS, pucPNT); + return TRUE; + } + + if (!qmRxPNtoU64(pucPNS, CCMPTSCPNNUM, &u8RxNum) + || !qmRxPNtoU64(pucPNT, CCMPTSCPNNUM, &u8LocalRec)) { + DBGLOG(QM, ERROR, "PN2U64 failed\n"); + return TRUE; + } + /* PN overflow ? */ + + return !(u8RxNum > u8LocalRec); +} + +/* TO filter broadcast and multicast data packet replay issue. */ +BOOLEAN qmHandleRxReplay(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) +{ + PUINT_8 pucPN = NULL; + UINT_8 ucKeyID = 0; /* 0~4 */ + UINT_8 ucSecMode = CIPHER_SUITE_NONE; /* CIPHER_SUITE_NONE~CIPHER_SUITE_GCMP */ + P_GLUE_INFO_T prGlueInfo = NULL; + P_GL_WPA_INFO_T prWpaInfo = NULL; + struct SEC_DETECT_REPLAY_INFO *prDetRplyInfo = NULL; + P_HW_MAC_RX_DESC_T prRxStatus = NULL; + UINT_8 ucBssIndex = 0; + P_BSS_INFO_T prBssInfo = NULL; + UINT_8 ucCheckZeroPN; + UINT_8 i; + + if (!prAdapter) + return TRUE; + if (prSwRfb->u2PacketLen <= ETHER_HEADER_LEN) + return TRUE; + + ucBssIndex = prSwRfb->prStaRec->ucBssIndex; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + ASSERT(prBssInfo); + + prGlueInfo = prAdapter->prGlueInfo; + prWpaInfo = &prGlueInfo->rWpaInfo; + + if (!(prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_1))) + return FALSE; + + /* BMC only need check CCMP and TKIP Cipher suite */ + prRxStatus = prSwRfb->prRxStatus; + ucSecMode = HAL_RX_STATUS_GET_SEC_MODE(prRxStatus); + if (ucSecMode != CIPHER_SUITE_CCMP + && ucSecMode != CIPHER_SUITE_TKIP) { + DBGLOG(QM, TRACE, "SecMode: %d and CipherGroup: %d, no need check replay\n", + ucSecMode, prWpaInfo->u4CipherGroup); +#if 0 + if (!(prSwRfb->ucGroupVLD & BIT(RX_GROUP_VLD_1))) { + DBGLOG(QM, ERROR, "Group 1 invalid\n"); + return TRUE; + } +#endif + return FALSE; + } + + ucKeyID = HAL_RX_STATUS_GET_KEY_ID(prRxStatus); + if (ucKeyID >= MAX_KEY_NUM) { + DBGLOG(QM, ERROR, "KeyID: %d error\n", ucKeyID); + return TRUE; + } + + prDetRplyInfo = &prBssInfo->rDetRplyInfo; + +#if 0 + if (prDetRplyInfo->arReplayPNInfo[ucKeyID].fgFirstPkt) { + prDetRplyInfo->arReplayPNInfo[ucKeyID].fgFirstPkt = FALSE; + HAL_RX_STATUS_GET_PN(prSwRfb->prRxStatusGroup1, prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN); + DBGLOG(QM, INFO, + "First check packet. Key ID:0x%x\n", ucKeyID); + return FALSE; + } +#endif + + pucPN = prSwRfb->prRxStatusGroup1->aucPN; + DBGLOG(QM, TRACE, + "BC packet 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x--0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n", + pucPN[0], pucPN[1], pucPN[2], pucPN[3], pucPN[4], pucPN[5], + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN[0], + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN[1], + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN[2], + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN[3], + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN[4], + prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN[5]); + + if (prDetRplyInfo->fgKeyRscFresh == TRUE) { + + /* PN non-fresh setting */ + prDetRplyInfo->fgKeyRscFresh = FALSE; + ucCheckZeroPN = 0; + + for (i = 0; i < 8; i++) { + if (prSwRfb->prRxStatusGroup1->aucPN[i] == 0x0) + ucCheckZeroPN++; + } + + /* for AP start PN from 0, bypass PN check and update */ + if (ucCheckZeroPN == 8) { + DBGLOG(QM, WARN, "Fresh BC_PN with AP PN=0\n"); + return FALSE; + } + } + + if (qmRxDetectReplay(pucPN, prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN)) { + DBGLOG(QM, WARN, "Drop BC replay packet!\n"); + return TRUE; + } + + HAL_RX_STATUS_GET_PN(prSwRfb->prRxStatusGroup1, prDetRplyInfo->arReplayPNInfo[ucKeyID].auPN); + + return FALSE; +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_ate_agent.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_ate_agent.c new file mode 100644 index 0000000000000..49c2475d18f03 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_ate_agent.c @@ -0,0 +1,2200 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + Module Name: + gl_ate_agent.c +*/ +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ + +#include "precomp.h" +#if CFG_SUPPORT_QA_TOOL +#include "gl_wext.h" +#include "gl_cfg80211.h" +#include "gl_ate_agent.h" +#include "gl_hook_api.h" +#include "gl_qa_agent.h" +#if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE +#include +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#if CFG_SUPPORT_TX_BF +PFMU_PROFILE_TAG1 g_rPfmuTag1; +PFMU_PROFILE_TAG2 g_rPfmuTag2; +PFMU_DATA g_rPfmuData; +#endif + +typedef struct _ATE_PRIV_CMD { + UINT_8 *name; + int (*set_proc)(struct net_device *prNetDev, UINT_8 *prInBuf); +} ATE_PRIV_CMD, *P_ATE_PRIV_CMD; + +ATE_PRIV_CMD rAtePrivCmdTable[] = { + {"ResetCounter", Set_ResetStatCounter_Proc}, + {"ATE", SetATE}, +#if 0 + {"ADCDump", SetADCDump}, + {"ATEBSSID", SetATEBssid}, +#endif + {"ATEDA", SetATEDa}, + {"ATESA", SetATESa}, + {"ATECHANNEL", SetATEChannel}, + {"ATETXPOW0", SetATETxPower0}, + {"ATETXGI", SetATETxGi}, + {"ATETXBW", SetATETxBw}, + {"ATETXLEN", SetATETxLength}, + {"ATETXCNT", SetATETxCount}, + {"ATETXMCS", SetATETxMcs}, + {"ATETXMODE", SetATETxMode}, + {"ATEIPG", SetATEIpg}, +#if CFG_SUPPORT_TX_BF + {"TxBfProfileTagHelp", Set_TxBfProfileTag_Help}, + {"TxBfProfileTagInValid", Set_TxBfProfileTag_InValid}, + {"TxBfProfileTagPfmuIdx", Set_TxBfProfileTag_PfmuIdx}, + {"TxBfProfileTagBfType", Set_TxBfProfileTag_BfType}, + {"TxBfProfileTagBw", Set_TxBfProfileTag_DBW}, + {"TxBfProfileTagSuMu", Set_TxBfProfileTag_SuMu}, + {"TxBfProfileTagMemAlloc", Set_TxBfProfileTag_Mem}, + {"TxBfProfileTagMatrix", Set_TxBfProfileTag_Matrix}, + {"TxBfProfileTagSnr", Set_TxBfProfileTag_SNR}, + {"TxBfProfileTagSmtAnt", Set_TxBfProfileTag_SmartAnt}, + {"TxBfProfileTagSeIdx", Set_TxBfProfileTag_SeIdx}, + {"TxBfProfileTagRmsdThrd", Set_TxBfProfileTag_RmsdThrd}, + {"TxBfProfileTagMcsThrd", Set_TxBfProfileTag_McsThrd}, + {"TxBfProfileTagTimeOut", Set_TxBfProfileTag_TimeOut}, + {"TxBfProfileTagDesiredBw", Set_TxBfProfileTag_DesiredBW}, + {"TxBfProfileTagDesiredNc", Set_TxBfProfileTag_DesiredNc}, + {"TxBfProfileTagDesiredNr", Set_TxBfProfileTag_DesiredNr}, + {"TxBfProfileTagRead", Set_TxBfProfileTagRead}, + {"TxBfProfileTagWrite", Set_TxBfProfileTagWrite}, + {"TxBfProfileDataRead", Set_TxBfProfileDataRead}, + {"TxBfProfileDataWrite", Set_TxBfProfileDataWrite}, + {"TxBfProfilePnRead", Set_TxBfProfilePnRead}, + {"TxBfProfilePnWrite", Set_TxBfProfilePnWrite}, + {"TxBfSounding", Set_Trigger_Sounding_Proc}, + {"TxBfSoundingStop", Set_Stop_Sounding_Proc}, + {"TxBfTxApply", Set_TxBfTxApply}, + {"TxBfManualAssoc", Set_TxBfManualAssoc}, + {"TxBfPfmuMemAlloc", Set_TxBfPfmuMemAlloc}, + {"TxBfPfmuMemRelease", Set_TxBfPfmuMemRelease}, + {"StaRecCmmUpdate", Set_StaRecCmmUpdate}, + {"StaRecBfUpdate", Set_StaRecBfUpdate}, + {"DevInfoUpdate", Set_DevInfoUpdate}, + {"BssInfoUpdate", Set_BssInfoUpdate}, +#if CFG_SUPPORT_MU_MIMO + {"MUGetInitMCS", Set_MUGetInitMCS}, + {"MUCalInitMCS", Set_MUCalInitMCS}, + {"MUCalLQ", Set_MUCalLQ}, + {"MUGetLQ", Set_MUGetLQ}, + {"MUSetSNROffset", Set_MUSetSNROffset}, + {"MUSetZeroNss", Set_MUSetZeroNss}, + {"MUSetSpeedUpLQ", Set_MUSetSpeedUpLQ}, + {"MUSetMUTable", Set_MUSetMUTable}, + {"MUSetGroup", Set_MUSetGroup}, + {"MUGetQD", Set_MUGetQD}, + {"MUSetEnable", Set_MUSetEnable}, + {"MUSetGID_UP", Set_MUSetGID_UP}, + {"MUTriggerTx", Set_MUTriggerTx}, +#endif +#endif + + {"WriteEfuse", WriteEfuse}, + {"TxPower", SetTxTargetPower}, +#if (CFG_SUPPORT_DFS_MASTER == 1) + {"RDDReport", SetRddReport}, + {"ByPassCac", SetByPassCac}, + {"RadarDetectMode", SetRadarDetectMode}, +#endif + + {NULL,} +}; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Reset RX Statistic Counters. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +int Set_ResetStatCounter_Proc(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + INT_32 i4Status; + + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv Set_ResetStatCounter_Proc\n"); + + i4Status = MT_ATEResetTXRXCounter(prNetDev); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set Start Test Mode / Stop Test Mode / Start TX / Stop TX / Start RX / Stop RX. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetATE(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + INT_32 i4Status; + + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv SetATE\n"); + + if (!strcmp(prInBuf, "ATESTART")) { + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv SetATE - ATESTART\n"); + i4Status = MT_ATEStart(prNetDev, prInBuf); + } else if (!strcmp(prInBuf, "ICAPSTART")) { + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv SetATE - ICAPSTART\n"); + i4Status = MT_ICAPStart(prNetDev, prInBuf); + } else if (!strcmp(prInBuf, "ATESTOP")) { + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv SetATE - ATESTOP\n"); + i4Status = MT_ATEStop(prNetDev, prInBuf); + } else if (!strcmp(prInBuf, "TXFRAME")) { + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv SetATE - TXFRAME\n"); + i4Status = MT_ATEStartTX(prNetDev, prInBuf); + } else if (!strcmp(prInBuf, "TXSTOP")) { + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv SetATE - TXSTOP\n"); + i4Status = MT_ATEStopTX(prNetDev, prInBuf); + } else if (!strcmp(prInBuf, "RXFRAME")) { + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv SetATE - RXFRAME\n"); + i4Status = MT_ATEStartRX(prNetDev, prInBuf); + } else if (!strcmp(prInBuf, "RXSTOP")) { + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv SetATE - RXSTOP\n"); + i4Status = MT_ATEStopRX(prNetDev, prInBuf); + } else { + return -EINVAL; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set TX Destination Address. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetATEDa(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + INT_32 i4Status = 0; + UINT_32 addr[MAC_ADDR_LEN]; + UINT_8 addr2[MAC_ADDR_LEN]; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 : ATE_AGENT iwpriv SetDa\n"); + /* xx:xx:xx:xx:xx:xx */ + rv = sscanf(prInBuf, "%x:%x:%x:%x:%x:%x", &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]); + if (rv == 6) { + DBGLOG(RFTEST, ERROR, "MT6632 : ATE_AGENT iwpriv SetATEDa Sa:%02x:%02x:%02x:%02x:%02x:%02x\n", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + + addr2[0] = (UINT_8) addr[0]; + addr2[1] = (UINT_8) addr[1]; + addr2[2] = (UINT_8) addr[2]; + addr2[3] = (UINT_8) addr[3]; + addr2[4] = (UINT_8) addr[4]; + addr2[5] = (UINT_8) addr[5]; + + i4Status = MT_ATESetMACAddress(prNetDev, RF_AT_FUNCID_SET_MAC_ADDRESS, addr2); + } else { + return -EINVAL; + } + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set TX Source Address. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetATESa(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + INT_32 i4Status = 0; + UINT_32 addr[MAC_ADDR_LEN]; + UINT_8 addr2[MAC_ADDR_LEN]; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 : ATE_AGENT iwpriv SetSa\n"); + /* xx:xx:xx:xx:xx:xx */ + rv = sscanf(prInBuf, "%x:%x:%x:%x:%x:%x", &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]); + if (rv == 6) { + DBGLOG(RFTEST, ERROR, "MT6632 : ATE_AGENT iwpriv SetATESa Sa:%02x:%02x:%02x:%02x:%02x:%02x\n", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + + addr2[0] = (UINT_8) addr[0]; + addr2[1] = (UINT_8) addr[1]; + addr2[2] = (UINT_8) addr[2]; + addr2[3] = (UINT_8) addr[3]; + addr2[4] = (UINT_8) addr[4]; + addr2[5] = (UINT_8) addr[5]; + + i4Status = MT_ATESetMACAddress(prNetDev, RF_AT_FUNCID_SET_TA, addr2); + } else { + return -EINVAL; + } + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set Channel Frequency. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetATEChannel(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 i4SetFreq = 0; + INT_32 i4Status, i4SetChan = 0; + INT_32 rv; + + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv SetChannel\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetChan); + if (rv == 0) { + i4SetFreq = nicChannelNum2Freq(i4SetChan); + i4Status = MT_ATESetChannel(prNetDev, 0, i4SetFreq); + } else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set TX WF0 Power. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetATETxPower0(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 i4SetTxPower0 = 0; + INT_32 i4Status; + INT_32 rv; + + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv SetTxPower0\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxPower0); + if (rv == 0) + i4Status = MT_ATESetTxPower0(prNetDev, i4SetTxPower0); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set TX Guard Interval. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetATETxGi(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 i4SetTxGi = 0; + INT_32 i4Status; + INT_32 rv; + + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv SetTxGi\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxGi); + if (rv == 0) + i4Status = MT_ATESetTxGi(prNetDev, i4SetTxGi); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set TX System Bandwidth. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetATETxBw(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 i4SetSystemBW = 0; + INT_32 i4Status; + INT_32 rv; + + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv SetSystemBW\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetSystemBW); + if (rv == 0) + i4Status = MT_ATESetSystemBW(prNetDev, i4SetSystemBW); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set TX Mode (Preamble). +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetATETxMode(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 i4SetTxMode = 0; + INT_32 i4Status; + INT_32 rv; + + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv SetTxMode\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxMode); + if (rv == 0) + i4Status = MT_ATESetPreamble(prNetDev, i4SetTxMode); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set TX Length. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetATETxLength(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 i4SetTxLength = 0; + INT_32 i4Status; + INT_32 rv; + + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv SetTxLength\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxLength); + if (rv == 0) + i4Status = MT_ATESetTxLength(prNetDev, i4SetTxLength); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set TX Count. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetATETxCount(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 i4SetTxCount = 0; + INT_32 i4Status; + INT_32 rv; + UCHAR addr[MAC_ADDR_LEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv SetTxCount\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxCount); + if (rv == 0) + i4Status = MT_ATESetTxCount(prNetDev, i4SetTxCount); + else + return -EINVAL; + + i4Status = MT_ATESetMACAddress(prNetDev, RF_AT_FUNCID_SET_MAC_ADDRESS, addr); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set TX Rate. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetATETxMcs(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 i4SetTxMcs = 0; + INT_32 i4Status; + INT_32 rv; + + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv SetTxMcs\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxMcs); + if (rv == 0) + i4Status = MT_ATESetRate(prNetDev, i4SetTxMcs); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set Inter-Packet Guard Interval. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetATEIpg(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 i4SetTxIPG = 0; + INT_32 i4Status; + INT_32 rv; + + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv SetIpg\n"); + + rv = kstrtoint(prInBuf, 0, &i4SetTxIPG); + if (rv == 0) + i4Status = MT_ATESetTxIPG(prNetDev, i4SetTxIPG); + else + return -EINVAL; + + return i4Status; +} + +#if CFG_SUPPORT_TX_BF +int Set_TxBfProfileTag_Help(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + DBGLOG(RFTEST, ERROR, + "========================================================================================================================\n" + "TxBfProfile Tag1 setting example :\n" + "iwpriv ra0 set TxBfProfileTagPfmuIdx =xx\n" + "iwpriv ra0 set TxBfProfileTagBfType =xx (0: iBF; 1: eBF)\n" + "iwpriv ra0 set TxBfProfileTagBw =xx (0/1/2/3 : BW20/40/80/160NC)\n" + "iwpriv ra0 set TxBfProfileTagSuMu =xx (0:SU, 1:MU)\n" + "iwpriv ra0 set TxBfProfileTagInvalid =xx (0: valid, 1: invalid)\n" + "iwpriv ra0 set TxBfProfileTagMemAlloc =xx:xx:xx:xx:xx:xx:xx:xx (mem_row, mem_col), ..\n" + "iwpriv ra0 set TxBfProfileTagMatrix =nrow:nol:ng:LM\n" + "iwpriv ra0 set TxBfProfileTagSnr =SNR_STS0:SNR_STS1:SNR_STS2:SNR_STS3\n" + "\n\n" + "TxBfProfile Tag2 setting example :\n" + "iwpriv ra0 set TxBfProfileTagSmtAnt =xx (11:0)\n" + "iwpriv ra0 set TxBfProfileTagSeIdx =xx\n" + "iwpriv ra0 set TxBfProfileTagRmsdThrd =xx\n" + "iwpriv ra0 set TxBfProfileTagMcsThrd =xx:xx:xx:xx:xx:xx (MCS TH L1SS:S1SS:L2SS:....)\n" + "iwpriv ra0 set TxBfProfileTagTimeOut =xx\n" + "iwpriv ra0 set TxBfProfileTagDesiredBw=xx (0/1/2/3 : BW20/40/80/160NC)\n" + "iwpriv ra0 set TxBfProfileTagDesiredNc=xx\n" + "iwpriv ra0 set TxBfProfileTagDesiredNr=xx\n" + "\n\n" + "Read TxBf profile Tag :\n" + "iwpriv ra0 set TxBfProfileTagRead =xx (PFMU ID)\n" + "\n" + "Write TxBf profile Tag :\n" + "iwpriv ra0 set TxBfProfileTagWrite =xx (PFMU ID)\n" + "When you use one of relative CMD to update one of tag parameters, you should call TxBfProfileTagWrite to update Tag\n" + "\n\n" + "Read TxBf profile Data :\n" + "iwpriv ra0 set TxBfProfileDataRead =xx (PFMU ID)\n" + "\n" + "Write TxBf profile Data :\n" + "iwpriv ra0 set TxBfProfileDataWrite =BW :subcarrier:phi11:psi2l:Phi21:Psi31:Phi31:Psi41:Phi22:Psi32:Phi32:Psi42:Phi33:Psi43\n" + "iwpriv ra0 set TxBfProfileDataWriteAll=Profile ID : BW (BW : 0x00 (20M) , 0x01 (40M), 0x02 (80M), 0x3 (160M)\n" + "When you use CMD TxBfProfileDataWrite to update profile data per subcarrier, you should call TxBfProfileDataWriteAll to update all of\n" + "subcarrier's profile data.\n\n" + "Read TxBf profile PN :\n" + "iwpriv ra0 set TxBfProfilePnRead =xx (PFMU ID)\n" + "\n" + "Write TxBf profile PN :\n" + "iwpriv ra0 set TxBfProfilePnWrite =Profile ID:BW:1STS_Tx0:1STS_Tx1:1STS_Tx2:1STS_Tx3:2STS_Tx0:2STS_Tx1:2STS_Tx2:2STS_Tx3:3STS_Tx1:3STS_Tx2:3STS_Tx3\n" + "========================================================================================================================\n"); + return 0; +} + +int Set_TxBfProfileTag_InValid(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 ucInValid; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_InValid\n"); + + rv = kstrtoint(prInBuf, 0, &ucInValid); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_InValid prInBuf = %s, ucInValid = %d\n", prInBuf, + ucInValid); + i4Status = TxBfProfileTag_InValid(prNetDev, &g_rPfmuTag1, ucInValid); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_PfmuIdx(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 ucProfileIdx; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_PfmuIdx\n"); + + rv = kstrtoint(prInBuf, 0, &ucProfileIdx); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_PfmuIdx prInBuf = %s, ucProfileIdx = %d\n", prInBuf, + ucProfileIdx); + i4Status = TxBfProfileTag_PfmuIdx(prNetDev, &g_rPfmuTag1, ucProfileIdx); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_BfType(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 ucBFType; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_BfType\n"); + + rv = kstrtoint(prInBuf, 0, &ucBFType); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_BfType prInBuf = %s, ucBFType = %d\n", + prInBuf, ucBFType); + i4Status = TxBfProfileTag_TxBfType(prNetDev, &g_rPfmuTag1, ucBFType); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_DBW(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 ucBW; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_DBW\n"); + + rv = kstrtoint(prInBuf, 0, &ucBW); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_DBW prInBuf = %s, ucBW = %d\n", prInBuf, ucBW); + i4Status = TxBfProfileTag_DBW(prNetDev, &g_rPfmuTag1, ucBW); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_SuMu(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 ucSuMu; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_SuMu\n"); + + rv = kstrtoint(prInBuf, 0, &ucSuMu); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_SuMu prInBuf = %s, ucSuMu = %d\n", prInBuf, ucSuMu); + i4Status = TxBfProfileTag_SuMu(prNetDev, &g_rPfmuTag1, ucSuMu); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_Mem(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 aucInput[8]; + INT_32 i4Status = 0; + UINT_8 aucMemAddrColIdx[4], aucMemAddrRowIdx[4]; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_Mem\n"); + + rv = sscanf(prInBuf, "%d:%d:%d:%d:%d:%d:%d:%d", + &aucInput[0], &aucInput[1], &aucInput[2], &aucInput[3], &aucInput[4], &aucInput[5], &aucInput[6], + &aucInput[7]); + /* mem col0:row0:col1:row1:col2:row2:col3:row3 */ + if (rv == 8) { + DBGLOG(RFTEST, ERROR, + "MT6632 : ATE_AGENT iwpriv Set_TxBfProfileTag_Mem aucInput:%d:%d:%d:%d:%d:%d:%d:%d\n", + aucInput[0], aucInput[1], aucInput[2], aucInput[3], aucInput[4], aucInput[5], aucInput[6], + aucInput[7]); + + aucMemAddrColIdx[0] = (UINT_8) aucInput[0]; + aucMemAddrRowIdx[0] = (UINT_8) aucInput[1]; + aucMemAddrColIdx[1] = (UINT_8) aucInput[2]; + aucMemAddrRowIdx[1] = (UINT_8) aucInput[3]; + aucMemAddrColIdx[2] = (UINT_8) aucInput[4]; + aucMemAddrRowIdx[2] = (UINT_8) aucInput[5]; + aucMemAddrColIdx[3] = (UINT_8) aucInput[6]; + aucMemAddrRowIdx[3] = (UINT_8) aucInput[7]; + + i4Status = TxBfProfileTag_Mem(prNetDev, &g_rPfmuTag1, aucMemAddrColIdx, aucMemAddrRowIdx); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_Matrix(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 aucInput[6]; + UINT_8 ucNrow, ucNcol, ucNgroup, ucLM, ucCodeBook, ucHtcExist; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_Matrix\n"); + + rv = sscanf(prInBuf, "%d:%d:%d:%d:%d:%d", + &aucInput[0], &aucInput[1], &aucInput[2], &aucInput[3], &aucInput[4], &aucInput[5]); + /* nrow:nol:ng:LM:CodeBook:HtcExist */ + if (rv == 6) { + DBGLOG(RFTEST, ERROR, + "MT6632 : ATE_AGENT iwpriv Set_TxBfProfileTag_Matrix aucInput:%d:%d:%d:%d:%d:%d\n", + aucInput[0], aucInput[1], aucInput[2], aucInput[3], aucInput[4], aucInput[5]); + ucNrow = (UINT_8) aucInput[0]; + ucNcol = (UINT_8) aucInput[1]; + ucNgroup = (UINT_8) aucInput[2]; + ucLM = (UINT_8) aucInput[3]; + ucCodeBook = (UINT_8) aucInput[4]; + ucHtcExist = (UINT_8) aucInput[5]; + + i4Status = TxBfProfileTag_Matrix(prNetDev, + &g_rPfmuTag1, ucNrow, ucNcol, ucNgroup, ucLM, ucCodeBook, ucHtcExist); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_SNR(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 aucInput[4]; + UINT_8 ucSNR_STS0, ucSNR_STS1, ucSNR_STS2, ucSNR_STS3; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_SNR\n"); + + rv = sscanf(prInBuf, "%d:%d:%d:%d", &aucInput[0], &aucInput[1], &aucInput[2], &aucInput[3]); + if (rv == 4) { + DBGLOG(RFTEST, ERROR, "MT6632 : ATE_AGENT iwpriv Set_TxBfProfileTag_SNR aucInput:%d:%d:%d:%d\n", + aucInput[0], aucInput[1], aucInput[2], aucInput[3]); + + ucSNR_STS0 = (UINT_8) aucInput[0]; + ucSNR_STS1 = (UINT_8) aucInput[1]; + ucSNR_STS2 = (UINT_8) aucInput[2]; + ucSNR_STS3 = (UINT_8) aucInput[3]; + + i4Status = TxBfProfileTag_SNR(prNetDev, &g_rPfmuTag1, ucSNR_STS0, ucSNR_STS1, ucSNR_STS2, ucSNR_STS3); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_SmartAnt(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + INT_32 i4Status = 0; + UINT_32 ucSmartAnt; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_SmartAnt\n"); + + rv = kstrtoint(prInBuf, 0, &ucSmartAnt); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_SmartAnt prInBuf = %s, ucSmartAnt = %d\n", prInBuf, + ucSmartAnt); + i4Status = TxBfProfileTag_SmtAnt(prNetDev, &g_rPfmuTag2, ucSmartAnt); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_SeIdx(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + INT_32 i4Status = 0; + UINT_32 ucSeIdx; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_SeIdx\n"); + + rv = kstrtoint(prInBuf, 0, &ucSeIdx); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfileTag_SeIdx prInBuf = %s, ucSeIdx = %d\n", prInBuf, ucSeIdx); + i4Status = TxBfProfileTag_SeIdx(prNetDev, &g_rPfmuTag2, ucSeIdx); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_RmsdThrd(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + INT_32 i4Status = 0; + UINT_32 ucRmsdThrd; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_RmsdThrd\n"); + + rv = kstrtoint(prInBuf, 0, &ucRmsdThrd); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_RmsdThrd prInBuf = %s, ucRmsdThrd = %d\n", prInBuf, + ucRmsdThrd); + i4Status = TxBfProfileTag_RmsdThd(prNetDev, &g_rPfmuTag2, ucRmsdThrd); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_McsThrd(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 aucInput[6]; + UINT_8 ucMcsLss[3], ucMcsSss[3]; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_McsThrd\n"); + + rv = sscanf(prInBuf, "%d:%d:%d:%d:%d:%d", + &aucInput[0], &aucInput[1], &aucInput[2], &aucInput[3], &aucInput[4], &aucInput[5]); + if (rv == 6) { + DBGLOG(RFTEST, ERROR, + "MT6632 : ATE_AGENT iwpriv Set_TxBfProfileTag_McsThrd aucInput:%d:%d:%d:%d:%d:%d\n", + aucInput[0], aucInput[1], aucInput[2], aucInput[3], aucInput[4], aucInput[5]); + + ucMcsLss[0] = (UINT_8) aucInput[0]; + ucMcsSss[0] = (UINT_8) aucInput[1]; + ucMcsLss[1] = (UINT_8) aucInput[2]; + ucMcsSss[1] = (UINT_8) aucInput[3]; + ucMcsLss[2] = (UINT_8) aucInput[4]; + ucMcsSss[2] = (UINT_8) aucInput[5]; + + i4Status = TxBfProfileTag_McsThd(prNetDev, &g_rPfmuTag2, ucMcsLss, ucMcsSss); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_TimeOut(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 ucTimeOut; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_TimeOut\n"); + + rv = kstrtouint(prInBuf, 0, &ucTimeOut); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_TimeOut prInBuf = %s, ucTimeOut = %d\n", prInBuf, + ucTimeOut); + i4Status = TxBfProfileTag_TimeOut(prNetDev, &g_rPfmuTag2, ucTimeOut); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_DesiredBW(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 ucDesiredBW; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_DesiredBW\n"); + + rv = kstrtoint(prInBuf, 0, &ucDesiredBW); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_DesiredBW prInBuf = %s, ucDesiredBW = %d\n", prInBuf, + ucDesiredBW); + i4Status = TxBfProfileTag_DesiredBW(prNetDev, &g_rPfmuTag2, ucDesiredBW); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_DesiredNc(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 ucDesiredNc; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_DesiredNc\n"); + + rv = kstrtoint(prInBuf, 0, &ucDesiredNc); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_DesiredNc prInBuf = %s, ucDesiredNc = %d\n", prInBuf, + ucDesiredNc); + i4Status = TxBfProfileTag_DesiredNc(prNetDev, &g_rPfmuTag2, ucDesiredNc); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTag_DesiredNr(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 ucDesiredNr; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_DesiredNr\n"); + + rv = kstrtoint(prInBuf, 0, &ucDesiredNr); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTag_DesiredNr prInBuf = %s, ucDesiredNr = %d\n", prInBuf, + ucDesiredNr); + i4Status = TxBfProfileTag_DesiredNr(prNetDev, &g_rPfmuTag2, ucDesiredNr); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTagWrite(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 profileIdx; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTagWrite\n"); + + rv = kstrtoint(prInBuf, 0, &profileIdx); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTagWrite prInBuf = %s, profileIdx = %d\n", prInBuf, + profileIdx); + i4Status = TxBfProfileTagWrite(prNetDev, &g_rPfmuTag1, &g_rPfmuTag2, profileIdx); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileTagRead(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 profileIdx, fgBFer; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileTagRead\n"); + + rv = sscanf(prInBuf, "%d:%d", &profileIdx, &fgBFer); + if (rv == 2) { + DBGLOG(RFTEST, ERROR, + "MT6632 Set_TxBfProfileTagRead prInBuf = %s, profileIdx = %d, fgBFer = %d\n", + prInBuf, profileIdx, fgBFer); + i4Status = TxBfProfileTagRead(prNetDev, profileIdx, fgBFer); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileDataRead(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 profileIdx, fgBFer, subcarrierIdxMsb, subcarrierIdxLsb; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfileDataRead\n"); + + rv = sscanf(prInBuf, "%d:%d:%x:%x", &profileIdx, &fgBFer, &subcarrierIdxMsb, &subcarrierIdxLsb); + if (rv == 4) { + DBGLOG(RFTEST, ERROR, + "MT6632 Set_TxBfProfileDataRead prInBuf = %s, profileIdx = %d, fgBFer = %d, subcarrierIdxMsb:%x, subcarrierIdxLsb:%x\n", + prInBuf, profileIdx, fgBFer, subcarrierIdxMsb, subcarrierIdxLsb); + i4Status = TxBfProfileDataRead(prNetDev, profileIdx, fgBFer, subcarrierIdxMsb, subcarrierIdxLsb); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfileDataWrite(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + + UINT_32 u4ProfileIdx; + UINT_32 u4SubcarrierIdx; + UINT_32 au4Phi[6]; + UINT_32 au4Psi[6]; + UINT_32 au4DSnr[4]; + UINT_16 au2Phi[6]; + UINT_8 aucPsi[6]; + UINT_8 aucDSnr[4]; + UINT_32 i; + INT_32 rv; + + INT_32 i4Status = 0; + + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfileDataWrite\n"); + + rv = sscanf(prInBuf, "%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x", + &u4ProfileIdx, &u4SubcarrierIdx, &au4Phi[0], &au4Psi[0], &au4Phi[1], &au4Psi[1], + &au4Phi[2], &au4Psi[2], &au4Phi[3], &au4Psi[3], &au4Phi[4], &au4Psi[4], + &au4Phi[5], &au4Psi[5], + &au4DSnr[0], &au4DSnr[1], &au4DSnr[2], &au4DSnr[3]); + + if (rv == 18) { + DBGLOG(RFTEST, ERROR, + "MT6632 TxBfProfileDataWrite prInBuf = %s, u4ProfileIdx = %x, u4SubcarrierIdx = %x, au4Phi[0]:%x, au4Phi[1]:%x, au4Phi[2]:%x, au4Phi[3]:%x, au4Phi[4]:%x, au4Phi[5]:%x, au4Psi[0]:%x, au4Psi[1]:%x, au4Psi[2]:%x, au4Psi[3]:%x, au4Psi[4]:%x, au4Psi[5]:%x,au4DSnr[0]:%x, au4DSnr[1]:%x, au4DSnr[2]:%x, au4DSnr[3]:%x\n", + prInBuf, u4ProfileIdx, u4SubcarrierIdx, + au4Phi[0], au4Phi[1], au4Phi[2], au4Phi[3], au4Phi[4], au4Phi[5], + au4Psi[0], au4Psi[1], au4Psi[2], au4Psi[3], au4Psi[4], au4Psi[5], + au4DSnr[0], au4DSnr[1], au4DSnr[2], au4DSnr[3]); + for (i = 0; i < 6; i++) { + au2Phi[i] = au4Phi[i]; + aucPsi[i] = au4Psi[i]; + } + for (i = 0; i < 4; i++) + aucDSnr[i] = au4DSnr[i]; + + i4Status = TxBfProfileDataWrite(prNetDev, u4ProfileIdx, u4SubcarrierIdx, au2Phi, aucPsi, aucDSnr); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfilePnRead(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 profileIdx; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfilePnRead\n"); + + rv = kstrtoint(prInBuf, 0, &profileIdx); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "MT6632 Set_TxBfProfilePnRead prInBuf = %s, profileIdx = %d\n", + prInBuf, profileIdx); + i4Status = TxBfProfilePnRead(prNetDev, profileIdx); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfProfilePnWrite(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 ucProfileIdx; + UINT_16 u2bw; + UINT_16 au2XSTS[12]; + INT_32 rv; + + INT_32 i4Status = 0; + + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfilePnWrite\n"); + + rv = sscanf(prInBuf, + "%d:%hd:%hd:%hd:%hd:%hd:%hd:%hd:%hd:%hd:%hd:%hd:%hd:%hd", + &ucProfileIdx, &u2bw, &au2XSTS[0], &au2XSTS[1], &au2XSTS[2], &au2XSTS[3], + &au2XSTS[4], &au2XSTS[5], &au2XSTS[6], &au2XSTS[7], &au2XSTS[8], &au2XSTS[9], &au2XSTS[10], + &au2XSTS[11]); + if (rv == 14) { + DBGLOG(RFTEST, ERROR, + "MT6632 TxBfProfilePnWrite prInBuf = %s, ucProfileIdx = %d, u2bw = %dau2XSTS[0]:%d, au2XSTS[1]:%d, au2XSTS[2]:%d, au2XSTS[3]:%d, au2XSTS[4]:%d, au2XSTS[5]:%d, au2XSTS[6]:%d, au2XSTS[7]:%d, au2XSTS[8]:%d, au2XSTS[9]:%d, au2XSTS[10]:%d, au2XSTS[11]:%d\n", + prInBuf, ucProfileIdx, u2bw, au2XSTS[0], au2XSTS[1], + au2XSTS[2], au2XSTS[3], au2XSTS[4], au2XSTS[5], + au2XSTS[6], au2XSTS[7], au2XSTS[8], au2XSTS[9], au2XSTS[10], au2XSTS[11]); + i4Status = TxBfProfilePnWrite(prNetDev, ucProfileIdx, u2bw, au2XSTS); + } else + return -EINVAL; + + return i4Status; +} + +/* Su_Mu:NumSta:SndInterval:WLan0:WLan1:WLan2:WLan3 */ +int Set_Trigger_Sounding_Proc(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 ucSuMu, ucNumSta, ucSndInterval, ucWLan0, ucWLan1, ucWLan2, ucWLan3; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_Trigger_Sounding_Proc\n"); + + rv = sscanf + (prInBuf, "%x:%x:%x:%x:%x:%x:%x", &ucSuMu, &ucNumSta, &ucSndInterval, &ucWLan0, &ucWLan1, &ucWLan2, + &ucWLan3); + if (rv == 7) { + DBGLOG(RFTEST, ERROR, + "MT6632 Set_Trigger_Sounding_Proc prInBuf = %s, ucSuMu = %d, ucNumSta = %d, ucSndInterval = %d, ucWLan0 = %d, ucWLan1 = %d, ucWLan2:%d, ucWLan3:%d\n", + prInBuf, ucSuMu, ucNumSta, ucSndInterval, ucWLan0, + ucWLan1, ucWLan2, ucWLan3); + i4Status = TxBfSounding(prNetDev, ucSuMu, ucNumSta, ucSndInterval, ucWLan0, ucWLan1, ucWLan2, ucWLan3); + } else + return -EINVAL; + + return i4Status; +} + +int Set_Stop_Sounding_Proc(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + INT_32 i4Status = 0; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_Stop_Sounding_Proc\n"); + + i4Status = TxBfSoundingStop(prNetDev); + + return i4Status; +} + +int Set_TxBfTxApply(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4WlanId, u4ETxBf, u4ITxBf, u4MuTxBf; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 TxBfTxApply\n"); + + rv = sscanf(prInBuf, "%d:%d:%d:%d", &u4WlanId, &u4ETxBf, &u4ITxBf, &u4MuTxBf); + if (rv == 4) { + DBGLOG(RFTEST, ERROR, + "MT6632 TxBfTxApply prInBuf = %s, u4WlanId = %d, u4ETxBf = %d, u4ITxBf = %d, u4MuTxBf = %d\n", + prInBuf, u4WlanId, u4ETxBf, u4ITxBf, u4MuTxBf); + i4Status = TxBfTxApply(prNetDev, u4WlanId, u4ETxBf, u4ITxBf, u4MuTxBf); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfManualAssoc(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + INT_32 au4Mac[MAC_ADDR_LEN]; + INT_32 u4Type, u4Wtbl, u4Ownmac, u4PhyMode, u4Bw, u4Nss, u4PfmuId, u4Mode, u4Marate, u4SpeIdx, ucaid, u4Rv; + INT_8 aucMac[MAC_ADDR_LEN]; + INT_32 i4Status = 0; + INT_32 i = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 TxBfManualAssoc\n"); + + rv = sscanf(prInBuf, "%x:%x:%x:%x:%x:%x:%x:%d:%x:%x:%x:%x:%d:%x:%x:%x:%d:%x", + &au4Mac[0], &au4Mac[1], &au4Mac[2], &au4Mac[3], &au4Mac[4], &au4Mac[5], + &u4Type, &u4Wtbl, &u4Ownmac, &u4PhyMode, &u4Bw, &u4Nss, &u4PfmuId, &u4Mode, &u4Marate, &u4SpeIdx, + &ucaid, &u4Rv); + if (rv == 18) { + DBGLOG(RFTEST, ERROR, + "MT6632 TxBfManualAssoc au4Mac[0] = %x, au4Mac[1] = %x, au4Mac[2] = %xau4Mac[3] = %x, au4Mac[4] = %x, au4Mac[5] = %x, u4Type = %x, u4Wtbl = %d, u4Ownmac = %x, u4PhyMode = %x u4Bw = %x, u4Nss = %x, u4PfmuId = %d, u4Mode = %x, u4Marate = %x, u4SpeIdx = %d, ucaid = %d, u4Rv = %x", + au4Mac[0], au4Mac[1], au4Mac[2], au4Mac[3], au4Mac[4], au4Mac[5], u4Type, u4Wtbl, u4Ownmac, + u4PhyMode, u4Bw, u4Nss, u4PfmuId, u4Mode, u4Marate, u4SpeIdx, ucaid, u4Rv); + for (i = 0; i < MAC_ADDR_LEN; i++) + aucMac[i] = au4Mac[i]; + + i4Status = + TxBfManualAssoc(prNetDev, aucMac, u4Type, u4Wtbl, u4Ownmac, u4Mode, u4Bw, u4Nss, u4PfmuId, u4Marate, + u4SpeIdx, ucaid, u4Rv); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfPfmuMemAlloc(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 ucSuMuMode, ucWlanIdx; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 TxBfPfmuMemAlloc\n"); + + rv = sscanf(prInBuf, "%d:%d", &ucSuMuMode, &ucWlanIdx); + if (rv == 2) { + DBGLOG(RFTEST, ERROR, "MT6632 TxBfPfmuMemAlloc ucSuMuMode = %d, ucWlanIdx = %d", ucSuMuMode, ucWlanIdx); + i4Status = TxBfPfmuMemAlloc(prNetDev, ucSuMuMode, ucWlanIdx); + } else + return -EINVAL; + + return i4Status; +} + +int Set_TxBfPfmuMemRelease(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 ucWlanId; + INT_32 i4Status = 0; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 TxBfPfmuMemRelease\n"); + + rv = kstrtoint(prInBuf, 0, &ucWlanId); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "MT6632 TxBfPfmuMemRelease ucWlanId = %d", ucWlanId); + i4Status = TxBfPfmuMemRelease(prNetDev, ucWlanId); + } else + return -EINVAL; + + return i4Status; +} + +int Set_DevInfoUpdate(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4OwnMacIdx, fgBand; + UINT_32 OwnMacAddr[MAC_ADDR_LEN]; + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + INT_32 i4Status = 0; + UINT_32 i; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 DevInfoUpdate\n"); + + rv = sscanf + (prInBuf, "%d:%x:%x:%x:%x:%x:%x:%d", &u4OwnMacIdx, &OwnMacAddr[0], &OwnMacAddr[1], &OwnMacAddr[2], + &OwnMacAddr[3], &OwnMacAddr[4], &OwnMacAddr[5], &fgBand); + if (rv == 8) { + DBGLOG(RFTEST, ERROR, + "MT6632 DevInfoUpdate prInBuf = %s, u4OwnMacIdx = %x, fgBand = %x,OwnMacAddr[0]:%x, OwnMacAddr[1]:%x, OwnMacAddr[2]:%x, OwnMacAddr[3]:%x, OwnMacAddr[4]:%x, OwnMacAddr[5]:%x,", + prInBuf, u4OwnMacIdx, fgBand, OwnMacAddr[0], OwnMacAddr[1], OwnMacAddr[2], OwnMacAddr[3], + OwnMacAddr[4], OwnMacAddr[5]); + for (i = 0; i < MAC_ADDR_LEN; i++) + aucMacAddr[i] = OwnMacAddr[i]; + + i4Status = DevInfoUpdate(prNetDev, u4OwnMacIdx, fgBand, aucMacAddr); + } else + return -EINVAL; + + return i4Status; +} + +int Set_BssInfoUpdate(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4OwnMacIdx, u4BssIdx; + UINT_32 au4BssId[MAC_ADDR_LEN]; + UINT_8 aucBssId[MAC_ADDR_LEN]; + INT_32 i4Status = 0; + UINT_32 i; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 BssInfoUpdate\n"); + + rv = sscanf + (prInBuf, "%d:%d:%x:%x:%x:%x:%x:%x", &u4OwnMacIdx, &u4BssIdx, &au4BssId[0], &au4BssId[1], &au4BssId[2], + &au4BssId[3], &au4BssId[4], &au4BssId[5]); + if (rv == 8) { + DBGLOG(RFTEST, ERROR, + "MT6632 BssInfoUpdate prInBuf = %s, u4OwnMacIdx = %x, u4BssIdx = %x,au4BssId[0]:%x, au4BssId[1]:%x, au4BssId[2]:%x, au4BssId[3]:%x, au4BssId[4]:%x, au4BssId[5]:%x,", + prInBuf, u4OwnMacIdx, u4BssIdx, au4BssId[0], au4BssId[1], au4BssId[2], au4BssId[3], au4BssId[4], + au4BssId[5]); + for (i = 0; i < MAC_ADDR_LEN; i++) + aucBssId[i] = au4BssId[i]; + + i4Status = BssInfoUpdate(prNetDev, u4OwnMacIdx, u4BssIdx, aucBssId); + } else + return -EINVAL; + + return i4Status; +} + +int Set_StaRecCmmUpdate(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4WlanId, u4BssId, u4Aid; + UINT_32 au4MacAddr[MAC_ADDR_LEN]; + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + INT_32 i4Status = 0; + UINT_32 i; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_StaRecCmmUpdate\n"); + + rv = sscanf + (prInBuf, "%x:%x:%x:%x:%x:%x:%x:%x:%x", &u4WlanId, &u4BssId, &u4Aid, &au4MacAddr[0], &au4MacAddr[1], + &au4MacAddr[2], &au4MacAddr[3], &au4MacAddr[4], &au4MacAddr[5]); + if (rv == 9) { + DBGLOG(RFTEST, ERROR, + "MT6632 Set_StaRecCmmUpdate prInBuf = %s, u4WlanId = %x, u4BssId = %x, u4Aid = %x,aucMacAddr[0]:%x, aucMacAddr[1]:%x, aucMacAddr[2]:%x, aucMacAddr[3]:%x, aucMacAddr[4]:%x, aucMacAddr[5]:%x,", + prInBuf, u4WlanId, u4BssId, u4Aid, au4MacAddr[0], au4MacAddr[1], au4MacAddr[2], au4MacAddr[3], + au4MacAddr[4], au4MacAddr[5]); + for (i = 0; i < MAC_ADDR_LEN; i++) + aucMacAddr[i] = au4MacAddr[i]; + + i4Status = StaRecCmmUpdate(prNetDev, u4WlanId, u4BssId, u4Aid, aucMacAddr); + } else + return -EINVAL; + + return i4Status; +} + +int Set_StaRecBfUpdate(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + STA_REC_BF_UPD_ARGUMENT rStaRecBfUpdArg; + UINT_8 aucMemRow[4], aucMemCol[4]; + INT_32 i4Status = 0; + UINT_32 i; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_StaRecBfUpdate\n"); + + rv = sscanf(prInBuf, "%x:%x:%x:%x:%x:%d:%d:%d:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x", + &rStaRecBfUpdArg.u4WlanId, &rStaRecBfUpdArg.u4BssId, &rStaRecBfUpdArg.u4PfmuId, + &rStaRecBfUpdArg.u4SuMu, &rStaRecBfUpdArg.u4eTxBfCap, &rStaRecBfUpdArg.u4NdpaRate, + &rStaRecBfUpdArg.u4NdpRate, &rStaRecBfUpdArg.u4ReptPollRate, &rStaRecBfUpdArg.u4TxMode, + &rStaRecBfUpdArg.u4Nc, &rStaRecBfUpdArg.u4Nr, &rStaRecBfUpdArg.u4Bw, &rStaRecBfUpdArg.u4SpeIdx, + &rStaRecBfUpdArg.u4TotalMemReq, &rStaRecBfUpdArg.u4MemReq20M, &rStaRecBfUpdArg.au4MemRow[0], + &rStaRecBfUpdArg.au4MemCol[0], &rStaRecBfUpdArg.au4MemRow[1], &rStaRecBfUpdArg.au4MemCol[1], + &rStaRecBfUpdArg.au4MemRow[2], &rStaRecBfUpdArg.au4MemCol[2], &rStaRecBfUpdArg.au4MemRow[3], + &rStaRecBfUpdArg.au4MemCol[3]); + if (rv == 23) { + /* + *DBGLOG(RFTEST, ERROR, + *"MT6632 Set_StaRecBfUpdate prInBuf = %s, u4WlanId = %x, u4BssId = %x, u4Aid = %x, + * aucMacAddr[0]:%x, aucMacAddr[1]:%x, aucMacAddr[2]:%x, aucMacAddr[3]:%x, aucMacAddr[4]:%x, + * aucMacAddr[5]:%x", + * prInBuf, u4OwnMacIdx, u4BssIdx, u4Aid, + * aucMacAddr[0], aucMacAddr[1], aucMacAddr[2], aucMacAddr[3], aucMacAddr[4], aucMacAddr[5]); + */ + for (i = 0; i < 4; i++) { + aucMemRow[i] = rStaRecBfUpdArg.au4MemRow[i]; + aucMemCol[i] = rStaRecBfUpdArg.au4MemCol[i]; + } + i4Status = StaRecBfUpdate(prNetDev, rStaRecBfUpdArg, aucMemRow, aucMemCol); + } else + return -EINVAL; + + return i4Status; +} + +#if CFG_SUPPORT_MU_MIMO +int Set_MUGetInitMCS(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T rMuMimoActionInfo; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + + UINT_32 u4groupIdx; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_MUGetInitMCS\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rv = kstrtouint(prInBuf, 0, &u4groupIdx); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "MT6632 Test\n"); + DBGLOG(RFTEST, ERROR, "MT6632 Set_MUGetInitMCS prInBuf = %s, u4groupIdx = %x", prInBuf, u4groupIdx); + + rMuMimoActionInfo.ucMuMimoCategory = MU_GET_CALC_INIT_MCS; + rMuMimoActionInfo.unMuMimoParam.rMuGetCalcInitMcs.ucgroupIdx = u4groupIdx; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, sizeof(rMuMimoActionInfo), TRUE, TRUE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUCalInitMCS(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T rMuMimoActionInfo; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + + UINT_32 u4NumOfUser, u4Bandwidth, u4NssOfUser0, u4NssOfUser1, u4PfMuIdOfUser0, u4PfMuIdOfUser1, u4NumOfTxer, + u4SpeIndex, u4GroupIndex; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_MUCalInitMCS\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rv = sscanf + (prInBuf, "%x:%x:%x:%x:%x:%x:%x:%x:%x", &u4NumOfUser, &u4Bandwidth, &u4NssOfUser0, &u4NssOfUser1, + &u4PfMuIdOfUser0, &u4PfMuIdOfUser1, &u4NumOfTxer, &u4SpeIndex, &u4GroupIndex); + if (rv == 9) { + DBGLOG(RFTEST, ERROR, + "MT6632 Set_MUCalInitMCS prInBuf = %s, u4NumOfUser = %x, u4Bandwidth = %x, u4NssOfUser0 = %x, u4NssOfUser1 = %x, u4PfMuIdOfUser0 = %x, u4PfMuIdOfUser1 = %x, u4NumOfTxer = %x, u4SpeIndex = %x, u4GroupIndex = %x", + prInBuf, u4NumOfUser, u4Bandwidth, u4NssOfUser0, u4NssOfUser1, u4PfMuIdOfUser0, u4PfMuIdOfUser1, + u4NumOfTxer, u4SpeIndex, u4GroupIndex); + + rMuMimoActionInfo.ucMuMimoCategory = MU_SET_CALC_INIT_MCS; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucNumOfUser = u4NumOfUser; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucBandwidth = u4Bandwidth; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucNssOfUser0 = u4NssOfUser0; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucNssOfUser1 = u4NssOfUser1; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucPfMuIdOfUser0 = u4PfMuIdOfUser0; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucPfMuIdOfUser1 = u4PfMuIdOfUser1; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucNumOfTxer = u4NumOfTxer; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.ucSpeIndex = u4SpeIndex; + rMuMimoActionInfo.unMuMimoParam.rMuSetInitMcs.u4GroupIndex = u4GroupIndex; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, sizeof(rMuMimoActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUCalLQ(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T rMuMimoActionInfo; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + + UINT_32 u4NumOfUser, u4Bandwidth, u4NssOfUser0, u4NssOfUser1, u4PfMuIdOfUser0, u4PfMuIdOfUser1, + u4NumOfTxer, u4SpeIndex, u4GroupIndex; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_MUCalLQ\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rv = sscanf + (prInBuf, "%x:%x:%x:%x:%x:%x:%x:%x:%x", + &u4NumOfUser, &u4Bandwidth, &u4NssOfUser0, &u4NssOfUser1, + &u4PfMuIdOfUser0, &u4PfMuIdOfUser1, &u4NumOfTxer, &u4SpeIndex, &u4GroupIndex); + if (rv == 9) { + DBGLOG(RFTEST, ERROR, + "MT6632 Set_MUCalLQ prInBuf = %s, u4NumOfUser = %x, u4Bandwidth = %x, u4NssOfUser0 = %x, u4NssOfUser1 = %x, u4PfMuIdOfUser0 = %x, u4PfMuIdOfUser1 = %x, u4NumOfTxer = %x, u4SpeIndex = %x, u4GroupIndex = %x", + prInBuf, u4NumOfUser, u4Bandwidth, u4NssOfUser0, u4NssOfUser1, u4PfMuIdOfUser0, u4PfMuIdOfUser1, + u4NumOfTxer, u4SpeIndex, u4GroupIndex); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_CALC_LQ; + /* rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucType = u4Type; */ + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucNumOfUser = u4NumOfUser; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucBandwidth = u4Bandwidth; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucNssOfUser0 = u4NssOfUser0; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucNssOfUser1 = u4NssOfUser1; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucPfMuIdOfUser0 = u4PfMuIdOfUser0; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucPfMuIdOfUser1 = u4PfMuIdOfUser1; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucNumOfTxer = u4NumOfTxer; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.ucSpeIndex = u4SpeIndex; + rMuMimoActionInfo.unMuMimoParam.rMuSetCalcLq.u4GroupIndex = u4GroupIndex; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, sizeof(rMuMimoActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUGetLQ(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T rMuMimoActionInfo; + INT_32 i4Status = 0; + /* UINT_32 u4Type; */ + UINT_32 u4BufLen = 0; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_MUGetLQ\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* if (sscanf(prInBuf, "%x", &u4Type) == 1) */ + /* { */ + /* DBGLOG(RFTEST, ERROR, "MT6632 Set_MUGetLQ prInBuf = %s, u4Type = %x", prInBuf, u4Type); */ + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_GET_CALC_LQ; + /* rMuMimoActionInfo.unMuMimoParam.rMuGetLq.ucType = u4Type; */ + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, sizeof(rMuMimoActionInfo), TRUE, TRUE, TRUE, &u4BufLen); + /* } */ + /* else */ + /* { */ + /* return -EINVAL; */ + /* } */ + + return i4Status; +} + +int Set_MUSetSNROffset(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T rMuMimoActionInfo; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + + UINT_32 u4Val; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_MUSetSNROffset\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rv = kstrtoint(prInBuf, 0, &u4Val); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "MT6632 Set_MUSetSNROffset prInBuf = %s, u4Val = %x", prInBuf, u4Val); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_SNR_OFFSET; + rMuMimoActionInfo.unMuMimoParam.rMuSetSnrOffset.ucVal = u4Val; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, sizeof(rMuMimoActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUSetZeroNss(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T rMuMimoActionInfo; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + + UINT_32 u4Val; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_MUSetZeroNss\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rv = kstrtouint(prInBuf, 0, &u4Val); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "MT6632 Set_MUSetZeroNss prInBuf = %s, u4Val = %x", prInBuf, u4Val); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_ZERO_NSS; + rMuMimoActionInfo.unMuMimoParam.rMuSetZeroNss.ucVal = u4Val; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, sizeof(rMuMimoActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUSetSpeedUpLQ(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T rMuMimoActionInfo; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + + UINT_32 u4Val; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_MUSetSpeedUpLQ\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rv = kstrtouint(prInBuf, 0, &u4Val); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "MT6632 Set_MUSetSpeedUpLQ prInBuf = %s, u4Val = %x", prInBuf, u4Val); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_SPEED_UP_LQ; + rMuMimoActionInfo.unMuMimoParam.rMuSpeedUpLq.u4Val = u4Val; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, sizeof(rMuMimoActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUSetMUTable(struct net_device *prNetDev, UINT_8 *prTable) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T rMuMimoActionInfo; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + /*UINT_32 i; + *UINT_32 u4Type, u4Length; + */ + + DBGLOG(RFTEST, ERROR, "MT6632 Set_MUSetMUTable\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* if (sscanf(prInBuf, "%x:%x", &u4Type, &u4Length) == 2) */ + /* { */ + /* DBGLOG(RFTEST, ERROR, "MT6632 Set_MUSetMUTable prInBuf = %s, */ + /* u4Type = %x, u4Length = %x", prInBuf, u4Type, u4Length); */ + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_MU_TABLE; + /* rMuMimoActionInfo.unMuMimoParam.rMuSetMuTable.u2Type = u4Type; */ + /* rMuMimoActionInfo.unMuMimoParam.rMuSetMuTable.u4Length = u4Length; */ + + /* for ( i = 0 ; i < NUM_MUT_NR_NUM * NUM_MUT_FEC * NUM_MUT_MCS * NUM_MUT_INDEX ; i++) */ + /* { */ + memcpy(rMuMimoActionInfo.unMuMimoParam.rMuSetMuTable.aucMetricTable, prTable, + NUM_MUT_NR_NUM * NUM_MUT_FEC * NUM_MUT_MCS * NUM_MUT_INDEX); + /* } */ + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, sizeof(rMuMimoActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + /* } */ + /* else */ + /* { */ + /* return -EINVAL; */ + /* } */ + + return i4Status; +} + +int Set_MUSetGroup(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T rMuMimoActionInfo; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + UINT_32 i = 0; + + UINT_32 aucUser0MacAddr[PARAM_MAC_ADDR_LEN], aucUser1MacAddr[PARAM_MAC_ADDR_LEN]; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_MUSetGroup\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (sscanf(prInBuf, "%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x", + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4GroupIndex, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4NumOfUser, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0Ldpc, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1Ldpc, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4ShortGI, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4Bw, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0Nss, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1Nss, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4GroupId, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0UP, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1UP, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0MuPfId, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1MuPfId, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0InitMCS, + &rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1InitMCS, &aucUser0MacAddr[0], + &aucUser0MacAddr[1], &aucUser0MacAddr[2], &aucUser0MacAddr[3], &aucUser0MacAddr[4], + &aucUser0MacAddr[5], &aucUser1MacAddr[0], &aucUser1MacAddr[1], &aucUser1MacAddr[2], + &aucUser1MacAddr[3], &aucUser1MacAddr[4], &aucUser1MacAddr[5]) == 27) { + DBGLOG(RFTEST, ERROR, + "MT6632 Set_MUSetGroup prInBuf = %s,u4GroupIndex = %d, u4NumOfUser = %d, u4User0Ldpc = %d, u4User1Ldpc = %d, u4ShortGI = %d, u4Bw = %d, u4User0Nss = %d, u4User1Nss = %d, u4GroupId = %d, u4User0UP = %d, u4User1UP = %d, u4User0MuPfId = %d, u4User1MuPfId = %d, u4User0InitMCS = %d, u4User1InitMCS = %d,aucUser0MacAddr[0] = %x, aucUser0MacAddr[1] = %x, aucUser0MacAddr[2] = %x, aucUser0MacAddr[3] = %x, aucUser0MacAddr[4] = %x, aucUser0MacAddr[5] = %x,aucUser1MacAddr[0] = %x, aucUser1MacAddr[1] = %x, aucUser1MacAddr[2] = %x, aucUser1MacAddr[3] = %x, aucUser1MacAddr[4] = %x, aucUser1MacAddr[5] = %x,", + prInBuf, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4GroupIndex, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4NumOfUser, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0Ldpc, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1Ldpc, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4ShortGI, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4Bw, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0Nss, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1Nss, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4GroupId, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0UP, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1UP, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0MuPfId, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1MuPfId, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User0InitMCS, + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.u4User1InitMCS, aucUser0MacAddr[0], + aucUser0MacAddr[1], aucUser0MacAddr[2], aucUser0MacAddr[3], aucUser0MacAddr[4], + aucUser0MacAddr[5], aucUser1MacAddr[0], aucUser1MacAddr[1], aucUser1MacAddr[2], + aucUser1MacAddr[3], aucUser1MacAddr[4], aucUser1MacAddr[5] + ); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_GROUP; + for (i = 0; i < PARAM_MAC_ADDR_LEN; i++) { + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.aucUser0MacAddr[i] = aucUser0MacAddr[i]; + rMuMimoActionInfo.unMuMimoParam.rMuSetGroup.aucUser1MacAddr[i] = aucUser1MacAddr[i]; + } + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, sizeof(rMuMimoActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + } else { + return -EINVAL; + } + + return i4Status; +} + +int Set_MUGetQD(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T rMuMimoActionInfo; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + + UINT_32 u4SubcarrierIndex, u4Length; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_MUGetQD\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (sscanf(prInBuf, "%x:%x", &u4SubcarrierIndex, &u4Length) == 2) { + DBGLOG(RFTEST, ERROR, "MT6632 Set_MUGetQD prInBuf = %s, u4SubcarrierIndex = %x, u4Length = %x", prInBuf, + u4SubcarrierIndex, u4Length); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_GET_QD; + rMuMimoActionInfo.unMuMimoParam.rMuGetQd.ucSubcarrierIndex = u4SubcarrierIndex; + /* rMuMimoActionInfo.unMuMimoParam.rMuGetQd.u4Length = u4Length; */ + /* rMuMimoActionInfo.unMuMimoParam.rMuGetQd.ucgroupIdx = ucgroupIdx; */ + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, sizeof(rMuMimoActionInfo), TRUE, TRUE, TRUE, &u4BufLen); + } else { + return -EINVAL; + } + + return i4Status; +} + +int Set_MUSetEnable(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T rMuMimoActionInfo; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + + UINT_32 u4Val; + INT_32 rv; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_MUSetEnable\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rv = kstrtouint(prInBuf, 0, &u4Val); + if (rv == 0) { + DBGLOG(RFTEST, ERROR, "MT6632 Set_MUSetEnable prInBuf = %s, u4Val = %x", prInBuf, u4Val); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_ENABLE; + rMuMimoActionInfo.unMuMimoParam.rMuSetEnable.ucVal = u4Val; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, sizeof(rMuMimoActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + } else + return -EINVAL; + + return i4Status; +} + +int Set_MUSetGID_UP(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T rMuMimoActionInfo; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_MUSetGID_UP\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (sscanf(prInBuf, "%x:%x:%x:%x:%x:%x", + &rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Gid[0], + &rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Gid[1], + &rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[0], + &rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[1], + &rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[2], + &rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[3]) == 6) { + DBGLOG(RFTEST, ERROR, + "MT6632 Set_MUSetGID_UP prInBuf = %s, au4Gid[0] = %x, au4Gid[1] = %x, au4Up[0] = %x, au4Up[1] = %x, au4Up[2] = %x, au4Up[3] = %x", + prInBuf, rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Gid[0], + rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Gid[1], + rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[0], + rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[1], + rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[2], + rMuMimoActionInfo.unMuMimoParam.rMuSetGidUp.au4Up[3]); + + rMuMimoActionInfo.ucMuMimoCategory = MU_HQA_SET_STA_PARAM; + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, sizeof(rMuMimoActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + } else { + return -EINVAL; + } + + return i4Status; +} + +int Set_MUTriggerTx(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T rMuMimoActionInfo; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + UINT_32 i, j; + + UINT_32 u4IsRandomPattern, u4MsduPayloadLength0, u4MsduPayloadLength1, u4MuPacketCount, u4NumOfSTAs; + UINT_32 au4MacAddrs[2][6]; + + DBGLOG(RFTEST, ERROR, "MT6632 Set_MUTriggerTx\n"); + + kalMemZero(&rMuMimoActionInfo, sizeof(rMuMimoActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (sscanf(prInBuf, "%d:%x:%x:%x:%d:%d:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x", + &u4IsRandomPattern, &u4MsduPayloadLength0, &u4MsduPayloadLength1, &u4MuPacketCount, &u4NumOfSTAs, + &au4MacAddrs[0][0], &au4MacAddrs[0][1], &au4MacAddrs[0][2], &au4MacAddrs[0][3], &au4MacAddrs[0][4], + &au4MacAddrs[0][5], &au4MacAddrs[1][0], &au4MacAddrs[1][1], &au4MacAddrs[1][2], &au4MacAddrs[1][3], + &au4MacAddrs[1][4], &au4MacAddrs[1][5]) == 17) { + DBGLOG(RFTEST, ERROR, + "MT6632 Set_MUTriggerTx prInBuf = %s, u4IsRandomPattern = %x, u4MsduPayloadLength0 = %x, u4MsduPayloadLength1 = %x, u4MuPacketCount = %x, u4NumOfSTAs = %x, au4MacAddrs[0][0] = %x, au4MacAddrs[0][1] = %x, au4MacAddrs[0][2] = %x, au4MacAddrs[0][3] = %x, au4MacAddrs[0][4] = %x, au4MacAddrs[0][5] = %x,au4MacAddrs[1][0] = %x, au4MacAddrs[1][1] = %x, au4MacAddrs[1][2] = %x, au4MacAddrs[1][3] = %x, au4MacAddrs[1][4] = %x, au4MacAddrs[1][5] = %x", + prInBuf, u4IsRandomPattern, u4MsduPayloadLength0, u4MsduPayloadLength1, u4MuPacketCount, + u4NumOfSTAs, au4MacAddrs[0][0], au4MacAddrs[0][1], au4MacAddrs[0][2], au4MacAddrs[0][3], + au4MacAddrs[0][4], au4MacAddrs[0][5], au4MacAddrs[1][0], au4MacAddrs[1][1], au4MacAddrs[1][2], + au4MacAddrs[1][3], au4MacAddrs[1][4], au4MacAddrs[1][5]); + + rMuMimoActionInfo.ucMuMimoCategory = MU_SET_TRIGGER_MU_TX; + rMuMimoActionInfo.unMuMimoParam.rMuTriggerMuTx.fgIsRandomPattern = u4IsRandomPattern; + rMuMimoActionInfo.unMuMimoParam.rMuTriggerMuTx.u4MsduPayloadLength0 = u4MsduPayloadLength0; + rMuMimoActionInfo.unMuMimoParam.rMuTriggerMuTx.u4MsduPayloadLength1 = u4MsduPayloadLength1; + rMuMimoActionInfo.unMuMimoParam.rMuTriggerMuTx.u4MuPacketCount = u4MuPacketCount; + rMuMimoActionInfo.unMuMimoParam.rMuTriggerMuTx.u4NumOfSTAs = u4NumOfSTAs; + + for (i = 0 ; i < 2 ; i++) { + for (j = 0 ; j < PARAM_MAC_ADDR_LEN ; j++) + rMuMimoActionInfo.unMuMimoParam.rMuTriggerMuTx.aucMacAddrs[i][j] = au4MacAddrs[i][j]; + } + + i4Status = kalIoctl(prGlueInfo, + wlanoidMuMimoAction, + &rMuMimoActionInfo, sizeof(rMuMimoActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + } else { + return -EINVAL; + } + + return i4Status; +} +#endif +#endif + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Write Efuse. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int WriteEfuse(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + INT_32 i4Status; + INT_32 rv; + UINT_32 addr[2]; + UINT_16 addr2[2]; + + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv WriteEfuse, buf: %s\n", prInBuf); + + rv = sscanf(prInBuf, "%x:%x", &addr[0], &addr[1]); + + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv WriteEfuse, prInBuf: %s\n", prInBuf); + DBGLOG(INIT, ERROR, "MT6632 : ATE_AGENT iwpriv WriteEfuse :%02x:%02x\n", addr[0], addr[1]); + + addr2[0] = (UINT_16) addr[0]; + addr2[1] = (UINT_16) addr[1]; + + if (rv == 2) + i4Status = MT_ATEWriteEfuse(prNetDev, addr2[0], addr2[1]); + else + return -EINVAL; + + return i4Status; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set Tx Power. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetTxTargetPower(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + INT_32 i4Status; + INT_32 rv; + int addr; + UINT_8 addr2; + + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv Set Tx Target Power, buf: %s\n", prInBuf); + + /* rv = sscanf(prInBuf, "%u", &addr);*/ + rv = kstrtoint(prInBuf, 0, &addr); + + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv Set Tx Target Power, prInBuf: %s\n", prInBuf); + DBGLOG(INIT, ERROR, "MT6632 : ATE_AGENT iwpriv Set Tx Target Power :%02x\n", addr); + + addr2 = (UINT_8) addr; + + if (rv == 0) + i4Status = MT_ATESetTxTargetPower(prNetDev, addr2); + else + return -EINVAL; + + return i4Status; +} + +#if (CFG_SUPPORT_DFS_MASTER == 1) +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set RDD Report +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetRddReport(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + INT_32 i4Status; + INT_32 rv; + int dbdcIdx; + UINT_8 ucDbdcIdx; + + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv Set RDD Report, buf: %s\n", prInBuf); + + /* rv = sscanf(prInBuf, "%u", &addr);*/ + rv = kstrtoint(prInBuf, 0, &dbdcIdx); + + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv Set RDD Report, prInBuf: %s\n", prInBuf); + DBGLOG(INIT, ERROR, "MT6632 : ATE_AGENT iwpriv Set RDD Report : Band %d\n", dbdcIdx); + + if (p2pFuncGetDfsState() == DFS_STATE_INACTIVE || p2pFuncGetDfsState() == DFS_STATE_DETECTED) { + DBGLOG(REQ, ERROR, "RDD Report is not supported in this DFS state (inactive or deteted)\n"); + return WLAN_STATUS_NOT_SUPPORTED; + } + + if (dbdcIdx != 0 && dbdcIdx != 1) { + DBGLOG(REQ, ERROR, "RDD index is not \"0\" or \"1\", Invalid data\n"); + return WLAN_STATUS_INVALID_DATA; + } + + ucDbdcIdx = (UINT_8) dbdcIdx; + + if (rv == 0) + i4Status = MT_ATESetRddReport(prNetDev, ucDbdcIdx); + else + return -EINVAL; + + return i4Status; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set By Pass CAC. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetByPassCac(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + INT_32 i4Status; + INT_32 rv; + INT_32 i4ByPassCacTime; + UINT_32 u4ByPassCacTime; + + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv Set By Pass Cac, buf: %s\n", prInBuf); + + rv = kstrtoint(prInBuf, 0, &i4ByPassCacTime); + + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv Set By Pass Cac, prInBuf: %s\n", prInBuf); + DBGLOG(INIT, ERROR, "MT6632 : ATE_AGENT iwpriv Set By Pass Cac : %dsec\n", i4ByPassCacTime); + + if (i4ByPassCacTime < 0) { + DBGLOG(REQ, ERROR, "Cac time < 0, Invalid data\n"); + return WLAN_STATUS_INVALID_DATA; + } + + u4ByPassCacTime = (UINT_32) i4ByPassCacTime; + + p2pFuncEnableManualCac(); + + if (rv == 0) + i4Status = p2pFuncSetDriverCacTime(u4ByPassCacTime); + else + return -EINVAL; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set Radar Detect Mode. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int SetRadarDetectMode(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + INT_32 i4Status; + INT_32 rv; + int radarDetectMode; + UINT_8 ucRadarDetectMode; + + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv Set Radar Detect Mode, buf: %s\n", prInBuf); + + rv = kstrtoint(prInBuf, 0, &radarDetectMode); + + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv Set Radar Detect Mode, prInBuf: %s\n", prInBuf); + DBGLOG(INIT, ERROR, "MT6632 : ATE_AGENT iwpriv Set Radar Detect Mode : %d\n", radarDetectMode); + + if (p2pFuncGetDfsState() == DFS_STATE_INACTIVE || p2pFuncGetDfsState() == DFS_STATE_DETECTED) { + DBGLOG(REQ, ERROR, "RDD Report is not supported in this DFS state (inactive or deteted)\n"); + return WLAN_STATUS_NOT_SUPPORTED; + } + + if (radarDetectMode != 0 && radarDetectMode != 1) { + DBGLOG(REQ, ERROR, "Radar Detect Mode is not \"0\" or \"1\", Invalid data\n"); + return WLAN_STATUS_INVALID_DATA; + } + + ucRadarDetectMode = (UINT_8) radarDetectMode; + + p2pFuncSetRadarDetectMode(ucRadarDetectMode); + + if (rv == 0) + i4Status = MT_ATESetRadarDetectMode(prNetDev, ucRadarDetectMode); + else + return -EINVAL; + + return i4Status; +} + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to search the corresponding ATE agent function. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval 0 On success. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +int AteCmdSetHandle(struct net_device *prNetDev, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + UINT_8 *this_char, *value; + P_ATE_PRIV_CMD prAtePrivCmd; + INT_32 i4Status = 0; + + while ((this_char = strsep((char **)&prInBuf, ",")) != NULL) { + if (!*this_char) + continue; + DBGLOG(RFTEST, ERROR, "MT6632 : ATE_AGENT iwpriv this_char = %s\n", this_char); + DBGLOG(RFTEST, INFO, "MT6632 : ATE_AGENT iwpriv this_char = %s\n", this_char); + + value = strchr(this_char, '='); + if (value != NULL) + *value++ = 0; + + DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv cmd = %s, value = %s\n", this_char, value); + + for (prAtePrivCmd = rAtePrivCmdTable; prAtePrivCmd->name; prAtePrivCmd++) { + if (!strcmp(this_char, prAtePrivCmd->name)) { + /*FALSE:Set private failed then return Invalid argument */ + if (prAtePrivCmd->set_proc(prNetDev, value) != 0) + i4Status = -EINVAL; + break; /*Exit for loop. */ + } + } + + if (prAtePrivCmd->name == NULL) { /*Not found argument */ + i4Status = -EINVAL; + break; + } + } + return i4Status; +} +#endif /*CFG_SUPPORT_QA_TOOL */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_bow.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_bow.c new file mode 100644 index 0000000000000..a708472834fc2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_bow.c @@ -0,0 +1,1169 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "debug.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "precomp.h" +#include +#include "bss.h" + +#if CFG_ENABLE_BT_OVER_WIFI + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* @FIXME if there is command/event with payload length > 28 */ +#define MAX_BUFFER_SIZE (64) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +UINT_32 g_u4PrevSysTime; +UINT_32 g_u4CurrentSysTime; +UINT_32 g_arBowRevPalPacketTime[32]; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/* forward declarations */ +static ssize_t bow_ampc_read(IN struct file *filp, IN char __user *buf, IN size_t size, IN OUT loff_t *ppos); + +static ssize_t bow_ampc_write(IN struct file *filp, OUT const char __user *buf, IN size_t size, IN OUT loff_t *ppos); + +static long bow_ampc_ioctl(IN struct file *filp, IN unsigned int cmd, IN OUT unsigned long arg); + +static unsigned int bow_ampc_poll(IN struct file *filp, IN poll_table * wait); + +static int bow_ampc_open(IN struct inode *inodep, IN struct file *filp); + +static int bow_ampc_release(IN struct inode *inodep, IN struct file *filp); + +/* character file operations */ +static const struct file_operations bow_ampc_fops = { + /* .owner = THIS_MODULE, */ + .read = bow_ampc_read, + .write = bow_ampc_write, + .unlocked_ioctl = bow_ampc_ioctl, + .poll = bow_ampc_poll, + .open = bow_ampc_open, + .release = bow_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); + + DBGLOG(BOW, INFO, "Register for character device to communicate with 802.11 PAL.\n"); + + if (prGlueInfo->rBowInfo.fgIsRegistered == TRUE) + return FALSE; +#if 0 + /* 1. allocate major number dynamically */ + + if (alloc_chrdev_region(&(prGlueInfo->rBowInfo.u4DeviceNumber), 0, /* first minor number */ + 1, /* number */ + GLUE_BOW_DEVICE_NAME) != 0) + + return FALSE; +#endif + +#if 1 + +#if defined(CONFIG_AMPC_CDEV_NUM) + prGlueInfo->rBowInfo.u4DeviceNumber = MKDEV(CONFIG_AMPC_CDEV_NUM, 0); +#else + prGlueInfo->rBowInfo.u4DeviceNumber = MKDEV(226, 0); +#endif + + if (register_chrdev_region(prGlueInfo->rBowInfo.u4DeviceNumber, 1, /* number */ + GLUE_BOW_DEVICE_NAME) != 0) + + return FALSE; +#endif + + /* 2. spin-lock initialization */ + /* spin_lock_init(&(prGlueInfo->rBowInfo.rSpinLock)); */ + + /* 3. initialize kfifo */ +#if 0 + prGlueInfo->rBowInfo.prKfifo = kfifo_alloc(GLUE_BOW_KFIFO_DEPTH, + GFP_KERNEL, + &(prGlueInfo->rBowInfo.rSpinLock)); +#endif + 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), &bow_ampc_fops); + /* prGlueInfo->rBowInfo.cdev.owner = THIS_MODULE; */ + prGlueInfo->rBowInfo.cdev.ops = &bow_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); + + DBGLOG(BOW, INFO, "Unregister character device for communicating with 802.11 PAL.\n"); + + if (prGlueInfo->rBowInfo.fgIsRegistered == FALSE) + return FALSE; + + prGlueInfo->rBowInfo.fgIsRegistered = FALSE; + + /* 1. free netdev if necessary */ +#if CFG_BOW_SEPARATE_DATA_PATH + kalUninitBowDevice(prGlueInfo); +#endif + + /* 2. removal of character device */ + cdev_del(&(prGlueInfo->rBowInfo.cdev)); + + /* 3. free kfifo */ +/* kfifo_free(prGlueInfo->rBowInfo.prKfifo); */ + kfifo_free(&(prGlueInfo->rBowInfo.rKfifo)); +/* prGlueInfo->rBowInfo.prKfifo = NULL; */ +/* prGlueInfo->rBowInfo.rKfifo = NULL; */ + + /* 4. free device number */ + unregister_chrdev_region(prGlueInfo->rBowInfo.u4DeviceNumber, 1); + + return TRUE; + +} /* end of glUnregisterAmpc */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief read handler for character device to communicate with 802.11 PAL +* +* \param[in] +* \return +* Follows Linux Character Device Interface +* +*/ +/*----------------------------------------------------------------------------*/ +static ssize_t bow_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); + + DBGLOG(BOW, INFO, "BoW EVENT read.\n"); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return -EFAULT; + /* size check */ +/* if(kfifo_len(prGlueInfo->rBowInfo.prKfifo) >= size) */ + if (kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)) >= size) + retval = size; + else + retval = kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)); +/* retval = kfifo_len(prGlueInfo->rBowInfo.prKfifo); */ + +/* kfifo_get(prGlueInfo->rBowInfo.prKfifo, aucBuffer, retval); */ +/* kfifo_out(prGlueInfo->rBowInfo.prKfifo, aucBuffer, retval); */ + if (!(kfifo_out(&(prGlueInfo->rBowInfo.rKfifo), aucBuffer, retval))) + retval = -EIO; + + 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 bow_ampc_write(IN struct file *filp, OUT const char __user *buf, IN size_t size, IN OUT loff_t *ppos) +{ + UINT_8 i; + + UINT_8 aucBuffer[MAX_BUFFER_SIZE]; + P_AMPC_COMMAND prCmd; + P_GLUE_INFO_T prGlueInfo; + + prGlueInfo = (P_GLUE_INFO_T) (filp->private_data); + ASSERT(prGlueInfo); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return -EFAULT; + + if (size > MAX_BUFFER_SIZE) + return -EINVAL; + else if (copy_from_user(aucBuffer, buf, size)) + return -EIO; + + 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"); + + prCmd = (P_AMPC_COMMAND) aucBuffer; + + 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)); + + /* size check */ + if (prCmd->rHeader.u2PayloadLength + sizeof(AMPC_COMMAND_HEADER_T) != size) { + DBGLOG(BOW, EVENT, "Wrong CMD total length.\n"); + + 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 bow_ampc_ioctl(IN struct file *filp, IN unsigned int cmd, IN OUT unsigned long arg) +{ + int err = 0; + P_GLUE_INFO_T prGlueInfo; + + prGlueInfo = (P_GLUE_INFO_T) (filp->private_data); + + ASSERT(prGlueInfo); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return -EFAULT; + /* permission check */ + if (_IOC_DIR(cmd) & _IOC_READ) + err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)); + else if (_IOC_DIR(cmd) & _IOC_WRITE) + err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)); + if (err) + return -EFAULT; + + /* no ioctl is implemented yet */ + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief ioctl handler for character device to communicate with 802.11 PAL +* +* \param[in] +* \return +* Follows Linux Character Device Interface +* +*/ +/*----------------------------------------------------------------------------*/ +static unsigned int bow_ampc_poll(IN struct file *filp, IN poll_table * wait) +{ + unsigned int retval; + P_GLUE_INFO_T prGlueInfo; + + prGlueInfo = (P_GLUE_INFO_T) (filp->private_data); + + ASSERT(prGlueInfo); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return -EFAULT; + + poll_wait(filp, &prGlueInfo->rBowInfo.outq, wait); + + retval = (POLLOUT | POLLWRNORM); /* always accepts incoming command packets */ + +/* DBGLOG(BOW, EVENT, ("bow_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, ("bow_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 bow_ampc_open(IN struct inode *inodep, IN struct file *filp) +{ + P_GLUE_INFO_T prGlueInfo; + P_GL_BOW_INFO prBowInfo; + + DBGLOG(BOW, INFO, "in %s\n", __func__); + + 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 bow_ampc_release(IN struct inode *inodep, IN struct file *filp) +{ + P_GLUE_INFO_T prGlueInfo; + + prGlueInfo = (P_GLUE_INFO_T) (filp->private_data); + + DBGLOG(BOW, INFO, "in %s\n", __func__); + + ASSERT(prGlueInfo); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to indicate event for Bluetooth over Wi-Fi +* +* \param[in] +* prGlueInfo +* prEvent +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalIndicateBOWEvent(IN P_GLUE_INFO_T prGlueInfo, IN P_AMPC_EVENT prEvent) +{ + size_t u4AvailSize, u4EventSize; + + ASSERT(prGlueInfo); + ASSERT(prEvent); + + /* check device */ + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return; +#if 0 + u4AvailSize = GLUE_BOW_KFIFO_DEPTH - kfifo_len(prGlueInfo->rBowInfo.prKfifo); +#endif + 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)); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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); + + DBGLOG(BOW, EVENT, "kalGetBowState.\n"); + + for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { + if (EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr, aucPeerAddress) == 0) { + 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]); + + 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); + DBGLOG(BOW, EVENT, "kalSetBowState, aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + aucPeerAddress[0], + aucPeerAddress[1], aucPeerAddress[2], aucPeerAddress[3], aucPeerAddress[4], aucPeerAddress[5]); + + for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { + if (EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr, aucPeerAddress) == 0) { + prGlueInfo->rBowInfo.aeState[i] = eBowState; + + 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]); + + 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) { + /* Henry, 0 : Responder, 1 : Initiator */ + prGlueInfo->rBowInfo.aucRole[i] = ucRole; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 + DBGLOG(BOW, EVENT, "kalGetBowAvailablePhysicalLinkCount, ucLinkCount, %c.\n", ucLinkCount); +#endif + + return ucLinkCount; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This inline function is to extract some packet information for BoW +* +* @param prGlueInfo Pointer to the glue structure +* @param prNdisPacket Packet descriptor +* @param pfgIs1X 802.1x packet or not +* +* @retval TRUE Success to extract information +* @retval FALSE Fail to extract correct information +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalBowFrameClassifier(IN P_GLUE_INFO_T prGlueInfo, IN P_NATIVE_PACKET prPacket, OUT PBOOLEAN pfgIs1X) +{ + UINT_32 u4PacketLen; + UINT_16 u2EtherTypeLen; + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + PUINT_8 aucLookAheadBuf = NULL; + UINT_8 ucEthTypeLenOffset = ETHER_HEADER_LEN - ETHER_TYPE_LEN; + PUINT_8 pucNextProtocol = NULL; + UINT_8 aucLLC[] = ETH_LLC; + UINT_8 aucSnapBtOui[] = ETH_SNAP_BT_SIG_OUI; + UINT_8 ucMinLength = ucEthTypeLenOffset + ETHER_TYPE_LEN + ETH_LLC_LEN + ETH_SNAP_LEN; + + DEBUGFUNC("kalQoSFrameClassifierAndPacketInfo"); + + u4PacketLen = prSkb->len; + + if (u4PacketLen < ETHER_HEADER_LEN) { + DBGLOG(INIT, WARN, "Invalid Ether packet length: %lu\n", u4PacketLen); + return FALSE; + } + + aucLookAheadBuf = prSkb->data; + + *pfgIs1X = FALSE; + + /* 4 <0> Obtain Ether Type/Len */ + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[ucEthTypeLenOffset], &u2EtherTypeLen); + + /* 4 <1> Skip 802.1Q header (VLAN Tagging) */ + if (u2EtherTypeLen == ETH_P_VLAN) { + ucEthTypeLenOffset += ETH_802_1Q_HEADER_LEN; + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[ucEthTypeLenOffset], &u2EtherTypeLen); + } + /* 4 <2> Obtain next protocol pointer */ + pucNextProtocol = &aucLookAheadBuf[ucEthTypeLenOffset + ETHER_TYPE_LEN]; + + /* 4 <3> Handle ethernet format */ + if (u2EtherTypeLen > ETH_802_3_MAX_LEN) { + /* Not BoW frame */ + return FALSE; + } + /* 4 <4> Check for PAL (BT over Wi-Fi) */ + /* BoW LLC/SNAP header check */ + if (u4PacketLen >= ucMinLength && + !kalMemCmp(pucNextProtocol, aucLLC, ETH_LLC_LEN) && + !kalMemCmp(pucNextProtocol + ETH_LLC_LEN, aucSnapBtOui, ETH_SNAP_OUI_LEN)) { + UINT_16 u2LocalCode; + + WLAN_GET_FIELD_BE16(pucNextProtocol + ETH_LLC_LEN + ETH_SNAP_OUI_LEN, &u2LocalCode); + + if (u2LocalCode == BOW_PROTOCOL_ID_SECURITY_FRAME) + *pfgIs1X = TRUE; + + return TRUE; + } + + return FALSE; +} /* end of kalBoWFrameClassifier() */ + +#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; +}; + +#if 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; + UINT_8 ucBssIndex; + + 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)) { + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(BOW, TRACE, "GLUE_FLAG_HALT skip tx\n"); + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } + + GLUE_SET_PKT_FLAG_PAL(prSkb); + + ucBssIndex = wlanGetBssIdxByNetInterface(prGlueInfo, NET_DEV_BOW_IDX); + + GLUE_SET_PKT_BSS_IDX(prSkb, ucBssIndex); + + prQueueEntry = (P_QUE_ENTRY_T) GLUE_GET_PKT_QUEUE_ENTRY(prSkb); + prTxQueue = &prGlueInfo->rTxQueue; + + 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[ucBssIndex][u2QueueIdx]); + + if (prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex][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; +} +#else +/*----------------------------------------------------------------------------*/ +/*! + * \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_NETDEV_PRIVATE_GLUE_INFO prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_8 ucBssIndex; + BOOLEAN fgIs1x; + + ASSERT(prSkb); + ASSERT(prDev); + +#if 1 + prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(prDev); + prGlueInfo = prNetDevPrivate->prGlueInfo; + ucBssIndex = prNetDevPrivate->ucBssIdx; +#else + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + + ucBssIndex = wlanGetBssIdxByNetInterface(prGlueInfo, NET_DEV_BOW_IDX); +#endif + + kalResetPacket(prGlueInfo, (P_NATIVE_PACKET) prSkb); + + /* Discard frames not generated by PAL */ + /* Parsing BOW frame info */ + if (!kalBowFrameClassifier(prGlueInfo, (P_NATIVE_PACKET) prSkb, &fgIs1x)) { + /* Cannot extract packet */ + DBGLOG(BOW, INFO, "Invalid BOW frame, skip Tx\n"); + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } + + if (fgIs1x) + GLUE_SET_PKT_FLAG(prSkb, ENUM_PKT_1X); + + if (kalHardStartXmit(prSkb, prDev, prGlueInfo, ucBssIndex) == WLAN_STATUS_SUCCESS) { + /* Successfully enqueue to Tx queue */ + /* Successfully enqueue to Tx queue */ + } + + /* For Linux, we'll always return OK FLAG, because we'll free this skb by ourself */ + return NETDEV_TX_OK; +} +#endif + +/* 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; + P_NETDEV_PRIVATE_GLUE_INFO prNetDevPriv = (P_NETDEV_PRIVATE_GLUE_INFO) NULL; + + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->rBowInfo.fgIsRegistered == TRUE); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prHif = &prGlueInfo->rHifInfo; + ASSERT(prHif); + + if (prGlueInfo->rBowInfo.fgIsNetRegistered == FALSE) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) + prGlueInfo->rBowInfo.prDevHandler = + alloc_netdev_mq(sizeof(P_GLUE_INFO_T), prDevName, + NET_NAME_PREDICTABLE, ether_setup, CFG_MAX_TXQ_NUM); +#else + prGlueInfo->rBowInfo.prDevHandler = + alloc_netdev_mq(sizeof(P_GLUE_INFO_T), prDevName, ether_setup, CFG_MAX_TXQ_NUM); +#endif + if (!prGlueInfo->rBowInfo.prDevHandler) + return FALSE; + + /* 1. setup netdev */ + /* 1.1 Point to shared glue structure */ + /* *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->rBowInfo.prDevHandler)) = prGlueInfo; */ + prNetDevPriv = (P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(prGlueInfo->rBowInfo.prDevHandler); + prNetDevPriv->prGlueInfo = prGlueInfo; + + /* 1.2 fill hardware address */ + COPY_MAC_ADDR(rMacAddr, prAdapter->rMyMacAddr); + rMacAddr[0] |= 0x2; /* change to local administrated address */ + kalMemCopy(prGlueInfo->rBowInfo.prDevHandler->dev_addr, rMacAddr, ETH_ALEN); + kalMemCopy(prGlueInfo->rBowInfo.prDevHandler->perm_addr, + prGlueInfo->rBowInfo.prDevHandler->dev_addr, ETH_ALEN); + + /* 1.3 register callback functions */ + prGlueInfo->rBowInfo.prDevHandler->needed_headroom += NIC_TX_HEAD_ROOM; + prGlueInfo->rBowInfo.prDevHandler->netdev_ops = &bow_netdev_ops; + +#if defined(_HIF_SDIO) && (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); + + /* 2.1 bind NetDev pointer to NetDev index */ + wlanBindBssIdxToNetInterface(prGlueInfo, bowInit(prAdapter), + (PVOID) prGlueInfo->rBowInfo.prDevHandler); + prNetDevPriv->ucBssIdx = prAdapter->rWifiVar.rBowFsmInfo.ucBssIndex; + /* wlanBindNetInterface(prGlueInfo, NET_DEV_BOW_IDX, */ + /* (PVOID)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) +{ + P_ADAPTER_T prAdapter; + + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + /* ASSERT(prGlueInfo->rBowInfo.fgIsRegistered == TRUE); */ + + if (prGlueInfo->rBowInfo.fgIsNetRegistered == TRUE) { + + prGlueInfo->rBowInfo.fgIsNetRegistered = FALSE; + + bowUninit(prAdapter); + + if (netif_carrier_ok(prGlueInfo->rBowInfo.prDevHandler)) + netif_carrier_off(prGlueInfo->rBowInfo.prDevHandler); + + netif_tx_stop_all_queues(prGlueInfo->rBowInfo.prDevHandler); + + /* netdevice unregistration & free */ + unregister_netdev(prGlueInfo->rBowInfo.prDevHandler); + free_netdev(prGlueInfo->rBowInfo.prDevHandler); + prGlueInfo->rBowInfo.prDevHandler = NULL; + + return TRUE; + + } else { + return FALSE; + } +} + +#endif /* CFG_BOW_SEPARATE_DATA_PATH */ +#endif /* CFG_ENABLE_BT_OVER_WIFI */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_cfg80211.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_cfg80211.c new file mode 100644 index 0000000000000..c7be7d54d981e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_cfg80211.c @@ -0,0 +1,5108 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "debug.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "precomp.h" +#include +#include +#include +#include "gl_cfg80211.h" + +/******************************************************************************* +* 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 responsible for change STA type between + * 1. Infrastructure Client (Non-AP STA) + * 2. Ad-Hoc IBSS + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +int +mtk_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type, + struct vif_params *params) +#else +int +mtk_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, enum nl80211_iftype type, u32 *flags, struct vif_params *params) +#endif +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + ENUM_PARAM_OP_MODE_T eOpMode; + UINT_32 u4BufLen; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, + "chip resetting, mtk_cfg80211_change_iface do nothing\n"); + return -EINVAL; + } +#endif + + 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, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "set infrastructure mode error:0x%x\n", + rStatus); + + /* reset wpa info */ + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + prGlueInfo->rWpaInfo.u4KeyMgmt = 0; + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; +#if CFG_SUPPORT_802_11W + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; + prGlueInfo->rWpaInfo.ucRSNMfpCap = 0; + prGlueInfo->rWpaInfo.u4CipherGroupMgmt = IW_AUTH_CIPHER_NONE; +#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], tmp2[8]; +#if CFG_SUPPORT_REPLAY_DETECTION + P_BSS_INFO_T prBssInfo = NULL; + struct SEC_DETECT_REPLAY_INFO *prDetRplyInfo = NULL; + UINT_8 ucCheckZeroKey = 0; + UINT_8 i = 0; +#endif + + const UINT_8 aucBCAddr[] = BC_MAC_ADDR; + /* const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; */ + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(RSN, ERROR, + "chip resetting, mtk_cfg80211_add_key do nothing\n"); + return -EINVAL; + } +#endif + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if DBG + DBGLOG(RSN, INFO, "mtk_cfg80211_add_key\n"); + if (mac_addr) { + DBGLOG(RSN, INFO, + "keyIdx = %d pairwise = %d mac = " MACSTR "\n", key_index, pairwise, MAC2STR(mac_addr)); + } else { + DBGLOG(RSN, INFO, "keyIdx = %d pairwise = %d null mac\n", key_index, pairwise); + } + DBGLOG(RSN, INFO, "Cipher = %x\n", params->cipher); + DBGLOG_MEM8(RSN, INFO, params->key, params->key_len); +#endif + + kalMemZero(&rKey, sizeof(PARAM_KEY_T)); + + rKey.u4KeyIndex = key_index; + + if (params->cipher) { + switch (params->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + rKey.ucCipher = CIPHER_SUITE_WEP40; + break; + case WLAN_CIPHER_SUITE_WEP104: + rKey.ucCipher = CIPHER_SUITE_WEP104; + break; +#if 0 + case WLAN_CIPHER_SUITE_WEP128: + rKey.ucCipher = CIPHER_SUITE_WEP128; + break; +#endif + case WLAN_CIPHER_SUITE_TKIP: + rKey.ucCipher = CIPHER_SUITE_TKIP; + break; + case WLAN_CIPHER_SUITE_CCMP: + rKey.ucCipher = CIPHER_SUITE_CCMP; + break; +#if 0 + case WLAN_CIPHER_SUITE_GCMP: + rKey.ucCipher = CIPHER_SUITE_GCMP; + break; + case WLAN_CIPHER_SUITE_CCMP_256: + rKey.ucCipher = CIPHER_SUITE_CCMP256; + break; +#endif + case WLAN_CIPHER_SUITE_SMS4: + rKey.ucCipher = CIPHER_SUITE_WPI; + break; + case WLAN_CIPHER_SUITE_AES_CMAC: + rKey.ucCipher = CIPHER_SUITE_BIP; + break; + default: + ASSERT(FALSE); + } + } + + if (pairwise) { + ASSERT(mac_addr); + rKey.u4KeyIndex |= BIT(31); + rKey.u4KeyIndex |= BIT(30); + COPY_MAC_ADDR(rKey.arBSSID, mac_addr); + + /* reset KCK, KEK, EAPOL Replay counter */ + kalMemZero(prGlueInfo->rWpaInfo.aucKek, NL80211_KEK_LEN); + kalMemZero(prGlueInfo->rWpaInfo.aucKck, NL80211_KCK_LEN); + kalMemZero(prGlueInfo->rWpaInfo.aucReplayCtr, NL80211_REPLAY_CTR_LEN); + + } else { /* Group key */ + COPY_MAC_ADDR(rKey.arBSSID, aucBCAddr); + } + + if (params->key) { + +#if CFG_SUPPORT_REPLAY_DETECTION + for (i = 0; i < params->key_len; i++) { + if (params->key[i] == 0x00) + ucCheckZeroKey++; + } + + if (ucCheckZeroKey == params->key_len) + return 0; +#endif + if (params->key_len > sizeof(rKey.aucKeyMaterial)) + return -EINVAL; + + kalMemCopy(rKey.aucKeyMaterial, params->key, params->key_len); + if (rKey.ucCipher == CIPHER_SUITE_TKIP) { + kalMemCopy(tmp1, ¶ms->key[16], 8); + kalMemCopy(tmp2, ¶ms->key[24], 8); + kalMemCopy(&rKey.aucKeyMaterial[16], tmp2, 8); + kalMemCopy(&rKey.aucKeyMaterial[24], tmp1, 8); + } + } + + rKey.ucBssIdx = prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + + rKey.u4KeyLength = params->key_len; + rKey.u4Length = ((ULONG)&(((P_PARAM_KEY_T) 0)->aucKeyMaterial)) + rKey.u4KeyLength; + +#if CFG_SUPPORT_REPLAY_DETECTION + prBssInfo = GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex); + + prDetRplyInfo = &prBssInfo->rDetRplyInfo; + + if ((!pairwise) && ((params->cipher == WLAN_CIPHER_SUITE_TKIP) || (params->cipher == WLAN_CIPHER_SUITE_CCMP))) { + if ((prDetRplyInfo->ucCurKeyId == key_index) && + (!kalMemCmp(prDetRplyInfo->aucKeyMaterial, params->key, params->key_len))) { + DBGLOG(RSN, TRACE, "M3/G1, KeyID and KeyValue equal.\n"); + DBGLOG(RSN, TRACE, "hit group key reinstall case, so no update BC/MC PN.\n"); + } else { + kalMemCopy(prDetRplyInfo->arReplayPNInfo[key_index].auPN, params->seq, params->seq_len); + prDetRplyInfo->ucCurKeyId = key_index; + prDetRplyInfo->u4KeyLength = params->key_len; + kalMemCopy(prDetRplyInfo->aucKeyMaterial, params->key, params->key_len); + } + + prDetRplyInfo->fgKeyRscFresh = TRUE; + } +#endif + + rStatus = kalIoctl(prGlueInfo, wlanoidSetAddKey, &rKey, rKey.u4Length, FALSE, FALSE, TRUE, &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; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(REQ, ERROR, "mtk_cfg80211_get_key\n"); +#endif + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if 1 + DBGLOG(INIT, INFO, "--> %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); + +#if CFG_CHIP_RESET_SUPPORT + if (g_u4HaltFlag) { + DBGLOG(INIT, WARN, "wlan is halt, skip key deletion\n"); + return WLAN_STATUS_FAILURE; + } + rst_data.entry_conut++; + DBGLOG(INIT, TRACE, "entry_conut = %d\n", rst_data.entry_conut); +#endif + +#if DBG + DBGLOG(RSN, TRACE, "mtk_cfg80211_del_key\n"); + if (mac_addr) { + DBGLOG(RSN, TRACE, + "keyIdx = %d pairwise = %d mac = " MACSTR "\n", key_index, pairwise, MAC2STR(mac_addr)); + } else { + DBGLOG(RSN, TRACE, "keyIdx = %d pairwise = %d null mac\n", key_index, pairwise); + } +#endif + + kalMemZero(&rRemoveKey, sizeof(PARAM_REMOVE_KEY_T)); + rRemoveKey.u4KeyIndex = key_index; + rRemoveKey.u4Length = sizeof(PARAM_REMOVE_KEY_T); + if (mac_addr) { + COPY_MAC_ADDR(rRemoveKey.arBSSID, mac_addr); + rRemoveKey.u4KeyIndex |= BIT(30); + } + if ((prGlueInfo->prAdapter == NULL) || (prGlueInfo->prAdapter + ->prAisBssInfo == NULL)) + return i4Rslt; + + rRemoveKey.ucBssIdx = prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRemoveKey, &rRemoveKey, rRemoveKey.u4Length, FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(RSN, WARN, "remove key error:0x%x\n", rStatus); + else + i4Rslt = 0; + +#if CFG_CHIP_RESET_SUPPORT + rst_data.entry_conut--; + DBGLOG(INIT, TRACE, "entry_conut = %d\n", rst_data.entry_conut); +#endif + 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; + PARAM_DEFAULT_KEY_T rDefaultKey; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + INT_32 i4Rst = -EINVAL; + UINT_32 u4BufLen = 0; + BOOLEAN fgDef = FALSE, fgMgtDef = FALSE; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, "mtk_cfg80211_set_default_key\n"); + return -EINVAL; + } +#endif + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + /* For STA, should wep set the default key !! */ +#if DBG + DBGLOG(RSN, INFO, "mtk_cfg80211_set_default_key\n"); + DBGLOG(RSN, INFO, "keyIdx = %d unicast = %d multicast = %d\n", key_index, unicast, multicast); +#endif + + rDefaultKey.ucKeyID = key_index; + rDefaultKey.ucUnicast = unicast; + rDefaultKey.ucMulticast = multicast; + if (rDefaultKey.ucUnicast && !rDefaultKey.ucMulticast) + return WLAN_STATUS_SUCCESS; + + if (rDefaultKey.ucUnicast && rDefaultKey.ucMulticast) + fgDef = TRUE; + + if (!rDefaultKey.ucUnicast && rDefaultKey.ucMulticast) + fgMgtDef = TRUE; + + rDefaultKey.ucBssIdx = prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetDefaultKey, + &rDefaultKey, sizeof(PARAM_DEFAULT_KEY_T), FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus == WLAN_STATUS_SUCCESS) + i4Rst = 0; + + return i4Rst; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for getting station information such as RSSI + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, const 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; + PARAM_GET_STA_STA_STATISTICS rQueryStaStatistics; + UINT_32 u4TotalError; + struct net_device_stats *prDevStats; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(INIT, WARN, "wlan is halt, skip get station\n"); + return WLAN_STATUS_FAILURE; + } + rst_data.entry_conut++; + DBGLOG(INIT, TRACE, " entry_conut = %d\n", rst_data.entry_conut); +#endif + + kalMemZero(arBssid, MAC_ADDR_LEN); + wlanQueryInformation(prGlueInfo->prAdapter, wlanoidQueryBssid, &arBssid[0], sizeof(arBssid), &u4BufLen); + + /* 1. check input MAC address */ + /* On Android O, this might be wlan0 address */ + if (UNEQUAL_MAC_ADDR(arBssid, mac) && UNEQUAL_MAC_ADDR(prGlueInfo->prAdapter->rWifiVar.aucMacAddress, mac)) { + /* wrong MAC address */ + DBGLOG(REQ, WARN, + "incorrect BSSID: [" MACSTR "] currently connected BSSID[" MACSTR "]\n", + MAC2STR(mac), MAC2STR(arBssid)); +#if CFG_CHIP_RESET_SUPPORT + rst_data.entry_conut--; + DBGLOG(INIT, TRACE, " entry_conut = %d\n", + rst_data.entry_conut); +#endif + return -ENOENT; + } + + /* 2. fill TX rate */ + if (prGlueInfo->eParamMediaStateIndicated != PARAM_MEDIA_STATE_CONNECTED) { + /* not connected */ + DBGLOG(REQ, WARN, "not yet connected\n"); + } else { + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryLinkSpeed, &u4Rate, sizeof(u4Rate), TRUE, FALSE, FALSE, &u4BufLen); + +#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE + sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); +#else + sinfo->filled |= STATION_INFO_TX_BITRATE; +#endif + if ((rStatus != WLAN_STATUS_SUCCESS) || (u4Rate == 0)) { + /* + * DBGLOG(REQ, WARN, "unable to retrieve link speed\n")); + */ + DBGLOG(REQ, WARN, "last link speed\n"); + sinfo->txrate.legacy = prGlueInfo->u4LinkSpeedCache; + } else { + /* + * sinfo->filled |= STATION_INFO_TX_BITRATE; + */ + sinfo->txrate.legacy = u4Rate / 1000; /* convert from 100bps to 100kbps */ + prGlueInfo->u4LinkSpeedCache = u4Rate / 1000; + } + } + + /* 3. fill RSSI */ + if (prGlueInfo->eParamMediaStateIndicated != PARAM_MEDIA_STATE_CONNECTED) { + /* not connected */ + DBGLOG(REQ, WARN, "not yet connected\n"); + } else { + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryRssi, &i4Rssi, sizeof(i4Rssi), TRUE, FALSE, FALSE, &u4BufLen); + +#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE + sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); +#else + sinfo->filled |= STATION_INFO_SIGNAL; +#endif + + if ((rStatus != WLAN_STATUS_SUCCESS) || (i4Rssi == PARAM_WHQL_RSSI_MIN_DBM) + || (i4Rssi == PARAM_WHQL_RSSI_MAX_DBM)) { + DBGLOG(REQ, WARN, "last rssi\n"); + sinfo->signal = prGlueInfo->i4RssiCache; + } else { + sinfo->signal = i4Rssi; /* dBm */ + prGlueInfo->i4RssiCache = i4Rssi; + } + } + + /* Get statistics from net_dev */ + prDevStats = (struct net_device_stats *)kalGetStats(ndev); + + if (prDevStats) { + /* 4. fill RX_PACKETS */ +#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE + sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS); +#else + sinfo->filled |= STATION_INFO_RX_PACKETS; +#endif + sinfo->rx_packets = prDevStats->rx_packets; + + /* 5. fill TX_PACKETS */ +#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE + sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS); +#else + sinfo->filled |= STATION_INFO_TX_PACKETS; +#endif + sinfo->tx_packets = prDevStats->tx_packets; + + /* 6. fill TX_FAILED */ + kalMemZero(&rQueryStaStatistics, sizeof(rQueryStaStatistics)); + COPY_MAC_ADDR(rQueryStaStatistics.aucMacAddr, arBssid); + rQueryStaStatistics.ucReadClear = TRUE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStaStatistics, + &rQueryStaStatistics, sizeof(rQueryStaStatistics), TRUE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "unable to retrieve link speed,status code = %d\n", rStatus); + } else { + DBGLOG(REQ, INFO, "BSSID: [" MACSTR "] TxFailCount %d LifeTimeOut %d\n", + MAC2STR(arBssid), rQueryStaStatistics.u4TxFailCount, + rQueryStaStatistics.u4TxLifeTimeoutCount); + + u4TotalError = rQueryStaStatistics.u4TxFailCount + rQueryStaStatistics.u4TxLifeTimeoutCount; + prDevStats->tx_errors += u4TotalError; + } +#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE + sinfo->filled |= BIT(NL80211_STA_INFO_TX_FAILED); +#else + sinfo->filled |= STATION_INFO_TX_FAILED; +#endif + sinfo->tx_failed = prDevStats->tx_errors; + } +#if CFG_CHIP_RESET_SUPPORT + rst_data.entry_conut--; + DBGLOG(INIT, TRACE, " entry_conut = %d\n", rst_data.entry_conut); +#endif + return 0; +} +#else +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; + PARAM_GET_STA_STA_STATISTICS rQueryStaStatistics; + UINT_32 u4TotalError; + struct net_device_stats *prDevStats; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(INIT, WARN, "wlan is halt, skip get station\n"); + return WLAN_STATUS_FAILURE; + } + rst_data.entry_conut++; + DBGLOG(INIT, TRACE, " entry_conut = %d\n", rst_data.entry_conut); +#endif + + 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)); +#if CFG_CHIP_RESET_SUPPORT + rst_data.entry_conut--; + DBGLOG(INIT, TRACE, " entry_conut = %d\n", + rst_data.entry_conut); +#endif + return -ENOENT; + } + + /* 2. fill TX rate */ + if (prGlueInfo->eParamMediaStateIndicated != PARAM_MEDIA_STATE_CONNECTED) { + /* not connected */ + DBGLOG(REQ, WARN, "not yet connected\n"); + } else { + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryLinkSpeed, &u4Rate, sizeof(u4Rate), TRUE, FALSE, FALSE, &u4BufLen); + + sinfo->filled |= STATION_INFO_TX_BITRATE; + + if ((rStatus != WLAN_STATUS_SUCCESS) || (u4Rate == 0)) { + /* + * DBGLOG(REQ, WARN, "unable to retrieve link speed\n")); + */ + DBGLOG(REQ, WARN, "last link speed\n"); + sinfo->txrate.legacy = prGlueInfo->u4LinkSpeedCache; + } else { + /* + * sinfo->filled |= STATION_INFO_TX_BITRATE; + */ + sinfo->txrate.legacy = u4Rate / 1000; /* convert from 100bps to 100kbps */ + prGlueInfo->u4LinkSpeedCache = u4Rate / 1000; + } + } + + /* 3. fill RSSI */ + if (prGlueInfo->eParamMediaStateIndicated != PARAM_MEDIA_STATE_CONNECTED) { + /* not connected */ + DBGLOG(REQ, WARN, "not yet connected\n"); + } else { + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryRssi, &i4Rssi, sizeof(i4Rssi), TRUE, FALSE, FALSE, &u4BufLen); + + sinfo->filled |= STATION_INFO_SIGNAL; + + if ((rStatus != WLAN_STATUS_SUCCESS) || (i4Rssi == PARAM_WHQL_RSSI_MIN_DBM) + || (i4Rssi == PARAM_WHQL_RSSI_MAX_DBM)) { + DBGLOG(REQ, WARN, "last rssi\n"); + sinfo->signal = prGlueInfo->i4RssiCache; + } else { + sinfo->signal = i4Rssi; /* dBm */ + prGlueInfo->i4RssiCache = i4Rssi; + } + } + + /* Get statistics from net_dev */ + prDevStats = (struct net_device_stats *)kalGetStats(ndev); + + if (prDevStats) { + /* 4. fill RX_PACKETS */ + sinfo->filled |= STATION_INFO_RX_PACKETS; + sinfo->rx_packets = prDevStats->rx_packets; + + /* 5. fill TX_PACKETS */ + sinfo->filled |= STATION_INFO_TX_PACKETS; + sinfo->tx_packets = prDevStats->tx_packets; + + /* 6. fill TX_FAILED */ + kalMemZero(&rQueryStaStatistics, sizeof(rQueryStaStatistics)); + COPY_MAC_ADDR(rQueryStaStatistics.aucMacAddr, arBssid); + rQueryStaStatistics.ucReadClear = TRUE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStaStatistics, + &rQueryStaStatistics, sizeof(rQueryStaStatistics), TRUE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "unable to get sta statistics: status[0x%x]\n", rStatus); + } else { + DBGLOG(REQ, INFO, "BSSID: [" MACSTR "] TxFailCount %d LifeTimeOut %d\n", + MAC2STR(arBssid), rQueryStaStatistics.u4TxFailCount, + rQueryStaStatistics.u4TxLifeTimeoutCount); + + u4TotalError = rQueryStaStatistics.u4TxFailCount + rQueryStaStatistics.u4TxLifeTimeoutCount; + prDevStats->tx_errors += u4TotalError; + } + sinfo->filled |= STATION_INFO_TX_FAILED; + sinfo->tx_failed = prDevStats->tx_errors; + } +#if CFG_CHIP_RESET_SUPPORT + rst_data.entry_conut--; + DBGLOG(INIT, TRACE, "entry_conut = %d\n", rst_data.entry_conut); +#endif + return 0; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for getting statistics for Link layer statistics + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*------------------------------------------------------------------------*/ +int mtk_cfg80211_get_link_statistics(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; + INT_32 i4Rssi; + PARAM_GET_STA_STA_STATISTICS rQueryStaStatistics; + PARAM_GET_BSS_STATISTICS rQueryBssStatistics; + struct net_device_stats *prDevStats; + P_NETDEV_PRIVATE_GLUE_INFO prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) NULL; + UINT_8 ucBssIndex; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(REQ, ERROR, "mtk_cfg80211_get_link_statistics\n"); +#endif + + 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 RSSI */ + if (prGlueInfo->eParamMediaStateIndicated != PARAM_MEDIA_STATE_CONNECTED) { + /* not connected */ + DBGLOG(REQ, WARN, "not yet connected\n"); + } else { + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryRssi, &i4Rssi, sizeof(i4Rssi), TRUE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "unable to retrieve rssi\n"); + } + + /* Get statistics from net_dev */ + prDevStats = (struct net_device_stats *)kalGetStats(ndev); + + /*3. get link layer statistics from Driver and FW */ + if (prDevStats) { + /* 3.1 get per-STA link statistics */ + kalMemZero(&rQueryStaStatistics, sizeof(rQueryStaStatistics)); + COPY_MAC_ADDR(rQueryStaStatistics.aucMacAddr, arBssid); + rQueryStaStatistics.ucLlsReadClear = FALSE; /* dont clear for get BSS statistic */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStaStatistics, + &rQueryStaStatistics, sizeof(rQueryStaStatistics), TRUE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "unable to retrieve per-STA link statistics\n"); + + /*3.2 get per-BSS link statistics */ + if (rStatus == WLAN_STATUS_SUCCESS) { + /* get Bss Index from ndev */ + prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(ndev); + ASSERT(prNetDevPrivate->prGlueInfo == prGlueInfo); + ucBssIndex = prNetDevPrivate->ucBssIdx; + + kalMemZero(&rQueryBssStatistics, sizeof(rQueryBssStatistics)); + rQueryBssStatistics.ucBssIndex = ucBssIndex; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryBssStatistics, + &rQueryBssStatistics, + sizeof(rQueryBssStatistics), TRUE, FALSE, TRUE, &u4BufLen); + } else { + DBGLOG(REQ, WARN, "unable to retrieve per-BSS link statistics\n"); + } + + } + + 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 cfg80211_scan_request *request) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 i, u4BufLen; + PARAM_SCAN_REQUEST_ADV_T rScanRequest; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + kalMemZero(&rScanRequest, sizeof(rScanRequest)); + + if (!wlanGetHifState(prGlueInfo)) + return -EINVAL; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(INIT, WARN, "wlan is halt, skip scan"); + return WLAN_STATUS_FAILURE; + } + rst_data.entry_conut++; + DBGLOG(INIT, TRACE, "entry_conut = %d\n", rst_data.entry_conut); +#endif + + /* check if there is any pending scan/sched_scan not yet finished */ + if (prGlueInfo->prScanRequest != NULL) { +#if CFG_CHIP_RESET_SUPPORT + rst_data.entry_conut--; + DBGLOG(INIT, TRACE, "entry_conut = %d\n", rst_data.entry_conut); +#endif + return -EBUSY; + } + + if (prGlueInfo->u4ReadyFlag == 0) { + DBGLOG(REQ, WARN, "prGlueInfo->u4ReadyFlag == 0\n"); +#if CFG_CHIP_RESET_SUPPORT + rst_data.entry_conut--; + DBGLOG(INIT, TRACE, "entry_conut = %d\n", rst_data.entry_conut); +#endif + } + + if (atomic_read(&prGlueInfo->cfgSuspend)) { + DBGLOG(REQ, WARN, "In suspend block cfg80211 ops\n"); + return -EFAULT; + } + + if (request->n_ssids == 0) { + rScanRequest.u4SsidNum = 0; + } else if (request->n_ssids <= SCN_SSID_MAX_NUM) { + rScanRequest.u4SsidNum = request->n_ssids; + + for (i = 0; i < request->n_ssids; i++) { + COPY_SSID(rScanRequest.rSsid[i].aucSsid, + rScanRequest.rSsid[i].u4SsidLen, request->ssids[i].ssid, request->ssids[i].ssid_len); + } + } else { +#if CFG_CHIP_RESET_SUPPORT + rst_data.entry_conut--; + DBGLOG(INIT, TRACE, "entry_conut = %d\n", rst_data.entry_conut); +#endif + return -EINVAL; + } + + rScanRequest.u4IELength = request->ie_len; + if (request->ie_len > 0) + rScanRequest.pucIE = (PUINT_8) (request->ie); + +#if CFG_SCAN_CHANNEL_SPECIFIED + DBGLOG(REQ, INFO, "scan channel num = %d\n", request->n_channels); + + if (request->n_channels > MAXIMUM_OPERATION_CHANNEL_LIST) { + DBGLOG(REQ, WARN, "scan channel num (%d) exceeds %d, do a full scan instead\n", + request->n_channels, MAXIMUM_OPERATION_CHANNEL_LIST); + rScanRequest.ucChannelListNum = 0; + } else { + rScanRequest.ucChannelListNum = request->n_channels; + for (i = 0; i < request->n_channels; i++) { + rScanRequest.arChnlInfoList[i].eBand = + kalCfg80211ToMtkBand(request->channels[i]->band); + rScanRequest.arChnlInfoList[i].u4CenterFreq1 = request->channels[i]->center_freq; + rScanRequest.arChnlInfoList[i].u4CenterFreq2 = 0; + rScanRequest.arChnlInfoList[i].u2PriChnlFreq = request->channels[i]->center_freq; +#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE + rScanRequest.arChnlInfoList[i].ucChnlBw = request->scan_width; +#else + rScanRequest.arChnlInfoList[i].ucChnlBw = 0; +#endif + rScanRequest.arChnlInfoList[i].ucChannelNum = + ieee80211_frequency_to_channel(request->channels[i]->center_freq); + } + } +#endif + /* 2018/04/18 frog: The point should be ready before doing IOCTL. */ + prGlueInfo->prScanRequest = request; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetBssidListScanAdv, + &rScanRequest, sizeof(PARAM_SCAN_REQUEST_ADV_T), FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "scan error:0x%x\n", rStatus); + /* 2018/04/18 frog: Remove pointer if IOCTL fail. */ + prGlueInfo->prScanRequest = NULL; + return -EINVAL; + } + +#if CFG_CHIP_RESET_SUPPORT + rst_data.entry_conut--; + DBGLOG(INIT, TRACE, "entry_conut = %d\n", rst_data.entry_conut); +#endif + + return 0; +} + +static UINT_8 wepBuf[48]; +#if CFG_SUPPORT_CFG80211_AUTH +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting auth to + * the ESS with the specified parameters + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_auth(struct wiphy *wiphy, struct net_device *ndev, + struct cfg80211_auth_request *req) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 rStatus; + UINT_32 u4BufLen; + PARAM_CONNECT_T rNewSsid; + ENUM_PARAM_OP_MODE_T eOpMode; + P_CONNECTION_SETTINGS_T prConnSettings = NULL; +#if CFG_SUPPORT_REPLAY_DETECTION + struct SEC_DETECT_REPLAY_INFO *prDetRplyInfo = NULL; +#endif + P_PARAM_WEP_T prWepKey; + /*Is auth parameter needed to be updated to AIS.*/ + UINT_8 fgNewAuthParam = FALSE; + P_STA_RECORD_T prStaRec = NULL; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, + "chip resetting, mtk_cfg80211_auth do nothing\n"); + return -EINVAL; + } +#endif + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); +#if KERNEL_VERSION(4, 10, 0) > CFG80211_VERSION_CODE + if (req->sae_data_len != 0) + DBGLOG(REQ, INFO, "[wlan] mtk_cfg80211_auth %p %zu\n", + req->sae_data, req->sae_data_len); +#else + if (req->auth_data_len != 0) + DBGLOG(REQ, INFO, "[wlan] mtk_cfg80211_auth %p %zu\n", + req->auth_data, req->auth_data_len); +#endif + DBGLOG(REQ, INFO, "auth to BSS [" MACSTR "]\n", + MAC2STR((PUINT_8)req->bss->bssid)); + DBGLOG(REQ, INFO, "auth_type:%d\n", req->auth_type); + + prConnSettings = &prGlueInfo->prAdapter->rWifiVar.rConnSettings; + + /* <1>Set OP mode */ + 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, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "wlanoidSetInfrastructureMode fail 0x%x\n", + rStatus); + return -EFAULT; + } + + /*<2> Set Auth data */ + prConnSettings->ucAuthDataLen = 0; +#if KERNEL_VERSION(4, 10, 0) > CFG80211_VERSION_CODE + if (req->sae_data_len != 0) { + if (req->sae_data_len > AUTH_DATA_MAX_LEN) { + DBGLOG(INIT, WARN, + "request auth with unexpected length:%d\n", + req->sae_data_len); + return -EFAULT; + } + + kalMemCopy(prConnSettings->aucAuthData, req->sae_data, + req->sae_data_len); + prConnSettings->ucAuthDataLen = req->sae_data_len; + + DBGLOG(INIT, INFO, + "Dump auth data in connectSettings, auth len:%d\n", + prConnSettings->ucAuthDataLen); + DBGLOG_MEM8(REQ, INFO, prConnSettings->aucAuthData, + req->sae_data_len); + } +#else + if (req->auth_data_len != 0) { + if (req->auth_data_len > AUTH_DATA_MAX_LEN) { + DBGLOG(INIT, WARN, + "request auth with unexpected length:%d\n", + req->auth_data_len); + return -EFAULT; + } + + kalMemCopy(prConnSettings->aucAuthData, req->auth_data, + req->auth_data_len); + prConnSettings->ucAuthDataLen = req->auth_data_len; + + DBGLOG(INIT, INFO, + "Dump auth data in connectSettings, auth len:%d\n", + prConnSettings->ucAuthDataLen); + DBGLOG_MEM8(REQ, INFO, prConnSettings->aucAuthData, + req->auth_data_len); + } +#endif + /*<2> Set ChannelNum */ + if (req->bss->channel->center_freq) { + prConnSettings->ucChannelNum = + nicFreq2ChannelNum( + req->bss->channel->center_freq * 1000); + DBGLOG(RSN, INFO, + "set prConnSettings->ucChannelNum:%d\n", + prConnSettings->ucChannelNum); + } else { + prConnSettings->ucChannelNum = 0; + DBGLOG(RSN, INFO, + "req->bss->channel->center_freq is NULL.\n"); + } + + +#if CFG_SUPPORT_REPLAY_DETECTION + /* reset Detect replay information */ + prDetRplyInfo = &prGlueInfo->prDetRplyInfo; + kalMemZero(prDetRplyInfo, sizeof(struct SEC_DETECT_REPLAY_INFO)); +#endif + + /* Reset WPA info */ + prGlueInfo->rWpaInfo.u4AuthAlg = 0; + + switch (req->auth_type) { + case NL80211_AUTHTYPE_OPEN_SYSTEM: + if (!(prGlueInfo->rWpaInfo.u4AuthAlg & AUTH_TYPE_OPEN_SYSTEM)) + fgNewAuthParam = TRUE; + prGlueInfo->rWpaInfo.u4AuthAlg |= AUTH_TYPE_OPEN_SYSTEM; + break; + case NL80211_AUTHTYPE_SHARED_KEY: + if (!(prGlueInfo->rWpaInfo.u4AuthAlg & AUTH_TYPE_SHARED_KEY)) + fgNewAuthParam = TRUE; + prGlueInfo->rWpaInfo.u4AuthAlg |= AUTH_TYPE_SHARED_KEY; + break; + case NL80211_AUTHTYPE_SAE: + if (!(prGlueInfo->rWpaInfo.u4AuthAlg & AUTH_TYPE_SAE)) + fgNewAuthParam = TRUE; + prGlueInfo->rWpaInfo.u4AuthAlg |= AUTH_TYPE_SAE; + break; + default: + DBGLOG(REQ, WARN, + "Auth type: %ld not support, use default OPEN system\n", + req->auth_type); + prGlueInfo->rWpaInfo.u4AuthAlg |= AUTH_TYPE_OPEN_SYSTEM; + break; + } + DBGLOG(REQ, INFO, "Auth Algorithm : %ld\n", + prGlueInfo->rWpaInfo.u4AuthAlg); + + if (req->key_len != 0) { + /* NL80211 only set the Tx wep key while connect, + * the max 4 wep key set prior via add key cmd + */ + + if (!(prGlueInfo->rWpaInfo.u4AuthAlg & AUTH_TYPE_SHARED_KEY)) + DBGLOG(REQ, WARN, "Auth Algorithm : %ld with wep key\n", + prGlueInfo->rWpaInfo.u4AuthAlg); + + prWepKey = (P_PARAM_WEP_T) wepBuf; + + kalMemZero(prWepKey, sizeof(PARAM_WEP_T)); + prWepKey->u4Length = OFFSET_OF(PARAM_WEP_T, aucKeyMaterial) + + req->key_len; + prWepKey->u4KeyLength = (UINT_32) req->key_len; + prWepKey->u4KeyIndex = (UINT_32) req->key_idx; + prWepKey->u4KeyIndex |= IS_TRANSMIT_KEY; + if (prWepKey->u4KeyLength > MAX_KEY_LEN) { + DBGLOG(REQ, WARN, "Too long key length (%u)\n", + prWepKey->u4KeyLength); + return -EINVAL; + } + kalMemCopy(prWepKey->aucKeyMaterial, req->key, + prWepKey->u4KeyLength); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetAddWep, prWepKey, + prWepKey->u4Length, FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "wlanoidSetAddWep fail 0x%x\n", + rStatus); + return -EFAULT; + } + } + kalMemZero(&rNewSsid, sizeof(PARAM_CONNECT_T)); + + if (rNewSsid.pucBssid != (PUINT_8)req->bss->bssid) { + fgNewAuthParam = TRUE; + rNewSsid.pucBssid = (PUINT_8)req->bss->bssid; + } + /* rNewSsid.pucSsid = (uint8_t *)sme->ssid;*/ + /* rNewSsid.u4SsidLen = sme->ssid_len;*/ + + DBGLOG(REQ, INFO, "auth to BSS [" MACSTR "],UpperReq [" MACSTR "]\n", + MAC2STR(rNewSsid.pucBssid), + MAC2STR((uint8_t *)req->bss->bssid)); + + prConnSettings->fgIsSendAssoc = FALSE; + if (!prConnSettings->fgIsConnInitialized /*|| fgNewAuthParam*/) { + /* [TODO] to consider if bssid/auth_alg changed + * (need to update to AIS) + */ + if (fgNewAuthParam) + DBGLOG(REQ, WARN, "auth param update\n"); + rStatus = kalIoctl(prGlueInfo, wlanoidSetConnect, + (void *)&rNewSsid, sizeof(PARAM_CONNECT_T), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set SSID:%x\n", rStatus); + return -EINVAL; + } + } else { + /* skip join initial flow + * when it has been completed with the same auth parameters + */ + prStaRec = cnmGetStaRecByAddress(prGlueInfo->prAdapter, + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex, + rNewSsid.pucBssid); + if (prStaRec) + saaSendAuthAssoc(prGlueInfo->prAdapter, prStaRec); + else + DBGLOG(REQ, WARN, + "can't send auth since can't find StaRec\n"); + } + + return 0; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to connect to + * the ESS with the specified parameters + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_connect_params *sme) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus; + ENUM_PARAM_AUTH_MODE_T eAuthMode; + UINT_32 cipher; + PARAM_CONNECT_T rNewSsid; + BOOLEAN fgCarryWPSIE = FALSE; + ENUM_PARAM_OP_MODE_T eOpMode; + UINT_32 i, u4AkmSuite = 0; + P_DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY prEntry; +#if CFG_SUPPORT_REPLAY_DETECTION + P_BSS_INFO_T prBssInfo = NULL; + struct SEC_DETECT_REPLAY_INFO *prDetRplyInfo = NULL; +#endif + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, WARN, "wlan is halt, skip conn."); + return WLAN_STATUS_FAILURE; + } + rst_data.entry_conut++; + DBGLOG(INIT, TRACE, "entry_conut = %d\n", rst_data.entry_conut); +#endif + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + if (prGlueInfo->u4ReadyFlag == 0) { + DBGLOG(INIT, ERROR, "Adapter is not ready\n"); + return -EINVAL; + } + + if (ndev == NULL) { + DBGLOG(REQ, ERROR, "ndev is NULL\n"); +#if CFG_CHIP_RESET_SUPPORT + rst_data.entry_conut--; + DBGLOG(INIT, TRACE, "entry_conut = %d\n", rst_data.entry_conut); +#endif + return -EINVAL; + } + + if (atomic_read(&prGlueInfo->cfgSuspend)) { + DBGLOG(REQ, WARN, "In suspend block cfg80211 ops\n"); + return -EFAULT; + } + + /* printk("[wlan]mtk_cfg80211_connect\n"); */ + 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, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, + "wlanoidSetInfrastructureMode fail 0x%x\n", rStatus); + return -EFAULT; + } + + /* after set operation mode, key table are cleared */ + + /* reset wpa info */ + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + prGlueInfo->rWpaInfo.u4KeyMgmt = 0; + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; + prGlueInfo->rWpaInfo.fgPrivacyInvoke = FALSE; + +#if CFG_SUPPORT_REPLAY_DETECTION + /* reset Detect replay information */ + prBssInfo = GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex); + + prDetRplyInfo = &prBssInfo->rDetRplyInfo; + kalMemZero(prDetRplyInfo, sizeof(struct SEC_DETECT_REPLAY_INFO)); +#endif + + +#if CFG_SUPPORT_802_11W + prGlueInfo->rWpaInfo.u4CipherGroupMgmt = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.ucRSNMfpCap = RSN_AUTH_MFP_DISABLED; + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; + switch (sme->mfp) { + case NL80211_MFP_NO: + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; + break; + case NL80211_MFP_REQUIRED: + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_REQUIRED; + break; + default: + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; + break; + } + /* DBGLOG(SCN, INFO, ("MFP=%d\n", prGlueInfo->rWpaInfo.u4Mfp)); */ +#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) { + DBGLOG(RSN, INFO, "[wlan] cipher pairwise (%x)\n", sme->crypto.ciphers_pairwise[0]); + + 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; +#if CFG_SUPPORT_SUITB + case WLAN_CIPHER_SUITE_BIP_GMAC_256: + prGlueInfo->rWpaInfo.u4CipherPairwise = + IW_AUTH_CIPHER_GCMP256; + break; + case WLAN_CIPHER_SUITE_GCMP_256: + prGlueInfo->rWpaInfo.u4CipherPairwise = + IW_AUTH_CIPHER_GCMP256; + break; +#endif + default: + DBGLOG(REQ, WARN, "invalid cipher pairwise (%d)\n", sme->crypto.ciphers_pairwise[0]); +#if CFG_CHIP_RESET_SUPPORT + rst_data.entry_conut--; + DBGLOG(INIT, TRACE, "entry_conut = %d\n", + rst_data.entry_conut); +#endif + 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; +#if CFG_SUPPORT_SUITB + case WLAN_CIPHER_SUITE_BIP_GMAC_256: + prGlueInfo->rWpaInfo.u4CipherGroup = + IW_AUTH_CIPHER_GCMP256; + break; + case WLAN_CIPHER_SUITE_GCMP_256: + prGlueInfo->rWpaInfo.u4CipherGroup = + IW_AUTH_CIPHER_GCMP256; + break; + case WLAN_CIPHER_SUITE_NO_GROUP_ADDR: + break; +#endif + default: + DBGLOG(REQ, WARN, "invalid cipher group (%d)\n", sme->crypto.cipher_group); +#if CFG_CHIP_RESET_SUPPORT + rst_data.entry_conut--; + DBGLOG(INIT, TRACE, "entry_conut = %d\n", + rst_data.entry_conut); +#endif + return -EINVAL; + } + } + + /* DBGLOG(SCN, INFO, ("akm_suites=%x\n", sme->crypto.akm_suites[0])); */ + 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; + u4AkmSuite = WPA_AKM_SUITE_802_1X; + break; + case WLAN_AKM_SUITE_PSK: + eAuthMode = AUTH_MODE_WPA_PSK; + u4AkmSuite = WPA_AKM_SUITE_PSK; + break; + default: + DBGLOG(REQ, WARN, "invalid Akm Suite (%d)\n", sme->crypto.akm_suites[0]); +#if CFG_CHIP_RESET_SUPPORT + rst_data.entry_conut--; + DBGLOG(INIT, TRACE, "entry_conut = %d\n", + rst_data.entry_conut); +#endif + 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; + u4AkmSuite = RSN_AKM_SUITE_802_1X; + break; + case WLAN_AKM_SUITE_PSK: + eAuthMode = AUTH_MODE_WPA2_PSK; + u4AkmSuite = RSN_AKM_SUITE_PSK; + break; +#if CFG_SUPPORT_802_11W + /* Notice:: Need kernel patch!! */ + case WLAN_AKM_SUITE_8021X_SHA256: + eAuthMode = AUTH_MODE_WPA2; + u4AkmSuite = RSN_AKM_SUITE_802_1X_SHA256; + break; + case WLAN_AKM_SUITE_PSK_SHA256: + eAuthMode = AUTH_MODE_WPA2_PSK; + u4AkmSuite = RSN_AKM_SUITE_PSK_SHA256; + break; +#endif +#if CFG_SUPPORT_SUITB + case WLAN_AKM_SUITE_8021X_SUITE_B: + eAuthMode = AUTH_MODE_WPA2_PSK; + u4AkmSuite = RSN_AKM_SUITE_8021X_SUITE_B_192; + break; + + case WLAN_AKM_SUITE_8021X_SUITE_B_192: + eAuthMode = AUTH_MODE_WPA2_PSK; + u4AkmSuite = RSN_AKM_SUITE_8021X_SUITE_B_192; + break; +#endif +#if CFG_SUPPORT_OWE + case WLAN_AKM_SUITE_OWE: + eAuthMode = AUTH_MODE_WPA2_PSK; + u4AkmSuite = RSN_AKM_SUITE_OWE; + break; +#endif + default: + DBGLOG(REQ, WARN, "invalid Akm Suite (%d)\n", sme->crypto.akm_suites[0]); +#if CFG_CHIP_RESET_SUPPORT + rst_data.entry_conut--; + DBGLOG(INIT, TRACE, "entry_conut = %d\n", + rst_data.entry_conut); +#endif + return -EINVAL; + } + } + } + + if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_DISABLED) { + eAuthMode = (prGlueInfo->rWpaInfo.u4AuthAlg == IW_AUTH_ALG_OPEN_SYSTEM) ? + AUTH_MODE_OPEN : AUTH_MODE_AUTO_SWITCH; + } + + prGlueInfo->rWpaInfo.fgPrivacyInvoke = sme->privacy; + prGlueInfo->fgWpsActive = FALSE; + +#if CFG_SUPPORT_PASSPOINT + prGlueInfo->fgConnectHS20AP = FALSE; +#endif /* CFG_SUPPORT_PASSPOINT */ + + prGlueInfo->non_wfa_vendor_ie_len = 0; + if (sme->ie && sme->ie_len > 0) { + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + PUINT_8 prDesiredIE = NULL; + PUINT_8 pucIEStart = (PUINT_8)sme->ie; +#if CFG_SUPPORT_WAPI + rStatus = kalIoctl(prGlueInfo, + wlanoidSetWapiAssocInfo, pucIEStart, sme->ie_len, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(SEC, WARN, + "[wapi] set wapi assoc info error:0x%x\n", rStatus); +#endif +#if CFG_SUPPORT_WPS2 + if (wextSrchDesiredWPSIE(pucIEStart, sme->ie_len, 0xDD, (PUINT_8 *) &prDesiredIE)) { + prGlueInfo->fgWpsActive = TRUE; + fgCarryWPSIE = TRUE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetWSCAssocInfo, + prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(SEC, WARN, + "[WSC] set WSC assoc info error:0x%x\n", + rStatus); + } +#endif +#if CFG_SUPPORT_PASSPOINT + if (wextSrchDesiredHS20IE(pucIEStart, sme->ie_len, (PUINT_8 *) &prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetHS20Info, + prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, TRUE, &u4BufLen); +#if 0 + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "[HS20] set HS20 assoc info error:%lx\n", rStatus); +#endif + } + if (wextSrchDesiredInterworkingIE(pucIEStart, sme->ie_len, (PUINT_8 *) &prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetInterworkingInfo, + prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, TRUE, &u4BufLen); +#if 0 + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "[HS20] set Interworking assoc info error:%lx\n", rStatus); +#endif + } + if (wextSrchDesiredRoamingConsortiumIE(pucIEStart, sme->ie_len, (PUINT_8 *) &prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRoamingConsortiumIEInfo, + prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, TRUE, &u4BufLen); +#if 0 + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "[HS20] set RoamingConsortium assoc info error:%lx\n", rStatus); +#endif + } +#endif /* CFG_SUPPORT_PASSPOINT */ + if (wextSrchDesiredWPAIE(pucIEStart, sme->ie_len, 0x30, (PUINT_8 *) &prDesiredIE)) { + RSN_INFO_T rRsnInfo; + + if (rsnParseRsnIE(prGlueInfo->prAdapter, (P_RSN_INFO_ELEM_T)prDesiredIE, &rRsnInfo)) { +#if CFG_SUPPORT_802_11W + /* Fill RSNE MFP Cap */ + if (rRsnInfo.u2RsnCap & ELEM_WPA_CAP_MFPC) { + prGlueInfo->rWpaInfo.u4CipherGroupMgmt + = rRsnInfo + .u4GroupMgmtKeyCipherSuite; + prGlueInfo->rWpaInfo.ucRSNMfpCap = RSN_AUTH_MFP_OPTIONAL; + if (rRsnInfo.u2RsnCap & ELEM_WPA_CAP_MFPR) + prGlueInfo->rWpaInfo.ucRSNMfpCap = RSN_AUTH_MFP_REQUIRED; + } else + prGlueInfo->rWpaInfo.ucRSNMfpCap = + RSN_AUTH_MFP_DISABLED; +#endif + } + } + + /* Find non-wfa vendor specific ies set from upper layer */ + if (cfg80211_get_non_wfa_vendor_ie(prGlueInfo, pucIEStart, + sme->ie_len) > 0) { + DBGLOG(AIS, INFO, "Found non-wfa vendor ie (len=%u)\n", + prGlueInfo->non_wfa_vendor_ie_len); + } + } + + /* clear WSC Assoc IE buffer in case WPS IE is not detected */ + if (fgCarryWPSIE == FALSE) { + kalMemZero(&prGlueInfo->aucWSCAssocInfoIE, 200); + prGlueInfo->u2WSCAssocInfoIELen = 0; + } + + /*Fill WPA info - mfp setting */ + /* Must put after paring RSNE from upper layer + * for prGlueInfo->rWpaInfo.ucRSNMfpCap assignment + */ +#if CFG_SUPPORT_802_11W + switch (sme->mfp) { + case NL80211_MFP_NO: + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; + /* Change Mfp parameter from DISABLED to OPTIONAL + * if upper layer set MFPC = 1 in RSNE + * since upper layer can't bring MFP OPTIONAL information + * to driver by sme->mfp + */ + if (prGlueInfo->rWpaInfo.ucRSNMfpCap == + RSN_AUTH_MFP_OPTIONAL) + prGlueInfo->rWpaInfo.u4Mfp = + IW_AUTH_MFP_OPTIONAL; + else if (prGlueInfo->rWpaInfo.ucRSNMfpCap == + RSN_AUTH_MFP_REQUIRED) + DBGLOG(REQ, ERROR, + "param(DISABLED) conflict with cap(REQUIRED)\n"); + break; + case NL80211_MFP_REQUIRED: + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_REQUIRED; + break; + default: + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; + break; + } +#endif + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAuthMode, &eAuthMode, sizeof(eAuthMode), FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "set auth mode error:0x%x\n", rStatus); + + /* Enable the specific AKM suite only. */ + for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) { + prEntry = &prGlueInfo->prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[i]; + + if (prEntry->dot11RSNAConfigAuthenticationSuite == u4AkmSuite) { + prEntry->dot11RSNAConfigAuthenticationSuiteEnabled = TRUE; + /* printk("match AuthenticationSuite = 0x%x", u4AkmSuite); */ + } else { + prEntry->dot11RSNAConfigAuthenticationSuiteEnabled = FALSE; + } + } + + cipher = prGlueInfo->rWpaInfo.u4CipherGroup | prGlueInfo->rWpaInfo.u4CipherPairwise; + + if (1 /* prGlueInfo->rWpaInfo.fgPrivacyInvoke */) { +#if CFG_SUPPORT_SUITB + if (cipher & IW_AUTH_CIPHER_GCMP256) { + eEncStatus = ENUM_ENCRYPTION4_ENABLED; + } else +#endif + 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, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "set encryption mode error:0x%x\n", rStatus); + + if (sme->key_len != 0 && prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_DISABLED) { + /* NL80211 only set the Tx wep key while connect, the max 4 wep key set prior via add key cmd */ + P_PARAM_WEP_T prWepKey = (P_PARAM_WEP_T) wepBuf; + + kalMemZero(prWepKey, sizeof(PARAM_WEP_T)); + prWepKey->u4Length = OFFSET_OF(PARAM_WEP_T, aucKeyMaterial) + sme->key_len; + prWepKey->u4KeyLength = (UINT_32) sme->key_len; + prWepKey->u4KeyIndex = (UINT_32) sme->key_idx; + prWepKey->u4KeyIndex |= IS_TRANSMIT_KEY; + if (prWepKey->u4KeyLength > MAX_KEY_LEN) { + DBGLOG(REQ, WARN, "Too long key length (%u)\n", + prWepKey->u4KeyLength); + +#if CFG_CHIP_RESET_SUPPORT + rst_data.entry_conut--; + DBGLOG(INIT, TRACE, "entry_conut = %d\n", + rst_data.entry_conut); +#endif + return -EINVAL; + } + kalMemCopy(prWepKey->aucKeyMaterial, sme->key, prWepKey->u4KeyLength); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAddWep, prWepKey, prWepKey->u4Length, FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "wlanoidSetAddWep fail 0x%x\n", + rStatus); + +#if CFG_CHIP_RESET_SUPPORT + rst_data.entry_conut--; + DBGLOG(INIT, TRACE, "entry_conut = %d\n", + rst_data.entry_conut); +#endif + return -EFAULT; + } + } + + rNewSsid.u4CenterFreq = sme->channel ? sme->channel->center_freq : 0; + rNewSsid.pucBssid = (UINT_8 *)sme->bssid; + rNewSsid.pucSsid = (UINT_8 *)sme->ssid; + rNewSsid.u4SsidLen = sme->ssid_len; + rStatus = kalIoctl(prGlueInfo, wlanoidSetConnect, (PVOID)&rNewSsid, sizeof(PARAM_CONNECT_T), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set SSID:%x\n", rStatus); +#if CFG_CHIP_RESET_SUPPORT + rst_data.entry_conut--; + DBGLOG(INIT, TRACE, "entry_conut = %d\n", rst_data.entry_conut); +#endif + return -EINVAL; + } +#if 0 + if (sme->bssid != NULL && 1 /* prGlueInfo->fgIsBSSIDSet */) { + /* connect by BSSID */ + if (sme->ssid_len > 0) { + P_CONNECTION_SETTINGS_T prConnSettings = NULL; + + prConnSettings = &(prGlueInfo->prAdapter->rWifiVar.rConnSettings); + /* prGlueInfo->fgIsSSIDandBSSIDSet = TRUE; */ + COPY_SSID(prConnSettings->aucSSID, prConnSettings->ucSSIDLen, sme->ssid, sme->ssid_len); + } + rStatus = kalIoctl(prGlueInfo, + wlanoidSetBssid, + (PVOID) sme->bssid, MAC_ADDR_LEN, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set BSSID:%lx\n", rStatus); + return -EINVAL; + } + } else 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; + } + } +#endif +#if CFG_CHIP_RESET_SUPPORT + rst_data.entry_conut--; + DBGLOG(INIT, TRACE, "entry_conut = %d\n", rst_data.entry_conut); +#endif + 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; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, + "chip resetting, mtk_cfg80211_disconnect do nothing\n"); + return -EINVAL; + } +#endif + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + if (atomic_read(&prGlueInfo->cfgSuspend)) { + DBGLOG(REQ, WARN, "In suspend block cfg80211 ops\n"); + return -EFAULT; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, NULL, 0, FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "disassociate error:%x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +#if CFG_SUPPORT_CFG80211_AUTH +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to deauth from + * currently connected ESS + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_deauth(struct wiphy *wiphy, struct net_device *ndev, + struct cfg80211_deauth_request *req) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 rStatus; + UINT_32 u4BufLen; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, + "chip resetting, mtk_cfg80211_change_iface do nothing\n"); + return -EINVAL; + } +#endif + + DBGLOG(REQ, INFO, "mtk_cfg80211_deauth\n"); +#if CFG_SUPPORT_CFG80211_AUTH + /* The BSS from cfg80211_ops.assoc must give back to + * cfg80211_send_rx_assoc() or to cfg80211_assoc_timeout(). + * To ensure proper refcounting, new association requests + * while already associating must be rejected. + */ + if (prGlueInfo->prAdapter->rWifiVar.rConnSettings.bss) { + DBGLOG(REQ, INFO, "assoc timeout notify\n"); + /* ops caller have already hold the mutex. */ + cfg80211_assoc_timeout(ndev, + prGlueInfo->prAdapter->rWifiVar.rConnSettings.bss); + DBGLOG(REQ, INFO, "assoc timeout notify, Done\n"); + prGlueInfo->prAdapter->rWifiVar.rConnSettings.bss = NULL; + } +#endif + rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, NULL, 0, + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "disassociate error:%x\n", rStatus); + return -EFAULT; + } + + return 0; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @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, u4SsidLen = 0; + WLAN_STATUS rStatus; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, + "chip resetting, mtk_cfg80211_join_ibss do nothing\n"); + return -EINVAL; + } +#endif + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + /* set channel */ + if (params->channel_fixed) { + u4ChnlFreq = params->chandef.center_freq1; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetFrequency, + &u4ChnlFreq, sizeof(u4ChnlFreq), FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + /* set SSID */ + if (params->ssid_len > PARAM_MAX_LEN_SSID) + u4SsidLen = PARAM_MAX_LEN_SSID; + else + u4SsidLen = params->ssid_len; + + kalMemCopy(rNewSsid.aucSsid, params->ssid, u4SsidLen); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetSsid, (PVOID)&rNewSsid, sizeof(PARAM_SSID_T), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set SSID:0x%x\n", rStatus); + return -EFAULT; + } + + return 0; + + return -EINVAL; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to leave from IBSS group + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, + "chip resetting, mtk_cfg80211_leave_ibss do nothing\n"); + return -EINVAL; + } +#endif + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, NULL, 0, FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "disassociate error:0x%x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to configure + * WLAN power managemenet + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, bool enabled, int timeout) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + PARAM_POWER_MODE_T rPowerMode; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + if (!prGlueInfo) + return -EFAULT; + + if (!prGlueInfo->prAdapter->prAisBssInfo) + return -EFAULT; + + if (prGlueInfo->u4ReadyFlag == 0) { + DBGLOG(REQ, WARN, "prGlueInfo->u4ReadyFlag == 0\n"); + return -EFAULT; + } + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(INIT, WARN, "wlan is halt, skip set pwr mgmt\n"); + return WLAN_STATUS_FAILURE; + } + rst_data.entry_conut++; + DBGLOG(INIT, TRACE, "entry_conut = %d\n", rst_data.entry_conut); +#endif + + if (enabled) { + if (timeout == -1) + rPowerMode.ePowerMode = Param_PowerModeFast_PSP; + else + rPowerMode.ePowerMode = Param_PowerModeMAX_PSP; + } else { + rPowerMode.ePowerMode = Param_PowerModeCAM; + } + + rPowerMode.ucBssIdx = prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, sizeof(PARAM_POWER_MODE_T), FALSE, FALSE, TRUE, &u4BufLen); +#if CFG_CHIP_RESET_SUPPORT + rst_data.entry_conut--; + DBGLOG(INIT, TRACE, "entry_conut = %d\n", rst_data.entry_conut); +#endif + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set_power_mgmt error:0x%x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to cache + * a PMKID for a BSSID + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_pmksa *pmksa) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + P_PARAM_PMKID_T prPmkid; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, + "chip resetting, mtk_cfg80211_set_pmksa do nothing\n"); + return -EINVAL; + } +#endif + + 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, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "add pmkid error:0x%x\n", rStatus); + kalMemFree(prPmkid, VIR_MEM_TYPE, 8 + sizeof(PARAM_BSSID_INFO_T)); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to remove + * a cached PMKID for a BSSID + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_pmksa *pmksa) +{ + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to flush + * all cached PMKID + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + P_PARAM_PMKID_T prPmkid; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + prPmkid = (P_PARAM_PMKID_T) kalMemAlloc(8, VIR_MEM_TYPE); + if (!prPmkid) { + DBGLOG(INIT, INFO, "Can not alloc memory for IW_PMKSA_FLUSH\n"); + return -ENOMEM; + } + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(INIT, WARN, "wlan is halt, skip flush pmksa\n"); + return WLAN_STATUS_FAILURE; + } + rst_data.entry_conut++; + DBGLOG(INIT, TRACE, "entry_conut = %d\n", rst_data.entry_conut); +#endif + + prPmkid->u4Length = 8; + prPmkid->u4BSSIDInfoCount = 0; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetPmkid, prPmkid, sizeof(PARAM_PMKID_T), FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "flush pmkid error:0x%x\n", rStatus); + kalMemFree(prPmkid, VIR_MEM_TYPE, 8); + +#if CFG_CHIP_RESET_SUPPORT + rst_data.entry_conut--; + DBGLOG(INIT, TRACE, "entry_conut = %d\n", rst_data.entry_conut); +#endif + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for setting the rekey data + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_gtk_rekey_data *data) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4BufLen; + P_PARAM_GTK_REKEY_DATA prGtkData; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + INT_32 i4Rslt = -EINVAL; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, "mtk_cfg80211_set_rekey_data\n"); + return -EINVAL; + } +#endif + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + /* if disable offload, we store key data here, and enable rekey offload when enter wow */ + if (!prGlueInfo->prAdapter->rWifiVar.ucEapolOffload) { + kalMemZero(prGlueInfo->rWpaInfo.aucKek, NL80211_KEK_LEN); + kalMemZero(prGlueInfo->rWpaInfo.aucKck, NL80211_KCK_LEN); + kalMemZero(prGlueInfo->rWpaInfo.aucReplayCtr, NL80211_REPLAY_CTR_LEN); + kalMemCopy(prGlueInfo->rWpaInfo.aucKek, data->kek, NL80211_KEK_LEN); + kalMemCopy(prGlueInfo->rWpaInfo.aucKck, data->kck, NL80211_KCK_LEN); + kalMemCopy(prGlueInfo->rWpaInfo.aucReplayCtr, data->replay_ctr, NL80211_REPLAY_CTR_LEN); + + return 0; + } + + prGtkData = + (P_PARAM_GTK_REKEY_DATA) kalMemAlloc(sizeof(PARAM_GTK_REKEY_DATA), VIR_MEM_TYPE); + + if (!prGtkData) + return WLAN_STATUS_SUCCESS; + + DBGLOG(RSN, INFO, "cfg80211_set_rekey_data size(%d)\n", + (uint32_t) sizeof(struct cfg80211_gtk_rekey_data)); + + DBGLOG(RSN, INFO, "kek\n"); + DBGLOG_MEM8(PF, ERROR, (PUINT_8)data->kek, NL80211_KEK_LEN); + DBGLOG(RSN, INFO, "kck\n"); + DBGLOG_MEM8(PF, ERROR, (PUINT_8)data->kck, NL80211_KCK_LEN); + DBGLOG(RSN, INFO, "replay count\n"); + DBGLOG_MEM8(PF, ERROR, (PUINT_8)data->replay_ctr, NL80211_REPLAY_CTR_LEN); + + +#if 0 + kalMemCopy(prGtkData, data, sizeof(*data)); +#else + kalMemCopy(prGtkData->aucKek, data->kek, NL80211_KEK_LEN); + kalMemCopy(prGtkData->aucKck, data->kck, NL80211_KCK_LEN); + kalMemCopy(prGtkData->aucReplayCtr, data->replay_ctr, NL80211_REPLAY_CTR_LEN); +#endif + + prGtkData->ucBssIndex = prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + + prGtkData->u4Proto = NL80211_WPA_VERSION_2; + if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA) + prGtkData->u4Proto = NL80211_WPA_VERSION_1; + + if (prGlueInfo->rWpaInfo.u4CipherPairwise == IW_AUTH_CIPHER_TKIP) + prGtkData->u4PairwiseCipher = BIT(3); + else if (prGlueInfo->rWpaInfo.u4CipherPairwise == IW_AUTH_CIPHER_CCMP) + prGtkData->u4PairwiseCipher = BIT(4); + else { + kalMemFree(prGtkData, VIR_MEM_TYPE, sizeof(PARAM_GTK_REKEY_DATA)); + return WLAN_STATUS_SUCCESS; + } + + if (prGlueInfo->rWpaInfo.u4CipherGroup == IW_AUTH_CIPHER_TKIP) + prGtkData->u4GroupCipher = BIT(3); + else if (prGlueInfo->rWpaInfo.u4CipherGroup == IW_AUTH_CIPHER_CCMP) + prGtkData->u4GroupCipher = BIT(4); + else { + kalMemFree(prGtkData, VIR_MEM_TYPE, sizeof(PARAM_GTK_REKEY_DATA)); + return WLAN_STATUS_SUCCESS; + } + + prGtkData->u4KeyMgmt = prGlueInfo->rWpaInfo.u4KeyMgmt; + prGtkData->u4MgmtGroupCipher = 0; + + prGtkData->ucRekeyMode = GTK_REKEY_CMD_MODE_OFFLOAD_ON; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetGtkRekeyData, + prGtkData, sizeof(PARAM_GTK_REKEY_DATA), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "set GTK rekey data error:0x%x\n", rStatus); + else + i4Rslt = 0; + + kalMemFree(prGtkData, VIR_MEM_TYPE, sizeof(PARAM_GTK_REKEY_DATA)); + + return i4Rslt; +} + +void mtk_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, + IN struct wireless_dev *wdev, IN u16 frame_type, IN bool reg) +{ +#if 0 + P_MSG_P2P_MGMT_FRAME_REGISTER_T prMgmtFrameRegister = (P_MSG_P2P_MGMT_FRAME_REGISTER_T) NULL; +#endif + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(INIT, WARN, "wlan is halt, skip mgmt reg."); + return; + } + rst_data.entry_conut++; + DBGLOG(INIT, TRACE, "entry_conut = %d\n", rst_data.entry_conut); +#endif + + do { + + DBGLOG(INIT, TRACE, "mtk_cfg80211_mgmt_frame_register\n"); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + switch (frame_type) { + case MAC_FRAME_PROBE_REQ: + if (reg) { + prGlueInfo->u4OsMgmtFrameFilter |= PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(INIT, TRACE, "Open packet filer probe request\n"); + } else { + prGlueInfo->u4OsMgmtFrameFilter &= ~PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(INIT, TRACE, "Close packet filer probe request\n"); + } + break; + case MAC_FRAME_ACTION: + if (reg) { + prGlueInfo->u4OsMgmtFrameFilter |= PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(INIT, TRACE, "Open packet filer action frame.\n"); + } else { + prGlueInfo->u4OsMgmtFrameFilter &= ~PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(INIT, TRACE, "Close packet filer action frame.\n"); + } + break; + default: + DBGLOG(INIT, TRACE, "Ask frog to add code for mgmt:%x\n", frame_type); + break; + } + + if (prGlueInfo->prAdapter != NULL) { + + set_bit(GLUE_FLAG_FRAME_FILTER_AIS_BIT, &prGlueInfo->ulFlag); + + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + + if (in_interrupt()) + DBGLOG(INIT, 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); + +#if CFG_CHIP_RESET_SUPPORT + rst_data.entry_conut--; + DBGLOG(INIT, TRACE, "entry_conut = %d\n", rst_data.entry_conut); +#endif + +} /* mtk_cfg80211_mgmt_frame_register */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to stay on a + * specified channel + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, unsigned int duration, u64 *cookie) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_REMAIN_ON_CHANNEL_T prMsgChnlReq = (P_MSG_REMAIN_ON_CHANNEL_T) NULL; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, + "chip resetting, mtk_cfg80211_remain_on_channel do nothing\n"); + return -EINVAL; + } +#endif + + do { + if ((wiphy == NULL) + || (wdev == NULL) + || (chan == NULL) + || (cookie == NULL)) { + break; + } + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + if (!wlanGetHifState(prGlueInfo)) + break; + +#if 1 + DBGLOG(INIT, INFO, "--> %s()\n", __func__); +#endif + + *cookie = prGlueInfo->u8Cookie++; + + prMsgChnlReq = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_REMAIN_ON_CHANNEL_T)); + + if (prMsgChnlReq == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgChnlReq->rMsgHdr.eMsgId = MID_MNY_AIS_REMAIN_ON_CHANNEL; + prMsgChnlReq->u8Cookie = *cookie; + prMsgChnlReq->u4DurationMs = duration; + + prMsgChnlReq->ucChannelNum = nicFreq2ChannelNum(chan->center_freq * 1000); + + switch (chan->band) { + case KAL_BAND_2GHZ: + prMsgChnlReq->eBand = BAND_2G4; + break; + case KAL_BAND_5GHZ: + prMsgChnlReq->eBand = BAND_5G; + break; + default: + prMsgChnlReq->eBand = BAND_2G4; + break; + } + + prMsgChnlReq->eSco = CHNL_EXT_SCN; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChnlReq, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to cancel staying + * on a specified channel + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_CANCEL_REMAIN_ON_CHANNEL_T prMsgChnlAbort = (P_MSG_CANCEL_REMAIN_ON_CHANNEL_T) NULL; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, + "chip resetting, mtk_cfg80211_cancel_remain_on_channel do nothing\n"); + return -EINVAL; + } +#endif + + do { + if ((wiphy == NULL) + || (wdev == NULL) + ) { + break; + } + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + prMsgChnlAbort = + cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_CANCEL_REMAIN_ON_CHANNEL_T)); + + if (prMsgChnlAbort == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgChnlAbort->rMsgHdr.eMsgId = MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL; + prMsgChnlAbort->u8Cookie = cookie; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChnlAbort, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to send a management frame + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_MGMT_TX_REQUEST_T prMsgTxReq = (P_MSG_MGMT_TX_REQUEST_T) NULL; + P_MSDU_INFO_T prMgmtFrame = (P_MSDU_INFO_T) NULL; + PUINT_8 pucFrameBuf = (PUINT_8) NULL; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, + "chip resetting, mtk_cfg80211_mgmt_tx do nothing\n"); + return -EINVAL; + } +#endif + + do { + if ((wiphy == NULL) || (wdev == NULL) || (params == 0) || (cookie == NULL)) + break; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + *cookie = prGlueInfo->u8Cookie++; + + /* Channel & Channel Type & Wait time are ignored. */ + prMsgTxReq = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_MGMT_TX_REQUEST_T)); + + if (prMsgTxReq == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgTxReq->fgNoneCckRate = FALSE; + prMsgTxReq->fgIsWaitRsp = TRUE; + + prMgmtFrame = cnmMgtPktAlloc(prGlueInfo->prAdapter, (UINT_32) (params->len + MAC_TX_RESERVED_FIELD)); + prMsgTxReq->prMgmtMsduInfo = prMgmtFrame; + if (prMsgTxReq->prMgmtMsduInfo == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgTxReq->u8Cookie = *cookie; + prMsgTxReq->rMsgHdr.eMsgId = MID_MNY_AIS_MGMT_TX; + + pucFrameBuf = (PUINT_8) ((ULONG) prMgmtFrame->prPacket + MAC_TX_RESERVED_FIELD); + + kalMemCopy(pucFrameBuf, params->buf, params->len); + + prMgmtFrame->u2FrameLength = params->len; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgTxReq, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + if ((i4Rslt != 0) && (prMsgTxReq != NULL)) { + if (prMsgTxReq->prMgmtMsduInfo != NULL) + cnmMgtPktFree(prGlueInfo->prAdapter, prMsgTxReq->prMgmtMsduInfo); + + cnmMemFree(prGlueInfo->prAdapter, prMsgTxReq); + } + + return i4Rslt; +} +#else +int mtk_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *channel, bool offscan, + 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; + INT_32 i4Rslt = -EINVAL; + P_MSG_MGMT_TX_REQUEST_T prMsgTxReq = (P_MSG_MGMT_TX_REQUEST_T) NULL; + P_MSDU_INFO_T prMgmtFrame = (P_MSDU_INFO_T) NULL; + PUINT_8 pucFrameBuf = (PUINT_8) NULL; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, + "chip resetting, mtk_cfg80211_mgmt_tx do nothing\n"); + return -EINVAL; + } +#endif + + do { + if ((wiphy == NULL) + || (buf == NULL) + || (len == 0) + || (wdev == NULL) + || (cookie == NULL)) { + break; + } + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + *cookie = prGlueInfo->u8Cookie++; + + /* Channel & Channel Type & Wait time are ignored. */ + prMsgTxReq = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_MGMT_TX_REQUEST_T)); + + if (prMsgTxReq == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgTxReq->fgNoneCckRate = FALSE; + prMsgTxReq->fgIsWaitRsp = TRUE; + + prMgmtFrame = cnmMgtPktAlloc(prGlueInfo->prAdapter, (UINT_32) (len + MAC_TX_RESERVED_FIELD)); + prMsgTxReq->prMgmtMsduInfo = prMgmtFrame; + if (prMsgTxReq->prMgmtMsduInfo == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgTxReq->u8Cookie = *cookie; + prMsgTxReq->rMsgHdr.eMsgId = MID_MNY_AIS_MGMT_TX; + + pucFrameBuf = (PUINT_8) ((ULONG) prMgmtFrame->prPacket + MAC_TX_RESERVED_FIELD); + + kalMemCopy(pucFrameBuf, 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; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to cancel the wait time + * from transmitting a management frame on another channel + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, + "chip resetting,mtk_cfg80211_mgmt_tx_cancel_wait do nothing\n"); + return -EINVAL; + } +#endif + +#if 1 + DBGLOG(INIT, INFO, "--> %s()\n", __func__); +#endif + + /* not implemented */ + + return -EINVAL; +} + +#ifdef CONFIG_NL80211_TESTMODE + +#if CFG_SUPPORT_PASSPOINT +int mtk_cfg80211_testmode_hs20_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + struct wpa_driver_hs20_data_s *prParams = NULL; + WLAN_STATUS rstatus = WLAN_STATUS_SUCCESS; + int fgIsValid = 0; + UINT_32 u4SetInfoLen = 0; + + ASSERT(wiphy); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, + "chip resetting, mtk_cfg80211_testmode_hs20_cmd do nothing\n"); + return -EINVAL; + } +#endif + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + +#if 1 + DBGLOG(INIT, INFO, "--> %s()\n", __func__); +#endif + + if (data && len) + prParams = (struct wpa_driver_hs20_data_s *)data; + + if (prParams) { + int i; + + DBGLOG(INIT, INFO, "[%s] Cmd Type (%d)\n", + __func__, prParams->CmdType); + switch (prParams->CmdType) { + case HS20_CMD_ID_SET_BSSID_POOL: + DBGLOG(INIT, INFO, + "[%s] fgBssidPoolIsEnable (%d)\n", __func__, + prParams->hs20_set_bssid_pool.fgBssidPoolIsEnable); + DBGLOG(INIT, INFO, + "[%s] ucNumBssidPool (%d)\n", __func__, prParams->hs20_set_bssid_pool.ucNumBssidPool); + + for (i = 0; i < prParams->hs20_set_bssid_pool.ucNumBssidPool; i++) { + DBGLOG(INIT, INFO, "[%s][%d][" MACSTR "]\n", __func__, i, + MAC2STR(prParams->hs20_set_bssid_pool.arBssidPool[i])); + } + rstatus = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC) wlanoidSetHS20BssidPool, + &prParams->hs20_set_bssid_pool, + sizeof(struct param_hs20_set_bssid_pool), FALSE, FALSE, TRUE, &u4SetInfoLen); + break; + default: + DBGLOG(INIT, INFO, "[%s] Unknown Cmd Type (%d)\n", __func__, prParams->CmdType); + rstatus = WLAN_STATUS_FAILURE; + + } + + } + + if (rstatus != WLAN_STATUS_SUCCESS) + fgIsValid = -EFAULT; + + return fgIsValid; +} + +#endif /* CFG_SUPPORT_PASSPOINT */ + +#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; + const UINT_8 aucBCAddr[] = BC_MAC_ADDR; + + P_PARAM_KEY_T prWpiKey = (P_PARAM_KEY_T) keyStructBuf; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, + "chip resetting, mtk_cfg80211_testmode_set_key_ext do nothing\n"); + return -EINVAL; + } +#endif + + memset(keyStructBuf, 0, sizeof(keyStructBuf)); + + ASSERT(wiphy); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + +#if 1 + DBGLOG(INIT, INFO, "--> %s()\n", __func__); +#endif + + if (data == NULL || len == 0) { + DBGLOG(INIT, TRACE, "%s data or len is invalid\n", __func__); + return -EINVAL; + } + + prParams = (P_NL80211_DRIVER_SET_KEY_EXTS) data; + prIWEncExt = (struct iw_encode_exts *)&prParams->ext; + + if (prIWEncExt->alg == IW_ENCODE_ALG_SMS4) { + /* KeyID */ + prWpiKey->u4KeyIndex = prParams->key_index; + prWpiKey->u4KeyIndex--; + if (prWpiKey->u4KeyIndex > 1) { + /* key id is out of range */ + + return -EINVAL; + } + + if (prIWEncExt->key_len != 32) { + /* key length not valid */ + + return -EINVAL; + } + prWpiKey->u4KeyLength = prIWEncExt->key_len; + + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY && + !(prIWEncExt->ext_flags & IW_ENCODE_EXT_GROUP_KEY)) { + /* WAI seems set the STA group key with IW_ENCODE_EXT_SET_TX_KEY !!!!*/ + /* Ignore the group case */ + prWpiKey->u4KeyIndex |= BIT(30); + prWpiKey->u4KeyIndex |= BIT(31); + /* BSSID */ + memcpy(prWpiKey->arBSSID, prIWEncExt->addr, 6); + } else { + COPY_MAC_ADDR(prWpiKey->arBSSID, aucBCAddr); + } + + /* PN */ + /* memcpy(prWpiKey->rKeyRSC, prIWEncExt->tx_seq, IW_ENCODE_SEQ_MAX_SIZE * 2); */ + + memcpy(prWpiKey->aucKeyMaterial, prIWEncExt->key, 32); + + prWpiKey->u4Length = sizeof(PARAM_KEY_T); + prWpiKey->ucBssIdx = prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + prWpiKey->ucCipher = CIPHER_SUITE_WPI; + + rstatus = kalIoctl(prGlueInfo, + wlanoidSetAddKey, prWpiKey, sizeof(PARAM_KEY_T), FALSE, FALSE, TRUE, &u4BufLen); + + if (rstatus != WLAN_STATUS_SUCCESS) { + + fgIsValid = -EFAULT; + } + + } + return fgIsValid; +} +#endif + +int +mtk_cfg80211_testmode_get_sta_statistics(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen; + UINT_32 u4LinkScore; + UINT_32 u4TotalError; + UINT_32 u4TxExceedThresholdCount; + UINT_32 u4TxTotalCount; + + P_NL80211_DRIVER_GET_STA_STATISTICS_PARAMS prParams = NULL; + PARAM_GET_STA_STA_STATISTICS rQueryStaStatistics; + struct sk_buff *skb; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, + "chip resetting, mtk_cfg80211_testmode_get_sta_statistics do nothing\n"); + } +#endif + + ASSERT(wiphy); + ASSERT(prGlueInfo); + + if (data && len) + prParams = (P_NL80211_DRIVER_GET_STA_STATISTICS_PARAMS) data; + + if (!prParams) { + DBGLOG(QM, TRACE, "%s prParams is NULL\n", __func__); + return -EINVAL; + } + + skb = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(PARAM_GET_STA_STA_STATISTICS) + 1); + + if (!skb) { + DBGLOG(QM, TRACE, "%s allocate skb failed:%lx\n", __func__, rStatus); + return -ENOMEM; + } + DBGLOG(QM, TRACE, "Get [" MACSTR "] STA statistics\n", MAC2STR(prParams->aucMacAddr)); + + kalMemZero(&rQueryStaStatistics, sizeof(rQueryStaStatistics)); + COPY_MAC_ADDR(rQueryStaStatistics.aucMacAddr, prParams->aucMacAddr); + rQueryStaStatistics.ucReadClear = TRUE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStaStatistics, + &rQueryStaStatistics, sizeof(rQueryStaStatistics), TRUE, FALSE, TRUE, &u4BufLen); + + /* Calcute Link Score */ + u4TxExceedThresholdCount = rQueryStaStatistics.u4TxExceedThresholdCount; + u4TxTotalCount = rQueryStaStatistics.u4TxTotalCount; + u4TotalError = rQueryStaStatistics.u4TxFailCount + rQueryStaStatistics.u4TxLifeTimeoutCount; + + /* u4LinkScore 10~100 , ExceedThreshold ratio 0~90 only */ + /* u4LinkScore 0~9 , Drop packet ratio 0~9 and all packets exceed threshold */ + if (u4TxTotalCount) { + if (u4TxExceedThresholdCount <= u4TxTotalCount) + u4LinkScore = (90 - ((u4TxExceedThresholdCount * 90) / u4TxTotalCount)); + else + u4LinkScore = 0; + } else { + u4LinkScore = 90; + } + + u4LinkScore += 10; + + if (u4LinkScore == 10) { + + if (u4TotalError <= u4TxTotalCount) + u4LinkScore = (10 - ((u4TotalError * 10) / u4TxTotalCount)); + else + u4LinkScore = 0; + + } + + if (u4LinkScore > 100) + u4LinkScore = 100; + + { + u8 __tmp = 0; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_INVALID, sizeof(u8), &__tmp) < 0)) + goto nla_put_failure; + } + { + u8 __tmp = NL80211_DRIVER_TESTMODE_VERSION; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_VERSION, sizeof(u8), &__tmp) < 0)) + goto nla_put_failure; + } + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_MAC, MAC_ADDR_LEN, prParams->aucMacAddr) < 0)) + goto nla_put_failure; + { + u8 __tmp = u4LinkScore; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE, sizeof(u8), &__tmp) < 0)) + goto nla_put_failure; + } + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_MAC, MAC_ADDR_LEN, prParams->aucMacAddr) < 0)) + goto nla_put_failure; + { + u32 __tmp = rQueryStaStatistics.u4Flag; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_FLAG, sizeof(u32), &__tmp) < 0)) + goto nla_put_failure; + } + + /* FW part STA link status */ + { + u8 __tmp = rQueryStaStatistics.ucPer; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_PER, sizeof(u8), &__tmp) < 0)) + goto nla_put_failure; + } + { + u8 __tmp = rQueryStaStatistics.ucRcpi; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_RSSI, sizeof(u8), &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4PhyMode; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_PHY_MODE, sizeof(u32), &__tmp) < 0)) + goto nla_put_failure; + } + { + u16 __tmp = rQueryStaStatistics.u2LinkSpeed; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TX_RATE, sizeof(u16), &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4TxFailCount; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT, sizeof(u32), &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4TxLifeTimeoutCount; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT, sizeof(u32), &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4TxAverageAirTime; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME, sizeof(u32), &__tmp) < 0)) + goto nla_put_failure; + } + + /* Driver part link status */ + { + u32 __tmp = rQueryStaStatistics.u4TxTotalCount; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT, sizeof(u32), &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4TxExceedThresholdCount; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT, sizeof(u32), &__tmp) < 0)) + goto nla_put_failure; + } + { + u32 __tmp = rQueryStaStatistics.u4TxAverageProcessTime; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME, sizeof(u32), &__tmp) < 0)) + goto nla_put_failure; + } + + /* Network counter */ + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY, + sizeof(rQueryStaStatistics.au4TcResourceEmptyCount), rQueryStaStatistics.au4TcResourceEmptyCount) < 0)) + goto nla_put_failure; + + /* Sta queue length */ + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY, + sizeof(rQueryStaStatistics.au4TcQueLen), rQueryStaStatistics.au4TcQueLen) < 0)) + goto nla_put_failure; + + /* Global QM counter */ + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY, + sizeof(rQueryStaStatistics.au4TcAverageQueLen), rQueryStaStatistics.au4TcAverageQueLen) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY, + sizeof(rQueryStaStatistics.au4TcCurrentQueLen), rQueryStaStatistics.au4TcCurrentQueLen) < 0)) + goto nla_put_failure; + + /* Reserved field */ + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY, + sizeof(rQueryStaStatistics.au4Reserved), rQueryStaStatistics.au4Reserved) < 0)) + goto nla_put_failure; + + return cfg80211_testmode_reply(skb); + +nla_put_failure: + /* nal_put_skb_fail */ + kfree_skb(skb); + return -EFAULT; +} + +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); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(REQ, ERROR, "mtk_cfg80211_testmode_sw_cmd\n"); +#endif + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + +#if 1 + DBGLOG(INIT, INFO, "--> %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, &u4SetInfoLen); + } + } + + if (rstatus != WLAN_STATUS_SUCCESS) + fgIsValid = -EFAULT; + + return fgIsValid; +} + +static int mtk_wlan_cfg_testmode_cmd(struct wiphy *wiphy, void *data, int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_TEST_MODE_PARAMS prParams = NULL; + INT_32 i4Status; + + ASSERT(wiphy); + DBGLOG(INIT, INFO, "-->%s()\n", __func__); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(REQ, ERROR, "mtk_wlan_cfg_testmode_cmd\n"); +#endif + + if (!data || !len) { + DBGLOG(REQ, ERROR, "mtk_cfg80211_testmode_cmd null data\n"); + return -EINVAL; + } + + if (!wiphy) { + DBGLOG(REQ, ERROR, "mtk_cfg80211_testmode_cmd null wiphy\n"); + return -EINVAL; + } + + prGlueInfo = (P_GLUE_INFO_T)wiphy_priv(wiphy); + prParams = (P_NL80211_DRIVER_TEST_MODE_PARAMS)data; + + /* Clear the version byte */ + prParams->index = prParams->index & ~BITS(24, 31); + + switch (prParams->index) { + case TESTMODE_CMD_ID_SW_CMD: /* SW cmd */ + i4Status = mtk_cfg80211_testmode_sw_cmd(wiphy, data, len); + break; + case TESTMODE_CMD_ID_WAPI: /* WAPI */ +#if CFG_SUPPORT_WAPI + i4Status = mtk_cfg80211_testmode_set_key_ext(wiphy, data, len); +#endif + break; + case 0x10: + i4Status = mtk_cfg80211_testmode_get_sta_statistics(wiphy, data, len, prGlueInfo); + break; + +#if CFG_SUPPORT_PASSPOINT + case TESTMODE_CMD_ID_HS20: + i4Status = mtk_cfg80211_testmode_hs20_cmd(wiphy, data, len); + break; +#endif /* CFG_SUPPORT_PASSPOINT */ + + default: + i4Status = -EINVAL; + break; + } + + if (i4Status != 0) + DBGLOG(REQ, TRACE, "prParams->index=%d, status=%d\n", + prParams->index, i4Status); + + return i4Status; +} + +#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_testmode_cmd(struct wiphy *wiphy, struct wireless_dev *wdev, + void *data, int len) +{ + ASSERT(wdev); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(REQ, ERROR, "mtk_cfg80211_testmode_cmd\n"); +#endif + + return mtk_wlan_cfg_testmode_cmd(wiphy, data, len); +} +#else +int mtk_cfg80211_testmode_cmd(struct wiphy *wiphy, void *data, int len) +{ +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(REQ, ERROR, "mtk_cfg80211_testmode_cmd\n"); +#endif + + return mtk_wlan_cfg_testmode_cmd(wiphy, data, len); +} +#endif +#endif + +int +mtk_cfg80211_sched_scan_start(IN struct wiphy *wiphy, + IN struct net_device *ndev, IN struct cfg80211_sched_scan_request *request) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 i, u4BufLen; + P_PARAM_SCHED_SCAN_REQUEST prSchedScanRequest; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, + "chip resetting, mtk_cfg80211_sched_scan_start do nothing\n"); + return -EINVAL; + } +#endif + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + /* check if there is any pending scan/sched_scan not yet finished */ + if (prGlueInfo->prScanRequest != NULL || prGlueInfo->prSchedScanRequest != NULL) { + DBGLOG(SCN, INFO, "(prGlueInfo->prScanRequest != NULL || prGlueInfo->prSchedScanRequest != NULL)\n"); + return -EBUSY; + } else if (request == NULL || request->n_match_sets > CFG_SCAN_SSID_MATCH_MAX_NUM) { + DBGLOG(SCN, INFO, "(request == NULL || request->n_match_sets > CFG_SCAN_SSID_MATCH_MAX_NUM)\n"); + /* invalid scheduled scan request */ + return -EINVAL; + } else if (!request->n_ssids || !request->n_match_sets) { + /* invalid scheduled scan request */ + return -EINVAL; + } + + prSchedScanRequest = (P_PARAM_SCHED_SCAN_REQUEST) kalMemAlloc(sizeof(PARAM_SCHED_SCAN_REQUEST), VIR_MEM_TYPE); + if (prSchedScanRequest == NULL) { + DBGLOG(SCN, INFO, "(prSchedScanRequest == NULL) kalMemAlloc fail\n"); + return -ENOMEM; + } + + prSchedScanRequest->u4SsidNum = request->n_match_sets; + for (i = 0; i < request->n_match_sets; i++) { + if (request->match_sets == NULL || &(request->match_sets[i]) == NULL) { + prSchedScanRequest->arSsid[i].u4SsidLen = 0; + } else { + COPY_SSID(prSchedScanRequest->arSsid[i].aucSsid, + prSchedScanRequest->arSsid[i].u4SsidLen, + request->match_sets[i].ssid.ssid, request->match_sets[i].ssid.ssid_len); + } + } + + prSchedScanRequest->u4IELength = request->ie_len; + if (request->ie_len > 0) + prSchedScanRequest->pucIE = (PUINT_8) (request->ie); + +#if KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE + prSchedScanRequest->u2ScanInterval = (UINT_16) (request->scan_plans->interval); +#else + prSchedScanRequest->u2ScanInterval = (UINT_16) (request->interval); +#endif + rStatus = kalIoctl(prGlueInfo, + wlanoidSetStartSchedScan, + prSchedScanRequest, sizeof(PARAM_SCHED_SCAN_REQUEST), FALSE, FALSE, TRUE, &u4BufLen); + + kalMemFree(prSchedScanRequest, VIR_MEM_TYPE, sizeof(PARAM_SCHED_SCAN_REQUEST)); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "scheduled scan error:%x\n", rStatus); + return -EINVAL; + } + + prGlueInfo->prSchedScanRequest = request; + + return 0; +} + +int mtk_cfg80211_sched_scan_stop(IN struct wiphy *wiphy, IN struct net_device *ndev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, + "chip resetting, mtk_cfg80211_sched_scan_stop do nothing\n"); + return -EINVAL; + } +#endif + + /* check if there is any pending scan/sched_scan not yet finished */ + if (prGlueInfo->prSchedScanRequest == NULL) + return -EBUSY; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetStopSchedScan, NULL, 0, FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_FAILURE) { + DBGLOG(REQ, WARN, "scheduled scan error:0x%x\n", rStatus); + return -EINVAL; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for handling association request + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_assoc(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_assoc_request *req) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_8 arBssid[PARAM_MAC_ADDR_LEN]; +#if CFG_SUPPORT_PASSPOINT + PUINT_8 prDesiredIE = NULL; +#endif /* CFG_SUPPORT_PASSPOINT */ + UINT_32 rStatus; + UINT_32 u4BufLen; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, + "chip resetting, mtk_cfg80211_assoc do nothing\n"); + return -EINVAL; + } +#endif + +#if CFG_SUPPORT_CFG80211_AUTH + ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus; + ENUM_PARAM_AUTH_MODE_T eAuthMode; + UINT_32 cipher; + UINT_32 i, u4AkmSuite; + P_DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY prEntry; + P_CONNECTION_SETTINGS_T prConnSettings = NULL; + PUINT_8 prDesiredIE = NULL; + PUINT_8 pucIEStart = NULL; + RSN_INFO_T rRsnInfo; + P_STA_RECORD_T prStaRec = NULL; +#endif + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if CFG_SUPPORT_CFG80211_AUTH + prConnSettings = &prGlueInfo->prAdapter->rWifiVar.rConnSettings; + + /* [todo]temp use for indicate rx assoc resp, may need to be modified */ + + /* The BSS from cfg80211_ops.assoc must give back to + * cfg80211_send_rx_assoc() or to cfg80211_assoc_timeout(). + * To ensure proper refcounting, new association requests + * while already associating must be rejected. + */ + if (prConnSettings->bss) + return -ENOENT; + prConnSettings->bss = req->bss; +#endif + DBGLOG(REQ, INFO, "mtk_cfg80211_assoc, media state:%d\n", + prGlueInfo->eParamMediaStateIndicated); + + kalMemZero(arBssid, MAC_ADDR_LEN); + if (prGlueInfo->eParamMediaStateIndicated == + PARAM_MEDIA_STATE_CONNECTED) { + wlanQueryInformation(prGlueInfo->prAdapter, wlanoidQueryBssid, + &arBssid[0], sizeof(arBssid), &u4BufLen); + + /* 1. check BSSID */ + if (UNEQUAL_MAC_ADDR(arBssid, req->bss->bssid)) { + /* wrong MAC address */ + DBGLOG(REQ, WARN, "incorrect BSSID: [" MACSTR + "] currently connected BSSID[" MACSTR "]\n", + MAC2STR(req->bss->bssid), MAC2STR(arBssid)); + return -ENOENT; + } + } +#if CFG_SUPPORT_CFG80211_AUTH + /* <1> 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; +#if CFG_SUPPORT_802_11W + prGlueInfo->rWpaInfo.u4CipherGroupMgmt = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; + prGlueInfo->rWpaInfo.ucRSNMfpCap = RSN_AUTH_MFP_DISABLED; +#endif + prGlueInfo->rWpaInfo.ucRsneLen = 0; + + /* 2.Fill WPA version */ + if (req->crypto.wpa_versions & NL80211_WPA_VERSION_1) + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_WPA; + else if (req->crypto.wpa_versions & NL80211_WPA_VERSION_2) + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_WPA2; + else + prGlueInfo->rWpaInfo.u4WpaVersion = + IW_AUTH_WPA_VERSION_DISABLED; + DBGLOG(REQ, INFO, "wpa ver=%d\n", prGlueInfo->rWpaInfo.u4WpaVersion); + + /* 3.Fill pairwise cipher suite */ + if (req->crypto.n_ciphers_pairwise) { + DBGLOG(RSN, INFO, "[wlan] cipher pairwise (%x)\n", + req->crypto.ciphers_pairwise[0]); + + prGlueInfo->prAdapter->rWifiVar.rConnSettings.rRsnInfo + .au4PairwiseKeyCipherSuite[0] = + req->crypto.ciphers_pairwise[0]; + switch (req->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; + case WLAN_CIPHER_SUITE_BIP_GMAC_256: + prGlueInfo->rWpaInfo.u4CipherPairwise = + IW_AUTH_CIPHER_GCMP256; + break; + case WLAN_CIPHER_SUITE_GCMP_256: + prGlueInfo->rWpaInfo.u4CipherPairwise = + IW_AUTH_CIPHER_GCMP256; + break; + default: + DBGLOG(REQ, WARN, "invalid cipher pairwise (%d)\n", + req->crypto.ciphers_pairwise[0]); + return -EINVAL; + } + } + + /* 4. Fill group cipher suite */ + if (req->crypto.cipher_group) { + DBGLOG(RSN, INFO, "[wlan] cipher group (%x)\n", + req->crypto.cipher_group); + prGlueInfo->prAdapter->rWifiVar.rConnSettings.rRsnInfo + .u4GroupKeyCipherSuite = req->crypto.cipher_group; + switch (req->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; + case WLAN_CIPHER_SUITE_BIP_GMAC_256: + prGlueInfo->rWpaInfo.u4CipherGroup = + IW_AUTH_CIPHER_GCMP256; + break; + case WLAN_CIPHER_SUITE_GCMP_256: + prGlueInfo->rWpaInfo.u4CipherGroup = + IW_AUTH_CIPHER_GCMP256; + break; + case WLAN_CIPHER_SUITE_NO_GROUP_ADDR: + break; + default: + DBGLOG(REQ, WARN, "invalid cipher group (%d)\n", + req->crypto.cipher_group); + return -EINVAL; + } + } + + /* 5. Fill encryption status */ + cipher = prGlueInfo->rWpaInfo.u4CipherGroup | + prGlueInfo->rWpaInfo.u4CipherPairwise; + if (1 /* prGlueInfo->rWpaInfo.fgPrivacyInvoke */) { + if (cipher & IW_AUTH_CIPHER_GCMP256) { + eEncStatus = ENUM_ENCRYPTION4_ENABLED; + } else 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, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "set encryption mode error:%x\n", rStatus); + + /* 6. Fill AKM suites */ + u4AkmSuite = 0; + eAuthMode = 0; + DBGLOG(REQ, INFO, "request numbers of Akm Suite:%d\n", + req->crypto.n_akm_suites); + for (i = 0; i < req->crypto.n_akm_suites; i++) + DBGLOG(REQ, INFO, "request Akm Suite[%d]:%d\n", + i, req->crypto.akm_suites[i]); + + if (req->crypto.n_akm_suites) { + prGlueInfo->prAdapter->rWifiVar.rConnSettings.rRsnInfo + .au4AuthKeyMgtSuite[0] = req->crypto.akm_suites[0]; + DBGLOG(REQ, INFO, "Akm Suite:%d\n", req->crypto.akm_suites[0]); + + if (prGlueInfo->rWpaInfo.u4WpaVersion == + IW_AUTH_WPA_VERSION_WPA) { + switch (req->crypto.akm_suites[0]) { + case WLAN_AKM_SUITE_8021X: + eAuthMode = AUTH_MODE_WPA; + u4AkmSuite = WPA_AKM_SUITE_802_1X; + break; + case WLAN_AKM_SUITE_PSK: + eAuthMode = AUTH_MODE_WPA_PSK; + u4AkmSuite = WPA_AKM_SUITE_PSK; + break; + default: + DBGLOG(REQ, WARN, "invalid Akm Suite (%08x)\n", + req->crypto.akm_suites[0]); + return -EINVAL; + } + } else if (prGlueInfo->rWpaInfo.u4WpaVersion == + IW_AUTH_WPA_VERSION_WPA2) { + switch (req->crypto.akm_suites[0]) { + case WLAN_AKM_SUITE_8021X: + eAuthMode = AUTH_MODE_WPA2; + u4AkmSuite = RSN_AKM_SUITE_802_1X; + break; + case WLAN_AKM_SUITE_PSK: + eAuthMode = AUTH_MODE_WPA2_PSK; + u4AkmSuite = RSN_AKM_SUITE_PSK; + break; +#if CFG_SUPPORT_802_11W + /* Notice:: Need kernel patch!! */ + case WLAN_AKM_SUITE_8021X_SHA256: + eAuthMode = AUTH_MODE_WPA2; + u4AkmSuite = RSN_AKM_SUITE_802_1X_SHA256; + break; + case WLAN_AKM_SUITE_PSK_SHA256: + eAuthMode = AUTH_MODE_WPA2_PSK; + u4AkmSuite = RSN_AKM_SUITE_PSK_SHA256; + break; +#endif + case WLAN_AKM_SUITE_8021X_SUITE_B: + eAuthMode = AUTH_MODE_WPA2_PSK; + u4AkmSuite = RSN_AKM_SUITE_8021X_SUITE_B_192; + break; + + case WLAN_AKM_SUITE_8021X_SUITE_B_192: + eAuthMode = AUTH_MODE_WPA2_PSK; + u4AkmSuite = RSN_AKM_SUITE_8021X_SUITE_B_192; + break; +#if CFG_SUPPORT_SAE + /* Need to add in WPA also? */ + case WLAN_AKM_SUITE_SAE: + eAuthMode = AUTH_MODE_WPA2_SAE; + u4AkmSuite = RSN_AKM_SUITE_SAE; + break; +#endif +#if CFG_SUPPORT_OWE + case WLAN_AKM_SUITE_OWE: + eAuthMode = AUTH_MODE_WPA2_PSK; + u4AkmSuite = RSN_AKM_SUITE_OWE; + break; +#endif + default: + DBGLOG(REQ, WARN, "invalid Akm Suite (%08x)\n", + req->crypto.akm_suites[0]); + 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; + } + + DBGLOG(REQ, INFO, "set auth mode:%d, akm suite:0x%x\n", + eAuthMode, u4AkmSuite); + + /* 6.1 Set auth mode*/ + rStatus = kalIoctl(prGlueInfo, wlanoidSetAuthMode, &eAuthMode, + sizeof(eAuthMode), FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "set auth mode error:%x\n", rStatus); + + /* 6.2 Enable the specific AKM suite only. */ + for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) { + prEntry = &prGlueInfo->prAdapter + ->rMib.dot11RSNAConfigAuthenticationSuitesTable[i]; + + if (prEntry->dot11RSNAConfigAuthenticationSuite == u4AkmSuite) { + prEntry->dot11RSNAConfigAuthenticationSuiteEnabled + = TRUE; + DBGLOG(REQ, INFO, "match AuthenticationSuite = 0x%x", + u4AkmSuite); + } else { + prEntry->dot11RSNAConfigAuthenticationSuiteEnabled + = FALSE; + } + } +#endif + + /* 7. Parsing desired ie from upper layer */ + prGlueInfo->fgWpsActive = FALSE; + + if (req->ie && req->ie_len > 0) { +#if CFG_SUPPORT_CFG80211_AUTH + pucIEStart = (PUINT_8)req->ie; +#endif + +#if CFG_SUPPORT_PASSPOINT + if (wextSrchDesiredHS20IE((PUINT_8) req->ie, req->ie_len, + (PPUINT_8) & prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetHS20Info, + prDesiredIE, IE_SIZE(prDesiredIE), + FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + /* DBGLOG(REQ, TRACE, ("[HS20] set HS20 assoc " + * "info error:%x\n", rStatus)); + */ + } + } + + if (wextSrchDesiredInterworkingIE((PUINT_8) req->ie, + req->ie_len, (PPUINT_8) & prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetInterworkingInfo, + prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + /* DBGLOG(REQ, TRACE, ("[HS20] set Interworking" + * " assoc info error:%x\n", rStatus)); + */ + } + } + + if (wextSrchDesiredRoamingConsortiumIE((PUINT_8) req->ie, + req->ie_len, (PPUINT_8) & prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRoamingConsortiumIEInfo, + prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + /* DBGLOG(REQ, TRACE, ("[HS20] set + * RoamingConsortium assoc info error:%x\n", + * rStatus)); + */ + } + } +#endif /* CFG_SUPPORT_PASSPOINT */ +#if CFG_SUPPORT_CFG80211_AUTH + if (wextSrchDesiredWPAIE(pucIEStart, req->ie_len, 0x30, + (PPUINT_8) & prDesiredIE)) { + if (rsnParseRsnIE(prGlueInfo->prAdapter, + (P_RSN_INFO_ELEM_T)prDesiredIE, &rRsnInfo)) { +#if CFG_SUPPORT_802_11W + /* Fill RSNE MFP Cap */ + if (rRsnInfo.u2RsnCap & ELEM_WPA_CAP_MFPC) { + prGlueInfo->rWpaInfo.u4CipherGroupMgmt + = rRsnInfo + .u4GroupMgmtKeyCipherSuite; + prGlueInfo->rWpaInfo.ucRSNMfpCap = + RSN_AUTH_MFP_OPTIONAL; + if (rRsnInfo.u2RsnCap & + ELEM_WPA_CAP_MFPR) + prGlueInfo->rWpaInfo.ucRSNMfpCap + = RSN_AUTH_MFP_REQUIRED; + } else + prGlueInfo->rWpaInfo.ucRSNMfpCap = + RSN_AUTH_MFP_DISABLED; +#endif + prGlueInfo->rWpaInfo.ucRsneLen = rRsnInfo.ucRsneLen; + + /* Fill RSNE PMKID Count and List */ + prConnSettings->rRsnInfo.u2PmkidCnt = + rRsnInfo.u2PmkidCnt; + if (rRsnInfo.u2PmkidCnt > 0) + kalMemCopy(prConnSettings + ->rRsnInfo.aucPmkidList, + rRsnInfo.aucPmkidList, + (rRsnInfo.u2PmkidCnt * RSN_PMKID_LEN)); + + } + } + +#if CFG_SUPPORT_OWE + /* Gen OWE IE */ + if (wextSrchDesiredWPAIE(pucIEStart, req->ie_len, 0xff, + (PPUINT_8) & prDesiredIE)) { + UINT_8 ucLength = (*(prDesiredIE+1)+2); + + kalMemCopy(&prGlueInfo->prAdapter + ->rWifiVar.rConnSettings.rOweInfo, + prDesiredIE, ucLength); + + DBGLOG(REQ, INFO, "DUMP OWE INFO, EID %x length %x\n", + *prDesiredIE, ucLength); + DBGLOG_MEM8(REQ, INFO, &prGlueInfo->prAdapter + ->rWifiVar.rConnSettings.rOweInfo, ucLength); + } else { + kalMemSet(&prGlueInfo->prAdapter + ->rWifiVar.rConnSettings.rOweInfo, + 0, sizeof(struct OWE_INFO_T)); + } +#endif +#endif + } + /* Fill WPA info - mfp setting */ + /* Must put after paring RSNE from upper layer + * for prGlueInfo->rWpaInfo.ucRSNMfpCap assignment + */ +#if CFG_SUPPORT_802_11W + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; + if (req->use_mfp) + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_REQUIRED; + else { + /* Change Mfp parameter from DISABLED to OPTIONAL + * if upper layer set MFPC = 1 in RSNE + * since upper layer can't bring MFP OPTIONAL information + * to driver by sme->mfp + */ + if (prGlueInfo->rWpaInfo.ucRSNMfpCap == RSN_AUTH_MFP_OPTIONAL) + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_OPTIONAL; + else if (prGlueInfo->rWpaInfo.ucRSNMfpCap == + RSN_AUTH_MFP_REQUIRED) + DBGLOG(REQ, WARN, + "mfp parameter(DISABLED) conflict with mfp cap(REQUIRED)\n"); + } + /* DBGLOG(REQ, INFO, "MFP=%d\n", prGlueInfo->rWpaInfo.u4Mfp); */ +#endif + +#if CFG_SUPPORT_CFG80211_AUTH + /*[TODO]may to check if assoc parameters change as cfg80211_auth*/ + prConnSettings->fgIsSendAssoc = TRUE; + if (!prConnSettings->fgIsConnInitialized) { + rStatus = kalIoctl(prGlueInfo, wlanoidSetBssid, + (void *) req->bss->bssid, MAC_ADDR_LEN, + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set BSSID:%x\n", rStatus); + return -EINVAL; + } + } else { /* skip join initial flow when it has been completed*/ + prStaRec = cnmGetStaRecByAddress(prGlueInfo->prAdapter, + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex, + req->bss->bssid); + + if (prStaRec) + saaSendAuthAssoc(prGlueInfo->prAdapter, prStaRec); + else + DBGLOG(REQ, WARN, + "can't send auth since can't find StaRec\n"); + } +#else + rStatus = kalIoctl(prGlueInfo, wlanoidSetBssid, + (void *)req->bss->bssid, MAC_ADDR_LEN, + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set BSSID:0x%x\n", rStatus); + return -EINVAL; + } +#endif + return 0; +} + +#if CFG_SUPPORT_NFC_BEAM_PLUS + +int mtk_cfg80211_testmode_get_scan_done(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo) +{ +#define NL80211_TESTMODE_P2P_SCANDONE_INVALID 0 +#define NL80211_TESTMODE_P2P_SCANDONE_STATUS 1 + +#ifdef CONFIG_NL80211_TESTMODE + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + INT_32 i4Status = -EINVAL, READY_TO_BEAM = 0; + + struct sk_buff *skb = NULL; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(REQ, ERROR, "mtk_cfg80211_testmode_get_scan_done\n"); +#endif + + ASSERT(wiphy); + ASSERT(prGlueInfo); + + skb = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(UINT_32)); + + /* READY_TO_BEAM = */ + /* (UINT_32)(prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsGOInitialDone) */ + /* &(!prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsScanRequest); */ + READY_TO_BEAM = 1; + /* DBGLOG(QM, TRACE, */ + /* ("NFC:GOInitialDone[%d] and P2PScanning[%d]\n", */ + /* prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsGOInitialDone, */ + /* prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsScanRequest)); */ + + if (!skb) { + DBGLOG(QM, TRACE, "%s allocate skb failed:%lx\n", __func__, rStatus); + return -ENOMEM; + } + { + u8 __tmp = 0; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_P2P_SCANDONE_INVALID, sizeof(u8), &__tmp) < 0)) { + kfree_skb(skb); + goto nla_put_failure; + } + } + { + u32 __tmp = READY_TO_BEAM; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_P2P_SCANDONE_STATUS, sizeof(u32), &__tmp) < 0)) { + kfree_skb(skb); + goto nla_put_failure; + } + } + + i4Status = cfg80211_testmode_reply(skb); + +nla_put_failure: + return i4Status; + +#else + DBGLOG(QM, WARN, "CONFIG_NL80211_TESTMODE not enabled\n"); + return -EINVAL; +#endif + +} + +#endif + +#if CFG_SUPPORT_TDLS + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for changing a station information + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int +mtk_cfg80211_change_station(struct wiphy *wiphy, struct net_device *ndev, const u8 *mac, + struct station_parameters *params) +{ + + /* return 0; */ + + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + P_GLUE_INFO_T prGlueInfo = NULL; + CMD_PEER_UPDATE_T rCmdUpdate; + WLAN_STATUS rStatus; + UINT_32 u4BufLen, u4Temp; + ADAPTER_T *prAdapter; + P_BSS_INFO_T prAisBssInfo; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, "mtk_cfg80211_change_station\n"); + return -EINVAL; + } +#endif + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + /* make up command */ + + prAdapter = prGlueInfo->prAdapter; + prAisBssInfo = prAdapter->prAisBssInfo; + + if (params == NULL) + return 0; + else if (params->supported_rates == NULL) + return 0; + + /* init */ + kalMemZero(&rCmdUpdate, sizeof(rCmdUpdate)); + kalMemCopy(rCmdUpdate.aucPeerMac, mac, 6); + + if (params->supported_rates != NULL) { + + u4Temp = params->supported_rates_len; + if (u4Temp > CMD_PEER_UPDATE_SUP_RATE_MAX) + u4Temp = CMD_PEER_UPDATE_SUP_RATE_MAX; + kalMemCopy(rCmdUpdate.aucSupRate, params->supported_rates, u4Temp); + rCmdUpdate.u2SupRateLen = u4Temp; + } + + /* + * In supplicant, only recognize WLAN_EID_QOS 46, not 0xDD WMM + * So force to support UAPSD here. + */ + rCmdUpdate.UapsdBitmap = 0x0F; /*params->uapsd_queues; */ + rCmdUpdate.UapsdMaxSp = 0; /*params->max_sp; */ + + rCmdUpdate.u2Capability = params->capability; + + if (params->ext_capab != NULL) { + + u4Temp = params->ext_capab_len; + if (u4Temp > CMD_PEER_UPDATE_EXT_CAP_MAXLEN) + u4Temp = CMD_PEER_UPDATE_EXT_CAP_MAXLEN; + kalMemCopy(rCmdUpdate.aucExtCap, params->ext_capab, u4Temp); + rCmdUpdate.u2ExtCapLen = u4Temp; + } + + if (params->ht_capa != NULL) { + + rCmdUpdate.rHtCap.u2CapInfo = params->ht_capa->cap_info; + rCmdUpdate.rHtCap.ucAmpduParamsInfo = params->ht_capa->ampdu_params_info; + rCmdUpdate.rHtCap.u2ExtHtCapInfo = params->ht_capa->extended_ht_cap_info; + rCmdUpdate.rHtCap.u4TxBfCapInfo = params->ht_capa->tx_BF_cap_info; + rCmdUpdate.rHtCap.ucAntennaSelInfo = params->ht_capa->antenna_selection_info; + kalMemCopy(rCmdUpdate.rHtCap.rMCS.arRxMask, + params->ht_capa->mcs.rx_mask, sizeof(rCmdUpdate.rHtCap.rMCS.arRxMask)); + + rCmdUpdate.rHtCap.rMCS.u2RxHighest = params->ht_capa->mcs.rx_highest; + rCmdUpdate.rHtCap.rMCS.ucTxParams = params->ht_capa->mcs.tx_params; + rCmdUpdate.fgIsSupHt = TRUE; + } + /* vht */ + + if (params->vht_capa != NULL) { + /* rCmdUpdate.rVHtCap */ + /* rCmdUpdate.rVHtCap */ + } + + /* update a TDLS peer record */ + /* sanity check */ + if ((params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) + rCmdUpdate.eStaType = STA_TYPE_DLS_PEER; + rStatus = kalIoctl(prGlueInfo, cnmPeerUpdate, &rCmdUpdate, sizeof(CMD_PEER_UPDATE_T), FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EINVAL; + /* for Ch Sw AP prohibit case */ + if (prAisBssInfo->fgTdlsIsChSwProhibited) { + /* disable TDLS ch sw function */ + + rStatus = kalIoctl(prGlueInfo, + TdlsSendChSwControlCmd, + &TdlsSendChSwControlCmd, sizeof(CMD_TDLS_CH_SW_T), FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + } + + return 0; +} +#else +int +mtk_cfg80211_change_station(struct wiphy *wiphy, struct net_device *ndev, u8 *mac, struct station_parameters *params) +{ + + /* return 0; */ + + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + P_GLUE_INFO_T prGlueInfo = NULL; + CMD_PEER_UPDATE_T rCmdUpdate; + WLAN_STATUS rStatus; + UINT_32 u4BufLen, u4Temp; + ADAPTER_T *prAdapter; + P_BSS_INFO_T prAisBssInfo; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, "mtk_cfg80211_change_station\n"); + return -EINVAL; + } +#endif + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + /* make up command */ + + prAdapter = prGlueInfo->prAdapter; + prAisBssInfo = prAdapter->prAisBssInfo; + + if (params == NULL) + return 0; + else if (params->supported_rates == NULL) + return 0; + + /* init */ + kalMemZero(&rCmdUpdate, sizeof(rCmdUpdate)); + kalMemCopy(rCmdUpdate.aucPeerMac, mac, 6); + + if (params->supported_rates != NULL) { + + u4Temp = params->supported_rates_len; + if (u4Temp > CMD_PEER_UPDATE_SUP_RATE_MAX) + u4Temp = CMD_PEER_UPDATE_SUP_RATE_MAX; + kalMemCopy(rCmdUpdate.aucSupRate, params->supported_rates, u4Temp); + rCmdUpdate.u2SupRateLen = u4Temp; + } + + /* + * In supplicant, only recognize WLAN_EID_QOS 46, not 0xDD WMM + * So force to support UAPSD here. + */ + rCmdUpdate.UapsdBitmap = 0x0F; /*params->uapsd_queues; */ + rCmdUpdate.UapsdMaxSp = 0; /*params->max_sp; */ + + rCmdUpdate.u2Capability = params->capability; + + if (params->ext_capab != NULL) { + + u4Temp = params->ext_capab_len; + if (u4Temp > CMD_PEER_UPDATE_EXT_CAP_MAXLEN) + u4Temp = CMD_PEER_UPDATE_EXT_CAP_MAXLEN; + kalMemCopy(rCmdUpdate.aucExtCap, params->ext_capab, u4Temp); + rCmdUpdate.u2ExtCapLen = u4Temp; + } + + if (params->ht_capa != NULL) { + + rCmdUpdate.rHtCap.u2CapInfo = params->ht_capa->cap_info; + rCmdUpdate.rHtCap.ucAmpduParamsInfo = params->ht_capa->ampdu_params_info; + rCmdUpdate.rHtCap.u2ExtHtCapInfo = params->ht_capa->extended_ht_cap_info; + rCmdUpdate.rHtCap.u4TxBfCapInfo = params->ht_capa->tx_BF_cap_info; + rCmdUpdate.rHtCap.ucAntennaSelInfo = params->ht_capa->antenna_selection_info; + kalMemCopy(rCmdUpdate.rHtCap.rMCS.arRxMask, + params->ht_capa->mcs.rx_mask, sizeof(rCmdUpdate.rHtCap.rMCS.arRxMask)); + + rCmdUpdate.rHtCap.rMCS.u2RxHighest = params->ht_capa->mcs.rx_highest; + rCmdUpdate.rHtCap.rMCS.ucTxParams = params->ht_capa->mcs.tx_params; + rCmdUpdate.fgIsSupHt = TRUE; + } + /* vht */ + + if (params->vht_capa != NULL) { + /* rCmdUpdate.rVHtCap */ + /* rCmdUpdate.rVHtCap */ + } + + /* update a TDLS peer record */ + /* sanity check */ + if ((params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) + rCmdUpdate.eStaType = STA_TYPE_DLS_PEER; + rStatus = kalIoctl(prGlueInfo, cnmPeerUpdate, &rCmdUpdate, sizeof(CMD_PEER_UPDATE_T), FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EINVAL; + /* for Ch Sw AP prohibit case */ + if (prAisBssInfo->fgTdlsIsChSwProhibited) { + /* disable TDLS ch sw function */ + + rStatus = kalIoctl(prGlueInfo, + TdlsSendChSwControlCmd, + &TdlsSendChSwControlCmd, sizeof(CMD_TDLS_CH_SW_T), FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + } + + return 0; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for adding a station information + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_add_station(struct wiphy *wiphy, struct net_device *ndev, + const u8 *mac, struct station_parameters *params) +{ + /* return 0; */ + + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + P_GLUE_INFO_T prGlueInfo = NULL; + CMD_PEER_ADD_T rCmdCreate; + ADAPTER_T *prAdapter; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, "mtk_cfg80211_add_station\n"); + return -EINVAL; + } +#endif + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + /* make up command */ + + prAdapter = prGlueInfo->prAdapter; + + /* init */ + kalMemZero(&rCmdCreate, sizeof(rCmdCreate)); + kalMemCopy(rCmdCreate.aucPeerMac, mac, 6); + + /* create a TDLS peer record */ + if ((params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) { + rCmdCreate.eStaType = STA_TYPE_DLS_PEER; + rStatus = kalIoctl(prGlueInfo, cnmPeerAdd, &rCmdCreate, sizeof(CMD_PEER_ADD_T), FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EINVAL; + } + + return 0; +} +#else +int mtk_cfg80211_add_station(struct wiphy *wiphy, struct net_device *ndev, u8 *mac, struct station_parameters *params) +{ + /* return 0; */ + + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + P_GLUE_INFO_T prGlueInfo = NULL; + CMD_PEER_ADD_T rCmdCreate; + ADAPTER_T *prAdapter; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, "mtk_cfg80211_add_station\n"); + return -EINVAL; + } +#endif + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + /* make up command */ + + prAdapter = prGlueInfo->prAdapter; + + /* init */ + kalMemZero(&rCmdCreate, sizeof(rCmdCreate)); + kalMemCopy(rCmdCreate.aucPeerMac, mac, 6); + + /* create a TDLS peer record */ + if ((params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) { + rCmdCreate.eStaType = STA_TYPE_DLS_PEER; + rStatus = kalIoctl(prGlueInfo, cnmPeerAdd, &rCmdCreate, sizeof(CMD_PEER_ADD_T), FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EINVAL; + } + + return 0; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for deleting a station information + * + * @param + * + * @retval 0: successful + * others: failure + * + * @other + * must implement if you have add_station(). + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +#if KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE +static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +int mtk_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, struct station_del_parameters *params) +{ + /* fgIsTDLSlinkEnable = 0; */ + + /* return 0; */ + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + + const u8 *mac = params->mac ? params->mac : bcast_addr; + P_GLUE_INFO_T prGlueInfo = NULL; + ADAPTER_T *prAdapter; + STA_RECORD_T *prStaRec; + u8 deleteMac[MAC_ADDR_LEN]; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, "mtk_cfg80211_del_station\n"); + return -EINVAL; + } +#endif + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + + /* For kernel 3.18 modification, we trasfer to local buff to query sta */ + memset(deleteMac, 0, MAC_ADDR_LEN); + memcpy(deleteMac, mac, MAC_ADDR_LEN); + + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) prAdapter->prAisBssInfo->ucBssIndex, deleteMac); + + if (prStaRec != NULL) + cnmStaRecFree(prAdapter, prStaRec); + + return 0; +} +#else +int mtk_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, const u8 *mac) +{ + /* fgIsTDLSlinkEnable = 0; */ + + /* return 0; */ + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + + P_GLUE_INFO_T prGlueInfo = NULL; + ADAPTER_T *prAdapter; + STA_RECORD_T *prStaRec; + u8 deleteMac[MAC_ADDR_LEN]; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, "mtk_cfg80211_del_station\n"); + return -EINVAL; + } +#endif + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + + /* For kernel 3.18 modification, we trasfer to local buff to query sta */ + memset(deleteMac, 0, MAC_ADDR_LEN); + memcpy(deleteMac, mac, MAC_ADDR_LEN); + + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) prAdapter->prAisBssInfo->ucBssIndex, deleteMac); + + if (prStaRec != NULL) + cnmStaRecFree(prAdapter, prStaRec); + + return 0; +} +#endif +#else +int mtk_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, u8 *mac) +{ + /* fgIsTDLSlinkEnable = 0; */ + + /* return 0; */ + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + + P_GLUE_INFO_T prGlueInfo = NULL; + ADAPTER_T *prAdapter; + STA_RECORD_T *prStaRec; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, "mtk_cfg80211_del_station\n"); + return -EINVAL; + } +#endif + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) prAdapter->prAisBssInfo->ucBssIndex, mac); + + if (prStaRec != NULL) + cnmStaRecFree(prAdapter, prStaRec); + + return 0; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to transmit a TDLS data frame from nl80211. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] +* \param[in] +* \param[in] buf includes RSN IE + FT IE + Lifetimeout IE +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE +int +mtk_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, + bool initiator, const u8 *buf, size_t len) +{ + GLUE_INFO_T *prGlueInfo; + TDLS_CMD_LINK_MGT_T rCmdMgt; + UINT_32 u4BufLen; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, "mtk_cfg80211_tdls_mgmt\n"); + return -EINVAL; + } +#endif + + /* sanity check */ + if ((wiphy == NULL) || (peer == NULL) || (buf == NULL)) + return -EINVAL; + + /* init */ + prGlueInfo = (GLUE_INFO_T *) wiphy_priv(wiphy); + if (prGlueInfo == NULL) + return -EINVAL; + + kalMemZero(&rCmdMgt, sizeof(rCmdMgt)); + rCmdMgt.u2StatusCode = status_code; + rCmdMgt.u4SecBufLen = len; + rCmdMgt.ucDialogToken = dialog_token; + rCmdMgt.ucActionCode = action_code; + kalMemCopy(&(rCmdMgt.aucPeer), peer, 6); + + if (len > TDLS_SEC_BUF_LENGTH) { + DBGLOG(REQ, WARN, "%s:len > TDLS_SEC_BUF_LENGTH\n", __func__); + return -EINVAL; + } + + kalMemCopy(&(rCmdMgt.aucSecBuf), buf, len); + + kalIoctl(prGlueInfo, TdlsexLinkMgt, &rCmdMgt, sizeof(TDLS_CMD_LINK_MGT_T), FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + return 0; + +} +#elif KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int +mtk_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, + const u8 *buf, size_t len) +{ + GLUE_INFO_T *prGlueInfo; + TDLS_CMD_LINK_MGT_T rCmdMgt; + UINT_32 u4BufLen; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, "mtk_cfg80211_tdls_mgmt\n"); + return -EINVAL; + } +#endif + + /* sanity check */ + if ((wiphy == NULL) || (peer == NULL) || (buf == NULL)) + return -EINVAL; + + /* init */ + prGlueInfo = (GLUE_INFO_T *) wiphy_priv(wiphy); + if (prGlueInfo == NULL) + return -EINVAL; + + kalMemZero(&rCmdMgt, sizeof(rCmdMgt)); + rCmdMgt.u2StatusCode = status_code; + rCmdMgt.u4SecBufLen = len; + rCmdMgt.ucDialogToken = dialog_token; + rCmdMgt.ucActionCode = action_code; + kalMemCopy(&(rCmdMgt.aucPeer), peer, 6); + kalMemCopy(&(rCmdMgt.aucSecBuf), buf, len); + + kalIoctl(prGlueInfo, TdlsexLinkMgt, &rCmdMgt, sizeof(TDLS_CMD_LINK_MGT_T), FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + return 0; + +} + +#else +int +mtk_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, + u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, const u8 *buf, size_t len) +{ + GLUE_INFO_T *prGlueInfo; + TDLS_CMD_LINK_MGT_T rCmdMgt; + UINT_32 u4BufLen; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, "mtk_cfg80211_tdls_mgmt\n"); + return -EINVAL; + } +#endif + + /* sanity check */ + if ((wiphy == NULL) || (peer == NULL) || (buf == NULL)) + return -EINVAL; + + /* init */ + prGlueInfo = (GLUE_INFO_T *) wiphy_priv(wiphy); + if (prGlueInfo == NULL) + return -EINVAL; + + kalMemZero(&rCmdMgt, sizeof(rCmdMgt)); + rCmdMgt.u2StatusCode = status_code; + rCmdMgt.u4SecBufLen = len; + rCmdMgt.ucDialogToken = dialog_token; + rCmdMgt.ucActionCode = action_code; + kalMemCopy(&(rCmdMgt.aucPeer), peer, 6); + if (len > TDLS_SEC_BUF_LENGTH) + DBGLOG(REQ, WARN, "In mtk_cfg80211_tdls_mgmt , len > TDLS_SEC_BUF_LENGTH, please check\n"); + else + kalMemCopy(&(rCmdMgt.aucSecBuf), buf, len); + + kalIoctl(prGlueInfo, TdlsexLinkMgt, &rCmdMgt, sizeof(TDLS_CMD_LINK_MGT_T), FALSE, FALSE, FALSE, + /* FALSE, //6628 -> 6630 fgIsP2pOid-> x */ + &u4BufLen); + return 0; + +} +#endif +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to hadel TDLS link from nl80211. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] +* \param[in] +* \param[in] buf includes RSN IE + FT IE + Lifetimeout IE +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, + const u8 *peer, enum nl80211_tdls_operation oper) +{ + + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4BufLen; + ADAPTER_T *prAdapter; + TDLS_CMD_LINK_OPER_T rCmdOper; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, "mtk_cfg80211_tdls_oper\n"); + return -EINVAL; + } +#endif + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rCmdOper, sizeof(rCmdOper)); + kalMemCopy(rCmdOper.aucPeerMac, peer, 6); + + rCmdOper.oper = oper; + + if (oper == NL80211_TDLS_DISABLE_LINK) { + /* [ALPS03767042] wlan: fix TDLS 5.3 test issue + * [Detail] + * Timing issue of data direct path design + * - Data sent directly through HW (new design ) + * - Command sent to FW to process (original design) + * Issue occurs while + * - Tear down packet sent by wlanHardStartXmit(), + * but not real sent out + * - CMD_ID_REMOVE_STA_RECORD sent to FW to disable TDLS link + * [Solution] + * Short-term + * - Delay TDLS disable link to let tear down data package + * to send + * Long-term + * - Enhance the TDLS flow to guarantee TX can send out + * successfully + */ + DBGLOG(TDLS, INFO, "NL80211_TDLS_DISABLE_LINK, kalMsleep(20)"); + kalMsleep(20); + } + + kalIoctl(prGlueInfo, TdlsexLinkOper, &rCmdOper, + sizeof(TDLS_CMD_LINK_OPER_T), + FALSE, FALSE, FALSE, &u4BufLen); + + return 0; +} +#else +int mtk_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, u8 *peer, enum nl80211_tdls_operation oper) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4BufLen; + ADAPTER_T *prAdapter; + TDLS_CMD_LINK_OPER_T rCmdOper; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, "mtk_cfg80211_tdls_oper\n"); + return -EINVAL; + } +#endif + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rCmdOper, sizeof(rCmdOper)); + kalMemCopy(rCmdOper.aucPeerMac, peer, 6); + + rCmdOper.oper = oper; + + if (oper == NL80211_TDLS_DISABLE_LINK) { + /* [ALPS03767042] wlan: fix TDLS 5.3 test issue + * [Detail] + * Timing issue of data direct path design + * - Data sent directly through HW (new design ) + * - Command sent to FW to process (original design) + * Issue occurs while + * - Tear down packet sent by wlanHardStartXmit(), + * but not real sent out + * - CMD_ID_REMOVE_STA_RECORD sent to FW to disable TDLS link + * [Solution] + * Short-term + * - Delay TDLS disable link to let tear down data package + * to send + * Long-term + * - Enhance the TDLS flow to guarantee TX can send out + * successfully + */ + DBGLOG(TDLS, INFO, "NL80211_TDLS_DISABLE_LINK, kalMsleep(20)"); + kalMsleep(20); + } + + kalIoctl(prGlueInfo, TdlsexLinkOper, &rCmdOper, + sizeof(TDLS_CMD_LINK_OPER_T), + FALSE, FALSE, FALSE, &u4BufLen); + + return 0; +} +#endif +#endif +#if (CFG_SUPPORT_SINGLE_SKU == 1) + +#if (CFG_BUILT_IN_DRIVER == 0) +bool is_world_regdom(char *alpha2) +{ + if (!alpha2) + return false; + + return (alpha2[0] == '0') && (alpha2[1] == '0'); +} +#endif + +enum regd_state regd_state_machine(IN struct regulatory_request *pRequest) +{ + switch (pRequest->initiator) { + case NL80211_REGDOM_SET_BY_USER: + DBGLOG(RLM, INFO, "regd_state_machine: SET_BY_USER\n"); + + return rlmDomainStateTransition(REGD_STATE_SET_COUNTRY_USER, pRequest); + + case NL80211_REGDOM_SET_BY_DRIVER: + DBGLOG(RLM, INFO, "regd_state_machine: SET_BY_DRIVER\n"); + + return rlmDomainStateTransition(REGD_STATE_SET_COUNTRY_DRIVER, pRequest); + + case NL80211_REGDOM_SET_BY_CORE: + DBGLOG(RLM, INFO, "regd_state_machine: NL80211_REGDOM_SET_BY_CORE\n"); + + return rlmDomainStateTransition(REGD_STATE_SET_WW_CORE, pRequest); + + case NL80211_REGDOM_SET_BY_COUNTRY_IE: + DBGLOG(RLM, WARN, "regd_state_machine: SET_BY_COUNTRY_IE\n"); + + return rlmDomainStateTransition(REGD_STATE_SET_COUNTRY_IE, pRequest); + + default: + return rlmDomainStateTransition(REGD_STATE_INVALID, pRequest); + } +} + + +void +mtk_apply_custom_regulatory(IN struct wiphy *pWiphy, + IN const struct ieee80211_regdomain *pRegdom) +{ + u32 band_idx, ch_idx; + struct ieee80211_supported_band *sband; + struct ieee80211_channel *chan; + + DBGLOG(RLM, INFO, "%s()\n", __func__); + + /* to reset cha->flags*/ + for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { + sband = pWiphy->bands[band_idx]; + if (!sband) + continue; + + for (ch_idx = 0; ch_idx < sband->n_channels; ch_idx++) { + chan = &sband->channels[ch_idx]; + + /*reset chan->flags*/ + chan->flags = 0; + } + + } + + /* update to kernel */ + wiphy_apply_custom_regulatory(pWiphy, pRegdom); + +#if KERNEL_VERSION(4, 3, 0) <= CFG80211_VERSION_CODE + /*Fix Kernel 4.3 and later bug for parser domain info*/ + for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { + sband = pWiphy->bands[band_idx]; + if (!sband) + continue; + + for (ch_idx = 0; ch_idx < sband->n_channels; ch_idx++) { + chan = &sband->channels[ch_idx]; + + if (chan->flags & IEEE80211_CHAN_NO_20MHZ) + chan->flags |= IEEE80211_CHAN_DISABLED; + } + } +#endif +} + +void +mtk_reg_notify(IN struct wiphy *pWiphy, + IN struct regulatory_request *pRequest) +{ + P_GLUE_INFO_T prGlueInfo; + P_ADAPTER_T prAdapter; + u8 send_cmd_request = 0; + enum regd_state old_state; + + + if (!pWiphy) { + DBGLOG(RLM, ERROR, "%s(): pWiphy = NULL.\n", __func__); + return; + } + + if (g_u4HaltFlag) { + DBGLOG(RLM, WARN, "wlan is halt, skip reg callback\n"); + return; + } + + /* + * Magic flow for driver to send inband command after kernel's calling reg_notifier callback + */ + if (!pRequest) { + + /*triggered by our driver in wlan initial process.*/ + + if (rlmDomainIsCtrlStateEqualTo(REGD_STATE_INIT)) { + if (rlmDomainIsUsingLocalRegDomainDataBase()) { + + DBGLOG(RLM, WARN, "County Code is not assigned. Use default WW.\n"); + goto DOMAIN_SEND_CMD; + + } else { + DBGLOG(RLM, ERROR, "Invalid REG state happened. state = 0x%x\n", + rlmDomainGetCtrlState()); + return; + } + } else if ((rlmDomainIsCtrlStateEqualTo(REGD_STATE_SET_WW_CORE)) + || (rlmDomainIsCtrlStateEqualTo(REGD_STATE_SET_COUNTRY_USER)) + || (rlmDomainIsCtrlStateEqualTo(REGD_STATE_SET_COUNTRY_DRIVER))) { + + send_cmd_request = 1; + + goto DOMAIN_SEND_CMD; + } else { + DBGLOG(RLM, ERROR, "Invalid REG state happened. state = 0x%x\n", rlmDomainGetCtrlState()); + return; + } + } + + + /* + * Ignore the CORE's WW setting when using local data base of regulatory rules + */ + if ((pRequest->initiator == NL80211_REGDOM_SET_BY_CORE) && +#if KERNEL_VERSION(3, 14, 0) > CFG80211_VERSION_CODE + (pWiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY)) +#else + (pWiphy->regulatory_flags & REGULATORY_CUSTOM_REG)) +#endif + return;/*Ignore the CORE's WW setting*/ + + + /* + * State machine transition + */ + DBGLOG(RLM, INFO, "request->alpha2=%s, initiator=%x, intersect=%d\n", + pRequest->alpha2, pRequest->initiator, pRequest->intersect); + + old_state = rlmDomainGetCtrlState(); + regd_state_machine(pRequest); + + if (rlmDomainGetCtrlState() == old_state) { + if (((old_state == REGD_STATE_SET_COUNTRY_USER) || (old_state == REGD_STATE_SET_COUNTRY_DRIVER)) + && (!(rlmDomainIsSameCountryCode(pRequest->alpha2, sizeof(pRequest->alpha2))))) + DBGLOG(RLM, INFO, "Set by user to NEW country code\n"); + else + /* Change to same state or same country, ignore */ + return; + } else if (rlmDomainIsCtrlStateEqualTo(REGD_STATE_INVALID)) { + DBGLOG(RLM, ERROR, "\n%s():\n---> WARNING. Transit to invalid state.\n", __func__); + DBGLOG(RLM, ERROR, "---> WARNING.\n "); + rlmDomainAssert(0); +#if 0 + return; /*error state*/ +#endif + } + + /* + * Set country code + */ + if (pRequest->initiator != NL80211_REGDOM_SET_BY_DRIVER) { + rlmDomainSetCountryCode(pRequest->alpha2, sizeof(pRequest->alpha2)); + } else { + + /*SET_BY_DRIVER*/ + + if (rlmDomainIsEfuseUsed()) { + if (!rlmDomainIsUsingLocalRegDomainDataBase()) + DBGLOG(RLM, WARN, "[WARNING!!!] Local DB must be used if country code from efuse.\n"); + } else { + /* iwpriv case */ + if (rlmDomainIsUsingLocalRegDomainDataBase() && + (!rlmDomainIsEfuseUsed())) { + /*iwpriv set country but local data base*/ + u32 country_code = rlmDomainGetTempCountryCode(); + + rlmDomainSetCountryCode((char *)&country_code, sizeof(country_code)); + } else { + /*iwpriv set country but query CRDA*/ + rlmDomainSetCountryCode(pRequest->alpha2, sizeof(pRequest->alpha2)); + } + } + } + + rlmDomainSetDfsRegion(pRequest->dfs_region); + +DOMAIN_SEND_CMD: + DBGLOG(RLM, INFO, "g_mtk_regd_control.alpha2 = 0x%x\n", rlmDomainGetCountryCode()); + + /* + * Check if using customized regulatory rule + */ + if (rlmDomainIsUsingLocalRegDomainDataBase()) { + const struct ieee80211_regdomain *pRegdom; + u32 country_code = rlmDomainGetCountryCode(); + char alpha2[4]; + + /*fetch regulatory rules from local data base*/ + alpha2[0] = country_code & 0xFF; + alpha2[1] = (country_code >> 8) & 0xFF; + alpha2[2] = (country_code >> 16) & 0xFF; + alpha2[3] = (country_code >> 24) & 0xFF; + + pRegdom = rlmDomainSearchRegdomainFromLocalDataBase(alpha2); + if (!pRegdom) { + DBGLOG(RLM, ERROR, + "%s(): Cannot find the correct country = %u\n", + __func__, rlmDomainGetCountryCode()); + + rlmDomainAssert(0); + return; + } + + + mtk_apply_custom_regulatory(pWiphy, pRegdom); + } + + + /* + * Parsing channels + */ + if (send_cmd_request) + rlmDomainParsingChannel(rlmDomainGetRefWiphy()); + else + rlmDomainParsingChannel(pWiphy);/*real regd update*/ + + + /* + * Always use the wlan GlueInfo as parameter, + * because P2P stores it as a different way + * and I do not want to make a detection about + * which wiphy, wlan wiphy or p2p wiphy is. + */ + + prGlueInfo = rlmDomainGetGlueInfo(); + + /* + * Prepare to send channel information to firmware + */ + if (!prGlueInfo) + return; /*interface is not up yet.*/ + + prAdapter = prGlueInfo->prAdapter; + if (!prAdapter) + return; /*interface is not up yet.*/ + + + /* + * Check if firmawre support single sku + */ + if (!regd_is_single_sku_en()) + return; /*no need to send information to firmware due to firmware is not supported*/ + + + /* + * Send commands to firmware + */ + prAdapter->rWifiVar.rConnSettings.u2CountryCode = (UINT_16)rlmDomainGetCountryCode(); + rlmDomainSendCmd(prAdapter, FALSE); +} + +void +cfg80211_regd_set_wiphy(IN struct wiphy *prWiphy) +{ +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) +#if KERNEL_VERSION(4, 3, 0) <= CFG80211_VERSION_CODE + u32 band_idx, ch_idx; + struct ieee80211_supported_band *sband; + struct ieee80211_channel *chan; +#endif +#endif + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, "cfg80211_regd_set_wiphy\n"); + return; + } +#endif + + /* + * register callback + */ + prWiphy->reg_notifier = mtk_reg_notify; + + + /* + * clear REGULATORY_CUSTOM_REG flag + */ +#if KERNEL_VERSION(3, 14, 0) > CFG80211_VERSION_CODE + /*tells kernel that assign WW as default*/ + prWiphy->flags &= ~(WIPHY_FLAG_CUSTOM_REGULATORY); +#else + prWiphy->regulatory_flags &= ~(REGULATORY_CUSTOM_REG); + + /*ignore the hint from IE*/ + prWiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE; + +#ifdef CFG_SUPPORT_DISABLE_BCN_HINTS + /*disable beacon hint to avoid channel flag be changed*/ + prWiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS; +#endif +#endif + + + /* + * set REGULATORY_CUSTOM_REG flag + */ +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) +#if KERNEL_VERSION(3, 14, 0) > CFG80211_VERSION_CODE + /*tells kernel that assign WW as default*/ + prWiphy->flags |= (WIPHY_FLAG_CUSTOM_REGULATORY); +#else + prWiphy->regulatory_flags |= (REGULATORY_CUSTOM_REG); +#endif + /* assigned a defautl one */ + if (rlmDomainGetLocalDefaultRegd()) { + wiphy_apply_custom_regulatory(prWiphy, rlmDomainGetLocalDefaultRegd()); + +#if KERNEL_VERSION(4, 3, 0) <= CFG80211_VERSION_CODE + /*Fix Kernel 4.3 and later bug for parser domain info*/ + for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { + sband = prWiphy->bands[band_idx]; + if (!sband) + continue; + + for (ch_idx = 0; ch_idx < sband->n_channels; ch_idx++) { + chan = &sband->channels[ch_idx]; + + if (chan->flags & IEEE80211_CHAN_NO_20MHZ) + chan->flags |= IEEE80211_CHAN_DISABLED; + } + } +#endif + + } +#endif + + + /* + * Initialize regd control information + */ + rlmDomainResetCtrlInfo(); +} + +#else +void +cfg80211_regd_set_wiphy(IN struct wiphy *prWiphy) +{ +} +#endif + +int mtk_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow) +{ + P_GLUE_INFO_T prGlueInfo; + ADAPTER_T *prAdapter; + UINT_32 u4BufLen; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) { + DBGLOG(REQ, ERROR, "mtk_cfg80211_suspend\n"); + return -EINVAL; + } +#endif + + DBGLOG(REQ, INFO, "CFG80211 suspend CB\n"); + if (!wlanGetGlueInfo()) { + DBGLOG(REQ, ERROR, "NIC does not exist!\n"); + return 0; + } + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + atomic_set(&prGlueInfo->cfgSuspend, 1); + DBGLOG(REQ, EVENT, "cfg80211 ops block\n"); + + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, WARN, "Wow:%d, WowEnable:%d, AdvPws:%d, state:%d\n", + prGlueInfo->prAdapter->rWifiVar.ucWow, prGlueInfo->prAdapter->rWowCtrl.fgWowEnable, + prGlueInfo->prAdapter->rWifiVar.ucAdvPws, + kalGetMediaStateIndicated(prGlueInfo)); + + /* 1) wifi cfg "Wow" must be true, + * 2) wow is disable + * 3) AdvPws is disable + * 4) WIfI connected => execute link down flow + */ + if (prGlueInfo->prAdapter->rWifiVar.ucWow + && !prGlueInfo->prAdapter->rWowCtrl.fgWowEnable + && !prGlueInfo->prAdapter->rWifiVar.ucAdvPws) { + if (kalGetMediaStateIndicated(prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + DBGLOG(REQ, WARN, "CFG80211 suspend link down\n"); + rStatus = kalIoctl(prGlueInfo, wlanoidLinkDown, NULL, 0, TRUE, FALSE, FALSE, &u4BufLen); + } + } + + /* In current design, only support AIS connection during suspend only. + * It need to add flow to deactive P2P (GC/GO) link during suspend flow. + * Otherwise, MT7668 would fail to enter deep sleep. + */ + p2pProcessPreSuspendFlow(prAdapter); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "cfg 80211 suspend fail!\n"); + return -EINVAL; + } + return 0; +} + +/*-----------------------------------------------------------------------*/ +/*! + * @brief This function goes through the provided ies buffer, and + * collects those non-wfa vendor specific ies into driver's + * internal buffer (non_wfa_vendor_ie_buf), to be sent in + * AssocReq in AIS mode. + * The non-wfa vendor specific ies are those with ie_id = 0xdd + * and ouis are different from wfa's oui. (i.e., it could be + * customer's vendor ie ...etc. + * + * @param prGlueInfo driver's private glueinfo + * ies ie buffer + * len length of ie + * + * @retval length of the non_wfa vendor ie + */ +/*-----------------------------------------------------------------------*/ +int cfg80211_get_non_wfa_vendor_ie(P_GLUE_INFO_T prGlueInfo, u8 *ies, int len) +{ + const u8 *pos = ies, *end = ies+len; + struct ieee80211_vendor_ie *ie; + int ie_oui = 0; + u32 *ret_len, max_len; + u8 *w_pos; + + if (!prGlueInfo || !ies || !len) + return 0; + w_pos = prGlueInfo->non_wfa_vendor_ie_buf; + ret_len = &prGlueInfo->non_wfa_vendor_ie_len; + max_len = sizeof(prGlueInfo->non_wfa_vendor_ie_buf); + + while (pos < end) { + pos = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, pos, + end - pos); + if (!pos) + break; + + ie = (struct ieee80211_vendor_ie *)pos; + + /* make sure we can access ie->len */ + BUILD_BUG_ON(offsetof(struct ieee80211_vendor_ie, len) != 1); + + if (ie->len < sizeof(*ie)) + goto cont; + + ie_oui = ie->oui[0] << 16 | ie->oui[1] << 8 | ie->oui[2]; + /* + * If oui is other than: 0x0050f2 & 0x506f9a, + * we consider it is non-wfa oui. + */ + if (ie_oui != WLAN_OUI_MICROSOFT && ie_oui != WLAN_OUI_WFA) { + /* + * if remaining buf len is capable, we copy + * this ie to the buf. + */ + if (max_len-(*ret_len) >= ie->len+2) { + DBGLOG(AIS, TRACE, + "vendor ie(len=%d, oui=0x%06x)\n", + ie->len, ie_oui); + memcpy(w_pos, pos, ie->len+2); + w_pos += (ie->len+2); + (*ret_len) += ie->len+2; + } else { + /* Otherwise we give an error msg + * and return. + */ + DBGLOG(AIS, ERROR, + "insufficient buf for vendor ie, exit!\n"); + break; + } + } +cont: + pos += 2 + ie->len; + } + return *ret_len; +} + + + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_hook_api.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_hook_api.c new file mode 100644 index 0000000000000..94f1ac7c05644 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_hook_api.c @@ -0,0 +1,3582 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + Module Name: + gl_ate_agent.c +*/ +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ +#include "precomp.h" + +#if CFG_SUPPORT_QA_TOOL +#include "gl_wext.h" +#include "gl_cfg80211.h" +#include "gl_ate_agent.h" +#include "gl_qa_agent.h" +#if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE +#include +#endif +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +enum { + ATE_LOG_RXV = 1, + ATE_LOG_RDD, + ATE_LOG_RE_CAL, + ATE_LOG_TYPE_NUM, + ATE_LOG_RXINFO, + ATE_LOG_TXDUMP, + ATE_LOG_TEST, +}; + +enum { + ATE_LOG_OFF, + ATE_LOG_ON, + ATE_LOG_DUMP, + ATE_LOG_CTRL_NUM, +}; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Enter Test Mode. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEStart(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK SetATE = %s\n", prInBuf); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetTestMode, /* pfnOidHandler */ + NULL, /* pvInfoBuf */ + 0, /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Enter ICAP Mode. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ICAPStart(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK SetATE = %s\n", prInBuf); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetTestIcapMode, /* pfnOidHandler */ + NULL, /* pvInfoBuf */ + 0, /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Abort Test Mode. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEStop(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK SetATE = %s\n", prInBuf); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAbortTestMode, /* pfnOidHandler */ + NULL, /* pvInfoBuf */ + 0, /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Start auto Tx test in packet format and the driver will enter auto Tx test mode. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEStartTX(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK SetATE = %s\n", prInBuf); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_STARTTX; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Stop TX/RX test action if the driver is in any test mode. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEStopTX(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK SetATE = %s\n", prInBuf); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_STOPTEST; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Start auto Rx test and the driver will enter auto Rx test mode. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEStartRX(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK SetATE = %s\n", prInBuf); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_STARTRX; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Stop TX/RX test action if the driver is in any test mode. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prInBuf +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEStopRX(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK SetATE = %s\n", prInBuf); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_STOPTEST; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set Channel Frequency. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4SetFreq Center frequency in unit of KHz +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetChannel(struct net_device *prNetDev, UINT_32 u4SXIdx, UINT_32 u4SetFreq) +{ + UINT_32 u4BufLen = 0; + UINT_32 i4SetChan; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + i4SetChan = nicFreq2ChannelNum(u4SetFreq); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK SetChannel=%d, Freq=%d\n", i4SetChan, u4SetFreq); + + if (u4SetFreq == 0) + return -EINVAL; + + if (u4SXIdx == 0) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_CHNL_FREQ; + rRfATInfo.u4FuncData = u4SetFreq; + } else { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_CHNL_FREQ | BIT(16); + rRfATInfo.u4FuncData = u4SetFreq; + } + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set Preamble. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4Mode depends on Rate. 0--> normal, 1--> CCK short preamble, 2: 11n MM, 3: 11n GF 4: 11ac VHT +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetPreamble(struct net_device *prNetDev, UINT_32 u4Mode) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK SetPreamble=%d\n", u4Mode); + + if (u4Mode > 4) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_PREAMBLE; + rRfATInfo.u4FuncData = u4Mode; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set Channel Bandwidth. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4BW Choose Channel Bandwidth 0: 20 / 1: 40 / 2: 80 / 3: 160 +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetSystemBW(struct net_device *prNetDev, UINT_32 u4BW) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 u4BWMapping = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK SetSystemBW=%d\n", u4BW); + + if (u4BW > 6) + return -EINVAL; + + /* BW Mapping in QA Tool + * 0: BW20 + * 1: BW40 + * 2: BW80 + * 3: BW10 + * 4: BW5 + * 5: BW160C + * 6: BW160NC + */ + /* BW Mapping in MT6632 FW + * 0: BW20 + * 1: BW40 + * 2: BW80 + * 3: BW160C + * 4: BW160NC + * 5: BW5 + * 6: BW10 + */ + if (u4BW == 0) + u4BWMapping = 0; + else if (u4BW == 1) + u4BWMapping = 1; + else if (u4BW == 2) + u4BWMapping = 2; + else if (u4BW == 3) + u4BWMapping = 6; + else if (u4BW == 4) + u4BWMapping = 5; + else if (u4BW == 5) + u4BWMapping = 3; + else if (u4BW == 6) + u4BWMapping = 4; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_CBW; + rRfATInfo.u4FuncData = u4BWMapping; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set TX Length. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4TxLength Packet length (MPDU) +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetTxLength(struct net_device *prNetDev, UINT_32 u4TxLength) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK SetTxLength=%d\n", u4TxLength); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_PKTLEN; + rRfATInfo.u4FuncData = u4TxLength; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set TX Count. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4TxCount Total packet count to send. 0 : unlimited, until stopped +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetTxCount(struct net_device *prNetDev, UINT_32 u4TxCount) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK SetTxCount=%d\n", u4TxCount); + + if (u4TxCount < 0) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_PKTCNT; + rRfATInfo.u4FuncData = u4TxCount; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set TX Inter-Packet Guard. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4TxIPG In unit of us. The min value is 19us and max value is 2314us. +* \ It will be round-up to (19+9n) us. +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetTxIPG(struct net_device *prNetDev, UINT_32 u4TxIPG) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK SetTxIPG=%d\n", u4TxIPG); + + if (u4TxIPG > 2314 || u4TxIPG < 19) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_PKTINTERVAL; + rRfATInfo.u4FuncData = u4TxIPG; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set WF0 TX Power. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4TxPower0 Tx Gain of RF. The value is signed absolute power +* (2's complement representation) in unit of 0.5 dBm. +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetTxPower0(struct net_device *prNetDev, UINT_32 u4TxPower0) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK SetTxPower0=0x%02x\n", u4TxPower0); + + if (u4TxPower0 > 0x3F) { + u4TxPower0 += 128; + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK Negative Power =0x%02x\n", u4TxPower0); + } + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_POWER; + rRfATInfo.u4FuncData = u4TxPower0; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set Per Packet BW. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4BW 0: 20 / 1: 40 / 2: 80 / 3: 160 +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetPerPacketBW(struct net_device *prNetDev, UINT_32 u4BW) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 u4BWMapping = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK SetPerPacketBW=%d\n", u4BW); + + if (u4BW > 6) + return -EINVAL; + + /* BW Mapping in QA Tool + * 0: BW20 + * 1: BW40 + * 2: BW80 + * 3: BW10 + * 4: BW5 + * 5: BW160C + * 6: BW160NC + */ + /* BW Mapping in MT6632 FW + * 0: BW20 + * 1: BW40 + * 2: BW80 + * 3: BW160C + * 4: BW160NC + * 5: BW5 + * 6: BW10 + */ + if (u4BW == 0) + u4BWMapping = 0; + else if (u4BW == 1) + u4BWMapping = 1; + else if (u4BW == 2) + u4BWMapping = 2; + else if (u4BW == 3) + u4BWMapping = 6; + else if (u4BW == 4) + u4BWMapping = 5; + else if (u4BW == 5) + u4BWMapping = 3; + else if (u4BW == 6) + u4BWMapping = 4; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_DBW; + rRfATInfo.u4FuncData = u4BWMapping; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Primary Channel Setting. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4PrimaryCh The range is from 0~7 +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEPrimarySetting(struct net_device *prNetDev, UINT_32 u4PrimaryCh) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK PrimarySetting=%d\n", u4PrimaryCh); + + if (u4PrimaryCh > 7) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_PRIMARY_CH; + rRfATInfo.u4FuncData = u4PrimaryCh; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set TX Guard Interval. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4SetTxGi 0: Normal GI, 1: Short GI +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetTxGi(struct net_device *prNetDev, UINT_32 u4SetTxGi) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK SetTxGi=%d\n", u4SetTxGi); + + if (u4SetTxGi != 0 && u4SetTxGi != 1) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_GI; + rRfATInfo.u4FuncData = u4SetTxGi; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set TX Path. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4Tx_path 0: All Tx, 1: WF0, 2: WF1, 3: WF0+WF1 +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetTxPath(struct net_device *prNetDev, UINT_32 u4Tx_path) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK u4Tx_path=%d\n", u4Tx_path); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TX_PATH; + rRfATInfo.u4FuncData = u4Tx_path; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set TX Payload Fix/Random. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4Stbc 0: Disable , 1 : Enable +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetTxPayLoad(struct net_device *prNetDev, UINT_32 u4Gen_payload_rule, UINT_8 ucPayload) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK rule=%d, len =0x%x\n", u4Gen_payload_rule, ucPayload); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_PAYLOAD; + rRfATInfo.u4FuncData = ((u4Gen_payload_rule << 16) | ucPayload); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set TX STBC. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4Stbc 0: Disable , 1 : Enable +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetTxSTBC(struct net_device *prNetDev, UINT_32 u4Stbc) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK u4Stbc=%d\n", u4Stbc); + + if (u4Stbc > 1) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_STBC; + rRfATInfo.u4FuncData = u4Stbc; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set TX Nss. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4Nss 1/2 +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetTxVhtNss(struct net_device *prNetDev, UINT_32 u4VhtNss) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK u4Nss=%d\n", u4VhtNss); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_NSS; + rRfATInfo.u4FuncData = u4VhtNss; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set Rate. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4Rate Rate +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetRate(struct net_device *prNetDev, UINT_32 u4Rate) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK SetRate=0x%08x\n", u4Rate); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_RATE; + rRfATInfo.u4FuncData = u4Rate; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set Encode Mode. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4Ldpc 0: BCC / 1: LDPC +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetEncodeMode(struct net_device *prNetDev, UINT_32 u4Ldpc) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK SetEncodeMode=%d\n", u4Ldpc); + + if (u4Ldpc != 0 && u4Ldpc != 1) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ENCODE_MODE; + rRfATInfo.u4FuncData = u4Ldpc; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set iBF Enable. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4iBF 0: disable / 1: enable +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetiBFEnable(struct net_device *prNetDev, UINT_32 u4iBF) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK SetiBFEnable=%d\n", u4iBF); + + if (u4iBF != 0 && u4iBF != 1) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_IBF_ENABLE; + rRfATInfo.u4FuncData = u4iBF; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set eBF Enable. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4eBF 0: disable / 1: enable +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESeteBFEnable(struct net_device *prNetDev, UINT_32 u4eBF) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK SeteBFEnable=%d\n", u4eBF); + + if (u4eBF != 0 && u4eBF != 1) + return -EINVAL; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_EBF_ENABLE; + rRfATInfo.u4FuncData = u4eBF; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set MAC Address. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4Type Address type +* \param[in] ucAddr Address ready to set +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetMACAddress(struct net_device *prNetDev, UINT_32 u4Type, PUINT_8 ucAddr) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, ERROR, "MT6632 : QA_ATE_HOOK SetMACAddress Type = %d, Addr = %02x:%02x:%02x:%02x:%02x:%02x\n", + u4Type, ucAddr[0], ucAddr[1], ucAddr[2], ucAddr[3], ucAddr[4], ucAddr[5]); + +#if 1 + rRfATInfo.u4FuncIndex = u4Type; + memcpy(&rRfATInfo.u4FuncData, ucAddr, 4); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; +#endif + rRfATInfo.u4FuncIndex = u4Type | BIT(18); + memset(&rRfATInfo.u4FuncData, 0, sizeof(rRfATInfo.u4FuncData)); + memcpy(&rRfATInfo.u4FuncData, ucAddr + 4, 2); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for RX Vector Dump. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4Type +* \param[in] u4On_off +* \param[in] u4Size +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATELogOnOff(struct net_device *prNetDev, UINT_32 u4Type, UINT_32 u4On_off, UINT_32 u4Size) +{ + INT_32 i4Status = 0, i, i4TargetLength = 0, i4MaxDumpRXVCnt = 500; + UINT_32 u4BufLen = 0, rxv; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATELogOnOff\n"); + + switch (u4Type) { + case ATE_LOG_RXV: + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATELogOnOff : ATE_LOG_RXV\n\n"); + break; + case ATE_LOG_RDD: + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATELogOnOff : ATE_LOG_RDD\n\n"); + break; + case ATE_LOG_RE_CAL: + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATELogOnOff : ATE_LOG_RE_CAL\n\n"); + break; + case ATE_LOG_RXINFO: + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATELogOnOff : ATE_LOG_RXINFO\n\n"); + break; + case ATE_LOG_TXDUMP: + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATELogOnOff : ATE_LOG_TXDUMP\n\n"); + break; + case ATE_LOG_TEST: + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATELogOnOff : ATE_LOG_TEST\n\n"); + break; + default: + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK log type %d not supported\n\n", u4Type); + } + + if ((u4On_off == ATE_LOG_DUMP) && (u4Type == ATE_LOG_RXV)) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_RESULT_INFO; + rRfATInfo.u4FuncData = RF_AT_FUNCID_RXV_DUMP; + + i4Status = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, + &rRfATInfo, sizeof(rRfATInfo), TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + i4TargetLength = rRfATInfo.u4FuncData * 36; + DBGLOG(RFTEST, ERROR, "MT6632 : QA_ATE_HOOK Get RX Vector Total size = %d\n", i4TargetLength); + + if (i4TargetLength >= (i4MaxDumpRXVCnt * 36)) + i4TargetLength = (i4MaxDumpRXVCnt * 36); + } else { + DBGLOG(RFTEST, ERROR, "MT6632 : QA_ATE_HOOK Get RX Vector Total Size Error!!!!\n\n"); + } + + TOOL_PRINTLOG(RFTEST, ERROR, "[LOG DUMP START]\n"); + + for (i = 0; i < i4TargetLength; i += 4) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_RXV_DUMP; + rRfATInfo.u4FuncData = i; + + i4Status = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, + &rRfATInfo, sizeof(rRfATInfo), TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + rxv = rRfATInfo.u4FuncData; + + if (i % 36 == 0) + TOOL_PRINTLOG(RFTEST, ERROR, + "%%[RXV DUMP START][%d]\n", + (i / 36) + 1); + + TOOL_PRINTLOG(RFTEST, ERROR, "[RXVD%d]%08x\n", ((i % 36) / 4) + 1, rxv); + + if (((i % 36) / 4) + 1 == 9) + TOOL_PRINTLOG(RFTEST, ERROR, "[RXV DUMP END]\n"); + } + } + + TOOL_PRINTLOG(RFTEST, ERROR, "[LOG DUMP END]\n"); + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Reset Counter. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEResetTXRXCounter(struct net_device *prNetDev) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATEResetTXRXCounter\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_RESETTXRXCOUNTER; + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set DBDC Band Index. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4BandIdx Band Index Number ready to set +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetDBDCBandIndex(struct net_device *prNetDev, UINT_32 u4BandIdx) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATESetDBDCBandIndex\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_DBDC_BAND_IDX; + rRfATInfo.u4FuncData = u4BandIdx; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set Band. (2G or 5G) +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] i4Band Band to set +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetBand(struct net_device *prNetDev, INT_32 i4Band) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATESetBand\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_BAND; + rRfATInfo.u4FuncData = i4Band; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set Tx Tone Type. (2G or 5G) +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] i4ToneType Set Single or Two Tone. +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetTxToneType(struct net_device *prNetDev, INT_32 i4ToneType) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATESetTxToneType\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TONE_TYPE; + rRfATInfo.u4FuncData = i4ToneType; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set Tx Tone Frequency. (DC/5M/10M/20M/40M) +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] i4ToneFreq Set Tx Tone Frequency. +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetTxToneBW(struct net_device *prNetDev, INT_32 i4ToneFreq) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATESetTxToneBW\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TONE_BW; + rRfATInfo.u4FuncData = i4ToneFreq; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set Tx Tone DC Offset. (DC Offset I / DC Offset Q) +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] i4DcOffsetI Set Tx Tone DC Offset I. +* \param[in] i4DcOffsetQ Set Tx Tone DC Offset Q. +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetTxToneDCOffset(struct net_device *prNetDev, INT_32 i4DcOffsetI, INT_32 i4DcOffsetQ) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATESetTxToneDCOffset\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TONE_DC_OFFSET; + rRfATInfo.u4FuncData = i4DcOffsetQ << 16 | i4DcOffsetI; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set Tx Tone Power. (RF and Digital) +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] i4AntIndex +* \param[in] i4RF_Power +* \param[in] i4Digi_Power +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetDBDCTxTonePower(struct net_device *prNetDev, INT_32 i4AntIndex, INT_32 i4RF_Power, INT_32 i4Digi_Power) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATESetDBDCTxTonePower\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TONE_RF_GAIN; + rRfATInfo.u4FuncData = i4AntIndex << 16 | i4RF_Power; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TONE_DIGITAL_GAIN; + rRfATInfo.u4FuncData = i4AntIndex << 16 | i4Digi_Power; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Start Tx Tone. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] i4Control Start or Stop TX Tone. +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEDBDCTxTone(struct net_device *prNetDev, INT_32 i4Control) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATEDBDCTxTone\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (i4Control) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_SINGLE_TONE; + } else { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_STOPTEST; + } + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set TX Mac Header. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u4BandIdx Band Index Number ready to set +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetMacHeader(struct net_device *prNetDev, UINT_32 u4FrameCtrl, UINT_32 u4DurationID, UINT_32 u4SeqCtrl) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATESetMacHeader\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MAC_HEADER; + rRfATInfo.u4FuncData = u4FrameCtrl || (u4DurationID << 16); + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_SEQ_CTRL; + rRfATInfo.u4FuncData = u4SeqCtrl; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for IRR Set ADC. (RF_AT_FUNCID_SET_ADC) +* +* \param[in] prNetDev Pointer to the Net Device +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATE_IRRSetADC(struct net_device *prNetDev, + UINT_32 u4WFIdx, + UINT_32 u4ChFreq, + UINT_32 u4BW, UINT_32 u4Sx, UINT_32 u4Band, UINT_32 u4RunType, UINT_32 u4FType) +{ + UINT_32 u4BufLen = 0, i = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 au4Param[7]; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATE_IRRSetADC\n"); + + if (u4BW == 3 || u4BW == 4 || u4BW > 5) + return -EINVAL; + + if (u4BW == 5) /* For BW160, UI will pass "5" */ + u4BW = 3; + + au4Param[0] = u4ChFreq; + au4Param[1] = u4WFIdx; + au4Param[2] = u4BW; + au4Param[3] = u4Sx; + au4Param[4] = u4Band; + au4Param[5] = u4RunType; + au4Param[6] = u4FType; + + for (i = 0; i < 8; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ADC | (i << 16); + if (i < 7) + rRfATInfo.u4FuncData = au4Param[i]; + else + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for IRR Set RX Gain. (RF_AT_FUNCID_SET_RX_GAIN) +* +* \param[in] prNetDev Pointer to the Net Device +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATE_IRRSetRxGain(struct net_device *prNetDev, + UINT_32 u4PgaLpfg, UINT_32 u4Lna, UINT_32 u4Band, UINT_32 u4WF_inx, UINT_32 u4Rfdgc) +{ + UINT_32 u4BufLen = 0, i = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 au4Param[5]; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATE_IRRSetRxGain\n"); + + au4Param[0] = u4PgaLpfg; + au4Param[1] = u4Lna; + au4Param[2] = u4Band; + au4Param[3] = u4WF_inx; + au4Param[4] = u4Rfdgc; + + for (i = 0; i < 6; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_RX_GAIN | (i << 16); + if (i < 5) + rRfATInfo.u4FuncData = au4Param[i]; + else + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for IRR Set TTG. (RF_AT_FUNCID_SET_TTG) +* +* \param[in] prNetDev Pointer to the Net Device +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATE_IRRSetTTG(struct net_device *prNetDev, + UINT_32 u4TTGPwrIdx, UINT_32 u4ChFreq, UINT_32 u4FIToneFreq, UINT_32 u4Band) +{ + UINT_32 u4BufLen = 0, i = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 au4Param[4]; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATE_IRRSetTTG\n"); + + au4Param[0] = u4ChFreq; + au4Param[1] = u4FIToneFreq; + au4Param[2] = u4TTGPwrIdx; + au4Param[3] = u4Band; + + for (i = 0; i < 5; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TTG | (i << 16); + if (i < 4) + rRfATInfo.u4FuncData = au4Param[i]; + else + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for IRR Set TTG On/Off. (RF_AT_FUNCID_TTG_ON_OFF) +* +* \param[in] prNetDev Pointer to the Net Device +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATE_IRRSetTrunOnTTG(struct net_device *prNetDev, UINT_32 u4TTGOnOff, UINT_32 u4Band, UINT_32 u4WF_inx) +{ + UINT_32 u4BufLen = 0, i = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 au4Param[3]; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATE_IRRSetTrunOnTTG\n"); + + au4Param[0] = u4TTGOnOff; + au4Param[1] = u4Band; + au4Param[2] = u4WF_inx; + + for (i = 0; i < 4; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_TTG_ON_OFF | (i << 16); + if (i < 3) + rRfATInfo.u4FuncData = au4Param[i]; + else + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for IRR Set TTG On/Off. +* +* \param[in] prNetDev Pointer to the Net Device +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATE_TMRSetting(struct net_device *prNetDev, + UINT_32 u4Setting, UINT_32 u4Version, UINT_32 u4MPThres, UINT_32 u4MPIter) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATE_TMRSetting\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TMR_ROLE; + rRfATInfo.u4FuncData = u4Setting; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TMR_MODULE; + rRfATInfo.u4FuncData = u4Version; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TMR_DBM; + rRfATInfo.u4FuncData = u4MPThres; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TMR_ITER; + rRfATInfo.u4FuncData = u4MPIter; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for MPS Setting. (Set Seq Data) +* +* \param[in] prNetDev Pointer to the Net Device +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEMPSSetSeqData(struct net_device *prNetDev, + UINT_32 u4TestNum, UINT_32 *pu4Phy, UINT_32 u4Band) +{ + UINT_32 u4BufLen = 0, i; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATEMPSSetSeqData\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_SIZE; + rRfATInfo.u4FuncData = u4TestNum; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + for (i = 0 ; i < u4TestNum ; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_SEQ_DATA | (i << 16); + rRfATInfo.u4FuncData = pu4Phy[i]; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for MPS Setting. (Set Payload Length) +* +* \param[in] prNetDev Pointer to the Net Device +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEMPSSetPayloadLength(struct net_device *prNetDev, + UINT_32 u4TestNum, UINT_32 *pu4Length, UINT_32 u4Band) +{ + UINT_32 u4BufLen = 0, i; + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATEMPSSetPayloadLength\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + for (i = 0 ; i < u4TestNum ; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_PAYLOAD_LEN | (i << 16); + rRfATInfo.u4FuncData = pu4Length[i]; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for MPS Setting. (Set Packet Count) +* +* \param[in] prNetDev Pointer to the Net Device +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEMPSSetPacketCount(struct net_device *prNetDev, + UINT_32 u4TestNum, UINT_32 *pu4PktCnt, UINT_32 u4Band) +{ + UINT_32 u4BufLen = 0, i; + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATEMPSSetPacketCount\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + for (i = 0 ; i < u4TestNum ; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_PKT_CNT | (i << 16); + rRfATInfo.u4FuncData = pu4PktCnt[i]; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for MPS Setting. (Set Power Gain) +* +* \param[in] prNetDev Pointer to the Net Device +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEMPSSetPowerGain(struct net_device *prNetDev, + UINT_32 u4TestNum, UINT_32 *pu4PwrGain, UINT_32 u4Band) +{ + UINT_32 u4BufLen = 0, i; + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATEMPSSetPowerGain\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + for (i = 0 ; i < u4TestNum ; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_PWR_GAIN | (i << 16); + rRfATInfo.u4FuncData = pu4PwrGain[i]; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for MPS Setting. (Set NSS) +* +* \param[in] prNetDev Pointer to the Net Device +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEMPSSetNss(struct net_device *prNetDev, + UINT_32 u4TestNum, UINT_32 *pu4Nss, UINT_32 u4Band) +{ + UINT_32 u4BufLen = 0, i; + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATEMPSSetNss\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + for (i = 0 ; i < u4TestNum ; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_NSS | (i << 16); + rRfATInfo.u4FuncData = pu4Nss[i]; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for MPS Setting. (Set NSS) +* +* \param[in] prNetDev Pointer to the Net Device +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEMPSSetPerpacketBW(struct net_device *prNetDev, + UINT_32 u4TestNum, UINT_32 *pu4PerPktBW, UINT_32 u4Band) +{ + UINT_32 u4BufLen = 0, i; + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK MT_ATEMPSSetPerpacketBW\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + for (i = 0 ; i < u4TestNum ; i++) { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_MPS_PACKAGE_BW | (i << 16); + rRfATInfo.u4FuncData = pu4PerPktBW[i]; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Start RDD. +* +* \param[in] prNetDev Pointer to the Net Device +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATERDDStart(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK SetATE = %s\n", prInBuf); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_RDD; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Stop RDD. +* +* \param[in] prNetDev Pointer to the Net Device +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATERDDStop(struct net_device *prNetDev, UINT_8 *prInBuf) +{ + UINT_32 u4BufLen = 0; + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_ATE_HOOK SetATE = %s\n", prInBuf); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_RDD_OFF; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Write Efuse. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u2Offset Efuse offset +* \param[in] u2Content Efuse content +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATEWriteEfuse(struct net_device *prNetDev, UINT_16 u2Offset, UINT_16 u2Content) +{ + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_ACCESS_EFUSE_T rAccessEfuseInfoRead, rAccessEfuseInfoWrite; + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS i4Status = WLAN_STATUS_SUCCESS; + UINT_8 u4Index = 0, u4Loop = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + kalMemSet(&rAccessEfuseInfoRead, 0, sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)); + kalMemSet(&rAccessEfuseInfoWrite, 0, sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)); + + + + /* Read */ + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT HQA_WriteBulkEEPROM Read\n"); + kalMemSet(&rAccessEfuseInfoRead, 0, sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)); + rAccessEfuseInfoRead.u4Address = (u2Offset / EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + i4Status = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfoRead, + sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T), TRUE, TRUE, TRUE, &u4BufLen); + + + /* Write */ + kalMemSet(&rAccessEfuseInfoWrite, 0, sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)); + u4Index = u2Offset % EFUSE_BLOCK_SIZE; + + if (u4Index > EFUSE_BLOCK_SIZE - 2) + return -EINVAL; + + prGlueInfo->prAdapter->aucEepromVaule[u4Index] = u2Content; + prGlueInfo->prAdapter->aucEepromVaule[u4Index+1] = u2Content >> 8 & 0xff; + + kalMemCopy(rAccessEfuseInfoWrite.aucData, prGlueInfo->prAdapter->aucEepromVaule, 16); + + for (u4Loop = 0; u4Loop < (EFUSE_BLOCK_SIZE); u4Loop++) { + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT aucEepromVaule u4Loop=%d u4Value=%x\n", + u4Loop, prGlueInfo->prAdapter->aucEepromVaule[u4Loop]); + + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT rAccessEfuseInfoWrite.aucData u4Loop=%d u4Value=%x\n", + u4Loop, rAccessEfuseInfoWrite.aucData[u4Loop]); + } + + rAccessEfuseInfoWrite.u4Address = (u2Offset / EFUSE_BLOCK_SIZE)*EFUSE_BLOCK_SIZE; + + i4Status = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseWrite, + &rAccessEfuseInfoWrite, + sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T), FALSE, TRUE, TRUE, &u4BufLen); + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set Tx Target Power. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] u2TxTargetPower TxTarget Power +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetTxTargetPower(struct net_device *prNetDev, UINT_8 ucTxTargetPower) +{ + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_SET_TX_TARGET_POWER_T rSetTxTargetPwr; + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS i4Status = WLAN_STATUS_SUCCESS; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + kalMemSet(&rSetTxTargetPwr, 0, sizeof(PARAM_CUSTOM_SET_TX_TARGET_POWER_T)); + + + /* Set Target Power Base */ + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT Set Tx Target Power= %x dbm\n", ucTxTargetPower); + rSetTxTargetPwr.ucTxTargetPwr = ucTxTargetPower; + + i4Status = kalIoctl(prGlueInfo, + wlanoidQuerySetTxTargetPower, + &rSetTxTargetPwr, + sizeof(PARAM_CUSTOM_SET_TX_TARGET_POWER_T), FALSE, FALSE, TRUE, &u4BufLen); + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +#if (CFG_SUPPORT_DFS_MASTER == 1) +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set Rdd Report. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] ucDbdcIdx Dbdc Index +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetRddReport(struct net_device *prNetDev, UINT_8 ucDbdcIdx) +{ + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_SET_RDD_REPORT_T rSetRddReport; + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS i4Status = WLAN_STATUS_SUCCESS; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + kalMemSet(&rSetRddReport, 0, sizeof(PARAM_CUSTOM_SET_RDD_REPORT_T)); + + /* Set Rdd Report */ + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT Set RDD Report - Band: %d\n", ucDbdcIdx); + rSetRddReport.ucDbdcIdx = ucDbdcIdx; + + i4Status = kalIoctl(prGlueInfo, + wlanoidQuerySetRddReport, + &rSetRddReport, + sizeof(PARAM_CUSTOM_SET_RDD_REPORT_T), FALSE, FALSE, TRUE, &u4BufLen); + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Hook API for Set Radar Detect Mode. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] ucRadarDetectMode Radar Detect Mode +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If kalIoctl return nonzero. +* \retval -EINVAL If invalid argument. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 MT_ATESetRadarDetectMode(struct net_device *prNetDev, UINT_8 ucRadarDetectMode) +{ + UINT_32 u4BufLen = 0; + struct PARAM_CUSTOM_SET_RADAR_DETECT_MODE rSetRadarDetectMode; + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS i4Status = WLAN_STATUS_SUCCESS; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + kalMemSet(&rSetRadarDetectMode, 0, sizeof(struct PARAM_CUSTOM_SET_RADAR_DETECT_MODE)); + + /* Set Rdd Report */ + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT Set Radar Detect Mode: %d\n", ucRadarDetectMode); + rSetRadarDetectMode.ucRadarDetectMode = ucRadarDetectMode; + + i4Status = kalIoctl(prGlueInfo, + wlanoidQuerySetRadarDetectMode, + &rSetRadarDetectMode, + sizeof(struct PARAM_CUSTOM_SET_RADAR_DETECT_MODE), FALSE, FALSE, TRUE, &u4BufLen); + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return i4Status; +} + +#endif + +#if CFG_SUPPORT_TX_BF +INT_32 TxBfProfileTag_InValid(struct net_device *prNetDev, P_PFMU_PROFILE_TAG1 prPfmuTag1, UINT_8 ucInValid) +{ + INT_32 i4Status = 0; + + prPfmuTag1->rField.ucInvalidProf = ucInValid; + + return i4Status; +} + +INT_32 TxBfProfileTag_PfmuIdx(struct net_device *prNetDev, P_PFMU_PROFILE_TAG1 prPfmuTag1, UINT_8 ucProfileIdx) +{ + INT_32 i4Status = 0; + + prPfmuTag1->rField.ucProfileID = ucProfileIdx; + + return i4Status; +} + +INT_32 TxBfProfileTag_TxBfType(struct net_device *prNetDev, P_PFMU_PROFILE_TAG1 prPfmuTag1, UINT_8 ucBFType) +{ + INT_32 i4Status = 0; + + prPfmuTag1->rField.ucTxBf = ucBFType; + + return i4Status; +} + +INT_32 TxBfProfileTag_DBW(struct net_device *prNetDev, P_PFMU_PROFILE_TAG1 prPfmuTag1, UINT_8 ucBW) +{ + INT_32 i4Status = 0; + + prPfmuTag1->rField.ucDBW = ucBW; + + return i4Status; +} + +INT_32 TxBfProfileTag_SuMu(struct net_device *prNetDev, P_PFMU_PROFILE_TAG1 prPfmuTag1, UINT_8 ucSuMu) +{ + INT_32 i4Status = 0; + + prPfmuTag1->rField.ucSU_MU = ucSuMu; + + return i4Status; +} + +INT_32 TxBfProfileTag_Mem(struct net_device *prNetDev, + P_PFMU_PROFILE_TAG1 prPfmuTag1, PUINT_8 aucMemAddrColIdx, PUINT_8 aucMemAddrRowIdx) +{ + INT_32 i4Status = 0; + + prPfmuTag1->rField.ucMemAddr1ColIdx = aucMemAddrColIdx[0]; + prPfmuTag1->rField.ucMemAddr1RowIdx = aucMemAddrRowIdx[0]; + prPfmuTag1->rField.ucMemAddr2ColIdx = aucMemAddrColIdx[1]; + prPfmuTag1->rField.ucMemAddr2RowIdx = aucMemAddrRowIdx[1] & 0x1F; + prPfmuTag1->rField.ucMemAddr2RowIdxMsb = aucMemAddrRowIdx[1] >> 5; + prPfmuTag1->rField.ucMemAddr3ColIdx = aucMemAddrColIdx[2]; + prPfmuTag1->rField.ucMemAddr3RowIdx = aucMemAddrRowIdx[2]; + prPfmuTag1->rField.ucMemAddr4ColIdx = aucMemAddrColIdx[3]; + prPfmuTag1->rField.ucMemAddr4RowIdx = aucMemAddrRowIdx[3]; + + return i4Status; +} + +INT_32 TxBfProfileTag_Matrix(struct net_device *prNetDev, + P_PFMU_PROFILE_TAG1 prPfmuTag1, + UINT_8 ucNrow, + UINT_8 ucNcol, UINT_8 ucNgroup, UINT_8 ucLM, UINT_8 ucCodeBook, UINT_8 ucHtcExist) +{ + INT_32 i4Status = 0; + + prPfmuTag1->rField.ucNrow = ucNrow; + prPfmuTag1->rField.ucNcol = ucNcol; + prPfmuTag1->rField.ucNgroup = ucNgroup; + prPfmuTag1->rField.ucLM = ucLM; + prPfmuTag1->rField.ucCodeBook = ucCodeBook; + prPfmuTag1->rField.ucHtcExist = ucHtcExist; + + return i4Status; +} + +INT_32 TxBfProfileTag_SNR(struct net_device *prNetDev, + P_PFMU_PROFILE_TAG1 prPfmuTag1, + UINT_8 ucSNR_STS0, UINT_8 ucSNR_STS1, UINT_8 ucSNR_STS2, UINT_8 ucSNR_STS3) +{ + INT_32 i4Status = 0; + + prPfmuTag1->rField.ucSNR_STS0 = ucSNR_STS0; + prPfmuTag1->rField.ucSNR_STS1 = ucSNR_STS1; + prPfmuTag1->rField.ucSNR_STS2 = ucSNR_STS2; + prPfmuTag1->rField.ucSNR_STS3 = ucSNR_STS3; + + return i4Status; +} + +INT_32 TxBfProfileTag_SmtAnt(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucSmartAnt) +{ + INT_32 i4Status = 0; + + prPfmuTag2->rField.u2SmartAnt = ucSmartAnt; + + return i4Status; +} + +INT_32 TxBfProfileTag_SeIdx(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucSeIdx) +{ + INT_32 i4Status = 0; + + prPfmuTag2->rField.ucSEIdx = ucSeIdx; + + return i4Status; +} + +INT_32 TxBfProfileTag_RmsdThd(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucRmsdThrd) +{ + INT_32 i4Status = 0; + + prPfmuTag2->rField.ucRMSDThd = ucRmsdThrd; + + return i4Status; +} + +INT_32 TxBfProfileTag_McsThd(struct net_device *prNetDev, + P_PFMU_PROFILE_TAG2 prPfmuTag2, PUINT_8 pMCSThLSS, PUINT_8 pMCSThSSS) +{ + INT_32 i4Status = 0; + + prPfmuTag2->rField.ucMCSThL1SS = pMCSThLSS[0]; + prPfmuTag2->rField.ucMCSThS1SS = pMCSThSSS[0]; + prPfmuTag2->rField.ucMCSThL2SS = pMCSThLSS[1]; + prPfmuTag2->rField.ucMCSThS2SS = pMCSThSSS[1]; + prPfmuTag2->rField.ucMCSThL3SS = pMCSThLSS[2]; + prPfmuTag2->rField.ucMCSThS3SS = pMCSThSSS[2]; + + return i4Status; +} + +INT_32 TxBfProfileTag_TimeOut(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucTimeOut) +{ + INT_32 i4Status = 0; + + prPfmuTag2->rField.uciBfTimeOut = ucTimeOut; + + return i4Status; +} + +INT_32 TxBfProfileTag_DesiredBW(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucDesiredBW) +{ + INT_32 i4Status = 0; + + prPfmuTag2->rField.uciBfDBW = ucDesiredBW; + + return i4Status; +} + +INT_32 TxBfProfileTag_DesiredNc(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucDesiredNc) +{ + INT_32 i4Status = 0; + + prPfmuTag2->rField.uciBfNcol = ucDesiredNc; + + return i4Status; +} + +INT_32 TxBfProfileTag_DesiredNr(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucDesiredNr) +{ + INT_32 i4Status = 0; + + prPfmuTag2->rField.uciBfNrow = ucDesiredNr; + + return i4Status; +} + +INT_32 TxBfProfileTagWrite(struct net_device *prNetDev, + P_PFMU_PROFILE_TAG1 prPfmuTag1, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 profileIdx) +{ + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_TXBF_ACTION_STRUCT_T rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : au4RawData[0] = 0x%08x\n", prPfmuTag1->au4RawData[0]); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : au4RawData[1] = 0x%08x\n", prPfmuTag1->au4RawData[1]); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : au4RawData[2] = 0x%08x\n", prPfmuTag1->au4RawData[2]); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : au4RawData[3] = 0x%08x\n", prPfmuTag1->au4RawData[3]); + + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag2 : au4RawData[0] = 0x%08x\n", prPfmuTag2->au4RawData[0]); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag2 : au4RawData[1] = 0x%08x\n", prPfmuTag2->au4RawData[1]); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag2 : au4RawData[2] = 0x%08x\n", prPfmuTag2->au4RawData[2]); + + DBGLOG(RFTEST, ERROR, + "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucProfileID= %d\n", prPfmuTag1->rField.ucProfileID); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucTxBf= %d\n", prPfmuTag1->rField.ucTxBf); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucDBW= %d\n", prPfmuTag1->rField.ucDBW); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucSU_MU= %d\n", prPfmuTag1->rField.ucSU_MU); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucInvalidProf= %d\n", + prPfmuTag1->rField.ucInvalidProf); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucRMSD= %d\n", prPfmuTag1->rField.ucRMSD); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucMemAddr1ColIdx= %d\n", + prPfmuTag1->rField.ucMemAddr1ColIdx); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucMemAddr1RowIdx= %d\n", + prPfmuTag1->rField.ucMemAddr1RowIdx); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucMemAddr2ColIdx= %d\n", + prPfmuTag1->rField.ucMemAddr2ColIdx); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucMemAddr2RowIdx= %d\n", + prPfmuTag1->rField.ucMemAddr2RowIdx); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucMemAddr2RowIdxMsb= %d\n", + prPfmuTag1->rField.ucMemAddr2RowIdxMsb); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucMemAddr3ColIdx= %d\n", + prPfmuTag1->rField.ucMemAddr3ColIdx); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucMemAddr3RowIdx= %d\n", + prPfmuTag1->rField.ucMemAddr3RowIdx); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucMemAddr4ColIdx= %d\n", + prPfmuTag1->rField.ucMemAddr4ColIdx); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucMemAddr4RowIdx= %d\n", + prPfmuTag1->rField.ucMemAddr4RowIdx); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucReserved= %d\n", prPfmuTag1->rField.ucReserved); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucNrow= %d\n", prPfmuTag1->rField.ucNrow); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucNcol= %d\n", prPfmuTag1->rField.ucNcol); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucNgroup= %d\n", prPfmuTag1->rField.ucNgroup); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucLM= %d\n", prPfmuTag1->rField.ucLM); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucCodeBook= %d\n", prPfmuTag1->rField.ucCodeBook); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucHtcExist= %d\n", prPfmuTag1->rField.ucHtcExist); + DBGLOG(RFTEST, ERROR, + "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucReserved1= %d\n", prPfmuTag1->rField.ucReserved1); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucSNR_STS0= %d\n", prPfmuTag1->rField.ucSNR_STS0); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucSNR_STS1= %d\n", prPfmuTag1->rField.ucSNR_STS1); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucSNR_STS2= %d\n", prPfmuTag1->rField.ucSNR_STS2); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucSNR_STS3= %d\n", prPfmuTag1->rField.ucSNR_STS3); + DBGLOG(RFTEST, ERROR, + "MT6632 prPfmuTag1 : prPfmuTag1->rField.ucIBfLnaIdx= %d\n", prPfmuTag1->rField.ucIBfLnaIdx); + + DBGLOG(RFTEST, ERROR, + "MT6632 prPfmuTag2 : prPfmuTag2->rField.u2SmartAnt = %d\n", prPfmuTag2->rField.u2SmartAnt); + DBGLOG(RFTEST, ERROR, + "MT6632 prPfmuTag2 : prPfmuTag2->rField.ucReserved0 = %d\n", prPfmuTag2->rField.ucReserved0); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag2 : prPfmuTag2->rField.ucSEIdx = %d\n", prPfmuTag2->rField.ucSEIdx); + DBGLOG(RFTEST, ERROR, "MT6632 prPfmuTag2 : prPfmuTag2->rField.ucRMSDThd = %d\n", prPfmuTag2->rField.ucRMSDThd); + DBGLOG(RFTEST, ERROR, + "MT6632 prPfmuTag2 : prPfmuTag2->rField.ucReserved1 = %d\n", prPfmuTag2->rField.ucReserved1); + DBGLOG(RFTEST, ERROR, + "MT6632 prPfmuTag2 : prPfmuTag2->rField.ucMCSThL1SS = %d\n", prPfmuTag2->rField.ucMCSThL1SS); + DBGLOG(RFTEST, ERROR, + "MT6632 prPfmuTag2 : prPfmuTag2->rField.ucMCSThS1SS = %d\n", prPfmuTag2->rField.ucMCSThS1SS); + DBGLOG(RFTEST, ERROR, + "MT6632 prPfmuTag2 : prPfmuTag2->rField.ucMCSThL2SS = %d\n", prPfmuTag2->rField.ucMCSThL2SS); + DBGLOG(RFTEST, ERROR, + "MT6632 prPfmuTag2 : prPfmuTag2->rField.ucMCSThS2SS = %d\n", prPfmuTag2->rField.ucMCSThS2SS); + DBGLOG(RFTEST, ERROR, + "MT6632 prPfmuTag2 : prPfmuTag2->rField.ucMCSThL3SS = %d\n", prPfmuTag2->rField.ucMCSThL3SS); + DBGLOG(RFTEST, ERROR, + "MT6632 prPfmuTag2 : prPfmuTag2->rField.ucMCSThS3SS = %d\n", prPfmuTag2->rField.ucMCSThS3SS); + DBGLOG(RFTEST, ERROR, + "MT6632 prPfmuTag2 : prPfmuTag2->rField.uciBfTimeOut = %d\n", + prPfmuTag2->rField.uciBfTimeOut); + DBGLOG(RFTEST, ERROR, + "MT6632 prPfmuTag2 : prPfmuTag2->rField.ucReserved2 = %d\n", prPfmuTag2->rField.ucReserved2); + DBGLOG(RFTEST, ERROR, + "MT6632 prPfmuTag2 : prPfmuTag2->rField.ucReserved3 = %d\n", prPfmuTag2->rField.ucReserved3); + DBGLOG(RFTEST, ERROR, + "MT6632 prPfmuTag2 : prPfmuTag2->rField.ucReserved4 = %d\n", prPfmuTag2->rField.ucReserved4); + DBGLOG(RFTEST, ERROR, + "MT6632 prPfmuTag2 : prPfmuTag2->rField.uciBfDBW = %d\n", prPfmuTag2->rField.uciBfDBW); + DBGLOG(RFTEST, ERROR, + "MT6632 prPfmuTag2 : prPfmuTag2->rField.uciBfNcol = %d\n", prPfmuTag2->rField.uciBfNcol); + DBGLOG(RFTEST, ERROR, + "MT6632 prPfmuTag2 : prPfmuTag2->rField.uciBfNrow = %d\n", prPfmuTag2->rField.uciBfNrow); + DBGLOG(RFTEST, ERROR, + "MT6632 prPfmuTag2 : prPfmuTag2->rField.u2Reserved5 = %d\n", prPfmuTag2->rField.u2Reserved5); + + rTxBfActionInfo.rProfileTagWrite.ucTxBfCategory = BF_PFMU_TAG_WRITE; + rTxBfActionInfo.rProfileTagWrite.ucPfmuId = profileIdx; + memcpy(&rTxBfActionInfo.rProfileTagWrite.ucBuffer, prPfmuTag1, sizeof(PFMU_PROFILE_TAG1)); + memcpy(&rTxBfActionInfo.rProfileTagWrite.ucBuffer[16], prPfmuTag2, sizeof(PFMU_PROFILE_TAG2)); + + i4Status = kalIoctl(prGlueInfo, + wlanoidTxBfAction, + &rTxBfActionInfo, sizeof(rTxBfActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 TxBfProfileTagRead(struct net_device *prNetDev, UINT_8 profileIdx, UINT_8 fgBFer) +{ + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_TXBF_ACTION_STRUCT_T rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfileTagRead : profileIdx = 0x%08x\n", profileIdx); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfileTagRead : fgBFer = 0x%08x\n", fgBFer); + + rTxBfActionInfo.rProfileTagRead.ucTxBfCategory = BF_PFMU_TAG_READ; + rTxBfActionInfo.rProfileTagRead.ucProfileIdx = profileIdx; + rTxBfActionInfo.rProfileTagRead.fgBfer = fgBFer; + + i4Status = kalIoctl(prGlueInfo, + wlanoidTxBfAction, &rTxBfActionInfo, sizeof(rTxBfActionInfo), TRUE, TRUE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 StaRecCmmUpdate(struct net_device *prNetDev, + UINT_8 ucWlanId, UINT_8 ucBssId, UINT_8 u4Aid, UINT_8 aucMacAddr[MAC_ADDR_LEN] +) +{ + CMD_STAREC_COMMON_T rStaRecCmm; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + INT_32 i4Status = 0; + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rStaRecCmm, sizeof(CMD_STAREC_COMMON_T)); + /* Tag assignment */ + rStaRecCmm.u2Tag = STA_REC_BASIC; + rStaRecCmm.u2Length = sizeof(CMD_STAREC_COMMON_T); + + /* content */ + kalMemCopy(rStaRecCmm.aucPeerMacAddr, aucMacAddr, MAC_ADDR_LEN); + rStaRecCmm.ucConnectionState = TRUE; + rStaRecCmm.u2AID = u4Aid; + rStaRecCmm.u2Reserve1 = ucWlanId; + + DBGLOG(RFTEST, ERROR, "ucWlanId = 0x%08x\n", ucWlanId); + + i4Status = kalIoctl(prGlueInfo, + wlanoidStaRecUpdate, + &rStaRecCmm, sizeof(CMD_STAREC_COMMON_T), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 StaRecBfUpdate(struct net_device *prNetDev, + STA_REC_BF_UPD_ARGUMENT rStaRecBfUpdArg, UINT_8 aucMemRow[4], UINT_8 aucMemCol[4] +) +{ + CMD_STAREC_BF rStaRecBF; + /* PARAM_CUSTOM_STA_REC_UPD_STRUCT_T rStaRecUpdateInfo = {0}; */ + /* P_STA_RECORD_T prStaRec; */ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + INT_32 i4Status = 0; + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rStaRecBF, sizeof(CMD_STAREC_BF)); + /* Tag assignment */ + rStaRecBF.u2Tag = STA_REC_BF; + rStaRecBF.u2Length = sizeof(CMD_STAREC_BF); + rStaRecBF.ucReserved[0] = rStaRecBfUpdArg.u4BssId; + rStaRecBF.ucReserved[1] = rStaRecBfUpdArg.u4WlanId; + /* content */ + rStaRecBF.rTxBfPfmuInfo.u2PfmuId = rStaRecBfUpdArg.u4PfmuId; + rStaRecBF.rTxBfPfmuInfo.ucTotMemRequire = rStaRecBfUpdArg.u4TotalMemReq; + rStaRecBF.rTxBfPfmuInfo.ucMemRequire20M = rStaRecBfUpdArg.u4MemReq20M; + rStaRecBF.rTxBfPfmuInfo.ucMemRow0 = aucMemRow[0]; + rStaRecBF.rTxBfPfmuInfo.ucMemCol0 = aucMemCol[0]; + rStaRecBF.rTxBfPfmuInfo.ucMemRow1 = aucMemRow[1]; + rStaRecBF.rTxBfPfmuInfo.ucMemCol1 = aucMemCol[1]; + rStaRecBF.rTxBfPfmuInfo.ucMemRow2 = aucMemRow[2]; + rStaRecBF.rTxBfPfmuInfo.ucMemCol2 = aucMemCol[2]; + rStaRecBF.rTxBfPfmuInfo.ucMemRow3 = aucMemRow[3]; + rStaRecBF.rTxBfPfmuInfo.ucMemCol3 = aucMemCol[3]; + /* 0 : SU, 1 : MU */ + rStaRecBF.rTxBfPfmuInfo.fgSU_MU = rStaRecBfUpdArg.u4SuMu; + /* 0: iBF, 1: eBF */ + rStaRecBF.rTxBfPfmuInfo.fgETxBfCap = rStaRecBfUpdArg.u4eTxBfCap; + /* 0: legacy, 1: OFDM, 2: HT, 4: VHT */ + rStaRecBF.rTxBfPfmuInfo.ucSoundingPhy = 1; + rStaRecBF.rTxBfPfmuInfo.ucNdpaRate = rStaRecBfUpdArg.u4NdpaRate; + rStaRecBF.rTxBfPfmuInfo.ucNdpRate = rStaRecBfUpdArg.u4NdpRate; + rStaRecBF.rTxBfPfmuInfo.ucReptPollRate = rStaRecBfUpdArg.u4ReptPollRate; + /* 0: legacy, 1: OFDM, 2: HT, 4: VHT */ + rStaRecBF.rTxBfPfmuInfo.ucTxMode = rStaRecBfUpdArg.u4TxMode; + rStaRecBF.rTxBfPfmuInfo.ucNc = rStaRecBfUpdArg.u4Nc; + rStaRecBF.rTxBfPfmuInfo.ucNr = rStaRecBfUpdArg.u4Nr; + /* 0 : 20M, 1 : 40M, 2 : 80M, 3 : 80 + 80M */ + rStaRecBF.rTxBfPfmuInfo.ucCBW = rStaRecBfUpdArg.u4Bw; + rStaRecBF.rTxBfPfmuInfo.ucSEIdx = rStaRecBfUpdArg.u4SpeIdx; + /* Default setting */ + rStaRecBF.rTxBfPfmuInfo.u2SmartAnt = 0; + rStaRecBF.rTxBfPfmuInfo.uciBfTimeOut = 0; + rStaRecBF.rTxBfPfmuInfo.uciBfDBW = 0; + rStaRecBF.rTxBfPfmuInfo.uciBfNcol = 0; + rStaRecBF.rTxBfPfmuInfo.uciBfNrow = 0; + + i4Status = kalIoctl(prGlueInfo, + wlanoidStaRecBFUpdate, &rStaRecBF, sizeof(CMD_STAREC_BF), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 DevInfoUpdate(struct net_device *prNetDev, UINT_8 ucOwnMacIdx, UINT_8 fgBand, UINT_8 aucMacAddr[MAC_ADDR_LEN]) +{ + CMD_DEVINFO_ACTIVE_T rDevInfo; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + INT_32 i4Status = 0; + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rDevInfo, sizeof(CMD_DEVINFO_ACTIVE_T)); + /* Tag assignment */ + rDevInfo.u2Tag = DEV_INFO_ACTIVE; + rDevInfo.u2Length = sizeof(CMD_DEVINFO_ACTIVE_T); + /* content */ + kalMemCopy(rDevInfo.aucOwnMacAddr, aucMacAddr, MAC_ADDR_LEN); + rDevInfo.ucActive = TRUE; + rDevInfo.ucBandNum = 0; + rDevInfo.aucReserve[0] = ucOwnMacIdx; + + i4Status = kalIoctl(prGlueInfo, + wlanoidDevInfoActive, + &rDevInfo, sizeof(CMD_DEVINFO_ACTIVE_T), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 BssInfoUpdate(struct net_device *prNetDev, UINT_8 ucOwnMacIdx, UINT_8 ucBssIdx, UINT_8 ucBssId[MAC_ADDR_LEN]) +{ + CMD_BSSINFO_BASIC_T rBssInfo; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + INT_32 i4Status = 0; + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rBssInfo, sizeof(CMD_BSSINFO_BASIC_T)); + /* Tag assignment */ + rBssInfo.u2Tag = BSS_INFO_BASIC; + rBssInfo.u2Length = sizeof(CMD_BSSINFO_BASIC_T); + /* content */ + kalMemCopy(rBssInfo.aucBSSID, ucBssId, MAC_ADDR_LEN); + rBssInfo.ucBcMcWlanidx = ucBssIdx; + rBssInfo.ucActive = TRUE; + rBssInfo.u4NetworkType = NETWORK_TYPE_AIS; + rBssInfo.u2BcnInterval = 100; + rBssInfo.ucDtimPeriod = 1; + + i4Status = kalIoctl(prGlueInfo, + wlanoidBssInfoBasic, &rBssInfo, sizeof(CMD_BSSINFO_BASIC_T), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 TxBfProfileDataRead(struct net_device *prNetDev, + UINT_8 profileIdx, UINT_8 fgBFer, UINT_8 ucSubCarrIdxMsb, UINT_8 ucSubCarrIdxLsb) +{ + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_TXBF_ACTION_STRUCT_T rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfileDataRead : ucPfmuIdx = 0x%08x\n", profileIdx); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfileDataRead : fgBFer = 0x%08x\n", fgBFer); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfileDataRead : ucSubCarrIdxMsb = 0x%08x\n", ucSubCarrIdxMsb); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfileDataRead : ucSubCarrIdxLsb = 0x%08x\n", ucSubCarrIdxLsb); + + rTxBfActionInfo.rProfileDataRead.ucTxBfCategory = BF_PROFILE_READ; + rTxBfActionInfo.rProfileDataRead.ucPfmuIdx = profileIdx; + rTxBfActionInfo.rProfileDataRead.fgBFer = fgBFer; + rTxBfActionInfo.rProfileDataRead.ucSubCarrIdxMsb = ucSubCarrIdxMsb; + rTxBfActionInfo.rProfileDataRead.ucSubCarrIdxLsb = ucSubCarrIdxLsb; + + i4Status = kalIoctl(prGlueInfo, + wlanoidTxBfAction, &rTxBfActionInfo, sizeof(rTxBfActionInfo), TRUE, TRUE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 TxBfProfileDataWrite(struct net_device *prNetDev, + UINT_8 profileIdx, + UINT_16 u2SubCarrIdx, UINT_16 au2Phi[6], UINT_8 aucPsi[6], UINT_8 aucDSnr[4] +) +{ + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_TXBF_ACTION_STRUCT_T rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfileDataWrite : ucPfmuIdx = 0x%08x\n", profileIdx); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfileDataWrite : u2SubCarrIdx = 0x%08x\n", u2SubCarrIdx); + + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfileDataWrite : au2Phi[0] = 0x%08x\n", au2Phi[0]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfileDataWrite : au2Phi[1] = 0x%08x\n", au2Phi[1]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfileDataWrite : au2Phi[2] = 0x%08x\n", au2Phi[2]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfileDataWrite : au2Phi[3] = 0x%08x\n", au2Phi[3]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfileDataWrite : au2Phi[4] = 0x%08x\n", au2Phi[4]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfileDataWrite : au2Phi[5] = 0x%08x\n", au2Phi[5]); + + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfileDataWrite : aucPsi[0] = 0x%08x\n", aucPsi[0]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfileDataWrite : aucPsi[1] = 0x%08x\n", aucPsi[1]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfileDataWrite : aucPsi[2] = 0x%08x\n", aucPsi[2]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfileDataWrite : aucPsi[3] = 0x%08x\n", aucPsi[3]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfileDataWrite : aucPsi[4] = 0x%08x\n", aucPsi[4]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfileDataWrite : aucPsi[5] = 0x%08x\n", aucPsi[5]); + + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfileDataWrite : aucDSnr[0] = 0x%x\n", aucDSnr[0]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfileDataWrite : aucDSnr[1] = 0x%x\n", aucDSnr[1]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfileDataWrite : aucDSnr[2] = 0x%x\n", aucDSnr[2]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfileDataWrite : aucDSnr[3] = 0x%x\n", aucDSnr[3]); + + rTxBfActionInfo.rProfileDataWrite.ucTxBfCategory = BF_PROFILE_WRITE; + rTxBfActionInfo.rProfileDataWrite.ucPfmuIdx = profileIdx; + rTxBfActionInfo.rProfileDataWrite.u2SubCarrIdxLsb = u2SubCarrIdx; + rTxBfActionInfo.rProfileDataWrite.u2SubCarrIdxMsb = u2SubCarrIdx >> 8; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2Phi11 = au2Phi[0]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2Phi21 = au2Phi[1]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2Phi31 = au2Phi[2]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2Phi22 = au2Phi[3]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2Phi32 = au2Phi[4]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2Phi33 = au2Phi[5]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.ucPsi21 = aucPsi[0]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.ucPsi31 = aucPsi[1]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.ucPsi41 = aucPsi[2]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.ucPsi32 = aucPsi[3]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.ucPsi42 = aucPsi[4]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.ucPsi43 = aucPsi[5]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2dSNR00 = aucDSnr[0]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2dSNR01 = aucDSnr[1]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2dSNR02 = aucDSnr[2]; + rTxBfActionInfo.rProfileDataWrite.rTxBfPfmuData.rField.u2dSNR03 = aucDSnr[3]; + + i4Status = kalIoctl(prGlueInfo, + wlanoidTxBfAction, + &rTxBfActionInfo, sizeof(rTxBfActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 TxBfProfilePnRead(struct net_device *prNetDev, UINT_8 profileIdx) +{ + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_TXBF_ACTION_STRUCT_T rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfilePnRead : ucPfmuIdx = 0x%08x\n", profileIdx); + + rTxBfActionInfo.rProfilePnRead.ucTxBfCategory = BF_PN_READ; + rTxBfActionInfo.rProfilePnRead.ucPfmuIdx = profileIdx; + + i4Status = kalIoctl(prGlueInfo, + wlanoidTxBfAction, + &rTxBfActionInfo, sizeof(rTxBfActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 TxBfProfilePnWrite(struct net_device *prNetDev, UINT_8 profileIdx, UINT_16 u2bw, UINT_16 au2XSTS[12]) +{ + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_TXBF_ACTION_STRUCT_T rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfilePnWrite : ucPfmuIdx = 0x%08x\n", profileIdx); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfilePnWrite : u2bw = 0x%08x\n", u2bw); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfilePnWrite : au2XSTS[0] = 0x%08x\n", au2XSTS[0]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfilePnWrite : au2XSTS[1] = 0x%08x\n", au2XSTS[1]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfilePnWrite : au2XSTS[2] = 0x%08x\n", au2XSTS[2]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfilePnWrite : au2XSTS[3] = 0x%08x\n", au2XSTS[3]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfilePnWrite : au2XSTS[4] = 0x%08x\n", au2XSTS[4]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfilePnWrite : au2XSTS[5] = 0x%08x\n", au2XSTS[5]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfilePnWrite : au2XSTS[6] = 0x%08x\n", au2XSTS[6]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfilePnWrite : au2XSTS[7] = 0x%08x\n", au2XSTS[7]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfilePnWrite : au2XSTS[8] = 0x%08x\n", au2XSTS[8]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfilePnWrite : au2XSTS[9] = 0x%08x\n", au2XSTS[9]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfilePnWrite : au2XSTS[10] = 0x%08x\n", au2XSTS[10]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfProfilePnWrite : au2XSTS[11] = 0x%08x\n", au2XSTS[11]); + + rTxBfActionInfo.rProfilePnWrite.ucTxBfCategory = BF_PN_WRITE; + rTxBfActionInfo.rProfilePnWrite.ucPfmuIdx = profileIdx; + rTxBfActionInfo.rProfilePnWrite.u2bw = u2bw; + memcpy(&rTxBfActionInfo.rProfilePnWrite.ucBuf[0], &au2XSTS[0], + sizeof(UINT_16)*12); + + i4Status = kalIoctl(prGlueInfo, + wlanoidTxBfAction, + &rTxBfActionInfo, sizeof(rTxBfActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 TxBfSounding(struct net_device *prNetDev, UINT_8 ucSuMu, /* 0/1/2/3 */ + UINT_8 ucNumSta, /* 00~04 */ + UINT_8 ucSndInterval, /* 00~FF */ + UINT_8 ucWLan0, /* 00~7F */ + UINT_8 ucWLan1, /* 00~7F */ + UINT_8 ucWLan2, /* 00~7F */ + + UINT_8 ucWLan3 /* 00~7F */ +) +{ + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_TXBF_ACTION_STRUCT_T rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, "MT6632 TxBfSounding : ucSuMu = 0x%08x\n", ucSuMu); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfSounding : ucNumSta = 0x%08x\n", ucNumSta); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfSounding : ucSndInterval = 0x%08x\n", ucSndInterval); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfSounding : ucWLan0 = 0x%08x\n", ucWLan0); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfSounding : ucWLan1 = 0x%08x\n", ucWLan1); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfSounding : ucWLan2 = 0x%08x\n", ucWLan2); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfSounding : ucWLan3 = 0x%08x\n", ucWLan3); + + switch (ucSuMu) { + case MU_SOUNDING: + + case MU_PERIODIC_SOUNDING: + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding.rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucCmdCategoryID = + BF_SOUNDING_ON; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding.rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucSuMuSndMode = + ucSuMu; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding.rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucStaNum = + ucNumSta; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding. + rExtCmdExtBfMuSndPeriodicTriggerCtrl.u4SoundingInterval = ucSndInterval; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding.rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucWlanId[0] = + ucWLan0; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding.rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucWlanId[1] = + ucWLan1; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding.rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucWlanId[2] = + ucWLan2; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding.rExtCmdExtBfMuSndPeriodicTriggerCtrl.ucWlanId[3] = + ucWLan3; + break; + + case SU_SOUNDING: + case SU_PERIODIC_SOUNDING: + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding.rExtCmdExtBfSndPeriodicTriggerCtrl.ucCmdCategoryID = + BF_SOUNDING_ON; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding.rExtCmdExtBfSndPeriodicTriggerCtrl.ucSuMuSndMode = + ucSuMu; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding.rExtCmdExtBfSndPeriodicTriggerCtrl.u4SoundingInterval = + ucSndInterval; + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding.rExtCmdExtBfSndPeriodicTriggerCtrl.ucWlanIdx = ucWLan0; + break; + default: + break; + } + + i4Status = kalIoctl(prGlueInfo, + wlanoidTxBfAction, + &rTxBfActionInfo, sizeof(rTxBfActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 TxBfSoundingStop(struct net_device *prNetDev) +{ + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_TXBF_ACTION_STRUCT_T rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, "MT6632 TxBfSoundingStop\n"); + + rTxBfActionInfo.rTxBfSoundingStop.ucTxBfCategory = BF_SOUNDING_OFF; + rTxBfActionInfo.rTxBfSoundingStop.ucSndgStop = 1; + + i4Status = kalIoctl(prGlueInfo, + wlanoidTxBfAction, + &rTxBfActionInfo, sizeof(rTxBfActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 TxBfTxApply(struct net_device *prNetDev, UINT_8 ucWlanId, UINT_8 fgETxBf, UINT_8 fgITxBf, UINT_8 fgMuTxBf) +{ + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_TXBF_ACTION_STRUCT_T rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, + "MT6632 TxBfTxApply : ucWlanId = 0x%08x, fgETxBf = 0x%08x,fgITxBf = 0x%08x,fgMuTxBf = 0x%08x\n", + ucWlanId, fgETxBf, fgITxBf, fgMuTxBf); + + rTxBfActionInfo.rTxBfTxApply.ucTxBfCategory = BF_DATA_PACKET_APPLY; + rTxBfActionInfo.rTxBfTxApply.ucWlanId = ucWlanId; + rTxBfActionInfo.rTxBfTxApply.fgETxBf = fgETxBf; + rTxBfActionInfo.rTxBfTxApply.fgITxBf = fgITxBf; + rTxBfActionInfo.rTxBfTxApply.fgMuTxBf = fgMuTxBf; + + i4Status = kalIoctl(prGlueInfo, + wlanoidTxBfAction, + &rTxBfActionInfo, sizeof(rTxBfActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 TxBfPfmuMemAlloc(struct net_device *prNetDev, UINT_8 ucSuMuMode, UINT_8 ucWlanIdx) +{ + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_TXBF_ACTION_STRUCT_T rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, + "MT6632 TxBfPfmuMemAlloc : ucSuMuMode = 0x%08x, ucWlanIdx = 0x%08x\n", ucSuMuMode, ucWlanIdx); + + rTxBfActionInfo.rTxBfPfmuMemAlloc.ucTxBfCategory = BF_PFMU_MEM_ALLOCATE; + rTxBfActionInfo.rTxBfPfmuMemAlloc.ucSuMuMode = ucSuMuMode; + rTxBfActionInfo.rTxBfPfmuMemAlloc.ucWlanIdx = ucWlanIdx; + + i4Status = kalIoctl(prGlueInfo, + wlanoidTxBfAction, + &rTxBfActionInfo, sizeof(rTxBfActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 TxBfPfmuMemRelease(struct net_device *prNetDev, UINT_8 ucWlanId) +{ + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_TXBF_ACTION_STRUCT_T rTxBfActionInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, "MT6632 TxBfPfmuMemRelease : ucWlanId = 0x%08x\n", ucWlanId); + + rTxBfActionInfo.rTxBfPfmuMemRls.ucTxBfCategory = BF_PFMU_MEM_RELEASE; + rTxBfActionInfo.rTxBfPfmuMemRls.ucWlanId = ucWlanId; + + i4Status = kalIoctl(prGlueInfo, + wlanoidTxBfAction, + &rTxBfActionInfo, sizeof(rTxBfActionInfo), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +INT_32 TxBfBssInfoUpdate(struct net_device *prNetDev, UINT_8 ucOwnMacIdx, UINT_8 ucBssIdx, UINT_8 ucBssId[MAC_ADDR_LEN]) +{ + INT_32 i4Status = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + /* UINT_32 u4BufLen = 0; */ + PARAM_CUSTOM_TXBF_ACTION_STRUCT_T rTxBfActionInfo; + P_BSS_INFO_T prBssInfo; + + kalMemZero(&rTxBfActionInfo, sizeof(rTxBfActionInfo)); + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(RFTEST, ERROR, "MT6632 TxBfBssInfoUpdate : ucOwnMacIdx = 0x%08x\n", ucOwnMacIdx); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfBssInfoUpdate : ucBssIdx = 0x%08x\n", ucBssIdx); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfBssInfoUpdate : ucBssId[0] = 0x%08x\n", ucBssId[0]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfBssInfoUpdate : ucBssId[1] = 0x%08x\n", ucBssId[1]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfBssInfoUpdate : ucBssId[2] = 0x%08x\n", ucBssId[2]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfBssInfoUpdate : ucBssId[3] = 0x%08x\n", ucBssId[3]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfBssInfoUpdate : ucBssId[4] = 0x%08x\n", ucBssId[4]); + DBGLOG(RFTEST, ERROR, "MT6632 TxBfBssInfoUpdate : ucBssId[5] = 0x%08x\n", ucBssId[5]); + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + if (!prBssInfo) + return WLAN_STATUS_FAILURE; + prBssInfo->ucOwnMacIndex = ucOwnMacIdx; + memcpy(&prBssInfo->aucBSSID, &ucBssId, MAC_ADDR_LEN); + + nicUpdateBss(prAdapter, prBssInfo->ucBssIndex); + + return i4Status; +} + +/* iwpriv ra0 set assoc=[mac:hh:hh:hh:hh:hh:hh]-[wtbl:dd]- +*[ownmac:dd]-[type:xx]-[mode:mmm]-[bw:dd]-[nss:ss]-[maxrate:kkk_dd] +*/ +INT_32 TxBfManualAssoc(struct net_device *prNetDev, UINT_8 aucMac[MAC_ADDR_LEN], UINT_8 ucType, /* no use */ + UINT_8 ucWtbl, + UINT_8 ucOwnmac, + UINT_8 ucMode, + UINT_8 ucBw, + UINT_8 ucNss, UINT_8 ucPfmuId, UINT_8 ucMarate, UINT_8 ucSpeIdx, UINT_8 ucRca2, UINT_8 ucRv) +{ + CMD_MANUAL_ASSOC_STRUCT_T rManualAssoc; + /* P_STA_RECORD_T prStaRec; */ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + INT_32 i4Status = 0; + /* UINT_8 ucNsts; + * UINT_32 i; + */ + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rManualAssoc, sizeof(CMD_MANUAL_ASSOC_STRUCT_T)); + /* Tag assignment */ + rManualAssoc.u2Tag = STA_REC_MAUNAL_ASSOC; + rManualAssoc.u2Length = sizeof(CMD_MANUAL_ASSOC_STRUCT_T); + /* content */ + kalMemCopy(rManualAssoc.aucMac, aucMac, MAC_ADDR_LEN); + rManualAssoc.ucType = ucType; + rManualAssoc.ucWtbl = ucWtbl; + rManualAssoc.ucOwnmac = ucOwnmac; + rManualAssoc.ucMode = ucMode; + rManualAssoc.ucBw = ucBw; + rManualAssoc.ucNss = ucNss; + rManualAssoc.ucPfmuId = ucPfmuId; + rManualAssoc.ucMarate = ucMarate; + rManualAssoc.ucSpeIdx = ucSpeIdx; + rManualAssoc.ucaid = ucRca2; + +#if 0 + switch (ucMode) { + case 0: /* abggnanac */ + prStaRec->ucDesiredPhyTypeSet = aucPhyCfg2PhyTypeSet[PHY_TYPE_SET_802_11ABGNAC]; + break; + case 1: /* bggnan */ + prStaRec->ucDesiredPhyTypeSet = aucPhyCfg2PhyTypeSet[PHY_TYPE_SET_802_11ABGN]; + break; + case 2: /* aanac */ + prStaRec->ucDesiredPhyTypeSet = aucPhyCfg2PhyTypeSet[PHY_TYPE_SET_802_11ANAC]; + break; + default: + prStaRec->ucDesiredPhyTypeSet = aucPhyCfg2PhyTypeSet[PHY_TYPE_SET_802_11ABGNAC]; + break; + } + + prStaRec->rTxBfPfmuStaInfo.u2PfmuId = ucPfmuId; + + memcpy(prStaRec->aucMacAddr, aucMac, MAC_ADDR_LEN); + + i4Status = kalIoctl(prGlueInfo, + wlanoidStaRecUpdate, + &rStaRecUpdateInfo, + sizeof(PARAM_CUSTOM_STA_REC_UPD_STRUCT_T), FALSE, FALSE, TRUE, &u4BufLen); +#endif + + i4Status = kalIoctl(prGlueInfo, + wlanoidManualAssoc, + &rManualAssoc, sizeof(CMD_MANUAL_ASSOC_STRUCT_T), FALSE, FALSE, TRUE, &u4BufLen); + + return i4Status; +} + +#endif +#endif /*CFG_SUPPORT_QA_TOOL */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_init.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_init.c new file mode 100644 index 0000000000000..008390bf2e964 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_init.c @@ -0,0 +1,3256 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_init.c#11 +*/ + +/*! \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. +*/ + + +/******************************************************************************* +* C O M P I L E 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" +#if CFG_SUPPORT_AGPS_ASSIST +#include "gl_kal.h" +#endif +#include "gl_vendor.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* #define MAX_IOREQ_NUM 10 */ +struct semaphore g_halt_sem; +int g_u4HaltFlag; + +struct wireless_dev *gprWdev; +/******************************************************************************* +* 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); + +/* MODULE_LICENSE("MTK Propietary"); */ +MODULE_LICENSE("Dual BSD/GPL"); + +#ifdef CFG_DRIVER_INF_NAME_CHANGE +char *gprifnamesta = ""; +char *gprifnamep2p = ""; +char *gprifnameap = ""; +module_param_named(sta, gprifnamesta, charp, 0); +module_param_named(p2p, gprifnamep2p, charp, 0); +module_param_named(ap, gprifnameap, charp, 0); +#endif /* CFG_DRIVER_INF_NAME_CHANGE */ + +/* NIC interface name */ +#ifdef CFG_SUPPORT_DUAL_CARD_DUAL_DRIVER_B +#define NIC_INF_NAME "wlanb%d" +#else +#define NIC_INF_NAME "wlan%d" +#endif + + +#ifdef CFG_DRIVER_INF_NAME_CHANGE +/* Kernel IFNAMESIZ is 16, we use 5 in case some protocol might auto gen interface name, */ +/* in that case, the interface name might have risk of over kernel's IFNAMESIZ */ +#define CUSTOM_IFNAMESIZ 5 +#endif /* CFG_DRIVER_INF_NAME_CHANGE */ + +#if CFG_SUPPORT_SNIFFER +#define NIC_MONITOR_INF_NAME "radiotap%d" +#endif + +UINT_8 aucDebugModule[DBG_MODULE_NUM]; + + +/* 4 2007/06/26, mikewu, now we don't use this, we just fix the number of wlan device to 1 */ +static WLANDEV_INFO_T arWlanDevInfo[CFG_MAX_WLAN_DEVICES] = { {0} }; + +static UINT_32 u4WlanDevNum; /* How many NICs coexist now */ + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +BOOLEAN g_fgIsCalDataBackuped = FALSE; +#endif + +/**20150205 added work queue for sched_scan to avoid cfg80211 stop schedule scan dead loack**/ +struct delayed_work sched_workq; + +#define CFG_EEPRM_FILENAME "EEPROM" +#define FILE_NAME_MAX 64 + +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1) +static PUINT_8 apucEepromName[] = { + (PUINT_8) CFG_EEPRM_FILENAME "_MT", + NULL +}; +#endif + +#if CFG_CHIP_RESET_SUPPORT +static int g_u4ProbeChipResetTimes; +#define PROBE_CHIP_RESET_LIMIT 3 +#endif +int CFG80211_Suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow) +{ + P_GLUE_INFO_T prGlueInfo; + ADAPTER_T *prAdapter; + + DBGLOG(INIT, INFO, "CFG80211 suspend CB\n"); + + if (!wlanGetGlueInfo()) { + DBGLOG(REQ, ERROR, "NIC does not exist!\n"); + return 0; + } + + prGlueInfo = (P_GLUE_INFO_T)wiphy_priv(wiphy); + prAdapter = prGlueInfo->prAdapter; + + atomic_set(&prGlueInfo->cfgSuspend, 1); + DBGLOG(REQ, EVENT, "cfg80211 ops block\n"); + + return 0; +} + +int CFG80211_Resume(struct wiphy *wiphy) +{ + P_GLUE_INFO_T prGlueInfo; + ADAPTER_T *prAdapter; + + DBGLOG(INIT, INFO, "CFG80211 resume CB\n"); + + if (!wlanGetGlueInfo()) { + DBGLOG(REQ, ERROR, "NIC does not exist!\n"); + return 0; + } + + prGlueInfo = (P_GLUE_INFO_T)wiphy_priv(wiphy); + prAdapter = prGlueInfo->prAdapter; + + atomic_set(&prGlueInfo->cfgSuspend, 0); + DBGLOG(REQ, EVENT, "cfg80211 ops unblock\n"); + + return 0; +} + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +#define CHAN2G(_channel, _freq, _flags) \ +{ \ + .band = KAL_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 = KAL_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(36, 0), CHAN5G(40, 0), + CHAN5G(44, 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(144, 0), + CHAN5G(149, 0), CHAN5G(153, 0), + CHAN5G(157, 0), CHAN5G(161, 0), + CHAN5G(165, 0), +}; + +#define RATETAB_ENT(_rate, _rateid, _flags) \ +{ \ + .bitrate = (_rate), \ + .hw_value = (_rateid), \ + .flags = (_flags), \ +} + +/* for cfg80211 - rate table */ +static struct ieee80211_rate mtk_rates[] = { + RATETAB_ENT(10, 0x1000, 0), + RATETAB_ENT(20, 0x1001, 0), + RATETAB_ENT(55, 0x1002, 0), + RATETAB_ENT(110, 0x1003, 0), /* 802.11b */ + RATETAB_ENT(60, 0x2000, 0), + RATETAB_ENT(90, 0x2001, 0), + RATETAB_ENT(120, 0x2002, 0), + RATETAB_ENT(180, 0x2003, 0), + RATETAB_ENT(240, 0x2004, 0), + RATETAB_ENT(360, 0x2005, 0), + RATETAB_ENT(480, 0x2006, 0), + RATETAB_ENT(540, 0x2007, 0), /* 802.11a/g */ +}; + +#define mtk_a_rates (mtk_rates + 4) +#define mtk_a_rates_size (ARRAY_SIZE(mtk_rates) - 4) +#define mtk_g_rates (mtk_rates + 0) +#define mtk_g_rates_size (ARRAY_SIZE(mtk_rates) - 0) + +#define WLAN_MCS_INFO \ +{ \ + .rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0},\ + .rx_highest = 0, \ + .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ +} + +#define WLAN_VHT_MCS_INFO \ +{ \ + .rx_mcs_map = 0xFFFA, \ + .rx_highest = cpu_to_le16(867), \ + .tx_mcs_map = 0xFFFA, \ + .tx_highest = cpu_to_le16(867), \ +} + + +#define WLAN_HT_CAP \ +{ \ + .ht_supported = true, \ + .cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 \ + | IEEE80211_HT_CAP_SM_PS \ + | IEEE80211_HT_CAP_GRN_FLD \ + | IEEE80211_HT_CAP_SGI_20 \ + | IEEE80211_HT_CAP_SGI_40, \ + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, \ + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE, \ + .mcs = WLAN_MCS_INFO, \ +} + +#define WLAN_VHT_CAP \ +{ \ + .vht_supported = true, \ + .cap = IEEE80211_VHT_CAP_RXLDPC \ + | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK \ + | IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 \ + | IEEE80211_VHT_CAP_RXLDPC \ + | IEEE80211_VHT_CAP_SHORT_GI_80 \ + | IEEE80211_VHT_CAP_TXSTBC \ + | IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE \ + | IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE, \ + .vht_mcs = WLAN_VHT_MCS_INFO, \ +} + +/* public for both Legacy Wi-Fi / P2P access */ +struct ieee80211_supported_band mtk_band_2ghz = { + .band = KAL_BAND_2GHZ, + .channels = mtk_2ghz_channels, + .n_channels = ARRAY_SIZE(mtk_2ghz_channels), + .bitrates = mtk_g_rates, + .n_bitrates = mtk_g_rates_size, + .ht_cap = WLAN_HT_CAP, +}; + +/* public for both Legacy Wi-Fi / P2P access */ +struct ieee80211_supported_band mtk_band_5ghz = { + .band = KAL_BAND_5GHZ, + .channels = mtk_5ghz_channels, + .n_channels = ARRAY_SIZE(mtk_5ghz_channels), + .bitrates = mtk_a_rates, + .n_bitrates = mtk_a_rates_size, + .ht_cap = WLAN_HT_CAP, + .vht_cap = WLAN_VHT_CAP, +}; + +const UINT_32 mtk_cipher_suites[5] = { + /* keep WEP first, it may be removed below */ + WLAN_CIPHER_SUITE_WEP40, + WLAN_CIPHER_SUITE_WEP104, + WLAN_CIPHER_SUITE_TKIP, + WLAN_CIPHER_SUITE_CCMP, + + /* keep last -- depends on hw flags! */ + WLAN_CIPHER_SUITE_AES_CMAC +}; + +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, +#if CFG_SUPPORT_TDLS + .change_station = mtk_cfg80211_change_station, + .add_station = mtk_cfg80211_add_station, + .del_station = mtk_cfg80211_del_station, +#endif + .scan = mtk_cfg80211_scan, + .connect = mtk_cfg80211_connect, +#if CFG_SUPPORT_CFG80211_AUTH + .deauth = mtk_cfg80211_deauth, +#endif + .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, +#if CONFIG_SUPPORT_GTK_REKEY + .set_rekey_data = mtk_cfg80211_set_rekey_data, +#endif + .suspend = mtk_cfg80211_suspend, + .resume = CFG80211_Resume, +#if CFG_SUPPORT_CFG80211_AUTH + .auth = mtk_cfg80211_auth, +#endif + .assoc = mtk_cfg80211_assoc, + + /* Action Frame TX/RX */ + .remain_on_channel = mtk_cfg80211_remain_on_channel, + .cancel_remain_on_channel = mtk_cfg80211_cancel_remain_on_channel, + .mgmt_tx = mtk_cfg80211_mgmt_tx, + /* .mgmt_tx_cancel_wait = mtk_cfg80211_mgmt_tx_cancel_wait, */ + .mgmt_frame_register = mtk_cfg80211_mgmt_frame_register, + +#ifdef CONFIG_NL80211_TESTMODE + .testmode_cmd = mtk_cfg80211_testmode_cmd, +#endif +#if 0 /* Remove schedule_scan because we need more verification for NLO */ + .sched_scan_start = mtk_cfg80211_sched_scan_start, + .sched_scan_stop = mtk_cfg80211_sched_scan_stop, +#endif +#if CFG_SUPPORT_TDLS + .tdls_oper = mtk_cfg80211_tdls_oper, + .tdls_mgmt = mtk_cfg80211_tdls_mgmt, +#endif +}; + +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE + +static const struct wiphy_vendor_command mtk_wlan_vendor_ops[] = { + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_GET_CHANNEL_LIST + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_channel_list + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_SET_COUNTRY_CODE + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_country_code + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_GET_ROAMING_CAPABILITIES + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV + | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_roaming_capabilities + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_CONFIG_ROAMING + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV + | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_config_roaming + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_ENABLE_ROAMING + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV + | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_enable_roaming + }, + /* Get Supported Feature Set*/ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_GET_FEATURE_SET + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_supported_feature_set + }, + /* Set Tx Power Scenario */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_SELECT_TX_POWER_SCENARIO + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_tx_power_scenario + }, + /* Get Driver Version or Firmware Version */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = LOGGER_GET_VER + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_version + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV + | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_scan_mac_oui + } +}; + +static const struct nl80211_vendor_cmd_info mtk_wlan_vendor_events[] = { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_HOTLIST_RESULTS_FOUND + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_SCAN_RESULTS_AVAILABLE + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_FULL_SCAN_RESULTS + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = RTT_EVENT_COMPLETE + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_COMPLETE_SCAN + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_HOTLIST_RESULTS_LOST + }, +}; +#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_ais_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { + [NL80211_IFTYPE_ADHOC] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) + }, + [NL80211_IFTYPE_STATION] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + }, + [NL80211_IFTYPE_AP] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | BIT(IEEE80211_STYPE_ACTION >> 4) + }, + [NL80211_IFTYPE_AP_VLAN] = { + /* copy AP */ + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) | BIT(IEEE80211_STYPE_ACTION >> 4) + }, + [NL80211_IFTYPE_P2P_CLIENT] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + }, + [NL80211_IFTYPE_P2P_GO] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | BIT(IEEE80211_STYPE_ACTION >> 4) + } +}; + +#ifdef CONFIG_PM +static const struct wiphy_wowlan_support mtk_wlan_wowlan_support = { + .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT | WIPHY_WOWLAN_ANY, +}; +#endif + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \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; +} +#endif + +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE +u16 wlanSelectQueue(struct net_device *dev, + struct sk_buff *skb, + struct net_device *sb_dev, select_queue_fallback_t fallback) +{ + return mtk_wlan_ndev_select_queue(skb); +} +#elif KERNEL_VERSION(3, 14, 0) <= LINUX_VERSION_CODE +u16 wlanSelectQueue(struct net_device *dev, struct sk_buff *skb, + void *accel_priv, select_queue_fallback_t fallback) +{ + return mtk_wlan_ndev_select_queue(skb); +} +#elif KERNEL_VERSION(3, 13, 0) <= LINUX_VERSION_CODE +u16 wlanSelectQueue(struct net_device *dev, struct sk_buff *skb, + void *accel_priv) +{ + return mtk_wlan_ndev_select_queue(skb); +} +#else +u16 wlanSelectQueue(struct net_device *dev, struct sk_buff *skb) +{ + return mtk_wlan_ndev_select_queue(skb); +} +#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 < 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]; + prRegInfo->ucRxDiversity = aucTmp[1]; + + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, fgRssiCompensationVaildbit), (PUINT_16) aucTmp); + prRegInfo->ucRssiPathCompasationUsed = aucTmp[0]; + prRegInfo->ucGpsDesense = aucTmp[1]; + +#if CFG_SUPPORT_NVRAM_5G + /* load EFUSE overriding part */ + for (i = 0; i < sizeof(prRegInfo->aucEFUSE); i += sizeof(UINT_16)) { + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, EfuseMapping) + i, + (PUINT_16) (((PUINT_8) &(prRegInfo->aucEFUSE)) + i)); + } + + prRegInfo->prOldEfuseMapping = (P_NEW_EFUSE_MAPPING2NVRAM_T)&prRegInfo->aucEFUSE; +#else + +/* 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)); + } +#endif + + /* load band edge tx power control */ + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, fg2G4BandEdgePwrUsed), (PUINT_16) aucTmp); + prRegInfo->fg2G4BandEdgePwrUsed = (BOOLEAN) aucTmp[0]; + if (aucTmp[0]) { + prRegInfo->cBandEdgeMaxPwrCCK = (INT_8) aucTmp[1]; + + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, cBandEdgeMaxPwrOFDM20), (PUINT_16) aucTmp); + prRegInfo->cBandEdgeMaxPwrOFDM20 = (INT_8) aucTmp[0]; + prRegInfo->cBandEdgeMaxPwrOFDM40 = (INT_8) aucTmp[1]; + } + + /* load regulation subbands */ + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, ucRegChannelListMap), (PUINT_16) aucTmp); + prRegInfo->eRegChannelListMap = (ENUM_REG_CH_MAP_T) aucTmp[0]; + prRegInfo->ucRegChannelListIndex = aucTmp[1]; + + if (prRegInfo->eRegChannelListMap == REG_CH_MAP_CUSTOMIZED) { + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + pucDest = (PUINT_8) &prRegInfo->rDomainInfo.rSubBand[i]; + for (j = 0; j < 6; j += sizeof(UINT_16)) { + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucRegSubbandInfo) + + (i * 6 + j), (PUINT_16) aucTmp); + + *pucDest++ = aucTmp[0]; + *pucDest++ = aucTmp[1]; + } + } + } + + /* load rssiPathCompensation */ + for (i = 0; i < sizeof(RSSI_PATH_COMPASATION_T); i += sizeof(UINT_16)) { + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, + rRssiPathCompensation) + i, + (PUINT_16) (((PUINT_8) &(prRegInfo->rRssiPathCompasation)) + + i)); + } +#if 1 + /* load full NVRAM */ + for (i = 0; i < sizeof(WIFI_CFG_PARAM_STRUCT); i += sizeof(UINT_16)) { + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part1OwnVersion) + i, + (PUINT_16) (((PUINT_8) &(prRegInfo->aucNvram)) + i)); + } + prRegInfo->prNvramSettings = (P_WIFI_CFG_PARAM_STRUCT)&prRegInfo->aucNvram; +#endif + } else { + DBGLOG(INIT, INFO, "glLoadNvram fail\n"); + prGlueInfo->fgNvramAvailable = FALSE; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Release prDev from wlandev_array and free tasklet object related to it. +* +* \param[in] prDev Pointer to struct net_device +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static void wlanClearDevIdx(struct net_device *prDev) +{ + int i; + + ASSERT(prDev); + + for (i = 0; i < CFG_MAX_WLAN_DEVICES; i++) { + if (arWlanDevInfo[i].prDev == prDev) { + arWlanDevInfo[i].prDev = NULL; + u4WlanDevNum--; + } + } + +} /* end of wlanClearDevIdx() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Allocate an unique interface index, net_device::ifindex member for this +* wlan device. Store the net_device in wlandev_array, and initialize +* tasklet object related to it. +* +* \param[in] prDev Pointer to struct net_device +* +* \retval >= 0 The device number. +* \retval -1 Fail to get index. +*/ +/*----------------------------------------------------------------------------*/ +static int wlanGetDevIdx(struct net_device *prDev) +{ + int i; + + ASSERT(prDev); + + for (i = 0; i < CFG_MAX_WLAN_DEVICES; i++) { + if (arWlanDevInfo[i].prDev == (struct net_device *)NULL) { + /* Reserve 2 bytes space to store one digit of + * device number and NULL terminator. + */ + arWlanDevInfo[i].prDev = prDev; + u4WlanDevNum++; + return i; + } + } + + return -1; +} /* end of wlanGetDevIdx() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A method of struct net_device, a primary SOCKET interface to configure +* the interface lively. Handle an ioctl call on one of our devices. +* Everything Linux ioctl specific is done here. Then we pass the contents +* of the ifr->data to the request message handler. +* +* \param[in] prDev Linux kernel netdevice +* +* \param[in] prIFReq Our private ioctl request structure, typed for the generic +* struct ifreq so we can use ptr to function +* +* \param[in] cmd Command ID +* +* \retval 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, ERROR, "Invalid input data\n"); + return -EINVAL; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + if (!prGlueInfo) { + DBGLOG(INIT, ERROR, "prGlueInfo is NULL\n"); + return -EFAULT; + } + + if (prGlueInfo->u4ReadyFlag == 0) { + DBGLOG(INIT, ERROR, "Adapter is not ready\n"); + return -EINVAL; + } + +#if defined(_HIF_USB) + if (prGlueInfo->rHifInfo.state == USB_STATE_SUSPEND) { + DBGLOG(INIT, ERROR, "usb is suspend\n"); + return -EINVAL; + } +#endif + + if ((i4Cmd >= SIOCIWFIRST) && (i4Cmd < SIOCIWFIRSTPRIV)) { + /* 0x8B00 ~ 0x8BDF, wireless extension region */ + ret = wext_support_ioctl(prDev, prIfReq, i4Cmd); + } else if ((i4Cmd >= SIOCIWFIRSTPRIV) && (i4Cmd < SIOCIWLASTPRIV)) { + /* 0x8BE0 ~ 0x8BFF, private ioctl region */ + ret = priv_support_ioctl(prDev, prIfReq, i4Cmd); + } else if (i4Cmd == SIOCDEVPRIVATE + 1) { +#ifdef CFG_ANDROID_AOSP_PRIV_CMD + ret = android_private_support_driver_cmd(prDev, prIfReq, i4Cmd); +#elif defined CFG_ALPS_ANDROID_AOSP_PRIV_CMD + ret = alps_android_private_support_driver_cmd(prDev, + prIfReq, i4Cmd); +#else + ret = priv_support_driver_cmd(prDev, prIfReq, i4Cmd); +#endif /* CFG_ANDROID_AOSP_PRIV_CMD */ + } else if (i4Cmd == SIOCDEVPRIVATE + 2) { + /* For mDNS offload template. */ + ret = priv_support_mdns_offload(prDev, prIfReq, i4Cmd); + } else { + DBGLOG(INIT, WARN, "Unexpected ioctl command: 0x%04x\n", i4Cmd); + ret = -EOPNOTSUPP; + } + + return ret; +} /* end of wlanDoIOCTL() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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 +*/ +/*---------------------------------------------------------------------------*/ +P_GLUE_INFO_T wlanGetGlueInfo(VOID) +{ + struct net_device *prDev = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + + if (u4WlanDevNum == 0) + return NULL; + + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + if (prDev == NULL) + return NULL; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + + return prGlueInfo; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function check the HIF state allow to handle callback or not. +* +* \param[in] prGlueInfo Pointer to struct GLUE_INFO_T +* +* \return TRUE: HIF state allow to handle it. +* FALSE: HIF state NOT allow to handle it. +*/ +/*---------------------------------------------------------------------------*/ +BOOLEAN wlanGetHifState(IN P_GLUE_INFO_T prGlueInfo) +{ + P_GL_HIF_INFO_T prHifInfo; + BOOLEAN fgIsHifReady = TRUE; +#if defined(_HIF_USB) + unsigned long flags; +#endif + + if (!prGlueInfo) { + DBGLOG(INIT, ERROR, "prGlueInfo is NULL\n"); + return FALSE; + } + + prHifInfo = &prGlueInfo->rHifInfo; + +#if defined(_HIF_USB) + spin_lock_irqsave(&prHifInfo->rStateLock, flags); + if (prHifInfo->state != USB_STATE_LINK_UP) { + DBGLOG(INIT, WARN, "USB in suspend skip cfg callback\n"); + fgIsHifReady = FALSE; + } + spin_unlock_irqrestore(&prHifInfo->rStateLock, flags); +#endif + + return fgIsHifReady; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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; +struct net_device *gPrDev; + +static void wlanSetMulticastList(struct net_device *prDev) +{ + /* Allow to receive all multicast for WOW */ + DBGLOG(INIT, INFO, "wlanSetMulticastList\n"); + prDev->flags |= (IFF_MULTICAST | IFF_ALLMULTI); + 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 + * main_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 = (prDev != NULL) ? *((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; + } + + DBGLOG(INIT, INFO, "wlanSetMulticastListWorkQueue prDev->flags:0x%x\n", prDev->flags); + + if (prDev->flags & IFF_PROMISC) + u4PacketFilter |= PARAM_PACKET_FILTER_PROMISCUOUS; + + if (prDev->flags & IFF_BROADCAST) + u4PacketFilter |= PARAM_PACKET_FILTER_BROADCAST; + + if (prDev->flags & IFF_MULTICAST) { + if ((prDev->flags & IFF_ALLMULTI) || (netdev_mc_count(prDev) > MAX_NUM_GROUP_ADDR)) + u4PacketFilter |= PARAM_PACKET_FILTER_ALL_MULTICAST; + else + u4PacketFilter |= PARAM_PACKET_FILTER_MULTICAST; + } + + up(&g_halt_sem); + + if (kalIoctl(prGlueInfo, + wlanoidSetCurrentPacketFilter, + &u4PacketFilter, + sizeof(u4PacketFilter), FALSE, FALSE, TRUE, &u4SetInfoLen) != WLAN_STATUS_SUCCESS) { + return; + } + + if (u4PacketFilter & PARAM_PACKET_FILTER_MULTICAST) { + /* Prepare multicast address list */ + struct netdev_hw_addr *ha; + 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); + + netdev_for_each_mc_addr(ha, prDev) { + if (i < MAX_NUM_GROUP_ADDR) { + kalMemCopy((prMCAddrList + i * ETH_ALEN), GET_ADDR(ha), ETH_ALEN); + i++; + } + } + + up(&g_halt_sem); + + kalIoctl(prGlueInfo, + wlanoidSetMulticastList, prMCAddrList, (i * ETH_ALEN), FALSE, FALSE, TRUE, &u4SetInfoLen); + + kalMemFree(prMCAddrList, VIR_MEM_TYPE, MAX_NUM_GROUP_ADDR * ETH_ALEN); + } + +} /* end of wlanSetMulticastList() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate scheduled scan has been stopped +* +* \param[in] +* prGlueInfo +* +* \return +* None +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanSchedScanStoppedWorkQueue(struct work_struct *work) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + struct net_device *prDev = gPrDev; + + DBGLOG(SCN, INFO, "wlanSchedScanStoppedWorkQueue\n"); + prGlueInfo = (prDev != NULL) ? *((P_GLUE_INFO_T *) netdev_priv(prDev)) : NULL; + if (!prGlueInfo) { + DBGLOG(SCN, INFO, "prGlueInfo == NULL unexpected\n"); + return; + } + + /* 2. indication to cfg80211 */ + /* 20150205 change cfg80211_sched_scan_stopped to work queue due to sched_scan_mtx dead lock issue */ +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE + cfg80211_sched_scan_stopped(priv_to_wiphy(prGlueInfo), + prGlueInfo->prSchedScanRequest->reqid); +#else + cfg80211_sched_scan_stopped(priv_to_wiphy(prGlueInfo)); +#endif + DBGLOG(SCN, INFO, + "cfg80211_sched_scan_stopped event send done WorkQueue thread return from wlanSchedScanStoppedWorkQueue\n"); + return; + +} + +/* FIXME: Since we cannot sleep in the wlanSetMulticastList, we arrange + * another workqueue for sleeping. We don't want to block + * main_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 + +} /* 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_NETDEV_PRIVATE_GLUE_INFO prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) NULL; + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + UINT_8 ucBssIndex; + + ASSERT(prSkb); + ASSERT(prDev); + ASSERT(prGlueInfo); + + prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(prDev); + ASSERT(prNetDevPrivate->prGlueInfo == prGlueInfo); + ucBssIndex = prNetDevPrivate->ucBssIdx; + +#if CFG_SUPPORT_PASSPOINT + if (prGlueInfo->fgIsDad) { + /* kalPrint("[Passpoint R2] Due to ipv4_dad...TX is forbidden\n"); */ + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } + if (prGlueInfo->fgIs6Dad) { + /* kalPrint("[Passpoint R2] Due to ipv6_dad...TX is forbidden\n"); */ + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } +#endif /* CFG_SUPPORT_PASSPOINT */ + + kalResetPacket(prGlueInfo, (P_NATIVE_PACKET) prSkb); + + if (kalHardStartXmit(prSkb, prDev, prGlueInfo, ucBssIndex) == WLAN_STATUS_SUCCESS) { + /* Successfully enqueue to Tx queue */ + /* Successfully enqueue to Tx queue */ + } + + /* 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) +{ + return (struct net_device_stats *)kalGetStats(prDev); +} /* end of wlanGetStats() */ + +VOID wlanDebugInit(VOID) +{ + UINT_8 i; + + /* Set the initial debug level of each module */ +#if DBG + for (i = 0; i < DBG_MODULE_NUM; i++) + aucDebugModule[i] = DBG_CLASS_MASK; /* enable all */ +#else +#ifdef CFG_DEFAULT_DBG_LEVEL + for (i = 0; i < DBG_MODULE_NUM; i++) + aucDebugModule[i] = CFG_DEFAULT_DBG_LEVEL; +#else + + for (i = 0; i < DBG_MODULE_NUM; i++) { + aucDebugModule[i] = DBG_CLASS_ERROR | + DBG_CLASS_WARN | DBG_CLASS_STATE | DBG_CLASS_EVENT | DBG_CLASS_INFO; + } + aucDebugModule[DBG_TX_IDX] &= ~(DBG_CLASS_EVENT | DBG_CLASS_INFO); + aucDebugModule[DBG_RX_IDX] &= ~(DBG_CLASS_EVENT | DBG_CLASS_INFO); + aucDebugModule[DBG_REQ_IDX] &= ~(DBG_CLASS_EVENT | DBG_CLASS_INFO); + aucDebugModule[DBG_INTR_IDX] = 0; + aucDebugModule[DBG_MEM_IDX] = DBG_CLASS_ERROR | DBG_CLASS_WARN; + aucDebugModule[DBG_REQ_IDX] = DBG_CLASS_MASK; + +#endif +#endif /* DBG */ + + DBGLOG(INIT, INFO, "Reset ALL DBG module log level to DEFAULT!\n"); + +} + +WLAN_STATUS wlanSetDebugLevel(IN UINT_32 u4DbgIdx, IN UINT_32 u4DbgMask) +{ + UINT_32 u4Idx; + WLAN_STATUS fgStatus = WLAN_STATUS_SUCCESS; + + if (u4DbgIdx == DBG_ALL_MODULE_IDX) { + for (u4Idx = 0; u4Idx < DBG_MODULE_NUM; u4Idx++) + aucDebugModule[u4Idx] = (UINT_8) u4DbgMask; + DBGLOG(INIT, INFO, "Set ALL DBG module log level to [0x%02x]\n", u4DbgMask); + } else if (u4DbgIdx < DBG_MODULE_NUM) { + aucDebugModule[u4DbgIdx] = (UINT_8) u4DbgMask; + DBGLOG(INIT, INFO, "Set DBG module[%u] log level to [0x%02x]\n", u4DbgIdx, u4DbgMask); + } else { + fgStatus = WLAN_STATUS_FAILURE; + } + + return fgStatus; +} + +WLAN_STATUS wlanGetDebugLevel(IN UINT_32 u4DbgIdx, OUT PUINT_32 pu4DbgMask) +{ + if (u4DbgIdx < DBG_MODULE_NUM) { + *pu4DbgMask = aucDebugModule[u4DbgIdx]; + return WLAN_STATUS_SUCCESS; + } + + return WLAN_STATUS_FAILURE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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)); + INIT_DELAYED_WORK(&workq, wlanSetMulticastListWorkQueue); + +/* 20150205 work queue for sched_scan */ + INIT_DELAYED_WORK(&sched_workq, wlanSchedScanStoppedWorkQueue); + +/* 20161024 init wow port setting */ +#if CFG_WOW_SUPPORT + kalWowInit(prGlueInfo); +#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) +{ +} /* end of wlanUninit() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief A method of struct net_device, to set the randomized mac address + * + * This method is called before Wifi Framework requests a new conenction with + * enabled feature "Connected Random Mac". + * + * \param[in] ndev Pointer to struct net_device. + * \param[in] addr Randomized Mac address passed from WIFI framework. + * + * \return int. + */ +/*----------------------------------------------------------------------------*/ +static int wlanSetMacAddress(struct net_device *ndev, void *addr) +{ + ADAPTER_T *prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + struct sockaddr *sa = NULL; + struct wireless_dev *wdev = NULL; + + /********************************************************************** + * Check if kernel passes valid data to us * + ********************************************************************** + */ + if (!ndev || !addr) { + DBGLOG(INIT, ERROR, "Set macaddr with ndev(%d) and addr(%d)\n", + (ndev == NULL) ? 0 : 1, (addr == NULL) ? 0 : 1); + return WLAN_STATUS_INVALID_DATA; + } + + /********************************************************************** + * Block mac address changing if this setting is not for connection * + ********************************************************************** + */ + wdev = ndev->ieee80211_ptr; + if (wdev->ssid_len > 0 || (wdev->current_bss)) { + DBGLOG(INIT, ERROR, + "Reject macaddr change due to ssid_len(%d) & bss(%d)\n", + wdev->ssid_len, wdev->current_bss); + return WLAN_STATUS_NOT_ACCEPTED; + } + + /********************************************************************** + * 1. Change OwnMacAddr which will be updated to FW through * + * rlmActivateNetwork later. * + * 2. Change dev_addr stored in kernel to notify framework that the * + * mac addr has been changed and what the new value is. * + ********************************************************************** + */ + sa = (struct sockaddr *)addr; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(ndev)); + prAdapter = prGlueInfo->prAdapter; + + COPY_MAC_ADDR(prAdapter->prAisBssInfo->aucOwnMacAddr, sa->sa_data); + COPY_MAC_ADDR(prGlueInfo->prDevHandler->dev_addr, sa->sa_data); + DBGLOG(INIT, INFO, "Set connect random macaddr to " MACSTR ".\n", + MAC2STR(prAdapter->prAisBssInfo->aucOwnMacAddr)); + + return WLAN_STATUS_SUCCESS; +} /* end of wlanSetMacAddr() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A function for prDev->open +* +* \param[in] prDev Pointer to struct net_device. +* +* \retval 0 The execution of wlanOpen succeeds. +* \retval < 0 The execution of wlanOpen failed. +*/ +/*----------------------------------------------------------------------------*/ +static int wlanOpen(struct net_device *prDev) +{ + ASSERT(prDev); + + netif_tx_start_all_queues(prDev); + + return 0; /* success */ +} /* end of wlanOpen() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A function for prDev->stop +* +* \param[in] prDev Pointer to struct net_device. +* +* \retval 0 The execution of wlanStop succeeds. +* \retval < 0 The execution of wlanStop failed. +*/ +/*----------------------------------------------------------------------------*/ +static int wlanStop(struct net_device *prDev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + 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) { + kalCfg80211ScanDone(prGlueInfo->prScanRequest, TRUE); + prGlueInfo->prScanRequest = NULL; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + /* zero clear old acs information */ + kalMemZero(&(prGlueInfo->prAdapter->rWifiVar.rChnLoadInfo), + sizeof(prGlueInfo->prAdapter->rWifiVar.rChnLoadInfo)); +#endif + + netif_tx_stop_all_queues(prDev); + + return 0; /* success */ +} /* end of wlanStop() */ +#if CFG_SUPPORT_SNIFFER +static int wlanMonOpen(struct net_device *prDev) +{ + ASSERT(prDev); + + netif_tx_start_all_queues(prDev); + + return 0; /* success */ +} + +static int wlanMonStop(struct net_device *prDev) +{ + ASSERT(prDev); + + netif_tx_stop_all_queues(prDev); + + return 0; /* success */ +} + +static const struct net_device_ops wlan_mon_netdev_ops = { + .ndo_open = wlanMonOpen, + .ndo_stop = wlanMonStop, +}; + +void wlanMonWorkHandler(struct work_struct *work) +{ + P_GLUE_INFO_T prGlueInfo; + + prGlueInfo = container_of(work, GLUE_INFO_T, monWork); + + if (prGlueInfo->fgIsEnableMon) { + if (prGlueInfo->prMonDevHandler) + return; +#if KERNEL_VERSION(3, 17, 0) <= CFG80211_VERSION_CODE + prGlueInfo->prMonDevHandler = + alloc_netdev_mq(sizeof(NETDEV_PRIVATE_GLUE_INFO), NIC_MONITOR_INF_NAME, + NET_NAME_PREDICTABLE, ether_setup, CFG_MAX_TXQ_NUM); +#else + prGlueInfo->prMonDevHandler = + alloc_netdev_mq(sizeof(NETDEV_PRIVATE_GLUE_INFO), NIC_MONITOR_INF_NAME, + ether_setup, CFG_MAX_TXQ_NUM); +#endif + if (prGlueInfo->prMonDevHandler == NULL) { + DBGLOG(INIT, ERROR, "wlanMonWorkHandler: Allocated prMonDevHandler context FAIL.\n"); + return; + } + + ((P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(prGlueInfo->prMonDevHandler))->prGlueInfo = prGlueInfo; + prGlueInfo->prMonDevHandler->type = ARPHRD_IEEE80211_RADIOTAP; + prGlueInfo->prMonDevHandler->netdev_ops = &wlan_mon_netdev_ops; + netif_carrier_off(prGlueInfo->prMonDevHandler); + netif_tx_stop_all_queues(prGlueInfo->prMonDevHandler); + kalResetStats(prGlueInfo->prMonDevHandler); + + if (register_netdev(prGlueInfo->prMonDevHandler) < 0) { + DBGLOG(INIT, ERROR, "wlanMonWorkHandler: Registered prMonDevHandler context FAIL.\n"); + free_netdev(prGlueInfo->prMonDevHandler); + prGlueInfo->prMonDevHandler = NULL; + } + DBGLOG(INIT, INFO, "wlanMonWorkHandler: Registered prMonDevHandler context DONE.\n"); + } else { + if (prGlueInfo->prMonDevHandler) { + unregister_netdev(prGlueInfo->prMonDevHandler); + prGlueInfo->prMonDevHandler = NULL; + DBGLOG(INIT, INFO, "wlanMonWorkHandler: unRegistered prMonDevHandler context DONE.\n"); + } + } +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \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 channels */ + for (i = 0; i < ARRAY_SIZE(mtk_2ghz_channels); i++) { + mtk_2ghz_channels[i].flags |= IEEE80211_CHAN_DISABLED; + mtk_2ghz_channels[i].orig_flags |= IEEE80211_CHAN_DISABLED; + } + + for (i = 0; i < ARRAY_SIZE(mtk_5ghz_channels); i++) { + mtk_5ghz_channels[i].flags |= IEEE80211_CHAN_DISABLED; + mtk_5ghz_channels[i].orig_flags |= IEEE80211_CHAN_DISABLED; + } + + /* 2. Get current domain channel list */ + rlmDomainGetChnlList(prGlueInfo->prAdapter, + BAND_NULL, FALSE, + ARRAY_SIZE(mtk_2ghz_channels) + ARRAY_SIZE(mtk_5ghz_channels), + &ucNumOfChannel, aucChannelList); + + /* 3. Enable specific channel based on domain channel list */ + for (i = 0; i < ucNumOfChannel; i++) { + switch (aucChannelList[i].eBand) { + case BAND_2G4: + for (j = 0; j < ARRAY_SIZE(mtk_2ghz_channels); j++) { + if (mtk_2ghz_channels[j].hw_value == aucChannelList[i].ucChannelNum) { + mtk_2ghz_channels[j].flags &= ~IEEE80211_CHAN_DISABLED; + mtk_2ghz_channels[j].orig_flags &= ~IEEE80211_CHAN_DISABLED; + break; + } + } + break; + + case BAND_5G: + for (j = 0; j < ARRAY_SIZE(mtk_5ghz_channels); j++) { + if (mtk_5ghz_channels[j].hw_value == aucChannelList[i].ucChannelNum) { + mtk_5ghz_channels[j].flags &= ~IEEE80211_CHAN_DISABLED; + mtk_5ghz_channels[j].orig_flags &= ~IEEE80211_CHAN_DISABLED; + break; + } + } + break; + + default: + DBGLOG(INIT, WARN, "Unknown band %d\n", aucChannelList[i].eBand); + break; + } + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Register the device to the kernel and return the index. +* +* \param[in] prDev Pointer to struct net_device. +* +* \retval 0 The execution of wlanNetRegister succeeds. +* \retval < 0 The execution of wlanNetRegister failed. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 wlanNetRegister(struct wireless_dev *prWdev) +{ + P_GLUE_INFO_T prGlueInfo; + INT_32 i4DevIdx = -1; + P_NETDEV_PRIVATE_GLUE_INFO prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) NULL; + P_ADAPTER_T prAdapter = NULL; + + ASSERT(prWdev); + + do { + if (!prWdev) + break; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); + prAdapter = prGlueInfo->prAdapter; + i4DevIdx = wlanGetDevIdx(prWdev->netdev); + if (i4DevIdx < 0) { + DBGLOG(INIT, ERROR, "net_device number exceeds!\n"); + break; + } + + if (prAdapter && prAdapter->rWifiVar.ucWow) + kalInitDevWakeup(prGlueInfo->prAdapter, wiphy_dev(prWdev->wiphy)); + + if (register_netdev(prWdev->netdev) < 0) { + DBGLOG(INIT, ERROR, "Register net_device failed\n"); + wlanClearDevIdx(prWdev->netdev); + i4DevIdx = -1; + } +#if 1 + prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(prGlueInfo->prDevHandler); + ASSERT(prNetDevPrivate->prGlueInfo == prGlueInfo); + prNetDevPrivate->ucBssIdx = prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + wlanBindBssIdxToNetInterface(prGlueInfo, + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex, (PVOID) prWdev->netdev); +#else + wlanBindBssIdxToNetInterface(prGlueInfo, + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex, (PVOID) prWdev->netdev); + /* wlanBindNetInterface(prGlueInfo, NET_DEV_WLAN_IDX, (PVOID)prWdev->netdev); */ +#endif + if (i4DevIdx != -1) + prGlueInfo->fgIsRegistered = TRUE; + } while (FALSE); + + return i4DevIdx; /* success */ +} /* end of wlanNetRegister() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Unregister the device from the kernel +* +* \param[in] prWdev Pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID wlanNetUnregister(struct wireless_dev *prWdev) +{ + P_GLUE_INFO_T prGlueInfo; + + if (!prWdev) { + DBGLOG(INIT, ERROR, "wlanNetUnregister: The device context is NULL\n"); + return; + } + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); + + wlanClearDevIdx(prWdev->netdev); + unregister_netdev(prWdev->netdev); + + prGlueInfo->fgIsRegistered = FALSE; + +#if CFG_SUPPORT_SNIFFER + if (prGlueInfo->prMonDevHandler) { + unregister_netdev(prGlueInfo->prMonDevHandler); + prGlueInfo->prMonDevHandler = NULL; + } + prGlueInfo->fgIsEnableMon = FALSE; +#endif + +} /* end of wlanNetUnregister() */ + +static const struct net_device_ops wlan_netdev_ops = { + .ndo_open = wlanOpen, + .ndo_stop = wlanStop, + .ndo_set_rx_mode = wlanSetMulticastList, + .ndo_get_stats = wlanGetStats, + .ndo_do_ioctl = wlanDoIOCTL, + .ndo_start_xmit = wlanHardStartXmit, + .ndo_init = wlanInit, + .ndo_uninit = wlanUninit, + .ndo_select_queue = wlanSelectQueue, + .ndo_set_mac_address = wlanSetMacAddress, +}; + + +static void wlanCreateWirelessDevice(void) +{ + struct wiphy *prWiphy = NULL; + struct wireless_dev *prWdev = NULL; + + /* 4 <1.1> Create wireless_dev */ + prWdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (!prWdev) { + DBGLOG(INIT, ERROR, "Allocating memory to wireless_dev context failed\n"); + return; + } + /* 4 <1.2> Create wiphy */ + prWiphy = wiphy_new(&mtk_wlan_ops, sizeof(GLUE_INFO_T)); + if (!prWiphy) { + DBGLOG(INIT, ERROR, "Allocating memory to wiphy device failed\n"); + goto free_wdev; + } + /* 4 <1.3> configure wireless_dev & wiphy */ + prWdev->iftype = NL80211_IFTYPE_STATION; + prWiphy->iface_combinations = p_mtk_iface_combinations_sta; + prWiphy->n_iface_combinations = mtk_iface_combinations_sta_num; + prWiphy->max_scan_ssids = CFG_SCAN_SSID_MAX_NUM; + prWiphy->max_scan_ie_len = 512; + prWiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); + prWiphy->bands[KAL_BAND_2GHZ] = &mtk_band_2ghz; + /* always assign 5Ghz bands here, if the chip is not support 5Ghz, + * bands[KAL_BAND_5GHZ] will be assign to NULL + */ + prWiphy->bands[KAL_BAND_5GHZ] = &mtk_band_5ghz; + prWiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + prWiphy->cipher_suites = (const u32 *)mtk_cipher_suites; + prWiphy->n_cipher_suites = ARRAY_SIZE(mtk_cipher_suites); + + /* CFG80211_VERSION_CODE >= 3.3 */ + prWiphy->flags = WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; + + /* CFG80211_VERSION_CODE >= 3.2 */ +#if (CFG_SUPPORT_ROAMING == 1) + prWiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; +#endif /* CFG_SUPPORT_ROAMING */ + +#if KERNEL_VERSION(3, 14, 0) > CFG80211_VERSION_CODE + prWiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; +#else + prWiphy->regulatory_flags = REGULATORY_CUSTOM_REG; +#if (CFG_SUPPORT_DFS_MASTER == 1) + prWiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; +#endif /* CFG_SUPPORT_DFS_MASTER */ +#endif +#if (CFG_SUPPORT_SAE == 1) + prWiphy->features |= NL80211_FEATURE_SAE; +#endif /* CFG_SUPPORT_DFS_MASTER */ + + cfg80211_regd_set_wiphy(prWiphy); + +#if (CFG_SUPPORT_TDLS == 1) + TDLSEX_WIPHY_FLAGS_INIT(prWiphy->flags); +#endif /* CFG_SUPPORT_TDLS */ + prWiphy->max_remain_on_channel_duration = 5000; + prWiphy->mgmt_stypes = mtk_cfg80211_ais_default_mgmt_stypes; + +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE + prWiphy->vendor_commands = mtk_wlan_vendor_ops; + prWiphy->n_vendor_commands = sizeof(mtk_wlan_vendor_ops) / sizeof(struct wiphy_vendor_command); + prWiphy->vendor_events = mtk_wlan_vendor_events; + prWiphy->n_vendor_events = ARRAY_SIZE(mtk_wlan_vendor_events); +#endif + /* 4 <1.4> wowlan support */ +#ifdef CONFIG_PM +#if KERNEL_VERSION(3, 11, 0) <= CFG80211_VERSION_CODE + prWiphy->wowlan = &mtk_wlan_wowlan_support; +#else + kalMemCopy(&prWiphy->wowlan, &mtk_wlan_wowlan_support, sizeof(struct wiphy_wowlan_support)); +#endif +#endif + +#ifdef CONFIG_CFG80211_WEXT + /* 4 <1.5> Use wireless extension to replace IOCTL */ + prWiphy->wext = &wext_handler_def; +#endif + if (wiphy_register(prWiphy) < 0) { + DBGLOG(INIT, ERROR, "wiphy_register error\n"); + goto free_wiphy; + } + prWdev->wiphy = prWiphy; + gprWdev = prWdev; + DBGLOG(INIT, INFO, "create wireless device success\n"); + return; + +free_wiphy: + wiphy_free(prWiphy); +free_wdev: + kfree(prWdev); +} + +static void wlanDestroyWirelessDevice(void) +{ + /* Move set_wiphy_dev(wiphy, NULL) in wlanNetDestroy */ + wiphy_unregister(gprWdev->wiphy); + wiphy_free(gprWdev->wiphy); + kfree(gprWdev); + gprWdev = NULL; +} + +VOID wlanWakeLockInit(P_GLUE_INFO_T prGlueInfo) +{ +#ifdef CONFIG_ANDROID + KAL_WAKE_LOCK_INIT(NULL, &prGlueInfo->rIntrWakeLock, "WLAN interrupt"); + KAL_WAKE_LOCK_INIT(NULL, &prGlueInfo->rTimeoutWakeLock, "WLAN timeout"); +#endif +} + +VOID wlanWakeLockUninit(P_GLUE_INFO_T prGlueInfo) +{ +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + if (KAL_WAKE_LOCK_ACTIVE(NULL, &prGlueInfo->rIntrWakeLock)) + KAL_WAKE_UNLOCK(NULL, &prGlueInfo->rIntrWakeLock); + KAL_WAKE_LOCK_DESTROY(NULL, &prGlueInfo->rIntrWakeLock); + + if (KAL_WAKE_LOCK_ACTIVE(NULL, &prGlueInfo->rTimeoutWakeLock)) + KAL_WAKE_UNLOCK(NULL, &prGlueInfo->rTimeoutWakeLock); + KAL_WAKE_LOCK_DESTROY(NULL, &prGlueInfo->rTimeoutWakeLock); +#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, PVOID pvDriverData) +{ + struct wireless_dev *prWdev = gprWdev; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 i; + struct device *prDev; + P_NETDEV_PRIVATE_GLUE_INFO prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) NULL; + + PUCHAR prInfName = NULL; + + if (prWdev == NULL) { + DBGLOG(INIT, ERROR, "No wireless dev exist, abort power on\n"); + return NULL; + } + + /* 4 <1.3> co-relate wiphy & prDev */ + glGetDev(pvData, &prDev); + if (!prDev) { + DBGLOG(INIT, ERROR, "unable to get struct dev for wlan\n"); + return NULL; + } + set_wiphy_dev(prWdev->wiphy, prDev); + + /* 4 <2> Create Glue structure */ + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); + kalMemZero(prGlueInfo, sizeof(GLUE_INFO_T)); + + /* 4 <2.1> Create Adapter structure */ + prAdapter = (P_ADAPTER_T) wlanAdapterCreate(prGlueInfo); + + if (!prAdapter) { + DBGLOG(INIT, ERROR, "Allocating memory to adapter failed\n"); + goto netcreate_err; + } + + prAdapter->chip_info = ((struct mt66xx_hif_driver_data *) pvDriverData)->chip_info; + prGlueInfo->prAdapter = prAdapter; + + /* 4 <3> Initialize Glue structure */ + /* 4 <3.1> Create net device */ + +#ifdef CFG_DRIVER_INF_NAME_CHANGE + + if (kalStrLen(gprifnamesta) > 0) { + if (kalStrStr(gprifnamesta, "%d")) + prInfName = gprifnamesta; + else + prInfName = kalStrCat(gprifnamesta, "%d"); + DBGLOG(INIT, WARN, "Station ifname customized, use %s\n", prInfName); + } else +#endif /* CFG_DRIVER_INF_NAME_CHANGE */ + prInfName = NIC_INF_NAME; + +#if KERNEL_VERSION(3, 17, 0) <= CFG80211_VERSION_CODE + prGlueInfo->prDevHandler = + alloc_netdev_mq(sizeof(NETDEV_PRIVATE_GLUE_INFO), prInfName, + NET_NAME_PREDICTABLE, ether_setup, CFG_MAX_TXQ_NUM); +#else + prGlueInfo->prDevHandler = + alloc_netdev_mq(sizeof(NETDEV_PRIVATE_GLUE_INFO), prInfName, + ether_setup, CFG_MAX_TXQ_NUM); +#endif + 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; + } + DBGLOG(INIT, INFO, "net_device prDev(0x%p) allocated\n", prGlueInfo->prDevHandler); + + /* 4 <3.1.1> Initialize net device varaiables */ +#if 1 + prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(prGlueInfo->prDevHandler); + prNetDevPrivate->prGlueInfo = prGlueInfo; +#else + *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->prDevHandler)) = prGlueInfo; +#endif + prGlueInfo->prDevHandler->needed_headroom += NIC_TX_HEAD_ROOM; + 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); + kalResetStats(prGlueInfo->prDevHandler); + +#if CFG_SUPPORT_SNIFFER + INIT_WORK(&(prGlueInfo->monWork), wlanMonWorkHandler); +#endif + + /* 4 <3.1.2> co-relate with wiphy bi-directionally */ + prGlueInfo->prDevHandler->ieee80211_ptr = prWdev; + + prWdev->netdev = prGlueInfo->prDevHandler; + + /* 4 <3.1.3> co-relate net device & prDev */ + SET_NETDEV_DEV(prGlueInfo->prDevHandler, wiphy_dev(prWdev->wiphy)); + + /* 4 <3.1.4> set device to glue */ + prGlueInfo->prDev = prDev; + + /* 4 <3.2> Initialize glue variables */ + prGlueInfo->eParamMediaStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; + prGlueInfo->ePowerState = ParamDeviceStateD0; + prGlueInfo->fgIsRegistered = FALSE; + prGlueInfo->prScanRequest = NULL; + prGlueInfo->prSchedScanRequest = NULL; + + +#if CFG_SUPPORT_PASSPOINT + /* Init DAD */ + prGlueInfo->fgIsDad = FALSE; + prGlueInfo->fgIs6Dad = FALSE; + kalMemZero(prGlueInfo->aucDADipv4, 4); + kalMemZero(prGlueInfo->aucDADipv6, 16); +#endif /* CFG_SUPPORT_PASSPOINT */ + + init_completion(&prGlueInfo->rScanComp); + init_completion(&prGlueInfo->rHaltComp); + init_completion(&prGlueInfo->rPendComp); + +#if CFG_SUPPORT_MULTITHREAD + init_completion(&prGlueInfo->rHifHaltComp); + init_completion(&prGlueInfo->rRxHaltComp); +#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]); + } + + for (i = 0; i < MUTEX_NUM; i++) + mutex_init(&prGlueInfo->arMutex[i]); + + /* initialize semaphore for ioctl */ + sema_init(&prGlueInfo->ioctl_sem, 1); + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN + /* initialize SDIO read-write pattern control */ + prGlueInfo->fgEnSdioTestPattern = FALSE; + prGlueInfo->fgIsSdioTestInitialized = FALSE; +#endif + + /* initialize semaphore for halt control */ + sema_init(&g_halt_sem, 1); + + /* 4 <8> Init Queues */ + init_waitqueue_head(&prGlueInfo->waitq); + QUEUE_INITIALIZE(&prGlueInfo->rCmdQueue); + prGlueInfo->i4TxPendingCmdNum = 0; + QUEUE_INITIALIZE(&prGlueInfo->rTxQueue); + glSetHifInfo(prGlueInfo, (ULONG) pvData); + + /* Init wakelock */ + wlanWakeLockInit(prGlueInfo); + + /* main thread is created in this function */ +#if CFG_SUPPORT_MULTITHREAD + init_waitqueue_head(&prGlueInfo->waitq_rx); + init_waitqueue_head(&prGlueInfo->waitq_hif); + + prGlueInfo->u4TxThreadPid = 0xffffffff; + prGlueInfo->u4RxThreadPid = 0xffffffff; + prGlueInfo->u4HifThreadPid = 0xffffffff; +#endif + +#if CFG_SUPPORT_CSI + /* init CSI wait queue */ + init_waitqueue_head(&(prGlueInfo->prAdapter->rCSIInfo.waitq)); +#endif + + + return prWdev; + +netcreate_err: + if (prAdapter != NULL) { + wlanAdapterDestroy(prAdapter); + prAdapter = NULL; + } + + if (prGlueInfo->prDevHandler != NULL) { + free_netdev(prGlueInfo->prDevHandler); + prGlueInfo->prDevHandler = NULL; + } + + return NULL; +} /* 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, "The device context is NULL\n"); + return; + } + + /* prGlueInfo is allocated with net_device */ + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); + ASSERT(prGlueInfo); + /* prWdev: base AIS dev + * Becase the interface dev (ex: usb_device) would be free + * after un-plug event. Should set the wiphy->dev->parent which + * pointer to the interface dev to NULL. Otherwise, the corresponding + * system operation (poweroff, suspend) might reference it. + * set_wiphy_dev(wiphy, NULL): set the wiphy->dev->parent = NULL + * The trunk-ce1 does this, but the trunk seems not. + * ce1 do set_wiphy_dev(prWdev->wiphy, prDev) in wlanNetCreate. + * But that is after wiphy_register, and will cause exception in + * wiphy_unregister(), if do not set_wiphy_dev(wiphy, NULL). + */ + set_wiphy_dev(prWdev->wiphy, NULL); + + /* 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); + +} /* end of wlanNetDestroy() */ + +VOID wlanSetSuspendMode(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgEnable) +{ + struct net_device *prDev = NULL; + + if (!prGlueInfo) + return; + + prDev = prGlueInfo->prDevHandler; + if (!prDev) + return; + + kalSetNetAddressFromInterface(prGlueInfo, prDev, fgEnable); + wlanNotifyFwSuspend(prGlueInfo, prDev, fgEnable); +} + +#if CFG_ENABLE_EARLY_SUSPEND +static struct early_suspend wlan_early_suspend_desc = { + .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN, +}; + +static void wlan_early_suspend(struct early_suspend *h) +{ + struct net_device *prDev = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + + /* 4 <1> Sanity Check */ + if ((u4WlanDevNum == 0) && (u4WlanDevNum > CFG_MAX_WLAN_DEVICES)) { + DBGLOG(INIT, ERROR, "wlanLateResume u4WlanDevNum==0 invalid!!\n"); + return; + } + + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + if (!prDev) + return; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + if (!prGlueInfo) + return; + + DBGLOG(INIT, INFO, "********<%s>********\n", __func__); + + if (prGlueInfo->fgIsInSuspendMode == TRUE) { + DBGLOG(INIT, INFO, "%s: Already in suspend mode, SKIP!\n", __func__); + return; + } + + prGlueInfo->fgIsInSuspendMode = TRUE; + + wlanSetSuspendMode(prGlueInfo, TRUE); + p2pSetSuspendMode(prGlueInfo, TRUE); +} + +static void wlan_late_resume(struct early_suspend *h) +{ + struct net_device *prDev = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + + /* 4 <1> Sanity Check */ + if ((u4WlanDevNum == 0) && (u4WlanDevNum > CFG_MAX_WLAN_DEVICES)) { + DBGLOG(INIT, ERROR, "wlanLateResume u4WlanDevNum==0 invalid!!\n"); + return; + } + + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + if (!prDev) + return; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + if (!prGlueInfo) + return; + + DBGLOG(INIT, INFO, "********<%s>********\n", __func__); + + if (prGlueInfo->fgIsInSuspendMode == FALSE) { + DBGLOG(INIT, INFO, "%s: Not in suspend mode, SKIP!\n", __func__); + return; + } + + prGlueInfo->fgIsInSuspendMode = FALSE; + + /* 4 <2> Set suspend mode for each network */ + wlanSetSuspendMode(prGlueInfo, FALSE); + p2pSetSuspendMode(prGlueInfo, FALSE); +} +#endif + +#if ((MTK_WCN_HIF_SDIO && CFG_SUPPORT_MTK_ANDROID_KK) || WLAN_INCLUDE_PROC) + +int set_p2p_mode_handler(struct net_device *netdev, PARAM_CUSTOM_P2P_SET_STRUCT_T p2pmode) +{ + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(netdev)); + PARAM_CUSTOM_P2P_SET_STRUCT_T rSetP2P; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + rSetP2P.u4Enable = p2pmode.u4Enable; + rSetP2P.u4Mode = p2pmode.u4Mode; + + if ((!rSetP2P.u4Enable) && (kalIsResetting() == FALSE)) + p2pNetUnregister(prGlueInfo, FALSE); + + rWlanStatus = kalIoctl(prGlueInfo, + wlanoidSetP2pMode, + (PVOID) &rSetP2P, sizeof(PARAM_CUSTOM_P2P_SET_STRUCT_T), FALSE, FALSE, TRUE, &u4BufLen); + + DBGLOG(INIT, INFO, "set_p2p_mode_handler ret = 0x%08x\n", + (UINT_32) rWlanStatus); + + + /* Need to check fgIsP2PRegistered, in case of whole chip reset. + * in this case, kalIOCTL return success always, + * and prGlueInfo->prP2PInfo[0] may be NULL + */ + if ((rSetP2P.u4Enable) && (prGlueInfo->prAdapter->fgIsP2PRegistered) && (kalIsResetting() == FALSE)) + p2pNetRegister(prGlueInfo, FALSE); + + return 0; +} + +#endif + +#if CFG_SUPPORT_EASY_DEBUG +/*----------------------------------------------------------------------------*/ +/*! +* \brief parse config from wifi.cfg +* +* \param[in] prAdapter +* +* \retval VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanGetParseConfig(P_ADAPTER_T prAdapter) +{ + PUINT_8 pucConfigBuf; + UINT_32 u4ConfigReadLen; +#ifdef CFG_SUPPORT_DUAL_CARD_DUAL_DRIVER_B +#define WIFI_CFG_FN "wifi_b.cfg" +#else +#define WIFI_CFG_FN "wifi.cfg" +#endif + + wlanCfgInit(prAdapter, NULL, 0, 0); + pucConfigBuf = (PUINT_8) kalMemAlloc(WLAN_CFG_FILE_BUF_SIZE, VIR_MEM_TYPE); + if (!pucConfigBuf) + return; + + kalMemZero(pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE); + u4ConfigReadLen = 0; + if (pucConfigBuf) { + if (kalRequestFirmware(WIFI_CFG_FN, pucConfigBuf, + WLAN_CFG_FILE_BUF_SIZE, &u4ConfigReadLen, prAdapter->prGlueInfo->prDev) == 0) { + /* ToDo:: Nothing */ + } else if (kalReadToFile("/storage/sdcard0/wifi.cfg", pucConfigBuf, + WLAN_CFG_FILE_BUF_SIZE, &u4ConfigReadLen) == 0) { + /* ToDo:: Nothing */ + } else if (kalReadToFile("/data/misc/wifi.cfg", pucConfigBuf, + WLAN_CFG_FILE_BUF_SIZE, &u4ConfigReadLen) == 0) { + /* ToDo:: Nothing */ + } else if (kalReadToFile("/data/misc/wifi/wifi.cfg", pucConfigBuf, + WLAN_CFG_FILE_BUF_SIZE, &u4ConfigReadLen) == 0) { + /* ToDo:: Nothing */ + } + + if (pucConfigBuf[0] != '\0' && u4ConfigReadLen > 0) + wlanCfgParse(prAdapter, pucConfigBuf, u4ConfigReadLen, TRUE); + + kalMemFree(pucConfigBuf, VIR_MEM_TYPE, WLAN_CFG_FILE_BUF_SIZE); + } /* pucConfigBuf */ +} + + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief get config from wifi.cfg +* +* \param[in] prAdapter +* +* \retval VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanGetConfig(P_ADAPTER_T prAdapter) +{ + PUINT_8 pucConfigBuf; + UINT_32 u4ConfigReadLen; + + wlanCfgInit(prAdapter, NULL, 0, 0); + pucConfigBuf = (PUINT_8) kalMemAlloc(WLAN_CFG_FILE_BUF_SIZE, VIR_MEM_TYPE); + if (!pucConfigBuf) + return; + + kalMemZero(pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE); + u4ConfigReadLen = 0; + if (pucConfigBuf) { + if (kalRequestFirmware("wifi.cfg", pucConfigBuf, + WLAN_CFG_FILE_BUF_SIZE, &u4ConfigReadLen, prAdapter->prGlueInfo->prDev) == 0) { + /* ToDo:: Nothing */ + } else if (kalReadToFile("/storage/sdcard0/wifi.cfg", pucConfigBuf, + WLAN_CFG_FILE_BUF_SIZE, &u4ConfigReadLen) == 0) { + /* ToDo:: Nothing */ + } else if (kalReadToFile("/data/misc/wifi.cfg", pucConfigBuf, + WLAN_CFG_FILE_BUF_SIZE, &u4ConfigReadLen) == 0) { + /* ToDo:: Nothing */ + } else if (kalReadToFile("/data/misc/wifi/wifi.cfg", pucConfigBuf, + WLAN_CFG_FILE_BUF_SIZE, &u4ConfigReadLen) == 0) { + /* ToDo:: Nothing */ + } + + if (pucConfigBuf[0] != '\0' && u4ConfigReadLen > 0) + wlanCfgInit(prAdapter, pucConfigBuf, u4ConfigReadLen, 0); + + kalMemFree(pucConfigBuf, VIR_MEM_TYPE, WLAN_CFG_FILE_BUF_SIZE); + } /* pucConfigBuf */ +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief this extract buffer bin EEPROB_MTxxxx.bin to temp buffer +* +* \param[in] prAdapter +* +* \retval WLAN_STATUS_SUCCESS Success +* \retval WLAN_STATUS_FAILURE Failed +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanExtractBufferBin(P_ADAPTER_T prAdapter) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4ContentLen; + PUINT_8 pucConfigBuf = NULL; + struct mt66xx_chip_info *prChipInfo; + UINT_32 chip_id; + UINT_8 aucEeprom[32]; + WLAN_STATUS retWlanStat = WLAN_STATUS_FAILURE; + + if (prAdapter->fgIsSupportPowerOnSendBufferModeCMD == TRUE) { + DBGLOG(INIT, INFO, "Start Efuse Buffer Mode step0\n"); + DBGLOG(INIT, INFO, "ucEfuseBUfferModeCal is %x\n", prAdapter->rWifiVar.ucEfuseBufferModeCal); + + prChipInfo = prAdapter->chip_info; + chip_id = prChipInfo->chip_id; + prGlueInfo = prAdapter->prGlueInfo; + + if (prGlueInfo == NULL || prGlueInfo->prDev == NULL) + goto label_exit; + + DBGLOG(INIT, INFO, "Start Efuse Buffer Mode step1\n"); + + /* allocate memory for buffer mode info */ + if ((prAdapter->rWifiVar.ucEfuseBufferModeCal + == LOAD_EEPROM_BIN) && + (prAdapter->fgIsBufferBinExtract == FALSE)) { + DBGLOG(INIT, INFO, "Start Efuse Buffer Mode step2\n"); + /* Only in buffer mode need to access bin file */ + /* 1 <1> Load bin file*/ + pucConfigBuf = (PUINT_8) kalMemAlloc(MAX_EEPROM_BUFFER_SIZE, VIR_MEM_TYPE); + if (pucConfigBuf == NULL) + goto label_exit; + + kalMemZero(pucConfigBuf, MAX_EEPROM_BUFFER_SIZE); + + /* 1 <2> Construct EEPROM binary name */ + kalMemZero(aucEeprom, sizeof(aucEeprom)); + + snprintf(aucEeprom, 32, "%s%x.bin", + apucEepromName[0], chip_id); + + /* 1 <3> Request buffer bin */ + if (kalRequestFirmware(aucEeprom, + pucConfigBuf, MAX_EEPROM_BUFFER_SIZE, &u4ContentLen, prGlueInfo->prDev) == 0) { + DBGLOG(INIT, INFO, "request file done\n"); + } else { + DBGLOG(INIT, INFO, "can't find file\n"); + kalMemFree(pucConfigBuf, VIR_MEM_TYPE, MAX_EEPROM_BUFFER_SIZE); + goto label_exit; + } + + /* Update contents in local table */ + kalMemCopy(uacEEPROMImage, pucConfigBuf, MAX_EEPROM_BUFFER_SIZE); + + /* Free buffer */ + kalMemFree(pucConfigBuf, VIR_MEM_TYPE, MAX_EEPROM_BUFFER_SIZE); + + DBGLOG(INIT, INFO, "Start Efuse Buffer Mode step3\n"); + prAdapter->fgIsBufferBinExtract = TRUE; + } + + } + + retWlanStat = WLAN_STATUS_SUCCESS; + +label_exit: + + return retWlanStat; +} + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief this function send buffer bin EEPROB_MTxxxx.bin to FW. +* +* \param[in] prAdapter +* +* \retval WLAN_STATUS_SUCCESS Success +* \retval WLAN_STATUS_FAILURE Failed +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanDownloadBufferBin(P_ADAPTER_T prAdapter) +{ + P_GLUE_INFO_T prGlueInfo = NULL; +#if (CFG_FW_Report_Efuse_Address) + UINT_16 u2InitAddr = prAdapter->u4EfuseStartAddress; +#else + UINT_16 u2InitAddr = EFUSE_CONTENT_BUFFER_START; +#endif + UINT_32 u4BufLen = 0; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + PARAM_CUSTOM_EFUSE_BUFFER_MODE_T *prSetEfuseBufModeInfo = NULL; + UINT_32 u4ContentLen; + struct mt66xx_chip_info *prChipInfo; + UINT_32 chip_id; + WLAN_STATUS retWlanStat = WLAN_STATUS_FAILURE; + INT_32 i4OidTimeout = -1; +#if 0 + UINT_8 aucBinMacAddr[MAC_ADDR_LEN]; + UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; +#endif + +#if CFG_EFUSE_AUTO_MODE_SUPPORT + UINT_32 u4Efuse_addr = 0; + PARAM_CUSTOM_ACCESS_EFUSE_T rAccessEfuseInfo; +#endif + + if (prAdapter->fgIsSupportPowerOnSendBufferModeCMD == TRUE) { + DBGLOG(INIT, INFO, "Start Efuse Buffer Mode ..\n"); + DBGLOG(INIT, INFO, "ucEfuseBUfferModeCal is %x\n", prAdapter->rWifiVar.ucEfuseBufferModeCal); + + prChipInfo = prAdapter->chip_info; + chip_id = prChipInfo->chip_id; + prGlueInfo = prAdapter->prGlueInfo; + + if (prGlueInfo == NULL || prGlueInfo->prDev == NULL) + goto label_exit; + + /* allocate memory for buffer mode info */ + prSetEfuseBufModeInfo = (PARAM_CUSTOM_EFUSE_BUFFER_MODE_T *) + kalMemAlloc(sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T), VIR_MEM_TYPE); + if (prSetEfuseBufModeInfo == NULL) + goto label_exit; + kalMemZero(prSetEfuseBufModeInfo, sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T)); + +#if CFG_EFUSE_AUTO_MODE_SUPPORT + if (prAdapter->rWifiVar.ucEfuseBufferModeCal == LOAD_AUTO) { + kalMemSet(&rAccessEfuseInfo, 0, + sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)); + rAccessEfuseInfo.u4Address = (u4Efuse_addr / + EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfo, + sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T), + TRUE, TRUE, TRUE, &u4BufLen); + if (prGlueInfo->prAdapter->aucEepromVaule[1] + == (chip_id>>8)) { + prAdapter->rWifiVar.ucEfuseBufferModeCal + = LOAD_EFUSE; + DBGLOG(INIT, STATE, + "[EFUSE AUTO] EFUSE Mode\n"); + } else { + prAdapter->rWifiVar.ucEfuseBufferModeCal + = LOAD_EEPROM_BIN; + DBGLOG(INIT, STATE, + "[EFUSE AUTO] Buffer Mode\n"); + } + } +#endif + if (prAdapter->rWifiVar.ucEfuseBufferModeCal + == LOAD_EEPROM_BIN) { + /* Buffer mode */ + /* Only in buffer mode need to access bin file */ + if (wlanExtractBufferBin(prAdapter) != WLAN_STATUS_SUCCESS) + goto label_exit; + + /* copy to the command buffer */ +#if (CFG_FW_Report_Efuse_Address) + u4ContentLen = (prAdapter->u4EfuseEndAddress)-(prAdapter->u4EfuseStartAddress)+1; +#else + u4ContentLen = EFUSE_CONTENT_BUFFER_SIZE; +#endif + if (u4ContentLen > MAX_EEPROM_BUFFER_SIZE) + goto label_exit; + kalMemCopy(prSetEfuseBufModeInfo->aBinContent, &uacEEPROMImage[u2InitAddr], u4ContentLen); + + prSetEfuseBufModeInfo->ucSourceMode = 1; + } else { + /* eFuse mode */ + /* Only need to tell FW the content from, contents are directly from efuse */ + prSetEfuseBufModeInfo->ucSourceMode = 0; + } + prSetEfuseBufModeInfo->ucCmdType = 0x1 | (prAdapter->rWifiVar.ucCalTimingCtrl << 4); + prSetEfuseBufModeInfo->ucCount = 0xFF; /* ucCmdType 1 don't care the ucCount */ + + if (!prAdapter->rWifiVar.ucCalTimingCtrl) { + /* Full channel RF-cal mode. Need 6000ms */ + i4OidTimeout = 6000; + } + + rStatus = kalIoctlTimeout(prGlueInfo, + wlanoidSetEfusBufferMode, + (PVOID)prSetEfuseBufModeInfo, + sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T), + FALSE, TRUE, TRUE, + i4OidTimeout, + &u4BufLen); + + } + + retWlanStat = WLAN_STATUS_SUCCESS; + +label_exit: + + /* free memory */ + if (prSetEfuseBufModeInfo != NULL) + kalMemFree(prSetEfuseBufModeInfo, VIR_MEM_TYPE, sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T)); + + return retWlanStat; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \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, PVOID pvDriverData) +{ + 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; + P_REG_INFO_T prRegInfo; + UINT_8 i = 0; +#if (MTK_WCN_HIF_SDIO && CFG_WMT_WIFI_PATH_SUPPORT) + INT_32 i4RetVal = 0; +#endif +#if CFG_SUPPORT_REPLAY_DETECTION + UINT_8 ucRpyDetectOffload; +#endif + +#if 0 + PUINT_8 pucConfigBuf = NULL, pucCfgBuf = NULL; + UINT_32 u4ConfigReadLen = 0; +#endif + + do { + /* 4 <1> Initialize the IO port of the interface */ + /* GeorgeKuo: pData has different meaning for _HIF_XXX: + * _HIF_EHPI: pointer to memory base variable, which will be + * initialized by glBusInit(). + * _HIF_SDIO: bus driver handle + */ + + DBGLOG(INIT, INFO, "enter wlanProbe\n"); + + bRet = glBusInit(pvData); + + /* Cannot get IO address from interface */ + if (bRet == FALSE) { + DBGLOG(INIT, ERROR, "wlanProbe: glBusInit() fail\n"); + i4Status = -EIO; + break; + } + /* 4 <2> Create network device, Adapter, KalInfo, prDevHandler(netdev) */ + prWdev = wlanNetCreate(pvData, pvDriverData); + if (prWdev == 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); + if (prGlueInfo == NULL) { + DBGLOG(INIT, ERROR, "wlanProbe: get wiphy_priv() fail\n"); + i4Status = -EFAULT; + break; + } + + gPrDev = prGlueInfo->prDevHandler; + + /* 4 <4> Setup IRQ */ + prWlandevInfo = &arWlanDevInfo[i4DevIdx]; + + i4Status = glBusSetIrq(prWdev->netdev, NULL, prGlueInfo); + + if (i4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "wlanProbe: Set IRQ error\n"); + break; + } + + prGlueInfo->i4DevIdx = i4DevIdx; + + prAdapter = prGlueInfo->prAdapter; + + prGlueInfo->u4ReadyFlag = 0; + + prGlueInfo->u4FWRoamingEnable = 1; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + prAdapter->fgIsSupportCsumOffload = FALSE; + prAdapter->u4CSUMFlags = CSUM_OFFLOAD_EN_ALL; +#endif + +#if CFG_SUPPORT_CFG_FILE + wlanGetConfig(prAdapter); +#endif + /* Default support 2.4/5G MIMO */ + prAdapter->rWifiFemCfg.u2WifiPath = + (WLAN_FLAG_2G4_WF0 | WLAN_FLAG_5G_WF0 | WLAN_FLAG_2G4_WF1 | WLAN_FLAG_5G_WF1); + + DBGLOG(INIT, INFO, "WifiPath Init=0x%x\n", prAdapter->rWifiFemCfg.u2WifiPath); + +#if (MTK_WCN_HIF_SDIO && CFG_WMT_WIFI_PATH_SUPPORT) + i4RetVal = mtk_wcn_wmt_wifi_fem_cfg_report((PVOID)&prAdapter->rWifiFemCfg); + + if (i4RetVal) + DBGLOG(INIT, WARN, "Get WifiPath from WMT drv FAIL\n"); + else + DBGLOG(INIT, INFO, "Get WifiPath from WMT drv Success WifiPath=0x%x\n", + prAdapter->rWifiFemCfg.u2WifiPath); +#endif + /* 4 <5> Start Device */ + 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)); + + /* Trigger the action of switching Pwr state to drv_own */ + prAdapter->fgIsFwOwn = TRUE; + + /* 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; +#if 0 + prRegInfo->fgEnArpFilter = TRUE; +#endif + /* The Init value of u4WpaVersion/u4AuthAlg shall be DISABLE/OPEN, not zero! */ + /* The Init value of u4CipherGroup/u4CipherPairwise shall be NONE, not zero! */ + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE; + + tasklet_init(&prGlueInfo->rRxTask, halRxTasklet, (unsigned long)prGlueInfo); + tasklet_init(&prGlueInfo->rTxCompleteTask, halTxCompleteTasklet, (unsigned long)prGlueInfo); + + if (wlanAdapterStart(prAdapter, prRegInfo) != WLAN_STATUS_SUCCESS) + i4Status = -EIO; + + if (i4Status < 0) + break; + + if (HAL_IS_TX_DIRECT(prAdapter)) { + if (!prAdapter->fgTxDirectInited) { + skb_queue_head_init(&prAdapter->rTxDirectSkbQueue); +#if KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE + timer_setup(&prAdapter->rTxDirectSkbTimer, + nicTxDirectTimerCheckSkbQ, 0); + + timer_setup(&prAdapter->rTxDirectHifTimer, + nicTxDirectTimerCheckHifQ, 0); +#else + init_timer(&prAdapter->rTxDirectSkbTimer); + prAdapter->rTxDirectSkbTimer.data = (unsigned long)prGlueInfo; + prAdapter->rTxDirectSkbTimer.function = nicTxDirectTimerCheckSkbQ; + + init_timer(&prAdapter->rTxDirectHifTimer); + prAdapter->rTxDirectHifTimer.data = (unsigned long)prGlueInfo; + prAdapter->rTxDirectHifTimer.function = nicTxDirectTimerCheckHifQ; +#endif + + prAdapter->fgTxDirectInited = TRUE; + } + } + + /* kfree(prRegInfo); */ + + INIT_WORK(&prGlueInfo->rTxMsduFreeWork, kalFreeTxMsduWorker); + INIT_DELAYED_WORK(&prGlueInfo->rRxPktDeAggWork, halDeAggRxPktWorker); + + prGlueInfo->main_thread = kthread_run(main_thread, prGlueInfo->prDevHandler, "main_thread"); +#if CFG_SUPPORT_MULTITHREAD + prGlueInfo->hif_thread = kthread_run(hif_thread, prGlueInfo->prDevHandler, "hif_thread"); + prGlueInfo->rx_thread = kthread_run(rx_thread, prGlueInfo->prDevHandler, "rx_thread"); +#endif + + + /* TODO the change schedule API shall be provided by OS glue layer */ + /* Switch the Wi-Fi task priority to higher priority and change the scheduling method */ + if (prGlueInfo->prAdapter->rWifiVar.ucThreadPriority > 0) { + const struct sched_param param = { + .sched_priority = + prAdapter->rWifiVar.ucThreadPriority + }; + sched_setscheduler(prGlueInfo->main_thread, + prGlueInfo->prAdapter->rWifiVar.ucThreadScheduling, ¶m); +#if CFG_SUPPORT_MULTITHREAD + sched_setscheduler(prGlueInfo->hif_thread, + prGlueInfo->prAdapter->rWifiVar.ucThreadScheduling, ¶m); + sched_setscheduler(prGlueInfo->rx_thread, + prGlueInfo->prAdapter->rWifiVar.ucThreadScheduling, ¶m); +#endif + DBGLOG(INIT, INFO, + "Set pri = %d, sched = %d\n", + prGlueInfo->prAdapter->rWifiVar.ucThreadPriority, + prGlueInfo->prAdapter->rWifiVar.ucThreadScheduling); + } + + g_u4HaltFlag = 0; + +#if CFG_SUPPORT_BUFFER_MODE +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1) + if (wlanDownloadBufferBin(prAdapter) != WLAN_STATUS_SUCCESS) + return -1; + +#endif +#endif + +#if CFG_SUPPORT_DBDC + /* Buffer mode delay cal will init dbdc as disable. So that, + * we should setup dbdc after buffer mode process. + */ + /* Update DBDC default setting */ + cnmInitDbdcSetting(prAdapter); +#endif /*CFG_SUPPORT_DBDC*/ + + /* send regulatory information to firmware */ + rlmDomainSendInfoToFirmware(prAdapter); + + /* 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, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, WARN, + "set MAC addr fail 0x%x\n", rStatus); + prGlueInfo->u4ReadyFlag = 0; + } else { + kalMemCopy(prGlueInfo->prDevHandler->dev_addr, + &MacAddr.sa_data, ETH_ALEN); + kalMemCopy(prGlueInfo->prDevHandler->perm_addr, + prGlueInfo->prDevHandler->dev_addr, ETH_ALEN); +#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 */ + if (prAdapter->fgIsSupportCsumOffload) { + 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, &u4SetInfoLen); + + if (rStatus == WLAN_STATUS_SUCCESS) { + prGlueInfo->prDevHandler->features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_RXCSUM; + } else { + DBGLOG(INIT, WARN, + "set HW checksum offload fail 0x%x\n", + rStatus); + prAdapter->fgIsSupportCsumOffload = FALSE; + } + } +#endif + + /* 4 <3> Register the card */ + i4DevIdx = wlanNetRegister(prWdev); + if (i4DevIdx < 0) { + i4Status = -ENXIO; + DBGLOG(INIT, ERROR, "wlanProbe: Cannot register the net_device context to the kernel\n"); + break; + } + /* 4 <4> Register early suspend callback */ +#if CFG_ENABLE_EARLY_SUSPEND + glRegisterEarlySuspend(&wlan_early_suspend_desc, wlan_early_suspend, wlan_late_resume); +#endif + + /* 4 <5> Register Notifier callback */ + wlanRegisterNotifier(); + + /* 4 <6> Initialize /proc filesystem */ +#ifdef WLAN_INCLUDE_PROC + i4Status = procCreateFsEntry(prGlueInfo); + if (i4Status < 0) { + DBGLOG(INIT, ERROR, "wlanProbe: init procfs failed\n"); + break; + } +#endif /* WLAN_INCLUDE_PROC */ + +#if CFG_MET_PACKET_TRACE_SUPPORT + kalMetInit(prGlueInfo); +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + prGlueInfo->rBowInfo.fgIsNetRegistered = FALSE; + prGlueInfo->rBowInfo.fgIsRegistered = FALSE; + glRegisterAmpc(prGlueInfo); +#endif + +#if (CFG_ENABLE_WIFI_DIRECT && MTK_WCN_HIF_SDIO && CFG_SUPPORT_MTK_ANDROID_KK) + register_set_p2p_mode_handler(set_p2p_mode_handler); +#elif (CFG_ENABLE_WIFI_DIRECT) + if (prAdapter->rWifiVar.u4RegP2pIfAtProbe) { + PARAM_CUSTOM_P2P_SET_STRUCT_T rSetP2P; + + rSetP2P.u4Enable = 1; + +#ifdef CFG_DRIVER_INITIAL_RUNNING_MODE + rSetP2P.u4Mode = CFG_DRIVER_INITIAL_RUNNING_MODE; +#else + rSetP2P.u4Mode = RUNNING_P2P_MODE; +#endif /* CFG_DRIVER_RUNNING_MODE */ + if (set_p2p_mode_handler(prWdev->netdev, rSetP2P) == 0) + DBGLOG(INIT, INFO, "%s: p2p device registered\n", __func__); + else + DBGLOG(INIT, ERROR, "%s: Failed to register p2p device\n", __func__); + } +#endif + } while (FALSE); + + + if (i4Status != 0) { + if (prGlueInfo == NULL) + return -1; + + glBusFreeIrq(prGlueInfo->prDevHandler, prGlueInfo); + DBGLOG(INIT, ERROR, "probe failed %d\n", i4Status); + + if (wlanIsChipRstRecEnabled(prGlueInfo->prAdapter)) { + wlanChipRstPreAct(prGlueInfo->prAdapter); +#if CFG_CHIP_RESET_SUPPORT + if (g_u4ProbeChipResetTimes < PROBE_CHIP_RESET_LIMIT) { + DBGLOG(INIT, ERROR, + "wlanProbe: trigger whole reset\n"); + g_u4ProbeChipResetTimes++; + glResetTrigger(prGlueInfo->prAdapter); + } +#else +#if defined(_HIF_USB) + HAL_WIFI_FUNC_CHIP_RESET(prGlueInfo->prAdapter); +#endif +#endif + DBGLOG(HAL, ERROR, "usb trigger whole reset\n"); + } + return i4Status; + } + + /* Configure 5G band for registered wiphy */ + if (prAdapter->fgEnable5GBand) + prWdev->wiphy->bands[KAL_BAND_5GHZ] = &mtk_band_5ghz; + else + prWdev->wiphy->bands[KAL_BAND_5GHZ] = NULL; + + for (i = 0 ; i < KAL_P2P_NUM; i++) { + if (gprP2pRoleWdev[i] == NULL) + continue; + + if (prAdapter->fgEnable5GBand) + gprP2pRoleWdev[i]->wiphy->bands[KAL_BAND_5GHZ] = + &mtk_band_5ghz; + else + gprP2pRoleWdev[i]->wiphy->bands[KAL_BAND_5GHZ] = NULL; + } + + +#if CFG_SUPPORT_AGPS_ASSIST + kalIndicateAgpsNotify(prAdapter, AGPS_EVENT_WLAN_ON, NULL, 0); +#endif + + + +#if CFG_SUPPORT_EASY_DEBUG + +#if 0 + wlanGetParseConfig(prGlueInfo->prAdapter); + /*wlanGetParseConfig would reparsing the config file, + *and then, sent to firmware + *use wlanFeatureToFw to take it(won't be reparsing) + */ +#endif + + /* move before reading file + *wlanLoadDefaultCustomerSetting(prAdapter); + */ + + wlanFeatureToFw(prGlueInfo->prAdapter); + +#endif + wlanCfgSetSwCtrl(prGlueInfo->prAdapter); + + wlanCfgSetChip(prGlueInfo->prAdapter); + + wlanCfgSetCountryCode(prGlueInfo->prAdapter); + +#if CFG_SUPPORT_ANT_SELECT + /* update some info needed before connected */ + wlanUpdateExtInfo(prGlueInfo->prAdapter); +#endif + +#if (CFG_MET_PACKET_TRACE_SUPPORT == 1) + DBGLOG(INIT, TRACE, "init MET procfs...\n"); + i4Status = kalMetInitProcfs(prGlueInfo); + if (i4Status < 0) + DBGLOG(INIT, ERROR, "wlanProbe: init MET procfs failed\n"); +#endif + +#if CFG_MET_TAG_SUPPORT + if (met_tag_init() != 0) + DBGLOG(INIT, ERROR, "MET_TAG_INIT error!\n"); +#endif + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST + /* Calibration Backup Flow */ + if (!g_fgIsCalDataBackuped) { + if (rlmTriggerCalBackup(prGlueInfo->prAdapter, g_fgIsCalDataBackuped) == WLAN_STATUS_FAILURE) { + DBGLOG(RFTEST, INFO, "Error : Boot Time Wi-Fi Enable Fail........\n"); + return -1; + } + + g_fgIsCalDataBackuped = TRUE; + } else { + if (rlmTriggerCalBackup(prGlueInfo->prAdapter, g_fgIsCalDataBackuped) == WLAN_STATUS_FAILURE) { + DBGLOG(RFTEST, INFO, "Error : Normal Wi-Fi Enable Fail........\n"); + return -1; + } + } +#endif + /* card is ready */ + prGlueInfo->u4ReadyFlag = 1; + +#if CFG_SUPPORT_REPLAY_DETECTION + ucRpyDetectOffload = prAdapter->rWifiVar.ucRpyDetectOffload; + + if (ucRpyDetectOffload == FEATURE_ENABLED) { + DBGLOG(INIT, INFO, "Send CMD to enable Replay Detection offload feature\n"); + wlanSuspendRekeyOffload(prAdapter->prGlueInfo, + GTK_REKEY_CMD_MODE_RPY_OFFLOAD_ON); + } else { + DBGLOG(INIT, INFO, "Send CMD to disable Replay Detection offload feature\n"); + wlanSuspendRekeyOffload(prAdapter->prGlueInfo, + GTK_REKEY_CMD_MODE_RPY_OFFLOAD_OFF); + } +#endif + +#if CFG_CHIP_RESET_SUPPORT + g_u4ProbeChipResetTimes = 0; +#endif + + DBGLOG(INIT, EVENT, "wlanProbe: probe success\n"); + + return i4Status; +} /* end of wlanProbe() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A method to stop driver operation and release all resources. Following +* this call, no frame should go up or down through this interface. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID wlanRemove(VOID) +{ + struct net_device *prDev = NULL; + P_WLANDEV_INFO_T prWlandevInfo = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + BOOLEAN fgResult = FALSE; + + DBGLOG(INIT, INFO, "Remove wlan!\n"); + + /* 4 <0> Sanity check */ + ASSERT(u4WlanDevNum <= CFG_MAX_WLAN_DEVICES); + if (u4WlanDevNum == 0) { + DBGLOG(INIT, INFO, "0 == u4WlanDevNum\n"); + return; + } +#if (CFG_ENABLE_WIFI_DIRECT && MTK_WCN_HIF_SDIO && CFG_SUPPORT_MTK_ANDROID_KK) + register_set_p2p_mode_handler(NULL); +#endif + if (u4WlanDevNum > 0 && u4WlanDevNum <= CFG_MAX_WLAN_DEVICES) { + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + prWlandevInfo = &arWlanDevInfo[u4WlanDevNum - 1]; + } + + ASSERT(prDev); + if (prDev == NULL) { + DBGLOG(INIT, INFO, "NULL == prDev\n"); + return; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + if (prGlueInfo == NULL) { + DBGLOG(INIT, INFO, "NULL == prGlueInfo\n"); + free_netdev(prDev); + return; + } + + prAdapter = prGlueInfo->prAdapter; + + prGlueInfo->u4ReadyFlag = 0; + +#if CFG_ENABLE_BT_OVER_WIFI + if (prGlueInfo->rBowInfo.fgIsNetRegistered) { + bowNotifyAllLinkDisconnected(prGlueInfo->prAdapter); + /* wait 300ms for BoW module to send deauth */ + kalMsleep(300); + } +#endif + + if (prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_CONNECTED) { + +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 2, 0) <= CFG80211_VERSION_CODE) + cfg80211_disconnected(prGlueInfo->prDevHandler, 0, NULL, 0, TRUE, GFP_KERNEL); +#else + cfg80211_disconnected(prGlueInfo->prDevHandler, 0, NULL, 0, GFP_KERNEL); +#endif + kalMsleep(500); + } + + flush_delayed_work(&workq); + +/* 20150205 work queue for sched_scan */ + + flush_delayed_work(&sched_workq); + + down(&g_halt_sem); + g_u4HaltFlag = 1; + up(&g_halt_sem); + + /* 4 <2> Mark HALT, notify main thread to stop, and clean up queued requests */ + set_bit(GLUE_FLAG_HALT_BIT, &prGlueInfo->ulFlag); + +#if CFG_SUPPORT_MULTITHREAD + wake_up_interruptible(&prGlueInfo->waitq_hif); + wait_for_completion_interruptible(&prGlueInfo->rHifHaltComp); + wake_up_interruptible(&prGlueInfo->waitq_rx); + wait_for_completion_interruptible(&prGlueInfo->rRxHaltComp); +#endif + + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + /* wait main thread stops */ + wait_for_completion_interruptible(&prGlueInfo->rHaltComp); + + /* Stop works */ + flush_work(&prGlueInfo->rTxMsduFreeWork); + cancel_delayed_work_sync(&prGlueInfo->rRxPktDeAggWork); + + DBGLOG(INIT, INFO, "wlan thread stopped\n"); + + /* prGlueInfo->rHifInfo.main_thread = NULL; */ + prGlueInfo->main_thread = NULL; +#if CFG_SUPPORT_MULTITHREAD + prGlueInfo->hif_thread = NULL; + prGlueInfo->rx_thread = NULL; + + prGlueInfo->u4TxThreadPid = 0xffffffff; + prGlueInfo->u4HifThreadPid = 0xffffffff; +#endif + + if (HAL_IS_TX_DIRECT(prAdapter)) { + if (prAdapter->fgTxDirectInited) { + del_timer_sync(&prAdapter->rTxDirectSkbTimer); + del_timer_sync(&prAdapter->rTxDirectHifTimer); + } + } + + /* Destroy wakelock */ + wlanWakeLockUninit(prGlueInfo); + + kalMemSet(&(prGlueInfo->prAdapter->rWlanInfo), 0, sizeof(WLAN_INFO_T)); + +#if CFG_ENABLE_WIFI_DIRECT + if (prGlueInfo->prAdapter->fgIsP2PRegistered) { + DBGLOG(INIT, INFO, "p2pNetUnregister...\n"); + p2pNetUnregister(prGlueInfo, FALSE); + DBGLOG(INIT, INFO, "p2pRemove...\n"); + /*p2pRemove must before wlanAdapterStop */ + p2pRemove(prGlueInfo); + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + if (prGlueInfo->rBowInfo.fgIsRegistered) + glUnregisterAmpc(prGlueInfo); +#endif + + /* 4 <3> Remove /proc filesystem. */ +#if WLAN_INCLUDE_PROC + procRemoveProcfs(); +#endif /* WLAN_INCLUDE_PROC */ + +#if (CFG_MET_PACKET_TRACE_SUPPORT == 1) + kalMetRemoveProcfs(prGlueInfo); +#endif + +#if CFG_MET_TAG_SUPPORT + if (GL_MET_TAG_UNINIT() != 0) + DBGLOG(INIT, ERROR, "MET_TAG_UNINIT error!\n"); +#endif + + /* 4 <4> wlanAdapterStop */ +#if CFG_SUPPORT_AGPS_ASSIST + kalIndicateAgpsNotify(prAdapter, AGPS_EVENT_WLAN_OFF, NULL, 0); +#endif + + wlanAdapterStop(prAdapter); + DBGLOG(INIT, INFO, "Number of Stalled Packets = %d\n", GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum)); + + HAL_LP_OWN_SET(prAdapter, &fgResult); + DBGLOG(INIT, INFO, "HAL_LP_OWN_SET(%d)\n", (uint32_t)fgResult); + + /* 4 Stopping handling interrupt and free IRQ */ + glBusFreeIrq(prDev, prGlueInfo); + + /* 4 <5> Release the Bus */ + glBusRelease(prDev); + + /* 4 <6> Unregister the card */ + wlanNetUnregister(prDev->ieee80211_ptr); + + /* 4 <7> Destroy the device */ + wlanNetDestroy(prDev->ieee80211_ptr); + prDev = NULL; + + tasklet_kill(&prGlueInfo->rTxCompleteTask); + tasklet_kill(&prGlueInfo->rRxTask); + + /* 4 <8> Unregister early suspend callback */ +#if CFG_ENABLE_EARLY_SUSPEND + glUnregisterEarlySuspend(&wlan_early_suspend_desc); +#endif + + gprWdev->netdev = NULL; + + /* 4 <9> Unregister notifier callback */ + wlanUnregisterNotifier(); + +} /* end of wlanRemove() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Driver entry point when the driver is configured as a Linux Module, and +* is called once at module load time, by the user-level modutils +* application: insmod or modprobe. +* +* \retval 0 Success +*/ +/*----------------------------------------------------------------------------*/ +/* 1 Module Entry Point */ +static int initWlan(void) +{ + int ret = 0; + + DBGLOG(INIT, INFO, "initWlan\n"); +#if CFG_CHIP_RESET_SUPPORT + rst_data.entry_conut = 0; +#endif + + +#ifdef CFG_DRIVER_INF_NAME_CHANGE + + if (kalStrLen(gprifnamesta) > CUSTOM_IFNAMESIZ || + kalStrLen(gprifnamep2p) > CUSTOM_IFNAMESIZ || + kalStrLen(gprifnameap) > CUSTOM_IFNAMESIZ) { + DBGLOG(INIT, ERROR, "custom infname len illegal > %d\n", CUSTOM_IFNAMESIZ); + return -EINVAL; + } + +#endif /* CFG_DRIVER_INF_NAME_CHANGE */ + + wlanDebugInit(); + + /* memory pre-allocation */ +#if CFG_PRE_ALLOCATION_IO_BUFFER + kalInitIOBuffer(TRUE); +#else + kalInitIOBuffer(FALSE); +#endif + + +#if WLAN_INCLUDE_PROC + procInitFs(); +#endif + + wlanCreateWirelessDevice(); + if (gprWdev) + glP2pCreateWirelessDevice((P_GLUE_INFO_T) wiphy_priv(gprWdev->wiphy)); + gprP2pWdev = gprP2pRoleWdev[0];/* P2PDev and P2PRole[0] share the same Wdev */ + + ret = ((glRegisterBus(wlanProbe, wlanRemove) == WLAN_STATUS_SUCCESS) ? 0 : -EIO); + + if (ret == -EIO) { + kalUninitIOBuffer(); + return ret; + } + + return ret; +} /* end of initWlan() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Driver exit point when the driver as a Linux Module is removed. Called +* at module unload time, by the user level modutils application: rmmod. +* This is our last chance to clean up after ourselves. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +/* 1 Module Leave Point */ +static VOID exitWlan(void) +{ + /* printk("remove %p\n", wlanRemove); */ + + glUnregisterBus(wlanRemove); + + /* free pre-allocated memory */ + kalUninitIOBuffer(); + wlanDestroyWirelessDevice(); + glP2pDestroyWirelessDevice(); +#if WLAN_INCLUDE_PROC + procUninitProcFs(); +#endif + DBGLOG(INIT, INFO, "exitWlan\n"); + +} /* end of exitWlan() */ + +#if ((MTK_WCN_HIF_SDIO == 1) && (CFG_BUILT_IN_DRIVER == 1)) + +int mtk_wcn_wlan_gen4_init(void) +{ + return initWlan(); +} +EXPORT_SYMBOL(mtk_wcn_wlan_gen4_init); + +void mtk_wcn_wlan_gen4_exit(void) +{ + return exitWlan(); +} +EXPORT_SYMBOL(mtk_wcn_wlan_gen4_exit); + +#elif ((MTK_WCN_HIF_SDIO == 0) && (CFG_BUILT_IN_DRIVER == 1)) + +device_initcall(initWlan); + +#else + +module_init(initWlan); +module_exit(exitWlan); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_kal.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_kal.c new file mode 100644 index 0000000000000..2ee169911701b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_kal.c @@ -0,0 +1,5827 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_kal.c#10 +*/ + +/*! \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. +*/ + + +/******************************************************************************* +* C O M P I L E 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 "gl_wext.h" +#include "precomp.h" +#if CFG_SUPPORT_AGPS_ASSIST +#include +#endif +#include + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define FILE_NAME_MAX CFG_FW_NAME_MAX_LEN /* the maximum length of a file name */ +#define FILE_NAME_TOTAL 8 /* the maximum number of all possible file name */ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +#if DBG +int allocatedMemSize; +#endif + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static PVOID pvIoBuffer; +static UINT_32 pvIoBufferSize; +static UINT_32 pvIoBufferUsage; + +u_int8_t g_fgIsOid = TRUE; +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#if CFG_ENABLE_FW_DOWNLOAD + +#if (defined(CONFIG_UIDGID_STRICT_TYPE_CHECKS) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))) +#define KUIDT_VALUE(v) (v.val) +#define KGIDT_VALUE(v) (v.val) +#else +#define KUIDT_VALUE(v) v +#define KGIDT_VALUE(v) v +#endif + +const struct firmware *fw_entry; + +/* Default */ +static PUINT_8 apucFwName[] = { + (PUINT_8) CFG_FW_FILENAME "_MT", + + NULL +}; + +static PUINT_8 apucCr4FwName[] = { + (PUINT_8) CFG_CR4_FW_FILENAME "_" HIF_NAME "_MT", + (PUINT_8) CFG_CR4_FW_FILENAME "_MT", + NULL +}; + +static PUINT_8 apucPatchName[] = { + (PUINT_8) "mt6632_patch_e1_hdr.bin", + (PUINT_8) "mt7666_patch_e1_hdr.bin", + NULL +}; + +#if CFG_ASSERT_DUMP +/* Core dump debug usage */ +#if MTK_WCN_HIF_SDIO +PUINT_8 apucCorDumpN9FileName = "/data/misc/wifi/FW_DUMP_N9"; +PUINT_8 apucCorDumpCr4FileName = "/data/misc/wifi/FW_DUMP_Cr4"; +#else +PUINT_8 apucCorDumpN9FileName = "/tmp/FW_DUMP_N9"; +PUINT_8 apucCorDumpCr4FileName = "/tmp/FW_DUMP_Cr4"; +#endif +#endif +/*----------------------------------------------------------------------------*/ +/*! +* \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, IN PPUINT_8 apucNameTable) +{ + UINT_8 ucNameIdx; + UINT_8 ucCurEcoVer = wlanGetEcoVersion(prGlueInfo->prAdapter); + BOOLEAN fgResult = FALSE; + int ret; + + /* Try to open FW binary */ + for (ucNameIdx = 0; apucNameTable[ucNameIdx]; ucNameIdx++) { + /* + * Driver support request_firmware() to get files + * Android path: "/etc/firmware", "/vendor/firmware", "/firmware/image" + * Linux path: "/lib/firmware", "/lib/firmware/update" + */ + ret = REQUEST_FIRMWARE(&fw_entry, apucNameTable[ucNameIdx], prGlueInfo->prDev); + + if (ret) { + DBGLOG(INIT, TRACE, "Request FW image: %s failed, errno[%d]\n", + apucNameTable[ucNameIdx], fgResult); + RELEASE_FIRMWARE(fw_entry); + continue; + } else { + DBGLOG(INIT, TRACE, "Request FW image: %s done\n", apucNameTable[ucNameIdx]); + fgResult = TRUE; + break; + } + } + + + /* Check result */ + if (!fgResult) + goto error_open; + + + return WLAN_STATUS_SUCCESS; + +error_open: + DBGLOG(INIT, ERROR, "Request FW image failed! Cur ECO Ver[E%u]\n", + ucCurEcoVer); + + 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) +{ + RELEASE_FIRMWARE(fw_entry); + + 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); + + if ((fw_entry == NULL) || (fw_entry->size == 0) || (fw_entry->data == NULL)) { + goto error_read; + } else { + memcpy(prBuf, fw_entry->data, fw_entry->size); + *pu4Size = fw_entry->size; + } + + return WLAN_STATUS_SUCCESS; + +error_read: + return WLAN_STATUS_FAILURE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to +* query firmware image size in kernel space +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* +* \retval WLAN_STATUS_SUCCESS. +* \retval WLAN_STATUS_FAILURE. +* +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS kalFirmwareSize(IN P_GLUE_INFO_T prGlueInfo, OUT PUINT_32 pu4Size) +{ + ASSERT(prGlueInfo); + ASSERT(pu4Size); + + *pu4Size = fw_entry->size; + + return WLAN_STATUS_SUCCESS; +} + +VOID +kalConstructDefaultFirmwarePrio(P_GLUE_INFO_T prGlueInfo, PPUINT_8 apucNameTable, +PPUINT_8 apucName, PUINT_8 pucNameIdx, UINT_8 ucMaxNameIdx) +{ + struct mt66xx_chip_info *prChipInfo = prGlueInfo->prAdapter->chip_info; + UINT_32 chip_id = prChipInfo->chip_id; + UINT_8 sub_idx = 0; + + for (sub_idx = 0; apucNameTable[sub_idx]; sub_idx++) { + if ((*pucNameIdx + 3) < ucMaxNameIdx) { + /* Type 1. WIFI_RAM_CODE_MTxxxx_Ex */ + snprintf(*(apucName + (*pucNameIdx)), FILE_NAME_MAX, "%s%x_E%u", + apucNameTable[sub_idx], chip_id, + wlanGetEcoVersion(prGlueInfo->prAdapter)); + (*pucNameIdx) += 1; + + /* Type 2. WIFI_RAM_CODE_MTxxxx_Ex.bin */ + snprintf(*(apucName + (*pucNameIdx)), FILE_NAME_MAX, "%s%x_E%u.bin", + apucNameTable[sub_idx], chip_id, + wlanGetEcoVersion(prGlueInfo->prAdapter)); + (*pucNameIdx) += 1; + + /* Type 3. WIFI_RAM_CODE_MTxxxx */ + snprintf(*(apucName + (*pucNameIdx)), FILE_NAME_MAX, "%s%x", + apucNameTable[sub_idx], chip_id); + (*pucNameIdx) += 1; + + /* Type 4. WIFI_RAM_CODE_MTxxxx.bin */ + snprintf(*(apucName + (*pucNameIdx)), FILE_NAME_MAX, "%s%x.bin", + apucNameTable[sub_idx], chip_id); + (*pucNameIdx) += 1; + } else { + /* the table is not large enough */ + DBGLOG(INIT, ERROR, "kalFirmwareImageMapping >> file name array is not enough.\n"); + ASSERT(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, IN ENUM_IMG_DL_IDX_T eDlIdx) +{ + PPUINT_8 apucNameTable = NULL; + PUINT_8 apucName[FILE_NAME_TOTAL + + 1]; /* extra +1, for the purpose of + * detecting the end of the array + */ + UINT_8 idx = 0, max_idx, ucRomVer = 0, + aucNameBody[FILE_NAME_TOTAL][FILE_NAME_MAX], sub_idx = 0; + struct mt66xx_chip_info *prChipInfo = prGlueInfo->prAdapter->chip_info; + UINT_32 chip_id = prChipInfo->chip_id; + + DEBUGFUNC("kalFirmwareImageMapping"); + + ASSERT(prGlueInfo); + ASSERT(ppvMapFileBuf); + ASSERT(pu4FileLength); + + *ppvMapFileBuf = NULL; + *pu4FileLength = 0; + + do { + /* <0.0> Get FW name prefix table */ + switch (eDlIdx) { + case IMG_DL_IDX_N9_FW: + apucNameTable = apucFwName; + break; + + case IMG_DL_IDX_CR4_FW: + apucNameTable = apucCr4FwName; + break; + + case IMG_DL_IDX_PATCH: + apucNameTable = apucPatchName; + break; + + default: + ASSERT(0); + break; + } + + /* <0.2> Construct FW name */ + memset(apucName, 0, sizeof(apucName)); + + /* magic number 1: reservation for detection + * of the end of the array + */ + max_idx = (sizeof(apucName) / sizeof(PUINT_8)) - 1; + + idx = 0; + apucName[idx] = (PUINT_8)(aucNameBody + idx); + + if (eDlIdx == IMG_DL_IDX_PATCH) { + /* construct the file name for patch */ + /* mtxxxx_patch_ex_hdr.bin*/ + ucRomVer = wlanGetRomVersion( + prGlueInfo->prAdapter) + 1; + snprintf(apucName[idx], FILE_NAME_MAX, + "mt%x_patch_e%u_hdr.bin", chip_id, + ucRomVer); + + idx += 1; + } else { + for (sub_idx = 0; sub_idx < max_idx; sub_idx++) + apucName[sub_idx] = (PUINT_8)(aucNameBody + sub_idx); + + if (prChipInfo->constructFirmwarePrio) + prChipInfo->constructFirmwarePrio(prGlueInfo, apucNameTable, apucName, &idx, max_idx); + else + kalConstructDefaultFirmwarePrio(prGlueInfo, apucNameTable, apucName, &idx, max_idx); + } + + /* let the last pointer point to NULL + * so that we can detect the end of the array in kalFirmwareOpen(). + */ + apucName[idx] = NULL; + + apucNameTable = apucName; + + /* <1> Open firmware */ + if (kalFirmwareOpen(prGlueInfo, apucNameTable) != WLAN_STATUS_SUCCESS) + break; + { + 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 + +/*----------------------------------------------------------------------------*/ +/*! +* \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 PULONG plFlags) +{ + ULONG ulFlags = 0; + + ASSERT(prGlueInfo); + ASSERT(plFlags); + + if (rLockCategory < SPIN_LOCK_NUM) { + DBGLOG(INIT, LOUD, "SPIN_LOCK[%u] Try to acquire\n", rLockCategory); +#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], ulFlags); +#endif /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + + *plFlags = ulFlags; + + DBGLOG(INIT, LOUD, "SPIN_LOCK[%u] Acquired\n", rLockCategory); + } + +} /* end of kalAcquireSpinLock() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to release +* OS SPIN_LOCK. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] rLockCategory Specify which SPIN_LOCK +* \param[in] u4Flags Saved IRQ flags +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID kalReleaseSpinLock(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, IN ULONG ulFlags) +{ + 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], ulFlags); +#endif /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + DBGLOG(INIT, LOUD, "SPIN_UNLOCK[%u]\n", rLockCategory); + } + +} /* end of kalReleaseSpinLock() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to acquire +* OS MUTEX. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] rMutexCategory Specify which MUTEX +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID kalAcquireMutex(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_MUTEX_CATEGORY_E rMutexCategory) +{ + ASSERT(prGlueInfo); + + if (rMutexCategory < MUTEX_NUM) { + DBGLOG(INIT, TRACE, "MUTEX_LOCK[%u] Try to acquire\n", rMutexCategory); + mutex_lock(&prGlueInfo->arMutex[rMutexCategory]); + DBGLOG(INIT, TRACE, "MUTEX_LOCK[%u] Acquired\n", rMutexCategory); + } + +} /* end of kalAcquireMutex() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to release +* OS MUTEX. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] rMutexCategory Specify which MUTEX +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID kalReleaseMutex(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_MUTEX_CATEGORY_E rMutexCategory) +{ + ASSERT(prGlueInfo); + + if (rMutexCategory < MUTEX_NUM) { + mutex_unlock(&prGlueInfo->arMutex[rMutexCategory]); + DBGLOG(INIT, TRACE, "MUTEX_UNLOCK[%u]\n", rMutexCategory); + } + +} /* end of kalReleaseMutex() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to update +* current MAC address. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pucMacAddr Pointer of current MAC address +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID kalUpdateMACAddress(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucMacAddr) +{ + ASSERT(prGlueInfo); + ASSERT(pucMacAddr); + + if (UNEQUAL_MAC_ADDR(prGlueInfo->prDevHandler->dev_addr, pucMacAddr)) + memcpy(prGlueInfo->prDevHandler->dev_addr, pucMacAddr, PARAM_MAC_ADDR_LEN); + +} + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +/*----------------------------------------------------------------------------*/ +/*! +* \brief To query the packet information for offload related parameters. +* +* \param[in] pvPacket Pointer to the packet descriptor. +* \param[in] pucFlag Points to the offload related parameter. +* +* \return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID kalQueryTxChksumOffloadParam(IN PVOID pvPacket, OUT PUINT_8 pucFlag) +{ + struct sk_buff *skb = (struct sk_buff *)pvPacket; + UINT_8 ucFlag = 0; + + ASSERT(pvPacket); + ASSERT(pucFlag); + + if (skb->ip_summed == CHECKSUM_PARTIAL) { +#if DBG + /* Kevin: do double check, we can remove this part in Normal Driver. + * Because we register NIC feature with NETIF_F_IP_CSUM for MT5912B MAC, so + * we'll process IP packet only. + */ + if (skb->protocol != htons(ETH_P_IP)) { + /* printk("Wrong skb->protocol( = %08x) for TX Checksum Offload.\n", skb->protocol); */ + } else +#endif + ucFlag |= (TX_CS_IP_GEN | TX_CS_TCP_UDP_GEN); + } + + *pucFlag = ucFlag; + +} /* kalQueryChksumOffloadParam */ + +/* 4 2007/10/8, mikewu, this is rewritten by Mike */ +/*----------------------------------------------------------------------------*/ +/*! +* \brief To update the checksum offload status to the packet to be indicated to OS. +* +* \param[in] pvPacket Pointer to the packet descriptor. +* \param[in] pucFlag Points to the offload related parameter. +* +* \return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID kalUpdateRxCSUMOffloadParam(IN PVOID pvPacket, IN ENUM_CSUM_RESULT_T aeCSUM[]) +{ + struct sk_buff *skb = (struct sk_buff *)pvPacket; + + ASSERT(pvPacket); + + if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_SUCCESS || aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_SUCCESS) + && ((aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_SUCCESS) + || (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_SUCCESS))) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + } else { + skb->ip_summed = CHECKSUM_NONE; +#if DBG + if (aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_NONE && aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_NONE) + DBGLOG(RX, TRACE, "RX: \"non-IPv4/IPv6\" Packet\n"); + else if (aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_FAILED) + DBGLOG(RX, TRACE, "RX: \"bad IP Checksum\" Packet\n"); + else if (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_FAILED) + DBGLOG(RX, TRACE, "RX: \"bad TCP Checksum\" Packet\n"); + else if (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_FAILED) + DBGLOG(RX, TRACE, "RX: \"bad UDP Checksum\" Packet\n"); + +#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; + UINT_32 u4flag = 0; + + /* Enable __GFP_NORETRY to prevent oom issue when WiFi traffic */ + /* Only Disable __GFP_NORETRY for nicRxInitialize */ + if (prGlueInfo->prAdapter->fgIsFwDownloaded) + u4flag = __GFP_NORETRY; + + if (in_interrupt()) { + u4flag |= (GFP_ATOMIC | __GFP_NOWARN); + prSkb = __dev_alloc_skb(u4Size + NIC_TX_HEAD_ROOM, u4flag); + } else { + u4flag |= (GFP_KERNEL); + prSkb = __dev_alloc_skb(u4Size + NIC_TX_HEAD_ROOM, u4flag); + } + + if (prSkb) { + skb_reserve(prSkb, NIC_TX_HEAD_ROOM); + + *ppucData = (PUINT_8) (prSkb->data); + + /* DBGLOG(TDLS, INFO, "kalPacketAlloc, skb head[0x%x] data[0x%x] tail[0x%x] end[0x%x]\n", + * prSkb->head, prSkb->data, prSkb->tail, prSkb->end); + */ + + kalResetPacket(prGlueInfo, (P_NATIVE_PACKET) prSkb); + } +#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; + + /* Reset skb */ + skb_reset_tail_pointer(skb); + skb_trim(skb, 0); + + /* Put data */ + skb_put(skb, u4PacketLen); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + if (prGlueInfo->prAdapter->fgIsSupportCsumOffload) + 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; + + ASSERT(prGlueInfo); + ASSERT(apvPkts); + + for (ucIdx = 0; ucIdx < ucPktNum; ucIdx++) + kalRxIndicateOnePkt(prGlueInfo, apvPkts[ucIdx]); + + KAL_WAKE_LOCK_TIMEOUT(prGlueInfo->prAdapter, &prGlueInfo->rTimeoutWakeLock, + MSEC_TO_JIFFIES(prGlueInfo->prAdapter->rWifiVar.u4WakeLockRxTimeout)); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate one received packets is available for higher +* level protocol uses. +* +* \param[in] prGlueInfo Pointer to the Adapter structure. +* \param[in] pvPkt The packet to be indicated +* +* \retval TRUE Success. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS kalRxIndicateOnePkt(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPkt) +{ + struct net_device *prNetDev = prGlueInfo->prDevHandler; + struct sk_buff *prSkb = NULL; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prGlueInfo); + ASSERT(pvPkt); + + prSkb = pvPkt; + prChipInfo = prGlueInfo->prAdapter->chip_info; +#if DBG && 0 + 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 1 + + prNetDev = (struct net_device *)wlanGetNetInterfaceByBssIdx(prGlueInfo, GLUE_GET_PKT_BSS_IDX(prSkb)); + if (!prNetDev) + prNetDev = prGlueInfo->prDevHandler; +#if CFG_SUPPORT_SNIFFER + if (prGlueInfo->fgIsEnableMon) + prNetDev = prGlueInfo->prMonDevHandler; +#endif + prNetDev->stats.rx_bytes += prSkb->len; + prNetDev->stats.rx_packets++; +#else + 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[0]->rNetDevStats.rx_bytes += prSkb->len; + prGlueInfo->prP2PInfo[0]->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++; + + } +#endif +#if KERNEL_VERSION(4, 11, 0) > CFG80211_VERSION_CODE + prNetDev->last_rx = jiffies; +#endif +#if CFG_SUPPORT_SNIFFER + if (prGlueInfo->fgIsEnableMon) { + skb_reset_mac_header(prSkb); + prSkb->ip_summed = CHECKSUM_UNNECESSARY; + prSkb->pkt_type = PACKET_OTHERHOST; + prSkb->protocol = htons(ETH_P_802_2); + } else { + prSkb->protocol = eth_type_trans(prSkb, prNetDev); + } +#else + prSkb->protocol = eth_type_trans(prSkb, prNetDev); +#endif + prSkb->dev = prNetDev; + /* DBGLOG_MEM32(RX, TRACE, (PUINT_32)prSkb->data, prSkb->len); */ + /* DBGLOG(RX, EVENT, ("kalRxIndicatePkts len = %d\n", prSkb->len)); */ + if (prSkb->tail > prSkb->end) { + DBGLOG(RX, ERROR, +#ifdef NET_SKBUFF_DATA_USES_OFFSET + "kalRxIndicateOnePkt [prSkb = 0x%p][prSkb->len = %d][prSkb->protocol = 0x%02x] %u,%u\n", +#else + "kalRxIndicateOnePkt [prSkb = 0x%p][prSkb->len = %d][prSkb->protocol = 0x%02x] %p,%p\n", +#endif + (PUINT_8) prSkb, prSkb->len, prSkb->protocol, prSkb->tail, prSkb->end); + DBGLOG_MEM32(RX, ERROR, (PUINT_32) prSkb->data, prSkb->len); + } + + if (prSkb->protocol == NTOHS(ETH_P_8021Q) + && !FEAT_SUP_LLC_VLAN_RX(prChipInfo)) { + /* + * DA-MAC + SA-MAC + 0x8100 was removed in eth_type_trans() + * pkt format here is TCI(2-bytes) + Len(2-btyes) + payload-type(2-bytes) + payload + * Remove "Len" field inserted by RX VLAN header translation + * Note: TCI+payload-type is a standard 8021Q header + * + * This format update is based on RX VLAN HW header translation. + * If the setting was changed, you may need to change rules here as well. + */ + const UINT_8 vlan_skb_mem_move = 2; + + /* Remove "Len" and shift data pointer 2 bytes */ + kalMemCopy(prSkb->data+vlan_skb_mem_move, prSkb->data, vlan_skb_mem_move); + skb_pull_rcsum(prSkb, vlan_skb_mem_move); + + /* Have to update MAC header properly. Otherwise, wrong MACs woud be passed up */ + kalMemMove(prSkb->data - ETH_HLEN, prSkb->data - ETH_HLEN - vlan_skb_mem_move, ETH_HLEN); + prSkb->mac_header += vlan_skb_mem_move; + + skb_reset_network_header(prSkb); + skb_reset_transport_header(prSkb); + kal_skb_reset_mac_len(prSkb); + } + + if (prSkb->protocol == HTONS(ETH_P_1X)) + DBGLOG(RSN, STATE, "Rx EAPOL Frame [Len: %d]\n", prSkb->len); + + if (!in_interrupt()) + netif_rx_ni(prSkb); /* only in non-interrupt context */ + else + netif_rx(prSkb); + + 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; + PARAM_SSID_T ssid; + struct ieee80211_channel *prChannel = NULL; + struct cfg80211_bss *bss; + UINT_8 ucChannelNum; + P_BSS_DESC_T prBssDesc = NULL; + struct wiphy *wiphy = NULL; + gfp_t flags = GFP_KERNEL; + + 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); +#if CFG_SUPPORT_CFG80211_AUTH /* Report RX association response frame */ + DBGLOG(INIT, INFO, + "Skip report CONNECTED when using supplicant SME\n"); + return; +#endif + 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, + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex); + if (ucChannelNum <= 14) { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency + (ucChannelNum, KAL_BAND_2GHZ)); + } else { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency + (ucChannelNum, KAL_BAND_5GHZ)); + } + + /* ensure BSS exists */ +#if KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE + bss = cfg80211_get_bss(priv_to_wiphy(prGlueInfo), + prChannel, arBssid, + ssid.aucSsid, ssid.u4SsidLen, + IEEE80211_BSS_TYPE_ESS, + IEEE80211_PRIVACY_ANY); +#else + bss = cfg80211_get_bss(priv_to_wiphy(prGlueInfo), + prChannel, arBssid, + ssid.aucSsid, ssid.u4SsidLen, + WLAN_CAPABILITY_ESS, + WLAN_CAPABILITY_ESS); +#endif + + if (bss == NULL) { + /* create BSS on-the-fly */ + prBssDesc = ((P_AIS_FSM_INFO_T) + (&(prGlueInfo->prAdapter->rWifiVar.rAisFsmInfo)))->prTargetBssDesc; + + if (prChannel && prBssDesc != NULL) { +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE + bss = cfg80211_inform_bss(priv_to_wiphy(prGlueInfo), + prChannel, + CFG80211_BSS_FTYPE_PRESP, + arBssid, + 0, /* TSF */ + WLAN_CAPABILITY_ESS, + prBssDesc->u2BeaconInterval, /* beacon interval */ + prBssDesc->aucIEBuf, /* IE */ + prBssDesc->u2IELength, /* IE Length */ + RCPI_TO_dBm(prBssDesc->ucRCPI) * 100, /* MBM */ + GFP_KERNEL); +#else + 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); +#endif + } + } + /* CFG80211 Indication */ + if (eStatus == WLAN_STATUS_ROAM_OUT_FIND_BEST) { + struct ieee80211_channel *prChannel = NULL; + UINT_8 ucChannelNum = wlanGetChannelNumberByNetwork(prGlueInfo->prAdapter, + prGlueInfo->prAdapter-> + prAisBssInfo->ucBssIndex); +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE + struct cfg80211_roam_info rRoamInfo = {}; +#endif + + if (ucChannelNum <= 14) { + prChannel = ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency + (ucChannelNum, KAL_BAND_2GHZ)); + } else { + prChannel = ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency + (ucChannelNum, KAL_BAND_5GHZ)); + } + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE + rRoamInfo.channel = prChannel; + rRoamInfo.bss = bss; + rRoamInfo.bssid = arBssid; + rRoamInfo.req_ie = prGlueInfo->aucReqIe; + rRoamInfo.req_ie_len = + prGlueInfo->u4ReqIeLength; + rRoamInfo.resp_ie = prGlueInfo->aucRspIe; + rRoamInfo.resp_ie_len = + prGlueInfo->u4RspIeLength; +#if ((KERNEL_VERSION(4, 13, 0) <= CFG80211_VERSION_CODE) \ + && (KERNEL_VERSION(4, 14, 0) >= CFG80211_VERSION_CODE)) + rRoamInfo.authorized = FALSE; +#endif + cfg80211_roamed(prGlueInfo->prDevHandler, + &rRoamInfo, GFP_KERNEL); +#else + cfg80211_roamed(prGlueInfo->prDevHandler, + prChannel, + arBssid, + prGlueInfo->aucReqIe, + prGlueInfo->u4ReqIeLength, + prGlueInfo->aucRspIe, prGlueInfo->u4RspIeLength, GFP_KERNEL); +#endif + /* cfg80211_roamed = + * cfg80211_get_bss + cfg80211_roamed_bss. + * If replace the cfg80211_roamed by + * cfg80211_roamed_bss, don't do the following + * cfg80211_put_bss. + */ + } else { + cfg80211_connect_result(prGlueInfo->prDevHandler, arBssid, + prGlueInfo->aucReqIe, + prGlueInfo->u4ReqIeLength, + prGlueInfo->aucRspIe, + prGlueInfo->u4RspIeLength, WLAN_STATUS_SUCCESS, GFP_KERNEL); + } + + /* cfg80211_put_bss decreases the bss refcount. + * The __cfg80211_unlink_bss will remove the bss from + * bss_list, and refcount--. If refcount == 0, free it. + * So that, the bss may be not freed with an incorrect + * refcount. + */ + if (bss != NULL) { + wiphy = priv_to_wiphy(prGlueInfo); + cfg80211_put_bss(wiphy, bss); + } + + } + + break; + + case WLAN_STATUS_MEDIA_DISCONNECT: + case WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY: + /* 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 + + if (prGlueInfo->prAdapter->fgIsChipAssert) + flags = GFP_ATOMIC; + + netif_carrier_off(prGlueInfo->prDevHandler); +#if CFG_SUPPORT_CFG80211_AUTH + /* Report T/RX deauth/disassociation frame */ + DBGLOG(INIT, INFO, + "Skip report DISCONNECTED when using supplicant SME\n"); +#else + if (prGlueInfo->fgIsRegistered == TRUE) { + P_BSS_INFO_T prBssInfo = prGlueInfo->prAdapter->prAisBssInfo; + UINT_16 u2DeauthReason = 0; + /* indicate disassoc event */ + wext_indicate_wext_event(prGlueInfo, + SIOCGIWAP, NULL, 0); +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) + + if (prBssInfo) + u2DeauthReason = prBssInfo->u2DeauthReason; + /* CFG80211 Indication */ + DBGLOG(INIT, INFO, "[wifi]Indicate disconnection: Locally[%d]\n", + (eStatus == WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY)); + cfg80211_disconnected(prGlueInfo->prDevHandler, u2DeauthReason, NULL, 0, + eStatus == WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY, + flags); + +#else + +#ifdef CONFIG_ANDROID +#if LINUX_VERSION_CODE == KERNEL_VERSION(3, 10, 0) + /* Don't indicate disconnection to upper layer for ANDROID kernel 3.10 */ + /* since cfg80211 will indicate disconnection to wpa_supplicant for this kernel */ + if (eStatus == WLAN_STATUS_MEDIA_DISCONNECT) +#endif +#endif + { + + + if (prBssInfo) + u2DeauthReason = prBssInfo->u2DeauthReason; + /* CFG80211 Indication */ + cfg80211_disconnected(prGlueInfo->prDevHandler, u2DeauthReason, NULL, 0, + flags); + } + + +#endif + } +#endif /* CFG_SUPPORT_CFG80211_AUTH */ + + prGlueInfo->eParamMediaStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; + + break; + + case WLAN_STATUS_SCAN_COMPLETE: + case WLAN_STATUS_SCAN_ABORT: + /* 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) { + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + break; + } + /* 2. then CFG80211 Indication */ + kalCfg80211ScanDone(prGlueInfo->prScanRequest, + eStatus == WLAN_STATUS_SCAN_ABORT ? TRUE : FALSE); + prGlueInfo->prScanRequest = NULL; + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + 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; + + for (i = 0; i < pPmkid->u4NumCandidates; i++) { + wext_indicate_wext_event(prGlueInfo, + IWEVPMKIDCAND, + (unsigned char *)&pPmkid->arCandidateList[i], + pPmkid->u4NumCandidates); + } + } + break; + + default: + /* case ENUM_STATUS_TYPE_MEDIA_STREAM_MODE */ + /* + * printk(KERN_NOTICE "unknown media specific indication type:%x\n", + * pStatus->StatusType); + */ + break; + } + } else { + /* + * printk(KERN_WARNING "media specific indication buffer NULL\n"); + */ + } + break; + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS + case WLAN_STATUS_BWCS_UPDATE: + { + wext_indicate_wext_event(prGlueInfo, IWEVCUSTOM, pvBuf, sizeof(PTA_IPC_T)); + } + + break; + +#endif + case WLAN_STATUS_JOIN_TIMEOUT: + { + P_BSS_DESC_T prBssDesc = prGlueInfo->prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc; + + if (prBssDesc) + COPY_MAC_ADDR(arBssid, prBssDesc->aucBSSID); + cfg80211_connect_result(prGlueInfo->prDevHandler, + arBssid, + prGlueInfo->aucReqIe, + prGlueInfo->u4ReqIeLength, + prGlueInfo->aucRspIe, + prGlueInfo->u4RspIeLength, WLAN_STATUS_AUTH_TIMEOUT, GFP_KERNEL); + break; + } + default: + /* + * printk(KERN_WARNING "unknown indication:%lx\n", eStatus); + */ + break; + } +} /* kalIndicateStatusAndComplete */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to update the (re)association request +* information to the structure used to query and set +* OID_802_11_ASSOCIATION_INFORMATION. +* +* \param[in] prGlueInfo Pointer to the Glue structure. +* \param[in] pucFrameBody Pointer to the frame body of the last (Re)Association +* Request frame from the AP. +* \param[in] u4FrameBodyLen The length of the frame body of the last +* (Re)Association Request frame. +* \param[in] fgReassocRequest TRUE, if it is a Reassociation Request frame. +* +* \return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalUpdateReAssocReqInfo(IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBody, IN UINT_32 u4FrameBodyLen, IN BOOLEAN fgReassocRequest) +{ + PUINT_8 cp; + + ASSERT(prGlueInfo); + + /* reset */ + prGlueInfo->u4ReqIeLength = 0; + + if (fgReassocRequest) { + if (u4FrameBodyLen < 15) { + /* + * printk(KERN_WARNING "frameBodyLen too short:%ld\n", frameBodyLen); + */ + return; + } + } else { + if (u4FrameBodyLen < 9) { + /* + * printk(KERN_WARNING "frameBodyLen too short:%ld\n", frameBodyLen); + */ + return; + } + } + + cp = pucFrameBody; + + if (fgReassocRequest) { + /* Capability information field 2 */ + /* Listen interval field 2 */ + /* Current AP address 6 */ + cp += 10; + u4FrameBodyLen -= 10; + } else { + /* Capability information field 2 */ + /* Listen interval field 2 */ + cp += 4; + u4FrameBodyLen -= 4; + } + + wext_indicate_wext_event(prGlueInfo, IWEVASSOCREQIE, cp, u4FrameBodyLen); + + if (u4FrameBodyLen <= CFG_CFG80211_IE_BUF_LEN) { + prGlueInfo->u4ReqIeLength = u4FrameBodyLen; + kalMemCopy(prGlueInfo->aucReqIe, cp, u4FrameBodyLen); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This routine is called to update the (re)association +* response information to the structure used to reply with +* cfg80211_connect_result +* +* @param prGlueInfo Pointer to adapter descriptor +* @param pucFrameBody Pointer to the frame body of the last (Re)Association +* Response frame from the AP +* @param u4FrameBodyLen The length of the frame body of the last +* (Re)Association Response frame +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID kalUpdateReAssocRspInfo(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucFrameBody, IN UINT_32 u4FrameBodyLen) +{ + UINT_32 u4IEOffset = 6; /* cap_info, status_code & assoc_id */ + UINT_32 u4IELength = u4FrameBodyLen - u4IEOffset; + + ASSERT(prGlueInfo); + + /* reset */ + prGlueInfo->u4RspIeLength = 0; + + if (u4IELength <= CFG_CFG80211_IE_BUF_LEN) { + prGlueInfo->u4RspIeLength = u4IELength; + kalMemCopy(prGlueInfo->aucRspIe, pucFrameBody + u4IEOffset, u4IELength); + } + +} /* kalUpdateReAssocRspInfo */ + +VOID kalResetPacket(IN P_GLUE_INFO_T prGlueInfo, IN P_NATIVE_PACKET prPacket) +{ + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + + /* Reset cb */ + kalMemZero(prSkb->cb, sizeof(prSkb->cb)); +} + +/*----------------------------------------------------------------------------*/ +/* +* \brief This function is to check the pairwise eapol and wapi 1x. +* +* \param[in] prPacket Pointer to struct net_device +* +* \retval WLAN_STATUS +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalIsPairwiseEapolPacket(IN P_NATIVE_PACKET prPacket) +{ + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + PUINT_8 pucPacket = (PUINT_8)prSkb->data; + UINT_16 u2EthType = 0; + UINT_16 u2KeyInfo = 0; + + WLAN_GET_FIELD_BE16(&pucPacket[ETHER_HEADER_LEN - ETHER_TYPE_LEN], &u2EthType); +#if CFG_SUPPORT_WAPI + /* prBssInfo && prBssInfo->eNetworkType == NETWORK_TYPE_AIS && wlanQueryWapiMode(prAdapter) */ + if (u2EthType == ETH_WPI_1X) + return TRUE; +#endif + if (u2EthType != ETH_P_1X) + return FALSE; + u2KeyInfo = pucPacket[5+ETHER_HEADER_LEN]<<8 | pucPacket[6+ETHER_HEADER_LEN]; +#if 1 + /* BIT3 is pairwise key bit, and check SM is 0. it means this is 4-way handshake frame */ + DBGLOG(RSN, INFO, "u2KeyInfo=%d\n", u2KeyInfo); + if ((u2KeyInfo & BIT(3)) && !(u2KeyInfo & BIT(13))) + return TRUE; +#else + /* BIT3 is pairwise key bit, bit 8 is key mic bit. + * only the two bits are set, it means this is 4-way handshake 4/4 or 2/4 frame + */ + DBGLOG(RSN, INFO, "u2KeyInfo=%d\n", u2KeyInfo); + if ((u2KeyInfo & (BIT(3) | BIT(8))) == (BIT(3) | BIT(8))) + return TRUE; +#endif + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/* +* \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 +* \param[in] prGlueInfo Pointer of prGlueInfo +* \param[in] ucBssIndex BSS index of this net device +* +* \retval WLAN_STATUS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +kalHardStartXmit(struct sk_buff *prOrgSkb, IN struct net_device *prDev, P_GLUE_INFO_T prGlueInfo, UINT_8 ucBssIndex) +{ + P_QUE_ENTRY_T prQueueEntry = NULL; + P_QUE_T prTxQueue = NULL; + UINT_16 u2QueueIdx = 0; + UINT_32 u4MaxTxPendingNum = prGlueInfo->prAdapter->rWifiVar.u4NetifStopTh; + struct sk_buff *prSkbNew = NULL; + struct sk_buff *prSkb = NULL; + + ASSERT(prOrgSkb); + ASSERT(prGlueInfo); + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(INIT, INFO, "GLUE_FLAG_HALT skip tx\n"); + dev_kfree_skb(prOrgSkb); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + +#if defined(_HIF_USB) + if (prGlueInfo->rHifInfo.state != USB_STATE_LINK_UP) { + DBGLOG(INIT, WARN, "USB in suspend skip tx\n"); + dev_kfree_skb(prOrgSkb); + return WLAN_STATUS_ADAPTER_NOT_READY; + } +#endif + + if (prGlueInfo->prAdapter->fgIsEnableLpdvt) { + DBGLOG(INIT, INFO, "LPDVT enable, skip this frame\n"); + dev_kfree_skb(prOrgSkb); + return WLAN_STATUS_NOT_ACCEPTED; + } + + if (skb_headroom(prOrgSkb) < NIC_TX_HEAD_ROOM) { + prSkbNew = skb_realloc_headroom(prOrgSkb, NIC_TX_HEAD_ROOM); + ASSERT(prSkbNew); + prSkb = prSkbNew; + dev_kfree_skb(prOrgSkb); + } else + prSkb = prOrgSkb; + + prQueueEntry = (P_QUE_ENTRY_T) GLUE_GET_PKT_QUEUE_ENTRY(prSkb); + prTxQueue = &prGlueInfo->rTxQueue; + + GLUE_SET_PKT_BSS_IDX(prSkb, ucBssIndex); + + /* Parsing frame info */ + if (!wlanProcessTxFrame(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb)) { + /* Cannot extract packet */ + DBGLOG(INIT, INFO, "Cannot extract content, skip this frame\n"); + dev_kfree_skb(prSkb); + return WLAN_STATUS_INVALID_PACKET; + } + + /* Tx profiling */ + wlanTxProfilingTagPacket(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb, TX_PROF_TAG_OS_TO_DRV); + + /* Handle normal data frame */ + u2QueueIdx = skb_get_queue_mapping(prSkb); + + if (u2QueueIdx >= CFG_MAX_TXQ_NUM) { + DBGLOG(INIT, INFO, "Incorrect queue index, skip this frame\n"); + dev_kfree_skb(prSkb); + return WLAN_STATUS_INVALID_PACKET; + } + + if (!HAL_IS_TX_DIRECT(prGlueInfo->prAdapter)) { + GLUE_SPIN_LOCK_DECLARATION(); + + 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[ucBssIndex][u2QueueIdx]); + + /* + * WMM flow control + * 1. To enlarge threshold for WMM certification, WMM phase two may hit netif_stop_subquene + * Which may cause test case fail due to high priority packets are not enough. + * 2. Dynamic control threshold for AC queue. + * If there is high priority traffic, decrease low priority threshold. + * If these is low priority traffic, increase high priority threshold. + * Else, remians the original threshold. + */ + if (prGlueInfo->prAdapter->rWifiVar.ucTpTestMode == ENUM_TP_TEST_MODE_SIGMA_AC_N_PMF) { + P_BSS_INFO_T prWmmBssInfo = prGlueInfo->prAdapter->aprBssInfo[ucBssIndex]; + + if ((u2QueueIdx < 3) && + (GLUE_GET_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex][u2QueueIdx+1]) + > CFG_CERT_WMM_MAX_TX_PENDING)) { + /* + * Use au8Statistics[RX_SIZE_ERR_DROP_COUNT] to track RX traffic in certification. + */ + if ((prWmmBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) && + ((prDev->stats.rx_packets - + (prGlueInfo->prAdapter->rRxCtrl.au8Statistics[RX_SIZE_ERR_DROP_COUNT])) + > CFG_CERT_WMM_MAX_RX_NUM)) + + u4MaxTxPendingNum = CFG_CERT_WMM_LOW_STOP_TX_WITH_RX; + + else + u4MaxTxPendingNum = CFG_CERT_WMM_LOW_STOP_TX_WO_RX; + } + else if ((u2QueueIdx > 0) && + (GLUE_GET_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex][u2QueueIdx-1]) + > CFG_CERT_WMM_MAX_TX_PENDING)) { + /* + * Use au8Statistics[RX_SIZE_ERR_DROP_COUNT] to track RX traffic in certification. + */ + if ((prWmmBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) && + ((prDev->stats.rx_packets - + (prGlueInfo->prAdapter->rRxCtrl.au8Statistics[RX_SIZE_ERR_DROP_COUNT])) + > CFG_CERT_WMM_MAX_RX_NUM)) + + u4MaxTxPendingNum = CFG_CERT_WMM_HIGH_STOP_TX_WITH_RX; + + else + u4MaxTxPendingNum = CFG_CERT_WMM_HIGH_STOP_TX_WO_RX; + } + else + u4MaxTxPendingNum = prGlueInfo->prAdapter->rWifiVar.u4NetifStopTh; + } + + if (GLUE_GET_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex][u2QueueIdx]) + >= u4MaxTxPendingNum) { + netif_stop_subqueue(prDev, u2QueueIdx); + + DBGLOG(TX, TRACE, + "Stop subqueue for BSS[%u] QIDX[%u] PKT_LEN[%u] TOT_CNT[%d] PER-Q_CNT[%d]\n", + ucBssIndex, u2QueueIdx, prSkb->len, + GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum), + GLUE_GET_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex] + [u2QueueIdx])); + + /* Re-use au8Statistics[RX_SIZE_ERR_DROP_COUNT] buffer to track RX traffic in certification */ + if (prGlueInfo->prAdapter->rWifiVar.ucTpTestMode == ENUM_TP_TEST_MODE_SIGMA_AC_N_PMF) + prGlueInfo->prAdapter->rRxCtrl.au8Statistics[RX_SIZE_ERR_DROP_COUNT] = prDev->stats.rx_packets; + } + + /* Update NetDev statisitcs */ + prDev->stats.tx_bytes += prSkb->len; + prDev->stats.tx_packets++; + + DBGLOG(TX, LOUD, + "Enqueue frame for BSS[%u] QIDX[%u] PKT_LEN[%u] TOT_CNT[%d] PER-Q_CNT[%d]\n", + ucBssIndex, u2QueueIdx, prSkb->len, + GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum), + GLUE_GET_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex][u2QueueIdx])); + + if (HAL_IS_TX_DIRECT(prGlueInfo->prAdapter)) + return nicTxDirectStartXmit(prSkb, prGlueInfo); + + kalSetEvent(prGlueInfo); + + return WLAN_STATUS_SUCCESS; +} /* end of kalHardStartXmit() */ + +WLAN_STATUS kalResetStats(IN struct net_device *prDev) +{ + DBGLOG(QM, INFO, "Reset NetDev[0x%p] statistics\n", prDev); + + kalMemZero(kalGetStats(prDev), sizeof(struct net_device_stats)); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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. +*/ +/*----------------------------------------------------------------------------*/ +PVOID kalGetStats(IN struct net_device *prDev) +{ + return (PVOID) &prDev->stats; +} /* end of wlanGetStats() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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 ucBssIndex = 0; + BOOLEAN fgIsValidDevice = TRUE; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(pvPacket); + /* ASSERT(prGlueInfo->i4TxPendingFrameNum); */ + + prSkb = (struct sk_buff *)pvPacket; + u2QueueIdx = skb_get_queue_mapping(prSkb); + ASSERT(u2QueueIdx < CFG_MAX_TXQ_NUM); + + ucBssIndex = GLUE_GET_PKT_BSS_IDX(pvPacket); + +#if 0 + if ((GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum) <= 0)) { + UINT_8 ucBssIdx; + UINT_16 u2QIdx; + + DBGLOG(INIT, INFO, "TxPendingFrameNum[%u] CurFrameId[%u]\n", prGlueInfo->i4TxPendingFrameNum, + GLUE_GET_PKT_ARRIVAL_TIME(pvPacket)); + + for (ucBssIdx = 0; ucBssIdx < HW_BSSID_NUM; ucBssIdx++) { + for (u2QIdx = 0; u2QIdx < CFG_MAX_TXQ_NUM; u2QIdx++) { + DBGLOG(INIT, INFO, "BSS[%u] Q[%u] TxPendingFrameNum[%u]\n", + ucBssIdx, u2QIdx, prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIdx][u2QIdx]); + } + } + } + + ASSERT((GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum) > 0)); +#endif + + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingFrameNum); + GLUE_DEC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex][u2QueueIdx]); + + DBGLOG(TX, LOUD, + "Release frame for BSS[%u] QIDX[%u] PKT_LEN[%u] TOT_CNT[%d] PER-Q_CNT[%d]\n", + ucBssIndex, u2QueueIdx, prSkb->len, + GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum), + GLUE_GET_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex][u2QueueIdx])); + + prDev = prSkb->dev; + + ASSERT(prDev); + +#if CFG_ENABLE_WIFI_DIRECT + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + { + P_BSS_INFO_T prBssInfo = GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, ucBssIndex); + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + struct net_device *prNetdevice = NULL; + + /* in case packet was sent after P2P device is unregistered or the net_device was be free */ + if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) { + if (prGlueInfo->prAdapter->fgIsP2PRegistered == FALSE) + fgIsValidDevice = FALSE; + else { + ASSERT(prBssInfo->u4PrivateData < KAL_P2P_NUM); + prGlueP2pInfo = prGlueInfo->prP2PInfo[prBssInfo->u4PrivateData]; + if (prGlueP2pInfo) { + prNetdevice = prGlueP2pInfo->aprRoleHandler; + /* The net_device may be free */ + if ((prDev != prNetdevice) && (prDev != prGlueP2pInfo->prDevHandler)) { + fgIsValidDevice = FALSE; + DBGLOG(TX, LOUD, + "kalSendCompleteAndAwakeQueue net device deleted! ucBssIndex = %u\n", + ucBssIndex); + } + } + } + } + } +#endif + + if (fgIsValidDevice == TRUE) { + UINT_32 u4StartTh = prGlueInfo->prAdapter->rWifiVar.u4NetifStartTh; + + if (netif_subqueue_stopped(prDev, prSkb) && + prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex][u2QueueIdx] <= u4StartTh) { + netif_wake_subqueue(prDev, u2QueueIdx); + DBGLOG(TX, TRACE, + "WakeUp Queue BSS[%u] QIDX[%u] PKT_LEN[%u] TOT_CNT[%d] PER-Q_CNT[%d]\n", + ucBssIndex, u2QueueIdx, prSkb->len, + GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum), + GLUE_GET_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[ucBssIndex] + [u2QueueIdx])); + } + } + +#if CFG_ENABLE_WIFI_DIRECT + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); +#endif + + dev_kfree_skb_any((struct sk_buff *)pvPacket); + + DBGLOG(TX, LOUD, "----- pending frame %d -----\n", prGlueInfo->i4TxPendingFrameNum); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Copy Mac Address setting from registry. It's All Zeros in Linux. +* +* \param[in] prAdapter Pointer to the Adapter structure +* +* \param[out] paucMacAddr Pointer to the Mac Address buffer +* +* \retval WLAN_STATUS_SUCCESS +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +VOID kalQueryRegistryMacAddr(IN P_GLUE_INFO_T prGlueInfo, OUT PUINT_8 paucMacAddr) +{ + UINT_8 aucZeroMac[MAC_ADDR_LEN] = { 0, 0, 0, 0, 0, 0 } + + DEBUGFUNC("kalQueryRegistryMacAddr"); + + ASSERT(prGlueInfo); + ASSERT(paucMacAddr); + + kalMemCopy((PVOID) paucMacAddr, (PVOID) aucZeroMac, MAC_ADDR_LEN); + +} /* end of kalQueryRegistryMacAddr() */ + +#if CFG_SUPPORT_EXT_CONFIG +/*----------------------------------------------------------------------------*/ +/*! +* \brief Read external configuration, ex. NVRAM or file +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 kalReadExtCfg(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + /* External data is given from user space by ioctl or /proc, not read by + * driver. + */ + if (prGlueInfo->u4ExtCfgLength != 0) + DBGLOG(INIT, TRACE, "Read external configuration data -- OK\n"); + else + DBGLOG(INIT, TRACE, "Read external configuration data -- fail\n"); + + return prGlueInfo->u4ExtCfgLength; +} +#endif + +BOOLEAN +kalIPv4FrameClassifier(IN P_GLUE_INFO_T prGlueInfo, + IN P_NATIVE_PACKET prPacket, IN PUINT_8 pucIpHdr, OUT P_TX_PACKET_INFO prTxPktInfo) +{ + UINT_8 ucIpVersion; + /* UINT_16 u2IpId; */ + + /* IPv4 version check */ + ucIpVersion = (pucIpHdr[0] & IP_VERSION_MASK) >> IP_VERSION_OFFSET; + if (ucIpVersion != IP_VERSION_4) { + DBGLOG(INIT, WARN, "Invalid IPv4 packet version: %u\n", ucIpVersion); + return FALSE; + } + /* WLAN_GET_FIELD_16(&pucIpHdr[IPV4_HDR_IP_IDENTIFICATION_OFFSET], &u2IpId); */ + + if (pucIpHdr[IPV4_HDR_IP_PROTOCOL_OFFSET] == IP_PROTOCOL_UDP) { + PUINT_8 pucUdpHdr = &pucIpHdr[IPV4_HDR_LEN]; + UINT_16 u2DstPort; + /* UINT_16 u2SrcPort; */ + + /* DBGLOG_MEM8(INIT, INFO, pucUdpHdr, 256); */ + + /* Get UDP DST port */ + WLAN_GET_FIELD_BE16(&pucUdpHdr[UDP_HDR_DST_PORT_OFFSET], &u2DstPort); + + /* DBGLOG(INIT, INFO, ("UDP DST[%u]\n", u2DstPort)); */ + + /* Get UDP SRC port */ + /* WLAN_GET_FIELD_BE16(&pucUdpHdr[UDP_HDR_SRC_PORT_OFFSET], &u2SrcPort); */ + + /* BOOTP/DHCP protocol */ + if ((u2DstPort == IP_PORT_BOOTP_SERVER) || (u2DstPort == IP_PORT_BOOTP_CLIENT)) { + + P_BOOTP_PROTOCOL_T prBootp = (P_BOOTP_PROTOCOL_T) &pucUdpHdr[UDP_HDR_LEN]; + + UINT_32 u4DhcpMagicCode; + + WLAN_GET_FIELD_BE32(&prBootp->aucOptions[0], &u4DhcpMagicCode); +#if 0 + DBGLOG(INIT, INFO, "DHCP MGC[0x%08x] XID[%u] OPT[%u] TYPE[%u]\n", + u4DhcpMagicCode, prBootp->u4TransId, prBootp->aucOptions[4], prBootp->aucOptions[6]); +#endif + if (u4DhcpMagicCode == DHCP_MAGIC_NUMBER) { + UINT_32 u4Xid; + + WLAN_GET_FIELD_BE32(&prBootp->u4TransId, &u4Xid); + + DBGLOG(SW4, INFO, "DHCP PKT[0x%p] XID[0x%08x] OPT[%u] TYPE[%u]\n", + prPacket, u4Xid, prBootp->aucOptions[4], prBootp->aucOptions[6]); + + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_DHCP); + } + } + } + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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 prPacket Packet descriptor +* @param prTxPktInfo Extracted packet info +* +* @retval TRUE Success to extract information +* @retval FALSE Fail to extract correct information +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalQoSFrameClassifierAndPacketInfo(IN P_GLUE_INFO_T prGlueInfo, + IN P_NATIVE_PACKET prPacket, OUT P_TX_PACKET_INFO prTxPktInfo) +{ + UINT_32 u4PacketLen; + UINT_16 u2EtherTypeLen; + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + PUINT_8 aucLookAheadBuf = NULL; + UINT_8 ucEthTypeLenOffset = ETHER_HEADER_LEN - ETHER_TYPE_LEN; + PUINT_8 pucNextProtocol = NULL; + UINT_16 u2KeyInfo = 0; + UINT_8 ucEAPoLKey = 0; + UINT_8 ucEapOffset = ETHER_HEADER_LEN; + + u4PacketLen = prSkb->len; + + if (u4PacketLen < ETHER_HEADER_LEN) { + DBGLOG(INIT, WARN, "Invalid Ether packet length: %u\n", + u4PacketLen); + return FALSE; + } + + aucLookAheadBuf = prSkb->data; + + /* Reset Packet Info */ + kalMemZero(prTxPktInfo, sizeof(TX_PACKET_INFO)); + + /* 4 <0> Obtain Ether Type/Len */ + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[ucEthTypeLenOffset], &u2EtherTypeLen); + + /* 4 <1> Skip 802.1Q header (VLAN Tagging) */ + if (u2EtherTypeLen == ETH_P_VLAN) { + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_VLAN_EXIST); + ucEthTypeLenOffset += ETH_802_1Q_HEADER_LEN; + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[ucEthTypeLenOffset], &u2EtherTypeLen); + } + /* 4 <2> Obtain next protocol pointer */ + pucNextProtocol = &aucLookAheadBuf[ucEthTypeLenOffset + ETHER_TYPE_LEN]; + + /* 4 <3> Handle ethernet format */ + switch (u2EtherTypeLen) { + + /* IPv4 */ + case ETH_P_IPV4: + /* IPv4 header length check */ + if (u4PacketLen < (ucEthTypeLenOffset + ETHER_TYPE_LEN + IPV4_HDR_LEN)) { + DBGLOG(INIT, WARN, "Invalid IPv4 packet length: %u\n", + u4PacketLen); + break; + } + + kalIPv4FrameClassifier(prGlueInfo, prPacket, pucNextProtocol, prTxPktInfo); + break; + +#if 0 + /* IPv6 */ + case ETH_P_IPV6: + { + PUINT_8 pucIpHdr = pucNextProtocol; + UINT_8 ucIpVersion; + + /* IPv6 header length check */ + if (u4PacketLen < (ucEthTypeLenOffset + ETHER_TYPE_LEN + IPV6_HDR_LEN)) { + DBGLOG(INIT, WARN, "Invalid IPv6 packet length: %lu\n", u4PacketLen); + return FALSE; + } + + /* IPv6 version check */ + ucIpVersion = (pucIpHdr[0] & IP_VERSION_MASK) >> IP_VERSION_OFFSET; + if (ucIpVersion != IP_VERSION_6) { + DBGLOG(INIT, WARN, "Invalid IPv6 packet version: %u\n", ucIpVersion); + return FALSE; + } + + /* Get the DSCP value from the header of IP packet. */ + ucUserPriority = ((pucIpHdr[0] & IPV6_HDR_TC_PREC_MASK) >> IPV6_HDR_TC_PREC_OFFSET); + } + break; +#endif + + case ETH_P_ARP: + { + UINT_16 u2ArpOp; + + WLAN_GET_FIELD_BE16(&pucNextProtocol[ARP_OPERATION_OFFSET], &u2ArpOp); + + DBGLOG(SW4, INFO, "ARP %s PKT[0x%p] TAR MAC/IP[" MACSTR "]/[" IPV4STR "]\n", + u2ArpOp == ARP_OPERATION_REQUEST ? "REQ" : "RSP", + prPacket, MAC2STR(&pucNextProtocol[ARP_TARGET_MAC_OFFSET]), + IPV4TOSTR(&pucNextProtocol[ARP_TARGET_IP_OFFSET])); + + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_ARP); + } + break; + + case ETH_P_1X: + case ETH_P_PRE_1X: +#if CFG_SUPPORT_WAPI + case ETH_WPI_1X: +#endif + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_1X); + DBGLOG(RSN, INFO, "T1x like normal data, PKT[0x%p]\n", prPacket); + + if (u2EtherTypeLen == ETH_P_1X) { + /* Leave EAP to check */ + ucEAPoLKey = aucLookAheadBuf[1 + ucEapOffset]; + if (ucEAPoLKey != ETH_EAPOL_KEY) + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_NON_PROTECTED_1X); + else { + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[5 + ucEapOffset], &u2KeyInfo); + /* BIT3 is pairwise key bit */ + DBGLOG(RSN, STATE, + "Tx EAPOL Frame[Len:%d, KeyInfo:%d]\n", + u4PacketLen, u2KeyInfo); + if (u2KeyInfo & BIT(3)) + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_NON_PROTECTED_1X); + } + } +#if CFG_SUPPORT_WAPI + else if (u2EtherTypeLen == ETH_WPI_1X) + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_NON_PROTECTED_1X); +#endif + break; + + default: + /* 4 <4> Handle 802.3 format if LEN <= 1500 */ + if (u2EtherTypeLen <= ETH_802_3_MAX_LEN) + prTxPktInfo->u2Flag |= BIT(ENUM_PKT_802_3); + break; + } + + /* 4 <4.1> Check for PAL (BT over Wi-Fi) */ + /* Move to kalBowFrameClassifier */ + + /* 4 <5> Return the value of Priority Parameter. */ + /* prSkb->priority is assigned by Linux wireless utility function(cfg80211_classify8021d) */ + /* at net_dev selection callback (ndo_select_queue) */ + prTxPktInfo->ucPriorityParam = prSkb->priority; + + /* 4 <6> Retrieve Packet Information - DA */ + /* Packet Length/ Destination Address */ + prTxPktInfo->u4PacketLen = u4PacketLen; + + kalMemCopy(prTxPktInfo->aucEthDestAddr, aucLookAheadBuf, PARAM_MAC_ADDR_LEN); + + return TRUE; +} /* end of kalQoSFrameClassifier() */ + +BOOLEAN kalGetEthDestAddr(IN P_GLUE_INFO_T prGlueInfo, IN P_NATIVE_PACKET prPacket, OUT PUINT_8 pucEthDestAddr) +{ + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + PUINT_8 aucLookAheadBuf = NULL; + + /* Sanity Check */ + if (!prPacket || !prGlueInfo) + return FALSE; + + aucLookAheadBuf = prSkb->data; + + kalMemCopy(pucEthDestAddr, aucLookAheadBuf, PARAM_MAC_ADDR_LEN); + + return TRUE; +} + +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); + + prGlueInfo->rPendStatus = rOidStatus; + + prGlueInfo->u4OidCompleteFlag = 1; + /* complete ONLY if there are waiters */ + if (!completion_done(&prGlueInfo->rPendComp)) { + complete(&prGlueInfo->rPendComp); + } else { + DBGLOG(INIT, WARN, "SKIP multiple OID complete!\n"); + /* WARN_ON(TRUE); */ + } + + if (rOidStatus == WLAN_STATUS_SUCCESS) + DBGLOG(INIT, TRACE, "Complete OID, status:success\n"); + else + DBGLOG(INIT, WARN, "Complete OID, status:0x%08x\n", rOidStatus); + + /* else let it timeout on kalIoctl entry */ +} + +VOID kalOidClearance(IN P_GLUE_INFO_T prGlueInfo) +{ + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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, OUT PUINT_32 pu4QryInfoLen) +{ + return kalIoctlTimeout(prGlueInfo, + pfnOidHandler, + pvInfoBuf, + u4InfoBufLen, fgRead, fgWaitResp, fgCmd, -1, + pu4QryInfoLen); +} + + + +/*----------------------------------------------------------------------------*/ +/*! +* @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 i4OidTimeout timeout for this OID +* @param pu4QryInfoLen The data length of the return values +* +* @retval TRUE Success to extract information +* @retval FALSE Fail to extract correct information +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS +kalIoctlTimeout(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 INT_32 i4OidTimeout, + OUT PUINT_32 pu4QryInfoLen) +{ + P_GL_IO_REQ_T prIoReq = NULL; + WLAN_STATUS ret = WLAN_STATUS_SUCCESS; + +#if CFG_CHIP_RESET_SUPPORT + if (kalIsResetting()) + return WLAN_STATUS_SUCCESS; +#endif + + if (wlanIsChipAssert(prGlueInfo->prAdapter)) + return WLAN_STATUS_SUCCESS; + + /* GLUE_SPIN_LOCK_DECLARATION(); */ + ASSERT(prGlueInfo); + + /* Just direct function call if already in main_thread */ + if (prGlueInfo->u4TxThreadPid == KAL_GET_CURRENT_THREAD_ID()) { + if (pfnOidHandler) { + g_fgIsOid = FALSE; + ret = pfnOidHandler(prGlueInfo->prAdapter, pvInfoBuf, + u4InfoBufLen, pu4QryInfoLen); + } + return ret; + } + + /* <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 (i4OidTimeout >= 0 && i4OidTimeout <= WLAN_OID_TIMEOUT_THRESHOLD_MAX) + prIoReq->u4Timeout = (UINT_32)i4OidTimeout; + else + prIoReq->u4Timeout = WLAN_OID_TIMEOUT_THRESHOLD; + + + /* <5> Reset the status of pending OID */ + prGlueInfo->rPendStatus = WLAN_STATUS_FAILURE; + /* prGlueInfo->u4TimeoutFlag = 0; */ + prGlueInfo->u4OidCompleteFlag = 0; + + /* <6> Check if we use the command queue */ + prIoReq->u4Flag = fgCmd; + + /* <7> schedule the OID bit */ + set_bit(GLUE_FLAG_OID_BIT, &prGlueInfo->ulFlag); + + /* <7.1> Hold wakelock to ensure OS won't be suspended */ + KAL_WAKE_LOCK_TIMEOUT(prGlueInfo->prAdapter, &prGlueInfo->rTimeoutWakeLock, + MSEC_TO_JIFFIES(prGlueInfo->prAdapter->rWifiVar.u4WakeLockThreadWakeup)); + + /* <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 2 secs */ + 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 + { + /* 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 + + /* <10> Clear bit for error handling */ + clear_bit(GLUE_FLAG_OID_BIT, &prGlueInfo->ulFlag); + + 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; + QUE_T rReturnCmdQue; + P_QUE_T prReturnCmdQue = &rReturnCmdQue; + 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); + + QUEUE_INITIALIZE(prReturnCmdQue); + /* Clear pending security frames in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) { + if (prCmdInfo->pfCmdTimeoutHandler) + prCmdInfo->pfCmdTimeoutHandler(prGlueInfo->prAdapter, prCmdInfo); + else + wlanReleaseCommand(prGlueInfo->prAdapter, prCmdInfo, TX_RESULT_QUEUE_CLEARANCE); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingCmdNum); + } else { + QUEUE_INSERT_TAIL(prReturnCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(prCmdQue, prReturnCmdQue); + 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 kalClearSecurityFramesByBssIdx(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucBssIndex) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + QUE_T rReturnCmdQue; + P_QUE_T prReturnCmdQue = &rReturnCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; + P_MSDU_INFO_T prMsduInfo; + BOOLEAN fgFree; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + QUEUE_INITIALIZE(prReturnCmdQue); + /* Clear pending security frames in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + prMsduInfo = prCmdInfo->prMsduInfo; + fgFree = FALSE; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME && prMsduInfo) { + if (prMsduInfo->ucBssIndex == ucBssIndex) + fgFree = TRUE; + } + + if (fgFree) { + if (prCmdInfo->pfCmdTimeoutHandler) + prCmdInfo->pfCmdTimeoutHandler(prGlueInfo->prAdapter, prCmdInfo); + else + wlanReleaseCommand(prGlueInfo->prAdapter, prCmdInfo, TX_RESULT_QUEUE_CLEARANCE); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingCmdNum); + } else + QUEUE_INSERT_TAIL(prReturnCmdQue, prQueueEntry); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(prCmdQue, prReturnCmdQue); + 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; + QUE_T rReturnCmdQue; + P_QUE_T prReturnCmdQue = &rReturnCmdQue; + 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); + + QUEUE_INITIALIZE(prReturnCmdQue); + /* Clear pending management frames in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + 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, TX_RESULT_QUEUE_CLEARANCE); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingCmdNum); + } else { + QUEUE_INSERT_TAIL(prReturnCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(prCmdQue, prReturnCmdQue); + 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 kalClearMgmtFramesByBssIdx(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucBssIndex) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + QUE_T rReturnCmdQue; + P_QUE_T prReturnCmdQue = &rReturnCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; + P_MSDU_INFO_T prMsduInfo; + BOOLEAN fgFree; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + QUEUE_INITIALIZE(prReturnCmdQue); + /* Clear pending management frames in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + prMsduInfo = prCmdInfo->prMsduInfo; + fgFree = FALSE; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME && prMsduInfo) { + if (prMsduInfo->ucBssIndex == ucBssIndex) + fgFree = TRUE; + } + + if (fgFree) { + wlanReleaseCommand(prGlueInfo->prAdapter, prCmdInfo, TX_RESULT_QUEUE_CLEARANCE); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingCmdNum); + } else { + QUEUE_INSERT_TAIL(prReturnCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(prCmdQue, prReturnCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); +} /* kalClearMgmtFramesByBssIdx */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to clear all commands in command queue +* \param prGlueInfo Pointer of GLUE Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalClearCommandQueue(IN P_GLUE_INFO_T prGlueInfo) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + QUE_T rReturnCmdQue; + P_QUE_T prReturnCmdQue = &rReturnCmdQue; + 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); + + QUEUE_INITIALIZE(prReturnCmdQue); + + /* Clear ALL in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + if (prCmdInfo->pfCmdTimeoutHandler) + prCmdInfo->pfCmdTimeoutHandler(prGlueInfo->prAdapter, prCmdInfo); + else + wlanReleaseCommand(prGlueInfo->prAdapter, prCmdInfo, TX_RESULT_QUEUE_CLEARANCE); + + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingCmdNum); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } +} + +UINT_32 kalProcessTxPacket(P_GLUE_INFO_T prGlueInfo, struct sk_buff *prSkb) +{ + UINT_32 u4Status = WLAN_STATUS_SUCCESS; + + if (prSkb == NULL) { + DBGLOG(INIT, WARN, "prSkb == NULL in tx\n"); + return u4Status; + } + + /* Handle security frame */ + if (0 /* GLUE_TEST_PKT_FLAG(prSkb, ENUM_PKT_1X) *//* No more sending via cmd */) { + if (wlanProcessSecurityFrame(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb)) { + u4Status = WLAN_STATUS_SUCCESS; + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum); + } else { + u4Status = WLAN_STATUS_RESOURCES; + } + } + /* Handle normal frame */ + else + u4Status = wlanEnqueueTxPacket(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to process Tx request to main_thread +* +* \param prGlueInfo Pointer of GLUE Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalProcessTxReq(P_GLUE_INFO_T prGlueInfo, PBOOLEAN pfgNeedHwAccess) +{ + P_QUE_T prCmdQue = NULL; + P_QUE_T prTxQueue = NULL; + QUE_T rTempQue; + P_QUE_T prTempQue = &rTempQue; + QUE_T rTempReturnQue; + P_QUE_T prTempReturnQue = &rTempReturnQue; + P_QUE_ENTRY_T prQueueEntry = NULL; + /* struct sk_buff *prSkb = NULL; */ + UINT_32 u4Status; +#if CFG_SUPPORT_MULTITHREAD + UINT_32 u4CmdCount = 0; +#endif + UINT_32 u4TxLoopCount; + + /* for spin lock acquire and release */ + GLUE_SPIN_LOCK_DECLARATION(); + + prTxQueue = &prGlueInfo->rTxQueue; + prCmdQue = &prGlueInfo->rCmdQueue; + + QUEUE_INITIALIZE(prTempQue); + QUEUE_INITIALIZE(prTempReturnQue); + + u4TxLoopCount = prGlueInfo->prAdapter->rWifiVar.u4TxFromOsLoopCount; + + /* Process Mailbox Messages */ + wlanProcessMboxMessage(prGlueInfo->prAdapter); + + /* Process CMD request */ +#if CFG_SUPPORT_MULTITHREAD + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + u4CmdCount = prCmdQue->u4NumElem; + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + if (u4CmdCount > 0) + wlanProcessCommandQueue(prGlueInfo->prAdapter, prCmdQue); + +#else + if (prCmdQue->u4NumElem > 0) { + if (*pfgNeedHwAccess == FALSE) { + *pfgNeedHwAccess = TRUE; + + wlanAcquirePowerControl(prGlueInfo->prAdapter); + } + wlanProcessCommandQueue(prGlueInfo->prAdapter, prCmdQue); + } +#endif + + while (u4TxLoopCount--) { + while (QUEUE_IS_NOT_EMPTY(prTxQueue)) { + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_MOVE_ALL(prTempQue, prTxQueue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + + /* Handle Packet Tx */ + while (QUEUE_IS_NOT_EMPTY(prTempQue)) { + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); + + if (prQueueEntry == NULL) + break; + + u4Status = kalProcessTxPacket(prGlueInfo, + (struct sk_buff *)GLUE_GET_PKT_DESCRIPTOR(prQueueEntry)); +#if 0 + prSkb = (struct sk_buff *)GLUE_GET_PKT_DESCRIPTOR(prQueueEntry); + ASSERT(prSkb); + if (prSkb == NULL) { + DBGLOG(INIT, WARN, "prSkb == NULL in tx\n"); + continue; + } + + /* Handle security frame */ + if (GLUE_GET_PKT_IS_1X(prSkb)) { + if (wlanProcessSecurityFrame(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb)) { + u4Status = WLAN_STATUS_SUCCESS; + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum); + } else { + u4Status = WLAN_STATUS_RESOURCES; + } + } + /* Handle normal frame */ + else + u4Status = wlanEnqueueTxPacket(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb); +#endif + /* Enqueue packet back into TxQueue if resource is not enough */ + if (u4Status == WLAN_STATUS_RESOURCES) { + QUEUE_INSERT_TAIL(prTempReturnQue, prQueueEntry); + break; + } + } + + if (wlanGetTxPendingFrameCount(prGlueInfo->prAdapter) > 0) + wlanTxPendingPackets(prGlueInfo->prAdapter, pfgNeedHwAccess); + + /* Enqueue packet back into TxQueue if resource is not enough */ + if (QUEUE_IS_NOT_EMPTY(prTempReturnQue)) { + QUEUE_CONCATENATE_QUEUES(prTempReturnQue, prTempQue); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(prTxQueue, prTempReturnQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + + break; + } + } + + if (wlanGetTxPendingFrameCount(prGlueInfo->prAdapter) > 0) + wlanTxPendingPackets(prGlueInfo->prAdapter, pfgNeedHwAccess); + } + +} + +#if CFG_SUPPORT_MULTITHREAD +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param data data pointer to private data of hif_thread +* +* @retval If the function succeeds, the return value is 0. +* Otherwise, an error code is returned. +* +*/ +/*----------------------------------------------------------------------------*/ + +int hif_thread(void *data) +{ + struct net_device *dev = data; + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(dev)); + int ret = 0; +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + KAL_WAKE_LOCK_T rHifThreadWakeLock; +#endif + + KAL_WAKE_LOCK_INIT(prGlueInfo->prAdapter, &rHifThreadWakeLock, "WLAN hif_thread"); + KAL_WAKE_LOCK(prGlueInfo->prAdapter, &rHifThreadWakeLock); + + DBGLOG(INIT, INFO, "%s:%u starts running...\n", KAL_GET_CURRENT_THREAD_NAME(), KAL_GET_CURRENT_THREAD_ID()); + + prGlueInfo->u4HifThreadPid = KAL_GET_CURRENT_THREAD_ID(); + + set_user_nice(current, prGlueInfo->prAdapter->rWifiVar.cThreadNice); + + while (TRUE) { + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(INIT, INFO, "hif_thread should stop now...\n"); + break; + } + + /* Unlock wakelock if hif_thread going to idle */ + if (!(prGlueInfo->ulFlag & GLUE_FLAG_HIF_PROCESS)) + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, &rHifThreadWakeLock); + + /* + * 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 + * + */ + do { + ret = wait_event_interruptible(prGlueInfo->waitq_hif, + ((prGlueInfo->ulFlag & GLUE_FLAG_HIF_PROCESS) != 0)); + } while (ret != 0); +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + if (!KAL_WAKE_LOCK_ACTIVE(prGlueInfo->prAdapter, &rHifThreadWakeLock)) + KAL_WAKE_LOCK(prGlueInfo->prAdapter, &rHifThreadWakeLock); +#endif + wlanAcquirePowerControl(prGlueInfo->prAdapter); + + /* Handle Interrupt */ + if (test_and_clear_bit(GLUE_FLAG_INT_BIT, &prGlueInfo->ulFlag)) { + /* 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; + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + /* Should stop now... skip pending interrupt */ + DBGLOG(INIT, INFO, "ignore pending interrupt\n"); + } else { + /* DBGLOG(INIT, INFO, ("HIF Interrupt!\n")); */ + wlanIST(prGlueInfo->prAdapter); + } + } + + /* Skip Tx request if SER is operating */ + if (!nicSerIsTxStop(prGlueInfo->prAdapter)) { + /* TX Commands */ + if (test_and_clear_bit(GLUE_FLAG_HIF_TX_CMD_BIT, &prGlueInfo->ulFlag)) + wlanTxCmdMthread(prGlueInfo->prAdapter); + + /* Process TX data packet to HIF */ + if (test_and_clear_bit(GLUE_FLAG_HIF_TX_BIT, &prGlueInfo->ulFlag)) + nicTxMsduQueueMthread(prGlueInfo->prAdapter); + } + + /* Read chip status when chip no response */ + if (test_and_clear_bit(GLUE_FLAG_HIF_PRT_HIF_DBG_INFO_BIT, &prGlueInfo->ulFlag)) + halPrintHifDbgInfo(prGlueInfo->prAdapter); + + /* Set FW own */ + if (test_and_clear_bit(GLUE_FLAG_HIF_FW_OWN_BIT, &prGlueInfo->ulFlag)) + prGlueInfo->prAdapter->fgWiFiInSleepyState = TRUE; + + /* Release to FW own */ + wlanReleasePowerControl(prGlueInfo->prAdapter); + } + + complete(&prGlueInfo->rHifHaltComp); +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + if (KAL_WAKE_LOCK_ACTIVE(prGlueInfo->prAdapter, &rHifThreadWakeLock)) + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, &rHifThreadWakeLock); + KAL_WAKE_LOCK_DESTROY(prGlueInfo->prAdapter, &rHifThreadWakeLock); +#endif + + DBGLOG(INIT, INFO, "%s:%u stopped!\n", KAL_GET_CURRENT_THREAD_NAME(), KAL_GET_CURRENT_THREAD_ID()); + + return 0; +} + +int rx_thread(void *data) +{ + struct net_device *dev = data; + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(dev)); + + QUE_T rTempRxQue; + P_QUE_T prTempRxQue = NULL; + P_QUE_ENTRY_T prQueueEntry = NULL; + + int ret = 0; +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + KAL_WAKE_LOCK_T rRxThreadWakeLock; +#endif + UINT_32 u4LoopCount; + + /* for spin lock acquire and release */ + KAL_SPIN_LOCK_DECLARATION(); + + KAL_WAKE_LOCK_INIT(prGlueInfo->prAdapter, &rRxThreadWakeLock, "WLAN rx_thread"); + KAL_WAKE_LOCK(prGlueInfo->prAdapter, &rRxThreadWakeLock); + + DBGLOG(INIT, INFO, "%s:%u starts running...\n", KAL_GET_CURRENT_THREAD_NAME(), KAL_GET_CURRENT_THREAD_ID()); + + prGlueInfo->u4RxThreadPid = KAL_GET_CURRENT_THREAD_ID(); + + set_user_nice(current, prGlueInfo->prAdapter->rWifiVar.cThreadNice); + + prTempRxQue = &rTempRxQue; + + while (TRUE) { + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(INIT, INFO, "rx_thread should stop now...\n"); + break; + } + + /* Unlock wakelock if rx_thread going to idle */ + if (!(prGlueInfo->ulFlag & GLUE_FLAG_RX_PROCESS)) + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, &rRxThreadWakeLock); + + /* + * sleep on waitqueue if no events occurred. + */ + do { + ret = wait_event_interruptible(prGlueInfo->waitq_rx, + ((prGlueInfo->ulFlag & GLUE_FLAG_RX_PROCESS) != 0)); + } while (ret != 0); +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + if (!KAL_WAKE_LOCK_ACTIVE(prGlueInfo->prAdapter, &rRxThreadWakeLock)) + KAL_WAKE_LOCK(prGlueInfo->prAdapter, &rRxThreadWakeLock); +#endif + if (test_and_clear_bit(GLUE_FLAG_RX_TO_OS_BIT, &prGlueInfo->ulFlag)) { + u4LoopCount = prGlueInfo->prAdapter->rWifiVar.u4Rx2OsLoopCount; + + while (u4LoopCount--) { + while (QUEUE_IS_NOT_EMPTY(&prGlueInfo->prAdapter->rRxQueue)) { + QUEUE_INITIALIZE(prTempRxQue); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_RX_TO_OS_QUE); + QUEUE_MOVE_ALL(prTempRxQue, &prGlueInfo->prAdapter->rRxQueue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_RX_TO_OS_QUE); + + while (QUEUE_IS_NOT_EMPTY(prTempRxQue)) { + QUEUE_REMOVE_HEAD(prTempRxQue, prQueueEntry, P_QUE_ENTRY_T); + kalRxIndicateOnePkt(prGlueInfo, + (PVOID) GLUE_GET_PKT_DESCRIPTOR(prQueueEntry)); + } + + KAL_WAKE_LOCK_TIMEOUT(prGlueInfo->prAdapter, &prGlueInfo->rTimeoutWakeLock, + MSEC_TO_JIFFIES(prGlueInfo->prAdapter->rWifiVar.u4WakeLockRxTimeout)); + } + } + } + } + + complete(&prGlueInfo->rRxHaltComp); +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + if (KAL_WAKE_LOCK_ACTIVE(prGlueInfo->prAdapter, &rRxThreadWakeLock)) + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, &rRxThreadWakeLock); + KAL_WAKE_LOCK_DESTROY(prGlueInfo->prAdapter, &rRxThreadWakeLock); +#endif + + DBGLOG(INIT, INFO, "%s:%u stopped!\n", KAL_GET_CURRENT_THREAD_NAME(), KAL_GET_CURRENT_THREAD_ID()); + + return 0; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @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 main_thread +* +* @retval If the function succeeds, the return value is 0. +* Otherwise, an error code is returned. +* +*/ +/*----------------------------------------------------------------------------*/ + +int main_thread(void *data) +{ + struct net_device *dev = data; + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(dev)); + P_GL_IO_REQ_T prIoReq = NULL; + int ret = 0; + BOOLEAN fgNeedHwAccess = FALSE; +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + KAL_WAKE_LOCK_T rTxThreadWakeLock; +#endif + +#if CFG_SUPPORT_MULTITHREAD + prGlueInfo->u4TxThreadPid = KAL_GET_CURRENT_THREAD_ID(); +#endif + + current->flags |= PF_NOFREEZE; + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prAdapter); + set_user_nice(current, prGlueInfo->prAdapter->rWifiVar.cThreadNice); + + KAL_WAKE_LOCK_INIT(prGlueInfo->prAdapter, &rTxThreadWakeLock, "WLAN main_thread"); + KAL_WAKE_LOCK(prGlueInfo->prAdapter, &rTxThreadWakeLock); + + DBGLOG(INIT, INFO, "%s:%u starts running...\n", KAL_GET_CURRENT_THREAD_NAME(), KAL_GET_CURRENT_THREAD_ID()); + + while (TRUE) { + +#if CFG_ENABLE_WIFI_DIRECT + /*run p2p multicast list work. */ + if (test_and_clear_bit(GLUE_FLAG_SUB_MOD_MULTICAST_BIT, &prGlueInfo->ulFlag)) + p2pSetMulticastListWorkQueueWrapper(prGlueInfo); +#endif + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(INIT, INFO, "%s should stop now...\n", KAL_GET_CURRENT_THREAD_NAME()); + break; + } + + /* Unlock wakelock if main_thread going to idle */ + if (!(prGlueInfo->ulFlag & GLUE_FLAG_MAIN_PROCESS)) + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, &rTxThreadWakeLock); + + /* + * 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 + * + */ + do { + ret = wait_event_interruptible(prGlueInfo->waitq, + ((prGlueInfo->ulFlag & GLUE_FLAG_MAIN_PROCESS) != 0)); + } while (ret != 0); +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + if (!KAL_WAKE_LOCK_ACTIVE(prGlueInfo->prAdapter, &rTxThreadWakeLock)) + KAL_WAKE_LOCK(prGlueInfo->prAdapter, &rTxThreadWakeLock); +#endif + +#if CFG_ENABLE_WIFI_DIRECT + /*run p2p multicast list work. */ + if (test_and_clear_bit(GLUE_FLAG_SUB_MOD_MULTICAST_BIT, &prGlueInfo->ulFlag)) + p2pSetMulticastListWorkQueueWrapper(prGlueInfo); + + if (test_and_clear_bit(GLUE_FLAG_FRAME_FILTER_BIT, &prGlueInfo->ulFlag)) { + p2pFuncUpdateMgmtFrameRegister(prGlueInfo->prAdapter, + prGlueInfo->prP2PDevInfo->u4OsMgmtFrameFilter); + } +#endif + if (test_and_clear_bit(GLUE_FLAG_FRAME_FILTER_AIS_BIT, &prGlueInfo->ulFlag)) { + P_AIS_FSM_INFO_T prAisFsmInfo = (P_AIS_FSM_INFO_T) NULL; + /* printk("prGlueInfo->u4OsMgmtFrameFilter = %x", prGlueInfo->u4OsMgmtFrameFilter); */ + prAisFsmInfo = &(prGlueInfo->prAdapter->rWifiVar.rAisFsmInfo); + prAisFsmInfo->u4AisPacketFilter = prGlueInfo->u4OsMgmtFrameFilter; + } + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(INIT, INFO, "%s should stop now...\n", KAL_GET_CURRENT_THREAD_NAME()); + break; + } + + fgNeedHwAccess = FALSE; + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN + if (prGlueInfo->fgEnSdioTestPattern == TRUE) { + if (fgNeedHwAccess == FALSE) { + fgNeedHwAccess = TRUE; + + wlanAcquirePowerControl(prGlueInfo->prAdapter); + } + + if (prGlueInfo->fgIsSdioTestInitialized == FALSE) { + /* enable PRBS mode */ + kalDevRegWrite(prGlueInfo, MCR_WTMCR, 0x00080002); + prGlueInfo->fgIsSdioTestInitialized = TRUE; + } + + if (prGlueInfo->fgSdioReadWriteMode == TRUE) { + /* read test */ + kalDevPortRead(prGlueInfo, + MCR_WTMDR, + 256, + prGlueInfo->aucSdioTestBuffer, sizeof(prGlueInfo->aucSdioTestBuffer)); + } else { + /* write test */ + kalDevPortWrite(prGlueInfo, + MCR_WTMDR, + 172, + prGlueInfo->aucSdioTestBuffer, sizeof(prGlueInfo->aucSdioTestBuffer)); + } + } +#endif +#if CFG_SUPPORT_MULTITHREAD +#else + /* Handle Interrupt */ + if (test_and_clear_bit(GLUE_FLAG_INT_BIT, &prGlueInfo->ulFlag)) { + + if (fgNeedHwAccess == FALSE) { + fgNeedHwAccess = TRUE; + + wlanAcquirePowerControl(prGlueInfo->prAdapter); + } + + /* the Wi-Fi interrupt is already disabled in mmc thread, + * so we set the flag only to enable the interrupt later + */ + prGlueInfo->prAdapter->fgIsIntEnable = FALSE; + /* wlanISR(prGlueInfo->prAdapter, TRUE); */ + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + /* Should stop now... skip pending interrupt */ + DBGLOG(INIT, INFO, "ignore pending interrupt\n"); + } else { + wlanIST(prGlueInfo->prAdapter); + } + } +#endif + /* transfer ioctl to OID request */ + + do { + if (test_and_clear_bit(GLUE_FLAG_OID_BIT, &prGlueInfo->ulFlag)) { + g_fgIsOid = TRUE; + /* get current prIoReq */ + prIoReq = &(prGlueInfo->OidEntry); + if (prIoReq->fgRead == FALSE) { + 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 ONLY if there are waiters */ + if (!completion_done(&prGlueInfo->rPendComp)) + complete(&prGlueInfo->rPendComp); + else + DBGLOG(INIT, WARN, "SKIP multiple OID complete!\n"); + } else { + wlanoidTimeoutCheck(prGlueInfo->prAdapter, + prIoReq->pfnOidHandler, + prIoReq->u4Timeout); + } + } + + } while (FALSE); + + /* + * + * if TX request, clear the TXREQ flag. TXREQ set by kalSetEvent/GlueSetEvent + * indicates the following requests occur + * + */ + + if (test_and_clear_bit(GLUE_FLAG_TXREQ_BIT, &prGlueInfo->ulFlag)) + kalProcessTxReq(prGlueInfo, &fgNeedHwAccess); +#if CFG_SUPPORT_MULTITHREAD + /* Process RX */ + if (test_and_clear_bit(GLUE_FLAG_RX_BIT, &prGlueInfo->ulFlag)) + nicRxProcessRFBs(prGlueInfo->prAdapter); + if (test_and_clear_bit(GLUE_FLAG_TX_CMD_DONE_BIT, &prGlueInfo->ulFlag)) + wlanTxCmdDoneMthread(prGlueInfo->prAdapter); +#endif + + /* 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 CFG_SUPPORT_MULTITHREAD +#else + if (fgNeedHwAccess == TRUE) + wlanReleasePowerControl(prGlueInfo->prAdapter); +#endif + /* handle cnmTimer time out */ + if (test_and_clear_bit(GLUE_FLAG_TIMEOUT_BIT, &prGlueInfo->ulFlag)) + wlanTimerTimeoutCheck(prGlueInfo->prAdapter); +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN + if (prGlueInfo->fgEnSdioTestPattern == TRUE) + kalSetEvent(prGlueInfo); +#endif + } + +#if 0 + if (fgNeedHwAccess == TRUE) + wlanReleasePowerControl(prGlueInfo->prAdapter); +#endif + + /* flush the pending TX packets */ + if (GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum) > 0) + kalFlushPendingTxPackets(prGlueInfo); + + /* flush pending security frames */ + if (GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum) > 0) + kalClearSecurityFrames(prGlueInfo); + + /* remove pending oid */ + wlanReleasePendingOid(prGlueInfo->prAdapter, 0); + + complete(&prGlueInfo->rHaltComp); +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + if (KAL_WAKE_LOCK_ACTIVE(prGlueInfo->prAdapter, &rTxThreadWakeLock)) + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, &rTxThreadWakeLock); + KAL_WAKE_LOCK_DESTROY(prGlueInfo->prAdapter, &rTxThreadWakeLock); +#endif + + DBGLOG(INIT, INFO, "%s:%u stopped!\n", KAL_GET_CURRENT_THREAD_NAME(), KAL_GET_CURRENT_THREAD_ID()); + + 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 */ +} + + +#ifdef CONFIG_IDME +#define IDME_MACADDR "/proc/idme/mac_addr" +static int idme_get_mac_addr(unsigned char *mac_addr, size_t addr_len) +{ + unsigned char buf[IFHWADDRLEN * 2 + 1] = {""}, str[3] = {""}; + int i, mac[IFHWADDRLEN]; + mm_segment_t old_fs; + struct file *f; + size_t len; + + if (!mac_addr || addr_len < IFHWADDRLEN) { + DBGLOG(INIT, ERROR, "invalid mac_addr ptr or buf\n"); + return -1; + } + + f = filp_open(IDME_MACADDR, O_RDONLY, 0); + if (IS_ERR(f)) { + DBGLOG(INIT, ERROR, "can't open mac addr file\n"); + return -1; + } + + old_fs = get_fs(); + set_fs(get_ds()); + f->f_op->read(f, buf, IFHWADDRLEN * 2, &f->f_pos); + filp_close(f, NULL); + set_fs(old_fs); + + if (strlen(buf) != IFHWADDRLEN * 2) + goto bailout; + + for (i = 0; i < IFHWADDRLEN; i++) { + str[0] = buf[i * 2]; + str[1] = buf[i * 2 + 1]; + if (!isxdigit(str[0]) || !isxdigit(str[1])) + goto bailout; + len = sscanf(str, "%02x", &mac[i]); + if (len != 1) + goto bailout; + } + for (i = 0; i < IFHWADDRLEN; i++) + mac_addr[i] = (unsigned char)mac[i]; + return 0; +bailout: + DBGLOG(INIT, ERROR, "wrong mac addr %02x %02x\n", buf[0], buf[1]); + return -1; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * \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) +{ + P_ADAPTER_T prAdapter; + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + + /* Get MAC address override from wlan feature option */ + prGlueInfo->fgIsMacAddrOverride = prAdapter->rWifiVar.ucMacAddrOverride; + + wlanHwAddrToBin(prAdapter->rWifiVar.aucMacAddrStr, prGlueInfo->rMacAddrOverride); + +#ifdef CONFIG_IDME + if (prMacAddr && 0 == idme_get_mac_addr((unsigned char *)prMacAddr, sizeof(PARAM_MAC_ADDRESS))) { + DBGLOG(INIT, INFO, "use IDME mac addr\n"); + return TRUE; + } +#endif + + if (prGlueInfo->fgIsMacAddrOverride == FALSE) { + UINT_32 i; + BOOLEAN fgIsReadError = FALSE; + +#if !defined(CONFIG_X86) + for (i = 0; i < MAC_ADDR_LEN; i += 2) { + if (kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucMacAddress) + i, + (PUINT_16) (((PUINT_8) prMacAddr) + i)) == FALSE) { + fgIsReadError = TRUE; + break; + } + } +#else + /* x86 Linux doesn't need to override network address so far */ + /*return FALSE;*/ + /*Modify for Linux PC support NVRAM Setting*/ + 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; + } + } + +#endif + +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1) + /* retrieve buffer mode efuse */ + if ((prAdapter->fgIsSupportPowerOnSendBufferModeCMD == TRUE) && + (prAdapter->rWifiVar.ucEfuseBufferModeCal + == LOAD_EEPROM_BIN)) { + if (wlanExtractBufferBin(prAdapter) == WLAN_STATUS_SUCCESS) { + UINT_32 u4BinOffset = prAdapter->u4EfuseMacAddrOffset; + + /* Update MAC address */ + kalMemCopy(prMacAddr, &uacEEPROMImage[u4BinOffset], MAC_ADDR_LEN); + fgIsReadError = FALSE; + } else { + fgIsReadError = TRUE; + } + } +#endif + /* return retrieve result */ + if (fgIsReadError == TRUE) + return FALSE; + else + return TRUE; + + + } 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; + + ASSERT(prGlueInfo); + + prTxQue = &(prGlueInfo->rTxQueue); + + if (GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum) == 0) + return; + + if (HAL_IS_TX_DIRECT()) { + nicTxDirectClearSkbQ(prGlueInfo->prAdapter); + } else { + GLUE_SPIN_LOCK_DECLARATION(); + + 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; + QUE_T rReturnCmdQue; + P_QUE_T prReturnCmdQue = &rReturnCmdQue; + 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); + + QUEUE_INITIALIZE(prReturnCmdQue); + + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + + if (((P_CMD_INFO_T) prQueueEntry)->fgIsOid) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + break; + } + QUEUE_INSERT_TAIL(prReturnCmdQue, prQueueEntry); + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_CONCATENATE_QUEUES_HEAD(prCmdQue, prReturnCmdQue); + 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); + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingCmdNum); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to insert command into prCmdQueue +* +* \param prGlueInfo Pointer of GLUE Data Structure +* prQueueEntry Pointer of queue entry to be inserted +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalEnqueueCommand(IN P_GLUE_INFO_T prGlueInfo, IN P_QUE_ENTRY_T prQueueEntry) +{ + P_QUE_T prCmdQue; + P_CMD_INFO_T prCmdInfo; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + ASSERT(prQueueEntry); + + prCmdQue = &prGlueInfo->rCmdQueue; + + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + DBGLOG(INIT, INFO, "EN-Q CMD TYPE[%u] ID[0x%02X] SEQ[%u] to CMD Q\n", + prCmdInfo->eCmdType, prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingCmdNum); + 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 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); */ + kalSendCompleteAndAwakeQueue(prGlueInfo, pvPacket); + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum); +} + +UINT_32 kalGetTxPendingFrameCount(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return (UINT_32) (GLUE_GET_REF_CNT(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) +{ + ASSERT(prGlueInfo); + + return (UINT_32)GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingCmdNum); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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); + +#if KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE + timer_setup(&(prGlueInfo->tickfn), prTimerHandler, 0); +#else + init_timer(&(prGlueInfo->tickfn)); + prGlueInfo->tickfn.function = prTimerHandler; + prGlueInfo->tickfn.data = (unsigned long)prGlueInfo; +#endif +} + +/* 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); + + if (HAL_IS_RX_DIRECT(prGlueInfo->prAdapter)) { + mod_timer(&prGlueInfo->tickfn, jiffies + u4Interval * HZ / MSEC_PER_SEC); + } else { + del_timer_sync(&(prGlueInfo->tickfn)); + + prGlueInfo->tickfn.expires = jiffies + u4Interval * HZ / MSEC_PER_SEC; + add_timer(&(prGlueInfo->tickfn)); + } + + return TRUE; /* success */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to cancel +* +* \param[in] prGlueInfo Pointer to GLUE Data Structure +* +* \retval TRUE : Timer has been canceled +* FALAE : Timer doens't exist +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalCancelTimer(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + clear_bit(GLUE_FLAG_TIMEOUT_BIT, &prGlueInfo->ulFlag); + + if (del_timer_sync(&(prGlueInfo->tickfn)) >= 0) + return TRUE; + else + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is a callback function for scanning done +* +* \param[in] prGlueInfo Pointer to GLUE Data Structure +* +* \retval none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID kalScanDone(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_KAL_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN WLAN_STATUS status) +{ + ASSERT(prGlueInfo); + + scanReportBss2Cfg80211(prGlueInfo->prAdapter, BSS_TYPE_INFRASTRUCTURE, NULL); + + /* 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) + */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE +void kalTimeoutHandler(struct timer_list *timer) +#else +VOID kalTimeoutHandler(unsigned long arg) +#endif +{ +#if KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE + struct _GLUE_INFO_T *prGlueInfo = + from_timer(prGlueInfo, timer, tickfn); +#else + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) arg; +#endif + ASSERT(prGlueInfo); + + /* Notify tx thread for timeout event */ + set_bit(GLUE_FLAG_TIMEOUT_BIT, &prGlueInfo->ulFlag); + wake_up_interruptible(&prGlueInfo->waitq); + +} + +VOID kalSetEvent(P_GLUE_INFO_T pr) +{ + set_bit(GLUE_FLAG_TXREQ_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq); +} + +VOID kalSetIntEvent(P_GLUE_INFO_T pr) +{ + KAL_WAKE_LOCK(pr->prAdapter, &pr->rIntrWakeLock); + + set_bit(GLUE_FLAG_INT_BIT, &pr->ulFlag); + + /* when we got interrupt, we wake up servie thread */ +#if CFG_SUPPORT_MULTITHREAD + wake_up_interruptible(&pr->waitq_hif); +#else + wake_up_interruptible(&pr->waitq); +#endif +} + +#if CFG_SUPPORT_MULTITHREAD +VOID kalSetTxEvent2Hif(P_GLUE_INFO_T pr) +{ + if (!pr->hif_thread) + return; + + KAL_WAKE_LOCK_TIMEOUT(pr->prAdapter, &pr->rTimeoutWakeLock, + MSEC_TO_JIFFIES(pr->prAdapter->rWifiVar.u4WakeLockThreadWakeup)); + + set_bit(GLUE_FLAG_HIF_TX_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq_hif); +} + +VOID kalSetFwOwnEvent2Hif(P_GLUE_INFO_T pr) +{ + if (!pr->hif_thread) + return; + + KAL_WAKE_LOCK_TIMEOUT(pr->prAdapter, &pr->rTimeoutWakeLock, + MSEC_TO_JIFFIES(pr->prAdapter->rWifiVar.u4WakeLockThreadWakeup)); + + set_bit(GLUE_FLAG_HIF_FW_OWN_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq_hif); +} + +VOID kalSetTxEvent2Rx(P_GLUE_INFO_T pr) +{ + if (!pr->rx_thread) + return; + + KAL_WAKE_LOCK_TIMEOUT(pr->prAdapter, &pr->rTimeoutWakeLock, + MSEC_TO_JIFFIES(pr->prAdapter->rWifiVar.u4WakeLockThreadWakeup)); + + set_bit(GLUE_FLAG_RX_TO_OS_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq_rx); +} + +VOID kalSetTxCmdEvent2Hif(P_GLUE_INFO_T pr) +{ + if (!pr->hif_thread) + return; + + KAL_WAKE_LOCK_TIMEOUT(pr->prAdapter, &pr->rTimeoutWakeLock, + MSEC_TO_JIFFIES(pr->prAdapter->rWifiVar.u4WakeLockThreadWakeup)); + + set_bit(GLUE_FLAG_HIF_TX_CMD_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq_hif); +} +#endif +/*----------------------------------------------------------------------------*/ +/*! +* \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;*/ + + + /*Modify for Linux PC support NVRAM Setting*/ + return prGlueInfo->fgNvramAvailable; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Registry information +* +* \param[in] +* prGlueInfo +* +* \return +* Pointer of REG_INFO_T +*/ +/*----------------------------------------------------------------------------*/ +P_REG_INFO_T kalGetConfiguration(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return &(prGlueInfo->rRegInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve version information of corresponding configuration file +* +* \param[in] +* prGlueInfo +* +* \param[out] +* pu2Part1CfgOwnVersion +* pu2Part1CfgPeerVersion +* pu2Part2CfgOwnVersion +* pu2Part2CfgPeerVersion +* +* \return +* NONE +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalGetConfigurationVersion(IN P_GLUE_INFO_T prGlueInfo, + OUT PUINT_16 pu2Part1CfgOwnVersion, + OUT PUINT_16 pu2Part1CfgPeerVersion, + OUT PUINT_16 pu2Part2CfgOwnVersion, OUT PUINT_16 pu2Part2CfgPeerVersion) +{ + ASSERT(prGlueInfo); + + ASSERT(pu2Part1CfgOwnVersion); + ASSERT(pu2Part1CfgPeerVersion); + ASSERT(pu2Part2CfgOwnVersion); + ASSERT(pu2Part2CfgPeerVersion); + + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part1OwnVersion), pu2Part1CfgOwnVersion); + + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part1PeerVersion), pu2Part1CfgPeerVersion); + + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part2OwnVersion), pu2Part2CfgOwnVersion); + + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part2PeerVersion), pu2Part2CfgPeerVersion); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to check if the WPS is active or not +* +* \param[in] +* prGlueInfo +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalWSCGetActiveState(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->fgWpsActive; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief update RSSI and LinkQuality to GLUE layer +* +* \param[in] +* prGlueInfo +* eNetTypeIdx +* cRssi +* cLinkQuality +* +* \return +* None +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalUpdateRSSI(IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_KAL_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN INT_8 cRssi, IN INT_8 cLinkQuality) +{ + struct iw_statistics *pStats = (struct iw_statistics *)NULL; + + ASSERT(prGlueInfo); + + switch (eNetTypeIdx) { + case KAL_NETWORK_TYPE_AIS_INDEX: + pStats = (struct iw_statistics *)(&(prGlueInfo->rIwStats)); + break; +#if CFG_ENABLE_WIFI_DIRECT +#if CFG_SUPPORT_P2P_RSSI_QUERY + case KAL_NETWORK_TYPE_P2P_INDEX: + pStats = (struct iw_statistics *)(&(prGlueInfo->rP2pIwStats)); + break; +#endif +#endif + default: + break; + + } + + if (pStats) { + pStats->qual.qual = cLinkQuality; + pStats->qual.noise = 0; + pStats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_NOISE_UPDATED; + pStats->qual.level = 0x100 + cRssi; + pStats->qual.updated |= IW_QUAL_LEVEL_UPDATED; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Pre-allocate I/O buffer +* +* \param[in] +* none +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalInitIOBuffer(BOOLEAN is_pre_alloc) +{ + UINT_32 u4Size; + + /* not pre-allocation for all memory usage */ + if (!is_pre_alloc) { + pvIoBuffer = NULL; + return FALSE; + } + + /* pre-allocation for all memory usage */ + if (HIF_TX_COALESCING_BUFFER_SIZE > HIF_RX_COALESCING_BUFFER_SIZE) + u4Size = HIF_TX_COALESCING_BUFFER_SIZE; + else + u4Size = HIF_RX_COALESCING_BUFFER_SIZE; + + u4Size += HIF_EXTRA_IO_BUFFER_SIZE; + + 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) +{ + kfree(pvIoBuffer); + + pvIoBuffer = (PVOID) NULL; + pvIoBufferSize = 0; + pvIoBufferUsage = 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Dispatch pre-allocated I/O buffer +* +* \param[in] +* u4AllocSize +* +* \return +* PVOID for pointer of pre-allocated I/O buffer +*/ +/*----------------------------------------------------------------------------*/ +PVOID kalAllocateIOBuffer(IN UINT_32 u4AllocSize) +{ + PVOID ret = (PVOID) NULL; + + if (pvIoBuffer) { + if (u4AllocSize <= (pvIoBufferSize - pvIoBufferUsage)) { + ret = (PVOID) &(((PUINT_8) (pvIoBuffer))[pvIoBufferUsage]); + pvIoBufferUsage += u4AllocSize; + } + } else { + /* fault tolerance */ + ret = (PVOID) kalMemAlloc(u4AllocSize, PHY_MEM_TYPE); + } + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Release all dispatched I/O buffer +* +* \param[in] +* none +* +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalReleaseIOBuffer(IN PVOID pvAddr, IN UINT_32 u4Size) +{ + if (pvIoBuffer) { + pvIoBufferUsage -= u4Size; + } else { + /* fault tolerance */ + kalMemFree(pvAddr, PHY_MEM_TYPE, u4Size); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalGetChannelList(IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_BAND_T eSpecificBand, + IN UINT_8 ucMaxChannelNum, IN PUINT_8 pucNumOfChannel, IN P_RF_CHANNEL_INFO_T paucChannelList) +{ + rlmDomainGetChnlList(prGlueInfo->prAdapter, eSpecificBand, FALSE, + ucMaxChannelNum, pucNumOfChannel, paucChannelList); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOL kalIsAPmode(IN P_GLUE_INFO_T prGlueInfo) +{ +#if 0 /* Marked for MT6630 (New ucBssIndex) */ +#if CFG_ENABLE_WIFI_DIRECT + if (IS_NET_ACTIVE(prGlueInfo->prAdapter, NETWORK_TYPE_P2P_INDEX) && + p2pFuncIsAPMode(prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo)) + return TRUE; +#endif +#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) +{ + UINT_32 u4RsnMfp = RSN_AUTH_MFP_DISABLED; + + ASSERT(prGlueInfo); + + switch (prGlueInfo->rWpaInfo.u4Mfp) { + case IW_AUTH_MFP_DISABLED: + u4RsnMfp = RSN_AUTH_MFP_DISABLED; + break; + case IW_AUTH_MFP_OPTIONAL: + u4RsnMfp = RSN_AUTH_MFP_OPTIONAL; + break; + case IW_AUTH_MFP_REQUIRED: + u4RsnMfp = RSN_AUTH_MFP_REQUIRED; + break; + default: + u4RsnMfp = RSN_AUTH_MFP_DISABLED; + break; + } + + return u4RsnMfp; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to check if the RSN IE CAP setting from supplicant +* +* \param[in] +* prGlueInfo +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 kalGetRsnIeMfpCap(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->rWpaInfo.ucRSNMfpCap; +} +#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) +{ +#if KERNEL_VERSION(4, 14, 0) <= CFG80211_VERSION_CODE + return kernel_read(file, data, size, &offset); +#else + return kernel_read(file, offset, data, size); +#endif +} + +UINT_32 kalFileWrite(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size) +{ +#if KERNEL_VERSION(4, 14, 0) <= CFG80211_VERSION_CODE + return kernel_write(file, data, size, (loff_t *)&offset); +#else + return kernel_write(file, data, size, (loff_t)offset); +#endif +} + +UINT_32 kalWriteToFile(const PUINT_8 pucPath, BOOLEAN fgDoAppend, PUINT_8 pucData, UINT_32 u4Size) +{ + struct file *file = NULL; + UINT_32 ret = 0; /* size been written */ + UINT_32 u4Flags = 0; + + if (fgDoAppend) + u4Flags = O_APPEND; + + file = kalFileOpen(pucPath, O_WRONLY | O_CREAT | u4Flags, S_IRWXU); + if (file) { + ret = kalFileWrite(file, 0, pucData, u4Size); + kalFileClose(file); + } + + return ret; +} + +INT_32 kalReadToFile(const PUINT_8 pucPath, PUINT_8 pucData, UINT_32 u4Size, PUINT_32 pu4ReadSize) +{ + struct file *file = NULL; + INT_32 ret = -1; + UINT_32 u4ReadSize = 0; + + DBGLOG(INIT, INFO, "kalReadToFile() path %s\n", pucPath); + + file = kalFileOpen(pucPath, O_RDONLY, 0); + + if ((file != NULL) && !IS_ERR(file)) { + u4ReadSize = kalFileRead(file, 0, pucData, u4Size); + kalFileClose(file); + if (pu4ReadSize) + *pu4ReadSize = u4ReadSize; + ret = 0; + } + return ret; +} + +UINT_32 kalCheckPath(const PUINT_8 pucPath) +{ + struct file *file = NULL; + UINT_32 u4Flags = 0; + + file = kalFileOpen(pucPath, O_WRONLY | O_CREAT | u4Flags, S_IRWXU); + if (!file) + return -1; + + kalFileClose(file); + return 1; +} + +UINT_32 kalTrunkPath(const PUINT_8 pucPath) +{ + struct file *file = NULL; + UINT_32 u4Flags = O_TRUNC; + + file = kalFileOpen(pucPath, O_WRONLY | O_CREAT | u4Flags, S_IRWXU); + if (!file) + return -1; + + kalFileClose(file); + return 1; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief read request firmware file binary to pucData +* +* \param[in] pucPath file name +* \param[out] pucData Request file output buffer +* \param[in] u4Size read size +* \param[out] pu4ReadSize real read size +* \param[in] dev +* +* \return +* 0 success +* >0 fail +*/ +/*----------------------------------------------------------------------------*/ +INT_32 kalRequestFirmware(const PUINT_8 pucPath, PUINT_8 pucData, UINT_32 u4Size, + PUINT_32 pu4ReadSize, struct device *dev) +{ + const struct firmware *fw; + int ret = 0; + + /* + * Driver support request_firmware() to get files + * Android path: "/etc/firmware", "/vendor/firmware", "/firmware/image" + * Linux path: "/lib/firmware", "/lib/firmware/update" + */ + ret = REQUEST_FIRMWARE(&fw, pucPath, dev); + + if (ret != 0) { + DBGLOG(INIT, INFO, "kalRequestFirmware %s Fail, errno[%d]!!\n", pucPath, ret); + pucData = NULL; + *pu4ReadSize = 0; + release_firmware(fw); + return ret; + } + + DBGLOG(INIT, INFO, "kalRequestFirmware(): %s OK\n", pucPath); + + if (fw->size < u4Size) + u4Size = fw->size; + + memcpy(pucData, fw->data, u4Size); + if (pu4ReadSize) + *pu4ReadSize = u4Size; + + release_firmware(fw); + + 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, KAL_BAND_2GHZ)); + } else { + prChannel = + ieee80211_get_channel(wiphy, ieee80211_channel_to_frequency(ucChannelNum, KAL_BAND_5GHZ)); + } + + if (prChannel != NULL && prGlueInfo->fgIsRegistered == TRUE) { + struct cfg80211_bss *bss; +#if CFG_SUPPORT_TSF_USING_BOOTTIME + struct ieee80211_mgmt *prMgmtFrame = (struct ieee80211_mgmt *)pucBeaconProbeResp; + + prMgmtFrame->u.beacon.timestamp = kalGetBootTime(); +#endif + + /* indicate to NL80211 subsystem */ + bss = cfg80211_inform_bss_frame(wiphy, + prChannel, + (struct ieee80211_mgmt *)pucBeaconProbeResp, + u4FrameLen, i4SignalStrength * 100, GFP_KERNEL); + + if (!bss) { + /* ToDo:: DBGLOG */ + DBGLOG(REQ, WARN, "cfg80211_inform_bss_frame() returned with NULL\n"); + } else + cfg80211_put_bss(wiphy, bss); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate channel ready +* +* \param[in] +* prGlueInfo +* +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalReadyOnChannel(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, + IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_8 ucChannelNum, IN UINT_32 u4DurationMs) +{ + struct ieee80211_channel *prChannel = NULL; + enum nl80211_channel_type rChannelType; + + /* ucChannelNum = wlanGetChannelNumberByNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_AIS_INDEX); */ + + if (prGlueInfo->fgIsRegistered == TRUE) { + if (ucChannelNum <= 14) { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, KAL_BAND_2GHZ)); + } else { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, KAL_BAND_5GHZ)); + } + + if (!prChannel) { + DBGLOG(INIT, ERROR, "ieee80211_get_channel fail!\n"); + return; + } + + switch (eSco) { + case CHNL_EXT_SCN: + rChannelType = NL80211_CHAN_NO_HT; + break; + + case CHNL_EXT_SCA: + rChannelType = NL80211_CHAN_HT40MINUS; + break; + + case CHNL_EXT_SCB: + rChannelType = NL80211_CHAN_HT40PLUS; + break; + + case CHNL_EXT_RES: + default: + rChannelType = NL80211_CHAN_HT20; + break; + } + + cfg80211_ready_on_channel(prGlueInfo->prDevHandler->ieee80211_ptr, + u8Cookie, prChannel, u4DurationMs, GFP_KERNEL); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate channel expiration +* +* \param[in] +* prGlueInfo +* +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalRemainOnChannelExpired(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_8 ucChannelNum) +{ + struct ieee80211_channel *prChannel = NULL; + enum nl80211_channel_type rChannelType; + + ucChannelNum = + wlanGetChannelNumberByNetwork(prGlueInfo->prAdapter, prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex); + + if (prGlueInfo->fgIsRegistered == TRUE) { + if (ucChannelNum <= 14) { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, KAL_BAND_2GHZ)); + } else { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, KAL_BAND_5GHZ)); + } + + if (!prChannel) { + DBGLOG(INIT, ERROR, "ieee80211_get_channel fail!\n"); + return; + } + + switch (eSco) { + case CHNL_EXT_SCN: + rChannelType = NL80211_CHAN_NO_HT; + break; + + case CHNL_EXT_SCA: + rChannelType = NL80211_CHAN_HT40MINUS; + break; + + case CHNL_EXT_SCB: + rChannelType = NL80211_CHAN_HT40PLUS; + break; + + case CHNL_EXT_RES: + default: + rChannelType = NL80211_CHAN_HT20; + break; + } + + cfg80211_remain_on_channel_expired(prGlueInfo->prDevHandler->ieee80211_ptr, + u8Cookie, prChannel, GFP_KERNEL); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate Mgmt tx status +* +* \param[in] +* prGlueInfo +* +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalIndicateMgmtTxStatus(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, IN BOOLEAN fgIsAck, IN PUINT_8 pucFrameBuf, IN UINT_32 u4FrameLen) +{ + + do { + if ((prGlueInfo == NULL) + || (pucFrameBuf == NULL) + || (u4FrameLen == 0)) { + DBGLOG(AIS, TRACE, + "Unexpected pointer PARAM. 0x%lx, 0x%lx, %d.", + prGlueInfo, pucFrameBuf, u4FrameLen); + ASSERT(FALSE); + break; + } + + cfg80211_mgmt_tx_status(prGlueInfo->prDevHandler->ieee80211_ptr, + u8Cookie, pucFrameBuf, u4FrameLen, fgIsAck, GFP_KERNEL); + + } while (FALSE); + +} /* kalIndicateMgmtTxStatus */ + +VOID kalIndicateRxMgmtFrame(IN P_GLUE_INFO_T prGlueInfo, IN P_SW_RFB_T prSwRfb) +{ + INT_32 i4Freq = 0; + UINT_8 ucChnlNum = 0; + + do { + if ((prGlueInfo == NULL) || (prSwRfb == NULL)) { + ASSERT(FALSE); + break; + } + + ucChnlNum = (UINT_8) HAL_RX_STATUS_GET_CHNL_NUM(prSwRfb->prRxStatus); + + i4Freq = nicChannelNum2Freq(ucChnlNum) / 1000; + if (prGlueInfo->prDevHandler->ieee80211_ptr == NULL) { + DBGLOG(AIS, WARN, + "ieee80211_ptr is NULL!\n"); + break; + } + + if (prGlueInfo->u4OsMgmtFrameFilter == 0) { + DBGLOG(AIS, WARN, + "The cfg80211 hasn't do mgmt register!\n"); + break; + } + +#if (KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE) + cfg80211_rx_mgmt(prGlueInfo->prDevHandler->ieee80211_ptr, + i4Freq, /* in MHz */ + RCPI_TO_dBm((UINT_8) nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0, prSwRfb)), + prSwRfb->pvHeader, prSwRfb->u2PacketLen, + NL80211_RXMGMT_FLAG_ANSWERED); + +#elif (KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE) + cfg80211_rx_mgmt(prGlueInfo->prDevHandler->ieee80211_ptr, i4Freq, /* in MHz */ + RCPI_TO_dBm((UINT_8) + nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0, prSwRfb)), + prSwRfb->pvHeader, prSwRfb->u2PacketLen, + NL80211_RXMGMT_FLAG_ANSWERED, + GFP_ATOMIC); +#else + cfg80211_rx_mgmt(prGlueInfo->prDevHandler->ieee80211_ptr, i4Freq, /* in MHz */ + RCPI_TO_dBm((UINT_8) + nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0, prSwRfb)), + prSwRfb->pvHeader, prSwRfb->u2PacketLen, + GFP_ATOMIC); +#endif + + } while (FALSE); + +} /* kalIndicateRxMgmtFrame */ + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN +/*----------------------------------------------------------------------------*/ +/*! +* \brief To configure SDIO test pattern mode +* +* \param[in] +* prGlueInfo +* fgEn +* fgRead +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalSetSdioTestPattern(IN P_GLUE_INFO_T prGlueInfo, IN BOOLEAN fgEn, IN BOOLEAN fgRead) +{ + const UINT_8 aucPattern[] = { + 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, + 0xaa, 0x55, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x80, + 0x80, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, + 0x40, 0x40, 0x40, 0xbf, 0x40, 0x40, 0x40, 0xbf, + 0xbf, 0xbf, 0x40, 0xbf, 0xbf, 0xbf, 0x20, 0x20, + 0x20, 0xdf, 0x20, 0x20, 0x20, 0xdf, 0xdf, 0xdf, + 0x20, 0xdf, 0xdf, 0xdf, 0x10, 0x10, 0x10, 0xef, + 0x10, 0x10, 0x10, 0xef, 0xef, 0xef, 0x10, 0xef, + 0xef, 0xef, 0x08, 0x08, 0x08, 0xf7, 0x08, 0x08, + 0x08, 0xf7, 0xf7, 0xf7, 0x08, 0xf7, 0xf7, 0xf7, + 0x04, 0x04, 0x04, 0xfb, 0x04, 0x04, 0x04, 0xfb, + 0xfb, 0xfb, 0x04, 0xfb, 0xfb, 0xfb, 0x02, 0x02, + 0x02, 0xfd, 0x02, 0x02, 0x02, 0xfd, 0xfd, 0xfd, + 0x02, 0xfd, 0xfd, 0xfd, 0x01, 0x01, 0x01, 0xfe, + 0x01, 0x01, 0x01, 0xfe, 0xfe, 0xfe, 0x01, 0xfe, + 0xfe, 0xfe, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff + }; + UINT_32 i; + + ASSERT(prGlueInfo); + + /* access to MCR_WTMCR to engage PRBS mode */ + prGlueInfo->fgEnSdioTestPattern = fgEn; + prGlueInfo->fgSdioReadWriteMode = fgRead; + + if (fgRead == FALSE) { + /* fill buffer for data to be written */ + for (i = 0; i < sizeof(aucPattern); i++) + prGlueInfo->aucSdioTestBuffer[i] = aucPattern[i]; + } + + return TRUE; +} +#endif + +#if (CFG_MET_PACKET_TRACE_SUPPORT == 1) +#define PROC_MET_PROF_CTRL "met_ctrl" +#define PROC_MET_PROF_PORT "met_port" + +struct proc_dir_entry *pMetProcDir; +void *pMetGlobalData; + +#endif +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate scheduled scan results are avilable +* +* \param[in] +* prGlueInfo +* +* \return +* None +*/ +/*----------------------------------------------------------------------------*/ +VOID kalSchedScanResults(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE + cfg80211_sched_scan_results(priv_to_wiphy(prGlueInfo), + prGlueInfo->prSchedScanRequest->reqid); +#else + cfg80211_sched_scan_results(priv_to_wiphy(prGlueInfo)); +#endif + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate scheduled scan has been stopped +* +* \param[in] +* prGlueInfo +* +* \return +* None +*/ +/*----------------------------------------------------------------------------*/ +VOID kalSchedScanStopped(IN P_GLUE_INFO_T prGlueInfo) +{ + /* DBGLOG(SCN, INFO, ("-->kalSchedScanStopped\n" )); */ + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + +#if 1 + /* 1. reset first for newly incoming request */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if (prGlueInfo->prSchedScanRequest != NULL) + prGlueInfo->prSchedScanRequest = NULL; + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); +#endif + DBGLOG(SCN, INFO, "cfg80211_sched_scan_stopped send event\n"); + + /* 2. indication to cfg80211 */ + /* 20150205 change cfg80211_sched_scan_stopped to work queue to use K thread to send event instead of Tx thread + * due to sched_scan_mtx dead lock issue by Tx thread serves oid cmds and send event in the same time + */ + DBGLOG(SCN, INFO, "start work queue to send event\n"); + schedule_delayed_work(&sched_workq, 0); + DBGLOG(SCN, INFO, "main_thread return from kalSchedScanStoppped\n"); +} + +BOOLEAN +kalGetIPv4Address(IN struct net_device *prDev, + IN UINT_32 u4MaxNumOfAddr, OUT PUINT_8 pucIpv4Addrs, OUT PUINT_32 pu4NumOfIpv4Addr) +{ + UINT_32 u4NumIPv4 = 0; + UINT_32 u4AddrLen = IPV4_ADDR_LEN; + struct in_ifaddr *prIfa; + + /* 4 <1> Sanity check of netDevice */ + if (!prDev || !(prDev->ip_ptr) || !((struct in_device *)(prDev->ip_ptr))->ifa_list) { + DBGLOG(INIT, INFO, "IPv4 address is not available for dev(0x%p)\n", prDev); + + *pu4NumOfIpv4Addr = 0; + return FALSE; + } + + prIfa = ((struct in_device *)(prDev->ip_ptr))->ifa_list; + + /* 4 <2> copy the IPv4 address */ + while ((u4NumIPv4 < u4MaxNumOfAddr) && prIfa) { + kalMemCopy(&pucIpv4Addrs[u4NumIPv4 * u4AddrLen], &prIfa->ifa_local, u4AddrLen); + prIfa = prIfa->ifa_next; + + DBGLOG(INIT, INFO, + "IPv4 addr [%u][" IPV4STR "]\n", u4NumIPv4, IPV4TOSTR(&pucIpv4Addrs[u4NumIPv4 * u4AddrLen])); + + u4NumIPv4++; + } + + *pu4NumOfIpv4Addr = u4NumIPv4; + + return TRUE; +} + +#if IS_ENABLED(CONFIG_IPV6) +BOOLEAN +kalGetIPv6Address(IN struct net_device *prDev, + IN UINT_32 u4MaxNumOfAddr, OUT PUINT_8 pucIpv6Addrs, OUT PUINT_32 pu4NumOfIpv6Addr) +{ + UINT_32 u4NumIPv6 = 0; + UINT_32 u4AddrLen = IPV6_ADDR_LEN; + struct inet6_ifaddr *prIfa; + + /* 4 <1> Sanity check of netDevice */ + if (!prDev || !(prDev->ip6_ptr)) { + DBGLOG(INIT, INFO, "IPv6 address is not available for dev(0x%p)\n", prDev); + + *pu4NumOfIpv6Addr = 0; + return FALSE; + } + + + /* 4 <2> copy the IPv6 address */ + LIST_FOR_EACH_IPV6_ADDR(prIfa, prDev->ip6_ptr) { + kalMemCopy(&pucIpv6Addrs[u4NumIPv6 * u4AddrLen], &prIfa->addr, u4AddrLen); + + DBGLOG(INIT, INFO, + "IPv6 addr [%u][" IPV6STR "]\n", u4NumIPv6, IPV6TOSTR(&pucIpv6Addrs[u4NumIPv6 * u4AddrLen])); + + if ((u4NumIPv6 + 1) >= u4MaxNumOfAddr) + break; + u4NumIPv6++; + } + + *pu4NumOfIpv6Addr = u4NumIPv6; + + return TRUE; +} +#endif /* IS_ENABLED(CONFIG_IPV6) */ + +VOID +kalSetNetAddress(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucBssIdx, + IN PUINT_8 pucIPv4Addr, IN UINT_32 u4NumIPv4Addr, IN PUINT_8 pucIPv6Addr, IN UINT_32 u4NumIPv6Addr) +{ + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_32 u4SetInfoLen = 0; + UINT_32 u4Len = OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress); + P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList; + P_PARAM_NETWORK_ADDRESS prParamNetAddr; + UINT_32 i, u4AddrLen; + + /* 4 <1> Calculate buffer size */ + /* IPv4 */ + u4Len += (((sizeof(PARAM_NETWORK_ADDRESS) - 1) + IPV4_ADDR_LEN) * u4NumIPv4Addr); + /* IPv6 */ + u4Len += (((sizeof(PARAM_NETWORK_ADDRESS) - 1) + IPV6_ADDR_LEN) * u4NumIPv6Addr); + + /* 4 <2> Allocate buffer */ + prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST) kalMemAlloc(u4Len, VIR_MEM_TYPE); + + if (!prParamNetAddrList) { + DBGLOG(INIT, WARN, "Fail to alloc buffer for setting BSS[%u] network address!\n", ucBssIdx); + return; + } + /* 4 <3> Fill up network address */ + prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + prParamNetAddrList->u4AddressCount = 0; + prParamNetAddrList->ucBssIdx = ucBssIdx; + + /* 4 <3.1> Fill up IPv4 address */ + u4AddrLen = IPV4_ADDR_LEN; + prParamNetAddr = prParamNetAddrList->arAddress; + for (i = 0; i < u4NumIPv4Addr; i++) { + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + prParamNetAddr->u2AddressLength = u4AddrLen; + kalMemCopy(prParamNetAddr->aucAddress, &pucIPv4Addr[i * u4AddrLen], u4AddrLen); + + prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prParamNetAddr + + (ULONG) (u4AddrLen + + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + prParamNetAddrList->u4AddressCount += u4NumIPv4Addr; + + /* 4 <3.2> Fill up IPv6 address */ + u4AddrLen = IPV6_ADDR_LEN; + for (i = 0; i < u4NumIPv6Addr; i++) { + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + prParamNetAddr->u2AddressLength = u4AddrLen; + kalMemCopy(prParamNetAddr->aucAddress, &pucIPv6Addr[i * u4AddrLen], u4AddrLen); + + prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prParamNetAddr + + (ULONG) (u4AddrLen + + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + prParamNetAddrList->u4AddressCount += u4NumIPv6Addr; + + /* 4 <4> IOCTL to main_thread */ + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNetworkAddress, + (PVOID) prParamNetAddrList, u4Len, FALSE, FALSE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "%s: Fail to set network address\n", __func__); + + kalMemFree(prParamNetAddrList, VIR_MEM_TYPE, u4Len); + +} + +VOID kalSetNetAddressFromInterface(IN P_GLUE_INFO_T prGlueInfo, IN struct net_device *prDev, IN BOOLEAN fgSet) +{ + UINT_32 u4NumIPv4, u4NumIPv6; + UINT_8 pucIPv4Addr[IPV4_ADDR_LEN * CFG_PF_ARP_NS_MAX_NUM], pucIPv6Addr[IPV6_ADDR_LEN * CFG_PF_ARP_NS_MAX_NUM]; + P_NETDEV_PRIVATE_GLUE_INFO prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) NULL; + + prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(prDev); + + if (prNetDevPrivate->prGlueInfo != prGlueInfo) + DBGLOG(REQ, WARN, "%s: unexpected prGlueInfo(0x%p)!\n", __func__, prNetDevPrivate->prGlueInfo); + + u4NumIPv4 = 0; + u4NumIPv6 = 0; + + if (fgSet) { + kalGetIPv4Address(prDev, CFG_PF_ARP_NS_MAX_NUM, pucIPv4Addr, &u4NumIPv4); + kalGetIPv6Address(prDev, CFG_PF_ARP_NS_MAX_NUM, pucIPv6Addr, &u4NumIPv6); + } + + if (u4NumIPv4 + u4NumIPv6 > CFG_PF_ARP_NS_MAX_NUM) { + if (u4NumIPv4 >= CFG_PF_ARP_NS_MAX_NUM) { + u4NumIPv4 = CFG_PF_ARP_NS_MAX_NUM; + u4NumIPv6 = 0; + } else { + u4NumIPv6 = CFG_PF_ARP_NS_MAX_NUM - u4NumIPv4; + } + } + + kalSetNetAddress(prGlueInfo, prNetDevPrivate->ucBssIdx, pucIPv4Addr, u4NumIPv4, pucIPv6Addr, u4NumIPv6); +} + +#if CFG_MET_PACKET_TRACE_SUPPORT + +BOOLEAN kalMetCheckProfilingPacket(IN P_GLUE_INFO_T prGlueInfo, IN P_NATIVE_PACKET prPacket) +{ + UINT_32 u4PacketLen; + UINT_16 u2EtherTypeLen; + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + PUINT_8 aucLookAheadBuf = NULL; + UINT_8 ucEthTypeLenOffset = ETHER_HEADER_LEN - ETHER_TYPE_LEN; + PUINT_8 pucNextProtocol = NULL; + + u4PacketLen = prSkb->len; + + if (u4PacketLen < ETHER_HEADER_LEN) { + DBGLOG(INIT, WARN, "Invalid Ether packet length: %u\n", + u4PacketLen); + return FALSE; + } + + aucLookAheadBuf = prSkb->data; + + /* 4 <0> Obtain Ether Type/Len */ + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[ucEthTypeLenOffset], &u2EtherTypeLen); + + /* 4 <1> Skip 802.1Q header (VLAN Tagging) */ + if (u2EtherTypeLen == ETH_P_VLAN) { + ucEthTypeLenOffset += ETH_802_1Q_HEADER_LEN; + WLAN_GET_FIELD_BE16(&aucLookAheadBuf[ucEthTypeLenOffset], &u2EtherTypeLen); + } + /* 4 <2> Obtain next protocol pointer */ + pucNextProtocol = &aucLookAheadBuf[ucEthTypeLenOffset + ETHER_TYPE_LEN]; + + /* 4 <3> Handle ethernet format */ + switch (u2EtherTypeLen) { + + /* IPv4 */ + case ETH_P_IPV4: + { + PUINT_8 pucIpHdr = pucNextProtocol; + UINT_8 ucIpVersion; + + /* IPv4 header length check */ + if (u4PacketLen < (ucEthTypeLenOffset + ETHER_TYPE_LEN + IPV4_HDR_LEN)) { + DBGLOG(INIT, WARN, + "Invalid IPv4 packet length: %u\n", + u4PacketLen); + return FALSE; + } + + /* IPv4 version check */ + ucIpVersion = (pucIpHdr[0] & IP_VERSION_MASK) >> IP_VERSION_OFFSET; + if (ucIpVersion != IP_VERSION_4) { + DBGLOG(INIT, WARN, + "Invalid IPv4 packet version: %u\n", + ucIpVersion); + return FALSE; + } + + if (pucIpHdr[IPV4_HDR_IP_PROTOCOL_OFFSET] == IP_PROTOCOL_UDP) { + PUINT_8 pucUdpHdr = &pucIpHdr[IPV4_HDR_LEN]; + UINT_16 u2UdpDstPort; + UINT_16 u2UdpSrcPort; + + /* Get UDP DST port */ + WLAN_GET_FIELD_BE16(&pucUdpHdr[UDP_HDR_DST_PORT_OFFSET], &u2UdpDstPort); + + /* Get UDP SRC port */ + WLAN_GET_FIELD_BE16(&pucUdpHdr[UDP_HDR_SRC_PORT_OFFSET], &u2UdpSrcPort); + + if (u2UdpSrcPort == prGlueInfo->u2MetUdpPort) { + UINT_16 u2IpId; + + /* Store IP ID for Tag */ + WLAN_GET_FIELD_BE16(&pucIpHdr[IPV4_HDR_IP_IDENTIFICATION_OFFSET], &u2IpId); +#if 0 + DBGLOG(INIT, INFO, "TX PKT PROTOCOL[0x%x] UDP DST port[%u] IP_ID[%u]\n", + pucIpHdr[IPV4_HDR_IP_PROTOCOL_OFFSET], u2UdpDstPort, u2IpId); +#endif + GLUE_SET_PKT_IP_ID(prPacket, u2IpId); + + return TRUE; + } + } + } + break; + + default: + break; + } + + return FALSE; +} + +static unsigned long __read_mostly tracing_mark_write_addr; + +static int __mt_find_tracing_mark_write_symbol_fn(void *prData, const char *pcNameBuf, + struct module *prModule, unsigned long ulAddress) +{ + if (strcmp(pcNameBuf, "tracing_mark_write") == 0) { + tracing_mark_write_addr = ulAddress; + return 1; + } + return 0; +} + +static inline void __mt_update_tracing_mark_write_addr(void) +{ + if (unlikely(tracing_mark_write_addr == 0)) + kallsyms_on_each_symbol(__mt_find_tracing_mark_write_symbol_fn, NULL); +} + +VOID kalMetTagPacket(IN P_GLUE_INFO_T prGlueInfo, IN P_NATIVE_PACKET prPacket, IN ENUM_TX_PROFILING_TAG_T eTag) +{ + if (!prGlueInfo->fgMetProfilingEn) + return; + + switch (eTag) { + case TX_PROF_TAG_OS_TO_DRV: + if (kalMetCheckProfilingPacket(prGlueInfo, prPacket)) { + /* trace_printk("S|%d|%s|%d\n", current->pid, "WIFI-CHIP", GLUE_GET_PKT_IP_ID(prPacket)); */ + __mt_update_tracing_mark_write_addr(); +#if 0 /* #ifdef CONFIG_TRACING */ /* #if CFG_MET_PACKET_TRACE_SUPPORT */ + event_trace_printk(tracing_mark_write_addr, "S|%d|%s|%d\n", current->tgid, "WIFI-CHIP", + GLUE_GET_PKT_IP_ID(prPacket)); +#endif + GLUE_SET_PKT_FLAG_PROF_MET(prPacket); + } + break; + + case TX_PROF_TAG_DRV_TX_DONE: + if (GLUE_GET_PKT_IS_PROF_MET(prPacket)) { + /* trace_printk("F|%d|%s|%d\n", current->pid, "WIFI-CHIP", GLUE_GET_PKT_IP_ID(prPacket)); */ + __mt_update_tracing_mark_write_addr(); +#if 0 /* #ifdef CONFIG_TRACING */ /* #if CFG_MET_PACKET_TRACE_SUPPORT */ + event_trace_printk(tracing_mark_write_addr, "F|%d|%s|%d\n", current->tgid, "WIFI-CHIP", + GLUE_GET_PKT_IP_ID(prPacket)); +#endif + } + break; + + case TX_PROF_TAG_MAC_TX_DONE: + break; + + default: + break; + } +} + +VOID kalMetInit(IN P_GLUE_INFO_T prGlueInfo) +{ + prGlueInfo->fgMetProfilingEn = FALSE; + prGlueInfo->u2MetUdpPort = 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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. +*/ +/*----------------------------------------------------------------------------*/ +#if 0 +static ssize_t kalMetWriteProcfs(struct file *file, const char __user *buffer, size_t count, loff_t *off) +{ + char acBuf[128 + 1]; /* + 1 for "\0" */ + UINT_32 u4CopySize; + int u16MetUdpPort; + int u8MetProfEnable; + + IN P_GLUE_INFO_T prGlueInfo; + ssize_t result; + + u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + result = copy_from_user(acBuf, buffer, u4CopySize); + acBuf[u4CopySize] = '\0'; + + if (sscanf(acBuf, " %d %d", &u8MetProfEnable, &u16MetUdpPort) == 2) + DBGLOG(INIT, INFO, "MET_PROF: Write MET PROC Enable=%d UDP_PORT=%d\n", u8MetProfEnable, u16MetUdpPort); + if (pMetGlobalData != NULL) { + prGlueInfo = (P_GLUE_INFO_T) pMetGlobalData; + prGlueInfo->fgMetProfilingEn = (BOOLEAN) u8MetProfEnable; + prGlueInfo->u2MetUdpPort = (UINT_16) u16MetUdpPort; + } + return count; +} +#endif +static ssize_t kalMetCtrlWriteProcfs(struct file *file, const char __user *buffer, size_t count, loff_t *off) +{ + char acBuf[128 + 1]; /* + 1 for "\0" */ + UINT_32 u4CopySize; + int u8MetProfEnable; + ssize_t result; + + IN P_GLUE_INFO_T prGlueInfo; + + u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + result = copy_from_user(acBuf, buffer, u4CopySize); + acBuf[u4CopySize] = '\0'; + + if (sscanf(acBuf, " %d", &u8MetProfEnable) == 1) + DBGLOG(INIT, INFO, "MET_PROF: Write MET PROC Enable=%d\n", u8MetProfEnable); + if (pMetGlobalData != NULL) { + prGlueInfo = (P_GLUE_INFO_T) pMetGlobalData; + prGlueInfo->fgMetProfilingEn = (UINT_8) u8MetProfEnable; + } + return count; +} + +static ssize_t kalMetPortWriteProcfs(struct file *file, const char __user *buffer, size_t count, loff_t *off) +{ + char acBuf[128 + 1]; /* + 1 for "\0" */ + UINT_32 u4CopySize; + int u16MetUdpPort; + ssize_t result; + + IN P_GLUE_INFO_T prGlueInfo; + + u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + result = copy_from_user(acBuf, buffer, u4CopySize); + acBuf[u4CopySize] = '\0'; + + if (sscanf(acBuf, " %d", &u16MetUdpPort) == 1) + DBGLOG(INIT, INFO, "MET_PROF: Write MET PROC UDP_PORT=%d\n", u16MetUdpPort); + if (pMetGlobalData != NULL) { + prGlueInfo = (P_GLUE_INFO_T) pMetGlobalData; + prGlueInfo->u2MetUdpPort = (UINT_16) u16MetUdpPort; + } + return count; +} + +#if 0 +const struct file_operations rMetProcFops = { + .write = kalMetWriteProcfs +}; +#endif +const struct file_operations rMetProcCtrlFops = { + .write = kalMetCtrlWriteProcfs +}; + +const struct file_operations rMetProcPortFops = { + .write = kalMetPortWriteProcfs +}; + +int kalMetInitProcfs(IN P_GLUE_INFO_T prGlueInfo) +{ + /* struct proc_dir_entry *pMetProcDir; */ + if (init_net.proc_net == (struct proc_dir_entry *)NULL) { + DBGLOG(INIT, INFO, "init proc fs fail: proc_net == NULL\n"); + return -ENOENT; + } + /* + * Directory: Root (/proc/net/wlan0) + */ + pMetProcDir = proc_mkdir(prGlueInfo->prDevHandler->name, + init_net.proc_net); + if (pMetProcDir == NULL) + return -ENOENT; + /* + * /proc/net/wlan0 + * |-- met_ctrl (PROC_MET_PROF_CTRL) + */ + /* proc_create(PROC_MET_PROF_CTRL, 0x0644, pMetProcDir, &rMetProcFops); */ + proc_create(PROC_MET_PROF_CTRL, 0, pMetProcDir, &rMetProcCtrlFops); + proc_create(PROC_MET_PROF_PORT, 0, pMetProcDir, &rMetProcPortFops); + + pMetGlobalData = (void *)prGlueInfo; + + return 0; +} + +int kalMetRemoveProcfs(IN P_GLUE_INFO_T prGlueInfo) +{ + + if (init_net.proc_net == (struct proc_dir_entry *)NULL) { + DBGLOG(INIT, WARN, "remove proc fs fail: proc_net == NULL\n"); + return -ENOENT; + } + remove_proc_entry(PROC_MET_PROF_CTRL, pMetProcDir); + remove_proc_entry(PROC_MET_PROF_PORT, pMetProcDir); + /* remove root directory (proc/net/wlan0) */ + remove_proc_entry(prGlueInfo->prDevHandler->name, init_net.proc_net); + /* clear MetGlobalData */ + pMetGlobalData = NULL; + + return 0; +} + +#endif +#if CFG_SUPPORT_AGPS_ASSIST +BOOLEAN kalIndicateAgpsNotify(P_ADAPTER_T prAdapter, UINT_8 cmd, PUINT_8 data, UINT_16 dataLen) +{ +#ifdef CONFIG_NL80211_TESTMODE + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + struct sk_buff *skb = cfg80211_testmode_alloc_event_skb(priv_to_wiphy(prGlueInfo), + dataLen, GFP_KERNEL); + + /* DBGLOG(CCX, INFO, ("WLAN_STATUS_AGPS_NOTIFY, cmd=%d\n", cmd)); */ + if (unlikely(nla_put(skb, MTK_ATTR_AGPS_CMD, sizeof(cmd), &cmd) < 0)) + goto nla_put_failure; + if (dataLen > 0 && data && unlikely(nla_put(skb, MTK_ATTR_AGPS_DATA, dataLen, data) < 0)) + goto nla_put_failure; + if (unlikely(nla_put(skb, MTK_ATTR_AGPS_IFINDEX, sizeof(UINT_32), &prGlueInfo->prDevHandler->ifindex) < 0)) + goto nla_put_failure; + /* currently, the ifname maybe wlan0, p2p0, so the maximum name length will be 5 bytes */ + if (unlikely(nla_put(skb, MTK_ATTR_AGPS_IFNAME, 5, prGlueInfo->prDevHandler->name) < 0)) + goto nla_put_failure; + + cfg80211_testmode_event(skb, GFP_KERNEL); + return TRUE; + +nla_put_failure: + kfree_skb(skb); + return FALSE; +#else + return FALSE; +#endif +} +#endif + +UINT_64 kalGetBootTime(void) +{ + struct timespec ts; + UINT_64 bootTime = 0; + +#if KERNEL_VERSION(2, 6, 39) <= LINUX_VERSION_CODE + get_monotonic_boottime(&ts); +#else + ts = ktime_to_timespec(ktime_get()); +#endif + + bootTime = ts.tv_sec; + bootTime *= USEC_PER_SEC; + bootTime += ts.tv_nsec / NSEC_PER_USEC; + return bootTime; +} + +#if CFG_ASSERT_DUMP +WLAN_STATUS kalOpenCorDumpFile(BOOLEAN fgIsN9) +{ + /* Move open-op to kalWriteCorDumpFile(). Empty files only */ + UINT_32 ret; + PUINT_8 apucFileName; + + if (fgIsN9) + apucFileName = apucCorDumpN9FileName; + else + apucFileName = apucCorDumpCr4FileName; + + ret = kalTrunkPath(apucFileName); + + return (ret >= 0)?WLAN_STATUS_SUCCESS:WLAN_STATUS_FAILURE; +} + +WLAN_STATUS kalWriteCorDumpFile(PUINT_8 pucBuffer, UINT_16 u2Size, BOOLEAN fgIsN9) +{ + UINT_32 ret; + PUINT_8 apucFileName; + + if (fgIsN9) + apucFileName = apucCorDumpN9FileName; + else + apucFileName = apucCorDumpCr4FileName; + + ret = kalWriteToFile(apucFileName, TRUE, pucBuffer, u2Size); + + return (ret >= 0)?WLAN_STATUS_SUCCESS:WLAN_STATUS_FAILURE; +} + +WLAN_STATUS kalCloseCorDumpFile(BOOLEAN fgIsN9) +{ + /* Move close-op to kalWriteCorDumpFile(). Do nothing here */ + + return WLAN_STATUS_SUCCESS; +} +#endif + +#if CFG_WOW_SUPPORT +VOID kalWowInit(IN P_GLUE_INFO_T prGlueInfo) +{ + kalMemZero(&prGlueInfo->prAdapter->rWowCtrl.stWowPort, sizeof(WOW_PORT_T)); + prGlueInfo->prAdapter->rWowCtrl.ucReason = INVALID_WOW_WAKE_UP_REASON; +} + +VOID kalWowCmdEventSetCb(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + + if (prCmdInfo->ucCID == CMD_ID_SET_PF_CAPABILITY) { + DBGLOG(INIT, STATE, "CMD_ID_SET_PF_CAPABILITY cmd submitted\n"); + prAdapter->fgSetPfCapabilityDone = TRUE; + } + + if (prCmdInfo->ucCID == CMD_ID_SET_WOWLAN) { + DBGLOG(INIT, STATE, "CMD_ID_SET_WOWLAN cmd submitted\n"); + prAdapter->fgSetWowDone = TRUE; + } + +} + +VOID kalWowProcess(IN P_GLUE_INFO_T prGlueInfo, UINT_8 enable) +{ + CMD_WOWLAN_PARAM_T rCmdWowlanParam; + CMD_PACKET_FILTER_CAP_T rCmdPacket_Filter_Cap; + CMD_FW_LOG_2_HOST_CTRL_T rFwLog2HostCtrl; + P_WOW_CTRL_T pWOW_CTRL = &prGlueInfo->prAdapter->rWowCtrl; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 ii, u4BufLen, wait = 0; + BOOLEAN bWake = TRUE; /* to wake up host or just keep connection */ + + kalMemZero(&rCmdWowlanParam, sizeof(CMD_WOWLAN_PARAM_T)); + kalMemZero(&rFwLog2HostCtrl, sizeof(rFwLog2HostCtrl)); + kalMemZero(&rCmdPacket_Filter_Cap, sizeof(CMD_PACKET_FILTER_CAP_T)); + + prGlueInfo->prAdapter->fgSetPfCapabilityDone = FALSE; + prGlueInfo->prAdapter->fgSetWowDone = FALSE; + + if (prGlueInfo->prAdapter->rWifiVar.ucAdvPws == 1 + && prGlueInfo->prAdapter->rWowCtrl.fgWowEnable == 0) + bWake = FALSE; + + DBGLOG(PF, INFO, "PF, pAd AIS ucBssIndex=%d, ucOwnMacIndex=%d, band=%d\n", + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex, prGlueInfo->prAdapter->prAisBssInfo->ucOwnMacIndex, + prGlueInfo->prAdapter->prAisBssInfo->eDBDCBand); + + DBGLOG(PF, INFO, "profile wow=%d, GpioInterval=%d\n", + prGlueInfo->prAdapter->rWifiVar.ucWow, prGlueInfo->prAdapter->rWowCtrl.astWakeHif[0].u4GpioInterval); + + /* Kernel log timestamp correction */ + if (prGlueInfo->prAdapter->rWifiVar.ucN9Log2HostCtrl > 0) { + rFwLog2HostCtrl.ucMcuDest = 0; + rFwLog2HostCtrl.ucFwLog2HostCtrl = prGlueInfo->prAdapter->rWifiVar.ucN9Log2HostCtrl; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetFwLog2Host, + &rFwLog2HostCtrl, sizeof(CMD_FW_LOG_2_HOST_CTRL_T), + TRUE, TRUE, TRUE, &u4BufLen); + } + + + /* add band info */ + rCmdWowlanParam.ucDbdcBand = (UINT_8)prGlueInfo->prAdapter->prAisBssInfo->eDBDCBand; + + rCmdPacket_Filter_Cap.packet_cap_type |= PACKETF_CAP_TYPE_MAGIC; + /* 20160627 Bennett: if receive BMC magic, PF search by bssid index, which is different with OM index */ + /* After discussion, enable all bssid bits */ + /* rCmdPacket_Filter_Cap.ucBssid |= BIT(prGlueInfo->prAdapter->prAisBssInfo->ucOwnMacIndex); */ + rCmdPacket_Filter_Cap.ucBssid |= BITS(0, 3); + + if (enable && bWake) + rCmdPacket_Filter_Cap.usEnableBits |= PACKETF_CAP_TYPE_MAGIC; + else + rCmdPacket_Filter_Cap.usEnableBits &= ~PACKETF_CAP_TYPE_MAGIC; + + rStatus = wlanSendSetQueryCmd(prGlueInfo->prAdapter, + CMD_ID_SET_PF_CAPABILITY, + TRUE, + FALSE, + FALSE, + kalWowCmdEventSetCb, + nicOidCmdTimeoutCommon, + sizeof(CMD_PACKET_FILTER_CAP_T), + (PUINT_8)&rCmdPacket_Filter_Cap, + NULL, + 0); + + /* ARP offload */ + wlanSetSuspendMode(prGlueInfo, enable); + /* p2pSetSuspendMode(prGlueInfo, TRUE); */ + + /* wake up reason reset to default only when enter wow mode */ + if (enable) + pWOW_CTRL->ucReason = INVALID_WOW_WAKE_UP_REASON; + /* Let WOW enable/disable as last command, so we can back/restore DMA classify filter in FW */ + rCmdWowlanParam.ucScenarioID = pWOW_CTRL->ucScenarioId; + rCmdWowlanParam.ucBlockCount = pWOW_CTRL->ucBlockCount; + kalMemCopy(&rCmdWowlanParam.astWakeHif[0], &pWOW_CTRL->astWakeHif[0], sizeof(WOW_WAKE_HIF_T)); + + /* copy UDP/TCP port setting */ + if (enable && bWake) + kalMemCopy(&rCmdWowlanParam.stWowPort, + &prGlueInfo->prAdapter->rWowCtrl.stWowPort, + sizeof(WOW_PORT_T)); + else + kalMemZero(&prGlueInfo->prAdapter->rWowCtrl.stWowPort, + sizeof(WOW_PORT_T)); + + DBGLOG(PF, INFO, "Cmd: IPV4/UDP=%d, IPV4/TCP=%d, IPV6/UDP=%d, IPV6/TCP=%d\n", + rCmdWowlanParam.stWowPort.ucIPv4UdpPortCnt, rCmdWowlanParam.stWowPort.ucIPv4TcpPortCnt, + rCmdWowlanParam.stWowPort.ucIPv6UdpPortCnt, rCmdWowlanParam.stWowPort.ucIPv6TcpPortCnt); + + for (ii = 0; ii < rCmdWowlanParam.stWowPort.ucIPv4UdpPortCnt; ii++) + DBGLOG(PF, INFO, "IPV4/UDP port[%d]=%d\n", ii, rCmdWowlanParam.stWowPort.ausIPv4UdpPort[ii]); + + for (ii = 0; ii < rCmdWowlanParam.stWowPort.ucIPv4TcpPortCnt; ii++) + DBGLOG(PF, INFO, "IPV4/TCP port[%d]=%d\n", ii, rCmdWowlanParam.stWowPort.ausIPv4TcpPort[ii]); + + for (ii = 0; ii < rCmdWowlanParam.stWowPort.ucIPv6UdpPortCnt; ii++) + DBGLOG(PF, INFO, "IPV6/UDP port[%d]=%d\n", ii, rCmdWowlanParam.stWowPort.ausIPv6UdpPort[ii]); + + for (ii = 0; ii < rCmdWowlanParam.stWowPort.ucIPv6TcpPortCnt; ii++) + DBGLOG(PF, INFO, "IPV6/TCP port[%d]=%d\n", ii, rCmdWowlanParam.stWowPort.ausIPv6TcpPort[ii]); + + + /* GPIO parameter is necessary in suspend/resume */ + if (enable) { + rCmdWowlanParam.ucCmd = PM_WOWLAN_REQ_START; + rCmdWowlanParam.ucDetectType = WOWLAN_DETECT_TYPE_MAGIC | WOWLAN_DETECT_TYPE_ONLY_PHONE_SUSPEND; + rCmdWowlanParam.u2FilterFlag = WOWLAN_FF_DROP_ALL | WOWLAN_FF_SEND_MAGIC_TO_HOST | + WOWLAN_FF_ALLOW_1X | WOWLAN_FF_ALLOW_ARP_REQ2ME; + if (!bWake) + rCmdWowlanParam.ucDetectType = WOWLAN_DETECT_TYPE_NONE; + } else { + rCmdWowlanParam.ucCmd = PM_WOWLAN_REQ_STOP; + } + + rStatus = wlanSendSetQueryCmd(prGlueInfo->prAdapter, + CMD_ID_SET_WOWLAN, + TRUE, + FALSE, + FALSE, + kalWowCmdEventSetCb, + nicOidCmdTimeoutCommon, + sizeof(CMD_WOWLAN_PARAM_T), + (PUINT_8)&rCmdWowlanParam, + NULL, + 0); + + + while (1) { + kalMsleep(5); + + if (wait > 100) { + DBGLOG(INIT, ERROR, "WoW process timeout\n\n"); + break; + } + if ((prGlueInfo->prAdapter->fgSetPfCapabilityDone == TRUE) + && (prGlueInfo->prAdapter->fgSetWowDone == TRUE)) { + DBGLOG(INIT, STATE, "WoW process done\n\n"); + break; + } + wait++; + } + +} +#define MDNS_CMD_ENABLE 1 +#define MDNS_CMD_DISABLE 2 +#define MDNS_CMD_ADD_RECORD 3 +#define MDNS_CMD_DEL_RECORD 4 + +/* Parse "cast.tcp.local" to "4cast3tcp5local0". */ +UINT_16 NameParse(IN PUINT_8 prParseName, + IN UINT_16 ParseNameLen, OUT PUINT_8 pucBuffer) +{ + UINT_32 u4BufOffset = 0; + UINT_32 u4Loop = 0; + UINT_16 u2LabelOffset = 0; + UINT_16 u2NameCnt = 0; + UINT_16 name_length = 0; + + if (ParseNameLen == 0) { + /*Domain name is empty.*/ + pucBuffer[u4BufOffset] = 0; + u4BufOffset++; + } else { + u4Loop = 0; + u4BufOffset = 1; + u2LabelOffset = 0; + u2NameCnt = 0; + while (u4Loop < ParseNameLen) { + if (prParseName[u4Loop] != '.') { + pucBuffer[u4BufOffset] = prParseName[u4Loop]; + u4BufOffset++; + u2NameCnt++; + } else { + pucBuffer[u2LabelOffset] = u2NameCnt; + u2LabelOffset += (u2NameCnt + 1); + u4BufOffset++; + u2NameCnt = 0; + } + u4Loop++; + } + pucBuffer[u2LabelOffset] = u2NameCnt; + pucBuffer[u2LabelOffset + u2NameCnt + 1] = 0; + u4BufOffset++; + } + + name_length = u4BufOffset; + + return name_length; +} + +void kalMdnsProcess(IN P_GLUE_INFO_T prGlueInfo, + IN struct MDNS_PARAM_T *prMdnsParam) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + struct CMD_MDNS_PARAM_T *prCmdMdnsParam; + struct WLAN_MAC_HEADER_QoS_T *prMacHeader = NULL; + PUINT_8 pucIPHeader = NULL; + PUINT_8 pucUDPHeader = NULL; + PUINT_8 pucMdnsARecord = NULL; + struct MDNS_Template_Record *prMdnsTemplateRecord = NULL; + struct MDNS_ANSWER_RR *prMdnsAnswerR = NULL; + struct MDNS_TXT_RR *prMdnsTxtR = NULL; + struct MDNS_SRV_RR *prMdnsSrvR = NULL; + struct MDNS_QUESTION *prMdnsQuestion = NULL; + + UINT_16 u2SrvDataLen = 0; + UINT_16 u2NameLen = 0; + + prCmdMdnsParam = kzalloc(sizeof(struct CMD_MDNS_PARAM_T), GFP_KERNEL); + if (!prCmdMdnsParam) { + DBGLOG(REQ, ERROR, "%s, alloc mem for prCmdMdnsParam failed\n", + __func__); + return; + } + + memset(prCmdMdnsParam, 0, sizeof(struct CMD_MDNS_PARAM_T)); + prCmdMdnsParam->ucCmd = prMdnsParam->ucCmd; + prCmdMdnsParam->u4RecordId = prMdnsParam->u4RecordId; + + if (prMdnsParam->ucCmd == MDNS_CMD_ENABLE) { + DBGLOG(REQ, INFO, "kalMdnsProcess, mDNS Enable.\n"); + /* Store 802.11 MAC header.*/ + { + prMacHeader = &prCmdMdnsParam->aucMdnsMacHdr; + prMacHeader->u2FrameCtrl = MAC_FRAME_QOS_DATA; + prMacHeader->u2FrameCtrl |= MASK_FC_TO_DS; + prMacHeader->u2FrameCtrl |= MASK_FC_PWR_MGT; + + /* SA, DA.*/ + COPY_MAC_ADDR(prMacHeader->aucAddr2, + prGlueInfo->prDevHandler->dev_addr); + prMacHeader->aucAddr3[0] = 1; + prMacHeader->aucAddr3[1] = 0; + prMacHeader->aucAddr3[2] = 0x5E; + prMacHeader->aucAddr3[3] = 0; + prMacHeader->aucAddr3[4] = 0; + prMacHeader->aucAddr3[5] = 0xFB; + + prMacHeader->u2SeqCtrl = 0; + + prMacHeader->u2QosCtrl = 0; + prMacHeader->u2QosCtrl |= + (ACK_POLICY_NORMAL_ACK_IMPLICIT_BA_REQ + << MASK_QC_ACK_POLICY_OFFSET); + } + + /* IPv4 header.*/ + { + pucIPHeader = &prCmdMdnsParam->aucMdnsIPHdr[0]; + /* Version: 4, Length:(5*4) */ + pucIPHeader[0] = 4<<4 | 5; + /* Diff.Services */ + pucIPHeader[1] = 0; + /* IP length: + *(IPV4_HEADER_LENGTH + UDP_HEADER_LENGTH + u4MdnsLen) + */ + pucIPHeader[2] = 0; + pucIPHeader[3] = 0; + /* Identifier.*/ + pucIPHeader[4] = 0; + pucIPHeader[5] = 0; + /* Fragmentation Flags, Mask 0xE0.*/ + pucIPHeader[6] = 0; + pucIPHeader[6] = 1 << 6; + /* Fragment Offset, [6,7]Mask 0x1FFF.*/ + pucIPHeader[7] = 0; + /* TTL.*/ + pucIPHeader[8] = 255; + /* Protocol, UDP.*/ + pucIPHeader[9] = 17; + /* Header Checksum.*/ + pucIPHeader[10] = 0; + pucIPHeader[11] = 0; + /* Source IP: FW could check and update SIP again.*/ + pucIPHeader[12] = 0; + pucIPHeader[13] = 0; + pucIPHeader[14] = 0; + pucIPHeader[15] = 0; + /* DIP:MC IP(224.0.0.251) */ + pucIPHeader[16] = 224; + pucIPHeader[17] = 0; + pucIPHeader[18] = 0; + pucIPHeader[19] = 251; + } + + /*UDP header*/ + { + pucUDPHeader = &prCmdMdnsParam->aucMdnsUdpHdr[0]; + /* Source port: 5353 */ + pucUDPHeader[0] = (5353 & 0xff00) >> 8; + pucUDPHeader[1] = 5353 & 0x00ff; + /* Destination port: 5353 */ + pucUDPHeader[2] = (5353 & 0xff00) >> 8; + pucUDPHeader[3] = 5353 & 0x00ff; + /* UDP length: Calculate by FW*/ + pucUDPHeader[4] = 0; + pucUDPHeader[5] = 0; + /* UDP CheckSum: Calculate by FW*/ + pucUDPHeader[6] = 0; + pucUDPHeader[7] = 0; + } + + /* Store A RR.*/ + { + pucMdnsARecord = &prCmdMdnsParam->mdnsARecord[0]; + /* Type.*/ + pucMdnsARecord[0] = 0; + pucMdnsARecord[1] = 1; + /* Class.*/ + pucMdnsARecord[2] = (32769 & 0xff00) >> 8; + pucMdnsARecord[3] = 32769 & 0x00ff; + /* TTL.*/ + pucMdnsARecord[4] = 0; + pucMdnsARecord[5] = 0; + pucMdnsARecord[6] = (4500 & 0xff00) >> 8; + pucMdnsARecord[7] = 4500 & 0x00ff; + /* Data Length.*/ + pucMdnsARecord[8] = 0; + pucMdnsARecord[9] = 4; + /* SIP Address.*/ + pucMdnsARecord[10] = 0; + pucMdnsARecord[11] = 0; + pucMdnsARecord[12] = 0; + pucMdnsARecord[13] = 0; + } + } /* end of if (MDNS_CMD_ENABLE == prMdnsParam->ucCmd).*/ + + else if (prMdnsParam->ucCmd == MDNS_CMD_ADD_RECORD) { + DBGLOG(REQ, INFO, "kalMdnsProcess, Add Record.\n"); + + prMdnsTemplateRecord = &prCmdMdnsParam->mdnsQueryRespTemplate; + /*Step 1: Store the RecordId & bIsUsed.*/ + { + prMdnsTemplateRecord->u4RecordId = + prMdnsParam->u4RecordId; + prMdnsTemplateRecord->bIsUsed = FALSE; + } + + /*Step 2: Store the query template.*/ + { + prMdnsQuestion = + &prMdnsTemplateRecord->mdnsQuestionTemplate; + + u2NameLen = 0; + u2NameLen = NameParse(prMdnsParam->ucQueryName, + prMdnsParam->u2QueryNameLen, + &prMdnsQuestion->name[0]); + prMdnsTemplateRecord->mdnsQuestionTemplate.name_length = + u2NameLen; + prMdnsTemplateRecord->mdnsQuestionTemplate.type = + prMdnsParam->u2QueryType; + prMdnsTemplateRecord->mdnsQuestionTemplate.class = + prMdnsParam->u2QueryClass; + } /* end of Store the query template.*/ + + /* Step 3:Store Response template.*/ + { + /* 3.1 Store Answer Response Record.*/ + prMdnsAnswerR = + &prMdnsTemplateRecord->mdnsResponseRecord; + if (prMdnsParam->u2ResponseRecordLen > 0) { + memcpy(&prMdnsAnswerR->data[0], + &prMdnsParam->ucResponseRecord[0], + prMdnsParam->u2ResponseRecordLen); + } + prMdnsAnswerR->data_length = + prMdnsParam->u2ResponseRecordLen; + + /* 3.2 Store ServiceName & ServiceNameLen.*/ + u2NameLen = 0; + u2NameLen = NameParse(prMdnsParam->ucServiceName, + prMdnsParam->u2ServiceNameLen, + prMdnsTemplateRecord->ucServiceName); + prMdnsTemplateRecord->ServiceNameLen = u2NameLen; + + /* 3.3 Store SRV RR.*/ + prMdnsSrvR = &prMdnsTemplateRecord->mdnsSrvRecord; + + /* Type.*/ + prMdnsSrvR->data[0] = 0; + prMdnsSrvR->data[1] = 33; + /* Class.*/ + prMdnsSrvR->data[2] = (32769 & 0xff00) >> 8; + prMdnsSrvR->data[3] = 32769 & 0x00ff; + /* TTL.*/ + prMdnsSrvR->data[4] = 0; + prMdnsSrvR->data[5] = 0; + prMdnsSrvR->data[6] = 0; + prMdnsSrvR->data[7] = 120; + /* Data Length: + *SRV Prio + SRV Weight + SRV Port + + *SRV target(u2SrvDomainNameLen + .locol). + */ + u2SrvDataLen = + 6 + prMdnsTemplateRecord->ServiceNameLen + 6; + prMdnsSrvR->data[8] = (u2SrvDataLen & 0xff00) >> 8; + prMdnsSrvR->data[9] = u2SrvDataLen & 0x00ff; + /* Data: except that SRV target.*/ + { + /* SRV Priority.*/ + prMdnsSrvR->data[10] = 0; + prMdnsSrvR->data[11] = 0; + /* SRV Weight.*/ + prMdnsSrvR->data[12] = 0; + prMdnsSrvR->data[13] = 0; + /* SRV Port.*/ + prMdnsSrvR->data[14] = + (prMdnsParam->u4Port & 0xff00) >> 8; + prMdnsSrvR->data[15] = + prMdnsParam->u4Port & 0x00ff; + } + prMdnsSrvR->data_length = 16; + + /* 3.4 Store TXT RR.*/ + prMdnsTxtR = &prMdnsTemplateRecord->mdnsTxtRecord; + if (prMdnsParam->u2TxtRecordLen != 0) { + /* Type.*/ + prMdnsTxtR->data[0] = 0; + prMdnsTxtR->data[1] = 16; + /* Class.*/ + prMdnsTxtR->data[2] = (32769 & 0xff00) >> 8; + prMdnsTxtR->data[3] = 32769 & 0x00ff; + /* TTL.*/ + prMdnsTxtR->data[4] = 0; + prMdnsTxtR->data[5] = 0; + prMdnsTxtR->data[6] = 0; + prMdnsTxtR->data[7] = 120; + /* Data Length.*/ + prMdnsTxtR->data[8] = + (prMdnsParam->u2TxtRecordLen & 0xff00) + >> 8; + prMdnsTxtR->data[9] = + prMdnsParam->u2TxtRecordLen & 0x00ff; + /* Data.*/ + memcpy(&prMdnsTxtR->data[10], + &prMdnsParam->ucTxtRecord[0], + prMdnsParam->u2TxtRecordLen); + } + prMdnsTxtR->data_length = + prMdnsParam->u2TxtRecordLen + 10; + } /* end of store Response template.*/ + } /* end of if (MDNS_CMD_ADD_RECORD == prMdnsParam->ucCmd) .*/ + + rStatus = wlanSendSetQueryCmd(prGlueInfo->prAdapter, + CMD_ID_SET_MDNS_RECORD, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(struct CMD_MDNS_PARAM_T), + (PUINT_8) prCmdMdnsParam, + NULL, + 0); + + kfree(prCmdMdnsParam); +} + +#endif + +VOID kalFreeTxMsduWorker(struct work_struct *work) +{ + P_GLUE_INFO_T prGlueInfo; + P_ADAPTER_T prAdapter; + QUE_T rTmpQue; + P_QUE_T prTmpQue = &rTmpQue; + P_MSDU_INFO_T prMsduInfo; + + if (g_u4HaltFlag) + return; + + prGlueInfo = ENTRY_OF(work, GLUE_INFO_T, rTxMsduFreeWork); + prAdapter = prGlueInfo->prAdapter; + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) + return; + + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); + QUEUE_MOVE_ALL(prTmpQue, &prAdapter->rTxDataDoneQueue); + KAL_RELEASE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); + + while (QUEUE_IS_NOT_EMPTY(prTmpQue)) { + QUEUE_REMOVE_HEAD(prTmpQue, prMsduInfo, P_MSDU_INFO_T); + + nicTxFreePacket(prAdapter, prMsduInfo, FALSE); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } +} + +VOID kalFreeTxMsdu(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); + QUEUE_INSERT_TAIL(&prAdapter->rTxDataDoneQueue, (P_QUE_ENTRY_T) prMsduInfo); + KAL_RELEASE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); + + schedule_work(&prAdapter->prGlueInfo->rTxMsduFreeWork); +} + + +#if CFG_SUPPORT_DFS +VOID kalIndicateChannelSwitch(IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_CHNL_EXT_T eSco, IN UINT_8 ucChannelNum) +{ + struct cfg80211_chan_def chandef; + struct ieee80211_channel *prChannel = NULL; + enum nl80211_channel_type rChannelType; + + if (ucChannelNum <= 14) { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, + KAL_BAND_2GHZ)); + } else { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, + KAL_BAND_5GHZ)); + } + + if (!prChannel) { + DBGLOG(REQ, ERROR, "ieee80211_get_channel fail!\n"); + return; + } + + switch (eSco) { + case CHNL_EXT_SCN: + rChannelType = NL80211_CHAN_NO_HT; + break; + + case CHNL_EXT_SCA: + rChannelType = NL80211_CHAN_HT40MINUS; + break; + + case CHNL_EXT_SCB: + rChannelType = NL80211_CHAN_HT40PLUS; + break; + + case CHNL_EXT_RES: + default: + rChannelType = NL80211_CHAN_HT20; + break; + } + + DBGLOG(REQ, STATE, "DFS channel switch to %d\n", ucChannelNum); + + cfg80211_chandef_create(&chandef, prChannel, rChannelType); + cfg80211_ch_switch_notify(prGlueInfo->prDevHandler, &chandef); +} +#endif + +VOID kalInitDevWakeup(P_ADAPTER_T prAdapter, struct device *prDev) +{ + /* + * The remote wakeup function will be disabled after first time resume, + * we need to call device_init_wakeup() to notify usbcore that we + * support wakeup function, so usbcore will re-enable our remote wakeup + * function before entering suspend. + */ + if (prAdapter->rWifiVar.ucWow) + device_init_wakeup(prDev, TRUE); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_p2p.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_p2p.c new file mode 100644 index 0000000000000..61c903550d5f6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_p2p.c @@ -0,0 +1,1937 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include + +#include + + +#include "gl_os.h" +#include "debug.h" +#include "wlan_lib.h" +#include "gl_wext.h" + +/* #include */ +#include "gl_p2p_ioctl.h" + +#include "precomp.h" +#include "gl_vendor.h" +#include "gl_cfg80211.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) + +#if 0 +#define RUNNING_P2P_MODE 0 +#define RUNNING_AP_MODE 1 +#define RUNNING_DUAL_AP_MODE 2 +#endif +/******************************************************************************* +* 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 +******************************************************************************** +*/ + +struct net_device *g_P2pPrDev; +struct wireless_dev *gprP2pWdev; +struct wireless_dev *gprP2pRoleWdev[KAL_P2P_NUM]; +struct net_device *gPrP2pDev[KAL_P2P_NUM]; + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +static struct cfg80211_ops mtk_p2p_ops = { +#if (CFG_ENABLE_WIFI_DIRECT_CFG_80211 != 0) + /* Froyo */ + .add_virtual_intf = mtk_p2p_cfg80211_add_iface, + .change_virtual_intf = mtk_p2p_cfg80211_change_iface, /* 1 st */ + .del_virtual_intf = mtk_p2p_cfg80211_del_iface, + .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, + .mgmt_tx_cancel_wait = mtk_p2p_cfg80211_mgmt_tx_cancel_wait, + .connect = mtk_p2p_cfg80211_connect, + .disconnect = mtk_p2p_cfg80211_disconnect, + .deauth = mtk_p2p_cfg80211_deauth, + .disassoc = mtk_p2p_cfg80211_disassoc, + .start_ap = mtk_p2p_cfg80211_start_ap, + .change_beacon = mtk_p2p_cfg80211_change_beacon, + .stop_ap = mtk_p2p_cfg80211_stop_ap, + .set_wiphy_params = mtk_p2p_cfg80211_set_wiphy_params, + .del_station = mtk_p2p_cfg80211_del_station, + .set_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, + .set_default_mgmt_key = mtk_p2p_cfg80211_set_mgmt_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, +#if (CFG_SUPPORT_DFS_MASTER == 1) + .start_radar_detection = mtk_p2p_cfg80211_start_radar_detection, +#if KERNEL_VERSION(3, 13, 0) <= CFG80211_VERSION_CODE + .channel_switch = mtk_p2p_cfg80211_channel_switch, +#endif +#endif +#ifdef CONFIG_NL80211_TESTMODE + .testmode_cmd = mtk_p2p_cfg80211_testmode_cmd, +#endif +#endif +}; +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE + +static const struct wiphy_vendor_command mtk_p2p_vendor_ops[] = { + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_GET_CHANNEL_LIST + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_channel_list + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_SET_COUNTRY_CODE + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_country_code + }, +}; + +#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 + + +static const struct iw_priv_args rP2PIwPrivTable[] = { +#if 0 + { + .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"} + , +#endif + {IOCTL_GET_DRIVER, IW_PRIV_TYPE_CHAR | 2000, IW_PRIV_TYPE_CHAR | 2000, "driver"}, +}; + +#if 0 +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 +}; +#endif + +#ifdef CONFIG_PM +static const struct wiphy_wowlan_support mtk_p2p_wowlan_support = { + .flags = WIPHY_WOWLAN_DISCONNECT | WIPHY_WOWLAN_ANY, +}; +#endif + +static const struct ieee80211_iface_limit mtk_p2p_sta_go_limits[] = { + { + .max = 3, + .types = BIT(NL80211_IFTYPE_STATION), + }, + + { + .max = 1, + .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT), + }, +}; + +#if ((CFG_SUPPORT_DFS_MASTER == 1) && (KERNEL_VERSION(3, 17, 0) > CFG80211_VERSION_CODE)) +static const struct ieee80211_iface_limit mtk_ap_limits[] = { + { + .max = 1, + .types = BIT(NL80211_IFTYPE_AP), + }, +}; +#endif + +static const struct ieee80211_iface_combination +mtk_iface_combinations_sta[] = { + { +#ifdef CFG_NUM_DIFFERENT_CHANNELS_STA + .num_different_channels = CFG_NUM_DIFFERENT_CHANNELS_STA, +#else + .num_different_channels = 2, +#endif /* CFG_NUM_DIFFERENT_CHANNELS_STA */ + .max_interfaces = 3, + /*.beacon_int_infra_match = true,*/ + .limits = mtk_p2p_sta_go_limits, + .n_limits = 1, /* include p2p */ + }, +}; + +static const struct ieee80211_iface_combination +mtk_iface_combinations_p2p[] = { + { +#ifdef CFG_NUM_DIFFERENT_CHANNELS_P2P + .num_different_channels = CFG_NUM_DIFFERENT_CHANNELS_P2P, +#else + .num_different_channels = 2, +#endif /* CFG_NUM_DIFFERENT_CHANNELS_P2P */ + .max_interfaces = 3, + /*.beacon_int_infra_match = true,*/ + .limits = mtk_p2p_sta_go_limits, + .n_limits = ARRAY_SIZE(mtk_p2p_sta_go_limits), /* include p2p */ + }, +#if ((CFG_SUPPORT_DFS_MASTER == 1) && (KERNEL_VERSION(3, 17, 0) > CFG80211_VERSION_CODE)) + /* ONLY for passing checks in cfg80211_can_use_iftype_chan before linux-3.17.0 */ + { + .num_different_channels = 1, + .max_interfaces = 1, + .limits = mtk_ap_limits, + .n_limits = ARRAY_SIZE(mtk_ap_limits), + .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | + BIT(NL80211_CHAN_WIDTH_20) | + BIT(NL80211_CHAN_WIDTH_40) | + BIT(NL80211_CHAN_WIDTH_80) | + BIT(NL80211_CHAN_WIDTH_80P80), + }, +#endif +}; + + +const struct ieee80211_iface_combination *p_mtk_iface_combinations_sta = mtk_iface_combinations_sta; +const INT_32 mtk_iface_combinations_sta_num = ARRAY_SIZE(mtk_iface_combinations_sta); + +const struct ieee80211_iface_combination *p_mtk_iface_combinations_p2p = mtk_iface_combinations_p2p; +const INT_32 mtk_iface_combinations_p2p_num = ARRAY_SIZE(mtk_iface_combinations_p2p); + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/* 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 p2pSetMACAddress(IN struct net_device *prDev, void *addr); + +static int p2pDoIOCTL(struct net_device *prDev, struct ifreq *prIFReq, int i4Cmd); + + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ +} /* end of p2pUninit() */ + +const struct net_device_ops p2p_netdev_ops = { + .ndo_open = p2pOpen, + .ndo_stop = p2pStop, + .ndo_set_mac_address = p2pSetMACAddress, + .ndo_set_rx_mode = p2pSetMulticastList, + .ndo_get_stats = p2pGetStats, + .ndo_do_ioctl = p2pDoIOCTL, + .ndo_start_xmit = p2pHardStartXmit, + /* .ndo_select_queue = p2pSelectQueue, */ + .ndo_select_queue = wlanSelectQueue, + .ndo_init = p2pInit, + .ndo_uninit = p2pUninit, +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Allocate memory for P2P_INFO, GL_P2P_INFO, P2P_CONNECTION_SETTINGS +* P2P_SPECIFIC_BSS_INFO, P2P_FSM_INFO +* +* \param[in] prGlueInfo Pointer to glue info +* +* \return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2PAllocInfo(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucIdex) +{ + P_ADAPTER_T prAdapter = NULL; + P_WIFI_VAR_T prWifiVar = NULL; + /* UINT_32 u4Idx = 0; */ + + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(P2P, ERROR, "prGlueInfo error\n"); + return FALSE; + } + + prAdapter = prGlueInfo->prAdapter; + prWifiVar = &(prAdapter->rWifiVar); + + ASSERT(prAdapter); + ASSERT(prWifiVar); + + do { + if (prGlueInfo->prP2PInfo[ucIdex] == NULL) { + /*alloc memory for p2p info */ + prGlueInfo->prP2PInfo[ucIdex] = kalMemAlloc(sizeof(GL_P2P_INFO_T), VIR_MEM_TYPE); + + if (ucIdex == 0) { + /*printk("[CHECK!]p2PAllocInfo : Alloc Common part only first interface\n");*/ + prGlueInfo->prP2PDevInfo = kalMemAlloc(sizeof(GL_P2P_DEV_INFO_T), VIR_MEM_TYPE); + prAdapter->prP2pInfo = kalMemAlloc(sizeof(P2P_INFO_T), VIR_MEM_TYPE); + prWifiVar->prP2pDevFsmInfo = kalMemAlloc(sizeof(P2P_DEV_FSM_INFO_T), VIR_MEM_TYPE); + } + prWifiVar->prP2PConnSettings[ucIdex] = + kalMemAlloc(sizeof(P2P_CONNECTION_SETTINGS_T), VIR_MEM_TYPE); + prWifiVar->prP2pSpecificBssInfo[ucIdex] = + kalMemAlloc(sizeof(P2P_SPECIFIC_BSS_INFO_T), VIR_MEM_TYPE); + + /* TODO: It can be moved to the interface been created. */ +#if 0 + for (u4Idx = 0; u4Idx < BSS_P2P_NUM; u4Idx++) { + prWifiVar->aprP2pRoleFsmInfo[u4Idx] = + kalMemAlloc(sizeof(P2P_ROLE_FSM_INFO_T), VIR_MEM_TYPE); + } +#endif + } else { + ASSERT(prAdapter->prP2pInfo != NULL); + ASSERT(prWifiVar->prP2PConnSettings[ucIdex] != NULL); + /* ASSERT(prWifiVar->prP2pFsmInfo != NULL); */ + ASSERT(prWifiVar->prP2pSpecificBssInfo[ucIdex] != NULL); + } + /*MUST set memory to 0 */ + kalMemZero(prGlueInfo->prP2PInfo[ucIdex], sizeof(GL_P2P_INFO_T)); + if (ucIdex == 0) { + if (prGlueInfo->prP2PDevInfo) + kalMemZero(prGlueInfo->prP2PDevInfo, + sizeof(GL_P2P_DEV_INFO_T)); + if (prAdapter->prP2pInfo) + kalMemZero(prAdapter->prP2pInfo, + sizeof(P2P_INFO_T)); + if (prWifiVar->prP2pDevFsmInfo) + kalMemZero(prWifiVar->prP2pDevFsmInfo, + sizeof(P2P_DEV_FSM_INFO_T)); + } + kalMemZero(prWifiVar->prP2PConnSettings[ucIdex], sizeof(P2P_CONNECTION_SETTINGS_T)); +/* kalMemZero(prWifiVar->prP2pFsmInfo, sizeof(P2P_FSM_INFO_T)); */ + kalMemZero(prWifiVar->prP2pSpecificBssInfo[ucIdex], sizeof(P2P_SPECIFIC_BSS_INFO_T)); + + } while (FALSE); + + if (!prGlueInfo->prP2PDevInfo) + DBGLOG(P2P, ERROR, "prP2PDevInfo error\n"); + else + DBGLOG(P2P, INFO, "prP2PDevInfo ok\n"); + + if (!prGlueInfo->prP2PInfo[ucIdex]) + DBGLOG(P2P, ERROR, "prP2PInfo error\n"); + else + DBGLOG(P2P, INFO, "prP2PInfo ok\n"); + + + + /* chk if alloc successful or not */ + if (prGlueInfo->prP2PInfo[ucIdex] && prGlueInfo->prP2PDevInfo && prAdapter->prP2pInfo && + prWifiVar->prP2PConnSettings[ucIdex] && +/* prWifiVar->prP2pFsmInfo && */ + prWifiVar->prP2pSpecificBssInfo[ucIdex]) + return TRUE; + + + DBGLOG(P2P, ERROR, "[fail!]p2PAllocInfo :fail\n"); + + if (prWifiVar->prP2pSpecificBssInfo[ucIdex]) { + kalMemFree(prWifiVar->prP2pSpecificBssInfo[ucIdex], VIR_MEM_TYPE, sizeof(P2P_SPECIFIC_BSS_INFO_T)); + + prWifiVar->prP2pSpecificBssInfo[ucIdex] = NULL; + } +/* if (prWifiVar->prP2pFsmInfo) { */ +/* kalMemFree(prWifiVar->prP2pFsmInfo, VIR_MEM_TYPE, sizeof(P2P_FSM_INFO_T)); */ + +/* prWifiVar->prP2pFsmInfo = NULL; */ +/* } */ + if (prWifiVar->prP2PConnSettings[ucIdex]) { + kalMemFree(prWifiVar->prP2PConnSettings[ucIdex], VIR_MEM_TYPE, sizeof(P2P_CONNECTION_SETTINGS_T)); + + prWifiVar->prP2PConnSettings[ucIdex] = NULL; + } + if (prGlueInfo->prP2PDevInfo) { + kalMemFree(prGlueInfo->prP2PDevInfo, VIR_MEM_TYPE, sizeof(GL_P2P_DEV_INFO_T)); + + prGlueInfo->prP2PDevInfo = NULL; + } + if (prGlueInfo->prP2PInfo[ucIdex]) { + kalMemFree(prGlueInfo->prP2PInfo[ucIdex], VIR_MEM_TYPE, sizeof(GL_P2P_INFO_T)); + + prGlueInfo->prP2PInfo[ucIdex] = 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) +{ + + UINT_8 i; + + 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)); + + for (i = 0; i < KAL_P2P_NUM; i++) + if (prGlueInfo->prP2PInfo[i] != NULL) { + kalMemFree(prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings[i], VIR_MEM_TYPE, + sizeof(P2P_CONNECTION_SETTINGS_T)); + + prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings[i] = NULL; + kalMemFree(prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo[i], VIR_MEM_TYPE, + sizeof(P2P_SPECIFIC_BSS_INFO_T)); + + prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo[i] = NULL; + } + + kalMemFree(prGlueInfo->prP2PDevInfo, VIR_MEM_TYPE, sizeof(GL_P2P_DEV_INFO_T)); + + for (i = 0; i < KAL_P2P_NUM; i++) { + + if (prGlueInfo->prP2PInfo[i] != NULL) { + +#if (CFG_SUPPORT_DFS_MASTER == 1) + if (prGlueInfo->prP2PInfo[i]->chandef) { + if (prGlueInfo->prP2PInfo[i] + ->chandef->chan) { + cnmMemFree(prGlueInfo + ->prAdapter, + prGlueInfo + ->prP2PInfo[i] + ->chandef + ->chan); + prGlueInfo->prP2PInfo[i] + ->chandef->chan = NULL; + } + cnmMemFree(prGlueInfo->prAdapter, + prGlueInfo->prP2PInfo[i] + ->chandef); + prGlueInfo->prP2PInfo[i] + ->chandef = NULL; + } +#endif + + kalMemFree(prGlueInfo->prP2PInfo[i], VIR_MEM_TYPE, sizeof(GL_P2P_INFO_T)); + prGlueInfo->prP2PInfo[i] = NULL; + } + } + +/* kalMemFree(prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo, VIR_MEM_TYPE, sizeof(P2P_FSM_INFO_T)); */ + + kalMemFree(prGlueInfo->prAdapter->rWifiVar.prP2pDevFsmInfo, VIR_MEM_TYPE, sizeof(P2P_DEV_FSM_INFO_T)); + + /*Reomve p2p bss scan list */ + scanRemoveAllP2pBssDesc(prGlueInfo->prAdapter); + + /*reset all pointer to NULL */ + /*prGlueInfo->prP2PInfo[0] = NULL;*/ + prGlueInfo->prAdapter->prP2pInfo = NULL; +/* prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo = NULL; */ + prGlueInfo->prAdapter->rWifiVar.prP2pDevFsmInfo = NULL; + + return TRUE; + } else { + return FALSE; + } + +} + + + +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(); + } + + /* net device initialize */ + netif_carrier_off(prGlueInfo->prP2PInfo[0]->prDevHandler); + netif_tx_stop_all_queues(prGlueInfo->prP2PInfo[0]->prDevHandler); + + /* register for net device */ + if (register_netdev(prGlueInfo->prP2PInfo[0]->prDevHandler) < 0) { + DBGLOG(INIT, WARN, "unable to register netdevice for p2p\n"); + + free_netdev(prGlueInfo->prP2PInfo[0]->prDevHandler); + + ret = FALSE; + } else { + prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_REGISTERED; + gPrP2pDev[0] = prGlueInfo->prP2PInfo[0]->prDevHandler; + ret = TRUE; + } + + if (prGlueInfo->prAdapter->prP2pInfo->u4DeviceNum == RUNNING_DUAL_AP_MODE) { + /* net device initialize */ + netif_carrier_off(prGlueInfo->prP2PInfo[1]->prDevHandler); + netif_tx_stop_all_queues(prGlueInfo->prP2PInfo[1]->prDevHandler); + + /* register for net device */ + if (register_netdev(prGlueInfo->prP2PInfo[1]->prDevHandler) < 0) { + DBGLOG(INIT, WARN, "unable to register netdevice for p2p\n"); + + free_netdev(prGlueInfo->prP2PInfo[1]->prDevHandler); + + ret = FALSE; + } else { + prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_REGISTERED; + gPrP2pDev[1] = prGlueInfo->prP2PInfo[1]->prDevHandler; + ret = TRUE; + } + + + DBGLOG(P2P, INFO, "P2P 2nd interface work\n"); + } + if (fgRollbackRtnlLock) + rtnl_lock(); + + return ret; +} + +BOOLEAN p2pNetUnregister(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgIsRtnlLockAcquired) +{ + BOOLEAN fgDoUnregister = FALSE; + BOOLEAN fgRollbackRtnlLock = FALSE; + UINT_8 ucRoleIdx; + + 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 (prGlueInfo->prP2PInfo[0]->prDevHandler != prGlueInfo->prP2PInfo[0]->aprRoleHandler) { + if (netif_carrier_ok(prGlueInfo->prP2PInfo[0]->aprRoleHandler)) + netif_carrier_off(prGlueInfo->prP2PInfo[0]->aprRoleHandler); + + netif_tx_stop_all_queues(prGlueInfo->prP2PInfo[0]->aprRoleHandler); + } + + if (netif_carrier_ok(prGlueInfo->prP2PInfo[0]->prDevHandler)) + netif_carrier_off(prGlueInfo->prP2PInfo[0]->prDevHandler); + + netif_tx_stop_all_queues(prGlueInfo->prP2PInfo[0]->prDevHandler); + + if (fgIsRtnlLockAcquired && rtnl_is_locked()) { + fgRollbackRtnlLock = TRUE; + rtnl_unlock(); + } + /* Here are functions which need rtnl_lock */ + if (prGlueInfo->prP2PInfo[0]->prDevHandler != prGlueInfo->prP2PInfo[0]->aprRoleHandler) { + DBGLOG(INIT, INFO, "unregister p2p[0]\n"); + unregister_netdev(prGlueInfo->prP2PInfo[0]->aprRoleHandler); + } + DBGLOG(INIT, INFO, "unregister p2pdev\n"); + unregister_netdev(prGlueInfo->prP2PInfo[0]->prDevHandler); + + /* unregister the netdev and index > 0 */ + if (prGlueInfo->prAdapter->prP2pInfo->u4DeviceNum >= 2) { + for (ucRoleIdx = 1; ucRoleIdx < BSS_P2P_NUM; ucRoleIdx++) { + /* prepare for removal */ + if (netif_carrier_ok(prGlueInfo->prP2PInfo[ucRoleIdx]->prDevHandler)) + netif_carrier_off(prGlueInfo->prP2PInfo[ucRoleIdx]->prDevHandler); + + netif_tx_stop_all_queues(prGlueInfo->prP2PInfo[ucRoleIdx]->prDevHandler); + + if (fgIsRtnlLockAcquired && rtnl_is_locked()) { + fgRollbackRtnlLock = TRUE; + rtnl_unlock(); + } + /* Here are functions which need rtnl_lock */ + + unregister_netdev(prGlueInfo->prP2PInfo[ucRoleIdx]->prDevHandler); + } + } + + if (fgRollbackRtnlLock) + rtnl_lock(); + + prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_UNREGISTERED; + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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, const char *prDevName2, UINT_8 ucApMode) +{ + P_ADAPTER_T prAdapter = NULL; + P_GL_HIF_INFO_T prHif = NULL; + PARAM_MAC_ADDRESS rMacAddr; + P_NETDEV_PRIVATE_GLUE_INFO prNetDevPriv = (P_NETDEV_PRIVATE_GLUE_INFO) NULL; + BOOLEAN fgIsApMode = FALSE; + UINT_8 ucRegisterNum = 1, i = 0; + struct wireless_dev *prP2pWdev; +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + struct device *prDev; +#endif + const char *prSetDevName; + + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prHif = &prGlueInfo->rHifInfo; + ASSERT(prHif); + + if ((ucApMode == RUNNING_AP_MODE) || (ucApMode == RUNNING_DUAL_AP_MODE || (ucApMode == RUNNING_P2P_AP_MODE))) { + fgIsApMode = TRUE; + if ((ucApMode == RUNNING_DUAL_AP_MODE) || (ucApMode == RUNNING_P2P_AP_MODE)) { + ucRegisterNum = 2; + glP2pCreateWirelessDevice(prGlueInfo); + } + } + prSetDevName = prDevName; + + do { + if ((ucApMode == RUNNING_P2P_AP_MODE) && (i == 0)) { + prSetDevName = prDevName; + fgIsApMode = FALSE; + } else if ((ucApMode == RUNNING_P2P_AP_MODE) && (i == 1)) { + prSetDevName = prDevName2; + fgIsApMode = TRUE; + } +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + if (!gprP2pRoleWdev[i]) { + DBGLOG(P2P, ERROR, "gl_p2p, wireless device is not exist\n"); + return FALSE; + } +#endif + prP2pWdev = gprP2pRoleWdev[i]; + DBGLOG(INIT, INFO, "glRegisterP2P(%d)\n", i); + /*0. allocate p2pinfo */ + if (!p2PAllocInfo(prGlueInfo, i)) { + DBGLOG(INIT, WARN, "Allocate memory for p2p FAILED\n"); + ASSERT(0); + return FALSE; + } +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + + /* 1.1 fill wiphy parameters */ + glGetHifDev(prHif, &prDev); + if (!prDev) + DBGLOG(INIT, INFO, "unable to get struct dev for p2p\n"); + + prGlueInfo->prP2PInfo[i]->prWdev = prP2pWdev; + /*prGlueInfo->prP2PInfo[i]->prRoleWdev[0] = prP2pWdev;*//* TH3 multiple P2P */ + + ASSERT(prP2pWdev); + ASSERT(prP2pWdev->wiphy); + ASSERT(prDev); + ASSERT(prGlueInfo->prAdapter); + + set_wiphy_dev(prP2pWdev->wiphy, prDev); + + if (!prGlueInfo->prAdapter->fgEnable5GBand) + prP2pWdev->wiphy->bands[BAND_5G] = NULL; + + + + + /* 2.2 wdev initialization */ + if (fgIsApMode) + prP2pWdev->iftype = NL80211_IFTYPE_AP; + else + prP2pWdev->iftype = NL80211_IFTYPE_P2P_CLIENT; + +#endif /* CFG_ENABLE_WIFI_DIRECT_CFG_80211 */ + + + /* 3. allocate netdev */ +#if KERNEL_VERSION(3, 17, 0) <= CFG80211_VERSION_CODE + prGlueInfo->prP2PInfo[i]->prDevHandler = + alloc_netdev_mq(sizeof(NETDEV_PRIVATE_GLUE_INFO), prSetDevName, + NET_NAME_PREDICTABLE, ether_setup, CFG_MAX_TXQ_NUM); +#else + prGlueInfo->prP2PInfo[i]->prDevHandler = + alloc_netdev_mq(sizeof(NETDEV_PRIVATE_GLUE_INFO), prSetDevName, + ether_setup, CFG_MAX_TXQ_NUM); +#endif + if (!prGlueInfo->prP2PInfo[i]->prDevHandler) { + DBGLOG(INIT, WARN, "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; */ + prNetDevPriv = (P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(prGlueInfo->prP2PInfo[i]->prDevHandler); + prNetDevPriv->prGlueInfo = prGlueInfo; + + /* 4.2 fill hardware address */ + COPY_MAC_ADDR(rMacAddr, prAdapter->rMyMacAddr); + rMacAddr[0] |= 0x2; + rMacAddr[0] ^= i << 2; /* change to local administrated address */ + kalMemCopy(prGlueInfo->prP2PInfo[i]->prDevHandler->dev_addr, rMacAddr, ETH_ALEN); + kalMemCopy(prGlueInfo->prP2PInfo[i]->prDevHandler->perm_addr, + prGlueInfo->prP2PInfo[i]->prDevHandler->dev_addr, + ETH_ALEN); + + /* 4.3 register callback functions */ + prGlueInfo->prP2PInfo[i]->prDevHandler->needed_headroom += NIC_TX_HEAD_ROOM; + prGlueInfo->prP2PInfo[i]->prDevHandler->netdev_ops = &p2p_netdev_ops; + /* prGlueInfo->prP2PInfo->prDevHandler->wireless_handlers = &mtk_p2p_wext_handler_def; */ + +#if defined(_HIF_SDIO) +#if (MTK_WCN_HIF_SDIO == 0) + SET_NETDEV_DEV(prGlueInfo->prP2PInfo[i]->prDevHandler, &(prHif->func->dev)); +#endif +#endif + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + prGlueInfo->prP2PInfo[i]->prDevHandler->ieee80211_ptr = prP2pWdev; + prP2pWdev->netdev = prGlueInfo->prP2PInfo[i]->prDevHandler; +#endif + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + /* set HW checksum offload */ + if (prAdapter->fgIsSupportCsumOffload) + prGlueInfo->prP2PInfo[i]->prDevHandler->features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_RXCSUM; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + kalResetStats(prGlueInfo->prP2PInfo[i]->prDevHandler); + + +#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) { + DBGLOG(INIT, WARN, "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 */ + /* 13. bind netdev pointer to netdev index */ + wlanBindBssIdxToNetInterface(prGlueInfo, p2pDevFsmInit(prAdapter), + (PVOID) prGlueInfo->prP2PInfo[i]->prDevHandler); + + prGlueInfo->prP2PInfo[i]->aprRoleHandler = prGlueInfo->prP2PInfo[i]->prDevHandler; + + + DBGLOG(P2P, INFO, "check prDevHandler = %p\n", prGlueInfo->prP2PInfo[i]->prDevHandler); + DBGLOG(P2P, INFO, "aprRoleHandler = %p\n", prGlueInfo->prP2PInfo[i]->aprRoleHandler); + + prNetDevPriv->ucBssIdx = p2pRoleFsmInit(prAdapter, i); + /* 11. Currently wpasupplicant can't support create interface. */ + /* so initial the corresponding data structure here. */ + wlanBindBssIdxToNetInterface(prGlueInfo, prNetDevPriv->ucBssIdx, + (PVOID) prGlueInfo->prP2PInfo[i]->aprRoleHandler); + + /* 13. bind netdev pointer to netdev index */ + /* wlanBindNetInterface(prGlueInfo, NET_DEV_P2P_IDX, (PVOID)prGlueInfo->prP2PInfo->prDevHandler); */ + + /* 12. setup running mode */ + p2pFuncInitConnectionSettings(prAdapter, prAdapter->rWifiVar.prP2PConnSettings[i], fgIsApMode); + + /* Active network too early would cause HW not able to sleep. + * Defer the network active time. + */ + /* nicActivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); */ + + i++; + } while (i < ucRegisterNum); + + if ((ucApMode == RUNNING_DUAL_AP_MODE) || (ucApMode == RUNNING_P2P_AP_MODE)) + prGlueInfo->prAdapter->prP2pInfo->u4DeviceNum = 2; + else + prGlueInfo->prAdapter->prP2pInfo->u4DeviceNum = 1; + + + return TRUE; +#if 0 +err_reg_netdev: + free_netdev(prGlueInfo->prP2PInfo->prDevHandler); +#endif +err_alloc_netdev: + return FALSE; +} /* end of glRegisterP2P() */ + + +BOOLEAN glP2pCreateWirelessDevice(P_GLUE_INFO_T prGlueInfo) +{ + struct wiphy *prWiphy = NULL; + struct wireless_dev *prWdev = NULL; + UINT_8 idx = 0; + u32 band_idx, ch_idx; + struct ieee80211_supported_band *sband = NULL; + struct ieee80211_channel *chan = NULL; + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + for (idx = 0; idx < KAL_P2P_NUM; idx++) { + if (!gprP2pRoleWdev[idx]) + break; + } + if (idx == KAL_P2P_NUM) { + DBGLOG(INIT, ERROR, "Fail to create wdev\n"); + return FALSE; + } + + prWdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (!prWdev) { + DBGLOG(P2P, ERROR, "allocate p2p wireless device fail, no memory\n"); + return FALSE; + } + /* 1. allocate WIPHY */ + prWiphy = wiphy_new(&mtk_p2p_ops, sizeof(P_GLUE_INFO_T)); + if (!prWiphy) { + DBGLOG(P2P, ERROR, "unable to allocate wiphy for p2p\n"); + goto free_wdev; + } + + prWiphy->interface_modes = BIT(NL80211_IFTYPE_AP) + | BIT(NL80211_IFTYPE_P2P_CLIENT) + | BIT(NL80211_IFTYPE_P2P_GO) + | BIT(NL80211_IFTYPE_STATION); + + prWiphy->software_iftypes |= BIT(NL80211_IFTYPE_P2P_DEVICE); + + prWiphy->iface_combinations = p_mtk_iface_combinations_p2p; + prWiphy->n_iface_combinations = mtk_iface_combinations_p2p_num; + + prWiphy->bands[KAL_BAND_2GHZ] = &mtk_band_2ghz; + prWiphy->bands[KAL_BAND_5GHZ] = &mtk_band_5ghz; + + /* + * Clear flags in ieee80211_channel before p2p registers to resolve + * overriding flags issue. For example, when country is changed to US, + * both WW and US flags are applied. The issue flow is: + * + * 1. Register wlan wiphy (wiphy_register()@core.c) + * chan->orig_flags = chan->flags = 0 + * 2. Apply WW regdomain (handle_channel()@reg.c): + * chan->flags = chan->orig_flags|reg_channel_flags = 0|WW_channel_flags + * 3. Register p2p wiphy: + * chan->orig_flags = chan->flags = WW channel flags + * 4. Apply US regdomain: + * chan->flags = chan->orig_flags|reg_channel_flags + * = WW_channel_flags|US_channel_flags + * (Unexpected! It includes WW flags) + */ + + for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { + sband = prWiphy->bands[band_idx]; + if (!sband) + continue; + for (ch_idx = 0; ch_idx < sband->n_channels; ch_idx++) { + chan = &sband->channels[ch_idx]; + chan->flags = 0; + } + } + + prWiphy->mgmt_stypes = mtk_cfg80211_default_mgmt_stypes; + prWiphy->max_remain_on_channel_duration = 5000; + prWiphy->n_cipher_suites = 5; + prWiphy->cipher_suites = mtk_cipher_suites; +#if KERNEL_VERSION(3, 14, 0) > CFG80211_VERSION_CODE + prWiphy->flags = WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | WIPHY_FLAG_HAVE_AP_SME; +#else +#if (CFG_SUPPORT_DFS_MASTER == 1) + prWiphy->flags = WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_HAS_CHANNEL_SWITCH; + prWiphy->max_num_csa_counters = 2; +#else + prWiphy->flags = WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | WIPHY_FLAG_HAVE_AP_SME; +#endif + prWiphy->regulatory_flags = REGULATORY_CUSTOM_REG; +#endif + prWiphy->ap_sme_capa = 1; + + prWiphy->max_scan_ssids = MAX_SCAN_LIST_NUM; + prWiphy->max_scan_ie_len = MAX_SCAN_IE_LEN; + prWiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE + prWiphy->vendor_commands = mtk_p2p_vendor_ops; + prWiphy->n_vendor_commands = sizeof(mtk_p2p_vendor_ops) / sizeof(struct wiphy_vendor_command); +#endif + +#ifdef CONFIG_PM +#if KERNEL_VERSION(3, 9, 0) > CFG80211_VERSION_CODE + prWiphy->wowlan = &mtk_p2p_wowlan_support; +#endif +#endif + + cfg80211_regd_set_wiphy(prWiphy); + + /* 2.1 set priv as pointer to glue structure */ + *((P_GLUE_INFO_T *) wiphy_priv(prWiphy)) = prGlueInfo; + /* Here are functions which need rtnl_lock */ + if (wiphy_register(prWiphy) < 0) { + DBGLOG(INIT, WARN, "fail to register wiphy for p2p\n"); + goto free_wiphy; + } + prWdev->wiphy = prWiphy; + DBGLOG(INIT, INFO, "Registered gprP2pRoleWdev[%d]=0x%p\n", idx, prWdev); + gprP2pRoleWdev[idx] = prWdev; + + return TRUE; + +free_wiphy: + wiphy_free(prWiphy); +free_wdev: + kfree(prWdev); +#endif + return FALSE; +} + +void glP2pDestroyWirelessDevice(void) +{ +#if 0 +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + set_wiphy_dev(gprP2pWdev->wiphy, NULL); + + wiphy_unregister(gprP2pWdev->wiphy); + wiphy_free(gprP2pWdev->wiphy); + kfree(gprP2pWdev); + gprP2pWdev = NULL; +#endif +#else + int i = 0; + + /* Move set_wiphy_dev(wiphy, NULL) in wlanNetDestroy */ + + wiphy_unregister(gprP2pWdev->wiphy); + wiphy_free(gprP2pWdev->wiphy); + kfree(gprP2pWdev); + + for (i = 0; i < KAL_P2P_NUM; i++) { + + if (gprP2pRoleWdev[i] == NULL) + continue; + + if (i != 0) { /* The P2P is always in index 0 and shares Wiphy with P2PWdev */ + DBGLOG(INIT, INFO, "glP2pDestroyWirelessDevice (%p)\n", gprP2pRoleWdev[i]->wiphy); + set_wiphy_dev(gprP2pRoleWdev[i]->wiphy, NULL); + wiphy_unregister(gprP2pRoleWdev[i]->wiphy); + wiphy_free(gprP2pRoleWdev[i]->wiphy); + } + if (gprP2pRoleWdev[i] && (gprP2pWdev != gprP2pRoleWdev[i])) + kfree(gprP2pRoleWdev[i]); + gprP2pRoleWdev[i] = NULL; + } + + gprP2pWdev = NULL; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ + UINT_8 ucRoleIdx; + P_ADAPTER_T prAdapter; + P_GL_P2P_INFO_T prP2PInfo; + + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + + /* 4 <1> Uninit P2P dev FSM */ + /* Uninit P2P device FSM */ + p2pDevFsmUninit(prAdapter); + + /* 4 <2> Uninit P2P role FSM */ + for (ucRoleIdx = 0; ucRoleIdx < BSS_P2P_NUM; ucRoleIdx++) { + if (P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, ucRoleIdx)) + p2pRoleFsmUninit(prGlueInfo->prAdapter, ucRoleIdx); + } + + /* 4 <3> Free Wiphy & netdev */ + for (ucRoleIdx = 0; ucRoleIdx < BSS_P2P_NUM; ucRoleIdx++) { + prP2PInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + + if (prP2PInfo == NULL) + continue; + /* For P2P interfaces, prDevHandler points to the net_device of p2p0 interface. */ + /* And aprRoleHandler points to the net_device of p2p virtual interface (i.e., p2p1) */ + /* when it was created. And when p2p virtual interface is deleted, aprRoleHandler will */ + /* change to point to prDevHandler. Hence, when aprRoleHandler & prDevHandler are pointing */ + /* to different addresses, it means vif p2p1 exists. Otherwise it means p2p1 was */ + /* already deleted. */ + if ((prP2PInfo->aprRoleHandler != NULL) && + (prP2PInfo->aprRoleHandler != prP2PInfo->prDevHandler)) { + /* This device is added by the P2P, and use ndev->destructor to free. */ + prP2PInfo->aprRoleHandler = NULL; + DBGLOG(P2P, INFO, "aprRoleHandler idx %d set NULL\n", ucRoleIdx); + } + + if (prP2PInfo->prDevHandler) { + free_netdev(prP2PInfo->prDevHandler); + prP2PInfo->prDevHandler = NULL; + } + } + + /* 4 <4> Free P2P internal memory */ + if (!p2PFreeInfo(prGlueInfo)) { + DBGLOG(INIT, WARN, "Free memory for p2p FAILED\n"); + ASSERT(0); + return FALSE; + } + + return TRUE; + +#if 0 + 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 */ + kalClearMgmtFramesByBssIdx(prGlueInfo, NETWORK_TYPE_P2P_INDEX); + kalClearSecurityFramesByBssIdx(prGlueInfo, NETWORK_TYPE_P2P_INDEX); + /* Clear PendingCmdQue */ + wlanReleasePendingCMDbyBssIdx(prGlueInfo->prAdapter, NETWORK_TYPE_P2P_INDEX); + /* Clear PendingTxMsdu */ + nicFreePendingTxMsduInfoByBssIdx(prGlueInfo->prAdapter, NETWORK_TYPE_P2P_INDEX); +#endif + +#if 0 + /* prepare for removal */ + if (netif_carrier_ok(prGlueInfo->prP2PInfo[0]->prDevHandler)) + netif_carrier_off(prGlueInfo->prP2PInfo[0]->prDevHandler); + + netif_tx_stop_all_queues(prGlueInfo->prP2PInfo[0]->prDevHandler); + + /* netdevice unregistration & free */ + unregister_netdev(prGlueInfo->prP2PInfo[0]->prDevHandler); +#endif + free_netdev(prGlueInfo->prP2PInfo[0]->prDevHandler); + prGlueInfo->prP2PInfo[0]->prDevHandler = NULL; + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#if 0 + wiphy_unregister(prGlueInfo->prP2PInfo[0]->wdev.wiphy); +#endif + wiphy_free(prGlueInfo->prP2PInfo[0]->wdev.wiphy); + prGlueInfo->prP2PInfo[0]->wdev.wiphy = NULL; +#endif + + /* Free p2p memory */ +#if 1 + if (!p2PFreeInfo(prGlueInfo)) { + DBGLOG(INIT, WARN, "Free memory for p2p FAILED\n"); + ASSERT(0); + return FALSE; + } +#endif + return TRUE; + +#else + return 0; +#endif +} /* end of glUnregisterP2P() */ + +/* 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 */ + /*DFS todo 20161220_DFS*/ +#if (CFG_SUPPORT_DFS_MASTER == 1) + if (prDev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) { + netif_carrier_on(prDev); + netif_tx_start_all_queues(prDev); + } +#else + netif_carrier_on(prDev); + netif_tx_start_all_queues(prDev); +#endif + + 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_GL_P2P_DEV_INFO_T prP2pGlueDevInfo = (P_GL_P2P_DEV_INFO_T) NULL; + struct cfg80211_scan_request *prScanRequest = NULL; +/* P_MSG_P2P_FUNCTION_SWITCH_T prFuncSwitch; */ + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prP2pGlueDevInfo = prGlueInfo->prP2PDevInfo; + ASSERT(prP2pGlueDevInfo); + + /* 0. Do the scan done and set parameter to abort if the scan pending */ + /* Default : P2P dev */ + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if ((prP2pGlueDevInfo->prScanRequest != NULL) && + (prP2pGlueDevInfo->prScanRequest->wdev + == prDev->ieee80211_ptr)) { + prScanRequest = prP2pGlueDevInfo->prScanRequest; + kalCfg80211ScanDone(prScanRequest, TRUE); + prP2pGlueDevInfo->prScanRequest = NULL; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + /* 1. stop TX queue */ + netif_tx_stop_all_queues(prDev); +#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 */ + 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[0]->eState = PARAM_MEDIA_STATE_DISCONNECTED;*//* TH3 multiple P2P */ + + 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) +{ + return (struct net_device_stats *)kalGetStats(prDev); +} /* end of p2pGetStats() */ + +static void p2pSetMulticastList(IN struct net_device *prDev) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + + prGlueInfo = (prDev != NULL) ? *((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); + return; + } + +#if CFG_CHIP_RESET_SUPPORT + if (g_u4HaltFlag || checkResetState()) { + DBGLOG(INIT, WARN, "wlan is halt, skip p2pSetMulticastList\n"); + return; + } +#endif + + g_P2pPrDev = prDev; + + /* 4 Mark HALT, notify main thread to finish current job */ + set_bit(GLUE_FLAG_SUB_MOD_MULTICAST_BIT, &prGlueInfo->ulFlag); + /* 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; + UINT_32 u4McCount; + struct net_device *prDev = g_P2pPrDev; + + prGlueInfo = (prDev != NULL) ? *((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); + return; + } + + if (prDev->flags & IFF_PROMISC) + prGlueInfo->prP2PDevInfo->u4PacketFilter |= PARAM_PACKET_FILTER_PROMISCUOUS; + + if (prDev->flags & IFF_BROADCAST) + prGlueInfo->prP2PDevInfo->u4PacketFilter |= PARAM_PACKET_FILTER_BROADCAST; + u4McCount = netdev_mc_count(prDev); + + if (prDev->flags & IFF_MULTICAST) { + if ((prDev->flags & IFF_ALLMULTI) || (u4McCount > MAX_NUM_GROUP_ADDR)) + prGlueInfo->prP2PDevInfo->u4PacketFilter |= PARAM_PACKET_FILTER_ALL_MULTICAST; + else + prGlueInfo->prP2PDevInfo->u4PacketFilter |= PARAM_PACKET_FILTER_MULTICAST; + } + + if (prGlueInfo->prP2PDevInfo->u4PacketFilter & PARAM_PACKET_FILTER_MULTICAST) { + /* Prepare multicast address list */ + struct netdev_hw_addr *ha; + UINT_32 i = 0; + + netdev_for_each_mc_addr(ha, prDev) { + /* Check mc count before accessing to ha to prevent from + * kernel crash. One example crash log reported: + * Unable to handle kernel NULL pointer dereference at + * virtual address 00000008 + * PC is at mtk_p2p_wext_set_Multicastlist+0x150/0x22c + */ + if (i == u4McCount || !ha) + break; + if (i < MAX_NUM_GROUP_ADDR) { + COPY_MAC_ADDR(&(prGlueInfo->prP2PDevInfo->aucMCAddrList[i]), GET_ADDR(ha)); + i++; + } + } + + DBGLOG(P2P, TRACE, "SEt Multicast Address List\n"); + + if (i >= MAX_NUM_GROUP_ADDR) + return; + wlanoidSetP2PMulticastList(prGlueInfo->prAdapter, + &(prGlueInfo->prP2PDevInfo->aucMCAddrList[0]), + (i * ETH_ALEN), &u4SetInfoLen); + + } + +} /* 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_NETDEV_PRIVATE_GLUE_INFO prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_8 ucBssIndex; + + ASSERT(prSkb); + ASSERT(prDev); + +#if CFG_CHIP_RESET_SUPPORT + if (g_u4HaltFlag || checkResetState()) { + DBGLOG(INIT, WARN, "wlan is halt, skip p2pHardStartXmit\n"); + return NETDEV_TX_BUSY; + } +#endif + + prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(prDev); + prGlueInfo = prNetDevPrivate->prGlueInfo; + ucBssIndex = prNetDevPrivate->ucBssIdx; + + kalResetPacket(prGlueInfo, (P_NATIVE_PACKET) prSkb); + + kalHardStartXmit(prSkb, prDev, prGlueInfo, ucBssIndex); + + 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; + /* fill rIwReqInfo */ + rIwReqInfo.cmd = (__u16) i4Cmd; + rIwReqInfo.flags = 0; + + ASSERT(prDev && prIfReq); + +#if CFG_CHIP_RESET_SUPPORT + if (g_u4HaltFlag || checkResetState()) { + DBGLOG(INIT, WARN, "wlan is halt, skip p2pDoIOCTL\n"); + return -EFAULT; + } +#endif + + DBGLOG(P2P, ERROR, "p2pDoIOCTL In %x %x\n", i4Cmd, SIOCDEVPRIVATE); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + if (!prGlueInfo) { + DBGLOG(P2P, ERROR, "prGlueInfo is NULL\n"); + return -EFAULT; + } + + if (prGlueInfo->u4ReadyFlag == 0) { + DBGLOG(P2P, ERROR, "Adapter is not ready\n"); + return -EINVAL; + } + + if (i4Cmd == IOCTL_GET_DRIVER) + ret = priv_support_driver_cmd(prDev, prIfReq, i4Cmd); + else if (i4Cmd == SIOCGIWPRIV) + ret = mtk_p2p_wext_get_priv(prDev, &rIwReqInfo, &(prIwReq->u), NULL); +#ifdef CFG_ANDROID_AOSP_PRIV_CMD + else if (i4Cmd == SIOCDEVPRIVATE + 1) + ret = android_private_support_driver_cmd(prDev, prIfReq, i4Cmd); +#elif defined CFG_ALPS_ANDROID_AOSP_PRIV_CMD + else if (i4Cmd == SIOCDEVPRIVATE + 1) + ret = alps_android_private_support_driver_cmd(prDev, + prIfReq, i4Cmd); +#endif + else { + DBGLOG(INIT, WARN, "Unexpected ioctl command: 0x%04x\n", i4Cmd); + ret = -1; + } + +#if 0 + /* 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)) { + DBGLOG(INIT, 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: +#if 0 + ret = rP2PIwPrivHandler[i4Cmd - SIOCIWFIRSTPRIV](prDev, + &rIwReqInfo, + &(prIwReq->u), + (char *)&(prIwReq->u)); +#endif + 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; + } +#endif /* 0 */ + + return ret; +} /* end of p2pDoIOCTL() */ + + +/*----------------------------------------------------------------------------*/ +/*! + * \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; + struct sockaddr *sa = NULL; + P_BSS_INFO_T prBssInfo = NULL; + P_BSS_INFO_T prDevBssInfo = NULL; + uint8_t ucRoleIdx = 0, ucBssIdx = 0; + P_GL_P2P_INFO_T prP2pInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + if (!prDev || !addr) { + DBGLOG(INIT, ERROR, "Set macaddr with ndev(%d) and addr(%d)\n", + (prDev == NULL) ? 0 : 1, (addr == NULL) ? 0 : 1); + return WLAN_STATUS_INVALID_DATA; + } + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prDev, &ucRoleIdx) != 0) { + DBGLOG(INIT, ERROR, "can't find the matched dev"); + return WLAN_STATUS_INVALID_DATA; + } + + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, + ucRoleIdx, &ucBssIdx) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "can't find the matched bss"); + return WLAN_STATUS_INVALID_DATA; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + if (!prBssInfo) { + DBGLOG(INIT, ERROR, "bss is not active\n"); + return WLAN_STATUS_INVALID_DATA; + } + + prDevBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + P2P_DEV_BSS_INDEX); + if (!prDevBssInfo) { + DBGLOG(INIT, ERROR, "dev bss is not active\n"); + return WLAN_STATUS_INVALID_DATA; + } + + prP2pInfo = prGlueInfo->prP2PInfo[0]; + if (!prP2pInfo) { + DBGLOG(INIT, ERROR, "p2p info is null\n"); + return WLAN_STATUS_INVALID_DATA; + } + + sa = (struct sockaddr *)addr; + + COPY_MAC_ADDR(prBssInfo->aucOwnMacAddr, sa->sa_data); + COPY_MAC_ADDR(prDev->dev_addr, sa->sa_data); + + if (prP2pInfo->prDevHandler == prDev) { + COPY_MAC_ADDR(prAdapter->rWifiVar.aucDeviceAddress, + sa->sa_data); + COPY_MAC_ADDR(prDevBssInfo->aucOwnMacAddr, sa->sa_data); + DBGLOG(INIT, INFO, + "[%d][%d] Set random macaddr to " MACSTR ".\n", + ucBssIdx, + prDevBssInfo->ucBssIndex, + MAC2STR(prDevBssInfo->aucOwnMacAddr)); + } else { + DBGLOG(INIT, INFO, + "[%d] Set random macaddr to " MACSTR ".\n", + ucBssIdx, + MAC2STR(prBssInfo->aucOwnMacAddr)); + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \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() */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_p2p_cfg80211.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_p2p_cfg80211.c new file mode 100644 index 0000000000000..5babc9f35acf5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_p2p_cfg80211.c @@ -0,0 +1,3977 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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 +******************************************************************************** +*/ + +#include "config.h" + +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#include +#include +#include +#include +#include + +#include "precomp.h" +#include "gl_cfg80211.h" +#include "gl_p2p_os.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 +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +BOOLEAN +mtk_p2p_cfg80211func_channel_sco_switch(IN enum nl80211_channel_type channel_type, + IN P_ENUM_CHNL_EXT_T prChnlSco) +{ + BOOLEAN fgIsValid = FALSE; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211func_channel_sco_switch\n"); +#endif + + do { + 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; +} + +BOOLEAN +mtk_p2p_cfg80211func_channel_format_switch(IN struct cfg80211_chan_def *channel_def, + IN struct ieee80211_channel *channel, + IN P_RF_CHANNEL_INFO_T prRfChnlInfo) +{ + BOOLEAN fgIsValid = FALSE; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, + "mtk_p2p_cfg80211func_channel_format_switch\n"); +#endif + + do { + if (channel == NULL) + break; + + if (prRfChnlInfo) { + prRfChnlInfo->ucChannelNum = nicFreq2ChannelNum(channel->center_freq * 1000); + + switch (channel->band) { + case KAL_BAND_2GHZ: + prRfChnlInfo->eBand = BAND_2G4; + break; + case KAL_BAND_5GHZ: + prRfChnlInfo->eBand = BAND_5G; + break; + default: + prRfChnlInfo->eBand = BAND_2G4; + break; + } + + } + + if (channel_def && prRfChnlInfo) { + + switch (channel_def->width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + prRfChnlInfo->ucChnlBw = MAX_BW_20MHZ; + break; + case NL80211_CHAN_WIDTH_40: + prRfChnlInfo->ucChnlBw = MAX_BW_40MHZ; + break; + case NL80211_CHAN_WIDTH_80: + prRfChnlInfo->ucChnlBw = MAX_BW_80MHZ; + break; + case NL80211_CHAN_WIDTH_80P80: + prRfChnlInfo->ucChnlBw = MAX_BW_80_80_MHZ; + break; + case NL80211_CHAN_WIDTH_160: + prRfChnlInfo->ucChnlBw = MAX_BW_160MHZ; + break; + default: + prRfChnlInfo->ucChnlBw = MAX_BW_20MHZ; + break; + } + prRfChnlInfo->u2PriChnlFreq = channel->center_freq; + prRfChnlInfo->u4CenterFreq1 = channel_def->center_freq1; + prRfChnlInfo->u4CenterFreq2 = channel_def->center_freq2; + } + + fgIsValid = TRUE; + + } while (FALSE); + + return fgIsValid; +} + +/* mtk_p2p_cfg80211func_channel_format_switch */ + +INT_32 mtk_Netdev_To_RoleIdx(P_GLUE_INFO_T prGlueInfo, struct net_device *ndev, PUINT_8 pucRoleIdx) +{ + INT_32 i4Ret = -1; + UINT_32 u4Idx = 0; + + if (pucRoleIdx == NULL) + return i4Ret; +#if 0 + for (u4Idx = 0; u4Idx < KAL_P2P_NUM; u4Idx++) { + if (prGlP2pInfo->aprRoleHandler[u4Idx] == ndev) { + *pucRoleIdx = (UINT_8) u4Idx; + i4Ret = 0; + } + } +#if 1 + i4Ret = 0; + *pucRoleIdx = 0; +#endif +#else + for (u4Idx = 0; u4Idx < prGlueInfo->prAdapter->prP2pInfo->u4DeviceNum ; u4Idx++) { + + if (prGlueInfo->prP2PInfo[u4Idx]->aprRoleHandler == NULL) + continue; + + if (prGlueInfo->prP2PInfo[u4Idx]->aprRoleHandler == ndev) { + *pucRoleIdx = (UINT_8) u4Idx; + i4Ret = 0; + + } + } +#endif + + return i4Ret; + +} /* mtk_Netdev_To_RoleIdx */ + +static void mtk_vif_destructor(struct net_device *dev) +{ + struct wireless_dev *prWdev = ERR_PTR(-ENOMEM); + UINT_32 u4Idx = 0; + + DBGLOG(P2P, INFO, "mtk_newInf_destructor\n"); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, WARN, "mtk_newInf_destructor\n"); +#endif + + if (dev) { + prWdev = dev->ieee80211_ptr; + free_netdev(dev); + if (prWdev) { + /* Role[i] and Dev share the same wireless dev by default */ + for (u4Idx = 0; u4Idx < KAL_P2P_NUM; u4Idx++) { + if ((prWdev == gprP2pRoleWdev[u4Idx]) && + (gprP2pRoleWdev[u4Idx] != gprP2pWdev)) { + DBGLOG(P2P, INFO, "mtk_newInf_destructor remove added Wd\n"); + gprP2pRoleWdev[u4Idx] = gprP2pWdev; + } + } + kfree(prWdev); + } + } +} + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +struct wireless_dev *mtk_p2p_cfg80211_add_iface(struct wiphy *wiphy, + const char *name, unsigned char name_assign_type, + enum nl80211_iftype type, struct vif_params *params) +#elif KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE +struct wireless_dev *mtk_p2p_cfg80211_add_iface(struct wiphy *wiphy, + const char *name, unsigned char name_assign_type, + enum nl80211_iftype type, u32 *flags, struct vif_params *params) +#else +struct wireless_dev *mtk_p2p_cfg80211_add_iface(struct wiphy *wiphy, + const char *name, + enum nl80211_iftype type, u32 *flags, struct vif_params *params) +#endif +{ + /* 2 TODO: Fit kernel 3.10 modification */ + P_ADAPTER_T prAdapter; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + struct net_device *prNewNetDevice = NULL; + UINT_32 u4Idx = 0; + P_GL_P2P_INFO_T prP2pInfo = (P_GL_P2P_INFO_T) NULL; + P_GL_HIF_INFO_T prHif = NULL; + P_MSG_P2P_SWITCH_OP_MODE_T prSwitchModeMsg = (P_MSG_P2P_SWITCH_OP_MODE_T) NULL; + struct wireless_dev *prWdev = ERR_PTR(-ENOMEM); + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + P_NETDEV_PRIVATE_GLUE_INFO prNetDevPriv = (P_NETDEV_PRIVATE_GLUE_INFO) NULL; + PARAM_MAC_ADDRESS rMacAddr; + P_MSG_P2P_ACTIVE_DEV_BSS_T prMsgActiveBss = (P_MSG_P2P_ACTIVE_DEV_BSS_T) NULL; + + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_add_iface\n"); +#endif + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_add_iface\n"); + + do { + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (prGlueInfo == NULL) + break; + + prAdapter = prGlueInfo->prAdapter; + + for (u4Idx = 0; u4Idx < KAL_P2P_NUM; u4Idx++) { + if (prGlueInfo->prP2PInfo[u4Idx]->aprRoleHandler == + prGlueInfo->prP2PInfo[u4Idx]->prDevHandler) + break; + if (prGlueInfo->prP2PInfo[u4Idx]->aprRoleHandler == NULL) { + p2pRoleFsmInit(prGlueInfo->prAdapter, u4Idx); + break; + } + } + + if (u4Idx == KAL_P2P_NUM) { + /* Role port full. */ + break; + } + + /*u4Idx = 0;*/ + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_add_iface u4Idx=%d\n", u4Idx); + + prP2pInfo = prGlueInfo->prP2PInfo[u4Idx]; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_add_iface name = %s\n", name); +#if KERNEL_VERSION(3, 17, 0) <= CFG80211_VERSION_CODE + prNewNetDevice = alloc_netdev_mq(sizeof(NETDEV_PRIVATE_GLUE_INFO), name, + NET_NAME_PREDICTABLE, ether_setup, CFG_MAX_TXQ_NUM); +#else + prNewNetDevice = alloc_netdev_mq(sizeof(NETDEV_PRIVATE_GLUE_INFO), name, ether_setup, CFG_MAX_TXQ_NUM); +#endif + if (prNewNetDevice == NULL) { + DBGLOG(P2P, TRACE, "alloc_netdev_mq fail\n"); + break; + } + prP2pInfo->aprRoleHandler = prNewNetDevice; + + *((P_GLUE_INFO_T *) netdev_priv(prNewNetDevice)) = prGlueInfo; + + prNewNetDevice->needed_headroom += NIC_TX_HEAD_ROOM; + prNewNetDevice->netdev_ops = &p2p_netdev_ops; + + prHif = &prGlueInfo->rHifInfo; + ASSERT(prHif); + +#if defined(_HIF_SDIO) +#if (MTK_WCN_HIF_SDIO == 0) + SET_NETDEV_DEV(prNewNetDevice, &(prHif->func->dev)); +#endif +#endif + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + prWdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (!prWdev) { + DBGLOG(P2P, ERROR, "allocate p2p wireless device fail, no memory\n"); + prWdev = ERR_PTR(-ENOMEM); + free_netdev(prP2pInfo->aprRoleHandler); + prP2pInfo->aprRoleHandler = NULL; + break; + } + kalMemCopy(prWdev, gprP2pWdev, sizeof(struct wireless_dev)); + prWdev->netdev = prNewNetDevice; + prNewNetDevice->ieee80211_ptr = prWdev; + if (prNewNetDevice->ieee80211_ptr) + prNewNetDevice->ieee80211_ptr->iftype = type; + /* register destructor function for virtual interface */ +#if KERNEL_VERSION(4, 11, 0) <= CFG80211_VERSION_CODE + prNewNetDevice->priv_destructor = mtk_vif_destructor; +#else + prNewNetDevice->destructor = mtk_vif_destructor; +#endif + + gprP2pRoleWdev[u4Idx] = prWdev; + /*prP2pInfo->prRoleWdev[0] = prWdev;*//* TH3 multiple P2P */ +#endif + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + /* set HW checksum offload */ + if (prAdapter->fgIsSupportCsumOffload) + prNewNetDevice->features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_RXCSUM; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + kalResetStats(prNewNetDevice); + /* net device initialize */ + netif_carrier_off(prP2pInfo->aprRoleHandler); + netif_tx_stop_all_queues(prP2pInfo->aprRoleHandler); + + /* register for net device */ + if (register_netdevice(prP2pInfo->aprRoleHandler) < 0) { + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_add_iface 456\n"); + DBGLOG(INIT, WARN, "unable to register netdevice for p2p\n"); + kfree(prWdev); + prWdev = ERR_PTR(-ENOMEM); + free_netdev(prP2pInfo->aprRoleHandler); + prP2pInfo->aprRoleHandler = NULL; + break; + } else { + DBGLOG(P2P, TRACE, "register_netdev OK\n"); + prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_REGISTERED; + } + prP2pRoleFsmInfo = prAdapter->rWifiVar.aprP2pRoleFsmInfo[u4Idx]; + + /* 13. bind netdev pointer to netdev index */ + wlanBindBssIdxToNetInterface(prGlueInfo, prP2pRoleFsmInfo->ucBssIndex, + (PVOID) prP2pInfo->aprRoleHandler); + prNetDevPriv = (P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(prP2pInfo->aprRoleHandler); + prNetDevPriv->prGlueInfo = prGlueInfo; + prNetDevPriv->ucBssIdx = prP2pRoleFsmInfo->ucBssIndex; + + /* 4.2 fill hardware address */ + COPY_MAC_ADDR(rMacAddr, prAdapter->rMyMacAddr); + if (prGlueInfo->prAdapter->rWifiVar.ucP2pShareMacAddr && + (type == NL80211_IFTYPE_P2P_CLIENT || type == NL80211_IFTYPE_P2P_GO)) { + rMacAddr[0] = gPrP2pDev[0]->dev_addr[0]; + } else { + rMacAddr[0] |= 0x2; /* change to local administrated address */ + if (u4Idx > 0) + rMacAddr[0] ^= u4Idx << 2; + else + rMacAddr[0] ^= prGlueInfo->prAdapter->prP2pInfo->u4DeviceNum << 2; + } + kalMemCopy(prNewNetDevice->dev_addr, rMacAddr, ETH_ALEN); + kalMemCopy(prNewNetDevice->perm_addr, rMacAddr, ETH_ALEN); + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_add_iface ucBssIdx=%d\n", prNetDevPriv->ucBssIdx); + + /* 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); + DBGLOG(INIT, WARN, "unable to alloc msg\n"); + kfree(prWdev); + prWdev = ERR_PTR(-ENOMEM); + free_netdev(prGlueInfo->prP2PInfo[u4Idx]->aprRoleHandler); + prGlueInfo->prP2PInfo[u4Idx]->aprRoleHandler = NULL; + break; + } else { + prSwitchModeMsg->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; + prSwitchModeMsg->ucRoleIdx = 0; + switch (type) { + case NL80211_IFTYPE_P2P_CLIENT: + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_P2P_CLIENT.\n"); + prSwitchModeMsg->eOpMode = OP_MODE_INFRASTRUCTURE; + kalP2PSetRole(prGlueInfo, 1, u4Idx); + break; + case NL80211_IFTYPE_STATION: + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_STATION.\n"); + prSwitchModeMsg->eOpMode = OP_MODE_INFRASTRUCTURE; + kalP2PSetRole(prGlueInfo, 1, u4Idx); + break; + case NL80211_IFTYPE_AP: + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_AP.\n"); + prSwitchModeMsg->eOpMode = OP_MODE_ACCESS_POINT; + kalP2PSetRole(prGlueInfo, 2, u4Idx); + break; + case NL80211_IFTYPE_P2P_GO: + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_P2P_GO not AP.\n"); + prSwitchModeMsg->eOpMode = OP_MODE_ACCESS_POINT; + kalP2PSetRole(prGlueInfo, 2, u4Idx); + break; + default: + DBGLOG(P2P, TRACE, "Other type :%d .\n", type); + prSwitchModeMsg->eOpMode = OP_MODE_P2P_DEVICE; + kalP2PSetRole(prGlueInfo, 0, u4Idx); + break; + } + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prSwitchModeMsg, + MSG_SEND_METHOD_BUF); + } + + /* Send Msg to DevFsm and active P2P dev BSS */ + prMsgActiveBss = + (P_MSG_P2P_ACTIVE_DEV_BSS_T) cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(MSG_P2P_ACTIVE_DEV_BSS_T)); + + if (prMsgActiveBss == NULL) { + ASSERT(FALSE); + DBGLOG(INIT, WARN, "unable to alloc msg\n"); + kfree(prWdev); + prWdev = ERR_PTR(-ENOMEM); + free_netdev(prGlueInfo->prP2PInfo[u4Idx]->aprRoleHandler); + prGlueInfo->prP2PInfo[u4Idx]->aprRoleHandler = NULL; + break; + } + + prMsgActiveBss->rMsgHdr.eMsgId = MID_MNY_P2P_ACTIVE_BSS; + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgActiveBss, MSG_SEND_METHOD_BUF); + + } while (FALSE); + + return prWdev; +} /* mtk_p2p_cfg80211_add_iface */ + +int mtk_p2p_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev) +{ +#if 0 + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + P_MSG_P2P_DEL_IFACE_T prP2pDelIfaceMsg = (P_MSG_P2P_DEL_IFACE_T) NULL; + P_MSG_P2P_ACTIVE_DEV_BSS_T prMsgActiveBss = (P_MSG_P2P_ACTIVE_DEV_BSS_T) NULL; + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + if (prGlueInfo == NULL) + return -EINVAL; + + prP2pDelIfaceMsg = + (P_MSG_P2P_DEL_IFACE_T) cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(MSG_P2P_DEL_IFACE_T)); + + if (prP2pDelIfaceMsg == NULL) { + ASSERT(FALSE); + DBGLOG(INIT, WARN, "unable to alloc msg\n"); + } else { + prP2pDelIfaceMsg->rMsgHdr.eMsgId = MID_MNY_P2P_DEL_IFACE; + prP2pDelIfaceMsg->ucRoleIdx = 0; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prP2pDelIfaceMsg, MSG_SEND_METHOD_BUF); + + /* Send Msg to DevFsm and Deactive P2P dev BSS */ + prMsgActiveBss = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_ACTIVE_DEV_BSS_T)); + prMsgActiveBss->rMsgHdr.eMsgId = MID_MNY_P2P_ACTIVE_BSS; + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgActiveBss, MSG_SEND_METHOD_BUF); + } + +#else + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + P_MSG_P2P_DEL_IFACE_T prP2pDelIfaceMsg = (P_MSG_P2P_DEL_IFACE_T) NULL; + P_ADAPTER_T prAdapter; + P_GL_P2P_INFO_T prP2pInfo = (P_GL_P2P_INFO_T) NULL; + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + P_GL_P2P_DEV_INFO_T prP2pGlueDevInfo = (P_GL_P2P_DEV_INFO_T) NULL; + struct net_device *UnregRoleHander = (struct net_device *)NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_del_iface\n"); +#endif + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_del_iface\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + if (prGlueInfo == NULL) + return -EINVAL; + + prAdapter = prGlueInfo->prAdapter; + prP2pInfo = prGlueInfo->prP2PInfo[0]; + prP2pGlueDevInfo = prGlueInfo->prP2PDevInfo; + + KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_DEL_INF); + + prP2pRoleFsmInfo = prAdapter->rWifiVar.aprP2pRoleFsmInfo[0]; + wlanBindBssIdxToNetInterface(prGlueInfo, prP2pRoleFsmInfo->ucBssIndex, + (PVOID) prGlueInfo->prP2PInfo[0]->prDevHandler); + + UnregRoleHander = prP2pInfo->aprRoleHandler; + + /* Wait for kalSendCompleteAndAwakeQueue() complete */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + prP2pInfo->aprRoleHandler = prP2pInfo->prDevHandler; + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + /* Check the Scan request is pending and we abort it before delete interface */ + if (prP2pGlueDevInfo->prScanRequest != NULL) { + /* Check the wdev with backup scan req due to */ + /* the kernel will free this request by error handling */ + if (prP2pGlueDevInfo->rBackupScanRequest.wdev == UnregRoleHander->ieee80211_ptr) { + kalCfg80211ScanDone(&(prP2pGlueDevInfo->rBackupScanRequest), TRUE); + /* clear the request to avoid the Role FSM calls the scan_done again */ + prP2pGlueDevInfo->prScanRequest = NULL; + } + } + + /* prepare for removal */ + if (netif_carrier_ok(UnregRoleHander)) + netif_carrier_off(UnregRoleHander); + + netif_tx_stop_all_queues(UnregRoleHander); + + /* Here are functions which need rtnl_lock */ + unregister_netdevice(UnregRoleHander); + /* free is called at destructor */ + /* free_netdev(UnregRoleHander); */ + + KAL_RELEASE_MUTEX(prAdapter, MUTEX_DEL_INF); + + prP2pDelIfaceMsg = + (P_MSG_P2P_DEL_IFACE_T) cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(MSG_P2P_DEL_IFACE_T)); + + if (prP2pDelIfaceMsg == NULL) { + ASSERT(FALSE); + DBGLOG(INIT, WARN, "unable to alloc msg\n"); + } else { + prP2pDelIfaceMsg->rMsgHdr.eMsgId = MID_MNY_P2P_DEL_IFACE; + prP2pDelIfaceMsg->ucRoleIdx = 0; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prP2pDelIfaceMsg, MSG_SEND_METHOD_BUF); + } +#endif + return 0; +} /* mtk_p2p_cfg80211_del_iface */ + +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; + UINT_8 ucRoleIdx = 0; + const UINT_8 aucBCAddr[] = BC_MAC_ADDR; + /* const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; */ +#if CFG_SUPPORT_REPLAY_DETECTION + P_BSS_INFO_T prBssInfo = NULL; + struct SEC_DETECT_REPLAY_INFO *prDetRplyInfo = NULL; + UINT_8 ucCheckZeroKey = 0; + UINT_8 i = 0; +#endif + + ASSERT(wiphy); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_add_key\n"); +#endif + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, ndev, &ucRoleIdx) != 0) + return -EINVAL; +#if DBG + DBGLOG(RSN, TRACE, "mtk_p2p_cfg80211_add_key\n"); + if (mac_addr) { + DBGLOG(RSN, INFO, + "keyIdx = %d pairwise = %d mac = " MACSTR "\n", key_index, pairwise, MAC2STR(mac_addr)); + } else { + DBGLOG(RSN, INFO, "keyIdx = %d pairwise = %d null mac\n", key_index, pairwise); + } + DBGLOG(RSN, TRACE, "Cipher = %x\n", params->cipher); + DBGLOG_MEM8(RSN, TRACE, params->key, params->key_len); +#endif + + /* Todo:: By Cipher to set the key */ + + kalMemZero(&rKey, sizeof(P2P_PARAM_KEY_T)); + + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &rKey.ucBssIdx) != WLAN_STATUS_SUCCESS) + return -EINVAL; + + rKey.u4KeyIndex = key_index; + + if (params->cipher) { + switch (params->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + rKey.ucCipher = CIPHER_SUITE_WEP40; + break; + case WLAN_CIPHER_SUITE_WEP104: + rKey.ucCipher = CIPHER_SUITE_WEP104; + break; +#if 0 + case WLAN_CIPHER_SUITE_WEP128: + rKey.ucCipher = CIPHER_SUITE_WEP128; + break; +#endif + case WLAN_CIPHER_SUITE_TKIP: + rKey.ucCipher = CIPHER_SUITE_TKIP; + break; + case WLAN_CIPHER_SUITE_CCMP: + rKey.ucCipher = CIPHER_SUITE_CCMP; + break; +#if 0 + case WLAN_CIPHER_SUITE_GCMP: + rKey.ucCipher = CIPHER_SUITE_GCMP; + break; + case WLAN_CIPHER_SUITE_CCMP_256: + rKey.ucCipher = CIPHER_SUITE_CCMP256; + break; +#endif + case WLAN_CIPHER_SUITE_SMS4: + rKey.ucCipher = CIPHER_SUITE_WPI; + break; + case WLAN_CIPHER_SUITE_AES_CMAC: + rKey.ucCipher = CIPHER_SUITE_BIP; + break; + default: + ASSERT(FALSE); + } + } + + /* For BC addr case: ex: AP mode, driver_nl80211 will not have mac_addr */ + if (pairwise) { + rKey.u4KeyIndex |= BIT(31); /* Tx */ + rKey.u4KeyIndex |= BIT(30); /* Pairwise */ + COPY_MAC_ADDR(rKey.arBSSID, mac_addr); + } else { + COPY_MAC_ADDR(rKey.arBSSID, aucBCAddr); + } + + /* Check if add key under AP mode */ + if (kalP2PGetRole(prGlueInfo, ucRoleIdx) == 2) + rKey.u4KeyIndex |= BIT(28); /* authenticator */ + +#if CFG_SUPPORT_REPLAY_DETECTION + if (params->key) { + for (i = 0; i < params->key_len; i++) { + if (params->key[i] == 0x00) + ucCheckZeroKey++; + } + + if (ucCheckZeroKey == params->key_len) + return 0; + } +#endif + + if (params->key) + kalMemCopy(rKey.aucKeyMaterial, params->key, params->key_len); + rKey.u4KeyLength = params->key_len; + rKey.u4Length = ((ULONG)&(((P_P2P_PARAM_KEY_T) 0)->aucKeyMaterial)) + rKey.u4KeyLength; + +#if CFG_SUPPORT_REPLAY_DETECTION + prBssInfo = GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, rKey.ucBssIdx); + + prDetRplyInfo = &prBssInfo->rDetRplyInfo; + + if ((!pairwise) && ((params->cipher == WLAN_CIPHER_SUITE_TKIP) || (params->cipher == WLAN_CIPHER_SUITE_CCMP))) { + if ((prDetRplyInfo->ucCurKeyId == key_index) && + (!kalMemCmp(prDetRplyInfo->aucKeyMaterial, params->key, params->key_len))) { + DBGLOG(RSN, TRACE, "M3/G1, KeyID and KeyValue equal.\n"); + DBGLOG(RSN, TRACE, "hit group key reinstall case, so no update BC/MC PN.\n"); + } else { + kalMemCopy(prDetRplyInfo->arReplayPNInfo[key_index].auPN, params->seq, params->seq_len); + prDetRplyInfo->ucCurKeyId = key_index; + prDetRplyInfo->u4KeyLength = params->key_len; + kalMemCopy(prDetRplyInfo->aucKeyMaterial, params->key, params->key_len); + } + + prDetRplyInfo->fgKeyRscFresh = TRUE; + } +#endif + + rStatus = kalIoctl(prGlueInfo, wlanoidSetAddKey, &rKey, rKey.u4Length, FALSE, FALSE, 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); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_get_key\n"); +#endif + 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 rRemoveKey; + INT_32 i4Rslt = -EINVAL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + UINT_8 ucRoleIdx = 0; + + ASSERT(wiphy); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_del_key\n"); +#endif + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, ndev, &ucRoleIdx) < 0) + return -EINVAL; +#if DBG + DBGLOG(RSN, TRACE, "mtk_p2p_cfg80211_del_key\n"); + if (mac_addr) { + DBGLOG(RSN, TRACE, + "keyIdx = %d pairwise = %d mac = " MACSTR "\n", key_index, pairwise, MAC2STR(mac_addr)); + } else { + DBGLOG(RSN, TRACE, "keyIdx = %d pairwise = %d null mac\n", key_index, pairwise); + } +#endif + + kalMemZero(&rRemoveKey, sizeof(PARAM_REMOVE_KEY_T)); + + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &rRemoveKey.ucBssIdx) != WLAN_STATUS_SUCCESS) + return -EINVAL; + + if (mac_addr) + COPY_MAC_ADDR(rRemoveKey.arBSSID, mac_addr); + rRemoveKey.u4KeyIndex = key_index; + rRemoveKey.u4Length = sizeof(PARAM_REMOVE_KEY_T); + if (mac_addr) { + COPY_MAC_ADDR(rRemoveKey.arBSSID, mac_addr); + rRemoveKey.u4KeyIndex |= BIT(30); + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRemoveKey, &rRemoveKey, rRemoveKey.u4Length, FALSE, FALSE, 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; + PARAM_DEFAULT_KEY_T rDefaultKey; + UINT_8 ucRoleIdx = 0; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + INT_32 i4Rst = -EINVAL; + UINT_32 u4BufLen = 0; + BOOLEAN fgDef = FALSE, fgMgtDef = FALSE; + + ASSERT(wiphy); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_set_default_key\n"); +#endif + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, netdev, &ucRoleIdx) != 0) + return -EINVAL; +#if DBG + DBGLOG(RSN, TRACE, "mtk_p2p_cfg80211_set_default_key\n"); + DBGLOG(RSN, TRACE, "keyIdx = %d unicast = %d multicast = %d\n", key_index, unicast, multicast); +#endif + + + /* For wep case, this set the key for tx */ + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &rDefaultKey.ucBssIdx) != WLAN_STATUS_SUCCESS) + return -EINVAL; + + + rDefaultKey.ucKeyID = key_index; + rDefaultKey.ucUnicast = unicast; + rDefaultKey.ucMulticast = multicast; + if (rDefaultKey.ucUnicast && !rDefaultKey.ucMulticast) + return WLAN_STATUS_SUCCESS; + + if (rDefaultKey.ucUnicast && rDefaultKey.ucMulticast) + fgDef = TRUE; + + if (!rDefaultKey.ucUnicast && rDefaultKey.ucMulticast) + fgMgtDef = TRUE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetDefaultKey, + &rDefaultKey, sizeof(PARAM_DEFAULT_KEY_T), FALSE, FALSE, TRUE, &u4BufLen); + + + if (rStatus == WLAN_STATUS_SUCCESS) + i4Rst = 0; + + + return i4Rst; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for setting the default mgmt key index + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_p2p_cfg80211_set_mgmt_key(struct wiphy *wiphy, struct net_device *dev, u8 key_index) +{ + DBGLOG(RSN, INFO, "mtk_p2p_cfg80211_set_mgmt_key, kid:%d\n", key_index); + + return 0; +} + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, + const u8 *mac, struct station_info *sinfo) +{ + INT_32 i4RetRslt = -EINVAL; + UINT_8 ucRoleIdx = 0; + 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); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_get_station\n"); +#endif + 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)); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, ndev, &ucRoleIdx) != 0) + return -EINVAL; + + prP2pGlueInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + + sinfo->filled = 0; + + /* Get station information. */ + /* 1. Inactive time? */ + p2pFuncGetStationInfo(prGlueInfo->prAdapter, (PUINT_8)mac, &rP2pStaInfo); + + /* Inactive time. */ +#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE + sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME); +#else + sinfo->filled |= STATION_INFO_INACTIVE_TIME; +#endif + sinfo->inactive_time = rP2pStaInfo.u4InactiveTime; + sinfo->generation = prP2pGlueInfo->i4Generation; + + i4RetRslt = 0; + } while (FALSE); + + return i4RetRslt; +} +#else +int mtk_p2p_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, u8 *mac, struct station_info *sinfo) +{ + INT_32 i4RetRslt = -EINVAL; + UINT_8 ucRoleIdx = 0; + 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); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_get_station\n"); +#endif + + 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)); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, ndev, &ucRoleIdx) != 0) + return -EINVAL; + + prP2pGlueInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + + 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; +} +#endif + +int mtk_p2p_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + P_GL_P2P_INFO_T prP2pGlueInfo = (P_GL_P2P_INFO_T) NULL; + P_GL_P2P_DEV_INFO_T prP2pGlueDevInfo = (P_GL_P2P_DEV_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; + UINT_8 ucBssIdx = 0; + BOOLEAN fgIsFullChanScan = FALSE; + + /* [---------Channel---------] [---------SSID---------][---------IE---------] */ + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_scan\n"); +#endif + + do { + if ((wiphy == NULL) || (request == NULL)) + break; + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (wlanIsChipAssert(prGlueInfo->prAdapter)) + break; + + if (!wlanGetHifState(prGlueInfo)) + break; + + prP2pGlueInfo = prGlueInfo->prP2PInfo[0]; + prP2pGlueDevInfo = prGlueInfo->prP2PDevInfo; + + if ((prP2pGlueInfo == NULL) || (prP2pGlueDevInfo == NULL)) { + ASSERT(FALSE); + break; + } + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_scan.\n"); + + if (prP2pGlueDevInfo->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; + } + + prP2pGlueDevInfo->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; + fgIsFullChanScan = TRUE; + DBGLOG(P2P, TRACE, "Channel list exceed the maximun support.\n"); + } + /* TODO: */ + /* Find a way to distinct DEV port scan & ROLE port scan. + */ + ucBssIdx = P2P_DEV_BSS_INDEX; + DBGLOG(P2P, TRACE, "Device Port Scan.\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; + prMsgScanRequest->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prMsgScanRequest->ucBssIdx = ucBssIdx; + + DBGLOG(P2P, INFO, "Requesting channel number:%d.\n", request->n_channels); + + for (u4Idx = 0; u4Idx < request->n_channels; u4Idx++) { + /* Translate Freq from MHz to channel number. */ + prRfChannelInfo = &(prMsgScanRequest->arChannelListInfo[u4Idx]); + prChannel = request->channels[u4Idx]; + + prRfChannelInfo->ucChannelNum = nicFreq2ChannelNum(prChannel->center_freq * 1000); + DBGLOG(P2P, TRACE, + "Scanning Channel:%d, freq: %d\n", prRfChannelInfo->ucChannelNum, + prChannel->center_freq); + switch (prChannel->band) { + case KAL_BAND_2GHZ: + prRfChannelInfo->eBand = BAND_2G4; + break; + case KAL_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; + if (fgIsFullChanScan) { + prMsgScanRequest->u4NumChannel = SCN_P2P_FULL_SCAN_PARAM; + DBGLOG(P2P, INFO, "request->n_channels = SCN_P2P_FULL_SCAN_PARAM\n"); + } + DBGLOG(P2P, TRACE, "Finish channel list.\n"); + + /* SSID */ + prSsid = request->ssids; + prSsidStruct = (P_P2P_SSID_STRUCT_T) prRfChannelInfo; + if (request->n_ssids) { + ASSERT((ULONG) prSsidStruct == (ULONG)&(prMsgScanRequest->arChannelListInfo[u4Idx])); + prMsgScanRequest->prSSID = prSsidStruct; + } + + for (u4Idx = 0; u4Idx < request->n_ssids; u4Idx++) { + COPY_SSID(prSsidStruct->aucSsid, + prSsidStruct->ucSsidLen, request->ssids->ssid, request->ssids->ssid_len); + + prSsidStruct++; + prSsid++; + } + + prMsgScanRequest->i4SsidNum = request->n_ssids; + + DBGLOG(P2P, TRACE, "Finish SSID list:%d.\n", request->n_ssids); + + /* IE BUFFERS */ + prMsgScanRequest->pucIEBuf = (PUINT_8) prSsidStruct; + if (request->ie_len) { + kalMemCopy(prMsgScanRequest->pucIEBuf, request->ie, request->ie_len); + prMsgScanRequest->u4IELen = request->ie_len; + } else { + prMsgScanRequest->u4IELen = 0; + } + + DBGLOG(P2P, TRACE, "Finish IE Buffer.\n"); + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgScanRequest, MSG_SEND_METHOD_BUF); + + /* Backup scan request structure */ + /* The purpose of this backup is due to the kernel free the scan req */ + /* when the wpa supplicant down the iface before down, and it will */ + /* free the original scan request structure */ + /* In this case, the scan resoure could be locked by kernel, and */ + /* driver needs this work around to clear the state */ + kalMemCopy(&(prP2pGlueDevInfo->rBackupScanRequest), + request, sizeof(struct cfg80211_scan_request)); + + 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; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_set_wiphy_params\n"); +#endif + + 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); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_join_ibss\n"); +#endif + + 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); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_leave_ibss\n"); +#endif + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* not implemented yet */ + + return -EINVAL; +} + +int mtk_p2p_cfg80211_set_txpower(struct wiphy *wiphy, + struct wireless_dev *wdev, enum nl80211_tx_power_setting type, int mbm) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_set_txpower\n"); +#endif + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* not implemented yet */ + + return -EINVAL; +} + +int mtk_p2p_cfg80211_get_txpower(struct wiphy *wiphy, struct wireless_dev *wdev, int *dbm) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_get_txpower\n"); +#endif + + 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 *ndev, bool enabled, int timeout) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_POWER_MODE ePowerMode; + PARAM_POWER_MODE_T rPowerMode; + UINT_32 u4Leng; + UINT_8 ucRoleIdx; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_set_power_mgmt\n"); +#endif + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (enabled) + ePowerMode = Param_PowerModeFast_PSP; + else + ePowerMode = Param_PowerModeCAM; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_set_power_mgmt ps=%d.\n", enabled); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, ndev, &ucRoleIdx) != 0) + return -EINVAL; + + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &rPowerMode.ucBssIdx) != WLAN_STATUS_SUCCESS) + return -EINVAL; + + rPowerMode.ePowerMode = ePowerMode; + + /* p2p_set_power_save */ + kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, &rPowerMode, sizeof(rPowerMode), FALSE, FALSE, TRUE, &u4Leng); + + return 0; +} + +/* &&&&&&&&&&&&&&&&&&&&&&&&&& Add for ICS Wi-Fi Direct Support. &&&&&&&&&&&&&&&&&&&&&&& */ +int mtk_p2p_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ap_settings *settings) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_P2P_BEACON_UPDATE_T prP2pBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T) NULL; + P_MSG_P2P_START_AP_T prP2pStartAPMsg = (P_MSG_P2P_START_AP_T) NULL; + PUINT_8 pucBuffer = (PUINT_8) NULL; + UINT_8 ucRoleIdx = 0; + struct cfg80211_chan_def *chandef; + RF_CHANNEL_INFO_T rRfChnlInfo; + + /* RF_CHANNEL_INFO_T rRfChnlInfo; */ +/* P_IE_SSID_T prSsidIE = (P_IE_SSID_T)NULL; */ + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_start_ap\n"); +#endif + + do { + if ((wiphy == NULL) || (settings == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_start_ap.\n"); + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + +#if (CFG_SUPPORT_DFS_MASTER == 1) + /*DFS todo 20161220_DFS*/ + netif_carrier_on(dev); + netif_tx_start_all_queues(dev); +#endif + + chandef = &settings->chandef; + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->fgIsNetDevDetach) { + netif_device_attach(dev); + prGlueInfo->prP2PInfo[ucRoleIdx] + ->fgIsNetDevDetach = FALSE; + } + + if (chandef) { + mtk_p2p_cfg80211func_channel_format_switch(chandef, chandef->chan, &rRfChnlInfo); + + /* Follow the channel info from wifi.cfg prior to hostapd.conf */ + { + P_ADAPTER_T prAdapter = (P_ADAPTER_T) NULL; + P_WIFI_VAR_T prWifiVar = (P_WIFI_VAR_T)NULL; + + prAdapter = prGlueInfo->prAdapter; + prWifiVar = &prAdapter->rWifiVar; + + if ((prWifiVar->ucApChannel != 0) && + (prWifiVar->ucApChnlDefFromCfg != 0) && + (prWifiVar->ucApChannel != rRfChnlInfo.ucChannelNum)) { + rRfChnlInfo.ucChannelNum = prWifiVar->ucApChannel; + rRfChnlInfo.eBand = + (rRfChnlInfo.ucChannelNum <= 14) ? BAND_2G4 : BAND_5G; + /* [TODO][20160829]If we will set SCO by nl80211_channel_type afterward, + * to check if we need to modify SCO by wifi.cfg here + */ + } + } + + p2pFuncSetChannel(prGlueInfo->prAdapter, ucRoleIdx, &rRfChnlInfo); + } else + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_start_ap. !!! no CH def!!!\n"); + + 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 + + settings->beacon.assocresp_ies_len)); + + if (prP2pBcnUpdateMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prP2pBcnUpdateMsg->ucRoleIndex = ucRoleIdx; + prP2pBcnUpdateMsg->rMsgHdr.eMsgId = MID_MNY_P2P_BEACON_UPDATE; + pucBuffer = prP2pBcnUpdateMsg->aucBuffer; + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_start_ap.(role %d)\n", ucRoleIdx); + +#if (CFG_SUPPORT_DFS_MASTER == 1) + if (p2pFuncGetDfsState() == DFS_STATE_DETECTED) { + p2pFuncSetDfsState(DFS_STATE_INACTIVE); + } +#endif + 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 += 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; + kalMemCopy(pucBuffer, settings->beacon.tail, settings->beacon.tail_len); + + prP2pBcnUpdateMsg->u4BcnBodyLen = ucLen; + + pucBuffer += settings->beacon.tail_len; + } else { + prP2pBcnUpdateMsg->u4BcnBodyLen = 0; + + prP2pBcnUpdateMsg->pucBcnBody = NULL; + } + + if ((settings->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) || + (settings->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104)) + prP2pBcnUpdateMsg->fgIsWepCipher = TRUE; + else + prP2pBcnUpdateMsg->fgIsWepCipher = FALSE; + + if (settings->beacon.assocresp_ies_len != 0 && settings->beacon.assocresp_ies != NULL) { + prP2pBcnUpdateMsg->pucAssocRespIE = pucBuffer; + kalMemCopy(pucBuffer, settings->beacon.assocresp_ies, settings->beacon.assocresp_ies_len); + prP2pBcnUpdateMsg->u4AssocRespLen = settings->beacon.assocresp_ies_len; + } else { + prP2pBcnUpdateMsg->u4AssocRespLen = 0; + prP2pBcnUpdateMsg->pucAssocRespIE = 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; + + prP2pStartAPMsg->ucRoleIdx = ucRoleIdx; + + kalP2PSetRole(prGlueInfo, 2, ucRoleIdx); + + 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; */ +/* }; */ +/* ////////////////// */ +} /* mtk_p2p_cfg80211_start_ap */ + +#if (CFG_SUPPORT_DFS_MASTER == 1) + +static int mtk_p2p_cfg80211_start_radar_detection_impl(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_chan_def *chandef, unsigned int cac_time_ms) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_P2P_DFS_CAC_T prP2pDfsCacMsg = (P_MSG_P2P_DFS_CAC_T) NULL; + UINT_8 ucRoleIdx = 0; + RF_CHANNEL_INFO_T rRfChnlInfo; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, + "mtk_p2p_cfg80211_start_radar_detection_impl\n"); +#endif + + do { + if ((wiphy == NULL) || (chandef == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_start_radar_detection.\n"); + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->chandef == NULL) { + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef = (struct cfg80211_chan_def *) + cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_BUF, sizeof(struct cfg80211_chan_def)); + + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->chan = (struct ieee80211_channel *) + cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_BUF, sizeof(struct ieee80211_channel)); + } + + /* Copy chan def to local buffer*/ + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->center_freq1 = chandef->center_freq1; + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->center_freq2 = chandef->center_freq2; + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->width = chandef->width; + memcpy(prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->chan, chandef->chan, + sizeof(struct ieee80211_channel)); + prGlueInfo->prP2PInfo[ucRoleIdx]->cac_time_ms = cac_time_ms; + + + mtk_p2p_cfg80211func_channel_format_switch(chandef, chandef->chan, &rRfChnlInfo); + + p2pFuncSetChannel(prGlueInfo->prAdapter, ucRoleIdx, &rRfChnlInfo); + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_start_radar_detection.(role %d)\n", ucRoleIdx); + + p2pFuncSetDfsState(DFS_STATE_INACTIVE); + + prP2pDfsCacMsg = (P_MSG_P2P_DFS_CAC_T) cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, sizeof(*prP2pDfsCacMsg)); + + if (prP2pDfsCacMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prP2pDfsCacMsg->rMsgHdr.eMsgId = MID_MNY_P2P_DFS_CAC; + + switch (chandef->width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + case NL80211_CHAN_WIDTH_40: + prP2pDfsCacMsg->eChannelWidth = CW_20_40MHZ; + break; + + case NL80211_CHAN_WIDTH_80: + prP2pDfsCacMsg->eChannelWidth = CW_80MHZ; + break; + + case NL80211_CHAN_WIDTH_80P80: + prP2pDfsCacMsg->eChannelWidth = CW_80P80MHZ; + break; + + default: + DBGLOG(P2P, ERROR, + "mtk_p2p_cfg80211_start_radar_detection. !!!Bandwidth do not support!!!\n"); + ASSERT(FALSE); + break; + } + + prP2pDfsCacMsg->ucRoleIdx = ucRoleIdx; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prP2pDfsCacMsg, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + + } while (FALSE); + + return i4Rslt; +} + +#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_start_radar_detection(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_chan_def *chandef, unsigned int cac_time_ms) +{ + return mtk_p2p_cfg80211_start_radar_detection_impl( + wiphy, dev, chandef, cac_time_ms); +} +#else +int mtk_p2p_cfg80211_start_radar_detection(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_chan_def *chandef) +{ + return mtk_p2p_cfg80211_start_radar_detection_impl( + wiphy, dev, chandef, IEEE80211_DFS_MIN_CAC_TIME_MS); +} +#endif + +#if KERNEL_VERSION(3, 13, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_csa_settings *params) +{ + 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_SET_NEW_CHANNEL_T prP2pSetNewChannelMsg = (P_MSG_P2P_SET_NEW_CHANNEL_T) NULL; + PUINT_8 pucBuffer = (PUINT_8) NULL; + UINT_8 ucRoleIdx = 0; + RF_CHANNEL_INFO_T rRfChnlInfo; + P_BSS_INFO_T prBssInfo; + UINT_8 ucBssIndex; + UINT_32 u4Len; + + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_channel_switch\n"); +#endif + + do { + if ((wiphy == NULL) || (params == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_channel_switch.\n"); + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->chandef == NULL) { + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef = (struct cfg80211_chan_def *) + cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_BUF, sizeof(struct cfg80211_chan_def)); + + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->chan = (struct ieee80211_channel *) + cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_BUF, sizeof(struct ieee80211_channel)); + } + /* Copy chan def to local buffer*/ + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->center_freq1 = params->chandef.center_freq1; + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->center_freq2 = params->chandef.center_freq2; + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->width = params->chandef.width; + memcpy(prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->chan, params->chandef.chan, + sizeof(struct ieee80211_channel)); + + mtk_p2p_cfg80211func_channel_format_switch(¶ms->chandef, + params->chandef.chan, &rRfChnlInfo); + + p2pFuncSetChannel(prGlueInfo->prAdapter, ucRoleIdx, &rRfChnlInfo); + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_channel_switch.(role %d)\n", ucRoleIdx); + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->chan-> + dfs_state == NL80211_DFS_AVAILABLE +#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE + && prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->chan-> + dfs_cac_ms != 0 +#endif + ) + p2pFuncSetDfsState(DFS_STATE_ACTIVE); + else + p2pFuncSetDfsState(DFS_STATE_INACTIVE); + + /* Set CSA IE parameters */ + prGlueInfo->prAdapter->rWifiVar.fgCsaInProgress = TRUE; + prGlueInfo->prAdapter->rWifiVar.ucChannelSwitchMode = 1; + prGlueInfo->prAdapter->rWifiVar.ucNewChannelNumber = + nicFreq2ChannelNum(params->chandef.chan->center_freq * 1000); + prGlueInfo->prAdapter->rWifiVar.ucChannelSwitchCount = params->count; + + /* Set new channel parameters */ + prP2pSetNewChannelMsg = (P_MSG_P2P_SET_NEW_CHANNEL_T) cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, sizeof(*prP2pSetNewChannelMsg)); + + if (prP2pSetNewChannelMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prP2pSetNewChannelMsg->rMsgHdr.eMsgId = MID_MNY_P2P_SET_NEW_CHANNEL; + + switch (params->chandef.width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + case NL80211_CHAN_WIDTH_40: + prP2pSetNewChannelMsg->eChannelWidth = CW_20_40MHZ; + break; + + case NL80211_CHAN_WIDTH_80: + prP2pSetNewChannelMsg->eChannelWidth = CW_80MHZ; + break; + + case NL80211_CHAN_WIDTH_80P80: + prP2pSetNewChannelMsg->eChannelWidth = CW_80P80MHZ; + break; + + default: + DBGLOG(P2P, ERROR, + "mtk_p2p_cfg80211_channel_switch. !!!Bandwidth do not support!!!\n"); + ASSERT(FALSE); + break; + } + + prP2pSetNewChannelMsg->ucRoleIdx = ucRoleIdx; + + for (ucBssIndex = 0; ucBssIndex < BSS_INFO_NUM; ucBssIndex++) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, ucBssIndex); + + if (prBssInfo && prBssInfo->fgIsDfsActive) { + prP2pSetNewChannelMsg->ucBssIndex = ucBssIndex; + break; + } + } + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prP2pSetNewChannelMsg, MSG_SEND_METHOD_BUF); + + /* Update beacon */ + if ((params->beacon_csa.head_len != 0) || (params->beacon_csa.tail_len != 0)) { + u4Len = sizeof(MSG_P2P_BEACON_UPDATE_T) + + params->beacon_csa.head_len + params->beacon_csa.tail_len; + prP2pBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T) cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, u4Len); + + if (prP2pBcnUpdateMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + kalMemZero(prP2pBcnUpdateMsg, u4Len); + + prP2pBcnUpdateMsg->ucRoleIndex = ucRoleIdx; + prP2pBcnUpdateMsg->rMsgHdr.eMsgId = MID_MNY_P2P_BEACON_UPDATE; + pucBuffer = prP2pBcnUpdateMsg->aucBuffer; + + if (params->beacon_csa.head_len != 0) { + kalMemCopy(pucBuffer, params->beacon_csa.head, params->beacon_csa.head_len); + + prP2pBcnUpdateMsg->u4BcnHdrLen = params->beacon_csa.head_len; + + prP2pBcnUpdateMsg->pucBcnHdr = pucBuffer; + + pucBuffer = (PUINT_8) ((ULONG) pucBuffer + (ULONG) params->beacon_csa.head_len); + } else { + prP2pBcnUpdateMsg->u4BcnHdrLen = 0; + + prP2pBcnUpdateMsg->pucBcnHdr = NULL; + } + + if (params->beacon_csa.tail_len != 0) { + UINT_8 ucLen = params->beacon_csa.tail_len; + + prP2pBcnUpdateMsg->pucBcnBody = pucBuffer; + kalMemCopy(pucBuffer, params->beacon_csa.tail, params->beacon_csa.tail_len); + + prP2pBcnUpdateMsg->u4BcnBodyLen = ucLen; + } else { + prP2pBcnUpdateMsg->u4BcnBodyLen = 0; + prP2pBcnUpdateMsg->pucBcnBody = NULL; + } + + kalP2PSetRole(prGlueInfo, 2, ucRoleIdx); + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, (P_MSG_HDR_T) prP2pBcnUpdateMsg, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; /* Return Success */ + } + + } while (FALSE); + + return i4Rslt; +} +#endif +#endif + +#if 0 +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; +}; +#endif + +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; + UINT_8 ucRoleIdx = 0; + UINT_32 u4Len = 0; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_change_beacon\n"); +#endif + + do { + if ((wiphy == NULL) || (info == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_change_beacon.\n"); + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + + if ((info->head_len != 0) || (info->tail_len != 0)) { + u4Len = sizeof(MSG_P2P_BEACON_UPDATE_T) + + info->head_len + info->tail_len + + info->assocresp_ies_len; + + prP2pBcnUpdateMsg = + (P_MSG_P2P_BEACON_UPDATE_T) cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, u4Len); + + if (prP2pBcnUpdateMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + kalMemZero(prP2pBcnUpdateMsg, u4Len); + + prP2pBcnUpdateMsg->ucRoleIndex = ucRoleIdx; + 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 += info->head_len; + } else { + prP2pBcnUpdateMsg->u4BcnHdrLen = 0; + + prP2pBcnUpdateMsg->pucBcnHdr = NULL; + } + + if (info->tail_len != 0) { + UINT_8 ucLen = info->tail_len; + + prP2pBcnUpdateMsg->pucBcnBody = pucBuffer; + kalMemCopy(pucBuffer, info->tail, info->tail_len); + + prP2pBcnUpdateMsg->u4BcnBodyLen = ucLen; + + pucBuffer += info->tail_len; + } else { + prP2pBcnUpdateMsg->u4BcnBodyLen = 0; + prP2pBcnUpdateMsg->pucBcnBody = NULL; + } + + if (info->assocresp_ies_len != 0 && info->assocresp_ies != NULL) { + + prP2pBcnUpdateMsg->pucAssocRespIE = pucBuffer; + kalMemCopy(pucBuffer, info->assocresp_ies, info->assocresp_ies_len); + prP2pBcnUpdateMsg->u4AssocRespLen = info->assocresp_ies_len; + } else { + prP2pBcnUpdateMsg->u4AssocRespLen = 0; + prP2pBcnUpdateMsg->pucAssocRespIE = NULL; + } + + kalP2PSetRole(prGlueInfo, 2, ucRoleIdx); + + mboxSendMsg(prGlueInfo->prAdapter, + MBOX_ID_0, (P_MSG_HDR_T) prP2pBcnUpdateMsg, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; /* Return Success */ + } + + /* TODO: Probe Rsp, Assoc Rsp, Beacon IE update. */ + +/* ////////////////////////// */ +/** + * struct cfg80211_beacon_data - beacon data + * @head: head portion of beacon (before TIM IE) + * or %NULL if not changed + * @tail: tail portion of beacon (after TIM IE) + * or %NULL if not changed + * @head_len: length of @head + * @tail_len: length of @tail + * @beacon_ies: extra information element(s) to add into Beacon frames or %NULL + * @beacon_ies_len: length of beacon_ies in octets + * @proberesp_ies: extra information element(s) to add into Probe Response + * frames or %NULL + * @proberesp_ies_len: length of proberesp_ies in octets + * @assocresp_ies: extra information element(s) to add into (Re)Association + * Response frames or %NULL + * @assocresp_ies_len: length of assocresp_ies in octets + * @probe_resp_len: length of probe response template (@probe_resp) + * @probe_resp: probe response template (AP mode only) + */ +/* struct cfg80211_beacon_data { */ +/* const u8 *head, *tail; */ +/* const u8 *beacon_ies; */ +/* const u8 *proberesp_ies; */ +/* const u8 *assocresp_ies; */ +/* const u8 *probe_resp; */ + +/* size_t head_len, tail_len; */ +/* size_t beacon_ies_len; */ +/* size_t proberesp_ies_len; */ +/* size_t assocresp_ies_len; */ +/* size_t probe_resp_len; */ +/* }; */ + +/* ////////////////////////// */ + + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_change_beacon */ + +int mtk_p2p_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_P2P_SWITCH_OP_MODE_T prP2pSwitchMode = (P_MSG_P2P_SWITCH_OP_MODE_T) NULL; + UINT_8 ucRoleIdx = 0; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_stop_ap\n"); +#endif + + do { + if (wiphy == NULL) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_stop_ap.\n"); + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + +#if (CFG_SUPPORT_DFS_MASTER == 1) + if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) { + netif_carrier_off(dev); + netif_tx_stop_all_queues(dev); + } +#endif + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + /* 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; + prP2pSwitchMode->ucRoleIdx = ucRoleIdx; + + 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) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + + ASSERT(wiphy); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_deauth\n"); +#endif + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* not implemented yet */ + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_deauth.\n"); + + return -EINVAL; +} /* mtk_p2p_cfg80211_deauth */ + +/* TODO: */ +int mtk_p2p_cfg80211_disassoc(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_disassoc_request *req) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + + ASSERT(wiphy); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_disassoc\n"); +#endif + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_disassoc.\n"); + + /* not implemented yet */ + + return -EINVAL; +} /* mtk_p2p_cfg80211_disassoc */ + +int mtk_p2p_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, unsigned int duration, u64 *cookie) +{ + INT_32 i4Rslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + P_GL_P2P_DEV_INFO_T prGlueP2pDevInfo = (P_GL_P2P_DEV_INFO_T) NULL; + P_MSG_P2P_CHNL_REQUEST_T prMsgChnlReq = (P_MSG_P2P_CHNL_REQUEST_T) NULL; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_remain_on_channel\n"); +#endif + + DBGLOG(P2P, STATE, "mtk_p2p_cfg80211_remain_on_channel\n"); + + do { + if ((wiphy == NULL) || + /* (dev == NULL) || */ + (chan == NULL) || (cookie == NULL)) { + break; + } + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (!wlanGetHifState(prGlueInfo)) + break; + + prGlueP2pDevInfo = prGlueInfo->prP2PDevInfo; + + *cookie = prGlueP2pDevInfo->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:%d\n", (INT_32) *cookie); + + prMsgChnlReq->rMsgHdr.eMsgId = MID_MNY_P2P_CHNL_REQ; + prMsgChnlReq->u8Cookie = *cookie; + prMsgChnlReq->u4Duration = duration; + prMsgChnlReq->eChnlReqType = CH_REQ_TYPE_P2P_LISTEN; + + mtk_p2p_cfg80211func_channel_format_switch(NULL, chan, + &prMsgChnlReq->rChannelInfo); + mtk_p2p_cfg80211func_channel_sco_switch(NL80211_CHAN_NO_HT, &prMsgChnlReq->eChnlSco); + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChnlReq, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} + +/* mtk_p2p_cfg80211_remain_on_channel */ + +int mtk_p2p_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie) +{ + INT_32 i4Rslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + P_MSG_P2P_CHNL_ABORT_T prMsgChnlAbort = (P_MSG_P2P_CHNL_ABORT_T) NULL; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, + "mtk_p2p_cfg80211_cancel_remain_on_channel\n"); +#endif + + do { + if (wiphy == NULL) + break; + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + prGlueP2pInfo = prGlueInfo->prP2PInfo[0]; + + 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%d\n", (INT_32) cookie); + + 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 */ +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + INT_32 i4Rslt = -EINVAL; + 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; + PUINT_64 pu8GlCookie = (PUINT_64) NULL; + UINT_8 ucRoleIdx = 0, ucBssIdx = 0; + struct net_device *dev = NULL; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_mgmt_tx\n"); +#endif + + do { + if ((wiphy == NULL) || (wdev == NULL) || (params == 0) || (cookie == NULL)) + break; + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + /* The owner of this function please check following line*/ + prGlueP2pInfo = (P_GL_P2P_INFO_T) prGlueInfo->prP2PInfo; + + dev = wdev->netdev; + + /* The owner of this function please check following line*/ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) { + /* Device Interface. */ + ucBssIdx = P2P_DEV_BSS_INDEX; + } else { + ASSERT(ucRoleIdx < KAL_P2P_NUM); + /* Role Interface. */ + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &ucBssIdx) != WLAN_STATUS_SUCCESS) { + /* Can't find BSS index. */ + break; + } + } + /* The owner of this function please check following line*/ + *cookie = prGlueInfo->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; + } + + if (params->offchan) { + DBGLOG(P2P, TRACE, " Off channel TRUE\n"); + prMsgTxReq->fgIsOffChannel = TRUE; + + mtk_p2p_cfg80211func_channel_format_switch(NULL, params->chan, + &prMsgTxReq->rChannelInfo); + mtk_p2p_cfg80211func_channel_sco_switch(NL80211_CHAN_NO_HT, &prMsgTxReq->eChnlExt); + } else { + prMsgTxReq->fgIsOffChannel = FALSE; + } + + if (params->no_cck) + prMsgTxReq->fgNoneCckRate = TRUE; + else + prMsgTxReq->fgNoneCckRate = FALSE; + + if (params->dont_wait_for_ack) + prMsgTxReq->fgIsWaitRsp = FALSE; + else + prMsgTxReq->fgIsWaitRsp = TRUE; + prMgmtFrame = + cnmMgtPktAlloc(prGlueInfo->prAdapter, + (INT_32) (params->len + sizeof(UINT_64) + MAC_TX_RESERVED_FIELD)); + prMsgTxReq->prMgmtMsduInfo = prMgmtFrame; + if (prMsgTxReq->prMgmtMsduInfo == NULL) { + /* ASSERT(FALSE); */ + i4Rslt = -ENOMEM; + break; + } + + prMsgTxReq->u8Cookie = *cookie; + prMsgTxReq->rMsgHdr.eMsgId = MID_MNY_P2P_MGMT_TX; + prMsgTxReq->ucBssIdx = ucBssIdx; + + pucFrameBuf = (PUINT_8) ((ULONG) prMgmtFrame->prPacket + MAC_TX_RESERVED_FIELD); + + pu8GlCookie = (PUINT_64) ((ULONG) prMgmtFrame->prPacket + (ULONG)params->len + MAC_TX_RESERVED_FIELD); + + kalMemCopy(pucFrameBuf, params->buf, params->len); + + *pu8GlCookie = *cookie; + + prMgmtFrame->u2FrameLength = params->len; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgTxReq, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + if ((i4Rslt != 0) && (prMsgTxReq != NULL)) { + if (prMsgTxReq->prMgmtMsduInfo != NULL) + cnmMgtPktFree(prGlueInfo->prAdapter, prMsgTxReq->prMgmtMsduInfo); + + cnmMemFree(prGlueInfo->prAdapter, prMsgTxReq); + } + + return i4Rslt; +} /* mtk_p2p_cfg80211_mgmt_tx */ +#else +int mtk_p2p_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, bool offchan, + unsigned int wait, const u8 *buf, size_t len, + bool no_cck, bool dont_wait_for_ack, u64 *cookie) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + P_GL_P2P_DEV_INFO_T prGlueP2pDevInfo = (P_GL_P2P_DEV_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; + PUINT_64 pu8GlCookie = (PUINT_64) NULL; + UINT_8 ucRoleIdx = 0, ucBssIdx = 0; + struct net_device *dev = NULL; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_mgmt_tx\n"); +#endif + + do { + if ((wiphy == NULL) || (buf == NULL) || (len == 0) || + /* (dev == NULL) || */ + (cookie == NULL)) { + break; + } + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + prGlueP2pDevInfo = prGlueInfo->prP2PDevInfo; + + dev = wdev->netdev; + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) { + /* Device Interface. */ + ucBssIdx = P2P_DEV_BSS_INDEX; + } else { + ASSERT(ucRoleIdx < KAL_P2P_NUM); + /* Role Interface. */ + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &ucBssIdx) < 0) { + /* Can't find BSS index. */ + break; + } + } + + *cookie = prGlueP2pDevInfo->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; + } + + if (offchan) { + DBGLOG(P2P, TRACE, " Off channel TRUE\n"); + prMsgTxReq->fgIsOffChannel = TRUE; + + mtk_p2p_cfg80211func_channel_format_switch(NULL, chan, + &prMsgTxReq->rChannelInfo); + mtk_p2p_cfg80211func_channel_sco_switch(NL80211_CHAN_NO_HT, &prMsgTxReq->eChnlExt); + } else { + prMsgTxReq->fgIsOffChannel = FALSE; + } + + if (no_cck) + prMsgTxReq->fgNoneCckRate = TRUE; + else + prMsgTxReq->fgNoneCckRate = FALSE; + + if (dont_wait_for_ack) + prMsgTxReq->fgIsWaitRsp = FALSE; + else + prMsgTxReq->fgIsWaitRsp = TRUE; + prMgmtFrame = + cnmMgtPktAlloc(prGlueInfo->prAdapter, (UINT_32) (len + sizeof(UINT_64) + MAC_TX_RESERVED_FIELD)); + prMsgTxReq->prMgmtMsduInfo = prMgmtFrame; + if (prMsgTxReq->prMgmtMsduInfo == NULL) { + /* ASSERT(FALSE); */ + i4Rslt = -ENOMEM; + break; + } + + prMsgTxReq->u8Cookie = *cookie; + prMsgTxReq->rMsgHdr.eMsgId = MID_MNY_P2P_MGMT_TX; + prMsgTxReq->ucBssIdx = ucBssIdx; + + pucFrameBuf = (PUINT_8) ((ULONG) prMgmtFrame->prPacket + MAC_TX_RESERVED_FIELD); + + pu8GlCookie = (PUINT_64) ((ULONG) prMgmtFrame->prPacket + (ULONG) len + MAC_TX_RESERVED_FIELD); + + kalMemCopy(pucFrameBuf, buf, len); + + *pu8GlCookie = *cookie; + + 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 */ +#endif + +int mtk_p2p_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie) +{ + INT_32 i4Rslt = -EINVAL; + + return i4Rslt; +} /* mtk_p2p_cfg80211_mgmt_tx_cancel_wait */ + +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); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_change_bss\n"); +#endif + + 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 */ + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +#if KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE +static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, struct station_del_parameters *params) +{ + const u8 *mac = params->mac ? params->mac : bcast_addr; + 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; + UINT_8 ucRoleIdx = 0; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_del_station\n"); +#endif + + 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)); + + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + /* 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; + prDisconnectMsg->ucRoleIdx = ucRoleIdx; + COPY_MAC_ADDR(prDisconnectMsg->aucTargetID, mac); + prDisconnectMsg->u2ReasonCode = REASON_CODE_UNSPECIFIED; + prDisconnectMsg->fgSendDeauth = TRUE; + + + 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 */ +#else +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, const u8 *mac) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_P2P_CONNECTION_ABORT_T prDisconnectMsg = (P_MSG_P2P_CONNECTION_ABORT_T) NULL; + UINT_8 aucBcMac[] = BC_MAC_ADDR; + UINT_8 ucRoleIdx = 0; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_del_station\n"); +#endif + + 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)); + + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + /* 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; + prDisconnectMsg->ucRoleIdx = ucRoleIdx; + COPY_MAC_ADDR(prDisconnectMsg->aucTargetID, mac); + prDisconnectMsg->u2ReasonCode = REASON_CODE_UNSPECIFIED; + prDisconnectMsg->fgSendDeauth = TRUE; + + + 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 */ +#endif +#else +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; + UINT_8 ucRoleIdx = 0; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_del_station\n"); +#endif + + 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)); + + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + /* 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; + prDisconnectMsg->ucRoleIdx = ucRoleIdx; + COPY_MAC_ADDR(prDisconnectMsg->aucTargetID, mac); + prDisconnectMsg->u2ReasonCode = REASON_CODE_UNSPECIFIED; + prDisconnectMsg->fgSendDeauth = TRUE; + + + 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 */ +#endif + +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; + UINT_8 ucRoleIdx = 0; +#if CFG_SUPPORT_REPLAY_DETECTION + UINT_8 ucBssIndex = 0; + P_BSS_INFO_T prBssInfo = NULL; + struct SEC_DETECT_REPLAY_INFO *prDetRplyInfo = NULL; +#endif + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_connect\n"); +#endif + + do { + if ((wiphy == NULL) || (dev == NULL) || (sme == NULL)) + break; + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_connect.\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + + 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; + prConnReqMsg->ucRoleIdx = ucRoleIdx; + + COPY_SSID(prConnReqMsg->rSsid.aucSsid, prConnReqMsg->rSsid.ucSsidLen, sme->ssid, sme->ssid_len); + + COPY_MAC_ADDR(prConnReqMsg->aucBssid, sme->bssid); + COPY_MAC_ADDR(prConnReqMsg->aucSrcMacAddr, dev->dev_addr); + + DBGLOG(P2P, TRACE, "Assoc Req IE Buffer Length:%zu\n", + sme->ie_len); + kalMemCopy(prConnReqMsg->aucIEBuf, sme->ie, sme->ie_len); + prConnReqMsg->u4IELen = sme->ie_len; + + kalP2PSetCipher(prGlueInfo, IW_AUTH_CIPHER_NONE, ucRoleIdx); + + if (sme->crypto.n_ciphers_pairwise) { + switch (sme->crypto.ciphers_pairwise[0]) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + kalP2PSetCipher(prGlueInfo, IW_AUTH_CIPHER_WEP40, ucRoleIdx); + break; + case WLAN_CIPHER_SUITE_TKIP: + kalP2PSetCipher(prGlueInfo, IW_AUTH_CIPHER_TKIP, ucRoleIdx); + break; + case WLAN_CIPHER_SUITE_CCMP: + case WLAN_CIPHER_SUITE_AES_CMAC: + kalP2PSetCipher(prGlueInfo, IW_AUTH_CIPHER_CCMP, ucRoleIdx); + break; + default: + cnmMemFree(prGlueInfo->prAdapter, prConnReqMsg); + DBGLOG(REQ, WARN, "invalid cipher pairwise (%d)\n", sme->crypto.ciphers_pairwise[0]); + return -EINVAL; + } + } + + mtk_p2p_cfg80211func_channel_format_switch(NULL, sme->channel, + &prConnReqMsg->rChannelInfo); + mtk_p2p_cfg80211func_channel_sco_switch(NL80211_CHAN_NO_HT, &prConnReqMsg->eChnlSco); + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prConnReqMsg, MSG_SEND_METHOD_BUF); + +#if CFG_SUPPORT_REPLAY_DETECTION + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &ucBssIndex) != WLAN_STATUS_SUCCESS) + return -EINVAL; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, ucBssIndex); + ASSERT(prBssInfo); + prDetRplyInfo = &prBssInfo->rDetRplyInfo; + kalMemZero(prDetRplyInfo, sizeof(struct SEC_DETECT_REPLAY_INFO)); +#endif + + 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; + UINT_8 ucRoleIdx = 0; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_disconnect\n"); +#endif + + do { + if ((wiphy == NULL) || (dev == NULL)) + break; + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_disconnect.\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; +/* 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->ucRoleIdx = ucRoleIdx; + prDisconnMsg->u2ReasonCode = reason_code; + prDisconnMsg->fgSendDeauth = TRUE; + COPY_MAC_ADDR(prDisconnMsg->aucTargetID, aucBCAddr); + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prDisconnMsg, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_disconnect */ + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +int +mtk_p2p_cfg80211_change_iface(IN struct wiphy *wiphy, + IN struct net_device *ndev, + IN enum nl80211_iftype type, + IN struct vif_params *params) +#else +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) +#endif +{ + 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; + UINT_8 ucRoleIdx = 0; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_change_iface\n"); +#endif + + 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)); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, ndev, &ucRoleIdx) != 0) { + DBGLOG(P2P, TRACE, "Device Interface no need to change interface type.\n"); + return 0; + } + /* 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; + prSwitchModeMsg->ucRoleIdx = ucRoleIdx; + + switch (type) { + case NL80211_IFTYPE_P2P_CLIENT: + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_P2P_CLIENT.\n"); + prSwitchModeMsg->eOpMode = OP_MODE_INFRASTRUCTURE; + kalP2PSetRole(prGlueInfo, 1, ucRoleIdx); + break; + case NL80211_IFTYPE_STATION: + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_STATION.\n"); + prSwitchModeMsg->eOpMode = OP_MODE_INFRASTRUCTURE; + kalP2PSetRole(prGlueInfo, 1, ucRoleIdx); + break; + case NL80211_IFTYPE_AP: + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_AP.\n"); + prSwitchModeMsg->eOpMode = OP_MODE_ACCESS_POINT; + kalP2PSetRole(prGlueInfo, 2, ucRoleIdx); + break; + case NL80211_IFTYPE_P2P_GO: + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_P2P_GO not AP.\n"); + prSwitchModeMsg->eOpMode = OP_MODE_ACCESS_POINT; + kalP2PSetRole(prGlueInfo, 2, ucRoleIdx); + break; + default: + DBGLOG(P2P, TRACE, "Other type :%d .\n", type); + prSwitchModeMsg->eOpMode = OP_MODE_P2P_DEVICE; + kalP2PSetRole(prGlueInfo, 0, ucRoleIdx); + break; + } + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prSwitchModeMsg, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + + } while (FALSE); + + return i4Rslt; + +} /* mtk_p2p_cfg80211_change_iface */ + +int mtk_p2p_cfg80211_set_channel(IN struct wiphy *wiphy, struct cfg80211_chan_def *chandef) +{ + INT_32 i4Rslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + struct net_device *dev = (struct net_device *) NULL; + RF_CHANNEL_INFO_T rRfChnlInfo; + UINT_8 ucRoleIdx = 0; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_set_channel\n"); +#endif + + if ((wiphy == NULL) || (chandef == NULL)) + return i4Rslt; + + dev = (struct net_device *) wiphy_dev(wiphy); + + do { + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_set_channel.\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + mtk_p2p_cfg80211func_channel_format_switch(chandef, chandef->chan, &rRfChnlInfo); + + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + break; + + p2pFuncSetChannel(prGlueInfo->prAdapter, ucRoleIdx, &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; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_set_bitrate_mask\n"); +#endif + + do { + if ((wiphy == NULL) || (dev == NULL) || (mask == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_set_bitrate_mask\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* TODO: Set bitrate mask of the peer? */ + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_set_bitrate_mask */ + +void mtk_p2p_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, + struct wireless_dev *wdev, IN u16 frame_type, IN bool reg) +{ +#if 0 + P_MSG_P2P_MGMT_FRAME_REGISTER_T prMgmtFrameRegister = (P_MSG_P2P_MGMT_FRAME_REGISTER_T) NULL; +#endif + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + UINT_8 ucRoleIdx = 0; + PUINT_32 pu4P2pPacketFilter = NULL; + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState() || g_u4HaltFlag) { + DBGLOG(INIT, WARN, "wlan is halt, skip reg callback"); + return; + } + rst_data.entry_conut++; + DBGLOG(INIT, TRACE, "entry_conut = %d\n", rst_data.entry_conut); +#else + if (g_u4HaltFlag) { + DBGLOG(RLM, WARN, "wlan is halt, skip reg callback\n"); + return; + } +#endif + + do { + if ((wiphy == NULL) || (wdev == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_mgmt_frame_register\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* since p2p device share the aprRoleHandler so needs to check DevHandler 1st */ + if (prGlueInfo->prP2PInfo[0]->prDevHandler == wdev->netdev) { + /* P2P device*/ + pu4P2pPacketFilter = &prGlueInfo->prP2PDevInfo->u4OsMgmtFrameFilter; + } else { + if (mtk_Netdev_To_RoleIdx(prGlueInfo, wdev->netdev, &ucRoleIdx) < 0) { + /* P2P device*/ + DBGLOG(P2P, WARN, "mtk_p2p_cfg80211_mgmt_frame_register wireless dev match fail!\n"); + pu4P2pPacketFilter = &prGlueInfo->prP2PDevInfo->u4OsMgmtFrameFilter; + } else { + /* Non P2P device*/ + ASSERT(ucRoleIdx < KAL_P2P_NUM); + DBGLOG(P2P, TRACE, "Open packet filer RoleIdx %u\n", ucRoleIdx); + prP2pRoleFsmInfo = prGlueInfo->prAdapter->rWifiVar.aprP2pRoleFsmInfo[ucRoleIdx]; + pu4P2pPacketFilter = &prP2pRoleFsmInfo->u4P2pPacketFilter; + } + } + switch (frame_type) { + case MAC_FRAME_PROBE_REQ: + if (reg) { + *pu4P2pPacketFilter |= PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(P2P, TRACE, "Open packet filer probe request\n"); + } else { + *pu4P2pPacketFilter &= ~PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(P2P, TRACE, "Close packet filer probe request\n"); + } + break; + case MAC_FRAME_ACTION: + if (reg) { + *pu4P2pPacketFilter |= PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(P2P, TRACE, "Open packet filer action frame.\n"); + } else { + *pu4P2pPacketFilter &= ~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; + } + + set_bit(GLUE_FLAG_FRAME_FILTER_BIT, &prGlueInfo->ulFlag); + + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + + if (in_interrupt()) + DBGLOG(P2P, TRACE, "It is in interrupt level\n"); +#if 0 + + prMgmtFrameRegister = + (P_MSG_P2P_MGMT_FRAME_REGISTER_T) cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, sizeof(MSG_P2P_MGMT_FRAME_REGISTER_T)); + + if (prMgmtFrameRegister == NULL) { + ASSERT(FALSE); + break; + } + + prMgmtFrameRegister->rMsgHdr.eMsgId = MID_MNY_P2P_MGMT_FRAME_REGISTER; + + prMgmtFrameRegister->u2FrameType = frame_type; + prMgmtFrameRegister->fgIsRegister = reg; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMgmtFrameRegister, MSG_SEND_METHOD_BUF); + +#endif + + } while (FALSE); + +#if CFG_CHIP_RESET_SUPPORT + rst_data.entry_conut--; + DBGLOG(INIT, TRACE, "entry_conut = %d\n", rst_data.entry_conut); +#endif + +} /* mtk_p2p_cfg80211_mgmt_frame_register */ + +#ifdef CONFIG_NL80211_TESTMODE + +#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_testmode_cmd(struct wiphy *wiphy, + struct wireless_dev *wdev, void *data, + int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_TEST_PARAMS prParams = (P_NL80211_DRIVER_TEST_PARAMS) NULL; + INT_32 i4Status = -EINVAL; + + ASSERT(wiphy); + ASSERT(wdev); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_testmode_cmd\n"); +#endif + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_testmode_cmd\n"); + + if (data && len) { + prParams = (P_NL80211_DRIVER_TEST_PARAMS) data; + } else { + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_testmode_cmd, data is NULL\n"); + return i4Status; + } + if (prParams->index >> 24 == 0x01) { + /* New version */ + prParams->index = prParams->index & ~BITS(24, 31); + } else { + /* Old version */ + mtk_p2p_cfg80211_testmode_p2p_sigma_pre_cmd(wiphy, data, len); + i4Status = 0; + return i4Status; + } + + /* Clear the version byte */ + prParams->index = prParams->index & ~BITS(24, 31); + + if (prParams) { + switch (prParams->index) { + case 1: /* P2P Simga */ +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION + { + P_NL80211_DRIVER_SW_CMD_PARAMS prParamsCmd; + + prParamsCmd = (P_NL80211_DRIVER_SW_CMD_PARAMS) data; + + if ((prParamsCmd->adr & 0xffff0000) == 0xffff0000) { + i4Status = mtk_p2p_cfg80211_testmode_sw_cmd(wiphy, data, len); + break; + } + } +#endif + i4Status = mtk_p2p_cfg80211_testmode_p2p_sigma_cmd(wiphy, data, len); + break; + case 2: /* WFD */ +#if CFG_SUPPORT_WFD + /* use normal driver command wifi_display */ + /* i4Status = mtk_p2p_cfg80211_testmode_wfd_update_cmd(wiphy, data, len); */ +#endif + break; + case 3: /* Hotspot Client Management */ +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + i4Status = mtk_p2p_cfg80211_testmode_hotspot_block_list_cmd(wiphy, data, len); +#endif + break; + case 0x10: + i4Status = mtk_cfg80211_testmode_get_sta_statistics(wiphy, data, len, prGlueInfo); + break; +#if CFG_SUPPORT_NFC_BEAM_PLUS + case 0x11: /*NFC Beam + Indication */ + if (data && len) { + P_NL80211_DRIVER_SET_NFC_PARAMS prParams = (P_NL80211_DRIVER_SET_NFC_PARAMS) data; + + DBGLOG(P2P, INFO, "NFC: BEAM[%d]\n", prParams->NFC_Enable); + } + break; + case 0x12: /*NFC Beam + Indication */ + DBGLOG(P2P, INFO, "NFC: Polling\n"); + i4Status = mtk_cfg80211_testmode_get_scan_done(wiphy, data, len, prGlueInfo); + break; +#endif +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + case 0x30: + i4Status = mtk_p2p_cfg80211_testmode_get_best_channel(wiphy, data, len); + break; +#endif +#if GO_STA_SCC + case 0x50: + 4Status = mtk_p2p_cfg80211_go_channel_switch( + wiphy, wdev, data, len); + break +#endif + + default: + i4Status = -EINVAL; + break; + } + } + + return i4Status; + +} +#else +int mtk_p2p_cfg80211_testmode_cmd(struct wiphy *wiphy, void *data, int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_TEST_PARAMS prParams = (P_NL80211_DRIVER_TEST_PARAMS) NULL; + INT_32 i4Status = -EINVAL; + + ASSERT(wiphy); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_testmode_cmd\n"); +#endif + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_testmode_cmd\n"); + + if (data && len) { + prParams = (P_NL80211_DRIVER_TEST_PARAMS) data; + } else { + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_testmode_cmd, data is NULL\n"); + return i4Status; + } + if (prParams->index >> 24 == 0x01) { + /* New version */ + prParams->index = prParams->index & ~BITS(24, 31); + } else { + /* Old version */ + mtk_p2p_cfg80211_testmode_p2p_sigma_pre_cmd(wiphy, data, len); + i4Status = 0; + return i4Status; + } + + /* Clear the version byte */ + prParams->index = prParams->index & ~BITS(24, 31); + + if (prParams) { + switch (prParams->index) { + case 1: /* P2P Simga */ +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION + { + P_NL80211_DRIVER_SW_CMD_PARAMS prParamsCmd; + + prParamsCmd = (P_NL80211_DRIVER_SW_CMD_PARAMS) data; + + if ((prParamsCmd->adr & 0xffff0000) == 0xffff0000) { + i4Status = mtk_p2p_cfg80211_testmode_sw_cmd(wiphy, data, len); + break; + } + } +#endif + i4Status = mtk_p2p_cfg80211_testmode_p2p_sigma_cmd(wiphy, data, len); + break; + case 2: /* WFD */ +#if CFG_SUPPORT_WFD + /* use normal driver command wifi_display */ + /* i4Status = mtk_p2p_cfg80211_testmode_wfd_update_cmd(wiphy, data, len); */ +#endif + break; + case 3: /* Hotspot Client Management */ +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + i4Status = mtk_p2p_cfg80211_testmode_hotspot_block_list_cmd(wiphy, data, len); +#endif + break; + case 0x10: + i4Status = mtk_cfg80211_testmode_get_sta_statistics(wiphy, data, len, prGlueInfo); + break; +#if CFG_SUPPORT_NFC_BEAM_PLUS + case 0x11: /*NFC Beam + Indication */ + if (data && len) { + P_NL80211_DRIVER_SET_NFC_PARAMS prParams = (P_NL80211_DRIVER_SET_NFC_PARAMS) data; + + DBGLOG(P2P, INFO, "NFC: BEAM[%d]\n", prParams->NFC_Enable); + } + break; + case 0x12: /*NFC Beam + Indication */ + DBGLOG(P2P, INFO, "NFC: Polling\n"); + i4Status = mtk_cfg80211_testmode_get_scan_done(wiphy, data, len, prGlueInfo); + break; +#endif +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + case 0x30: /* Auto channel selection in LTE safe channels */ + i4Status = mtk_p2p_cfg80211_testmode_get_best_channel(wiphy, data, len); + break; +#endif + + default: + i4Status = -EINVAL; + break; + } + } + + return i4Status; + +} +#endif + +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; + UINT_8 ucBssIdx; + + ASSERT(wiphy); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, + "mtk_p2p_cfg80211_testmode_p2p_sigma_pre_cmd\n"); +#endif + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + kalMemZero(&rParams, sizeof(NL80211_DRIVER_TEST_PRE_PARAMS)); + + prP2pSpecificBssInfo = prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo[0]; + /* prP2pConnSettings = prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings; */ + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_testmode_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; + + /* 3 FIX ME: Add p2p role index selection */ + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, 0, &ucBssIdx) != WLAN_STATUS_SUCCESS) + return -EINVAL; + + 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 */ + { + PARAM_POWER_MODE_T rPowerMode; + + rPowerMode.ePowerMode = Param_PowerModeMAX_PSP; + rPowerMode.ucBssIdx = ucBssIdx; + + kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, sizeof(rPowerMode), FALSE, FALSE, 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 */ + { + PARAM_POWER_MODE_T rPowerMode; + + rPowerMode.ePowerMode = value; + rPowerMode.ucBssIdx = ucBssIdx; + + kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, sizeof(rPowerMode), FALSE, FALSE, 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; + UINT_8 ucBssIdx; + UINT_32 i; + + ASSERT(wiphy); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, + "mtk_p2p_cfg80211_testmode_p2p_sigma_cmd\n"); +#endif + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + prP2pSpecificBssInfo = prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo[0]; + /* 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); + + /* 3 FIX ME: Add p2p role index selection */ + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, 0, &ucBssIdx) != WLAN_STATUS_SUCCESS) + return -EINVAL; + + 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 */ + { + PARAM_POWER_MODE_T rPowerMode; + + rPowerMode.ePowerMode = Param_PowerModeMAX_PSP; + rPowerMode.ucBssIdx = ucBssIdx; + + kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, sizeof(rPowerMode), FALSE, FALSE, 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 */ + { + PARAM_POWER_MODE_T rPowerMode; + + rPowerMode.ePowerMode = value; + rPowerMode.ucBssIdx = ucBssIdx; + + kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, sizeof(rPowerMode), FALSE, FALSE, TRUE, &u4Leng); + } + break; + case 109: /* Max Clients */ +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + for (i = 0; i < KAL_P2P_NUM; i++) + kalP2PSetMaxClients(prGlueInfo, value, i); +#endif + break; + case 110: /* Hotspot WPS mode */ +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + kalIoctl(prGlueInfo, wlanoidSetP2pWPSmode, &value, sizeof(value), FALSE, FALSE, TRUE, &u4Leng); +#endif + break; + default: + break; + } + + return status; + +} + +#if CFG_SUPPORT_WFD && 0 +/* obsolete/decrepated */ +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); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, + "mtk_p2p_cfg80211_testmode_wfd_update_cmd\n"); +#endif + + 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.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 */ + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + +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; + UINT_32 i; + + ASSERT(wiphy); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, + "mtk_p2p_cfg80211_testmode_hotspot_block_list_cmd\n"); +#endif + + 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"); + + for (i = 0; i < KAL_P2P_NUM; i++) + fgIsValid |= kalP2PSetBlackList(prGlueInfo, prParams->aucBssid, prParams->ucblocked, i); + + return fgIsValid; + +} + +#endif + +int mtk_p2p_cfg80211_testmode_sw_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_SW_CMD_PARAMS prParams = (P_NL80211_DRIVER_SW_CMD_PARAMS) NULL; + WLAN_STATUS rstatus = WLAN_STATUS_SUCCESS; + int fgIsValid = 0; + UINT_32 u4SetInfoLen = 0; + + ASSERT(wiphy); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_testmode_sw_cmd\n"); +#endif + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + +#if 1 + DBGLOG(P2P, TRACE, "--> %s()\n", __func__); +#endif + + if (data && len) + prParams = (P_NL80211_DRIVER_SW_CMD_PARAMS) data; + + if (prParams) { + if (prParams->set == 1) { + rstatus = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC) wlanoidSetSwCtrlWrite, + &prParams->adr, (UINT_32) 8, FALSE, FALSE, TRUE, &u4SetInfoLen); + } + } + + if (rstatus != WLAN_STATUS_SUCCESS) + fgIsValid = -EFAULT; + + return fgIsValid; +} + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +int mtk_p2p_cfg80211_testmode_get_best_channel(IN struct wiphy *wiphy, IN void *data, IN int len) +{ + + struct sk_buff *skb; + + BOOLEAN fgIsReady = FALSE; + + P_GLUE_INFO_T prGlueInfo = NULL; + RF_CHANNEL_INFO_T aucChannelList[MAX_2G_BAND_CHN_NUM]; + UINT_8 ucNumOfChannel, i, ucIdx; + UINT_16 u2APNumScore = 0, u2UpThreshold = 0, u2LowThreshold = 0, ucInnerIdx = 0; + UINT_32 u4BufLen, u4LteSafeChnBitMask_2G = 0; + UINT_32 u4AcsChnReport[5]; + + P_PARAM_GET_CHN_INFO prGetChnLoad, prQueryLteChn; + PARAM_PREFER_CHN_INFO rPreferChannel = { 0, 0xFFFF, 0 }; + PARAM_PREFER_CHN_INFO arChannelDirtyScore_2G[MAX_2G_BAND_CHN_NUM]; + + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + ASSERT(wiphy); + +#if CFG_CHIP_RESET_SUPPORT + if (checkResetState()) + DBGLOG(P2P, ERROR, + "mtk_p2p_cfg80211_testmode_get_best_channel\n"); +#endif + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + if (!prGlueInfo) { + DBGLOG(P2P, ERROR, "No glue info\n"); + return -EFAULT; + } + + /* Prepare reply skb buffer */ + skb = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(u4AcsChnReport)); + if (!skb) { + DBGLOG(P2P, ERROR, "Allocate skb failed\n"); + return -ENOMEM; + } + + kalMemZero(u4AcsChnReport, sizeof(u4AcsChnReport)); + + fgIsReady = prGlueInfo->prAdapter->rWifiVar.rChnLoadInfo.fgDataReadyBit; + if (fgIsReady == FALSE) + goto acs_report; + + /* + * 1. Get 2.4G Band channel list in current regulatory domain + */ + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_2G4, TRUE, + MAX_2G_BAND_CHN_NUM, &ucNumOfChannel, aucChannelList); + + /* + * 2. Calculate each channel's dirty score + */ + prGetChnLoad = &(prGlueInfo->prAdapter->rWifiVar.rChnLoadInfo); + + for (i = 0; i < ucNumOfChannel; i++) { + ucIdx = aucChannelList[i].ucChannelNum - 1; + + /* Current channel's dirty score */ + u2APNumScore = prGetChnLoad->rEachChnLoad[ucIdx].u2APNum * CHN_DIRTY_WEIGHT_UPPERBOUND; + u2LowThreshold = u2UpThreshold = 3; + + if (ucIdx < 3) { + u2LowThreshold = ucIdx; + u2UpThreshold = 3; + } else if (ucIdx >= (ucNumOfChannel - 3)) { + u2LowThreshold = 3; + u2UpThreshold = ucNumOfChannel - (ucIdx + 1); + } + + /* Lower channel's dirty score */ + for (ucInnerIdx = 0; ucInnerIdx < u2LowThreshold; ucInnerIdx++) { + u2APNumScore += + (prGetChnLoad->rEachChnLoad[ucIdx - ucInnerIdx - 1].u2APNum * + (CHN_DIRTY_WEIGHT_UPPERBOUND - 1 - ucInnerIdx)); + } + + /* Upper channel's dirty score */ + for (ucInnerIdx = 0; ucInnerIdx < u2UpThreshold; ucInnerIdx++) { + u2APNumScore += + (prGetChnLoad->rEachChnLoad[ucIdx + ucInnerIdx + 1].u2APNum * + (CHN_DIRTY_WEIGHT_UPPERBOUND - 1 - ucInnerIdx)); + } + + arChannelDirtyScore_2G[i].ucChannel = aucChannelList[i].ucChannelNum; + arChannelDirtyScore_2G[i].u2APNumScore = u2APNumScore; + + DBGLOG(P2P, INFO, "[ACS]channel=%d, AP num=%d, score=%d\n", aucChannelList[i].ucChannelNum, + prGetChnLoad->rEachChnLoad[ucIdx].u2APNum, u2APNumScore); + } + + /* + * 3. Query LTE safe channels + */ + prQueryLteChn = kalMemAlloc(sizeof(PARAM_GET_CHN_INFO), VIR_MEM_TYPE); + if (prQueryLteChn == NULL) { + DBGLOG(P2P, ERROR, "Alloc prQueryLteChn failed\n"); + /* Continue anyway */ + } else { + kalMemZero(prQueryLteChn, sizeof(PARAM_GET_CHN_INFO)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryLteSafeChannel, + prQueryLteChn, + sizeof(PARAM_GET_CHN_INFO), + TRUE, + FALSE, + TRUE, + &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(P2P, ERROR, "Query LTE safe channels failed\n"); + /* Continue anyway */ + } + + u4LteSafeChnBitMask_2G = + prQueryLteChn->rLteSafeChnList.au4SafeChannelBitmask + [NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_2G_BASE_1 - 1]; + if (!u4LteSafeChnBitMask_2G) { + DBGLOG(P2P, WARN, " Can't get any 2G4 safe channel from fw!?\n"); + u4LteSafeChnBitMask_2G = BITS(1, 14); + } + + kalMemFree(prQueryLteChn, VIR_MEM_TYPE, sizeof(PARAM_GET_CHN_INFO)); + } + + /* 4. Find out the best channel, skip LTE unsafe channels */ + for (i = 0; i < ucNumOfChannel; i++) { + if (!(u4LteSafeChnBitMask_2G & BIT(arChannelDirtyScore_2G[i].ucChannel))) + continue; + + if (rPreferChannel.u2APNumScore >= arChannelDirtyScore_2G[i].u2APNumScore) { + rPreferChannel.ucChannel = arChannelDirtyScore_2G[i].ucChannel; + rPreferChannel.u2APNumScore = arChannelDirtyScore_2G[i].u2APNumScore; + } + } + + u4AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_2G_BASE_1 - 1] = fgIsReady ? BIT(31) : 0; + if (rPreferChannel.ucChannel > 0) + u4AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_2G_BASE_1 - 1] |= BIT(rPreferChannel.ucChannel - 1); + + /* ToDo: Support 5G Channel Selection */ + +acs_report: + if (unlikely(nla_put_u32(skb, NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_2G_BASE_1, + u4AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_2G_BASE_1 - 1]) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put_u32(skb, NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_36, + u4AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_36 - 1]) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put_u32(skb, NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_52, + u4AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_52 - 1]) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put_u32(skb, NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_100, + u4AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_100 - 1]) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put_u32(skb, NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_149, + u4AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_149 - 1]) < 0)) + goto nla_put_failure; + + DBGLOG(P2P, INFO, "[ACS]Relpy u4AcsChnReport[2G_BASE_1]=0x%08x\n", u4AcsChnReport[0]); + + return cfg80211_testmode_reply(skb); + +nla_put_failure: + kfree_skb(skb); + return -EMSGSIZE; +} +#endif + + +#if GO_STA_SCC +int mtk_p2p_cfg80211_go_channel_switch(IN struct wiphy *wiphy, + IN struct wireless_dev *wdev, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + NT_32 i4Status = -EINVAL + struct net_device *dev = (struct net_device *) NULL; + P_MSG_P2P_SET_NEW_CHANNEL_T prP2pSetNewChannelMsg = + (P_MSG_P2P_SET_NEW_CHANNEL_T) NULL; + UINT_8 ucRoleIdx = 0; + RF_CHANNEL_INFO_T rRfChnlInfo; + struct cfg80211_go_chan_switch *p_go_chan_switch; + struct cfg80211_chan_def *chan_def; + + p_go_chan_switch = (struct cfg80211_go_chan_switch *) data; + dev = wdev->netdev; + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0) + return -EINVAL; + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->chandef == NULL) { + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef = + (struct cfg80211_chan_def *) + cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_BUF, sizeof(struct cfg80211_chan_def)); + + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->chan = + (struct ieee80211_channel *) + cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_BUF, sizeof(struct ieee80211_channel)); + } + + chan_def = p_go_chan_switch->chan_def; + /* Copy chan def to local buffer*/ + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->center_freq1 = + chan_def->center_freq1; + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->center_freq2 = + chan_def->center_freq2; + prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->width = chan_def->width; + memcpy(prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->chan, chan_def->chan, + sizeof(struct ieee80211_channel)); + + mtk_p2p_cfg80211func_channel_format_switch(chan_def, + chan_def->chan, &rRfChnlInfo); + p2pFuncSetChannel(prGlueInfo->prAdapter, ucRoleIdx, &rRfChnlInfo); + /* Set new channel parameters */ + prP2pSetNewChannelMsg = + (P_MSG_P2P_SET_NEW_CHANNEL_T) cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, sizeof(*prP2pSetNewChannelMsg)); + if (prP2pSetNewChannelMsg == NULL) { + i4Status = -ENOMEM; + return i4Status; + } + prP2pSetNewChannelMsg->rMsgHdr.eMsgId = MID_MNY_P2P_SET_NEW_CHANNEL; + + switch (chan_def->width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + case NL80211_CHAN_WIDTH_40: + prP2pSetNewChannelMsg->eChannelWidth = CW_20_40MHZ; + break; + + case NL80211_CHAN_WIDTH_80: + prP2pSetNewChannelMsg->eChannelWidth = CW_80MHZ; + break; + + case NL80211_CHAN_WIDTH_80P80: + prP2pSetNewChannelMsg->eChannelWidth = CW_80P80MHZ; + break; + + default: + DBGLOG(P2P, ERROR, + "Bandwidth do not support!!!\n"); + i4Status = -EINVAL; + return i4Status; + } + + prP2pSetNewChannelMsg->ucRoleIdx = ucRoleIdx; + prP2pSetNewChannelMsg->ucBssIndex = 1; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, + (P_MSG_HDR_T) prP2pSetNewChannelMsg, MSG_SEND_METHOD_BUF); + + i4Status = 0; + return i4Status; +} +#endif + +#endif + +#endif /* CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_WIFI_DIRECT_CFG_80211 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_p2p_init.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_p2p_init.c new file mode 100644 index 0000000000000..ab7a84527a4a0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_p2p_init.c @@ -0,0 +1,254 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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_INF_NAME "p2p%d" +#define AP_INF_NAME "ap%d" + +/******************************************************************************* +* 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 PUCHAR ifname = P2P_INF_NAME; +static PUCHAR ifname2 = P2P_INF_NAME; +static UINT_16 mode = RUNNING_P2P_MODE; + + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +VOID p2pSetSuspendMode(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgEnable) +{ + struct net_device *prDev = NULL; + + if (!prGlueInfo) + return; + + if (!prGlueInfo->prAdapter->fgIsP2PRegistered) { + DBGLOG(INIT, INFO, "%s: P2P is not enabled, SKIP!\n", __func__); + return; + } + + prDev = prGlueInfo->prP2PInfo[0]->prDevHandler; + if (!prDev) { + DBGLOG(INIT, INFO, "%s: P2P dev is not available, SKIP!\n", __func__); + return; + } + + kalSetNetAddressFromInterface(prGlueInfo, prDev, fgEnable); + wlanNotifyFwSuspend(prGlueInfo, prDev, fgEnable); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* run p2p init procedure, glue register p2p and set p2p registered flag +* +* \retval 1 Success +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2pLaunch(P_GLUE_INFO_T prGlueInfo) +{ + if (prGlueInfo->prAdapter->fgIsP2PRegistered == TRUE) { + DBGLOG(P2P, INFO, "p2p is already registered\n"); + return FALSE; + } + + if (!glRegisterP2P(prGlueInfo, ifname, ifname2, mode)) { + DBGLOG(P2P, ERROR, "Launch failed\n"); + return FALSE; + } + + prGlueInfo->prAdapter->fgIsP2PRegistered = TRUE; + prGlueInfo->prAdapter->p2p_scan_report_all_bss = CFG_P2P_SCAN_REPORT_ALL_BSS; + DBGLOG(P2P, INFO, "Launch success, fgIsP2PRegistered TRUE\n"); + return TRUE; +} + +VOID p2pSetMode(IN UINT_8 ucAPMode) +{ + PUCHAR prAPInfName = AP_INF_NAME; + PUCHAR prP2PInfName = P2P_INF_NAME; + +#ifdef CFG_DRIVER_INF_NAME_CHANGE + + if (kalStrLen(gprifnamep2p) > 0) { + if (kalStrStr(gprifnamep2p, "%d")) + prP2PInfName = gprifnamep2p; + else + prP2PInfName = kalStrCat(gprifnamep2p, "%d"); + DBGLOG(INIT, WARN, "P2P ifname customized, use %s\n", prP2PInfName); + } + + if (kalStrLen(gprifnameap) > 0) { + if (kalStrStr(gprifnameap, "%d")) + prAPInfName = gprifnameap; + else + prAPInfName = kalStrCat(gprifnameap, "%d"); + DBGLOG(INIT, WARN, "AP ifname customized, use %s\n", prAPInfName); + } + +#endif /* CFG_DRIVER_INF_NAME_CHANGE */ + + switch (ucAPMode) { + case 0: + mode = RUNNING_P2P_MODE; + ifname = prP2PInfName; + break; + case 1: + mode = RUNNING_AP_MODE; + ifname = prAPInfName; + break; + case 2: + mode = RUNNING_DUAL_AP_MODE; + ifname = prAPInfName; + break; + case 3: + mode = RUNNING_P2P_AP_MODE; + ifname = prP2PInfName; + ifname2 = prAPInfName; + break; + } +} /* p2pSetMode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* run p2p exit procedure, glue unregister p2p and set p2p registered flag +* +* \retval 1 Success +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2pRemove(P_GLUE_INFO_T prGlueInfo) +{ + int idx = 0; + if (prGlueInfo->prAdapter->fgIsP2PRegistered == FALSE) { + DBGLOG(P2P, INFO, "p2p is not registered\n"); + return FALSE; + } + + DBGLOG(P2P, INFO, "fgIsP2PRegistered FALSE\n"); + prGlueInfo->prAdapter->fgIsP2PRegistered = FALSE; + prGlueInfo->prAdapter->p2p_scan_report_all_bss = FALSE; + glUnregisterP2P(prGlueInfo); + + /* gprP2pWdev/gprP2pRoleWdev[0]: base P2P dev + * gprP2pRoleWdev[1]: AP dev + * Becase the interface dev (ex: usb_device) would be free + * after un-plug event. Should set the wiphy->dev->parent which + * pointer to the interface dev to NULL. Otherwise, the corresponding + * system operation (poweroff, suspend) might reference it. + * set_wiphy_dev(wiphy, NULL): set the wiphy->dev->parent = NULL + * The trunk-ce1 does this, but the trunk seems not. + * ce1 do set_wiphy_dev(prWdev->wiphy, prDev) in wlanNetCreate. + * But that is after wiphy_register, and will cause exception in + * wiphy_unregister(), if do not set_wiphy_dev(wiphy, NULL). + */ + for (idx = 0 ; idx < KAL_P2P_NUM; idx++) { + if (gprP2pRoleWdev[idx] == NULL) + continue; + + DBGLOG(INIT, INFO, "Clean parent dev of P2P[%d] wiphy\n", idx); + set_wiphy_dev(gprP2pRoleWdev[idx]->wiphy, NULL); + } + + return TRUE; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_p2p_kal.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_p2p_kal.c new file mode 100644 index 0000000000000..b4bcffc04fa7f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_p2p_kal.c @@ -0,0 +1,1692 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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" +#include "gl_wext.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 +******************************************************************************** +*/ + +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 +*/ +/*----------------------------------------------------------------------------*/ +#if 0 +ENUM_PARAM_MEDIA_STATE_T kalP2PGetState(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->prP2PInfo[0]->eState; +} /* end of kalP2PGetState() */ +#endif +/*----------------------------------------------------------------------------*/ +/*! +* \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, IN UINT_8 ucBssIndex) +{ + P_BSS_INFO_T prBssInfo; + union iwreq_data wrqu; + unsigned char *pucExtraInfo = NULL; + unsigned char *pucDesiredIE = NULL; +/* unsigned char aucExtraInfoBuf[200]; */ + PUINT_8 cp; + struct net_device *prNetdevice = (struct net_device *)NULL; + + 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 */ + return; + } + + /* IWEVASSOCREQIE, indicate binary string */ + pucExtraInfo = pucDesiredIE; + wrqu.data.length = pucDesiredIE[1] + 2; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, ucBssIndex); + + if (ucBssIndex == P2P_DEV_BSS_INDEX) + prNetdevice = prGlueInfo->prP2PInfo[prBssInfo->u4PrivateData]->prDevHandler; + else + prNetdevice = prGlueInfo->prP2PInfo[prBssInfo->u4PrivateData]->aprRoleHandler; + + /* Send event to user space */ + wireless_send_event(prNetdevice, IWEVASSOCREQIE, &wrqu, pucExtraInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to set Wi-Fi Direct state in glue layer +* +* \param[in] +* prGlueInfo +* eBowState +* rPeerAddr +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +#if 0 +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[0]->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[0]->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[0]->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + } else { + ASSERT(0); + } + +} /* end of kalP2PSetState() */ +#endif +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Wi-Fi Direct operating frequency +* +* \param[in] +* prGlueInfo +* +* \return +* in unit of KHz +*/ +/*----------------------------------------------------------------------------*/ +#if 0 +UINT_32 kalP2PGetFreqInKHz(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->prP2PInfo[0]->u4FreqInKHz; +} /* end of kalP2PGetFreqInKHz() */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \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, IN UINT_8 ucRoleIdx) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->prP2PInfo[ucRoleIdx]->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 +*/ +/*----------------------------------------------------------------------------*/ +#if 1 +VOID kalP2PSetRole(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRole, IN UINT_8 ucRoleIdx) +{ + ASSERT(prGlueInfo); + ASSERT(ucRole <= 2); + + prGlueInfo->prP2PInfo[ucRoleIdx]->ucRole = ucRole; + /* Remove non-used code */ +} /* end of kalP2PSetRole() */ + +#else +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[0]->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[0]->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PSetRole() */ + +#endif +/*----------------------------------------------------------------------------*/ +/*! +* \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, IN UINT_8 ucRoleIdx) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo[ucRoleIdx]); + + /* It can be WEP40 (used to identify cipher is WEP), TKIP and CCMP */ + prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise = u4Cipher; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to get the cipher, return false for security is none +* +* \param[in] +* prGlueInfo +* +* \return +* TRUE: cipher is ccmp +* FALSE: cipher is none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalP2PGetCipher(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRoleIdx) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo[ucRoleIdx]); + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise == IW_AUTH_CIPHER_CCMP) + return TRUE; + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise == IW_AUTH_CIPHER_TKIP) + return TRUE; + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise == IW_AUTH_CIPHER_WEP40) + return TRUE; + + return FALSE; +} + +BOOLEAN kalP2PGetWepCipher(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRoleIdx) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo[ucRoleIdx]); + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise == IW_AUTH_CIPHER_WEP40) + return TRUE; + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise == IW_AUTH_CIPHER_WEP104) + return TRUE; + + return FALSE; +} + +#if CFG_SUPPORT_SUITB +BOOLEAN kalP2PGetGcmp256Cipher(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRoleIdx) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo[ucRoleIdx]); + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise + == IW_AUTH_CIPHER_GCMP256) + return TRUE; + + return FALSE; +} +#endif + +BOOLEAN kalP2PGetCcmpCipher(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRoleIdx) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo[ucRoleIdx]); + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise == IW_AUTH_CIPHER_CCMP) + return TRUE; + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise == IW_AUTH_CIPHER_TKIP) + return FALSE; + + return FALSE; +} + +BOOLEAN kalP2PGetTkipCipher(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRoleIdx) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo[ucRoleIdx]); + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise == IW_AUTH_CIPHER_CCMP) + return FALSE; + + if (prGlueInfo->prP2PInfo[ucRoleIdx]->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->prP2PDevInfo); + + prGlueInfo->prP2PDevInfo->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->prP2PDevInfo); + + return prGlueInfo->prP2PDevInfo->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, IN UINT_8 ucRoleIdx) +{ + ASSERT(prGlueInfo); + + ASSERT(ucType < 4); + + return prGlueInfo->prP2PInfo[ucRoleIdx]->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, IN UINT_8 ucRoleIdx) +{ + P_GL_P2P_INFO_T prGlP2pInfo = (P_GL_P2P_INFO_T) NULL; + + do { + if ((prGlueInfo == NULL) || (ucType >= 4) || (pucBuffer == NULL)) + break; + + prGlP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + + kalMemCopy(pucBuffer, prGlP2pInfo->aucWSCIE[ucType], prGlP2pInfo->u2WSCIELen[ucType]); + + } while (FALSE); + +} + +VOID kalP2PUpdateWSC_IE(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucType, IN PUINT_8 pucBuffer, + IN UINT_16 u2BufferLength, IN UINT_8 ucRoleIdx) +{ + P_GL_P2P_INFO_T prGlP2pInfo = (P_GL_P2P_INFO_T) NULL; + + do { + if ((prGlueInfo == NULL) || (ucType >= 4) || ((u2BufferLength > 0) && (pucBuffer == NULL))) + break; + + if (u2BufferLength > VENDOR_SPECIFIC_IE_LENGTH) { + DBGLOG(P2P, ERROR, "Allow %d bytes but %d received\n", + VENDOR_SPECIFIC_IE_LENGTH, u2BufferLength); + ASSERT(FALSE); + break; + } + + prGlP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + + kalMemCopy(prGlP2pInfo->aucWSCIE[ucType], pucBuffer, u2BufferLength); + + prGlP2pInfo->u2WSCIELen[ucType] = u2BufferLength; + + } while (FALSE); + +} /* kalP2PUpdateWSC_IE */ + +UINT_16 kalP2PCalP2P_IELen(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_32 u4IEIdx, IN UINT_8 ucRoleIdx) +{ + if (u4IEIdx >= MAX_MULTI_P2P_IE_COUNT) + return 0; + + return prGlueInfo->prP2PInfo[ucRoleIdx]->u2P2PIELen[u4IEIdx]; +} + +/* kalP2PGenP2P_IE + * append p2p ie to output frame + */ +VOID kalP2PGenP2P_IE(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4IEIdx, + IN PUINT_8 pucBuffer, IN UINT_8 ucRoleIdx) +{ + P_GL_P2P_INFO_T prGlP2pInfo = (P_GL_P2P_INFO_T) NULL; + + if (!pucBuffer) + return; + + if (u4IEIdx >= MAX_MULTI_P2P_IE_COUNT) + return; + + prGlP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + + if (prGlP2pInfo->u2P2PIELen[u4IEIdx] > 0) + kalMemCopy(pucBuffer, prGlP2pInfo->aucP2PIE[u4IEIdx], + prGlP2pInfo->u2P2PIELen[u4IEIdx]); +} + +VOID kalP2PResetP2P_IE(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRoleIdx) +{ + P_GL_P2P_INFO_T prGlP2pInfo = (P_GL_P2P_INFO_T) NULL; + UINT_32 u4IEIdx = MAX_MULTI_P2P_IE_COUNT; + + prGlP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + + while (u4IEIdx-- > 0) + prGlP2pInfo->u2P2PIELen[u4IEIdx] = 0; +} + +/* kalP2PUpdateP2P_IE + * copy multiple p2p ie to local buffer + */ +VOID kalP2PUpdateP2P_IE(IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucBuffer, IN UINT_16 u2BufferLength, IN UINT_8 ucRoleIdx) +{ + P_GL_P2P_INFO_T prGlP2pInfo = (P_GL_P2P_INFO_T) NULL; + UINT_32 u4IEIdx; + + if (!prGlueInfo) { + DBGLOG(P2P, ERROR, "NULL prGlueInfo!\n"); + return; + } + + if (!pucBuffer) { + DBGLOG(P2P, ERROR, "NULL pucBuffer!\n"); + return; + } + + if (u2BufferLength == 0) { + DBGLOG(P2P, WARN, "0 IE length, skip update\n"); + return; + } + + if (u2BufferLength > VENDOR_SPECIFIC_IE_LENGTH) { + DBGLOG(P2P, ERROR, "Allow %d bytes but %d received\n", + VENDOR_SPECIFIC_IE_LENGTH, u2BufferLength); + return; + } + + DBGLOG(P2P, TRACE, "ucRoleIdx=%d, u2BufferLength=%d\n", + ucRoleIdx, u2BufferLength); + + prGlP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + + for (u4IEIdx = 0; u4IEIdx < MAX_MULTI_P2P_IE_COUNT; u4IEIdx++) { + if (prGlP2pInfo->u2P2PIELen[u4IEIdx] == 0) { + DBGLOG(P2P, INFO, + "ucRoleIdx=%d, u4IEIdx=%d, u2BufferLength=%d\n", + ucRoleIdx, u4IEIdx, u2BufferLength); + kalMemCopy(prGlP2pInfo->aucP2PIE[u4IEIdx], + pucBuffer, u2BufferLength); + prGlP2pInfo->u2P2PIELen[u4IEIdx] = u2BufferLength; + break; + } + } + + if (u4IEIdx == MAX_MULTI_P2P_IE_COUNT) + DBGLOG(P2P, WARN, "No available aucP2PIE\n"); +} + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \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[0]->u4ConnReqNameLength = u4NameLength > 32 ? 32 : u4NameLength; + kalMemCopy(prGlueInfo->prP2PInfo[0]->aucConnReqDevName, + pucDevName, + prGlueInfo->prP2PInfo[0]->u4ConnReqNameLength); + COPY_MAC_ADDR(prGlueInfo->prP2PInfo[0]->rConnReqPeerAddr, rPeerAddr); + prGlueInfo->prP2PInfo[0]->ucConnReqDevType = ucDevType; + prGlueInfo->prP2PInfo[0]->i4ConnReqConfigMethod = i4ConfigMethod; + prGlueInfo->prP2PInfo[0]->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[0]->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PIndicateConnReq() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Indicate an event to supplicant for device connection request from other device. +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* \param[in] pucGroupBssid Only valid when invitation Type equals to 0. +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalP2PInvitationIndication(IN P_GLUE_INFO_T prGlueInfo, + IN P_P2P_DEVICE_DESC_T prP2pDevDesc, + IN PUINT_8 pucSsid, + IN UINT_8 ucSsidLen, + IN UINT_8 ucOperatingChnl, IN UINT_8 ucInvitationType, IN PUINT_8 pucGroupBssid) +{ +#if 1 + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + /* buffer peer information for later IOC_P2P_GET_STRUCT access */ + prGlueInfo->prP2PInfo[0]->u4ConnReqNameLength = + (UINT_32) ((prP2pDevDesc->u2NameLength > 32) ? 32 : prP2pDevDesc->u2NameLength); + kalMemCopy(prGlueInfo->prP2PInfo[0]->aucConnReqDevName, prP2pDevDesc->aucName, + prGlueInfo->prP2PInfo[0]->u4ConnReqNameLength); + COPY_MAC_ADDR(prGlueInfo->prP2PInfo[0]->rConnReqPeerAddr, prP2pDevDesc->aucDeviceAddr); + COPY_MAC_ADDR(prGlueInfo->prP2PInfo[0]->rConnReqGroupAddr, pucGroupBssid); + prGlueInfo->prP2PInfo[0]->i4ConnReqConfigMethod = (INT_32) (prP2pDevDesc->u2ConfigMethod); + prGlueInfo->prP2PInfo[0]->ucOperatingChnl = ucOperatingChnl; + prGlueInfo->prP2PInfo[0]->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[0]->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + +#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[0]->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 */ + +#endif + +} /* kalP2PInvitationIndication */ +#endif + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \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[0]->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[0]->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + +} /* kalP2PInvitationStatus */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \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[0]->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PIndicateSDRequest() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Indicate an event to supplicant for Service Discovery response +* from other device. +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +void kalP2PIndicateSDResponse(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rPeerAddr, IN UINT_8 ucSeqNum) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_SD_RESP %d", ucSeqNum); + evt.data.length = strlen(aucBuffer); + + /* indicate IWEVP2PSDREQ event */ + wireless_send_event(prGlueInfo->prP2PInfo[0]->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PIndicateSDResponse() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Indicate an event to supplicant for Service Discovery TX Done +* from other device. +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* \param[in] ucSeqNum Sequence number of the frame +* \param[in] ucStatus Status code for TX +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalP2PIndicateTXDone(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucSeqNum, IN UINT_8 ucStatus) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_SD_XMITTED: %d %d", ucSeqNum, ucStatus); + evt.data.length = strlen(aucBuffer); + + /* indicate IWEVP2PSDREQ event */ + wireless_send_event(prGlueInfo->prP2PInfo[0]->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PIndicateSDResponse() */ + +struct net_device *kalP2PGetDevHdlr(P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo[0]); + return prGlueInfo->prP2PInfo[0]->prDevHandler; +} + +#if CFG_SUPPORT_ANTI_PIRACY +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \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[0]->aucSecCheckRsp, pucRsp, u2RspLen); + evt.data.length = strlen(aucBuffer); + +#if DBG + DBGLOG_MEM8(SEC, LOUD, prGlueInfo->prP2PInfo[0]->aucSecCheckRsp, u2RspLen); +#endif + /* indicate in IWECUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo[0]->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); +} /* p2pFsmRunEventRxDisassociation */ +#endif +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalGetChnlList(IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_BAND_T eSpecificBand, + IN UINT_8 ucMaxChannelNum, IN PUINT_8 pucNumOfChannel, IN P_RF_CHANNEL_INFO_T paucChannelList) +{ + rlmDomainGetChnlList(prGlueInfo->prAdapter, eSpecificBand, + FALSE, ucMaxChannelNum, pucNumOfChannel, paucChannelList); +} /* kalGetChnlList */ + +/* ////////////////////////////////////ICS SUPPORT////////////////////////////////////// */ + +VOID +kalP2PIndicateChannelReady(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8SeqNum, + IN UINT_32 u4ChannelNum, + IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_32 u4Duration) +{ + struct ieee80211_channel *prIEEE80211ChnlStruct = (struct ieee80211_channel *)NULL; + RF_CHANNEL_INFO_T rChannelInfo; + enum nl80211_channel_type eChnlType = NL80211_CHAN_NO_HT; + + do { + if (prGlueInfo == NULL) + break; + + kalMemZero(&rChannelInfo, sizeof(RF_CHANNEL_INFO_T)); + + rChannelInfo.ucChannelNum = u4ChannelNum; + rChannelInfo.eBand = eBand; + + prIEEE80211ChnlStruct = kalP2pFuncGetChannelEntry(prGlueInfo->prP2PInfo[0], &rChannelInfo); + + kalP2pFuncGetChannelType(eSco, &eChnlType); + + cfg80211_ready_on_channel(prGlueInfo->prP2PInfo[0]->prWdev, /* struct wireless_dev, */ + u8SeqNum, /* u64 cookie, */ + prIEEE80211ChnlStruct, /* struct ieee80211_channel * chan, */ + u4Duration, /* unsigned int duration, */ + GFP_KERNEL); /* gfp_t gfp *//* allocation flags */ + } while (FALSE); + +} /* kalP2PIndicateChannelReady */ + +VOID +kalP2PIndicateChannelExpired(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8SeqNum, + IN UINT_32 u4ChannelNum, IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco) +{ + + 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) { + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo[0]; + + if (prGlueP2pInfo == NULL) { + ASSERT(FALSE); + break; + } + + DBGLOG(P2P, TRACE, "kalP2PIndicateChannelExpired\n"); + + rRfChannelInfo.eBand = eBand; + rRfChannelInfo.ucChannelNum = u4ChannelNum; + + prIEEE80211ChnlStruct = kalP2pFuncGetChannelEntry(prGlueP2pInfo, &rRfChannelInfo); + if (!prIEEE80211ChnlStruct) { + DBGLOG(P2P, ERROR, "prIEEE80211ChnlStruct is NULL!\n"); + break; + } + + kalP2pFuncGetChannelType(eSco, &eChnlType); + + cfg80211_remain_on_channel_expired(prGlueP2pInfo->prWdev, /* struct wireless_dev, */ + u8SeqNum, prIEEE80211ChnlStruct, GFP_KERNEL); + } while (FALSE); + +} /* kalP2PIndicateChannelExpired */ + +VOID kalP2PIndicateScanDone(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRoleIndex, IN BOOLEAN fgIsAbort) +{ + P_GL_P2P_DEV_INFO_T prP2pGlueDevInfo = (P_GL_P2P_DEV_INFO_T) NULL; + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + struct cfg80211_scan_request *prScanRequest = NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + do { + if (prGlueInfo == NULL) { + + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo[0]; + prP2pGlueDevInfo = prGlueInfo->prP2PDevInfo; + + if ((prGlueP2pInfo == NULL) || (prP2pGlueDevInfo == NULL)) { + ASSERT(FALSE); + break; + } + + DBGLOG(INIT, INFO, "[p2p] scan complete %p\n", prP2pGlueDevInfo->prScanRequest); + + KAL_ACQUIRE_MUTEX(prGlueInfo->prAdapter, MUTEX_DEL_INF); + + /* The cfg80211_scan_done may be interruptd by the p2pStop. + * And the following kernel process calls __cfg80211_scan_done, + * that causes some issue. the temporary solution is putting + * the scan_done inside the lock. ref: change 1022227. + */ + if (prGlueInfo->prAdapter->fgIsP2PRegistered == TRUE) { + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + prScanRequest = prP2pGlueDevInfo->prScanRequest; + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + if (prScanRequest != NULL) { + scanReportBss2Cfg80211(prGlueInfo->prAdapter, + BSS_TYPE_P2P_DEVICE, NULL); + } + /* scanReportBss2Cfg80211() do many works, so don't put + * it inside the lock. And its main function puts bss + * to cfg80211, that isn't related to scan_req. + */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + prScanRequest = prP2pGlueDevInfo->prScanRequest; + if (prScanRequest != NULL) { + DBGLOG(INIT, INFO, "DBG:p2p_cfg_scan_done\n"); + kalCfg80211ScanDone(prScanRequest, fgIsAbort); + prP2pGlueDevInfo->prScanRequest = NULL; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + } + KAL_RELEASE_MUTEX(prGlueInfo->prAdapter, MUTEX_DEL_INF); + + } 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[0]; + + 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->prWdev->wiphy, /* struct wiphy * wiphy, */ + prChannelEntry, + prBcnProbeRspFrame, u4BufLen, i4SignalStrength, GFP_KERNEL); + + /* Return this structure. */ + cfg80211_put_bss(prGlueP2pInfo->prWdev->wiphy, prCfg80211Bss); + + } while (FALSE); + + return; + +} /* kalP2PIndicateBssInfo */ + +VOID kalP2PIndicateMgmtTxStatus(IN P_GLUE_INFO_T prGlueInfo, IN P_MSDU_INFO_T prMsduInfo, IN BOOLEAN fgIsAck) +{ + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + PUINT_64 pu8GlCookie = (PUINT_64) NULL; + struct net_device *prNetdevice = (struct net_device *)NULL; + + do { + if ((prGlueInfo == NULL) || (prMsduInfo == NULL)) { + DBGLOG(P2P, WARN, "Unexpected pointer PARAM. 0x%lx, 0x%lx.\n", prGlueInfo, prMsduInfo); + ASSERT(FALSE); + break; + } + + pu8GlCookie = + (PUINT_64) ((ULONG) prMsduInfo->prPacket + + (ULONG) prMsduInfo->u2FrameLength + MAC_TX_RESERVED_FIELD); + + if (prMsduInfo->ucBssIndex == P2P_DEV_BSS_INDEX) { + prGlueP2pInfo = prGlueInfo->prP2PInfo[0]; + prNetdevice = prGlueP2pInfo->prDevHandler; + + } else { + P_BSS_INFO_T prP2pBssInfo = + GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, prMsduInfo->ucBssIndex); + prGlueP2pInfo = prGlueInfo->prP2PInfo[prP2pBssInfo->u4PrivateData]; + prNetdevice = prGlueP2pInfo->aprRoleHandler; + } + + cfg80211_mgmt_tx_status(prNetdevice->ieee80211_ptr, /* struct net_device * dev, */ + *pu8GlCookie, + (PUINT_8) ((ULONG) prMsduInfo->prPacket + + MAC_TX_RESERVED_FIELD), + prMsduInfo->u2FrameLength, fgIsAck, GFP_KERNEL); + + } while (FALSE); + +} /* kalP2PIndicateMgmtTxStatus */ + +VOID +kalP2PIndicateRxMgmtFrame(IN P_GLUE_INFO_T prGlueInfo, + IN P_SW_RFB_T prSwRfb, IN BOOLEAN fgIsDevInterface, IN UINT_8 ucRoleIdx) +{ +#define DBG_P2P_MGMT_FRAME_INDICATION 1 + 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 + struct net_device *prNetdevice = (struct net_device *)NULL; + + do { + if ((prGlueInfo == NULL) || (prSwRfb == NULL)) { + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + + /* ToDo[6630]: Get the following by channel freq */ + /* HAL_RX_STATUS_GET_CHAN_FREQ( prSwRfb->prRxStatus) */ + /* ucChnlNum = prSwRfb->prHifRxHdr->ucHwChannelNum; */ + + ucChnlNum = HAL_RX_STATUS_GET_CHNL_NUM(prSwRfb->prRxStatus); + +#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 (fgIsDevInterface) + prNetdevice = prGlueP2pInfo->prDevHandler; + else + prNetdevice = prGlueP2pInfo->aprRoleHandler; + if (prNetdevice == NULL) { + DBGLOG(AIS, WARN, + "prNetdevice is NULL!\n"); + break; + } + if (prGlueInfo->prDevHandler->ieee80211_ptr == NULL) { + DBGLOG(AIS, WARN, + "ieee80211_ptr is NULL!\n"); + break; + } + +#if (KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE) + cfg80211_rx_mgmt(prNetdevice->ieee80211_ptr, /* struct net_device * dev, */ + i4Freq, + RCPI_TO_dBm(nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0, prSwRfb)), + prSwRfb->pvHeader, + prSwRfb->u2PacketLen, + NL80211_RXMGMT_FLAG_ANSWERED); +#elif (KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE) + cfg80211_rx_mgmt(prNetdevice->ieee80211_ptr, /* struct net_device * dev, */ + i4Freq, + RCPI_TO_dBm(nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0, prSwRfb)), + prSwRfb->pvHeader, + prSwRfb->u2PacketLen, + NL80211_RXMGMT_FLAG_ANSWERED, + GFP_ATOMIC); +#else + cfg80211_rx_mgmt(prNetdevice->ieee80211_ptr, /* struct net_device * dev, */ + i4Freq, + RCPI_TO_dBm(nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0, prSwRfb)), + prSwRfb->pvHeader, + prSwRfb->u2PacketLen, + GFP_ATOMIC); +#endif + + + } while (FALSE); + +} /* kalP2PIndicateRxMgmtFrame */ +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) +VOID +kalP2PGCIndicateConnectionStatus(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucRoleIndex, + IN P_P2P_CONNECTION_REQ_INFO_T prP2pConnInfo, + IN PUINT_8 pucRxIEBuf, IN UINT_16 u2RxIELen, IN UINT_16 u2StatusReason, + IN WLAN_STATUS eStatus) +{ + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + + do { + if (prGlueInfo == NULL) { + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo[ucRoleIndex]; + + if (prP2pConnInfo) { + cfg80211_connect_result(prGlueP2pInfo->aprRoleHandler, + /* struct net_device * dev, */ + prP2pConnInfo->aucBssid, prP2pConnInfo->aucIEBuf, + prP2pConnInfo->u4BufLength, + pucRxIEBuf, u2RxIELen, u2StatusReason, + GFP_KERNEL); /* gfp_t gfp *//* allocation flags */ + + prP2pConnInfo->eConnRequest = P2P_CONNECTION_TYPE_IDLE; + } else { + /* Disconnect, what if u2StatusReason == 0? */ + cfg80211_disconnected(prGlueP2pInfo->aprRoleHandler, + /* struct net_device * dev, */ + u2StatusReason, pucRxIEBuf, u2RxIELen, + eStatus == WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY, GFP_KERNEL); + } + + } while (FALSE); + +} /* kalP2PGCIndicateConnectionStatus */ + +#else +VOID +kalP2PGCIndicateConnectionStatus(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucRoleIndex, + 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[ucRoleIndex]; + + if (prP2pConnInfo) { + cfg80211_connect_result(prGlueP2pInfo->aprRoleHandler, + /* struct net_device * dev, */ + prP2pConnInfo->aucBssid, prP2pConnInfo->aucIEBuf, + prP2pConnInfo->u4BufLength, + pucRxIEBuf, u2RxIELen, u2StatusReason, + GFP_KERNEL); /* gfp_t gfp *//* allocation flags */ + + prP2pConnInfo->eConnRequest = P2P_CONNECTION_TYPE_IDLE; + } else { + /* Disconnect, what if u2StatusReason == 0? */ + cfg80211_disconnected(prGlueP2pInfo->aprRoleHandler, + /* struct net_device * dev, */ + u2StatusReason, pucRxIEBuf, u2RxIELen, GFP_KERNEL); + } + + } while (FALSE); + +} /* kalP2PGCIndicateConnectionStatus */ + +#endif + +VOID +kalP2PGOStationUpdate(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucRoleIndex, IN P_STA_RECORD_T prCliStaRec, IN BOOLEAN fgIsNew) +{ + P_GL_P2P_INFO_T prP2pGlueInfo = (P_GL_P2P_INFO_T) NULL; + + do { + if ((prGlueInfo == NULL) || (prCliStaRec == NULL) || (ucRoleIndex >= 2)) + break; + + prP2pGlueInfo = prGlueInfo->prP2PInfo[ucRoleIndex]; + + if (fgIsNew) { + struct station_info rStationInfo; + + kalMemZero(&rStationInfo, sizeof(rStationInfo)); + +#if KERNEL_VERSION(4, 0, 0) > CFG80211_VERSION_CODE + rStationInfo.filled = STATION_INFO_ASSOC_REQ_IES; +#endif + rStationInfo.generation = ++prP2pGlueInfo->i4Generation; + + rStationInfo.assoc_req_ies = prCliStaRec->pucAssocReqIe; + rStationInfo.assoc_req_ies_len = prCliStaRec->u2AssocReqIeLen; + + cfg80211_new_sta(prP2pGlueInfo->aprRoleHandler, + /* struct net_device * dev, */ + prCliStaRec->aucMacAddr, &rStationInfo, GFP_KERNEL); + } else { + ++prP2pGlueInfo->i4Generation; + + cfg80211_del_sta(prP2pGlueInfo->aprRoleHandler, + /* struct net_device * dev, */ + prCliStaRec->aucMacAddr, GFP_KERNEL); + } + + } while (FALSE); + + return; + +} /* kalP2PGOStationUpdate */ + +#if (CFG_SUPPORT_DFS_MASTER == 1) +VOID kalP2PRddDetectUpdate(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRoleIndex) +{ + DBGLOG(INIT, INFO, "Radar Detection event\n"); + + do { + if (prGlueInfo == NULL) { + ASSERT(FALSE); + break; + } + + if (prGlueInfo->prP2PInfo[ucRoleIndex]->chandef == NULL) { + ASSERT(FALSE); + break; + } + + /* cac start disable for next cac slot if enable in dfs channel */ + prGlueInfo->prP2PInfo[ucRoleIndex]->prWdev->cac_started = FALSE; + DBGLOG(INIT, INFO, "kalP2PRddDetectUpdate: Update to OS\n"); + cfg80211_radar_event(prGlueInfo->prP2PInfo[ucRoleIndex]->prWdev->wiphy, + prGlueInfo->prP2PInfo[ucRoleIndex]->chandef, GFP_KERNEL); + DBGLOG(INIT, INFO, "kalP2PRddDetectUpdate: Update to OS Done\n"); + + netif_device_detach(prGlueInfo-> + prP2PInfo[ucRoleIndex]->prDevHandler); + prGlueInfo->prP2PInfo[ucRoleIndex]->fgIsNetDevDetach = TRUE; + + } while (FALSE); + +} /* kalP2PRddDetectUpdate */ + +VOID kalP2PCacFinishedUpdate(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRoleIndex) +{ + DBGLOG(INIT, INFO, "CAC Finished event\n"); + + if (prGlueInfo == NULL) + return; + + if (prGlueInfo->prP2PInfo[ucRoleIndex]->chandef == NULL) + return; + + DBGLOG(INIT, INFO, "kalP2PCacFinishedUpdate: Update to OS\n"); +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE + cfg80211_cac_event(prGlueInfo->prP2PInfo[ucRoleIndex]->prDevHandler, + prGlueInfo->prP2PInfo[ucRoleIndex]->chandef, + NL80211_RADAR_CAC_FINISHED, GFP_KERNEL); +#else + cfg80211_cac_event(prGlueInfo->prP2PInfo[ucRoleIndex]->prDevHandler, + NL80211_RADAR_CAC_FINISHED, GFP_KERNEL); +#endif + DBGLOG(INIT, INFO, "kalP2PCacFinishedUpdate: Update to OS Done\n"); +} /* kalP2PRddDetectUpdate */ +#endif + +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; + struct wiphy *wiphy = (struct wiphy *) NULL; + UINT_32 u4TblSize = 0, u4Idx = 0; + + if ((prP2pInfo == NULL) || (prChannelInfo == NULL)) + return NULL; + + wiphy = prP2pInfo->prWdev->wiphy; + + do { + + switch (prChannelInfo->eBand) { + case BAND_2G4: + prTargetChannelEntry = wiphy->bands[KAL_BAND_2GHZ]->channels; + u4TblSize = wiphy->bands[KAL_BAND_2GHZ]->n_channels; + break; + case BAND_5G: + prTargetChannelEntry = wiphy->bands[KAL_BAND_5GHZ]->channels; + u4TblSize = wiphy->bands[KAL_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 */ + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + +/*----------------------------------------------------------------------------*/ +/*! +* \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, + IN UINT_8 ucRoleIndex) +{ + UINT_8 aucNullAddr[] = NULL_MAC_ADDR; + BOOLEAN fgIsValid = FALSE; + UINT_32 i; + + ASSERT(prGlueInfo); + /*ASSERT(prGlueInfo->prP2PInfo[ucRoleIndex]);*/ + + + /*if only one ap mode register, prGlueInfo->prP2PInfo[1] would be null*/ + if (!prGlueInfo->prP2PInfo[ucRoleIndex]) + return fgIsValid; + + + if (fgIsblock) { + for (i = 0; i < P2P_MAXIMUM_CLIENT_COUNT; i++) { + if (UNEQUAL_MAC_ADDR(rbssid, aucNullAddr)) { + if (UNEQUAL_MAC_ADDR(&(prGlueInfo->prP2PInfo[ucRoleIndex]->aucblackMACList[i]), + rbssid)) { + if (EQUAL_MAC_ADDR(&(prGlueInfo->prP2PInfo[ucRoleIndex]->aucblackMACList[i]), + aucNullAddr)) { + COPY_MAC_ADDR(&(prGlueInfo->prP2PInfo[ucRoleIndex] + ->aucblackMACList[i]), rbssid); + fgIsValid = FALSE; + return fgIsValid; + } + } + } + } + } else { + for (i = 0; i < P2P_MAXIMUM_CLIENT_COUNT; i++) { + if (EQUAL_MAC_ADDR(&(prGlueInfo->prP2PInfo[ucRoleIndex]->aucblackMACList[i]), rbssid)) { + COPY_MAC_ADDR(&(prGlueInfo->prP2PInfo[ucRoleIndex]->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, IN UINT_8 ucRoleIndex) +{ + UINT_8 aucNullAddr[] = NULL_MAC_ADDR; + BOOLEAN fgIsExsit = FALSE; + UINT_32 i; + + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo[ucRoleIndex]); + + for (i = 0; i < P2P_MAXIMUM_CLIENT_COUNT; i++) { + if (UNEQUAL_MAC_ADDR(rbssid, aucNullAddr)) { + if (EQUAL_MAC_ADDR(&(prGlueInfo->prP2PInfo[ucRoleIndex]->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, IN UINT_8 ucRoleIndex) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo[ucRoleIndex]); + + if (u4MaxClient == 0 || prGlueInfo->prP2PInfo[ucRoleIndex]->ucMaxClients >= P2P_MAXIMUM_CLIENT_COUNT) + prGlueInfo->prP2PInfo[ucRoleIndex]->ucMaxClients = P2P_MAXIMUM_CLIENT_COUNT; + else + prGlueInfo->prP2PInfo[ucRoleIndex]->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, IN UINT_8 ucRoleIndex) +{ + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo[ucRoleIndex]); + + if (prGlueInfo->prP2PInfo[ucRoleIndex]->ucMaxClients) { + if ((UINT_8) u4NumClient > prGlueInfo->prP2PInfo[ucRoleIndex]->ucMaxClients) + return TRUE; + else + return FALSE; + } + + return FALSE; +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_proc.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_proc.c new file mode 100644 index 0000000000000..e663e2c6bfa3a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_proc.c @@ -0,0 +1,2633 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_proc.c#2 +*/ + +/*! \file "gl_proc.c" +* \brief This file defines the interface which can interact with users in /proc fs. +* +* Detail description. +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" +#include "gl_os.h" +#include "gl_kal.h" +#include "debug.h" +#include "wlan_lib.h" +#include "debug.h" +#include "wlan_oid.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define PROC_MCR_ACCESS "mcr" + +#ifdef CFG_SUPPORT_DUAL_CARD_DUAL_DRIVER_B +#define PROC_ROOT_NAME "wlanb" +#else +#define PROC_ROOT_NAME "wlan" +#endif + +#if CFG_SUPPORT_DEBUG_FS +#define PROC_ROAM_PARAM "roam_param" +#define PROC_COUNTRY "country" +#endif +#define PROC_DRV_STATUS "status" +#define PROC_RX_STATISTICS "rx_statistics" +#define PROC_TX_STATISTICS "tx_statistics" +#define PROC_DBG_LEVEL_NAME "dbg_level" +#define PROC_DRIVER_CMD "driver" +#define PROC_CFG "cfg" +#define PROC_EFUSE_DUMP "efuse_dump" +#if CFG_SUPPORT_CSI +#define PROC_CSI_DATA_NAME "csi_data" +#endif + +#define PROC_GET_TXPWR_TBL "get_txpwr_tbl" + +#if CFG_DISCONN_DEBUG_FEATURE +#define PROC_DISCONN_INFO "disconn_info" +#endif + + +#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 +#define PROC_UID_SHELL 2000 +#define PROC_GID_WIFI 1010 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +struct PROC_CSI_FORMAT_T { + UINT_8 ucMagicNum; + UINT_8 ucCsiType; + UINT_16 u2Length; + UINT_64 u8TimeStamp; + INT_8 cRssi; + UINT_8 ucSNR; +} __KAL_ATTRIB_PACKED__; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static P_GLUE_INFO_T g_prGlueInfo_proc; +static UINT_32 u4McrOffset; +static struct proc_dir_entry *gprProcRoot; +static UINT_8 aucDbModuleName[][PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN] = { + "INIT", "HAL", "INTR", "REQ", "TX", "RX", "RFTEST", "EMU", "SW1", "SW2", + "SW3", "SW4", "HEM", "AIS", "RLM", "MEM", "CNM", "RSN", "BSS", "SCN", + "SAA", "AAA", "P2P", "QM", "SEC", "BOW", "WAPI", "ROAMING", "TDLS", "PF", + "OID", "NIC" +}; +/* This buffer could be overwrite by any proc commands */ +static UINT_8 g_aucProcBuf[3000]; + +/* This u32 is only for DriverCmdRead/Write, should not be used by other function */ +static INT_32 g_i4NextDriverReadLen; +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define GET_VARNAME(var) #var + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#if CFG_SUPPORT_CSI +static int procCSIDataOpen(struct inode *n, struct file *f) +{ + struct CSI_INFO_T *prCSIInfo = NULL; + + if (g_prGlueInfo_proc && g_prGlueInfo_proc->prAdapter) { + prCSIInfo = &(g_prGlueInfo_proc->prAdapter->rCSIInfo); + prCSIInfo->bIncomplete = FALSE; + } + + return 0; +} + +static int procCSIDataRelease(struct inode *n, struct file *f) +{ + struct CSI_INFO_T *prCSIInfo = NULL; + + if (g_prGlueInfo_proc && g_prGlueInfo_proc->prAdapter) { + prCSIInfo = &(g_prGlueInfo_proc->prAdapter->rCSIInfo); + prCSIInfo->bIncomplete = FALSE; + } + + return 0; +} + +static ssize_t procCSIDataPrepare( + UINT_8 *buf, + struct CSI_INFO_T *prCSIInfo, + struct CSI_DATA_T *prCSIData) +{ + INT_32 i4Pos = 0; + UINT_8 *tmpBuf = buf; + UINT_16 u2DataSize = prCSIData->u2DataCount * sizeof(INT_16); + UINT_16 u2Rsvd1Size = prCSIData->ucRsvd1Cnt * sizeof(INT_32); + UINT_16 u2TotalCSISize = 0; + enum ENUM_CSI_MODULATION_BW_TYPE_T eModulationType = CSI_TYPE_CCK_BW20; + + if (prCSIData->ucBw == 0) + eModulationType = prCSIData->bIsCck ? + CSI_TYPE_CCK_BW20 : CSI_TYPE_OFDM_BW20; + else if (prCSIData->ucBw == 1) + eModulationType = CSI_TYPE_OFDM_BW40; + else if (prCSIData->ucBw == 2) + eModulationType = CSI_TYPE_OFDM_BW80; + + put_unaligned(0xAC, (tmpBuf + i4Pos)); + i4Pos++; + + u2TotalCSISize = u2DataSize * 2 + + (CSI_DATA_TLV_TAG_NUM - 4) * 3 + + 26; + + if (prCSIInfo->ucValue1[CSI_CONFIG_INFO] & CSI_INFO_RSVD1) + u2TotalCSISize += u2Rsvd1Size * 2 + 4 + 3 * 3; + + if (prCSIInfo->ucValue1[CSI_CONFIG_INFO] & CSI_INFO_RSVD2) + u2TotalCSISize += 4; + + put_unaligned(u2TotalCSISize, (UINT_16 *) (tmpBuf + i4Pos)); + i4Pos += 2; + + put_unaligned(CSI_DATA_VER, (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos++; + put_unaligned(1, (UINT_16 *) (tmpBuf + i4Pos)); + i4Pos += 2; + put_unaligned(0x1, (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos++; + + put_unaligned(CSI_DATA_TYPE, (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos++; + put_unaligned(1, (UINT_16 *) (tmpBuf + i4Pos)); + i4Pos += 2; + put_unaligned(eModulationType, (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos++; + + put_unaligned(CSI_DATA_TS, (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos++; + put_unaligned(8, (UINT_16 *) (tmpBuf + i4Pos)); + i4Pos += 2; + put_unaligned(prCSIData->u8TimeStamp, (UINT_64 *) (tmpBuf + i4Pos)); + i4Pos += 8; + + put_unaligned(CSI_DATA_RSSI, (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos++; + put_unaligned(1, (UINT_16 *) (tmpBuf + i4Pos)); + i4Pos += 2; + put_unaligned(prCSIData->cRssi, (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos++; + + put_unaligned(CSI_DATA_SNR, (tmpBuf + i4Pos)); + i4Pos++; + put_unaligned(1, (UINT_16 *) (tmpBuf + i4Pos)); + i4Pos += 2; + put_unaligned(prCSIData->ucSNR, (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos++; + + put_unaligned(CSI_DATA_DBW, (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos++; + put_unaligned(1, (UINT_16 *) (tmpBuf + i4Pos)); + i4Pos += 2; + put_unaligned(prCSIData->ucDataBw, (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos++; + + put_unaligned(CSI_DATA_CH_IDX, (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos++; + put_unaligned(1, (UINT_16 *) (tmpBuf + i4Pos)); + i4Pos += 2; + put_unaligned(prCSIData->ucPrimaryChIdx, (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos++; + + put_unaligned(CSI_DATA_TA, (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos++; + put_unaligned(MAC_ADDR_LEN, (UINT_16 *) (tmpBuf + i4Pos)); + i4Pos += 2; + kalMemCopy((tmpBuf + i4Pos), prCSIData->aucTA, MAC_ADDR_LEN); + i4Pos += MAC_ADDR_LEN; + + put_unaligned(CSI_DATA_EXTRA_INFO, (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos++; + put_unaligned(4, (UINT_16 *) (tmpBuf + i4Pos)); + i4Pos += 2; + put_unaligned(prCSIData->u4ExtraInfo, (UINT_32 *) (tmpBuf + i4Pos)); + i4Pos += sizeof(UINT_32); + + put_unaligned(CSI_DATA_I, (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos++; + put_unaligned(u2DataSize, (UINT_16 *) (tmpBuf + i4Pos)); + i4Pos += 2; + kalMemCopy((tmpBuf + i4Pos), prCSIData->ac2IData, u2DataSize); + i4Pos += u2DataSize; + + put_unaligned(CSI_DATA_Q, (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos++; + put_unaligned(u2DataSize, (UINT_16 *) (tmpBuf + i4Pos)); + i4Pos += 2; + kalMemCopy((tmpBuf + i4Pos), prCSIData->ac2QData, u2DataSize); + i4Pos += u2DataSize; + + if (prCSIInfo->ucValue1[CSI_CONFIG_INFO] & CSI_INFO_RSVD1) { + put_unaligned(CSI_DATA_RSVD1, (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos++; + put_unaligned(u2Rsvd1Size, (UINT_16 *) (tmpBuf + i4Pos)); + i4Pos += 2; + kalMemCopy((tmpBuf + i4Pos), + prCSIData->ai4Rsvd1, + u2Rsvd1Size); + i4Pos += u2Rsvd1Size; + + put_unaligned(CSI_DATA_RSVD2, (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos++; + put_unaligned(u2Rsvd1Size, (UINT_16 *) (tmpBuf + i4Pos)); + i4Pos += 2; + kalMemCopy((tmpBuf + i4Pos), + prCSIData->au4Rsvd2, + u2Rsvd1Size); + i4Pos += u2Rsvd1Size; + + put_unaligned(CSI_DATA_RSVD3, (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos++; + put_unaligned(sizeof(INT_32), (INT_16 *) (tmpBuf + i4Pos)); + i4Pos += 2; + put_unaligned(prCSIData->i4Rsvd3, + (INT_32 *) (tmpBuf + i4Pos)); + i4Pos += sizeof(INT_32); + } + + if (prCSIInfo->ucValue1[CSI_CONFIG_INFO] & CSI_INFO_RSVD2) { + put_unaligned(CSI_DATA_RSVD4, (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos++; + put_unaligned(sizeof(UINT_8), (INT_16 *) (tmpBuf + i4Pos)); + i4Pos += 2; + put_unaligned(prCSIData->ucRsvd4, (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos += sizeof(UINT_8); + } + + put_unaligned(CSI_DATA_TX_IDX, (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos++; + put_unaligned(sizeof(UINT_8), (INT_16 *) (tmpBuf + i4Pos)); + i4Pos += 2; + put_unaligned(prCSIInfo->ucValue1[CSI_CONFIG_TX_PATH], + (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos += sizeof(UINT_8); + + put_unaligned(CSI_DATA_RX_IDX, (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos++; + put_unaligned(sizeof(UINT_8), (INT_16 *) (tmpBuf + i4Pos)); + i4Pos += 2; + put_unaligned(prCSIInfo->ucValue1[CSI_CONFIG_WF], + (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos += sizeof(UINT_8); + + put_unaligned(CSI_DATA_FRAME_MODE, (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos++; + put_unaligned(sizeof(UINT_8), (INT_16 *) (tmpBuf + i4Pos)); + i4Pos += 2; + put_unaligned(prCSIData->ucRxMode, + (UINT_8 *) (tmpBuf + i4Pos)); + i4Pos += sizeof(UINT_8); + + + return i4Pos; +} + +struct CSI_DATA_T rTmpCSIData; +static ssize_t procCSIDataRead(struct file *filp, + char __user *buf, size_t count, loff_t *f_pos) +{ + UINT_8 *temp = &g_aucProcBuf[0]; + UINT_32 u4CopySize = 0; + UINT_32 u4StartIdx = 0; + INT_32 i4Pos = 0; + struct CSI_INFO_T *prCSIInfo = NULL; + + if (g_prGlueInfo_proc && g_prGlueInfo_proc->prAdapter) + prCSIInfo = &(g_prGlueInfo_proc->prAdapter->rCSIInfo); + else + return 0; + + if (prCSIInfo->bIncomplete == FALSE) { + + wait_event_interruptible(prCSIInfo->waitq, + prCSIInfo->u4CSIBufferUsed != 0); + + /* + * No older CSI data in buffer waiting for reading out, so prepare a new one + * for reading. + */ + if (wlanPopCSIData(g_prGlueInfo_proc->prAdapter, + &rTmpCSIData)) + i4Pos = procCSIDataPrepare(temp, + prCSIInfo, &rTmpCSIData); + + /* The frist run of reading the CSI data */ + u4StartIdx = 0; + if (i4Pos > count) { + u4CopySize = count; + prCSIInfo->u4RemainingDataSize = i4Pos - count; + prCSIInfo->u4CopiedDataSize = count; + prCSIInfo->bIncomplete = TRUE; + } else { + u4CopySize = i4Pos; + } + } else { + /* Reading the remaining CSI data in the buffer */ + + u4StartIdx = prCSIInfo->u4CopiedDataSize; + if (prCSIInfo->u4RemainingDataSize > count) { + u4CopySize = count; + prCSIInfo->u4RemainingDataSize -= count; + prCSIInfo->u4CopiedDataSize += count; + } else { + u4CopySize = prCSIInfo->u4RemainingDataSize; + prCSIInfo->bIncomplete = FALSE; + } + } + + if (copy_to_user(buf, &g_aucProcBuf[u4StartIdx], u4CopySize)) { + DBGLOG(INIT, ERROR, "copy to user failed\n"); + return -EFAULT; + } + + *f_pos += u4CopySize; + + return (ssize_t)u4CopySize; +} +#endif + +static ssize_t procDbgLevelRead(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + UINT_8 *temp = &g_aucProcBuf[0]; + UINT_32 u4CopySize = 0; + UINT_16 i; + UINT_16 u2ModuleNum = 0; + UINT_32 u4BufMax = sizeof(g_aucProcBuf); + INT_32 i4Pos = 0; + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0) + return 0; + + i4Pos = scnprintf(temp, (sizeof(g_aucProcBuf) - i4Pos), + "\nERROR|WARN|STATE|EVENT|TRACE|INFO|LOUD|TEMP\n" + "bit0 |bit1|bit2 |bit3 |bit4 |bit5|bit6|bit7\n\n" + "Debug Module\tIndex\tLevel\tDebug Module\tIndex\tLevel\n\n"); + + u2ModuleNum = (sizeof(aucDbModuleName) / PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN) & 0xfe; + for (i = 0; i < u2ModuleNum; i += 2) + i4Pos += scnprintf((temp + i4Pos), (u4BufMax - i4Pos), + "DBG_%s_IDX\t(0x%02x):\t0x%02x\tDBG_%s_IDX\t(0x%02x):\t0x%02x\n", + &aucDbModuleName[i][0], i, aucDebugModule[i], + &aucDbModuleName[i+1][0], i+1, aucDebugModule[i+1]); + + if ((sizeof(aucDbModuleName) / PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN) & 0x1) + i4Pos += scnprintf((temp + i4Pos), (u4BufMax - i4Pos), + "DBG_%s_IDX\t(0x%02x):\t0x%02x\n", + &aucDbModuleName[u2ModuleNum][0], u2ModuleNum, aucDebugModule[u2ModuleNum]); + + u4CopySize = i4Pos; + if (u4CopySize > count) + u4CopySize = count; + if (copy_to_user(buf, g_aucProcBuf, u4CopySize)) { + DBGLOG(INIT, ERROR, "copy to user failed\n"); + return -EFAULT; + } + + *f_pos += u4CopySize; + return (ssize_t)u4CopySize; +} + +#if WLAN_INCLUDE_PROC +#if CFG_SUPPORT_EASY_DEBUG + +static void *procEfuseDump_start(struct seq_file *s, loff_t *pos) +{ + static unsigned long counter; + + if (*pos == 0) + counter = *pos; /* read file init */ + + if (counter >= EFUSE_ADDR_MAX) + return NULL; + return &counter; +} +static void *procEfuseDump_next(struct seq_file *s, void *v, loff_t *pos) +{ + unsigned long *tmp_v = (unsigned long *)v; + + (*tmp_v) += EFUSE_BLOCK_SIZE; + + if (*tmp_v >= EFUSE_ADDR_MAX) + return NULL; + return tmp_v; +} +static void procEfuseDump_stop(struct seq_file *s, void *v) +{ + /* nothing to do, we use a static value in start() */ +} +static int procEfuseDump_show(struct seq_file *s, void *v) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo; + UINT_32 idx_addr, idx_value; + PARAM_CUSTOM_ACCESS_EFUSE_T rAccessEfuseInfo = {}; + + prGlueInfo = g_prGlueInfo_proc; + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + idx_addr = *(loff_t *)v; + rAccessEfuseInfo.u4Address = (idx_addr / EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfo, + sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T), TRUE, TRUE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + seq_printf(s, "efuse read fail (0x%03X)\n", rAccessEfuseInfo.u4Address); + return 0; + } + + for (idx_value = 0; idx_value < EFUSE_BLOCK_SIZE; idx_value++) + seq_printf(s, "0x%03X=0x%02X\n" + , rAccessEfuseInfo.u4Address+idx_value + , prGlueInfo->prAdapter->aucEepromVaule[idx_value]); + return 0; +#else + seq_puts(s, "efuse ops is invalid\n"); + return -EPERM; /* return negative value to stop read process */ +#endif +} +static int procEfuseDumpOpen(struct inode *inode, struct file *file) +{ + static const struct seq_operations procEfuseDump_ops = { + .start = procEfuseDump_start, + .next = procEfuseDump_next, + .stop = procEfuseDump_stop, + .show = procEfuseDump_show + }; + + return seq_open(file, &procEfuseDump_ops); +} + + +static ssize_t procCfgRead(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + UINT_8 *temp = &g_aucProcBuf[0]; + UINT_32 u4CopySize = 0; + UINT_16 i; + INT_32 i4Pos = 0; + UINT_32 u4BufMax = sizeof(g_aucProcBuf); + +#define BUFFER_RESERVE_BYTE 50 + + P_GLUE_INFO_T prGlueInfo; + + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + P_ADAPTER_T prAdapter; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(gPrDev)); + + if (!prGlueInfo) { + DBGLOG(INIT, ERROR, "procCfgRead prGlueInfo is NULL?\n"); + return -EFAULT; + } + + prAdapter = prGlueInfo->prAdapter; + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0) + return 0; + + i4Pos = scnprintf(temp, (sizeof(g_aucProcBuf) - i4Pos), "\nDUMP CONFIGURATION :\n" + " OR \n" + "'D': driver part current setting\n" + "===================================\n"); + + for (i = 0; i < WLAN_CFG_ENTRY_NUM_MAX; i++) { + prWlanCfgEntry = wlanCfgGetEntryByIndex(prAdapter, i, 0); + + if ((!prWlanCfgEntry) || (prWlanCfgEntry->aucKey[0] == '\0')) + break; + + i4Pos += scnprintf((temp + i4Pos), (u4BufMax - i4Pos), + "%s|%s\n", prWlanCfgEntry->aucKey, prWlanCfgEntry->aucValue); + + if (i4Pos > (sizeof(g_aucProcBuf)-BUFFER_RESERVE_BYTE)) + break; + } + + for (i = 0; i < WLAN_CFG_REC_ENTRY_NUM_MAX; i++) { + prWlanCfgEntry = wlanCfgGetEntryByIndex(prAdapter, i, 1); + + if ((!prWlanCfgEntry) || (prWlanCfgEntry->aucKey[0] == '\0')) + break; + + i4Pos += scnprintf((temp + i4Pos), (u4BufMax - i4Pos), + "D:%s|%s\n", prWlanCfgEntry->aucKey, prWlanCfgEntry->aucValue); + + if (i4Pos > (sizeof(g_aucProcBuf)-BUFFER_RESERVE_BYTE)) + break; + } + + u4CopySize = i4Pos; + if (u4CopySize > count) + u4CopySize = count; + if (copy_to_user(buf, g_aucProcBuf, u4CopySize)) { + DBGLOG(INIT, ERROR, "copy to user failed\n"); + return -EFAULT; + } + + *f_pos += u4CopySize; + return (ssize_t)u4CopySize; + + +} + + +static ssize_t procCfgWrite(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + + /* UINT_32 u4DriverCmd, u4DriverValue; + *UINT_8 *temp = &g_aucProcBuf[0]; + */ + INT_32 CopySize = sizeof(g_aucProcBuf); + P_GLUE_INFO_T prGlueInfo; + PUINT_8 pucTmp; + INT_32 i4Pos = 0; + /* PARAM_CUSTOM_P2P_SET_STRUCT_T rSetP2P; */ + + + kalMemSet(g_aucProcBuf, 0, CopySize); + + pucTmp = g_aucProcBuf; + i4Pos = scnprintf(pucTmp, sizeof(g_aucProcBuf), "%s ", "set_cfg"); + pucTmp += i4Pos; + CopySize -= i4Pos; + + if (CopySize >= (count+1)) + CopySize = count; + else + CopySize -= 1; + + if ((CopySize < 0) || (copy_from_user(pucTmp, buffer, CopySize))) { + DBGLOG(INIT, ERROR, "error of copy from user\n"); + return -EFAULT; + } + g_aucProcBuf[CopySize] = '\0'; + + + prGlueInfo = g_prGlueInfo_proc; + /* if g_i4NextDriverReadLen >0, + * the content for next DriverCmdRead will be in : + * g_aucProcBuf with length : g_i4NextDriverReadLen + */ + g_i4NextDriverReadLen = priv_driver_set_cfg(prGlueInfo->prDevHandler, + g_aucProcBuf, sizeof(g_aucProcBuf)); + + return count; + +} + +static ssize_t procDriverCmdRead(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + /* DriverCmd read should only be executed right after a DriverCmd write + * because content buffer 'g_aucProcBuf' is a global buffer for all proc command, + * otherwise , the content could be overwrite by other proc command + */ + UINT_32 u4CopySize = 0; + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0) + return 0; + + if (g_i4NextDriverReadLen > 0) /* Detect content to show */ + u4CopySize = g_i4NextDriverReadLen; + if (copy_to_user(buf, g_aucProcBuf, u4CopySize)) { + DBGLOG(INIT, ERROR, "copy to user failed\n"); + return -EFAULT; + } + g_i4NextDriverReadLen = 0; + + *f_pos += u4CopySize; + return (ssize_t)u4CopySize; +} + + + +static ssize_t procDriverCmdWrite(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + +/* UINT_32 u4DriverCmd, u4DriverValue; +* UINT_8 *temp = &g_aucProcBuf[0]; +*/ + P_GLUE_INFO_T prGlueInfo; +/* PARAM_CUSTOM_P2P_SET_STRUCT_T rSetP2P; */ + + + kalMemSet(g_aucProcBuf, 0, sizeof(g_aucProcBuf)); + + if (count > sizeof(g_aucProcBuf)-1) { + DBGLOG(INIT, ERROR, + "input count %zu over local buffer size %zu\n", + count, sizeof(g_aucProcBuf)); + return 0; + } + + if (copy_from_user(g_aucProcBuf, buffer, count)) { + DBGLOG(INIT, ERROR, "error of copy from user\n"); + return -EFAULT; + } + g_aucProcBuf[count] = '\0'; + + + prGlueInfo = g_prGlueInfo_proc; + /* if g_i4NextDriverReadLen >0, + * the content for next DriverCmdRead will be in : + * g_aucProcBuf with length : g_i4NextDriverReadLen + */ + g_i4NextDriverReadLen = priv_driver_cmds(prGlueInfo->prDevHandler, + g_aucProcBuf, sizeof(g_aucProcBuf)); + + return count; +} + +#endif +#endif + +static ssize_t procDbgLevelWrite(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + UINT_32 u4NewDbgModule, u4NewDbgLevel; + UINT_8 *temp = &g_aucProcBuf[0]; + + kalMemSet(g_aucProcBuf, 0, sizeof(g_aucProcBuf)); + + if (count > sizeof(g_aucProcBuf)-1) { + DBGLOG(INIT, ERROR, + "input count %zu over local buffer size %zu\n", + count, sizeof(g_aucProcBuf)); + return 0; + } + + if (copy_from_user(g_aucProcBuf, buffer, count)) { + DBGLOG(INIT, ERROR, "error of copy from user\n"); + return -EFAULT; + } + g_aucProcBuf[count] = '\0'; + +#if CFG_CHIP_RESET_SUPPORT + if (temp[0] == 'R') { + P_GLUE_INFO_T prGlueInfo = NULL; + + prGlueInfo = g_prGlueInfo_proc; + DBGLOG(RSN, ERROR, "WIFI trigger reset!!\n"); + glResetTrigger(prGlueInfo->prAdapter); + temp[0] = 'X'; + } +#endif + + while (temp) { + if (sscanf(temp, "0x%x:0x%x", &u4NewDbgModule, &u4NewDbgLevel) != 2) { + DBGLOG(INIT, ERROR, "debug module and debug level should be one byte in length\n"); + break; + } + if (u4NewDbgModule == 0xFF) { + UINT_8 i = 0; + + for (; i < DBG_MODULE_NUM; i++) + aucDebugModule[i] = u4NewDbgLevel & DBG_CLASS_MASK; + + break; + } + if (u4NewDbgModule >= DBG_MODULE_NUM) { + DBGLOG(INIT, ERROR, "debug module index should less than %d\n", DBG_MODULE_NUM); + break; + } + aucDebugModule[u4NewDbgModule] = u4NewDbgLevel & DBG_CLASS_MASK; + temp = kalStrChr(temp, ','); + if (!temp) + break; + temp++; /* skip ',' */ + } + return count; +} + +#define TXPWR_TABLE_ENTRY(_siso_mcs, _cdd_mcs, _mimo_mcs, _idx) \ +{ \ + .mcs[STREAM_SISO] = _siso_mcs, \ + .mcs[STREAM_CDD] = _cdd_mcs, \ + .mcs[STREAM_MIMO] = _mimo_mcs, \ + .idx = (_idx), \ +} + +static struct txpwr_table_entry dsss[] = { + TXPWR_TABLE_ENTRY("DSSS1", "", "", PWR_DSSS_CCK), + TXPWR_TABLE_ENTRY("DSSS2", "", "", PWR_DSSS_CCK), + TXPWR_TABLE_ENTRY("CCK5", "", "", PWR_DSSS_BPKS), + TXPWR_TABLE_ENTRY("CCK11", "", "", PWR_DSSS_BPKS), +}; + +static struct txpwr_table_entry ofdm[] = { + TXPWR_TABLE_ENTRY("OFDM6", "OFDM6", "", PWR_OFDM_BPSK), + TXPWR_TABLE_ENTRY("OFDM9", "OFDM9", "", PWR_OFDM_BPSK), + TXPWR_TABLE_ENTRY("OFDM12", "OFDM12", "", PWR_OFDM_QPSK), + TXPWR_TABLE_ENTRY("OFDM18", "OFDM18", "", PWR_OFDM_QPSK), + TXPWR_TABLE_ENTRY("OFDM24", "OFDM24", "", PWR_OFDM_16QAM), + TXPWR_TABLE_ENTRY("OFDM36", "OFDM36", "", PWR_OFDM_16QAM), + TXPWR_TABLE_ENTRY("OFDM48", "OFDM48", "", PWR_OFDM_48Mbps), + TXPWR_TABLE_ENTRY("OFDM54", "OFDM54", "", PWR_OFDM_54Mbps), +}; + +static struct txpwr_table_entry ht[] = { + TXPWR_TABLE_ENTRY("MCS0", "MCS0", "MCS8", PWR_HT_BPSK), + TXPWR_TABLE_ENTRY("MCS1", "MCS1", "MCS9", PWR_HT_QPSK), + TXPWR_TABLE_ENTRY("MCS2", "MCS2", "MCS10", PWR_HT_QPSK), + TXPWR_TABLE_ENTRY("MCS3", "MCS3", "MCS11", PWR_HT_16QAM), + TXPWR_TABLE_ENTRY("MCS4", "MCS4", "MCS12", PWR_HT_16QAM), + TXPWR_TABLE_ENTRY("MCS5", "MCS5", "MCS13", PWR_HT_MCS5), + TXPWR_TABLE_ENTRY("MCS6", "MCS6", "MCS14", PWR_HT_MCS6), + TXPWR_TABLE_ENTRY("MCS7", "MCS7", "MCS15", PWR_HT_MCS7), +}; + +static struct txpwr_table_entry vht[] = { + TXPWR_TABLE_ENTRY("MCS0", "MCS0", "MCS0", PWR_VHT20_BPSK), + TXPWR_TABLE_ENTRY("MCS1", "MCS1", "MCS1", PWR_VHT20_QPSK), + TXPWR_TABLE_ENTRY("MCS2", "MCS2", "MCS2", PWR_VHT20_QPSK), + TXPWR_TABLE_ENTRY("MCS3", "MCS3", "MCS3", PWR_VHT20_16QAM), + TXPWR_TABLE_ENTRY("MCS4", "MCS4", "MCS4", PWR_VHT20_16QAM), + TXPWR_TABLE_ENTRY("MCS5", "MCS5", "MCS5", PWR_VHT20_64QAM), + TXPWR_TABLE_ENTRY("MCS6", "MCS6", "MCS6", PWR_VHT20_64QAM), + TXPWR_TABLE_ENTRY("MCS7", "MCS7", "MCS7", PWR_VHT20_MCS7), + TXPWR_TABLE_ENTRY("MCS8", "MCS8", "MCS8", PWR_VHT20_MCS8), + TXPWR_TABLE_ENTRY("MCS9", "MCS9", "MCS9", PWR_VHT20_MCS9), +}; + +static struct txpwr_table txpwr_tables[] = { + {"Legacy", dsss, ARRAY_SIZE(dsss)}, + {"11g", ofdm, ARRAY_SIZE(ofdm)}, + {"11a", ofdm, ARRAY_SIZE(ofdm)}, + {"HT20", ht, ARRAY_SIZE(ht)}, + {"HT40", ht, ARRAY_SIZE(ht)}, + {"VHT20", vht, ARRAY_SIZE(vht)}, + {"VHT40", vht, ARRAY_SIZE(vht)}, + {"VHT80", vht, ARRAY_SIZE(vht)}, +}; + +#define TMP_SZ (512) +#define CDD_PWR_OFFSET (6) +#define TXPWR_DUMP_SZ (8192) +void print_txpwr_tbl(struct txpwr_table *txpwr_tbl, unsigned char ch, + unsigned char *tx_pwr[], char pwr_offset[], + char *stream_buf[], unsigned int stream_pos[]) +{ + struct txpwr_table_entry *tmp_tbl = txpwr_tbl->tables; + unsigned int idx, pwr_idx, stream_idx; + char pwr[TXPWR_TBL_NUM] = {0}, tmp_pwr = 0; + char prefix[5], tmp[4]; + char *buf = NULL; + unsigned int *pos = NULL; + int i; + + for (i = 0; i < txpwr_tbl->n_tables; i++) { + idx = tmp_tbl[i].idx; + + for (pwr_idx = 0; pwr_idx < TXPWR_TBL_NUM; pwr_idx++) { + if (!tx_pwr[pwr_idx]) { + DBGLOG(REQ, WARN, + "Power table[%d] is NULL\n", pwr_idx); + return; + } + pwr[pwr_idx] = tx_pwr[pwr_idx][idx] + + pwr_offset[pwr_idx]; + pwr[pwr_idx] = (pwr[pwr_idx] > MAX_TX_POWER) ? + MAX_TX_POWER : pwr[pwr_idx]; + } + + for (stream_idx = 0; stream_idx < STREAM_NUM; stream_idx++) { + buf = stream_buf[stream_idx]; + pos = &stream_pos[stream_idx]; + + if (tmp_tbl[i].mcs[stream_idx][0] == '\0') + continue; + + switch (stream_idx) { + case STREAM_SISO: + kalStrnCpy(prefix, "siso", sizeof(prefix)); + break; + case STREAM_CDD: + kalStrnCpy(prefix, "cdd", sizeof(prefix)); + break; + case STREAM_MIMO: + kalStrnCpy(prefix, "mimo", sizeof(prefix)); + break; + } + + *pos += kalScnprintf(buf + *pos, TMP_SZ - *pos, + "%s, %d, %s, %s, ", + prefix, ch, + txpwr_tbl->phy_mode, + tmp_tbl[i].mcs[stream_idx]); + + for (pwr_idx = 0; pwr_idx < TXPWR_TBL_NUM; pwr_idx++) { + tmp_pwr = pwr[pwr_idx]; + + tmp_pwr = (tmp_pwr > 0) ? tmp_pwr : 0; + + if (pwr_idx + 1 == TXPWR_TBL_NUM) + kalStrnCpy(tmp, "\n", sizeof(tmp)); + else + kalStrnCpy(tmp, ", ", sizeof(tmp)); + *pos += kalScnprintf(buf + *pos, TMP_SZ - *pos, + "%d.%d%s", + tmp_pwr / 2, + tmp_pwr % 2 * 5, + tmp); + + } + } + } +} + +static ssize_t procGetTxpwrTblRead(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + P_BSS_INFO_T prBssInfo = NULL; + unsigned char ucBssIndex; + P_NETDEV_PRIVATE_GLUE_INFO prNetDevPrivate = NULL; + WLAN_STATUS status; + struct PARAM_CMD_GET_TXPWR_TBL pwr_tbl; + struct POWER_LIMIT *tx_pwr_tbl = pwr_tbl.tx_pwr_tbl; + char *buffer; + unsigned int pos = 0, buf_len = TXPWR_DUMP_SZ, oid_len; + unsigned char i, j; + char *stream_buf[STREAM_NUM] = {NULL}; + unsigned int stream_pos[STREAM_NUM] = {0}; + unsigned char *tx_pwr[TXPWR_TBL_NUM] = {NULL}; + char pwr_offset[TXPWR_TBL_NUM] = {0}; + unsigned char offset = 0; + int ret; + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0) + return 0; + + prGlueInfo = g_prGlueInfo_proc; + if (!prGlueInfo) + return -EFAULT; + prAdapter = prGlueInfo->prAdapter; + prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(gPrDev); + if (prNetDevPrivate->prGlueInfo != prGlueInfo) + return -EFAULT; + ucBssIndex = prNetDevPrivate->ucBssIdx; + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + if (!prBssInfo) + return -EFAULT; + + kalMemZero(&pwr_tbl, sizeof(pwr_tbl)); + + if (prAdapter->rWifiVar.fgDbDcModeEn) + pwr_tbl.ucDbdcIdx = prBssInfo->eDBDCBand; + else + pwr_tbl.ucDbdcIdx = ENUM_BAND_0; + + status = kalIoctl(prGlueInfo, + wlanoidGetTxPwrTbl, + &pwr_tbl, + sizeof(pwr_tbl), TRUE, FALSE, TRUE, &oid_len); + + if (status != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "Query Tx Power Table fail\n"); + return -EINVAL; + } + + buffer = (char *) kalMemAlloc(buf_len, VIR_MEM_TYPE); + if (!buffer) + return -ENOMEM; + + for (i = 0; i < STREAM_NUM; i++) { + stream_buf[i] = (char *) kalMemAlloc(TMP_SZ, VIR_MEM_TYPE); + if (!stream_buf[i]) { + ret = -ENOMEM; + goto out; + } + } + + pos = kalScnprintf(buffer, buf_len, + "\n%s", + "spatial stream, Channel, bw, modulation, "); + pos += kalScnprintf(buffer + pos, buf_len - pos, + "%s\n", + "regulatory limit, board limit, target power"); + + for (i = 0; i < ARRAY_SIZE(txpwr_tables); i++) { + for (j = 0; j < STREAM_NUM; j++) { + kalMemZero(stream_buf[j], TMP_SZ); + stream_pos[j] = 0; + } + + for (j = 0; j < TXPWR_TBL_NUM; j++) { + tx_pwr[j] = NULL; + pwr_offset[j] = 0; + } + + switch (i) { + case DSSS: + if (pwr_tbl.ucCenterCh > 14) + continue; + for (j = 0; j < TXPWR_TBL_NUM; j++) + tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_dsss; + break; + case OFDM_24G: + if (pwr_tbl.ucCenterCh > 14) + continue; + for (j = 0; j < TXPWR_TBL_NUM; j++) + tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_ofdm; + break; + case OFDM_5G: + if (pwr_tbl.ucCenterCh <= 14) + continue; + for (j = 0; j < TXPWR_TBL_NUM; j++) + tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_ofdm; + break; + case HT20: + for (j = 0; j < TXPWR_TBL_NUM; j++) + tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_ht20; + break; + case HT40: + for (j = 0; j < TXPWR_TBL_NUM; j++) + tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_ht40; + break; + case VHT20: + if (pwr_tbl.ucCenterCh <= 14) + continue; + for (j = 0; j < TXPWR_TBL_NUM; j++) + tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_vht20; + break; + case VHT40: + case VHT80: + if (pwr_tbl.ucCenterCh <= 14) + continue; + offset = (i == VHT40) ? + PWR_Vht40_OFFSET : PWR_Vht80_OFFSET; + for (j = 0; j < TXPWR_TBL_NUM; j++) { + tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_vht20; + pwr_offset[j] = + tx_pwr_tbl[j].tx_pwr_vht_OFST[offset]; + /* Covert 7bit 2'complement value to 8bit */ + pwr_offset[j] |= (pwr_offset[j] & BIT(6)) ? + BIT(7) : 0; + } + break; + default: + break; + } + + print_txpwr_tbl(&txpwr_tables[i], pwr_tbl.ucCenterCh, + tx_pwr, pwr_offset, + stream_buf, stream_pos); + + for (j = 0; j < STREAM_NUM; j++) { + pos += kalScnprintf(buffer + pos, buf_len - pos, + "%s", + stream_buf[j]); + } + } + + if (copy_to_user(buf, buffer, pos)) { + DBGLOG(INIT, ERROR, "copy to user failed\n"); + ret = -EFAULT; + goto out; + } + + *f_pos += pos; + ret = pos; +out: + for (i = 0; i < STREAM_NUM; i++) { + if (stream_buf[i]) + kalMemFree(stream_buf[i], VIR_MEM_TYPE, TMP_SZ); + } + kalMemFree(buffer, VIR_MEM_TYPE, buf_len); + return ret; +} + +#if CFG_DISCONN_DEBUG_FEATURE +static INT_32 parseTxRateInfo(IN char *pcBuffer, IN int i4Size, + IN P_TX_VECTOR_BBP_LATCH_T prTxV) +{ + UINT_8 rate, txmode, frmode, sgi, ldpc, nsts, stbc, txpwr; + INT_32 i4BytesWritten = 0; + + rate = TX_VECTOR_GET_TX_RATE(prTxV); + txmode = TX_VECTOR_GET_TX_MODE(prTxV); + frmode = TX_VECTOR_GET_TX_FRMODE(prTxV); + nsts = TX_VECTOR_GET_TX_NSTS(prTxV) + 1; + sgi = TX_VECTOR_GET_TX_SGI(prTxV); + ldpc = TX_VECTOR_GET_TX_LDPC(prTxV); + stbc = TX_VECTOR_GET_TX_STBC(prTxV); + txpwr = TX_VECTOR_GET_TX_PWR(prTxV); + + if (prTxV->u4TxVector1 == 0xFFFFFFFF) { + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%-26s%s%s\n", "Last TX Rate", " = ", "N/A"); + } else { + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%-26s%s", "Last TX Rate", " = "); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf( + pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%s, ", rate < 4 ? + HW_TX_RATE_CCK_STR[rate] : + HW_TX_RATE_CCK_STR[4]); + else if (txmode == TX_RATE_MODE_OFDM) + i4BytesWritten += kalScnprintf( + pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%s, ", hw_rate_ofdm_str(rate)); + else if ((txmode == TX_RATE_MODE_HTMIX) || + (txmode == TX_RATE_MODE_HTGF)) + i4BytesWritten += kalScnprintf( + pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "MCS%d, ", rate); + else + i4BytesWritten += kalScnprintf( + pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "NSS%d_MCS%d, ", nsts, rate); + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%s, ", frmode < 4 ? + HW_TX_RATE_BW[frmode] : HW_TX_RATE_BW[4]); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf( + pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%s, ", rate < 4 ? "LP" : "SP"); + else if (txmode == TX_RATE_MODE_OFDM) + ; + else + i4BytesWritten += kalScnprintf( + pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%s, ", sgi == 0 ? "LGI" : "SGI"); + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%s%s%s\n", txmode < 5 ? + HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5], + stbc ? ", STBC, " : ", ", ldpc == 0 ? "BCC" : "LDPC"); + } + + return i4BytesWritten; +} + +static INT_32 parseRxRateInfo(IN char *pcBuffer, IN int i4Size, + IN P_STA_RECORD_T prStaRec) +{ + UINT_32 txmode, rate, frmode, sgi, nsts, ldpc, stbc, groupid, mu; + INT_32 i4BytesWritten = 0; + UINT_32 u4RxVector0 = 0, u4RxVector1 = 0; + + u4RxVector0 = prStaRec->u4RxVector0; + u4RxVector1 = prStaRec->u4RxVector1; + + txmode = (u4RxVector0 & RX_VT_RX_MODE_MASK) >> RX_VT_RX_MODE_OFFSET; + rate = (u4RxVector0 & RX_VT_RX_RATE_MASK) >> RX_VT_RX_RATE_OFFSET; + frmode = (u4RxVector0 & RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET; + nsts = ((u4RxVector1 & RX_VT_NSTS_MASK) >> RX_VT_NSTS_OFFSET); + stbc = (u4RxVector0 & RX_VT_STBC_MASK) >> RX_VT_STBC_OFFSET; + sgi = u4RxVector0 & RX_VT_SHORT_GI; + ldpc = u4RxVector0 & RX_VT_LDPC; + groupid = (u4RxVector1 & RX_VT_GROUP_ID_MASK) >> RX_VT_GROUP_ID_OFFSET; + + if (groupid && groupid != 63) { + mu = 1; + } else { + mu = 0; + nsts += 1; + } + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%-26s%s", "Last RX Rate", " = "); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%s, ", rate < 4 ? + HW_TX_RATE_CCK_STR[rate] : HW_TX_RATE_CCK_STR[4]); + else if (txmode == TX_RATE_MODE_OFDM) + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%s, ", hw_rate_ofdm_str(rate)); + else if ((txmode == TX_RATE_MODE_HTMIX) || + (txmode == TX_RATE_MODE_HTGF)) + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "MCS%d, ", rate); + else + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "NSS%d_MCS%d, ", nsts, rate); + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%s, ", frmode < 4 ? + HW_TX_RATE_BW[frmode] : HW_TX_RATE_BW[4]); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%s, ", rate < 4 ? "LP" : "SP"); + else if (txmode == TX_RATE_MODE_OFDM) + ; + else + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%s,", sgi == 0 ? "LGI" : "SGI"); + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%s", stbc == 0 ? " " : " STBC, "); + + if (mu) { + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%s, %s, %s (%d)\n", txmode < 5 ? + HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5], + ldpc == 0 ? "BCC" : "LDPC", "MU", groupid); + } else { + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%s, %s\n", txmode < 5 ? + HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5], + ldpc == 0 ? "BCC" : "LDPC"); + } + + return i4BytesWritten; +} + +static INT_32 parseRxRssiInfo(IN char *pcBuffer, IN int i4Size, + IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + INT_32 i4RSSI0 = 0, i4RSSI1 = 0, i4RSSI2 = 0, i4RSSI3; + INT_32 i4BytesWritten = 0; + UINT_32 u4RxVector3 = 0; + + u4RxVector3 = prStaRec->u4RxVector3; + + i4RSSI0 = RCPI_TO_dBm((u4RxVector3 & RX_VT_RCPI0_MASK) + >> RX_VT_RCPI0_OFFSET); + i4RSSI1 = RCPI_TO_dBm((u4RxVector3 & RX_VT_RCPI1_MASK) + >> RX_VT_RCPI1_OFFSET); + + if (prAdapter->rWifiVar.ucNSS > 2) { + i4RSSI2 = RCPI_TO_dBm((u4RxVector3 & RX_VT_RCPI2_MASK) + >> RX_VT_RCPI2_OFFSET); + i4RSSI3 = RCPI_TO_dBm((u4RxVector3 & RX_VT_RCPI3_MASK) + >> RX_VT_RCPI3_OFFSET); + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%-26s%s%d %d %d %d\n", "Last RX Data RSSI", " = ", + i4RSSI0, i4RSSI1, i4RSSI2, i4RSSI3); + } else + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%-26s%s%d %d\n", "Last RX Data RSSI", " = ", + i4RSSI0, i4RSSI1); + + return i4BytesWritten; +} + +static UINT_32 parseRxRespRssiInfo(IN char *pcBuffer, IN int i4Size, + IN P_ADAPTER_T prAdapter, IN P_PARAM_HW_WLAN_INFO_T prHwWlanInfo) +{ + INT_32 i4BytesWritten = 0; + + if (prAdapter->rWifiVar.ucNSS > 2) + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%-26s%s%d %d %d %d\n", "Tx Response RSSI", " = ", + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi0), + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi1), + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi2), + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi3)); + else + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%-26s%s%d %d\n", "Tx Response RSSI", " = ", + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi0), + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi1)); + + return i4BytesWritten; +} + +static INT_32 parseTxPerInfo(IN char *pcBuffer, IN int i4Size, + IN P_PARAM_HW_WLAN_INFO_T prHwWlanInfo, + IN P_PARAM_GET_STA_STATISTICS prQueryStaStatistics) +{ + UINT_32 u4InstantPer; + INT_32 i4BytesWritten = 0; + UINT_8 ucSkipAr; + P_MIB_INFO_STAT_T prMibInfo; + + ucSkipAr = prQueryStaStatistics->ucSkipAr; + prMibInfo = prQueryStaStatistics->rMibInfo; + + if (ucSkipAr) { + u4InstantPer = + (prHwWlanInfo->rWtblTxCounter.u2Rate1TxCnt == 0) ? + (0) : + (1000 * (prHwWlanInfo->rWtblTxCounter.u2Rate1FailCnt) + / (prHwWlanInfo->rWtblTxCounter.u2Rate1TxCnt)); + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%-26s%s%d.%1d%%\n", "instant PER", " = ", + u4InstantPer/10, u4InstantPer%10); + } else { + u4InstantPer = (prQueryStaStatistics->ucPer == 0) ? + (0) : (prQueryStaStatistics->ucPer); + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%-26s%s%d%%\n", "instant PER", " = ", + u4InstantPer); + } + + return i4BytesWritten; +} + +static INT_32 parseRxPerInfo(IN char *pcBuffer, IN int i4Size, + IN P_ADAPTER_T prAdapter, + IN P_PARAM_GET_STA_STATISTICS prQueryStaStatistics) +{ + UINT_32 u4InstantPer[ENUM_BAND_NUM]; + INT_32 i4BytesWritten = 0; + UINT_8 ucDbdcIdx; + P_MIB_INFO_STAT_T prMibInfo; + + prMibInfo = prQueryStaStatistics->rMibInfo; + + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; ucDbdcIdx++) { + u4InstantPer[ucDbdcIdx] = ((prMibInfo[ucDbdcIdx].u4RxMpduCnt + + prMibInfo[ucDbdcIdx].u4FcsError) == 0) ? + (0) : (1000 * prMibInfo[ucDbdcIdx].u4FcsError / + (prMibInfo[ucDbdcIdx].u4RxMpduCnt + + prMibInfo[ucDbdcIdx].u4FcsError)); + } + + if (!prAdapter->rWifiVar.fgDbDcModeEn) { + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%-26s%s%d.%1d%%\n", "instant PER", " = ", + u4InstantPer[ENUM_BAND_0]/10, + u4InstantPer[ENUM_BAND_0]%10); + } else { + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; ucDbdcIdx++) { + i4BytesWritten += kalScnprintf( + pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "[DBDC_%d] :\n", ucDbdcIdx); + i4BytesWritten += kalScnprintf( + pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%-26s%s%d.%1d%%\n", "instant PER", " = ", + u4InstantPer[ucDbdcIdx]/10, + u4InstantPer[ucDbdcIdx]%10); + } + } + + return i4BytesWritten; +} + +static UINT_32 parseTrigger(IN char *pcBuffer, + IN int i4Size, IN UINT_8 trigger) +{ + INT_32 i4BytesWritten = 0; + PCHAR pString; + + switch (trigger) { + case DISCONNECT_TRIGGER_RESERVED: + pString = GET_VARNAME(DISCONNECT_TRIGGER_RESERVED); + break; + case DISCONNECT_TRIGGER_ACTIVE: + pString = GET_VARNAME(DISCONNECT_TRIGGER_ACTIVE); + break; + case DISCONNECT_TRIGGER_PASSIVE: + pString = GET_VARNAME(DISCONNECT_TRIGGER_PASSIVE); + break; + default: + pString = "N/A"; + break; + } + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%-26s%s%s\n", + "Trigger", + " = ", + pString); + + return i4BytesWritten; +} + + +static UINT_32 parseDisconnReasonCode(IN char *pcBuffer, + IN int i4Size, IN UINT_8 ucReason) +{ + INT_32 i4BytesWritten = 0; + PCHAR pString; + + switch (ucReason) { + case DISCONNECT_REASON_CODE_RESERVED: + pString = GET_VARNAME(DISCONNECT_REASON_CODE_RESERVED); + break; + case DISCONNECT_REASON_CODE_RADIO_LOST: + pString = GET_VARNAME(DISCONNECT_REASON_CODE_RADIO_LOST); + break; + case DISCONNECT_REASON_CODE_DEAUTHENTICATED: + pString = GET_VARNAME(DISCONNECT_REASON_CODE_DEAUTHENTICATED); + break; + case DISCONNECT_REASON_CODE_DISASSOCIATED: + pString = GET_VARNAME(DISCONNECT_REASON_CODE_DISASSOCIATED); + break; + case DISCONNECT_REASON_CODE_NEW_CONNECTION: + pString = GET_VARNAME(DISCONNECT_REASON_CODE_NEW_CONNECTION); + break; + case DISCONNECT_REASON_CODE_REASSOCIATION: + pString = GET_VARNAME(DISCONNECT_REASON_CODE_REASSOCIATION); + break; + default: + pString = "N/A"; + break; + } + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%-26s%s%s\n", + "Disconnect reason", + " = ", + pString); + + return i4BytesWritten; +} + +static UINT_32 parseBcnTimeoutReasonCode(IN char *pcBuffer, + IN int i4Size, IN UINT_8 ucReason) +{ + INT_32 i4BytesWritten = 0; + PCHAR pString; + + switch (ucReason) { + case BEACON_TIMEOUT_DUE_2_HW_BEACON_LOST_NONADHOC: + pString = GET_VARNAME( + BEACON_TIMEOUT_DUE_2_HW_BEACON_LOST_NONADHOC); + break; + case BEACON_TIMEOUT_DUE_2_HW_BEACON_LOST_ADHOC: + pString = GET_VARNAME( + BEACON_TIMEOUT_DUE_2_HW_BEACON_LOST_ADHOC); + break; + case BEACON_TIMEOUT_DUE_2_HW_TSF_DRIFT: + pString = GET_VARNAME( + BEACON_TIMEOUT_DUE_2_HW_TSF_DRIFT); + break; + case BEACON_TIMEOUT_DUE_2_NULL_FRAME_THRESHOLD: + pString = GET_VARNAME( + BEACON_TIMEOUT_DUE_2_NULL_FRAME_THRESHOLD); + break; + case BEACON_TIMEOUT_DUE_2_BSSID_BEACON_PEIROD_NOT_ILLIGAL: + pString = GET_VARNAME( + BEACON_TIMEOUT_DUE_2_BSSID_BEACON_PEIROD_NOT_ILLIGAL); + break; + case BEACON_TIMEOUT_DUE_2_CONNECTION_FAIL: + pString = GET_VARNAME( + BEACON_TIMEOUT_DUE_2_CONNECTION_FAIL); + break; + case BEACON_TIMEOUT_DUE_2_ALLOCAT_NULL_PKT_FAIL_THRESHOLD: + pString = GET_VARNAME( + BEACON_TIMEOUT_DUE_2_ALLOCAT_NULL_PKT_FAIL_THRESHOLD); + break; + case BEACON_TIMEOUT_DUE_2_NO_TX_DONE_EVENT: + pString = GET_VARNAME( + BEACON_TIMEOUT_DUE_2_NO_TX_DONE_EVENT); + break; + case BEACON_TIMEOUT_DUE_2_UNSPECIF_REASON: + pString = GET_VARNAME( + BEACON_TIMEOUT_DUE_2_UNSPECIF_REASON); + break; + case BEACON_TIMEOUT_DUE_2_SET_CHIP: + pString = GET_VARNAME( + BEACON_TIMEOUT_DUE_2_SET_CHIP); + break; + case BEACON_TIMEOUT_DUE_2_RESERVED: + pString = GET_VARNAME( + BEACON_TIMEOUT_DUE_2_RESERVED); + break; + default: + pString = "N/A"; + break; + } + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%-26s%s%s\n", + "Beacon timeout reason", + " = ", + pString); + + return i4BytesWritten; +} + +static UINT_32 parseDisassocReasonCode(IN char *pcBuffer, + IN int i4Size, IN UINT_8 ucReason) +{ + INT_32 i4BytesWritten = 0; + PCHAR pString; + + switch (ucReason) { + case REASON_CODE_RESERVED: + pString = GET_VARNAME( + REASON_CODE_RESERVED); + break; + case REASON_CODE_UNSPECIFIED: + pString = GET_VARNAME( + REASON_CODE_UNSPECIFIED); + break; + case REASON_CODE_PREV_AUTH_INVALID: + pString = GET_VARNAME( + REASON_CODE_PREV_AUTH_INVALID); + break; + case REASON_CODE_DEAUTH_LEAVING_BSS: + pString = GET_VARNAME( + REASON_CODE_DEAUTH_LEAVING_BSS); + break; + case REASON_CODE_DISASSOC_INACTIVITY: + pString = GET_VARNAME( + REASON_CODE_DISASSOC_INACTIVITY); + break; + case REASON_CODE_DISASSOC_AP_OVERLOAD: + pString = GET_VARNAME( + REASON_CODE_DISASSOC_AP_OVERLOAD); + break; + case REASON_CODE_CLASS_2_ERR: + pString = GET_VARNAME( + REASON_CODE_CLASS_2_ERR); + break; + case REASON_CODE_CLASS_3_ERR: + pString = GET_VARNAME( + REASON_CODE_CLASS_3_ERR); + break; + case REASON_CODE_DISASSOC_LEAVING_BSS: + pString = GET_VARNAME( + REASON_CODE_DISASSOC_LEAVING_BSS); + break; + case REASON_CODE_ASSOC_BEFORE_AUTH: + pString = GET_VARNAME( + REASON_CODE_ASSOC_BEFORE_AUTH); + break; + case REASON_CODE_DISASSOC_PWR_CAP_UNACCEPTABLE: + pString = GET_VARNAME( + REASON_CODE_DISASSOC_PWR_CAP_UNACCEPTABLE); + break; + case REASON_CODE_DISASSOC_SUP_CHS_UNACCEPTABLE: + pString = GET_VARNAME( + REASON_CODE_DISASSOC_SUP_CHS_UNACCEPTABLE); + break; + case REASON_CODE_INVALID_INFO_ELEM: + pString = GET_VARNAME( + REASON_CODE_INVALID_INFO_ELEM); + break; + case REASON_CODE_MIC_FAILURE: + pString = GET_VARNAME( + REASON_CODE_MIC_FAILURE); + break; + case REASON_CODE_4_WAY_HANDSHAKE_TIMEOUT: + pString = GET_VARNAME( + REASON_CODE_4_WAY_HANDSHAKE_TIMEOUT); + break; + case REASON_CODE_GROUP_KEY_UPDATE_TIMEOUT: + pString = GET_VARNAME( + REASON_CODE_GROUP_KEY_UPDATE_TIMEOUT); + break; + case REASON_CODE_DIFFERENT_INFO_ELEM: + pString = GET_VARNAME( + REASON_CODE_DIFFERENT_INFO_ELEM); + break; + case REASON_CODE_MULTICAST_CIPHER_NOT_VALID: + pString = GET_VARNAME( + REASON_CODE_MULTICAST_CIPHER_NOT_VALID); + break; + case REASON_CODE_UNICAST_CIPHER_NOT_VALID: + pString = GET_VARNAME( + REASON_CODE_UNICAST_CIPHER_NOT_VALID); + break; + case REASON_CODE_AKMP_NOT_VALID: + pString = GET_VARNAME( + REASON_CODE_AKMP_NOT_VALID); + break; + case REASON_CODE_UNSUPPORTED_RSNE_VERSION: + pString = GET_VARNAME( + REASON_CODE_UNSUPPORTED_RSNE_VERSION); + break; + case REASON_CODE_INVALID_RSNE_CAPABILITIES: + pString = GET_VARNAME( + REASON_CODE_INVALID_RSNE_CAPABILITIES); + break; + case REASON_CODE_IEEE_802_1X_AUTH_FAILED: + pString = GET_VARNAME( + REASON_CODE_IEEE_802_1X_AUTH_FAILED); + break; + case REASON_CODE_CIPHER_REJECT_SEC_POLICY: + pString = GET_VARNAME( + REASON_CODE_CIPHER_REJECT_SEC_POLICY); + break; + case REASON_CODE_DISASSOC_UNSPECIFIED_QOS: + pString = GET_VARNAME( + REASON_CODE_DISASSOC_UNSPECIFIED_QOS); + break; + case REASON_CODE_DISASSOC_LACK_OF_BANDWIDTH: + pString = GET_VARNAME( + REASON_CODE_DISASSOC_LACK_OF_BANDWIDTH); + break; + case REASON_CODE_DISASSOC_ACK_LOST_POOR_CHANNEL: + pString = GET_VARNAME( + REASON_CODE_DISASSOC_ACK_LOST_POOR_CHANNEL); + break; + case REASON_CODE_DISASSOC_TX_OUTSIDE_TXOP_LIMIT: + pString = GET_VARNAME( + REASON_CODE_DISASSOC_TX_OUTSIDE_TXOP_LIMIT); + break; + case REASON_CODE_PEER_WHILE_LEAVING: + pString = GET_VARNAME( + REASON_CODE_PEER_WHILE_LEAVING); + break; + case REASON_CODE_PEER_REFUSE_DLP: + pString = GET_VARNAME( + REASON_CODE_PEER_REFUSE_DLP); + break; + case REASON_CODE_PEER_SETUP_REQUIRED: + pString = GET_VARNAME( + REASON_CODE_PEER_SETUP_REQUIRED); + break; + case REASON_CODE_PEER_TIME_OUT: + pString = GET_VARNAME( + REASON_CODE_PEER_TIME_OUT); + break; + case REASON_CODE_PEER_CIPHER_UNSUPPORTED: + pString = GET_VARNAME( + REASON_CODE_PEER_CIPHER_UNSUPPORTED); + break; + default: + pString = "N/A"; + break; + } + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "%-26s%s%s\n", + "Disassociation reason", + " = ", + pString); + + return i4BytesWritten; + +} + +static UINT_32 parseRssiInfo(IN char *pcBuffer, IN int i4Size, + IN struct CMD_NOISE_HISTOGRAM_REPORT *prNoise) +{ + INT_32 i4BytesWritten = 0; + struct CMD_NOISE_HISTOGRAM_REPORT rEmptyNoise; + + kalMemZero(&rEmptyNoise, sizeof(rEmptyNoise)); + rEmptyNoise.u2Type = prNoise->u2Type; + rEmptyNoise.u2Len = prNoise->u2Len; + rEmptyNoise.ucAction = prNoise->ucAction; + + if (kalMemCmp(prNoise, &rEmptyNoise, + sizeof(struct CMD_NOISE_HISTOGRAM_REPORT)) == 0) { + DBGLOG(INIT, WARN, "Empty info\n"); + return i4BytesWritten; + } + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "\n%s", "----- Noise Info -----"); + + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "\n Power > -55: %10d", + prNoise->u4IPI10); + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "\n-55 >= Power > -60: %10d", + prNoise->u4IPI9); + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "\n-60 >= Power > -65: %10d", + prNoise->u4IPI8); + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "\n-65 >= Power > -70: %10d", + prNoise->u4IPI7); + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "\n-70 >= Power > -75: %10d", + prNoise->u4IPI6); + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "\n-75 >= Power > -80: %10d", + prNoise->u4IPI5); + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "\n-80 >= Power > -83: %10d", + prNoise->u4IPI4); + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "\n-83 >= Power > -86: %10d", + prNoise->u4IPI3); + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "\n-86 >= Power > -89: %10d", + prNoise->u4IPI2); + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "\n-89 >= Power > -92: %10d", + prNoise->u4IPI1); + i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten, + i4Size - i4BytesWritten, + "\n-92 >= Power : %10d\n", + prNoise->u4IPI0); + + return i4BytesWritten; +} + +static ssize_t procDisconnInfoRead(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + P_GLUE_INFO_T prGlueInfo; + INT_32 i4Count = 0; + UINT_8 ucDbdcIdx; + UINT_8 *temp = &g_aucProcBuf[0]; + struct AIS_DISCONN_INFO_T *prDisconn = NULL; + UINT_8 cnt; + UINT_8 temp_idx = 0; + struct tm broken; + char date[20] = {0}; + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0) + return 0; + + if (g_prDisconnInfo == NULL) { + DBGLOG(INIT, WARN, "NULL g_prDisconnInfo\n"); + return 0; + } + + if (g_DisconnInfoIdx >= MAX_DISCONNECT_RECORD) { + DBGLOG(AIS, LOUD, "Invalid g_DisconnInfoIdx\n"); + return 0; + } + + prGlueInfo = g_prGlueInfo_proc; + + kalMemZero(g_aucProcBuf, sizeof(g_aucProcBuf)); + + for (cnt = 0; cnt < MAX_DISCONNECT_RECORD; cnt++) { + + temp_idx = (g_DisconnInfoIdx + cnt) % MAX_DISCONNECT_RECORD; + + prDisconn = g_prDisconnInfo + temp_idx; + + if (prDisconn->ucTrigger != DISCONNECT_TRIGGER_RESERVED) { + + time_to_tm(prDisconn->tv.tv_sec, 0, &broken); + kalScnprintf(date, + sizeof(date), + "%02d-%02d %02d:%02d:%02d.%ld", + broken.tm_mon + 1, + broken.tm_mday, + broken.tm_hour, + broken.tm_min, + broken.tm_sec, + prDisconn->tv.tv_usec); + + i4Count += kalScnprintf(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + "%s %s %d %s %s %s %s", + "===============", + "Record", + temp_idx, + "(", + date, + ")", + "==============="); + + /* Dump misc info*/ + i4Count += kalScnprintf(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + "\n%s", "\n"); + + i4Count += parseTrigger(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + prDisconn->ucTrigger); + + i4Count += parseDisconnReasonCode(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + prDisconn->ucDisConnReason); + + i4Count += parseBcnTimeoutReasonCode(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + prDisconn->ucBcnTimeoutReason); + + i4Count += parseDisassocReasonCode(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + prDisconn->ucDisassocReason); + + if (prDisconn->u2DisassocSeqNum != 0xFFFF) { + i4Count += kalScnprintf(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + "%-26s%s%d\n", + "Disassociation SeqNum", + " = ", + prDisconn->u2DisassocSeqNum); + } + + /* Noise info*/ + i4Count += parseRssiInfo(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + &prDisconn->rNoise); + + /* Dump RX info */ + i4Count += kalScnprintf(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + "\n%s", "\n"); + + /* Last RX Rate info */ + i4Count += parseRxRateInfo(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + &prDisconn->rStaRec); + + /* RX PER info */ + i4Count += parseRxPerInfo(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + prGlueInfo->prAdapter, + &prDisconn->rStaStatistics); + + /* Last RX RSSI info*/ + i4Count += parseRxRssiInfo(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + prGlueInfo->prAdapter, + &prDisconn->rStaRec); + + /* Last RX Resp RSSI */ + i4Count += parseRxRespRssiInfo(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + prGlueInfo->prAdapter, + &prDisconn->rHwInfo); + + /* Last Beacon RSSI */ + if (prDisconn->rBcnRssi != 0) { + i4Count += kalScnprintf(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + "%-26s%s%d\n", "Beacon RSSI", " = ", + prDisconn->rBcnRssi); + } + + /* Dump TX info */ + i4Count += kalScnprintf(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + "\n%s", "\n"); + + /* Last TX Rate info */ + if (!prGlueInfo->prAdapter->rWifiVar.fgDbDcModeEn) { + + i4Count += parseTxRateInfo(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + &prDisconn->rStaStatistics + .rTxVector[ENUM_BAND_0]); + + } else { + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; + ucDbdcIdx++) { + + i4Count += kalScnprintf(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + "[DBDC_%d] :\n", ucDbdcIdx); + + i4Count += parseTxRateInfo( + temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + &prDisconn->rStaStatistics + .rTxVector[ucDbdcIdx]); + } + } + + /* TX PER info */ + i4Count += parseTxPerInfo(temp + i4Count, + sizeof(g_aucProcBuf) - i4Count, + &prDisconn->rHwInfo, + &prDisconn->rStaStatistics); + + } + } + + if (copy_to_user(buf, g_aucProcBuf, i4Count)) { + DBGLOG(INIT, ERROR, "copy to user failed\n"); + return -EFAULT; + } + + *f_pos += i4Count; + + return i4Count; +} +#endif /* CFG_DISCONN_DEBUG_FEATURE */ + +static const struct file_operations dbglevel_ops = { + .owner = THIS_MODULE, + .read = procDbgLevelRead, + .write = procDbgLevelWrite, +}; + + +#if CFG_SUPPORT_CSI +static const struct file_operations csidata_ops = { + .owner = THIS_MODULE, + .read = procCSIDataRead, + .open = procCSIDataOpen, + .release = procCSIDataRelease, +}; +#endif + + + +#if WLAN_INCLUDE_PROC +#if CFG_SUPPORT_EASY_DEBUG + +static const struct file_operations efusedump_ops = { + .owner = THIS_MODULE, + .open = procEfuseDumpOpen, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static const struct file_operations drivercmd_ops = { + .owner = THIS_MODULE, + .read = procDriverCmdRead, + .write = procDriverCmdWrite, +}; + +static const struct file_operations cfg_ops = { + .owner = THIS_MODULE, + .read = procCfgRead, + .write = procCfgWrite, +}; +#endif +#endif + +static const struct file_operations get_txpwr_tbl_ops = { + .owner = THIS_MODULE, + .read = procGetTxpwrTblRead, +}; + +#if CFG_DISCONN_DEBUG_FEATURE +static const struct file_operations disconn_info_ops = { + .owner = THIS_MODULE, + .read = procDisconnInfoRead, +}; +#endif + +/******************************************************************************* +* 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 ssize_t procMCRRead(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + P_GLUE_INFO_T prGlueInfo; + PARAM_CUSTOM_MCR_RW_STRUCT_T rMcrInfo; + UINT_32 u4BufLen; + UINT_8 *temp = &g_aucProcBuf[0]; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + INT_32 i4Count = 0; + + /* Kevin: Apply PROC read method 1. */ + if (*f_pos > 0) + return 0; /* To indicate end of file. */ + + prGlueInfo = g_prGlueInfo_proc; + + rMcrInfo.u4McrOffset = u4McrOffset; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryMcrRead, (PVOID)&rMcrInfo, sizeof(rMcrInfo), TRUE, TRUE, TRUE, &u4BufLen); + kalMemZero(g_aucProcBuf, sizeof(g_aucProcBuf)); + + i4Count = scnprintf(temp, sizeof(g_aucProcBuf), + "MCR (0x%08xh): 0x%08x\n", rMcrInfo.u4McrOffset, rMcrInfo.u4McrData); + + if (copy_to_user(buf, g_aucProcBuf, i4Count)) { + DBGLOG(INIT, ERROR, "copy to user failed\n"); + return -EFAULT; + } + + *f_pos += i4Count; + + return i4Count; + +} /* 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 ssize_t procMCRWrite(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + P_GLUE_INFO_T prGlueInfo; + char acBuf[PROC_MCR_ACCESS_MAX_USER_INPUT_LEN + 1]; /* + 1 for "\0" */ + int i4CopySize; + PARAM_CUSTOM_MCR_RW_STRUCT_T rMcrInfo; + UINT_32 u4BufLen; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + int num = 0; + + ASSERT(data); + + i4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + if (copy_from_user(acBuf, buffer, i4CopySize)) + return 0; + acBuf[i4CopySize] = '\0'; + + num = sscanf(acBuf, "0x%x 0x%x", &rMcrInfo.u4McrOffset, &rMcrInfo.u4McrData); + switch (num) { + 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, &u4BufLen); + + } + break; + case 1: + /* if (IS_ALIGN_4(rMcrInfo.u4McrOffset)) */ + { + u4McrOffset = rMcrInfo.u4McrOffset; + } + break; + + default: + break; + } + + return count; + +} /* end of procMCRWrite() */ + +static const struct file_operations mcr_ops = { + .owner = THIS_MODULE, + .read = procMCRRead, + .write = procMCRWrite, +}; + +#if CFG_SUPPORT_DEBUG_FS +static ssize_t procRoamRead(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + UINT_32 u4CopySize; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + + /* if *f_pos > 0, it means has read successed last time, don't try again */ + if (*f_pos > 0) + return 0; + + rStatus = kalIoctl(g_prGlueInfo_proc, wlanoidGetRoamParams, g_aucProcBuf, sizeof(g_aucProcBuf), + TRUE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "failed to read roam params\n"); + return -EINVAL; + } + + u4CopySize = kalStrLen(g_aucProcBuf); + if (copy_to_user(buf, g_aucProcBuf, u4CopySize)) { + DBGLOG(INIT, ERROR, "copy to user failed\n"); + return -EFAULT; + } + *f_pos += u4CopySize; + + return (INT_32)u4CopySize; +} + +static ssize_t procRoamWrite(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + WLAN_STATUS rStatus; + UINT_32 u4BufLen = 0; + UINT_32 u4CopySize = sizeof(g_aucProcBuf); + + kalMemSet(g_aucProcBuf, 0, u4CopySize); + if (u4CopySize >= count+1) + u4CopySize = count; + else + u4CopySize -= 1; + + if (copy_from_user(g_aucProcBuf, buffer, u4CopySize)) { + DBGLOG(INIT, ERROR, "error of copy from user\n"); + return -EFAULT; + } + g_aucProcBuf[u4CopySize] = '\0'; + + if (kalStrnCmp(g_aucProcBuf, "force_roam", 10) == 0) + rStatus = kalIoctl(g_prGlueInfo_proc, wlanoidSetForceRoam, NULL, 0, + FALSE, FALSE, TRUE, &u4BufLen); + else + rStatus = kalIoctl(g_prGlueInfo_proc, wlanoidSetRoamParams, g_aucProcBuf, + kalStrLen(g_aucProcBuf), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "failed to set roam params: %s\n", g_aucProcBuf); + return -EINVAL; + } + return count; +} + +static const struct file_operations roam_ops = { + .owner = THIS_MODULE, + .read = procRoamRead, + .write = procRoamWrite, +}; + +static ssize_t procCountryRead(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + UINT_32 u4CopySize; + UINT_16 u2CountryCode = 0; + UINT_32 u4BufLen; + WLAN_STATUS rStatus; + + /* if *f_pos > 0, it means has read successed last time, don't try again */ + if (*f_pos > 0) + return 0; + + rStatus = kalIoctl(g_prGlueInfo_proc, wlanoidGetCountryCode, + &u2CountryCode, 2, TRUE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "failed to get country code\n"); + return -EINVAL; + } + if (u2CountryCode) + kalSprintf(g_aucProcBuf, "Current Country Code: %c%c\n", + (u2CountryCode>>8) & 0xff, u2CountryCode & 0xff); + else + kalStrCpy(g_aucProcBuf, "Current Country Code: NULL\n"); + + u4CopySize = kalStrLen(g_aucProcBuf); + if (copy_to_user(buf, g_aucProcBuf, u4CopySize)) { + DBGLOG(INIT, ERROR, "copy to user failed\n"); + return -EFAULT; + } + *f_pos += u4CopySize; + + return (INT_32)u4CopySize; +} + +static ssize_t procCountryWrite(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + UINT_32 u4BufLen = 0; + WLAN_STATUS rStatus; + UINT_32 u4CopySize = sizeof(g_aucProcBuf); + + kalMemSet(g_aucProcBuf, 0, u4CopySize); + if (u4CopySize >= count+1) + u4CopySize = count; + else + u4CopySize -= 1; + + if (copy_from_user(g_aucProcBuf, buffer, u4CopySize)) { + DBGLOG(INIT, ERROR, "error of copy from user\n"); + return -EFAULT; + } + g_aucProcBuf[u4CopySize] = '\0'; + + rStatus = kalIoctl(g_prGlueInfo_proc, wlanoidSetCountryCode, + &g_aucProcBuf[0], 2, FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "failed set country code: %s\n", g_aucProcBuf); + return -EINVAL; + } + return count; +} + +static const struct file_operations country_ops = { + .owner = THIS_MODULE, + .read = procCountryRead, + .write = procCountryWrite, +}; +#endif + +INT_32 procInitFs(VOID) +{ + + g_i4NextDriverReadLen = 0; + + if (init_net.proc_net == (struct proc_dir_entry *)NULL) { + DBGLOG(INIT, ERROR, "init proc fs fail: proc_net == NULL\n"); + return -ENOENT; + } + + /* + * Directory: Root (/proc/net/wlan0) + */ + + gprProcRoot = proc_mkdir(PROC_ROOT_NAME, init_net.proc_net); + if (!gprProcRoot) { + DBGLOG(INIT, ERROR, "gprProcRoot == NULL\n"); + return -ENOENT; + } + proc_set_user(gprProcRoot, KUIDT_INIT(PROC_UID_SHELL), KGIDT_INIT(PROC_GID_WIFI)); + + + return 0; +} /* end of procInitProcfs() */ + +INT_32 procUninitProcFs(VOID) +{ +#if KERNEL_VERSION(3, 9, 0) <= LINUX_VERSION_CODE + remove_proc_subtree(PROC_ROOT_NAME, init_net.proc_net); +#else + remove_proc_entry(PROC_ROOT_NAME, init_net.proc_net); +#endif + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function clean up a PROC fs created by procInitProcfs(). +* +* \param[in] prDev Pointer to the struct net_device. +* \param[in] pucDevName Pointer to the name of net_device. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +INT_32 procRemoveProcfs(VOID) +{ + remove_proc_entry(PROC_MCR_ACCESS, gprProcRoot); + remove_proc_entry(PROC_DRIVER_CMD, gprProcRoot); + remove_proc_entry(PROC_DBG_LEVEL_NAME, gprProcRoot); + remove_proc_entry(PROC_CFG, gprProcRoot); + remove_proc_entry(PROC_EFUSE_DUMP, gprProcRoot); + +#if CFG_SUPPORT_CSI + remove_proc_entry(PROC_CSI_DATA_NAME, gprProcRoot); +#endif + + remove_proc_entry(PROC_GET_TXPWR_TBL, gprProcRoot); + +#if CFG_DISCONN_DEBUG_FEATURE + remove_proc_entry(PROC_DISCONN_INFO, gprProcRoot); +#endif + +#if CFG_SUPPORT_DEBUG_FS + remove_proc_entry(PROC_ROAM_PARAM, gprProcRoot); + remove_proc_entry(PROC_COUNTRY, gprProcRoot); + +#endif + return 0; +} /* end of procRemoveProcfs() */ + +INT_32 procCreateFsEntry(P_GLUE_INFO_T prGlueInfo) +{ + struct proc_dir_entry *prEntry; + + DBGLOG(INIT, INFO, "[%s]\n", __func__); + g_prGlueInfo_proc = prGlueInfo; + + prEntry = proc_create(PROC_MCR_ACCESS, 0664, gprProcRoot, &mcr_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry\n\r"); + return -1; + } +#if CFG_SUPPORT_DEBUG_FS + prEntry = proc_create(PROC_ROAM_PARAM, 0664, gprProcRoot, &roam_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry\n\r"); + return -1; + } + prEntry = proc_create(PROC_COUNTRY, 0664, gprProcRoot, &country_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry\n\r"); + return -1; + } +#endif +#if CFG_SUPPORT_EASY_DEBUG + + prEntry = proc_create(PROC_DRIVER_CMD, 0664, gprProcRoot, &drivercmd_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry for driver command\n\r"); + return -1; + } + + prEntry = proc_create(PROC_CFG, 0664, gprProcRoot, &cfg_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry for driver command\n\r"); + return -1; + } + + prEntry = proc_create(PROC_EFUSE_DUMP, 0664, gprProcRoot, &efusedump_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry efuse\n\r"); + return -1; + } +#endif + + prEntry = proc_create(PROC_GET_TXPWR_TBL, 0664, gprProcRoot, + &get_txpwr_tbl_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry efuse\n\r"); + return -1; + } + + prEntry = proc_create(PROC_DBG_LEVEL_NAME, 0664, gprProcRoot, &dbglevel_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry dbgLevel\n\r"); + return -1; + } + +#if CFG_SUPPORT_CSI + prEntry = proc_create(PROC_CSI_DATA_NAME, 0664, gprProcRoot, &csidata_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry csidata\n\r"); + return -1; + } +#endif + + +#if CFG_DISCONN_DEBUG_FEATURE + prEntry = proc_create(PROC_DISCONN_INFO, 0664, gprProcRoot, + &disconn_info_ops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, + "Unable to create /proc entry disconn_info\n\r"); + return -1; + } +#endif + + return 0; +} + +#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; + INT_32 rv; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(data); + + u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + copy_from_user(acBuf, buffer, u4CopySize); + acBuf[u4CopySize] = '\0'; + + rv = kstrtoint(acBuf, 0, &u4ClearCounter); + if (rv == 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; + INT_32 rv; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(data); + + u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + copy_from_user(acBuf, buffer, u4CopySize); + acBuf[u4CopySize] = '\0'; + + rv = kstrtoint(acBuf, 0, &u4ClearCounter); + if (rv == 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 + + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_qa_agent.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_qa_agent.c new file mode 100644 index 0000000000000..04157a6b1e3e7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_qa_agent.c @@ -0,0 +1,7838 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + Module Name: + gl_ate_agent.c +*/ +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ + +#include "precomp.h" + +#if (CFG_SUPPORT_QA_TOOL == 1) +#include "gl_wext.h" +#include "gl_cfg80211.h" +#include "gl_ate_agent.h" +#include "gl_qa_agent.h" +#include "gl_hook_api.h" +#if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE +#include +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +PARAM_RX_STAT_T g_HqaRxStat; +UINT_32 u4RxStatSeqNum; +BOOLEAN g_DBDCEnable = FALSE; +/* For SA Buffer Mode Temp Solution */ +BOOLEAN g_BufferDownload = FALSE; +UINT_32 u4EepromMode = 4; +UINT_32 g_u4Chip_ID; +UINT_8 g_ucEepromCurrentMode = EFUSE_MODE; + +#if CFG_SUPPORT_BUFFER_MODE +UINT_8 uacEEPROMImage[MAX_EEPROM_BUFFER_SIZE] = { + /* 0x000 ~ 0x00F */ + 0xAE, 0x86, 0x06, 0x00, 0x18, 0x0D, 0x00, 0x00, 0xC0, 0x1F, 0xBD, 0x81, 0x3F, 0x01, 0x19, 0x00, + /* 0x010 ~ 0x01F */ + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, + /* 0x020 ~ 0x02F */ + 0x80, 0x02, 0x00, 0x00, 0x32, 0x66, 0xC3, 0x14, 0x32, 0x66, 0xC3, 0x14, 0x03, 0x22, 0xFF, 0xFF, + /* 0x030 ~ 0x03F */ + 0x23, 0x04, 0x0D, 0xF2, 0x8F, 0x02, 0x00, 0x80, 0x0A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x040 ~ 0x04F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x40, 0x00, 0x00, + /* 0x050 ~ 0x05F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x08, + /* 0x060 ~ 0x06F */ + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x08, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x08, + /* 0x070 ~ 0x07F */ + 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x080 ~ 0x08F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x090 ~ 0x09F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x0A0 ~ 0x0AF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x0B0 ~ 0x0BF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x10, 0x10, 0x28, 0x00, 0x00, 0x00, 0x00, + /* 0x0C0 ~ 0x0CF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x0D0 ~ 0x0DF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x0E0 ~ 0x0EF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x0F0 ~ 0x0FF */ + 0x0E, 0x05, 0x06, 0x06, 0x06, 0x0F, 0x00, 0x00, 0x0E, 0x05, 0x06, 0x05, 0x05, 0x09, 0xFF, 0x00, + /* 0x100 ~ 0x10F */ + 0x12, 0x34, 0x56, 0x78, 0x2C, 0x2C, 0x28, 0x28, 0x28, 0x26, 0x26, 0x28, 0x28, 0x28, 0x26, 0xFF, + /* 0x110 ~ 0x11F */ + 0x26, 0x25, 0x28, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x27, 0x27, 0x25, + /* 0x120 ~ 0x12F */ + 0x25, 0x25, 0x25, 0x25, 0x23, 0x23, 0x23, 0x21, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, + /* 0x130 ~ 0x13F */ + 0x40, 0x40, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + /* 0x140 ~ 0x14F */ + 0x25, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x150 ~ 0x15F */ + 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, + /* 0x160 ~ 0x16F */ + 0xD0, 0xD0, 0xD0, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x170 ~ 0x17F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, 0xC4, 0xC5, 0xC8, + /* 0x180 ~ 0x18F */ + 0x00, 0x26, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x190 ~ 0x19F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x1A0 ~ 0x1AF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0xD0, 0xD0, 0x0E, 0x05, 0x06, 0x05, 0x09, 0x0E, 0x00, + /* 0x1B0 ~ 0x1BF */ + 0x05, 0x06, 0x05, 0x05, 0x09, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + /* 0x1C0 ~ 0x1CF */ + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, + /* 0x1D0 ~ 0x1DF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x1E0 ~ 0x1EF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x1F0 ~ 0x1FF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x200 ~ 0x20F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x210 ~ 0x21F */ + 0x48, 0xF5, 0x27, 0x49, 0x48, 0xF5, 0x57, 0x12, 0x4B, 0x71, 0x80, 0x50, 0x91, 0xF6, 0x87, 0x50, + /* 0x220 ~ 0x22F */ + 0x7D, 0x29, 0x09, 0x42, 0x7D, 0x29, 0x41, 0x44, 0x7D, 0x29, 0x41, 0x3C, 0x7D, 0x29, 0x31, 0x4D, + /* 0x230 ~ 0x23F */ + 0x49, 0x71, 0x24, 0x49, 0x49, 0x71, 0x54, 0x12, 0x4B, 0x71, 0x80, 0x50, 0x91, 0xF6, 0x87, 0x50, + /* 0x240 ~ 0x24F */ + 0x7D, 0x29, 0x09, 0x42, 0x7D, 0x29, 0x41, 0x04, 0x7D, 0x29, 0x41, 0x04, 0x7D, 0x29, 0x01, 0x40, + /* 0x250 ~ 0x25F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x260 ~ 0x26F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x270 ~ 0x27F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x280 ~ 0x28F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x290 ~ 0x29F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x2A0 ~ 0x2AF */ + 0x7D, 0x29, 0xC9, 0x16, 0x7D, 0x29, 0xC9, 0x16, 0x44, 0x22, 0x32, 0x15, 0xEE, 0xEE, 0xEE, 0x08, + /* 0x2B0 ~ 0x2BF */ + 0x78, 0x90, 0x79, 0x1C, 0x78, 0x90, 0x79, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x2C0 ~ 0x2CF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x2D0 ~ 0x2DF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x2E0 ~ 0x2EF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x2F0 ~ 0x2FF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x300 ~ 0x30F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x310 ~ 0x31F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x42, 0x10, 0x42, 0x08, 0x21, + /* 0x320 ~ 0x32F */ + 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x21, + /* 0x330 ~ 0x33F */ + 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x21, + /* 0x340 ~ 0x34F */ + 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x21, 0x10, 0x42, 0x08, 0x01, + /* 0x350 ~ 0x35F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x360 ~ 0x36F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x370 ~ 0x37F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x380 ~ 0x38F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x390 ~ 0x39F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x3A0 ~ 0x3AF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x3B0 ~ 0x3BF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x3C0 ~ 0x3CF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x3D0 ~ 0x3DF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x3E0 ~ 0x3EF */ + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + /* 0x3F0 ~ 0x3FF */ + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + /* 0x400 ~ 0x40F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x410 ~ 0x41F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x420 ~ 0x42F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x430 ~ 0x43F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x440 ~ 0x44F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x450 ~ 0x45F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x460 ~ 0x46F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x470 ~ 0x47F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x480 ~ 0x48F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x490 ~ 0x49F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x4A0 ~ 0x4AF */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Response ACK to QA Tool DLL. +* +* \param[in] HqaCmdFrame Ethernet Frame Format respond to QA Tool DLL +* \param[in] prIwReqData +* \param[in] i4Length Length of Ethernet Frame data field +* \param[in] i4Status Status to respond +* \param[out] None +* +* \retval 0 On success. +* \retval -EFAULT If copy_to_user fail +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 ResponseToQA(HQA_CMD_FRAME *HqaCmdFrame, + IN union iwreq_data *prIwReqData, INT_32 i4Length, INT_32 i4Status) +{ + HqaCmdFrame->Length = ntohs((i4Length)); + + i4Status = ntohs((i4Status)); + memcpy(HqaCmdFrame->Data, &i4Status, 2); + + prIwReqData->data.length = sizeof((HqaCmdFrame)->MagicNo) + sizeof((HqaCmdFrame)->Type) + + sizeof((HqaCmdFrame)->Id) + sizeof((HqaCmdFrame)->Length) + + sizeof((HqaCmdFrame)->Sequence) + ntohs((HqaCmdFrame)->Length); + + if (copy_to_user(prIwReqData->data.pointer, (UCHAR *) (HqaCmdFrame), prIwReqData->data.length)) { + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT copy_to_user() fail in %s\n", __func__); + return -EFAULT; + } + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA command(0x%04x)[Magic number(0x%08x)] is done\n", + ntohs(HqaCmdFrame->Id), ntohl(HqaCmdFrame->MagicNo)); + + return 0; +} + +static INT_32 ToDoFunction(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT ToDoFunction\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Open Adapter (called when QA Tool UI Open). +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_OpenAdapter(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_OpenAdapter\n"); + + i4Ret = MT_ATEStart(prNetDev, "ATESTART"); + + /* For SA Buffer Mode Temp Solution */ + g_BufferDownload = FALSE; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Close Adapter (called when QA Tool UI Close). +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_CloseAdapter(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_CloseAdapter\n"); + + i4Ret = MT_ATEStop(prNetDev, "ATESTOP"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Start TX. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_StartTx(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 TxCount; + UINT_16 TxLength; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_StartTx\n"); + + memcpy((PUCHAR)&TxCount, HqaCmdFrame->Data + 4 * 0, 4); + TxCount = ntohl(TxCount); + memcpy((PUCHAR)&TxLength, HqaCmdFrame->Data + 4 * 1, 2); + TxLength = ntohs(TxLength); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_StartTx TxCount = %d\n", TxCount); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_StartTx TxLength = %d\n", TxLength); + + i4Ret = MT_ATESetTxCount(prNetDev, TxCount); + i4Ret = MT_ATESetTxLength(prNetDev, (UINT_32) TxLength); + i4Ret = MT_ATEStartTX(prNetDev, "TXFRAME"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +/* 1 todo not support yet */ +static INT_32 HQA_StartTxExt(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_StartTxExt\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Start Continuous TX. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +/* 1 todo not support yet */ +static INT_32 HQA_StartTxContiTx(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_StartTxContiTx\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +/* 1 todo not support yets */ +static INT_32 HQA_StartTxCarrier(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_StartTxCarrier\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Start RX (Legacy function). +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_StartRx(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_StartRx\n"); + + MT_ATESetDBDCBandIndex(prNetDev, 0); + MT_ATEStartRX(prNetDev, "RXFRAME"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Stop TX (Legacy function). +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_StopTx(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_StopTx\n"); + + MT_ATESetDBDCBandIndex(prNetDev, 0); + MT_ATEStopRX(prNetDev, "RXSTOP"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Stop Continuous TX. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_StopContiTx(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_StopContiTx\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_StopTxCarrier(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_StopTxCarrier\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Stop RX (Legacy function). +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_StopRx(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_StopRx\n"); + + MT_ATESetDBDCBandIndex(prNetDev, 0); + MT_ATEStopRX(prNetDev, "RXSTOP"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set TX Path. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetTxPath(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetTxPath\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set RX Path. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetRxPath(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; +/* INT_16 Value = 0; +* P_GLUE_INFO_T prGlueInfo = NULL; +* PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; +* UINT_32 u4BufLen = 0; +*/ + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetRxPath\n"); + +#if 0 + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memcpy(&Value, HqaCmdFrame->Data + 4 * 0, 2); + Value = ntohs(Value); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetRxPath Value : %d\n", Value); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_RX_PATH; + rRfATInfo.u4FuncData = (UINT_32) ((Value << 16) || (0 & BITS(0, 15))); + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; +#endif + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set TX Inter-Packet Guard. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetTxIPG(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Aifs = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetTxIPG\n"); + + memcpy(&u4Aifs, HqaCmdFrame->Data + 4 * 0, 4); + u4Aifs = ntohs(u4Aifs); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetTxIPG u4Aifs : %d\n", u4Aifs); + + MT_ATESetTxIPG(prNetDev, u4Aifs); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set TX Power0 (Legacy Function). +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetTxPower0(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetTxPower0\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set TX Power1. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HAQ_SetTxPower1(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HAQ_SetTxPower1\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetTxPowerExt(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Power = 0; + UINT_32 u4Channel = 0; + UINT_32 u4Dbdc_idx = 0; + UINT_32 u4Band_idx = 0; + UINT_32 u4Ant_idx = 0; + + memcpy(&u4Power, HqaCmdFrame->Data + 4 * 0, 4); + u4Power = ntohl(u4Power); + memcpy(&u4Dbdc_idx, HqaCmdFrame->Data + 4 * 1, 4); + u4Dbdc_idx = ntohl(u4Dbdc_idx); + memcpy(&u4Channel, HqaCmdFrame->Data + 4 * 2, 4); + u4Channel = ntohl(u4Channel); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 3, 4); + u4Band_idx = ntohl(u4Band_idx); + memcpy(&u4Ant_idx, HqaCmdFrame->Data + 4 * 4, 4); + u4Ant_idx = ntohl(u4Ant_idx); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetTxPowerExt u4Power : %d\n", u4Power); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetTxPowerExt u4Dbdc_idx : %d\n", u4Dbdc_idx); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetTxPowerExt u4Channel : %d\n", u4Channel); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetTxPowerExt u4Band_idx : %d\n", u4Band_idx); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetTxPowerExt u4Ant_idx : %d\n", u4Ant_idx); + + MT_ATESetDBDCBandIndex(prNetDev, u4Dbdc_idx); + MT_ATESetTxPower0(prNetDev, u4Power); + /* u4Freq = nicChannelNum2Freq(u4Channel); */ + /* i4Ret = MT_ATESetChannel(prNetDev, 0, u4Freq); */ + /* MT_ATESetBand(prNetDev, u4Band_idx); */ + /* Antenna?? */ + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetOnOff(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetOnOff\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Antenna Selection. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_AntennaSel(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_AntennaSel\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_FWPacketCMD_ClockSwitchDisable(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_FWPacketCMD_ClockSwitchDisable\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_CMD_SET0[] = { + /* cmd id start from 0x1000 */ + HQA_OpenAdapter, /* 0x1000 */ + HQA_CloseAdapter, /* 0x1001 */ + HQA_StartTx, /* 0x1002 */ + HQA_StartTxExt, /* 0x1003 */ + HQA_StartTxContiTx, /* 0x1004 */ + HQA_StartTxCarrier, /* 0x1005 */ + HQA_StartRx, /* 0x1006 */ + HQA_StopTx, /* 0x1007 */ + HQA_StopContiTx, /* 0x1008 */ + HQA_StopTxCarrier, /* 0x1009 */ + HQA_StopRx, /* 0x100A */ + HQA_SetTxPath, /* 0x100B */ + HQA_SetRxPath, /* 0x100C */ + HQA_SetTxIPG, /* 0x100D */ + HQA_SetTxPower0, /* 0x100E */ + HAQ_SetTxPower1, /* 0x100F */ + ToDoFunction, /* 0x1010 */ + HQA_SetTxPowerExt, /* 0x1011 */ + HQA_SetOnOff, /* 0x1012 */ + HQA_AntennaSel, /* 0x1013 */ + HQA_FWPacketCMD_ClockSwitchDisable, /* 0x1014 */ +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set Channel Frequency (Legacy Function). +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetChannel(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + UINT_32 i4SetFreq = 0, i4SetChan = 0; + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetChannel\n"); + + memcpy((PUCHAR)&i4SetChan, HqaCmdFrame->Data, 4); + i4SetChan = ntohl(i4SetChan); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetChannel Channel = %d\n", i4SetChan); + + i4SetFreq = nicChannelNum2Freq(i4SetChan); + i4Ret = MT_ATESetChannel(prNetDev, 0, i4SetFreq); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set Preamble (Legacy Function). +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetPreamble(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Mode = 0; + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetPreamble\n"); + + memcpy((PUCHAR)&i4Mode, HqaCmdFrame->Data, 4); + i4Mode = ntohl(i4Mode); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetPreamble Mode = %d\n", i4Mode); + + i4Ret = MT_ATESetPreamble(prNetDev, i4Mode); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set Rate (Legacy Function). +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetRate(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ +/* INT_32 i4Value = 0; */ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetRate\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set Nss. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetNss(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetNss\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set System BW (Legacy Function). +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetSystemBW(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + UINT_32 i4BW; + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetSystemBW\n"); + + memcpy((PUCHAR)&i4BW, HqaCmdFrame->Data, 4); + i4BW = ntohl(i4BW); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetSystemBW BW = %d\n", i4BW); + + i4Ret = MT_ATESetSystemBW(prNetDev, i4BW); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set Data BW (Legacy Function). +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetPerPktBW(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Perpkt_bw; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetPerPktBW\n"); + + memcpy((PUCHAR)&u4Perpkt_bw, HqaCmdFrame->Data, 4); + u4Perpkt_bw = ntohl(u4Perpkt_bw); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetPerPktBW u4Perpkt_bw = %d\n", u4Perpkt_bw); + + i4Ret = MT_ATESetPerPacketBW(prNetDev, u4Perpkt_bw); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set Primary BW. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetPrimaryBW(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Pri_sel = 0; + + memcpy(&u4Pri_sel, HqaCmdFrame->Data, 4); + u4Pri_sel = ntohl(u4Pri_sel); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetPrimaryBW u4Pri_sel : %d\n", u4Pri_sel); + + i4Ret = MT_ATEPrimarySetting(prNetDev, u4Pri_sel); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set Frequency Offset. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetFreqOffset(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4FreqOffset = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 u4BufLen = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memcpy(&u4FreqOffset, HqaCmdFrame->Data, 4); + u4FreqOffset = ntohl(u4FreqOffset); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetFreqOffset u4FreqOffset : %d\n", u4FreqOffset); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_FRWQ_OFFSET; + rRfATInfo.u4FuncData = (UINT_32) u4FreqOffset; + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetAutoResponder(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetAutoResponder\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetTssiOnOff(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetTssiOnOff\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +/* 1 todo not support yet */ + +static INT_32 HQA_SetRxHighLowTemperatureCompensation(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetRxHighLowTemperatureCompensation\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_LowPower(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_LowPower\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_CMD_SET1[] = { + /* cmd id start from 0x1100 */ + HQA_SetChannel, /* 0x1100 */ + HQA_SetPreamble, /* 0x1101 */ + HQA_SetRate, /* 0x1102 */ + HQA_SetNss, /* 0x1103 */ + HQA_SetSystemBW, /* 0x1104 */ + HQA_SetPerPktBW, /* 0x1105 */ + HQA_SetPrimaryBW, /* 0x1106 */ + HQA_SetFreqOffset, /* 0x1107 */ + HQA_SetAutoResponder, /* 0x1108 */ + HQA_SetTssiOnOff, /* 0x1109 */ + HQA_SetRxHighLowTemperatureCompensation, /* 0x110A */ + HQA_LowPower, /* 0x110B */ +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Reset TRX Counter +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_ResetTxRxCounter(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + UINT_32 i4Status; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_ResetTxRxCounter\n"); + + i4Status = MT_ATEResetTXRXCounter(prNetDev); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetStatistics(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_GetStatistics\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetRxOKData(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_GetRxOKData\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetRxOKOther(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_GetRxOKOther\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetRxAllPktCount(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_GetRxAllPktCount\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetTxTransmitted(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_GetTxTransmitted\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetHwCounter(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_GetHwCounter\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_CalibrationOperation(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_CalibrationOperation\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_CalibrationBypassExt(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Status = 0; + UINT_32 u4Item = 0; + UINT_32 u4Band_idx = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 u4BufLen = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memcpy(&u4Item, HqaCmdFrame->Data, 4); + u4Item = ntohl(u4Item); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_CalibrationBypassExt u4Item : 0x%08x\n", u4Item); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_CalibrationBypassExt u4Band_idx : %d\n", u4Band_idx); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_BYPASS_CAL_STEP; + rRfATInfo.u4FuncData = u4Item; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetRXVectorIdx(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 band_idx = 0; + UINT_32 Group_1 = 0, Group_2 = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 u4BufLen = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memcpy(&band_idx, HqaCmdFrame->Data + 4 * 0, 4); + band_idx = ntohl(band_idx); + memcpy(&Group_1, HqaCmdFrame->Data + 4 * 1, 4); + Group_1 = ntohl(Group_1); + memcpy(&Group_2, HqaCmdFrame->Data + 4 * 2, 4); + Group_2 = ntohl(Group_2); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetRXVectorIdx band_idx : %d\n", band_idx); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetRXVectorIdx Group_1 : %d\n", Group_1); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetRXVectorIdx Group_2 : %d\n", Group_2); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_RXV_INDEX; + rRfATInfo.u4FuncData = (UINT_32) (Group_1); + rRfATInfo.u4FuncData |= (UINT_32) (Group_2 << 8); + rRfATInfo.u4FuncData |= (UINT_32) (band_idx << 16); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetRXVectorIdx rRfATInfo.u4FuncData : 0x%08x\n", + rRfATInfo.u4FuncData); + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set FAGC Rssi Path +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetFAGCRssiPath(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4band_idx = 0; + UINT_32 u4FAGC_Path = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 u4BufLen = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memcpy(&u4band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4band_idx = ntohl(u4band_idx); + memcpy(&u4FAGC_Path, HqaCmdFrame->Data + 4 * 1, 4); + u4FAGC_Path = ntohl(u4FAGC_Path); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetFAGCRssiPath u4band_idx : %d\n", u4band_idx); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetFAGCRssiPath u4FAGC_Path : %d\n", u4FAGC_Path); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_FAGC_RSSI_PATH; + rRfATInfo.u4FuncData = (UINT_32) ((u4band_idx << 16) || (u4FAGC_Path & BITS(0, 15))); + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_CMD_SET2[] = { + /* cmd id start from 0x1200 */ + HQA_ResetTxRxCounter, /* 0x1200 */ + HQA_GetStatistics, /* 0x1201 */ + HQA_GetRxOKData, /* 0x1202 */ + HQA_GetRxOKOther, /* 0x1203 */ + HQA_GetRxAllPktCount, /* 0x1204 */ + HQA_GetTxTransmitted, /* 0x1205 */ + HQA_GetHwCounter, /* 0x1206 */ + HQA_CalibrationOperation, /* 0x1207 */ + HQA_CalibrationBypassExt, /* 0x1208 */ + HQA_SetRXVectorIdx, /* 0x1209 */ + HQA_SetFAGCRssiPath, /* 0x120A */ +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For MAC CR Read. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_MacBbpRegRead(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + UINT_32 u4Offset, u4Value; + INT_32 i4Status; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MCR_RW_STRUCT_T rMcrInfo; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MacBbpRegRead\n"); + + memcpy(&u4Offset, HqaCmdFrame->Data, 4); + u4Offset = ntohl(u4Offset); + + DBGLOG(RFTEST, INFO, + "MT6632 : QA_AGENT HQA_MacBbpRegRead Offset = 0x%08x\n", + u4Offset); + + rMcrInfo.u4McrOffset = u4Offset; + rMcrInfo.u4McrData = 0; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, wlanoidQueryMcrRead, &rMcrInfo, sizeof(rMcrInfo), TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + u4Value = rMcrInfo.u4McrData; + + DBGLOG(RFTEST, INFO, + "MT6632 : QA_AGENT Address = 0x%08x, Result = 0x%08x\n", + u4Offset, u4Value); + + u4Value = ntohl(u4Value); + memcpy(HqaCmdFrame->Data + 2, &u4Value, 4); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For MAC CR Write. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_MacBbpRegWrite(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + +/* INT_32 i4Ret = 0; */ + UINT_32 u4Offset, u4Value; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MCR_RW_STRUCT_T rMcrInfo; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MacBbpRegWrite\n"); + + memcpy(&u4Offset, HqaCmdFrame->Data, 4); + memcpy(&u4Value, HqaCmdFrame->Data + 4, 4); + + u4Offset = ntohl(u4Offset); + u4Value = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, + "MT6632 : QA_AGENT HQA_MacBbpRegWrite Offset = 0x%08x\n", + u4Offset); + DBGLOG(RFTEST, INFO, + "MT6632 : QA_AGENT HQA_MacBbpRegWrite Value = 0x%08x\n", + u4Value); + + rMcrInfo.u4McrOffset = u4Offset; + rMcrInfo.u4McrData = u4Value; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, wlanoidSetMcrWrite, &rMcrInfo, sizeof(rMcrInfo), FALSE, FALSE, TRUE, &u4BufLen); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Read Bulk MAC CR. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_MACBbpRegBulkRead(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + UINT_32 u4Index, u4Offset, u4Value; + UINT_16 u2Len; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MCR_RW_STRUCT_T rMcrInfo; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MACBbpRegBulkRead\n"); + + memcpy(&u4Offset, HqaCmdFrame->Data, 4); + u4Offset = ntohl(u4Offset); + memcpy(&u2Len, HqaCmdFrame->Data + 4, 2); + u2Len = ntohs(u2Len); + + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MACBbpRegBulkRead Offset = 0x%08x\n", + u4Offset); + DBGLOG(RFTEST, INFO, + "QA_AGENT HQA_MACBbpRegBulkRead Len = 0x%08x\n", + u2Len); + + for (u4Index = 0; u4Index < u2Len; u4Index++) { + rMcrInfo.u4McrOffset = u4Offset + u4Index * 4; + rMcrInfo.u4McrData = 0; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, + wlanoidQueryMcrRead, &rMcrInfo, sizeof(rMcrInfo), TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + u4Value = rMcrInfo.u4McrData; + + DBGLOG(RFTEST, INFO, + "QA_AGENT Address = 0x%08x, Result = 0x%08x\n", + u4Offset + u4Index * 4, u4Value); + + u4Value = ntohl(u4Value); + memcpy(HqaCmdFrame->Data + 2 + (u4Index * 4), &u4Value, 4); + } + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + (u2Len * 4), i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Read Bulk RF CR. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_RfRegBulkRead(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + UINT_32 u4Index, u4WfSel, u4Offset, u4Length, u4Value; + INT_32 i4Status = 0; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MCR_RW_STRUCT_T rMcrInfo; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_RfRegBulkRead\n"); + + memcpy(&u4WfSel, HqaCmdFrame->Data, 4); + u4WfSel = ntohl(u4WfSel); + memcpy(&u4Offset, HqaCmdFrame->Data + 4, 4); + u4Offset = ntohl(u4Offset); + memcpy(&u4Length, HqaCmdFrame->Data + 8, 4); + u4Length = ntohl(u4Length); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_RfRegBulkRead WfSel = %d\n", u4WfSel); + DBGLOG(RFTEST, INFO, + "MT6632 : QA_AGENT HQA_RfRegBulkRead Offset = 0x%08x\n", + u4Offset); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_RfRegBulkRead Length = %d\n", u4Length); + + if (u4WfSel == 0) + u4Offset = u4Offset | 0x99900000; + else if (u4WfSel == 1) + u4Offset = u4Offset | 0x99910000; + + + for (u4Index = 0; u4Index < u4Length; u4Index++) { + rMcrInfo.u4McrOffset = u4Offset + u4Index * 4; + rMcrInfo.u4McrData = 0; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, + wlanoidQueryMcrRead, &rMcrInfo, sizeof(rMcrInfo), TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + u4Value = rMcrInfo.u4McrData; + + DBGLOG(RFTEST, INFO, + "QA_AGENT Address = 0x%08x, Result = 0x%08x\n", + u4Offset + u4Index * 4, u4Value); + + u4Value = ntohl(u4Value); + memcpy(HqaCmdFrame->Data + 2 + (u4Index * 4), &u4Value, 4); + } + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + (u4Length * 4), i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Write RF CR. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_RfRegBulkWrite(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + UINT_32 u4WfSel, u4Offset, u4Length, u4Value; + INT_32 i4Status; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_MCR_RW_STRUCT_T rMcrInfo; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_RfRegBulkWrite\n"); + + memcpy(&u4WfSel, HqaCmdFrame->Data, 4); + u4WfSel = ntohl(u4WfSel); + memcpy(&u4Offset, HqaCmdFrame->Data + 4, 4); + u4Offset = ntohl(u4Offset); + memcpy(&u4Length, HqaCmdFrame->Data + 8, 4); + u4Length = ntohl(u4Length); + memcpy(&u4Value, HqaCmdFrame->Data + 12, 4); + u4Value = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_RfRegBulkWrite WfSel = %d\n", u4WfSel); + DBGLOG(RFTEST, INFO, + "MT6632 : QA_AGENT HQA_RfRegBulkWrite Offset = 0x%08x\n", + u4Offset); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_RfRegBulkWrite Length = %d\n", u4Length); + DBGLOG(RFTEST, INFO, + "MT6632 : QA_AGENT HQA_RfRegBulkWrite Value = 0x%08x\n", + u4Value); + + if (u4WfSel == 0) + u4Offset = u4Offset | 0x99900000; + else if (u4WfSel == 1) + u4Offset = u4Offset | 0x99910000; + + + rMcrInfo.u4McrOffset = u4Offset; + rMcrInfo.u4McrData = u4Value; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, wlanoidSetMcrWrite, &rMcrInfo, sizeof(rMcrInfo), FALSE, FALSE, TRUE, &u4BufLen); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_ReadEEPROM(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + + UINT_16 Offset; + UINT_16 Len; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + UINT_32 u4BufLen = 0; + UINT_8 u4Index = 0; + UINT_16 u4Value = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_ACCESS_EFUSE_T rAccessEfuseInfo; +#endif + + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT HQA_ReadEEPROM\n"); + + memcpy(&Offset, HqaCmdFrame->Data + 2 * 0, 2); + Offset = ntohs(Offset); + memcpy(&Len, HqaCmdFrame->Data + 2 * 1, 2); + Len = ntohs(Len); + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + kalMemSet(&rAccessEfuseInfo, 0, sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)); + + + rAccessEfuseInfo.u4Address = (Offset / EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfo, + sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T), TRUE, TRUE, TRUE, &u4BufLen); + + u4Index = Offset % EFUSE_BLOCK_SIZE; + if (u4Index <= 14) + u4Value = (prGlueInfo->prAdapter->aucEepromVaule[u4Index]) + | (prGlueInfo->prAdapter->aucEepromVaule[u4Index+1] << 8); + + + /* isVaild = pResult->u4Valid; */ + + if (rStatus == WLAN_STATUS_SUCCESS) { + + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT HQA_ReadEEPROM u4Value = %x\n", u4Value); + + u4Value = ntohl(u4Value); + memcpy(HqaCmdFrame->Data + 2, &u4Value, sizeof(u4Value)); + } +#endif + + ResponseToQA(HqaCmdFrame, prIwReqData, 4, rStatus); + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_WriteEEPROM(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + UINT_16 u4WriteData = 0; + UINT_32 u4BufLen = 0; + UINT_8 u4Index = 0; + UINT_16 Offset; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_ACCESS_EFUSE_T rAccessEfuseInfoWrite; + + memcpy(&Offset, HqaCmdFrame->Data + 2 * 0, 2); + Offset = ntohs(Offset); + memcpy(&u4WriteData, HqaCmdFrame->Data + 2 * 1, 2); + u4WriteData = ntohs(u4WriteData); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); +#if 0 + /* Read */ + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT HQA_ReadEEPROM\n"); + kalMemSet(&rAccessEfuseInfoRead, 0, sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)); + rAccessEfuseInfoRead.u4Address = (Offset / EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfoRead, + sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T), FALSE, FALSE, TRUE, &u4BufLen); +#endif + + /* Write */ + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT HQA_WriteEEPROM\n"); + kalMemSet(&rAccessEfuseInfoWrite, 0, sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)); + u4Index = Offset % EFUSE_BLOCK_SIZE; + + if (prGlueInfo->prAdapter->rWifiVar.ucEfuseBufferModeCal + == LOAD_EEPROM_BIN) { + uacEEPROMImage[Offset] = u4WriteData & 0xff; + uacEEPROMImage[Offset + 1] = u4WriteData >> 8 & 0xff; + } else { + + if (u4Index >= EFUSE_BLOCK_SIZE - 1) { + DBGLOG(INIT, ERROR, "MT6632 : efuse Offset error\n"); + return -EINVAL; + } + + prGlueInfo->prAdapter->aucEepromVaule[u4Index] = u4WriteData & 0xff; /* Note: u4WriteData is UINT_16 */ + prGlueInfo->prAdapter->aucEepromVaule[u4Index+1] = u4WriteData >> 8 & 0xff; + + kalMemCopy(rAccessEfuseInfoWrite.aucData, prGlueInfo->prAdapter->aucEepromVaule, 16); + rAccessEfuseInfoWrite.u4Address = (Offset / EFUSE_BLOCK_SIZE)*EFUSE_BLOCK_SIZE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseWrite, + &rAccessEfuseInfoWrite, + sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T), FALSE, FALSE, TRUE, &u4BufLen); + } +#endif + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_ReadBulkEEPROM(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_16 Offset; + UINT_16 Len; +#if (CFG_EEPROM_PAGE_ACCESS == 1) + PARAM_CUSTOM_ACCESS_EFUSE_T rAccessEfuseInfo; + UINT_32 u4BufLen = 0; + UINT_8 u4Loop = 0; + + UINT_16 Buffer; + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_8 tmp = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + kalMemSet(&rAccessEfuseInfo, 0, sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)); +#endif + + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT HQA_ReadBulkEEPROM\n"); + + memcpy(&Offset, HqaCmdFrame->Data + 2 * 0, 2); + Offset = ntohs(Offset); + memcpy(&Len, HqaCmdFrame->Data + 2 * 1, 2); + Len = ntohs(Len); + tmp = Offset; + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT HQA_ReadBulkEEPROM Offset : %d\n", Offset); + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT HQA_ReadBulkEEPROM Len : %d\n", Len); + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + rAccessEfuseInfo.u4Address = (Offset / EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT HQA_ReadBulkEEPROM Address : %d\n", rAccessEfuseInfo.u4Address); + + if ((g_ucEepromCurrentMode == EFUSE_MODE) + && (prGlueInfo->prAdapter->fgIsSupportQAAccessEfuse == TRUE)) { + + /* Read from Efuse */ + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT HQA_ReadBulkEEPROM Efuse Mode\n"); + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfo, + sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T), TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_FAILURE) + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT HQA_ReadBulkEEPROM kal fail\n"); + + Offset = Offset % EFUSE_BLOCK_SIZE; + +#if 0 + for (u4Loop = 0; u4Loop < 16; u4Loop++) { + DBGLOG(INIT, INFO, "MT6632:QA_AGENT HQA_ReadBulkEEPROM Efuse Offset=%x u4Loop=%d u4Value=%x\n", + Offset, u4Loop, prGlueInfo->prAdapter->aucEepromVaule[u4Loop]); + } +#endif + for (u4Loop = 0; u4Loop < Len; u4Loop += 2) { + memcpy(&Buffer, prGlueInfo->prAdapter->aucEepromVaule + Offset + u4Loop, 2); + Buffer = ntohs(Buffer); + DBGLOG(INIT, INFO, "MT6632 :From Efuse u4Loop=%d Buffer=%x\n", u4Loop, Buffer); + memcpy(HqaCmdFrame->Data + 2 + u4Loop, &Buffer, 2); + } + + } else { /* Read from EEPROM */ + for (u4Loop = 0; u4Loop < Len; u4Loop += 2) { + memcpy(&Buffer, uacEEPROMImage + Offset + u4Loop, 2); + Buffer = ntohs(Buffer); + memcpy(HqaCmdFrame->Data + 2 + u4Loop, &Buffer, 2); + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT HQA_ReadBulkEEPROM u4Loop=%d u4Value=%x\n", + u4Loop, uacEEPROMImage[Offset + u4Loop]); + } + } +#endif + + /*kfree(Buffer);*/ + + /* Read from buffer array in driver */ + /* Pass these data to FW also */ +#if 0 + for (i = 0 ; i < Len ; i += 2) { + memcpy(&u2Temp, uacEEPROMImage + Offset + i, 2); + u2Temp = ntohs(u2Temp); + memcpy(HqaCmdFrame->Data + 2 + i, &u2Temp, 2); + } +#endif + /* For SA Buffer Mode Temp Solution */ +#if 0 + if (Offset == 0x4A0 && !g_BufferDownload) { + + UINT_16 u2InitAddr = 0x000; + UINT_32 i = 0, j = 0; + UINT_32 u4BufLen = 0; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_EFUSE_BUFFER_MODE_T rSetEfuseBufModeInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + for (i = 0 ; i < MAX_EEPROM_BUFFER_SIZE/16 ; i++) { + for (j = 0 ; j < 16 ; j++) { + rSetEfuseBufModeInfo.aBinContent[j].u2Addr = u2InitAddr; + rSetEfuseBufModeInfo.aBinContent[j].ucValue = uacEEPROMImage[u2InitAddr]; + u2InitAddr += 1; + } + + rSetEfuseBufModeInfo.ucSourceMode = 1; + rSetEfuseBufModeInfo.ucCount = EFUSE_CONTENT_SIZE; + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEfusBufferMode, + &rSetEfuseBufModeInfo, + sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T), FALSE, FALSE, TRUE, &u4BufLen); + } + + g_BufferDownload = TRUE; + } +#endif + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + Len, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_WriteBulkEEPROM(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_16 Offset; + UINT_16 Len; + P_ADAPTER_T prAdapter = NULL; + + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_ACCESS_EFUSE_T rAccessEfuseInfoRead, rAccessEfuseInfoWrite; + UINT_16 testBuffer1, testBuffer2, testBuffer; + UINT_16 *Buffer = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_8 u4Loop = 0, u4Index = 0; + UINT_16 ucTemp2; + UINT_16 i = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + kalMemSet(&rAccessEfuseInfoRead, 0, sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)); + kalMemSet(&rAccessEfuseInfoWrite, 0, sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)); + + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT HQA_WriteBulkEEPROM\n"); + + + memcpy(&Offset, HqaCmdFrame->Data + 2 * 0, 2); + Offset = ntohs(Offset); + memcpy(&Len, HqaCmdFrame->Data + 2 * 1, 2); + Len = ntohs(Len); + + memcpy(&testBuffer1, HqaCmdFrame->Data + 2 * 2, Len); + testBuffer2 = ntohs(testBuffer1); + testBuffer = ntohs(testBuffer1); + + + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT HQA_WriteBulkEEPROM Offset : %x\n", Offset); + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT HQA_WriteBulkEEPROM Len : %d\n", Len); + + + /* Support Delay Calibraiton */ + if (prGlueInfo->prAdapter->fgIsSupportQAAccessEfuse == TRUE) { + + Buffer = kmalloc(sizeof(UINT_8)*(EFUSE_BLOCK_SIZE), GFP_KERNEL); + if (!Buffer) + return -ENOMEM; + kalMemSet(Buffer, 0, sizeof(UINT_8)*(EFUSE_BLOCK_SIZE)); + + kalMemCopy((UINT_8 *)Buffer, (UINT_8 *)HqaCmdFrame->Data + 4, Len); + +#if 0 + for (u4Loop = 0; u4Loop < (Len)/2; u4Loop++) { + + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT HQA_WriteBulkEEPROM u4Loop=%d u4Value=%x\n", + u4Loop, Buffer[u4Loop]); + } +#endif + + if (g_ucEepromCurrentMode == BUFFER_BIN_MODE) { + /* EEPROM */ + DBGLOG(INIT, INFO, "Direct EEPROM buffer, offset=%x, len=%x\n", Offset, Len); +#if 0 + for (i = 0; i < EFUSE_BLOCK_SIZE; i++) + memcpy(uacEEPROMImage + Offset + i, Buffer + i, 1); + +#endif + if (Len > 2) { + for (u4Loop = 0; u4Loop < EFUSE_BLOCK_SIZE/2 ; u4Loop++) { + Buffer[u4Loop] = ntohs(Buffer[u4Loop]); + uacEEPROMImage[Offset] = Buffer[u4Loop] & 0xff; + uacEEPROMImage[Offset + 1] = Buffer[u4Loop] >> 8 & 0xff; + Offset += 2; + } + } else { + *Buffer = ntohs(*Buffer); + uacEEPROMImage[Offset] = *Buffer & 0xff; + uacEEPROMImage[Offset + 1] = *Buffer >> 8 & 0xff; + } + } else if (g_ucEepromCurrentMode == EFUSE_MODE) { + /* EFUSE */ + /* Read */ + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT HQA_WriteBulkEEPROM Read\n"); + kalMemSet(&rAccessEfuseInfoRead, 0, sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)); + rAccessEfuseInfoRead.u4Address = (Offset / EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfoRead, + sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T), TRUE, TRUE, TRUE, &u4BufLen); + + /* Write */ + kalMemSet(&rAccessEfuseInfoWrite, 0, sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)); + + if (Len > 2) { + for (u4Loop = 0; u4Loop < 8 ; u4Loop++) + Buffer[u4Loop] = ntohs(Buffer[u4Loop]); + memcpy(rAccessEfuseInfoWrite.aucData, Buffer, 16); + } else { + u4Index = Offset % EFUSE_BLOCK_SIZE; + DBGLOG(INIT, INFO, "MT6632:QA_AGENT HQA_WriteBulkEEPROM Wr,u4Index=%x,Buffer=%x\n", + u4Index, testBuffer); + + if (u4Index >= EFUSE_BLOCK_SIZE - 1) { + DBGLOG(INIT, ERROR, "MT6632 : efuse Offset error\n"); + i4Ret = -EINVAL; + goto exit; + } + + + *Buffer = ntohs(*Buffer); + DBGLOG(INIT, INFO, "MT6632 : Buffer[0]=%x, Buffer[0]&0xff=%x\n" + , Buffer[0], Buffer[0]&0xff); + DBGLOG(INIT, INFO, "MT6632 : Buffer[0] >> 8 & 0xff=%x\n" + , Buffer[0] >> 8 & 0xff); + + prGlueInfo->prAdapter->aucEepromVaule[u4Index] = *Buffer & 0xff; + prGlueInfo->prAdapter->aucEepromVaule[u4Index+1] = *Buffer >> 8 & 0xff; + kalMemCopy(rAccessEfuseInfoWrite.aucData, prGlueInfo->prAdapter->aucEepromVaule, 16); + } + + rAccessEfuseInfoWrite.u4Address = (Offset / EFUSE_BLOCK_SIZE)*EFUSE_BLOCK_SIZE; + for (u4Loop = 0; u4Loop < (EFUSE_BLOCK_SIZE); u4Loop++) { + + DBGLOG(INIT, INFO, "MT6632 : Loop=%d aucData=%x\n", + u4Loop, rAccessEfuseInfoWrite.aucData[u4Loop]); + } + + DBGLOG(INIT, INFO, "Going for e-Fuse\n"); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseWrite, + &rAccessEfuseInfoWrite, + sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T), + FALSE, TRUE, TRUE, &u4BufLen); + } else { + DBGLOG(INIT, INFO, "Invalid ID!!\n"); + } + } else { + + if (Len == 2) { + memcpy(&ucTemp2, HqaCmdFrame->Data + 2 * 2, 2); + ucTemp2 = ntohs(ucTemp2); + memcpy(uacEEPROMImage + Offset, &ucTemp2, Len); + } else { + for (i = 0 ; i < 8 ; i++) { + memcpy(&ucTemp2, HqaCmdFrame->Data + 2 * 2 + 2*i, 2); + ucTemp2 = ntohs(ucTemp2); + memcpy(uacEEPROMImage + Offset + 2*i, &ucTemp2, 2); + } + + if (!g_BufferDownload) { + UINT_16 u2InitAddr = Offset; + UINT_32 j = 0; + UINT_32 u4BufLen = 0; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_EFUSE_BUFFER_MODE_T *prSetEfuseBufModeInfo = NULL; + BIN_CONTENT_T *pBinContent; + + prSetEfuseBufModeInfo = (PARAM_CUSTOM_EFUSE_BUFFER_MODE_T *) + kalMemAlloc(sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T), VIR_MEM_TYPE); + if (prSetEfuseBufModeInfo == NULL) + return 0; + kalMemZero(prSetEfuseBufModeInfo, sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T)); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + pBinContent = (BIN_CONTENT_T *)prSetEfuseBufModeInfo->aBinContent; + + for (j = 0 ; j < 16 ; j++) { + pBinContent->u2Addr = u2InitAddr; + pBinContent->ucValue = uacEEPROMImage[u2InitAddr]; + + pBinContent++; + } + + prSetEfuseBufModeInfo->ucSourceMode = 1; + prSetEfuseBufModeInfo->ucCount = EFUSE_CONTENT_SIZE; + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEfusBufferMode, + (PVOID)prSetEfuseBufModeInfo, + sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T), + FALSE, FALSE, TRUE, &u4BufLen); + + kalMemFree(prSetEfuseBufModeInfo, VIR_MEM_TYPE, + sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T)); + + if (Offset == 0x4A0) + g_BufferDownload = TRUE; + } + } + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + Len, i4Ret); + +exit: + kfree(Buffer); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_CheckEfuseMode(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 Value = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_CheckEfuseMode\n"); + + /* Value: 0:eeprom mode, 1:eFuse mode */ + Value = ntohl(Value); + memcpy(HqaCmdFrame->Data + 2, &(Value), sizeof(Value)); + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetFreeEfuseBlock(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + + INT_32 i4Ret = 0, u4FreeBlockCount = 0; + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + PARAM_CUSTOM_EFUSE_FREE_BLOCK_T rEfuseFreeBlock; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; +#endif + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(INIT, INFO, "MT6632 : QA_AGENT HQA_GetFreeEfuseBlock\n"); + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + if (prGlueInfo->prAdapter->fgIsSupportGetFreeEfuseBlockCount == TRUE) { + kalMemSet(&rEfuseFreeBlock, 0, sizeof(PARAM_CUSTOM_EFUSE_FREE_BLOCK_T)); + + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryEfuseFreeBlock, + &rEfuseFreeBlock, + sizeof(PARAM_CUSTOM_EFUSE_FREE_BLOCK_T), TRUE, TRUE, TRUE, &u4BufLen); + + u4FreeBlockCount = prGlueInfo->prAdapter->u4FreeBlockNum; + u4FreeBlockCount = ntohl(u4FreeBlockCount); + kalMemCopy(HqaCmdFrame->Data + 2, &u4FreeBlockCount, 4); + } +#endif + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetEfuseBlockNr(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_GetEfuseBlockNr\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_WriteEFuseFromBuffer(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_WriteEFuseFromBuffer\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetTxPower(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Channel = 0, u4Band = 0, u4Ch_Band = 0, u4TxTargetPower = 0; +/* UINT_32 u4EfuseAddr = 0, u4Power = 0; */ + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + PARAM_CUSTOM_GET_TX_POWER_T rGetTxPower; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; +#endif + + memcpy(&u4Channel, HqaCmdFrame->Data + 4 * 0, 4); + u4Channel = ntohl(u4Channel); + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 1, 4); + u4Band = ntohl(u4Band); + memcpy(&u4Ch_Band, HqaCmdFrame->Data + 4 * 2, 4); + u4Ch_Band = ntohl(u4Ch_Band); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_GetTxPower u4Channel : %d\n", u4Channel); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_GetTxPower u4Band : %d\n", u4Band); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_GetTxPower u4Ch_Band : %d\n", u4Ch_Band); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (prGlueInfo->prAdapter->fgIsSupportGetTxPower == TRUE) { + kalMemSet(&rGetTxPower, 0, sizeof(PARAM_CUSTOM_GET_TX_POWER_T)); + + rGetTxPower.ucCenterChannel = u4Channel; + rGetTxPower.ucBand = u4Band; + rGetTxPower.ucDbdcIdx = u4Ch_Band; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryGetTxPower, + &rGetTxPower, + sizeof(PARAM_CUSTOM_GET_TX_POWER_T), TRUE, TRUE, TRUE, &u4BufLen); + + u4TxTargetPower = prGlueInfo->prAdapter->u4GetTxPower; + u4TxTargetPower = ntohl(u4TxTargetPower); + kalMemCopy(HqaCmdFrame->Data + 6, &u4TxTargetPower, 4); + } + ResponseToQA(HqaCmdFrame, prIwReqData, 10, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetCfgOnOff(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 Type, Enable, Band; + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 u4BufLen = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memcpy(&Type, HqaCmdFrame->Data + 4 * 0, 4); + Type = ntohl(Type); + memcpy(&Enable, HqaCmdFrame->Data + 4 * 1, 4); + Enable = ntohl(Enable); + memcpy(&Band, HqaCmdFrame->Data + 4 * 2, 4); + Band = ntohl(Band); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetCfgOnOff Type : %d\n", Type); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetCfgOnOff Enable : %d\n", Enable); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetCfgOnOff Band : %d\n", Band); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_TSSI; + rRfATInfo.u4FuncData = 0; + + if (Band == 0 && Enable == 1) + rRfATInfo.u4FuncData |= BIT(0); + else if (Band == 1 && Enable == 1) + rRfATInfo.u4FuncData |= BIT(1); + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetFreqOffset(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4FreqOffset = 0; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_GET_FREQ_OFFSET; + rRfATInfo.u4FuncData = 0; + + i4Ret = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, &rRfATInfo, sizeof(rRfATInfo), TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Ret == 0) { + u4FreqOffset = rRfATInfo.u4FuncData; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_GetFreqOffset u4FreqOffset = %d\n", u4FreqOffset); + + u4FreqOffset = ntohl(u4FreqOffset); + memcpy(HqaCmdFrame->Data + 2, &u4FreqOffset, sizeof(u4FreqOffset)); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_DBDCTXTone(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + INT_32 i4BandIdx = 0, i4Control = 0, i4AntIndex = 0, i4ToneType = 0, i4ToneFreq = 0; + INT_32 i4DcOffsetI = 0, i4DcOffsetQ = 0, i4Band = 0, i4RF_Power = 0, i4Digi_Power = 0; + + memcpy(&i4BandIdx, HqaCmdFrame->Data + 4 * 0, 4); /* DBDC Band Index : Band0, Band1 */ + i4BandIdx = ntohl(i4BandIdx); + memcpy(&i4Control, HqaCmdFrame->Data + 4 * 1, 4); /* Control TX Tone Start and Stop */ + i4Control = ntohl(i4Control); + memcpy(&i4AntIndex, HqaCmdFrame->Data + 4 * 2, 4); /* Select TX Antenna */ + i4AntIndex = ntohl(i4AntIndex); + memcpy(&i4ToneType, HqaCmdFrame->Data + 4 * 3, 4); /* ToneType : Single or Two */ + i4ToneType = ntohl(i4ToneType); + memcpy(&i4ToneFreq, HqaCmdFrame->Data + 4 * 4, 4); /* ToneFreq: DC/5M/10M/20M/40M */ + i4ToneFreq = ntohl(i4ToneFreq); + memcpy(&i4DcOffsetI, HqaCmdFrame->Data + 4 * 5, 4); /* DC Offset I : -512~1535 */ + i4DcOffsetI = ntohl(i4DcOffsetI); + memcpy(&i4DcOffsetQ, HqaCmdFrame->Data + 4 * 6, 4); /* DC Offset Q : -512~1535 */ + i4DcOffsetQ = ntohl(i4DcOffsetQ); + memcpy(&i4Band, HqaCmdFrame->Data + 4 * 7, 4); /* Band : 2.4G/5G */ + i4Band = ntohl(i4Band); + memcpy(&i4RF_Power, HqaCmdFrame->Data + 4 * 8, 4); /* RF_Power: (1db) 0~15 */ + i4RF_Power = ntohl(i4RF_Power); + memcpy(&i4Digi_Power, HqaCmdFrame->Data + 4 * 9, 4); /* Digi_Power: (0.25db) -32~31 */ + i4Digi_Power = ntohl(i4Digi_Power); + + DBGLOG(RFTEST, INFO, + "MT6632 : QA_AGENT HQA_DBDCTXTone BandIdx = 0x%08x\n", + i4BandIdx); + DBGLOG(RFTEST, INFO, + "MT6632 : QA_AGENT HQA_DBDCTXTone Control = 0x%08x\n", + i4Control); + DBGLOG(RFTEST, INFO, + "MT6632 : QA_AGENT HQA_DBDCTXTone AntIndex = 0x%08x\n", + i4AntIndex); + DBGLOG(RFTEST, INFO, + "MT6632 : QA_AGENT HQA_DBDCTXTone ToneType = 0x%08x\n", + i4ToneType); + DBGLOG(RFTEST, INFO, + "MT6632 : QA_AGENT HQA_DBDCTXTone ToneFreq = 0x%08x\n", + i4ToneFreq); + DBGLOG(RFTEST, INFO, + "MT6632 : QA_AGENT HQA_DBDCTXTone DcOffsetI = 0x%08x\n", + i4DcOffsetI); + DBGLOG(RFTEST, INFO, + "MT6632 : QA_AGENT HQA_DBDCTXTone DcOffsetQ = 0x%08x\n", + i4DcOffsetQ); + DBGLOG(RFTEST, INFO, + "MT6632 : QA_AGENT HQA_DBDCTXTone Band = 0x%08x\n", + i4Band); + DBGLOG(RFTEST, INFO, + "MT6632 : QA_AGENT HQA_DBDCTXTone RF_Power = 0x%08x\n", + i4RF_Power); + DBGLOG(RFTEST, INFO, + "MT6632 : QA_AGENT HQA_DBDCTXTone Digi_Power = 0x%08x\n", + i4Digi_Power); + + /* + * Select TX Antenna + * RF_Power: (1db) 0~15 + * Digi_Power: (0.25db) -32~31 + */ + MT_ATESetDBDCTxTonePower(prNetDev, i4AntIndex, i4RF_Power, i4Digi_Power); + + /* DBDC Band Index : Band0, Band1 */ + MT_ATESetDBDCBandIndex(prNetDev, i4BandIdx); + + if (i4Control) { + /* Band : 2.4G/5G */ + MT_ATESetBand(prNetDev, i4Band); + + /* ToneType : Single or Two */ + MT_ATESetTxToneType(prNetDev, i4ToneType); + + /* ToneFreq: DC/5M/10M/20M/40M */ + MT_ATESetTxToneBW(prNetDev, i4ToneFreq); + + /* DC Offset I, DC Offset Q */ + MT_ATESetTxToneDCOffset(prNetDev, i4DcOffsetI, i4DcOffsetQ); + + /* Control TX Tone Start and Stop */ + MT_ATEDBDCTxTone(prNetDev, i4Control); + } else { + /* Control TX Tone Start and Stop */ + MT_ATEDBDCTxTone(prNetDev, i4Control); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_DBDCContinuousTX(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Band = 0, u4Control = 0, u4AntMask = 0, u4Phymode = 0, u4BW = 0; + UINT_32 u4Pri_Ch = 0, u4Rate = 0, u4Central_Ch = 0, u4TxfdMode = 0, u4Freq = 0; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 0, 4); + u4Band = ntohl(u4Band); + memcpy(&u4Control, HqaCmdFrame->Data + 4 * 1, 4); + u4Control = ntohl(u4Control); + memcpy(&u4AntMask, HqaCmdFrame->Data + 4 * 2, 4); + u4AntMask = ntohl(u4AntMask); + memcpy(&u4Phymode, HqaCmdFrame->Data + 4 * 3, 4); + u4Phymode = ntohl(u4Phymode); + memcpy(&u4BW, HqaCmdFrame->Data + 4 * 4, 4); + u4BW = ntohl(u4BW); + memcpy(&u4Pri_Ch, HqaCmdFrame->Data + 4 * 5, 4); + u4Pri_Ch = ntohl(u4Pri_Ch); + memcpy(&u4Rate, HqaCmdFrame->Data + 4 * 6, 4); + u4Rate = ntohl(u4Rate); + memcpy(&u4Central_Ch, HqaCmdFrame->Data + 4 * 7, 4); + u4Central_Ch = ntohl(u4Central_Ch); + memcpy(&u4TxfdMode, HqaCmdFrame->Data + 4 * 8, 4); + u4TxfdMode = ntohl(u4TxfdMode); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_DBDCContinuousTX u4Band : %d\n", u4Band); /* ok */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_DBDCContinuousTX u4Control : %d\n", u4Control); /* ok */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_DBDCContinuousTX u4AntMask : %d\n", u4AntMask); /* ok */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_DBDCContinuousTX u4Phymode : %d\n", u4Phymode); /* ok */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_DBDCContinuousTX u4BW : %d\n", u4BW); /* ok */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_DBDCContinuousTX u4Pri_Ch : %d\n", u4Pri_Ch); /* ok */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_DBDCContinuousTX u4Rate : %d\n", u4Rate); /* ok */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_DBDCContinuousTX u4Central_Ch : %d\n", u4Central_Ch); /* ok */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_DBDCContinuousTX u4TxfdMode : %d\n", u4TxfdMode); /* ok */ + + if (u4Control) { + MT_ATESetDBDCBandIndex(prNetDev, u4Band); + u4Freq = nicChannelNum2Freq(u4Central_Ch); + MT_ATESetChannel(prNetDev, 0, u4Freq); + MT_ATEPrimarySetting(prNetDev, u4Pri_Ch); + + if (u4Phymode == 1) { + u4Phymode = 0; + u4Rate += 4; + } else if ((u4Phymode == 0) && ((u4Rate == 9) || (u4Rate == 10) || (u4Rate == 11))) + u4Phymode = 1; + MT_ATESetPreamble(prNetDev, u4Phymode); + + if (u4Phymode == 0) { + u4Rate |= 0x00000000; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT CCK/OFDM (normal preamble) rate : %d\n", u4Rate); + + MT_ATESetRate(prNetDev, u4Rate); + } else if (u4Phymode == 1) { + if (u4Rate == 9) + u4Rate = 1; + else if (u4Rate == 10) + u4Rate = 2; + else if (u4Rate == 11) + u4Rate = 3; + u4Rate |= 0x00000000; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT CCK (short preamble) rate : %d\n", u4Rate); + + MT_ATESetRate(prNetDev, u4Rate); + } else if (u4Phymode >= 2 && u4Phymode <= 4) { + u4Rate |= 0x80000000; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HT/VHT rate : %d\n", u4Rate); + + MT_ATESetRate(prNetDev, u4Rate); + } + + MT_ATESetSystemBW(prNetDev, u4BW); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_CW_MODE; + rRfATInfo.u4FuncData = u4TxfdMode; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ANTMASK; + rRfATInfo.u4FuncData = u4AntMask; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_CW; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + } else { + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_STOPTEST; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetRXFilterPktLen(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Band = 0, u4Control = 0, u4RxPktlen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 u4BufLen = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 0, 4); + u4Band = ntohl(u4Band); + memcpy(&u4Control, HqaCmdFrame->Data + 4 * 1, 4); + u4Control = ntohl(u4Control); + memcpy(&u4RxPktlen, HqaCmdFrame->Data + 4 * 2, 4); + u4RxPktlen = ntohl(u4RxPktlen); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetRXFilterPktLen Band : %d\n", u4Band); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetRXFilterPktLen Control : %d\n", u4Control); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetRXFilterPktLen RxPktlen : %d\n", u4RxPktlen); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_RX_FILTER_PKT_LEN; + rRfATInfo.u4FuncData = (UINT_32) (u4RxPktlen & BITS(0, 23)); + rRfATInfo.u4FuncData |= (UINT_32) (u4Band << 24); + + if (u4Control == 1) + rRfATInfo.u4FuncData |= BIT(30); + else + rRfATInfo.u4FuncData &= ~BIT(30); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetRXFilterPktLen rRfATInfo.u4FuncData : 0x%08x\n", + rRfATInfo.u4FuncData); + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetTXInfo(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + UINT_32 u4Txed_band0 = 0; + UINT_32 u4Txed_band1 = 0; + INT_32 i4Status; + UINT_32 u4BufLen = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_GetTXInfo\n"); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_TXED_COUNT; + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, &rRfATInfo, sizeof(rRfATInfo), TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + u4Txed_band0 = rRfATInfo.u4FuncData; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT u4Txed_band0 packet count = %d\n", u4Txed_band0); + + u4Txed_band0 = ntohl(u4Txed_band0); + memcpy(HqaCmdFrame->Data + 2, &u4Txed_band0, sizeof(u4Txed_band0)); + } + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_TXED_COUNT; + rRfATInfo.u4FuncIndex |= BIT(8); + rRfATInfo.u4FuncData = 0; + + i4Status = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, &rRfATInfo, sizeof(rRfATInfo), TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + u4Txed_band1 = rRfATInfo.u4FuncData; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT u4Txed_band1 packet count = %d\n", u4Txed_band1); + + u4Txed_band1 = ntohl(u4Txed_band1); + memcpy(HqaCmdFrame->Data + 2 + 4, &u4Txed_band1, sizeof(u4Txed_band1)); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + sizeof(u4Txed_band0) + sizeof(u4Txed_band1), i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetCfgOnOff(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_GetCfgOnOff\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetBufferBin(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 Ret = 0; + UINT_32 data = 0; + + kalMemCopy(&data, HqaCmdFrame->Data, sizeof(data)); + data = ntohl(data); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetBufferBin data=%x\n", data); + + if (data == BUFFER_BIN_MODE) { + /*Buffer mode*/ + g_ucEepromCurrentMode = BUFFER_BIN_MODE; + } else if (data == EFUSE_MODE) { + /*Efuse mode */ + g_ucEepromCurrentMode = EFUSE_MODE; + } else { + DBGLOG(RFTEST, INFO, "Invalid data!!\n"); + } + + DBGLOG(RFTEST, INFO, "MT6632 : ucEepromCurrentMode=%x\n", g_ucEepromCurrentMode); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, Ret); + return Ret; +} + + +static HQA_CMD_HANDLER HQA_CMD_SET3[] = { + /* cmd id start from 0x1300 */ + HQA_MacBbpRegRead, /* 0x1300 */ + HQA_MacBbpRegWrite, /* 0x1301 */ + HQA_MACBbpRegBulkRead, /* 0x1302 */ + HQA_RfRegBulkRead, /* 0x1303 */ + HQA_RfRegBulkWrite, /* 0x1304 */ + HQA_ReadEEPROM, /* 0x1305 */ + HQA_WriteEEPROM, /* 0x1306 */ + HQA_ReadBulkEEPROM, /* 0x1307 */ + HQA_WriteBulkEEPROM, /* 0x1308 */ + HQA_CheckEfuseMode, /* 0x1309 */ + HQA_GetFreeEfuseBlock, /* 0x130A */ + HQA_GetEfuseBlockNr, /* 0x130B */ + HQA_WriteEFuseFromBuffer, /* 0x130C */ + HQA_GetTxPower, /* 0x130D */ + HQA_SetCfgOnOff, /* 0x130E */ + HQA_GetFreqOffset, /* 0x130F */ + HQA_DBDCTXTone, /* 0x1310 */ + HQA_DBDCContinuousTX, /* 0x1311 */ + HQA_SetRXFilterPktLen, /* 0x1312 */ + HQA_GetTXInfo, /* 0x1313 */ + HQA_GetCfgOnOff, /* 0x1314 */ + NULL, /* 0x1315 */ + HQA_SetBufferBin, /* 0x1316 */ +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_ReadTempReferenceValue(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_ReadTempReferenceValue\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Get Thermal Value. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetThermalValue(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + UINT_32 u4Value; + UINT_32 u4BufLen = 0; + INT_32 i4Status; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_TEMP_SENSOR; + rRfATInfo.u4FuncData = 0; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + i4Status = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, &rRfATInfo, sizeof(rRfATInfo), TRUE, TRUE, TRUE, &u4BufLen); + + if (i4Status == 0) { + u4Value = rRfATInfo.u4FuncData; + u4Value = u4Value >> 16; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_GetThermalValue Value = %d\n", u4Value); + + u4Value = ntohl(u4Value); + memcpy(HqaCmdFrame->Data + 2, &u4Value, 4); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetSideBandOption(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetSideBandOption\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_CMD_SET4[] = { + /* cmd id start from 0x1400 */ + HQA_ReadTempReferenceValue, /* 0x1400 */ + HQA_GetThermalValue, /* 0x1401 */ + HQA_SetSideBandOption, /* 0x1402 */ +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetFWInfo(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_GetFWInfo\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_StartContinousTx(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_StartContinousTx\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetSTBC(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetSTBC\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Set short GI. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetShortGI(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4ShortGi; + + memcpy(&u4ShortGi, HqaCmdFrame->Data, 4); + u4ShortGi = ntohl(u4ShortGi); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetShortGI u4ShortGi = %d\n", u4ShortGi); + + i4Ret = MT_ATESetTxGi(prNetDev, u4ShortGi); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetDPD(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetDPD\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Get Rx Statistics. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetRxStatisticsAll(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4BufLen = 0; + PARAM_CUSTOM_ACCESS_RX_STAT rRxStatisticsTest; + + /* memset(&g_HqaRxStat, 0, sizeof(PARAM_RX_STAT_T)); */ + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_GetRxStatisticsAll\n"); + + rRxStatisticsTest.u4SeqNum = u4RxStatSeqNum; + rRxStatisticsTest.u4TotalNum = HQA_RX_STATISTIC_NUM + 6; + + i4Ret = kalIoctl(prGlueInfo, + wlanoidQueryRxStatistics, + &rRxStatisticsTest, sizeof(rRxStatisticsTest), TRUE, TRUE, TRUE, &u4BufLen); + + /* ASSERT(rRxStatisticsTest.u4SeqNum == u4RxStatSeqNum); */ + + u4RxStatSeqNum++; + + memcpy(HqaCmdFrame->Data + 2, &(g_HqaRxStat), sizeof(PARAM_RX_STAT_T)); + ResponseToQA(HqaCmdFrame, prIwReqData, (2 + sizeof(PARAM_RX_STAT_T)), i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_StartContiTxTone(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_StartContiTxTone\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_StopContiTxTone(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_StopContiTxTone\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_CalibrationTestMode(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Mode = 0; + UINT_32 u4IcapLen = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_CalibrationTestMode\n"); + + memcpy(&u4Mode, HqaCmdFrame->Data + 4 * 0, 4); + u4Mode = ntohl(u4Mode); + memcpy(&u4IcapLen, HqaCmdFrame->Data + 4 * 1, 4); + u4IcapLen = ntohl(u4IcapLen); + + if (u4Mode == 2) + i4Ret = MT_ICAPStart(prNetDev, "ICAPSTART"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_DoCalibrationTestItem(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Status = 0; + UINT_32 u4Item = 0; + UINT_32 u4Band_idx = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 u4BufLen = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memcpy(&u4Item, HqaCmdFrame->Data, 4); + u4Item = ntohl(u4Item); + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_DoCalibrationTestItem item : 0x%08x\n", u4Item); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_DoCalibrationTestItem band_idx : %d\n", u4Band_idx); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_RECAL_CAL_STEP; + rRfATInfo.u4FuncData = u4Item; + + i4Status = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Status); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_eFusePhysicalWrite(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_eFusePhysicalWrite\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_eFusePhysicalRead(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_eFusePhysicalRead\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_eFuseLogicalRead(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_eFuseLogicalRead\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_eFuseLogicalWrite(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_eFuseLogicalWrite\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_TMRSetting(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Setting; + UINT_32 u4Version; + UINT_32 u4MPThres; + UINT_32 u4MPIter; + + memcpy(&u4Setting, HqaCmdFrame->Data + 4 * 0, 4); + u4Setting = ntohl(u4Setting); + memcpy(&u4Version, HqaCmdFrame->Data + 4 * 1, 4); + u4Version = ntohl(u4Version); + memcpy(&u4MPThres, HqaCmdFrame->Data + 4 * 2, 4); + u4MPThres = ntohl(u4MPThres); + memcpy(&u4MPIter, HqaCmdFrame->Data + 4 * 3, 4); + u4MPIter = ntohl(u4MPIter); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_TMRSetting u4Setting : %d\n", u4Setting); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_TMRSetting u4Version : %d\n", u4Version); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_TMRSetting u4MPThres : %d\n", u4MPThres); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_TMRSetting u4MPIter : %d\n", u4MPIter); + + i4Ret = MT_ATE_TMRSetting(prNetDev, u4Setting, u4Version, u4MPThres, u4MPIter); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetRxSNR(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_GetRxSNR\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_WriteBufferDone(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_16 u2InitAddr; + UINT_32 Value; +/* UINT_32 i = 0, j = 0; +* UINT_32 u4BufLen = 0; +*/ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; +/* PARAM_CUSTOM_EFUSE_BUFFER_MODE_T rSetEfuseBufModeInfo; */ + PARAM_CUSTOM_EFUSE_BUFFER_MODE_T *prSetEfuseBufModeInfo = NULL; + PUINT_8 pucConfigBuf = NULL; + UINT_32 u4ContentLen; + UINT_32 u4BufLen = 0; + P_ADAPTER_T prAdapter = NULL; + + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + +#if (CFG_FW_Report_Efuse_Address) + u2InitAddr = prAdapter->u4EfuseStartAddress; +#else + u2InitAddr = EFUSE_CONTENT_BUFFER_START; +#endif + + + memcpy(&Value, HqaCmdFrame->Data + 4 * 0, 4); + Value = ntohl(Value); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_WriteBufferDone Value : %d\n", Value); + + u4EepromMode = Value; + + /* allocate memory for buffer mode info */ + prSetEfuseBufModeInfo = (PARAM_CUSTOM_EFUSE_BUFFER_MODE_T *) + kalMemAlloc(sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T), VIR_MEM_TYPE); + if (prSetEfuseBufModeInfo == NULL) + goto label_exit; + kalMemZero(prSetEfuseBufModeInfo, sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T)); + + /* copy to the command buffer */ +#if (CFG_FW_Report_Efuse_Address) + u4ContentLen = (prAdapter->u4EfuseEndAddress)-(prAdapter->u4EfuseStartAddress)+1; +#else + u4ContentLen = EFUSE_CONTENT_BUFFER_SIZE; +#endif + if (u4ContentLen > MAX_EEPROM_BUFFER_SIZE) + goto label_exit; + kalMemCopy(prSetEfuseBufModeInfo->aBinContent, &uacEEPROMImage[u2InitAddr], u4ContentLen); + + prSetEfuseBufModeInfo->ucSourceMode = Value; + + prSetEfuseBufModeInfo->ucCmdType = 0x1 | (prAdapter->rWifiVar.ucCalTimingCtrl << 4); + prSetEfuseBufModeInfo->ucCount = 0xFF; /* ucCmdType 1 don't care the ucCount */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEfusBufferMode, + (PVOID)prSetEfuseBufModeInfo, + sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T), + FALSE, TRUE, TRUE, &u4BufLen); + +#if 0 + for (i = 0 ; i < MAX_EEPROM_BUFFER_SIZE/16 ; i++) { + for (j = 0 ; j < 16 ; j++) { + rSetEfuseBufModeInfo.aBinContent[j].u2Addr = u2InitAddr; + rSetEfuseBufModeInfo.aBinContent[j].ucValue = uacEEPROMImage[u2InitAddr]; + DBGLOG(RFTEST, INFO, "u2Addr = %x\n", rSetEfuseBufModeInfo.aBinContent[j].u2Addr); + DBGLOG(RFTEST, INFO, "ucValue = %x\n", rSetEfuseBufModeInfo.aBinContent[j].ucValue); + u2InitAddr += 1; + } + + rSetEfuseBufModeInfo.ucSourceMode = 1; + rSetEfuseBufModeInfo.ucCount = EFUSE_CONTENT_SIZE; + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEfusBufferMode, + &rSetEfuseBufModeInfo, + sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T), FALSE, FALSE, TRUE, &u4BufLen); + } +#endif + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + +label_exit: + + /* free memory */ + if (prSetEfuseBufModeInfo != NULL) + kalMemFree(prSetEfuseBufModeInfo, VIR_MEM_TYPE, sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T)); + + if (pucConfigBuf != NULL) + kalMemFree(pucConfigBuf, VIR_MEM_TYPE, MAX_EEPROM_BUFFER_SIZE); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_FFT(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_FFT\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetTxTonePower(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetTxTonePower\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetChipID(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4ChipId; + struct mt66xx_chip_info *prChipInfo; + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; +/* UINT_32 u4BufLen = 0; +* PARAM_CUSTOM_MCR_RW_STRUCT_T rMcrInfo; +*/ + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_GetChipID\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + prChipInfo = prAdapter->chip_info; + g_u4Chip_ID = prChipInfo->chip_id; + u4ChipId = g_u4Chip_ID; + + DBGLOG(RFTEST, INFO, + "MT6632 : QA_AGENT HQA_GetChipID ChipId = 0x%08x\n", u4ChipId); + + u4ChipId = ntohl(u4ChipId); + memcpy(HqaCmdFrame->Data + 2, &u4ChipId, 4); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_MPSSetSeqData(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 *mps_setting = NULL; + UINT_32 u4Band_idx = 0; + UINT_32 u4Offset = 0; + UINT_32 u4Len = 0; + UINT_32 i = 0; + UINT_32 u4Value = 0; + UINT_32 u4Mode = 0; + UINT_32 u4TxPath = 0; + UINT_32 u4Mcs = 0; + + u4Len = ntohs(HqaCmdFrame->Length)/sizeof(UINT_32) - 1; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MPSSetSeqData u4Len : %d\n", u4Len); + + mps_setting = kmalloc(sizeof(UINT_32)*(u4Len), GFP_KERNEL); + + if (!mps_setting) + return -ENOMEM; + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MPSSetSeqData u4Band_idx : %d\n", u4Band_idx); + + for (i = 0 ; i < u4Len ; i++) { + u4Offset = 4 + 4 * i; + if (u4Offset + 4 > sizeof(HqaCmdFrame->Data)) /* Reserved at least 4 byte availbale data */ + break; + memcpy(&u4Value, HqaCmdFrame->Data + 4 + 4*i, 4); + u4Value = ntohl(u4Value); + + u4Mode = (u4Value & BITS(24, 27)) >> 24; + u4TxPath = (u4Value & BITS(8, 23)) >> 8; + u4Mcs = (u4Value & BITS(0, 7)); + + DBGLOG(RFTEST, INFO, + "MT6632 : QA_AGENT HQA_MPSSetSeqData mps_setting Case %d (Mode : %d / TX Path : %d / MCS : %d)\n" + , i, u4Mode, u4TxPath, u4Mcs); + + if (u4Mode == 1) { + u4Mode = 0; + u4Mcs += 4; + } else if ((u4Mode == 0) && ((u4Mcs == 9) || (u4Mcs == 10) || (u4Mcs == 11))) + u4Mode = 1; + + if (u4Mode == 0) { + u4Mcs |= 0x00000000; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT CCK/OFDM (normal preamble) rate : %d\n", u4Mcs); + } else if (u4Mode == 1) { + if (u4Mcs == 9) + u4Mcs = 1; + else if (u4Mcs == 10) + u4Mcs = 2; + else if (u4Mcs == 11) + u4Mcs = 3; + u4Mcs |= 0x00000000; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT CCK (short preamble) rate : %d\n", u4Mcs); + } else if (u4Mode >= 2 && u4Mode <= 4) { + u4Mcs |= 0x80000000; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HT/VHT rate : %d\n", u4Mcs); + } + + mps_setting[i] = (u4Mcs) | (u4TxPath << 8) | (u4Mode << 24); + + DBGLOG(RFTEST, INFO, + "MT6632 : QA_AGENT HQA_MPSSetSeqData mps_setting Case %d (Mode : %d / TX Path : %d / MCS : %d)\n", + i, + (int)((mps_setting[i] & BITS(24, 27)) >> 24), + (int)((mps_setting[i] & BITS(8, 23)) >> 8), + (int)((mps_setting[i] & BITS(0, 7)))); + + } + + i4Ret = MT_ATEMPSSetSeqData(prNetDev, u4Len, mps_setting, u4Band_idx); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(mps_setting); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_MPSSetPayloadLength(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 *mps_setting = NULL; + UINT_32 u4Band_idx = 0; + UINT_32 u4Offset = 0; + UINT_32 u4Len = 0; + UINT_32 i = 0; + UINT_32 u4Value = 0; + + u4Len = ntohs(HqaCmdFrame->Length)/sizeof(UINT_32) - 1; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MPSSetPayloadLength u4Len : %d\n", u4Len); + + mps_setting = kmalloc(sizeof(UINT_32)*(u4Len), GFP_KERNEL); + + if (!mps_setting) + return -ENOMEM; + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MPSSetPayloadLength u4Band_idx : %d\n", u4Band_idx); + + for (i = 0 ; i < u4Len ; i++) { + u4Offset = 4 + 4 * i; + if (u4Offset + 4 > sizeof(HqaCmdFrame->Data)) /* Reserved at least 4 byte availbale data */ + break; + memcpy(&u4Value, HqaCmdFrame->Data + 4 + 4*i, 4); + mps_setting[i] = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, + "MT6632 : QA_AGENT HQA_MPSSetPayloadLength mps_setting Case %d (Payload Length : %d)\n", + i, mps_setting[i]); + } + + i4Ret = MT_ATEMPSSetPayloadLength(prNetDev, u4Len, mps_setting, u4Band_idx); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(mps_setting); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_MPSSetPacketCount(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 *mps_setting = NULL; + UINT_32 u4Band_idx = 0; + UINT_32 u4Offset = 0; + UINT_32 u4Len = 0; + UINT_32 i = 0; + UINT_32 u4Value = 0; + + u4Len = ntohs(HqaCmdFrame->Length)/sizeof(UINT_32) - 1; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MPSSetPacketCount u4Len : %d\n", u4Len); + + mps_setting = kmalloc(sizeof(UINT_32)*(u4Len), GFP_KERNEL); + + if (!mps_setting) + return -ENOMEM; + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MPSSetPacketCount u4Band_idx : %d\n", u4Band_idx); + + for (i = 0 ; i < u4Len ; i++) { + u4Offset = 4 + 4 * i; + if (u4Offset + 4 > sizeof(HqaCmdFrame->Data)) /* Reserved at least 4 byte availbale data */ + break; + memcpy(&u4Value, HqaCmdFrame->Data + 4 + 4*i, 4); + mps_setting[i] = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, + "MT6632 : QA_AGENT HQA_MPSSetPacketCount mps_setting Case %d (Packet Count : %d)\n", + i, mps_setting[i]); + } + + i4Ret = MT_ATEMPSSetPacketCount(prNetDev, u4Len, mps_setting, u4Band_idx); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(mps_setting); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_MPSSetPowerGain(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 *mps_setting = NULL; + UINT_32 u4Band_idx = 0; + UINT_32 u4Offset = 0; + UINT_32 u4Len = 0; + UINT_32 i = 0; + UINT_32 u4Value = 0; + + u4Len = ntohs(HqaCmdFrame->Length)/sizeof(UINT_32) - 1; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MPSSetPowerGain u4Len : %d\n", u4Len); + + mps_setting = kmalloc(sizeof(UINT_32)*(u4Len), GFP_KERNEL); + + if (!mps_setting) + return -ENOMEM; + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MPSSetPowerGain u4Band_idx : %d\n", u4Band_idx); + + for (i = 0 ; i < u4Len ; i++) { + u4Offset = 4 + 4 * i; + if (u4Offset + 4 > sizeof(HqaCmdFrame->Data)) /* Reserved at least 4 byte availbale data */ + break; + memcpy(&u4Value, HqaCmdFrame->Data + 4 + 4*i, 4); + mps_setting[i] = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MPSSetPowerGain mps_setting Case %d (Power : %d)\n", + i, mps_setting[i]); + } + + i4Ret = MT_ATEMPSSetPowerGain(prNetDev, u4Len, mps_setting, u4Band_idx); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(mps_setting); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_MPSStart(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Band_idx = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MPSStart\n"); + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + MT_ATEStartTX(prNetDev, "TXFRAME"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_MPSStop(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Band_idx = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MPSStop\n"); + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + /* To Do : MPS Stop for Specific Band. */ + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_MPSSetNss(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 *mps_setting = NULL; + UINT_32 u4Band_idx = 0; + UINT_32 u4Offset = 0; + UINT_32 u4Len = 0; + UINT_32 i = 0; + UINT_32 u4Value = 0; + + u4Len = ntohs(HqaCmdFrame->Length)/sizeof(UINT_32) - 1; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MPSSetNss u4Len : %d\n", u4Len); + + mps_setting = kmalloc(sizeof(UINT_32)*(u4Len), GFP_KERNEL); + + if (!mps_setting) + return -ENOMEM; + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MPSSetNss u4Band_idx : %d\n", u4Band_idx); + + for (i = 0; i < u4Len; i++) { + u4Offset = 4 + 4 * i; + if (u4Offset + 4 > sizeof(HqaCmdFrame->Data)) /* Reserved at least 4 byte availbale data */ + break; + memcpy(&u4Value, HqaCmdFrame->Data + 4 + 4*i, 4); + mps_setting[i] = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MPSSetNss mps_setting Case %d (Nss : %d)\n", + i, mps_setting[i]); + } + + i4Ret = MT_ATEMPSSetNss(prNetDev, u4Len, mps_setting, u4Band_idx); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(mps_setting); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_MPSSetPerpacketBW( + struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 *mps_setting = NULL; + UINT_32 u4Band_idx = 0; + UINT_32 u4Offset = 0; + UINT_32 u4Len = 0; + UINT_32 i = 0; + UINT_32 u4Value = 0; + + u4Len = ntohs(HqaCmdFrame->Length)/sizeof(UINT_32) - 1; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MPSSetPerpacketBW u4Len : %d\n", u4Len); + + mps_setting = kmalloc(sizeof(UINT_32)*(u4Len), GFP_KERNEL); + + if (!mps_setting) + return -ENOMEM; + + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MPSSetPerpacketBW u4Band_idx : %d\n", u4Band_idx); + + for (i = 0 ; i < u4Len ; i++) { + u4Offset = 4 + 4 * i; + if (u4Offset + 4 > sizeof(HqaCmdFrame->Data)) /* Reserved at least 4 byte availbale data */ + break; + memcpy(&u4Value, HqaCmdFrame->Data + 4 + 4*i, 4); + mps_setting[i] = ntohl(u4Value); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MPSSetPerpacketBW mps_setting Case %d (BW : %d)\n", + i, mps_setting[i]); + } + + i4Ret = MT_ATEMPSSetPerpacketBW(prNetDev, u4Len, mps_setting, u4Band_idx); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(mps_setting); + + return i4Ret; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetAIFS(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 SlotTime = 0; + UINT_32 SifsTime = 0; + + memcpy(&SlotTime, HqaCmdFrame->Data + 4 * 0, 4); + SlotTime = ntohl(SlotTime); + memcpy(&SifsTime, HqaCmdFrame->Data + 4 * 1, 4); + SifsTime = ntohl(SifsTime); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetAIFS SlotTime = %d\n", SlotTime); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetAIFS SifsTime = %d\n", SifsTime); + + i4Ret = MT_ATESetTxIPG(prNetDev, SifsTime); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_CheckEfuseModeType(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 Value = u4EepromMode; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_CheckEfuseModeType\n"); + + /* + * Value: + * 1 -> efuse Mode + * 2 -> flash Mode + * 3 -> eeprom Mode + * 4 -> bin Mode + */ + Value = ntohl(Value); + memcpy(HqaCmdFrame->Data + 2, &(Value), sizeof(Value)); + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_CheckEfuseNativeModeType(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_CheckEfuseNativeModeType\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_SetBandMode(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Band_mode = 0; + UINT_32 u4Band_type = 0; + + memcpy((PUCHAR)&u4Band_mode, HqaCmdFrame->Data + 4 * 0, 4); + u4Band_mode = ntohl(u4Band_mode); + memcpy((PUCHAR)&u4Band_type, HqaCmdFrame->Data + 4 * 1, 4); + u4Band_type = ntohl(u4Band_type); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetBandMode u4Band_mode : %d\n", u4Band_mode); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_SetBandMode u4Band_type : %d\n", u4Band_type); + + if (u4Band_mode == 2) + g_DBDCEnable = TRUE; + else if (u4Band_mode == 1) + g_DBDCEnable = FALSE; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_GetBandMode(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Band_mode = 0; + UINT_32 u4Band_idx = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 u4BufLen = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memcpy((PUCHAR)&u4Band_idx, HqaCmdFrame->Data, 4); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_GetBandMode u4Band_idx : %d\n", u4Band_idx); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_DBDC_ENABLE; + if (g_DBDCEnable) + rRfATInfo.u4FuncData = 1; + else + rRfATInfo.u4FuncData = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_GetBandMode g_DBDCEnable = %d\n", g_DBDCEnable); + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + + if (u4Band_idx == 0) { + u4Band_mode = 3; + } else { + if (g_DBDCEnable) + u4Band_mode = 3; + else + u4Band_mode = 0; + } + + u4Band_mode = ntohl(u4Band_mode); + + memcpy(HqaCmdFrame->Data + 2, &(u4Band_mode), sizeof(u4Band_mode)); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + sizeof(u4Band_mode), i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_RDDStartExt(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_RDDStartExt\n"); + + DBGLOG(RFTEST, INFO, "[RDD DUMP START]\n"); + + i4Ret = MT_ATERDDStart(prNetDev, "RDDSTART"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_RDDStopExt(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_RDDStopExt\n"); + + i4Ret = MT_ATERDDStop(prNetDev, "RDDSTOP"); + + DBGLOG(RFTEST, INFO, "[RDD DUMP END]\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_BssInfoUpdate(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 OwnMacIdx = 0, BssIdx = 0; + UINT_8 ucAddr1[MAC_ADDR_LEN]; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + memcpy(&OwnMacIdx, HqaCmdFrame->Data + 4 * 0, 4); + OwnMacIdx = ntohl(OwnMacIdx); + memcpy(&BssIdx, HqaCmdFrame->Data + 4 * 1, 4); + BssIdx = ntohl(BssIdx); + memcpy(ucAddr1, HqaCmdFrame->Data + 4 * 2, 6); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_BssInfoUpdate OwnMacIdx : %d\n", OwnMacIdx); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_BssInfoUpdate BssIdx : %d\n", BssIdx); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_BssInfoUpdate addr1:%02x:%02x:%02x:%02x:%02x:%02x\n", + ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], ucAddr1[4], ucAddr1[5]); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + OwnMacIdx, BssIdx, ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], ucAddr1[4], ucAddr1[5]); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_BssInfoUpdate(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_DevInfoUpdate(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 Band = 0, OwnMacIdx = 0; + UINT_8 ucAddr1[MAC_ADDR_LEN]; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + memcpy(&Band, HqaCmdFrame->Data + 4 * 0, 4); + Band = ntohl(Band); + memcpy(&OwnMacIdx, HqaCmdFrame->Data + 4 * 1, 4); + OwnMacIdx = ntohl(OwnMacIdx); + memcpy(ucAddr1, HqaCmdFrame->Data + 4 * 2, 6); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_DevInfoUpdate Band : %d\n", Band); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_DevInfoUpdate OwnMacIdx : %d\n", OwnMacIdx); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_DevInfoUpdate addr1:%02x:%02x:%02x:%02x:%02x:%02x\n", + ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], ucAddr1[4], ucAddr1[5]); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + OwnMacIdx, ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], ucAddr1[4], ucAddr1[5], Band); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_DevInfoUpdate(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_LogOnOff(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Band_idx = 0; + UINT_32 u4Log_type = 0; + UINT_32 u4Log_ctrl = 0; + UINT_32 u4Log_size = 200; + + memcpy(&u4Band_idx, HqaCmdFrame->Data, 4); + u4Band_idx = ntohl(u4Band_idx); + memcpy(&u4Log_type, HqaCmdFrame->Data + 4, 4); + u4Log_type = ntohl(u4Log_type); + memcpy(&u4Log_ctrl, HqaCmdFrame->Data + 4 + 4, 4); + u4Log_ctrl = ntohl(u4Log_ctrl); + memcpy(&u4Log_size, HqaCmdFrame->Data + 4 + 4 + 4, 4); + u4Log_size = ntohl(u4Log_size); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_LogOnOff band_idx : %d\n", u4Band_idx); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_LogOnOff log_type : %d\n", u4Log_type); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_LogOnOff log_ctrl : %d\n", u4Log_ctrl); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_LogOnOff log_size : %d\n", u4Log_size); + + i4Ret = MT_ATELogOnOff(prNetDev, u4Log_type, u4Log_ctrl, u4Log_size); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_CMD_SET5[] = { + /* cmd id start from 0x1500 */ + HQA_GetFWInfo, /* 0x1500 */ + HQA_StartContinousTx, /* 0x1501 */ + HQA_SetSTBC, /* 0x1502 */ + HQA_SetShortGI, /* 0x1503 */ + HQA_SetDPD, /* 0x1504 */ + HQA_SetTssiOnOff, /* 0x1505 */ + HQA_GetRxStatisticsAll, /* 0x1506 */ + HQA_StartContiTxTone, /* 0x1507 */ + HQA_StopContiTxTone, /* 0x1508 */ + HQA_CalibrationTestMode, /* 0x1509 */ + HQA_DoCalibrationTestItem, /* 0x150A */ + HQA_eFusePhysicalWrite, /* 0x150B */ + HQA_eFusePhysicalRead, /* 0x150C */ + HQA_eFuseLogicalRead, /* 0x150D */ + HQA_eFuseLogicalWrite, /* 0x150E */ + HQA_TMRSetting, /* 0x150F */ + HQA_GetRxSNR, /* 0x1510 */ + HQA_WriteBufferDone, /* 0x1511 */ + HQA_FFT, /* 0x1512 */ + HQA_SetTxTonePower, /* 0x1513 */ + HQA_GetChipID, /* 0x1514 */ + HQA_MPSSetSeqData, /* 0x1515 */ + HQA_MPSSetPayloadLength, /* 0x1516 */ + HQA_MPSSetPacketCount, /* 0x1517 */ + HQA_MPSSetPowerGain, /* 0x1518 */ + HQA_MPSStart, /* 0x1519 */ + HQA_MPSStop, /* 0x151A */ + ToDoFunction, /* 0x151B */ + ToDoFunction, /* 0x151C */ + ToDoFunction, /* 0x151D */ + ToDoFunction, /* 0x151E */ + ToDoFunction, /* 0x151F */ + ToDoFunction, /* 0x1520 */ + HQA_SetAIFS, /* 0x1521 */ + HQA_CheckEfuseModeType, /* 0x1522 */ + HQA_CheckEfuseNativeModeType, /* 0x1523 */ + ToDoFunction, /* 0x1524 */ + ToDoFunction, /* 0x1525 */ + ToDoFunction, /* 0x1526 */ + ToDoFunction, /* 0x1527 */ + ToDoFunction, /* 0x1528 */ + ToDoFunction, /* 0x1529 */ + ToDoFunction, /* 0x152A */ + ToDoFunction, /* 0x152B */ + HQA_SetBandMode, /* 0x152C */ + HQA_GetBandMode, /* 0x152D */ + HQA_RDDStartExt, /* 0x152E */ + HQA_RDDStopExt, /* 0x152F */ + ToDoFunction, /* 0x1530 */ + HQA_BssInfoUpdate, /* 0x1531 */ + HQA_DevInfoUpdate, /* 0x1532 */ + HQA_LogOnOff, /* 0x1533 */ + ToDoFunction, /* 0x1534 */ + ToDoFunction, /* 0x1535 */ + HQA_MPSSetNss, /* 0x1536 */ + HQA_MPSSetPerpacketBW, /* 0x1537 */ +}; + +#if CFG_SUPPORT_TX_BF +static INT_32 HQA_TxBfProfileTagInValid(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 invalid = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(invalid), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_TxBfProfileTagInValid\n"); + + memcpy(&invalid, HqaCmdFrame->Data, 4); + invalid = ntohl(invalid); + + kalMemSet(prInBuf, 0, sizeof(invalid)); + kalSprintf(prInBuf, "%u", invalid); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_InValid(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagPfmuIdx(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 pfmuidx = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(pfmuidx), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_TxBfProfileTagPfmuIdx\n"); + + memcpy(&pfmuidx, HqaCmdFrame->Data, 4); + pfmuidx = ntohl(pfmuidx); + + kalMemSet(prInBuf, 0, sizeof(pfmuidx)); + kalSprintf(prInBuf, "%u", pfmuidx); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_PfmuIdx(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagBfType(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 bftype = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(bftype), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_TxBfProfileTagBfType\n"); + + memcpy(&bftype, HqaCmdFrame->Data, 4); + bftype = ntohl(bftype); + + kalMemSet(prInBuf, 0, sizeof(bftype)); + kalSprintf(prInBuf, "%u", bftype); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_BfType(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagBw(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 tag_bw = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(tag_bw), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_TxBfProfileTagBw\n"); + + memcpy(&tag_bw, HqaCmdFrame->Data, 4); + tag_bw = ntohl(tag_bw); + + kalMemSet(prInBuf, 0, sizeof(tag_bw)); + kalSprintf(prInBuf, "%u", tag_bw); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_DBW(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagSuMu(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 su_mu = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(su_mu), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_TxBfProfileTagSuMu\n"); + + memcpy(&su_mu, HqaCmdFrame->Data, 4); + su_mu = ntohl(su_mu); + + kalMemSet(prInBuf, 0, sizeof(su_mu)); + kalSprintf(prInBuf, "%u", su_mu); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_SuMu(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagMemAlloc(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 col_idx0, row_idx0, col_idx1, row_idx1; + UINT_32 col_idx2, row_idx2, col_idx3, row_idx3; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_TxBfProfileTagMemAlloc\n"); + + memcpy(&col_idx0, HqaCmdFrame->Data + 4 * 0, 4); + col_idx0 = ntohl(col_idx0); + memcpy(&row_idx0, HqaCmdFrame->Data + 4 * 1, 4); + row_idx0 = ntohl(row_idx0); + memcpy(&col_idx1, HqaCmdFrame->Data + 4 * 2, 4); + col_idx1 = ntohl(col_idx1); + memcpy(&row_idx1, HqaCmdFrame->Data + 4 * 3, 4); + row_idx1 = ntohl(row_idx1); + memcpy(&col_idx2, HqaCmdFrame->Data + 4 * 4, 4); + col_idx2 = ntohl(col_idx2); + memcpy(&row_idx2, HqaCmdFrame->Data + 4 * 5, 4); + row_idx2 = ntohl(row_idx2); + memcpy(&col_idx3, HqaCmdFrame->Data + 4 * 6, 4); + col_idx3 = ntohl(col_idx3); + memcpy(&row_idx3, HqaCmdFrame->Data + 4 * 7, 4); + row_idx3 = ntohl(row_idx3); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + col_idx0, row_idx0, col_idx1, row_idx1, col_idx2, row_idx2, col_idx3, row_idx3); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_Mem(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagMatrix(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 nrow, ncol, ngroup, LM, code_book, htc_exist; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_TxBfProfileTagMatrix\n"); + + memcpy(&nrow, HqaCmdFrame->Data + 4 * 0, 4); + nrow = ntohl(nrow); + memcpy(&ncol, HqaCmdFrame->Data + 4 * 1, 4); + ncol = ntohl(ncol); + memcpy(&ngroup, HqaCmdFrame->Data + 4 * 2, 4); + ngroup = ntohl(ngroup); + memcpy(&LM, HqaCmdFrame->Data + 4 * 3, 4); + LM = ntohl(LM); + memcpy(&code_book, HqaCmdFrame->Data + 4 * 4, 4); + code_book = ntohl(code_book); + memcpy(&htc_exist, HqaCmdFrame->Data + 4 * 5, 4); + htc_exist = ntohl(htc_exist); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x:%02x:%02x:%02x:%02x:%02x", nrow, ncol, ngroup, LM, code_book, htc_exist); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_Matrix(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagSnr(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 snr_sts0, snr_sts1, snr_sts2, snr_sts3; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_TxBfProfileTagSnr\n"); + + memcpy(&snr_sts0, HqaCmdFrame->Data + 4 * 0, 4); + snr_sts0 = ntohl(snr_sts0); + memcpy(&snr_sts1, HqaCmdFrame->Data + 4 * 1, 4); + snr_sts1 = ntohl(snr_sts1); + memcpy(&snr_sts2, HqaCmdFrame->Data + 4 * 2, 4); + snr_sts2 = ntohl(snr_sts2); + memcpy(&snr_sts3, HqaCmdFrame->Data + 4 * 3, 4); + snr_sts3 = ntohl(snr_sts3); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x:%02x:%02x:%02x", snr_sts0, snr_sts1, snr_sts2, snr_sts3); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_SNR(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagSmtAnt(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 smt_ant = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(smt_ant), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_TxBfProfileTagSmtAnt\n"); + + memcpy(&smt_ant, HqaCmdFrame->Data + 4 * 0, 4); + smt_ant = ntohl(smt_ant); + + kalMemSet(prInBuf, 0, sizeof(smt_ant)); + kalSprintf(prInBuf, "%u", smt_ant); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_SmartAnt(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagSeIdx(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 se_idx = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(se_idx), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_TxBfProfileTagSeIdx\n"); + + memcpy(&se_idx, HqaCmdFrame->Data + 4 * 0, 4); + se_idx = ntohl(se_idx); + + kalMemSet(prInBuf, 0, sizeof(se_idx)); + kalSprintf(prInBuf, "%u", se_idx); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_SeIdx(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagRmsdThrd(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 rmsd_thrd = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(rmsd_thrd), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_TxBfProfileTagRmsdThrd\n"); + + memcpy(&rmsd_thrd, HqaCmdFrame->Data + 4 * 0, 4); + rmsd_thrd = ntohl(rmsd_thrd); + + kalMemSet(prInBuf, 0, sizeof(rmsd_thrd)); + kalSprintf(prInBuf, "%u", rmsd_thrd); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_RmsdThrd(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagMcsThrd(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 mcs_lss0, mcs_sss0, mcs_lss1, mcs_sss1, mcs_lss2, mcs_sss2; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_TxBfProfileTagMcsThrd\n"); + + memcpy(&mcs_lss0, HqaCmdFrame->Data + 4 * 0, 4); + mcs_lss0 = ntohl(mcs_lss0); + memcpy(&mcs_sss0, HqaCmdFrame->Data + 4 * 1, 4); + mcs_sss0 = ntohl(mcs_sss0); + memcpy(&mcs_lss1, HqaCmdFrame->Data + 4 * 2, 4); + mcs_lss1 = ntohl(mcs_lss1); + memcpy(&mcs_sss1, HqaCmdFrame->Data + 4 * 3, 4); + mcs_sss1 = ntohl(mcs_sss1); + memcpy(&mcs_lss2, HqaCmdFrame->Data + 4 * 4, 4); + mcs_lss2 = ntohl(mcs_lss2); + memcpy(&mcs_sss2, HqaCmdFrame->Data + 4 * 5, 4); + mcs_sss2 = ntohl(mcs_sss2); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x:%02x:%02x:%02x:%02x:%02x", mcs_lss0, mcs_sss0, mcs_lss1, mcs_sss1, mcs_lss2, + mcs_sss2); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_McsThrd(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagTimeOut(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 bf_tout = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(bf_tout), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_TxBfProfileTagTimeOut\n"); + + memcpy(&bf_tout, HqaCmdFrame->Data + 4 * 0, 4); + bf_tout = ntohl(bf_tout); + + kalMemSet(prInBuf, 0, sizeof(bf_tout)); + kalSprintf(prInBuf, "%x", bf_tout); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_TimeOut(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagDesiredBw(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 desire_bw = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(desire_bw), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_TxBfProfileTagDesiredBw\n"); + + memcpy(&desire_bw, HqaCmdFrame->Data + 4 * 0, 4); + desire_bw = ntohl(desire_bw); + + kalMemSet(prInBuf, 0, sizeof(desire_bw)); + kalSprintf(prInBuf, "%u", desire_bw); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_DesiredBW(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagDesiredNc(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 desire_nc = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(desire_nc), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_TxBfProfileTagDesiredNc\n"); + + memcpy(&desire_nc, HqaCmdFrame->Data + 4 * 0, 4); + desire_nc = ntohl(desire_nc); + + kalMemSet(prInBuf, 0, sizeof(desire_nc)); + kalSprintf(prInBuf, "%u", desire_nc); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_DesiredNc(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagDesiredNr(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 desire_nr = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(desire_nr), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_TxBfProfileTagDesiredNr\n"); + + memcpy(&desire_nr, HqaCmdFrame->Data + 4 * 0, 4); + desire_nr = ntohl(desire_nr); + + kalMemSet(prInBuf, 0, sizeof(desire_nr)); + kalSprintf(prInBuf, "%u", desire_nr); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTag_DesiredNr(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagWrite(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 idx = 0; /* WLAN_IDX */ + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(idx), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_TxBfProfileTagWrite\n"); + + memcpy(&idx, HqaCmdFrame->Data + 4 * 0, 4); + idx = ntohl(idx); + + kalMemSet(prInBuf, 0, sizeof(idx)); + kalSprintf(prInBuf, "%u", idx); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTagWrite(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TxBfProfileTagRead(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 idx = 0, isBFer = 0; + UINT_8 *prInBuf; + PFMU_PROFILE_TAG1 rPfmuTag1; + PFMU_PROFILE_TAG2 rPfmuTag2; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_TxBfProfileTagRead\n"); + + memcpy(&idx, HqaCmdFrame->Data + 4 * 0, 4); + idx = ntohl(idx); + memcpy(&isBFer, HqaCmdFrame->Data + 4 * 1, 4); + isBFer = ntohl(isBFer); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x:%02x", idx, isBFer); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileTagRead(prNetDev, prInBuf); + + rPfmuTag1.au4RawData[0] = ntohl(g_rPfmuTag1.au4RawData[0]); + rPfmuTag1.au4RawData[1] = ntohl(g_rPfmuTag1.au4RawData[1]); + rPfmuTag1.au4RawData[2] = ntohl(g_rPfmuTag1.au4RawData[2]); + rPfmuTag1.au4RawData[3] = ntohl(g_rPfmuTag1.au4RawData[3]); + + rPfmuTag2.au4RawData[0] = ntohl(g_rPfmuTag2.au4RawData[0]); + rPfmuTag2.au4RawData[1] = ntohl(g_rPfmuTag2.au4RawData[1]); + rPfmuTag2.au4RawData[2] = ntohl(g_rPfmuTag2.au4RawData[2]); + + memcpy(HqaCmdFrame->Data + 2, &rPfmuTag1, sizeof(PFMU_PROFILE_TAG1)); + memcpy(HqaCmdFrame->Data + 2 + sizeof(PFMU_PROFILE_TAG1), &rPfmuTag2, sizeof(PFMU_PROFILE_TAG2)); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + sizeof(PFMU_PROFILE_TAG1) + sizeof(PFMU_PROFILE_TAG2), i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_StaRecCmmUpdate(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 wlan_idx, bss_idx, aid; + UINT_8 mac[MAC_ADDR_LEN]; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_StaRecCmmUpdate\n"); + + memcpy(&wlan_idx, HqaCmdFrame->Data + 4 * 0, 4); + wlan_idx = ntohl(wlan_idx); + memcpy(&bss_idx, HqaCmdFrame->Data + 4 * 1, 4); + bss_idx = ntohl(bss_idx); + memcpy(&aid, HqaCmdFrame->Data + 4 * 2, 4); + aid = ntohl(aid); + + memcpy(mac, HqaCmdFrame->Data + 4 * 3, 6); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + wlan_idx, bss_idx, aid, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_StaRecCmmUpdate(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_StaRecBfUpdate(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 wlan_idx, bss_idx, PfmuId, su_mu, etxbf_cap, ndpa_rate, ndp_rate; + UINT_32 report_poll_rate, tx_mode, nc, nr, cbw, spe_idx, tot_mem_req; + UINT_32 mem_req_20m, mem_row0, mem_col0, mem_row1, mem_col1; + UINT_32 mem_row2, mem_col2, mem_row3, mem_col3; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_StaRecBfUpdate\n"); + + memcpy(&wlan_idx, HqaCmdFrame->Data + 4 * 0, 4); + wlan_idx = ntohl(wlan_idx); + memcpy(&bss_idx, HqaCmdFrame->Data + 4 * 1, 4); + bss_idx = ntohl(bss_idx); + memcpy(&PfmuId, HqaCmdFrame->Data + 4 * 2, 4); + PfmuId = ntohl(PfmuId); + memcpy(&su_mu, HqaCmdFrame->Data + 4 * 3, 4); + su_mu = ntohl(su_mu); + memcpy(&etxbf_cap, HqaCmdFrame->Data + 4 * 4, 4); + etxbf_cap = ntohl(etxbf_cap); + memcpy(&ndpa_rate, HqaCmdFrame->Data + 4 * 5, 4); + ndpa_rate = ntohl(ndpa_rate); + memcpy(&ndp_rate, HqaCmdFrame->Data + 4 * 6, 4); + ndp_rate = ntohl(ndp_rate); + memcpy(&report_poll_rate, HqaCmdFrame->Data + 4 * 7, 4); + report_poll_rate = ntohl(report_poll_rate); + memcpy(&tx_mode, HqaCmdFrame->Data + 4 * 8, 4); + tx_mode = ntohl(tx_mode); + memcpy(&nc, HqaCmdFrame->Data + 4 * 9, 4); + nc = ntohl(nc); + memcpy(&nr, HqaCmdFrame->Data + 4 * 10, 4); + nr = ntohl(nr); + memcpy(&cbw, HqaCmdFrame->Data + 4 * 11, 4); + cbw = ntohl(cbw); + memcpy(&spe_idx, HqaCmdFrame->Data + 4 * 12, 4); + spe_idx = ntohl(spe_idx); + memcpy(&tot_mem_req, HqaCmdFrame->Data + 4 * 13, 4); + tot_mem_req = ntohl(tot_mem_req); + memcpy(&mem_req_20m, HqaCmdFrame->Data + 4 * 14, 4); + mem_req_20m = ntohl(mem_req_20m); + memcpy(&mem_row0, HqaCmdFrame->Data + 4 * 15, 4); + mem_row0 = ntohl(mem_row0); + memcpy(&mem_col0, HqaCmdFrame->Data + 4 * 16, 4); + mem_col0 = ntohl(mem_col0); + memcpy(&mem_row1, HqaCmdFrame->Data + 4 * 17, 4); + mem_row1 = ntohl(mem_row1); + memcpy(&mem_col1, HqaCmdFrame->Data + 4 * 18, 4); + mem_col1 = ntohl(mem_col1); + memcpy(&mem_row2, HqaCmdFrame->Data + 4 * 19, 4); + mem_row2 = ntohl(mem_row2); + memcpy(&mem_col2, HqaCmdFrame->Data + 4 * 20, 4); + mem_col2 = ntohl(mem_col2); + memcpy(&mem_row3, HqaCmdFrame->Data + 4 * 21, 4); + mem_row3 = ntohl(mem_row3); + memcpy(&mem_col3, HqaCmdFrame->Data + 4 * 22, 4); + mem_col3 = ntohl(mem_col3); + + /* For Tool wrong memory row and col num 20160501 */ + if (PfmuId == 0) { + mem_row0 = 0; + mem_col0 = 0; + mem_row1 = 1; + mem_col1 = 0; + mem_row2 = 2; + mem_col2 = 0; + mem_row3 = 3; + mem_col3 = 0; + } else if (PfmuId == 1) { + mem_row0 = 0; + mem_col0 = 2; + mem_row1 = 1; + mem_col1 = 2; + mem_row2 = 2; + mem_col2 = 2; + mem_row3 = 3; + mem_col3 = 2; + } + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, + "%02x:%02x:%02x:%02x:%02x:%02d:%02d:%02d:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + wlan_idx, bss_idx, PfmuId, su_mu, etxbf_cap, ndpa_rate, ndp_rate, report_poll_rate, tx_mode, nc, nr, + cbw, spe_idx, tot_mem_req, mem_req_20m, mem_row0, mem_col0, mem_row1, mem_col1, mem_row2, mem_col2, + mem_row3, mem_col3); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_StaRecBfUpdate(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_BFProfileDataRead(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 idx = 0, fgBFer = 0, subcarrIdx = 0, subcarr_start = 0, subcarr_end = 0; + UINT_32 NumOfsub = 0; + UINT_32 offset = 0; + UINT_8 *SubIdx = NULL; + UINT_8 *prInBuf; + PFMU_DATA rPfmuData; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_BFProfileDataRead\n"); + + memcpy(&idx, HqaCmdFrame->Data + 4 * 0, 4); + idx = ntohl(idx); + memcpy(&fgBFer, HqaCmdFrame->Data + 4 * 1, 4); + fgBFer = ntohl(fgBFer); + memcpy(&subcarr_start, HqaCmdFrame->Data + 4 * 2, 4); + subcarr_start = ntohl(subcarr_start); + memcpy(&subcarr_end, HqaCmdFrame->Data + 4 * 3, 4); + subcarr_end = ntohl(subcarr_end); + + NumOfsub = subcarr_end - subcarr_start + 1; + NumOfsub = ntohl(NumOfsub); + + memcpy(HqaCmdFrame->Data + 2, &NumOfsub, sizeof(NumOfsub)); + offset += sizeof(NumOfsub); + + for (subcarrIdx = subcarr_start; subcarrIdx <= subcarr_end; subcarrIdx++) { + SubIdx = (UINT_8 *) &subcarrIdx; + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x:%02x:%02x:%02x", idx, fgBFer, SubIdx[1], SubIdx[0]); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileDataRead(prNetDev, prInBuf); + + rPfmuData.au4RawData[0] = ntohl(g_rPfmuData.au4RawData[0]); + rPfmuData.au4RawData[1] = ntohl(g_rPfmuData.au4RawData[1]); + rPfmuData.au4RawData[2] = ntohl(g_rPfmuData.au4RawData[2]); + rPfmuData.au4RawData[3] = ntohl(g_rPfmuData.au4RawData[3]); + rPfmuData.au4RawData[4] = ntohl(g_rPfmuData.au4RawData[4]); + + memcpy(HqaCmdFrame->Data + 2 + offset, &rPfmuData, sizeof(rPfmuData)); + offset += sizeof(rPfmuData); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + offset, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_BFProfileDataWrite(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 pfmuid, subcarrier, phi11, psi21, phi21, psi31, phi31, psi41; + UINT_32 phi22, psi32, phi32, psi42, phi33, psi43, snr00, snr01, snr02, snr03; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_BFProfileDataWrite\n"); + + memcpy(&pfmuid, HqaCmdFrame->Data + 4 * 0, 4); + pfmuid = ntohl(pfmuid); + memcpy(&subcarrier, HqaCmdFrame->Data + 4 * 1, 4); + subcarrier = ntohl(subcarrier); + memcpy(&phi11, HqaCmdFrame->Data + 4 * 2, 4); + phi11 = ntohl(phi11); + memcpy(&psi21, HqaCmdFrame->Data + 4 * 3, 4); + psi21 = ntohl(psi21); + memcpy(&phi21, HqaCmdFrame->Data + 4 * 4, 4); + phi21 = ntohl(phi21); + memcpy(&psi31, HqaCmdFrame->Data + 4 * 5, 4); + psi31 = ntohl(psi31); + memcpy(&phi31, HqaCmdFrame->Data + 4 * 6, 4); + phi31 = ntohl(phi31); + memcpy(&psi41, HqaCmdFrame->Data + 4 * 7, 4); + psi41 = ntohl(psi41); + memcpy(&phi22, HqaCmdFrame->Data + 4 * 8, 4); + phi22 = ntohl(phi22); + memcpy(&psi32, HqaCmdFrame->Data + 4 * 9, 4); + psi32 = ntohl(psi32); + memcpy(&phi32, HqaCmdFrame->Data + 4 * 10, 4); + phi32 = ntohl(phi32); + memcpy(&psi42, HqaCmdFrame->Data + 4 * 11, 4); + psi42 = ntohl(psi42); + memcpy(&phi33, HqaCmdFrame->Data + 4 * 12, 4); + phi33 = ntohl(phi33); + memcpy(&psi43, HqaCmdFrame->Data + 4 * 13, 4); + psi43 = ntohl(psi43); + memcpy(&snr00, HqaCmdFrame->Data + 4 * 14, 4); + snr00 = ntohl(snr00); + memcpy(&snr01, HqaCmdFrame->Data + 4 * 15, 4); + snr01 = ntohl(snr01); + memcpy(&snr02, HqaCmdFrame->Data + 4 * 16, 4); + snr02 = ntohl(snr02); + memcpy(&snr03, HqaCmdFrame->Data + 4 * 17, 4); + snr03 = ntohl(snr03); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x:%03x:%03x:%02x:%03x:%02x:%03x:%02x:%03x:%02x:%03x:%02x:%03x:%02x:%02x:%02x:%02x:%02x", + pfmuid, subcarrier, phi11, psi21, phi21, psi31, phi31, psi41, + phi22, psi32, phi32, psi42, phi33, psi43, snr00, snr01, snr02, snr03); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfProfileDataWrite(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_BFSounding(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 su_mu, mu_num, snd_interval, wlan_id0; + UINT_32 wlan_id1, wlan_id2, wlan_id3, band_idx; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_BFSounding\n"); + + memcpy(&su_mu, HqaCmdFrame->Data + 4 * 0, 4); + su_mu = ntohl(su_mu); + memcpy(&mu_num, HqaCmdFrame->Data + 4 * 1, 4); + mu_num = ntohl(mu_num); + memcpy(&snd_interval, HqaCmdFrame->Data + 4 * 2, 4); + snd_interval = ntohl(snd_interval); + memcpy(&wlan_id0, HqaCmdFrame->Data + 4 * 3, 4); + wlan_id0 = ntohl(wlan_id0); + memcpy(&wlan_id1, HqaCmdFrame->Data + 4 * 4, 4); + wlan_id1 = ntohl(wlan_id1); + memcpy(&wlan_id2, HqaCmdFrame->Data + 4 * 5, 4); + wlan_id2 = ntohl(wlan_id2); + memcpy(&wlan_id3, HqaCmdFrame->Data + 4 * 6, 4); + wlan_id3 = ntohl(wlan_id3); + memcpy(&band_idx, HqaCmdFrame->Data + 4 * 7, 4); + band_idx = ntohl(band_idx); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x:%02x:%02x:%02x:%02x:%02x:%02x", + su_mu, mu_num, snd_interval, wlan_id0, wlan_id1, wlan_id2, wlan_id3); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_Trigger_Sounding_Proc(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_TXBFSoundingStop(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_TXBFSoundingStop\n"); + + i4Ret = Set_Stop_Sounding_Proc(prNetDev, NULL); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static INT_32 HQA_TXBFProfileDataWriteAllExt(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static INT_32 HQA_TxBfTxApply(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 eBF_enable = 0; + UINT_32 iBF_enable = 0; + UINT_32 wlan_id = 0; + UINT_32 MuTx_enable = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_TxBfTxApply\n"); + + memcpy(&eBF_enable, HqaCmdFrame->Data + 4 * 0, 4); + eBF_enable = ntohl(eBF_enable); + memcpy(&iBF_enable, HqaCmdFrame->Data + 4 * 1, 4); + iBF_enable = ntohl(iBF_enable); + memcpy(&wlan_id, HqaCmdFrame->Data + 4 * 2, 4); + wlan_id = ntohl(wlan_id); + memcpy(&MuTx_enable, HqaCmdFrame->Data + 4 * 3, 4); + MuTx_enable = ntohl(MuTx_enable); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x:%02x:%02x:%02x", wlan_id, eBF_enable, iBF_enable, MuTx_enable); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfTxApply(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_ManualAssoc(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 type; + UINT_32 wtbl_idx; + UINT_32 ownmac_idx; + UINT_32 phymode; + UINT_32 bw; + UINT_32 pfmuid; + UINT_32 marate_mode; + UINT_32 marate_mcs; + UINT_32 spe_idx; + UINT_32 aid; + UINT_8 ucAddr1[MAC_ADDR_LEN]; + UINT_32 nss = 1; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_ManualAssoc\n"); + + memcpy(&type, HqaCmdFrame->Data + 4 * 0, 4); + type = ntohl(type); + memcpy(&wtbl_idx, HqaCmdFrame->Data + 4 * 1, 4); + wtbl_idx = ntohl(wtbl_idx); + memcpy(&ownmac_idx, HqaCmdFrame->Data + 4 * 2, 4); + ownmac_idx = ntohl(ownmac_idx); + memcpy(&phymode, HqaCmdFrame->Data + 4 * 3, 4); + phymode = ntohl(phymode); + memcpy(&bw, HqaCmdFrame->Data + 4 * 4, 4); + bw = ntohl(bw); + memcpy(&pfmuid, HqaCmdFrame->Data + 4 * 5, 4); + pfmuid = ntohl(pfmuid); + memcpy(&marate_mode, HqaCmdFrame->Data + 4 * 6, 4); + marate_mode = ntohl(marate_mode); + memcpy(&marate_mcs, HqaCmdFrame->Data + 4 * 7, 4); + marate_mcs = ntohl(marate_mcs); + memcpy(&spe_idx, HqaCmdFrame->Data + 4 * 8, 4); + spe_idx = ntohl(spe_idx); + memcpy(&aid, HqaCmdFrame->Data + 4 * 9, 4); + aid = ntohl(aid); + memcpy(ucAddr1, HqaCmdFrame->Data + 4 * 10, 6); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], ucAddr1[4], ucAddr1[5], type, wtbl_idx, ownmac_idx, + phymode, bw, nss, pfmuid, marate_mode, marate_mcs, spe_idx, aid, 0); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_TxBfManualAssoc(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_TXBF_CMDS[] = { + HQA_TxBfProfileTagInValid, /* 0x1540 */ + HQA_TxBfProfileTagPfmuIdx, /* 0x1541 */ + HQA_TxBfProfileTagBfType, /* 0x1542 */ + HQA_TxBfProfileTagBw, /* 0x1543 */ + HQA_TxBfProfileTagSuMu, /* 0x1544 */ + HQA_TxBfProfileTagMemAlloc, /* 0x1545 */ + HQA_TxBfProfileTagMatrix, /* 0x1546 */ + HQA_TxBfProfileTagSnr, /* 0x1547 */ + HQA_TxBfProfileTagSmtAnt, /* 0x1548 */ + HQA_TxBfProfileTagSeIdx, /* 0x1549 */ + HQA_TxBfProfileTagRmsdThrd, /* 0x154A */ + HQA_TxBfProfileTagMcsThrd, /* 0x154B */ + HQA_TxBfProfileTagTimeOut, /* 0x154C */ + HQA_TxBfProfileTagDesiredBw, /* 0x154D */ + HQA_TxBfProfileTagDesiredNc, /* 0x154E */ + HQA_TxBfProfileTagDesiredNr, /* 0x154F */ + HQA_TxBfProfileTagWrite, /* 0x1550 */ + HQA_TxBfProfileTagRead, /* 0x1551 */ + HQA_StaRecCmmUpdate, /* 0x1552 */ + HQA_StaRecBfUpdate, /* 0x1553 */ + HQA_BFProfileDataRead, /* 0x1554 */ + HQA_BFProfileDataWrite, /* 0x1555 */ + HQA_BFSounding, /* 0x1556 */ + HQA_TXBFSoundingStop, /* 0x1557 */ + HQA_TXBFProfileDataWriteAllExt, /* 0x1558 */ + HQA_TxBfTxApply, /* 0x1559 */ + HQA_ManualAssoc, /* 0x155A */ +}; + +#if CFG_SUPPORT_MU_MIMO +static INT_32 HQA_MUGetInitMCS(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Gid = 0; + UINT_32 u4User0InitMCS = 0; + UINT_32 u4User1InitMCS = 0; + UINT_32 u4User2InitMCS = 0; + UINT_32 u4User3InitMCS = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MUGetInitMCS\n"); + + memcpy(&u4Gid, HqaCmdFrame->Data, 4); + u4Gid = ntohl(u4Gid); + + kalMemSet(prInBuf, 0, sizeof(u4Gid)); + kalSprintf(prInBuf, "%u", u4Gid); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUGetInitMCS(prNetDev, prInBuf); + + u4User0InitMCS = ntohl(u4User0InitMCS); + u4User1InitMCS = ntohl(u4User1InitMCS); + u4User2InitMCS = ntohl(u4User2InitMCS); + u4User3InitMCS = ntohl(u4User3InitMCS); + + memcpy(HqaCmdFrame->Data + 2, &u4User0InitMCS, sizeof(UINT_32)); + memcpy(HqaCmdFrame->Data + 2 + 1 * sizeof(UINT_32), &u4User1InitMCS, sizeof(UINT_32)); + memcpy(HqaCmdFrame->Data + 2 + 2 * sizeof(UINT_32), &u4User2InitMCS, sizeof(UINT_32)); + memcpy(HqaCmdFrame->Data + 2 + 3 * sizeof(UINT_32), &u4User3InitMCS, sizeof(UINT_32)); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_MUCalInitMCS(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Num_of_user; + UINT_32 u4Bandwidth; + UINT_32 u4Nss_of_user0; + UINT_32 u4Nss_of_user1; + UINT_32 u4Nss_of_user2; + UINT_32 u4Nss_of_user3; + UINT_32 u4Pf_mu_id_of_user0; + UINT_32 u4Pf_mu_id_of_user1; + UINT_32 u4Pf_mu_id_of_user2; + UINT_32 u4Pf_mu_id_of_user3; + UINT_32 u4Num_of_txer; /* number of antenna */ + UINT_32 u4Spe_index; + UINT_32 u4Group_index; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MUCalInitMCS\n"); + + memcpy(&u4Num_of_user, HqaCmdFrame->Data + 4 * 0, 4); + u4Num_of_user = ntohl(u4Num_of_user); + memcpy(&u4Bandwidth, HqaCmdFrame->Data + 4 * 1, 4); + u4Bandwidth = ntohl(u4Bandwidth); + memcpy(&u4Nss_of_user0, HqaCmdFrame->Data + 4 * 2, 4); + u4Nss_of_user0 = ntohl(u4Nss_of_user0); + memcpy(&u4Nss_of_user1, HqaCmdFrame->Data + 4 * 3, 4); + u4Nss_of_user1 = ntohl(u4Nss_of_user1); + memcpy(&u4Nss_of_user2, HqaCmdFrame->Data + 4 * 4, 4); + u4Nss_of_user2 = ntohl(u4Nss_of_user2); + memcpy(&u4Nss_of_user3, HqaCmdFrame->Data + 4 * 5, 4); + u4Nss_of_user3 = ntohl(u4Nss_of_user3); + memcpy(&u4Pf_mu_id_of_user0, HqaCmdFrame->Data + 4 * 6, 4); + u4Pf_mu_id_of_user0 = ntohl(u4Pf_mu_id_of_user0); + memcpy(&u4Pf_mu_id_of_user1, HqaCmdFrame->Data + 4 * 7, 4); + u4Pf_mu_id_of_user1 = ntohl(u4Pf_mu_id_of_user1); + memcpy(&u4Pf_mu_id_of_user2, HqaCmdFrame->Data + 4 * 8, 4); + u4Pf_mu_id_of_user2 = ntohl(u4Pf_mu_id_of_user2); + memcpy(&u4Pf_mu_id_of_user3, HqaCmdFrame->Data + 4 * 9, 4); + u4Pf_mu_id_of_user3 = ntohl(u4Pf_mu_id_of_user3); + memcpy(&u4Num_of_txer, HqaCmdFrame->Data + 4 * 10, 4); + u4Num_of_txer = ntohl(u4Num_of_txer); + memcpy(&u4Spe_index, HqaCmdFrame->Data + 4 * 11, 4); + u4Spe_index = ntohl(u4Spe_index); + memcpy(&u4Group_index, HqaCmdFrame->Data + 4 * 12, 4); + u4Group_index = ntohl(u4Group_index); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + u4Num_of_user, u4Bandwidth, u4Nss_of_user0, u4Nss_of_user1, u4Pf_mu_id_of_user0, u4Pf_mu_id_of_user1, + u4Num_of_txer, u4Spe_index, u4Group_index); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUCalInitMCS(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_MUCalLQ(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Type = 0; + UINT_32 u4Num_of_user; + UINT_32 u4Bandwidth; + UINT_32 u4Nss_of_user0; + UINT_32 u4Nss_of_user1; + UINT_32 u4Nss_of_user2; + UINT_32 u4Nss_of_user3; + UINT_32 u4Pf_mu_id_of_user0; + UINT_32 u4Pf_mu_id_of_user1; + UINT_32 u4Pf_mu_id_of_user2; + UINT_32 u4Pf_mu_id_of_user3; + UINT_32 u4Num_of_txer; /* number of antenna */ + UINT_32 u4Spe_index; + UINT_32 u4Group_index; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MUCalLQ\n"); + + memcpy(&u4Type, HqaCmdFrame->Data + 4 * 0, 4); + u4Type = ntohl(u4Type); + memcpy(&u4Num_of_user, HqaCmdFrame->Data + 4 * 1, 4); + u4Num_of_user = ntohl(u4Num_of_user); + memcpy(&u4Bandwidth, HqaCmdFrame->Data + 4 * 2, 4); + u4Bandwidth = ntohl(u4Bandwidth); + memcpy(&u4Nss_of_user0, HqaCmdFrame->Data + 4 * 3, 4); + u4Nss_of_user0 = ntohl(u4Nss_of_user0); + memcpy(&u4Nss_of_user1, HqaCmdFrame->Data + 4 * 4, 4); + u4Nss_of_user1 = ntohl(u4Nss_of_user1); + memcpy(&u4Nss_of_user2, HqaCmdFrame->Data + 4 * 5, 4); + u4Nss_of_user2 = ntohl(u4Nss_of_user2); + memcpy(&u4Nss_of_user3, HqaCmdFrame->Data + 4 * 6, 4); + u4Nss_of_user3 = ntohl(u4Nss_of_user3); + memcpy(&u4Pf_mu_id_of_user0, HqaCmdFrame->Data + 4 * 7, 4); + u4Pf_mu_id_of_user0 = ntohl(u4Pf_mu_id_of_user0); + memcpy(&u4Pf_mu_id_of_user1, HqaCmdFrame->Data + 4 * 8, 4); + u4Pf_mu_id_of_user1 = ntohl(u4Pf_mu_id_of_user1); + memcpy(&u4Pf_mu_id_of_user2, HqaCmdFrame->Data + 4 * 9, 4); + u4Pf_mu_id_of_user2 = ntohl(u4Pf_mu_id_of_user2); + memcpy(&u4Pf_mu_id_of_user3, HqaCmdFrame->Data + 4 * 10, 4); + u4Pf_mu_id_of_user3 = ntohl(u4Pf_mu_id_of_user3); + memcpy(&u4Num_of_txer, HqaCmdFrame->Data + 4 * 11, 4); + u4Num_of_txer = ntohl(u4Num_of_txer); + memcpy(&u4Spe_index, HqaCmdFrame->Data + 4 * 12, 4); + u4Spe_index = ntohl(u4Spe_index); + memcpy(&u4Group_index, HqaCmdFrame->Data + 4 * 13, 4); + u4Group_index = ntohl(u4Group_index); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + u4Num_of_user, u4Bandwidth, u4Nss_of_user0, u4Nss_of_user1, u4Pf_mu_id_of_user0, u4Pf_mu_id_of_user1, + u4Num_of_txer, u4Spe_index, u4Group_index); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUCalLQ(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_MUGetLQ(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 i; + UINT_8 u4LqReport[NUM_OF_USER * NUM_OF_MODUL]; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MUGetLQ\n"); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + kalMemSet(u4LqReport, 0, (NUM_OF_USER * NUM_OF_MODUL)); + + i4Ret = Set_MUGetLQ(prNetDev, prInBuf); + + for (i = 0; i < NUM_OF_USER * NUM_OF_MODUL; i++) { + u4LqReport[i] = ntohl(u4LqReport[i]); + memcpy(HqaCmdFrame->Data + 2 + i * sizeof(UINT_32), &u4LqReport[i], sizeof(UINT_32)); + } + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_MUSetSNROffset(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Offset = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MUSetSNROffset\n"); + + memcpy(&u4Offset, HqaCmdFrame->Data + 4 * 0, 4); + u4Offset = ntohl(u4Offset); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x", u4Offset); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUSetSNROffset(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_MUSetZeroNss(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Zero_nss = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MUSetZeroNss\n"); + + memcpy(&u4Zero_nss, HqaCmdFrame->Data + 4 * 0, 4); + u4Zero_nss = ntohl(u4Zero_nss); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x", u4Zero_nss); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUSetZeroNss(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_MUSetSpeedUpLQ(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4SpeedUpLq = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MUSetSpeedUpLQ\n"); + + memcpy(&u4SpeedUpLq, HqaCmdFrame->Data + 4 * 0, 4); + u4SpeedUpLq = ntohl(u4SpeedUpLq); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x", u4SpeedUpLq); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUSetSpeedUpLQ(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; + +} + +static INT_32 HQA_MUSetMUTable(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_8 *prTable; + UINT_16 u2Len = 0; + UINT_32 u4SuMu = 0; + + prTable = kmalloc_array(u2Len, sizeof(UINT_8), GFP_KERNEL); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MUSetMUTable\n"); + + u2Len = ntohl(HqaCmdFrame->Length) - sizeof(u4SuMu); + + memcpy(&u4SuMu, HqaCmdFrame->Data + 4 * 0, 4); + u4SuMu = ntohl(u4SuMu); + + memcpy(prTable, HqaCmdFrame->Data + 4, u2Len); + + i4Ret = Set_MUSetMUTable(prNetDev, prTable); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static INT_32 HQA_MUSetGroup(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4GroupIndex, u4NumOfUser, u4User0Ldpc, u4User1Ldpc, u4User2Ldpc, u4User3Ldpc; + UINT_32 u4ShortGI, u4Bw, u4User0Nss, u4User1Nss, u4User2Nss, u4User3Nss; + UINT_32 u4GroupId, u4User0UP, u4User1UP, u4User2UP, u4User3UP; + UINT_32 u4User0MuPfId, u4User1MuPfId, u4User2MuPfId, u4User3MuPfId; + UINT_32 u4User0InitMCS, u4User1InitMCS, u4User2InitMCS, u4User3InitMCS; + UINT_8 ucAddr1[MAC_ADDR_LEN], ucAddr2[MAC_ADDR_LEN], ucAddr3[MAC_ADDR_LEN], ucAddr4[MAC_ADDR_LEN]; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MUSetGroup\n"); + + memcpy(&u4GroupIndex, HqaCmdFrame->Data + 4 * 0, 4); + u4GroupIndex = ntohl(u4GroupIndex); + memcpy(&u4NumOfUser, HqaCmdFrame->Data + 4 * 1, 4); + u4NumOfUser = ntohl(u4NumOfUser); + memcpy(&u4User0Ldpc, HqaCmdFrame->Data + 4 * 2, 4); + u4User0Ldpc = ntohl(u4User0Ldpc); + memcpy(&u4User1Ldpc, HqaCmdFrame->Data + 4 * 3, 4); + u4User1Ldpc = ntohl(u4User1Ldpc); + memcpy(&u4User2Ldpc, HqaCmdFrame->Data + 4 * 4, 4); + u4User2Ldpc = ntohl(u4User2Ldpc); + memcpy(&u4User3Ldpc, HqaCmdFrame->Data + 4 * 5, 4); + u4User3Ldpc = ntohl(u4User3Ldpc); + memcpy(&u4ShortGI, HqaCmdFrame->Data + 4 * 6, 4); + u4ShortGI = ntohl(u4ShortGI); + memcpy(&u4Bw, HqaCmdFrame->Data + 4 * 7, 4); + u4Bw = ntohl(u4Bw); + memcpy(&u4User0Nss, HqaCmdFrame->Data + 4 * 8, 4); + u4User0Nss = ntohl(u4User0Nss); + memcpy(&u4User1Nss, HqaCmdFrame->Data + 4 * 9, 4); + u4User1Nss = ntohl(u4User1Nss); + memcpy(&u4User2Nss, HqaCmdFrame->Data + 4 * 10, 4); + u4User2Nss = ntohl(u4User2Nss); + memcpy(&u4User3Nss, HqaCmdFrame->Data + 4 * 11, 4); + u4User3Nss = ntohl(u4User3Nss); + memcpy(&u4GroupId, HqaCmdFrame->Data + 4 * 12, 4); + u4GroupId = ntohl(u4GroupId); + memcpy(&u4User0UP, HqaCmdFrame->Data + 4 * 13, 4); + u4User0UP = ntohl(u4User0UP); + memcpy(&u4User1UP, HqaCmdFrame->Data + 4 * 14, 4); + u4User1UP = ntohl(u4User1UP); + memcpy(&u4User2UP, HqaCmdFrame->Data + 4 * 15, 4); + u4User2UP = ntohl(u4User2UP); + memcpy(&u4User3UP, HqaCmdFrame->Data + 4 * 16, 4); + u4User3UP = ntohl(u4User3UP); + memcpy(&u4User0MuPfId, HqaCmdFrame->Data + 4 * 17, 4); + u4User0MuPfId = ntohl(u4User0MuPfId); + memcpy(&u4User1MuPfId, HqaCmdFrame->Data + 4 * 18, 4); + u4User1MuPfId = ntohl(u4User1MuPfId); + memcpy(&u4User2MuPfId, HqaCmdFrame->Data + 4 * 19, 4); + u4User2MuPfId = ntohl(u4User2MuPfId); + memcpy(&u4User3MuPfId, HqaCmdFrame->Data + 4 * 20, 4); + u4User3MuPfId = ntohl(u4User3MuPfId); + memcpy(&u4User0InitMCS, HqaCmdFrame->Data + 4 * 21, 4); + u4User0InitMCS = ntohl(u4User0InitMCS); + memcpy(&u4User1InitMCS, HqaCmdFrame->Data + 4 * 22, 4); + u4User1InitMCS = ntohl(u4User1InitMCS); + memcpy(&u4User2InitMCS, HqaCmdFrame->Data + 4 * 23, 4); + u4User2InitMCS = ntohl(u4User2InitMCS); + memcpy(&u4User3InitMCS, HqaCmdFrame->Data + 4 * 24, 4); + u4User3InitMCS = ntohl(u4User3InitMCS); + + memcpy(ucAddr1, HqaCmdFrame->Data + 4 * 25, 6); + memcpy(ucAddr2, HqaCmdFrame->Data + 4 * 25 + 6 * 1, 6); + memcpy(ucAddr3, HqaCmdFrame->Data + 4 * 25 + 6 * 2, 6); + memcpy(ucAddr4, HqaCmdFrame->Data + 4 * 25 + 6 * 3, 6); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + u4GroupIndex, u4NumOfUser, u4User0Ldpc, u4User1Ldpc, u4ShortGI, u4Bw, u4User0Nss, u4User1Nss, + u4GroupId, u4User0UP, u4User1UP, u4User0MuPfId, u4User1MuPfId, u4User0InitMCS, u4User1InitMCS, + ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], ucAddr1[4], ucAddr1[5], ucAddr2[0], ucAddr2[1], + ucAddr2[2], ucAddr2[3], ucAddr2[4], ucAddr2[5]); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUSetGroup(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_MUGetQD(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4SubIdx = 0; + + /* TODO */ + UINT_32 u4User0InitMCS = 0; + UINT_32 u4User1InitMCS = 0; + UINT_32 u4User2InitMCS = 0; + UINT_32 u4User3InitMCS = 0; + + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MUGetQD\n"); + + memcpy(&u4SubIdx, HqaCmdFrame->Data, 4); + u4SubIdx = ntohl(u4SubIdx); + + kalMemSet(prInBuf, 0, sizeof(u4SubIdx)); + kalSprintf(prInBuf, "%u", u4SubIdx); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUGetQD(prNetDev, prInBuf); + + /* TODO */ + u4User0InitMCS = ntohl(u4User0InitMCS); + u4User1InitMCS = ntohl(u4User1InitMCS); + u4User2InitMCS = ntohl(u4User2InitMCS); + u4User3InitMCS = ntohl(u4User3InitMCS); + + memcpy(HqaCmdFrame->Data + 2, &u4User0InitMCS, sizeof(UINT_32)); + memcpy(HqaCmdFrame->Data + 2 + 1 * sizeof(UINT_32), &u4User1InitMCS, sizeof(UINT_32)); + memcpy(HqaCmdFrame->Data + 2 + 2 * sizeof(UINT_32), &u4User2InitMCS, sizeof(UINT_32)); + memcpy(HqaCmdFrame->Data + 2 + 3 * sizeof(UINT_32), &u4User3InitMCS, sizeof(UINT_32)); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_MUSetEnable(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Enable = 0; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MUSetEnable\n"); + + memcpy(&u4Enable, HqaCmdFrame->Data + 4 * 0, 4); + u4Enable = ntohl(u4Enable); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x", u4Enable); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUSetEnable(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_MUSetGID_UP(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 au4Gid[2]; + UINT_32 au4Up[4]; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MUSetGID_UP\n"); + + memcpy(&au4Gid[0], HqaCmdFrame->Data + 4 * 0, 4); + au4Gid[0] = ntohl(au4Gid[0]); + memcpy(&au4Gid[1], HqaCmdFrame->Data + 4 * 1, 4); + au4Gid[1] = ntohl(au4Gid[1]); + memcpy(&au4Up[0], HqaCmdFrame->Data + 4 * 2, 4); + au4Up[0] = ntohl(au4Up[0]); + memcpy(&au4Up[1], HqaCmdFrame->Data + 4 * 3, 4); + au4Up[1] = ntohl(au4Up[1]); + memcpy(&au4Up[2], HqaCmdFrame->Data + 4 * 4, 4); + au4Up[2] = ntohl(au4Up[2]); + memcpy(&au4Up[3], HqaCmdFrame->Data + 4 * 5, 4); + au4Up[3] = ntohl(au4Up[3]); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x:%02x:%02x:%02x:%02x:%02x", au4Gid[0], au4Gid[1], au4Up[0], au4Up[1], au4Up[2], + au4Up[3]); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUSetGID_UP(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static INT_32 HQA_MUTriggerTx(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4BandIdx, u4IsRandomPattern; + UINT_32 u4MsduPayloadLength0, u4MsduPayloadLength1, u4MsduPayloadLength2, u4MsduPayloadLength3; + UINT_32 u4MuPacketCount, u4NumOfSTAs; + UINT_8 ucAddr1[MAC_ADDR_LEN], ucAddr2[MAC_ADDR_LEN], ucAddr3[MAC_ADDR_LEN], ucAddr4[MAC_ADDR_LEN]; + UINT_8 *prInBuf; + + prInBuf = kmalloc(sizeof(UINT_8) * (HQA_BF_STR_SIZE), GFP_KERNEL); + + if (!prInBuf) + return -ENOMEM; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_MUTriggerTx\n"); + + memcpy(&u4BandIdx, HqaCmdFrame->Data + 4 * 0, 4); + u4BandIdx = ntohl(u4BandIdx); + memcpy(&u4IsRandomPattern, HqaCmdFrame->Data + 4 * 1, 4); + u4IsRandomPattern = ntohl(u4IsRandomPattern); + memcpy(&u4MsduPayloadLength0, HqaCmdFrame->Data + 4 * 2, 4); + u4MsduPayloadLength0 = ntohl(u4MsduPayloadLength0); + memcpy(&u4MsduPayloadLength1, HqaCmdFrame->Data + 4 * 3, 4); + u4MsduPayloadLength1 = ntohl(u4MsduPayloadLength1); + memcpy(&u4MsduPayloadLength2, HqaCmdFrame->Data + 4 * 4, 4); + u4MsduPayloadLength2 = ntohl(u4MsduPayloadLength2); + memcpy(&u4MsduPayloadLength3, HqaCmdFrame->Data + 4 * 5, 4); + u4MsduPayloadLength3 = ntohl(u4MsduPayloadLength3); + memcpy(&u4MuPacketCount, HqaCmdFrame->Data + 4 * 6, 4); + u4MuPacketCount = ntohl(u4MuPacketCount); + memcpy(&u4NumOfSTAs, HqaCmdFrame->Data + 4 * 7, 4); + u4NumOfSTAs = ntohl(u4NumOfSTAs); + memcpy(ucAddr1, HqaCmdFrame->Data + 4 * 8, 6); + memcpy(ucAddr2, HqaCmdFrame->Data + 4 * 8 + 6 * 1, 6); + memcpy(ucAddr3, HqaCmdFrame->Data + 4 * 8 + 6 * 2, 6); + memcpy(ucAddr4, HqaCmdFrame->Data + 4 * 8 + 6 * 3, 6); + + kalMemSet(prInBuf, 0, sizeof(UINT_8) * (HQA_BF_STR_SIZE)); + kalSprintf(prInBuf, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + u4IsRandomPattern, u4MsduPayloadLength0, u4MsduPayloadLength1, u4MuPacketCount, u4NumOfSTAs, + ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], ucAddr1[4], ucAddr1[5], + ucAddr2[0], ucAddr2[1], ucAddr2[2], ucAddr2[3], ucAddr2[4], ucAddr2[5]); + + DBGLOG(RFTEST, ERROR, "MT6632 prInBuf = %s\n", prInBuf); + + i4Ret = Set_MUTriggerTx(prNetDev, prInBuf); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + kfree(prInBuf); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_TXMU_CMDS[] = { + HQA_MUGetInitMCS, /* 0x1560 */ + HQA_MUCalInitMCS, /* 0x1561 */ + HQA_MUCalLQ, /* 0x1562 */ + HQA_MUGetLQ, /* 0x1563 */ + HQA_MUSetSNROffset, /* 0x1564 */ + HQA_MUSetZeroNss, /* 0x1565 */ + HQA_MUSetSpeedUpLQ, /* 0x1566 */ + HQA_MUSetMUTable, /* 0x1567 */ + HQA_MUSetGroup, /* 0x1568 */ + HQA_MUGetQD, /* 0x1569 */ + HQA_MUSetEnable, /* 0x156A */ + HQA_MUSetGID_UP, /* 0x156B */ + HQA_MUTriggerTx, /* 0x156C */ +}; +#endif +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For ICAP +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 HQA_CapWiFiSpectrum(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 u4BufLen = 0; + UINT_32 u4Control = 0; + UINT_32 u4Trigger = 0; + UINT_32 u4RingCapEn = 0; + UINT_32 u4TriggerEvent = 0; + UINT_32 u4CaptureNode = 0; + UINT_32 u4CaptureLen = 0; + UINT_32 u4CapStopCycle = 0; + UINT_32 u4BW = 0; +/* UINT_32 u4MacTriggerEvent = 0; */ /* Temp unused */ +/* UINT_32 u4TriggerMac = 0; */ /* Temp unused */ + UINT_32 u4WFNum; + UINT_32 u4IQ; + UINT_32 u4TempLen = 0; + UINT_32 u4DataLen; + INT_32 i = 0, i4Ret = 0; + INT_32 *prIQAry; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memcpy((PUCHAR)&u4Control, HqaCmdFrame->Data + 4 * 0, 4); + u4Control = ntohl(u4Control); + memcpy((PUCHAR)&u4Trigger, HqaCmdFrame->Data + 4 * 1, 4); + u4Trigger = ntohl(u4Trigger); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_CapWiFiSpectrum u4Control = %d\n", u4Control); + + if (u4Control == 1 && u4Trigger == 1) { + memcpy((PUCHAR)&u4RingCapEn, HqaCmdFrame->Data + 4 * 2, 4); + u4RingCapEn = ntohl(u4RingCapEn); + memcpy((PUCHAR)&u4TriggerEvent, HqaCmdFrame->Data + 4 * 3, 4); + u4TriggerEvent = ntohl(u4TriggerEvent); + memcpy((PUCHAR)&u4CaptureNode, HqaCmdFrame->Data + 4 * 4, 4); + u4CaptureNode = ntohl(u4CaptureNode); + memcpy((PUCHAR)&u4CaptureLen, HqaCmdFrame->Data + 4 * 5, 4); + u4CaptureLen = ntohl(u4CaptureLen); + memcpy((PUCHAR)&u4CapStopCycle, HqaCmdFrame->Data + 4 * 6, 4); + u4CapStopCycle = ntohl(u4CapStopCycle); + memcpy((PUCHAR)&u4BW, HqaCmdFrame->Data + 4 * 7, 4); + u4BW = ntohl(u4BW); + + /* AT Command #1, Trigger always = 1 */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_CapWiFiSpectrum u4Trigger = %d\n", u4Trigger); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_CapWiFiSpectrum u4RingCapEn = %d\n", u4RingCapEn); + /* AT Command #81 */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_CapWiFiSpectrum u4TriggerEvent = %d\n", u4TriggerEvent); + /* AT Command #80 */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_CapWiFiSpectrum u4CaptureNode = %d\n", u4CaptureNode); + /* AT Command #83 */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_CapWiFiSpectrum u4CaptureLen = %d\n", u4CaptureLen); + /* AT Command #84 */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_CapWiFiSpectrum u4CapStopCycle = %d\n", u4CapStopCycle); + /* AT Command #71 */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_CapWiFiSpectrum u4BW = %d\n", u4BW); + + /* iwpriv wlan205 set_test_cmd 75 0 (J mode Setting) */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_J_MODE; + rRfATInfo.u4FuncData = 0; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + /* iwpriv wlan205 set_test_cmd 71 0 (Channel Bandwidth) */ + if (u4BW == 4) + u4BW = 3; + else if (u4BW == 3) + u4BW = 4; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_CBW; + rRfATInfo.u4FuncData = u4BW; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + /* iwpriv wlan205 set_test_cmd 24 0 (ADC clock mode) */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_ADC_CLK_MODE; + rRfATInfo.u4FuncData = 0; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + /* iwpriv wlan205 set_test_cmd 84 18000 (Internal Capture Trigger Offset) */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ICAP_TRIGGER_OFFSET; + rRfATInfo.u4FuncData = u4CapStopCycle; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + if (u4CaptureLen == 0) + u4CaptureLen = 196615;/* 24000; */ + /* iwpriv wlan205 set_test_cmd 83 24576 (Internal Capture Size) */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ICAP_SIZE; + rRfATInfo.u4FuncData = u4CaptureLen; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + /* iwpriv wlan205 set_test_cmd 80 0 (Internal Capture Content) */ + if (u4CaptureNode == 0x6) + u4CaptureNode = 0x10000006; + else if (u4CaptureNode == 0x8) + u4CaptureNode = 0x49; + else if (u4CaptureNode == 0x9) + u4CaptureNode = 0x48; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ICAP_CONTENT; + rRfATInfo.u4FuncData = u4CaptureNode; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + /* iwpriv wlan205 set_test_cmd 81 0 (Internal Capture Trigger mode) */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ICAP_MODE; + rRfATInfo.u4FuncData = u4TriggerEvent; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_ICAP_RING; + rRfATInfo.u4FuncData = u4RingCapEn; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + /* iwpriv wlan205 set_test_cmd 1 13 */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_CH_SWITCH_FOR_ICAP; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + /* iwpriv wlan205 set_test_cmd 1 11 */ + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_COMMAND; + rRfATInfo.u4FuncData = RF_AT_COMMAND_ICAP; + + rStatus = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + } else if (u4Control == 2) { + if (g_bCaptureDone) { + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_CapWiFiSpectrum Done!!!!!!!!!!!!!!!!!\n"); + i4Ret = 0; + /* Query whether ICAP Done */ + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + } else { + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_CapWiFiSpectrum Wait!!!!!!!!!!!!!!!!!\n"); + i4Ret = 1; + /* Query whether ICAP Done */ + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + } + } else if (u4Control == 3) { + memcpy((PUCHAR)&u4WFNum, HqaCmdFrame->Data + 4 * 1, 4); + u4WFNum = ntohl(u4WFNum); + memcpy((PUCHAR)&u4IQ, HqaCmdFrame->Data + 4 * 2, 4); + u4IQ = ntohl(u4IQ); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_CapWiFiSpectrum u4WFNum = %d\n", u4WFNum); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_CapWiFiSpectrum u4IQ = %d\n", u4IQ); + + if (u4WFNum <= 1) { + u4DataLen = 0; + GetIQData(&prIQAry, &u4DataLen, u4IQ, u4WFNum); + u4TempLen = u4DataLen; + u4DataLen /= 4; + + u4Control = ntohl(u4Control); + memcpy(HqaCmdFrame->Data + 2 + 4 * 0, (UCHAR *) &u4Control, sizeof(u4Control)); + u4WFNum = ntohl(u4WFNum); + memcpy(HqaCmdFrame->Data + 2 + 4 * 1, (UCHAR *) &u4WFNum, sizeof(u4WFNum)); + u4IQ = ntohl(u4IQ); + memcpy(HqaCmdFrame->Data + 2 + 4 * 2, (UCHAR *) &u4IQ, sizeof(u4IQ)); + u4DataLen = ntohl(u4DataLen); + memcpy(HqaCmdFrame->Data + 2 + 4 * 3, (UCHAR *) &u4DataLen, sizeof(u4DataLen)); + + for (i = 0; i < u4TempLen / sizeof(UINT_32); i++) + prIQAry[i] = ntohl(prIQAry[i]); + + memcpy(HqaCmdFrame->Data + 2 + 4 * 4, (UCHAR *) &prIQAry[0], u4TempLen); + } else { + u4TempLen = 0; + } + + /* Get IQ Data and transmit them to UI DLL */ + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + 4 * 4 + u4TempLen, i4Ret); + } else { + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + } + return rStatus; +} + +static HQA_CMD_HANDLER HQA_ICAP_CMDS[] = { + HQA_CapWiFiSpectrum, /* 0x1580 */ +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 hqa_set_channel_ext(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Ext_id = 0; + UINT_32 u4Param_num = 0; + UINT_32 u4Band_idx = 0; + UINT_32 u4Central_ch0 = 0; + UINT_32 u4Central_ch1 = 0; + UINT_32 u4Sys_bw = 0; + UINT_32 u4Perpkt_bw = 0; + UINT_32 u4Pri_sel = 0; + UINT_32 u4Reason = 0; + UINT_32 u4Ch_band = 0; + UINT_32 u4SetFreq = 0; + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4Param_num, HqaCmdFrame->Data + 4 * 1, 4); + u4Param_num = ntohl(u4Param_num); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 2, 4); + u4Band_idx = ntohl(u4Band_idx); + memcpy(&u4Central_ch0, HqaCmdFrame->Data + 4 * 3, 4); + u4Central_ch0 = ntohl(u4Central_ch0); + memcpy(&u4Central_ch1, HqaCmdFrame->Data + 4 * 4, 4); + u4Central_ch1 = ntohl(u4Central_ch1); + memcpy(&u4Sys_bw, HqaCmdFrame->Data + 4 * 5, 4); + u4Sys_bw = ntohl(u4Sys_bw); + memcpy(&u4Perpkt_bw, HqaCmdFrame->Data + 4 * 6, 4); + u4Perpkt_bw = ntohl(u4Perpkt_bw); + memcpy(&u4Pri_sel, HqaCmdFrame->Data + 4 * 7, 4); + u4Pri_sel = ntohl(u4Pri_sel); + memcpy(&u4Reason, HqaCmdFrame->Data + 4 * 8, 4); + u4Reason = ntohl(u4Reason); + memcpy(&u4Ch_band, HqaCmdFrame->Data + 4 * 9, 4); + u4Ch_band = ntohl(u4Ch_band); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_set_channel_ext ext_id : %d\n", u4Ext_id); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_set_channel_ext param_num : %d\n", u4Param_num); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_set_channel_ext band_idx : %d\n", u4Band_idx); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_set_channel_ext central_ch0 : %d\n", u4Central_ch0); + /* for BW80+80 */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_set_channel_ext central_ch1 : %d\n", u4Central_ch1); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_set_channel_ext sys_bw : %d\n", u4Sys_bw); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_set_channel_ext perpkt_bw : %d\n", u4Perpkt_bw); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_set_channel_ext pri_sel : %d\n", u4Pri_sel); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_set_channel_ext reason : %d\n", u4Reason); + /* 0:2.4G 1:5G */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_set_channel_ext ch_band : %d\n", u4Ch_band); + + /* BW Mapping in QA Tool + * 0: BW20 + * 1: BW40 + * 2: BW80 + * 3: BW10 + * 4: BW5 + * 5: BW160C + * 6: BW160NC + */ + /* BW Mapping in MT6632 FW + * 0: BW20 + * 1: BW40 + * 2: BW80 + * 3: BW160C + * 4: BW160NC + * 5: BW5 + * 6: BW10 + */ + /* For POR Cal Setting - 20160601 */ + if ((u4Central_ch0 == u4Central_ch1) && (u4Sys_bw == 6) && (u4Perpkt_bw == 6)) { + DBGLOG(RFTEST, INFO, "MT6632 : Wrong Setting for POR Cal\n"); + goto exit; + } + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + if ((u4Central_ch0 >= 7 && u4Central_ch0 <= 16) && u4Ch_band == 1) { + /*Ch7 - Ch12, 5G (5035-5060)*/ + u4SetFreq = 1000 * (5000 + u4Central_ch0 * 5); + } else if (u4Central_ch0 == 6 && u4Ch_band == 1) { + u4SetFreq = 1000 * 5032; + } else { + u4SetFreq = nicChannelNum2Freq(u4Central_ch0); + } + MT_ATESetChannel(prNetDev, 0, u4SetFreq); + + if (u4Sys_bw == 6) { + u4SetFreq = nicChannelNum2Freq(u4Central_ch1); + MT_ATESetChannel(prNetDev, 1, u4SetFreq); + } + + MT_ATESetSystemBW(prNetDev, u4Sys_bw); + + /* For POR Cal Setting - 20160601 */ + if ((u4Sys_bw == 6) && (u4Perpkt_bw == 6)) + MT_ATESetPerPacketBW(prNetDev, 5); + else + MT_ATESetPerPacketBW(prNetDev, u4Perpkt_bw); + + MT_ATEPrimarySetting(prNetDev, u4Pri_sel); + /* PeiHsuan Memo : No Set Reason ? */ + MT_ATESetBand(prNetDev, u4Ch_band); + +exit: + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (UCHAR *) &u4Ext_id, sizeof(u4Ext_id)); + + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 hqa_set_txcontent_ext(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Len = 0; + UINT_32 u4Ext_id = 0; + UINT_32 u4Param_num = 0; + UINT_32 u4Band_idx = 0; + UINT_32 u4FC = 0; + UINT_32 u4Dur = 0; + UINT_32 u4Seq = 0; + UINT_32 u4Gen_payload_rule = 0; + UINT_32 u4Txlen = 0; + UINT_32 u4Payload_len = 0; + UINT_8 ucAddr1[MAC_ADDR_LEN]; + UINT_8 ucAddr2[MAC_ADDR_LEN]; + UINT_8 ucAddr3[MAC_ADDR_LEN]; + UINT_32 ucPayload = 0; + + u4Len = ntohs(HqaCmdFrame->Length); + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4Param_num, HqaCmdFrame->Data + 4 * 1, 4); + u4Param_num = ntohl(u4Param_num); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 2, 4); + u4Band_idx = ntohl(u4Band_idx); + memcpy(&u4FC, HqaCmdFrame->Data + 4 * 3, 4); + u4FC = ntohl(u4FC); + memcpy(&u4Dur, HqaCmdFrame->Data + 4 * 4, 4); + u4Dur = ntohl(u4Dur); + memcpy(&u4Seq, HqaCmdFrame->Data + 4 * 5, 4); + u4Seq = ntohl(u4Seq); + memcpy(&u4Gen_payload_rule, HqaCmdFrame->Data + 4 * 6, 4); + u4Gen_payload_rule = ntohl(u4Gen_payload_rule); + memcpy(&u4Txlen, HqaCmdFrame->Data + 4 * 7, 4); + u4Txlen = ntohl(u4Txlen); + memcpy(&u4Payload_len, HqaCmdFrame->Data + 4 * 8, 4); + u4Payload_len = ntohl(u4Payload_len); + memcpy(ucAddr1, HqaCmdFrame->Data + 4 * 9, 6); + memcpy(ucAddr2, HqaCmdFrame->Data + 4 * 9 + 6 * 1, 6); + memcpy(ucAddr3, HqaCmdFrame->Data + 4 * 9 + 6 * 2, 6); + memcpy(&ucPayload, HqaCmdFrame->Data + 4 * 9 + 6 * 3, 1); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_set_txcontent_ext ext_id : %d\n", u4Ext_id); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_set_txcontent_ext param_num : %d\n", u4Param_num); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_set_txcontent_ext band_idx : %d\n", u4Band_idx); + /* Frame Control...0800 : Beacon */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_set_txcontent_ext FC : 0x%x\n", u4FC); + /* Duration....NAV */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_set_txcontent_ext dur : 0x%x\n", u4Dur); + /* Sequence Control */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_set_txcontent_ext seq : 0x%x\n", u4Seq); + /* Normal:0,Repeat:1,Random:2 */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_set_txcontent_ext gen_payload_rule : %d\n", u4Gen_payload_rule); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_set_txcontent_ext txlen : %d\n", u4Txlen); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_set_txcontent_ext payload_len : %d\n", u4Payload_len); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_set_txcontent_ext addr1:%02x:%02x:%02x:%02x:%02x:%02x\n", + ucAddr1[0], ucAddr1[1], ucAddr1[2], ucAddr1[3], ucAddr1[4], ucAddr1[5]); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_set_txcontent_ext addr2:%02x:%02x:%02x:%02x:%02x:%02x\n", + ucAddr2[0], ucAddr2[1], ucAddr2[2], ucAddr2[3], ucAddr2[4], ucAddr2[5]); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_set_txcontent_ext addr3:%02x:%02x:%02x:%02x:%02x:%02x\n", + ucAddr3[0], ucAddr3[1], ucAddr3[2], ucAddr3[3], ucAddr3[4], ucAddr3[5]); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_start_tx_ext payload : 0x%x\n", ucPayload); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + MT_ATESetMacHeader(prNetDev, u4FC, u4Dur, u4Seq); + MT_ATESetTxPayLoad(prNetDev, u4Gen_payload_rule, ucPayload); + MT_ATESetTxLength(prNetDev, u4Txlen); + MT_ATESetMACAddress(prNetDev, RF_AT_FUNCID_SET_MAC_ADDRESS, ucAddr1); + MT_ATESetMACAddress(prNetDev, RF_AT_FUNCID_SET_TA, ucAddr2); + /* PeiHsuan Memo : No Set Addr3 */ + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (UCHAR *) &u4Ext_id, sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + sizeof(u4Ext_id), i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 hqa_start_tx_ext(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Ext_id = 0; + UINT_32 u4Param_num = 0; + UINT_32 u4Band_idx = 0; + UINT_32 u4Pkt_cnt = 0; + UINT_32 u4Phymode = 0; + UINT_32 u4Rate = 0; + UINT_32 u4Pwr = 0; + UINT_32 u4Stbc = 0; + UINT_32 u4Ldpc = 0; + UINT_32 u4iBF = 0; + UINT_32 u4eBF = 0; + UINT_32 u4Wlan_id = 0; + UINT_32 u4Aifs = 0; + UINT_32 u4Gi = 0; + UINT_32 u4Tx_path = 0; + UINT_32 u4Nss = 0; + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4Param_num, HqaCmdFrame->Data + 4 * 1, 4); + u4Param_num = ntohl(u4Param_num); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 * 2, 4); + u4Band_idx = ntohl(u4Band_idx); + memcpy(&u4Pkt_cnt, HqaCmdFrame->Data + 4 * 3, 4); + u4Pkt_cnt = ntohl(u4Pkt_cnt); + memcpy(&u4Phymode, HqaCmdFrame->Data + 4 * 4, 4); + u4Phymode = ntohl(u4Phymode); + memcpy(&u4Rate, HqaCmdFrame->Data + 4 * 5, 4); + u4Rate = ntohl(u4Rate); + memcpy(&u4Pwr, HqaCmdFrame->Data + 4 * 6, 4); + u4Pwr = ntohl(u4Pwr); + memcpy(&u4Stbc, HqaCmdFrame->Data + 4 * 7, 4); + u4Stbc = ntohl(u4Stbc); + memcpy(&u4Ldpc, HqaCmdFrame->Data + 4 * 8, 4); + u4Ldpc = ntohl(u4Ldpc); + memcpy(&u4iBF, HqaCmdFrame->Data + 4 * 9, 4); + u4iBF = ntohl(u4iBF); + memcpy(&u4eBF, HqaCmdFrame->Data + 4 * 10, 4); + u4eBF = ntohl(u4eBF); + memcpy(&u4Wlan_id, HqaCmdFrame->Data + 4 * 11, 4); + u4Wlan_id = ntohl(u4Wlan_id); + memcpy(&u4Aifs, HqaCmdFrame->Data + 4 * 12, 4); + u4Aifs = ntohl(u4Aifs); + memcpy(&u4Gi, HqaCmdFrame->Data + 4 * 13, 4); + u4Gi = ntohl(u4Gi); + memcpy(&u4Tx_path, HqaCmdFrame->Data + 4 * 14, 4); + u4Tx_path = ntohl(u4Tx_path); + memcpy(&u4Nss, HqaCmdFrame->Data + 4 * 15, 4); + u4Nss = ntohl(u4Nss); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_start_tx_ext ext_id : %d\n", u4Ext_id); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_start_tx_ext param_num : %d\n", u4Param_num); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_start_tx_ext band_idx : %d\n", u4Band_idx); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_start_tx_ext pkt_cnt : %d\n", u4Pkt_cnt); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_start_tx_ext phymode : %d\n", u4Phymode); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_start_tx_ext rate : %d\n", u4Rate); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_start_tx_ext pwr : %d\n", u4Pwr); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_start_tx_ext stbc : %d\n", u4Stbc); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_start_tx_ext ldpc : %d\n", u4Ldpc); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_start_tx_ext ibf : %d\n", u4iBF); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_start_tx_ext ebf : %d\n", u4eBF); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_start_tx_ext wlan_id : %d\n", u4Wlan_id); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_start_tx_ext aifs : %d\n", u4Aifs); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_start_tx_ext gi : %d\n", u4Gi); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_start_tx_ext tx_path : %d\n", u4Tx_path); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_start_tx_ext nss : %d\n", u4Nss); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + MT_ATESetTxCount(prNetDev, u4Pkt_cnt); + +#if 1 + if (u4Phymode == 1) { + u4Phymode = 0; + u4Rate += 4; + } else if ((u4Phymode == 0) && ((u4Rate == 9) || (u4Rate == 10) || (u4Rate == 11))) + u4Phymode = 1; + MT_ATESetPreamble(prNetDev, u4Phymode); + + if (u4Phymode == 0) { + u4Rate |= 0x00000000; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT CCK/OFDM (normal preamble) rate : %d\n", u4Rate); + + MT_ATESetRate(prNetDev, u4Rate); + } else if (u4Phymode == 1) { + if (u4Rate == 9) + u4Rate = 1; + else if (u4Rate == 10) + u4Rate = 2; + else if (u4Rate == 11) + u4Rate = 3; + u4Rate |= 0x00000000; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT CCK (short preamble) rate : %d\n", u4Rate); + + MT_ATESetRate(prNetDev, u4Rate); + } else if (u4Phymode >= 2 && u4Phymode <= 4) { + u4Rate |= 0x80000000; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HT/VHT rate : %d\n", u4Rate); + + MT_ATESetRate(prNetDev, u4Rate); + } +#endif + + MT_ATESetTxPower0(prNetDev, u4Pwr); + MT_ATESetTxSTBC(prNetDev, u4Stbc); + MT_ATESetEncodeMode(prNetDev, u4Ldpc); + MT_ATESetiBFEnable(prNetDev, u4iBF); + MT_ATESeteBFEnable(prNetDev, u4eBF); + /* PeiHsuan Memo : No Set Wlan ID */ + MT_ATESetTxIPG(prNetDev, u4Aifs); + MT_ATESetTxGi(prNetDev, u4Gi); + MT_ATESetTxVhtNss(prNetDev, u4Nss); + MT_ATESetTxPath(prNetDev, u4Tx_path); + MT_ATEStartTX(prNetDev, "TXFRAME"); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (UCHAR *) &u4Ext_id, sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + sizeof(u4Ext_id), i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 hqa_start_rx_ext(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Ext_id = 0; + UINT_32 u4Param_num = 0; + UINT_32 u4Band_idx = 0; + UINT_32 u4Rx_path = 0; + UCHAR ucOwn_mac[MAC_ADDR_LEN]; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + UINT_32 u4BufLen = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memcpy(&u4Ext_id, HqaCmdFrame->Data, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4Param_num, HqaCmdFrame->Data + 4, 4); + u4Param_num = ntohl(u4Param_num); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 + 4, 4); + u4Band_idx = ntohl(u4Band_idx); + memcpy(ucOwn_mac, HqaCmdFrame->Data + 4 + 4 + 4, 6); + memcpy(&u4Rx_path, HqaCmdFrame->Data + 4 + 4 + 4 + 6, 4); + u4Rx_path = ntohl(u4Rx_path); + + memset(&g_HqaRxStat, 0, sizeof(PARAM_RX_STAT_T)); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_start_rx_ext ext_id : %d\n", u4Ext_id); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_start_rx_ext param_num : %d\n", u4Param_num); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_start_rx_ext band_idx : %d\n", u4Band_idx); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_start_rx_ext own_mac:%02x:%02x:%02x:%02x:%02x:%02x\n", + ucOwn_mac[0], ucOwn_mac[1], ucOwn_mac[2], ucOwn_mac[3], ucOwn_mac[4], ucOwn_mac[5]); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_start_rx_ext rx_path : 0x%x\n", u4Rx_path); + + u4RxStatSeqNum = 0; + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + + rRfATInfo.u4FuncIndex = RF_AT_FUNCID_SET_RX_PATH; + rRfATInfo.u4FuncData = u4Rx_path << 16 | u4Band_idx; + + i4Ret = kalIoctl(prGlueInfo, /* prGlueInfo */ + wlanoidRftestSetAutoTest, /* pfnOidHandler */ + &rRfATInfo, /* pvInfoBuf */ + sizeof(rRfATInfo), /* u4InfoBufLen */ + FALSE, /* fgRead */ + FALSE, /* fgWaitResp */ + TRUE, /* fgCmd */ + &u4BufLen); /* pu4QryInfoLen */ + + if (i4Ret != WLAN_STATUS_SUCCESS) + return -EFAULT; + /* PeiHsuan Memo : No Set Own MAC Address */ + MT_ATEStartRX(prNetDev, "RXFRAME"); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (UCHAR *) &u4Ext_id, sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 2 + sizeof(u4Ext_id), i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 hqa_stop_tx_ext(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Ext_id = 0; + UINT_32 u4Param_num = 0; + UINT_32 u4Band_idx = 0; + + memcpy(&u4Ext_id, HqaCmdFrame->Data, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4Param_num, HqaCmdFrame->Data + 4, 4); + u4Param_num = ntohl(u4Param_num); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 + 4, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_stop_tx_ext ext_id : %d\n", u4Ext_id); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_stop_tx_ext param_num : %d\n", u4Param_num); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_stop_tx_ext band_idx : %d\n", u4Band_idx); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + MT_ATEStopTX(prNetDev, "TXSTOP"); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (UCHAR *) &u4Ext_id, sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 hqa_stop_rx_ext(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Ext_id = 0; + UINT_32 u4Param_num = 0; + UINT_32 u4Band_idx = 0; + + memcpy(&u4Ext_id, HqaCmdFrame->Data, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4Param_num, HqaCmdFrame->Data + 4, 4); + u4Param_num = ntohl(u4Param_num); + memcpy(&u4Band_idx, HqaCmdFrame->Data + 4 + 4, 4); + u4Band_idx = ntohl(u4Band_idx); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_stop_rx_ext ext_id : %d\n", u4Ext_id); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_stop_rx_ext param_num : %d\n", u4Param_num); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_stop_rx_ext band_idx : %d\n", u4Band_idx); + + MT_ATESetDBDCBandIndex(prNetDev, u4Band_idx); + MT_ATEStopRX(prNetDev, "RXSTOP"); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (UCHAR *) &u4Ext_id, sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +static INT_32 HQA_iBFInit(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_iBFInit\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static INT_32 HQA_iBFSetValue(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_iBFSetValue\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static INT_32 HQA_iBFGetStatus(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_iBFGetStatus\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static INT_32 HQA_iBFChanProfUpdate(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_iBFChanProfUpdate\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static INT_32 HQA_iBFProfileRead(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_iBFProfileRead\n"); + + ResponseToQA(HqaCmdFrame, prIwReqData, 2, i4Ret); + + return i4Ret; +} + +static INT_32 HQA_IRRSetADC(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4WFIdx; + UINT_32 u4ChFreq; + UINT_32 u4BW; + UINT_32 u4Sx; + UINT_32 u4Band; + UINT_32 u4Ext_id; + UINT_32 u4RunType; + UINT_32 u4FType; + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4WFIdx, HqaCmdFrame->Data + 4 * 1, 4); + u4WFIdx = ntohl(u4WFIdx); + memcpy(&u4ChFreq, HqaCmdFrame->Data + 4 * 2, 4); + u4ChFreq = ntohl(u4ChFreq); + memcpy(&u4BW, HqaCmdFrame->Data + 4 * 3, 4); + u4BW = ntohl(u4BW); + memcpy(&u4Sx, HqaCmdFrame->Data + 4 * 4, 4); + u4Sx = ntohl(u4Sx); + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 5, 4); + u4Band = ntohl(u4Band); + memcpy(&u4RunType, HqaCmdFrame->Data + 4 * 6, 4); + u4RunType = ntohl(u4RunType); + memcpy(&u4FType, HqaCmdFrame->Data + 4 * 7, 4); + u4FType = ntohl(u4FType); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_IRRSetADC ext_id : %d\n", u4Ext_id); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_IRRSetADC u4WFIdx : %d\n", u4WFIdx); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_IRRSetADC u4ChFreq : %d\n", u4ChFreq); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_IRRSetADC u4BW : %d\n", u4BW); + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_IRRSetADC u4Sx : %d\n", u4Sx); /* SX : 0, 2 */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_IRRSetADC u4Band : %d\n", u4Band); + /* RunType : 0 -> QA, 1 -> ATE */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_IRRSetADC u4RunType : %d\n", u4RunType); + /* FType : 0 -> FI, 1 -> FD */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_IRRSetADC u4FType : %d\n", u4FType); + + i4Ret = MT_ATE_IRRSetADC(prNetDev, u4WFIdx, u4ChFreq, u4BW, u4Sx, u4Band, u4RunType, u4FType); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (UCHAR *) &u4Ext_id, sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +static INT_32 HQA_IRRSetRxGain(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4PgaLpfg; + UINT_32 u4Lna; + UINT_32 u4Band; + UINT_32 u4WF_inx; + UINT_32 u4Rfdgc; + UINT_32 u4Ext_id; + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4PgaLpfg, HqaCmdFrame->Data + 4 * 1, 4); + u4PgaLpfg = ntohl(u4PgaLpfg); + memcpy(&u4Lna, HqaCmdFrame->Data + 4 * 2, 4); + u4Lna = ntohl(u4Lna); + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 3, 4); + u4Band = ntohl(u4Band); + memcpy(&u4WF_inx, HqaCmdFrame->Data + 4 * 4, 4); + u4WF_inx = ntohl(u4WF_inx); + memcpy(&u4Rfdgc, HqaCmdFrame->Data + 4 * 5, 4); + u4Rfdgc = ntohl(u4Rfdgc); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_IRRSetRxGain ext_id : %d\n", u4Ext_id); + /* PGA is for MT663, LPFG is for MT7615 */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_IRRSetRxGain u4PgaLpfg : %d\n", u4PgaLpfg); + /* 5 : UH, 4 : H, 3 : M, 2 : L, 1 : UL */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_IRRSetRxGain u4Lna : %d\n", u4Lna); + /* DBDC band0 or band1 */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_IRRSetRxGain u4Band : %d\n", u4Band); + /* (each bit for each WF) */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_IRRSetRxGain u4WF_inx : 0x%x\n", u4WF_inx); + /* only for MT6632 */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_IRRSetRxGain u4Rfdgc : %d\n", u4Rfdgc); + + i4Ret = MT_ATE_IRRSetRxGain(prNetDev, u4PgaLpfg, u4Lna, u4Band, u4WF_inx, u4Rfdgc); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (UCHAR *) &u4Ext_id, sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +static INT_32 HQA_IRRSetTTG(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Ext_id; + UINT_32 u4TTGPwrIdx; + UINT_32 u4ChFreq; + UINT_32 u4FIToneFreq; + UINT_32 u4Band; + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4TTGPwrIdx, HqaCmdFrame->Data + 4 * 1, 4); + u4TTGPwrIdx = ntohl(u4TTGPwrIdx); + memcpy(&u4ChFreq, HqaCmdFrame->Data + 4 * 2, 4); + u4ChFreq = ntohl(u4ChFreq); + memcpy(&u4FIToneFreq, HqaCmdFrame->Data + 4 * 3, 4); + u4FIToneFreq = ntohl(u4FIToneFreq); + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 4, 4); + u4Band = ntohl(u4Band); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_IRRSetTTG ext_id : %d\n", u4Ext_id); + /* TTG Power Index: Power index value 0~15 */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_IRRSetTTG u4TTGPwrIdx : %d\n", u4TTGPwrIdx); + /* Ch Freq: channel frequency value */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_IRRSetTTG u4ChFreq : %d\n", u4ChFreq); + /* FI Tone Freq(float): driver calculate TTG Freq(TTG Freq = Ch_freq + FI tone freq) */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_IRRSetTTG u4FIToneFreq : %d\n", u4FIToneFreq); + /* Band: DBDC band0 or band1 */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_IRRSetTTG u4Band : %d\n", u4Band); + + i4Ret = MT_ATE_IRRSetTTG(prNetDev, u4TTGPwrIdx, u4ChFreq, u4FIToneFreq, u4Band); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (UCHAR *) &u4Ext_id, sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +static INT_32 HQA_IRRSetTrunOnTTG(struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + UINT_32 u4Ext_id; + UINT_32 u4TTGOnOff; + UINT_32 u4Band; + UINT_32 u4WF_inx = 0; + + memcpy(&u4Ext_id, HqaCmdFrame->Data + 4 * 0, 4); + u4Ext_id = ntohl(u4Ext_id); + memcpy(&u4TTGOnOff, HqaCmdFrame->Data + 4 * 1, 4); + u4TTGOnOff = ntohl(u4TTGOnOff); + memcpy(&u4Band, HqaCmdFrame->Data + 4 * 2, 4); + u4Band = ntohl(u4Band); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_IRRSetTrunOnTTG ext_id : %d\n", u4Ext_id); + /* TTG on/off: 0:off, 1: on */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_IRRSetTrunOnTTG u4TTGOnOff : %d\n", u4TTGOnOff); + /* Band: DBDC band0 or band1 */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_IRRSetTrunOnTTG u4Band : %d\n", u4Band); + /* (each bit for each WF) */ + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT HQA_IRRSetTrunOnTTG u4WF_inx : %d\n", u4WF_inx); + + i4Ret = MT_ATE_IRRSetTrunOnTTG(prNetDev, u4TTGOnOff, u4Band, u4WF_inx); + + u4Ext_id = ntohl(u4Ext_id); + memcpy(HqaCmdFrame->Data + 2, (UCHAR *) &u4Ext_id, sizeof(u4Ext_id)); + ResponseToQA(HqaCmdFrame, prIwReqData, 6, i4Ret); + + return i4Ret; +} + +static HQA_CMD_HANDLER hqa_ext_cmd_set[] = { + NULL, + hqa_set_channel_ext, /* 0x00000001 */ + hqa_set_txcontent_ext, /* 0x00000002 */ + hqa_start_tx_ext, /* 0x00000003 */ + hqa_start_rx_ext, /* 0x00000004 */ + hqa_stop_tx_ext, /* 0x00000005 */ + hqa_stop_rx_ext, /* 0x00000006 */ + HQA_iBFInit, /* 0x00000007 */ + HQA_iBFSetValue, /* 0x00000008 */ + HQA_iBFGetStatus, /* 0x00000009 */ + HQA_iBFChanProfUpdate, /* 0x0000000A */ + HQA_iBFProfileRead, /* 0x0000000B */ + ToDoFunction, /* 0x0000000C */ + ToDoFunction, /* 0x0000000D */ + ToDoFunction, /* 0x0000000E */ + ToDoFunction, /* 0x0000000F */ + ToDoFunction, /* 0x00000010 */ + ToDoFunction, /* 0x00000011 */ + ToDoFunction, /* 0x00000012 */ + ToDoFunction, /* 0x00000013 */ + ToDoFunction, /* 0x00000014 */ + ToDoFunction, /* 0x00000015 */ + ToDoFunction, /* 0x00000016 */ + ToDoFunction, /* 0x00000017 */ + ToDoFunction, /* 0x00000018 */ + ToDoFunction, /* 0x00000019 */ + ToDoFunction, /* 0x0000001A */ + ToDoFunction, /* 0x0000001B */ + ToDoFunction, /* 0x0000001C */ + ToDoFunction, /* 0x0000001D */ + ToDoFunction, /* 0x0000001E */ + ToDoFunction, /* 0x0000001F */ + HQA_IRRSetADC, /* 0x00000020 */ + HQA_IRRSetRxGain, /* 0x00000021 */ + HQA_IRRSetTTG, /* 0x00000022 */ + HQA_IRRSetTrunOnTTG, /* 0x00000023 */ +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Extension Commands (For MT7615). +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 hqa_ext_cmds(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Ret = 0; + INT_32 i4Idx = 0; + + memmove((PUCHAR)&i4Idx, (PUCHAR)&HqaCmdFrame->Data, 4); + i4Idx = ntohl(i4Idx); + + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT hqa_ext_cmds index : %d\n", i4Idx); + + if (i4Idx < (sizeof(hqa_ext_cmd_set) / sizeof(HQA_CMD_HANDLER))) { + if (hqa_ext_cmd_set[i4Idx] != NULL) + i4Ret = (*hqa_ext_cmd_set[i4Idx]) (prNetDev, prIwReqData, HqaCmdFrame); + else + DBGLOG(RFTEST, INFO, + "MT6632 : QA_AGENT hqa_ext_cmds cmd idx %d is NULL\n", + i4Idx); + } else + DBGLOG(RFTEST, INFO, + "MT6632 : QA_AGENT hqa_ext_cmds cmd idx %d is not supported\n", + i4Idx); + + return i4Ret; +} + +static HQA_CMD_HANDLER HQA_CMD_SET6[] = { + /* cmd id start from 0x1600 */ + hqa_ext_cmds, /* 0x1600 */ +}; + +static HQA_CMD_TABLE HQA_CMD_TABLES[] = { + { + HQA_CMD_SET0, + sizeof(HQA_CMD_SET0) / sizeof(HQA_CMD_HANDLER), + 0x1000, + } + , + { + HQA_CMD_SET1, + sizeof(HQA_CMD_SET1) / sizeof(HQA_CMD_HANDLER), + 0x1100, + } + , + { + HQA_CMD_SET2, + sizeof(HQA_CMD_SET2) / sizeof(HQA_CMD_HANDLER), + 0x1200, + } + , + { + HQA_CMD_SET3, + sizeof(HQA_CMD_SET3) / sizeof(HQA_CMD_HANDLER), + 0x1300, + } + , + { + HQA_CMD_SET4, + sizeof(HQA_CMD_SET4) / sizeof(HQA_CMD_HANDLER), + 0x1400, + } + , + { + HQA_CMD_SET5, + sizeof(HQA_CMD_SET5) / sizeof(HQA_CMD_HANDLER), + 0x1500, + } + , +#if CFG_SUPPORT_TX_BF + { + HQA_TXBF_CMDS, + sizeof(HQA_TXBF_CMDS) / sizeof(HQA_CMD_HANDLER), + 0x1540, + } + , +#if CFG_SUPPORT_MU_MIMO + { + HQA_TXMU_CMDS, + sizeof(HQA_TXMU_CMDS) / sizeof(HQA_CMD_HANDLER), + 0x1560, + } + , +#endif +#endif + { + HQA_ICAP_CMDS, + sizeof(HQA_ICAP_CMDS) / sizeof(HQA_CMD_HANDLER), + 0x1580, + } + , + { + HQA_CMD_SET6, + sizeof(HQA_CMD_SET6) / sizeof(HQA_CMD_HANDLER), + 0x1600, + } + , +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief QA Agent For Handle Ethernet command by Command Idx. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqData +* \param[in] HqaCmdFrame Ethernet Frame Format receive from QA Tool DLL +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +int HQA_CMDHandler(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame) +{ + INT_32 i4Status = 0; + UINT_32 u4CmdId; + UINT_32 u4TableIndex = 0; + + u4CmdId = ntohs(HqaCmdFrame->Id); + + while (u4TableIndex < (sizeof(HQA_CMD_TABLES) / sizeof(HQA_CMD_TABLE))) { + int CmdIndex = 0; + + CmdIndex = u4CmdId - HQA_CMD_TABLES[u4TableIndex].CmdOffset; + if ((CmdIndex >= 0) && (CmdIndex < HQA_CMD_TABLES[u4TableIndex].CmdSetSize)) { + HQA_CMD_HANDLER *pCmdSet; + + pCmdSet = HQA_CMD_TABLES[u4TableIndex].CmdSet; + + if (pCmdSet[CmdIndex] != NULL) + i4Status = (*pCmdSet[CmdIndex]) (prNetDev, prIwReqData, HqaCmdFrame); + break; + } + u4TableIndex++; + } + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Ioctl entry from ATE Daemon. +* +* \param[in] prNetDev Pointer to the Net Device +* \param[in] prIwReqInfo +* \param[in] prIwReqData +* \param[in] pcExtra +* \param[out] None +* +* \retval 0 On success. +*/ +/*----------------------------------------------------------------------------*/ +int priv_qa_agent(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) +{ + INT_32 i4Status = 0; + HQA_CMD_FRAME *HqaCmdFrame; + UINT_32 u4ATEMagicNum, u4ATEId, u4ATEData; + + HqaCmdFrame = kmalloc(sizeof(*HqaCmdFrame), GFP_KERNEL); + + if (!HqaCmdFrame) { + i4Status = -ENOMEM; + goto ERROR0; + } + + memset(HqaCmdFrame, 0, sizeof(*HqaCmdFrame)); + + if (copy_from_user(HqaCmdFrame, prIwReqData->data.pointer, prIwReqData->data.length)) { + i4Status = -EFAULT; + goto ERROR1; + } + + u4ATEMagicNum = ntohl(HqaCmdFrame->MagicNo); + u4ATEId = ntohs(HqaCmdFrame->Id); + memcpy((PUCHAR)&u4ATEData, HqaCmdFrame->Data, 4); + u4ATEData = ntohl(u4ATEData); + + switch (u4ATEMagicNum) { + case HQA_CMD_MAGIC_NO: + i4Status = HQA_CMDHandler(prNetDev, prIwReqData, HqaCmdFrame); + break; + default: + i4Status = -EINVAL; + DBGLOG(RFTEST, INFO, "MT6632 : QA_AGENT ATEMagicNum Error!!!\n"); + break; + } + +ERROR1: + kfree(HqaCmdFrame); +ERROR0: + return i4Status; +} + +int priv_set_eeprom_mode(IN UINT_32 u4Mode) +{ + if ((u4Mode != EFUSE_MODE) && (u4Mode != BUFFER_BIN_MODE)) + return -EINVAL; + + g_ucEepromCurrentMode = u4Mode; + return 0; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_rst.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_rst.c new file mode 100644 index 0000000000000..ce9b2ea7e9607 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_rst.c @@ -0,0 +1,672 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" +#include "gl_os.h" +#include +#include + +#if CFG_CHIP_RESET_SUPPORT + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#ifdef _HIF_SDIO +#define WAIT_CD_STAR_TIME 3 +#define WAIT_CD_END_TIME 30 + +#define MT76x8_PMU_EN_PIN_NAME "mt76x8_pmu_en_gpio" +#define MT76x8_PMU_EN_DELAY_NAME "mt76x8_pmu_en_delay" +#define MT76x8_PMU_EN_DEFAULT_DELAY (5) /* Default delay 5ms */ + +#define BT_NOTIFY 1 +#define TIMEOUT_NOTIFY 2 + +#define NOTIFY_SUCCESS 0 +#define RESETTING 1 +#define NOTIFY_REPEAT 2 +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +struct rst_struct rst_data; + +#ifdef _HIF_SDIO + +BOOLEAN g_fgIsCoreDumpStart = FALSE; +BOOLEAN g_fgIsCoreDumpEnd = FALSE; +BOOLEAN g_fgIsNotifyWlanRemove = FALSE; +BOOLEAN gl_sdio_fail = FALSE; + +struct work_struct remove_work; + + +wait_queue_head_t wait_core_dump_start; +wait_queue_head_t wait_core_dump_end; +struct timer_list wait_CD_start_timer; +struct timer_list wait_CD_end_timer; + +#endif + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#ifdef _HIF_SDIO +BOOLEAN g_fgIsWifiTrig = FALSE; +BOOLEAN g_fgIsBTTrig = FALSE; + +static BOOLEAN g_fgIsBTExist = TRUE; +static BOOLEAN g_fgIsCDEndTimeout = FALSE; +static BOOLEAN g_fgIsNotifyBTRemoveEnd = FALSE; + +#endif +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifdef _HIF_SDIO + +#define IS_CORE_DUMP_START() (g_fgIsCoreDumpStart) +#define IS_CORE_DUMP_END() (g_fgIsCoreDumpEnd) + +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +#ifdef _HIF_SDIO +static void resetInit(void); + +static INT_32 pmu_toggle(struct rst_struct *data); + +static void init_wait_CD_start_timer(void); +static void start_wait_CD_start_timer(void); +static void wait_CD_start_timeout(unsigned long data); + +static void init_wait_CD_end_timer(void); +static void start_wait_CD_end_timer(void); +static void wait_CD_end_timeout(unsigned long data); +static void removeWlanSelf(struct work_struct *work); +static void probeWlanSelf(struct work_struct *work); + +static void RSTClearResource(void); +static void RSTClearState(void); +static VOID set_core_dump_start(BOOLEAN fgVal); +static void RSTP2pDestroyWirelessDevice(void); + +#endif + + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#ifdef _HIF_USB +VOID glResetTrigger(P_ADAPTER_T prAdapter) +{ + void (*btmtk_usb_toggle_rst_pin)(void); + + /* Call POR(Power On Reset) off->on API provided by BT driver */ + btmtk_usb_toggle_rst_pin = (void *)kallsyms_lookup_name("btmtk_usb_toggle_rst_pin"); + + if (!btmtk_usb_toggle_rst_pin) { + DBGLOG(HAL, ERROR, "btmtk_usb_toggle_rst_pin() is not found\n"); + } else { + DBGLOG(HAL, ERROR, "Trigger MT7668 POR(Power On Reset) off->on by BT driver\n"); + btmtk_usb_toggle_rst_pin(); + } + +} +#endif + +#ifdef _HIF_SDIO +VOID glResetTrigger(P_ADAPTER_T prAdapter) +{ + int bet = 0; + typedef int (*p_bt_fun_type) (int); + p_bt_fun_type bt_func; + + /* int btmtk_sdio_bt_trigger_core_dump(int reserved); */ + char *bt_func_name = "btmtk_sdio_bt_trigger_core_dump"; + + DBGLOG(HAL, INFO, "[RST] rst_mutex lock\n"); + mutex_lock(&(rst_data.rst_mutex)); + + if (checkResetState()) { + DBGLOG(HAL, STATE, "[RST] resetting...\n"); + mutex_unlock(&(rst_data.rst_mutex)); + DBGLOG(INIT, INFO, "[RST] rst_mutex unlock\n"); + return; + } + + dump_stack(); + DBGLOG(HAL, STATE, "[RST] glResetTrigger start\n"); + g_fgIsWifiTrig = TRUE; + + mutex_unlock(&(rst_data.rst_mutex)); + DBGLOG(INIT, INFO, "[RST] rst_mutex unlock\n"); + + resetInit(); + + /* check bt module */ + bt_func = (p_bt_fun_type) kallsyms_lookup_name(bt_func_name); + if (bt_func) { + BOOLEAN is_coredump = (~(prAdapter->fgIsChipNoAck)) & 0x1; + + DBGLOG(INIT, STATE, "[RST] wifi driver trigger rst\n"); + DBGLOG(INIT, STATE, "[RST] is_coredump = %d\n", is_coredump); + +#if CFG_ASSERT_DUMP + bet = bt_func(is_coredump); +#else + bet = bt_func(0); +#endif + if (bet) { + g_fgIsBTExist = FALSE; + DBGLOG(INIT, ERROR, "[RST] bt driver is not ready\n"); + /* error handle not yet */ + goto RESET_START; + } else { + g_fgIsBTExist = TRUE; + start_wait_CD_start_timer(); + DBGLOG(INIT, STATE, + "[RST] wait bt core dump start...\n"); + + if (!IS_CORE_DUMP_START()) { + /* wait bt notify */ + wait_event(wait_core_dump_start, + g_fgIsCoreDumpStart); + DBGLOG(INIT, STATE, + "[RST] wait_core_dump_start end\n"); + } + bet = del_timer_sync(&wait_CD_start_timer); + DBGLOG(INIT, INFO, + "[RST] cancel wait_CD_start_timer=%d\n", bet); + + goto RESET_START; + } + } else { + g_fgIsBTExist = FALSE; + DBGLOG(INIT, ERROR, "[RST] %s: do not get %s\n", __func__, + bt_func_name); + goto RESET_START; + + } + +RESET_START: + + /* checkResetState(); // for debug */ + schedule_work(&remove_work); + DBGLOG(INIT, STATE, "[RST] creat remove_work\n"); +} +#endif + +#ifdef _HIF_PCIE +VOID glResetTrigger(P_ADAPTER_T prAdapter) +{ + DBGLOG(HAL, ERROR, "pcie does not support trigger core dump yet !!\n"); +} +#endif + +#ifdef _HIF_SDIO +/*----------------------------------------------------------------------------*/ +/*! +* \brief . +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void resetInit(void) +{ + DBGLOG(INIT, STATE, "[RST] resetInit start\n"); + + g_fgIsCoreDumpStart = FALSE; + g_fgIsCoreDumpEnd = FALSE; + g_fgIsCDEndTimeout = FALSE; + g_fgIsNotifyWlanRemove = FALSE; + g_fgIsNotifyBTRemoveEnd = FALSE; + + INIT_WORK(&remove_work, removeWlanSelf); + INIT_WORK(&(rst_data.rst_work), probeWlanSelf); + + init_waitqueue_head(&wait_core_dump_start); + /* init_waitqueue_head(&wait_core_dump_end); */ + init_wait_CD_start_timer(); + init_wait_CD_end_timer(); + + DBGLOG(INIT, STATE, "[RST] resetInit end\n"); + +} +static void RSTClearResource(void) +{ + DBGLOG(INIT, STATE, "[RST] resetClear start\n"); + + del_timer_sync(&wait_CD_start_timer); + del_timer_sync(&wait_CD_end_timer); + + /* cancel_work_sync(&rst_data.rst_work); */ + cancel_work_sync(&remove_work); + + gl_sdio_fail = FALSE; + DBGLOG(INIT, STATE, "[RST] resetClear end\n"); +} + +static void RSTClearState(void) +{ + DBGLOG(INIT, STATE, "[RST] RSTClearState\n"); + g_fgIsWifiTrig = FALSE; + g_fgIsBTTrig = FALSE; + g_fgIsNotifyWlanRemove = FALSE; +} + +void removeWlanSelf(struct work_struct *work) +{ + int bet = 0; + typedef int (*p_bt_fun_type) (void); + p_bt_fun_type bt_func; + /* int btmtk_sdio_notify_wlan_remove_end(void) */ + char *bt_func_name = "btmtk_sdio_notify_wlan_remove_end"; + + DBGLOG(INIT, STATE, "[RST] check entry_conut = %d\n", + rst_data.entry_conut); + + while (rst_data.entry_conut != 0) + kalMsleep(100); + + DBGLOG(INIT, STATE, "[RST] start mtk_sdio_remove\n"); +#if MTK_WCN_HIF_SDIO + bet = mtk_sdio_remove(); +#else + mtk_sdio_remove(rst_data.func); +#endif + DBGLOG(INIT, STATE, "[RST] mtk_sdio_remove end\n"); + + DBGLOG(INIT, STATE, "[RST] RSTP2pDestroyWirelessDevice start\n"); + RSTP2pDestroyWirelessDevice(); + DBGLOG(INIT, STATE, "[RST] RSTP2pDestroyWirelessDevice end\n"); + + /* notify bt wifi remove end */ + bt_func = (p_bt_fun_type) kallsyms_lookup_name(bt_func_name); + if (bt_func) { + + DBGLOG(INIT, STATE, "[RST] notify bt remove...\n"); + bet = bt_func(); + if (bet) { + g_fgIsBTExist = FALSE; + DBGLOG(INIT, ERROR, "[RST] notify bt fail\n"); + notify_wlan_toggle_rst_end(0); + } else { + g_fgIsNotifyBTRemoveEnd = TRUE; + DBGLOG(INIT, STATE, "[RST] notify bt remove end\n"); + start_wait_CD_end_timer(); + } + } else { + g_fgIsBTExist = FALSE; + DBGLOG(INIT, ERROR, "[RST] do not get %s\n", + bt_func_name); + notify_wlan_toggle_rst_end(0); + } + +} +void probeWlanSelf(struct work_struct *work) +{ + INT_32 i4Status = 0; + + DBGLOG(INIT, INFO, "[RST] g_fgIsBTExist=%d\n", g_fgIsBTExist); + DBGLOG(INIT, INFO, "[RST] g_fgIsCDEndTimeout=%d\n", + g_fgIsCDEndTimeout); + DBGLOG(INIT, INFO, "[RST] g_fgIsNotifyBTRemoveEnd=%d\n", + g_fgIsNotifyBTRemoveEnd); + + while (g_fgIsNotifyBTRemoveEnd == FALSE && g_fgIsBTExist == TRUE) + kalMsleep(10); + + DBGLOG(INIT, STATE, "[RST] probeWlanSelf start\n"); + + if (g_fgIsBTExist == FALSE || g_fgIsCDEndTimeout == TRUE) { + + DBGLOG(INIT, WARN, "[RST] sdio_claim_host\n"); + sdio_claim_host(rst_data.func); + + i4Status = pmu_toggle(&rst_data); + if (i4Status) { + DBGLOG(INIT, WARN, + "[RST] pmu_toggle fail num=%d!\n" + , i4Status); + return; + } + kalMsleep(500); + + DBGLOG(INIT, WARN, "[RST] sdio_reset_comm\n"); + i4Status = sdio_reset_comm(rst_data.func->card); + if (i4Status) + DBGLOG(INIT, ERROR, + "[RST] sdio_reset_comm, err=%d\n", i4Status); + kalMsleep(1000); + + sdio_release_host(rst_data.func); + DBGLOG(INIT, WARN, "[RST] sdio_release_host\n"); + } + + RSTClearResource(); + + DBGLOG(INIT, STATE, "[RST] mtk_sdio_probe start\n"); +#if MTK_WCN_HIF_SDIO + i4Status = mtk_sdio_probe(rst_data.func, &mtk_sdio_ids[1]); +#else + i4Status = mtk_sdio_probe(rst_data.func, &mtk_sdio_ids[1]); +#endif + if (i4Status) { + DBGLOG(INIT, ERROR, "[RST] mtk_sdio_probe fail num=%d!\n" + , i4Status); + } + + + RSTClearState(); + + DBGLOG(INIT, STATE, "[RST] resetWlanSelf end\n"); +} +void init_wait_CD_start_timer(void) +{ + DBGLOG(INIT, INFO, "[RST] init CD start timer\n"); + init_timer(&wait_CD_start_timer); + wait_CD_start_timer.function = wait_CD_start_timeout; +} + +void start_wait_CD_start_timer(void) +{ + DBGLOG(INIT, LOUD, "[RST] create CD start timer\n"); + + wait_CD_start_timer.expires = jiffies + (WAIT_CD_STAR_TIME * HZ); + wait_CD_start_timer.data = ((unsigned long) 0); + add_timer(&wait_CD_start_timer); +} + +void wait_CD_start_timeout(unsigned long data) +{ + DBGLOG(INIT, ERROR, "[RST] timeout=%d\n", WAIT_CD_STAR_TIME); + DBGLOG(INIT, ERROR, "[RST] g_fgIsCoreDumpStart = %d\n", + g_fgIsCoreDumpStart); + DBGLOG(INIT, ERROR, "[RST] wake up glResetTrigger\n"); + wake_up(&wait_core_dump_start); + set_core_dump_start(TRUE); + g_fgIsBTExist = FALSE; +} + +void init_wait_CD_end_timer(void) +{ + DBGLOG(INIT, INFO, "[RST] init CD end timer\n"); + init_timer(&wait_CD_end_timer); + wait_CD_end_timer.function = wait_CD_end_timeout; +} + +void start_wait_CD_end_timer(void) +{ + DBGLOG(INIT, STATE, "[RST] create CD end timer\n"); + wait_CD_end_timer.expires = jiffies + (WAIT_CD_END_TIME * HZ); + wait_CD_end_timer.data = ((unsigned long) 0); + add_timer(&wait_CD_end_timer); +} +void wait_CD_end_timeout(unsigned long data) +{ + DBGLOG(INIT, ERROR, "[RST] timeout=%ld\n", WAIT_CD_END_TIME); + DBGLOG(INIT, ERROR, "[RST] g_fgIsCoreDumpEnd = %d\n", + g_fgIsCoreDumpEnd); + + if (g_fgIsCoreDumpEnd == FALSE) { + g_fgIsCDEndTimeout = TRUE; + g_fgIsCoreDumpEnd = TRUE; + schedule_work(&rst_data.rst_work); + } +} + +BOOLEAN checkResetState(void) +{ + return (g_fgIsWifiTrig | g_fgIsBTTrig); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief . +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID set_core_dump_start(BOOLEAN fgVal) +{ + DBGLOG(INIT, ERROR, "[RST] set_core_dump_start = %d\n", fgVal); + g_fgIsCoreDumpStart = fgVal; +} +INT_32 bt_notify_wlan_remove(INT_32 reserved) +{ + if (g_fgIsNotifyWlanRemove) { + DBGLOG(INIT, ERROR, "[RST] g_fgIsNotifyWlanRemove=%d\n", + g_fgIsNotifyWlanRemove); + return NOTIFY_REPEAT; + } + g_fgIsNotifyWlanRemove = TRUE; + DBGLOG(INIT, ERROR, "[RST] bt notify cd start...\n"); + if (g_fgIsWifiTrig) { + DBGLOG(INIT, ERROR, "[RST] wake up glResetTrigger\n"); + set_core_dump_start(TRUE); + wake_up(&wait_core_dump_start); + } else { + g_fgIsBTTrig = TRUE; + g_fgIsBTExist = TRUE; + resetInit(); + set_core_dump_start(TRUE); + schedule_work(&remove_work); + DBGLOG(INIT, ERROR, "[RST] creat remove_work\n"); + } + DBGLOG(INIT, ERROR, "[RST] bt notify cd start end\n"); + return NOTIFY_SUCCESS; + +} + +INT_32 notify_wlan_remove_start(INT_32 reserved) +{ + return bt_notify_wlan_remove(reserved); +} +EXPORT_SYMBOL(notify_wlan_remove_start); +/*----------------------------------------------------------------------------*/ +/*! +* \brief . +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID set_core_dump_end(BOOLEAN fgVal) +{ + DBGLOG(INIT, INFO, "[RST] g_fgIsCoreDumpEnd = %d\n", fgVal); + g_fgIsCoreDumpEnd = fgVal; +} + +INT_32 notify_wlan_toggle_rst_end(INT_32 reserved) +{ + /* create work queue */ + DBGLOG(INIT, STATE, "[RST] bt notify CD end\n"); + set_core_dump_end(TRUE); + schedule_work(&rst_data.rst_work); + DBGLOG(INIT, STATE, "[RST] create probe work\n"); + + /* cencel timer */ + del_timer_sync(&wait_CD_end_timer); + + return NOTIFY_SUCCESS; +} +EXPORT_SYMBOL(notify_wlan_toggle_rst_end); + +INT_32 pmu_toggle(struct rst_struct *data) +{ + UINT_32 pmu_en_delay = MT76x8_PMU_EN_DEFAULT_DELAY; + int pmu_en; + struct device *prDev; + INT_32 i4Status = 0; + + typedef void (*p_sdio_fun_type) (int); + p_sdio_fun_type sdio_func; + /* int btmtk_sdio_notify_wlan_remove_end(void) */ + char *sdio_func_name = "sdio_set_card_clkpd"; + + ASSERT(data); + + /* stop mtk sdio clk */ + sdio_func = (p_sdio_fun_type) kallsyms_lookup_name(sdio_func_name); + if (sdio_func) { + sdio_func(0); + DBGLOG(INIT, STATE, "[RST] stop sdio clk\n"); + } else { + DBGLOG(INIT, ERROR, "[RST] do not get %s\n", sdio_func); + } + + DBGLOG(INIT, STATE, "[RST] get device\n"); + prDev = mmc_dev(data->func->card->host); + if (!prDev) { + DBGLOG(INIT, ERROR, "unable to get struct dev for wlan\n"); + return WLAN_STATUS_FAILURE; + } + + DBGLOG(INIT, STATE, "[RST] pmu reset\n"); + pmu_en = of_get_named_gpio(prDev->of_node, MT76x8_PMU_EN_PIN_NAME, 0); + + if (gpio_is_valid(pmu_en)) { + i4Status = of_property_read_u32(prDev->of_node, + MT76x8_PMU_EN_DELAY_NAME, + &pmu_en_delay); + if (i4Status) { + DBGLOG(INIT, ERROR, + "[RST] undefined pmu_en delay, use default %ums\n", + i4Status); + } + gpio_direction_output(pmu_en, 0); + mdelay(pmu_en_delay); + gpio_direction_output(pmu_en, 1); + } else { + DBGLOG(INIT, ERROR, "[RST] invalid gpio %s\n", + MT76x8_PMU_EN_PIN_NAME); + return WLAN_STATUS_FAILURE; + } + + return WLAN_STATUS_SUCCESS; +} + +void RSTP2pDestroyWirelessDevice(void) +{ + int i = 0; + + for (i = 1; i < KAL_P2P_NUM; i++) { + + if (gprP2pRoleWdev[i] == NULL) + continue; + + DBGLOG(INIT, STATE, + "glP2pDestroyWirelessDevice[%d] (0x%p)\n", + i, gprP2pRoleWdev[i]->wiphy); + set_wiphy_dev(gprP2pRoleWdev[i]->wiphy, NULL); + wiphy_unregister(gprP2pRoleWdev[i]->wiphy); + wiphy_free(gprP2pRoleWdev[i]->wiphy); + kfree(gprP2pRoleWdev[i]); + + gprP2pRoleWdev[i] = NULL; + } + +} + + +#else +BOOLEAN checkResetState(void) +{ + return FALSE; +} +#endif +#endif /* CFG_CHIP_RESET_SUPPORT */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is called for checking if connectivity chip is resetting + * + * @param None + * + * @retval TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalIsResetting(VOID) +{ + return FALSE; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_vendor.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_vendor.c new file mode 100644 index 0000000000000..423c2ddc65d21 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_vendor.c @@ -0,0 +1,1378 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** gl_vendor.c +** +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "debug.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "precomp.h" +#include +#include +#include +#include "gl_cfg80211.h" +#include "gl_vendor.h" +#include "wlan_oid.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* These values must sync from Wifi HAL + * /hardware/libhardware_legacy/include/hardware_legacy/wifi_hal.h + */ +/* Basic infrastructure mode */ +#define WIFI_FEATURE_INFRA (0x0001) +/* Support for 5 GHz Band */ +#define WIFI_FEATURE_INFRA_5G (0x0002) +/* Support for GAS/ANQP */ +#define WIFI_FEATURE_HOTSPOT (0x0004) +/* Wifi-Direct */ +#define WIFI_FEATURE_P2P (0x0008) +/* Soft AP */ +#define WIFI_FEATURE_SOFT_AP (0x0010) +/* Google-Scan APIs */ +#define WIFI_FEATURE_GSCAN (0x0020) +/* Neighbor Awareness Networking */ +#define WIFI_FEATURE_NAN (0x0040) +/* Device-to-device RTT */ +#define WIFI_FEATURE_D2D_RTT (0x0080) +/* Device-to-AP RTT */ +#define WIFI_FEATURE_D2AP_RTT (0x0100) +/* Batched Scan (legacy) */ +#define WIFI_FEATURE_BATCH_SCAN (0x0200) +/* Preferred network offload */ +#define WIFI_FEATURE_PNO (0x0400) +/* Support for two STAs */ +#define WIFI_FEATURE_ADDITIONAL_STA (0x0800) +/* Tunnel directed link setup */ +#define WIFI_FEATURE_TDLS (0x1000) +/* Support for TDLS off channel */ +#define WIFI_FEATURE_TDLS_OFFCHANNEL (0x2000) +/* Enhanced power reporting */ +#define WIFI_FEATURE_EPR (0x4000) +/* Support for AP STA Concurrency */ +#define WIFI_FEATURE_AP_STA (0x8000) +/* Link layer stats collection */ +#define WIFI_FEATURE_LINK_LAYER_STATS (0x10000) +/* WiFi Logger */ +#define WIFI_FEATURE_LOGGER (0x20000) +/* WiFi PNO enhanced */ +#define WIFI_FEATURE_HAL_EPNO (0x40000) +/* RSSI Monitor */ +#define WIFI_FEATURE_RSSI_MONITOR (0x80000) +/* WiFi mkeep_alive */ +#define WIFI_FEATURE_MKEEP_ALIVE (0x100000) +/* ND offload configure */ +#define WIFI_FEATURE_CONFIG_NDO (0x200000) +/* Capture Tx transmit power levels */ +#define WIFI_FEATURE_TX_TRANSMIT_POWER (0x400000) +/* Enable/Disable firmware roaming */ +#define WIFI_FEATURE_CONTROL_ROAMING (0x800000) +/* Support Probe IE white listing */ +#define WIFI_FEATURE_IE_WHITELIST (0x1000000) +/* Support MAC & Probe Sequence Number randomization */ +#define WIFI_FEATURE_SCAN_RAND (0x2000000) +/* Support Tx Power Limit setting */ +#define WIFI_FEATURE_SET_TX_POWER_LIMIT (0x4000000) +/* Support Using Body/Head Proximity for SAR */ +#define WIFI_FEATURE_USE_BODY_HEAD_SAR (0x8000000) +/* note: WIFI_FEATURE_GSCAN be enabled just for ACTS test item: scanner */ +#define WIFI_HAL_FEATURE_SET ((WIFI_FEATURE_P2P) |\ + (WIFI_FEATURE_SOFT_AP) |\ + (WIFI_FEATURE_TDLS)) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +P_SW_RFB_T g_arGscnResultsTempBuffer[MAX_BUFFERED_GSCN_RESULTS]; +UINT_8 g_GscanResultsTempBufferIndex; +UINT_8 g_arGscanResultsIndicateNumber[MAX_BUFFERED_GSCN_RESULTS] = { 0, 0, 0, 0, 0 }; + +UINT_8 g_GetResultsBufferedCnt; +UINT_8 g_GetResultsCmdCnt; + +/******************************************************************************* +* 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 KERNEL_VERSION(3, 17, 0) <= CFG80211_VERSION_CODE + +int mtk_cfg80211_vendor_get_supported_feature_set(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + u32 u4FeatureSet = WIFI_HAL_FEATURE_SET; + P_GLUE_INFO_T prGlueInfo = NULL; + P_REG_INFO_T prRegInfo = NULL; + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(wdev); + + if (wdev == gprWdev) /*wlan0*/ + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + else + prGlueInfo = *(P_GLUE_INFO_T *) wiphy_priv(wiphy); + + if (!prGlueInfo) + return -EFAULT; + prRegInfo = &prGlueInfo->rRegInfo; + if (!prRegInfo) + return -EFAULT; + if (prRegInfo->ucSupport5GBand) + u4FeatureSet |= WIFI_FEATURE_INFRA_5G; + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u4FeatureSet)); + if (!skb) { + DBGLOG(REQ, ERROR, "Allocate skb failed\n"); + return -ENOMEM; + } + if (unlikely( + nla_put_nohdr(skb, sizeof(u4FeatureSet), &u4FeatureSet) < 0)) { + DBGLOG(REQ, ERROR, "nla_put_nohdr failed\n"); + goto nla_put_failure; + } + DBGLOG(REQ, INFO, "supported feature set=0x%x\n", u4FeatureSet); + return cfg80211_vendor_cmd_reply(skb); +nla_put_failure: + kfree_skb(skb); + return -EFAULT; +} + +int mtk_cfg80211_vendor_set_tx_power_scenario(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + return -EOPNOTSUPP; +} + +int mtk_cfg80211_vendor_get_version(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ +#define STR_HELPER(x) #x +#define STRR(x) STR_HELPER(x) +#define DriverVersionStr STRR(NIC_DRIVER_MAJOR_VERSION) "_"\ + STRR(NIC_DRIVER_MINOR_VERSION) "_"\ + STRR(NIC_DRIVER_SERIAL_VERSION) "-" + + P_GLUE_INFO_T prGlueInfo = NULL; + struct sk_buff *skb = NULL; + struct nlattr *attrlist = NULL; + char aucVersionBuf[256]; + char aucBuf[32]; + char aucDate[32]; + uint16_t u2CopySize = 0; + uint16_t u2Len = 0; + + ASSERT(wiphy); + ASSERT(wdev); + + if ((data == NULL) || !data_len) + return -ENOMEM; + + kalMemZero(aucVersionBuf, 256); + attrlist = (struct nlattr *)((uint8_t *) data); + if (attrlist->nla_type == LOGGER_ATTRIBUTE_DRIVER_VER) { + + char aucDriverVersionStr[] = DriverVersionStr DRIVER_BUILD_DATE; + + u2Len = kalStrLen(aucDriverVersionStr); + DBGLOG(REQ, INFO, "Get driver version len: %d\n", u2Len); + u2CopySize = (u2Len >= 256) ? 255 : u2Len; + if (u2CopySize > 0) + kalMemCopy(aucVersionBuf, &aucDriverVersionStr[0], + u2CopySize); + } else if (attrlist->nla_type == LOGGER_ATTRIBUTE_FW_VER) { + P_WIFI_VER_INFO_T prVerInfo = NULL; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + prVerInfo = &(prGlueInfo->prAdapter->rVerInfo); + kalStrnCpy(aucBuf, prVerInfo->aucFwBranchInfo, 4); + aucBuf[4] = '\0'; + kalStrnCpy(aucDate, prVerInfo->aucFwDateCode, 16); + aucDate[16] = '\0'; + + snprintf(aucVersionBuf, 256, "%s-%u.%u.%u[DEC] (%s)", + aucBuf, (prVerInfo->u2FwOwnVersion >> 8), + (prVerInfo->u2FwOwnVersion & BITS(0, 7)), + prVerInfo->ucFwBuildNumber, aucDate); + u2CopySize = strlen(aucVersionBuf); + } + + if (u2CopySize <= 0) + return -EFAULT; + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, u2CopySize); + if (!skb) { + DBGLOG(REQ, ERROR, "Allocate skb failed\n"); + return -ENOMEM; + } + + DBGLOG(REQ, INFO, "Get version(%d)=[%s]\n", u2CopySize, aucVersionBuf); + if (unlikely(nla_put_nohdr(skb, u2CopySize, &aucVersionBuf[0]) < 0)) + goto nla_put_failure; + + return cfg80211_vendor_cmd_reply(skb); + +nla_put_failure: + kfree_skb(skb); + return -EFAULT; +} + +int mtk_cfg80211_vendor_set_scan_mac_oui(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + ASSERT(wiphy); + ASSERT(wdev); + DBGLOG(REQ, INFO, "scan mac oui not supported\n"); + return 0; +} + +int mtk_cfg80211_NLA_PUT(struct sk_buff *skb, int attrtype, int attrlen, const void *data) +{ + if (unlikely(nla_put(skb, attrtype, attrlen, data) < 0)) + return 0; + return 1; +} + +int mtk_cfg80211_nla_put_type(struct sk_buff *skb, ENUM_NLA_PUT_DATE_TYPE type, int attrtype, const void *value) +{ + u8 u8data = 0; + u16 u16data = 0; + u32 u32data = 0; + u64 u64data = 0; + + switch (type) { + case NLA_PUT_DATE_U8: + u8data = *(u8 *)value; + return mtk_cfg80211_NLA_PUT(skb, attrtype, sizeof(u8), &u8data); + case NLA_PUT_DATE_U16: + u16data = *(u16 *)value; + return mtk_cfg80211_NLA_PUT(skb, attrtype, sizeof(u16), &u16data); + case NLA_PUT_DATE_U32: + u32data = *(u32 *)value; + return mtk_cfg80211_NLA_PUT(skb, attrtype, sizeof(u32), &u32data); + case NLA_PUT_DATE_U64: + u64data = *(u64 *)value; + return mtk_cfg80211_NLA_PUT(skb, attrtype, sizeof(u64), &u64data); + default: + break; + } + + return 0; +} + +#if 0 +int mtk_cfg80211_vendor_get_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Status = -EINVAL; + PARAM_WIFI_GSCAN_CAPABILITIES_STRUCT_T rGscanCapabilities; + struct sk_buff *skb; + + DBGLOG(REQ, TRACE, "for vendor command\r\n"); + + ASSERT(wiphy); + ASSERT(wdev); + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(rGscanCapabilities)); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed:%x\n", __func__, i4Status); + return -ENOMEM; + } + + kalMemZero(&rGscanCapabilities, sizeof(rGscanCapabilities)); + + /*rStatus = kalIoctl(prGlueInfo, + * wlanoidQueryStatistics, + * &rGscanCapabilities, + * sizeof(rGscanCapabilities), + * TRUE, + * TRUE, + * TRUE, + * FALSE, + * &u4BufLen); + */ + rGscanCapabilities.max_scan_cache_size = PSCAN_MAX_SCAN_CACHE_SIZE; + rGscanCapabilities.max_scan_buckets = GSCAN_MAX_BUCKETS; + rGscanCapabilities.max_ap_cache_per_scan = PSCAN_MAX_AP_CACHE_PER_SCAN; + rGscanCapabilities.max_rssi_sample_size = 10; + rGscanCapabilities.max_scan_reporting_threshold = GSCAN_MAX_REPORT_THRESHOLD; + rGscanCapabilities.max_hotlist_aps = MAX_HOTLIST_APS; + rGscanCapabilities.max_significant_wifi_change_aps = MAX_SIGNIFICANT_CHANGE_APS; + rGscanCapabilities.max_bssid_history_entries = PSCAN_MAX_AP_CACHE_PER_SCAN * PSCAN_MAX_SCAN_CACHE_SIZE; + + /* NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_INVALID, 0); */ + /* NLA_PUT_U32(skb, NL80211_ATTR_VENDOR_ID, GOOGLE_OUI); */ + /* NLA_PUT_U32(skb, NL80211_ATTR_VENDOR_SUBCMD, GSCAN_SUBCMD_GET_CAPABILITIES); */ + NLA_PUT(skb, NL80211_ATTR_VENDOR_CAPABILITIES, sizeof(rGscanCapabilities), &rGscanCapabilities); + + i4Status = cfg80211_vendor_cmd_reply(skb); + + return i4Status; +} + +int mtk_cfg80211_vendor_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) +{ + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + P_GLUE_INFO_T prGlueInfo = NULL; + /* CMD_GSCN_REQ_T rCmdGscnParam; */ + + /* INT_32 i4Status = -EINVAL; */ + P_PARAM_WIFI_GSCAN_CMD_PARAMS prWifiScanCmd; + struct nlattr *attr[GSCAN_ATTRIBUTE_REPORT_EVENTS + 1]; + struct nlattr *pbucket, *pchannel; + UINT_32 len_basic, len_bucket, len_channel; + int i, j, k; + static struct nla_policy policy[GSCAN_ATTRIBUTE_REPORT_EVENTS + 1] = { + [GSCAN_ATTRIBUTE_NUM_BUCKETS] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BASE_PERIOD] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BUCKETS_BAND] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BUCKET_ID] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BUCKET_PERIOD] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BUCKET_CHANNELS] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_REPORT_EVENTS] = {.type = NLA_U32}, + }; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + + prWifiScanCmd = (P_PARAM_WIFI_GSCAN_CMD_PARAMS) kalMemAlloc(sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS), VIR_MEM_TYPE); + if (!prWifiScanCmd) { + DBGLOG(REQ, ERROR, "Can not alloc memory for PARAM_WIFI_GSCAN_CMD_PARAMS\n"); + return -ENOMEM; + } + + DBGLOG(REQ, INFO, "%s for vendor command: data_len=%d\r\n", __func__, data_len); + kalMemZero(prWifiScanCmd, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); + kalMemZero(attr, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_REPORT_EVENTS + 1)); + + nla_parse_nested(attr, GSCAN_ATTRIBUTE_REPORT_EVENTS, (struct nlattr *)(data - NLA_HDRLEN), policy); + len_basic = 0; + for (k = GSCAN_ATTRIBUTE_NUM_BUCKETS; k <= GSCAN_ATTRIBUTE_REPORT_EVENTS; k++) { + if (attr[k]) { + switch (k) { + case GSCAN_ATTRIBUTE_BASE_PERIOD: + prWifiScanCmd->base_period = nla_get_u32(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_NUM_BUCKETS: + prWifiScanCmd->num_buckets = nla_get_u32(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + DBGLOG(REQ, TRACE, "attr=0x%x, num_buckets=%d nla_len=%d\r\n", + *(UINT_32 *) attr[k], prWifiScanCmd->num_buckets, attr[k]->nla_len); + break; + } + } + } + pbucket = (struct nlattr *)((UINT_8 *) data + len_basic); + DBGLOG(REQ, TRACE, "+++basic attribute size=%d pbucket=%p\r\n", len_basic, pbucket); + + for (i = 0; i < prWifiScanCmd->num_buckets; i++) { + nla_parse_nested(attr, GSCAN_ATTRIBUTE_REPORT_EVENTS, (struct nlattr *)pbucket, policy); + len_bucket = 0; + for (k = GSCAN_ATTRIBUTE_NUM_BUCKETS; k <= GSCAN_ATTRIBUTE_REPORT_EVENTS; k++) { + if (attr[k]) { + switch (k) { + case GSCAN_ATTRIBUTE_BUCKETS_BAND: + prWifiScanCmd->buckets[i].band = nla_get_u32(attr[k]); + len_bucket += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_BUCKET_ID: + prWifiScanCmd->buckets[i].bucket = nla_get_u32(attr[k]); + len_bucket += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_BUCKET_PERIOD: + prWifiScanCmd->buckets[i].period = nla_get_u32(attr[k]); + len_bucket += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_REPORT_EVENTS: + prWifiScanCmd->buckets[i].report_events = nla_get_u32(attr[k]); + len_bucket += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS: + prWifiScanCmd->buckets[i].num_channels = nla_get_u32(attr[k]); + len_bucket += NLA_ALIGN(attr[k]->nla_len); + DBGLOG(REQ, TRACE, + "bucket%d: attr=0x%x, num_channels=%d nla_len=%d\r\n", + i, *(UINT_32 *) attr[k], nla_get_u32(attr[k]), attr[k]->nla_len); + break; + } + } + } + pbucket = (struct nlattr *)((UINT_8 *) pbucket + NLA_HDRLEN); + /* request.attr_start(i) as nested attribute */ + DBGLOG(REQ, TRACE, "+++pure bucket size=%d pbucket=%p\r\n", len_bucket, pbucket); + pbucket = (struct nlattr *)((UINT_8 *) pbucket + len_bucket); + /* pure bucket payload, not include channels */ + + /*don't need to use nla_parse_nested to parse channels */ + /* the header of channel in bucket i */ + pchannel = (struct nlattr *)((UINT_8 *) pbucket + NLA_HDRLEN); + for (j = 0; j < prWifiScanCmd->buckets[i].num_channels; j++) { + prWifiScanCmd->buckets[i].channels[j].channel = nla_get_u32(pchannel); + len_channel = NLA_ALIGN(pchannel->nla_len); + DBGLOG(REQ, TRACE, + "attr=0x%x, channel=%d\r\n", *(UINT_32 *) pchannel, nla_get_u32(pchannel)); + + pchannel = (struct nlattr *)((UINT_8 *) pchannel + len_channel); + } + pbucket = pchannel; + } + + DBGLOG(REQ, TRACE, "base_period=%d, num_buckets=%d, bucket0: %d %d %d %d", + prWifiScanCmd->base_period, prWifiScanCmd->num_buckets, + prWifiScanCmd->buckets[0].bucket, prWifiScanCmd->buckets[0].period, + prWifiScanCmd->buckets[0].band, prWifiScanCmd->buckets[0].report_events); + + DBGLOG(REQ, TRACE, "num_channels=%d, channel0=%d, channel1=%d; num_channels=%d, channel0=%d, channel1=%d", + prWifiScanCmd->buckets[0].num_channels, + prWifiScanCmd->buckets[0].channels[0].channel, prWifiScanCmd->buckets[0].channels[1].channel, + prWifiScanCmd->buckets[1].num_channels, + prWifiScanCmd->buckets[1].channels[0].channel, prWifiScanCmd->buckets[1].channels[1].channel); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetGSCNAParam, + prWifiScanCmd, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS), FALSE, FALSE, TRUE, &u4BufLen); + + return 0; + +nla_put_failure: + return -1; +} + +int mtk_cfg80211_vendor_set_scan_config(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) +{ + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + P_GLUE_INFO_T prGlueInfo = NULL; + + PARAM_WIFI_GSCAN_CMD_PARAMS rWifiScanCmd; + struct nlattr *attr[GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE + 1]; + int i, k; + static struct nla_policy policy[GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE + 1] = { + [GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_REPORT_THRESHOLD] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE] = {.type = NLA_U32}, + }; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + + DBGLOG(SCN, INFO, "%s for vendor command: data_len=%d \r\n", __func__, data_len); + for (i = 0; i < 2; i++) + DBGLOG(SCN, INFO, "0x%x 0x%x 0x%x 0x%x \r\n", *((UINT_32 *) data + i * 4), + *((UINT_32 *) data + i * 4 + 1), *((UINT_32 *) data + i * 4 + 2), + *((UINT_32 *) data + i * 4 + 3)); + kalMemZero(&rWifiScanCmd, sizeof(rWifiScanCmd)); + kalMemZero(attr, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE + 1)); + + nla_parse_nested(attr, GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, (struct nlattr *)(data - NLA_HDRLEN), policy); + for (k = GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN; k <= GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE; k++) { + if (attr[k]) { + switch (k) { + case GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN: + rWifiScanCmd.max_ap_per_scan = nla_get_u32(attr[k]); + break; + case GSCAN_ATTRIBUTE_REPORT_THRESHOLD: + rWifiScanCmd.report_threshold = nla_get_u32(attr[k]); + break; + case GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE: + rWifiScanCmd.num_scans = nla_get_u32(attr[k]); + break; + } + } + } + DBGLOG(REQ, TRACE, "attr=0x%x, attr2=0x%x", *(UINT_32 *)attr[GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN], + *(UINT_32 *)attr[GSCAN_ATTRIBUTE_REPORT_THRESHOLD]); + + DBGLOG(REQ, TRACE, "max_ap_per_scan=%d, report_threshold=%d num_scans=%d\r\n", + rWifiScanCmd.max_ap_per_scan, rWifiScanCmd.report_threshold, rWifiScanCmd.num_scans); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetGSCNAConfig, + &rWifiScanCmd, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS), FALSE, FALSE, TRUE, &u4BufLen); + + return 0; + +nla_put_failure: + return -1; +} + +int mtk_cfg80211_vendor_set_significant_change(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + PARAM_WIFI_SIGNIFICANT_CHANGE rWifiChangeCmd; + UINT_8 flush = 0; + struct nlattr *attr[GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1]; + struct nlattr *paplist; + int i, k; + UINT_32 len_basic, len_aplist; + static struct nla_policy policy[GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1] = { + [GSCAN_ATTRIBUTE_BSSID] = {.type = NLA_UNSPEC}, + [GSCAN_ATTRIBUTE_RSSI_LOW] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_RSSI_HIGH] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE] = {.type = NLA_U16}, + [GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE] = {.type = NLA_U16}, + [GSCAN_ATTRIBUTE_MIN_BREACHING] = {.type = NLA_U16}, + [GSCAN_ATTRIBUTE_NUM_AP] = {.type = NLA_U16}, + [GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH] = {.type = NLA_U8}, + }; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + DBGLOG(REQ, INFO, "%s for vendor command: data_len=%d\r\n", __func__, data_len); + for (i = 0; i < 6; i++) + DBGLOG(REQ, LOUD, "0x%x 0x%x 0x%x 0x%x\r\n", + *((UINT_32 *) data + i * 4), *((UINT_32 *) data + i * 4 + 1), + *((UINT_32 *) data + i * 4 + 2), *((UINT_32 *) data + i * 4 + 3)); + kalMemZero(&rWifiChangeCmd, sizeof(rWifiChangeCmd)); + kalMemZero(attr, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1)); + + nla_parse_nested(attr, GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, (struct nlattr *)(data - NLA_HDRLEN), policy); + len_basic = 0; + for (k = GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE; k <= GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH; k++) { + if (attr[k]) { + switch (k) { + case GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE: + rWifiChangeCmd.rssi_sample_size = nla_get_u16(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE: + rWifiChangeCmd.lost_ap_sample_size = nla_get_u16(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_MIN_BREACHING: + rWifiChangeCmd.min_breaching = nla_get_u16(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_NUM_AP: + rWifiChangeCmd.num_ap = nla_get_u16(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + DBGLOG(REQ, TRACE, "attr=0x%x, num_ap=%d nla_len=%d\r\n", + *(UINT_32 *) attr[k], rWifiChangeCmd.num_ap, attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH: + flush = nla_get_u8(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + } + } + } + paplist = (struct nlattr *)((UINT_8 *) data + len_basic); + DBGLOG(REQ, TRACE, "+++basic attribute size=%d flush=%d\r\n", len_basic, flush); + + if (paplist->nla_type == GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS) + paplist = (struct nlattr *)((UINT_8 *) paplist + NLA_HDRLEN); + + for (i = 0; i < rWifiChangeCmd.num_ap; i++) { + nla_parse_nested(attr, GSCAN_ATTRIBUTE_RSSI_HIGH, (struct nlattr *)paplist, policy); + paplist = (struct nlattr *)((UINT_8 *) paplist + NLA_HDRLEN); + /* request.attr_start(i) as nested attribute */ + len_aplist = 0; + for (k = GSCAN_ATTRIBUTE_BSSID; k <= GSCAN_ATTRIBUTE_RSSI_HIGH; k++) { + if (attr[k]) { + switch (k) { + case GSCAN_ATTRIBUTE_BSSID: + kalMemCopy(rWifiChangeCmd.ap[i].bssid, nla_data(attr[k]), sizeof(mac_addr)); + len_aplist += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_RSSI_LOW: + rWifiChangeCmd.ap[i].low = nla_get_u32(attr[k]); + len_aplist += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_RSSI_HIGH: + rWifiChangeCmd.ap[i].high = nla_get_u32(attr[k]); + len_aplist += NLA_ALIGN(attr[k]->nla_len); + break; + } + } + } + if (((i + 1) % 4 == 0) || (i == rWifiChangeCmd.num_ap - 1)) + DBGLOG(REQ, TRACE, "ap[%d], len_aplist=%d\n", i, len_aplist); + else + DBGLOG(REQ, TRACE, "ap[%d], len_aplist=%d\t", i, len_aplist); + paplist = (struct nlattr *)((UINT_8 *) paplist + len_aplist); + } + + DBGLOG(REQ, TRACE, + "flush=%d, rssi_sample_size=%d lost_ap_sample_size=%d min_breaching=%d", + flush, rWifiChangeCmd.rssi_sample_size, rWifiChangeCmd.lost_ap_sample_size, + rWifiChangeCmd.min_breaching); + DBGLOG(REQ, TRACE, + "ap[0].channel=%d low=%d high=%d, ap[1].channel=%d low=%d high=%d", + rWifiChangeCmd.ap[0].channel, rWifiChangeCmd.ap[0].low, rWifiChangeCmd.ap[0].high, + rWifiChangeCmd.ap[1].channel, rWifiChangeCmd.ap[1].low, rWifiChangeCmd.ap[1].high); + return 0; + +nla_put_failure: + return -1; +} + +int mtk_cfg80211_vendor_set_hotlist(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + CMD_SET_PSCAN_ADD_HOTLIST_BSSID rCmdPscnAddHotlist; + + PARAM_WIFI_BSSID_HOTLIST rWifiHotlistCmd; + UINT_8 flush = 0; + struct nlattr *attr[GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1]; + struct nlattr *paplist; + int i, k; + UINT_32 len_basic, len_aplist; + static struct nla_policy policy[GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1] = { + [GSCAN_ATTRIBUTE_BSSID] = {.type = NLA_UNSPEC}, + [GSCAN_ATTRIBUTE_RSSI_LOW] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_RSSI_HIGH] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_NUM_AP] = {.type = NLA_U16}, + [GSCAN_ATTRIBUTE_HOTLIST_FLUSH] = {.type = NLA_U8}, + }; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + DBGLOG(REQ, INFO, "%s for vendor command: data_len=%d\r\n", __func__, data_len); + for (i = 0; i < 5; i++) + DBGLOG(REQ, LOUD, "0x%x 0x%x 0x%x 0x%x\r\n", + *((UINT_32 *) data + i * 4), *((UINT_32 *) data + i * 4 + 1), + *((UINT_32 *) data + i * 4 + 2), *((UINT_32 *) data + i * 4 + 3)); + kalMemZero(&rWifiHotlistCmd, sizeof(rWifiHotlistCmd)); + kalMemZero(attr, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1)); + + nla_parse_nested(attr, GSCAN_ATTRIBUTE_NUM_AP, (struct nlattr *)(data - NLA_HDRLEN), policy); + len_basic = 0; + for (k = GSCAN_ATTRIBUTE_HOTLIST_FLUSH; k <= GSCAN_ATTRIBUTE_NUM_AP; k++) { + if (attr[k]) { + switch (k) { + case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE: + rWifiHotlistCmd.lost_ap_sample_size = nla_get_u32(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_NUM_AP: + rWifiHotlistCmd.num_ap = nla_get_u16(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + DBGLOG(REQ, TRACE, "attr=0x%x, num_ap=%d nla_len=%d\r\n", + *(UINT_32 *) attr[k], rWifiHotlistCmd.num_ap, attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_HOTLIST_FLUSH: + flush = nla_get_u8(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + } + } + } + paplist = (struct nlattr *)((UINT_8 *) data + len_basic); + DBGLOG(REQ, TRACE, "+++basic attribute size=%d flush=%d\r\n", len_basic, flush); + + if (paplist->nla_type == GSCAN_ATTRIBUTE_HOTLIST_BSSIDS) + paplist = (struct nlattr *)((UINT_8 *) paplist + NLA_HDRLEN); + + for (i = 0; i < rWifiHotlistCmd.num_ap; i++) { + nla_parse_nested(attr, GSCAN_ATTRIBUTE_RSSI_HIGH, (struct nlattr *)paplist, policy); + paplist = (struct nlattr *)((UINT_8 *) paplist + NLA_HDRLEN); + /* request.attr_start(i) as nested attribute */ + len_aplist = 0; + for (k = GSCAN_ATTRIBUTE_BSSID; k <= GSCAN_ATTRIBUTE_RSSI_HIGH; k++) { + if (attr[k]) { + switch (k) { + case GSCAN_ATTRIBUTE_BSSID: + kalMemCopy(rWifiHotlistCmd.ap[i].bssid, nla_data(attr[k]), sizeof(mac_addr)); + len_aplist += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_RSSI_LOW: + rWifiHotlistCmd.ap[i].low = nla_get_u32(attr[k]); + len_aplist += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_RSSI_HIGH: + rWifiHotlistCmd.ap[i].high = nla_get_u32(attr[k]); + len_aplist += NLA_ALIGN(attr[k]->nla_len); + break; + } + } + } + if (((i + 1) % 4 == 0) || (i == rWifiHotlistCmd.num_ap - 1)) + DBGLOG(REQ, TRACE, "ap[%d], len_aplist=%d\n", i, len_aplist); + else + DBGLOG(REQ, TRACE, "ap[%d], len_aplist=%d\t", i, len_aplist); + paplist = (struct nlattr *)((UINT_8 *) paplist + len_aplist); + } + + DBGLOG(REQ, TRACE, + "flush=%d, lost_ap_sample_size=%d, Hotlist:ap[0].channel=%d low=%d high=%d, ap[1].channel=%d low=%d high=%d", + flush, rWifiHotlistCmd.lost_ap_sample_size, + rWifiHotlistCmd.ap[0].channel, rWifiHotlistCmd.ap[0].low, rWifiHotlistCmd.ap[0].high, + rWifiHotlistCmd.ap[1].channel, rWifiHotlistCmd.ap[1].low, rWifiHotlistCmd.ap[1].high); + + memcpy(&(rCmdPscnAddHotlist.aucMacAddr), &(rWifiHotlistCmd.ap[0].bssid), 6 * sizeof(UINT_8)); + rCmdPscnAddHotlist.ucFlags = (UINT_8) TRUE; + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + return 0; + +nla_put_failure: + return -1; +} + +int mtk_cfg80211_vendor_enable_scan(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) +{ + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_WIFI_GSCAN_ACTION_CMD_PARAMS rWifiScanActionCmd; + + struct nlattr *attr; + UINT_8 gGScanEn = 0; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + DBGLOG(REQ, INFO, "%s for vendor command: data_len=%d, data=0x%x 0x%x\r\n", + __func__, data_len, *((UINT_32 *) data), *((UINT_32 *) data + 1)); + + attr = (struct nlattr *)data; + if (attr->nla_type == GSCAN_ATTRIBUTE_ENABLE_FEATURE) + gGScanEn = nla_get_u32(attr); + DBGLOG(REQ, INFO, "gGScanEn=%d\r\n", gGScanEn); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + if (gGScanEn == TRUE) + rWifiScanActionCmd.ucPscanAct = ENABLE; + else + rWifiScanActionCmd.ucPscanAct = DISABLE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetGSCNAction, + &rWifiScanActionCmd, + sizeof(PARAM_WIFI_GSCAN_ACTION_CMD_PARAMS), FALSE, FALSE, TRUE, &u4BufLen); + + /* mtk_cfg80211_vendor_get_scan_results(wiphy, wdev, data, data_len ); */ + + return 0; + +nla_put_failure: + return -1; +} + +int mtk_cfg80211_vendor_enable_full_scan_results(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + struct nlattr *attr; + UINT_8 gFullScanResultsEn = 0; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + DBGLOG(REQ, INFO, "%s for vendor command: data_len=%d, data=0x%x 0x%x\r\n", + __func__, data_len, *((UINT_32 *) data), *((UINT_32 *) data + 1)); + + attr = (struct nlattr *)data; + if (attr->nla_type == GSCAN_ENABLE_FULL_SCAN_RESULTS) + gFullScanResultsEn = nla_get_u32(attr); + DBGLOG(REQ, INFO, "gFullScanResultsEn=%d, \r\n", gFullScanResultsEn); + + return 0; + +nla_put_failure: + return -1; +} + +int mtk_cfg80211_vendor_get_scan_results(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) +{ + UINT_32 u4BufLen; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_WIFI_GSCAN_GET_RESULT_PARAMS rGSscnResultParm; + + struct nlattr *attr; + UINT_32 get_num, real_num; + UINT_8 flush = 0; + int i; + + ASSERT(wiphy); + ASSERT(wdev); + get_num = 0; + real_num = 0; + if ((data == NULL) || !data_len) + goto nla_put_failure; + DBGLOG(REQ, TRACE, "%s for vendor command: data_len=%d\r\n", __func__, data_len); + for (i = 0; i < 2; i++) + DBGLOG(REQ, LOUD, "0x%x 0x%x 0x%x 0x%x\r\n", *((UINT_32 *) data + i * 4), + *((UINT_32 *) data + i * 4 + 1), *((UINT_32 *) data + i * 4 + 2), + *((UINT_32 *) data + i * 4 + 3)); + + attr = (struct nlattr *)data; + if (attr->nla_type == GSCAN_ATTRIBUTE_NUM_OF_RESULTS) { + get_num = nla_get_u32(attr); + attr = (struct nlattr *)((UINT_8 *) attr + attr->nla_len); + } + if (attr->nla_type == GSCAN_ATTRIBUTE_FLUSH_RESULTS) { + flush = nla_get_u8(attr); + attr = (struct nlattr *)((UINT_8 *) attr + attr->nla_len); + } + DBGLOG(REQ, TRACE, "number=%d, flush=%d\r\n", get_num, flush); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + real_num = (get_num < PSCAN_MAX_SCAN_CACHE_SIZE) ? get_num : PSCAN_MAX_SCAN_CACHE_SIZE; + get_num = real_num; + + rGSscnResultParm.get_num = get_num; + rGSscnResultParm.flush = flush; + + kalIoctl(prGlueInfo, + wlanoidGetGSCNResult, + &rGSscnResultParm, sizeof(PARAM_WIFI_GSCAN_GET_RESULT_PARAMS), FALSE, FALSE, TRUE, &u4BufLen); + + scnGscnGetResultReplyCheck(prGlueInfo->prAdapter); + + return 0; + +nla_put_failure: + return -1; +} +#endif +int mtk_cfg80211_vendor_get_channel_list(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) + { + P_GLUE_INFO_T prGlueInfo; + struct nlattr *attr; + UINT_32 band = 0; + UINT_8 ucNumOfChannel, i, j; + RF_CHANNEL_INFO_T aucChannelList[MAX_CHN_NUM]; + UINT_32 num_channels; + wifi_channel channels[MAX_CHN_NUM]; + struct sk_buff *skb; + uint16_t u2CountryCode; + + ASSERT(wiphy && wdev); + if ((data == NULL) || !data_len) + return -EINVAL; + + DBGLOG(REQ, INFO, "vendor command: data_len=%d\n", data_len); + + attr = (struct nlattr *)data; + if (attr->nla_type == WIFI_ATTRIBUTE_BAND) + band = nla_get_u32(attr); + + DBGLOG(REQ, INFO, "Get channel list for band: %d\n", band); + + if (wdev == gprWdev) /*wlan0*/ + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + else + prGlueInfo = *(P_GLUE_INFO_T *) wiphy_priv(wiphy); + if (!prGlueInfo) + return -EFAULT; + + if (band == 0) { /* 2.4G band */ + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_2G4, TRUE, + MAX_CHN_NUM, &ucNumOfChannel, aucChannelList); + } else { /* 5G band */ + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_5G, TRUE, + MAX_CHN_NUM, &ucNumOfChannel, aucChannelList); + } + + kalMemZero(channels, sizeof(channels)); + u2CountryCode = prGlueInfo->prAdapter + ->rWifiVar.rConnSettings.u2CountryCode; + for (i = 0, j = 0; i < ucNumOfChannel; i++) { + /* We need to report frequency list to HAL */ + channels[j] = nicChannelNum2Freq(aucChannelList[i].ucChannelNum) / 1000; + if (channels[j] == 0) + continue; + else if ((u2CountryCode == COUNTRY_CODE_TW) && + (channels[j] >= 5180 && channels[j] <= 5260)) { + /* Taiwan NCC has resolution to follow FCC spec to support 5G Band 1/2/3/4 + * (CH36~CH48, CH52~CH64, CH100~CH140, CH149~CH165) + * Filter CH36~CH52 for compatible with some old devices. + */ + continue; + } else { + DBGLOG(REQ, INFO, "channels[%d] = %d\n", j, channels[j]); + j++; + } + } + num_channels = j; + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(channels)); + if (!skb) { + DBGLOG(REQ, ERROR, "Allocate skb failed\n"); + return -ENOMEM; + } + + if (unlikely(nla_put_u32(skb, WIFI_ATTRIBUTE_NUM_CHANNELS, num_channels) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put(skb, WIFI_ATTRIBUTE_CHANNEL_LIST, + (sizeof(wifi_channel) * num_channels), channels) < 0)) + goto nla_put_failure; + + return cfg80211_vendor_cmd_reply(skb); + +nla_put_failure: + kfree_skb(skb); + return -EFAULT; + } + + + +int mtk_cfg80211_vendor_set_country_code(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + struct nlattr *attr; + UINT_8 country[2]; + + ASSERT(wiphy && wdev); + if ((data == NULL) || (data_len == 0)) + return -EINVAL; + + DBGLOG(REQ, INFO, "vendor command: data_len=%d\n", data_len); + + attr = (struct nlattr *)data; + + if (attr->nla_type != WIFI_ATTRIBUTE_COUNTRY_CODE) + return -EINVAL; + + country[0] = *((PUINT_8)nla_data(attr)); + country[1] = *((PUINT_8)nla_data(attr) + 1); + + DBGLOG(REQ, INFO, "Set country code: %c%c\n", country[0], country[1]); + + if (wdev == gprWdev) /*wlan0*/ + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + else + prGlueInfo = *(P_GLUE_INFO_T *) wiphy_priv(wiphy); + + if (!prGlueInfo) + return -EFAULT; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetCountryCode, country, 2, FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "Set country code error: %x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +int mtk_cfg80211_vendor_get_roaming_capabilities(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + UINT_32 maxNumOfList[2] = { MAX_FW_ROAMING_BLACKLIST_SIZE, +MAX_FW_ROAMING_WHITELIST_SIZE }; + struct sk_buff *skb; + + if (wiphy == NULL || wdev == NULL) + return -EFAULT; + + DBGLOG(REQ, INFO, "Get roaming capabilities: max black/whitelist=%d/%d", +maxNumOfList[0], maxNumOfList[1]); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(maxNumOfList)); + if (!skb) { + DBGLOG(REQ, ERROR, "Allocate skb failed\n"); + return -ENOMEM; + } + + if (unlikely(nla_put(skb, WIFI_ATTRIBUTE_ROAMING_CAPABILITIES, + sizeof(maxNumOfList), maxNumOfList) < 0)) + goto nla_put_failure; + + return cfg80211_vendor_cmd_reply(skb); + +nla_put_failure: + kfree_skb(skb); + return -EFAULT; +} + +int mtk_cfg80211_vendor_config_roaming(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4ResultLen = 0; + + + DBGLOG(REQ, TRACE, + "Receives roaming blacklist & whitelist with data_len=%d\n", + data_len); + if ((wiphy == NULL) || (wdev == NULL)) { + DBGLOG(REQ, INFO, "wiphy or wdev is NULL\n"); + return -EINVAL; + } + + if ((data == NULL) || (data_len == 0)) + return -EINVAL; + + if (wdev->iftype != NL80211_IFTYPE_STATION) + return -EINVAL; + + if (wdev == gprWdev) /*wlan0*/ + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + else + prGlueInfo = *(P_GLUE_INFO_T *) wiphy_priv(wiphy); + + + if (!prGlueInfo) + return -EINVAL; + + if (prGlueInfo->u4FWRoamingEnable == 0) { + DBGLOG(REQ, INFO, + "FWRoaming is disabled (FWRoamingEnable=%d)\n", + prGlueInfo->u4FWRoamingEnable); + return WLAN_STATUS_SUCCESS; + } + + kalIoctl(prGlueInfo, wlanoidConfigRoaming, (PVOID)data, data_len, FALSE, + FALSE, FALSE, &u4ResultLen); + + return WLAN_STATUS_SUCCESS; +} + +int mtk_cfg80211_vendor_enable_roaming(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4ResultLen = 0; + struct nlattr *attr; + + if ((wiphy == NULL) || (wdev == NULL)) { + DBGLOG(REQ, INFO, "wiphy or wdev is NULL\n"); + return -EINVAL; + } + + if (wdev == gprWdev) /*wlan0*/ + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + else + prGlueInfo = *(P_GLUE_INFO_T *) wiphy_priv(wiphy); + + if (!prGlueInfo) + return -EFAULT; + + attr = (struct nlattr *)data; + if (attr->nla_type == WIFI_ATTRIBUTE_ROAMING_STATE) + prGlueInfo->u4FWRoamingEnable = nla_get_u32(attr); + + if (prGlueInfo->u4FWRoamingEnable == 0) + kalIoctl(prGlueInfo, wlanoidEnableRoaming, + NULL, 0, FALSE, FALSE, FALSE, &u4ResultLen); + + + DBGLOG(REQ, INFO, "FWK set FWRoamingEnable = %d\n", + prGlueInfo->u4FWRoamingEnable); + + return WLAN_STATUS_SUCCESS; +} + +#if 0 +int mtk_cfg80211_vendor_llstats_get_info(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) +{ + INT_32 i4Status = -EINVAL; + WIFI_RADIO_STAT *pRadioStat; + struct sk_buff *skb; + UINT_32 u4BufLen; + + DBGLOG(REQ, INFO, "%s for vendor command\r\n", __func__); + + ASSERT(wiphy); + ASSERT(wdev); + + u4BufLen = sizeof(WIFI_RADIO_STAT) + sizeof(WIFI_IFACE_STAT); + pRadioStat = kalMemAlloc(u4BufLen, VIR_MEM_TYPE); + if (!pRadioStat) { + DBGLOG(REQ, ERROR, "%s kalMemAlloc pRadioStat failed\n", __func__); + return -ENOMEM; + } + kalMemZero(pRadioStat, u4BufLen); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, u4BufLen); + if (!skb) { + DBGLOG(REQ, TRACE, "%s allocate skb failed:%x\n", __func__, i4Status); + return -ENOMEM; + } + + /*rStatus = kalIoctl(prGlueInfo, + * wlanoidQueryStatistics, + * &rRadioStat, + * sizeof(rRadioStat), + * TRUE, + * TRUE, + * TRUE, + * FALSE, + * &u4BufLen); + */ + /* only for test */ + pRadioStat->radio = 10; + pRadioStat->on_time = 11; + pRadioStat->tx_time = 12; + pRadioStat->num_channels = 4; + + NLA_PUT(skb, NL80211_ATTR_VENDOR_LLSTAT, u4BufLen, pRadioStat); + + i4Status = cfg80211_vendor_cmd_reply(skb); + + kalMemFree(pRadioStat, VIR_MEM_TYPE, u4BufLen); + + return i4Status; +} + +int mtk_cfg80211_vendor_event_complete_scan(struct wiphy *wiphy, struct wireless_dev *wdev, WIFI_SCAN_EVENT complete) +{ + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(wdev); + /* WIFI_SCAN_EVENT complete_scan; */ + + DBGLOG(REQ, INFO, "%s for vendor command\r\n", __func__); + + skb = cfg80211_vendor_event_alloc(wiphy, sizeof(complete), GSCAN_EVENT_COMPLETE_SCAN, GFP_KERNEL); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + /* complete_scan = WIFI_SCAN_COMPLETE; */ + if (!NLA_PUT_U32(skb, GSCAN_EVENT_COMPLETE_SCAN, &complete)) + return -1; + + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +} + +int mtk_cfg80211_vendor_event_scan_results_available(struct wiphy *wiphy, struct wireless_dev *wdev, UINT_32 num) +{ + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(wdev); + /* UINT_32 scan_result; */ + + DBGLOG(REQ, INFO, "%s for vendor command %d\r\n", __func__, num); + + skb = cfg80211_vendor_event_alloc(wiphy, sizeof(num), GSCAN_EVENT_SCAN_RESULTS_AVAILABLE, GFP_KERNEL); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + /* scan_result = 2; */ + if (!NLA_PUT_U32(skb, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE, &num)) + return -1; + + cfg80211_vendor_event(skb, GFP_KERNEL); + DBGLOG(SCN, INFO, "%s for vendor command done\r\n", __func__); + return 0; + +} + +int mtk_cfg80211_vendor_event_full_scan_results(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_GSCAN_RESULT pdata, UINT_32 data_len) +{ + PARAM_WIFI_GSCAN_RESULT result; + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(wdev); + DBGLOG(REQ, INFO, "%s for vendor command\r\n", __func__); + + skb = cfg80211_vendor_event_alloc(wiphy, sizeof(result), GSCAN_EVENT_FULL_SCAN_RESULTS, GFP_KERNEL); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + kalMemZero(&result, sizeof(result)); + kalMemCopy(result.ssid, "Gscan_full_test", sizeof("Gscan_full_test")); + result.channel = 2437; + + /* kalMemCopy(&result, pdata, sizeof(PARAM_WIFI_GSCAN_RESULT); */ + if (!NLA_PUT(skb, GSCAN_EVENT_FULL_SCAN_RESULTS, sizeof(result), &result)) + return -1; + + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +} + +int mtk_cfg80211_vendor_event_significant_change_results(struct wiphy *wiphy, + struct wireless_dev *wdev, + P_PARAM_WIFI_CHANGE_RESULT pdata, UINT_32 data_len) +{ + struct sk_buff *skb; + PARAM_WIFI_CHANGE_RESULT result[2], *presult; + + ASSERT(wiphy); + ASSERT(wdev); + DBGLOG(REQ, INFO, "%s for vendor command\r\n", __func__); + + skb = cfg80211_vendor_event_alloc(wiphy, sizeof(PARAM_WIFI_CHANGE_RESULT), + GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS, GFP_KERNEL); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + presult = result; + kalMemZero(presult, (sizeof(PARAM_WIFI_CHANGE_RESULT) * 2)); + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +} + +int mtk_cfg80211_vendor_event_hotlist_ap_found(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_GSCAN_RESULT pdata, UINT_32 data_len) +{ + struct sk_buff *skb; + PARAM_WIFI_GSCAN_RESULT result[2], *presult; + + ASSERT(wiphy); + ASSERT(wdev); + DBGLOG(REQ, INFO, "%s for vendor command\r\n", __func__); + + skb = cfg80211_vendor_event_alloc(wiphy, sizeof(PARAM_WIFI_GSCAN_RESULT), + GSCAN_EVENT_HOTLIST_RESULTS_FOUND, GFP_KERNEL); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + presult = result; + kalMemZero(presult, (sizeof(PARAM_WIFI_GSCAN_RESULT) * 2)); + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +} + +int mtk_cfg80211_vendor_event_hotlist_ap_lost(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_GSCAN_RESULT pdata, UINT_32 data_len) +{ + struct sk_buff *skb; + PARAM_WIFI_GSCAN_RESULT result[2], *presult; + + ASSERT(wiphy); + ASSERT(wdev); + DBGLOG(REQ, INFO, "%s for vendor command\r\n", __func__); + + skb = cfg80211_vendor_event_alloc(wiphy, sizeof(PARAM_WIFI_GSCAN_RESULT), + GSCAN_EVENT_HOTLIST_RESULTS_LOST, GFP_KERNEL); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + presult = result; + kalMemZero(presult, (sizeof(PARAM_WIFI_GSCAN_RESULT) * 2)); + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; +} + +#endif +#endif + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_wext.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_wext.c new file mode 100644 index 0000000000000..78b397bf3b250 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_wext.c @@ -0,0 +1,3910 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_wext.c#5 +*/ + +/*! \file gl_wext.c +* \brief ioctl() (mostly Linux Wireless Extensions) routines for STA driver. +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "gl_os.h" + +#include "config.h" +#include "wlan_oid.h" + +#include "gl_wext.h" +#include "gl_wext_priv.h" + +#include "precomp.h" + +#if CFG_SUPPORT_WAPI +#include "gl_sec.h" +#endif + +/* compatibility to wireless extensions */ +#ifdef WIRELESS_EXT + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +const long channel_freq[] = { + 2412, 2417, 2422, 2427, 2432, 2437, 2442, + 2447, 2452, 2457, 2462, 2467, 2472, 2484 +}; + +#define NUM_CHANNELS (ARRAY_SIZE(channel_freq)) + +#define MAX_SSID_LEN 32 +#define COUNTRY_CODE_LEN 10 /* country code length */ + +/******************************************************************************* +* 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, IW_PRIV_TYPE_CHAR | sizeof(NDIS_TRANSPORT_STRUCT), 0, + ""}, + {IOCTL_GET_STRUCT, 0, IW_PRIV_TYPE_CHAR | sizeof(NDIS_TRANSPORT_STRUCT), + ""}, + + {IOCTL_GET_DRIVER, IW_PRIV_TYPE_CHAR | 2000, IW_PRIV_TYPE_CHAR | 2000, "driver"}, + +#if CFG_SUPPORT_QA_TOOL + /* added for ATE iwpriv Command */ + {IOCTL_QA_TOOL_DAEMON, IW_PRIV_TYPE_BYTE | sizeof(HQA_CMD_FRAME), + 0, ""}, + {IOCTL_IWPRIV_ATE, IW_PRIV_TYPE_CHAR | 2000, 0, ""}, +#endif + + /* 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 + +#if CFG_SUPPORT_QA_TOOL + {PRIV_QACMD_SET, IW_PRIV_TYPE_CHAR | 2000, 0, "set"}, +#endif + + {PRIV_CMD_SW_CTRL, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_sw_ctrl"}, + {PRIV_CMD_SW_CTRL, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_sw_ctrl"}, + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS + {PRIV_CUSTOM_BWCS_CMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_bwcs"}, + /* GET STRUCT sub-ioctls commands */ + {PRIV_CUSTOM_BWCS_CMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_bwcs"}, +#endif + + /* SET STRUCT sub-ioctls commands */ + {PRIV_CMD_OID, 256, 0, "set_oid"}, + /* GET STRUCT sub-ioctls commands */ + {PRIV_CMD_OID, 0, 256, "get_oid"}, + + {PRIV_CMD_BAND_CONFIG, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_band"}, + {PRIV_CMD_BAND_CONFIG, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_band"}, + + {PRIV_CMD_SET_TX_POWER, IW_PRIV_TYPE_INT | 4, 0, "set_txpower"}, + {PRIV_CMD_GET_CH_LIST, 0, IW_PRIV_TYPE_INT | 50, "get_ch_list"}, + {PRIV_CMD_DUMP_MEM, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_mem"}, + +#if CFG_ENABLE_WIFI_DIRECT + {PRIV_CMD_P2P_MODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_p2p_mode"}, +#endif + {PRIV_CMD_MET_PROFILING, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_met_prof"}, + +}; + +static const iw_handler rIwPrivHandler[] = { + [IOCTL_SET_INT - SIOCIWFIRSTPRIV] = priv_set_int, + [IOCTL_GET_INT - SIOCIWFIRSTPRIV] = priv_get_int, + [IOCTL_SET_ADDRESS - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_GET_ADDRESS - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_SET_STR - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_GET_STR - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_SET_KEY - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_GET_KEY - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_SET_STRUCT - SIOCIWFIRSTPRIV] = priv_set_struct, + [IOCTL_GET_STRUCT - SIOCIWFIRSTPRIV] = priv_get_struct, + [IOCTL_SET_STRUCT_FOR_EM - SIOCIWFIRSTPRIV] = priv_set_struct, + [IOCTL_SET_INTS - SIOCIWFIRSTPRIV] = priv_set_ints, + [IOCTL_GET_INTS - SIOCIWFIRSTPRIV] = priv_get_ints, + [IOCTL_GET_DRIVER - SIOCIWFIRSTPRIV] = priv_set_driver, + +#if CFG_SUPPORT_QA_TOOL + [IOCTL_QA_TOOL_DAEMON - SIOCIWFIRSTPRIV] = priv_qa_agent, + [IOCTL_IWPRIV_ATE - SIOCIWFIRSTPRIV] = priv_ate_set +#endif +}; + +const struct iw_handler_def wext_handler_def = { + .num_standard = 0, +#if defined(CONFIG_WEXT_PRIV) || LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32) + .num_private = (__u16) sizeof(rIwPrivHandler) / sizeof(iw_handler), + .num_private_args = (__u16) sizeof(rIwPrivTable) / sizeof(struct iw_priv_args), +#endif /* CONFIG_WEXT_PRIV || LINUX_VERSION_CODE <= 2.6.32 */ + .standard = (iw_handler *) NULL, +#if defined(CONFIG_WEXT_PRIV) || LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32) + .private = rIwPrivHandler, + .private_args = rIwPrivTable, +#endif /* CONFIG_WEXT_PRIV || LINUX_VERSION_CODE <= 2.6.32 */ + .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 +******************************************************************************** +*/ +static void wext_support_ioctl_SIOCSIWGENIE(IN P_GLUE_INFO_T prGlueInfo, IN char *prExtraBuf, IN UINT_32 u4ExtraSize); + +static void +wext_support_ioctl_SIOCSIWPMKSA_Action(IN struct net_device *prDev, IN char *prExtraBuf, IN int ioMode, OUT int *ret); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired WPA/RSN Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +wextSrchDesiredWPAIE(IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT PUINT_8 *ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ucDesiredElemId && i4InfoElemLen <= i4TotalIeLen) { + if (ucDesiredElemId != 0xDD) { + /* Non 0xDD, OK! */ + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } /* EID == 0xDD, check WPA IE */ + if (pucIEStart[1] >= 4) { + if (memcmp(&pucIEStart[2], "\x00\x50\xf2\x01", 4) == 0) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + } /* check WPA IE length */ + /* check EID == 0xDD */ + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* parseSearchDesiredWPAIE */ + +#if CFG_SUPPORT_WAPI +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired WAPI Information Element . +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextSrchDesiredWAPIIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ELEM_ID_WAPI && i4InfoElemLen <= i4TotalIeLen) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* wextSrchDesiredWAPIIE */ +#endif + +#if CFG_SUPPORT_PASSPOINT +/*----------------------------------------------------------------------------*/ +/*! +* \brief Check if exist the desired HS2.0 Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextIsDesiredHS20IE(IN PUINT_8 pucCurIE, IN INT_32 i4TotalIeLen) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucCurIE); + + i4InfoElemLen = (INT_32) pucCurIE[1] + 2; + + if (pucCurIE[0] == ELEM_ID_VENDOR && i4InfoElemLen <= i4TotalIeLen) { + if (pucCurIE[1] >= ELEM_MIN_LEN_HS20_INDICATION) { + if (memcmp(&pucCurIE[2], "\x50\x6f\x9a\x10", 4) == 0) + return TRUE; + } + } + /* check desired EID */ + return FALSE; +} /* wextIsDesiredHS20IE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Check if exist the desired interworking Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextIsDesiredInterworkingIE(IN PUINT_8 pucCurIE, IN INT_32 i4TotalIeLen) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucCurIE); + + i4InfoElemLen = (INT_32) pucCurIE[1] + 2; + + if (pucCurIE[0] == ELEM_ID_INTERWORKING && i4InfoElemLen <= i4TotalIeLen) { + switch (pucCurIE[1]) { + case IW_IE_LENGTH_ANO: + case IW_IE_LENGTH_ANO_HESSID: + case IW_IE_LENGTH_ANO_VENUE: + case IW_IE_LENGTH_ANO_VENUE_HESSID: + return TRUE; + default: + break; + } + + } + /* check desired EID */ + return FALSE; +} /* wextIsDesiredInterworkingIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Check if exist the desired Adv Protocol Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextIsDesiredAdvProtocolIE(IN PUINT_8 pucCurIE, IN INT_32 i4TotalIeLen) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucCurIE); + + i4InfoElemLen = (INT_32) pucCurIE[1] + 2; + + if (pucCurIE[0] == ELEM_ID_ADVERTISEMENT_PROTOCOL && i4InfoElemLen <= i4TotalIeLen) + return TRUE; + /* check desired EID */ + return FALSE; +} /* wextIsDesiredAdvProtocolIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Check if exist the desired Roaming Consortium Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextIsDesiredRoamingConsortiumIE(IN PUINT_8 pucCurIE, IN INT_32 i4TotalIeLen) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucCurIE); + + i4InfoElemLen = (INT_32) pucCurIE[1] + 2; + + if (pucCurIE[0] == ELEM_ID_ROAMING_CONSORTIUM && i4InfoElemLen <= i4TotalIeLen) + return TRUE; + /* check desired EID */ + return FALSE; +} /* wextIsDesiredRoamingConsortiumIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired HS2.0 Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextSrchDesiredHS20IE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ELEM_ID_VENDOR && i4InfoElemLen <= i4TotalIeLen) { + if (pucIEStart[1] >= ELEM_MIN_LEN_HS20_INDICATION) { + if (memcmp(&pucIEStart[2], "\x50\x6f\x9a\x10", 4) == 0) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + } + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* wextSrchDesiredHS20IE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired interworking Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextSrchDesiredInterworkingIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ELEM_ID_INTERWORKING && i4InfoElemLen <= i4TotalIeLen) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* wextSrchDesiredInterworkingIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired Adv Protocol Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextSrchDesiredAdvProtocolIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ELEM_ID_ADVERTISEMENT_PROTOCOL && i4InfoElemLen <= i4TotalIeLen) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* wextSrchDesiredAdvProtocolIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired Roaming Consortium Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextSrchDesiredRoamingConsortiumIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ELEM_ID_ROAMING_CONSORTIUM && i4InfoElemLen <= i4TotalIeLen) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* wextSrchDesiredRoamingConsortiumIE */ + +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_WPS +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired WPS Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +wextSrchDesiredWPSIE(IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT PUINT_8 *ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ucDesiredElemId && i4InfoElemLen <= i4TotalIeLen) { + if (ucDesiredElemId != 0xDD) { + /* Non 0xDD, OK! */ + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + /* EID == 0xDD, check WPS IE */ + if (pucIEStart[1] >= 4) { + if (memcmp(&pucIEStart[2], "\x00\x50\xf2\x04", 4) == 0) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + } /* check WPS IE length */ + /* check EID == 0xDD */ + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* parseSearchDesiredWPSIE */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Get the name of the protocol used on the air. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] pcName Buffer to store protocol name string +* \param[in] pcExtra NULL. +* +* \retval 0 For success. +* +* \note If netif_carrier_ok, protocol name is returned; +* otherwise, "disconnected" is returned. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_name(IN struct net_device *prNetDev, IN struct iw_request_info *prIwrInfo, OUT char *pcName, IN char *pcExtra) +{ + ENUM_PARAM_NETWORK_TYPE_T eNetWorkType; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(pcName); + if (GLUE_CHK_PR2(prNetDev, pcName) == FALSE) + 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, &u4BufLen); + + switch (eNetWorkType) { + case PARAM_NETWORK_TYPE_DS: + strncpy(pcName, "IEEE 802.11b", sizeof(((struct iwreq *)0)->u.name)); + break; + case PARAM_NETWORK_TYPE_OFDM24: + strncpy(pcName, "IEEE 802.11bgn", sizeof(((struct iwreq *)0)->u.name)); + break; + case PARAM_NETWORK_TYPE_AUTOMODE: + case PARAM_NETWORK_TYPE_OFDM5: + strncpy(pcName, "IEEE 802.11abgn", sizeof(((struct iwreq *)0)->u.name)); + break; + case PARAM_NETWORK_TYPE_FH: + default: + strncpy(pcName, "IEEE 802.11", sizeof(((struct iwreq *)0)->u.name)); + break; + } + } else { + strncpy(pcName, "Disconnected", sizeof(((struct iwreq *)0)->u.name)); + } + + 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 (GLUE_CHK_PR2(prNetDev, prIwFreq) == FALSE) + 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 (rStatus != WLAN_STATUS_SUCCESS) + return -EINVAL; + } + /* Setting by channel number */ + else if ((prIwFreq->m > KILO) || (prIwFreq->e > 0)) + return -EOPNOTSUPP; + /* Change to channel number format */ + u4ChnlFreq = (UINT_32) prIwFreq->m; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetChannel, &u4ChnlFreq, sizeof(u4ChnlFreq), FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + 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 (GLUE_CHK_PR2(prNetDev, prIwFreq) == FALSE) + 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, &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 (GLUE_CHK_PR2(prNetDev, pu4Mode) == FALSE) + 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", __func__, *pu4Mode); + return -EOPNOTSUPP; + } + + /* printk("%s(): Set Mode = %d\n", __FUNCTION__, *pu4Mode); */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetInfrastructureMode, &eOpMode, sizeof(eOpMode), FALSE, FALSE, TRUE, &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 (GLUE_CHK_PR2(prNetDev, pu4Mode) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryInfrastructureMode, &eOpMode, sizeof(eOpMode), TRUE, 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", __func__); + return -EINVAL; + } + + return 0; +} /* wext_get_mode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get the valid range for each configurable STA setting value. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prData Pointer to iw_point structure, not used. +* \param[out] pcExtra Pointer to buffer which is allocated by caller of this +* function, wext_support_ioctl() or ioctl_standard_call() in +* wireless.c. +* +* \retval 0 If data is valid. +* +* \note The extra buffer (pcExtra) is filled with information from driver. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_range(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, IN struct iw_point *prData, OUT char *pcExtra) +{ + struct iw_range *prRange = NULL; + PARAM_RATES_EX aucSuppRate = { 0 }; /* data buffers */ + int i = 0; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(pcExtra); + if (GLUE_CHK_PR2(prNetDev, pcExtra) == FALSE) + 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, &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 (GLUE_CHK_PR2(prNetDev, prAddr) == FALSE) + 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, sizeof(*prAddr)); + return 0; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryBssid, prAddr->sa_data, ETH_ALEN, TRUE, 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 (GLUE_CHK_PR2(prNetDev, pcExtra) == FALSE) + 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, &u4BufLen); + return 0; + } + 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 (GLUE_CHK_DEV(prNetDev) == FALSE) + 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, &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 (GLUE_CHK_PR3(prNetDev, prData, pcExtra) == FALSE) + 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, &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, &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:%d\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; + kalMemCopy(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 length is ok, device will try connecting to the new network. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_set_essid(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, IN struct iw_point *prEssid, IN char *pcExtra) +{ + PARAM_SSID_T rNewSsid; + UINT_32 cipher; + ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus; + ENUM_PARAM_AUTH_MODE_T eAuthMode; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prEssid); + ASSERT(pcExtra); + if (GLUE_CHK_PR3(prNetDev, prEssid, pcExtra) == FALSE) + 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, &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, &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, &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 (GLUE_CHK_PR3(prNetDev, prEssid, pcExtra) == FALSE) + 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, &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 rStatus; +} /* 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 (GLUE_CHK_PR2(prNetDev, prRate) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* + * printk("value = %d, fixed = %d, disable = %d, flags = %d\n", + * prRate->value, prRate->fixed, prRate->disabled, prRate->flags); + */ + + rStatus = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQuerySupportedRates, &aucSuppRate, sizeof(aucSuppRate), &u4BufLen); + + /* Case: AUTO */ + if (prRate->value < 0) { + if (prRate->fixed == 0) { + /* iwconfig wlan0 rate auto */ + + /* set full supported rate to device */ + /* printk("wlanoidQuerySupportedRates():u4BufLen = %ld\n", u4BufLen); */ + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetDesiredRates, + &aucSuppRate, sizeof(aucSuppRate), &u4BufLen); + return 0; + } + /* iwconfig wlan0 rate fixed */ + + /* fix rate to what? DO NOTHING */ + return -EINVAL; + } + + aucNewRate[0] = prRate->value / 500000; /* In unit of 500k */ + + for (i = 0; i < PARAM_MAX_LEN_RATES_EX; i++) { + /* check the given value is supported */ + if (aucSuppRate[i] == 0) + break; + + if (aucNewRate[0] == aucSuppRate[i]) { + u4NewRateLen = 1; + break; + } + } + + if (u4NewRateLen == 0) { + /* the given value is not supported */ + /* return error or use given rate as upper bound? */ + return -EINVAL; + } + + if (prRate->fixed == 0) { + /* add all rates lower than desired rate */ + for (i = 0; i < PARAM_MAX_LEN_RATES_EX; ++i) { + if (aucSuppRate[i] == 0) + break; + + if (aucSuppRate[i] < aucNewRate[0]) + aucNewRate[u4NewRateLen++] = aucSuppRate[i]; + } + } + + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetDesiredRates, &aucNewRate, sizeof(aucNewRate), &u4BufLen); + return 0; +} /* wext_set_rate */ + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get current tx bit rate. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] prRate Pointer to iw_param structure to store current tx rate. +* \param[in] pcExtra NULL. +* +* \retval 0 If netif_carrier_ok. +* \retval -ENOTCONN Otherwise. +* +* \note If netif_carrier_ok, current tx rate is stored in pRate. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_rate(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, OUT struct iw_param *prRate, IN char *pcExtra) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + UINT_32 u4Rate = 0; + + ASSERT(prNetDev); + ASSERT(prRate); + if (GLUE_CHK_PR2(prNetDev, prRate) == FALSE) + 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, &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 (GLUE_CHK_PR2(prNetDev, prRts) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (prRts->value < 0 || prRts->value > 2347) + return -EINVAL; + + if (prRts->disabled == 1) + u4RtsThresh = 2347; + else + u4RtsThresh = (PARAM_RTS_THRESHOLD) prRts->value; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRtsThreshold, &u4RtsThresh, sizeof(u4RtsThresh), 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 (GLUE_CHK_PR2(prNetDev, prRts) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryRtsThreshold, &u4RtsThresh, sizeof(u4RtsThresh), TRUE, 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 (GLUE_CHK_PR2(prNetDev, prTxPow) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (prTxPow->disabled) { + /* <1> disconnect */ + rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, NULL, 0, FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + /* ToDo:: DBGLOG */ + 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 = ParamDeviceStateD0; + + 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 (GLUE_CHK_PR2(prNetDev, prTxPow) == FALSE) + 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 (GLUE_CHK_PR2(prNetDev, prEnc) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryEncryptionStatus, &eEncMode, sizeof(eEncMode), TRUE, 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 (GLUE_CHK_PR3(prNetDev, prEnc, pcExtra) == FALSE) + 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, &u4BufLen); + + eEncStatus = ENUM_ENCRYPTION_DISABLED; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEncryptionStatus, + &eEncStatus, sizeof(eEncStatus), 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, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "wlanoidSetAddWep fail 0x%x\n", + rStatus); + return -EFAULT; + } + + /* change to auto switch */ + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_SHARED_KEY | IW_AUTH_ALG_OPEN_SYSTEM; + eAuthMode = AUTH_MODE_AUTO_SWITCH; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAuthMode, &eAuthMode, sizeof(eAuthMode), FALSE, FALSE, FALSE, &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, &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; + PARAM_POWER_MODE_T rPowerMode; + + ASSERT(prNetDev); + ASSERT(prPower); + if (GLUE_CHK_PR2(prNetDev, prPower) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (!prGlueInfo) + return -EFAULT; + + if (!prGlueInfo->prAdapter->prAisBssInfo) + return -EFAULT; + /* 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", + __func__, prPower->value); + + return -EINVAL; + } + } + + rPowerMode.ePowerMode = ePowerMode; + rPowerMode.ucBssIdx = prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &rPowerMode, sizeof(PARAM_POWER_MODE_T), FALSE, FALSE, TRUE, &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 (GLUE_CHK_PR2(prNetDev, prPower) == FALSE) + 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 (GLUE_CHK_PR2(prNetDev, prAuth) == FALSE) + 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, &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, &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[1024]; /* 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 (GLUE_CHK_PR3(prNetDev, prEnc, pcExtra) == FALSE) + 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[0], &prIWEncExt->tx_seq[0], IW_ENCODE_SEQ_MAX_SIZE); + memcpy(&prWpiKey->aucPN[8], &prIWEncExt->rx_seq[0], IW_ENCODE_SEQ_MAX_SIZE); + + /* 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, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + /* do nothing */ + /* printk(KERN_INFO "[wapi] add key error:%lx\n", rStatus); */ + } + + } else +#endif + { + + if ((prEnc->flags & IW_ENCODE_MODE) == IW_ENCODE_DISABLED) { + prRemoveKey->u4Length = sizeof(*prRemoveKey); + memcpy(prRemoveKey->arBSSID, prIWEncExt->addr.sa_data, 6); + /* + * printk("IW_ENCODE_DISABLED: ID:%d, Addr:[" MACSTR "]\n", + * prRemoveKey->KeyIndex, MAC2STR(prRemoveKey->BSSID)); + */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRemoveKey, + prRemoveKey, prRemoveKey->u4Length, FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "remove key error:%x\n", + rStatus); + return 0; + } + /* return 0; */ + /* printk ("alg %x\n", prIWEncExt->alg); */ + + switch (prIWEncExt->alg) { + case IW_ENCODE_ALG_NONE: + break; + case IW_ENCODE_ALG_WEP: + /* iwconfig wlan0 key 0123456789 */ + /* iwconfig wlan0 key s:abcde */ + /* iwconfig wlan0 key 0123456789 [1] */ + /* iwconfig wlan0 key 01234567890123456789012345 [1] */ + /* check key size for WEP */ + if (prIWEncExt->key_len == 5 || prIWEncExt->key_len == 13 || prIWEncExt->key_len == 16) { + /* prepare PARAM_WEP key structure */ + prWepKey->u4KeyIndex = (prEnc->flags & IW_ENCODE_INDEX) ? + (prEnc->flags & IW_ENCODE_INDEX) - 1 : 0; + if (prWepKey->u4KeyIndex > 3) { + /* key id is out of range */ + return -EINVAL; + } + prWepKey->u4KeyIndex |= 0x80000000; + prWepKey->u4Length = 12 + prIWEncExt->key_len; + prWepKey->u4KeyLength = prIWEncExt->key_len; + /* kalMemCopy(prWepKey->aucKeyMaterial, pcExtra, prIWEncExt->key_len); */ + kalMemCopy(prWepKey->aucKeyMaterial, prIWEncExt->key, prIWEncExt->key_len); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAddWep, + prWepKey, prWepKey->u4Length, FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, + "wlanoidSetAddWep fail 0x%x\n", + rStatus); + return -EFAULT; + } + + /* change to auto switch */ + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_SHARED_KEY | IW_AUTH_ALG_OPEN_SYSTEM; + eAuthMode = AUTH_MODE_AUTO_SWITCH; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAuthMode, + &eAuthMode, sizeof(eAuthMode), FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, + "wlanoidSetAuthMode fail 0x%x\n", + rStatus); + return -EFAULT; + } + + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40; + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40; + + eEncStatus = ENUM_WEP_ENABLED; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEncryptionStatus, + &eEncStatus, + sizeof(ENUM_PARAM_ENCRYPTION_STATUS_T), + FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, + "wlanoidSetEncryptionStatus fail 0x%x\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%x\n", + prKey->u4KeyIndex); + /* key id is out of range */ + return -EINVAL; + } + + /* bit(31) and bit(30) are shared by pKey and pRemoveKey */ + /* Tx Key Bit(31) */ + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + prKey->u4KeyIndex |= 0x1UL << 31; + + /* 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 { + /* aucKeyMaterial is defined as a 32-elements array */ + if (prIWEncExt->key_len > 32) { + DBGLOG(REQ, ERROR, "prIWEncExt->key_len: %d is too long!\n", + prIWEncExt->key_len); + return -EFAULT; + } + memcpy(prKey->aucKeyMaterial, prIWEncExt->key, prIWEncExt->key_len); + } + + prKey->u4KeyLength = prIWEncExt->key_len; + prKey->u4Length = ((ULONG)&(((P_PARAM_KEY_T) 0)->aucKeyMaterial)) + prKey->u4KeyLength; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAddKey, prKey, prKey->u4Length, FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, + "add key error:%x\n", rStatus); + return -EFAULT; + } + break; + } + } + + return 0; +} /* wext_set_encode_ext */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set country code +* +* \param[in] prNetDev Net device requested. +* \param[in] prData iwreq.u.data carries country code value. +* +* \retval 0 For success. +* \retval -EEFAULT For fail. +* +* \note Country code is stored and channel list is updated based on current country domain. +*/ +/*----------------------------------------------------------------------------*/ +static int wext_set_country(IN struct net_device *prNetDev, IN struct iw_point *prData) +{ + P_GLUE_INFO_T prGlueInfo; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + UINT_8 aucCountry[COUNTRY_CODE_LEN]; + + ASSERT(prNetDev); + + /* prData->pointer should be like "COUNTRY US", "COUNTRY EU" + * and "COUNTRY JP" + */ + if (GLUE_CHK_PR2(prNetDev, prData) == FALSE + || !prData->pointer + || prData->length < COUNTRY_CODE_LEN) + return -EINVAL; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (copy_from_user(aucCountry, prData->pointer, COUNTRY_CODE_LEN)) + return -EFAULT; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetCountryCode, + &aucCountry[COUNTRY_CODE_LEN-2], + 2, FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "Set country code error: %x\n", rStatus); + return -EFAULT; + } + + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To report the iw private args table to user space. +* +* \param[in] prNetDev Net device requested. +* \param[out] prData iwreq.u.data to carry the private args table. +* +* \retval 0 For success. +* \retval -E2BIG For user's buffer size is too small. +* \retval -EFAULT For fail. +* +*/ +/*----------------------------------------------------------------------------*/ +int wext_get_priv(IN struct net_device *prNetDev, OUT struct iw_point *prData) +{ + UINT_16 u2BufferSize = prData->length; + + /* Update our private args table size */ + prData->length = (__u16)sizeof(rIwPrivTable); + if (u2BufferSize < prData->length) + return -E2BIG; + + if (prData->length) { + if (copy_to_user(prData->pointer, rIwPrivTable, sizeof(rIwPrivTable))) + return -EFAULT; + } + + return 0; +} /* wext_get_priv */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief ioctl() (Linux Wireless Extensions) routines +* +* \param[in] prDev Net device requested. +* \param[in] ifr The ifreq structure for seeting the wireless extension. +* \param[in] i4Cmd The wireless extension ioctl command. +* +* \retval zero On success. +* \retval -EOPNOTSUPP If the cmd is not supported. +* \retval -EFAULT If copy_to_user goes wrong. +* \retval -EINVAL If any value's out of range. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int wext_support_ioctl(IN struct net_device *prDev, IN struct ifreq *prIfReq, IN int i4Cmd) +{ + /* 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 should be large enough */ + if (iwr->u.data.length < sizeof(struct iw_range)) { + ret = -E2BIG; + break; + } + + prExtraBuf = kalMemAlloc(sizeof(struct iw_range), VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + /* reset all fields */ + memset(prExtraBuf, 0, sizeof(struct iw_range)); + iwr->u.data.length = sizeof(struct iw_range); + + ret = wext_get_range(prDev, NULL, &iwr->u.data, prExtraBuf); + /* Push up to the caller */ + if (copy_to_user(iwr->u.data.pointer, prExtraBuf, iwr->u.data.length)) + ret = -EFAULT; + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, sizeof(struct iw_range)); + prExtraBuf = NULL; + } else { + ret = -EINVAL; + } + break; + + case SIOCSIWPRIV: /* 0x8B0C, set country code */ + ret = wext_set_country(prDev, &iwr->u.data); + break; + + case SIOCGIWPRIV: /* 0x8B0D, get private args table */ + ret = wext_get_priv(prDev, &iwr->u.data); + break; + + /* 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; + } + 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)) { + struct iw_scan_req *req; + + prExtraBuf = kalMemAlloc(MAX_SSID_LEN, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + req = (struct iw_scan_req *)(iwr->u.data.pointer); + + if (req->essid_len > MAX_SSID_LEN) { + ret = -EFAULT; + } else if (copy_from_user + (prExtraBuf, req->essid, req->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 > %d)\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; + } + + kalMemZero(prExtraBuf, IW_ESSID_MAX_SIZE); + /* 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, IW_ESSID_MAX_SIZE)) + 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 + wext_support_ioctl_SIOCSIWGENIE(prGlueInfo, prExtraBuf, u4ExtraSize); + 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; + + if (u4ExtraSize > sizeof(struct iw_encode_ext)) { + ret = -EINVAL; + break; + } + + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, iwr->u.encoding.pointer, u4ExtraSize)) + 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)); + */ + { + wext_support_ioctl_SIOCSIWPMKSA_Action(prDev, prExtraBuf, IW_PMKSA_ADD, + &ret); + } + 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"); + */ + { + wext_support_ioctl_SIOCSIWPMKSA_Action(prDev, prExtraBuf, + IW_PMKSA_FLUSH, &ret); + } + 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 */ + +static void wext_support_ioctl_SIOCSIWGENIE(IN P_GLUE_INFO_T prGlueInfo, IN char *prExtraBuf, IN UINT_32 u4ExtraSize) +{ + WLAN_STATUS rStatus; + UINT_32 u4BufLen; +#if CFG_SUPPORT_WAPI + rStatus = kalIoctl(prGlueInfo, wlanoidSetWapiAssocInfo, prExtraBuf, u4ExtraSize, FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { +#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, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + /* do nothing */ + /* printk(KERN_INFO "[WSC] set WSC assoc info error:%lx\n", rStatus); */ + } + } +#endif +#if CFG_SUPPORT_WAPI + } +#endif + +} + +static void +wext_support_ioctl_SIOCSIWPMKSA_Action(IN struct net_device *prDev, IN char *prExtraBuf, IN int ioMode, OUT int *ret) +{ + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + P_PARAM_PMKID_T prPmkid; + + switch (ioMode) { + case IW_PMKSA_ADD: + 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, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "add pmkid error:%x\n", rStatus); + + kalMemFree(prPmkid, VIR_MEM_TYPE, 8 + sizeof(PARAM_BSSID_INFO_T)); + break; + case IW_PMKSA_FLUSH: + 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, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "flush pmkid error:%x\n", rStatus); + + kalMemFree(prPmkid, VIR_MEM_TYPE, 8); + break; + default: + break; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To send an event (RAW socket pacekt) to user process actively. +* +* \param[in] prGlueInfo Glue layer info. +* \param[in] u4cmd Which event command we want to indicate to user process. +* \param[in] pData Data buffer to be indicated. +* \param[in] dataLen Available data size in pData. +* +* \return (none) +* +* \note Event is indicated to upper layer if cmd is supported and data is valid. +* Using of kernel symbol wireless_send_event(), which is defined in +* after WE-14 (2.4.20). +*/ +/*----------------------------------------------------------------------------*/ +void +wext_indicate_wext_event(IN P_GLUE_INFO_T prGlueInfo, + IN unsigned int u4Cmd, IN unsigned char *pucData, IN unsigned int u4dataLen) +{ + union iwreq_data wrqu; + unsigned char *pucExtraInfo = NULL; +#if WIRELESS_EXT >= 15 + unsigned char *pucDesiredIE = NULL; + unsigned char aucExtraInfoBuf[200]; +#endif +#if WIRELESS_EXT < 18 + int i; +#endif + + memset(&wrqu, 0, sizeof(wrqu)); + + switch (u4Cmd) { + case SIOCGIWTXPOW: + memcpy(&wrqu.power, pucData, u4dataLen); + break; + case SIOCGIWSCAN: + complete_all(&prGlueInfo->rScanComp); + break; + + case SIOCGIWAP: + if (pucData) + kalMemCopy(&wrqu.ap_addr.sa_data, pucData, ETH_ALEN); + else + eth_zero_addr((u8 *)&wrqu.ap_addr.sa_data); + 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 */ + /* RSN IE found */ + } +#if 0 + else if (wextSrchDesiredWPSIE(pucData, u4dataLen, 0xDD, &pucDesiredIE)) { + /* WPS IE found */ + /* WPS IE found */ + } +#endif + else if (wextSrchDesiredWPAIE(pucData, u4dataLen, 0xDD, &pucDesiredIE)) { + /* WPA IE found */ + /* 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) { + INT_32 i4BufLen = 0; + P_PARAM_AUTH_REQUEST_T pAuthReq = (P_PARAM_AUTH_REQUEST_T) pucData; + /* under WE-18, only IWEVCUSTOM can be used */ + u4Cmd = IWEVCUSTOM; + pucExtraInfo = aucExtraInfoBuf; + + i4BufLen = scnprintf(pucExtraInfo, sizeof(aucExtraInfoBuf), + "MLME-MICHAELMICFAILURE.indication "); + + i4BufLen += scnprintf((pucExtraInfo + i4BufLen), + (sizeof(aucExtraInfoBuf) - i4BufLen), + "%s", + (pAuthReq->u4Flags == + PARAM_AUTH_REQUEST_GROUP_ERROR) ? "groupcast " : "unicast "); + + wrqu.data.length = i4BufLen; + 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, &bufLen); + +stat_out: + return pStats; +} /* wlan_get_wireless_stats */ + + + +#endif /* WIRELESS_EXT */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_wext_priv.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_wext_priv.c new file mode 100644 index 0000000000000..6d0cc0734095e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/gl_wext_priv.c @@ -0,0 +1,11628 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_wext_priv.c#8 +*/ + +/*! \file gl_wext_priv.c +* \brief This file includes private ioctl support. +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" +#include "gl_os.h" +#include "gl_wext_priv.h" + +#if CFG_SUPPORT_QA_TOOL +#include "gl_ate_agent.h" +#include "gl_qa_agent.h" +#endif + +#if CFG_SUPPORT_WAPI +#include "gl_sec.h" +#endif +#if CFG_ENABLE_WIFI_DIRECT +#include "gl_p2p_os.h" +#endif + +/* +* #if CFG_SUPPORT_QA_TOOL +* extern UINT_16 g_u2DumpIndex; +* #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[] = { +#if 0 + {(NDIS_OID)rOid, + (PUINT_8)pucOidName, + fgQryBufLenChecking, fgSetBufLenChecking, fgIsHandleInGlueLayerOnly, u4InfoBufLen, + pfOidQueryHandler, + pfOidSetHandler} +#endif + /* 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 0 + #if PTA_ENABLED + {OID_CUSTOM_BT_COEXIST_CTRL, + DISP_STRING("OID_CUSTOM_BT_COEXIST_CTRL"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_BT_COEXIST_T), + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetBtCoexistCtrl}, + #endif + + {OID_CUSTOM_POWER_MANAGEMENT_PROFILE, + DISP_STRING("OID_CUSTOM_POWER_MANAGEMENT_PROFILE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryPwrMgmtProfParam, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetPwrMgmtProfParam}, + {OID_CUSTOM_PATTERN_CONFIG, + DISP_STRING("OID_CUSTOM_PATTERN_CONFIG"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_PATTERN_SEARCH_CONFIG_STRUCT_T), + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetPatternConfig}, + {OID_CUSTOM_BG_SSID_SEARCH_CONFIG, + DISP_STRING("OID_CUSTOM_BG_SSID_SEARCH_CONFIG"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetBgSsidParam}, + {OID_CUSTOM_VOIP_SETUP, + DISP_STRING("OID_CUSTOM_VOIP_SETUP"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryVoipConnectionStatus, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetVoipConnectionStatus}, + {OID_CUSTOM_ADD_TS, + DISP_STRING("OID_CUSTOM_ADD_TS"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidAddTS}, + {OID_CUSTOM_DEL_TS, + DISP_STRING("OID_CUSTOM_DEL_TS"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidDelTS}, + + #if CFG_LP_PATTERN_SEARCH_SLT + {OID_CUSTOM_SLT, + DISP_STRING("OID_CUSTOM_SLT"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQuerySltResult, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetSltMode}, + #endif + + {OID_CUSTOM_ROAMING_EN, + DISP_STRING("OID_CUSTOM_ROAMING_EN"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryRoamingFunction, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetRoamingFunction}, + {OID_CUSTOM_WMM_PS_TEST, + DISP_STRING("OID_CUSTOM_WMM_PS_TEST"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetWiFiWmmPsTest}, + {OID_CUSTOM_COUNTRY_STRING, + DISP_STRING("OID_CUSTOM_COUNTRY_STRING"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryCurrentCountry, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetCurrentCountry}, + + #if CFG_SUPPORT_802_11D + {OID_CUSTOM_MULTI_DOMAIN_CAPABILITY, + DISP_STRING("OID_CUSTOM_MULTI_DOMAIN_CAPABILITY"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryMultiDomainCap, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetMultiDomainCap}, + #endif + + {OID_CUSTOM_GPIO2_MODE, + DISP_STRING("OID_CUSTOM_GPIO2_MODE"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(ENUM_PARAM_GPIO2_MODE_T), + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetGPIO2Mode}, + {OID_CUSTOM_CONTINUOUS_POLL, + DISP_STRING("OID_CUSTOM_CONTINUOUS_POLL"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CONTINUOUS_POLL_T), + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryContinuousPollInterval, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetContinuousPollProfile}, + {OID_CUSTOM_DISABLE_BEACON_DETECTION, + DISP_STRING("OID_CUSTOM_DISABLE_BEACON_DETECTION"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, 4, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryDisableBeaconDetectionFunc, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetDisableBeaconDetectionFunc}, + + /* WPS */ + {OID_CUSTOM_DISABLE_PRIVACY_CHECK, + DISP_STRING("OID_CUSTOM_DISABLE_PRIVACY_CHECK"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, 4, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetDisablePriavcyCheck}, +#endif + + {OID_CUSTOM_MCR_RW, + DISP_STRING("OID_CUSTOM_MCR_RW"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryMcrRead, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetMcrWrite} + , + + {OID_CUSTOM_EEPROM_RW, + DISP_STRING("OID_CUSTOM_EEPROM_RW"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryEepromRead, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetEepromWrite} + , + + {OID_CUSTOM_SW_CTRL, + DISP_STRING("OID_CUSTOM_SW_CTRL"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQuerySwCtrlRead, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetSwCtrlWrite} + , + + {OID_CUSTOM_MEM_DUMP, + DISP_STRING("OID_CUSTOM_MEM_DUMP"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_MEM_DUMP_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryMemDump, + NULL} + , + + {OID_CUSTOM_TEST_MODE, + DISP_STRING("OID_CUSTOM_TEST_MODE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + NULL, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestSetTestMode} + , + +#if 0 + {OID_CUSTOM_TEST_RX_STATUS, + DISP_STRING("OID_CUSTOM_TEST_RX_STATUS"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryRfTestRxStatus, + NULL}, + {OID_CUSTOM_TEST_TX_STATUS, + DISP_STRING("OID_CUSTOM_TEST_TX_STATUS"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryRfTestTxStatus, + NULL}, +#endif + {OID_CUSTOM_ABORT_TEST_MODE, + DISP_STRING("OID_CUSTOM_ABORT_TEST_MODE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + NULL, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestSetAbortTestMode} + , + {OID_CUSTOM_MTK_WIFI_TEST, + DISP_STRING("OID_CUSTOM_MTK_WIFI_TEST"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_MTK_WIFI_TEST_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestQueryAutoTest, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestSetAutoTest} + , + {OID_CUSTOM_TEST_ICAP_MODE, + DISP_STRING("OID_CUSTOM_TEST_ICAP_MODE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + NULL, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestSetTestIcapMode} + , + + /* 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 +#if 0 + {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}, +#endif + + {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 +}; + +#ifdef CONFIG_COMPAT +#ifdef in_compat_syscall + #define mtk_is_compat_task in_compat_syscall +#else + #define mtk_is_compat_task is_compat_task +#endif +#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; + int err = 0; + /* prNetDev is verified in the caller function wlanDoIOCTL() */ + +#ifdef CONFIG_COMPAT + struct compat_iw_point *iwp_compat; + union iwreq_data wrq_data; + + iwp_compat = (struct compat_iw_point *)&prIwReq->u.data; + wrq_data.data.pointer = compat_ptr(iwp_compat->pointer); + wrq_data.data.length = iwp_compat->length; + wrq_data.data.flags = iwp_compat->flags; +#endif /* CONFIG_COMPAT */ + + /* 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() */ +#ifdef CONFIG_COMPAT + if (mtk_is_compat_task()) + /* User space is 32-bit, use compat ioctl */ + err = priv_set_int(prNetDev, &rIwReqInfo, &(wrq_data), + (char *)&(wrq_data)); +#else + err = priv_set_int(prNetDev, &rIwReqInfo, &(prIwReq->u), + (char *)&(prIwReq->u)); +#endif + break; + + case IOCTL_GET_INT: + /* NOTE(Kevin): 1/3 INT Type <= IFNAMSIZ, so we don't need copy_from/to_user() */ +#ifdef CONFIG_COMPAT + if (mtk_is_compat_task()) + /* User space is 32-bit, use compat ioctl */ + err = priv_get_int(prNetDev, &rIwReqInfo, &wrq_data, + (char *)&(wrq_data)); +#else + err = priv_get_int(prNetDev, &rIwReqInfo, &(prIwReq->u), + (char *)&(prIwReq->u)); +#endif + break; + + case IOCTL_SET_STRUCT: + case IOCTL_SET_STRUCT_FOR_EM: +#ifdef CONFIG_COMPAT + if (mtk_is_compat_task()) + /* User space is 32-bit, use compat ioctl */ + err = priv_set_struct(prNetDev, &rIwReqInfo, &wrq_data, + (char *)&(wrq_data)); +#else + err = priv_set_struct(prNetDev, &rIwReqInfo, &(prIwReq->u), + (char *)&(prIwReq->u)); +#endif + break; + + case IOCTL_GET_STRUCT: +#ifdef CONFIG_COMPAT + if (mtk_is_compat_task()) + /* User space is 32-bit, use compat ioctl */ + err = priv_get_struct(prNetDev, &rIwReqInfo, &wrq_data, + (char *)&(wrq_data)); +#else + err = priv_get_struct(prNetDev, &rIwReqInfo, &(prIwReq->u), + (char *)&(prIwReq->u)); +#endif + break; + +#if (CFG_SUPPORT_QA_TOOL) + case IOCTL_QA_TOOL_DAEMON: +#ifdef CONFIG_COMPAT + if (mtk_is_compat_task()) + /* User space is 32-bit, use compat ioctl */ + err = priv_qa_agent(prNetDev, &rIwReqInfo, &wrq_data, + (char *)&(wrq_data)); +#else + err = priv_qa_agent(prNetDev, &rIwReqInfo, &(prIwReq->u), + (char *)&(prIwReq->u)); +#endif + break; +#endif + + case IOCTL_GET_STR: + + default: +#ifdef CONFIG_COMPAT + iwp_compat->pointer = ptr_to_compat(wrq_data.data.pointer); + iwp_compat->length = wrq_data.data.length; + iwp_compat->flags = wrq_data.data.flags; +#endif + return -EOPNOTSUPP; + + } /* end of switch */ +#ifdef CONFIG_COMPAT + iwp_compat->pointer = ptr_to_compat(wrq_data.data.pointer); + iwp_compat->length = wrq_data.data.length; + iwp_compat->flags = wrq_data.data.flags; +#endif + return err; +} /* priv_support_ioctl */ + +#if CFG_SUPPORT_BATCH_SCAN + +EVENT_BATCH_RESULT_T g_rEventBatchResult[CFG_BATCH_MAX_MSCAN]; + +UINT_32 batchChannelNum2Freq(UINT_32 u4ChannelNum) +{ + UINT_32 u4ChannelInMHz; + + if (u4ChannelNum >= 1 && u4ChannelNum <= 13) + u4ChannelInMHz = 2412 + (u4ChannelNum - 1) * 5; + else if (u4ChannelNum == 14) + u4ChannelInMHz = 2484; + else if (u4ChannelNum == 133) + u4ChannelInMHz = 3665; /* 802.11y */ + else if (u4ChannelNum == 137) + u4ChannelInMHz = 3685; /* 802.11y */ + else if (u4ChannelNum >= 34 && u4ChannelNum <= 165) + u4ChannelInMHz = 5000 + u4ChannelNum * 5; + else if (u4ChannelNum >= 183 && u4ChannelNum <= 196) + u4ChannelInMHz = 4000 + u4ChannelNum * 5; + else + u4ChannelInMHz = 0; + + return u4ChannelInMHz; +} + +#define TMP_TEXT_LEN_S 40 +#define TMP_TEXT_LEN_L 60 +static UCHAR text1[TMP_TEXT_LEN_S], text2[TMP_TEXT_LEN_L], text3[TMP_TEXT_LEN_L]; /* A safe len */ + +WLAN_STATUS +batchConvertResult(IN P_EVENT_BATCH_RESULT_T prEventBatchResult, + OUT PVOID pvBuffer, IN UINT_32 u4MaxBufferLen, OUT PUINT_32 pu4RetLen) +{ + CHAR *p = pvBuffer; + CHAR ssid[ELEM_MAX_LEN_SSID + 1]; + INT_32 nsize, nsize1, nsize2, nsize3, scancount; + INT_32 i, j, nleft; + UINT_32 freq; + + P_EVENT_BATCH_RESULT_ENTRY_T prEntry; + P_EVENT_BATCH_RESULT_T pBr; + + nsize = 0; + nleft = u4MaxBufferLen; + + pBr = prEventBatchResult; + scancount = 0; + for (j = 0; j < CFG_BATCH_MAX_MSCAN; j++) { + scancount += pBr->ucScanCount; + pBr++; + } + + nsize1 = scnprintf(text1, TMP_TEXT_LEN_S, + "scancount=%d\nnextcount=%d\n", + scancount, scancount); + if (nsize1 < nleft) { + nsize1 = scnprintf(p, nleft, "%s", text1); + p += nsize1; + nleft -= nsize1; + } else + goto short_buf; + + pBr = prEventBatchResult; + for (j = 0; j < CFG_BATCH_MAX_MSCAN; j++) { + DBGLOG(SCN, TRACE, "convert mscan = %d, apcount=%d, nleft=%d\n", j, pBr->ucScanCount, nleft); + + if (pBr->ucScanCount == 0) { + pBr++; + continue; + } + + nleft -= 5; /* -5 for "####\n" */ + + /* We only support one round scan result now. */ + nsize1 = scnprintf(text1, TMP_TEXT_LEN_S, "apcount=%d\n", pBr->ucScanCount); + if (nsize1 < nleft) { + nsize1 = scnprintf(p, nleft, "%s", text1); + p += nsize1; + nleft -= nsize1; + } else + goto short_buf; + + for (i = 0; i < pBr->ucScanCount; i++) { + prEntry = &pBr->arBatchResult[i]; + + nsize1 = scnprintf(text1, TMP_TEXT_LEN_S, "bssid=" MACSTR "\n", + MAC2STR(prEntry->aucBssid)); + kalMemCopy(ssid, + prEntry->aucSSID, + (prEntry->ucSSIDLen < ELEM_MAX_LEN_SSID ? prEntry->ucSSIDLen : ELEM_MAX_LEN_SSID)); + ssid[(prEntry->ucSSIDLen < + (ELEM_MAX_LEN_SSID - 1) ? prEntry->ucSSIDLen : (ELEM_MAX_LEN_SSID - 1))] = '\0'; + nsize2 = scnprintf(text2, TMP_TEXT_LEN_L, "ssid=%s\n", ssid); + + freq = batchChannelNum2Freq(prEntry->ucFreq); + nsize3 = + scnprintf(text3, TMP_TEXT_LEN_L, + "freq=%u\nlevel=%d\ndist=%u\ndistSd=%u\n===\n", + freq, prEntry->cRssi, prEntry->u4Dist, + prEntry->u4Distsd); + + nsize = nsize1 + nsize2 + nsize3; + if (nsize < nleft) { + + kalStrnCpy(p, text1, TMP_TEXT_LEN_S); + p += nsize1; + + kalStrnCpy(p, text2, TMP_TEXT_LEN_L); + p += nsize2; + + kalStrnCpy(p, text3, TMP_TEXT_LEN_L); + p += nsize3; + + nleft -= nsize; + } else { + DBGLOG(SCN, TRACE, "Warning: Early break! (%d)\n", i); + break; /* discard following entries, TODO: apcount? */ + } + } + + nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "%s", "####\n"); + if (nsize1 < nleft) { + nsize1 = scnprintf(p, nleft, "%s", text1); + p += nsize1; + nleft -= nsize1; + } else + goto short_buf; + + pBr++; + } + + nsize1 = scnprintf(text1, TMP_TEXT_LEN_S, "%s", "----\n"); + if (nsize1 < nleft) + scnprintf(p, nleft, "%s", text1); + else + goto short_buf; + + *pu4RetLen = u4MaxBufferLen - nleft; + DBGLOG(SCN, TRACE, "total len = %d (max len = %d)\n", *pu4RetLen, u4MaxBufferLen); + + return WLAN_STATUS_SUCCESS; + +short_buf: + DBGLOG(SCN, TRACE, + "Short buffer issue! %d > %d, %s\n", + u4MaxBufferLen + (nsize - nleft), + u4MaxBufferLen, (char *)pvBuffer); + return WLAN_STATUS_INVALID_LENGTH; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \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 (GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (prGlueInfo == NULL || prGlueInfo->u4ReadyFlag == 0) { + DBGLOG(REQ, INFO, "adapter is not ready\n"); + return -EIO; + } + + 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 if (pu4IntBuf[1] == PRIV_CMD_TEST_MAGIC_KEY_ICAP) { + prNdisReq->ndisOidCmd = OID_CUSTOM_TEST_ICAP_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; + } + + if (pu4IntBuf[1] == PRIV_CMD_TEST_MAGIC_KEY && pu4IntBuf[2] == PRIV_CMD_TEST_MAGIC_KEY) { + 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: + /* pu4IntBuf[0] is used as input SubCmd */ + rStatus = wlanSetInformation(prGlueInfo->prAdapter, wlanoidSetBeaconInterval, (PVOID)&pu4IntBuf[1], + 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, &u4BufLen) == WLAN_STATUS_SUCCESS) { + if (pu4IntBuf[1] == 1) + prNetDev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM; + else if (pu4IntBuf[1] == 0) + prNetDev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM); + } + } + break; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + case PRIV_CMD_POWER_MODE: + { + PARAM_POWER_MODE_T rPowerMode; + + P_BSS_INFO_T prBssInfo = prGlueInfo->prAdapter->prAisBssInfo; + + if (!prBssInfo) + break; + + rPowerMode.ePowerMode = (PARAM_POWER_MODE) pu4IntBuf[1]; + rPowerMode.ucBssIdx = prBssInfo->ucBssIndex; + + /* pu4IntBuf[0] is used as input SubCmd */ + kalIoctl(prGlueInfo, wlanoidSet802dot11PowerSaveProfile, &rPowerMode, + sizeof(PARAM_POWER_MODE_T), FALSE, FALSE, TRUE, &u4BufLen); + } + break; + + case PRIV_CMD_WMM_PS: + { + PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T rWmmPsTest; + + rWmmPsTest.bmfgApsdEnAc = (UINT_8) pu4IntBuf[1]; + rWmmPsTest.ucIsEnterPsAtOnce = (UINT_8) pu4IntBuf[2]; + rWmmPsTest.ucIsDisableUcTrigger = (UINT_8) pu4IntBuf[3]; + rWmmPsTest.reserved = 0; + + kalIoctl(prGlueInfo, + wlanoidSetWiFiWmmPsTest, + (PVOID)&rWmmPsTest, + sizeof(PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T), FALSE, FALSE, TRUE, &u4BufLen); + } + break; + +#if 0 + case PRIV_CMD_ADHOC_MODE: + /* pu4IntBuf[0] is used as input SubCmd */ + rStatus = wlanSetInformation(prGlueInfo->prAdapter, wlanoidSetAdHocMode, (PVOID)&pu4IntBuf[1], + sizeof(UINT_32), &u4BufLen); + break; +#endif + + case PRIV_CUSTOM_BWCS_CMD: + + DBGLOG(REQ, INFO, + "pu4IntBuf[1] = %x, size of PTA_IPC_T = %zu.\n", + pu4IntBuf[1], sizeof(PARAM_PTA_IPC_T)); + + prPtaIpc = (P_PTA_IPC_T) aucOidBuf; + prPtaIpc->u.aucBTPParams[0] = (UINT_8) (pu4IntBuf[1] >> 24); + prPtaIpc->u.aucBTPParams[1] = (UINT_8) (pu4IntBuf[1] >> 16); + prPtaIpc->u.aucBTPParams[2] = (UINT_8) (pu4IntBuf[1] >> 8); + prPtaIpc->u.aucBTPParams[3] = (UINT_8) (pu4IntBuf[1]); + + DBGLOG(REQ, INFO, + "BCM BWCS CMD : PRIV_CUSTOM_BWCS_CMD : aucBTPParams[0] = %02x, aucBTPParams[1] = %02x.\n", + prPtaIpc->u.aucBTPParams[0], prPtaIpc->u.aucBTPParams[1]); + DBGLOG(REQ, INFO, + "BCM BWCS CMD : PRIV_CUSTOM_BWCS_CMD : aucBTPParams[2] = %02x, aucBTPParams[3] = %02x.\n", + 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 (status != WLAN_STATUS_SUCCESS) + status = -EFAULT; + + break; + + case PRIV_CMD_BAND_CONFIG: + { + DBGLOG(INIT, INFO, "CMD set_band = %u\n", + (UINT_32) pu4IntBuf[1]); + } + break; + +#if CFG_ENABLE_WIFI_DIRECT + case PRIV_CMD_P2P_MODE: + { + PARAM_CUSTOM_P2P_SET_STRUCT_T rSetP2P; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + rSetP2P.u4Enable = pu4IntBuf[1]; + rSetP2P.u4Mode = pu4IntBuf[2]; +#if 1 + if (!rSetP2P.u4Enable) + p2pNetUnregister(prGlueInfo, TRUE); + + /* pu4IntBuf[0] is used as input SubCmd */ + rWlanStatus = kalIoctl(prGlueInfo, wlanoidSetP2pMode, (PVOID)&rSetP2P, + sizeof(PARAM_CUSTOM_P2P_SET_STRUCT_T), FALSE, FALSE, TRUE, &u4BufLen); + + if ((rSetP2P.u4Enable) && (rWlanStatus == WLAN_STATUS_SUCCESS)) + p2pNetRegister(prGlueInfo, TRUE); +#endif + + } + break; +#endif + +#if (CFG_MET_PACKET_TRACE_SUPPORT == 1) + case PRIV_CMD_MET_PROFILING: + { + /* PARAM_CUSTOM_WFD_DEBUG_STRUCT_T rWfdDebugModeInfo; */ + /* rWfdDebugModeInfo.ucWFDDebugMode=(UINT_8)pu4IntBuf[1]; */ + /* rWfdDebugModeInfo.u2SNPeriod=(UINT_16)pu4IntBuf[2]; */ + /* DBGLOG(REQ, INFO, ("WFD Debug Mode:%d Period:%d\n", + * rWfdDebugModeInfo.ucWFDDebugMode, rWfdDebugModeInfo.u2SNPeriod)); + */ + prGlueInfo->fgMetProfilingEn = (UINT_8) pu4IntBuf[1]; + prGlueInfo->u2MetUdpPort = (UINT_16) pu4IntBuf[2]; + /* DBGLOG(INIT, INFO, ("MET_PROF: Enable=%d UDP_PORT=%d\n", + * prGlueInfo->fgMetProfilingEn, prGlueInfo->u2MetUdpPort); + */ + + } + 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[MAX_CHN_NUM]; + + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + if (GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (prGlueInfo == NULL || prGlueInfo->u4ReadyFlag == 0) { + DBGLOG(REQ, INFO, "adapter is not ready\n"); + return -EIO; + } + + 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 = sizeof(PARAM_CUSTOM_MEM_DUMP_STRUCT_T); + prNdisReq->outNdisOidLength = sizeof(PARAM_CUSTOM_MEM_DUMP_STRUCT_T); + + 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 = MAX_CHN_NUM; + UINT_8 ucMaxChannelNum = MAX_CHN_NUM; + RF_CHANNEL_INFO_T aucChannelList[MAX_CHN_NUM]; + + DBGLOG(RLM, INFO, "Domain: Query Channel List.\n"); + kalGetChannelList(prGlueInfo, BAND_NULL, ucMaxChannelNum, &NumOfChannel, aucChannelList); + if (NumOfChannel > MAX_CHN_NUM) + NumOfChannel = MAX_CHN_NUM; + + 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, u4CmdLen; + P_GLUE_INFO_T prGlueInfo; + int status = 0; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_SET_TXPWR_CTRL_T prTxpwr; + UINT_16 i = 0; + INT_32 setting[4] = {0}; + + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + + if (GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + u4SubCmd = (UINT_32) prIwReqData->data.flags; + u4CmdLen = prIwReqData->data.length; + + switch (u4SubCmd) { + case PRIV_CMD_SET_TX_POWER: + { + if (u4CmdLen > 4) + return -EINVAL; + if (copy_from_user(setting, + prIwReqData->data.pointer, u4CmdLen)) + return -EFAULT; + + 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), FALSE, FALSE, TRUE, &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[MAX_CHN_NUM]; + + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + if (GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (prGlueInfo == NULL || prGlueInfo->u4ReadyFlag == 0) { + DBGLOG(REQ, INFO, "adapter is not ready\n"); + return -EIO; + } + + u4SubCmd = (UINT_32) prIwReqData->data.flags; + + switch (u4SubCmd) { + case PRIV_CMD_GET_CH_LIST: + { + UINT_16 i; + UINT_8 NumOfChannel = MAX_CHN_NUM; + UINT_8 ucMaxChannelNum = MAX_CHN_NUM; + RF_CHANNEL_INFO_T aucChannelList[MAX_CHN_NUM]; + + kalGetChannelList(prGlueInfo, BAND_NULL, ucMaxChannelNum, &NumOfChannel, aucChannelList); + if (NumOfChannel > MAX_CHN_NUM) + NumOfChannel = MAX_CHN_NUM; + + 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 (GLUE_CHK_PR2(prNetDev, prIwReqData) == FALSE) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (prGlueInfo == NULL || prGlueInfo->u4ReadyFlag == 0) { + DBGLOG(REQ, INFO, "adapter is not ready\n"); + return -EIO; + } + + u4SubCmd = (UINT_32) prIwReqData->data.flags; + +#if 0 + DBGLOG(INIT, INFO, "priv_set_struct(): prIwReqInfo->cmd(0x%X), u4SubCmd(%ld)\n", prIwReqInfo->cmd, u4SubCmd); +#endif + + switch (u4SubCmd) { +#if 0 /* PTA_ENABLED */ + case PRIV_CMD_BT_COEXIST: + u4CmdLen = prIwReqData->data.length * sizeof(UINT_32); + ASSERT(sizeof(PARAM_CUSTOM_BT_COEXIST_T) >= u4CmdLen); + if (sizeof(PARAM_CUSTOM_BT_COEXIST_T) < u4CmdLen) + return -EFAULT; + + if (copy_from_user(&aucOidBuf[0], prIwReqData->data.pointer, u4CmdLen)) { + status = -EFAULT; /* return -EFAULT; */ + break; + } + + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetBtCoexistCtrl, (PVOID)&aucOidBuf[0], u4CmdLen, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + 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 (status != WLAN_STATUS_SUCCESS) + status = -EFAULT; + + break; + +#if CFG_SUPPORT_WPS2 + case PRIV_CMD_WSC_PROBE_REQ: + { + if (prIwReqData->data.length > + (sizeof(prGlueInfo->aucWSCIE)/sizeof(UINT_8))) { + status = -EINVAL; + break; + } + /* 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 (prIwReqData->data.length > + (sizeof(aucOidBuf)/sizeof(UINT_8))) { + status = -EINVAL; + break; + } + if (copy_from_user(&aucOidBuf[0], prIwReqData->data.pointer, prIwReqData->data.length)) { + status = -EFAULT; + break; + } + if (!kalMemCmp(&aucOidBuf[0], pcExtra, prIwReqData->data.length)) { + /* ToDo:: DBGLOG */ + 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; + PUINT_8 prDest = 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 (prGlueInfo == NULL || prGlueInfo->u4ReadyFlag == 0) { + DBGLOG(REQ, INFO, "adapter is not ready\n"); + return -EIO; + } + +#if 0 + DBGLOG(INIT, INFO, "priv_get_struct(): prIwReqInfo->cmd(0x%X), u4SubCmd(%ld)\n", prIwReqInfo->cmd, u4SubCmd); +#endif + memset(aucOidBuf, 0, sizeof(aucOidBuf)); + + switch (u4SubCmd) { + case PRIV_CMD_OID: + if (copy_from_user(&aucOidBuf[0], prIwReqData->data.pointer, sizeof(NDIS_TRANSPORT_STRUCT))) { + DBGLOG(REQ, INFO, "priv_get_struct() copy_from_user oidBuf fail\n"); + return -EFAULT; + } + + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; +#if 0 + DBGLOG(INIT, INFO, "\n priv_get_struct cmd 0x%02x len:%d OID:0x%08x OID Len:%d\n", cmd, + pIwReq->u.data.length, ndisReq->ndisOidCmd, ndisReq->inNdisOidlength); +#endif + if (priv_get_ndis(prNetDev, prNdisReq, &u4BufLen) == 0) { + prNdisReq->outNdisOidLength = u4BufLen; + kalMemCopy(pcExtra, prNdisReq, + u4BufLen + sizeof(NDIS_TRANSPORT_STRUCT) - + sizeof(prNdisReq->ndisOidContent)); + if (copy_to_user(prIwReqData->data.pointer, + &aucOidBuf[0], + u4BufLen + sizeof(NDIS_TRANSPORT_STRUCT) - + sizeof(prNdisReq->ndisOidContent))) { + DBGLOG(REQ, INFO, "priv_get_struct() copy_to_user oidBuf fail(1)\n"); + return -EFAULT; + } + return 0; + } + prNdisReq->outNdisOidLength = u4BufLen; + if (copy_to_user(prIwReqData->data.pointer, + &aucOidBuf[0], OFFSET_OF(NDIS_TRANSPORT_STRUCT, ndisOidContent))) { + DBGLOG(REQ, INFO, "priv_get_struct() copy_to_user oidBuf fail(2)\n"); + } + return -EFAULT; + + case PRIV_CMD_SW_CTRL: + pu4IntBuf = (PUINT_32) prIwReqData->data.pointer; + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + prDest = (PUINT_8) &aucOidBuf[OFFSET_OF(NDIS_TRANSPORT_STRUCT, ndisOidContent)]; + + if (prIwReqData->data.length > (sizeof(aucOidBuf) - OFFSET_OF(NDIS_TRANSPORT_STRUCT, ndisOidContent))) { + DBGLOG(REQ, INFO, "priv_get_struct() exceeds length limit\n"); + return -EFAULT; + } + + if (copy_from_user(prDest, 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)) + DBGLOG(REQ, INFO, "priv_get_struct() copy_to_user oidBuf fail(2)\n"); + } + return 0; + default: + DBGLOG(REQ, WARN, "get struct cmd:0x%x\n", u4SubCmd); + return -EOPNOTSUPP; + } +} /* priv_get_struct */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The routine handles a set operation for a single OID. +* +* \param[in] pDev Net device requested. +* \param[in] ndisReq Ndis request OID information copy from user. +* \param[out] outputLen_p If the call is successful, returns the number of +* bytes written into the query buffer. If the +* call failed due to invalid length of the query +* buffer, returns the amount of storage needed.. +* +* \retval 0 On success. +* \retval -EOPNOTSUPP If cmd is not supported. +* +*/ +/*----------------------------------------------------------------------------*/ +static int +priv_set_ndis(IN struct net_device *prNetDev, IN NDIS_TRANSPORT_STRUCT * prNdisReq, OUT PUINT_32 pu4OutputLen) +{ + P_WLAN_REQ_ENTRY prWlanReqEntry = NULL; + WLAN_STATUS status = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4SetInfoLen = 0; + + ASSERT(prNetDev); + ASSERT(prNdisReq); + ASSERT(pu4OutputLen); + + if (!prNetDev || !prNdisReq || !pu4OutputLen) { + DBGLOG(REQ, INFO, "priv_set_ndis(): invalid param(0x%p, 0x%p, 0x%p)\n", + prNetDev, prNdisReq, pu4OutputLen); + return -EINVAL; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, "priv_set_ndis(): invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, *((P_GLUE_INFO_T *) netdev_priv(prNetDev))); + return -EINVAL; + } +#if 0 + DBGLOG(INIT, INFO, "priv_set_ndis(): prNdisReq->ndisOidCmd(0x%lX)\n", prNdisReq->ndisOidCmd); +#endif + + if (reqSearchSupportedOidEntry(prNdisReq->ndisOidCmd, &prWlanReqEntry) == FALSE) { + /* WARNLOG(("Set OID: 0x%08lx (unknown)\n", prNdisReq->ndisOidCmd)); */ + return -EOPNOTSUPP; + } + + if (prWlanReqEntry->pfOidSetHandler == NULL) { + /* WARNLOG(("Set %s: Null set handler\n", prWlanReqEntry->pucOidName)); */ + return -EOPNOTSUPP; + } +#if 0 + DBGLOG(INIT, INFO, "priv_set_ndis(): %s\n", prWlanReqEntry->pucOidName); +#endif + + if (prWlanReqEntry->fgSetBufLenChecking) { + if (prNdisReq->inNdisOidlength != prWlanReqEntry->u4InfoBufLen) { + DBGLOG(REQ, WARN, + "Set %s: Invalid length (current=%d, needed=%d)\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, &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 (status != WLAN_STATUS_SUCCESS) + return -EFAULT; + + return 0; +} /* priv_set_ndis */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The routine handles a query operation for a single OID. Basically we +* return information about the current state of the OID in question. +* +* \param[in] pDev Net device requested. +* \param[in] ndisReq Ndis request OID information copy from user. +* \param[out] outputLen_p If the call is successful, returns the number of +* bytes written into the query buffer. If the +* call failed due to invalid length of the query +* buffer, returns the amount of storage needed.. +* +* \retval 0 On success. +* \retval -EOPNOTSUPP If cmd is not supported. +* \retval -EINVAL invalid input parameters +* +*/ +/*----------------------------------------------------------------------------*/ +static int +priv_get_ndis(IN struct net_device *prNetDev, IN NDIS_TRANSPORT_STRUCT * prNdisReq, OUT PUINT_32 pu4OutputLen) +{ + P_WLAN_REQ_ENTRY prWlanReqEntry = NULL; + UINT_32 u4BufLen = 0; + WLAN_STATUS status = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prNetDev); + ASSERT(prNdisReq); + ASSERT(pu4OutputLen); + + if (!prNetDev || !prNdisReq || !pu4OutputLen) { + DBGLOG(REQ, INFO, "priv_get_ndis(): invalid param(0x%p, 0x%p, 0x%p)\n", + prNetDev, prNdisReq, pu4OutputLen); + return -EINVAL; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, "priv_get_ndis(): invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, *((P_GLUE_INFO_T *) netdev_priv(prNetDev))); + return -EINVAL; + } +#if 0 + DBGLOG(INIT, INFO, "priv_get_ndis(): prNdisReq->ndisOidCmd(0x%lX)\n", prNdisReq->ndisOidCmd); +#endif + + if (reqSearchSupportedOidEntry(prNdisReq->ndisOidCmd, &prWlanReqEntry) == FALSE) { + /* WARNLOG(("Query OID: 0x%08lx (unknown)\n", prNdisReq->ndisOidCmd)); */ + return -EOPNOTSUPP; + } + + if (prWlanReqEntry->pfOidQueryHandler == NULL) { + /* WARNLOG(("Query %s: Null query handler\n", prWlanReqEntry->pucOidName)); */ + return -EOPNOTSUPP; + } +#if 0 + DBGLOG(INIT, INFO, "priv_get_ndis(): %s\n", prWlanReqEntry->pucOidName); +#endif + + if (prWlanReqEntry->fgQryBufLenChecking) { + if (prNdisReq->inNdisOidlength < prWlanReqEntry->u4InfoBufLen) { + /* Not enough room in InformationBuffer. Punt */ + /* WARNLOG(("Query %s: Buffer too short (current=%ld, needed=%ld)\n", */ + /* prWlanReqEntry->pucOidName, */ + /* prNdisReq->inNdisOidlength, */ + /* prWlanReqEntry->u4InfoBufLen)); */ + + *pu4OutputLen = prWlanReqEntry->u4InfoBufLen; + + status = WLAN_STATUS_INVALID_LENGTH; + return -EINVAL; + } + } + + if (prWlanReqEntry->eOidMethod == ENUM_OID_GLUE_ONLY) { + /* GLUE sw info only */ + status = prWlanReqEntry->pfOidQueryHandler(prGlueInfo, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, &u4BufLen); + } else if (prWlanReqEntry->eOidMethod == ENUM_OID_GLUE_EXTENSION) { + /* multiple sw operations */ + status = prWlanReqEntry->pfOidQueryHandler(prGlueInfo, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, &u4BufLen); + } else if (prWlanReqEntry->eOidMethod == ENUM_OID_DRIVER_CORE) { + /* driver core */ + + status = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC) prWlanReqEntry->pfOidQueryHandler, + prNdisReq->ndisOidContent, prNdisReq->inNdisOidlength, TRUE, TRUE, TRUE, &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 (status != WLAN_STATUS_SUCCESS) + return -EOPNOTSUPP; + + return 0; +} /* priv_get_ndis */ + +#if CFG_SUPPORT_QA_TOOL +/*----------------------------------------------------------------------------*/ +/*! +* \brief The routine handles ATE set operation. +* +* \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 -EFAULT If copy from user space buffer fail. +* +*/ +/*----------------------------------------------------------------------------*/ +int +priv_ate_set(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) +{ + P_GLUE_INFO_T GlueInfo; + INT_32 i4Status; + UINT_8 *InBuf; + /* UINT_8 *addr_str, *value_str; */ + UINT_32 InBufLen; + UINT_32 u4SubCmd; + /* BOOLEAN isWrite = 0; + *UINT_32 u4BufLen = 0; + *P_NDIS_TRANSPORT_STRUCT prNdisReq; + *UINT_32 pu4IntBuf[2]; + */ + + /* sanity check */ + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + + /* init */ + DBGLOG(REQ, INFO, "priv_set_string (%s)(%d)\n", + (UINT_8 *) prIwReqData->data.pointer, (INT_32) prIwReqData->data.length); + + if (GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra) == FALSE) + return -EINVAL; + + GlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (GlueInfo == NULL || GlueInfo->u4ReadyFlag == 0) { + DBGLOG(REQ, INFO, "adapter is not ready\n"); + return -EIO; + } + + u4SubCmd = (UINT_32) prIwReqData->data.flags; + + DBGLOG(REQ, INFO, "MT6632 : priv_ate_set u4SubCmd = %d\n", u4SubCmd); + + switch (u4SubCmd) { + case PRIV_QACMD_SET: + DBGLOG(REQ, INFO, "MT6632 : priv_ate_set PRIV_QACMD_SET\n"); + InBuf = aucOidBuf; + InBufLen = prIwReqData->data.length; + i4Status = 0; + + if (copy_from_user(InBuf, prIwReqData->data.pointer, prIwReqData->data.length)) + return -EFAULT; + i4Status = AteCmdSetHandle(prNetDev, InBuf, InBufLen); + break; + + default: + return -EOPNOTSUPP; + } + return 0; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \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 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Private ioctl driver 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_set_driver(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + UINT_32 u4SubCmd = 0; + UINT_16 u2Cmd = 0; + + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4BytesWritten = 0; + + ASSERT(prNetDev); + ASSERT(prIwReqData); + if (!prNetDev || !prIwReqData) { + DBGLOG(REQ, INFO, "priv_set_driver(): invalid param(0x%p, 0x%p)\n", prNetDev, prIwReqData); + return -EINVAL; + } + + u2Cmd = prIwReqInfo->cmd; + DBGLOG(REQ, INFO, "prIwReqInfo->cmd %u\n", u2Cmd); + + u4SubCmd = (UINT_32) prIwReqData->data.flags; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, "priv_set_driver(): invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, *((P_GLUE_INFO_T *) netdev_priv(prNetDev))); + return -EINVAL; + } + + if (prGlueInfo == NULL || prGlueInfo->u4ReadyFlag == 0) { + DBGLOG(REQ, INFO, "adapter is not ready\n"); + return -EIO; + } + + /* trick,hack in ./net/wireless/wext-priv.c ioctl_private_iw_point */ + /* because the cmd number is odd (get), the input string will not be copy_to_user */ + + DBGLOG(REQ, INFO, "prIwReqData->data.length %u\n", prIwReqData->data.length); + + /* Use GET type becauase large data by iwpriv. */ + + ASSERT(IW_IS_GET(u2Cmd)); + if (prIwReqData->data.length != 0) { + if (!access_ok(VERIFY_READ, prIwReqData->data.pointer, prIwReqData->data.length)) { + DBGLOG(REQ, INFO, "%s access_ok Read fail written = %d\n", __func__, i4BytesWritten); + return -EFAULT; + } + if (copy_from_user(pcExtra, prIwReqData->data.pointer, prIwReqData->data.length)) { + DBGLOG(REQ, INFO, "%s copy_form_user fail written = %d\n", __func__, prIwReqData->data.length); + return -EFAULT; + } + } + + if (pcExtra) { + DBGLOG(REQ, INFO, "pcExtra %s\n", pcExtra); + /* Please check max length in rIwPrivTable */ + DBGLOG(REQ, INFO, "%s prIwReqData->data.length = %d\n", __func__, prIwReqData->data.length); + i4BytesWritten = priv_driver_cmds(prNetDev, pcExtra, 2000 /*prIwReqData->data.length */); + DBGLOG(REQ, INFO, "%s i4BytesWritten = %d\n", __func__, i4BytesWritten); + } + + DBGLOG(REQ, INFO, "pcExtra done\n"); + + if (i4BytesWritten > 0) { + + if (i4BytesWritten > 2000) + i4BytesWritten = 2000; + prIwReqData->data.length = i4BytesWritten; /* the iwpriv will use the length */ + + } else if (i4BytesWritten == 0) { + prIwReqData->data.length = i4BytesWritten; + } +#if 0 + /* trick,hack in ./net/wireless/wext-priv.c ioctl_private_iw_point */ + /* because the cmd number is even (set), the return string will not be copy_to_user */ + ASSERT(IW_IS_SET(u2Cmd)); + if (!access_ok(VERIFY_WRITE, prIwReqData->data.pointer, i4BytesWritten)) { + DBGLOG(REQ, INFO, "%s access_ok Write fail written = %d\n", __func__, i4BytesWritten); + return -EFAULT; + } + if (copy_to_user(prIwReqData->data.pointer, pcExtra, i4BytesWritten)) { + DBGLOG(REQ, INFO, "%s copy_to_user fail written = %d\n", __func__, i4BytesWritten); + return -EFAULT; + } + DBGLOG(RSN, INFO, "%s copy_to_user written = %d\n", __func__, i4BytesWritten); +#endif + return 0; + +} /* priv_set_driver */ +#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; +} + +#define CMD_START "START" +#define CMD_STOP "STOP" +#define CMD_SCAN_ACTIVE "SCAN-ACTIVE" +#define CMD_SCAN_PASSIVE "SCAN-PASSIVE" +#define CMD_RSSI "RSSI" +#define CMD_LINKSPEED "LINKSPEED" +#define CMD_RXFILTER_START "RXFILTER-START" +#define CMD_RXFILTER_STOP "RXFILTER-STOP" +#define CMD_RXFILTER_ADD "RXFILTER-ADD" +#define CMD_RXFILTER_REMOVE "RXFILTER-REMOVE" +#define CMD_BTCOEXSCAN_START "BTCOEXSCAN-START" +#define CMD_BTCOEXSCAN_STOP "BTCOEXSCAN-STOP" +#define CMD_BTCOEXMODE "BTCOEXMODE" +#define CMD_SETSUSPENDOPT "SETSUSPENDOPT" +#define CMD_SETSUSPENDMODE "SETSUSPENDMODE" +#define CMD_P2P_DEV_ADDR "P2P_DEV_ADDR" +#define CMD_SETFWPATH "SETFWPATH" +#define CMD_SETBAND "SETBAND" +#define CMD_GETBAND "GETBAND" +#define CMD_AP_START "AP_START" + +#if CFG_SUPPORT_QA_TOOL +#define CMD_GET_RX_STATISTICS "GET_RX_STATISTICS" +#endif +#define CMD_GET_STAT "GET_STAT" +#define CMD_GET_BSS_STATISTICS "GET_BSS_STATISTICS" +#define CMD_GET_STA_STATISTICS "GET_STA_STATISTICS" +#define CMD_GET_WTBL_INFO "GET_WTBL" +#define CMD_GET_MIB_INFO "GET_MIB" +#if CFG_SUPPORT_LAST_SEC_MCS_INFO +#define CMD_GET_MCS_INFO "GET_MCS_INFO" +#endif +#define CMD_GET_STA_INFO "GET_STA" +#define CMD_SET_FW_LOG "SET_FWLOG" +#define CMD_GET_QUE_INFO "GET_QUE" +#define CMD_GET_MEM_INFO "GET_MEM" +#define CMD_GET_HIF_INFO "GET_HIF" +#define CMD_GET_STA_KEEP_CNT "KEEPCOUNTER" +#define CMD_STAT_RESET_CNT "RESETCOUNTER" +#define CMD_STAT_NOISE_SEL "NOISESELECT" +#define CMD_STAT_GROUP_SEL "GROUP" + + +#define CMD_SET_TXPOWER "SET_TXPOWER" +#define CMD_COUNTRY "COUNTRY" +#define CMD_GET_COUNTRY "GET_COUNTRY" +#define CMD_GET_CHANNELS "GET_CHANNELS" +#define CMD_P2P_SET_NOA "P2P_SET_NOA" +#define CMD_P2P_GET_NOA "P2P_GET_NOA" +#define CMD_P2P_SET_PS "P2P_SET_PS" +#define CMD_SET_AP_WPS_P2P_IE "SET_AP_WPS_P2P_IE" +#define CMD_SETROAMMODE "SETROAMMODE" +#define CMD_MIRACAST "MIRACAST" + +#if (CFG_SUPPORT_DFS_MASTER == 1) +#define CMD_SHOW_DFS_STATE "SHOW_DFS_STATE" +#define CMD_SHOW_DFS_RADAR_PARAM "SHOW_DFS_RADAR_PARAM" +#define CMD_SHOW_DFS_HELP "SHOW_DFS_HELP" +#define CMD_SHOW_DFS_CAC_TIME "SHOW_DFS_CAC_TIME" +#endif + +#define CMD_PNOSSIDCLR_SET "PNOSSIDCLR" +#define CMD_PNOSETUP_SET "PNOSETUP " +#define CMD_PNOENABLE_SET "PNOFORCE" +#define CMD_PNODEBUG_SET "PNODEBUG" +#define CMD_WLS_BATCHING "WLS_BATCHING" + +#define CMD_OKC_SET_PMK "SET_PMK" +#define CMD_OKC_ENABLE "OKC_ENABLE" + +#define CMD_SETMONITOR "MONITOR" +#define CMD_SETBUFMODE "BUFFER_MODE" +#define CMD_SETEEPROM_MODE "EEPROM_MODE" + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +#define CMD_GET_CH_RANK_LIST "GET_CH_RANK_LIST" +#define CMD_GET_CH_DIRTINESS "GET_CH_DIRTINESS" +#endif + +#define CMD_EFUSE "EFUSE" +#define CMD_CCCR "CCCR" + + +/* miracast related definition */ +#define MIRACAST_MODE_OFF 0 +#define MIRACAST_MODE_SOURCE 1 +#define MIRACAST_MODE_SINK 2 + +#ifndef MIRACAST_AMPDU_SIZE +#define MIRACAST_AMPDU_SIZE 8 +#endif + +#ifndef MIRACAST_MCHAN_ALGO +#define MIRACAST_MCHAN_ALGO 1 +#endif + +#ifndef MIRACAST_MCHAN_BW +#define MIRACAST_MCHAN_BW 25 +#endif + +#define CMD_BAND_AUTO 0 +#define CMD_BAND_5G 1 +#define CMD_BAND_2G 2 +#define CMD_BAND_ALL 3 + +/* Mediatek private command */ +#define CMD_SET_MCR "SET_MCR" +#define CMD_GET_MCR "GET_MCR" +#define CMD_SET_DRV_MCR "SET_DRV_MCR" +#define CMD_GET_DRV_MCR "GET_DRV_MCR" +#define CMD_SET_SW_CTRL "SET_SW_CTRL" +#define CMD_GET_SW_CTRL "GET_SW_CTRL" +#define CMD_SET_CFG "SET_CFG" +#define CMD_GET_CFG "GET_CFG" +#define CMD_SET_CHIP "SET_CHIP" +#define CMD_GET_CHIP "GET_CHIP" +#define CMD_SET_DBG_LEVEL "SET_DBG_LEVEL" +#define CMD_GET_DBG_LEVEL "GET_DBG_LEVEL" +#ifdef CFG_ALPS_ANDROID_AOSP_PRIV_CMD +#define PRIV_CMD_SIZE 512 +#else +#define PRIV_CMD_SIZE 2000 +#endif /* CFG_ALPS_ANDROID_AOSP_PRIV_CMD */ +#define CMD_SET_FIXED_RATE "FixedRate" +#define CMD_GET_VERSION "VER" +#define CMD_SET_TEST_MODE "SET_TEST_MODE" +#define CMD_SET_TEST_CMD "SET_TEST_CMD" +#define CMD_GET_TEST_RESULT "GET_TEST_RESULT" +#define CMD_GET_STA_STAT "STAT" +#define CMD_GET_STA_STAT2 "STAT2" +#define CMD_GET_STA_RX_STAT "RX_STAT" +#define CMD_SET_ACL_POLICY "SET_ACL_POLICY" +#define CMD_ADD_ACL_ENTRY "ADD_ACL_ENTRY" +#define CMD_DEL_ACL_ENTRY "DEL_ACL_ENTRY" +#define CMD_SHOW_ACL_ENTRY "SHOW_ACL_ENTRY" +#define CMD_CLEAR_ACL_ENTRY "CLEAR_ACL_ENTRY" +#define CMD_GET_CURR_AR_RATE "GET_CURR_AR_RATE" +#define CMD_COEX_CONTROL "COEX_CONTROL" +#if CFG_SUPPORT_CSI +#define CMD_SET_CSI "SET_CSI" +#endif + +#if CFG_WOW_SUPPORT +#define CMD_WOW_START "WOW_START" +#define CMD_SET_WOW_ENABLE "SET_WOW_ENABLE" +#define CMD_SET_WOW_PAR "SET_WOW_PAR" +#define CMD_SET_WOW_UDP "SET_WOW_UDP" +#define CMD_SET_WOW_TCP "SET_WOW_TCP" +#define CMD_GET_WOW_PORT "GET_WOW_PORT" +#define CMD_GET_WOW_REASON "GET_WOW_REASON" +#endif +#define CMD_SET_ADV_PWS "SET_ADV_PWS" +#define CMD_SET_MDTIM "SET_MDTIM" +#define CMD_SET_LISTEN_DTIM_INTERVAL "SET_LISTEN_DTIM_INTERVAL" + +#define CMD_SET_DBDC "SET_DBDC" + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +#define CMD_SET_CALBACKUP_TEST_DRV_FW "SET_CALBACKUP_TEST_DRV_FW" +#endif + +#define CMD_SET_P2P_PS "SET_P2P_PS" +#define CMD_SET_P2P_NOA "SET_P2P_NOA" + +#define CMD_GET_CNM_INFO "GET_CNM" +#define CMD_GET_DSLP_CNT "GET_DSLEEP_CNT" + +#define CMD_GET_BSS_TABLE "BSSTABLE_RSSI" + +static UINT_8 g_ucMiracastMode = MIRACAST_MODE_OFF; + +typedef struct cmd_tlv { + char prefix; + char version; + char subver; + char reserved; +} cmd_tlv_t; + +typedef struct priv_driver_cmd_s { + char buf[PRIV_CMD_SIZE]; + int used_len; + int total_len; +} priv_driver_cmd_t; + +#ifdef CFG_ANDROID_AOSP_PRIV_CMD +struct android_wifi_priv_cmd { + char *buf; + int used_len; + int total_len; +}; +#endif /* CFG_ANDROID_AOSP_PRIV_CMD */ + +#ifdef CFG_ALPS_ANDROID_AOSP_PRIV_CMD +struct android_wifi_priv_cmd { + char buf[PRIV_CMD_SIZE]; + int used_len; + int total_len; +}; +#endif /* CFG_ALPS_ANDROID_AOSP_PRIV_CMD */ + +/* Coex Ctrl Cmd - Coex Info Content */ +struct COEX_REF_TABLE { + UINT_16 ucCoexInfoId; + char *cContent; +}; + +const struct COEX_REF_TABLE coex_ref_table[] = { + {1, "Isolation Detection Value"}, + {2, "Coex FDD Parameter"}, + {3, "Coex WMT Config"}, + {4, "Active BSSID"}, + {5, "Coex Mode"}, + {6, "Hybrid Mode"}, + {7, "Coex Iso"}, + {8, "Coex Channel Info"}, + {9, "Coex BT Profile"}, + {10, "BT Long Rx Disable WF Tx"}, + {11, "BT Port"}, + {12, "BT Tx Power"}, + {13, "TDD Band"}, + {30, "Perpkt Stat"}, + {31, "Perpkt BTHitCnt"}, + {32, "Perpkt RxProtectCtl"}, + {33, "Perpkt WfProtTime"}, + {34, "Perpkt BTDuration"}, + {35, "BtRxGainInfo"}, + {36, "BtTxPwrDist"}, + {37, "WfRxGainDist"} +}; + + +int priv_driver_get_dbg_level(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + UINT_32 u4DbgIdx, u4DbgMask; + BOOLEAN fgIsCmdAccept = FALSE; + INT_32 u4Ret = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= 2) { + /* u4DbgIdx = kalStrtoul(apcArgv[1], NULL, 0); */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4DbgIdx); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", u4Ret); + + if (wlanGetDebugLevel(u4DbgIdx, &u4DbgMask) == WLAN_STATUS_SUCCESS) { + fgIsCmdAccept = TRUE; + i4BytesWritten = + snprintf(pcCommand, i4TotalLen, + "Get DBG module[%u] log level => [0x%02x]!", + u4DbgIdx, (UINT_8) u4DbgMask); + } + } + + if (!fgIsCmdAccept) + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "Get DBG module log level failed!"); + + return i4BytesWritten; + +} /* priv_driver_get_sw_ctrl */ + + +#if CFG_SUPPORT_QA_TOOL +#if CFG_SUPPORT_BUFFER_MODE +static int priv_driver_set_eeprom_mode(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + INT_32 i4Argc = 0; + INT_32 i4BytesWritten = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + UINT_32 arg; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc >= 2) { + rStatus = kalkStrtou32(apcArgv[1], 0, &arg); + if (rStatus) { + DBGLOG(REQ, LOUD, "parse apcArgv error rStatus=%d\n", rStatus); + return -1; + } + + rStatus = priv_set_eeprom_mode(arg); + if (rStatus) { + DBGLOG(REQ, LOUD, "priv_set_eeprom_mode rStatus=%d\n", rStatus); + return -1; + } + + i4BytesWritten = + snprintf(pcCommand, i4TotalLen, "Switch eeprom source as %s", + (arg == EFUSE_MODE) ? "Efuse" : "Buffer Bin"); + } + + return i4BytesWritten; +} +static int priv_driver_set_efuse_buffer_mode(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4Argc = 0; + INT_32 i4BytesWritten = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + PARAM_CUSTOM_EFUSE_BUFFER_MODE_T *prSetEfuseBufModeInfo = NULL; +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 0) + BIN_CONTENT_T *pBinContent; + int i = 0; +#endif + PUINT_8 pucConfigBuf = NULL; + UINT_32 u4ConfigReadLen; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + pucConfigBuf = (PUINT_8) kalMemAlloc(2048, VIR_MEM_TYPE); + + if (!pucConfigBuf) { + DBGLOG(INIT, INFO, "allocate memory for pucConfigBuf failed\n"); + i4BytesWritten = -1; + goto out; + } + kalMemZero(pucConfigBuf, 2048); + u4ConfigReadLen = 0; + + if (kalReadToFile("/MT6632_eFuse_usage_table.xlsm.bin", pucConfigBuf, 2048, &u4ConfigReadLen) == 0) { + /* ToDo:: Nothing */ + } else { + DBGLOG(INIT, INFO, "can't find file\n"); + i4BytesWritten = -1; + goto out; + } + + /* pucConfigBuf */ + prSetEfuseBufModeInfo = + (PARAM_CUSTOM_EFUSE_BUFFER_MODE_T *) kalMemAlloc(sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T), VIR_MEM_TYPE); + if (prSetEfuseBufModeInfo == NULL) { + DBGLOG(INIT, INFO, "allocate memory for prSetEfuseBufModeInfo failed\n"); + i4BytesWritten = -1; + goto out; + } + kalMemZero(prSetEfuseBufModeInfo, sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T)); + + prSetEfuseBufModeInfo->ucSourceMode = 1; + prSetEfuseBufModeInfo->ucCount = (UINT_8)EFUSE_CONTENT_SIZE; + +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 0) + pBinContent = (BIN_CONTENT_T *)prSetEfuseBufModeInfo->aBinContent; + for (i = 0; i < EFUSE_CONTENT_SIZE; i++) { + pBinContent->u2Addr = i; + pBinContent->ucValue = *(pucConfigBuf + i); + + pBinContent++; + } + + for (i = 0; i < 20; i++) + DBGLOG(INIT, INFO, "%x\n", prSetEfuseBufModeInfo->aBinContent[i].ucValue); +#endif + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEfusBufferMode, + prSetEfuseBufModeInfo, sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T), FALSE, FALSE, TRUE, + &u4BufLen); + + i4BytesWritten = + snprintf(pcCommand, i4TotalLen, "set buffer mode %s", + (rStatus == WLAN_STATUS_SUCCESS) ? "success" : "fail"); +out: + if (pucConfigBuf) + kalMemFree(pucConfigBuf, VIR_MEM_TYPE, 2048); + + if (prSetEfuseBufModeInfo) + kalMemFree(prSetEfuseBufModeInfo, VIR_MEM_TYPE, + sizeof(PARAM_CUSTOM_EFUSE_BUFFER_MODE_T)); + + return i4BytesWritten; +} +#endif /* CFG_SUPPORT_BUFFER_MODE */ + +static int priv_driver_get_rx_statistics(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 u4Ret = 0; + PARAM_CUSTOM_ACCESS_RX_STAT rRxStatisticsTest; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + DBGLOG(INIT, ERROR, "MT6632 : priv_driver_get_rx_statistics\n"); + + if (i4Argc >= 2) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rRxStatisticsTest.u4SeqNum)); + rRxStatisticsTest.u4TotalNum = sizeof(PARAM_RX_STAT_T) / 4; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryRxStatistics, + &rRxStatisticsTest, sizeof(rRxStatisticsTest), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } + + return i4BytesWritten; +} +#endif /* CFG_SUPPORT_QA_TOOL */ + +#if CFG_SUPPORT_MSP +#if 0 +static int priv_driver_get_stat(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + INT_32 i4ArgNum = 2; + PARAM_GET_STA_STA_STATISTICS rQueryStaStatistics; + PARAM_RSSI rRssi; + UINT_16 u2LinkSpeed; + UINT_32 u4Per; + UINTT_8 i; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + kalMemZero(&rQueryStaStatistics, sizeof(rQueryStaStatistics)); + + if (i4Argc >= i4ArgNum) { + wlanHwAddrToBin(apcArgv[1], &rQueryStaStatistics.aucMacAddr[0]); + + rQueryStaStatistics.ucReadClear = TRUE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStaStatistics, + &rQueryStaStatistics, + sizeof(rQueryStaStatistics), TRUE, FALSE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_SUCCESS) { + rRssi = RCPI_TO_dBm(rQueryStaStatistics.ucRcpi); + u2LinkSpeed = rQueryStaStatistics.u2LinkSpeed == 0 ? 0 : rQueryStaStatistics.u2LinkSpeed/2; + + i4BytesWritten = kalScnprintf(pcCommand, i4TotalLen, "%s", "\n\nSTA Stat:\n"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "CurrentTemperature = %d\n", 0); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Tx success = %lu\n", 0); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Tx fail count = %ld, PER=%ld.%1ld%%\n", 0, 0, 0); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Rx success = %lu\n", 0); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Rx with CRC = %ld, PER=%ld.%1ld%%\n", 0, 0, 0); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Rx with PhyErr = %lu\n", 0); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Rx with PlcpErr = %lu\n", 0); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Rx drop due to out of resource= %lu\n", 0); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Rx duplicate frame = %lu\n", 0); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "False CCA = %lu\n", 0); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "RSSI = %d %d %d %d\n", 0, 0, 0, 0); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Last TX Rate = %s, %s, %s, %s, %s\n", "NA", "NA", "NA", "NA", "NA"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Last RX Rate = %s, %s, %s, %s, %s\n", "NA", "NA", "NA", "NA", "NA"); + + for (i = 0; i < 2 /* band num */; i++) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "BandIdx: = %d\n", i); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "\tRange: 1 2~5 6~15 16~22 23~33 34~49 50~57 58~64\n"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\t\t%d \t%d \t%d \t%d \t%d \t%d \t%d \t%d\n", + 0, 0, 0, 0, 0, 0, 0, 0); + } + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Tx success = %ld\n", + rQueryStaStatistics.u4TransmitCount - rQueryStaStatistics.u4TransmitFailCount); + + u4Per = rQueryStaStatistics.u4TransmitFailCount == 0 ? 0 : + (1000 * (rQueryStaStatistics.u4TransmitFailCount)) / + rQueryStaStatistics.u4TransmitCount; + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Tx fail count = %ld, PER=%ld.%1ld%%\n", + rQueryStaStatistics.u4TransmitFailCount, u4Per/10, u4Per%10); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "RSSI = %d\n", rRssi); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "LinkSpeed = %d\n", u2LinkSpeed); + } + } else + i4BytesWritten = kalScnprintf(pcCommand, i4TotalLen, "%s", "\n\nNo STA Stat:\n"); + + return i4BytesWritten; +} +#endif + + +static int priv_driver_get_sta_statistics(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + INT_32 i4ArgNum = 3; + PARAM_GET_STA_STA_STATISTICS rQueryStaStatistics; + PARAM_RSSI rRssi; + UINT_16 u2LinkSpeed; + UINT_32 u4Per; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + kalMemZero(&rQueryStaStatistics, sizeof(rQueryStaStatistics)); + rQueryStaStatistics.ucReadClear = TRUE; + + if (i4Argc >= i4ArgNum) { + if (strnicmp(apcArgv[1], CMD_GET_STA_KEEP_CNT, + strlen(CMD_GET_STA_KEEP_CNT)) == 0) { + wlanHwAddrToBin(apcArgv[2], + &rQueryStaStatistics.aucMacAddr[0]); + rQueryStaStatistics.ucReadClear = FALSE; + } else if (strnicmp(apcArgv[2], CMD_GET_STA_KEEP_CNT, + strlen(CMD_GET_STA_KEEP_CNT)) == 0) { + wlanHwAddrToBin(apcArgv[1], + &rQueryStaStatistics.aucMacAddr[0]); + rQueryStaStatistics.ucReadClear = FALSE; + } + } else { + /* Get AIS AP address for no argument */ + if (prGlueInfo->prAdapter->prAisBssInfo->prStaRecOfAP) { + COPY_MAC_ADDR(rQueryStaStatistics.aucMacAddr, + prGlueInfo->prAdapter->prAisBssInfo->prStaRecOfAP->aucMacAddr); + DBGLOG(RSN, INFO, "use ais ap "MACSTR"\n", + MAC2STR(prGlueInfo->prAdapter->prAisBssInfo->prStaRecOfAP->aucMacAddr)); + } else { + DBGLOG(RSN, INFO, "not connect to ais ap %lx\n", + prGlueInfo->prAdapter->prAisBssInfo->prStaRecOfAP); + i4BytesWritten = kalScnprintf(pcCommand, i4TotalLen, "%s", "\n\nNo STA Stat:\n"); + return i4BytesWritten; + } + + if (i4Argc == 2) { + if (strnicmp(apcArgv[1], CMD_GET_STA_KEEP_CNT, strlen(CMD_GET_STA_KEEP_CNT)) == 0) + rQueryStaStatistics.ucReadClear = FALSE; + } + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStaStatistics, + &rQueryStaStatistics, + sizeof(rQueryStaStatistics), TRUE, FALSE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_SUCCESS) { + rRssi = RCPI_TO_dBm(rQueryStaStatistics.ucRcpi); + u2LinkSpeed = rQueryStaStatistics.u2LinkSpeed == 0 ? 0 : rQueryStaStatistics.u2LinkSpeed/2; + + i4BytesWritten = kalScnprintf(pcCommand, i4TotalLen, "%s", "\n\nSTA Stat:\n"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Tx total cnt = %d\n", + rQueryStaStatistics.u4TransmitCount); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Tx success = %d\n", + rQueryStaStatistics.u4TransmitCount - rQueryStaStatistics.u4TransmitFailCount); + + u4Per = rQueryStaStatistics.u4TransmitCount == 0 ? 0 : + (1000 * (rQueryStaStatistics.u4TransmitFailCount)) / + rQueryStaStatistics.u4TransmitCount; + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Tx fail count = %d, PER=%d.%1d%%\n", + rQueryStaStatistics.u4TransmitFailCount, u4Per/10, u4Per%10); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "RSSI = %d\n", rRssi); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "LinkSpeed = %d\n", u2LinkSpeed); + + } else + i4BytesWritten = kalScnprintf(pcCommand, i4TotalLen, "%s", "\n\nNo STA Stat:\n"); + + return i4BytesWritten; + +} + + +static int priv_driver_get_bss_statistics(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + PARAM_MAC_ADDRESS arBssid; + UINT_32 u4BufLen; + INT_32 i4Rssi; + PARAM_GET_BSS_STATISTICS rQueryBssStatistics; + P_NETDEV_PRIVATE_GLUE_INFO prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) NULL; + UINT_8 ucBssIndex; + INT_32 i4BytesWritten = 0; +#if 0 + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 i4Argc = 0; + UINT_32 u4Index; +#endif + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + + kalMemZero(arBssid, MAC_ADDR_LEN); + wlanQueryInformation(prGlueInfo->prAdapter, wlanoidQueryBssid, &arBssid[0], sizeof(arBssid), &u4BufLen); + +#if 0 /* Todo:: Get the none-AIS statistics */ + if (i4Argc >= 2) + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Index); +#endif + + /* 2. fill RSSI */ + if (prGlueInfo->eParamMediaStateIndicated != PARAM_MEDIA_STATE_CONNECTED) { + /* not connected */ + DBGLOG(REQ, WARN, "not yet connected\n"); + return WLAN_STATUS_SUCCESS; + } + rStatus = kalIoctl(prGlueInfo, wlanoidQueryRssi, &i4Rssi, + sizeof(i4Rssi), TRUE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "unable to retrieve rssi\n"); + + + /* 3 get per-BSS link statistics */ + if (rStatus == WLAN_STATUS_SUCCESS) { + /* get Bss Index from ndev */ + prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(prNetDev); + ASSERT(prNetDevPrivate->prGlueInfo == prGlueInfo); + ucBssIndex = prNetDevPrivate->ucBssIdx; + + kalMemZero(&rQueryBssStatistics, sizeof(rQueryBssStatistics)); + rQueryBssStatistics.ucBssIndex = ucBssIndex; + + rQueryBssStatistics.ucReadClear = TRUE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryBssStatistics, + &rQueryBssStatistics, + sizeof(rQueryBssStatistics), TRUE, FALSE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_SUCCESS) { + i4BytesWritten = kalScnprintf(pcCommand, i4TotalLen, "%s", "\n\nStat:\n"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "CurrentTemperature = -\n"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Tx success = %d\n", + rQueryBssStatistics.u4TransmitCount - rQueryBssStatistics.u4TransmitFailCount); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Tx fail count = %d\n", + rQueryBssStatistics.u4TransmitFailCount); +#if 0 + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Rx success = %ld\n", 0); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Rx with CRC = %ld\n", prStatistics->rFCSErrorCount.QuadPart); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "Rx with PhyErr = 0\n"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "Rx with PlcpErr = 0\n"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "Rx drop due to out of resource = 0\n"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Rx duplicate frame = %ld\n", prStatistics->rFrameDuplicateCount.QuadPart); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "False CCA = 0\n"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "RSSI = %d\n", i4Rssi); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Last TX Rate = %s, %s, %s, %s, %s\n", "NA", "NA", "NA", "NA", "NA"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Last RX Rate = %s, %s, %s, %s, %s\n", "NA", "NA", "NA", "NA", "NA"); +#endif + + } + + } else { + DBGLOG(REQ, WARN, "unable to retrieve per-BSS link statistics\n"); + } + + + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + + return i4BytesWritten; + +} + +char *HW_TX_MODE_STR[] = {"CCK", "OFDM", "MM", "GF", "VHT", "N/A"}; +char *HW_TX_RATE_CCK_STR[] = {"1M", "2M", "5.5M", "11M", "N/A"}; +char *HW_TX_RATE_OFDM_STR[] = {"6M", "9M", "12M", "18M", "24M", + "36M", "48M", "54M", "N/A"}; +char *HW_TX_RATE_BW[] = {"BW20", "BW40", "BW80", "BW160/BW8080", "N/A"}; +enum { + RATE_TBL_B = 0, + RATE_TBL_G, + RATE_TBL_N, + RATE_TBL_N_2SS, + RATE_TBL_AC, + RATE_TBL_AC_2SS, + RATE_TBL_MAX +}; + +static char *RATE_TBLE[] = { + [RATE_TBL_B] = "B", + [RATE_TBL_G] = "G", + [RATE_TBL_N] = "N", + [RATE_TBL_N_2SS] = "N_2SS", + [RATE_TBL_AC] = "AC", + [RATE_TBL_AC_2SS] = "AC_2SS", + [RATE_TBL_MAX] = "N/A" +}; +#if 0 +static char *AR_STATE[] = {"NULL", "STEADY", "PROBE", "N/A"}; +static char *AR_ACTION[] = {"NULL", "INDEX", "RATE_UP", "RATE_DOWN", "RATE_GRP", "RATE_BACK", + "GI", "SGI_EN", "SGI_DIS", "PWR", "PWR_UP", "PWR_DOWN", + "PWR_RESET_UP", "BF", "BF_EN", "BF_DIS", "N/A"}; +#endif +#define BW_20 0 +#define BW_40 1 +#define BW_80 2 +#define BW_160 3 +#define BW_10 4 +#define BW_5 6 +#define BW_8080 7 +#define BW_ALL 0xFF + +char *hw_rate_ofdm_str(UINT_16 ofdm_idx) +{ + switch (ofdm_idx) { + case 11: /* 6M */ + return HW_TX_RATE_OFDM_STR[0]; + case 15: /* 9M */ + return HW_TX_RATE_OFDM_STR[1]; + case 10: /* 12M */ + return HW_TX_RATE_OFDM_STR[2]; + case 14: /* 18M */ + return HW_TX_RATE_OFDM_STR[3]; + case 9: /* 24M */ + return HW_TX_RATE_OFDM_STR[4]; + case 13: /* 36M */ + return HW_TX_RATE_OFDM_STR[5]; + case 8: /* 48M */ + return HW_TX_RATE_OFDM_STR[6]; + case 12: /* 54M */ + return HW_TX_RATE_OFDM_STR[7]; + default: + return HW_TX_RATE_OFDM_STR[8]; + } +} + +static BOOL priv_driver_get_sgi_info(IN P_PARAM_PEER_CAP_T prWtblPeerCap) +{ + if (!prWtblPeerCap) + return FALSE; + + switch (prWtblPeerCap->ucFrequencyCapability) { + case BW_20: + return prWtblPeerCap->fgG2; + case BW_40: + return prWtblPeerCap->fgG4; + case BW_80: + return prWtblPeerCap->fgG8; + case BW_160: + return prWtblPeerCap->fgG16; + default: + return FALSE; + } +} + +static BOOL priv_driver_get_ldpc_info(IN P_PARAM_TX_CONFIG_T prWtblTxConfig) +{ + if (!prWtblTxConfig) + return FALSE; + + if (prWtblTxConfig->fgIsVHT) + return prWtblTxConfig->fgVhtLDPC; + else + return prWtblTxConfig->fgLDPC; +} + +INT_32 priv_driver_rate_to_string(IN char *pcCommand, IN int i4TotalLen, UINT_8 TxRx, + P_PARAM_HW_WLAN_INFO_T prHwWlanInfo) +{ + UINT_8 i, txmode, rate, stbc; + UINT_8 nss; + INT_32 i4BytesWritten = 0; + + for (i = 0; i < AUTO_RATE_NUM; i++) { + + txmode = HW_TX_RATE_TO_MODE(prHwWlanInfo->rWtblRateInfo.au2RateCode[i]); + if (txmode >= MAX_TX_MODE) + txmode = MAX_TX_MODE; + rate = HW_TX_RATE_TO_MCS(prHwWlanInfo->rWtblRateInfo.au2RateCode[i], txmode); + nss = HW_TX_RATE_TO_NSS(prHwWlanInfo->rWtblRateInfo.au2RateCode[i]) + 1; + stbc = HW_TX_RATE_TO_STBC(prHwWlanInfo->rWtblRateInfo.au2RateCode[i]); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRate index[%d] ", i); + + if (prHwWlanInfo->rWtblRateInfo.ucRateIdx == i) { + if (TxRx == 0) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "[Last RX Rate] "); + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "[Last TX Rate] "); + } else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", " "); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, ", rate < 4 ? HW_TX_RATE_CCK_STR[rate] : HW_TX_RATE_CCK_STR[4]); + else if (txmode == TX_RATE_MODE_OFDM) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, ", hw_rate_ofdm_str(rate)); + else { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "NSS%d_MCS%d, ", nss, rate); + } + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, ", HW_TX_RATE_BW[prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability]); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, ", rate < 4 ? "LP" : "SP"); + else if (txmode == TX_RATE_MODE_OFDM) + ; + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, ", priv_driver_get_sgi_info(&prHwWlanInfo->rWtblPeerCap) == 0 ? "LGI" : "SGI"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s%s %s\n", HW_TX_MODE_STR[txmode], + stbc ? "STBC" : " ", + priv_driver_get_ldpc_info(&prHwWlanInfo->rWtblTxConfig) == 0 ? "BCC" : "LDPC"); + } + + return i4BytesWritten; +} + +static INT_32 priv_driver_dump_helper_wtbl_info(IN char *pcCommand, IN int i4TotalLen, + P_PARAM_HW_WLAN_INFO_T prHwWlanInfo) +{ + UINT_8 i; + INT_32 i4BytesWritten = 0; + + ASSERT(pcCommand); + + i4BytesWritten = kalScnprintf(pcCommand, i4TotalLen, "%s", "\n\nwtbl:\n"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Dump WTBL info of WLAN_IDX = %d\n", prHwWlanInfo->u4Index); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tAddr="MACSTR"\n", MAC2STR(prHwWlanInfo->rWtblTxConfig.aucPA)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tMUAR_Idx = %d\n", prHwWlanInfo->rWtblSecConfig.ucMUARIdx); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\trc_a1/rc_a2:%d/%d\n", prHwWlanInfo->rWtblSecConfig.fgRCA1, prHwWlanInfo->rWtblSecConfig.fgRCA2); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tKID:%d/RCID:%d/RKV:%d/RV:%d/IKV:%d/WPI_FLAG:%d\n", prHwWlanInfo->rWtblSecConfig.ucKeyID, + prHwWlanInfo->rWtblSecConfig.fgRCID, prHwWlanInfo->rWtblSecConfig.fgRKV, + prHwWlanInfo->rWtblSecConfig.fgRV, prHwWlanInfo->rWtblSecConfig.fgIKV, + prHwWlanInfo->rWtblSecConfig.fgEvenPN); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "\tGID_SU:NA"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tsw/DIS_RHTR:%d/%d\n", prHwWlanInfo->rWtblTxConfig.fgSW, prHwWlanInfo->rWtblTxConfig.fgDisRxHdrTran); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tHT/VHT/HT-LDPC/VHT-LDPC/DYN_BW/MMSS:%d/%d/%d/%d/%d/%d\n", + prHwWlanInfo->rWtblTxConfig.fgIsHT, prHwWlanInfo->rWtblTxConfig.fgIsVHT, + prHwWlanInfo->rWtblTxConfig.fgLDPC, prHwWlanInfo->rWtblTxConfig.fgVhtLDPC, + prHwWlanInfo->rWtblTxConfig.fgDynBw, prHwWlanInfo->rWtblPeerCap.ucMMSS); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tFCAP/G2/G4/G8/G16/CBRN:%d/%d/%d/%d/%d/%d\n", + prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability, prHwWlanInfo->rWtblPeerCap.fgG2, + prHwWlanInfo->rWtblPeerCap.fgG4, prHwWlanInfo->rWtblPeerCap.fgG8, prHwWlanInfo->rWtblPeerCap.fgG16, + prHwWlanInfo->rWtblPeerCap.ucChangeBWAfterRateN); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tHT-TxBF(tibf/tebf):%d/%d, VHT-TxBF(tibf/tebf):%d/%d, PFMU_IDX=%d\n", + prHwWlanInfo->rWtblTxConfig.fgTIBF, prHwWlanInfo->rWtblTxConfig.fgTEBF, + prHwWlanInfo->rWtblTxConfig.fgVhtTIBF, prHwWlanInfo->rWtblTxConfig.fgVhtTEBF, + prHwWlanInfo->rWtblTxConfig.ucPFMUIdx); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "\tSPE_IDX=NA\n"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tBA Enable:0x%x, BAFail Enable:%d\n", prHwWlanInfo->rWtblBaConfig.ucBaEn, + prHwWlanInfo->rWtblTxConfig.fgBAFEn); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tQoS Enable:%d\n", prHwWlanInfo->rWtblTxConfig.fgIsQoS); + if (prHwWlanInfo->rWtblTxConfig.fgIsQoS) { + for (i = 0; i < 8; i += 2) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\t\tBA WinSize: TID 0 - %d, TID 1 - %d\n", + (UINT_32) + ((prHwWlanInfo->rWtblBaConfig.u4BaWinSize >> + (i * 3)) & BITS(0, 2)), + (UINT_32) + ((prHwWlanInfo->rWtblBaConfig.u4BaWinSize >> + ((i + 1) * 3)) & BITS(0, 2))); + } + } + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tpartial_aid:%d\n", prHwWlanInfo->rWtblTxConfig.u2PartialAID); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\twpi_even:%d\n", prHwWlanInfo->rWtblSecConfig.fgEvenPN); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tAAD_OM/CipherSuit:%d/%d\n", prHwWlanInfo->rWtblTxConfig.fgAADOM, + prHwWlanInfo->rWtblSecConfig.ucCipherSuit); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\taf:%d\n", prHwWlanInfo->rWtblPeerCap.ucAmpduFactor); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\trdg_ba:%d/rdg capability:%d\n", prHwWlanInfo->rWtblTxConfig.fgRdgBA, + prHwWlanInfo->rWtblTxConfig.fgRDG); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tcipher_suit:%d\n", prHwWlanInfo->rWtblSecConfig.ucCipherSuit); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tFromDS:%d\n", prHwWlanInfo->rWtblTxConfig.fgIsFromDS); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tToDS:%d\n", prHwWlanInfo->rWtblTxConfig.fgIsToDS); +#if 0 + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRCPI = %d %d %d %d\n", prHwWlanInfo->rWtblRxCounter.ucRxRcpi0, + prHwWlanInfo->rWtblRxCounter.ucRxRcpi1, + prHwWlanInfo->rWtblRxCounter.ucRxRcpi2, + prHwWlanInfo->rWtblRxCounter.ucRxRcpi3); +#endif + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRSSI = %d %d %d %d\n", RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi0), + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi1), + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi2), + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi3)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "\tRate Info\n"); + + i4BytesWritten += priv_driver_rate_to_string(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, 1, + prHwWlanInfo); + +#if 0 + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "\t===Key======\n"); + for (i = 0; i < 32; i += 8) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\t0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", + prHwWlanInfo->rWtblKeyConfig.aucKey[i + 0], prHwWlanInfo->rWtblKeyConfig.aucKey[i + 1], + prHwWlanInfo->rWtblKeyConfig.aucKey[i + 2], prHwWlanInfo->rWtblKeyConfig.aucKey[i + 3], + prHwWlanInfo->rWtblKeyConfig.aucKey[i + 4], prHwWlanInfo->rWtblKeyConfig.aucKey[i + 5], + prHwWlanInfo->rWtblKeyConfig.aucKey[i + 6], prHwWlanInfo->rWtblKeyConfig.aucKey[i + 7]); + } +#endif + + return i4BytesWritten; +} + +static int priv_driver_get_wtbl_info(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + INT_32 u4Ret = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + P_PARAM_HW_WLAN_INFO_T prHwWlanInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + /* DBGLOG(RSN, INFO, "MT6632 : priv_driver_get_wtbl_info\n"); */ + + prHwWlanInfo = (P_PARAM_HW_WLAN_INFO_T)kalMemAlloc(sizeof(PARAM_HW_WLAN_INFO_T), VIR_MEM_TYPE); + if (!prHwWlanInfo) + return -1; + + if (i4Argc >= 2) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &prHwWlanInfo->u4Index); + + DBGLOG(REQ, INFO, "MT6632 : index = %d\n", prHwWlanInfo->u4Index); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryWlanInfo, + prHwWlanInfo, sizeof(PARAM_HW_WLAN_INFO_T), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, INFO, "rStatus %u u4BufLen = %d\n", rStatus, u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + kalMemFree(prHwWlanInfo, VIR_MEM_TYPE, sizeof(PARAM_HW_WLAN_INFO_T)); + return -1; + } + i4BytesWritten = priv_driver_dump_helper_wtbl_info(pcCommand, i4TotalLen, prHwWlanInfo); + } + + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + + kalMemFree(prHwWlanInfo, VIR_MEM_TYPE, sizeof(PARAM_HW_WLAN_INFO_T)); + + return i4BytesWritten; +} + +static int priv_driver_get_sta_info(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + UINT_8 ucWlanIndex; + PUINT_8 pucMacAddr = NULL; + P_PARAM_HW_WLAN_INFO_T prHwWlanInfo = NULL; + PARAM_GET_STA_STA_STATISTICS rQueryStaStatistics; + PARAM_RSSI rRssi; + UINT_16 u2LinkSpeed; + UINT_32 u4Per; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + kalMemZero(&rQueryStaStatistics, sizeof(rQueryStaStatistics)); + rQueryStaStatistics.ucReadClear = TRUE; + + /* DBGLOG(RSN, INFO, "MT6632 : priv_driver_get_sta_info\n"); */ + if (i4Argc >= 3) { + if (strnicmp(apcArgv[1], CMD_GET_STA_KEEP_CNT, strlen(CMD_GET_STA_KEEP_CNT)) == 0) { + wlanHwAddrToBin(apcArgv[2], &aucMacAddr[0]); + rQueryStaStatistics.ucReadClear = FALSE; + } else if (strnicmp(apcArgv[2], CMD_GET_STA_KEEP_CNT, strlen(CMD_GET_STA_KEEP_CNT)) == 0) { + wlanHwAddrToBin(apcArgv[1], &aucMacAddr[0]); + rQueryStaStatistics.ucReadClear = FALSE; + } + + if (!wlanGetWlanIdxByAddress(prGlueInfo->prAdapter, &aucMacAddr[0], &ucWlanIndex)) + return i4BytesWritten; + } else { + /* Get AIS AP address for no argument */ + if (prGlueInfo->prAdapter->prAisBssInfo->prStaRecOfAP) + ucWlanIndex = prGlueInfo->prAdapter->prAisBssInfo->prStaRecOfAP->ucWlanIndex; + else if (!wlanGetWlanIdxByAddress(prGlueInfo->prAdapter, NULL, &ucWlanIndex)) /* try get a peer */ + return i4BytesWritten; + + if (i4Argc == 2) { + if (strnicmp(apcArgv[1], CMD_GET_STA_KEEP_CNT, strlen(CMD_GET_STA_KEEP_CNT)) == 0) + rQueryStaStatistics.ucReadClear = FALSE; + } + } + + prHwWlanInfo = (P_PARAM_HW_WLAN_INFO_T)kalMemAlloc(sizeof(PARAM_HW_WLAN_INFO_T), VIR_MEM_TYPE); + + if (!prHwWlanInfo) { + DBGLOG(REQ, ERROR, "alloc memory for prHwWlanInfo failed!\n"); + i4BytesWritten = -1; + goto out; + } + prHwWlanInfo->u4Index = ucWlanIndex; + + DBGLOG(REQ, INFO, "MT6632 : index = %d i4TotalLen = %d\n", prHwWlanInfo->u4Index, i4TotalLen); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryWlanInfo, + prHwWlanInfo, sizeof(PARAM_HW_WLAN_INFO_T), TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "query prHwWlanInfo failed!\n"); + goto out; + } + + i4BytesWritten = priv_driver_dump_helper_wtbl_info(pcCommand, i4TotalLen, prHwWlanInfo); + + pucMacAddr = wlanGetStaAddrByWlanIdx(prGlueInfo->prAdapter, ucWlanIndex); + if (pucMacAddr) { + COPY_MAC_ADDR(rQueryStaStatistics.aucMacAddr, pucMacAddr); + /* i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + * "\tAddr="MACSTR"\n", MAC2STR(rQueryStaStatistics.aucMacAddr)); + */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStaStatistics, + &rQueryStaStatistics, + sizeof(rQueryStaStatistics), TRUE, FALSE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_SUCCESS) { + rRssi = RCPI_TO_dBm(rQueryStaStatistics.ucRcpi); + u2LinkSpeed = rQueryStaStatistics.u2LinkSpeed == 0 ? 0 : rQueryStaStatistics.u2LinkSpeed/2; + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "\n\nSTA Stat:\n"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Tx total cnt = %d\n", + rQueryStaStatistics.u4TransmitCount); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Tx success = %d\n", + rQueryStaStatistics.u4TransmitCount - rQueryStaStatistics.u4TransmitFailCount); + + u4Per = rQueryStaStatistics.u4TransmitCount == 0 ? 0 : + (1000 * (rQueryStaStatistics.u4TransmitFailCount)) / + rQueryStaStatistics.u4TransmitCount; + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Tx fail count = %d, PER=%d.%1d%%\n", + rQueryStaStatistics.u4TransmitFailCount, u4Per/10, u4Per%10); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "RSSI = %d\n", rRssi); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "LinkSpeed = %d\n", u2LinkSpeed); + } + } + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + +out: + if (prHwWlanInfo) + kalMemFree(prHwWlanInfo, VIR_MEM_TYPE, sizeof(PARAM_HW_WLAN_INFO_T)); + + return i4BytesWritten; +} + + +static int priv_driver_get_mib_info(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + UINT_8 i; + UINT_32 u4Per; + INT_32 u4Ret = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + P_PARAM_HW_MIB_INFO_T prHwMibInfo; + P_RX_CTRL_T prRxCtrl; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + prRxCtrl = &prGlueInfo->prAdapter->rRxCtrl; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + DBGLOG(REQ, INFO, "MT6632 : priv_driver_get_mib_info\n"); + + prHwMibInfo = (P_PARAM_HW_MIB_INFO_T)kalMemAlloc(sizeof(PARAM_HW_MIB_INFO_T), VIR_MEM_TYPE); + if (!prHwMibInfo) + return -1; + + if (i4Argc == 1) + prHwMibInfo->u4Index = 0; + + if (i4Argc >= 2) + u4Ret = kalkStrtou32(apcArgv[1], 0, &prHwMibInfo->u4Index); + + DBGLOG(REQ, INFO, "MT6632 : index = %d\n", prHwMibInfo->u4Index); + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryMibInfo, + prHwMibInfo, sizeof(PARAM_HW_MIB_INFO_T), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) { + kalMemFree(prHwMibInfo, VIR_MEM_TYPE, sizeof(PARAM_HW_MIB_INFO_T)); + return -1; + } + + if (prHwMibInfo->u4Index < 2) { + i4BytesWritten = kalScnprintf(pcCommand, i4TotalLen, "%s", "\n\nmib state:\n"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Dump MIB info of IDX = %d\n", prHwMibInfo->u4Index); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "===Rx Related Counters===\n"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx with CRC=%d\n", + prHwMibInfo->rHwMibCnt.u4RxFcsErrCnt); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx drop due to out of resource=%d\n", + prHwMibInfo->rHwMibCnt.u4RxFifoFullCnt); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx Mpdu=%d\n", prHwMibInfo->rHwMibCnt.u4RxMpduCnt); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx AMpdu=%d\n", prHwMibInfo->rHwMibCnt.u4RxAMPDUCnt); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx PF Drop=%d\n", + prHwMibInfo->rHwMibCnt.u4PFDropCnt); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx Len Mismatch=%d\n", + prHwMibInfo->rHwMibCnt.u4RxLenMismatchCnt); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx data indicate total=%ld\n", RX_GET_CNT(prRxCtrl, RX_DATA_INDICATION_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx data retain total=%ld\n", RX_GET_CNT(prRxCtrl, RX_DATA_RETAINED_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx drop by SW total=%ld\n", RX_GET_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx reorder miss=%ld\n", RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_MISS_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx reorder within=%ld\n", RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_WITHIN_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx reorder ahead=%ld\n", RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_AHEAD_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx reorder behind=%ld\n", RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_BEHIND_COUNT)); + + do { + UINT_32 u4AmsduCntx100 = 0; + + if (RX_GET_CNT(prRxCtrl, RX_DATA_AMSDU_COUNT)) + u4AmsduCntx100 = (UINT_32)div64_u64(RX_GET_CNT(prRxCtrl, + RX_DATA_MSDU_IN_AMSDU_COUNT) * 100, + RX_GET_CNT(prRxCtrl, RX_DATA_AMSDU_COUNT)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx avg MSDU in AMSDU=%1d.%02d\n", + u4AmsduCntx100 / 100, u4AmsduCntx100 % 100); + } while (FALSE); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx total MSDU in AMSDU=%ld\n", RX_GET_CNT(prRxCtrl, RX_DATA_MSDU_IN_AMSDU_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx AMSDU=%ld\n", RX_GET_CNT(prRxCtrl, RX_DATA_AMSDU_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx AMSDU miss=%ld\n", RX_GET_CNT(prRxCtrl, RX_DATA_AMSDU_MISS_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx no StaRec drop=%ld\n", RX_GET_CNT(prRxCtrl, RX_NO_STA_DROP_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx inactive BSS drop=%ld\n", RX_GET_CNT(prRxCtrl, RX_INACTIVE_BSS_DROP_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx HS20 drop=%ld\n", RX_GET_CNT(prRxCtrl, RX_HS20_DROP_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx low SwRfb drop=%ld\n", RX_GET_CNT(prRxCtrl, RX_LESS_SW_RFB_DROP_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx dupicate drop=%ld\n", RX_GET_CNT(prRxCtrl, RX_DUPICATE_DROP_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx MIC err drop=%ld\n", RX_GET_CNT(prRxCtrl, RX_MIC_ERROR_DROP_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx BAR handle=%ld\n", RX_GET_CNT(prRxCtrl, RX_BAR_DROP_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx non-interest drop=%ld\n", RX_GET_CNT(prRxCtrl, RX_NO_INTEREST_DROP_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx type err drop=%ld\n", RX_GET_CNT(prRxCtrl, RX_TYPE_ERR_DROP_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx class err drop=%ld\n", RX_GET_CNT(prRxCtrl, RX_CLASS_ERR_DROP_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "===Phy/Timing Related Counters===\n"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tChannelIdleCnt=%d\n", + prHwMibInfo->rHwMibCnt.u4ChannelIdleCnt); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tCCA_NAV_Tx_Time=%d\n", + prHwMibInfo->rHwMibCnt.u4CcaNavTx); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRx_MDRDY_CNT=%d\n", + prHwMibInfo->rHwMibCnt.u4MdrdyCnt); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tCCK_MDRDY=%d, OFDM_MDRDY=0x%x, OFDM_GREEN_MDRDY=0x%x\n", + prHwMibInfo->rHwMibCnt.u4CCKMdrdyCnt, prHwMibInfo->rHwMibCnt.u4OFDMLGMixMdrdy, + prHwMibInfo->rHwMibCnt.u4OFDMGreenMdrdy); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tPrim CCA Time=%d\n", + prHwMibInfo->rHwMibCnt.u4PCcaTime); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tSec CCA Time=%d\n", + prHwMibInfo->rHwMibCnt.u4SCcaTime); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tPrim ED Time=%d\n", + prHwMibInfo->rHwMibCnt.u4PEDTime); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "===Tx Related Counters(Generic)===\n"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tBeaconTxCnt=%d\n", + prHwMibInfo->rHwMibCnt.u4BeaconTxCnt); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tTx 40MHz Cnt=%d\n", + prHwMibInfo->rHwMib2Cnt.u4Tx40MHzCnt); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tTx 80MHz Cnt=%d\n", + prHwMibInfo->rHwMib2Cnt.u4Tx80MHzCnt); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tTx 160MHz Cnt=%d\n", + prHwMibInfo->rHwMib2Cnt.u4Tx160MHzCnt); + for (i = 0; i < BSSID_NUM; i++) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\t===BSSID[%d] Related Counters===\n", i); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tBA Miss Cnt=%d\n", + prHwMibInfo->rHwMibCnt.au4BaMissedCnt[i]); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRTS Tx Cnt=%d\n", + prHwMibInfo->rHwMibCnt.au4RtsTxCnt[i]); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tFrame Retry Cnt=%d\n", + prHwMibInfo->rHwMibCnt.au4FrameRetryCnt[i]); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tFrame Retry 2 Cnt=%d\n", + prHwMibInfo->rHwMibCnt.au4FrameRetry2Cnt[i]); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tRTS Retry Cnt=%d\n", + prHwMibInfo->rHwMibCnt.au4RtsRetryCnt[i]); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tAck Failed Cnt=%d\n", + prHwMibInfo->rHwMibCnt.au4AckFailedCnt[i]); + } + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "===AMPDU Related Counters===\n"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tTx AMPDU_Pkt_Cnt=%d\n", + prHwMibInfo->rHwTxAmpduMts.u2TxAmpduCnt); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tTx AMPDU_MPDU_Pkt_Cnt=%d\n", + prHwMibInfo->rHwTxAmpduMts.u4TxSfCnt); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tAMPDU SuccessCnt=%d\n", + prHwMibInfo->rHwTxAmpduMts.u4TxAckSfCnt); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tAMPDU Tx success = %d\n", + prHwMibInfo->rHwTxAmpduMts.u4TxAckSfCnt); + + u4Per = prHwMibInfo->rHwTxAmpduMts.u4TxSfCnt == 0 ? 0 : + (1000 * (prHwMibInfo->rHwTxAmpduMts.u4TxSfCnt - prHwMibInfo->rHwTxAmpduMts.u4TxAckSfCnt)) / + prHwMibInfo->rHwTxAmpduMts.u4TxSfCnt; + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\tAMPDU Tx fail count = %d, PER=%d.%1d%%\n", + prHwMibInfo->rHwTxAmpduMts.u4TxSfCnt - prHwMibInfo->rHwTxAmpduMts.u4TxAckSfCnt, + u4Per/10, u4Per%10); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "\tTx Agg\n"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "\tRange: 1 2~5 6~15 16~22 23~33 34~49 50~57 58~64\n"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\t\t%d \t%d \t%d \t%d \t%d \t%d \t%d \t%d\n", + prHwMibInfo->rHwTxAmpduMts.u2TxRange1AmpduCnt, prHwMibInfo->rHwTxAmpduMts.u2TxRange2AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange3AmpduCnt, prHwMibInfo->rHwTxAmpduMts.u2TxRange4AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange5AmpduCnt, prHwMibInfo->rHwTxAmpduMts.u2TxRange6AmpduCnt, + prHwMibInfo->rHwTxAmpduMts.u2TxRange7AmpduCnt, prHwMibInfo->rHwTxAmpduMts.u2TxRange8AmpduCnt); + } else + i4BytesWritten = kalScnprintf(pcCommand, i4TotalLen, "%s", "\nClear All Statistics\n"); + + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + + kalMemFree(prHwMibInfo, VIR_MEM_TYPE, sizeof(PARAM_HW_MIB_INFO_T)); + + nicRxClearStatistics(prGlueInfo->prAdapter); + + return i4BytesWritten; +} + +/* Private Coex Ctrl Subcmd for Isolation Detection */ +static int priv_driver_iso_detect(IN P_GLUE_INFO_T prGlueInfo, + IN struct CMD_COEX_CTRL *prCmdCoexCtrl, IN signed char *argv[]) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + UINT_32 u4Ret = 0; + + struct CMD_COEX_ISO_DETECT rCmdCoexIsoDetect; + + rCmdCoexIsoDetect.u4Isolation = 0; + + u4Ret = kalkStrtou32(argv[2], 0, &(rCmdCoexIsoDetect.u4IsoPath)); + if (u4Ret) { + DBGLOG(REQ, LOUD, " -priv_driver_coex_iso_detect - Parse Iso Path failed u4Ret=%d\n", u4Ret); + return -1; + } + + u4Ret = kalkStrtou32(argv[3], 0, &(rCmdCoexIsoDetect.u4Channel)); + if (u4Ret) { + DBGLOG(REQ, LOUD, " -priv_driver_coex_iso_detect - Parse channel failed u4Ret = %d\n", u4Ret); + return -1; + } + + /* Copy Memory */ + kalMemCopy(prCmdCoexCtrl->aucBuffer, &rCmdCoexIsoDetect, sizeof(struct CMD_COEX_ISO_DETECT)); + + /* Ioctl Isolation Detect */ + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryCoexIso, + prCmdCoexCtrl, + sizeof(struct CMD_COEX_CTRL), + TRUE, + TRUE, + TRUE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + /* If all pass, return u4Ret to 0 */ + return u4Ret; +} + +/* Private Coex Ctrl Subcmd for Getting Coex Info */ +static int priv_driver_get_coex_info(IN P_GLUE_INFO_T prGlueInfo, + IN struct CMD_COEX_CTRL *prCmdCoexCtrl, IN signed char *argv[]) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + UINT_32 u4Ret = 0; + + struct CMD_COEX_GET_INFO rCmdCoexGetInfo; + + kalMemSet(&rCmdCoexGetInfo, 0, sizeof(struct CMD_COEX_GET_INFO)); + + /* Copy Memory */ + kalMemCopy(prCmdCoexCtrl->aucBuffer, &rCmdCoexGetInfo, sizeof(struct CMD_COEX_GET_INFO)); + DBGLOG(REQ, INFO, "priv_driver_get_coex_info end\n"); + + /* Ioctl Get Coex Info */ + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryCoexGetInfo, + prCmdCoexCtrl, + sizeof(struct CMD_COEX_CTRL), + TRUE, + TRUE, + TRUE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + /* If all pass, return u4Ret to 0 */ + return u4Ret; +} + +/* Private Command for Coex Ctrl */ +static int priv_driver_coex_ctrl(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + INT_32 i4ArgNum = 2; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + UINT_32 u4Ret = 0; + UINT_32 u4Offset = 0; + INT_32 i4SubArgNum; + enum ENUM_COEX_CTRL_CMD CoexCtrlCmd; + struct CMD_COEX_CTRL rCmdCoexCtrl; + + ASSERT(prNetDev); + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + /* Prevent Kernel Panic, set default i4ArgNum to 2 */ + if (i4Argc >= i4ArgNum) { + + /* Parse Coex SubCmd */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &rCmdCoexCtrl.u4SubCmd); + if (u4Ret) + return -1; + + CoexCtrlCmd = (enum ENUM_COEX_CTRL_CMD) rCmdCoexCtrl.u4SubCmd; + + switch (CoexCtrlCmd) { + /* Isolation Detection */ + case ENUM_COEX_CTRL_ISO_DETECT: + { + struct CMD_COEX_ISO_DETECT *prCmdCoexIsoDetect; + + i4SubArgNum = 3; + /* Safely dereference "argv[3]".*/ + if (i4Argc < i4SubArgNum) + break; + /* Isolation Detection Method */ + u4Ret = priv_driver_iso_detect(prGlueInfo, &rCmdCoexCtrl, apcArgv); + if (u4Ret) + return -1; + + /* Get Isolation value */ + prCmdCoexIsoDetect = (struct CMD_COEX_ISO_DETECT *) rCmdCoexCtrl.aucBuffer; + + /* Set Return i4BytesWritten Value */ + u4Offset = snprintf(pcCommand, i4TotalLen, "%d", + (prCmdCoexIsoDetect->u4Isolation/2)); + DBGLOG(REQ, INFO, "Isolation: %d\n", + (prCmdCoexIsoDetect->u4Isolation/2)); + break; + } + case ENUM_COEX_CTRL_GET_INFO: + { + struct CMD_COEX_GET_INFO *prCmdCoexGetInfo; + UINT_8 ucCoexTblSize = sizeof(coex_ref_table) / sizeof(struct COEX_REF_TABLE); + UINT_8 ucCoexInfoNum, ucIdx = 0, ucTblIdx; + UINT_16 u2CoexInfoId, u2CoexInfoLen; + PUINT_32 pu4CoexInfo; + + u4Ret = priv_driver_get_coex_info(prGlueInfo, &rCmdCoexCtrl, apcArgv); + if (u4Ret) + return -1; + + prCmdCoexGetInfo = (struct CMD_COEX_GET_INFO *) rCmdCoexCtrl.aucBuffer; + + pu4CoexInfo = &prCmdCoexGetInfo->u4CoexInfo[0]; + ucCoexInfoNum = *pu4CoexInfo++ & 0xff; + while (ucIdx < ucCoexInfoNum) { + u2CoexInfoId = (*pu4CoexInfo >> 16) & 0xffff; + u2CoexInfoLen = *pu4CoexInfo++ & 0xffff; + + /* Find Coex Info Cmd Id from priv_driver_coex_info_table[] */ + for (ucTblIdx = 0; ucTblIdx < ucCoexTblSize; ucTblIdx++) { + if (u2CoexInfoId == coex_ref_table[ucTblIdx].ucCoexInfoId) { + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "\n%-25s:", coex_ref_table[ucTblIdx].cContent); + break; + } + } + + /* If not found in priv_driver_coex_info_table[], show Unknown Id */ + if (ucTblIdx == ucCoexTblSize) { + u4Offset += snprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, "\nUnknown Cmd ID :%-9d:", u2CoexInfoId); + } + + switch (u2CoexInfoLen) { + case 0x0001: + { + u4Offset += snprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, "0x%02x", + *pu4CoexInfo++); + break; + } + case 0x0002: + { + u4Offset += snprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, "0x%04x", + *pu4CoexInfo++); + break; + } + case 0x0003: + { + u4Offset += snprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, "0x%06x", + *pu4CoexInfo++); + break; + } + case 0x0004: + { + u4Offset += snprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, "0x%08x", + *pu4CoexInfo++); + break; + } + default: + break; + } + ucIdx++; + } + break; + } + /* Default Coex Cmd */ + default: + break; + } + + /* Set Return i4BytesWritten Value */ + i4BytesWritten = (INT_32)u4Offset; + } + return i4BytesWritten; +} + +static int priv_driver_set_fw_log(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + UINT_32 u4McuDest = 0; + UINT_32 u4LogType = 0; +#if CFG_SUPPORT_FW_DBG_LEVEL_CTRL + UINT_32 ucFwLogLevel = FW_DBG_LEVEL_DONT_SET; +#endif + P_CMD_FW_LOG_2_HOST_CTRL_T prFwLog2HostCtrl = NULL; + UINT_32 u4Ret = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RSN, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + DBGLOG(RSN, INFO, "MT6632 : priv_driver_set_fw_log\n"); + + prFwLog2HostCtrl = (P_CMD_FW_LOG_2_HOST_CTRL_T)kalMemAlloc(sizeof(CMD_FW_LOG_2_HOST_CTRL_T), VIR_MEM_TYPE); + if (!prFwLog2HostCtrl) { + DBGLOG(REQ, ERROR, "allocate memory for prFwLog2HostCtrl failed\n"); + i4BytesWritten = -1; + goto out; + } + +#if CFG_SUPPORT_FW_DBG_LEVEL_CTRL + if ((i4Argc != 3) && (i4Argc != 4)) { + DBGLOG(REQ, ERROR, "argc %i must be 3 or 4\n", i4Argc); + i4BytesWritten = -1; + goto out; + } +#else + if (i4Argc != 3) { + DBGLOG(REQ, ERROR, "argc %i is not equal to 3\n", i4Argc); + i4BytesWritten = -1; + goto out; + } +#endif + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4McuDest); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse u4McuDest error u4Ret=%d\n", u4Ret); + + u4Ret = kalkStrtou32(apcArgv[2], 0, &u4LogType); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse u4LogType error u4Ret=%d\n", u4Ret); + +#if CFG_SUPPORT_FW_DBG_LEVEL_CTRL + if (i4Argc == 4) { + u4Ret = kalkStrtou32(apcArgv[3], 0, &ucFwLogLevel); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse ucFwLogLevel error u4Ret=%d\n", u4Ret); + } + prFwLog2HostCtrl->ucFwLogLevel = (UINT_8)ucFwLogLevel; +#endif + + prFwLog2HostCtrl->ucMcuDest = (UINT_8)u4McuDest; + prFwLog2HostCtrl->ucFwLog2HostCtrl = (UINT_8)u4LogType; + + if (prFwLog2HostCtrl->ucMcuDest == 0) + prGlueInfo->prAdapter->rWifiVar.ucN9Log2HostCtrl = prFwLog2HostCtrl->ucFwLog2HostCtrl; + else if (prFwLog2HostCtrl->ucMcuDest == 1) + prGlueInfo->prAdapter->rWifiVar.ucCR4Log2HostCtrl = prFwLog2HostCtrl->ucFwLog2HostCtrl; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetFwLog2Host, + prFwLog2HostCtrl, sizeof(CMD_FW_LOG_2_HOST_CTRL_T), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, INFO, "%s: command result is %s (%d %d)\n", __func__, pcCommand, u4McuDest, u4LogType); + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "send fw log to host cmd failed\n"); + i4BytesWritten = -1; + goto out; + } + +out: + if (prFwLog2HostCtrl) + kalMemFree(prFwLog2HostCtrl, VIR_MEM_TYPE, + sizeof(CMD_FW_LOG_2_HOST_CTRL_T)); + + return i4BytesWritten; +} +#endif + +static int priv_driver_get_mcr(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + UINT_32 u4Ret; + INT_32 i4ArgNum = 2; + CMD_ACCESS_REG rCmdAccessReg; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rCmdAccessReg.u4Address)); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse get_mcr error (Address) u4Ret=%d\n", u4Ret); + + /* rCmdAccessReg.u4Address = kalStrtoul(apcArgv[1], NULL, 0); */ + rCmdAccessReg.u4Data = 0; + + DBGLOG(REQ, LOUD, "address is %x\n", rCmdAccessReg.u4Address); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryMcrRead, + &rCmdAccessReg, sizeof(rCmdAccessReg), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "0x%08x", (unsigned int)rCmdAccessReg.u4Data); + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + } + + return i4BytesWritten; + +} /* priv_driver_get_mcr */ + +int priv_driver_set_mcr(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + UINT_32 u4Ret; + INT_32 i4ArgNum = 3; + CMD_ACCESS_REG rCmdAccessReg; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rCmdAccessReg.u4Address)); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse get_mcr error (Address) u4Ret=%d\n", u4Ret); + + u4Ret = kalkStrtou32(apcArgv[2], 0, &(rCmdAccessReg.u4Data)); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse get_mcr error (Data) u4Ret=%d\n", u4Ret); + + /* rCmdAccessReg.u4Address = kalStrtoul(apcArgv[1], NULL, 0); */ + /* rCmdAccessReg.u4Data = kalStrtoul(apcArgv[2], NULL, 0); */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetMcrWrite, + &rCmdAccessReg, sizeof(rCmdAccessReg), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + } + + return i4BytesWritten; + +} + +static int priv_driver_set_test_mode(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + UINT_32 u4Ret; + INT_32 i4ArgNum = 2, u4MagicKey; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &(u4MagicKey)); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse Magic Key error u4Ret=%d\n", u4Ret); + + DBGLOG(REQ, LOUD, "The Set Test Mode Magic Key is %d\n", u4MagicKey); + + if (u4MagicKey == PRIV_CMD_TEST_MAGIC_KEY) { + rStatus = kalIoctl(prGlueInfo, + wlanoidRftestSetTestMode, + NULL, 0, FALSE, FALSE, TRUE, &u4BufLen); + } else if (u4MagicKey == 0) { + rStatus = kalIoctl(prGlueInfo, + wlanoidRftestSetAbortTestMode, + NULL, 0, FALSE, FALSE, TRUE, &u4BufLen); + } + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } + + return i4BytesWritten; + +} /* priv_driver_set_test_mode */ + +static int priv_driver_set_test_cmd(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + UINT_32 u4Ret; + INT_32 i4ArgNum = 3; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rRfATInfo.u4FuncIndex)); + if (u4Ret) + DBGLOG(REQ, LOUD, "Parse Test CMD Index error u4Ret=%d\n", u4Ret); + + u4Ret = kalkStrtou32(apcArgv[2], 0, &(rRfATInfo.u4FuncData)); + if (u4Ret) + DBGLOG(REQ, LOUD, "Parse Test CMD Data error u4Ret=%d\n", u4Ret); + + DBGLOG(REQ, LOUD, "Set Test CMD FuncIndex = %d, FuncData = %d\n", + rRfATInfo.u4FuncIndex, rRfATInfo.u4FuncData); + + rStatus = kalIoctl(prGlueInfo, + wlanoidRftestSetAutoTest, + &rRfATInfo, sizeof(rRfATInfo), FALSE, FALSE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } + + return i4BytesWritten; + +} /* priv_driver_set_test_cmd */ + +static int priv_driver_get_test_result(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + UINT_32 u4Ret; + UINT_32 u4Data = 0; + INT_32 i4ArgNum = 3; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rRfATInfo.u4FuncIndex)); + if (u4Ret) + DBGLOG(REQ, LOUD, "Parse Test CMD Index error u4Ret=%d\n", u4Ret); + + u4Ret = kalkStrtou32(apcArgv[2], 0, &(rRfATInfo.u4FuncData)); + if (u4Ret) + DBGLOG(REQ, LOUD, "Parse Test CMD Data error u4Ret=%d\n", u4Ret); + + DBGLOG(REQ, LOUD, "Get Test CMD FuncIndex = %d, FuncData = %d\n", + rRfATInfo.u4FuncIndex, rRfATInfo.u4FuncData); + + rStatus = kalIoctl(prGlueInfo, + wlanoidRftestQueryAutoTest, + &rRfATInfo, sizeof(rRfATInfo), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + u4Data = (unsigned int)rRfATInfo.u4FuncData; + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "%d[0x%08x]", u4Data, u4Data); + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + } + + return i4BytesWritten; + +} /* priv_driver_get_test_result */ + +#if CFG_SUPPORT_LAST_SEC_MCS_INFO +INT_32 priv_driver_last_sec_mcs_info(IN P_ADAPTER_T prAdapter, IN char *pcCommand, IN int i4TotalLen, + P_PARAM_HW_WLAN_INFO_T prHwWlanInfo, struct PARAM_TX_MCS_INFO *prTxMcsInfo) +{ + UINT_8 i, j, txmode, rate, stbc; + UINT_8 nsts; + INT_32 i4BytesWritten = 0; + UINT_32 au4RxVect0Que[MCS_INFO_SAMPLE_CNT], au4RxVect1Que[MCS_INFO_SAMPLE_CNT]; + UINT_8 ucStaIdx = prAdapter->prAisBssInfo->prStaRecOfAP->ucIndex; + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, "\nTx MCS:\n"); + + for (i = 0; i < MCS_INFO_SAMPLE_CNT; i++) { + UINT_8 tmpPerSum = 0, cnt = 0; + UINT_16 tmpRateCode = 0xFFFF; + + if (prTxMcsInfo->au2TxRateCode[i] == 0xFFFF) + continue; + + if (tmpRateCode == 0xFFFF) + tmpRateCode = prTxMcsInfo->au2TxRateCode[i]; + + txmode = HW_TX_RATE_TO_MODE(prTxMcsInfo->au2TxRateCode[i]); + if (txmode >= MAX_TX_MODE) + txmode = MAX_TX_MODE; + rate = HW_TX_RATE_TO_MCS(prTxMcsInfo->au2TxRateCode[i], txmode); + nsts = HW_TX_RATE_TO_NSS(prTxMcsInfo->au2TxRateCode[i]) + 1; + stbc = HW_TX_RATE_TO_STBC(prTxMcsInfo->au2TxRateCode[i]); + + for (j = 0; j < MCS_INFO_SAMPLE_CNT; j++) { + if (tmpRateCode == prTxMcsInfo->au2TxRateCode[j]) { + tmpPerSum += prTxMcsInfo->aucTxRatePer[j]; + cnt++; + prTxMcsInfo->au2TxRateCode[j] = 0xFFFF; + } + } + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + " %s, ", HW_TX_RATE_CCK_STR[rate & 0x3]); + else if (txmode == TX_RATE_MODE_OFDM) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + " %s, ", hw_rate_ofdm_str(rate)); + else if ((txmode == TX_RATE_MODE_HTMIX) || (txmode == TX_RATE_MODE_HTGF)) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + " MCS%d, ", rate); + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + " NSS%d_MCS%d, ", nsts, rate); + + if ((txmode == TX_RATE_MODE_CCK) || (txmode == TX_RATE_MODE_OFDM)) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, ", HW_TX_RATE_BW[0]); + else + if (i > prHwWlanInfo->rWtblPeerCap.ucChangeBWAfterRateN) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability < 4 ? + (prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability > BW_20 ? + HW_TX_RATE_BW[prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability - 1] : + HW_TX_RATE_BW[prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability]) : + HW_TX_RATE_BW[4]); + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability < 4 ? + HW_TX_RATE_BW[prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability] : + HW_TX_RATE_BW[4]); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, ", rate < 4 ? "LP" : "SP"); + else if (txmode == TX_RATE_MODE_OFDM) + ; + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, ", priv_driver_get_sgi_info(&prHwWlanInfo->rWtblPeerCap) == 0 ? "LGI" : "SGI"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s%s%s [PER: %02d%]\t", txmode < 5 ? HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5], + stbc ? ", STBC, " : ", ", + ((priv_driver_get_ldpc_info(&prHwWlanInfo->rWtblTxConfig) == 0) || + (txmode == TX_RATE_MODE_CCK) || (txmode == TX_RATE_MODE_OFDM)) ? "BCC" : "LDPC", + tmpPerSum/cnt); + + for (j = 0; j < cnt; j++) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, "*"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, "\n"); + } + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, "\nRx MCS:\n"); + + kalMemCopy(au4RxVect0Que, prAdapter->arStaRec[ucStaIdx].au4RxVect0Que, sizeof(au4RxVect0Que)); + kalMemCopy(au4RxVect1Que, prAdapter->arStaRec[ucStaIdx].au4RxVect1Que, sizeof(au4RxVect1Que)); + + for (i = 0; i < MCS_INFO_SAMPLE_CNT; i++) { + UINT_8 cnt = 0; + UINT_32 u4RxVector0 = 0xFFFFFFFF; + UINT_32 txmode, rate, frmode, sgi, nsts, ldpc, stbc, groupid, mu; + #define RX_MCS_INFO_MASK BITS(0, 17) + + if (au4RxVect0Que[i] == 0xFFFFFFFF) + continue; + + if (u4RxVector0 == 0xFFFFFFFF) + u4RxVector0 = au4RxVect0Que[i]; + + txmode = (au4RxVect0Que[i] & RX_VT_RX_MODE_MASK) >> RX_VT_RX_MODE_OFFSET; + rate = (au4RxVect0Que[i] & RX_VT_RX_RATE_MASK) >> RX_VT_RX_RATE_OFFSET; + frmode = (au4RxVect0Que[i] & RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET; + nsts = ((au4RxVect1Que[i] & RX_VT_NSTS_MASK) >> RX_VT_NSTS_OFFSET); + stbc = (au4RxVect0Que[i] & RX_VT_STBC_MASK) >> RX_VT_STBC_OFFSET; + sgi = au4RxVect0Que[i] & RX_VT_SHORT_GI; + ldpc = au4RxVect0Que[i] & RX_VT_LDPC; + groupid = (au4RxVect1Que[i] & RX_VT_GROUP_ID_MASK) >> RX_VT_GROUP_ID_OFFSET; + + for (j = 0; j < MCS_INFO_SAMPLE_CNT; j++) { + if ((u4RxVector0 & RX_MCS_INFO_MASK) == (au4RxVect0Que[j] & RX_MCS_INFO_MASK)) { + au4RxVect0Que[j] = 0xFFFFFFFF; + cnt++; + } + } + + if (groupid && groupid != 63) { + mu = 1; + } else { + mu = 0; + nsts += 1; + } + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + " %s, ", rate < 4 ? HW_TX_RATE_CCK_STR[rate] : HW_TX_RATE_CCK_STR[4]); + else if (txmode == TX_RATE_MODE_OFDM) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + " %s, ", hw_rate_ofdm_str(rate)); + else if ((txmode == TX_RATE_MODE_HTMIX) || (txmode == TX_RATE_MODE_HTGF)) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + " MCS%d, ", rate); + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + " NSS%d_MCS%d, ", nsts, rate); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, ", frmode < 4 ? HW_TX_RATE_BW[frmode] : HW_TX_RATE_BW[4]); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, ", rate < 4 ? "LP" : "SP"); + else if (txmode == TX_RATE_MODE_OFDM) + ; + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s,", sgi == 0 ? "LGI" : "SGI"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", stbc == 0 ? " " : " STBC, "); + + if (mu) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, %s, %s (%d)\t", txmode < 5 ? HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5], + ldpc == 0 ? "BCC" : "LDPC", "MU", groupid); + } else { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, %s\t", txmode < 5 ? HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5], + ldpc == 0 ? "BCC" : "LDPC"); + } + + for (j = 0; j < cnt; j++) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, "*"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, "\n"); + } + + return i4BytesWritten; +} +#endif + +INT_32 priv_driver_tx_rate_info(IN char *pcCommand, IN int i4TotalLen, BOOLEAN fgDumpAll, + P_PARAM_HW_WLAN_INFO_T prHwWlanInfo, P_PARAM_GET_STA_STATISTICS prQueryStaStatistics) +{ + UINT_8 i, txmode, rate, stbc; + UINT_8 nsts; + INT_32 i4BytesWritten = 0; + + for (i = 0; i < AUTO_RATE_NUM; i++) { + + txmode = HW_TX_RATE_TO_MODE(prHwWlanInfo->rWtblRateInfo.au2RateCode[i]); + if (txmode >= MAX_TX_MODE) + txmode = MAX_TX_MODE; + rate = HW_TX_RATE_TO_MCS(prHwWlanInfo->rWtblRateInfo.au2RateCode[i], txmode); + nsts = HW_TX_RATE_TO_NSS(prHwWlanInfo->rWtblRateInfo.au2RateCode[i]) + 1; + stbc = HW_TX_RATE_TO_STBC(prHwWlanInfo->rWtblRateInfo.au2RateCode[i]); + + if (fgDumpAll) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "Rate index - %d ", i); + + if (prHwWlanInfo->rWtblRateInfo.ucRateIdx == i) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "--> "); + } else { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", " "); + } + } + + if (!fgDumpAll) { + if (prHwWlanInfo->rWtblRateInfo.ucRateIdx != i) + continue; + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s", "AR TX Rate", " = "); + } + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, ", HW_TX_RATE_CCK_STR[rate & 0x3]); + else if (txmode == TX_RATE_MODE_OFDM) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, ", hw_rate_ofdm_str(rate)); + else if ((txmode == TX_RATE_MODE_HTMIX) || (txmode == TX_RATE_MODE_HTGF)) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "MCS%d, ", rate); + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "NSS%d_MCS%d, ", nsts, rate); + + if (prQueryStaStatistics->ucSkipAr) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, ", prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability < 4 ? + HW_TX_RATE_BW[prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability] : HW_TX_RATE_BW[4]); + } else { + if ((txmode == TX_RATE_MODE_CCK) || (txmode == TX_RATE_MODE_OFDM)) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, ", HW_TX_RATE_BW[0]); + else + if (i > prHwWlanInfo->rWtblPeerCap.ucChangeBWAfterRateN) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability < 4 ? + (prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability > BW_20 ? + HW_TX_RATE_BW[prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability - 1] : + HW_TX_RATE_BW[prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability]) : + HW_TX_RATE_BW[4]); + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s, ", + prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability < 4 ? + HW_TX_RATE_BW[prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability] : + HW_TX_RATE_BW[4]); + } + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, ", rate < 4 ? "LP" : "SP"); + else if (txmode == TX_RATE_MODE_OFDM) + ; + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, ", priv_driver_get_sgi_info(&prHwWlanInfo->rWtblPeerCap) == 0 ? "LGI" : "SGI"); + + if (prQueryStaStatistics->ucSkipAr) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s%s%s\n", txmode < 5 ? HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5], + stbc ? ", STBC, " : ", ", + priv_driver_get_ldpc_info(&prHwWlanInfo->rWtblTxConfig) == 0 ? "BCC" : "LDPC"); + } else if (prQueryStaStatistics->aucArRatePer[prQueryStaStatistics->aucRateEntryIndex[i]] == 0xFF) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s%s%s (--)\n", txmode < 5 ? HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5], + stbc ? ", STBC, " : ", ", + ((priv_driver_get_ldpc_info(&prHwWlanInfo->rWtblTxConfig) == 0) || + (txmode == TX_RATE_MODE_CCK) || (txmode == TX_RATE_MODE_OFDM)) ? "BCC" : "LDPC"); + } else { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s%s%s (%d)\n", txmode < 5 ? HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5], + stbc ? ", STBC, " : ", ", + ((priv_driver_get_ldpc_info(&prHwWlanInfo->rWtblTxConfig) == 0) || + (txmode == TX_RATE_MODE_CCK) || (txmode == TX_RATE_MODE_OFDM)) ? "BCC" : "LDPC", + prQueryStaStatistics->aucArRatePer[prQueryStaStatistics->aucRateEntryIndex[i]]); + } + + if (!fgDumpAll) + break; + } + + return i4BytesWritten; +} + + +INT_32 priv_driver_last_rx_rssi(P_ADAPTER_T prAdapter, IN char *pcCommand, IN int i4TotalLen, + IN UINT_8 ucWlanIdx) +{ + INT_32 i4RSSI0 = 0, i4RSSI1 = 0, i4RSSI2 = 0, i4RSSI3; + INT_32 i4BytesWritten = 0; + UINT_32 u4RxVector3 = 0; + UINT_8 ucStaIdx; + + if (wlanGetStaIdxByWlanIdx(prAdapter, ucWlanIdx, &ucStaIdx) == WLAN_STATUS_SUCCESS) { + u4RxVector3 = prAdapter->arStaRec[ucStaIdx].u4RxVector3; + DBGLOG(REQ, LOUD, "****** RX Vector3 = 0x%08x ******\n", u4RxVector3); + } else { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s", "Last RX RSSI", " = NOT SUPPORT"); + return i4BytesWritten; + } + + i4RSSI0 = RCPI_TO_dBm((u4RxVector3 & RX_VT_RCPI0_MASK) >> RX_VT_RCPI0_OFFSET); + i4RSSI1 = RCPI_TO_dBm((u4RxVector3 & RX_VT_RCPI1_MASK) >> RX_VT_RCPI1_OFFSET); + + if (prAdapter->rWifiVar.ucNSS > 2) { + i4RSSI2 = RCPI_TO_dBm((u4RxVector3 & RX_VT_RCPI2_MASK) >> RX_VT_RCPI2_OFFSET); + i4RSSI3 = RCPI_TO_dBm((u4RxVector3 & RX_VT_RCPI3_MASK) >> RX_VT_RCPI3_OFFSET); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d %d %d %d\n", "Last RX Data RSSI", " = ", i4RSSI0, i4RSSI1, i4RSSI2, i4RSSI3); + } else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d %d\n", "Last RX Data RSSI", " = ", i4RSSI0, i4RSSI1); + + return i4BytesWritten; +} + + +INT_32 priv_driver_rx_rate_info(P_ADAPTER_T prAdapter, IN char *pcCommand, IN int i4TotalLen, + IN UINT_8 ucWlanIdx) +{ + UINT_32 txmode, rate, frmode, sgi, nsts, ldpc, stbc, groupid, mu; + INT_32 i4BytesWritten = 0; + UINT_32 u4RxVector0 = 0, u4RxVector1 = 0; + UINT_8 ucStaIdx; + + if (wlanGetStaIdxByWlanIdx(prAdapter, ucWlanIdx, &ucStaIdx) == WLAN_STATUS_SUCCESS) { + u4RxVector0 = prAdapter->arStaRec[ucStaIdx].u4RxVector0; + u4RxVector1 = prAdapter->arStaRec[ucStaIdx].u4RxVector1; + DBGLOG(REQ, LOUD, "****** RX Vector0 = 0x%08x ******\n", u4RxVector0); + DBGLOG(REQ, LOUD, "****** RX Vector1 = 0x%08x ******\n", u4RxVector1); + } else { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s", "Last RX Rate", " = NOT SUPPORT"); + return i4BytesWritten; + } + + txmode = (u4RxVector0 & RX_VT_RX_MODE_MASK) >> RX_VT_RX_MODE_OFFSET; + rate = (u4RxVector0 & RX_VT_RX_RATE_MASK) >> RX_VT_RX_RATE_OFFSET; + frmode = (u4RxVector0 & RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET; + nsts = ((u4RxVector1 & RX_VT_NSTS_MASK) >> RX_VT_NSTS_OFFSET); + stbc = (u4RxVector0 & RX_VT_STBC_MASK) >> RX_VT_STBC_OFFSET; + sgi = u4RxVector0 & RX_VT_SHORT_GI; + ldpc = u4RxVector0 & RX_VT_LDPC; + groupid = (u4RxVector1 & RX_VT_GROUP_ID_MASK) >> RX_VT_GROUP_ID_OFFSET; + + if (groupid && groupid != 63) { + mu = 1; + } else { + mu = 0; + nsts += 1; + } + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s", "Last RX Rate", " = "); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, ", rate < 4 ? HW_TX_RATE_CCK_STR[rate] : HW_TX_RATE_CCK_STR[4]); + else if (txmode == TX_RATE_MODE_OFDM) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, ", hw_rate_ofdm_str(rate)); + else if ((txmode == TX_RATE_MODE_HTMIX) || (txmode == TX_RATE_MODE_HTGF)) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "MCS%d, ", rate); + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "NSS%d_MCS%d, ", nsts, rate); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, ", frmode < 4 ? HW_TX_RATE_BW[frmode] : HW_TX_RATE_BW[4]); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, ", rate < 4 ? "LP" : "SP"); + else if (txmode == TX_RATE_MODE_OFDM) + ; + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s,", sgi == 0 ? "LGI" : "SGI"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", stbc == 0 ? " " : " STBC, "); + + if (mu) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, %s, %s (%d)\n", txmode < 5 ? HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5], + ldpc == 0 ? "BCC" : "LDPC", "MU", groupid); + } else { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, %s\n", txmode < 5 ? HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5], + ldpc == 0 ? "BCC" : "LDPC"); + } + + return i4BytesWritten; +} + +INT_32 priv_driver_tx_vector_info(IN char *pcCommand, IN int i4TotalLen, + IN P_TX_VECTOR_BBP_LATCH_T prTxV) +{ + UINT_8 rate, txmode, frmode, sgi, ldpc, nsts, stbc, txpwr; + INT_32 i4BytesWritten = 0; + + rate = TX_VECTOR_GET_TX_RATE(prTxV); + txmode = TX_VECTOR_GET_TX_MODE(prTxV); + frmode = TX_VECTOR_GET_TX_FRMODE(prTxV); + nsts = TX_VECTOR_GET_TX_NSTS(prTxV) + 1; + sgi = TX_VECTOR_GET_TX_SGI(prTxV); + ldpc = TX_VECTOR_GET_TX_LDPC(prTxV); + stbc = TX_VECTOR_GET_TX_STBC(prTxV); + txpwr = TX_VECTOR_GET_TX_PWR(prTxV); + + if (prTxV->u4TxVector1 == 0xFFFFFFFF) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Last TX Rate", " = ", "N/A"); + } else { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s", "Last TX Rate", " = "); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, ", rate < 4 ? HW_TX_RATE_CCK_STR[rate] : HW_TX_RATE_CCK_STR[4]); + else if (txmode == TX_RATE_MODE_OFDM) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, ", hw_rate_ofdm_str(rate)); + else if ((txmode == TX_RATE_MODE_HTMIX) || (txmode == TX_RATE_MODE_HTGF)) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "MCS%d, ", rate); + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "NSS%d_MCS%d, ", nsts, rate); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, ", frmode < 4 ? HW_TX_RATE_BW[frmode] : HW_TX_RATE_BW[4]); + + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, ", rate < 4 ? "LP" : "SP"); + else if (txmode == TX_RATE_MODE_OFDM) + ; + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s, ", sgi == 0 ? "LGI" : "SGI"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s%s%s\n", txmode < 5 ? HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5], + stbc ? ", STBC, " : ", ", ldpc == 0 ? "BCC" : "LDPC"); + } + + return i4BytesWritten; +} + +static INT_32 priv_driver_dump_stat_info(P_ADAPTER_T prAdapter, IN char *pcCommand, IN int i4TotalLen, + P_PARAM_HW_WLAN_INFO_T prHwWlanInfo, P_PARAM_GET_STA_STATISTICS prQueryStaStatistics, BOOLEAN fgResetCnt, + UINT_32 u4StatGroup) +{ + INT_32 i4BytesWritten = 0; + PARAM_RSSI rRssi = 0; + UINT_16 u2LinkSpeed; + UINT_32 u4Per, u4RxPer[ENUM_BAND_NUM], u4AmpduPer[ENUM_BAND_NUM], u4InstantPer; + UINT_8 ucDbdcIdx, ucStaIdx, ucNss; + UINT_8 ucSkipAr; + static UINT_32 u4TotalTxCnt, u4TotalFailCnt; + static UINT_32 u4Rate1TxCnt, u4Rate1FailCnt; + static UINT_32 au4RxMpduCnt[ENUM_BAND_NUM] = {0}; + static UINT_32 au4FcsError[ENUM_BAND_NUM] = {0}; + static UINT_32 au4RxFifoCnt[ENUM_BAND_NUM] = {0}; + static UINT_32 au4AmpduTxSfCnt[ENUM_BAND_NUM] = {0}; + static UINT_32 au4AmpduTxAckSfCnt[ENUM_BAND_NUM] = {0}; + P_RX_CTRL_T prRxCtrl; + UINT_32 u4InstantRxPer[ENUM_BAND_NUM]; + PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + INT_16 i2Wf0AvgPwr; + INT_16 i2Wf1AvgPwr; + UINT_32 u4BufLen = 0; + + ucSkipAr = prQueryStaStatistics->ucSkipAr; + prRxCtrl = &prAdapter->rRxCtrl; + ucNss = prAdapter->rWifiVar.ucNSS; + + if (ucSkipAr) { + u4TotalTxCnt += prHwWlanInfo->rWtblTxCounter.u2CurBwTxCnt + + prHwWlanInfo->rWtblTxCounter.u2OtherBwTxCnt; + u4TotalFailCnt += prHwWlanInfo->rWtblTxCounter.u2CurBwFailCnt + + prHwWlanInfo->rWtblTxCounter.u2OtherBwFailCnt; + u4Rate1TxCnt += prHwWlanInfo->rWtblTxCounter.u2Rate1TxCnt; + u4Rate1FailCnt += prHwWlanInfo->rWtblTxCounter.u2Rate1FailCnt; + } + + if (ucSkipAr) { + u4Per = (prHwWlanInfo->rWtblTxCounter.u2Rate1TxCnt == 0) ? + (0) : (1000 * u4Rate1FailCnt / u4Rate1TxCnt); + + u4InstantPer = (prHwWlanInfo->rWtblTxCounter.u2Rate1TxCnt == 0) ? + (0) : (1000 * (prHwWlanInfo->rWtblTxCounter.u2Rate1FailCnt) / + (prHwWlanInfo->rWtblTxCounter.u2Rate1TxCnt)); + } else { + u4Per = (prQueryStaStatistics->u4Rate1TxCnt == 0) ? + (0) : (1000 * (prQueryStaStatistics->u4Rate1FailCnt) / + (prQueryStaStatistics->u4Rate1TxCnt)); + + u4InstantPer = (prQueryStaStatistics->ucPer == 0) ? + (0) : (prQueryStaStatistics->ucPer); + } + + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; ucDbdcIdx++) { + au4RxMpduCnt[ucDbdcIdx] += prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4RxMpduCnt; + au4FcsError[ucDbdcIdx] += prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4FcsError; + au4RxFifoCnt[ucDbdcIdx] += prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4RxFifoFull; + au4AmpduTxSfCnt[ucDbdcIdx] += prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4AmpduTxSfCnt; + au4AmpduTxAckSfCnt[ucDbdcIdx] += prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4AmpduTxAckSfCnt; + + u4RxPer[ucDbdcIdx] = ((au4RxMpduCnt[ucDbdcIdx] + au4FcsError[ucDbdcIdx]) == 0) ? + (0) : (1000 * au4FcsError[ucDbdcIdx] / + (au4RxMpduCnt[ucDbdcIdx] + au4FcsError[ucDbdcIdx])); + + u4AmpduPer[ucDbdcIdx] = (au4AmpduTxSfCnt[ucDbdcIdx] == 0) ? + (0) : (1000 * (au4AmpduTxSfCnt[ucDbdcIdx] - au4AmpduTxAckSfCnt[ucDbdcIdx]) / + au4AmpduTxSfCnt[ucDbdcIdx]); + + u4InstantRxPer[ucDbdcIdx] = ((prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4RxMpduCnt + + prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4FcsError) == 0) ? + (0) : (1000 * prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4FcsError / + (prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4RxMpduCnt + + prQueryStaStatistics->rMibInfo[ucDbdcIdx].u4FcsError)); + } + + /* get Beacon RSSI */ + rStatus = kalIoctl(prAdapter->prGlueInfo, + wlanoidQueryRssi, &rRssi, sizeof(rRssi), TRUE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "unable to retrieve rssi\n"); + + u2LinkSpeed = (prQueryStaStatistics->u2LinkSpeed == 0) ? 0 : prQueryStaStatistics->u2LinkSpeed / 2; + + /* =========== Group 0x0001 =========== */ + if (u4StatGroup & 0x0001) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "\n----- STA Stat (Group 0x01) -----\n"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CurrTemperature", " = ", + prQueryStaStatistics->ucTemperature); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Tx Total cnt", " = ", ucSkipAr ? + (u4TotalTxCnt) : (prQueryStaStatistics->u4TransmitCount)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Tx Fail Cnt", " = ", ucSkipAr ? + (u4TotalFailCnt) : (prQueryStaStatistics->u4TransmitFailCount)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Rate1 Tx Cnt", " = ", ucSkipAr ? + (u4Rate1TxCnt) : (prQueryStaStatistics->u4Rate1TxCnt)); + + if (ucSkipAr) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d, PER = %d.%1d%%, instant PER = %d.%1d%%\n", "Rate1 Fail Cnt", " = ", + u4Rate1FailCnt, u4Per/10, u4Per%10, u4InstantPer/10, u4InstantPer%10); + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d, PER = %d.%1d%%, instant PER = %d%%\n", "Rate1 Fail Cnt", " = ", + prQueryStaStatistics->u4Rate1FailCnt, u4Per/10, u4Per%10, u4InstantPer); + + if ((ucSkipAr) && (fgResetCnt)) { + u4TotalTxCnt = 0; + u4TotalFailCnt = 0; + u4Rate1TxCnt = 0; + u4Rate1FailCnt = 0; + } + } + + /* =========== Group 0x0002 =========== */ + if (u4StatGroup & 0x0002) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "----- MIB Info (Group 0x02) -----\n"); + + if (!prAdapter->rWifiVar.fgDbDcModeEn) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RX Success", " = ", au4RxMpduCnt[ENUM_BAND_0]); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d, PER = %d.%1d%%, instant PER = %d.%1d%%\n", "RX with CRC", " = ", + au4FcsError[ENUM_BAND_0], u4RxPer[ENUM_BAND_0]/10, u4RxPer[ENUM_BAND_0]%10, + u4InstantRxPer[ENUM_BAND_0]/10, u4InstantRxPer[ENUM_BAND_0]%10); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RX drop FIFO full", " = ", au4RxFifoCnt[ENUM_BAND_0]); + } else { + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; ucDbdcIdx++) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "[DBDC_%d] :\n", ucDbdcIdx); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RX Success", " = ", au4RxMpduCnt[ucDbdcIdx]); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d, PER = %d.%1d%%, instant PER = %d.%1d%%\n", "RX with CRC", " = ", + au4FcsError[ucDbdcIdx], u4RxPer[ucDbdcIdx]/10, u4RxPer[ucDbdcIdx]%10, + u4InstantRxPer[ucDbdcIdx]/10, u4InstantRxPer[ucDbdcIdx]%10); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RX drop FIFO full", " = ", au4RxFifoCnt[ucDbdcIdx]); +#if 0 + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "AMPDU Tx success", " = ", au4AmpduTxSfCnt[ucDbdcIdx]); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d, PER = %d.%1d%%\n", "AMPDU Tx fail count", " = ", + (au4AmpduTxSfCnt[ucDbdcIdx] - au4AmpduTxAckSfCnt[ucDbdcIdx]), + u4AmpduPer[ucDbdcIdx]/10, u4AmpduPer[ucDbdcIdx]%10); +#endif + } + } + + if (fgResetCnt) { + kalMemZero(au4RxMpduCnt, sizeof(au4RxMpduCnt)); + kalMemZero(au4FcsError, sizeof(au4RxMpduCnt)); + kalMemZero(au4RxFifoCnt, sizeof(au4RxMpduCnt)); + kalMemZero(au4AmpduTxSfCnt, sizeof(au4RxMpduCnt)); + kalMemZero(au4AmpduTxAckSfCnt, sizeof(au4RxMpduCnt)); + } + } + + /* =========== Group 0x0004 =========== */ + if (u4StatGroup & 0x0004) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "----- Last Rx Info (Group 0x04) -----\n"); + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + 1; + + rStatus = kalIoctl(prAdapter->prGlueInfo, + wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u, rSwCtrlInfo.u4Data 0x%x\n", rStatus, rSwCtrlInfo.u4Data); + if (rStatus == WLAN_STATUS_SUCCESS) { + i2Wf0AvgPwr = rSwCtrlInfo.u4Data & 0xFFFF; + i2Wf1AvgPwr = (rSwCtrlInfo.u4Data >> 16) & 0xFFFF; + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d %d\n", "NOISE", " = ", i2Wf0AvgPwr, i2Wf1AvgPwr); + } + + /* Last RX Rate */ + i4BytesWritten += priv_driver_rx_rate_info(prAdapter, pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, (UINT_8)(prHwWlanInfo->u4Index)); + + /* Last RX RSSI */ + i4BytesWritten += priv_driver_last_rx_rssi(prAdapter, pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, (UINT_8)(prHwWlanInfo->u4Index)); + + /* Last RX Resp RSSI */ + if (ucNss > 2) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d %d %d %d\n", "Tx Response RSSI", " = ", + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi0), + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi1), + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi2), + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi3)); + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d %d\n", "Tx Response RSSI", " = ", + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi0), + RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi1)); + + /* Last Beacon RSSI */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Beacon RSSI", " = ", rRssi); + } + + /* =========== Group 0x0008 =========== */ + if (u4StatGroup & 0x0008) { + /* TxV */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "----- Last TX Info (Group 0x08) -----\n"); + + if (!prAdapter->rWifiVar.fgDbDcModeEn) { + i4BytesWritten += priv_driver_tx_vector_info(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, &prQueryStaStatistics->rTxVector[ENUM_BAND_0]); + + if (prQueryStaStatistics->rTxVector[ENUM_BAND_0].u4TxVector1 == 0xFFFFFFFF) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Chip Out TX Power", " = ", "N/A"); + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%ld.%1ld dBm\n", "Chip Out TX Power", " = ", + TX_VECTOR_GET_TX_PWR(&prQueryStaStatistics->rTxVector[ENUM_BAND_0]) >> 1, + 5 * (TX_VECTOR_GET_TX_PWR(&prQueryStaStatistics->rTxVector[ENUM_BAND_0]) % 2)); + } else { + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; ucDbdcIdx++) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "[DBDC_%d] :\n", ucDbdcIdx); + + i4BytesWritten += priv_driver_tx_vector_info(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, &prQueryStaStatistics->rTxVector[ucDbdcIdx]); + + if (prQueryStaStatistics->rTxVector[ucDbdcIdx].u4TxVector1 == 0xFFFFFFFF) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%-20s%s%s\n", "Chip Out TX Power", " = ", "N/A"); + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%-20s%s%ld.%1ld dBm\n", "ChipOut TX Power", " = ", + TX_VECTOR_GET_TX_PWR(&prQueryStaStatistics->rTxVector[ucDbdcIdx]) >> 1, + 5 * (TX_VECTOR_GET_TX_PWR(&prQueryStaStatistics->rTxVector[ucDbdcIdx]) % 2)); +#if 0 + if (prQueryStaStatistics->rTxVector[ucDbdcIdx].u4TxVector2 == 0xFFFFFFFF) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%-20s%s%s\n", "Beamform Enable", " = ", "N/A"); + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%-20s%s%d\n", "Beamform Enable", " = ", + TX_VECTOR_GET_BF_EN(&prQueryStaStatistics->rTxVector[ucDbdcIdx]) ? 1 : 0); + + if (prQueryStaStatistics->rTxVector[ucDbdcIdx].u4TxVector4 == 0xFFFFFFFF) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + "%-20s%s%s\n", "Dynamic BW", " = ", "N/A"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%-20s%s%s\n", "Sounding Pkt", " = ", "N/A"); + } else { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%-20s%s%d\n", "Dynamic BW", " = ", + TX_VECTOR_GET_DYN_BW(&prQueryStaStatistics->rTxVector[ucDbdcIdx]) ? 1 : 0); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%-20s%s%d\n", "Sounding Pkt", " = ", + TX_VECTOR_GET_NO_SOUNDING(&prQueryStaStatistics->rTxVector[ucDbdcIdx]) ? 1 : 0); + } +#endif + } + } + } + + /* =========== Group 0x0010 =========== */ + if (u4StatGroup & 0x0010) { + /* RX Reorder */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "------ RX Reorder (Group 0x10) -----\n"); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%ld\n", "Rx reorder miss", " = ", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_MISS_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%ld\n", "Rx reorder within", " = ", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_WITHIN_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%ld\n", "Rx reorder ahead", " = ", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_AHEAD_COUNT)); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%ld\n", "Rx reorder behind", " = ", + RX_GET_CNT(prRxCtrl, RX_DATA_REORDER_BEHIND_COUNT)); + } + + /* =========== Group 0x0020 =========== */ + if (u4StatGroup & 0x0020) { + /* AR info */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "------ AR Info (Group 0x20) -----\n"); + + /* Last TX Rate */ + i4BytesWritten += priv_driver_tx_rate_info(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, FALSE, prHwWlanInfo, prQueryStaStatistics); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "LinkSpeed", " = ", u2LinkSpeed); + + if (!prQueryStaStatistics->ucSkipAr) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "RateTable", " = ", prQueryStaStatistics->ucArTableIdx < RATE_TBL_MAX ? + RATE_TBLE[prQueryStaStatistics->ucArTableIdx] : RATE_TBLE[RATE_TBL_MAX]); + + if (wlanGetStaIdxByWlanIdx(prAdapter, (UINT_8)(prHwWlanInfo->u4Index), &ucStaIdx) == + WLAN_STATUS_SUCCESS){ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "2G Support 256QAM TX", " = ", + (prAdapter->arStaRec[ucStaIdx].u4Flags & MTK_SYNERGY_CAP_SUPPORT_24G_MCS89) ? + 1 : 0); + } + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d%%\n", "Rate1 instantPer", " = ", u4InstantPer); + + if (prQueryStaStatistics->ucAvePer == 0xFF) { +#if 0 + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "average RSSI", " = ", "N/A"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Rate1 AvePer", " = ", "N/A"); +#endif + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Train Down", " = ", "N/A"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Train Up", " = ", "N/A"); +#if 0 + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Highest Rate Cnt", " = ", "N/A"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Lowest Rate Cnt", " = ", "N/A"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "SGI Pass Cnt", " = ", "N/A"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "AR State Prev", " = ", "N/A"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "AR State Curr", " = ", "N/A"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "AR Action Type", " = ", "N/A"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Rate Entry Idx", " = ", "N/A"); +#endif + } else { +#if 0 + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "average RSSI", " = ", rRssi); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d%%\n", "Rate1 AvePer", " = ", prQueryStaStatistics->ucAvePer); +#endif + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d -> %d\n", "Train Down", " = ", + (UINT_16)(prQueryStaStatistics + ->u2TrainDown & BITS(0, 7)), + (UINT_16)((prQueryStaStatistics + ->u2TrainDown >> 8) & BITS(0, 7))); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d -> %d\n", "Train Up", " = ", + (UINT_16)(prQueryStaStatistics + ->u2TrainUp & BITS(0, 7)), + (UINT_16)((prQueryStaStatistics + ->u2TrainUp >> 8) & BITS(0, 7))); +#if 0 + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Highest Rate Cnt", " = ", + prQueryStaStatistics->ucHighestRateCnt); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Lowest Rate Cnt", " = ", prQueryStaStatistics->ucLowestRateCnt); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "SGI Pass Cnt", " = ", + prQueryStaStatistics->ucTxSgiDetectPassCnt); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "AR State Prev", " = ", + prQueryStaStatistics->ucArStatePrev < 3 ? + AR_STATE[prQueryStaStatistics->ucArStatePrev] : AR_STATE[3]); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "AR State Curr", " = ", + prQueryStaStatistics->ucArStateCurr < 3 ? + AR_STATE[prQueryStaStatistics->ucArStateCurr] : AR_STATE[3]); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "AR Action Type", " = ", + prQueryStaStatistics->ucArActionType < 16 ? + AR_ACTION[prQueryStaStatistics->ucArActionType] : AR_ACTION[16]); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d -> %d\n", "Rate Entry Idx", " = ", + (prQueryStaStatistics->ucRateEntryIdxPrev == AR_RATE_ENTRY_INDEX_NULL) ? + (prQueryStaStatistics->ucRateEntryIdx) : + (prQueryStaStatistics->ucRateEntryIdxPrev), + prQueryStaStatistics->ucRateEntryIdx); +#endif + } + + if (prQueryStaStatistics->fgIsForceTxStream == 0) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Force Tx Stream", " = ", "N/A"); + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Force Tx Stream", " = ", + prQueryStaStatistics->fgIsForceTxStream); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Force SE off", " = ", prQueryStaStatistics->fgIsForceSeOff); + } + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CBRN", " = ", prHwWlanInfo->rWtblPeerCap.ucChangeBWAfterRateN); + + /* Rate1~Rate8 */ + i4BytesWritten += priv_driver_tx_rate_info(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, TRUE, prHwWlanInfo, prQueryStaStatistics); + } + + /* =========== Group 0x0040 =========== */ + if (u4StatGroup & 0x0040) { + /* Tx Agg */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "------ TX AGG (Group 0x40) -----\n"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-12s%s", "Range:", "1 2~5 6~15 16~22 23~33 34~49 50~57 58~64\n"); + + for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; ucDbdcIdx++) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "DBDC%d:", ucDbdcIdx); + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%7d%8d%9d%9d%9d%9d%9d%9d\n", + prQueryStaStatistics->rMibInfo[ucDbdcIdx].u2TxRange1AmpduCnt, + prQueryStaStatistics->rMibInfo[ucDbdcIdx].u2TxRange2AmpduCnt, + prQueryStaStatistics->rMibInfo[ucDbdcIdx].u2TxRange3AmpduCnt, + prQueryStaStatistics->rMibInfo[ucDbdcIdx].u2TxRange4AmpduCnt, + prQueryStaStatistics->rMibInfo[ucDbdcIdx].u2TxRange5AmpduCnt, + prQueryStaStatistics->rMibInfo[ucDbdcIdx].u2TxRange6AmpduCnt, + prQueryStaStatistics->rMibInfo[ucDbdcIdx].u2TxRange7AmpduCnt, + prQueryStaStatistics->rMibInfo[ucDbdcIdx].u2TxRange8AmpduCnt); + } + } + + return i4BytesWritten; +} + +static int priv_driver_get_sta_stat(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0, u4Ret, u4StatGroup = 0xFFFFFFFF; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + UINT_8 ucWlanIndex; + PUINT_8 pucMacAddr = NULL; + P_PARAM_HW_WLAN_INFO_T prHwWlanInfo = NULL; + P_PARAM_GET_STA_STATISTICS prQueryStaStatistics = NULL; + BOOLEAN fgResetCnt = FALSE; + BOOLEAN fgRxCCSel = FALSE; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= 3) { + if (strnicmp(apcArgv[1], CMD_STAT_GROUP_SEL, strlen(CMD_STAT_GROUP_SEL)) == 0) { + u4Ret = kalkStrtou32(apcArgv[2], 0, &(u4StatGroup)); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse get_mcr error (Address) u4Ret=%d\n", u4Ret); + if (u4StatGroup == 0) + u4StatGroup = 0xFFFFFFFF; + + if (prGlueInfo->prAdapter->prAisBssInfo->prStaRecOfAP) { + ucWlanIndex = prGlueInfo->prAdapter->prAisBssInfo->prStaRecOfAP->ucWlanIndex; + } else if (!wlanGetWlanIdxByAddress(prGlueInfo->prAdapter, NULL, &ucWlanIndex)) { + DBGLOG(REQ, INFO, "Can't find the wlan index of MAC addr %pM!\n", aucMacAddr); + goto out; + } + } else { + if (strnicmp(apcArgv[1], CMD_STAT_RESET_CNT, strlen(CMD_STAT_RESET_CNT)) == 0) { + wlanHwAddrToBin(apcArgv[2], &aucMacAddr[0]); + fgResetCnt = TRUE; + } else if (strnicmp(apcArgv[2], CMD_STAT_RESET_CNT, strlen(CMD_STAT_RESET_CNT)) == 0) { + wlanHwAddrToBin(apcArgv[1], &aucMacAddr[0]); + fgResetCnt = TRUE; + } else { + wlanHwAddrToBin(apcArgv[1], &aucMacAddr[0]); + fgResetCnt = FALSE; + } + + if (!wlanGetWlanIdxByAddress(prGlueInfo->prAdapter, &aucMacAddr[0], &ucWlanIndex)) { + DBGLOG(REQ, INFO, "Can't find the wlan index of MAC addr %pM!\n", aucMacAddr); + goto out; + } + } + + } else { + /* Get AIS AP address for no argument */ + if (prGlueInfo->prAdapter->prAisBssInfo->prStaRecOfAP) { + ucWlanIndex = prGlueInfo->prAdapter->prAisBssInfo->prStaRecOfAP->ucWlanIndex; + } else if (!wlanGetWlanIdxByAddress(prGlueInfo->prAdapter, NULL, &ucWlanIndex)) { + DBGLOG(REQ, INFO, "No connected peer found!\n"); + goto out; + } + + if (i4Argc == 2) { + if (strnicmp(apcArgv[1], CMD_STAT_RESET_CNT, strlen(CMD_STAT_RESET_CNT)) == 0) + fgResetCnt = TRUE; + else if (strnicmp(apcArgv[1], CMD_STAT_NOISE_SEL, strlen(CMD_STAT_NOISE_SEL)) == 0) + fgRxCCSel = TRUE; + } + } + + prHwWlanInfo = (P_PARAM_HW_WLAN_INFO_T)kalMemAlloc(sizeof(PARAM_HW_WLAN_INFO_T), VIR_MEM_TYPE); + if (!prHwWlanInfo) { + DBGLOG(REQ, ERROR, "Allocate memory for prHwWlanInfo failed!\n"); + i4BytesWritten = -1; + goto out; + } + + prHwWlanInfo->u4Index = ucWlanIndex; + if (fgRxCCSel == TRUE) + prHwWlanInfo->rWtblRxCounter.fgRxCCSel = TRUE; + else + prHwWlanInfo->rWtblRxCounter.fgRxCCSel = FALSE; + + DBGLOG(REQ, INFO, "MT6632 : index = %d i4TotalLen = %d\n", prHwWlanInfo->u4Index, i4TotalLen); + + /* Get WTBL info */ + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryWlanInfo, + prHwWlanInfo, sizeof(PARAM_HW_WLAN_INFO_T), TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "Query prHwWlanInfo failed!\n"); + i4BytesWritten = -1; + goto out; + } + + /* Get Statistics info */ + prQueryStaStatistics = + (P_PARAM_GET_STA_STATISTICS)kalMemAlloc(sizeof(PARAM_GET_STA_STA_STATISTICS), VIR_MEM_TYPE); + if (!prQueryStaStatistics) { + DBGLOG(REQ, ERROR, "Allocate memory for prQueryStaStatistics failed!\n"); + i4BytesWritten = -1; + goto out; + } + + prQueryStaStatistics->ucResetCounter = fgResetCnt; + + pucMacAddr = wlanGetStaAddrByWlanIdx(prGlueInfo->prAdapter, ucWlanIndex); + + if (!pucMacAddr) { + DBGLOG(REQ, ERROR, "Couldn't find the MAC addr of WlanIndex %d!\n", + ucWlanIndex); + i4BytesWritten = -1; + goto out; + } + + COPY_MAC_ADDR(prQueryStaStatistics->aucMacAddr, pucMacAddr); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStaStatistics, + prQueryStaStatistics, + sizeof(PARAM_GET_STA_STA_STATISTICS), TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "Query prQueryStaStatistics failed!\n"); + i4BytesWritten = -1; + goto out; + } + + if (pucMacAddr) { + i4BytesWritten = priv_driver_dump_stat_info(prAdapter, pcCommand, i4TotalLen, + prHwWlanInfo, prQueryStaStatistics, fgResetCnt, u4StatGroup); + } + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + +out: + if (prHwWlanInfo) + kalMemFree(prHwWlanInfo, VIR_MEM_TYPE, sizeof(PARAM_HW_WLAN_INFO_T)); + + if (prQueryStaStatistics) + kalMemFree(prQueryStaStatistics, VIR_MEM_TYPE, sizeof(PARAM_GET_STA_STA_STATISTICS)); + + if (fgResetCnt) + nicRxClearStatistics(prGlueInfo->prAdapter); + + return i4BytesWritten; +} + +static INT_32 priv_driver_dump_stat2_info(P_ADAPTER_T prAdapter, IN char *pcCommand, IN int i4TotalLen, + P_UMAC_STAT2_GET_T prUmacStat2GetInfo, P_PARAM_GET_DRV_STATISTICS prQueryDrvStatistics) +{ + INT_32 i4BytesWritten = 0; + UINT_16 u2PleTotalRevPage = 0; + UINT_16 u2PleTotalSrcPage = 0; + UINT_16 u2PseTotalRevPage = 0; + UINT_16 u2PseTotalSrcPage = 0; + + u2PleTotalRevPage = prUmacStat2GetInfo->u2PleRevPgHif0Group0 + + prUmacStat2GetInfo->u2PleRevPgCpuGroup2; + + u2PleTotalSrcPage = prUmacStat2GetInfo->u2PleSrvPgHif0Group0 + + prUmacStat2GetInfo->u2PleSrvPgCpuGroup2; + + u2PseTotalRevPage = prUmacStat2GetInfo->u2PseRevPgHif0Group0 + + prUmacStat2GetInfo->u2PseRevPgHif1Group1 + + prUmacStat2GetInfo->u2PseRevPgCpuGroup2 + + prUmacStat2GetInfo->u2PseRevPgLmac0Group3 + + prUmacStat2GetInfo->u2PseRevPgLmac1Group4 + + prUmacStat2GetInfo->u2PseRevPgLmac2Group5 + + prUmacStat2GetInfo->u2PseRevPgPleGroup6; + + u2PseTotalSrcPage = prUmacStat2GetInfo->u2PseSrvPgHif0Group0 + + prUmacStat2GetInfo->u2PseSrvPgHif1Group1 + + prUmacStat2GetInfo->u2PseSrvPgCpuGroup2 + + prUmacStat2GetInfo->u2PseSrvPgLmac0Group3 + + prUmacStat2GetInfo->u2PseSrvPgLmac1Group4 + + prUmacStat2GetInfo->u2PseSrvPgLmac2Group5 + + prUmacStat2GetInfo->u2PseSrvPgPleGroup6; + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "\n----- Stat2 Info -----\n"); + + + /* Rev Page number Info. */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "\n----- PLE Reservation Page Info. -----\n"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Ple Hif0 Group0 RevPage", " = ", + prUmacStat2GetInfo->u2PleRevPgHif0Group0); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Ple Cpu Group2 RevPage", " = ", + prUmacStat2GetInfo->u2PleRevPgCpuGroup2); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Ple Total RevPage", " = ", + u2PleTotalRevPage); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "\n----- PLE Source Page Info. ----------\n"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Ple Hif0 Group0 SrcPage", " = ", + prUmacStat2GetInfo->u2PleSrvPgHif0Group0); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Ple Cpu Group2 SrcPage", " = ", + prUmacStat2GetInfo->u2PleSrvPgCpuGroup2); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Ple Total SrcPage", " = ", + u2PleTotalSrcPage); + + /* umac MISC Info. */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "\n----- PLE Misc Info. -----------------\n"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "ple Total Page Number", " = ", + prUmacStat2GetInfo->u2PleTotalPageNum); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "ple Free Page Number", " = ", + prUmacStat2GetInfo->u2PleFreePageNum); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "ple FFA Page Number", " = ", + prUmacStat2GetInfo->u2PleFfaNum); + + /* PSE Info. */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "\n----- PSE Reservation Page Info. -----\n"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Hif0 Group0 RevPage", " = ", + prUmacStat2GetInfo->u2PseRevPgHif0Group0); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Hif1 Group1 RevPage", " = ", + prUmacStat2GetInfo->u2PseRevPgHif1Group1); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Cpu Group2 RevPage", " = ", + prUmacStat2GetInfo->u2PseRevPgCpuGroup2); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Lmac0 Group3 RevPage", " = ", + prUmacStat2GetInfo->u2PseRevPgLmac0Group3); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Lmac1 Group4 RevPage", " = ", + prUmacStat2GetInfo->u2PseRevPgLmac1Group4); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Lmac2 Group5 RevPage", " = ", + prUmacStat2GetInfo->u2PseRevPgLmac2Group5); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Ple Group6 RevPage", " = ", + prUmacStat2GetInfo->u2PseRevPgPleGroup6); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Total RevPage", " = ", + u2PseTotalRevPage); + + /* PSE Info. */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "\n----- PSE Source Page Info. ----------\n"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Hif0 Group0 SrcPage", " = ", + prUmacStat2GetInfo->u2PseSrvPgHif0Group0); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Hif1 Group1 SrcPage", " = ", + prUmacStat2GetInfo->u2PseSrvPgHif1Group1); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Cpu Group2 SrcPage", " = ", + prUmacStat2GetInfo->u2PseSrvPgCpuGroup2); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Lmac0 Group3 SrcPage", " = ", + prUmacStat2GetInfo->u2PseSrvPgLmac0Group3); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Lmac1 Group4 SrcPage", " = ", + prUmacStat2GetInfo->u2PseSrvPgLmac1Group4); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Lmac2 Group5 SrcPage", " = ", + prUmacStat2GetInfo->u2PseSrvPgLmac2Group5); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Ple Group6 SrcPage", " = ", + prUmacStat2GetInfo->u2PseSrvPgPleGroup6); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pse Total SrcPage", " = ", + u2PseTotalSrcPage); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "\n----- PSE Misc Info. -----------------\n"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "pse Total Page Number", " = ", + prUmacStat2GetInfo->u2PseTotalPageNum); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "pse Free Page Number", " = ", + prUmacStat2GetInfo->u2PseFreePageNum); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "pse FFA Page Number", " = ", + prUmacStat2GetInfo->u2PseFfaNum); + + + /* driver info */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "\n\n----- DRV Stat -----------------------\n\n"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pending Data", " = ", + prQueryDrvStatistics->i4TxPendingFrameNum); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Pending Sec", " = ", + prQueryDrvStatistics->i4TxPendingSecurityFrameNum); +#if 0 + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%s\n", "Tx Pending Cmd Number", " = ", + prQueryDrvStatistics->i4TxPendingCmdNum); +#endif + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Tx Pending For-pkt Number", " = ", + prQueryDrvStatistics->i4PendingFwdFrameCount); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "MsduInfo Available Number", " = ", + prQueryDrvStatistics->u4MsduNumElem); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "MgmtTxRing Pending Number", " = ", + prQueryDrvStatistics->u4TxMgmtTxringQueueNumElem); + + /* Driver Rx Info. */ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Rx Free Sw Rfb Number", " = ", + prQueryDrvStatistics->u4RxFreeSwRfbMsduNumElem); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Rx Received Sw Rfb Number", " = ", + prQueryDrvStatistics->u4RxReceivedRfbNumElem); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-26s%s%d\n", "Rx Indicated Sw Rfb Number", " = ", + prQueryDrvStatistics->u4RxIndicatedNumElem); + + return i4BytesWritten; +} + +static int priv_driver_get_sta_stat2(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + INT_32 i4BytesWritten = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 i4ArgNum = 1; + P_UMAC_STAT2_GET_T prUmacStat2GetInfo = NULL; + P_PARAM_GET_DRV_STATISTICS prQueryDrvStatistics = NULL; + P_QUE_T prQueList, prTxMgmtTxRingQueList; + P_RX_CTRL_T prRxCtrl; + + KAL_SPIN_LOCK_DECLARATION(); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc < i4ArgNum) + return -1; + + prQueList = &prAdapter->rTxCtrl.rFreeMsduInfoList; + + prTxMgmtTxRingQueList = &prAdapter->rTxCtrl.rTxMgmtTxingQueue; + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + /* to do for UMAC Dump */ + prUmacStat2GetInfo = (P_UMAC_STAT2_GET_T)kalMemAlloc(sizeof(UMAC_STAT2_GET_T), VIR_MEM_TYPE); + if (!prUmacStat2GetInfo) { + DBGLOG(REQ, ERROR, "allocate memory for prUmacStat2GetInfo failed\n"); + i4BytesWritten = -1; + goto out; + } + + halUmacInfoGetMiscStatus(prAdapter, prUmacStat2GetInfo); + + + /* Get Driver stat info */ + prQueryDrvStatistics = + (P_PARAM_GET_DRV_STATISTICS)kalMemAlloc(sizeof(PARAM_GET_DRV_STATISTICS), VIR_MEM_TYPE); + if (!prQueryDrvStatistics) { + DBGLOG(REQ, ERROR, "allocate memory for prQueryDrvStatistics failed\n"); + i4BytesWritten = -1; + goto out; + } + + prQueryDrvStatistics->i4TxPendingFrameNum = + (UINT_32) GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingFrameNum); + prQueryDrvStatistics->i4TxPendingSecurityFrameNum = + (UINT_32) GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum); +#if 0 + prQueryDrvStatistics->i4TxPendingCmdNum = + (UINT_32) GLUE_GET_REF_CNT(prGlueInfo->i4TxPendingCmdNum); +#endif + + prQueryDrvStatistics->i4PendingFwdFrameCount = prAdapter->rTxCtrl.i4PendingFwdFrameCount; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + prQueryDrvStatistics->u4MsduNumElem = prQueList->u4NumElem; + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + prQueryDrvStatistics->u4TxMgmtTxringQueueNumElem = prTxMgmtTxRingQueList->u4NumElem; + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + prQueryDrvStatistics->u4RxFreeSwRfbMsduNumElem = prRxCtrl->rFreeSwRfbList.u4NumElem; + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + prQueryDrvStatistics->u4RxReceivedRfbNumElem = prRxCtrl->rReceivedRfbList.u4NumElem; + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + prQueryDrvStatistics->u4RxIndicatedNumElem = prRxCtrl->rIndicatedRfbList.u4NumElem; + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + + i4BytesWritten = priv_driver_dump_stat2_info(prAdapter, pcCommand, i4TotalLen, + prUmacStat2GetInfo, prQueryDrvStatistics); + +out: + if (prUmacStat2GetInfo) + kalMemFree(prUmacStat2GetInfo, VIR_MEM_TYPE, sizeof(UMAC_STAT2_GET_T)); + if (prQueryDrvStatistics) + kalMemFree(prQueryDrvStatistics, VIR_MEM_TYPE, sizeof(PARAM_GET_DRV_STATISTICS)); + + return i4BytesWritten; +} + + +static INT_32 priv_driver_dump_rx_stat_info(P_ADAPTER_T prAdapter, IN char *pcCommand, IN int i4TotalLen, + IN BOOLEAN fgResetCnt) +{ + INT_32 i4BytesWritten = 0; + UINT_32 u4RxVector0 = 0, u4RxVector2 = 0, u4RxVector3 = 0, u4RxVector4 = 0; + UINT_8 ucStaIdx, ucWlanIndex, cbw; + BOOLEAN fgWlanIdxFound = TRUE, fgSkipRxV = FALSE; + UINT_32 u4FAGCRssiWBR0, u4FAGCRssiIBR0; + UINT_32 u4Value, u4Foe, foe_const; + static UINT_32 au4MacMdrdy[ENUM_BAND_NUM] = {0}; + static UINT_32 au4FcsError[ENUM_BAND_NUM] = {0}; + static UINT_32 au4OutOfResource[ENUM_BAND_NUM] = {0}; + static UINT_32 au4LengthMismatch[ENUM_BAND_NUM] = {0}; + + au4MacMdrdy[ENUM_BAND_0] += htonl(g_HqaRxStat.MAC_Mdrdy); + au4MacMdrdy[ENUM_BAND_1] += htonl(g_HqaRxStat.MAC_Mdrdy1); + au4FcsError[ENUM_BAND_0] += htonl(g_HqaRxStat.MAC_FCS_Err); + au4FcsError[ENUM_BAND_1] += htonl(g_HqaRxStat.MAC_FCS_Err1); + au4OutOfResource[ENUM_BAND_0] += htonl(g_HqaRxStat.OutOfResource); + au4OutOfResource[ENUM_BAND_1] += htonl(g_HqaRxStat.OutOfResource1); + au4LengthMismatch[ENUM_BAND_0] += htonl(g_HqaRxStat.LengthMismatchCount_B0); + au4LengthMismatch[ENUM_BAND_1] += htonl(g_HqaRxStat.LengthMismatchCount_B1); + + if (fgResetCnt) { + kalMemZero(au4MacMdrdy, sizeof(au4MacMdrdy)); + kalMemZero(au4FcsError, sizeof(au4FcsError)); + kalMemZero(au4OutOfResource, sizeof(au4OutOfResource)); + kalMemZero(au4LengthMismatch, sizeof(au4LengthMismatch)); + } + + if (prAdapter->prAisBssInfo->prStaRecOfAP) + ucWlanIndex = prAdapter->prAisBssInfo->prStaRecOfAP->ucWlanIndex; + else if (!wlanGetWlanIdxByAddress(prAdapter, NULL, &ucWlanIndex)) + fgWlanIdxFound = FALSE; + + if (fgWlanIdxFound) { + if (wlanGetStaIdxByWlanIdx(prAdapter, ucWlanIndex, &ucStaIdx) == WLAN_STATUS_SUCCESS) { + u4RxVector0 = prAdapter->arStaRec[ucStaIdx].u4RxVector0; + u4RxVector2 = prAdapter->arStaRec[ucStaIdx].u4RxVector2; + u4RxVector3 = prAdapter->arStaRec[ucStaIdx].u4RxVector3; + u4RxVector4 = prAdapter->arStaRec[ucStaIdx].u4RxVector4; + } else{ + fgSkipRxV = TRUE; + } + } else{ + fgSkipRxV = TRUE; + } + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", "\n\nRX Stat:\n"); +#if 0 + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "PER0", " = ", + g_HqaRxStat.PER0); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "PER1", " = ", + g_HqaRxStat.PER1); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RX OK0", " = ", + g_HqaRxStat.RXOK0); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RX OK1", " = ", + g_HqaRxStat.RXOK1); +#endif + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "MAC Mdrdy0", " = ", + au4MacMdrdy[ENUM_BAND_0]); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "MAC Mdrdy1", " = ", + au4MacMdrdy[ENUM_BAND_1]); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "FCS Err0", " = ", + au4FcsError[ENUM_BAND_0]); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "FCS Err1", " = ", + au4FcsError[ENUM_BAND_1]); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK PD Cnt B0", " = ", + htonl(g_HqaRxStat.CCK_PD)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK PD Cnt B1", " = ", + htonl(g_HqaRxStat.CCK_PD_Band1)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK SIG Err B0", " = ", + htonl(g_HqaRxStat.CCK_SIG_Err)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK SIG Err B1", " = ", + htonl(g_HqaRxStat.CCK_SIG_Err_Band1)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM PD Cnt B0", " = ", + htonl(g_HqaRxStat.OFDM_PD)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM PD Cnt B1", " = ", + htonl(g_HqaRxStat.OFDM_PD_Band1)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM TAG Error", " = ", + htonl(g_HqaRxStat.OFDM_TAG_Err)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK SFD Err B0", " = ", + htonl(g_HqaRxStat.CCK_SFD_Err)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK SFD Err B1", " = ", + htonl(g_HqaRxStat.CCK_SFD_Err_Band1)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM SIG Err B0", " = ", + htonl(g_HqaRxStat.OFDM_SIG_Err)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM SIG Err B1", " = ", + htonl(g_HqaRxStat.OFDM_SIG_Err_Band1)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK FCS Err B0", " = ", + htonl(g_HqaRxStat.FCSErr_CCK)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK FCS Err B1", " = ", + htonl(g_HqaRxStat.CCK_FCS_Err_Band1)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM FCS Err B0", " = ", + htonl(g_HqaRxStat.FCSErr_OFDM)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM FCS Err B1", " = ", + htonl(g_HqaRxStat.OFDM_FCS_Err_Band1)); + + if (!fgSkipRxV) { + u4FAGCRssiIBR0 = (u4RxVector2 & BITS(16, 23)) >> 16; + u4FAGCRssiWBR0 = (u4RxVector2 & BITS(24, 31)) >> 24; + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "FAGC RSSI W", " = ", + (u4FAGCRssiWBR0 >= 128) ? (u4FAGCRssiWBR0 - 256) : (u4FAGCRssiWBR0)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "FAGC RSSI I", " = ", + (u4FAGCRssiIBR0 >= 128) ? (u4FAGCRssiIBR0 - 256) : (u4FAGCRssiIBR0)); + } else{ + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "FAGC RSSI W", " = ", "N/A"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "FAGC RSSI I", " = ", "N/A"); + } + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK MDRDY B0", " = ", + htonl(g_HqaRxStat.PhyMdrdyCCK)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "CCK MDRDY B1", " = ", + htonl(g_HqaRxStat.PHY_CCK_MDRDY_Band1)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM MDRDY B0", " = ", + htonl(g_HqaRxStat.PhyMdrdyOFDM)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OFDM MDRDY B1", " = ", + htonl(g_HqaRxStat.PHY_OFDM_MDRDY_Band1)); + + if (!fgSkipRxV) { +#if 0 + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Driver RX Cnt0", " = ", + htonl(g_HqaRxStat.DriverRxCount)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Driver RX Cnt1", " = ", + htonl(g_HqaRxStat.DriverRxCount1)); +#endif + u4Value = (u4RxVector0 & BITS(12, 14)) >> 12; + if (u4Value == 0) { + u4Foe = (((u4RxVector4 & BITS(7, 31)) >> 7) & 0x7ff); + u4Foe = (u4Foe * 1000)>>11; + } else{ + cbw = ((u4RxVector0 & BITS(15, 16)) >> 15); + foe_const = ((1 << (cbw + 1)) & 0xf) * 10000; + u4Foe = (((u4RxVector4 & BITS(7, 31)) >> 7) & 0xfff); + u4Foe = (u4Foe * foe_const) >> 15; + } + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Freq Offset From RX", " = ", u4Foe); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RX SNR (dB)", " = ", + (UINT_32)(((u4RxVector4 & BITS(26, 31)) >> 26) - 16)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RCPI RX0", " = ", + (UINT_32)(u4RxVector3 & BITS(0, 7))); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RCPI RX1", " = ", + (UINT_32)((u4RxVector3 & BITS(8, 15)) >> 8)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RCPI RX2", " = ", + ((u4RxVector3 & BITS(16, 23)) >> 16) == 0xFF ? (0) : + (UINT_32)((u4RxVector3 & BITS(16, 23)) >> 16)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "RCPI RX3", " = ", + ((u4RxVector3 & BITS(24, 31)) >> 24) == 0xFF ? (0) : + (UINT_32)((u4RxVector3 & BITS(24, 31)) >> 24)); + } else{ +#if 0 + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Driver RX Cnt0", " = ", "N/A"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Driver RX Cnt1", " = ", "N/A"); +#endif + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "Freq Offset From RX", " = ", "N/A"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "RX SNR (dB)", " = ", "N/A"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "RCPI RX0", " = ", "N/A"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "RCPI RX1", " = ", "N/A"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "RCPI RX2", " = ", "N/A"); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%s\n", "RCPI RX3", " = ", "N/A"); + } + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Inst RSSI IB R0", " = ", + htonl(g_HqaRxStat.InstRssiIBR0)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Inst RSSI WB R0", " = ", + htonl(g_HqaRxStat.InstRssiWBR0)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Inst RSSI IB R1", " = ", + htonl(g_HqaRxStat.InstRssiIBR1)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Inst RSSI WB R1", " = ", + htonl(g_HqaRxStat.InstRssiWBR1)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Inst RSSI IB R2", " = ", + htonl(g_HqaRxStat.InstRssiIBR2)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Inst RSSI WB R2", " = ", + htonl(g_HqaRxStat.InstRssiWBR2)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Inst RSSI IB R3", " = ", + htonl(g_HqaRxStat.InstRssiIBR3)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Inst RSSI WB R3", " = ", + htonl(g_HqaRxStat.InstRssiWBR3)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "ACI Hit Lower", " = ", + htonl(g_HqaRxStat.ACIHitLower)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "ACI Hit Higher", " = ", + htonl(g_HqaRxStat.ACIHitUpper)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OutOf Resource Pkt0", " = ", + au4OutOfResource[ENUM_BAND_0]); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "OutOf Resource Pkt1", " = ", + au4OutOfResource[ENUM_BAND_1]); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Len Mismatch Cnt B0", " = ", + au4LengthMismatch[ENUM_BAND_0]); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "Len Mismatch Cnt B1", " = ", + au4LengthMismatch[ENUM_BAND_1]); +#if 0 + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%-20s%s%d\n", "MU RX Cnt", " = ", + htonl(g_HqaRxStat.MRURxCount)); +#endif + return i4BytesWritten; +} + + +static int priv_driver_show_rx_stat(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + P_PARAM_CUSTOM_ACCESS_RX_STAT prRxStatisticsTest; + BOOLEAN fgResetCnt = FALSE; + PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo; + UINT_32 u4Id = 0x99980000; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + DBGLOG(INIT, ERROR, "MT6632 : priv_driver_show_rx_stat\n"); + + if (i4Argc >= 2) { + if (strnicmp(apcArgv[1], CMD_STAT_RESET_CNT, strlen(CMD_STAT_RESET_CNT)) == 0) + fgResetCnt = TRUE; + } + + if (i4Argc >= 1) { + if (fgResetCnt) { + rSwCtrlInfo.u4Id = u4Id; + rSwCtrlInfo.u4Data = 0; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } + + prRxStatisticsTest = + (P_PARAM_CUSTOM_ACCESS_RX_STAT)kalMemAlloc(sizeof(PARAM_CUSTOM_ACCESS_RX_STAT), VIR_MEM_TYPE); + if (!prRxStatisticsTest) + return -1; + + prRxStatisticsTest->u4SeqNum = u4RxStatSeqNum; + prRxStatisticsTest->u4TotalNum = sizeof(PARAM_RX_STAT_T) / 4; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryRxStatistics, + prRxStatisticsTest, sizeof(PARAM_CUSTOM_ACCESS_RX_STAT), + TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + kalMemFree(prRxStatisticsTest, VIR_MEM_TYPE, sizeof(PARAM_CUSTOM_ACCESS_RX_STAT)); + return -1; + } + + i4BytesWritten = priv_driver_dump_rx_stat_info(prAdapter, pcCommand, i4TotalLen, fgResetCnt); + + kalMemFree(prRxStatisticsTest, VIR_MEM_TYPE, sizeof(PARAM_CUSTOM_ACCESS_RX_STAT)); + } + + return i4BytesWritten; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Handle command to get current Tx rate from rate table and respond +* string buffer. Example: VHT-2SS-BW80-SGI-MCS7 +* +* \param[in] net_device Pointer to the Adapter structure. +* \param[out] pcCommand Pointer to the command buffer to respond. +* \param[in] i4TotalLen The length of buffer. +* +* \retval Length of response buffer +*/ +/*----------------------------------------------------------------------------*/ +static int priv_driver_get_sta_curr_ar_rate(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + UINT_8 ucWlanIndex = 0; + PUINT_8 pucMacAddr = NULL; + UINT_8 idx, txmode, rate; + P_PARAM_GET_STA_STATISTICS prQueryStaStatistics = NULL; + P_PARAM_HW_WLAN_INFO_T prHwWlanInfo = NULL; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -EINVAL; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + /* Get AIS AP address for no argument */ + if (prAdapter->prAisBssInfo->prStaRecOfAP) + ucWlanIndex = prAdapter->prAisBssInfo->prStaRecOfAP->ucWlanIndex; + else if (!wlanGetWlanIdxByAddress(prAdapter, NULL, &ucWlanIndex)) + return i4BytesWritten; + pucMacAddr = wlanGetStaAddrByWlanIdx(prAdapter, ucWlanIndex); + if (!pucMacAddr) { + DBGLOG(REQ, WARN, "%s: MAC address is invalid!\n", __func__); + return -EFAULT; + } + /* Get WTBL info */ + prHwWlanInfo = (P_PARAM_HW_WLAN_INFO_T)kalMemAlloc(sizeof(PARAM_HW_WLAN_INFO_T), VIR_MEM_TYPE); + if (!prHwWlanInfo) + return -ENOMEM; + prHwWlanInfo->u4Index = ucWlanIndex; + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryWlanInfo, + prHwWlanInfo, sizeof(PARAM_HW_WLAN_INFO_T), TRUE, TRUE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + i4BytesWritten = -EFAULT; + goto out_get_curr_ar_rate; + } + + prQueryStaStatistics = + (P_PARAM_GET_STA_STATISTICS)kalMemAlloc(sizeof(PARAM_GET_STA_STA_STATISTICS), VIR_MEM_TYPE); + if (!prQueryStaStatistics) { + i4BytesWritten = -ENOMEM; + goto out_get_curr_ar_rate; + } + + /* Get Statistics info */ + COPY_MAC_ADDR(prQueryStaStatistics->aucMacAddr, pucMacAddr); + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStaStatistics, + prQueryStaStatistics, + sizeof(PARAM_GET_STA_STA_STATISTICS), TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + i4BytesWritten = -EFAULT; + goto out_get_curr_ar_rate; + } + + idx = prHwWlanInfo->rWtblRateInfo.ucRateIdx; + if (idx >= AUTO_RATE_NUM) { + DBGLOG(REQ, WARN, "%s: Rate index is incorrect (%d)\n", __func__, idx); + i4BytesWritten = -EFAULT; + goto out_get_curr_ar_rate; + } + txmode = HW_TX_RATE_TO_MODE(prHwWlanInfo->rWtblRateInfo.au2RateCode[idx]); + if (txmode >= MAX_TX_MODE) + txmode = MAX_TX_MODE; + rate = HW_TX_RATE_TO_MCS(prHwWlanInfo->rWtblRateInfo.au2RateCode[idx], txmode); + + /* Mode: [CCK | OFDM | HT | VHT] */ + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "CCK-"); + else if (txmode == TX_RATE_MODE_OFDM) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "OFDM-"); + else if (txmode == TX_RATE_MODE_HTGF || txmode == TX_RATE_MODE_HTMIX) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "HT-"); + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "VHT-"); + /* Spatial Streams: [1SS | 2SS | N/A] */ + if (prQueryStaStatistics->ucArTableIdx == RATE_TBL_N_2SS || + prQueryStaStatistics->ucArTableIdx == RATE_TBL_AC_2SS) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "2SS-"); + else if (prQueryStaStatistics->ucArTableIdx == RATE_TBL_N || + prQueryStaStatistics->ucArTableIdx == RATE_TBL_AC) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "1SS-"); + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "N/A-"); + + /* BW mode: [BW20 | BW40 | BW80 | BW160/BW8080] */ + if ((txmode == TX_RATE_MODE_CCK) || (txmode == TX_RATE_MODE_OFDM)) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s-", HW_TX_RATE_BW[0]); + else + if (idx > prHwWlanInfo->rWtblPeerCap.ucChangeBWAfterRateN) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s-", + prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability < 4 ? + (prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability > BW_20 ? + HW_TX_RATE_BW[prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability - 1] : + HW_TX_RATE_BW[prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability]) : + HW_TX_RATE_BW[4]); + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, "%s-", + prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability < 4 ? + HW_TX_RATE_BW[prHwWlanInfo->rWtblPeerCap.ucFrequencyCapability] : + HW_TX_RATE_BW[4]); + /* GI mode: [LGI | SGI | X] */ + if (txmode == TX_RATE_MODE_CCK || txmode == TX_RATE_MODE_OFDM) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "N/A-"); + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s-", priv_driver_get_sgi_info(&prHwWlanInfo->rWtblPeerCap) == 0 ? + "LGI" : "SGI"); + /* Rate index: [1M | 2M | 5.5M | 11M | + * 6M | 9M | 12M | 18M | 24M | 36M | 48M | 54M | + * MCS# ] + */ + if (txmode == TX_RATE_MODE_CCK) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", rate < 4 ? HW_TX_RATE_CCK_STR[rate] : HW_TX_RATE_CCK_STR[4]); + else if (txmode == TX_RATE_MODE_OFDM) + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "%s", hw_rate_ofdm_str(rate)); + else + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "MCS%d", rate); + +out_get_curr_ar_rate: + if (prHwWlanInfo) + kalMemFree(prHwWlanInfo, VIR_MEM_TYPE, sizeof(PARAM_HW_WLAN_INFO_T)); + if (prQueryStaStatistics) + kalMemFree(prQueryStaStatistics, VIR_MEM_TYPE, sizeof(PARAM_GET_STA_STA_STATISTICS)); + + return i4BytesWritten; + +} + +/*----------------------------------------------------------------------------*/ +/* +* @ The function will set policy of ACL. +* 0: disable ACL +* 1: enable accept list +* 2: enable deny list +* example: iwpriv p2p0 driver "set_acl_policy 1" +*/ +/*----------------------------------------------------------------------------*/ +static int priv_driver_set_acl_policy(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + P_BSS_INFO_T prBssInfo = NULL; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 i4Argc = 0, i4BytesWritten = 0, i4Ret = 0, i4Policy = 0; + UINT_8 ucRoleIdx = 0, ucBssIdx = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + /* get Bss Index from ndev */ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prNetDev, &ucRoleIdx) != 0) + return -1; + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) + return -1; + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + DBGLOG(REQ, LOUD, "ucRoleIdx %hhu ucBssIdx %hhu\n", ucRoleIdx, ucBssIdx); + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc < 2) + return -1; + + i4Ret = kalkStrtou32(apcArgv[1], 0, &i4Policy); + if (i4Ret) { + DBGLOG(REQ, ERROR, "integer format error i4Ret=%d\n", i4Ret); + return -1; + } + + switch (i4Policy) { + case PARAM_CUSTOM_ACL_POLICY_DISABLE: + case PARAM_CUSTOM_ACL_POLICY_ACCEPT: + case PARAM_CUSTOM_ACL_POLICY_DENY: + prBssInfo->rACL.ePolicy = i4Policy; + break; + default: /*Invalid argument */ + DBGLOG(REQ, ERROR, "Invalid ACL Policy=%d\n", i4Policy); + return -1; + } + + DBGLOG(REQ, TRACE, "ucBssIdx[%hhu] ACL Policy=%d\n", ucBssIdx, prBssInfo->rACL.ePolicy); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "ucBssIdx[%hhu] ACL Policy=%d\n", ucBssIdx, prBssInfo->rACL.ePolicy); + + /* check if the change in ACL affects any existent association */ + if (prBssInfo->rACL.ePolicy != PARAM_CUSTOM_ACL_POLICY_DISABLE) + p2pRoleUpdateACLEntry(prAdapter, ucBssIdx); + + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + + return i4BytesWritten; +} /* priv_driver_set_acl_policy */ + +static INT_32 priv_driver_inspect_mac_addr(IN char *pcMacAddr) +{ + INT_32 i = 0; + + if (pcMacAddr == NULL) + return -1; + + for (i = 0; i < 17; i++) { + if ((i % 3 != 2) && (!kalIsXdigit(pcMacAddr[i]))) { + DBGLOG(REQ, ERROR, "[%c] is not hex digit\n", pcMacAddr[i]); + return -1; + } + if ((i % 3 == 2) && (pcMacAddr[i] != ':')) { + DBGLOG(REQ, ERROR, "[%c]separate symbol is error\n", pcMacAddr[i]); + return -1; + } + } + + if (pcMacAddr[17] != '\0') { + DBGLOG(REQ, ERROR, "no null-terminated character\n"); + return -1; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/* +* @ The function will add entry to ACL for accept or deny list. +* example: iwpriv p2p0 driver "add_acl_entry 01:02:03:04:05:06" +*/ +/*----------------------------------------------------------------------------*/ +static int priv_driver_add_acl_entry(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + P_BSS_INFO_T prBssInfo = NULL; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + UINT_8 aucMacAddr[MAC_ADDR_LEN] = {0}; + INT_32 i = 0, i4Argc = 0, i4BytesWritten = 0, i4Ret = 0; + UINT_8 ucRoleIdx = 0, ucBssIdx = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + /* get Bss Index from ndev */ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prNetDev, &ucRoleIdx) != 0) + return -1; + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) + return -1; + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + DBGLOG(REQ, LOUD, "ucRoleIdx %hhu ucBssIdx %hhu\n", ucRoleIdx, ucBssIdx); + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc < 2) + return -1; + + i4Ret = priv_driver_inspect_mac_addr(apcArgv[1]); + if (i4Ret) { + DBGLOG(REQ, ERROR, "inspect mac format error u4Ret=%d\n", i4Ret); + return -1; + } + + i4Ret = sscanf(apcArgv[1], "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", + &aucMacAddr[0], &aucMacAddr[1], &aucMacAddr[2], + &aucMacAddr[3], &aucMacAddr[4], &aucMacAddr[5]); + + if (i4Ret != MAC_ADDR_LEN) { + DBGLOG(REQ, ERROR, "sscanf mac format fail u4Ret=%d\n", i4Ret); + return -1; + } + + for (i = 0; i <= prBssInfo->rACL.u4Num; i++) { + if (memcmp(prBssInfo->rACL.rEntry[i].aucAddr, &aucMacAddr, MAC_ADDR_LEN) == 0) { + DBGLOG(REQ, ERROR, "add this mac [" MACSTR "] is duplicate.\n", MAC2STR(aucMacAddr)); + return -1; + } + } + + if ((i < 1) || (i > MAX_NUMBER_OF_ACL)) { + DBGLOG(REQ, ERROR, "idx[%d] error or ACL is full.\n", i); + return -1; + } + + memcpy(prBssInfo->rACL.rEntry[i-1].aucAddr, &aucMacAddr, MAC_ADDR_LEN); + prBssInfo->rACL.u4Num = i; + DBGLOG(REQ, TRACE, "add mac addr [" MACSTR "] to ACL(%d).\n", + MAC2STR(prBssInfo->rACL.rEntry[i-1].aucAddr), i); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "add mac addr [" MACSTR "] to ACL(%d)\n", MAC2STR(prBssInfo->rACL.rEntry[i-1].aucAddr), i); + + /* Check if the change in ACL affects any existent association. */ + if (prBssInfo->rACL.ePolicy == PARAM_CUSTOM_ACL_POLICY_DENY) + p2pRoleUpdateACLEntry(prAdapter, ucBssIdx); + + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + + return i4BytesWritten; +} /* priv_driver_add_acl_entry */ + +/*----------------------------------------------------------------------------*/ +/* +* @ The function will delete entry to ACL for accept or deny list. +* example: iwpriv p2p0 driver "add_del_entry 01:02:03:04:05:06" +*/ +/*----------------------------------------------------------------------------*/ +static int priv_driver_del_acl_entry(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + P_BSS_INFO_T prBssInfo = NULL; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + UINT_8 aucMacAddr[MAC_ADDR_LEN] = {0}; + INT_32 i = 0, j = 0, i4Argc = 0, i4BytesWritten = 0, i4Ret = 0; + UINT_8 ucRoleIdx = 0, ucBssIdx = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + /* get Bss Index from ndev */ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prNetDev, &ucRoleIdx) != 0) + return -1; + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) + return -1; + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + DBGLOG(REQ, LOUD, "ucRoleIdx %hhu ucBssIdx %hhu\n", ucRoleIdx, ucBssIdx); + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc < 2) + return -1; + + i4Ret = priv_driver_inspect_mac_addr(apcArgv[1]); + if (i4Ret) { + DBGLOG(REQ, ERROR, "inspect mac format error u4Ret=%d\n", i4Ret); + return -1; + } + + i4Ret = sscanf(apcArgv[1], "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", + &aucMacAddr[0], &aucMacAddr[1], &aucMacAddr[2], + &aucMacAddr[3], &aucMacAddr[4], &aucMacAddr[5]); + + if (i4Ret != MAC_ADDR_LEN) { + DBGLOG(REQ, ERROR, "sscanf mac format fail u4Ret=%d\n", i4Ret); + return -1; + } + + for (i = 0; i < prBssInfo->rACL.u4Num; i++) { + if (memcmp(prBssInfo->rACL.rEntry[i].aucAddr, &aucMacAddr, MAC_ADDR_LEN) == 0) { + memset(&prBssInfo->rACL.rEntry[i], 0x00, sizeof(PARAM_CUSTOM_ACL_ENTRY)); + DBGLOG(REQ, TRACE, "delete this mac [" MACSTR "]\n", MAC2STR(aucMacAddr)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "delete this mac [" MACSTR "] from ACL(%d)\n", MAC2STR(aucMacAddr), i+1); + break; + } + } + + if ((prBssInfo->rACL.u4Num == 0) || (i == MAX_NUMBER_OF_ACL)) { + DBGLOG(REQ, ERROR, "delete entry fail, num of entries=%d\n", i); + return -1; + } + + for (j = i+1; j < prBssInfo->rACL.u4Num; j++) + memcpy(prBssInfo->rACL.rEntry[j-1].aucAddr, prBssInfo->rACL.rEntry[j].aucAddr, MAC_ADDR_LEN); + + prBssInfo->rACL.u4Num = j-1; + memset(prBssInfo->rACL.rEntry[j-1].aucAddr, 0x00, MAC_ADDR_LEN); + + /* check if the change in ACL affects any existent association */ + if (prBssInfo->rACL.ePolicy == PARAM_CUSTOM_ACL_POLICY_ACCEPT) + p2pRoleUpdateACLEntry(prAdapter, ucBssIdx); + + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + + return i4BytesWritten; +} /* priv_driver_del_acl_entry */ + +/*----------------------------------------------------------------------------*/ +/* +* @ The function will show all entries to ACL for accept or deny list. +* example: iwpriv p2p0 driver "show_acl_entry" +*/ +/*----------------------------------------------------------------------------*/ +static int priv_driver_show_acl_entry(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + P_BSS_INFO_T prBssInfo = NULL; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 i = 0, i4Argc = 0, i4BytesWritten = 0; + UINT_8 ucRoleIdx = 0, ucBssIdx = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + /* get Bss Index from ndev */ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prNetDev, &ucRoleIdx) != 0) + return -1; + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) + return -1; + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + DBGLOG(REQ, TRACE, "ACL Policy = %d\n", prBssInfo->rACL.ePolicy); + DBGLOG(REQ, TRACE, "Total ACLs = %d\n", prBssInfo->rACL.u4Num); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "ACL Policy = %d, Total ACLs = %d\n", prBssInfo->rACL.ePolicy, prBssInfo->rACL.u4Num); + + for (i = 0; i < prBssInfo->rACL.u4Num; i++) { + DBGLOG(REQ, TRACE, "ACL(%d): [" MACSTR "]\n", i+1, MAC2STR(prBssInfo->rACL.rEntry[i].aucAddr)); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "ACL(%d): [" MACSTR "]\n", i+1, MAC2STR(prBssInfo->rACL.rEntry[i].aucAddr)); + } + + return i4BytesWritten; +} /* priv_driver_show_acl_entry */ + +/*----------------------------------------------------------------------------*/ +/* +* @ The function will clear all entries to ACL for accept or deny list. +* example: iwpriv p2p0 driver "clear_acl_entry" +*/ +/*----------------------------------------------------------------------------*/ +static int priv_driver_clear_acl_entry(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + P_BSS_INFO_T prBssInfo = NULL; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 i4Argc = 0, i4BytesWritten = 0; + UINT_8 ucRoleIdx = 0, ucBssIdx = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + /* get Bss Index from ndev */ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prNetDev, &ucRoleIdx) != 0) + return -1; + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &ucBssIdx) != + WLAN_STATUS_SUCCESS) + return -1; + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (prBssInfo->rACL.u4Num) { + memset(&prBssInfo->rACL.rEntry[0], 0x00, sizeof(PARAM_CUSTOM_ACL_ENTRY)*MAC_ADDR_LEN); + prBssInfo->rACL.u4Num = 0; + } + + DBGLOG(REQ, TRACE, "ACL Policy = %d\n", prBssInfo->rACL.ePolicy); + DBGLOG(REQ, TRACE, "Total ACLs = %d\n", prBssInfo->rACL.u4Num); + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "ACL Policy = %d, Total ACLs = %d\n", prBssInfo->rACL.ePolicy, prBssInfo->rACL.u4Num); + + /* check if the change in ACL affects any existent association */ + if (prBssInfo->rACL.ePolicy == PARAM_CUSTOM_ACL_POLICY_ACCEPT) + p2pRoleUpdateACLEntry(prAdapter, ucBssIdx); + + return i4BytesWritten; +} /* priv_driver_clear_acl_entry */ + +static int priv_driver_get_drv_mcr(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + UINT_32 u4Ret; + /* INT_32 i4ArgNum_with_ant_sel = 3; */ /* Add Antenna Selection Input */ + INT_32 i4ArgNum = 2; + + CMD_ACCESS_REG rCmdAccessReg; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rCmdAccessReg.u4Address)); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse get_drv_mcr error (Address) u4Ret=%d\n", u4Ret); + + /* rCmdAccessReg.u4Address = kalStrtoul(apcArgv[1], NULL, 0); */ + rCmdAccessReg.u4Data = 0; + + DBGLOG(REQ, LOUD, "address is %x\n", rCmdAccessReg.u4Address); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryDrvMcrRead, + &rCmdAccessReg, sizeof(rCmdAccessReg), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "0x%08x", (unsigned int)rCmdAccessReg.u4Data); + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + } + + return i4BytesWritten; + +} /* priv_driver_get_drv_mcr */ + +int priv_driver_set_drv_mcr(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + UINT_32 u4Ret; + /* INT_32 i4ArgNum_with_ant_sel = 4; */ /* Add Antenna Selection Input */ + INT_32 i4ArgNum = 3; + + CMD_ACCESS_REG rCmdAccessReg; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rCmdAccessReg.u4Address)); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse get_drv_mcr error (Address) u4Ret=%d\n", u4Ret); + + u4Ret = kalkStrtou32(apcArgv[2], 0, &(rCmdAccessReg.u4Data)); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse get_drv_mcr error (Data) u4Ret=%d\n", u4Ret); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetDrvMcrWrite, + &rCmdAccessReg, sizeof(rCmdAccessReg), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + } + + return i4BytesWritten; + +} + +static int priv_driver_get_sw_ctrl(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 u4Ret = 0; + + PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= 2) { + /* rSwCtrlInfo.u4Id = kalStrtoul(apcArgv[1], NULL, 0); */ + rSwCtrlInfo.u4Data = 0; + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rSwCtrlInfo.u4Id)); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + + DBGLOG(REQ, LOUD, "id is %x\n", rSwCtrlInfo.u4Id); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "0x%08x", (unsigned int)rSwCtrlInfo.u4Data); + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + } + + return i4BytesWritten; + +} /* priv_driver_get_sw_ctrl */ + + +int priv_driver_set_sw_ctrl(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + INT_32 u4Ret = 0; + + PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= 3) { + /* rSwCtrlInfo.u4Id = kalStrtoul(apcArgv[1], NULL, 0); + * rSwCtrlInfo.u4Data = kalStrtoul(apcArgv[2], NULL, 0); + */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rSwCtrlInfo.u4Id)); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + u4Ret = kalkStrtou32(apcArgv[2], 0, &(rSwCtrlInfo.u4Data)); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + } + + return i4BytesWritten; + +} /* priv_driver_set_sw_ctrl */ + + + +int priv_driver_set_fixed_rate(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + /* INT_32 u4Ret = 0; */ + UINT_32 u4WCID = 0; + UINT_32 u4Mode = 0, u4Bw = 0, u4Mcs = 0, u4VhtNss = 0; + UINT_32 u4SGI = 0, u4Preamble = 0, u4STBC = 0, u4LDPC = 0, u4SpeEn = 0; + INT_32 i4Recv = 0; + CHAR *this_char = NULL; + UINT_32 u4Id = 0xa0610000; + UINT_32 u4Data = 0x80000000; + UINT_32 u4Id2 = 0xa0600000; + UINT_8 u4Nsts = 1; + BOOLEAN fgStatus = TRUE; + + PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %d, apcArgv[0] = %s\n\n", i4Argc, *apcArgv); + + this_char = kalStrStr(*apcArgv, "="); + + if (!this_char) + return -1; + + this_char++; + + DBGLOG(REQ, LOUD, "string = %s\n", this_char); + + if (strnicmp(this_char, "auto", strlen("auto")) == 0) { + i4Recv = 1; + } else { + i4Recv = sscanf(this_char, "%d-%d-%d-%d-%d-%d-%d-%d-%d-%d", &(u4WCID), + &(u4Mode), &(u4Bw), &(u4Mcs), &(u4VhtNss), + &(u4SGI), &(u4Preamble), &(u4STBC), &(u4LDPC), &(u4SpeEn)); + + DBGLOG(REQ, LOUD, "u4WCID=%d\nu4Mode=%d\nu4Bw=%d\n", u4WCID, u4Mode, u4Bw); + DBGLOG(REQ, LOUD, "u4Mcs=%d\nu4VhtNss=%d\nu4SGI=%d\n", u4Mcs, u4VhtNss, u4SGI); + DBGLOG(REQ, LOUD, "u4Preamble=%d\nu4STBC=%d\n", u4Preamble, u4STBC); + DBGLOG(REQ, LOUD, "u4LDPC=%d\nu4SpeEn=%d\n", u4LDPC, u4SpeEn); + } + + if (i4Recv == 1) { + rSwCtrlInfo.u4Id = u4Id2; + rSwCtrlInfo.u4Data = 0; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + FALSE, FALSE, TRUE, &u4BufLen); + } else if (i4Recv == 10) { + rSwCtrlInfo.u4Id = u4Id; + rSwCtrlInfo.u4Data = u4Data; + + if (u4SGI) + rSwCtrlInfo.u4Data |= BIT(30); + if (u4LDPC) + rSwCtrlInfo.u4Data |= BIT(29); + if (u4SpeEn) + rSwCtrlInfo.u4Data |= BIT(28); + if (u4STBC) + rSwCtrlInfo.u4Data |= BIT(11); + + if (u4Bw <= 3) + rSwCtrlInfo.u4Data |= ((u4Bw << 26) & BITS(26, 27)); + else { + fgStatus = FALSE; + DBGLOG(INIT, ERROR, "Wrong BW! BW20=0, BW40=1, BW80=2,BW160=3\n"); + } + if (u4Mode <= 4) { + rSwCtrlInfo.u4Data |= ((u4Mode << 6) & BITS(6, 8)); + + switch (u4Mode) { + case 0: + if (u4Mcs <= 3) + rSwCtrlInfo.u4Data |= u4Mcs; + else { + fgStatus = FALSE; + DBGLOG(INIT, ERROR, "CCK mode but wrong MCS!\n"); + } + + if (u4Preamble) + rSwCtrlInfo.u4Data |= BIT(2); + else + rSwCtrlInfo.u4Data &= ~BIT(2); + + break; + case 1: + switch (u4Mcs) { + case 0: + /* 6'b001011 */ + rSwCtrlInfo.u4Data |= 11; + break; + case 1: + /* 6'b001111 */ + rSwCtrlInfo.u4Data |= 15; + break; + case 2: + /* 6'b001010 */ + rSwCtrlInfo.u4Data |= 10; + break; + case 3: + /* 6'b001110 */ + rSwCtrlInfo.u4Data |= 14; + break; + case 4: + /* 6'b001001 */ + rSwCtrlInfo.u4Data |= 9; + break; + case 5: + /* 6'b001101 */ + rSwCtrlInfo.u4Data |= 13; + break; + case 6: + /* 6'b001000 */ + rSwCtrlInfo.u4Data |= 8; + break; + case 7: + /* 6'b001100 */ + rSwCtrlInfo.u4Data |= 12; + break; + default: + fgStatus = FALSE; + DBGLOG(INIT, ERROR, "OFDM mode but wrong MCS!\n"); + break; + } + break; + case 2: + case 3: + if (u4Mcs <= 32) + rSwCtrlInfo.u4Data |= u4Mcs; + else { + fgStatus = FALSE; + DBGLOG(INIT, ERROR, "HT mode but wrong MCS!\n"); + } + + if (u4Mcs != 32) { + u4Nsts += (u4Mcs >> 3); + if (u4STBC && (u4Nsts == 1)) + u4Nsts++; + } + break; + case 4: + if (u4Mcs <= 9) + rSwCtrlInfo.u4Data |= u4Mcs; + else { + fgStatus = FALSE; + DBGLOG(INIT, ERROR, "VHT mode but wrong MCS!\n"); + } + if (u4STBC && (u4VhtNss == 1)) + u4Nsts++; + else + u4Nsts = u4VhtNss; + break; + default: + break; + } + } else { + fgStatus = FALSE; + DBGLOG(INIT, ERROR, "Wrong TxMode! CCK=0, OFDM=1, HT=2, GF=3, VHT=4\n"); + } + + rSwCtrlInfo.u4Data |= (((u4Nsts - 1) << 9) & BITS(9, 10)); + + if (fgStatus) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), + FALSE, FALSE, TRUE, &u4BufLen); + } + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } else { + DBGLOG(INIT, ERROR, "iwpriv wlanXX driver FixedRate=Option\n"); + DBGLOG(INIT, ERROR, + "Option:[WCID]-[Mode]-[BW]-[MCS]-[VhtNss]-[SGI]-[Preamble]-[STBC]-[LDPC]-[SPE_EN]\n"); + DBGLOG(INIT, ERROR, "[WCID]Wireless Client ID\n"); + DBGLOG(INIT, ERROR, "[Mode]CCK=0, OFDM=1, HT=2, GF=3, VHT=4\n"); + DBGLOG(INIT, ERROR, "[BW]BW20=0, BW40=1, BW80=2,BW160=3\n"); + DBGLOG(INIT, ERROR, "[MCS]CCK=0~3, OFDM=0~7, HT=0~32, VHT=0~9\n"); + DBGLOG(INIT, ERROR, "[VhtNss]VHT=1~4, Other=ignore\n"); + DBGLOG(INIT, ERROR, "[Preamble]Long=0, Other=Short\n"); + } + + return i4BytesWritten; +} /* priv_driver_set_fixed_rate */ + +int priv_driver_set_cfg(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + + PARAM_CUSTOM_KEY_CFG_STRUCT_T rKeyCfgInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + prAdapter = prGlueInfo->prAdapter; + + kalMemZero(&rKeyCfgInfo, sizeof(rKeyCfgInfo)); + + if (i4Argc >= 3) { + + CHAR ucTmp[WLAN_CFG_VALUE_LEN_MAX]; + PUINT_8 pucCurrBuf = ucTmp; + UINT_8 i = 0; + INT_32 i4TmpBufLen = 0; + + kalMemZero(ucTmp, WLAN_CFG_VALUE_LEN_MAX); + + if (i4Argc == 3) { + /*no space for it, driver can't accept space in the end of the line*/ + /*ToDo: skip the space when parsing*/ + scnprintf(pucCurrBuf, sizeof(ucTmp), "%s", apcArgv[2]); + } else { + for (i = 2; i < i4Argc; i++) + i4TmpBufLen += scnprintf((pucCurrBuf + i4TmpBufLen), + (sizeof(ucTmp) - i4TmpBufLen), "%s", apcArgv[i]); + } + + DBGLOG(INIT, WARN, "Update to driver temp buffer as [%s]\n", ucTmp); + + /* wlanCfgSet(prAdapter, apcArgv[1], apcArgv[2], 0); */ + /* Call by wlanoid because the set_cfg will trigger callback */ + kalStrnCpy(rKeyCfgInfo.aucKey, apcArgv[1], WLAN_CFG_KEY_LEN_MAX); + kalStrnCpy(rKeyCfgInfo.aucValue, ucTmp, WLAN_CFG_KEY_LEN_MAX); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetKeyCfg, &rKeyCfgInfo, sizeof(rKeyCfgInfo), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } + + return i4BytesWritten; + +} /* priv_driver_set_cfg */ + +int priv_driver_get_cfg(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + CHAR aucValue[WLAN_CFG_VALUE_LEN_MAX]; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + prAdapter = prGlueInfo->prAdapter; + + if (i4Argc >= 2) { + /* by wlanoid ? */ + if (wlanCfgGet(prAdapter, apcArgv[1], aucValue, "", 0) == WLAN_STATUS_SUCCESS) { + kalStrnCpy(pcCommand, aucValue, WLAN_CFG_VALUE_LEN_MAX); + i4BytesWritten = kalStrnLen(pcCommand, WLAN_CFG_VALUE_LEN_MAX); + } + } + + return i4BytesWritten; + +} /* priv_driver_get_cfg */ + +int priv_driver_set_chip_config(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + UINT_32 u4CmdLen = 0; + UINT_32 u4PrefixLen = 0; + /* INT_32 i4Argc = 0; */ + /* PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = {0}; */ + + PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T rChipConfigInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + /* wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); */ + /* DBGLOG(REQ, LOUD,("argc is %i\n",i4Argc)); */ + /* */ + u4CmdLen = kalStrnLen(pcCommand, i4TotalLen); + u4PrefixLen = kalStrLen(CMD_SET_CHIP) + 1 /*space */; + + kalMemZero(&rChipConfigInfo, sizeof(rChipConfigInfo)); + + /* if(i4Argc >= 2) { */ + if (u4CmdLen > u4PrefixLen) { + + rChipConfigInfo.ucType = CHIP_CONFIG_TYPE_WO_RESPONSE; + /* rChipConfigInfo.u2MsgSize = kalStrnLen(apcArgv[1],CHIP_CONFIG_RESP_SIZE); */ + rChipConfigInfo.u2MsgSize = u4CmdLen - u4PrefixLen; + /* kalStrnCpy(rChipConfigInfo.aucCmd,apcArgv[1],CHIP_CONFIG_RESP_SIZE); */ + kalStrnCpy(rChipConfigInfo.aucCmd, pcCommand + u4PrefixLen, CHIP_CONFIG_RESP_SIZE - 1); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetChipConfig, + &rChipConfigInfo, sizeof(rChipConfigInfo), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, INFO, "%s: kalIoctl ret=%d\n", __func__, rStatus); + i4BytesWritten = -1; + } + } + + return i4BytesWritten; + +} /* priv_driver_set_chip_config */ + +void +priv_driver_get_chip_config_16(PUINT_8 pucStartAddr, UINT_32 u4Length, UINT_32 u4Line, int i4TotalLen, + INT_32 i4BytesWritten, char *pcCommand) +{ + + while (u4Length >= 16) { + if (i4TotalLen > i4BytesWritten) { + i4BytesWritten += + snprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "%04x %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x %02x %02x %02x\n", + u4Line, 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]); + } + + pucStartAddr += 16; + u4Length -= 16; + u4Line += 16; + } /* u4Length */ +} + + +void +priv_driver_get_chip_config_4(PUINT_32 pu4StartAddr, UINT_32 u4Length, UINT_32 u4Line, int i4TotalLen, + INT_32 i4BytesWritten, char *pcCommand) +{ + while (u4Length >= 16) { + if (i4TotalLen > i4BytesWritten) { + i4BytesWritten += + snprintf(pcCommand + + i4BytesWritten, + i4TotalLen - + i4BytesWritten, + "%04x %08x %08x %08x %08x\n", + u4Line, pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2], pu4StartAddr[3]); + } + + pu4StartAddr += 4; + u4Length -= 16; + u4Line += 4; + } /* u4Length */ +} + +int priv_driver_get_chip_config(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + INT_32 i4BytesWritten = 0; + UINT_32 u4BufLen = 0; + UINT_32 u2MsgSize = 0; + UINT_32 u4CmdLen = 0; + UINT_32 u4PrefixLen = 0; + /* INT_32 i4Argc = 0; */ + /* PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; */ + + PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T rChipConfigInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + /* wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); */ + /* DBGLOG(REQ, LOUD,("argc is %i\n",i4Argc)); */ + + u4CmdLen = kalStrnLen(pcCommand, i4TotalLen); + u4PrefixLen = kalStrLen(CMD_GET_CHIP) + 1 /*space */; + + /* if(i4Argc >= 2) { */ + if (u4CmdLen > u4PrefixLen) { + rChipConfigInfo.ucType = CHIP_CONFIG_TYPE_ASCII; + /* rChipConfigInfo.u2MsgSize = kalStrnLen(apcArgv[1],CHIP_CONFIG_RESP_SIZE); */ + rChipConfigInfo.u2MsgSize = u4CmdLen - u4PrefixLen; + /* kalStrnCpy(rChipConfigInfo.aucCmd,apcArgv[1],CHIP_CONFIG_RESP_SIZE); */ + kalStrnCpy(rChipConfigInfo.aucCmd, pcCommand + u4PrefixLen, CHIP_CONFIG_RESP_SIZE - 1); + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryChipConfig, + &rChipConfigInfo, sizeof(rChipConfigInfo), TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, INFO, "%s: kalIoctl ret=%d\n", __func__, rStatus); + return -1; + } + + /* Check respType */ + u2MsgSize = rChipConfigInfo.u2MsgSize; + DBGLOG(REQ, INFO, "%s: RespTyep %u\n", __func__, rChipConfigInfo.ucRespType); + DBGLOG(REQ, INFO, "%s: u2MsgSize %u\n", __func__, rChipConfigInfo.u2MsgSize); + + if (u2MsgSize > sizeof(rChipConfigInfo.aucCmd)) { + DBGLOG(REQ, INFO, "%s: u2MsgSize error ret=%u\n", __func__, rChipConfigInfo.u2MsgSize); + return -1; + } + + if (u2MsgSize > 0) { + + if (rChipConfigInfo.ucRespType == CHIP_CONFIG_TYPE_ASCII) { + i4BytesWritten = + snprintf(pcCommand + i4BytesWritten, i4TotalLen, "%s", rChipConfigInfo.aucCmd); + } else { + UINT_32 u4Length; + UINT_32 u4Line; + + if (rChipConfigInfo.ucRespType == CHIP_CONFIG_TYPE_MEM8) { + PUINT_8 pucStartAddr = NULL; + + pucStartAddr = (PUINT_8) rChipConfigInfo.aucCmd; + /* align 16 bytes because one print line is 16 bytes */ + u4Length = (((u2MsgSize + 15) >> 4)) << 4; + u4Line = 0; + priv_driver_get_chip_config_16(pucStartAddr, u4Length, u4Line, i4TotalLen, + i4BytesWritten, pcCommand); + } else { + PUINT_32 pu4StartAddr = NULL; + + pu4StartAddr = (PUINT_32) rChipConfigInfo.aucCmd; + /* align 16 bytes because one print line is 16 bytes */ + u4Length = (((u2MsgSize + 15) >> 4)) << 4; + u4Line = 0; + + if (IS_ALIGN_4((ULONG) pu4StartAddr)) { + priv_driver_get_chip_config_4(pu4StartAddr, u4Length, u4Line, + i4TotalLen, i4BytesWritten, pcCommand); + } else { + DBGLOG(REQ, INFO, + "%s: rChipConfigInfo.aucCmd is not 4 bytes alignment %p\n", + __func__, rChipConfigInfo.aucCmd); + } + } /* ChipConfigInfo.ucRespType */ + } + } + /* u2MsgSize > 0 */ + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + } + /* i4Argc */ + return i4BytesWritten; + +} /* priv_driver_get_chip_config */ + + + +int priv_driver_set_ap_start(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + + PARAM_CUSTOM_P2P_SET_STRUCT_T rSetP2P; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + UINT_32 u4Ret; + INT_32 i4ArgNum = 2; + + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &(rSetP2P.u4Mode)); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse ap-start error (u4Enable) u4Ret=%d\n", u4Ret); + + if (rSetP2P.u4Mode >= RUNNING_P2P_MODE_NUM) { + rSetP2P.u4Mode = 0; + rSetP2P.u4Enable = 0; + } else + rSetP2P.u4Enable = 1; + + set_p2p_mode_handler(prNetDev, rSetP2P); + } + + return 0; +} + +int priv_driver_get_linkspeed(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + UINT_32 u4Rate = 0; + UINT_32 u4LinkSpeed = 0; + INT_32 i4BytesWritten = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (!netif_carrier_ok(prNetDev)) + return -1; + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryLinkSpeed, &u4Rate, sizeof(u4Rate), TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + u4LinkSpeed = u4Rate * 100; + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "LinkSpeed %u", (unsigned int)u4LinkSpeed); + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + return i4BytesWritten; + +} /* priv_driver_get_linkspeed */ + +int priv_driver_set_band(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Argc = 0; + UINT_32 ucBand = 0; + UINT_8 ucBssIndex; + ENUM_BAND_T eBand = BAND_NULL; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 u4Ret = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + prAdapter = prGlueInfo->prAdapter; + if (i4Argc >= 2) { + /* ucBand = kalStrtoul(apcArgv[1], NULL, 0); */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &ucBand); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse ucBand error u4Ret=%d\n", u4Ret); + + ucBssIndex = wlanGetAisBssIndex(prGlueInfo->prAdapter); + eBand = BAND_NULL; + if (ucBand == CMD_BAND_5G) + eBand = BAND_5G; + else if (ucBand == CMD_BAND_2G) + eBand = BAND_2G4; + prAdapter->aePreferBand[ucBssIndex] = eBand; + /* XXX call wlanSetPreferBandByNetwork directly in different thread */ + /* wlanSetPreferBandByNetwork (prAdapter, eBand, ucBssIndex); */ + } + + return 0; +} + +int priv_driver_set_txpower(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + P_SET_TXPWR_CTRL_T prTxpwr; + UINT_16 i; + INT_32 u4Ret = 0; + INT_32 ai4Setting[4]; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + prTxpwr = &prGlueInfo->rTxPwr; + + if (i4Argc >= 3 && i4Argc <= 5) { + for (i = 0; i < (i4Argc - 1); i++) { + /* ai4Setting[i] = kalStrtol(apcArgv[i + 1], NULL, 0); */ + u4Ret = kalkStrtos32(apcArgv[i + 1], 0, &(ai4Setting[i])); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", u4Ret); + /* printk("PeiHsuan setting[%d] = %d\n", i, setting[i]); */ + } + } else { + DBGLOG(REQ, INFO, "set_txpower wrong argc : %d\n", i4Argc); + return -1; + } + + /* + * ai4Setting[0] + * 0 : Set TX power offset for specific network + * 1 : Set TX power offset policy when multiple networks are in the same channel + * 2 : Set TX power limit for specific channel in 2.4GHz band + * 3 : Set TX power limit of specific sub-band in 5GHz band + * 4 : Enable or reset setting + */ + if (ai4Setting[0] == 0 && (i4Argc - 1) == 4 /* argc num */) { + /* ai4Setting[1] : 0 (All networks), 1 (legacy STA), 2 (Hotspot AP), 3 (P2P), 4 (BT over Wi-Fi) */ + /* ai4Setting[2] : 0 (All bands),1 (2.4G), 2 (5G) */ + /* ai4Setting[3] : -30 ~ 20 in unit of 0.5dBm (default: 0) */ + if (ai4Setting[1] == 1 || ai4Setting[1] == 0) { + if (ai4Setting[2] == 0 || ai4Setting[2] == 1) + prTxpwr->c2GLegacyStaPwrOffset = ai4Setting[3]; + if (ai4Setting[2] == 0 || ai4Setting[2] == 2) + prTxpwr->c5GLegacyStaPwrOffset = ai4Setting[3]; + } + if (ai4Setting[1] == 2 || ai4Setting[1] == 0) { + if (ai4Setting[2] == 0 || ai4Setting[2] == 1) + prTxpwr->c2GHotspotPwrOffset = ai4Setting[3]; + if (ai4Setting[2] == 0 || ai4Setting[2] == 2) + prTxpwr->c5GHotspotPwrOffset = ai4Setting[3]; + } + if (ai4Setting[1] == 3 || ai4Setting[1] == 0) { + if (ai4Setting[2] == 0 || ai4Setting[2] == 1) + prTxpwr->c2GP2pPwrOffset = ai4Setting[3]; + if (ai4Setting[2] == 0 || ai4Setting[2] == 2) + prTxpwr->c5GP2pPwrOffset = ai4Setting[3]; + } + if (ai4Setting[1] == 4 || ai4Setting[1] == 0) { + if (ai4Setting[2] == 0 || ai4Setting[2] == 1) + prTxpwr->c2GBowPwrOffset = ai4Setting[3]; + if (ai4Setting[2] == 0 || ai4Setting[2] == 2) + prTxpwr->c5GBowPwrOffset = ai4Setting[3]; + } + } else if (ai4Setting[0] == 1 && (i4Argc - 1) == 2) { + /* ai4Setting[1] : 0 (highest power is used) (default), 1 (lowest power is used) */ + prTxpwr->ucConcurrencePolicy = ai4Setting[1]; + } else if (ai4Setting[0] == 2 && (i4Argc - 1) == 3) { + /* ai4Setting[1] : 0 (all channels in 2.4G), 1~14 */ + /* ai4Setting[2] : 10 ~ 46 in unit of 0.5dBm (default: 46) */ + if (ai4Setting[1] == 0) { + for (i = 0; i < 14; i++) + prTxpwr->acTxPwrLimit2G[i] = ai4Setting[2]; + } else if (ai4Setting[1] <= 14) + prTxpwr->acTxPwrLimit2G[ai4Setting[1] - 1] = ai4Setting[2]; + } else if (ai4Setting[0] == 3 && (i4Argc - 1) == 3) { + /* ai4Setting[1] : 0 (all sub-bands in 5G), + * 1 (5000 ~ 5250MHz), + * 2 (5255 ~ 5350MHz), + * 3 (5355 ~ 5725MHz), + * 4 (5730 ~ 5825MHz) + */ + /* ai4Setting[2] : 10 ~ 46 in unit of 0.5dBm (default: 46) */ + if (ai4Setting[1] == 0) { + for (i = 0; i < 4; i++) + prTxpwr->acTxPwrLimit5G[i] = ai4Setting[2]; + } else if (ai4Setting[1] <= 4) + prTxpwr->acTxPwrLimit5G[ai4Setting[1] - 1] = ai4Setting[2]; + } else if (ai4Setting[0] == 4 && (i4Argc - 1) == 2) { + /* ai4Setting[1] : 1 (enable), 0 (reset and disable) */ + if (ai4Setting[1] == 0) + wlanDefTxPowerCfg(prGlueInfo->prAdapter); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetTxPower, prTxpwr, sizeof(SET_TXPWR_CTRL_T), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } else + return -EFAULT; + + return 0; +} + +int priv_driver_set_country(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + UINT_8 aucCountry[2]; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (regd_is_single_sku_en()) { + UINT_8 aucCountry_code[4] = {0, 0, 0, 0}; + UINT_8 i, count; + + /* command like "COUNTRY US", "COUNTRY US1" and "COUNTRY US01" */ + count = kalStrnLen(apcArgv[1], sizeof(aucCountry_code)); + for (i = 0; i < count; i++) + aucCountry_code[i] = apcArgv[1][i]; + + + rStatus = kalIoctl(prGlueInfo, wlanoidSetCountryCode, + &aucCountry_code[0], count, FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + return 0; + } + + + if (i4Argc >= 2) { + /* command like "COUNTRY US", "COUNTRY EU" and "COUNTRY JP" */ + aucCountry[0] = apcArgv[1][0]; + aucCountry[1] = apcArgv[1][1]; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetCountryCode, &aucCountry[0], 2, FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + } + return 0; +} + +int priv_driver_get_country(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + UINT_32 i4BytesWritten = 0; + UINT_32 country = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (!regd_is_single_sku_en()) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "Not Supported."); + return i4BytesWritten; + } + + country = rlmDomainGetCountryCode(); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nCountry Code: (0x%x)", + country); + + return i4BytesWritten; +} + +int priv_driver_get_channels(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + UINT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; +#if (CFG_SUPPORT_SINGLE_SKU == 1) + UINT_32 ch_idx, start_idx, end_idx; + struct channel *pCh; + UINT_32 ch_num = 0; + UINT_8 maxbw = 160; + UINT_32 u4Ret = 0; +#endif + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (!regd_is_single_sku_en()) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "Not Supported."); + return i4BytesWritten; + } + +#if (CFG_SUPPORT_SINGLE_SKU == 1) + /** + * Usage: iwpriv wlan0 driver "get_channels [2g |5g |ch_num]" + **/ + if (i4Argc >= 2 && (apcArgv[1][0] == '2') && (apcArgv[1][1] == 'g')) { + start_idx = 0; + end_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + } else if (i4Argc >= 2 && (apcArgv[1][0] == '5') && (apcArgv[1][1] == 'g')) { + start_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + end_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ) + + rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ); + } else { + start_idx = 0; + end_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ) + + rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ); + if (i4Argc >= 2) + /* Dump only specified channel */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &ch_num); + } + + if (regd_is_single_sku_en()) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\n"); + + for (ch_idx = start_idx; ch_idx < end_idx; ch_idx++) { + + pCh = (rlmDomainGetActiveChannels() + ch_idx); + + if (ch_num && (ch_num != pCh->chNum)) + continue; /*show specific channel information*/ + + /* Channel number */ + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "CH-%d:", + pCh->chNum); + /* Active/Passive */ + if (pCh->flags & IEEE80211_CHAN_PASSIVE_FLAG) + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, " " IEEE80211_CHAN_PASSIVE_STR); + else + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, " ACTIVE"); + /* Max BW */ + if ((pCh->flags & IEEE80211_CHAN_NO_160MHZ) == IEEE80211_CHAN_NO_160MHZ) + maxbw = 80; + if ((pCh->flags & IEEE80211_CHAN_NO_80MHZ) == IEEE80211_CHAN_NO_80MHZ) + maxbw = 40; + if ((pCh->flags & IEEE80211_CHAN_NO_HT40) == IEEE80211_CHAN_NO_HT40) + maxbw = 20; + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, " BW_%dMHz", maxbw); + /* Channel flags */ + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, " (flags=0x%x)\n", pCh->flags); + } + } +#endif + + return i4BytesWritten; +} + +#if (CFG_SUPPORT_DFS_MASTER == 1) +int priv_driver_show_dfs_state(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 i4BytesWritten = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nDFS State: \"%s\"", + p2pFuncShowDfsState()); + + return i4BytesWritten; +} + +int priv_driver_show_dfs_radar_param(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 i4BytesWritten = 0; + UINT_8 ucCnt = 0; + struct P2P_RADAR_INFO *prP2pRadarInfo = NULL; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + prP2pRadarInfo = (struct P2P_RADAR_INFO *) cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, sizeof(*prP2pRadarInfo)); + + if (!prP2pRadarInfo) + return -1; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + p2pFuncGetRadarInfo(prP2pRadarInfo); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nRDD idx: %d\n", + prP2pRadarInfo->ucRddIdx); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nLong Pulse detected: %d\n", + prP2pRadarInfo->ucLongDetected); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nPeriodic Pulse detected: %d\n", + prP2pRadarInfo->ucPeriodicDetected); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nLPB Num: %d\n", + prP2pRadarInfo->ucLPBNum); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nPPB Num: %d\n", + prP2pRadarInfo->ucPPBNum); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\n==========================="); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nLong Pulse Buffer Contents:\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\npulse_time pulse_width PRI\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\n%-10d %-11d -\n" + , prP2pRadarInfo->arLpbContent[ucCnt].u4LongStartTime + , prP2pRadarInfo->arLpbContent[ucCnt].u2LongPulseWidth); + for (ucCnt = 1; ucCnt < prP2pRadarInfo->ucLPBNum; ucCnt++) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\n%-10d %-11d %d\n" + , prP2pRadarInfo->arLpbContent[ucCnt].u4LongStartTime + , prP2pRadarInfo->arLpbContent[ucCnt].u2LongPulseWidth + , (prP2pRadarInfo->arLpbContent[ucCnt].u4LongStartTime + - prP2pRadarInfo->arLpbContent[ucCnt-1].u4LongStartTime) * 2 / 5); + } + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nLPB Period Valid: %d", + prP2pRadarInfo->ucLPBPeriodValid); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nLPB Period Valid: %d\n", + prP2pRadarInfo->ucLPBWidthValid); + + ucCnt = 0; + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\n==========================="); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nPeriod Pulse Buffer Contents:\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\npulse_time pulse_width PRI\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\n%-10d %-11d -\n" + , prP2pRadarInfo->arPpbContent[ucCnt].u4PeriodicStartTime + , prP2pRadarInfo->arPpbContent[ucCnt].u2PeriodicPulseWidth); + for (ucCnt = 1; ucCnt < prP2pRadarInfo->ucPPBNum; ucCnt++) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\n%-10d %-11d %d\n" + , prP2pRadarInfo->arPpbContent[ucCnt].u4PeriodicStartTime + , prP2pRadarInfo->arPpbContent[ucCnt].u2PeriodicPulseWidth + , (prP2pRadarInfo->arPpbContent[ucCnt].u4PeriodicStartTime + - prP2pRadarInfo->arPpbContent[ucCnt-1].u4PeriodicStartTime) * 2 / 5); + } + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nPRI Count M1 TH: %d; PRI Count M1: %d", + prP2pRadarInfo->ucPRICountM1TH, prP2pRadarInfo->ucPRICountM1); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nPRI Count M2 TH: %d; PRI Count M2: %d", + prP2pRadarInfo->ucPRICountM2TH, prP2pRadarInfo->ucPRICountM2); + + + cnmMemFree(prGlueInfo->prAdapter, prP2pRadarInfo); + + return i4BytesWritten; +} + +int priv_driver_show_dfs_help(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 i4BytesWritten = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\n--iwpriv wlanX driver \"show_dfs_state\"\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nINACTIVE: RDD disable or temporary RDD disable"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nCHECKING: During CAC time"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nACTIVE : In-serive monitoring"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nDETECTED: Has detected radar but hasn't moved to new channel\n"); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\n--iwpriv wlanX driver \"show_dfs_radar_param\"\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nShow the latest pulse information\n"); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\n--iwpriv wlanX driver \"show_dfs_cac_time\"\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nShow the remaining time of CAC\n"); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\n--iwpriv wlanX set ByPassCac=yy\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nValue yy: set the time of CAC\n"); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\n--iwpriv wlanX set RDDReport=yy\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nValue yy is \"0\" or \"1\""); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\n\"0\": Emulate RDD0 manual radar event"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\n\"1\": Emulate RDD1 manual radar event\n"); + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\n--iwpriv wlanX set RadarDetectMode=yy\n"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nValue yy is \"0\" or \"1\""); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\n\"0\": Switch channel when radar detected (default)"); + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\n\"1\": Do not switch channel when radar detected"); + + return i4BytesWritten; +} + +int priv_driver_show_dfs_cac_time(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 i4BytesWritten = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (p2pFuncGetDfsState() != DFS_STATE_CHECKING) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nNot in CAC period"); + return i4BytesWritten; + } + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nRemaining time of CAC: %dsec", p2pFuncGetCacRemainingTime()); + + return i4BytesWritten; +} + +#endif +int priv_driver_set_miracast(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 i4BytesWritten = 0; + /* WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; */ + /* UINT_32 u4BufLen = 0; */ + INT_32 i4Argc = 0; + UINT_32 ucMode = 0; + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T prMsgWfdCfgUpdate = (P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T) NULL; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 u4Ret = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + prAdapter = prGlueInfo->prAdapter; + if (i4Argc >= 2) { + /* ucMode = kalStrtoul(apcArgv[1], NULL, 0); */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &ucMode); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse ucMode error u4Ret=%d\n", u4Ret); + + if (g_ucMiracastMode == (UINT_8) ucMode) { + /* XXX: continue or skip */ + /* XXX: continue or skip */ + } + + g_ucMiracastMode = (UINT_8) ucMode; + prMsgWfdCfgUpdate = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_WFD_CONFIG_SETTINGS_CHANGED_T)); + + if (prMsgWfdCfgUpdate != NULL) { + + prWfdCfgSettings = &(prAdapter->rWifiVar.rWfdConfigureSettings); + prMsgWfdCfgUpdate->rMsgHdr.eMsgId = MID_MNY_P2P_WFD_CFG_UPDATE; + prMsgWfdCfgUpdate->prWfdCfgSettings = prWfdCfgSettings; + + if (ucMode == MIRACAST_MODE_OFF) { + prWfdCfgSettings->ucWfdEnable = 0; + snprintf(pcCommand, i4TotalLen, CMD_SET_CHIP " mira 0"); + } else if (ucMode == MIRACAST_MODE_SOURCE) { + prWfdCfgSettings->ucWfdEnable = 1; + snprintf(pcCommand, i4TotalLen, CMD_SET_CHIP " mira 1"); + } else if (ucMode == MIRACAST_MODE_SINK) { + prWfdCfgSettings->ucWfdEnable = 2; + snprintf(pcCommand, i4TotalLen, CMD_SET_CHIP " mira 2"); + } else { + prWfdCfgSettings->ucWfdEnable = 0; + snprintf(pcCommand, i4TotalLen, CMD_SET_CHIP " mira 0"); + } + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgWfdCfgUpdate, MSG_SEND_METHOD_BUF); + + priv_driver_set_chip_config(prNetDev, pcCommand, i4TotalLen); + } /* prMsgWfdCfgUpdate */ + else { + ASSERT(FALSE); + i4BytesWritten = -1; + } + } + + /* i4Argc */ + return i4BytesWritten; +} + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +/* + * Memo + * 00 : Reset All Cal Data in Driver + * 01 : Trigger All Cal Function + * 02 : Get Thermal Temp from FW + * 03 : Get Cal Data Size from FW + * 04 : Get Cal Data from FW (Rom) + * 05 : Get Cal Data from FW (Ram) + * 06 : Print Cal Data in Driver (Rom) + * 07 : Print Cal Data in Driver (Ram) + * 08 : Print Cal Data in FW (Rom) + * 09 : Print Cal Data in FW (Ram) + * 10 : Send Cal Data to FW (Rom) + * 11 : Send Cal Data to FW (Ram) + */ +static int priv_driver_set_calbackup_test_drv_fw(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + UINT_32 u4Ret, u4GetInput; + INT_32 i4ArgNum = 2; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RFTEST, INFO, "%s\r\n", __func__); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= i4ArgNum) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4GetInput); + if (u4Ret) + DBGLOG(RFTEST, INFO, "priv_driver_set_calbackup_test_drv_fw Parsing Fail\n"); + + if (u4GetInput == 0) { + DBGLOG(RFTEST, INFO, "(New Flow) CMD#0 : Reset All Cal Data in Driver.\n"); + /* (New Flow 20160720) Step 0 : Reset All Cal Data Structure */ + memset(&g_rBackupCalDataAllV2, 1, sizeof(RLM_CAL_RESULT_ALL_V2_T)); + g_rBackupCalDataAllV2.u4MagicNum1 = 6632; + g_rBackupCalDataAllV2.u4MagicNum2 = 6632; + } else if (u4GetInput == 1) { + DBGLOG(RFTEST, INFO, "CMD#1 : Trigger FW Do All Cal.\n"); + /* Step 1 : Trigger All Cal Function */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 1, 2, 0); + DBGLOG(RFTEST, INFO, "Trigger FW Do All Cal, rStatus = 0x%08x\n", rStatus); + } else if (u4GetInput == 2) { + DBGLOG(RFTEST, INFO, "(New Flow) CMD#2 : Get Thermal Temp from FW.\n"); + /* (New Flow 20160720) Step 2 : Get Thermal Temp from FW */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 0, 0, 0); + DBGLOG(RFTEST, INFO, "Get Thermal Temp from FW, rStatus = 0x%08x\n", rStatus); + + } else if (u4GetInput == 3) { + DBGLOG(RFTEST, INFO, "(New Flow) CMD#3 : Get Cal Data Size from FW.\n"); + /* (New Flow 20160720) Step 3 : Get Cal Data Size from FW */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 0, 1, 0); + DBGLOG(RFTEST, INFO, "Get Rom Cal Data Size, rStatus = 0x%08x\n", rStatus); + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 0, 1, 1); + DBGLOG(RFTEST, INFO, "Get Ram Cal Data Size, rStatus = 0x%08x\n", rStatus); + + } else if (u4GetInput == 4) { +#if 1 + DBGLOG(RFTEST, INFO, "(New Flow) CMD#4 : Print Cal Data in FW (Ram) (Part 1 - [0]~[3327]).\n"); + /* Debug Use : Print Cal Data in FW (Ram) */ + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 4, 6, 1); + DBGLOG(RFTEST, INFO, "Print Cal Data in FW (Ram), rStatus = 0x%08x\n", rStatus); +#else /* For Temp Use this Index */ + DBGLOG(RFTEST, INFO, "(New Flow) CMD#4 : Get Cal Data from FW (Rom). Start!!!!!!!!!!!\n"); + DBGLOG(RFTEST, INFO, "Thermal Temp = %d\n", g_rBackupCalDataAllV2.u4ThermalInfo); + DBGLOG(RFTEST, INFO, "Total Length (Rom) = %d\n", + g_rBackupCalDataAllV2.u4ValidRomCalDataLength); + /* (New Flow 20160720) Step 3 : Get Cal Data from FW */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 2, 4, 0); + DBGLOG(RFTEST, INFO, "Get Cal Data from FW (Rom), rStatus = 0x%08x\n", rStatus); +#endif + } else if (u4GetInput == 5) { +#if 1 + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#5 : Print RAM Cal Data in Driver (Part 1 - [0]~[3327]).\n"); + DBGLOG(RFTEST, INFO, "==================================================================\n"); + /* RFTEST_INFO_LOGDUMP32(&(g_rBackupCalDataAllV2.au4RamCalData[0]), 3328*sizeof(UINT_32)); */ + DBGLOG(RFTEST, INFO, "==================================================================\n"); + DBGLOG(RFTEST, INFO, "Dumped Ram Cal Data Szie : %d bytes\n", 3328*sizeof(UINT_32)); + DBGLOG(RFTEST, INFO, "Total Ram Cal Data Szie : %d bytes\n", + g_rBackupCalDataAllV2.u4ValidRamCalDataLength); + DBGLOG(RFTEST, INFO, "==================================================================\n"); +#else /* For Temp Use this Index */ + DBGLOG(RFTEST, INFO, "(New Flow) CMD#5 : Get Cal Data from FW (Ram). Start!!!!!!!!!!!\n"); + DBGLOG(RFTEST, INFO, "Thermal Temp = %d\n", g_rBackupCalDataAllV2.u4ThermalInfo); + DBGLOG(RFTEST, INFO, "Total Length (Ram) = %d\n", + g_rBackupCalDataAllV2.u4ValidRamCalDataLength); + /* (New Flow 20160720) Step 3 : Get Cal Data from FW */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 2, 4, 1); + DBGLOG(RFTEST, INFO, "Get Cal Data from FW (Ram), rStatus = 0x%08x\n", rStatus); +#endif + } else if (u4GetInput == 6) { + DBGLOG(RFTEST, INFO, "(New Flow) CMD#6 : Print ROM Cal Data in Driver.\n"); + DBGLOG(RFTEST, INFO, "==================================================================\n"); + /* RFTEST_INFO_LOGDUMP32(&(g_rBackupCalDataAllV2.au4RomCalData[0]), */ + /* g_rBackupCalDataAllV2.u4ValidRomCalDataLength); */ + DBGLOG(RFTEST, INFO, "==================================================================\n"); + DBGLOG(RFTEST, INFO, "Total Rom Cal Data Szie : %d bytes\n", + g_rBackupCalDataAllV2.u4ValidRomCalDataLength); + DBGLOG(RFTEST, INFO, "==================================================================\n"); + } else if (u4GetInput == 7) { + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#7 : Print RAM Cal Data in Driver (Part 2 - [3328]~[6662]).\n"); + DBGLOG(RFTEST, INFO, "==================================================================\n"); + /* RFTEST_INFO_LOGDUMP32(&(g_rBackupCalDataAllV2.au4RamCalData[3328]), */ + /*(g_rBackupCalDataAllV2.u4ValidRamCalDataLength - 3328*sizeof(UINT_32))); */ + DBGLOG(RFTEST, INFO, "==================================================================\n"); + DBGLOG(RFTEST, INFO, "Dumped Ram Cal Data Szie : %d bytes\n", + (g_rBackupCalDataAllV2.u4ValidRamCalDataLength - 3328*sizeof(UINT_32))); + DBGLOG(RFTEST, INFO, "Total Ram Cal Data Szie : %d bytes\n", + g_rBackupCalDataAllV2.u4ValidRamCalDataLength); + DBGLOG(RFTEST, INFO, "==================================================================\n"); + } else if (u4GetInput == 8) { + DBGLOG(RFTEST, INFO, "(New Flow) CMD#8 : Print Cal Data in FW (Rom).\n"); + /* Debug Use : Print Cal Data in FW (Rom) */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 4, 6, 0); + DBGLOG(RFTEST, INFO, "Print Cal Data in FW (Rom), rStatus = 0x%08x\n", rStatus); + + } else if (u4GetInput == 9) { + DBGLOG(RFTEST, INFO, + "(New Flow) CMD#9 : Print Cal Data in FW (Ram) (Part 2 - [3328]~[6662]).\n"); + /* Debug Use : Print Cal Data in FW (Ram) */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 4, 6, 2); + DBGLOG(RFTEST, INFO, "Print Cal Data in FW (Ram), rStatus = 0x%08x\n", rStatus); + + } else if (u4GetInput == 10) { + DBGLOG(RFTEST, INFO, "(New Flow) CMD#10 : Send Cal Data to FW (Rom).\n"); + /* Send Cal Data to FW (Rom) */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 3, 5, 0); + DBGLOG(RFTEST, INFO, "Send Cal Data to FW (Rom), rStatus = 0x%08x\n", rStatus); + + } else if (u4GetInput == 11) { + DBGLOG(RFTEST, INFO, "(New Flow) CMD#11 : Send Cal Data to FW (Ram).\n"); + /* Send Cal Data to FW (Ram) */ + + rStatus = rlmCalBackup(prGlueInfo->prAdapter, 3, 5, 1); + DBGLOG(RFTEST, INFO, "Send Cal Data to FW (Ram), rStatus = 0x%08x\n", rStatus); + + } + } + + return i4BytesWritten; +} /* priv_driver_set_calbackup_test_drv_fw */ +#endif + +#if CFG_WOW_SUPPORT +static int priv_driver_set_wow(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_WOW_CTRL_T pWOW_CTRL = NULL; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + UINT_32 u4Ret = 0; + UINT_32 Enable = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + pWOW_CTRL = &prGlueInfo->prAdapter->rWowCtrl; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + u4Ret = kalkStrtou32(apcArgv[1], 0, &Enable); + + if (u4Ret) + DBGLOG(REQ, LOUD, "parse bEnable error u4Ret=%d\n", u4Ret); + + DBGLOG(INIT, INFO, "CMD set_wow_enable = %d\n", Enable); + DBGLOG(INIT, INFO, "Scenario ID %d\n", pWOW_CTRL->ucScenarioId); + DBGLOG(INIT, INFO, "ucBlockCount %d\n", pWOW_CTRL->ucBlockCount); + DBGLOG(INIT, INFO, "interface %d\n", pWOW_CTRL->astWakeHif[0].ucWakeupHif); + DBGLOG(INIT, INFO, "gpio_pin %d\n", pWOW_CTRL->astWakeHif[0].ucGpioPin); + DBGLOG(INIT, INFO, "gpio_level 0x%x\n", pWOW_CTRL->astWakeHif[0].ucTriggerLvl); + DBGLOG(INIT, INFO, "gpio_timer %d\n", pWOW_CTRL->astWakeHif[0].u4GpioInterval); + kalWowProcess(prGlueInfo, Enable); + +#if defined(_HIF_USB) + if (Enable) + glUsbSetState(&prGlueInfo->rHifInfo, USB_STATE_SUSPEND); + else + glUsbSetState(&prGlueInfo->rHifInfo, USB_STATE_LINK_UP); +#endif + + return 0; +} + +static int priv_driver_set_wow_enable(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_WOW_CTRL_T pWOW_CTRL = NULL; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + UINT_32 u4Ret = 0; + UINT_8 ucEnable = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + pWOW_CTRL = &prGlueInfo->prAdapter->rWowCtrl; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + u4Ret = kalkStrtou8(apcArgv[1], 0, &ucEnable); + + if (u4Ret) + DBGLOG(REQ, LOUD, "parse bEnable error u4Ret=%d\n", u4Ret); + + pWOW_CTRL->fgWowEnable = ucEnable; + + DBGLOG(PF, INFO, "WOW enable %d\n", pWOW_CTRL->fgWowEnable); + + return 0; +} + +static int priv_driver_set_wow_par(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_WOW_CTRL_T pWOW_CTRL = NULL; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + INT_32 u4Ret = 0; + UINT_8 ucWakeupHif = 0, GpioPin = 0, ucGpioLevel = 0, ucBlockCount, ucScenario = 0; + UINT_32 u4GpioTimer = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + pWOW_CTRL = &prGlueInfo->prAdapter->rWowCtrl; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc > 3) { + + u4Ret = kalkStrtou8(apcArgv[1], 0, &ucWakeupHif); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse ucWakeupHif error u4Ret=%d\n", u4Ret); + pWOW_CTRL->astWakeHif[0].ucWakeupHif = ucWakeupHif; + + u4Ret = kalkStrtou8(apcArgv[2], 0, &GpioPin); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse GpioPin error u4Ret=%d\n", u4Ret); + pWOW_CTRL->astWakeHif[0].ucGpioPin = GpioPin; + + u4Ret = kalkStrtou8(apcArgv[3], 0, &ucGpioLevel); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse Gpio level error u4Ret=%d\n", u4Ret); + pWOW_CTRL->astWakeHif[0].ucTriggerLvl = ucGpioLevel; + + u4Ret = kalkStrtou32(apcArgv[4], 0, &u4GpioTimer); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse u4GpioTimer error u4Ret=%d\n", u4Ret); + pWOW_CTRL->astWakeHif[0].u4GpioInterval = u4GpioTimer; + + u4Ret = kalkStrtou8(apcArgv[5], 0, &ucScenario); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse ucScenario error u4Ret=%d\n", u4Ret); + pWOW_CTRL->ucScenarioId = ucScenario; + + u4Ret = kalkStrtou8(apcArgv[6], 0, &ucBlockCount); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse ucBlockCnt error u4Ret=%d\n", u4Ret); + pWOW_CTRL->ucBlockCount = ucBlockCount; + + DBGLOG(INIT, INFO, "gpio_scenario%d\n", pWOW_CTRL->ucScenarioId); + DBGLOG(INIT, INFO, "interface %d\n", pWOW_CTRL->astWakeHif[0].ucWakeupHif); + DBGLOG(INIT, INFO, "gpio_pin %d\n", pWOW_CTRL->astWakeHif[0].ucGpioPin); + DBGLOG(INIT, INFO, "gpio_level %d\n", pWOW_CTRL->astWakeHif[0].ucTriggerLvl); + DBGLOG(INIT, INFO, "gpio_timer %d\n", pWOW_CTRL->astWakeHif[0].u4GpioInterval); + + return 0; + } else + return -1; + + +} + +static int priv_driver_set_wow_udpport(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_WOW_CTRL_T pWOW_CTRL = NULL; + INT_32 i4Argc = 0; + PCHAR apcPortArgv[WLAN_CFG_ARGV_MAX_LONG] = { 0 }; /* to input 20 port */ + INT_32 u4Ret = 0, ii; + UINT_8 ucVer, ucCount; + UINT_16 u2Port = 0; + PUINT_16 pausPortArry; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + pWOW_CTRL = &prGlueInfo->prAdapter->rWowCtrl; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgumentLong(pcCommand, &i4Argc, apcPortArgv); + DBGLOG(REQ, WARN, "argc is %i\n", i4Argc); + + /* example: set_wow_udp 0 5353,8080 (set) */ + /* example: set_wow_udp 1 (clear) */ + + if (i4Argc >= 3) { + + /* Pick Max */ + ucCount = ((i4Argc - 2) > MAX_TCP_UDP_PORT) ? MAX_TCP_UDP_PORT : (i4Argc - 2); + DBGLOG(PF, INFO, "UDP ucCount=%d\n", ucCount); + + u4Ret = kalkStrtou8(apcPortArgv[1], 0, &ucVer); + if (u4Ret) { + DBGLOG(REQ, LOUD, "parse ucWakeupHif error u4Ret=%d\n", u4Ret); + return -1; + } + + /* IPv4/IPv6 */ + DBGLOG(PF, INFO, "ucVer=%d\n", ucVer); + if (ucVer == 0) { + pWOW_CTRL->stWowPort.ucIPv4UdpPortCnt = ucCount; + pausPortArry = pWOW_CTRL->stWowPort.ausIPv4UdpPort; + } else { + pWOW_CTRL->stWowPort.ucIPv6UdpPortCnt = ucCount; + pausPortArry = pWOW_CTRL->stWowPort.ausIPv6UdpPort; + } + + /* Port */ + for (ii = 0; ii < ucCount; ii++) { + u4Ret = kalkStrtou16(apcPortArgv[ii+2], 0, &u2Port); + if (u4Ret) { + DBGLOG(PF, ERROR, "parse u2Port error u4Ret=%d\n", u4Ret); + return -1; + } + + pausPortArry[ii] = u2Port; + DBGLOG(PF, INFO, "ucPort=%d, idx=%d\n", u2Port, ii); + } + + return 0; + } else if (i4Argc == 2) { + + u4Ret = kalkStrtou8(apcPortArgv[1], 0, &ucVer); + if (u4Ret) { + DBGLOG(REQ, LOUD, "parse ucWakeupHif error u4Ret=%d\n", u4Ret); + return -1; + } + + if (ucVer == 0) { + kalMemZero(prGlueInfo->prAdapter->rWowCtrl.stWowPort.ausIPv4UdpPort, + sizeof(UINT_16) * MAX_TCP_UDP_PORT); + prGlueInfo->prAdapter->rWowCtrl.stWowPort.ucIPv4UdpPortCnt = 0; + } else { + kalMemZero(prGlueInfo->prAdapter->rWowCtrl.stWowPort.ausIPv6UdpPort, + sizeof(UINT_16) * MAX_TCP_UDP_PORT); + prGlueInfo->prAdapter->rWowCtrl.stWowPort.ucIPv6UdpPortCnt = 0; + } + + return 0; + } else + return -1; + +} + +static int priv_driver_set_wow_tcpport(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_WOW_CTRL_T pWOW_CTRL = NULL; + INT_32 i4Argc = 0; + PCHAR apcPortArgv[WLAN_CFG_ARGV_MAX_LONG] = { 0 }; /* to input 20 port */ + INT_32 u4Ret = 0, ii; + UINT_8 ucVer, ucCount; + UINT_16 u2Port = 0; + PUINT_16 pausPortArry; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + pWOW_CTRL = &prGlueInfo->prAdapter->rWowCtrl; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgumentLong(pcCommand, &i4Argc, apcPortArgv); + DBGLOG(REQ, WARN, "argc is %i\n", i4Argc); + + /* example: set_wow_tcp 0 5353,8080 (Set) */ + /* example: set_wow_tcp 1 (clear) */ + + if (i4Argc >= 3) { + + /* Pick Max */ + ucCount = ((i4Argc - 2) > MAX_TCP_UDP_PORT) ? MAX_TCP_UDP_PORT : (i4Argc - 2); + DBGLOG(PF, INFO, "TCP ucCount=%d\n", ucCount); + + u4Ret = kalkStrtou8(apcPortArgv[1], 0, &ucVer); + if (u4Ret) { + DBGLOG(REQ, LOUD, "parse ucWakeupHif error u4Ret=%d\n", u4Ret); + return -1; + } + + /* IPv4/IPv6 */ + DBGLOG(PF, INFO, "Ver=%d\n", ucVer); + if (ucVer == 0) { + pWOW_CTRL->stWowPort.ucIPv4TcpPortCnt = ucCount; + pausPortArry = pWOW_CTRL->stWowPort.ausIPv4TcpPort; + } else { + pWOW_CTRL->stWowPort.ucIPv6TcpPortCnt = ucCount; + pausPortArry = pWOW_CTRL->stWowPort.ausIPv6TcpPort; + } + + /* Port */ + for (ii = 0; ii < ucCount; ii++) { + u4Ret = kalkStrtou16(apcPortArgv[ii+2], 0, &u2Port); + if (u4Ret) { + DBGLOG(PF, ERROR, "parse u2Port error u4Ret=%d\n", u4Ret); + return -1; + } + + pausPortArry[ii] = u2Port; + DBGLOG(PF, INFO, "ucPort=%d, idx=%d\n", u2Port, ii); + } + + return 0; + } else if (i4Argc == 2) { + + u4Ret = kalkStrtou8(apcPortArgv[1], 0, &ucVer); + if (u4Ret) { + DBGLOG(REQ, LOUD, "parse ucWakeupHif error u4Ret=%d\n", u4Ret); + return -1; + } + + if (ucVer == 0) { + kalMemZero(prGlueInfo->prAdapter-> + rWowCtrl.stWowPort.ausIPv4TcpPort, + sizeof(UINT_16) * MAX_TCP_UDP_PORT); + prGlueInfo->prAdapter-> + rWowCtrl.stWowPort.ucIPv4TcpPortCnt = 0; + } else { + kalMemZero(prGlueInfo->prAdapter-> + rWowCtrl.stWowPort.ausIPv6TcpPort, + sizeof(UINT_16) * MAX_TCP_UDP_PORT); + prGlueInfo->prAdapter-> + rWowCtrl.stWowPort.ucIPv6TcpPortCnt = 0; + } + + return 0; + } else + return -1; + +} + +static int priv_driver_get_wow_port(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_WOW_CTRL_T pWOW_CTRL = NULL; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + INT_32 u4Ret = 0, ii; + UINT_8 ucVer, ucProto; + UINT_16 ucCount; + PUINT_16 pausPortArry; + PCHAR aucIp[2] = {"IPv4", "IPv6"}; + PCHAR aucProto[2] = {"UDP", "TCP"}; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + pWOW_CTRL = &prGlueInfo->prAdapter->rWowCtrl; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + /* example: get_wow_port 0 0 (ipv4-udp) */ + /* example: get_wow_port 0 1 (ipv4-tcp) */ + /* example: get_wow_port 1 0 (ipv6-udp) */ + /* example: get_wow_port 1 1 (ipv6-tcp) */ + + if (i4Argc >= 3) { + + /* 0=IPv4, 1=IPv6 */ + u4Ret = kalkStrtou8(apcArgv[1], 0, &ucVer); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse argc[1] error u4Ret=%d\n", u4Ret); + + /* 0=UDP, 1=TCP */ + u4Ret = kalkStrtou8(apcArgv[2], 0, &ucProto); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse argc[2] error u4Ret=%d\n", u4Ret); + + if (ucVer > 1) + ucVer = 0; + + if (ucProto > 1) + ucProto = 0; + + if (ucVer == 0) { + if (ucProto == 0) { + /* IPv4/UDP */ + ucCount = pWOW_CTRL->stWowPort.ucIPv4UdpPortCnt; + pausPortArry = pWOW_CTRL->stWowPort.ausIPv4UdpPort; + } else { + /* IPv4/TCP */ + ucCount = pWOW_CTRL->stWowPort.ucIPv4TcpPortCnt; + pausPortArry = pWOW_CTRL->stWowPort.ausIPv4TcpPort; + } + } else { + if (ucProto == 0) { + /* IPv6/UDP */ + ucCount = pWOW_CTRL->stWowPort.ucIPv6UdpPortCnt; + pausPortArry = pWOW_CTRL->stWowPort.ausIPv6UdpPort; + } else { + /* IPv6/TCP */ + ucCount = pWOW_CTRL->stWowPort.ucIPv6TcpPortCnt; + pausPortArry = pWOW_CTRL->stWowPort.ausIPv6TcpPort; + } + } + + /* Dunp Port */ + for (ii = 0; ii < ucCount; ii++) + DBGLOG(PF, INFO, "ucPort=%d, idx=%d\n", pausPortArry[ii], ii); + + + DBGLOG(PF, INFO, "[%s/%s] count:%d\n", aucIp[ucVer], aucProto[ucProto], ucCount); + + return 0; + } else + return -1; + +} + +static int priv_driver_get_wow_reason(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Argc = 0; + INT_32 i4BytesWritten = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + P_WOW_CTRL_T pWOW_CTRL = NULL; + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + pWOW_CTRL = &prGlueInfo->prAdapter->rWowCtrl; + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (pWOW_CTRL->ucReason != INVALID_WOW_WAKE_UP_REASON) + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, "\nwakeup_reason:%d", pWOW_CTRL->ucReason); + + return i4BytesWritten; +} +#endif + +static int priv_driver_set_adv_pws(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + UINT_32 u4Ret = 0; + UINT_8 ucAdvPws = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + u4Ret = kalkStrtou8(apcArgv[1], 0, &ucAdvPws); + + if (u4Ret) + DBGLOG(REQ, LOUD, "parse bEnable error u4Ret=%d\n", u4Ret); + + prGlueInfo->prAdapter->rWifiVar.ucAdvPws = ucAdvPws; + + DBGLOG(INIT, INFO, "AdvPws:%d\n", + prGlueInfo->prAdapter->rWifiVar.ucAdvPws); + + return 0; + +} + +static int priv_driver_set_mdtim(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + UINT_32 u4Ret = 0; + UINT_8 ucMultiDtim = 0, ucVer; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + /* iwpriv wlan0 driver "set_mdtim 1 3 */ + if (i4Argc >= 3) { + + u4Ret = kalkStrtou8(apcArgv[1], 0, &ucVer); + if (u4Ret) { + DBGLOG(REQ, ERROR, "parse apcArgv1 error u4Ret=%d\n", u4Ret); + return -1; + } + + u4Ret = kalkStrtou8(apcArgv[2], 0, &ucMultiDtim); + if (u4Ret) { + DBGLOG(REQ, ERROR, "parse apcArgv2 error u4Ret=%d\n", u4Ret); + return -1; + } + + if (ucVer == 0) { + prGlueInfo->prAdapter->rWifiVar.ucWowOnMdtim = ucMultiDtim; + DBGLOG(REQ, INFO, "WOW On MDTIM:%d\n", + prGlueInfo->prAdapter->rWifiVar.ucWowOnMdtim); + } else { + prGlueInfo->prAdapter->rWifiVar.ucWowOffMdtim = ucMultiDtim; + DBGLOG(REQ, INFO, "WOW Off MDTIM:%d\n", + prGlueInfo->prAdapter->rWifiVar.ucWowOffMdtim); + } + } + + return 0; + +} + +static int priv_driver_set_listen_dtim_interval(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + UINT_32 u4Ret = 0; + UINT_8 ucInterval = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + /* iwpriv wlan0 driver "set_listen_dtim_interval x */ + if (i4Argc >= 2) { + + u4Ret = kalkStrtou8(apcArgv[1], 0, &ucInterval); + if (u4Ret) { + DBGLOG(REQ, ERROR, "parse apcArgv1 error u4Ret=%d\n", u4Ret); + return -1; + } + + prGlueInfo->prAdapter->rWifiVar.ucListenDtimInterval = ucInterval; + DBGLOG(REQ, INFO, "Listen Interval(DTIM) :%d\n", + prGlueInfo->prAdapter->rWifiVar.ucListenDtimInterval); + } + + return 0; +} + +int priv_driver_set_suspend_mode(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + BOOLEAN fgEnable; + UINT_32 u4Enable; + INT_32 u4Ret = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= 2) { + /* fgEnable = (kalStrtoul(apcArgv[1], NULL, 0) == 1) ? TRUE : FALSE; */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Enable); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse u4Enable error u4Ret=%d\n", u4Ret); + if (u4Enable == 1) + fgEnable = TRUE; + else + fgEnable = FALSE; + + DBGLOG(REQ, INFO, "%s: Set suspend mode [%u]\n", __func__, fgEnable); + + if (prGlueInfo->fgIsInSuspendMode == fgEnable) { + DBGLOG(REQ, INFO, "%s: Already in suspend mode, SKIP!\n", __func__); + return 0; + } + + prGlueInfo->fgIsInSuspendMode = fgEnable; + + wlanSetSuspendMode(prGlueInfo, fgEnable); + p2pSetSuspendMode(prGlueInfo, fgEnable); + } + + return 0; +} + +#if CFG_SUPPORT_SNIFFER +int priv_driver_set_monitor(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4Argc = 0; + INT_32 i4BytesWritten = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + PARAM_CUSTOM_MONITOR_SET_STRUCT_T rMonitorSetInfo; + UINT_8 ucEnable = 0; + UINT_8 ucPriChannel = 0; + UINT_8 ucChannelWidth = 0; + UINT_8 ucExt = 0; + UINT_8 ucSco = 0; + UINT_8 ucChannelS1 = 0; + UINT_8 ucChannelS2 = 0; + BOOLEAN fgIsLegalChannel = FALSE; + BOOLEAN fgError = FALSE; + BOOLEAN fgEnable = FALSE; + ENUM_BAND_T eBand = BAND_NULL; + UINT_32 u4Parse = 0; + INT_32 u4Ret = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc >= 5) { + /* ucEnable = (UINT_8) (kalStrtoul(apcArgv[1], NULL, 0)); + * ucPriChannel = (UINT_8) (kalStrtoul(apcArgv[2], NULL, 0)); + * ucChannelWidth = (UINT_8) (kalStrtoul(apcArgv[3], NULL, 0)); + * ucExt = (UINT_8) (kalStrtoul(apcArgv[4], NULL, 0)); + */ + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", u4Ret); + ucEnable = (UINT_8) u4Parse; + u4Ret = kalkStrtou32(apcArgv[2], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", u4Ret); + ucPriChannel = (UINT_8) u4Parse; + u4Ret = kalkStrtou32(apcArgv[3], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", u4Ret); + ucChannelWidth = (UINT_8) u4Parse; + u4Ret = kalkStrtou32(apcArgv[4], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", u4Ret); + ucExt = (UINT_8) u4Parse; + + eBand = (ucPriChannel <= 14) ? BAND_2G4 : BAND_5G; + fgIsLegalChannel = rlmDomainIsLegalChannel(prAdapter, eBand, ucPriChannel); + + if (fgIsLegalChannel == FALSE) { + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "Illegal primary channel %d", ucPriChannel); + return i4BytesWritten; + } + + switch (ucChannelWidth) { + case 160: + ucChannelWidth = (UINT_8) CW_160MHZ; + ucSco = (UINT_8) CHNL_EXT_SCN; + + if (ucPriChannel >= 36 && ucPriChannel <= 64) + ucChannelS2 = 50; + else if (ucPriChannel >= 100 && ucPriChannel <= 128) + ucChannelS2 = 114; + else + fgError = TRUE; + break; + + case 80: + ucChannelWidth = (UINT_8) CW_80MHZ; + ucSco = (UINT_8) CHNL_EXT_SCN; + + if (ucPriChannel >= 36 && ucPriChannel <= 48) + ucChannelS1 = 42; + else if (ucPriChannel >= 52 && ucPriChannel <= 64) + ucChannelS1 = 58; + else if (ucPriChannel >= 100 && ucPriChannel <= 112) + ucChannelS1 = 106; + else if (ucPriChannel >= 116 && ucPriChannel <= 128) + ucChannelS1 = 122; + else if (ucPriChannel >= 132 && ucPriChannel <= 144) + ucChannelS1 = 138; + else if (ucPriChannel >= 149 && ucPriChannel <= 161) + ucChannelS1 = 155; + else + fgError = TRUE; + break; + + case 40: + ucChannelWidth = (UINT_8) CW_20_40MHZ; + ucSco = (ucExt) ? (UINT_8) CHNL_EXT_SCA : (UINT_8) CHNL_EXT_SCB; + break; + + case 20: + ucChannelWidth = (UINT_8) CW_20_40MHZ; + ucSco = (UINT_8) CHNL_EXT_SCN; + break; + + default: + fgError = TRUE; + break; + } + + if (fgError) { + i4BytesWritten = + snprintf(pcCommand, i4TotalLen, "Invalid primary channel %d with bandwidth %d", + ucPriChannel, ucChannelWidth); + return i4BytesWritten; + } + + fgEnable = (ucEnable) ? TRUE : FALSE; + + if (prGlueInfo->fgIsEnableMon != fgEnable) { + prGlueInfo->fgIsEnableMon = fgEnable; + schedule_work(&prGlueInfo->monWork); + } + + kalMemZero(&rMonitorSetInfo, sizeof(rMonitorSetInfo)); + + rMonitorSetInfo.ucEnable = ucEnable; + rMonitorSetInfo.ucPriChannel = ucPriChannel; + rMonitorSetInfo.ucSco = ucSco; + rMonitorSetInfo.ucChannelWidth = ucChannelWidth; + rMonitorSetInfo.ucChannelS1 = ucChannelS1; + rMonitorSetInfo.ucChannelS2 = ucChannelS2; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetMonitor, + &rMonitorSetInfo, sizeof(rMonitorSetInfo), FALSE, FALSE, TRUE, &u4BufLen); + + i4BytesWritten = + snprintf(pcCommand, i4TotalLen, "set monitor config %s", + (rStatus == WLAN_STATUS_SUCCESS) ? "success" : "fail"); + + return i4BytesWritten; + } + + i4BytesWritten = snprintf(pcCommand, i4TotalLen, "monitor [Enable][PriChannel][ChannelWidth][Sco]"); + + return i4BytesWritten; +} +#endif + +static int priv_driver_get_version(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter; + INT_32 i4BytesWritten = 0; + UINT_32 u4Offset = 0; + P_WIFI_VER_INFO_T prVerInfo; + tailer_format_t *prTailer; + UINT_8 aucBuf[32], aucDate[32]; + + ASSERT(prNetDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + prVerInfo = &prAdapter->rVerInfo; + + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "\nChip ROM ver [%u]\n", prAdapter->chip_info->eco_ver); + + wlanPrintVersion(prAdapter); + + kalStrnCpy(aucBuf, prVerInfo->aucFwBranchInfo, 4); + aucBuf[4] = '\0'; + kalStrnCpy(aucDate, prVerInfo->aucFwDateCode, 16); + aucDate[16] = '\0'; + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "\nN9 FW version %s-%u.%u.%u[DEC] (%s)\n", + aucBuf, (UINT_32)(prVerInfo->u2FwOwnVersion >> 8), + (UINT_32)(prVerInfo->u2FwOwnVersion & BITS(0, 7)), + prVerInfo->ucFwBuildNumber, aucDate); +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + if (prVerInfo->fgIsN9CompressedFW) { + tailer_format_t_2 *prTailer; + + prTailer = &prVerInfo->rN9Compressedtailer; + kalMemCopy(aucBuf, prTailer->ram_version, 10); + aucBuf[10] = '\0'; + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "N9 tailer version %s (%s) info %u:E%u\n", + aucBuf, prTailer->ram_built_date, prTailer->chip_info, + prTailer->eco_code + 1); + } else { + prTailer = &prVerInfo->rN9tailer; + kalMemCopy(aucBuf, prTailer->ram_version, 10); + aucBuf[10] = '\0'; + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "N9 tailer version %s (%s) info %u:E%u\n", + aucBuf, prTailer->ram_built_date, prTailer->chip_info, + prTailer->eco_code + 1); + } + if (prVerInfo->fgIsCR4CompressedFW) { + tailer_format_t_2 *prTailer; + + prTailer = &prVerInfo->rCR4Compressedtailer; + kalMemCopy(aucBuf, prTailer->ram_version, 10); + aucBuf[10] = '\0'; + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "CR4 tailer version %s (%s) info %u:E%u\n", + aucBuf, prTailer->ram_built_date, prTailer->chip_info, + prTailer->eco_code + 1); + } else { + prTailer = &prVerInfo->rCR4tailer; + kalMemCopy(aucBuf, prTailer->ram_version, 10); + aucBuf[10] = '\0'; + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "CR4 tailer version %s (%s) info %u:E%u\n", + aucBuf, prTailer->ram_built_date, prTailer->chip_info, + prTailer->eco_code + 1); + } +#else + prTailer = &prVerInfo->rN9tailer; + kalMemCopy(aucBuf, prTailer->ram_version, 10); + aucBuf[10] = '\0'; + kalMemCopy(aucDate, prTailer->ram_built_date, sizeof(prTailer->ram_built_date)); + aucDate[sizeof(prTailer->ram_built_date)] = '\0'; + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "N9 tailer version %s (%s) info %u:E%u\n", + aucBuf, aucDate, prTailer->chip_info, + prTailer->eco_code + 1); + + prTailer = &prVerInfo->rCR4tailer; + kalMemCopy(aucBuf, prTailer->ram_version, 10); + aucBuf[10] = '\0'; + kalMemCopy(aucDate, prTailer->ram_built_date, sizeof(prTailer->ram_built_date)); + aucDate[sizeof(prTailer->ram_built_date)] = '\0'; + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "CR4 tailer version %s (%s) info %u:E%u\n", + aucBuf, aucDate, prTailer->chip_info, + prTailer->eco_code + 1); +#endif + if (!prVerInfo->fgPatchIsDlByDrv) { + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "Patch is not downloaded by driver, read patch binary\n"); + wlanGetPatchInfo(prAdapter); + } + + kalStrnCpy(aucBuf, prVerInfo->rPatchHeader.aucPlatform, 4); + aucBuf[4] = '\0'; + kalStrnCpy(aucDate, prVerInfo->rPatchHeader.aucBuildDate, 16); + aucDate[16] = '\0'; + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "Patch platform %s version 0x%04X %s\n", + aucBuf, prVerInfo->rPatchHeader.u4PatchVersion, aucDate); + +#if 0 + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "Drv version %u.%u[DEC]", (prVerInfo->u2FwPeerVersion >> 8), + (prVerInfo->u2FwPeerVersion & BITS(0, 7))); +#endif + + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "WiFi Driver Version " NIC_DRIVER_VERSION_STRING "\n"); + + i4BytesWritten = (INT_32)u4Offset; + + return i4BytesWritten; +} + +#if CFG_SUPPORT_DBDC +int priv_driver_set_dbdc(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + + UINT_32 u4Ret, u4Parse; + + UINT_8 ucDBDCEnable; + /*UINT_8 ucBssIndex;*/ + /*P_BSS_INFO_T prBssInfo;*/ + + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); +#if 0 + for (ucBssIndex = 0; ucBssIndex < (HW_BSSID_NUM+1); ucBssIndex++) { + prBssInfo = prGlueInfo->prAdapter->aprBssInfo[ucBssIndex]; + pr_info("****BSS %u inUse %u active %u Mode %u priCh %u state %u rfBand %u\n", + ucBssIndex, + prBssInfo->fgIsInUse, + prBssInfo->fgIsNetActive, + prBssInfo->eCurrentOPMode, + prBssInfo->ucPrimaryChannel, + prBssInfo->eConnectionState, + prBssInfo->eBand); + } +#endif + if (prGlueInfo->prAdapter->rWifiVar.ucDbdcMode != DBDC_MODE_DYNAMIC) { + DBGLOG(REQ, LOUD, "Current DBDC mode %u cannot enable/disable DBDC!!\n", + prGlueInfo->prAdapter->rWifiVar.ucDbdcMode); + return -1; + } + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc == 2) { + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Parse); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv error u4Ret=%d\n", u4Ret); + + ucDBDCEnable = (UINT_8) u4Parse; + if ((!prGlueInfo->prAdapter->rWifiVar.fgDbDcModeEn && !ucDBDCEnable) || + (prGlueInfo->prAdapter->rWifiVar.fgDbDcModeEn && ucDBDCEnable)) + return i4BytesWritten; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetDbdcEnable, + &ucDBDCEnable, 1, + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + } else { + DBGLOG(INIT, ERROR, "iwpriv wlanXX driver SET_DBDC \n"); + DBGLOG(INIT, ERROR, " 1: enable. 0: disable.\n"); + } + + return i4BytesWritten; +} +#endif /*CFG_SUPPORT_DBDC*/ + +#if CFG_SUPPORT_BATCH_SCAN +#define CMD_BATCH_SET "WLS_BATCHING SET" +#define CMD_BATCH_GET "WLS_BATCHING GET" +#define CMD_BATCH_STOP "WLS_BATCHING STOP" +#endif + +static int priv_driver_get_que_info(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + return qmDumpQueueStatus(prGlueInfo->prAdapter, pcCommand, i4TotalLen); +} + +static int priv_driver_get_mem_info(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + return cnmDumpMemoryStatus(prGlueInfo->prAdapter, pcCommand, i4TotalLen); +} + +static int priv_driver_get_hif_info(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + return halDumpHifStatus(prGlueInfo->prAdapter, pcCommand, i4TotalLen); +} + +int priv_driver_set_p2p_ps(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = {0}; + UINT_32 u4Ret; + INT_32 i4Parameter; + PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T rOpppsParamInfo; + UINT_8 ucRoleIdx = 0; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc >= 3) { + /* get Bss Index from ndev */ + if (mtk_Netdev_To_RoleIdx(prGlueInfo, prNetDev, &ucRoleIdx) != 0) + return -1; + if (p2pFuncRoleToBssIdx(prGlueInfo->prAdapter, ucRoleIdx, &rOpppsParamInfo.ucBssIdx) != + WLAN_STATUS_SUCCESS) + return -1; + + DBGLOG(REQ, LOUD, "priv_driver_set_p2p_ps bss Idx %u\n", rOpppsParamInfo.ucBssIdx); + + u4Ret = kalkStrtos32(apcArgv[1], 0, &i4Parameter); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv[1] error u4Ret=%d\n", u4Ret); + + if (i4Parameter >= 1) + rOpppsParamInfo.ucLegcyPS = 1; + else + rOpppsParamInfo.ucLegcyPS = 0; + + u4Ret = kalkStrtos32(apcArgv[2], 0, &i4Parameter); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv[2] error u4Ret=%d\n", u4Ret); + + if (i4Parameter >= 1) + rOpppsParamInfo.ucOppPs = 1; + else + rOpppsParamInfo.ucOppPs = 0; + + u4Ret = kalkStrtos32(apcArgv[3], 0, &i4Parameter); + if (u4Ret) + DBGLOG(REQ, LOUD, "parse apcArgv[2] error u4Ret=%d\n", u4Ret); + + if (rOpppsParamInfo.ucOppPs) + rOpppsParamInfo.u4CTwindowMs = (UINT_32)i4Parameter; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetOppPsParam, + &rOpppsParamInfo, sizeof(rOpppsParamInfo), + FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + } else { + DBGLOG(INIT, ERROR, "ERR, iwpriv wlanXX driver SET_P2P_PS \n"); + } + + return i4BytesWritten; +} + +#if CFG_SUPPORT_LAST_SEC_MCS_INFO +static int priv_driver_get_mcs_info(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0, i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + P_PARAM_HW_WLAN_INFO_T prHwWlanInfo = NULL; + struct PARAM_TX_MCS_INFO *prTxMcsInfo = NULL; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (prGlueInfo->prAdapter->rRxMcsInfoTimer.pfMgmtTimeOutFunc == NULL) { + cnmTimerInitTimer(prGlueInfo->prAdapter, + &prGlueInfo->prAdapter->rRxMcsInfoTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisRxMcsCollectionTimeout, (ULONG) NULL); + } + + if (i4Argc >= 2) { + if (strnicmp(apcArgv[1], "START", strlen("START")) == 0) { + cnmTimerStartTimer(prGlueInfo->prAdapter, &prGlueInfo->prAdapter->rRxMcsInfoTimer, 100); + prGlueInfo->prAdapter->fgIsMcsInfoValid = TRUE; + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nStart the MCS Info Function\n"); + return i4BytesWritten; + } else if (strnicmp(apcArgv[1], "STOP", strlen("STOP")) == 0) { + cnmTimerStopTimer(prGlueInfo->prAdapter, &prGlueInfo->prAdapter->rRxMcsInfoTimer); + prGlueInfo->prAdapter->fgIsMcsInfoValid = FALSE; + + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nStop the MCS Info Function\n"); + return i4BytesWritten; + } + } + + if (prGlueInfo->prAdapter->fgIsMcsInfoValid != TRUE) { + i4BytesWritten += kalScnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nUse GET_MCS_INFO [START/STOP] to control the MCS Info Function\n"); + return i4BytesWritten; + } + + if (prGlueInfo->prAdapter->prAisBssInfo->eConnectionState != PARAM_MEDIA_STATE_CONNECTED) + return -1; + + prHwWlanInfo = (P_PARAM_HW_WLAN_INFO_T)kalMemAlloc(sizeof(PARAM_HW_WLAN_INFO_T), VIR_MEM_TYPE); + if (!prHwWlanInfo) + return -1; + + prHwWlanInfo->u4Index = prGlueInfo->prAdapter->prAisBssInfo->prStaRecOfAP->ucWlanIndex; + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryWlanInfo, + prHwWlanInfo, sizeof(PARAM_HW_WLAN_INFO_T), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, INFO, "rStatus %u u4BufLen = %d\n", rStatus, u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + goto out; + + prTxMcsInfo = (struct PARAM_TX_MCS_INFO *)kalMemAlloc(sizeof(struct PARAM_TX_MCS_INFO), VIR_MEM_TYPE); + if (!prTxMcsInfo) + goto out; + + prTxMcsInfo->ucStaIndex = prGlueInfo->prAdapter->prAisBssInfo->prStaRecOfAP->ucIndex; + rStatus = kalIoctl(prGlueInfo, + wlanoidTxMcsInfo, + prTxMcsInfo, sizeof(struct PARAM_TX_MCS_INFO), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, INFO, "rStatus %u u4BufLen = %d\n", rStatus, u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + goto out; + + i4BytesWritten = priv_driver_last_sec_mcs_info(prGlueInfo->prAdapter, + pcCommand, i4TotalLen, prHwWlanInfo, prTxMcsInfo); + + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + +out: + if (prHwWlanInfo) + kalMemFree(prHwWlanInfo, VIR_MEM_TYPE, sizeof(PARAM_HW_WLAN_INFO_T)); + if (prTxMcsInfo) + kalMemFree(prTxMcsInfo, VIR_MEM_TYPE, sizeof(struct PARAM_TX_MCS_INFO)); + + return i4BytesWritten; +} +#endif + +static int priv_driver_get_deep_sleep_cnt(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + CNM_STATUS_T rCnmStatus; + PUINT_32 pu4Ptr; + UINT_32 u4Offset = 0; + PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo; + + ASSERT(prNetDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = 0xb0100000; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + pu4Ptr = (PUINT_32)&rCnmStatus; + *pu4Ptr = rSwCtrlInfo.u4Data; + + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "Deep Sleep Cnt %d\n", rSwCtrlInfo.u4Data); + + i4BytesWritten = (INT_32)u4Offset; + + return i4BytesWritten; +} + +static int priv_driver_get_cnm_info(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + CNM_STATUS_T rCnmStatus; + PUINT_32 pu4Ptr; + P_CNM_CH_LIST_T prChList; + UINT_32 u4Offset = 0; + PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo; + + ASSERT(prNetDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = 0xb0000000; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + pu4Ptr = (PUINT_32)&rCnmStatus; + *pu4Ptr = rSwCtrlInfo.u4Data; + + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "DBDC is %s, %u CHs in BAND0, %u CHs in BAND1\n", + rCnmStatus.fgDbDcModeEn ? "ON" : "OFF", rCnmStatus.ucChNumB0, rCnmStatus.ucChNumB1); + + if (rCnmStatus.ucChNumB0 > 0) { + rSwCtrlInfo.u4Id = 0xb0010000; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + prChList = (P_CNM_CH_LIST_T)&rSwCtrlInfo.u4Data; + + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "BAND0 channels : %u %u %u\n", + prChList->ucChNum[0], prChList->ucChNum[1], prChList->ucChNum[2]); + } + if (rCnmStatus.ucChNumB1 > 0) { + rSwCtrlInfo.u4Id = 0xb0010001; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + prChList = (P_CNM_CH_LIST_T)&rSwCtrlInfo.u4Data; + + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "BAND1 channels : %u %u %u\n", + prChList->ucChNum[0], prChList->ucChNum[1], prChList->ucChNum[2]); + } + + i4BytesWritten = (INT_32)u4Offset; + + return i4BytesWritten; + +} /* priv_driver_get_sw_ctrl */ + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +static int priv_driver_get_ch_rank_list(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 i4BytesWritten = 0; + INT_8 ucIdx = 0, ucIdx2 = 0, ucChannelNum = 0, + ucNumOf2gChannel = 0, ucNumOf5gChannel = 0; + P_PARAM_GET_CHN_INFO prChnLoadInfo = NULL; + RF_CHANNEL_INFO_T *prChannelList = NULL, + auc2gChannelList[MAX_2G_BAND_CHN_NUM], + auc5gChannelList[MAX_5G_BAND_CHN_NUM]; + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prChnLoadInfo = &(prGlueInfo->prAdapter->rWifiVar.rChnLoadInfo); + kalMemZero(pcCommand, i4TotalLen); + + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_2G4, TRUE, + MAX_2G_BAND_CHN_NUM, &ucNumOf2gChannel, auc2gChannelList); + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_5G, TRUE, + MAX_5G_BAND_CHN_NUM, &ucNumOf5gChannel, auc5gChannelList); + + for (ucIdx = 0; ucIdx < MAX_CHN_NUM; ucIdx++) { + + if (prChnLoadInfo->rChnRankList[ucIdx].ucChannel > 14) { + prChannelList = auc5gChannelList; + ucChannelNum = ucNumOf5gChannel; + } else { + prChannelList = auc2gChannelList; + ucChannelNum = ucNumOf2gChannel; + } + + for (ucIdx2 = 0; ucIdx2 < ucChannelNum; ucIdx2++) { + if (prChnLoadInfo->rChnRankList[ucIdx].ucChannel == + prChannelList[ucIdx2].ucChannelNum) { + pcCommand[i4BytesWritten++] = + prChnLoadInfo->rChnRankList[ucIdx].ucChannel; + DBGLOG(SCN, TRACE, "ch %u, dirtiness %d\n", + prChnLoadInfo->rChnRankList[ucIdx].ucChannel, + prChnLoadInfo->rChnRankList[ucIdx].u4Dirtiness); + break; + } + } + } + + return i4BytesWritten; +} + +static int priv_driver_get_ch_dirtiness(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_8 cIdx = 0; + UINT_8 ucNumOf2gChannel = 0; + UINT_8 ucNumOf5gChannel = 0; + UINT_32 i4BytesWritten = 0; + P_PARAM_GET_CHN_INFO prChnLoadInfo = NULL; + RF_CHANNEL_INFO_T ar2gChannelList[MAX_2G_BAND_CHN_NUM]; + RF_CHANNEL_INFO_T ar5gChannelList[MAX_5G_BAND_CHN_NUM]; + + ASSERT(prNetDev); + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prChnLoadInfo = &(prGlueInfo->prAdapter->rWifiVar.rChnLoadInfo); + kalMemZero(pcCommand, i4TotalLen); + + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_2G4, TRUE, + MAX_2G_BAND_CHN_NUM, &ucNumOf2gChannel, ar2gChannelList); + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_5G, TRUE, + MAX_5G_BAND_CHN_NUM, &ucNumOf5gChannel, ar5gChannelList); + + for (cIdx = 0; cIdx < MAX_CHN_NUM; cIdx++) { + INT_8 cIdx2 = 0; + UINT_8 ucChannelNum = 0; + UINT_32 u4Offset = 0; + RF_CHANNEL_INFO_T *prChannelList = NULL; + + if (prChnLoadInfo->rChnRankList[cIdx].ucChannel > 14) { + prChannelList = ar5gChannelList; + ucChannelNum = ucNumOf5gChannel; + } else { + prChannelList = ar2gChannelList; + ucChannelNum = ucNumOf2gChannel; + } + + for (cIdx2 = 0; cIdx2 < ucChannelNum; cIdx2++) { + if (prChnLoadInfo->rChnRankList[cIdx].ucChannel == + prChannelList[cIdx2].ucChannelNum) { + u4Offset = kalSnprintf(pcCommand + i4BytesWritten, + i4TotalLen - i4BytesWritten, + "\nch %03u -> dirtiness %u", + prChnLoadInfo->rChnRankList[cIdx].ucChannel, + prChnLoadInfo->rChnRankList[cIdx].u4Dirtiness); + i4BytesWritten += u4Offset; + break; + } + + if (i4BytesWritten >= i4TotalLen) + return i4BytesWritten; + } + } + + return i4BytesWritten; +} +#endif + +static int priv_driver_efuse_ops(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + enum EFUSE_OP_MODE { + EFUSE_READ, + EFUSE_WRITE, + EFUSE_FREE, + EFUSE_INVALID, + }; + UINT_8 ucOpMode = EFUSE_INVALID; + UCHAR ucOpChar; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + UINT_32 u4Ret; + INT_32 i4Parameter; + UINT_32 u4Efuse_addr = 0; + UINT_8 ucEfuse_value = 0; + +#if (CFG_EEPROM_PAGE_ACCESS == 1) + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4Offset = 0; + UINT_32 u4BufLen = 0; + UINT_8 u4Index = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CUSTOM_ACCESS_EFUSE_T rAccessEfuseInfo; +#endif + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + /* Sanity check */ + if (i4Argc < 2) + goto efuse_op_invalid; + + ucOpChar = (UCHAR)apcArgv[1][0]; + if ((i4Argc == 3) && (ucOpChar == 'r' || ucOpChar == 'R')) + ucOpMode = EFUSE_READ; + else if ((i4Argc == 4) && (ucOpChar == 'w' || ucOpChar == 'W')) + ucOpMode = EFUSE_WRITE; + else if ((ucOpChar == 'f' || ucOpChar == 'F')) + ucOpMode = EFUSE_FREE; + + /* Print out help if input format is wrong */ + if (ucOpMode == EFUSE_INVALID) + goto efuse_op_invalid; + + /* convert address */ + if (ucOpMode == EFUSE_READ || ucOpMode == EFUSE_WRITE) { + u4Ret = kalkStrtos32(apcArgv[2], 16, &i4Parameter); + u4Efuse_addr = (UINT_32)i4Parameter; + } + + /* convert value */ + if (ucOpMode == EFUSE_WRITE) { + u4Ret = kalkStrtos32(apcArgv[3], 16, &i4Parameter); + ucEfuse_value = (UINT_8)i4Parameter; + } + + /* Start operation */ +#if (CFG_EEPROM_PAGE_ACCESS == 1) + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + kalMemSet(&rAccessEfuseInfo, 0, sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T)); + rAccessEfuseInfo.u4Address = (u4Efuse_addr / EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE; + u4Index = u4Efuse_addr % EFUSE_BLOCK_SIZE; + + if (ucOpMode == EFUSE_READ) { + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseRead, + &rAccessEfuseInfo, + sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T), TRUE, TRUE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_SUCCESS) { + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "Read success 0x%X = 0x%X\n", u4Efuse_addr + , prGlueInfo->prAdapter->aucEepromVaule[u4Index]); + } + } else if (ucOpMode == EFUSE_WRITE) { + + prGlueInfo->prAdapter->aucEepromVaule[u4Index] = ucEfuse_value; + + kalMemCopy(rAccessEfuseInfo.aucData, prGlueInfo->prAdapter->aucEepromVaule, 16); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryProcessAccessEfuseWrite, + &rAccessEfuseInfo, + sizeof(PARAM_CUSTOM_ACCESS_EFUSE_T), FALSE, FALSE, TRUE, &u4BufLen); + if (rStatus == WLAN_STATUS_SUCCESS) { + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "Write success 0x%X = 0x%X\n" + , u4Efuse_addr + , ucEfuse_value); + } + } else if (ucOpMode == EFUSE_FREE) { + PARAM_CUSTOM_EFUSE_FREE_BLOCK_T rEfuseFreeBlock = {}; + + if (prGlueInfo->prAdapter->fgIsSupportGetFreeEfuseBlockCount == FALSE) { + u4Offset += snprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, "Cannot read free block size\n"); + return (INT_32)u4Offset; + } + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryEfuseFreeBlock, + &rEfuseFreeBlock, + sizeof(PARAM_CUSTOM_EFUSE_FREE_BLOCK_T), TRUE, TRUE, TRUE, &u4BufLen); + if (rStatus == WLAN_STATUS_SUCCESS) { + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "Free block size 0x%X\n", prGlueInfo->prAdapter->u4FreeBlockNum); + } + } +#else + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "efuse ops is invalid\n"); +#endif + + return (INT_32)u4Offset; + +efuse_op_invalid: + + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "\nHelp menu\n"); + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "\tRead:\t\"efuse read addr_hex\"\n"); + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "\tWrite:\t\"efuse write addr_hex val_hex\"\n"); + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "\tFree Blocks:\t\"efuse free\"\n"); + return (INT_32)u4Offset; +} + +static int priv_driver_cccr_ops(IN struct net_device *prNetDev, + IN char *pcCommand, IN int i4TotalLen) +{ + uint32_t u4Offset = 0; +#if defined(_HIF_SDIO) && (MTK_WCN_HIF_SDIO == 0) + enum CCCR_OP_MODE { + CCCR_READ, + CCCR_WRITE, + CCCR_INVALID, + }; + uint8_t ucOpMode = CCCR_INVALID; + uint8_t ucOpChar; + int32_t i4Argc = 0; + int8_t *apcArgv[WLAN_CFG_ARGV_MAX]; + int32_t i4Ret; + int32_t i4Parameter; + uint32_t u4CCCR_addr = 0; + uint8_t ucCCCR_value = 0; + + uint32_t rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + + struct sdio_func *func; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + /* Sanity check */ + if (i4Argc < 2) + goto cccr_op_invalid; + + ucOpChar = (uint8_t)apcArgv[1][0]; + if ((i4Argc == 3) && (ucOpChar == 'r' || ucOpChar == 'R')) + ucOpMode = CCCR_READ; + else if ((i4Argc == 4) && (ucOpChar == 'w' || ucOpChar == 'W')) + ucOpMode = CCCR_WRITE; + + /* Print out help if input format is wrong */ + if (ucOpMode == CCCR_INVALID) + goto cccr_op_invalid; + + /* convert address */ + if (ucOpMode == CCCR_READ || ucOpMode == CCCR_WRITE) { + i4Ret = kalkStrtos32(apcArgv[2], 16, &i4Parameter); + /* Valid address 0x0~0xFF */ + u4CCCR_addr = (uint32_t)(i4Parameter & 0xFF); + } + + /* convert value */ + if (ucOpMode == CCCR_WRITE) { + i4Ret = kalkStrtos32(apcArgv[3], 16, &i4Parameter); + ucCCCR_value = (uint8_t)i4Parameter; + } + + /* Set SDIO host reference */ + func = prGlueInfo->rHifInfo.func; + + /* Start operation */ + if (ucOpMode == CCCR_READ) { + sdio_claim_host(func); + ucCCCR_value = sdio_f0_readb(func, u4CCCR_addr, &rStatus); + sdio_release_host(func); + + if (rStatus) /* Fail case */ + u4Offset += snprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "Read Fail 0x%X (ret=%d)\n", + u4CCCR_addr, rStatus); + else + u4Offset += snprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "Read success 0x%X = 0x%X\n", + u4CCCR_addr, ucCCCR_value); + } else if (ucOpMode == CCCR_WRITE) { + uint32_t quirks_bak; + + sdio_claim_host(func); + /* Enable capability to write CCCR */ + quirks_bak = func->card->quirks; + func->card->quirks |= MMC_QUIRK_LENIENT_FN0; + /* Write CCCR into card */ + sdio_f0_writeb(func, ucCCCR_value, u4CCCR_addr, &rStatus); + func->card->quirks = quirks_bak; + sdio_release_host(func); + + if (rStatus) /* Fail case */ + u4Offset += snprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "Write Fail 0x%X (ret=%d)\n", + u4CCCR_addr, rStatus); + else + u4Offset += snprintf(pcCommand + u4Offset, + i4TotalLen - u4Offset, + "Write success 0x%X = 0x%X\n", + u4CCCR_addr, ucCCCR_value); + } + + return (int32_t)u4Offset; + +cccr_op_invalid: + + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "\nHelp menu\n"); + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "\tRead:\t\"cccr read addr_hex\"\n"); + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "\tWrite:\t\"cccr write addr_hex val_hex\"\n"); +#else + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "\tSupport Linux standard SDIO only\n"); +#endif /* _HIF_SDIO && (MTK_WCN_HIF_SDIO == 0) */ + return (int32_t)u4Offset; +} + + + +#if CFG_SUPPORT_ADVANCE_CONTROL +static int priv_driver_set_noise(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + INT_32 u4Ret = 0; + UINT_32 u4Id = CMD_SW_DBGCTL_ADVCTL_SET_ID + CMD_ADVCTL_NOISE_ID; + UINT_32 u4Sel = 0; + PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + rSwCtrlInfo.u4Id = u4Id; + + if (i4Argc <= 1) { + DBGLOG(REQ, ERROR, "Argc(%d) ERR: SET_NOISE \n", i4Argc); + return -1; + } + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Sel); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + + rSwCtrlInfo.u4Data = u4Sel << 30; + DBGLOG(REQ, LOUD, "u4Sel=%d u4Data=0x%x,\n", u4Sel, rSwCtrlInfo.u4Data); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + return i4BytesWritten; + +} + +static int priv_driver_get_noise(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + UINT_32 u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + CMD_ADVCTL_NOISE_ID; + UINT_32 u4Offset = 0; + PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo; + INT_16 u2Wf0AvgPwr, u2Wf1AvgPwr; + + ASSERT(prNetDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = u4Id; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + u2Wf0AvgPwr = rSwCtrlInfo.u4Data & 0xFFFF; + u2Wf1AvgPwr = (rSwCtrlInfo.u4Data >> 16) & 0xFFFF; + + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "Noise Idle Avg. Power: WF0:%ddB WF1:%ddB\n", u2Wf0AvgPwr, u2Wf1AvgPwr); + + i4BytesWritten = (INT_32)u4Offset; + + return i4BytesWritten; + +} /* priv_driver_get_sw_ctrl */ + +static int priv_driver_get_traffic_report(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo; + INT_32 i4BytesWritten = 0; + UINT_32 u4BufLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + struct CMD_GET_TRAFFIC_REPORT *cmd = NULL; + UINT_8 ucBand = ENUM_BAND_0; + UINT_16 u2Val = 0; + UINT_8 ucVal = 0; + INT_32 u4Ret = 0; + BOOL fgWaitResp = FALSE; + BOOL fgRead = FALSE; + BOOL fgGetDbg = FALSE; + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + if (!prGlueInfo) + goto get_report_invalid; + + cmd = (struct CMD_GET_TRAFFIC_REPORT *)kalMemAlloc(sizeof(*cmd), VIR_MEM_TYPE); + if (!cmd) + goto get_report_invalid; + + if ((i4Argc > 4) || (i4Argc < 2)) + goto get_report_invalid; + + memset(cmd, 0, sizeof(*cmd)); + + cmd->u2Type = CMD_GET_REPORT_TYPE; + cmd->u2Len = sizeof(*cmd); + cmd->ucBand = ucBand; + + if (strnicmp(apcArgv[1], "ENABLE", strlen("ENABLE")) == 0) { + prGlueInfo->prAdapter->u4IsKeepFullPwrBitmap |= KEEP_FULL_PWR_TRAFFIC_REPORT_BIT; + cmd->ucAction = CMD_GET_REPORT_ENABLE; + cmd->u2Type |= CMD_ADV_CONTROL_SET; + } else if (strnicmp(apcArgv[1], "DISABLE", strlen("DISABLE")) == 0) { + prGlueInfo->prAdapter->u4IsKeepFullPwrBitmap &= ~KEEP_FULL_PWR_TRAFFIC_REPORT_BIT; + cmd->ucAction = CMD_GET_REPORT_DISABLE; + cmd->u2Type |= CMD_ADV_CONTROL_SET; + } else if (strnicmp(apcArgv[1], "RESET", strlen("RESET")) == 0) { + cmd->ucAction = CMD_GET_REPORT_RESET; + cmd->u2Type |= CMD_ADV_CONTROL_SET; + } else if ((strnicmp(apcArgv[1], "GET", strlen("GET")) == 0) || + (strnicmp(apcArgv[1], "GETDBG", strlen("GETDBG")) == 0)) { + cmd->ucAction = CMD_GET_REPORT_GET; + fgWaitResp = TRUE; + fgRead = TRUE; + if ((i4Argc == 4) && (strnicmp(apcArgv[2], "BAND", strlen("BAND")) == 0)) { + u4Ret = kalkStrtou8(apcArgv[3], 0, &ucVal); + cmd->ucBand = ucVal; + } + if (strnicmp(apcArgv[1], "GETDBG", strlen("GETDBG")) == 0) + fgGetDbg = TRUE; + } else if ((strnicmp(apcArgv[1], "SAMPLEPOINTS", strlen("SAMPLEPOINTS")) == 0) && (i4Argc == 3)) { + u4Ret = kalkStrtou16(apcArgv[2], 0, &u2Val); + cmd->u2SamplePoints = u2Val; + cmd->u2Type |= CMD_ADV_CONTROL_SET; + cmd->ucAction = CMD_SET_REPORT_SAMPLE_POINT; + } else if ((strnicmp(apcArgv[1], "TXTHRES", strlen("TXTHRES")) == 0) && (i4Argc == 3)) { + u4Ret = kalkStrtou8(apcArgv[2], 0, &ucVal); + /* valid val range is from 0 - 100% */ + if (ucVal > 100) + ucVal = 100; + cmd->ucTxThres = ucVal; + cmd->u2Type |= CMD_ADV_CONTROL_SET; + cmd->ucAction = CMD_SET_REPORT_TXTHRES; + } else if ((strnicmp(apcArgv[1], "RXTHRES", strlen("RXTHRES")) == 0) && (i4Argc == 3)) { + u4Ret = kalkStrtou8(apcArgv[2], 0, &ucVal); + /* valid val range is from 0 - 100% */ + if (ucVal > 100) + ucVal = 100; + cmd->ucRxThres = ucVal; + cmd->u2Type |= CMD_ADV_CONTROL_SET; + cmd->ucAction = CMD_SET_REPORT_RXTHRES; + } else + goto get_report_invalid; + + DBGLOG(REQ, LOUD, "%s(%s) action %x band %x wait_resp %x\n" + , __func__, pcCommand, cmd->ucAction, ucBand, fgWaitResp); + + rStatus = kalIoctl(prGlueInfo, wlanoidAdvCtrl, cmd, sizeof(*cmd), TRUE, TRUE, TRUE, &u4BufLen); + + if ((rStatus != WLAN_STATUS_SUCCESS) && (rStatus != WLAN_STATUS_PENDING)) + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\ncommand failed %x", rStatus); + else if (cmd->ucAction == CMD_GET_REPORT_GET) { + int persentage = 0; + int sample_dur = cmd->u4FetchEd - cmd->u4FetchSt; + + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\nCCK false detect cnt: %d" + , (cmd->u4FalseCCA >> EVENT_REPORT_CCK_FCCA) & EVENT_REPORT_CCK_FCCA_FEILD); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\nOFDM false detect cnt: %d" + , (cmd->u4FalseCCA >> EVENT_REPORT_OFDM_FCCA) & EVENT_REPORT_OFDM_FCCA_FEILD); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\nCCK Sig CRC cnt: %d" + , (cmd->u4HdrCRC >> EVENT_REPORT_CCK_SIGERR) & EVENT_REPORT_CCK_SIGERR_FEILD); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\nOFDM Sig CRC cnt: %d" + , (cmd->u4HdrCRC >> EVENT_REPORT_OFDM_SIGERR) & EVENT_REPORT_OFDM_SIGERR_FEILD); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\nBand%d Info:", cmd->ucBand); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n\tSample every %u ms with %u points", cmd->u4TimerDur, cmd->u2SamplePoints); + if (fgGetDbg) { + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + " from systime %u - %u total_dur %u us f_cost %u us t_drift %d ms" + , cmd->u4FetchSt, cmd->u4FetchEd + , sample_dur + , cmd->u4FetchCost, cmd->TimerDrift); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n\tbusy-RMAC %u us, idle-TMAC %u us, t_total %u" + , cmd->u4ChBusy, cmd->u4ChIdle, cmd->u4ChBusy + cmd->u4ChIdle); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n\theavy tx threshold %u%% rx threshold %u%%" + , cmd->ucTxThres, cmd->ucRxThres); + } + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n\tch_busy %u us, ch_idle %u us, total_period %u us" + , sample_dur - cmd->u4ChIdle + , cmd->u4ChIdle, sample_dur); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n\tmy_tx_time: %u us" + , cmd->u4TxAirTime); + if (cmd->u4FetchEd - cmd->u4FetchSt) { + persentage = cmd->u4TxAirTime / (sample_dur / 1000); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + ", tx utility: %d.%1d%%" + , persentage / 10 + , persentage % 10); + } + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n\tmy_data_rx_time (no BMC data): %u us" + , cmd->u4RxAirTime); + if (cmd->u4FetchEd - cmd->u4FetchSt) { + persentage = cmd->u4RxAirTime / (sample_dur / 1000); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + ", rx utility: %d.%1d%%" + , persentage / 10 + , persentage % 10); + } + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n\tTotal packet transmitted: %u", cmd->u4PktSent); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n\tTotal tx ok packet: %u", cmd->u4PktSent - cmd->u4PktTxfailed); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n\tTotal tx failed packet: %u", cmd->u4PktTxfailed); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n\tTotal tx retried packet: %u", cmd->u4PktRetried); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n\tTotal rx mpdu: %u", cmd->u4RxMPDU); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n\tTotal rx fcs: %u", cmd->u4RxFcs); + } else + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\ncommand sent %x", rStatus); + + if (cmd) + kalMemFree(cmd, VIR_MEM_TYPE, sizeof(*cmd)); + + return i4BytesWritten; +get_report_invalid: + if (cmd) + kalMemFree(cmd, VIR_MEM_TYPE, sizeof(*cmd)); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\nformat:get_report [enable|disable|get|reset]"); + return i4BytesWritten; +} + + +static int priv_driver_pta_config(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo; + INT_32 i4BytesWritten = 0; + UINT_32 u4BufLen = 0; + INT_32 i4Argc = 0; + UINT_32 u4Val = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + P_CMD_PTA_CONFIG_T cmd = NULL; + INT_32 u4Ret = 0; + INT_32 i = 0; + + DBGLOG(REQ, LOUD, "%s(%s)>\n", __func__, pcCommand); + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + if (i4Argc < 2) + goto set_pta_invalid; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + if (!prGlueInfo) + goto set_pta_invalid; + + cmd = (P_CMD_PTA_CONFIG_T)kalMemAlloc(sizeof(*cmd), VIR_MEM_TYPE); + if (!cmd) + goto set_pta_invalid; + + memset(cmd, 0, sizeof(*cmd)); + cmd->u2Type = CMD_PTA_CONFIG_TYPE; + cmd->u2Len = sizeof(*cmd); + /* set command + parameter must be even number */ + if ((strnicmp(apcArgv[1], "SET", strlen("SET")) == 0) && (i4Argc >= 4) && !(i4Argc & 1)) { + cmd->u2Type |= CMD_ADV_CONTROL_SET; + for (i = 2; i < i4Argc; i += 2) { + u4Ret = kalkStrtou32(apcArgv[i+1], 0, &u4Val); + if (u4Ret) { + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\nparsing err(%d) %s %s", u4Ret, apcArgv[i], apcArgv[i+1]); + goto set_pta_invalid; + } + + DBGLOG(REQ, LOUD, "arg[%d] %s %s (0x%x)\n", i, apcArgv[i], apcArgv[i+1], u4Val); + if (strnicmp(apcArgv[i], "ENABLE", strlen("ENABLE")) == 0) { + cmd->u4ConfigMask |= CMD_PTA_CONFIG_PTA; + if (u4Val) + cmd->u4PtaConfig |= CMD_PTA_CONFIG_PTA_EN; + } else if (strnicmp(apcArgv[i], "TXDATA", strlen("TXDATA")) == 0) { + cmd->u4ConfigMask |= CMD_PTA_CONFIG_TXDATA_TAG; + cmd->u4TxDataTag = u4Val; + } else if (strnicmp(apcArgv[i], "RXDATAACK", strlen("RXDATAACK")) == 0) { + cmd->u4ConfigMask |= CMD_PTA_CONFIG_RXDATAACK_TAG; + cmd->u4RxDataAckTag = u4Val; + } else if (strnicmp(apcArgv[i], "RXDATA", strlen("RXDATA")) == 0) { + cmd->u4ConfigMask |= CMD_PTA_CONFIG_RX_NSW_TAG; + cmd->u4RxNswTag = u4Val; + } else if (strnicmp(apcArgv[i], "TXACK", strlen("TXACK")) == 0) { + cmd->u4ConfigMask |= CMD_PTA_CONFIG_TXACK_TAG; + cmd->u4TxAckTag = u4Val; + } else if (strnicmp(apcArgv[i], "PROTTAG", strlen("PROTTAG")) == 0) { + cmd->u4ConfigMask |= CMD_PTA_CONFIG_TXPROTFRAME_TAG; + cmd->u4ConfigMask |= CMD_PTA_CONFIG_RXPROTFRAMEACK_TAG; + cmd->u4TxProtFrameTag = u4Val; + cmd->u4RxProtFrameAckTag = u4Val; + } else if (strnicmp(apcArgv[i], "TXBMC", strlen("TXBMC")) == 0) { + cmd->u4ConfigMask |= CMD_PTA_CONFIG_TX_BMC_TAG; + cmd->u4TxBMCTag = u4Val; + } else if (strnicmp(apcArgv[i], "TXBCN", strlen("TXBCN")) == 0) { + cmd->u4ConfigMask |= CMD_PTA_CONFIG_TX_BCN_TAG; + cmd->u4TxBCNTag = u4Val; + } else if (strnicmp(apcArgv[i], "RXBCN", strlen("RXBCN")) == 0) { + cmd->u4ConfigMask |= CMD_PTA_CONFIG_RX_SP_TAG; + cmd->u4RxSPTag = u4Val; + } else if (strnicmp(apcArgv[i], "TXMGMT", strlen("TXMGMT")) == 0) { + cmd->u4ConfigMask |= CMD_PTA_CONFIG_TX_MGMT_TAG; + cmd->u4TxMgmtTag = u4Val; + } else if (strnicmp(apcArgv[i], "RXMGMTACK", strlen("RXMGMTACK")) == 0) { + cmd->u4ConfigMask |= CMD_PTA_CONFIG_RXMGMTACK_TAG; + cmd->u4RxMgmtAckTag = u4Val; + } else if (strnicmp(apcArgv[i], "STATENABLE", strlen("STATENABLE")) == 0) { + cmd->u4ConfigMask |= CMD_PTA_CONFIG_PTA_STAT; + if (!u4Val) + cmd->u4PtaConfig &= ~CMD_PTA_CONFIG_PTA_STAT_EN; + else + cmd->u4PtaConfig |= CMD_PTA_CONFIG_PTA_STAT_EN; + } else if (strnicmp(apcArgv[i], "STATRESET", strlen("STATRESET")) == 0) + cmd->u4ConfigMask |= CMD_PTA_CONFIG_PTA_STAT_RESET; + else { + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\nunknown parameter %s %s", apcArgv[i], apcArgv[i+1]); + goto set_pta_invalid; + } + } + + rStatus = wlanSendSetQueryCmd(prGlueInfo->prAdapter, + CMD_ID_ADV_CONTROL, + TRUE, + FALSE, + FALSE, + NULL, NULL, sizeof(*cmd), (PUINT_8) cmd, NULL, 0); + } else if (strnicmp(apcArgv[1], "GET", strlen("GET")) == 0) { + rStatus = kalIoctl(prGlueInfo, wlanoidAdvCtrl, cmd, sizeof(*cmd), TRUE, TRUE, TRUE, &u4BufLen); + } else + goto set_pta_invalid; + + if ((rStatus != WLAN_STATUS_SUCCESS) && (rStatus != WLAN_STATUS_PENDING)) + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\ncommand failed %x", rStatus); + else if (!(cmd->u2Type & CMD_ADV_CONTROL_SET)) { + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\nCoex mode: %s", (cmd->u4CoexMode) ? "FDD" : "TDD"); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\nPTA status:"); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n module enable %x wifi %x bt %x wifi arb %x" + , (cmd->u4PtaConfig>>EVENT_CONFIG_PTA_OFFSET)&EVENT_CONFIG_PTA_FEILD + , (cmd->u4PtaConfig>>EVENT_CONFIG_PTA_WIFI_OFFSET)&EVENT_CONFIG_PTA_WIFI_FEILD + , (cmd->u4PtaConfig>>EVENT_CONFIG_PTA_BT_OFFSET)&EVENT_CONFIG_PTA_BT_FEILD + , (cmd->u4PtaConfig>>EVENT_CONFIG_PTA_ARB_OFFSET)&EVENT_CONFIG_PTA_ARB_FEILD); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\nPriority stat:"); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n txData %d", cmd->u4TxDataTag); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n rxDataAck %d", cmd->u4RxDataAckTag); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n rxData %d", cmd->u4RxNswTag); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n txAck %d", cmd->u4TxAckTag); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n txBmc %d", cmd->u4TxBMCTag); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n txBcn %d", cmd->u4TxBCNTag); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n txMgmt %d", cmd->u4TxMgmtTag); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n rxMgmtAck %d", cmd->u4RxMgmtAckTag); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n rxBcn %d", cmd->u4RxSPTag); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n prottag %d", cmd->u4TxProtFrameTag); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\nLast fetched grant stat:"); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n wifi grant %x txreq %x rxreq %x pritag %x" + , (cmd->u4GrantStat>>EVENT_CONFIG_WIFI_GRANT_OFFSET)&EVENT_CONFIG_WIFI_GRANT_FEILD + , (cmd->u4GrantStat>>EVENT_CONFIG_WIFI_TXREQ_OFFSET)&EVENT_CONFIG_WIFI_TXREQ_FEILD + , (cmd->u4GrantStat>>EVENT_CONFIG_WIFI_RXREQ_OFFSET)&EVENT_CONFIG_WIFI_RXREQ_FEILD + , (cmd->u4GrantStat>>EVENT_CONFIG_WIFI_PRI_OFFSET)&EVENT_CONFIG_WIFI_PRI_FEILD); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n bt grant %x txreq %x rxreq %x pritag %x" + , (cmd->u4GrantStat>>EVENT_CONFIG_BT_GRANT_OFFSET)&EVENT_CONFIG_BT_GRANT_FEILD + , (cmd->u4GrantStat>>EVENT_CONFIG_BT_TXREQ_OFFSET)&EVENT_CONFIG_BT_TXREQ_FEILD + , (cmd->u4GrantStat>>EVENT_CONFIG_BT_RXREQ_OFFSET)&EVENT_CONFIG_BT_RXREQ_FEILD + , (cmd->u4GrantStat>>EVENT_CONFIG_BT_PRI_OFFSET)&EVENT_CONFIG_BT_PRI_FEILD); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\nPTA stat:"); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n wf0 txreq_cnt %d txgrant_cnt %d txabort_cnt %d" + , (cmd->u4PtaWF0TxCnt>>EVENT_PTA_WFTRX_CNT_OFFSET)&EVENT_PTA_WFTRX_CNT_FEILD + , (cmd->u4PtaWF0TxCnt>>EVENT_PTA_WFTRX_GRANT_CNT_OFFSET)&EVENT_PTA_WFTRX_GRANT_CNT_FEILD + , (cmd->u4PtaWF0AbtCnt>>EVENT_PTA_TX_ABT_CNT_OFFSET)&EVENT_PTA_TX_ABT_CNT_FEILD); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n wf0 rxreq_cnt %d rxgrant_cnt %d rxabort_cnt %d" + , (cmd->u4PtaWF0RxCnt>>EVENT_PTA_WFTRX_CNT_OFFSET)&EVENT_PTA_WFTRX_CNT_FEILD + , (cmd->u4PtaWF0RxCnt>>EVENT_PTA_WFTRX_GRANT_CNT_OFFSET)&EVENT_PTA_WFTRX_GRANT_CNT_FEILD + , (cmd->u4PtaWF0AbtCnt>>EVENT_PTA_RX_ABT_CNT_OFFSET)&EVENT_PTA_RX_ABT_CNT_FEILD); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n wf1 txreq_cnt %d txgrant_cnt %d txabort_cnt %d" + , (cmd->u4PtaWF1TxCnt>>EVENT_PTA_WFTRX_CNT_OFFSET)&EVENT_PTA_WFTRX_CNT_FEILD + , (cmd->u4PtaWF1TxCnt>>EVENT_PTA_WFTRX_GRANT_CNT_OFFSET)&EVENT_PTA_WFTRX_GRANT_CNT_FEILD + , (cmd->u4PtaWF1AbtCnt>>EVENT_PTA_TX_ABT_CNT_OFFSET)&EVENT_PTA_TX_ABT_CNT_FEILD); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n wf1 rxreq_cnt %d rxgrant_cnt %d rxabort_cnt %d" + , (cmd->u4PtaWF1RxCnt>>EVENT_PTA_WFTRX_CNT_OFFSET)&EVENT_PTA_WFTRX_CNT_FEILD + , (cmd->u4PtaWF1RxCnt>>EVENT_PTA_WFTRX_GRANT_CNT_OFFSET)&EVENT_PTA_WFTRX_GRANT_CNT_FEILD + , (cmd->u4PtaWF1AbtCnt>>EVENT_PTA_RX_ABT_CNT_OFFSET)&EVENT_PTA_RX_ABT_CNT_FEILD); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n bt txreq_cnt %d txgrant_cnt %d txabort_cnt %d" + , (cmd->u4PtaBTTxCnt>>EVENT_PTA_BTTRX_CNT_OFFSET)&EVENT_PTA_BTTRX_CNT_FEILD + , (cmd->u4PtaBTTxCnt>>EVENT_PTA_BTTRX_GRANT_CNT_OFFSET)&EVENT_PTA_BTTRX_GRANT_CNT_FEILD + , (cmd->u4PtaBTAbtCnt>>EVENT_PTA_TX_ABT_CNT_OFFSET)&EVENT_PTA_TX_ABT_CNT_FEILD); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n bt rxreq_cnt %d rxgrant_cnt %d rxabort_cnt %d" + , (cmd->u4PtaBTRxCnt>>EVENT_PTA_BTTRX_CNT_OFFSET)&EVENT_PTA_BTTRX_CNT_FEILD + , (cmd->u4PtaBTRxCnt>>EVENT_PTA_BTTRX_GRANT_CNT_OFFSET)&EVENT_PTA_BTTRX_GRANT_CNT_FEILD + , (cmd->u4PtaBTAbtCnt>>EVENT_PTA_RX_ABT_CNT_OFFSET)&EVENT_PTA_RX_ABT_CNT_FEILD); + } else + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\ncommand sent %x", rStatus); + + if (cmd) + kalMemFree(cmd, VIR_MEM_TYPE, sizeof(*cmd)); + + return i4BytesWritten; +set_pta_invalid: + if (cmd) + kalMemFree(cmd, VIR_MEM_TYPE, sizeof(*cmd)); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\nformat:pta_config set [enable 1|0][txdata val][rxdataack val]"); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n\t[rxdata val][txack val][txbmc val][txbcn val][rxbcn val]"); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n\t[txmgmt val][rxmgmtack val][prottag val]"); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n\t[statenable 1|0][statreset 1]"); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n [enable val]: enable PTA(1) or not(0)"); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n [txtag val<0~15>]: priority tag for tx ac0-ac3"); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n [rxdataack val<0~15>]: priority tag for rx ac0-ac3 ack"); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n [rxdata val<0~15>]: priority tag for rx data"); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n [txack val<0~15>]: priority tag for tx ack"); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n [txbmc val<0~15>]: priority tag for tx bmc packet"); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n [txbcn val<0~15>]: priority tag for tx beacon"); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n [rxbcn val<0~15>]: priority tag for rx beacon"); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n [prottag val<0~15>]: priority tag for Protection frame"); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\nformat(%d):pta_config get", i4Argc); + return i4BytesWritten; +} + +static int priv_driver_set_pop(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + INT_32 u4Ret = 0; + UINT_32 u4Id = CMD_SW_DBGCTL_ADVCTL_SET_ID + CMD_ADVCTL_POP_ID; + UINT_32 u4Sel = 0, u4CckTh = 0, u4OfdmTh = 0; + PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + rSwCtrlInfo.u4Id = u4Id; + + if (i4Argc <= 3) { + DBGLOG(REQ, ERROR, "Argc(%d) ERR: SET_POP \n", i4Argc); + return -1; + } + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Sel); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + u4Ret = kalkStrtou32(apcArgv[2], 0, &u4CckTh); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + u4Ret = kalkStrtou32(apcArgv[3], 0, &u4OfdmTh); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + + rSwCtrlInfo.u4Data = (u4CckTh | (u4OfdmTh<<8) | (u4Sel<<30)); + DBGLOG(REQ, LOUD, "u4Sel=%d u4CckTh=%d u4OfdmTh=%d, u4Data=0x%x,\n", + u4Sel, u4CckTh, u4OfdmTh, rSwCtrlInfo.u4Data); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + return i4BytesWritten; + +} + +static int priv_driver_get_pop(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + UINT_32 u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + CMD_ADVCTL_POP_ID; + UINT_32 u4Offset = 0; + PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo; + UINT_32 u4CckTh = 0, u4OfdmTh = 0; + + ASSERT(prNetDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = u4Id; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + u4CckTh = rSwCtrlInfo.u4Data & 0xFF; + u4OfdmTh = (rSwCtrlInfo.u4Data >> 8) & 0xFF; + + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "PoP: CckTh:%ddB OfdmTh:%ddB\n", u4CckTh, u4OfdmTh); + + i4BytesWritten = (INT_32)u4Offset; + + return i4BytesWritten; + +} + +static int priv_driver_set_ed(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + INT_32 u4Ret = 0, u4EdVal = 0; + UINT_32 u4Id = CMD_SW_DBGCTL_ADVCTL_SET_ID + CMD_ADVCTL_ED_ID; + UINT_32 u4Sel = 0; + PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + rSwCtrlInfo.u4Id = u4Id; + + if (i4Argc <= 2) { + DBGLOG(REQ, ERROR, "Argc(%d) ERR: SET_ED \n", i4Argc); + return -1; + } + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Sel); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + u4Ret = kalkStrtos32(apcArgv[2], 0, &u4EdVal); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + + rSwCtrlInfo.u4Data = ((u4EdVal & 0xFF) | (u4Sel << 31)); + DBGLOG(REQ, LOUD, "u4Sel=%d u4EdCcaVal=%d, u4Data=0x%x,\n", + u4Sel, u4EdVal, rSwCtrlInfo.u4Data); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + return i4BytesWritten; + +} + +static int priv_driver_get_ed(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + UINT_32 u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + CMD_ADVCTL_ED_ID; + UINT_32 u4Offset = 0; + PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo; + INT_8 u4EdVal = 0; + + ASSERT(prNetDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = u4Id; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + u4EdVal = rSwCtrlInfo.u4Data & 0xFF; + + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "ED: %ddB\n", u4EdVal); + + i4BytesWritten = (INT_32)u4Offset; + + return i4BytesWritten; + +} + +static int priv_driver_set_pd(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + INT_32 u4Ret = 0; + UINT_32 u4Id = CMD_SW_DBGCTL_ADVCTL_SET_ID + CMD_ADVCTL_PD_ID; + UINT_32 u4Sel = 0; + INT_32 u4CckTh = 0, u4OfdmTh = 0; + PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + rSwCtrlInfo.u4Id = u4Id; + + if (i4Argc <= 1) { + DBGLOG(REQ, ERROR, "Argc(%d) ERR: SET_PD [CCK TH] [OFDM TH]\n", i4Argc); + return -1; + } + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Sel); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + + if (u4Sel == 1) { + if (i4Argc <= 3) { + DBGLOG(REQ, ERROR, "Argc(%d) ERR: SET_PD 1 \n", i4Argc); + return -1; + } + u4Ret = kalkStrtos32(apcArgv[2], 0, &u4CckTh); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + u4Ret = kalkStrtos32(apcArgv[3], 0, &u4OfdmTh); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + } + + rSwCtrlInfo.u4Data = ((u4OfdmTh & 0xFFFF) | ((u4CckTh & 0xFF) << 16) | (u4Sel << 30)); + DBGLOG(REQ, LOUD, "u4Sel=%d u4OfdmTh=%d, u4CckTh=%d, u4Data=0x%x,\n", + u4Sel, u4OfdmTh, u4CckTh, rSwCtrlInfo.u4Data); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + return i4BytesWritten; +} + +static int priv_driver_get_pd(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + UINT_32 u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + CMD_ADVCTL_PD_ID; + UINT_32 u4Offset = 0; + PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo; + INT_8 u4CckTh = 0, u4OfdmTh = 0; + + ASSERT(prNetDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = u4Id; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + u4CckTh = rSwCtrlInfo.u4Data & 0xFF; + u4OfdmTh = (rSwCtrlInfo.u4Data >> 8) & 0xFF; + + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "PD: CckTh:%ddB OfdmTh:%ddB\n", u4CckTh, u4OfdmTh); + + i4BytesWritten = (INT_32)u4Offset; + + return i4BytesWritten; +} + +static int priv_cmd_not_support(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + DBGLOG(REQ, WARN, "not support priv command: %s\n", pcCommand); + + return -EOPNOTSUPP; +} + +static int priv_driver_set_maxrfgain(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + INT_32 u4Ret = 0; + UINT_32 u4Id = CMD_SW_DBGCTL_ADVCTL_SET_ID + CMD_ADVCTL_MAX_RFGAIN_ID; + UINT_32 u4Sel = 0; + INT_32 u4Wf0Gain = 0, u4Wf1Gain = 0; + PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + rSwCtrlInfo.u4Id = u4Id; + + if (i4Argc <= 1) { + DBGLOG(REQ, ERROR, "Argc(%d) ERR: SET_RFGAIN \n", i4Argc); + return -1; + } + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Sel); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + + if (u4Sel == 1) { + if (i4Argc <= 3) { + DBGLOG(REQ, ERROR, "Argc(%d) ERR: SET_RFGAIN 1 \n", i4Argc); + return -1; + } + u4Ret = kalkStrtos32(apcArgv[2], 0, &u4Wf0Gain); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + u4Ret = kalkStrtos32(apcArgv[3], 0, &u4Wf1Gain); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error u4Ret=%d\n", u4Ret); + } + + rSwCtrlInfo.u4Data = ((u4Wf0Gain & 0xFF) | ((u4Wf1Gain & 0xFF) << 8) | (u4Sel << 31)); + DBGLOG(REQ, LOUD, "u4Sel=%d u4Wf0Gain=%d, u4Wf1Gain=%d, u4Data=0x%x,\n", + u4Sel, u4Wf0Gain, u4Wf1Gain, rSwCtrlInfo.u4Data); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + return i4BytesWritten; +} + +static int priv_driver_get_maxrfgain(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + UINT_32 u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + CMD_ADVCTL_MAX_RFGAIN_ID; + UINT_32 u4Offset = 0; + PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo; + UINT_8 u4Wf0Gain = 0, u4Wf1Gain = 0; + + ASSERT(prNetDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = u4Id; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + u4Wf0Gain = rSwCtrlInfo.u4Data & 0xFF; + u4Wf1Gain = (rSwCtrlInfo.u4Data >> 8) & 0xFF; + + u4Offset += snprintf(pcCommand + u4Offset, i4TotalLen - u4Offset, + "Max RFGain: WF0:%ddB WF1:%ddB\n", u4Wf0Gain, u4Wf1Gain); + + i4BytesWritten = (INT_32)u4Offset; + + return i4BytesWritten; + +} + +static int priv_driver_noise_histogram(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo; + INT_32 i4BytesWritten = 0; + UINT_32 u4BufLen = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + struct CMD_NOISE_HISTOGRAM_REPORT *cmd = NULL; + + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + if (!prGlueInfo) + goto noise_histogram_invalid; + + cmd = (struct CMD_NOISE_HISTOGRAM_REPORT *)kalMemAlloc(sizeof(*cmd), VIR_MEM_TYPE); + if (!cmd) + goto noise_histogram_invalid; + + if ((i4Argc > 4) || (i4Argc < 2)) + goto noise_histogram_invalid; + + memset(cmd, 0, sizeof(*cmd)); + + cmd->u2Type = CMD_NOISE_HISTOGRAM_TYPE; + cmd->u2Len = sizeof(*cmd); + + if (strnicmp(apcArgv[1], "ENABLE", strlen("ENABLE")) == 0) { + prGlueInfo->prAdapter->u4IsKeepFullPwrBitmap |= KEEP_FULL_PWR_NOISE_HISTOGRAM_BIT; + cmd->ucAction = CMD_NOISE_HISTOGRAM_ENABLE; + cmd->u2Type |= CMD_ADV_CONTROL_SET; + } else if (strnicmp(apcArgv[1], "DISABLE", strlen("DISABLE")) == 0) { + prGlueInfo->prAdapter->u4IsKeepFullPwrBitmap &= ~KEEP_FULL_PWR_NOISE_HISTOGRAM_BIT; + cmd->ucAction = CMD_NOISE_HISTOGRAM_DISABLE; + cmd->u2Type |= CMD_ADV_CONTROL_SET; + } else if (strnicmp(apcArgv[1], "RESET", strlen("RESET")) == 0) { + cmd->ucAction = CMD_NOISE_HISTOGRAM_RESET; + cmd->u2Type |= CMD_ADV_CONTROL_SET; + } else if (strnicmp(apcArgv[1], "GET", strlen("GET")) == 0) { + cmd->ucAction = CMD_NOISE_HISTOGRAM_GET; + } else + goto noise_histogram_invalid; + + DBGLOG(REQ, LOUD, "%s(%s) action %x\n" + , __func__, pcCommand, cmd->ucAction); + + rStatus = kalIoctl(prGlueInfo, wlanoidAdvCtrl, cmd, sizeof(*cmd), TRUE, TRUE, TRUE, &u4BufLen); + + if ((rStatus != WLAN_STATUS_SUCCESS) && (rStatus != WLAN_STATUS_PENDING)) + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\ncommand failed %x", rStatus); + else if (cmd->ucAction == CMD_NOISE_HISTOGRAM_GET) { + + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n Power > -55: %10d" + , cmd->u4IPI10); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n-55 >= Power > -60: %10d" + , cmd->u4IPI9); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n-60 >= Power > -65: %10d" + , cmd->u4IPI8); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n-65 >= Power > -70: %10d" + , cmd->u4IPI7); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n-70 >= Power > -75: %10d" + , cmd->u4IPI6); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n-75 >= Power > -80: %10d" + , cmd->u4IPI5); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n-80 >= Power > -83: %10d" + , cmd->u4IPI4); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n-83 >= Power > -86: %10d" + , cmd->u4IPI3); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n-86 >= Power > -89: %10d" + , cmd->u4IPI2); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n-89 >= Power > -92: %10d" + , cmd->u4IPI1); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\n-92 >= Power : %10d" + , cmd->u4IPI0); + + } else + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\ncommand sent %x", rStatus); + + if (cmd) + kalMemFree(cmd, VIR_MEM_TYPE, sizeof(*cmd)); + + return i4BytesWritten; +noise_histogram_invalid: + if (cmd) + kalMemFree(cmd, VIR_MEM_TYPE, sizeof(*cmd)); + i4BytesWritten += snprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\nformat:get_report [enable|disable|get|reset]"); + return i4BytesWritten; +} + +static int priv_driver_set_adm_ctrl(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + INT_32 u4Ret = 0; + UINT_32 u4Id = CMD_SW_DBGCTL_ADVCTL_SET_ID + CMD_ADVCTL_ADM_CTRL_ID; + UINT_32 u4Enable = 0, u4TimeRatio = 100, u4AdmBase = 0; + PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo; + + ASSERT(prNetDev); + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + rSwCtrlInfo.u4Id = u4Id; + + if ((i4Argc > 4) || (i4Argc < 2)) { + DBGLOG(REQ, ERROR, "Argc(%d) ERR: set_admission_ctrl\n", i4Argc); + return -1; + } + + u4Ret = kalkStrtou32(apcArgv[1], 0, &u4Enable); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse u4Enable error u4Ret=%d\n", u4Ret); + + if (i4Argc > 2) { + /* u4AdmTime default is 100% */ + u4Ret = kalkStrtos32(apcArgv[2], 0, &u4TimeRatio); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse u4AdmTime error u4Ret=%d\n", u4Ret); + } + + if (i4Argc > 3) { + u4Ret = kalkStrtos32(apcArgv[3], 0, &u4AdmBase); + if (u4Ret) + DBGLOG(REQ, ERROR, "parse u4AdmBase error u4Ret=%d\n", u4Ret); + } + + rSwCtrlInfo.u4Data = ((u4AdmBase & 0xFFFF) | ((u4TimeRatio & 0xFF) << 16) | + ((u4Enable & 0xFF) << 24)); + DBGLOG(REQ, LOUD, "u4Enable=%d u4AdmTime=%d, u4AdmBase=%d, u4Data=0x%x,\n", + u4Enable, u4TimeRatio, u4AdmBase, rSwCtrlInfo.u4Data); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + return i4BytesWritten; +} + +static int priv_driver_set_bcn_th(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + INT_32 i4Ret = 0; + UINT_32 u4Id = CMD_SW_DBGCTL_ADVCTL_SET_ID + CMD_ADVCTL_BCN_TH_ID; + UINT_8 ucAdhoc, ucInfra, ucWithbt; + PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo; + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + rSwCtrlInfo.u4Id = u4Id; + + if (i4Argc != 4) { + i4BytesWritten += scnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\nformat:set_bcn_th "); + return i4BytesWritten; + } + + i4Ret = kalkStrtou8(apcArgv[1], 0, &ucAdhoc); + if (i4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error i4Ret=%d\n", i4Ret); + i4Ret = kalkStrtou8(apcArgv[2], 0, &ucInfra); + if (i4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error i4Ret=%d\n", i4Ret); + i4Ret = kalkStrtou8(apcArgv[3], 0, &ucWithbt); + if (i4Ret) + DBGLOG(REQ, ERROR, "parse rSwCtrlInfo error i4Ret=%d\n", i4Ret); + + rSwCtrlInfo.u4Data = (ucAdhoc | (ucInfra << 8) | (ucWithbt << 16)); + DBGLOG(REQ, LOUD, "u4Withbt=%d u4Infra=%d, u4Withbt=%d u4Data=0x%x,\n", + ucAdhoc, ucInfra, ucWithbt, rSwCtrlInfo.u4Data); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetSwCtrlWrite, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "ERR: kalIoctl fail (%d)\n", rStatus); + return -1; + } + + return i4BytesWritten; +} + +static int priv_driver_get_bcn_th(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + UINT_32 u4Id = CMD_SW_DBGCTL_ADVCTL_GET_ID + CMD_ADVCTL_BCN_TH_ID; + UINT_8 ucAdhoc, ucInfra, ucWithbt; + PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo; + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc != 1) { + i4BytesWritten += scnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\nformat:get_bcn_th"); + return i4BytesWritten; + } + + rSwCtrlInfo.u4Data = 0; + rSwCtrlInfo.u4Id = u4Id; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySwCtrlRead, + &rSwCtrlInfo, sizeof(rSwCtrlInfo), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + return -1; + + ucAdhoc = rSwCtrlInfo.u4Data & 0xFF; + ucInfra = (rSwCtrlInfo.u4Data >> 8) & 0xFF; + ucWithbt = (rSwCtrlInfo.u4Data >> 16) & 0xFF; + + i4BytesWritten += scnprintf(pcCommand + i4BytesWritten, i4TotalLen - i4BytesWritten, + "\nBeacon loss threshold: ADHOC:%d, INFRA:%d, With BT:%d\n", + ucAdhoc, ucInfra, ucWithbt); + + return i4BytesWritten; +} +#endif + +#if CFG_SUPPORT_CSI +static int priv_driver_set_csi(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + struct CMD_CSI_CONTROL_T *prCSICtrl = NULL; + UINT_32 u4Ret = 0; + struct CSI_INFO_T *prCSIInfo = NULL; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(RSN, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + DBGLOG(RSN, INFO, "priv_driver_csi_control\n"); + + prCSIInfo = &(prGlueInfo->prAdapter->rCSIInfo); + + prCSICtrl = (struct CMD_CSI_CONTROL_T *)kalMemAlloc(sizeof(struct CMD_CSI_CONTROL_T), VIR_MEM_TYPE); + if (!prCSICtrl) { + DBGLOG(REQ, ERROR, "allocate memory for prCSICtrl failed\n"); + i4BytesWritten = -1; + goto out; + } + + if (i4Argc < 2 || i4Argc > 5) { + DBGLOG(REQ, ERROR, "argc %i is invalid\n", i4Argc); + i4BytesWritten = -1; + goto out; + } + + u4Ret = kalkStrtou8(apcArgv[1], 0, &(prCSICtrl->ucMode)); + if (u4Ret) { + DBGLOG(REQ, LOUD, "parse ucMode error u4Ret=%d\n", u4Ret); + goto out; + } + + if (prCSICtrl->ucMode >= CSI_CONTROL_MODE_NUM) { + DBGLOG(REQ, LOUD, "Invalid ucMode %d, should be 0 or 1\n", + prCSICtrl->ucMode); + goto out; + } + + prCSIInfo->ucMode = prCSICtrl->ucMode; + + if (prCSICtrl->ucMode == CSI_CONTROL_MODE_STOP || + prCSICtrl->ucMode == CSI_CONTROL_MODE_START) { + prCSIInfo->bIncomplete = FALSE; + prCSIInfo->u4CopiedDataSize = 0; + prCSIInfo->u4RemainingDataSize = 0; + prCSIInfo->u4CSIBufferHead = 0; + prCSIInfo->u4CSIBufferTail = 0; + prCSIInfo->u4CSIBufferUsed = 0; + goto send_cmd; + } + + u4Ret = kalkStrtou8(apcArgv[2], 0, &(prCSICtrl->ucCfgItem)); + if (u4Ret) { + DBGLOG(REQ, LOUD, "parse cfg item error u4Ret=%d\n", u4Ret); + goto out; + } + + if (prCSICtrl->ucCfgItem >= CSI_CONFIG_ITEM_NUM) { + DBGLOG(REQ, LOUD, "Invalid csi cfg_item %u\n", + prCSICtrl->ucCfgItem); + goto out; + } + + u4Ret = kalkStrtou8(apcArgv[3], 0, &(prCSICtrl->ucValue1)); + if (u4Ret) { + DBGLOG(REQ, LOUD, + "parse csi cfg value1 error u4Ret=%d\n", u4Ret); + goto out; + } + prCSIInfo->ucValue1[prCSICtrl->ucCfgItem] = prCSICtrl->ucValue1; + + if (i4Argc == 5) { + u4Ret = kalkStrtou8(apcArgv[4], 0, &(prCSICtrl->ucValue2)); + if (u4Ret) { + DBGLOG(REQ, LOUD, + "parse csi cfg value2 error u4Ret=%d\n", u4Ret); + goto out; + } + prCSIInfo->ucValue2[prCSICtrl->ucCfgItem] = prCSICtrl->ucValue2; + } + +send_cmd: + rStatus = kalIoctl(prGlueInfo, wlanoidSetCSIControl, prCSICtrl, + sizeof(struct CMD_CSI_CONTROL_T), TRUE, TRUE, TRUE, &u4BufLen); + + DBGLOG(REQ, INFO, "%s: command result is %s\n", __func__, pcCommand); + DBGLOG(REQ, INFO, + "mode %d, csi cfg item %d, value1 %d, value2 %d", + prCSICtrl->ucMode, prCSICtrl->ucCfgItem, + prCSICtrl->ucValue1, prCSICtrl->ucValue2); + DBGLOG(REQ, LOUD, "rStatus %u\n", rStatus); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "send CSI control cmd failed\n"); + i4BytesWritten = -1; + } + +out: + if (prCSICtrl) + kalMemFree(prCSICtrl, VIR_MEM_TYPE, sizeof(struct CMD_CSI_CONTROL_T)); + + return i4BytesWritten; +} +#endif + +int priv_driver_get_bsstable(IN struct net_device *prNetDev, IN char *pcCommand, + IN int i4TotalLen) +{ + UINT_32 i4BytesWritten = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc; + P_ADAPTER_T prAdapter = NULL; + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "\nBSSID, rssi0, rssi1\n------\n"); + + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + LOGBUF(pcCommand, i4TotalLen, i4BytesWritten, + "%02x:%02x:%02x:%02x:%02x:%02x, %d, %d\n", + prBssDesc->aucBSSID[0], prBssDesc->aucBSSID[1], + prBssDesc->aucBSSID[2], prBssDesc->aucBSSID[3], + prBssDesc->aucBSSID[4], prBssDesc->aucBSSID[5], + RCPI_TO_dBm(prBssDesc->ucRCPI), + RCPI_TO_dBm(prBssDesc->ucRCPI1)); + } + + return i4BytesWritten; +} + +INT_32 priv_driver_cmds(IN struct net_device *prNetDev, IN PCHAR pcCommand, IN INT_32 i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4BytesWritten = 0; + + if (g_u4HaltFlag) { + DBGLOG(REQ, WARN, "wlan is halt, skip priv_driver_cmds\n"); + return -1; + } + + if (GLUE_CHK_PR2(prNetDev, pcCommand) == FALSE) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (strnicmp(pcCommand, CMD_RSSI, strlen(CMD_RSSI)) == 0) { + /* i4BytesWritten = + * wl_android_get_rssi(net, command, i4TotalLen); + */ + } else if (strnicmp(pcCommand, CMD_AP_START, strlen(CMD_AP_START)) == 0) { + i4BytesWritten = priv_driver_set_ap_start(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_LINKSPEED, strlen(CMD_LINKSPEED)) == 0) { + i4BytesWritten = priv_driver_get_linkspeed(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_PNOSSIDCLR_SET, strlen(CMD_PNOSSIDCLR_SET)) == 0) { + /* ToDo:: Nothing */ + } else if (strnicmp(pcCommand, CMD_PNOSETUP_SET, strlen(CMD_PNOSETUP_SET)) == 0) { + /* ToDo:: Nothing */ + } else if (strnicmp(pcCommand, CMD_PNOENABLE_SET, strlen(CMD_PNOENABLE_SET)) == 0) { + /* ToDo:: Nothing */ + } else if (strnicmp(pcCommand, CMD_SETSUSPENDOPT, strlen(CMD_SETSUSPENDOPT)) == 0) { + /* i4BytesWritten = wl_android_set_suspendopt(net, pcCommand, i4TotalLen); */ + } else if (strnicmp(pcCommand, CMD_SETSUSPENDMODE, strlen(CMD_SETSUSPENDMODE)) == 0) { + i4BytesWritten = priv_driver_set_suspend_mode(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) { + i4BytesWritten = priv_driver_set_band(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GETBAND, strlen(CMD_GETBAND)) == 0) { + /* i4BytesWritten = wl_android_get_band(net, pcCommand, i4TotalLen); */ + } else if (strnicmp(pcCommand, CMD_SET_TXPOWER, strlen(CMD_SET_TXPOWER)) == 0) { + i4BytesWritten = priv_driver_set_txpower(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_COUNTRY, strlen(CMD_COUNTRY)) == 0) { + i4BytesWritten = priv_driver_set_country(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_COUNTRY, strlen(CMD_GET_COUNTRY)) == 0) { + i4BytesWritten = priv_driver_get_country(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_CHANNELS, strlen(CMD_GET_CHANNELS)) == 0) { + i4BytesWritten = priv_driver_get_channels(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_MIRACAST, strlen(CMD_MIRACAST)) == 0) { + i4BytesWritten = priv_driver_set_miracast(prNetDev, pcCommand, i4TotalLen); + } + /* Mediatek private command */ + else if (strnicmp(pcCommand, CMD_SET_SW_CTRL, strlen(CMD_SET_SW_CTRL)) == 0) { + i4BytesWritten = priv_driver_set_sw_ctrl(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_FIXED_RATE, strlen(CMD_SET_FIXED_RATE)) == 0) { + i4BytesWritten = priv_driver_set_fixed_rate(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_SW_CTRL, strlen(CMD_GET_SW_CTRL)) == 0) { + i4BytesWritten = priv_driver_get_sw_ctrl(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_MCR, strlen(CMD_SET_MCR)) == 0) { + i4BytesWritten = priv_driver_set_mcr(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_MCR, strlen(CMD_GET_MCR)) == 0) { + i4BytesWritten = priv_driver_get_mcr(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_DRV_MCR, strlen(CMD_SET_DRV_MCR)) == 0) { + i4BytesWritten = priv_driver_set_drv_mcr(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_DRV_MCR, strlen(CMD_GET_DRV_MCR)) == 0) { + i4BytesWritten = priv_driver_get_drv_mcr(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_TEST_MODE, strlen(CMD_SET_TEST_MODE)) == 0) { + i4BytesWritten = priv_driver_set_test_mode(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_TEST_CMD, strlen(CMD_SET_TEST_CMD)) == 0) { + i4BytesWritten = priv_driver_set_test_cmd(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_TEST_RESULT, strlen(CMD_GET_TEST_RESULT)) == 0) { + i4BytesWritten = priv_driver_get_test_result(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_STA_STAT2, strlen(CMD_GET_STA_STAT2)) == 0) { + i4BytesWritten = priv_driver_get_sta_stat2(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_STA_STAT, strlen(CMD_GET_STA_STAT)) == 0) { + i4BytesWritten = priv_driver_get_sta_stat(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_CURR_AR_RATE, strlen(CMD_GET_CURR_AR_RATE)) == 0) { + i4BytesWritten = priv_driver_get_sta_curr_ar_rate(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_STA_RX_STAT, strlen(CMD_GET_STA_RX_STAT)) == 0) { + i4BytesWritten = priv_driver_show_rx_stat(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_ACL_POLICY, strlen(CMD_SET_ACL_POLICY)) == 0) { + i4BytesWritten = priv_driver_set_acl_policy(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_ADD_ACL_ENTRY, strlen(CMD_ADD_ACL_ENTRY)) == 0) { + i4BytesWritten = priv_driver_add_acl_entry(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_DEL_ACL_ENTRY, strlen(CMD_DEL_ACL_ENTRY)) == 0) { + i4BytesWritten = priv_driver_del_acl_entry(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SHOW_ACL_ENTRY, strlen(CMD_SHOW_ACL_ENTRY)) == 0) { + i4BytesWritten = priv_driver_show_acl_entry(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_CLEAR_ACL_ENTRY, strlen(CMD_CLEAR_ACL_ENTRY)) == 0) { + i4BytesWritten = priv_driver_clear_acl_entry(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_COEX_CONTROL, strlen(CMD_COEX_CONTROL)) == 0) { + i4BytesWritten = priv_driver_coex_ctrl(prNetDev, pcCommand, i4TotalLen); + } +#if CFG_SUPPORT_CSI + else if (strnicmp(pcCommand, + CMD_SET_CSI, strlen(CMD_SET_CSI)) == 0) { + i4BytesWritten = priv_driver_set_csi(prNetDev, pcCommand, i4TotalLen); + } +#endif +#if (CFG_SUPPORT_DFS_MASTER == 1) + else if (strnicmp(pcCommand, CMD_SHOW_DFS_STATE, strlen(CMD_SHOW_DFS_STATE)) == 0) { + i4BytesWritten = priv_driver_show_dfs_state(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SHOW_DFS_RADAR_PARAM, strlen(CMD_SHOW_DFS_RADAR_PARAM)) == 0) { + i4BytesWritten = priv_driver_show_dfs_radar_param(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SHOW_DFS_HELP, strlen(CMD_SHOW_DFS_HELP)) == 0) { + i4BytesWritten = priv_driver_show_dfs_help(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SHOW_DFS_CAC_TIME, strlen(CMD_SHOW_DFS_CAC_TIME)) == 0) { + i4BytesWritten = priv_driver_show_dfs_cac_time(prNetDev, pcCommand, i4TotalLen); + } +#endif +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST + else if (strnicmp(pcCommand, + CMD_SET_CALBACKUP_TEST_DRV_FW, strlen(CMD_SET_CALBACKUP_TEST_DRV_FW)) == 0) + i4BytesWritten = priv_driver_set_calbackup_test_drv_fw(prNetDev, pcCommand, i4TotalLen); +#endif +#if CFG_WOW_SUPPORT + else if (strnicmp(pcCommand, CMD_WOW_START, strlen(CMD_WOW_START)) == 0) + i4BytesWritten = priv_driver_set_wow(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_WOW_ENABLE, strlen(CMD_SET_WOW_ENABLE)) == 0) + i4BytesWritten = priv_driver_set_wow_enable(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_WOW_PAR, strlen(CMD_SET_WOW_PAR)) == 0) + i4BytesWritten = priv_driver_set_wow_par(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_WOW_UDP, strlen(CMD_SET_WOW_UDP)) == 0) + i4BytesWritten = priv_driver_set_wow_udpport(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_WOW_TCP, strlen(CMD_SET_WOW_TCP)) == 0) + i4BytesWritten = priv_driver_set_wow_tcpport(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_WOW_PORT, strlen(CMD_GET_WOW_PORT)) == 0) + i4BytesWritten = priv_driver_get_wow_port(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_WOW_REASON, strlen(CMD_GET_WOW_REASON)) == 0) + i4BytesWritten = priv_driver_get_wow_reason(prNetDev, pcCommand, i4TotalLen); +#endif + else if (strnicmp(pcCommand, CMD_SET_ADV_PWS, strlen(CMD_SET_ADV_PWS)) == 0) + i4BytesWritten = priv_driver_set_adv_pws(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_MDTIM, strlen(CMD_SET_MDTIM)) == 0) + i4BytesWritten = priv_driver_set_mdtim(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_LISTEN_DTIM_INTERVAL, strlen(CMD_SET_LISTEN_DTIM_INTERVAL)) == 0) + i4BytesWritten = priv_driver_set_listen_dtim_interval(prNetDev, pcCommand, i4TotalLen); +#if CFG_SUPPORT_QA_TOOL + else if (strnicmp(pcCommand, CMD_GET_RX_STATISTICS, strlen(CMD_GET_RX_STATISTICS)) == 0) + i4BytesWritten = priv_driver_get_rx_statistics(prNetDev, pcCommand, i4TotalLen); +#if CFG_SUPPORT_BUFFER_MODE + else if (strnicmp(pcCommand, CMD_SETBUFMODE, strlen(CMD_SETBUFMODE)) == 0) + i4BytesWritten = priv_driver_set_efuse_buffer_mode(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SETEEPROM_MODE, strlen(CMD_SETEEPROM_MODE)) == 0) + i4BytesWritten = priv_driver_set_eeprom_mode(prNetDev, pcCommand, i4TotalLen); +#endif +#endif +#if CFG_SUPPORT_MSP +#if 0 + else if (strnicmp(pcCommand, CMD_GET_STAT, strlen(CMD_GET_STAT)) == 0) + i4BytesWritten = priv_driver_get_stat(prNetDev, pcCommand, i4TotalLen); +#endif + else if (strnicmp(pcCommand, CMD_GET_STA_STATISTICS, strlen(CMD_GET_STA_STATISTICS)) == 0) + i4BytesWritten = priv_driver_get_sta_statistics(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_BSS_STATISTICS, strlen(CMD_GET_BSS_STATISTICS)) == 0) + i4BytesWritten = priv_driver_get_bss_statistics(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_STA_INFO, strlen(CMD_GET_STA_INFO)) == 0) + i4BytesWritten = priv_driver_get_sta_info(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_WTBL_INFO, strlen(CMD_GET_WTBL_INFO)) == 0) + i4BytesWritten = priv_driver_get_wtbl_info(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_MIB_INFO, strlen(CMD_GET_MIB_INFO)) == 0) + i4BytesWritten = priv_driver_get_mib_info(prNetDev, pcCommand, i4TotalLen); +#if CFG_SUPPORT_LAST_SEC_MCS_INFO + else if (strnicmp(pcCommand, CMD_GET_MCS_INFO, strlen(CMD_GET_MCS_INFO)) == 0) + i4BytesWritten = priv_driver_get_mcs_info(prNetDev, pcCommand, i4TotalLen); +#endif + else if (strnicmp(pcCommand, CMD_SET_FW_LOG, strlen(CMD_SET_FW_LOG)) == 0) + i4BytesWritten = priv_driver_set_fw_log(prNetDev, pcCommand, i4TotalLen); +#endif + else if (strnicmp(pcCommand, CMD_SET_CFG, strlen(CMD_SET_CFG)) == 0) { + i4BytesWritten = priv_driver_set_cfg(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_CFG, strlen(CMD_GET_CFG)) == 0) { + i4BytesWritten = priv_driver_get_cfg(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_CHIP, strlen(CMD_SET_CHIP)) == 0) { + i4BytesWritten = priv_driver_set_chip_config(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_CHIP, strlen(CMD_GET_CHIP)) == 0) { + i4BytesWritten = priv_driver_get_chip_config(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_VERSION, strlen(CMD_GET_VERSION)) == 0) { + i4BytesWritten = priv_driver_get_version(prNetDev, pcCommand, i4TotalLen); +#if CFG_SUPPORT_DBDC + + } else if (strnicmp(pcCommand, CMD_SET_DBDC, strlen(CMD_SET_DBDC)) == 0) { + i4BytesWritten = priv_driver_set_dbdc(prNetDev, pcCommand, i4TotalLen); +#endif /*CFG_SUPPORT_DBDC*/ +#if CFG_SUPPORT_BATCH_SCAN + } else if (strnicmp(pcCommand, CMD_BATCH_SET, strlen(CMD_BATCH_SET)) == 0) { + kalIoctl(prGlueInfo, + wlanoidSetBatchScanReq, + (PVOID) pcCommand, i4TotalLen, FALSE, FALSE, TRUE, &i4BytesWritten); + } else if (strnicmp(pcCommand, CMD_BATCH_GET, strlen(CMD_BATCH_GET)) == 0) { + /* strcpy(pcCommand, "BATCH SCAN DATA FROM FIRMWARE"); */ + /* i4BytesWritten = strlen("BATCH SCAN DATA FROM FIRMWARE") + 1; */ + /* i4BytesWritten = priv_driver_get_linkspeed (prNetDev, pcCommand, i4TotalLen); */ + + UINT_32 u4BufLen; + int i; + /* int rlen=0; */ + + for (i = 0; i < CFG_BATCH_MAX_MSCAN; i++) { + g_rEventBatchResult[i].ucScanCount = i + 1; /* for get which mscan */ + kalIoctl(prGlueInfo, + wlanoidQueryBatchScanResult, + (PVOID)&g_rEventBatchResult[i], + sizeof(EVENT_BATCH_RESULT_T), TRUE, TRUE, TRUE, &u4BufLen); + } + +#if 0 + DBGLOG(SCN, INFO, "Batch Scan Results, scan count = %u\n", g_rEventBatchResult.ucScanCount); + for (i = 0; i < g_rEventBatchResult.ucScanCount; i++) { + prEntry = &g_rEventBatchResult.arBatchResult[i]; + DBGLOG(SCN, INFO, "Entry %u\n", i); + DBGLOG(SCN, INFO, " BSSID = " MACSTR "\n", MAC2STR(prEntry->aucBssid)); + DBGLOG(SCN, INFO, " SSID = %s\n", prEntry->aucSSID); + DBGLOG(SCN, INFO, " SSID len = %u\n", prEntry->ucSSIDLen); + DBGLOG(SCN, INFO, " RSSI = %d\n", prEntry->cRssi); + DBGLOG(SCN, INFO, " Freq = %u\n", prEntry->ucFreq); + } +#endif + + batchConvertResult(&g_rEventBatchResult[0], pcCommand, i4TotalLen, &i4BytesWritten); + + /* Dump for debug */ + /* print_hex_dump(KERN_INFO, + * "BATCH", DUMP_PREFIX_ADDRESS, 16, 1, pcCommand, i4BytesWritten, TRUE); + */ + + } else if (strnicmp(pcCommand, CMD_BATCH_STOP, strlen(CMD_BATCH_STOP)) == 0) { + kalIoctl(prGlueInfo, + wlanoidSetBatchScanReq, + (PVOID) pcCommand, i4TotalLen, FALSE, FALSE, TRUE, &i4BytesWritten); +#endif + } +#if CFG_SUPPORT_SNIFFER + else if (strnicmp(pcCommand, CMD_SETMONITOR, strlen(CMD_SETMONITOR)) == 0) + i4BytesWritten = priv_driver_set_monitor(prNetDev, pcCommand, i4TotalLen); +#endif + else if (strnicmp(pcCommand, CMD_GET_QUE_INFO, strlen(CMD_GET_QUE_INFO)) == 0) + i4BytesWritten = priv_driver_get_que_info(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_MEM_INFO, strlen(CMD_GET_MEM_INFO)) == 0) + i4BytesWritten = priv_driver_get_mem_info(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_HIF_INFO, strlen(CMD_GET_HIF_INFO)) == 0) + i4BytesWritten = priv_driver_get_hif_info(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_P2P_PS, strlen(CMD_SET_P2P_PS)) == 0) + i4BytesWritten = priv_driver_set_p2p_ps(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_CNM_INFO, strlen(CMD_GET_CNM_INFO)) == 0) + i4BytesWritten = priv_driver_get_cnm_info(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_DSLP_CNT, strlen(CMD_GET_DSLP_CNT)) == 0) + i4BytesWritten = priv_driver_get_deep_sleep_cnt(prNetDev, pcCommand, i4TotalLen); +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + else if (strnicmp(pcCommand, CMD_GET_CH_RANK_LIST, strlen(CMD_GET_CH_RANK_LIST)) == 0) + i4BytesWritten = priv_driver_get_ch_rank_list(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_CH_DIRTINESS, strlen(CMD_GET_CH_DIRTINESS)) == 0) + i4BytesWritten = priv_driver_get_ch_dirtiness(prNetDev, pcCommand, i4TotalLen); +#endif + else if (strnicmp(pcCommand, CMD_EFUSE, sizeof(CMD_EFUSE)-1) == 0) + i4BytesWritten = priv_driver_efuse_ops(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_CCCR, strlen(CMD_CCCR)) == 0) + i4BytesWritten = priv_driver_cccr_ops(prNetDev, + pcCommand, + i4TotalLen); +#if CFG_SUPPORT_ADVANCE_CONTROL + else if (strnicmp(pcCommand, CMD_SET_NOISE, strlen(CMD_SET_NOISE)) == 0) + i4BytesWritten = priv_driver_set_noise(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_NOISE, strlen(CMD_GET_NOISE)) == 0) + i4BytesWritten = priv_driver_get_noise(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_PTA_CONFIG, strlen(CMD_PTA_CONFIG)) == 0) + i4BytesWritten = priv_driver_pta_config(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_TRAFFIC_REPORT, strlen(CMD_TRAFFIC_REPORT)) == 0) + i4BytesWritten = priv_driver_get_traffic_report(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_POP, strlen(CMD_SET_POP)) == 0) + i4BytesWritten = priv_driver_set_pop(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_POP, strlen(CMD_GET_POP)) == 0) + i4BytesWritten = priv_driver_get_pop(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_ED, strlen(CMD_SET_ED)) == 0) + i4BytesWritten = priv_driver_set_ed(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_ED, strlen(CMD_GET_ED)) == 0) + i4BytesWritten = priv_driver_get_ed(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_PD, strlen(CMD_SET_PD)) == 0) + i4BytesWritten = priv_driver_set_pd(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_PD, strlen(CMD_GET_PD)) == 0) + i4BytesWritten = priv_driver_get_pd(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_MAX_RFGAIN, strlen(CMD_SET_MAX_RFGAIN)) == 0) + i4BytesWritten = priv_driver_set_maxrfgain(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_MAX_RFGAIN, strlen(CMD_GET_MAX_RFGAIN)) == 0) + i4BytesWritten = priv_driver_get_maxrfgain(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_NOISE_HISTOGRAM, strlen(CMD_NOISE_HISTOGRAM)) == 0) + i4BytesWritten = priv_driver_noise_histogram(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_ADM_CTRL, strlen(CMD_SET_ADM_CTRL)) == 0) + i4BytesWritten = priv_driver_set_adm_ctrl(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_SET_BCN_TH, strlen(CMD_SET_BCN_TH)) == 0) + i4BytesWritten = priv_driver_set_bcn_th(prNetDev, pcCommand, i4TotalLen); + else if (strnicmp(pcCommand, CMD_GET_BCN_TH, strlen(CMD_GET_BCN_TH)) == 0) + i4BytesWritten = priv_driver_get_bcn_th(prNetDev, pcCommand, i4TotalLen); +#endif + else if (strnicmp(pcCommand, CMD_GET_BSS_TABLE, + strlen(CMD_GET_BSS_TABLE)) == 0) + i4BytesWritten = priv_driver_get_bsstable(prNetDev, + pcCommand, i4TotalLen); + else + i4BytesWritten = priv_cmd_not_support(prNetDev, pcCommand, i4TotalLen); + + if (i4BytesWritten >= 0) { + if ((i4BytesWritten == 0) && (i4TotalLen > 0)) { + /* reset the command buffer */ + pcCommand[0] = '\0'; + } + + if (i4BytesWritten >= i4TotalLen) { + DBGLOG(REQ, INFO, + "%s: i4BytesWritten %d > i4TotalLen < %d\n", __func__, i4BytesWritten, i4TotalLen); + i4BytesWritten = i4TotalLen; + } else { + pcCommand[i4BytesWritten] = '\0'; + i4BytesWritten++; + } + } + + return i4BytesWritten; + +} /* priv_driver_cmds */ + +int priv_support_driver_cmd(IN struct net_device *prNetDev, IN OUT struct ifreq *prReq, IN int i4Cmd) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + int ret = 0; + char *pcCommand = NULL; + priv_driver_cmd_t *priv_cmd = NULL; + int i4BytesWritten = 0; + int i4TotalLen = 0; + struct iwreq *wrqin = (struct iwreq *) prReq; + struct iw_point iwp; +#ifdef CONFIG_COMPAT + struct compat_iw_point *iwp_compat = NULL; +#endif + iwp.pointer = wrqin->u.data.pointer; + iwp.length = wrqin->u.data.length; + iwp.flags = wrqin->u.data.flags; + +#ifdef CONFIG_COMPAT +#if KERNEL_VERSION(4, 6, 0) <= LINUX_VERSION_CODE + if (in_compat_syscall()) { +#else + if (is_compat_task()) { +#endif + iwp_compat = (struct compat_iw_point *) &wrqin->u.data; + iwp.pointer = compat_ptr(iwp_compat->pointer); + iwp.length = iwp_compat->length; + iwp.flags = iwp_compat->flags; + } +#endif + + if (!prReq->ifr_data) { + ret = -EINVAL; + goto exit; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + if (!prGlueInfo) { + DBGLOG(REQ, WARN, "No glue info\n"); + ret = -EFAULT; + goto exit; + } + if (prGlueInfo->u4ReadyFlag == 0) { + ret = -EINVAL; + goto exit; + } + + priv_cmd = kzalloc(sizeof(priv_driver_cmd_t), GFP_KERNEL); + if (!priv_cmd) { + DBGLOG(REQ, WARN, "%s, alloc mem failed\n", __func__); + return -ENOMEM; + } + + if (iwp.length > PRIV_CMD_SIZE) + iwp.length = PRIV_CMD_SIZE; + + if (copy_from_user(priv_cmd->buf, iwp.pointer, iwp.length)) { + DBGLOG(REQ, ERROR, "%s: copy_from_user fail with len [%d]\n", + __func__, iwp.length); + ret = -EFAULT; + goto exit; + } + + priv_cmd->total_len = iwp.length; + + i4TotalLen = priv_cmd->total_len; + + if (i4TotalLen <= 0) { + ret = -EINVAL; + DBGLOG(REQ, ERROR, "%s: Invalid Len %x %x %s\n", __func__, + i4TotalLen, priv_cmd->used_len, priv_cmd->buf); + goto exit; + } + + pcCommand = priv_cmd->buf; + + DBGLOG(REQ, STATE, "%s: driver cmd \"%s\" on %s\n", + __func__, pcCommand, prReq->ifr_name); + + i4BytesWritten = priv_driver_cmds(prNetDev, pcCommand, PRIV_CMD_SIZE); + + if (i4BytesWritten < 0) { + DBGLOG(REQ, ERROR, "%s: command %s Written is %d\n", + __func__, pcCommand, i4BytesWritten); + if (i4TotalLen >= 3) { + snprintf(pcCommand, 3, "OK"); + i4BytesWritten = strlen("OK"); + } else { + ret = -EFAULT; + goto exit; + } + } + + if (copy_to_user(iwp.pointer, priv_cmd->buf, i4BytesWritten)) { + DBGLOG(REQ, ERROR, "%s: copy_to_user fail with Len : %d\n", + __func__, i4BytesWritten); + ret = -EFAULT; + goto exit; + } + + if (i4BytesWritten > PRIV_CMD_SIZE) + i4BytesWritten = PRIV_CMD_SIZE; + + wrqin->u.data.length = i4BytesWritten; +#ifdef CONFIG_COMPAT +#if KERNEL_VERSION(4, 6, 0) <= CFG80211_VERSION_CODE + if (in_compat_syscall()) { +#else + if (is_compat_task()) { +#endif + iwp_compat->pointer = ptr_to_compat(iwp.pointer); + iwp_compat->length = i4BytesWritten; + } +#endif + +exit: + kfree(priv_cmd); + + return ret; +} /* priv_support_driver_cmd */ + +int priv_support_mdns_offload(IN struct net_device *prNetDev, + IN OUT struct ifreq *prReq, IN int i4Cmd) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + struct MDNS_PARAM_T *prMdnsParam = NULL; + + int ret = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (!prReq->ifr_data) { + DBGLOG(REQ, ERROR, "%s: prReq->ifr_data is NULL.\n", __func__); + return -EINVAL; + } + + prMdnsParam = kzalloc(sizeof(struct MDNS_PARAM_T), GFP_KERNEL); + if (!prMdnsParam) { + DBGLOG(REQ, WARN, "%s, alloc mem failed\n", __func__); + return -ENOMEM; + } + + if (copy_from_user(prMdnsParam, + prReq->ifr_data, sizeof(struct MDNS_PARAM_T))) { + DBGLOG(REQ, ERROR, "%s: copy_from_user fail\n", __func__); + ret = -EFAULT; + goto exit; + } + + kalMdnsProcess(prGlueInfo, prMdnsParam); + +exit: + kfree(prMdnsParam); + return ret; + +} + +#ifdef CFG_ANDROID_AOSP_PRIV_CMD +int android_private_support_driver_cmd(IN struct net_device *prNetDev, + IN OUT struct ifreq *prReq, IN int i4Cmd) +{ + struct android_wifi_priv_cmd priv_cmd; + char *command = NULL; + int ret = 0, bytes_written = 0; +#ifdef CONFIG_COMPAT + struct compat_android_wifi_priv_cmd compat_priv_cmd; +#endif + + if (!prReq->ifr_data) + return -EINVAL; + +#ifdef CONFIG_COMPAT + if (mtk_is_compat_task()) { + /* User space is 32-bit, use compat ioctl */ + if (copy_from_user(&compat_priv_cmd, prReq->ifr_data, + sizeof(compat_priv_cmd))) { + return -EFAULT; + } + priv_cmd.buf = compat_ptr(compat_priv_cmd.buf); + priv_cmd.used_len = compat_priv_cmd.used_len; + priv_cmd.total_len = compat_priv_cmd.total_len; + } else +#endif + if (copy_from_user(&priv_cmd, prReq->ifr_data, sizeof(priv_cmd))) + return -EFAULT; + + if (priv_cmd.total_len <= 0) + return -EINVAL; + + command = kzalloc(priv_cmd.total_len, GFP_KERNEL); + if (!command) { + DBGLOG(REQ, WARN, "%s, alloc mem failed\n", __func__); + return -ENOMEM; + } + + if (copy_from_user(command, priv_cmd.buf, priv_cmd.total_len)) { + ret = -EFAULT; + goto FREE; + } + + bytes_written = priv_driver_cmds(prNetDev, command, priv_cmd.total_len); + + if (bytes_written == -EOPNOTSUPP) { + /* Report positive status */ + INT_32 i4BytesWritten = 0; + + i4BytesWritten += kalSnprintf(command + i4BytesWritten, + priv_cmd.total_len - i4BytesWritten, + "%s", "NotSupport"); + bytes_written = i4BytesWritten; + } + + if (bytes_written >= 0) { + /* priv_cmd in but no response */ + if ((bytes_written == 0) && (priv_cmd.total_len > 0)) + command[0] = '\0'; + + if (bytes_written >= priv_cmd.total_len) + bytes_written = priv_cmd.total_len; + else + bytes_written++; + + priv_cmd.used_len = bytes_written; + + if (copy_to_user(priv_cmd.buf, command, bytes_written)) + ret = -EFAULT; + } else + ret = bytes_written; + +FREE: + kfree(command); + + return ret; +} +#endif /* CFG_ANDROID_AOSP_PRIV_CMD */ + +#ifdef CFG_ALPS_ANDROID_AOSP_PRIV_CMD +int alps_android_private_support_driver_cmd(IN struct net_device *prNetDev, + IN OUT struct ifreq *prReq, IN int i4Cmd) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + int ret = 0; + char *pcCommand = NULL; + struct android_wifi_priv_cmd *priv_cmd = NULL; + int i4BytesWritten = 0; + int i4TotalLen = 0; + + if (!prReq->ifr_data) { + ret = -EINVAL; + goto exit; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (!prGlueInfo) { + DBGLOG(REQ, WARN, "No glue info\n"); + ret = -EFAULT; + goto exit; + } + if (prGlueInfo->u4ReadyFlag == 0) { + ret = -EINVAL; + goto exit; + } + + priv_cmd = kzalloc(sizeof(struct android_wifi_priv_cmd), GFP_KERNEL); + if (!priv_cmd) { + DBGLOG(REQ, WARN, "%s, alloc mem failed\n", __func__); + return -ENOMEM; + } + + if (copy_from_user(priv_cmd, prReq->ifr_data, sizeof(struct + android_wifi_priv_cmd))) { + DBGLOG(REQ, INFO, "%s: copy_from_user fail\n", __func__); + ret = -EFAULT; + goto exit; + } + + i4TotalLen = priv_cmd->total_len; + if (i4TotalLen <= 0) { + ret = -EINVAL; + DBGLOG(REQ, INFO, "%s: i4TotalLen invalid\n", __func__); + goto exit; + } + + pcCommand = priv_cmd->buf; + + DBGLOG(REQ, INFO, "%s: driver cmd \"%s\" on %s\n", + __func__, pcCommand, prReq->ifr_name); + + i4BytesWritten = priv_driver_cmds(prNetDev, pcCommand, i4TotalLen); + + if (i4BytesWritten < 0) { + DBGLOG(REQ, INFO, "%s: command %s failed; Written is %d\n", + __func__, pcCommand, i4BytesWritten); + ret = -EFAULT; + } + +exit: + kfree(priv_cmd); + + return ret; + +} +#endif /* CFG_ALPS_ANDROID_AOSP_PRIV_CMD */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/ehpi/arm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/ehpi/arm.c new file mode 100644 index 0000000000000..f7c3524b3d96a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/ehpi/arm.c @@ -0,0 +1,534 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/ehpi/arm.c#1 +*/ + +/*! \file "colibri.c" +* \brief Brief description. +* +* Detail description. +*/ + + +/****************************************************************************** +* C O M P I L E R F L A G S +******************************************************************************* +*/ +#if !defined(MCR_EHTCR) +#define MCR_EHTCR 0x0054 +#endif + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "colibri.h" +#include "wlan_lib.h" + +/******************************************************************************* +* 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 void __iomem *mt5931_mcr_base; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#if CFG_EHPI_FASTER_BUS_TIMING +#define EHPI_CONFIG MSC_CS(4, MSC_RBUFF_SLOW | \ + MSC_RRR(4) | \ + MSC_RDN(8) | \ + MSC_RDF(7) | \ + MSC_RBW_16 | \ + MSC_RT_VLIO) +#else +#define EHPI_CONFIG MSC_CS(4, MSC_RBUFF_SLOW | \ + MSC_RRR(7) | \ + MSC_RDN(13) | \ + MSC_RDF(12) | \ + MSC_RBW_16 | \ + MSC_RT_VLIO) +#endif /* CFG_EHPI_FASTER_BUS_TIMING */ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static VOID collibri_ehpi_reg_init(VOID); + +static VOID collibri_ehpi_reg_uninit(VOID); + +static VOID mt5931_ehpi_reg_init(VOID); + +static VOID mt5931_ehpi_reg_uninit(VOID); + +static void busSetIrq(void); + +static void busFreeIrq(void); + +static irqreturn_t glEhpiInterruptHandler(int irq, void *dev_id); + +#if DBG +static void initTrig(void); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will register sdio bus to the os +* +* \param[in] pfProbe Function pointer to detect card +* \param[in] pfRemove Function pointer to remove card +* +* \return The result of registering sdio bus +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS glRegisterBus(probe_card pfProbe, remove_card pfRemove) +{ + + ASSERT(pfProbe); + ASSERT(pfRemove); + + pr_info("mtk_sdio: MediaTek eHPI WLAN driver\n"); + pr_info("mtk_sdio: Copyright MediaTek Inc.\n"); + + if (pfProbe(NULL) != WLAN_STATUS_SUCCESS) { + pfRemove(); + return WLAN_STATUS_FAILURE; + } + + return WLAN_STATUS_SUCCESS; +} /* 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(); + + /* TODO: eHPI uninitialization */ +} /* 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, ULONG ulCookie) +{ + P_GL_HIF_INFO_T prHif = NULL; + + ASSERT(prGlueInfo); + + prHif = &prGlueInfo->rHifInfo; + + /* fill some buffered information into prHif */ + prHif->mcr_addr_base = mt5931_mcr_base + EHPI_OFFSET_ADDR; + prHif->mcr_data_base = mt5931_mcr_base + EHPI_OFFSET_DATA; +} /* 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; + + /* do something */ + prHif->mcr_addr_base = 0; + prHif->mcr_data_base = 0; +} /* 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 DBG + initTrig(); +#endif + + /* 1. initialize eHPI control registers */ + collibri_ehpi_reg_init(); + + /* 2. memory remapping for MT5931 */ + mt5931_ehpi_reg_init(); + + return TRUE; +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus operation and release resources. +* +* \param[in] pvData A pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glBusRelease(PVOID pvData) +{ + /* 1. memory unmapping for MT5931 */ + mt5931_ehpi_reg_uninit(); + + /* 2. uninitialize eHPI control registers */ + collibri_ehpi_reg_uninit(); +} /* 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) +{ + struct net_device *pDev = (struct net_device *)pvData; + int i4Status = 0; + + /* 1. enable GPIO pin as IRQ */ + busSetIrq(); + + /* 2. Specify IRQ number into net_device */ + pDev->irq = WLAN_STA_IRQ; + + /* 3. register ISR callback */ + + i4Status = request_irq(pDev->irq, + glEhpiInterruptHandler, + IRQF_DISABLED | IRQF_SHARED | IRQF_TRIGGER_FALLING, pDev->name, pvCookie); + + if (i4Status < 0) + pr_debug("request_irq(%d) failed\n", pDev->irq); + else + pr_info("request_irq(%d) success with dev_id(%x)\n", pDev->irq, (unsigned int)pvCookie); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus interrupt operation and disable interrupt handling for os. +* +* \param[in] pvData A pointer to struct net_device. +* \param[in] pvCookie Private data for pfnIsr function. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glBusFreeIrq(PVOID pvData, PVOID pvCookie) +{ + struct net_device *prDev = (struct net_device *)pvData; + + if (!prDev) { + pr_info("Invalid net_device context.\n"); + return; + } + + if (prDev->irq) { + disable_irq(prDev->irq); + free_irq(prDev->irq, pvCookie); + prDev->irq = 0; + } + + busFreeIrq(); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set power state +* +* \param[in] pvGlueInfo A pointer to GLUE_INFO_T +* \param[in] ePowerMode Power Mode Setting +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glSetPowerState(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 ePowerMode) +{ +} + +#if DBG +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setup the GPIO pin. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void setTrig(void) +{ + GPSR1 = (0x1UL << 8); +} /* end of setTrig() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Clear the GPIO pin. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void clearTrig(void) +{ + GPCR1 = (0x1UL << 8); +} /* end of clearTrig() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set a specified GPIO pin to H or L. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static void initTrig(void) +{ + set_GPIO_mode(GPIO40_FFDTR | GPIO_OUT); + clearTrig(); +} /* end of initTrig() */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function congifure platform-dependent interrupt triger type. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void busSetIrq(void) +{ +#if defined(WLAN_STA_IRQ_GPIO) + pxa_gpio_mode(WLAN_STA_IRQ_GPIO | GPIO_IN); + set_irq_type(WLAN_STA_IRQ, IRQT_FALLING); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function should restore settings changed by busSetIrq(). +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void busFreeIrq(void) +{ +#if defined(WLAN_STA_IRQ_GPIO) + pxa_gpio_mode(WLAN_STA_IRQ_GPIO | GPIO_OUT); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function configures colibri memory controller registers +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static VOID collibri_ehpi_reg_init(VOID) +{ + UINT_32 u4RegValue; + + /* 1. enable nCS as memory controller */ + pxa_gpio_mode(GPIO80_nCS_4_MD); + + /* 2. nCS<4> configuration */ + u4RegValue = MSC2; + u4RegValue &= ~MSC_CS(4, 0xFFFF); + u4RegValue |= EHPI_CONFIG; + MSC2 = u4RegValue; + + pr_info("EHPI new MSC2:0x%08x\n", MSC2); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function restores colibri memory controller registers +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static VOID collibri_ehpi_reg_uninit(VOID) +{ + UINT_32 u4RegValue; + + /* 1. restore nCS<4> configuration */ + u4RegValue = MSC2; + u4RegValue &= ~MSC_CS(4, 0xFFFF); + MSC2 = u4RegValue; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function configures MT5931 mapped registers on colibri +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static VOID mt5931_ehpi_reg_init(VOID) +{ + struct resource *reso = NULL; + + /* 1. request memory regioin */ + reso = request_mem_region((unsigned long)MEM_MAPPED_ADDR, (unsigned long)MEM_MAPPED_LEN, (char *)MODULE_PREFIX); + if (!reso) { + pr_err("request_mem_region(0x%08X) failed.\n", MEM_MAPPED_ADDR); + return; + } + + /* 2. memory regioin remapping */ + mt5931_mcr_base = ioremap_nocache(MEM_MAPPED_ADDR, MEM_MAPPED_LEN); + if (!(mt5931_mcr_base)) { + release_mem_region(MEM_MAPPED_ADDR, MEM_MAPPED_LEN); + pr_err("ioremap_nocache(0x%08X) failed.\n", MEM_MAPPED_ADDR); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function releases MT5931 mapped registers on colibri +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static VOID mt5931_ehpi_reg_uninit(VOID) +{ + iounmap(mt5931_mcr_base); + mt5931_mcr_base = NULL; + + release_mem_region(MEM_MAPPED_ADDR, MEM_MAPPED_LEN); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Callback for interrupt coming from device +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static irqreturn_t glEhpiInterruptHandler(int irq, void *dev_id) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) dev_id; + + ASSERT(prGlueInfo); + + if (!prGlueInfo) + return IRQ_HANDLED; + + /* 1. Running for ISR */ + wlanISR(prGlueInfo->prAdapter, TRUE); + + /* 1.1 Halt flag Checking */ + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) + return IRQ_HANDLED; + + /* 2. Flag marking for interrupt */ + set_bit(GLUE_FLAG_INT_BIT, &prGlueInfo->ulFlag); + + /* 3. wake up tx service thread */ + wake_up_interruptible(&prGlueInfo->waitq); + + return IRQ_HANDLED; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/ehpi/colibri.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/ehpi/colibri.c new file mode 100644 index 0000000000000..6929b961fdd50 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/ehpi/colibri.c @@ -0,0 +1,534 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/ehpi/colibri.c#1 +*/ + +/*! \file "colibri.c" +* \brief Brief description. +* +* Detail description. +*/ + + +/****************************************************************************** +* C O M P I L E R F L A G S +******************************************************************************* +*/ +#if !defined(MCR_EHTCR) +#define MCR_EHTCR 0x0054 +#endif + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "colibri.h" +#include "wlan_lib.h" + +/******************************************************************************* +* 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 void __iomem *mt5931_mcr_base; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#if CFG_EHPI_FASTER_BUS_TIMING +#define EHPI_CONFIG MSC_CS(4, MSC_RBUFF_SLOW | \ + MSC_RRR(4) | \ + MSC_RDN(8) | \ + MSC_RDF(7) | \ + MSC_RBW_16 | \ + MSC_RT_VLIO) +#else +#define EHPI_CONFIG MSC_CS(4, MSC_RBUFF_SLOW | \ + MSC_RRR(7) | \ + MSC_RDN(13) | \ + MSC_RDF(12) | \ + MSC_RBW_16 | \ + MSC_RT_VLIO) +#endif /* CFG_EHPI_FASTER_BUS_TIMING */ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static VOID collibri_ehpi_reg_init(VOID); + +static VOID collibri_ehpi_reg_uninit(VOID); + +static VOID mt5931_ehpi_reg_init(VOID); + +static VOID mt5931_ehpi_reg_uninit(VOID); + +static void busSetIrq(void); + +static void busFreeIrq(void); + +static irqreturn_t glEhpiInterruptHandler(int irq, void *dev_id); + +#if DBG +static void initTrig(void); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will register sdio bus to the os +* +* \param[in] pfProbe Function pointer to detect card +* \param[in] pfRemove Function pointer to remove card +* +* \return The result of registering sdio bus +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS glRegisterBus(probe_card pfProbe, remove_card pfRemove) +{ + + ASSERT(pfProbe); + ASSERT(pfRemove); + + pr_info("mtk_sdio: MediaTek eHPI WLAN driver\n"); + pr_info("mtk_sdio: Copyright MediaTek Inc.\n"); + + if (pfProbe(NULL) != WLAN_STATUS_SUCCESS) { + pfRemove(); + return WLAN_STATUS_FAILURE; + } + + return WLAN_STATUS_SUCCESS; +} /* 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(); + + /* TODO: eHPI uninitialization */ +} /* 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, ULONG ulCookie) +{ + P_GL_HIF_INFO_T prHif = NULL; + + ASSERT(prGlueInfo); + + prHif = &prGlueInfo->rHifInfo; + + /* fill some buffered information into prHif */ + prHif->mcr_addr_base = mt5931_mcr_base + EHPI_OFFSET_ADDR; + prHif->mcr_data_base = mt5931_mcr_base + EHPI_OFFSET_DATA; +} /* 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; + + /* do something */ + prHif->mcr_addr_base = 0; + prHif->mcr_data_base = 0; +} /* 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 DBG + initTrig(); +#endif + + /* 1. initialize eHPI control registers */ + collibri_ehpi_reg_init(); + + /* 2. memory remapping for MT5931 */ + mt5931_ehpi_reg_init(); + + return TRUE; +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus operation and release resources. +* +* \param[in] pvData A pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glBusRelease(PVOID pvData) +{ + /* 1. memory unmapping for MT5931 */ + mt5931_ehpi_reg_uninit(); + + /* 2. uninitialize eHPI control registers */ + collibri_ehpi_reg_uninit(); +} /* 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) +{ + struct net_device *pDev = (struct net_device *)pvData; + int i4Status = 0; + + /* 1. enable GPIO pin as IRQ */ + busSetIrq(); + + /* 2. Specify IRQ number into net_device */ + pDev->irq = WLAN_STA_IRQ; + + /* 3. register ISR callback */ + + i4Status = request_irq(pDev->irq, + glEhpiInterruptHandler, + IRQF_DISABLED | IRQF_SHARED | IRQF_TRIGGER_FALLING, pDev->name, pvCookie); + + if (i4Status < 0) + pr_debug("request_irq(%d) failed\n", pDev->irq); + else + pr_info("request_irq(%d) success with dev_id(%x)\n", pDev->irq, (unsigned int)pvCookie); + + return i4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus interrupt operation and disable interrupt handling for os. +* +* \param[in] pvData A pointer to struct net_device. +* \param[in] pvCookie Private data for pfnIsr function. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glBusFreeIrq(PVOID pvData, PVOID pvCookie) +{ + struct net_device *prDev = (struct net_device *)pvData; + + if (!prDev) { + pr_info("Invalid net_device context.\n"); + return; + } + + if (prDev->irq) { + disable_irq(prDev->irq); + free_irq(prDev->irq, pvCookie); + prDev->irq = 0; + } + + busFreeIrq(); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set power state +* +* \param[in] pvGlueInfo A pointer to GLUE_INFO_T +* \param[in] ePowerMode Power Mode Setting +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glSetPowerState(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 ePowerMode) +{ +} + +#if DBG +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setup the GPIO pin. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void setTrig(void) +{ + GPSR1 = (0x1UL << 8); +} /* end of setTrig() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Clear the GPIO pin. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void clearTrig(void) +{ + GPCR1 = (0x1UL << 8); +} /* end of clearTrig() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set a specified GPIO pin to H or L. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static void initTrig(void) +{ + set_GPIO_mode(GPIO40_FFDTR | GPIO_OUT); + clearTrig(); +} /* end of initTrig() */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function congifure platform-dependent interrupt triger type. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void busSetIrq(void) +{ +#if defined(WLAN_STA_IRQ_GPIO) + pxa_gpio_mode(WLAN_STA_IRQ_GPIO | GPIO_IN); + set_irq_type(WLAN_STA_IRQ, IRQT_FALLING); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function should restore settings changed by busSetIrq(). +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +void busFreeIrq(void) +{ +#if defined(WLAN_STA_IRQ_GPIO) + pxa_gpio_mode(WLAN_STA_IRQ_GPIO | GPIO_OUT); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function configures colibri memory controller registers +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static VOID collibri_ehpi_reg_init(VOID) +{ + UINT_32 u4RegValue; + + /* 1. enable nCS as memory controller */ + pxa_gpio_mode(GPIO80_nCS_4_MD); + + /* 2. nCS<4> configuration */ + u4RegValue = MSC2; + u4RegValue &= ~MSC_CS(4, 0xFFFF); + u4RegValue |= EHPI_CONFIG; + MSC2 = u4RegValue; + + pr_info("EHPI new MSC2:0x%08x\n", MSC2); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function restores colibri memory controller registers +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static VOID collibri_ehpi_reg_uninit(VOID) +{ + UINT_32 u4RegValue; + + /* 1. restore nCS<4> configuration */ + u4RegValue = MSC2; + u4RegValue &= ~MSC_CS(4, 0xFFFF); + MSC2 = u4RegValue; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function configures MT5931 mapped registers on colibri +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static VOID mt5931_ehpi_reg_init(VOID) +{ + struct resource *reso = NULL; + + /* 1. request memory regioin */ + reso = request_mem_region((unsigned long)MEM_MAPPED_ADDR, (unsigned long)MEM_MAPPED_LEN, (char *)MODULE_PREFIX); + if (!reso) { + pr_err("request_mem_region(0x%08X) failed.\n", MEM_MAPPED_ADDR); + return; + } + + /* 2. memory regioin remapping */ + mt5931_mcr_base = ioremap_nocache(MEM_MAPPED_ADDR, MEM_MAPPED_LEN); + if (!(mt5931_mcr_base)) { + release_mem_region(MEM_MAPPED_ADDR, MEM_MAPPED_LEN); + pr_err("ioremap_nocache(0x%08X) failed.\n", MEM_MAPPED_ADDR); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function releases MT5931 mapped registers on colibri +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static VOID mt5931_ehpi_reg_uninit(VOID) +{ + iounmap(mt5931_mcr_base); + mt5931_mcr_base = NULL; + + release_mem_region(MEM_MAPPED_ADDR, MEM_MAPPED_LEN); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Callback for interrupt coming from device +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +static irqreturn_t glEhpiInterruptHandler(int irq, void *dev_id) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) dev_id; + + ASSERT(prGlueInfo); + + if (!prGlueInfo) + return IRQ_HANDLED; + + /* 1. Running for ISR */ + wlanISR(prGlueInfo->prAdapter, TRUE); + + /* 1.1 Halt flag Checking */ + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) + return IRQ_HANDLED; + + /* 2. Flag marking for interrupt */ + set_bit(GLUE_FLAG_INT_BIT, &prGlueInfo->ulFlag); + + /* 3. wake up tx service thread */ + wake_up_interruptible(&prGlueInfo->waitq); + + return IRQ_HANDLED; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/ehpi/ehpi.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/ehpi/ehpi.c new file mode 100644 index 0000000000000..6e0b9ac1b15c7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/ehpi/ehpi.c @@ -0,0 +1,414 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/ehpi/ehpi.c#1 +*/ + +/*! \file "ehpi.c" +* \brief Brief description. +* +* Detail description. +*/ + + +/****************************************************************************** +* C O M P I L E R F L A G S +******************************************************************************* +*/ +#if !defined(MCR_EHTCR) +#define MCR_EHTCR 0x0054 +#endif + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "colibri.h" +#include "wlan_lib.h" + +/******************************************************************************* +* 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 BOOL kalDevRegRead_impl(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Register, OUT PUINT_32 pu4Value); + +static BOOL kalDevRegWrite_impl(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Register, IN UINT_32 u4Value); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to read a 32 bit register value from device. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u4Register The register offset. +* \param[out] pu4Value Pointer to the 32-bit value of the register been read. +* +* \retval TRUE +* \retval FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOL kalDevRegRead(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Register, OUT PUINT_32 pu4Value) +{ + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + ASSERT(pu4Value); + + /* 0. acquire spinlock */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + /* 1. I/O stuff */ + kalDevRegRead_impl(prGlueInfo, u4Register, pu4Value); + + /* 2. release spin lock */ + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to write a 32 bit register value to device. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u4Register The register offset. +* \param[out] u4Value The 32-bit value of the register to be written. +* +* \retval TRUE +* \retval FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOL kalDevRegWrite(P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Register, IN UINT_32 u4Value) +{ + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + /* 0. acquire spinlock */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + /* 1. I/O stuff */ + kalDevRegWrite_impl(prGlueInfo, u4Register, u4Value); + + /* 2. release spin lock */ + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to read port data from device in unit of byte. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u2Port The register offset. +* \param[in] u2Len The number of byte to be read. +* \param[out] pucBuf Pointer to data buffer for read +* \param[in] u2ValidOutBufSize Length of the buffer valid to be accessed +* +* \retval TRUE +* \retval FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOL +kalDevPortRead(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_16 u2Port, IN UINT_16 u2Len, OUT PUINT_8 pucBuf, IN UINT_16 u2ValidOutBufSize) +{ + UINT_32 i; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + /* 0. acquire spinlock */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + /* 1. indicate correct length to HIFSYS if larger than 4-bytes */ + if (u2Len > 4) + kalDevRegWrite_impl(prGlueInfo, MCR_EHTCR, ALIGN_4(u2Len)); + + /* 2. address cycle */ +#if EHPI16 + writew(u2Port, prGlueInfo->rHifInfo.mcr_addr_base); +#elif EHPI8 + writew((u2Port & 0xFF), prGlueInfo->rHifInfo.mcr_addr_base); + writew(((u2Port & 0xFF00) >> 8), prGlueInfo->rHifInfo.mcr_addr_base); +#endif + + /* 3. data cycle */ + for (i = 0; i < ALIGN_4(u2Len); i += 4) { +#if EHPI16 + *((PUINT_16)&(pucBuf[i])) = (UINT_16) (readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFFFF); + *((PUINT_16)&(pucBuf[i + 2])) = (UINT_16) (readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFFFF); +#elif EHPI8 + *((PUINT_8)&(pucBuf[i])) = (UINT_8) (readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF); + *((PUINT_8)&(pucBuf[i + 1])) = (UINT_8) (readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF); + *((PUINT_8)&(pucBuf[i + 2])) = (UINT_8) (readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF); + *((PUINT_8)&(pucBuf[i + 3])) = (UINT_8) (readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF); +#endif + } + + /* 4. restore length to 4 if necessary */ + if (u2Len > 4) + kalDevRegWrite_impl(prGlueInfo, MCR_EHTCR, 4); + + /* 5. release spin lock */ + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to write port data to device in unit of byte. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u2Port The register offset. +* \param[in] u2Len The number of byte to be write. +* \param[out] pucBuf Pointer to data buffer for write +* \param[in] u2ValidOutBufSize Length of the buffer valid to be accessed +* +* \retval TRUE +* \retval FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOL +kalDevPortWrite(P_GLUE_INFO_T prGlueInfo, + IN UINT_16 u2Port, IN UINT_16 u2Len, IN PUINT_8 pucBuf, IN UINT_16 u2ValidInBufSize) +{ + UINT_32 i; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + /* 0. acquire spinlock */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + /* 1. indicate correct length to HIFSYS if larger than 4-bytes */ + if (u2Len > 4) + kalDevRegWrite_impl(prGlueInfo, MCR_EHTCR, ALIGN_4(u2Len)); + + /* 2. address cycle */ +#if EHPI16 + writew(u2Port, prGlueInfo->rHifInfo.mcr_addr_base); +#elif EHPI8 + writew((u2Port & 0xFF), prGlueInfo->rHifInfo.mcr_addr_base); + writew(((u2Port & 0xFF00) >> 8), prGlueInfo->rHifInfo.mcr_addr_base); +#endif + + /* 3. data cycle */ + for (i = 0; i < ALIGN_4(u2Len); i += 4) { +#if EHPI16 + writew((UINT_32) (*((PUINT_16)&(pucBuf[i]))), prGlueInfo->rHifInfo.mcr_data_base); + writew((UINT_32) (*((PUINT_16)&(pucBuf[i + 2]))), prGlueInfo->rHifInfo.mcr_data_base); +#elif EHPI8 + writew((UINT_32) (*((PUINT_8)&(pucBuf[i]))), prGlueInfo->rHifInfo.mcr_data_base); + writew((UINT_32) (*((PUINT_8)&(pucBuf[i + 1]))), prGlueInfo->rHifInfo.mcr_data_base); + writew((UINT_32) (*((PUINT_8)&(pucBuf[i + 2]))), prGlueInfo->rHifInfo.mcr_data_base); + writew((UINT_32) (*((PUINT_8)&(pucBuf[i + 3]))), prGlueInfo->rHifInfo.mcr_data_base); +#endif + } + + /* 4. restore length to 4 if necessary */ + if (u2Len > 4) + kalDevRegWrite_impl(prGlueInfo, MCR_EHTCR, 4); + + /* 5. release spin lock */ + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write device I/O port with single byte (for SDIO compatibility) +* +* \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 +* \param[in] u4ValidInBufSize Length of the buffer valid to be accessed +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +BOOL kalDevWriteWithSdioCmd52(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Addr, IN UINT_8 ucData) +{ + UINT_32 u4RegValue; + BOOLEAN bRet; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + /* 0. acquire spinlock */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + /* 1. there is no single byte access support for eHPI, use 4-bytes write-after-read approach instead */ + if (kalDevRegRead_impl(prGlueInfo, u4Addr, &u4RegValue) == TRUE) { + u4RegValue &= 0x00; + u4RegValue |= ucData; + + bRet = kalDevRegWrite_impl(prGlueInfo, u4Addr, u4RegValue); + } else { + bRet = FALSE; + } + + /* 2. release spin lock */ + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_EHPI_BUS); + + return bRet; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to read a 32 bit register value from device +* without spin lock protection and dedicated for internal use +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u4Register The register offset. +* \param[out] pu4Value Pointer to the 32-bit value of the register been read. +* +* \retval TRUE +* \retval FALSE +*/ +/*----------------------------------------------------------------------------*/ +static BOOL kalDevRegRead_impl(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Register, OUT PUINT_32 pu4Value) +{ + ASSERT(prGlueInfo); + + /* 1. address cycle */ +#if EHPI16 + writew(u4Register, prGlueInfo->rHifInfo.mcr_addr_base); +#elif EHPI8 + writew((u4Register & 0xFF), prGlueInfo->rHifInfo.mcr_addr_base); + writew(((u4Register & 0xFF00) >> 8), prGlueInfo->rHifInfo.mcr_addr_base); +#endif + + /* 2. data cycle */ +#if EHPI16 + *pu4Value = (readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFFFF); + *pu4Value |= ((readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFFFF) << 16); +#elif EHPI8 + *pu4Value = (readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF); + *pu4Value |= ((readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF) << 8); + *pu4Value |= ((readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF) << 16); + *pu4Value |= ((readw(prGlueInfo->rHifInfo.mcr_data_base) & 0xFF) << 24); +#endif + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to write a 32 bit register value to device. +* without spin lock protection and dedicated for internal use +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] u4Register The register offset. +* \param[out] u4Value The 32-bit value of the register to be written. +* +* \retval TRUE +* \retval FALSE +*/ +/*----------------------------------------------------------------------------*/ +static BOOL kalDevRegWrite_impl(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Register, IN UINT_32 u4Value) +{ + ASSERT(prGlueInfo); + + /* 1. address cycle */ +#if EHPI16 + writew(u4Register, prGlueInfo->rHifInfo.mcr_addr_base); +#elif EHPI8 + writew((u4Register & 0xFF), prGlueInfo->rHifInfo.mcr_addr_base); + writew(((u4Register & 0xFF00) >> 8), prGlueInfo->rHifInfo.mcr_addr_base); +#endif + + /* 2. data cycle */ +#if EHPI16 + writew(u4Value, prGlueInfo->rHifInfo.mcr_data_base); + writew((u4Value & 0xFFFF0000) >> 16, prGlueInfo->rHifInfo.mcr_data_base); +#elif EHPI8 + writew((u4Value & 0x000000FF), prGlueInfo->rHifInfo.mcr_data_base); + writew((u4Value & 0x0000FF00) >> 8, prGlueInfo->rHifInfo.mcr_data_base); + writew((u4Value & 0x00FF0000) >> 16, prGlueInfo->rHifInfo.mcr_data_base); + writew((u4Value & 0xFF000000) >> 24, prGlueInfo->rHifInfo.mcr_data_base); +#endif + + return TRUE; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/ehpi/include/colibri.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/ehpi/include/colibri.h new file mode 100644 index 0000000000000..a877b79d8fa96 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/ehpi/include/colibri.h @@ -0,0 +1,190 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/ehpi/include/colibri.h#1 +*/ + +/*! \file "colibri.h" +* \brief This file contains colibri BSP configuration based on eHPI interface +* +* N/A +*/ + +#ifndef _COLIBRI_H +#define _COLIBRI_H +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include +#include +#include +#include +#include + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define WLAN_STA_IRQ_GPIO 23 /* use SSP_EXTCLK as interrupt source */ +#define WLAN_STA_IRQ IRQ_GPIO(WLAN_STA_IRQ_GPIO) + +#define MSC_CS(cs, val) ((val)<<(((cs)&1)<<4)) + +#define MSC_RBUFF_SHIFT 15 +#define MSC_RBUFF(x) ((x)< +#ifndef CONFIG_X86 +#include +#endif + +#include "mt66xx_reg.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define RX_RESPONSE_TIMEOUT (15000) + + +/******************************************************************************* +* 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 PCIE_CHIP_CR_MAPPING arBus2ChipCrMapping[] = { + /* chip addr, bus addr, range */ + {0x82060000, 0x00008000, 0x00000450}, /* WF_PLE */ + {0x82068000, 0x0000c000, 0x00000450}, /* WF_PSE */ + {0x8206c000, 0x0000e000, 0x00000300}, /* PP */ + {0x820d0000, 0x00020000, 0x00000200}, /* WF_AON */ + {0x820f0000, 0x00020200, 0x00000400}, /* WF_CFG */ + {0x820f0800, 0x00020600, 0x00000200}, /* WF_CFGOFF */ + {0x820f1000, 0x00020800, 0x00000200}, /* WF_TRB */ + {0x820f2000, 0x00020a00, 0x00000200}, /* WF_AGG */ + {0x820f3000, 0x00020c00, 0x00000400}, /* WF_ARB */ + {0x820f4000, 0x00021000, 0x00000200}, /* WF_TMAC */ + {0x820f5000, 0x00021200, 0x00000400}, /* WF_RMAC */ + {0x820f6000, 0x00021600, 0x00000200}, /* WF_SEC */ + {0x820f7000, 0x00021800, 0x00000200}, /* WF_DMA */ + + {0x820f8000, 0x00022000, 0x00001000}, /* WF_PF */ + {0x820f9000, 0x00023000, 0x00000400}, /* WF_WTBLON */ + {0x820f9800, 0x00023400, 0x00000200}, /* WF_WTBLOFF */ + + {0x820fa000, 0x00024000, 0x00000200}, /* WF_ETBF */ + {0x820fb000, 0x00024200, 0x00000400}, /* WF_LPON */ + {0x820fc000, 0x00024600, 0x00000200}, /* WF_INT */ + {0x820fd000, 0x00024800, 0x00000400}, /* WF_MIB */ + + {0x820fe000, 0x00025000, 0x00002000}, /* WF_MU */ + + {0x820e0000, 0x00030000, 0x00010000}, /* WF_WTBL */ + + {0x80020000, 0x00000000, 0x00002000}, /* TOP_CFG */ + {0x80000000, 0x00002000, 0x00002000}, /* MCU_CFG */ + {0x50000000, 0x00004000, 0x00004000}, /* PDMA_CFG */ + {0xA0000000, 0x00008000, 0x00008000}, /* PSE_CFG */ + {0x82070000, 0x00010000, 0x00010000}, /* WF_PHY */ + + {0x0, 0x0, 0x0} +}; + +/******************************************************************************* +* M A 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 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 halVerifyChipID(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4CIR = 0; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + + if (prAdapter->fgIsReadRevID) + return TRUE; + + HAL_MCR_RD(prAdapter, TOP_HW_CONTROL, &u4CIR); + + prChipInfo = prAdapter->chip_info; + + if ((u4CIR & WCIR_CHIP_ID) != prChipInfo->chip_id) + return FALSE; + + HAL_MCR_RD(prAdapter, TOP_HW_VERSION, &u4CIR); + + prAdapter->ucRevID = (UINT_8)(u4CIR & 0xF); + prAdapter->fgIsReadRevID = TRUE; + + return TRUE; +} + +WLAN_STATUS halRxWaitResponse(IN P_ADAPTER_T prAdapter, IN UINT_8 ucPortIdx, + OUT PUINT_8 pucRspBuffer, IN UINT_32 u4MaxRespBufferLen, OUT PUINT_32 pu4Length) +{ + UINT_32 u4PktLen = 0, i = 0; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + UINT_32 u4Time, u4Current; + BOOLEAN fgStatus; + + DEBUGFUNC("nicRxWaitResponse"); + + ASSERT(prAdapter); + ASSERT(pucRspBuffer); + ASSERT(ucPortIdx < 2); + + ucPortIdx = HIF_IMG_DL_STATUS_PORT_IDX; + + u4Time = (UINT_32) kalGetTimeTick(); + + u4PktLen = u4MaxRespBufferLen; + + do { + fgStatus = kalDevPortRead(prAdapter->prGlueInfo, ucPortIdx, u4PktLen, + pucRspBuffer, HIF_RX_COALESCING_BUFFER_SIZE); + + if (!fgStatus) { + /* 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 { + *pu4Length = u4PktLen; + break; + } + } while (TRUE); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief enable global interrupt +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID halEnableInterrupt(IN P_ADAPTER_T prAdapter) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_GL_HIF_INFO_T prHifInfo = NULL; + WPMDA_INT_MASK IntMask; + + prGlueInfo = prAdapter->prGlueInfo; + prHifInfo = &prGlueInfo->rHifInfo; + + prAdapter->fgIsIntEnable = TRUE; + + HAL_MCR_RD(prAdapter, WPDMA_INT_MSK, &IntMask.word); + + IntMask.field.rx_done_0 = 1; + IntMask.field.rx_done_1 = 1; + IntMask.field.tx_done_0 = 1; + IntMask.field.tx_done_1 = 1; + IntMask.field.tx_done_2 = 1; + IntMask.field.tx_done_3 = 1; + IntMask.field.tx_coherent = 0; + IntMask.field.rx_coherent = 0; + IntMask.field.tx_dly_int = 0; + IntMask.field.rx_dly_int = 0; + IntMask.field.fw_clr_own = 1; + + HAL_MCR_WR(prAdapter, WPDMA_INT_MSK, IntMask.word); + + DBGLOG(HAL, TRACE, "%s [0x%08x]\n", __func__, IntMask.word); +} /* end of nicEnableInterrupt() */ + + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief disable global interrupt +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID halDisableInterrupt(IN P_ADAPTER_T prAdapter) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WPMDA_INT_MASK IntMask; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + + IntMask.word = 0; + + HAL_MCR_WR(prAdapter, WPDMA_INT_MSK, IntMask.word); + HAL_MCR_RD(prAdapter, WPDMA_INT_MSK, &IntMask.word); + + prAdapter->fgIsIntEnable = FALSE; + + DBGLOG(HAL, TRACE, "%s\n", __func__); + +} +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to process the POWER OFF procedure. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN halSetDriverOwn(IN P_ADAPTER_T prAdapter) +{ + BOOLEAN fgStatus = TRUE; + UINT_32 i, u4CurrTick; + BOOLEAN fgTimeout; + BOOLEAN fgResult; + BOOLEAN fgReady = FALSE; + BOOLEAN fgDummyReq = FALSE; + + ASSERT(prAdapter); + + GLUE_INC_REF_CNT(prAdapter->u4PwrCtrlBlockCnt); + + if (prAdapter->fgIsFwOwn == FALSE) + return fgStatus; + + DBGLOG(INIT, INFO, "DRIVER OWN\n"); + + u4CurrTick = kalGetTimeTick(); + i = 0; + + /* PCIE need to do clear own, then could start polling status */ + HAL_LP_OWN_CLR(prAdapter, &fgResult); + fgResult = FALSE; + + while (1) { + + if (test_bit(GLUE_FLAG_INT_BIT, &prAdapter->prGlueInfo->ulFlag)) + HAL_LP_OWN_RD(prAdapter, &fgResult); + + fgTimeout = ((kalGetTimeTick() - u4CurrTick) > LP_OWN_BACK_TOTAL_DELAY_MS) ? TRUE : FALSE; + + if (fgResult) { + /* Check WPDMA FW own interrupt status and clear */ + /* + *HAL_MCR_RD(prAdapter, WPDMA_INT_STA, &u4RegValue); + *DBGLOG(INIT, INFO, "Already own back %x\n", u4RegValue); + */ + HAL_MCR_WR(prAdapter, WPDMA_INT_STA, WPDMA_FW_CLR_OWN_INT); + prAdapter->fgIsFwOwn = FALSE; + prAdapter->u4OwnFailedCount = 0; + prAdapter->u4OwnFailedLogCount = 0; + break; + } else if ((i > LP_OWN_BACK_FAILED_RETRY_CNT) && + (kalIsCardRemoved(prAdapter->prGlueInfo) || fgIsBusAccessFailed || fgTimeout + || wlanIsChipNoAck(prAdapter))) { + + if ((prAdapter->u4OwnFailedCount == 0) || + CHECK_FOR_TIMEOUT(u4CurrTick, prAdapter->rLastOwnFailedLogTime, + MSEC_TO_SYSTIME(LP_OWN_BACK_FAILED_LOG_SKIP_MS))) { + + DBGLOG(INIT, ERROR, + "LP cannot be own back, Timeout[%u](%ums), BusAccessError[%u]", + fgTimeout, kalGetTimeTick() - u4CurrTick, fgIsBusAccessFailed); + DBGLOG(INIT, ERROR, + "Resetting[%u], CardRemoved[%u] NoAck[%u] Cnt[%u]\n", + kalIsResetting(), + kalIsCardRemoved(prAdapter->prGlueInfo), wlanIsChipNoAck(prAdapter), + prAdapter->u4OwnFailedCount); + + DBGLOG(INIT, INFO, + "Skip LP own back failed log for next %ums\n", LP_OWN_BACK_FAILED_LOG_SKIP_MS); + + prAdapter->u4OwnFailedLogCount++; + if (prAdapter->u4OwnFailedLogCount > LP_OWN_BACK_FAILED_RESET_CNT) { + /* Trigger RESET */ +#if CFG_CHIP_RESET_SUPPORT + glResetTrigger(prAdapter); +#endif + } + GET_CURRENT_SYSTIME(&prAdapter->rLastOwnFailedLogTime); + } + + prAdapter->u4OwnFailedCount++; + fgStatus = FALSE; + break; + } + + if ((i & (LP_OWN_BACK_CLR_OWN_ITERATION - 1)) == 0) { + /* Software get LP ownership - per 256 iterations */ + HAL_LP_OWN_CLR(prAdapter, &fgResult); + } + + /* Delay for LP engine to complete its operation. */ + kalMsleep(LP_OWN_BACK_LOOP_DELAY_MS); + i++; + } + + /* For Low power Test */ + /* 1. Driver need to polling until CR4 ready, then could do normal Tx/Rx */ + /* 2. After CR4 readyy, send a dummy command to change data path to store-forward mode */ +#if 1 + if (prAdapter->fgIsFwDownloaded) { + HAL_WIFI_FUNC_READY_CHECK(prAdapter, WIFI_FUNC_DUMMY_REQ, &fgDummyReq); + + /* Wait CR4 ready */ + u4CurrTick = kalGetTimeTick(); + while (1) { + /* kalMsleep(2); */ + HAL_WIFI_FUNC_READY_CHECK(prAdapter, WIFI_FUNC_READY_BITS, &fgReady); + if (fgReady) { + break; + } else if (kalIsCardRemoved(prAdapter->prGlueInfo) || fgIsBusAccessFailed || fgTimeout + || wlanIsChipNoAck(prAdapter)) { + DBGLOG(INIT, INFO, + "Skip waiting CR4 ready for next %ums\n", LP_OWN_BACK_FAILED_LOG_SKIP_MS); + fgStatus = FALSE; +#if CFG_CHIP_RESET_SUPPORT + glResetTrigger(prAdapter); +#endif + break; + } + /* Delay for CR4 to complete its operation. */ + kalMsleep(LP_OWN_BACK_LOOP_DELAY_MS); + } + + /* Send dummy cmd and clear flag */ + if (fgDummyReq) { + wlanSendDummyCmd(prAdapter, FALSE); + HAL_CLEAR_DUMMY_REQ(prAdapter); + } + } +#endif + + return fgStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to process the POWER ON procedure. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID halSetFWOwn(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnableGlobalInt) +{ + BOOLEAN fgResult; + + ASSERT(prAdapter); + + ASSERT(prAdapter->u4PwrCtrlBlockCnt != 0); + /* Decrease Block to Enter Low Power Semaphore count */ + GLUE_DEC_REF_CNT(prAdapter->u4PwrCtrlBlockCnt); + if (!(prAdapter->fgWiFiInSleepyState && (prAdapter->u4PwrCtrlBlockCnt == 0))) + return; + + if (prAdapter->fgIsFwOwn == TRUE) + return; + + if (nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) { + DBGLOG(INIT, STATE, "Skip FW OWN due to pending INT\n"); + /* pending interrupts */ + return; + } + + + if (fgEnableGlobalInt) { + prAdapter->fgIsIntEnableWithLPOwnSet = TRUE; + } else { + HAL_LP_OWN_SET(prAdapter, &fgResult); + + if (fgResult) { + /* if set firmware own not successful (possibly pending interrupts), */ + /* indicate an own clear event */ + HAL_LP_OWN_CLR(prAdapter, &fgResult); + + return; + } + + prAdapter->fgIsFwOwn = TRUE; + + DBGLOG(INIT, INFO, "FW OWN\n"); + } +} + +VOID halWakeUpWiFi(IN P_ADAPTER_T prAdapter) +{ + BOOLEAN fgResult, fgOwnResult; + UINT_8 ucCount = 0; + +#if CFG_SUPPORT_PMIC_SPI_CLOCK_SWITCH + UINT_32 u4Value = 0; + /*E1 PMIC clock workaround*/ + HAL_MCR_RD(prAdapter, TOP_CKGEN2_CR_PMIC_CK_MANUAL, &u4Value); + + if ((TOP_CKGEN2_CR_PMIC_CK_MANUAL_MASK & u4Value) == 0) + HAL_MCR_WR(prAdapter, TOP_CKGEN2_CR_PMIC_CK_MANUAL, (TOP_CKGEN2_CR_PMIC_CK_MANUAL_MASK|u4Value)); + HAL_MCR_RD(prAdapter, TOP_CKGEN2_CR_PMIC_CK_MANUAL, &u4Value); + DBGLOG(INIT, INFO, "PMIC SPI clock switch = %s\n", + (TOP_CKGEN2_CR_PMIC_CK_MANUAL_MASK&u4Value) ? "SUCCESS" : "FAIL"); +#endif + + ASSERT(prAdapter); + + DBGLOG(INIT, INFO, "Power on Wi-Fi....\n"); + fgOwnResult = FALSE; + HAL_WIFI_FUNC_READY_CHECK(prAdapter, WIFI_FUNC_INIT_DONE, &fgResult); + + while (!fgResult && !fgOwnResult) { + HAL_LP_OWN_CLR(prAdapter, &fgOwnResult); + kalMdelay(50); + HAL_WIFI_FUNC_READY_CHECK(prAdapter, WIFI_FUNC_INIT_DONE, &fgResult); + + ucCount++; + + if (ucCount >= 5) { + DBGLOG(INIT, WARN, "Power on failed!!!\n"); + break; + } + } + + prAdapter->fgIsFwOwn = FALSE; + +#if 0 + HAL_LP_OWN_RD(prAdapter, &fgResult); + + if (fgResult) + prAdapter->fgIsFwOwn = FALSE; + else + HAL_LP_OWN_CLR(prAdapter, &fgResult); +#endif +} + +VOID halTxCancelSendingCmd(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ +} + +BOOLEAN halTxIsDataBufEnough(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_GL_HIF_INFO_T prHifInfo = NULL; + P_RTMP_TX_RING prTxRing; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + prTxRing = &prHifInfo->TxRing[TX_RING_DATA0_IDX_0]; + + if ((halGetMsduTokenFreeCnt(prAdapter) > 0) && ((TX_RING_SIZE - prTxRing->u4UsedCnt) > 1)) + return TRUE; + + DBGLOG(HAL, TRACE, "Low Tx Data Resource Tok[%u] Ring[%u]\n", halGetMsduTokenFreeCnt(prAdapter), + (TX_RING_SIZE - prTxRing->u4UsedCnt)); + return FALSE; + +} + +VOID halProcessTxInterrupt(IN P_ADAPTER_T prAdapter) +{ + P_GL_HIF_INFO_T prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + WPDMA_INT_STA_STRUCT rIntrStatus; + + rIntrStatus = (WPDMA_INT_STA_STRUCT)prHifInfo->u4IntStatus; + + if (rIntrStatus.field.tx_done_3 == 1) + halWpdmaProcessCmdDmaDone(prAdapter->prGlueInfo, TX_RING_FWDL_IDX_3); + + if (rIntrStatus.field.tx_done_2 == 1) + halWpdmaProcessCmdDmaDone(prAdapter->prGlueInfo, TX_RING_CMD_IDX_2); + + if (rIntrStatus.field.tx_done_0 == 1) { + halWpdmaProcessDataDmaDone(prAdapter->prGlueInfo, TX_RING_DATA0_IDX_0); + + kalSetTxEvent2Hif(prAdapter->prGlueInfo); + } +} + +VOID halInitMsduTokenInfo(IN P_ADAPTER_T prAdapter) +{ + P_MSDU_TOKEN_INFO_T prTokenInfo = &prAdapter->prGlueInfo->rHifInfo.rTokenInfo; + P_MSDU_TOKEN_ENTRY_T prToken; + UINT_32 u4Idx; + + prTokenInfo->i4UsedCnt = 0; + + for (u4Idx = 0; u4Idx < HIF_TX_MSDU_TOKEN_NUM; u4Idx++) { + prToken = &prTokenInfo->arToken[u4Idx]; + prToken->fgInUsed = FALSE; + prToken->prMsduInfo = NULL; + +#if HIF_TX_PREALLOC_DATA_BUFFER + prToken->u4DmaLength = NIC_TX_MAX_SIZE_PER_FRAME + NIC_TX_HEAD_ROOM; + prToken->prPacket = kalMemAlloc(prToken->u4DmaLength, PHY_MEM_TYPE); + if (prToken->prPacket) { + DBGLOG(HAL, TRACE, "Msdu Entry[0x%p] Tok[%u] Buf[0x%p] len[%u]\n", prToken, + u4Idx, prToken->prPacket, prToken->u4DmaLength); + } else { + prTokenInfo->i4UsedCnt++; + DBGLOG(HAL, WARN, "Msdu Token Memory alloc failed[%u]\n", u4Idx); + continue; + } +#else + prToken->prPacket = NULL; + prToken->u4DmaLength = 0; +#endif + prToken->rDmaAddr = 0; + prToken->rPktDmaAddr = 0; + prToken->u4PktDmaLength = 0; + prToken->u4Token = u4Idx; + + prTokenInfo->aprTokenStack[u4Idx] = prToken; + } + + spin_lock_init(&prTokenInfo->rTokenLock); + + DBGLOG(HAL, INFO, "Msdu Token Init: Tot[%u] Used[%u]\n", HIF_TX_MSDU_TOKEN_NUM, prTokenInfo->i4UsedCnt); +} + +VOID halUninitMsduTokenInfo(IN P_ADAPTER_T prAdapter) +{ + P_MSDU_TOKEN_INFO_T prTokenInfo = &prAdapter->prGlueInfo->rHifInfo.rTokenInfo; + P_MSDU_TOKEN_ENTRY_T prToken; + UINT_32 u4Idx; + + for (u4Idx = 0; u4Idx < HIF_TX_MSDU_TOKEN_NUM; u4Idx++) { + prToken = &prTokenInfo->arToken[u4Idx]; + + if (prToken->fgInUsed) { + kalPciUnmapToDev(prAdapter->prGlueInfo, prToken->rPktDmaAddr, prToken->u4PktDmaLength); + kalPciUnmapToDev(prAdapter->prGlueInfo, prToken->rDmaAddr, prToken->u4DmaLength); + + DBGLOG(HAL, TRACE, "Clear pending Tok[%u] Msdu[0x%p] Free[%u]\n", prToken->u4Token, + prToken->prMsduInfo, halGetMsduTokenFreeCnt(prAdapter)); + +#if !HIF_TX_PREALLOC_DATA_BUFFER + nicTxFreePacket(prAdapter, prToken->prMsduInfo, FALSE); + nicTxReturnMsduInfo(prAdapter, prToken->prMsduInfo); +#endif + } + +#if HIF_TX_PREALLOC_DATA_BUFFER + kalMemFree(prToken->prPacket, PHY_MEM_TYPE, prToken->u4DmaLength); + prToken->prPacket = NULL; +#endif + } + + prTokenInfo->i4UsedCnt = 0; + + DBGLOG(HAL, INFO, "Msdu Token Uninit: Tot[%u] Used[%u]\n", HIF_TX_MSDU_TOKEN_NUM, prTokenInfo->i4UsedCnt); +} + +UINT_32 halGetMsduTokenFreeCnt(IN P_ADAPTER_T prAdapter) +{ + P_MSDU_TOKEN_INFO_T prTokenInfo = &prAdapter->prGlueInfo->rHifInfo.rTokenInfo; + + return HIF_TX_MSDU_TOKEN_NUM - prTokenInfo->i4UsedCnt; +} + +P_MSDU_TOKEN_ENTRY_T halGetMsduTokenEntry(IN P_ADAPTER_T prAdapter, UINT_32 u4TokenNum) +{ + P_MSDU_TOKEN_INFO_T prTokenInfo = &prAdapter->prGlueInfo->rHifInfo.rTokenInfo; + + return &prTokenInfo->arToken[u4TokenNum]; +} + +P_MSDU_TOKEN_ENTRY_T halAcquireMsduToken(IN P_ADAPTER_T prAdapter) +{ + P_MSDU_TOKEN_INFO_T prTokenInfo = &prAdapter->prGlueInfo->rHifInfo.rTokenInfo; + P_MSDU_TOKEN_ENTRY_T prToken; + ULONG flags = 0; + + if (!halGetMsduTokenFreeCnt(prAdapter)) { + DBGLOG(HAL, INFO, "No more free MSDU token, Used[%u]\n", prTokenInfo->i4UsedCnt); + return NULL; + } + + spin_lock_irqsave(&prTokenInfo->rTokenLock, flags); + + prToken = prTokenInfo->aprTokenStack[prTokenInfo->i4UsedCnt]; + prToken->fgInUsed = TRUE; + prTokenInfo->i4UsedCnt++; + + spin_unlock_irqrestore(&prTokenInfo->rTokenLock, flags); + + DBGLOG(HAL, TRACE, "Acquire Entry[0x%p] Tok[%u] Buf[%u] Len[%u]\n", prToken, + prToken->u4Token, prToken->prPacket, prToken->u4DmaLength); + + return prToken; +} + +VOID halReturnMsduToken(IN P_ADAPTER_T prAdapter, UINT_32 u4TokenNum) +{ + P_MSDU_TOKEN_INFO_T prTokenInfo = &prAdapter->prGlueInfo->rHifInfo.rTokenInfo; + P_MSDU_TOKEN_ENTRY_T prToken; + ULONG flags = 0; + + if (!prTokenInfo->i4UsedCnt) { + DBGLOG(HAL, INFO, "MSDU token is full, Used[%u]\n", prTokenInfo->i4UsedCnt); + return; + } + + prToken = &prTokenInfo->arToken[u4TokenNum]; + + spin_lock_irqsave(&prTokenInfo->rTokenLock, flags); + + prToken->fgInUsed = FALSE; + prTokenInfo->i4UsedCnt--; + prTokenInfo->aprTokenStack[prTokenInfo->i4UsedCnt] = prToken; + + spin_unlock_irqrestore(&prTokenInfo->rTokenLock, flags); +} + +VOID halHifSwInfoInit(IN P_ADAPTER_T prAdapter) +{ + halInitMsduTokenInfo(prAdapter); +} + +VOID halRxProcessMsduReport(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) +{ + P_HW_MAC_MSDU_REPORT_T prMsduReport; +#if !HIF_TX_PREALLOC_DATA_BUFFER + P_MSDU_INFO_T prMsduInfo; +#endif + QUE_T rFreeQueue; + P_QUE_T prFreeQueue; + UINT_16 u2TokenCnt; + UINT_32 u4Idx, u4Token; + P_MSDU_TOKEN_ENTRY_T prTokenEntry; + + prFreeQueue = &rFreeQueue; + QUEUE_INITIALIZE(prFreeQueue); + + prMsduReport = (P_HW_MAC_MSDU_REPORT_T)prSwRfb->pucRecvBuff; + u2TokenCnt = prMsduReport->u2MsduCount; + + for (u4Idx = 0; u4Idx < u2TokenCnt; u4Idx++) { + u4Token = prMsduReport->au2MsduToken[u4Idx]; + prTokenEntry = halGetMsduTokenEntry(prAdapter, u4Token); + +#if HIF_TX_PREALLOC_DATA_BUFFER + DBGLOG(HAL, TRACE, "MsduRpt: Cnt[%u] Tok[%u] Free[%u]\n", u2TokenCnt, + u4Token, halGetMsduTokenFreeCnt(prAdapter)); +#else + prMsduInfo = prTokenEntry->prMsduInfo; + prMsduInfo->prToken = NULL; + if (!prMsduInfo->pfTxDoneHandler) + QUEUE_INSERT_TAIL(prFreeQueue, (P_QUE_ENTRY_T) prMsduInfo); + + DBGLOG(HAL, TRACE, "MsduRpt: Cnt[%u] Tok[%u] Msdu[0x%p] TxDone[%u] Free[%u]\n", u2TokenCnt, + u4Token, prMsduInfo, (prMsduInfo->pfTxDoneHandler ? TRUE : FALSE), + halGetMsduTokenFreeCnt(prAdapter)); +#endif + kalPciUnmapToDev(prAdapter->prGlueInfo, prTokenEntry->rPktDmaAddr, prTokenEntry->u4PktDmaLength); + kalPciUnmapToDev(prAdapter->prGlueInfo, prTokenEntry->rDmaAddr, prTokenEntry->u4DmaLength); + + halReturnMsduToken(prAdapter, u4Token); + } + +#if !HIF_TX_PREALLOC_DATA_BUFFER + nicTxMsduDoneCb(prAdapter->prGlueInfo, prFreeQueue); +#endif + + /* Indicate Service Thread */ + if (wlanGetTxPendingFrameCount(prAdapter) > 0) + kalSetEvent(prAdapter->prGlueInfo); + + kalSetTxEvent2Hif(prAdapter->prGlueInfo); +} + +VOID halTxUpdateCutThroughDesc(P_GLUE_INFO_T prGlueInfo, P_MSDU_INFO_T prMsduInfo, + P_MSDU_TOKEN_ENTRY_T prToken) +{ + P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; + struct pci_dev *pdev = prHifInfo->pdev; + PUINT_8 pucBufferTxD; + P_HW_MAC_TX_DESC_APPEND_T prHwTxDescAppend; + dma_addr_t rDmaAddr; + + pucBufferTxD = prToken->prPacket; + + prHwTxDescAppend = (P_HW_MAC_TX_DESC_APPEND_T) (pucBufferTxD + NIC_TX_DESC_LONG_FORMAT_LENGTH); + prHwTxDescAppend->u2MsduToken = (UINT_16)prToken->u4Token; + prHwTxDescAppend->ucBufNum = 1; + + rDmaAddr = pci_map_single(pdev, pucBufferTxD + NIC_TX_HEAD_ROOM, prMsduInfo->u2FrameLength, + PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(pdev, rDmaAddr)) { + DBGLOG(HAL, ERROR, "pci_map_single() error!\n"); + return; + } + + prHwTxDescAppend->au4BufPtr[0] = rDmaAddr; + prHwTxDescAppend->au2BufLen[0] = prMsduInfo->u2FrameLength; + + prToken->rPktDmaAddr = rDmaAddr; + prToken->u4PktDmaLength = prMsduInfo->u2FrameLength; +} + +UINT_32 halTxGetPageCount(IN UINT_32 u4FrameLength, IN BOOLEAN fgIncludeDesc) +{ + return 1; +} + +WLAN_STATUS halTxPollingResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC) +{ + return WLAN_STATUS_SUCCESS; +} + +VOID halSerHifReset(IN P_ADAPTER_T prAdapter) +{ +} + +VOID halRxPCIeReceiveRFBs(IN P_ADAPTER_T prAdapter, UINT_32 u4Port) +{ + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; + PUINT_8 pucBuf = NULL; + P_HW_MAC_RX_DESC_T prRxStatus; + BOOLEAN fgStatus; + UINT_32 u4RxCnt; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxPCIeReceiveRFBs"); + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + u4RxCnt = halWpdmaGetRxDmaDoneCnt(prAdapter->prGlueInfo, u4Port); + + while (u4RxCnt--) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + if (!prSwRfb) { + DBGLOG(RX, WARN, "No More RFB for P[%u]\n", u4Port); + break; + } + + if (u4Port == RX_RING_DATA_IDX_0) { + fgStatus = kalDevReadData(prAdapter->prGlueInfo, u4Port, prSwRfb); + } else { + pucBuf = prSwRfb->pucRecvBuff; + ASSERT(pucBuf); + + fgStatus = kalDevPortRead(prAdapter->prGlueInfo, u4Port, CFG_RX_MAX_PKT_SIZE, + pucBuf, CFG_RX_MAX_PKT_SIZE); + } + if (!fgStatus) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_INSERT_TAIL(&prRxCtrl->rFreeSwRfbList, &prSwRfb->rQueEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + continue; + } + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + prSwRfb->ucPacketType = (UINT_8) HAL_RX_STATUS_GET_PKT_TYPE(prRxStatus); + DBGLOG(RX, TRACE, "ucPacketType = %d\n", prSwRfb->ucPacketType); + + if (prSwRfb->ucPacketType == RX_PKT_TYPE_MSDU_REPORT) { + nicRxProcessMsduReport(prAdapter, prSwRfb); + + continue; + } + + prSwRfb->ucStaRecIdx = + secGetStaIdxByWlanIdx(prAdapter, (UINT_8)HAL_RX_STATUS_GET_WLAN_IDX(prRxStatus)); + + 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); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read frames from the data port for PCIE +* I/F, fill RFB and put each frame into the rReceivedRFBList queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID halProcessRxInterrupt(IN P_ADAPTER_T prAdapter) +{ + P_GL_HIF_INFO_T prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + WPDMA_INT_STA_STRUCT rIntrStatus; + + rIntrStatus = (WPDMA_INT_STA_STRUCT)prHifInfo->u4IntStatus; + + if (rIntrStatus.field.rx_done_1) + halRxPCIeReceiveRFBs(prAdapter, RX_RING_EVT_IDX_1); + + if (rIntrStatus.field.rx_done_0) + halRxPCIeReceiveRFBs(prAdapter, RX_RING_DATA_IDX_0); +} + +static INT_32 halWpdmaAllocRingDesc(P_GLUE_INFO_T prGlueInfo, RTMP_DMABUF *pDescRing, INT_32 size) +{ + P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; + struct pci_dev *pdev = prHifInfo->pdev; + + pDescRing->AllocSize = size; + + pDescRing->AllocVa = (PVOID) pci_alloc_consistent(pdev, pDescRing->AllocSize, &pDescRing->AllocPa); + + if (pDescRing->AllocVa == NULL) { + DBGLOG(HAL, ERROR, "Failed to allocate a big buffer\n"); + return -1; + } + + /* Zero init this memory block */ + kalMemZero(pDescRing->AllocVa, size); + + return 0; +} + +static INT_32 halWpdmaFreeRingDesc(P_GLUE_INFO_T prGlueInfo, RTMP_DMABUF *pDescRing) +{ + P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; + struct pci_dev *pdev = prHifInfo->pdev; + + if (pDescRing->AllocVa) + pci_free_consistent(pdev, pDescRing->AllocSize, pDescRing->AllocVa, pDescRing->AllocPa); + + kalMemZero(pDescRing, sizeof(RTMP_DMABUF)); + + return TRUE; +} + +static PVOID halWpdmaAllocRxPacketBuff(IN PVOID pPciDev, IN ULONG Length, + IN BOOLEAN Cached, OUT PPVOID VirtualAddress, OUT dma_addr_t *phy_addr) +{ + struct sk_buff *pkt; + + /* pkt = __dev_alloc_skb(Length, GFP_DMA | GFP_ATOMIC); */ + pkt = dev_alloc_skb(Length); + + if (pkt == NULL) + DBGLOG(HAL, ERROR, "can't allocate rx %ld size packet\n", Length); + + if (pkt) { + *VirtualAddress = (PVOID) pkt->data; + *phy_addr = pci_map_single(pPciDev, *VirtualAddress, Length, PCI_DMA_FROMDEVICE); + } else { + *VirtualAddress = (PVOID) NULL; + *phy_addr = (dma_addr_t) 0; + } + + return (PVOID) pkt; +} + +VOID halWpdmaAllocRxRing(P_GLUE_INFO_T prGlueInfo, UINT_32 u4Num, UINT_32 u4Size, + UINT_32 u4DescSize, UINT_32 u4BufSize) +{ + dma_addr_t RingBasePa; + PVOID RingBaseVa; + INT_32 index; + RXD_STRUCT *pRxD; + RTMP_DMABUF *pDmaBuf; + RTMP_DMACB *dma_cb; + PVOID pPacket; + P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; + + /* Alloc RxRingDesc memory except Tx ring allocated eariler */ + halWpdmaAllocRingDesc(prGlueInfo, &prHifInfo->RxDescRing[u4Num], u4Size * u4DescSize); + if (prHifInfo->RxDescRing[u4Num].AllocVa == NULL) { + DBGLOG(HAL, ERROR, "\n\n\nRxDescRing[%p] allocation failed!!\n\n\n"); + return; + } + + DBGLOG(HAL, INFO, "RxDescRing[%p]: total %d bytes allocated\n", + prHifInfo->RxDescRing[u4Num].AllocVa, (INT_32) prHifInfo->RxDescRing[u4Num].AllocSize); + + /* Initialize Rx Ring and associated buffer memory */ + RingBasePa = prHifInfo->RxDescRing[u4Num].AllocPa; + RingBaseVa = prHifInfo->RxDescRing[u4Num].AllocVa; + + prHifInfo->RxRing[u4Num].u4BufSize = u4BufSize; + prHifInfo->RxRing[u4Num].u4RingSize = u4Size; + prHifInfo->RxRing[u4Num].fgRxSegPkt = FALSE; + + for (index = 0; index < u4Size; index++) { + dma_cb = &prHifInfo->RxRing[u4Num].Cell[index]; + /* Init RX Ring Size, Va, Pa variables */ + dma_cb->AllocSize = u4DescSize; + dma_cb->AllocVa = RingBaseVa; + dma_cb->AllocPa = RingBasePa; + + /* Offset to next ring descriptor address */ + RingBasePa += u4DescSize; + RingBaseVa = (PUCHAR) RingBaseVa + u4DescSize; + + /* Setup Rx associated Buffer size & allocate share memory */ + pDmaBuf = &dma_cb->DmaBuf; + pDmaBuf->AllocSize = u4BufSize; + pPacket = halWpdmaAllocRxPacketBuff(prHifInfo->pdev, pDmaBuf->AllocSize, + FALSE, &pDmaBuf->AllocVa, &pDmaBuf->AllocPa); + + /* keep allocated rx packet */ + dma_cb->pPacket = pPacket; + if (pDmaBuf->AllocVa == NULL) { + DBGLOG(HAL, ERROR, "\n\n\nFailed to allocate RxRing buffer index[%u]\n\n\n", index); + return; + } + + /* Zero init this memory block */ + kalMemZero(pDmaBuf->AllocVa, pDmaBuf->AllocSize); + + /* Write RxD buffer address & allocated buffer length */ + pRxD = (RXD_STRUCT *) dma_cb->AllocVa; + pRxD->SDP0 = pDmaBuf->AllocPa; + pRxD->SDL0 = u4BufSize; + pRxD->DDONE = 0; + } + + DBGLOG(HAL, TRACE, "Rx[%d] Ring: total %d entry allocated\n", u4Num, index); +} + +VOID halWpdmaAllocRing(P_GLUE_INFO_T prGlueInfo) +{ + dma_addr_t RingBasePa; + PVOID RingBaseVa; + INT_32 index, num; + TXD_STRUCT *pTxD; + RTMP_TX_RING *pTxRing; + RTMP_DMABUF *pDmaBuf; + RTMP_DMACB *dma_cb; + P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; + + do { + /* + * Allocate all ring descriptors, include TxD, RxD, MgmtD. + * Although each size is different, to prevent cacheline and alignment + * issue, I intentional set them all to 64 bytes + */ + for (num = 0; num < NUM_OF_TX_RING; num++) { + dma_addr_t BufBasePa; + PVOID BufBaseVa; + + /* + * Allocate Tx ring descriptor's memory + */ + halWpdmaAllocRingDesc(prGlueInfo, &prHifInfo->TxDescRing[num], TX_RING_SIZE * TXD_SIZE); + if (prHifInfo->TxDescRing[num].AllocVa == NULL) + break; + + pDmaBuf = &prHifInfo->TxDescRing[num]; + DBGLOG(HAL, TRACE, "TxDescRing[%p]: total %d bytes allocated\n", + pDmaBuf->AllocVa, (INT_32) pDmaBuf->AllocSize); + + /* Save PA & VA for further operation */ + RingBasePa = pDmaBuf->AllocPa; + RingBaseVa = pDmaBuf->AllocVa; + + /* + * Allocate all 1st TXBuf's memory for this TxRing + */ + halWpdmaAllocRingDesc(prGlueInfo, &prHifInfo->TxBufSpace[num], + TX_RING_SIZE * TX_DMA_1ST_BUFFER_SIZE); + if (prHifInfo->TxBufSpace[num].AllocVa == NULL) { + DBGLOG(HAL, ERROR, "Failed to allocate a big buffer\n"); + break; + } + + /* Zero init this memory block */ + kalMemZero(prHifInfo->TxBufSpace[num].AllocVa, prHifInfo->TxBufSpace[num].AllocSize); + + /* Save PA & VA for further operation */ + BufBasePa = prHifInfo->TxBufSpace[num].AllocPa; + BufBaseVa = prHifInfo->TxBufSpace[num].AllocVa; + + /* + * Initialize Tx Ring Descriptor and associated buffer memory + */ + pTxRing = &prHifInfo->TxRing[num]; + for (index = 0; index < TX_RING_SIZE; index++) { + dma_cb = &pTxRing->Cell[index]; + dma_cb->pPacket = NULL; + dma_cb->pBuffer = NULL; + /* Init Tx Ring Size, Va, Pa variables */ + dma_cb->AllocSize = TXD_SIZE; + dma_cb->AllocVa = RingBaseVa; + dma_cb->AllocPa = RingBasePa; + + /* Setup Tx Buffer size & address. only 802.11 header will store in this space */ + pDmaBuf = &dma_cb->DmaBuf; + pDmaBuf->AllocSize = TX_DMA_1ST_BUFFER_SIZE; + pDmaBuf->AllocVa = BufBaseVa; + pDmaBuf->AllocPa = BufBasePa; + + /* link the pre-allocated TxBuf to TXD */ + pTxD = (TXD_STRUCT *) dma_cb->AllocVa; + pTxD->SDPtr0 = BufBasePa; + /* advance to next ring descriptor address */ + pTxD->DMADONE = 1; + + RingBasePa += TXD_SIZE; + RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; + + /* advance to next TxBuf address */ + BufBasePa += TX_DMA_1ST_BUFFER_SIZE; + BufBaseVa = (PUCHAR) BufBaseVa + TX_DMA_1ST_BUFFER_SIZE; + } + + DBGLOG(HAL, TRACE, "TxRing[%d]: total %d entry allocated\n", num, index); + } + + /* Data Rx path */ + halWpdmaAllocRxRing(prGlueInfo, RX_RING_DATA_IDX_0, RX_RING0_SIZE, RXD_SIZE, CFG_RX_MAX_PKT_SIZE); + /* Event Rx path */ + halWpdmaAllocRxRing(prGlueInfo, RX_RING_EVT_IDX_1, RX_RING1_SIZE, RXD_SIZE, RX_BUFFER_AGGRESIZE); + } while (FALSE); + + /* Initialize all transmit related software queues */ + + /* Init TX rings index pointer */ + for (index = 0; index < NUM_OF_TX_RING; index++) { + prHifInfo->TxRing[index].TxSwUsedIdx = 0; + prHifInfo->TxRing[index].TxCpuIdx = 0; + } + +} + +VOID halWpdmaFreeRing(P_GLUE_INFO_T prGlueInfo) +{ + int index, num, j; + RTMP_TX_RING *pTxRing; + TXD_STRUCT *pTxD; + PVOID pPacket, pBuffer; + RTMP_DMACB *dma_cb; + P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; + struct pci_dev *pdev = prHifInfo->pdev; + + /* Free Tx Ring Packet */ + for (index = 0; index < NUM_OF_TX_RING; index++) { + pTxRing = &prHifInfo->TxRing[index]; + + for (j = 0; j < TX_RING_SIZE; j++) { + pTxD = (TXD_STRUCT *) (pTxRing->Cell[j].AllocVa); + + pPacket = pTxRing->Cell[j].pPacket; + pBuffer = pTxRing->Cell[j].pBuffer; + + if (pPacket || pBuffer) + pci_unmap_single(pdev, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE); + + pTxRing->Cell[j].pPacket = NULL; + + if (pBuffer) + kalMemFree(pBuffer, PHY_MEM_TYPE, 0); + + pTxRing->Cell[j].pBuffer = NULL; + } + } + + for (j = 0; j < NUM_OF_RX_RING; j++) { + for (index = prHifInfo->RxRing[j].u4RingSize - 1; index >= 0; index--) { + dma_cb = &prHifInfo->RxRing[j].Cell[index]; + if ((dma_cb->DmaBuf.AllocVa) && (dma_cb->pPacket)) { + pci_unmap_single(pdev, dma_cb->DmaBuf.AllocPa, + dma_cb->DmaBuf.AllocSize, PCI_DMA_FROMDEVICE); + + kalPacketFree(prGlueInfo, dma_cb->pPacket); + } + } + kalMemZero(prHifInfo->RxRing[j].Cell, prHifInfo->RxRing[j].u4RingSize * sizeof(RTMP_DMACB)); + + halWpdmaFreeRingDesc(prGlueInfo, &prHifInfo->RxDescRing[j]); + } + + for (num = 0; num < NUM_OF_TX_RING; num++) { + halWpdmaFreeRingDesc(prGlueInfo, &prHifInfo->TxBufSpace[num]); + + halWpdmaFreeRingDesc(prGlueInfo, &prHifInfo->TxDescRing[num]); + } +} + +VOID halWpdmaSetup(P_GLUE_INFO_T prGlueInfo, BOOLEAN enable) +{ + struct mt66xx_chip_info *chip_info = prGlueInfo->prAdapter->chip_info; + + if (chip_info->is_pcie_32dw_read) + halWpdmaConfig(prGlueInfo, enable); + else + halEnhancedWpdmaConfig(prGlueInfo, enable); +} + +VOID halEnhancedWpdmaConfig(P_GLUE_INFO_T prGlueInfo, BOOLEAN enable) +{ + WPDMA_GLO_CFG_STRUCT GloCfg; + WPMDA_INT_MASK IntMask; + + kalDevRegRead(prGlueInfo, WPDMA_GLO_CFG, &GloCfg.word); + + kalDevRegRead(prGlueInfo, WPDMA_INT_MSK, &IntMask.word); + + if (enable == TRUE) { + /*0x4208 = 5440_1E70*/ + GloCfg.field_1.EnableTxDMA = 1; + GloCfg.field_1.EnableRxDMA = 1; + + GloCfg.field_1.WPDMABurstSIZE = 3; + GloCfg.field_1.EnTXWriteBackDDONE = 1; + + GloCfg.field_1.tx_bt_size = 1; + GloCfg.field_1.multi_dma_en = 3; + GloCfg.field_1.fifo_little_endian = 1; + + GloCfg.field_1.tx_bt_size_bit21 = 1; + GloCfg.field_1.sw_rst = 0; + GloCfg.field_1.first_token = 1; + GloCfg.field_1.omit_tx_info = 1; + GloCfg.field_1.reserve_30 = 1; + + IntMask.field.rx_done_0 = 1; + IntMask.field.rx_done_1 = 1; + IntMask.field.tx_done_0 = 1; + IntMask.field.tx_done_1 = 0; + IntMask.field.tx_done_2 = 1; + IntMask.field.tx_dly_int = 0; + } else { + GloCfg.field_1.EnableRxDMA = 0; + GloCfg.field_1.EnableTxDMA = 0; + GloCfg.field_1.sw_rst = 1; + + IntMask.field.rx_done_0 = 0; + IntMask.field.rx_done_1 = 0; + IntMask.field.tx_done_0 = 0; + IntMask.field.tx_done_1 = 0; + IntMask.field.tx_done_2 = 0; + IntMask.field.tx_dly_int = 0; + } + + kalDevRegWrite(prGlueInfo, WPDMA_INT_MSK, IntMask.word); + kalDevRegWrite(prGlueInfo, WPDMA_GLO_CFG, GloCfg.word); + + + /* new PDMA */ + /* 0x4260 = 0000_0005 */ + kalDevRegWrite(prGlueInfo, MT_WPDMA_PAUSE_RX_Q, 0x5); + + /* 0x4500 = 0000_0001*/ + kalDevRegWrite(prGlueInfo, MT_WPDMA_GLO_CFG_1, 0x1); + + /* 0x4510 = 000F_0000*/ + kalDevRegWrite(prGlueInfo, MT_WPDMA_TX_PRE_CFG, 0xF0000); + + /* 0x4520 = 0F7F_0000 */ + kalDevRegWrite(prGlueInfo, MT_WPDMA_RX_PRE_CFG, 0xF7F0000); + + /* 0x4530 = 0EA6_0026 */ + kalDevRegWrite(prGlueInfo, MT_WPDMA_ABT_CFG, 0x0EA60026); + + /* 0x4534 = E4E4_E4E4*/ + kalDevRegWrite(prGlueInfo, MT_WPDMA_ABT_CFG1, 0xE4E4E4E4); + +} + +VOID halWpdmaConfig(P_GLUE_INFO_T prGlueInfo, BOOLEAN enable) +{ + WPDMA_GLO_CFG_STRUCT GloCfg; + WPMDA_INT_MASK IntMask; + + kalDevRegRead(prGlueInfo, WPDMA_GLO_CFG, &GloCfg.word); + + kalDevRegRead(prGlueInfo, WPDMA_INT_MSK, &IntMask.word); + + if (enable == TRUE) { + GloCfg.field.EnableTxDMA = 1; + GloCfg.field.EnableRxDMA = 1; + GloCfg.field.EnTXWriteBackDDONE = 1; + GloCfg.field.WPDMABurstSIZE = 3; + GloCfg.field.omit_tx_info = 1; + GloCfg.field.fifo_little_endian = 1; + GloCfg.field.multi_dma_en = 3; + GloCfg.field.sw_rst = 0; + GloCfg.field.clk_gate_dis = 1; + + IntMask.field.rx_done_0 = 1; + IntMask.field.rx_done_1 = 1; + IntMask.field.tx_done_0 = 1; + IntMask.field.tx_done_1 = 1; + IntMask.field.tx_done_2 = 1; + } else { + GloCfg.field.EnableRxDMA = 0; + GloCfg.field.EnableTxDMA = 0; + GloCfg.field.multi_dma_en = 2; + GloCfg.field.sw_rst = 1; + IntMask.field.rx_done_0 = 0; + IntMask.field.rx_done_1 = 0; + IntMask.field.tx_done_0 = 0; + IntMask.field.tx_done_1 = 0; + IntMask.field.tx_done_2 = 0; + } + + kalDevRegWrite(prGlueInfo, WPDMA_INT_MSK, IntMask.word); + + kalDevRegWrite(prGlueInfo, WPDMA_GLO_CFG, GloCfg.word); +} + +static BOOLEAN halWpdmaWaitIdle(P_GLUE_INFO_T prGlueInfo, INT_32 round, INT_32 wait_us) +{ + INT_32 i = 0; + WPDMA_GLO_CFG_STRUCT GloCfg; + + do { + kalDevRegRead(prGlueInfo, WPDMA_GLO_CFG, &GloCfg.word); + if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0)) { + DBGLOG(HAL, TRACE, "==> DMAIdle, GloCfg=0x%x\n", GloCfg.word); + return TRUE; + } + kalUdelay(wait_us); + } while ((i++) < round); + + DBGLOG(HAL, INFO, "==> DMABusy, GloCfg=0x%x\n", GloCfg.word); + + return FALSE; +} + +VOID halWpdmaInitRing(P_GLUE_INFO_T prGlueInfo) +{ + UINT_32 phy_addr, offset; + INT_32 i; + P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; + RTMP_TX_RING *tx_ring; + RTMP_RX_RING *rx_ring; + + /* Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits */ + halWpdmaSetup(prGlueInfo, FALSE); + + halWpdmaWaitIdle(prGlueInfo, 100, 1000); + + /* Reset DMA Index */ + kalDevRegWrite(prGlueInfo, WPDMA_RST_PTR, 0xFFFFFFFF); + + for (i = 0; i < NUM_OF_TX_RING; i++) { + tx_ring = &prHifInfo->TxRing[i]; + offset = i * MT_RINGREG_DIFF; + phy_addr = prHifInfo->TxRing[i].Cell[0].AllocPa; + tx_ring->TxSwUsedIdx = 0; + tx_ring->u4UsedCnt = 0; + tx_ring->TxCpuIdx = 0; + tx_ring->hw_desc_base = MT_TX_RING_BASE + offset; + tx_ring->hw_cidx_addr = MT_TX_RING_CIDX + offset; + tx_ring->hw_didx_addr = MT_TX_RING_DIDX + offset; + tx_ring->hw_cnt_addr = MT_TX_RING_CNT + offset; + kalDevRegWrite(prGlueInfo, tx_ring->hw_desc_base, phy_addr); + kalDevRegWrite(prGlueInfo, tx_ring->hw_cidx_addr, tx_ring->TxCpuIdx); + kalDevRegWrite(prGlueInfo, tx_ring->hw_cnt_addr, TX_RING_SIZE); + + spin_lock_init((spinlock_t *) (&prHifInfo->TxRingLock[i])); + + DBGLOG(HAL, INFO, "-->TX_RING_%d[0x%x]: Base=0x%x, Cnt=%d!\n", + i, prHifInfo->TxRing[i].hw_desc_base, phy_addr, TX_RING_SIZE); + } + + /* Init RX Ring0 Base/Size/Index pointer CSR */ + for (i = 0; i < NUM_OF_RX_RING; i++) { + rx_ring = &prHifInfo->RxRing[i]; + offset = i * MT_RINGREG_DIFF; + phy_addr = rx_ring->Cell[0].AllocPa; + rx_ring->RxSwReadIdx = 0; + rx_ring->RxCpuIdx = rx_ring->u4RingSize - 1; + rx_ring->hw_desc_base = MT_RX_RING_BASE + offset; + rx_ring->hw_cidx_addr = MT_RX_RING_CIDX + offset; + rx_ring->hw_didx_addr = MT_RX_RING_DIDX + offset; + rx_ring->hw_cnt_addr = MT_RX_RING_CNT + offset; + kalDevRegWrite(prGlueInfo, rx_ring->hw_desc_base, phy_addr); + kalDevRegWrite(prGlueInfo, rx_ring->hw_cidx_addr, rx_ring->RxCpuIdx); + kalDevRegWrite(prGlueInfo, rx_ring->hw_cnt_addr, rx_ring->u4RingSize); + + spin_lock_init((spinlock_t *) (&prHifInfo->RxRingLock[i])); + + DBGLOG(HAL, INFO, "-->RX_RING%d[0x%x]: Base=0x%x, Cnt=%d\n", + i, rx_ring->hw_desc_base, phy_addr, rx_ring->u4RingSize); + } + + halWpdmaSetup(prGlueInfo, TRUE); +} + +VOID halWpdmaProcessCmdDmaDone(IN P_GLUE_INFO_T prGlueInfo, IN UINT_16 u2Port) +{ + P_GL_HIF_INFO_T prHifInfo = NULL; + UINT_32 u4SwIdx, u4DmaIdx; + P_RTMP_TX_RING prTxRing; + TXD_STRUCT *pTxD; + PVOID pBuffer = NULL; + struct pci_dev *pdev; + ULONG flags = 0; + + ASSERT(prGlueInfo); + + prHifInfo = &prGlueInfo->rHifInfo; + pdev = prHifInfo->pdev; + prTxRing = &prHifInfo->TxRing[u2Port]; + + spin_lock_irqsave(&prHifInfo->TxRingLock[u2Port], flags); + + kalDevRegRead(prGlueInfo, prTxRing->hw_didx_addr, &u4DmaIdx); + + u4SwIdx = prTxRing->TxSwUsedIdx; + + do { + pBuffer = prTxRing->Cell[u4SwIdx].pBuffer; + pTxD = (TXD_STRUCT *) prTxRing->Cell[u4SwIdx].AllocVa; + + if (!pBuffer || (pTxD->DMADONE == 0)) + break; + + DBGLOG(HAL, TRACE, "DMA done: port[%u] dma[%u] idx[%u] done[%u] pkt[0x%p] used[%u]\n", u2Port, + u4DmaIdx, u4SwIdx, pTxD->DMADONE, prTxRing->Cell[u4SwIdx].pPacket, prTxRing->u4UsedCnt); + + if (pTxD->SDPtr0) + pci_unmap_single(pdev, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE); + + if (pTxD->SDPtr1) + pci_unmap_single(pdev, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); + + pTxD->DMADONE = 0; + kalMemFree(prTxRing->Cell[u4SwIdx].pBuffer, PHY_MEM_TYPE, 0); + prTxRing->Cell[u4SwIdx].pBuffer = NULL; + prTxRing->Cell[u4SwIdx].pPacket = NULL; + prTxRing->u4UsedCnt--; + + if (u2Port == TX_RING_CMD_IDX_2) + nicTxReleaseResource(prGlueInfo->prAdapter, TC4_INDEX, + nicTxGetPageCount(pTxD->SDLen0, TRUE), TRUE); + + INC_RING_INDEX(u4SwIdx, TX_RING_SIZE); + } while (u4SwIdx != u4DmaIdx); + + prTxRing->TxSwUsedIdx = u4SwIdx; + + spin_unlock_irqrestore(&prHifInfo->TxRingLock[u2Port], flags); +} + +VOID halWpdmaProcessDataDmaDone(IN P_GLUE_INFO_T prGlueInfo, IN UINT_16 u2Port) +{ + P_GL_HIF_INFO_T prHifInfo = NULL; + UINT_32 u4SwIdx, u4DmaIdx; + P_RTMP_TX_RING prTxRing; + ULONG flags = 0; + + ASSERT(prGlueInfo); + + prHifInfo = &prGlueInfo->rHifInfo; + prTxRing = &prHifInfo->TxRing[u2Port]; + + kalDevRegRead(prGlueInfo, prTxRing->hw_didx_addr, &u4DmaIdx); + u4SwIdx = prTxRing->TxSwUsedIdx; + + spin_lock_irqsave(&prHifInfo->TxRingLock[u2Port], flags); + + if (u4DmaIdx > u4SwIdx) + prTxRing->u4UsedCnt -= u4DmaIdx - u4SwIdx; + else if (u4DmaIdx < u4SwIdx) + prTxRing->u4UsedCnt -= (TX_RING_SIZE + u4DmaIdx) - u4SwIdx; + else { + /* DMA index == SW used index */ + if (prTxRing->u4UsedCnt == TX_RING_SIZE) + prTxRing->u4UsedCnt = 0; + } + + spin_unlock_irqrestore(&prHifInfo->TxRingLock[u2Port], flags); + + DBGLOG(HAL, TRACE, "DMA done: port[%u] dma[%u] idx[%u] used[%u]\n", u2Port, + u4DmaIdx, u4SwIdx, prTxRing->u4UsedCnt); + + prTxRing->TxSwUsedIdx = u4DmaIdx; +} + +UINT_32 halWpdmaGetRxDmaDoneCnt(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRingNum) +{ + P_RTMP_RX_RING prRxRing; + P_GL_HIF_INFO_T prHifInfo; + UINT_32 u4MaxCnt, u4CpuIdx, u4DmaIdx, u4RxPktCnt; + + prHifInfo = &prGlueInfo->rHifInfo; + prRxRing = &prHifInfo->RxRing[ucRingNum]; + + kalDevRegRead(prGlueInfo, prRxRing->hw_cnt_addr, &u4MaxCnt); + kalDevRegRead(prGlueInfo, prRxRing->hw_cidx_addr, &u4CpuIdx); + kalDevRegRead(prGlueInfo, prRxRing->hw_didx_addr, &u4DmaIdx); + + u4RxPktCnt = u4MaxCnt; + + if (u4CpuIdx > u4DmaIdx) + u4RxPktCnt = u4MaxCnt + u4DmaIdx - u4CpuIdx - 1; + else if (u4CpuIdx < u4DmaIdx) + u4RxPktCnt = u4DmaIdx - u4CpuIdx - 1; + + return u4RxPktCnt; +} + +VOID halDumpTxRing(IN P_GLUE_INFO_T prGlueInfo, IN UINT_16 u2Port, IN UINT_32 u4Idx) +{ + P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; + P_RTMP_TX_RING prTxRing; + TXD_STRUCT *pTxD; + + prTxRing = &prHifInfo->TxRing[u2Port]; + + pTxD = (TXD_STRUCT *) prTxRing->Cell[u4Idx].AllocVa; + + DBGLOG(SW4, INFO, "TX Ring[%u] Idx[%04u] SDP0[0x%08x] SDL0[%u] LS[%u] B[%u] DDONE[%u]\n", + u2Port, u4Idx, pTxD->SDPtr0, pTxD->SDLen0, pTxD->LastSec0, pTxD->Burst, pTxD->DMADONE); +} + +UINT_32 halDumpHifStatus(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuf, IN UINT_32 u4Max) +{ + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; + UINT_32 u4Idx, u4DmaIdx, u4CpuIdx, u4MaxCnt; + UINT_32 u4Len = 0; + P_RTMP_TX_RING prTxRing; + P_RTMP_RX_RING prRxRing; + + LOGBUF(pucBuf, u4Max, u4Len, "\n------------\n"); + + for (u4Idx = 0; u4Idx < NUM_OF_TX_RING; u4Idx++) { + prTxRing = &prHifInfo->TxRing[u4Idx]; + kalDevRegRead(prGlueInfo, prTxRing->hw_cnt_addr, &u4MaxCnt); + kalDevRegRead(prGlueInfo, prTxRing->hw_cidx_addr, &u4CpuIdx); + kalDevRegRead(prGlueInfo, prTxRing->hw_didx_addr, &u4DmaIdx); + + LOGBUF(pucBuf, u4Max, u4Len, "TX[%u] SZ[%04u] CPU[%04u/%04u] DMA[%04u/%04u] SW_UD[%04u] Used[%u]\n", + u4Idx, u4MaxCnt, prTxRing->TxCpuIdx, u4CpuIdx, prTxRing->TxDmaIdx, + u4DmaIdx, prTxRing->TxSwUsedIdx, prTxRing->u4UsedCnt); + + if (u4Idx == TX_RING_DATA0_IDX_0) { + halDumpTxRing(prGlueInfo, u4Idx, prTxRing->TxCpuIdx); + halDumpTxRing(prGlueInfo, u4Idx, u4CpuIdx); + halDumpTxRing(prGlueInfo, u4Idx, u4DmaIdx); + halDumpTxRing(prGlueInfo, u4Idx, prTxRing->TxSwUsedIdx); + } + } + + for (u4Idx = 0; u4Idx < NUM_OF_RX_RING; u4Idx++) { + prRxRing = &prHifInfo->RxRing[u4Idx]; + + kalDevRegRead(prGlueInfo, prRxRing->hw_cnt_addr, &u4MaxCnt); + kalDevRegRead(prGlueInfo, prRxRing->hw_cidx_addr, &u4CpuIdx); + kalDevRegRead(prGlueInfo, prRxRing->hw_didx_addr, &u4DmaIdx); + + LOGBUF(pucBuf, u4Max, u4Len, "RX[%u] SZ[%04u] CPU[%04u/%04u] DMA[%04u/%04u] SW_RD[%04u]\n", u4Idx, + u4MaxCnt, prRxRing->RxCpuIdx, u4CpuIdx, prRxRing->RxDmaIdx, u4DmaIdx, prRxRing->RxSwReadIdx); + } + + LOGBUF(pucBuf, u4Max, u4Len, "MSDU Tok: Free[%u] Used[%u]\n", + halGetMsduTokenFreeCnt(prGlueInfo->prAdapter), prGlueInfo->rHifInfo.rTokenInfo.i4UsedCnt); + LOGBUF(pucBuf, u4Max, u4Len, "Pending QLen Normal[%u] Sec[%u]\n", + prGlueInfo->i4TxPendingFrameNum, prGlueInfo->i4TxPendingSecurityFrameNum); + + LOGBUF(pucBuf, u4Max, u4Len, "---------------------------------\n\n"); + + return u4Len; +} + + +BOOLEAN halIsStaticMapBusAddr(IN UINT_32 u4Addr) +{ + if (u4Addr < MAX_PCIE_BUS_STATIC_MAP_ADDR) + return TRUE; + else + return FALSE; +} + +BOOLEAN halChipToStaticMapBusAddr(IN UINT_32 u4ChipAddr, OUT PUINT_32 pu4BusAddr) +{ + UINT_32 u4StartAddr, u4EndAddr, u4BusAddr; + UINT_32 u4Idx = 0; + + if (halIsStaticMapBusAddr(u4ChipAddr)) { + *pu4BusAddr = u4ChipAddr; + return TRUE; + } + + while (TRUE) { + u4StartAddr = arBus2ChipCrMapping[u4Idx].u4ChipAddr; + u4EndAddr = arBus2ChipCrMapping[u4Idx].u4ChipAddr + arBus2ChipCrMapping[u4Idx].u4Range; + + /* End of mapping table */ + if (u4EndAddr == 0x0) + return FALSE; + + + if ((u4ChipAddr >= u4StartAddr) && (u4ChipAddr <= u4EndAddr)) { + u4BusAddr = (u4ChipAddr - u4StartAddr) + arBus2ChipCrMapping[u4Idx].u4BusAddr; + break; + } + + u4Idx++; + } + + *pu4BusAddr = u4BusAddr; + return TRUE; +} + +BOOLEAN halGetDynamicMapReg(IN P_GL_HIF_INFO_T prHifInfo, IN UINT_32 u4ChipAddr, OUT PUINT_32 pu4Value) +{ + UINT_32 u4ReMapReg, u4BusAddr; + ULONG flags; + + if (!halChipToStaticMapBusAddr(MCU_CFG_PCIE_REMAP2, &u4ReMapReg)) + return FALSE; + + spin_lock_irqsave(&prHifInfo->rDynMapRegLock, flags); + + RTMP_IO_WRITE32(prHifInfo, u4ReMapReg, u4ChipAddr & PCIE_REMAP2_MASK); + u4BusAddr = PCIE_REMAP2_BUS_ADDR + (u4ChipAddr & ~PCIE_REMAP2_MASK); + RTMP_IO_READ32(prHifInfo, u4BusAddr, pu4Value); + + spin_unlock_irqrestore(&prHifInfo->rDynMapRegLock, flags); + + return TRUE; +} + +BOOLEAN halSetDynamicMapReg(IN P_GL_HIF_INFO_T prHifInfo, IN UINT_32 u4ChipAddr, IN UINT_32 u4Value) +{ + UINT_32 u4ReMapReg, u4BusAddr; + ULONG flags; + + if (!halChipToStaticMapBusAddr(MCU_CFG_PCIE_REMAP2, &u4ReMapReg)) + return FALSE; + + spin_lock_irqsave(&prHifInfo->rDynMapRegLock, flags); + + RTMP_IO_WRITE32(prHifInfo, u4ReMapReg, u4ChipAddr & PCIE_REMAP2_MASK); + u4BusAddr = PCIE_REMAP2_BUS_ADDR + (u4ChipAddr & ~PCIE_REMAP2_MASK); + RTMP_IO_WRITE32(prHifInfo, u4BusAddr, u4Value); + + spin_unlock_irqrestore(&prHifInfo->rDynMapRegLock, flags); + + return TRUE; +} + +BOOLEAN halIsPendingRx(IN P_ADAPTER_T prAdapter) +{ + /* TODO: check pending Rx if previous Rx handling is break due to lack of SwRfb */ + return FALSE; +} + +UINT_32 halGetValidCoalescingBufSize(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4BufSize; + + if (HIF_TX_COALESCING_BUFFER_SIZE > HIF_RX_COALESCING_BUFFER_SIZE) + u4BufSize = HIF_TX_COALESCING_BUFFER_SIZE; + else + u4BufSize = HIF_RX_COALESCING_BUFFER_SIZE; + + return u4BufSize; +} + +WLAN_STATUS halAllocateIOBuffer(IN P_ADAPTER_T prAdapter) +{ + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS halReleaseIOBuffer(IN P_ADAPTER_T prAdapter) +{ + return WLAN_STATUS_SUCCESS; +} + +VOID halProcessSoftwareInterrupt(IN P_ADAPTER_T prAdapter) +{ + +} + +VOID halDeAggRxPktWorker(struct work_struct *work) +{ + +} + +VOID halRxTasklet(unsigned long data) +{ + +} + +VOID halTxCompleteTasklet(unsigned long data) +{ + +} + +/* Hif power off wifi */ +WLAN_STATUS halHifPowerOffWifi(IN P_ADAPTER_T prAdapter) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DBGLOG(INIT, INFO, "Power off Wi-Fi!\n"); + + nicDisableInterrupt(prAdapter); + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + /* Power off Wi-Fi */ + wlanSendNicPowerCtrlCmd(prAdapter, TRUE); + + wlanClearPendingInterrupt(prAdapter); + + /* prAdapter->fgWiFiInSleepyState = TRUE; */ + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + + rStatus = wlanCheckWifiFunc(prAdapter, FALSE); + + return rStatus; +} + +VOID halPrintHifDbgInfo(IN P_ADAPTER_T prAdapter) +{ + +} + +BOOLEAN halIsTxResourceControlEn(IN P_ADAPTER_T prAdapter) +{ + return FALSE; +} + +VOID halTxResourceResetHwTQCounter(IN P_ADAPTER_T prAdapter) +{ +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/pcie/include/hif.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/pcie/include/hif.h new file mode 100644 index 0000000000000..656b02579d246 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/pcie/include/hif.h @@ -0,0 +1,242 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \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 +*/ + +#ifndef _HIF_H +#define _HIF_H + +#include "hif_pci.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 +******************************************************************************** +*/ +#if defined(_HIF_PCIE) +#define HIF_NAME "PCIE" +#else +#error "No HIF defined!" +#endif + +#define HIF_TX_PREALLOC_DATA_BUFFER 1 + +#define HIF_NUM_OF_QM_RX_PKT_NUM 4096 +#define HIF_IST_LOOP_COUNT 32 +#define HIF_IST_TX_THRESHOLD 1 /* Min msdu count to trigger Tx during INT polling state */ + +#define HIF_TX_BUFF_COUNT_TC0 4096 +#define HIF_TX_BUFF_COUNT_TC1 4096 +#define HIF_TX_BUFF_COUNT_TC2 4096 +#define HIF_TX_BUFF_COUNT_TC3 4096 +#define HIF_TX_BUFF_COUNT_TC4 (TX_RING_SIZE - 1) +#define HIF_TX_BUFF_COUNT_TC5 4096 + +#define HIF_TX_RESOURCE_CTRL 1 /* enable/disable TX resource control */ + +#define HIF_TX_PAGE_SIZE_IN_POWER_OF_2 11 +#define HIF_TX_PAGE_SIZE 2048 /* in unit of bytes */ + +#define HIF_EXTRA_IO_BUFFER_SIZE 0 + +#define HIF_TX_COALESCING_BUFFER_SIZE (TX_BUFFER_NORMSIZE) +#define HIF_RX_COALESCING_BUFFER_SIZE (RX_BUFFER_AGGRESIZE) + +#define HIF_CR4_FWDL_SECTION_NUM 1 +#define HIF_IMG_DL_STATUS_PORT_IDX 1 + +#define HIF_TX_INIT_CMD_PORT TX_RING_FWDL_IDX_3 + +#define HIF_TX_MSDU_TOKEN_NUM 8192 + +#define HIF_TX_PAYLOAD_LENGTH 72 +#define HIF_TX_DESC_PAYLOAD_LENGTH (NIC_TX_HEAD_ROOM + HIF_TX_PAYLOAD_LENGTH) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef struct _MSDU_TOKEN_ENTRY_T { + UINT_32 u4Token; + BOOLEAN fgInUsed; + P_MSDU_INFO_T prMsduInfo; + P_NATIVE_PACKET prPacket; + dma_addr_t rDmaAddr; + UINT_32 u4DmaLength; + dma_addr_t rPktDmaAddr; + UINT_32 u4PktDmaLength; +} MSDU_TOKEN_ENTRY_T, *P_MSDU_TOKEN_ENTRY_T; + +typedef struct _MSDU_TOKEN_INFO_T { + INT_32 i4UsedCnt; + P_MSDU_TOKEN_ENTRY_T aprTokenStack[HIF_TX_MSDU_TOKEN_NUM]; + spinlock_t rTokenLock; + + MSDU_TOKEN_ENTRY_T arToken[HIF_TX_MSDU_TOKEN_NUM]; +} MSDU_TOKEN_INFO_T, *P_MSDU_TOKEN_INFO_T; + +/* host interface's private data structure, which is attached to os glue +** layer info structure. + */ +typedef struct _GL_HIF_INFO_T { + struct pci_dev *pdev; + + PUCHAR CSRBaseAddress; /* PCI MMIO Base Address, all access will use */ + + /* Shared memory of all 1st pre-allocated + * TxBuf associated with each TXD + */ + RTMP_DMABUF TxBufSpace[NUM_OF_TX_RING]; + RTMP_DMABUF TxDescRing[NUM_OF_TX_RING]; /* Shared memory for Tx descriptors */ + RTMP_TX_RING TxRing[NUM_OF_TX_RING]; /* AC0~3 + HCCA */ + spinlock_t TxRingLock[NUM_OF_TX_RING]; /* Rx Ring spinlock */ + + RTMP_DMABUF RxDescRing[2]; /* Shared memory for RX descriptors */ + RTMP_RX_RING RxRing[NUM_OF_RX_RING]; + spinlock_t RxRingLock[NUM_OF_RX_RING]; /* Rx Ring spinlock */ + + BOOLEAN fgIntReadClear; + BOOLEAN fgMbxReadClear; + + UINT_32 u4IntStatus; + + MSDU_TOKEN_INFO_T rTokenInfo; + + spinlock_t rDynMapRegLock; +} GL_HIF_INFO_T, *P_GL_HIF_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 +******************************************************************************** +*/ + +WLAN_STATUS glRegisterBus(probe_card pfProbe, remove_card pfRemove); + +VOID glUnregisterBus(remove_card pfRemove); + +VOID glSetHifInfo(P_GLUE_INFO_T prGlueInfo, ULONG ulCookie); + +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); + +void glGetDev(PVOID ctx, struct device **dev); + +void glGetHifDev(P_GL_HIF_INFO_T prHif, struct device **dev); + +VOID halWpdmaAllocRing(P_GLUE_INFO_T prGlueInfo); +VOID halWpdmaFreeRing(P_GLUE_INFO_T prGlueInfo); +VOID halWpdmaInitRing(P_GLUE_INFO_T prGlueInfo); +VOID halWpdmaProcessCmdDmaDone(IN P_GLUE_INFO_T prGlueInfo, IN UINT_16 u2Port); +VOID halWpdmaProcessDataDmaDone(IN P_GLUE_INFO_T prGlueInfo, IN UINT_16 u2Port); +UINT_32 halWpdmaGetRxDmaDoneCnt(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRingNum); +VOID kalPciUnmapToDev(IN P_GLUE_INFO_T prGlueInfo, IN dma_addr_t rDmaAddr, IN UINT_32 u4Length); + +VOID halInitMsduTokenInfo(IN P_ADAPTER_T prAdapter); +VOID halUninitMsduTokenInfo(IN P_ADAPTER_T prAdapter); +UINT_32 halGetMsduTokenFreeCnt(IN P_ADAPTER_T prAdapter); +P_MSDU_TOKEN_ENTRY_T halGetMsduTokenEntry(IN P_ADAPTER_T prAdapter, UINT_32 u4TokenNum); +P_MSDU_TOKEN_ENTRY_T halAcquireMsduToken(IN P_ADAPTER_T prAdapter); +VOID halReturnMsduToken(IN P_ADAPTER_T prAdapter, UINT_32 u4TokenNum); + +VOID halTxUpdateCutThroughDesc(P_GLUE_INFO_T prGlueInfo, P_MSDU_INFO_T prMsduInfo, + P_MSDU_TOKEN_ENTRY_T prToken); +BOOLEAN halIsStaticMapBusAddr(IN UINT_32 u4Addr); +BOOLEAN halChipToStaticMapBusAddr(IN UINT_32 u4ChipAddr, OUT PUINT_32 pu4BusAddr); +BOOLEAN halGetDynamicMapReg(IN P_GL_HIF_INFO_T prHifInfo, IN UINT_32 u4ChipAddr, OUT PUINT_32 pu4Value); +BOOLEAN halSetDynamicMapReg(IN P_GL_HIF_INFO_T prHifInfo, IN UINT_32 u4ChipAddr, IN UINT_32 u4Value); +VOID halEnhancedWpdmaConfig(P_GLUE_INFO_T prGlueInfo, BOOLEAN enable); +VOID halWpdmaConfig(P_GLUE_INFO_T prGlueInfo, BOOLEAN enable); + +BOOL kalDevReadData(IN P_GLUE_INFO_T prGlueInfo, IN UINT_16 u2Port, IN OUT P_SW_RFB_T prSwRfb); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _HIF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/pcie/include/hif_pci.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/pcie/include/hif_pci.h new file mode 100644 index 0000000000000..998fb44ffc148 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/pcie/include/hif_pci.h @@ -0,0 +1,241 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + Module Name: + hif_pci.h + */ + +#ifndef __HIF_PCI_H__ +#define __HIF_PCI_H__ + +#define NUM_OF_TX_RING 4 +#define NUM_OF_RX_RING 2 + +#define TX_DMA_1ST_BUFFER_SIZE 128 /* only the 1st physical buffer is pre-allocated */ + +#define TX_RING_SIZE 4095 +#define RX_RING_SIZE 256 /* Max Rx ring size */ + +#define RX_RING0_SIZE 256 /* Data Rx ring */ +#define RX_RING1_SIZE 16 /* Event/MSDU_report Rx ring */ + +#define TXD_SIZE 16 /* TXD_SIZE = TxD + TxInfo */ +#define RXD_SIZE 16 + +#define RX_BUFFER_AGGRESIZE 3840 +#define RX_BUFFER_NORMSIZE 3840 +#define TX_BUFFER_NORMSIZE 3840 + +#define INC_RING_INDEX(_idx, _RingSize) \ +{ \ + (_idx) = (_idx+1) % (_RingSize); \ +} + +#define RTMP_IO_READ32(_A, _R, _pV) \ +{ \ + (*(_pV) = readl((void *)((_A)->CSRBaseAddress + (_R)))); \ +} + +#define RTMP_IO_WRITE32(_A, _R, _V) \ +{ \ + writel(_V, (void *)((_A)->CSRBaseAddress + (_R))); \ +} + +#define MAX_PCIE_BUS_STATIC_MAP_ADDR 0x00040000 + +#define MT_RINGREG_DIFF 0x10 + +#define MT_TX_RING_BASE WPDMA_TX_RING0_CTRL0 +#define MT_TX_RING_PTR WPDMA_TX_RING0_CTRL0 +#define MT_TX_RING_CNT WPDMA_TX_RING0_CTRL1 +#define MT_TX_RING_CIDX WPDMA_TX_RING0_CTRL2 +#define MT_TX_RING_DIDX WPDMA_TX_RING0_CTRL3 + +#define MT_RX_RING_BASE WPDMA_RX_RING0_CTRL0 +#define MT_RX_RING_PTR WPDMA_RX_RING0_CTRL0 +#define MT_RX_RING_CNT WPDMA_RX_RING0_CTRL1 +#define MT_RX_RING_CIDX WPDMA_RX_RING0_CTRL2 +#define MT_RX_RING_DIDX WPDMA_RX_RING0_CTRL3 + +typedef enum _ENUM_TX_RING_IDX_T { + TX_RING_DATA0_IDX_0 = 0, + TX_RING_DATA1_IDX_1, + TX_RING_CMD_IDX_2, + TX_RING_FWDL_IDX_3, +} ENUM_TX_RING_IDX__T; + +typedef enum _ENUM_RX_RING_IDX_T { + RX_RING_DATA_IDX_0 = 0, + RX_RING_EVT_IDX_1 +} ENUM_RX_RING_IDX_T; + +/* ============================================================================ +* PCI/RBUS TX / RX Frame Descriptors format +* +* Memory Layout +* +* 1. Tx Descriptor +* TxD (12 bytes) + TXINFO (4 bytes) +* 2. Packet Buffer +* TXWI + 802.11 +* 31 0 +* +--------------------------------------------------------------------------+ +* | SDP0[31:0] | +* +-+--+---------------------+-+--+------------------------------------------+ +* |D |L0| SDL0[13:0] |B|L1| SDL1[13:0] | +* +-+--+---------------------+-+--+------------------------------------------+ +* | SDP1[31:0] | +* +--------------------------------------------------------------------------+ +* | TXINFO | +* +--------------------------------------------------------------------------+ +* ========================================================================= +*/ +/* + * TX descriptor format for Tx Data/Mgmt Rings + */ +typedef struct _TXD_STRUCT { + /* Word 0 */ + UINT_32 SDPtr0; + + /* Word 1 */ + UINT_32 SDLen1:14; + UINT_32 LastSec1:1; + UINT_32 Burst:1; + UINT_32 SDLen0:14; + UINT_32 LastSec0:1; + UINT_32 DMADONE:1; + /*Word2 */ + UINT_32 SDPtr1; +} TXD_STRUCT; + +/* + * Rx descriptor format for Rx Rings + */ +typedef struct _RXD_STRUCT { + /* Word 0 */ + UINT_32 SDP0; + + /* Word 1 */ + UINT_32 SDL1:14; + UINT_32 LS1:1; + UINT_32 BURST:1; + UINT_32 SDL0:14; + UINT_32 LS0:1; + UINT_32 DDONE:1; + + /* Word 2 */ + UINT_32 SDP1; +} RXD_STRUCT; + +/* +* Data buffer for DMA operation, the buffer must be contiguous physical memory +* Both DMA to / from CPU use the same structure. +*/ +typedef struct _RTMP_DMABUF { + ULONG AllocSize; + PVOID AllocVa; /* TxBuf virtual address */ + dma_addr_t AllocPa; /* TxBuf physical address */ +} RTMP_DMABUF, *PRTMP_DMABUF; + +/* +* Control block (Descriptor) for all ring descriptor DMA operation, buffer must be +* contiguous physical memory. NDIS_PACKET stored the binding Rx packet descriptor +* which won't be released, driver has to wait until upper layer return the packet +* before giveing up this rx ring descriptor to ASIC. NDIS_BUFFER is assocaited pair +* to describe the packet buffer. For Tx, NDIS_PACKET stored the tx packet descriptor +* which driver should ACK upper layer when the tx is physically done or failed. +*/ +typedef struct _RTMP_DMACB { + ULONG AllocSize; /* Control block size */ + PVOID AllocVa; /* Control block virtual address */ + dma_addr_t AllocPa; /* Control block physical address */ + PVOID pPacket; + PVOID pBuffer; + dma_addr_t PacketPa; + RTMP_DMABUF DmaBuf; /* Associated DMA buffer structure */ +} RTMP_DMACB, *PRTMP_DMACB; + +typedef struct _RTMP_TX_RING { + RTMP_DMACB Cell[TX_RING_SIZE]; + UINT_32 TxCpuIdx; + UINT_32 TxDmaIdx; + UINT_32 TxSwUsedIdx; + UINT_32 u4UsedCnt; + UINT_32 hw_desc_base; + UINT_32 hw_cidx_addr; + UINT_32 hw_didx_addr; + UINT_32 hw_cnt_addr; +} RTMP_TX_RING, *P_RTMP_TX_RING; + +typedef struct _RTMP_RX_RING { + RTMP_DMACB Cell[RX_RING_SIZE]; + UINT_32 RxCpuIdx; + UINT_32 RxDmaIdx; + INT_32 RxSwReadIdx; /* software next read index */ + UINT_32 u4BufSize; + UINT_32 u4RingSize; + BOOLEAN fgRxSegPkt; + + UINT_32 hw_desc_base; + UINT_32 hw_cidx_addr; + UINT_32 hw_didx_addr; + UINT_32 hw_cnt_addr; +} RTMP_RX_RING, *P_RTMP_RX_RING; + +typedef struct _PCIE_CHIP_CR_MAPPING { + UINT_32 u4ChipAddr; + UINT_32 u4BusAddr; + UINT_32 u4Range; +} PCIE_CHIP_CR_MAPPING, *P_PCIE_CHIP_CR_MAPPING; + + +#endif /* HIF_PCI_H__ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/pcie/include/mtk_porting.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/pcie/include/mtk_porting.h new file mode 100644 index 0000000000000..89c2f378f3e70 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/pcie/include/mtk_porting.h @@ -0,0 +1,92 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* porting layer */ +/* Android */ + +#ifndef _MTK_PORTING_H_ +#define _MTK_PORTING_H_ + +#include /* include stddef.h for NULL */ + +/* 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 INT_32(*MUTEX_DESTROY) (MTK_WCN_MUTEX mtx); +typedef INT_32(*MUTEX_LOCK) (MTK_WCN_MUTEX mtx); +typedef INT_32(*MUTEX_UNLOCK) (MTK_WCN_MUTEX mtx, unsigned long flags); +/* debug */ +typedef INT_32(*DBG_PRINT) (const char *str, ...); +typedef INT_32(*DBG_ASSERT) (INT_32 expr, const char *file, INT_32 line); +/* timer */ +typedef void (*MTK_WCN_TIMER_CB) (void); +typedef MTK_WCN_TIMER(*TIMER_CREATE) (const char *const name); +typedef INT_32(*TIMER_DESTROY) (MTK_WCN_TIMER tmr); +typedef INT_32(*TIMER_START) (MTK_WCN_TIMER tmr, UINT_32 timeout, MTK_WCN_TIMER_CB tmr_cb, void *param); +typedef INT_32(*TIMER_STOP) (MTK_WCN_TIMER tmr); +/* kernel lib */ +typedef void *(*SYS_MEMCPY) (void *dest, const void *src, UINT_32 n); +typedef void *(*SYS_MEMSET) (void *s, INT_32 c, UINT_32 n); +typedef INT_32(*SYS_SPRINTF) (char *str, const char *format, ...); + +#endif /* _MTK_PORTING_H_ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/pcie/pcie.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/pcie/pcie.c new file mode 100644 index 0000000000000..5e3ff7b2a65f5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/pcie/pcie.c @@ -0,0 +1,1165 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** +*[File] pcie.c +*[Version] v1.0 +*[Revision Date] 2010-03-01 +*[Author] +*[Description] +* The program provides PCIE HIF driver +*[Copyright] +* Copyright (C) 2010 MediaTek Incorporation. All Rights Reserved. +******************************************************************************/ + + +/******************************************************************************* +* C O M P I L E 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 "hif_pci.h" + +#include "precomp.h" + +#include +#ifndef CONFIG_X86 +#include +#endif + +#include "mt66xx_reg.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define MTK_PCI_VENDOR_ID 0x14C3 +#define NIC6632_PCIe_DEVICE_ID 0x6632 +#define NIC7668_PCIe_DEVICE_ID 0x7668 + +static const struct pci_device_id mtk_pci_ids[] = { + { PCI_DEVICE(MTK_PCI_VENDOR_ID, NIC6632_PCIe_DEVICE_ID), + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_mt6632}, + { PCI_DEVICE(MTK_PCI_VENDOR_ID, NIC7668_PCIe_DEVICE_ID), + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_mt7668}, + { /* end: all zeroes */ }, +}; + +MODULE_DEVICE_TABLE(pci, mtk_pci_ids); + +/******************************************************************************* +* 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 probe_card pfWlanProbe; +static remove_card pfWlanRemove; + +static struct pci_driver mtk_pci_driver = { + .name = "wlan", + .id_table = mtk_pci_ids, + .probe = NULL, + .remove = NULL, +}; + +static BOOLEAN g_fgDriverProbed = FALSE; +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a PCIE interrupt callback function +* +* \param[in] func pointer to PCIE handle +* +* \return void +*/ +/*----------------------------------------------------------------------------*/ +static PUCHAR CSRBaseAddress; + +static irqreturn_t mtk_pci_interrupt(int irq, void *dev_instance) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4RegValue; + + prGlueInfo = (P_GLUE_INFO_T) dev_instance; + if (!prGlueInfo) { + DBGLOG(HAL, INFO, "No glue info in mtk_pci_interrupt()\n"); + return IRQ_NONE; + } + + HAL_MCR_RD(prGlueInfo->prAdapter, WPDMA_INT_STA, &u4RegValue); + if (!u4RegValue) + return IRQ_HANDLED; + + halDisableInterrupt(prGlueInfo->prAdapter); + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(HAL, INFO, "GLUE_FLAG_HALT skip INT\n"); + return IRQ_NONE; + } + + DBGLOG(HAL, TRACE, "%s INT[0x%08x]\n", __func__, u4RegValue); + + kalSetIntEvent(prGlueInfo); + + return IRQ_HANDLED; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a PCIE probe function +* +* \param[in] func pointer to PCIE handle +* \param[in] id pointer to PCIE device id table +* +* \return void +*/ +/*----------------------------------------------------------------------------*/ +static int mtk_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + int ret = 0; + + ASSERT(pdev); + ASSERT(id); + + ret = pci_enable_device(pdev); + + if (ret) { + DBGLOG(INIT, INFO, "pci_enable_device failed!\n"); + goto out; + } + + DBGLOG(INIT, INFO, "pci_enable_device done!\n"); + + if (pfWlanProbe((PVOID) pdev, (PVOID) id->driver_data) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, INFO, "pfWlanProbe fail!call pfWlanRemove()\n"); + pfWlanRemove(); + ret = -1; + } else { + g_fgDriverProbed = TRUE; + } +out: + DBGLOG(INIT, INFO, "mtk_pci_probe() done(%d)\n", ret); + + return ret; +} + +static void mtk_pci_remove(struct pci_dev *pdev) +{ + ASSERT(pdev); + + if (g_fgDriverProbed) + pfWlanRemove(); + DBGLOG(INIT, INFO, "pfWlanRemove done\n"); + + /* Unmap CSR base address */ + iounmap(CSRBaseAddress); + + /* release memory region */ + release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); + + pci_disable_device(pdev); + DBGLOG(INIT, INFO, "mtk_pci_remove() done\n"); +} + +static int mtk_pci_suspend(struct pci_dev *pdev, pm_message_t state) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)pci_get_drvdata(pdev); + + if (!prGlueInfo) { + DBGLOG(HAL, ERROR, "pci_get_drvdata fail!\n"); + return -1; + } + + wlanSuspendPmHandle(prGlueInfo); + + if (prGlueInfo->prAdapter->fgIsFwOwn == FALSE) + RECLAIM_POWER_CONTROL_TO_PM(prGlueInfo->prAdapter, FALSE); + + pci_save_state(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + prGlueInfo->prAdapter->fgIsFwOwn = TRUE; + + DBGLOG(HAL, STATE, "mtk_pci_suspend() done!\n"); + return 0; +} + +int mtk_pci_resume(struct pci_dev *pdev) +{ + UINT_32 i; + UINT_32 phy_addr, offset; + RTMP_TX_RING *tx_ring; + RTMP_RX_RING *rx_ring; + P_GL_HIF_INFO_T prHifInfo; + P_GLUE_INFO_T prGlueInfo = NULL; + + prGlueInfo = (P_GLUE_INFO_T)pci_get_drvdata(pdev); + + if (!prGlueInfo) { + DBGLOG(HAL, ERROR, "pci_get_drvdata fail!\n"); + return -1; + } + + prHifInfo = &prGlueInfo->rHifInfo; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + /* Restore PDMA settings */ + for (i = 0; i < NUM_OF_TX_RING; i++) { + tx_ring = &prHifInfo->TxRing[i]; + offset = i * MT_RINGREG_DIFF; + phy_addr = prHifInfo->TxRing[i].Cell[0].AllocPa; + tx_ring->TxSwUsedIdx = 0; + tx_ring->u4UsedCnt = 0; + tx_ring->TxCpuIdx = 0; + tx_ring->hw_desc_base = MT_TX_RING_BASE + offset; + tx_ring->hw_cidx_addr = MT_TX_RING_CIDX + offset; + tx_ring->hw_didx_addr = MT_TX_RING_DIDX + offset; + tx_ring->hw_cnt_addr = MT_TX_RING_CNT + offset; + kalDevRegWrite(prGlueInfo, tx_ring->hw_desc_base, phy_addr); + kalDevRegWrite(prGlueInfo, tx_ring->hw_cidx_addr, tx_ring->TxCpuIdx); + kalDevRegWrite(prGlueInfo, tx_ring->hw_cnt_addr, TX_RING_SIZE); + } + + for (i = 0; i < NUM_OF_RX_RING; i++) { + rx_ring = &prHifInfo->RxRing[i]; + offset = i * MT_RINGREG_DIFF; + phy_addr = rx_ring->Cell[0].AllocPa; + rx_ring->RxSwReadIdx = 0; + rx_ring->RxCpuIdx = rx_ring->u4RingSize - 1; + rx_ring->hw_desc_base = MT_RX_RING_BASE + offset; + rx_ring->hw_cidx_addr = MT_RX_RING_CIDX + offset; + rx_ring->hw_didx_addr = MT_RX_RING_DIDX + offset; + rx_ring->hw_cnt_addr = MT_RX_RING_CNT + offset; + kalDevRegWrite(prGlueInfo, rx_ring->hw_desc_base, phy_addr); + kalDevRegWrite(prGlueInfo, rx_ring->hw_cidx_addr, rx_ring->RxCpuIdx); + kalDevRegWrite(prGlueInfo, rx_ring->hw_cnt_addr, rx_ring->u4RingSize); + } + + halWpdmaSetup(prGlueInfo, TRUE); + halEnableInterrupt(prGlueInfo->prAdapter); + DBGLOG(HAL, STATE, "PDMA restore done\n"); + + if (prGlueInfo->prAdapter->fgIsFwOwn == FALSE) { + prGlueInfo->prAdapter->fgIsFwOwn = TRUE; + halSetDriverOwn(prGlueInfo->prAdapter); + } else { + ACQUIRE_POWER_CONTROL_FROM_PM(prGlueInfo->prAdapter); + } + + kalMsleep(5); + + wlanResumePmHandle(prGlueInfo); + + DBGLOG(HAL, STATE, "mtk_pci_resume done\n"); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will register pci 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 pci bus +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS glRegisterBus(probe_card pfProbe, remove_card pfRemove) +{ + int ret = 0; + + ASSERT(pfProbe); + ASSERT(pfRemove); + + /* printk(KERN_INFO "mtk_pci: MediaTek PCIE WLAN driver\n"); */ + /* printk(KERN_INFO "mtk_pci: Copyright MediaTek Inc.\n"); */ + + pfWlanProbe = pfProbe; + pfWlanRemove = pfRemove; + + mtk_pci_driver.probe = mtk_pci_probe; + mtk_pci_driver.remove = mtk_pci_remove; + + mtk_pci_driver.suspend = mtk_pci_suspend; + mtk_pci_driver.resume = mtk_pci_resume; + + ret = (pci_register_driver(&mtk_pci_driver) == 0) ? WLAN_STATUS_SUCCESS : WLAN_STATUS_FAILURE; + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will unregister pci bus to the os +* +* \param[in] pfRemove Function pointer to remove card +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glUnregisterBus(remove_card pfRemove) +{ + if (g_fgDriverProbed) { + pfRemove(); + g_fgDriverProbed = FALSE; + } + pci_unregister_driver(&mtk_pci_driver); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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, ULONG ulCookie) +{ + P_GL_HIF_INFO_T prHif = NULL; + + prHif = &prGlueInfo->rHifInfo; + + prHif->pdev = (struct pci_dev *)ulCookie; + + prHif->CSRBaseAddress = CSRBaseAddress; + + pci_set_drvdata(prHif->pdev, prGlueInfo); + + SET_NETDEV_DEV(prGlueInfo->prDevHandler, &prHif->pdev->dev); + + halWpdmaAllocRing(prGlueInfo); + + halWpdmaInitRing(prGlueInfo); + + spin_lock_init(&prHif->rDynMapRegLock); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function clears hif related info. +* +* \param[in] prGlueInfo Pointer to glue info structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glClearHifInfo(P_GLUE_INFO_T prGlueInfo) +{ + halUninitMsduTokenInfo(prGlueInfo->prAdapter); + halWpdmaFreeRing(prGlueInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ + int ret = 0; + struct pci_dev *pdev = NULL; + + ASSERT(pvData); + + pdev = (struct pci_dev *)pvData; + + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (ret != 0) { + DBGLOG(INIT, INFO, "set DMA mask failed!errno=%d\n", ret); + return FALSE; + } + + ret = pci_request_regions(pdev, pci_name(pdev)); + if (ret != 0) { + DBGLOG(INIT, INFO, "Request PCI resource failed, errno=%d!\n", ret); + goto err_out; + } + + /* map physical address to virtual address for accessing register */ + CSRBaseAddress = (PUCHAR) ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); + DBGLOG(INIT, INFO, "ioremap for device %s, region 0x%lX @ 0x%lX\n", + pci_name(pdev), (ULONG) pci_resource_len(pdev, 0), (ULONG) pci_resource_start(pdev, 0)); + if (!CSRBaseAddress) { + DBGLOG(INIT, INFO, "ioremap failed for device %s, region 0x%lX @ 0x%lX\n", + pci_name(pdev), (ULONG) pci_resource_len(pdev, 0), (ULONG) pci_resource_start(pdev, 0)); + goto err_out_free_res; + } + + /* Set DMA master */ + pci_set_master(pdev); + + return TRUE; +#if 0 +err_out_iounmap: + iounmap((void *)(CSRBaseAddress)); + release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); +#endif +err_out_free_res: + pci_release_regions(pdev); + +err_out: + pci_disable_device(pdev); + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus operation and release resources. +* +* \param[in] pvData A pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glBusRelease(PVOID pvData) +{ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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; + + struct net_device *prNetDevice = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_GL_HIF_INFO_T prHifInfo = NULL; + struct pci_dev *pdev = 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; + pdev = prHifInfo->pdev; + +#if defined(CONFIG_ARCH_MT7623) || defined(CONFIG_ARCH_MT7621) + ret = request_irq(pdev->irq, mtk_pci_interrupt, IRQF_SHARED | + IRQF_TRIGGER_FALLING, prNetDevice->name, prGlueInfo); +#else + ret = request_irq(pdev->irq, mtk_pci_interrupt, IRQF_SHARED, prNetDevice->name, prGlueInfo); +#endif + + if (ret != 0) + DBGLOG(INIT, INFO, "glBusSetIrq: request_irq ERROR(%d)\n", ret); + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus interrupt operation and disable interrupt handling for os. +* +* \param[in] pvData A pointer to struct net_device. +* \param[in] pvCookie Private data for pfnIsr function. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glBusFreeIrq(PVOID pvData, PVOID pvCookie) +{ + struct net_device *prNetDevice = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_GL_HIF_INFO_T prHifInfo = NULL; + struct pci_dev *pdev = NULL; + + ASSERT(pvData); + if (!pvData) { + DBGLOG(INIT, INFO, "%s null pvData\n", __func__); + return; + } + prNetDevice = (struct net_device *)pvData; + prGlueInfo = (P_GLUE_INFO_T) pvCookie; + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(INIT, INFO, "%s no glue info\n", __func__); + return; + } + + prHifInfo = &prGlueInfo->rHifInfo; + pdev = prHifInfo->pdev; + + synchronize_irq(pdev->irq); + free_irq(pdev->irq, prGlueInfo); +} + +BOOLEAN glIsReadClearReg(UINT_32 u4Address) +{ + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ + P_GL_HIF_INFO_T prHifInfo = NULL; + UINT_32 u4BusAddr = u4Register; + BOOLEAN fgResult = TRUE; + + ASSERT(prGlueInfo); + ASSERT(pu4Value); + + prHifInfo = &prGlueInfo->rHifInfo; + + if (halChipToStaticMapBusAddr(u4Register, &u4BusAddr)) { + /* Static mapping */ + RTMP_IO_READ32(prHifInfo, u4BusAddr, pu4Value); + } else { + /* Dynamic mapping */ + fgResult = halGetDynamicMapReg(prHifInfo, u4BusAddr, pu4Value); + } + + if ((u4Register & 0xFFFFF000) != PCIE_HIF_BASE) + DBGLOG(HAL, INFO, "Get CR[0x%08x/0x%08x] value[0x%08x]\n", u4Register, u4BusAddr, *pu4Value); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ + P_GL_HIF_INFO_T prHifInfo = NULL; + UINT_32 u4BusAddr = u4Register; + BOOLEAN fgResult = TRUE; + + ASSERT(prGlueInfo); + + prHifInfo = &prGlueInfo->rHifInfo; + + if (halChipToStaticMapBusAddr(u4Register, &u4BusAddr)) { + /* Static mapping */ + RTMP_IO_WRITE32(prHifInfo, u4BusAddr, u4Value); + } else { + /* Dynamic mapping */ + fgResult = halSetDynamicMapReg(prHifInfo, u4BusAddr, u4Value); + } + + if ((u4Register & 0xFFFFF000) != PCIE_HIF_BASE) + DBGLOG(HAL, INFO, "Set CR[0x%08x/0x%08x] value[0x%08x]\n", u4Register, u4BusAddr, u4Value); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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_32 u4Len, + OUT PUINT_8 pucBuf, IN UINT_32 u4ValidOutBufSize) +{ + P_GL_HIF_INFO_T prHifInfo = NULL; + PUINT_8 pucDst = NULL; + RXD_STRUCT *pRxD; + P_RTMP_RX_RING prRxRing; + spinlock_t *pRxRingLock; + PVOID pRxPacket = NULL; + RTMP_DMACB *pRxCell; + struct pci_dev *pdev = NULL; + BOOL fgRet = TRUE; + ULONG flags = 0; + PRTMP_DMABUF prDmaBuf; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + ASSERT(pucBuf); + pucDst = pucBuf; + + ASSERT(u4Len <= u4ValidOutBufSize); + + pdev = prHifInfo->pdev; + + prRxRing = &prHifInfo->RxRing[u2Port]; + pRxRingLock = &prHifInfo->RxRingLock[u2Port]; + + spin_lock_irqsave(pRxRingLock, flags); + + pRxCell = &prRxRing->Cell[prRxRing->RxSwReadIdx]; + + /* Point to Rx indexed rx ring descriptor */ + pRxD = (RXD_STRUCT *) pRxCell->AllocVa; + + if (pRxD->DDONE == 0) { + /* Get how may packets had been received */ + kalDevRegRead(prGlueInfo, prRxRing->hw_didx_addr, &prRxRing->RxDmaIdx); + + DBGLOG(HAL, TRACE, "Rx DMA done P[%u] DMA[%u] SW_RD[%u]\n", u2Port, + prRxRing->RxDmaIdx, prRxRing->RxSwReadIdx); + fgRet = FALSE; + goto done; + } + + prDmaBuf = &pRxCell->DmaBuf; + + pci_unmap_single(pdev, prDmaBuf->AllocPa, prDmaBuf->AllocSize, PCI_DMA_FROMDEVICE); + + if (pRxD->LS0 == 0 || prRxRing->fgRxSegPkt) { + /* Rx segmented packet */ + + DBGLOG(HAL, WARN, "Skip Rx segmented packet, SDL0[%u] LS0[%u]\n", pRxD->SDL0, pRxD->LS0); + if (pRxD->LS0 == 1) { + /* Last segmented packet */ + prRxRing->fgRxSegPkt = FALSE; + } else { + /* Segmented packet */ + prRxRing->fgRxSegPkt = TRUE; + } + + fgRet = FALSE; + goto skip; + } + + if (pRxD->SDL0 <= u4Len) { + pRxPacket = pRxCell->pPacket; + ASSERT(pRxPacket); + kalMemCopy(pucDst, ((UCHAR *) ((struct sk_buff *)(pRxPacket))->data), pRxD->SDL0); + } else + DBGLOG(HAL, WARN, "Skip Rx packet, SDL0[%u] > SwRfb max len[%u]\n", pRxD->SDL0, u4Len); + +skip: + prDmaBuf->AllocVa = ((struct sk_buff *)pRxCell->pPacket)->data; + prDmaBuf->AllocPa = pci_map_single(pdev, prDmaBuf->AllocVa, prDmaBuf->AllocSize, PCI_DMA_FROMDEVICE); + + pRxD->SDP0 = prDmaBuf->AllocPa; + pRxD->SDL0 = prRxRing->u4BufSize; + pRxD->DDONE = 0; + + prRxRing->RxCpuIdx = prRxRing->RxSwReadIdx; + kalDevRegWrite(prGlueInfo, prRxRing->hw_cidx_addr, prRxRing->RxCpuIdx); + INC_RING_INDEX(prRxRing->RxSwReadIdx, prRxRing->u4RingSize); + +done: + spin_unlock_irqrestore(pRxRingLock, flags); + + return fgRet; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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_32 u4Len, IN PUINT_8 pucBuf, IN UINT_32 u4ValidInBufSize) +{ + P_GL_HIF_INFO_T prHifInfo = NULL; + PUINT_8 pucSrc = NULL; + UINT_32 u4SrcLen = u4Len; + ULONG flags = 0; + UINT_32 SwIdx = 0; + P_RTMP_TX_RING prTxRing; + spinlock_t *prTxRingLock; + TXD_STRUCT *pTxD; + struct pci_dev *pdev = NULL; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + ASSERT(pucBuf); + + ASSERT(u4Len <= u4ValidInBufSize); + + pucSrc = kalMemAlloc(u4SrcLen, PHY_MEM_TYPE); + ASSERT(pucSrc); + + kalMemCopy(pucSrc, pucBuf, u4SrcLen); + + pdev = prHifInfo->pdev; + prTxRing = &prHifInfo->TxRing[u2Port]; + prTxRingLock = &prHifInfo->TxRingLock[u2Port]; + + spin_lock_irqsave((spinlock_t *)prTxRingLock, flags); + + SwIdx = prTxRing->TxCpuIdx; + pTxD = (TXD_STRUCT *) prTxRing->Cell[SwIdx].AllocVa; + + prTxRing->Cell[SwIdx].pPacket = NULL; + prTxRing->Cell[SwIdx].pBuffer = pucSrc; + prTxRing->Cell[SwIdx].PacketPa = pci_map_single(pdev, pucSrc, u4SrcLen, PCI_DMA_TODEVICE); + + pTxD->LastSec0 = 1; + pTxD->LastSec1 = 0; + pTxD->SDLen0 = u4SrcLen; + pTxD->SDLen1 = 0; + pTxD->SDPtr0 = prTxRing->Cell[SwIdx].PacketPa; + pTxD->SDPtr1 = 0; + pTxD->Burst = 0; + pTxD->DMADONE = 0; + + /* Increase TX_CTX_IDX, but write to register later. */ + INC_RING_INDEX(prTxRing->TxCpuIdx, TX_RING_SIZE); + + prTxRing->u4UsedCnt++; + + kalDevRegWrite(prGlueInfo, prTxRing->hw_cidx_addr, prTxRing->TxCpuIdx); + + spin_unlock_irqrestore((spinlock_t *)prTxRingLock, flags); + + return TRUE; +} + +VOID kalDevReadIntStatus(IN P_ADAPTER_T prAdapter, OUT PUINT_32 pu4IntStatus) +{ + UINT_32 u4RegValue; + P_GL_HIF_INFO_T prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + *pu4IntStatus = 0; + + HAL_MCR_RD(prAdapter, WPDMA_INT_STA, &u4RegValue); + + if (HAL_IS_RX_DONE_INTR(u4RegValue)) + *pu4IntStatus |= WHISR_RX0_DONE_INT; + + if (HAL_IS_TX_DONE_INTR(u4RegValue)) + *pu4IntStatus |= WHISR_TX_DONE_INT; + + prHifInfo->u4IntStatus = u4RegValue; + + /* clear interrupt */ + HAL_MCR_WR(prAdapter, WPDMA_INT_STA, u4RegValue); + +} + +BOOL kalDevWriteCmd(IN P_GLUE_INFO_T prGlueInfo, IN P_CMD_INFO_T prCmdInfo, IN UINT_8 ucTC) +{ + P_GL_HIF_INFO_T prHifInfo = NULL; + ULONG flags = 0; + UINT_32 SwIdx = 0; + P_RTMP_TX_RING prTxRing; + spinlock_t *prTxRingLock; + TXD_STRUCT *pTxD; + struct pci_dev *pdev = NULL; + UINT_16 u2Port = TX_RING_CMD_IDX_2; + UINT_32 u4TotalLen; + PUINT_8 pucSrc = NULL; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + pdev = prHifInfo->pdev; + prTxRing = &prHifInfo->TxRing[u2Port]; + prTxRingLock = &prHifInfo->TxRingLock[u2Port]; + + u4TotalLen = prCmdInfo->u4TxdLen + prCmdInfo->u4TxpLen; + pucSrc = kalMemAlloc(u4TotalLen, PHY_MEM_TYPE); + ASSERT(pucSrc); + + kalMemCopy(pucSrc, prCmdInfo->pucTxd, prCmdInfo->u4TxdLen); + kalMemCopy(pucSrc + prCmdInfo->u4TxdLen, prCmdInfo->pucTxp, prCmdInfo->u4TxpLen); + + spin_lock_irqsave((spinlock_t *)prTxRingLock, flags); + + SwIdx = prTxRing->TxCpuIdx; + pTxD = (TXD_STRUCT *) prTxRing->Cell[SwIdx].AllocVa; + + prTxRing->Cell[SwIdx].pPacket = (PVOID)prCmdInfo; + prTxRing->Cell[SwIdx].pBuffer = pucSrc; + prTxRing->Cell[SwIdx].PacketPa = pci_map_single(pdev, pucSrc, u4TotalLen, PCI_DMA_TODEVICE); + + pTxD->SDPtr0 = prTxRing->Cell[SwIdx].PacketPa; + pTxD->SDLen0 = u4TotalLen; + pTxD->SDPtr1 = 0; + pTxD->SDLen1 = 0; + pTxD->LastSec0 = 1; + pTxD->LastSec1 = 0; + pTxD->Burst = 0; + pTxD->DMADONE = 0; + + /* Increase TX_CTX_IDX, but write to register later. */ + INC_RING_INDEX(prTxRing->TxCpuIdx, TX_RING_SIZE); + + prTxRing->u4UsedCnt++; + kalDevRegWrite(prGlueInfo, prTxRing->hw_cidx_addr, prTxRing->TxCpuIdx); + + spin_unlock_irqrestore((spinlock_t *)prTxRingLock, flags); + + DBGLOG(HAL, TRACE, "%s: CmdInfo[0x%p], TxD[0x%p/%u] TxP[0x%p/%u] CPU idx[%u] Used[%u]\n", __func__, + prCmdInfo, prCmdInfo->pucTxd, prCmdInfo->u4TxdLen, prCmdInfo->pucTxp, prCmdInfo->u4TxpLen, + SwIdx, prTxRing->u4UsedCnt); + + return TRUE; +} + +BOOL kalDevWriteData(IN P_GLUE_INFO_T prGlueInfo, IN P_MSDU_INFO_T prMsduInfo) +{ + P_GL_HIF_INFO_T prHifInfo = NULL; + ULONG flags = 0; + UINT_32 SwIdx = 0; + P_RTMP_TX_RING prTxRing; + spinlock_t *prTxRingLock; + TXD_STRUCT *pTxD; + struct pci_dev *pdev = NULL; + UINT_16 u2Port = TX_RING_DATA0_IDX_0; + UINT_32 u4TotalLen; + struct sk_buff *skb; + PUINT_8 pucSrc; + P_MSDU_TOKEN_ENTRY_T prToken; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + pdev = prHifInfo->pdev; + prTxRing = &prHifInfo->TxRing[u2Port]; + prTxRingLock = &prHifInfo->TxRingLock[u2Port]; + + skb = (struct sk_buff *)prMsduInfo->prPacket; + pucSrc = skb->data; + u4TotalLen = skb->len; + + /* Acquire MSDU token */ + prToken = halAcquireMsduToken(prGlueInfo->prAdapter); + +#if HIF_TX_PREALLOC_DATA_BUFFER + kalMemCopy(prToken->prPacket, pucSrc, u4TotalLen); +#else + prToken->prMsduInfo = prMsduInfo; + prToken->prPacket = pucSrc; + prToken->u4DmaLength = u4TotalLen; + prMsduInfo->prToken = prToken; +#endif + + /* Update Tx descriptor */ + halTxUpdateCutThroughDesc(prGlueInfo, prMsduInfo, prToken); + + prToken->rDmaAddr = pci_map_single(pdev, prToken->prPacket, prToken->u4DmaLength, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(pdev, prToken->rDmaAddr)) { + DBGLOG(HAL, ERROR, "pci_map_single() error!\n"); + halReturnMsduToken(prGlueInfo->prAdapter, prToken->u4Token); + return FALSE; + } + + SwIdx = prTxRing->TxCpuIdx; + pTxD = (TXD_STRUCT *) prTxRing->Cell[SwIdx].AllocVa; + + pTxD->SDPtr0 = prToken->rDmaAddr; + pTxD->SDLen0 = HIF_TX_DESC_PAYLOAD_LENGTH; + pTxD->SDPtr1 = 0; + pTxD->SDLen1 = 0; + pTxD->LastSec0 = 1; + pTxD->LastSec1 = 0; + pTxD->Burst = 0; + pTxD->DMADONE = 0; + + /* Increase TX_CTX_IDX, but write to register later. */ + INC_RING_INDEX(prTxRing->TxCpuIdx, TX_RING_SIZE); + + /* Update HW Tx DMA ring */ + spin_lock_irqsave((spinlock_t *)prTxRingLock, flags); + + prTxRing->u4UsedCnt++; + kalDevRegWrite(prGlueInfo, prTxRing->hw_cidx_addr, prTxRing->TxCpuIdx); + + spin_unlock_irqrestore((spinlock_t *)prTxRingLock, flags); + + DBGLOG(HAL, TRACE, "Tx Data: Msdu[0x%p], Tok[%u] TokFree[%u] CPU idx[%u] Used[%u] TxDone[%u]\n", + prMsduInfo, prToken->u4Token, halGetMsduTokenFreeCnt(prGlueInfo->prAdapter), + SwIdx, prTxRing->u4UsedCnt, (prMsduInfo->pfTxDoneHandler ? TRUE : FALSE)); + + DBGLOG_MEM32(HAL, TRACE, pucSrc, HIF_TX_DESC_PAYLOAD_LENGTH); + + nicTxReleaseResource(prGlueInfo->prAdapter, prMsduInfo->ucTC, + nicTxGetPageCount(prMsduInfo->u2FrameLength, TRUE), TRUE); + +#if HIF_TX_PREALLOC_DATA_BUFFER + if (!prMsduInfo->pfTxDoneHandler) { + nicTxFreePacket(prGlueInfo->prAdapter, prMsduInfo, FALSE); + nicTxReturnMsduInfo(prGlueInfo->prAdapter, prMsduInfo); + } +#endif + + if (wlanGetTxPendingFrameCount(prGlueInfo->prAdapter)) + kalSetEvent(prGlueInfo); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Kick Tx data to device +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +BOOL kalDevKickData(IN P_GLUE_INFO_T prGlueInfo) +{ + P_GL_HIF_INFO_T prHifInfo = NULL; + ULONG flags = 0; + P_RTMP_TX_RING prTxRing; + spinlock_t *prTxRingLock; + UINT_16 u2Port = TX_RING_DATA0_IDX_0; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + prTxRing = &prHifInfo->TxRing[u2Port]; + prTxRingLock = &prHifInfo->TxRingLock[u2Port]; + + spin_lock_irqsave((spinlock_t *)prTxRingLock, flags); + + kalDevRegWrite(prGlueInfo, prTxRing->hw_cidx_addr, prTxRing->TxCpuIdx); + + spin_unlock_irqrestore((spinlock_t *)prTxRingLock, flags); + + return TRUE; +} + +BOOL kalDevReadData(IN P_GLUE_INFO_T prGlueInfo, IN UINT_16 u2Port, IN OUT P_SW_RFB_T prSwRfb) +{ + P_GL_HIF_INFO_T prHifInfo = NULL; + RXD_STRUCT *pRxD; + P_RTMP_RX_RING prRxRing; + spinlock_t *pRxRingLock; + PVOID pRxPacket = NULL; + RTMP_DMACB *pRxCell; + struct pci_dev *pdev = NULL; + BOOL fgRet = TRUE; + ULONG flags = 0; + PRTMP_DMABUF prDmaBuf; + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + pdev = prHifInfo->pdev; + + prRxRing = &prHifInfo->RxRing[u2Port]; + pRxRingLock = &prHifInfo->RxRingLock[u2Port]; + + spin_lock_irqsave(pRxRingLock, flags); + + pRxCell = &prRxRing->Cell[prRxRing->RxSwReadIdx]; + + /* Point to Rx indexed rx ring descriptor */ + pRxD = (RXD_STRUCT *) pRxCell->AllocVa; + + if (pRxD->DDONE == 0) { + /* Get how may packets had been received */ + kalDevRegRead(prGlueInfo, prRxRing->hw_didx_addr, &prRxRing->RxDmaIdx); + + DBGLOG(HAL, TRACE, "Rx DMA done P[%u] DMA[%u] SW_RD[%u]\n", u2Port, + prRxRing->RxDmaIdx, prRxRing->RxSwReadIdx); + fgRet = FALSE; + goto done; + } + + if (pRxD->LS0 == 0 || prRxRing->fgRxSegPkt) { + /* Rx segmented packet */ + + DBGLOG(HAL, WARN, "Skip Rx segmented data packet, SDL0[%u] LS0[%u]\n", pRxD->SDL0, pRxD->LS0); + if (pRxD->LS0 == 1) { + /* Last segmented packet */ + prRxRing->fgRxSegPkt = FALSE; + } else { + /* Segmented packet */ + prRxRing->fgRxSegPkt = TRUE; + } + + fgRet = FALSE; + goto skip; + } + + pRxPacket = pRxCell->pPacket; + ASSERT(pRxPacket); + + prDmaBuf = &pRxCell->DmaBuf; + + pRxCell->pPacket = prSwRfb->pvPacket; + + pci_unmap_single(pdev, prDmaBuf->AllocPa, prDmaBuf->AllocSize, PCI_DMA_FROMDEVICE); + prSwRfb->pvPacket = pRxPacket; + prSwRfb->pucRecvBuff = ((struct sk_buff *)pRxPacket)->data; + prSwRfb->prRxStatus = (P_HW_MAC_RX_DESC_T)prSwRfb->pucRecvBuff; + + prDmaBuf->AllocVa = ((struct sk_buff *)pRxCell->pPacket)->data; + prDmaBuf->AllocPa = pci_map_single(pdev, prDmaBuf->AllocVa, prDmaBuf->AllocSize, PCI_DMA_FROMDEVICE); + + pRxD->SDP0 = prDmaBuf->AllocPa; +skip: + pRxD->SDL0 = prRxRing->u4BufSize; + pRxD->DDONE = 0; + + prRxRing->RxCpuIdx = prRxRing->RxSwReadIdx; + kalDevRegWrite(prGlueInfo, prRxRing->hw_cidx_addr, prRxRing->RxCpuIdx); + INC_RING_INDEX(prRxRing->RxSwReadIdx, prRxRing->u4RingSize); + +done: + spin_unlock_irqrestore(pRxRingLock, flags); + + return fgRet; +} + + +VOID kalPciUnmapToDev(IN P_GLUE_INFO_T prGlueInfo, IN dma_addr_t rDmaAddr, IN UINT_32 u4Length) +{ + P_GL_HIF_INFO_T prHifInfo = NULL; + struct pci_dev *pdev = NULL; + + prHifInfo = &prGlueInfo->rHifInfo; + pdev = prHifInfo->pdev; + pci_unmap_single(pdev, rDmaAddr, u4Length, PCI_DMA_TODEVICE); +} + +VOID glSetPowerState(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 ePowerMode) +{ +} + +void glGetDev(PVOID ctx, struct device **dev) +{ + *dev = &((struct pci_dev *)ctx)->dev; +} + +void glGetHifDev(P_GL_HIF_INFO_T prHif, struct device **dev) +{ + *dev = &(prHif->pdev->dev); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/pcie/x86.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/pcie/x86.c new file mode 100644 index 0000000000000..7cbc34e29cdef --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/pcie/x86.c @@ -0,0 +1,62 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** +*[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. +******************************************************************************/ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/arm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/arm.c new file mode 100644 index 0000000000000..7cbc34e29cdef --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/arm.c @@ -0,0 +1,62 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** +*[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. +******************************************************************************/ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/hal_api.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/hal_api.c new file mode 100644 index 0000000000000..6ef7b69d9c75c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/hal_api.c @@ -0,0 +1,2227 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** +*[File] hif_api.c +*[Version] v1.0 +*[Revision Date] 2015-09-08 +*[Author] +*[Description] +* The program provides SDIO HIF APIs +*[Copyright] +* Copyright (C) 2015 MediaTek Incorporation. All Rights Reserved. +******************************************************************************/ + +/******************************************************************************* +* C O M P I L E 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 MTK_WCN_HIF_SDIO +#include "hif_sdio.h" +#else +#include +#include +#include +#include /* sdio_readl(), etc */ +#include +#endif + +#include +#ifndef CONFIG_X86 +#include +#endif + +#include "mt66xx_reg.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define RX_RESPONSE_TIMEOUT (15000) + +/******************************************************************************* +* 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 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 halVerifyChipID(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4CIR = 0; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + + if (prAdapter->fgIsReadRevID) + return TRUE; + + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4CIR); + + DBGLOG(INIT, TRACE, "Chip ID: 0x%lx\n", u4CIR & WCIR_CHIP_ID); + DBGLOG(INIT, TRACE, "Revision ID: 0x%lx\n", ((u4CIR & WCIR_REVISION_ID) >> 16)); + + prChipInfo = prAdapter->chip_info; + + if ((u4CIR & WCIR_CHIP_ID) != prChipInfo->chip_id) + return FALSE; + + prAdapter->ucRevID = (UINT_8) (((u4CIR & WCIR_REVISION_ID) >> 16) & 0xF); + prAdapter->fgIsReadRevID = TRUE; + + return TRUE; +} + +WLAN_STATUS +halRxWaitResponse(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, u4CpyLen; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + UINT_32 u4Time, u4Current; + P_RX_CTRL_T prRxCtrl; + + DEBUGFUNC("halRxWaitResponse"); + + ASSERT(prAdapter); + ASSERT(pucRspBuffer); + + prRxCtrl = &prAdapter->rRxCtrl; + + u4Time = (UINT_32) kalGetTimeTick(); + + do { + /* Read the packet length */ + HAL_MCR_RD(prAdapter, MCR_WRPLR, &u4Value); + + if ((u4Value & 0xFFFF) != 0) { + u4PktLen = u4Value & 0xFFFF; + i = 0; + } else { + u4PktLen = (u4Value >> 16) & 0xFFFF; + i = 1; + } + + 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); + } else { + +#if (CFG_ENABLE_READ_EXTRA_4_BYTES == 1) +#if CFG_SDIO_RX_AGG + /* decide copy length */ + if (u4PktLen > u4MaxRespBufferLen) + u4CpyLen = u4MaxRespBufferLen; + else + u4CpyLen = u4PktLen; + + /* read from SDIO to tmp. buffer */ + HAL_PORT_RD(prAdapter, i == 0 ? MCR_WRDR0 : MCR_WRDR1, + ALIGN_4(u4PktLen + 4), prRxCtrl->pucRxCoalescingBufPtr, + HIF_RX_COALESCING_BUFFER_SIZE); + + /* copy to destination buffer */ + kalMemCopy(pucRspBuffer, prRxCtrl->pucRxCoalescingBufPtr, u4CpyLen); + + /* update valid buffer count */ + u4PktLen = u4CpyLen; +#else +#error "Please turn on RX coalescing" +#endif +#else + HAL_PORT_RD(prAdapter, + i == 0 ? MCR_WRDR0 : MCR_WRDR1, u4PktLen, pucRspBuffer, u4MaxRespBufferLen); +#endif + *pu4Length = u4PktLen; + break; + } + } while (TRUE); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief enable global interrupt +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID halEnableInterrupt(IN P_ADAPTER_T prAdapter) +{ + BOOLEAN fgIsIntEnableCache, fgIsPendingInt; + + ASSERT(prAdapter); + fgIsIntEnableCache = prAdapter->fgIsIntEnable; + /* Not to enable interrupt if there is pending interrupt */ + fgIsPendingInt = prAdapter->prGlueInfo->rHifInfo.fgIsPendingInt; + + if (!fgIsPendingInt) + 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 if (!fgIsPendingInt) { + 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 && !fgIsPendingInt) + HAL_BYTE_WR(prAdapter, MCR_WHLPCR, WHLPCR_INT_EN_SET); + + if (fgIsPendingInt) + kalSetIntEvent(prAdapter->prGlueInfo); +} /* end of nicEnableInterrupt() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief disable global interrupt +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID halDisableInterrupt(IN P_ADAPTER_T prAdapter) +{ + + ASSERT(prAdapter); + + HAL_BYTE_WR(prAdapter, MCR_WHLPCR, WHLPCR_INT_EN_CLR); + + prAdapter->fgIsIntEnable = FALSE; + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to process the POWER OFF procedure. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN halSetDriverOwn(IN P_ADAPTER_T prAdapter) +{ + BOOLEAN fgStatus = TRUE; + UINT_32 i, u4CurrTick = 0; + BOOLEAN fgTimeout; + BOOLEAN fgResult; + BOOLEAN fgReady = FALSE; + + ASSERT(prAdapter); + + GLUE_INC_REF_CNT(prAdapter->u4PwrCtrlBlockCnt); + + if (prAdapter->fgIsFwOwn == FALSE) + return fgStatus; + + DBGLOG(INIT, INFO, "DRIVER OWN\n"); + + u4CurrTick = kalGetTimeTick(); + i = 0; + + glWakeupSdio(prAdapter->prGlueInfo); + + while (1) { + HAL_LP_OWN_RD(prAdapter, &fgResult); + + if (TIME_BEFORE(kalGetTimeTick(), u4CurrTick)) { /* To prevent timer wraparound */ + fgTimeout = + ((kalGetTimeTick() + (~u4CurrTick)) > LP_OWN_BACK_TOTAL_DELAY_MS) ? TRUE : FALSE; + } else { + fgTimeout = + ((kalGetTimeTick() - u4CurrTick) > LP_OWN_BACK_TOTAL_DELAY_MS) ? TRUE : FALSE; + } + + if (fgResult) { + prAdapter->fgIsFwOwn = FALSE; + prAdapter->u4OwnFailedCount = 0; + prAdapter->u4OwnFailedLogCount = 0; + + if (nicSerIsWaitingReset(prAdapter)) { + /* SER is done, start Tx/Rx */ + nicSerStartTxRx(prAdapter); + } + break; + } else if ((i > LP_OWN_BACK_FAILED_RETRY_CNT) && + (kalIsCardRemoved(prAdapter->prGlueInfo) || fgIsBusAccessFailed || fgTimeout + || wlanIsChipNoAck(prAdapter))) { + +#if CFG_SUPPORT_LOW_POWER_DEBUG + /* For driver own back fail debug, get current PC value */ + halPrintMailbox(prAdapter); + halPollDbgCr(prAdapter, LP_OWN_BACK_FAILED_DBGCR_POLL_ROUND); +#endif + if ((prAdapter->u4OwnFailedCount == 0) || + CHECK_FOR_TIMEOUT(u4CurrTick, prAdapter->rLastOwnFailedLogTime, + MSEC_TO_SYSTIME(LP_OWN_BACK_FAILED_LOG_SKIP_MS))) { + + DBGLOG(INIT, ERROR, + "LP cannot be own back, Timeout[%u](%ums), BusAccessError[%u]", + fgTimeout, kalGetTimeTick() - u4CurrTick, fgIsBusAccessFailed); + DBGLOG(INIT, ERROR, + "Resetting[%u], CardRemoved[%u] NoAck[%u] Cnt[%u]\n", + kalIsResetting(), + kalIsCardRemoved(prAdapter->prGlueInfo), wlanIsChipNoAck(prAdapter), + prAdapter->u4OwnFailedCount); + + DBGLOG(INIT, INFO, + "Skip LP own back failed log for next %ums\n", LP_OWN_BACK_FAILED_LOG_SKIP_MS); + + prAdapter->u4OwnFailedLogCount++; + if (prAdapter->u4OwnFailedLogCount > LP_OWN_BACK_FAILED_RESET_CNT) { + /* Trigger RESET */ +#if CFG_CHIP_RESET_SUPPORT + glResetTrigger(prAdapter); +#endif + } + GET_CURRENT_SYSTIME(&prAdapter->rLastOwnFailedLogTime); + } + + prAdapter->u4OwnFailedCount++; + fgStatus = FALSE; + break; + } + +#if 1 + if (i == 0) { + /* Software get LP ownership - only one time. + * Suppose one CLR_LP_OWN will trigger firmware to return the hif_own. + * If not, there is something wrong in chipset. + */ + HAL_LP_OWN_CLR(prAdapter, &fgResult); + } +#else + if ((i & (LP_OWN_BACK_CLR_OWN_ITERATION - 1)) == 0) { + /* Software get LP ownership - per 256 iterations */ + HAL_LP_OWN_CLR(prAdapter, &fgResult); + } +#endif + /* Delay for LP engine to complete its operation. */ + kalMsleep(LP_OWN_BACK_LOOP_DELAY_MS); + i++; + } + + /* For Low power Test */ + /* 1. Driver need to polling until CR4 ready, then could do normal Tx/Rx */ + /* 2. Send a dummy command to change data path to store-forward mode */ +#if 1 + if (prAdapter->fgIsFwDownloaded) { + u4CurrTick = kalGetTimeTick(); + while (1) { + HAL_WIFI_FUNC_READY_CHECK(prAdapter, WIFI_FUNC_READY_BITS, &fgReady); + + if (TIME_BEFORE(kalGetTimeTick(), u4CurrTick)) { /* To prevent timer wraparound */ + fgTimeout = + ((kalGetTimeTick() + (~u4CurrTick)) > LP_OWN_BACK_TOTAL_DELAY_MS) + ? TRUE : FALSE; + } else { + fgTimeout = + ((kalGetTimeTick() - u4CurrTick) > LP_OWN_BACK_TOTAL_DELAY_MS) + ? TRUE : FALSE; + } + + if (fgReady) { + break; + } else if (kalIsCardRemoved(prAdapter->prGlueInfo) || fgIsBusAccessFailed || fgTimeout + || wlanIsChipNoAck(prAdapter)) { + +#if CFG_SUPPORT_LOW_POWER_DEBUG + /* For driver own back fail debug, get current PC value */ + halPrintMailbox(prAdapter); + halPollDbgCr(prAdapter, LP_OWN_BACK_FAILED_DBGCR_POLL_ROUND); +#endif + + DBGLOG(INIT, ERROR, + "Resetting[%u], CardRemoved[%u] NoAck[%u] Timeout[%u](%u - %u)ms\n", + kalIsResetting(), + kalIsCardRemoved(prAdapter->prGlueInfo), wlanIsChipNoAck(prAdapter), + fgTimeout, kalGetTimeTick(), u4CurrTick); + + + DBGLOG(INIT, INFO, + "Skip waiting CR4 ready for next %ums\n", LP_OWN_BACK_FAILED_LOG_SKIP_MS); + fgStatus = FALSE; + + if (fgTimeout) { + /* Trigger RESET */ +#if CFG_CHIP_RESET_SUPPORT + glResetTrigger(prAdapter); +#endif + } + + break; + } + /* Delay for CR4 to complete its operation. */ + kalMsleep(LP_OWN_BACK_LOOP_DELAY_MS); + } + + HAL_MCR_RD(prAdapter, MCR_D2HRM1R, &i); + if (i == 0x77889901) { + /* fgIsWakeupFromDeepSleep */ + wlanSendDummyCmd(prAdapter, FALSE); + + /* Workaround for dummy command which is not count in Tx done count */ + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[TC4_INDEX]--; + } + } +#endif + + return fgStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to process the POWER ON procedure. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID halSetFWOwn(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnableGlobalInt) +{ + + BOOLEAN fgResult; + + ASSERT(prAdapter); + + ASSERT(prAdapter->u4PwrCtrlBlockCnt != 0); + /* Decrease Block to Enter Low Power Semaphore count */ + GLUE_DEC_REF_CNT(prAdapter->u4PwrCtrlBlockCnt); + + if (prAdapter->u4PwrCtrlBlockCnt != 0) + return; + + if (prAdapter->fgForceFwOwn == FALSE) + if (prAdapter->fgWiFiInSleepyState == FALSE) + return; + + if (prAdapter->fgIsFwOwn == TRUE) + return; + + if ((nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) && !nicSerIsWaitingReset(prAdapter)) { + DBGLOG(INIT, INFO, "FW OWN Skipped due to pending INT\n"); + /* pending interrupts */ + return; + } + + if (fgEnableGlobalInt) { + prAdapter->fgIsIntEnableWithLPOwnSet = TRUE; + } else { + HAL_LP_OWN_SET(prAdapter, &fgResult); + + if (fgResult) { + /* if set firmware own not successful (possibly pending interrupts), */ + /* indicate an own clear event */ + HAL_LP_OWN_CLR(prAdapter, &fgResult); + + return; + } + + prAdapter->fgIsFwOwn = TRUE; + + DBGLOG(INIT, INFO, "FW OWN\n"); + } + +} + +VOID halWakeUpWiFi(IN P_ADAPTER_T prAdapter) +{ + + BOOLEAN fgResult; + + ASSERT(prAdapter); + + HAL_LP_OWN_RD(prAdapter, &fgResult); + + if (fgResult) + prAdapter->fgIsFwOwn = FALSE; + else + HAL_LP_OWN_CLR(prAdapter, &fgResult); + +#if CFG_SUPPORT_LOW_POWER_DEBUG + /* Polling MCU programming counter */ + halPollDbgCr(prAdapter, LP_DBGCR_POLL_ROUND); +#endif +} + +VOID halDevInit(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4Value = 0; + + ASSERT(prAdapter); + +#if CFG_SDIO_INTR_ENHANCE + /* 4 <1> Check STATUS Buffer is DW alignment. */ + ASSERT(IS_ALIGN_4((ULONG)&prAdapter->prGlueInfo->rHifInfo.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); + } +#endif /* CFG_SDIO_INTR_ENHANCE */ + + HAL_MCR_WR(prAdapter, MCR_WHIER, WHIER_DEFAULT); + + HAL_CFG_MAX_HIF_RX_LEN_NUM(prAdapter, HIF_RX_MAX_AGG_NUM); +} + +VOID halTxCancelSendingCmd(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ +} + +BOOLEAN halTxIsDataBufEnough(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + return TRUE; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Driver maintain a variable that is synchronous with the usage of individual +* TC Buffer Count. This function will calculate TC page count according to +* the given TX_STATUS COUNTER after TX Done. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] au2TxRlsCnt array of TX STATUS +* \param[in] au2FreeTcResource array of free & available resource count +* +* @return TRUE there are available resource to release +* @return FALSE no available resource to release +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN halTxCalculateResource(IN P_ADAPTER_T prAdapter, IN PUINT_16 au2TxRlsCnt, OUT PUINT_16 au2FreeTcResource) +{ + P_TX_TCQ_STATUS_T prTcqStatus; + BOOLEAN bStatus = FALSE; + UINT_8 ucTcIdx; + UINT_32 u4TotalTxDoneCnt = 0; + UINT_32 u4TotalExtraTxDone = 0; + UINT_32 au4UsedCnt[TC_NUM]; + UINT_32 au4ExtraTxDone[TC_NUM]; + + PUINT_32 au4TxDoneCnt; + PUINT_32 au4PreUsedCnt; + UINT_32 u4AvaliableCnt; + BOOLEAN fgEnExtraTxDone; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prTcqStatus = &prAdapter->rTxCtrl.rTc; + + au4TxDoneCnt = prTcqStatus->au4TxDonePageCount; + au4PreUsedCnt = prTcqStatus->au4PreUsedPageCount; + u4AvaliableCnt = prTcqStatus->u4AvaliablePageCount; + fgEnExtraTxDone = prAdapter->rWifiVar.ucExtraTxDone; + + /* Get used page count */ + if (fgEnExtraTxDone) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + for (ucTcIdx = TC0_INDEX; ucTcIdx < TC_NUM; ucTcIdx++) { + au4UsedCnt[ucTcIdx] = prTcqStatus->au4MaxNumOfPage[ucTcIdx] - + prTcqStatus->au4FreePageCount[ucTcIdx]; + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + } + + /* Get Tx done & available page count */ + u4AvaliableCnt += au2TxRlsCnt[HIF_TX_FFA_INDEX]; + for (ucTcIdx = TC0_INDEX; ucTcIdx < TC_NUM; ucTcIdx++) { + + /* Get Tx done count from Tx interrupt status */ + au4TxDoneCnt[ucTcIdx] += au2TxRlsCnt[nicTxGetTxQByTc(prAdapter, ucTcIdx)]; + + /* Get available EXTRA Tx done */ + if (fgEnExtraTxDone) { + /* Release Tx done if there are pre-used resource */ + if (au4TxDoneCnt[ucTcIdx] >= au4PreUsedCnt[ucTcIdx]) { + au4TxDoneCnt[ucTcIdx] -= au4PreUsedCnt[ucTcIdx]; + au4PreUsedCnt[ucTcIdx] = 0; + } else { + au4PreUsedCnt[ucTcIdx] -= au4TxDoneCnt[ucTcIdx]; + au4TxDoneCnt[ucTcIdx] = 0; + } + + /* Calculate extra Tx done to share rest FFA resource */ + if (au4TxDoneCnt[ucTcIdx] >= au4UsedCnt[ucTcIdx]) { + au4TxDoneCnt[ucTcIdx] = au4UsedCnt[ucTcIdx]; + au4ExtraTxDone[ucTcIdx] = 0; + } else { + au4ExtraTxDone[ucTcIdx] = au4UsedCnt[ucTcIdx] - au4TxDoneCnt[ucTcIdx]; + } + u4TotalExtraTxDone += au4ExtraTxDone[ucTcIdx]; + } + + u4TotalTxDoneCnt += au4TxDoneCnt[ucTcIdx]; + + } + + DBGLOG(TX, TRACE, "TxDone result, FFA[%u] AC[%u:%u:%u:%u] CPU[%u]\n", + au2TxRlsCnt[HIF_TX_FFA_INDEX], au2TxRlsCnt[HIF_TX_AC0_INDEX], + au2TxRlsCnt[HIF_TX_AC1_INDEX], au2TxRlsCnt[HIF_TX_AC2_INDEX], + au2TxRlsCnt[HIF_TX_AC3_INDEX], au2TxRlsCnt[HIF_TX_CPU_INDEX]); + + DBGLOG(TX, TRACE, "TxDone Page count, TC[%u:%u:%u:%u:%u:%u]\n", + au4TxDoneCnt[TC0_INDEX], au4TxDoneCnt[TC1_INDEX], au4TxDoneCnt[TC2_INDEX], + au4TxDoneCnt[TC3_INDEX], au4TxDoneCnt[TC4_INDEX], au4TxDoneCnt[TC5_INDEX]); + + /* Calculate free Tc page count */ + if (u4AvaliableCnt && u4TotalTxDoneCnt) { + /* Distribute resource by Tx done counter */ + if (u4AvaliableCnt >= u4TotalTxDoneCnt) { + /* Fulfill all TC resource */ + kalMemCopy(au2FreeTcResource, prTcqStatus->au4TxDonePageCount, + sizeof(prTcqStatus->au4TxDonePageCount)); + + kalMemZero(prTcqStatus->au4TxDonePageCount, sizeof(prTcqStatus->au4TxDonePageCount)); + + u4AvaliableCnt -= u4TotalTxDoneCnt; + } else { + /* Round-robin distribute resource */ + ucTcIdx = prTcqStatus->ucNextTcIdx; + while (u4AvaliableCnt) { + /* Enough resource, fulfill this TC */ + if (u4AvaliableCnt >= au4TxDoneCnt[ucTcIdx]) { + au2FreeTcResource[ucTcIdx] = au4TxDoneCnt[ucTcIdx]; + u4AvaliableCnt -= au4TxDoneCnt[ucTcIdx]; + au4TxDoneCnt[ucTcIdx] = 0; + + /* Round-robin get next TC */ + ucTcIdx++; + ucTcIdx %= TC_NUM; + } + /* no more resource, distribute rest of resource to this TC */ + else { + au2FreeTcResource[ucTcIdx] = u4AvaliableCnt; + au4TxDoneCnt[ucTcIdx] -= u4AvaliableCnt; + u4AvaliableCnt = 0; + } + } + prTcqStatus->ucNextTcIdx = ucTcIdx; + } + bStatus = TRUE; + } + + if (u4AvaliableCnt && u4TotalExtraTxDone && fgEnExtraTxDone) { + /* Distribute resource by EXTRA Tx done counter */ + if (u4AvaliableCnt >= u4TotalExtraTxDone) { + for (ucTcIdx = TC0_INDEX; ucTcIdx < TC_NUM; ucTcIdx++) { + au2FreeTcResource[ucTcIdx] += au4ExtraTxDone[ucTcIdx]; + au4PreUsedCnt[ucTcIdx] += au4ExtraTxDone[ucTcIdx]; + au4ExtraTxDone[ucTcIdx] = 0; + } + + u4AvaliableCnt -= u4TotalExtraTxDone; + } else { + /* Round-robin distribute resource */ + ucTcIdx = prTcqStatus->ucNextTcIdx; + while (u4AvaliableCnt) { + /* Enough resource, fulfill this TC */ + if (u4AvaliableCnt >= au4ExtraTxDone[ucTcIdx]) { + au2FreeTcResource[ucTcIdx] += au4ExtraTxDone[ucTcIdx]; + au4PreUsedCnt[ucTcIdx] += au4ExtraTxDone[ucTcIdx]; + u4AvaliableCnt -= au4ExtraTxDone[ucTcIdx]; + au4ExtraTxDone[ucTcIdx] = 0; + + /* Round-robin get next TC */ + ucTcIdx++; + ucTcIdx %= TC_NUM; + } + /* no more resource, distribute rest of resource to this TC */ + else { + au2FreeTcResource[ucTcIdx] += u4AvaliableCnt; + au4PreUsedCnt[ucTcIdx] += u4AvaliableCnt; + au4ExtraTxDone[ucTcIdx] -= u4AvaliableCnt; + u4AvaliableCnt = 0; + } + } + prTcqStatus->ucNextTcIdx = ucTcIdx; + } + bStatus = TRUE; + } + + prTcqStatus->u4AvaliablePageCount = u4AvaliableCnt; + + return bStatus; +} +BOOLEAN halTxReleaseResource(IN P_ADAPTER_T prAdapter, IN PUINT_16 au2TxRlsCnt) +{ + P_TX_TCQ_STATUS_T prTcqStatus; + BOOLEAN bStatus = FALSE; + UINT_32 i; + P_SDIO_STAT_COUNTER_T prStatCnt; + UINT_16 au2TxDoneCnt[HIF_TX_NUM] = { 0 }; + UINT_16 u2ReturnCnt; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prTcqStatus = &prAdapter->rTxCtrl.rTc; + prStatCnt = &prAdapter->prGlueInfo->rHifInfo.rStatCounter; + + /* Update Free Tc resource counter */ + for (i = HIF_TX_AC0_INDEX; i <= HIF_TX_AC23_INDEX; i++) + au2TxDoneCnt[i % WMM_AC_INDEX_NUM] += au2TxRlsCnt[i]; + au2TxDoneCnt[HIF_TX_CPU_INDEX] = au2TxRlsCnt[HIF_TX_CPU_INDEX]; + + /* Return free Tc page count */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + for (i = TC0_INDEX; i < TC5_INDEX; i++) { + u2ReturnCnt = au2TxDoneCnt[nicTxGetTxQByTc(prAdapter, i)]; + nicTxReleaseResource(prAdapter, i, u2ReturnCnt, FALSE); + prAdapter->prGlueInfo->rHifInfo.au4PendingTxDoneCount[i] -= u2ReturnCnt; + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + bStatus = TRUE; + + /* Update Statistic counter */ + prStatCnt->u4TxDonePendingPktCnt += nicTxGetMsduPendingCnt(prAdapter); + prStatCnt->u4TxDoneIntTotCnt++; + + for (i = HIF_TX_AC0_INDEX; i < HIF_TX_NUM; i++) { + if (au2TxRlsCnt[i]) { + prStatCnt->u4TxDoneCnt[i] += au2TxRlsCnt[i]; + prStatCnt->u4TxDoneIntCnt[i]++; + } + } + + if (!nicTxSanityCheckResource(prAdapter)) + DBGLOG(TX, ERROR, "Tx Done INT result, FFA[%u] AC[%u:%u:%u:%u] CPU[%u]\n", + au2TxRlsCnt[HIF_TX_FFA_INDEX], au2TxRlsCnt[HIF_TX_AC0_INDEX], + au2TxRlsCnt[HIF_TX_AC1_INDEX], au2TxRlsCnt[HIF_TX_AC2_INDEX], + au2TxRlsCnt[HIF_TX_AC3_INDEX], au2TxRlsCnt[HIF_TX_CPU_INDEX]); + + DBGLOG(TX, LOUD, "TCQ Status Free Page:Buf[%u:%u, %u:%u, %u:%u, %u:%u, %u:%u, %u:%u]\n", + prTcqStatus->au4FreePageCount[TC0_INDEX], prTcqStatus->au4FreeBufferCount[TC0_INDEX], + prTcqStatus->au4FreePageCount[TC1_INDEX], prTcqStatus->au4FreeBufferCount[TC1_INDEX], + prTcqStatus->au4FreePageCount[TC2_INDEX], prTcqStatus->au4FreeBufferCount[TC2_INDEX], + prTcqStatus->au4FreePageCount[TC3_INDEX], prTcqStatus->au4FreeBufferCount[TC3_INDEX], + prTcqStatus->au4FreePageCount[TC4_INDEX], prTcqStatus->au4FreeBufferCount[TC4_INDEX], + prTcqStatus->au4FreePageCount[TC5_INDEX], prTcqStatus->au4FreeBufferCount[TC5_INDEX]); + + return bStatus; +} + +WLAN_STATUS halTxPollingResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC) +{ + P_TX_CTRL_T prTxCtrl; + WLAN_STATUS u4Status = WLAN_STATUS_RESOURCES; + UINT_32 au4WTSR[8]; + P_GL_HIF_INFO_T prHifInfo; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + prTxCtrl = &prAdapter->rTxCtrl; + + if (prHifInfo->fgIsPendingInt && (prHifInfo->prSDIOCtrl->u4WHISR & WHISR_TX_DONE_INT)) { + /* Get Tx done resource from pending interrupt status */ + kalMemCopy(au4WTSR, &prHifInfo->prSDIOCtrl->rTxInfo, sizeof(UINT_32) * 8); + + /* Clear pending Tx done interrupt */ + prHifInfo->prSDIOCtrl->u4WHISR &= ~WHISR_TX_DONE_INT; + } else + HAL_READ_TX_RELEASED_COUNT(prAdapter, au4WTSR); + + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + } else if (halTxReleaseResource(prAdapter, (PUINT_16) au4WTSR)) { + if (prTxCtrl->rTc.au4FreeBufferCount[ucTC] > 0) + u4Status = WLAN_STATUS_SUCCESS; + } + + return u4Status; +} + +VOID halTxInterruptSanityCheck(IN P_ADAPTER_T prAdapter, IN PUINT_16 au2TxRlsCnt) +{ + UINT_8 ucIdx; + BOOLEAN fgError = FALSE; + + if (prAdapter->rWifiVar.ucTxDbg & BIT(1)) { + for (ucIdx = HIF_TX_AC0_INDEX; ucIdx < HIF_TX_NUM; ucIdx++) { + if (au2TxRlsCnt[ucIdx] > prAdapter->rTxCtrl.u4TotalPageNum) + fgError = TRUE; + } + + if (fgError) + DBGLOG(TX, ERROR, "Tx Done INT result, FFA[%u] AC[%u:%u:%u:%u] CPU[%u]\n", + au2TxRlsCnt[HIF_TX_FFA_INDEX], au2TxRlsCnt[HIF_TX_AC0_INDEX], + au2TxRlsCnt[HIF_TX_AC1_INDEX], au2TxRlsCnt[HIF_TX_AC2_INDEX], + au2TxRlsCnt[HIF_TX_AC3_INDEX], au2TxRlsCnt[HIF_TX_CPU_INDEX]); + } +} + +#if CFG_SDIO_INTR_ENHANCE +VOID halProcessEnhanceInterruptStatus(IN P_ADAPTER_T prAdapter) +{ + P_SDIO_CTRL_T prSDIOCtrl = prAdapter->prGlueInfo->rHifInfo.prSDIOCtrl; + + /* Set Tx done interrupt if there are Tx done count */ + if ((prSDIOCtrl->u4WHISR & WHISR_TX_DONE_INT) == 0 && + (prSDIOCtrl->rTxInfo.au4WTSR[0] | prSDIOCtrl->rTxInfo.au4WTSR[1] | + prSDIOCtrl->rTxInfo.au4WTSR[2] | prSDIOCtrl->rTxInfo.au4WTSR[3] | + prSDIOCtrl->rTxInfo.au4WTSR[4] | prSDIOCtrl->rTxInfo.au4WTSR[5] | + prSDIOCtrl->rTxInfo.au4WTSR[6] | prSDIOCtrl->rTxInfo.au4WTSR[7])) { + + prSDIOCtrl->u4WHISR |= WHISR_TX_DONE_INT; + } + + /* Set SW ASSERT INFO interrupt if there are pending mail box */ + if (((prSDIOCtrl->u4WHISR & WHISR_D2H_SW_ASSERT_INFO_INT) == 0) && + HAL_GET_MAILBOX_READ_CLEAR(prAdapter) && + (prSDIOCtrl->u4RcvMailbox0 || prSDIOCtrl->u4RcvMailbox1)) { + + prSDIOCtrl->u4WHISR |= WHISR_D2H_SW_ASSERT_INFO_INT; + } +} +#endif + +VOID halProcessTxInterrupt(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 */ + SDIO_TIME_INTERVAL_DEC(); + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + SDIO_REC_TIME_START(); + + /* Get the TX STATUS */ +#if CFG_SDIO_INTR_ENHANCE + + prSDIOCtrl = prAdapter->prGlueInfo->rHifInfo.prSDIOCtrl; +#if DBG + /* DBGLOG_MEM8(RX, TRACE, (PUINT_8)prSDIOCtrl, sizeof(SDIO_CTRL_T)); */ +#endif + + halTxInterruptSanityCheck(prAdapter, (PUINT_16)&prSDIOCtrl->rTxInfo); + halTxReleaseResource(prAdapter, (PUINT_16)&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]); + + halTxReleaseResource(prAdapter, (PUINT_8) au4TxCount); + +#endif /* CFG_SDIO_INTR_ENHANCE */ + + nicTxAdjustTcq(prAdapter); + + SDIO_REC_TIME_END(); + SDIO_ADD_TIME_INTERVAL(prAdapter->prGlueInfo->rHifInfo.rStatCounter.u4TxDoneIntTime); + +} /* end of nicProcessTxInterrupt() */ + +#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 halRxReadBuffer(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) +{ + P_RX_CTRL_T prRxCtrl; + PUINT_8 pucBuf; + P_HW_MAC_RX_DESC_T prRxStatus; + UINT_32 u4PktLen = 0, u4ReadBytes; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + BOOL fgResult = TRUE; + UINT_32 u4RegValue; + UINT_32 rxNum; + + DEBUGFUNC("halRxReadBuffer"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + pucBuf = prSwRfb->pucRecvBuff; + prRxStatus = prSwRfb->prRxStatus; + + ASSERT(prRxStatus); + ASSERT(pucBuf); + DBGLOG(RX, TRACE, "pucBuf= 0x%x, prRxStatus= 0x%x\n", pucBuf, prRxStatus); + + 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) HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus)) { + DBGLOG(RX, ERROR, "Read u4PktLen = %d, prHifRxHdr->u2PacketLen: %d\n", + u4PktLen, HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus)); +#if DBG + DBGLOG_MEM8(RX, TRACE, (PUINT_8) prRxStatus, + (HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus) > + 4096) ? 4096 : prRxStatus->u2RxByteCount); +#endif + ASSERT(0); + } + /* u4PktLen is byte unit, not inlude HW appended DW */ + + prSwRfb->ucPacketType = (UINT_8) HAL_RX_STATUS_GET_PKT_TYPE(prRxStatus); + DBGLOG(RX, TRACE, "ucPacketType = %d\n", prSwRfb->ucPacketType); + + prSwRfb->ucStaRecIdx = + secGetStaIdxByWlanIdx(prAdapter, (UINT_8) HAL_RX_STATUS_GET_WLAN_IDX(prRxStatus)); + + /* 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 halRxSDIOReceiveRFBs(IN P_ADAPTER_T prAdapter) +{ + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; + P_HW_MAC_RX_DESC_T prRxStatus; + UINT_32 u4HwAppendDW; + PUINT_32 pu4Temp; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("halRxSDIOReceiveRFBs"); + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + do { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + if (!prSwRfb) { + DBGLOG(RX, TRACE, "No More RFB\n"); + break; + } + /* need to consider */ + if (halRxReadBuffer(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); + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + pu4Temp = (PUINT_32) prRxStatus; + u4HwAppendDW = *(pu4Temp + (ALIGN_4(prRxStatus->u2RxByteCount) >> 2)); + DBGLOG(RX, TRACE, "u4HwAppendDW = 0x%x\n", u4HwAppendDW); + DBGLOG(RX, TRACE, "u2PacketLen = 0x%x\n", HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus)); + } while (FALSE); + +} /* 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 +halRxEnhanceReadBuffer(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_HW_MAC_RX_DESC_T prRxStatus; + UINT_32 u4PktLen = 0; + WLAN_STATUS u4Status = WLAN_STATUS_FAILURE; + BOOL fgResult = TRUE; + + DEBUGFUNC("halRxEnhanceReadBuffer"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + pucBuf = prSwRfb->pucRecvBuff; + ASSERT(pucBuf); + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + /* 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) (HAL_RX_STATUS_GET_RX_BYTE_CNT(prRxStatus)); + /* DBGLOG(RX, TRACE, ("u4PktLen = %d\n", u4PktLen)); */ + + prSwRfb->ucPacketType = (UINT_8) HAL_RX_STATUS_GET_PKT_TYPE(prRxStatus); + /* DBGLOG(RX, TRACE, ("ucPacketType = %d\n", prSwRfb->ucPacketType)); */ + + prSwRfb->ucStaRecIdx = + secGetStaIdxByWlanIdx(prAdapter, (UINT_8) HAL_RX_STATUS_GET_WLAN_IDX(prRxStatus)); + + /* 4 <2> if the RFB dw size or packet size is zero */ + if (u4PktLen == 0) { + DBGLOG(RX, ERROR, "Packet Length = %u\n", u4PktLen); + ASSERT(0); + break; + } + /* 4 <3> if the packet is too large or too small */ + /* ToDo[6630]: adjust CFG_RX_MAX_PKT_SIZE */ + if (u4PktLen > CFG_RX_MAX_PKT_SIZE) { + DBGLOG(RX, TRACE, "Read RX Packet Lentgh Error (%u)\n", + u4PktLen); + ASSERT(0); + break; + } + + u4Status = WLAN_STATUS_SUCCESS; + } while (FALSE); + + DBGLOG_MEM8(RX, TRACE, pucBuf, ALIGN_4(u2RxLength + HIF_RX_HW_APPENDED_LEN)); + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read frames from the data port for SDIO +* I/F, fill RFB and put each frame into the rReceivedRFBList queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID halRxSDIOEnhanceReceiveRFBs(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("halRxSDIOEnhanceReceiveRFBs"); + + ASSERT(prAdapter); + + prSDIOCtrl = prAdapter->prGlueInfo->rHifInfo.prSDIOCtrl; + ASSERT(prSDIOCtrl); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + for (rxNum = 0; rxNum < 2; rxNum++) { + u2RxPktNum = + (rxNum == 0 ? prSDIOCtrl->rRxInfo.u.u2NumValidRx0Len : prSDIOCtrl->rRxInfo.u.u2NumValidRx1Len); + + if (u2RxPktNum == 0) + continue; + + for (i = 0; i < u2RxPktNum; i++) { + if (rxNum == 0) { + /* HAL_READ_RX_LENGTH */ + HAL_READ_RX_LENGTH(prAdapter, &u2RxLength, &u2Tmp); + } else if (rxNum == 1) { + /* HAL_READ_RX_LENGTH */ + HAL_READ_RX_LENGTH(prAdapter, &u2Tmp, &u2RxLength); + } + + if (!u2RxLength) + break; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + if (!prSwRfb) { + DBGLOG(RX, TRACE, "No More RFB\n"); + break; + } + ASSERT(prSwRfb); + + if (halRxEnhanceReadBuffer(prAdapter, rxNum, u2RxLength, prSwRfb) == WLAN_STATUS_FAILURE) { + DBGLOG(RX, TRACE, "nicRxEnhanceRxReadBuffer failed\n"); + nicRxReturnRFB(prAdapter, prSwRfb); + break; + } + /* prSDIOCtrl->au4RxLength[i] = 0; */ + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_INSERT_TAIL(&prRxCtrl->rReceivedRfbList, &prSwRfb->rQueEntry); + RX_INC_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + } + } + + prSDIOCtrl->rRxInfo.u.u2NumValidRx0Len = 0; + prSDIOCtrl->rRxInfo.u.u2NumValidRx1Len = 0; + +} /* end of nicRxSDIOReceiveRFBs() */ + +#endif /* CFG_SDIO_INTR_ENHANCE */ + +#if CFG_SDIO_RX_AGG +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read frames from the data port for SDIO with Rx aggregation enabled +* I/F, fill RFB and put each frame into the rReceivedRFBList queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID halRxSDIOAggReceiveRFBs(IN P_ADAPTER_T prAdapter) +{ + P_ENHANCE_MODE_DATA_STRUCT_T prEnhDataStr; + P_RX_CTRL_T prRxCtrl; + UINT_32 u4RxLength; + UINT_32 i, rxNum; + UINT_32 u4RxAggCount = 0, u4RxAggLength = 0; + UINT_32 u4RxAvailAggLen; + PUINT_8 pucSrcAddr; + UINT_16 u2RxPktNum; + P_GL_HIF_INFO_T prHifInfo; + P_SDIO_RX_COALESCING_BUF_T prRxBuf; + BOOLEAN fgNoFreeBuf = FALSE; + + SDIO_TIME_INTERVAL_DEC(); + + DEBUGFUNC("halRxSDIOAggReceiveRFBs"); + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + prEnhDataStr = prHifInfo->prSDIOCtrl; + + if (prEnhDataStr->rRxInfo.u.u2NumValidRx0Len == 0 && prEnhDataStr->rRxInfo.u.u2NumValidRx1Len == 0) + return; + + for (rxNum = 0; rxNum < 2; rxNum++) { + u2RxPktNum = (rxNum == 0 ? prEnhDataStr->rRxInfo.u.u2NumValidRx0Len : + prEnhDataStr->rRxInfo.u.u2NumValidRx1Len); + + /* if this assertion happened, it is most likely a F/W bug */ + ASSERT(u2RxPktNum <= HIF_RX_MAX_AGG_NUM); + + if (u2RxPktNum > HIF_RX_MAX_AGG_NUM) + continue; + + if (u2RxPktNum == 0) + continue; + +#if CFG_HIF_STATISTICS + prRxCtrl->u4TotalRxAccessNum++; + prRxCtrl->u4TotalRxPacketNum += u2RxPktNum; +#endif + + mutex_lock(&prHifInfo->rRxFreeBufQueMutex); + fgNoFreeBuf = QUEUE_IS_EMPTY(&prHifInfo->rRxFreeBufQueue); + mutex_unlock(&prHifInfo->rRxFreeBufQueMutex); + + if (fgNoFreeBuf) { + DBGLOG(RX, TRACE, "[%s] No free Rx buffer\n", __func__); + prHifInfo->rStatCounter.u4RxBufUnderFlowCnt++; + + if (prAdapter->prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + QUE_T rTempQue; + P_QUE_T prTempQue = &rTempQue; + + /* During halt state, move all pending Rx buffer to free queue */ + mutex_lock(&prHifInfo->rRxDeAggQueMutex); + QUEUE_MOVE_ALL(prTempQue, &prHifInfo->rRxDeAggQueue); + mutex_unlock(&prHifInfo->rRxDeAggQueMutex); + + mutex_lock(&prHifInfo->rRxFreeBufQueMutex); + QUEUE_CONCATENATE_QUEUES(&prHifInfo->rRxFreeBufQueue, prTempQue); + mutex_unlock(&prHifInfo->rRxFreeBufQueMutex); + } + + continue; + } + + u4RxAvailAggLen = HIF_RX_COALESCING_BUFFER_SIZE; +#if CFG_SDIO_RX_ENHANCE + u4RxAvailAggLen -= (sizeof(ENHANCE_MODE_DATA_STRUCT_T) + HIF_RX_ENHANCE_MODE_PAD_LEN); +#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); + DBGLOG(RX, ERROR, "[%s] RxLength == 0\n", __func__); + break; + } + + if (ALIGN_4(u4RxLength + HIF_RX_HW_APPENDED_LEN) < u4RxAvailAggLen) { + u4RxAvailAggLen -= ALIGN_4(u4RxLength + HIF_RX_HW_APPENDED_LEN); + u4RxAggCount++; + } else { + /* CFG_RX_COALESCING_BUFFER_SIZE is not large enough */ + DBGLOG(RX, ERROR, "[%s] Request_len(%d) >= Available_len(%d)\n", + __func__, (ALIGN_4(u4RxLength + HIF_RX_HW_APPENDED_LEN)), u4RxAvailAggLen); + ASSERT(0); + break; + } + } + + mutex_lock(&prHifInfo->rRxFreeBufQueMutex); + QUEUE_REMOVE_HEAD(&prHifInfo->rRxFreeBufQueue, prRxBuf, P_SDIO_RX_COALESCING_BUF_T); + mutex_unlock(&prHifInfo->rRxFreeBufQueMutex); + + prRxBuf->u4PktCount = u4RxAggCount; + + u4RxAggLength = (HIF_RX_COALESCING_BUFFER_SIZE - u4RxAvailAggLen); + + SDIO_REC_TIME_START(); + HAL_READ_RX_PORT(prAdapter, rxNum, u4RxAggLength, + prRxBuf->pvRxCoalescingBuf, HIF_RX_COALESCING_BUFFER_SIZE); + SDIO_REC_TIME_END(); + SDIO_ADD_TIME_INTERVAL(prHifInfo->rStatCounter.u4PortReadTime); + +#if CFG_SDIO_RX_ENHANCE + pucSrcAddr = prRxBuf->pvRxCoalescingBuf + u4RxAggLength - sizeof(ENHANCE_MODE_DATA_STRUCT_T); + kalMemCopy(prHifInfo->prSDIOCtrl, pucSrcAddr, sizeof(ENHANCE_MODE_DATA_STRUCT_T)); + + halProcessEnhanceInterruptStatus(prAdapter); + + if (prHifInfo->prSDIOCtrl->u4WHISR) { + /* Interrupt status without Rx done */ + /* Mask Rx done interrupt to avoid recurrsion */ + UINT_32 u4IntStatus = prHifInfo->prSDIOCtrl->u4WHISR & + (~(WHISR_RX0_DONE_INT | WHISR_RX1_DONE_INT)); + + if ((rxNum == 0) && prEnhDataStr->rRxInfo.u.u2NumValidRx1Len && u4IntStatus) { + /* Handle interrupt here if there are pending Rx port1 */ + + nicProcessIST_impl(prAdapter, u4IntStatus); + } else { + prAdapter->prGlueInfo->rHifInfo.fgIsPendingInt = TRUE; + } + } +#endif + halDeAggRxPkt(prAdapter, prRxBuf); + + /* Update statistic counter */ + prHifInfo->rStatCounter.u4PktReadCnt[rxNum] += u4RxAggCount; + prHifInfo->rStatCounter.u4PortReadCnt[rxNum]++; + } + +} +#endif /* CFG_SDIO_RX_AGG */ + + +VOID halProcessRxInterrupt(IN P_ADAPTER_T prAdapter) +{ +#if CFG_SDIO_INTR_ENHANCE +#if CFG_SDIO_RX_AGG + halRxSDIOAggReceiveRFBs(prAdapter); +#else + halRxSDIOEnhanceReceiveRFBs(prAdapter); +#endif +#else + halRxSDIOReceiveRFBs(prAdapter); +#endif /* CFG_SDIO_INTR_ENHANCE */ +} + +VOID halHifSwInfoInit(IN P_ADAPTER_T prAdapter) +{ + +} + +VOID halRxProcessMsduReport(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) +{ + +} + +UINT_32 halTxGetPageCount(IN UINT_32 u4FrameLength, IN BOOLEAN fgIncludeDesc) +{ + return 1; +} + +UINT_32 halDumpHifStatus(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuf, IN UINT_32 u4Max) +{ + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; + P_SDIO_STAT_COUNTER_T prStatCnt = &prHifInfo->rStatCounter; + UINT_32 u4Len = 0; + + /* Print out counter */ + LOGBUF(pucBuf, u4Max, u4Len, "\n"); + LOGBUF(pucBuf, u4Max, u4Len, "------------\n"); + + LOGBUF(pucBuf, u4Max, u4Len, "Coalescing buffer size[%u] Rx Cnt[%u/%u] DeAgg[%u] UF Cnt[%u]\n", + prAdapter->u4CoalescingBufCachedSize, prHifInfo->rRxFreeBufQueue.u4NumElem, + HIF_RX_COALESCING_BUF_COUNT, prHifInfo->rRxDeAggQueue.u4NumElem, + prStatCnt->u4RxBufUnderFlowCnt); + + LOGBUF(pucBuf, u4Max, u4Len, "Pkt cnt Tx[%u] RxP0[%u] RxP1[%u] Tx/Rx ratio[%u.%u]\n", + prStatCnt->u4DataPktWriteCnt, prStatCnt->u4PktReadCnt[0], prStatCnt->u4PktReadCnt[1], + DIV2INT(prStatCnt->u4DataPktWriteCnt, prStatCnt->u4PktReadCnt[0]), + DIV2DEC(prStatCnt->u4DataPktWriteCnt, prStatCnt->u4PktReadCnt[0])); + + LOGBUF(pucBuf, u4Max, u4Len, "Tx pkt/wt[%u.%u] pkt/kick[%u.%u] cmd/wt[%u.%u]\n", + DIV2INT(prStatCnt->u4DataPktWriteCnt, prStatCnt->u4DataPortWriteCnt), + DIV2DEC(prStatCnt->u4DataPktWriteCnt, prStatCnt->u4DataPortWriteCnt), + DIV2INT(prStatCnt->u4DataPktWriteCnt, prStatCnt->u4DataPortKickCnt), + DIV2DEC(prStatCnt->u4DataPktWriteCnt, prStatCnt->u4DataPortKickCnt), + DIV2INT(prStatCnt->u4CmdPktWriteCnt, prStatCnt->u4CmdPortWriteCnt), + DIV2DEC(prStatCnt->u4CmdPktWriteCnt, prStatCnt->u4CmdPortWriteCnt)); + + LOGBUF(pucBuf, u4Max, u4Len, "Rx P0 pkt/rd[%u.%u] P1 pkt/rd[%u.%u]\n", + DIV2INT(prStatCnt->u4PktReadCnt[0], prStatCnt->u4PortReadCnt[0]), + DIV2DEC(prStatCnt->u4PktReadCnt[0], prStatCnt->u4PortReadCnt[0]), + DIV2INT(prStatCnt->u4PktReadCnt[1], prStatCnt->u4PortReadCnt[1]), + DIV2DEC(prStatCnt->u4PktReadCnt[1], prStatCnt->u4PortReadCnt[1])); + + LOGBUF(pucBuf, u4Max, u4Len, "Tx done pending cnt TC00~05[%u, %u, %u, %u, %u, %u]\n", + prHifInfo->au4PendingTxDoneCount[TC0_INDEX], + prHifInfo->au4PendingTxDoneCount[TC1_INDEX], + prHifInfo->au4PendingTxDoneCount[TC2_INDEX], + prHifInfo->au4PendingTxDoneCount[TC3_INDEX], + prHifInfo->au4PendingTxDoneCount[TC4_INDEX], + prHifInfo->au4PendingTxDoneCount[TC5_INDEX]); + + LOGBUF(pucBuf, u4Max, u4Len, "Tx done counter/int:\n"); + LOGBUF(pucBuf, u4Max, u4Len, "AC00~03[%u.%u, %u.%u, %u.%u, %u.%u]\n", + DIV2INT(prStatCnt->u4TxDoneCnt[0], prStatCnt->u4TxDoneIntCnt[0]), + DIV2DEC(prStatCnt->u4TxDoneCnt[0], prStatCnt->u4TxDoneIntCnt[0]), + DIV2INT(prStatCnt->u4TxDoneCnt[1], prStatCnt->u4TxDoneIntCnt[1]), + DIV2DEC(prStatCnt->u4TxDoneCnt[1], prStatCnt->u4TxDoneIntCnt[1]), + DIV2INT(prStatCnt->u4TxDoneCnt[2], prStatCnt->u4TxDoneIntCnt[2]), + DIV2DEC(prStatCnt->u4TxDoneCnt[2], prStatCnt->u4TxDoneIntCnt[2]), + DIV2INT(prStatCnt->u4TxDoneCnt[3], prStatCnt->u4TxDoneIntCnt[3]), + DIV2DEC(prStatCnt->u4TxDoneCnt[3], prStatCnt->u4TxDoneIntCnt[3])); + + LOGBUF(pucBuf, u4Max, u4Len, "AC10~13[%u.%u, %u.%u, %u.%u, %u.%u]\n", + DIV2INT(prStatCnt->u4TxDoneCnt[4], prStatCnt->u4TxDoneIntCnt[4]), + DIV2DEC(prStatCnt->u4TxDoneCnt[4], prStatCnt->u4TxDoneIntCnt[4]), + DIV2INT(prStatCnt->u4TxDoneCnt[5], prStatCnt->u4TxDoneIntCnt[5]), + DIV2DEC(prStatCnt->u4TxDoneCnt[5], prStatCnt->u4TxDoneIntCnt[5]), + DIV2INT(prStatCnt->u4TxDoneCnt[6], prStatCnt->u4TxDoneIntCnt[6]), + DIV2DEC(prStatCnt->u4TxDoneCnt[5], prStatCnt->u4TxDoneIntCnt[5]), + DIV2INT(prStatCnt->u4TxDoneCnt[7], prStatCnt->u4TxDoneIntCnt[7]), + DIV2DEC(prStatCnt->u4TxDoneCnt[7], prStatCnt->u4TxDoneIntCnt[7])); + + LOGBUF(pucBuf, u4Max, u4Len, "AC20~23[%u.%u, %u.%u, %u.%u, %u.%u] FFA,CPU[%u.%u, %u.%u]\n", + DIV2INT(prStatCnt->u4TxDoneCnt[8], prStatCnt->u4TxDoneIntCnt[8]), + DIV2DEC(prStatCnt->u4TxDoneCnt[8], prStatCnt->u4TxDoneIntCnt[8]), + DIV2INT(prStatCnt->u4TxDoneCnt[9], prStatCnt->u4TxDoneIntCnt[9]), + DIV2DEC(prStatCnt->u4TxDoneCnt[9], prStatCnt->u4TxDoneIntCnt[9]), + DIV2INT(prStatCnt->u4TxDoneCnt[10], prStatCnt->u4TxDoneIntCnt[10]), + DIV2DEC(prStatCnt->u4TxDoneCnt[10], prStatCnt->u4TxDoneIntCnt[10]), + DIV2INT(prStatCnt->u4TxDoneCnt[11], prStatCnt->u4TxDoneIntCnt[11]), + DIV2DEC(prStatCnt->u4TxDoneCnt[11], prStatCnt->u4TxDoneIntCnt[11]), + DIV2INT(prStatCnt->u4TxDoneCnt[14], prStatCnt->u4TxDoneIntCnt[14]), + DIV2DEC(prStatCnt->u4TxDoneCnt[14], prStatCnt->u4TxDoneIntCnt[14]), + DIV2INT(prStatCnt->u4TxDoneCnt[15], prStatCnt->u4TxDoneIntCnt[15]), + DIV2DEC(prStatCnt->u4TxDoneCnt[15], prStatCnt->u4TxDoneIntCnt[15])); + + LOGBUF(pucBuf, u4Max, u4Len, "Pending pkt/int[%u.%u] kick/int[%u.%u] rx_enh/sts[%u.%u]\n", + DIV2INT(prStatCnt->u4TxDonePendingPktCnt, prStatCnt->u4TxDoneIntTotCnt), + DIV2DEC(prStatCnt->u4TxDonePendingPktCnt, prStatCnt->u4TxDoneIntTotCnt), + DIV2INT(prStatCnt->u4DataPortKickCnt, prStatCnt->u4TxDoneIntTotCnt), + DIV2DEC(prStatCnt->u4DataPortKickCnt, prStatCnt->u4TxDoneIntTotCnt), + DIV2INT((prStatCnt->u4IntCnt - prStatCnt->u4IntReadCnt), prStatCnt->u4IntCnt), + DIV2DEC((prStatCnt->u4IntCnt - prStatCnt->u4IntReadCnt), prStatCnt->u4IntCnt)); + +#if CFG_SDIO_TIMING_PROFILING + LOGBUF(pucBuf, u4Max, u4Len, "Tx cp_t/pkt[%u.%uus] free/pkt[%u.%uus]\n", + DIV2INT(prStatCnt->u4TxDataCpTime, prStatCnt->u4DataPktWriteCnt), + DIV2DEC(prStatCnt->u4TxDataCpTime, prStatCnt->u4DataPktWriteCnt), + DIV2INT(prStatCnt->u4TxDataFreeTime, prStatCnt->u4DataPktWriteCnt), + DIV2DEC(prStatCnt->u4TxDataFreeTime, prStatCnt->u4DataPktWriteCnt)); + + LOGBUF(pucBuf, u4Max, u4Len, "Rx P0 cp_t/pkt[%u.%uus] avg read[%u.%uus]\n", + DIV2INT(prStatCnt->u4RxDataCpTime, prStatCnt->u4PktReadCnt[0]), + DIV2DEC(prStatCnt->u4RxDataCpTime, prStatCnt->u4PktReadCnt[0]), + DIV2INT(prStatCnt->u4PortReadTime, prStatCnt->u4PortReadCnt[0]), + DIV2DEC(prStatCnt->u4PortReadTime, prStatCnt->u4PortReadCnt[0])); + + LOGBUF(pucBuf, u4Max, u4Len, "INT rd_sts/sts[%u.%uus] tx_sts/sts[%u.%uus]\n", + DIV2INT(prStatCnt->u4IntReadTime, prStatCnt->u4IntReadCnt), + DIV2DEC(prStatCnt->u4IntReadTime, prStatCnt->u4IntReadCnt), + DIV2INT(prStatCnt->u4TxDoneIntTime, prStatCnt->u4TxDoneIntTotCnt), + DIV2DEC(prStatCnt->u4TxDoneIntTime, prStatCnt->u4TxDoneIntTotCnt)); +#endif + + LOGBUF(pucBuf, u4Max, u4Len, "---------------------------------\n"); + + /* Reset statistic counter */ + kalMemZero(prStatCnt, sizeof(SDIO_STAT_COUNTER_T)); + + return u4Len; +} + +#if (CFG_SDIO_ACCESS_N9_REGISTER_BY_MAILBOX == 1) +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* This routine is used to get the value of N9 register +* by SDIO SW interrupt and mailbox. +* +* \param[in] +* pvAdapter: Pointer to the Adapter structure. +* addr: the interested address to be read +* prresult: to stored the value of the addr +* +* \return +* the error of the reading operation +*/ +/*----------------------------------------------------------------------------*/ + +BOOL halReadN9RegisterByMailBox(IN P_ADAPTER_T prAdapter, IN UINT_32 addr, IN UINT_32 *prresult) +{ + UINT_32 ori_whlpcr, temp, counter = 0; + BOOL err = TRUE, stop = FALSE; + + /* use polling mode */ + HAL_MCR_RD(prAdapter, MCR_WHLPCR, &ori_whlpcr); /* backup the original setting of W_INT_EN */ + ori_whlpcr &= WHLPCR_INT_EN_SET; + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_INT_EN_CLR); /* disabel interrupt */ + + /* progrqm h2d mailbox0 as interested register address */ + HAL_MCR_WR(prAdapter, MCR_H2DSM0R, addr); + + /* set h2d interrupt to notify firmware (bit16) */ + HAL_MCR_WR(prAdapter, MCR_WSICR, SDIO_MAILBOX_FUNC_READ_REG_IDX); + + /* polling interrupt status for the returned result */ + while (!stop) { + HAL_MCR_RD(prAdapter, MCR_WHISR, &temp); /* read clear mode */ + if (temp & SDIO_MAILBOX_FUNC_READ_REG_IDX) { + /* get the result */ + + /* read d2h mailbox0 for interested register address */ + HAL_MCR_RD(prAdapter, MCR_D2HRM0R, &temp); + if (temp == addr) { + /* read d2h mailbox1 for the value of the register */ + HAL_MCR_RD(prAdapter, MCR_D2HRM1R, prresult); + err = FALSE; + } else { + DBGLOG(HAL, ERROR, "halReadN9RegisterByMailBox >> interested address is not correct.\n"); + } + stop = TRUE; + } else { +counter++; + +if (counter > 300000) { + DBGLOG(HAL, ERROR, "halReadN9RegisterByMailBox >> get response failure.\n"); + ASSERT(0); + break; + } + } + } + + HAL_MCR_WR(prAdapter, MCR_WHLPCR, ori_whlpcr); /* restore the W_INT_EN */ + + return err; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* This routine is used to write the value of N9 register by SDIO SW interrupt and mailbox. +* +* \param[in] +* pvAdapter: Pointer to the Adapter structure. +* addr: the interested address to be write +* value: the value to write into the addr +* +* \return +* the error of the write operation +*/ +/*----------------------------------------------------------------------------*/ + +BOOL halWriteN9RegisterByMailBox(IN P_ADAPTER_T prAdapter, IN UINT_32 addr, IN UINT_32 value) +{ + UINT_32 ori_whlpcr, temp, counter = 0; + BOOL err = TRUE, stop = FALSE; + + /* use polling mode */ + HAL_MCR_RD(prAdapter, MCR_WHLPCR, &ori_whlpcr); /* backup the original setting of W_INT_EN */ + ori_whlpcr &= WHLPCR_INT_EN_SET; + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_INT_EN_CLR); /* disabel interrupt */ + + /* progrqm h2d mailbox0 as interested register address */ + HAL_MCR_WR(prAdapter, MCR_H2DSM0R, addr); + + /* progrqm h2d mailbox1 as the value to write */ + HAL_MCR_WR(prAdapter, MCR_H2DSM1R, value); + + /* set h2d interrupt to notify firmware (bit17) */ + HAL_MCR_WR(prAdapter, MCR_WSICR, SDIO_MAILBOX_FUNC_WRITE_REG_IDX); + + /* polling interrupt status for the returned result */ + while (!stop) { + HAL_MCR_RD(prAdapter, MCR_WHISR, &temp); /* read clear mode */ + + if (temp & SDIO_MAILBOX_FUNC_WRITE_REG_IDX) { + /* get the result */ + + /* read d2h mailbox0 for interested register address */ + HAL_MCR_RD(prAdapter, MCR_D2HRM0R, &temp); + if (temp == addr) + err = FALSE; + else { + DBGLOG(HAL, ERROR, "halWriteN9RegisterByMailBox >> "); + DBGLOG(HAL, ERROR, "interested address is not correct.\n"); + } + stop = TRUE; + } else { + counter++; + +if (counter > 300000) { + DBGLOG(HAL, ERROR, "halWriteN9RegisterByMailBox >> get response failure.\n"); + ASSERT(0); + break; + } + } + } + + HAL_MCR_WR(prAdapter, MCR_WHLPCR, ori_whlpcr); /* restore the W_INT_EN */ + + return err; +} +#endif + +BOOLEAN halIsPendingRx(IN P_ADAPTER_T prAdapter) +{ + return FALSE; +} + +UINT_32 halGetValidCoalescingBufSize(IN P_ADAPTER_T prAdapter) +{ + P_GL_HIF_INFO_T prHifInfo; + UINT_32 u4BufSize; +#if (MTK_WCN_HIF_SDIO == 0) + struct sdio_func *prSdioFunc; + UINT_32 u4RuntimeMaxBuf; +#endif + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + if (HIF_TX_COALESCING_BUFFER_SIZE > HIF_RX_COALESCING_BUFFER_SIZE) + u4BufSize = HIF_TX_COALESCING_BUFFER_SIZE; + else + u4BufSize = HIF_RX_COALESCING_BUFFER_SIZE; + +#if (MTK_WCN_HIF_SDIO == 0) + prSdioFunc = prHifInfo->func; + + /* Check host capability */ + /* 1. Should less than host-max_req_size */ + if (u4BufSize > prSdioFunc->card->host->max_req_size) + u4BufSize = prSdioFunc->card->host->max_req_size; + + /* 2. Should less than runtime-blksize * host-blk_count */ + u4RuntimeMaxBuf = prSdioFunc->cur_blksize * + prSdioFunc->card->host->max_blk_count; + if (u4BufSize > u4RuntimeMaxBuf) + u4BufSize = u4RuntimeMaxBuf; + + DBGLOG(INIT, TRACE, "\n" + "Final buf : 0x%X\n" + "Default TX buf : 0x%X\n" + "Default RX buf : 0x%X\n" + "Host caps -\n" + "max_req_size : 0x%X\n" + "max_seg_size : 0x%X\n" + "max_segs : 0x%X\n" + "max_blk_size : 0x%X\n" + "max_blk_count : 0x%X\n" + "Runtime -\n" + "cur_blksize : 0x%X\n", + u4BufSize, + HIF_TX_COALESCING_BUFFER_SIZE, + HIF_RX_COALESCING_BUFFER_SIZE, + prSdioFunc->card->host->max_req_size, + prSdioFunc->card->host->max_seg_size, + prSdioFunc->card->host->max_segs, + prSdioFunc->card->host->max_blk_size, + prSdioFunc->card->host->max_blk_count, + prSdioFunc->cur_blksize); +#endif + + return u4BufSize; +} + +WLAN_STATUS halAllocateIOBuffer(IN P_ADAPTER_T prAdapter) +{ + P_GL_HIF_INFO_T prHifInfo; + UINT_8 ucIdx; + P_SDIO_RX_COALESCING_BUF_T prRxBuf; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + /* 4 <5> Memory for enhanced interrupt response */ +#ifdef CFG_PREALLOC_MEMORY + prHifInfo->prSDIOCtrl = (P_SDIO_CTRL_T)preallocGetMem(MEM_ID_IO_CTRL); +#else + prHifInfo->prSDIOCtrl = (P_SDIO_CTRL_T) + kalAllocateIOBuffer(sizeof(ENHANCE_MODE_DATA_STRUCT_T)); +#endif + if (prHifInfo->prSDIOCtrl == NULL) { + DBGLOG(HAL, ERROR, + "Could not allocate %zu bytes for interrupt response.\n", + sizeof(ENHANCE_MODE_DATA_STRUCT_T)); + + return WLAN_STATUS_RESOURCES; + } + + /* Alloc coalescing buffer */ + for (ucIdx = 0; ucIdx < HIF_RX_COALESCING_BUF_COUNT; ucIdx++) { + prRxBuf = &prHifInfo->rRxCoalesingBuf[ucIdx]; + + prRxBuf->u4PktCount = 0; + + prRxBuf->u4BufSize = HIF_RX_COALESCING_BUFFER_SIZE; +#ifdef CFG_PREALLOC_MEMORY + prRxBuf->pvRxCoalescingBuf = preallocGetMem(MEM_ID_RX_DATA); +#else + prRxBuf->pvRxCoalescingBuf = kalAllocateIOBuffer(prRxBuf->u4BufSize); +#endif + if (!prRxBuf->pvRxCoalescingBuf) { + DBGLOG(HAL, ERROR, "Rx coalescing alloc failed!\n"); + continue; + } + + QUEUE_INSERT_TAIL(&prHifInfo->rRxFreeBufQueue, &prRxBuf->rQueEntry); + } + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS halReleaseIOBuffer(IN P_ADAPTER_T prAdapter) +{ + P_GL_HIF_INFO_T prHifInfo; + UINT_8 ucIdx; + P_SDIO_RX_COALESCING_BUF_T prRxBuf; + + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + /* Release coalescing buffer */ + for (ucIdx = 0; ucIdx < HIF_RX_COALESCING_BUF_COUNT; ucIdx++) { + prRxBuf = &prHifInfo->rRxCoalesingBuf[ucIdx]; +#ifndef CFG_PREALLOC_MEMORY + kalReleaseIOBuffer(prRxBuf->pvRxCoalescingBuf, prRxBuf->u4BufSize); +#endif + prRxBuf->pvRxCoalescingBuf = NULL; + } + + /* 4 <5> Memory for enhanced interrupt response */ + if (prHifInfo->prSDIOCtrl) { +#ifndef CFG_PREALLOC_MEMORY + kalReleaseIOBuffer((PVOID) prHifInfo->prSDIOCtrl, sizeof(ENHANCE_MODE_DATA_STRUCT_T)); +#endif + prHifInfo->prSDIOCtrl = (P_SDIO_CTRL_T) NULL; + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief dump firmware Assert message +* +* \param[in] +* prAdapter +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +VOID halPrintFirmwareAssertInfo(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->prGlueInfo->rHifInfo.prSDIOCtrl->u4RcvMailbox0; + u4MailBox1 = prAdapter->prGlueInfo->rHifInfo.prSDIOCtrl->u4RcvMailbox1; +#else + halGetMailbox(prAdapter, 0, &u4MailBox0); + halGetMailbox(prAdapter, 1, &u4MailBox1); +#endif + + line = u4MailBox0 & 0x0000FFFF; + + u4MailBox0 = ((u4MailBox0 >> 16) & 0x0000FFFF); + + kalMemCopy(&aucAssertFile[0], &u4MailBox0, 2); + kalMemCopy(&aucAssertFile[2], &u4MailBox1, 4); + + aucAssertFile[6] = '\0'; + + LOG_FUNC("[%s][wifi][Firmware] Assert at \"%s\" #%d\n\n", + NIC_NAME, aucAssertFile, line); + +} + +VOID halPrintMailbox(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4MailBoxStatus0, u4MailBoxStatus1; + + halGetMailbox(prAdapter, 0, &u4MailBoxStatus0); + halGetMailbox(prAdapter, 1, &u4MailBoxStatus1); + DBGLOG(INIT, ERROR, "MailBox Status = 0x%08X, 0x%08X\n", u4MailBoxStatus0, u4MailBoxStatus1); +} + +VOID halProcessSoftwareInterrupt(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) { + halPrintFirmwareAssertInfo(prAdapter); +#if CFG_CHIP_RESET_SUPPORT + glResetTrigger(prAdapter); +#endif + } + + if (u4IntrBits & WHISR_D2H_WKUP_BY_RX_PACKET) + DBGLOG(RX, INFO, "Wake up by Rx\n"); + + if (u4IntrBits & WHISR_D2H_SW_RD_MAILBOX_INT) + halPrintMailbox(prAdapter); + + if (u4IntrBits & SER_SDIO_N9_HOST_STOP_TX_OP) { + halPrintMailbox(prAdapter); + /* Stop HIF Tx operation */ + nicSerStopTx(prAdapter); + } + + if (u4IntrBits & SER_SDIO_N9_HOST_STOP_TX_RX_OP) { + halPrintMailbox(prAdapter); + /* Stop HIF Tx/Rx operation */ + nicSerStopTxRx(prAdapter); + } + + if ((u4IntrBits & ~WHISR_D2H_WKUP_BY_RX_PACKET) != 0) + DBGLOG(SW4, WARN, "u4IntrBits: 0x%x\n", u4IntrBits); + +} /* end of halProcessSoftwareInterrupt() */ + +VOID halPutMailbox(IN P_ADAPTER_T prAdapter, IN UINT_32 u4MailboxNum, IN UINT_32 u4Data) +{ + + switch (u4MailboxNum) { + case 0: + HAL_MCR_WR(prAdapter, MCR_H2DSM0R, u4Data); + break; + case 1: + HAL_MCR_WR(prAdapter, MCR_H2DSM1R, u4Data); + break; + + default: + ASSERT(0); + } + +} + +VOID halGetMailbox(IN P_ADAPTER_T prAdapter, IN UINT_32 u4MailboxNum, OUT PUINT_32 pu4Data) +{ + switch (u4MailboxNum) { + case 0: + HAL_MCR_RD(prAdapter, MCR_D2HRM0R, pu4Data); + break; + case 1: + HAL_MCR_RD(prAdapter, MCR_D2HRM1R, pu4Data); + break; + + default: + ASSERT(0); + } +} + +VOID halDeAggRxPktProc(P_ADAPTER_T prAdapter, P_SDIO_RX_COALESCING_BUF_T prRxBuf) +{ + P_GL_HIF_INFO_T prHifInfo; + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; + PUINT_8 pucSrcAddr; + UINT_16 u2PktLength; + UINT_32 i; + BOOLEAN fgReschedule = FALSE; + + QUE_T rTempFreeRfbList, rTempRxRfbList; + P_QUE_T prTempFreeRfbList = &rTempFreeRfbList; + P_QUE_T prTempRxRfbList = &rTempRxRfbList; + + KAL_SPIN_LOCK_DECLARATION(); + SDIO_TIME_INTERVAL_DEC(); + + prRxCtrl = &prAdapter->rRxCtrl; + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + QUEUE_INITIALIZE(prTempFreeRfbList); + QUEUE_INITIALIZE(prTempRxRfbList); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + if (prRxCtrl->rFreeSwRfbList.u4NumElem < prRxBuf->u4PktCount) { + fgReschedule = TRUE; + } else { + /* Get enough free SW_RFB to be Rx */ + for (i = 0; i < prRxBuf->u4PktCount; i++) { + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); + QUEUE_INSERT_TAIL(prTempFreeRfbList, &prSwRfb->rQueEntry); + } + fgReschedule = FALSE; + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + if (fgReschedule) { + mutex_lock(&prHifInfo->rRxDeAggQueMutex); + QUEUE_INSERT_HEAD(&prHifInfo->rRxDeAggQueue, (P_QUE_ENTRY_T)prRxBuf); + mutex_unlock(&prHifInfo->rRxDeAggQueMutex); + + /* Reschedule this work */ + if ((prAdapter->prGlueInfo->ulFlag & GLUE_FLAG_HALT) == 0) + schedule_delayed_work(&prAdapter->prGlueInfo->rRxPktDeAggWork, 0); + + return; + } + + + pucSrcAddr = prRxBuf->pvRxCoalescingBuf; + + SDIO_REC_TIME_START(); + for (i = 0; i < prRxBuf->u4PktCount; i++) { + u2PktLength = HAL_RX_STATUS_GET_RX_BYTE_CNT((P_HW_MAC_RX_DESC_T)pucSrcAddr); + + QUEUE_REMOVE_HEAD(prTempFreeRfbList, prSwRfb, P_SW_RFB_T); + kalMemCopy(prSwRfb->pucRecvBuff, pucSrcAddr, ALIGN_4(u2PktLength + HIF_RX_HW_APPENDED_LEN)); + + prSwRfb->ucPacketType = (UINT_8)HAL_RX_STATUS_GET_PKT_TYPE(prSwRfb->prRxStatus); + + QUEUE_INSERT_TAIL(prTempRxRfbList, &prSwRfb->rQueEntry); + + pucSrcAddr += ALIGN_4(u2PktLength + HIF_RX_HW_APPENDED_LEN); + } + SDIO_REC_TIME_END(); + SDIO_ADD_TIME_INTERVAL(prHifInfo->rStatCounter.u4RxDataCpTime); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + RX_ADD_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT, prTempRxRfbList->u4NumElem); + QUEUE_CONCATENATE_QUEUES(&prRxCtrl->rReceivedRfbList, prTempRxRfbList); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + /* Wake up Rx handling thread */ + set_bit(GLUE_FLAG_RX_BIT, &(prAdapter->prGlueInfo->ulFlag)); + wake_up_interruptible(&(prAdapter->prGlueInfo->waitq)); + + if (prTempFreeRfbList->u4NumElem) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + QUEUE_CONCATENATE_QUEUES(&prRxCtrl->rFreeSwRfbList, prTempFreeRfbList); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + } + + prRxBuf->u4PktCount = 0; + mutex_lock(&prHifInfo->rRxFreeBufQueMutex); + QUEUE_INSERT_TAIL(&prHifInfo->rRxFreeBufQueue, (P_QUE_ENTRY_T)prRxBuf); + mutex_unlock(&prHifInfo->rRxFreeBufQueMutex); +} + +VOID halDeAggRxPktWorker(struct work_struct *work) +{ + P_GLUE_INFO_T prGlueInfo; + P_GL_HIF_INFO_T prHifInfo; + P_ADAPTER_T prAdapter; + P_SDIO_RX_COALESCING_BUF_T prRxBuf; + P_RX_CTRL_T prRxCtrl; + + if (g_u4HaltFlag) + return; + + prGlueInfo = ENTRY_OF(work, GLUE_INFO_T, rRxPktDeAggWork); + prHifInfo = &prGlueInfo->rHifInfo; + prAdapter = prGlueInfo->prAdapter; + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) + return; + + prRxCtrl = &prAdapter->rRxCtrl; + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + mutex_lock(&prHifInfo->rRxDeAggQueMutex); + QUEUE_REMOVE_HEAD(&prHifInfo->rRxDeAggQueue, prRxBuf, P_SDIO_RX_COALESCING_BUF_T); + mutex_unlock(&prHifInfo->rRxDeAggQueMutex); + + while (prRxBuf) { + halDeAggRxPktProc(prAdapter, prRxBuf); + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) + return; + + mutex_lock(&prHifInfo->rRxDeAggQueMutex); + QUEUE_REMOVE_HEAD(&prHifInfo->rRxDeAggQueue, prRxBuf, P_SDIO_RX_COALESCING_BUF_T); + mutex_unlock(&prHifInfo->rRxDeAggQueMutex); + } +} + +VOID halDeAggRxPkt(P_ADAPTER_T prAdapter, P_SDIO_RX_COALESCING_BUF_T prRxBuf) +{ + P_GL_HIF_INFO_T prHifInfo; + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + /* Avoid to schedule DeAggWorker during uninit flow */ + if (prAdapter->prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + mutex_lock(&prHifInfo->rRxFreeBufQueMutex); + QUEUE_INSERT_TAIL(&prHifInfo->rRxFreeBufQueue, (P_QUE_ENTRY_T)prRxBuf); + mutex_unlock(&prHifInfo->rRxFreeBufQueMutex); + + return; + } + +#if CFG_SDIO_RX_AGG_TASKLET + mutex_lock(&prHifInfo->rRxDeAggQueMutex); + QUEUE_INSERT_TAIL(&prHifInfo->rRxDeAggQueue, (P_QUE_ENTRY_T)prRxBuf); + mutex_unlock(&prHifInfo->rRxDeAggQueMutex); + + schedule_delayed_work(&prAdapter->prGlueInfo->rRxPktDeAggWork, 0); +#else + halDeAggRxPktProc(prAdapter, prRxBuf); +#endif +} + +VOID halRxTasklet(unsigned long data) +{ + +} + +VOID halTxCompleteTasklet(unsigned long data) +{ + +} + +/* Hif power off wifi */ +WLAN_STATUS halHifPowerOffWifi(IN P_ADAPTER_T prAdapter) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + if (prAdapter->rAcpiState == ACPI_STATE_D0 && + !wlanIsChipNoAck(prAdapter) && !kalIsCardRemoved(prAdapter->prGlueInfo)) { + /* 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) { + UINT_32 i; + /* 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 */ + rStatus = wlanCheckWifiFunc(prAdapter, FALSE); + } +#if !CFG_ENABLE_FULL_PM + /* 4. Set Onwership to F/W */ + nicpmSetFWOwn(prAdapter, FALSE); +#endif + +#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); + } + return rStatus; +} + +VOID halPollDbgCr(IN P_ADAPTER_T prAdapter, IN UINT_32 u4LoopCount) +{ + UINT_32 u4Data = 0; + UINT_32 u4Loop = 0; + + for (u4Loop = 0; u4Loop < u4LoopCount; u4Loop++) { + HAL_MCR_RD(prAdapter, MCR_SWPCDBGR, &u4Data); + DBGLOG(INIT, WARN, "SWPCDBGR 0x%08X\n", u4Data); + } +} + +VOID halSerHifReset(IN P_ADAPTER_T prAdapter) +{ + P_GL_HIF_INFO_T prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + UINT_32 i; + + KAL_SPIN_LOCK_DECLARATION(); + + /* Restore Tx resource */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + for (i = TC0_INDEX; i <= TC5_INDEX; i++) { + nicTxReleaseResource(prAdapter, i, prHifInfo->au4PendingTxDoneCount[i], FALSE); + prHifInfo->au4PendingTxDoneCount[i] = 0; + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + /* Clear interrupt status from Rx interrupt enhance mode */ + prHifInfo->fgIsPendingInt = FALSE; + kalMemZero(prHifInfo->prSDIOCtrl, sizeof(ENHANCE_MODE_DATA_STRUCT_T)); +} + +VOID halPrintHifDbgInfo(IN P_ADAPTER_T prAdapter) +{ + halPrintMailbox(prAdapter); + halPollDbgCr(prAdapter, LP_OWN_BACK_FAILED_DBGCR_POLL_ROUND); +} + +BOOLEAN halIsTxResourceControlEn(IN P_ADAPTER_T prAdapter) +{ + return TRUE; +} + +VOID halTxResourceResetHwTQCounter(IN P_ADAPTER_T prAdapter) +{ + PUINT_32 pu4WHISR = NULL; + UINT_16 au2TxCount[16]; + + pu4WHISR = (PUINT_32)kalMemAlloc(sizeof(UINT_32), PHY_MEM_TYPE); + if (!pu4WHISR) { + DBGLOG(INIT, ERROR, "Allocate pu4WHISR fail\n"); + return; + } + + HAL_READ_INTR_STATUS(prAdapter, sizeof(UINT_32), (PUINT_8)pu4WHISR); + if (HAL_IS_TX_DONE_INTR(*pu4WHISR)) + HAL_READ_TX_RELEASED_COUNT(prAdapter, au2TxCount); + + if (pu4WHISR) + kalMemFree(pu4WHISR, PHY_MEM_TYPE, sizeof(UINT_32)); +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/include/hif.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/include/hif.h new file mode 100644 index 0000000000000..78eb1d231b197 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/include/hif.h @@ -0,0 +1,336 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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 +*/ + + +#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 +******************************************************************************** +*/ +#if MTK_WCN_HIF_SDIO +#define HIF_SDIO_SUPPORT_GPIO_SLEEP_MODE 1 +#else +#define HIF_SDIO_SUPPORT_GPIO_SLEEP_MODE 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 +******************************************************************************** +*/ +#if defined(_HIF_SDIO) +#define HIF_NAME "SDIO" +#else +#error "No HIF defined!" +#endif + + +/* Enable driver timing profiling */ +#define CFG_SDIO_TIMING_PROFILING 0 + +#define SDIO_X86_WORKAROUND_WRITE_MCR 0x00C4 +#define HIF_NUM_OF_QM_RX_PKT_NUM 512 + +#define HIF_TX_INIT_CMD_PORT TX_RING_FWDL_IDX_3 + +#define HIF_IST_LOOP_COUNT 128 +#define HIF_IST_TX_THRESHOLD 32 /* Min msdu count to trigger Tx during INT polling state */ + +#define HIF_TX_MAX_AGG_LENGTH (511 * 512) /* 511 blocks x 512 */ + +#define HIF_RX_MAX_AGG_NUM 16 +/*!< Setting the maximum RX aggregation number 0: no limited (16) */ + +#define HIF_TX_BUFF_COUNT_TC0 8 +#define HIF_TX_BUFF_COUNT_TC1 167 +#define HIF_TX_BUFF_COUNT_TC2 8 +#define HIF_TX_BUFF_COUNT_TC3 8 +#define HIF_TX_BUFF_COUNT_TC4 7 +#define HIF_TX_BUFF_COUNT_TC5 0 + +#define HIF_TX_RESOURCE_CTRL 1 /* enable/disable TX resource control */ + +#define HIF_TX_PAGE_SIZE_IN_POWER_OF_2 11 +#define HIF_TX_PAGE_SIZE 2048 /* in unit of bytes */ + +#define HIF_EXTRA_IO_BUFFER_SIZE \ + (sizeof(ENHANCE_MODE_DATA_STRUCT_T) + HIF_RX_COALESCING_BUF_COUNT * HIF_RX_COALESCING_BUFFER_SIZE) + +#define HIF_CR4_FWDL_SECTION_NUM 2 +#define HIF_IMG_DL_STATUS_PORT_IDX 0 + +#define HIF_RX_ENHANCE_MODE_PAD_LEN 4 + +#define HIF_TX_TERMINATOR_LEN 4 + +#if CFG_SDIO_TX_AGG +#define HIF_TX_COALESCING_BUFFER_SIZE (HIF_TX_MAX_AGG_LENGTH) +#else +#define HIF_TX_COALESCING_BUFFER_SIZE (CFG_TX_MAX_PKT_SIZE) +#endif + +#if CFG_SDIO_RX_AGG +#define HIF_RX_COALESCING_BUFFER_SIZE ((HIF_RX_MAX_AGG_NUM + 1) * CFG_RX_MAX_PKT_SIZE) +#else +#define HIF_RX_COALESCING_BUFFER_SIZE (CFG_RX_MAX_PKT_SIZE) +#endif + +#define HIF_RX_COALESCING_BUF_COUNT 16 + +/* WHISR device to host (D2H) */ +/* N9 Interrupt Host to stop tx/rx operation (at the moment, HIF tx/rx are stopted) */ +#define SER_SDIO_N9_HOST_STOP_TX_RX_OP BIT(8) +/* N9 Interrupt Host to stop tx operation (at the moment, HIF tx are stopted) */ +#define SER_SDIO_N9_HOST_STOP_TX_OP BIT(9) +/* N9 Interrupt Host all modules were reset done (to let host reinit HIF) */ +#define SER_SDIO_N9_HOST_RESET_DONE BIT(10) +/* N9 Interrupt Host System Error Recovery Done */ +#define SER_SDIO_N9_HOST_RECOVERY_DONE BIT(11) + +/* WSICR host to device (H2D) */ +/* Host ACK HIF tx/rx ring stop operatio */ +#define SER_SDIO_HOST_N9_STOP_TX_RX_OP_ACK BIT(19) +/* Host interrupt N9 HIF init done */ +#define SER_SDIO_HOST_N9_RESET_DONE_ACK BIT(20) +/* Host interrupt N9 System Error Recovery done */ +#define SER_SDIO_HOST_N9_RECOVERY_DONE_ACK BIT(21) + +/******************************************************************************* +* 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 _SDIO_STAT_COUNTER_T { + /* Tx data */ + UINT_32 u4DataPortWriteCnt; + UINT_32 u4DataPktWriteCnt; + UINT_32 u4DataPortKickCnt; + + /* Tx command */ + UINT_32 u4CmdPortWriteCnt; + UINT_32 u4CmdPktWriteCnt; + + /* Tx done interrupt */ + UINT_32 u4TxDoneCnt[16]; + UINT_32 u4TxDoneIntCnt[16]; + UINT_32 u4TxDoneIntTotCnt; + UINT_32 u4TxDonePendingPktCnt; + + UINT_32 u4IntReadCnt; + UINT_32 u4IntCnt; + + /* Rx data/cmd*/ + UINT_32 u4PortReadCnt[2]; + UINT_32 u4PktReadCnt[2]; + + UINT_32 u4RxBufUnderFlowCnt; + +#if CFG_SDIO_TIMING_PROFILING + UINT_32 u4TxDataCpTime; + UINT_32 u4TxDataFreeTime; + + UINT_32 u4RxDataCpTime; + UINT_32 u4PortReadTime; + + UINT_32 u4TxDoneIntTime; + UINT_32 u4IntReadTime; +#endif +} SDIO_STAT_COUNTER_T, *P_SDIO_STAT_COUNTER_T; + +typedef struct _SDIO_RX_COALESCING_BUF_T { + QUE_ENTRY_T rQueEntry; + PVOID pvRxCoalescingBuf; + UINT_32 u4BufSize; + UINT_32 u4PktCount; +} SDIO_RX_COALESCING_BUF_T, *P_SDIO_RX_COALESCING_BUF_T; + +/* 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 + + P_SDIO_CTRL_T prSDIOCtrl; + + BOOLEAN fgIntReadClear; + BOOLEAN fgMbxReadClear; + QUE_T rFreeQueue; + BOOLEAN fgIsPendingInt; + + UINT_32 au4PendingTxDoneCount[6]; + + /* Statistic counter */ + SDIO_STAT_COUNTER_T rStatCounter; + + SDIO_RX_COALESCING_BUF_T rRxCoalesingBuf[HIF_RX_COALESCING_BUF_COUNT]; + + QUE_T rRxDeAggQueue; + QUE_T rRxFreeBufQueue; + + struct mutex rRxFreeBufQueMutex; + struct mutex rRxDeAggQueMutex; +} GL_HIF_INFO_T, *P_GL_HIF_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_SDIO_TIMING_PROFILING +#define SDIO_TIME_INTERVAL_DEC() KAL_TIME_INTERVAL_DECLARATION() +#define SDIO_REC_TIME_START() KAL_REC_TIME_START() +#define SDIO_REC_TIME_END() KAL_REC_TIME_END() +#define SDIO_GET_TIME_INTERVAL() KAL_GET_TIME_INTERVAL() +#define SDIO_ADD_TIME_INTERVAL(_Interval) KAL_ADD_TIME_INTERVAL(_Interval) +#else +#define SDIO_TIME_INTERVAL_DEC() +#define SDIO_REC_TIME_START() +#define SDIO_REC_TIME_END() +#define SDIO_GET_TIME_INTERVAL() +#define SDIO_ADD_TIME_INTERVAL(_Interval) +#endif + +/******************************************************************************* +* 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, ULONG ulCookie); + +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); + +void glGetDev(PVOID ctx, struct device **dev); + +void glGetHifDev(P_GL_HIF_INFO_T prHif, struct device **dev); + +BOOLEAN glWakeupSdio(P_GLUE_INFO_T prGlueInfo); + +#if !CFG_SDIO_INTR_ENHANCE +VOID halRxSDIOReceiveRFBs(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS halRxReadBuffer(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb); + +#else +VOID halRxSDIOEnhanceReceiveRFBs(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS halRxEnhanceReadBuffer(IN P_ADAPTER_T prAdapter, IN UINT_32 u4DataPort, + IN UINT_16 u2RxLength, IN OUT P_SW_RFB_T prSwRfb); + +VOID halProcessEnhanceInterruptStatus(IN P_ADAPTER_T prAdapter); + +#endif /* CFG_SDIO_INTR_ENHANCE */ + +#if CFG_SDIO_RX_AGG +VOID halRxSDIOAggReceiveRFBs(IN P_ADAPTER_T prAdapter); +#endif + +VOID halPutMailbox(IN P_ADAPTER_T prAdapter, IN UINT_32 u4MailboxNum, IN UINT_32 u4Data); +VOID halGetMailbox(IN P_ADAPTER_T prAdapter, IN UINT_32 u4MailboxNum, OUT PUINT_32 pu4Data); +VOID halDeAggRxPkt(P_ADAPTER_T prAdapter, P_SDIO_RX_COALESCING_BUF_T prRxBuf); +VOID halPrintMailbox(IN P_ADAPTER_T prAdapter); +VOID halPollDbgCr(IN P_ADAPTER_T prAdapter, IN UINT_32 u4LoopCount); +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _HIF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/include/hif_sdio.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/include/hif_sdio.h new file mode 100644 index 0000000000000..ec1449e40758d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/include/hif_sdio.h @@ -0,0 +1,259 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/sdio/include/hif_sdio.h#2 +*/ + +/*! \file "hif_sdio.h" +* \brief +* +* +*/ + + +#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:turn off debug msg and assert, 1:turn 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 (8) + +#define HIF_DEFAULT_BLK_SIZE (256) +#define HIF_DEFAULT_VENDOR (0x037A) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/* sdio driver data mapping */ +typedef struct _MTK_WCN_SDIO_DRIVER_DATA_MAPPING { + UINT_16 card_id; /* TPLMID_CARD: card ID */ + struct mt66xx_hif_driver_data *mt66xx_driver_data; +} MTK_WCN_SDIO_DRIVER_DATA_MAPPING; + + +/* 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 ULONG MTK_WCN_HIF_SDIO_CLTCTX; + +/* Callback functions provided by client driver */ +typedef INT_32(*MTK_WCN_HIF_SDIO_PROBE)(MTK_WCN_HIF_SDIO_CLTCTX, const MTK_WCN_HIF_SDIO_FUNCINFO *prFuncInfo); +typedef INT_32(*MTK_WCN_HIF_SDIO_REMOVE)(MTK_WCN_HIF_SDIO_CLTCTX); +typedef INT_32(*MTK_WCN_HIF_SDIO_IRQ)(MTK_WCN_HIF_SDIO_CLTCTX); + +/* Function info provided by client driver */ +struct _MTK_WCN_HIF_SDIO_FUNCINFO { + UINT_16 manf_id; /* TPLMID_MANF: manufacturer ID */ + UINT_16 card_id; /* TPLMID_CARD: card ID */ + UINT_16 func_num; /* Function Number */ + UINT_16 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 */ + UINT_32 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 */ + INT_8 clt_idx; /* registered function table info element number (initial value is -1) */ + MTK_WCN_BOOL interrupted; /* TRUE: interrupted, FALSE: not interrupted */ + void *private_data_p; /* clt's private data pointer */ +} 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 */ + INT_8 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, /* generic error */ + HIF_SDIO_ERR_INVALID_PARAM, + HIF_SDIO_ERR_DUPLICATED, + HIF_SDIO_ERR_UNSUP_MANF_ID, + HIF_SDIO_ERR_UNSUP_CARD_ID, + HIF_SDIO_ERR_INVALID_FUNC_NUM, + HIF_SDIO_ERR_INVALID_BLK_SZ, +} 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) + +/*! + * \brief A debug print used to print debug messages while compiler flag HIF_SDIO_DEBUG on. + * + */ +#if HIF_SDIO_DEBUG +#define DPRINTK(fmt, args...) pr_debug("%s: " fmt, __func__, ## args) +#else +#define DPRINTK(fmt, args...) +#endif + +/*! + * \brief ASSERT function definition. + * + */ +#if HIF_SDIO_DEBUG +#define ASSERT(expr) \ + { \ + if (!(expr)) { \ + LOG_FUNC("assertion failed! %s[%d]: %s\n",\ + __func__, __LINE__, #expr); \ + WARN_ON(!(expr));\ + } \ + } +#else +#define 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 INT_32 mtk_wcn_hif_sdio_client_reg(const MTK_WCN_HIF_SDIO_CLTINFO *pinfo); + +extern INT_32 mtk_wcn_hif_sdio_client_unreg(const MTK_WCN_HIF_SDIO_CLTINFO *pinfo); + +extern INT_32 mtk_wcn_hif_sdio_readb(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT_32 offset, PUINT_8 pvb); + +extern INT_32 mtk_wcn_hif_sdio_writeb(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT_32 offset, UINT_8 vb); + +extern INT_32 mtk_wcn_hif_sdio_readl(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT_32 offset, PUINT_32 pvl); + +extern INT_32 mtk_wcn_hif_sdio_writel(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT_32 offset, UINT_32 vl); + +extern INT_32 mtk_wcn_hif_sdio_read_buf(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT_32 offset, PUINT_32 pbuf, UINT_32 len); + +extern INT_32 mtk_wcn_hif_sdio_write_buf(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT_32 offset, PUINT_32 pbuf, UINT_32 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); + +extern INT_32 mtk_wcn_hif_sdio_wake_up_ctrl(MTK_WCN_HIF_SDIO_CLTCTX ctx); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _HIF_SDIO_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/include/mtk_porting.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/include/mtk_porting.h new file mode 100644 index 0000000000000..89c2f378f3e70 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/include/mtk_porting.h @@ -0,0 +1,92 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* porting layer */ +/* Android */ + +#ifndef _MTK_PORTING_H_ +#define _MTK_PORTING_H_ + +#include /* include stddef.h for NULL */ + +/* 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 INT_32(*MUTEX_DESTROY) (MTK_WCN_MUTEX mtx); +typedef INT_32(*MUTEX_LOCK) (MTK_WCN_MUTEX mtx); +typedef INT_32(*MUTEX_UNLOCK) (MTK_WCN_MUTEX mtx, unsigned long flags); +/* debug */ +typedef INT_32(*DBG_PRINT) (const char *str, ...); +typedef INT_32(*DBG_ASSERT) (INT_32 expr, const char *file, INT_32 line); +/* timer */ +typedef void (*MTK_WCN_TIMER_CB) (void); +typedef MTK_WCN_TIMER(*TIMER_CREATE) (const char *const name); +typedef INT_32(*TIMER_DESTROY) (MTK_WCN_TIMER tmr); +typedef INT_32(*TIMER_START) (MTK_WCN_TIMER tmr, UINT_32 timeout, MTK_WCN_TIMER_CB tmr_cb, void *param); +typedef INT_32(*TIMER_STOP) (MTK_WCN_TIMER tmr); +/* kernel lib */ +typedef void *(*SYS_MEMCPY) (void *dest, const void *src, UINT_32 n); +typedef void *(*SYS_MEMSET) (void *s, INT_32 c, UINT_32 n); +typedef INT_32(*SYS_SPRINTF) (char *str, const char *format, ...); + +#endif /* _MTK_PORTING_H_ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/sdio.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/sdio.c new file mode 100644 index 0000000000000..ed750adf00b24 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/sdio.c @@ -0,0 +1,1698 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** +*[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. +******************************************************************************/ + + +/******************************************************************************* +* C O M P I L E 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 "precomp.h" + +#if MTK_WCN_HIF_SDIO +#include "hif_sdio.h" +#else +#include +#include +#include +#include /* sdio_readl(), etc */ +#include +#endif + +#include +#ifndef CONFIG_X86 +#include +#endif + +#include "mt66xx_reg.h" + +#if (CFG_SDIO_1BIT_DATA_MODE == 1) +#include "test_driver_sdio_ops.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" + +#define HIF_SDIO_ACCESS_RETRY_LIMIT 3 +#define HIF_SDIO_INTERRUPT_RESPONSE_TIMEOUT (15000) + +#if MTK_WCN_HIF_SDIO + +/* + * function prototypes + * + */ + +static INT_32 mtk_sdio_probe(MTK_WCN_HIF_SDIO_CLTCTX, const MTK_WCN_HIF_SDIO_FUNCINFO *); + +static INT_32 mtk_sdio_remove(MTK_WCN_HIF_SDIO_CLTCTX); +static INT_32 mtk_sdio_interrupt(MTK_WCN_HIF_SDIO_CLTCTX); + +/* + * sdio function info table + */ + +static MTK_WCN_HIF_SDIO_FUNCINFO funcInfo[] = { + {MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x6602, 0x1, 512)}, +}; + +static MTK_WCN_SDIO_DRIVER_DATA_MAPPING sdio_driver_data_mapping[] = { + {0x6602, &mt66xx_driver_data_mt6632}, +}; + +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 +/* + * function prototypes + * + */ +static int mtk_sdio_pm_suspend(struct device *pDev); +static int mtk_sdio_pm_resume(struct device *pDev); + +const struct sdio_device_id mtk_sdio_ids[] = { + { SDIO_DEVICE(0x037a, 0x6602), + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_mt6632},/* Not an SDIO standard class device */ + { SDIO_DEVICE(0x037a, 0x7608), + .driver_data = (kernel_ulong_t)&mt66xx_driver_data_mt7668},/* Not an SDIO standard class device */ + { /* 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 +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static probe_card pfWlanProbe; +static remove_card pfWlanRemove; + +#if (MTK_WCN_HIF_SDIO == 0) +static const struct dev_pm_ops mtk_sdio_pm_ops = { + .suspend = mtk_sdio_pm_suspend, + .resume = mtk_sdio_pm_resume, +}; + +static struct sdio_driver mtk_sdio_driver = { +#ifdef CFG_SUPPORT_DUAL_CARD_DUAL_DRIVER_B + .name = "wlanb", /* "MTK SDIO WLAN Driver" */ +#else + .name = "wlan", /* "MTK SDIO WLAN Driver" */ +#endif + .id_table = mtk_sdio_ids, + .probe = NULL, + .remove = NULL, + .drv = { + .owner = THIS_MODULE, + .pm = &mtk_sdio_pm_ops, + } +}; +#endif + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define dev_to_sdio_func(d) container_of(d, struct sdio_func, dev) + + +/******************************************************************************* +* 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 a SDIO interrupt callback function +* +* \param[in] func pointer to SDIO handle +* +* \return void +*/ +/*----------------------------------------------------------------------------*/ + +#if MTK_WCN_HIF_SDIO + +static INT_32 mtk_sdio_interrupt(MTK_WCN_HIF_SDIO_CLTCTX cltCtx) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 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->ulFlag & GLUE_FLAG_HALT) { + /* printk(KERN_INFO DRV_NAME"GLUE_FLAG_HALT skip INT\n"); */ + ret = mtk_wcn_hif_sdio_writeb(cltCtx, MCR_WHLPCR, WHLPCR_INT_EN_CLR); + return ret; + } + + ret = mtk_wcn_hif_sdio_writeb(cltCtx, MCR_WHLPCR, WHLPCR_INT_EN_CLR); + + prGlueInfo->rHifInfo.fgIsPendingInt = FALSE; + + kalSetIntEvent(prGlueInfo); + + return ret; +} + +#else +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->ulFlag & GLUE_FLAG_HALT) { + sdio_writeb(prGlueInfo->rHifInfo.func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, &ret); + /* printk(KERN_INFO DRV_NAME"GLUE_FLAG_HALT skip INT\n"); */ + return; + } + + sdio_writeb(prGlueInfo->rHifInfo.func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, &ret); + + kalSetIntEvent(prGlueInfo); +} +#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; +INT_32 mtk_sdio_probe( + MTK_WCN_HIF_SDIO_CLTCTX cltCtx, + const MTK_WCN_HIF_SDIO_FUNCINFO *prFuncInfo) +{ + INT_32 ret = HIF_SDIO_ERR_SUCCESS; + INT_32 i = 0; + INT_32 dd_table_len = sizeof(sdio_driver_data_mapping) / sizeof(MTK_WCN_SDIO_DRIVER_DATA_MAPPING); + struct mt66xx_hif_driver_data *sdio_driver_data = NULL; + + prFunc = prFuncInfo; + + for (i = 0; i < dd_table_len; i++) { + if (prFunc->card_id == sdio_driver_data_mapping[i].card_id) { + sdio_driver_data = sdio_driver_data_mapping[i].mt66xx_driver_data; + break; + } + } + + if (sdio_driver_data == NULL) { + DBGLOG(HAL, ERROR, "sdio probe error: %x driver data not found!\n", prFunc->card_id); + return HIF_SDIO_ERR_UNSUP_CARD_ID; + } + + if (pfWlanProbe((PVOID)&cltCtx, (PVOID) sdio_driver_data) != 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 +int mtk_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) +{ + int ret = 0; +#if defined(CFG_SUPPORT_DUAL_CARD_DUAL_DRIVER_A) +#define MMC_FILTER "mmc1" +#elif defined(CFG_SUPPORT_DUAL_CARD_DUAL_DRIVER_B) +#define MMC_FILTER "mmc0" +#endif + + /* 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]); + * + */ +#ifdef MMC_FILTER + if (strcmp(mmc_hostname(func->card->host), MMC_FILTER) == 0) { + ret = -1; + goto out; + } +#endif + + + + 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, (PVOID) id->driver_data) != WLAN_STATUS_SUCCESS) { + /* printk(KERN_WARNING DRV_NAME"pfWlanProbe fail!call pfWlanRemove()\n"); */ + pfWlanRemove(); + ret = -1; + } + +out: + /* printk(KERN_INFO DRV_NAME"mtk_sdio_probe() done(%d)\n", ret); */ + return ret; +} +#endif + +#if MTK_WCN_HIF_SDIO +INT_32 mtk_sdio_remove(MTK_WCN_HIF_SDIO_CLTCTX cltCtx) +{ + INT_32 ret = HIF_SDIO_ERR_SUCCESS; + /* printk(KERN_INFO DRV_NAME"pfWlanRemove done\n"); */ + pfWlanRemove(); + + return ret; +} +#else +void mtk_sdio_remove(struct sdio_func *func) +{ + /* printk(KERN_INFO DRV_NAME"mtk_sdio_remove()\n"); */ + + 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_pm_suspend(struct device *pDev) +{ + int ret = 0, wait = 0; + int pm_caps, set_flag; + const char *func_id; + struct sdio_func *func; + P_GLUE_INFO_T prGlueInfo = NULL; + + DBGLOG(HAL, STATE, "==>\n"); + + func = dev_to_sdio_func(pDev); + prGlueInfo = sdio_get_drvdata(func); + + /* This suspend API could be triggered multiple times. + * Make sure wlanSuspendPmHandle() called once only. + */ + if (prGlueInfo->prAdapter->fgForceFwOwn == FALSE) + wlanSuspendPmHandle(prGlueInfo); + + prGlueInfo->prAdapter->fgForceFwOwn = TRUE; + + /* Wait for + * 1. The other unfinished ownership handshakes + * 2. FW own back + */ + wait = 0; + while (1) { + if (prGlueInfo->prAdapter->u4PwrCtrlBlockCnt == 0 + && prGlueInfo->prAdapter->fgIsFwOwn == TRUE) { + DBGLOG(HAL, STATE, "************************\n"); + DBGLOG(HAL, STATE, "* Entered SDIO Supsend *\n"); + DBGLOG(HAL, STATE, "************************\n"); + DBGLOG(HAL, INFO, "wait = %d\n\n", wait); + break; + } + + ACQUIRE_POWER_CONTROL_FROM_PM(prGlueInfo->prAdapter); + kalMsleep(5); + RECLAIM_POWER_CONTROL_TO_PM(prGlueInfo->prAdapter, FALSE); + + if (wait > 200) { + DBGLOG(HAL, ERROR, "Timeout !!\n\n"); + return -EAGAIN; + } + wait++; + } + + pm_caps = sdio_get_host_pm_caps(func); + func_id = sdio_func_id(func); + + /* Ask kernel keeping SDIO bus power-on */ + set_flag = MMC_PM_KEEP_POWER; + ret = sdio_set_host_pm_flags(func, set_flag); + if (ret) { + DBGLOG(HAL, ERROR, "set flag %d err %d\n", set_flag, ret); + DBGLOG(HAL, ERROR, + "%s: cannot remain alive(0x%X)\n", func_id, pm_caps); + return -ENOSYS; + } + + /* If wow enable, ask kernel accept SDIO IRQ in suspend mode */ + if (prGlueInfo->prAdapter->rWifiVar.ucWow && + prGlueInfo->prAdapter->rWowCtrl.fgWowEnable) { + set_flag = MMC_PM_WAKE_SDIO_IRQ; + ret = sdio_set_host_pm_flags(func, set_flag); + if (ret) { + DBGLOG(HAL, ERROR, "set flag %d err %d\n", set_flag, ret); + DBGLOG(HAL, ERROR, + "%s: cannot sdio wake-irq(0x%X)\n", func_id, pm_caps); + } + } + + DBGLOG(HAL, STATE, "<==\n"); + return 0; +} + +static int mtk_sdio_pm_resume(struct device *pDev) +{ + struct sdio_func *func; + P_GLUE_INFO_T prGlueInfo = NULL; + + DBGLOG(HAL, STATE, "==>\n"); + + func = dev_to_sdio_func(pDev); + prGlueInfo = sdio_get_drvdata(func); + + prGlueInfo->prAdapter->fgForceFwOwn = FALSE; + + wlanResumePmHandle(prGlueInfo); + + DBGLOG(HAL, STATE, "<==\n"); + return 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 mtk_sdio_pm_suspend(pDev); +} + +int mtk_sdio_resume(struct device *pDev) +{ + /* printk(KERN_INFO "mtk_sdio: mtk_sdio_resume dev(0x%p)\n", pDev); */ + + return mtk_sdio_pm_resume(pDev); +} +#if (CFG_SDIO_ASYNC_IRQ_AUTO_ENABLE == 1) +int mtk_sdio_async_irq_enable(struct sdio_func *func) +{ +#define SDIO_CCCR_IRQ_EXT 0x16 +#define SDIO_IRQ_EXT_SAI BIT(0) +#define SDIO_IRQ_EXT_EAI BIT(1) + unsigned char data = 0; + unsigned int quirks_bak; + int ret; + + /* Read CCCR 0x16 (interrupt extension)*/ + data = sdio_f0_readb(func, SDIO_CCCR_IRQ_EXT, &ret); + if (ret) { + DBGLOG(HAL, ERROR, "CCCR 0x%X read fail (%d).\n", SDIO_CCCR_IRQ_EXT, ret); + return FALSE; + } + /* Check CCCR capability status */ + if (!(data & SDIO_IRQ_EXT_SAI)) { + /* SAI = 0 */ + DBGLOG(HAL, ERROR, "No Async-IRQ capability.\n"); + return FALSE; + } else if (data & SDIO_IRQ_EXT_EAI) { + /* EAI = 1 */ + DBGLOG(INIT, INFO, "Async-IRQ enabled already.\n"); + return TRUE; + } + + /* Set EAI bit */ + data |= SDIO_IRQ_EXT_EAI; + + /* Enable capability to write CCCR */ + quirks_bak = func->card->quirks; + func->card->quirks |= MMC_QUIRK_LENIENT_FN0; + /* Write CCCR into card */ + sdio_f0_writeb(func, data, SDIO_CCCR_IRQ_EXT, &ret); + if (ret) { + DBGLOG(HAL, ERROR, "CCCR 0x%X write fail (%d).\n", SDIO_CCCR_IRQ_EXT, ret); + return FALSE; + } + func->card->quirks = quirks_bak; + + data = sdio_f0_readb(func, SDIO_CCCR_IRQ_EXT, &ret); + if (ret || !(data & SDIO_IRQ_EXT_EAI)) { + DBGLOG(HAL, ERROR, "CCCR 0x%X write fail (%d).\n", SDIO_CCCR_IRQ_EXT, ret); + return FALSE; + } + return TRUE; +} +#endif +#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 +} /* 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, ULONG ulCookie) +{ + P_GL_HIF_INFO_T prHif = NULL; + UINT_8 ucIdx; + + prHif = &prGlueInfo->rHifInfo; + + QUEUE_INITIALIZE(&prHif->rFreeQueue); + QUEUE_INITIALIZE(&prHif->rRxDeAggQueue); + QUEUE_INITIALIZE(&prHif->rRxFreeBufQueue); + +#if MTK_WCN_HIF_SDIO + /* prHif->prFuncInfo = ((MTK_WCN_HIF_SDIO_FUNCINFO *) u4Cookie); */ + prHif->prFuncInfo = prFunc; + prHif->cltCtx = *((MTK_WCN_HIF_SDIO_CLTCTX *) ulCookie); + mtk_wcn_hif_sdio_set_drvdata(prHif->cltCtx, prGlueInfo); + +#else + prHif->func = (struct sdio_func *)ulCookie; + + /* 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 + + /* Reset statistic counter */ + kalMemZero(&prHif->rStatCounter, sizeof(SDIO_STAT_COUNTER_T)); + + for (ucIdx = TC0_INDEX; ucIdx < TC_NUM; ucIdx++) + prHif->au4PendingTxDoneCount[ucIdx] = 0; + + mutex_init(&prHif->rRxFreeBufQueMutex); + mutex_init(&prHif->rRxDeAggQueMutex); +#if CFG_CHIP_RESET_SUPPORT + rst_data.func = prGlueInfo->rHifInfo.func; + mutex_init(&(rst_data.rst_mutex)); +#endif + +} /* 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; */ +} /* 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); + +#if (CFG_SDIO_1BIT_DATA_MODE == 1) + ret = sdio_disable_wide(func->card); + if (ret) + DBGLOG(HAL, ERROR, "glBusInit() Error at enabling SDIO 1-BIT data mode.\n"); + else + DBGLOG(HAL, INFO, "glBusInit() SDIO 1-BIT data mode is working.\n"); +#endif + +#if (CFG_SDIO_ASYNC_IRQ_AUTO_ENABLE == 1) + ret = mtk_sdio_async_irq_enable(func); + if (ret == FALSE) + DBGLOG(HAL, ERROR, "Async-IRQ auto-enable fail.\n"); + else + DBGLOG(INIT, INFO, "Async-IRQ is enabled.\n"); +#endif + + 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) +{ +} /* 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; + + 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; + +#if (MTK_WCN_HIF_SDIO == 0) + sdio_claim_host(prHifInfo->func); + ret = sdio_claim_irq(prHifInfo->func, mtk_sdio_interrupt); + sdio_release_host(prHifInfo->func); +#else + mtk_wcn_hif_sdio_enable_irq(prHifInfo->cltCtx, TRUE); +#endif + + prHifInfo->fgIsPendingInt = FALSE; + + return ret; +} /* end of glBusSetIrq() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus interrupt operation and disable interrupt handling for os. +* +* \param[in] pvData A pointer to struct net_device. +* \param[in] pvCookie Private data for pfnIsr function. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glBusFreeIrq(PVOID pvData, PVOID pvCookie) +{ + struct net_device *prNetDevice = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_GL_HIF_INFO_T prHifInfo = 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; + } + + prHifInfo = &prGlueInfo->rHifInfo; +#if (MTK_WCN_HIF_SDIO == 0) + sdio_claim_host(prHifInfo->func); + sdio_release_irq(prHifInfo->func); + sdio_release_host(prHifInfo->func); +#else + mtk_wcn_hif_sdio_enable_irq(prHifInfo->cltCtx, FALSE); +#endif +} /* end of glBusreeIrq() */ + +BOOLEAN glIsReadClearReg(UINT_32 u4Address) +{ + switch (u4Address) { + case MCR_WHISR: + case MCR_WASR: + case MCR_D2HRM0R: + case MCR_D2HRM1R: + case MCR_WTQCR0: + case MCR_WTQCR1: + case MCR_WTQCR2: + case MCR_WTQCR3: + case MCR_WTQCR4: + case MCR_WTQCR5: + case MCR_WTQCR6: + case MCR_WTQCR7: + return TRUE; + + default: + return FALSE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Read a 32-bit device register of SDIO host driver domian +* +* \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; + UINT_8 ucRetryCount = 0; + + ASSERT(prGlueInfo); + ASSERT(pu4Value); + + do { +#if MTK_WCN_HIF_SDIO + ret = mtk_wcn_hif_sdio_readl(prGlueInfo->rHifInfo.cltCtx, u4Register, (PUINT_32) pu4Value); +#else + sdio_claim_host(prGlueInfo->rHifInfo.func); + *pu4Value = sdio_readl(prGlueInfo->rHifInfo.func, u4Register, &ret); + sdio_release_host(prGlueInfo->rHifInfo.func); +#endif + + if (ret || ucRetryCount) { + /* DBGLOG(HAL, ERROR, + * ("sdio_readl() addr: 0x%08x value: 0x%08x status: %x retry: %u\n", + * u4Register, (unsigned int)*pu4Value, (unsigned int)ret, ucRetryCount)); + */ + + if (glIsReadClearReg(u4Register) && (ucRetryCount == 0)) { + /* Read Snapshot CR instead */ + u4Register = MCR_WSR; + } + } + + ucRetryCount++; + if (ucRetryCount > HIF_SDIO_ACCESS_RETRY_LIMIT) + break; + } while (ret); + + if (ret) { +#if CFG_CHIP_RESET_SUPPORT + P_ADAPTER_T prAdapter = NULL; +#endif + kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, + HIF_SDIO_ERR_DESC_STR "sdio_readl() reports error: %x retry: %u", ret, ucRetryCount); + DBGLOG(HAL, ERROR, "sdio_readl() reports error: %x retry: %u\n", ret, ucRetryCount); +#if CFG_CHIP_RESET_SUPPORT + prAdapter = container_of(&prGlueInfo, ADAPTER_T, prGlueInfo); + prAdapter->fgIsChipNoAck = TRUE; + DBGLOG(HAL, ERROR, "fgIsChipNoAck = %d\n", + prAdapter->fgIsChipNoAck); + glResetTrigger(prAdapter); +#endif + } + + return (ret) ? FALSE : TRUE; +} /* end of kalDevRegRead() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Read a 32-bit device register of chip firmware register domain +* +* \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_mac(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Register, OUT PUINT_32 pu4Value) +{ + UINT_32 value; + UINT_32 u4Time, u4Current; + BOOL ucRet; + + /* progrqm h2d mailbox0 as interested register address */ + kalDevRegWrite(prGlueInfo, MCR_H2DSM0R, u4Register); + + /* set h2d interrupt to notify firmware. bit16 */ + kalDevRegWrite(prGlueInfo, MCR_WSICR, SDIO_MAILBOX_FUNC_READ_REG_IDX); + + /* polling interrupt status asserted. bit16 */ + + /* first, disable interrupt enable for SDIO_MAILBOX_FUNC_READ_REG_IDX */ + ucRet = kalDevRegRead(prGlueInfo, MCR_WHIER, &value); + kalDevRegWrite(prGlueInfo, MCR_WHIER, (value & ~SDIO_MAILBOX_FUNC_READ_REG_IDX)); + + u4Time = (UINT_32) kalGetTimeTick(); + + do { + /* check bit16 of WHISR assert for read register response */ + ucRet = kalDevRegRead(prGlueInfo, MCR_WHISR, &value); + + if (value & SDIO_MAILBOX_FUNC_READ_REG_IDX) { + /* read d2h mailbox0 for interested register address */ + ucRet = kalDevRegRead(prGlueInfo, MCR_D2HRM0R, &value); + + if (value != u4Register) { + DBGLOG(HAL, ERROR, "ERROR! kalDevRegRead_mac():register address mis-match"); + DBGLOG(HAL, ERROR, "(u4Register = 0x%08x, reported register = 0x%08x)\n", + u4Register, value); + return FALSE; + } + + /* read d2h mailbox1 for the value of the register */ + ucRet = kalDevRegRead(prGlueInfo, MCR_D2HRM1R, &value); + *pu4Value = value; + return TRUE; + } + + /* timeout exceeding check */ + u4Current = (UINT_32) kalGetTimeTick(); + + if (((u4Current > u4Time) && ((u4Current - u4Time) > HIF_SDIO_INTERRUPT_RESPONSE_TIMEOUT)) + || (u4Current < u4Time && ((u4Current + (0xFFFFFFFF - u4Time)) + > HIF_SDIO_INTERRUPT_RESPONSE_TIMEOUT))) { + DBGLOG(HAL, ERROR, "ERROR: kalDevRegRead_mac(): response timeout\n"); + return FALSE; + } + + /* Response packet is not ready */ + kalUdelay(50); + } while (1); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write a 32-bit device register of SDIO driver domian +* +* \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; + UINT_8 ucRetryCount = 0; + + ASSERT(prGlueInfo); + + do { +#if MTK_WCN_HIF_SDIO + ret = mtk_wcn_hif_sdio_writel(prGlueInfo->rHifInfo.cltCtx, u4Register, u4Value); +#else + sdio_claim_host(prGlueInfo->rHifInfo.func); + sdio_writel(prGlueInfo->rHifInfo.func, u4Value, u4Register, &ret); + sdio_release_host(prGlueInfo->rHifInfo.func); +#endif + + if (ret || ucRetryCount) { + /* DBGLOG(HAL, ERROR, + * ("sdio_writel() addr: 0x%x status: %x retry: %u\n", u4Register, + * ret, ucRetryCount)); + */ + } + + ucRetryCount++; + if (ucRetryCount > HIF_SDIO_ACCESS_RETRY_LIMIT) + break; + + } while (ret); + + if (ret) { +#if CFG_CHIP_RESET_SUPPORT + P_ADAPTER_T prAdapter = NULL; +#endif + kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, + HIF_SDIO_ERR_DESC_STR "sdio_writel() reports error: %x retry: %u", ret, ucRetryCount); + DBGLOG(HAL, ERROR, "sdio_writel() reports error: %x retry: %u\n", ret, ucRetryCount); +#if CFG_CHIP_RESET_SUPPORT + prAdapter = container_of(&prGlueInfo, ADAPTER_T, prGlueInfo); + prAdapter->fgIsChipNoAck = TRUE; + DBGLOG(HAL, ERROR, "fgIsChipNoAck = %d\n", + prAdapter->fgIsChipNoAck); + glResetTrigger(prAdapter); +#endif + } + + return (ret) ? FALSE : TRUE; +} /* end of kalDevRegWrite() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write a 32-bit device register of chip firmware register domain +* +* \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_mac(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Register, IN UINT_32 u4Value) +{ + UINT_32 value; + UINT_32 u4Time, u4Current; + BOOL ucRet; + + /* progrqm h2d mailbox0 as interested register address */ + kalDevRegWrite(prGlueInfo, MCR_H2DSM0R, u4Register); + + /* progrqm h2d mailbox1 as the value to write */ + kalDevRegWrite(prGlueInfo, MCR_H2DSM1R, u4Value); + + /* set h2d interrupt to notify firmware bit17 */ + kalDevRegWrite(prGlueInfo, MCR_WSICR, SDIO_MAILBOX_FUNC_WRITE_REG_IDX); + + /* polling interrupt status asserted. bit17 */ + + /* first, disable interrupt enable for SDIO_MAILBOX_FUNC_WRITE_REG_IDX */ + ucRet = kalDevRegRead(prGlueInfo, MCR_WHIER, &value); + kalDevRegWrite(prGlueInfo, MCR_WHIER, (value & ~SDIO_MAILBOX_FUNC_WRITE_REG_IDX)); + + u4Time = (UINT_32) kalGetTimeTick(); + + do { + /* check bit17 of WHISR assert for response */ + ucRet = kalDevRegRead(prGlueInfo, MCR_WHISR, &value); + + if (value & SDIO_MAILBOX_FUNC_WRITE_REG_IDX) { + /* read d2h mailbox0 for interested register address */ + ucRet = kalDevRegRead(prGlueInfo, MCR_D2HRM0R, &value); + + if (value != u4Register) { + DBGLOG(HAL, ERROR, "ERROR! kalDevRegWrite_mac():register address mis-match"); + DBGLOG(HAL, ERROR, "(u4Register = 0x%08x, reported register = 0x%08x)\n", + u4Register, value); + return FALSE; + } + return TRUE; + } + + /* timeout exceeding check */ + u4Current = (UINT_32) kalGetTimeTick(); + + if (((u4Current > u4Time) && ((u4Current - u4Time) > HIF_SDIO_INTERRUPT_RESPONSE_TIMEOUT)) + || (u4Current < u4Time && ((u4Current + (0xFFFFFFFF - u4Time)) + > HIF_SDIO_INTERRUPT_RESPONSE_TIMEOUT))) { + DBGLOG(HAL, ERROR, "ERROR: kalDevRegWrite_mac(): response timeout\n"); + return FALSE; + } + + /* Response packet is not ready */ + kalUdelay(50); + } while (1); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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_32 u4Len, OUT PUINT_8 pucBuf, IN UINT_32 u4ValidOutBufSize) +{ + P_GL_HIF_INFO_T prHifInfo = NULL; + PUINT_8 pucDst = NULL; + int count = u4Len; + 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, u4Len); */ +#endif + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + ASSERT(pucBuf); + pucDst = pucBuf; + + ASSERT(u4Len <= u4ValidOutBufSize); + +#if (MTK_WCN_HIF_SDIO == 0) + prSdioFunc = prHifInfo->func; + + ASSERT(prSdioFunc->cur_blksize > 0); + + 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); + } + + 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, (PUINT_32) pucDst, + ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz) * bNum); + } else { + ret = mtk_wcn_hif_sdio_read_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT_32) pucDst, count); + } +#endif + + if (ret) { +#if CFG_CHIP_RESET_SUPPORT + P_ADAPTER_T prAdapter = NULL; +#endif + 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\n", ret); +#if CFG_CHIP_RESET_SUPPORT + prAdapter = container_of(&prGlueInfo, ADAPTER_T, prGlueInfo); + prAdapter->fgIsChipNoAck = TRUE; + DBGLOG(HAL, ERROR, "fgIsChipNoAck = %d\n", + prAdapter->fgIsChipNoAck); + glResetTrigger(prAdapter); +#endif + } + + 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_32 u4Len, IN PUINT_8 pucBuf, IN UINT_32 u4ValidInBufSize) +{ + P_GL_HIF_INFO_T prHifInfo = NULL; + PUINT_8 pucSrc = NULL; + int count = u4Len; + 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(u4Len <= u4ValidInBufSize); + +#if (MTK_WCN_HIF_SDIO == 0) + prSdioFunc = prHifInfo->func; + ASSERT(prSdioFunc->cur_blksize > 0); + + 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); + } + + 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, + (PUINT_32) pucSrc, ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz) * bNum); + } else { /* byte mode */ + ret = mtk_wcn_hif_sdio_write_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT_32) pucSrc, count); + } +#endif + + if (ret) { +#if CFG_CHIP_RESET_SUPPORT + P_ADAPTER_T prAdapter = NULL; +#endif + 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\n", ret); +#if CFG_CHIP_RESET_SUPPORT + prAdapter = container_of(&prGlueInfo, ADAPTER_T, prGlueInfo); + prAdapter->fgIsChipNoAck = TRUE; + DBGLOG(HAL, ERROR, "fgIsChipNoAck = %d\n", + prAdapter->fgIsChipNoAck); + glResetTrigger(prAdapter); +#endif + } + + return (ret) ? FALSE : TRUE; +} /* end of kalDevPortWrite() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read interrupt status from hardware +* +* @param prAdapter pointer to the Adapter handler +* @param the interrupts +* +* @return N/A +* +*/ +/*----------------------------------------------------------------------------*/ +VOID kalDevReadIntStatus(IN P_ADAPTER_T prAdapter, OUT PUINT_32 pu4IntStatus) +{ +#if CFG_SDIO_INTR_ENHANCE + P_SDIO_CTRL_T prSDIOCtrl; + P_SDIO_STAT_COUNTER_T prStatCounter; + + SDIO_TIME_INTERVAL_DEC(); + + DEBUGFUNC("nicSDIOReadIntStatus"); + + ASSERT(prAdapter); + ASSERT(pu4IntStatus); + + prSDIOCtrl = prAdapter->prGlueInfo->rHifInfo.prSDIOCtrl; + ASSERT(prSDIOCtrl); + + prStatCounter = &prAdapter->prGlueInfo->rHifInfo.rStatCounter; + + /* There are pending interrupt to be handled */ + if (prAdapter->prGlueInfo->rHifInfo.fgIsPendingInt) + prAdapter->prGlueInfo->rHifInfo.fgIsPendingInt = FALSE; + else { + SDIO_REC_TIME_START(); + HAL_PORT_RD(prAdapter, MCR_WHISR, sizeof(ENHANCE_MODE_DATA_STRUCT_T), + (PUINT_8) prSDIOCtrl, sizeof(ENHANCE_MODE_DATA_STRUCT_T)); + SDIO_REC_TIME_END(); + SDIO_ADD_TIME_INTERVAL(prStatCounter->u4IntReadTime); + prStatCounter->u4IntReadCnt++; + } + + prStatCounter->u4IntCnt++; + + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + *pu4IntStatus = 0; + return; + } + + halProcessEnhanceInterruptStatus(prAdapter); + + *pu4IntStatus = prSDIOCtrl->u4WHISR; +#else + HAL_MCR_RD(prAdapter, MCR_WHISR, pu4IntStatus); +#endif /* CFG_SDIO_INTR_ENHANCE */ + + if (*pu4IntStatus & ~(WHIER_DEFAULT | WHIER_FW_OWN_BACK_INT_EN)) { + DBGLOG(INTR, WARN, "Un-handled HISR %#lx, HISR = %#lx (HIER:0x%lx)\n", + (*pu4IntStatus & ~WHIER_DEFAULT), *pu4IntStatus, WHIER_DEFAULT); + *pu4IntStatus &= WHIER_DEFAULT; + } +} /* end of nicSDIOReadIntStatus() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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) + sdio_claim_host(prGlueInfo->rHifInfo.func); + sdio_writeb(prGlueInfo->rHifInfo.func, ucData, u4Addr, &ret); + sdio_release_host(prGlueInfo->rHifInfo.func); +#else + ret = mtk_wcn_hif_sdio_writeb(prGlueInfo->rHifInfo.cltCtx, u4Addr, ucData); +#endif + + if (ret) { +#if CFG_CHIP_RESET_SUPPORT + P_ADAPTER_T prAdapter = container_of(&prGlueInfo, ADAPTER_T, + prGlueInfo); +#endif + 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\n", ret); +#if CFG_CHIP_RESET_SUPPORT + prAdapter->fgIsChipNoAck = TRUE; + DBGLOG(HAL, ERROR, "fgIsChipNoAck = %d\n", + prAdapter->fgIsChipNoAck); + glResetTrigger(prAdapter); +#endif + } + + return (ret) ? FALSE : TRUE; + +} /* end of kalDevWriteWithSdioCmd52() */ + +VOID glSetPowerState(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 ePowerMode) +{ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write data to device +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] prMsduInfo msdu info +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +BOOL kalDevWriteData(IN P_GLUE_INFO_T prGlueInfo, IN P_MSDU_INFO_T prMsduInfo) +{ + P_ADAPTER_T prAdapter = prGlueInfo->prAdapter; + P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; + P_TX_CTRL_T prTxCtrl; + PUINT_8 pucOutputBuf = (PUINT_8) NULL; + UINT_32 u4PaddingLength; + struct sk_buff *skb; + UINT_8 *pucBuf; + UINT_32 u4Length; + UINT_8 ucTC; + + SDIO_TIME_INTERVAL_DEC(); + + skb = (struct sk_buff *)prMsduInfo->prPacket; + pucBuf = skb->data; + u4Length = skb->len; + ucTC = prMsduInfo->ucTC; + + prTxCtrl = &prAdapter->rTxCtrl; + pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; + + if (prTxCtrl->u4WrIdx + ALIGN_4(u4Length) > prAdapter->u4CoalescingBufCachedSize) { + if ((prAdapter->u4CoalescingBufCachedSize - ALIGN_4(prTxCtrl->u4WrIdx)) >= HIF_TX_TERMINATOR_LEN) { + /* fill with single dword of zero as TX-aggregation termination */ + *(PUINT_32) (&((pucOutputBuf)[ALIGN_4(prTxCtrl->u4WrIdx)])) = 0; + } + + if (HAL_TEST_FLAG(prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { + if (kalDevPortWrite(prGlueInfo, MCR_WTDR1, prTxCtrl->u4WrIdx, + pucOutputBuf, prAdapter->u4CoalescingBufCachedSize) == FALSE) { + HAL_SET_FLAG(prAdapter, ADAPTER_FLAG_HW_ERR); + fgIsBusAccessFailed = TRUE; + } + prHifInfo->rStatCounter.u4DataPortWriteCnt++; + } + prTxCtrl->u4WrIdx = 0; + } + + SDIO_REC_TIME_START(); + memcpy(pucOutputBuf + prTxCtrl->u4WrIdx, pucBuf, u4Length); + SDIO_REC_TIME_END(); + SDIO_ADD_TIME_INTERVAL(prHifInfo->rStatCounter.u4TxDataCpTime); + + prTxCtrl->u4WrIdx += u4Length; + + u4PaddingLength = (ALIGN_4(u4Length) - u4Length); + if (u4PaddingLength) { + memset(pucOutputBuf + prTxCtrl->u4WrIdx, 0, u4PaddingLength); + prTxCtrl->u4WrIdx += u4PaddingLength; + } + + SDIO_REC_TIME_START(); + if (!prMsduInfo->pfTxDoneHandler) + kalFreeTxMsdu(prAdapter, prMsduInfo); + SDIO_REC_TIME_END(); + SDIO_ADD_TIME_INTERVAL(prHifInfo->rStatCounter.u4TxDataFreeTime); + + /* Update pending Tx done count */ + prHifInfo->au4PendingTxDoneCount[ucTC]++; + + prHifInfo->rStatCounter.u4DataPktWriteCnt++; + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Kick Tx data to device +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +BOOL kalDevKickData(IN P_GLUE_INFO_T prGlueInfo) +{ + P_ADAPTER_T prAdapter = prGlueInfo->prAdapter; + P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; + P_TX_CTRL_T prTxCtrl; + PUINT_8 pucOutputBuf = (PUINT_8) NULL; + + prTxCtrl = &prAdapter->rTxCtrl; + pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; + + if (prTxCtrl->u4WrIdx == 0) + return FALSE; + + if ((prAdapter->u4CoalescingBufCachedSize - ALIGN_4(prTxCtrl->u4WrIdx)) >= HIF_TX_TERMINATOR_LEN) { + /* fill with single dword of zero as TX-aggregation termination */ + *(PUINT_32) (&((pucOutputBuf)[ALIGN_4(prTxCtrl->u4WrIdx)])) = 0; + } + + if (HAL_TEST_FLAG(prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { + if (kalDevPortWrite(prGlueInfo, MCR_WTDR1, prTxCtrl->u4WrIdx, + pucOutputBuf, prAdapter->u4CoalescingBufCachedSize) == FALSE) { + HAL_SET_FLAG(prAdapter, ADAPTER_FLAG_HW_ERR); + fgIsBusAccessFailed = TRUE; + } + prHifInfo->rStatCounter.u4DataPortWriteCnt++; + } + + prTxCtrl->u4WrIdx = 0; + + prHifInfo->rStatCounter.u4DataPortKickCnt++; + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write command to device +* +* \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 kalDevWriteCmd(IN P_GLUE_INFO_T prGlueInfo, IN P_CMD_INFO_T prCmdInfo, IN UINT_8 ucTC) +{ + P_ADAPTER_T prAdapter = prGlueInfo->prAdapter; +/* P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; */ + P_TX_CTRL_T prTxCtrl; + PUINT_8 pucOutputBuf = (PUINT_8) NULL; + UINT_16 u2OverallBufferLength = 0; +/* WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; */ + + prTxCtrl = &prAdapter->rTxCtrl; + pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; + + if (TFCB_FRAME_PAD_TO_DW(prCmdInfo->u4TxdLen + prCmdInfo->u4TxpLen) > + prAdapter->u4CoalescingBufCachedSize) { + DBGLOG(HAL, ERROR, "Command TX buffer underflow!\n"); + return FALSE; + } + if (prCmdInfo->u4TxdLen) { + memcpy((pucOutputBuf + u2OverallBufferLength), prCmdInfo->pucTxd, prCmdInfo->u4TxdLen); + u2OverallBufferLength += prCmdInfo->u4TxdLen; + } + + if (prCmdInfo->u4TxpLen) { + memcpy((pucOutputBuf + u2OverallBufferLength), prCmdInfo->pucTxp, prCmdInfo->u4TxpLen); + u2OverallBufferLength += prCmdInfo->u4TxpLen; + } + + memset(pucOutputBuf + u2OverallBufferLength, 0, + (TFCB_FRAME_PAD_TO_DW(u2OverallBufferLength) - u2OverallBufferLength)); + + if ((prAdapter->u4CoalescingBufCachedSize - ALIGN_4(u2OverallBufferLength)) >= HIF_TX_TERMINATOR_LEN) { + /* fill with single dword of zero as TX-aggregation termination */ + *(PUINT_32) (&((pucOutputBuf)[ALIGN_4(u2OverallBufferLength)])) = 0; + } + if (HAL_TEST_FLAG(prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { + if (kalDevPortWrite(prGlueInfo, MCR_WTDR1, TFCB_FRAME_PAD_TO_DW(u2OverallBufferLength), + pucOutputBuf, prAdapter->u4CoalescingBufCachedSize) == FALSE) { + HAL_SET_FLAG(prAdapter, ADAPTER_FLAG_HW_ERR); + fgIsBusAccessFailed = TRUE; + } + prGlueInfo->rHifInfo.rStatCounter.u4CmdPortWriteCnt++; + } + + /* Update pending Tx done count */ + prGlueInfo->rHifInfo.au4PendingTxDoneCount[ucTC]++; + + prGlueInfo->rHifInfo.rStatCounter.u4CmdPktWriteCnt++; + return TRUE; +} + +void glGetDev(PVOID ctx, struct device **dev) +{ +#if MTK_WCN_HIF_SDIO + mtk_wcn_hif_sdio_get_dev(*((MTK_WCN_HIF_SDIO_CLTCTX *) ctx), dev); +#else + *dev = &((struct sdio_func *)ctx)->dev; +#endif +} + +void glGetHifDev(P_GL_HIF_INFO_T prHif, struct device **dev) +{ +#if MTK_WCN_HIF_SDIO + mtk_wcn_hif_sdio_get_dev(prHif->cltCtx, dev); +#else + *dev = &(prHif->func->dev); +#endif +} + +BOOLEAN glWakeupSdio(P_GLUE_INFO_T prGlueInfo) +{ + BOOLEAN fgSuccess = TRUE; + +#if (HIF_SDIO_SUPPORT_GPIO_SLEEP_MODE && MTK_WCN_HIF_SDIO) + if (mtk_wcn_hif_sdio_wake_up_ctrl(prGlueInfo->rHifInfo.cltCtx) != 0) + fgSuccess = FALSE; +#endif + + return fgSuccess; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/x86.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/x86.c new file mode 100644 index 0000000000000..7cbc34e29cdef --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/sdio/x86.c @@ -0,0 +1,62 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** +*[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. +******************************************************************************/ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/usb/hal_api.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/usb/hal_api.c new file mode 100644 index 0000000000000..00cb273631ee0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/usb/hal_api.c @@ -0,0 +1,1582 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** +*[File] hif_api.c +*[Version] v1.0 +*[Revision Date] 2015-09-08 +*[Author] +*[Description] +* The program provides USB HIF APIs +*[Copyright] +* Copyright (C) 2015 MediaTek Incorporation. All Rights Reserved. +******************************************************************************/ + +/******************************************************************************* +* C O M P I L E 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 +#include + +#include +#ifndef CONFIG_X86 +#include +#endif + +#include "mt66xx_reg.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 const UINT_16 arTcToUSBEP[USB_TC_NUM] = { + USB_DATA_BULK_OUT_EP4, + USB_DATA_BULK_OUT_EP5, + USB_DATA_BULK_OUT_EP6, + USB_DATA_BULK_OUT_EP7, + USB_DATA_BULK_OUT_EP8, + USB_DATA_BULK_OUT_EP4, + USB_DATA_BULK_OUT_EP9, + + /* Second HW queue */ +#if NIC_TX_ENABLE_SECOND_HW_QUEUE + USB_DATA_BULK_OUT_EP9, + USB_DATA_BULK_OUT_EP9, + USB_DATA_BULK_OUT_EP9, + USB_DATA_BULK_OUT_EP9, +#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 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 halVerifyChipID(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4CIR = 0; + struct mt66xx_chip_info *prChipInfo; + + ASSERT(prAdapter); + + if (prAdapter->fgIsReadRevID) + return TRUE; + + prChipInfo = prAdapter->chip_info; + + HAL_MCR_RD(prAdapter, TOP_HCR, &u4CIR); + DBGLOG(INIT, TRACE, "Chip ID: 0x%x\n", u4CIR); + + if (u4CIR != prChipInfo->chip_id) + return FALSE; + + HAL_MCR_RD(prAdapter, TOP_HVR, &u4CIR); + DBGLOG(INIT, TRACE, "Revision ID: 0x%x\n", u4CIR); + + prAdapter->ucRevID = (UINT_8) (u4CIR & 0xF); + prAdapter->fgIsReadRevID = TRUE; + return TRUE; +} + +WLAN_STATUS +halRxWaitResponse(IN P_ADAPTER_T prAdapter, IN UINT_8 ucPortIdx, OUT PUINT_8 pucRspBuffer, + IN UINT_32 u4MaxRespBufferLen, OUT PUINT_32 pu4Length) +{ + P_GL_HIF_INFO_T prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + P_RX_CTRL_T prRxCtrl; + BOOL ret = FALSE; + + DEBUGFUNC("halRxWaitResponse"); + + ASSERT(prAdapter); + ASSERT(pucRspBuffer); + + prRxCtrl = &prAdapter->rRxCtrl; + + if (prHifInfo->fgEventEpDetected == FALSE) { + /* NOTE: This is temporary compatiable code with old/new CR4 FW to detect which EVENT endpoint that + * CR4 FW is using. If the new EP4IN-using CR4 FW works without any issue for a while, + * this code block will be removed. + */ + if (prAdapter->fgIsCr4FwDownloaded) { + ucPortIdx = USB_DATA_EP_IN; + ret = kalDevPortRead(prAdapter->prGlueInfo, ucPortIdx, + ALIGN_4(u4MaxRespBufferLen) + LEN_USB_RX_PADDING_CSO, + prRxCtrl->pucRxCoalescingBufPtr, HIF_RX_COALESCING_BUFFER_SIZE); + + if (ret == TRUE) { + prHifInfo->eEventEpType = EVENT_EP_TYPE_DATA_EP; + } else { + ucPortIdx = USB_EVENT_EP_IN; + ret = kalDevPortRead(prAdapter->prGlueInfo, ucPortIdx, + ALIGN_4(u4MaxRespBufferLen) + LEN_USB_RX_PADDING_CSO, + prRxCtrl->pucRxCoalescingBufPtr, HIF_RX_COALESCING_BUFFER_SIZE); + } + prHifInfo->fgEventEpDetected = TRUE; + + kalMemCopy(pucRspBuffer, prRxCtrl->pucRxCoalescingBufPtr, u4MaxRespBufferLen); + *pu4Length = u4MaxRespBufferLen; + + if (ret == FALSE) + u4Status = WLAN_STATUS_FAILURE; + return u4Status; + } + + ucPortIdx = USB_EVENT_EP_IN; + } else { + if (prHifInfo->eEventEpType == EVENT_EP_TYPE_DATA_EP) + if (prAdapter->fgIsCr4FwDownloaded) + ucPortIdx = USB_DATA_EP_IN; + else + ucPortIdx = USB_EVENT_EP_IN; + else + ucPortIdx = USB_EVENT_EP_IN; + + } + ret = kalDevPortRead(prAdapter->prGlueInfo, ucPortIdx, + ALIGN_4(u4MaxRespBufferLen) + LEN_USB_RX_PADDING_CSO, + prRxCtrl->pucRxCoalescingBufPtr, HIF_RX_COALESCING_BUFFER_SIZE); + + kalMemCopy(pucRspBuffer, prRxCtrl->pucRxCoalescingBufPtr, u4MaxRespBufferLen); + *pu4Length = u4MaxRespBufferLen; + + if (ret == FALSE) + u4Status = WLAN_STATUS_FAILURE; + + return u4Status; +} + +WLAN_STATUS halTxUSBSendCmd(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucTc, IN P_CMD_INFO_T prCmdInfo) +{ + P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + P_USB_REQ_T prUsbReq; + P_BUF_CTRL_T prBufCtrl; + UINT_16 u2OverallBufferLength = 0; + unsigned long flags; + P_HW_MAC_TX_DESC_T prTxDesc; + UINT_8 ucQueIdx; + + prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxCmdFreeQ, &prHifInfo->rTxCmdQLock); + if (prUsbReq == NULL) + return WLAN_STATUS_RESOURCES; + + prBufCtrl = prUsbReq->prBufCtrl; + + if ((TFCB_FRAME_PAD_TO_DW(prCmdInfo->u4TxdLen + prCmdInfo->u4TxpLen) + LEN_USB_UDMA_TX_TERMINATOR) > + prBufCtrl->u4BufSize) { + DBGLOG(HAL, ERROR, "Command TX buffer underflow!\n"); + glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxCmdFreeQ, prUsbReq, + &prHifInfo->rTxCmdQLock, FALSE); + return WLAN_STATUS_RESOURCES; + } + + DBGLOG(HAL, INFO, "TX URB[0x%p]\n", prUsbReq->prUrb); + + if (prCmdInfo->u4TxdLen) { + memcpy((prBufCtrl->pucBuf + u2OverallBufferLength), prCmdInfo->pucTxd, prCmdInfo->u4TxdLen); + u2OverallBufferLength += prCmdInfo->u4TxdLen; + } + + if (prCmdInfo->u4TxpLen) { + memcpy((prBufCtrl->pucBuf + u2OverallBufferLength), prCmdInfo->pucTxp, prCmdInfo->u4TxpLen); + u2OverallBufferLength += prCmdInfo->u4TxpLen; + } + + prTxDesc = (P_HW_MAC_TX_DESC_T)prBufCtrl->pucBuf; + ucQueIdx = HAL_MAC_TX_DESC_GET_QUEUE_INDEX(prTxDesc); + /* For H2CDMA Tx CMD mapping */ + /* Mapping port1 queue0~3 to queue28~31, and CR4 will unmask this */ + HAL_MAC_TX_DESC_SET_QUEUE_INDEX(prTxDesc, (ucQueIdx | USB_TX_CMD_QUEUE_MASK)); + + /* DBGLOG_MEM32(SW4, INFO, prBufCtrl->pucBuf, 32); */ + + memset(prBufCtrl->pucBuf + u2OverallBufferLength, 0, + ((TFCB_FRAME_PAD_TO_DW(u2OverallBufferLength) - u2OverallBufferLength) + LEN_USB_UDMA_TX_TERMINATOR)); + prBufCtrl->u4WrIdx = TFCB_FRAME_PAD_TO_DW(u2OverallBufferLength) + LEN_USB_UDMA_TX_TERMINATOR; + + prUsbReq->prPriv = (PVOID) prCmdInfo; + usb_fill_bulk_urb(prUsbReq->prUrb, + prHifInfo->udev, + usb_sndbulkpipe(prHifInfo->udev, arTcToUSBEP[ucTc]), + (void *)prUsbReq->prBufCtrl->pucBuf, + prBufCtrl->u4WrIdx, halTxUSBSendCmdComplete, (void *)prUsbReq); + +#if CFG_USB_CONSISTENT_DMA + prUsbReq->prUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; +#endif + spin_lock_irqsave(&prHifInfo->rTxCmdQLock, flags); + u4Status = glUsbSubmitUrb(prHifInfo, prUsbReq->prUrb, SUBMIT_TYPE_TX_CMD); + if (u4Status) { + DBGLOG(HAL, ERROR, "glUsbSubmitUrb() reports error (%d)\n", u4Status); + list_add_tail(&prUsbReq->list, &prHifInfo->rTxCmdFreeQ); + spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, flags); + return WLAN_STATUS_FAILURE; + } + list_add_tail(&prUsbReq->list, &prHifInfo->rTxCmdSendingQ); + spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, flags); + + if (wlanIsChipRstRecEnabled(prGlueInfo->prAdapter) + && wlanIsChipNoAck(prGlueInfo->prAdapter)) { + wlanChipRstPreAct(prGlueInfo->prAdapter); +#if CFG_CHIP_RESET_SUPPORT + glResetTrigger(prGlueInfo->prAdapter); +#else + DBGLOG(HAL, ERROR, "usb trigger whole reset\n"); + HAL_WIFI_FUNC_CHIP_RESET(prGlueInfo->prAdapter); +#endif + } + return u4Status; +} + +VOID halTxUSBSendCmdComplete(struct urb *urb) +{ + P_USB_REQ_T prUsbReq = urb->context; + P_GL_HIF_INFO_T prHifInfo = prUsbReq->prHifInfo; + P_GLUE_INFO_T prGlueInfo = prHifInfo->prGlueInfo; + unsigned long flags; + +#if CFG_USB_TX_HANDLE_IN_HIF_THREAD + spin_lock_irqsave(&prHifInfo->rTxCmdQLock, flags); + list_del_init(&prUsbReq->list); + list_add_tail(&prUsbReq->list, &prHifInfo->rTxCmdCompleteQ); + spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, flags); + + kalSetIntEvent(prGlueInfo); +#else + spin_lock_irqsave(&prHifInfo->rTxCmdQLock, flags); + list_del_init(&prUsbReq->list); + spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, flags); + + halTxUSBProcessCmdComplete(prGlueInfo->prAdapter, prUsbReq); +#endif +} + +VOID halTxUSBProcessCmdComplete(IN P_ADAPTER_T prAdapter, P_USB_REQ_T prUsbReq) +{ + struct urb *urb = prUsbReq->prUrb; + UINT_32 u4SentDataSize; + P_GL_HIF_INFO_T prHifInfo = prUsbReq->prHifInfo; + static UINT_32 uUsbCmdFailCounter; + + if (urb->status != 0) { + DBGLOG(TX, ERROR, "[%s] send CMD fail (status = %d)\n", __func__, urb->status); + /* TODO: handle error */ + if ((urb->status != -ENOENT) && + (urb->status != -ECONNRESET) && + (urb->status != -ESHUTDOWN)) { + uUsbCmdFailCounter++; + if (uUsbCmdFailCounter > 3) { + prAdapter->fgIsChipNoAck = TRUE; + uUsbCmdFailCounter = 0; + } + } + } else { + uUsbCmdFailCounter = 0; + } + DBGLOG(HAL, INFO, "TX CMD DONE: URB[0x%p]\n", urb); + + glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxCmdFreeQ, prUsbReq, &prHifInfo->rTxCmdQLock, FALSE); + + u4SentDataSize = urb->actual_length - LEN_USB_UDMA_TX_TERMINATOR; + nicTxReleaseResource(prAdapter, TC4_INDEX, nicTxGetPageCount(u4SentDataSize, TRUE), TRUE); +} + +VOID halTxCancelSendingCmd(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + P_USB_REQ_T prUsbReq, prNext; + unsigned long flags; + struct urb *urb = NULL; + P_GL_HIF_INFO_T prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + spin_lock_irqsave(&prHifInfo->rTxCmdQLock, flags); + list_for_each_entry_safe(prUsbReq, prNext, &prHifInfo->rTxCmdSendingQ, list) { + if (prUsbReq->prPriv == (PVOID) prCmdInfo) { + list_del_init(&prUsbReq->list); + urb = prUsbReq->prUrb; + break; + } + } + spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, flags); + + if (urb) { + prCmdInfo->pfHifTxCmdDoneCb = NULL; + usb_kill_urb(urb); + } +} + +VOID halTxCancelAllSending(IN P_ADAPTER_T prAdapter) +{ + P_GLUE_INFO_T prGlueInfo; + P_USB_REQ_T prUsbReq, prUsbReqNext; + P_GL_HIF_INFO_T prHifInfo; +#if CFG_USB_TX_AGG + UINT_8 ucTc; +#endif + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + prHifInfo = &prGlueInfo->rHifInfo; + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxCmdSendingQ, list) { + usb_kill_urb(prUsbReq->prUrb); + } + +#if CFG_USB_TX_AGG + for (ucTc = 0; ucTc < USB_TC_NUM; ++ucTc) + usb_kill_anchored_urbs(&prHifInfo->rTxDataAnchor[ucTc]); +#else + usb_kill_anchored_urbs(&prHifInfo->rTxDataAnchor); +#endif +} + +#if CFG_USB_TX_AGG +WLAN_STATUS halTxUSBSendAggData(IN P_GL_HIF_INFO_T prHifInfo, IN UINT_8 ucTc, IN P_USB_REQ_T prUsbReq) +{ + P_GLUE_INFO_T prGlueInfo = prHifInfo->prGlueInfo; + P_BUF_CTRL_T prBufCtrl = prUsbReq->prBufCtrl; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + memset(prBufCtrl->pucBuf + prBufCtrl->u4WrIdx, 0, LEN_USB_UDMA_TX_TERMINATOR); + prBufCtrl->u4WrIdx += LEN_USB_UDMA_TX_TERMINATOR; + + list_del_init(&prUsbReq->list); + + usb_fill_bulk_urb(prUsbReq->prUrb, + prHifInfo->udev, + usb_sndbulkpipe(prHifInfo->udev, arTcToUSBEP[ucTc]), + (void *)prBufCtrl->pucBuf, prBufCtrl->u4WrIdx, halTxUSBSendDataComplete, (void *)prUsbReq); +#if CFG_USB_CONSISTENT_DMA + prUsbReq->prUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; +#endif + + usb_anchor_urb(prUsbReq->prUrb, &prHifInfo->rTxDataAnchor[ucTc]); + u4Status = glUsbSubmitUrb(prHifInfo, prUsbReq->prUrb, SUBMIT_TYPE_TX_DATA); + if (u4Status) { + DBGLOG(HAL, ERROR, "glUsbSubmitUrb() reports error (%d)\n", u4Status); + halTxUSBProcessMsduDone(prHifInfo->prGlueInfo, prUsbReq); + prBufCtrl->u4WrIdx = 0; + usb_unanchor_urb(prUsbReq->prUrb); + list_add_tail(&prUsbReq->list, &prHifInfo->rTxDataCompleteQ); +#if CFG_USB_TX_HANDLE_IN_HIF_THREAD + kalSetIntEvent(prGlueInfo); +#else + /*tasklet_hi_schedule(&prGlueInfo->rTxCompleteTask);*/ + tasklet_schedule(&prGlueInfo->rTxCompleteTask); +#endif + return WLAN_STATUS_FAILURE; + } + + return u4Status; +} +#endif + +WLAN_STATUS halTxUSBSendData(IN P_GLUE_INFO_T prGlueInfo, IN P_MSDU_INFO_T prMsduInfo) +{ + P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + P_USB_REQ_T prUsbReq; + P_BUF_CTRL_T prBufCtrl; + UINT_32 u4PaddingLength; + struct sk_buff *skb; + UINT_8 ucTc; + UINT_8 *pucBuf; + UINT_32 u4Length; +#if CFG_USB_TX_AGG + unsigned long flags; +#endif + + skb = (struct sk_buff *)prMsduInfo->prPacket; + pucBuf = skb->data; + u4Length = skb->len; + ucTc = USB_TRANS_MSDU_TC(prMsduInfo); +#if CFG_USB_TX_AGG + spin_lock_irqsave(&prHifInfo->rTxDataQLock, flags); + + if (list_empty(&prHifInfo->rTxDataFreeQ[ucTc])) { + if (glUsbBorrowFfaReq(prHifInfo, ucTc) == FALSE) { + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, flags); + DBGLOG(HAL, ERROR, "run out of rTxDataFreeQ #1!!\n"); + wlanProcessQueuedMsduInfo(prGlueInfo->prAdapter, prMsduInfo); + return WLAN_STATUS_RESOURCES; + } + } + prUsbReq = list_entry(prHifInfo->rTxDataFreeQ[ucTc].next, struct _USB_REQ_T, list); + prBufCtrl = prUsbReq->prBufCtrl; + + if (prHifInfo->u4AggRsvSize[ucTc] < ALIGN_4(u4Length)) + DBGLOG(HAL, ERROR, "u4AggRsvSize[%hhu] count FAIL (%u, %u)\n", + ucTc, prHifInfo->u4AggRsvSize[ucTc], u4Length); + prHifInfo->u4AggRsvSize[ucTc] -= ALIGN_4(u4Length); + + if (prBufCtrl->u4WrIdx + ALIGN_4(u4Length) + LEN_USB_UDMA_TX_TERMINATOR > prBufCtrl->u4BufSize) { + halTxUSBSendAggData(prHifInfo, ucTc, prUsbReq); + + if (list_empty(&prHifInfo->rTxDataFreeQ[ucTc])) { + if (glUsbBorrowFfaReq(prHifInfo, ucTc) == FALSE) { + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, flags); + DBGLOG(HAL, ERROR, "run out of rTxDataFreeQ #2!!\n"); + wlanProcessQueuedMsduInfo(prGlueInfo->prAdapter, prMsduInfo); + return WLAN_STATUS_FAILURE; + } + } + + prUsbReq = list_entry(prHifInfo->rTxDataFreeQ[ucTc].next, struct _USB_REQ_T, list); + prBufCtrl = prUsbReq->prBufCtrl; + } + + memcpy(prBufCtrl->pucBuf + prBufCtrl->u4WrIdx, pucBuf, u4Length); + prBufCtrl->u4WrIdx += u4Length; + + u4PaddingLength = (ALIGN_4(u4Length) - u4Length); + if (u4PaddingLength) { + memset(prBufCtrl->pucBuf + prBufCtrl->u4WrIdx, 0, u4PaddingLength); + prBufCtrl->u4WrIdx += u4PaddingLength; + } + + if (!prMsduInfo->pfTxDoneHandler) + QUEUE_INSERT_TAIL(&prUsbReq->rSendingDataMsduInfoList, (P_QUE_ENTRY_T) prMsduInfo); + + if (usb_anchor_empty(&prHifInfo->rTxDataAnchor[ucTc])) + halTxUSBSendAggData(prHifInfo, ucTc, prUsbReq); + + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, flags); +#else + prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxDataFreeQ, &prHifInfo->rTxDataQLock); + if (prUsbReq == NULL) { + DBGLOG(HAL, ERROR, "run out of rTxDataFreeQ!!\n"); + wlanProcessQueuedMsduInfo(prGlueInfo->prAdapter, prMsduInfo); + return WLAN_STATUS_RESOURCES; + } + + prBufCtrl = prUsbReq->prBufCtrl; + prBufCtrl->u4WrIdx = 0; + + memcpy(prBufCtrl->pucBuf, pucBuf, u4Length); + prBufCtrl->u4WrIdx += u4Length; + + u4PaddingLength = (ALIGN_4(u4Length) - u4Length); + if (u4PaddingLength) { + memset(prBufCtrl->pucBuf + prBufCtrl->u4WrIdx, 0, u4PaddingLength); + prBufCtrl->u4WrIdx += u4PaddingLength; + } + + memset(prBufCtrl->pucBuf + prBufCtrl->u4WrIdx, 0, LEN_USB_UDMA_TX_TERMINATOR); + prBufCtrl->u4WrIdx += LEN_USB_UDMA_TX_TERMINATOR; + + if (!prMsduInfo->pfTxDoneHandler) + QUEUE_INSERT_TAIL(&prUsbReq->rSendingDataMsduInfoList, (P_QUE_ENTRY_T) prMsduInfo); + + *((PUINT_8)&prUsbReq->prPriv) = ucTc; + usb_fill_bulk_urb(prUsbReq->prUrb, + prHifInfo->udev, + usb_sndbulkpipe(prHifInfo->udev, arTcToUSBEP[ucTc]), + (void *)prUsbReq->prBufCtrl->pucBuf, + prBufCtrl->u4WrIdx, halTxUSBSendDataComplete, (void *)prUsbReq); +#if CFG_USB_CONSISTENT_DMA + prUsbReq->prUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; +#endif + + usb_anchor_urb(prUsbReq->prUrb, &prHifInfo->rTxDataAnchor); + u4Status = glUsbSubmitUrb(prHifInfo, prUsbReq->prUrb, SUBMIT_TYPE_TX_DATA); + if (u4Status) { + DBGLOG(HAL, ERROR, "glUsbSubmitUrb() reports error (%d)\n", u4Status); + halTxUSBProcessMsduDone(prHifInfo->prGlueInfo, prUsbReq); + prBufCtrl->u4WrIdx = 0; + usb_unanchor_urb(prUsbReq->prUrb); + glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxDataFreeQ, prUsbReq, &prHifInfo->rTxDataQLock, FALSE); + return WLAN_STATUS_FAILURE; + } +#endif + + if (wlanIsChipRstRecEnabled(prGlueInfo->prAdapter) + && wlanIsChipNoAck(prGlueInfo->prAdapter)) { + wlanChipRstPreAct(prGlueInfo->prAdapter); +#if CFG_CHIP_RESET_SUPPORT + glResetTrigger(prGlueInfo->prAdapter); +#else + DBGLOG(HAL, ERROR, "usb trigger whole reset\n"); + HAL_WIFI_FUNC_CHIP_RESET(prGlueInfo->prAdapter); +#endif + } + return u4Status; +} + +WLAN_STATUS halTxUSBKickData(IN P_GLUE_INFO_T prGlueInfo) +{ +#if CFG_USB_TX_AGG + P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; + P_USB_REQ_T prUsbReq; + P_BUF_CTRL_T prBufCtrl; + UINT_8 ucTc; + unsigned long flags; + + spin_lock_irqsave(&prHifInfo->rTxDataQLock, flags); + + for (ucTc = TC0_INDEX; ucTc < USB_TC_NUM; ucTc++) { + if (list_empty(&prHifInfo->rTxDataFreeQ[ucTc])) + continue; + + prUsbReq = list_entry(prHifInfo->rTxDataFreeQ[ucTc].next, struct _USB_REQ_T, list); + prBufCtrl = prUsbReq->prBufCtrl; + + if (prBufCtrl->u4WrIdx) + halTxUSBSendAggData(prHifInfo, ucTc, prUsbReq); + } + + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, flags); +#endif + + return WLAN_STATUS_SUCCESS; +} + +VOID halTxUSBSendDataComplete(struct urb *urb) +{ + P_USB_REQ_T prUsbReq = urb->context; + P_GL_HIF_INFO_T prHifInfo = prUsbReq->prHifInfo; + P_GLUE_INFO_T prGlueInfo = prHifInfo->prGlueInfo; + + glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxDataCompleteQ, prUsbReq, &prHifInfo->rTxDataQLock, FALSE); + +#if CFG_USB_TX_HANDLE_IN_HIF_THREAD + kalSetIntEvent(prGlueInfo); +#else + /*tasklet_hi_schedule(&prGlueInfo->rTxCompleteTask);*/ + tasklet_schedule(&prGlueInfo->rTxCompleteTask); +#endif +} + +VOID halTxUSBProcessMsduDone(IN P_GLUE_INFO_T prGlueInfo, P_USB_REQ_T prUsbReq) +{ + UINT_8 ucTc; + QUE_T rFreeQueue; + P_QUE_T prFreeQueue; + struct urb *urb = prUsbReq->prUrb; + UINT_32 u4SentDataSize; + + if (g_u4HaltFlag) { + DBGLOG(TX, WARN, "wlan is halt\n"); + return; + } + + ucTc = *((PUINT_8)&prUsbReq->prPriv) & TC_MASK; + + prFreeQueue = &rFreeQueue; + QUEUE_INITIALIZE(prFreeQueue); + QUEUE_MOVE_ALL((prFreeQueue), (&(prUsbReq->rSendingDataMsduInfoList))); + if (g_pfTxDataDoneCb) + g_pfTxDataDoneCb(prGlueInfo, prFreeQueue); + + u4SentDataSize = urb->actual_length - LEN_USB_UDMA_TX_TERMINATOR; + nicTxReleaseResource(prGlueInfo->prAdapter, ucTc, nicTxGetPageCount(u4SentDataSize, TRUE), TRUE); +} + +VOID halTxUSBProcessDataComplete(IN P_ADAPTER_T prAdapter, P_USB_REQ_T prUsbReq) +{ + UINT_8 ucTc; + BOOLEAN fgFfa; + struct urb *urb = prUsbReq->prUrb; + P_GL_HIF_INFO_T prHifInfo = prUsbReq->prHifInfo; +#if CFG_USB_TX_AGG + P_BUF_CTRL_T prBufCtrl = prUsbReq->prBufCtrl; +#endif + unsigned long flags; + + ucTc = *((PUINT_8)&prUsbReq->prPriv) & TC_MASK; + fgFfa = *((PUINT_8)&prUsbReq->prPriv) & FFA_MASK; + + if (urb->status != 0) { + DBGLOG(TX, ERROR, "[%s] send DATA fail (status = %d)\n", __func__, urb->status); + /* TODO: handle error */ + if ((prAdapter->prGlueInfo-> + rHifInfo.state == USB_STATE_WIFI_OFF) + || (prAdapter->rTxCtrl.pucTxCached == NULL)) + return; + } + + halTxUSBProcessMsduDone(prAdapter->prGlueInfo, prUsbReq); + + spin_lock_irqsave(&prHifInfo->rTxDataQLock, flags); +#if CFG_USB_TX_AGG + prBufCtrl->u4WrIdx = 0; + + if ((fgFfa == FALSE) || list_empty(&prHifInfo->rTxDataFreeQ[ucTc])) + list_add_tail(&prUsbReq->list, &prHifInfo->rTxDataFreeQ[ucTc]); + else + list_add_tail(&prUsbReq->list, &prHifInfo->rTxDataFfaQ); + + if (usb_anchor_empty(&prHifInfo->rTxDataAnchor[ucTc])) { + prUsbReq = list_entry(prHifInfo->rTxDataFreeQ[ucTc].next, struct _USB_REQ_T, list); + prBufCtrl = prUsbReq->prBufCtrl; + + if (prBufCtrl->u4WrIdx != 0) + halTxUSBSendAggData(prHifInfo, ucTc, prUsbReq); /* TODO */ + } +#else + list_add_tail(&prUsbReq->list, &prHifInfo->rTxDataFreeQ); +#endif + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, flags); + + if (!HAL_IS_TX_DIRECT(prAdapter)) { + if (kalGetTxPendingCmdCount(prAdapter->prGlueInfo) > 0 || wlanGetTxPendingFrameCount(prAdapter) > 0) + kalSetEvent(prAdapter->prGlueInfo); + kalSetTxEvent2Hif(prAdapter->prGlueInfo); + } +} + +UINT_32 halRxUSBEnqueueRFB(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuf, IN UINT_32 u4Length, + IN UINT_32 u4MinRfbCnt) +{ + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + P_RX_CTRL_T prRxCtrl = &prAdapter->rRxCtrl; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; + P_HW_MAC_RX_DESC_T prRxStatus; + UINT_32 u4RemainCount; + UINT_16 u2RxByteCount; + UINT_8 *pucRxFrame; + UINT_32 u4EnqCnt = 0; + + KAL_SPIN_LOCK_DECLARATION(); + + pucRxFrame = pucBuf; + u4RemainCount = u4Length; + while (u4RemainCount > 4) { + u2RxByteCount = HAL_RX_STATUS_GET_RX_BYTE_CNT((P_HW_MAC_RX_DESC_T) pucRxFrame); + u2RxByteCount = ALIGN_4(u2RxByteCount) + LEN_USB_RX_PADDING_CSO; + + if (u2RxByteCount <= CFG_RX_MAX_PKT_SIZE) { + prSwRfb = NULL; + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + if (prRxCtrl->rFreeSwRfbList.u4NumElem > u4MinRfbCnt) + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); + + if (!prSwRfb) + return u4Length - u4RemainCount; + + kalMemCopy(prSwRfb->pucRecvBuff, pucRxFrame, u2RxByteCount); + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + prSwRfb->ucPacketType = (UINT_8) HAL_RX_STATUS_GET_PKT_TYPE(prRxStatus); + /* DBGLOG(RX, TRACE, ("ucPacketType = %d\n", prSwRfb->ucPacketType)); */ +#if DBG + DBGLOG(RX, TRACE, "Rx status flag = %x wlan index = %d SecMode = %d\n", + prRxStatus->u2StatusFlag, prRxStatus->ucWlanIdx, HAL_RX_STATUS_GET_SEC_MODE(prRxStatus)); +#endif + if (HAL_IS_RX_DIRECT(prAdapter)) { + switch (prSwRfb->ucPacketType) { + case RX_PKT_TYPE_RX_DATA: +#if CFG_SUPPORT_SNIFFER + if (prGlueInfo->fgIsEnableMon) { + nicRxProcessMonitorPacket(prAdapter, prSwRfb); + break; + } +#endif + nicRxProcessDataPacket(prAdapter, prSwRfb); + break; + default: + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_INSERT_TAIL(&prRxCtrl->rReceivedRfbList, &prSwRfb->rQueEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + u4EnqCnt++; + break; + } + } else { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_INSERT_TAIL(&prRxCtrl->rReceivedRfbList, &prSwRfb->rQueEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + u4EnqCnt++; + } + RX_INC_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT); + } else { + DBGLOG(RX, WARN, "Rx byte count:%u exceeds SW_RFB max length:%u\n!", + u2RxByteCount, CFG_RX_MAX_PKT_SIZE); + DBGLOG_MEM32(RX, WARN, pucRxFrame, sizeof(HW_MAC_RX_DESC_T)); + break; + } + + u4RemainCount -= u2RxByteCount; + pucRxFrame += u2RxByteCount; + } + + if (u4EnqCnt) { + set_bit(GLUE_FLAG_RX_BIT, &(prGlueInfo->ulFlag)); + wake_up_interruptible(&(prGlueInfo->waitq)); + } + + return u4Length; +} + +WLAN_STATUS halRxUSBReceiveEvent(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgFillUrb) +{ + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; + P_USB_REQ_T prUsbReq; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + while (1) { + prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, &prHifInfo->rRxEventQLock); + if (prUsbReq == NULL) + return WLAN_STATUS_RESOURCES; + + usb_anchor_urb(prUsbReq->prUrb, &prHifInfo->rRxEventAnchor); + + prUsbReq->prBufCtrl->u4ReadSize = 0; + if (prHifInfo->eEventEpType == EVENT_EP_TYPE_INTR && fgFillUrb) { + usb_fill_int_urb(prUsbReq->prUrb, + prHifInfo->udev, + usb_rcvintpipe(prHifInfo->udev, USB_EVENT_EP_IN), + (void *)prUsbReq->prBufCtrl->pucBuf, prUsbReq->prBufCtrl->u4BufSize, + halRxUSBReceiveEventComplete, (void *)prUsbReq, 1); + } else if (prHifInfo->eEventEpType == EVENT_EP_TYPE_BULK) { + usb_fill_bulk_urb(prUsbReq->prUrb, + prHifInfo->udev, + usb_rcvbulkpipe(prHifInfo->udev, USB_EVENT_EP_IN), + (void *)prUsbReq->prBufCtrl->pucBuf, prUsbReq->prBufCtrl->u4BufSize, + halRxUSBReceiveEventComplete, (void *)prUsbReq); + } + u4Status = glUsbSubmitUrb(prHifInfo, prUsbReq->prUrb, SUBMIT_TYPE_RX_EVENT); + if (u4Status) { + DBGLOG(HAL, ERROR, "glUsbSubmitUrb() reports error (%d)\n", u4Status); + usb_unanchor_urb(prUsbReq->prUrb); + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, + &prHifInfo->rRxEventQLock, FALSE); + break; + } + } + + return u4Status; +} + +VOID halRxUSBReceiveEventComplete(struct urb *urb) +{ + P_USB_REQ_T prUsbReq = urb->context; + P_GL_HIF_INFO_T prHifInfo = prUsbReq->prHifInfo; + P_GLUE_INFO_T prGlueInfo = prHifInfo->prGlueInfo; + + if (prHifInfo->state != USB_STATE_LINK_UP) { + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); + return; + } + + /* Hif power off wifi, drop rx packets and continue polling RX packets until RX path empty */ + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); + halRxUSBReceiveEvent(prGlueInfo->prAdapter, FALSE); + return; + } + + if (urb->status == -ESHUTDOWN || urb->status == -ENOENT) { + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); + DBGLOG(RX, ERROR, "USB device shutdown skip Rx [%s]\n", __func__); + return; + } + +#if CFG_USB_RX_HANDLE_IN_HIF_THREAD + DBGLOG(RX, TRACE, "[%s] Rx URB[0x%p] Len[%u] Sts[%u]\n", __func__, urb, urb->actual_length, urb->status); + + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventCompleteQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); + + kalSetIntEvent(prGlueInfo); +#else + if (urb->status == 0) { + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventCompleteQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); + + /*tasklet_hi_schedule(&prGlueInfo->rRxTask);*/ + tasklet_schedule(&prGlueInfo->rRxTask); + } else { + DBGLOG(RX, ERROR, "[%s] receive EVENT fail (status = %d)\n", __func__, urb->status); + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); + + halRxUSBReceiveEvent(prGlueInfo->prAdapter, FALSE); + } +#endif +} + +WLAN_STATUS halRxUSBReceiveData(IN P_ADAPTER_T prAdapter) +{ + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; + P_USB_REQ_T prUsbReq; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + while (1) { + prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, &prHifInfo->rRxDataQLock); + if (prUsbReq == NULL) + return WLAN_STATUS_RESOURCES; + + usb_anchor_urb(prUsbReq->prUrb, &prHifInfo->rRxDataAnchor); + + prUsbReq->prBufCtrl->u4ReadSize = 0; + usb_fill_bulk_urb(prUsbReq->prUrb, + prHifInfo->udev, + usb_rcvbulkpipe(prHifInfo->udev, USB_DATA_EP_IN), + (void *)prUsbReq->prBufCtrl->pucBuf, + prUsbReq->prBufCtrl->u4BufSize, halRxUSBReceiveDataComplete, (void *)prUsbReq); + u4Status = glUsbSubmitUrb(prHifInfo, prUsbReq->prUrb, SUBMIT_TYPE_RX_DATA); + if (u4Status) { + DBGLOG(HAL, ERROR, "glUsbSubmitUrb() reports error (%d)\n", u4Status); + usb_unanchor_urb(prUsbReq->prUrb); + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE); + break; + } + } + + return u4Status; +} + +VOID halRxUSBReceiveDataComplete(struct urb *urb) +{ + P_USB_REQ_T prUsbReq = urb->context; + P_GL_HIF_INFO_T prHifInfo = prUsbReq->prHifInfo; + P_GLUE_INFO_T prGlueInfo = prHifInfo->prGlueInfo; + static UINT_32 uUsbCmdFailCounter; + + if (prHifInfo->state != USB_STATE_LINK_UP) { + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE); + return; + } + + /* Hif power off wifi, drop rx packets and continue polling RX packets until RX path empty */ + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE); + halRxUSBReceiveData(prGlueInfo->prAdapter); + return; + } + + if (urb->status == -ESHUTDOWN || urb->status == -ENOENT) { + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE); + DBGLOG(RX, ERROR, "USB device shutdown skip Rx [%s]\n", __func__); + return; + } + +#if CFG_USB_RX_HANDLE_IN_HIF_THREAD + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataCompleteQ, prUsbReq, FALSE); + + kalSetIntEvent(prGlueInfo); +#else + if (urb->status == 0) { + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataCompleteQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE); + + /*tasklet_hi_schedule(&prGlueInfo->rRxTask);*/ + tasklet_schedule(&prGlueInfo->rRxTask); + uUsbCmdFailCounter = 0; + } else { + LIMITED_DBGLOG(RX, ERROR, + "[%s] receive DATA fail (status = %d)\n", + __func__, urb->status); + + if ((urb->status == -EOVERFLOW) || (urb->status == -EPROTO)) + uUsbCmdFailCounter++; + + if (uUsbCmdFailCounter > 3) { + prGlueInfo->prAdapter->fgIsChipNoAck = TRUE; + if (uUsbCmdFailCounter > 10) + return; + } + + glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, + prUsbReq, &prHifInfo->rRxDataQLock, FALSE); + halRxUSBReceiveData(prGlueInfo->prAdapter); + } +#endif +} + +VOID halRxUSBProcessEventDataComplete(IN P_ADAPTER_T prAdapter, + struct list_head *prCompleteQ, struct list_head *prFreeQ, UINT_32 u4MinRfbCnt) +{ + P_USB_REQ_T prUsbReq; + struct urb *prUrb; + P_BUF_CTRL_T prBufCtrl; + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; + PUINT_8 pucBufAddr; + UINT_32 u4BufLen; + static BOOL s_fgOutOfSwRfb = FALSE; + static UINT_32 s_u4OutOfSwRfbPrintLimit; + static UINT_32 s_u4OutOfSwRfbBeginTime; + + /* Process complete event/data */ + prUsbReq = glUsbDequeueReq(prHifInfo, prCompleteQ, &prHifInfo->rRxEventQLock); + while (prUsbReq) { + prUrb = prUsbReq->prUrb; + prBufCtrl = prUsbReq->prBufCtrl; + + DBGLOG(RX, LOUD, "[%s] Rx URB[0x%p] Len[%u] Sts[%u]\n", __func__, + prUrb, prUrb->actual_length, prUrb->status); + + if (prUrb->status != 0) { + DBGLOG(RX, ERROR, "[%s] receive EVENT/DATA fail (status = %d)\n", __func__, prUrb->status); + + glUsbEnqueueReq(prHifInfo, prFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); + prUsbReq = glUsbDequeueReq(prHifInfo, prCompleteQ, &prHifInfo->rRxEventQLock); + continue; + } + + pucBufAddr = prBufCtrl->pucBuf + prBufCtrl->u4ReadSize; + u4BufLen = prUrb->actual_length - prBufCtrl->u4ReadSize; + + prBufCtrl->u4ReadSize += halRxUSBEnqueueRFB(prAdapter, pucBufAddr, u4BufLen, u4MinRfbCnt); + + if (unlikely(prUrb->actual_length - prBufCtrl->u4ReadSize > 4)) { + if (s_fgOutOfSwRfb == FALSE) { + if ((long)jiffies - (long)s_u4OutOfSwRfbPrintLimit > 0) { + DBGLOG(RX, WARN, "Out of SwRfb!\n"); + s_u4OutOfSwRfbPrintLimit = jiffies + MSEC_TO_JIFFIES(SW_RFB_LOG_LIMIT_MS); + } + s_u4OutOfSwRfbBeginTime = jiffies; + s_fgOutOfSwRfb = TRUE; + } + + /* If the out-of-SW-RFB situation continues more than SW_RFB_BLOCKING_LIMIT_MS millie seconds, + * we discard the remaining Rx packets so as to break the possible dead lock + */ + if (jiffies_to_msecs((long)jiffies - (long)s_u4OutOfSwRfbBeginTime) > + SW_RFB_BLOCKING_LIMIT_MS) { + DBGLOG(RX, WARN, "Discard Rx packets (%u bytes)!\n", + prUrb->actual_length - prBufCtrl->u4ReadSize); + glUsbEnqueueReq(prHifInfo, prFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); + s_fgOutOfSwRfb = FALSE; + break; + } + + glUsbEnqueueReq(prHifInfo, prCompleteQ, prUsbReq, &prHifInfo->rRxEventQLock, TRUE); + + set_bit(GLUE_FLAG_RX_BIT, &prGlueInfo->ulFlag); + wake_up_interruptible(&prGlueInfo->waitq); + + schedule_delayed_work(&prGlueInfo->rRxPktDeAggWork, MSEC_TO_JIFFIES(SW_RFB_RECHECK_MS)); + break; + } + + if (unlikely(s_fgOutOfSwRfb == TRUE)) + s_fgOutOfSwRfb = FALSE; + + glUsbEnqueueReq(prHifInfo, prFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); + prUsbReq = glUsbDequeueReq(prHifInfo, prCompleteQ, &prHifInfo->rRxEventQLock); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief enable global interrupt +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID halEnableInterrupt(IN P_ADAPTER_T prAdapter) +{ + P_GLUE_INFO_T prGlueInfo; + P_GL_HIF_INFO_T prHifInfo; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + prHifInfo = &prGlueInfo->rHifInfo; + + halRxUSBReceiveData(prAdapter); + if (prHifInfo->eEventEpType != EVENT_EP_TYPE_DATA_EP) + halRxUSBReceiveEvent(prAdapter, TRUE); + + glUdmaRxAggEnable(prGlueInfo, TRUE); +} /* end of halEnableInterrupt() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief disable global interrupt +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID halDisableInterrupt(IN P_ADAPTER_T prAdapter) +{ + P_GLUE_INFO_T prGlueInfo; + P_GL_HIF_INFO_T prHifInfo; + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + prHifInfo = &prGlueInfo->rHifInfo; + + usb_kill_anchored_urbs(&prHifInfo->rRxDataAnchor); + usb_kill_anchored_urbs(&prHifInfo->rRxEventAnchor); + + glUdmaRxAggEnable(prGlueInfo, FALSE); + prAdapter->fgIsIntEnable = FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to process the POWER OFF procedure. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN halSetDriverOwn(IN P_ADAPTER_T prAdapter) +{ + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to process the POWER ON procedure. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID halSetFWOwn(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnableGlobalInt) +{ +} + +VOID halWakeUpWiFi(IN P_ADAPTER_T prAdapter) +{ + BOOLEAN fgResult; + UINT_8 ucCount = 0; + +#if CFG_SUPPORT_PMIC_SPI_CLOCK_SWITCH + UINT_32 u4Value = 0; + /*E1 PMIC clock workaround*/ + HAL_MCR_RD(prAdapter, TOP_CKGEN2_CR_PMIC_CK_MANUAL, &u4Value); + + if ((TOP_CKGEN2_CR_PMIC_CK_MANUAL_MASK & u4Value) == 0) + HAL_MCR_WR(prAdapter, TOP_CKGEN2_CR_PMIC_CK_MANUAL, (TOP_CKGEN2_CR_PMIC_CK_MANUAL_MASK|u4Value)); + HAL_MCR_RD(prAdapter, TOP_CKGEN2_CR_PMIC_CK_MANUAL, &u4Value); + DBGLOG(INIT, INFO, "PMIC SPI clock switch = %s\n", + (TOP_CKGEN2_CR_PMIC_CK_MANUAL_MASK&u4Value) ? "SUCCESS" : "FAIL"); +#endif + + DBGLOG(INIT, INFO, "Power on Wi-Fi....\n"); + + HAL_WIFI_FUNC_READY_CHECK(prAdapter, WIFI_FUNC_INIT_DONE, &fgResult); + + while (!fgResult) { + HAL_WIFI_FUNC_POWER_ON(prAdapter); + kalMdelay(50); + HAL_WIFI_FUNC_READY_CHECK(prAdapter, WIFI_FUNC_INIT_DONE, &fgResult); + + ucCount++; + + if (ucCount >= 5) { + DBGLOG(INIT, WARN, "Power on failed!!!\n"); + break; + } + } + + if (prAdapter->prGlueInfo->rHifInfo.state == USB_STATE_WIFI_OFF) + glUsbSetState(&prAdapter->prGlueInfo->rHifInfo, + USB_STATE_LINK_UP); + + prAdapter->fgIsFwOwn = FALSE; +} + +VOID halEnableFWDownload(IN P_ADAPTER_T prAdapter, IN BOOL fgEnable) +{ +#if (CFG_UMAC_GENERATION >= 0x20) + + UINT_32 u4Value = 0; + + ASSERT(prAdapter); + + { + HAL_MCR_RD(prAdapter, UDMA_TX_QSEL, &u4Value); + + if (fgEnable) + u4Value |= FW_DL_EN; + else + u4Value &= ~FW_DL_EN; + + HAL_MCR_WR(prAdapter, UDMA_TX_QSEL, u4Value); + } +#endif +} + +VOID halDevInit(IN P_ADAPTER_T prAdapter) +{ + P_GLUE_INFO_T prGlueInfo; + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + + glUdmaRxAggEnable(prGlueInfo, FALSE); + glUdmaTxRxEnable(prGlueInfo, TRUE); +} + +BOOLEAN halTxIsDataBufEnough(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; +#if CFG_USB_TX_AGG + P_USB_REQ_T prUsbReq; + P_BUF_CTRL_T prBufCtrl; +#endif + UINT_8 ucTc; + struct sk_buff *skb; + UINT_32 u4Length; + + unsigned long flags; + + skb = (struct sk_buff *)prMsduInfo->prPacket; + u4Length = skb->len; + ucTc = USB_TRANS_MSDU_TC(prMsduInfo); + + spin_lock_irqsave(&prHifInfo->rTxDataQLock, flags); + +#if CFG_USB_TX_AGG + if (list_empty(&prHifInfo->rTxDataFreeQ[ucTc])) { + if (glUsbBorrowFfaReq(prHifInfo, ucTc) == FALSE) { + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, flags); + return FALSE; + } + } + + prUsbReq = list_entry(prHifInfo->rTxDataFreeQ[ucTc].next, struct _USB_REQ_T, list); + prBufCtrl = prUsbReq->prBufCtrl; + + if (prHifInfo->rTxDataFreeQ[ucTc].next->next == &prHifInfo->rTxDataFreeQ[ucTc]) { + /* length of rTxDataFreeQ equals 1 */ + if (prBufCtrl->u4WrIdx + ALIGN_4(u4Length) > + prBufCtrl->u4BufSize - prHifInfo->u4AggRsvSize[ucTc] - LEN_USB_UDMA_TX_TERMINATOR) { + /* Buffer is not enough */ + if (glUsbBorrowFfaReq(prHifInfo, ucTc) == FALSE) { + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, flags); + return FALSE; + } + } + } + prHifInfo->u4AggRsvSize[ucTc] += ALIGN_4(u4Length); +#else + if (list_empty(&prHifInfo->rTxDataFreeQ)) { + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, flags); + + return FALSE; + } +#endif + + spin_unlock_irqrestore(&prHifInfo->rTxDataQLock, flags); + return TRUE; +} + +VOID halProcessTxInterrupt(IN P_ADAPTER_T prAdapter) +{ +#if CFG_USB_TX_HANDLE_IN_HIF_THREAD + P_USB_REQ_T prUsbReq; + P_GL_HIF_INFO_T prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + /* Process complete Tx cmd */ + prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxCmdCompleteQ, &prHifInfo->rTxCmdQLock); + while (prUsbReq) { + halTxUSBProcessCmdComplete(prAdapter, prUsbReq); + prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxCmdCompleteQ, &prHifInfo->rTxCmdQLock); + } + + /* Process complete Tx data */ + prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxDataCompleteQ, &prHifInfo->rTxDataQLock); + while (prUsbReq) { + halTxUSBProcessDataComplete(prAdapter, prUsbReq); + prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxDataCompleteQ, &prHifInfo->rTxDataQLock); + } +#endif +} + +VOID halHifSwInfoInit(IN P_ADAPTER_T prAdapter) +{ + +} + +VOID halRxProcessMsduReport(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) +{ + +} + +UINT_32 halTxGetPageCount(IN UINT_32 u4FrameLength, IN BOOLEAN fgIncludeDesc) +{ +#if CFG_USB_TX_AGG + UINT_32 u4RequiredBufferSize; + UINT_32 u4PageCount; + + /* Frame Buffer + * |<--Tx Descriptor-->|<--Tx descriptor padding-->| + * <--802.3/802.11 Header-->|<--Header padding-->|<--Payload-->| + */ + + if (fgIncludeDesc) + u4RequiredBufferSize = u4FrameLength; + else + u4RequiredBufferSize = NIC_TX_HEAD_ROOM + u4FrameLength; + + u4RequiredBufferSize = ALIGN_4(u4RequiredBufferSize); + + if (NIC_TX_PAGE_SIZE_IS_POWER_OF_2) + u4PageCount = (u4RequiredBufferSize + (NIC_TX_PAGE_SIZE - 1)) >> NIC_TX_PAGE_SIZE_IN_POWER_OF_2; + else + u4PageCount = (u4RequiredBufferSize + (NIC_TX_PAGE_SIZE - 1)) / NIC_TX_PAGE_SIZE; + + return u4PageCount; +#else + return 1; +#endif +} + +WLAN_STATUS halTxPollingResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC) +{ + return WLAN_STATUS_SUCCESS; +} + +VOID halSerHifReset(IN P_ADAPTER_T prAdapter) +{ +} + +VOID halProcessRxInterrupt(IN P_ADAPTER_T prAdapter) +{ + P_GL_HIF_INFO_T prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + if (g_u4HaltFlag) { + DBGLOG(RX, WARN, "wlan is halt\n"); + return; + } + + /* Process complete data */ + halRxUSBProcessEventDataComplete(prAdapter, &prHifInfo->rRxDataCompleteQ, + &prHifInfo->rRxDataFreeQ, USB_RX_DATA_RFB_RSV_CNT); + halRxUSBReceiveData(prAdapter); + + if (prHifInfo->eEventEpType != EVENT_EP_TYPE_DATA_EP) { + /* Process complete event */ + halRxUSBProcessEventDataComplete(prAdapter, &prHifInfo->rRxEventCompleteQ, + &prHifInfo->rRxEventFreeQ, USB_RX_EVENT_RFB_RSV_CNT); + halRxUSBReceiveEvent(prAdapter, FALSE); + } +} + +UINT_32 halDumpHifStatus(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuf, IN UINT_32 u4Max) +{ + UINT_32 u4CpuIdx, u4DmaIdx, u4Int, u4GloCfg, u4Reg; + UINT_32 u4Len = 0; + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + UCHAR pBuffer[512] = {0}; + + HAL_MCR_RD(prAdapter, 0x820b0118, &u4CpuIdx); + HAL_MCR_RD(prAdapter, 0x820b011c, &u4DmaIdx); + HAL_MCR_RD(prAdapter, 0x820b0220, &u4Int); + HAL_MCR_RD(prAdapter, 0x820b0204, &u4GloCfg); + + LOGBUF(pucBuf, u4Max, u4Len, "\n"); + LOGBUF(pucBuf, u4Max, u4Len, "PDMA1R1 CPU[%u] DMA[%u] INT[0x%08x] CFG[0x%08x]\n", u4CpuIdx, + u4DmaIdx, u4Int, u4GloCfg); + + HAL_MCR_RD(prAdapter, UDMA_WLCFG_0, &u4Reg); + + LOGBUF(pucBuf, u4Max, u4Len, "UDMA WLCFG[0x%08x]\n", u4Reg); + + LOGBUF(pucBuf, u4Max, u4Len, "\n"); + LOGBUF(pucBuf, u4Max, u4Len, "VenderID: %04x\n", + glGetUsbDeviceVendorId(prGlueInfo->rHifInfo.udev)); + LOGBUF(pucBuf, u4Max, u4Len, "ProductID: %04x\n", + glGetUsbDeviceProductId(prGlueInfo->rHifInfo.udev)); + + glGetUsbDeviceManufacturerName(prGlueInfo->rHifInfo.udev, pBuffer, + sizeof(pBuffer)); + LOGBUF(pucBuf, u4Max, u4Len, "Manufacturer: %s\n", + pBuffer); + + glGetUsbDeviceProductName(prGlueInfo->rHifInfo.udev, pBuffer, + sizeof(pBuffer)); + LOGBUF(pucBuf, u4Max, u4Len, "Product: %s\n", pBuffer); + + glGetUsbDeviceSerialNumber(prGlueInfo->rHifInfo.udev, pBuffer, + sizeof(pBuffer)); + LOGBUF(pucBuf, u4Max, u4Len, "SerialNumber: %s\n", + pBuffer); + + return u4Len; +} + +VOID halGetCompleteStatus(IN P_ADAPTER_T prAdapter, OUT PUINT_32 pu4IntStatus) +{ +#if CFG_USB_RX_HANDLE_IN_HIF_THREAD || CFG_USB_TX_HANDLE_IN_HIF_THREAD + P_GL_HIF_INFO_T prHifInfo = &prAdapter->prGlueInfo->rHifInfo; +#endif + + *pu4IntStatus = 0; + +#if CFG_USB_RX_HANDLE_IN_HIF_THREAD + if (!list_empty(&prHifInfo->rRxDataCompleteQ) || !list_empty(&prHifInfo->rRxEventCompleteQ)) + *pu4IntStatus |= WHISR_RX0_DONE_INT; +#endif + +#if CFG_USB_TX_HANDLE_IN_HIF_THREAD + if (!list_empty(&prHifInfo->rTxDataCompleteQ) || !list_empty(&prHifInfo->rTxCmdCompleteQ)) + *pu4IntStatus |= WHISR_TX_DONE_INT; +#endif +} + +BOOLEAN halIsPendingRx(IN P_ADAPTER_T prAdapter) +{ +#if CFG_USB_RX_HANDLE_IN_HIF_THREAD + P_GL_HIF_INFO_T prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + if (!list_empty(&prHifInfo->rRxDataCompleteQ) || !list_empty(&prHifInfo->rRxEventCompleteQ)) + return TRUE; + else + return FALSE; +#else + return FALSE; +#endif +} + +VOID halUSBPreSuspendCmd(IN P_ADAPTER_T prAdapter) +{ + CMD_HIF_CTRL_T rCmdHifCtrl; + WLAN_STATUS rStatus; + + rCmdHifCtrl.ucHifType = ENUM_HIF_TYPE_USB; + rCmdHifCtrl.ucHifDirection = ENUM_HIF_TX; + rCmdHifCtrl.ucHifStop = 1; + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_HIF_CTRL, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_HIF_CTRL_T), /* u4SetQueryInfoLen */ + (PUINT_8)&rCmdHifCtrl, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); +} + +VOID halUSBPreSuspendDone(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + unsigned long flags; + P_GL_HIF_INFO_T prHifInfo; + + ASSERT(prAdapter); + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + spin_lock_irqsave(&prHifInfo->rStateLock, flags); + + if (prHifInfo->state == USB_STATE_LINK_UP) + prHifInfo->state = USB_STATE_PRE_SUSPEND_DONE; + else + DBGLOG(HAL, ERROR, "Previous USB state (%d)!\n", prHifInfo->state); + + spin_unlock_irqrestore(&prHifInfo->rStateLock, flags); +} + +VOID halUSBPreSuspendTimeout(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + unsigned long flags; + P_GL_HIF_INFO_T prHifInfo; + + ASSERT(prAdapter); + prHifInfo = &prAdapter->prGlueInfo->rHifInfo; + + spin_lock_irqsave(&prHifInfo->rStateLock, flags); + + if (prHifInfo->state == USB_STATE_LINK_UP) + prHifInfo->state = USB_STATE_PRE_SUSPEND_FAIL; + else + DBGLOG(HAL, ERROR, "Previous USB state (%d)!\n", prHifInfo->state); + + spin_unlock_irqrestore(&prHifInfo->rStateLock, flags); +} + +UINT_32 halGetValidCoalescingBufSize(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4BufSize; + + if (HIF_TX_COALESCING_BUFFER_SIZE > HIF_RX_COALESCING_BUFFER_SIZE) + u4BufSize = HIF_TX_COALESCING_BUFFER_SIZE; + else + u4BufSize = HIF_RX_COALESCING_BUFFER_SIZE; + + return u4BufSize; +} + +WLAN_STATUS halAllocateIOBuffer(IN P_ADAPTER_T prAdapter) +{ + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS halReleaseIOBuffer(IN P_ADAPTER_T prAdapter) +{ + return WLAN_STATUS_SUCCESS; +} + +VOID halProcessSoftwareInterrupt(IN P_ADAPTER_T prAdapter) +{ + +} + +VOID halDeAggRxPktWorker(struct work_struct *work) +{ + P_GLUE_INFO_T prGlueInfo = ENTRY_OF(work, GLUE_INFO_T, rRxPktDeAggWork); + + /*tasklet_hi_schedule(&prGlueInfo->rRxTask);*/ + tasklet_schedule(&prGlueInfo->rRxTask); +} + +VOID halRxTasklet(unsigned long data) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)data; + + halProcessRxInterrupt(prGlueInfo->prAdapter); +} + +VOID halTxCompleteTasklet(unsigned long data) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)data; + P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; + P_USB_REQ_T prUsbReq; + + /* Process complete Tx data */ + prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxDataCompleteQ, &prHifInfo->rTxDataQLock); + while (prUsbReq) { + halTxUSBProcessDataComplete(prGlueInfo->prAdapter, prUsbReq); + prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxDataCompleteQ, &prHifInfo->rTxDataQLock); + } +} + +/* Hif power off wifi */ +WLAN_STATUS halHifPowerOffWifi(IN P_ADAPTER_T prAdapter) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DBGLOG(INIT, INFO, "Power off Wi-Fi!\n"); + + /* Power off Wi-Fi */ + rStatus = wlanSendNicPowerCtrlCmd(prAdapter, TRUE); + + rStatus = wlanCheckWifiFunc(prAdapter, FALSE); + + glUsbSetState(&prAdapter->prGlueInfo->rHifInfo, USB_STATE_WIFI_OFF); + + nicDisableInterrupt(prAdapter); + + wlanClearPendingInterrupt(prAdapter); + + halTxCancelAllSending(prAdapter); + + return rStatus; +} + +VOID halPrintHifDbgInfo(IN P_ADAPTER_T prAdapter) +{ + +} + +BOOLEAN halIsTxResourceControlEn(IN P_ADAPTER_T prAdapter) +{ + return FALSE; +} + +VOID halTxResourceResetHwTQCounter(IN P_ADAPTER_T prAdapter) +{ +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/usb/include/cust_usb_id.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/usb/include/cust_usb_id.h new file mode 100644 index 0000000000000..3b6f3add81113 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/usb/include/cust_usb_id.h @@ -0,0 +1,116 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "cust_usb_id.h" + * \brief Define USB vid/pid table for customers + */ + + +#ifndef _CUST_USB_ID_H +#define _CUST_USB_ID_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 +******************************************************************************** +*/ + +/*! + * \brief Additional USB vid/pid tables for customers. + * Please add your vid/pid in table below as the example shows. + * + */ +#define CUST_USB_ID_TABLES \ +/* +* { USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x7618, 0xff, 0xff, 0xff), \ +* .driver_info = (kernel_ulong_t)&mt66xx_driver_data_mt7668},\ +* { USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x7658, 0xff, 0xff, 0xff), \ +* .driver_info = (kernel_ulong_t)&mt66xx_driver_data_mt7668},\ +*/ + +/******************************************************************************* +* 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 /* _CUST_USB_ID_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/usb/include/hif.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/usb/include/hif.h new file mode 100644 index 0000000000000..436949326744a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/usb/include/hif.h @@ -0,0 +1,419 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \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 +*/ + + +#ifndef _HIF_H +#define _HIF_H + +#include "nic_cmd_event.h" +#include "wlan_typedef.h" +#include "nic_tx.h" + +typedef enum _ENUM_USB_END_POINT_T { + USB_DATA_BULK_OUT_EP4 = 4, + USB_DATA_BULK_OUT_EP5, + USB_DATA_BULK_OUT_EP6, + USB_DATA_BULK_OUT_EP7, + USB_DATA_BULK_OUT_EP8, + USB_DATA_BULK_OUT_EP9, +} ENUM_USB_END_POINT_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 +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#if defined(_HIF_USB) +#define HIF_NAME "USB" +#else +#error "No HIF defined!" +#endif +#define HIF_CR4_FWDL_SECTION_NUM 2 +#define HIF_IMG_DL_STATUS_PORT_IDX 0 +#define HIF_IST_LOOP_COUNT (4) +#define HIF_IST_TX_THRESHOLD (1) /* Min msdu count to trigger Tx during INT polling state */ + +#define HIF_NUM_OF_QM_RX_PKT_NUM (1024) + +#define HIF_TX_BUFF_COUNT_TC0 256 +#define HIF_TX_BUFF_COUNT_TC1 256 +#define HIF_TX_BUFF_COUNT_TC2 256 +#define HIF_TX_BUFF_COUNT_TC3 256 +#define HIF_TX_BUFF_COUNT_TC4 256 +#define HIF_TX_BUFF_COUNT_TC5 256 + +#define HIF_TX_RESOURCE_CTRL 0 /* enable/disable TX resource control */ + +#if CFG_USB_TX_AGG +#define HIF_TX_PAGE_SIZE_IN_POWER_OF_2 0 +#define HIF_TX_PAGE_SIZE 1 /* in unit of bytes */ +#else +#define HIF_TX_PAGE_SIZE_IN_POWER_OF_2 11 +#define HIF_TX_PAGE_SIZE 2048 /* in unit of bytes */ +#endif + +#define USB_EVENT_TYPE (EVENT_EP_TYPE_UNKONW) + +#define USB_CMD_EP_OUT (USB_DATA_BULK_OUT_EP8) +#define USB_EVENT_EP_IN (0x85) +#define USB_DATA_EP_IN (0x84) + +#define HIF_TX_INIT_CMD_PORT USB_CMD_EP_OUT + +#ifdef CFG_USB_REQ_TX_DATA_FFA_CNT +#define USB_REQ_TX_DATA_FFA_CNT (CFG_USB_REQ_TX_DATA_FFA_CNT) /* platform specific USB_REQ_TX_DATA_FFA_CNT */ +#else +#define USB_REQ_TX_DATA_FFA_CNT (10) +#endif + +#ifdef CFG_USB_REQ_TX_DATA_CNT +#define USB_REQ_TX_DATA_CNT (CFG_USB_REQ_TX_DATA_CNT) /* platform specific USB_REQ_TX_DATA_CNT */ +#else +#if CFG_USB_TX_AGG +#define USB_REQ_TX_DATA_CNT (2) /* must be >= 2 */ +#else +#define USB_REQ_TX_DATA_CNT (CFG_TX_MAX_PKT_NUM) +#endif +#endif + +#define USB_REQ_TX_CMD_CNT (CFG_TX_MAX_CMD_PKT_NUM) +#define USB_REQ_RX_EVENT_CNT (1) +#ifdef CFG_USB_REQ_RX_DATA_CNT +#define USB_REQ_RX_DATA_CNT (CFG_USB_REQ_RX_DATA_CNT) /* platform specific USB_REQ_RX_DATA_CNT */ +#else +#define USB_REQ_RX_DATA_CNT (2) +#endif + +#define USB_RX_AGGREGTAION_LIMIT (32) /* Unit: K-bytes */ +#define USB_RX_AGGREGTAION_TIMEOUT (100) /* Unit: us */ +#define USB_RX_AGGREGTAION_PKT_LIMIT (30) + +#define USB_TX_CMD_BUF_SIZE (1600) +#if CFG_USB_TX_AGG +#define USB_TX_DATA_BUFF_SIZE (32*1024) +#else +#define USB_TX_DATA_BUF_SIZE (NIC_TX_DESC_AND_PADDING_LENGTH + NIC_TX_DESC_HEADER_PADDING_LENGTH + \ + NIC_TX_MAX_SIZE_PER_FRAME + LEN_USB_UDMA_TX_TERMINATOR) +#endif +#define USB_RX_EVENT_BUF_SIZE (CFG_RX_MAX_PKT_SIZE + 3 + LEN_USB_RX_PADDING_CSO + 4) +#define USB_RX_DATA_BUF_SIZE (CFG_RX_MAX_PKT_SIZE + \ + min(USB_RX_AGGREGTAION_LIMIT * 1024, \ + (USB_RX_AGGREGTAION_PKT_LIMIT * \ + (CFG_RX_MAX_PKT_SIZE + 3 + LEN_USB_RX_PADDING_CSO) + 4))) + +#define LEN_USB_UDMA_TX_TERMINATOR (4) /*HW design spec */ +#define LEN_USB_RX_PADDING_CSO (4) /*HW design spec */ + +#define USB_RX_EVENT_RFB_RSV_CNT (0) +#define USB_RX_DATA_RFB_RSV_CNT (4) + +#define DEVICE_VENDOR_REQUEST_IN (0xc0) +#define DEVICE_VENDOR_REQUEST_OUT (0x40) +#define VENDOR_TIMEOUT_MS (1000) +#define BULK_TIMEOUT_MS (1500) +#define INTERRUPT_TIMEOUT_MS (1000) +#define SW_RFB_RECHECK_MS (10) +#define SW_RFB_LOG_LIMIT_MS (5000) +#define SW_RFB_BLOCKING_LIMIT_MS (1000) + +/* Vendor Request */ +#define VND_REQ_POWER_ON_WIFI (0x4) +#define VND_REQ_REG_READ (0x63) +#define VND_REQ_REG_WRITE (0x66) +#define VND_REQ_FEATURE_SET (0x91) +#define FEATURE_SET_WVALUE_RESUME (0x5) +#define VND_REQ_BUF_SIZE (16) + +#define USB_TX_CMD_QUEUE_MASK (BITS(2, 4)) /* For H2CDMA Tx CMD mapping */ + +#define USB_DBDC1_TC (TC_NUM)/* for DBDC1 */ +#define USB_TC_NUM (TC_NUM + 1)/* for DBDC1 */ + +#define HIF_EXTRA_IO_BUFFER_SIZE (0) + +#define HIF_TX_COALESCING_BUFFER_SIZE (USB_TX_CMD_BUF_SIZE) +#define HIF_RX_COALESCING_BUFFER_SIZE (USB_RX_EVENT_BUF_SIZE) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/* host interface's private data structure, which is attached to os glue +** layer info structure. + */ + +enum usb_state { + USB_STATE_LINK_DOWN, + USB_STATE_LINK_UP, + USB_STATE_PRE_SUSPEND_DONE, + USB_STATE_PRE_SUSPEND_FAIL, + USB_STATE_SUSPEND, + USB_STATE_PRE_RESUME, + USB_STATE_WIFI_OFF /* Hif power off wifi */ +}; + +enum usb_submit_type { + SUBMIT_TYPE_TX_CMD, + SUBMIT_TYPE_TX_DATA, + SUBMIT_TYPE_RX_EVENT, + SUBMIT_TYPE_RX_DATA +}; + +typedef enum _EVENT_EP_TYPE { + EVENT_EP_TYPE_UNKONW, + EVENT_EP_TYPE_BULK, + EVENT_EP_TYPE_INTR, + EVENT_EP_TYPE_DATA_EP +} EVENT_EP_TYPE; + +typedef struct _BUF_CTRL_T { + UINT_8 *pucBuf; + UINT_32 u4BufSize; + UINT_32 u4WrIdx; + UINT_32 u4ReadSize; +} BUF_CTRL_T, *P_BUF_CTRL_T; + +typedef struct _GL_HIF_INFO_T { + struct usb_interface *intf; + struct usb_device *udev; + + P_GLUE_INFO_T prGlueInfo; + enum usb_state state; + + spinlock_t rTxDataQLock; + spinlock_t rTxCmdQLock; + spinlock_t rRxEventQLock; + spinlock_t rRxDataQLock; + spinlock_t rStateLock; + + PVOID prTxCmdReqHead; + PVOID arTxDataFfaReqHead; + PVOID arTxDataReqHead[USB_TC_NUM]; + PVOID prRxEventReqHead; + PVOID prRxDataReqHead; + struct list_head rTxCmdFreeQ; + spinlock_t rTxCmdFreeQLock; + struct list_head rTxCmdSendingQ; + spinlock_t rTxCmdSendingQLock; + struct list_head rTxDataFfaQ; +#if CFG_USB_TX_AGG + UINT_32 u4AggRsvSize[USB_TC_NUM]; + struct list_head rTxDataFreeQ[USB_TC_NUM]; + struct usb_anchor rTxDataAnchor[USB_TC_NUM]; +#else + struct list_head rTxDataFreeQ; + struct usb_anchor rTxDataAnchor; +#endif + /*spinlock_t rTxDataFreeQLock;*/ + struct list_head rRxEventFreeQ; + /*spinlock_t rRxEventFreeQLock;*/ + struct usb_anchor rRxEventAnchor; + struct list_head rRxDataFreeQ; + /*spinlock_t rRxDataFreeQLock;*/ + struct usb_anchor rRxDataAnchor; + struct list_head rRxEventCompleteQ; + /*spinlock_t rRxEventCompleteQLock;*/ + struct list_head rRxDataCompleteQ; + /*spinlock_t rRxDataCompleteQLock;*/ + struct list_head rTxCmdCompleteQ; + struct list_head rTxDataCompleteQ; + + BUF_CTRL_T rTxCmdBufCtrl[USB_REQ_TX_CMD_CNT]; + BUF_CTRL_T rTxDataFfaBufCtrl[USB_REQ_TX_DATA_FFA_CNT]; +#if CFG_USB_TX_AGG + BUF_CTRL_T rTxDataBufCtrl[USB_TC_NUM][USB_REQ_TX_DATA_CNT]; +#else + BUF_CTRL_T rTxDataBufCtrl[USB_REQ_TX_DATA_CNT]; +#endif + BUF_CTRL_T rRxEventBufCtrl[USB_REQ_RX_EVENT_CNT]; + BUF_CTRL_T rRxDataBufCtrl[USB_REQ_RX_DATA_CNT]; + + struct mutex vendor_req_sem; + void *vendor_req_buf; + UINT_32 vendor_req_buf_sz; + + BOOLEAN fgIntReadClear; + BOOLEAN fgMbxReadClear; + BOOLEAN fgEventEpDetected; + EVENT_EP_TYPE eEventEpType; +} GL_HIF_INFO_T, *P_GL_HIF_INFO_T; + +typedef struct _USB_REQ_T { + struct list_head list; + struct urb *prUrb; + P_BUF_CTRL_T prBufCtrl; + P_GL_HIF_INFO_T prHifInfo; + PVOID prPriv; + QUE_T rSendingDataMsduInfoList; +} USB_REQ_T, *P_USB_REQ_T; + +/* USB_REQ_T prPriv field for TxData */ +#define FFA_MASK BIT(7) /* Indicate if this UsbReq is from FFA queue. */ +#define TC_MASK BITS(0, 6) /* Indicate which TC this UsbReq belongs to */ + + +/******************************************************************************* +* P U B 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 USB_TRANS_MSDU_TC(_prMsduInfo) ((_prMsduInfo)->ucWmmQueSet ? USB_DBDC1_TC : (_prMsduInfo)->ucTC) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +VOID glUsbWlanRemove(VOID); + +WLAN_STATUS glRegisterBus(probe_card pfProbe, remove_card pfRemove); + +VOID glUnregisterBus(remove_card pfRemove); + +VOID glSetHifInfo(P_GLUE_INFO_T prGlueInfo, ULONG ulCookie); + +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); + +VOID glUdmaTxRxEnable(P_GLUE_INFO_T prGlueInfo, BOOLEAN enable); + +VOID glUdmaRxAggEnable(P_GLUE_INFO_T prGlueInfo, BOOLEAN enable); + +int mtk_usb_vendor_request(IN P_GLUE_INFO_T prGlueInfo, IN UCHAR uEndpointAddress, IN UCHAR RequestType, + IN UCHAR Request, IN UINT_16 Value, IN UINT_16 Index, IN PVOID TransferBuffer, + IN UINT_32 TransferBufferLength); + +VOID glUsbEnqueueReq(P_GL_HIF_INFO_T prHifInfo, struct list_head *prHead, P_USB_REQ_T prUsbReq, + spinlock_t *prLock, BOOLEAN fgHead); +P_USB_REQ_T glUsbDequeueReq(P_GL_HIF_INFO_T prHifInfo, struct list_head *prHead, spinlock_t *prLock); +BOOLEAN glUsbBorrowFfaReq(P_GL_HIF_INFO_T prHifInfo, UINT_8 ucTc); + +VOID glUsbSetState(P_GL_HIF_INFO_T prHifInfo, enum usb_state state); + +INT_32 glUsbSubmitUrb(P_GL_HIF_INFO_T prHifInfo, struct urb *urb, enum usb_submit_type type); + +WLAN_STATUS halTxUSBSendCmd(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucTc, IN P_CMD_INFO_T prCmdInfo); +VOID halTxUSBSendCmdComplete(struct urb *urb); +VOID halTxUSBProcessCmdComplete(IN P_ADAPTER_T prAdapter, P_USB_REQ_T prUsbReq); + +WLAN_STATUS halTxUSBSendData(IN P_GLUE_INFO_T prGlueInfo, IN P_MSDU_INFO_T prMsduInfo); +WLAN_STATUS halTxUSBKickData(IN P_GLUE_INFO_T prGlueInfo); +VOID halTxUSBSendDataComplete(struct urb *urb); +VOID halTxUSBProcessMsduDone(IN P_GLUE_INFO_T prGlueInfo, P_USB_REQ_T prUsbReq); +VOID halTxUSBProcessDataComplete(IN P_ADAPTER_T prAdapter, P_USB_REQ_T prUsbReq); + +UINT_32 halRxUSBEnqueueRFB(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuf, IN UINT_32 u4Length, + IN UINT_32 u4MinRfbCnt); +WLAN_STATUS halRxUSBReceiveEvent(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgFillUrb); +VOID halRxUSBReceiveEventComplete(struct urb *urb); +WLAN_STATUS halRxUSBReceiveData(IN P_ADAPTER_T prAdapter); +VOID halRxUSBReceiveDataComplete(struct urb *urb); +VOID halRxUSBProcessEventDataComplete(IN P_ADAPTER_T prAdapter, + struct list_head *prCompleteQ, struct list_head *prFreeQ, UINT_32 u4MinRfbCnt); + +VOID halUSBPreSuspendCmd(IN P_ADAPTER_T prAdapter); +VOID halUSBPreSuspendDone(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +VOID halUSBPreSuspendTimeout(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +void glGetDev(PVOID ctx, struct device **dev); +void glGetHifDev(P_GL_HIF_INFO_T prHif, struct device **dev); + +VOID halGetCompleteStatus(IN P_ADAPTER_T prAdapter, OUT PUINT_32 pu4IntStatus); + +UINT_16 glGetUsbDeviceVendorId(struct usb_device *dev); +UINT_16 glGetUsbDeviceProductId(struct usb_device *dev); + +INT_32 glGetUsbDeviceManufacturerName(struct usb_device *dev, UCHAR *buffer, UINT_32 bufLen); +INT_32 glGetUsbDeviceProductName(struct usb_device *dev, UCHAR *buffer, UINT_32 bufLen); +INT_32 glGetUsbDeviceSerialNumber(struct usb_device *dev, UCHAR *buffer, UINT_32 bufLen); + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _HIF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/usb/include/hif_usb.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/usb/include/hif_usb.h new file mode 100644 index 0000000000000..acb7ad32ad802 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/usb/include/hif_usb.h @@ -0,0 +1,131 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file "hif_usb.h" + * \brief + */ + + +#ifndef _HIF_USB_H +#define _HIF_USB_H +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#define HIF_USB_DEBUG (0) /* 0:turn off debug msg and assert, 1:turn off debug msg and assert */ + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + +/*! + * \brief A debug print used to print debug messages while compiler flag HIF_SDIO_DEBUG on. + * + */ +#if HIF_USB_DEBUG +#define DPRINTK(fmt, args...) pr_debug("%s: " fmt, __func__, ## args) +#else +#define DPRINTK(fmt, args...) +#endif + +/*! + * \brief ASSERT function definition. + * + */ +#if HIF_USB_DEBUG +#define ASSERT(expr) \ + do { \ + if (!(expr)) { \ + pr_err("assertion failed! %s[%d]: %s\n", \ + __func__, __LINE__, #expr); \ + WARN_ON(!(expr)); \ + } \ + } while (0) +#else +#define 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 +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _HIF_USB_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/usb/usb.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/usb/usb.c new file mode 100644 index 0000000000000..cc70310afdfa4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/hif/usb/usb.c @@ -0,0 +1,1693 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/****************************************************************************** +*[File] usb.c +*[Version] v1.0 +*[Revision Date] 2010-03-01 +*[Author] +*[Description] +* The program provides USB HIF driver +*[Copyright] +* Copyright (C) 2010 MediaTek Incorporation. All Rights Reserved. +******************************************************************************/ + + +/******************************************************************************* +* C O M P I L E 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 +#include + +#include +#ifndef CONFIG_X86 +#include +#endif + +#include "mt66xx_reg.h" +#include "cust_usb_id.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define HIF_USB_ERR_TITLE_STR "["CHIP_NAME"] USB Access Error!" +#define HIF_USB_ERR_DESC_STR "**USB Access Error**\n" + +#define HIF_USB_ACCESS_RETRY_LIMIT 1 + +#define MT_MAC_BASE 0x2 + +#define MTK_USB_PORT_MASK 0x0F +#define MTK_USB_BULK_IN_MIN_EP 4 +#define MTK_USB_BULK_IN_MAX_EP 5 +#define MTK_USB_BULK_OUT_MIN_EP 4 +#define MTK_USB_BULK_OUT_MAX_EP 9 + +static const struct usb_device_id mtk_usb_ids[] = { + /* {USB_DEVICE(0x0E8D,0x6632), .driver_info = MT_MAC_BASE}, */ + { USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x6632, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&mt66xx_driver_data_mt6632}, + { USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x7666, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&mt66xx_driver_data_mt6632}, + { USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x7668, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&mt66xx_driver_data_mt7668}, + /* If customer usb id is presented, add to the table. */ + CUST_USB_ID_TABLES + { /* end: all zeroes */ }, +}; + +MODULE_DEVICE_TABLE(usb, mtk_usb_ids); + +#if CFG_USB_TX_AGG +/* TODO */ +const UINT_32 USB_TX_DATA_BUF_SIZE[TC_NUM] = { NIC_TX_PAGE_COUNT_TC0 / (USB_REQ_TX_DATA_CNT - 1), + NIC_TX_PAGE_COUNT_TC1 / (USB_REQ_TX_DATA_CNT - 1), + NIC_TX_PAGE_COUNT_TC2 / (USB_REQ_TX_DATA_CNT - 1), + NIC_TX_PAGE_COUNT_TC3 / (USB_REQ_TX_DATA_CNT - 1), + NIC_TX_PAGE_COUNT_TC4 / (USB_REQ_TX_DATA_CNT - 1), + NIC_TX_PAGE_COUNT_TC5 / (USB_REQ_TX_DATA_CNT - 1), +}; +#endif + +/******************************************************************************* +* 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 probe_card pfWlanProbe; +static remove_card pfWlanRemove; + +static BOOLEAN g_fgDriverProbed = FALSE; + +static struct usb_driver mtk_usb_driver = { + .name = "wlan", /* "MTK USB WLAN Driver" */ + .id_table = mtk_usb_ids, + .probe = NULL, + .disconnect = NULL, + .suspend = NULL, + .resume = NULL, + .reset_resume = NULL, + .supports_autosuspend = 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 +******************************************************************************** +*/ +static int mtk_usb_probe(struct usb_interface *intf, const struct usb_device_id *id); +static void mtk_usb_disconnect(struct usb_interface *intf); +static int mtk_usb_suspend(struct usb_interface *intf, pm_message_t message); +static int mtk_usb_resume(struct usb_interface *intf); +static int mtk_usb_reset_resume(struct usb_interface *intf); +static int mtk_usb_bulk_in_msg(IN P_GL_HIF_INFO_T prHifInfo, IN UINT_32 len, OUT UCHAR * buffer, int InEp); +static int mtk_usb_intr_in_msg(IN P_GL_HIF_INFO_T prHifInfo, IN UINT_32 len, OUT UCHAR * buffer, int InEp); +static int mtk_usb_bulk_out_msg(IN P_GL_HIF_INFO_T prHifInfo, IN UINT_32 len, IN UCHAR * buffer, int OutEp); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a USB probe function +* +* \param[in] intf USB interface +* \param[in] id USB device id +* +* \return void +*/ +/*----------------------------------------------------------------------------*/ +static int mtk_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + int ret = 0; + struct usb_device *dev; + + DBGLOG(HAL, EVENT, "mtk_usb_probe()\n"); + + ASSERT(intf); + ASSERT(id); + + dev = interface_to_usbdev(intf); + dev = usb_get_dev(dev); + + /* Prevent un-expected usb operation */ + if (g_fgDriverProbed) { + DBGLOG(HAL, ERROR, "wlan_probe(): Device already probed!!\n"); + return -EBUSY; + } + + DBGLOG(HAL, EVENT, "wlan_probe()\n"); + if (pfWlanProbe((PVOID) intf, (PVOID) id->driver_info) != WLAN_STATUS_SUCCESS) { + /* printk(KERN_WARNING DRV_NAME"pfWlanProbe fail!call pfWlanRemove()\n"); */ + pfWlanRemove(); + DBGLOG(HAL, ERROR, "wlan_probe() failed\n"); + ret = -1; + } else { + g_fgDriverProbed = TRUE; + } + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a USB remove function +* +* \param[in] intf USB interface +* +* \return void +*/ +/*----------------------------------------------------------------------------*/ +static void mtk_usb_disconnect(struct usb_interface *intf) +{ + P_GLUE_INFO_T prGlueInfo; + + DBGLOG(HAL, STATE, "mtk_usb_disconnect()\n"); + + ASSERT(intf); + prGlueInfo = (P_GLUE_INFO_T)usb_get_intfdata(intf); + if (prGlueInfo) { + glUsbSetState(&prGlueInfo->rHifInfo, USB_STATE_LINK_DOWN); + usb_set_intfdata(intf, NULL); + } else + DBGLOG(HAL, ERROR, "prGlueInfo is NULL!!\n"); + + glUsbWlanRemove(); + + usb_put_dev(interface_to_usbdev(intf)); + + DBGLOG(HAL, STATE, "mtk_usb_disconnect() done\n"); +} + +static int mtk_usb_suspend(struct usb_interface *intf, pm_message_t message) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)usb_get_intfdata(intf); + ADAPTER_T *prAdapter; + P_AIS_FSM_INFO_T prAisFsmInfo = NULL; + UINT_8 count = 1; + UINT_8 ret = 0; + + DBGLOG(HAL, STATE, "mtk_usb_suspend()\n"); + + /* clear ongoing scan */ + prAdapter = prGlueInfo->prAdapter; + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + while (prAisFsmInfo->eCurrentState != AIS_STATE_NORMAL_TR + && prAisFsmInfo->eCurrentState != AIS_STATE_IDLE) { + DBGLOG(REQ, STATE, "AIS(%d) await count(%d)!\n", + prAisFsmInfo->eCurrentState, count); + + if (++count > 20) { + DBGLOG(REQ, WARN, "AIS await idle timeout!!!\n"); + break; + } + + if (prAisFsmInfo->eCurrentState == AIS_STATE_ONLINE_SCAN + || prAisFsmInfo->eCurrentState == AIS_STATE_LOOKING_FOR + || prAisFsmInfo->eCurrentState == AIS_STATE_SCAN) { + DBGLOG(REQ, STATE, "AIS is scanning, do abort\n"); + aisFsmStateAbort_SCAN(prAdapter); + kalMsleep(200); + continue; + } + kalMsleep(25); + } + count = 0; + + wlanSuspendPmHandle(prGlueInfo); + + halUSBPreSuspendCmd(prGlueInfo->prAdapter); + + while (prGlueInfo->rHifInfo.state != USB_STATE_PRE_SUSPEND_DONE) { + if (count > 25) { + DBGLOG(HAL, ERROR, + "pre_suspend timeout, return -ETIME in the end\n"); + ret = -ETIME; + break; + } + msleep(20); + count++; + } + + glUsbSetState(&prGlueInfo->rHifInfo, USB_STATE_SUSPEND); + halDisableInterrupt(prGlueInfo->prAdapter); + halTxCancelAllSending(prGlueInfo->prAdapter); + + DBGLOG(HAL, STATE, "mtk_usb_suspend() done!\n"); + + if (ret && PMSG_IS_AUTO(message)) + mtk_usb_resume(intf); + + return ret; +} + +static int mtk_usb_resume(struct usb_interface *intf) +{ + int ret = 0; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)usb_get_intfdata(intf); + + DBGLOG(HAL, STATE, "mtk_usb_resume()\n"); + if (!prGlueInfo) { + DBGLOG(HAL, ERROR, "prGlueInfo is NULL!\n"); + return -EFAULT; + } + + /* NOTE: USB bus may not really do suspend and resume*/ + ret = usb_control_msg(prGlueInfo->rHifInfo.udev, + usb_sndctrlpipe(prGlueInfo->rHifInfo.udev, 0), VND_REQ_FEATURE_SET, + DEVICE_VENDOR_REQUEST_OUT, FEATURE_SET_WVALUE_RESUME, 0, NULL, 0, + VENDOR_TIMEOUT_MS); + if (ret) + DBGLOG(HAL, ERROR, "VendorRequest FeatureSetResume ERROR: %x\n", (unsigned int)ret); + + glUsbSetState(&prGlueInfo->rHifInfo, USB_STATE_PRE_RESUME); + /* To trigger CR4 path */ + wlanSendDummyCmd(prGlueInfo->prAdapter, FALSE); + + glUsbSetState(&prGlueInfo->rHifInfo, USB_STATE_LINK_UP); + halEnableInterrupt(prGlueInfo->prAdapter); + + wlanResumePmHandle(prGlueInfo); + + DBGLOG(HAL, STATE, "mtk_usb_resume() done!\n"); + + /* TODO */ + return 0; +} + +static int mtk_usb_reset_resume(struct usb_interface *intf) +{ + DBGLOG(HAL, STATE, "mtk_usb_reset_resume()\n"); + + mtk_usb_resume(intf); + + DBGLOG(HAL, STATE, "mtk_usb_reset_resume done!()\n"); + + /* TODO */ + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief USB EP0 vendor request +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] uEndpointAddress +* \param[in] RequestType +* \param[in] Request +* \param[in] Value +* \param[in] Index +* \param[in] TransferBuffer +* \param[in] TransferBufferLength +* +* \retval 0 if success +* non-zero if fail, the return value of usb_control_msg() +*/ +/*----------------------------------------------------------------------------*/ +int mtk_usb_vendor_request(IN P_GLUE_INFO_T prGlueInfo, IN UCHAR uEndpointAddress, IN UCHAR RequestType, + IN UCHAR Request, IN UINT_16 Value, IN UINT_16 Index, IN PVOID TransferBuffer, + IN UINT_32 TransferBufferLength) +{ + P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; + void *xfer_buf; + /* refer to RTUSB_VendorRequest */ + int ret = 0; + + /* TODO: semaphore */ + + if (in_interrupt()) { + DBGLOG(REQ, ERROR, "BUG: mtk_usb_vendor_request is called from invalid context\n"); + return -EFAULT; + } + + if (unlikely(TransferBufferLength > prHifInfo->vendor_req_buf_sz)) { + DBGLOG(REQ, ERROR, "len %u exceeds limit %zu\n", TransferBufferLength, + prHifInfo->vendor_req_buf_sz); + return -E2BIG; + } + + if (unlikely(TransferBuffer && !prHifInfo->vendor_req_buf)) { + DBGLOG(REQ, ERROR, "NULL vendor_req_buf\n"); + return -EFAULT; + } + + /* use heap instead of old stack memory */ + xfer_buf = (TransferBuffer) ? prHifInfo->vendor_req_buf : NULL; + + mutex_lock(&prHifInfo->vendor_req_sem); + + if (RequestType == DEVICE_VENDOR_REQUEST_OUT) { + if (xfer_buf) + memcpy(xfer_buf, TransferBuffer, TransferBufferLength); + ret = usb_control_msg(prHifInfo->udev, + usb_sndctrlpipe(prHifInfo->udev, uEndpointAddress), + Request, RequestType, Value, Index, + xfer_buf, TransferBufferLength, + VENDOR_TIMEOUT_MS); + } else if (RequestType == DEVICE_VENDOR_REQUEST_IN) { + ret = usb_control_msg(prHifInfo->udev, + usb_rcvctrlpipe(prHifInfo->udev, uEndpointAddress), + Request, RequestType, Value, Index, + xfer_buf, TransferBufferLength, + VENDOR_TIMEOUT_MS); + if (xfer_buf && (ret > 0)) + memcpy(TransferBuffer, xfer_buf, TransferBufferLength); + } + mutex_unlock(&prHifInfo->vendor_req_sem); + + return (ret == TransferBufferLength) ? 0 : ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief USB Bulk IN msg +* +* \param[in] prHifInfo Pointer to the GL_HIF_INFO_T structure +* \param[in] len +* \param[in] buffer +* \param[in] InEp +* +* \retval +*/ +/*----------------------------------------------------------------------------*/ +static int mtk_usb_bulk_in_msg(IN P_GL_HIF_INFO_T prHifInfo, IN UINT_32 len, OUT UCHAR *buffer, int InEp) +{ + int ret = 0; + UINT_32 count; + + if (in_interrupt()) { + DBGLOG(REQ, ERROR, "BUG: mtk_usb_bulk_in_msg is called from invalid context\n"); + return FALSE; + } + + mutex_lock(&prHifInfo->vendor_req_sem); + + /* do a blocking bulk read to get data from the device */ + ret = usb_bulk_msg(prHifInfo->udev, + usb_rcvbulkpipe(prHifInfo->udev, InEp), buffer, len, &count, BULK_TIMEOUT_MS); + + mutex_unlock(&prHifInfo->vendor_req_sem); + + if (ret >= 0) { +#if 0 /* maximize buff len for usb in */ + if (count != len) { + DBGLOG(HAL, WARN, "usb_bulk_msg(IN=%d) Warning. Data is not completed. (receive %d/%u)\n", + InEp, count, len); + } +#endif + return count; + } + + DBGLOG(HAL, ERROR, "usb_bulk_msg(IN=%d) Fail. Error code = %d.\n", InEp, ret); + return ret; +} + +static int mtk_usb_intr_in_msg(IN P_GL_HIF_INFO_T prHifInfo, IN UINT_32 len, OUT UCHAR *buffer, int InEp) +{ + int ret = 0; + UINT_32 count; + + if (in_interrupt()) { + DBGLOG(REQ, ERROR, "BUG: mtk_usb_intr_in_msg is called from invalid context\n"); + return FALSE; + } + + mutex_lock(&prHifInfo->vendor_req_sem); + + /* do a blocking interrupt read to get data from the device */ + ret = usb_interrupt_msg(prHifInfo->udev, + usb_rcvintpipe(prHifInfo->udev, InEp), buffer, len, &count, INTERRUPT_TIMEOUT_MS); + + mutex_unlock(&prHifInfo->vendor_req_sem); + + if (ret >= 0) { +#if 0 /* maximize buff len for usb in */ + if (count != len) { + DBGLOG(HAL, WARN, "usb_interrupt_msg(IN=%d) Warning. Data is not completed. (receive %d/%u)\n", + InEp, count, len); + } +#endif + return count; + } + + DBGLOG(HAL, ERROR, "usb_interrupt_msg(IN=%d) Fail. Error code = %d.\n", InEp, ret); + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief USB Bulk OUT msg +* +* \param[in] prHifInfo Pointer to the GL_HIF_INFO_T structure +* \param[in] len +* \param[in] buffer +* \param[in] OutEp +* +* \retval +*/ +/*----------------------------------------------------------------------------*/ +static int mtk_usb_bulk_out_msg(IN P_GL_HIF_INFO_T prHifInfo, IN UINT_32 len, IN UCHAR *buffer, int OutEp) +{ + int ret = 0; + UINT_32 count; + + if (in_interrupt()) { + DBGLOG(REQ, ERROR, "BUG: mtk_usb_bulk_out_msg is called from invalid context\n"); + return FALSE; + } + + mutex_lock(&prHifInfo->vendor_req_sem); + + /* do a blocking bulk read to get data from the device */ + ret = usb_bulk_msg(prHifInfo->udev, + usb_sndbulkpipe(prHifInfo->udev, OutEp), buffer, len, &count, BULK_TIMEOUT_MS); + + mutex_unlock(&prHifInfo->vendor_req_sem); + + if (ret >= 0) { +#if 0 + if (count != len) { + DBGLOG(HAL, ERROR, "usb_bulk_msg(OUT=%d) Warning. Data is not completed. (send %d/%u)\n", OutEp, + count, len); + } +#endif + return count; + } + + DBGLOG(HAL, ERROR, "usb_bulk_msg(OUT=%d) Fail. Error code = %d.\n", OutEp, ret); + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is wlan remove wrapper for different caller +* +* \param[in] (none) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glUsbWlanRemove(VOID) +{ + if (g_fgDriverProbed) { + g_fgDriverProbed = FALSE; + pfWlanRemove(); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will register USB 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 USB bus +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS glRegisterBus(probe_card pfProbe, remove_card pfRemove) +{ + int ret = 0; + + ASSERT(pfProbe); + ASSERT(pfRemove); + + pfWlanProbe = pfProbe; + pfWlanRemove = pfRemove; + + mtk_usb_driver.probe = mtk_usb_probe; + mtk_usb_driver.disconnect = mtk_usb_disconnect; + mtk_usb_driver.suspend = mtk_usb_suspend; + mtk_usb_driver.resume = mtk_usb_resume; + mtk_usb_driver.reset_resume = mtk_usb_reset_resume; + mtk_usb_driver.supports_autosuspend = 1; + + ret = (usb_register(&mtk_usb_driver) == 0) ? WLAN_STATUS_SUCCESS : WLAN_STATUS_FAILURE; + + return ret; +} /* end of glRegisterBus() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will unregister USB bus to the os +* +* \param[in] pfRemove Function pointer to remove card +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glUnregisterBus(remove_card pfRemove) +{ + glUsbWlanRemove(); + usb_deregister(&mtk_usb_driver); +} /* end of glUnregisterBus() */ + +VOID glUdmaTxRxEnable(P_GLUE_INFO_T prGlueInfo, BOOLEAN enable) +{ + UINT_32 u4Value = 0; + + kalDevRegRead(prGlueInfo, UDMA_WLCFG_0, &u4Value); + + /* enable UDMA TX & RX */ + if (enable) + u4Value |= UDMA_WLCFG_0_TX_EN(1) | UDMA_WLCFG_0_RX_EN(1) | UDMA_WLCFG_0_RX_MPSZ_PAD0(1); + else + u4Value &= ~(UDMA_WLCFG_0_TX_EN(1) | UDMA_WLCFG_0_RX_EN(1)); + + kalDevRegWrite(prGlueInfo, UDMA_WLCFG_0, u4Value); +} + +VOID glUdmaRxAggEnable(P_GLUE_INFO_T prGlueInfo, BOOLEAN enable) +{ + UINT_32 u4Value = 0; + + if (enable) { + kalDevRegRead(prGlueInfo, UDMA_WLCFG_0, &u4Value); + /* enable UDMA TX & RX */ + u4Value &= ~(UDMA_WLCFG_0_RX_AGG_EN_MASK | + UDMA_WLCFG_0_RX_AGG_LMT_MASK | + UDMA_WLCFG_0_RX_AGG_TO_MASK); + u4Value |= UDMA_WLCFG_0_RX_AGG_EN(1) | + UDMA_WLCFG_0_RX_AGG_LMT(USB_RX_AGGREGTAION_LIMIT) | + UDMA_WLCFG_0_RX_AGG_TO(USB_RX_AGGREGTAION_TIMEOUT); + kalDevRegWrite(prGlueInfo, UDMA_WLCFG_0, u4Value); + + kalDevRegRead(prGlueInfo, UDMA_WLCFG_1, &u4Value); + u4Value &= ~UDMA_WLCFG_1_RX_AGG_PKT_LMT_MASK; + u4Value |= UDMA_WLCFG_1_RX_AGG_PKT_LMT(USB_RX_AGGREGTAION_PKT_LIMIT); + kalDevRegWrite(prGlueInfo, UDMA_WLCFG_1, u4Value); + } else { + kalDevRegRead(prGlueInfo, UDMA_WLCFG_0, &u4Value); + u4Value &= ~UDMA_WLCFG_0_RX_AGG_EN(1); + kalDevRegWrite(prGlueInfo, UDMA_WLCFG_0, u4Value); + } +} + +PVOID glUsbInitQ(P_GL_HIF_INFO_T prHifInfo, struct list_head *prHead, UINT_32 u4Cnt) +{ + UINT_32 i; + P_USB_REQ_T prUsbReqs, prUsbReq; + + INIT_LIST_HEAD(prHead); + + prUsbReqs = kcalloc(u4Cnt, sizeof(struct _USB_REQ_T), GFP_ATOMIC); + if (!prUsbReqs) { + DBGLOG(HAL, ERROR, "kcalloc fail!\n"); + return NULL; + } + prUsbReq = prUsbReqs; + + for (i = 0; i < u4Cnt; ++i) { + prUsbReq->prHifInfo = prHifInfo; + prUsbReq->prUrb = usb_alloc_urb(0, GFP_ATOMIC); + + if (prUsbReq->prUrb == NULL) + DBGLOG(HAL, ERROR, "usb_alloc_urb() reports error\n"); + + prUsbReq->prBufCtrl = NULL; + + INIT_LIST_HEAD(&prUsbReq->list); + list_add_tail(&prUsbReq->list, prHead); + + prUsbReq++; + } + + return (PVOID) prUsbReqs; +} + +void glUsbUnInitQ(struct list_head *prHead) +{ + P_USB_REQ_T prUsbReq, prUsbReqNext; + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, prHead, list) { + usb_free_urb(prUsbReq->prUrb); + list_del_init(&prUsbReq->list); + } +} + +VOID glUsbEnqueueReq(P_GL_HIF_INFO_T prHifInfo, struct list_head *prHead, P_USB_REQ_T prUsbReq, spinlock_t *prLock, + BOOLEAN fgHead) +{ + unsigned long flags; + P_USB_REQ_T prUsbReqCur, prUsbReqTmp; + + spin_lock_irqsave(prLock, flags); + + /* check for repeated prUsbReq */ + if (&prHifInfo->rRxDataFreeQ == prHead) { + list_for_each_entry_safe(prUsbReqCur, + prUsbReqTmp, prHead, list) { + if (&prUsbReq->list == &prUsbReqCur->list) { + DBGLOG(HAL, ERROR, + "error: try to insert existed prUsbReq!!\n"); + spin_unlock_irqrestore(prLock, flags); + return; + } + } + } + + if (fgHead) + list_add(&prUsbReq->list, prHead); + else + list_add_tail(&prUsbReq->list, prHead); + spin_unlock_irqrestore(prLock, flags); +} + +P_USB_REQ_T glUsbDequeueReq(P_GL_HIF_INFO_T prHifInfo, struct list_head *prHead, spinlock_t *prLock) +{ + P_USB_REQ_T prUsbReq; + unsigned long flags; + + spin_lock_irqsave(prLock, flags); + if (list_empty(prHead) || (prHead->next == NULL)) { + spin_unlock_irqrestore(prLock, flags); + return NULL; + } + prUsbReq = list_entry(prHead->next, struct _USB_REQ_T, list); + + /* prHead->next->next == NULL, error happen */ + if ((&prHifInfo->rRxDataFreeQ == prHead) && + (prHead->next->next == NULL)) { + /* Fatal error happen, ring list interrupt */ + DBGLOG(HAL, ERROR, + "Fatal error: rRxDataFreeQ ring list break!!\n"); + /* Try to resume*/ + INIT_LIST_HEAD(prHead); + INIT_LIST_HEAD(&prUsbReq->list); + list_add_tail(&prUsbReq->list, prHead); + spin_unlock_irqrestore(prLock, flags); + return NULL; + } + + list_del_init(prHead->next); + spin_unlock_irqrestore(prLock, flags); + + return prUsbReq; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function borrow UsbReq from Tx data FFA queue to the spcified TC Tx data free queue +* +* \param[in] prHifInfo Pointer to the GL_HIF_INFO_T structure +* \param[in] ucTc Specify TC index +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN glUsbBorrowFfaReq(P_GL_HIF_INFO_T prHifInfo, UINT_8 ucTc) +{ + P_USB_REQ_T prUsbReq; + + if (list_empty(&prHifInfo->rTxDataFfaQ)) + return FALSE; + prUsbReq = list_entry(prHifInfo->rTxDataFfaQ.next, struct _USB_REQ_T, list); + list_del_init(prHifInfo->rTxDataFfaQ.next); + + *((PUINT_8)&prUsbReq->prPriv) = FFA_MASK | ucTc; + list_add_tail(&prUsbReq->list, &prHifInfo->rTxDataFreeQ[ucTc]); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function set USB state +* +* \param[in] prHifInfo Pointer to the GL_HIF_INFO_T structure +* \param[in] state Specify TC index +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +VOID glUsbSetState(P_GL_HIF_INFO_T prHifInfo, enum usb_state state) +{ + unsigned long flags; + + spin_lock_irqsave(&prHifInfo->rStateLock, flags); + prHifInfo->state = state; + spin_unlock_irqrestore(&prHifInfo->rStateLock, flags); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a wrapper of submit urb to ensure driver can transmit +* WiFi packet when WiFi path of device is allowed. +* +* \param[in] prHifInfo Pointer to the GL_HIF_INFO_T structure +* \param[in] type Specify submit type +* +* \retval 0 Successful submissions. +* \retval negative Error number. +*/ +/*----------------------------------------------------------------------------*/ +INT_32 glUsbSubmitUrb(P_GL_HIF_INFO_T prHifInfo, struct urb *urb, enum usb_submit_type type) +{ + unsigned long flags; + int ret = 0; + + if (type == SUBMIT_TYPE_RX_EVENT || type == SUBMIT_TYPE_RX_DATA) + return usb_submit_urb(urb, GFP_ATOMIC); + + spin_lock_irqsave(&prHifInfo->rStateLock, flags); + if (type == SUBMIT_TYPE_TX_CMD) { + if (!(prHifInfo->state == USB_STATE_LINK_UP || prHifInfo->state == USB_STATE_PRE_RESUME)) { + spin_unlock_irqrestore(&prHifInfo->rStateLock, flags); + DBGLOG(HAL, INFO, "WiFi path is not allowed to transmit CMD packet. (%d)\n", prHifInfo->state); + return -ESHUTDOWN; + } + } else if (type == SUBMIT_TYPE_TX_DATA) { + if (prHifInfo->state != USB_STATE_LINK_UP) { + spin_unlock_irqrestore(&prHifInfo->rStateLock, flags); + DBGLOG(HAL, INFO, "WiFi path is not allowed to transmit DATA packet. (%d)\n", prHifInfo->state); + return -ESHUTDOWN; + } + } + ret = usb_submit_urb(urb, GFP_ATOMIC); + spin_unlock_irqrestore(&prHifInfo->rStateLock, flags); + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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, ULONG ulCookie) +{ + struct usb_host_interface *alts; + struct usb_host_endpoint *ep; + struct usb_endpoint_descriptor *ep_desc; + P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; + P_USB_REQ_T prUsbReq, prUsbReqNext; + UINT_32 i; +#if CFG_USB_TX_AGG + UINT_8 ucTc; +#endif + + prHifInfo->eEventEpType = USB_EVENT_TYPE; + prHifInfo->fgEventEpDetected = FALSE; + + prHifInfo->intf = (struct usb_interface *)ulCookie; + prHifInfo->udev = interface_to_usbdev(prHifInfo->intf); + + alts = prHifInfo->intf->cur_altsetting; + DBGLOG(HAL, STATE, "USB Device speed: %x [%u]\n", + prHifInfo->udev->speed, alts->endpoint[0].desc.wMaxPacketSize); + + if (prHifInfo->eEventEpType == EVENT_EP_TYPE_UNKONW) { + for (i = 0; i < alts->desc.bNumEndpoints; ++i) { + ep = &alts->endpoint[i]; + if (ep->desc.bEndpointAddress == USB_EVENT_EP_IN) { + ep_desc = &alts->endpoint[i].desc; + switch (ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + case USB_ENDPOINT_XFER_INT: + prHifInfo->eEventEpType = EVENT_EP_TYPE_INTR; + break; + case USB_ENDPOINT_XFER_BULK: + default: + prHifInfo->eEventEpType = EVENT_EP_TYPE_BULK; + break; + } + } + } + } + ASSERT(prHifInfo->eEventEpType != EVENT_EP_TYPE_UNKONW); + DBGLOG(HAL, INFO, "Event EP Type: %x\n", prHifInfo->eEventEpType); + + prHifInfo->prGlueInfo = prGlueInfo; + usb_set_intfdata(prHifInfo->intf, prGlueInfo); + + SET_NETDEV_DEV(prGlueInfo->prDevHandler, &prHifInfo->udev->dev); + + spin_lock_init(&prHifInfo->rTxCmdQLock); + spin_lock_init(&prHifInfo->rTxDataQLock); + spin_lock_init(&prHifInfo->rRxEventQLock); + spin_lock_init(&prHifInfo->rRxDataQLock); + spin_lock_init(&prHifInfo->rStateLock); + + mutex_init(&prHifInfo->vendor_req_sem); + prHifInfo->vendor_req_buf = kzalloc(VND_REQ_BUF_SIZE, GFP_KERNEL); + if (!prHifInfo->vendor_req_buf) { + DBGLOG(HAL, ERROR, "kzalloc vendor_req_buf %zu error\n", + VND_REQ_BUF_SIZE); + goto error; + } + prHifInfo->vendor_req_buf_sz = VND_REQ_BUF_SIZE; + +#if CFG_USB_TX_AGG + for (ucTc = 0; ucTc < USB_TC_NUM; ++ucTc) { + prHifInfo->u4AggRsvSize[ucTc] = 0; + init_usb_anchor(&prHifInfo->rTxDataAnchor[ucTc]); + } +#else + init_usb_anchor(&prHifInfo->rTxDataAnchor); +#endif + init_usb_anchor(&prHifInfo->rRxDataAnchor); + init_usb_anchor(&prHifInfo->rRxEventAnchor); + + /* TX CMD */ + prHifInfo->prTxCmdReqHead = glUsbInitQ(prHifInfo, &prHifInfo->rTxCmdFreeQ, USB_REQ_TX_CMD_CNT); + prUsbReq = list_entry(prHifInfo->rTxCmdFreeQ.next, struct _USB_REQ_T, list); + i = 0; + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxCmdFreeQ, list) { + prUsbReq->prBufCtrl = &prHifInfo->rTxCmdBufCtrl[i]; +#if CFG_USB_CONSISTENT_DMA + prUsbReq->prBufCtrl->pucBuf = usb_alloc_coherent(prHifInfo->udev, USB_TX_CMD_BUF_SIZE, GFP_ATOMIC, + &prUsbReq->prUrb->transfer_dma); +#else +#ifdef CFG_PREALLOC_MEMORY + prUsbReq->prBufCtrl->pucBuf = preallocGetMem(MEM_ID_TX_CMD); +#else + prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_TX_CMD_BUF_SIZE, GFP_ATOMIC); +#endif +#endif + if (prUsbReq->prBufCtrl->pucBuf == NULL) { + DBGLOG(HAL, ERROR, "kmalloc() reports error\n"); + goto error; + } + prUsbReq->prBufCtrl->u4BufSize = USB_TX_CMD_BUF_SIZE; + ++i; + } + + glUsbInitQ(prHifInfo, &prHifInfo->rTxCmdSendingQ, 0); + + /* TX Data FFA */ + prHifInfo->arTxDataFfaReqHead = glUsbInitQ(prHifInfo, + &prHifInfo->rTxDataFfaQ, USB_REQ_TX_DATA_FFA_CNT); + i = 0; + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxDataFfaQ, list) { + QUEUE_INITIALIZE(&prUsbReq->rSendingDataMsduInfoList); + *((PUINT_8)&prUsbReq->prPriv) = FFA_MASK; + prUsbReq->prBufCtrl = &prHifInfo->rTxDataFfaBufCtrl[i]; +#if CFG_USB_CONSISTENT_DMA + prUsbReq->prBufCtrl->pucBuf = + usb_alloc_coherent(prHifInfo->udev, USB_TX_DATA_BUFF_SIZE, GFP_ATOMIC, + &prUsbReq->prUrb->transfer_dma); +#else +#ifdef CFG_PREALLOC_MEMORY + prUsbReq->prBufCtrl->pucBuf = preallocGetMem(MEM_ID_TX_DATA_FFA); +#else + prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_TX_DATA_BUFF_SIZE, GFP_ATOMIC); +#endif +#endif + if (prUsbReq->prBufCtrl->pucBuf == NULL) { + DBGLOG(HAL, ERROR, "kmalloc() reports error\n"); + goto error; + } + prUsbReq->prBufCtrl->u4BufSize = USB_TX_DATA_BUFF_SIZE; + prUsbReq->prBufCtrl->u4WrIdx = 0; + ++i; + } + + /* TX Data */ +#if CFG_USB_TX_AGG + for (ucTc = 0; ucTc < USB_TC_NUM; ++ucTc) { + /* Only for TC0 ~ TC3 and DBDC1_TC */ + if (ucTc >= TC4_INDEX && ucTc < USB_DBDC1_TC) + continue; + prHifInfo->arTxDataReqHead[ucTc] = glUsbInitQ(prHifInfo, + &prHifInfo->rTxDataFreeQ[ucTc], USB_REQ_TX_DATA_CNT); + i = 0; + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxDataFreeQ[ucTc], list) { + QUEUE_INITIALIZE(&prUsbReq->rSendingDataMsduInfoList); + /* TODO: every endpoint should has an unique and only TC */ + *((PUINT_8)&prUsbReq->prPriv) = ucTc; + prUsbReq->prBufCtrl = &prHifInfo->rTxDataBufCtrl[ucTc][i]; +#if CFG_USB_CONSISTENT_DMA + prUsbReq->prBufCtrl->pucBuf = + usb_alloc_coherent(prHifInfo->udev, USB_TX_DATA_BUFF_SIZE, GFP_ATOMIC, + &prUsbReq->prUrb->transfer_dma); +#else +#ifdef CFG_PREALLOC_MEMORY + prUsbReq->prBufCtrl->pucBuf = preallocGetMem(MEM_ID_TX_DATA); +#else + prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_TX_DATA_BUFF_SIZE, GFP_ATOMIC); +#endif +#endif + if (prUsbReq->prBufCtrl->pucBuf == NULL) { + DBGLOG(HAL, ERROR, "kmalloc() reports error\n"); + goto error; + } + prUsbReq->prBufCtrl->u4BufSize = USB_TX_DATA_BUFF_SIZE; + prUsbReq->prBufCtrl->u4WrIdx = 0; + ++i; + } + + DBGLOG(INIT, INFO, "USB Tx URB INIT Tc[%u] cnt[%u] len[%u]\n", ucTc, i, + prHifInfo->rTxDataBufCtrl[ucTc][0].u4BufSize); + } +#else + glUsbInitQ(prHifInfo, &prHifInfo->rTxDataFreeQ, USB_REQ_TX_DATA_CNT); + prUsbReq = list_entry(prHifInfo->rTxDataFreeQ.next, struct _USB_REQ_T, list); + i = 0; + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxDataFreeQ, list) { + QUEUE_INITIALIZE(&prUsbReq->rSendingDataMsduInfoList); + prUsbReq->prBufCtrl = &prHifInfo->rTxDataBufCtrl[i]; +#if CFG_USB_CONSISTENT_DMA + prUsbReq->prBufCtrl->pucBuf = + usb_alloc_coherent(prHifInfo->udev, USB_TX_DATA_BUF_SIZE, GFP_ATOMIC, + &prUsbReq->prUrb->transfer_dma); +#else +#ifdef CFG_PREALLOC_MEMORY + prUsbReq->prBufCtrl->pucBuf = preallocGetMem(MEM_ID_TX_DATA); +#else + prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_TX_DATA_BUF_SIZE, GFP_ATOMIC); +#endif +#endif + if (prUsbReq->prBufCtrl->pucBuf == NULL) { + DBGLOG(HAL, ERROR, "kmalloc() reports error\n"); + goto error; + } + prUsbReq->prBufCtrl->u4BufSize = USB_TX_DATA_BUF_SIZE; + ++i; + } +#endif + + glUsbInitQ(prHifInfo, &prHifInfo->rTxCmdCompleteQ, 0); + glUsbInitQ(prHifInfo, &prHifInfo->rTxDataCompleteQ, 0); + + /* RX EVENT */ + prHifInfo->prRxEventReqHead = glUsbInitQ(prHifInfo, &prHifInfo->rRxEventFreeQ, USB_REQ_RX_EVENT_CNT); + i = 0; + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxEventFreeQ, list) { + prUsbReq->prBufCtrl = &prHifInfo->rRxEventBufCtrl[i]; +#ifdef CFG_PREALLOC_MEMORY + prUsbReq->prBufCtrl->pucBuf = preallocGetMem(MEM_ID_RX_EVENT); +#else + prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_RX_EVENT_BUF_SIZE, GFP_ATOMIC); +#endif + if (prUsbReq->prBufCtrl->pucBuf == NULL) { + DBGLOG(HAL, ERROR, "kmalloc() reports error\n"); + goto error; + } + prUsbReq->prBufCtrl->u4BufSize = USB_RX_EVENT_BUF_SIZE; + prUsbReq->prBufCtrl->u4ReadSize = 0; + ++i; + } + + /* RX Data */ + prHifInfo->prRxDataReqHead = glUsbInitQ(prHifInfo, &prHifInfo->rRxDataFreeQ, USB_REQ_RX_DATA_CNT); + i = 0; + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxDataFreeQ, list) { + prUsbReq->prBufCtrl = &prHifInfo->rRxDataBufCtrl[i]; +#ifdef CFG_PREALLOC_MEMORY + prUsbReq->prBufCtrl->pucBuf = preallocGetMem(MEM_ID_RX_DATA); +#else + prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_RX_DATA_BUF_SIZE, GFP_ATOMIC); +#endif + if (prUsbReq->prBufCtrl->pucBuf == NULL) { + DBGLOG(HAL, ERROR, "kmalloc() reports error\n"); + goto error; + } + prUsbReq->prBufCtrl->u4BufSize = USB_RX_DATA_BUF_SIZE; + prUsbReq->prBufCtrl->u4ReadSize = 0; + ++i; + } + + glUsbInitQ(prHifInfo, &prHifInfo->rRxEventCompleteQ, 0); + glUsbInitQ(prHifInfo, &prHifInfo->rRxDataCompleteQ, 0); + + glUsbSetState(prHifInfo, USB_STATE_LINK_UP); + + return; + +error: + /* TODO */ + ; +} /* 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 prHifInfo = NULL; */ + /* ASSERT(prGlueInfo); */ + /* prHifInfo = &prGlueInfo->rHifInfo; */ +#if CFG_USB_TX_AGG + UINT_8 ucTc; +#endif + P_USB_REQ_T prUsbReq, prUsbReqNext; + P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; + +#if CFG_USB_TX_AGG + for (ucTc = 0; ucTc < USB_TC_NUM; ++ucTc) { + if (ucTc >= TC4_INDEX && ucTc < USB_DBDC1_TC) + continue; + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxDataFreeQ[ucTc], list) { +#if CFG_USB_CONSISTENT_DMA + usb_free_coherent(prHifInfo->udev, USB_TX_DATA_BUFF_SIZE, + prUsbReq->prBufCtrl->pucBuf, prUsbReq->prUrb->transfer_dma); +#else +#ifndef CFG_PREALLOC_MEMORY + kfree(prUsbReq->prBufCtrl->pucBuf); +#endif +#endif + usb_free_urb(prUsbReq->prUrb); + } + } +#else + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxDataFreeQ, list) { +#if CFG_USB_CONSISTENT_DMA + usb_free_coherent(prHifInfo->udev, USB_TX_DATA_BUFF_SIZE, + prUsbReq->prBufCtrl->pucBuf, prUsbReq->prUrb->transfer_dma); +#else +#ifndef CFG_PREALLOC_MEMORY + kfree(prUsbReq->prBufCtrl->pucBuf); +#endif +#endif + usb_free_urb(prUsbReq->prUrb); + } +#endif + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxDataFfaQ, list) { +#if CFG_USB_CONSISTENT_DMA + usb_free_coherent(prHifInfo->udev, USB_TX_DATA_BUFF_SIZE, + prUsbReq->prBufCtrl->pucBuf, prUsbReq->prUrb->transfer_dma); +#else +#ifndef CFG_PREALLOC_MEMORY + kfree(prUsbReq->prBufCtrl->pucBuf); +#endif +#endif + usb_free_urb(prUsbReq->prUrb); + } + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxCmdFreeQ, list) { +#if CFG_USB_CONSISTENT_DMA + usb_free_coherent(prHifInfo->udev, USB_TX_CMD_BUF_SIZE, + prUsbReq->prBufCtrl->pucBuf, prUsbReq->prUrb->transfer_dma); +#else +#ifndef CFG_PREALLOC_MEMORY + kfree(prUsbReq->prBufCtrl->pucBuf); +#endif +#endif + usb_free_urb(prUsbReq->prUrb); + } + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxCmdCompleteQ, list) { +#if CFG_USB_CONSISTENT_DMA + usb_free_coherent(prHifInfo->udev, USB_TX_CMD_BUF_SIZE, + prUsbReq->prBufCtrl->pucBuf, prUsbReq->prUrb->transfer_dma); +#else +#ifndef CFG_PREALLOC_MEMORY + kfree(prUsbReq->prBufCtrl->pucBuf); +#endif +#endif + usb_free_urb(prUsbReq->prUrb); + } + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxDataCompleteQ, list) { +#if CFG_USB_CONSISTENT_DMA + usb_free_coherent(prHifInfo->udev, USB_TX_CMD_BUF_SIZE, + prUsbReq->prBufCtrl->pucBuf, prUsbReq->prUrb->transfer_dma); +#else +#ifndef CFG_PREALLOC_MEMORY + kfree(prUsbReq->prBufCtrl->pucBuf); +#endif +#endif + usb_free_urb(prUsbReq->prUrb); + } + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxDataFreeQ, list) { +#ifndef CFG_PREALLOC_MEMORY + kfree(prUsbReq->prBufCtrl->pucBuf); +#endif + usb_free_urb(prUsbReq->prUrb); + } + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxEventFreeQ, list) { +#ifndef CFG_PREALLOC_MEMORY + kfree(prUsbReq->prBufCtrl->pucBuf); +#endif + usb_free_urb(prUsbReq->prUrb); + } + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxDataCompleteQ, list) { +#ifndef CFG_PREALLOC_MEMORY + kfree(prUsbReq->prBufCtrl->pucBuf); +#endif + usb_free_urb(prUsbReq->prUrb); + } + + list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxEventCompleteQ, list) { +#ifndef CFG_PREALLOC_MEMORY + kfree(prUsbReq->prBufCtrl->pucBuf); +#endif + usb_free_urb(prUsbReq->prUrb); + } + kfree(prHifInfo->prTxCmdReqHead); + prHifInfo->prTxCmdReqHead = NULL; + + + kfree(prHifInfo->arTxDataFfaReqHead); + prHifInfo->arTxDataFfaReqHead = NULL; + + for (ucTc = 0; ucTc < USB_TC_NUM; ++ucTc) { + kfree(prHifInfo->arTxDataReqHead[ucTc]); + prHifInfo->arTxDataReqHead[ucTc] = NULL; + } + + kfree(prHifInfo->prRxEventReqHead); + prHifInfo->prRxEventReqHead = NULL; + + kfree(prHifInfo->prRxDataReqHead); + prHifInfo->prRxDataReqHead = NULL; + + mutex_destroy(&prHifInfo->vendor_req_sem); + kfree(prHifInfo->vendor_req_buf); + prHifInfo->vendor_req_buf = NULL; + + prHifInfo->vendor_req_buf_sz = 0; +} /* 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) +{ + return TRUE; +} /* end of glBusInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus operation and release resources. +* +* \param[in] pvData A pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glBusRelease(PVOID pvData) +{ +} /* end of glBusRelease() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setup bus interrupt operation and interrupt handler for os. +* +* \param[in] pvData A pointer to struct net_device. +* \param[in] pfnIsr A pointer to interrupt handler function. +* \param[in] pvCookie Private data for pfnIsr function. +* +* \retval WLAN_STATUS_SUCCESS if success +* NEGATIVE_VALUE if fail +*/ +/*----------------------------------------------------------------------------*/ +INT_32 glBusSetIrq(PVOID pvData, PVOID pfnIsr, PVOID pvCookie) +{ + int ret = 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; + + return ret; +} /* end of glBusSetIrq() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus interrupt operation and disable interrupt handling for os. +* +* \param[in] pvData A pointer to struct net_device. +* \param[in] pvCookie Private data for pfnIsr function. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glBusFreeIrq(PVOID pvData, PVOID pvCookie) +{ + struct net_device *prNetDevice = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_GL_HIF_INFO_T prHifInfo = 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; + } + + prHifInfo = &prGlueInfo->rHifInfo; +} /* end of glBusreeIrq() */ + +BOOLEAN glIsReadClearReg(UINT_32 u4Address) +{ + switch (u4Address) { + case MCR_WHISR: + case MCR_WASR: + case MCR_D2HRM0R: + case MCR_D2HRM1R: + case MCR_WTQCR0: + case MCR_WTQCR1: + case MCR_WTQCR2: + case MCR_WTQCR3: + case MCR_WTQCR4: + case MCR_WTQCR5: + case MCR_WTQCR6: + case MCR_WTQCR7: + return TRUE; + + default: + return FALSE; + } +} + +UINT_16 glGetUsbDeviceVendorId(struct usb_device *dev) +{ + return dev->descriptor.idVendor; +} /* end of glGetUsbDeviceVendorId() */ + +UINT_16 glGetUsbDeviceProductId(struct usb_device *dev) +{ + return dev->descriptor.idProduct; +} /* end of glGetUsbDeviceProductId() */ + +INT_32 glGetUsbDeviceManufacturerName(struct usb_device *dev, UCHAR *buffer, UINT_32 bufLen) +{ + return usb_string(dev, dev->descriptor.iManufacturer, buffer, bufLen); +} /* end of glGetUsbDeviceManufacturerName() */ + +INT_32 glGetUsbDeviceProductName(struct usb_device *dev, UCHAR *buffer, UINT_32 bufLen) +{ + return usb_string(dev, dev->descriptor.iProduct, buffer, bufLen); +} /* end of glGetUsbDeviceManufacturerName() */ + +INT_32 glGetUsbDeviceSerialNumber(struct usb_device *dev, UCHAR *buffer, UINT_32 bufLen) +{ + return usb_string(dev, dev->descriptor.iSerialNumber, buffer, bufLen); +} /* end of glGetUsbDeviceSerialNumber() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \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; + UINT_8 ucRetryCount = 0; + + ASSERT(prGlueInfo); + ASSERT(pu4Value); + + *pu4Value = 0xFFFFFFFF; + + do { + ret = mtk_usb_vendor_request(prGlueInfo, 0, DEVICE_VENDOR_REQUEST_IN, VND_REQ_REG_READ, + (u4Register & 0xffff0000) >> 16, (u4Register & 0x0000ffff), pu4Value, + sizeof(*pu4Value)); + + if (ret || ucRetryCount) + DBGLOG(HAL, ERROR, "usb_control_msg() status: %d retry: %u\n", + ret, ucRetryCount); + + + ucRetryCount++; + if (ucRetryCount > HIF_USB_ACCESS_RETRY_LIMIT) + break; + } while (ret); + + if (ret) { + kalSendAeeWarning(HIF_USB_ERR_TITLE_STR, + HIF_USB_ERR_DESC_STR "USB() reports error: %x retry: %u", ret, ucRetryCount); + DBGLOG(HAL, ERROR, "usb_readl() reports error: %x retry: %u\n", ret, ucRetryCount); + } else { + DBGLOG(HAL, INFO, "Get CR[0x%08x] value[0x%08x]\n", u4Register, *pu4Value); + } + + 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; + UINT_8 ucRetryCount = 0; + + ASSERT(prGlueInfo); + + do { + ret = mtk_usb_vendor_request(prGlueInfo, 0, DEVICE_VENDOR_REQUEST_OUT, VND_REQ_REG_WRITE, + (u4Register & 0xffff0000) >> 16, (u4Register & 0x0000ffff), &u4Value, + sizeof(u4Value)); + + if (ret || ucRetryCount) + DBGLOG(HAL, ERROR, "usb_control_msg() status: %d retry: %u\n", ret, ucRetryCount); + + ucRetryCount++; + if (ucRetryCount > HIF_USB_ACCESS_RETRY_LIMIT) + break; + + } while (ret); + + if (ret) { + kalSendAeeWarning(HIF_USB_ERR_TITLE_STR, + HIF_USB_ERR_DESC_STR "usb_writel() reports error: %x retry: %u", ret, ucRetryCount); + DBGLOG(HAL, ERROR, "usb_writel() reports error: %x retry: %u\n", ret, ucRetryCount); + } else { + DBGLOG(HAL, INFO, "Set CR[0x%08x] value[0x%08x]\n", u4Register, u4Value); + } + + 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_32 u4Len, OUT PUINT_8 pucBuf, IN UINT_32 u4ValidOutBufSize) +{ + P_GL_HIF_INFO_T prHifInfo = NULL; + PUINT_8 pucDst = NULL; + /* int count = u4Len; */ + int ret = 0; + /* int bNum = 0; */ + +#if DBG + DBGLOG(HAL, INFO, "++kalDevPortRead++ buf:0x%p, port:0x%x, length:%d\n", pucBuf, u2Port, u4Len); +#endif + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + ASSERT(pucBuf); + pucDst = pucBuf; + + ASSERT(u4Len <= u4ValidOutBufSize); + + u2Port &= MTK_USB_PORT_MASK; + if (prGlueInfo->rHifInfo.eEventEpType == EVENT_EP_TYPE_INTR && + u2Port == (USB_EVENT_EP_IN & USB_ENDPOINT_NUMBER_MASK)) { + /* maximize buff len for usb in */ + ret = mtk_usb_intr_in_msg(&prGlueInfo->rHifInfo, u4ValidOutBufSize, pucDst, u2Port); + if (ret != u4Len) { + DBGLOG(HAL, WARN, "usb_interrupt_msg(IN=%d) Warning. Data is not completed. (receive %d/%u)\n", + u2Port, ret, u4Len); + } + ret = ret >= 0 ? 0 : ret; + } else if (u2Port >= MTK_USB_BULK_IN_MIN_EP && u2Port <= MTK_USB_BULK_IN_MAX_EP) { + /* maximize buff len for usb in */ + ret = mtk_usb_bulk_in_msg(&prGlueInfo->rHifInfo, u4ValidOutBufSize, pucDst, u2Port); + if (ret != u4Len) { + DBGLOG(HAL, WARN, "usb_bulk_msg(IN=%d) Warning. Data is not completed. (receive %d/%u)\n", + u2Port, ret, u4Len); + } + ret = ret >= 0 ? 0 : ret; + } else { + DBGLOG(HAL, ERROR, "kalDevPortRead reports error: invalid port %x\n", u2Port); + ret = -EINVAL; + } + + if (ret) { + kalSendAeeWarning(HIF_USB_ERR_TITLE_STR, HIF_USB_ERR_DESC_STR "usb_readsb() reports error: %x", ret); + DBGLOG(HAL, ERROR, "usb_readsb() reports error: %x\n", 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_32 u4Len, IN PUINT_8 pucBuf, IN UINT_32 u4ValidInBufSize) +{ + P_GL_HIF_INFO_T prHifInfo = NULL; + PUINT_8 pucSrc = NULL; + /* int count = u4Len; */ + int ret = 0; + /* int bNum = 0; */ + +#if DBG + DBGLOG(HAL, INFO, "++kalDevPortWrite++ buf:0x%p, port:0x%x, length:%d\n", pucBuf, u2Port, u4Len); +#endif + + ASSERT(prGlueInfo); + prHifInfo = &prGlueInfo->rHifInfo; + + ASSERT(pucBuf); + pucSrc = pucBuf; + + ASSERT((u4Len + LEN_USB_UDMA_TX_TERMINATOR) <= u4ValidInBufSize); + + kalMemZero(pucSrc + u4Len, LEN_USB_UDMA_TX_TERMINATOR); + u4Len += LEN_USB_UDMA_TX_TERMINATOR; + + u2Port &= MTK_USB_PORT_MASK; + if (u2Port >= MTK_USB_BULK_OUT_MIN_EP && u2Port <= MTK_USB_BULK_OUT_MAX_EP) { + ret = mtk_usb_bulk_out_msg(&prGlueInfo->rHifInfo, u4Len, pucSrc, 8); + if (ret != u4Len) { + DBGLOG(HAL, WARN, "usb_bulk_msg(OUT=%d) Warning. Data is not completed. (receive %d/%u)\n", + u2Port, ret, u4Len); + } + ret = ret >= 0 ? 0 : ret; + } else { + DBGLOG(HAL, ERROR, "kalDevPortWrite reports error: invalid port %x\n", u2Port); + ret = -EINVAL; + } + + if (ret) { + kalSendAeeWarning(HIF_USB_ERR_TITLE_STR, HIF_USB_ERR_DESC_STR "usb_writesb() reports error: %x", ret); + DBGLOG(HAL, ERROR, "usb_writesb() reports error: %x\n", ret); + } + + return (ret) ? FALSE : TRUE; +} /* end of kalDevPortWrite() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set power state +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] ePowerMode +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glSetPowerState(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 ePowerMode) +{ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write data to device +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] prMsduInfo msdu info +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +BOOL kalDevWriteData(IN P_GLUE_INFO_T prGlueInfo, IN P_MSDU_INFO_T prMsduInfo) +{ + halTxUSBSendData(prGlueInfo, prMsduInfo); + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Kick Tx data to device +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +BOOL kalDevKickData(IN P_GLUE_INFO_T prGlueInfo) +{ +#if 0 + halTxUSBKickData(prGlueInfo); +#endif + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write command to device +* +* \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 kalDevWriteCmd(IN P_GLUE_INFO_T prGlueInfo, IN P_CMD_INFO_T prCmdInfo, IN UINT_8 ucTC) +{ + halTxUSBSendCmd(prGlueInfo, ucTC, prCmdInfo); + return TRUE; +} + +void glGetDev(PVOID ctx, struct device **dev) +{ + struct usb_interface *prUsbIntf = (struct usb_interface *) ctx; + struct usb_device *prUsbDev = interface_to_usbdev(prUsbIntf); + + *dev = &prUsbDev->dev; +} + +void glGetHifDev(P_GL_HIF_INFO_T prHif, struct device **dev) +{ + *dev = &(prHif->udev->dev); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_ate_agent.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_ate_agent.h new file mode 100644 index 0000000000000..c61d8f48990be --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_ate_agent.h @@ -0,0 +1,199 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file gl_ate_agent.h +* \brief This file includes private ioctl support. +*/ + +#ifndef _GL_ATE_AGENT_H +#define _GL_ATE_AGENT_H +#if CFG_SUPPORT_QA_TOOL +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +extern UINT_32 u4RxStatSeqNum; + +#if CFG_SUPPORT_TX_BF +extern PFMU_PROFILE_TAG1 g_rPfmuTag1; +extern PFMU_PROFILE_TAG2 g_rPfmuTag2; +extern PFMU_DATA g_rPfmuData; +#endif +extern BOOLEAN g_bCaptureDone; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef struct _STA_REC_BF_UPD_ARGUMENT { + UINT_32 u4WlanId; + UINT_32 u4BssId; + UINT_32 u4PfmuId; + UINT_32 u4SuMu; + UINT_32 u4eTxBfCap; + UINT_32 u4NdpaRate; + UINT_32 u4NdpRate; + UINT_32 u4ReptPollRate; + UINT_32 u4TxMode; + UINT_32 u4Nc; + UINT_32 u4Nr; + UINT_32 u4Bw; + UINT_32 u4SpeIdx; + UINT_32 u4TotalMemReq; + UINT_32 u4MemReq20M; + UINT_32 au4MemRow[4]; + UINT_32 au4MemCol[4]; +} STA_REC_BF_UPD_ARGUMENT, *P_STA_REC_BF_UPD_ARGUMENT; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +int Set_ResetStatCounter_Proc(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetATE(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetATEDa(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetATESa(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetATEChannel(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetATETxPower0(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetATETxGi(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetATETxBw(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetATETxMode(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetATETxLength(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetATETxCount(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetATETxMcs(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetATEIpg(struct net_device *prNetDev, UINT_8 *prInBuf); + +#if CFG_SUPPORT_TX_BF +int Set_TxBfProfileTag_Help(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_InValid(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_PfmuIdx(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_BfType(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_DBW(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_SuMu(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_Mem(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_Matrix(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_SNR(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_SmartAnt(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_SeIdx(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_RmsdThrd(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_McsThrd(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_TimeOut(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_DesiredBW(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_DesiredNc(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTag_DesiredNr(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTagRead(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileTagWrite(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_StaRecCmmUpdate(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_StaRecBfUpdate(struct net_device *prNetDev, UINT_8 *prInBuf); + +int Set_DevInfoUpdate(struct net_device *prNetDev, UINT_8 *prInBuf); + +int Set_BssInfoUpdate(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileDataRead(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfileDataWrite(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_Trigger_Sounding_Proc(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_Stop_Sounding_Proc(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfTxApply(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfilePnRead(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfProfilePnWrite(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfManualAssoc(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfPfmuMemAlloc(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_TxBfPfmuMemRelease(struct net_device *prNetDev, UINT_8 *prInBuf); + +#if CFG_SUPPORT_MU_MIMO +int Set_MUGetInitMCS(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_MUCalInitMCS(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_MUCalLQ(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_MUGetLQ(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_MUSetSNROffset(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_MUSetZeroNss(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_MUSetSpeedUpLQ(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_MUSetMUTable(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_MUSetGroup(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_MUGetQD(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_MUSetEnable(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_MUSetGID_UP(struct net_device *prNetDev, UINT_8 *prInBuf); +int Set_MUTriggerTx(struct net_device *prNetDev, UINT_8 *prInBuf); +#endif +#endif + + +int WriteEfuse(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetTxTargetPower(struct net_device *prNetDev, UINT_8 *prInBuf); + +#if (CFG_SUPPORT_DFS_MASTER == 1) +int SetRddReport(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetByPassCac(struct net_device *prNetDev, UINT_8 *prInBuf); +int SetRadarDetectMode(struct net_device *prNetDev, UINT_8 *prInBuf); +#endif + + +int AteCmdSetHandle(struct net_device *prNetDev, UINT_8 *prInBuf, UINT_32 u4InBufLen); +#endif /*CFG_SUPPORT_QA_TOOL */ +#endif /* _GL_ATE_AGENT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_cfg80211.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_cfg80211.h new file mode 100644 index 0000000000000..044ff5bb443e9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_cfg80211.h @@ -0,0 +1,351 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +#ifndef _GL_CFG80211_H +#define _GL_CFG80211_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#include +#include + +#include "gl_os.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#ifdef CONFIG_NL80211_TESTMODE +#define NL80211_DRIVER_TESTMODE_VERSION 2 +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +#ifdef CONFIG_NL80211_TESTMODE +#if CFG_SUPPORT_NFC_BEAM_PLUS + +typedef struct _NL80211_DRIVER_SET_NFC_PARAMS { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + UINT_32 NFC_Enable; + +} NL80211_DRIVER_SET_NFC_PARAMS, *P_NL80211_DRIVER_SET_NFC_PARAMS; + +#endif + + + +typedef struct _NL80211_DRIVER_GET_STA_STATISTICS_PARAMS { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + UINT_32 u4Version; + UINT_32 u4Flag; + UINT_8 aucMacAddr[MAC_ADDR_LEN]; +} NL80211_DRIVER_GET_STA_STATISTICS_PARAMS, *P_NL80211_DRIVER_GET_STA_STATISTICS_PARAMS; + +typedef enum _ENUM_TESTMODE_STA_STATISTICS_ATTR { + NL80211_TESTMODE_STA_STATISTICS_INVALID = 0, + NL80211_TESTMODE_STA_STATISTICS_VERSION, + NL80211_TESTMODE_STA_STATISTICS_MAC, + NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE, + NL80211_TESTMODE_STA_STATISTICS_FLAG, + + NL80211_TESTMODE_STA_STATISTICS_PER, + NL80211_TESTMODE_STA_STATISTICS_RSSI, + NL80211_TESTMODE_STA_STATISTICS_PHY_MODE, + NL80211_TESTMODE_STA_STATISTICS_TX_RATE, + + NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT, + NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT, + NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME, + + NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT, + NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT, + NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME, + + NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_NUM +} ENUM_TESTMODE_STA_STATISTICS_ATTR; +#endif +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/* cfg80211 hooks */ +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +int +mtk_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type, + struct vif_params *params); +#else +int +mtk_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, enum nl80211_iftype type, u32 *flags, struct vif_params *params); +#endif + +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); + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, const u8 *mac, struct station_info *sinfo); +#else +int mtk_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, u8 *mac, struct station_info *sinfo); +#endif + +int +mtk_cfg80211_get_link_statistics(struct wiphy *wiphy, struct net_device *ndev, u8 *mac, struct station_info *sinfo); + +int mtk_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request); + +#if CFG_SUPPORT_CFG80211_AUTH +int mtk_cfg80211_auth(struct wiphy *wiphy, struct net_device *ndev, + struct cfg80211_auth_request *req); +#endif + +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); + +#if CFG_SUPPORT_CFG80211_AUTH +int mtk_cfg80211_deauth(struct wiphy *wiphy, struct net_device *ndev, + struct cfg80211_deauth_request *req); +#endif + +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_set_rekey_data(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_gtk_rekey_data *data); + +int mtk_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, unsigned int duration, u64 *cookie); + +int mtk_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie); +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie); +#else +int mtk_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *channel, bool offscan, + unsigned int wait, + const u8 *buf, size_t len, bool no_cck, bool dont_wait_for_ack, u64 *cookie); +#endif + +void mtk_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, + IN struct wireless_dev *wdev, IN u16 frame_type, IN bool reg); + +int mtk_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie); + +#ifdef CONFIG_NL80211_TESTMODE +int +mtk_cfg80211_testmode_get_sta_statistics(IN struct wiphy *wiphy, + IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo); + +int mtk_cfg80211_testmode_get_scan_done(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo); + +#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_testmode_cmd(struct wiphy *wiphy, struct wireless_dev *wdev, + void *data, int len); +#else +int mtk_cfg80211_testmode_cmd(struct wiphy *wiphy, void *data, int len); +#endif + +int mtk_cfg80211_testmode_sw_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); + +#if CFG_SUPPORT_PASSPOINT +int mtk_cfg80211_testmode_hs20_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_WAPI +int mtk_cfg80211_testmode_set_key_ext(IN struct wiphy *wiphy, IN void *data, IN int len); +#endif +#if CFG_SUPPORT_NFC_BEAM_PLUS +int mtk_cfg80211_testmode_get_scan_done(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo); +#endif +#else +/* IGNORE KERNEL DEPENCY ERRORS*/ +/*#error "Please ENABLE kernel config (CONFIG_NL80211_TESTMODE) to support Wi-Fi Direct"*/ +#endif + +int +mtk_cfg80211_sched_scan_start(IN struct wiphy *wiphy, + IN struct net_device *ndev, IN struct cfg80211_sched_scan_request *request); + +int mtk_cfg80211_sched_scan_stop(IN struct wiphy *wiphy, IN struct net_device *ndev); + +int mtk_cfg80211_assoc(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_assoc_request *req); + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int +mtk_cfg80211_change_station(struct wiphy *wiphy, struct net_device *ndev, + const u8 *mac, struct station_parameters *params); + +int mtk_cfg80211_add_station(struct wiphy *wiphy, struct net_device *ndev, + const u8 *mac, struct station_parameters *params); + +#if KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, struct station_del_parameters *params); +#else +int mtk_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, + const u8 *mac); +#endif +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE +int mtk_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, + bool initiator, const u8 *buf, size_t len); +#else +int mtk_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, + const u8 *buf, size_t len); +#endif + +int mtk_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, + const u8 *peer, enum nl80211_tdls_operation oper); +#else +int +mtk_cfg80211_change_station(struct wiphy *wiphy, struct net_device *ndev, u8 *mac, struct station_parameters *params); + +int mtk_cfg80211_add_station(struct wiphy *wiphy, struct net_device *ndev, u8 *mac, struct station_parameters *params); + +int mtk_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, u8 *mac); + +int +mtk_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + u8 *peer, u8 action_code, u8 dialog_token, u16 status_code, const u8 *buf, size_t len); + +int mtk_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, u8 *peer, enum nl80211_tdls_operation oper); +#endif + +void mtk_reg_notify(IN struct wiphy *pWiphy, IN struct regulatory_request *pRequest); +void cfg80211_regd_set_wiphy(IN struct wiphy *pWiphy); + +int mtk_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow); +int cfg80211_get_non_wfa_vendor_ie(P_GLUE_INFO_T prGlueInfo, u8 *ies, int len); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _GL_CFG80211_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_hook_api.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_hook_api.h new file mode 100644 index 0000000000000..9c14f721036bb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_hook_api.h @@ -0,0 +1,230 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file gl_hook_api.h +* \brief This file includes private ioctl support. +*/ + +#ifndef _GL_HOOK_API_H +#define _GL_HOOK_API_H +#if CFG_SUPPORT_QA_TOOL +/******************************************************************************* +* C O M P I L E 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 +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +INT_32 MT_ATEStart(struct net_device *prNetDev, UINT_8 *prInBuf); +INT_32 MT_ICAPStart(struct net_device *prNetDev, UINT_8 *prInBuf); +INT_32 MT_ATEStop(struct net_device *prNetDev, UINT_8 *prInBuf); +INT_32 MT_ATEStartTX(struct net_device *prNetDev, UINT_8 *prInBuf); +INT_32 MT_ATEStopTX(struct net_device *prNetDev, UINT_8 *prInBuf); +INT_32 MT_ATEStartRX(struct net_device *prNetDev, UINT_8 *prInBuf); +INT_32 MT_ATEStopRX(struct net_device *prNetDev, UINT_8 *prInBuf); +INT_32 MT_ATESetChannel(struct net_device *prNetDev, UINT_32 u4SXIdx, UINT_32 u4SetFreq); +INT_32 MT_ATESetPreamble(struct net_device *prNetDev, UINT_32 u4Mode); +INT_32 MT_ATESetSystemBW(struct net_device *prNetDev, UINT_32 u4BW); +INT_32 MT_ATESetTxLength(struct net_device *prNetDev, UINT_32 u4TxLength); +INT_32 MT_ATESetTxCount(struct net_device *prNetDev, UINT_32 u4TxCount); +INT_32 MT_ATESetTxIPG(struct net_device *prNetDev, UINT_32 u4TxIPG); +INT_32 MT_ATESetTxPower0(struct net_device *prNetDev, UINT_32 u4TxPower0); +INT_32 MT_ATESetPerPacketBW(struct net_device *prNetDev, UINT_32 u4BW); +INT_32 MT_ATEPrimarySetting(struct net_device *prNetDev, UINT_32 u4PrimaryCh); +INT_32 MT_ATESetTxGi(struct net_device *prNetDev, UINT_32 u4SetTxGi); +INT_32 MT_ATESetTxPayLoad(struct net_device *prNetDev, UINT_32 u4Gen_payload_rule, UINT_8 ucPayload); +INT_32 MT_ATESetTxSTBC(struct net_device *prNetDev, UINT_32 u4Stbc); +INT_32 MT_ATESetTxPath(struct net_device *prNetDev, UINT_32 u4Tx_path); +INT_32 MT_ATESetTxVhtNss(struct net_device *prNetDev, UINT_32 u4VhtNss); +INT_32 MT_ATESetRate(struct net_device *prNetDev, UINT_32 u4Rate); +INT_32 MT_ATESetEncodeMode(struct net_device *prNetDev, UINT_32 u4Ldpc); +INT_32 MT_ATESetiBFEnable(struct net_device *prNetDev, UINT_32 u4iBF); +INT_32 MT_ATESeteBFEnable(struct net_device *prNetDev, UINT_32 u4eBF); +INT_32 MT_ATESetMACAddress(struct net_device *prNetDev, UINT_32 u4Type, UCHAR ucAddr[]); +INT_32 MT_ATELogOnOff(struct net_device *prNetDev, UINT_32 u4Type, UINT_32 u4On_off, UINT_32 u4Size); +INT_32 MT_ATEResetTXRXCounter(struct net_device *prNetDev); +INT_32 MT_ATESetDBDCBandIndex(struct net_device *prNetDev, UINT_32 u4BandIdx); +INT_32 MT_ATESetBand(struct net_device *prNetDev, INT_32 i4Band); +INT_32 MT_ATESetTxToneType(struct net_device *prNetDev, INT_32 i4ToneType); +INT_32 MT_ATESetTxToneBW(struct net_device *prNetDev, INT_32 i4ToneFreq); +INT_32 MT_ATESetTxToneDCOffset(struct net_device *prNetDev, INT_32 i4DcOffsetI, INT_32 i4DcOffsetQ); +INT_32 MT_ATESetDBDCTxTonePower(struct net_device *prNetDev, INT_32 i4AntIndex, INT_32 i4RF_Power, INT_32 i4Digi_Power); +INT_32 MT_ATEDBDCTxTone(struct net_device *prNetDev, INT_32 i4Control); +INT_32 MT_ATESetMacHeader(struct net_device *prNetDev, UINT_32 u2FrameCtrl, UINT_32 u2DurationID, UINT_32 u4SeqCtrl); +INT_32 MT_ATE_IRRSetADC(struct net_device *prNetDev, + UINT_32 u4WFIdx, + UINT_32 u4ChFreq, + UINT_32 u4BW, UINT_32 u4Sx, UINT_32 u4Band, UINT_32 u4RunType, UINT_32 u4FType); +INT_32 MT_ATE_IRRSetRxGain(struct net_device *prNetDev, + UINT_32 u4PgaLpfg, UINT_32 u4Lna, UINT_32 u4Band, UINT_32 u4WF_inx, UINT_32 u4Rfdgc); +INT_32 MT_ATE_IRRSetTTG(struct net_device *prNetDev, + UINT_32 u4TTGPwrIdx, UINT_32 u4ChFreq, UINT_32 u4FIToneFreq, UINT_32 u4Band); +INT_32 MT_ATE_IRRSetTrunOnTTG(struct net_device *prNetDev, UINT_32 u4TTGOnOff, UINT_32 u4Band, UINT_32 u4WF_inx); +INT_32 MT_ATE_TMRSetting(struct net_device *prNetDev, + UINT_32 u4Setting, UINT_32 u4Version, UINT_32 u4MPThres, UINT_32 u4MPIter); +INT_32 MT_ATERDDStart(struct net_device *prNetDev, UINT_8 *prInBuf); +INT_32 MT_ATERDDStop(struct net_device *prNetDev, UINT_8 *prInBuf); +INT_32 MT_ATEMPSSetSeqData(struct net_device *prNetDev, + UINT_32 u4TestNum, UINT_32 *pu4Phy, UINT_32 u4Band); +INT_32 MT_ATEMPSSetPayloadLength(struct net_device *prNetDev, + UINT_32 u4TestNum, UINT_32 *pu4Length, UINT_32 u4Band); +INT_32 MT_ATEMPSSetPacketCount(struct net_device *prNetDev, + UINT_32 u4TestNum, UINT_32 *pu4PktCnt, UINT_32 u4Band); +INT_32 MT_ATEMPSSetPowerGain(struct net_device *prNetDev, + UINT_32 u4TestNum, UINT_32 *pu4PwrGain, UINT_32 u4Band); +INT_32 MT_ATEMPSSetNss(struct net_device *prNetDev, + UINT_32 u4TestNum, UINT_32 *pu4Nss, UINT_32 u4Band); +INT_32 MT_ATEMPSSetPerpacketBW(struct net_device *prNetDev, + UINT_32 u4TestNum, UINT_32 *pu4PerPktBW, UINT_32 u4Band); + + +INT_32 MT_ATEWriteEfuse(struct net_device *prNetDev, UINT_16 u2Offset, UINT_16 u2Content); +INT_32 MT_ATESetTxTargetPower(struct net_device *prNetDev, UINT_8 ucTxTargetPower); +#if (CFG_SUPPORT_DFS_MASTER == 1) +INT_32 MT_ATESetRddReport(struct net_device *prNetDev, UINT_8 ucDbdcIdx); +INT_32 MT_ATESetRadarDetectMode(struct net_device *prNetDev, UINT_8 ucRadarDetectMode); +#endif + + +#if CFG_SUPPORT_TX_BF +INT_32 TxBfProfileTag_InValid(struct net_device *prNetDev, P_PFMU_PROFILE_TAG1 prPfmuTag1, UINT_8 ucInValid); +INT_32 TxBfProfileTag_PfmuIdx(struct net_device *prNetDev, P_PFMU_PROFILE_TAG1 prPfmuTag1, UINT_8 ucProfileIdx); +INT_32 TxBfProfileTag_TxBfType(struct net_device *prNetDev, P_PFMU_PROFILE_TAG1 prPfmuTag1, UINT_8 ucBFType); +INT_32 TxBfProfileTag_DBW(struct net_device *prNetDev, P_PFMU_PROFILE_TAG1 prPfmuTag1, UINT_8 ucBW); +INT_32 TxBfProfileTag_SuMu(struct net_device *prNetDev, P_PFMU_PROFILE_TAG1 prPfmuTag1, UINT_8 ucSuMu); +INT_32 TxBfProfileTag_Mem(struct net_device *prNetDev, + P_PFMU_PROFILE_TAG1 prPfmuTag1, PUINT_8 aucMemAddrColIdx, PUINT_8 aucMemAddrRowIdx); +INT_32 TxBfProfileTag_Matrix(struct net_device *prNetDev, + P_PFMU_PROFILE_TAG1 prPfmuTag1, + UINT_8 ucNrow, + UINT_8 ucNcol, UINT_8 ucNgroup, UINT_8 ucLM, UINT_8 ucCodeBook, UINT_8 ucHtcExist); +INT_32 TxBfProfileTag_SNR(struct net_device *prNetDev, + P_PFMU_PROFILE_TAG1 prPfmuTag1, + UINT_8 ucSNR_STS0, UINT_8 ucSNR_STS1, UINT_8 ucSNR_STS2, UINT_8 ucSNR_STS3); +INT_32 TxBfProfileTag_SmtAnt(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucSmartAnt); +INT_32 TxBfProfileTag_SeIdx(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucSeIdx); +INT_32 TxBfProfileTag_RmsdThd(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucRmsdThrd); +INT_32 TxBfProfileTag_McsThd(struct net_device *prNetDev, + P_PFMU_PROFILE_TAG2 prPfmuTag2, PUINT_8 pMCSThLSS, PUINT_8 pMCSThSSS); +INT_32 TxBfProfileTag_TimeOut(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucTimeOut); +INT_32 TxBfProfileTag_DesiredBW(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucDesiredBW); +INT_32 TxBfProfileTag_DesiredNc(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucDesiredNc); +INT_32 TxBfProfileTag_DesiredNr(struct net_device *prNetDev, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 ucDesiredNr); +INT_32 TxBfProfileTagWrite(struct net_device *prNetDev, + P_PFMU_PROFILE_TAG1 prPfmuTag1, P_PFMU_PROFILE_TAG2 prPfmuTag2, UINT_8 profileIdx); +INT_32 TxBfProfileTagRead(struct net_device *prNetDev, UINT_8 PfmuIdx, UINT_8 fgBFer); +INT_32 TxBfProfileDataRead(struct net_device *prNetDev, + UINT_8 profileIdx, UINT_8 fgBFer, UINT_8 subcarrierIdxMsb, UINT_8 subcarrierIdxLsb); +INT_32 TxBfProfileDataWrite(struct net_device *prNetDev, + UINT_8 profileIdx, + UINT_16 subcarrierIdx, UINT_16 au2Phi[6], UINT_8 aucPsi[6], UINT_8 aucDSnr[4] +); +INT_32 TxBfProfilePnRead(struct net_device *prNetDev, UINT_8 profileIdx); +INT_32 TxBfProfilePnWrite(struct net_device *prNetDev, UINT_8 ucProfileIdx, UINT_16 u2bw, UINT_16 au2XSTS[12]); + +INT_32 TxBfSounding(struct net_device *prNetDev, UINT_8 ucSuMu, /* 0/1/2/3 */ + UINT_8 ucNumSta, /* 00~04 */ + UINT_8 ucSndInterval, /* 00~FF */ + UINT_8 ucWLan0, /* 00~7F */ + UINT_8 ucWLan1, /* 00~7F */ + UINT_8 ucWLan2, /* 00~7F */ + + UINT_8 ucWLan3 /* 00~7F */ +); +INT_32 TxBfSoundingStop(struct net_device *prNetDev); +INT_32 TxBfTxApply(struct net_device *prNetDev, UINT_8 ucWlanId, UINT_8 fgETxBf, UINT_8 fgITxBf, UINT_8 fgMuTxBf); + +INT_32 TxBfManualAssoc(struct net_device *prNetDev, + UINT_8 aucMac[MAC_ADDR_LEN], + UINT_8 ucType, + UINT_8 ucWtbl, + UINT_8 ucOwnmac, + UINT_8 ucPhyMode, + UINT_8 ucBw, + UINT_8 ucNss, UINT_8 ucPfmuId, UINT_8 ucMarate, UINT_8 ucSpeIdx, UINT_8 ucRca2, UINT_8 ucRv); + +INT_32 TxBfPfmuMemAlloc(struct net_device *prNetDev, UINT_8 ucSuMuMode, UINT_8 ucWlanIdx); + +INT_32 TxBfPfmuMemRelease(struct net_device *prNetDev, UINT_8 ucWlanId); + +INT_32 DevInfoUpdate(struct net_device *prNetDev, UINT_8 ucOwnMacIdx, UINT_8 fgBand, UINT_8 aucMacAddr[MAC_ADDR_LEN]); + +INT_32 BssInfoUpdate(struct net_device *prNetDev, UINT_8 u4OwnMacIdx, UINT_8 u4BssIdx, UINT_8 u4BssId[MAC_ADDR_LEN]); + +INT_32 StaRecCmmUpdate(struct net_device *prNetDev, + UINT_8 ucWlanId, UINT_8 ucBssId, UINT_8 u4Aid, UINT_8 aucMacAddr[MAC_ADDR_LEN] +); + +INT_32 StaRecBfUpdate(struct net_device *prNetDev, + STA_REC_BF_UPD_ARGUMENT rStaRecBfUpdArg, UINT_8 aucMemRow[4], UINT_8 aucMemCol[4] +); + +#endif +#endif /*CFG_SUPPORT_QA_TOOL */ +#endif /* _GL_HOOK_API_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_kal.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_kal.h new file mode 100644 index 0000000000000..e901be22af839 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_kal.h @@ -0,0 +1,1289 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_kal.h#2 +*/ + +/*! \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. +*/ + +#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_wext_priv.h" +#include "link.h" +#include "nic/mac.h" +#include "nic/wlan_def.h" +#include "wlan_lib.h" +#include "wlan_oid.h" + +#if CFG_ENABLE_BT_OVER_WIFI +#include "nic/bow.h" +#endif + +#include "linux/kallsyms.h" +/*#include */ + +#if DBG +extern int allocatedMemSize; +#endif + +extern struct semaphore g_halt_sem; +extern int g_u4HaltFlag; + +extern struct delayed_work sched_workq; +extern u_int8_t g_fgIsOid; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* Define how many concurrent operation networks. */ +#define KAL_BSS_NUM 4 + +#if CFG_DUAL_P2PLIKE_INTERFACE +#define KAL_P2P_NUM 2 +#else +#define KAL_P2P_NUM 1 +#endif + +#if CFG_SUPPORT_MULTITHREAD +#define GLUE_FLAG_MAIN_PROCESS \ + (GLUE_FLAG_HALT | GLUE_FLAG_SUB_MOD_MULTICAST | GLUE_FLAG_TX_CMD_DONE | GLUE_FLAG_TXREQ | \ + GLUE_FLAG_TIMEOUT | GLUE_FLAG_FRAME_FILTER | GLUE_FLAG_OID | GLUE_FLAG_RX) + +#define GLUE_FLAG_HIF_PROCESS \ + (GLUE_FLAG_HALT | GLUE_FLAG_INT | GLUE_FLAG_HIF_TX | GLUE_FLAG_HIF_TX_CMD | GLUE_FLAG_HIF_FW_OWN) + +#define GLUE_FLAG_RX_PROCESS (GLUE_FLAG_HALT | GLUE_FLAG_RX_TO_OS) +#else +/* All flags for single thread driver */ +#define GLUE_FLAG_TX_PROCESS 0xFFFFFFFF +#endif + +#if CFG_SUPPORT_SNIFFER +#define RADIOTAP_FIELD_TSFT BIT(0) +#define RADIOTAP_FIELD_FLAGS BIT(1) +#define RADIOTAP_FIELD_RATE BIT(2) +#define RADIOTAP_FIELD_CHANNEL BIT(3) +#define RADIOTAP_FIELD_ANT_SIGNAL BIT(5) +#define RADIOTAP_FIELD_ANT_NOISE BIT(6) +#define RADIOTAP_FIELD_ANT BIT(11) +#define RADIOTAP_FIELD_MCS BIT(19) +#define RADIOTAP_FIELD_AMPDU BIT(20) +#define RADIOTAP_FIELD_VHT BIT(21) +#define RADIOTAP_FIELD_VENDOR BIT(30) + +#define RADIOTAP_LEN_VHT 48 +#define RADIOTAP_FIELDS_VHT (RADIOTAP_FIELD_TSFT | \ + RADIOTAP_FIELD_FLAGS | \ + RADIOTAP_FIELD_RATE | \ + RADIOTAP_FIELD_CHANNEL | \ + RADIOTAP_FIELD_ANT_SIGNAL | \ + RADIOTAP_FIELD_ANT_NOISE | \ + RADIOTAP_FIELD_ANT | \ + RADIOTAP_FIELD_AMPDU | \ + RADIOTAP_FIELD_VHT | \ + RADIOTAP_FIELD_VENDOR) + +#define RADIOTAP_LEN_HT 36 +#define RADIOTAP_FIELDS_HT (RADIOTAP_FIELD_TSFT | \ + RADIOTAP_FIELD_FLAGS | \ + RADIOTAP_FIELD_RATE | \ + RADIOTAP_FIELD_CHANNEL | \ + RADIOTAP_FIELD_ANT_SIGNAL | \ + RADIOTAP_FIELD_ANT_NOISE | \ + RADIOTAP_FIELD_ANT | \ + RADIOTAP_FIELD_MCS | \ + RADIOTAP_FIELD_AMPDU | \ + RADIOTAP_FIELD_VENDOR) + +#define RADIOTAP_LEN_LEGACY 26 +#define RADIOTAP_FIELDS_LEGACY (RADIOTAP_FIELD_TSFT | \ + RADIOTAP_FIELD_FLAGS | \ + RADIOTAP_FIELD_RATE | \ + RADIOTAP_FIELD_CHANNEL | \ + RADIOTAP_FIELD_ANT_SIGNAL | \ + RADIOTAP_FIELD_ANT_NOISE | \ + RADIOTAP_FIELD_ANT | \ + RADIOTAP_FIELD_VENDOR) +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_SPIN_LOCK_CATEGORY_E { + SPIN_LOCK_FSM = 0, + +#if CFG_SUPPORT_MULTITHREAD + SPIN_LOCK_TX_PORT_QUE, + SPIN_LOCK_TX_CMD_QUE, + SPIN_LOCK_TX_CMD_DONE_QUE, + SPIN_LOCK_TC_RESOURCE, + SPIN_LOCK_RX_TO_OS_QUE, +#endif + + /* FIX ME */ + SPIN_LOCK_RX_QUE, + SPIN_LOCK_RX_FREE_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, + /* TX/RX Direct : BEGIN */ + SPIN_LOCK_TX_DIRECT, + SPIN_LOCK_TX_DESC, + SPIN_LOCK_RX_DIRECT_REORDER, + /* TX/RX Direct : END */ + SPIN_LOCK_IO_REQ, + SPIN_LOCK_INT, + + SPIN_LOCK_MGT_BUF, + SPIN_LOCK_MSG_BUF, + SPIN_LOCK_STA_REC, + SPIN_LOCK_STA_RECOFAP, + SPIN_LOCK_REQ_LIST, + + SPIN_LOCK_MAILBOX, + SPIN_LOCK_TIMER, + + SPIN_LOCK_BOW_TABLE, + + SPIN_LOCK_EHPI_BUS, /* only for EHPI */ + SPIN_LOCK_NET_DEV, + SPIN_LOCK_CHIP_RST, + SPIN_LOCK_NUM +} ENUM_SPIN_LOCK_CATEGORY_E; + +typedef enum _ENUM_MUTEX_CATEGORY_E { + MUTEX_TX_CMD_CLEAR, + MUTEX_TX_DATA_DONE_QUE, + MUTEX_DEL_INF, +#if CFG_SUPPORT_CSI + MUTEX_CSI_BUFFER, +#endif + + MUTEX_NUM +} ENUM_MUTEX_CATEGORY_E; + +/* event for assoc information update */ +typedef struct _EVENT_ASSOC_INFO { + UINT_8 ucAssocReq; /* 1 for assoc req, 0 for assoc rsp */ + UINT_8 ucReassoc; /* 0 for assoc, 1 for reassoc */ + UINT_16 u2Length; + PUINT_8 pucIe; +} EVENT_ASSOC_INFO, *P_EVENT_ASSOC_INFO; + +typedef enum _ENUM_KAL_NETWORK_TYPE_INDEX_T { + KAL_NETWORK_TYPE_AIS_INDEX = 0, +#if CFG_ENABLE_WIFI_DIRECT + KAL_NETWORK_TYPE_P2P_INDEX, +#endif +#if CFG_ENABLE_BT_OVER_WIFI + KAL_NETWORK_TYPE_BOW_INDEX, +#endif + KAL_NETWORK_TYPE_INDEX_NUM +} ENUM_KAL_NETWORK_TYPE_INDEX_T; + +typedef enum _ENUM_KAL_MEM_ALLOCATION_TYPE_E { + PHY_MEM_TYPE, /* physically continuous */ + VIR_MEM_TYPE, /* virtually continuous */ + MEM_TYPE_NUM +} ENUM_KAL_MEM_ALLOCATION_TYPE; + +#ifdef CONFIG_ANDROID /* Defined in Android kernel source */ +typedef struct wake_lock KAL_WAKE_LOCK_T, *P_KAL_WAKE_LOCK_T; +#else +typedef UINT_32 KAL_WAKE_LOCK_T, *P_KAL_WAKE_LOCK_T; +#endif + +#if CFG_SUPPORT_AGPS_ASSIST +typedef enum _ENUM_MTK_AGPS_ATTR { + MTK_ATTR_AGPS_INVALID, + MTK_ATTR_AGPS_CMD, + MTK_ATTR_AGPS_DATA, + MTK_ATTR_AGPS_IFINDEX, + MTK_ATTR_AGPS_IFNAME, + MTK_ATTR_AGPS_MAX +} ENUM_MTK_CCX_ATTR; + +typedef enum _ENUM_AGPS_EVENT { + AGPS_EVENT_WLAN_ON, + AGPS_EVENT_WLAN_OFF, + AGPS_EVENT_WLAN_AP_LIST, +} ENUM_CCX_EVENT; +BOOLEAN kalIndicateAgpsNotify(P_ADAPTER_T prAdapter, UINT_8 cmd, PUINT_8 data, UINT_16 dataLen); +#endif /* CFG_SUPPORT_AGPS_ASSIST */ + +#if CFG_SUPPORT_SNIFFER +/* Vendor Namespace + * Bit Number 30 + * Required Alignment 2 bytes + */ +typedef struct _RADIOTAP_FIELD_VENDOR_T { + UINT_8 aucOUI[3]; + UINT_8 ucSubNamespace; + UINT_16 u2DataLen; + UINT_8 ucData; +} __packed RADIOTAP_FIELD_VENDOR_T, *P_RADIOTAP_FIELD_VENDOR_T; + +typedef struct _MONITOR_RADIOTAP_T { + /* radiotap header */ + UINT_8 ucItVersion; /* set to 0 */ + UINT_8 ucItPad; + UINT_16 u2ItLen; /* entire length */ + UINT_32 u4ItPresent; /* fields present */ + + /* TSFT + * Bit Number 0 + * Required Alignment 8 bytes + * Unit microseconds + */ + UINT_64 u8MacTime; + + /* Flags + * Bit Number 1 + */ + UINT_8 ucFlags; + + /* Rate + * Bit Number 2 + * Unit 500 Kbps + */ + UINT_8 ucRate; + + /* Channel + * Bit Number 3 + * Required Alignment 2 bytes + */ + UINT_16 u2ChFrequency; + UINT_16 u2ChFlags; + + /* Antenna signal + * Bit Number 5 + * Unit dBm + */ + UINT_8 ucAntennaSignal; + + /* Antenna noise + * Bit Number 6 + * Unit dBm + */ + UINT_8 ucAntennaNoise; + + /* Antenna + * Bit Number 11 + * Unit antenna index + */ + UINT_8 ucAntenna; + + /* MCS + * Bit Number 19 + * Required Alignment 1 byte + */ + UINT_8 ucMcsKnown; + UINT_8 ucMcsFlags; + UINT_8 ucMcsMcs; + + /* A-MPDU status + * Bit Number 20 + * Required Alignment 4 bytes + */ + UINT_32 u4AmpduRefNum; + UINT_16 u2AmpduFlags; + UINT_8 ucAmpduDelimiterCRC; + UINT_8 ucAmpduReserved; + + /* VHT + * Bit Number 21 + * Required Alignment 2 bytes + */ + UINT_16 u2VhtKnown; + UINT_8 ucVhtFlags; + UINT_8 ucVhtBandwidth; + UINT_8 aucVhtMcsNss[4]; + UINT_8 ucVhtCoding; + UINT_8 ucVhtGroupId; + UINT_16 u2VhtPartialAid; + + /* extension space */ + UINT_8 aucReserve[12]; +} __packed MONITOR_RADIOTAP_T, *P_MONITOR_RADIOTAP_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 getting current thread id */ +/*----------------------------------------------------------------------------*/ +#define KAL_GET_CURRENT_THREAD_ID() (current->pid) +#define KAL_GET_CURRENT_THREAD_NAME() (current->comm) + +/*----------------------------------------------------------------------------*/ +/* Macros of SPIN LOCK operations for using in Driver Layer */ +/*----------------------------------------------------------------------------*/ +#define KAL_SPIN_LOCK_DECLARATION() unsigned long __ulFlags + +#define KAL_ACQUIRE_SPIN_LOCK(_prAdapter, _rLockCategory) \ + kalAcquireSpinLock(((P_ADAPTER_T)_prAdapter)->prGlueInfo, _rLockCategory, &__ulFlags) + +#define KAL_RELEASE_SPIN_LOCK(_prAdapter, _rLockCategory) \ + kalReleaseSpinLock(((P_ADAPTER_T)_prAdapter)->prGlueInfo, _rLockCategory, __ulFlags) + +/*----------------------------------------------------------------------------*/ +/* Macros of MUTEX operations for using in Driver Layer */ +/*----------------------------------------------------------------------------*/ +#define KAL_ACQUIRE_MUTEX(_prAdapter, _rLockCategory) \ + kalAcquireMutex(((P_ADAPTER_T)_prAdapter)->prGlueInfo, _rLockCategory) + +#define KAL_RELEASE_MUTEX(_prAdapter, _rLockCategory) \ + kalReleaseMutex(((P_ADAPTER_T)_prAdapter)->prGlueInfo, _rLockCategory) + +/*----------------------------------------------------------------------------*/ +/* 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 for kernel related defines */ +/*----------------------------------------------------------------------------*/ +#if KERNEL_VERSION(3, 14, 0) > CFG80211_VERSION_CODE +#define IEEE80211_CHAN_PASSIVE_FLAG IEEE80211_CHAN_PASSIVE_SCAN +#define IEEE80211_CHAN_PASSIVE_STR "PASSIVE" +#else +#define IEEE80211_CHAN_PASSIVE_FLAG IEEE80211_CHAN_NO_IR +#define IEEE80211_CHAN_PASSIVE_STR "NO_IR" +#endif + +#if KERNEL_VERSION(4, 7, 0) <= CFG80211_VERSION_CODE +/** + * enum nl80211_band - Frequency band + * @NL80211_BAND_2GHZ: 2.4 GHz ISM band + * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz) + * @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 64.80 GHz) + * @NUM_NL80211_BANDS: number of bands, avoid using this in userspace + * since newer kernel versions may support more bands + */ +#define KAL_BAND_2GHZ NL80211_BAND_2GHZ +#define KAL_BAND_5GHZ NL80211_BAND_5GHZ +#define KAL_NUM_BANDS NUM_NL80211_BANDS +#else +#define KAL_BAND_2GHZ IEEE80211_BAND_2GHZ +#define KAL_BAND_5GHZ IEEE80211_BAND_5GHZ +#define KAL_NUM_BANDS IEEE80211_NUM_BANDS +#endif + +/** + * enum nl80211_reg_rule_flags - regulatory rule flags + * @NL80211_RRF_NO_OFDM: OFDM modulation not allowed + * @NL80211_RRF_AUTO_BW: maximum available bandwidth should be calculated + * base on contiguous rules and wider channels will be allowed to cross + * multiple contiguous/overlapping frequency ranges. + * @NL80211_RRF_DFS: DFS support is required to be used + */ +#define KAL_RRF_NO_OFDM NL80211_RRF_NO_OFDM +#define KAL_RRF_DFS NL80211_RRF_DFS +#if KERNEL_VERSION(3, 15, 0) > CFG80211_VERSION_CODE +#define KAL_RRF_AUTO_BW 0 +#else +#define KAL_RRF_AUTO_BW NL80211_RRF_AUTO_BW +#endif + +/** + * kalCfg80211ToMtkBand - Band translation helper + * + * @band: cfg80211_band + * + * Translates cfg80211 band into internal band definition + */ +#if CFG_SCAN_CHANNEL_SPECIFIED +#define kalCfg80211ToMtkBand(cfg80211_band) \ + (cfg80211_band == KAL_BAND_2GHZ ? BAND_2G4 : \ + cfg80211_band == KAL_BAND_5GHZ ? BAND_5G : BAND_NULL) +#endif + +/** + * kalCfg80211ScanDone - abstraction of cfg80211_scan_done + * + * @request: the corresponding scan request (sanity checked by callers!) + * @aborted: set to true if the scan was aborted for any reason, + * userspace will be notified of that + * + * Since linux-4.8.y the 2nd parameter is changed from bool to + * struct cfg80211_scan_info, but we don't use all fields yet. + */ +#if KERNEL_VERSION(4, 8, 0) <= CFG80211_VERSION_CODE +static inline void kalCfg80211ScanDone(struct cfg80211_scan_request *request, + bool aborted) +{ + struct cfg80211_scan_info info = { .aborted = aborted }; + + cfg80211_scan_done(request, &info); +} +#else +static inline void kalCfg80211ScanDone(struct cfg80211_scan_request *request, + bool aborted) +{ + cfg80211_scan_done(request, aborted); +} +#endif + +/* Consider on some Android platform, using request_firmware_direct() + * may cause system failed to load firmware. So we still use + * request_firmware(). + */ +#define REQUEST_FIRMWARE(_fw, _name, _dev) \ + request_firmware(_fw, _name, _dev) + +#define RELEASE_FIRMWARE(_fw) \ + do { \ + release_firmware(_fw); \ + _fw = NULL; \ + } while (0) + +/*----------------------------------------------------------------------------*/ +/* Macros of wake_lock operations for using in Driver Layer */ +/*----------------------------------------------------------------------------*/ +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) +/* CONFIG_ANDROID is 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) + +#define KAL_WAKE_LOCK_ACTIVE(_prAdapter, _prWakeLock) \ + wake_lock_active(_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) +#define KAL_WAKE_LOCK_ACTIVE(_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) { \ + if (in_interrupt()) \ + pvAddr = kmalloc(u4Size, GFP_ATOMIC); \ + else \ + pvAddr = kmalloc(u4Size, GFP_KERNEL); \ + } \ + else { \ + pvAddr = vmalloc(u4Size); \ + } \ + if (pvAddr) { \ + allocatedMemSize += u4Size; \ + DBGLOG(INIT, INFO, "0x%p(%ld) allocated (%s:%s)\n", \ + pvAddr, (UINT_32)u4Size, __FILE__, __func__); \ + } \ + pvAddr; \ +}) +#else +#define kalMemAlloc(u4Size, eMemType) ({ \ + void *pvAddr; \ + if (eMemType == PHY_MEM_TYPE) { \ + if (in_interrupt()) \ + pvAddr = kmalloc(u4Size, GFP_ATOMIC); \ + else \ + pvAddr = kmalloc(u4Size, GFP_KERNEL); \ + } \ + else { \ + pvAddr = vmalloc(u4Size); \ + } \ + pvAddr; \ +}) +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Free allocated cache memory +* +* \param[in] pvAddr Required memory size. +* \param[in] eMemType Memory allocation type +* \param[in] u4Size Allocated memory size. +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +#if DBG +#define kalMemFree(pvAddr, eMemType, u4Size) \ +{ \ + if (pvAddr) { \ + allocatedMemSize -= u4Size; \ + DBGLOG(INIT, INFO, "0x%p(%ld) freed (%s:%s)\n", \ + pvAddr, (UINT_32)u4Size, __FILE__, __func__); \ + } \ + if (eMemType == PHY_MEM_TYPE) { \ + kfree(pvAddr); \ + } \ + else { \ + vfree(pvAddr); \ + } \ +} +#else +#define kalMemFree(pvAddr, eMemType, u4Size) \ +{ \ + if (eMemType == PHY_MEM_TYPE) { \ + kfree(pvAddr); \ + } \ + else { \ + vfree(pvAddr); \ + } \ +} +#endif + +#define kalUdelay(u4USec) udelay(u4USec) + +#define kalMdelay(u4MSec) mdelay(u4MSec) +#define kalMsleep(u4MSec) msleep(u4MSec) + +/* Copy memory from user space to kernel space */ +#define kalMemCopyFromUser(_pvTo, _pvFrom, _u4N) copy_from_user(_pvTo, _pvFrom, _u4N) + +/* Copy memory from kernel space to user space */ +#define kalMemCopyToUser(_pvTo, _pvFrom, _u4N) copy_to_user(_pvTo, _pvFrom, _u4N) + +/* Copy memory block with specific size */ +#define kalMemCopy(pvDst, pvSrc, u4Size) memcpy(pvDst, pvSrc, u4Size) + +/* Set memory block with specific pattern */ +#define kalMemSet(pvAddr, ucPattern, u4Size) memset(pvAddr, ucPattern, u4Size) + +/* Compare two memory block with specific length. + * Return zero if they are the same. + */ +#define kalMemCmp(pvAddr1, pvAddr2, u4Size) memcmp(pvAddr1, pvAddr2, u4Size) + +/* Zero specific memory block */ +#define kalMemZero(pvAddr, u4Size) memset(pvAddr, 0, u4Size) + +/* Move memory block with specific size */ +#define kalMemMove(pvDst, pvSrc, u4Size) memmove(pvDst, pvSrc, u4Size) + +#if KERNEL_VERSION(4, 0, 0) <= LINUX_VERSION_CODE +#define strnicmp(s1, s2, n) strncasecmp(s1, s2, n) +#endif + +/* string operation */ +#define kalStrCpy(dest, src) strcpy(dest, src) +#define kalStrnCpy(dest, src, n) strncpy(dest, src, n) +#define kalStrCmp(ct, cs) strcmp(ct, cs) +#define kalStrnCmp(ct, cs, n) strncmp(ct, cs, n) +#define kalStrChr(s, c) strchr(s, c) +#define kalStrrChr(s, c) strrchr(s, c) +#define kalStrnChr(s, n, c) strnchr(s, n, c) +#define kalStrLen(s) strlen(s) +#define kalStrnLen(s, b) strnlen(s, b) +/* #define kalStrniCmp(s, n) strnicmp(s, n) */ +/* #define kalStrtoul(cp, endp, base) simple_strtoul(cp, endp, base) */ +/* #define kalStrtol(cp, endp, base) simple_strtol(cp, endp, base) */ +#define kalkStrtou8(cp, base, resp) kstrtou8(cp, base, resp) +#define kalkStrtou16(cp, base, resp) kstrtou16(cp, base, resp) +#define kalkStrtou32(cp, base, resp) kstrtou32(cp, base, resp) +#define kalkStrtos32(cp, base, resp) kstrtos32(cp, base, resp) +#define kalSnprintf(buf, size, fmt, ...) snprintf(buf, size, fmt, ##__VA_ARGS__) +#define kalScnprintf(buf, size, fmt, ...) scnprintf(buf, size, fmt, ##__VA_ARGS__) +#define kalSprintf(buf, fmt, ...) sprintf(buf, fmt, __VA_ARGS__) +/* remove for AOSP */ +/* #define kalSScanf(buf, fmt, ...) sscanf(buf, fmt, __VA_ARGS__) */ +#define kalStrStr(ct, cs) strstr(ct, cs) +#define kalStrSep(s, ct) strsep(s, ct) +#define kalStrCat(dest, src) strcat(dest, src) +#define kalIsXdigit(c) isxdigit(c) + +/* defined for wince sdio driver only */ +#if defined(_HIF_SDIO) +#define kalDevSetPowerState(prGlueInfo, ePowerMode) glSetPowerState(prGlueInfo, ePowerMode) +#else +#define kalDevSetPowerState(prGlueInfo, ePowerMode) +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Notify OS with SendComplete event of the specific packet. Linux should +* free packets here. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pvPacket Pointer of Packet Handle +* \param[in] status Status Code for OS upper layer +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +#define kalSendComplete(prGlueInfo, pvPacket, status) \ + kalSendCompleteAndAwakeQueue(prGlueInfo, pvPacket) + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to locate the starting address of incoming ethernet +* frame for skb. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pvPacket Pointer of Packet Handle +* +* \return starting address of ethernet frame buffer. +*/ +/*----------------------------------------------------------------------------*/ +#define kalQueryBufferPointer(prGlueInfo, pvPacket) \ + ((PUINT_8)((struct sk_buff *)pvPacket)->data) + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to query the length of valid buffer which is accessible during +* port read/write. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pvPacket Pointer of Packet Handle +* +* \return starting address of ethernet frame buffer. +*/ +/*----------------------------------------------------------------------------*/ +#define kalQueryValidBufferLength(prGlueInfo, pvPacket) \ + ((UINT_32)((struct sk_buff *)pvPacket)->end - \ + (UINT_32)((struct sk_buff *)pvPacket)->data) + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to copy the entire frame from skb to the destination +* address in the input parameter. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pvPacket Pointer of Packet Handle +* \param[in] pucDestBuffer Destination Address +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +#define kalCopyFrame(prGlueInfo, pvPacket, pucDestBuffer) \ + do {struct sk_buff *skb = (struct sk_buff *)pvPacket; \ + memcpy(pucDestBuffer, skb->data, skb->len); } while (0) + +#define kalGetTimeTick() jiffies_to_msecs(jiffies) + +#define WLAN_TAG "[wlan]" +#define kalPrint(_Fmt...) printk(WLAN_TAG _Fmt) +#define limitedKalPrint(_Fmt...)\ + pr_info_ratelimited(WLAN_TAG _Fmt) + +#define kalBreakPoint() \ +do { \ + WARN_ON(1); \ + panic("Oops"); \ +} while (0) + +#if CFG_ENABLE_AEE_MSG +#define kalSendAeeException aee_kernel_exception +#define kalSendAeeWarning aee_kernel_warning +#define kalSendAeeReminding aee_kernel_reminding +#else +#define kalSendAeeException(_module, _desc, ...) +#define kalSendAeeWarning(_module, _desc, ...) +#define kalSendAeeReminding(_module, _desc, ...) +#endif + +#define PRINTF_ARG(...) __VA_ARGS__ +#define SPRINTF(buf, arg) {buf += sprintf((char *)(buf), PRINTF_ARG arg); } + +#define USEC_TO_SYSTIME(_usec) ((_usec) / USEC_PER_MSEC) +#define MSEC_TO_SYSTIME(_msec) (_msec) + +#define MSEC_TO_JIFFIES(_msec) msecs_to_jiffies(_msec) + +#define KAL_TIME_INTERVAL_DECLARATION() struct timeval __rTs, __rTe +#define KAL_REC_TIME_START() do_gettimeofday(&__rTs) +#define KAL_REC_TIME_END() do_gettimeofday(&__rTe) +#define KAL_GET_TIME_INTERVAL() \ + ((SEC_TO_USEC(__rTe.tv_sec) + __rTe.tv_usec) - (SEC_TO_USEC(__rTs.tv_sec) + __rTs.tv_usec)) +#define KAL_ADD_TIME_INTERVAL(_Interval) \ + { \ + (_Interval) += KAL_GET_TIME_INTERVAL(); \ + } + +#define KAL_GET_HOST_CLOCK() local_clock() + +/******************************************************************************* +* 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 PULONG plFlags); + +VOID kalReleaseSpinLock(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, IN ULONG ulFlags); + +VOID kalUpdateMACAddress(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucMacAddr); + +VOID kalAcquireMutex(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_MUTEX_CATEGORY_E rMutexCategory); + +VOID kalReleaseMutex(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_MUTEX_CATEGORY_E rMutexCategory); + +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); + +WLAN_STATUS kalRxIndicateOnePkt(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPkt); + +VOID +kalIndicateStatusAndComplete(IN P_GLUE_INFO_T prGlueInfo, IN WLAN_STATUS eStatus, IN PVOID pvBuf, IN UINT_32 u4BufLen); + +VOID +kalUpdateReAssocReqInfo(IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBody, IN UINT_32 u4FrameBodyLen, IN BOOLEAN fgReassocRequest); + +VOID kalUpdateReAssocRspInfo(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucFrameBody, IN UINT_32 u4FrameBodyLen); + +#if CFG_TX_FRAGMENT +BOOLEAN +kalQueryTxPacketHeader(IN P_GLUE_INFO_T prGlueInfo, + IN PVOID pvPacket, OUT PUINT_16 pu2EtherTypeLen, OUT PUINT_8 pucEthDestAddr); +#endif /* CFG_TX_FRAGMENT */ + +VOID kalSendCompleteAndAwakeQueue(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +VOID kalQueryTxChksumOffloadParam(IN PVOID pvPacket, OUT PUINT_8 pucFlag); + +VOID kalUpdateRxCSUMOffloadParam(IN PVOID pvPacket, IN ENUM_CSUM_RESULT_T eCSUM[]); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +BOOLEAN kalRetrieveNetworkAddress(IN P_GLUE_INFO_T prGlueInfo, IN OUT PARAM_MAC_ADDRESS *prMacAddr); + +VOID +kalReadyOnChannel(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, + IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_8 ucChannelNum, IN UINT_32 u4DurationMs); + +VOID +kalRemainOnChannelExpired(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_8 ucChannelNum); + +#if CFG_SUPPORT_DFS +VOID +kalIndicateChannelSwitch(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_CHNL_EXT_T eSco, + IN UINT_8 ucChannelNum); +#endif + +VOID +kalIndicateMgmtTxStatus(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, IN BOOLEAN fgIsAck, IN PUINT_8 pucFrameBuf, IN UINT_32 u4FrameLen); + +VOID kalIndicateRxMgmtFrame(IN P_GLUE_INFO_T prGlueInfo, IN P_SW_RFB_T prSwRfb); + +/*----------------------------------------------------------------------------*/ +/* Routines in interface - ehpi/sdio.c */ +/*----------------------------------------------------------------------------*/ +BOOL kalDevRegRead(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Register, OUT PUINT_32 pu4Value); +BOOL kalDevRegRead_mac(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 kalDevRegWrite_mac(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_32 u2Len, OUT PUINT_8 pucBuf, IN UINT_32 u2ValidOutBufSize); + +BOOL +kalDevPortWrite(P_GLUE_INFO_T prGlueInfo, + IN UINT_16 u2Port, IN UINT_32 u2Len, IN PUINT_8 pucBuf, IN UINT_32 u2ValidInBufSize); + +BOOL kalDevWriteData(IN P_GLUE_INFO_T prGlueInfo, IN P_MSDU_INFO_T prMsduInfo); +BOOL kalDevWriteCmd(IN P_GLUE_INFO_T prGlueInfo, IN P_CMD_INFO_T prCmdInfo, IN UINT_8 ucTC); +BOOL kalDevKickData(IN P_GLUE_INFO_T prGlueInfo); +VOID kalDevReadIntStatus(IN P_ADAPTER_T prAdapter, OUT PUINT_32 pu4IntStatus); + +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 + +BOOLEAN +kalQoSFrameClassifierAndPacketInfo(IN P_GLUE_INFO_T prGlueInfo, + IN P_NATIVE_PACKET prPacket, OUT P_TX_PACKET_INFO prTxPktInfo); + +BOOLEAN kalGetEthDestAddr(IN P_GLUE_INFO_T prGlueInfo, IN P_NATIVE_PACKET prPacket, OUT PUINT_8 pucEthDestAddr); + +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, OUT PUINT_32 pu4QryInfoLen); + +WLAN_STATUS +kalIoctlTimeout(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 INT_32 i4OidTimeout, + OUT PUINT_32 pu4QryInfoLen); + +VOID kalHandleAssocInfo(IN P_GLUE_INFO_T prGlueInfo, IN P_EVENT_ASSOC_INFO prAssocInfo); + +#if CFG_ENABLE_FW_DOWNLOAD +WLAN_STATUS kalFirmwareOpen(IN P_GLUE_INFO_T prGlueInfo, IN PPUINT_8 apucNameTable); +WLAN_STATUS kalFirmwareClose(IN P_GLUE_INFO_T prGlueInfo); +WLAN_STATUS kalFirmwareLoad(IN P_GLUE_INFO_T prGlueInfo, OUT PVOID prBuf, IN UINT_32 u4Offset, OUT PUINT_32 pu4Size); +WLAN_STATUS kalFirmwareSize(IN P_GLUE_INFO_T prGlueInfo, OUT PUINT_32 pu4Size); +VOID kalConstructDefaultFirmwarePrio(P_GLUE_INFO_T prGlueInfo, PPUINT_8 apucNameTable, + PPUINT_8 apucName, PUINT_8 pucNameIdx, UINT_8 ucMaxNameIdx); +PVOID kalFirmwareImageMapping(IN P_GLUE_INFO_T prGlueInfo, + OUT PPVOID ppvMapFileBuf, OUT PUINT_32 pu4FileLength, IN ENUM_IMG_DL_IDX_T eDlIdx); +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 */ + +/*----------------------------------------------------------------------------*/ +/* Security Frame Clearance */ +/*----------------------------------------------------------------------------*/ +VOID kalClearSecurityFrames(IN P_GLUE_INFO_T prGlueInfo); + +VOID kalClearSecurityFramesByBssIdx(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucBssIndex); + +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 kalClearMgmtFramesByBssIdx(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucBssIndex); + +UINT_32 kalGetTxPendingFrameCount(IN P_GLUE_INFO_T prGlueInfo); + +UINT_32 kalGetTxPendingCmdCount(IN P_GLUE_INFO_T prGlueInfo); + +VOID kalClearCommandQueue(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); + +#if KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE +void kalTimeoutHandler(struct timer_list *timer); +#else +VOID kalTimeoutHandler(unsigned long arg); +#endif +VOID kalSetEvent(P_GLUE_INFO_T pr); + +VOID kalSetIntEvent(P_GLUE_INFO_T pr); + +#if CFG_SUPPORT_MULTITHREAD +VOID kalSetTxEvent2Hif(P_GLUE_INFO_T pr); + +VOID kalSetTxEvent2Rx(P_GLUE_INFO_T pr); + +VOID kalSetTxCmdEvent2Hif(P_GLUE_INFO_T pr); +#endif +/*----------------------------------------------------------------------------*/ +/* 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(BOOLEAN is_pre_alloc); + +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); +UINT_8 kalGetRsnIeMfpCap(IN P_GLUE_INFO_T prGlueInfo); +#endif + +/*----------------------------------------------------------------------------*/ +/* file opetation */ +/*----------------------------------------------------------------------------*/ +UINT_32 kalWriteToFile(const PUINT_8 pucPath, BOOLEAN fgDoAppend, PUINT_8 pucData, UINT_32 u4Size); + +UINT_32 kalCheckPath(const PUINT_8 pucPath); + +UINT_32 kalTrunkPath(const PUINT_8 pucPath); + +INT_32 kalReadToFile(const PUINT_8 pucPath, PUINT_8 pucData, UINT_32 u4Size, PUINT_32 pu4ReadSize); + +INT_32 kalRequestFirmware(const PUINT_8 pucPath, PUINT_8 pucData, UINT_32 u4Size, + PUINT_32 pu4ReadSize, struct device *dev); + + +/*----------------------------------------------------------------------------*/ +/* 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); + +/*----------------------------------------------------------------------------*/ +/* Net device */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +kalHardStartXmit(struct sk_buff *prSkb, IN struct net_device *prDev, P_GLUE_INFO_T prGlueInfo, UINT_8 ucBssIndex); + +BOOLEAN +kalIsPairwiseEapolPacket(IN P_NATIVE_PACKET prPacket); + +BOOLEAN +kalGetIPv4Address(IN struct net_device *prDev, + IN UINT_32 u4MaxNumOfAddr, OUT PUINT_8 pucIpv4Addrs, OUT PUINT_32 pu4NumOfIpv4Addr); + +#if IS_ENABLED(CONFIG_IPV6) +BOOLEAN +kalGetIPv6Address(IN struct net_device *prDev, + IN UINT_32 u4MaxNumOfAddr, OUT PUINT_8 pucIpv6Addrs, OUT PUINT_32 pu4NumOfIpv6Addr); +#else +static inline BOOLEAN +kalGetIPv6Address(IN struct net_device *prDev, + IN UINT_32 u4MaxNumOfAddr, OUT PUINT_8 pucIpv6Addrs, OUT PUINT_32 pu4NumOfIpv6Addr) { + /* Not support IPv6 */ + *pu4NumOfIpv6Addr = 0; + return FALSE; +} +#endif /* IS_ENABLED(CONFIG_IPV6) */ + +VOID kalSetNetAddressFromInterface(IN P_GLUE_INFO_T prGlueInfo, IN struct net_device *prDev, IN BOOLEAN fgSet); + +WLAN_STATUS kalResetStats(IN struct net_device *prDev); + +PVOID kalGetStats(IN struct net_device *prDev); + +VOID kalResetPacket(IN P_GLUE_INFO_T prGlueInfo, IN P_NATIVE_PACKET prPacket); + +#if CFG_SUPPORT_QA_TOOL +struct file *kalFileOpen(const char *path, int flags, int rights); + +VOID kalFileClose(struct file *file); + +UINT_32 kalFileRead(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size); +#endif + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN +/*----------------------------------------------------------------------------*/ +/* SDIO Read/Write Pattern Support */ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalSetSdioTestPattern(IN P_GLUE_INFO_T prGlueInfo, IN BOOLEAN fgEn, IN BOOLEAN fgRead); +#endif + +/*----------------------------------------------------------------------------*/ +/* PNO Support */ +/*----------------------------------------------------------------------------*/ +VOID kalSchedScanResults(IN P_GLUE_INFO_T prGlueInfo); + +VOID kalSchedScanStopped(IN P_GLUE_INFO_T prGlueInfo); + +#if CFG_MULTI_ECOVER_SUPPORT + +#if 0 +typedef enum _ENUM_WMTHWVER_TYPE_T { + WMTHWVER_E1 = 0x0, + WMTHWVER_E2 = 0x1, + WMTHWVER_E3 = 0x2, + WMTHWVER_E4 = 0x3, + WMTHWVER_E5 = 0x4, + WMTHWVER_E6 = 0x5, + WMTHWVER_MAX, + WMTHWVER_INVALID = 0xff +} ENUM_WMTHWVER_TYPE_T, *P_ENUM_WMTHWVER_TYPE_T; + +extern ENUM_WMTHWVER_TYPE_T mtk_wcn_wmt_hwver_get(VOID); + +#else + +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; + +UINT_32 mtk_wcn_wmt_ic_info_get(ENUM_WMT_CHIPINFO_TYPE_T type); + +#endif + +#endif + +VOID kalSetFwOwnEvent2Hif(P_GLUE_INFO_T pr); +#if CFG_ASSERT_DUMP +/* Core Dump out put file */ +WLAN_STATUS kalOpenCorDumpFile(BOOLEAN fgIsN9); +WLAN_STATUS kalWriteCorDumpFile(PUINT_8 pucBuffer, UINT_16 u2Size, BOOLEAN fgIsN9); +WLAN_STATUS kalCloseCorDumpFile(BOOLEAN fgIsN9); +#endif +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#if CFG_WOW_SUPPORT +VOID kalWowInit(IN P_GLUE_INFO_T prGlueInfo); +VOID kalWowProcess(IN P_GLUE_INFO_T prGlueInfo, UINT_8 enable); +void kalMdnsProcess(IN P_GLUE_INFO_T prGlueInfo, + IN struct MDNS_PARAM_T *prMdnsParam); +#endif + +int main_thread(void *data); + +#if CFG_SUPPORT_MULTITHREAD +int hif_thread(void *data); +int rx_thread(void *data); +#endif +UINT_64 kalGetBootTime(VOID); + +int kalMetInitProcfs(IN P_GLUE_INFO_T prGlueInfo); +int kalMetRemoveProcfs(IN P_GLUE_INFO_T prGlueInfo); + +VOID kalFreeTxMsduWorker(struct work_struct *work); +VOID kalFreeTxMsdu(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + +#if KERNEL_VERSION(3, 0, 0) <= LINUX_VERSION_CODE +/* since: 0b5c9db1b11d3175bb42b80663a9f072f801edf5 */ +static inline void kal_skb_reset_mac_len(struct sk_buff *skb) +{ + skb_reset_mac_len(skb); +} +#else +static inline void kal_skb_reset_mac_len(struct sk_buff *skb) +{ + skb->mac_len = skb->network_header - skb->mac_header; +} +#endif + +static inline UINT_64 kalDivU64(UINT_64 dividend, UINT_32 divisor) +{ + return div_u64(dividend, divisor); +} + +VOID kalInitDevWakeup(P_ADAPTER_T prAdapter, struct device *prDev); + + +#endif /* _GL_KAL_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_os.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_os.h new file mode 100644 index 0000000000000..66c036529247d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_os.h @@ -0,0 +1,1114 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_os.h#4 +*/ + +/*! \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. +*/ + + +#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 */ + +/* 1: Enable use of SPIN LOCK Bottom Half for LINUX */ +/* 0: Disable - use SPIN LOCK IRQ SAVE instead */ +#define CFG_USE_SPIN_LOCK_BOTTOM_HALF 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_PADDING_SMALL_ETH_PACKET 0 + +#define CFG_TX_STOP_NETIF_QUEUE_THRESHOLD 256 /* packets */ + +#define CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD 512 /* packets */ +#define CFG_TX_START_NETIF_PER_QUEUE_THRESHOLD 128 /* packets */ + +/* WMM Certification Related */ +#define CFG_CERT_WMM_MAX_TX_PENDING 20 +#define CFG_CERT_WMM_MAX_RX_NUM 10 +#define CFG_CERT_WMM_HIGH_STOP_TX_WITH_RX (CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD * 3) +#define CFG_CERT_WMM_HIGH_STOP_TX_WO_RX (CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD * 2) +#define CFG_CERT_WMM_LOW_STOP_TX_WITH_RX (CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD >> 4) +#define CFG_CERT_WMM_LOW_STOP_TX_WO_RX (CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD >> 3) + +#define CHIP_NAME "MT6632" + +#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) +/* for non-wfa vendor specific IE buffer */ +#define NON_WFA_VENDOR_IE_MAX_LEN (128) + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include /* constant of kernel version */ + +#include /* bitops.h */ + +#if KERNEL_VERSION(4, 11, 0) <= LINUX_VERSION_CODE +#include /* sched_setscheduler */ +#include +#endif +#include /* struct timer_list */ +#include /* jiffies */ +#include /* udelay and mdelay macro */ + +#ifdef CONFIG_HAS_WAKELOCK +#include +#endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 12) +#include /* IRQT_FALLING */ +#endif + +#include /* struct net_device, struct net_device_stats */ +#include /* for eth_type_trans() function */ +#include /* struct iw_statistics */ +#include +#include /* struct in_device */ + +#include /* struct iphdr */ + +#include /* for memcpy()/memset() function */ +#include /* for offsetof() macro */ + +#include /* The proc filesystem constants/structures */ + +#include /* for rtnl_lock() and rtnl_unlock() */ +#include /* kthread_should_stop(), kthread_run() */ +#include /* for copy_from_user() */ +#include /* for firmware download */ +#include + +#include /* for kfifo interface */ +#include /* for cdev interface */ + +#include /* for firmware download */ +#include + +#include + +#if KERNEL_VERSION(4, 11, 0) <= LINUX_VERSION_CODE +#include +#endif + +#if defined(_HIF_USB) +#include +#include +#include +#endif + +#if defined(_HIF_PCIE) +#include +#endif + +#if defined(_HIF_SDIO) +#include +#include +#include +#endif + +#include + +#include /* readw and writew */ + +#if WIRELESS_EXT > 12 +#include +#endif + +#include + +#ifdef CFG_CFG80211_VERSION +#define CFG80211_VERSION_CODE CFG_CFG80211_VERSION +#else +#define CFG80211_VERSION_CODE LINUX_VERSION_CODE +#endif + +#include "version.h" +#include "config.h" + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#include +#include +#endif + +#include +#include +#include + +#if IS_ENABLED(CONFIG_IPV6) +#include +#include +#include +#endif + +#if CFG_SUPPORT_PASSPOINT +#include +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE +#include +#endif + +#include "gl_typedef.h" +#include "typedef.h" +#include "queue.h" +#include "gl_kal.h" +#include "gl_rst.h" +#include "hif.h" + +#if CFG_SUPPORT_TDLS +#include "tdls.h" +#endif + +#include "debug.h" + +#include "wlan_lib.h" +#include "wlan_oid.h" + +#if CFG_ENABLE_AEE_MSG +#ifdef CONFIG_ANDROID +#include +#else +#include +#endif +#endif + +#if CFG_MET_TAG_SUPPORT +#include +#endif +#include + +extern BOOLEAN fgIsBusAccessFailed; +extern const struct ieee80211_iface_combination *p_mtk_iface_combinations_sta; +extern const INT_32 mtk_iface_combinations_sta_num; +extern struct wireless_dev *gprWdev; + +/******************************************************************************* +* 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_MULTICAST BIT(7) +#define GLUE_FLAG_FRAME_FILTER BIT(8) +#define GLUE_FLAG_FRAME_FILTER_AIS BIT(9) + +#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_MULTICAST_BIT (7) +#define GLUE_FLAG_FRAME_FILTER_BIT (8) +#define GLUE_FLAG_FRAME_FILTER_AIS_BIT (9) + +#if CFG_SUPPORT_MULTITHREAD +#define GLUE_FLAG_RX BIT(10) +#define GLUE_FLAG_TX_CMD_DONE BIT(11) +#define GLUE_FLAG_HIF_TX BIT(12) +#define GLUE_FLAG_HIF_TX_CMD BIT(13) +#define GLUE_FLAG_RX_TO_OS BIT(14) +#define GLUE_FLAG_HIF_FW_OWN BIT(15) +#define GLUE_FLAG_HIF_PRT_HIF_DBG_INFO BIT(16) + +#define GLUE_FLAG_RX_BIT (10) +#define GLUE_FLAG_TX_CMD_DONE_BIT (11) +#define GLUE_FLAG_HIF_TX_BIT (12) +#define GLUE_FLAG_HIF_TX_CMD_BIT (13) +#define GLUE_FLAG_RX_TO_OS_BIT (14) +#define GLUE_FLAG_HIF_FW_OWN_BIT (15) +#define GLUE_FLAG_HIF_PRT_HIF_DBG_INFO_BIT (16) +#endif + +#define GLUE_BOW_KFIFO_DEPTH (1024) +/* #define GLUE_BOW_DEVICE_NAME "MT6620 802.11 AMP" */ +#define GLUE_BOW_DEVICE_NAME "ampc0" + +#define WAKE_LOCK_RX_TIMEOUT 300 /* ms */ +#define WAKE_LOCK_THREAD_WAKEUP_TIMEOUT 50 /* ms */ + +/* EFUSE Auto Mode Support */ +#define LOAD_EFUSE 0 +#define LOAD_EEPROM_BIN 1 +#define LOAD_AUTO 2 + +#if CFG_SUPPORT_CFG80211_AUTH +#if KERNEL_VERSION(4, 0, 0) > CFG80211_VERSION_CODE +#define WLAN_CIPHER_SUITE_GCMP_256 0x000FAC09 +#define WLAN_CIPHER_SUITE_CCMP_256 0x000FAC0A +#define WLAN_CIPHER_SUITE_BIP_GMAC_128 0x000FAC0B +#define WLAN_CIPHER_SUITE_BIP_GMAC_256 0x000FAC0C +#define WLAN_CIPHER_SUITE_BIP_CMAC_256 0x000FAC0D +#endif + +#if KERNEL_VERSION(4, 12, 0) > CFG80211_VERSION_CODE +#define WLAN_AKM_SUITE_8021X_SUITE_B 0x000FAC0B +#define WLAN_AKM_SUITE_8021X_SUITE_B_192 0x000FAC0C +#endif + +#if KERNEL_VERSION(4, 2, 0) > CFG80211_VERSION_CODE +#if CFG_SUPPORT_SAE +#define WLAN_AKM_SUITE_SAE 0x000FAC08 +#endif +#endif + +#if CFG_SUPPORT_OWE +#define WLAN_AKM_SUITE_OWE 0x000FAC12 +#endif + +#define IW_AUTH_CIPHER_GCMP256 0x00000080 +#endif + +/******************************************************************************* +* 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 u4CipherGroupMgmt; + UINT_32 u4Mfp; + UINT_8 ucRSNMfpCap; +#endif + UINT_8 ucRsneLen; + UINT_8 aucKek[NL80211_KEK_LEN]; + UINT_8 aucKck[NL80211_KCK_LEN]; + UINT_8 aucReplayCtr[NL80211_REPLAY_CTR_LEN]; +} GL_WPA_INFO_T, *P_GL_WPA_INFO_T; + +#if CFG_SUPPORT_REPLAY_DETECTION +struct SEC_REPLEY_PN_INFO { + UINT_8 auPN[16]; + BOOLEAN fgRekey; + BOOLEAN fgFirstPkt; +}; +struct SEC_DETECT_REPLAY_INFO { + UINT_8 ucCurKeyId; + UINT_8 ucKeyType; + struct SEC_REPLEY_PN_INFO arReplayPNInfo[4]; + UINT_32 u4KeyLength; + UINT_8 aucKeyMaterial[32]; + BOOLEAN fgPairwiseInstalled; + BOOLEAN fgKeyRscFresh; +}; +#endif + +typedef enum _ENUM_NET_DEV_IDX_T { + NET_DEV_WLAN_IDX = 0, + NET_DEV_P2P_IDX, + NET_DEV_BOW_IDX, + NET_DEV_NUM +} ENUM_NET_DEV_IDX_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_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 enum _ENUM_PKT_FLAG_T { + ENUM_PKT_802_11, /* 802.11 or non-802.11 */ + ENUM_PKT_802_3, /* 802.3 or ethernetII */ + ENUM_PKT_1X, /* 1x frame or not */ + ENUM_PKT_PROTECTED_1X, /* protected 1x frame */ + ENUM_PKT_NON_PROTECTED_1X, /* Non protected 1x frame */ + ENUM_PKT_VLAN_EXIST, /* VLAN tag exist */ + ENUM_PKT_DHCP, /* DHCP frame */ + ENUM_PKT_ARP, /* ARP */ + ENUM_PKT_FLAG_NUM +} ENUM_PKT_FLAG_T; + +typedef struct _GL_IO_REQ_T { + QUE_ENTRY_T rQueEntry; + /* wait_queue_head_t cmdwait_q; */ + BOOL fgRead; + BOOL fgWaitResp; + P_ADAPTER_T prAdapter; + PFN_OID_HANDLER_FUNC pfnOidHandler; + PVOID pvInfoBuf; + UINT_32 u4InfoBufLen; + PUINT_32 pu4QryInfoLen; + WLAN_STATUS rStatus; + UINT_32 u4Flag; + UINT_32 u4Timeout; +} 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; +typedef struct _GL_P2P_DEV_INFO_T GL_P2P_DEV_INFO_T, *P_GL_P2P_DEV_INFO_T; + +struct _GLUE_INFO_T { + /* Device handle */ + struct net_device *prDevHandler; + + /* Device */ + struct device *prDev; + + /* 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]; + + /* Mutex to protect interruptible section */ + struct mutex arMutex[MUTEX_NUM]; + + /* semaphore for ioctl */ + struct semaphore ioctl_sem; + + UINT_64 u8Cookie; + + atomic_t cfgSuspend; + + ULONG ulFlag; /* GLUE_FLAG_XXX */ + UINT_32 u4PendFlag; + /* UINT_32 u4TimeoutFlag; */ + UINT_32 u4OidCompleteFlag; + UINT_32 u4ReadyFlag; /* check if card is ready */ + + UINT_32 u4OsMgmtFrameFilter; + + /* Number of pending frames, also used for debuging if any frame is + * missing during the process of unloading Driver. + * + * NOTE(Kevin): In Linux, we also use this variable as the threshold + * for manipulating the netif_stop(wake)_queue() func. + */ + INT_32 ai4TxPendingFrameNumPerQueue[HW_BSSID_NUM][CFG_MAX_TXQ_NUM]; + INT_32 i4TxPendingFrameNum; + INT_32 i4TxPendingSecurityFrameNum; + INT_32 i4TxPendingCmdNum; + + /* Tx: for NetDev to BSS index mapping */ + NET_INTERFACE_INFO_T arNetInterfaceInfo[HW_BSSID_NUM]; + + /* Rx: for BSS index to NetDev mapping */ + /* P_NET_INTERFACE_INFO_T aprBssIdxToNetInterfaceInfo[HW_BSSID_NUM]; */ + + /* 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; +#if CFG_SUPPORT_REPLAY_DETECTION + struct SEC_DETECT_REPLAY_INFO prDetRplyInfo; +#endif + + /* 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_SUPPORT_MULTITHREAD + struct completion rHifHaltComp; /* indicate hif_thread halt complete */ + struct completion rRxHaltComp; /* indicate hif_thread halt complete */ + + UINT_32 u4TxThreadPid; + UINT_32 u4RxThreadPid; + UINT_32 u4HifThreadPid; +#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; + +#if CFG_SUPPORT_MULTITHREAD + wait_queue_head_t waitq_hif; + struct task_struct *hif_thread; + + wait_queue_head_t waitq_rx; + struct task_struct *rx_thread; + +#endif + struct tasklet_struct rRxTask; + struct tasklet_struct rTxCompleteTask; + + struct work_struct rTxMsduFreeWork; + struct delayed_work rRxPktDeAggWork; + + 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_DEV_INFO_T prP2PDevInfo; + P_GL_P2P_INFO_T prP2PInfo[KAL_P2P_NUM]; +#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 Overridden by IOCTL */ + BOOLEAN fgIsMacAddrOverride; + PARAM_MAC_ADDRESS rMacAddrOverride; + + SET_TXPWR_CTRL_T rTxPwr; + + /* for cfg80211 scan done indication */ + struct cfg80211_scan_request *prScanRequest; + + /* for cfg80211 scheduled scan */ + struct cfg80211_sched_scan_request *prSchedScanRequest; + + /* to indicate registered or not */ + BOOLEAN fgIsRegistered; + + /* for cfg80211 connected indication */ + UINT_32 u4RspIeLength; + UINT_8 aucRspIe[CFG_CFG80211_IE_BUF_LEN]; + + UINT_32 u4ReqIeLength; + UINT_8 aucReqIe[CFG_CFG80211_IE_BUF_LEN]; + + /* + * buffer to hold non-wfa vendor specific IEs set + * from wpa_supplicant. This is used in sending + * Association Request in AIS mode. + */ + u32 non_wfa_vendor_ie_len; + u8 non_wfa_vendor_ie_buf[NON_WFA_VENDOR_IE_MAX_LEN]; + +#if CFG_SUPPORT_SDIO_READ_WRITE_PATTERN + BOOLEAN fgEnSdioTestPattern; + BOOLEAN fgSdioReadWriteMode; + BOOLEAN fgIsSdioTestInitialized; + UINT_8 aucSdioTestBuffer[256]; +#endif + + BOOLEAN fgIsInSuspendMode; + +#if CFG_SUPPORT_PASSPOINT + UINT_8 aucHS20AssocInfoIE[200]; /*for Assoc req */ + UINT_16 u2HS20AssocInfoIELen; + UINT_8 ucHotspotConfig; + BOOLEAN fgConnectHS20AP; + + BOOLEAN fgIsDad; + UINT_8 aucDADipv4[4]; + BOOLEAN fgIs6Dad; + UINT_8 aucDADipv6[16]; +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + KAL_WAKE_LOCK_T rIntrWakeLock; + KAL_WAKE_LOCK_T rTimeoutWakeLock; +#endif + +#if CFG_MET_PACKET_TRACE_SUPPORT + BOOLEAN fgMetProfilingEn; + UINT_16 u2MetUdpPort; +#endif + +#if CFG_SUPPORT_SNIFFER + BOOLEAN fgIsEnableMon; + struct net_device *prMonDevHandler; + struct work_struct monWork; +#endif + + INT_32 i4RssiCache; + UINT_32 u4LinkSpeedCache; + + /* FW Roaming */ + /* store the FW roaming enable state which FWK determines */ + /* if it's = 0, ignore the black/whitelists settings from FWK */ + UINT_32 u4FWRoamingEnable; + +}; + +typedef irqreturn_t(*PFN_WLANISR) (int irq, void *dev_id, struct pt_regs *regs); + +typedef void (*PFN_LINUX_TIMER_FUNC) (unsigned long); + +/* generic sub module init/exit handler +* now, we only have one sub module, p2p +*/ +#if CFG_ENABLE_WIFI_DIRECT +typedef BOOLEAN(*SUB_MODULE_INIT) (P_GLUE_INFO_T prGlueInfo); +typedef BOOLEAN(*SUB_MODULE_EXIT) (P_GLUE_INFO_T prGlueInfo); + +typedef struct _SUB_MODULE_HANDLER { + SUB_MODULE_INIT subModInit; + SUB_MODULE_EXIT subModExit; + BOOLEAN fgIsInited; +} SUB_MODULE_HANDLER, *P_SUB_MODULE_HANDLER; + +#endif + +#ifdef CONFIG_NL80211_TESTMODE + +enum TestModeCmdType { + TESTMODE_CMD_ID_SW_CMD = 1, + TESTMODE_CMD_ID_WAPI = 2, + TESTMODE_CMD_ID_HS20 = 3, + NUM_OF_TESTMODE_CMD_ID +}; + +#if CFG_SUPPORT_PASSPOINT +enum Hs20CmdType { + HS20_CMD_ID_SET_BSSID_POOL = 0, + NUM_OF_HS20_CMD_ID +}; +#endif /* CFG_SUPPORT_PASSPOINT */ + +typedef struct _NL80211_DRIVER_TEST_MODE_PARAMS { + UINT_32 index; + UINT_32 buflen; +} NL80211_DRIVER_TEST_MODE_PARAMS, *P_NL80211_DRIVER_TEST_MODE_PARAMS; + +/*SW CMD */ +typedef struct _NL80211_DRIVER_SW_CMD_PARAMS { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + UINT_8 set; + UINT_32 adr; + UINT_32 data; +} NL80211_DRIVER_SW_CMD_PARAMS, *P_NL80211_DRIVER_SW_CMD_PARAMS; + +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 */ + /*!< ff:ff:ff:ff:ff:ff for broadcast/multicast + * (group) keys or unicast address for + * individual keys + */ + __u8 addr[MAC_ADDR_LEN]; + __u16 alg; /*!< IW_ENCODE_ALG_* */ + __u16 key_len; + __u8 key[32]; +}; + +/*SET KEY EXT */ +typedef struct _NL80211_DRIVER_SET_KEY_EXTS { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + UINT_8 key_index; + UINT_8 key_len; + struct iw_encode_exts ext; +} NL80211_DRIVER_SET_KEY_EXTS, *P_NL80211_DRIVER_SET_KEY_EXTS; + +#if CFG_SUPPORT_PASSPOINT + +struct param_hs20_set_bssid_pool { + UINT_8 fgBssidPoolIsEnable; + UINT_8 ucNumBssidPool; + UINT_8 arBssidPool[8][ETH_ALEN]; +}; + +struct wpa_driver_hs20_data_s { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + enum Hs20CmdType CmdType; + struct param_hs20_set_bssid_pool hs20_set_bssid_pool; +}; + +#endif /* CFG_SUPPORT_PASSPOINT */ + +#endif + +typedef struct _NETDEV_PRIVATE_GLUE_INFO { + P_GLUE_INFO_T prGlueInfo; + UINT_8 ucBssIdx; +} NETDEV_PRIVATE_GLUE_INFO, *P_NETDEV_PRIVATE_GLUE_INFO; + +typedef struct _PACKET_PRIVATE_DATA { + QUE_ENTRY_T rQueEntry; + UINT_16 u2Flag; + UINT_8 ucTid; + UINT_8 ucBssIdx; + + UINT_8 ucHeaderLen; + UINT_16 u2FrameLen; + + UINT_8 ucProfilingFlag; + OS_SYSTIME rArrivalTime; + UINT_16 u2IpId; +} PACKET_PRIVATE_DATA, *P_PACKET_PRIVATE_DATA; + +/******************************************************************************* +* P U B 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() ULONG __ulFlags = 0 +#define GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, rLockCategory) \ + { \ + if (rLockCategory < SPIN_LOCK_NUM) \ + spin_lock_irqsave(&(prGlueInfo)->rSpinLock[rLockCategory], __ulFlags); \ + } +#define GLUE_RELEASE_SPIN_LOCK(prGlueInfo, rLockCategory) \ + { \ + if (rLockCategory < SPIN_LOCK_NUM) \ + spin_unlock_irqrestore(&(prGlueInfo->rSpinLock[rLockCategory]), __ulFlags); \ + } +#endif /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + +/*----------------------------------------------------------------------------*/ +/* Macros for accessing Reserved Fields of native packet */ +/*----------------------------------------------------------------------------*/ + +#define GLUE_GET_PKT_PRIVATE_DATA(_p) \ + ((P_PACKET_PRIVATE_DATA)(&(((struct sk_buff *)(_p))->cb[0]))) + +#define GLUE_GET_PKT_QUEUE_ENTRY(_p) \ + (&(GLUE_GET_PKT_PRIVATE_DATA(_p)->rQueEntry)) + +#define GLUE_GET_PKT_DESCRIPTOR(_prQueueEntry) \ + ((P_NATIVE_PACKET) (((ULONG)_prQueueEntry) - offsetof(struct sk_buff, cb[0]))) + +#define GLUE_SET_PKT_TID(_p, _tid) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucTid = (UINT_8)(_tid)) + +#define GLUE_GET_PKT_TID(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucTid) + +#define GLUE_SET_PKT_FLAG(_p, _flag) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2Flag |= BIT(_flag)) + +#define GLUE_TEST_PKT_FLAG(_p, _flag) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2Flag & BIT(_flag)) + +#define GLUE_IS_PKT_FLAG_SET(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2Flag) + +#define GLUE_SET_PKT_BSS_IDX(_p, _ucBssIndex) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucBssIdx = (UINT_8)(_ucBssIndex)) + +#define GLUE_GET_PKT_BSS_IDX(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucBssIdx) + +#define GLUE_SET_PKT_HEADER_LEN(_p, _ucMacHeaderLen) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucHeaderLen = (UINT_8)(_ucMacHeaderLen)) + +#define GLUE_GET_PKT_HEADER_LEN(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucHeaderLen) + +#define GLUE_SET_PKT_FRAME_LEN(_p, _u2PayloadLen) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2FrameLen = (UINT_16)(_u2PayloadLen)) + +#define GLUE_GET_PKT_FRAME_LEN(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2FrameLen) + +#define GLUE_SET_PKT_ARRIVAL_TIME(_p, _rSysTime) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->rArrivalTime = (OS_SYSTIME)(_rSysTime)) + +#define GLUE_GET_PKT_ARRIVAL_TIME(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->rArrivalTime) + +#define GLUE_SET_PKT_IP_ID(_p, _u2IpId) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2IpId = (UINT_16)(_u2IpId)) + +#define GLUE_GET_PKT_IP_ID(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->u2IpId) + +#define GLUE_SET_PKT_FLAG_PROF_MET(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucProfilingFlag |= BIT(0)) + +#define GLUE_GET_PKT_IS_PROF_MET(_p) \ + (GLUE_GET_PKT_PRIVATE_DATA(_p)->ucProfilingFlag & BIT(0)) + +#define GLUE_GET_PKT_ETHER_DEST_ADDR(_p) \ + ((PUINT_8)&(((struct sk_buff *)(_p))->data)) + +/* 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 GLUE_GET_REF_CNT(_refCount) atomic_read((atomic_t *)&(_refCount)) + +#define DbgPrint(...) + +#if CFG_MET_TAG_SUPPORT +#define GL_MET_TAG_START(_id, _name) met_tag_start(_id, _name) +#define GL_MET_TAG_END(_id, _name) met_tag_end(_id, _name) +#define GL_MET_TAG_ONESHOT(_id, _name, _value) met_tag_oneshot(_id, _name, _value) +#define GL_MET_TAG_DISABLE(_id) met_tag_disable(_id) +#define GL_MET_TAG_ENABLE(_id) met_tag_enable(_id) +#define GL_MET_TAG_REC_ON() met_tag_record_on() +#define GL_MET_TAG_REC_OFF() met_tag_record_off() +#define GL_MET_TAG_INIT() met_tag_init() +#define GL_MET_TAG_UNINIT() met_tag_uninit() +#else +#define GL_MET_TAG_START(_id, _name) +#define GL_MET_TAG_END(_id, _name) +#define GL_MET_TAG_ONESHOT(_id, _name, _value) +#define GL_MET_TAG_DISABLE(_id) +#define GL_MET_TAG_ENABLE(_id) +#define GL_MET_TAG_REC_ON() +#define GL_MET_TAG_REC_OFF() +#define GL_MET_TAG_INIT() +#define GL_MET_TAG_UNINIT() +#endif + +#define MET_TAG_ID 0 + +/*----------------------------------------------------------------------------*/ +/* Macros of Data Type Check */ +/*----------------------------------------------------------------------------*/ +/* Kevin: we don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + */ +static __KAL_INLINE__ VOID glPacketDataTypeCheck(VOID) +{ + + DATA_STRUCT_INSPECTING_ASSERT(sizeof(PACKET_PRIVATE_DATA) <= sizeof(((struct sk_buff *) 0)->cb)); +} + +static inline u16 mtk_wlan_ndev_select_queue(struct sk_buff *skb) +{ + static u16 ieee8021d_to_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; + + /* cfg80211_classify8021d returns 0~7 */ +#if KERNEL_VERSION(3, 14, 0) > CFG80211_VERSION_CODE + skb->priority = cfg80211_classify8021d(skb); +#else + skb->priority = cfg80211_classify8021d(skb, NULL); +#endif + return ieee8021d_to_queue[skb->priority]; +} + +#if KERNEL_VERSION(2, 6, 34) > LINUX_VERSION_CODE +#define netdev_for_each_mc_addr(mclist, dev) \ + for (mclist = dev->mc_list; mclist; mclist = mclist->next) +#endif + +#if KERNEL_VERSION(2, 6, 34) > LINUX_VERSION_CODE +#define GET_ADDR(ha) (ha->da_addr) +#else +#define GET_ADDR(ha) (ha->addr) +#endif + +#if KERNEL_VERSION(2, 6, 35) <= LINUX_VERSION_CODE +#define LIST_FOR_EACH_IPV6_ADDR(_prIfa, _ip6_ptr) \ + list_for_each_entry(_prIfa, &((struct inet6_dev *) _ip6_ptr)->addr_list, if_list) +#else +#define LIST_FOR_EACH_IPV6_ADDR(_prIfa, _ip6_ptr) \ + for (_prIfa = ((struct inet6_dev *) _ip6_ptr)->addr_list; _prIfa; _prIfa = _prIfa->if_next) +#endif + + +/******************************************************************************* +* 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 procCreateFsEntry(P_GLUE_INFO_T prGlueInfo); +INT_32 procRemoveProcfs(VOID); + + +INT_32 procInitFs(VOID); +INT_32 procUninitProcFs(VOID); + + + +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 p2pSetMulticastListWorkQueueWrapper(P_GLUE_INFO_T prGlueInfo); +#endif + +P_GLUE_INFO_T wlanGetGlueInfo(VOID); + +BOOLEAN wlanGetHifState(P_GLUE_INFO_T prGlueInfo); + +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE +u16 wlanSelectQueue(struct net_device *dev, + struct sk_buff *skb, struct net_device *sb_dev, + select_queue_fallback_t fallback); +#elif KERNEL_VERSION(3, 14, 0) <= LINUX_VERSION_CODE +u16 wlanSelectQueue(struct net_device *dev, struct sk_buff *skb, + void *accel_priv, select_queue_fallback_t fallback); +#elif KERNEL_VERSION(3, 13, 0) <= LINUX_VERSION_CODE +u16 wlanSelectQueue(struct net_device *dev, struct sk_buff *skb, + void *accel_priv); +#else +u16 wlanSelectQueue(struct net_device *dev, struct sk_buff *skb); +#endif + +VOID wlanDebugInit(VOID); + +WLAN_STATUS wlanSetDebugLevel(IN UINT_32 u4DbgIdx, IN UINT_32 u4DbgMask); + +WLAN_STATUS wlanGetDebugLevel(IN UINT_32 u4DbgIdx, OUT PUINT_32 pu4DbgMask); + +VOID wlanSetSuspendMode(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgEnable); + +VOID wlanGetConfig(P_ADAPTER_T prAdapter); + +WLAN_STATUS wlanExtractBufferBin(P_ADAPTER_T prAdapter); + +/******************************************************************************* +* E X T E R N A L F U N C T I O N S / V A R I A B L E +******************************************************************************** +*/ +extern struct net_device *gPrP2pDev[KAL_P2P_NUM]; +extern struct net_device *gPrDev; + +#ifdef CFG_DRIVER_INF_NAME_CHANGE +extern char *gprifnameap; +extern char *gprifnamep2p; +extern char *gprifnamesta; +#endif /* CFG_DRIVER_INF_NAME_CHANGE */ + +extern void wlanRegisterNotifier(void); +extern void wlanUnregisterNotifier(void); + +#if (MTK_WCN_HIF_SDIO && CFG_SUPPORT_MTK_ANDROID_KK) +typedef int (*set_p2p_mode) (struct net_device *netdev, PARAM_CUSTOM_P2P_SET_STRUCT_T p2pmode); +extern void register_set_p2p_mode_handler(set_p2p_mode handler); +#endif + +#if CFG_ENABLE_EARLY_SUSPEND +extern int glRegisterEarlySuspend(struct early_suspend *prDesc, + early_suspend_callback wlanSuspend, late_resume_callback wlanResume); + +extern int glUnregisterEarlySuspend(struct early_suspend *prDesc); +#endif + +#if CFG_MET_PACKET_TRACE_SUPPORT +VOID kalMetTagPacket(IN P_GLUE_INFO_T prGlueInfo, IN P_NATIVE_PACKET prPacket, IN ENUM_TX_PROFILING_TAG_T eTag); + +VOID kalMetInit(IN P_GLUE_INFO_T prGlueInfo); +#endif + +VOID wlanUpdateChannelTable(P_GLUE_INFO_T prGlueInfo); + +#if ((MTK_WCN_HIF_SDIO && CFG_SUPPORT_MTK_ANDROID_KK) || WLAN_INCLUDE_PROC) +int set_p2p_mode_handler(struct net_device *netdev, PARAM_CUSTOM_P2P_SET_STRUCT_T p2pmode); +#endif + +#endif /* _GL_OS_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_p2p_ioctl.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_p2p_ioctl.h new file mode 100644 index 0000000000000..50d689cd44cae --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_p2p_ioctl.h @@ -0,0 +1,720 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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 +*/ + + +#ifndef _GL_P2P_IOCTL_H +#define _GL_P2P_IOCTL_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#include +#include +#endif + +#include "wlan_oid.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/* (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 + +#define CHN_DIRTY_WEIGHT_UPPERBOUND 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; + +/*----------------------------------------------------------------------------*/ +/* NL80211 TEST MODE */ +/*----------------------------------------------------------------------------*/ +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +typedef enum _ENUM_TESTMODE_AVAILABLE_CHAN_ATTR { + __NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_INVALID, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_2G_BASE_1, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_36, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_52, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_100, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_149, + __NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_AFTER_LAST, + NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_MAX = __NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_AFTER_LAST - 1 +} ENUM_TESTMODE_AVAILABLE_CHAN_ATTR; +#endif + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +extern struct ieee80211_supported_band mtk_band_2ghz; +extern struct ieee80211_supported_band mtk_band_5ghz; + +extern const UINT_32 mtk_cipher_suites[5]; + + +/******************************************************************************* +* 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 = KAL_BAND_2GHZ, \ + .center_freq = (_freq), \ + .hw_value = (_channel), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} + +#define CHAN5G(_channel, _flags) \ +{ \ + .band = KAL_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 (CFG_ENABLE_WIFI_DIRECT_CFG_80211 != 0) + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +struct wireless_dev *mtk_p2p_cfg80211_add_iface(struct wiphy *wiphy, + const char *name, unsigned char name_assign_type, + enum nl80211_iftype type, struct vif_params *params); +#elif KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE +struct wireless_dev *mtk_p2p_cfg80211_add_iface(struct wiphy *wiphy, + const char *name, unsigned char name_assign_type, + enum nl80211_iftype type, u32 *flags, struct vif_params *params); +#else +struct wireless_dev *mtk_p2p_cfg80211_add_iface(struct wiphy *wiphy, + const char *name, + enum nl80211_iftype type, u32 *flags, struct vif_params *params); +#endif + +#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE +int +mtk_p2p_cfg80211_change_iface(IN struct wiphy *wiphy, + IN struct net_device *ndev, + IN enum nl80211_iftype type, + IN struct vif_params *params); +#else +int +mtk_p2p_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type, u32 *flags, struct vif_params *params); +#endif + +int mtk_p2p_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev); + +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_set_mgmt_key(struct wiphy *wiphy, struct net_device *dev, u8 key_index); + +#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, + const u8 *mac, struct station_info *sinfo); +#else +int mtk_p2p_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, u8 *mac, struct station_info *sinfo); +#endif +int mtk_p2p_cfg80211_scan(struct wiphy *wiphy, 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, + struct wireless_dev *wdev, enum nl80211_tx_power_setting type, int mbm); + +int mtk_p2p_cfg80211_get_txpower(struct wiphy *wiphy, struct wireless_dev *wdev, int *dbm); + +int mtk_p2p_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, unsigned int duration, u64 *cookie); + +int mtk_p2p_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie); + +int mtk_p2p_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, bool enabled, int timeout); + +#if (CFG_SUPPORT_DFS_MASTER == 1) + +#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_start_radar_detection(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef, + unsigned int cac_time_ms); +#else +int mtk_p2p_cfg80211_start_radar_detection(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef); +#endif + + +#if KERNEL_VERSION(3, 13, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_csa_settings *params); +#endif +#endif + +int mtk_p2p_cfg80211_change_bss(struct wiphy *wiphy, struct net_device *dev, struct bss_parameters *params); + +int mtk_p2p_cfg80211_deauth(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_deauth_request *req); + +int mtk_p2p_cfg80211_disassoc(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_disassoc_request *req); + +int mtk_p2p_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ap_settings *settings); + +int mtk_p2p_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_beacon_data *info); +#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie); +#else +int mtk_p2p_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, bool offchan, + unsigned int wait, const u8 *buf, size_t len, + bool no_cck, bool dont_wait_for_ack, u64 *cookie); +#endif + +#if KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, struct station_del_parameters *params); +#elif KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, const u8 *mac); +#else +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, u8 *mac); +#endif + +int mtk_p2p_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie); + +int mtk_p2p_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev); + +int mtk_p2p_cfg80211_set_channel(struct wiphy *wiphy, struct cfg80211_chan_def *chandef); + +void mtk_p2p_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, + struct wireless_dev *wdev, IN u16 frame_type, IN bool reg); + +int +mtk_p2p_cfg80211_set_bitrate_mask(IN struct wiphy *wiphy, + IN struct net_device *dev, + IN const u8 *peer, IN const struct cfg80211_bitrate_mask *mask); + +#ifdef CONFIG_NL80211_TESTMODE +#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE +int mtk_p2p_cfg80211_testmode_cmd(struct wiphy *wiphy, + struct wireless_dev *wdev, void *data, + int len); +#else +int mtk_p2p_cfg80211_testmode_cmd(struct wiphy *wiphy, void *data, int len); +#endif +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); + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +int mtk_p2p_cfg80211_testmode_get_best_channel(IN struct wiphy *wiphy, IN void *data, IN int len); +#endif + +#if GO_STA_SCC +int mtk_p2p_cfg80211_go_channel_switch(IN struct wiphy *wiphy, + IN struct wireless_dev *wdev, IN void *data, IN int len); +#endif + +#else +/* IGNORE KERNEL DEPENCY ERRORS*/ +/*#error "Please ENABLE kernel config (CONFIG_NL80211_TESTMODE) to support Wi-Fi Direct"*/ +#endif + +#endif + +/* I/O control handlers */ + +int +mtk_p2p_wext_get_priv(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_reconnect(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_auth(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_key(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_mlme_handler(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_powermode(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_get_powermode(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +/* Private Wireless I/O Controls takes use of iw_handler */ +int +mtk_p2p_wext_set_local_dev_info(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_provision_complete(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_start_stop_discovery(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_discovery_results(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_wsc_ie(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_connect_disconnect(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_password_ready(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_request_dev_info(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_invitation_indicate(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_invitation_status(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_pm_param(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_ps_profile(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_network_address(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_int(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +/* Private Wireless I/O Controls for IOC_SET_STRUCT/IOC_GET_STRUCT */ +int +mtk_p2p_wext_set_struct(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_get_struct(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +/* IOC_SET_STRUCT/IOC_GET_STRUCT: Service Discovery */ +int +mtk_p2p_wext_get_service_discovery_request(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_get_service_discovery_response(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_send_service_discovery_request(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_send_service_discovery_response(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_terminate_service_discovery_phase(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +#if CFG_SUPPORT_ANTI_PIRACY +int +mtk_p2p_wext_set_sec_check_request(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_get_sec_check_response(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); +#endif + +int +mtk_p2p_wext_set_noa_param(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_oppps_param(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_p2p_version(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_get_p2p_version(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +void mtk_p2p_wext_set_Multicastlist(IN P_GLUE_INFO_T prGlueInfo); + +#if CFG_SUPPORT_P2P_RSSI_QUERY +int +mtk_p2p_wext_get_rssi(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +struct iw_statistics *mtk_p2p_wext_get_wireless_stats(struct net_device *prDev); + +#endif + +int +mtk_p2p_wext_set_txpow(IN struct net_device *prDev, + IN struct iw_request_info *prIwrInfo, IN OUT union iwreq_data *prTxPow, IN char *pcExtra); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _GL_P2P_IOCTL_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_p2p_kal.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_p2p_kal.h new file mode 100644 index 0000000000000..0e21b945022a7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_p2p_kal.h @@ -0,0 +1,288 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +#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 + +BOOLEAN kalP2pFuncGetChannelType(IN ENUM_CHNL_EXT_T rChnlSco, OUT enum nl80211_channel_type *channel_type); + +/******************************************************************************* +* 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, IN UINT_8 ucBssIndex); + +/*UINT_32 kalP2PGetFreqInKHz(IN P_GLUE_INFO_T prGlueInfo);*/ + +INT_32 mtk_Netdev_To_RoleIdx(P_GLUE_INFO_T prGlueInfo, struct net_device *ndev, PUINT_8 pucRoleIdx); + +UINT_8 kalP2PGetRole(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRoleIdx); + +#if 1 +VOID kalP2PSetRole(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRole, IN UINT_8 ucRoleIdx); + +#else +VOID +kalP2PSetRole(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucResult, IN PUINT_8 pucSSID, IN UINT_8 ucSSIDLen, IN UINT_8 ucRole); +#endif + +VOID kalP2PSetCipher(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Cipher, IN UINT_8 ucRoleIdx); + +BOOLEAN kalP2PGetCipher(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRoleIdx); + +BOOLEAN kalP2PGetWepCipher(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRoleIdx); + +BOOLEAN kalP2PGetTkipCipher(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRoleIdx); + +BOOLEAN kalP2PGetCcmpCipher(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRoleIdx); + +#if CFG_SUPPORT_SUITB +BOOLEAN kalP2PGetGcmp256Cipher(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucRoleIdx); +#endif +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, IN UINT_8 ucRoleIdx); + +VOID kalP2PGenWSC_IE(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucType, IN PUINT_8 pucBuffer, IN UINT_8 ucRoleIdx); + +VOID kalP2PUpdateWSC_IE(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucType, IN PUINT_8 pucBuffer, + IN UINT_16 u2BufferLength, IN UINT_8 ucRoleIdx); + +UINT_16 kalP2PCalP2P_IELen(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_32 u4IEIdx, IN UINT_8 ucRoleIdx); +VOID kalP2PGenP2P_IE(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4IEIdx, + IN PUINT_8 pucBuffer, IN UINT_8 ucRoleIdx); +VOID kalP2PResetP2P_IE(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucRoleIdx); +VOID kalP2PUpdateP2P_IE(IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucBuffer, IN UINT_16 u2BufferLength, IN UINT_8 ucRoleIdx); + +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 UINT_8 ucRoleIndex, 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, IN BOOLEAN fgIsDevInterface, IN UINT_8 ucRoleIdx); + +VOID kalP2PIndicateMgmtTxStatus(IN P_GLUE_INFO_T prGlueInfo, IN P_MSDU_INFO_T prMsduInfo, IN BOOLEAN fgIsAck); + +VOID +kalP2PIndicateChannelExpired(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); + +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) +VOID +kalP2PGCIndicateConnectionStatus(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucRoleIndex, + IN P_P2P_CONNECTION_REQ_INFO_T prP2pConnInfo, + IN PUINT_8 pucRxIEBuf, IN UINT_16 u2RxIELen, IN UINT_16 u2StatusReason, + IN WLAN_STATUS eStatus); +#else +VOID +kalP2PGCIndicateConnectionStatus(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucRoleIndex, + IN P_P2P_CONNECTION_REQ_INFO_T prP2pConnInfo, + IN PUINT_8 pucRxIEBuf, IN UINT_16 u2RxIELen, IN UINT_16 u2StatusReason); + +#endif +VOID +kalP2PGOStationUpdate(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucRoleIndex, IN P_STA_RECORD_T prCliStaRec, IN BOOLEAN fgIsNew); + +#if (CFG_SUPPORT_DFS_MASTER == 1) +VOID +kalP2PRddDetectUpdate(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRoleIndex); + +VOID +kalP2PCacFinishedUpdate(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRoleIndex); +#endif + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + +BOOLEAN kalP2PSetBlackList(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rbssid, IN BOOLEAN fgIsblock, + IN UINT_8 ucRoleIndex); + +BOOLEAN kalP2PCmpBlackList(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rbssid, IN UINT_8 ucRoleIndex); + +VOID kalP2PSetMaxClients(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4MaxClient, IN UINT_8 ucRoleIndex); + +BOOLEAN kalP2PMaxClients(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4NumClient, IN UINT_8 ucRoleIndex); + +#endif + +#endif /* _GL_P2P_KAL_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_p2p_os.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_p2p_os.h new file mode 100644 index 0000000000000..2fb5ff3a2cb85 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_p2p_os.h @@ -0,0 +1,338 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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 + +#define VENDOR_SPECIFIC_IE_LENGTH 300 /* 1(IE) + 1(length) + 0xff(max length) */ +#define MAX_MULTI_P2P_IE_COUNT 4 +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L V A R I A B L E +******************************************************************************** +*/ +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_WIFI_DIRECT_CFG_80211 +extern const struct net_device_ops p2p_netdev_ops; +#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 +******************************************************************************** +*/ +extern struct net_device *g_P2pPrDev; +extern struct wireless_dev *gprP2pWdev; +extern struct wireless_dev *gprP2pRoleWdev[KAL_P2P_NUM]; + +/******************************************************************************* +* 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 { + + /* P2P Device interface handle */ + /*only first p2p have this devhandler*/ + struct net_device *prDevHandler; + /*struct net_device *prRoleDevHandler;*//* TH3 multiple P2P */ + + struct net_device *aprRoleHandler; + + /* Todo : should move to the glueinfo or not*/ + /*UINT_8 ucRoleInterfaceNum;*//* TH3 multiple P2P */ + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + /* cfg80211 */ + struct wireless_dev *prWdev; + /*struct wireless_dev *prRoleWdev[KAL_P2P_NUM];*//* TH3 multiple P2P */ + + /*struct cfg80211_scan_request *prScanRequest;*//* TH3 multiple P2P */ + + /*UINT_64 u8Cookie;*//* TH3 multiple P2P */ + + /* Generation for station list update. */ + INT_32 i4Generation; + + /*UINT_32 u4OsMgmtFrameFilter;*//* TH3 multiple P2P */ + +#endif + + /* Device statistics */ + /*struct net_device_stats rNetDevStats;*//* TH3 multiple P2P */ + + /* glue layer variables */ + /*move to glueinfo->adapter */ + /* BOOLEAN fgIsRegistered; */ + /*UINT_32 u4FreqInKHz;*//* TH3 multiple P2P */ /* frequency */ + UINT_8 ucRole; /* 0: P2P Device, 1: Group Client, 2: Group Owner */ + /*UINT_8 ucIntent;*//* TH3 multiple P2P */ /* range: 0-15 */ + /*UINT_8 ucScanMode;*//* TH3 multiple P2P */ /* 0: Search & Listen, 1: Scan without probe response */ + + /*ENUM_PARAM_MEDIA_STATE_T eState;*//* TH3 multiple P2P */ + /*UINT_32 u4PacketFilter;*//* TH3 multiple P2P */ + /*PARAM_MAC_ADDRESS aucMCAddrList[MAX_NUM_GROUP_ADDR];*//* TH3 multiple P2P */ + + /* connection-requested peer information *//* TH3 multiple P2P */ + /*UINT_8 aucConnReqDevName[32];*//* TH3 multiple P2P */ + /*INT_32 u4ConnReqNameLength;*//* TH3 multiple P2P */ + /*PARAM_MAC_ADDRESS rConnReqPeerAddr;*//* TH3 multiple P2P */ + /*PARAM_MAC_ADDRESS rConnReqGroupAddr;*//* TH3 multiple P2P */ /* For invitation group. */ + /*UINT_8 ucConnReqDevType;*//* TH3 multiple P2P */ + /*INT_32 i4ConnReqConfigMethod;*//* TH3 multiple P2P */ + /*INT_32 i4ConnReqActiveConfigMethod;*//* TH3 multiple P2P */ + + UINT_32 u4CipherPairwise; + /*UINT_8 ucWSCRunning;*//* TH3 multiple P2P */ + + /* 0: beacon, 1: probe req, 2: probe response, 3: assoc response */ + UINT_8 aucWSCIE[4][VENDOR_SPECIFIC_IE_LENGTH]; + UINT_16 u2WSCIELen[4]; + + UINT_8 aucP2PIE[MAX_MULTI_P2P_IE_COUNT][VENDOR_SPECIFIC_IE_LENGTH]; + UINT_16 u2P2PIELen[MAX_MULTI_P2P_IE_COUNT]; + +#if CFG_SUPPORT_WFD + UINT_8 aucWFDIE[VENDOR_SPECIFIC_IE_LENGTH]; + UINT_16 u2WFDIELen; + /* UINT_8 aucVenderIE[1024]; *//* Save the other IE for prove resp */ +/* UINT_16 u2VenderIELen; */ +#endif + + /*UINT_8 ucOperatingChnl;*//* TH3 multiple P2P */ + /*UINT_8 ucInvitationType;*//* TH3 multiple P2P */ + + /*UINT_32 u4InvStatus;*//* TH3 multiple P2P */ + + /* For SET_STRUCT/GET_STRUCT */ + /*UINT_8 aucOidBuf[4096];*//* TH3 multiple P2P */ + +#if 1 /* CFG_SUPPORT_ANTI_PIRACY */ + /*UINT_8 aucSecCheck[256];*//* TH3 multiple P2P */ + /*UINT_8 aucSecCheckRsp[256];*//* TH3 multiple P2P */ +#endif + +#if (CFG_SUPPORT_DFS_MASTER == 1) + struct cfg80211_chan_def *chandef; + UINT_32 cac_time_ms; + BOOLEAN fgIsNetDevDetach; +#endif + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + /* Hotspot Client Management */ + /* dependent with #define P2P_MAXIMUM_CLIENT_COUNT 10, + * fix me to PARAM_MAC_ADDRESS aucblackMACList[P2P_MAXIMUM_CLIENT_COUNT]; + */ + PARAM_MAC_ADDRESS aucblackMACList[10]; + UINT_8 ucMaxClients; +#endif + +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION + /*BOOLEAN fgEnableHotspotOptimization;*//* TH3 multiple P2P */ + /*UINT_32 u4PsLevel;*//* TH3 multiple P2P */ +#endif +}; + +struct _GL_P2P_DEV_INFO_T { +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + struct cfg80211_scan_request *prScanRequest; + struct cfg80211_scan_request rBackupScanRequest; + UINT_64 u8Cookie; + UINT_32 u4OsMgmtFrameFilter; +#endif + UINT_32 u4PacketFilter; + PARAM_MAC_ADDRESS aucMCAddrList[MAX_NUM_GROUP_ADDR]; + UINT_8 ucWSCRunning; +}; + +#ifdef CONFIG_NL80211_TESTMODE +typedef struct _NL80211_DRIVER_TEST_PRE_PARAMS { + UINT_16 idx_mode; + UINT_16 idx; + UINT_32 value; +} NL80211_DRIVER_TEST_PRE_PARAMS, *P_NL80211_DRIVER_TEST_PRE_PARAMS; + +typedef struct _NL80211_DRIVER_TEST_PARAMS { + UINT_32 index; + UINT_32 buflen; +} NL80211_DRIVER_TEST_PARAMS, *P_NL80211_DRIVER_TEST_PARAMS; + +/* P2P Sigma*/ +typedef struct _NL80211_DRIVER_P2P_SIGMA_PARAMS { + NL80211_DRIVER_TEST_PARAMS hdr; + UINT_32 idx; + UINT_32 value; +} NL80211_DRIVER_P2P_SIGMA_PARAMS, *P_NL80211_DRIVER_P2P_SIGMA_PARAMS; + +/* Hotspot Client Management */ +typedef struct _NL80211_DRIVER_hotspot_block_PARAMS { + NL80211_DRIVER_TEST_PARAMS hdr; + UINT_8 ucblocked; + UINT_8 aucBssid[MAC_ADDR_LEN]; +} NL80211_DRIVER_hotspot_block_PARAMS, *P_NL80211_DRIVER_hotspot_block_PARAMS; + +#if CFG_SUPPORT_WFD +typedef struct _NL80211_DRIVER_WFD_PARAMS { + NL80211_DRIVER_TEST_PARAMS hdr; + UINT_32 WfdCmdType; + UINT_8 WfdEnable; + UINT_8 WfdCoupleSinkStatus; + UINT_8 WfdSessionAvailable; + UINT_8 WfdSigmaMode; + UINT_16 WfdDevInfo; + UINT_16 WfdControlPort; + UINT_16 WfdMaximumTp; + UINT_16 WfdExtendCap; + UINT_8 WfdCoupleSinkAddress[MAC_ADDR_LEN]; + UINT_8 WfdAssociatedBssid[MAC_ADDR_LEN]; + UINT_8 WfdVideoIp[4]; + UINT_8 WfdAudioIp[4]; + UINT_16 WfdVideoPort; + UINT_16 WfdAudioPort; + UINT_32 WfdFlag; + UINT_32 WfdPolicy; + UINT_32 WfdState; + UINT_8 WfdSessionInformationIE[24 * 8]; /* Include Subelement ID, length */ + UINT_16 WfdSessionInformationIELen; + UINT_8 aucReserved1[2]; + UINT_8 aucWfdPrimarySinkMac[MAC_ADDR_LEN]; + UINT_8 aucWfdSecondarySinkMac[MAC_ADDR_LEN]; + UINT_32 WfdAdvanceFlag; + /* Group 1 64 bytes */ + UINT_8 aucWfdLocalIp[4]; + UINT_16 WfdLifetimeAc2; /* Unit is 2 TU */ + UINT_16 WfdLifetimeAc3; /* Unit is 2 TU */ + UINT_16 WfdCounterThreshold; /* Unit is ms */ + UINT_8 aucReserved2[54]; + /* Group 3 64 bytes */ + UINT_8 aucReserved3[64]; + /* Group 3 64 bytes */ + UINT_8 aucReserved4[64]; +} NL80211_DRIVER_WFD_PARAMS, *P_NL80211_DRIVER_WFD_PARAMS; +#endif +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +BOOLEAN 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 UINT_8 ucAPMode); + +BOOLEAN glRegisterP2P(P_GLUE_INFO_T prGlueInfo, const char *prDevName, const char *prDevName2, UINT_8 ucApMode); + +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 p2PFreeInfo(P_GLUE_INFO_T prGlueInfo); + +VOID p2pSetSuspendMode(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgEnable); +BOOLEAN glP2pCreateWirelessDevice(P_GLUE_INFO_T prGlueInfo); +VOID glP2pDestroyWirelessDevice(VOID); +VOID p2pUpdateChannelTableByDomain(P_GLUE_INFO_T prGlueInfo); +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_qa_agent.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_qa_agent.h new file mode 100644 index 0000000000000..e185ad4a2c65f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_qa_agent.h @@ -0,0 +1,273 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*! \file gl_qa_agent.h +* \brief This file includes private ioctl support. +*/ + +#ifndef _GL_QA_AGENT_H +#define _GL_QA_AGENT_H +#if CFG_SUPPORT_QA_TOOL +/******************************************************************************* +* C O M P I L E 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 +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#define HQA_CMD_MAGIC_NO 0x18142880 +#define HQA_CHIP_ID_6632 0x6632 +#define HQA_CHIP_ID_7668 0x7668 + +#if CFG_SUPPORT_TX_BF +#define HQA_BF_STR_SIZE 512 +#endif + +#define HQA_RX_STATISTIC_NUM 66 +#define BUFFER_BIN_MODE 0x0 +#define EFUSE_MODE 0x2 + +extern UINT_8 uacEEPROMImage[MAX_EEPROM_BUFFER_SIZE]; + +#if 0 +typedef struct _PARAM_RX_STAT_T { + UINT_32 MacFCSErr; /* Y 0x820F_D014 */ + UINT_32 MacMdrdy; /* Y 0x820F_D030 */ + UINT_32 FCSErr_CCK; /* Y 0x8207_021C [15:00] */ + UINT_32 FCSErr_OFDM; /* Y 0x8207_021C [31:16] */ + UINT_32 CCK_PD; /* Y 0x8207_020C [15:00] */ + UINT_32 OFDM_PD; /* Y 0x8207_020C [15:00] */ + UINT_32 CCK_SIG_Err; /* Y 0x8207_0210 [31:16] */ + UINT_32 CCK_SFD_Err; /* Y 0x8207_0210 [15:00] */ + UINT_32 OFDM_SIG_Err; /* Y 0x8207_0214 [31:16] */ + UINT_32 OFDM_TAG_Err; /* Y 0x8207_0214 [15:00] */ + UINT_32 WB_RSSSI0; /* Y 0x8207_21A8 [23:16] */ + UINT_32 IB_RSSSI0; /* Y 0x8207_21A8 [31:24] */ + UINT_32 WB_RSSSI1; /* Y 0x8207_21A8 [07:00] */ + UINT_32 IB_RSSSI1; /* Y 0x8207_21A8 [15:08] */ + UINT_32 PhyMdrdyCCK; /* Y 0x8207_0220 [15:00] */ + UINT_32 PhyMdrdyOFDM; /* Y 0x8207_0220 [31:16] */ + UINT_32 DriverRxCount; /* Y FW Counter Band0 */ + UINT_32 RCPI0; /* Y RXV4 [07:00] */ + UINT_32 RCPI1; /* Y RXV4 [15:08] */ + UINT_32 FreqOffsetFromRX; /* Y RXV5 MISC1[24:00] OFDM:[11:00] CCK:[10:00] */ + UINT_32 RSSI0; /* N */ + UINT_32 RSSI1; /* N */ + UINT_32 rx_fifo_full; /* N */ + UINT_32 RxLenMismatch; /* N */ + UINT_32 MacFCSErr_band1; /* Y 0x820F_D214 */ + UINT_32 MacMdrdy_band1; /* Y 0x820F_D230 */ + /* Y RXV3 [23:16] (must set 0x8207066C[1:0] = 0x0 ~ 0x3) */ + UINT_32 FAGC_IB_RSSSI[4]; + /* Y RXV3 [31:24] (must set 0x8207066C[1:0] = 0x0 ~ 0x3) */ + UINT_32 FAGC_WB_RSSSI[4]; + /* Y 0x8207_21A8 [31:24] [15:08] 0x8207_29A8 [31:24] [15:08] */ + UINT_32 Inst_IB_RSSSI[4]; + /* Y 0x8207_21A8 [23:16] [07:00] 0x8207_29A8 [23:16] [07:00] */ + UINT_32 Inst_WB_RSSSI[4]; + UINT_32 ACIHitLow; /* Y 0x8207_21B0 [18] */ + UINT_32 ACIHitHigh; /* Y 0x8207_29B0 [18] */ + UINT_32 DriverRxCount1; /* Y FW Counter Band1 */ + UINT_32 RCPI2; /* Y RXV4 [23:16] */ + UINT_32 RCPI3; /* Y RXV4 [31:24] */ + UINT_32 RSSI2; /* N */ + UINT_32 RSSI3; /* N */ + UINT_32 SNR0; /* Y RXV5 (MISC1 >> 19) - 16 */ + UINT_32 SNR1; /* N */ + UINT_32 SNR2; /* N */ + UINT_32 SNR3; /* N */ + UINT_32 rx_fifo_full_band1; /* N */ + UINT_32 RxLenMismatch_band1; /* N */ + UINT_32 CCK_PD_band1; /* Y 0x8207_040C [15:00] */ + UINT_32 OFDM_PD_band1; /* Y 0x8207_040C [31:16] */ + UINT_32 CCK_SIG_Err_band1; /* Y 0x8207_0410 [31:16] */ + UINT_32 CCK_SFD_Err_band1; /* Y 0x8207_0410 [15:00] */ + UINT_32 OFDM_SIG_Err_band1; /* Y 0x8207_0414 [31:16] */ + UINT_32 OFDM_TAG_Err_band1; /* Y 0x8207_0414 [15:00] */ + UINT_32 PhyMdrdyCCK_band1; /* Y 0x8207_0420 [15:00] */ + UINT_32 PhyMdrdyOFDM_band1; /* Y 0x8207_0420 [31:16] */ + UINT_32 CCK_FCS_Err_band1; /* Y 0x8207_041C [15:00] */ + UINT_32 OFDM_FCS_Err_band1; /* Y 0x8207_041C [31:16] */ + UINT_32 MuPktCount; /* Y MT_ATEUpdateRxStatistic RXV1_2ND_CYCLE->GroupId */ +} PARAM_RX_STAT_T, *P_PARAM_RX_STAT_T; +#else +typedef struct _PARAM_RX_STAT_T { + UINT_32 MAC_FCS_Err; /* b0 */ + UINT_32 MAC_Mdrdy; /* b0 */ + UINT_32 FCSErr_CCK; + UINT_32 FCSErr_OFDM; + UINT_32 CCK_PD; + UINT_32 OFDM_PD; + UINT_32 CCK_SIG_Err; + UINT_32 CCK_SFD_Err; + UINT_32 OFDM_SIG_Err; + UINT_32 OFDM_TAG_Err; + UINT_32 WB_RSSI0; + UINT_32 IB_RSSI0; + UINT_32 WB_RSSI1; + UINT_32 IB_RSSI1; + UINT_32 PhyMdrdyCCK; + UINT_32 PhyMdrdyOFDM; + UINT_32 DriverRxCount; + UINT_32 RCPI0; + UINT_32 RCPI1; + UINT_32 FreqOffsetFromRX; + UINT_32 RSSI0; + UINT_32 RSSI1; /* insert new member here */ + UINT_32 OutOfResource; /* MT7615 begin here */ + UINT_32 LengthMismatchCount_B0; + UINT_32 MAC_FCS_Err1; /* b1 */ + UINT_32 MAC_Mdrdy1; /* b1 */ + UINT_32 FAGCRssiIBR0; + UINT_32 FAGCRssiIBR1; + UINT_32 FAGCRssiIBR2; + UINT_32 FAGCRssiIBR3; + UINT_32 FAGCRssiWBR0; + UINT_32 FAGCRssiWBR1; + UINT_32 FAGCRssiWBR2; + UINT_32 FAGCRssiWBR3; + + UINT_32 InstRssiIBR0; + UINT_32 InstRssiIBR1; + UINT_32 InstRssiIBR2; + UINT_32 InstRssiIBR3; + UINT_32 InstRssiWBR0; + UINT_32 InstRssiWBR1; + UINT_32 InstRssiWBR2; + UINT_32 InstRssiWBR3; + UINT_32 ACIHitLower; + UINT_32 ACIHitUpper; + UINT_32 DriverRxCount1; + UINT_32 RCPI2; + UINT_32 RCPI3; + UINT_32 RSSI2; + UINT_32 RSSI3; + UINT_32 SNR0; + UINT_32 SNR1; + UINT_32 SNR2; + UINT_32 SNR3; + UINT_32 OutOfResource1; + UINT_32 LengthMismatchCount_B1; + UINT_32 CCK_PD_Band1; + UINT_32 OFDM_PD_Band1; + UINT_32 CCK_SIG_Err_Band1; + UINT_32 CCK_SFD_Err_Band1; + UINT_32 OFDM_SIG_Err_Band1; + UINT_32 OFDM_TAG_Err_Band1; + UINT_32 PHY_CCK_MDRDY_Band1; + UINT_32 PHY_OFDM_MDRDY_Band1; + UINT_32 CCK_FCS_Err_Band1; + UINT_32 OFDM_FCS_Err_Band1; + UINT_32 MRURxCount; + UINT_32 SIGMCS; + UINT_32 SINR; + UINT_32 RXVRSSI; + UINT_32 Reserved[184]; + UINT_32 PHY_Mdrdy; + UINT_32 Noise_Floor; + UINT_32 AllLengthMismatchCount_B0; + UINT_32 AllLengthMismatchCount_B1; + UINT_32 AllMacMdrdy0; + UINT_32 AllMacMdrdy1; + UINT_32 AllFCSErr0; + UINT_32 AllFCSErr1; + UINT_32 RXOK0; + UINT_32 RXOK1; + UINT_32 PER0; + UINT_32 PER1; +} PARAM_RX_STAT_T, *P_PARAM_RX_STAT_T; +extern PARAM_RX_STAT_T g_HqaRxStat; +#endif + +typedef struct _HQA_CMD_FRAME { + UINT_32 MagicNo; + UINT_16 Type; + UINT_16 Id; + UINT_16 Length; + UINT_16 Sequence; + UCHAR Data[2048]; +} __packed HQA_CMD_FRAME; + +typedef INT_32(*HQA_CMD_HANDLER) (struct net_device *prNetDev, + IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame); + +typedef struct _HQA_CMD_TABLE { + HQA_CMD_HANDLER *CmdSet; + UINT_32 CmdSetSize; + UINT_32 CmdOffset; +} HQA_CMD_TABLE; + +int HQA_CMDHandler(struct net_device *prNetDev, IN union iwreq_data *prIwReqData, HQA_CMD_FRAME *HqaCmdFrame); + +int priv_qa_agent(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra); + +int priv_set_eeprom_mode(IN UINT_32 u4Mode); +#endif /*CFG_SUPPORT_QA_TOOL */ +#endif /* _GL_QA_AGENT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_rst.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_rst.h new file mode 100644 index 0000000000000..3f70bd9541c85 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_rst.h @@ -0,0 +1,143 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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" +#include +#include +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +struct rst_struct { +#ifdef _HIF_SDIO + struct sdio_func *func; + struct work_struct rst_work; +#endif + struct mutex rst_mutex; + int entry_conut; +}; + +/******************************************************************************* +* E X T E R N A L F U N C T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +extern struct rst_struct rst_data; + +#ifdef _HIF_SDIO + extern const struct sdio_device_id mtk_sdio_ids[]; +#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 +******************************************************************************** +*/ +#ifdef _HIF_SDIO + extern int sdio_reset_comm(struct mmc_card *card); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +BOOLEAN kalIsResetting(VOID); + +#if CFG_CHIP_RESET_SUPPORT + +BOOLEAN checkResetState(void); +VOID glResetTrigger(P_ADAPTER_T prAdapter); +INT_32 notify_wlan_toggle_rst_end(INT_32 reserved); +#else +#define glResetTrigger(A) +#endif + +#endif /* _GL_RST_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_sec.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_sec.h new file mode 100644 index 0000000000000..48cada0ab3239 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_sec.h @@ -0,0 +1,72 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_sec.h#1 +*/ + +/*! \file p2p_fsm.h +* \brief Declaration of functions and finite state machine for P2P Module. +* +* Declaration of functions and finite state machine for P2P Module. +*/ + +#ifndef _GL_SEC_H +#define _GL_SEC_H + +extern void handle_sec_msg_1(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_2(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_3(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_4(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_5(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_final(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); + +#endif /* _GL_SEC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_typedef.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_typedef.h new file mode 100644 index 0000000000000..3fe754b19857d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_typedef.h @@ -0,0 +1,279 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +#ifndef _GL_TYPEDEF_H +#define _GL_TYPEDEF_H + +#if CFG_ENABLE_EARLY_SUSPEND +#include +#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 CFG_ENABLE_EARLY_SUSPEND +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 int INT_32, *PINT_32, **PPINT_32; +typedef signed long LONG, *PLONG, **PPLONG; +typedef signed long long INT_64, *PINT_64, **PPINT_64; + +/* Type definition for unsigned integers */ +typedef unsigned char UCHAR, *PUCHAR, **PPUCHAR; +typedef unsigned char UINT_8, *PUINT_8, **PPUINT_8, *P_UINT_8; +typedef unsigned short UINT_16, *PUINT_16, **PPUINT_16; +typedef unsigned int UINT_32, *PUINT_32, **PPUINT_32; +typedef unsigned long ULONG, *PULONG, *PPULONG; +typedef unsigned long long UINT_64, *PUINT_64, **PPUINT_64; + +typedef unsigned int OS_SYSTIME, *POS_SYSTIME, **PPOS_SYSTIME; + +/* Type definition of large integer (64bits) union to be comptaible with + * Windows definition, so we won't apply our own coding style to these data types. + * NOTE: LARGE_INTEGER must NOT be floating variable. + * : Check for big-endian compatibility. + */ +typedef union _LARGE_INTEGER { + struct { + UINT_32 LowPart; + INT_32 HighPart; + } u; + INT_64 QuadPart; +} LARGE_INTEGER, *PLARGE_INTEGER; + +typedef union _ULARGE_INTEGER { + struct { + UINT_32 LowPart; + UINT_32 HighPart; + } u; + UINT_64 QuadPart; +} ULARGE_INTEGER, *PULARGE_INTEGER; + +typedef INT_32(*probe_card) (PVOID pvData, PVOID pvDriverData); +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__ inline +#define __KAL_ATTRIB_PACKED__ __attribute__((__packed__)) +#define __KAL_ATTRIB_ALIGN_4__ __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) ((unsigned long)&(((_type *)0)->_field)) +#endif /* OFFSET_OF */ + +/* This macro returns the base address of an instance of a structure + * given the type of the structure and the address of a field within the + * containing structure. + * _addrOfField - address of current field of the structure, + * _type - structure name, + * _field - field name of the structure + */ +#ifndef ENTRY_OF +#define ENTRY_OF(_addrOfField, _type, _field) \ + ((_type *)((PINT_8)(_addrOfField) - (PINT_8)OFFSET_OF(_type, _field))) +#endif /* ENTRY_OF */ + +/* This macro align the input value to the DW boundary. + * _value - value need to check + */ +#ifndef ALIGN_4 +#define ALIGN_4(_value) (((_value) + 3) & ~3u) +#endif /* ALIGN_4 */ + +/* This macro check the DW alignment of the input value. + * _value - value of address need to check + */ +#ifndef IS_ALIGN_4 +#define IS_ALIGN_4(_value) (((_value) & 0x3) ? FALSE : TRUE) +#endif /* IS_ALIGN_4 */ + +#ifndef IS_NOT_ALIGN_4 +#define IS_NOT_ALIGN_4(_value) (((_value) & 0x3) ? TRUE : FALSE) +#endif /* IS_NOT_ALIGN_4 */ + +/* This macro evaluate the input length in unit of Double Word(4 Bytes). + * _value - value in unit of Byte, output will round up to DW boundary. + */ +#ifndef BYTE_TO_DWORD +#define BYTE_TO_DWORD(_value) ((_value + 3) >> 2) +#endif /* BYTE_TO_DWORD */ + +/* This macro evaluate the input length in unit of Byte. + * _value - value in unit of DW, output is in unit of Byte. + */ +#ifndef DWORD_TO_BYTE +#define DWORD_TO_BYTE(_value) ((_value) << 2) +#endif /* DWORD_TO_BYTE */ + +#if 1 /* Little-Endian */ +#define CONST_NTOHS(_x) ntohs(_x) + +#define CONST_HTONS(_x) htons(_x) + +#define NTOHS(_x) ntohs(_x) + +#define HTONS(_x) htons(_x) + +#define NTOHL(_x) ntohl(_x) + +#define HTONL(_x) htonl(_x) + +#else /* Big-Endian */ + +#define CONST_NTOHS(_x) + +#define CONST_HTONS(_x) + +#define NTOHS(_x) + +#define HTONS(_x) + +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _GL_TYPEDEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_vendor.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_vendor.h new file mode 100644 index 0000000000000..bcc45715a513d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_vendor.h @@ -0,0 +1,758 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Log: gl_vendor.h +** +** 10 14 2014 +** add vendor declaration +** + * +*/ + +#ifndef _GL_VENDOR_H +#define _GL_VENDOR_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#include +#include + +#include "gl_os.h" + +#include "wlan_lib.h" +#include "gl_wext.h" +#include +#include + +#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 +/* workaround for some ANR CRs. if suppliant is blocked longer than 10s, wifi hal will tell wifiMonitor +* to teminate. for the case which can block supplicant 10s is to del key more than 5 times. the root cause +* is that there is no resource in TC4, so del key command was not able to set, and then oid +* timeout was happed. if we found the root cause why fw couldn't release TC resouce, we will remove this +* workaround +*/ + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define GOOGLE_OUI 0x001A11 + +typedef enum { + /* Don't use 0 as a valid subcommand */ + ANDROID_NL80211_SUBCMD_UNSPECIFIED, + + /* Define all vendor startup commands between 0x0 and 0x0FFF */ + ANDROID_NL80211_SUBCMD_WIFI_RANGE_START = 0x0001, + ANDROID_NL80211_SUBCMD_WIFI_RANGE_END = 0x0FFF, + + /* Define all GScan related commands between 0x1000 and 0x10FF */ + ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START = 0x1000, + ANDROID_NL80211_SUBCMD_GSCAN_RANGE_END = 0x10FF, + + /* Define all RTT related commands between 0x1100 and 0x11FF */ + ANDROID_NL80211_SUBCMD_RTT_RANGE_START = 0x1100, + ANDROID_NL80211_SUBCMD_RTT_RANGE_END = 0x11FF, + + ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START = 0x1200, + ANDROID_NL80211_SUBCMD_LSTATS_RANGE_END = 0x12FF, + + /* Define all Logger related commands between 0x1400 and 0x14FF */ + ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START = 0x1400, + ANDROID_NL80211_SUBCMD_DEBUG_RANGE_END = 0x14FF, + + /* Define all wifi offload related commands between 0x1600 and 0x16FF */ + ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START = 0x1600, + ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_END = 0x16FF, + + /* This is reserved for future usage */ + +} ANDROID_VENDOR_SUB_COMMAND; + +typedef enum { + WIFI_SUBCMD_GET_CHANNEL_LIST = ANDROID_NL80211_SUBCMD_WIFI_RANGE_START, + + WIFI_SUBCMD_GET_FEATURE_SET, /* 0x0002 */ + WIFI_SUBCMD_GET_FEATURE_SET_MATRIX, /* 0x0003 */ + WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI, /* 0x0004 */ + WIFI_SUBCMD_NODFS_SET, /* 0x0005 */ + WIFI_SUBCMD_SET_COUNTRY_CODE, /* 0x0006 */ + WIFI_SUBCMD_SET_RSSI_MONITOR, /* 0x0007 */ + + WIFI_SUBCMD_GET_ROAMING_CAPABILITIES, /* 0x0008 */ + WIFI_SUBCMD_CONFIG_ROAMING = 0x000a, /* 0x000a */ + WIFI_SUBCMD_ENABLE_ROAMING = 0x000b, /* 0x000b */ + WIFI_SUBCMD_SELECT_TX_POWER_SCENARIO, /* 0x000c */ + /* Add more sub commands here */ + +} WIFI_SUB_COMMAND; + +typedef enum { + GSCAN_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START, + + GSCAN_SUBCMD_SET_CONFIG, /* 0x1001 */ + GSCAN_SUBCMD_SET_SCAN_CONFIG, /* 0x1002 */ + GSCAN_SUBCMD_ENABLE_GSCAN, /* 0x1003 */ + GSCAN_SUBCMD_GET_SCAN_RESULTS, /* 0x1004 */ + GSCAN_SUBCMD_SCAN_RESULTS, /* 0x1005 */ + + GSCAN_SUBCMD_SET_HOTLIST, /* 0x1006 */ + + GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG, /* 0x1007 */ + GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, /* 0x1008 */ + /* Add more sub commands here */ + +} GSCAN_SUB_COMMAND; + +typedef enum { + LSTATS_SUBCMD_GET_INFO = ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START, +} LSTATS_SUB_COMMAND; + + +/* moved from wifi_logger.cpp */ +enum DEBUG_SUB_COMMAND { + LOGGER_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START, + LOGGER_GET_VER +}; + +/* moved from wifi_logger.cpp */ +enum LOGGER_ATTRIBUTE { + LOGGER_ATTRIBUTE_DRIVER_VER, + LOGGER_ATTRIBUTE_FW_VER +}; + +typedef enum { + GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS, + GSCAN_EVENT_HOTLIST_RESULTS_FOUND, + GSCAN_EVENT_SCAN_RESULTS_AVAILABLE, + GSCAN_EVENT_FULL_SCAN_RESULTS, + RTT_EVENT_COMPLETE, + GSCAN_EVENT_COMPLETE_SCAN, + GSCAN_EVENT_HOTLIST_RESULTS_LOST +} WIFI_VENDOR_EVENT; + +typedef enum { + WIFI_ATTRIBUTE_BAND = 1, + WIFI_ATTRIBUTE_NUM_CHANNELS, + WIFI_ATTRIBUTE_CHANNEL_LIST, + + WIFI_ATTRIBUTE_NUM_FEATURE_SET, + WIFI_ATTRIBUTE_FEATURE_SET, + WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, + WIFI_ATTRIBUTE_NODFS_VALUE, + WIFI_ATTRIBUTE_COUNTRY_CODE, + + WIFI_ATTRIBUTE_MAX_RSSI, + WIFI_ATTRIBUTE_MIN_RSSI, + WIFI_ATTRIBUTE_RSSI_MONITOR_START, + + WIFI_ATTRIBUTE_ROAMING_CAPABILITIES, + WIFI_ATTRIBUTE_ROAMING_BLACKLIST_NUM, + WIFI_ATTRIBUTE_ROAMING_BLACKLIST_BSSID, + WIFI_ATTRIBUTE_ROAMING_WHITELIST_NUM, + WIFI_ATTRIBUTE_ROAMING_WHITELIST_SSID, + WIFI_ATTRIBUTE_ROAMING_STATE + +} WIFI_ATTRIBUTE; + +typedef enum { + GSCAN_ATTRIBUTE_CAPABILITIES = 1, + + GSCAN_ATTRIBUTE_NUM_BUCKETS = 10, + GSCAN_ATTRIBUTE_BASE_PERIOD, + GSCAN_ATTRIBUTE_BUCKETS_BAND, + GSCAN_ATTRIBUTE_BUCKET_ID, + GSCAN_ATTRIBUTE_BUCKET_PERIOD, + GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS, + GSCAN_ATTRIBUTE_BUCKET_CHANNELS, + GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, + GSCAN_ATTRIBUTE_REPORT_THRESHOLD, + GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, + + GSCAN_ATTRIBUTE_ENABLE_FEATURE = 20, + GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, /* indicates no more results */ + GSCAN_ATTRIBUTE_FLUSH_FEATURE, /* Flush all the configs */ + GSCAN_ENABLE_FULL_SCAN_RESULTS, + GSCAN_ATTRIBUTE_REPORT_EVENTS, + + GSCAN_ATTRIBUTE_NUM_OF_RESULTS = 30, + GSCAN_ATTRIBUTE_FLUSH_RESULTS, + GSCAN_ATTRIBUTE_SCAN_RESULTS, /* flat array of wifi_scan_result */ + GSCAN_ATTRIBUTE_SCAN_ID, /* indicates scan number */ + GSCAN_ATTRIBUTE_SCAN_FLAGS, /* indicates if scan was aborted */ + GSCAN_ATTRIBUTE_AP_FLAGS, /* flags on significant change event */ + + GSCAN_ATTRIBUTE_SSID = 40, + GSCAN_ATTRIBUTE_BSSID, + GSCAN_ATTRIBUTE_CHANNEL, + GSCAN_ATTRIBUTE_RSSI, + GSCAN_ATTRIBUTE_TIMESTAMP, + GSCAN_ATTRIBUTE_RTT, + GSCAN_ATTRIBUTE_RTTSD, + + GSCAN_ATTRIBUTE_HOTLIST_BSSIDS = 50, + GSCAN_ATTRIBUTE_RSSI_LOW, + GSCAN_ATTRIBUTE_RSSI_HIGH, + GSCAN_ATTRIBUTE_HOTLIST_ELEM, + GSCAN_ATTRIBUTE_HOTLIST_FLUSH, + + GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE = 60, + GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, + GSCAN_ATTRIBUTE_MIN_BREACHING, + GSCAN_ATTRIBUTE_NUM_AP, + GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS, + GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + +} GSCAN_ATTRIBUTE; + +typedef enum { + LSTATS_ATTRIBUTE_STATS = 2, +} LSTATS_ATTRIBUTE; + +typedef enum { + WIFI_BAND_UNSPECIFIED, + WIFI_BAND_BG = 1, /* 2.4 GHz */ + WIFI_BAND_A = 2, /* 5 GHz without DFS */ + WIFI_BAND_A_DFS = 4, /* 5 GHz DFS only */ + WIFI_BAND_A_WITH_DFS = 6, /* 5 GHz with DFS */ + WIFI_BAND_ABG = 3, /* 2.4 GHz + 5 GHz; no DFS */ + WIFI_BAND_ABG_WITH_DFS = 7, /* 2.4 GHz + 5 GHz with DFS */ +} WIFI_BAND; + +typedef enum { + WIFI_SCAN_BUFFER_FULL, + WIFI_SCAN_COMPLETE, +} WIFI_SCAN_EVENT; + +#define GSCAN_MAX_REPORT_THRESHOLD 1024000 +#define GSCAN_MAX_CHANNELS 8 +#define GSCAN_MAX_BUCKETS 8 +#define MAX_HOTLIST_APS 16 +#define MAX_SIGNIFICANT_CHANGE_APS 16 +#define PSCAN_MAX_SCAN_CACHE_SIZE 16 +#define PSCAN_MAX_AP_CACHE_PER_SCAN 16 +#define PSCAN_VERSION 1 + +#define MAX_BUFFERED_GSCN_RESULTS 5 + + + +#define GSCAN_MAX_REPORT_THRESHOLD 1024000 +#define GSCAN_MAX_CHANNELS 8 +#define GSCAN_MAX_BUCKETS 8 +#define MAX_HOTLIST_APS 16 +#define MAX_SIGNIFICANT_CHANGE_APS 16 +#define PSCAN_MAX_SCAN_CACHE_SIZE 16 +#define PSCAN_MAX_AP_CACHE_PER_SCAN 16 +#define PSCAN_VERSION 1 + +#define MAX_BUFFERED_GSCN_RESULTS 5 + +#define MAX_FW_ROAMING_BLACKLIST_SIZE 16 +#define MAX_FW_ROAMING_WHITELIST_SIZE 16 +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +typedef UINT_64 wifi_timestamp; /* In microseconds (us) */ +typedef UINT_64 wifi_timespan; /* In nanoseconds (ns) */ + +typedef UINT_8 mac_addr[6]; +typedef UINT_32 wifi_channel; /* indicates channel frequency in MHz */ +typedef INT_32 wifi_rssi; + +/******************************************************************************* +* MACROS +******************************************************************************** +*/ + +#if KERNEL_VERSION(3, 5, 0) <= LINUX_VERSION_CODE +/* +* #define NLA_PUT(skb, attrtype, attrlen, data) \ +* do { \ +* if (unlikely(nla_put(skb, attrtype, attrlen, data) < 0)) \ +* goto nla_put_failure; \ +* } while (0) +* +*#define NLA_PUT_TYPE(skb, type, attrtype, value) \ +* do { \ +* type __tmp = value; \ +* NLA_PUT(skb, attrtype, sizeof(type), &__tmp); \ +* } while (0) +*/ +#define NLA_PUT(skb, attrtype, attrlen, data) mtk_cfg80211_NLA_PUT(skb, attrtype, attrlen, data) + +#define NLA_PUT_TYPE(skb, type, attrtype, value) mtk_cfg80211_nla_put_type(skb, type, attrtype, value) + +#define NLA_PUT_U8(skb, attrtype, value) \ + NLA_PUT_TYPE(skb, NLA_PUT_DATE_U8, attrtype, value) + +#define NLA_PUT_U16(skb, attrtype, value) \ + NLA_PUT_TYPE(skb, NLA_PUT_DATE_U16, attrtype, value) + +#define NLA_PUT_U32(skb, attrtype, value) \ + NLA_PUT_TYPE(skb, NLA_PUT_DATE_U32, attrtype, value) + +#define NLA_PUT_U64(skb, attrtype, value) \ + NLA_PUT_TYPE(skb, NLA_PUT_DATE_U64, attrtype, value) + +#endif + +/******************************************************************************** +* P R I V A T E D A T A +* +********************************************************************************/ + +typedef struct _PARAM_WIFI_GSCAN_GET_RESULT_PARAMS { + UINT_32 get_num; + UINT_8 flush; +} PARAM_WIFI_GSCAN_GET_RESULT_PARAMS, *P_PARAM_WIFI_GSCAN_GET_RESULT_PARAMS; + +typedef struct _PARAM_WIFI_GSCAN_ACTION_CMD_PARAMS { + UINT_8 ucPscanAct; + UINT_8 aucReserved[3]; +} PARAM_WIFI_GSCAN_ACTION_CMD_PARAMS, *P_PARAM_WIFI_GSCAN_ACTION_CMD_PARAMS; + +typedef struct _PARAM_WIFI_GSCAN_CAPABILITIES_STRUCT_T { + UINT_32 max_scan_cache_size; /*total space allocated for scan (in bytes) */ + UINT_32 max_scan_buckets; /*maximum number of channel buckets */ + UINT_32 max_ap_cache_per_scan; /*maximum number of APs that can be stored per scan */ + UINT_32 max_rssi_sample_size; /*number of RSSI samples used for averaging RSSI */ + UINT_32 max_scan_reporting_threshold; /*max possible report_threshold as described in wifi_scan_cmd_params */ + UINT_32 max_hotlist_aps; /*maximum number of entries for hotlist APs */ + UINT_32 max_significant_wifi_change_aps; /*maximum number of entries for significant wifi change APs */ + UINT_32 max_bssid_history_entries; /*number of BSSID/RSSI entries that device can hold */ +} PARAM_WIFI_GSCAN_CAPABILITIES_STRUCT_T, *P_PARAM_WIFI_GSCAN_CAPABILITIES_STRUCT_T; + +typedef struct _PARAM_WIFI_GSCAN_CHANNEL_SPEC { + UINT_32 channel; + UINT_32 dwellTimeMs; + UINT_32 passive; + /* Add channel class */ +} PARAM_WIFI_GSCAN_CHANNEL_SPEC, *P_PARAM_WIFI_GSCAN_CHANNEL_SPEC; + +typedef struct _PARAM_WIFI_GSCAN_BUCKET_SPEC { + UINT_32 bucket; /* bucket index, 0 based */ + WIFI_BAND band; /*when UNSPECIFIED, use channel lis */ + UINT_32 period; /* desired period, in millisecond; if this is too low, the firmware should choose to generate + * results as fast as it can instead of failing the command + */ + /* report_events semantics - + * 0 => report only when scan history is % full + * 1 => same as 0 + report a scan completion event after scanning this bucket + * 2 => same as 1 + forward scan results (beacons/probe responses + IEs) in real time to HAL + * 3 => same as 2 + forward scan results (beacons/probe responses + IEs) in real time to + * supplicant as well (optional) . + */ + UINT_8 report_events; + + UINT_32 num_channels; + PARAM_WIFI_GSCAN_CHANNEL_SPEC channels[GSCAN_MAX_CHANNELS]; + /* channels to scan; these may include DFS channels */ +} PARAM_WIFI_GSCAN_BUCKET_SPEC, *P_PARAM_WIFI_GSCAN_BUCKET_SPEC; + +typedef struct _PARAM_WIFI_GSCAN_CMD_PARAMS { + UINT_32 base_period; /* base timer period in ms */ + UINT_32 max_ap_per_scan; + /* number of APs to store in each scan in the + * BSSID/RSSI history buffer (keep the highest RSSI APs) + */ + UINT_32 report_threshold; /* in %, when scan buffer is this much full, wake up AP */ + UINT_32 num_scans; + UINT_32 num_buckets; + PARAM_WIFI_GSCAN_BUCKET_SPEC buckets[GSCAN_MAX_BUCKETS]; +} PARAM_WIFI_GSCAN_CMD_PARAMS, *P_PARAM_WIFI_GSCAN_CMD_PARAMS; + +typedef struct _PARAM_WIFI_GSCAN_RESULT { + wifi_timestamp ts; /* time since boot (in microsecond) when the result was */ + /* retrieved */ + UINT_8 ssid[32 + 1]; /* null terminated */ + mac_addr bssid; + wifi_channel channel; /* channel frequency in MHz */ + wifi_rssi rssi; /* in db */ + wifi_timespan rtt; /* in nanoseconds */ + wifi_timespan rtt_sd; /* standard deviation in rtt */ + UINT_16 beacon_period; /* period advertised in the beacon */ + UINT_16 capability; /* capabilities advertised in the beacon */ + UINT_32 ie_length; /* size of the ie_data blob */ + UINT_8 ie_data[1]; /* blob of all the information elements found in the */ + /* beacon; this data should be a packed list of */ + /* wifi_information_element objects, one after the other. */ + /* other fields */ +} PARAM_WIFI_GSCAN_RESULT, *P_PARAM_WIFI_GSCAN_RESULT; + + /* Significant wifi change */ +#if 0 + typedef struct _PARAM_WIFI_CHANGE_RESULT { + mac_addr bssid; /* BSSID */ + wifi_channel channel; /* channel frequency in MHz */ + UINT_32 num_rssi; /* number of rssi samples */ + wifi_rssi rssi[8]; /* RSSI history in db */ + } PARAM_WIFI_CHANGE_RESULT, *P_PARAM_WIFI_CHANGE_RESULT; +#endif + +typedef struct _PARAM_WIFI_CHANGE_RESULT { + UINT_16 flags; + UINT_16 channel; + mac_addr bssid; /* BSSID */ + INT_8 rssi[8]; /* RSSI history in db */ +} PARAM_WIFI_CHANGE_RESULT, *P_PARAM_WIFI_CHANGE_RESULT; + +typedef struct _PARAM_AP_THRESHOLD { + mac_addr bssid; /* AP BSSID */ + wifi_rssi low; /* low threshold */ + wifi_rssi high; /* high threshold */ + wifi_channel channel; /* channel hint */ +} PARAM_AP_THRESHOLD, *P_PARAM_AP_THRESHOLD; + +typedef struct _PARAM_WIFI_BSSID_HOTLIST { + UINT_32 lost_ap_sample_size; + UINT_32 num_ap; /* number of hotlist APs */ + PARAM_AP_THRESHOLD ap[MAX_HOTLIST_APS]; /* hotlist APs */ +} PARAM_WIFI_BSSID_HOTLIST, *P_PARAM_WIFI_BSSID_HOTLIST; + +typedef struct _PARAM_WIFI_SIGNIFICANT_CHANGE { + UINT_16 rssi_sample_size; /* number of samples for averaging RSSI */ + UINT_16 lost_ap_sample_size; /* number of samples to confirm AP loss */ + UINT_16 min_breaching; /* number of APs breaching threshold */ + UINT_16 num_ap; /* max 64 */ + PARAM_AP_THRESHOLD ap[MAX_SIGNIFICANT_CHANGE_APS]; +} PARAM_WIFI_SIGNIFICANT_CHANGE, *P_PARAM_WIFI_SIGNIFICANT_CHANGE; + +/* channel operating width */ +typedef enum { + WIFI_CHAN_WIDTH_20 = 0, + WIFI_CHAN_WIDTH_40 = 1, + WIFI_CHAN_WIDTH_80 = 2, + WIFI_CHAN_WIDTH_160 = 3, + WIFI_CHAN_WIDTH_80P80 = 4, + WIFI_CHAN_WIDTH_5 = 5, + WIFI_CHAN_WIDTH_10 = 6, + WIFI_CHAN_WIDTH_INVALID = -1 +} WIFI_CHANNEL_WIDTH; + +/* channel information */ +typedef struct { + WIFI_CHANNEL_WIDTH width; + UINT_32 center_freq; + UINT_32 center_freq0; + UINT_32 center_freq1; +} WIFI_CHANNEL_INFO; + +/* channel statistics */ +typedef struct { + WIFI_CHANNEL_INFO channel; + UINT_32 on_time; + UINT_32 cca_busy_time; +} WIFI_CHANNEL_STAT; + +/* radio statistics */ +typedef struct { + UINT_32 radio; + UINT_32 on_time; + UINT_32 tx_time; + UINT_32 rx_time; + UINT_32 on_time_scan; + UINT_32 on_time_nbd; + UINT_32 on_time_gscan; + UINT_32 on_time_roam_scan; + UINT_32 on_time_pno_scan; + UINT_32 on_time_hs20; + UINT_32 num_channels; + WIFI_CHANNEL_STAT channels[]; +} WIFI_RADIO_STAT; + +/* wifi rate */ +typedef struct { + UINT_32 preamble:3; + UINT_32 nss:2; + UINT_32 bw:3; + UINT_32 rateMcsIdx:8; + + UINT_32 reserved:16; + UINT_32 bitrate; +} WIFI_RATE; + +/* per rate statistics */ +typedef struct { + WIFI_RATE rate; + UINT_32 tx_mpdu; + UINT_32 rx_mpdu; + UINT_32 mpdu_lost; + UINT_32 retries; + UINT_32 retries_short; + UINT_32 retries_long; +} WIFI_RATE_STAT; + +/*wifi_interface_link_layer_info*/ +typedef enum { + WIFI_DISCONNECTED = 0, + WIFI_AUTHENTICATING = 1, + WIFI_ASSOCIATING = 2, + WIFI_ASSOCIATED = 3, + WIFI_EAPOL_STARTED = 4, + WIFI_EAPOL_COMPLETED = 5, +} WIFI_CONNECTION_STATE; + +typedef enum { + WIFI_ROAMING_IDLE = 0, + WIFI_ROAMING_ACTIVE = 1, +} WIFI_ROAM_STATE; + +typedef enum { + WIFI_INTERFACE_STA = 0, + WIFI_INTERFACE_SOFTAP = 1, + WIFI_INTERFACE_IBSS = 2, + WIFI_INTERFACE_P2P_CLIENT = 3, + WIFI_INTERFACE_P2P_GO = 4, + WIFI_INTERFACE_NAN = 5, + WIFI_INTERFACE_MESH = 6, + WIFI_INTERFACE_UNKNOWN = -1 +} WIFI_INTERFACE_MODE; + +typedef struct { + WIFI_INTERFACE_MODE mode; + u8 mac_addr[6]; + WIFI_CONNECTION_STATE state; + WIFI_ROAM_STATE roaming; + u32 capabilities; + u8 ssid[33]; + u8 bssid[6]; + u8 ap_country_str[3]; + u8 country_str[3]; +} WIFI_INTERFACE_LINK_LAYER_INFO; + +/* access categories */ +typedef enum { + WIFI_AC_VO = 0, + WIFI_AC_VI = 1, + WIFI_AC_BE = 2, + WIFI_AC_BK = 3, + WIFI_AC_MAX = 4, +} WIFI_TRAFFIC_AC; + +/* wifi peer type */ +typedef enum { + WIFI_PEER_STA, + WIFI_PEER_AP, + WIFI_PEER_P2P_GO, + WIFI_PEER_P2P_CLIENT, + WIFI_PEER_NAN, + WIFI_PEER_TDLS, + WIFI_PEER_INVALID, +} WIFI_PEER_TYPE; + +/* per peer statistics */ +typedef struct { + WIFI_PEER_TYPE type; + UINT_8 peer_mac_address[6]; + UINT_32 capabilities; + UINT_32 num_rate; + WIFI_RATE_STAT rate_stats[]; +} WIFI_PEER_INFO; + +/* per access category statistics */ +typedef struct { + WIFI_TRAFFIC_AC ac; + UINT_32 tx_mpdu; + UINT_32 rx_mpdu; + UINT_32 tx_mcast; + + UINT_32 rx_mcast; + UINT_32 rx_ampdu; + UINT_32 tx_ampdu; + UINT_32 mpdu_lost; + UINT_32 retries; + UINT_32 retries_short; + UINT_32 retries_long; + UINT_32 contention_time_min; + UINT_32 contention_time_max; + UINT_32 contention_time_avg; + UINT_32 contention_num_samples; +} WIFI_WMM_AC_STAT; + +/* interface statistics */ +typedef struct { + WIFI_INTERFACE_LINK_LAYER_INFO info; + UINT_32 beacon_rx; + UINT_32 mgmt_rx; + UINT_32 mgmt_action_rx; + UINT_32 mgmt_action_tx; + wifi_rssi rssi_mgmt; + wifi_rssi rssi_data; + wifi_rssi rssi_ack; + WIFI_WMM_AC_STAT ac[WIFI_AC_MAX]; + UINT_32 num_peers; + WIFI_PEER_INFO peer_info[]; +} WIFI_IFACE_STAT; + + +typedef enum _ENUM_NLA_PUT_DATE_TYPE { + NLA_PUT_DATE_U8 = 0, + NLA_PUT_DATE_U16, + NLA_PUT_DATE_U32, + NLA_PUT_DATE_U64, +} ENUM_NLA_PUT_DATE_TYPE; + + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + + + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +int mtk_cfg80211_NLA_PUT(struct sk_buff *skb, int attrtype, int attrlen, const void *data); + +int mtk_cfg80211_nla_put_type(struct sk_buff *skb, ENUM_NLA_PUT_DATE_TYPE type, int attrtype, const void *value); + +int mtk_cfg80211_vendor_get_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_scan_config(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_significant_change(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_hotlist(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_enable_scan(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_enable_full_scan_results(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_get_scan_results(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_get_channel_list(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_country_code(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_get_roaming_capabilities(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_config_roaming(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_enable_roaming(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + + +int mtk_cfg80211_vendor_llstats_get_info(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_event_complete_scan(struct wiphy *wiphy, struct wireless_dev *wdev, + WIFI_SCAN_EVENT complete); + +int mtk_cfg80211_vendor_event_scan_results_available(struct wiphy *wiphy, struct wireless_dev *wdev, + UINT_32 num); + +int mtk_cfg80211_vendor_event_full_scan_results(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_GSCAN_RESULT pdata, UINT_32 data_len); + +int mtk_cfg80211_vendor_event_significant_change_results(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_CHANGE_RESULT pdata, UINT_32 data_len); + +int mtk_cfg80211_vendor_event_hotlist_ap_found(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_GSCAN_RESULT pdata, UINT_32 data_len); + +int mtk_cfg80211_vendor_event_hotlist_ap_lost(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_GSCAN_RESULT pdata, UINT_32 data_len); + +int mtk_cfg80211_vendor_get_supported_feature_set( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); +int mtk_cfg80211_vendor_set_tx_power_scenario( + struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); +int mtk_cfg80211_vendor_get_version(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); +int mtk_cfg80211_vendor_set_scan_mac_oui(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); +#endif /* _GL_VENDOR_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_wext.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_wext.h new file mode 100644 index 0000000000000..0fcb65d0556c0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_wext.h @@ -0,0 +1,366 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +#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 +******************************************************************************** +*/ +extern VOID wlanUpdateChannelTable(P_GLUE_INFO_T prGlueInfo); + +#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 + +/* 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 + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define KILO 1000 +#define RATE_5_5M 11 /* 5.5M */ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef struct _PARAM_FIXED_IEs { + UINT_8 aucTimestamp[8]; + UINT_16 u2BeaconInterval; + UINT_16 u2Capabilities; +} PARAM_FIXED_IEs; + +typedef struct _PARAM_VARIABLE_IE_T { + UINT_8 ucElementID; + UINT_8 ucLength; + UINT_8 aucData[1]; +} PARAM_VARIABLE_IE_T, *P_PARAM_VARIABLE_IE_T; + +#if WIRELESS_EXT < 18 + +#define SIOCSIWMLME 0x8B16 /* request MLME operation; uses struct iw_mlme */ +/* MLME requests (SIOCSIWMLME / struct iw_mlme) */ +#define IW_MLME_DEAUTH 0 +#define IW_MLME_DISASSOC 1 + +/*! \brief SIOCSIWMLME data */ +struct iw_mlme { + __u16 cmd; /*!< IW_MLME_* */ + __u16 reason_code; + struct sockaddr addr; +}; + +#define SIOCSIWAUTH 0x8B32 /* set authentication mode params */ +#define SIOCGIWAUTH 0x8B33 /* get authentication mode params */ +/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */ +#define IW_AUTH_INDEX 0x0FFF +#define IW_AUTH_FLAGS 0xF000 +/* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095) + * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the + * parameter that is being set/get to; value will be read/written to + * struct iw_param value field) + */ +#define IW_AUTH_WPA_VERSION 0 +#define IW_AUTH_CIPHER_PAIRWISE 1 +#define IW_AUTH_CIPHER_GROUP 2 +#define IW_AUTH_KEY_MGMT 3 +#define IW_AUTH_TKIP_COUNTERMEASURES 4 +#define IW_AUTH_DROP_UNENCRYPTED 5 +#define IW_AUTH_80211_AUTH_ALG 6 +#define IW_AUTH_WPA_ENABLED 7 +#define IW_AUTH_RX_UNENCRYPTED_EAPOL 8 +#define IW_AUTH_ROAMING_CONTROL 9 +#define IW_AUTH_PRIVACY_INVOKED 10 +#if CFG_SUPPORT_802_11W +#define IW_AUTH_MFP 12 + +#define IW_AUTH_MFP_DISABLED 0 /* MFP disabled */ +#define IW_AUTH_MFP_OPTIONAL 1 /* MFP optional */ +#define IW_AUTH_MFP_REQUIRED 2 /* MFP required */ +#endif + +/* IW_AUTH_WPA_VERSION values (bit field) */ +#define IW_AUTH_WPA_VERSION_DISABLED 0x00000001 +#define IW_AUTH_WPA_VERSION_WPA 0x00000002 +#define IW_AUTH_WPA_VERSION_WPA2 0x00000004 + +/* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */ +#define IW_AUTH_CIPHER_NONE 0x00000001 +#define IW_AUTH_CIPHER_WEP40 0x00000002 +#define IW_AUTH_CIPHER_TKIP 0x00000004 +#define IW_AUTH_CIPHER_CCMP 0x00000008 +#define IW_AUTH_CIPHER_WEP104 0x00000010 + +/* IW_AUTH_KEY_MGMT values (bit field) */ +#define IW_AUTH_KEY_MGMT_802_1X 1 +#define IW_AUTH_KEY_MGMT_PSK 2 +#define IW_AUTH_KEY_MGMT_WPA_NONE 4 + +/* IW_AUTH_80211_AUTH_ALG values (bit field) */ +#define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001 +#define IW_AUTH_ALG_SHARED_KEY 0x00000002 +#define IW_AUTH_ALG_LEAP 0x00000004 + +/* IW_AUTH_ROAMING_CONTROL values */ +#define IW_AUTH_ROAMING_ENABLE 0 /* driver/firmware based roaming */ +#define IW_AUTH_ROAMING_DISABLE 1 /* user space program used for roaming control */ + +#define SIOCSIWENCODEEXT 0x8B34 /* set encoding token & mode */ +#define SIOCGIWENCODEEXT 0x8B35 /* get encoding token & mode */ +/* SIOCSIWENCODEEXT definitions */ +#define IW_ENCODE_SEQ_MAX_SIZE 8 +/* struct iw_encode_ext ->alg */ +#define IW_ENCODE_ALG_NONE 0 +#define IW_ENCODE_ALG_WEP 1 +#define IW_ENCODE_ALG_TKIP 2 +#define IW_ENCODE_ALG_CCMP 3 +#if CFG_SUPPORT_802_11W +#define IW_ENCODE_ALG_AES_CMAC 5 +#endif + +/* struct iw_encode_ext ->ext_flags */ +#define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001 +#define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002 +#define IW_ENCODE_EXT_GROUP_KEY 0x00000004 +#define IW_ENCODE_EXT_SET_TX_KEY 0x00000008 + +struct iw_encode_ext { + __u32 ext_flags; /*!< IW_ENCODE_EXT_* */ + __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /*!< LSB first */ + __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /*!< LSB first */ + struct sockaddr addr; /*!< ff:ff:ff:ff:ff:ff for broadcast/multicast + * (group) keys or unicast address for + * individual keys + */ + __u16 alg; /*!< IW_ENCODE_ALG_* */ + __u16 key_len; + __u8 key[0]; +}; + +#define SIOCSIWPMKSA 0x8B36 /* PMKSA cache operation */ +#define IW_PMKSA_ADD 1 +#define IW_PMKSA_REMOVE 2 +#define IW_PMKSA_FLUSH 3 + +#define IW_PMKID_LEN 16 + +struct iw_pmksa { + __u32 cmd; /*!< IW_PMKSA_* */ + struct sockaddr bssid; + __u8 pmkid[IW_PMKID_LEN]; +}; + +#define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..) + * (scan results); This includes id and + * length fields. One IWEVGENIE may + * contain more than one IE. Scan + * results may contain one or more + * IWEVGENIE events. + */ +#define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure + * (struct iw_michaelmicfailure) + */ +#define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request. + * The data includes id and length + * fields and may contain more than one + * IE. This event is required in + * Managed mode if the driver + * generates its own WPA/RSN IE. This + * should be sent just before + * IWEVREGISTERED event for the + * association. + */ +#define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association + * Response. The data includes id and + * length fields and may contain more + * than one IE. This may be sent + * between IWEVASSOCREQIE and + * IWEVREGISTERED events for the + * association. + */ +#define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN + * pre-authentication + * (struct iw_pmkid_cand) + */ + +#endif /* WIRELESS_EXT < 18 */ + +#if WIRELESS_EXT < 17 +/* Statistics flags (bitmask in updated) */ +#define IW_QUAL_QUAL_UPDATED 0x1 /* Value was updated since last read */ +#define IW_QUAL_LEVEL_UPDATED 0x2 +#define IW_QUAL_NOISE_UPDATED 0x4 +#define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */ +#define IW_QUAL_LEVEL_INVALID 0x20 +#define IW_QUAL_NOISE_INVALID 0x40 +#endif + +enum { + IEEE80211_FILTER_TYPE_BEACON = 1 << 0, + IEEE80211_FILTER_TYPE_PROBE_REQ = 1 << 1, + IEEE80211_FILTER_TYPE_PROBE_RESP = 1 << 2, + IEEE80211_FILTER_TYPE_ASSOC_REQ = 1 << 3, + IEEE80211_FILTER_TYPE_ASSOC_RESP = 1 << 4, + IEEE80211_FILTER_TYPE_AUTH = 1 << 5, + IEEE80211_FILTER_TYPE_DEAUTH = 1 << 6, + IEEE80211_FILTER_TYPE_DISASSOC = 1 << 7, + IEEE80211_FILTER_TYPE_ALL = 0xFF /* used to check the valid filter bits */ +}; + +#if CFG_SUPPORT_WAPI +#define IW_AUTH_WAPI_ENABLED 0x20 +#define IW_ENCODE_ALG_SMS4 0x20 +#endif + +#if CFG_SUPPORT_WAPI /* Android+ */ +#define IW_AUTH_KEY_MGMT_WAPI_PSK 3 +#define IW_AUTH_KEY_MGMT_WAPI_CERT 4 +#endif +#define IW_AUTH_KEY_MGMT_WPS 5 + +#if CFG_SUPPORT_802_11W +#define IW_AUTH_KEY_MGMT_802_1X_SHA256 7 +#define IW_AUTH_KEY_MGMT_PSK_SHA256 8 +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +extern const struct iw_handler_def wext_handler_def; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/* wireless extensions' ioctls */ +int wext_support_ioctl(IN struct net_device *prDev, IN struct ifreq *prIfReq, IN int i4Cmd); + +int +wext_set_rate(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN struct iw_param *prRate, IN char *pcExtra); + +void +wext_indicate_wext_event(IN P_GLUE_INFO_T prGlueInfo, + IN unsigned int u4Cmd, IN unsigned char *pucData, IN unsigned int u4DataLen); + +struct iw_statistics *wext_get_wireless_stats(struct net_device *prDev); + + +BOOLEAN +wextSrchDesiredWPAIE(IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT PUINT_8 *ppucDesiredIE); + +#if CFG_SUPPORT_WPS +BOOLEAN +wextSrchDesiredWPSIE(IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT PUINT_8 *ppucDesiredIE); +#endif + +#if CFG_SUPPORT_PASSPOINT +BOOLEAN wextSrchDesiredHS20IE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE); + +BOOLEAN wextSrchDesiredInterworkingIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE); + +BOOLEAN wextSrchDesiredAdvProtocolIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE); + +BOOLEAN wextSrchDesiredRoamingConsortiumIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE); +#endif /* CFG_SUPPORT_PASSPOINT */ + +BOOLEAN wextSrchDesiredWAPIIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* WIRELESS_EXT */ + +#endif /* _GL_WEXT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_wext_priv.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_wext_priv.h new file mode 100644 index 0000000000000..5fc6ce38bde95 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/include/gl_wext_priv.h @@ -0,0 +1,437 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +#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 +******************************************************************************** +*/ +extern char *HW_TX_MODE_STR[]; +extern char *HW_TX_RATE_CCK_STR[]; +extern char *HW_TX_RATE_OFDM_STR[]; +extern char *HW_TX_RATE_BW[]; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* New wireless extensions API - SET/GET convention (even ioctl numbers are + * root only) + */ +#define IOCTL_SET_INT (SIOCIWFIRSTPRIV + 0) +#define IOCTL_GET_INT (SIOCIWFIRSTPRIV + 1) + +#define IOCTL_SET_ADDRESS (SIOCIWFIRSTPRIV + 2) +#define IOCTL_GET_ADDRESS (SIOCIWFIRSTPRIV + 3) +#define IOCTL_SET_STR (SIOCIWFIRSTPRIV + 4) +#define IOCTL_GET_STR (SIOCIWFIRSTPRIV + 5) +#define IOCTL_SET_KEY (SIOCIWFIRSTPRIV + 6) +#define IOCTL_GET_KEY (SIOCIWFIRSTPRIV + 7) +#define IOCTL_SET_STRUCT (SIOCIWFIRSTPRIV + 8) +#define IOCTL_GET_STRUCT (SIOCIWFIRSTPRIV + 9) +#define IOCTL_SET_STRUCT_FOR_EM (SIOCIWFIRSTPRIV + 11) +#define IOCTL_SET_INTS (SIOCIWFIRSTPRIV + 12) +#define IOCTL_GET_INTS (SIOCIWFIRSTPRIV + 13) +#define IOCTL_SET_DRIVER (SIOCIWFIRSTPRIV + 14) +#define IOCTL_GET_DRIVER (SIOCIWFIRSTPRIV + 15) + +#if CFG_SUPPORT_QA_TOOL +#define IOCTL_QA_TOOL_DAEMON (SIOCIWFIRSTPRIV + 16) +#define IOCTL_IWPRIV_ATE (SIOCIWFIRSTPRIV + 17) +#endif + +#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 + +#if CFG_SUPPORT_QA_TOOL +#define PRIV_QACMD_SET 29 +#endif + +#define PRIV_CMD_MET_PROFILING 33 + +#if CFG_WOW_SUPPORT +#define PRIV_CMD_SET_WOW_ENABLE 34 +#define PRIV_CMD_SET_WOW_PAR 35 +#endif + +/* 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 +#define OID_CUSTOM_TEST_ICAP_MODE 0xFFA0C913 + +/* 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 +#define PRIV_CMD_TEST_MAGIC_KEY_ICAP 2013 + +/* CFG_SUPPORT_ADVANCE_CONTROL */ +#define TX_RATE_MODE_CCK 0 +#define TX_RATE_MODE_OFDM 1 +#define TX_RATE_MODE_HTMIX 2 +#define TX_RATE_MODE_HTGF 3 +#define TX_RATE_MODE_VHT 4 +#define MAX_TX_MODE 5 + +#if CFG_SUPPORT_ADVANCE_CONTROL +#define CMD_SW_DBGCTL_ADVCTL_SET_ID 0xa1260000 +#define CMD_SW_DBGCTL_ADVCTL_GET_ID 0xb1260000 +#define CMD_SET_NOISE "SET_NOISE" +#define CMD_GET_NOISE "GET_NOISE" +#define CMD_AFH_RANGE_CONFIG "AFH_RANGE_CONFIG" +#define CMD_PTA_CONFIG "PTA_CONFIG" +#define CMD_PTA_TAG_CONFIG "PTA_TAG_CONFIG" +#define CMD_BA_SIZE_CONFIG "BA_SIZE_CONFIG" +#define CMD_TRAFFIC_REPORT "TRAFFIC_REPORT" +#define CMD_SET_POP "SET_POP" +#define CMD_GET_POP "GET_POP" +#define CMD_SET_ED "SET_ED" +#define CMD_GET_ED "GET_ED" +#define CMD_SET_PD "SET_PD" +#define CMD_GET_PD "GET_PD" +#define CMD_SET_MAX_RFGAIN "SET_MAX_RFGAIN" +#define CMD_GET_MAX_RFGAIN "GET_MAX_RFGAIN" +#define CMD_NOISE_HISTOGRAM "NOISE_HISTOGRAM" +#define CMD_SET_ADM_CTRL "SET_ADM" +#define CMD_SET_BCN_TH "SET_BCN_TH" +#define CMD_GET_BCN_TH "GET_BCN_TH" + +enum { + CMD_ADVCTL_NOISE_ID = 1, + CMD_ADVCTL_POP_ID, + CMD_ADVCTL_ED_ID, + CMD_ADVCTL_PD_ID, + CMD_ADVCTL_MAX_RFGAIN_ID, + CMD_ADVCTL_ADM_CTRL_ID, + CMD_ADVCTL_BCN_TH_ID = 9, + CMD_ADVCTL_MAX +}; +#endif + +/******************************************************************************* +* 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; + +#ifdef CONFIG_COMPAT +struct compat_android_wifi_priv_cmd { + compat_caddr_t buf; + int used_len; + int total_len; +}; +#endif /* CONFIG_COMPAT */ +/******************************************************************************* +* P U B 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 HW_TX_RATE_TO_MODE(_x) (((_x) & (0x7 << 6)) >> 6) +#define HW_TX_RATE_TO_MCS(_x, _mode) ((_x) & (0x3f)) +#define HW_TX_RATE_TO_NSS(_x) (((_x) & (0x3 << 9)) >> 9) +#define HW_TX_RATE_TO_STBC(_x) (((_x) & (0x1 << 11)) >> 11) + +#define TX_VECTOR_GET_TX_RATE(_txv) (((_txv)->u4TxVector1) & \ + BITS(0, 6)) +#define TX_VECTOR_GET_TX_LDPC(_txv) ((((_txv)->u4TxVector1) >> 7) & \ + BIT(0)) +#define TX_VECTOR_GET_TX_STBC(_txv) ((((_txv)->u4TxVector1) >> 8) & \ + BITS(0, 1)) +#define TX_VECTOR_GET_TX_FRMODE(_txv) ((((_txv)->u4TxVector1) >> 10) & \ + BITS(0, 1)) +#define TX_VECTOR_GET_TX_MODE(_txv) ((((_txv)->u4TxVector1) >> 12) & \ + BITS(0, 2)) +#define TX_VECTOR_GET_TX_NSTS(_txv) ((((_txv)->u4TxVector1) >> 21) & \ + BITS(0, 1)) +#define TX_VECTOR_GET_TX_PWR(_txv) ((((_txv)->u4TxVector1) >> 24) & \ + BITS(0, 6)) +#define TX_VECTOR_GET_BF_EN(_txv) ((((_txv)->u4TxVector2) >> 31) & \ + BIT(0)) +#define TX_VECTOR_GET_DYN_BW(_txv) ((((_txv)->u4TxVector4) >> 31) & \ + BIT(0)) +#define TX_VECTOR_GET_NO_SOUNDING(_txv) ((((_txv)->u4TxVector4) >> 28) & \ + BIT(0)) +#define TX_VECTOR_GET_TX_SGI(_txv) ((((_txv)->u4TxVector4) >> 27) & \ + BIT(0)) + + +/******************************************************************************* +* 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_set_driver(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); + +int priv_support_driver_cmd(IN struct net_device *prDev, IN OUT struct ifreq *prReq, IN int i4Cmd); + +int priv_support_mdns_offload(IN struct net_device *prDev, + IN OUT struct ifreq *prReq, IN int i4Cmd); + +#ifdef CFG_ANDROID_AOSP_PRIV_CMD +int android_private_support_driver_cmd(IN struct net_device *prDev, IN OUT struct ifreq *prReq, IN int i4Cmd); +#endif /* CFG_ANDROID_AOSP_PRIV_CMD */ + +#ifdef CFG_ALPS_ANDROID_AOSP_PRIV_CMD +int alps_android_private_support_driver_cmd(IN struct net_device *prDev, + IN OUT struct ifreq *prReq, IN int i4Cmd); +#endif /* CFG_ALPS_ANDROID_AOSP_PRIV_CMD */ + +INT_32 priv_driver_cmds(IN struct net_device *prNetDev, IN PCHAR pcCommand, IN INT_32 i4TotalLen); + +int priv_driver_set_cfg(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen); + +#if CFG_SUPPORT_QA_TOOL +int +priv_qa_agent(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, + IN union iwreq_data *prIwReqData, IN char *pcExtra); +int +priv_ate_set(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra); +#endif + +char *hw_rate_ofdm_str(UINT_16 ofdm_idx); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _GL_WEXT_PRIV_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/platform.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/platform.c new file mode 100644 index 0000000000000..57bc83211adae --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/linux/platform.c @@ -0,0 +1,479 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/platform.c#3 +*/ + +/*! \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 +* +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#include +#include + +#include +#include "precomp.h" +#include "gl_os.h" + +#if CFG_ENABLE_EARLY_SUSPEND +#include +#endif + +/******************************************************************************* +* 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 +******************************************************************************** +*/ +#if 1 +static int netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr) +{ + struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; + struct net_device *prDev = ifa->ifa_dev->dev; + 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; + } +#if 0 /* CFG_SUPPORT_PASSPOINT */ + { + /* printk(KERN_INFO "[netdev_event] IPV4_DAD is unlock now!!\n"); */ + prGlueInfo->fgIsDad = FALSE; + } +#endif /* CFG_SUPPORT_PASSPOINT */ + if ((prDev != gPrDev) && (prDev != gPrP2pDev[0]) && (prDev != gPrP2pDev[1])) { + /* DBGLOG(REQ, INFO, ("netdev_event: device is not mine.\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; + } + + if (prGlueInfo->fgIsInSuspendMode == FALSE) { + /* DBGLOG(REQ, INFO, + * ("netdev_event: PARAM_MEDIA_STATE_DISCONNECTED. (%d)\n", + * prGlueInfo->eParamMediaStateIndicated)); + */ + return NOTIFY_DONE; + } + + kalSetNetAddressFromInterface(prGlueInfo, prDev, TRUE); + + return NOTIFY_DONE; + +} +#endif +#if 0 /* CFG_SUPPORT_PASSPOINT */ +static int net6dev_event(struct notifier_block *nb, unsigned long notification, void *ptr) +{ + struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr; + struct net_device *prDev = ifa->idev->dev; + P_GLUE_INFO_T prGlueInfo = NULL; + + if (prDev == NULL) { + DBGLOG(REQ, INFO, "net6dev_event: device is empty.\n"); + return NOTIFY_DONE; + } + + if ((strncmp(prDev->name, "p2p", 3) != 0) && (strncmp(prDev->name, "wlan", 4) != 0)) { + DBGLOG(REQ, INFO, "net6dev_event: xxx\n"); + return NOTIFY_DONE; + } + + if (strncmp(prDev->name, "p2p", 3) == 0) { + /* because we store the address of prGlueInfo in p2p's private date of net device */ + /* *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->prP2PInfo[0]->prDevHandler)) = prGlueInfo; */ + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + } else { /* wlan0 */ + prGlueInfo = (P_GLUE_INFO_T) netdev_priv(prDev); + } + + if (prGlueInfo == NULL) { + DBGLOG(REQ, INFO, "netdev_event: prGlueInfo is empty.\n"); + return NOTIFY_DONE; + } + /* printk(KERN_INFO "[net6dev_event] IPV6_DAD is unlock now!!\n"); */ + prGlueInfo->fgIs6Dad = FALSE; + + return NOTIFY_DONE; +} +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if 1 /* unused */ +static struct notifier_block inetaddr_notifier = { + .notifier_call = netdev_event, +}; +#endif + +#if 0 /* CFG_SUPPORT_PASSPOINT */ +static struct notifier_block inet6addr_notifier = { + .notifier_call = net6dev_event, +}; +#endif /* CFG_SUPPORT_PASSPOINT */ + +void wlanRegisterNotifier(void) +{ +#if CFG_ENABLE_NET_DEV_NOTIFY + + register_inetaddr_notifier(&inetaddr_notifier); +#if 0 /* CFG_SUPPORT_PASSPOINT */ + register_inet6addr_notifier(&inet6addr_notifier); +#endif /* CFG_SUPPORT_PASSPOINT */ + +#endif +} + +void wlanUnregisterNotifier(void) +{ +#if CFG_ENABLE_NET_DEV_NOTIFY + + unregister_inetaddr_notifier(&inetaddr_notifier); +#if 0 /* CFG_SUPPORT_PASSPOINT */ + unregister_inetaddr_notifier(&inet6addr_notifier); +#endif /* CFG_SUPPORT_PASSPOINT */ + +#endif +} + +#if CFG_ENABLE_EARLY_SUSPEND +/*----------------------------------------------------------------------------*/ +/*! +* \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 (wlanSuspend != NULL) + prDesc->suspend = wlanSuspend; + else { + DBGLOG(REQ, INFO, "glRegisterEarlySuspend wlanSuspend ERROR.\n"); + ret = -1; + } + + if (wlanResume != NULL) + prDesc->resume = wlanResume; + else { + DBGLOG(REQ, INFO, "glRegisterEarlySuspend wlanResume ERROR.\n"); + ret = -1; + } + + register_early_suspend(prDesc); + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \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, "[nvram_read] : failed to open!!\n"); + set_fs(old_fs); + return -1; + } + + do { + if ((fd->f_op == NULL) || (fd->f_op->read == NULL)) { + DBGLOG(INIT, INFO, "[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, "[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, "[nvram_write] : failed to open!!\n"); + set_fs(old_fs); + return -1; + } + + do { + if ((fd->f_op == NULL) || (fd->f_op->write == NULL)) { + DBGLOG(INIT, INFO, "[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, "[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/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/version.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/version.h new file mode 100644 index 0000000000000..0583c30e0ffdb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/os/version.h @@ -0,0 +1,140 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/version.h#1 +*/ + +/*! \file "version.h" +* \brief Driver's version definition +* +*/ + + +#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 +#define NIC_NAME "MT6632" +#define NIC_DEVICE_ID "MT6632" +#define NIC_DEVICE_ID_LOW "mt6632" +#endif + +/* NIC driver information */ +#define NIC_VENDOR "MediaTek Inc." +#define NIC_VENDOR_OUI {0x00, 0x0C, 0xE7} + +#define NIC_PRODUCT_NAME "MediaTek Inc. Wireless LAN Adapter" +#define NIC_DRIVER_NAME "MediaTek Inc. Wireless LAN Adapter Driver" + +/* Define our driver version */ +#define NIC_DRIVER_MAJOR_VERSION 2 +#define NIC_DRIVER_MINOR_VERSION 2 +#define NIC_DRIVER_SERIAL_VERSION 0 + +#define STR(s) #s +#define XSTR(x) STR(x) +#define NDV(v) XSTR(NIC_DRIVER_##v##_VERSION) +#define NDV_STR(a, i, s) NDV(a) "." NDV(i) "." NDV(s) +#define NIC_DRIVER_VERSION_STRING NDV_STR(MAJOR, MINOR, SERIAL) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _VERSION_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/prealloc/include/prealloc.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/prealloc/include/prealloc.h new file mode 100644 index 0000000000000..de263f80ae757 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/prealloc/include/prealloc.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + *Copyright (c) 2019 MediaTek Inc. + */ + + +#ifndef _PREALLOC_H +#define _PREALLOC_H + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +enum ENUM_MEM_ID { + MEM_ID_NIC_ADAPTER, + MEM_ID_IO_BUFFER, +#if defined(_HIF_SDIO) + MEM_ID_IO_CTRL, + MEM_ID_RX_DATA, +#endif +#if defined(_HIF_USB) + MEM_ID_TX_CMD, + MEM_ID_TX_DATA_FFA, + MEM_ID_TX_DATA, + MEM_ID_RX_EVENT, + MEM_ID_RX_DATA, +#endif + + MEM_ID_NUM, /* END, Do not modify */ +}; + +/******************************************************************************* +* P U B 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 PreLog(level, ...) pr_info("[wlan][MemPrealloc] " __VA_ARGS__) +#define MP_Dbg(...) PreLog(KERN_DEBUG, __VA_ARGS__) +#define MP_Info(...) PreLog(KERN_INFO, __VA_ARGS__) +#define MP_Err(...) PreLog(KERN_ERR, __VA_ARGS__) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +PVOID preallocGetMem(enum ENUM_MEM_ID memId); + +#endif /* _PREALLOC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/prealloc/prealloc.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/prealloc/prealloc.c new file mode 100644 index 0000000000000..b3f53e85af651 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/prealloc/prealloc.c @@ -0,0 +1,246 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + *Copyright (c) 2019 MediaTek Inc. + */ + +#include +#include +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* + * ----------------- ---------------- ---------- + * | PRE_MEM_BLOCK |-pItemArray->| PRE_MEM_ITEM |-pvBuffer->| Memory | + * |---------------| |--------------| ---------- + * | PRE_MEM_BLOCK |->... | PRE_MEM_ITEM |-pvBuffer->---------- + * |---------------| |--------------| | Memory | + * . . ---------- + * . . + * . . + */ +struct PRE_MEM_ITEM { + PVOID pvBuffer; +}; + +struct PRE_MEM_BLOCK { + PUCHAR pucName; + struct PRE_MEM_ITEM *pItemArray; + UINT_32 u4Count; + UINT_32 u4Size; + UINT_32 u4KmallocFlags; + UINT_32 u4Curr; +}; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +MODULE_LICENSE("Dual BSD/GPL"); + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static INT_32 blockCount; +static struct PRE_MEM_BLOCK arMemBlocks[MEM_ID_NUM]; + +/******************************************************************************* +* M A 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 export function for memory preallocation +* +* \param[in] memId memory id. +* +* \retval void pointer to the memory address +*/ +/*----------------------------------------------------------------------------*/ +PVOID preallocGetMem(enum ENUM_MEM_ID memId) +{ + struct PRE_MEM_BLOCK *block = NULL; + UINT_32 curr = 0, count = 0; + PUCHAR name = NULL; + + /* check memId exist */ + if (memId < 0 || memId >= MEM_ID_NUM) { + MP_Err("request wrong memId %d", memId); + return NULL; + } + + block = &arMemBlocks[memId]; + curr = block->u4Curr; + count = block->u4Count; + name = block->pucName; + block->u4Curr = (curr + 1) % count; /* point to next */ + + /* return request memory address */ + MP_Dbg("request [%s], return [%d]\n", name, curr); + return block->pItemArray[curr].pvBuffer; +} +EXPORT_SYMBOL(preallocGetMem); + +static void preallocFree(void) +{ + INT_32 i = 0, j = 0; + struct PRE_MEM_BLOCK *block = NULL; + struct PRE_MEM_ITEM *items = NULL; + PVOID memory = NULL; + + for (i = 0; i < MEM_ID_NUM; i++) { + block = &arMemBlocks[i]; + MP_Info("free [%d], block name=\"%s\" count=%d size=%d\n", + i, block->pucName, block->u4Count, block->u4Size); + items = block->pItemArray; + if (items == NULL) + continue; + /* free memory */ + for (j = 0; j < block->u4Count; j++) { + memory = items[j].pvBuffer; + MP_Dbg(" - [%d] memory 0x%p\n", j, memory); + kfree(memory); + } + /* free items */ + MP_Dbg(" - items 0x%p\n", items); + kfree(items); + memset(block, 0, sizeof(*block)); + } +} + +static int preallocAlloc(void) +{ + INT_32 i = 0, j = 0; + struct PRE_MEM_BLOCK *block = NULL; + struct PRE_MEM_ITEM *items = NULL; + PVOID memory = NULL; + + for (i = 0; i < MEM_ID_NUM; i++) { + block = &arMemBlocks[i]; + MP_Info("allocate [%d] block name=\"%s\" count=%d size=%d\n", + i, block->pucName, block->u4Count, block->u4Size); + /* allocate u4Count items */ + items = kcalloc(block->u4Count, sizeof(*items), GFP_KERNEL); + if (items == NULL) { + MP_Err("allocate [%d] items failed\n", i); + goto fail; + } + MP_Dbg(" + items 0x%p\n", items); + block->pItemArray = items; + for (j = 0; j < block->u4Count; j++) { + /* allocate u4Size memory */ + memory = kmalloc(block->u4Size, block->u4KmallocFlags); + if (memory == NULL) { + MP_Err("allocate [%d][%d] memory failed\n", i, j); + goto fail; + } + MP_Dbg(" + [%d] memory 0x%p\n", j, memory); + items[j].pvBuffer = memory; + } + } + + return 0; + +fail: + preallocFree(); + return -ENOMEM; +} + +static void preallocAddBlock(enum ENUM_MEM_ID memId, + PUCHAR name, UINT_32 count, UINT_32 size, UINT_32 kmallocFlags) +{ + if (memId != blockCount) { + MP_Err("memId %d != index %d\n", memId, blockCount); + return; + } + arMemBlocks[blockCount].pucName = name; + arMemBlocks[blockCount].pItemArray = NULL; + arMemBlocks[blockCount].u4Count = count; + arMemBlocks[blockCount].u4Size = size; + arMemBlocks[blockCount].u4KmallocFlags = kmallocFlags; + arMemBlocks[blockCount].u4Curr = 0; + blockCount++; +} + +static int __init preallocInit(void) +{ + u32 u4Size; + + blockCount = 0; + + /* ADD BLOCK START, follow the sequence of ENUM_MEM_ID */ + preallocAddBlock(MEM_ID_NIC_ADAPTER, "NIC ADAPTER MEMORY", + 1, MGT_BUFFER_SIZE, + GFP_KERNEL); + + u4Size = HIF_TX_COALESCING_BUFFER_SIZE; + u4Size = u4Size > HIF_RX_COALESCING_BUFFER_SIZE ? + u4Size : HIF_RX_COALESCING_BUFFER_SIZE; + + preallocAddBlock(MEM_ID_IO_BUFFER, "IO BUFFER", + 1, u4Size, + GFP_KERNEL); + +#if defined(_HIF_SDIO) + preallocAddBlock(MEM_ID_IO_CTRL, "IO CTRL", + 1, sizeof(ENHANCE_MODE_DATA_STRUCT_T), + GFP_KERNEL); + preallocAddBlock(MEM_ID_RX_DATA, "RX DATA", + HIF_RX_COALESCING_BUF_COUNT, + HIF_RX_COALESCING_BUFFER_SIZE, + GFP_KERNEL); +#endif +#if defined(_HIF_USB) + preallocAddBlock(MEM_ID_TX_CMD, "TX CMD", + USB_REQ_TX_CMD_CNT, USB_TX_CMD_BUF_SIZE, + GFP_KERNEL); + preallocAddBlock(MEM_ID_TX_DATA_FFA, "TX DATA FFA", + USB_REQ_TX_DATA_FFA_CNT, USB_TX_DATA_BUFF_SIZE, + GFP_KERNEL); +#if CFG_USB_TX_AGG + preallocAddBlock(MEM_ID_TX_DATA, "TX AGG DATA", + (USB_TC_NUM * USB_REQ_TX_DATA_CNT), USB_TX_DATA_BUFF_SIZE, + GFP_KERNEL); +#else + preallocAddBlock(MEM_ID_TX_DATA, "TX DATA", + USB_REQ_TX_DATA_CNT, USB_TX_DATA_BUFF_SIZE, + GFP_KERNEL); +#endif + preallocAddBlock(MEM_ID_RX_EVENT, "RX EVENT", + USB_REQ_RX_EVENT_CNT, USB_RX_EVENT_BUF_SIZE, + GFP_KERNEL); + preallocAddBlock(MEM_ID_RX_DATA, "RX DATA", + USB_REQ_RX_DATA_CNT, USB_RX_DATA_BUF_SIZE, + GFP_KERNEL); +#endif + /* ADD BLOCK END */ + + return preallocAlloc(); +} + +static void __exit preallocExit(void) +{ + preallocFree(); +} + +module_init(preallocInit); +module_exit(preallocExit); From 9d28f8c24114fbbe060b2f05b375b28d2968714d Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 22:25:45 +0800 Subject: [PATCH 30/32] Add files via upload --- .../core/gen4-mt7668/include/CFG_Wifi_File.h | 351 ++ .../core/gen4-mt7668/include/chips/mt6632.h | 113 + .../core/gen4-mt7668/include/chips/mt7668.h | 115 + .../wlan/core/gen4-mt7668/include/config.h | 1064 +++++ .../wlan/core/gen4-mt7668/include/debug.h | 348 ++ .../wlan/core/gen4-mt7668/include/link.h | 415 ++ .../core/gen4-mt7668/include/mgmt/aa_fsm.h | 225 ++ .../core/gen4-mt7668/include/mgmt/ais_fsm.h | 535 +++ .../core/gen4-mt7668/include/mgmt/assoc.h | 136 + .../wlan/core/gen4-mt7668/include/mgmt/auth.h | 151 + .../core/gen4-mt7668/include/mgmt/bow_fsm.h | 189 + .../wlan/core/gen4-mt7668/include/mgmt/bss.h | 237 ++ .../wlan/core/gen4-mt7668/include/mgmt/cnm.h | 313 ++ .../core/gen4-mt7668/include/mgmt/cnm_mem.h | 939 +++++ .../core/gen4-mt7668/include/mgmt/cnm_scan.h | 164 + .../core/gen4-mt7668/include/mgmt/cnm_timer.h | 231 ++ .../core/gen4-mt7668/include/mgmt/hem_mbox.h | 303 ++ .../wlan/core/gen4-mt7668/include/mgmt/hs20.h | 189 + .../wlan/core/gen4-mt7668/include/mgmt/mib.h | 174 + .../core/gen4-mt7668/include/mgmt/p2p_assoc.h | 103 + .../core/gen4-mt7668/include/mgmt/p2p_bss.h | 107 + .../core/gen4-mt7668/include/mgmt/p2p_dev.h | 237 ++ .../gen4-mt7668/include/mgmt/p2p_dev_state.h | 95 + .../core/gen4-mt7668/include/mgmt/p2p_fsm.h | 81 + .../core/gen4-mt7668/include/mgmt/p2p_func.h | 312 ++ .../core/gen4-mt7668/include/mgmt/p2p_ie.h | 100 + .../core/gen4-mt7668/include/mgmt/p2p_rlm.h | 126 + .../gen4-mt7668/include/mgmt/p2p_rlm_obss.h | 113 + .../core/gen4-mt7668/include/mgmt/p2p_role.h | 422 ++ .../gen4-mt7668/include/mgmt/p2p_role_state.h | 129 + .../core/gen4-mt7668/include/mgmt/p2p_scan.h | 117 + .../core/gen4-mt7668/include/mgmt/privacy.h | 248 ++ .../wlan/core/gen4-mt7668/include/mgmt/rate.h | 125 + .../wlan/core/gen4-mt7668/include/mgmt/rlm.h | 423 ++ .../gen4-mt7668/include/mgmt/rlm_domain.h | 770 ++++ .../core/gen4-mt7668/include/mgmt/rlm_obss.h | 146 + .../gen4-mt7668/include/mgmt/rlm_protection.h | 142 + .../gen4-mt7668/include/mgmt/rlm_txpwr_init.h | 1253 ++++++ .../gen4-mt7668/include/mgmt/roaming_fsm.h | 212 + .../wlan/core/gen4-mt7668/include/mgmt/rsn.h | 287 ++ .../wlan/core/gen4-mt7668/include/mgmt/scan.h | 742 ++++ .../wlan/core/gen4-mt7668/include/mgmt/swcr.h | 247 ++ .../wlan/core/gen4-mt7668/include/mgmt/tdls.h | 472 +++ .../wlan/core/gen4-mt7668/include/mgmt/wapi.h | 130 + .../gen4-mt7668/include/mgmt/wlan_typedef.h | 140 + .../wlan/core/gen4-mt7668/include/mgmt/wnm.h | 129 + .../core/gen4-mt7668/include/nic/adapter.h | 1478 +++++++ .../wlan/core/gen4-mt7668/include/nic/bow.h | 266 ++ .../core/gen4-mt7668/include/nic/cmd_buf.h | 194 + .../wlan/core/gen4-mt7668/include/nic/hal.h | 1080 ++++++ .../core/gen4-mt7668/include/nic/hif_rx.h | 155 + .../core/gen4-mt7668/include/nic/hif_tx.h | 168 + .../wlan/core/gen4-mt7668/include/nic/mac.h | 2736 +++++++++++++ .../core/gen4-mt7668/include/nic/mt66xx_reg.h | 993 +++++ .../wlan/core/gen4-mt7668/include/nic/nic.h | 371 ++ .../core/gen4-mt7668/include/nic/nic_rate.h | 158 + .../core/gen4-mt7668/include/nic/nic_rx.h | 1047 +++++ .../core/gen4-mt7668/include/nic/nic_tx.h | 1535 ++++++++ .../core/gen4-mt7668/include/nic/nic_umac.h | 138 + .../wlan/core/gen4-mt7668/include/nic/p2p.h | 327 ++ .../gen4-mt7668/include/nic/p2p_cmd_buf.h | 120 + .../core/gen4-mt7668/include/nic/p2p_mac.h | 393 ++ .../core/gen4-mt7668/include/nic/p2p_nic.h | 112 + .../include/nic/p2p_nic_cmd_event.h | 121 + .../core/gen4-mt7668/include/nic/que_mgt.h | 973 +++++ .../core/gen4-mt7668/include/nic/wlan_def.h | 1099 ++++++ .../core/gen4-mt7668/include/nic_cmd_event.h | 3427 +++++++++++++++++ .../gen4-mt7668/include/nic_init_cmd_event.h | 312 ++ .../core/gen4-mt7668/include/p2p_precomp.h | 248 ++ .../core/gen4-mt7668/include/p2p_typedef.h | 219 ++ .../wlan/core/gen4-mt7668/include/precomp.h | 304 ++ .../wlan/core/gen4-mt7668/include/pwr_mgt.h | 149 + .../wlan/core/gen4-mt7668/include/queue.h | 231 ++ .../wlan/core/gen4-mt7668/include/rftest.h | 428 ++ .../wlan/core/gen4-mt7668/include/typedef.h | 202 + .../wlan/core/gen4-mt7668/include/wlan_bow.h | 302 ++ .../wlan/core/gen4-mt7668/include/wlan_lib.h | 1508 ++++++++ .../wlan/core/gen4-mt7668/include/wlan_oid.h | 2950 ++++++++++++++ .../wlan/core/gen4-mt7668/include/wlan_p2p.h | 271 ++ 79 files changed, 37615 insertions(+) create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/CFG_Wifi_File.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/chips/mt6632.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/chips/mt7668.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/config.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/debug.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/link.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/aa_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/ais_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/assoc.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/auth.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/bow_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/bss.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/cnm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/cnm_mem.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/cnm_scan.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/cnm_timer.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/hem_mbox.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/hs20.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/mib.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_assoc.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_bss.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_dev.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_dev_state.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_func.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_ie.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_rlm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_rlm_obss.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_role.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_role_state.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_scan.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/privacy.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rate.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rlm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rlm_domain.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rlm_obss.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rlm_protection.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rlm_txpwr_init.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/roaming_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rsn.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/scan.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/swcr.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/tdls.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/wapi.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/wlan_typedef.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/wnm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/adapter.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/bow.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/cmd_buf.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/hal.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/hif_rx.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/hif_tx.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/mac.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/mt66xx_reg.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/nic.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/nic_rate.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/nic_rx.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/nic_tx.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/nic_umac.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/p2p.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/p2p_cmd_buf.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/p2p_mac.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/p2p_nic.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/p2p_nic_cmd_event.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/que_mgt.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/wlan_def.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic_cmd_event.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic_init_cmd_event.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/p2p_precomp.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/p2p_typedef.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/precomp.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/pwr_mgt.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/queue.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/rftest.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/typedef.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/wlan_bow.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/wlan_lib.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/wlan_oid.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/wlan_p2p.h diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/CFG_Wifi_File.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/CFG_Wifi_File.h new file mode 100644 index 0000000000000..474a9ee6d904f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/CFG_Wifi_File.h @@ -0,0 +1,351 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + +#ifndef _CFG_WIFI_FILE_H +#define _CFG_WIFI_FILE_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_typedef.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +/* duplicated from nic_cmd_event.h to avoid header dependency */ +typedef struct _TX_PWR_PARAM_T { + INT_8 cTxPwr2G4Cck; /* signed, in unit of 0.5dBm */ + INT_8 cTxPwr2G4Dsss; /* signed, in unit of 0.5dBm */ + INT_8 acReserved[2]; + + 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 _TX_AC_PWR_T { + INT_8 c11AcTxPwr_BPSK; + INT_8 c11AcTxPwr_QPSK; + INT_8 c11AcTxPwr_16QAM; + INT_8 c11AcTxPwr_MCS5_MCS6; + INT_8 c11AcTxPwr_MCS7; + INT_8 c11AcTxPwr_MCS8; + INT_8 c11AcTxPwr_MCS9; + INT_8 c11AcTxPwrVht40_OFFSET; + INT_8 c11AcTxPwrVht80_OFFSET; + INT_8 c11AcTxPwrVht160_OFFSET; + INT_8 acReverse[2]; +} TX_AC_PWR_T, *P_TX_AC_PWR_T; + +typedef struct _RSSI_PATH_COMPASATION_T { + INT_8 c2GRssiCompensation; + INT_8 c5GRssiCompensation; +} RSSI_PATH_COMPASATION_T, *P_RSSI_PATH_COMPASATION_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; + +#if 0 +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; +#else + +typedef struct _AC_PWR_SETTING_STRUCT { + UINT_8 c11AcTxPwr_BPSK; + UINT_8 c11AcTxPwr_QPSK; + UINT_8 c11AcTxPwr_16QAM; + UINT_8 c11AcTxPwr_MCS5_MCS6; + UINT_8 c11AcTxPwr_MCS7; + UINT_8 c11AcTxPwr_MCS8; + UINT_8 c11AcTxPwr_MCS9; + UINT_8 c11AcTxPwr_Reserved; + UINT_8 c11AcTxPwrVht40_OFFSET; + UINT_8 c11AcTxPwrVht80_OFFSET; + UINT_8 c11AcTxPwrVht160_OFFSET; +} AC_PWR_SETTING_STRUCT, *P_AC_PWR_SETTING_STRUCT; + +typedef struct _BANDEDGE_5G_T { + UINT_8 uc5GBandEdgePwrUsed; + UINT_8 c5GBandEdgeMaxPwrOFDM20; + UINT_8 c5GBandEdgeMaxPwrOFDM40; + UINT_8 c5GBandEdgeMaxPwrOFDM80; + +} BANDEDGE_5G_T, *P_BANDEDGE_5G_T; + +typedef struct _NEW_EFUSE_MAPPING2NVRAM_T { + UINT_8 ucReverse1[8]; + UINT_16 u2Signature; + BANDEDGE_5G_T r5GBandEdgePwr; + UINT_8 ucReverse2[14]; + + /* 0x50 */ + UINT_8 aucChOffset[3]; + UINT_8 ucChannelOffsetVaild; + UINT_8 acAllChannelOffset; + UINT_8 aucChOffset3[11]; + + /* 0x60 */ + UINT_8 auc5GChOffset[8]; + UINT_8 uc5GChannelOffsetVaild; + UINT_8 aucChOffset4[7]; + + /* 0x70 */ + AC_PWR_SETTING_STRUCT r11AcTxPwr; + UINT_8 uc11AcTxPwrValid; + + UINT_8 ucReverse4[20]; + + /* 0x90 */ + AC_PWR_SETTING_STRUCT r11AcTxPwr2G; + UINT_8 uc11AcTxPwrValid2G; + + UINT_8 ucReverse5[40]; +} NEW_EFUSE_MAPPING2NVRAM_T, *P_NEW_EFUSE_MAPPING2NVRAM_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; +#if CFG_SUPPORT_NVRAM_5G + union { + NEW_EFUSE_MAPPING2NVRAM_T u; + UINT_8 aucEFUSE[144]; + } EfuseMapping; +#else + UINT_8 aucEFUSE[144]; +#endif + 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 ucRxDiversity; + RSSI_PATH_COMPASATION_T rRssiPathCompensation; + UINT_8 fgRssiCompensationVaildbit; + UINT_8 ucGpsDesense; + UINT_16 u2FeatureReserved; + UINT_8 aucPreTailReserved; + UINT_8 aucTailReserved[256 - 15]; +} MT6620_CFG_PARAM_STRUCT, *P_MT6620_CFG_PARAM_STRUCT, WIFI_CFG_PARAM_STRUCT, *P_WIFI_CFG_PARAM_STRUCT; + +#endif +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifndef DATA_STRUCT_INSPECTING_ASSERT +#define DATA_STRUCT_INSPECTING_ASSERT(expr) \ + {switch (0) {case 0: case (expr): default:; } } +#endif + +#define CFG_FILE_WIFI_REC_SIZE sizeof(WIFI_CFG_PARAM_STRUCT) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#ifndef _lint +/* We don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + * We'll need this to guarantee the same member order in different structures + * to simply handling effort in some functions. + */ +static __KAL_INLINE__ VOID nvramOffsetCheck(VOID) +{ + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part2OwnVersion) == 256); + + DATA_STRUCT_INSPECTING_ASSERT(sizeof(WIFI_CFG_PARAM_STRUCT) == 512); +#if CFG_SUPPORT_NVRAM_5G + DATA_STRUCT_INSPECTING_ASSERT((OFFSET_OF(WIFI_CFG_PARAM_STRUCT, EfuseMapping) & 0x0001) == 0); +#else + DATA_STRUCT_INSPECTING_ASSERT((OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucEFUSE) & 0x0001) == 0); +#endif + DATA_STRUCT_INSPECTING_ASSERT((OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucRegSubbandInfo) & 0x0001) + == 0); +} +#endif + +#endif /* _CFG_WIFI_FILE_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/chips/mt6632.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/chips/mt6632.h new file mode 100644 index 0000000000000..8b29ee69d04fc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/chips/mt6632.h @@ -0,0 +1,113 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/chips/mt6632.h#1 +*/ + +/*! \file mt6632.h +* \brief This file contains the info of MT6632 +*/ + +#ifndef _MT6632_H +#define _MT6632_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 MT6632_CHIP_ID (0x6632) +#define MT6632_SW_SYNC0 WIFI_CFG_SW_SYNC0 +#define MT6632_SW_SYNC0_RDY_OFFSET WIFI_CFG_SYNC0_RDY_OFFSET +#define MT6632_PATCH_START_ADDR (0x000B4000) +#define MT6632_IS_PCIE_32DW_READ (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 /* _MT6632_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/chips/mt7668.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/chips/mt7668.h new file mode 100644 index 0000000000000..df8925161654f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/chips/mt7668.h @@ -0,0 +1,115 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/chips/mt7668.h#1 +*/ + +/*! \file mt7668.h +* \brief This file contains the info of MT7668 +*/ + +#ifndef _MT7668_H +#define _MT7668_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 MT7668_CHIP_ID (0x7668) +#define MT7668_SW_SYNC0 WIFI_RGU_SW_SYNC0 +#define MT7668_SW_SYNC0_RDY_OFFSET WIFI_RGU_SYNC0_RDY_OFFSET +#define MT7668_PATCH_START_ADDR (0x000C8000) +#define MT7668_IS_PCIE_32DW_READ (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 /* _MT7668_H */ + + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/config.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/config.h new file mode 100644 index 0000000000000..b0633cc8d0e68 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/config.h @@ -0,0 +1,1064 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/config.h#3 +*/ + +/*! \file "config.h" +* \brief This file includes the various configurable parameters for customers +* +* This file ncludes the configurable parameters except the parameters indicate the turning-on/off of some features +*/ + +#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 +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* 2 Flags for OS capability */ + +#if defined(_HIF_SDIO) +#ifdef LINUX +#ifdef CONFIG_X86 +#define MTK_WCN_HIF_SDIO 0 +#else +#define MTK_WCN_HIF_SDIO 0 +#endif +#else +#define MTK_WCN_HIF_SDIO 0 +#endif +#else +#define MTK_WCN_HIF_SDIO 0 +#endif + +/* Android build-in driver switch, Mike 2016/11/11*/ +#ifndef CFG_BUILT_IN_DRIVER +#define CFG_BUILT_IN_DRIVER 0 +#endif + +/* Mike 2016/09/01 ALPS update K3.18 80211_disconnect to K4.4 version*/ +/* work around for any alps K3.18 platform*/ +#ifndef CFG_WPS_DISCONNECT +#define CFG_WPS_DISCONNECT 0 +#endif + + +#if (CFG_SUPPORT_AEE == 1) +#define CFG_ENABLE_AEE_MSG 1 +#else +#define CFG_ENABLE_AEE_MSG 0 +#endif + +#define CFG_SUPPORT_MTK_ANDROID_KK 1 + +#define CFG_ENABLE_EARLY_SUSPEND 0 +#define CFG_ENABLE_NET_DEV_NOTIFY 1 + +/* 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" */ +#define CFG_SUPPORT_DEBUG_FS 0 +#ifndef LINUX +#define CFG_FW_FILENAME L"WIFI_RAM_CODE" +#define CFG_CR4_FW_FILENAME L"WIFI_RAM_CODE2" +#else +#define CFG_FW_FILENAME "WIFI_RAM_CODE" +#define CFG_CR4_FW_FILENAME "WIFI_RAM_CODE2" +#endif + +#ifndef CFG_MET_PACKET_TRACE_SUPPORT +#define CFG_MET_PACKET_TRACE_SUPPORT 0 /*move to wlan/MAKEFILE */ +#endif + +#ifndef CFG_MET_TAG_SUPPORT +#define CFG_MET_TAG_SUPPORT 0 +#endif + +/*------------------------------------------------------------------------------ + * Driver config + *------------------------------------------------------------------------------ + */ + +#ifndef LINUX +#define CFG_SUPPORT_CFG_FILE 0 +#else +#define CFG_SUPPORT_CFG_FILE 1 +#endif + +#define CFG_SUPPORT_802_11D 1 /*!< 1(default): Enable 802.11d */ + /* 0: Disable */ + +#define CFG_SUPPORT_RRM 0 /* Radio Reasource Measurement (802.11k) */ +#ifndef CFG_SUPPORT_DFS +#define CFG_SUPPORT_DFS 1 /* DFS (802.11h) */ +#endif +#ifndef CFG_SUPPORT_DFS_MASTER +#define CFG_SUPPORT_DFS_MASTER 1 +#endif + +#if (CFG_SUPPORT_DFS == 1) /* Add by Enlai */ +#define CFG_SUPPORT_QUIET 0 /* Quiet (802.11h) */ +#define CFG_SUPPORT_SPEC_MGMT 1 /* Spectrum Management (802.11h): TPC and DFS */ +#else +#define CFG_SUPPORT_QUIET 0 /* Quiet (802.11h) */ +#define CFG_SUPPORT_SPEC_MGMT 0 /* Spectrum Management (802.11h): TPC and DFS */ +#endif + +#define CFG_SUPPORT_RX_RDG 0 /* 11n feature. RX RDG capability */ +#define CFG_SUPPORT_MFB 0 /* 802.11n MCS Feedback responder */ +#define CFG_SUPPORT_RX_STBC 1 /* 802.11n RX STBC (1SS) */ +#define CFG_SUPPORT_RX_SGI 1 /* 802.11n RX short GI for both 20M and 40M BW */ +#define CFG_SUPPORT_RX_HT_GF 1 /* 802.11n RX HT green-field capability */ +#define CFG_SUPPORT_BFER 1 +#define CFG_SUPPORT_BFEE 1 +#define CFG_SUPPORT_WAPI 1 + +/* Enable QA Tool Support */ +#define CFG_SUPPORT_QA_TOOL 1 + +/* Enable TX BF Support */ +#define CFG_SUPPORT_TX_BF 1 + +/* Enable MU MIMO Support */ +#define CFG_SUPPORT_MU_MIMO 1 + +/* Enable WOW Support */ +#define CFG_WOW_SUPPORT 1 + +/* Enable A-MSDU RX Reordering Support */ +#define CFG_SUPPORT_RX_AMSDU 1 + +/* Enable Android wake_lock operations */ +#ifdef CONFIG_HAS_WAKELOCK +#ifndef CFG_ENABLE_WAKE_LOCK +#define CFG_ENABLE_WAKE_LOCK 1 +#endif + +#else +#undef CFG_ENABLE_WAKE_LOCK +#define CFG_ENABLE_WAKE_LOCK 0 +#endif + +/*------------------------------------------------------------------------------ + * Flags of Buffer mode SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_BUFFER_MODE 1 + +/*------------------------------------------------------------------------------ + * 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 +#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 + *------------------------------------------------------------------------------ + */ +/*!< 1: Do workaround for faster bus timing */ +/* 0(default): Disable */ +#define CFG_EHPI_FASTER_BUS_TIMING 0 + +/*------------------------------------------------------------------------------ + * Flags for UMAC + *------------------------------------------------------------------------------ + */ +#define CFG_UMAC_GENERATION 0x20 + +/*------------------------------------------------------------------------------ + * Flags for HIFSYS Interface + *------------------------------------------------------------------------------ + */ +#ifdef _lint +/* #define _HIF_SDIO 1 */ +#endif + +/* 1(default): Enable SDIO ISR & TX/RX status enhance mode + * 0: Disable + */ +#define CFG_SDIO_INTR_ENHANCE 1 +/* 1(default): Enable SDIO ISR & TX/RX status enhance mode + * 0: Disable + */ +#define CFG_SDIO_RX_ENHANCE 1 +/* 1: Enable SDIO TX enhance mode(Multiple frames in single BLOCK CMD) + * 0(default): Disable + */ +#define CFG_SDIO_TX_AGG 1 + +/* 1: Enable SDIO RX enhance mode(Multiple frames in single BLOCK CMD) + * 0(default): Disable + */ +#define CFG_SDIO_RX_AGG 1 + +/* 1: Enable SDIO RX Tasklet De-Aggregation + * 0(default): Disable + */ +#ifndef CFG_SDIO_RX_AGG_TASKLET +#define CFG_SDIO_RX_AGG_TASKLET 0 +#endif + +#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 + +#ifdef WINDOWS_CE +#define CFG_SDIO_PATHRU_MODE 1 /*!< 1: Support pass through (PATHRU) mode */ + /* 0: Disable */ +#else +#define CFG_SDIO_PATHRU_MODE 0 /*!< 0: Always disable if WINDOWS_CE is not defined */ +#endif + +#define CFG_SDIO_ACCESS_N9_REGISTER_BY_MAILBOX 0 +#define CFG_MAX_RX_ENHANCE_LOOP_COUNT 3 + +#define CFG_USB_TX_AGG 1 +#define CFG_USB_CONSISTENT_DMA 0 +#define CFG_USB_TX_HANDLE_IN_HIF_THREAD 0 +#define CFG_USB_RX_HANDLE_IN_HIF_THREAD 0 + +#ifndef CFG_TX_DIRECT_USB +#define CFG_TX_DIRECT_USB 1 +#endif +#ifndef CFG_RX_DIRECT_USB +#define CFG_RX_DIRECT_USB 1 +#endif + +#define CFG_HW_WMM_BY_BSS 1 +/*------------------------------------------------------------------------------ + * Flags and Parameters for Integration + *------------------------------------------------------------------------------ + */ + +#define CFG_MULTI_ECOVER_SUPPORT 1 + +#define CFG_ENABLE_CAL_LOG 1 +#define CFG_REPORT_RFBB_VERSION 1 + +#define HW_BSSID_NUM 4 /* HW BSSID number by chip */ +#define HW_WMM_NUM 4 /* HW WMM number by chip */ + +#ifndef CFG_CHIP_RESET_SUPPORT +#define CFG_CHIP_RESET_SUPPORT 0 +#endif + +/*------------------------------------------------------------------------------ + * Flags for workaround + *------------------------------------------------------------------------------ + */ + +/*------------------------------------------------------------------------------ + * 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 and Parameters for TX path + *------------------------------------------------------------------------------ + */ + +/*! Maximum number of SW TX packet queue */ +#define CFG_TX_MAX_PKT_NUM 1024 + +/*! Maximum number of SW TX CMD packet buffer */ +#define CFG_TX_MAX_CMD_PKT_NUM 32 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for RX path + *------------------------------------------------------------------------------ + */ + +/*------------------------------------------------------------------------------ +* CONFIG_TITLE : Move BA from FW to Driver +* OWNER : Puff Wen +* Description : Move BA from FW to Driver +*------------------------------------------------------------------------------ +*/ +#define CFG_M0VE_BA_TO_DRIVER 0 + +/*! 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 HIF_NUM_OF_QM_RX_PKT_NUM + +/*! 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 */ +/* TODO: it should be 4096 under emulation mode */ +#define CFG_RX_MAX_PKT_SIZE (28 + 2312 + 12 /*HIF_RX_HEADER_T*/) + +/*! 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 */ + +/*! RX BA capability */ +#define CFG_NUM_OF_RX_BA_AGREEMENTS 8 +#if CFG_M0VE_BA_TO_DRIVER +#define CFG_RX_BA_MAX_WINSIZE 64 +#endif +#define CFG_RX_BA_INC_SIZE 64 +#define CFG_RX_MAX_BA_TID_NUM 8 +#define CFG_RX_REORDERING_ENABLED 1 + +#define CFG_PF_ARP_NS_MAX_NUM 3 + +#define CFG_COMPRESSION_DEBUG 0 +#define CFG_DECOMPRESSION_TMP_ADDRESS 0 +#define CFG_SUPPORT_COMPRESSION_FW_OPTION 0 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for CMD/RESPONSE + *------------------------------------------------------------------------------ + */ +#define CFG_RESPONSE_POLLING_TIMEOUT 1000 +#define CFG_RESPONSE_POLLING_DELAY 5 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Protocol Stack + *------------------------------------------------------------------------------ + */ +/*! Maximum number of BSS in the SCAN list */ +#define CFG_MAX_NUM_BSS_LIST 192 + +#define CFG_MAX_COMMON_IE_BUF_LEN ((1500 * CFG_MAX_NUM_BSS_LIST) / 3) + +/*! Maximum size of Header buffer of each SCAN record */ +#define CFG_RAW_BUFFER_SIZE 1024 + +/*! Maximum size of IE buffer of each SCAN record */ +#define CFG_IE_BUFFER_SIZE 800 + +/*------------------------------------------------------------------------------ + * 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 + *------------------------------------------------------------------------------ + */ +/*!< max number of PMKID cache 16(default) : The Max PMKID cache */ +#define CFG_MAX_PMKID_CACHE 16 + +/*------------------------------------------------------------------------------ + * Auto Channel Selection maximun channel number + *------------------------------------------------------------------------------ + */ +#define MAX_CHN_NUM 39 /* ARRAY_SIZE(mtk_5ghz_channels) + ARRAY_SIZE(mtk_2ghz_channels) */ +#define MAX_2G_BAND_CHN_NUM 14 +#define MAX_5G_BAND_CHN_NUM (MAX_CHN_NUM - MAX_2G_BAND_CHN_NUM) + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Ad-Hoc + *------------------------------------------------------------------------------ + */ +#define CFG_INIT_ADHOC_FREQ (2462000) +#define CFG_INIT_ADHOC_MODE AD_HOC_MODE_MIXED_11BG +#define CFG_INIT_ADHOC_BEACON_INTERVAL (100) +#define CFG_INIT_ADHOC_ATIM_WINDOW (0) + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Maximum Scan SSID number + *------------------------------------------------------------------------------ + */ +#define CFG_SCAN_SSID_MAX_NUM (4) +#define CFG_SCAN_SSID_MATCH_MAX_NUM (16) + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Load Setup Default + *------------------------------------------------------------------------------ + */ + +/*------------------------------------------------------------------------------ + * Flags for enable 802.11A Band setting + *------------------------------------------------------------------------------ + */ + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Interrupt Process + *------------------------------------------------------------------------------ + */ +#define CFG_IST_LOOP_COUNT HIF_IST_LOOP_COUNT + +#define CFG_INT_WRITE_CLEAR 0 + +/* 2 Flags for Driver Debug Options */ +/*------------------------------------------------------------------------------ + * Flags of TX Debug Option. NOTE(Kevin): Confirm with SA before modifying following flags. + *------------------------------------------------------------------------------ + */ +/*!< 1: Debug statistics usage of MGMT Buffer */ +/* 0: Disable */ +#define CFG_DBG_MGT_BUF 1 + +#define CFG_HIF_STATISTICS 0 + +#define CFG_HIF_RX_STARVATION_WARNING 0 + +#define CFG_RX_PKTS_DUMP 0 + +#define CFG_ASSERT_DUMP 1 +/*------------------------------------------------------------------------------ + * Flags of Firmware Download Option. + *------------------------------------------------------------------------------ + */ +#define CFG_ENABLE_FW_DOWNLOAD 1 + +#define CFG_ENABLE_FW_DOWNLOAD_ACK 1 + +/*------------------------------------------------------------------------------ + * Flags of Bluetooth-over-WiFi (BT 3.0 + HS) support + *------------------------------------------------------------------------------ + */ + +#define CFG_ENABLE_BT_OVER_WIFI 0 + +#define CFG_BOW_SEPARATE_DATA_PATH 1 + +#define CFG_BOW_PHYSICAL_LINK_NUM 4 + +#define CFG_BOW_LIMIT_AIS_CHNL 1 + +#define CFG_BOW_SUPPORT_11N 1 + +#define CFG_BOW_RATE_LIMITATION 1 + +/*------------------------------------------------------------------------------ + * Flags of Wi-Fi Direct support + *------------------------------------------------------------------------------ + */ +/*------------------------------------------------------------------------------ + * Support reporting all BSS networks to cfg80211 kernel when scan + * request is from P2P interface + * Originally only P2P networks will be reported when scan request is from p2p0 + *------------------------------------------------------------------------------ + */ +#ifndef CFG_P2P_SCAN_REPORT_ALL_BSS +#define CFG_P2P_SCAN_REPORT_ALL_BSS 0 +#endif + +/*------------------------------------------------------------------------------ + * Flags for GTK rekey offload + *------------------------------------------------------------------------------ + */ + +#ifdef LINUX +#ifdef CONFIG_X86 +#define CFG_ENABLE_WIFI_DIRECT 1 +#define CFG_SUPPORT_802_11W 1 +#define CONFIG_SUPPORT_GTK_REKEY 1 +#else +#define CFG_ENABLE_WIFI_DIRECT 1 +#define CFG_SUPPORT_802_11W 1 /*!< 0(default): Disable 802.11W */ +#define CONFIG_SUPPORT_GTK_REKEY 1 +#endif +#else /* !LINUX */ +#define CFG_ENABLE_WIFI_DIRECT 0 +#define CFG_SUPPORT_802_11W 0 /* Not support at WinXP */ +#endif /* LINUX */ + +#define CFG_SUPPORT_PERSISTENT_GROUP 0 + +#define CFG_TEST_WIFI_DIRECT_GO 0 + +#define CFG_TEST_ANDROID_DIRECT_GO 0 + +#define CFG_UNITEST_P2P 0 + +/* + * Enable cfg80211 option after Android 2.2(Froyo) is suggested, + * cfg80211 on linux 2.6.29 is not mature yet + */ +#define CFG_ENABLE_WIFI_DIRECT_CFG_80211 1 + +#define CFG_SUPPORT_HOTSPOT_OPTIMIZATION 0 +#define CFG_HOTSPOT_OPTIMIZATION_BEACON_INTERVAL 300 +#define CFG_HOTSPOT_OPTIMIZATION_DTIM 1 +#define CFG_AUTO_CHANNEL_SEL_SUPPORT 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 500 + +/*------------------------------------------------------------------------------ + * Migration Option + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_ADHOC 1 +#define CFG_SUPPORT_AAA 1 + +#define CFG_SUPPORT_BCM 0 +#define CFG_SUPPORT_BCM_BWCS 0 +#define CFG_SUPPORT_BCM_BWCS_DEBUG 0 + +#define CFG_SUPPORT_RDD_TEST_MODE 0 + +#define CFG_SUPPORT_PWR_MGT 1 + +#define CFG_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_PNO 1 +#define CFG_SUPPORT_TDLS 1 + +#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 + +#ifndef CFG_SUPPORT_ROAMING +#define CFG_SUPPORT_ROAMING 1 /* Roaming System */ +#endif +#if (CFG_SUPPORT_ROAMING == 1) + +/* Roaming feature: skip roaming when only one ESSID AP +* Need Android background scan +* if no roaming event occurred +* to trigger roaming scan +* after skip roaming in one ESSID AP case +*/ +#define CFG_SUPPORT_ROAMING_SKIP_ONE_AP 1 +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP +#define CFG_MAX_NUM_ROAM_BSS_LIST 64 +#endif +#else +#define CFG_SUPPORT_ROAMING_SKIP_ONE_AP 0 + +#endif /* CFG_SUPPORT_ROAMING */ + +#define CFG_SUPPORT_SWCR 1 + +#define CFG_SUPPORT_ANTI_PIRACY 1 + +#define CFG_SUPPORT_OSC_SETTING 1 + +#define CFG_SUPPORT_P2P_RSSI_QUERY 0 + +#define CFG_SHOW_MACADDR_SOURCE 1 + +#define CFG_SUPPORT_802_11V 0 /* Support 802.11v Wireless Network Management */ +#define CFG_SUPPORT_802_11V_TIMING_MEASUREMENT 0 +#if (CFG_SUPPORT_802_11V_TIMING_MEASUREMENT == 1) && (CFG_SUPPORT_802_11V == 0) +#error "CFG_SUPPORT_802_11V should be 1 once CFG_SUPPORT_802_11V_TIMING_MEASUREMENT equals to 1" +#endif +#if (CFG_SUPPORT_802_11V == 0) +#define WNM_UNIT_TEST 0 +#endif + +#define CFG_DRIVER_COMPOSE_ASSOC_REQ 1 +#define CFG_SUPPORT_802_11AC 1 +#define CFG_STRICT_CHECK_CAPINFO_PRIVACY 0 + +#define CFG_SUPPORT_WFD 1 +#define CFG_SUPPORT_WFD_COMPOSE_IE 1 + +#define CFG_SUPPORT_HOTSPOT_WPS_MANAGER 1 +#define CFG_SUPPORT_NFC_BEAM_PLUS 1 + +/* Refer to CONFIG_MTK_STAGE_SCAN */ +#define CFG_MTK_STAGE_SCAN 1 + +#define CFG_SUPPORT_MULTITHREAD 1 /* Enable driver support multicore */ + +#define CFG_SUPPORT_MTK_SYNERGY 1 + +#define CFG_SUPPORT_PWR_LIMIT_COUNTRY 1 + +#define CFG_FIX_2_TX_PORT 0 + +#ifndef CFG_DISCONN_DEBUG_FEATURE +#define CFG_DISCONN_DEBUG_FEATURE 1 +#define MAX_DISCONNECT_RECORD 5 +#endif + +/*------------------------------------------------------------------------------ + * Flags of bus error tolerance + *------------------------------------------------------------------------------ + */ +#define CFG_FORCE_RESET_UNDER_BUS_ERROR 0 + +/*------------------------------------------------------------------------------ + * Build Date Code Integration + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_BUILD_DATE_CODE 0 + +/*------------------------------------------------------------------------------ + * Flags of SDIO test pattern support + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_SDIO_READ_WRITE_PATTERN 1 + +/*------------------------------------------------------------------------------ + * Flags of AIS passive scan support + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_AIS_PASSIVE_SCAN 0 + +/*------------------------------------------------------------------------------ + * Flags of Workaround + *------------------------------------------------------------------------------ + */ +#define CFG_ENABLE_READ_EXTRA_4_BYTES 1 + +/* Temp workaround for 11ac certification */ +#define CFG_WORKAROUND_OPMODE_CONFLICT_OPINFO 1 + + +/*------------------------------------------------------------------------------ + * Flags of 5G NVRAM SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_NVRAM_5G 1 + +/*------------------------------------------------------------------------------ + * Flags of Packet Lifetime Profiling Mechanism + *------------------------------------------------------------------------------ + */ +#define CFG_ENABLE_PKT_LIFETIME_PROFILE 1 +#define CFG_PRINT_PKT_LIFETIME_PROFILE 0 + +#define CFG_ENABLE_PER_STA_STATISTICS 1 + +/*------------------------------------------------------------------------------ + * Flags for prepare the FW compile flag + *------------------------------------------------------------------------------ + */ +#define COMPILE_FLAG0_GET_STA_LINK_STATUS (1<<0) +#define COMPILE_FLAG0_WFD_ENHANCEMENT_PROTECT (1<<1) + +/*------------------------------------------------------------------------------ + * Flags for prepare the FW feature flag + *------------------------------------------------------------------------------ + */ +#define FEATURE_FLAG0_NIC_CAPABILITY_V2 (1<<0) + +/*------------------------------------------------------------------------------ + * Flags of Batch Scan SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_BATCH_SCAN 1 +#define CFG_BATCH_MAX_MSCAN 2 + +/*------------------------------------------------------------------------------ + * Flags of Sniffer SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_SNIFFER 1 + +#define WLAN_INCLUDE_PROC 1 + + +/*------------------------------------------------------------------------------ + * Flags of Sniffer SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_DUAL_P2PLIKE_INTERFACE 1 + +#define RUNNING_P2P_MODE 0 +#define RUNNING_AP_MODE 1 +#define RUNNING_DUAL_AP_MODE 2 +#define RUNNING_P2P_AP_MODE 3 +#define RUNNING_P2P_MODE_NUM 4 + +/*------------------------------------------------------------------------------ + * Flags of MSP SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_MSP 1 + + +/*------------------------------------------------------------------------------ + * Flags of Drop Packet Replay SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_REPLAY_DETECTION 1 + +/*------------------------------------------------------------------------------ + * Flags of Last Second MCS Tx/Rx Info + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_LAST_SEC_MCS_INFO 1 +#if CFG_SUPPORT_LAST_SEC_MCS_INFO +#define MCS_INFO_SAMPLE_CNT 10 +#endif + + +/*------------------------------------------------------------------------------ + * Flags of driver fw customization + *------------------------------------------------------------------------------ + */ + +#define CFG_SUPPORT_EASY_DEBUG 1 +#define CFG_SUPPORT_FW_DBG_LEVEL_CTRL 1 + + +/*------------------------------------------------------------------------------ + * Flags of driver delay calibration atfer efuse buffer mode CMD + *------------------------------------------------------------------------------ + */ + +#define CFG_EFUSE_BUFFER_MODE_DELAY_CAL 1 + +/*------------------------------------------------------------------------------ + * Flags for E1 IC workaround (SPI clock divided by 2) + * Disabled for MT7668 since external PMIC is NOT used. + * TBD: Let chip info structs decide. + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_PMIC_SPI_CLOCK_SWITCH 0 + +/*------------------------------------------------------------------------------ + * Flags of driver EEPROM pages for QA tool + *------------------------------------------------------------------------------ + */ + +#define CFG_EEPROM_PAGE_ACCESS 1 + +/*------------------------------------------------------------------------------ + * Flags for HOST_OFFLOAD + *------------------------------------------------------------------------------ + */ + +#define CFG_SUPPORT_WIFI_HOST_OFFLOAD 1 + +/*------------------------------------------------------------------------------ + * Flags for DBDC Feature + *------------------------------------------------------------------------------ + */ + +#define CFG_SUPPORT_DBDC 1 + +/*------------------------------------------------------------------------------ + * Flags for Using TC4 Resource in ROM code stage + *------------------------------------------------------------------------------ + */ + +#define CFG_USE_TC4_RESOURCE_FOR_INIT_CMD 0 + +/*------------------------------------------------------------------------------ + * Flags for Efuse Start and End address report from FW + *------------------------------------------------------------------------------ + */ + +#define CFG_FW_Report_Efuse_Address 1 + +/*------------------------------------------------------------------------------ + * FW name max length + *------------------------------------------------------------------------------ + */ +#define CFG_FW_NAME_MAX_LEN (64) + +/*------------------------------------------------------------------------------ + * Chip low power debug function + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_LOW_POWER_DEBUG 1 + +/*------------------------------------------------------------------------------ + * Support WMT WIFI Path Config + *------------------------------------------------------------------------------ + */ +#define CFG_WMT_WIFI_PATH_SUPPORT 0 + +/*------------------------------------------------------------------------------ + * Support CFG_SISO_SW_DEVELOP + *------------------------------------------------------------------------------ + */ +#define CFG_SISO_SW_DEVELOP 1 + +/*------------------------------------------------------------------------------ + * Support antenna selection + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_ANT_SELECT 1 + +/*------------------------------------------------------------------------------ + * Flags for a Goal for MT6632 : Cal Result Backup in Host or NVRam when Android Boot + *------------------------------------------------------------------------------ + */ +#if 0 /*(MTK_WCN_HIF_SDIO) : 20161003 Default Off, later will enable by MTK_WCN_HIF_SDIO */ +#define CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST 1 +#define CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST_DBGLOG 0 +#else +#define CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST 0 +#define CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST_DBGLOG 0 +#endif + +/*------------------------------------------------------------------------------ + * Enable SDIO 1-bit Data Mode. (Usually debug only) + *------------------------------------------------------------------------------ + */ +#define CFG_SDIO_1BIT_DATA_MODE 0 + +/*------------------------------------------------------------------------------ + * Single Sku + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_SINGLE_SKU 1 +#ifndef CFG_SUPPORT_SINGLE_SKU_LOCAL_DB +#define CFG_SUPPORT_SINGLE_SKU_LOCAL_DB 1 +#endif + +/*------------------------------------------------------------------------------ + * Auto enable SDIO asynchronous interrupt mode + *------------------------------------------------------------------------------ + */ +#define CFG_SDIO_ASYNC_IRQ_AUTO_ENABLE 1 + + +/*------------------------------------------------------------------------------ + * Direct Control for RF/PHY/BB/MAC for Manual Configuration via command/api + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_ADVANCE_CONTROL 1 + +/*------------------------------------------------------------------------------ + * Support GO and STA SIGNLE CHANNEL CONCURRENT + *------------------------------------------------------------------------------ + */ +#define GO_STA_SCC 0 + + +/*------------------------------------------------------------------------------ + * Driver pre-allocate total size of memory in one time + *------------------------------------------------------------------------------ + */ +#ifndef CFG_PRE_ALLOCATION_IO_BUFFER +#define CFG_PRE_ALLOCATION_IO_BUFFER 0 +#endif + + +/*------------------------------------------------------------------------------ + * Support scan with channels specified + *------------------------------------------------------------------------------ + */ +#ifndef CFG_SCAN_CHANNEL_SPECIFIED +#define CFG_SCAN_CHANNEL_SPECIFIED 1 +#endif + + +/*------------------------------------------------------------------------------ + * Support EFUSE / EEPROM Auto Detect + *------------------------------------------------------------------------------ + */ +#ifndef CFG_EFUSE_AUTO_MODE_SUPPORT +#define CFG_EFUSE_AUTO_MODE_SUPPORT 1 +#endif + +#ifndef CFG_SUPPORT_CSI +#define CFG_SUPPORT_CSI 1 +#endif + + + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _CONFIG_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/debug.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/debug.h new file mode 100644 index 0000000000000..e557b88542afe --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/debug.h @@ -0,0 +1,348 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + +#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 + +#define DBG_DISABLE_ALL_LOG 0 + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_typedef.h" + +extern UINT_8 aucDebugModule[]; + +/******************************************************************************* +* 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 +#define DBG_ALL_MODULE_IDX 0xFFFFFFFF +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Define debug module index */ +typedef enum _ENUM_DBG_MODULE_T { + DBG_INIT_IDX = 0, /* 0x00 *//* For driver initial */ + DBG_HAL_IDX, /* 0x01 *//* For HAL(HW) Layer */ + DBG_INTR_IDX, /* 0x02 *//* For Interrupt */ + DBG_REQ_IDX, /* 0x03 */ + DBG_TX_IDX, /* 0x04 */ + DBG_RX_IDX, /* 0x05 */ + DBG_RFTEST_IDX, /* 0x06 *//* For RF test mode */ + DBG_EMU_IDX, /* 0x07 *//* Developer specific */ + DBG_SW1_IDX, /* 0x08 *//* Developer specific */ + DBG_SW2_IDX, /* 0x09 *//* Developer specific */ + DBG_SW3_IDX, /* 0x0A *//* Developer specific */ + DBG_SW4_IDX, /* 0x0B *//* Developer specific */ + DBG_HEM_IDX, /* 0x0C *//* HEM */ + DBG_AIS_IDX, /* 0x0D *//* AIS */ + DBG_RLM_IDX, /* 0x0E *//* RLM */ + DBG_MEM_IDX, /* 0x0F *//* RLM */ + DBG_CNM_IDX, /* 0x10 *//* CNM */ + DBG_RSN_IDX, /* 0x11 *//* RSN */ + DBG_BSS_IDX, /* 0x12 *//* BSS */ + DBG_SCN_IDX, /* 0x13 *//* SCN */ + DBG_SAA_IDX, /* 0x14 *//* SAA */ + DBG_AAA_IDX, /* 0x15 *//* AAA */ + DBG_P2P_IDX, /* 0x16 *//* P2P */ + DBG_QM_IDX, /* 0x17 *//* QUE_MGT */ + DBG_SEC_IDX, /* 0x18 *//* SEC */ + DBG_BOW_IDX, /* 0x19 *//* BOW */ + DBG_WAPI_IDX, /* 0x1A *//* WAPI */ + DBG_ROAMING_IDX, /* 0x1B *//* ROAMING */ + DBG_TDLS_IDX, /* 0x1C *//* TDLS *//* CFG_SUPPORT_TDLS */ + DBG_PF_IDX, /* 0x1D *//* PF */ + DBG_OID_IDX, + DBG_NIC_IDX, + DBG_MODULE_NUM /* Notice the XLOG check */ +} ENUM_DBG_MODULE_T; +typedef enum _ENUM_DBG_ASSERT_CTRL_LEVEL_T { + DBG_ASSERT_CTRL_LEVEL_ERROR, + DBG_ASSERT_CTRL_LEVEL_WARN, + DBG_ASSERT_CTRL_LEVEL_LITE +} ENUM_DBG_ASSERT_LEVEL_CTRL_T, *P_ENUM_DBG_ASSERT_LEVEL_CTRL_T; +typedef enum _ENUM_DBG_ASSERT_PATH_T { + DBG_ASSERT_PATH_WIFI, + DBG_ASSERT_PATH_WMT +} ENUM_DBG_ASSERT_PATH_T, *P_ENUM_DBG_ASSERT_PATH_T; +#if MTK_WCN_HIF_SDIO +#define DBG_ASSERT_PATH_DEFAULT DBG_ASSERT_PATH_WMT +#else +#define DBG_ASSERT_PATH_DEFAULT DBG_ASSERT_PATH_WIFI +#endif +#define DBG_ASSERT_CTRL_LEVEL_DEFAULT DBG_ASSERT_CTRL_LEVEL_ERROR +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/* Debug print format string for the OS system time */ +#define OS_SYSTIME_DBG_FORMAT "0x%08x" +/* Debug print argument for the OS system time */ +#define OS_SYSTIME_DBG_ARGUMENT(systime) (systime) +/* Debug print format string for the MAC Address */ +#define MACSTR "%pM" +/* Debug print argument for the MAC Address */ +#define MAC2STR(a) a +/* Debug print format string for the IPv4 Address */ +#define IPV4STR "%pI4" +/* Debug print argument for the IPv4 Address */ +#define IPV4TOSTR(a) a +/* Debug print format string for the MAC Address */ +#define IPV6STR "%pI6" +/* Debug print argument for the MAC Address */ +#define IPV6TOSTR(a) a +/* 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)) +/* Debug print format string for the floating point */ +#define FPSTR "%u.%u" +/* Debug print argument for the floating point */ +#define DIV2INT(_dividend, _divisor) ((_divisor) ? (_dividend) / (_divisor) : 0) +#define DIV2DEC(_dividend, _divisor) ((_divisor) ? (((_dividend) * 100) / (_divisor)) % 100 : 0) +/* 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 kalPrint +#define LIMITED_LOG_FUNC limitedKalPrint +/* If __FUNCTION__ is already defined by compiler, we just use it. */ +#define DEBUGFUNC(_Func) +/* Disabled due to AOSP +*#if defined(__FUNCTION__) +*#define DEBUGFUNC(_Func) +*#else +* #define DEBUGFUNC(_Func) static const char __FUNCTION__[] = _Func; +*#endif +*/ +#if DBG_DISABLE_ALL_LOG +#define DBGLOG(_Module, _Class, _Fmt) +#define DBGLOG_MEM8(_Module, _Class, _StartAddr, _Length) +#define DBGLOG_MEM32(_Module, _Class, _StartAddr, _Length) +#define LIMITED_LOG_FUNC(_Module, _Class, _StartAddr, _Length) +#else +#define DBGLOG(_Module, _Class, _Fmt, ...) \ + do { \ + if ((aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) == 0) \ + break; \ + LOG_FUNC("[%u]%s:(" #_Module " " #_Class ") " _Fmt, KAL_GET_CURRENT_THREAD_ID(), \ + __func__, ##__VA_ARGS__); \ + } while (0) +#define TOOL_PRINTLOG(_Module, _Class, _Fmt, ...) \ + do { \ + if ((aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) == 0) \ + break; \ + LOG_FUNC(_Fmt, ##__VA_ARGS__); \ + } while (0) +#define DBGLOG_MEM8(_Module, _Class, _StartAddr, _Length) \ + { \ + if (aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) { \ + LOG_FUNC("%s:(" #_Module " " #_Class ")\n", __func__); \ + dumpMemory8((PUINT_8)(_StartAddr), (UINT_32)(_Length)); \ + } \ + } +#define DBGLOG_MEM32(_Module, _Class, _StartAddr, _Length) \ + { \ + if (aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) { \ + LOG_FUNC("%s:(" #_Module " " #_Class ")\n", __func__); \ + dumpMemory32((PUINT_32)(_StartAddr), (UINT_32)(_Length)); \ + } \ + } +#define LIMITED_DBGLOG(_Module, _Class, _Fmt, ...) \ + do { \ + if ((aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) == 0) \ + break; \ + LIMITED_LOG_FUNC("[%u]%s:(" #_Module " " #_Class ") " _Fmt,\ + KAL_GET_CURRENT_THREAD_ID(), \ + __func__, ##__VA_ARGS__); \ + } while (0) +#endif +#define DISP_STRING(_str) _str +#undef ASSERT +#undef ASSERT_REPORT +#if (BUILD_QA_DBG || DBG) +#ifdef _lint +#define ASSERT(_exp) \ + { \ + if (!(_exp)) { \ + do {} while (1); \ + } \ + } +#define ASSERT_REPORT(_exp, _fmt) \ + { \ + LOG_FUNC("Assertion failed: %s:%d (%s)\n", __FILE__, __LINE__, #_exp); \ + LOG_FUNC _fmt; \ + if (!(_exp)) { \ + do {} while (1); \ + } \ + } +#elif defined(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) { \ + 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(); \ + } \ + } +#endif /* WINDOWS_CE */ +#else +#define ASSERT(_exp) +#define ASSERT_REPORT(_exp, _fmt) +#endif /* BUILD_QA_DBG */ +/* LOG function for print to buffer */ +/* If buffer pointer is NULL, redirect to normal DBGLOG */ +#define LOGBUF(_pucBuf, _maxLen, _curLen, _Fmt, ...) \ + do { \ + if (_pucBuf) \ + (_curLen) += kalScnprintf((_pucBuf) + (_curLen), (_maxLen) - (_curLen), _Fmt, ##__VA_ARGS__); \ + else \ + DBGLOG(SW4, INFO, _Fmt, ##__VA_ARGS__); \ + } while (0) +/* The following macro is used for debugging packed structures. */ +#ifndef DATA_STRUCT_INSPECTING_ASSERT +#define DATA_STRUCT_INSPECTING_ASSERT(expr) \ +{ \ + switch (0) {case 0: case (expr): default:; } \ +} +#endif +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID dumpMemory8(IN PUINT_8 pucStartAddr, IN UINT_32 u4Length); +VOID dumpMemory32(IN PUINT_32 pu4StartAddr, IN UINT_32 u4Length); +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _DEBUG_H */ + + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/link.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/link.h new file mode 100644 index 0000000000000..0726d9fc346ad --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/link.h @@ -0,0 +1,415 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + +#ifndef _LINK_H +#define _LINK_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_typedef.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* May cause page fault & unalignment issue (data abort) */ +#define INVALID_LINK_POISON1 ((VOID *) 0x00100101) + +/* Used to verify that nonbody uses non-initialized link entries. */ +#define INVALID_LINK_POISON2 ((VOID *) 0x00100201) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Simple Doubly Linked List Structures - Entry Part */ +typedef struct _LINK_ENTRY_T { + struct _LINK_ENTRY_T *prNext, *prPrev; +} LINK_ENTRY_T, *P_LINK_ENTRY_T; + +/* Simple Doubly Linked List Structures - List Part */ +typedef struct _LINK_T { + P_LINK_ENTRY_T prNext; + P_LINK_ENTRY_T prPrev; + UINT_32 u4NumElem; +} LINK_T, *P_LINK_T; + +struct LINK_MGMT { + LINK_T rUsingLink; + LINK_T rFreeLink; +}; + +/******************************************************************************* +* P U B 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_MGMT_INIT(prLinkMgmt) \ + do { \ + LINK_INITIALIZE( \ + &((struct LINK_MGMT *)prLinkMgmt)->rUsingLink); \ + LINK_INITIALIZE( \ + &((struct LINK_MGMT *)prLinkMgmt)->rFreeLink); \ + } while (0) + +#define LINK_MGMT_GET_ENTRY(prLinkMgmt, prEntry, EntryType, memType) \ + do { \ + LINK_REMOVE_HEAD(&((struct LINK_MGMT *)prLinkMgmt)->rFreeLink, \ + prEntry, EntryType*); \ + if (!prEntry) \ + prEntry = kalMemAlloc(sizeof(EntryType), memType); \ + } while (0) + +#define LINK_MGMT_UNINIT(prLinkMgmt, EntryType, memType) \ + do { \ + EntryType *prEntry = NULL; \ + P_LINK_T prFreeList = \ + &((struct LINK_MGMT *)prLinkMgmt)->rFreeLink; \ + P_LINK_T prUsingList = \ + &((struct LINK_MGMT *)prLinkMgmt)->rUsingLink; \ + LINK_REMOVE_HEAD(prFreeList, prEntry, EntryType *); \ + while (prEntry) { \ + kalMemFree(prEntry, memType, sizeof(EntryType)); \ + LINK_REMOVE_HEAD(prFreeList, prEntry, EntryType *); \ + } \ + LINK_REMOVE_HEAD(prUsingList, prEntry, EntryType *); \ + while (prEntry) { \ + kalMemFree(prEntry, memType, sizeof(EntryType)); \ + LINK_REMOVE_HEAD(prUsingList, prEntry, EntryType *); \ + } \ + } while (0) + + +#define LINK_ENTRY_INITIALIZE(prEntry) \ + do { \ + ((P_LINK_ENTRY_T)(prEntry))->prNext = (P_LINK_ENTRY_T)NULL; \ + ((P_LINK_ENTRY_T)(prEntry))->prPrev = (P_LINK_ENTRY_T)NULL; \ + } while (0) + +#define LINK_ENTRY_INVALID(prEntry) \ + do { \ + ((P_LINK_ENTRY_T)(prEntry))->prNext = (P_LINK_ENTRY_T)INVALID_LINK_POISON1; \ + ((P_LINK_ENTRY_T)(prEntry))->prPrev = (P_LINK_ENTRY_T)INVALID_LINK_POISON2; \ + } while (0) + +#define LINK_IS_EMPTY(prLink) (((P_LINK_T)(prLink))->prNext == (P_LINK_ENTRY_T)(prLink)) + +/* NOTE: We should do memory zero before any LINK been initiated, so we can check + * if it is valid before parsing the LINK. + */ +#define LINK_IS_INVALID(prLink) (((P_LINK_T)(prLink))->prNext == (P_LINK_ENTRY_T)NULL) + +#define LINK_IS_VALID(prLink) (((P_LINK_T)(prLink))->prNext != (P_LINK_ENTRY_T)NULL) + +#define LINK_ENTRY(ptr, type, member) ENTRY_OF(ptr, type, member) + +/* Insert an entry into a link list's head */ +#define LINK_INSERT_HEAD(prLink, prEntry) \ + { \ + linkAdd(prEntry, prLink); \ + ((prLink)->u4NumElem)++; \ + } + +/* Append an entry into a link list's tail */ +#define LINK_INSERT_TAIL(prLink, prEntry) \ + { \ + linkAddTail(prEntry, prLink); \ + ((prLink)->u4NumElem)++; \ + } + +/* Peek head entry, but keep still in link list */ +#define LINK_PEEK_HEAD(prLink, _type, _member) \ + ( \ + LINK_IS_EMPTY(prLink) ? \ + NULL : LINK_ENTRY((prLink)->prNext, _type, _member) \ + ) + +/* Peek tail entry, but keep still in link list */ +#define LINK_PEEK_TAIL(prLink, _type, _member) \ + ( \ + LINK_IS_EMPTY(prLink) ? \ + NULL : LINK_ENTRY((prLink)->prPrev, _type, _member) \ + ) + +/* Get first entry from a link list */ +/* NOTE: We assume the link entry located at the beginning of "prEntry Type", + * so that we can cast the link entry to other data type without doubts. + * And this macro also decrease the total entry count at the same time. + */ +#define LINK_REMOVE_HEAD(prLink, prEntry, _P_TYPE) \ + { \ + ASSERT(prLink); \ + if (LINK_IS_EMPTY(prLink)) { \ + prEntry = (_P_TYPE)NULL; \ + } \ + else { \ + prEntry = (_P_TYPE)(((P_LINK_T)(prLink))->prNext); \ + linkDel((P_LINK_ENTRY_T)prEntry); \ + ((prLink)->u4NumElem)--; \ + } \ + } + +/* Assume the link entry located at the beginning of prEntry Type. + * And also decrease the total entry count. + */ +#define LINK_REMOVE_KNOWN_ENTRY(prLink, prEntry) \ + { \ + ASSERT(prLink); \ + ASSERT(prEntry); \ + linkDel((P_LINK_ENTRY_T)prEntry); \ + ((prLink)->u4NumElem)--; \ + } + +/* Iterate over a link list */ +#define LINK_FOR_EACH(prEntry, prLink) \ + for (prEntry = (prLink)->prNext; \ + prEntry != (P_LINK_ENTRY_T)(prLink); \ + prEntry = (P_LINK_ENTRY_T)prEntry->prNext) + +/* Iterate over a link list backwards */ +#define LINK_FOR_EACH_PREV(prEntry, prLink) \ + for (prEntry = (prLink)->prPrev; \ + prEntry != (P_LINK_ENTRY_T)(prLink); \ + prEntry = (P_LINK_ENTRY_T)prEntry->prPrev) + +/* Iterate over a link list safe against removal of link entry */ +#define LINK_FOR_EACH_SAFE(prEntry, prNextEntry, prLink) \ + for (prEntry = (prLink)->prNext, prNextEntry = prEntry->prNext; \ + prEntry != (P_LINK_ENTRY_T)(prLink); \ + prEntry = prNextEntry, prNextEntry = prEntry->prNext) + +/* Iterate over a link list of given type */ +#define LINK_FOR_EACH_ENTRY(prObj, prLink, rMember, _TYPE) \ + for (prObj = LINK_ENTRY((prLink)->prNext, _TYPE, rMember); \ + &prObj->rMember != (P_LINK_ENTRY_T)(prLink); \ + prObj = LINK_ENTRY(prObj->rMember.prNext, _TYPE, rMember)) + +/* Iterate backwards over a link list of given type */ +#define LINK_FOR_EACH_ENTRY_PREV(prObj, prLink, rMember, _TYPE) \ + for (prObj = LINK_ENTRY((prLink)->prPrev, _TYPE, rMember); \ + &prObj->rMember != (P_LINK_ENTRY_T)(prLink); \ + prObj = LINK_ENTRY(prObj->rMember.prPrev, _TYPE, rMember)) + +/* Iterate over a link list of given type safe against removal of link entry */ +#define LINK_FOR_EACH_ENTRY_SAFE(prObj, prNextObj, prLink, rMember, _TYPE) \ + for (prObj = LINK_ENTRY((prLink)->prNext, _TYPE, rMember), \ + prNextObj = LINK_ENTRY(prObj->rMember.prNext, _TYPE, rMember); \ + &prObj->rMember != (P_LINK_ENTRY_T)(prLink); \ + prObj = prNextObj, \ + prNextObj = LINK_ENTRY(prNextObj->rMember.prNext, _TYPE, rMember)) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is only for internal link list manipulation. +* +* \param[in] prNew Pointer of new link head +* \param[in] prPrev Pointer of previous link head +* \param[in] prNext Pointer of next link head +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __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; +} /* end of __linkAdd() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will add a new entry after the specified link head. +* +* \param[in] prNew New entry to be added +* \param[in] prHead Specified link head to add it after +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ VOID linkAdd(IN P_LINK_ENTRY_T prNew, IN P_LINK_T prLink) +{ + __linkAdd(prNew, (P_LINK_ENTRY_T) prLink, prLink->prNext); +} /* end of linkAdd() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will add a new entry before the specified link head. +* +* \param[in] prNew New entry to be added +* \param[in] prHead Specified link head to add it before +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ VOID linkAddTail(IN P_LINK_ENTRY_T prNew, IN P_LINK_T prLink) +{ + __linkAdd(prNew, prLink->prPrev, (P_LINK_ENTRY_T) prLink); +} /* end of linkAddTail() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is only for internal link list manipulation. +* +* \param[in] prPrev Pointer of previous link head +* \param[in] prNext Pointer of next link head +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ VOID __linkDel(IN P_LINK_ENTRY_T prPrev, IN P_LINK_ENTRY_T prNext) +{ + prNext->prPrev = prPrev; + prPrev->prNext = prNext; +} /* end of __linkDel() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will delete a specified entry from link list. +* NOTE: the entry is in an initial state. +* +* \param prEntry Specified link head(entry) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ VOID linkDel(IN P_LINK_ENTRY_T prEntry) +{ + __linkDel(prEntry->prPrev, prEntry->prNext); + + LINK_ENTRY_INITIALIZE(prEntry); +} /* end of linkDel() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will delete a specified entry from link list and then add it +* after the specified link head. +* +* \param[in] prEntry Specified link head(entry) +* \param[in] prOtherHead Another link head to add it after +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ VOID linkMove(IN P_LINK_ENTRY_T prEntry, IN P_LINK_T prLink) +{ + __linkDel(prEntry->prPrev, prEntry->prNext); + linkAdd(prEntry, prLink); +} /* end of linkMove() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will delete a specified entry from link list and then add it +* before the specified link head. +* +* \param[in] prEntry Specified link head(entry) +* \param[in] prOtherHead Another link head to add it before +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ VOID linkMoveTail(IN P_LINK_ENTRY_T prEntry, IN P_LINK_T prLink) +{ + __linkDel(prEntry->prPrev, prEntry->prNext); + linkAddTail(prEntry, prLink); +} /* end of linkMoveTail() */ + +#endif /* _LINK_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/aa_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/aa_fsm.h new file mode 100644 index 0000000000000..5e106850b80d6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/aa_fsm.h @@ -0,0 +1,225 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + +#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. */ +#if CFG_SUPPORT_CFG80211_AUTH +/* Wait for a response to a transmitted SAE authentication MMPDU. */ +/* Default value on 802.11-REVmd-D0.5 */ +#define DOT11_RSNA_SAE_RETRANS_PERIOD_TU 2000 +#endif +/* 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 */ + +#define TX_AUTHENTICATION_RESPONSE_TIMEOUT_TU 512 /* TU. */ + +#define TX_ASSOCIATE_TIMEOUT_TU 512 /* TU. */ + +/******************************************************************************* +* 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; + +#if CFG_SUPPORT_CFG80211_AUTH +enum ENUM_AA_SENT_T { + AA_SENT_NONE = 0, + AA_SENT_AUTH1, /* = auth transaction SN */ + AA_SENT_AUTH2, + AA_SENT_AUTH3, + AA_SENT_AUTH4, + AA_SENT_ASSOC1, /* req */ + AA_SENT_ASSOC2, /* resp */ + AA_SENT_RESOURCE, /* A state for debug the case of out of msg buffer */ + AA_SENT_NUM +}; +#endif + +typedef enum _ENUM_AA_FRM_TYPE_T { + FRM_DISASSOC = 0, + FRM_DEAUTH +} ENUM_AA_FRM_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 +******************************************************************************** +*/ + +/******************************************************************************* +* 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 ULONG plParamPtr); + +VOID saaFsmRunEventRxRespTimeOut(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); + +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); + +VOID saaChkDeauthfrmParamHandler(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN P_STA_RECORD_T prStaRec); + +VOID +saaChkDisassocfrmParamHandler(IN P_ADAPTER_T prAdapter, + IN P_WLAN_DISASSOC_FRAME_T prDisassocFrame, IN P_STA_RECORD_T prStaRec, + IN P_SW_RFB_T prSwRfb); + +VOID +saaSendDisconnectMsgHandler(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_BSS_INFO_T prAisBssInfo, + IN ENUM_AA_FRM_TYPE_T eFrmType); + +#if CFG_SUPPORT_CFG80211_AUTH +VOID saaSendAuthAssoc(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); +#endif + +/*----------------------------------------------------------------------------*/ +/* Routines in aaa_fsm.c */ +/*----------------------------------------------------------------------------*/ +VOID aaaFsmRunEventRxAuth(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +WLAN_STATUS aaaFsmRunEventRxAssoc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +WLAN_STATUS +aaaFsmRunEventTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _AA_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/ais_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/ais_fsm.h new file mode 100644 index 0000000000000..790a28bf58808 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/ais_fsm.h @@ -0,0 +1,535 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/ais_fsm.h#2 +*/ + +/*! \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. +*/ + + +#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 +******************************************************************************** +*/ +#if CFG_DISCONN_DEBUG_FEATURE +extern struct AIS_DISCONN_INFO_T g_rDisconnInfoTemp; +extern UINT_8 g_DisconnInfoIdx; +extern struct AIS_DISCONN_INFO_T *g_prDisconnInfo; +#endif + +/******************************************************************************* +* 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 5 /* 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 +#if CFG_SUPPORT_CFG80211_AUTH +/* expand 4000 to 6000 to improve SAE connection success probability */ +#define AIS_JOIN_CH_REQUEST_INTERVAL 6000 +#else +#define AIS_JOIN_CH_REQUEST_INTERVAL 4000 +#endif +#define AIS_SCN_DONE_TIMEOUT_SEC 15 /* 15 for 2.4G + 5G */ /* 5 */ +#define AIS_BLACKLIST_TIMEOUT 15 /* seconds */ + +#ifdef CFG_SUPPORT_ADJUST_JOIN_CH_REQ_INTERVAL +#define AIS_JOIN_CH_REQUEST_MAX_INTERVAL 4000 +#endif +/******************************************************************************* +* 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_JOIN_FAILURE, + AIS_STATE_IBSS_ALONE, + AIS_STATE_IBSS_MERGE, + AIS_STATE_NORMAL_TR, + AIS_STATE_DISCONNECTING, + AIS_STATE_REQ_REMAIN_ON_CHANNEL, + AIS_STATE_REMAIN_ON_CHANNEL, + AIS_STATE_NUM +} ENUM_AIS_STATE_T; + +/* these name of reasons code are the same as name in FW */ +enum BEACON_TIME_OUT_REASON_CODE_T { + BEACON_TIMEOUT_DUE_2_HW_BEACON_LOST_NONADHOC, + BEACON_TIMEOUT_DUE_2_HW_BEACON_LOST_ADHOC, + BEACON_TIMEOUT_DUE_2_HW_TSF_DRIFT, + BEACON_TIMEOUT_DUE_2_NULL_FRAME_THRESHOLD, + BEACON_TIMEOUT_DUE_2_AGING_THRESHOLD, + BEACON_TIMEOUT_DUE_2_BSSID_BEACON_PEIROD_NOT_ILLIGAL, + BEACON_TIMEOUT_DUE_2_CONNECTION_FAIL, + BEACON_TIMEOUT_DUE_2_ALLOCAT_NULL_PKT_FAIL_THRESHOLD, + BEACON_TIMEOUT_DUE_2_NO_TX_DONE_EVENT, + BEACON_TIMEOUT_DUE_2_UNSPECIF_REASON, + BEACON_TIMEOUT_DUE_2_SET_CHIP, + BEACON_TIMEOUT_DUE_2_RESERVED = 0xF, +}; + +#if CFG_SUPPORT_CSI +enum CSI_DATA_TLV_TAG { + CSI_DATA_VER, + CSI_DATA_TYPE, + CSI_DATA_TS, + CSI_DATA_RSSI, + CSI_DATA_SNR, + CSI_DATA_DBW, + CSI_DATA_CH_IDX, + CSI_DATA_TA, + CSI_DATA_I, + CSI_DATA_Q, + CSI_DATA_EXTRA_INFO, + CSI_DATA_RSVD1, + CSI_DATA_RSVD2, + CSI_DATA_RSVD3, + CSI_DATA_RSVD4, + CSI_DATA_TX_IDX, + CSI_DATA_RX_IDX, + CSI_DATA_FRAME_MODE, + CSI_DATA_TLV_TAG_NUM, +}; +#endif + +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 ucBssIndex; + BOOLEAN fgIsMergeIn; /* TRUE: Merge In, FALSE: Merge Out */ + P_STA_RECORD_T prStaRec; +} MSG_AIS_IBSS_PEER_FOUND_T, *P_MSG_AIS_IBSS_PEER_FOUND_T; + +typedef enum _ENUM_AIS_REQUEST_TYPE_T { + AIS_REQUEST_SCAN, + AIS_REQUEST_RECONNECT, + AIS_REQUEST_ROAMING_SEARCH, + AIS_REQUEST_ROAMING_CONNECT, + AIS_REQUEST_REMAIN_ON_CHANNEL, + AIS_REQUEST_NUM +} ENUM_AIS_REQUEST_TYPE_T; + +typedef struct _AIS_REQ_HDR_T { + LINK_ENTRY_T rLinkEntry; + ENUM_AIS_REQUEST_TYPE_T eReqType; +} AIS_REQ_HDR_T, *P_AIS_REQ_HDR_T; + +typedef struct _AIS_REQ_CHNL_INFO { + ENUM_BAND_T eBand; + ENUM_CHNL_EXT_T eSco; + UINT_8 ucChannelNum; + UINT_32 u4DurationMs; + UINT_64 u8Cookie; +} AIS_REQ_CHNL_INFO, *P_AIS_REQ_CHNL_INFO; + +typedef struct _AIS_MGMT_TX_REQ_INFO_T { + BOOLEAN fgIsMgmtTxRequested; + P_MSDU_INFO_T prMgmtTxMsdu; + UINT_64 u8Cookie; +} AIS_MGMT_TX_REQ_INFO_T, *P_AIS_MGMT_TX_REQ_INFO_T; + +struct AIS_BLACKLIST_ITEM { + LINK_ENTRY_T rLinkEntry; + + UINT_8 aucBSSID[MAC_ADDR_LEN]; + UINT_16 u2DeauthReason; + UINT_16 u2AuthStatus; + UINT_8 ucCount; + UINT_8 ucSSIDLen; + UINT_8 aucSSID[32]; + OS_SYSTIME rAddTime; + UINT_64 u8DisapperTime; + UINT_8 blackListSource; +}; + +enum _BLACK_LIST_SOURCE { + AIS_BLACK_LIST_FROM_DRIVER = 1, + AIS_BLACK_LIST_FROM_FWK = 2, + + AIS_BLACK_LIST_MAX = 1 << 7 +}; + +typedef struct _AIS_FSM_INFO_T { + ENUM_AIS_STATE_T ePreviousState; + ENUM_AIS_STATE_T eCurrentState; + + BOOLEAN fgTryScan; + + BOOLEAN fgIsInfraChannelFinished; + BOOLEAN fgIsChannelRequested; + BOOLEAN fgIsChannelGranted; + +#if CFG_SUPPORT_ROAMING + BOOLEAN fgIsRoamingScanPending; +#endif /* CFG_SUPPORT_ROAMING */ + + UINT_8 ucAvailableAuthTypes; /* Used for AUTH_MODE_AUTO_SWITCH */ + + P_BSS_DESC_T prTargetBssDesc; /* For destination */ + + P_STA_RECORD_T prTargetStaRec; /* For JOIN Abort */ + + UINT_32 u4SleepInterval; + + TIMER_T rBGScanTimer; + + TIMER_T rIbssAloneTimer; + + TIMER_T rIndicationOfDisconnectTimer; + + TIMER_T rJoinTimeoutTimer; + + TIMER_T rChannelTimeoutTimer; + + TIMER_T rScanDoneTimer; + + TIMER_T rDeauthDoneTimer; + + UINT_8 ucSeqNumOfReqMsg; + UINT_8 ucSeqNumOfChReq; + UINT_8 ucSeqNumOfScanReq; + + UINT_32 u4ChGrantedInterval; + + UINT_8 ucConnTrialCount; + + UINT_8 ucScanSSIDNum; + PARAM_SSID_T arScanSSID[SCN_SSID_MAX_NUM]; + + UINT_32 u4ScanIELength; + UINT_8 aucScanIEBuf[MAX_IE_LENGTH]; + +#if CFG_SCAN_CHANNEL_SPECIFIED + UINT_8 ucScanChannelListNum; + RF_CHANNEL_INFO_T arScanChnlInfoList[MAXIMUM_OPERATION_CHANNEL_LIST]; +#endif + + /* Pending Request List */ + LINK_T rPendingReqList; + + /* Join Request Timestamp */ + OS_SYSTIME rJoinReqTime; + + /* for cfg80211 REMAIN_ON_CHANNEL support */ + AIS_REQ_CHNL_INFO rChReqInfo; + + /* Mgmt tx related. */ + AIS_MGMT_TX_REQ_INFO_T rMgmtTxInfo; + + /* Packet filter for AIS module. */ + UINT_32 u4AisPacketFilter; + + /* for roaming target */ + PARAM_SSID_T rRoamingSSID; +} AIS_FSM_INFO_T, *P_AIS_FSM_INFO_T; + +#if CFG_DISCONN_DEBUG_FEATURE +struct AIS_DISCONN_INFO_T { + struct timeval tv; + UINT_8 ucTrigger; + UINT_8 ucDisConnReason; + UINT_8 ucBcnTimeoutReason; + UINT_8 ucDisassocReason; + UINT_16 u2DisassocSeqNum; + STA_RECORD_T rStaRec; + PARAM_RSSI rBcnRssi; + struct CMD_NOISE_HISTOGRAM_REPORT rNoise; + PARAM_HW_WLAN_INFO_T rHwInfo; + PARAM_GET_STA_STA_STATISTICS rStaStatistics; +}; +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define aisChangeMediaState(_prAdapter, _eNewMediaState) \ + (_prAdapter->prAisBssInfo->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); + +enum _ENUM_AIS_STATE_T aisFsmJoinCompleteAction(IN struct _ADAPTER_T *prAdapter, IN struct _MSG_HDR_T *prMsgHdr); + +VOID aisFsmRunEventFoundIBSSPeer(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID aisFsmRunEventRemainOnChannel(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID aisFsmRunEventCancelRemainOnChannel(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +/*----------------------------------------------------------------------------*/ +/* Handling for Ad-Hoc Network */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmCreateIBSS(IN P_ADAPTER_T prAdapter); + +VOID aisFsmMergeIBSS(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +/*----------------------------------------------------------------------------*/ +/* Handling of Incoming Mailbox Message from CNM */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventChGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +/*----------------------------------------------------------------------------*/ +/* Generating Outgoing Mailbox Message to CNM */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmReleaseCh(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* Event Indication */ +/*----------------------------------------------------------------------------*/ +VOID +aisIndicationOfMediaStateToHost(IN P_ADAPTER_T prAdapter, + ENUM_PARAM_MEDIA_STATE_T eConnectionState, BOOLEAN fgDelayIndication); + +VOID aisPostponedEventOfDisconnTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr); + +VOID aisUpdateBssInfoForJOIN(IN P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, P_SW_RFB_T prAssocRspSwRfb); + +VOID aisUpdateBssInfoForCreateIBSS(IN P_ADAPTER_T prAdapter); + +VOID aisUpdateBssInfoForMergeIBSS(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +BOOLEAN aisValidateProbeReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_32 pu4ControlFlags); + +WLAN_STATUS +aisFsmRunEventMgmtFrameTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +/*----------------------------------------------------------------------------*/ +/* Disconnection Handling */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmDisconnect(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgDelayIndication); +#if CFG_DISCONN_DEBUG_FEATURE +VOID aisCollectDisconnInfo(IN P_ADAPTER_T prAdapter); +#endif +/*----------------------------------------------------------------------------*/ +/* Event Handling */ +/*----------------------------------------------------------------------------*/ +VOID aisBssBeaconTimeout(IN P_ADAPTER_T prAdapter); + +VOID aisBssLinkDown(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS +aisDeauthXmitComplete(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +#if CFG_SUPPORT_ROAMING +VOID aisFsmRunEventRoamingDiscovery(IN P_ADAPTER_T prAdapter, UINT_32 u4ReqScan); + +ENUM_AIS_STATE_T aisFsmRoamingScanResultsUpdate(IN P_ADAPTER_T prAdapter); + +VOID aisFsmRoamingDisconnectPrevAP(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prTargetStaRec); + +VOID aisUpdateBssInfoForRoamingAP(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prAssocRspSwRfb); +#endif /*CFG_SUPPORT_ROAMING */ + +/*----------------------------------------------------------------------------*/ +/* Timeout Handling */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventBGSleepTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr); + +VOID aisFsmRunEventIbssAloneTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr); + +VOID aisFsmRunEventJoinTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr); + +VOID aisFsmRunEventChannelTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr); + +VOID aisFsmRunEventDeauthTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr); + +#if CFG_SUPPORT_LAST_SEC_MCS_INFO +VOID aisRxMcsCollectionTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr); +#endif + +/*----------------------------------------------------------------------------*/ +/* OID/IOCTL Handling */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmScanRequest(IN P_ADAPTER_T prAdapter, IN P_PARAM_SSID_T prSsid, IN PUINT_8 pucIe, IN UINT_32 u4IeLength); + +VOID +aisFsmScanRequestAdv(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucSsidNum, IN P_PARAM_SSID_T prSsid, + IN UINT_8 ucChannelListNum, IN P_RF_CHANNEL_INFO_T prChnlInfoList, + IN PUINT_8 pucIe, IN UINT_32 u4IeLength); + +/*----------------------------------------------------------------------------*/ +/* Internal State Checking */ +/*----------------------------------------------------------------------------*/ +BOOLEAN aisFsmIsRequestPending(IN P_ADAPTER_T prAdapter, IN ENUM_AIS_REQUEST_TYPE_T eReqType, IN BOOLEAN bRemove); + +P_AIS_REQ_HDR_T aisFsmGetNextRequest(IN P_ADAPTER_T prAdapter); + +BOOLEAN aisFsmInsertRequest(IN P_ADAPTER_T prAdapter, IN ENUM_AIS_REQUEST_TYPE_T eReqType); + +VOID aisFsmFlushRequest(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS +aisFuncTxMgmtFrame(IN P_ADAPTER_T prAdapter, + IN P_AIS_MGMT_TX_REQ_INFO_T prMgmtTxReqInfo, IN P_MSDU_INFO_T prMgmtTxMsdu, IN UINT_64 u8Cookie); + +VOID aisFsmRunEventMgmtFrameTx(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID aisFuncValidateRxActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +enum _ENUM_AIS_STATE_T aisFsmStateSearchAction(IN struct _ADAPTER_T *prAdapter, UINT_8 ucPhase); +#if defined(CFG_TEST_MGMT_FSM) && (CFG_TEST_MGMT_FSM != 0) +VOID aisTest(VOID); +#endif /* CFG_TEST_MGMT_FSM */ + +VOID aisRemoveBlacklistBySource(P_ADAPTER_T prAdapter, enum +_BLACK_LIST_SOURCE source); +struct AIS_BLACKLIST_ITEM *aisAddBlacklist(P_ADAPTER_T prAdapter, +P_BSS_DESC_T prBssDesc, + enum _BLACK_LIST_SOURCE source); +struct AIS_BLACKLIST_ITEM *aisAddBlacklistByBssid(P_ADAPTER_T prAdapter, +UINT_8 aucBSSID[], + enum _BLACK_LIST_SOURCE source); +VOID aisRemoveBlackList(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc, enum +_BLACK_LIST_SOURCE source); +VOID aisRemoveTimeoutBlacklist(P_ADAPTER_T prAdapter); +struct AIS_BLACKLIST_ITEM *aisQueryBlackList(P_ADAPTER_T prAdapter, +P_BSS_DESC_T prBssDesc); +struct AIS_BLACKLIST_ITEM *aisQueryBlackListByBssid(P_ADAPTER_T prAdapter, +UINT_8 aucBSSID[]); +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _AIS_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/assoc.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/assoc.h new file mode 100644 index 0000000000000..6587ec0d65659 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/assoc.h @@ -0,0 +1,136 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +#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); + +UINT_16 assocBuildCapabilityInfo(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +u32 assoc_get_nonwfa_vend_ie_len(IN P_ADAPTER_T prAdapter); +void assoc_build_nonwfa_vend_ie(P_ADAPTER_T prAdapter, + P_MSDU_INFO_T prMsduInfo); +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _ASSOC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/auth.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/auth.h new file mode 100644 index 0000000000000..164ca1cfa2c44 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/auth.h @@ -0,0 +1,151 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +#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 UINT_8 uBssIndex, + 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_BSS_INFO_T prBssInfo, + IN P_STA_RECORD_T prStaRec, + IN P_SW_RFB_T prClassErrSwRfb, IN UINT_16 u2ReasonCode, IN PFN_TX_DONE_HANDLER pfTxDoneHandler); + +WLAN_STATUS authProcessRxDeauthFrame(IN P_SW_RFB_T prSwRfb, IN UINT_8 aucBSSID[], OUT PUINT_16 pu2ReasonCode); + +WLAN_STATUS +authProcessRxAuth1Frame(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN UINT_8 aucExpectedBSSID[], + IN UINT_16 u2ExpectedAuthAlgNum, + IN UINT_16 u2ExpectedTransSeqNum, OUT PUINT_16 pu2ReturnStatusCode); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _AUTH_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/bow_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/bow_fsm.h new file mode 100644 index 0000000000000..08d45181acbe5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/bow_fsm.h @@ -0,0 +1,189 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +#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 { + /* Channel Privilege */ + BOOLEAN fgIsChannelRequested; + BOOLEAN fgIsChannelGranted; + UINT_32 u4ChGrantedInterval; + + UINT_8 ucPrimaryChannel; + ENUM_BAND_T eBand; + UINT_16 u2BeaconInterval; + + P_STA_RECORD_T prTargetStaRec; + P_BSS_DESC_T prTargetBssDesc; /* For destination */ + + UINT_8 aucPeerAddress[6]; + UINT_8 ucBssIndex; /* Assume there is only 1 BSS for BOW */ + UINT_8 ucRole; /* Initiator or responder */ + UINT_8 ucAvailableAuthTypes; /* Used for AUTH_MODE_AUTO_SWITCH */ + + BOOLEAN fgSupportQoS; + + /* Sequence number of requested message. */ + UINT_8 ucSeqNumOfChReq; + UINT_8 ucSeqNumOfReqMsg; + UINT_8 ucSeqNumOfScnMsg; + UINT_8 ucSeqNumOfScanReq; + UINT_8 ucSeqNumOfCancelMsg; + + /* Timer */ + TIMER_T rStartingBeaconTimer; /* For device discovery time of each discovery request from user. */ + TIMER_T rChGrantedTimer; + + /* can be deleted? */ + TIMER_T rIndicationOfDisconnectTimer; + +} 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(_prBssInfo, _eNewMediaState) \ + (_prBssInfo->eConnectionState = (_eNewMediaState)) + /* (_prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX].eConnectionState = (_eNewMediaState)); */ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/bss.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/bss.h new file mode 100644 index 0000000000000..9e9b3f3cc3b93 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/bss.h @@ -0,0 +1,237 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +#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 +******************************************************************************** +*/ +#include "wlan_def.h" +extern const PUINT_8 apucNetworkType[NETWORK_TYPE_NUM]; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* Fixed value=4 for MT6630. + * It is the biggest index of this pointer array prAdapter->aprBssInfo[]. + */ +#define MAX_BSS_INDEX HW_BSSID_NUM +#define P2P_DEV_BSS_INDEX MAX_BSS_INDEX + +/* Define how many concurrent operation networks. */ +#define BSS_INFO_NUM KAL_BSS_NUM +#define BSS_P2P_NUM KAL_P2P_NUM + +#if (KAL_BSS_NUM > HW_BSSID_NUM) || (KAL_P2P_NUM > KAL_BSS_NUM) +#error Exceed HW capability (KAL_BSS_NUM or KAL_P2P_NUM)!! +#endif + +/* 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 IS_BSS_INDEX_VALID(_ucBssIndex) ((_ucBssIndex) <= P2P_DEV_BSS_INDEX) + +#define GET_BSS_INFO_BY_INDEX(_prAdapter, _ucBssIndex) \ + ((_prAdapter)->aprBssInfo[(_ucBssIndex)]) + +#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 UINT_8 uBssIndex, 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); + +VOID bssDumpBssInfo(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex); + +VOID bssDetermineApBssInfoPhyTypeSet(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsPureAp, OUT P_BSS_INFO_T prBssInfo); + +/*----------------------------------------------------------------------------*/ +/* 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 UINT_8 uBssIndex, IN PUINT_8 pucDestAddr, IN UINT_32 u4ControlFlags); + +WLAN_STATUS bssProcessProbeRequest(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID bssInitializeClientList(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo); + +VOID bssAddClient(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_STA_RECORD_T prStaRec); + +BOOLEAN bssRemoveClient(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_STA_RECORD_T prStaRec); + +P_STA_RECORD_T bssRemoveClientByMac(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN PUINT_8 pucMac); + +P_STA_RECORD_T bssGetClientByMac(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN PUINT_8 pucMac); + +P_STA_RECORD_T bssRemoveHeadClient(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo); + +UINT_32 bssGetClientCount(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo); + +VOID bssDumpClientList(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo); + +VOID bssCheckClientList(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo); + +/*----------------------------------------------------------------------------*/ +/* 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 UINT_8 uBssIndex); + +/*----------------------------------------------------------------------------*/ +/* 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 UINT_8 uBssIndex); + +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/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/cnm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/cnm.h new file mode 100644 index 0000000000000..3d32353918db6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/cnm.h @@ -0,0 +1,313 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/cnm.h#1 +*/ + +/*! \file "cnm.h" +* \brief +*/ + + +#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 +******************************************************************************** +*/ +#if CFG_SUPPORT_DBDC +#define DBDC_5G_WMM_INDEX 0 +#define DBDC_2G_WMM_INDEX 1 +#endif +#define MAX_HW_WMM_INDEX (HW_WMM_NUM - 1) +#define DEFAULT_HW_WMM_INDEX (MAX_HW_WMM_INDEX - 1) +/******************************************************************************* +* 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_OFFCHNL_TX, + CH_REQ_TYPE_GO_START_BSS, +#if (CFG_SUPPORT_DFS_MASTER == 1) + CH_REQ_TYPE_DFS_CAC, +#endif + 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 ucBssIndex; + UINT_8 ucTokenID; + UINT_8 ucPrimaryChannel; + ENUM_CHNL_EXT_T eRfSco; + ENUM_BAND_T eRfBand; + ENUM_CHANNEL_WIDTH_T eRfChannelWidth; /* To support 80/160MHz bandwidth */ + UINT_8 ucRfCenterFreqSeg1; /* To support 80/160MHz bandwidth */ + UINT_8 ucRfCenterFreqSeg2; /* To support 80/160MHz bandwidth */ + ENUM_CH_REQ_TYPE_T eReqType; + UINT_32 u4MaxInterval; /* In unit of ms */ + ENUM_DBDC_BN_T eDBDCBand; +} 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 ucBssIndex; + UINT_8 ucTokenID; + ENUM_DBDC_BN_T eDBDCBand; +} 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 ucBssIndex; + UINT_8 ucTokenID; + UINT_8 ucPrimaryChannel; + ENUM_CHNL_EXT_T eRfSco; + ENUM_BAND_T eRfBand; + ENUM_CHANNEL_WIDTH_T eRfChannelWidth; /* To support 80/160MHz bandwidth */ + UINT_8 ucRfCenterFreqSeg1; /* To support 80/160MHz bandwidth */ + UINT_8 ucRfCenterFreqSeg2; /* To support 80/160MHz bandwidth */ + ENUM_CH_REQ_TYPE_T eReqType; + UINT_32 u4GrantInterval; /* In unit of ms */ + ENUM_DBDC_BN_T eDBDCBand; +} 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 ucBssIndex; + UINT_8 ucTokenID; + UINT_8 ucPrimaryChannel; + ENUM_CHNL_EXT_T eRfSco; + ENUM_BAND_T eRfBand; + ENUM_CHANNEL_WIDTH_T eRfChannelWidth; /* To support 80/160MHz bandwidth */ + UINT_8 ucRfCenterFreqSeg1; /* To support 80/160MHz bandwidth */ + UINT_8 ucRfCenterFreqSeg2; /* To support 80/160MHz bandwidth */ + ENUM_CH_REQ_TYPE_T eReqType; +} MSG_CH_RECOVER_T, *P_MSG_CH_RECOVER_T; + +typedef struct _CNM_INFO_T { + BOOLEAN fgChGranted; + UINT_8 ucBssIndex; + UINT_8 ucTokenID; +} 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 + +#if CFG_SUPPORT_DBDC +typedef struct _CNM_DBDC_CAP_T { + UINT_8 ucBssIndex; + UINT_8 ucNss; + UINT_8 ucWmmSetIndex; +} CNM_DBDC_CAP_T, *P_CNM_DBDC_CAP_T; + +typedef enum _ENUM_CNM_DBDC_MODE_T { + DBDC_MODE_DISABLED, /* A/G traffic separate by WMM, but both WMM TRX on band 0, CANNOT enable DBDC */ + DBDC_MODE_STATIC, /* A/G traffic separate by WMM, WMM0/1 TRX on band 0/1, CANNOT disable DBDC */ + DBDC_MODE_DYNAMIC, /* Automatically enable/disable DBDC, setting just like static/disable mode */ + DBDC_MODE_NUM +} ENUM_CNM_DBDC_MODE_T, *P_ENUM_CNM_DBDC_MODE_T; + +typedef enum _ENUM_CNM_DBDC_SWITCH_MECHANISM_T { /* When DBDC available in dynamic DBDC */ + DBDC_SWITCH_MECHANISM_LATENCY_MODE, /* Switch to DBDC when available (less latency) */ + DBDC_SWITCH_MECHANISM_THROUGHPUT_MODE, /* Switch to DBDC when DBDC T-put > MCC T-put */ + DBDC_SWITCH_MECHANISM_NUM +} ENUM_CNM_DBDC_SWITCH_MECHANISM_T, *P_ENUM_CNM_DBDC_SWITCH_MECHANISM_T; +#endif /*CFG_SUPPORT_DBDC*/ + +/******************************************************************************* +* P U B 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 CNM_CH_GRANTED_FOR_BSS(_prAdapter, _ucBssIndex) \ + ((_prAdapter)->rCnmInfo.fgChGranted && \ + (_prAdapter)->rCnmInfo.ucBssIndex == (_ucBssIndex)) + +/******************************************************************************* +* 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); + +#if (CFG_SUPPORT_DFS_MASTER == 1) +VOID cnmRadarDetectEvent(P_ADAPTER_T prAdapter, P_WIFI_EVENT_T prEvent); + +VOID cnmCsaDoneEvent(P_ADAPTER_T prAdapter, P_WIFI_EVENT_T prEvent); +#endif + +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, UINT_8 ucBssIndex); + +BOOLEAN cnmBss80mBwPermitted(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex); + +UINT_8 cnmGetBssMaxBw(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex); + +UINT_8 cnmGetBssMaxBwToChnlBW(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex); + +P_BSS_INFO_T cnmGetBssInfoAndInit(P_ADAPTER_T prAdapter, ENUM_NETWORK_TYPE_T eNetworkType, BOOLEAN fgIsP2pDevice); + +VOID cnmFreeBssInfo(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); +#if CFG_SUPPORT_CHNL_CONFLICT_REVISE +BOOLEAN cnmAisDetectP2PChannel(P_ADAPTER_T prAdapter, P_ENUM_BAND_T prBand, PUINT_8 pucPrimaryChannel); +#endif + +#if (CFG_HW_WMM_BY_BSS == 1) +UINT_8 cnmWmmIndexDecision(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo); +VOID cnmFreeWmmIndex(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo); +#endif + +#if CFG_SUPPORT_DBDC +VOID cnmInitDbdcSetting(IN P_ADAPTER_T prAdapter); + +VOID cnmUpdateDbdcSetting(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgDbdcEn); + +VOID cnmGetDbdcCapability( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucBssIndex, + IN ENUM_BAND_T eRfBand, + IN UINT_8 ucPrimaryChannel, + IN UINT_8 ucNss, + OUT P_CNM_DBDC_CAP_T prDbdcCap +); + +VOID cnmDbdcEnableDecision( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucChangedBssIndex, + IN ENUM_BAND_T eRfBand +); + +VOID cnmDbdcDisableDecision(IN P_ADAPTER_T prAdapter, IN UINT_8 ucChangedBssIndex); +VOID cnmDbdcDecision(IN P_ADAPTER_T prAdapter, IN ULONG plParamPtr); +#endif /*CFG_SUPPORT_DBDC*/ +VOID cnmCheckPendingTimer(IN P_ADAPTER_T prAdapter); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#ifndef _lint +/* We don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + * We'll need this to guarantee the same member order in different structures + * to simply handling effort in some functions. + */ +static __KAL_INLINE__ VOID cnmMsgDataTypeCheck(VOID) +{ + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, rMsgHdr) == 0); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, rMsgHdr) == OFFSET_OF(MSG_CH_RECOVER_T, rMsgHdr)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, ucBssIndex) == OFFSET_OF(MSG_CH_RECOVER_T, ucBssIndex)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, ucTokenID) == OFFSET_OF(MSG_CH_RECOVER_T, ucTokenID)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, ucPrimaryChannel) == + OFFSET_OF(MSG_CH_RECOVER_T, ucPrimaryChannel)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, eRfSco) == OFFSET_OF(MSG_CH_RECOVER_T, eRfSco)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, eRfBand) == OFFSET_OF(MSG_CH_RECOVER_T, eRfBand)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, eReqType) == OFFSET_OF(MSG_CH_RECOVER_T, eReqType)); +} +#endif /* _lint */ + +#endif /* _CNM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/cnm_mem.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/cnm_mem.h new file mode 100644 index 0000000000000..b608343362b3c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/cnm_mem.h @@ -0,0 +1,939 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +#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 + +/* Define the argument of cnmStaFreeAllStaByNetwork when all station records + * will be free. No one will be free + */ +#define STA_REC_EXCLUDE_NONE CFG_STA_REC_NUM + +/******************************************************************************* +* 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; + +#if 0 +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; +#endif + +#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; + +#if CFG_SUPPORT_802_11W +/* AP PMF */ +struct AP_PMF_CFG { + BOOLEAN fgMfpc; + BOOLEAN fgMfpr; + BOOLEAN fgSha256; + BOOLEAN fgAPApplyPmfReq; + BOOLEAN fgBipKeyInstalled; +}; + +struct STA_PMF_CFG { + BOOLEAN fgMfpc; + BOOLEAN fgMfpr; + BOOLEAN fgSha256; + BOOLEAN fgApplyPmf; + BOOLEAN fgBipKeyInstalled; + BOOLEAN fgRxDeauthResp; /* for certification 4.3.3.1, 4.3.3.2 TX unprotected deauth */ + + /* For PMF SA query TX request retry a timer */ + UINT_32 u4SAQueryStart; /* record the start time of 1st SAQ request */ + UINT_32 u4SAQueryCount; + UINT_8 ucSAQueryTimedOut; /* retry more than 1000ms */ + TIMER_T rSAQueryTimer; + UINT_16 u2TransactionID; + +}; +#endif + +/* Define STA record structure */ +struct _STA_RECORD_T { + LINK_ENTRY_T rLinkEntry; + UINT_8 ucIndex; /* Not modify it except initializing */ + UINT_8 ucWlanIndex; /* WLAN table index */ + + /* UINT_8 ucBMCWlanIndex; */ /* The BSS STA Rx WLAN index, + * IBSS Rx BC WLAN table index, + * work at IBSS Open and WEP + */ + + 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 ucBssIndex; /* BSS_INFO_I index */ + + 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 ucVhtCapNumSoundingDimensions; /* record from bcn or probe response*/ + + UINT_8 ucDesiredPhyTypeSet; /* The match result by AND operation of peer's + * PhyTypeSet and ours. + */ + BOOLEAN fgHasBasicPhyType; /* A flag to indicate a Basic Phy Type which + * is used to generate some Phy Attribute IE + * (e.g. capability, MIB) during association. + */ + UINT_8 ucNonHTBasicPhyType; /* The Basic Phy Type chosen among the + * ucDesiredPhyTypeSet. + */ + + UINT_16 u2HwDefaultFixedRateCode; + + 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_8 aucRxMcsBitmask[SUP_MCS_RX_BITMASK_OCTET_NUM]; + UINT_16 u2RxHighestSupportedRate; + UINT_32 u4TxRateInfo; + 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 */ +#if 1 /* CFG_SUPPORT_802_11AC */ + /*------------------------------------------------------------------------------------------*/ + /* 802.11ac VHT capabilities when (prStaRec->ucPhyTypeSet & PHY_TYPE_BIT_VHT) is true */ + /* They have the same definition with fields of information element */ + /*------------------------------------------------------------------------------------------*/ + UINT_32 u4VhtCapInfo; + UINT_16 u2VhtRxMcsMap; + UINT_16 u2VhtRxHighestSupportedDataRate; + UINT_16 u2VhtTxMcsMap; + UINT_16 u2VhtTxHighestSupportedDataRate; + UINT_8 ucVhtOpMode; +#endif + UINT_8 ucRCPI; /* RCPI of peer */ + + UINT_8 ucDTIMPeriod; /* Target BSS's DTIM Period, we use this + * value for setup Listen Interval + * TODO(Kevin): TBD + */ + UINT_8 ucAuthAlgNum; /* For Infra/AP Mode, the Auth Algorithm Num used in Authentication(SAA/AAA) */ + BOOLEAN fgIsReAssoc; /* For Infra/AP Mode, to indicate ReAssoc Frame was in used(SAA/AAA) */ + + UINT_8 ucTxAuthAssocRetryCount; /* For Infra Mode, the Retry Count of TX Auth/Assod Frame(SAA) */ + UINT_8 ucTxAuthAssocRetryLimit; /* For Infra Mode, the Retry Limit of TX Auth/Assod Frame(SAA) */ +#if CFG_SUPPORT_CFG80211_AUTH + /* Record what we sent for retry TX Auth/Assoc without SAA FSM */ + enum ENUM_AA_SENT_T eAuthAssocSent; +#endif + UINT_16 u2StatusCode; /* Status of Auth/Assoc Req */ + UINT_16 u2ReasonCode; /* Reason that been Deauth/Disassoc */ + + /* Point to an allocated buffer for storing Challenge */ + /* Text for Shared Key Authentication */ + P_IE_CHALLENGE_TEXT_T prChallengeText; + + /* For Infra Mode, a timer used to send a timeout event + * while waiting for TX request done or RX response. + */ + TIMER_T rTxReqDoneOrRxRespTimer; + + /* For Infra Mode, a timer used to avoid the Deauth frame + * not be sent + */ + TIMER_T rDeauthTxDoneTimer; + + /*------------------------------------------------------------------------------------------*/ + /* 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 */ + + /* Duplicate removal for HT STA on a + * per-TID basis ("+1" is for MMPDU and non-QoS) + */ + UINT_16 au2CachedSeqCtrl[TID_NUM + 1]; + + BOOLEAN afgIsIgnoreAmsduDuplicate[TID_NUM + 1]; + +#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 */ + +#if CFG_SUPPORT_ADHOC + BOOLEAN fgAdhocRsnBcKeyExist[2]; /* Ad-hoc RSN Rx BC key exist flag, + * only reserved two entry for each peer + */ + UINT_8 ucAdhocRsnBcWlanIndex[2]; /* Ad-hoc RSN Rx BC wlan index */ +#endif + + BOOLEAN fgPortBlock; /* The 802.1x Port Control flag */ + + BOOLEAN fgTransmitKeyExist; /* Unicast key exist for this STA */ + + BOOLEAN fgTxAmpduEn; /* Enable TX AMPDU for this Peer */ + BOOLEAN fgRxAmpduEn; /* Enable RX AMPDU for this Peer */ + + PUINT_8 pucAssocReqIe; + UINT_16 u2AssocReqIeLen; + + WIFI_WMM_AC_STAT_T arLinkStatistics[WMM_AC_INDEX_NUM]; /*link layer satatistics */ + + /*------------------------------------------------------------------------------------------*/ + /* WMM/QoS related fields */ + /*------------------------------------------------------------------------------------------*/ + BOOLEAN fgIsQoS; /* If the STA is associated as a QSTA or QAP (for TX/RX) */ + BOOLEAN fgIsWmmSupported; /* If the peer supports WMM, set to TRUE (for association) */ + BOOLEAN fgIsUapsdSupported; /* Set according to the scan result (for association) */ + + /*------------------------------------------------------------------------------------------*/ + /* P2P related fields */ + /*------------------------------------------------------------------------------------------*/ +#if CFG_ENABLE_WIFI_DIRECT + UINT_8 u2DevNameLen; + UINT_8 aucDevName[WPS_ATTRI_MAX_LEN_DEVICE_NAME]; + + UINT_8 aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ + + UINT_16 u2ConfigMethods; + + UINT_8 ucDeviceCap; + + UINT_8 ucSecondaryDevTypeCount; + + DEVICE_TYPE_T rPrimaryDevTypeBE; + + DEVICE_TYPE_T arSecondaryDevTypeBE[P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT]; +#endif /* CFG_SUPPORT_P2P */ + + /*------------------------------------------------------------------------------------------*/ + /* QM related fields */ + /*------------------------------------------------------------------------------------------*/ + + UINT_8 ucFreeQuota; /* Per Sta flow controal. Valid when fgIsInPS is TRUE. + *Change it for per Queue flow control + */ + /* UINT_8 aucFreeQuotaPerQueue[NUM_OF_PER_STA_TX_QUEUES]; *//* used in future */ + UINT_8 ucFreeQuotaForDelivery; + UINT_8 ucFreeQuotaForNonDelivery; + + /*------------------------------------------------------------------------------------------*/ + /* TXM related fields */ + /*------------------------------------------------------------------------------------------*/ + PVOID aprTxDescTemplate[TX_DESC_TID_NUM]; + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE && CFG_ENABLE_PER_STA_STATISTICS + UINT_32 u4TotalTxPktsNumber; + UINT_32 u4TotalTxPktsTime; + UINT_32 u4TotalRxPktsNumber; + UINT_32 u4MaxTxPktsTime; + UINT_32 u4ThresholdCounter; +#endif + +#if 1 + /*------------------------------------------------------------------------------------------*/ + /* To be removed, this is to make que_mgt compilation success only */ + /*------------------------------------------------------------------------------------------*/ + /* When this STA_REC is in use, set to TRUE. */ + BOOLEAN fgIsValid; + + /* TX key is ready */ + BOOLEAN fgIsTxKeyReady; + + /* When the STA is connected or TX key is ready */ + BOOLEAN fgIsTxAllowed; + + /* Per-STA Queues: [0] AC0, [1] AC1, [2] AC2, [3] AC3 */ + QUE_T arTxQueue[NUM_OF_PER_STA_TX_QUEUES]; + + /* Per-STA Pending Queues: [0] AC0, [1] AC1, [2] AC2, [3] AC3 */ + /* This queue is for Tx packet in protected BSS before key is set */ + QUE_T arPendingTxQueue[NUM_OF_PER_STA_TX_QUEUES]; + + /* Tx packet target queue pointer. Select between arTxQueue & arPendingTxQueue */ + P_QUE_T aprTargetQueue[NUM_OF_PER_STA_TX_QUEUES]; + + /* 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 + UINT_8 ucTrafficDataType; /* 0: auto 1: data 2: video 3: voice */ + UINT_8 ucTxGfMode; /* 0: auto 1:Force enable 2: Force disable 3: enable by peer */ + UINT_8 ucTxSgiMode; /* 0: auto 1:Force enable 2: Force disable 3: enable by peer */ + UINT_8 ucTxStbcMode; /* 0: auto 1:Force enable 2: Force disable 3: enable by peer */ + UINT_32 u4FixedPhyRate; /* */ + UINT_16 u2MaxLinkSpeed; /* unit is 0.5 Mbps */ + UINT_16 u2MinLinkSpeed; + UINT_32 u4Flags; /* reserved for MTK Synergies */ + +#if CFG_SUPPORT_TDLS + BOOLEAN fgTdlsIsProhibited; /* TRUE: AP prohibits TDLS links */ + BOOLEAN fgTdlsIsChSwProhibited; /* TRUE: AP prohibits TDLS chan switch */ + + BOOLEAN flgTdlsIsInitiator; /* TRUE: the peer is the initiator */ + IE_HT_CAP_T rTdlsHtCap; /* temp to queue HT capability element */ + PARAM_KEY_T rTdlsKeyTemp; /* temp to queue the key information */ + UINT_8 ucTdlsIndex; +#endif /* CFG_SUPPORT_TDLS */ +#if CFG_SUPPORT_TX_BF + TXBF_PFMU_STA_INFO rTxBfPfmuStaInfo; +#endif +#if CFG_SUPPORT_MSP + UINT_32 u4RxVector0; + UINT_32 u4RxVector1; + UINT_32 u4RxVector2; + UINT_32 u4RxVector3; + UINT_32 u4RxVector4; +#endif +#if CFG_SUPPORT_LAST_SEC_MCS_INFO + UINT_32 au4RxVect0Que[MCS_INFO_SAMPLE_CNT]; + UINT_32 au4RxVect1Que[MCS_INFO_SAMPLE_CNT]; +#endif + UINT_8 ucSmDialogToken; /* Spectrum Mngt Dialog Token */ + UINT_8 ucSmMsmtRequestMode; /* Measurement Request Mode */ + UINT_8 ucSmMsmtToken; /* Measurement Request Token */ +#if CFG_SUPPORT_802_11W + /* AP PMF */ + struct STA_PMF_CFG rPmfCfg; +#endif + UINT_8 eapol_re_enqueue_cnt; +}; + +#if 0 +/* use nic_tx.h instead */ +/* MSDU_INFO and SW_RFB structure */ +typedef struct _MSDU_INFO_T { + + /* 4 ----------------MSDU_INFO and SW_RFB Common Fields------------------ */ + + LINK_ENTRY_T rLinkEntry; + PUINT_8 pucBuffer; /* Pointer to the associated buffer */ + + UINT_8 ucBufferSource; /* HIF TX0, HIF TX1, MAC RX, or MNG Pool */ + UINT_8 ucNetworkTypeIndex; /* Network type index that this TX packet is assocaited with */ + UINT_8 ucTC; /* 0 to 5 (used by HIF TX to increment the corresponding TC counter) */ + UINT_8 ucTID; /* Traffic Identification */ + + BOOLEAN fgIs802_11Frame; /* Set to TRUE for 802.11 frame */ + UINT_8 ucMacHeaderLength; + UINT_16 u2PayloadLength; + PUINT_8 pucMacHeader; /* 802.11 header */ + PUINT_8 pucPayload; /* 802.11 payload */ + + OS_SYSTIME rArrivalTime; /* System Timestamp (4) */ + P_STA_RECORD_T prStaRec; + +#if CFG_PROFILE_BUFFER_TRACING + ENUM_BUFFER_ACTIVITY_TYPE_T eActivity[2]; + UINT_32 rActivityTime[2]; +#endif +#if DBG && CFG_BUFFER_FREE_CHK + BOOLEAN fgBufferInSource; +#endif + + UINT_8 ucControlFlag; /* For specify some Control Flags, e.g. Basic Rate */ + + /* 4 -----------------------Non-Common ------------------------- */ + /* TODO: move flags to ucControlFlag */ + + BOOLEAN fgIs1xFrame; /* Set to TRUE for 802.1x frame */ + + /* TXM: For TX Done handling, callback function & parameter (5) */ + BOOLEAN fgIsTxFailed; /* Set to TRUE if transmission failure */ + + PFN_TX_DONE_HANDLER pfTxDoneHandler; + + UINT_64 u8TimeStamp; /* record the TX timestamp */ + + /* TXM: For PS forwarding control (per-STA flow control) */ + UINT_8 ucPsForwardingType; /* Delivery-enabled, non-delivery-enabled, non-PS */ + UINT_8 ucPsSessionID; /* The Power Save session id for PS forwarding control */ + + /* TXM: For MAC TX DMA operations */ + UINT_8 ucMacTxQueIdx; /* MAC TX queue: AC0-AC6, BCM, or BCN */ + BOOLEAN fgNoAck; /* Set to true if Ack is not required for this packet */ + BOOLEAN fgBIP; /* Set to true if BIP is used for this packet */ + UINT_8 ucFragTotalCount; + UINT_8 ucFragFinishedCount; + UINT_16 u2FragThreshold; /* Fragmentation threshold without WLAN Header & FCS */ + BOOLEAN fgFixedRate; /* If a fixed rate is used, set to TRUE. */ + UINT_8 ucFixedRateCode; /* The rate code copied to MAC TX Desc */ + UINT_8 ucFixedRateRetryLimit; /* The retry limit when a fixed rate is used */ + BOOLEAN fgIsBmcQueueEnd; /* Set to true if this packet is the end of BMC */ + + /* TXM: For flushing ACL frames */ + UINT_16 u2PalLLH; /* 802.11 PAL LLH */ + /* UINT_16 u2LLH; */ + UINT_16 u2ACLSeq; /* u2LLH+u2ACLSeq for AM HCI flush ACL frame */ + + /* TXM for retransmitting a flushed packet */ + BOOLEAN fgIsSnAssigned; + UINT_16 u2SequenceNumber; /* To remember the Sequence Control field of this MPDU */ + +} MSDU_INFO_T, *P_MSDU_INFO_T; +#endif + +#if 0 +/* nic_rx.h */ +typedef struct _SW_RFB_T { + + /* 4 ----------------MSDU_INFO and SW_RFB Common Fields------------------ */ + + LINK_ENTRY_T rLinkEntry; + PUINT_8 pucBuffer; /* Pointer to the associated buffer */ + + UINT_8 ucBufferSource; /* HIF TX0, HIF TX1, MAC RX, or MNG Pool */ + UINT_8 ucNetworkTypeIndex; /* Network type index that this TX packet is assocaited with */ + UINT_8 ucTC; /* 0 to 5 (used by HIF TX to increment the corresponding TC counter) */ + UINT_8 ucTID; /* Traffic Identification */ + + BOOLEAN fgIs802_11Frame; /* Set to TRUE for 802.11 frame */ + UINT_8 ucMacHeaderLength; + UINT_16 u2PayloadLength; + PUINT_8 pucMacHeader; /* 802.11 header */ + PUINT_8 pucPayload; /* 802.11 payload */ + + OS_SYSTIME rArrivalTime; /* System Timestamp (4) */ + P_STA_RECORD_T prStaRec; + +#if CFG_PROFILE_BUFFER_TRACING + ENUM_BUFFER_ACTIVITY_TYPE_T eActivity[2]; + UINT_32 rActivityTime[2]; +#endif +#if DBG && CFG_BUFFER_FREE_CHK + BOOLEAN fgBufferInSource; +#endif + + UINT_8 ucControlFlag; /* For specify some Control Flags, e.g. Basic Rate */ + + /* 4 -----------------------Non-Common ------------------------- */ + + /* For composing the HIF RX Header (TODO: move flags to ucControlFlag) */ + PUINT_8 pucHifRxPacket; /* Pointer to the Response packet to HIF RX0 or RX1 */ + UINT_16 u2HifRxPacketLength; + UINT_8 ucHeaderOffset; + UINT_8 ucHifRxPortIndex; + + UINT_16 u2SequenceControl; + BOOLEAN fgIsA4Frame; /* (For MAC RX packet parsing) set to TRUE if 4 addresses are present */ + BOOLEAN fgIsBAR; + BOOLEAN fgIsQoSData; + BOOLEAN fgIsAmsduSubframe; /* Set to TRUE for A-MSDU Subframe */ + + /* For HIF RX DMA Desc */ + BOOLEAN fgTUChecksumCheckRequired; + BOOLEAN fgIPChecksumCheckRequired; + UINT_8 ucEtherTypeOffset; + +} SW_RFB_T, *P_SW_RFB_T; +#endif + +typedef enum _ENUM_STA_REC_CMD_ACTION_T { + STA_REC_CMD_ACTION_STA = 0, + STA_REC_CMD_ACTION_BSS = 1, + STA_REC_CMD_ACTION_BSS_EXCLUDE_STA = 2 +} ENUM_STA_REC_CMD_ACTION_T, *P_ENUM_STA_REC_CMD_ACTION_T; + +#if CFG_SUPPORT_TDLS + +/* TDLS FSM */ +typedef struct _CMD_PEER_ADD_T { + + UINT_8 aucPeerMac[6]; + ENUM_STA_TYPE_T eStaType; +} CMD_PEER_ADD_T; + +typedef struct _CMD_PEER_UPDATE_HT_CAP_MCS_INFO_T { + UINT_8 arRxMask[SUP_MCS_RX_BITMASK_OCTET_NUM]; + UINT_16 u2RxHighest; + UINT_8 ucTxParams; + UINT_8 Reserved[3]; +} CMD_PEER_UPDATE_HT_CAP_MCS_INFO_T; + +typedef struct _CMD_PEER_UPDATE_VHT_CAP_MCS_INFO_T { + UINT_8 arRxMask[SUP_MCS_RX_BITMASK_OCTET_NUM]; +} CMD_PEER_UPDATE_VHT_CAP_MCS_INFO_T; + +typedef struct _CMD_PEER_UPDATE_HT_CAP_T { + UINT_16 u2CapInfo; + UINT_8 ucAmpduParamsInfo; + + /* 16 bytes MCS information */ + CMD_PEER_UPDATE_HT_CAP_MCS_INFO_T rMCS; + + UINT_16 u2ExtHtCapInfo; + UINT_32 u4TxBfCapInfo; + UINT_8 ucAntennaSelInfo; +} CMD_PEER_UPDATE_HT_CAP_T; + +typedef struct _CMD_PEER_UPDATE_VHT_CAP_T { + UINT_16 u2CapInfo; + /* 16 bytes MCS information */ + CMD_PEER_UPDATE_VHT_CAP_MCS_INFO_T rVMCS; + +} CMD_PEER_UPDATE_VHT_CAP_T; + +typedef struct _CMD_PEER_UPDATE_T { + + UINT_8 aucPeerMac[6]; + +#define CMD_PEER_UPDATE_SUP_CHAN_MAX 50 + UINT_8 aucSupChan[CMD_PEER_UPDATE_SUP_CHAN_MAX]; + + UINT_16 u2StatusCode; + +#define CMD_PEER_UPDATE_SUP_RATE_MAX 50 + UINT_8 aucSupRate[CMD_PEER_UPDATE_SUP_RATE_MAX]; + UINT_16 u2SupRateLen; + + UINT_8 UapsdBitmap; + UINT_8 UapsdMaxSp; /* MAX_SP */ + + UINT_16 u2Capability; +#define CMD_PEER_UPDATE_EXT_CAP_MAXLEN 5 + UINT_8 aucExtCap[CMD_PEER_UPDATE_EXT_CAP_MAXLEN]; + UINT_16 u2ExtCapLen; + + CMD_PEER_UPDATE_HT_CAP_T rHtCap; + CMD_PEER_UPDATE_VHT_CAP_T rVHtCap; + + BOOLEAN fgIsSupHt; + ENUM_STA_TYPE_T eStaType; + + /* TODO */ + /* So far, TDLS only a few of the parameters, the rest will be added in the future requiements */ + /* kernel 3.10 station paramenters */ +#if 0 + struct station_parameters { + const u8 *supported_rates; + struct net_device *vlan; + u32 sta_flags_mask, sta_flags_set; + u32 sta_modify_mask; + int listen_interval; + u16 aid; + u8 supported_rates_len; + u8 plink_action; + u8 plink_state; + const struct ieee80211_ht_cap *ht_capa; + const struct ieee80211_vht_cap *vht_capa; + u8 uapsd_queues; + u8 max_sp; + enum nl80211_mesh_power_mode local_pm; + u16 capability; + const u8 *ext_capab; + u8 ext_capab_len; + const u8 *supported_channels; + u8 supported_channels_len; + const u8 *supported_oper_classes; + u8 supported_oper_classes_len; + }; +#endif + +} CMD_PEER_UPDATE_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 +******************************************************************************** +*/ + +#if CFG_DBG_MGT_BUF +#define cnmMgtPktAlloc(_prAdapter, _u4Length) \ + cnmPktAllocWrapper((_prAdapter), (_u4Length), (PUINT_8)__func__) + +#define cnmMgtPktFree(_prAdapter, _prMsduInfo) \ + cnmPktFreeWrapper((_prAdapter), (_prMsduInfo), (PUINT_8)__func__) +#else +#define cnmMgtPktAlloc cnmPktAlloc +#define cnmMgtPktFree cnmPktFree +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +P_MSDU_INFO_T cnmPktAllocWrapper(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Length, IN PUINT_8 pucStr); + +VOID cnmPktFreeWrapper(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN PUINT_8 pucStr); + +P_MSDU_INFO_T cnmPktAlloc(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Length); + +VOID cnmPktFree(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); + +P_STA_RECORD_T +cnmStaRecAlloc(IN P_ADAPTER_T prAdapter, IN ENUM_STA_TYPE_T eStaType, IN UINT_8 ucBssIndex, IN PUINT_8 pucMacAddr); + +VOID cnmStaRecFree(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +VOID cnmStaFreeAllStaByNetwork(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex, UINT_8 ucStaRecIndexExcluded); + +P_STA_RECORD_T cnmGetStaRecByIndex(IN P_ADAPTER_T prAdapter, IN UINT_8 ucIndex); + +P_STA_RECORD_T cnmGetStaRecByAddress(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex, UINT_8 aucPeerMACAddress[]); + +P_STA_RECORD_T cnmGetAnyStaRecByAddress(P_ADAPTER_T prAdapter, + PUINT_8 pucPeerMacAddr); + +VOID cnmStaRecChangeState(IN P_ADAPTER_T prAdapter, IN OUT P_STA_RECORD_T prStaRec, IN UINT_8 ucNewState); + +VOID cnmDumpStaRec(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIdx); + +UINT_32 cnmDumpMemoryStatus(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuf, IN UINT_32 u4Max); + +#if CFG_SUPPORT_TDLS +WLAN_STATUS /* TDLS_STATUS */ +cnmPeerAdd(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, PUINT_32 pu4SetInfoLen); + +WLAN_STATUS /* TDLS_STATUS */ +cnmPeerUpdate(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, PUINT_32 pu4SetInfoLen); + +P_STA_RECORD_T cnmGetTdlsPeerByAddress(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex, UINT_8 aucPeerMACAddress[]); +#endif + +VOID cnmStaSendUpdateCmd(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, P_TXBF_PFMU_STA_INFO prTxBfPfmuStaInfo, + BOOLEAN fgNeedResp); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#ifndef _lint +/* Kevin: we don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + * We'll need this for porting driver to different RTOS. + */ +static __KAL_INLINE__ VOID cnmMemDataTypeCheck(VOID) +{ +#if 0 + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, rLinkEntry) == 0); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, rLinkEntry) == OFFSET_OF(SW_RFB_T, rLinkEntry)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, pucBuffer) == OFFSET_OF(SW_RFB_T, pucBuffer)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucBufferSource) == OFFSET_OF(SW_RFB_T, ucBufferSource)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, pucMacHeader) == OFFSET_OF(SW_RFB_T, pucMacHeader)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucMacHeaderLength) == + OFFSET_OF(SW_RFB_T, ucMacHeaderLength)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, pucPayload) == OFFSET_OF(SW_RFB_T, pucPayload)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, u2PayloadLength) == OFFSET_OF(SW_RFB_T, u2PayloadLength)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, prStaRec) == OFFSET_OF(SW_RFB_T, prStaRec)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucNetworkTypeIndex) == + OFFSET_OF(SW_RFB_T, ucNetworkTypeIndex)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucTID) == OFFSET_OF(SW_RFB_T, ucTID)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, fgIs802_11Frame) == OFFSET_OF(SW_RFB_T, fgIs802_11Frame)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucControlFlag) == OFFSET_OF(SW_RFB_T, ucControlFlag)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, rArrivalTime) == OFFSET_OF(SW_RFB_T, rArrivalTime)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucTC) == OFFSET_OF(SW_RFB_T, ucTC)); + +#if CFG_PROFILE_BUFFER_TRACING + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, eActivity[0]) == OFFSET_OF(SW_RFB_T, eActivity[0])); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, rActivityTime[0]) == + OFFSET_OF(SW_RFB_T, rActivityTime[0])); +#endif + +#if DBG && CFG_BUFFER_FREE_CHK + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, fgBufferInSource) == + OFFSET_OF(SW_RFB_T, fgBufferInSource)); +#endif + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(STA_RECORD_T, rLinkEntry) == 0); + + return; +#endif +} +#endif /* _lint */ + +#endif /* _CNM_MEM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/cnm_scan.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/cnm_scan.h new file mode 100644 index 0000000000000..ea2ad50193385 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/cnm_scan.h @@ -0,0 +1,164 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: @(#) +*/ + +/*! \file "cnm_scan.h" +* \brief +* +*/ + + +#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 +#define SCN_P2P_FULL_SCAN_PARAM 0 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* The type of Scan Source */ +typedef enum _ENUM_SCN_REQ_SOURCE_T { + SCN_REQ_SOURCE_HEM = 0, + SCN_REQ_SOURCE_NET_FSM, + SCN_REQ_SOURCE_ROAMING, /* ROAMING Module is independent of AIS FSM */ + SCN_REQ_SOURCE_OBSS, /* 2.4G OBSS scan */ + SCN_REQ_SOURCE_NUM +} ENUM_SCN_REQ_SOURCE_T, *P_ENUM_SCN_REQ_SOURCE_T; + +typedef enum _ENUM_SCAN_PROFILE_T { + SCAN_PROFILE_FULL = 0, + SCAN_PROFILE_PARTIAL, + SCAN_PROFILE_VOIP, + SCAN_PROFILE_FULL_2G4, + SCAN_PROFILE_NUM +} ENUM_SCAN_PROFILE_T, *P_ENUM_SCAN_PROFILE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#if 0 +VOID cnmScanInit(VOID); + +VOID cnmScanRunEventScanRequest(IN P_MSG_HDR_T prMsgHdr); + +BOOLEAN cnmScanRunEventScanAbort(IN P_MSG_HDR_T prMsgHdr); + +VOID cnmScanProfileSelection(VOID); + +VOID cnmScanProcessStart(VOID); + +VOID cnmScanProcessStop(VOID); + +VOID cnmScanRunEventReqAISAbsDone(IN P_MSG_HDR_T prMsgHdr); + +VOID cnmScanRunEventCancelAISAbsDone(IN P_MSG_HDR_T prMsgHdr); + +VOID cnmScanPartialScanTimeout(UINT_32 u4Param); + +VOID cnmScanRunEventScnFsmComplete(IN P_MSG_HDR_T prMsgHdr); +#endif + +#endif /* _CNM_SCAN_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/cnm_timer.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/cnm_timer.h new file mode 100644 index 0000000000000..5770ab3870d13 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/cnm_timer.h @@ -0,0 +1,231 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +#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 +#undef USEC_PER_SEC +#define USEC_PER_SEC 1000000 + +#define USEC_PER_TU 1024 /* microsecond */ + +#define MSEC_PER_MIN (60 * MSEC_PER_SEC) + +#define MGMT_MAX_TIMEOUT_INTERVAL ((UINT_32)0x7fffffff) + +#define WAKE_LOCK_MAX_TIME 5 /* Unit: sec */ + +/* If WAKE_LOCK_MAX_TIME is too large, the whole system may always keep awake + * because of periodic timer of OBSS scanning + */ +#if (WAKE_LOCK_MAX_TIME >= OBSS_SCAN_MIN_INTERVAL) +#error WAKE_LOCK_MAX_TIME is too large +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef VOID(*PFN_MGMT_TIMEOUT_FUNC) (P_ADAPTER_T, ULONG); + +typedef struct _TIMER_T { + LINK_ENTRY_T rLinkEntry; + OS_SYSTIME rExpiredSysTime; + UINT_16 u2Minutes; + UINT_16 u2Reserved; + ULONG ulDataPtr; + 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) +#define SEC_TO_USEC(_sec) ((UINT_32)(_sec) * USEC_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) * USEC_PER_SEC) / KAL_HZ) + +/* 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 ULONG ulDataPtr); + +VOID cnmTimerStopTimer(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer); + +VOID cnmTimerStartTimer(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer, IN UINT_32 u4TimeoutMs); + +VOID cnmTimerDoTimeOutCheck(IN P_ADAPTER_T prAdapter); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +static __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/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/hem_mbox.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/hem_mbox.h new file mode 100644 index 0000000000000..52a2f65ea0b0a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/hem_mbox.h @@ -0,0 +1,303 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/hem_mbox.h#3 +*/ + +/*! \file hem_mbox.h +* \brief +* +*/ + +#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 */ + +#if (CFG_SUPPORT_DFS_MASTER == 1) + MID_CNM_P2P_RADAR_DETECT, + MID_CNM_P2P_CSA_DONE, +#endif + /*--------------------------------------------------*/ + /* 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_DEL_IFACE, + MID_MNY_P2P_MGMT_FRAME_UPDATE, +#if (CFG_SUPPORT_DFS_MASTER == 1) + MID_MNY_P2P_DFS_CAC, + MID_MNY_P2P_SET_NEW_CHANNEL, +#endif +#if CFG_SUPPORT_WFD + MID_MNY_P2P_WFD_CFG_UPDATE, +#endif + MID_MNY_P2P_ACTIVE_BSS, +#endif + +#if CFG_SUPPORT_ADHOC + MID_SCN_AIS_FOUND_IBSS, /* SCN notify AIS that an IBSS Peer has been found and can merge into */ +#endif /* CFG_SUPPORT_ADHOC */ + + MID_SAA_AIS_FSM_ABORT, /* SAA notify AIS for indicating deauthentication/disassociation */ + + /*--------------------------------------------------*/ + /* AIS MGMT-TX Support */ + /*--------------------------------------------------*/ + MID_MNY_AIS_REMAIN_ON_CHANNEL, + MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL, + MID_MNY_AIS_MGMT_TX, + + MID_TOTAL_NUM +} ENUM_MSG_ID_T, *P_ENUM_MSG_ID_T; + +/* Message header of inter-components */ +struct _MSG_HDR_T { + LINK_ENTRY_T rLinkEntry; + ENUM_MSG_ID_T eMsgId; +}; + +typedef VOID(*PFN_MSG_HNDL_FUNC) (P_ADAPTER_T, P_MSG_HDR_T); + +typedef struct _MSG_HNDL_ENTRY { + ENUM_MSG_ID_T eMsgId; + PFN_MSG_HNDL_FUNC pfMsgHndl; +} MSG_HNDL_ENTRY_T, *P_MSG_HNDL_ENTRY_T; + +typedef enum _EUNM_MSG_SEND_METHOD_T { + MSG_SEND_METHOD_BUF = 0, /* Message is put in the queue and will be */ + /*executed when mailbox is checked. */ + MSG_SEND_METHOD_UNBUF /* The handler function is called immediately */ + /* in the same context of the sender */ +} EUNM_MSG_SEND_METHOD_T, *P_EUNM_MSG_SEND_METHOD_T; + +typedef enum _ENUM_MBOX_ID_T { + MBOX_ID_0 = 0, + MBOX_ID_TOTAL_NUM +} ENUM_MBOX_ID_T, *P_ENUM_MBOX_ID_T; + +/* Define Mailbox structure */ +typedef struct _MBOX_T { + LINK_T rLinkHead; +} MBOX_T, *P_MBOX_T; + +typedef struct _MSG_SAA_FSM_START_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + P_STA_RECORD_T prStaRec; +} MSG_SAA_FSM_START_T, *P_MSG_SAA_FSM_START_T; + +typedef struct _MSG_SAA_FSM_COMP_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + WLAN_STATUS rJoinStatus; + P_STA_RECORD_T prStaRec; + P_SW_RFB_T prSwRfb; +} MSG_SAA_FSM_COMP_T, *P_MSG_SAA_FSM_COMP_T; + +typedef struct _MSG_SAA_FSM_ABORT_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + P_STA_RECORD_T prStaRec; +} MSG_SAA_FSM_ABORT_T, *P_MSG_SAA_FSM_ABORT_T; + +typedef struct _MSG_CONNECTION_ABORT_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucNetTypeIndex; +} MSG_CONNECTION_ABORT_T, *P_MSG_CONNECTION_ABORT_T; + +typedef struct _MSG_REMAIN_ON_CHANNEL_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + ENUM_BAND_T eBand; + ENUM_CHNL_EXT_T eSco; + UINT_8 ucChannelNum; + UINT_32 u4DurationMs; + UINT_64 u8Cookie; +} MSG_REMAIN_ON_CHANNEL_T, *P_MSG_REMAIN_ON_CHANNEL_T; + +typedef struct _MSG_CANCEL_REMAIN_ON_CHANNEL_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_64 u8Cookie; +} MSG_CANCEL_REMAIN_ON_CHANNEL_T, *P_MSG_CANCEL_REMAIN_ON_CHANNEL_T; + +typedef struct _MSG_MGMT_TX_REQUEST_T { + MSG_HDR_T rMsgHdr; + P_MSDU_INFO_T prMgmtMsduInfo; + UINT_64 u8Cookie; /* For indication. */ + BOOLEAN fgNoneCckRate; + BOOLEAN fgIsWaitRsp; +} MSG_MGMT_TX_REQUEST_T, *P_MSG_MGMT_TX_REQUEST_T; + +/* specific message data types */ +typedef MSG_SAA_FSM_START_T MSG_JOIN_REQ_T, *P_MSG_JOIN_REQ_T; +typedef MSG_SAA_FSM_COMP_T MSG_JOIN_COMP_T, *P_MSG_JOIN_COMP_T; +typedef MSG_SAA_FSM_ABORT_T MSG_JOIN_ABORT_T, *P_MSG_JOIN_ABORT_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID mboxSetup(IN P_ADAPTER_T prAdapter, IN ENUM_MBOX_ID_T eMboxId); + +VOID +mboxSendMsg(IN P_ADAPTER_T prAdapter, + IN ENUM_MBOX_ID_T eMboxId, IN P_MSG_HDR_T prMsg, IN EUNM_MSG_SEND_METHOD_T eMethod); + +VOID mboxRcvAllMsg(IN P_ADAPTER_T prAdapter, IN ENUM_MBOX_ID_T eMboxId); + +VOID mboxInitialize(IN P_ADAPTER_T prAdapter); + +VOID mboxDestroy(IN P_ADAPTER_T prAdapter); + +VOID mboxDummy(IN P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _HEM_MBOX_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/hs20.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/hs20.h new file mode 100644 index 0000000000000..4fbc56f733fa1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/hs20.h @@ -0,0 +1,189 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/*! \file hs20.h + * \brief This file contains the function declaration for hs20.c. + */ + +#ifndef _HS20_H +#define _HS20_H + +#if CFG_SUPPORT_PASSPOINT +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************** + */ +#define BSSID_POOL_MAX_SIZE 8 +#define HS20_SIGMA_SCAN_RESULT_TIMEOUT 30 /* sec */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************** + */ + +#if CFG_ENABLE_GTK_FRAME_FILTER +/*For GTK Frame Filter*/ +typedef struct _IPV4_NETWORK_ADDRESS_LIST { + UINT_8 ucAddrCount; + IPV4_NETWORK_ADDRESS arNetAddr[1]; +} IPV4_NETWORK_ADDRESS_LIST, *P_IPV4_NETWORK_ADDRESS_LIST; +#endif + +/* Entry of BSSID Pool - For SIGMA Test */ +typedef struct _BSSID_ENTRY_T { + UINT_8 aucBSSID[MAC_ADDR_LEN]; +} BSSID_ENTRY_T, P_HS20_BSSID_POOL_ENTRY_T; + +struct _HS20_INFO_T { + /*Hotspot 2.0 Information */ + UINT_8 aucHESSID[MAC_ADDR_LEN]; + UINT_8 ucAccessNetworkOptions; + UINT_8 ucVenueGroup; /* VenueInfo - Group */ + UINT_8 ucVenueType; + UINT_8 ucHotspotConfig; + + /*Roaming Consortium Information */ + /* PARAM_HS20_ROAMING_CONSORTIUM_INFO rRCInfo; */ + + /*Hotspot 2.0 dummy AP Info */ + + /*Time Advertisement Information */ + /* UINT_32 u4UTCOffsetTime; */ + /* UINT_8 aucTimeZone[ELEM_MAX_LEN_TIME_ZONE]; */ + /* UINT_8 ucLenTimeZone; */ + + /* For SIGMA Test */ + /* BSSID Pool */ + BSSID_ENTRY_T arBssidPool[BSSID_POOL_MAX_SIZE]; + UINT_8 ucNumBssidPoolEntry; + BOOLEAN fgIsHS2SigmaMode; +}; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************** + */ + +/*For GTK Frame Filter*/ +#if DBG +#define FREE_IPV4_NETWORK_ADDR_LIST(_prAddrList) \ + { \ + UINT_32 u4Size = OFFSET_OF(IPV4_NETWORK_ADDRESS_LIST, arNetAddr) + \ + (((_prAddrList)->ucAddrCount) * sizeof(IPV4_NETWORK_ADDRESS)); \ + kalMemFree((_prAddrList), VIR_MEM_TYPE, u4Size); \ + (_prAddrList) = NULL; \ + } +#else +#define FREE_IPV4_NETWORK_ADDR_LIST(_prAddrList) \ + { \ + kalMemFree((_prAddrList), VIR_MEM_TYPE, 0); \ + (_prAddrList) = NULL; \ + } +#endif + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************** + */ + +VOID hs20GenerateInterworkingIE(IN P_ADAPTER_T prAdapter, OUT P_MSDU_INFO_T prMsduInfo); + +VOID hs20GenerateRoamingConsortiumIE(IN P_ADAPTER_T prAdapter, OUT P_MSDU_INFO_T prMsduInfo); + +VOID hs20GenerateHS20IE(IN P_ADAPTER_T prAdapter, OUT P_MSDU_INFO_T prMsduInfo); + +VOID hs20FillExtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo); + +VOID hs20FillProreqExtCapIE(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucIE); + +VOID hs20FillHS20IE(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucIE); + +UINT_32 hs20CalculateHS20RelatedIEForProbeReq(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucTargetBSSID); + +WLAN_STATUS hs20GenerateHS20RelatedIEForProbeReq(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucTargetBSSID, OUT PUINT_8 prIE); + +BOOLEAN hs20IsGratuitousArp(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prCurrSwRfb); + +BOOLEAN hs20IsUnsolicitedNeighborAdv(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prCurrSwRfb); + +#if CFG_ENABLE_GTK_FRAME_FILTER +BOOLEAN hs20IsForgedGTKFrame(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_SW_RFB_T prCurrSwRfb); +#endif + +BOOLEAN hs20IsUnsecuredFrame(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_SW_RFB_T prCurrSwRfb); + +BOOLEAN hs20IsFrameFilterEnabled(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo); + +WLAN_STATUS hs20SetBssidPool(IN P_ADAPTER_T prAdapter, IN PVOID pvBuffer, IN ENUM_KAL_NETWORK_TYPE_INDEX_T eNetTypeIdx); + +#endif /* CFG_SUPPORT_PASSPOINT */ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/mib.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/mib.h new file mode 100644 index 0000000000000..3b1b2c67f894b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/mib.h @@ -0,0 +1,174 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. + */ + + +#ifndef _MIB_H +#define _MIB_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************** + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************** + */ +/* Entry in SMT AuthenticationAlgorithms Table: dot11AuthenticationAlgorithmsEntry */ +typedef struct _DOT11_AUTHENTICATION_ALGORITHMS_ENTRY { + BOOLEAN dot11AuthenticationAlgorithmsEnable; /* dot11AuthenticationAlgorithmsEntry 3 */ +} DOT11_AUTHENTICATION_ALGORITHMS_ENTRY, *P_DOT11_AUTHENTICATION_ALGORITHMS_ENTRY; + +/* Entry in SMT dot11RSNAConfigPairwiseCiphersTalbe Table: dot11RSNAConfigPairwiseCiphersEntry */ +typedef struct _DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY { + UINT_32 dot11RSNAConfigPairwiseCipher; /* dot11RSNAConfigPairwiseCiphersEntry 2 */ + BOOLEAN dot11RSNAConfigPairwiseCipherEnabled; /* dot11RSNAConfigPairwiseCiphersEntry 3 */ +} DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY, *P_DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY; + +/* Entry in SMT dot11RSNAConfigAuthenticationSuitesTalbe Table: dot11RSNAConfigAuthenticationSuitesEntry */ +typedef struct _DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY { + UINT_32 dot11RSNAConfigAuthenticationSuite; /* dot11RSNAConfigAuthenticationSuitesEntry 2 */ + BOOLEAN dot11RSNAConfigAuthenticationSuiteEnabled; /* dot11RSNAConfigAuthenticationSuitesEntry 3 */ +} DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY, *P_DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY; + +/* ----- IEEE 802.11 MIB Major sections ----- */ +typedef struct _IEEE_802_11_MIB_T { + /* dot11PrivacyTable (dot11smt 5) */ + UINT_8 dot11WEPDefaultKeyID; /* dot11PrivacyEntry 2 */ + BOOLEAN dot11TranmitKeyAvailable; + UINT_32 dot11WEPICVErrorCount; /* dot11PrivacyEntry 5 */ + UINT_32 dot11WEPExcludedCount; /* dot11PrivacyEntry 6 */ + + /* dot11RSNAConfigTable (dot11smt 8) */ + UINT_32 dot11RSNAConfigGroupCipher; /* dot11RSNAConfigEntry 4 */ + + /* dot11RSNAConfigPairwiseCiphersTable (dot11smt 9) */ + DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY dot11RSNAConfigPairwiseCiphersTable[MAX_NUM_SUPPORTED_CIPHER_SUITES]; + + /* dot11RSNAConfigAuthenticationSuitesTable (dot11smt 10) */ + DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY + dot11RSNAConfigAuthenticationSuitesTable[MAX_NUM_SUPPORTED_AKM_SUITES]; + +#if 0 /* SUPPORT_WAPI */ + BOOLEAN fgWapiKeyInstalled; + PARAM_WPI_KEY_T rWapiPairwiseKey[2]; + BOOLEAN fgPairwiseKeyUsed[2]; + UINT_8 ucWpiActivedPWKey; /* Must be 0 or 1, by wapi spec */ + PARAM_WPI_KEY_T rWapiGroupKey[2]; + BOOLEAN fgGroupKeyUsed[2]; +#endif +} IEEE_802_11_MIB_T, *P_IEEE_802_11_MIB_T; + +/* ------------------ IEEE 802.11 non HT PHY characteristics ---------------- */ +typedef const struct _NON_HT_PHY_ATTRIBUTE_T { + UINT_16 u2SupportedRateSet; + + BOOLEAN fgIsShortPreambleOptionImplemented; + + BOOLEAN fgIsShortSlotTimeOptionImplemented; +} NON_HT_PHY_ATTRIBUTE_T, *P_NON_HT_PHY_ATTRIBUTE_T; + +typedef const struct _NON_HT_ADHOC_MODE_ATTRIBUTE_T { + ENUM_PHY_TYPE_INDEX_T ePhyTypeIndex; + + UINT_16 u2BSSBasicRateSet; +} NON_HT_ADHOC_MODE_ATTRIBUTE_T, *P_NON_HT_ADHOC_MODE_ATTRIBUTE_T; + +typedef NON_HT_ADHOC_MODE_ATTRIBUTE_T NON_HT_AP_MODE_ATTRIBUTE_T; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************** + */ +extern NON_HT_PHY_ATTRIBUTE_T rNonHTPhyAttributes[]; +extern NON_HT_ADHOC_MODE_ATTRIBUTE_T rNonHTAdHocModeAttributes[]; +extern NON_HT_AP_MODE_ATTRIBUTE_T rNonHTApModeAttributes[]; + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************** + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************** + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************** + */ + +#endif /* _MIB_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_assoc.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_assoc.h new file mode 100644 index 0000000000000..8b4bff3fd3812 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_assoc.h @@ -0,0 +1,103 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/*! \file p2p_assoc.h + * \brief This file contains the Wi-Fi Direct ASSOC REQ/RESP of + * IEEE 802.11 family for MediaTek 802.11 Wireless LAN Adapters. + */ + +#ifndef _P2P_ASSOC_H +#define _P2P_ASSOC_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************** + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************** + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************** + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************** + */ + +PUINT_8 p2pBuildReAssocReqFrameCommonIEs(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN PUINT_8 pucBuffer); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_bss.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_bss.h new file mode 100644 index 0000000000000..0c8a35b762db1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_bss.h @@ -0,0 +1,107 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/mgmt/p2p_bss.h#2 +*/ + +/*! \file "p2p_bss.h" +* \brief In this file we define the function prototype used in p2p BSS/IBSS. +* +* The file contains the function declarations and defines for used in BSS/IBSS. +*/ + +#ifndef _P2P_BSS_H +#define _P2P_BSS_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +UINT_32 p2pGetTxProbRspIeTableSize(VOID); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_dev.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_dev.h new file mode 100644 index 0000000000000..cab90dcc88159 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_dev.h @@ -0,0 +1,237 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +typedef enum _ENUM_P2P_DEV_STATE_T { + P2P_DEV_STATE_IDLE = 0, + P2P_DEV_STATE_SCAN, + P2P_DEV_STATE_REQING_CHANNEL, + P2P_DEV_STATE_CHNL_ON_HAND, + P2P_DEV_STATE_OFF_CHNL_TX, /* Requesting Channel to Send Specific Frame. */ + P2P_DEV_STATE_NUM +} ENUM_P2P_DEV_STATE_T, *P_ENUM_P2P_DEV_STATE_T; + +/*-------------------- EVENT MESSAGE ---------------------*/ +typedef struct _MSG_P2P_SCAN_REQUEST_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucBssIdx; + ENUM_SCAN_TYPE_T eScanType; + 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; + ENUM_CH_REQ_TYPE_T eChnlReqType; +} MSG_P2P_CHNL_REQUEST_T, *P_MSG_P2P_CHNL_REQUEST_T; + +typedef struct _MSG_P2P_MGMT_TX_REQUEST_T { + MSG_HDR_T rMsgHdr; + UINT_8 ucBssIdx; + P_MSDU_INFO_T prMgmtMsduInfo; + UINT_64 u8Cookie; /* For indication. */ + BOOLEAN fgNoneCckRate; + BOOLEAN fgIsOffChannel; + RF_CHANNEL_INFO_T rChannelInfo; /* Off channel TX. */ + ENUM_CHNL_EXT_T eChnlExt; + BOOLEAN fgIsWaitRsp; +} MSG_P2P_MGMT_TX_REQUEST_T, *P_MSG_P2P_MGMT_TX_REQUEST_T; + +#if CFG_SUPPORT_WFD + +#define WFD_FLAGS_DEV_INFO_VALID BIT(0) /* 1. WFD_DEV_INFO, 2. WFD_CTRL_PORT, 3. WFD_MAT_TP. */ +#define WFD_FLAGS_SINK_INFO_VALID BIT(1) /* 1. WFD_SINK_STATUS, 2. WFD_SINK_MAC. */ +#define WFD_FLAGS_ASSOC_MAC_VALID BIT(2) /* 1. WFD_ASSOC_MAC. */ +#define WFD_FLAGS_EXT_CAPABILITY_VALID BIT(3) /* 1. WFD_EXTEND_CAPABILITY. */ + +struct _WFD_CFG_SETTINGS_T { + UINT_32 u4WfdCmdType; + UINT_8 ucWfdEnable; + UINT_8 ucWfdCoupleSinkStatus; + UINT_8 ucWfdSessionAvailable; /* 0: NA 1:Set 2:Clear */ + UINT_8 ucWfdSigmaMode; + UINT_16 u2WfdDevInfo; + UINT_16 u2WfdControlPort; + UINT_16 u2WfdMaximumTp; + UINT_16 u2WfdExtendCap; + UINT_8 aucWfdCoupleSinkAddress[MAC_ADDR_LEN]; + UINT_8 aucWfdAssociatedBssid[MAC_ADDR_LEN]; + UINT_8 aucWfdVideoIp[4]; + UINT_8 aucWfdAudioIp[4]; + UINT_16 u2WfdVideoPort; + UINT_16 u2WfdAudioPort; + UINT_32 u4WfdFlag; + UINT_32 u4WfdPolicy; + UINT_32 u4WfdState; + UINT_8 aucWfdSessionInformationIE[24 * 8]; + UINT_16 u2WfdSessionInformationIELen; + UINT_8 aucReserved1[2]; + UINT_8 aucWfdPrimarySinkMac[MAC_ADDR_LEN]; + UINT_8 aucWfdSecondarySinkMac[MAC_ADDR_LEN]; + UINT_32 u4WfdAdvancedFlag; + /* Group 1 64 bytes */ + UINT_8 aucWfdLocalIp[4]; + UINT_16 u2WfdLifetimeAc2; /* Unit is 2 TU */ + UINT_16 u2WfdLifetimeAc3; /* Unit is 2 TU */ + UINT_16 u2WfdCounterThreshold; /* Unit is ms */ + UINT_8 aucReverved2[54]; + /* Group 2 64 bytes */ + UINT_8 aucReverved3[64]; + /* Group 3 64 bytes */ + UINT_8 aucReverved4[64]; +}; + +#endif + +typedef struct _MSG_P2P_ACTIVE_DEV_BSS_T { + MSG_HDR_T rMsgHdr; +} MSG_P2P_ACTIVE_DEV_BSS_T, *P_MSG_P2P_ACTIVE_DEV_BSS_T; + +/*-------------------- P2P FSM ACTION STRUCT ---------------------*/ + +typedef struct _P2P_OFF_CHNL_TX_REQ_INFO_T { + LINK_ENTRY_T rLinkEntry; + P_MSDU_INFO_T prMgmtTxMsdu; + BOOLEAN fgNoneCckRate; + RF_CHANNEL_INFO_T rChannelInfo; /* Off channel TX. */ + ENUM_CHNL_EXT_T eChnlExt; + BOOLEAN fgIsWaitRsp; /* See if driver should keep at the same channel. */ +} P2P_OFF_CHNL_TX_REQ_INFO_T, *P_P2P_OFF_CHNL_TX_REQ_INFO_T; + +typedef struct _P2P_MGMT_TX_REQ_INFO_T { + LINK_T rP2pTxReqLink; + P_MSDU_INFO_T prMgmtTxMsdu; + BOOLEAN fgIsWaitRsp; +} P2P_MGMT_TX_REQ_INFO_T, *P_P2P_MGMT_TX_REQ_INFO_T; + +struct _P2P_DEV_FSM_INFO_T { + UINT_8 ucBssIndex; + /* State related. */ + ENUM_P2P_DEV_STATE_T eCurrentState; + + /* Channel related. */ + P2P_CHNL_REQ_INFO_T rChnlReqInfo; + + /* Scan related. */ + P2P_SCAN_REQ_INFO_T rScanReqInfo; + + /* Mgmt tx related. */ + P2P_MGMT_TX_REQ_INFO_T rMgmtTxInfo; + + /* FSM Timer */ + TIMER_T rP2pFsmTimeoutTimer; + + /* Packet filter for P2P module. */ + UINT_32 u4P2pPacketFilter; +}; + +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 + +/*========================= Initial ============================*/ + +UINT_8 p2pDevFsmInit(IN P_ADAPTER_T prAdapter); + +VOID p2pDevFsmUninit(IN P_ADAPTER_T prAdapter); + +/*========================= FUNCTIONs ============================*/ + +VOID +p2pDevFsmStateTransition(IN P_ADAPTER_T prAdapter, IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo, IN ENUM_P2P_DEV_STATE_T + eNextState); + +VOID p2pDevFsmRunEventAbort(IN P_ADAPTER_T prAdapter, IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo); + +VOID p2pDevFsmRunEventTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); + +/*================ Message Event =================*/ +VOID p2pDevFsmRunEventScanRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID +p2pDevFsmRunEventScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr, IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo); + +VOID p2pDevFsmRunEventChannelRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pDevFsmRunEventChannelAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID +p2pDevFsmRunEventChnlGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr, IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo); + +VOID p2pDevFsmRunEventMgmtTx(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +WLAN_STATUS +p2pDevFsmRunEventMgmtFrameTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T + rTxDoneStatus); + +VOID p2pDevFsmRunEventMgmtFrameRegister(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +/* /////////////////////////////// */ + +VOID p2pDevFsmRunEventActiveDevBss(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_dev_state.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_dev_state.h new file mode 100644 index 0000000000000..2714907cb64d8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_dev_state.h @@ -0,0 +1,95 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#ifndef _P2P_DEV_STATE_H +#define _P2P_DEV_STATE_H + +BOOLEAN +p2pDevStateInit_IDLE(IN P_ADAPTER_T prAdapter, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, OUT P_ENUM_P2P_DEV_STATE_T peNextState); + +VOID p2pDevStateAbort_IDLE(IN P_ADAPTER_T prAdapter); + +BOOLEAN +p2pDevStateInit_REQING_CHANNEL(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucBssIdx, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, OUT P_ENUM_P2P_DEV_STATE_T peNextState); + +VOID +p2pDevStateAbort_REQING_CHANNEL(IN P_ADAPTER_T prAdapter, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, IN ENUM_P2P_DEV_STATE_T eNextState); + +VOID +p2pDevStateInit_CHNL_ON_HAND(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, + IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo); + +VOID +p2pDevStateAbort_CHNL_ON_HAND(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, + IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo); + +VOID p2pDevStateInit_SCAN(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo); + +VOID p2pDevStateAbort_SCAN(IN P_ADAPTER_T prAdapter, IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo); + +BOOLEAN +p2pDevStateInit_OFF_CHNL_TX(IN P_ADAPTER_T prAdapter, + IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, + IN P_P2P_MGMT_TX_REQ_INFO_T prP2pMgmtTxInfo, OUT P_ENUM_P2P_DEV_STATE_T peNextState); + +VOID +p2pDevStateAbort_OFF_CHNL_TX(IN P_ADAPTER_T prAdapter, + IN P_P2P_MGMT_TX_REQ_INFO_T prP2pMgmtTxInfo, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, IN ENUM_P2P_DEV_STATE_T eNextState); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_fsm.h new file mode 100644 index 0000000000000..206fd34438ffa --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_fsm.h @@ -0,0 +1,81 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. + */ + + +#ifndef _P2P_FSM_H +#define _P2P_FSM_H + +VOID p2pFsmRunEventScanRequest(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 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); + +#if CFG_SUPPORT_WFD +VOID p2pFsmRunEventWfdSettingUpdate(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); +#endif + +VOID p2pFsmRunEventScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + + +#endif /* _P2P_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_func.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_func.h new file mode 100644 index 0000000000000..1bc9b6cc5f06d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_func.h @@ -0,0 +1,312 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#ifndef _P2P_FUNC_H +#define _P2P_FUNC_H + +#define P2P_OFF_CHNL_TX_DEFAULT_TIME_MS 1000 + +#if (CFG_SUPPORT_DFS_MASTER == 1) +extern struct P2P_RADAR_INFO g_rP2pRadarInfo; + +enum _ENUM_DFS_STATE_T { + DFS_STATE_INACTIVE = 0, + DFS_STATE_CHECKING, + DFS_STATE_ACTIVE, + DFS_STATE_DETECTED, + DFS_STATE_NUM +}; +#endif + +/******************************************************************************* + * M A C R O S + ******************************************************************************** + */ +#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_SIZE(_fp) (P2P_ATTRI_HDR_LEN + WSC_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))) + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************** + */ + +VOID p2pFuncRequestScan(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo); + +VOID p2pFuncCancelScan(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo); + +VOID +p2pFuncUpdateBssInfoForJOIN(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc, IN P_STA_RECORD_T prStaRec, IN + P_BSS_INFO_T prP2pBssInfo, IN P_SW_RFB_T prAssocRspSwRfb); + +VOID p2pFuncAcquireCh(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo); + +VOID +p2pFuncDisconnect(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo, IN P_STA_RECORD_T prStaRec, IN BOOLEAN + fgSendDeauth, IN UINT_16 u2ReasonCode); + +P_BSS_INFO_T p2pFuncBSSIDFindBssInfo(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBSSID); + +/* //////////////////////////////// MT6630 CODE //////////////////////////////////// */ + +VOID p2pFuncGCJoin(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo, IN P_P2P_JOIN_INFO_T prP2pJoinInfo); + +VOID p2pFuncStopComplete(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo); + +VOID +p2pFuncStartGO(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_P2P_CONNECTION_REQ_INFO_T prP2pConnReqInfo, IN + P_P2P_CHNL_REQ_INFO_T prP2pChnlReqInfo); + +VOID p2pFuncStopGO(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo); + +WLAN_STATUS p2pFuncRoleToBssIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucRoleIdx, OUT PUINT_8 pucBssIdx); + +P_P2P_ROLE_FSM_INFO_T p2pFuncGetRoleByBssIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex); + +VOID +p2pFuncSwitchOPMode(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo, IN ENUM_OP_MODE_T eOpMode, IN BOOLEAN + fgSyncToFW); + +VOID p2pFuncReleaseCh(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo); + +#if (CFG_SUPPORT_DFS_MASTER == 1) +VOID p2pFuncStartRdd(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx); + +VOID p2pFuncStopRdd(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx); + +VOID p2pFuncDfsSwitchCh(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P2P_CHNL_REQ_INFO_T rP2pChnlReqInfo); + +BOOLEAN p2pFuncCheckWeatherRadarBand(IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo); + +INT_32 p2pFuncSetDriverCacTime(IN UINT_32 u4CacTime); + +VOID p2pFuncEnableManualCac(VOID); + +UINT_32 p2pFuncGetDriverCacTime(VOID); + +BOOLEAN p2pFuncIsManualCac(VOID); + +VOID p2pFuncRadarInfoInit(VOID); + +VOID p2pFuncShowRadarInfo(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx); + +VOID p2pFuncGetRadarInfo(IN struct P2P_RADAR_INFO *prP2pRadarInfo); + +PUINT_8 p2pFuncJpW53RadarType(VOID); + +PUINT_8 p2pFuncJpW56RadarType(VOID); + +VOID p2pFuncSetRadarDetectMode(IN UINT_8 ucRadarDetectMode); + +UINT_8 p2pFuncGetRadarDetectMode(VOID); + +VOID p2pFuncSetDfsState(IN UINT_8 ucDfsState); + +UINT_8 p2pFuncGetDfsState(VOID); + +PUINT_8 p2pFuncShowDfsState(VOID); + +VOID p2pFuncRecordCacStartBootTime(VOID); + +UINT_32 p2pFuncGetCacRemainingTime(VOID); +#endif + +VOID p2pFuncSetChannel(IN P_ADAPTER_T prAdapter, IN UINT_8 ucRoleIdx, 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); + +WLAN_STATUS +p2pFuncTxMgmtFrame(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN P_MSDU_INFO_T prMgmtTxMsdu, IN BOOLEAN + fgNonCckRate); + +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 +p2pFuncAssocRespUpdate(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo, IN PUINT_8 AssocRespIE, IN + UINT_32 u4AssocRespLen); + +BOOLEAN +p2pFuncValidateAuth(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, 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, IN BOOLEAN + fgIsApMode); + +BOOLEAN p2pFuncParseCheckForTKIPInfoElem(IN PUINT_8 pucBuf); + +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, IN BOOLEAN + fgIsDevInterface, IN UINT_8 ucRoleIdx); + +VOID p2pFuncValidateRxActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN BOOLEAN + fgIsDevInterface, IN UINT_8 ucRoleIdx); + +BOOLEAN p2pFuncIsAPMode(IN P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings); + +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_BSS_INFO_T prBssInfo, 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_P2P_JOIN_INFO_T prP2pJoinInfo, 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); + +P_MSDU_INFO_T p2pFuncProcessP2pProbeRsp(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, 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 UINT_8 ucBssIndex, 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 UINT_8 ucBssIndex, 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 UINT_8 ucBssIndex, 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 UINT_8 ucBssIndex, IN P_STA_RECORD_T prStaRec); + +VOID p2pFuncGenerateP2p_IEForAssocRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +UINT_32 +p2pFuncCalculateP2P_IELen(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, 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 UINT_8 ucBssIndex, 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 UINT_8 ucBssIndex, IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pFuncAppendAttriExtListenTiming(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, 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_8 ucAttriID); + +UINT_32 wfdFuncCalculateWfdIELenForAssocRsp(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN P_STA_RECORD_T prStaRec); + +VOID wfdFuncGenerateWfdIEForAssocRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +UINT_32 p2pFuncCalculateP2P_IE_NoA(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, IN P_STA_RECORD_T prStaRec); + +VOID p2pFuncGenerateP2P_IE_NoA(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_ie.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_ie.h new file mode 100644 index 0000000000000..45be52298e67e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_ie.h @@ -0,0 +1,100 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#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 + +/* == OFFSET_OF(IE_P2P_T,*/ +/*aucP2PAttributes[0]) */ +#define WFD_IE_OUI_HDR (ELEM_HDR_LEN + WFD_OUI_TYPE_LEN) + +/* 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 */ + +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; + +#endif + +UINT_32 p2pCalculate_IEForAssocReq(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN P_STA_RECORD_T prStaRec); + +VOID p2pGenerate_IEForAssocReq(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_rlm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_rlm.h new file mode 100644 index 0000000000000..1692fae91ea65 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_rlm.h @@ -0,0 +1,126 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/*! \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 + ******************************************************************************** + */ +#define CHANNEL_SPAN_20 20 + +/******************************************************************************* + * 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); + +ENUM_CHNL_EXT_T rlmGetScoForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); + +UINT_8 rlmGetVhtS1ForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); + + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_rlm_obss.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_rlm_obss.h new file mode 100644 index 0000000000000..9b7890642cfef --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_rlm_obss.h @@ -0,0 +1,113 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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 rlmHandleObssStatusEventPkt(P_ADAPTER_T prAdapter, P_EVENT_AP_OBSS_STATUS_T prObssStatus); + +UINT_8 rlmObssChnlLevel(P_BSS_INFO_T prBssInfo, ENUM_BAND_T eBand, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend); + +VOID rlmObssScanExemptionRsp(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_SW_RFB_T prSwRfb); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_role.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_role.h new file mode 100644 index 0000000000000..7fa3aaf6c2135 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_role.h @@ -0,0 +1,422 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#ifndef _P2P_ROLE_H +#define _P2P_ROLE_H + +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_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 _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; + +/* ////////////////////////////////// Message //////////////////////////////////////////////////// */ + +typedef struct _MSG_P2P_BEACON_UPDATE_T { + MSG_HDR_T rMsgHdr; + UINT_8 ucRoleIndex; + UINT_32 u4BcnHdrLen; + UINT_32 u4BcnBodyLen; + UINT_32 u4AssocRespLen; + PUINT_8 pucBcnHdr; + PUINT_8 pucBcnBody; + PUINT_8 pucAssocRespIE; + BOOLEAN fgIsWepCipher; + UINT_8 aucBuffer[1]; /* Header & Body & Extra IEs 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; + UINT_8 ucRoleIdx; +} 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_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 */ + UINT_8 ucRoleIdx; + P2P_SSID_STRUCT_T rSsid; + UINT_8 aucBssid[MAC_ADDR_LEN]; + UINT_8 aucSrcMacAddr[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 ucRoleIdx; + 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_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; + UINT_8 ucRoleIdx; + AP_CRYPTO_SETTINGS_T rEncryptionSettings; + INT_32 i4InactiveTimeout; +} MSG_P2P_START_AP_T, *P_MSG_P2P_START_AP_T; + +#if (CFG_SUPPORT_DFS_MASTER == 1) +typedef struct _MSG_P2P_DFS_CAC_T { + MSG_HDR_T rMsgHdr; + ENUM_CHANNEL_WIDTH_T eChannelWidth; + UINT_8 ucRoleIdx; +} MSG_P2P_DFS_CAC_T, *P_MSG_P2P_DFS_CAC_T; + +typedef struct _MSG_P2P_RADAR_DETECT_T { + MSG_HDR_T rMsgHdr; + UINT_8 ucBssIndex; +} MSG_P2P_RADAR_DETECT_T, *P_MSG_P2P_RADAR_DETECT_T; + +struct P2P_RADAR_INFO { + UINT_8 ucRadarReportMode; /*0: Only report radar detected; 1: Add parameter reports*/ + UINT_8 ucRddIdx; + UINT_8 ucLongDetected; + UINT_8 ucPeriodicDetected; + UINT_8 ucLPBNum; + UINT_8 ucPPBNum; + UINT_8 ucLPBPeriodValid; + UINT_8 ucLPBWidthValid; + UINT_8 ucPRICountM1; + UINT_8 ucPRICountM1TH; + UINT_8 ucPRICountM2; + UINT_8 ucPRICountM2TH; + UINT_32 u4PRI1stUs; + LONG_PULSE_BUFFER_T arLpbContent[32]; + PERIODIC_PULSE_BUFFER_T arPpbContent[32]; +}; + +typedef struct _MSG_P2P_SET_NEW_CHANNEL_T { + MSG_HDR_T rMsgHdr; + ENUM_CHANNEL_WIDTH_T eChannelWidth; + UINT_8 ucRoleIdx; + UINT_8 ucBssIndex; +} MSG_P2P_SET_NEW_CHANNEL_T, *P_MSG_P2P_SET_NEW_CHANNEL_T; + +typedef struct _MSG_P2P_CSA_DONE_T { + MSG_HDR_T rMsgHdr; + UINT_8 ucBssIndex; +} MSG_P2P_CSA_DONE_T, *P_MSG_P2P_CSA_DONE_T; +#endif + +typedef struct _MSG_P2P_DEL_IFACE_T { + MSG_HDR_T rMsgHdr; + UINT_8 ucRoleIdx; +} MSG_P2P_DEL_IFACE_T, *P_MSG_P2P_DEL_IFACE_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; + +/* 3 --------------- WFA P2P Attributes Handler prototype --------------- */ +typedef UINT_32(*PFN_APPEND_ATTRI_FUNC) (P_ADAPTER_T, UINT_8, BOOLEAN, PUINT_16, PUINT_8, UINT_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_P2P_ROLE_STATE_T { + P2P_ROLE_STATE_IDLE = 0, + P2P_ROLE_STATE_SCAN, + P2P_ROLE_STATE_REQING_CHANNEL, + P2P_ROLE_STATE_AP_CHNL_DETECTION, /* Requesting Channel to Send Specific Frame. */ + P2P_ROLE_STATE_GC_JOIN, +#if (CFG_SUPPORT_DFS_MASTER == 1) + P2P_ROLE_STATE_DFS_CAC, + P2P_ROLE_STATE_SWITCH_CHANNEL, +#endif + P2P_ROLE_STATE_NUM +} ENUM_P2P_ROLE_STATE_T, *P_ENUM_P2P_ROLE_STATE_T; + +typedef enum _ENUM_P2P_CONNECTION_TYPE_T { + P2P_CONNECTION_TYPE_IDLE = 0, + P2P_CONNECTION_TYPE_GO, + P2P_CONNECTION_TYPE_GC, + P2P_CONNECTION_TYPE_PURE_AP, + P2P_CONNECTION_TYPE_NUM +} ENUM_P2P_CONNECTION_TYPE_T, *P_ENUM_P2P_CONNECTION_TYPE_T; + +typedef struct _P2P_JOIN_INFO_T { + UINT_8 ucSeqNumOfReqMsg; + UINT_8 ucAvailableAuthTypes; + P_STA_RECORD_T prTargetStaRec; + P_BSS_DESC_T prTargetBssDesc; + BOOLEAN fgIsJoinComplete; + /* For ASSOC Rsp. */ + UINT_32 u4BufLength; + UINT_8 aucIEBuf[MAX_IE_LENGTH]; +} P2P_JOIN_INFO_T, *P_P2P_JOIN_INFO_T; + +/* For STA & AP mode. */ +typedef struct _P2P_CONNECTION_REQ_INFO_T { + ENUM_P2P_CONNECTION_TYPE_T eConnRequest; + P2P_SSID_STRUCT_T rSsidStruct; + UINT_8 aucBssid[MAC_ADDR_LEN]; + + /* AP preferred channel. */ + RF_CHANNEL_INFO_T rChannelInfo; + ENUM_CHNL_EXT_T eChnlExt; + + /* To record channel bandwidth from CFG80211 */ + ENUM_MAX_BANDWIDTH_SETTING eChnlBw; + + /* To record primary channel frequency (MHz) from CFG80211 */ + UINT_16 u2PriChnlFreq; + + /* To record Channel Center Frequency Segment 0 (MHz) from CFG80211 */ + UINT_32 u4CenterFreq1; + + /* To record Channel Center Frequency Segment 1 (MHz) from CFG80211 */ + UINT_32 u4CenterFreq2; + + /* For ASSOC Req. */ + UINT_32 u4BufLength; + UINT_8 aucIEBuf[MAX_IE_LENGTH]; +} P2P_CONNECTION_REQ_INFO_T, *P_P2P_CONNECTION_REQ_INFO_T; + +#define P2P_ROLE_INDEX_2_ROLE_FSM_INFO(_prAdapter, _RoleIndex) \ + ((_prAdapter)->rWifiVar.aprP2pRoleFsmInfo[_RoleIndex]) + +struct _P2P_ROLE_FSM_INFO_T { + UINT_8 ucRoleIndex; + + UINT_8 ucBssIndex; + + /* State related. */ + ENUM_P2P_ROLE_STATE_T eCurrentState; + + /* Channel related. */ + P2P_CHNL_REQ_INFO_T rChnlReqInfo; + + /* Scan related. */ + P2P_SCAN_REQ_INFO_T rScanReqInfo; + + /* FSM Timer */ + TIMER_T rP2pRoleFsmTimeoutTimer; + +#if (CFG_SUPPORT_DFS_MASTER == 1) + TIMER_T rDfsShutDownTimer; +#endif + + /* Packet filter for P2P module. */ + UINT_32 u4P2pPacketFilter; + + /* GC Join related. */ + P2P_JOIN_INFO_T rJoinInfo; + + /* Connection related. */ + P2P_CONNECTION_REQ_INFO_T rConnReqInfo; + + /* Beacon Information. */ + P2P_BEACON_UPDATE_INFO_T rBeaconUpdateInfo; +}; + +/*========================= Initial ============================*/ + +UINT_8 p2pRoleFsmInit(IN P_ADAPTER_T prAdapter, IN UINT_8 ucRoleIdx); + +VOID p2pRoleFsmUninit(IN P_ADAPTER_T prAdapter, IN UINT_8 ucRoleIdx); + +/*================== Message Event ==================*/ + +VOID p2pRoleFsmRunEventAbort(IN P_ADAPTER_T prAdapter, IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo); + +VOID p2pRoleFsmRunEventStartAP(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pRoleFsmRunEventDelIface(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pRoleFsmRunEventStopAP(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +#if (CFG_SUPPORT_DFS_MASTER == 1) +VOID p2pRoleFsmRunEventDfsCac(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pRoleFsmRunEventRadarDet(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pRoleFsmRunEventSetNewChannel(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pRoleFsmRunEventCsaDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pRoleFsmRunEventDfsShutDownTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); +#endif + +VOID p2pRoleFsmRunEventScanRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID +p2pRoleFsmRunEventScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr, IN P_P2P_ROLE_FSM_INFO_T + prP2pRoleFsmInfo); + +VOID p2pRoleFsmRunEventJoinComplete(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pRoleFsmRunEventTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); + +VOID p2pRoleFsmDeauthTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); + +VOID p2pRoleFsmRunEventBeaconTimeout(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo); + +VOID p2pRoleUpdateACLEntry(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx); + +BOOL p2pRoleProcessACLInspection(IN P_ADAPTER_T prAdapter, IN PUCHAR pMacAddr, IN UINT_8 ucBssIdx); + +WLAN_STATUS +p2pRoleFsmRunEventAAAComplete(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_BSS_INFO_T prP2pBssInfo); + +WLAN_STATUS +p2pRoleFsmRunEventAAASuccess(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_BSS_INFO_T prP2pBssInfo); + +VOID p2pRoleFsmRunEventAAATxFail(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_BSS_INFO_T prP2pBssInfo); + +VOID p2pRoleFsmRunEventConnectionRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pRoleFsmRunEventConnectionAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID +p2pRoleFsmRunEventChnlGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr, IN P_P2P_ROLE_FSM_INFO_T + prP2pRoleFsmInfo); + +WLAN_STATUS +p2pRoleFsmRunEventDeauthTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T + rTxDoneStatus); + +VOID p2pRoleFsmRunEventRxDeauthentication(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb); + +VOID p2pRoleFsmRunEventRxDisassociation(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb); + +/* //////////////////////// TO BE REFINE ///////////////////// */ +VOID p2pRoleFsmRunEventSwitchOPMode(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pRoleFsmRunEventBeaconUpdate(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pRoleFsmRunEventDissolve(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID +p2pProcessEvent_UpdateNOAParam(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, IN P_EVENT_UPDATE_NOA_PARAMS_T + prEventUpdateNoaParam); + +VOID +p2pProcessPreSuspendFlow(IN P_ADAPTER_T prAdapter); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_role_state.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_role_state.h new file mode 100644 index 0000000000000..a6fad853186c1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_role_state.h @@ -0,0 +1,129 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#ifndef _P2P_ROLE_STATE_H +#define _P2P_ROLE_STATE_H + +VOID +p2pRoleStateInit_IDLE(IN P_ADAPTER_T prAdapter, + IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo, IN P_BSS_INFO_T prP2pBssInfo); + +VOID +p2pRoleStateAbort_IDLE(IN P_ADAPTER_T prAdapter, + IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo, IN P_P2P_CHNL_REQ_INFO_T prP2pChnlReqInfo); + +VOID p2pRoleStateInit_SCAN(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo); + +VOID p2pRoleStateAbort_SCAN(IN P_ADAPTER_T prAdapter, IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo); + +VOID +p2pRoleStateInit_REQING_CHANNEL(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo); + +VOID +p2pRoleStateAbort_REQING_CHANNEL(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pRoleBssInfo, + IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo, IN ENUM_P2P_ROLE_STATE_T eNextState); + +VOID +p2pRoleStateInit_AP_CHNL_DETECTION(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucBssIndex, + IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo, + IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo); + +VOID +p2pRoleStateAbort_AP_CHNL_DETECTION(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucBssIndex, + IN P_P2P_CONNECTION_REQ_INFO_T prP2pConnReqInfo, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, + IN P_P2P_SCAN_REQ_INFO_T prP2pScanReqInfo, IN ENUM_P2P_ROLE_STATE_T eNextState); + +VOID +p2pRoleStateInit_GC_JOIN(IN P_ADAPTER_T prAdapter, + IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo); + +VOID +p2pRoleStateAbort_GC_JOIN(IN P_ADAPTER_T prAdapter, + IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo, + IN P_P2P_JOIN_INFO_T prJoinInfo, IN ENUM_P2P_ROLE_STATE_T eNextState); + +#if (CFG_SUPPORT_DFS_MASTER == 1) +VOID +p2pRoleStateInit_DFS_CAC(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo); + +VOID +p2pRoleStateAbort_DFS_CAC(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pRoleBssInfo, + IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo, IN ENUM_P2P_ROLE_STATE_T eNextState); + +VOID +p2pRoleStateInit_SWITCH_CHANNEL(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo); + +VOID +p2pRoleStateAbort_SWITCH_CHANNEL(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pRoleBssInfo, + IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo, IN ENUM_P2P_ROLE_STATE_T eNextState); + +VOID +p2pRoleStatePrepare_To_DFS_CAC_STATE(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, + IN ENUM_CHANNEL_WIDTH_T rChannelWidth, + IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo, + OUT P_P2P_CHNL_REQ_INFO_T prChnlReqInfo); + +#endif + +VOID +p2pRoleStatePrepare_To_REQING_CHANNEL_STATE(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, + IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo, + OUT P_P2P_CHNL_REQ_INFO_T prChnlReqInfo); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_scan.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_scan.h new file mode 100644 index 0000000000000..4f2d2ead43d02 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/p2p_scan.h @@ -0,0 +1,117 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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 + ******************************************************************************** + */ + +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_P2P_CONNECTION_REQ_INFO_T prConnReqInfo); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/privacy.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/privacy.h new file mode 100644 index 0000000000000..f70dbf6057c96 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/privacy.h @@ -0,0 +1,248 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: include/mgmt/privacy.h#1 +*/ + +/*! \file privacy.h + * \brief This file contains the function declaration for privacy.c. + */ + + +#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 WEP_128_LEN 16 +#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 CIPHER_SUITE_CCMP_W_CCX 9 +#define CIPHER_SUITE_GCMP 10 +#define CIPHER_SUITE_GCMP_128 11 +#define CIPHER_SUITE_GCMP_256 12 + +/* Todo:: Move to register */ +#if defined(MT6630) +#define WTBL_RESERVED_ENTRY 255 +#else +#define WTBL_RESERVED_ENTRY 255 +#endif +/* Todo:: By chip capability */ +/* Max wlan table size, the max+1 used for probe request,... mgmt frame */ +/*sending use basic rate and no security */ +#define WTBL_SIZE 32 + +#define WTBL_ALLOC_FAIL WTBL_RESERVED_ENTRY +#define WTBL_DEFAULT_ENTRY 0 + +/******************************************************************************* + * 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 ucBssIndex); + +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); + +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); + +UINT_8 secGetBmcWlanIndex(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_T eNetType, IN P_STA_RECORD_T prStaRec); + +BOOLEAN secTransmitKeyExist(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +BOOLEAN secEnabledInAis(IN P_ADAPTER_T prAdapter); + +BOOL secPrivacySeekForEntry(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +VOID secPrivacyFreeForEntry(IN P_ADAPTER_T prAdapter, IN UINT_8 ucEntry); + +VOID secPrivacyFreeSta(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +VOID secRemoveBssBcEntry(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN BOOL fgRoam); + +UINT_8 +secPrivacySeekForBcEntry(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucBssIndex, + IN PUINT_8 pucAddr, IN UINT_8 ucStaIdx, IN UINT_8 ucAlg, IN UINT_8 ucKeyId); + +UINT_8 secGetStaIdxByWlanIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucWlanIdx); + +UINT_8 secGetBssIdxByWlanIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucWlanIdx); + +UINT_8 secLookupStaRecIndexFromTA(P_ADAPTER_T prAdapter, PUINT_8 pucMacAddress); + +void secPrivacyDumpWTBL(IN P_ADAPTER_T prAdapter); + +BOOLEAN secCheckWTBLAssign(IN P_ADAPTER_T prAdapter); + +BOOLEAN secIsProtected1xFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +BOOLEAN secIsProtectedBss(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo); + +BOOLEAN tkipMicDecapsulate(IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucMicKey); + +BOOLEAN tkipMicDecapsulateInRxHdrTransMode(IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucMicKey); + +void secPostUpdateAddr(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************** + */ + +#endif /* _PRIVACY_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rate.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rate.h new file mode 100644 index 0000000000000..41f91578b174b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rate.h @@ -0,0 +1,125 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. + */ + + +#ifndef _RATE_H +#define _RATE_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************** + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************** + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************** + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************** + */ +/*----------------------------------------------------------------------------*/ +/* Routines in rate.c */ +/*----------------------------------------------------------------------------*/ +VOID +rateGetRateSetFromIEs(IN P_IE_SUPPORTED_RATE_T prIeSupportedRate, IN P_IE_EXT_SUPPORTED_RATE_T prIeExtSupportedRate, OUT + PUINT_16 pu2OperationalRateSet, OUT PUINT_16 pu2BSSBasicRateSet, + OUT PBOOLEAN pfgIsUnknownBSSBasicRate); + +VOID +rateGetDataRatesFromRateSet(IN UINT_16 u2OperationalRateSet, IN UINT_16 u2BSSBasicRateSet, OUT PUINT_8 pucDataRates, OUT + PUINT_8 pucDataRatesLen); + +BOOLEAN rateGetHighestRateIndexFromRateSet(IN UINT_16 u2RateSet, OUT PUINT_8 pucHighestRateIndex); + +BOOLEAN rateGetLowestRateIndexFromRateSet(IN UINT_16 u2RateSet, OUT PUINT_8 pucLowestRateIndex); + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************** + */ + +#endif /* _RATE_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rlm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rlm.h new file mode 100644 index 0000000000000..94acaf09cc454 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rlm.h @@ -0,0 +1,423 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rlm.h#2 +*/ + +/*! \file "rlm.h" +* \brief +*/ + + +#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 +******************************************************************************** +*/ + +extern BOOLEAN g_bIcapEnable; +extern BOOLEAN g_bCaptureDone; +extern UINT_16 g_u2DumpIndex; +#if CFG_SUPPORT_QA_TOOL +extern UINT_32 g_au4Offset[2][2]; +extern UINT_32 g_au4IQData[256]; +#endif + +/******************************************************************************* +* 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 | HT_CAP_INFO_DSSS_CCK_IN_40M | HT_CAP_INFO_SM_POWER_SAVE) + +#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 + +#if CFG_SUPPORT_BFEE +#define TX_BEAMFORMING_CAP_BFEE \ + (TXBF_RX_NDP_CAPABLE | \ + TXBF_EXPLICIT_COMPRESSED_FEEDBACK_IMMEDIATE_CAPABLE | \ + TXBF_MINIMAL_GROUPING_1_2_3_CAPABLE | \ + TXBF_COMPRESSED_TX_ANTENNANUM_4_SUPPORTED | \ + TXBF_CHANNEL_ESTIMATION_4STS_CAPABILITY) +#else +#define TX_BEAMFORMING_CAP_BFEE 0 +#endif + +#if CFG_SUPPORT_BFER +#define TX_BEAMFORMING_CAP_BFER \ + (TXBF_TX_NDP_CAPABLE | \ + TXBF_EXPLICIT_COMPRESSED_TX_CAPAB) +#else +#define TX_BEAMFORMING_CAP_BFER 0 +#endif + +#define ASEL_CAP_DEFAULT_VAL 0 + +/* Define bandwidth from user setting */ +#define CONFIG_BW_20_40M 0 +#define CONFIG_BW_20M 1 /* 20MHz only */ + +#if CFG_SUPPORT_BFER +#define MODE_LEGACY 0 +#define MODE_HT 1 +#define MODE_VHT 2 +#endif + +#if CFG_SUPPORT_802_11AC +#if CFG_SUPPORT_BFEE +#define FIELD_VHT_CAP_INFO_BFEE \ + (VHT_CAP_INFO_SU_BEAMFORMEE_CAPABLE) +#define VHT_CAP_INFO_BEAMFORMEE_STS_CAP_MAX 3 +#else +#define FIELD_VHT_CAP_INFO_BFEE 0 +#endif + +#if CFG_SUPPORT_BFER + #define FIELD_VHT_CAP_INFO_BFER \ + (VHT_CAP_INFO_SU_BEAMFORMER_CAPABLE| \ + VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS_2_SUPPORTED) +#else +#define FIELD_VHT_CAP_INFO_BFER 0 +#endif + +#define VHT_CAP_INFO_DEFAULT_VAL \ + (VHT_CAP_INFO_MAX_MPDU_LEN_3K | \ + (AMPDU_PARAM_MAX_AMPDU_LEN_1024K << VHT_CAP_INFO_MAX_AMPDU_LENGTH_OFFSET)) + +#define VHT_CAP_INFO_DEFAULT_HIGHEST_DATA_RATE 0 +#endif +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +typedef struct _RLM_CAL_RESULT_ALL_V2_T { + /* Used for checking the Cal Data is damaged */ + UINT_32 u4MagicNum1; + + /* Thermal Value when do these Calibration */ + UINT_32 u4ThermalInfo; + + /* Total Rom Data Length Backup in Host Side */ + UINT_32 u4ValidRomCalDataLength; + + /* Total Ram Data Length Backup in Host Side */ + UINT_32 u4ValidRamCalDataLength; + + /* All Rom Cal Data Dumpped by FW */ + UINT_32 au4RomCalData[10000]; + + /* All Ram Cal Data Dumpped by FW */ + UINT_32 au4RamCalData[10000]; + + /* Used for checking the Cal Data is damaged */ + UINT_32 u4MagicNum2; +} RLM_CAL_RESULT_ALL_V2_T, *P_RLM_CAL_RESULT_ALL_V2_T; +extern RLM_CAL_RESULT_ALL_V2_T g_rBackupCalDataAllV2; +#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 +******************************************************************************** +*/ + +/* 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 || \ + IS_BSS_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) + +#if CFG_SUPPORT_802_11AC +#define RLM_NET_IS_11AC(_prBssInfo) \ + ((_prBssInfo)->ucPhyTypeSet & PHY_TYPE_SET_802_11AC) +#endif + +/* 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 rlmReqGeneratePowerCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + +VOID rlmReqGenerateSupportedChIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + + +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 rlmGenerateMTKOuiIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + +BOOLEAN rlmParseCheckMTKOuiIE(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuf, IN PUINT_32 pu4Cap); + +VOID rlmGenerateCsaIE(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 rlmProcessHtAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); + +#if CFG_SUPPORT_802_11AC +VOID rlmProcessVhtAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); +#endif + +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); + +#if CFG_SUPPORT_TDLS +UINT_32 +rlmFillHtCapIEByParams(BOOLEAN fg40mAllowed, + BOOLEAN fgShortGIDisabled, + UINT_8 u8SupportRxSgi20, + UINT_8 u8SupportRxSgi40, UINT_8 u8SupportRxGf, ENUM_OP_MODE_T eCurrentOPMode, UINT_8 *pOutBuf); + +UINT_32 rlmFillHtCapIEByAdapter(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, UINT_8 *pOutBuf); + +UINT_32 rlmFillVhtCapIEByAdapter(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, UINT_8 *pOutBuf); + +#endif + +#if CFG_SUPPORT_802_11AC +VOID rlmReqGenerateVhtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + +VOID rlmRspGenerateVhtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + +VOID rlmRspGenerateVhtOpIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + +VOID rlmFillVhtOpIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo); + +VOID rlmRspGenerateVhtOpNotificationIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); +VOID rlmReqGenerateVhtOpNotificationIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + + + + +#endif + +#if CFG_SUPPORT_DFS +VOID rlmProcessSpecMgtAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); +#endif + +VOID +rlmSendOpModeNotificationFrame(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, UINT_8 ucChannelWidth, UINT_8 ucNss); + +VOID +rlmSendSmPowerSaveFrame(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, UINT_8 ucNss); + +VOID +rlmChangeVhtOpBwPara(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex, UINT_8 ucChannelWidth); + +BOOLEAN +rlmChangeOperationMode(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex, UINT_8 ucChannelWidth, UINT_8 ucNss); + +#if CFG_SUPPORT_BFER +VOID +rlmBfStaRecPfmuUpdate(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec); + +VOID +rlmETxBfTriggerPeriodicSounding(P_ADAPTER_T prAdapter); + +BOOLEAN +rlmClientSupportsVhtETxBF(P_STA_RECORD_T prStaRec); + +UINT_8 +rlmClientSupportsVhtBfeeStsCap(P_STA_RECORD_T prStaRec); + +BOOLEAN +rlmClientSupportsHtETxBF(P_STA_RECORD_T prStaRec); +#endif + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +WLAN_STATUS rlmCalBackup( + P_ADAPTER_T prAdapter, + UINT_8 ucReason, + UINT_8 ucAction, + UINT_8 ucRomRam + ); + +WLAN_STATUS rlmTriggerCalBackup( + P_ADAPTER_T prAdapter, + BOOLEAN fgIsCalDataBackuped + ); +#endif + +VOID rlmModifyVhtBwPara(PUINT_8 pucVhtChannelFrequencyS1, PUINT_8 pucVhtChannelFrequencyS2, PUINT_8 pucVhtChannelWidth); + +VOID rlmReviseMaxBw( + P_ADAPTER_T prAdapter, + UINT_8 ucBssIndex, + P_ENUM_CHNL_EXT_T peExtend, + P_ENUM_CHANNEL_WIDTH_P peChannelWidth, + PUINT_8 pucS1, + PUINT_8 pucPrimaryCh); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#ifndef _lint +static __KAL_INLINE__ VOID rlmDataTypeCheck(VOID) +{ +} +#endif /* _lint */ + +#endif /* _RLM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rlm_domain.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rlm_domain.h new file mode 100644 index 0000000000000..0d356eacf009f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rlm_domain.h @@ -0,0 +1,770 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rlm_domain.h#1 +*/ + +/*! \file "rlm_domain.h" +* \brief +*/ + + +#ifndef _RLM_DOMAIN_H +#define _RLM_DOMAIN_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define MAX_SUBBAND_NUM 6 +#define MAX_SUBBAND_NUM_5G 8 + +#define COUNTRY_CODE_NULL ((UINT_16)0x0) + +/* ISO/IEC 3166-1 two-character country codes */ + +#define COUNTRY_CODE_AD (((UINT_16) 'A' << 8) | (UINT_16) 'D') /* Andorra */ +#define COUNTRY_CODE_AE (((UINT_16) 'A' << 8) | (UINT_16) 'E') /* UAE */ +#define COUNTRY_CODE_AF (((UINT_16) 'A' << 8) | (UINT_16) 'F') /* Afghanistan */ +#define COUNTRY_CODE_AG (((UINT_16) 'A' << 8) | (UINT_16) 'G') /* Antigua & Barbuda */ +#define COUNTRY_CODE_AI (((UINT_16) 'A' << 8) | (UINT_16) 'I') /* Anguilla */ +#define COUNTRY_CODE_AL (((UINT_16) 'A' << 8) | (UINT_16) 'L') /* Albania */ +#define COUNTRY_CODE_AM (((UINT_16) 'A' << 8) | (UINT_16) 'M') /* Armenia */ +#define COUNTRY_CODE_AN (((UINT_16) 'A' << 8) | (UINT_16) 'N') /* Netherlands Antilles */ +#define COUNTRY_CODE_AO (((UINT_16) 'A' << 8) | (UINT_16) 'O') /* Angola */ +#define COUNTRY_CODE_AR (((UINT_16) 'A' << 8) | (UINT_16) 'R') /* Argentina */ +#define COUNTRY_CODE_AS (((UINT_16) 'A' << 8) | (UINT_16) 'S') /* American Samoa (USA) */ +#define COUNTRY_CODE_AT (((UINT_16) 'A' << 8) | (UINT_16) 'T') /* Austria */ +#define COUNTRY_CODE_AU (((UINT_16) 'A' << 8) | (UINT_16) 'U') /* Australia */ +#define COUNTRY_CODE_AW (((UINT_16) 'A' << 8) | (UINT_16) 'W') /* Aruba */ +#define COUNTRY_CODE_AZ (((UINT_16) 'A' << 8) | (UINT_16) 'Z') /* Azerbaijan */ +#define COUNTRY_CODE_BA (((UINT_16) 'B' << 8) | (UINT_16) 'A') /* Bosnia and Herzegovina */ +#define COUNTRY_CODE_BB (((UINT_16) 'B' << 8) | (UINT_16) 'B') /* Barbados */ +#define COUNTRY_CODE_BD (((UINT_16) 'B' << 8) | (UINT_16) 'D') /* Bangladesh */ +#define COUNTRY_CODE_BE (((UINT_16) 'B' << 8) | (UINT_16) 'E') /* Belgium */ +#define COUNTRY_CODE_BF (((UINT_16) 'B' << 8) | (UINT_16) 'F') /* Burkina Faso */ +#define COUNTRY_CODE_BG (((UINT_16) 'B' << 8) | (UINT_16) 'G') /* Bulgaria */ +#define COUNTRY_CODE_BH (((UINT_16) 'B' << 8) | (UINT_16) 'H') /* Bahrain */ +#define COUNTRY_CODE_BI (((UINT_16) 'B' << 8) | (UINT_16) 'I') /* Burundi */ +#define COUNTRY_CODE_BJ (((UINT_16) 'B' << 8) | (UINT_16) 'J') /* Benin */ +#define COUNTRY_CODE_BM (((UINT_16) 'B' << 8) | (UINT_16) 'M') /* Bermuda */ +#define COUNTRY_CODE_BN (((UINT_16) 'B' << 8) | (UINT_16) 'N') /* Brunei */ +#define COUNTRY_CODE_BO (((UINT_16) 'B' << 8) | (UINT_16) 'O') /* Bolivia */ +#define COUNTRY_CODE_BR (((UINT_16) 'B' << 8) | (UINT_16) 'R') /* Brazil */ +#define COUNTRY_CODE_BS (((UINT_16) 'B' << 8) | (UINT_16) 'S') /* Bahamas */ +#define COUNTRY_CODE_BT (((UINT_16) 'B' << 8) | (UINT_16) 'T') /* Bhutan */ +#define COUNTRY_CODE_BW (((UINT_16) 'B' << 8) | (UINT_16) 'W') /* Botswana */ +#define COUNTRY_CODE_BY (((UINT_16) 'B' << 8) | (UINT_16) 'Y') /* Belarus */ +#define COUNTRY_CODE_BZ (((UINT_16) 'B' << 8) | (UINT_16) 'Z') /* Belize */ +#define COUNTRY_CODE_CA (((UINT_16) 'C' << 8) | (UINT_16) 'A') /* Canada */ +#define COUNTRY_CODE_CD (((UINT_16) 'C' << 8) | (UINT_16) 'D') /* Congo. Democratic Republic of the */ +#define COUNTRY_CODE_CF (((UINT_16) 'C' << 8) | (UINT_16) 'F') /* Central African Republic */ +#define COUNTRY_CODE_CG (((UINT_16) 'C' << 8) | (UINT_16) 'G') /* Congo. Republic of the */ +#define COUNTRY_CODE_CH (((UINT_16) 'C' << 8) | (UINT_16) 'H') /* Switzerland */ +#define COUNTRY_CODE_CI (((UINT_16) 'C' << 8) | (UINT_16) 'I') /* Cote d'lvoire */ +#define COUNTRY_CODE_CK (((UINT_16) 'C' << 8) | (UINT_16) 'K') /* Cook Island */ +#define COUNTRY_CODE_CL (((UINT_16) 'C' << 8) | (UINT_16) 'L') /* Chile */ +#define COUNTRY_CODE_CM (((UINT_16) 'C' << 8) | (UINT_16) 'M') /* Cameroon */ +#define COUNTRY_CODE_CN (((UINT_16) 'C' << 8) | (UINT_16) 'N') /* China */ +#define COUNTRY_CODE_CO (((UINT_16) 'C' << 8) | (UINT_16) 'O') /* Columbia */ +#define COUNTRY_CODE_CR (((UINT_16) 'C' << 8) | (UINT_16) 'R') /* Costa Rica */ +#define COUNTRY_CODE_CU (((UINT_16) 'C' << 8) | (UINT_16) 'U') /* Cuba */ +#define COUNTRY_CODE_CV (((UINT_16) 'C' << 8) | (UINT_16) 'V') /* Cape Verde */ +#define COUNTRY_CODE_CX (((UINT_16) 'C' << 8) | (UINT_16) 'X') /* "Christmas Island(Australia) */ +#define COUNTRY_CODE_CY (((UINT_16) 'C' << 8) | (UINT_16) 'Y') /* Cyprus */ +#define COUNTRY_CODE_CZ (((UINT_16) 'C' << 8) | (UINT_16) 'Z') /* Czech */ +#define COUNTRY_CODE_DE (((UINT_16) 'D' << 8) | (UINT_16) 'E') /* Germany */ +#define COUNTRY_CODE_DJ (((UINT_16) 'D' << 8) | (UINT_16) 'J') /* Djibouti */ +#define COUNTRY_CODE_DK (((UINT_16) 'D' << 8) | (UINT_16) 'K') /* Denmark */ +#define COUNTRY_CODE_DM (((UINT_16) 'D' << 8) | (UINT_16) 'M') /* Dominica */ +#define COUNTRY_CODE_DO (((UINT_16) 'D' << 8) | (UINT_16) 'O') /* Dominican Republic */ +#define COUNTRY_CODE_DZ (((UINT_16) 'D' << 8) | (UINT_16) 'Z') /* Algeria */ +#define COUNTRY_CODE_EC (((UINT_16) 'E' << 8) | (UINT_16) 'C') /* Ecuador */ +#define COUNTRY_CODE_EE (((UINT_16) 'E' << 8) | (UINT_16) 'E') /* Estonia */ +#define COUNTRY_CODE_EG (((UINT_16) 'E' << 8) | (UINT_16) 'G') /* Egypt */ +#define COUNTRY_CODE_EH (((UINT_16) 'E' << 8) | (UINT_16) 'H') /* Western Sahara (Morocco) */ +#define COUNTRY_CODE_ER (((UINT_16) 'E' << 8) | (UINT_16) 'R') /* Eritrea */ +#define COUNTRY_CODE_ES (((UINT_16) 'E' << 8) | (UINT_16) 'S') /* Spain */ +#define COUNTRY_CODE_ET (((UINT_16) 'E' << 8) | (UINT_16) 'T') /* Ethiopia */ +#define COUNTRY_CODE_EU (((UINT_16) 'E' << 8) | (UINT_16) 'U') /* Europe */ +#define COUNTRY_CODE_FI (((UINT_16) 'F' << 8) | (UINT_16) 'I') /* Finland */ +#define COUNTRY_CODE_FJ (((UINT_16) 'F' << 8) | (UINT_16) 'J') /* Fiji */ +#define COUNTRY_CODE_FK (((UINT_16) 'F' << 8) | (UINT_16) 'K') /* Falkland Island */ +#define COUNTRY_CODE_FM (((UINT_16) 'F' << 8) | (UINT_16) 'M') /* Micronesia */ +#define COUNTRY_CODE_FO (((UINT_16) 'F' << 8) | (UINT_16) 'O') /* Faroe Island */ +#define COUNTRY_CODE_FR (((UINT_16) 'F' << 8) | (UINT_16) 'R') /* France */ +#define COUNTRY_CODE_FR (((UINT_16) 'F' << 8) | (UINT_16) 'R') /* Wallis and Futuna (France) */ +#define COUNTRY_CODE_GA (((UINT_16) 'G' << 8) | (UINT_16) 'A') /* Gabon */ +#define COUNTRY_CODE_GB (((UINT_16) 'G' << 8) | (UINT_16) 'B') /* United Kingdom */ +#define COUNTRY_CODE_GD (((UINT_16) 'G' << 8) | (UINT_16) 'D') /* Grenada */ +#define COUNTRY_CODE_GE (((UINT_16) 'G' << 8) | (UINT_16) 'E') /* Georgia */ +#define COUNTRY_CODE_GF (((UINT_16) 'G' << 8) | (UINT_16) 'F') /* French Guiana */ +#define COUNTRY_CODE_GG (((UINT_16) 'G' << 8) | (UINT_16) 'G') /* Guernsey */ +#define COUNTRY_CODE_GH (((UINT_16) 'G' << 8) | (UINT_16) 'H') /* Ghana */ +#define COUNTRY_CODE_GI (((UINT_16) 'G' << 8) | (UINT_16) 'I') /* Gibraltar */ +#define COUNTRY_CODE_GM (((UINT_16) 'G' << 8) | (UINT_16) 'M') /* Gambia */ +#define COUNTRY_CODE_GN (((UINT_16) 'G' << 8) | (UINT_16) 'N') /* Guinea */ +#define COUNTRY_CODE_GP (((UINT_16) 'G' << 8) | (UINT_16) 'P') /* Guadeloupe */ +#define COUNTRY_CODE_GQ (((UINT_16) 'G' << 8) | (UINT_16) 'Q') /* Equatorial Guinea */ +#define COUNTRY_CODE_GR (((UINT_16) 'G' << 8) | (UINT_16) 'R') /* Greece */ +#define COUNTRY_CODE_GT (((UINT_16) 'G' << 8) | (UINT_16) 'T') /* Guatemala */ +#define COUNTRY_CODE_GU (((UINT_16) 'G' << 8) | (UINT_16) 'U') /* Guam */ +#define COUNTRY_CODE_GW (((UINT_16) 'G' << 8) | (UINT_16) 'W') /* Guinea-Bissau */ +#define COUNTRY_CODE_GY (((UINT_16) 'G' << 8) | (UINT_16) 'Y') /* Guyana */ +#define COUNTRY_CODE_HK (((UINT_16) 'H' << 8) | (UINT_16) 'K') /* Hong Kong */ +#define COUNTRY_CODE_HN (((UINT_16) 'H' << 8) | (UINT_16) 'N') /* Honduras */ +#define COUNTRY_CODE_HR (((UINT_16) 'H' << 8) | (UINT_16) 'R') /* Croatia */ +#define COUNTRY_CODE_HT (((UINT_16) 'H' << 8) | (UINT_16) 'T') /* Haiti */ +#define COUNTRY_CODE_HU (((UINT_16) 'H' << 8) | (UINT_16) 'U') /* Hungary */ +#define COUNTRY_CODE_ID (((UINT_16) 'I' << 8) | (UINT_16) 'D') /* Indonesia */ +#define COUNTRY_CODE_IE (((UINT_16) 'I' << 8) | (UINT_16) 'E') /* Ireland */ +#define COUNTRY_CODE_IL (((UINT_16) 'I' << 8) | (UINT_16) 'L') /* Israel */ +#define COUNTRY_CODE_IM (((UINT_16) 'I' << 8) | (UINT_16) 'M') /* Isle of Man */ +#define COUNTRY_CODE_IN (((UINT_16) 'I' << 8) | (UINT_16) 'N') /* India */ +#define COUNTRY_CODE_IQ (((UINT_16) 'I' << 8) | (UINT_16) 'Q') /* Iraq */ +#define COUNTRY_CODE_IR (((UINT_16) 'I' << 8) | (UINT_16) 'R') /* Iran */ +#define COUNTRY_CODE_IS (((UINT_16) 'I' << 8) | (UINT_16) 'S') /* Iceland */ +#define COUNTRY_CODE_IT (((UINT_16) 'I' << 8) | (UINT_16) 'T') /* Italy */ +#define COUNTRY_CODE_JE (((UINT_16) 'J' << 8) | (UINT_16) 'E') /* Jersey */ +#define COUNTRY_CODE_JM (((UINT_16) 'J' << 8) | (UINT_16) 'M') /* Jameica */ +#define COUNTRY_CODE_JO (((UINT_16) 'J' << 8) | (UINT_16) 'O') /* Jordan */ +#define COUNTRY_CODE_JP (((UINT_16) 'J' << 8) | (UINT_16) 'P') /* Japan */ +#define COUNTRY_CODE_KE (((UINT_16) 'K' << 8) | (UINT_16) 'E') /* Kenya */ +#define COUNTRY_CODE_KG (((UINT_16) 'K' << 8) | (UINT_16) 'G') /* Kyrgyzstan */ +#define COUNTRY_CODE_KH (((UINT_16) 'K' << 8) | (UINT_16) 'H') /* Cambodia */ +#define COUNTRY_CODE_KI (((UINT_16) 'K' << 8) | (UINT_16) 'I') /* Kiribati */ +#define COUNTRY_CODE_KM (((UINT_16) 'K' << 8) | (UINT_16) 'M') /* Comoros */ +#define COUNTRY_CODE_KN (((UINT_16) 'K' << 8) | (UINT_16) 'N') /* Saint Kitts and Nevis */ +#define COUNTRY_CODE_KP (((UINT_16) 'K' << 8) | (UINT_16) 'P') /* North Korea */ +#define COUNTRY_CODE_KR (((UINT_16) 'K' << 8) | (UINT_16) 'R') /* South Korea */ +#define COUNTRY_CODE_KW (((UINT_16) 'K' << 8) | (UINT_16) 'W') /* Kuwait */ +#define COUNTRY_CODE_KY (((UINT_16) 'K' << 8) | (UINT_16) 'Y') /* Cayman Islands */ +#define COUNTRY_CODE_KZ (((UINT_16) 'K' << 8) | (UINT_16) 'Z') /* Kazakhstan */ +#define COUNTRY_CODE_LA (((UINT_16) 'L' << 8) | (UINT_16) 'A') /* Laos */ +#define COUNTRY_CODE_LB (((UINT_16) 'L' << 8) | (UINT_16) 'B') /* Lebanon */ +#define COUNTRY_CODE_LC (((UINT_16) 'L' << 8) | (UINT_16) 'C') /* Saint Lucia */ +#define COUNTRY_CODE_LI (((UINT_16) 'L' << 8) | (UINT_16) 'I') /* Liechtenstein */ +#define COUNTRY_CODE_LK (((UINT_16) 'L' << 8) | (UINT_16) 'K') /* Sri Lanka */ +#define COUNTRY_CODE_LR (((UINT_16) 'L' << 8) | (UINT_16) 'R') /* Liberia */ +#define COUNTRY_CODE_LS (((UINT_16) 'L' << 8) | (UINT_16) 'S') /* Lesotho */ +#define COUNTRY_CODE_LT (((UINT_16) 'L' << 8) | (UINT_16) 'T') /* Lithuania */ +#define COUNTRY_CODE_LU (((UINT_16) 'L' << 8) | (UINT_16) 'U') /* Luxemburg */ +#define COUNTRY_CODE_LV (((UINT_16) 'L' << 8) | (UINT_16) 'V') /* Latvia */ +#define COUNTRY_CODE_LY (((UINT_16) 'L' << 8) | (UINT_16) 'Y') /* Libya */ +#define COUNTRY_CODE_MA (((UINT_16) 'M' << 8) | (UINT_16) 'A') /* Morocco */ +#define COUNTRY_CODE_MC (((UINT_16) 'M' << 8) | (UINT_16) 'C') /* Monaco */ +#define COUNTRY_CODE_MD (((UINT_16) 'M' << 8) | (UINT_16) 'D') /* Moldova */ +#define COUNTRY_CODE_ME (((UINT_16) 'M' << 8) | (UINT_16) 'E') /* Montenegro */ +#define COUNTRY_CODE_MF (((UINT_16) 'M' << 8) | (UINT_16) 'F') /* Saint Martin / Sint Marteen */ + /*(Added on window's list) */ +#define COUNTRY_CODE_MG (((UINT_16) 'M' << 8) | (UINT_16) 'G') /* Madagascar */ +#define COUNTRY_CODE_MH (((UINT_16) 'M' << 8) | (UINT_16) 'H') /* Marshall Islands */ +#define COUNTRY_CODE_MK (((UINT_16) 'M' << 8) | (UINT_16) 'K') /* Macedonia */ +#define COUNTRY_CODE_ML (((UINT_16) 'M' << 8) | (UINT_16) 'L') /* Mali */ +#define COUNTRY_CODE_MM (((UINT_16) 'M' << 8) | (UINT_16) 'M') /* Myanmar */ +#define COUNTRY_CODE_MN (((UINT_16) 'M' << 8) | (UINT_16) 'N') /* Mongolia */ +#define COUNTRY_CODE_MO (((UINT_16) 'M' << 8) | (UINT_16) 'O') /* Macao */ +#define COUNTRY_CODE_MP (((UINT_16) 'M' << 8) | (UINT_16) 'P') /* Northern Mariana Islands (Rota Island*/ + /*Saipan and Tinian Island) */ +#define COUNTRY_CODE_MQ (((UINT_16) 'M' << 8) | (UINT_16) 'Q') /* Martinique (France) */ +#define COUNTRY_CODE_MR (((UINT_16) 'M' << 8) | (UINT_16) 'R') /* Mauritania */ +#define COUNTRY_CODE_MS (((UINT_16) 'M' << 8) | (UINT_16) 'S') /* Montserrat (UK) */ +#define COUNTRY_CODE_MT (((UINT_16) 'M' << 8) | (UINT_16) 'T') /* Malta */ +#define COUNTRY_CODE_MU (((UINT_16) 'M' << 8) | (UINT_16) 'U') /* Mauritius */ +#define COUNTRY_CODE_MV (((UINT_16) 'M' << 8) | (UINT_16) 'V') /* Maldives */ +#define COUNTRY_CODE_MW (((UINT_16) 'M' << 8) | (UINT_16) 'W') /* Malawi */ +#define COUNTRY_CODE_MX (((UINT_16) 'M' << 8) | (UINT_16) 'X') /* Mexico */ +#define COUNTRY_CODE_MY (((UINT_16) 'M' << 8) | (UINT_16) 'Y') /* Malaysia */ +#define COUNTRY_CODE_MZ (((UINT_16) 'M' << 8) | (UINT_16) 'Z') /* Mozambique */ +#define COUNTRY_CODE_NA (((UINT_16) 'N' << 8) | (UINT_16) 'A') /* Namibia */ +#define COUNTRY_CODE_NC (((UINT_16) 'N' << 8) | (UINT_16) 'C') /* New Caledonia */ +#define COUNTRY_CODE_NE (((UINT_16) 'N' << 8) | (UINT_16) 'E') /* Niger */ +#define COUNTRY_CODE_NF (((UINT_16) 'N' << 8) | (UINT_16) 'F') /* Norfolk Island */ +#define COUNTRY_CODE_NG (((UINT_16) 'N' << 8) | (UINT_16) 'G') /* Nigeria */ +#define COUNTRY_CODE_NI (((UINT_16) 'N' << 8) | (UINT_16) 'I') /* Nicaragua */ +#define COUNTRY_CODE_NL (((UINT_16) 'N' << 8) | (UINT_16) 'L') /* Netherlands */ +#define COUNTRY_CODE_NO (((UINT_16) 'N' << 8) | (UINT_16) 'O') /* Norway */ +#define COUNTRY_CODE_NP (((UINT_16) 'N' << 8) | (UINT_16) 'P') /* Nepal */ +#define COUNTRY_CODE_NR (((UINT_16) 'N' << 8) | (UINT_16) 'R') /* Nauru */ +#define COUNTRY_CODE_NU (((UINT_16) 'N' << 8) | (UINT_16) 'U') /* Niue */ +#define COUNTRY_CODE_NZ (((UINT_16) 'N' << 8) | (UINT_16) 'Z') /* New Zealand */ +#define COUNTRY_CODE_OM (((UINT_16) 'O' << 8) | (UINT_16) 'M') /* Oman */ +#define COUNTRY_CODE_PA (((UINT_16) 'P' << 8) | (UINT_16) 'A') /* Panama */ +#define COUNTRY_CODE_PE (((UINT_16) 'P' << 8) | (UINT_16) 'E') /* Peru */ +#define COUNTRY_CODE_PF (((UINT_16) 'P' << 8) | (UINT_16) 'F') /* "French Polynesia */ +#define COUNTRY_CODE_PG (((UINT_16) 'P' << 8) | (UINT_16) 'G') /* Papua New Guinea */ +#define COUNTRY_CODE_PH (((UINT_16) 'P' << 8) | (UINT_16) 'H') /* Philippines */ +#define COUNTRY_CODE_PK (((UINT_16) 'P' << 8) | (UINT_16) 'K') /* Pakistan */ +#define COUNTRY_CODE_PL (((UINT_16) 'P' << 8) | (UINT_16) 'L') /* Poland */ +#define COUNTRY_CODE_PM (((UINT_16) 'P' << 8) | (UINT_16) 'M') /* Saint Pierre and Miquelon */ +#define COUNTRY_CODE_PN (((UINT_16) 'P' << 8) | (UINT_16) 'N') /* Pitcairn Islands */ +#define COUNTRY_CODE_PR (((UINT_16) 'P' << 8) | (UINT_16) 'R') /* Puerto Rico (USA) */ +#define COUNTRY_CODE_PS (((UINT_16) 'P' << 8) | (UINT_16) 'S') /* Palestinian Authority */ +#define COUNTRY_CODE_PT (((UINT_16) 'P' << 8) | (UINT_16) 'T') /* Portugal */ +#define COUNTRY_CODE_PW (((UINT_16) 'P' << 8) | (UINT_16) 'W') /* Palau */ +#define COUNTRY_CODE_PY (((UINT_16) 'P' << 8) | (UINT_16) 'Y') /* Paraguay */ +#define COUNTRY_CODE_QA (((UINT_16) 'Q' << 8) | (UINT_16) 'A') /* Qatar */ +#define COUNTRY_CODE_RE (((UINT_16) 'R' << 8) | (UINT_16) 'E') /* Reunion (France) */ +#define COUNTRY_CODE_RKS (((UINT_16) 'R' << 8) | (UINT_16) 'K') /* Kosvo (Added on window's list) */ +#define COUNTRY_CODE_RO (((UINT_16) 'R' << 8) | (UINT_16) 'O') /* Romania */ +#define COUNTRY_CODE_RS (((UINT_16) 'R' << 8) | (UINT_16) 'S') /* Serbia */ +#define COUNTRY_CODE_RU (((UINT_16) 'R' << 8) | (UINT_16) 'U') /* Russia */ +#define COUNTRY_CODE_RW (((UINT_16) 'R' << 8) | (UINT_16) 'W') /* Rwanda */ +#define COUNTRY_CODE_SA (((UINT_16) 'S' << 8) | (UINT_16) 'A') /* Saudi Arabia */ +#define COUNTRY_CODE_SB (((UINT_16) 'S' << 8) | (UINT_16) 'B') /* Solomon Islands */ +#define COUNTRY_CODE_SC (((UINT_16) 'S' << 8) | (UINT_16) 'C') /* Seychelles */ +#define COUNTRY_CODE_SD (((UINT_16) 'S' << 8) | (UINT_16) 'D') /* Sudan */ +#define COUNTRY_CODE_SE (((UINT_16) 'S' << 8) | (UINT_16) 'E') /* Sweden */ +#define COUNTRY_CODE_SG (((UINT_16) 'S' << 8) | (UINT_16) 'G') /* Singapole */ +#define COUNTRY_CODE_SI (((UINT_16) 'S' << 8) | (UINT_16) 'I') /* Slovenia */ +#define COUNTRY_CODE_SK (((UINT_16) 'S' << 8) | (UINT_16) 'K') /* Slovakia */ +#define COUNTRY_CODE_SL (((UINT_16) 'S' << 8) | (UINT_16) 'L') /* Sierra Leone */ +#define COUNTRY_CODE_SM (((UINT_16) 'S' << 8) | (UINT_16) 'M') /* San Marino */ +#define COUNTRY_CODE_SN (((UINT_16) 'S' << 8) | (UINT_16) 'N') /* Senegal */ +#define COUNTRY_CODE_SO (((UINT_16) 'S' << 8) | (UINT_16) 'O') /* Somalia */ +#define COUNTRY_CODE_SR (((UINT_16) 'S' << 8) | (UINT_16) 'R') /* Suriname */ +#define COUNTRY_CODE_SS (((UINT_16) 'S' << 8) | (UINT_16) 'S') /* South_Sudan */ +#define COUNTRY_CODE_ST (((UINT_16) 'S' << 8) | (UINT_16) 'T') /* Sao Tome and Principe */ +#define COUNTRY_CODE_SV (((UINT_16) 'S' << 8) | (UINT_16) 'V') /* El Salvador */ +#define COUNTRY_CODE_SY (((UINT_16) 'S' << 8) | (UINT_16) 'Y') /* Syria */ +#define COUNTRY_CODE_SZ (((UINT_16) 'S' << 8) | (UINT_16) 'Z') /* Swaziland */ +#define COUNTRY_CODE_TC (((UINT_16) 'T' << 8) | (UINT_16) 'C') /* Turks and Caicos Islands (UK) */ +#define COUNTRY_CODE_TD (((UINT_16) 'T' << 8) | (UINT_16) 'D') /* Chad */ +#define COUNTRY_CODE_TF (((UINT_16) 'T' << 8) | (UINT_16) 'F') /* French Southern and Antarctic Lands */ +#define COUNTRY_CODE_TG (((UINT_16) 'T' << 8) | (UINT_16) 'G') /* Togo */ +#define COUNTRY_CODE_TH (((UINT_16) 'T' << 8) | (UINT_16) 'H') /* Thailand */ +#define COUNTRY_CODE_TJ (((UINT_16) 'T' << 8) | (UINT_16) 'J') /* Tajikistan */ +#define COUNTRY_CODE_TL (((UINT_16) 'T' << 8) | (UINT_16) 'L') /* East Timor */ +#define COUNTRY_CODE_TM (((UINT_16) 'T' << 8) | (UINT_16) 'M') /* Turkmenistan */ +#define COUNTRY_CODE_TN (((UINT_16) 'T' << 8) | (UINT_16) 'N') /* Tunisia */ +#define COUNTRY_CODE_TO (((UINT_16) 'T' << 8) | (UINT_16) 'O') /* Tonga */ +#define COUNTRY_CODE_TR (((UINT_16) 'T' << 8) | (UINT_16) 'R') /* Turkey */ +#define COUNTRY_CODE_TT (((UINT_16) 'T' << 8) | (UINT_16) 'T') /* Trinidad and Tobago */ +#define COUNTRY_CODE_TV (((UINT_16) 'T' << 8) | (UINT_16) 'V') /* Tuvalu */ +#define COUNTRY_CODE_TW (((UINT_16) 'T' << 8) | (UINT_16) 'W') /* Taiwan */ +#define COUNTRY_CODE_TZ (((UINT_16) 'T' << 8) | (UINT_16) 'Z') /* Tanzania */ +#define COUNTRY_CODE_UA (((UINT_16) 'U' << 8) | (UINT_16) 'A') /* Ukraine */ +#define COUNTRY_CODE_UG (((UINT_16) 'U' << 8) | (UINT_16) 'G') /* Ugnada */ +#define COUNTRY_CODE_US (((UINT_16) 'U' << 8) | (UINT_16) 'S') /* US */ +#define COUNTRY_CODE_UY (((UINT_16) 'U' << 8) | (UINT_16) 'Y') /* Uruguay */ +#define COUNTRY_CODE_UZ (((UINT_16) 'U' << 8) | (UINT_16) 'Z') /* Uzbekistan */ +#define COUNTRY_CODE_VA (((UINT_16) 'V' << 8) | (UINT_16) 'A') /* Vatican (Holy See) */ +#define COUNTRY_CODE_VC (((UINT_16) 'V' << 8) | (UINT_16) 'C') /* Saint Vincent and the Grenadines */ +#define COUNTRY_CODE_VE (((UINT_16) 'V' << 8) | (UINT_16) 'E') /* Venezuela */ +#define COUNTRY_CODE_VG (((UINT_16) 'V' << 8) | (UINT_16) 'G') /* British Virgin Islands */ +#define COUNTRY_CODE_VI (((UINT_16) 'V' << 8) | (UINT_16) 'I') /* US Virgin Islands */ +#define COUNTRY_CODE_VN (((UINT_16) 'V' << 8) | (UINT_16) 'N') /* Vietnam */ +#define COUNTRY_CODE_VU (((UINT_16) 'V' << 8) | (UINT_16) 'U') /* Vanuatu */ +#define COUNTRY_CODE_WS (((UINT_16) 'W' << 8) | (UINT_16) 'S') /* Samoa */ +#define COUNTRY_CODE_YE (((UINT_16) 'Y' << 8) | (UINT_16) 'E') /* Yemen */ +#define COUNTRY_CODE_YT (((UINT_16) 'Y' << 8) | (UINT_16) 'T') /* Mayotte (France) */ +#define COUNTRY_CODE_ZA (((UINT_16) 'Z' << 8) | (UINT_16) 'A') /* South Africa */ +#define COUNTRY_CODE_ZM (((UINT_16) 'Z' << 8) | (UINT_16) 'M') /* Zambia */ +#define COUNTRY_CODE_ZW (((UINT_16) 'Z' << 8) | (UINT_16) 'W') /* Zimbabwe */ +#define COUNTRY_CODE_DF (((UINT_16) 'D' << 8) | (UINT_16) 'F') /* Default country domain */ +#define COUNTRY_CODE_WW (((UINT_16) '0' << 8) | (UINT_16) '0') /* World Wide */ + + +/* dot11RegDomainsSupportValue */ +#define MIB_REG_DOMAIN_FCC 0x10 /* FCC (US) */ +#define MIB_REG_DOMAIN_IC 0x20 /* IC or DOC (Canada) */ +#define MIB_REG_DOMAIN_ETSI 0x30 /* ETSI (Europe) */ +#define MIB_REG_DOMAIN_SPAIN 0x31 /* Spain */ +#define MIB_REG_DOMAIN_FRANCE 0x32 /* France */ +#define MIB_REG_DOMAIN_JAPAN 0x40 /* MPHPT (Japan) */ +#define MIB_REG_DOMAIN_OTHER 0x00 /* other */ + +/*2.4G*/ +#define BAND_2G4_LOWER_BOUND 1 +#define BAND_2G4_UPPER_BOUND 14 +/*5G SubBand FCC spec*/ +#define UNII1_LOWER_BOUND 36 +#define UNII1_UPPER_BOUND 48 +#define UNII2A_LOWER_BOUND 52 +#define UNII2A_UPPER_BOUND 64 +#define UNII2C_LOWER_BOUND 100 +#define UNII2C_UPPER_BOUND 144 +#define UNII3_LOWER_BOUND 149 +#define UNII3_UPPER_BOUND 173 + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +#define POWER_LIMIT_TABLE_NULL 0xFFFF +#define MAX_TX_POWER 63 +#define MIN_TX_POWER -64 +#define MAX_CMD_SUPPORT_CHANNEL_NUM 64 + +#endif + +#if (CFG_SUPPORT_SINGLE_SKU == 1) +#define MAX_SUPPORTED_CH_COUNT MAX_CHN_NUM +#define REG_RULE_LIGHT(start, end, bw, reg_flags) REG_RULE(start, end, bw, 0, 0, reg_flags) +#define TX_PWR_LIMIT_CMD_CH_NUM_THRESHOLD 32 +#endif +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +typedef enum _ENUM_POWER_LIMIT_T { + PWR_LIMIT_CCK = 0, + PWR_LIMIT_20M = 1, + PWR_LIMIT_40M = 2, + PWR_LIMIT_80M = 3, + PWR_LIMIT_160M = 4, + PWR_LIMIT_NUM +} ENUM_POWER_LIMIT_T, *P_ENUM_POWER_LIMIT_T; + +#endif + +typedef enum _ENUM_POWER_LIMIT_SUBBAND_T { + POWER_LIMIT_2G4 = 0, + POWER_LIMIT_UNII1 = 1, + POWER_LIMIT_UNII2A = 2, + POWER_LIMIT_UNII2C = 3, + POWER_LIMIT_UNII3 = 4, + POWER_LIMIT_SUBAND_NUM +} ENUM_POWER_LIMIT_SUBBAND_T, *P_ENUM_POWER_LIMIT_SUBBAND_T; + +/* Define channel offset in unit of 5MHz bandwidth */ +typedef enum _ENUM_CHNL_SPAN_T { + CHNL_SPAN_5 = 1, + CHNL_SPAN_10 = 2, + CHNL_SPAN_20 = 4, + CHNL_SPAN_40 = 8 +} ENUM_CHNL_SPAN_T, *P_ENUM_CHNL_SPAN_T; + +/* Define BSS operating bandwidth */ +typedef enum _ENUM_CHNL_BW_T { + CHNL_BW_20, + CHNL_BW_20_40, + CHNL_BW_10, + CHNL_BW_5 +} ENUM_CHNL_BW_T, *P_ENUM_CHNL_BW_T; + +#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 fgDfs; /* Type: BOOLEAN*/ +} DOMAIN_SUBBAND_INFO, *P_DOMAIN_SUBBAND_INFO; + +/* Use it as all available channel list for STA */ +typedef struct _DOMAIN_INFO_ENTRY { + PUINT_16 pu2CountryGroup; + UINT_32 u4CountryNum; + + /* If different attributes, put them into different rSubBands. + * For example, DFS shall be used or not. + */ + DOMAIN_SUBBAND_INFO rSubBand[MAX_SUBBAND_NUM]; +} DOMAIN_INFO_ENTRY, *P_DOMAIN_INFO_ENTRY; +#endif + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +#if (CFG_SUPPORT_SINGLE_SKU == 1) +/* + * MT_TxPwrLimit.dat format + */ +#define SECTION_PREFIX (0x23232323) +#define ELEMENT_PREFIX (0xffff) +#define VERSION (0x00000001) +#define SIZE_OF_VERSION 4 +#define WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE 204800 +#define WLAN_TX_PWR_LIMIT_FILE_NAME "TxPwrLimit_MT76x8.dat" + + +struct tx_pwr_element { + UINT_16 prefix; + UINT_8 channel_num; + UINT_8 reserved; + + /*the followings are in unit: 0.5 dbm*/ + + UINT_8 tx_pwr_dsss_cck; + UINT_8 tx_pwr_dsss_bpsk; + + UINT_8 tx_pwr_ofdm_bpsk; /* 6M, 9M */ + UINT_8 tx_pwr_ofdm_qpsk; /* 12M, 18M */ + UINT_8 tx_pwr_ofdm_16qam; /* 24M, 36M */ + UINT_8 tx_pwr_ofdm_48m; + UINT_8 tx_pwr_ofdm_54m; + + UINT_8 tx_pwr_ht20_bpsk; /* MCS0*/ + UINT_8 tx_pwr_ht20_qpsk; /* MCS1, MCS2*/ + UINT_8 tx_pwr_ht20_16qam; /* MCS3, MCS4*/ + UINT_8 tx_pwr_ht20_mcs5; /* MCS5*/ + UINT_8 tx_pwr_ht20_mcs6; /* MCS6*/ + UINT_8 tx_pwr_ht20_mcs7; /* MCS7*/ + + UINT_8 tx_pwr_ht40_bpsk; /* MCS0*/ + UINT_8 tx_pwr_ht40_qpsk; /* MCS1, MCS2*/ + UINT_8 tx_pwr_ht40_16qam; /* MCS3, MCS4*/ + UINT_8 tx_pwr_ht40_mcs5; /* MCS5*/ + UINT_8 tx_pwr_ht40_mcs6; /* MCS6*/ + UINT_8 tx_pwr_ht40_mcs7; /* MCS7*/ + + UINT_8 tx_pwr_vht20_bpsk; /* MCS0*/ + UINT_8 tx_pwr_vht20_qpsk; /* MCS1, MCS2*/ + UINT_8 tx_pwr_vht20_16qam; /* MCS3, MCS4*/ + UINT_8 tx_pwr_vht20_64qam; /* MCS5, MCS6*/ + UINT_8 tx_pwr_vht20_mcs7; + UINT_8 tx_pwr_vht20_mcs8; + UINT_8 tx_pwr_vht20_mcs9; + + UINT_8 tx_pwr_vht_40; + UINT_8 tx_pwr_vht_80; + UINT_8 tx_pwr_vht_160nc; + UINT_8 tx_pwr_lg_40; + UINT_8 tx_pwr_lg_80; + + UINT_8 tx_pwr_1ss_delta; + UINT_8 reserved_3[3]; +}; + +struct tx_pwr_section { + UINT_32 prefix; + UINT_32 country_code; +}; +#endif /*#if (CFG_SUPPORT_SINGLE_SKU == 1)*/ + +/* CMD_SET_PWR_LIMIT_TABLE */ +typedef struct _CHANNEL_POWER_LIMIT { + UINT_8 ucCentralCh; + INT_8 cPwrLimitCCK; + INT_8 cPwrLimit20; + INT_8 cPwrLimit40; + INT_8 cPwrLimit80; + INT_8 cPwrLimit160; + UINT_8 ucFlag; + UINT_8 aucReserved[1]; +} CHANNEL_POWER_LIMIT, *P_CHANNEL_POWER_LIMIT; + +typedef struct _COUNTRY_CHANNEL_POWER_LIMIT { + UINT_8 aucCountryCode[2]; + UINT_8 ucCountryFlag; + UINT_8 ucChannelNum; + UINT_8 aucReserved[4]; + CHANNEL_POWER_LIMIT rChannelPowerLimit[80]; +} COUNTRY_CHANNEL_POWER_LIMIT, *P_COUNTRY_CHANNEL_POWER_LIMIT; + +#define CHANNEL_PWR_LIMIT(_channel, _pwrLimit_cck, _pwrLimit_bw20, \ + _pwrLimit_bw40, _pwrLimit_bw80, _pwrLimit_bw160, _ucFlag) \ + { \ + .ucCentralCh = (_channel), \ + .cPwrLimitCCK = (_pwrLimit_cck), \ + .cPwrLimit20 = (_pwrLimit_bw20), \ + .cPwrLimit40 = (_pwrLimit_bw40), \ + .cPwrLimit80 = (_pwrLimit_bw80), \ + .cPwrLimit160 = (_pwrLimit_bw160), \ + .ucFlag = (_ucFlag), \ + .aucReserved = {0} \ +} + +typedef struct _COUNTRY_POWER_LIMIT_TABLE_DEFAULT { + UINT_8 aucCountryCode[2]; + /* 0: ch 1 ~14 , 1: ch 36 ~48, 2: ch 52 ~64, 3: ch 100 ~144, 4: ch 149 ~165 */ + INT_8 aucPwrLimitSubBand[POWER_LIMIT_SUBAND_NUM]; + /* bit0: cPwrLimit2G4, bit1: cPwrLimitUnii1; bit2: cPwrLimitUnii2A;*/ + /* bit3: cPwrLimitUnii2C; bit4: cPwrLimitUnii3; mW: 0, mW\MHz : 1 */ + UINT_8 ucPwrUnit; +} COUNTRY_POWER_LIMIT_TABLE_DEFAULT, *P_COUNTRY_POWER_LIMIT_TABLE_DEFAULT; + +typedef struct _COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION { + UINT_8 aucCountryCode[2]; + UINT_8 ucCentralCh; + INT_8 aucPwrLimit[PWR_LIMIT_NUM]; +} COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION, *P_COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION; + +typedef struct _SUBBAND_CHANNEL_T { + UINT_8 ucStartCh; + UINT_8 ucEndCh; + UINT_8 ucInterval; + UINT_8 ucReserved; +} SUBBAND_CHANNEL_T, *P_SUBBAND_CHANNEL_T; + +#endif + +#if (CFG_SUPPORT_SINGLE_SKU == 1) +/* + * Event from chip for single sku + */ +typedef struct _SINGLE_SKU_INFO { + UINT_32 u4EfuseCountryCode; + UINT_8 isEfuseValid; + UINT_8 ucReserved[7]; +} SINGLE_SKU_INFO, *P_SINGLE_SKU_INFO; + + +/* + * channel structure + */ +struct channel { + u16 chNum; + u8 reserved[2]; + u32 flags; /*enum ieee80211_channel_flags*/ +}; + +struct acctive_channel_list { + u8 n_channels_2g; + u8 n_channels_5g; + u8 ucReserved[2]; + struct channel channels[0]; +}; + +/* + * single sku control structure + */ +enum regd_state { + REGD_STATE_UNDEFINED, + REGD_STATE_INIT, + REGD_STATE_SET_WW_CORE, + REGD_STATE_SET_COUNTRY_USER, + REGD_STATE_SET_COUNTRY_DRIVER, + REGD_STATE_SET_COUNTRY_IE, + REGD_STATE_INVALID +}; + +enum regd_control_flag { + REGD_CTRL_FLAG_SUPPORT_LOCAL_REGD_DB = (0x1 << 0) +}; + +typedef struct mtk_regd_control_t { + BOOLEAN en; + BOOLEAN isEfuseCountryCodeUsed; + enum regd_state state; + u32 alpha2; + u32 tmp_alpha2; /*store country code set by iwpriv "country XX"*/ + u32 flag; /*enum regd_control_flag*/ + struct wiphy *pRefWiphy; /*log the referenced wiphy*/ + P_GLUE_INFO_T pGlueInfo; /*wlan GlueInfo*/ + u8 n_channel_active_2g; + u8 n_channel_active_5g; + struct channel channels[MAX_SUPPORTED_CH_COUNT]; + enum nl80211_dfs_regions dfs_region; +} mtk_regd_control; + +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) +struct mtk_regdomain { + char country_code[4]; + const struct ieee80211_regdomain *prRegdRules; +}; +#endif + +#endif +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define CAL_CH_OFFSET_80M(_PRIMARY_CH, _CENTRAL_CH) \ + (((_PRIMARY_CH - _CENTRAL_CH) + 6) >> 2) + +#define CAL_CH_OFFSET_160M(_PRIMARY_CH, _CENTRAL_CH) \ + (((_PRIMARY_CH - _CENTRAL_CH) + 14) >> 2) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +P_DOMAIN_INFO_ENTRY rlmDomainGetDomainInfo(P_ADAPTER_T prAdapter); + +VOID +rlmDomainGetChnlList(P_ADAPTER_T prAdapter, + ENUM_BAND_T eSpecificBand, BOOLEAN fgNoDfs, + UINT_8 ucMaxChannelNum, PUINT_8 pucNumOfChannel, P_RF_CHANNEL_INFO_T paucChannelList); + +VOID rlmDomainSendCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid); + +VOID rlmDomainSendDomainInfoCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid); + +VOID rlmDomainSendPassiveScanInfoCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid); + +UINT_32 rlmDomainSupOperatingClassIeFill(PUINT_8 pBuf); + +BOOLEAN rlmDomainCheckChannelEntryValid(P_ADAPTER_T prAdapter, UINT_8 ucCentralCh); + +UINT_8 rlmDomainGetCenterChannel(ENUM_BAND_T eBand, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend); + +BOOLEAN rlmDomainIsValidRfSetting(P_ADAPTER_T prAdapter, ENUM_BAND_T eBand, + UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend, + ENUM_CHANNEL_WIDTH_T eChannelWidth, UINT_8 ucChannelS1, UINT_8 ucChannelS2); + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +BOOLEAN +rlmDomainCheckPowerLimitValid(P_ADAPTER_T prAdapter, + COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION rPowerLimitTableConfiguration, + UINT_8 ucPwrLimitNum); + +VOID rlmDomainCheckCountryPowerLimitTable(P_ADAPTER_T prAdapter); + +UINT_16 rlmDomainPwrLimitDefaultTableDecision(P_ADAPTER_T prAdapter, UINT_16 u2CountryCode); + +VOID rlmDomainSendPwrLimitCmd(P_ADAPTER_T prAdapter); +#endif + +#if (CFG_SUPPORT_SINGLE_SKU == 1) +extern struct ieee80211_supported_band mtk_band_2ghz; +extern struct ieee80211_supported_band mtk_band_5ghz; + +BOOLEAN rlmDomainIsCtrlStateEqualTo(enum regd_state state); +BOOLEAN rlmDomainIsUsingLocalRegDomainDataBase(void); +enum regd_state rlmDomainStateTransition(enum regd_state request_state, struct regulatory_request *pRequest); +void rlmDomainSetCountryCode(char *alpha2, u8 size_of_alpha2); +void rlmDomainSetDfsRegion(enum nl80211_dfs_regions dfs_region); +enum nl80211_dfs_regions rlmDomainGetDfsRegion(void); +void rlmDomainResetCtrlInfo(void); +void rlmDomainAddActiveChannel(u8 band); +u8 rlmDomainGetActiveChannelCount(u8 band); +void rlmDomainParsingChannel(IN struct wiphy *pWiphy); +struct channel *rlmDomainGetActiveChannels(void); +void rlmExtractChannelInfo(u32 max_ch_count, struct acctive_channel_list *prBuff); +void regd_set_using_local_regdomain_db(void); +void rlmDomainSetDefaultCountryCode(void); +struct wiphy *rlmDomainGetRefWiphy(void); +void rlmDomainSetRefWiphy(struct wiphy *pWiphy); +enum regd_state rlmDomainGetCtrlState(void); +bool rlmDomainIsSameCountryCode(char *alpha2, u8 size_of_alpha2); +const struct ieee80211_regdomain *rlmDomainSearchRegdomainFromLocalDataBase(char *alpha2); +P_GLUE_INFO_T rlmDomainGetGlueInfo(void); +bool rlmDomainIsEfuseUsed(void); +UINT_8 rlmDomainGetChannelBw(UINT_8 channelNum); + +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) +extern const struct mtk_regdomain *g_prRegRuleTable[]; +#endif + +#endif + +const struct ieee80211_regdomain *rlmDomainGetLocalDefaultRegd(void); +void rlmDomainSendInfoToFirmware(IN P_ADAPTER_T prAdapter); +WLAN_STATUS rlmDomainExtractSingleSkuInfoFromFirmware(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEventBuf); +BOOLEAN regd_is_single_sku_en(void); +BOOLEAN rlmDomainIsLegalChannel(P_ADAPTER_T prAdapter, ENUM_BAND_T eBand, UINT_8 ucChannel); +ENUM_CHNL_EXT_T rlmSelectSecondaryChannelType(P_ADAPTER_T prAdapter, ENUM_BAND_T band, u8 primary_ch); +extern void mtk_reg_notify(IN struct wiphy *pWiphy, + IN struct regulatory_request *pRequest); +void rlmDomainOidSetCountry(IN P_ADAPTER_T prAdapter, char *country, u8 size_of_country); +u32 rlmDomainGetCountryCode(void); +u32 rlmDomainGetTempCountryCode(void); +void rlmDomainAssert(BOOLEAN cond); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _RLM_DOMAIN_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rlm_obss.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rlm_obss.h new file mode 100644 index 0000000000000..017596fc6773b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rlm_obss.h @@ -0,0 +1,146 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rlm_obss.h#1 +*/ + +/*! \file "rlm_obss.h" +* \brief +*/ + + +#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); +VOID rlmObssAbortScan(P_ADAPTER_T prAdapter); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _RLM_OBSS_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rlm_protection.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rlm_protection.h new file mode 100644 index 0000000000000..062dde0ebbfdc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rlm_protection.h @@ -0,0 +1,142 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rlm_protection.h#1 +*/ + +/*! \file "rlm_protection.h" +* \brief +*/ + + +#ifndef _RLM_PROTECTION_H +#define _RLM_PROTECTION_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_SYS_PROTECT_MODE_T { + SYS_PROTECT_MODE_NONE = 0, /* Mode 0 */ + SYS_PROTECT_MODE_ERP, /* Mode 1 */ + SYS_PROTECT_MODE_NON_HT, /* Mode 2 */ + SYS_PROTECT_MODE_20M, /* Mode 3 */ + + SYS_PROTECT_MODE_NUM +} ENUM_SYS_PROTECT_MODE_T, *P_ENUM_SYS_PROTECT_MODE_T; + +/* This definition follows HT Protection field of HT Operation IE */ +typedef enum _ENUM_HT_PROTECT_MODE_T { + HT_PROTECT_MODE_NONE = 0, + HT_PROTECT_MODE_NON_MEMBER, + HT_PROTECT_MODE_20M, + HT_PROTECT_MODE_NON_HT, + + HT_PROTECT_MODE_NUM +} ENUM_HT_PROTECT_MODE_T, *P_ENUM_HT_PROTECT_MODE_T; + +typedef enum _ENUM_GF_MODE_T { + GF_MODE_NORMAL = 0, + GF_MODE_PROTECT, + GF_MODE_DISALLOWED, + + GF_MODE_NUM +} ENUM_GF_MODE_T, *P_ENUM_GF_MODE_T; + +typedef enum _ENUM_RIFS_MODE_T { + RIFS_MODE_NORMAL = 0, + RIFS_MODE_DISALLOWED, + + RIFS_MODE_NUM +} ENUM_RIFS_MODE_T, *P_ENUM_RIFS_MODE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _RLM_PROTECTION_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rlm_txpwr_init.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rlm_txpwr_init.h new file mode 100644 index 0000000000000..e9e74b5629dd8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rlm_txpwr_init.h @@ -0,0 +1,1253 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rlm_txpwr_init.h#1 +*/ + +/*! \file "rlm_txpwr_init.h" +* \brief +*/ + +/* +** Log: rlm_txpwr_init.h +*/ + +#ifndef _RLM_TXPWR_INIT_H +#define _RLM_TXPWR_INIT_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/*Support Tx Power Range : 63~ -64 (unit : 0.5dBm)*/ + +#define PWR_LIMIT_2G4_IN_MW_MHZ BIT(0) +#define PWR_LIMIT_UNII1_IN_MW_MHZ BIT(1) +#define PWR_LIMIT_UNII2A_IN_MW_MHZ BIT(2) +#define PWR_LIMIT_UNII2C_IN_MW_MHZ BIT(3) +#define PWR_LIMIT_UNII3_IN_MW_MHZ BIT(4) + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +COUNTRY_POWER_LIMIT_TABLE_DEFAULT g_rRlmPowerLimitDefault[] = { + + {{'A', 'O'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'B', 'Z'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'B', 'J'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'B', 'T'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'B', 'O'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'B', 'I'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'C', 'M'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'C', 'F'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'T', 'D'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'K', 'M'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'C', 'D'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'C', 'G'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'C', 'I'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'D', 'J'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'G', 'Q'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'E', 'R'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'F', 'J'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'G', 'A'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'G', 'M'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'G', 'N'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'G', 'W'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'R', 'K'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'K', 'G'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'L', 'Y'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'M', 'G'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'M', 'L'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'N', 'R'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'N', 'C'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'T'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'C'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'L'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'B'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'O'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'R'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'Z'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'T', 'J'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'T', 'G'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'T', 'O'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'T', 'M'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'T', 'V'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'V', 'U'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'Y', 'E'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'A', 'S'} + , {60, 34, 46, 48, 60} + , 0} + , + {{'A', 'I'} + , {60, 34, 48, 60, 60} + , 0} + , + {{'B', 'M'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'C', 'A'} + , {60, 46, 48, 48, 60} + , 0} + , + {{'K', 'Y'} + , {60, 34, 48, 60, 60} + , 0} + , + {{'G', 'U'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'F', 'M'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'P', 'R'} + , {60, 34, 46, 48, 60} + , 0} + , + {{'U', 'S'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'V', 'I'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'A', 'R'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'A', 'U'} + , {63, 46, 46, 60, 63} + , 0} + , + {{'A', 'Z'} + , {40, 34, 48, 60, 60} + , 0} + , + {{'B', 'W'} + , {40, 46, 46, 60, 60} + , 0} + , + {{'K', 'H'} + , {40, 46, 46, 48, 60} + , 0} + , + {{'C', 'X'} + , {63, 46, 46, 60, 63} + , 0} + , + {{'C', 'O'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'C', 'R'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'E', 'C'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'G', 'D'} + , {40, 46, 46, 60, 60} + , 0} + , + {{'G', 'T'} + , {40, 34, 48, 48, 60} + , 0} + , + {{'H', 'K'} + , {63, 46, 46, 60, 63} + , 0} + , + {{'K', 'I'} + , {63, 46, 46, 60, 63} + , 0} + , + {{'L', 'B'} + , {40, 46, 46, 46, 46} + , 0} + , + {{'L', 'R'} + , {60, 46, 60, 63, 63} + , 0} + , + {{'M', 'N'} + , {46, 32, 46, 46, 58} + , 0} + , + {{'A', 'N'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'N', 'Z'} + , {63, 46, 60, 48, 63} + , 0} + , + {{'N', 'I'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'P', 'W'} + , {60, 60, 60, 60, 60} + , 0} + , + {{'P', 'Y'} + , {60, 46, 46, 48, 60} + , 0} + , + {{'P', 'E'} + , {54, 46, 48, 42, 48} + , 0} + , + {{'P', 'H'} + , {40, 46, 46, 48, 48} + , 0} + , + {{'W', 'S'} + , {40, 40, 40, 40, 60} + , 0} + , + {{'S', 'G'} + , {46, 46, 46, 60, 60} + , 0} + , + {{'L', 'K'} + , {46, 46, 46, 46, 46} + , 0} + , + {{'T', 'H'} + , {40, 46, 46, 60, 60} + , 0} + , + {{'T', 'T'} + , {60, 46, 46, 60, 60} + , 0} + , + {{'U', 'Y'} + , {63, 46, 46, 46, 46} + , 0} + , + {{'V', 'N'} + , {46, 46, 46, 60, 60} + , 0} + , + {{'A', 'W'} + , {60, 46, 60, 60, 63} + , 0} + , + {{'L', 'A'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'S', 'A'} + , {40, 46, 46, 60, 60} + , 0} + , + {{'A', 'E'} + , {40, 46, 46, 60, 46} + , 0} + , + {{'U', 'G'} + , {40, 46, 46, 48, 60} + , 0} + , + {{'M', 'M'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'A', 'L'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'D', 'Z'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'A', 'D'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'A', 'T'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'B', 'Y'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'B', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'B', 'A'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'V', 'G'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'B', 'G'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'C', 'V'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'H', 'R'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'C', 'Y'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'C', 'Z'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'D', 'K'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'E', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'E', 'T'} + , {40, 40, 40, 40, 63} + , 0} + , + {{'F', 'I'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'F', 'R'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'G', 'F'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'P', 'F'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'T', 'F'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'G', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'D', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'G', 'H'} + , {40, 34, 48, 60, 63} + , 0} + , + {{'G', 'R'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'G', 'P'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'H', 'U'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'I', 'S'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'I', 'Q'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'I', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'I', 'T'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'K', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'L', 'V'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'L', 'S'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'L', 'I'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'L', 'T'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'L', 'U'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'K'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'T'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'Q'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'R'} + , {40, 46, 46, 46, 63} + , 0} + , + {{'M', 'U'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'Y', 'T'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'D'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'C'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'S'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'N', 'L'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'N', 'O'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'O', 'M'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'P', 'L'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'P', 'T'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'R', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'R', 'O'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'F'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'S', 'M'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'S', 'N'} + , {40, 40, 40, 60, 63} + , 0} + , + {{'R', 'S'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'S', 'K'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'S', 'I'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'Z', 'A'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'E', 'S'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'S', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'C', 'H'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'T', 'R'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'T', 'C'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'G', 'B'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'V', 'A'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'A', 'M'} + , {40, 40, 40, 63, 63} + , 0} + , + {{'I', 'L'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'K', 'W'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'M', 'A'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'N', 'E'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'T', 'N'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'E', 'H'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'N', 'P'} + , {60, 46, 46, 63, 60} + , 0} + , + {{'A', 'F'} + , {40, 46, 63, 63, 63} + , 0} + , + {{'A', 'G'} + , {40, 46, 48, 63, 54} + , 0} + , + {{'B', 'S'} + , {63, 46, 60, 63, 63} + , 0} + , + {{'B', 'H'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'B', 'B'} + , {40, 46, 48, 63, 54} + , 0} + , + {{'B', 'N'} + , {46, 46, 46, 63, 60} + , 0} + , + {{'C', 'L'} + , {40, 44, 44, 63, 44} + , 0} + , + {{'C', 'N'} + , {40, 46, 46, 63, 54} + , 0} + , + {{'E', 'G'} + , {40, 46, 46, 63, 46} + , 0} + , + {{'S', 'V'} + , {60, 34, 48, 63, 60} + , 0} + , + {{'I', 'N'} + , {60, 46, 46, 63, 60} + , 0} + , + {{'M', 'Y'} + , {54, 60, 60, 63, 60} + , 0} + , + {{'M', 'V'} + , {40, 46, 46, 63, 40} + , 0} + , + {{'P', 'A'} + , {60, 34, 48, 63, 60} + , 0} + , + {{'V', 'E'} + , {60, 46, 46, 63, 60} + , 0} + , + {{'Z', 'M'} + , {60, 46, 46, 63, 60} + , 0} + , + {{'J', 'O'} + , {40, 46, 63, 63, 46} + , 0} + , + {{'P', 'G'} + , {40, 46, 63, 63, 60} + , 0} + , + {{'B', 'F'} + , {40, 63, 63, 63, 60} + , 0} + , + {{'G', 'Y'} + , {60, 63, 63, 63, 60} + , 0} + , + {{'H', 'T'} + , {40, 63, 63, 63, 60} + , 0} + , + {{'H', 'N'} + , {60, 63, 63, 63, 60} + , 0} + , + {{'J', 'M'} + , {54, 63, 63, 63, 57} + , 0} + , + {{'M', 'O'} + , {40, 63, 63, 63, 40} + , 0} + , + {{'M', 'W'} + , {60, 63, 63, 63, 60} + , 0} + , + {{'P', 'K'} + , {40, 63, 63, 63, 40} + , 0} + , + {{'Q', 'A'} + , {40, 63, 63, 63, 40} + , 0} + , + {{'R', 'W'} + , {40, 63, 63, 63, 60} + , 0} + , + {{'K', 'N'} + , {40, 63, 63, 63, 60} + , 0} + , + {{'T', 'Z'} + , {40, 63, 63, 63, 40} + , 0} + , + {{'I', 'D'} + , {46, 63, 63, 63, 60} + , 0} + , + {{'N', 'G'} + , {40, 63, 46, 63, 60} + , 0} + , + {{'B', 'D'} + , {40, 46, 46, 60, 28} + , 0} + , + {{'B', 'R'} + , {52, 46, 46, 60, 60} + , 0} + , + {{'D', 'M'} + , {60, 34, 46, 48, 60} + , 0} + , + {{'D', 'O'} + , {63, 46, 46, 60, 63} + , 0} + , + {{'F', 'K'} + , {40, 46, 46, 60, 28} + , 0} + , + {{'K', 'Z'} + , {40, 34, 48, 60, 60} + , 0} + , + {{'M', 'X'} + , {60, 34, 48, 60, 63} + , 0} + , + {{'M', 'Z'} + , {40, 34, 46, 48, 60} + , 0} + , + {{'N', 'A'} + , {40, 34, 46, 48, 60} + , 0} + , + {{'R', 'U'} + , {40, 34, 48, 60, 60} + , 0} + , + {{'L', 'C'} + , {40, 34, 48, 48, 60} + , 0} + , + {{'V', 'C'} + , {40, 34, 46, 48, 60} + , 0} + , + {{'U', 'A'} + , {40, 46, 46, 46, 48} + , 0} + , + {{'U', 'Z'} + , {40, 48, 48, 48, 60} + , 0} + , + {{'Z', 'W'} + , {40, 34, 46, 48, 60} + , 0} + , + {{'M', 'P'} + , {60, 34, 46, 48, 60} + , 0} + , + {{'T', 'W'} + , {60, 63, 34, 48, 60} + , 0} + , + {{'C', 'K'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'C', 'U'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'T', 'L'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'F', 'O'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'G', 'I'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'G', 'G'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'I', 'R'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'I', 'M'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'J', 'E'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'K', 'P'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'M', 'H'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'N', 'U'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'N', 'F'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'P', 'S'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'P', 'N'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'P', 'M'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'S', 'S'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'S', 'D'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'S', 'Y'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'J', 'P'} + , {46, 46, 46, 60, 63} + , 0} + , + {{'K', 'R'} + , {46, 34, 46, 46, 46} + , PWR_LIMIT_UNII1_IN_MW_MHZ} + , + +/*Default*/ + {{0, 0} + , {63, 63, 63, 63, 63} + , 0} +}; + +COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION g_rRlmPowerLimitConfiguration[] = { + + {{'A', 'I'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'A', 'Z'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'B', 'W'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'G', 'D'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'L', 'B'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'L', 'R'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'W', 'S'} + , 165, {40, 40, 40, 40, 40} + } + , + {{'V', 'N'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'U', 'S'} + , 1, {38, 30, 60, 60, 60} + } + , + {{'U', 'S'} + , 3, {60, 60, 26, 60, 60} + } + , + {{'U', 'S'} + , 9, {60, 60, 26, 60, 60} + } + , + {{'U', 'S'} + , 11, {38, 30, 60, 60, 60} + } + , + {{'U', 'S'} + , 36, {34, 34, 34, 34, 34} + } + , + {{'U', 'S'} + , 38, {34, 34, 34, 34, 34} + } + , + {{'U', 'S'} + , 42, {34, 34, 34, 31, 34} + } + , + {{'U', 'S'} + , 58, {48, 48, 48, 31, 48} + } + , + {{'U', 'S'} + , 62, {48, 48, 34, 48, 48} + } + , + {{'U', 'S'} + , 64, {37, 37, 48, 48, 48} + } + , + {{'U', 'S'} + , 100, {37, 37, 48, 48, 48} + } + , + {{'U', 'S'} + , 102, {48, 48, 34, 48, 48} + } + , + {{'U', 'S'} + , 106, {48, 48, 48, 31, 48} + } + , + {{'U', 'S'} + , 155, {60, 60, 60, 31, 60} + } + , + {{'U', 'S'} + , 159, {60, 60, 34, 60, 60} + } + , + {{'U', 'S'} + , 165, {37, 37, 60, 60, 60} + } + , + +/*Default*/ + {{0, 0} + , 165, {63, 63, 63, 63, 63} + } +}; + +#if 0 +COUNTRY_CHANNEL_POWER_LIMIT g_rRlmCountryPowerLimitTable[] = { + { + {'A', 'O'} + , 0, 0, {0, 0, 0, 0} + , + { + CHANNEL_PWR_LIMIT(1, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(2, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(3, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(4, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(5, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(6, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(7, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(8, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(9, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(10, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(11, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(12, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(13, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(14, 40, 40, 40, 40, 40, 0), + + CHANNEL_PWR_LIMIT(36, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(38, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(40, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(42, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(44, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(46, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(48, 63, 63, 63, 63, 63, 0), + + CHANNEL_PWR_LIMIT(52, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(54, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(56, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(58, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(60, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(62, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(64, 63, 63, 63, 63, 63, 0), + + CHANNEL_PWR_LIMIT(100, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(102, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(104, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(106, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(108, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(110, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(112, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(114, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(116, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(118, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(120, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(122, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(124, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(126, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(128, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(130, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(132, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(134, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(136, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(138, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(140, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(142, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(144, 63, 63, 63, 63, 63, 0), + + CHANNEL_PWR_LIMIT(149, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(151, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(153, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(155, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(157, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(159, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(161, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(163, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(165, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(167, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(169, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(171, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(173, 63, 63, 63, 63, 63, 0) + } + } + , + { + /*Used to check the end of country entry */ + {0, 0} + , 0, 0, {0, 0, 0, 0} + , + { + /*Used to check the end of channel power limit */ + CHANNEL_PWR_LIMIT(ENDCH, 0, 0, 0, 0, 0, 0) + } + } /*end of CountryTable */ +}; +#endif +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#endif /* _RLM_TXPWR_INIT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/roaming_fsm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/roaming_fsm.h new file mode 100644 index 0000000000000..e6cd038024cb5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/roaming_fsm.h @@ -0,0 +1,212 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: +*/ + +/*! \file "roaming_fsm.h" +* \brief This file defines the FSM for Roaming MODULE. +* +* This file defines the FSM for Roaming MODULE. +*/ + + +#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. */ +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP +#define ROAMING_ONE_AP_SKIP_TIMES 3 +#endif + +/* #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 enum _ENUM_ROAMING_REASON_T { + ROAMING_REASON_POOR_RCPI = 0, + ROAMING_REASON_TX_ERR, /*Lowest rate, high PER*/ + ROAMING_REASON_RETRY, + ROAMING_REASON_NUM +} ENUM_ROAMING_REASON_T; + +typedef struct _CMD_ROAMING_TRANSIT_T { + UINT_16 u2Event; + UINT_16 u2Data; + UINT_16 u2RcpiLowThreshold; + UINT_8 ucIsSupport11B; + UINT_8 aucReserved[1]; + ENUM_ROAMING_REASON_T eReason; + UINT_32 u4RoamingTriggerTime; /*sec in mcu*/ + UINT_8 aucReserved2[8]; +} CMD_ROAMING_TRANSIT_T, *P_CMD_ROAMING_TRANSIT_T; + + +typedef struct _CMD_ROAMING_CTRL_T { + UINT_8 fgEnable; + UINT_8 ucRcpiAdjustStep; + UINT_16 u2RcpiLowThr; + UINT_8 ucRoamingRetryLimit; + UINT_8 ucRoamingStableTimeout; + UINT_8 aucReserved[2]; +} CMD_ROAMING_CTRL_T, *P_CMD_ROAMING_CTRL_T; + +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP +typedef struct _CMD_ROAMING_SKIP_ONE_AP_T { + UINT_8 fgIsRoamingSkipOneAP; + UINT_8 aucReserved[3]; + UINT_8 aucReserved2[8]; +} CMD_ROAMING_SKIP_ONE_AP_T, *P_CMD_ROAMING_SKIP_ONE_AP_T; +#endif + + /**/ 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_CMD_ROAMING_TRANSIT_T prTransit); + +VOID roamingFsmScanResultsUpdate(IN P_ADAPTER_T prAdapter); + +VOID roamingFsmSteps(IN P_ADAPTER_T prAdapter, IN ENUM_ROAMING_STATE_T eNextState); + +VOID roamingFsmRunEventStart(IN P_ADAPTER_T prAdapter); + +VOID roamingFsmRunEventDiscovery(IN P_ADAPTER_T prAdapter, IN P_CMD_ROAMING_TRANSIT_T prTransit); + +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_CMD_ROAMING_TRANSIT_T prTransit); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _ROAMING_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rsn.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rsn.h new file mode 100644 index 0000000000000..82dd73290f914 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/rsn.h @@ -0,0 +1,287 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: include/mgmt/rsn.h#1 +*/ + +/*! \file rsn.h +* \brief The wpa/rsn related define, macro and structure are described here. +*/ + + +#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 +#if CFG_SUPPORT_CFG80211_AUTH +#define RSN_CIPHER_SUITE_GROUP_NOT_USED 0x07AC0F00 +#define RSN_CIPHER_SUITE_GCMP 0x08AC0F00 +#define RSN_CIPHER_SUITE_GCMP_256 0x09AC0F00 +#define RSN_CIPHER_SUITE_CCMP_256 0x0AAC0F00 +#define RSN_CIPHER_SUITE_BIP_GMAC_128 0x0BAC0F00 +#define RSN_CIPHER_SUITE_BIP_GMAC_256 0x0CAC0F00 +#define RSN_CIPHER_SUITE_BIP_CMAC_256 0x0DAC0F00 +#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 +#if CFG_SUPPORT_CFG80211_AUTH +#define RSN_AKM_SUITE_SAE 0x08AC0F00 +#define RSN_AKM_SUITE_8021X_SUITE_B 0x0BAC0F00 +#define RSN_AKM_SUITE_8021X_SUITE_B_192 0x0CAC0F00 +#define RSN_AKM_SUITE_OWE 0x12AC0F00 +#endif + +#define WPA_AKM_SUITE_NONE 0x00F25000 +#define WPA_AKM_SUITE_802_1X 0x01F25000 +#define WPA_AKM_SUITE_PSK 0x02F25000 +#if CFG_SUPPORT_CFG80211_AUTH +#define WLAN_CIPHER_SUITE_NO_GROUP_ADDR 0x000fac07 +#endif + +#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 */ +#if CFG_SUPPORT_SUITB +#define CIPHER_FLAG_GCMP256 0x00000080 /* BIT 7 */ +#endif + +#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 + + +#define GTK_REKEY_CMD_MODE_OFFLOAD_ON 0 +#define GTK_REKEY_CMD_MODE_OFLOAD_OFF 1 +#define GTK_REKEY_CMD_MODE_SET_BCMC_PN 2 +#define GTK_REKEY_CMD_MODE_GET_BCMC_PN 3 +#define GTK_REKEY_CMD_MODE_RPY_OFFLOAD_ON 4 +#define GTK_REKEY_CMD_MODE_RPY_OFFLOAD_OFF 5 + + +/******************************************************************************* +* 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) + +#define ELEM_MAX_LEN_ASSOC_RSP_WSC_IE (32 - ELEM_HDR_LEN) +#define ELEM_MAX_LEN_TIMEOUT_IE (5) + +/******************************************************************************* +* 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 rsnIsSuitableBSS(IN P_ADAPTER_T prAdapter, IN P_RSN_INFO_T prBssRsnInfo); + +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); + +#if CFG_SUPPORT_AAA +void rsnParserCheckForRSNCCMPPSK(P_ADAPTER_T prAdapter, P_RSN_INFO_ELEM_T prIe, P_STA_RECORD_T prStaRec, + PUINT_16 pu2StatusCode); +#endif + +VOID rsnTkipHandleMICFailure(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta, IN BOOLEAN fgErrorKeyType); + +VOID rsnSelectPmkidCandidateList(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); + +VOID rsnUpdatePmkidCandidateList(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); + +BOOLEAN rsnSearchPmkidEntry(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBssid, OUT PUINT_32 pu4EntryIndex); + +BOOLEAN rsnCheckPmkidCandicate(IN P_ADAPTER_T prAdapter); + +VOID rsnCheckPmkidCache(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBss); + +VOID rsnGeneratePmkidIndication(IN P_ADAPTER_T prAdapter); + +VOID rsnIndicatePmkidCand(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); +#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, IN ULONG ulParamPtr); + +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); + +UINT_16 rsnPmfCapableValidation(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_STA_RECORD_T prStaRec); + +VOID rsnPmfGenerateTimeoutIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + +void rsnApStartSaQuery(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +void rsnApSaQueryAction(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +#endif /* CFG_SUPPORT_802_11W */ + +#if CFG_SUPPORT_AAA +VOID rsnGenerateWSCIEForAssocRsp(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); +#endif + +#if CFG_SUPPORT_OWE +void rsnGenerateOWEIE(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo); + +UINT_32 rsnCalOweIELen(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucBssIndex, P_STA_RECORD_T prStaRec); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _RSN_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/scan.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/scan.h new file mode 100644 index 0000000000000..5c166b902735a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/scan.h @@ -0,0 +1,742 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: @(#) +*/ + +/*! \file "scan.h" +* \brief +* +*/ + + +#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))) + +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP +#define SCN_ROAM_MAX_BUFFER_SIZE (CFG_MAX_NUM_ROAM_BSS_LIST * ALIGN_4(sizeof(ROAM_BSS_DESC_T))) +#endif + +#define SCN_RM_POLICY_EXCLUDE_SPECIFIC_SSID BIT(4) /* Remove SCAN result except the connected one. */ + +#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. + */ +/* Remove entire SCAN result */ +#define SCN_RM_POLICY_ENTIRE BIT(5) + +#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. + */ +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP +#define REMOVE_TIMEOUT_TWO_DAY (60*60*24*2) +#endif + +#if 1 +#define SCN_BSS_DESC_REMOVE_TIMEOUT_SEC 30 +#define SCN_BSS_DESC_STALE_SEC 20 /* Scan Request Timeout */ +#else +#define SCN_BSS_DESC_REMOVE_TIMEOUT_SEC 5 /* Second. */ + /* This is used by POLICY TIMEOUT, + * If exceed this value, remove timeout BSS_DESC_T. + */ + +#endif + +#define SCN_PROBE_DELAY_MSEC 0 + +#define SCN_ADHOC_BSS_DESC_TIMEOUT_SEC 5 /* Second. */ + +#define SCN_NLO_NETWORK_CHANNEL_NUM (4) + +#define SCAN_DONE_DIFFERENCE 3 + +/*----------------------------------------------------------------------------*/ +/* MSG_SCN_SCAN_REQ */ +/*----------------------------------------------------------------------------*/ +#define SCAN_REQ_SSID_WILDCARD BIT(0) +#define SCAN_REQ_SSID_P2P_WILDCARD BIT(1) +#define SCAN_REQ_SSID_SPECIFIED BIT(2) + +/*----------------------------------------------------------------------------*/ +/* Support Multiple SSID SCAN */ +/*----------------------------------------------------------------------------*/ +#define SCN_SSID_MAX_NUM CFG_SCAN_SSID_MAX_NUM +#define SCN_SSID_MATCH_MAX_NUM CFG_SCAN_SSID_MATCH_MAX_NUM + +#if CFG_SUPPORT_AGPS_ASSIST +#define SCN_AGPS_AP_LIST_MAX_NUM 32 +#endif + +#define SCN_BSS_JOIN_FAIL_THRESOLD 5 +#define SCN_BSS_JOIN_FAIL_CNT_RESET_SEC 15 +#define SCN_BSS_JOIN_FAIL_RESET_STEP 2 + +#if CFG_SUPPORT_BATCH_SCAN +/*----------------------------------------------------------------------------*/ +/* SCAN_BATCH_REQ */ +/*----------------------------------------------------------------------------*/ +#define SCAN_BATCH_REQ_START BIT(0) +#define SCAN_BATCH_REQ_STOP BIT(1) +#define SCAN_BATCH_REQ_RESULT BIT(2) +#endif + +#define SCAN_NLO_CHECK_SSID_ONLY 0x00000001 +#define SCAN_NLO_DEFAULT_INTERVAL 30000 + +#define SCN_CTRL_SCAN_CHANNEL_LISTEN_TIME_ENABLE BIT(1) +#define SCN_CTRL_IGNORE_AIS_FIX_CHANNEL BIT(1) +#define SCN_CTRL_ENABLE BIT(0) + +#define SCN_CTRL_DEFAULT_SCAN_CTRL SCN_CTRL_IGNORE_AIS_FIX_CHANNEL + +#define SCN_SCAN_DONE_PRINT_BUFFER_LENGTH 200 +/******************************************************************************* +* 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_FW_SCAN_STATE_T { + FW_SCAN_STATE_IDLE = 0, /* 0 */ + FW_SCAN_STATE_SCAN_START, /* 1 */ + FW_SCAN_STATE_REQ_CHANNEL, /* 2 */ + FW_SCAN_STATE_SET_CHANNEL, /* 3 */ + FW_SCAN_STATE_DELAYED_ACTIVE_PROB_REQ, /* 4 */ + FW_SCAN_STATE_ACTIVE_PROB_REQ, /* 5 */ + FW_SCAN_STATE_LISTEN, /* 6 */ + FW_SCAN_STATE_SCAN_DONE, /* 7 */ + FW_SCAN_STATE_NLO_START, /* 8 */ + FW_SCAN_STATE_NLO_HIT_CHECK, /* 9 */ + FW_SCAN_STATE_NLO_STOP, /* 10 */ + FW_SCAN_STATE_BATCH_START, /* 11 */ + FW_SCAN_STATE_BATCH_CHECK, /* 12 */ + FW_SCAN_STATE_BATCH_STOP, /* 13 */ + FW_SCAN_STATE_NUM /* 14 */ +} ENUM_FW_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; + BOOLEAN fgIsVHTPresent; + + UINT_8 ucPhyTypeSet; /* Available PHY Type Set of this BSS */ + UINT_8 ucVhtCapNumSoundingDimensions; /* record from bcn or probe response*/ + + UINT_8 ucChannelNum; + + ENUM_CHNL_EXT_T eSco; /* Record bandwidth for association process */ + /*Some AP will send association resp by 40MHz BW */ + ENUM_CHANNEL_WIDTH_T eChannelWidth; /*VHT operation ie */ + UINT_8 ucCenterFreqS1; + UINT_8 ucCenterFreqS2; + 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; /* WF0 */ + UINT_8 ucRCPI1; /* WF1 */ + + 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; + BOOLEAN fgIsP2PReport; /* TRUE: report to upper layer */ + P_P2P_DEVICE_DESC_T prP2pDesc; + + UINT_8 aucIntendIfAddr[MAC_ADDR_LEN]; /* For IBSS, the SrcAddr is different from BSSID */ + /* UINT_8 ucDevCapabilityBitmap; *//* Device Capability Attribute. (P2P_DEV_CAPABILITY_XXXX) */ + /* UINT_8 ucGroupCapabilityBitmap; *//* Group Capability Attribute. (P2P_GROUP_CAPABILITY_XXXX) */ + + LINK_T rP2pDeviceList; + +/* P_LINK_T prP2pDeviceList; */ + + /* For + * 1. P2P Capability. + * 2. P2P Device ID. ( in aucSrcAddr[] ) + * 3. NOA (TODO:) + * 4. Extend Listen Timing. (Probe Rsp) (TODO:) + * 5. P2P Device Info. (Probe Rsp) + * 6. P2P Group Info. (Probe Rsp) + */ +#endif + + BOOLEAN fgIsIEOverflow; /* The received IE length exceed the maximum IE buffer size */ + UINT_16 u2RawLength; /* The byte count of aucRawBuf[] */ + UINT_16 u2IELength; /* The byte count of aucIEBuf[] */ + + ULARGE_INTEGER u8TimeStamp; /* Place u8TimeStamp before aucIEBuf[1] to force DW align */ + UINT_8 aucRawBuf[CFG_RAW_BUFFER_SIZE]; + UINT_8 aucIEBuf[CFG_IE_BUFFER_SIZE]; + UINT_8 ucJoinFailureCount; + OS_SYSTIME rJoinFailTime; + struct AIS_BLACKLIST_ITEM *prBlack; +}; + +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP +struct _ROAM_BSS_DESC_T { + LINK_ENTRY_T rLinkEntry; + UINT_8 ucSSIDLen; + UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; + OS_SYSTIME rUpdateTime; +}; +#endif + +typedef struct _SCAN_PARAM_T { /* Used by SCAN FSM */ + /* Active or Passive */ + ENUM_SCAN_TYPE_T eScanType; + + /* Network Type */ + UINT_8 ucBssIndex; + + /* 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; + + /* TODO: Find Specific Device Type. */ +#endif /* CFG_SUPPORT_P2P */ + + UINT_16 u2ChannelDwellTime; + UINT_16 u2TimeoutValue; + + BOOLEAN fgIsObssScan; + BOOLEAN fgIsScanV2; + + /* Run time flags */ + UINT_16 u2ProbeDelayTime; + + /* channel information */ + ENUM_SCAN_CHANNEL eScanChannel; + UINT_8 ucChannelListNum; + RF_CHANNEL_INFO_T arChnlInfoList[MAXIMUM_OPERATION_CHANNEL_LIST]; + + /* Feedback information */ + UINT_8 ucSeqNum; + + /* Information Element */ + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; + +} SCAN_PARAM_T, *P_SCAN_PARAM_T; + +typedef struct _NLO_PARAM_T { /* Used by SCAN FSM */ + SCAN_PARAM_T rScanParam; + + /* NLO */ + BOOLEAN fgStopAfterIndication; + UINT_8 ucFastScanIteration; + UINT_16 u2FastScanPeriod; + UINT_16 u2SlowScanPeriod; + + /* Match SSID */ + UINT_8 ucMatchSSIDNum; + UINT_8 ucMatchSSIDLen[SCN_SSID_MATCH_MAX_NUM]; + UINT_8 aucMatchSSID[SCN_SSID_MATCH_MAX_NUM][ELEM_MAX_LEN_SSID]; + + UINT_8 aucCipherAlgo[SCN_SSID_MATCH_MAX_NUM]; + UINT_16 au2AuthAlgo[SCN_SSID_MATCH_MAX_NUM]; + UINT_8 aucChannelHint[SCN_SSID_MATCH_MAX_NUM][SCN_NLO_NETWORK_CHANNEL_NUM]; + +} NLO_PARAM_T, *P_NLO_PARAM_T; + +typedef struct _SCAN_INFO_T { + ENUM_SCAN_STATE_T eCurrentState; /* Store the STATE variable of SCAN FSM */ + + OS_SYSTIME rLastScanCompletedTime; + + SCAN_PARAM_T rScanParam; + NLO_PARAM_T rNloParam; + + UINT_32 u4NumOfBssDesc; + + UINT_8 aucScanBuffer[SCN_MAX_BUFFER_SIZE]; + + LINK_T rBSSDescList; + + LINK_T rFreeBSSDescList; + + LINK_T rPendingMsgList; +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + UINT_8 aucScanRoamBuffer[SCN_ROAM_MAX_BUFFER_SIZE]; + LINK_T rRoamFreeBSSDescList; + LINK_T rRoamBSSDescList; +#endif + /* Sparse Channel Detection */ + BOOLEAN fgIsSparseChannelValid; + RF_CHANNEL_INFO_T rSparseChannel; + + /* NLO scanning state tracking */ + BOOLEAN fgNloScanning; + + /*channel idle count # Mike */ + UINT_8 ucSparseChannelArrayValidNum; + UINT_8 aucReserved[3]; + UINT_8 aucChannelNum[64]; + UINT_16 au2ChannelIdleTime[64]; + UINT_8 aucChannelFlag[64]; + UINT_8 aucChannelMDRDYCnt[64]; + +} 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 ucBssIndex; + 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]; + UINT_16 u2ChannelDwellTime; /* ms unit */ + UINT_16 u2TimeoutValue; /* ms unit */ + 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 ucBssIndex; + 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. */ + UINT_16 u2TimeoutValue; /* ms unit */ + 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 ucBssIndex; + BOOLEAN fgIsChannelExt; +} MSG_SCN_SCAN_CANCEL, *P_MSG_SCN_SCAN_CANCEL; + +typedef struct _tagOFFLOAD_NETWORK { + UINT_8 aucSsid[ELEM_MAX_LEN_SSID]; + UINT_8 ucSsidLen; + UINT_8 ucUnicastCipher; /* ENUM_NLO_CIPHER_ALGORITHM */ + UINT_16 u2AuthAlgo; /* ENUM_NLO_AUTH_ALGORITHM */ + UINT_8 aucChannelList[SCN_NLO_NETWORK_CHANNEL_NUM]; +} OFFLOAD_NETWORK, *P_OFFLOAD_NETWORK; + +typedef struct _MSG_SCN_NLO_REQ_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + BOOLEAN fgStopAfterIndication; + UINT_8 ucSeqNum; + UINT_8 ucBssIndex; + UINT_32 u4FastScanPeriod; + UINT_32 u4FastScanIterations; + UINT_32 u4SlowScanPeriod; + UINT_32 u4NumOfEntries; + OFFLOAD_NETWORK arNetwork[CFG_SCAN_SSID_MAX_NUM]; +} MSG_SCN_NLO_REQ, *P_MSG_SCN_NLO_REQ; + +typedef struct _MSG_SCN_NLO_CANCEL_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + UINT_8 ucBssIndex; +} MSG_SCN_NLO_CANCEL, *P_MSG_SCN_NLO_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 ucBssIndex; + ENUM_SCAN_STATUS eScanStatus; +} MSG_SCN_SCAN_DONE, *P_MSG_SCN_SCAN_DONE; + +#if CFG_SUPPORT_AGPS_ASSIST +typedef enum { + AGPS_PHY_A, + AGPS_PHY_B, + AGPS_PHY_G, +} AP_PHY_TYPE; + +typedef struct _AGPS_AP_INFO_T { + UINT_8 aucBSSID[MAC_ADDR_LEN]; + INT_16 i2ApRssi; /* -127..128 */ + UINT_16 u2Channel; /* 0..256 */ + AP_PHY_TYPE ePhyType; +} AGPS_AP_INFO_T, *P_AGPS_AP_INFO_T; + +typedef struct _AGPS_AP_LIST_T { + UINT_8 ucNum; + AGPS_AP_INFO_T arApInfo[SCN_AGPS_AP_LIST_MAX_NUM]; +} AGPS_AP_LIST_T, *P_AGPS_AP_LIST_T; +#endif + +typedef enum _ENUM_NLO_STATUS_T { + NLO_STATUS_FOUND = 0, + NLO_STATUS_CANCELLED, + NLO_STATUS_FAIL, + NLO_STATUS_BUSY, + NLO_STATUS_NUM +} ENUM_NLO_STATUS, *P_ENUM_NLO_STATUS; + +typedef struct _MSG_SCN_NLO_DONE_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + UINT_8 ucBssIndex; + ENUM_NLO_STATUS eNloStatus; +} MSG_SCN_NLO_DONE, *P_MSG_SCN_NLO_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); + +#if CFG_SUPPORT_CFG80211_AUTH +P_BSS_DESC_T +scanSearchBssDescByBssidAndChanNum(IN P_ADAPTER_T prAdapter, + IN UINT_8 aucBSSID[], IN BOOLEAN fgCheckChanNum, + IN UINT_8 ucChannelNum); +#endif +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 UINT_8 ucBssIndex); + +/* BSS-DESC State Change */ +VOID scanRemoveConnFlagOfBssDescByBssid(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]); + +/* 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 UINT_8 ucBssIndex); + +WLAN_STATUS scanAddScanResult(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc, IN P_SW_RFB_T prSwRfb); + +VOID scanReportBss2Cfg80211(IN P_ADAPTER_T prAdapter, IN ENUM_BSS_TYPE_T eBSSType, IN P_BSS_DESC_T SpecificprBssDesc); + +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP +P_ROAM_BSS_DESC_T scanSearchRoamBssDescBySsid(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); +P_ROAM_BSS_DESC_T scanAllocateRoamBssDesc(IN P_ADAPTER_T prAdapter); +VOID scanAddToRoamBssDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); +VOID scanSearchBssDescOfRoamSsid(IN P_ADAPTER_T prAdapter); +VOID scanRemoveRoamBssDescsByTime(IN P_ADAPTER_T prAdapter, IN UINT_32 u4RemoveTime); +#endif +/*----------------------------------------------------------------------------*/ +/* 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, BOOLEAN fgIsNewVersion); + +VOID scnEventNloDone(IN P_ADAPTER_T prAdapter, IN P_EVENT_NLO_DONE_T prNloDone); + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Handling */ +/*----------------------------------------------------------------------------*/ +VOID scnFsmMsgStart(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID scnFsmMsgAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID scnFsmHandleScanMsg(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_SCAN_REQ prScanReqMsg); + +VOID scnFsmHandleScanMsgV2(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_SCAN_REQ_V2 prScanReqMsg); + +VOID scnFsmRemovePendingMsg(IN P_ADAPTER_T prAdapter, IN UINT_8 ucSeqNum, IN UINT_8 ucBssIndex); + +VOID scnFsmNloMsgStart(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID scnFsmNloMsgAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID scnFsmHandleNloMsg(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_NLO_REQ prNloReqMsg); + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Generation */ +/*----------------------------------------------------------------------------*/ +VOID +scnFsmGenerateScanDoneMsg(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucSeqNum, IN UINT_8 ucBssIndex, IN ENUM_SCAN_STATUS eScanStatus); + +/*----------------------------------------------------------------------------*/ +/* Query for sparse channel */ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnQuerySparseChannel(IN P_ADAPTER_T prAdapter, P_ENUM_BAND_T prSparseBand, PUINT_8 pucSparseChannel); + +/*----------------------------------------------------------------------------*/ +/* OID/IOCTL Handling */ +/*----------------------------------------------------------------------------*/ +BOOLEAN +scnFsmSchedScanRequest(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucSsidNum, + IN P_PARAM_SSID_T prSsid, IN UINT_32 u4IeLength, IN PUINT_8 pucIe, IN UINT_16 u2Interval); + +BOOLEAN scnFsmSchedScanStopRequest(IN P_ADAPTER_T prAdapter); + +#if CFG_SUPPORT_PASSPOINT +P_BSS_DESC_T scanSearchBssDescByBssidAndLatestUpdateTime(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]); +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_AGPS_ASSIST +VOID scanReportScanResultToAgps(P_ADAPTER_T prAdapter); +#endif + +#if CFG_SCAN_CHANNEL_SPECIFIED +static inline bool is_valid_scan_chnl_cnt(UINT_8 num) +{ + return (num && num < MAXIMUM_OPERATION_CHANNEL_LIST); +} +#endif +#endif /* _SCAN_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/swcr.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/swcr.h new file mode 100644 index 0000000000000..b46e046cf3c01 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/swcr.h @@ -0,0 +1,247 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/swcr.h#1 +*/ + +/*! \file "swcr.h" +* \brief +*/ + +/* + * + */ + +#ifndef _SWCR_H +#define _SWCR_H + +#include "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 TEST_PS 1 + +#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) (ARRAY_SIZE(x)) + +#define SWCR_CR_NUM 7 + +#define SWCR_GET_RW_INDEX(action, rw, index) \ +do { \ + index = action & 0x7F; \ + rw = action >> 7; \ +} while (0) + +extern UINT_32 g_au4SwCr[]; /*: 0: command other: data */ + +typedef VOID(*PFN_SWCR_RW_T) (P_ADAPTER_T prAdapter, UINT_8 ucRead, UINT_16 u2Addr, UINT_32 *pu4Data); +typedef VOID(*PFN_CMD_RW_T) (P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1); + +typedef struct _SWCR_MAP_ENTRY_T { + UINT_16 u2Type; + PVOID u4Addr; +} SWCR_MAP_ENTRY_T, *P_SWCR_MAP_ENTRY_T; + +typedef struct _SWCR_MOD_MAP_ENTRY_T { + UINT_8 ucMapNum; + P_SWCR_MAP_ENTRY_T prSwCrMap; +} SWCR_MOD_MAP_ENTRY_T, *P_SWCR_MOD_MAP_ENTRY_T; + +typedef enum _ENUM_SWCR_DBG_TYPE_T { + SWCR_DBG_TYPE_ALL = 0, + SWCR_DBG_TYPE_TXRX, + SWCR_DBG_TYPE_RX_RATES, + SWCR_DBG_TYPE_PS, + SWCR_DBG_TYPE_NUM +} ENUM_SWCR_DBG_TYPE_T; + +typedef enum _ENUM_SWCR_DBG_ALL_T { + SWCR_DBG_ALL_TX_CNT = 0, + SWCR_DBG_ALL_TX_BCN_CNT, + SWCR_DBG_ALL_TX_FAILED_CNT, + SWCR_DBG_ALL_TX_RETRY_CNT, + SWCR_DBG_ALL_TX_AGING_TIMEOUT_CNT, + SWCR_DBG_ALL_TX_PS_OVERFLOW_CNT, + SWCR_DBG_ALL_TX_MGNT_DROP_CNT, + SWCR_DBG_ALL_TX_ERROR_CNT, + + SWCR_DBG_ALL_RX_CNT, + SWCR_DBG_ALL_RX_DROP_CNT, + SWCR_DBG_ALL_RX_DUP_DROP_CNT, + SWCR_DBG_ALL_RX_TYPE_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_CLASS_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_AMPDU_ERROR_DROP_CNT, + + SWCR_DBG_ALL_RX_STATUS_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_FORMAT_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_ICV_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_KEY_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_TKIP_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_MIC_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_BIP_ERROR_DROP_CNT, + + SWCR_DBG_ALL_RX_FCSERR_CNT, + SWCR_DBG_ALL_RX_FIFOFULL_CNT, + SWCR_DBG_ALL_RX_PFDROP_CNT, + + SWCR_DBG_ALL_PWR_PS_POLL_CNT, + SWCR_DBG_ALL_PWR_TRIGGER_NULL_CNT, + SWCR_DBG_ALL_PWR_BCN_IND_CNT, + SWCR_DBG_ALL_PWR_BCN_TIMEOUT_CNT, + SWCR_DBG_ALL_PWR_PM_STATE0, + SWCR_DBG_ALL_PWR_PM_STATE1, + SWCR_DBG_ALL_PWR_CUR_PS_PROF0, + SWCR_DBG_ALL_PWR_CUR_PS_PROF1, + + SWCR_DBG_ALL_AR_STA0_RATE, + SWCR_DBG_ALL_AR_STA0_BWGI, + SWCR_DBG_ALL_AR_STA0_RX_RATE_RCPI, + + SWCR_DBG_ALL_ROAMING_ENABLE, + SWCR_DBG_ALL_ROAMING_ROAM_CNT, + SWCR_DBG_ALL_ROAMING_INT_CNT, + + SWCR_DBG_ALL_BB_RX_MDRDY_CNT, + SWCR_DBG_ALL_BB_RX_FCSERR_CNT, + SWCR_DBG_ALL_BB_CCK_PD_CNT, + SWCR_DBG_ALL_BB_OFDM_PD_CNT, + SWCR_DBG_ALL_BB_CCK_SFDERR_CNT, + SWCR_DBG_ALL_BB_CCK_SIGERR_CNT, + SWCR_DBG_ALL_BB_OFDM_TAGERR_CNT, + SWCR_DBG_ALL_BB_OFDM_SIGERR_CNT, + + SWCR_DBG_ALL_NUM +} ENUM_SWCR_DBG_ALL_T; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* 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); + +#if CFG_SUPPORT_SWCR +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); +#if TEST_PS +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); +#endif +#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); +#endif +#endif +VOID swCtrlSwCr(P_ADAPTER_T prAdapter, UINT_8 ucRead, UINT_16 u2Addr, UINT_32 *pu4Data); + +/* Support Debug */ +VOID swCrDebugCheck(P_ADAPTER_T prAdapter, P_CMD_SW_DBG_CTRL_T prCmdSwCtrl); +VOID swCrDebugCheckTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr); +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); +#endif + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/tdls.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/tdls.h new file mode 100644 index 0000000000000..2449a1b1be7be --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/tdls.h @@ -0,0 +1,472 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: include/tdls.h#1 +*/ + +/*! \file "tdls.h" +* \brief This file contains the internal used in TDLS modules +* for MediaTek Inc. 802.11 Wireless LAN Adapters. +*/ + + +#ifndef _TDLS_H +#define _TDLS_H + +#include "wlan_typedef.h" + +#if CFG_SUPPORT_TDLS + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#define TDLS_CFG_CMD_TEST + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/* assign station record idx for the packet */ +#define TDLSEX_STA_REC_IDX_GET(__prAdapter__, __MsduInfo__) \ +{ \ + STA_RECORD_T *__StaRec__; \ + __MsduInfo__->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; \ + __StaRec__ = cnmGetStaRecByAddress(__prAdapter__, \ + (UINT_8) NETWORK_TYPE_AIS_INDEX,\ + __MsduInfo__->aucEthDestAddr); \ + if ((__StaRec__ != NULL) && (IS_DLS_STA(__StaRec__))) \ + __MsduInfo__->ucStaRecIndex = __StaRec__->ucIndex; \ +} + +/* fill wiphy flag */ +#define TDLSEX_WIPHY_FLAGS_INIT(__fgFlag__) \ +{ \ + __fgFlag__ |= (WIPHY_FLAG_SUPPORTS_TDLS | WIPHY_FLAG_TDLS_EXTERNAL_SETUP);\ +} + +#define LR_TDLS_FME_FIELD_FILL(__Len) \ +{ \ + pPkt += __Len; \ + u4PktLen += __Len; \ +} + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +extern int wlanHardStartXmit(struct sk_buff *prSkb, struct net_device *prDev); + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/* Status code */ +#define TDLS_STATUS WLAN_STATUS + +#define TDLS_STATUS_SUCCESS WLAN_STATUS_SUCCESS +#define TDLS_STATUS_FAIL WLAN_STATUS_FAILURE +#define TDLS_STATUS_INVALID_LENGTH WLAN_STATUS_INVALID_LENGTH +#define TDLS_STATUS_RESOURCES WLAN_STATUS_RESOURCES +#define TDLS_FME_MAC_ADDR_LEN 6 +#define TDLS_EX_CAP_PEER_UAPSD BIT(0) +#define TDLS_EX_CAP_CHAN_SWITCH BIT(1) +#define TDLS_EX_CAP_TDLS BIT(2) +#define TDLS_CMD_PEER_UPDATE_EXT_CAP_MAXLEN 5 +#define TDLS_CMD_PEER_UPDATE_SUP_RATE_MAX 50 +#define TDLS_CMD_PEER_UPDATE_SUP_CHAN_MAX 50 +#define TDLS_SEC_BUF_LENGTH 600 + + + +#define MAXNUM_TDLS_PEER 4 + +/* command */ +typedef enum _TDLS_CMD_ID { + TDLS_CMD_TEST_TX_FRAME = 0x00, + TDLS_CMD_TEST_RCV_FRAME, + TDLS_CMD_TEST_PEER_ADD, + TDLS_CMD_TEST_PEER_UPDATE, + TDLS_CMD_TEST_DATA_FRAME, + TDLS_CMD_TEST_RCV_NULL +} TDLS_CMD_ID; + +/* protocol */ +#define TDLS_FRM_PROT_TYPE 0x890d + +/* payload specific type in the LLC/SNAP header */ +#define TDLS_FRM_PAYLOAD_TYPE 2 + +#define TDLS_FRM_CATEGORY 12 + +typedef enum _TDLS_FRM_ACTION_ID { + TDLS_FRM_ACTION_SETUP_REQ = 0x00, + TDLS_FRM_ACTION_SETUP_RSP, + TDLS_FRM_ACTION_CONFIRM, + TDLS_FRM_ACTION_TEARDOWN, + TDLS_FRM_ACTION_PTI, + TDLS_FRM_ACTION_CHAN_SWITCH_REQ, + TDLS_FRM_ACTION_CHAN_SWITCH_RSP, + TDLS_FRM_ACTION_PEER_PSM_REQ, + TDLS_FRM_ACTION_PEER_PSM_RSP, + TDLS_FRM_ACTION_PTI_RSP, + TDLS_FRM_ACTION_DISCOVERY_REQ, + TDLS_FRM_ACTION_DISCOVERY_RSP = 0x0e, + TDLS_FRM_ACTION_EVENT_TEAR_DOWN_TO_SUPPLICANT = 0x30 +} TDLS_FRM_ACTION_ID; + +/* 7.3.2.62 Link Identifier element */ +#define ELEM_ID_LINK_IDENTIFIER 101 + +typedef struct _IE_LINK_IDENTIFIER_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aBSSID[6]; + UINT_8 aInitiator[6]; + UINT_8 aResponder[6]; +} __KAL_ATTRIB_PACKED__ IE_LINK_IDENTIFIER_T; + +#define TDLS_LINK_IDENTIFIER_IE(__ie__) ((IE_LINK_IDENTIFIER_T *)(__ie__)) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef struct _STATION_PRARAMETERS { + const u8 *supported_rates; + struct net_device *vlan; + u32 sta_flags_mask, sta_flags_set; + u32 sta_modify_mask; + int listen_interval; + u16 aid; + u8 supported_rates_len; + u8 plink_action; + u8 plink_state; + const struct ieee80211_ht_cap *ht_capa; + const struct ieee80211_vht_cap *vht_capa; + u8 uapsd_queues; + u8 max_sp; + /* enum nl80211_mesh_power_mode local_pm; */ + u16 capability; + const u8 *ext_capab; + u8 ext_capab_len; +} STATION_PRARAMETERS, P_STATION_PRARAMETERS; + +/* test command use */ +typedef struct _PARAM_CUSTOM_TDLS_CMD_STRUCT_T { + + UINT_8 ucFmeType; /* TDLS_FRM_ACTION_ID */ + + UINT_8 ucToken; + UINT_8 ucCap; + + /* bit0: TDLS, bit1: Peer U-APSD Buffer, bit2: Channel Switching */ + + UINT_8 ucExCap; + + UINT_8 arSupRate[4]; + UINT_8 arSupChan[4]; + + UINT_32 u4Timeout; + + UINT_8 arRspAddr[TDLS_FME_MAC_ADDR_LEN]; + UINT_8 arBssid[TDLS_FME_MAC_ADDR_LEN]; + + /* Linux Kernel-3.10 */ + + struct ieee80211_ht_cap rHtCapa; + struct ieee80211_vht_cap rVhtCapa; + /* struct */ + STATION_PRARAMETERS rPeerInfo; + +} PARAM_CUSTOM_TDLS_CMD_STRUCT_T; + +typedef enum _ENUM_TDLS_LINK_OPER { + TDLS_DISCOVERY_REQ, + TDLS_SETUP, + TDLS_TEARDOWN, + TDLS_ENABLE_LINK, + TDLS_DISABLE_LINK +} ENUM_TDLS_LINK_OPER; + +typedef struct _TDLS_CMD_LINK_OPER_T { + + UINT_8 aucPeerMac[6]; + enum nl80211_tdls_operation oper; +} TDLS_CMD_LINK_OPER_T; + +typedef struct _TDLS_CMD_LINK_MGT_T { + + UINT_8 aucPeer[6]; + UINT_8 ucActionCode; + UINT_8 ucDialogToken; + UINT_16 u2StatusCode; + UINT_32 u4SecBufLen; + UINT_8 aucSecBuf[TDLS_SEC_BUF_LENGTH]; + +} TDLS_CMD_LINK_MGT_T; + +typedef struct _TDLS_CMD_PEER_ADD_T { + + UINT_8 aucPeerMac[6]; + ENUM_STA_TYPE_T eStaType; +} TDLS_CMD_PEER_ADD_T; + +typedef struct _TDLS_CMD_PEER_UPDATE_HT_CAP_MCS_INFO_T { + UINT_8 arRxMask[SUP_MCS_RX_BITMASK_OCTET_NUM]; + UINT_16 u2RxHighest; + UINT_8 ucTxParams; + UINT_8 Reserved[3]; +} TDLS_CMD_PEER_UPDATE_HT_CAP_MCS_INFO_T; + +typedef struct _TDLS_CMD_PEER_UPDATE_VHT_CAP_MCS_INFO_T { + UINT_8 arRxMask[SUP_MCS_RX_BITMASK_OCTET_NUM]; +} TDLS_CMD_PEER_UPDATE_VHT_CAP_MCS_INFO_T; + +typedef struct _TDLS_CMD_PEER_UPDATE_HT_CAP_T { + UINT_16 u2CapInfo; + UINT_8 ucAmpduParamsInfo; + + /* 16 bytes MCS information */ + TDLS_CMD_PEER_UPDATE_HT_CAP_MCS_INFO_T rMCS; + + UINT_16 u2ExtHtCapInfo; + UINT_32 u4TxBfCapInfo; + UINT_8 ucAntennaSelInfo; +} TDLS_CMD_PEER_UPDATE_HT_CAP_T; + +typedef struct _TDLS_CMD_PEER_UPDATE_VHT_CAP_T { + UINT_16 u2CapInfo; + /* 16 bytes MCS information */ + TDLS_CMD_PEER_UPDATE_VHT_CAP_MCS_INFO_T rVMCS; + +} TDLS_CMD_PEER_UPDATE_VHT_CAP_T; + +typedef struct _TDLS_CMD_PEER_UPDATE_T { + + UINT_8 aucPeerMac[6]; + + UINT_8 aucSupChan[TDLS_CMD_PEER_UPDATE_SUP_CHAN_MAX]; + + UINT_16 u2StatusCode; + + UINT_8 aucSupRate[TDLS_CMD_PEER_UPDATE_SUP_RATE_MAX]; + UINT_16 u2SupRateLen; + + UINT_8 UapsdBitmap; + UINT_8 UapsdMaxSp; /* MAX_SP */ + + UINT_16 u2Capability; + + UINT_8 aucExtCap[TDLS_CMD_PEER_UPDATE_EXT_CAP_MAXLEN]; + UINT_16 u2ExtCapLen; + + TDLS_CMD_PEER_UPDATE_HT_CAP_T rHtCap; + TDLS_CMD_PEER_UPDATE_VHT_CAP_T rVHtCap; + + BOOLEAN fgIsSupHt; + ENUM_STA_TYPE_T eStaType; + +} TDLS_CMD_PEER_UPDATE_T; + +/* Command to TDLS core module */ +typedef enum _TDLS_CMD_CORE_ID { + TDLS_CORE_CMD_TEST_NULL_RCV = 0x00 +} TDLS_CMD_CORE_ID; + +typedef struct _TDLS_CMD_CORE_TEST_NULL_RCV_T { + + UINT_32 u4PM; +} TDLS_CMD_CORE_TEST_NULL_RCV_T; + +typedef struct _TDLS_CMD_CORE_T { + + UINT_32 u4Command; + + UINT_8 aucPeerMac[6]; + +#define TDLS_CMD_CORE_RESERVED_SIZE 50 + union { + TDLS_CMD_CORE_TEST_NULL_RCV_T rCmdNullRcv; + UINT_8 Reserved[TDLS_CMD_CORE_RESERVED_SIZE]; + } Content; +} TDLS_CMD_CORE_T; + +typedef enum _TDLS_EVENT_HOST_ID { + TDLS_HOST_EVENT_TEAR_DOWN = 0x00, + TDLS_HOST_EVENT_TX_DONE +} TDLS_EVENT_HOST_ID; + +typedef enum _TDLS_EVENT_HOST_SUBID_TEAR_DOWN { + TDLS_HOST_EVENT_TD_PTI_TIMEOUT = 0x00, + TDLS_HOST_EVENT_TD_AGE_TIMEOUT, + TDLS_HOST_EVENT_TD_PTI_SEND_FAIL, + TDLS_HOST_EVENT_TD_PTI_SEND_MAX_FAIL, + TDLS_HOST_EVENT_TD_WRONG_NETWORK_IDX, + TDLS_HOST_EVENT_TD_NON_STATE3, + TDLS_HOST_EVENT_TD_LOST_TEAR_DOWN +} TDLS_EVENT_HOST_SUBID_TEAR_DOWN; + +typedef enum _TDLS_REASON_CODE { + TDLS_REASON_CODE_UNREACHABLE = 25, + TDLS_REASON_CODE_UNSPECIFIED = 26, + + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_UNKNOWN = 0x80, /* 128 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_WIFI_OFF = 0x81, /* 129 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_ROAMING = 0x82, /* 130 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_TIMEOUT = 0x83, /* 131 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_AGE_TIMEOUT = 0x84, /* 132 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_REKEY = 0x85, /* 133 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_SEND_FAIL = 0x86, /* 134 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_SEND_MAX_FAIL = 0x87, /* 135 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_WRONG_NETWORK_IDX = 0x88, /* 136 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_NON_STATE3 = 0x89, /* 137 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_TX_QUOTA_EMPTY = 0x8a, /* 138 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_LOST_TEAR_DOWN = 0x8b /* 139 */ +} TDLS_REASON_CODE; + +/******************************************************************************* +* P U B 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 +******************************************************************************** +*/ +UINT_32 TdlsFrameGeneralIeAppend(ADAPTER_T *prAdapter, STA_RECORD_T *prStaRec, UINT_8 *pPkt); + +WLAN_STATUS /* TDLS_STATUS */ + +TdlsDataFrameSend_TearDown(ADAPTER_T *prAdapter, + STA_RECORD_T *prStaRec, + UINT_8 *pPeerMac, + UINT_8 ucActionCode, + UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen); + +WLAN_STATUS /* TDLS_STATUS */ + +TdlsDataFrameSend_CONFIRM(ADAPTER_T *prAdapter, + STA_RECORD_T *prStaRec, + UINT_8 *pPeerMac, + UINT_8 ucActionCode, + UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen); + +WLAN_STATUS /* TDLS_STATUS */ + +TdlsDataFrameSend_SETUP_REQ(ADAPTER_T *prAdapter, + STA_RECORD_T *prStaRec, + UINT_8 *pPeerMac, + UINT_8 ucActionCode, + UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen); + +WLAN_STATUS /* TDLS_STATUS */ + +TdlsDataFrameSend_DISCOVERY_REQ(ADAPTER_T *prAdapter, + STA_RECORD_T *prStaRec, + UINT_8 *pPeerMac, + UINT_8 ucActionCode, + UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen); + +WLAN_STATUS /* TDLS_STATUS */ + +TdlsDataFrameSend_SETUP_RSP(ADAPTER_T *prAdapter, + STA_RECORD_T *prStaRec, + UINT_8 *pPeerMac, + UINT_8 ucActionCode, + UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen); + +WLAN_STATUS /* TDLS_STATUS */ + +TdlsDataFrameSend_DISCOVERY_RSP(ADAPTER_T *prAdapter, + STA_RECORD_T *prStaRec, + UINT_8 *pPeerMac, + UINT_8 ucActionCode, + UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen); + +UINT_32 TdlsexLinkOper(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, PUINT_32 pu4SetInfoLen); + +UINT_32 TdlsexLinkMgt(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, PUINT_32 pu4SetInfoLen); + +VOID TdlsexEventHandle(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +VOID TdlsEventTearDown(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +VOID TdlsBssExtCapParse(P_STA_RECORD_T prStaRec, P_UINT_8 pucIE); + +WLAN_STATUS +TdlsSendChSwControlCmd(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +TdlsTxCtrl(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, BOOLEAN fgEnable); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* CFG_SUPPORT_TDLS */ + +#endif /* _TDLS_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/wapi.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/wapi.h new file mode 100644 index 0000000000000..f65d81e1b0f4d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/wapi.h @@ -0,0 +1,130 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +#ifndef _WAPI_H +#define _WAPI_H + +#if CFG_SUPPORT_WAPI + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define WAPI_CIPHER_SUITE_WPI 0x01721400 /* WPI_SMS4 */ +#define WAPI_AKM_SUITE_802_1X 0x01721400 /* WAI */ +#define WAPI_AKM_SUITE_PSK 0x02721400 /* WAI_PSK */ + +#define ELEM_ID_WAPI 68 /* WAPI IE */ + +#define WAPI_IE(fp) ((P_WAPI_INFO_ELEM_T) fp) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +VOID wapiGenerateWAPIIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +BOOLEAN wapiParseWapiIE(IN P_WAPI_INFO_ELEM_T prInfoElem, OUT P_WAPI_INFO_T prWapiInfo); + +BOOLEAN wapiPerformPolicySelection(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBss); + +/* BOOLEAN */ +/* wapiUpdateTxKeyIdx ( */ +/* IN P_STA_RECORD_T prStaRec, */ +/* IN UINT_8 ucWlanIdx */ +/* ); */ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif +#endif /* _WAPI_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/wlan_typedef.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/wlan_typedef.h new file mode 100644 index 0000000000000..7725ff1685ba1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/wlan_typedef.h @@ -0,0 +1,140 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +#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 struct _BSS_INFO_T P2P_DEV_INFO_T, *P_P2P_DEV_INFO_T; + +#if 0 /* Marked for MT6630 */ +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; +#endif + +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; + +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP +typedef struct _ROAM_BSS_DESC_T ROAM_BSS_DESC_T, *P_ROAM_BSS_DESC_T, **PP_ROAM_BSS_DESC_T; +#endif + +#if CFG_SUPPORT_PASSPOINT +typedef struct _HS20_INFO_T HS20_INFO_T, *P_HS20_INFO_T; +#endif /* CFG_SUPPORT_PASSPOINT */ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _WLAN_TYPEDEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/wnm.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/wnm.h new file mode 100644 index 0000000000000..58c2b08e881cd --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/mgmt/wnm.h @@ -0,0 +1,129 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +#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/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/adapter.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/adapter.h new file mode 100644 index 0000000000000..ef1c9879fb532 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/adapter.h @@ -0,0 +1,1478 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/adapter.h#5 +*/ + +/*! \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. +*/ + +#ifndef _ADAPTER_H +#define _ADAPTER_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#if CFG_SUPPORT_CSI +#define CSI_RING_SIZE 1000 +#define CSI_MAX_DATA_COUNT 256 +#define CSI_MAX_RSVD1_COUNT 10 +#endif + + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#if CFG_SUPPORT_PASSPOINT +#include "hs20.h" +#endif /* CFG_SUPPORT_PASSPOINT */ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +enum { + ENUM_SW_TEST_MODE_NONE = 0, + ENUM_SW_TEST_MODE_SIGMA_AC = 0x1, + ENUM_SW_TEST_MODE_SIGMA_WFD = 0x2, + ENUM_SW_TEST_MODE_CTIA = 0x3, + ENUM_SW_TEST_MODE_SIGMA_TDLS = 0x4, + ENUM_SW_TEST_MODE_SIGMA_P2P = 0x5, + ENUM_SW_TEST_MODE_SIGMA_N = 0x6, + ENUM_SW_TEST_MODE_SIGMA_HS20_R1 = 0x7, + ENUM_SW_TEST_MODE_SIGMA_HS20_R2 = 0x8, + ENUM_SW_TEST_MODE_SIGMA_PMF = 0x9, + ENUM_SW_TEST_MODE_SIGMA_WMMPS = 0xA, + ENUM_SW_TEST_MODE_SIGMA_AC_R2 = 0xB, + ENUM_SW_TEST_MODE_SIGMA_NAN = 0xC, + ENUM_SW_TEST_MODE_SIGMA_AC_AP = 0xD, + ENUM_SW_TEST_MODE_SIGMA_N_AP = 0xE, + ENUM_SW_TEST_MODE_SIGMA_WFDS = 0xF, + ENUM_SW_TEST_MODE_SIGMA_WFD_R2 = 0x10, + ENUM_SW_TEST_MODE_SIGMA_LOCATION = 0x11, + ENUM_SW_TEST_MODE_SIGMA_TIMING_MANAGEMENT = 0x12, + ENUM_SW_TEST_MODE_SIGMA_WMMAC = 0x13, + ENUM_SW_TEST_MODE_SIGMA_VOICE_ENT = 0x14 +}; + +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[BSS_INFO_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 *//* Not used */ + UINT_8 uc5GBandwidthMode; /* 20/40M or 20M only *//* Not used */ + +#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; + +#if CFG_SUPPORT_CFG80211_AUTH + struct cfg80211_bss *bss; + + BOOLEAN fgIsConnInitialized; + + BOOLEAN fgIsSendAssoc; + + BOOLEAN ucAuthDataLen; + /* Temp assign a fixed large number + * Additional elements for Authentication frame, + * starts with the Authentication transaction sequence number field + */ + BOOLEAN aucAuthData[AUTH_DATA_MAX_LEN]; + UINT_8 ucChannelNum; +#endif +#if CFG_SUPPORT_OWE + /* for OWE info store, when upper layer set rsn info */ + struct OWE_INFO_T rOweInfo; +#endif + struct LINK_MGMT rBlackList; +} CONNECTION_SETTINGS_T, *P_CONNECTION_SETTINGS_T; + +struct _BSS_INFO_T { + + ENUM_NETWORK_TYPE_T eNetworkType; + + UINT_32 u4PrivateData; /* Private data parameter for each NETWORK type usage. */ + /* P2P network type has 3 network interface to distinguish. */ + + 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 + +#if (CFG_SUPPORT_DFS_MASTER == 1) + BOOLEAN fgIsDfsActive; +#endif + + BOOLEAN fgIsInUse; /* For CNM to assign BSS_INFO */ + BOOLEAN fgIsNetActive; /* TRUE if this network has been activated */ + + UINT_8 ucBssIndex; /* BSS_INFO_T index */ + + 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 */ + + UINT_8 ucOwnMacIndex; /* Owned MAC index 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_8 ucBMCWlanIndex; /* For open Mode, BC/MC Tx wlan index, For STA, BC/MC Rx wlan index */ + + UINT_8 ucBMCWlanIndexS[MAX_KEY_NUM]; /* For AP Mode, BC/MC Tx wlan index, For STA, BC/MC Rx wlan index */ + UINT_8 ucBMCWlanIndexSUsed[MAX_KEY_NUM]; + + BOOLEAN fgBcDefaultKeyExist; /* Bc Transmit key exist or not */ + UINT_8 ucBcDefaultKeyIdx; /* Bc default key idx, for STA, the Rx just set, for AP, the tx key id */ + + UINT_8 wepkeyUsed[MAX_KEY_NUM]; + UINT_8 wepkeyWlanIdx; /* wlan index of the wep key */ + + 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_SW]; + + 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 */ + + BOOLEAN fgIsWepCipherGroup; + UINT_32 u4RsnSelectedGroupCipher; + UINT_32 u4RsnSelectedPairwiseCipher; + UINT_32 u4RsnSelectedAKMSuite; + UINT_16 u2RsnSelectedCapInfo; + + UINT_8 ucOpChangeChannelWidth; /* The OpMode channel width that we want to change to*/ + /* 0:20MHz, 1:40MHz, 2:80MHz, 3:160MHz 4:80+80MHz */ + BOOLEAN fgIsOpChangeChannelWidth; + + /*------------------------------------------------------------------------*/ + /* 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 */ + UINT_8 ucWmmQueSet; +#if (CFG_HW_WMM_BY_BSS == 1) + BOOLEAN fgIsWmmInited; +#endif + + /*------------------------------------------------------------------------*/ + /* 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_8 ucHtPeerOpInfo1; /*Backup peer HT OP Info*/ + UINT_16 u2HtOpInfo2; + UINT_16 u2HtOpInfo3; + UINT_8 ucNss; + /*------------------------------------------------------------------------*/ + /* 802.11ac VHT operation IE when (prStaRec->ucPhyTypeSet & PHY_TYPE_BIT_VHT) */ + /* is true. They have the same definition with fields of */ + /* information element (EASON) */ + /*------------------------------------------------------------------------*/ +#if 1 /* CFG_SUPPORT_802_11AC */ + UINT_8 ucVhtChannelWidth; + UINT_8 ucVhtChannelFrequencyS1; + UINT_8 ucVhtChannelFrequencyS2; + UINT_16 u2VhtBasicMcsSet; + + /* Backup peer VHT OpInfo */ + UINT_8 ucVhtPeerChannelWidth; + UINT_8 ucVhtPeerChannelFrequencyS1; + UINT_8 ucVhtPeerChannelFrequencyS2; +#endif + /*------------------------------------------------------------------------*/ + /* 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_16 u2HwDefaultFixedRateCode; /* The default rate code copied to MAC TX Desc */ + UINT_16 u2HwLPWakeupGuardTimeUsec; + + UINT_8 ucBssFreeQuota; /* The value is updated from FW */ + +#if CFG_ENABLE_GTK_FRAME_FILTER + P_IPV4_NETWORK_ADDRESS_LIST prIpV4NetAddrList; +#endif + UINT_16 u2DeauthReason; + +#if CFG_SUPPORT_TDLS + BOOLEAN fgTdlsIsProhibited; + BOOLEAN fgTdlsIsChSwProhibited; +#endif +#if CFG_SUPPORT_PNO + BOOLEAN fgIsPNOEnable; + BOOLEAN fgIsNetRequestInActive; +#endif + + WIFI_WMM_AC_STAT_T arLinkStatistics[WMM_AC_INDEX_NUM]; /*link layer statistics */ + + ENUM_DBDC_BN_T eDBDCBand; + + UINT_32 u4CoexPhyRateLimit; + +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + UINT_8 ucRoamSkipTimes; + BOOLEAN fgGoodRcpiArea; + BOOLEAN fgPoorRcpiArea; +#endif + + BOOLEAN fgIsGranted; + ENUM_BAND_T eBandGranted; + UINT_8 ucPrimaryChannelGranted; + PARAM_CUSTOM_ACL rACL; + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + struct AP_PMF_CFG rApPmfCfg; +#endif + +#if CFG_SUPPORT_REPLAY_DETECTION + struct SEC_DETECT_REPLAY_INFO rDetRplyInfo; +#endif + +}; + +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 ucTxWlanIndex; *//* Legacy wep, adhoc wep wpa Transmit key wlan index */ + + /* BOOLEAN fgKeyMaterialExist[4]; */ + /* UINT_8 aucKeyMaterial[32][4]; */ + +#if 0 + BOOLEAN fgWepWapiBcKeyExist; /* WEP WAPI BC key exist flag */ + UINT_8 ucWepWapiBcWlanIndex; /* WEP WAPI BC wlan index */ + + BOOLEAN fgRsnBcKeyExist[4]; /* RSN BC key exist flag, map to key id 0, 1, 2, 3 */ + UINT_8 ucRsnBcWlanIndex[4]; /* RSN BC wlan index, map to key id 0, 1, 2, 3 */ +#endif + + /* 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; + BOOLEAN fgAPApplyPmfReq; + 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 + +typedef struct _WLAN_TABLE_T { + UINT_8 ucUsed; + UINT_8 ucBssIndex; + UINT_8 ucKeyId; + UINT_8 ucPairwise; + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + UINT_8 ucStaIndex; +} WLAN_TABLE_T, *P_WLAN_TABLE_T; + +/* 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[BSS_INFO_NUM]; + + BSS_INFO_T arBssInfoPool[BSS_INFO_NUM]; + + P2P_DEV_INFO_T rP2pDevInfo; + + AIS_SPECIFIC_BSS_INFO_T rAisSpecificBssInfo; + +#if CFG_ENABLE_WIFI_DIRECT + P_P2P_CONNECTION_SETTINGS_T prP2PConnSettings[BSS_P2P_NUM]; + + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo[BSS_P2P_NUM]; + +/* P_P2P_FSM_INFO_T prP2pFsmInfo; */ + + P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo; + + /* Currently we only support 2 p2p interface. */ + P_P2P_ROLE_FSM_INFO_T aprP2pRoleFsmInfo[BSS_P2P_NUM]; + +#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 */ + + WLAN_TABLE_T arWtbl[WTBL_SIZE]; + + 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; + +#if CFG_SUPPORT_WFD + WFD_CFG_SETTINGS_T rWfdConfigureSettings; +#endif + +#if CFG_SLT_SUPPORT + SLT_INFO_T rSltInfo; +#endif + +#if CFG_SUPPORT_PASSPOINT + HS20_INFO_T rHS20Info; +#endif /* CFG_SUPPORT_PASSPOINT */ + UINT_8 aucMediatekOuiIE[64]; + UINT_16 u2MediatekOuiIELen; + + /* Feature Options */ + UINT_8 ucQoS; + + UINT_8 ucStaHt; + UINT_8 ucStaVht; + UINT_8 ucApHt; + UINT_8 ucApVht; + UINT_8 ucP2pGoHt; + UINT_8 ucP2pGoVht; + UINT_8 ucP2pGcHt; + UINT_8 ucP2pGcVht; + + UINT_8 ucAmpduTx; + UINT_8 ucAmpduRx; + UINT_8 ucAmsduInAmpduTx; + UINT_8 ucAmsduInAmpduRx; + UINT_8 ucHtAmsduInAmpduTx; + UINT_8 ucHtAmsduInAmpduRx; + UINT_8 ucVhtAmsduInAmpduTx; + UINT_8 ucVhtAmsduInAmpduRx; + UINT_8 ucTspec; + UINT_8 ucUapsd; + UINT_8 ucStaUapsd; + UINT_8 ucApUapsd; + UINT_8 ucP2pUapsd; + + UINT_8 ucTxShortGI; + UINT_8 ucRxShortGI; + UINT_8 ucTxLdpc; + UINT_8 ucRxLdpc; + UINT_8 ucTxStbc; + UINT_8 ucRxStbc; + UINT_8 ucRxStbcNss; + UINT_8 ucTxGf; + UINT_8 ucRxGf; + + UINT_8 ucMCS32; + + UINT_8 ucTxopPsTx; + UINT_8 ucSigTaRts; + UINT_8 ucDynBwRts; + + UINT_8 ucStaHtBfee; + UINT_8 ucStaVhtBfee; + UINT_8 ucStaHtBfer; + UINT_8 ucStaVhtBfer; + UINT_8 ucStaVhtMuBfee; + + UINT_8 ucDataTxDone; + UINT_8 ucDataTxRateMode; + UINT_32 u4DataTxRateCode; + + UINT_8 ucApWpsMode; + UINT_8 ucApChannel; + + UINT_8 ucApSco; + UINT_8 ucP2pGoSco; + + UINT_8 ucStaBandwidth; + UINT_8 ucSta5gBandwidth; + UINT_8 ucSta2gBandwidth; + UINT_8 ucApBandwidth; + UINT_8 ucAp2gBandwidth; + UINT_8 ucAp5gBandwidth; + UINT_8 ucP2p5gBandwidth; + UINT_8 ucP2p2gBandwidth; + + /* If enable, AP channel bandwidth Channel Center Frequency Segment 0/1 */ + /* and secondary channel offset will align wifi.cfg */ + /* Otherwise align cfg80211 */ + UINT_8 ucApChnlDefFromCfg; + + /* + * According TGn/TGac 4.2.44, AP should not connect + * to TKIP client with * HT/VHT capabilities. We leave + * a wifi.cfg item for user to decide whether * to + * enable HT/VHT capabilities in that case + */ + UINT_8 ucApAllowHtVhtTkip; + + UINT_8 ucNSS; + + UINT_8 ucRxMaxMpduLen; + UINT_32 u4TxMaxAmsduInAmpduLen; + + UINT_8 ucTxBaSize; + UINT_8 ucRxHtBaSize; + UINT_8 ucRxVhtBaSize; + + UINT_8 ucStaDisconnectDetectTh; + UINT_8 ucApDisconnectDetectTh; + UINT_8 ucP2pDisconnectDetectTh; + + UINT_8 ucThreadScheduling; + UINT_8 ucThreadPriority; + INT_8 cThreadNice; + + UINT_8 ucTcRestrict; + UINT_32 u4MaxTxDeQLimit; + UINT_8 ucAlwaysResetUsedRes; + + UINT_32 u4NetifStopTh; + UINT_32 u4NetifStartTh; +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + PARAM_GET_CHN_INFO rChnLoadInfo; +#endif +#if CFG_SUPPORT_MTK_SYNERGY + UINT_8 ucMtkOui; + UINT_32 u4MtkOuiCap; + UINT_8 aucMtkFeature[4]; +#endif + + BOOLEAN fgCsaInProgress; + UINT_8 ucChannelSwitchMode; + UINT_8 ucNewChannelNumber; + UINT_8 ucChannelSwitchCount; + + UINT_32 u4HifIstLoopCount; + UINT_32 u4Rx2OsLoopCount; + UINT_32 u4HifTxloopCount; + UINT_32 u4TxRxLoopCount; + UINT_32 u4TxFromOsLoopCount; + UINT_32 u4TxIntThCount; + + UINT_32 au4TcPageCount[TC_NUM]; + UINT_8 ucExtraTxDone; + UINT_8 ucTxDbg; + + UINT_8 ucCmdRsvResource; + UINT_32 u4MgmtQueueDelayTimeout; + + UINT_32 u4StatsLogTimeout; + UINT_32 u4StatsLogDuration; + UINT_8 ucDhcpTxDone; + UINT_8 ucArpTxDone; + + UINT_8 ucMacAddrOverride; + UINT_8 aucMacAddrStr[32]; + + UINT_8 ucCtiaMode; + UINT_8 ucTpTestMode; + UINT_8 ucSigmaTestMode; +#if CFG_SUPPORT_DBDC + UINT_8 ucDbdcMode; + BOOLEAN fgDbDcModeEn; + TIMER_T rDBDCDisableCountdownTimer; /* Prevent continuously trigger by reconnection */ + TIMER_T rDBDCSwitchGuardTimer; /* Prevent switch too quick*/ +#endif + UINT_8 u4ScanCtrl; + UINT_8 ucScanChannelListenTime; + +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1) + UINT_8 ucEfuseBufferModeCal; +#endif + UINT_8 ucCalTimingCtrl; + UINT_8 ucWow; + UINT_8 ucOffload; + UINT_8 ucAdvPws; /* enable LP multiple DTIM function, default disable */ + UINT_8 ucWowOnMdtim; /* multiple DTIM if WOW enable, default 1 */ + UINT_8 ucWowOffMdtim; /* multiple DTIM if WOW disable, default 3 */ + UINT_8 ucWowPwsMode; /* when enter wow, automatically enter wow power-saving profile */ + UINT_8 ucListenDtimInterval; /* adjust the listen interval by dtim interval */ + UINT_8 ucEapolOffload; /* eapol offload when active mode / wow mode */ + +#if CFG_SUPPORT_REPLAY_DETECTION + UINT_8 ucRpyDetectOffload; /* eapol offload when active mode / wow mode */ +#endif + + UINT_8 u4SwTestMode; + UINT_8 ucCtrlFlagAssertPath; + UINT_8 ucCtrlFlagDebugLevel; + UINT_32 u4WakeLockRxTimeout; + UINT_32 u4WakeLockThreadWakeup; + UINT_32 u4RegP2pIfAtProbe; /* register p2p interface during probe */ + UINT_8 ucP2pShareMacAddr; /* p2p group interface use the same mac addr as p2p device interface */ + UINT_8 ucSmartRTS; + + UINT_32 u4UapsdAcBmp; + UINT_32 u4MaxSpLen; + UINT_32 fgDisOnlineScan; /* 0: enable online scan, non-zero: disable online scan */ + UINT_32 fgDisBcnLostDetection; + UINT_32 fgDisRoaming; /* 0:enable roaming 1:disable */ + UINT_32 fgEnArpFilter; + + UINT_8 uDeQuePercentEnable; + UINT_32 u4DeQuePercentVHT80Nss1; + UINT_32 u4DeQuePercentVHT40Nss1; + UINT_32 u4DeQuePercentVHT20Nss1; + UINT_32 u4DeQuePercentHT40Nss1; + UINT_32 u4DeQuePercentHT20Nss1; + + BOOLEAN fgTdlsBufferSTASleep; /* Support TDLS 5.5.4.2 optional case */ + BOOLEAN fgChipResetRecover; + + UINT_8 ucN9Log2HostCtrl; + UINT_8 ucCR4Log2HostCtrl; + +#if CFG_SUPPORT_ANT_SELECT + UINT_8 ucSpeIdxCtrl; /* 0:WF0, 1:WF1, 2: both WF0/1 */ +#endif +#ifdef CFG_SUPPORT_ADJUST_JOIN_CH_REQ_INTERVAL + UINT_32 u4AisJoinChReqIntervel; +#endif +} WIFI_VAR_T, *P_WIFI_VAR_T; /* end of _WIFI_VAR_T */ + +/* cnm_timer module */ +typedef struct { + LINK_T rLinkHead; + OS_SYSTIME rNextExpiredSysTime; +#if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) + KAL_WAKE_LOCK_T rWakeLock; +#endif + 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 */ + /* N9 SW */ + UINT_16 u2FwProductID; + UINT_16 u2FwOwnVersion; + UINT_16 u2FwPeerVersion; + UINT_8 ucFwBuildNumber; + UINT_8 aucFwBranchInfo[4]; + UINT_8 aucFwDateCode[16]; + + /* N9 tailer */ + tailer_format_t rN9tailer; + + /* CR4 tailer */ + tailer_format_t rCR4tailer; +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + /* N9 Compressed tailer */ + tailer_format_t_2 rN9Compressedtailer; + /* CR4 tailer */ + tailer_format_t_2 rCR4Compressedtailer; + BOOLEAN fgIsN9CompressedFW; + BOOLEAN fgIsCR4CompressedFW; +#endif + /* Patch header */ + PATCH_FORMAT_T rPatchHeader; + BOOLEAN fgPatchIsDlByDrv; +} 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 + +typedef struct _WIFI_FEM_CFG_T { + /* WiFi FEM path */ + UINT_16 u2WifiPath; + UINT_16 u2Reserved; + /* Reserved */ + UINT_32 au4Reserved[4]; +} WIFI_FEM_CFG_T, *P_WIFI_FEM_CFG_T; + +#if CFG_SUPPORT_CSI +/* + * CSI_DATA_T is used for representing + * the CSI and other useful * information + * for application usage + */ +struct CSI_DATA_T { + UINT_8 ucBw; + BOOLEAN bIsCck; + UINT_16 u2DataCount; + INT_16 ac2IData[CSI_MAX_DATA_COUNT]; + INT_16 ac2QData[CSI_MAX_DATA_COUNT]; + UINT_8 ucDbdcIdx; + INT_8 cRssi; + UINT_8 ucSNR; + UINT_64 u8TimeStamp; + UINT_8 ucDataBw; + UINT_8 ucPrimaryChIdx; + UINT_8 aucTA[MAC_ADDR_LEN]; + UINT_32 u4ExtraInfo; + UINT_8 ucRxMode; + INT_32 ai4Rsvd1[CSI_MAX_RSVD1_COUNT]; + INT_32 au4Rsvd2[CSI_MAX_RSVD1_COUNT]; + UINT_8 ucRsvd1Cnt; + INT_32 i4Rsvd3; + UINT_8 ucRsvd4; +}; + +/* + * CSI_INFO_T is used to store the CSI + * settings and CSI event data + */ +struct CSI_INFO_T { + /* Variables for manipulate the CSI data in g_aucProcBuf */ + BOOLEAN bIncomplete; + INT_32 u4CopiedDataSize; + INT_32 u4RemainingDataSize; + wait_queue_head_t waitq; + /* Variable for recording the CSI function config */ + UINT_8 ucMode; + UINT_8 ucValue1[CSI_CONFIG_ITEM_NUM]; + UINT_8 ucValue2[CSI_CONFIG_ITEM_NUM]; + /* Variable for manipulating the CSI ring buffer */ + struct CSI_DATA_T arCSIBuffer[CSI_RING_SIZE]; + UINT_32 u4CSIBufferHead; + UINT_32 u4CSIBufferTail; + UINT_32 u4CSIBufferUsed; + INT_16 ai2TempIData[CSI_MAX_DATA_COUNT]; + INT_16 ai2TempQData[CSI_MAX_DATA_COUNT]; +}; +#endif + + +/* + * Major ADAPTER structure + * Major data structure for driver operation + */ +struct _ADAPTER_T { + struct mt66xx_chip_info *chip_info; + UINT_8 ucRevID; + BOOLEAN fgIsReadRevID; + + 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 */ + BOOLEAN fgAllMulicastFilter; /* mDNS filter used by OS */ + + P_BSS_INFO_T aprBssInfo[HW_BSSID_NUM + 1]; + P_BSS_INFO_T prAisBssInfo; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + BOOLEAN fgIsSupportCsumOffload; /* Does FW support Checksum Offload feature */ + UINT_32 u4CSUMFlags; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + ENUM_BAND_T aePreferBand[BSS_INFO_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 */ + + UINT_32 u4CoalescingBufCachedSize; + PUINT_8 pucCoalescingBufCached; + + /* 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; + + /* Timer for restarting RFB setup procedure */ + TIMER_T rPacketDelaySetupTimer; + + /* Buffer for Authentication Event */ + /* Move to glue layer and refine the kal function */ + /* Reference to rsnGeneratePmkidIndication function at rsn.c */ + UINT_8 aucIndicationEventBuffer[(CFG_MAX_PMKID_CACHE * 20) + 8]; + + UINT_32 u4IntStatus; + + ENUM_ACPI_STATE_T rAcpiState; + + BOOLEAN fgIsIntEnable; + BOOLEAN fgIsIntEnableWithLPOwnSet; + + BOOLEAN fgIsFwOwn; + BOOLEAN fgWiFiInSleepyState; + + /* Set by callback to make sure WOW process done before system suspend */ + BOOLEAN fgSetPfCapabilityDone; + BOOLEAN fgSetWowDone; + + BOOLEAN fgForceFwOwn; + + OS_SYSTIME rLastOwnFailedLogTime; + UINT_32 u4OwnFailedCount; + UINT_32 u4OwnFailedLogCount; + + UINT_32 u4PwrCtrlBlockCnt; + + /* TX Direct related : BEGIN */ + BOOLEAN fgTxDirectInited; + + #define TX_DIRECT_CHECK_INTERVAL (1000 * HZ / USEC_PER_SEC) + struct timer_list rTxDirectSkbTimer; /* check if an empty MsduInfo is available */ + struct timer_list rTxDirectHifTimer; /* check if HIF port is ready to accept a new Msdu */ + + struct sk_buff_head rTxDirectSkbQueue; + QUE_T rTxDirectHifQueue[TX_PORT_NUM]; + + QUE_T rStaPsQueue[CFG_STA_REC_NUM]; + UINT_32 u4StaPsBitmap; + QUE_T rBssAbsentQueue[HW_BSSID_NUM + 1]; + UINT_32 u4BssAbsentBitmap; + /* TX Direct related : END */ + + QUE_T rPendingCmdQueue; + +#if CFG_SUPPORT_MULTITHREAD + QUE_T rTxCmdQueue; + QUE_T rTxCmdDoneQueue; +#if CFG_FIX_2_TX_PORT + QUE_T rTxP0Queue; + QUE_T rTxP1Queue; +#else + QUE_T rTxPQueue[TX_PORT_NUM]; +#endif + QUE_T rRxQueue; + QUE_T rTxDataDoneQueue; +#endif + + P_GLUE_INFO_T prGlueInfo; + + UINT_8 ucCmdSeqNum; + UINT_8 ucTxSeqNum; + UINT_8 aucPidPool[WTBL_SIZE]; + +#if 1 /* CFG_SUPPORT_WAPI */ + BOOLEAN fgUseWapi; +#endif + + /* RF Test flags */ + BOOLEAN fgTestMode; + BOOLEAN fgIcapMode; + + /* WLAN Info for DRIVER_CORE OID query */ + WLAN_INFO_T rWlanInfo; + +#if CFG_ENABLE_WIFI_DIRECT + BOOLEAN fgIsP2PRegistered; + BOOLEAN p2p_scan_report_all_bss; /* flag to report all networks in p2p scan */ + 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; + +#if CFG_SUPPORT_MSP + EVENT_WLAN_INFO rEventWlanInfo; +#endif + +#if CFG_SUPPORT_LAST_SEC_MCS_INFO + TIMER_T rRxMcsInfoTimer; + BOOLEAN fgIsMcsInfoValid; +#endif + + 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; + UINT_8 ucOidTimeoutCount; + + /* Root Timer for cnm_timer module */ + ROOT_TIMER rRootTimer; + + BOOLEAN fgIsChipNoAck; + BOOLEAN fgIsChipAssert; + + /* 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; + + /* Bitmap is defined as #define KEEP_FULL_PWR_{FEATURE}_BIT in wlan_lib.h + * Each feature controls KeepFullPwr(CMD_ID_KEEP_FULL_PWR) should + * register bitmap to ensure low power during suspend. + */ + UINT_32 u4IsKeepFullPwrBitmap; + + UINT_32 fgEnArpFilter; + + UINT_32 u4UapsdAcBmp; + + UINT_32 u4MaxSpLen; + + UINT_32 u4PsCurrentMeasureEn; + + /* Version Information */ + WIFI_VER_INFO_T rVerInfo; + + /* 5GHz support (from F/W) */ + BOOLEAN fgIsHw5GBandDisabled; + BOOLEAN fgEnable5GBand; + BOOLEAN fgIsEepromUsed; + BOOLEAN fgIsEfuseValid; + BOOLEAN fgIsEmbbededMacAddrValid; + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + BOOLEAN fgIsPowerLimitTableValid; +#endif + + /* Packet Forwarding Tracking */ + INT_32 i4PendingFwdFrameCount; + +#if CFG_SUPPORT_RDD_TEST_MODE + UINT_8 ucRddStatus; +#endif + + BOOL fgDisStaAgingTimeoutDetection; + + UINT_32 u4FwCompileFlag0; + UINT_32 u4FwCompileFlag1; + UINT_32 u4FwFeatureFlag0; + UINT_32 u4FwFeatureFlag1; + +#if CFG_SUPPORT_CFG_FILE + P_WLAN_CFG_T prWlanCfg; + WLAN_CFG_T rWlanCfg; + + P_WLAN_CFG_REC_T prWlanCfgRec; + WLAN_CFG_REC_T rWlanCfgRec; +#endif + +#if CFG_M0VE_BA_TO_DRIVER + TIMER_T rMqmIdleRxBaDetectionTimer; + UINT_32 u4FlagBitmap; +#endif +#if CFG_ASSERT_DUMP + TIMER_T rN9CorDumpTimer; + TIMER_T rCr4CorDumpTimer; + BOOLEAN fgN9CorDumpFileOpend; + BOOLEAN fgCr4CorDumpFileOpend; + BOOLEAN fgN9AssertDumpOngoing; + BOOLEAN fgCr4AssertDumpOngoing; + BOOLEAN fgKeepPrintCoreDump; +#endif + /* Tx resource information */ + BOOLEAN fgIsNicTxReousrceValid; + NIC_TX_RESOURCE_T nicTxReousrce; + + /* Efuse Start and End address */ + UINT_32 u4EfuseStartAddress; + UINT_32 u4EfuseEndAddress; + + /* COEX feature */ + UINT_32 u4FddMode; + +#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1) + /* MAC address Efuse Offset */ + UINT_32 u4EfuseMacAddrOffset; +#endif + +#if CFG_WOW_SUPPORT + WOW_CTRL_T rWowCtrl; +#endif + +/*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ + UINT_8 aucEepromVaule[16]; /* HQA CMD for Efuse Block size contents */ + UINT_32 u4FreeBlockNum; + UINT_32 u4GetTxPower; +/*#endif*/ + BOOLEAN fgIsCr4FwDownloaded; + BOOLEAN fgIsFwDownloaded; + BOOLEAN fgIsSupportBufferBinSize16Byte; + BOOLEAN fgIsSupportDelayCal; + BOOLEAN fgIsSupportGetFreeEfuseBlockCount; + BOOLEAN fgIsSupportQAAccessEfuse; + BOOLEAN fgIsSupportPowerOnSendBufferModeCMD; + BOOLEAN fgIsBufferBinExtract; + BOOLEAN fgIsSupportGetTxPower; + BOOLEAN fgIsEnableLpdvt; + + /* SER related info */ + UINT_8 ucSerState; + +#if CFG_SUPPORT_BFER + BOOLEAN fgIsHwSupportBfer; +#endif + +#if (CFG_HW_WMM_BY_BSS == 1) + UINT_8 ucHwWmmEnBit; +#endif + WIFI_FEM_CFG_T rWifiFemCfg; + + UINT_8 ucRModeOnlyFlag; + UINT_8 ucRModeReserve[7]; + +#if CFG_SUPPORT_CSI + struct CSI_INFO_T rCSIInfo; +#endif + + +}; /* 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 argument _BssIndex */ +#define IS_NET_ACTIVE(_prAdapter, _BssIndex) \ + ((_prAdapter)->aprBssInfo[(_BssIndex)]->fgIsNetActive) + +/* Macros for argument _prBssInfo */ +#define IS_BSS_ACTIVE(_prBssInfo) ((_prBssInfo)->fgIsNetActive) + +#define IS_BSS_AIS(_prBssInfo) \ + ((_prBssInfo)->eNetworkType == NETWORK_TYPE_AIS) + +#define IS_BSS_P2P(_prBssInfo) \ + ((_prBssInfo)->eNetworkType == NETWORK_TYPE_P2P) + +#define IS_BSS_BOW(_prBssInfo) \ + ((_prBssInfo)->eNetworkType == NETWORK_TYPE_BOW) + +#define SET_NET_ACTIVE(_prAdapter, _BssIndex) \ + {(_prAdapter)->aprBssInfo[(_BssIndex)]->fgIsNetActive = TRUE; } + +#define UNSET_NET_ACTIVE(_prAdapter, _BssIndex) \ + {(_prAdapter)->aprBssInfo[(_BssIndex)]->fgIsNetActive = FALSE; } + +#define BSS_INFO_INIT(_prAdapter, _prBssInfo) \ + { UINT_8 _aucZeroMacAddr[] = NULL_MAC_ADDR; \ + \ + (_prBssInfo)->eConnectionState = PARAM_MEDIA_STATE_DISCONNECTED; \ + (_prBssInfo)->eConnectionStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; \ + (_prBssInfo)->eCurrentOPMode = OP_MODE_INFRASTRUCTURE; \ + (_prBssInfo)->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_RESERVED; \ + COPY_MAC_ADDR((_prBssInfo)->aucBSSID, _aucZeroMacAddr); \ + LINK_INITIALIZE(&((_prBssInfo)->rStaRecOfClientList)); \ + (_prBssInfo)->fgIsBeaconActivated = FALSE; \ + (_prBssInfo)->u2HwDefaultFixedRateCode = RATE_CCK_1M_LONG; \ + } + +/*----------------------------------------------------------------------------*/ +/* Macros for Power State */ +/*----------------------------------------------------------------------------*/ +#define SET_NET_PWR_STATE_IDLE(_prAdapter, _BssIndex) \ + {_prAdapter->rWifiVar.aePwrState[(_BssIndex)] = PWR_STATE_IDLE; } + +#define SET_NET_PWR_STATE_ACTIVE(_prAdapter, _BssIndex) \ + {_prAdapter->rWifiVar.aePwrState[(_BssIndex)] = PWR_STATE_ACTIVE; } + +#define SET_NET_PWR_STATE_PS(_prAdapter, _BssIndex) \ + {_prAdapter->rWifiVar.aePwrState[(_BssIndex)] = PWR_STATE_PS; } + +#define IS_NET_PWR_STATE_ACTIVE(_prAdapter, _BssIndex) \ + (_prAdapter->rWifiVar.aePwrState[(_BssIndex)] == PWR_STATE_ACTIVE) + +#define IS_NET_PWR_STATE_IDLE(_prAdapter, _BssIndex) \ + (_prAdapter->rWifiVar.aePwrState[(_BssIndex)] == 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) + +#define IS_WIFI_2G4_WF0_SUPPORT(_prAdapter) \ + ((_prAdapter)->rWifiFemCfg.u2WifiPath & WLAN_FLAG_2G4_WF0) + +#define IS_WIFI_5G_WF0_SUPPORT(_prAdapter) \ + ((_prAdapter)->rWifiFemCfg.u2WifiPath & WLAN_FLAG_5G_WF0) + +#define IS_WIFI_2G4_WF1_SUPPORT(_prAdapter) \ + ((_prAdapter)->rWifiFemCfg.u2WifiPath & WLAN_FLAG_2G4_WF1) + +#define IS_WIFI_5G_WF1_SUPPORT(_prAdapter) \ + ((_prAdapter)->rWifiFemCfg.u2WifiPath & WLAN_FLAG_5G_WF1) + +#define IS_WIFI_2G4_SISO(_prAdapter) \ + ((IS_WIFI_2G4_WF0_SUPPORT(_prAdapter) && !(IS_WIFI_2G4_WF1_SUPPORT(_prAdapter))) || \ + (IS_WIFI_2G4_WF1_SUPPORT(_prAdapter) && !(IS_WIFI_2G4_WF0_SUPPORT(_prAdapter)))) + +#define IS_WIFI_5G_SISO(_prAdapter) \ + ((IS_WIFI_5G_WF0_SUPPORT(_prAdapter) && !(IS_WIFI_5G_WF1_SUPPORT(_prAdapter))) || \ + (IS_WIFI_5G_WF1_SUPPORT(_prAdapter) && !(IS_WIFI_5G_WF0_SUPPORT(_prAdapter)))) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _ADAPTER_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/bow.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/bow.h new file mode 100644 index 0000000000000..bdd798c0842cb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/bow.h @@ -0,0 +1,266 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/bow.h#1 +*/ + + +#ifndef _BOW_H_ +#define _BOW_H_ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define BOWDEVNAME "bow0" + +#define MAX_BOW_NUMBER_OF_CHANNEL_2G4 14 +#define MAX_BOW_NUMBER_OF_CHANNEL_5G 4 +/* (MAX_BOW_NUMBER_OF_CHANNEL_2G4 + MAX_BOW_NUMBER_OF_CHANNEL_5G) */ +#define MAX_BOW_NUMBER_OF_CHANNEL 18 + +#define MAX_ACTIVITY_REPORT 2 +#define MAX_ACTIVITY_REPROT_TIME 660 + +#define ACTIVITY_REPORT_STATUS_SUCCESS 0 +#define ACTIVITY_REPORT_STATUS_FAILURE 1 +#define ACTIVITY_REPORT_STATUS_TIME_INVALID 2 +#define ACTIVITY_REPORT_STATUS_OTHERS 3 + +#define ACTIVITY_REPORT_SCHEDULE_UNKNOWN 0 /* Does not know the schedule of the interference */ +#define ACTIVITY_REPORT_SCHEDULE_KNOWN 1 + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef struct _BT_OVER_WIFI_COMMAND_HEADER_T { + UINT_8 ucCommandId; + UINT_8 ucSeqNumber; + UINT_16 u2PayloadLength; +} AMPC_COMMAND_HEADER_T, *P_AMPC_COMMAND_HEADER_T; + +typedef struct _BT_OVER_WIFI_COMMAND { + AMPC_COMMAND_HEADER_T rHeader; + UINT_8 aucPayload[0]; +} AMPC_COMMAND, *P_AMPC_COMMAND; + +typedef struct _BT_OVER_WIFI_EVENT_HEADER_T { + UINT_8 ucEventId; + UINT_8 ucSeqNumber; + UINT_16 u2PayloadLength; +} AMPC_EVENT_HEADER_T, *P_AMPC_EVENT_HEADER_T; + +typedef struct _BT_OVER_WIFI_EVENT { + AMPC_EVENT_HEADER_T rHeader; + UINT_8 aucPayload[0]; +} AMPC_EVENT, *P_AMPC_EVENT; + +typedef struct _CHANNEL_DESC_T { + UINT_8 ucChannelBand; + UINT_8 ucChannelNum; +} CHANNEL_DESC, P_CHANNEL_DESC; + +/* Command Structures */ +typedef struct _BOW_SETUP_CONNECTION { +/* Fixed to 2.4G */ + UINT_8 ucChannelNum; + UINT_8 ucReserved1; + UINT_8 aucPeerAddress[6]; + UINT_16 u2BeaconInterval; + UINT_8 ucTimeoutDiscovery; + UINT_8 ucTimeoutInactivity; + UINT_8 ucRole; + UINT_8 ucPAL_Capabilities; + INT_8 cMaxTxPower; + UINT_8 ucReserved2; + +/* Pending, for future BOW 5G supporting. */ +/* UINT_8 aucPeerAddress[6]; + * UINT_16 u2BeaconInterval; + * UINT_8 ucTimeoutDiscovery; + * UINT_8 ucTimeoutInactivity; + * UINT_8 ucRole; + * UINT_8 ucPAL_Capabilities; + * INT_8 cMaxTxPower; + * UINT_8 ucChannelListNum; + * CHANNEL_DESC arChannelList[1]; + */ +} BOW_SETUP_CONNECTION, *P_BOW_SETUP_CONNECTION; + +typedef struct _BOW_DESTROY_CONNECTION { + UINT_8 aucPeerAddress[6]; + UINT_8 aucReserved[2]; +} BOW_DESTROY_CONNECTION, *P_BOW_DESTROY_CONNECTION; + +typedef struct _BOW_SET_PTK { + UINT_8 aucPeerAddress[6]; + UINT_8 aucReserved[2]; + UINT_8 aucTemporalKey[16]; +} BOW_SET_PTK, *P_BOW_SET_PTK; + +typedef struct _BOW_READ_RSSI { + UINT_8 aucPeerAddress[6]; + UINT_8 aucReserved[2]; +} BOW_READ_RSSI, *P_BOW_READ_RSSI; + +typedef struct _BOW_READ_LINK_QUALITY { + UINT_8 aucPeerAddress[6]; + UINT_8 aucReserved[2]; +} BOW_READ_LINK_QUALITY, *P_BOW_READ_LINK_QUALITY; + +typedef struct _BOW_SHORT_RANGE_MODE { + UINT_8 aucPeerAddress[6]; + INT_8 cTxPower; + UINT_8 ucReserved; +} BOW_SHORT_RANGE_MODE, *P_BOW_SHORT_RANGE_MODE; + +/* Event Structures */ +typedef struct _BOW_COMMAND_STATUS { + UINT_8 ucStatus; + UINT_8 ucReserved[3]; +} BOW_COMMAND_STATUS, *P_BOW_COMMAND_STATUS; + +typedef struct _BOW_MAC_STATUS { + UINT_8 aucMacAddr[6]; + UINT_8 ucAvailability; + UINT_8 ucNumOfChannel; + CHANNEL_DESC arChannelList[MAX_BOW_NUMBER_OF_CHANNEL]; +} BOW_MAC_STATUS, *P_BOW_MAC_STATUS; + +typedef struct _BOW_LINK_CONNECTED { + CHANNEL_DESC rChannel; + UINT_8 aucReserved; + UINT_8 aucPeerAddress[6]; +} BOW_LINK_CONNECTED, *P_BOW_LINK_CONNECTED; + +typedef struct _BOW_LINK_DISCONNECTED { + UINT_8 ucReason; + UINT_8 aucReserved; + UINT_8 aucPeerAddress[6]; +} BOW_LINK_DISCONNECTED, *P_BOW_LINK_DISCONNECTED; + +typedef struct _BOW_RSSI { + INT_8 cRssi; + UINT_8 aucReserved[3]; +} BOW_RSSI, *P_BOW_RSSI; + +typedef struct _BOW_LINK_QUALITY { + UINT_8 ucLinkQuality; + UINT_8 aucReserved[3]; +} BOW_LINK_QUALITY, *P_BOW_LINK_QUALITY; + +typedef enum _ENUM_BOW_CMD_ID_T { + BOW_CMD_ID_GET_MAC_STATUS = 1, + BOW_CMD_ID_SETUP_CONNECTION, + BOW_CMD_ID_DESTROY_CONNECTION, + BOW_CMD_ID_SET_PTK, + BOW_CMD_ID_READ_RSSI, + BOW_CMD_ID_READ_LINK_QUALITY, + BOW_CMD_ID_SHORT_RANGE_MODE, + BOW_CMD_ID_GET_CHANNEL_LIST, +} ENUM_BOW_CMD_ID_T, *P_ENUM_BOW_CMD_ID_T; + +typedef enum _ENUM_BOW_EVENT_ID_T { + BOW_EVENT_ID_COMMAND_STATUS = 1, + BOW_EVENT_ID_MAC_STATUS, + BOW_EVENT_ID_LINK_CONNECTED, + BOW_EVENT_ID_LINK_DISCONNECTED, + BOW_EVENT_ID_RSSI, + BOW_EVENT_ID_LINK_QUALITY, + BOW_EVENT_ID_CHANNEL_LIST, + BOW_EVENT_ID_CHANNEL_SELECTED, +} ENUM_BOW_EVENT_ID_T, *P_ENUM_BOW_EVENT_ID_T; + +typedef enum _ENUM_BOW_DEVICE_STATE { + BOW_DEVICE_STATE_DISCONNECTED = 0, + BOW_DEVICE_STATE_DISCONNECTING, + BOW_DEVICE_STATE_ACQUIRING_CHANNEL, + BOW_DEVICE_STATE_STARTING, + BOW_DEVICE_STATE_SCANNING, + BOW_DEVICE_STATE_CONNECTING, + BOW_DEVICE_STATE_CONNECTED, + BOW_DEVICE_STATE_NUM +} ENUM_BOW_DEVICE_STATE, *P_ENUM_BOW_DEVICE_STATE; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#endif /*_BOW_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/cmd_buf.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/cmd_buf.h new file mode 100644 index 0000000000000..3b97da6e36a1b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/cmd_buf.h @@ -0,0 +1,194 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +#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); + +typedef VOID(*PFN_HIF_TX_CMD_DONE_CB) (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_MSDU_INFO_T prMsduInfo; /* only valid when it's a security/MGMT frame */ + P_NATIVE_PACKET prPacket; /* only valid when it's a security frame */ + + PFN_CMD_DONE_HANDLER pfCmdDoneHandler; + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler; + PFN_HIF_TX_CMD_DONE_CB pfHifTxCmdDoneCb; + + BOOLEAN fgIsOid; /* Used to check if we need indicate */ + + UINT_8 ucCID; + BOOLEAN fgSetQuery; + BOOLEAN fgNeedResp; + 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; + + /* TXD/TXP pointer/len for hif tx copy */ + UINT_32 u4TxdLen; + UINT_32 u4TxpLen; + PUINT_8 pucTxd; + PUINT_8 pucTxp; +}; + +/******************************************************************************* +* P U B 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); + +#if CFG_SUPPORT_TX_BF +WLAN_STATUS +wlanSendSetQueryExtCmd(IN P_ADAPTER_T prAdapter, + UINT_8 ucCID, + UINT_8 ucExtCID, + 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 + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _CMD_BUF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/hal.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/hal.h new file mode 100644 index 0000000000000..fb36d2e7f683e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/hal.h @@ -0,0 +1,1080 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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 +*/ + + +#ifndef _HAL_H +#define _HAL_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/* Macros for flag operations for the Adapter structure */ +#define HAL_SET_FLAG(_M, _F) ((_M)->u4HwFlags |= (_F)) +#define HAL_CLEAR_FLAG(_M, _F) ((_M)->u4HwFlags &= ~(_F)) +#define HAL_TEST_FLAG(_M, _F) ((_M)->u4HwFlags & (_F)) +#define HAL_TEST_FLAGS(_M, _F) (((_M)->u4HwFlags & (_F)) == (_F)) + +#if defined(_HIF_SDIO) +#define HAL_MCR_RD(_prAdapter, _u4Offset, _pu4Value) \ +do { \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (_u4Offset > 0xFFFF) { \ + if (kalDevRegRead_mac(_prAdapter->prGlueInfo, _u4Offset, _pu4Value) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, \ + "HAL_MCR_RD (MAC) access fail! 0x%x: 0x%x\n", \ + (UINT_32) (_u4Offset), *((PUINT_32) (_pu4Value))); \ + } \ + } else { \ + if (kalDevRegRead(_prAdapter->prGlueInfo, _u4Offset, _pu4Value) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, \ + "HAL_MCR_RD (SDIO) access fail! 0x%x: 0x%x\n", \ + (UINT_32) (_u4Offset), *((PUINT_32) (_pu4Value))); \ + } \ + } \ + } else { \ + DBGLOG(HAL, WARN, "ignore HAL_MCR_RD access! 0x%x\n", \ + (UINT_32) (_u4Offset)); \ + } \ +} while (0) + +#define HAL_MCR_WR(_prAdapter, _u4Offset, _u4Value) \ +do { \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (_u4Offset > 0xFFFF) { \ + if (kalDevRegWrite_mac(_prAdapter->prGlueInfo, _u4Offset, _u4Value) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, \ + "HAL_MCR_WR (MAC) access fail! 0x%x: 0x%x\n", \ + (UINT_32) (_u4Offset), (UINT_32) (_u4Value)); \ + } \ + } else { \ + if (kalDevRegWrite(_prAdapter->prGlueInfo, _u4Offset, _u4Value) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, \ + "HAL_MCR_WR (SDIO) access fail! 0x%x: 0x%x\n", \ + (UINT_32) (_u4Offset), (UINT_32) (_u4Value)); \ + } \ + } \ + } else { \ + DBGLOG(HAL, WARN, "ignore HAL_MCR_WR access! 0x%x: 0x%x\n", \ + (UINT_32) (_u4Offset), (UINT_32) (_u4Value)); \ + } \ +} while (0) + +#define HAL_PORT_RD(_prAdapter, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ +{ \ + /*fgResult = FALSE; */\ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (kalDevPortRead(_prAdapter->prGlueInfo, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, "HAL_PORT_RD access fail! 0x%x\n", \ + (UINT_32) (_u4Port)); \ + } \ + else { \ + /*fgResult = TRUE;*/ } \ + } else { \ + DBGLOG(HAL, WARN, "ignore HAL_PORT_RD access! 0x%x\n", \ + (UINT_32) (_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", \ + (UINT_32) (_u4Port)); \ + } \ + else \ + ; /*fgResult = TRUE;*/ \ + } else { \ + DBGLOG(HAL, WARN, "ignore HAL_PORT_WR access! 0x%x\n", \ + (UINT_32) (_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", \ + (UINT_32)(_u4Port)); \ + } \ + else { \ + /* Todo:: Nothing*/ \ + } \ + } \ + else { \ + DBGLOG(HAL, WARN, "ignore HAL_BYTE_WR access! 0x%x\n", \ + (UINT_32) (_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); \ + } \ + if (kalDevRegRead(_prAdapter->prGlueInfo, _u4Offset, _pu4Value) \ + == FALSE) { \ + DBGLOG(HAL, ERROR, "[USB] kalDevRegRead fail\n"); \ + } \ +} + +#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) \ +{ \ + HAL_MCR_WR(_prAdapter, _u4Port, (UINT_32)_ucBuf); \ +} + +#endif /* #if defined(_HIF_SDIO) */ + +#define HAL_WRITE_TX_DATA(_prAdapter, _prMsduInfo) \ +{ \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + kalDevWriteData(_prAdapter->prGlueInfo, _prMsduInfo); \ +} + +#define HAL_KICK_TX_DATA(_prAdapter) \ +{ \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + kalDevKickData(_prAdapter->prGlueInfo); \ +} + +#define HAL_WRITE_TX_CMD(_prAdapter, _prCmdInfo, _ucTC) \ +{ \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + kalDevWriteCmd(_prAdapter->prGlueInfo, _prCmdInfo, _ucTC); \ +} + +#if defined(_HIF_PCIE) +#define HAL_READ_RX_PORT(prAdapter, u4PortId, u4Len, pvBuf, _u4ValidBufSize) \ +{ \ + ASSERT(u4PortId < 2); \ + HAL_PORT_RD(prAdapter, \ + u4PortId, \ + u4Len, \ + pvBuf, \ + _u4ValidBufSize/*temp!!*//*4Kbyte*/) \ +} + +#define HAL_WRITE_TX_PORT(_prAdapter, _u4PortId, _u4Len, _pucBuf, _u4ValidBufSize) \ +{ \ + HAL_PORT_WR(_prAdapter, \ + _u4PortId, \ + _u4Len, \ + _pucBuf, \ + _u4ValidBufSize/*temp!!*//*4KByte*/) \ +} + +#define HAL_MCR_RD_AND_WAIT(_pAdapter, _offset, _pReadValue, _waitCondition, _waitDelay, _waitCount, _status) + +#define HAL_MCR_WR_AND_WAIT(_pAdapter, _offset, _writeValue, _busyMask, _waitDelay, _waitCount, _status) + +#define HAL_GET_CHIP_ID_VER(_prAdapter, pu2ChipId, pu2Version) \ +{ \ + UINT_32 u4Value; \ + HAL_MCR_RD(_prAdapter, HIF_SYS_REV, &u4Value); \ + *pu2ChipId = ((u4Value & PCIE_HIF_SYS_PROJ) >> 16); \ + *pu2Version = (u4Value & PCIE_HIF_SYS_REV); \ +} + +#define HAL_WIFI_FUNC_READY_CHECK(_prAdapter, _checkItem, _pfgResult) \ +do { \ + struct mt66xx_chip_info *prChipInfo; \ + UINT_32 u4Value = 0; \ + if (!_prAdapter->chip_info) \ + ASSERT(0); \ + *_pfgResult = FALSE; \ + prChipInfo = _prAdapter->chip_info; \ + HAL_MCR_RD(_prAdapter, prChipInfo->sw_sync0, &u4Value); \ + if ((u4Value & (_checkItem << prChipInfo->sw_ready_bit_offset)) \ + == (_checkItem << prChipInfo->sw_ready_bit_offset)) \ + *_pfgResult = TRUE; \ +} while (0) + +#define HAL_WIFI_FUNC_OFF_CHECK(_prAdapter, _checkItem, _pfgResult) \ +do { \ + struct mt66xx_chip_info *prChipInfo; \ + UINT_32 u4Value; \ + BOOLEAN fgLpOwnResult; \ + if (!_prAdapter->chip_info) \ + ASSERT(0); \ + *_pfgResult = FALSE; \ + prChipInfo = _prAdapter->chip_info; \ + HAL_MCR_RD(_prAdapter, prChipInfo->sw_sync0, &u4Value); \ + if ((u4Value & (_checkItem << prChipInfo->sw_ready_bit_offset)) == 0) { \ + *_pfgResult = TRUE; \ + } else { \ + HAL_LP_OWN_RD(_prAdapter, &fgLpOwnResult); \ + if (fgLpOwnResult == FALSE) { \ + DBGLOG(INIT, INFO, "HAL_LP_OWN_RD %d\n", fgLpOwnResult); \ + HAL_LP_OWN_SET(prAdapter, &fgLpOwnResult); \ + DBGLOG(INIT, INFO, "HAL_LP_OWN_SET %d\n", fgLpOwnResult); \ + } \ + } \ +} while (0) + +#define HAL_WIFI_FUNC_GET_STATUS(_prAdapter, _u4Result) \ +do { \ + struct mt66xx_chip_info *prChipInfo; \ + if (!_prAdapter->chip_info) \ + ASSERT(0); \ + prChipInfo = _prAdapter->chip_info; \ + HAL_MCR_RD(_prAdapter, prChipInfo->sw_sync0, &_u4Result); \ +} while (0) + +#define HAL_INTR_DISABLE(_prAdapter) + +#define HAL_INTR_ENABLE(_prAdapter) + +#define HAL_INTR_ENABLE_AND_LP_OWN_SET(_prAdapter) + +/* Polling interrupt status bit due to CFG_PCIE_LPCR_HOST status bit not work when chip sleep */ +#define HAL_LP_OWN_RD(_prAdapter, _pfgResult) \ +{ \ + UINT_32 u4RegValue = 0; \ + *_pfgResult = FALSE; \ + HAL_MCR_RD(prAdapter, WPDMA_INT_STA, &u4RegValue); \ + *_pfgResult = HAL_IS_FW_OWNBACK_INTR(u4RegValue);\ +} + +#define HAL_LP_OWN_SET(_prAdapter, _pfgResult) \ +{ \ + UINT_32 u4RegValue = 0; \ + *_pfgResult = FALSE; \ + HAL_MCR_WR(_prAdapter, CFG_PCIE_LPCR_HOST, PCIE_LPCR_HOST_SET_OWN); \ + HAL_MCR_RD(_prAdapter, CFG_PCIE_LPCR_HOST, &u4RegValue); \ + if (u4RegValue == 0) { \ + *_pfgResult = TRUE; \ + } \ +} + +#define HAL_LP_OWN_CLR(_prAdapter, _pfgResult) \ +{ \ + UINT_32 u4RegValue = 0; \ + *_pfgResult = FALSE; \ + /* Software get LP ownership */ \ + HAL_MCR_WR(_prAdapter, \ + CFG_PCIE_LPCR_HOST, \ + PCIE_LPCR_HOST_CLR_OWN); \ + HAL_MCR_RD(_prAdapter, CFG_PCIE_LPCR_HOST, &u4RegValue); \ + if (u4RegValue == 0) { \ + *_pfgResult = TRUE; \ + } \ +} + +#define HAL_GET_ABNORMAL_INTERRUPT_REASON_CODE(_prAdapter, pu4AbnormalReason) + +#define HAL_DISABLE_RX_ENHANCE_MODE(_prAdapter) + +#define HAL_ENABLE_RX_ENHANCE_MODE(_prAdapter) + +#define HAL_CFG_MAX_HIF_RX_LEN_NUM(_prAdapter, _ucNumOfRxLen) + +#define HAL_SET_INTR_STATUS_READ_CLEAR(prAdapter) + +#define HAL_SET_INTR_STATUS_WRITE_1_CLEAR(prAdapter) + +#define HAL_READ_INTR_STATUS(prAdapter, length, pvBuf) + +#define HAL_READ_TX_RELEASED_COUNT(_prAdapter, au2TxReleaseCount) + +#define HAL_READ_RX_LENGTH(prAdapter, pu2Rx0Len, pu2Rx1Len) + +#define HAL_GET_INTR_STATUS_FROM_ENHANCE_MODE_STRUCT(pvBuf, u2Len, pu4Status) + +#define HAL_GET_TX_STATUS_FROM_ENHANCE_MODE_STRUCT(pvInBuf, pu4BufOut, u4LenBufOut) + +#define HAL_GET_RX_LENGTH_FROM_ENHANCE_MODE_STRUCT(pvInBuf, pu2Rx0Num, au2Rx0Len, pu2Rx1Num, au2Rx1Len) + +#define HAL_GET_MAILBOX_FROM_ENHANCE_MODE_STRUCT(pvInBuf, pu4Mailbox0, pu4Mailbox1) + +#define HAL_IS_TX_DONE_INTR(u4IntrStatus) \ + ((u4IntrStatus & (WPDMA_TX_DONE_INT0 | WPDMA_TX_DONE_INT1 | WPDMA_TX_DONE_INT2 | WPDMA_TX_DONE_INT3)) \ + ? TRUE : FALSE) + +#define HAL_IS_RX_DONE_INTR(u4IntrStatus) \ + ((u4IntrStatus & (WPDMA_RX_DONE_INT0 | WPDMA_RX_DONE_INT1)) ? TRUE : FALSE) + +#define HAL_IS_ABNORMAL_INTR(u4IntrStatus) + +#define HAL_IS_FW_OWNBACK_INTR(u4IntrStatus) \ + ((u4IntrStatus & WPDMA_FW_CLR_OWN_INT) ? TRUE : FALSE) + +#define HAL_PUT_MAILBOX(prAdapter, u4MboxId, u4Data) + +#define HAL_GET_MAILBOX(prAdapter, u4MboxId, pu4Data) + +#define HAL_SET_MAILBOX_READ_CLEAR(prAdapter, fgEnableReadClear) \ +{ \ + prAdapter->prGlueInfo->rHifInfo.fgMbxReadClear = fgEnableReadClear;\ +} + +#define HAL_GET_MAILBOX_READ_CLEAR(prAdapter) (prAdapter->prGlueInfo->rHifInfo.fgMbxReadClear) + +#define HAL_READ_INT_STATUS(prAdapter, _pu4IntStatus) \ +{ \ + kalDevReadIntStatus(prAdapter, _pu4IntStatus);\ +} + +#define HAL_HIF_INIT(prAdapter) + +#define HAL_ENABLE_FWDL(_prAdapter, _fgEnable) + +#define HAL_WAKE_UP_WIFI(_prAdapter) \ +{ \ + halWakeUpWiFi(_prAdapter);\ +} + +#define HAL_CLEAR_DUMMY_REQ(_prAdapter) \ +{ \ + struct mt66xx_chip_info *prChipInfo; \ + UINT_32 u4Value; \ + if (!_prAdapter->chip_info) {\ + ASSERT(0); \ + } else {\ + prChipInfo = _prAdapter->chip_info; \ + HAL_MCR_RD(_prAdapter, prChipInfo->sw_sync0, &u4Value); \ + u4Value &= ~(WIFI_FUNC_DUMMY_REQ << prChipInfo->sw_ready_bit_offset);\ + HAL_MCR_WR(prAdapter, prChipInfo->sw_sync0, u4Value);\ + } \ +} + +#define HAL_IS_TX_DIRECT(_prAdapter) FALSE + +#define HAL_IS_RX_DIRECT(_prAdapter) FALSE + +#endif + +#if defined(_HIF_SDIO) +#define HIF_H2D_SW_INT_SHFT (16) +#define SDIO_MAILBOX_FUNC_READ_REG_IDX (BIT(0) << HIF_H2D_SW_INT_SHFT) /* bit16 */ +#define SDIO_MAILBOX_FUNC_WRITE_REG_IDX (BIT(1) << HIF_H2D_SW_INT_SHFT) /* bit17 */ +#define SDIO_MAILBOX_FUNC_CHECKSUN16_IDX (BIT(2) << HIF_H2D_SW_INT_SHFT) /* bit18 */ + +#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, _u4PortId, _u4Len, _pucBuf, _u4ValidBufSize) \ +{ \ + 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, \ + 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_WIFI_FUNC_READY_CHECK(_prAdapter, _checkItem, _pfgResult) \ +do { \ + UINT_32 u4Value = 0; \ + *_pfgResult = FALSE; \ + HAL_MCR_RD(_prAdapter, \ + MCR_WCIR, \ + &u4Value); \ + if (u4Value & WCIR_WLAN_READY) { \ + *_pfgResult = TRUE; \ + } \ +} while (0) + +#define HAL_WIFI_FUNC_OFF_CHECK(_prAdapter, _checkItem, _pfgResult) \ +do { \ + UINT_32 u4Value = 0; \ + *_pfgResult = FALSE; \ + HAL_MCR_RD(_prAdapter, MCR_WCIR, &u4Value); \ + if ((u4Value & WCIR_WLAN_READY) == 0) { \ + *_pfgResult = TRUE; \ + } \ + halPrintMailbox(prAdapter);\ + halPollDbgCr(_prAdapter, LP_DBGCR_POLL_ROUND); \ +} while (0) + +#define HAL_WIFI_FUNC_GET_STATUS(_prAdapter, _u4Result) \ + halGetMailbox(_prAdapter, 0, &_u4Result) + +#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_RD(_prAdapter, _pfgResult) \ +{ \ + UINT_32 u4RegValue = 0; \ + *_pfgResult = FALSE; \ + HAL_MCR_RD(_prAdapter, MCR_WHLPCR, &u4RegValue); \ + if (u4RegValue & WHLPCR_IS_DRIVER_OWN) { \ + *_pfgResult = TRUE; \ + } \ +} + +#define HAL_LP_OWN_SET(_prAdapter, _pfgResult) \ +{ \ + UINT_32 u4RegValue = 0; \ + *_pfgResult = FALSE; \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHLPCR, \ + WHLPCR_FW_OWN_REQ_SET); \ + HAL_MCR_RD(_prAdapter, MCR_WHLPCR, &u4RegValue); \ + if (u4RegValue & WHLPCR_IS_DRIVER_OWN) { \ + *_pfgResult = TRUE; \ + } \ +} + +#define HAL_LP_OWN_CLR(_prAdapter, _pfgResult) \ +{ \ + UINT_32 u4RegValue = 0; \ + *_pfgResult = FALSE; \ + /* Software get LP ownership */ \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHLPCR, \ + WHLPCR_FW_OWN_REQ_CLR); \ + HAL_MCR_RD(_prAdapter, MCR_WHLPCR, &u4RegValue); \ + if (u4RegValue & WHLPCR_IS_DRIVER_OWN) { \ + *_pfgResult = TRUE; \ + } \ +} + +#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) << WHCR_OFFSET_MAX_HIF_RX_LEN_NUM) & 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, au2TxReleaseCount) \ +{ \ + PUINT_32 pu4Value = (PUINT_32)au2TxReleaseCount; \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTQCR0, \ + &pu4Value[0]); \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTQCR1, \ + &pu4Value[1]); \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTQCR2, \ + &pu4Value[2]); \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTQCR3, \ + &pu4Value[3]); \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTQCR4, \ + &pu4Value[4]); \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTQCR5, \ + &pu4Value[5]); \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTQCR6, \ + &pu4Value[6]); \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTQCR7, \ + &pu4Value[7]); \ +} + +#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_RECV_MAILBOX_RD_CLR_EN) : \ + (u4Value & ~WHCR_RECV_MAILBOX_RD_CLR_EN)); \ + prAdapter->prGlueInfo->rHifInfo.fgMbxReadClear = fgEnableReadClear;\ +} + +#define HAL_GET_MAILBOX_READ_CLEAR(prAdapter) (prAdapter->prGlueInfo->rHifInfo.fgMbxReadClear) + +#define HAL_READ_INT_STATUS(prAdapter, _pu4IntStatus) \ +{ \ + kalDevReadIntStatus(prAdapter, _pu4IntStatus);\ +} + +#define HAL_HIF_INIT(_prAdapter) \ +{ \ + halDevInit(_prAdapter);\ +} + +#define HAL_ENABLE_FWDL(_prAdapter, _fgEnable) + +#define HAL_WAKE_UP_WIFI(_prAdapter) \ +{ \ + halWakeUpWiFi(_prAdapter);\ +} + +#define HAL_IS_TX_DIRECT(_prAdapter) FALSE + +#define HAL_IS_RX_DIRECT(_prAdapter) FALSE + +#endif + +#if defined(_HIF_USB) +#define HAL_GET_ABNORMAL_INTERRUPT_REASON_CODE(_prAdapter, pu4AbnormalReason) + +#define HAL_DISABLE_RX_ENHANCE_MODE(_prAdapter) + +#define HAL_ENABLE_RX_ENHANCE_MODE(_prAdapter) + +#define HAL_CFG_MAX_HIF_RX_LEN_NUM(_prAdapter, _ucNumOfRxLen) + +#define HAL_SET_INTR_STATUS_READ_CLEAR(prAdapter) + +#define HAL_SET_INTR_STATUS_WRITE_1_CLEAR(prAdapter) + +#define HAL_READ_INTR_STATUS(prAdapter, length, pvBuf) + +#define HAL_READ_TX_RELEASED_COUNT(_prAdapter, au2TxReleaseCount) + +#define HAL_READ_RX_LENGTH(prAdapter, pu2Rx0Len, pu2Rx1Len) + +#define HAL_GET_INTR_STATUS_FROM_ENHANCE_MODE_STRUCT(pvBuf, u2Len, pu4Status) + +#define HAL_GET_TX_STATUS_FROM_ENHANCE_MODE_STRUCT(pvInBuf, pu4BufOut, u4LenBufOut) + +#define HAL_GET_RX_LENGTH_FROM_ENHANCE_MODE_STRUCT(pvInBuf, pu2Rx0Num, au2Rx0Len, pu2Rx1Num, au2Rx1Len) + +#define HAL_GET_MAILBOX_FROM_ENHANCE_MODE_STRUCT(pvInBuf, pu4Mailbox0, pu4Mailbox1) + +#define HAL_READ_TX_RELEASED_COUNT(_prAdapter, au2TxReleaseCount) + +#define HAL_IS_TX_DONE_INTR(u4IntrStatus) FALSE + +#define HAL_IS_RX_DONE_INTR(u4IntrStatus) + +#define HAL_IS_ABNORMAL_INTR(u4IntrStatus) + +#define HAL_IS_FW_OWNBACK_INTR(u4IntrStatus) + +#define HAL_PUT_MAILBOX(prAdapter, u4MboxId, u4Data) + +#define HAL_GET_MAILBOX(prAdapter, u4MboxId, pu4Data) TRUE + +#define HAL_SET_MAILBOX_READ_CLEAR(prAdapter, fgEnableReadClear) + +#define HAL_GET_MAILBOX_READ_CLEAR(prAdapter) TRUE + +#define HAL_WIFI_FUNC_POWER_ON(_prAdapter) \ + mtk_usb_vendor_request(_prAdapter->prGlueInfo, 0, DEVICE_VENDOR_REQUEST_OUT, \ + VND_REQ_POWER_ON_WIFI, 0, 1, NULL, 0) + +#define HAL_WIFI_FUNC_CHIP_RESET(_prAdapter) \ + mtk_usb_vendor_request(_prAdapter->prGlueInfo, 0, DEVICE_VENDOR_REQUEST_OUT, \ + VND_REQ_POWER_ON_WIFI, 1, 1, NULL, 0) + +#define HAL_WIFI_FUNC_READY_CHECK(_prAdapter, _checkItem, _pfgResult) \ +do { \ + struct mt66xx_chip_info *prChipInfo; \ + UINT_32 u4Value = 0; \ + if (!_prAdapter->chip_info) \ + ASSERT(0); \ + *_pfgResult = FALSE; \ + prChipInfo = _prAdapter->chip_info; \ + HAL_MCR_RD(_prAdapter, prChipInfo->sw_sync0, &u4Value); \ + if ((u4Value & (_checkItem << prChipInfo->sw_ready_bit_offset)) \ + == (_checkItem << prChipInfo->sw_ready_bit_offset)) \ + *_pfgResult = TRUE; \ +} while (0) + +#define HAL_WIFI_FUNC_OFF_CHECK(_prAdapter, _checkItem, _pfgResult) \ +do { \ + struct mt66xx_chip_info *prChipInfo; \ + UINT_32 u4Value = 0; \ + if (!_prAdapter->chip_info) \ + ASSERT(0); \ + *_pfgResult = FALSE; \ + prChipInfo = _prAdapter->chip_info; \ + HAL_MCR_RD(_prAdapter, prChipInfo->sw_sync0, &u4Value); \ + if ((u4Value & (_checkItem << prChipInfo->sw_ready_bit_offset)) == 0) \ + *_pfgResult = TRUE; \ +} while (0) + +#define HAL_WIFI_FUNC_GET_STATUS(_prAdapter, _u4Result) \ +do { \ + struct mt66xx_chip_info *prChipInfo; \ + if (!_prAdapter->chip_info) \ + ASSERT(0); \ + prChipInfo = _prAdapter->chip_info; \ + HAL_MCR_RD(_prAdapter, prChipInfo->sw_sync0, &_u4Result); \ +} while (0) + +#define HAL_INTR_DISABLE(_prAdapter) + +#define HAL_INTR_ENABLE(_prAdapter) + +#define HAL_INTR_ENABLE_AND_LP_OWN_SET(_prAdapter) + +#define HAL_READ_INT_STATUS(prAdapter, _pu4IntStatus) \ +{ \ + halGetCompleteStatus(prAdapter, _pu4IntStatus); \ +} + +#define HAL_HIF_INIT(_prAdapter) \ +{ \ + halDevInit(_prAdapter);\ +} + +#define HAL_ENABLE_FWDL(_prAdapter, _fgEnable) \ +{ \ + halEnableFWDownload(_prAdapter, _fgEnable);\ +} + +#define HAL_WAKE_UP_WIFI(_prAdapter) \ +{ \ + halWakeUpWiFi(_prAdapter);\ +} + +#define HAL_LP_OWN_RD(_prAdapter, _pfgResult) + +#define HAL_LP_OWN_SET(_prAdapter, _pfgResult) + +#define HAL_LP_OWN_CLR(_prAdapter, _pfgResult) + +#define HAL_WRITE_TX_PORT(_prAdapter, _u4PortId, _u4Len, _pucBuf, _u4ValidBufSize) \ +{ \ + HAL_PORT_WR(_prAdapter, \ + _u4PortId, \ + _u4Len, \ + _pucBuf, \ + _u4ValidBufSize/*temp!!*//*4KByte*/) \ +} + +#define HAL_IS_TX_DIRECT(_prAdapter) \ + ((CFG_TX_DIRECT_USB) ? TRUE : FALSE) + +#define HAL_IS_RX_DIRECT(_prAdapter) \ + ((CFG_RX_DIRECT_USB) ? TRUE : FALSE) + +#endif + +#define INVALID_VERSION 0xFFFF /* used by HW/FW version */ +/******************************************************************************* +* 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 +******************************************************************************** +*/ + +BOOL halVerifyChipID(IN P_ADAPTER_T prAdapter); +UINT_32 halGetChipHwVer(IN P_ADAPTER_T prAdapter); +UINT_32 halGetChipSwVer(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS halRxWaitResponse(IN P_ADAPTER_T prAdapter, IN UINT_8 ucPortIdx, OUT PUINT_8 pucRspBuffer, + IN UINT_32 u4MaxRespBufferLen, OUT PUINT_32 pu4Length); + +VOID halEnableInterrupt(IN P_ADAPTER_T prAdapter); +VOID halDisableInterrupt(IN P_ADAPTER_T prAdapter); + +BOOLEAN halSetDriverOwn(IN P_ADAPTER_T prAdapter); +VOID halSetFWOwn(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnableGlobalInt); + +VOID halDevInit(IN P_ADAPTER_T prAdapter); +VOID halEnableFWDownload(IN P_ADAPTER_T prAdapter, IN BOOL fgEnable); +VOID halWakeUpWiFi(IN P_ADAPTER_T prAdapter); +VOID halTxCancelSendingCmd(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); +VOID halTxCancelAllSending(IN P_ADAPTER_T prAdapter); +BOOLEAN halTxIsDataBufEnough(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); +VOID halProcessTxInterrupt(IN P_ADAPTER_T prAdapter); +WLAN_STATUS halTxPollingResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC); +VOID halSerHifReset(IN P_ADAPTER_T prAdapter); + +VOID halProcessRxInterrupt(IN P_ADAPTER_T prAdapter); +VOID halProcessSoftwareInterrupt(IN P_ADAPTER_T prAdapter); +/* Hif power off wifi */ +WLAN_STATUS halHifPowerOffWifi(IN P_ADAPTER_T prAdapter); + + +VOID halHifSwInfoInit(IN P_ADAPTER_T prAdapter); +VOID halRxProcessMsduReport(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb); +UINT_32 halTxGetPageCount(IN UINT_32 u4FrameLength, IN BOOLEAN fgIncludeDesc); +UINT_32 halDumpHifStatus(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuf, IN UINT_32 u4Max); +BOOLEAN halIsPendingRx(IN P_ADAPTER_T prAdapter); +UINT_32 halGetValidCoalescingBufSize(IN P_ADAPTER_T prAdapter); +WLAN_STATUS halAllocateIOBuffer(IN P_ADAPTER_T prAdapter); +WLAN_STATUS halReleaseIOBuffer(IN P_ADAPTER_T prAdapter); +VOID halDeAggRxPktWorker(struct work_struct *work); +VOID halRxTasklet(unsigned long data); +VOID halTxCompleteTasklet(unsigned long data); +VOID halPrintHifDbgInfo(IN P_ADAPTER_T prAdapter); +BOOLEAN halIsTxResourceControlEn(IN P_ADAPTER_T prAdapter); +VOID halTxResourceResetHwTQCounter(IN P_ADAPTER_T prAdapter); + +VOID halWpdmaSetup(P_GLUE_INFO_T prGlueInfo, BOOLEAN enable); +#endif /* _HAL_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/hif_rx.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/hif_rx.h new file mode 100644 index 0000000000000..fdc1f99201374 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/hif_rx.h @@ -0,0 +1,155 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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 +*/ + + +#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 +******************************************************************************** +*/ + +/******************************************************************************* +* P U B 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 __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. + */ +static __KAL_INLINE__ VOID hifDataTypeCheck(VOID) +{ +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/hif_tx.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/hif_tx.h new file mode 100644 index 0000000000000..29f73e8b5f7ae --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/hif_tx.h @@ -0,0 +1,168 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/hif_tx.h#1 +*/ + + +#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 */ +#if 0 +#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 +#endif + +#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 (for short-header format) */ +/* DW 0, Byte 0,1 */ +#define HIF_TX_HDR_TX_BYTE_COUNT_MASK BITS(0, 15) + +/* DW 0, Byte 2 */ +#define HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK BITS(0, 6) +#define HIF_TX_HDR_IP_CSUM BIT(7) + +/* DW 0, Byte 3 */ +#define HIF_TX_HDR_TCP_CSUM BIT(0) +#define HIF_TX_HDR_QUEUE_IDX_MASK BITS(3, 6) +#define HIF_TX_HDR_QUEUE_IDX_OFFSET 3 +#define HIF_TX_HDR_PORT_IDX_MASK BIT(7) +#define HIF_TX_HDR_PORT_IDX_OFFSET 7 + +/******************************************************************************* +* 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_OOB_CTRL_PKT_TYPE_T { + HIF_OOB_CTRL_PKT_TYPE_LOOPBACK = 1, + HIF_OOB_CTRL_PKT_TYP_NUM +} ENUM_HIF_OOB_CTRL_PKT_TYPE_T, *P_ENUM_HIF_OOB_CTRL_PKT_TYPE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define TFCB_FRAME_PAD_TO_DW(u2Length) ALIGN_4(u2Length) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/* Kevin: we don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + */ +static __KAL_INLINE__ VOID hif_txDataTypeCheck(VOID); + +static __KAL_INLINE__ VOID hif_txDataTypeCheck(VOID) +{ + DATA_STRUCT_INSPECTING_ASSERT(sizeof(HIF_TX_HEADER_T) == 16); +} + +#endif /*_HIF_TX_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/mac.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/mac.h new file mode 100644 index 0000000000000..0e307348f5e4c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/mac.h @@ -0,0 +1,2736 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/mac.h#1 +*/ + +/*! \file "mac.h" +* \brief Brief description. +* +* Detail description. +*/ + + +#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 +******************************************************************************** +*/ +#if CFG_SUPPORT_CFG80211_AUTH +#define AUTH_DATA_MAX_LEN 1024 /* temp defined */ +#endif +/* 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_ARP 0x0806 +#define ETH_P_IPX 0x8137 /* Novell IPX */ +#define ETH_P_AARP 0x80F3 /* AppleTalk Address Resolution Protocol (AARP) */ +#define ETH_P_IPV6 0x86DD +#define ETH_P_VLAN 0x8100 + +#define ETH_P_1X 0x888E +#define ETH_P_PRE_1X 0x88C7 +#if CFG_SUPPORT_WAPI +#define ETH_WPI_1X 0x88B4 +#endif +#define ETH_EAPOL_KEY 3 + +/* 802.3 Frame If Ether Type/Len <= 1500 */ +#define ETH_802_3_MAX_LEN 1500 + +/* IP Header definition */ +#define IP_VERSION_MASK BITS(4, 7) +#define IP_VERSION_OFFSET 4 +#define IP_VERSION_4 4 +#define IP_VERSION_6 6 + +#define IP_PROTOCOL_TCP 6 +#define IP_PROTOCOL_UDP 17 + +/* IPv4 Header definition */ +#define IPV4_HDR_TOS_OFFSET 1 +#define IPV4_HDR_TOS_PREC_MASK BITS(5, 7) +#define IPV4_HDR_TOS_PREC_OFFSET 5 +#define IPV4_HDR_IP_IDENTIFICATION_OFFSET 4 +#define IPV4_HDR_IP_PROTOCOL_OFFSET 9 +#define IPV4_HDR_IP_CSUM_OFFSET 10 +#define IPV4_HDR_IP_SRC_ADDR_OFFSET 12 +#define IPV4_HDR_IP_DST_ADDR_OFFSET 16 + +#define IPV4_HDR_LEN 20 +#define IPV4_ADDR_LEN 4 + +#define IPV6_HDR_IP_PROTOCOL_OFFSET 6 +#define IPV6_HDR_IP_SRC_ADDR_OFFSET 8 +#define IPV6_HDR_IP_DST_ADDR_OFFSET 24 +#define IPV6_HDR_IP_DST_ADDR_MAC_HIGH_OFFSET 32 +#define IPV6_HDR_IP_DST_ADDR_MAC_LOW_OFFSET 37 +#define IPV6_PROTOCOL_ICMPV6 0x3A + +#define IPV6_HDR_TC_PREC_OFFSET 1 +#define IPV6_HDR_TC_PREC_MASK BITS(1, 3) +#define IPV6_HDR_PROTOCOL_OFFSET 6 +#define IPV6_HDR_LEN 40 + +#define IPV6_ADDR_LEN 16 + +#define ICMPV6_TYPE_OFFSET 0 +#define ICMPV6_FLAG_OFFSET 4 +#define ICMPV6_TARGET_ADDR_OFFSET 8 +#define ICMPV6_TARGET_LL_ADDR_TYPE_OFFSET 24 +#define ICMPV6_TARGET_LL_ADDR_LEN_OFFSET 25 +#define ICMPV6_TARGET_LL_ADDR_TA_OFFSET 26 + +#define ICMPV6_FLAG_ROUTER_BIT BIT(7) +#define ICMPV6_FLAG_SOLICITED_BIT BIT(6) +#define ICMPV6_FLAG_OVERWRITE_BIT BIT(5) +#define ICMPV6_TYPE_NEIGHBOR_SOLICITATION 0x87 +#define ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT 0x88 + +#define TCP_HDR_TCP_CSUM_OFFSET 16 + +#define UDP_HDR_LEN 8 + +#define UDP_HDR_SRC_PORT_OFFSET 0 +#define UDP_HDR_DST_PORT_OFFSET 2 +#define UDP_HDR_UDP_CSUM_OFFSET 6 + +#define IP_PORT_BOOTP_SERVER 67 +#define IP_PORT_BOOTP_CLIENT 68 + +#define DHCP_MAGIC_NUMBER 0x63825363 + +#define ARP_OPERATION_OFFSET 6 +#define ARP_SNEDER_MAC_OFFSET 8 +#define ARP_SENDER_IP_OFFSET 14 +#define ARP_TARGET_MAC_OFFSET 18 +#define ARP_TARGET_IP_OFFSET 24 +#define ARP_OPERATION_REQUEST 0x0001 +#define ARP_OPERATION_RESPONSE 0x0002 + +#define 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} + +#if 1 + +#define ETH_HLEN 14 +#define ETH_TYPE_LEN_OFFSET 12 + +#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 + +#define LOOK_AHEAD_LEN (ETH_HLEN + IP_HEADER_LEN + SOURCE_PORT_LEN) + +#endif + +/* 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 + +#define ETHER_TYPE_LEN_OFFSET 12 + +/* 802.1Q (VLAN) */ +#define ETH_802_1Q_HEADER_LEN 4 + +/* 802.2 LLC/SNAP */ +#define ETH_LLC_OFFSET (ETHER_HEADER_LEN) +#define ETH_LLC_LEN 3 +#define ETH_LLC_DSAP_SNAP 0xAA +#define ETH_LLC_SSAP_SNAP 0xAA +#define ETH_LLC_CONTROL_UNNUMBERED_INFORMATION 0x03 +#define ETH_LLC \ + {ETH_LLC_DSAP_SNAP, ETH_LLC_SSAP_SNAP, ETH_LLC_CONTROL_UNNUMBERED_INFORMATION} + +/* Bluetooth SNAP */ +#define ETH_SNAP_OFFSET (ETHER_HEADER_LEN + ETH_LLC_LEN) +#define ETH_SNAP_LEN 5 +#define ETH_SNAP_OUI_LEN 3 +#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 ETH_SNAP_BT_SIG_OUI {ETH_SNAP_BT_SIG_OUI_0, ETH_SNAP_BT_SIG_OUI_1, ETH_SNAP_BT_SIG_OUI_2} + +#define BOW_PROTOCOL_ID_SECURITY_FRAME 0x0003 + +/* 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_VHT_PHY 126 /* BSS Selector - Clause 22. HT PHY */ +#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 + +#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 */ +#if CFG_SUPPORT_CFG80211_AUTH +#define AUTH_ALGORITHM_NUM_SAE 3 /* SAE */ +#endif + +/* 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 */ +/* Disassoc because the info in Power Capability is unacceptable */ +#define REASON_CODE_DISASSOC_PWR_CAP_UNACCEPTABLE 10 +/* Disassoc because the info in Supported Channels is unacceptable */ +#define REASON_CODE_DISASSOC_SUP_CHS_UNACCEPTABLE 11 +#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 */ +/* Info element in 4-way handshake different from */ +/* (Re-)associate request/Probe response/Beacon */ +#define REASON_CODE_DIFFERENT_INFO_ELEM 17 +#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 */ +/* Disassoc because QAP lacks sufficient bandwidth for this QSTA */ +#define REASON_CODE_DISASSOC_LACK_OF_BANDWIDTH 33 +/* Disassoc because of too many ACKs lost for AP transmissions */ +/* and/or poor channel conditions */ +#define REASON_CODE_DISASSOC_ACK_LOST_POOR_CHANNEL 34 +/* Disassoc because QSTA is transmitting outside the limits of its TXOPs */ +#define REASON_CODE_DISASSOC_TX_OUTSIDE_TXOP_LIMIT 35 +#define REASON_CODE_PEER_WHILE_LEAVING 36 /* QSTA is leaving the QBSS or resetting */ +#define REASON_CODE_PEER_REFUSE_DLP 37 /* Peer does not want to use this mechanism */ +#define REASON_CODE_PEER_SETUP_REQUIRED 38 /* Frames received but a setup is reqired */ +#define REASON_CODE_PEER_TIME_OUT 39 /* Time out */ +#define REASON_CODE_PEER_CIPHER_UNSUPPORTED 45 /* Peer does not support the requested cipher suite */ +#define REASON_CODE_BEACON_TIMEOUT 100 /* for beacon timeout, defined by mediatek */ +/* 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 */ +/* Reassoc denied due to inability to confirm that assoc exists */ +#define STATUS_CODE_REASSOC_DENIED_WITHOUT_ASSOC 11 +#define STATUS_CODE_ASSOC_DENIED_OUTSIDE_STANDARD 12 /* Assoc denied due to reason outside the scope of this std. */ +/* Responding STA does not support the specified auth algorithm */ +#define STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED 13 +/* Rx an auth frame with auth transaction seq num out of expected seq */ +#define STATUS_CODE_AUTH_OUT_OF_SEQ 14 +#define STATUS_CODE_AUTH_REJECTED_CHAL_FAIL 15 /* Auth rejected because of challenge failure */ +/* Auth rejected due to timeout waiting for next frame in sequence */ +#define STATUS_CODE_AUTH_REJECTED_TIMEOUT 16 +/* Assoc denied because AP is unable to handle additional assoc STAs */ +#define STATUS_CODE_ASSOC_DENIED_AP_OVERLOAD 17 +/* Assoc denied due to requesting STA not supporting all of basic rates */ +#define STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED 18 +/* Assoc denied due to requesting STA not supporting short preamble */ +#define STATUS_CODE_ASSOC_DENIED_NO_SHORT_PREAMBLE 19 +#define STATUS_CODE_ASSOC_DENIED_NO_PBCC 20 /* Assoc denied due to requesting STA not supporting PBCC */ +/* Assoc denied due to requesting STA not supporting channel agility */ +#define STATUS_CODE_ASSOC_DENIED_NO_CH_AGILITY 21 +#define STATUS_CODE_ASSOC_REJECTED_NO_SPEC_MGT 22 /* Assoc rejected because Spectrum Mgt capability is required */ +/* Assoc rejected because the info in Power Capability is unacceptable */ +#define STATUS_CODE_ASSOC_REJECTED_PWR_CAP 23 +/* Assoc rejected because the info in Supported Channels is unacceptable */ +#define STATUS_CODE_ASSOC_REJECTED_SUP_CHS 24 +/* Assoc denied due to requesting STA not supporting short slot time */ +#define STATUS_CODE_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25 +/* Assoc denied due to requesting STA not supporting DSSS-OFDM */ +#define STATUS_CODE_ASSOC_DENIED_NO_DSSS_OFDM 26 +#if CFG_SUPPORT_802_11W +#define STATUS_CODE_ASSOC_REJECTED_TEMPORARILY 30 /* IEEE 802.11w, Assoc denied due to the SA query */ +/* IEEE 802.11w, Assoc denied due to the MFP select policy */ +#define STATUS_CODE_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31 +#endif +#define STATUS_CODE_UNSPECIFIED_QOS_FAILURE 32 /* Unspecified, QoS-related failure */ +/* Assoc denied due to insufficient bandwidth to handle another QSTA */ +#define STATUS_CODE_ASSOC_DENIED_BANDWIDTH 33 +/* Assoc denied due to excessive frame loss rates and/or poor channel conditions */ +#define STATUS_CODE_ASSOC_DENIED_POOR_CHANNEL 34 +/* Assoc denied due to requesting STA not supporting QoS facility */ +#define STATUS_CODE_ASSOC_DENIED_NO_QOS_FACILITY 35 +#define STATUS_CODE_REQ_DECLINED 37 /* Request has been declined */ +/* Request has not been successful as one or more parameters have invalid values */ +#define STATUS_CODE_REQ_INVALID_PARAMETER_VALUE 38 +/* TS not created because request cannot be honored. */ +/* Suggested TSPEC provided. */ +#define STATUS_CODE_REQ_NOT_HONORED_TSPEC 39 +#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 */ +/* TS not created because request cannot be honored. */ +/* Attempt to create a TS later. */ +#define STATUS_CODE_REQ_NOT_HONORED_TS_DELAY 47 +#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_QUERY_ACTION 8 +#define CATEGORY_PROTECTED_DUAL_OF_PUBLIC_ACTION 9 +#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_VHT_ACTION 21 /* VHT action */ + +#if CFG_SUPPORT_802_11W +#define CATEGORY_VENDOR_SPECIFIC_ACTION_PROTECTED 126 +#endif +#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_SUP_OPERATING_CLASS 59 /* Supported Operating Classes */ + +#define ELEM_ID_HT_OP 61 /* HT Operation */ +#define ELEM_ID_SCO 62 /* Secondary Channel Offset */ +#define ELEM_ID_RRM_ENABLED_CAP 70 /* Radio Resource Management Enabled Capabilities */ +#define ELEM_ID_20_40_BSS_COEXISTENCE 72 /* 20/40 BSS Coexistence */ +#define ELEM_ID_20_40_INTOLERANT_CHNL_REPORT 73 /* 20/40 BSS Intolerant Channel Report */ +#define ELEM_ID_OBSS_SCAN_PARAMS 74 /* Overlapping BSS Scan Parameters */ +#define ELEM_ID_EXTENDED_CAP 127 /* Extended capabilities */ + +#define ELEM_ID_INTERWORKING 107 /* Interworking with External Network */ +#define ELEM_ID_ADVERTISEMENT_PROTOCOL 108 /* Advertisement Protocol */ +#define ELEM_ID_ROAMING_CONSORTIUM 111 /* Roaming Consortium */ +#define ELEM_ID_EXTENDED_CAP 127 /* Extended capabilities */ + +#define ELEM_ID_VENDOR 221 /* Vendor specific IE */ +#define ELEM_ID_WPA ELEM_ID_VENDOR /* WPA IE */ +#define ELEM_ID_WMM ELEM_ID_VENDOR /* WMM IE */ +#define ELEM_ID_P2P ELEM_ID_VENDOR /* WiFi Direct */ +#define ELEM_ID_WSC ELEM_ID_VENDOR /* WSC IE */ + +#define ELEM_ID_VHT_CAP 191 /* VHT Capabilities subelement */ +#define ELEM_ID_VHT_OP 192 /* VHT Operation information */ +#define ELEM_ID_WIDE_BAND_CHANNEL_SWITCH 194 /*Wide Bandwidth Channel Switch */ +#define ELEM_ID_OP_MODE 199 /* Operation Mode Notification */ +#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 */ + +#define ELEM_MAX_LEN_SUPPORTED_CHANNELS (MAX_CHN_NUM * 2) + +/* 7.3.2.14 Extended Supported Rates */ +#define ELEM_MAX_LEN_EXTENDED_SUP_RATES 255 + +/* 7.3.2.16 Power Capability element */ +#define ELEM_MAX_LEN_POWER_CAP 2 + + +/* 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 34 /* one pairwise, one AKM suite, one PMKID */ +#define ELEM_MAX_LEN_RSN 38 /* one pairwise, one AKM suite, one PMKID */ +#define ELEM_MAX_LEN_WAPI 38 /* one pairwise, one AKM suite, one BKID */ +#define ELEM_MAX_LEN_WSC 200 /* one pairwise, one AKM suite, one BKID */ + +/* 802.11i */ +/* length of one PMKID */ +#define RSN_PMKID_LEN 16 + +#if CFG_SUPPORT_802_11W +#define ELEM_WPA_CAP_MFPR BIT(6) +#define ELEM_WPA_CAP_MFPC BIT(7) +#endif + +/* 7.3.2.27 Extended Capabilities information element */ +#define ELEM_EXT_CAP_20_40_COEXIST_SUPPORT BIT(0) +#define ELEM_EXT_CAP_PSMP_CAP BIT(4) +#define ELEM_EXT_CAP_SERVICE_INTERVAL_GRANULARITY BIT(5) +#define ELEM_EXT_CAP_SCHEDULE_PSMP BIT(6) + +#define ELEM_EXT_CAP_BSS_TRANSITION_BIT 19 +#define ELEM_EXT_CAP_UTC_TSF_OFFSET_BIT 27 +#define ELEM_EXT_CAP_INTERWORKING_BIT 31 +#define ELEM_EXT_CAP_WNM_NOTIFICATION_BIT 46 +#define ELEM_EXT_CAP_OP_MODE_NOTIFICATION_BIT 62 + +#define ELEM_MAX_LEN_EXT_CAP (8) + +/* 7.3.2.30 TSPEC element */ +#define TS_INFO_TRAFFIC_TYPE_MASK BIT(0) /* WMM: 0 (Asynchronous TS of low-duty cycles) */ +#define TS_INFO_TID_OFFSET 1 +#define TS_INFO_TID_MASK BITS(1, 4) +#define TS_INFO_DIRECTION_OFFSET 5 +#define TS_INFO_DIRECTION_MASK BITS(5, 6) +#define TS_INFO_ACCESS_POLICY_OFFSET 7 +#define TS_INFO_ACCESS_POLICY_MASK BITS(7, 8) +#define TS_INFO_AGGREGATION_MASK BIT(9) /* WMM: 0 */ +#define TS_INFO_APSD_MASK BIT(10) +#define TS_INFO_UP_OFFSET 11 +#define TS_INFO_UP_MASK BITS(11, 13) +#define TS_INFO_ACK_POLICY_OFFSET 14 +#define TS_INFO_ACK_POLICY_MASK BITS(14, 15) +#define TS_INFO_SCHEDULE_MASK 16 + +/* 7.3.2.56 HT capabilities element */ +#define ELEM_MAX_LEN_HT_CAP (28 - ELEM_HDR_LEN) /* sizeof(IE_HT_CAP_T)-2 */ + +/* 7.3.2.56.2 HT capabilities Info field */ +#define HT_CAP_INFO_LDPC_CAP BIT(0) +#define HT_CAP_INFO_SUP_CHNL_WIDTH BIT(1) +#define HT_CAP_INFO_SM_POWER_SAVE BITS(2, 3) +#define HT_CAP_INFO_SM_POWER_SAVE_OFFSET 2 +#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 + +#define ELEM_MAX_LEN_VHT_CAP (14 - ELEM_HDR_LEN) /* sizeof(IE_VHT_CAP_T)-2 */ +/* 8.4.2.161 VHT Operation element */ +#define ELEM_MAX_LEN_VHT_OP (7 - ELEM_HDR_LEN) /* sizeof(IE_VHT_OP_T)-2 */ + +#define ELEM_MAX_LEN_VHT_OP_MODE_NOTIFICATION (3 - ELEM_HDR_LEN) /* sizeof(IE_VHT_OP_MODE_T)-2 */ + +/*8.4.2.160.3 VHT Supported MCS Set field*/ + +/*8.4.2.160.2 VHT Capabilities Info field*/ +#define VHT_CAP_INFO_MAX_MPDU_LEN_3K 0 +#define VHT_CAP_INFO_MAX_MPDU_LEN_8K BIT(0) +#define VHT_CAP_INFO_MAX_MPDU_LEN_11K BIT(1) +#define VHT_CAP_INFO_MAX_MPDU_LEN_MASK BITS(0, 1) + +#define VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_SET_NONE 0 +#define VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_SET_160 BIT(2) +#define VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_SET_160_80P80 BIT(3) +#define VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_MASK BITS(2, 3) + +#define VHT_CAP_INFO_RX_LDPC BIT(4) +#define VHT_CAP_INFO_SHORT_GI_80 BIT(5) +#define VHT_CAP_INFO_SHORT_GI_160_80P80 BIT(6) +#define VHT_CAP_INFO_TX_STBC BIT(7) + +#define VHT_CAP_INFO_RX_STBC_NONE 0 +#define VHT_CAP_INFO_RX_STBC_MASK BITS(8, 10) +#define VHT_CAP_INFO_RX_STBC_OFFSET 8 +#define VHT_CAP_INFO_RX_STBC_ONE_STREAM BIT(8) +#define VHT_CAP_INFO_RX_STBC_TWO_STREAM BIT(9) +#define VHT_CAP_INFO_RX_STBC_THREE_STREAM BITS(8, 9) +#define VHT_CAP_INFO_RX_STBC_FOUR_STREAM BIT(10) + +#define VHT_CAP_INFO_SU_BEAMFORMER_CAPABLE BIT(11) +#define VHT_CAP_INFO_SU_BEAMFORMEE_CAPABLE BIT(12) +#define VHT_CAP_INFO_SU_BEAMFORMEE_CAPABLE_OFFSET 12 + +#define VHT_CAP_INFO_COMP_STEERING_NUM_OF_BFER_ANT_SUP_OFFSET 13 +#define VHT_CAP_INFO_COMP_STEERING_NUM_OF_BFER_ANT_SUP BITS(13, 15) +#define VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF_BEAMFORMER_ANTENNAS_2_SUPPOERTED BIT(13) +#define VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF_BEAMFORMER_ANTENNAS_3_SUPPOERTED BIT(14) +#define VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF_BEAMFORMER_ANTENNAS_4_SUPPOERTED BITS(13, 14) + +#define VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS_OFFSET 16 +#define VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS BITS(16, 18) +#define VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS_2_SUPPORTED BIT(16) +#define VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS_3_SUPPORTED BIT(17) +#define VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS_4_SUPPORTED BITS(16, 17) + +#define VHT_CAP_INFO_MU_BEAMFOMER_CAPABLE BIT(19) +#define VHT_CAP_INFO_MU_BEAMFOMEE_CAPABLE BIT(20) +#define VHT_CAP_INFO_VHT_TXOP_PS BIT(21) +#define VHT_CAP_INFO_HTC_VHT_CAPABLE BIT(22) + +#define VHT_CAP_INFO_MAX_AMPDU_LENGTH_OFFSET 23 + +#define VHT_CAP_INFO_VHT_LINK_ADAPTATION_CAPABLE_NOFEEDBACK 0 +#define VHT_CAP_INFO_VHT_LINK_ADAPTATION_CAPABLE_UNSOLICITED BITS(27) +#define VHT_CAP_INFO_VHT_LINK_ADAPTATION_CAPABLE_BOTH BITS(26, 27) + +#define VHT_CAP_INFO_RX_ANTENNA_PATTERN_CONSISTENCY BIT(28) +#define VHT_CAP_INFO_TX_ANTENNA_PATTERN_CONSISTENCY BIT(29) + +#define VHT_CAP_INFO_MCS_MAP_MCS7 0 +#define VHT_CAP_INFO_MCS_MAP_MCS8 BIT(0) +#define VHT_CAP_INFO_MCS_MAP_MCS9 BIT(1) +#define VHT_CAP_INFO_MCS_NOT_SUPPORTED BITS(0, 1) + +#define VHT_CAP_INFO_MCS_1SS_OFFSET 0 +#define VHT_CAP_INFO_MCS_2SS_OFFSET 2 +#define VHT_CAP_INFO_MCS_3SS_OFFSET 4 +#define VHT_CAP_INFO_MCS_4SS_OFFSET 6 +#define VHT_CAP_INFO_MCS_5SS_OFFSET 8 +#define VHT_CAP_INFO_MCS_6SS_OFFSET 10 +#define VHT_CAP_INFO_MCS_7SS_OFFSET 12 +#define VHT_CAP_INFO_MCS_8SS_OFFSET 14 + +#define VHT_CAP_INFO_MCS_1SS_MASK BITS(0, 1) +#define VHT_CAP_INFO_MCS_2SS_MASK BITS(2, 3) +#define VHT_CAP_INFO_MCS_3SS_MASK BITS(4, 5) +#define VHT_CAP_INFO_MCS_4SS_MASK BITS(6, 7) +#define VHT_CAP_INFO_MCS_5SS_MASK BITS(8, 9) +#define VHT_CAP_INFO_MCS_6SS_MASK BITS(10, 11) +#define VHT_CAP_INFO_MCS_7SS_MASK BITS(12, 13) +#define VHT_CAP_INFO_MCS_8SS_MASK BITS(14, 15) + +#define VHT_OP_CHANNEL_WIDTH_20_40 0 +#define VHT_OP_CHANNEL_WIDTH_80 1 +#define VHT_OP_CHANNEL_WIDTH_160 2 +#define VHT_OP_CHANNEL_WIDTH_80P80 3 + +/*8.4.1.50 Operating Mode Field*/ +#define VHT_OP_MODE_CHANNEL_WIDTH BITS(0, 1) +#define VHT_OP_MODE_RX_NSS BITS(4, 6) +#define VHT_OP_MODE_RX_NSS_TYPE BIT(7) + +#define VHT_OP_MODE_CHANNEL_WIDTH_OFFSET 0 +#define VHT_OP_MODE_RX_NSS_OFFSET 4 +#define VHT_OP_MODE_RX_NSS_TYPE_OFFSET 7 + +#define VHT_OP_MODE_CHANNEL_WIDTH_20 0 +#define VHT_OP_MODE_CHANNEL_WIDTH_40 1 +#define VHT_OP_MODE_CHANNEL_WIDTH_80 2 +#define VHT_OP_MODE_CHANNEL_WIDTH_160_80P80 3 + +/* 8.4.1.22 SM Power Control field*/ +#define HT_SM_POWER_SAVE_CONTROL_ENABLED BIT(0) +#define HT_SM_POWER_SAVE_CONTROL_SM_MODE BIT(1) /* 0:static, 1:dynamic */ +#define HT_SM_POWER_SAVE_CONTROL_SM_MODE_OFFSET 1 + +/* 8.4.1.21 Channel Width field */ +#define HT_NOTIFY_CHANNEL_WIDTH_20 0 +#define HT_NOTIFY_CHANNEL_WIDTH_ANY_SUPPORT_CAHNNAEL_WIDTH 1 + +/* 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_MAX_AMPDU_LEN_128K BIT(2) +#define AMPDU_PARAM_MAX_AMPDU_LEN_256K (BIT(2) | BIT(0)) +#define AMPDU_PARAM_MAX_AMPDU_LEN_512K BITS(1, 2) +#define AMPDU_PARAM_MAX_AMPDU_LEN_1024K BITS(0, 2) + +#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 */ +#define TXBF_IMPLICIT_RX_CAPABLE BIT(0) +#define TXBF_RX_STAGGERED_SOUNDING_CAPABLE BIT(1) +#define TXBF_TX_STAGGERED_SOUNDING_CAPABLE BIT(2) +#define TXBF_RX_NDP_CAPABLE_OFFSET 3 +#define TXBF_RX_NDP_CAPABLE BIT(3) +#define TXBF_TX_NDP_CAPABLE BIT(4) +#define TXBF_IMPLICIT_TX_CAPABLE BIT(5) +#define TXBF_CALIBRATION_CAPABLE BITS(6, 7) +#define TXBF_EXPLICIT_CSI_TX_CAPABLE BIT(8) +#define TXBF_EXPLICIT_NONCOMPRESSED_TX_CAPABLE BIT(9) +#define TXBF_EXPLICIT_COMPRESSED_TX_CAPAB BIT(10) +#define TXBF_EXPLICIT_CSI_FEEDBACK_CAPABLE BITS(11, 12) +#define TXBF_EXPLICIT_NONCOMPRESSED_FEEDBACK_CAPABLE BITS(13, 14) + +#define TXBF_EXPLICIT_COMPRESSED_FEEDBACK_CAPABLE_OFFSET 15 +#define TXBF_EXPLICIT_COMPRESSED_FEEDBACK_CAPABLE BITS(15, 16) +#define TXBF_EXPLICIT_COMPRESSED_FEEDBACK_IMMEDIATE_CAPABLE BIT(16) + +#define TXBF_MINIMAL_GROUPING_CAPABLE BITS(17, 18) +#define TXBF_MINIMAL_GROUPING_1_2_3_CAPABLE BITS(17, 18) + +#define TXBF_CSI_BFER_ANTENNANUM_SUPPORTED BITS(19, 20) +#define TXBF_NONCOMPRESSED_TX_ANTENNANUM_SUPPORTED BITS(21, 22) + +#define TXBF_COMPRESSED_TX_ANTENNANUM_SUPPORTED_OFFSET 23 +#define TXBF_COMPRESSED_TX_ANTENNANUM_SUPPORTED BITS(23, 24) +#define TXBF_COMPRESSED_TX_ANTENNANUM_4_SUPPORTED BITS(23, 24) + +#define TXBF_CSI_MAX_ROWS_BFER_SUPPORTED BITS(25, 26) + +#define TXBF_CHANNEL_ESTIMATION_CAPABILITY BITS(27, 28) +#define TXBF_CHANNEL_ESTIMATION_4STS_CAPABILITY BITS(27, 28) + +/* 7.3.2.56.7 Antenna Selection Capability field */ +#define ASEL_CAP_CAPABLE BIT(0) +#define ASEL_CAP_CSI_FB_BY_TX_ASEL_CAPABLE BIT(1) +#define ASEL_CAP_ANT_INDICES_FB_BY_TX_ASEL_CAPABLE BIT(2) +#define ASEL_CAP_EXPLICIT_CSI_FB_CAPABLE BIT(3) +#define ASEL_CAP_ANT_INDICES_CAPABLE BIT(4) +#define ASEL_CAP_RX_ASEL_CAPABLE BIT(5) +#define ASEL_CAP_TX_SOUNDING_CAPABLE BIT(6) + +/* 7.3.2.57 HT Operation element */ +#define ELEM_MAX_LEN_HT_OP (24 - ELEM_HDR_LEN) /* sizeof(IE_HT_OP_T)-2 */ + +#define HT_OP_INFO1_SCO BITS(0, 1) +#define HT_OP_INFO1_STA_CHNL_WIDTH BIT(2) +#define HT_OP_INFO1_RIFS_MODE BIT(3) + +#define HT_OP_INFO2_HT_PROTECTION BITS(0, 1) +#define HT_OP_INFO2_NON_GF_HT_STA_PRESENT BIT(2) +#define HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT BIT(4) + +#define HT_OP_INFO3_DUAL_BEACON BIT(6) +#define HT_OP_INFO3_DUAL_CTS_PROTECTION BIT(7) +#define HT_OP_INFO3_STBC_BEACON BIT(8) +#define HT_OP_INFO3_LSIG_TXOP_FULL_SUPPORT BIT(9) +#define HT_OP_INFO3_PCO_ACTIVE BIT(10) +#define HT_OP_INFO3_PCO_PHASE BIT(11) + +/* 7.3.2.59 OBSS Scan Parameter element */ +#define ELEM_MAX_LEN_OBSS_SCAN (16 - ELEM_HDR_LEN) + +/* 7.3.2.60 20/40 BSS Coexistence element */ +#define ELEM_MAX_LEN_20_40_BSS_COEXIST (3 - ELEM_HDR_LEN) + +#define BSS_COEXIST_INFO_REQ BIT(0) +#define BSS_COEXIST_40M_INTOLERANT BIT(1) +#define BSS_COEXIST_20M_REQ BIT(2) +#define BSS_COEXIST_OBSS_SCAN_EXEMPTION_REQ BIT(3) +#define BSS_COEXIST_OBSS_SCAN_EXEMPTION_GRANT BIT(4) + +/* 802.11u 7.3.2.92 Interworking IE */ +#define ELEM_MAX_LEN_INTERWORKING (11 - ELEM_HDR_LEN) + +/* 802.11u 7.3.2.93 Advertisement Protocol IE */ +#define ELEM_MAX_LEN_ADV_PROTOCOL (4 - ELEM_HDR_LEN) + +/* 802.11u 7.3.2.96 Roaming Consortium IE */ +#define ELEM_MAX_LEN_ROAMING_CONSORTIUM (19 - ELEM_HDR_LEN) + +#define IW_IE_LENGTH_ANO 1 +#define IW_IE_LENGTH_ANO_VENUE 3 +#define IW_IE_LENGTH_ANO_HESSID 7 +#define IW_IE_LENGTH_ANO_VENUE_HESSID 9 + +#if CFG_SUPPORT_PASSPOINT +/* HOTSPOT 2.0 Indication IE*/ +#define ELEM_MAX_LEN_HS20_INDICATION 5 +#define ELEM_MIN_LEN_HS20_INDICATION 4 + +/* Hotspot Configuration*/ +#define ELEM_HS_CONFIG_DGAF_DISABLED_MASK BIT(0) /* Downstream Group-Addressed Forwarding */ +#endif /* CFG_SUPPORT_PASSPOINT */ + +/* MTK Vendor Specific OUI */ +#define ELEM_MIN_LEN_MTK_OUI 7 +#define VENDOR_OUI_MTK { 0x00, 0x0C, 0xE7 } +#define MTK_SYNERGY_CAP_SUPPORT_24G_MCS89 BIT(3) +#define MTK_SYNERGY_CAP0 (MTK_SYNERGY_CAP_SUPPORT_24G_MCS89) +#define MTK_SYNERGY_CAP1 0x0 +#define MTK_SYNERGY_CAP2 0x0 +#define MTK_SYNERGY_CAP3 0x0 + +/* 802.11h CSA element */ +#define ELEM_MIN_LEN_CSA 3 + +/* 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 */ + +#define ACTION_SM_TPC_REQ_LEN 5 +#define ACTION_SM_TPC_REPORT_LEN 7 +#define ACTION_SM_MEASURE_REQ_LEN 19 +#define ACTION_SM_MEASURE_REPORT_LEN 8 +#define ACTION_SM_BASIC_REPORT_LEN 12 +#define ACTION_SM_CCA_REPORT_LEN 12 +#define ACTION_SM_PRI_REPORT_LEN 19 +#define MIN_RCV_PWR 100 /* Negative value ((dBm) */ + +/* 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 + +/* 8.5.23.1 VHT Action */ +#define ACTION_VHT_COMPRESSED_BFEAMFORMING 0 +#define ACTION_GROUP_ID_MANAGEMENT 1 +#define ACTION_OPERATING_MODE_NOTIFICATION 2 + +/* 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 + +#if CFG_SUPPORT_PASSPOINT +#define VENDOR_OUI_TYPE_HS20 16 +#endif /* CFG_SUPPORT_PASSPOINT */ + +#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_CONTROL_TID_OFFSET 12 +#define CTRL_BAR_BAR_INFORMATION_OFFSET 18 +#define CTRL_BAR_BAR_INFORMATION_SSN_OFFSET 4 + +/******************************************************************************* +* 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; + +typedef struct _BOOTP_PROTOCOL_T { + UINT_8 ucOperation; + UINT_8 ucHdrType; + UINT_8 ucHdrLen; + UINT_8 ucHops; + UINT_32 u4TransId; + UINT_16 u2Seconds; + UINT_16 u2Flags; + UINT_32 u4CIAddr; + UINT_32 u4YIAddr; + UINT_32 u4SIAddr; + UINT_32 u4GIAddr; + UINT_8 aucCHAddr[16]; + UINT_8 aucServerName[64]; + UINT_8 aucFileName[128]; + UINT_8 aucOptions[0]; +} __KAL_ATTRIB_PACKED__ BOOTP_PROTOCOL_T, *P_BOOTP_PROTOCOL_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 */ +#if CFG_SUPPORT_CFG80211_AUTH + BOOLEAN aucAuthData[AUTH_DATA_MAX_LEN]; +#else + UINT_16 u2AuthTransSeqNo; /* Authentication transaction sequence number */ + UINT_16 u2StatusCode; /* Status code */ +#endif + 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.19 Supported Channels element*/ +typedef struct _IE_SUPPORTED_CHANNELS_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucChannelNum[0]; +} __KAL_ATTRIB_PACKED__ IE_SUPPORTED_CHANNELS_T, *P_IE_SUPPORTED_CHANNELS_T; + +/* 7.3.2.20 Channel Switch Announcement element*/ +typedef struct _IE_CHANNEL_SWITCH_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucChannelSwitchMode; + UINT_8 ucNewChannelNum; + UINT_8 ucChannelSwitchCount; +} __KAL_ATTRIB_PACKED__ IE_CHANNEL_SWITCH_T, *P_IE_CHANNEL_SWITCH_T; + +typedef struct _IE_TIMEOUT_INTERVAL_T { + UINT_8 ucId; + UINT_8 ucLength; +#define IE_TIMEOUT_INTERVAL_TYPE_RESERVED 0 +#define IE_TIMEOUT_INTERVAL_TYPE_REASSOC 1 +#define IE_TIMEOUT_INTERVAL_TYPE_KEY_LIFETIME 43200 +#define IE_TIMEOUT_INTERVAL_TYPE_ASSOC_COMEBACK 3 + UINT_8 ucType; + UINT_32 u4Value; +} __KAL_ATTRIB_PACKED__ IE_TIMEOUT_INTERVAL_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; + +/* 7.3.2.60 20/40 BSS Coexistence element */ +typedef struct _IE_SUP_OPERATING_CLASS_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucCur; + UINT_8 ucSup[255]; +} __KAL_ATTRIB_PACKED__ IE_SUP_OPERATING_CLASS_T, *P_IE_SUP_OPERATING_CLASS_T; + +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; + +/*8.4.2.160.3 VHT Supported MCS Set field*/ +typedef struct _VHT_SUPPORTED_MCS_FIELD { + UINT_16 u2RxMcsMap; + UINT_16 u2RxHighestSupportedDataRate; + UINT_16 u2TxMcsMap; + UINT_16 u2TxHighestSupportedDataRate; +} __KAL_ATTRIB_PACKED__ VHT_SUPPORTED_MCS_FIELD, *P_VHT_SUPPORTED_MCS_FIELD; + +typedef struct _IE_VHT_CAP_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_32 u4VhtCapInfo; + VHT_SUPPORTED_MCS_FIELD rVhtSupportedMcsSet; +} __KAL_ATTRIB_PACKED__ IE_VHT_CAP_T, *P_IE_VHT_CAP_T; + +/*8.4.2.161 VHT Operation element*/ +typedef struct _IE_VHT_OP_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucVhtOperation[3]; + UINT_16 u2VhtBasicMcsSet; +} __KAL_ATTRIB_PACKED__ IE_VHT_OP_T, *P_IE_VHT_OP_T; + +/*8.4.1.50 Operating Mode field*/ +typedef struct _IE_VHT_OP_MODE_NOTIFICATION_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucOperatingMode; +} __KAL_ATTRIB_PACKED__ IE_VHT_OP_MODE_NOTIFICATION_T, *P_IE_VHT_OP_MODE_NOTIFICATION_T; + + +/*8.4.2.22 Secondary Channel Offset element*/ +typedef struct _IE_SECONDARY_OFFSET_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucSecondaryOffset; +} __KAL_ATTRIB_PACKED__ IE_SECONDARY_OFFSET_T, *P_IE_SECONDARY_OFFSET_T; + +/*8.4.2.105 Mesh Channel Switch Parameters element*/ +typedef struct _IE_MESH_CHANNEL_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucTimetoLive; + UINT_8 ucFlags; + UINT_16 u2ReasonCodes; + UINT_16 u2ProcedenceValue; +} __KAL_ATTRIB_PACKED__ IE_MESH_CHANNEL_T, *P_IE_MESH_CHANNEL_T; + +/*8.4.2.163 Wide Bandwidth Channel Switch element*/ +typedef struct _IE_WIDE_BAND_CHANNEL_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucNewChannelWidth; + UINT_8 ucChannelS1; + UINT_8 ucChannelS2; +} __KAL_ATTRIB_PACKED__ IE_WIDE_BAND_CHANNEL_T, *P_IE_WIDE_BAND_CHANNEL_T; + +/*8.4.2.168 Operating Mode Notification element*/ +typedef struct _IE_OP_MODE_NOTIFICATION_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucOpMode; +} __KAL_ATTRIB_PACKED__ IE_OP_MODE_NOTIFICATION_T, *P_IE_OP_MODE_NOTIFICATION_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.1.3 Spectrum TPC Request frame format */ +typedef struct _ACTION_TPC_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 ucElemId; /* Element ID */ + UINT_8 ucLength; /* Length */ +} __KAL_ATTRIB_PACKED__ ACTION_TPC_REQ_FRAME, *P_ACTION_TPC_REQ_FRAME; + +/* 7.4.1.4 Spectrum TPC Report frame format */ +typedef struct _ACTION_TPC_REPORT_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 ucElemId; /* Element ID */ + UINT_8 ucLength; /* Length */ + UINT_8 ucTransPwr; /* Transmit Power */ + UINT_8 ucLinkMargin; /* Link Margin */ +} __KAL_ATTRIB_PACKED__ ACTION_TPC_REPORT_FRAME, *P_ACTION_TPC_REPORT_FRAME; + +/* 7.4.1.5 Channel Switch Announcement frame format */ +typedef struct _ACTION_CHANNEL_SWITCH_FRAME { + /* ADDTS Request MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* ADDTS Request frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 aucInfoElem[1]; /* Information elements */ +} __KAL_ATTRIB_PACKED__ ACTION_CHANNEL_SWITCH_FRAME, *P_ACTION_CHANNEL_SWITCH_FRAME; + +/* 7.4.2.1 ADDTS Request frame format */ +typedef struct _ACTION_ADDTS_REQ_FRAME { + /* ADDTS Request MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* ADDTS Request frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 aucInfoElem[1]; /* Information elements, such as */ + /* TS Delay, and etc. */ +} __KAL_ATTRIB_PACKED__ ACTION_ADDTS_REQ_FRAME, *P_ACTION_ADDTS_REQ_FRAME; + +/* 7.4.2.2 ADDTS Response frame format */ +typedef struct _ACTION_ADDTS_RSP_FRAME { + /* ADDTS Response MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* ADDTS Response frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 ucStatusCode; /* WMM Status Code is of one byte */ + UINT_8 aucInfoElem[1]; /* Information elements, such as */ + /* TS Delay, and etc. */ +} __KAL_ATTRIB_PACKED__ ACTION_ADDTS_RSP_FRAME, *P_ACTION_ADDTS_RSP_FRAME; + +/* 7.4.2.3 DELTS frame format */ +typedef struct _ACTION_DELTS_FRAME { + /* DELTS MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* DELTS frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 aucTsInfo[3]; /* TS Info */ +} __KAL_ATTRIB_PACKED__ ACTION_DELTS_FRAME, *P_ACTION_DELTS_FRAME; + +/* 7.4.4.1 ADDBA Request frame format */ +typedef struct _ACTION_ADDBA_REQ_FRAME_T { + /* Action MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Action frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token chosen by the sender */ + UINT_8 aucBAParameterSet[2]; /* BA policy, TID, buffer size */ + UINT_8 aucBATimeoutValue[2]; + UINT_8 aucBAStartSeqCtrl[2]; /* SSN */ +} __KAL_ATTRIB_PACKED__ ACTION_ADDBA_REQ_FRAME_T, *P_ACTION_ADDBA_REQ_FRAME_T; + +typedef struct _ACTION_ADDBA_REQ_BODY_T { + UINT_16 u2BAParameterSet; /* BA policy, TID, buffer size */ + UINT_16 u2BATimeoutValue; + UINT_16 u2BAStartSeqCtrl; /* SSN */ +} __KAL_ATTRIB_PACKED__ ACTION_ADDBA_REQ_BODY_T, *P_ACTION_ADDBA_REQ_BODY_T; + +/* 7.4.4.2 ADDBA Response frame format */ +typedef struct _ACTION_ADDBA_RSP_FRAME_T { + /* Action MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Action frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token chosen by the sender */ + UINT_8 aucStatusCode[2]; + UINT_8 aucBAParameterSet[2]; /* BA policy, TID, buffer size */ + UINT_8 aucBATimeoutValue[2]; +} __KAL_ATTRIB_PACKED__ ACTION_ADDBA_RSP_FRAME_T, *P_ACTION_ADDBA_RSP_FRAME_T; + +typedef struct _ACTION_ADDBA_RSP_BODY_T { + UINT_16 u2StatusCode; + UINT_16 u2BAParameterSet; /* BA policy, TID, buffer size */ + UINT_16 u2BATimeoutValue; +} __KAL_ATTRIB_PACKED__ ACTION_ADDBA_RSP_BODY_T, *P_ACTION_ADDBA_RSP_BODY_T; + +/* 7.4.4.3 DELBA frame format */ +typedef struct _ACTION_DELBA_FRAME_T { + /* Action MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Action frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_16 u2DelBaParameterSet; /* Bit 11 Initiator, Bits 12-15 TID */ + UINT_16 u2ReasonCode; /* 7.3.1.7 */ +} __KAL_ATTRIB_PACKED__ ACTION_DELBA_FRAME_T, *P_ACTION_DELBA_FRAME_T; + +/* 7.4.6.1 Radio Measurement Request frame format */ +typedef struct _ACTION_RM_REQ_FRAME { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Radio Measurement Request frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_16 u2Repetitions; /* Number of repetitions */ + UINT_8 aucInfoElem[1]; /* Measurement Request elements, such as */ + /* channel load request, and etc. */ +} __KAL_ATTRIB_PACKED__ ACTION_RM_REQ_FRAME, *P_ACTION_RM_REQ_FRAME; + +/* 7.4.6.2 Radio Measurement Report frame format */ +typedef struct _ACTION_RM_REPORT_FRAME { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Radio Measurement Report frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 aucInfoElem[1]; /* Measurement Report elements, such as */ + /* channel load report, and etc. */ +} __KAL_ATTRIB_PACKED__ ACTION_RM_REPORT_FRAME, *P_ACTION_RM_REPORT_FRAME; + +/* 7.4.7.1a 20/40 BSS Coexistence Management frame format */ +typedef struct _ACTION_20_40_COEXIST_FRAME { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* BSS Coexistence Management frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + + IE_20_40_COEXIST_T rBssCoexist; /* 20/40 BSS coexistence element */ + IE_INTOLERANT_CHNL_REPORT_T rChnlReport; /* Intolerant channel report */ + +} __KAL_ATTRIB_PACKED__ ACTION_20_40_COEXIST_FRAME, *P_ACTION_20_40_COEXIST_FRAME; + +#if CFG_SUPPORT_802_11W +/* 7.4.9 SA Query Management frame format */ +typedef struct _ACTION_SA_QUERY_FRAME { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* BSS Coexistence Management frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + + UINT_8 ucTransId[ACTION_SA_QUERY_TR_ID_LEN]; /* Transaction id */ + +} __KAL_ATTRIB_PACKED__ ACTION_SA_QUERY_FRAME, *P_ACTION_SA_QUERY_FRAME; +#endif + +/* 7.4.10 Notify Channel Width Management frame format */ +typedef struct _ACTION_NOTIFY_CHNL_WIDTH_FRAME { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* BSS Coexistence Management frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucChannelWidth; /* Channel Width */ +} __KAL_ATTRIB_PACKED__ ACTION_NOTIFY_CHNL_WIDTH_FRAME, *P_ACTION_NOTIFY_CHNL_WIDTH_FRAME; + +/* 802.11v Wireless Network Management: Timing Measurement Request */ +typedef struct _ACTION_WNM_TIMING_MEAS_REQ_FRAME { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Timing Measurement Request Management frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucTrigger; /* Trigger */ +} __KAL_ATTRIB_PACKED__ ACTION_WNM_TIMING_MEAS_REQ_FRAME, *P_ACTION_WNM_TIMING_MEAS_REQ_FRAME; + +/* 802.11v Wireless Network Management: Timing Measurement */ +typedef struct _ACTION_UNPROTECTED_WNM_TIMING_MEAS_FRAME { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Timing Measurement Management frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 ucFollowUpDialogToken; /* Follow Up Dialog Token */ + UINT_32 u4ToD; /* Timestamp of Departure [10ns] */ + UINT_32 u4ToA; /* Timestamp of Arrival [10ns] */ + UINT_8 ucMaxToDErr; /* Maximum of ToD Error [10ns] */ + UINT_8 ucMaxToAErr; /* Maximum of ToA Error [10ns] */ +} __KAL_ATTRIB_PACKED__ ACTION_UNPROTECTED_WNM_TIMING_MEAS_FRAME, *P_ACTION_UNPROTECTED_WNM_TIMING_MEAS_FRAME; + +/* 8.5.23.4 Operating Mode Notification frame format */ +typedef struct _ACTION_OP_MODE_NOTIFICATION_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 */ + /* Operating Mode Notification frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucOperatingMode; /* Operating Mode */ +} __KAL_ATTRIB_PACKED__ ACTION_OP_MODE_NOTIFICATION_FRAME, *P_ACTION_OP_MODE_NOTIFICATION_FRAME; + +/* 8.5.12.3 SM Power Save frame format */ +typedef struct _ACTION_SM_POWER_SAVE_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 */ + /* SM power save frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucSmPowerCtrl; /* SM Power Control (see 8.4.1.22) */ +} __KAL_ATTRIB_PACKED__ ACTION_SM_POWER_SAVE_FRAME, *P_ACTION_SM_POWER_SAVE_FRAME; + +/* 8.5.12.2 Notify Channel Width frame format */ +typedef struct _ACTION_NOTIFY_CHANNEL_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 */ + /* SM power save frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucChannelWidth; /* Channel Width (see 8.4.1.21) */ +} __KAL_ATTRIB_PACKED__ ACTION_NOTIFY_CHANNEL_WIDTH_FRAME, *P_ACTION_NOTIFY_CHANNEL_WIDTH_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; + +#if CFG_SUPPORT_PASSPOINT +/* HS20 3.1 - HS 2.0 Indication Information Element */ +typedef struct _IE_HS20_INDICATION_T { + UINT_8 ucId; /* Element ID */ + UINT_8 ucLength; /* Length */ + UINT_8 aucOui[3]; /* OUI */ + UINT_8 ucType; /* Type */ + UINT_8 ucHotspotConfig; /* Hotspot Configuration */ +} __KAL_ATTRIB_PACKED__ IE_HS20_INDICATION_T, *P_IE_HS20_INDICATION_T; +#endif /* CFG_SUPPORT_PASSPOINT */ + +/* 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; + +/* Information Elements from MTK Synergies.*/ +typedef struct _IE_MTK_OUI_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucOui[3]; + UINT_8 aucCapability[4]; + UINT_8 aucInfoElem[1]; +} __KAL_ATTRIB_PACKED__ IE_MTK_OUI_T, *P_IE_MTK_OUI_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 POWER_CAP_IE(fp) ((P_IE_POWER_CAP_T) fp) + +#define SUP_CH_IE(fp) ((P_IE_SUPPORTED_CHANNELS_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 VHT_CAP_IE(fp) ((P_IE_VHT_CAP_T) fp) + +#define VHT_OP_IE(fp) ((P_IE_VHT_OP_T) fp) + +#define OBSS_SCAN_PARAM_IE(fp) ((P_IE_OBSS_SCAN_PARAM_T) fp) + +#define BSS_20_40_COEXIST_IE(fp) ((P_IE_20_40_COEXIST_T) fp) + +#define SUP_OPERATING_CLASS_IE(fp) ((P_IE_SUP_OPERATING_CLASS_T) fp) + +#define QUIET_IE(fp) ((P_IE_QUIET_T) fp) + +#define MTK_OUI_IE(fp) ((P_IE_MTK_OUI_T) fp) + +#define CSA_IE(fp) ((P_IE_CHANNEL_SWITCH_T) fp) + +#define SUPPORTED_CHANNELS_IE(fp) ((P_IE_SUPPORTED_CHANNELS_T)fp) +#define TIMEOUT_INTERVAL_IE(fp) ((IE_TIMEOUT_INTERVAL_T *)fp) + +#define SM_TPC_REQ_IE(fp) ((P_IE_TPC_REQ_T) fp) +#define SM_TPC_REP_IE(fp) ((P_IE_TPC_REPORT_T) fp) +#define SM_MEASUREMENT_REQ_IE(fp) ((P_IE_MEASUREMENT_REQ_T) fp) +#define SM_MEASUREMENT_REP_IE(fp) ((P_IE_MEASUREMENT_REPORT_T) fp) +#define SM_BASIC_REQ_IE(fp) ((P_SM_BASIC_REQ_T) fp) + +/* The macro to check if the MAC address is B/MCAST Address */ +#define IS_BMCAST_MAC_ADDR(_pucDestAddr) \ + ((BOOLEAN) (((PUINT_8)(_pucDestAddr))[0] & BIT(0))) + +/* The macro to check if the MAC address is UCAST Address */ +#define IS_UCAST_MAC_ADDR(_pucDestAddr) \ + ((BOOLEAN) !(((PUINT_8)(_pucDestAddr))[0] & BIT(0))) + +/* The macro to copy the MAC address */ +#define COPY_MAC_ADDR(_pucDestAddr, _pucSrcAddr) \ + kalMemCopy(_pucDestAddr, _pucSrcAddr, MAC_ADDR_LEN) + +/* The macro to check if two MAC addresses are equal */ +#define EQUAL_MAC_ADDR(_pucDestAddr, _pucSrcAddr) \ + (!kalMemCmp(_pucDestAddr, _pucSrcAddr, MAC_ADDR_LEN)) + +/* The macro to check if two MAC addresses are not equal */ +#define UNEQUAL_MAC_ADDR(_pucDestAddr, _pucSrcAddr) \ + (kalMemCmp(_pucDestAddr, _pucSrcAddr, MAC_ADDR_LEN)) + +/* The macro to check whether two SSIDs are equal */ +#define EQUAL_SSID(pucSsid1, ucSsidLen1, pucSsid2, ucSsidLen2) \ + ((ucSsidLen1 <= ELEM_MAX_LEN_SSID) && \ + (ucSsidLen2 <= ELEM_MAX_LEN_SSID) && \ + ((ucSsidLen1) == (ucSsidLen2)) && \ + !kalMemCmp(pucSsid1, pucSsid2, ucSsidLen1)) + +/* The macro to check whether two SSIDs are equal */ +#define UNEQUAL_SSID(pucSsid1, ucSsidLen1, pucSsid2, ucSsidLen2) \ + ((ucSsidLen1 > ELEM_MAX_LEN_SSID) || \ + (ucSsidLen2 > ELEM_MAX_LEN_SSID) || \ + ((ucSsidLen1) != (ucSsidLen2)) || \ + kalMemCmp(pucSsid1, pucSsid2, ucSsidLen1)) + +/* The macro to copy the SSID, the length of pucDestSsid should have at least 32 bytes */ +#define COPY_SSID(pucDestSsid, ucDestSsidLen, pucSrcSsid, ucSrcSsidLen) \ + do { \ + ucDestSsidLen = ucSrcSsidLen; \ + if (ucSrcSsidLen) { \ + ASSERT(ucSrcSsidLen <= ELEM_MAX_LEN_SSID); \ + kalMemCopy(pucDestSsid, pucSrcSsid, \ + ((ucSrcSsidLen > ELEM_MAX_LEN_SSID) ? ELEM_MAX_LEN_SSID : ucSrcSsidLen)); \ + } \ + } while (FALSE) + +/* The macro to copy the IE */ +#define COPY_IE(pucDestIE, pucSrcIE) \ + do { \ + kalMemCopy((PUINT_8)pucDestIE, \ + (PUINT_8)pucSrcIE,\ + IE_SIZE(pucSrcIE)); \ + } while (FALSE) + +#define IE_FOR_EACH(_pucIEsBuf, _u2IEsBufLen, _u2Offset) \ + for ((_u2Offset) = 0; \ + ((((_u2Offset) + 2) <= (_u2IEsBufLen)) && (((_u2Offset) + IE_SIZE(_pucIEsBuf)) <= (_u2IEsBufLen))); \ + (_u2Offset) += IE_SIZE(_pucIEsBuf), (_pucIEsBuf) += IE_SIZE(_pucIEsBuf)) + +#define SET_EXT_CAP(_aucField, _ucFieldLength, _ucBit) \ + do { \ + if ((_ucBit) < ((_ucFieldLength) * 8)) { \ + PUINT_8 aucExtCap = (PUINT_8)(_aucField); \ + ((aucExtCap)[(_ucBit) / 8]) |= BIT((_ucBit) % 8); \ + } \ + } while (FALSE) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _MAC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/mt66xx_reg.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/mt66xx_reg.h new file mode 100644 index 0000000000000..ca7419743af6b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/mt66xx_reg.h @@ -0,0 +1,993 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: +*/ + +/*! \file "mt66xx_reg.h" + * \brief The common register definition of MT6630 + * + * N/A +*/ + + + +#ifndef _MT66XX_REG_H +#define _MT66XX_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 +******************************************************************************** +*/ + +extern struct mt66xx_hif_driver_data mt66xx_driver_data_mt6632; +extern struct mt66xx_hif_driver_data mt66xx_driver_data_mt7668; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* 1 MT6630 MCR Definition */ + +/* 2 Host Interface */ + +/* #define TOP_CFG_BASE 0x0000 */ +#define TOP_CFG_BASE 0x80020000 +#define TOP_RGU_BASE 0x81020000 +#define TOP_CFG_AON_base 0x81021000 +#define MCU_CFG_BASE 0x80000000 + +#define TOP_HVR (TOP_CFG_BASE + 0x1000) +#define HW_VER_MASK (0xffff) +#define GET_HW_VER(p) (((p) & HW_VER_MASK)) +#define RESC_CID_MASK (0xf << 28) +#define GET_RESC_CID(p) (((p) & RESC_CID_MASK) >> 28) + +#define TOP_FVR (TOP_CFG_BASE + 0x1004) +#define FW_VER_MASK (0xff) +#define GET_FW_VER(p) (((p) & FW_VER_MASK)) + +#define TOP_HCR (TOP_CFG_BASE + 0x1008) +#define HW_CODE_MASK (0xffff) +#define GET_HW_CODE(p) (((p) & HW_CODE_MASK)) + +#define STRAP_STA (TOP_CFG_BASE + 0x1010) +#define XTAL_SEL_MASK (0x3) +#define GET_XTAL_SEL(p) (((p) & XTAL_SEL_MASK)) +#define EEPROM_SEL (1 << 2) +#define GET_EEPROM_SEL(p) (((p) & EEPROM_SEL) >> 2) +#define CO_CLOCK_SEL (1 << 8) +#define GET_CO_CLOCK_SEL(p) (((p) & CO_CLOCK_SEL) >> 8) +#define ONE_ANT (1 << 24) +#define GET_ONE_ANT(p) (((p) & ONE_ANT) >> 24) +#define USB_MODE (1 << 25) +#define GET_USB_MODE(p) (((p) & USB_MODE) >> 25) + +#define TOP_MISC2 (TOP_CFG_BASE + 0x1134) + +#define TOP_CKGEN2_CR_PMIC_CK_MANUAL (TOP_CFG_AON_base + 0x00000108) +#define TOP_CKGEN2_CR_PMIC_CK_MANUAL_MASK 0x00080000 + +#define MTK_CHIP_REV 0x00006632 + +#define WIFI_RGU_SW_SYNC0 (TOP_RGU_BASE + 0x1250) +#define WIFI_RGU_SYNC0_RDY_OFFSET (0) +#define MCU_CFG_PCIE_REMAP1 (MCU_CFG_BASE + 0x0500) +#define PCIE_REMAP1_OFFSET (18) +#define PCIE_REMAP1_MASK (BITS(18, 31)) +#define PCIE_REMAP1_BUS_ADDR (0x40000) +#define MCU_CFG_PCIE_REMAP2 (MCU_CFG_BASE + 0x0504) +#define PCIE_REMAP2_OFFSET (19) +#define PCIE_REMAP2_MASK (BITS(19, 31)) +#define PCIE_REMAP2_BUS_ADDR (0x80000) + + + +/* UMAC Register */ +#define UMAC_PLE_CR_CFG_BASE_ADDR 0x82060000 +#define UMAC_PSE_CR_CFG_BASE_ADDR 0x82068000 + +#define UMAC_PSE_PLE_CR_ADDR_DIFF (UMAC_PSE_CR_CFG_BASE_ADDR - UMAC_PLE_CR_CFG_BASE_ADDR) +#define UMAC_PSE_CR_BITMAP_OFFSET 15 +#define UMAC_PSE_PLE_ADDR_DIFF_MAR(_x) (_x << UMAC_PSE_CR_BITMAP_OFFSET) + + +#define UMAC_PLE_BASE_ADDRESS (0xa << 28) + +#define UMAC_PSE_BASE_ADDRESS (0xb << 28) + +#define UMAC_FID_SHIFT_16_BIT_VM_MAP 16 + +#define UMAC_BASE(_x) (UMAC_PLE_CR_CFG_BASE_ADDR | (_x << UMAC_PSE_CR_BITMAP_OFFSET)) + +#define UMAC_RESET(_x) (UMAC_BASE(_x) + 0x00000000) + +#define UMAC_INT_CR4_EN_MASK(_x) (UMAC_BASE(_x) + 0x00000004) +#define UMAC_INT_CR4_STS(_x) (UMAC_BASE(_x) + 0x00000008) +#define UMAC_INT_CR4_ERR_RES(_x) (UMAC_BASE(_x) + 0x0000000C) +#define UMAC_INT_CR4_ERR_MASK(_x) (UMAC_BASE(_x) + 0x00000010) + + + +#define UMAC_PBUF_CTRL(_x) (UMAC_BASE(_x) + 0x00000014) + +#define UMAC_CHIP_ID_VER(_x) (UMAC_BASE(_x) + 0x00000018) + +#define UMAC_TIMER_CNF(_x) (UMAC_BASE(_x) + 0x0000001C) + +#define UMAC_INT_N9_EN_MASK(_x) (UMAC_BASE(_x) + 0x00000020) +#define UMAC_INT_N9_STS(_x) (UMAC_BASE(_x) + 0x00000024) +#define UMAC_INT_N9_ERR_STS(_x) (UMAC_BASE(_x) + 0x00000028) +#define UMAC_INT_N9_ERR_MASK(_x) (UMAC_BASE(_x) + 0x0000002C) +#define UMAC_IGNORE_BUSY_EN_MASK(_x) (UMAC_BASE(_x) + 0x0000038C) + +#define UMAC_RELEASE_CTRL(_x) (UMAC_BASE(_x) + 0x00000030) + +#define UMAC_HIF_REPROT(_x) (UMAC_BASE(_x) + 0x00000034) + + +#define UMAC_C_GET_FID_0(_x) (UMAC_BASE(_x) + 0x00000040) +#define UMAC_C_GET_FID_1(_x) (UMAC_BASE(_x) + 0x00000044) + +#define UMAC_C_EN_QUEUE_0(_x) (UMAC_BASE(_x) + 0x00000060) +#define UMAC_C_EN_QUEUE_1(_x) (UMAC_BASE(_x) + 0x00000064) +#define UMAC_C_EN_QUEUE_2(_x) (UMAC_BASE(_x) + 0x00000068) + + +#define UMAC_C_DE_QUEUE_0(_x) (UMAC_BASE(_x) + 0x00000080) +#define UMAC_C_DE_QUEUE_1(_x) (UMAC_BASE(_x) + 0x00000084) +#define UMAC_C_DE_QUEUE_2(_x) (UMAC_BASE(_x) + 0x00000088) +#define UMAC_C_DE_QUEUE_3(_x) (UMAC_BASE(_x) + 0x0000008C) + +#define UMAC_ALLOCATE_0(_x) (UMAC_BASE(_x) + 0x000000A0) +#define UMAC_ALLOCATE_1(_x) (UMAC_BASE(_x) + 0x000000A4) +#define UMAC_ALLOCATE_2(_x) (UMAC_BASE(_x) + 0x000000A8) + +#define UMAC_QUEUE_EMPTY(_x) (UMAC_BASE(_x) + 0x000000B0) + +/* 0x820680B4 QUEUE_EMPTY_MASK Queue empty status mask register, 7615 E3 eco item only PSE with this setting, but ple */ +#define UMAC_QUEUE_EMPTY_MASK (UMAC_BASE(UMAC_PSE_CFG_POOL_INDEX) + 0x000000B4) + +#define UMAC_TO_CR4_INT(_x) (UMAC_BASE(_x) + 0x000000e0) +#define UMAC_TO_N9_INT(_x) (UMAC_BASE(_x) + 0x000000f0) + + +#define UMAC_FREEPG_CNT(_x) (UMAC_BASE(_x) + 0x00000100) + +#define UMAC_FREEPG_HEAD_TAIL(_x) (UMAC_BASE(_x) + 0x00000104) + + +#define UMAC_PG_HIF0_GROUP(_x) (UMAC_BASE(_x) + 0x00000110) +#define UMAC_HIF0_PG_INFO(_x) (UMAC_BASE(_x) + 0x00000114) + +#define UMAC_PG_HIF1_GROUP(_x) (UMAC_BASE(_x) + 0x00000118) +#define UMAC_HIF1_PG_INFO(_x) (UMAC_BASE(_x) + 0x0000011C) + +#define UMAC_PG_CPU_GROUP(_x) (UMAC_BASE(_x) + 0x00000150) +#define UMAC_CPU_PG_INFO(_x) (UMAC_BASE(_x) + 0x00000154) + + +#define UMAC_PG_LMAC0_GROUP(_x) (UMAC_BASE(_x) + 0x00000170) +#define UMAC_LMAC0_PG_INFO(_x) (UMAC_BASE(_x) + 0x00000174) + +#define UMAC_PG_LMAC1_GROUP(_x) (UMAC_BASE(_x) + 0x00000178) +#define UMAC_LMAC1_PG_INFO(_x) (UMAC_BASE(_x) + 0x0000017C) + + +#define UMAC_PG_LMAC2_GROUP(_x) (UMAC_BASE(_x) + 0x00000180) +#define UMAC_LMAC2_PG_INFO(_x) (UMAC_BASE(_x) + 0x00000184) + +#define UMAC_PG_PLE_GROUP(_x) (UMAC_BASE(_x) + 0x00000190) +#define UMAC_PLE_PG_INFO(_x) (UMAC_BASE(_x) + 0x00000194) + + +#define UMAC_RL_BUF_CTRL_0(_x) (UMAC_BASE(_x) + 0x000001A0) +#define UMAC_RL_BUF_CTRL_1(_x) (UMAC_BASE(_x) + 0x000001A4) + +#define UMAC_FL_QUE_CTRL_0(_x) (UMAC_BASE(_x) + 0x000001B0) +#define UMAC_FL_QUE_CTRL_1(_x) (UMAC_BASE(_x) + 0x000001B4) +#define UMAC_FL_QUE_CTRL_2(_x) (UMAC_BASE(_x) + 0x000001B8) +#define UMAC_FL_QUE_CTRL_3(_x) (UMAC_BASE(_x) + 0x000001BC) + +#define UMAC_HIF_ENQ_PKT_NUM(_x) (UMAC_BASE(_x) + 0x000001F0) +#define UMAC_CPU_ENQ_PKT_NUM(_x) (UMAC_BASE(_x) + 0x000001F4) +#define UMAC_RLS_MSDU_PKT_NUM(_x) (UMAC_BASE(_x) + 0x000001F8) +#define UMAC_HOST_REPORT_NUM(_x) (UMAC_BASE(_x) + 0x000001FC) + +#define UMAC_PL_QUE_CTRL_0(_x) (UMAC_BASE(_x) + 0x000001C0) + +#define UMAC_TP_HIF_EN(_x) (UMAC_BASE(_x) + 0x00000200) + +#define UMAC_TP_HIF_Q_CTRL0(_x) (UMAC_BASE(_x) + 0x00000204) +#define UMAC_TP_HIF_Q_CTRL1(_x) (UMAC_BASE(_x) + 0x00000208) +#define UMAC_TP_HIF_Q_CTRL2(_x) (UMAC_BASE(_x) + 0x0000020C) + +#define UMAC_TP_HIF_ALLOC0(_x) (UMAC_BASE(_x) + 0x00000210) +#define UMAC_TP_HIF_ALLOC1(_x) (UMAC_BASE(_x) + 0x00000214) + +#define UMAC_TP_HIF_OPER0(_x) (UMAC_BASE(_x) + 0x00000218) +#define UMAC_TP_HIF_OPER1(_x) (UMAC_BASE(_x) + 0x0000021C) + + +#define UMAC_TP_LMAC_EN(_x) (UMAC_BASE(_x) + 0x00000220) + +#define UMAC_TP_LMAC_Q_CTRL0(_x) (UMAC_BASE(_x) + 0x00000224) +#define UMAC_TP_LMAC_Q_CTRL1(_x) (UMAC_BASE(_x) + 0x00000228) +#define UMAC_TP_LMAC_Q_CTRL2(_x) (UMAC_BASE(_x) + 0x0000022C) + +#define UMAC_TP_LMAC_ALLOC0(_x) (UMAC_BASE(_x) + 0x00000230) +#define UMAC_TP_LMAC_ALLOC1(_x) (UMAC_BASE(_x) + 0x00000234) + +#define UMAC_TP_LMAC_OPER0(_x) (UMAC_BASE(_x) + 0x00000238) +#define UMAC_TP_LMAC_OPER1(_x) (UMAC_BASE(_x) + 0x0000023C) + +#define UMAC_STATE_IDLE_CTL(_x) (UMAC_BASE(_x) + 0x0000024C) + +#define UMAC_DIS_STA_MAP0(_x) (UMAC_BASE(_x) + 0x00000260) +#define UMAC_DIS_STA_MAP1(_x) (UMAC_BASE(_x) + 0x00000264) +#define UMAC_DIS_STA_MAP2(_x) (UMAC_BASE(_x) + 0x00000268) +#define UMAC_DIS_STA_MAP3(_x) (UMAC_BASE(_x) + 0x0000026c) + +#define UMAC_AC0_QUEUE_EMPTY0(_x) (UMAC_BASE(_x) + 0x00000300) +#define UMAC_AC0_QUEUE_EMPTY1(_x) (UMAC_BASE(_x) + 0x00000304) +#define UMAC_AC0_QUEUE_EMPTY2(_x) (UMAC_BASE(_x) + 0x00000308) +#define UMAC_AC0_QUEUE_EMPTY3(_x) (UMAC_BASE(_x) + 0x0000030C) + +#define UMAC_AC1_QUEUE_EMPTY0(_x) (UMAC_BASE(_x) + 0x00000310) +#define UMAC_AC1_QUEUE_EMPTY1(_x) (UMAC_BASE(_x) + 0x00000314) +#define UMAC_AC1_QUEUE_EMPTY2(_x) (UMAC_BASE(_x) + 0x00000318) +#define UMAC_AC1_QUEUE_EMPTY3(_x) (UMAC_BASE(_x) + 0x0000031C) + +#define UMAC_AC2_QUEUE_EMPTY0(_x) (UMAC_BASE(_x) + 0x00000320) +#define UMAC_AC2_QUEUE_EMPTY1(_x) (UMAC_BASE(_x) + 0x00000324) +#define UMAC_AC2_QUEUE_EMPTY2(_x) (UMAC_BASE(_x) + 0x00000328) +#define UMAC_AC2_QUEUE_EMPTY3(_x) (UMAC_BASE(_x) + 0x0000032C) + +#define UMAC_AC3_QUEUE_EMPTY0(_x) (UMAC_BASE(_x) + 0x00000330) +#define UMAC_AC3_QUEUE_EMPTY1(_x) (UMAC_BASE(_x) + 0x00000334) +#define UMAC_AC3_QUEUE_EMPTY2(_x) (UMAC_BASE(_x) + 0x00000338) +#define UMAC_AC3_QUEUE_EMPTY3(_x) (UMAC_BASE(_x) + 0x0000033C) + +#define UMAC_QUEUE_EMPTY_MASK (UMAC_BASE(UMAC_PSE_CFG_POOL_INDEX) + 0x000000B4) + +/* BSS PS INT */ +#define UMAC_N9_BSS_PS_INT_EN (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000000F4) +#define UMAC_N9_BSS_PS_INT_STS (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000000F8) + +/* CR for VoW and BW Ctrl */ + +#define UMAC_DRR_TABLE_CTRL0 (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000388) + +#define UMAC_DRR_TABLE_WDATA0 (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000340) +#define UMAC_DRR_TABLE_WDATA1 (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000344) +#define UMAC_DRR_TABLE_WDATA2 (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000348) +#define UMAC_DRR_TABLE_WDATA3 (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x0000034C) + + +#define UMAC_DRR_TABLE_RDATA0 (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000350) +#define UMAC_DRR_TABLE_RDATA1 (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000354) +#define UMAC_DRR_TABLE_RDATA2 (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000358) +#define UMAC_DRR_TABLE_RDATA3 (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x0000035C) + + +#define UMAC_STATION_PAUSE_0 (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000360) +#define UMAC_STATION_PAUSE_1 (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000364) +#define UMAC_STATION_PAUSE_2 (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000368) +#define UMAC_STATION_PAUSE_3 (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x0000036C) +#define UMAC_VOW_ENABLE (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000370) +#define UMAC_AIR_TIME_DRR_SIZE (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000374) +#define UMAC_CHECK_TIME_TOKEN (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000378) +#define UMAC_CHECK_LENGTH_TOKEN (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x0000037C) +#define UMAC_WDRR0 (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000380) +#define UMAC_WDRR1 (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x00000384) + +#define UMAC_VOW_CTRL1 (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x0000038C) + +#define UMAC_VOW_DBG_MUX (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000003A0) +#define UMAC_AIRTIME_DBG_INFO0 (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000003A4) +#define UMAC_AIRTIME_DBG_INFO1 (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000003A8) + +#define UMAC_BW_DBG_INFO (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000003AC) + +#define UMAC_BW_WDRR0 (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000003B0) +#define UMAC_BW_WDRR1 (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000003B4) +#define UMAC_BW_WDRR2 (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000003B8) +#define UMAC_BW_WDRR3 (UMAC_BASE(UMAC_PLE_CFG_POOL_INDEX) + 0x000003BC) +/* UMAC Register */ + + +#if defined(_HIF_USB) + +#define WIFI_CFG_SW_SYNC0 (TOP_CFG_BASE + 0x1128) +#define WIFI_CFG_SYNC0_RDY_OFFSET (16) + +/* UDMA register */ +#define UDMA_BASE 0x50029000 +#define UDMA_TX_QSEL (UDMA_BASE + 0x8) +#define FW_DL_EN (1 << 3) + +#define UDMA_RESET (UDMA_BASE + 0x14) + +#define UDMA_WLCFG_1 (UDMA_BASE + 0xc) +#define UDMA_WLCFG_1_TX_TMOUT_LMT_MASK (0xfffff << 8) +#define UDMA_WLCFG_1_TX_TMOUT_LMT(p) (((p) & 0xfffff) << 8) +#define UDMA_WLCFG_1_RX_AGG_PKT_LMT_MASK (0xff << 0) +#define UDMA_WLCFG_1_RX_AGG_PKT_LMT(p) (((p) & 0xff) << 0) + +#define UDMA_WLCFG_0 (UDMA_BASE + 0x18) +#define UDMA_WLCFG_0_TX_BT_SIZE_MASK (0x07 << 27) +#define UDMA_WLCFG_0_TX_BT_SIZE(p) (((p) & 0x07) << 27) +#define UDMA_WLCFG_0_RX_BT_SIZE_MASK (0x07 << 24) +#define UDMA_WLCFG_0_RX_BT_SIZE(p) (((p) & 0x07) << 24) +#define UDMA_WLCFG_0_TX_EN_MASK (0x1 << 23) +#define UDMA_WLCFG_0_TX_EN(p) (((p) & 0x1) << 23) +#define UDMA_WLCFG_0_RX_EN_MASK (0x1 << 22) +#define UDMA_WLCFG_0_RX_EN(p) (((p) & 0x1) << 22) +#define UDMA_WLCFG_0_RX_AGG_EN_MASK (0x1 << 21) +#define UDMA_WLCFG_0_RX_AGG_EN(p) (((p) & 0x1) << 21) +#define UDMA_WLCFG_0_LPK_EN_MASK (0x1 << 20) +#define UDMA_WLCFG_0_LPK_EN(p) (((p) & 0x1) << 20) +#define UDMA_WLCFG_0_RX_MPSZ_PAD0_MASK (0x1 << 18) +#define UDMA_WLCFG_0_RX_MPSZ_PAD0(p) (((p) & 0x1) << 18) +#define UDMA_WLCFG_0_RX_AGG_LMT_MASK (0xff << 8) +#define UDMA_WLCFG_0_RX_AGG_LMT(p) (((p) & 0xff) << 8) +#define UDMA_WLCFG_0_RX_AGG_TO_MASK (0xff << 0) +#define UDMA_WLCFG_0_RX_AGG_TO(p) (((p) & 0xff) << 0) + +#define PP_R_RXCUTDISP0 (0x8206C054) +#define PP_R_RXCUTDISP0_CT_EN_MASK (0x1 << 0) +#define PP_R_RXCUTDISP0_CT_EN(p) (((p) & 0x1) << 0) +#define PP_R_RXCUTDISP0_CR4_EN_MASK (0x1 << 1) +#define PP_R_RXCUTDISP0_CR4_EN(p) (((p) & 0x1) << 1) +#define PP_R_RXCUTDISP0_START_OFFSET_MASK (0x3fff << 2) +#define PP_R_RXCUTDISP0_START_OFFSET(p) (((p) & 0x3fff) << 2) +#define PP_R_RXCUTDISP0_END_OFFSET_MASK (0x3fff << 18) +#define PP_R_RXCUTDISP0_END_OFFSET(p) (((p) & 0x3fff) << 18) + + +#elif defined(_HIF_PCIE) +#define RTC_TOP_BASE 0x0000 + +#define RTC_TOP_MISC2 (RTC_TOP_BASE + 0x1128) + +#define TOP_HIF_BASE 0x0000 +#define TOP_HW_VERSION (TOP_HIF_BASE + 0x1000) +#define TOP_HW_CONTROL (TOP_HIF_BASE + 0x1008) + +#define WIFI_CFG_SW_SYNC0 RTC_TOP_MISC2 +#define WIFI_CFG_SYNC0_RDY_OFFSET (16) + +#define PCIE_HIF_BASE 0x4000 + +/* HIF Sys Revision */ +#define HIF_SYS_REV (PCIE_HIF_BASE + 0x0000) + +/* HIF Low Power Control Host Register */ +#define CFG_PCIE_LPCR_HOST (PCIE_HIF_BASE + 0x01F0) + +/* HIF Low Power Control Fw Register */ +#define CFG_PCIE_LPCR_FW (PCIE_HIF_BASE + 0x01F4) + +/* Interrupt Status */ +#define WPDMA_INT_STA (PCIE_HIF_BASE + 0x0200) + +/* Interrupt Mask */ +#define WPDMA_INT_MSK (PCIE_HIF_BASE + 0x0204) + +/* Global Configuration */ +#define WPDMA_GLO_CFG (PCIE_HIF_BASE + 0x0208) + +/* Pointer Reset */ +#define WPDMA_RST_PTR (PCIE_HIF_BASE + 0x020C) + +/* Configuration for WPDMA Delayed Interrupt */ +#define WPDMA_DELAY_INT_CFG (PCIE_HIF_BASE + 0x0210) + +#define MT_WPDMA_PAUSE_RX_Q (PCIE_HIF_BASE + 0x0260) + +/* TX Ring0 Control 0 */ +#define WPDMA_TX_RING0_CTRL0 (PCIE_HIF_BASE + 0x0300) + +/* TX Ring0 Control 1 */ +#define WPDMA_TX_RING0_CTRL1 (PCIE_HIF_BASE + 0x0304) + +/* TX Ring0 Control 2 */ +#define WPDMA_TX_RING0_CTRL2 (PCIE_HIF_BASE + 0x0308) + +/* TX Ring0 Control 3 */ +#define WPDMA_TX_RING0_CTRL3 (PCIE_HIF_BASE + 0x030C) + +/* RX Ring0 Control 0 */ +#define WPDMA_RX_RING0_CTRL0 (PCIE_HIF_BASE + 0x0400) + +/* RX Ring0 Control 1 */ +#define WPDMA_RX_RING0_CTRL1 (PCIE_HIF_BASE + 0x0404) + +/* RX Ring0 Control 2 */ +#define WPDMA_RX_RING0_CTRL2 (PCIE_HIF_BASE + 0x0408) + +/* RX Ring0 Control 3 */ +#define WPDMA_RX_RING0_CTRL3 (PCIE_HIF_BASE + 0x040C) + +#define MT_WPDMA_GLO_CFG_1 (PCIE_HIF_BASE + 0x0500) + +#define MT_WPDMA_TX_PRE_CFG (PCIE_HIF_BASE + 0x0510) + +#define MT_WPDMA_RX_PRE_CFG (PCIE_HIF_BASE + 0x0520) + +#define MT_WPDMA_ABT_CFG (PCIE_HIF_BASE + 0x0530) + +#define MT_WPDMA_ABT_CFG1 (PCIE_HIF_BASE + 0x0534) + +/* WPDMA_INT_STA */ +typedef union _WPDMA_INT_STA_STRUCT { + struct { + UINT_32 rx_done_0:1; + UINT_32 rx_done_1:1; + UINT_32 err_det_int_0:1; + UINT_32 err_det_int_1:1; + UINT_32 tx_done_0:1; + UINT_32 tx_done_1:1; + UINT_32 tx_done_2:1; + UINT_32 tx_done_3:1; + UINT_32 tx_done_4:1; + UINT_32 tx_done_5:1; + UINT_32 tx_done_6:1; + UINT_32 tx_done_7:1; + UINT_32 tx_done_8:1; + UINT_32 tx_done_9:1; + UINT_32 tx_done_10:1; + UINT_32 tx_done_11:1; + UINT_32 tx_done_12:1; + UINT_32 tx_done_13:1; + UINT_32 rsv_18:1; + UINT_32 tx_done_15:1; + UINT_32 rx_coherent:1; + UINT_32 tx_coherent:1; + UINT_32 rx_dly_int:1; + UINT_32 tx_dly_int:1; + UINT_32 wf_mac_int_0:1; + UINT_32 wf_mac_int_1:1; + UINT_32 wf_mac_int_2:1; + UINT_32 wf_mac_int_3:1; + UINT_32 wf_mac_int_4:1; + UINT_32 wf_mac_int_5:1; + UINT_32 mcu_cmd_int:1; + UINT_32 fw_clr_own:1; + } field; + + UINT_32 word; +} WPDMA_INT_STA_STRUCT; + +/* WPDMA_INT_MSK */ +typedef union _WPDMA_INT_MASK { + struct { + UINT_32 rx_done_0:1; + UINT_32 rx_done_1:1; + UINT_32 err_det_int_0:1; + UINT_32 err_det_int_1:1; + UINT_32 tx_done_0:1; + UINT_32 tx_done_1:1; + UINT_32 tx_done_2:1; + UINT_32 tx_done_3:1; + UINT_32 tx_done_4:1; + UINT_32 tx_done_5:1; + UINT_32 tx_done_6:1; + UINT_32 tx_done_7:1; + UINT_32 tx_done_8:1; + UINT_32 tx_done_9:1; + UINT_32 tx_done_10:1; + UINT_32 tx_done_11:1; + UINT_32 tx_done_12:1; + UINT_32 tx_done_13:1; + UINT_32 rsv_18:1; + UINT_32 tx_done_15:1; + UINT_32 rx_coherent:1; + UINT_32 tx_coherent:1; + UINT_32 rx_dly_int:1; + UINT_32 tx_dly_int:1; + UINT_32 wf_mac_int_0:1; + UINT_32 wf_mac_int_1:1; + UINT_32 wf_mac_int_2:1; + UINT_32 wf_mac_int_3:1; + UINT_32 wf_mac_int_4:1; + UINT_32 wf_mac_int_5:1; + UINT_32 mcu_cmd_int:1; + UINT_32 fw_clr_own:1; + } field; + + UINT_32 word; +} WPMDA_INT_MASK; + +/* WPDMA_GLO_CFG */ +typedef union _WPDMA_GLO_CFG_STRUCT { + struct { + UINT_32 EnableTxDMA:1; + UINT_32 TxDMABusy:1; + UINT_32 EnableRxDMA:1; + UINT_32 RxDMABusy:1; + UINT_32 WPDMABurstSIZE:2; + UINT_32 EnTXWriteBackDDONE:1; + UINT_32 BigEndian:1; + UINT_32 Desc32BEn:1; + UINT_32 share_fifo_en:1; + UINT_32 multi_dma_en:2; + UINT_32 fifo_little_endian:1; + UINT_32 mi_depth:3; + UINT_32 err_det_th:8; + UINT_32 sw_rst:1; + UINT_32 force_tx_eof:1; + UINT_32 rsv_26:1; + UINT_32 omit_rx_info:1; + UINT_32 omit_tx_info:1; + UINT_32 byte_swap:1; + UINT_32 clk_gate_dis:1; + UINT_32 rx_2b_offset:1; + } field; + + struct { + UINT_32 EnableTxDMA:1; + UINT_32 TxDMABusy:1; + UINT_32 EnableRxDMA:1; + UINT_32 RxDMABusy:1; + UINT_32 WPDMABurstSIZE:2; + UINT_32 EnTXWriteBackDDONE:1; + UINT_32 BigEndian:1; + UINT_32 dis_bt_size_align:1; + UINT_32 tx_bt_size:1; + UINT_32 multi_dma_en:2; + UINT_32 fifo_little_endian:1; + UINT_32 mi_depth:3; + UINT_32 mi_depth_rd_3_5:3; + UINT_32 mi_depth_rd_8_6:3; + UINT_32 tx_bt_size_bit21:2; + UINT_32 sw_rst:1; + UINT_32 force_tx_eof:1; + UINT_32 first_token:1; + UINT_32 omit_rx_info:1; + UINT_32 omit_tx_info:1; + UINT_32 byte_swap:1; + UINT_32 reserve_30:1; + UINT_32 rx_2b_offset:1; + } field_1; + + UINT_32 word; +} WPDMA_GLO_CFG_STRUCT; + +/* WPDMA_RST_PTR */ +typedef union _WPDMA_RST_IDX_STRUCT { + struct { + UINT_32 RST_DTX_IDX0:1; + UINT_32 RST_DTX_IDX1:1; + UINT_32 rsv_2_15:14; + UINT_32 RST_DRX_IDX0:1; + UINT_32 RST_DRX_IDX1:1; + UINT_32 rsv_18_31:14; + } field; + + UINT_32 word; +} WPDMA_RST_IDX_STRUCT; + +/* WPDMA_DELAY_INT_CFG */ +typedef union _DELAY_INT_CFG_STRUCT { + struct { + UINT_32 RXMAX_PTIME:8; + UINT_32 RXMAX_PINT:7; + UINT_32 RXDLY_INT_EN:1; + UINT_32 TXMAX_PTIME:8; + UINT_32 TXMAX_PINT:7; + UINT_32 TXDLY_INT_EN:1; + } field; + + UINT_32 word; +} DELAY_INT_CFG_STRUCT; + +/* RTC_TOP_MISC2 */ +#define TOP_MISC2_CR4_INIT_DONE BIT(18) +#define TOP_MISC2_N9_INIT_DONE BIT(17) +#define TOP_MISC2_FW_READY BIT(16) +#define WLAN_READY_BITS BITS(16, 18) + +/* HIF_SYS_REV */ +#define PCIE_HIF_SYS_PROJ BITS(16, 31) +#define PCIE_HIF_SYS_REV BITS(0, 15) + +/* CFG_PCIE_LPCR_HOST */ +#define PCIE_LPCR_HOST_CLR_OWN BIT(1) +#define PCIE_LPCR_HOST_SET_OWN BIT(0) + +/* CFG_PCIE_LPCR_FW */ +#define PCIE_LPCR_FW_CLR_OWN BIT(0) + +/* WPDMA_INT_STA */ +#define WPDMA_FW_CLR_OWN_INT BIT(31) +#define WPDMA_TX_DONE_INT3 BIT(7) +#define WPDMA_TX_DONE_INT2 BIT(6) +#define WPDMA_TX_DONE_INT1 BIT(5) +#define WPDMA_TX_DONE_INT0 BIT(4) +#define WPDMA_RX_DONE_INT3 BIT(3) +#define WPDMA_RX_DONE_INT2 BIT(2) +#define WPDMA_RX_DONE_INT1 BIT(1) +#define WPDMA_RX_DONE_INT0 BIT(0) + +#else +#define WIFI_CFG_SW_SYNC0 0 +#define WIFI_CFG_SYNC0_RDY_OFFSET 0 +#endif + +/* 4 CHIP ID Register */ +#define MCR_WCIR 0x0000 + +/* 4 HIF Low Power Control Register */ +#define MCR_WHLPCR 0x0004 + +/* 4 Control Status Register */ +#define MCR_WSDIOCSR 0x0008 + +/* 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 0x0020 + +/* 4 WLAN Software Interrupt Control Register */ +#define MCR_WSICR 0x0024 + +/* 4 WLAN TX Data Register 1 */ +#define MCR_WTDR1 0x0034 + +/* 4 WLAN RX Data Register 0 */ +#define MCR_WRDR0 0x0050 + +/* 4 WLAN RX Data Register 1 */ +#define MCR_WRDR1 0x0054 + +/* 4 Host to Device Send Mailbox 0 Register */ +#define MCR_H2DSM0R 0x0070 + +/* 4 Host to Device Send Mailbox 1 Register */ +#define MCR_H2DSM1R 0x0074 + +/* 4 Device to Host Receive Mailbox 0 Register */ +#define MCR_D2HRM0R 0x0078 + +/* 4 Device to Host Receive Mailbox 1 Register */ +#define MCR_D2HRM1R 0x007c + +/* 4 WLAN RX Packet Length Register */ +#define MCR_WRPLR 0x0090 + +/* 4 Test Mode Data Port */ +#define MCR_WTMDR 0x00b0 + +/* 4 Test Mode Control Register */ +#define MCR_WTMCR 0x00b4 + +/* 4 Test Mode Data Pattern Control Register #0 */ +#define MCR_WTMDPCR0 0x00b8 + +/* 4 Test Mode Data Pattern Control Register #1 */ +#define MCR_WTMDPCR1 0x00bc + +/* 4 WLAN Packet Length Report Control Register */ +#define MCR_WPLRCR 0x00d4 + +/* 4 WLAN Snapshot Register */ +#define MCR_WSR 0x00D8 + +/* 4 Clock Pad Macro IO Control Register */ +#define MCR_CLKIOCR 0x0100 + +/* 4 Command Pad Macro IO Control Register */ +#define MCR_CMDIOCR 0x0104 + +/* 4 Data 0 Pad Macro IO Control Register */ +#define MCR_DAT0IOCR 0x0108 + +/* 4 Data 1 Pad Macro IO Control Register */ +#define MCR_DAT1IOCR 0x010C + +/* 4 Data 2 Pad Macro IO Control Register */ +#define MCR_DAT2IOCR 0x0110 + +/* 4 Data 3 Pad Macro IO Control Register */ +#define MCR_DAT3IOCR 0x0114 + +/* 4 Clock Pad Macro Delay Chain Control Register */ +#define MCR_CLKDLYCR 0x0118 + +/* 4 Command Pad Macro Delay Chain Control Register */ +#define MCR_CMDDLYCR 0x011C + +/* 4 SDIO Output Data Delay Chain Control Register */ +#define MCR_ODATDLYCR 0x0120 + +/* 4 SDIO Input Data Delay Chain Control Register 1 */ +#define MCR_IDATDLYCR1 0x0124 + +/* 4 SDIO Input Data Delay Chain Control Register 2 */ +#define MCR_IDATDLYCR2 0x0128 + +/* 4 SDIO Input Data Latch Time Control Register */ +#define MCR_ILCHCR 0x012C + +/* 4 WLAN TXQ Count Register 0 */ +#define MCR_WTQCR0 0x0130 + +/* 4 WLAN TXQ Count Register 1 */ +#define MCR_WTQCR1 0x0134 + +/* 4 WLAN TXQ Count Register 2 */ +#define MCR_WTQCR2 0x0138 + +/* 4 WLAN TXQ Count Register 3 */ +#define MCR_WTQCR3 0x013C + +/* 4 WLAN TXQ Count Register 4 */ +#define MCR_WTQCR4 0x0140 + +/* 4 WLAN TXQ Count Register 5 */ +#define MCR_WTQCR5 0x0144 + +/* 4 WLAN TXQ Count Register 6 */ +#define MCR_WTQCR6 0x0148 + +/* 4 WLAN TXQ Count Register 7 */ +#define MCR_WTQCR7 0x014C + +/* WLAN/Common PC value Debug registre */ +#define MCR_SWPCDBGR 0x0154 + +/* #if CFG_SDIO_INTR_ENHANCE */ +typedef struct _ENHANCE_MODE_DATA_STRUCT_T { + UINT_32 u4WHISR; + union { + struct { + UINT_16 u2TQ0Cnt; + UINT_16 u2TQ1Cnt; + UINT_16 u2TQ2Cnt; + UINT_16 u2TQ3Cnt; + UINT_16 u2TQ4Cnt; + UINT_16 u2TQ5Cnt; + UINT_16 u2TQ6Cnt; + UINT_16 u2TQ7Cnt; + UINT_16 u2TQ8Cnt; + UINT_16 u2TQ9Cnt; + UINT_16 u2TQ10Cnt; + UINT_16 u2TQ11Cnt; + UINT_16 u2TQ12Cnt; + UINT_16 u2TQ13Cnt; + UINT_16 u2TQ14Cnt; + UINT_16 u2TQ15Cnt; + } u; + UINT_32 au4WTSR[8]; + } 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 0x00006632 +#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_DB_CMD7_RESELECT_DIS BIT(4) +#define WSDIOCSR_DB_WR_BUSY_EN BIT(3) +#define WSDIOCSR_DB_RD_BUSY_EN BIT(2) +#define WSDIOCSR_SDIO_INT_CTL BIT(1) +#define WSDIOCSR_SDIO_RE_INIT_EN BIT(0) + +/* 3 WHCR 0x000C */ +#define WHCR_RX_ENHANCE_MODE_EN BIT(16) +#define WHCR_MAX_HIF_RX_LEN_NUM BITS(8, 13) +#define WHCR_RPT_OWN_RX_PACKET_LEN BIT(3) +#define WHCR_RECV_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 8 + +/* 3 WHISR 0x0010 */ +#define WHISR_D2H_SW_INT BITS(8, 31) +#define WHISR_D2H_SW_ASSERT_INFO_INT BIT(31) +#define WHISR_D2H_WKUP_BY_RX_PACKET BIT(30) +#define WHISR_D2H_SW_RD_MAILBOX_INT BIT(29) +#define WHISR_FW_OWN_BACK_INT BIT(7) +#define WHISR_ABNORMAL_INT BIT(6) +#define WHISR_RX1_DONE_INT BIT(2) +#define WHISR_RX0_DONE_INT BIT(1) +#define WHISR_TX_DONE_INT BIT(0) + +/* 3 WHIER 0x0014 */ +#define WHIER_D2H_SW_INT BITS(8, 31) +#define WHIER_FW_OWN_BACK_INT_EN BIT(7) +#define WHIER_ABNORMAL_INT_EN BIT(6) +#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 0x0020 */ +#define WASR_FW_OWN_INVALID_ACCESS BIT(16) +#define WASR_RX1_UNDER_FLOW BIT(9) +#define WASR_RX0_UNDER_FLOW BIT(8) +#define WASR_TX1_OVER_FLOW BIT(1) + +/* 3 WSICR 0x0024 */ +#define WSICR_H2D_SW_INT_SET BITS(16, 31) + +/* 3 WRPLR 0x0090 */ +#define WRPLR_RX1_PACKET_LENGTH BITS(16, 31) +#define WRPLR_RX0_PACKET_LENGTH BITS(0, 15) + +/* 3 WTMCR 0x00b4 */ +#define WMTCR_TEST_MODE_FW_OWN BIT(24) +#define WMTCR_PRBS_INIT_VAL BITS(16, 23) +#define WMTCR_TEST_MODE_STATUS BIT(8) +#define WMTCR_TEST_MODE_SELECT BITS(0, 1) + + + +/* Support features */ +/* Options for VLAN-over-ethernet pkt to/from 802.11 LLC VLAN pkt. + * This should depend on the configurations of HW-header-translation. + */ +#define FEAT_BITS_LLC_VLAN_TX BIT(0) +#define FEAT_BITS_LLC_VLAN_RX BIT(1) + +/* Support features API */ +#define FEAT_SUP_LLC_VLAN_TX(__chip_info) ((__chip_info)->features & FEAT_BITS_LLC_VLAN_TX) +#define FEAT_SUP_LLC_VLAN_RX(__chip_info) ((__chip_info)->features & FEAT_BITS_LLC_VLAN_RX) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef enum _ENUM_WIFI_FUNC_T { + WIFI_FUNC_INIT_DONE = BIT(0), + WIFI_FUNC_N9_DONE = BIT(1), + WIFI_FUNC_CR4_READY = BIT(2), + WIFI_FUNC_READY_BITS = BITS(0, 2), + WIFI_FUNC_DUMMY_REQ = BIT(3) +} ENUM_WIFI_FUNC_T; + +enum enum_mt66xx_chip { + MT66XX_CHIP_6632 = 0, + MT66XX_CHIP_7666, + MT66XX_CHIP_7668, + MT66XX_CHIP_NUM +}; + +struct mt66xx_chip_info { + const unsigned int chip_id; /* chip id */ + const unsigned int sw_sync0; /* sw_sync0 address */ + const unsigned int sw_ready_bit_offset; /* sw_sync0 ready bit offset */ + const unsigned int patch_addr; /* patch download start address */ + const unsigned char is_pcie_32dw_read; /* diff PDMA config */ + + const P_ECO_INFO_T eco_info; /* chip version table */ + UINT_8 eco_ver; /* chip version */ + + void (*constructFirmwarePrio)(P_GLUE_INFO_T prGlueInfo, PPUINT_8 apucNameTable, + PPUINT_8 apucName, PUINT_8 pucNameIdx, UINT_8 ucMaxNameIdx);/* load firmware bin priority */ + + const UINT_32 features; /* feature bits */ +}; + +struct mt66xx_hif_driver_data { + struct mt66xx_chip_info *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 +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/nic.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/nic.h new file mode 100644 index 0000000000000..98703b7f6e2f0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/nic.h @@ -0,0 +1,371 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +#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; + +typedef struct _ECO_INFO_T { + UINT_8 ucHwVer; + UINT_8 ucRomVer; + UINT_8 ucFactoryVer; + UINT_8 ucEcoVer; +} ECO_INFO_T, *P_ECO_INFO_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; + +typedef enum _ENUM_SER_STATE_T { + SER_IDLE_DONE, /* SER is idle or done */ + SER_STOP_HOST_TX, /* Host HIF Tx is stopped */ + SER_STOP_HOST_TX_RX, /* Host HIF Tx/Rx is stopped */ + SER_REINIT_HIF, /* Host HIF is reinit */ + + SER_STATE_NUM +} ENUM_SER_STATE_T, *P_ENUM_SER_STATE_T; + +/* Test mode bitmask of disable flag */ +#define TEST_MODE_DISABLE_ONLINE_SCAN BIT(0) +#define TEST_MODE_DISABLE_ROAMING BIT(1) +#define TEST_MODE_FIXED_CAM_MODE BIT(2) +#define TEST_MODE_DISABLE_BCN_LOST_DET BIT(3) +#define TEST_MODE_NONE 0 +#define TEST_MODE_THROUGHPUT \ + (TEST_MODE_DISABLE_ONLINE_SCAN | TEST_MODE_DISABLE_ROAMING | \ + TEST_MODE_FIXED_CAM_MODE | TEST_MODE_DISABLE_BCN_LOST_DET) +#define TEST_MODE_SIGMA_AC_N_PMF (TEST_MODE_DISABLE_ONLINE_SCAN | TEST_MODE_FIXED_CAM_MODE) +#define TEST_MODE_SIGMA_WMM_PS (TEST_MODE_DISABLE_ONLINE_SCAN) +/******************************************************************************* +* 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); + +VOID nicpmWakeUpWiFi(IN P_ADAPTER_T prAdapter); + +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 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 ucWlanIndex, IN UINT_8 ucSeqNum); + +VOID nicFreePendingTxMsduInfoByBssIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex); + +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 UINT_8 ucBssIndex, IN P_EVENT_CONNECTION_STATUS prConnectionStatus); + +WLAN_STATUS nicMediaJoinFailure(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN WLAN_STATUS rStatus); + +/* Utility function for channel number conversion */ +UINT_32 nicChannelNum2Freq(IN UINT_32 u4ChannelNum); + +UINT_32 nicFreq2ChannelNum(IN UINT_32 u4FreqInKHz); + +UINT_8 nicGetVhtS1(IN UINT_8 ucPrimaryChannel, IN UINT_8 ucBandwidth); + +/* firmware command wrapper */ + /* NETWORK (WIFISYS) */ +WLAN_STATUS nicActivateNetwork(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex); + +WLAN_STATUS nicDeactivateNetwork(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex); + + /* BSS-INFO */ +WLAN_STATUS nicUpdateBss(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex); + + /* BSS-INFO Indication (PM) */ +WLAN_STATUS nicPmIndicateBssCreated(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex); + +WLAN_STATUS nicPmIndicateBssConnected(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex); + +WLAN_STATUS nicPmIndicateBssAbort(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex); + + /* Beacon Template Update */ +WLAN_STATUS +nicUpdateBeaconIETemplate(IN P_ADAPTER_T prAdapter, + IN ENUM_IE_UPD_METHOD_T eIeUpdMethod, + IN UINT_8 ucBssIndex, IN UINT_16 u2Capability, IN PUINT_8 aucIe, IN UINT_16 u2IELen); + +WLAN_STATUS nicQmUpdateWmmParms(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex); + +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, UINT_8 ucBssIndex, PARAM_POWER_MODE ePwrMode, BOOLEAN fgEnCmdEvent); + +WLAN_STATUS +nicConfigPowerSaveWowProfile(IN P_ADAPTER_T prAdapter, UINT_8 ucBssIndex, PARAM_POWER_MODE ePwrMode, + BOOLEAN fgEnCmdEvent, BOOLEAN fgSuspend); + +WLAN_STATUS nicEnterCtiaMode(IN P_ADAPTER_T prAdapter, BOOLEAN fgEnterCtia, BOOLEAN fgEnCmdEvent); +WLAN_STATUS nicEnterTPTestMode(IN P_ADAPTER_T prAdapter, IN UINT_8 ucFuncMask); + +/*----------------------------------------------------------------------------*/ +/* 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); + +/*----------------------------------------------------------------------------*/ +/* 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); + +/*----------------------------------------------------------------------------*/ +/* Link Quality Updating */ +/*----------------------------------------------------------------------------*/ +VOID +nicUpdateLinkQuality(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN P_EVENT_LINK_QUALITY_V2 prEventLinkQuality); + +VOID nicUpdateRSSI(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN INT_8 cRssi, IN INT_8 cLinkQuality); + +VOID nicUpdateLinkSpeed(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, 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 + +/*----------------------------------------------------------------------------*/ +/* Address Setting Apply */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicApplyNetworkAddress(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* ECO Version */ +/*----------------------------------------------------------------------------*/ +uint8_t nicGetChipSwVer(void); +UINT_8 nicGetChipEcoVer(IN P_ADAPTER_T prAdapter); +BOOLEAN nicIsEcoVerEqualTo(IN P_ADAPTER_T prAdapter, UINT_8 ucEcoVer); +BOOLEAN nicIsEcoVerEqualOrLaterTo(IN P_ADAPTER_T prAdapter, UINT_8 ucEcoVer); +UINT_8 nicSetChipHwVer(UINT_8 value); +UINT_8 nicSetChipSwVer(UINT_8 value); +UINT_8 nicSetChipFactoryVer(UINT_8 value); + +VOID nicSerStopTxRx(IN P_ADAPTER_T prAdapter); +VOID nicSerStopTx(IN P_ADAPTER_T prAdapter); +VOID nicSerStartTxRx(IN P_ADAPTER_T prAdapter); +BOOLEAN nicSerIsWaitingReset(IN P_ADAPTER_T prAdapter); +BOOLEAN nicSerIsTxStop(IN P_ADAPTER_T prAdapter); +BOOLEAN nicSerIsRxStop(IN P_ADAPTER_T prAdapter); + +#endif /* _NIC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/nic_rate.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/nic_rate.h new file mode 100644 index 0000000000000..881d845f021c5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/nic_rate.h @@ -0,0 +1,158 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/nic_rate.h#1 +*/ + +/*! \file nic_rate.h +* \brief This file contains the rate utility function of +* IEEE 802.11 family for MediaTek 802.11 Wireless LAN Adapters. +*/ + + +#ifndef _NIC_RATE_H +#define _NIC_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 +******************************************************************************** +*/ +UINT_32 +nicGetPhyRateByMcsRate( + IN UINT_8 ucIdx, + IN UINT_8 ucBw, + IN UINT_8 ucGI + ); + +UINT_32 +nicGetHwRateByPhyRate( + IN UINT_8 ucIdx + ); + +WLAN_STATUS +nicSwIndex2RateIndex( + IN UINT_8 ucRateSwIndex, + OUT PUINT_8 pucRateIndex, + OUT PUINT_8 pucPreambleOption + ); + +WLAN_STATUS +nicRateIndex2RateCode( + IN UINT_8 ucPreambleOption, + IN UINT_8 ucRateIndex, + OUT PUINT_16 pu2RateCode + ); + +UINT_32 +nicRateCode2PhyRate( + IN UINT_16 u2RateCode, + IN UINT_8 ucBandwidth, + IN UINT_8 ucGI, + IN UINT_8 ucRateNss + ); + +UINT_32 +nicRateCode2DataRate( + IN UINT_16 u2RateCode, + IN UINT_8 ucBandwidth, + IN UINT_8 ucGI + ); + +BOOLEAN +nicGetRateIndexFromRateSetWithLimit( + IN UINT_16 u2RateSet, + IN UINT_32 u4PhyRateLimit, + IN BOOLEAN fgGetLowest, + OUT PUINT_8 pucRateSwIndex + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _NIC_RATE_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/nic_rx.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/nic_rx.h new file mode 100644 index 0000000000000..609054fc979f7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/nic_rx.h @@ -0,0 +1,1047 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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 +* +*/ + + +#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 UNIFIED_MAC_RX_FORMAT 1 + +#define MAX_SEQ_NO 4095 +#define MAX_SEQ_NO_COUNT 4096 +#define HALF_SEQ_NO_CNOUT 2048 + +#define HALF_SEQ_NO_COUNT 2048 + +#define MT6620_FIXED_WIN_SIZE 64 +#define CFG_RX_MAX_BA_ENTRY 4 +#define CFG_RX_MAX_BA_TID_NUM 8 + +#define RX_STATUS_FLAG_MORE_PACKET BIT(30) +#define RX_STATUS_CHKSUM_MASK BITS(0, 10) + +#define RX_RFB_LEN_FIELD_LEN 4 +#define RX_HEADER_OFFSET 2 + +#define RX_RETURN_INDICATED_RFB_TIMEOUT_SEC 1 + +#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 + +/* RXM Definitions */ +/* The payload format of a RX packet */ +#define RX_PAYLOAD_FORMAT_MSDU 0 +#define RX_PAYLOAD_FORMAT_FIRST_SUB_AMSDU 3 +#define RX_PAYLOAD_FORMAT_MIDDLE_SUB_AMSDU 2 +#define RX_PAYLOAD_FORMAT_LAST_SUB_AMSDU 1 + +/* HAL RX from hal_hw_def_rom.h */ +/*------------------------------------------------------------------------------ + * Cipher define + *------------------------------------------------------------------------------ +*/ +#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 CIPHER_SUITE_CCMP_W_CCX 9 +#define CIPHER_SUITE_GCMP 10 + +/*------------------------------------------------------------------------------ + * Bit fields for HW_MAC_RX_DESC_T + *------------------------------------------------------------------------------ +*/ + +/*! MAC RX DMA Descriptor */ +/* DW 0*/ +/* Word 0 */ +#define RX_STATUS_RX_BYTE_COUNT_MASK BITS(0, 16) +/* Word 1 */ +#define RX_STATUS_ETH_TYPE_OFFSET_MASK BITS(0, 6) +#define RX_STATUS_ETH_TYPE_OFFSET 0 +#define RX_STATUS_IP_CHKSUM BIT(7) +#define RX_STATUS_UDP_TCP_CHKSUM BIT(8) +#define RX_STATUS_GROUP_VLD_MASK BITS(9, 12) +#define RX_STATUS_GROUP_VLD_OFFSET 9 +#define RX_STATUS_PKT_TYPE_MASK BITS(13, 15) +#define RX_STATUS_PKT_TYPE_OFFSET 13 + +/* DW 1 */ +/* Byte 0 */ +#define RX_STATUS_HTC BIT(0) +#define RX_STATUS_UC2ME BIT(1) +#define RX_STATUS_MC_FRAME BIT(2) +#define RX_STATUS_BC_FRAME BIT(3) +#define RX_STATUS_BCN_WITH_BMC BIT(4) +#define RX_STATUS_BCN_WITH_UC BIT(5) +#define RX_STATUS_KEYID_MASK BITS(6, 7) +#define RX_STATUS_KEYID_OFFSET 6 + +/* Byte 1 */ +#define RX_STATUS_CHAN_FREQ_MASK BITS(0, 7) +/* Byte 2 */ +#define RX_STATUS_HEADER_LEN_MASK BITS(0, 5) +#define RX_STATUS_HEADER_OFFSET BIT(6) +#define RX_STATUS_HEADER_TRAN BIT(7) +/* Byte 3 */ +#define RX_STATUS_PAYLOAD_FORMAT_MASK BITS(0, 1) +#define RX_STATUS_PAYLOAD_FORMAT_OFFSET 0 +#define RX_STATUS_BSSID_MASK BITS(2, 7) +#define RX_STATUS_BSSID_OFFSET 2 + +/* DW 2 */ +/* Byte 1 */ +#define RX_STATUS_TID_MASK BITS(0, 3) +#define RX_STATUS_SEC_MASK BITS(4, 7) +#define RX_STATUS_SEC_OFFSET 4 +/* Byte 2-3 */ +#define RX_STATUS_SW_BIT BIT(0) +#define RX_STATUS_FLAG_FCS_ERROR BIT(1) +#define RX_STATUS_FLAG_CIPHER_MISMATCH BIT(2) +#define RX_STATUS_FLAG_CIPHER_LENGTH_MISMATCH BIT(3) +#define RX_STATUS_FLAG_ICV_ERROR BIT(4) +#define RX_STATUS_FLAG_TKIPMIC_ERROR BIT(5) +#define RX_STATUS_FLAG_LEN_MISMATCH BIT(6) +#define RX_STATUS_FLAG_DE_AMSDU_FAIL BIT(7) +#define RX_STATUS_FLAG_EXCEED_LEN BIT(8) +#define RX_STATUS_LLC_MIS BIT(9) +#define RX_STATUS_UDF_VLT BIT(10) +#define RX_STATUS_FRAG BIT(11) +#define RX_STATUS_NULL BIT(12) +#define RX_STATUS_DATA BIT(13) +#define RX_STATUS_AMPDU_SUB_FRAME BIT(14) +#define RX_STATUS_AMPDU_FORMAT BIT(15) +#define PAYLOAD_FORMAT_IS_MSDU_FRAME 0 +#define RX_STATUS_FLAG_ERROR_MASK (RX_STATUS_FLAG_FCS_ERROR | RX_STATUS_FLAG_ICV_ERROR | \ + RX_STATUS_FLAG_CIPHER_LENGTH_MISMATCH) /* No TKIP MIC error */ + +/* DW 3 */ +#define RX_STATUS_RXV_SEQ_NO_MASK BITS(0, 7) +#define RX_STATUS_TCL BIT(8) +#define RX_STATUS_CLS BIT(11) +#define RX_STATUS_OFLD_MASK BITS(12, 13) +#define RX_STATUS_OFLD_OFFSET 12 +#define RX_STATUS_EAPOL_PACKET BIT(12) +#define RX_STATUS_ARP_NS_PACKET BIT(13) +#define RX_STATUS_TDLS_PACKET BITS(12, 13) +#define RX_STATUS_MGC BIT(14) +#define RX_STATUS_WOL_MASK BITS(15, 19) +#define RX_STATUS_WOL_OFFSET 15 +#define RX_STATUS_CLS_BITMAP_MASK BITS(20, 29) +#define RX_STATUS_CLS_BITMAP_OFFSET 20 +#define RX_STATUS_PF_MODE_BLACK_LIST BIT(30) +#define RX_STATUS_PF_STS_CHECKED BIT(31) + +/* DW 12 */ +#define RX_STATUS_FRAG_NUM_MASK BITS(0, 3) +#define RX_STATUS_SEQ_NUM_MASK BITS(4, 15) +#define RX_STATUS_SEQ_NUM_OFFSET 4 + +#define RX_STATUS_GROUP1_VALID BIT(0) +#define RX_STATUS_GROUP2_VALID BIT(1) +#define RX_STATUS_GROUP3_VALID BIT(2) +#define RX_STATUS_GROUP4_VALID BIT(3) + +#define RX_STATUS_FIXED_LEN 16 + +#define RX_STATUS_CHAN_FREQ_MASK_FOR_BY_PASS_MPDE BITS(0, 7) +#define RX_STATUS_FLAG_FCS_ERROR_FOR_BY_PASS_MODE BIT(16) + +/* Timing Measurement Report */ +/* DW0 Word 1 */ +#define RX_TMR_TOA_VALID BIT(11) +#define RX_TMR_TOD_VALID BIT(10) +#define RX_TMR_TYPE_MASK BITS(8, 9) +#define RX_TMR_TYPE_OFFSET 8 +#define RX_TMR_SUBTYPE_MASK BITS(4, 7) +#define RX_TMR_SUBTYPE_OFFSET 4 + +/* DW0 Byte 1*/ +#define RX_TMR_TM_FAILED BIT(2) +#define RX_TMR_NOISY_CHAN BIT(1) +#define RX_TMR_RESPONDER BIT(0) + +/* TBD */ +#define DMA_OWN_TO_HW BIT(0) +#define DMA_OWN_TO_FW_PENDING BIT(1) +#define STATUS_IS_OWN_TO_FW(flag) (((flag) & DMA_OWN_TO_HW) ? FALSE : TRUE) +#define STATUS_IS_FW_PENDING(flag) (((flag) & DMA_OWN_TO_FW_PENDING) ? TRUE : FALSE) + +/* DW 2 */ +#define RX_STATUS_PACKET_LENGTH_MASK BITS(0, 16) + +#define RX_STATUS_HEADER_TRAN_MASK BIT(7) +#define RX_STATUS_HEADER_TRAN_OFFSET 7 +#define RX_STATUS_HEADER_TRAN_BSS0_MASK BIT(6) +#define RX_STATUS_HEADER_TRAN_BSS0_OFFSET 6 +#define RX_STATUS_HEADER_TRAN_BSS1_MASK BIT(7) +#define RX_STATUS_HEADER_TRAN_BSS1_OFFSET 7 + +/* DW 4 */ +#define RX_STATUS_MATCH_PACKET BIT(4) + +#define RX_STATUS_HEADER_OFFSET_MASK 0xC0 +#define RX_STATUS_HEADER_OFFSET_OFFSET 6 + +/*------------------------------------------------------------------------------ + * Bit fields for HW_RX_VECTOR_DESC_T + *------------------------------------------------------------------------------ +*/ +/* DW 2 */ +#define RX_VECTOR_FOR_BA_ACK BIT(7) + +/*! HIF RX DMA Descriptor */ +/* DW 2 */ +#define HIF_RX_DESC_BUFFER_LEN BITS(0, 15) +#define HIF_RX_DESC_ETHER_TYPE_OFFSET_MASK BITS(16, 23) +#define HIF_RX_DESC_ETHER_TYPE_OFFSET_OFFSET 16 +#define HIF_RX_DESC_IP_CHKSUM_CHECK BIT(24) +#define HIF_RX_DESC_TCP_UDP_CHKSUM_CHECK BIT(25) + +#define HIF_RX_DATA_QUEUE 0 +#define HIF_RX_EVENT_QUEUE 1 + +/*------------------------------------------------------------------------------ + * Bit fields for PHY Vector + *------------------------------------------------------------------------------ +*/ + +/* RX Vector, 1st Cycle */ +#define RX_VT_RX_RATE_AC_MASK BITS(0, 3) +#define RX_VT_RX_RATE_MASK BITS(0, 6) +#define RX_VT_RX_RATE_OFFSET 0 +#define RX_VT_STBC_MASK BITS(7, 8) +#define RX_VT_STBC_OFFSET 7 +#define RX_VT_LDPC BIT(9) +#define RX_VT_NESS_MASK BITS(10, 11) +#define RX_VT_NESS_OFFSET 10 +#define RX_VT_RX_MODE_MASK BITS(12, 14) +#define RX_VT_RX_MODE_OFFSET 12 +#define RX_VT_RX_MODE_VHT BIT(14) +#define RX_VT_FR_MODE_MASK BITS(15, 16) +#define RX_VT_FR_MODE_OFFSET 15 +#define RX_VT_TXOP_PS_NOT_ALLOWED BIT(17) +#define RX_VT_AGGREGATION BIT(18) +#define RX_VT_SHORT_GI BIT(19) +#define RX_VT_SMOOTH BIT(20) +#define RX_VT_NO_SOUNDING BIT(21) +#define RX_VT_SOUNDING BIT(21) +#if 0 +#define RX_VT_SHORT_GI_NSYM BIT(22) /* VHT_SIG_A2[B1], not defined in MT6632 */ +#define RX_VT_CODING_MASK BITS(23, 24) /* VHT_SIG_A2[B2:B3], not defined in MT6632 */ +#define RX_VT_CODING_OFFSET 23 +#endif +#define RX_VT_NUM_RX_MASK BITS(22, 23) +#define RX_VT_NUM_RX_OFFSET 22 +#define RX_VT_LDPC_EXTRA_OFDM_SYM BIT(24) /* VHT_SIG_A2[B3] */ +#define RX_VT_SU_VHT_MU1_3_CODING BITS(25, 28) /* VHT_SIG_A2[B4:B7] */ +#define RX_VT_SU_VHT_MU1_3_CODING_OFFSET 25 +#define RX_VT_BEAMFORMED BIT(29) /* VHT_SIG_A2[B8] */ +#define RX_VT_ACID_DET_LOW BIT(30) +#define RX_VT_ACID_DET_HIGH BIT(31) + +#define RX_VT_RX_RATE_1M 0x0 +#define RX_VT_RX_RATE_2M 0x1 +#define RX_VT_RX_RATE_5M 0x2 +#define RX_VT_RX_RATE_11M 0x3 +#define RX_VT_RX_RATE_6M 0xB +#define RX_VT_RX_RATE_9M 0xF +#define RX_VT_RX_RATE_12M 0xA +#define RX_VT_RX_RATE_18M 0xE +#define RX_VT_RX_RATE_24M 0x9 +#define RX_VT_RX_RATE_36M 0xD +#define RX_VT_RX_RATE_48M 0x8 +#define RX_VT_RX_RATE_54M 0xC + +#define RX_VT_RX_RATE_MCS0 0 +#define RX_VT_RX_RATE_MCS1 1 +#define RX_VT_RX_RATE_MCS2 2 +#define RX_VT_RX_RATE_MCS3 3 +#define RX_VT_RX_RATE_MCS4 4 +#define RX_VT_RX_RATE_MCS5 5 +#define RX_VT_RX_RATE_MCS6 6 +#define RX_VT_RX_RATE_MCS7 7 +#define RX_VT_RX_RATE_MCS32 32 + +#define RX_VT_LEGACY_CCK 0 +#define RX_VT_LEGACY_OFDM 1 +#define RX_VT_MIXED_MODE 2 +#define RX_VT_GREEN_MODE 3 +#define RX_VT_VHT_MODE 4 + +#define RX_VT_LG20_HT20 0 +#define RX_VT_DL40_HT40 1 +#define RX_VT_U20 2 +#define RX_VT_L20 3 + +#define RX_VT_FR_MODE_20 0 +#define RX_VT_FR_MODE_40 1 +#define RX_VT_FR_MODE_80 2 +#define RX_VT_FR_MODE_160 3 /*BW160 or BW80+80*/ + +#define RX_VT_CCK_SHORT_PREAMBLE BIT(2) + +/* RX Vector, 2nd Cycle */ +#define RX_VT_RX_LEN_HT_MASK BITS(0, 15) +#define RX_VT_RX_LEN_LEACY_MASK BITS(0, 11) +#define RX_VT_RX_LEN_VHT_MASK BITS(0, 20) +#define RX_VT_GROUP_ID_MASK BITS(21, 26) +#define RX_VT_GROUP_ID_OFFSET 21 +#define RX_VT_GROUPID_0_MASK BITS(21, 22) /* VHT_SIG_A1[B4:B5] */ +#define RX_VT_GROUPID_0_OFFSET 21 +#define RX_VT_GROUPID_1_MASK BITS(23, 26) /* VHT_SIG_A1[B6:B9] */ +#define RX_VT_GROUPID_1_OFFSET 23 + +#define RX_VT_NSTS_MASK BITS(27, 29) +#define RX_VT_NSTS_OFFSET 27 +#define RX_VT_RX_INDICATOR BIT(30) +#define RX_VT_SEL_ANT BIT(31) /* Not use in MT7615 and MT6632 */ + +/* RX Vector, 3rd Cycle */ +#define RX_VT_PART_AID_MASK BITS(3, 11) +#define RX_VT_PART_AID_OFFSET 3 +#define RX_VT_AID_0_MASK BITS(3, 6) /* VHT_SIG_A1[B13:B16] */ +#define RX_VT_AID_0_OFFSET 3 +#define RX_VT_AID_1_MASK BITS(7, 11) /* VHT_SIG_A1[B17:B21] */ +#define RX_VT_AID_1_OFFSET 7 + + +#define RX_VT_NSTS_PART_AID_MASK BITS(0, 11) +#define RX_VT_NSTS_PART_AID_OFFSET 0 +#define RX_VT_POP_EVER_TRIG BIT(12) +#define RX_VT_FAGC_LNA_RX_MASK BITS(13, 15) +#define RX_VT_FAGC_LNA_RX_OFFSET 13 +#define RX_VT_IB_RSSI_MASK BITS(16, 23) +#define RX_VT_IB_RSSI_OFFSET 16 +#define RX_VT_WB_RSSI_MASK BITS(24, 31) +#define RX_VT_WB_RSSI_OFFSET 24 + +/* RX Vector, 4th Cycle */ +#define RX_VT_RCPI0_MASK BITS(0, 7) +#define RX_VT_RCPI0_OFFSET 0 +#define RX_VT_RCPI1_MASK BITS(8, 15) +#define RX_VT_RCPI1_OFFSET 8 +#define RX_VT_RCPI2_MASK BITS(16, 23) +#define RX_VT_RCPI2_OFFSET 16 +#define RX_VT_RCPI3_MASK BITS(24, 31) +#define RX_VT_RCPI3_OFFSET 24 + +/* RX Vector, 5th Cycle */ +#define RX_VT_FAGC_LNA_GAIN_MASK BITS(0, 2) +#define RX_VT_FAGC_LNA_GAIN_OFFSET 0 +#define RX_VT_FAGC_LPF_GAIN_MASK BITS(3, 6) +#define RX_VT_FAGC_LPF_GAIN_OFFSET 3 +#define RX_VT_OFDM_FOE_MASK BITS(7, 18) +#define RX_VT_OFDM_FOE_OFFSET 7 +#define RX_VT_LTF_PROC_TIME_MASK BITS(19, 25) +#define RX_VT_LTF_PROC_TIME_OFFSET 19 +#define RX_VT_LTF_SNR_MASK BITS(26, 31) +#define RX_VT_LTF_SNR_OFFSET 26 + +/*RX Vector, 6th Cycle*/ +#define RX_VT_NF0_MASK BITS(0, 7) +#define RX_VT_NF0_OFFSET 0 +#define RX_VT_NF1_MASK BITS(8, 15) +#define RX_VT_NF1_OFFSET 8 +#define RX_VT_NF2_MASK BITS(16, 23) +#define RX_VT_NF2_OFFSET 16 +#define RX_VT_NF3_MASK BITS(24, 31) +#define RX_VT_NF3_OFFSET 24 + +/* RX Vector Group 2, the 1st cycle */ +#define RX_VT_PRIM_ITFR_ENV BIT(0) +#define RX_VT_SEC_ITFR_ENV BIT(1) +#define RX_VT_SEC40_ITFR_ENV BIT(2) +#define RX_VT_SEC80_ITFR_ENV BIT(3) +#define RX_VT_OFDM_LQ_BPSK_MASK BITS(4, 10) +#define RX_VT_OFDM_LQ_BPSK_OFFSET 4 +#define RX_VT_OFDM_CAPACITY_LQ_MASK BITS(11, 17) +#define RX_VT_OFDM_CAPACITY_LQ_OFFSET 11 +#define RX_VT_CCK_LQ_MASK BITS(4, 13) +#define RX_VT_CCK_LQ_OFFSET 4 + +/* RX Vector Group 2, the 2nd cycle */ +#define RX_VT_DYNA_BW_IN_NON_HT_DYNA BIT(19) +#define RX_VT_CH_BW_IN_NON_HT_MASK BITS(20, 21) +#define RX_VT_CH_BW_IN_NON_HT_OFFSET 20 + +#define RX_VT_CH_BW_IN_NON_HT_CBW40 BIT(20) +#define RX_VT_CH_BW_IN_NON_HT_CBW80 BIT(21) +#define RX_VT_CH_BW_IN_NON_HT_CBW160 BITS(20, 21) + +/* RX Data Type */ +#define RX_DATA_TYPE_RX_VECTOR 0 +#define RX_DATA_TYPE_RX_DATA 1 +#define RX_DATA_TYPE_RX_EVM 2 +#define RX_DATA_TYPE_RX_AMBI 3 +#define RX_DATA_TYPE_RX_BT 4 + +/*------------------------------------------------------------------------------ + * Radiotap define + *------------------------------------------------------------------------------ +*/ + +/*Radiotap VHT*/ +#define RADIOTAP_VHT_ALL_KNOWN BITS(0, 8) +#define RADIOTAP_VHT_STBC_KNOWN BIT(0) +#define RADIOTAP_VHT_TXOP_PS_NOT_ALLOWED_KNOWN BIT(1) +#define RADIOTAP_VHT_GI_KNOWN BIT(2) +#define RADIOTAP_VHT_SHORT_GI_NSYM_KNOWN BIT(3) +#define RADIOTAP_VHT_LDPC_EXTRA_OFDM_SYM_KNOWN BIT(4) +#define RADIOTAP_VHT_BEAMFORMED_KNOWN BIT(5) +#define RADIOTAP_VHT_BAND_WIDTH_KNOWN BIT(6) +#define RADIOTAP_VHT_BAND_GROUP_ID_KNOWN BIT(7) +#define RADIOTAP_VHT_BAND_PARTIAL_AID_KNOWN BIT(8) + + +/******************************************************************************* +* 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_DATA_REORDER_TOTAL_COUINT, + RX_DATA_REORDER_MISS_COUNT, + RX_DATA_REORDER_WITHIN_COUNT, + RX_DATA_REORDER_AHEAD_COUNT, + RX_DATA_REORDER_BEHIND_COUNT, + + RX_DATA_MSDU_IN_AMSDU_COUNT, + RX_DATA_AMSDU_MISS_COUNT, + RX_DATA_AMSDU_COUNT, + + RX_DROP_TOTAL_COUNT, + + RX_NO_STA_DROP_COUNT, + RX_INACTIVE_BSS_DROP_COUNT, + RX_HS20_DROP_COUNT, + RX_LESS_SW_RFB_DROP_COUNT, + RX_DUPICATE_DROP_COUNT, + RX_MIC_ERROR_DROP_COUNT, + RX_BAR_DROP_COUNT, + RX_NO_INTEREST_DROP_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; + +/* Used for MAC RX */ +typedef enum _ENUM_MAC_RX_PKT_TYPE_T { + RX_PKT_TYPE_TX_STATUS = 0, + RX_PKT_TYPE_RX_VECTOR, + RX_PKT_TYPE_RX_DATA, + RX_PKT_TYPE_DUP_RFB, + RX_PKT_TYPE_TM_REPORT, + RX_PKT_TYPE_MSDU_REPORT = 6, + RX_PKT_TYPE_SW_DEFINED = 7 +} ENUM_MAC_RX_PKT_TYPE_T; + +typedef enum _ENUM_MAC_RX_GROUP_VLD_T { + RX_GROUP_VLD_1 = 0, + RX_GROUP_VLD_2, + RX_GROUP_VLD_3, + RX_GROUP_VLD_4, + RX_GROUP_VLD_NUM +} ENUM_MAC_RX_GROUP_VLD_T; + +typedef enum _ENUM_MAC_GI_INFO_T { + MAC_GI_NORMAL = 0, + MAC_GI_SHORT +} ENUM_MAC_GI_INFO_T, *P_ENUM_MAC_GI_INFO_T; + +typedef enum _ENUM_RXPI_MODE_T { + RCPI_MODE_WF0 = 0, + RCPI_MODE_WF1, + RCPI_MODE_WF2, + RCPI_MODE_WF3, + RCPI_MODE_AVG, + RCPI_MODE_MAX, + RCPI_MODE_MIN, + RCPI_MODE_NUM +} ENUM_RXPI_MODE_T; + +#define RXM_RXD_PKT_TYPE_SW_BITMAP 0xE00F +#define RXM_RXD_PKT_TYPE_SW_EVENT 0xE000 +#define RXM_RXD_PKT_TYPE_SW_FRAME 0xE001 + +/* AMPDU data frame with no errors including FC/FM/I/T/LM/DAF/EL/LLC-MIS/ UDFVLT and Class 3 error */ +#define RXS_DW2_AMPDU_nERR_BITMAP 0xFFFB /* ignore CM bit (2) 0xFFFF */ +#define RXS_DW2_AMPDU_nERR_VALUE 0x0000 +/* no error including FC/CLM/I/T/LM/DAF/EL/HTF */ +#define RXS_DW2_RX_nERR_BITMAP 0x03FA /* ignore CM bit (2) 0x03FE */ +#define RXS_DW2_RX_nERR_VALUE 0x0000 +/* Non-Data frames */ +#define RXS_DW2_RX_nDATA_BITMAP 0x3000 +#define RXS_DW2_RX_nDATA_VALUE 0x2000 +/* Claas Error */ +#define RXS_DW2_RX_CLASSERR_BITMAP 0x0001 +#define RXS_DW2_RX_CLASSERR_VALUE 0x0001 +/* Fragmentation */ +#define RXS_DW2_RX_FRAG_BITMAP 0x3800 +#define RXS_DW2_RX_FRAG_VALUE 0x0800 + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/*! A data structure which is identical with MAC RX DMA Descriptor */ +typedef struct _HW_MAC_RX_DESC_T { + UINT_16 u2RxByteCount; /* DW 0 */ + UINT_16 u2PktTYpe; + UINT_8 ucMatchPacket; /* DW 1 */ + UINT_8 ucChanFreq; + UINT_8 ucHeaderLen; + UINT_8 ucBssid; + UINT_8 ucWlanIdx; /* DW 2 */ + UINT_8 ucTidSecMode; + UINT_16 u2StatusFlag; + UINT_32 u4PatternFilterInfo; /* DW 3 */ +} HW_MAC_RX_DESC_T, *P_HW_MAC_RX_DESC_T; + +typedef struct _HW_MAC_RX_STS_GROUP_1_T { + UINT_8 aucPN[16]; +} HW_MAC_RX_STS_GROUP_1_T, *P_HW_MAC_RX_STS_GROUP_1_T; + +typedef struct _HW_MAC_RX_STS_GROUP_2_T { + UINT_32 u4Timestamp; /* DW 12 */ + UINT_32 u4CRC; /* DW 13 */ +} HW_MAC_RX_STS_GROUP_2_T, *P_HW_MAC_RX_STS_GROUP_2_T; + +typedef struct _HW_MAC_RX_STS_GROUP_4_T { + /* For HDR_TRAN */ + UINT_16 u2FrameCtl; /* DW 4 */ + UINT_8 aucTA[6]; /* DW 4~5 */ + UINT_16 u2SeqFrag; /* DW 6 */ + UINT_16 u2Qos; /* DW 6 */ + UINT_32 u4HTC; /* DW 7 */ +} HW_MAC_RX_STS_GROUP_4_T, *P_HW_MAC_RX_STS_GROUP_4_T; + +typedef struct _HW_MAC_RX_STS_GROUP_3_T { + /*! RX Vector Info */ + UINT_32 u4RxVector[6]; /* DW 14~19 */ +} HW_MAC_RX_STS_GROUP_3_T, *P_HW_MAC_RX_STS_GROUP_3_T; + +typedef struct _HW_MAC_RX_TMRI_PKT_FORMAT_T { + UINT_8 ucPID; + UINT_8 ucStatus; + UINT_16 u2PktTYpe; + UINT_32 u4Reserved[2]; + UINT_32 u4ToA; + UINT_32 u4ToD; +} HW_MAC_RX_TMRI_PKT_FORMAT_T, *P_HW_MAC_RX_TMRI_PKT_FORMAT_T; + +typedef struct _HW_MAC_RX_TMRR_PKT_FORMAT_T { + UINT_8 ucVtSeq; + UINT_8 ucStatus; + UINT_16 u2PktTYpe; + UINT_8 aucTALow[2]; + UINT_16 u2SnField; + UINT_8 aucTAHigh[4]; + UINT_32 u4ToA; + UINT_32 u4ToD; +} HW_MAC_RX_TMRR_PKT_FORMAT_T, *P_HW_MAC_RX_TMRR_PKT_FORMAT_T; + +/*! A data structure which is identical with MAC RX Vector DMA Descriptor */ +typedef struct _HW_RX_VECTOR_DESC_T { + UINT_8 aucTA[6]; /* DW 0~1 */ + UINT_8 ucRxVtSeqNo; + /*! RX Vector Info */ + UINT_32 u4RxVector[9]; /* DW 2~10 */ + +} HW_RX_VECTOR_DESC_T, *P_HW_RX_VECTOR_DESC_T; + +typedef struct _HW_MAC_MSDU_REPORT_T { + /* 1st DW */ + UINT_16 u2BufByteCount; + UINT_16 u2MsduCount:7; + UINT_16 u2DoneEventType:6; + UINT_16 u2PktType:3; + /* 2nd DW */ + UINT_32 u4TxdCount:8; + UINT_32 u4RvS2:24; + /* MSDU token array */ + UINT_16 au2MsduToken[0]; +} HW_MAC_MSDU_REPORT_T, *P_HW_MAC_MSDU_REPORT_T; + +struct _SW_RFB_T { + QUE_ENTRY_T rQueEntry; + PVOID pvPacket; /*!< ptr to rx Packet Descriptor */ + PUINT_8 pucRecvBuff; /*!< ptr to receive data buffer */ + + /* add fot mt6630 */ + UINT_8 ucGroupVLD; + UINT_16 u2RxStatusOffst; + P_HW_MAC_RX_DESC_T prRxStatus; + P_HW_MAC_RX_STS_GROUP_1_T prRxStatusGroup1; + P_HW_MAC_RX_STS_GROUP_2_T prRxStatusGroup2; + P_HW_MAC_RX_STS_GROUP_3_T prRxStatusGroup3; + P_HW_MAC_RX_STS_GROUP_4_T prRxStatusGroup4; + + /* rx data information */ + PVOID pvHeader; + UINT_16 u2PacketLen; + UINT_16 u2HeaderLen; + + PUINT_8 pucPayload; + UINT_16 u2PayloadLength; + + P_STA_RECORD_T prStaRec; + + UINT_8 ucPacketType; + + /* rx sta record */ + UINT_8 ucWlanIdx; + UINT_8 ucStaRecIdx; + + BOOLEAN fgReorderBuffer; + BOOLEAN fgDataFrame; + BOOLEAN fgFragFrame; + /* duplicate detection */ + UINT_16 u2FrameCtrl; + UINT_16 u2SequenceControl; + UINT_16 u2SSN; + UINT_8 ucTid; + + 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 */ +#if 0 + /* RX reorder for one MSDU in AMSDU issue */ + /*QUE_T rAmsduQue;*/ +#endif +}; + +/*! 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 + +#if CFG_SUPPORT_SNIFFER + UINT_32 u4AmpduRefNum; +#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); + +typedef VOID(*PROCESS_RX_EVENT_FUNCTION) (P_ADAPTER_T, P_WIFI_EVENT_T); + +typedef struct _RX_EVENT_HANDLER_T { + ENUM_EVENT_ID_T eEID; + PROCESS_RX_EVENT_FUNCTION pfnHandler; +} RX_EVENT_HANDLER_T, *P_RX_EVENT_HANDLER_T; + +typedef struct _EMU_MAC_RATE_INFO_T { + UINT_8 ucPhyRateCode; + UINT_32 u4PhyRate[4][2]; +} EMU_MAC_RATE_INFO_T, *P_EMU_MAC_RATE_INFO_T; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define RATE_INFO(_RateCode, _Bw20, _Bw20SGI, _Bw40, _BW40SGI, _Bw80, _Bw80SGI, _Bw160, _Bw160SGI) \ + { \ + .ucPhyRateCode = (_RateCode), \ + .u4PhyRate[RX_VT_FR_MODE_20][MAC_GI_NORMAL] = (_Bw20), \ + .u4PhyRate[RX_VT_FR_MODE_20][MAC_GI_SHORT] = (_Bw20SGI), \ + .u4PhyRate[RX_VT_FR_MODE_40][MAC_GI_NORMAL] = (_Bw40), \ + .u4PhyRate[RX_VT_FR_MODE_40][MAC_GI_SHORT] = (_BW40SGI), \ + .u4PhyRate[RX_VT_FR_MODE_80][MAC_GI_NORMAL] = (_Bw80), \ + .u4PhyRate[RX_VT_FR_MODE_80][MAC_GI_SHORT] = (_Bw80SGI), \ + .u4PhyRate[RX_VT_FR_MODE_160][MAC_GI_NORMAL] = (_Bw160), \ + .u4PhyRate[RX_VT_FR_MODE_160][MAC_GI_SHORT] = (_Bw160SGI), \ + } + +#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)) + +/*------------------------------------------------------------------------------ + * MACRO for HW_MAC_RX_DESC_T + *------------------------------------------------------------------------------ +*/ +/* DW 0 */ +#define HAL_RX_STATUS_GET_RX_BYTE_CNT(_prHwMacRxDesc) ((_prHwMacRxDesc)->u2RxByteCount) +#define HAL_RX_STATUS_GET_ETH_TYPE_OFFSET(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2PktTYpe & RX_STATUS_ETH_TYPE_OFFSET_MASK) >> RX_STATUS_ETH_TYPE_OFFSET) +#define HAL_RX_STATUS_GET_GROUP_VLD(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2PktTYpe & RX_STATUS_GROUP_VLD_MASK) >> RX_STATUS_GROUP_VLD_OFFSET) +#define HAL_RX_STATUS_GET_PKT_TYPE(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2PktTYpe & RX_STATUS_PKT_TYPE_MASK) >> RX_STATUS_PKT_TYPE_OFFSET) + +/* DW 1 */ +#define HAL_RX_STATUS_IS_HTC_EXIST(_prHwMacRxDesc) (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_HTC)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_UC2ME(_prHwMacRxDesc) (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_UC2ME)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_MC(_prHwMacRxDesc) (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_MC_FRAME)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_BC(_prHwMacRxDesc) (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_BC_FRAME)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_BCN_WITH_BMC(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_BCN_WITH_BMC)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_BCN_WITH_UC(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_BCN_WITH_UC)?TRUE:FALSE) +#define HAL_RX_STATUS_GET_KEY_ID(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucMatchPacket & RX_STATUS_KEYID_MASK) >> RX_STATUS_KEYID_OFFSET) +#define HAL_RX_STATUS_GET_CHAN_FREQ(_prHwMacRxDesc) \ + ((_prHwMacRxDesc)->ucChanFreq) +#define HAL_RX_STATUS_GET_HEADER_LEN(_prHwMacRxDesc) ((_prHwMacRxDesc)->ucHeaderLen & RX_STATUS_HEADER_LEN_MASK) +#define HAL_RX_STATUS_IS_HEADER_OFFSET(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucHeaderLen & RX_STATUS_HEADER_OFFSET)?TRUE:FALSE) +#define HAL_RX_STATUS_GET_HEADER_OFFSET(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucHeaderLen & RX_STATUS_HEADER_OFFSET) ? 2 : 0) +#define HAL_RX_STATUS_IS_HEADER_TRAN(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucHeaderLen & RX_STATUS_HEADER_TRAN)?TRUE:FALSE) +#define HAL_RX_STATUS_GET_HEADER_TRAN(_prHwMacRxDesc) HAL_RX_STATUS_IS_HEADER_TRAN(_prHwMacRxDesc) +#define HAL_RX_STATUS_GET_PAYLOAD_FORMAT(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucBssid & RX_STATUS_PAYLOAD_FORMAT_MASK) >> RX_STATUS_PAYLOAD_FORMAT_OFFSET) +#define HAL_RX_STATUS_GET_BSSID(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucBssid & RX_STATUS_BSSID_MASK) >> RX_STATUS_BSSID_OFFSET) + +/* DW 2 */ +#define HAL_RX_STATUS_GET_WLAN_IDX(_prHwMacRxDesc) ((_prHwMacRxDesc)->ucWlanIdx) +#define HAL_RX_STATUS_GET_TID(_prHwMacRxDesc) (((_prHwMacRxDesc)->ucTidSecMode & RX_STATUS_TID_MASK)) +#define HAL_RX_STATUS_GET_SEC_MODE(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->ucTidSecMode & RX_STATUS_SEC_MASK) >> RX_STATUS_SEC_OFFSET) +#define HAL_RX_STATUS_GET_SW_BIT(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_SW_BIT)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_FCS_ERROR(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_FCS_ERROR)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_CIPHER_MISMATCH(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_CIPHER_MISMATCH)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_CLM_ERROR(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_CIPHER_LENGTH_MISMATCH)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_ICV_ERROR(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_ICV_ERROR)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_TKIP_MIC_ERROR(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_TKIPMIC_ERROR) > 0?TRUE:FALSE) +#define HAL_RX_STATUS_IS_ERROR(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_ERROR_MASK)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_LEN_MISMATCH(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_LEN_MISMATCH)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_DE_AMSDU_FAIL(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_DE_AMSDU_FAIL)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_EXCEED_LEN(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FLAG_EXCEED_LEN)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_LLC_MIS(_prHwMacRxDesc) (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_LLC_MIS)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_UDF_VLT(_prHwMacRxDesc) (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_UDF_VLT)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_FRAG(_prHwMacRxDesc) (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_FRAG)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_NULL(_prHwMacRxDesc) (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_NULL)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_DATA(_prHwMacRxDesc) (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_DATA)?FALSE:TRUE) +#define HAL_RX_STATUS_IS_AMPDU_SUB_FRAME(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_AMPDU_SUB_FRAME)?FALSE:TRUE) +#define HAL_RX_STATUS_IS_AMPDU_FORMAT(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u2StatusFlag & RX_STATUS_AMPDU_FORMAT)?FALSE:TRUE) + +/* DW 3 */ +#define HAL_RX_STATUS_IS_RV_VALID(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_RXV_SEQ_NO_MASK)?TRUE:FALSE) +#define HAL_RX_STATUS_GET_RXV_SEQ_NO(_prHwMacRxDesc) \ + ((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_RXV_SEQ_NO_MASK) +#define HAL_RX_STATUS_GET_TCL(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_TCL)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_CLS(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_CLS)?TRUE:FALSE) +#define HAL_RX_STATUS_GET_OFLD(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_OFLD_MASK) >> RX_STATUS_OFLD_OFFSET) +#define HAL_RX_STATUS_IS_MGC(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_MGC)?TRUE:FALSE) +#define HAL_RX_STATUS_GET_WOL(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_WOL_MASK) >> RX_STATUS_WOL_OFFSET) +#define HAL_RX_STATUS_GET_CLS_BITMAP(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_CLS_BITMAP_MASK) >> RX_STATUS_CLS_BITMAP_OFFSET) +#define HAL_RX_STATUS_IS_PF_BLACK_LIST(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_PF_MODE_BLACK_LIST)?TRUE:FALSE) +#define HAL_RX_STATUS_IS_PF_CHECKED(_prHwMacRxDesc) \ + (((_prHwMacRxDesc)->u4PatternFilterInfo & RX_STATUS_PF_STS_CHECKED)?TRUE:FALSE) + +/* DW 4~7 */ +#define HAL_RX_STATUS_GET_FRAME_CTL_FIELD(_prHwMacRxStsGroup4) ((_prHwMacRxStsGroup4)->u2FrameCtl) +#define HAL_RX_STATUS_GET_TA(_prHwMacRxStsGroup4, pucTA) \ +{\ + kalMemCopy(pucTA, &(_prHwMacRxStsGroup4)->aucTA[0], 6); \ +} +#define HAL_RX_STATUS_GET_SEQ_FRAG_NUM(_prHwMacRxStsGroup4) ((_prHwMacRxStsGroup4)->u2SeqFrag) +#define HAL_RX_STATUS_GET_QOS_CTL_FIELD(_prHwMacRxStsGroup4) ((_prHwMacRxStsGroup4)->u2Qos) + +#define HAL_RX_STATUS_GET_SEQFrag_NUM(_prHwMacRxStsGroup4) ((_prHwMacRxStsGroup4)->u2SeqFrag) +#define HAL_RX_STATUS_GET_HTC(_prHwMacRxStsGroup4) ((_prHwMacRxStsGroup4)->u4HTC) + +/* DW 8~11 */ +#define HAL_RX_STATUS_GET_RSC(_prHwMacRxStsGroup1, pucRSC) \ +{\ + kalMemCopy(pucRSC, &(_prHwMacRxStsGroup1)->aucPN[0], 6); \ +} + +#define HAL_RX_STATUS_GET_PN(_prHwMacRxStsGroup1, pucPN) \ +{\ + kalMemCopy(pucPN, &(_prHwMacRxStsGroup1)->aucPN[0], 16); \ +} + +/* DW 12~13 */ +#define HAL_RX_STATUS_GET_TIMESTAMP(_prHwMacRxStsGroup2, _ucIdx) ((_prHwMacRxStsGroup2)->u4Timestamp) +#define HAL_RX_STATUS_GET_FCS32(_prHwMacRxStsGroup2) ((_prHwMacRxStsGroup2)->u4CRC) + +/* DW 14~19 */ +#define HAL_RX_STATUS_GET_RX_VECTOR(_prHwMacRxStsGroup3, _ucIdx) ((_prHwMacRxStsGroup3)->u4RxVector[_ucIdx]) + +#define HAL_RX_STATUS_GET_RX_NUM(_prHwMacRxStsGroup3) \ + (((_prHwMacRxStsGroup3)->u4RxVector[0] & RX_VT_NUM_RX_MASK) >> RX_VT_NUM_RX_OFFSET) + +#define HAL_RX_STATUS_GET_RCPI0(_prHwMacRxStsGroup3) \ + (((_prHwMacRxStsGroup3)->u4RxVector[3] & RX_VT_RCPI0_MASK) >> RX_VT_RCPI0_OFFSET) +#define HAL_RX_STATUS_GET_RCPI1(_prHwMacRxStsGroup3) \ + (((_prHwMacRxStsGroup3)->u4RxVector[3] & RX_VT_RCPI1_MASK) >> RX_VT_RCPI1_OFFSET) + +/* TBD */ +#define HAL_RX_STATUS_GET_RX_PACKET_LEN(_prHwMacRxDesc) +#define HAL_RX_STATUS_IS_MATCH_PACKET(_prHwMacRxDesc) + +#define HAL_RX_STATUS_GET_CHNL_NUM(_prHwMacRxDesc) \ + ((((_prHwMacRxDesc)->ucChanFreq) > HW_CHNL_NUM_MAX_4G_5G) ? \ + (((_prHwMacRxDesc)->ucChanFreq) - HW_CHNL_NUM_MAX_4G_5G) : \ + ((_prHwMacRxDesc)->ucChanFreq)) + +/* To do: support more bands other than 2.4G and 5G */ +#define HAL_RX_STATUS_GET_RF_BAND(_prHwMacRxDesc) \ + ((((_prHwMacRxDesc)->ucChanFreq) <= HW_CHNL_NUM_MAX_2G4) ? \ + BAND_2G4 : BAND_5G) + +/*------------------------------------------------------------------------------ + * MACRO for HW_RX_VECTOR_DESC_T + *------------------------------------------------------------------------------ +*/ +#define HAL_RX_VECTOR_GET_TA(_prHwRxVector, pucTA) \ +{\ + kalMemCopy(pucTA, &(_prHwRxVector)->aucTA[0], 6); \ +} + +#define HAL_RX_VECTOR_GET_SEQ_NO(_prHwRxVector) ((_prHwRxVector)->ucRxVtSeqNo & RX_STATUS_RXV_SEQ_NO_MASK) +#define HAL_RX_VECTOR_IS_FOR_BA_ACK(_prHwRxVector) (((_prHwRxVector)->ucRxVtSeqNo & RX_VECTOR_FOR_BA_ACK)?TRUE:FALSE) +#define HAL_RX_VECTOR_GET_RX_VECTOR(_prHwRxVector, _ucIdx) ((_prHwRxVector)->u4RxVector[_ucIdx]) + +#define RXM_IS_QOS_DATA_FRAME(_u2FrameCtrl) \ + (((_u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_QOS_DATA) ? TRUE : FALSE) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +VOID nicRxInitialize(IN P_ADAPTER_T prAdapter); + +VOID nicRxUninitialize(IN P_ADAPTER_T prAdapter); + +VOID nicRxProcessRFBs(IN P_ADAPTER_T prAdapter); + +VOID nicRxProcessMsduReport(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb); + +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); + +P_SW_RFB_T incRxDefragMPDU(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSWRfb, OUT P_QUE_T prReturnedQue); + +BOOLEAN nicRxIsDuplicateFrame(IN OUT P_SW_RFB_T prSwRfb); + +#if CFG_SUPPORT_SNIFFER +VOID nicRxProcessMonitorPacket(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb); +#endif + +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); + +UINT_8 nicRxGetRcpiValueFromRxv(IN UINT_8 ucRcpiMode, IN P_SW_RFB_T prSwRfb); + +#endif /* _NIC_RX_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/nic_tx.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/nic_tx.h new file mode 100644 index 0000000000000..e2111a3498312 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/nic_tx.h @@ -0,0 +1,1535 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +* +*/ + + +#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 UNIFIED_MAC_TX_FORMAT 1 + +#define MAC_TX_RESERVED_FIELD 0 + +#define NIC_TX_RESOURCE_POLLING_TIMEOUT 256 +#define NIC_TX_RESOURCE_POLLING_DELAY_MSEC 5 + +#define NIC_TX_CMD_INFO_RESERVED_COUNT 4 + +/* Maximum buffer count for individual HIF TCQ */ +#define NIC_TX_PAGE_COUNT_TC0 (NIC_TX_BUFF_COUNT_TC0 * NIC_TX_MAX_PAGE_PER_FRAME) +#define NIC_TX_PAGE_COUNT_TC1 (NIC_TX_BUFF_COUNT_TC1 * NIC_TX_MAX_PAGE_PER_FRAME) +#define NIC_TX_PAGE_COUNT_TC2 (NIC_TX_BUFF_COUNT_TC2 * NIC_TX_MAX_PAGE_PER_FRAME) +#define NIC_TX_PAGE_COUNT_TC3 (NIC_TX_BUFF_COUNT_TC3 * NIC_TX_MAX_PAGE_PER_FRAME) +#define NIC_TX_PAGE_COUNT_TC4 (NIC_TX_BUFF_COUNT_TC4 * NIC_TX_MAX_PAGE_PER_FRAME) +#define NIC_TX_PAGE_COUNT_TC5 (NIC_TX_BUFF_COUNT_TC5 * NIC_TX_MAX_PAGE_PER_FRAME) + +#define NIC_TX_BUFF_COUNT_TC0 HIF_TX_BUFF_COUNT_TC0 +#define NIC_TX_BUFF_COUNT_TC1 HIF_TX_BUFF_COUNT_TC1 +#define NIC_TX_BUFF_COUNT_TC2 HIF_TX_BUFF_COUNT_TC2 +#define NIC_TX_BUFF_COUNT_TC3 HIF_TX_BUFF_COUNT_TC3 +#define NIC_TX_BUFF_COUNT_TC4 HIF_TX_BUFF_COUNT_TC4 +#define NIC_TX_BUFF_COUNT_TC5 HIF_TX_BUFF_COUNT_TC5 + +#define NIC_TX_RESOURCE_CTRL HIF_TX_RESOURCE_CTRL /* to enable/disable TX resource control */ + +#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 8 +#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) + +#define NIC_TX_INIT_PAGE_COUNT_TC0 (NIC_TX_INIT_BUFF_COUNT_TC0 * NIC_TX_MAX_PAGE_PER_FRAME) +#define NIC_TX_INIT_PAGE_COUNT_TC1 (NIC_TX_INIT_BUFF_COUNT_TC1 * NIC_TX_MAX_PAGE_PER_FRAME) +#define NIC_TX_INIT_PAGE_COUNT_TC2 (NIC_TX_INIT_BUFF_COUNT_TC2 * NIC_TX_MAX_PAGE_PER_FRAME) +#define NIC_TX_INIT_PAGE_COUNT_TC3 (NIC_TX_INIT_BUFF_COUNT_TC3 * NIC_TX_MAX_PAGE_PER_FRAME) +#define NIC_TX_INIT_PAGE_COUNT_TC4 (NIC_TX_INIT_BUFF_COUNT_TC4 * NIC_TX_MAX_PAGE_PER_FRAME) +#define NIC_TX_INIT_PAGE_COUNT_TC5 (NIC_TX_INIT_BUFF_COUNT_TC5 * NIC_TX_MAX_PAGE_PER_FRAME) + +#endif + +#define NIC_TX_ENABLE_SECOND_HW_QUEUE 0 + +/* 4 TODO: The following values shall be got from FW by query CMD */ +/*------------------------------------------------------------------------*/ +/* Resource Management related information */ +/*------------------------------------------------------------------------*/ +#define NIC_TX_PAGE_SIZE_IS_POWER_OF_2 TRUE +#define NIC_TX_PAGE_SIZE_IN_POWER_OF_2 HIF_TX_PAGE_SIZE_IN_POWER_OF_2 +#define NIC_TX_PAGE_SIZE HIF_TX_PAGE_SIZE + +/* For development only */ +#define NIC_TX_MAX_SIZE_PER_FRAME 1532 /* calculated by MS native 802.11 format */ +#define NIC_TX_MAX_PAGE_PER_FRAME \ + ((NIC_TX_DESC_AND_PADDING_LENGTH + NIC_TX_DESC_HEADER_PADDING_LENGTH + \ + NIC_TX_MAX_SIZE_PER_FRAME + NIC_TX_PAGE_SIZE - 1) / NIC_TX_PAGE_SIZE) + +/*------------------------------------------------------------------------*/ +/* Tx descriptor related information */ +/*------------------------------------------------------------------------*/ + +/* Frame Buffer +* |<--Tx Descriptor-->|<--Tx descriptor padding-->|<--802.3/802.11 Header-->|<--Header padding-->|<--Payload-->| +*/ + +/* Tx descriptor length by format (TXD.FT) */ +#define NIC_TX_DESC_LONG_FORMAT_LENGTH_DW 8 /* in unit of double word */ +#define NIC_TX_DESC_LONG_FORMAT_LENGTH DWORD_TO_BYTE(NIC_TX_DESC_LONG_FORMAT_LENGTH_DW) +#define NIC_TX_DESC_SHORT_FORMAT_LENGTH_DW 3 /* in unit of double word */ +#define NIC_TX_DESC_SHORT_FORMAT_LENGTH DWORD_TO_BYTE(NIC_TX_DESC_SHORT_FORMAT_LENGTH_DW) + +/* Tx descriptor padding length (DMA.MICR.TXDSCR_PAD) */ +#define NIC_TX_DESC_PADDING_LENGTH_DW 0 /* in unit of double word */ +#define NIC_TX_DESC_PADDING_LENGTH DWORD_TO_BYTE(NIC_TX_DESC_PADDING_LENGTH_DW) + +#define NIC_TX_PSE_HEADER_LENGTH 4 + +#define NIC_TX_DESC_AND_PADDING_LENGTH (NIC_TX_DESC_LONG_FORMAT_LENGTH + NIC_TX_DESC_PADDING_LENGTH) + +/* Tx header padding (TXD.HeaderPadding) */ +/* Warning!! To use MAC header padding, every Tx packet must be decomposed */ +#define NIC_TX_DESC_HEADER_PADDING_LENGTH 0 /* in unit of bytes */ + +#define NIC_TX_DEFAULT_WLAN_INDEX 31 /* For Tx packets to peer who has no WLAN table index. */ + +#define NIC_TX_DESC_PID_RESERVED 0 +#define NIC_TX_DESC_DRIVER_PID_MIN 1 +#define NIC_TX_DESC_DRIVER_PID_MAX 127 + +#define NIC_TX_DATA_DEFAULT_RETRY_COUNT_LIMIT 30 +#define NIC_TX_MGMT_DEFAULT_RETRY_COUNT_LIMIT 30 + +#define NIC_TX_AC_BE_REMAINING_TX_TIME TX_DESC_TX_TIME_NO_LIMIT /* in unit of ms */ +#define NIC_TX_AC_BK_REMAINING_TX_TIME TX_DESC_TX_TIME_NO_LIMIT /* in unit of ms */ +#define NIC_TX_AC_VO_REMAINING_TX_TIME TX_DESC_TX_TIME_NO_LIMIT /* in unit of ms */ +#define NIC_TX_AC_VI_REMAINING_TX_TIME TX_DESC_TX_TIME_NO_LIMIT /* in unit of ms */ +#define NIC_TX_MGMT_REMAINING_TX_TIME 2000 /* in unit of ms */ +#define NIC_TX_BMC_REMAINING_TX_TIME 2000 /* in unit of ms */ + +#define NIC_TX_CRITICAL_DATA_TID 7 + +#define HW_MAC_TX_DESC_APPEND_T_LENGTH 44 +#define NIC_TX_HEAD_ROOM (NIC_TX_DESC_LONG_FORMAT_LENGTH + NIC_TX_DESC_PADDING_LENGTH \ + + HW_MAC_TX_DESC_APPEND_T_LENGTH) + +/*------------------------------------------------------------------------*/ +/* Tx status related information */ +/*------------------------------------------------------------------------*/ + +/* Tx status header & content length */ +#define NIC_TX_STATUS_HEADER_LENGTH_DW 1 /* in unit of double word */ +#define NIC_TX_STATUS_HEADER_LENGTH DWORD_TO_BYTE(NIC_TX_STATUS_HEADER_LENGTH_DW) +#define NIC_TX_STATUS_LENGTH_DW 7 /* in unit of double word */ +#define NIC_TX_STATUS_LENGTH DWORD_TO_BYTE(NIC_TX_STATUS_LENGTH_DW) + +/*------------------------------------------------------------------------*/ +/* Tx descriptor field related information */ +/*------------------------------------------------------------------------*/ +/* DW 0 */ +#define TX_DESC_TX_BYTE_COUNT_MASK BITS(0, 15) +#define TX_DESC_TX_BYTE_COUNT_OFFSET 0 + +#define TX_DESC_ETHER_TYPE_OFFSET_MASK BITS(0, 6) +#define TX_DESC_ETHER_TYPE_OFFSET_OFFSET 0 +#define TX_DESC_IP_CHKSUM_OFFLOAD BIT(7) +#define TX_DESC_TCP_UDP_CHKSUM_OFFLOAD BIT(0) +#define TX_DESC_USB_NEXT_VLD BIT(1) +#define TX_DESC_USB_TX_BURST BIT(2) +#define TX_DESC_QUEUE_INDEX_MASK BITS(2, 6) +#define TX_DESC_QUEUE_INDEX_OFFSET 2 +#define TX_DESC_PORT_INDEX BIT(7) +#define TX_DESC_PORT_INDEX_OFFSET 7 + +#define PORT_INDEX_LMAC 0 +#define PORT_INDEX_MCU 1 + +/* DW 1 */ +#define TX_DESC_WLAN_INDEX_MASK BITS(0, 7) +#define TX_DESC_WLAN_INDEX_OFFSET 0 +#define TX_DESC_HEADER_FORMAT_MASK BITS(5, 6) +#define TX_DESC_HEADER_FORMAT_OFFSET 5 + +#define HEADER_FORMAT_NON_802_11 0 /* Non-802.11 */ +#define HEADER_FORMAT_COMMAND 1 /* Command */ +#define HEADER_FORMAT_802_11_NORMAL_MODE 2 /* 802.11 (normal mode) */ +#define HEADER_FORMAT_802_11_ENHANCE_MODE 3 /* 802.11 (Enhancement mode) */ +#define HEADER_FORMAT_802_11_MASK BIT(1) + +#define TX_DESC_NON_802_11_MORE_DATA BIT(0) +#define TX_DESC_NON_802_11_EOSP BIT(1) +#define TX_DESC_NON_802_11_REMOVE_VLAN BIT(2) +#define TX_DESC_NON_802_11_VLAN_FIELD BIT(3) +#define TX_DESC_NON_802_11_ETHERNET_II BIT(4) +#define TX_DESC_NOR_802_11_HEADER_LENGTH_MASK BITS(0, 4) +#define TX_DESC_NOR_802_11_HEADER_LENGTH_OFFSET 0 +#define TX_DESC_ENH_802_11_EOSP BIT(1) +#define TX_DESC_ENH_802_11_AMSDU BIT(2) + +#define TX_DESC_FORMAT BIT(7) +#define TX_DESC_SHORT_FORMAT 0 +#define TX_DESC_LONG_FORMAT 1 + +#define TX_DESC_TXD_LENGTH_MASK BIT(0) +#define TX_DESC_TXD_LENGTH_OFFSET 0 + +#define TX_DESC_HEADER_PADDING_LENGTH_MASK BIT(1) +#define TX_DESC_HEADER_PADDING_LENGTH_OFFSET 1 +#define TX_DESC_HEADER_PADDING_MODE BIT(2) + +#define TX_DESC_TXD_EXTEND_LENGTH_MASK BIT(3) +#define TX_DESC_TXD_EXTEND_LENGTH_OFFSET 3 + +#define TX_DESC_TXD_UTXB_AMSDU_MASK BIT(4) +#define TX_DESC_TXD_UTXB_AMSDU_OFFSET 4 + +#define TX_DESC_TID_MASK BITS(5, 7) +#define TX_DESC_TID_OFFSET 5 +#define TX_DESC_TID_NUM 8 + +#define TX_DESC_PACKET_FORMAT_MASK BITS(0, 1) /* SW Field */ +#define TX_DESC_PACKET_FORMAT_OFFSET 0 +#define TX_DESC_OWN_MAC_MASK BITS(2, 7) +#define TX_DESC_OWN_MAC_OFFSET 2 + +/* DW 2 */ +#define TX_DESC_SUB_TYPE_MASK BITS(0, 3) +#define TX_DESC_SUB_TYPE_OFFSET 0 +#define TX_DESC_TYPE_MASK BITS(4, 5) +#define TX_DESC_TYPE_OFFSET 4 +#define TX_DESC_NDP BIT(6) +#define TX_DESC_NDPA BIT(7) + +#define TX_DESC_SOUNDING BIT(0) +#define TX_DESC_FORCE_RTS_CTS BIT(1) +#define TX_DESC_BROADCAST_MULTICAST BIT(2) +#define TX_DESC_BIP_PROTECTED BIT(3) +#define TX_DESC_DURATION_FIELD_CONTROL BIT(4) +#define TX_DESC_HTC_EXISTS BIT(5) +#define TX_DESC_FRAGMENT_MASK BITS(6, 7) +#define TX_DESC_FRAGMENT_OFFSET 6 +#define FRAGMENT_FISRT_PACKET 1 +#define FRAGMENT_MIDDLE_PACKET 2 +#define FRAGMENT_LAST_PACKET 3 + +#define TX_DESC_REMAINING_MAX_TX_TIME BITS(0, 7) +#define TX_DESC_TX_TIME_NO_LIMIT 0 +/* Unit of life time calculation of Tx descriptor */ +#define TX_DESC_LIFE_TIME_UNIT_IN_POWER_OF_2 5 +#define TX_DESC_LIFE_TIME_UNIT POWER_OF_2(TX_DESC_LIFE_TIME_UNIT_IN_POWER_OF_2) +#define TX_DESC_POWER_OFFSET_MASK BITS(0, 4) +#define TX_DESC_BA_DISABLE BIT(5) +#define TX_DESC_TIMING_MEASUREMENT BIT(6) +#define TX_DESC_FIXED_RATE BIT(7) + +/* DW 3 */ +#define TX_DESC_NO_ACK BIT(0) +#define TX_DESC_PROTECTED_FRAME BIT(1) +#define TX_DESC_EXTEND_MORE_DATA BIT(2) +#define TX_DESC_EXTEND_EOSP BIT(3) + +#define TX_DESC_SW_RESERVED_MASK BITS(4, 5) +#define TX_DESC_SW_RESERVED_OFFSET 4 + +#define TX_DESC_TX_COUNT_MASK BITS(6, 10) +#define TX_DESC_TX_COUNT_OFFSET 6 +#define TX_DESC_TX_COUNT_NO_ATTEMPT 0 +#define TX_DESC_TX_COUNT_NO_LIMIT 31 +#define TX_DESC_REMAINING_TX_COUNT_MASK BITS(11, 15) +#define TX_DESC_REMAINING_TX_COUNT_OFFSET 11 +#define TX_DESC_SEQUENCE_NUMBER BITS(0, 11) +#define TX_DESC_HW_RESERVED_MASK BITS(12, 13) +#define TX_DESC_HW_RESERVED_OFFSET 12 +#define TX_DESC_PN_IS_VALID BIT(14) +#define TX_DESC_SN_IS_VALID BIT(15) + +/* DW 4 */ +#define TX_DESC_PN_PART1 BITS(0, 31) + +/* DW 5 */ +#define TX_DESC_PACKET_ID BIT(0, 7) +#define TX_DESC_TX_STATUS_FORMAT BIT(0) +#define TX_DESC_TX_STATUS_FORMAT_OFFSET 0 +#define TX_DESC_TX_STATUS_TO_MCU BIT(1) +#define TX_DESC_TX_STATUS_TO_HOST BIT(2) +#define TX_DESC_DA_SOURCE BIT(3) +#define TX_DESC_POWER_MANAGEMENT_CONTROL BIT(5) +#define TX_DESC_PN_PART2 BITS(0, 15) + +/* DW 6 *//* FR = 1 */ +#define TX_DESC_BANDWIDTH_MASK BITS(0, 2) +#define TX_DESC_BANDWIDTH_OFFSET 0 +#define TX_DESC_DYNAMIC_BANDWIDTH BIT(3) +#define TX_DESC_ANTENNA_INDEX_MASK BITS(4, 15) +#define TX_DESC_ANTENNA_INDEX_OFFSET 4 + +#define TX_DESC_FIXDE_RATE_MASK BITS(0, 11) +#define TX_DESC_FIXDE_RATE_OFFSET 0 +#define TX_DESC_TX_RATE BITS(0, 5) +#define TX_DESC_TX_RATE_OFFSET 0 +#define TX_DESC_TX_MODE BITS(6, 8) +#define TX_DESC_TX_MODE_OFFSET 6 +#define TX_DESC_NSTS_MASK BITS(9, 10) +#define TX_DESC_NSTS_OFFSET 9 +#define TX_DESC_STBC BIT(11) +#define TX_DESC_BF BIT(12) +#define TX_DESC_LDPC BIT(13) +#define TX_DESC_GUARD_INTERVAL BIT(14) +#define TX_DESC_FIXED_RATE_MODE BIT(15) + +/* DW 7 */ +#define TX_DESC_SPE_EXT_IDX_MASK BITS(11, 15) +#define TX_DESC_SPE_EXT_IDX_OFFSET 11 + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE +#define NIC_TX_TIME_THRESHOLD 100 /* in unit of ms */ +#endif + +#define NIC_TX_INIT_CMD_PORT HIF_TX_INIT_CMD_PORT + +/******************************************************************************* +* 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. + */ +/* TXD_PKT_FORMAT options*/ +typedef enum _ENUM_TXD_PKT_FORMAT_OPTION_T { + TXD_PKT_FORMAT_TXD = 0, /* TXD only */ + TXD_PKT_FORMAT_TXD_PAYLOAD, /* TXD and paload */ + TXD_PKT_FORMAT_COMMAND, /* Command */ + TXD_PKT_FORMAT_FWDL, /* Firmware download */ + TXD_PKT_FORMAT_NUM, +} ENUM_TXD_PKT_FORMAT_OPTION_T; + +/* HIF Tx interrupt status queue index*/ +typedef enum _ENUM_HIF_TX_INDEX_T { + HIF_TX_AC0_INDEX = 0, + HIF_TX_AC1_INDEX, + HIF_TX_AC2_INDEX, + HIF_TX_AC3_INDEX, + + HIF_TX_AC10_INDEX, + HIF_TX_AC11_INDEX, + HIF_TX_AC12_INDEX, + HIF_TX_AC13_INDEX, + + HIF_TX_AC20_INDEX, + HIF_TX_AC21_INDEX, + HIF_TX_AC22_INDEX, + HIF_TX_AC23_INDEX, + + HIF_TX_RSV0_INDEX, + HIF_TX_RSV1_INDEX, + HIF_TX_FFA_INDEX, + HIF_TX_CPU_INDEX, + + HIF_TX_NUM +} ENUM_HIF_TX_INDEX_T; + +/* LMAC Tx queue index */ +typedef enum _ENUM_MAC_TXQ_INDEX_T { + MAC_TXQ_AC0_INDEX = 0, + MAC_TXQ_AC1_INDEX, + MAC_TXQ_AC2_INDEX, + MAC_TXQ_AC3_INDEX, + + MAC_TXQ_AC10_INDEX, + MAC_TXQ_AC11_INDEX, + MAC_TXQ_AC12_INDEX, + MAC_TXQ_AC13_INDEX, + + MAC_TXQ_AC20_INDEX, + MAC_TXQ_AC21_INDEX, + MAC_TXQ_AC22_INDEX, + MAC_TXQ_AC23_INDEX, + + MAC_TXQ_AC30_INDEX, + MAC_TXQ_AC31_INDEX, + MAC_TXQ_AC32_INDEX, + MAC_TXQ_AC33_INDEX, + + MAC_TXQ_ALTX_0_INDEX, + MAC_TXQ_BMC_0_INDEX, + MAC_TXQ_BCN_0_INDEX, + MAC_TXQ_PSMP_0_INDEX, + + MAC_TXQ_ALTX_1_INDEX, + MAC_TXQ_BMC_1_INDEX, + MAC_TXQ_BCN_1_INDEX, + MAC_TXQ_PSMP_1_INDEX, + + MAC_TXQ_NAF_INDEX, + MAC_TXQ_NBCN_INDEX, + + MAC_TXQ_NUM +} ENUM_MAC_TXQ_INDEX_T; + +/* MCU quque index */ +typedef enum _ENUM_MCU_Q_INDEX_T { + MCU_Q0_INDEX = 0, + MCU_Q1_INDEX, + MCU_Q2_INDEX, + MCU_Q3_INDEX, + MCU_Q_NUM +} ENUM_MCU_Q_INDEX_T; + +/* Tc Resource index */ +typedef enum _ENUM_TRAFFIC_CLASS_INDEX_T { + /*First HW queue */ + TC0_INDEX = 0, /* HIF TX: AC0 packets */ + TC1_INDEX, /* HIF TX: AC1 packets */ + TC2_INDEX, /* HIF TX: AC2 packets */ + TC3_INDEX, /* HIF TX: AC3 packets */ + TC4_INDEX, /* HIF TX: CPU packets */ + TC5_INDEX, /* HIF TX: AC4 packets */ + + /* Second HW queue */ +#if NIC_TX_ENABLE_SECOND_HW_QUEUE + TC6_INDEX, /* HIF TX: AC10 packets */ + TC7_INDEX, /* HIF TX: AC11 packets */ + TC8_INDEX, /* HIF TX: AC12 packets */ + TC9_INDEX, /* HIF TX: AC13 packets */ + TC10_INDEX, /* HIF TX: AC14 packets */ +#endif + + TC_NUM /* Maximum number of Traffic Classes. */ +} ENUM_TRAFFIC_CLASS_INDEX_T; + +/* +1 for DBDC */ +#define TX_PORT_NUM (TC_NUM + 1) + +#define TX_2G_WMM_PORT_NUM (TC_NUM) + +#define BMC_TC_INDEX TC1_INDEX + +/* per-Network Tc Resource index */ +typedef enum _ENUM_NETWORK_TC_RESOURCE_INDEX_T { + /* QoS Data frame, WMM AC index */ + NET_TC_WMM_AC_BE_INDEX = 0, + NET_TC_WMM_AC_BK_INDEX, + NET_TC_WMM_AC_VI_INDEX, + NET_TC_WMM_AC_VO_INDEX, + /* Mgmt frame */ + NET_TC_MGMT_INDEX, + /* nonQoS / non StaRec frame (BMC/non-associated frame) */ + NET_TC_BMC_INDEX, + + NET_TC_NUM +} ENUM_NETWORK_TC_RESOURCE_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 enum _ENUM_FIX_BW_T { + FIX_BW_NO_FIXED = 0, + FIX_BW_20 = 4, + FIX_BW_40, + FIX_BW_80, + FIX_BW_160, + FIX_BW_NUM +} ENUM_FIX_BW_T; + +typedef enum _ENUM_MSDU_OPTION_T { + MSDU_OPT_NO_ACK = BIT(0), + MSDU_OPT_NO_AGGREGATE = BIT(1), + MSDU_OPT_TIMING_MEASURE = BIT(2), + MSDU_OPT_RCPI_NOISE_STATUS = BIT(3), + + /* Option by Frame Format */ + /* Non-80211 */ + MSDU_OPT_MORE_DATA = BIT(4), + MSDU_OPT_REMOVE_VLAN = BIT(5), /* Remove VLAN tag if exists */ + + /* 80211-enhanced */ + MSDU_OPT_AMSDU = BIT(6), + + /* 80211-enhanced & Non-80211 */ + MSDU_OPT_EOSP = BIT(7), + + /* Beamform */ + MSDU_OPT_NDP = BIT(8), + MSDU_OPT_NDPA = BIT(9), + MSDU_OPT_SOUNDING = BIT(10), + + /* Protection */ + MSDU_OPT_FORCE_RTS = BIT(11), + + /* Security */ + MSDU_OPT_BIP = BIT(12), + MSDU_OPT_PROTECTED_FRAME = BIT(13), + + /* SW Field */ + MSDU_OPT_SW_DURATION = BIT(14), + MSDU_OPT_SW_PS_BIT = BIT(15), + MSDU_OPT_SW_HTC = BIT(16), + MSDU_OPT_SW_BAR_SN = BIT(17), + + /* Manual Mode */ + MSDU_OPT_MANUAL_FIRST_BIT = BIT(18), + + MSDU_OPT_MANUAL_LIFE_TIME = MSDU_OPT_MANUAL_FIRST_BIT, + MSDU_OPT_MANUAL_RETRY_LIMIT = BIT(19), + MSDU_OPT_MANUAL_POWER_OFFSET = BIT(20), + MSDU_OPT_MANUAL_TX_QUE = BIT(21), + MSDU_OPT_MANUAL_SN = BIT(22), + + MSDU_OPT_MANUAL_LAST_BIT = MSDU_OPT_MANUAL_SN +} ENUM_MSDU_OPTION_T; + +typedef enum _ENUM_MSDU_CONTROL_FLAG_T { + MSDU_CONTROL_FLAG_FORCE_TX = BIT(0) +} ENUM_MSDU_CONTROL_FLAG_T; + +typedef enum _ENUM_MSDU_RATE_MODE_T { + MSDU_RATE_MODE_AUTO = 0, + MSDU_RATE_MODE_MANUAL_DESC, + /* The following rate mode is not implemented yet */ + /* DON'T use!!! */ + MSDU_RATE_MODE_MANUAL_CR, + MSDU_RATE_MODE_LOWEST_RATE +} ENUM_MSDU_RATE_MODE_T; + +typedef enum _ENUM_DATA_RATE_MODE_T { + DATA_RATE_MODE_AUTO = 0, + DATA_RATE_MODE_MANUAL, + DATA_RATE_MODE_BSS_LOWEST +} ENUM_DATA_RATE_MODE_T; + +typedef struct _TX_TCQ_STATUS_T { + /* HIF reported page count delta */ + UINT_32 au4TxDonePageCount[TC_NUM]; /* other TC */ + UINT_32 au4PreUsedPageCount[TC_NUM]; + UINT_32 u4AvaliablePageCount; /* FFA */ + UINT_8 ucNextTcIdx; /* For round-robin distribute free page count */ + + /* distributed page count */ + UINT_32 au4FreePageCount[TC_NUM]; + UINT_32 au4MaxNumOfPage[TC_NUM]; + + /* buffer count */ + UINT_32 au4FreeBufferCount[TC_NUM]; + UINT_32 au4MaxNumOfBuffer[TC_NUM]; +} TX_TCQ_STATUS_T, *P_TX_TCQ_STATUS_T; + +typedef struct _TX_TCQ_ADJUST_T { + INT_32 ai4Variation[TC_NUM]; +} TX_TCQ_ADJUST_T, *P_TX_TCQ_ADJUST_T; + +typedef struct _TX_CTRL_T { + UINT_32 u4TxCachedSize; + PUINT_8 pucTxCached; + + UINT_32 u4PageSize; + + UINT_32 u4TotalPageNum; + + UINT_32 u4TotalTxRsvPageNum; + +/* Elements below is classified according to TC (Traffic Class) value. */ + + TX_TCQ_STATUS_T rTc; + + PUINT_8 pucTxCoalescingBufPtr; + + UINT_32 u4WrIdx; + + 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; + + /* enable/disable TX resource control */ + BOOLEAN fgIsTxResourceCtrl; +} TX_CTRL_T, *P_TX_CTRL_T; + +typedef enum _ENUM_TX_PACKET_TYPE_T { + TX_PACKET_TYPE_DATA = 0, + TX_PACKET_TYPE_MGMT, + /* TX_PACKET_TYPE_1X, */ + X_PACKET_TYPE_NUM +} ENUM_TX_PACKET_TYPE_T, *P_ENUM_TX_PACKET_TYPE_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; + +/* TX Call Back Function */ +typedef WLAN_STATUS(*PFN_TX_DONE_HANDLER) (IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE +typedef struct _PKT_PROFILE_T { + BOOLEAN fgIsValid; +#if CFG_PRINT_PKT_LIFETIME_PROFILE + BOOLEAN fgIsPrinted; + UINT_16 u2IpSn; + UINT_16 u2RtpSn; + UINT_8 ucTcxFreeCount; +#endif + OS_SYSTIME rHardXmitArrivalTimestamp; + OS_SYSTIME rEnqueueTimestamp; + OS_SYSTIME rDequeueTimestamp; + OS_SYSTIME rHifTxDoneTimestamp; +} PKT_PROFILE_T, *P_PKT_PROFILE_T; +#endif +/* TX transactions could be divided into 4 kinds: + * + * 1) 802.1X / Bluetooth-over-Wi-Fi Security Frames + * [CMD_INFO_T] - [prPacket] - in skb or NDIS_PACKET form + * + * 2) MMPDU + * [CMD_INFO_T] - [prPacket] - [MSDU_INFO_T] - [prPacket] - direct buffer for frame body + * + * 3) Command Packets + * [CMD_INFO_T] - [pucInfoBuffer] - direct buffer for content of command packet + * + * 4) Normal data frame + * [MSDU_INFO_T] - [prPacket] - in skb or NDIS_PACKET form + */ + +/* PS_FORWARDING_TYPE_NON_PS means that the receiving STA is in Active Mode +* from the perspective of host driver (maybe not synchronized with FW --> SN is needed) +*/ + +struct _MSDU_INFO_T { + QUE_ENTRY_T rQueEntry; + P_NATIVE_PACKET prPacket; /* Pointer to packet buffer */ + + ENUM_TX_PACKET_SRC_T eSrc; /* specify OS/FORWARD packet */ + UINT_8 ucUserPriority; /* QoS parameter, convert to TID */ + + /* For composing TX descriptor header */ + UINT_8 ucTC; /* Traffic Class: 0~4 (HIF TX0), 5 (HIF TX1) */ + UINT_8 ucPacketType; /* 0: Data, 1: Management Frame */ + UINT_8 ucStaRecIndex; /* STA_REC index */ + UINT_8 ucBssIndex; /* BSS_INFO_T index */ + UINT_8 ucWlanIndex; /* Wlan entry index */ + + BOOLEAN fgIs802_1x; /* TRUE: 802.1x frame */ + BOOLEAN fgIs802_1x_NonProtected; /* TRUE: 802.1x frame - Non-Protected */ + BOOLEAN fgIs802_11; /* TRUE: 802.11 header is present */ + BOOLEAN fgIs802_3; /* TRUE: 802.3 frame */ + BOOLEAN fgIsVlanExists; /* TRUE: VLAN tag is exists */ + + /* BOOLEAN fgIsBIP; *//* Management Frame Protection */ + /* BOOLEAN fgIsBasicRate; *//* Force Basic Rate Transmission */ + /* BOOLEAN fgIsMoreData; *//* More data */ + /* BOOLEAN fgIsEOSP; *//* End of service period */ + + /* Special Option */ + UINT_32 u4Option; /* Special option in bitmask, no ACK, etc... */ + INT_8 cPowerOffset; /* Per-packet power offset, in 2's complement */ + UINT_16 u2SwSN; /* SW assigned sequence number */ + UINT_8 ucRetryLimit; /* The retry limit */ + UINT_32 u4RemainingLifetime; /* Remaining lifetime, unit:ms */ + + /* Control flag */ + UINT_8 ucControlFlag; /* Control flag in bitmask */ + + /* Fixed Rate Option */ + UINT_8 ucRateMode; /* Rate mode: AUTO, MANUAL_DESC, MANUAL_CR */ + UINT_32 u4FixedRateOption; /* The rate option, rate code, GI, etc... */ + + BOOLEAN fgIsTXDTemplateValid; /* There is a valid Tx descriptor for this packet */ + + /* flattened from PACKET_INFO_T */ + UINT_8 ucMacHeaderLength; /* MAC header legth */ + UINT_8 ucLlcLength; /* w/o EtherType */ + UINT_16 u2FrameLength; /* Total frame length */ + UINT_8 aucEthDestAddr[MAC_ADDR_LEN]; /* Ethernet Destination Address */ + UINT_32 u4PageCount; /* Required page count for this MSDU */ + + /* for TX done tracking */ + UINT_8 ucTxSeqNum; /* MGMT frame serial number */ + UINT_8 ucPID; /* PID */ + UINT_8 ucWmmQueSet; /* WMM Set */ + PFN_TX_DONE_HANDLER pfTxDoneHandler; /* Tx done handler */ + UINT_32 u4TxDoneTag; /* Tag for data frame Tx done log */ + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + PKT_PROFILE_T rPktProfile; +#endif + + /* To be removed */ + UINT_8 ucFormatID; /* 0: MAUI, Linux, Windows NDIS 5.1 */ + /* 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 */ + /* TRUE means this is the last packet of the burst for (STA, TID) */ + /* BOOLEAN fgIsBurstEnd; */ +#if CFG_M0VE_BA_TO_DRIVER + UINT_8 ucTID; +#endif + +#if CFG_SUPPORT_MULTITHREAD + /* Compose TxDesc in main_thread and place here */ + UINT_8 aucTxDescBuffer[NIC_TX_DESC_AND_PADDING_LENGTH]; +#endif + +#if defined(_HIF_PCIE) + P_MSDU_TOKEN_ENTRY_T prToken; +#endif +}; + +#define HIT_PKT_FLAGS_CT_WITH_TXD BIT(0) +#define HIF_PKT_FLAGS_COPY_HOST_TXD_ALL BIT(1) + +#define MAX_BUF_NUM_PER_PKT 6 + +typedef struct _HW_MAC_TX_DESC_APPEND_T { + UINT_16 u2PktFlags; + UINT_16 u2MsduToken; + UINT_8 ucBssIndex; + UINT_8 aucReserved[2]; + UINT_8 ucBufNum; + + UINT_32 au4BufPtr[MAX_BUF_NUM_PER_PKT]; + UINT_16 au2BufLen[MAX_BUF_NUM_PER_PKT]; + UINT_8 aucPktContent[0]; +} HW_MAC_TX_DESC_APPEND_T, *P_HW_MAC_TX_DESC_APPEND_T; + +/*!A data structure which is identical with HW MAC TX DMA Descriptor */ +typedef struct _HW_MAC_TX_DESC_T { + /* DW 0 */ + UINT_16 u2TxByteCount; + UINT_8 ucEtherOffset; /* Ether-Type Offset, IP checksum offload */ + UINT_8 ucPortIdx_QueueIdx; /* UDP/TCP checksum offload, USB NextVLD/TxBURST, Queue index, Port index */ + /* DW 1 */ + UINT_8 ucWlanIdx; + UINT_8 ucHeaderFormat; /* Header format, TX descriptor format */ + UINT_8 ucHeaderPadding; /* Header padding, no ACK, TID, Protect frame */ + UINT_8 ucOwnMAC; + + /* Long Format, the following structure is for long format ONLY */ + /* DW 2 */ + UINT_8 ucType_SubType; /* Type, Sub-type, NDP, NDPA */ + UINT_8 ucFrag; /* Sounding, force RTS/CTS, BMC, BIP, Duration, HTC exist, Fragment */ + UINT_8 ucRemainingMaxTxTime; + UINT_8 ucPowerOffset; /* Power offset, Disable BA, Timing measurement, Fixed rate */ + /* DW 3 */ + UINT_16 u2TxCountLimit; /* TX count limit */ + UINT_16 u2SN; /* SN, HW own, PN valid, SN valid */ + /* DW 4 */ + UINT_32 u4PN1; + /* DW 5 */ + UINT_8 ucPID; + UINT_8 ucTxStatus; /* TXS format, TXS to mcu, TXS to host, DA source, BAR SSN, Power management */ + UINT_16 u2PN2; + /* DW 6 */ + UINT_16 u2AntID; /* Fixed rate, Antenna ID */ + UINT_16 u2FixedRate; /* Explicit/implicit beamforming, Fixed rate table, LDPC, GI */ + /* DW 7 */ + UINT_16 u2SwTxTime; /* Sw Tx time[9:0], SPE_IDX[15:11] */ + UINT_16 u2PseFid; /* indicate frame ID in PSE for this TXD */ +} HW_MAC_TX_DESC_T, *P_HW_MAC_TX_DESC_T, **PP_HW_MAC_TX_DESC_T; + +typedef struct _TX_RESOURCE_CONTROL_T { + /* HW TX queue definition */ + UINT_8 ucDestPortIndex; + UINT_8 ucDestQueueIndex; + /* HIF Interrupt status index */ + UINT_8 ucHifTxQIndex; +} TX_RESOURCE_CONTROL_T, *PTX_RESOURCE_CONTROL_T; + +typedef struct _TX_TC_TRAFFIC_SETTING_T { + UINT_32 u4TxDescLength; + UINT_32 u4RemainingTxTime; + UINT_8 ucTxCountLimit; +} TX_TC_TRAFFIC_SETTING_T, P_TX_TC_TRAFFIC_SETTING_T; + +typedef void (*PFN_TX_DATA_DONE_CB) (IN P_GLUE_INFO_T prGlueInfo, IN P_QUE_T prQue); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +extern PFN_TX_DATA_DONE_CB g_pfTxDataDoneCb; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define TX_INC_CNT(prTxCtrl, eCounter) \ + {((P_TX_CTRL_T)prTxCtrl)->au4Statistics[eCounter]++; } + +#define TX_ADD_CNT(prTxCtrl, eCounter, u8Amount) \ + {((P_TX_CTRL_T)prTxCtrl)->au4Statistics[eCounter] += (UINT_32)u8Amount; } + +#define TX_GET_CNT(prTxCtrl, eCounter) \ + (((P_TX_CTRL_T)prTxCtrl)->au4Statistics[eCounter]) + +#define TX_RESET_ALL_CNTS(prTxCtrl) \ + {kalMemZero(&prTxCtrl->au4Statistics[0], sizeof(prTxCtrl->au4Statistics)); } +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + +#if CFG_PRINT_PKT_LIFETIME_PROFILE +#define PRINT_PKT_PROFILE(_pkt_profile, _note) \ +do { \ + if (!(_pkt_profile)->fgIsPrinted) { \ + DBGLOG(TX, TRACE, "X[%lu] E[%lu] D[%lu] HD[%lu] B[%d] RTP[%d] %s\n", \ + (UINT_32)((_pkt_profile)->rHardXmitArrivalTimestamp), \ + (UINT_32)((_pkt_profile)->rEnqueueTimestamp), \ + (UINT_32)((_pkt_profile)->rDequeueTimestamp), \ + (UINT_32)((_pkt_profile)->rHifTxDoneTimestamp), \ + (UINT_8)((_pkt_profile)->ucTcxFreeCount), \ + (UINT_16)((_pkt_profile)->u2RtpSn), \ + (_note))); \ + (_pkt_profile)->fgIsPrinted = TRUE; \ + } \ +} while (0) +#else +#define PRINT_PKT_PROFILE(_pkt_profile, _note) +#endif + +#define CHK_PROFILES_DELTA(_pkt1, _pkt2, _delta) \ + (CHECK_FOR_TIMEOUT((_pkt1)->rHardXmitArrivalTimestamp, (_pkt2)->rHardXmitArrivalTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt1)->rEnqueueTimestamp, (_pkt2)->rEnqueueTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt1)->rDequeueTimestamp, (_pkt2)->rDequeueTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt1)->rHifTxDoneTimestamp, (_pkt2)->rHifTxDoneTimestamp, (_delta))) + +#define CHK_PROFILE_DELTA(_pkt, _delta) \ + (CHECK_FOR_TIMEOUT((_pkt)->rEnqueueTimestamp, (_pkt)->rHardXmitArrivalTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt)->rDequeueTimestamp, (_pkt)->rEnqueueTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt)->rHifTxDoneTimestamp, (_pkt)->rDequeueTimestamp, (_delta))) +#endif + +/*------------------------------------------------------------------------------ + * MACRO for MSDU_INFO + *------------------------------------------------------------------------------ + */ +#define TX_SET_MMPDU nicTxSetMngPacket +#define TX_SET_DATA_PACKET nicTxSetDataPacket + +/*------------------------------------------------------------------------------ + * MACRO for HW_MAC_TX_DESC_T + *------------------------------------------------------------------------------ + */ +#define TX_DESC_GET_FIELD(_rHwMacTxDescField, _mask, _offset) \ + (((_rHwMacTxDescField) & (_mask)) >> (_offset)) +#define TX_DESC_SET_FIELD(_rHwMacTxDescField, _value, _mask, _offset) \ +{ \ + (_rHwMacTxDescField) &= ~(_mask); \ + (_rHwMacTxDescField) |= (((_value) << (_offset)) & (_mask)); \ +} + +#define HAL_MAC_TX_DESC_SET_DW(_prHwMacTxDesc, _ucOffsetInDw, _ucLengthInDw, _pucValueAddr) \ + kalMemCopy((PUINT_32)(_prHwMacTxDesc) + (_ucOffsetInDw), \ + (PUINT_8)(_pucValueAddr), DWORD_TO_BYTE(_ucLengthInDw)) +#define HAL_MAC_TX_DESC_GET_DW(_prHwMacTxDesc, _ucOffsetInDw, _ucLengthInDw, _pucValueAddr) \ + kalMemCopy((PUINT_8)(_pucValueAddr), \ + (PUINT_32)(_prHwMacTxDesc) + (_ucOffsetInDw), DWORD_TO_BYTE(_ucLengthInDw)) + +/* DW 0 */ +#define HAL_MAC_TX_DESC_GET_TX_BYTE_COUNT(_prHwMacTxDesc) ((_prHwMacTxDesc)->u2TxByteCount) +#define HAL_MAC_TX_DESC_SET_TX_BYTE_COUNT(_prHwMacTxDesc, _u2TxByteCount) \ + (((_prHwMacTxDesc)->u2TxByteCount) = ((UINT_16)_u2TxByteCount)) + +#define HAL_MAC_TX_DESC_GET_ETHER_TYPE_OFFSET(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucEtherOffset, \ + TX_DESC_ETHER_TYPE_OFFSET_MASK, TX_DESC_ETHER_TYPE_OFFSET_OFFSET) +#define HAL_MAC_TX_DESC_SET_ETHER_TYPE_OFFSET(_prHwMacTxDesc, _ucEtherTypeOffset) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucEtherOffset), ((UINT_8)_ucEtherTypeOffset), \ + TX_DESC_ETHER_TYPE_OFFSET_MASK, TX_DESC_ETHER_TYPE_OFFSET_OFFSET) + +#define HAL_MAC_TX_DESC_IS_IP_CHKSUM_ENABLED(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucEtherOffset & TX_DESC_IP_CHKSUM_OFFLOAD)?FALSE:TRUE) +#define HAL_MAC_TX_DESC_SET_IP_CHKSUM(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucEtherOffset |= TX_DESC_IP_CHKSUM_OFFLOAD) +#define HAL_MAC_TX_DESC_UNSET_IP_CHKSUM(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucEtherOffset &= ~TX_DESC_IP_CHKSUM_OFFLOAD) + +#define HAL_MAC_TX_DESC_IS_TCP_UDP_CHKSUM_ENABLED(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPortIdx_QueueIdx & TX_DESC_TCP_UDP_CHKSUM_OFFLOAD)?FALSE:TRUE) +#define HAL_MAC_TX_DESC_SET_TCP_UDP_CHKSUM(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPortIdx_QueueIdx |= TX_DESC_TCP_UDP_CHKSUM_OFFLOAD) +#define HAL_MAC_TX_DESC_UNSET_TCP_UDP_CHKSUM(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPortIdx_QueueIdx &= ~TX_DESC_TCP_UDP_CHKSUM_OFFLOAD) + +#define HAL_MAC_TX_DESC_IS_USB_NEXT_VLD_ENABLED(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPortIdx_QueueIdx & TX_DESC_USB_NEXT_VLD)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_USB_NEXT_VLD(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucPortIdx_QueueIdx |= TX_DESC_USB_NEXT_VLD) +#define HAL_MAC_TX_DESC_UNSET_USB_NEXT_VLD(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPortIdx_QueueIdx &= ~TX_DESC_USB_NEXT_VLD) + +#define HAL_MAC_TX_DESC_GET_QUEUE_INDEX(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucPortIdx_QueueIdx, TX_DESC_QUEUE_INDEX_MASK, TX_DESC_QUEUE_INDEX_OFFSET) +#define HAL_MAC_TX_DESC_SET_QUEUE_INDEX(_prHwMacTxDesc, _ucQueueIndex) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucPortIdx_QueueIdx), ((UINT_8)_ucQueueIndex), \ + TX_DESC_QUEUE_INDEX_MASK, TX_DESC_QUEUE_INDEX_OFFSET) + +#define HAL_MAC_TX_DESC_GET_PORT_INDEX(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucPortIdx_QueueIdx, TX_DESC_PORT_INDEX, TX_DESC_PORT_INDEX_OFFSET) +#define HAL_MAC_TX_DESC_SET_PORT_INDEX(_prHwMacTxDesc, _ucPortIndex) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucPortIdx_QueueIdx), ((UINT_8)_ucPortIndex), \ + TX_DESC_PORT_INDEX, TX_DESC_PORT_INDEX_OFFSET) + +/* DW 1 */ +#define HAL_MAC_TX_DESC_GET_WLAN_INDEX(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucWlanIdx) +#define HAL_MAC_TX_DESC_SET_WLAN_INDEX(_prHwMacTxDesc, _ucWlanIdx) \ + (((_prHwMacTxDesc)->ucWlanIdx) = (_ucWlanIdx)) + +#define HAL_MAC_TX_DESC_IS_LONG_FORMAT(_prHwMacTxDesc) (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_FORMAT)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_LONG_FORMAT(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_FORMAT) +#define HAL_MAC_TX_DESC_SET_SHORT_FORMAT(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_FORMAT) + +#define HAL_MAC_TX_DESC_GET_HEADER_FORMAT(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucHeaderFormat, TX_DESC_HEADER_FORMAT_MASK, TX_DESC_HEADER_FORMAT_OFFSET) +#define HAL_MAC_TX_DESC_SET_HEADER_FORMAT(_prHwMacTxDesc, _ucHdrFormat) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucHeaderFormat), \ + ((UINT_8)_ucHdrFormat), TX_DESC_HEADER_FORMAT_MASK, TX_DESC_HEADER_FORMAT_OFFSET) + +/* HF = 0x00, 802.11 normal mode */ +#define HAL_MAC_TX_DESC_IS_MORE_DATA(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_NON_802_11_MORE_DATA)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_MORE_DATA(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_NON_802_11_MORE_DATA) +#define HAL_MAC_TX_DESC_UNSET_MORE_DATA(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_NON_802_11_MORE_DATA) + +#define HAL_MAC_TX_DESC_IS_REMOVE_VLAN(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_NON_802_11_REMOVE_VLAN)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_REMOVE_VLAN(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_NON_802_11_REMOVE_VLAN) +#define HAL_MAC_TX_DESC_UNSET_REMOVE_VLAN(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_NON_802_11_REMOVE_VLAN) + +#define HAL_MAC_TX_DESC_IS_VLAN(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_NON_802_11_VLAN_FIELD)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_VLAN(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_NON_802_11_VLAN_FIELD) +#define HAL_MAC_TX_DESC_UNSET_VLAN(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_NON_802_11_VLAN_FIELD) + +#define HAL_MAC_TX_DESC_IS_ETHERNET_II(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_NON_802_11_ETHERNET_II)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_ETHERNET_II(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_NON_802_11_ETHERNET_II) +#define HAL_MAC_TX_DESC_UNSET_ETHERNET_II(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_NON_802_11_ETHERNET_II) + +/* HF = 0x00/0x11, 802.11 normal/enhancement mode */ +#define HAL_MAC_TX_DESC_IS_EOSP(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_NON_802_11_EOSP)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_EOSP(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_NON_802_11_EOSP) +#define HAL_MAC_TX_DESC_UNSET_EOSP(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_NON_802_11_EOSP) + +/* HF = 0x11, 802.11 enhancement mode */ +#define HAL_MAC_TX_DESC_IS_AMSDU(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderFormat & TX_DESC_ENH_802_11_AMSDU)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_AMSDU(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucHeaderFormat |= TX_DESC_ENH_802_11_AMSDU) +#define HAL_MAC_TX_DESC_UNSET_AMSDU(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucHeaderFormat &= ~TX_DESC_ENH_802_11_AMSDU) + +/* HF = 0x10, non-802.11 */ +#define HAL_MAC_TX_DESC_GET_802_11_HEADER_LENGTH(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucHeaderFormat, \ + TX_DESC_NOR_802_11_HEADER_LENGTH_MASK, TX_DESC_NOR_802_11_HEADER_LENGTH_OFFSET) +#define HAL_MAC_TX_DESC_SET_802_11_HEADER_LENGTH(_prHwMacTxDesc, _ucHdrLength) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucHeaderFormat), ((UINT_8)_ucHdrLength), \ + TX_DESC_NOR_802_11_HEADER_LENGTH_MASK, TX_DESC_NOR_802_11_HEADER_LENGTH_OFFSET) + +#define HAL_MAC_TX_DESC_GET_TXD_LENGTH(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucHeaderPadding, TX_DESC_TXD_LENGTH_MASK, TX_DESC_TXD_LENGTH_OFFSET) +#define HAL_MAC_TX_DESC_SET_TXD_LENGTH(_prHwMacTxDesc, _ucHdrPadding) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucHeaderPadding), ((UINT_8)_ucHdrPadding), \ + TX_DESC_TXD_LENGTH_MASK, TX_DESC_TXD_LENGTH_OFFSET) + +#define HAL_MAC_TX_DESC_GET_TXD_EXTEND_LENGTH(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucHeaderPadding, \ + TX_DESC_TXD_EXTEND_LENGTH_MASK, TX_DESC_TXD_EXTEND_LENGTH_OFFSET) +#define HAL_MAC_TX_DESC_SET_TXD_EXTEND_LENGTH(_prHwMacTxDesc, _ucHdrPadding) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucHeaderPadding), ((UINT_8)_ucHdrPadding), \ + TX_DESC_TXD_EXTEND_LENGTH_MASK, TX_DESC_TXD_EXTEND_LENGTH_OFFSET) + +#define HAL_MAC_TX_DESC_GET_HEADER_PADDING(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucHeaderPadding, \ + TX_DESC_HEADER_PADDING_LENGTH_MASK, TX_DESC_HEADER_PADDING_LENGTH_OFFSET) +#define HAL_MAC_TX_DESC_SET_HEADER_PADDING(_prHwMacTxDesc, _ucHdrPadding) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucHeaderPadding), ((UINT_8)_ucHdrPadding), \ + TX_DESC_HEADER_PADDING_LENGTH_MASK, TX_DESC_HEADER_PADDING_LENGTH_OFFSET) + +#define HAL_MAC_TX_DESC_GET_UTXB_AMSDU(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucHeaderPadding, TX_DESC_TXD_UTXB_AMSDU_MASK, TX_DESC_TXD_UTXB_AMSDU_OFFSET) +#define HAL_MAC_TX_DESC_SET_UTXB_AMSDU(_prHwMacTxDesc, _ucHdrPadding) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucHeaderPadding), ((UINT_8)_ucHdrPadding), \ + TX_DESC_TXD_UTXB_AMSDU_MASK, TX_DESC_TXD_UTXB_AMSDU_OFFSET) + +#define HAL_MAC_TX_DESC_IS_HEADER_PADDING_IN_THE_HEAD(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucHeaderPadding & TX_DESC_HEADER_PADDING_MODE)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_HEADER_PADDING_IN_THE_HEAD(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderPadding |= TX_DESC_HEADER_PADDING_MODE) +#define HAL_MAC_TX_DESC_SET_HEADER_PADDING_IN_THE_TAIL(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucHeaderPadding &= ~TX_DESC_HEADER_PADDING_MODE) + +#define HAL_MAC_TX_DESC_GET_TID(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucHeaderPadding, TX_DESC_TID_MASK, TX_DESC_TID_OFFSET) +#define HAL_MAC_TX_DESC_SET_TID(_prHwMacTxDesc, _ucTID) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucHeaderPadding), ((UINT_8)_ucTID), TX_DESC_TID_MASK, TX_DESC_TID_OFFSET) + +#define HAL_MAC_TX_DESC_GET_PKT_FORMAT(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucOwnMAC, TX_DESC_PACKET_FORMAT_MASK, TX_DESC_PACKET_FORMAT_OFFSET) +#define HAL_MAC_TX_DESC_SET_PKT_FORMAT(_prHwMacTxDesc, _ucPktFormat) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucOwnMAC), ((UINT_8)_ucPktFormat), \ + TX_DESC_PACKET_FORMAT_MASK, TX_DESC_PACKET_FORMAT_OFFSET) + +#define HAL_MAC_TX_DESC_GET_OWN_MAC_INDEX(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucOwnMAC, TX_DESC_OWN_MAC_MASK, TX_DESC_OWN_MAC_OFFSET) +#define HAL_MAC_TX_DESC_SET_OWN_MAC_INDEX(_prHwMacTxDesc, _ucOwnMacIdx) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucOwnMAC), ((UINT_8)_ucOwnMacIdx), \ + TX_DESC_OWN_MAC_MASK, TX_DESC_OWN_MAC_OFFSET) + +/* DW 2 */ +#define HAL_MAC_TX_DESC_GET_SUB_TYPE(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucType_SubType, TX_DESC_SUB_TYPE_MASK, TX_DESC_SUB_TYPE_OFFSET) +#define HAL_MAC_TX_DESC_SET_SUB_TYPE(_prHwMacTxDesc, _ucSubType) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucType_SubType), ((UINT_8)_ucSubType), \ + TX_DESC_SUB_TYPE_MASK, TX_DESC_SUB_TYPE_OFFSET) + +#define HAL_MAC_TX_DESC_GET_TYPE(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucType_SubType, TX_DESC_TYPE_MASK, TX_DESC_TYPE_OFFSET) +#define HAL_MAC_TX_DESC_SET_TYPE(_prHwMacTxDesc, _ucType) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucType_SubType), ((UINT_8)_ucType), TX_DESC_TYPE_MASK, TX_DESC_TYPE_OFFSET) + +#define HAL_MAC_TX_DESC_IS_NDP(_prHwMacTxDesc) (((_prHwMacTxDesc)->ucType_SubType & TX_DESC_NDP)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_NDP(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucType_SubType |= TX_DESC_NDP) +#define HAL_MAC_TX_DESC_UNSET_NDP(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucType_SubType &= ~TX_DESC_NDP) + +#define HAL_MAC_TX_DESC_IS_NDPA(_prHwMacTxDesc) (((_prHwMacTxDesc)->ucType_SubType & TX_DESC_NDPA)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_NDPA(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucType_SubType |= TX_DESC_NDPA) +#define HAL_MAC_TX_DESC_UNSET_NDPA(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucType_SubType &= ~TX_DESC_NDPA) + +#define HAL_MAC_TX_DESC_IS_SOUNDING_FRAME(_prHwMacTxDesc) (((_prHwMacTxDesc)->ucFrag & TX_DESC_SOUNDING)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_SOUNDING_FRAME(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucFrag |= TX_DESC_SOUNDING) +#define HAL_MAC_TX_DESC_UNSET_SOUNDING_FRAME(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucFrag &= ~TX_DESC_SOUNDING) + +#define HAL_MAC_TX_DESC_IS_FORCE_RTS_CTS_EN(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucFrag & TX_DESC_FORCE_RTS_CTS)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_FORCE_RTS_CTS(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucFrag |= TX_DESC_FORCE_RTS_CTS) +#define HAL_MAC_TX_DESC_UNSET_FORCE_RTS_CTS(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucFrag &= ~TX_DESC_FORCE_RTS_CTS) + +#define HAL_MAC_TX_DESC_IS_BMC(_prHwMacTxDesc) (((_prHwMacTxDesc)->ucFrag & TX_DESC_BROADCAST_MULTICAST)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_BMC(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucFrag |= TX_DESC_BROADCAST_MULTICAST) +#define HAL_MAC_TX_DESC_UNSET_BMC(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucFrag &= ~TX_DESC_BROADCAST_MULTICAST) + +#define HAL_MAC_TX_DESC_IS_BIP(_prHwMacTxDesc) (((_prHwMacTxDesc)->ucFrag & TX_DESC_BIP_PROTECTED)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_BIP(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucFrag |= TX_DESC_BIP_PROTECTED) +#define HAL_MAC_TX_DESC_UNSET_BIP(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucFrag &= ~TX_DESC_BIP_PROTECTED) + +#define HAL_MAC_TX_DESC_IS_DURATION_CONTROL_BY_SW(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucFrag & TX_DESC_DURATION_FIELD_CONTROL)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_DURATION_CONTROL_BY_SW(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucFrag |= TX_DESC_DURATION_FIELD_CONTROL) +#define HAL_MAC_TX_DESC_SET_DURATION_CONTROL_BY_HW(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucFrag &= ~TX_DESC_DURATION_FIELD_CONTROL) + +#define HAL_MAC_TX_DESC_IS_HTC_EXIST(_prHwMacTxDesc) (((_prHwMacTxDesc)->ucFrag & TX_DESC_HTC_EXISTS)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_HTC_EXIST(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucFrag |= TX_DESC_HTC_EXISTS) +#define HAL_MAC_TX_DESC_UNSET_HTC_EXIST(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucFrag &= ~TX_DESC_HTC_EXISTS) + +#define HAL_MAC_TX_DESC_IS_FRAG_PACKET(_prHwMacTxDesc) (((_prHwMacTxDesc)->ucFrag & TX_DESC_FRAGMENT_MASK)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_GET_FRAG_PACKET_POS(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucFrag, TX_DESC_FRAGMENT_MASK, TX_DESC_FRAGMENT_OFFSET) +#define HAL_MAC_TX_DESC_SET_FRAG_PACKET_POS(_prHwMacTxDesc, _ucFragPos) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucFrag), ((UINT_8)_ucFragPos), \ + TX_DESC_FRAGMENT_MASK, TX_DESC_FRAGMENT_OFFSET) + +/* For driver */ +/* in unit of 32TU */ +#define HAL_MAC_TX_DESC_GET_REMAINING_LIFE_TIME(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucRemainingMaxTxTime) +#define HAL_MAC_TX_DESC_SET_REMAINING_LIFE_TIME(_prHwMacTxDesc, _ucLifeTime) \ + ((_prHwMacTxDesc)->ucRemainingMaxTxTime = (_ucLifeTime)) +/* in unit of ms (minimal value is about 40ms) */ +#define HAL_MAC_TX_DESC_GET_REMAINING_LIFE_TIME_IN_MS(_prHwMacTxDesc) \ + (TU_TO_MSEC(HAL_MAC_TX_DESC_GET_REMAINING_LIFE_TIME(_prHwMacTxDesc) << TX_DESC_LIFE_TIME_UNIT_IN_POWER_OF_2)) +#define HAL_MAC_TX_DESC_SET_REMAINING_LIFE_TIME_IN_MS(_prHwMacTxDesc, _u4LifeTimeMs) \ +do { \ + UINT_32 u4LifeTimeInUnit = ((MSEC_TO_USEC(_u4LifeTimeMs) / USEC_PER_TU) \ + >> TX_DESC_LIFE_TIME_UNIT_IN_POWER_OF_2); \ + if (u4LifeTimeInUnit >= BIT(8)) \ + u4LifeTimeInUnit = BITS(0, 7); \ + else if ((_u4LifeTimeMs != TX_DESC_TX_TIME_NO_LIMIT) && (u4LifeTimeInUnit == TX_DESC_TX_TIME_NO_LIMIT)) \ + u4LifeTimeInUnit = 1; \ + HAL_MAC_TX_DESC_SET_REMAINING_LIFE_TIME(_prHwMacTxDesc, (UINT_8)u4LifeTimeInUnit); \ +} while (0) + +#define HAL_MAC_TX_DESC_GET_POWER_OFFSET(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucPowerOffset, TX_DESC_POWER_OFFSET_MASK, 0) +#define HAL_MAC_TX_DESC_SET_POWER_OFFSET(_prHwMacTxDesc, _ucPowerOffset) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucPowerOffset), ((UINT_8)_ucPowerOffset), TX_DESC_POWER_OFFSET_MASK, 0) + +#define HAL_MAC_TX_DESC_IS_BA_DISABLE(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPowerOffset & TX_DESC_BA_DISABLE)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_BA_DISABLE(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucPowerOffset |= TX_DESC_BA_DISABLE) +#define HAL_MAC_TX_DESC_SET_BA_ENABLE(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucPowerOffset &= ~TX_DESC_BA_DISABLE) + +#define HAL_MAC_TX_DESC_IS_TIMING_MEASUREMENT(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPowerOffset & TX_DESC_TIMING_MEASUREMENT)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_TIMING_MEASUREMENT(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset |= TX_DESC_TIMING_MEASUREMENT) +#define HAL_MAC_TX_DESC_UNSET_TIMING_MEASUREMENT(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset &= ~TX_DESC_TIMING_MEASUREMENT) + +#define HAL_MAC_TX_DESC_IS_FIXED_RATE_ENABLE(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPowerOffset & TX_DESC_FIXED_RATE)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_FIXED_RATE_ENABLE(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucPowerOffset |= TX_DESC_FIXED_RATE) +#define HAL_MAC_TX_DESC_SET_FIXED_RATE_DISABLE(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucPowerOffset &= ~TX_DESC_FIXED_RATE) + +/* DW 3 */ +#define HAL_MAC_TX_DESC_IS_NO_ACK(_prHwMacTxDesc) (((_prHwMacTxDesc)->u2TxCountLimit & TX_DESC_NO_ACK)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_NO_ACK(_prHwMacTxDesc) ((_prHwMacTxDesc)->u2TxCountLimit |= TX_DESC_NO_ACK) +#define HAL_MAC_TX_DESC_UNSET_NO_ACK(_prHwMacTxDesc) ((_prHwMacTxDesc)->u2TxCountLimit &= ~TX_DESC_NO_ACK) + +#define HAL_MAC_TX_DESC_IS_PROTECTION(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->u2TxCountLimit & TX_DESC_PROTECTED_FRAME)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_PROTECTION(_prHwMacTxDesc) ((_prHwMacTxDesc)->u2TxCountLimit |= TX_DESC_PROTECTED_FRAME) +#define HAL_MAC_TX_DESC_UNSET_PROTECTION(_prHwMacTxDesc) ((_prHwMacTxDesc)->u2TxCountLimit &= ~TX_DESC_PROTECTED_FRAME) + +#define HAL_MAC_TX_DESC_IS_EXTEND_MORE_DATA(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->u2TxCountLimit & TX_DESC_EXTEND_MORE_DATA)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_EXTEND_MORE_DATA(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2TxCountLimit |= TX_DESC_EXTEND_MORE_DATA) +#define HAL_MAC_TX_DESC_UNSET_EXTEND_MORE_DATA(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2TxCountLimit &= ~TX_DESC_EXTEND_MORE_DATA) + +#define HAL_MAC_TX_DESC_IS_EXTEND_EOSP(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->u2TxCountLimit & TX_DESC_EXTEND_EOSP)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_EXTEND_EOSP(_prHwMacTxDesc) ((_prHwMacTxDesc)->u2TxCountLimit |= TX_DESC_EXTEND_EOSP) +#define HAL_MAC_TX_DESC_UNSET_EXTEND_EOSP(_prHwMacTxDesc) ((_prHwMacTxDesc)->u2TxCountLimit &= ~TX_DESC_EXTEND_EOSP) + +#define HAL_MAC_TX_DESC_GET_SW_RESERVED(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->u2TxCountLimit, TX_DESC_SW_RESERVED_MASK, TX_DESC_SW_RESERVED_OFFSET) +#define HAL_MAC_TX_DESC_SET_SW_RESERVED(_prHwMacTxDesc, _ucSwReserved) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2TxCountLimit), ((UINT_8)_ucSwReserved), \ + TX_DESC_SW_RESERVED_MASK, TX_DESC_SW_RESERVED_OFFSET) +#define HAL_MAC_TX_DESC_GET_TX_COUNT(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->u2TxCountLimit, TX_DESC_TX_COUNT_MASK, TX_DESC_TX_COUNT_OFFSET) +#define HAL_MAC_TX_DESC_SET_TX_COUNT(_prHwMacTxDesc, _ucTxCountLimit) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2TxCountLimit), ((UINT_8)_ucTxCountLimit), \ + TX_DESC_TX_COUNT_MASK, TX_DESC_TX_COUNT_OFFSET) +#define HAL_MAC_TX_DESC_GET_REMAINING_TX_COUNT(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->u2TxCountLimit, \ + TX_DESC_REMAINING_TX_COUNT_MASK, TX_DESC_REMAINING_TX_COUNT_OFFSET) +#define HAL_MAC_TX_DESC_SET_REMAINING_TX_COUNT(_prHwMacTxDesc, _ucTxCountLimit) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2TxCountLimit), ((UINT_8)_ucTxCountLimit), \ + TX_DESC_REMAINING_TX_COUNT_MASK, TX_DESC_REMAINING_TX_COUNT_OFFSET) +#define HAL_MAC_TX_DESC_GET_SEQUENCE_NUMBER(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->u2SN, TX_DESC_SEQUENCE_NUMBER, 0) +#define HAL_MAC_TX_DESC_SET_SEQUENCE_NUMBER(_prHwMacTxDesc, _u2SN) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2SN), ((UINT_16)_u2SN), TX_DESC_SEQUENCE_NUMBER, 0) +#define HAL_MAC_TX_DESC_SET_HW_RESERVED(_prHwMacTxDesc, _ucHwReserved) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2SN), ((UINT_8)_ucHwReserved), \ + TX_DESC_HW_RESERVED_MASK, TX_DESC_HW_RESERVED_OFFSET) +#define HAL_MAC_TX_DESC_IS_TXD_SN_VALID(_prHwMacTxDesc) (((_prHwMacTxDesc)->u2SN & TX_DESC_SN_IS_VALID)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_TXD_SN_VALID(_prHwMacTxDesc) ((_prHwMacTxDesc)->u2SN |= TX_DESC_SN_IS_VALID) +#define HAL_MAC_TX_DESC_SET_TXD_SN_INVALID(_prHwMacTxDesc) ((_prHwMacTxDesc)->u2SN &= ~TX_DESC_SN_IS_VALID) + +#define HAL_MAC_TX_DESC_IS_TXD_PN_VALID(_prHwMacTxDesc) (((_prHwMacTxDesc)->u2SN & TX_DESC_PN_IS_VALID)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_TXD_PN_VALID(_prHwMacTxDesc) ((_prHwMacTxDesc)->u2SN |= TX_DESC_PN_IS_VALID) +#define HAL_MAC_TX_DESC_SET_TXD_PN_INVALID(_prHwMacTxDesc) ((_prHwMacTxDesc)->u2SN &= ~TX_DESC_PN_IS_VALID) + +#define HAL_MAC_TX_DESC_ASSIGN_SN_BY_SW(_prHwMacTxDesc, _u2SN) \ +{ \ + HAL_MAC_TX_DESC_SET_SEQUENCE_NUMBER(_prHwMacTxDesc, _u2SN); \ + HAL_MAC_TX_DESC_SET_TXD_SN_VALID(_prHwMacTxDesc); \ +} +#define HAL_MAC_TX_DESC_ASSIGN_SN_BY_HW(_prHwMacTxDesc) \ +{ \ + HAL_MAC_TX_DESC_SET_SEQUENCE_NUMBER(_prHwMacTxDesc, 0); \ + HAL_MAC_TX_DESC_SET_TXD_SN_INVALID(_prHwMacTxDesc); \ +} + +/* DW 4 */ +#define HAL_MAC_TX_DESC_GET_PN(_prHwMacTxDesc, _u4PN_0_31, _u2PN_32_47) \ +{ \ + ((UINT_32)_u4PN_0_31) = (_prHwMacTxDesc)->u4PN1; \ + ((UINT_16)_u2PN_32_47) = (_prHwMacTxDesc)->u2PN2; \ +} +#define HAL_MAC_TX_DESC_SET_PN(_prHwMacTxDesc, _u4PN_0_31, _u2PN_32_47) \ +{ \ + (_prHwMacTxDesc)->u4PN1 = ((UINT_32)_u4PN_0_31); \ + (_prHwMacTxDesc)->u2PN2 = ((UINT_16)_u2PN_32_47); \ +} + +#define HAL_MAC_TX_DESC_ASSIGN_PN_BY_SW(_prHwMacTxDesc, _u4PN_0_31, _u2PN_32_47) \ +{ \ + HAL_MAC_TX_DESC_SET_PN(_prHwMacTxDesc, _u4PN_0_31, _u2PN_32_47); \ + HAL_MAC_TX_DESC_SET_TXD_PN_VALID(_prHwMacTxDesc); \ +} +#define HAL_MAC_TX_DESC_ASSIGN_PSN_BY_HW(_prHwMacTxDesc) \ +{ \ + HAL_MAC_TX_DESC_SET_PN(_prHwMacTxDesc, 0, 0); \ + HAL_MAC_TX_DESC_SET_TXD_PN_INVALID(_prHwMacTxDesc); \ +} + +/* DW 5 */ +#define HAL_MAC_TX_DESC_GET_PID(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPID) +#define HAL_MAC_TX_DESC_SET_PID(_prHwMacTxDesc, _ucPID) \ + (((_prHwMacTxDesc)->ucPID) = (_ucPID)) + +#define HAL_MAC_TX_DESC_GET_TXS_FORMAT(_prHwMacTxDesc) \ + TX_DESC_GET_FIELD((_prHwMacTxDesc)->ucTxStatus, TX_DESC_TX_STATUS_FORMAT, TX_DESC_TX_STATUS_FORMAT_OFFSET) +#define HAL_MAC_TX_DESC_SET_TXS_FORMAT(_prHwMacTxDesc, _ucTXSFormat) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->ucTxStatus), ((UINT_8)_ucTXSFormat), \ + TX_DESC_TX_STATUS_FORMAT, TX_DESC_TX_STATUS_FORMAT_OFFSET) + +#define HAL_MAC_TX_DESC_IS_TXS_TO_MCU(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucTxStatus & TX_DESC_TX_STATUS_TO_MCU)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_TXS_TO_MCU(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucTxStatus |= TX_DESC_TX_STATUS_TO_MCU) +#define HAL_MAC_TX_DESC_UNSET_TXS_TO_MCU(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucTxStatus &= ~TX_DESC_TX_STATUS_TO_MCU) + +#define HAL_MAC_TX_DESC_IS_TXS_TO_HOST(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucTxStatus & TX_DESC_TX_STATUS_TO_HOST)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_TXS_TO_HOST(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucTxStatus |= TX_DESC_TX_STATUS_TO_HOST) +#define HAL_MAC_TX_DESC_UNSET_TXS_TO_HOST(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucTxStatus &= ~TX_DESC_TX_STATUS_TO_HOST) + +#define HAL_MAC_TX_DESC_IS_DA_FROM_WTBL(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPowerOffset & TX_DESC_DA_SOURCE)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_DA_FROM_WTBL(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucPowerOffset |= TX_DESC_DA_SOURCE) +#define HAL_MAC_TX_DESC_SET_DA_FROM_MSDU(_prHwMacTxDesc) ((_prHwMacTxDesc)->ucPowerOffset &= ~TX_DESC_DA_SOURCE) + +#define HAL_MAC_TX_DESC_IS_SW_PM_CONTROL(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->ucPowerOffset & TX_DESC_POWER_MANAGEMENT_CONTROL)?TRUE:FALSE) +#define HAL_MAC_TX_DESC_SET_SW_PM_CONTROL(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset |= TX_DESC_POWER_MANAGEMENT_CONTROL) +#define HAL_MAC_TX_DESC_SET_HW_PM_CONTROL(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->ucPowerOffset &= ~TX_DESC_POWER_MANAGEMENT_CONTROL) + +/* DW 6 */ +#define HAL_MAC_TX_DESC_SET_FR_BW(_prHwMacTxDesc, ucBw) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2AntID), ((UINT_8)ucBw), TX_DESC_BANDWIDTH_MASK, TX_DESC_BANDWIDTH_OFFSET) + +#define HAL_MAC_TX_DESC_SET_FR_DYNAMIC_BW_RTS(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2AntID |= TX_DESC_DYNAMIC_BANDWIDTH) + +#define HAL_MAC_TX_DESC_SET_FR_ANTENNA_ID(_prHwMacTxDesc, _ucAntId) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2AntID), ((UINT_8)_ucAntId), \ + TX_DESC_ANTENNA_INDEX_MASK, TX_DESC_ANTENNA_INDEX_OFFSET) + +#define HAL_MAC_TX_DESC_SET_FR_RATE(_prHwMacTxDesc, _u2RatetoFixed) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2FixedRate), ((UINT_8)_u2RatetoFixed), \ + TX_DESC_FIXDE_RATE_MASK, TX_DESC_FIXDE_RATE_OFFSET) + +#define HAL_MAC_TX_DESC_SET_FR_BF(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2FixedRate |= TX_DESC_BF) + +#define HAL_MAC_TX_DESC_SET_FR_LDPC(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2FixedRate |= TX_DESC_LDPC) + +#define HAL_MAC_TX_DESC_SET_FR_SHORT_GI(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2FixedRate |= TX_DESC_GUARD_INTERVAL) + +#define HAL_MAC_TX_DESC_SET_FR_NORMAL_GI(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2FixedRate &= ~TX_DESC_GUARD_INTERVAL) + +#define HAL_MAC_TX_DESC_IS_CR_FIXED_RATE_MODE(_prHwMacTxDesc) \ + (((_prHwMacTxDesc)->u2FixedRate & TX_DESC_FIXED_RATE_MODE)?TRUE:FALSE) + +#define HAL_MAC_TX_DESC_SET_FIXED_RATE_MODE_TO_DESC(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2FixedRate &= ~TX_DESC_FIXED_RATE_MODE) +#define HAL_MAC_TX_DESC_SET_FIXED_RATE_MODE_TO_CR(_prHwMacTxDesc) \ + ((_prHwMacTxDesc)->u2FixedRate |= TX_DESC_FIXED_RATE_MODE) + +/* DW 7 */ +#define HAL_MAC_TX_DESC_SET_SPE_IDX(_prHwMacTxDesc, _ucSpeIdx) \ + TX_DESC_SET_FIELD(((_prHwMacTxDesc)->u2SwTxTime), ((UINT_16)_ucSpeIdx), \ + TX_DESC_SPE_EXT_IDX_MASK, TX_DESC_SPE_EXT_IDX_OFFSET) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID nicTxInitialize(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS nicTxAcquireResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC, IN UINT_32 u4PageCount, + IN BOOLEAN fgReqLock); + +WLAN_STATUS nicTxPollingResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC); + +BOOLEAN nicTxReleaseResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTc, IN UINT_32 u4PageCount, + IN BOOLEAN fgReqLock); + +VOID nicTxReleaseMsduResource(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead); + +WLAN_STATUS nicTxResetResource(IN P_ADAPTER_T prAdapter); + +UINT_32 nicTxGetAdjustableResourceCnt(IN P_ADAPTER_T prAdapter); + +UINT_16 nicTxGetResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC); + +UINT_8 nicTxGetFrameResourceType(IN UINT_8 eFrameType, IN P_MSDU_INFO_T prMsduInfo); + +UINT_8 nicTxGetCmdResourceType(IN P_CMD_INFO_T prCmdInfo); + +BOOLEAN nicTxSanityCheckResource(IN P_ADAPTER_T prAdapter); + +VOID nicTxFillDesc(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, OUT PUINT_8 prTxDescBuffer, + OUT PUINT_32 pu4TxDescLength); + +VOID nicTxFillDataDesc(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +VOID nicTxComposeSecurityFrameDesc(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, + OUT PUINT_8 prTxDescBuffer, OUT PUINT_8 pucTxDescLength); + +WLAN_STATUS nicTxMsduInfoList(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead); + +UINT_8 nicTxGetTxQByTc(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTc); + +#if CFG_SUPPORT_MULTITHREAD +WLAN_STATUS nicTxMsduInfoListMthread(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead); + +UINT_32 nicTxMsduQueueMthread(IN P_ADAPTER_T prAdapter); + +UINT_32 nicTxGetMsduPendingCnt(IN P_ADAPTER_T prAdapter); +#endif + +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, IN BOOLEAN fgProcTxDoneHandler); + +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); + +WLAN_STATUS nicTxInitResetResource(IN P_ADAPTER_T prAdapter); +#endif + +WLAN_STATUS nicTxEnqueueMsdu(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +UINT_8 nicTxGetWlanIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, IN UINT_8 ucStaRecIdx); + +BOOLEAN nicTxIsMgmtResourceEnough(IN P_ADAPTER_T prAdapter); + +UINT_32 nicTxGetFreeCmdCount(IN P_ADAPTER_T prAdapter); + +UINT_32 nicTxGetPageCount(IN UINT_32 u4FrameLength, IN BOOLEAN fgIncludeDesc); + +UINT_32 nicTxGetCmdPageCount(IN P_CMD_INFO_T prCmdInfo); + +WLAN_STATUS nicTxGenerateDescTemplate(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +VOID nicTxFreeDescTemplate(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +VOID nicTxFreePacket(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN BOOLEAN fgDrop); + +VOID +nicTxSetMngPacket(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN UINT_8 ucBssIndex, + IN UINT_8 ucStaRecIndex, + IN UINT_8 ucMacHeaderLength, + IN UINT_16 u2FrameLength, IN PFN_TX_DONE_HANDLER pfTxDoneHandler, IN UINT_8 ucRateMode); + +VOID +nicTxSetDataPacket(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN UINT_8 ucBssIndex, + IN UINT_8 ucStaRecIndex, + IN UINT_8 ucMacHeaderLength, + IN UINT_16 u2FrameLength, + IN PFN_TX_DONE_HANDLER pfTxDoneHandler, + IN UINT_8 ucRateMode, + IN ENUM_TX_PACKET_SRC_T eSrc, IN UINT_8 ucTID, IN BOOLEAN fgIs802_11Frame, IN BOOLEAN fgIs1xFrame); + +VOID nicTxFillDescByPktOption(IN P_MSDU_INFO_T prMsduInfo, IN P_HW_MAC_TX_DESC_T prTxDesc); + +VOID nicTxConfigPktOption(IN P_MSDU_INFO_T prMsduInfo, IN UINT_32 u4OptionMask, IN BOOLEAN fgSetOption); + +VOID nicTxFillDescByPktControl(P_MSDU_INFO_T prMsduInfo, P_HW_MAC_TX_DESC_T prTxDesc); + +VOID nicTxConfigPktControlFlag(IN P_MSDU_INFO_T prMsduInfo, IN UINT_8 ucControlFlagMask, IN BOOLEAN fgSetFlag); + +VOID nicTxSetPktLifeTime(IN P_MSDU_INFO_T prMsduInfo, IN UINT_32 u4TxLifeTimeInMs); + +VOID nicTxSetPktRetryLimit(IN P_MSDU_INFO_T prMsduInfo, IN UINT_8 ucRetryLimit); + +VOID nicTxSetPktPowerOffset(IN P_MSDU_INFO_T prMsduInfo, IN INT_8 cPowerOffset); + +VOID nicTxSetPktSequenceNumber(IN P_MSDU_INFO_T prMsduInfo, IN UINT_16 u2SN); + +VOID nicTxSetPktMacTxQue(IN P_MSDU_INFO_T prMsduInfo, IN UINT_8 ucMacTxQue); + +VOID nicTxSetPktFixedRateOptionFull(P_MSDU_INFO_T prMsduInfo, + UINT_16 u2RateCode, UINT_8 ucBandwidth, BOOLEAN fgShortGI, BOOLEAN fgLDPC, + BOOLEAN fgDynamicBwRts, BOOLEAN fgBeamforming, UINT_8 ucAntennaIndex); + +VOID nicTxSetPktFixedRateOption(IN P_MSDU_INFO_T prMsduInfo, + IN UINT_16 u2RateCode, IN UINT_8 ucBandwidth, IN BOOLEAN fgShortGI, + IN BOOLEAN fgDynamicBwRts); + +VOID nicTxSetPktLowestFixedRate(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +VOID nicTxSetPktMoreData(IN P_MSDU_INFO_T prCurrentMsduInfo, IN BOOLEAN fgSetMoreDataBit); + +VOID nicTxSetPktEOSP(IN P_MSDU_INFO_T prCurrentMsduInfo, IN BOOLEAN fgSetEOSPBit); + +UINT_8 nicTxAssignPID(IN P_ADAPTER_T prAdapter, IN UINT_8 ucWlanIndex); + +WLAN_STATUS +nicTxDummyTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +VOID nicTxUpdateBssDefaultRate(IN P_BSS_INFO_T prBssInfo); + +VOID nicTxUpdateStaRecDefaultRate(IN P_STA_RECORD_T prStaRec); + +VOID +nicTxPrintMetRTP(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN P_NATIVE_PACKET prPacket, IN UINT_32 u4PacketLen, IN BOOLEAN bFreeSkb); + +VOID nicTxProcessTxDoneEvent(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); + +void nicTxMsduDoneCb(IN P_GLUE_INFO_T prGlueInfo, IN P_QUE_T prQue); + +VOID nicTxCancelSendingCmd(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +/* TX Direct functions : BEGIN */ +VOID nicTxDirectStartCheckQTimer(IN P_ADAPTER_T prAdapter); +VOID nicTxDirectClearSkbQ(IN P_ADAPTER_T prAdapter); +VOID nicTxDirectClearHifQ(IN P_ADAPTER_T prAdapter); +VOID nicTxDirectClearStaPsQ(IN P_ADAPTER_T prAdapter, UINT_8 ucStaRecIndex); +VOID nicTxDirectClearBssAbsentQ(IN P_ADAPTER_T prAdapter, UINT_8 ucBssIndex); +VOID nicTxDirectClearAllStaPsQ(IN P_ADAPTER_T prAdapter); +#if KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE +void nicTxDirectTimerCheckSkbQ(struct timer_list *timer); +void nicTxDirectTimerCheckHifQ(struct timer_list *timer); +#else +void nicTxDirectTimerCheckSkbQ(unsigned long data); +void nicTxDirectTimerCheckHifQ(unsigned long data); +#endif +WLAN_STATUS nicTxDirectStartXmit(struct sk_buff *prSkb, P_GLUE_INFO_T prGlueInfo); +/* TX Direct functions : END */ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _NIC_TX_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/nic_umac.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/nic_umac.h new file mode 100644 index 0000000000000..fc4e2e398830f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/nic_umac.h @@ -0,0 +1,138 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/nic_umac.h#1 +*/ + +/*! \file "nic_umac.h" +* \brief The declaration of the nic umac debug functions +* +*/ + + +#ifndef _NIC_UMAC_H +#define _NIC_UMAC_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 +******************************************************************************** +*/ + +#define UMAC_FID_MASK 0xFFF + +#define UMAC_FID_FAULT 0xFFF + +#define UMAC_PLE_CFG_POOL_INDEX 0 +#define UMAC_PSE_CFG_POOL_INDEX 1 + +#define UMAC_PG_HIF0_GROUP_0 0 +#define UMAC_PG_HIF1_GROUP_1 1 +#define UMAC_PG_CPU_GROUP_2 2 +#define UMAC_PG_LMAC0_GROUP_3 3 +#define UMAC_PG_LMAC1_GROUP_4 4 +#define UMAC_PG_LMAC2_GROUP_5 5 +#define UMAC_PG_PLE_GROUP_6 6 + +#define UMAC_PBUF_CTRL_TOTAL_PAGE_NUM_MASK BITS(0, 11) +#define UMAC_PBUF_CTRL_TOTAL_PAGE_NUM_OFFSET 0 + +#define UMAC_FREEPG_CNT_FREEPAGE_CNT_MASK BITS(0, 11) +#define UMAC_FREEPG_CNT_FREEPAGE_CNT_OFFSET 0 + +#define UMAC_FREEPG_CNT_FFA_CNT_MASK BITS(16, 27) +#define UMAC_FREEPG_CNT_FFA_CNT_OFFSET 16 + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +OUT BOOLEAN +halUmacInfoGetMiscStatus(IN P_ADAPTER_T prAdapter, IN P_UMAC_STAT2_GET_T pUmacStat2Get); + +#endif /* _NIC_UMAC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/p2p.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/p2p.h new file mode 100644 index 0000000000000..7370303151ab5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/p2p.h @@ -0,0 +1,327 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/nic/p2p.h#3 +*/ + + +#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 + +/* Device Capability Definition. */ +#define P2P_MAXIMUM_CLIENT_COUNT 10 +#define P2P_MAXIMUM_NOA_COUNT 8 + +#define P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE 51 /* Contains 6 sub-band. */ + +/* Memory Size Definition. */ +#define P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE 768 +#define WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE 300 + +#define P2P_WILDCARD_SSID "DIRECT-" + +/* Device Charactoristic. */ +#define P2P_AP_CHNL_HOLD_TIME_MS 5000 /* 1000 is too short , the deauth would block in the queue */ +#define P2P_DEFAULT_LISTEN_CHANNEL 1 + +#if (CFG_SUPPORT_DFS_MASTER == 1) +#define P2P_AP_CAC_WEATHER_CHNL_HOLD_TIME_MS (600*1000) +#endif + +#define P2P_DEAUTH_TIMEOUT_TIME_MS 1000 + +/******************************************************************************* + * M A C R O S + ******************************************************************************** + */ + +#if DBG +#define ASSERT_BREAK(_exp) \ + { \ + if (!(_exp)) { \ + ASSERT(FALSE); \ + break; \ + } \ + } + +#else +#define ASSERT_BREAK(_exp) +#endif + +#define p2pChangeMediaState(_prAdapter, _prP2pBssInfo, _eNewMediaState) \ + (_prP2pBssInfo->eConnectionState = (_eNewMediaState)) + +/******************************************************************************* + * 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; + /* A common pool for IE of all scan results. */ + UINT_8 aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN]; +}; + +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; + +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_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]; + UINT_8 ucSsidNum; + P2P_SSID_STRUCT_T arSsidStruct[SCN_SSID_MAX_NUM]; /* Currently we can only take one SSID scan request */ +} P2P_SCAN_REQ_INFO_T, *P_P2P_SCAN_REQ_INFO_T; + +typedef struct _P2P_CHNL_REQ_INFO_T { + LINK_T rP2pChnlReqLink; + BOOLEAN fgIsChannelRequested; + UINT_8 ucSeqNumOfChReq; + UINT_64 u8Cookie; + UINT_8 ucReqChnlNum; + ENUM_BAND_T eBand; + ENUM_CHNL_EXT_T eChnlSco; + UINT_8 ucOriChnlNum; + ENUM_CHANNEL_WIDTH_T eChannelWidth; /*VHT operation ie */ + UINT_8 ucCenterFreqS1; + UINT_8 ucCenterFreqS2; + ENUM_BAND_T eOriBand; + ENUM_CHNL_EXT_T eOriChnlSco; + UINT_32 u4MaxInterval; + ENUM_CH_REQ_TYPE_T eChnlReqType; +#if CFG_SUPPORT_NFC_BEAM_PLUS + UINT_32 NFC_BEAM; /*NFC Beam + Indication */ +#endif +} P2P_CHNL_REQ_INFO_T, *P_P2P_CHNL_REQ_INFO_T; + +/* Glubal Connection Settings. */ +struct _P2P_CONNECTION_SETTINGS_T { + /*UINT_8 ucRfChannelListSize;*/ +#if P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE + /*UINT_8 aucChannelEntriesField[P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE];*/ +#endif + + BOOLEAN fgIsApMode; +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + BOOLEAN fgIsWPSMode; +#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; + +struct _P2P_SPECIFIC_BSS_INFO_T { + /* For GO(AP) Mode - Compose TIM IE */ + /*UINT_16 u2SmallestAID;*//* TH3 multiple P2P */ + /*UINT_16 u2LargestAID;*//* TH3 multiple P2P */ + /*UINT_8 ucBitmapCtrl;*//* TH3 multiple P2P */ + /* 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;*//* TH3 multiple P2P */ /* Regulatory Class for channel. */ + /* Linten Channel only on channels 1, 6 and 11 in the 2.4 GHz. */ + /*UINT_8 ucListenChannel;*//* TH3 multiple P2P */ + + /* Operating Channel, should be one of channel */ + /* list in p2p connection settings. */ + UINT_8 ucPreferredChannel; + ENUM_CHNL_EXT_T eRfSco; + ENUM_BAND_T eRfBand; + + /* Extended Listen Timing. */ + UINT_16 u2AvailabilityPeriod; + UINT_16 u2AvailabilityInterval; + + UINT_16 u2AttributeLen; + UINT_8 aucAttributesCache[P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; + + /*UINT_16 u2WscAttributeLen;*//* TH3 multiple P2P */ + /*UINT_8 aucWscAttributesCache[WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE];*//* TH3 multiple P2P */ + + /*UINT_8 aucGroupID[MAC_ADDR_LEN];*//* TH3 multiple P2P */ + UINT_16 u2GroupSsidLen; + UINT_8 aucGroupSsid[ELEM_MAX_LEN_SSID]; + + PARAM_CUSTOM_NOA_PARAM_STRUCT_T rNoaParam; + PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T rOppPsParam; + + UINT_16 u2WpaIeLen; + UINT_8 aucWpaIeBuffer[ELEM_HDR_LEN + ELEM_MAX_LEN_WPA]; +}; + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************** + */ + +#endif /*_P2P_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/p2p_cmd_buf.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/p2p_cmd_buf.h new file mode 100644 index 0000000000000..3d435f51c6933 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/p2p_cmd_buf.h @@ -0,0 +1,120 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. + */ + + +#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, IN UINT_8 ucCID, + IN UINT_8 ucBssIdx, IN BOOLEAN fgSetQuery, + IN BOOLEAN fgNeedResp, IN BOOLEAN fgIsOid, + IN PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + IN PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + IN UINT_32 u4SetQueryInfoLen, + IN PUINT_8 pucInfoBuffer, OUT PVOID pvSetQueryBuffer, + IN UINT_32 u4SetQueryBufferLen); + +#endif /* _P2P_CMD_BUF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/p2p_mac.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/p2p_mac.h new file mode 100644 index 0000000000000..92260d5610c29 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/p2p_mac.h @@ -0,0 +1,393 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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 + ******************************************************************************** + */ + +/* --------------- 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 + +/* --------------- WFA P2P IE --------------- */ +/* P2P 4.1.1 - P2P IE format */ +#define P2P_OUI_TYPE_LEN 4 +/* == OFFSET_OF(IE_P2P_T, aucP2PAttributes[0]) */ +#define P2P_IE_OUI_HDR (ELEM_HDR_LEN + P2P_OUI_TYPE_LEN) + +/* 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 */ +#define P2P_ATTRI_MAX_LEN_LISTEN_CHANNEL 5 /* 6 */ +#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_MAXIMUM_ATTRIBUTE_LEN 251 + +/* 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.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) + +/* --------------- 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 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; + +/* 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.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.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; + +/* 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.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 _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; + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/p2p_nic.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/p2p_nic.h new file mode 100644 index 0000000000000..cb168e0797964 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/p2p_nic.h @@ -0,0 +1,112 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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 UINT_8 ucBssIndex, IN P_EVENT_CONNECTION_STATUS prConnectionStatus); + +VOID +nicRxAddP2pDevice(IN P_ADAPTER_T prAdapter, IN P_EVENT_P2P_DEV_DISCOVER_RESULT_T prP2pResult, IN PUINT_8 pucRxIEBuf, IN + UINT_16 u2RxIELength); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/p2p_nic_cmd_event.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/p2p_nic_cmd_event.h new file mode 100644 index 0000000000000..98f827e388c12 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/p2p_nic_cmd_event.h @@ -0,0 +1,121 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/nic/p2p_nic_cmd_event.h#1 +*/ + +/*! \file p2p_nic_cmd_event.h + * \brief + */ + +#ifndef _P2P_NIC_CMD_EVENT_H +#define _P2P_NIC_CMD_EVENT_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************** + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************** + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************** + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************** + */ + +typedef struct _EVENT_P2P_DEV_DISCOVER_RESULT_T { +/* UINT_8 aucCommunicateAddr[MAC_ADDR_LEN]; // Deprecated. */ + UINT_8 aucDeviceAddr[MAC_ADDR_LEN]; /* Device Address. */ + UINT_8 aucInterfaceAddr[MAC_ADDR_LEN]; /* Device Address. */ + UINT_8 ucDeviceCapabilityBitmap; + UINT_8 ucGroupCapabilityBitmap; + UINT_16 u2ConfigMethod; /* Configure Method. */ + P2P_DEVICE_TYPE_T rPriDevType; + UINT_8 ucSecDevTypeNum; + P2P_DEVICE_TYPE_T arSecDevType[2]; + UINT_16 u2NameLength; + UINT_8 aucName[32]; + PUINT_8 pucIeBuf; + UINT_16 u2IELength; + UINT_8 aucBSSID[MAC_ADDR_LEN]; + /* TODO: Service Information or PasswordID valid? */ +} EVENT_P2P_DEV_DISCOVER_RESULT_T, *P_EVENT_P2P_DEV_DISCOVER_RESULT_T; + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/que_mgt.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/que_mgt.h new file mode 100644 index 0000000000000..7209b3b1cce46 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/que_mgt.h @@ -0,0 +1,973 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/que_mgt.h#2 +*/ + +/*! \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. + */ + + +#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 + ******************************************************************************** + */ +extern UINT_8 g_arTdlsLink[MAXNUM_TDLS_PEER]; +extern const PUINT_8 apucACI2Str[4]; +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************** + */ + +/* Queue Manager Features */ +#define QM_BURST_END_INFO_ENABLED 0 /* 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 */ +#if defined(_HIF_SDIO) +#define QM_ADAPTIVE_TC_RESOURCE_CTRL 1 /* 1: To adaptively adjust resource for each TC */ +#define QM_FAST_TC_RESOURCE_CTRL 1 /* 1: To fast adjust resource for EMPTY TC (assigned resource is 0) */ +#else +#define QM_ADAPTIVE_TC_RESOURCE_CTRL 0 /* 1: To adaptively adjust resource for each TC */ +#define QM_FAST_TC_RESOURCE_CTRL 0 /* 1: To fast adjust resource for EMPTY TC (assigned resource is 0) */ +#endif +#define QM_PRINT_TC_RESOURCE_CTRL 0 /* 1: To print TC resource adjustment results */ +/* 1: If pkt with SSN is missing, auto advance the RX reordering window */ +#define QM_RX_WIN_SSN_AUTO_ADVANCING 1 +/* 1: Indicate the packets falling behind to OS before the frame with SSN is received */ +#define QM_RX_INIT_FALL_BEHIND_PASS 1 +#define QM_TC_RESOURCE_EMPTY_COUNTER 1 /* 1: Count times of TC resource empty happened */ + +/* Parameters */ +#define QM_INIT_TIME_TO_UPDATE_QUE_LEN 256 /* p: Update queue lengths when p TX packets are enqueued */ +#define QM_INIT_TIME_TO_ADJUST_TC_RSC 2 /* 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 0 +#define QM_MIN_RESERVED_TC1_RESOURCE 1 +#define QM_MIN_RESERVED_TC2_RESOURCE 0 +#define QM_MIN_RESERVED_TC3_RESOURCE 0 +#define QM_MIN_RESERVED_TC4_RESOURCE 2 /* Resource for TC4 is not adjustable */ +#define QM_MIN_RESERVED_TC5_RESOURCE 0 + +#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 + +#define QM_EXTRA_RESERVED_RESOURCE_WHEN_BUSY 0 + +#define QM_AVERAGE_TC_RESOURCE 6 + +#define QM_ACTIVE_TC_NUM TC_NUM + +#define QM_MGMT_QUEUED_THRESHOLD 6 +#define QM_CMD_RESERVED_THRESHOLD 4 +#define QM_MGMT_QUEUED_TIMEOUT 1000 /* ms */ + +#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 */ +/* Per-Type Queues: [0] BMCAST */ +#define NUM_OF_PER_STA_TX_QUEUES 4 +#define NUM_OF_PER_TYPE_TX_QUEUES 1 + +/* TX Queue Index */ +/* Per-Type */ +#define TX_QUEUE_INDEX_BMCAST 0 +#define TX_QUEUE_INDEX_NO_STA_REC 0 + +/* Per-STA */ +#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_NON_QOS TX_QUEUE_INDEX_AC1 + +#define QM_DEFAULT_USER_PRIORITY 0 + +#define QM_STA_FORWARD_COUNT_UNLIMITED 0xFFFFFFFF +#define QM_FWD_PKT_QUE_THRESHOLD 128 + +/* 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 (200) + +#if CFG_M0VE_BA_TO_DRIVER +/* MQM internal control bitmap per-bit usage (for operations on g_prMqm->u4FlagBitmap) */ +#define MQM_FLAG_TSPEC_NEGO_ADD_IN_PROGRESS 0 +#define MQM_FLAG_IDLE_TX_BA_TIMER_STARTED 1 +#define MQM_FLAG_IDLE_RX_BA_TIMER_STARTED 2 + +#define MQM_IDLE_RX_BA_DETECTION 0 +#define MQM_IDLE_RX_BA_CHECK_INTERVAL 5000 /* in msec */ +#define MQM_DEL_IDLE_RXBA_THRESHOLD_BK 6 +#define MQM_DEL_IDLE_RXBA_THRESHOLD_BE 12 +#define MQM_DEL_IDLE_RXBA_THRESHOLD_VI 6 +#define MQM_DEL_IDLE_RXBA_THRESHOLD_VO 6 + +/* For indicating whether the role when generating a DELBA message */ +#define DELBA_ROLE_INITIATOR TRUE +#define DELBA_ROLE_RECIPIENT FALSE + +#define MQM_SET_FLAG(_Bitmap, _flag) { (_Bitmap) |= (BIT((_flag))); } +#define MQM_CLEAR_FLAG(_Bitmap, _flag) { (_Bitmap) &= (~BIT((_flag))); } +#define MQM_CHECK_FLAG(_Bitmap, _flag) ((_Bitmap) & (BIT((_flag)))) + +typedef enum _ENUM_BA_RESET_SEL_T { + MAC_ADDR_TID_MATCH = 0, + MAC_ADDR_MATCH, + ALWAYS_MATCH, + MATCH_NUM +} ENUM_BA_RESET_SEL_T; + +#endif + +#define QM_DEQUE_PERCENT_VHT80_NSS1 75 /* BW80 NSS1 rate: MCS9 433 Mbps */ +#define QM_DEQUE_PERCENT_VHT40_NSS1 35 /* BW40 NSS1 Max rate: 200 Mbps */ +#define QM_DEQUE_PERCENT_VHT20_NSS1 15 /* BW20 NSS1 Max rate: 86.7Mbps */ + +#define QM_DEQUE_PERCENT_HT40_NSS1 25 /* BW40 NSS1 Max rate: 150 Mbps (MCS9 200Mbps)*/ +#define QM_DEQUE_PERCENT_HT20_NSS1 12 /* BW20 NSS1 Max rate: 72.2Mbps (MCS8 86.7Mbps)*/ + +/******************************************************************************* + * 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; + + TIMER_T rReorderBubbleTimer; + UINT_16 u2FirstBubbleSn; + BOOLEAN fgHasBubble; + +#if CFG_M0VE_BA_TO_DRIVER + UINT_8 ucStatus; + UINT_8 ucIdleCount; + UINT_16 u2SnapShotSN; +#endif + /* UINT_8 ucTxBufferSize; */ + /* BOOL fgIsAcConstrain; */ + /* BOOL fgIsBaEnabled; */ +#if CFG_SUPPORT_RX_AMSDU + /* RX reorder for one MSDU in AMSDU issue */ + /* P_SW_RFB_T prMpduSwRfb; */ + UINT_32 u4SeqNo; /* for statistic */ + BOOL fgAmsduNeedLastFrame; /* for statistic */ + UINT_8 u8LastAmsduSubIdx; + BOOL fgIsAmsduDuplicated; +#endif + BOOLEAN fgFirstSnToWinStart; +} RX_BA_ENTRY_T, *P_RX_BA_ENTRY_T; + +typedef UINT_32(*PFN_DEQUEUE_FUNCTION) (IN P_ADAPTER_T prAdapter, OUT P_QUE_T prQue, IN UINT_8 ucTC, IN UINT_32 + u4CurrentQuota, IN UINT_32 u4TotalQuota); + +/* 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 resource used count for a STA with respect to a TC index */ + UINT_32 au4ResourceUsedCount[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]; + + /* For TC5 only */ + BOOLEAN fgGlobalQFirst; + UINT_32 u4GlobalResourceUsedCount; +#endif + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + UINT_32 au4AverageQueLen[TC_NUM]; + UINT_32 au4CurrentTcResource[TC_NUM]; + UINT_32 au4MinReservedTcResource[TC_NUM]; /* The minimum amount of resource no matter busy or idle */ + UINT_32 au4GuaranteedTcResource[TC_NUM]; /* The minimum amount of resource when extremely busy */ + + UINT_32 u4TimeToAdjustTcResource; + UINT_32 u4TimeToUpdateQueLen; + + UINT_32 u4QueLenMovingAverage; + UINT_32 u4ExtraReservedTcResource; + UINT_32 u4ResidualTcResource; + + /* 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; + +#if QM_FAST_TC_RESOURCE_CTRL + BOOLEAN fgTcResourceFastReaction; +#endif + +#endif + +#if QM_DEBUG_COUNTER + UINT_32 au4QmDebugCounters[QM_DBG_CNT_NUM]; +#endif + + UINT_32 u4TxAllowedStaCount; + +#if QM_TC_RESOURCE_EMPTY_COUNTER + UINT_32 au4QmTcResourceEmptyCounter[MAX_BSS_INDEX][TC_NUM]; +#endif + + UINT_32 u4MaxForwardBufferCount; + + OS_SYSTIME rLastTxPktDumpTime; + BOOLEAN fgIsTxResrouceControlEn; +} QUE_MGT_T, *P_QUE_MGT_T; + +typedef struct _EVENT_RX_ADDBA_T { + /* 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 { + /* Fields not present in the received ADDBA_REQ */ + UINT_8 ucStaRecIdx; + UINT_8 ucTid; + UINT_8 aucReserved[2]; +} EVENT_RX_DELBA_T, *P_EVENT_RX_DELBA_T; + +typedef struct _EVENT_BSS_ABSENCE_PRESENCE_T { + /* Event Body */ + UINT_8 ucBssIndex; + UINT_8 ucIsAbsent; + 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 Body */ + UINT_8 ucStaRecIdx; + UINT_8 ucIsInPs; + 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 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; + +typedef struct _EVENT_CHECK_REORDER_BUBBLE_T { + /* Event Body */ + UINT_8 ucStaRecIdx; + UINT_8 ucTid; +} EVENT_CHECK_REORDER_BUBBLE_T, *P_EVENT_CHECK_REORDER_BUBBLE_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; + +typedef struct _WMM_AC_PARAM_T { + UINT_8 ucAciAifsn; + UINT_8 ucEcw; + UINT_16 u2TxopLimit; +} WMM_AC_PARAM_T, *P_WMM_AC_PARAM_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 */ +#if 1 + WMM_AC_PARAM_T arAcParam[4]; +#else + 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]; +#endif +} 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. */ + UINT_8 ucIsACMSet; +} AC_QUE_PARMS_T, *P_AC_QUE_PARMS_T; + +/* WMM ACI (AC index) */ +typedef enum _ENUM_WMM_ACI_T { + WMM_AC_BE_INDEX = 0, + WMM_AC_BK_INDEX, + WMM_AC_VI_INDEX, + WMM_AC_VO_INDEX, + WMM_AC_INDEX_NUM +} ENUM_WMM_ACI_T, *P_ENUM_WMM_ACI_T; + +/* Used for CMD Queue Operation */ +typedef enum _ENUM_FRAME_ACTION_T { + FRAME_ACTION_DROP_PKT = 0, + FRAME_ACTION_QUEUE_PKT, + FRAME_ACTION_TX_PKT, + FRAME_ACTION_NUM +} ENUM_FRAME_ACTION_T; + +typedef enum _ENUM_FRAME_TYPE_IN_CMD_Q_T { + FRAME_TYPE_802_1X = 0, + FRAME_TYPE_MMPDU, + FRAME_TYPE_NUM +} ENUM_FRAME_TYPE_IN_CMD_Q_T; + +typedef enum _ENUM_FREE_QUOTA_MODET_T { + FREE_QUOTA_UPDATE_MODE_INIT = 0, + FREE_QUOTA_UPDATE_MODE_OVERWRITE, + FREE_QUOTA_UPDATE_MODE_INCREASE, + FREE_QUOTA_UPDATE_MODE_DECREASE +} ENUM_FREE_QUOTA_MODET_T, *P_ENUM_FREE_QUOTA_MODET_T; + +typedef struct _CMD_UPDATE_WMM_PARMS_T { + AC_QUE_PARMS_T arACQueParms[AC_NUM]; + UINT_8 ucBssIndex; + UINT_8 fgIsQBSS; + UINT_8 ucWmmSet; + UINT_8 aucReserved; +} 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; + +#if CFG_M0VE_BA_TO_DRIVER +/* The status of an TX/RX BA entry in FW (NEGO means the negotiation process is in progress) */ +typedef enum _ENUM_BA_ENTRY_STATUS_T { + BA_ENTRY_STATUS_INVALID = 0, + BA_ENTRY_STATUS_NEGO, + BA_ENTRY_STATUS_ACTIVE, + BA_ENTRY_STATUS_DELETING +} ENUM_BA_ENTRY_STATUS_T, *P_ENUM_BA_ENTRY_STATUS_T; +#endif + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************** + */ + +#define 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) + +#if 0 +#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); \ + } +#else +#define QM_TX_SET_MSDU_INFO_FOR_DATA_PACKET( \ + _prMsduInfo, \ + _ucTC, \ + _ucPacketType, \ + _ucFormatID, \ + _fgIs802_1x, \ + _fgIs802_11, \ + _ucPsForwardingType \ + ) \ + { \ + ASSERT(_prMsduInfo); \ + (_prMsduInfo)->ucTC = (_ucTC); \ + (_prMsduInfo)->ucPacketType = (_ucPacketType); \ + (_prMsduInfo)->ucFormatID = (_ucFormatID); \ + (_prMsduInfo)->fgIs802_1x = (_fgIs802_1x); \ + (_prMsduInfo)->fgIs802_11 = (_fgIs802_11); \ + (_prMsduInfo)->ucPsForwardingType = (_ucPsForwardingType); \ + } +#endif + +#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)] >> (_prAdapter)->rQM.u4QueLenMovingAverage)) +#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, IN BOOLEAN isTxResrouceControlEn); + +#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 P_STA_RECORD_T prStaRec); + +VOID qmUpdateStaRec(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +/*----------------------------------------------------------------------------*/ +/* 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); + +#if CFG_SUPPORT_MULTITHREAD +P_MSDU_INFO_T qmDequeueTxPacketsMthread(IN P_ADAPTER_T prAdapter, IN P_TX_TCQ_STATUS_T prTcqStatus); + +BOOLEAN +qmAdjustTcQuotasMthread(IN P_ADAPTER_T prAdapter, OUT P_TX_TCQ_ADJUST_T prTcqAdjust, IN P_TX_TCQ_STATUS_T prTcqStatus); +#endif + +BOOLEAN 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); + +VOID qmDoAdaptiveTcResourceCtrl(IN P_ADAPTER_T prAdapter); + +VOID qmCheckForFastTcResourceCtrl(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTc); + +#endif + +VOID qmDetermineStaRecIndex(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +UINT_32 +qmDequeueTxPacketsFromPerStaQueues(IN P_ADAPTER_T prAdapter, OUT P_QUE_T prQue, IN UINT_8 ucTC, IN UINT_32 + u4CurrentQuota, IN UINT_32 u4TotalQuota); + +VOID +qmDequeueTxPacketsFromPerTypeQueues(IN P_ADAPTER_T prAdapter, OUT P_QUE_T prQue, IN UINT_8 ucTC, IN UINT_32 + u4CurrentQuota, IN UINT_32 u4TotalQuota); + +UINT_32 +qmDequeueTxPacketsFromGlobalQueue(IN P_ADAPTER_T prAdapter, OUT P_QUE_T prQue, IN UINT_8 ucTC, IN UINT_32 + u4CurrentQuota, IN UINT_32 u4TotalQuota); + +VOID qmSetStaRecTxAllowed(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN BOOLEAN fgIsTxAllowed); + +UINT_32 gmGetDequeueQuota( + IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN P_BSS_INFO_T prBssInfo, + IN UINT_32 u4TotalQuota + ); + +/*----------------------------------------------------------------------------*/ +/* RX-Related Queue Management */ +/*----------------------------------------------------------------------------*/ + +VOID qmInitRxQueues(IN P_ADAPTER_T prAdapter); + +P_SW_RFB_T qmFlushRxQueues(IN P_ADAPTER_T prAdapter); + +P_QUE_T qmDetermineStaTxQueue(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, OUT PUINT_8 pucTC); + +VOID qmSetTxPacketDescTemplate(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +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 qmInsertReorderPkt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, + IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue); + +VOID qmInsertFallWithinReorderPkt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, + IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue); + +VOID qmInsertFallAheadReorderPkt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, + IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue); + +VOID qmPopOutReorderPkt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT P_QUE_T prReturnedQue, + IN ENUM_RX_STATISTIC_COUNTER_T eRxCounter); + +VOID qmPopOutDueToFallWithin(IN P_ADAPTER_T prAdapter, IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue); + +VOID qmPopOutDueToFallAhead(IN P_ADAPTER_T prAdapter, IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue); + +VOID qmHandleReorderBubbleTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); + +VOID qmHandleEventCheckReorderBubble(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); + +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 mqmProcessBcn(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength); + +BOOLEAN +mqmParseEdcaParameters(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength, IN + BOOLEAN fgForceOverride); + +BOOLEAN mqmCompareEdcaParameters(IN P_IE_WMM_PARAM_T prIeWmmParam, IN P_BSS_INFO_T prBssInfo); + +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); + +UINT_32 +mqmFillWmmInfoIE(P_UINT_8 pucOutBuf, BOOLEAN fgSupportUAPSD, UINT_8 ucBmpDeliveryAC, UINT_8 ucBmpTriggerAC, UINT_8 + ucUapsdSp); + +UINT_32 +mqmGenerateWmmInfoIEByStaRec(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_STA_RECORD_T prStaRec, P_UINT_8 + pucOutBuf); + +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); + +#if CFG_SUPPORT_TDLS + +UINT_32 mqmGenerateWmmParamIEByParam(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, PUINT_8 pOutBuf); +#endif + +ENUM_FRAME_ACTION_T qmGetFrameAction(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucBssIndex, IN UINT_8 ucStaRecIdx, IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_FRAME_TYPE_IN_CMD_Q_T eFrameType, IN UINT_16 u2FrameLength); + +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 qmFreeAllByBssIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex); + +UINT_32 qmGetRxReorderQueuedBufferCount(IN P_ADAPTER_T prAdapter); + +UINT_32 qmDumpQueueStatus(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuf, IN UINT_32 u4MaxLen); + +#if CFG_M0VE_BA_TO_DRIVER +VOID +mqmSendDelBaFrame(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsInitiator, IN P_STA_RECORD_T prStaRec, IN UINT_32 u4Tid, IN + UINT_32 u4ReasonCode); + +WLAN_STATUS +mqmCallbackAddBaRspSent(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +VOID mqmTimeoutCheckIdleRxBa(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); + +VOID +mqmRxModifyBaEntryStatus(IN P_ADAPTER_T prAdapter, IN P_RX_BA_ENTRY_T prRxBaEntry, IN ENUM_BA_ENTRY_STATUS_T eStatus); + +VOID mqmHandleAddBaReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID mqmHandleBaActionFrame(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); +#endif + +VOID qmResetTcControlResource(IN P_ADAPTER_T prAdapter); + +#if CFG_SUPPORT_REPLAY_DETECTION +BOOLEAN qmHandleRxReplay(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); +BOOLEAN qmRxDetectReplay(PUINT_8 pucPNS, PUINT_8 pucPNT); +#endif + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************** + */ + +#if QM_TEST_MODE +extern QUE_MGT_T g_rQM; +#endif +extern const UINT_8 aucTid2ACI[TX_DESC_TID_NUM]; +extern const UINT_8 arNetwork2TcResource[HW_BSSID_NUM + 1][NET_TC_NUM]; + +#endif /* _QUE_MGT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/wlan_def.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/wlan_def.h new file mode 100644 index 0000000000000..15189b440c6de --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic/wlan_def.h @@ -0,0 +1,1099 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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 + * + */ + + +#ifndef _WLAN_DEF_H +#define _WLAN_DEF_H + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************** + */ +/* disconnect reason */ +#define DISCONNECT_REASON_CODE_RESERVED 0 +#define DISCONNECT_REASON_CODE_RADIO_LOST 1 +#define DISCONNECT_REASON_CODE_DEAUTHENTICATED 2 +#define DISCONNECT_REASON_CODE_DISASSOCIATED 3 +#define DISCONNECT_REASON_CODE_NEW_CONNECTION 4 +#define DISCONNECT_REASON_CODE_REASSOCIATION 5 + +/* disconnect trigger */ +#define DISCONNECT_TRIGGER_RESERVED 0 +#define DISCONNECT_TRIGGER_ACTIVE 1 +#define DISCONNECT_TRIGGER_PASSIVE 2 + +/* 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 TX_MODE_VHT 0x100 + +#define RATE_CCK_SHORT_PREAMBLE 0x4 + +#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_MCS8 0x8 +#define PHY_RATE_MCS9 0x9 +#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 | PHY_RATE_6M) +#define RATE_OFDM_9M (TX_MODE_OFDM | PHY_RATE_9M) +#define RATE_OFDM_12M (TX_MODE_OFDM | PHY_RATE_12M) +#define RATE_OFDM_18M (TX_MODE_OFDM | PHY_RATE_18M) +#define RATE_OFDM_24M (TX_MODE_OFDM | PHY_RATE_24M) +#define RATE_OFDM_36M (TX_MODE_OFDM | PHY_RATE_36M) +#define RATE_OFDM_48M (TX_MODE_OFDM | PHY_RATE_48M) +#define RATE_OFDM_54M (TX_MODE_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_VHT_MCS_0 (TX_MODE_VHT | PHY_RATE_MCS0) +#define RATE_VHT_MCS_1 (TX_MODE_VHT | PHY_RATE_MCS1) +#define RATE_VHT_MCS_2 (TX_MODE_VHT | PHY_RATE_MCS2) +#define RATE_VHT_MCS_3 (TX_MODE_VHT | PHY_RATE_MCS3) +#define RATE_VHT_MCS_4 (TX_MODE_VHT | PHY_RATE_MCS4) +#define RATE_VHT_MCS_5 (TX_MODE_VHT | PHY_RATE_MCS5) +#define RATE_VHT_MCS_6 (TX_MODE_VHT | PHY_RATE_MCS6) +#define RATE_VHT_MCS_7 (TX_MODE_VHT | PHY_RATE_MCS7) +#define RATE_VHT_MCS_8 (TX_MODE_VHT | PHY_RATE_MCS8) +#define RATE_VHT_MCS_9 (TX_MODE_VHT | PHY_RATE_MCS9) + +#define RATE_NSTS_MASK BITS(9, 10) +#define RATE_NSTS_OFFSET 9 +#define RATE_TX_MODE_MASK BITS(6, 8) +#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(2) +#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 27 + +/* 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) */ +#define PHY_TYPE_BIT_VHT BIT(PHY_TYPE_VHT_INDEX) /* HT PHY (clause 22) */ + +/* 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) + +#define PHY_TYPE_SET_802_11AC (PHY_TYPE_BIT_VHT) + +#define PHY_TYPE_SET_802_11ANAC (PHY_TYPE_BIT_OFDM | \ + PHY_TYPE_BIT_HT | \ + PHY_TYPE_BIT_VHT) + +#define PHY_TYPE_SET_802_11ABGNAC (PHY_TYPE_BIT_OFDM | \ + PHY_TYPE_BIT_HR_DSSS | \ + PHY_TYPE_BIT_ERP | \ + PHY_TYPE_BIT_HT | \ + PHY_TYPE_BIT_VHT) + +/* Rate set bit definitions */ +#define RATE_SET_BIT_1M BIT(RATE_1M_SW_INDEX) /* Bit 0: 1M */ +#define RATE_SET_BIT_2M BIT(RATE_2M_SW_INDEX) /* Bit 1: 2M */ +#define RATE_SET_BIT_5_5M BIT(RATE_5_5M_SW_INDEX) /* Bit 2: 5.5M */ +#define RATE_SET_BIT_11M BIT(RATE_11M_SW_INDEX) /* Bit 3: 11M */ +#define RATE_SET_BIT_22M BIT(RATE_22M_SW_INDEX) /* Bit 4: 22M */ +#define RATE_SET_BIT_33M BIT(RATE_33M_SW_INDEX) /* Bit 5: 33M */ +#define RATE_SET_BIT_6M BIT(RATE_6M_SW_INDEX) /* Bit 6: 6M */ +#define RATE_SET_BIT_9M BIT(RATE_9M_SW_INDEX) /* Bit 7: 9M */ +#define RATE_SET_BIT_12M BIT(RATE_12M_SW_INDEX) /* Bit 8: 12M */ +#define RATE_SET_BIT_18M BIT(RATE_18M_SW_INDEX) /* Bit 9: 18M */ +#define RATE_SET_BIT_24M BIT(RATE_24M_SW_INDEX) /* Bit 10: 24M */ +#define RATE_SET_BIT_36M BIT(RATE_36M_SW_INDEX) /* Bit 11: 36M */ +#define RATE_SET_BIT_48M BIT(RATE_48M_SW_INDEX) /* Bit 12: 48M */ +#define RATE_SET_BIT_54M BIT(RATE_54M_SW_INDEX) /* Bit 13: 54M */ +#define RATE_SET_BIT_HT_PHY BIT(RATE_HT_PHY_SW_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 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) +#if CFG_SUPPORT_CFG80211_AUTH +#define AUTH_TYPE_SAE BIT(AUTH_ALGORITHM_NUM_SAE) +#endif + +/* Authentication Retry Limit */ +#define TX_AUTH_ASSOCI_RETRY_LIMIT 2 +#define TX_AUTH_ASSOCI_RETRY_LIMIT_FOR_ROAMING 1 + +/* WMM-2.2.1 WMM Information Element */ +#define ELEM_MAX_LEN_WMM_INFO 7 + +/* PF TCP/UDP max port number */ +#define MAX_TCP_UDP_PORT 20 + +/******************************************************************************* + * 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_2, + BSSID_3, + 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; + +typedef enum _ENUM_NETWORK_TYPE_T { + NETWORK_TYPE_AIS, + NETWORK_TYPE_P2P, + NETWORK_TYPE_BOW, + NETWORK_TYPE_MBSS, + NETWORK_TYPE_NUM +} ENUM_NETWORK_TYPE_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, + STA_ROLE_MAX_INDEX +} ENUM_STA_ROLE_INDEX_T; + +#define STA_ROLE_INDEX_NUM (STA_ROLE_MAX_INDEX - STA_ROLE_BASE_INDEX) + +/* 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_VHT_INDEX, /* HT PHY (clause 22) */ + PHY_TYPE_INDEX_NUM /* 6 */ +} ENUM_PHY_TYPE_INDEX_T, *P_ENUM_PHY_TYPE_INDEX_T; + +typedef enum _ENUM_SW_RATE_INDEX_T { + RATE_1M_SW_INDEX = 0, /* 1M */ + RATE_2M_SW_INDEX, /* 2M */ + RATE_5_5M_SW_INDEX, /* 5.5M */ + RATE_11M_SW_INDEX, /* 11M */ + RATE_22M_SW_INDEX, /* 22M */ + RATE_33M_SW_INDEX, /* 33M */ + RATE_6M_SW_INDEX, /* 6M */ + RATE_9M_SW_INDEX, /* 9M */ + RATE_12M_SW_INDEX, /* 12M */ + RATE_18M_SW_INDEX, /* 18M */ + RATE_24M_SW_INDEX, /* 24M */ + RATE_36M_SW_INDEX, /* 36M */ + RATE_48M_SW_INDEX, /* 48M */ + RATE_54M_SW_INDEX, /* 54M */ + RATE_HT_PHY_SW_INDEX, /* BSS Selector - HT PHY */ + RATE_NUM_SW /* 15 */ +} ENUM_SW_RATE_INDEX_T, *P_ENUM_SW_RATE_INDEX_T; + +typedef enum _ENUM_CCK_RATE_INDEX_T { + RATE_1M_INDEX = 0, /* 1M */ + RATE_2M_INDEX, /* 2M */ + RATE_5_5M_INDEX, /* 5.5M */ + RATE_11M_INDEX, /* 11M */ + CCK_RATE_NUM /* 4 */ +} ENUM_CCK_RATE_INDEX_T, *P_ENUM_CCK_RATE_INDEX_T; + +typedef enum _ENUM_OFDM_RATE_INDEX_T { + RATE_6M_INDEX = 0, /* 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 */ + OFDM_RATE_NUM /* 8 */ +} ENUM_OFDM_RATE_INDEX_T, *P_ENUM_OFDM_RATE_INDEX_T; + +typedef enum _ENUM_HT_RATE_INDEX_T { + HT_RATE_MCS32_INDEX = 0, + HT_RATE_MCS0_INDEX, + 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_MCS8_INDEX, + HT_RATE_MCS9_INDEX, + HT_RATE_MCS10_INDEX, + HT_RATE_MCS11_INDEX, + HT_RATE_MCS12_INDEX, + HT_RATE_MCS13_INDEX, + HT_RATE_MCS14_INDEX, + HT_RATE_MCS15_INDEX, + HT_RATE_NUM /* 16 */ +} ENUM_HT_RATE_INDEX_T, *P_ENUM_HT_RATE_INDEX_T; + +typedef enum _ENUM_VHT_RATE_INDEX_T { + VHT_RATE_MCS0_INDEX = 0, + VHT_RATE_MCS1_INDEX, + VHT_RATE_MCS2_INDEX, + VHT_RATE_MCS3_INDEX, + VHT_RATE_MCS4_INDEX, + VHT_RATE_MCS5_INDEX, + VHT_RATE_MCS6_INDEX, + VHT_RATE_MCS7_INDEX, + VHT_RATE_MCS8_INDEX, + VHT_RATE_MCS9_INDEX, + VHT_RATE_NUM /* 10 */ +} ENUM_VHT_RATE_INDEX_T, *P_ENUM_VHT_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_OFDM_MODE, + PREAMBLE_HT_MIXED_MODE, + PREAMBLE_HT_GREEN_FIELD, + PREAMBLE_VHT_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_MCS6, + MODULATION_TYPE_54M_MCS7, + MODULATION_TYPE_MCS32, + MODULATION_TYPE_NUM +} ENUM_MODULATION_TYPE_T, *P_ENUM_MODULATION_TYPE_T; + +enum ENUM_VHT_SYSTEM { + VHT_SYSTEM_VHT20 = 0, + VHT_SYSTEM_VHT40, + VHT_SYSTEM_VHT80, + VHT_SYSTEM_VHT160C, + VHT_SYSTEM_VHT160NC, + VHT_SYSTEM_LG_VHT40, + VHT_SYSTEM_LG_VHT80, + VHT_SYSTEM_LG_VHT160, + VHT_SYSTEM_NUM +}; + +enum ENUM_VHT_MODULATION_TYPE { + MODULATION_TYPE_VHT_BPSK = 0, + MODULATION_TYPE_VHT_QPSK, + MODULATION_TYPE_VHT_16QAM, + MODULATION_TYPE_VHT_64QAM_MSC5_6, + MODULATION_TYPE_VHT_64QAM_MSC7, + MODULATION_TYPE_VHT_64QAM_MSC8, + MODULATION_TYPE_VHT_64QAM_MSC9, + MODULATION_TYPE_VHT_NUM +}; + +enum PWR_DSSS_CAT { + PWR_DSSS_CCK, + PWR_DSSS_BPKS, + PWR_DSSS_NUM +}; + +enum PWR_OFDM_CAT { + PWR_OFDM_BPSK, /* 6M, 9M */ + PWR_OFDM_QPSK, /* 12M, 18M */ + PWR_OFDM_16QAM, /* 24M, 36M */ + PWR_OFDM_48Mbps, /* 48M */ + PWR_OFDM_54Mbps, /* 54M */ + PWR_OFDM_NUM +}; + +enum PWR_HT20_CAT { + PWR_HT_BPSK, /* MCS0*/ + PWR_HT_QPSK, /* MCS1, MCS2 */ + PWR_HT_16QAM, /* MCS3, MCS4 */ + PWR_HT_MCS5, /* MCS5 */ + PWR_HT_MCS6, /* MCS6 */ + PWR_HT_MCS7, /* MCS7 */ + PWR_HT_MCS32, /* MCS32 */ + PWR_HT_NUM +}; + +enum PWR_VHT20_CAT { + PWR_VHT20_BPSK, + PWR_VHT20_QPSK, + PWR_VHT20_16QAM, + PWR_VHT20_64QAM, + PWR_VHT20_MCS7, + PWR_VHT20_MCS8, + PWR_VHT20_MCS9, + PWR_VHT20_NUM +}; + +enum PWR_VHT_OFST_CAT { + PWR_Vht40_OFFSET = VHT_SYSTEM_VHT40, /*to sync to ENUM_VHT_SYSTEM_T*/ + PWR_Vht80_OFFSET, + PWR_Vht160c_OFFSET, + PWR_Vht160nc_OFFSET, + PWR_LgVht40_OFFSET, + PWR_LgVht80_OFFSET, + PWR_VHT_OFST_NUM +}; + +struct POWER_LIMIT { + UINT_8 ucCentralCh; + UINT_8 tx_pwr_dsss[PWR_DSSS_NUM]; /*unit: 0.5 dbm*/ + UINT_8 tx_pwr_ofdm[PWR_OFDM_NUM]; /*unit: 0.5 dbm*/ + UINT_8 tx_pwr_ht20[PWR_HT_NUM]; /*unit: 0.5 dbm*/ + UINT_8 tx_pwr_ht40[PWR_HT_NUM]; /*unit: 0.5 dbm*/ + UINT_8 tx_pwr_vht20[PWR_VHT20_NUM]; /*unit: 0.5 dbm*/ + UINT_8 tx_pwr_vht_OFST[PWR_VHT_OFST_NUM]; /*unit: 0.5 dbm*/ +}; + +enum ENUM_TXPWR_TBL_IDX { + LIMIT_TBL, + EEPROM_TBL, + MAC_TBL, + TXPWR_TBL_NUM +}; + +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; + +typedef enum _ENUM_CHANNEL_WIDTH_T { + CW_20_40MHZ = 0, + CW_80MHZ = 1, + CW_160MHZ = 2, + CW_80P80MHZ = 3 +} ENUM_CHANNEL_WIDTH_T, *P_ENUM_CHANNEL_WIDTH_P; + +/* 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; + +typedef enum _ENUM_DBDC_BN_T { + ENUM_BAND_0, + ENUM_BAND_1, + ENUM_BAND_NUM, + ENUM_BAND_ALL, + ENUM_BAND_AUTO /*Auto select by A/G band, Driver only*/ +} ENUM_DBDC_BN_T, *P_ENUM_DBDC_BN_T; + +/* Provide supported channel list to other components in array format */ +typedef struct _RF_CHANNEL_INFO_T { + ENUM_BAND_T eBand; + UINT_32 u4CenterFreq1; /* To record Channel Center Frequency Segment 0 (MHz) from CFG80211 */ + UINT_32 u4CenterFreq2; /* To record Channel Center Frequency Segment 1 (MHz) from CFG80211 */ + UINT_16 u2PriChnlFreq; /* To record primary channel frequency (MHz) from CFG80211 */ + UINT_8 ucChnlBw; /* To record channel bandwidth from CFG80211 */ + UINT_8 ucChannelNum; +} RF_CHANNEL_INFO_T, *P_RF_CHANNEL_INFO_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 enum _ENUM_AR_SS_T { + AR_SS_NULL = 0, + AR_SS_1, + AR_SS_2, + AR_SS_3, + AR_SS_4, + AR_SS_NUM +} ENUM_AR_SS_T, P_ENUM_AR_SS_T; + +typedef enum _ENUM_MAC_BANDWIDTH_T { + MAC_BW_20 = 0, + MAC_BW_40, + MAC_BW_80, + MAC_BW_160 +} ENUM_MAC_BANDWIDTH_T, *P_ENUM_MAC_BANDWIDTH_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, UINT_8, 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_802_11AC, + PHY_CONFIG_802_11ANAC, + PHY_CONFIG_802_11ABGNAC, + PHY_CONFIG_NUM /* 12 */ +} 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 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)->ucBssIndex == prAdapter->prAisBssInfo->ucBssIndex) +#define IS_STA_IN_P2P(_prStaRec) (prAdapter->aprBssInfo[(_prStaRec)->ucBssIndex]->eNetworkType == \ + NETWORK_TYPE_P2P) +#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; + +typedef enum _ENUM_ANTENNA_NUM { + ANTENNA_WF0 = 0, + ANTENNA_WF1 = 1, + MAX_ANTENNA_NUM +} ENUM_ANTENNA_NUM, *P_ENUM_ANTENNA_NUM; + +#if CFG_SUPPORT_CSI +enum ENUM_CSI_MODULATION_BW_TYPE_T { + CSI_TYPE_CCK_BW20, + CSI_TYPE_OFDM_BW20, + CSI_TYPE_OFDM_BW40, + CSI_TYPE_OFDM_BW80 +}; +#endif + + + +/*----------------------------------------------------------------------------*/ +/* RSN structures */ +/*----------------------------------------------------------------------------*/ +/* #if defined(WINDOWS_DDK) || defined(WINDOWS_CE) */ +/* #pragma pack(1) */ +/* #endif */ +#if CFG_SUPPORT_CFG80211_AUTH +/* max number of supported cipher suites */ +#define MAX_NUM_SUPPORTED_CIPHER_SUITES 10 +#if CFG_SUPPORT_802_11W +/* max number of supported AKM suites */ +#define MAX_NUM_SUPPORTED_AKM_SUITES 15 +#else +/* max number of supported AKM suites */ +#define MAX_NUM_SUPPORTED_AKM_SUITES 13 +#endif +#else +#define MAX_NUM_SUPPORTED_CIPHER_SUITES 8 +#if CFG_SUPPORT_802_11W +/* max number of supported AKM suites */ +#define MAX_NUM_SUPPORTED_AKM_SUITES 8 +#else +/* max number of supported AKM suites */ +#define MAX_NUM_SUPPORTED_AKM_SUITES 6 +#endif +#endif +/* max number of supported PMKID */ +#define MAX_NUM_SUPPORTED_PMKID 10 + +/* Structure of RSN Information */ +typedef struct _RSN_INFO_T { + UINT_8 ucElemId; + UINT_8 ucRsneLen; + 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; + UINT_16 u2PmkidCnt; + BOOLEAN aucPmkidList[MAX_NUM_SUPPORTED_PMKID * RSN_PMKID_LEN]; + UINT_32 u4GroupMgmtKeyCipherSuite; +} /*__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 + +#if CFG_SUPPORT_OWE +/* Structure of OWE Information */ +struct OWE_INFO_T { + UINT_8 ucElemId; + UINT_8 ucLength; + UINT_8 ucElemIdExt; + UINT_16 u2Group; + UINT_8 aucPublicKey[100]; +}; +#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 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_BE32(_memAddr_p, _value_p) \ + { \ + PUINT_8 __cp = (PUINT_8)(_memAddr_p); \ + *(PUINT_32)(_value_p) = ((UINT_32)__cp[0] << 24) | \ + ((UINT_32)__cp[1] << 16) | ((UINT_32)__cp[2] << 8) | \ + ((UINT_32)__cp[3]); \ + } + +#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); \ + } + +#define WLAN_SET_FIELD_BE24(_memAddr_p, _value) \ + { \ + PUINT_8 __cp = (PUINT_8)(_memAddr_p); \ + __cp[0] = (UINT_8)((_value) >> 16); \ + __cp[1] = (UINT_8)((_value) >> 8); \ + __cp[2] = (UINT_8)(_value); \ + } + +#define WLAN_SET_FIELD_BE32(_memAddr_p, _value) \ + { \ + PUINT_8 __cp = (PUINT_8)(_memAddr_p); \ + __cp[0] = (UINT_8)((_value) >> 24); \ + __cp[1] = (UINT_8)((_value) >> 16); \ + __cp[2] = (UINT_8)((_value) >> 8); \ + __cp[3] = (UINT_8)(_value); \ + } + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************** + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************** + */ + +#endif /* _WLAN_DEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic_cmd_event.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic_cmd_event.h new file mode 100644 index 0000000000000..0183689b2358d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic_cmd_event.h @@ -0,0 +1,3427 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + +#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_PQ_ID (0x8000) +#define CMD_PACKET_TYPE_ID (0xA0) + +#define PKT_FT_CMD 0x2 + +#define CMD_STATUS_SUCCESS 0 +#define CMD_STATUS_REJECTED 1 +#define CMD_STATUS_UNKNOWN 2 + +#define EVENT_HDR_WITHOUT_RXD_SIZE (OFFSET_OF(WIFI_EVENT_T, aucBuffer[0]) - OFFSET_OF(WIFI_EVENT_T, u2PacketLength)) + +#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 + +/*CMD_POWER_OFFSET_T , follow 5G sub-band*/ +/* #define MAX_SUBBAND_NUM 8 */ +/* */ +/* */ +/* */ +/* */ +#define S2D_INDEX_CMD_H2N 0x0 +#define S2D_INDEX_CMD_C2N 0x1 +#define S2D_INDEX_CMD_H2C 0x2 +#define S2D_INDEX_CMD_H2N_H2C 0x3 + +#define S2D_INDEX_EVENT_N2H 0x0 +#define S2D_INDEX_EVENT_N2C 0x1 +#define S2D_INDEX_EVENT_C2H 0x2 +#define S2D_INDEX_EVENT_N2H_N2C 0x3 + +#define RDD_EVENT_HDR_SIZE 20 +#define RDD_ONEPLUSE_SIZE 8 /* size of one pulse is 8 bytes */ +#define RDD_PULSE_OFFSET0 0 +#define RDD_PULSE_OFFSET1 1 +#define RDD_PULSE_OFFSET2 2 +#define RDD_PULSE_OFFSET3 3 +#define RDD_PULSE_OFFSET4 4 +#define RDD_PULSE_OFFSET5 5 +#define RDD_PULSE_OFFSET6 6 +#define RDD_PULSE_OFFSET7 7 + +#if (CFG_SUPPORT_DFS_MASTER == 1) +#define RDD_IN_SEL_0 0 +#define RDD_IN_SEL_1 1 +#endif + +#if CFG_SUPPORT_QA_TOOL +#define IQ_FILE_LINE_OFFSET 18 +#define IQ_FILE_IQ_STR_LEN 8 +#define RTN_IQ_DATA_LEN 1024 /* return 1k per packet */ + +#define MCAST_WCID_TO_REMOVE 0 + +/* Network type */ +#define NETWORK_INFRA BIT(16) +#define NETWORK_P2P BIT(17) +#define NETWORK_IBSS BIT(18) +#define NETWORK_MESH BIT(19) +#define NETWORK_BOW BIT(20) +#define NETWORK_WDS BIT(21) + +/* Station role */ +#define STA_TYPE_STA BIT(0) +#define STA_TYPE_AP BIT(1) +#define STA_TYPE_ADHOC BIT(2) +#define STA_TYPE_TDLS BIT(3) +#define STA_TYPE_WDS BIT(4) + +/* Connection type */ +#define CONNECTION_INFRA_STA (STA_TYPE_STA|NETWORK_INFRA) +#define CONNECTION_INFRA_AP (STA_TYPE_AP|NETWORK_INFRA) +#define CONNECTION_P2P_GC (STA_TYPE_STA|NETWORK_P2P) +#define CONNECTION_P2P_GO (STA_TYPE_AP|NETWORK_P2P) +#define CONNECTION_MESH_STA (STA_TYPE_STA|NETWORK_MESH) +#define CONNECTION_MESH_AP (STA_TYPE_AP|NETWORK_MESH) +#define CONNECTION_IBSS_ADHOC (STA_TYPE_ADHOC|NETWORK_IBSS) +#define CONNECTION_TDLS (STA_TYPE_STA|NETWORK_INFRA|STA_TYPE_TDLS) +#define CONNECTION_WDS (STA_TYPE_WDS|NETWORK_WDS) + +#define ICAP_CONTENT_ADC 0x10000006 +#define ICAP_CONTENT_TOAE 0x7 +#define ICAP_CONTENT_SPECTRUM 0xB +#define ICAP_CONTENT_RBIST 0x10 +#define ICAP_CONTENT_DCOC 0x20 +#define ICAP_CONTENT_FIIQ 0x48 +#define ICAP_CONTENT_FDIQ 0x49 + +#if CFG_SUPPORT_BUFFER_MODE + +typedef struct _CMD_EFUSE_BUFFER_MODE_T { + UINT_8 ucSourceMode; + UINT_8 ucCount; + UINT_8 ucCmdType; /* 0:6632, 1: 7668 */ + UINT_8 ucReserved; + UINT_8 aBinContent[MAX_EEPROM_BUFFER_SIZE]; +} CMD_EFUSE_BUFFER_MODE_T, *P_CMD_EFUSE_BUFFER_MODE_T; + + +/*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ +typedef struct _CMD_ACCESS_EFUSE_T { + UINT_32 u4Address; + UINT_32 u4Valid; + UINT_8 aucData[16]; +} CMD_ACCESS_EFUSE_T, *P_CMD_ACCESS_EFUSE_T; + +typedef struct _CMD_EFUSE_FREE_BLOCK_T { + UINT_8 ucGetFreeBlock; + UINT_8 aucReserved[3]; +} CMD_EFUSE_FREE_BLOCK_T, *P_CMD_EFUSE_FREE_BLOCK_T; + + +typedef struct _CMD_GET_TX_POWER_T { + UINT_8 ucTxPwrType; + UINT_8 ucCenterChannel; + UINT_8 ucDbdcIdx; /* 0:Band 0, 1: Band1 */ + UINT_8 ucBand; /* 0:G-band 1: A-band*/ + UINT_8 ucReserved[4]; +} CMD_GET_TX_POWER_T, *P_CMD_GET_TX_POWER_T; + +/*#endif*/ + +#endif /* CFG_SUPPORT_BUFFER_MODE */ + + +typedef struct _CMD_SET_TX_TARGET_POWER_T { + INT_8 cTxPwr2G4Cck; /* signed, in unit of 0.5dBm */ + INT_8 cTxPwr2G4Dsss; /* signed, in unit of 0.5dBm */ + UINT_8 ucTxTargetPwr; /* Tx target power base for all*/ + UINT_8 ucReserved; + + 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_SET_TX_TARGET_POWER_T, *P_CMD_SET_TX_TARGET_POWER_T; + + +/* +* Definitions for extension CMD_ID +*/ +typedef enum _ENUM_EXT_CMD_ID_T { + EXT_CMD_ID_EFUSE_ACCESS = 0x01, + EXT_CMD_ID_RF_REG_ACCESS = 0x02, + EXT_CMD_ID_EEPROM_ACCESS = 0x03, + EXT_CMD_ID_RF_TEST = 0x04, + EXT_CMD_ID_RADIO_ON_OFF_CTRL = 0x05, + EXT_CMD_ID_WIFI_RX_DISABLE = 0x06, + EXT_CMD_ID_PM_STATE_CTRL = 0x07, + EXT_CMD_ID_CHANNEL_SWITCH = 0x08, + EXT_CMD_ID_NIC_CAPABILITY = 0x09, + EXT_CMD_ID_AP_PWR_SAVING_CLEAR = 0x0A, + EXT_CMD_ID_SET_WTBL2_RATETABLE = 0x0B, + EXT_CMD_ID_GET_WTBL_INFORMATION = 0x0C, + EXT_CMD_ID_ASIC_INIT_UNINIT_CTRL = 0x0D, + EXT_CMD_ID_MULTIPLE_REG_ACCESS = 0x0E, + EXT_CMD_ID_AP_PWR_SAVING_CAPABILITY = 0x0F, + EXT_CMD_ID_SECURITY_ADDREMOVE_KEY = 0x10, + EXT_CMD_ID_SET_TX_POWER_CONTROL = 0x11, + EXT_CMD_ID_SET_THERMO_CALIBRATION = 0x12, + EXT_CMD_ID_FW_LOG_2_HOST = 0x13, + EXT_CMD_ID_AP_PWR_SAVING_START = 0x14, + EXT_CMD_ID_MCC_OFFLOAD_START = 0x15, + EXT_CMD_ID_MCC_OFFLOAD_STOP = 0x16, + EXT_CMD_ID_LED = 0x17, + EXT_CMD_ID_PACKET_FILTER = 0x18, + EXT_CMD_ID_COEXISTENCE = 0x19, + EXT_CMD_ID_PWR_MGT_BIT_WIFI = 0x1B, + EXT_CMD_ID_GET_TX_POWER = 0x1C, + EXT_CMD_ID_BF_ACTION = 0x1E, + + EXT_CMD_ID_WMT_CMD_OVER_WIFI = 0x20, + EXT_CMD_ID_EFUSE_BUFFER_MODE = 0x21, + EXT_CMD_ID_OFFLOAD_CTRL = 0x22, + EXT_CMD_ID_THERMAL_PROTECT = 0x23, + EXT_CMD_ID_CLOCK_SWITCH_DISABLE = 0x24, + EXT_CMD_ID_STAREC_UPDATE = 0x25, + EXT_CMD_ID_BSSINFO_UPDATE = 0x26, + EXT_CMD_ID_EDCA_SET = 0x27, + EXT_CMD_ID_SLOT_TIME_SET = 0x28, + EXT_CMD_ID_DEVINFO_UPDATE = 0x2A, + EXT_CMD_ID_NOA_OFFLOAD_CTRL = 0x2B, + EXT_CMD_ID_GET_SENSOR_RESULT = 0x2C, + EXT_CMD_ID_TMR_CAL = 0x2D, + EXT_CMD_ID_WAKEUP_OPTION = 0x2E, + EXT_CMD_ID_OBTW = 0x2F, + + EXT_CMD_ID_GET_TX_STATISTICS = 0x30, + EXT_CMD_ID_AC_QUEUE_CONTROL = 0x31, + EXT_CMD_ID_WTBL_UPDATE = 0x32, + EXT_CMD_ID_BCN_UPDATE = 0x33, + + EXT_CMD_ID_DRR_CTRL = 0x36, + EXT_CMD_ID_BSSGROUP_CTRL = 0x37, + EXT_CMD_ID_VOW_FEATURE_CTRL = 0x38, + EXT_CMD_ID_PKT_PROCESSOR_CTRL = 0x39, + EXT_CMD_ID_PALLADIUM = 0x3A, +#if CFG_SUPPORT_MU_MIMO + EXT_CMD_ID_MU_CTRL = 0x40, +#endif /* CFG_SUPPORT_MU_MIMO */ + + EXT_CMD_ID_EFUSE_FREE_BLOCK = 0x4F + +} ENUM_EXT_CMD_ID_T, *P_ENUM_EXT_CMD_ID_T; + +typedef enum _NDIS_802_11_WEP_STATUS { + Ndis802_11WEPEnabled, + Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, + Ndis802_11WEPDisabled, + Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, + Ndis802_11WEPKeyAbsent, + Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, + Ndis802_11WEPNotSupported, + Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, + Ndis802_11TKIPEnable, + Ndis802_11Encryption2Enabled = Ndis802_11TKIPEnable, + Ndis802_11Encryption2KeyAbsent, + Ndis802_11AESEnable, + Ndis802_11Encryption3Enabled = Ndis802_11AESEnable, + Ndis802_11CCMP256Enable, + Ndis802_11GCMP128Enable, + Ndis802_11GCMP256Enable, + Ndis802_11Encryption3KeyAbsent, + Ndis802_11TKIPAESMix, + Ndis802_11Encryption4Enabled = Ndis802_11TKIPAESMix, /* TKIP or AES mix */ + Ndis802_11Encryption4KeyAbsent, + Ndis802_11GroupWEP40Enabled, + Ndis802_11GroupWEP104Enabled, +#ifdef WAPI_SUPPORT + Ndis802_11EncryptionSMS4Enabled, /* WPI SMS4 support */ +#endif /* WAPI_SUPPORT */ +} NDIS_802_11_WEP_STATUS, *PNDIS_802_11_WEP_STATUS, NDIS_802_11_ENCRYPTION_STATUS, *PNDIS_802_11_ENCRYPTION_STATUS; + +#if CFG_SUPPORT_MU_MIMO +enum { + /* debug commands */ + MU_SET_ENABLE = 0, + MU_GET_ENABLE, + MU_SET_MUPROFILE_ENTRY, + MU_GET_MUPROFILE_ENTRY, + MU_SET_GROUP_TBL_ENTRY, + MU_GET_GROUP_TBL_ENTRY, + MU_SET_CLUSTER_TBL_ENTRY, + MU_GET_CLUSTER_TBL_ENTRY, + MU_SET_GROUP_USER_THRESHOLD, + MU_GET_GROUP_USER_THRESHOLD, + MU_SET_GROUP_NSS_THRESHOLD, + MU_GET_GROUP_NSS_THRESHOLD, + MU_SET_TXREQ_MIN_TIME, + MU_GET_TXREQ_MIN_TIME, + MU_SET_SU_NSS_CHECK, + MU_GET_SU_NSS_CHECK, + MU_SET_CALC_INIT_MCS, + MU_GET_CALC_INIT_MCS, + MU_SET_TXOP_DEFAULT, + MU_GET_TXOP_DEFAULT, + MU_SET_SU_LOSS_THRESHOLD, + MU_GET_SU_LOSS_THRESHOLD, + MU_SET_MU_GAIN_THRESHOLD, + MU_GET_MU_GAIN_THRESHOLD, + MU_SET_SECONDARY_AC_POLICY, + MU_GET_SECONDARY_AC_POLICY, + MU_SET_GROUP_TBL_DMCS_MASK, + MU_GET_GROUP_TBL_DMCS_MASK, + MU_SET_MAX_GROUP_SEARCH_CNT, + MU_GET_MAX_GROUP_SEARCH_CNT, + MU_GET_MU_PROFILE_TX_STATUS_CNT, + MU_SET_TRIGGER_MU_TX, + /* F/W flow test commands */ + MU_SET_TRIGGER_GID_MGMT_FRAME, + /* HQA commands */ + MU_HQA_SET_STA_PARAM, + MU_HQA_SET_ENABLE, + MU_HQA_SET_SNR_OFFSET, + MU_HQA_SET_ZERO_NSS, + MU_HQA_SET_SPEED_UP_LQ, + MU_HQA_SET_GROUP, + MU_HQA_SET_MU_TABLE, + MU_HQA_SET_CALC_LQ, + MU_HQA_GET_CALC_LQ, + MU_HQA_SET_CALC_INIT_MCS, + MU_HQA_GET_CALC_INIT_MCS, + MU_HQA_GET_QD, +}; +#endif /* CFG_SUPPORT_MU_MIMO */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +typedef enum _ENUM_CMD_ID_T { + CMD_ID_DUMMY_RSV = 0x00, /* 0x00 (Set) */ + CMD_ID_TEST_CTRL = 0x01, /* 0x01 (Set) */ + CMD_ID_BASIC_CONFIG, /* 0x02 (Set) */ + CMD_ID_SCAN_REQ_V2, /* 0x03 (Set) */ + CMD_ID_NIC_POWER_CTRL, /* 0x04 (Set) */ + CMD_ID_POWER_SAVE_MODE, /* 0x05 (Set) */ + CMD_ID_LINK_ATTRIB, /* 0x06 (Set) */ + CMD_ID_ADD_REMOVE_KEY, /* 0x07 (Set) */ + CMD_ID_DEFAULT_KEY_ID, /* 0x08 (Set) */ + CMD_ID_INFRASTRUCTURE, /* 0x09 (Set) */ + CMD_ID_SET_RX_FILTER, /* 0x0a (Set) */ + CMD_ID_DOWNLOAD_BUF, /* 0x0b (Set) */ + CMD_ID_WIFI_START, /* 0x0c (Set) */ + CMD_ID_CMD_BT_OVER_WIFI, /* 0x0d (Set) */ + CMD_ID_SET_MEDIA_CHANGE_DELAY_TIME, /* 0x0e (Set) */ + CMD_ID_SET_DOMAIN_INFO, /* 0x0f (Set) */ + CMD_ID_SET_IP_ADDRESS, /* 0x10 (Set) */ + CMD_ID_BSS_ACTIVATE_CTRL, /* 0x11 (Set) */ + CMD_ID_SET_BSS_INFO, /* 0x12 (Set) */ + CMD_ID_UPDATE_STA_RECORD, /* 0x13 (Set) */ + CMD_ID_REMOVE_STA_RECORD, /* 0x14 (Set) */ + CMD_ID_INDICATE_PM_BSS_CREATED, /* 0x15 (Set) */ + CMD_ID_INDICATE_PM_BSS_CONNECTED, /* 0x16 (Set) */ + CMD_ID_INDICATE_PM_BSS_ABORT, /* 0x17 (Set) */ + CMD_ID_UPDATE_BEACON_CONTENT, /* 0x18 (Set) */ + CMD_ID_SET_BSS_RLM_PARAM, /* 0x19 (Set) */ + CMD_ID_SCAN_REQ, /* 0x1a (Set) */ + CMD_ID_SCAN_CANCEL, /* 0x1b (Set) */ + CMD_ID_CH_PRIVILEGE, /* 0x1c (Set) */ + CMD_ID_UPDATE_WMM_PARMS, /* 0x1d (Set) */ + CMD_ID_SET_WMM_PS_TEST_PARMS, /* 0x1e (Set) */ + CMD_ID_TX_AMPDU, /* 0x1f (Set) */ + CMD_ID_ADDBA_REJECT, /* 0x20 (Set) */ + CMD_ID_SET_PS_PROFILE_ADV, /* 0x21 (Set) */ + CMD_ID_SET_RAW_PATTERN, /* 0x22 (Set) */ + CMD_ID_CONFIG_PATTERN_FUNC, /* 0x23 (Set) */ + CMD_ID_SET_TX_PWR, /* 0x24 (Set) */ + CMD_ID_SET_PWR_PARAM, /* 0x25 (Set) */ + CMD_ID_P2P_ABORT, /* 0x26 (Set) */ + CMD_ID_SET_DBDC_PARMS = 0x28, /* 0x28 (Set) */ + + CMD_ID_KEEP_FULL_PWR = 0x2A, /* 0x2A (Set) */ + + /* SLT commands */ + 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 ) */ + + CMD_ID_ROAMING_TRANSIT = 0x30, /* 0x30 (Set) */ + CMD_ID_SET_PHY_PARAM, /* 0x31 (Set) */ + CMD_ID_SET_NOA_PARAM, /* 0x32 (Set) */ + CMD_ID_SET_OPPPS_PARAM, /* 0x33 (Set) */ + CMD_ID_SET_UAPSD_PARAM, /* 0x34 (Set) */ + CMD_ID_SET_SIGMA_STA_SLEEP, /* 0x35 (Set) */ + CMD_ID_SET_EDGE_TXPWR_LIMIT, /* 0x36 (Set) */ + CMD_ID_SET_DEVICE_MODE, /* 0x37 (Set) */ + CMD_ID_SET_TXPWR_CTRL, /* 0x38 (Set) */ + CMD_ID_SET_AUTOPWR_CTRL, /* 0x39 (Set) */ + CMD_ID_SET_WFD_CTRL, /* 0x3a (Set) */ + CMD_ID_SET_NLO_REQ, /* 0x3b (Set) */ + CMD_ID_SET_NLO_CANCEL, /* 0x3c (Set) */ + CMD_ID_SET_GTK_REKEY_DATA, /* 0x3d (Set) */ + CMD_ID_ROAMING_CONTROL, /* 0x3e (Set) */ +/* CFG_M0VE_BA_TO_DRIVER */ + CMD_ID_RESET_BA_SCOREBOARD = 0x3f, /* 0x3f (Set) */ + CMD_ID_SET_EDGE_TXPWR_LIMIT_5G = 0x40, /* 0x40 (Set) */ + CMD_ID_SET_CHANNEL_PWR_OFFSET, /* 0x41 (Set) */ + CMD_ID_SET_80211AC_TX_PWR, /* 0x42 (Set) */ + CMD_ID_SET_PATH_COMPASATION, /* 0x43 (Set) */ + + CMD_ID_SET_BATCH_REQ = 0x47, /* 0x47 (Set) */ + CMD_ID_SET_NVRAM_SETTINGS, /* 0x48 (Set) */ + CMD_ID_SET_COUNTRY_POWER_LIMIT, /* 0x49 (Set) */ + +#if CFG_WOW_SUPPORT + CMD_ID_SET_WOWLAN, /* 0x4a (Set) */ +#endif + +#if CFG_SUPPORT_CSI + CMD_ID_CSI_CONTROL = 0x4c, /* 0x4c (Set /Query) */ +#endif + + CMD_ID_SET_MDNS_RECORD = 0X4e, + +#if CFG_SUPPORT_WIFI_HOST_OFFLOAD + CMD_ID_SET_AM_FILTER = 0x55, /* 0x55 (Set) */ + CMD_ID_SET_AM_HEARTBEAT, /* 0x56 (Set) */ + CMD_ID_SET_AM_TCP, /* 0x57 (Set) */ +#endif + CMD_ID_SET_SUSPEND_MODE = 0x58, /* 0x58 (Set) */ + +#if CFG_WOW_SUPPORT + CMD_ID_SET_PF_CAPABILITY = 0x59, /* 0x59 (Set) */ +#endif + +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + CMD_ID_SET_ROAMING_SKIP = 0x6D, /* 0x6D (Set) used to setting roaming skip*/ +#endif + CMD_ID_GET_SET_CUSTOMER_CFG = 0x70, /* 0x70(Set) */ + CMD_ID_COEX_CTRL = 0x7C, /* 0x7C (Set/Query) */ + 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_STA_STATISTICS = 0x85, /* 0x85 (Query) */ + + CMD_ID_GET_LTE_CHN = 0x87, /* 0x87 (Query) */ + CMD_ID_GET_CHN_LOADING = 0x88, /* 0x88 (Query) */ + CMD_ID_GET_BUG_REPORT = 0x89, /* 0x89 (Query) */ + CMD_ID_GET_NIC_CAPABILITY_V2 = 0x8A,/* 0x8A (Query) */ + +#if (CFG_SUPPORT_DFS_MASTER == 1) + CMD_ID_RDD_ON_OFF_CTRL = 0x8F, /* 0x8F(Set) */ +#endif + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST + CMD_ID_CAL_BACKUP_IN_HOST_V2 = 0xAE, /* 0xAE (Set / Query) */ +#endif + + CMD_ID_ACCESS_REG = 0xc0, /* 0xc0 (Set / Query) */ + CMD_ID_MAC_MCAST_ADDR, /* 0xc1 (Set / Query) */ + CMD_ID_802_11_PMKID, /* 0xc2 (Set / Query) */ + CMD_ID_ACCESS_EEPROM, /* 0xc3 (Set / Query) */ + CMD_ID_SW_DBG_CTRL, /* 0xc4 (Set / Query) */ + CMD_ID_FW_LOG_2_HOST, /* 0xc5 (Set) */ + CMD_ID_DUMP_MEM, /* 0xc6 (Query) */ + CMD_ID_RESOURCE_CONFIG, /* 0xc7 (Set / Query) */ +#if CFG_SUPPORT_QA_TOOL + CMD_ID_ACCESS_RX_STAT, /* 0xc8 (Query) */ +#endif /* CFG_SUPPORT_QA_TOOL */ + CMD_ID_CHIP_CONFIG = 0xCA, /* 0xca (Set / Query) */ + CMD_ID_STATS_LOG = 0xCB, /* 0xcb (Set) */ + + CMD_ID_WLAN_INFO = 0xCD, /* 0xcd (Query) */ + CMD_ID_MIB_INFO = 0xCE, /* 0xce (Query) */ + +#if CFG_SUPPORT_LAST_SEC_MCS_INFO + CMD_ID_TX_MCS_INFO = 0xCF, /* 0xcf (Query) */ +#endif + CMD_ID_GET_TXPWR_TBL = 0xD0, /* 0xd0 (Query) */ + + CMD_ID_SET_RDD_CH = 0xE1, + +#if CFG_SUPPORT_QA_TOOL + CMD_ID_LAYER_0_EXT_MAGIC_NUM = 0xED, /* magic number for Extending MT6630 original CMD header */ +#endif /* CFG_SUPPORT_QA_TOOL */ + + CMD_ID_SET_BWCS = 0xF1, + CMD_ID_SET_OSC = 0xF2, + + CMD_ID_HIF_CTRL = 0xF6, /* 0xF6 (Set) */ + + CMD_ID_GET_BUILD_DATE_CODE = 0xF8, /* 0xf8 (Query) */ + CMD_ID_GET_BSS_INFO = 0xF9, /* 0xF9 (Query) */ + CMD_ID_SET_HOTSPOT_OPTIMIZATION = 0xFA, /* 0xFA (Set) */ + CMD_ID_SET_TDLS_CH_SW = 0xFB, + CMD_ID_SET_MONITOR = 0xFC, /* 0xFC (Set) */ +#if CFG_SUPPORT_ADVANCE_CONTROL + CMD_ID_ADV_CONTROL = 0xFE, /* 0xFE (Set / Query) */ +#endif + CMD_ID_END +} ENUM_CMD_ID_T, *P_ENUM_CMD_ID_T; + +typedef enum _ENUM_EVENT_ID_T { + EVENT_ID_NIC_CAPABILITY = 0x01, /* 0x01 (Query) */ + EVENT_ID_LINK_QUALITY, /* 0x02 (Query / Unsolicited) */ + EVENT_ID_STATISTICS, /* 0x03 (Query) */ + EVENT_ID_MIC_ERR_INFO, /* 0x04 (Unsolicited) */ + EVENT_ID_ACCESS_REG, /* 0x05 (Query - CMD_ID_ACCESS_REG) */ + EVENT_ID_ACCESS_EEPROM, /* 0x06 (Query - CMD_ID_ACCESS_EEPROM) */ + EVENT_ID_SLEEPY_INFO, /* 0x07 (Unsolicited) */ + EVENT_ID_BT_OVER_WIFI, /* 0x08 (Unsolicited) */ + EVENT_ID_TEST_STATUS, /* 0x09 (Query - CMD_ID_TEST_CTRL) */ + EVENT_ID_RX_ADDBA, /* 0x0a (Unsolicited) */ + EVENT_ID_RX_DELBA, /* 0x0b (Unsolicited) */ + EVENT_ID_ACTIVATE_STA_REC, /* 0x0c (Response) */ + EVENT_ID_SCAN_DONE, /* 0x0d (Unsoiicited) */ + EVENT_ID_RX_FLUSH, /* 0x0e (Unsolicited) */ + EVENT_ID_TX_DONE, /* 0x0f (Unsolicited) */ + EVENT_ID_CH_PRIVILEGE, /* 0x10 (Unsolicited) */ + EVENT_ID_BSS_ABSENCE_PRESENCE, /* 0x11 (Unsolicited) */ + EVENT_ID_STA_CHANGE_PS_MODE, /* 0x12 (Unsolicited) */ + EVENT_ID_BSS_BEACON_TIMEOUT, /* 0x13 (Unsolicited) */ + EVENT_ID_UPDATE_NOA_PARAMS, /* 0x14 (Unsolicited) */ + EVENT_ID_AP_OBSS_STATUS, /* 0x15 (Unsolicited) */ + EVENT_ID_STA_UPDATE_FREE_QUOTA, /* 0x16 (Unsolicited) */ + EVENT_ID_SW_DBG_CTRL, /* 0x17 (Query - CMD_ID_SW_DBG_CTRL) */ + EVENT_ID_ROAMING_STATUS, /* 0x18 (Unsolicited) */ + EVENT_ID_STA_AGING_TIMEOUT, /* 0x19 (Unsolicited) */ + EVENT_ID_SEC_CHECK_RSP, /* 0x1a (Query - CMD_ID_SEC_CHECK) */ + EVENT_ID_SEND_DEAUTH, /* 0x1b (Unsolicited) */ + EVENT_ID_UPDATE_RDD_STATUS, /* 0x1c (Unsolicited) */ + EVENT_ID_UPDATE_BWCS_STATUS, /* 0x1d (Unsolicited) */ + EVENT_ID_UPDATE_BCM_DEBUG, /* 0x1e (Unsolicited) */ + EVENT_ID_RX_ERR, /* 0x1f (Unsolicited) */ + EVENT_ID_DUMP_MEM = 0x20, /* 0x20 (Query - CMD_ID_DUMP_MEM) */ + EVENT_ID_STA_STATISTICS, /* 0x21 (Query ) */ + EVENT_ID_STA_STATISTICS_UPDATE, /* 0x22 (Unsolicited) */ + EVENT_ID_NLO_DONE, /* 0x23 (Unsoiicited) */ + EVENT_ID_ADD_PKEY_DONE, /* 0x24 (Unsoiicited) */ + EVENT_ID_ICAP_DONE, /* 0x25 (Unsoiicited) */ + EVENT_ID_RESOURCE_CONFIG = 0x26, /* 0x26 (Query - CMD_ID_RESOURCE_CONFIG) */ + EVENT_ID_DEBUG_MSG = 0x27, /* 0x27 (Unsoiicited) */ + EVENT_ID_RTT_CALIBR_DONE = 0x28, /* 0x28 (Unsoiicited) */ + EVENT_ID_RTT_UPDATE_RANGE = 0x29, /* 0x29 (Unsoiicited) */ + EVENT_ID_CHECK_REORDER_BUBBLE = 0x2a, /* 0x2a (Unsoiicited) */ + EVENT_ID_BATCH_RESULT = 0x2b, /* 0x2b (Query) */ + +#if CFG_SUPPORT_CSI + EVENT_ID_CSI_DATA = 0x3c, /* 0x3c (Query) */ +#endif + + EVENT_ID_GET_GTK_REKEY_DATA = 0x3d, /* 0x3d (Query) */ + + EVENT_ID_UART_ACK = 0x40, /* 0x40 (Unsolicited) */ + EVENT_ID_UART_NAK, /* 0x41 (Unsolicited) */ + EVENT_ID_GET_CHIPID, /* 0x42 (Query - CMD_ID_GET_CHIPID) */ + EVENT_ID_SLT_STATUS, /* 0x43 (Query - CMD_ID_SET_SLTINFO) */ + EVENT_ID_CHIP_CONFIG, /* 0x44 (Query - CMD_ID_CHIP_CONFIG) */ +#if CFG_SUPPORT_QA_TOOL + EVENT_ID_ACCESS_RX_STAT, /* 0x45 (Query - CMD_ID_ACCESS_RX_STAT) */ +#endif /* CFG_SUPPORT_QA_TOOL */ + + EVENT_ID_RDD_SEND_PULSE = 0x50, + +#if CFG_SUPPORT_TX_BF + EVENT_ID_PFMU_TAG_READ = 0x51, + EVENT_ID_PFMU_DATA_READ = 0x52, +#endif + +#if CFG_SUPPORT_MU_MIMO + EVENT_ID_MU_GET_QD = 0x53, + EVENT_ID_MU_GET_LQ = 0x54, +#endif + +#if (CFG_SUPPORT_DFS_MASTER == 1) + EVENT_ID_RDD_REPORT = 0x60, + EVENT_ID_CSA_DONE = 0x61, +#endif + +#if (CFG_WOW_SUPPORT == 1) + EVENT_ID_WOW_WAKEUP_REASON = 0x62, +#endif + + EVENT_ID_TDLS = 0x80, /* TDLS event_id */ + + EVENT_ID_UPDATE_COEX_PHYRATE = 0x90, /* 0x90 (Unsolicited) */ + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST + EVENT_ID_CAL_BACKUP_IN_HOST_V2 = 0xAE, /* 0xAE (Query - CMD_ID_CAL_BACKUP) */ + EVENT_ID_CAL_ALL_DONE = 0xAF, /* 0xAF (FW Cal All Done Event) */ +#endif + + EVENT_ID_WLAN_INFO = 0xCD, + EVENT_ID_MIB_INFO = 0xCE, + +#if CFG_SUPPORT_LAST_SEC_MCS_INFO + EVENT_ID_TX_MCS_INFO = 0xCF, +#endif + EVENT_ID_GET_TXPWR_TBL = 0xD0, + + EVENT_ID_NIC_CAPABILITY_V2 = 0xEC, /* 0xEC (Query - CMD_ID_GET_NIC_CAPABILITY_V2) */ +/*#if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1)*/ + EVENT_ID_LAYER_0_EXT_MAGIC_NUM = 0xED, /* magic number for Extending MT6630 original EVENT header */ +/*#endif*/ + +#if CFG_ASSERT_DUMP + EVENT_ID_ASSERT_DUMP = 0xF0, +#endif + EVENT_ID_HIF_CTRL = 0xF6, + EVENT_ID_BUILD_DATE_CODE = 0xF8, + EVENT_ID_GET_AIS_BSS_INFO = 0xF9, + EVENT_ID_DEBUG_CODE = 0xFB, + EVENT_ID_RFTEST_READY = 0xFC, /* 0xFC */ +#if CFG_SUPPORT_ADVANCE_CONTROL + EVENT_ID_ADV_CONTROL = 0xFE, +#endif + EVENT_ID_END +} ENUM_EVENT_ID_T, *P_ENUM_EVENT_ID_T; + +#if CFG_WOW_SUPPORT + +/* Filter Flag */ +#define WOWLAN_FF_DROP_ALL BIT(0) +#define WOWLAN_FF_SEND_MAGIC_TO_HOST BIT(1) +#define WOWLAN_FF_ALLOW_ARP BIT(2) +#define WOWLAN_FF_ALLOW_BMC BIT(3) +#define WOWLAN_FF_ALLOW_UC BIT(4) +#define WOWLAN_FF_ALLOW_1X BIT(5) +#define WOWLAN_FF_ALLOW_ARP_REQ2ME BIT(6) + +/* wow detect type */ +#define WOWLAN_DETECT_TYPE_MAGIC BIT(0) +#define WOWLAN_DETECT_TYPE_ALLOW_NORMAL BIT(1) +#define WOWLAN_DETECT_TYPE_ONLY_PHONE_SUSPEND BIT(2) +#define WOWLAN_DETECT_TYPE_DISASSOCIATION BIT(3) +#define WOWLAN_DETECT_TYPE_BCN_LOST BIT(4) + +/* Wakeup command bit define */ +#define WOWLAN_DETECT_TYPE_NONE 0 +#define PF_WAKEUP_CMD_BIT0_OUTPUT_MODE_EN BIT(0) +#define PF_WAKEUP_CMD_BIT1_OUTPUT_DATA BIT(1) +#define PF_WAKEUP_CMD_BIT2_WAKEUP_LEVEL BIT(2) + +#define PM_WOWLAN_REQ_START 0x1 +#define PM_WOWLAN_REQ_STOP 0x2 + +typedef struct _CMD_WAKE_HIF_T { + UINT_8 ucWakeupHif; /* use in-band signal to wakeup system, ENUM_HIF_TYPE */ + UINT_8 ucGpioPin; /* GPIO Pin */ + UINT_8 ucTriggerLvl; /* GPIO Pin */ + UINT_8 aucResv1[1]; + UINT_32 u4GpioInterval;/* 0: low to high, 1: high to low */ + UINT_8 aucResv2[4]; +} CMD_WAKE_HIF_T, *P_CMD_WAKE_HIF_T; + +typedef struct _CMD_WOWLAN_PARAM_T { + UINT_8 ucCmd; + UINT_8 ucDetectType; + UINT_16 u2FilterFlag; /* ARP/MC/DropExceptMagic/SendMagicToHost */ + UINT_8 ucScenarioID; /* WOW/WOBLE/Proximity */ + UINT_8 ucBlockCount; + UINT_8 ucDbdcBand; + UINT_8 aucReserved1[1]; + CMD_WAKE_HIF_T astWakeHif[2]; + WOW_PORT_T stWowPort; + UINT_8 aucReserved2[32]; +} CMD_WOWLAN_PARAM_T, *P_CMD_WOWLAN_PARAM_T; + +typedef struct _EVENT_WOWLAN_NOTIFY_T { + UINT_8 ucNetTypeIndex; + UINT_8 aucReserved[3]; +} EVENT_WOWLAN_NOTIFY_T, *P_EVENT_WOWLAN_NOTIFY_T; + +/* PACKETFILTER CAPABILITY TYPE */ + +#define PACKETF_CAP_TYPE_ARP BIT(1) +#define PACKETF_CAP_TYPE_MAGIC BIT(2) +#define PACKETF_CAP_TYPE_BITMAP BIT(3) +#define PACKETF_CAP_TYPE_EAPOL BIT(4) +#define PACKETF_CAP_TYPE_TDLS BIT(5) +#define PACKETF_CAP_TYPE_CF BIT(6) +#define PACKETF_CAP_TYPE_HEARTBEAT BIT(7) +#define PACKETF_CAP_TYPE_TCP_SYN BIT(8) +#define PACKETF_CAP_TYPE_UDP_SYN BIT(9) +#define PACKETF_CAP_TYPE_BCAST_SYN BIT(10) +#define PACKETF_CAP_TYPE_MCAST_SYN BIT(11) +#define PACKETF_CAP_TYPE_V6 BIT(12) +#define PACKETF_CAP_TYPE_TDIM BIT(13) + + +typedef enum _ENUM_FUNCTION_SELECT { + FUNCTION_PF = 1, + FUNCTION_BITMAP = 2, + FUNCTION_EAPOL = 3, + FUNCTION_TDLS = 4, + FUNCTION_ARPNS = 5, + FUNCTION_CF = 6, + FUNCTION_MODE = 7, + FUNCTION_BSSID = 8, + FUNCTION_MGMT = 9, + FUNCTION_BMC_DROP = 10, + FUNCTION_UC_DROP = 11, + FUNCTION_ALL_TOMCU = 12, +} _ENUM_FUNCTION_SELECT, *P_ENUM_FUNCTION_SELECT; + +typedef enum _ENUM_PF_OPCODE_T { + PF_OPCODE_ADD = 0, + PF_OPCODE_DEL, + PF_OPCODE_ENABLE, + PF_OPCODE_DISABLE, + PF_OPCODE_NUM +} ENUM_PF_OPCODE_T; + +typedef struct _CMD_PACKET_FILTER_CAP_T { + UINT_8 ucCmd; + UINT_16 packet_cap_type; + UINT_8 aucReserved1[1]; +/* GLOBAL */ + UINT_32 PFType; + UINT_32 FunctionSelect; + UINT_32 Enable; +/* MAGIC */ + UINT_8 ucBssid; + UINT_16 usEnableBits; + UINT_8 aucReserved5[1]; +/* DTIM */ + UINT_8 DtimEnable; + UINT_8 DtimValue; + UINT_8 aucReserved2[2]; +/* BITMAP_PATTERN_T */ + UINT_32 Index; + UINT_32 Offset; + UINT_32 FeatureBits; + UINT_32 Resv; + UINT_32 PatternLength; + UINT_32 Mask[4]; + UINT_32 Pattern[32]; +/* COALESCE */ + UINT_32 FilterID; + UINT_32 PacketType; + UINT_32 CoalesceOP; + UINT_8 FieldLength; + UINT_8 CompareOP; + UINT_8 FieldID; + UINT_8 aucReserved3[1]; + UINT_32 Pattern3[4]; +/* TCPSYN */ + UINT_32 AddressType; + UINT_32 TCPSrcPort; + UINT_32 TCPDstPort; + UINT_32 SourceIP[4]; + UINT_32 DstIP[4]; + UINT_8 aucReserved4[64]; +} CMD_PACKET_FILTER_CAP_T, *P_CMD_PACKET_FILTER_CAP_T; +#endif /*CFG_WOW_SUPPORT*/ + +#if CFG_SUPPORT_WIFI_HOST_OFFLOAD +typedef struct _CMD_TCP_GENERATOR { + ENUM_PF_OPCODE_T eOpcode; + UINT_32 u4ReplyId; + UINT_32 u4Period; + UINT_32 u4Timeout; + UINT_32 u4IpId; + UINT_32 u4DestPort; + UINT_32 u4SrcPort; + UINT_32 u4Seq; + UINT_8 aucDestIp[4]; + UINT_8 aucSrcIp[4]; + UINT_8 aucDestMac[6]; + UINT_8 ucBssId; + UINT_8 aucReserved1[1]; + UINT_8 aucReserved2[64]; +} CMD_TCP_GENERATOR, *P_CMD_TCP_GENERATOR; + +typedef struct _CMD_PATTERN_GENERATOR { + ENUM_PF_OPCODE_T eOpcode; + UINT_32 u4ReplyId; + UINT_32 u4EthernetLength; + UINT_32 u4Period; + UINT_8 aucEthernetFrame[128]; + UINT_8 ucBssId; + UINT_8 aucReserved1[3]; + UINT_8 aucReserved2[64]; +} CMD_PATTERN_GENERATOR, *P_CMD_PATTERN_GENERATOR; + +typedef struct _CMD_BITMAP_FILTER { + ENUM_PF_OPCODE_T eOpcode; + UINT_32 u4ReplyId; + UINT_32 u4Offset; + UINT_32 u4Length; + UINT_8 aucPattern[64]; + UINT_8 aucBitMask[64]; + BOOLEAN fgIsEqual; + BOOLEAN fgIsAccept; + UINT_8 ucBssId; + UINT_8 aucReserved1[1]; + UINT_8 aucReserved2[64]; +} CMD_BITMAP_FILTER, *P_CMD_BITMAP_FILTER; + +#endif /*CFG_SUPPORT_WIFI_HOST_OFFLOAD*/ + +typedef struct _CMD_RX_PACKET_FILTER { + UINT_32 u4RxPacketFilter; + UINT_8 aucReserved[64]; +} CMD_RX_PACKET_FILTER, *P_CMD_RX_PACKET_FILTER; + + +#if defined(MT6632) +#define S2D_INDEX_CMD_H2N 0x0 +#define S2D_INDEX_CMD_C2N 0x1 +#define S2D_INDEX_CMD_H2C 0x2 +#define S2D_INDEX_CMD_H2N_H2C 0x3 + +#define S2D_INDEX_EVENT_N2H 0x0 +#define S2D_INDEX_EVENT_N2C 0x1 +#define S2D_INDEX_EVENT_C2H 0x2 +#define S2D_INDEX_EVENT_N2H_N2C 0x3 +#endif + +#define EXT_EVENT_ID_CMD_RESULT 0x00 + +/*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ +#define EXT_EVENT_ID_CMD_EFUSE_ACCESS 0x1 +#define EXT_EVENT_ID_EFUSE_FREE_BLOCK 0x4D +#define EXT_EVENT_ID_GET_TX_POWER 0x1C +#define EXT_EVENT_TARGET_TX_POWER 0x1 + +/*#endif*/ +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +#ifndef LINUX +typedef UINT_8 CMD_STATUS; +#endif +/* for Event Packet (via HIF-RX) */ +typedef struct _PSE_CMD_HDR_T { + /* DW0 */ + UINT_16 u2TxByteCount; + UINT_16 u2Reserved1:10; + UINT_16 u2Qidx:5; + UINT_16 u2Pidx:1; + + /* DW1 */ + UINT_16 u2Reserved2:13; + UINT_16 u2Hf:2; + UINT_16 u2Ft:1; + UINT_16 u2Reserved3:8; + UINT_16 u2PktFt:2; + UINT_16 u2Reserved4:6; + + /* DW2~7 */ + UINT_32 au4Reserved[6]; +} PSE_CMD_HDR_T, *P_PSE_CMD_HDR_T; + +typedef struct _WIFI_CMD_T { + UINT_16 u2TxByteCount; /* Max value is over 2048 */ + UINT_16 u2PQ_ID; /* Must be 0x8000 (Port1, Queue 0) */ +#if 1 + UINT_8 ucWlanIdx; + UINT_8 ucHeaderFormat; + UINT_8 ucHeaderPadding; + UINT_8 ucPktFt:2; + UINT_8 ucOwnMAC:6; + UINT_32 au4Reserved1[6]; + + UINT_16 u2Length; + UINT_16 u2PqId; +#endif + UINT_8 ucCID; + UINT_8 ucPktTypeID; /* Must be 0x20 (CMD Packet) */ + UINT_8 ucSetQuery; + UINT_8 ucSeqNum; +#if 1 + UINT_8 ucD2B0Rev; /* padding fields, hw may auto modify this field */ + UINT_8 ucExtenCID; /* Extend CID */ + UINT_8 ucS2DIndex; /* Index for Src to Dst in CMD usage */ + UINT_8 ucExtCmdOption; /* Extend CID option */ + + UINT_8 ucCmdVersion; + UINT_8 ucReserved2[3]; + UINT_32 au4Reserved3[4]; /* padding fields */ +#endif + 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 { +#if 1 + UINT_32 au4HwMacRxDesc[4]; +#endif + UINT_16 u2PacketLength; + UINT_16 u2PacketType; /* Must be filled with 0xE000 (EVENT Packet) */ + UINT_8 ucEID; + UINT_8 ucSeqNum; + UINT_8 ucEventVersion; + UINT_8 aucReserved[1]; + + UINT_8 ucExtenEID; + UINT_8 aucReserved2[2]; + UINT_8 ucS2DIndex; + + UINT_8 aucBuffer[0]; +} WIFI_EVENT_T, *P_WIFI_EVENT_T; + +/* CMD_ID_TEST_CTRL */ +typedef struct _CMD_TEST_CTRL_T { + UINT_8 ucAction; + UINT_8 aucReserved[3]; + union { + UINT_32 u4OpMode; + UINT_32 u4ChannelFreq; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + } u; +} CMD_TEST_CTRL_T, *P_CMD_TEST_CTRL_T; + +/* EVENT_TEST_STATUS */ +typedef struct _PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T { + UINT_32 u4PktSentStatus; + UINT_32 u4PktSentCount; + UINT_16 u2AvgAlc; + UINT_8 ucCckGainControl; + UINT_8 ucOfdmGainControl; +} PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T, *P_PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T; + +typedef struct _PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T { + UINT_32 u4IntRxOk; /*!< number of packets that Rx ok from interrupt */ + UINT_32 u4IntCrcErr; /*!< number of packets that CRC error from interrupt */ + UINT_32 u4IntShort; /*!< number of packets that is short preamble from interrupt */ + UINT_32 u4IntLong; /*!< number of packets that is long preamble from interrupt */ + UINT_32 u4PauRxPktCount; /*!< number of packets that Rx ok from PAU */ + UINT_32 u4PauCrcErrCount; /*!< number of packets that CRC error from PAU */ + UINT_32 u4PauRxFifoFullCount; /*!< number of packets that is short preamble from PAU */ + UINT_32 u4PauCCACount; /*!< CCA rising edge count */ +} PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T, *P_PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T; + +typedef union _EVENT_TEST_STATUS { + PARAM_MTK_WIFI_TEST_STRUCT_T rATInfo; +/* PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T rTxStatus; */ +/* PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T rRxStatus; */ +} EVENT_TEST_STATUS, *P_EVENT_TEST_STATUS; + +/* CMD_BUILD_CONNECTION */ +typedef struct _CMD_BUILD_CONNECTION { + UINT_8 ucInfraMode; + UINT_8 ucAuthMode; + UINT_8 ucEncryptStatus; + UINT_8 ucSsidLen; + UINT_8 aucSsid[PARAM_MAX_LEN_SSID]; + UINT_8 aucBssid[PARAM_MAC_ADDR_LEN]; + + /* Ad-hoc mode */ + UINT_16 u2BeaconPeriod; + UINT_16 u2ATIMWindow; + UINT_8 ucJoinOnly; + UINT_8 ucReserved; + UINT_32 u4FreqInKHz; + + /* for faster connection */ + UINT_8 aucScanResult[0]; +} CMD_BUILD_CONNECTION, *P_CMD_BUILD_CONNECTION; + +/* CMD_ADD_REMOVE_KEY */ +typedef struct _CMD_802_11_KEY { + UINT_8 ucAddRemove; + UINT_8 ucTxKey; + UINT_8 ucKeyType; + UINT_8 ucIsAuthenticator; + UINT_8 aucPeerAddr[6]; + UINT_8 ucBssIdx; + UINT_8 ucAlgorithmId; + UINT_8 ucKeyId; + UINT_8 ucKeyLen; + UINT_8 ucWlanIndex; + UINT_8 ucMgmtProtection; + UINT_8 aucKeyMaterial[32]; + UINT_8 aucKeyRsc[16]; +} CMD_802_11_KEY, *P_CMD_802_11_KEY; + +/* CMD_ID_DEFAULT_KEY_ID */ +typedef struct _CMD_DEFAULT_KEY { + UINT_8 ucBssIdx; + UINT_8 ucKeyId; + UINT_8 ucWlanIndex; + UINT_8 ucMulticast; +} CMD_DEFAULT_KEY, *P_CMD_DEFAULT_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 { + UINT_32 u4BSSIDInfoCount; + P_PMKID_ENTRY_T arPMKIDInfo[1]; +} CMD_802_11_PMKID, *P_CMD_802_11_PMKID; + +typedef struct _CMD_GTK_REKEY_DATA_T { + UINT_8 aucKek[16]; + UINT_8 aucKck[16]; + UINT_8 aucReplayCtr[8]; +} CMD_GTK_REKEY_DATA_T, *P_CMD_GTK_REKEY_DATA_T; + +typedef struct _CMD_CSUM_OFFLOAD_T { + UINT_16 u2RxChecksum; /* bit0: IP, bit1: UDP, bit2: TCP */ + UINT_16 u2TxChecksum; /* bit0: IP, bit1: UDP, bit2: TCP */ +} CMD_CSUM_OFFLOAD_T, *P_CMD_CSUM_OFFLOAD_T; + +/* CMD_BASIC_CONFIG */ +typedef struct _CMD_BASIC_CONFIG_T { + UINT_8 ucNative80211; + UINT_8 ucCtrlFlagAssertPath; + UINT_8 ucCtrlFlagDebugLevel; + UINT_8 aucReserved[1]; + CMD_CSUM_OFFLOAD_T rCsumOffload; + UINT_8 ucCrlFlagSegememt; + UINT_8 aucReserved2[3]; +} CMD_BASIC_CONFIG_T, *P_CMD_BASIC_CONFIG_T; + +/* CMD_MAC_MCAST_ADDR */ +typedef struct _CMD_MAC_MCAST_ADDR { + UINT_32 u4NumOfGroupAddr; + UINT_8 ucBssIndex; + UINT_8 aucReserved[3]; + PARAM_MAC_ADDRESS arAddress[MAX_NUM_GROUP_ADDR]; +} CMD_MAC_MCAST_ADDR, *P_CMD_MAC_MCAST_ADDR, EVENT_MAC_MCAST_ADDR, *P_EVENT_MAC_MCAST_ADDR; + +/* CMD_ACCESS_EEPROM */ +typedef struct _CMD_ACCESS_EEPROM { + UINT_16 u2Offset; + UINT_16 u2Data; +} CMD_ACCESS_EEPROM, *P_CMD_ACCESS_EEPROM, EVENT_ACCESS_EEPROM, *P_EVENT_ACCESS_EEPROM; + +typedef struct _CMD_CUSTOM_NOA_PARAM_STRUCT_T { + UINT_32 u4NoaDurationMs; + UINT_32 u4NoaIntervalMs; + UINT_32 u4NoaCount; + UINT_8 ucBssIdx; + UINT_8 aucReserved[3]; +} CMD_CUSTOM_NOA_PARAM_STRUCT_T, *P_CMD_CUSTOM_NOA_PARAM_STRUCT_T; + +typedef struct _CMD_CUSTOM_OPPPS_PARAM_STRUCT_T { + UINT_32 u4CTwindowMs; + UINT_8 ucBssIdx; + UINT_8 aucReserved[3]; +} CMD_CUSTOM_OPPPS_PARAM_STRUCT_T, *P_CMD_CUSTOM_OPPPS_PARAM_STRUCT_T; + +typedef struct _CMD_CUSTOM_UAPSD_PARAM_STRUCT_T { + UINT_8 fgEnAPSD; + UINT_8 fgEnAPSD_AcBe; + UINT_8 fgEnAPSD_AcBk; + UINT_8 fgEnAPSD_AcVo; + UINT_8 fgEnAPSD_AcVi; + UINT_8 ucMaxSpLen; + UINT_8 aucResv[2]; +} CMD_CUSTOM_UAPSD_PARAM_STRUCT_T, *P_CMD_CUSTOM_UAPSD_PARAM_STRUCT_T; + +#if CFG_M0VE_BA_TO_DRIVER +typedef struct _CMD_RESET_BA_SCOREBOARD_T { + UINT_8 ucflag; + UINT_8 ucTID; + UINT_8 aucMacAddr[PARAM_MAC_ADDR_LEN]; +} CMD_RESET_BA_SCOREBOARD_T, *P_CMD_RESET_BA_SCOREBOARD_T; +#endif + +/* 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_T { + UINT_16 u2ProductID; + UINT_16 u2FwVersion; + UINT_16 u2DriverVersion; + UINT_8 ucHw5GBandDisabled; + UINT_8 ucEepromUsed; + UINT_8 aucMacAddr[6]; + UINT_8 ucEndianOfMacAddrNumber; + UINT_8 ucHwNotSupportAC; + + UINT_8 ucRfVersion; + UINT_8 ucPhyVersion; + UINT_8 ucRfCalFail; + UINT_8 ucBbCalFail; + UINT_8 aucDateCode[16]; + UINT_32 u4FeatureFlag0; + UINT_32 u4FeatureFlag1; + UINT_32 u4CompileFlag0; + UINT_32 u4CompileFlag1; + UINT_8 aucBranchInfo[4]; + UINT_8 ucFwBuildNumber; + UINT_8 ucHwSetNss1x1; + UINT_8 ucHwNotSupportDBDC; + UINT_8 ucHwWiFiZeroOnly; + UINT_8 aucReserved1[56]; +} EVENT_NIC_CAPABILITY_T, *P_EVENT_NIC_CAPABILITY_T; + +typedef struct _EVENT_NIC_CAPABILITY_V2_T { + UINT_16 u2TotalElementNum; + UINT_8 aucReserved[2]; + UINT_8 aucBuffer[0]; +} EVENT_NIC_CAPABILITY_V2_T, *P_EVENT_NIC_CAPABILITY_V2_T; + +typedef struct _NIC_CAPABILITY_V2_ELEMENT { + UINT_32 tag_type; /* NIC_CAPABILITY_V2_TAG_T */ + UINT_32 body_len; + UINT_8 aucbody[0]; +} NIC_CAPABILITY_V2_ELEMENT, *P_NIC_CAPABILITY_V2_ELEMENT; + +typedef WLAN_STATUS(*NIC_CAP_V2_ELEMENT_HDLR)(P_ADAPTER_T prAdapter, P_UINT_8 buff); +typedef struct _NIC_CAPABILITY_V2_REF_TABLE_T { + UINT_32 tag_type; /* NIC_CAPABILITY_V2_TAG_T */ + NIC_CAP_V2_ELEMENT_HDLR hdlr; +} NIC_CAPABILITY_V2_REF_TABLE_T, *P_NIC_CAPABILITY_V2_REF_TABLE_T; + +typedef enum _NIC_CAPABILITY_V2_TAG_T { + TAG_CAP_TX_RESOURCE = 0x0, + TAG_CAP_TX_EFUSEADDRESS = 0x1, + TAG_CAP_COEX_FEATURE = 0x2, + TAG_CAP_SINGLE_SKU = 0x3, +#if CFG_TCP_IP_CHKSUM_OFFLOAD + TAG_CAP_CSUM_OFFLOAD = 0x4, +#endif + TAG_CAP_R_MODE_CAP = 0xf, + TAG_CAP_MAC_EFUSE_OFFSET = 0x14, + TAG_CAP_TOTAL +} NIC_CAPABILITY_V2_TAG_T; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +typedef struct _NIC_CSUM_OFFLOAD_T { + UINT_8 ucIsSupportCsumOffload; /* 1: Support, 0: Not Support */ + UINT_8 acReseved[3]; +} NIC_CSUM_OFFLOAD_T, *P_NIC_CSUM_OFFLOAD_T; +#endif + +typedef struct _NIC_COEX_FEATURE_T { + UINT_32 u4FddMode; /* TRUE for COEX FDD mode */ +} NIC_COEX_FEATURE_T, *P_NIC_COEX_FEATURE_T; + +typedef struct _NIC_EFUSE_ADDRESS_T { + UINT_32 u4EfuseStartAddress; /* Efuse Start Address */ + UINT_32 u4EfuseEndAddress; /* Efuse End Address */ +} NIC_EFUSE_ADDRESS_T, *P_NIC_EFUSE_ADDRESS_T; + +struct _NIC_EFUSE_OFFSET_T { + UINT_32 u4TotalItem; /* Efuse offset items */ + UINT_32 u4WlanMacAddr; /* Efuse Offset 1 */ +}; + + +struct _CAP_R_MODE_CAP_T { + UINT_8 ucRModeOnlyFlag; /* 1: R mode only, 0:not R mode only */ + UINT_8 ucRModeReserve[7]; /* reserve fields for future use */ +}; + +typedef struct _NIC_TX_RESOURCE_T { + UINT_32 u4McuTotalResource; /* the total usable resource for MCU port */ + UINT_32 u4McuResourceUnit; /* the unit of a MCU resource */ + UINT_32 u4LmacTotalResource; /* the total usable resource for LMAC port */ + UINT_32 u4LmacResourceUnit; /* the unit of a LMAC resource */ +} NIC_TX_RESOURCE_T, *P_NIC_TX_RESOURCE_T; + +/* 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; + +/* event of add key done for port control */ +typedef struct _EVENT_ADD_KEY_DONE_INFO { + UINT_8 ucBSSIndex; + UINT_8 ucReserved; + UINT_8 aucStaAddr[6]; +} EVENT_ADD_KEY_DONE_INFO, *P_EVENT_ADD_KEY_DONE_INFO; + +typedef struct _EVENT_PMKID_CANDIDATE_LIST_T { + UINT_32 u4Version; /*!< Version */ + UINT_32 u4NumCandidates; /*!< How many candidates follow */ + PARAM_PMKID_CANDIDATE_T arCandidateList[1]; +} EVENT_PMKID_CANDIDATE_LIST_T, *P_EVENT_PMKID_CANDIDATE_LIST_T; + +typedef struct _EVENT_CMD_RESULT { + UINT_8 ucCmdID; + UINT_8 ucStatus; + UINT_8 aucReserved[2]; +} EVENT_CMD_RESULT, *P_EVENT_CMD_RESULT; + +/* CMD_ID_ACCESS_REG & EVENT_ID_ACCESS_REG */ +typedef struct _CMD_ACCESS_REG { + UINT_32 u4Address; + UINT_32 u4Data; +} CMD_ACCESS_REG, *P_CMD_ACCESS_REG; + +#define COEX_CTRL_BUF_LEN 460 +#define COEX_INFO_LEN 115 + +/* CMD_COEX_CTRL & EVENT_COEX_CTRL */ +/************************************************/ +/* UINT_32 u4SubCmd : Coex Ctrl Sub Command */ +/* UINT_8 aucBuffer : Reserve for Sub Command */ +/* Data Structure */ +/************************************************/ +struct CMD_COEX_CTRL { + UINT_32 u4SubCmd; + UINT_8 aucBuffer[COEX_CTRL_BUF_LEN]; +}; + +/* Sub Command Data Structure */ +/************************************************/ +/* UINT_32 u4IsoPath : WF Path (WF0/WF1) */ +/* UINT_32 u4Channel : WF Channel */ +/* UINT_32 u4Band : WF Band (Band0/Band1)(Not used now) */ +/* UINT_32 u4Isolation : Isolation value */ +/************************************************/ +struct CMD_COEX_ISO_DETECT { + UINT_32 u4IsoPath; + UINT_32 u4Channel; + /*UINT_32 u4Band;*/ + UINT_32 u4Isolation; +}; + + +/************************************************/ +/* PCHAR pucCoexInfo : CoexInfoTag */ +/************************************************/ +struct CMD_COEX_GET_INFO { + UINT_32 u4CoexInfo[COEX_INFO_LEN]; +}; + +/* Use for Coex Ctrl Cmd */ +enum ENUM_COEX_CTRL_CMD { + ENUM_COEX_CTRL_ISO_DETECT = 1, + ENUM_COEX_CTRL_GET_INFO = 2, + ENUM_COEX_CTRL_NUM +}; + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +/* CMD_ID_CAL_BACKUP_IN_HOST_V2 & EVENT_ID_CAL_BACKUP_IN_HOST_V2 */ +typedef struct _CMD_CAL_BACKUP_STRUCT_V2_T { + UINT_8 ucReason; + UINT_8 ucAction; + UINT_8 ucNeedResp; + UINT_8 ucFragNum; + UINT_8 ucRomRam; + UINT_32 u4ThermalValue; + UINT_32 u4Address; + UINT_32 u4Length; + UINT_32 u4RemainLength; + UINT_32 au4Buffer[PARAM_CAL_DATA_DUMP_MAX_NUM]; +} CMD_CAL_BACKUP_STRUCT_V2_T, *P_CMD_CAL_BACKUP_STRUCT_V2_T; + +typedef struct _CMD_CAL_BACKUP_STRUCT_T { + UINT_8 ucReason; + UINT_8 ucAction; + UINT_8 ucNeedResp; + UINT_8 ucFragNum; + UINT_8 ucRomRam; + UINT_32 u4ThermalValue; + UINT_32 u4Address; + UINT_32 u4Length; + UINT_32 u4RemainLength; +} CMD_CAL_BACKUP_STRUCT_T, *P_CMD_CAL_BACKUP_STRUCT_T; +#endif + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +typedef struct _CMD_ACCESS_CHN_LOAD { + UINT_32 u4Address; + UINT_32 u4Data; + UINT_16 u2Channel; + UINT_8 aucReserved[2]; +} CMD_ACCESS_CHN_LOAD, *P_ACCESS_CHN_LOAD; + +typedef struct _CMD_GET_LTE_SAFE_CHN_T { + UINT_8 ucIndex; + UINT_8 ucFlags; + UINT_8 aucReserved0[2]; + UINT_8 aucReserved2[16]; +} CMD_GET_LTE_SAFE_CHN_T, *P_CMD_GET_LTE_SAFE_CHN_T; +#endif + +/* CMD_DUMP_MEMORY */ +typedef struct _CMD_DUMP_MEM { + UINT_32 u4Address; + UINT_32 u4Length; + UINT_32 u4RemainLength; +#if CFG_SUPPORT_QA_TOOL + UINT_32 u4IcapContent; +#endif /* CFG_SUPPORT_QA_TOOL */ + 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; +#if CFG_SUPPORT_QA_TOOL + UINT_32 eIcapContent; +#endif /* CFG_SUPPORT_QA_TOOL */ + UINT_8 ucFragNum; + UINT_8 aucBuffer[1]; +} EVENT_DUMP_MEM_T, *P_EVENT_DUMP_MEM_T; + +#if CFG_SUPPORT_QA_TOOL +typedef struct _CMD_ACCESS_RX_STAT { + UINT_32 u4SeqNum; + UINT_32 u4TotalNum; +} CMD_ACCESS_RX_STAT, *P_CMD_ACCESS_RX_STAT; + +typedef struct _EVENT_ACCESS_RX_STAT { + UINT_32 u4SeqNum; + UINT_32 u4TotalNum; + UINT_32 au4Buffer[1]; +} EVENT_ACCESS_RX_STAT, *P_EVENT_ACCESS_RX_STAT; + +#if CFG_SUPPORT_TX_BF +typedef union _CMD_TXBF_ACTION_T { + PROFILE_TAG_READ_T rProfileTagRead; + PROFILE_TAG_WRITE_T rProfileTagWrite; + PROFILE_DATA_READ_T rProfileDataRead; + PROFILE_DATA_WRITE_T rProfileDataWrite; + PROFILE_PN_READ_T rProfilePnRead; + PROFILE_PN_WRITE_T rProfilePnWrite; + TX_BF_SOUNDING_START_T rTxBfSoundingStart; + TX_BF_SOUNDING_STOP_T rTxBfSoundingStop; + TX_BF_TX_APPLY_T rTxBfTxApply; + TX_BF_PFMU_MEM_ALLOC_T rTxBfPfmuMemAlloc; + TX_BF_PFMU_MEM_RLS_T rTxBfPfmuMemRls; +} CMD_TXBF_ACTION_T, *P_CMD_TXBF_ACTION_T; + +#define CMD_DEVINFO_UPDATE_HDR_SIZE 8 +typedef struct _CMD_DEV_INFO_UPDATE_T { + UINT_8 ucOwnMacIdx; + UINT_8 ucReserve; + UINT_16 u2TotalElementNum; + UINT_8 ucAppendCmdTLV; + UINT_8 aucReserve[3]; + UINT_8 aucBuffer[0]; + /* CMD_DEVINFO_ACTIVE_T rCmdDevInfoActive; */ +} CMD_DEV_INFO_UPDATE_T, *P_CMD_DEV_INFO_UPDATE_T; + +#define CMD_BSSINFO_UPDATE_HDR_SIZE 8 +typedef struct _CMD_BSS_INFO_UPDATE_T { + UINT_8 ucBssIndex; + UINT_8 ucReserve; + UINT_16 u2TotalElementNum; + UINT_32 u4Reserve; + /* CMD_BSSINFO_BASIC_T rCmdBssInfoBasic; */ + UINT_8 aucBuffer[0]; +} CMD_BSS_INFO_UPDATE_T, *P_CMD_BSS_INFO_UPDATE_T; + +/* STA record command */ +#define CMD_STAREC_UPDATE_HDR_SIZE 8 +typedef struct _CMD_STAREC_UPDATE_T { + UINT_8 ucBssIndex; + UINT_8 ucWlanIdx; + UINT_16 u2TotalElementNum; + UINT_32 u4Reserve; + UINT_8 aucBuffer[0]; +} CMD_STAREC_UPDATE_T, *P_CMD_STAREC_UPDATE_T; + +typedef struct _EVENT_PFMU_TAG_READ_T { + PFMU_PROFILE_TAG1 ru4TxBfPFMUTag1; + PFMU_PROFILE_TAG2 ru4TxBfPFMUTag2; +} EVENT_PFMU_TAG_READ_T, *P_EVENT_PFMU_TAG_READ_T; + +#if CFG_SUPPORT_MU_MIMO +typedef struct _EVENT_HQA_GET_QD { + UINT_32 u4EventId; + UINT_32 au4RawData[14]; +} EVENT_HQA_GET_QD, *P_EVENT_HQA_GET_QD; + +typedef struct _EVENT_HQA_GET_MU_CALC_LQ { + UINT_32 u4EventId; + MU_STRUCT_LQ_REPORT rEntry; +} EVENT_HQA_GET_MU_CALC_LQ, *P_EVENT_HQA_GET_MU_CALC_LQ; + +typedef struct _EVENT_SHOW_GROUP_TBL_ENTRY { + UINT_32 u4EventId; + UINT_8 index; + UINT_8 numUser:2; + UINT_8 BW:2; + UINT_8 NS0:2; + UINT_8 NS1:2; + /* UINT_8 NS2:1; */ + /* UINT_8 NS3:1; */ + UINT_8 PFIDUser0; + UINT_8 PFIDUser1; + /* UINT_8 PFIDUser2; */ + /* UINT_8 PFIDUser3; */ + BOOLEAN fgIsShortGI; + BOOLEAN fgIsUsed; + BOOLEAN fgIsDisable; + UINT_8 initMcsUser0:4; + UINT_8 initMcsUser1:4; + /* UINT_8 initMcsUser2:4; */ + /* UINT_8 initMcsUser3:4; */ + UINT_8 dMcsUser0:4; + UINT_8 dMcsUser1:4; + /* UINT_8 dMcsUser2:4; */ + /* UINT_8 dMcsUser3:4; */ +} EVENT_SHOW_GROUP_TBL_ENTRY, *P_EVENT_SHOW_GROUP_TBL_ENTRY; + +typedef union _CMD_MUMIMO_ACTION_T { + UINT_8 ucMuMimoCategory; + UINT_8 aucRsv[3]; + union { + MU_GET_CALC_INIT_MCS_T rMuGetCalcInitMcs; + MU_SET_INIT_MCS_T rMuSetInitMcs; + MU_SET_CALC_LQ_T rMuSetCalcLq; + MU_GET_LQ_T rMuGetLq; + MU_SET_SNR_OFFSET_T rMuSetSnrOffset; + MU_SET_ZERO_NSS_T rMuSetZeroNss; + MU_SPEED_UP_LQ_T rMuSpeedUpLq; + MU_SET_MU_TABLE_T rMuSetMuTable; + MU_SET_GROUP_T rMuSetGroup; + MU_GET_QD_T rMuGetQd; + MU_SET_ENABLE_T rMuSetEnable; + MU_SET_GID_UP_T rMuSetGidUp; + MU_TRIGGER_MU_TX_T rMuTriggerMuTx; + } unMuMimoParam; +} CMD_MUMIMO_ACTION_T, *P_CMD_MUMIMO_ACTION_T; +#endif /* CFG_SUPPORT_MU_MIMO */ +#endif /* CFG_SUPPORT_TX_BF */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +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; + +typedef struct _CMD_FW_LOG_2_HOST_CTRL_T { + UINT_8 ucFwLog2HostCtrl; + UINT_8 ucMcuDest; +#if CFG_SUPPORT_FW_DBG_LEVEL_CTRL + UINT_8 ucFwLogLevel; + UINT_8 ucReserve; +#else + UINT_8 ucReserve[2]; +#endif + UINT_32 u4HostTimeSec; + UINT_32 u4HostTimeMSec; +} CMD_FW_LOG_2_HOST_CTRL_T, *P_CMD_FW_LOG_2_HOST_CTRL_T; + +typedef struct _CMD_CHIP_CONFIG_T { + UINT_16 u2Id; + UINT_8 ucType; + UINT_8 ucRespType; + UINT_16 u2MsgSize; + UINT_8 aucReserved0[2]; + UINT_8 aucCmd[CHIP_CONFIG_RESP_SIZE]; +} CMD_CHIP_CONFIG_T, *P_CMD_CHIP_CONFIG_T; + +/* 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_KEEP_FULL_PWR */ +struct CMD_KEEP_FULL_PWR_T { + UINT_8 ucEnable; + UINT_8 aucReserved[3]; +}; + +/* CMD_ID_POWER_SAVE_MODE */ +typedef struct _CMD_PS_PROFILE_T { + UINT_8 ucBssIndex; + UINT_8 ucPsProfile; + UINT_8 aucReserved[2]; +} CMD_PS_PROFILE_T, *P_CMD_PS_PROFILE_T; + +/* EVENT_LINK_QUALITY */ +#if 1 +typedef struct _LINK_QUALITY_ { + INT_8 cRssi; /* AIS Network. */ + INT_8 cLinkQuality; + UINT_16 u2LinkSpeed; /* TX rate1 */ + UINT_8 ucMediumBusyPercentage; /* Read clear */ + UINT_8 ucIsLQ0Rdy; /* Link Quality BSS0 Ready. */ +} LINK_QUALITY, *P_LINK_QUALITY; + +typedef struct _EVENT_LINK_QUALITY_V2 { + LINK_QUALITY rLq[BSSID_NUM]; +} EVENT_LINK_QUALITY_V2, *P_EVENT_LINK_QUALITY_V2; + +typedef struct _EVENT_LINK_QUALITY { + INT_8 cRssi; + INT_8 cLinkQuality; + UINT_16 u2LinkSpeed; + UINT_8 ucMediumBusyPercentage; +} EVENT_LINK_QUALITY, *P_EVENT_LINK_QUALITY; +#endif + +#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_INFO_T { + UINT_8 ucSleepyState; + UINT_8 aucReserved[3]; +} EVENT_SLEEPY_INFO_T, *P_EVENT_SLEEPY_INFO_T; + +typedef struct _EVENT_ACTIVATE_STA_REC_T { + UINT_8 aucMacAddr[6]; + UINT_8 ucStaRecIdx; + UINT_8 ucBssIndex; +} 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; + +#if (CFG_SUPPORT_DFS_MASTER == 1) +typedef enum _ENUM_REG_DOMAIN_T { + REG_DEFAULT = 0, + REG_JP_53, + REG_JP_56 +} ENUM_REG_DOMAIN_T, *P_ENUM_REG_DOMAIN_T; + +typedef struct _CMD_RDD_ON_OFF_CTRL_T { + UINT_8 ucDfsCtrl; + UINT_8 ucRddIdx; + UINT_8 ucRddInSel; + UINT_8 ucRegDomain; + UINT_8 ucRadarDetectMode; +} CMD_RDD_ON_OFF_CTRL_T, *P_CMD_RDD_ON_OFF_CTRL_T; +#endif + +/* 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 */ +#if (CFG_SUPPORT_SINGLE_SKU == 1) +typedef struct _CMD_SET_DOMAIN_INFO_V2_T { + UINT_32 u4CountryCode; + + 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]; + struct acctive_channel_list active_chs; +} CMD_SET_DOMAIN_INFO_V2_T, *P_CMD_SET_DOMAIN_INFO_V2_T; +#endif + +typedef struct _CMD_SET_DOMAIN_INFO_T { + UINT_16 u2CountryCode; + UINT_16 u2IsSetPassiveScan; + CMD_SUBBAND_INFO rSubBand[6]; + + UINT_8 uc2G4Bandwidth; /* CONFIG_BW_20_40M or CONFIG_BW_20M */ + UINT_8 uc5GBandwidth; /* CONFIG_BW_20_40M or CONFIG_BW_20M */ + UINT_8 aucReserved[2]; +} CMD_SET_DOMAIN_INFO_T, *P_CMD_SET_DOMAIN_INFO_T; + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +/* CMD_SET_PWR_LIMIT_TABLE */ +typedef struct _CMD_CHANNEL_POWER_LIMIT { + UINT_8 ucCentralCh; + INT_8 cPwrLimitCCK; + INT_8 cPwrLimit20; + INT_8 cPwrLimit40; + INT_8 cPwrLimit80; + INT_8 cPwrLimit160; + UINT_8 ucFlag; + UINT_8 aucReserved[1]; +} CMD_CHANNEL_POWER_LIMIT, *P_CMD_CHANNEL_POWER_LIMIT; + +typedef struct _CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T { + UINT_16 u2CountryCode; + UINT_8 ucCountryFlag; + UINT_8 ucNum; + UINT_8 aucReserved[4]; + CMD_CHANNEL_POWER_LIMIT rChannelPowerLimit[1]; +} CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T, *P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T; + +#if (CFG_SUPPORT_SINGLE_SKU == 1) +typedef struct _CMD_CHANNEL_POWER_LIMIT_V2 { + UINT_8 ucCentralCh; + UINT_8 ucReserved[3]; + + UINT_8 tx_pwr_dsss_cck; + UINT_8 tx_pwr_dsss_bpsk; + + UINT_8 tx_pwr_ofdm_bpsk; /* 6M, 9M */ + UINT_8 tx_pwr_ofdm_qpsk; /* 12M, 18M */ + UINT_8 tx_pwr_ofdm_16qam; /* 24M, 36M */ + UINT_8 tx_pwr_ofdm_48m; + UINT_8 tx_pwr_ofdm_54m; + + UINT_8 tx_pwr_ht20_bpsk; /* MCS0*/ + UINT_8 tx_pwr_ht20_qpsk; /* MCS1, MCS2*/ + UINT_8 tx_pwr_ht20_16qam; /* MCS3, MCS4*/ + UINT_8 tx_pwr_ht20_mcs5; /* MCS5*/ + UINT_8 tx_pwr_ht20_mcs6; /* MCS6*/ + UINT_8 tx_pwr_ht20_mcs7; /* MCS7*/ + + UINT_8 tx_pwr_ht40_bpsk; /* MCS0*/ + UINT_8 tx_pwr_ht40_qpsk; /* MCS1, MCS2*/ + UINT_8 tx_pwr_ht40_16qam; /* MCS3, MCS4*/ + UINT_8 tx_pwr_ht40_mcs5; /* MCS5*/ + UINT_8 tx_pwr_ht40_mcs6; /* MCS6*/ + UINT_8 tx_pwr_ht40_mcs7; /* MCS7*/ + UINT_8 tx_pwr_ht40_mcs32; /* MCS32*/ + + UINT_8 tx_pwr_vht20_bpsk; /* MCS0*/ + UINT_8 tx_pwr_vht20_qpsk; /* MCS1, MCS2*/ + UINT_8 tx_pwr_vht20_16qam; /* MCS3, MCS4*/ + UINT_8 tx_pwr_vht20_64qam; /* MCS5, MCS6*/ + UINT_8 tx_pwr_vht20_mcs7; + UINT_8 tx_pwr_vht20_mcs8; + UINT_8 tx_pwr_vht20_mcs9; + + UINT_8 tx_pwr_vht_40; + UINT_8 tx_pwr_vht_80; + UINT_8 tx_pwr_vht_160c; + UINT_8 tx_pwr_vht_160nc; + UINT_8 tx_pwr_lg_40; + UINT_8 tx_pwr_lg_80; + + UINT_8 tx_pwr_1ss_delta; + UINT_8 ucReserved_1[2]; +} CMD_CHANNEL_POWER_LIMIT_V2, *P_CMD_CHANNEL_POWER_LIMIT_V2; + +typedef struct _CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T { + UINT_8 ucNum; + UINT_8 eband; /*ENUM_BAND_T*/ + UINT_8 usReserved[2]; + UINT_32 countryCode; + CMD_CHANNEL_POWER_LIMIT_V2 rChannelPowerLimit[0]; +} CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T, *P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T; + +#define TX_PWR_LIMIT_SECTION_NUM 5 +#define TX_PWR_LIMIT_ELEMENT_NUM 7 +#define TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN 4 +#define TX_PWR_LIMIT_MAX_VAL 63 + + + +struct CHANNEL_TX_PWR_LIMIT { + UINT_8 ucChannel; + INT_8 rTxPwrLimitValue[TX_PWR_LIMIT_SECTION_NUM][TX_PWR_LIMIT_ELEMENT_NUM]; +}; + +struct TX_PWR_LIMIT_DATA { + UINT_32 countryCode; + UINT_32 ucChNum; + struct CHANNEL_TX_PWR_LIMIT *rChannelTxPwrLimit; +}; + +#endif + +#endif + +/* CMD_SET_IP_ADDRESS */ +typedef struct _IPV4_NETWORK_ADDRESS { + UINT_8 aucIpAddr[4]; +} IPV4_NETWORK_ADDRESS, *P_IPV4_NETWORK_ADDRESS; + +typedef struct _CMD_SET_NETWORK_ADDRESS_LIST { + UINT_8 ucBssIndex; + 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 u2PatternOffset; + 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_8 ucWlanIndex; + UINT_8 ucTxCount; + UINT_16 u2TxRate; + + UINT_8 ucFlag; + UINT_8 ucTid; + UINT_8 ucRspRate; + UINT_8 ucRateTableIdx; + + UINT_8 ucBandwidth; + UINT_8 ucTxPower; + UINT_8 aucReserved0[2]; + + UINT_32 u4TxDelay; + UINT_32 u4Timestamp; + UINT_32 u4AppliedFlag; + + UINT_8 aucRawTxS[28]; + + UINT_8 aucReserved1[32]; +} EVENT_TX_DONE_T, *P_EVENT_TX_DONE_T; + +typedef enum _ENUM_TXS_APPLIED_FLAG_T { + TX_FRAME_IN_AMPDU_FORMAT = 0, + TX_FRAME_EXP_BF, + TX_FRAME_IMP_BF, + TX_FRAME_PS_BIT +} ENUM_TXS_APPLIED_FLAG_T, *P_ENUM_TXS_APPLIED_FLAG_T; + +typedef enum _ENUM_TXS_CONTROL_FLAG_T { + TXS_WITH_ADVANCED_INFO = 0, + TXS_IS_EXIST +} ENUM_TXS_CONTROL_FLAG_T, *P_ENUM_TXS_CONTROL_FLAG_T; + +#if (CFG_SUPPORT_DFS_MASTER == 1) +typedef enum _ENUM_DFS_CTRL_T { + RDD_STOP = 0, + RDD_START, + RDD_DET_MODE, + RDD_RADAR_EMULATE, + RDD_START_TXQ +} ENUM_DFS_CTRL_T, *P_ENUM_DFS_CTRL_T; +#endif + +typedef struct _CMD_BSS_ACTIVATE_CTRL { + UINT_8 ucBssIndex; + UINT_8 ucActive; + UINT_8 ucNetworkType; + UINT_8 ucOwnMacAddrIndex; + UINT_8 aucBssMacAddr[6]; + UINT_8 ucBMCWlanIndex; + UINT_8 ucReserved; +} CMD_BSS_ACTIVATE_CTRL, *P_CMD_BSS_ACTIVATE_CTRL; + +typedef struct _CMD_SET_BSS_RLM_PARAM_T { + UINT_8 ucBssIndex; + 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 ucVhtChannelWidth; + UINT_8 ucVhtChannelFrequencyS1; + UINT_8 ucVhtChannelFrequencyS2; + UINT_16 u2VhtBasicMcsSet; + UINT_8 ucNss; +} CMD_SET_BSS_RLM_PARAM_T, *P_CMD_SET_BSS_RLM_PARAM_T; + +typedef struct _CMD_SET_BSS_INFO { + UINT_8 ucBssIndex; + 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_16 u2HwDefaultFixedRateCode; + UINT_8 ucNonHTBasicPhyType; /* For Slot Time and CWmin */ + UINT_8 ucAuthMode; + UINT_8 ucEncStatus; + UINT_8 ucPhyTypeSet; + UINT_8 ucWapiMode; + UINT_8 ucIsApMode; + UINT_8 ucBMCWlanIndex; + UINT_8 ucHiddenSsidMode; + UINT_8 ucDisconnectDetectTh; + UINT_32 u4PrivateData; + CMD_SET_BSS_RLM_PARAM_T rBssRlmParam; + UINT_8 ucDBDCBand; + UINT_8 ucWmmSet; + UINT_8 ucDBDCAction; + UINT_8 ucNss; + UINT_8 aucReserved[20]; +} CMD_SET_BSS_INFO, *P_CMD_SET_BSS_INFO; + +typedef enum _ENUM_RTS_POLICY_T { + RTS_POLICY_AUTO, + RTS_POLICY_STATIC_BW, + RTS_POLICY_DYNAMIC_BW, + RTS_POLICY_LEGACY, + RTS_POLICY_NO_RTS +} ENUM_RTS_POLICY; + +typedef struct _CMD_UPDATE_STA_RECORD_T { + UINT_8 ucStaIndex; + UINT_8 ucStaType; + /* This field should assign at create and keep consistency for update usage */ + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + + UINT_16 u2AssocId; + UINT_16 u2ListenInterval; + UINT_8 ucBssIndex; /* This field should assign at create and keep consistency for update usage */ + 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 aucReserved1[1]; + + UINT_8 aucRxMcsBitmask[10]; + UINT_16 u2RxHighestSupportedRate; + UINT_32 u4TxRateInfo; + + UINT_16 u2HtCapInfo; + UINT_16 u2HtExtendedCap; + UINT_32 u4TxBeamformingCap; + + UINT_8 ucAmpduParam; + 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 ucWlanIndex; /* This field should assign at create and keep consistency for update usage */ + UINT_8 ucBMCWlanIndex; /* This field should assign at create and keep consistency for update usage */ + + UINT_32 u4VhtCapInfo; + UINT_16 u2VhtRxMcsMap; + UINT_16 u2VhtRxHighestSupportedDataRate; + UINT_16 u2VhtTxMcsMap; + UINT_16 u2VhtTxHighestSupportedDataRate; + UINT_8 ucRtsPolicy; /* 0: auto 1: Static BW 2: Dynamic BW 3: Legacy 7: WoRts */ + UINT_8 ucVhtOpMode; /* VHT operating mode, bit 7: Rx NSS Type, bit 4-6, Rx NSS, bit 0-1: Channel Width */ + + UINT_8 ucTrafficDataType; /* 0: auto 1: data 2: video 3: voice */ + UINT_8 ucTxGfMode; + UINT_8 ucTxSgiMode; + UINT_8 ucTxStbcMode; + UINT_16 u2HwDefaultFixedRateCode; + UINT_8 ucTxAmpdu; + UINT_8 ucRxAmpdu; + UINT_32 u4FixedPhyRate; /* */ + UINT_16 u2MaxLinkSpeed; /* unit is 0.5 Mbps */ + UINT_16 u2MinLinkSpeed; + + UINT_32 u4Flags; + + UINT_8 ucTxBaSize; + UINT_8 ucRxBaSize; + UINT_8 aucReserved3[2]; + + TXBF_PFMU_STA_INFO rTxBfPfmuInfo; + + UINT_8 ucTxAmsduInAmpdu; + UINT_8 ucRxAmsduInAmpdu; + UINT_8 aucReserved5[2]; + + UINT_32 u4TxMaxAmsduInAmpduLen; + /* UINT_8 aucReserved4[30]; */ +} CMD_UPDATE_STA_RECORD_T, *P_CMD_UPDATE_STA_RECORD_T; + +typedef struct _CMD_REMOVE_STA_RECORD_T { + UINT_8 ucActionType; + UINT_8 ucStaIndex; + UINT_8 ucBssIndex; + UINT_8 ucReserved; +} CMD_REMOVE_STA_RECORD_T, *P_CMD_REMOVE_STA_RECORD_T; + +typedef struct _CMD_INDICATE_PM_BSS_CREATED_T { + UINT_8 ucBssIndex; + 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 ucBssIndex; + 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 ucBssIndex; + UINT_8 aucReserved[3]; +} CMD_INDICATE_PM_BSS_ABORT, *P_CMD_INDICATE_PM_BSS_ABORT; + +typedef struct _CMD_BEACON_TEMPLATE_UPDATE { +/* 0: update randomly, 1: update all, 2: delete all (1 and 2 will update directly without search) */ + UINT_8 ucUpdateMethod; + UINT_8 ucBssIndex; + UINT_8 aucReserved[2]; + UINT_16 u2Capability; + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; +} CMD_BEACON_TEMPLATE_UPDATE, *P_CMD_BEACON_TEMPLATE_UPDATE; + +typedef struct _CMD_SET_WMM_PS_TEST_STRUCT_T { + UINT_8 ucBssIndex; + UINT_8 bmfgApsdEnAc; /* b0~3: trigger-en AC0~3. b4~7: delivery-en AC0~3 */ + UINT_8 ucIsEnterPsAtOnce; /* enter PS immediately without 5 second guard after connected */ + UINT_8 ucIsDisableUcTrigger; /* not to trigger UC on beacon TIM is matched (under U-APSD) */ +} CMD_SET_WMM_PS_TEST_STRUCT_T, *P_CMD_SET_WMM_PS_TEST_STRUCT_T; + +/* Definition for CHANNEL_INFO.ucBand: + * 0: Reserved + * 1: BAND_2G4 + * 2: BAND_5G + * Others: Reserved + */ +typedef struct _CHANNEL_INFO_T { + UINT_8 ucBand; + UINT_8 ucChannelNum; +} CHANNEL_INFO_T, *P_CHANNEL_INFO_T; + +typedef struct _CMD_SCAN_REQ_T { + UINT_8 ucSeqNum; + UINT_8 ucBssIndex; + UINT_8 ucScanType; + UINT_8 ucSSIDType; /* BIT(0) wildcard / BIT(1) P2P-wildcard / BIT(2) specific */ + UINT_8 ucSSIDLength; + UINT_8 ucNumProbeReq; + UINT_16 u2ChannelMinDwellTime; + UINT_16 u2ChannelDwellTime; + UINT_16 u2TimeoutValue; + UINT_8 aucSSID[32]; + UINT_8 ucChannelType; + UINT_8 ucChannelListNum; + UINT_8 aucReserved[2]; + 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 ucBssIndex; + UINT_8 ucScanType; + UINT_8 ucSSIDType; + UINT_8 ucSSIDNum; + UINT_8 ucNumProbeReq; + UINT_8 aucReserved[2]; /*total 8*/ + PARAM_SSID_T arSSID[4]; /*(4+32)*4 = 144, total 152*/ + UINT_16 u2ProbeDelayTime; + UINT_16 u2ChannelDwellTime; + UINT_16 u2TimeoutValue; + UINT_8 ucChannelType; + UINT_8 ucChannelListNum; /*total 160*/ + CHANNEL_INFO_T arChannelList[32]; /*total 160+64=224*/ + UINT_16 u2IELen; /*total 226*/ + UINT_8 aucIE[MAX_IE_LENGTH]; /*total 826*/ + UINT_8 ucScnCtrlFlag; + UINT_8 aucReserved2; /*total 828*/ + /*Extend for Scan cmds*/ + CHANNEL_INFO_T arChannelListExtend[32]; /*total 892*/ + UINT_8 arPerChannelControl[32]; + UINT_8 arPerExtendChannelControl[32]; /*total 956*/ + UINT_8 ucScanChannelListenTime; /*total 957*/ + UINT_8 aucReserved3[3]; /*total 960, max 1024*/ +} CMD_SCAN_REQ_V2, *P_CMD_SCAN_REQ_V2; + +typedef struct _CMD_SCAN_CANCEL_T { + UINT_8 ucSeqNum; + UINT_8 ucIsExtChannel; /* For P2P channel extension. */ + UINT_8 aucReserved[2]; +} CMD_SCAN_CANCEL, *P_CMD_SCAN_CANCEL; + +/* 20150107 Daniel Added complete channels number in the scan done event */ +/* before*/ +/* +*typedef struct _EVENT_SCAN_DONE_T { +* UINT_8 ucSeqNum; +* UINT_8 ucSparseChannelValid; +* CHANNEL_INFO_T rSparseChannel; +*} EVENT_SCAN_DONE, *P_EVENT_SCAN_DONE; +*/ +/* after */ + +#define EVENT_SCAN_DONE_CHANNEL_NUM_MAX 64 +typedef struct _EVENT_SCAN_DONE_T { + UINT_8 ucSeqNum; + UINT_8 ucSparseChannelValid; + CHANNEL_INFO_T rSparseChannel; + /*scan done version #2 */ + UINT_8 ucCompleteChanCount; + UINT_8 ucCurrentState; + UINT_8 ucScanDoneVersion; + /*scan done version #3 */ + UINT_8 ucReserved; + UINT_32 u4ScanDurBcnCnt; + UINT_8 fgIsPNOenabled; + UINT_8 aucReserving[3]; + /*channel idle count # Mike */ + UINT_8 ucSparseChannelArrayValidNum; + UINT_8 aucReserved[3]; + UINT_8 aucChannelNum[EVENT_SCAN_DONE_CHANNEL_NUM_MAX]; + /* Idle format for au2ChannelIdleTime */ + /* 0: first bytes: idle time(ms) 2nd byte: dwell time(ms) */ + /* 1: first bytes: idle time(8ms) 2nd byte: dwell time(8ms) */ + /* 2: dwell time (16us) */ + UINT_16 au2ChannelIdleTime[EVENT_SCAN_DONE_CHANNEL_NUM_MAX]; + /* B0: Active/Passive B3-B1: Idle format */ + UINT_8 aucChannelFlag[EVENT_SCAN_DONE_CHANNEL_NUM_MAX]; + UINT_8 aucChannelMDRDYCnt[EVENT_SCAN_DONE_CHANNEL_NUM_MAX]; + +} EVENT_SCAN_DONE, *P_EVENT_SCAN_DONE; + +#if CFG_SUPPORT_BATCH_SCAN +typedef struct _CMD_BATCH_REQ_T { + UINT_8 ucSeqNum; + UINT_8 ucNetTypeIndex; + UINT_8 ucCmd; /* Start/ Stop */ + UINT_8 ucMScan; /* an integer number of scans per batch */ + UINT_8 ucBestn; /* an integer number of the max AP to remember per scan */ + UINT_8 ucRtt; /* an integer number of highest-strength AP for which we'd */ + /* like approximate distance reported */ + UINT_8 ucChannel; /* channels */ + UINT_8 ucChannelType; + UINT_8 ucChannelListNum; + UINT_8 aucReserved[3]; + UINT_32 u4Scanfreq; /* an integer number of seconds between scans */ + CHANNEL_INFO_T arChannelList[32]; /* channels */ +} CMD_BATCH_REQ_T, *P_CMD_BATCH_REQ_T; + +typedef struct _EVENT_BATCH_RESULT_ENTRY_T { + UINT_8 aucBssid[MAC_ADDR_LEN]; + UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; + UINT_8 ucSSIDLen; + INT_8 cRssi; + UINT_32 ucFreq; + UINT_32 u4Age; + UINT_32 u4Dist; + UINT_32 u4Distsd; +} EVENT_BATCH_RESULT_ENTRY_T, *P_EVENT_BATCH_RESULT_ENTRY_T; + +typedef struct _EVENT_BATCH_RESULT_T { + UINT_8 ucScanCount; + UINT_8 aucReserved[3]; + EVENT_BATCH_RESULT_ENTRY_T arBatchResult[12]; /* Must be the same with SCN_BATCH_STORE_MAX_NUM */ +} EVENT_BATCH_RESULT_T, *P_EVENT_BATCH_RESULT_T; +#endif + +typedef struct _CMD_CH_PRIVILEGE_T { + UINT_8 ucBssIndex; + UINT_8 ucTokenID; + UINT_8 ucAction; + UINT_8 ucPrimaryChannel; + UINT_8 ucRfSco; + UINT_8 ucRfBand; + UINT_8 ucRfChannelWidth; /* To support 80/160MHz bandwidth */ + UINT_8 ucRfCenterFreqSeg1; /* To support 80/160MHz bandwidth */ + UINT_8 ucRfCenterFreqSeg2; /* To support 80/160MHz bandwidth */ + UINT_8 ucReqType; + UINT_8 ucDBDCBand; + UINT_8 aucReserved; + UINT_32 u4MaxInterval; /* In unit of ms */ + UINT_8 aucReserved2[8]; +} CMD_CH_PRIVILEGE_T, *P_CMD_CH_PRIVILEGE_T; + +typedef struct _CMD_TX_PWR_T { + INT_8 cTxPwr2G4Cck; /* signed, in unit of 0.5dBm */ + INT_8 cTxPwr2G4Dsss; /* signed, in unit of 0.5dBm */ + INT_8 acReserved[2]; + + 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_TX_AC_PWR_T { + INT_8 ucBand; +#if 0 + INT_8 c11AcTxPwr_BPSK; + INT_8 c11AcTxPwr_QPSK; + INT_8 c11AcTxPwr_16QAM; + INT_8 c11AcTxPwr_MCS5_MCS6; + INT_8 c11AcTxPwr_MCS7; + INT_8 c11AcTxPwr_MCS8; + INT_8 c11AcTxPwr_MCS9; + INT_8 c11AcTxPwrVht40_OFFSET; + INT_8 c11AcTxPwrVht80_OFFSET; + INT_8 c11AcTxPwrVht160_OFFSET; +#else + AC_PWR_SETTING_STRUCT rAcPwr; +#endif +} CMD_TX_AC_PWR_T, *P_CMD_TX_AC_PWR_T; + +typedef struct _CMD_RSSI_PATH_COMPASATION_T { + INT_8 c2GRssiCompensation; + INT_8 c5GRssiCompensation; +} CMD_RSSI_PATH_COMPASATION_T, *P_CMD_RSSI_PATH_COMPASATION_T; +typedef struct _CMD_5G_PWR_OFFSET_T { + INT_8 cOffsetBand0; /* 4.915-4.980G */ + INT_8 cOffsetBand1; /* 5.000-5.080G */ + INT_8 cOffsetBand2; /* 5.160-5.180G */ + INT_8 cOffsetBand3; /* 5.200-5.280G */ + INT_8 cOffsetBand4; /* 5.300-5.340G */ + INT_8 cOffsetBand5; /* 5.500-5.580G */ + INT_8 cOffsetBand6; /* 5.600-5.680G */ + INT_8 cOffsetBand7; /* 5.700-5.825G */ +} CMD_5G_PWR_OFFSET_T, *P_CMD_5G_PWR_OFFSET_T; + +typedef struct _CMD_PWR_PARAM_T { + UINT_32 au4Data[28]; + UINT_32 u4RefValue1; + UINT_32 u4RefValue2; +} CMD_PWR_PARAM_T, *P_CMD_PWR_PARAM_T; + +typedef struct _CMD_PHY_PARAM_T { + UINT_8 aucData[144]; /* eFuse content */ +} CMD_PHY_PARAM_T, *P_CMD_PHY_PARAM_T; + +typedef struct _CMD_AUTO_POWER_PARAM_T { + UINT_8 ucType; /* 0: Disable 1: Enalbe 0x10: Change parameters */ + UINT_8 ucBssIndex; + 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 _CMD_DBDC_SETTING_T { + UINT_8 ucDbdcEn; + UINT_8 ucWmmBandBitmap; + UINT_8 ucUpdateSettingNextChReq; + UINT_8 aucReserved1; + UINT_8 aucReserved2[32]; +} CMD_DBDC_SETTING_T, *P_CMD_DBDC_SETTING_T; + +typedef struct _EVENT_CH_PRIVILEGE_T { + UINT_8 ucBssIndex; + UINT_8 ucTokenID; + UINT_8 ucStatus; + UINT_8 ucPrimaryChannel; + UINT_8 ucRfSco; + UINT_8 ucRfBand; + UINT_8 ucRfChannelWidth; /* To support 80/160MHz bandwidth */ + UINT_8 ucRfCenterFreqSeg1; /* To support 80/160MHz bandwidth */ + UINT_8 ucRfCenterFreqSeg2; /* To support 80/160MHz bandwidth */ + UINT_8 ucReqType; + UINT_8 ucDBDCBand; + UINT_8 aucReserved; + UINT_32 u4GrantInterval; /* In unit of ms */ + UINT_8 aucReserved2[8]; +} EVENT_CH_PRIVILEGE_T, *P_EVENT_CH_PRIVILEGE_T; + +#if (CFG_SUPPORT_DFS_MASTER == 1) +typedef struct _LONG_PULSE_BUFFER_T { + UINT_32 u4LongStartTime; + UINT_16 u2LongPulseWidth; +} LONG_PULSE_BUFFER_T, *PLONG_PULSE_BUFFER_T; + +typedef struct _PERIODIC_PULSE_BUFFER_T { + UINT_32 u4PeriodicStartTime; + UINT_16 u2PeriodicPulseWidth; + INT_16 i2PeriodicPulsePower; +} PERIODIC_PULSE_BUFFER_T, *PPERIODIC_PULSE_BUFFER_T; + +typedef struct _EVENT_RDD_REPORT_T { + UINT_8 ucRadarReportMode; /*0: Only report radar detected; 1: Add parameter reports*/ + UINT_8 ucRddIdx; + UINT_8 ucLongDetected; + UINT_8 ucPeriodicDetected; + UINT_8 ucLPBNum; + UINT_8 ucPPBNum; + UINT_8 ucLPBPeriodValid; + UINT_8 ucLPBWidthValid; + UINT_8 ucPRICountM1; + UINT_8 ucPRICountM1TH; + UINT_8 ucPRICountM2; + UINT_8 ucPRICountM2TH; + UINT_32 u4PRI1stUs; + LONG_PULSE_BUFFER_T arLpbContent[32]; + PERIODIC_PULSE_BUFFER_T arPpbContent[32]; +} EVENT_RDD_REPORT_T, *P_EVENT_RDD_REPORT_T; +#endif + +#if (CFG_WOW_SUPPORT == 1) +/* event of wake up reason */ +struct _EVENT_WAKEUP_REASON_INFO { + UINT_8 reason; + UINT_8 aucReserved[3]; +}; +#endif + +typedef struct _EVENT_BSS_BEACON_TIMEOUT_T { + UINT_8 ucBssIndex; + UINT_8 ucReasonCode; + UINT_8 aucReserved[2]; +} EVENT_BSS_BEACON_TIMEOUT_T, *P_EVENT_BSS_BEACON_TIMEOUT_T; + +typedef struct _EVENT_STA_AGING_TIMEOUT_T { + UINT_8 ucStaRecIdx; + UINT_8 aucReserved[3]; +} EVENT_STA_AGING_TIMEOUT_T, *P_EVENT_STA_AGING_TIMEOUT_T; + +typedef struct _EVENT_NOA_TIMING_T { + UINT_8 ucIsInUse; /* 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 ucBssIndex; + UINT_8 aucReserved[2]; + UINT_8 ucEnableOppPS; + 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 ucBssIndex; + 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 _EVENT_DEBUG_MSG_T { + UINT_16 u2DebugMsgId; + UINT_8 ucMsgType; + UINT_8 ucFlags; /* unused */ + UINT_32 u4Value; /* memory addre or ... */ + UINT_16 u2MsgSize; + UINT_8 aucReserved0[2]; + UINT_8 aucMsg[1]; +} EVENT_DEBUG_MSG_T, *P_EVENT_DEBUG_MSG_T; + +typedef struct _CMD_EDGE_TXPWR_LIMIT_T { + INT_8 cBandEdgeMaxPwrCCK; + INT_8 cBandEdgeMaxPwrOFDM20; + INT_8 cBandEdgeMaxPwrOFDM40; + INT_8 cBandEdgeMaxPwrOFDM80; +} CMD_EDGE_TXPWR_LIMIT_T, *P_CMD_EDGE_TXPWR_LIMIT_T; + +typedef struct _CMD_POWER_OFFSET_T { + UINT_8 ucBand; /*1:2.4G ; 2:5G */ + UINT_8 ucSubBandOffset[MAX_SUBBAND_NUM_5G]; /*the max num subband is 5G, devide with 8 subband */ + UINT_8 aucReverse[3]; + +} CMD_POWER_OFFSET_T, *P_CMD_POWER_OFFSET_T; + +typedef struct _CMD_NVRAM_SETTING_T { + + WIFI_CFG_PARAM_STRUCT rNvramSettings; + +} CMD_NVRAM_SETTING_T, *P_CMD_NVRAM_SETTING_T; + +#if CFG_SUPPORT_TDLS +typedef struct _CMD_TDLS_CH_SW_T { + BOOLEAN fgIsTDLSChSwProhibit; +} CMD_TDLS_CH_SW_T, *P_CMD_TDLS_CH_SW_T; +#endif + +#if CFG_SUPPORT_CSI +enum CSI_EVENT_TLV_TAG { + CSI_EVENT_IS_CCK, + CSI_EVENT_CBW, + CSI_EVENT_RSSI, + CSI_EVENT_SNR, + CSI_EVENT_BAND, + CSI_EVENT_CSI_NUM, + CSI_EVENT_CSI_I_DATA, + CSI_EVENT_CSI_Q_DATA, + CSI_EVENT_DBW, + CSI_EVENT_CH_IDX, + CSI_EVENT_TA, + CSI_EVENT_EXTRA_INFO, + CSI_EVENT_RX_MODE, + CSI_EVENT_RSVD1, + CSI_EVENT_RSVD2, + CSI_EVENT_RSVD3, + CSI_EVENT_RSVD4, + CSI_EVENT_TLV_TAG_NUM, +}; +#endif + +#if CFG_SUPPORT_ADVANCE_CONTROL +/* command type */ +#define CMD_ADV_CONTROL_SET (1<<15) +#define CMD_PTA_CONFIG_TYPE (0x1) +#define CMD_AFH_CONFIG_TYPE (0x2) +#define CMD_BA_CONFIG_TYPE (0x3) +#define CMD_GET_REPORT_TYPE (0x4) +#define CMD_NOISE_HISTOGRAM_TYPE (0x5) + +/* for PtaConfig field */ +#define CMD_PTA_CONFIG_PTA_EN (1<<0) +#define CMD_PTA_CONFIG_RW_EN (1<<1) +#define CMD_PTA_CONFIG_PTA_STAT_EN (1<<2) + +/* pta config related mask */ +#define CMD_PTA_CONFIG_PTA (1<<0) +#define CMD_PTA_CONFIG_RW (1<<1) +#define CMD_PTA_CONFIG_TXDATA_TAG (1<<2) +#define CMD_PTA_CONFIG_RXDATAACK_TAG (1<<3) +#define CMD_PTA_CONFIG_RX_NSW_TAG (1<<4) +#define CMD_PTA_CONFIG_TXACK_TAG (1<<5) +#define CMD_PTA_CONFIG_TXPROTFRAME_TAG (1<<6) +#define CMD_PTA_CONFIG_RXPROTFRAMEACK_TAG (1<<7) +#define CMD_PTA_CONFIG_TX_BMC_TAG (1<<8) +#define CMD_PTA_CONFIG_TX_BCN_TAG (1<<9) +#define CMD_PTA_CONFIG_RX_SP_TAG (1<<10) +#define CMD_PTA_CONFIG_TX_MGMT_TAG (1<<11) +#define CMD_PTA_CONFIG_RXMGMTACK_TAG (1<<12) +#define CMD_PTA_CONFIG_PTA_STAT (1<<13) +#define CMD_PTA_CONFIG_PTA_STAT_RESET (1<<14) + +/* for config PTA Tag */ +#define EVENT_CONFIG_PTA_OFFSET (0) +#define EVENT_CONFIG_PTA_FEILD (0x1) +#define EVENT_CONFIG_PTA_WIFI_OFFSET (12) +#define EVENT_CONFIG_PTA_WIFI_FEILD (0x1) +#define EVENT_CONFIG_PTA_BT_OFFSET (15) +#define EVENT_CONFIG_PTA_BT_FEILD (0x1) +#define EVENT_CONFIG_PTA_ARB_OFFSET (16) +#define EVENT_CONFIG_PTA_ARB_FEILD (0x1) + +#define EVENT_CONFIG_WIFI_GRANT_OFFSET (30) +#define EVENT_CONFIG_WIFI_GRANT_FEILD (0x1) +#define EVENT_CONFIG_WIFI_PRI_OFFSET (12) +#define EVENT_CONFIG_WIFI_PRI_FEILD (0xf) +#define EVENT_CONFIG_WIFI_TXREQ_OFFSET (8) +#define EVENT_CONFIG_WIFI_TXREQ_FEILD (0x1) +#define EVENT_CONFIG_WIFI_RXREQ_OFFSET (9) +#define EVENT_CONFIG_WIFI_RXREQ_FEILD (0x1) + +#define EVENT_CONFIG_BT_GRANT_OFFSET (29) +#define EVENT_CONFIG_BT_GRANT_FEILD (0x1) +#define EVENT_CONFIG_BT_PRI_OFFSET (4) +#define EVENT_CONFIG_BT_PRI_FEILD (0xf) +#define EVENT_CONFIG_BT_TXREQ_OFFSET (0) +#define EVENT_CONFIG_BT_TXREQ_FEILD (0x1) +#define EVENT_CONFIG_BT_RXREQ_OFFSET (1) +#define EVENT_CONFIG_BT_RXREQ_FEILD (0x1) + +#define EVENT_PTA_BTTRX_CNT_OFFSET (16) +#define EVENT_PTA_BTTRX_CNT_FEILD (0xFFFF) +#define EVENT_PTA_BTTRX_GRANT_CNT_OFFSET (0) +#define EVENT_PTA_BTTRX_GRANT_CNT_FEILD (0xFFFF) + +#define EVENT_PTA_WFTRX_CNT_OFFSET (16) +#define EVENT_PTA_WFTRX_CNT_FEILD (0xFFFF) +#define EVENT_PTA_WFTRX_GRANT_CNT_OFFSET (0) +#define EVENT_PTA_WFTRX_GRANT_CNT_FEILD (0xFFFF) + +#define EVENT_PTA_TX_ABT_CNT_OFFSET (16) +#define EVENT_PTA_TX_ABT_CNT_FEILD (0xFFFF) +#define EVENT_PTA_RX_ABT_CNT_OFFSET (0) +#define EVENT_PTA_RX_ABT_CNT_FEILD (0xFFFF) +typedef struct _CMD_PTA_CONFIG { + UINT_16 u2Type; + UINT_16 u2Len; + UINT_32 u4ConfigMask; + /* common usage in set/get */ + UINT_32 u4PtaConfig; + UINT_32 u4TxDataTag; + UINT_32 u4RxDataAckTag; + UINT_32 u4RxNswTag; + UINT_32 u4TxAckTag; + UINT_32 u4TxProtFrameTag; + UINT_32 u4RxProtFrameAckTag; + UINT_32 u4TxBMCTag; + UINT_32 u4TxBCNTag; + UINT_32 u4RxSPTag; + UINT_32 u4TxMgmtTag; + UINT_32 u4RxMgmtAckTag; + /* Only used in get */ + UINT_32 u4PtaWF0TxCnt; + UINT_32 u4PtaWF0RxCnt; + UINT_32 u4PtaWF0AbtCnt; + UINT_32 u4PtaWF1TxCnt; + UINT_32 u4PtaWF1RxCnt; + UINT_32 u4PtaWF1AbtCnt; + UINT_32 u4PtaBTTxCnt; + UINT_32 u4PtaBTRxCnt; + UINT_32 u4PtaBTAbtCnt; + UINT_32 u4GrantStat; + UINT_32 u4CoexMode; +} CMD_PTA_CONFIG_T, *P_CMD_PTA_CONFIG_T; + +/* get report related */ +enum _ENUM_GET_REPORT_ACTION_T { + CMD_GET_REPORT_ENABLE = 1, + CMD_GET_REPORT_DISABLE, + CMD_GET_REPORT_RESET, + CMD_GET_REPORT_GET, + CMD_SET_REPORT_SAMPLE_DUR, + CMD_SET_REPORT_SAMPLE_POINT, + CMD_SET_REPORT_TXTHRES, + CMD_SET_REPORT_RXTHRES, + CMD_GET_REPORT_ACTIONS +}; +#define EVENT_REPORT_OFDM_FCCA (16) +#define EVENT_REPORT_OFDM_FCCA_FEILD (0xffff) +#define EVENT_REPORT_CCK_FCCA (0) +#define EVENT_REPORT_CCK_FCCA_FEILD (0xffff) +#define EVENT_REPORT_OFDM_SIGERR (16) +#define EVENT_REPORT_OFDM_SIGERR_FEILD (0xffff) +#define EVENT_REPORT_CCK_SIGERR (0) +#define EVENT_REPORT_CCK_SIGERR_FEILD (0xffff) +struct CMD_GET_TRAFFIC_REPORT { + UINT_16 u2Type; + UINT_16 u2Len; + /* parameter */ + UINT_8 ucBand; + UINT_8 ucAction; + UINT_8 reserved[2]; + /* report 1 */ + UINT_32 u4FalseCCA; + UINT_32 u4HdrCRC; + UINT_32 u4PktSent; + UINT_32 u4PktRetried; + UINT_32 u4PktTxfailed; + UINT_32 u4RxMPDU; + UINT_32 u4RxFcs; + /* air time report */ + UINT_32 u4FetchSt; /* ms */ + UINT_32 u4FetchEd; /* ms */ + UINT_32 u4ChBusy; /* us */ + UINT_32 u4ChIdle; /* us */ + UINT_32 u4TxAirTime; /* us */ + UINT_32 u4RxAirTime; /* us */ + UINT_32 u4TimerDur; /* ms */ + UINT_32 u4FetchCost; /* us */ + INT_32 TimerDrift; /* ms */ + INT_16 u2SamplePoints; /* ms */ + INT_8 ucTxThres; /* ms */ + INT_8 ucRxThres; /* ms */ +}; + +typedef struct _CMD_ADV_CONFIG_HEADER { + UINT_16 u2Type; + UINT_16 u2Len; +} CMD_ADV_CONFIG_HEADER_T, *P_CMD_ADV_CONFIG_HEADER_T; + +/* noise histogram related */ +enum _ENUM_NOISE_HISTOGRAM_ACTION_T { + CMD_NOISE_HISTOGRAM_ENABLE = 1, + CMD_NOISE_HISTOGRAM_DISABLE, + CMD_NOISE_HISTOGRAM_RESET, + CMD_NOISE_HISTOGRAM_GET +}; +struct CMD_NOISE_HISTOGRAM_REPORT { + UINT_16 u2Type; + UINT_16 u2Len; + /* parameter */ + UINT_8 ucAction; + UINT_8 reserved[3]; + /* IPI_report */ + UINT_32 u4IPI0; /* Power <= -92 */ + UINT_32 u4IPI1; /* -92 < Power <= -89 */ + UINT_32 u4IPI2; /* -89 < Power <= -86 */ + UINT_32 u4IPI3; /* -86 < Power <= -83 */ + UINT_32 u4IPI4; /* -83 < Power <= -80 */ + UINT_32 u4IPI5; /* -80 < Power <= -75 */ + UINT_32 u4IPI6; /* -75 < Power <= -70 */ + UINT_32 u4IPI7; /* -70 < Power <= -65 */ + UINT_32 u4IPI8; /* -65 < Power <= -60 */ + UINT_32 u4IPI9; /* -60 < Power <= -55 */ + UINT_32 u4IPI10; /* -55 < Power */ +}; +#endif +typedef struct _CMD_SET_DEVICE_MODE_T { + UINT_16 u2ChipID; + UINT_16 u2Mode; +} CMD_SET_DEVICE_MODE_T, *P_CMD_SET_DEVICE_MODE_T; + +#if CFG_SUPPORT_RDD_TEST_MODE +typedef struct _CMD_RDD_CH_T { + UINT_8 ucRddTestMode; + UINT_8 ucRddShutCh; + UINT_8 ucRddStartCh; + UINT_8 ucRddStopCh; + UINT_8 ucRddDfs; + UINT_8 ucReserved; + UINT_8 ucReserved1; + UINT_8 ucReserved2; +} CMD_RDD_CH_T, *P_CMD_RDD_CH_T; + +typedef struct _EVENT_RDD_STATUS_T { + UINT_8 ucRddStatus; + UINT_8 aucReserved[3]; +} EVENT_RDD_STATUS_T, *P_EVENT_RDD_STATUS_T; +#endif + +typedef struct _EVENT_ICAP_STATUS_T { + UINT_8 ucRddStatus; + UINT_8 aucReserved[3]; + UINT_32 u4StartAddress; + UINT_32 u4IcapSieze; +#if CFG_SUPPORT_QA_TOOL + UINT_32 u4IcapContent; +#endif /* CFG_SUPPORT_QA_TOOL */ +} EVENT_ICAP_STATUS_T, *P_EVENT_ICAP_STATUS_T; + +#if CFG_SUPPORT_QA_TOOL +typedef struct _ADC_BUS_FMT_T { + UINT_32 u4Dcoc0Q:14; /* [13:0] */ + UINT_32 u4Dcoc0I:14; /* [27:14] */ + UINT_32 u4DbgData1:4; /* [31:28] */ + + UINT_32 u4Dcoc1Q:14; /* [45:32] */ + UINT_32 u4Dcoc1I:14; /* [46:59] */ + UINT_32 u4DbgData2:4; /* [63:60] */ + + UINT_32 u4DbgData3; /* [95:64] */ +} ADC_BUS_FMT_T, *P_ADC_BUS_FMT_T; + +typedef struct _IQC_BUS_FMT_T { + INT_32 u4Iqc0Q:14; /* [13:0] */ + INT_32 u4Iqc0I:14; /* [27:14] */ + INT_32 u4Na1:4; /* [31:28] */ + + INT_32 u4Iqc1Q:14; /* [45:32] */ + INT_32 u4Iqc1I:14; /* [59:46] */ + INT_32 u4Na2:4; /* [63:60] */ + + INT_32 u4Na3; /* [95:64] */ +} IQC_BUS_FMT_T, *P_IQC_BUS_FMT_T; + +typedef struct _IQC_160_BUS_FMT_T { + INT_32 u4Iqc0Q1:12; /* [11:0] */ + INT_32 u4Iqc0I1:12; /* [23:12] */ + UINT_32 u4Iqc0Q0P1:8; /* [31:24] */ + + INT_32 u4Iqc0Q0P2:4; /* [35:32] */ + INT_32 u4Iqc0I0:12; /* [47:36] */ + INT_32 u4Iqc1Q1:12; /* [59:48] */ + UINT_32 u4Iqc1I1P1:4; /* [63:60] */ + + INT_32 u4Iqc1I1P2:8; /* [71:64] */ + INT_32 u4Iqc1Q0:12; /* [83:72] */ + INT_32 u4Iqc1I0:12; /* [95:84] */ +} IQC_160_BUS_FMT_T, *P_IQC_160_BUS_FMT_T; + +typedef struct _SPECTRUM_BUS_FMT_T { + INT_32 u4DcocQ:12; /* [11:0] */ + INT_32 u4DcocI:12; /* [23:12] */ + INT_32 u4LpfGainIdx:4; /* [27:24] */ + INT_32 u4LnaGainIdx:2; /* [29:28] */ + INT_32 u4AssertData:2; /* [31:30] */ +} SPECTRUM_BUS_FMT_T, *P_SPECTRUM_BUS_FMT_T; + +typedef struct _PACKED_ADC_BUS_FMT_T { + UINT_32 u4AdcQ0T2:4; /* [19:16] */ + UINT_32 u4AdcQ0T1:4; /* [11:8] */ + UINT_32 u4AdcQ0T0:4; /* [3:0] */ + + UINT_32 u4AdcI0T2:4; /* [23:20] */ + UINT_32 u4AdcI0T1:4; /* [15:12] */ + UINT_32 u4AdcI0T0:4; /* [7:4] */ + + UINT_32 u4AdcQ0T5:4; /* [43:40] */ + UINT_32 u4AdcQ0T4:4; /* [35:32] */ + UINT_32 u4AdcQ0T3:4; /* [27:24] */ + + UINT_32 u4AdcI0T5:4; /* [47:44] */ + UINT_32 u4AdcI0T4:4; /* [39:36] */ + UINT_32 u4AdcI0T3:4; /* [31:28] */ + + UINT_32 u4AdcQ1T2:4; /* [19:16] */ + UINT_32 u4AdcQ1T1:4; /* [11:8] */ + UINT_32 u4AdcQ1T0:4; /* [3:0] */ + + UINT_32 u4AdcI1T2:4; /* [23:20] */ + UINT_32 u4AdcI1T1:4; /* [15:12] */ + UINT_32 u4AdcI1T0:4; /* [7:4] */ + + UINT_32 u4AdcQ1T5:4; /* [43:40] */ + UINT_32 u4AdcQ1T4:4; /* [35:32] */ + UINT_32 u4AdcQ1T3:4; /* [27:24] */ + + UINT_32 u4AdcI1T5:4; /* [47:44] */ + UINT_32 u4AdcI1T4:4; /* [39:36] */ + UINT_32 u4AdcI1T3:4; /* [31:28] */ +} PACKED_ADC_BUS_FMT_T, *P_PACKED_ADC_BUS_FMT_T; + +typedef union _ICAP_BUS_FMT { + ADC_BUS_FMT_T rAdcBusData; /* 12 bytes */ + IQC_BUS_FMT_T rIqcBusData; /* 12 bytes */ + IQC_160_BUS_FMT_T rIqc160BusData; /* 12 bytes */ + SPECTRUM_BUS_FMT_T rSpectrumBusData; /* 4 bytes */ + PACKED_ADC_BUS_FMT_T rPackedAdcBusData; /* 12 bytes */ +} ICAP_BUS_FMT, *P_ICAP_BUS_FMT; +#endif /* CFG_SUPPORT_QA_TOOL */ + +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; + /* TX power policy when concurrence + * in the same channel + * 0: Highest power has priority + * 1: Lowest power has priority + */ + UINT_8 ucConcurrencePolicy; + 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; + +typedef enum _ENUM_NLO_CIPHER_ALGORITHM { + NLO_CIPHER_ALGO_NONE = 0x00, + NLO_CIPHER_ALGO_WEP40 = 0x01, + NLO_CIPHER_ALGO_TKIP = 0x02, + NLO_CIPHER_ALGO_CCMP = 0x04, + NLO_CIPHER_ALGO_WEP104 = 0x05, + NLO_CIPHER_ALGO_WPA_USE_GROUP = 0x100, + NLO_CIPHER_ALGO_RSN_USE_GROUP = 0x100, + NLO_CIPHER_ALGO_WEP = 0x101, +} ENUM_NLO_CIPHER_ALGORITHM, *P_ENUM_NLO_CIPHER_ALGORITHM; + +typedef enum _ENUM_NLO_AUTH_ALGORITHM { + NLO_AUTH_ALGO_80211_OPEN = 1, + NLO_AUTH_ALGO_80211_SHARED_KEY = 2, + NLO_AUTH_ALGO_WPA = 3, + NLO_AUTH_ALGO_WPA_PSK = 4, + NLO_AUTH_ALGO_WPA_NONE = 5, + NLO_AUTH_ALGO_RSNA = 6, + NLO_AUTH_ALGO_RSNA_PSK = 7, +} ENUM_NLO_AUTH_ALGORITHM, *P_ENUM_NLO_AUTH_ALGORITHM; + +typedef struct _NLO_NETWORK { + UINT_8 ucNumChannelHint[4]; + UINT_8 ucSSIDLength; + UINT_8 ucCipherAlgo; + UINT_16 u2AuthAlgo; + UINT_8 aucSSID[32]; +} NLO_NETWORK, *P_NLO_NETWORK; + +typedef struct _CMD_NLO_REQ { + UINT_8 ucSeqNum; + UINT_8 ucBssIndex; + UINT_8 fgStopAfterIndication; + UINT_8 ucFastScanIteration; + UINT_16 u2FastScanPeriod; + UINT_16 u2SlowScanPeriod; + UINT_8 ucEntryNum; + UINT_8 ucFlag; /* BIT(0) Check cipher */ + UINT_16 u2IELen; + NLO_NETWORK arNetworkList[16]; + UINT_8 aucIE[0]; +} CMD_NLO_REQ, *P_CMD_NLO_REQ; + +typedef struct _CMD_NLO_CANCEL_T { + UINT_8 ucSeqNum; + UINT_8 ucBssIndex; + UINT_8 aucReserved[2]; +} CMD_NLO_CANCEL, *P_CMD_NLO_CANCEL; + +typedef struct _EVENT_NLO_DONE_T { + UINT_8 ucSeqNum; + UINT_8 ucStatus; + UINT_8 aucReserved[2]; +} EVENT_NLO_DONE_T, *P_EVENT_NLO_DONE_T; + +typedef struct _CMD_HIF_CTRL_T { + UINT_8 ucHifType; + UINT_8 ucHifDirection; + UINT_8 ucHifStop; + UINT_8 aucReserved1; + UINT_8 aucReserved2[32]; +} CMD_HIF_CTRL_T, *P_CMD_HIF_CTRL_T; + +typedef enum _ENUM_HIF_TYPE { + ENUM_HIF_TYPE_SDIO = 0x00, + ENUM_HIF_TYPE_USB = 0x01, + ENUM_HIF_TYPE_PCIE = 0x02, + ENUM_HIF_TYPE_GPIO = 0x03, +} ENUM_HIF_TYPE, *P_ENUM_HIF_TYPE; + +typedef enum _ENUM_HIF_DIRECTION { + ENUM_HIF_TX = 0x01, + ENUM_HIF_RX = 0x02, + ENUM_HIF_TRX = 0x03, +} ENUM_HIF_DIRECTION, *P_ENUM_HIF_DIRECTION; + +typedef enum _ENUM_HIF_TRAFFIC_STATUS { + ENUM_HIF_TRAFFIC_BUSY = 0x01, + ENUM_HIF_TRAFFIC_IDLE = 0x02, + ENUM_HIF_TRAFFIC_INVALID = 0x3, +} ENUM_HIF_TRAFFIC_STATUS, *P_ENUM_HIF_TRAFFIC_STATUS; + +typedef struct _EVENT_HIF_CTRL_T { + UINT_8 ucHifType; + UINT_8 ucHifTxTrafficStatus; + UINT_8 ucHifRxTrafficStatus; + UINT_8 ucReserved1; + UINT_8 aucReserved2[32]; +} EVENT_HIF_CTRL_T, *P_EVENT_HIF_CTRL_T; + +#if CFG_SUPPORT_BUILD_DATE_CODE +typedef struct _CMD_GET_BUILD_DATE_CODE { + UINT_8 aucReserved[4]; +} CMD_GET_BUILD_DATE_CODE, *P_CMD_GET_BUILD_DATE_CODE; + +typedef struct _EVENT_BUILD_DATE_CODE { + UINT_8 aucDateCode[16]; +} EVENT_BUILD_DATE_CODE, *P_EVENT_BUILD_DATE_CODE; +#endif + +typedef struct _CMD_GET_STA_STATISTICS_T { + UINT_8 ucIndex; + UINT_8 ucFlags; + UINT_8 ucReadClear; + UINT_8 ucLlsReadClear; + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + UINT_8 ucResetCounter; + UINT_8 aucReserved1[1]; + UINT_8 aucReserved2[16]; +} CMD_GET_STA_STATISTICS_T, *P_CMD_GET_STA_STATISTICS_T; + +/* per access category statistics */ +typedef struct _WIFI_WMM_AC_STAT_GET_FROM_FW_T { + UINT_32 u4TxFailMsdu; + UINT_32 u4TxRetryMsdu; +} WIFI_WMM_AC_STAT_GET_FROM_FW_T, *P_WIFI_WMM_AC_STAT_GET_FROM_FW_T; + +/* CFG_SUPPORT_WFD */ +typedef struct _EVENT_STA_STATISTICS_T { + /* Event header */ + /* UINT_16 u2Length; */ + /* UINT_16 u2Reserved1; *//* Must be filled with 0x0001 (EVENT Packet) */ + /* UINT_8 ucEID; */ + /* UINT_8 ucSeqNum; */ + /* UINT_8 aucReserved2[2]; */ + + /* Event Body */ + UINT_8 ucVersion; + UINT_8 aucReserved1[3]; + UINT_32 u4Flags; /* Bit0: valid */ + + UINT_8 ucStaRecIdx; + UINT_8 ucNetworkTypeIndex; + UINT_8 ucWTEntry; + UINT_8 aucReserved4[1]; + + UINT_8 ucMacAddr[MAC_ADDR_LEN]; + UINT_8 ucPer; /* base: 128 */ + UINT_8 ucRcpi; + + UINT_32 u4PhyMode; /* SGI BW */ + UINT_16 u2LinkSpeed; /* unit is 0.5 Mbits */ + UINT_8 ucLinkQuality; + UINT_8 ucLinkReserved; + + UINT_32 u4TxCount; + UINT_32 u4TxFailCount; + UINT_32 u4TxLifeTimeoutCount; + UINT_32 u4TxDoneAirTime; + UINT_32 u4TransmitCount; /* Transmit in the air (wtbl) */ + UINT_32 u4TransmitFailCount; /* Transmit without ack/ba in the air (wtbl) */ + + WIFI_WMM_AC_STAT_GET_FROM_FW_T arLinkStatistics[AC_NUM]; /*link layer statistics */ + + UINT_8 ucTemperature; + UINT_8 ucSkipAr; + UINT_8 ucArTableIdx; + UINT_8 ucRateEntryIdx; + UINT_8 ucRateEntryIdxPrev; + UINT_8 ucTxSgiDetectPassCnt; + UINT_8 ucAvePer; + UINT_8 aucArRatePer[AR_RATE_TABLE_ENTRY_MAX]; + UINT_8 aucRateEntryIndex[AUTO_RATE_NUM]; + UINT_8 ucArStateCurr; + UINT_8 ucArStatePrev; + UINT_8 ucArActionType; + UINT_8 ucHighestRateCnt; + UINT_8 ucLowestRateCnt; + UINT_16 u2TrainUp; + UINT_16 u2TrainDown; + UINT_32 u4Rate1TxCnt; + UINT_32 u4Rate1FailCnt; + TX_VECTOR_BBP_LATCH_T rTxVector[ENUM_BAND_NUM]; + MIB_INFO_STAT_T rMibInfo[ENUM_BAND_NUM]; + BOOLEAN fgIsForceTxStream; + BOOLEAN fgIsForceSeOff; + UINT_8 aucReserved[21]; +} EVENT_STA_STATISTICS_T, *P_EVENT_STA_STATISTICS_T; + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +typedef struct _EVENT_LTE_SAFE_CHN_T { + UINT_8 ucVersion; + UINT_8 aucReserved[3]; + UINT_32 u4Flags; /* Bit0: valid */ + LTE_SAFE_CHN_INFO_T rLteSafeChn; +} EVENT_LTE_SAFE_CHN_T, *P_EVENT_LTE_SAFE_CHN_T; +#endif + +#if CFG_SUPPORT_SNIFFER +typedef struct _CMD_MONITOR_SET_INFO_T { + UINT_8 ucEnable; + UINT_8 ucBand; + UINT_8 ucPriChannel; + UINT_8 ucSco; + UINT_8 ucChannelWidth; + UINT_8 ucChannelS1; + UINT_8 ucChannelS2; + UINT_8 aucResv[9]; +} CMD_MONITOR_SET_INFO_T, *P_CMD_MONITOR_SET_INFO_T; +#endif + +typedef struct _CMD_STATS_LOG_T { + UINT_32 u4DurationInMs; + UINT_8 aucReserved[32]; +} CMD_STATS_LOG_T, *P_CMD_STATS_LOG_T; + +typedef struct _EVENT_WIFI_RDD_TEST_T { + UINT_32 u4FuncIndex; + UINT_32 u4FuncLength; + UINT_32 u4Prefix; + UINT_32 u4Count; + UINT_32 u4SubBandRssi0; + UINT_32 u4SubBandRssi1; + UINT_8 ucRddIdx; + UINT_8 aucReserve[3]; + UINT_8 aucBuffer[0]; +} EVENT_WIFI_RDD_TEST_T, *P_EVENT_WIFI_RDD_TEST_T; + +#if CFG_SUPPORT_MSP +/* EVENT_ID_WLAN_INFO */ +typedef struct _EVENT_WLAN_INFO { + + PARAM_TX_CONFIG_T rWtblTxConfig; + PARAM_SEC_CONFIG_T rWtblSecConfig; + PARAM_KEY_CONFIG_T rWtblKeyConfig; + PARAM_PEER_RATE_INFO_T rWtblRateInfo; + PARAM_PEER_BA_CONFIG_T rWtblBaConfig; + PARAM_PEER_CAP_T rWtblPeerCap; + PARAM_PEER_RX_COUNTER_ALL_T rWtblRxCounter; + PARAM_PEER_TX_COUNTER_ALL_T rWtblTxCounter; +} EVENT_WLAN_INFO, *P_EVENT_WLAN_INFO; + +/* EVENT_ID_MIB_INFO */ +typedef struct _EVENT_MIB_INFO { + HW_MIB_COUNTER_T rHwMibCnt; + HW_MIB2_COUNTER_T rHwMib2Cnt; + HW_TX_AMPDU_METRICS_T rHwTxAmpduMts; + +} EVENT_MIB_INFO, *P_EVENT_MIB_INFO; +#endif + +#if CFG_SUPPORT_LAST_SEC_MCS_INFO +struct EVENT_TX_MCS_INFO { + UINT_16 au2TxRateCode[MCS_INFO_SAMPLE_CNT]; + UINT_8 aucTxRatePer[MCS_INFO_SAMPLE_CNT]; + UINT_8 aucReserved[2]; +}; +#endif + +/*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ +typedef struct _EVENT_ACCESS_EFUSE { + + UINT_32 u4Address; + UINT_32 u4Valid; + UINT_8 aucData[16]; + +} EVENT_ACCESS_EFUSE, *P_EVENT_ACCESS_EFUSE; + + +typedef struct _EXT_EVENT_EFUSE_FREE_BLOCK_T { + + UINT_16 u2FreeBlockNum; + UINT_8 aucReserved[2]; +} EVENT_EFUSE_FREE_BLOCK_T, *P_EVENT_EFUSE_FREE_BLOCK_T; + +typedef struct _EXT_EVENT_GET_TX_POWER_T { + + UINT_8 ucTxPwrType; + UINT_8 ucEfuseAddr; + UINT_8 ucTx0TargetPower; + UINT_8 ucDbdcIdx; + +} EVENT_GET_TX_POWER_T, *P_EVENT_GET_TX_POWER_T; + +typedef struct _CMD_SUSPEND_MODE_SETTING_T { + UINT_8 ucBssIndex; + UINT_8 ucEnableSuspendMode; + UINT_8 ucMdtim; /* LP parameter */ + UINT_8 ucReserved1[1]; + UINT_8 ucReserved2[64]; +} CMD_SUSPEND_MODE_SETTING_T, *P_CMD_SUSPEND_MODE_SETTING_T; + +typedef struct _EVENT_UPDATE_COEX_PHYRATE_T { + UINT_8 ucVersion; + UINT_8 aucReserved1[3]; /* 4 byte alignment */ + UINT_32 u4Flags; + UINT_32 au4PhyRateLimit[HW_BSSID_NUM+1]; +} EVENT_UPDATE_COEX_PHYRATE_T, *P_EVENT_UPDATE_COEX_PHYRATE_T; + +#if CFG_SUPPORT_CSI + +#define CSI_INFO_RSVD1 BIT(0) +#define CSI_INFO_RSVD2 BIT(1) + +enum CSI_CONTROL_MODE_T { + CSI_CONTROL_MODE_STOP, + CSI_CONTROL_MODE_START, + CSI_CONTROL_MODE_SET, + CSI_CONTROL_MODE_NUM +}; + +enum CSI_CONFIG_ITEM_T { + CSI_CONFIG_RSVD1, + CSI_CONFIG_WF, + CSI_CONFIG_RSVD2, + CSI_CONFIG_FRAME_TYPE, + CSI_CONFIG_TX_PATH, + CSI_CONFIG_OUTPUT_FORMAT, + CSI_CONFIG_INFO, + CSI_CONFIG_ITEM_NUM +}; + +struct CMD_CSI_CONTROL_T { + UINT_8 ucMode; + UINT_8 ucCfgItem; + UINT_8 ucValue1; + UINT_8 ucValue2; +}; + +enum CSI_OUTPUT_FORMAT_T { + CSI_OUTPUT_RAW, + CSI_OUTPUT_TONE_MASKED, + CSI_OUTPUT_TONE_MASKED_SHIFTED, + CSI_OUTPUT_FORMAT_NUM +}; + +#endif + + +struct CMD_GET_TXPWR_TBL { + UINT_8 ucDbdcIdx; + UINT_8 aucReserved[3]; +}; + +struct EVENT_GET_TXPWR_TBL { + UINT_8 ucCenterCh; + UINT_8 aucReserved[3]; + struct POWER_LIMIT tx_pwr_tbl[TXPWR_TBL_NUM]; +}; + +struct TLV_ELEMENT { + UINT_32 tag_type; + UINT_32 body_len; + UINT_8 aucbody[0]; +}; + +/*#endif*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* 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); + +/* Nic cmd/event for Coex related */ +VOID nicCmdEventQueryCoexIso(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +VOID nicCmdEventQueryCoexGetInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +#if CFG_SUPPORT_QA_TOOL +VOID nicCmdEventQueryRxStatistics(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +UINT_32 TsfRawData2IqFmt(P_EVENT_DUMP_MEM_T prEventDumpMem); + +INT_32 GetIQData(INT_32 **prIQAry, UINT_32 *prDataLen, UINT_32 u4IQ, UINT_32 u4GetWf1); + +#if CFG_SUPPORT_TX_BF +VOID nicCmdEventPfmuDataRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventPfmuTagRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +#endif /* CFG_SUPPORT_TX_BF */ +#if CFG_SUPPORT_MU_MIMO +VOID nicCmdEventGetQd(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +VOID nicCmdEventGetCalcLq(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +VOID nicCmdEventGetCalcInitMcs(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +#endif /* CFG_SUPPORT_MU_MIMO */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +VOID nicCmdEventQueryCalBackupV2(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +#endif + +VOID nicEventQueryMemDump(IN P_ADAPTER_T prAdapter, 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 nicCmdEventQueryChipConfig(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 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); + +VOID nicCmdEventSetStopSchedScan(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +/* Statistics responder */ +VOID nicCmdEventQueryXmitOk(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryRecvOk(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryXmitError(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryRecvError(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryRecvNoBuffer(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryRecvCrcError(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryRecvErrorAlignment(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryXmitOneCollision(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryXmitMoreCollisions(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryXmitMaxCollisions(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +/* for timeout check */ +VOID nicOidCmdTimeoutCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +VOID nicCmdTimeoutCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +VOID nicOidCmdEnterRFTestTimeout(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +#if CFG_SUPPORT_BUILD_DATE_CODE +VOID nicCmdEventBuildDateCode(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +#endif + +VOID nicCmdEventQueryStaStatistics(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +/* 4 Auto Channel Selection */ +VOID nicCmdEventQueryLteSafeChn(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +#endif + +#if CFG_SUPPORT_BATCH_SCAN +VOID nicCmdEventBatchScanResult(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +#endif + +#if CFG_SUPPORT_ADVANCE_CONTROL +VOID nicCmdEventQueryAdvCtrl(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +#endif + +VOID nicEventRddPulseDump(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryWlanInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryMibInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +#if CFG_SUPPORT_LAST_SEC_MCS_INFO +VOID nicCmdEventTxMcsInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +#endif + +VOID nicCmdEventQueryNicCapabilityV2(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEventBuf); + +WLAN_STATUS nicCmdEventQueryNicTxResource(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEventBuf); + +WLAN_STATUS nicCmdEventQueryNicEfuseAddr(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEventBuf); + +WLAN_STATUS nicCmdEventQueryEfuseOffset(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEventBuf); + +WLAN_STATUS nicCmdEventQueryRModeCapability(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEventBuf); + +WLAN_STATUS nicCmdEventQueryNicCoexFeature(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEventBuf); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +WLAN_STATUS nicCmdEventQueryNicCsumOffload(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEventBuf); +#endif + +VOID nicEventLinkQuality(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +VOID nicEventLayer0ExtMagic(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +VOID nicEventMicErrorInfo(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +VOID nicEventScanDone(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +VOID nicEventNloDone(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +VOID nicEventSleepyNotify(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +VOID nicEventBtOverWifi(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +VOID nicEventStatistics(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +VOID nicEventWlanInfo(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +VOID nicEventMibInfo(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +#if CFG_SUPPORT_LAST_SEC_MCS_INFO +VOID nicEventTxMcsInfo(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +#endif +VOID nicEventBeaconTimeout(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +VOID nicEventUpdateNoaParams(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +VOID nicEventStaAgingTimeout(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +VOID nicEventApObssStatus(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +VOID nicEventRoamingStatus(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +VOID nicEventSendDeauth(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +VOID nicEventUpdateRddStatus(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +VOID nicEventUpdateBwcsStatus(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +VOID nicEventUpdateBcmDebug(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +VOID nicEventAddPkeyDone(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +VOID nicEventIcapDone(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +VOID nicEventCalAllDone(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +#endif +VOID nicEventDebugMsg(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +VOID nicEventTdls(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +VOID nicEventDumpMem(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +VOID nicEventAssertDump(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +VOID nicEventHifCtrl(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +VOID nicEventRddSendPulse(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +VOID nicEventUpdateCoexPhyrate(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +#if (CFG_WOW_SUPPORT == 1) +VOID nicEventWakeUpReason(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +#endif +VOID nicEventCSIData(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); + +#if CFG_SUPPORT_REPLAY_DETECTION +VOID nicCmdEventSetAddKey(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +VOID nicOidCmdTimeoutSetAddKey(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +VOID nicEventGetGtkDataSync(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); +#endif + +VOID nicCmdEventGetTxPwrTbl(IN P_ADAPTER_T prAdapter, + IN P_CMD_INFO_T prCmdInfo, + IN PUINT_8 pucEventBuf); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _NIC_CMD_EVENT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic_init_cmd_event.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic_init_cmd_event.h new file mode 100644 index 0000000000000..6e6b541c5f46a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/nic_init_cmd_event.h @@ -0,0 +1,312 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + +#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_WITHOUT_RXD_SIZE (OFFSET_OF(WIFI_EVENT_T, aucBuffer[0]) - OFFSET_OF(WIFI_EVENT_T, u2PacketLength)) + +#define INIT_PKT_FT_CMD 0x2 +#define INIT_PKT_FT_PDA_FWDL 0x3 + +#define INIT_CMD_PQ_ID (0x8000) +#define INIT_CMD_PACKET_TYPE_ID (0xA0) + +#define INIT_CMD_PDA_PQ_ID (0xF800) +#define INIT_CMD_PDA_PACKET_TYPE_ID (0xA0) + +#if (CFG_UMAC_GENERATION >= 0x20) +#define TXD_Q_IDX_MCU_RQ0 0 +#define TXD_Q_IDX_MCU_RQ1 1 +#define TXD_Q_IDX_MCU_RQ2 2 +#define TXD_Q_IDX_MCU_RQ3 3 + +#define TXD_Q_IDX_PDA_FW_DL 0x1E + +/* DW0 Bit31 */ +#define TXD_P_IDX_LMAC 0 +#define TXD_P_IDX_MCU 1 + +/* DW1 Bit 14:13 */ +#define TXD_HF_NON_80211_FRAME 0x0 +#define TXD_HF_CMD 0x1 +#define TXD_HF_80211_NORMAL 0x2 +#define TXD_HF_80211_ENHANCEMENT 0x3 + +/* DW1 Bit 15 */ +#define TXD_FT_OFFSET 15 +#define TXD_FT_SHORT_FORMAT 0x0 +#define TXD_FT_LONG_FORMAT 0x1 + +/* DW1 Bit 16 */ +#define TXD_TXDLEN_OFFSET 16 +#define TXD_TXDLEN_1PAGE 0x0 +#define TXD_TXDLEN_2PAGE 0x1 + +/* DW1 Bit 25:24 */ +#define TXD_PKT_FT_CUT_THROUGH 0x0 +#define TXD_PKT_FT_STORE_FORWARD 0X1 +#define TXD_PKT_FT_CMD 0X2 +#define TXD_PKT_FT_PDA_FW 0X3 +#endif + +typedef enum _ENUM_INIT_CMD_ID { + INIT_CMD_ID_DOWNLOAD_CONFIG = 1, + INIT_CMD_ID_WIFI_START, + INIT_CMD_ID_ACCESS_REG, + INIT_CMD_ID_QUERY_PENDING_ERROR, + INIT_CMD_ID_PATCH_START, + INIT_CMD_ID_PATCH_WRITE, + INIT_CMD_ID_PATCH_FINISH, + INIT_CMD_ID_PATCH_SEMAPHORE_CONTROL = 0x10, + INIT_CMD_ID_HIF_LOOPBACK = 0x20, +#if CFG_SUPPORT_COMPRESSION_FW_OPTION + INIT_CMD_ID_DECOMPRESSED_WIFI_START = 0xFF, +#endif + INIT_CMD_ID_NUM +} 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, + INIT_EVENT_ID_PATCH_SEMA_CTRL +} ENUM_INIT_EVENT_ID, *P_ENUM_INIT_EVENT_ID; + +typedef enum _ENUM_INIT_PATCH_STATUS { + PATCH_STATUS_NO_SEMA_NEED_PATCH = 0, /* no SEMA, need patch */ + PATCH_STATUS_NO_NEED_TO_PATCH, /* patch is DL & ready */ + PATCH_STATUS_GET_SEMA_NEED_PATCH, /* get SEMA, need patch */ + PATCH_STATUS_RELEASE_SEMA /* release SEMA */ +} ENUM_INIT_PATCH_STATUS, *P_ENUM_INIT_PATCH_STATUS; + +/******************************************************************************* +* 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 ucPktTypeID; /* Must be 0xA0 (CMD Packet) */ + UINT_8 ucReserved; + UINT_8 ucSeqNum; +#if 1 + UINT_8 ucD2B0Rev; /* padding fields, hw may auto modify this field */ + UINT_8 ucExtenCID; /* Extend CID */ + UINT_8 ucS2DIndex; /* Index for Src to Dst in CMD usage */ + UINT_8 ucExtCmdOption; /* Extend CID option */ + + UINT_32 au4D3toD7Rev[5]; /* padding fields */ +#endif + UINT_8 aucBuffer[0]; +} INIT_WIFI_CMD_T, *P_INIT_WIFI_CMD_T; + +typedef struct _INIT_HIF_TX_HEADER_T { + UINT_16 u2TxByteCount; /* Max value is over 2048 */ + UINT_16 u2PQ_ID; /* Must be 0x8000 (Port1, Queue 0) */ +#if 1 + UINT_8 ucWlanIdx; + UINT_8 ucHeaderFormat; + UINT_8 ucHeaderPadding; + UINT_8 ucPktFt:2; + UINT_8 ucOwnMAC:6; + UINT_32 au4D2toD7Rev[6]; + + UINT_16 u2Length; + UINT_16 u2PqId; +#endif + INIT_WIFI_CMD_T rInitWifiCmd; +} INIT_HIF_TX_HEADER_T, *P_INIT_HIF_TX_HEADER_T; + +#define DOWNLOAD_CONFIG_ENCRYPTION_MODE BIT(0) +#define DOWNLOAD_CONFIG_KEY_INDEX_MASK BITS(1, 2) +#define DOWNLOAD_CONFIG_RESET_OPTION BIT(3) +#define DOWNLOAD_CONFIG_WORKING_PDA_OPTION BIT(4) +#define DOWNLOAD_CONFIG_ACK_OPTION BIT(31) +typedef struct _INIT_CMD_DOWNLOAD_CONFIG { + UINT_32 u4Address; + UINT_32 u4Length; + UINT_32 u4DataMode; +} INIT_CMD_DOWNLOAD_CONFIG, *P_INIT_CMD_DOWNLOAD_CONFIG; + +#define START_OVERRIDE_START_ADDRESS BIT(0) +#define START_DELAY_CALIBRATION BIT(1) +#define START_WORKING_PDA_OPTION BIT(2) +#define START_CRC_CHECK BIT(3) +#define CHANGE_DECOMPRESSION_TMP_ADDRESS BIT(4) + +#if CFG_SUPPORT_COMPRESSION_FW_OPTION +#define WIFI_FW_DECOMPRESSION_FAILED 0xFF +typedef struct _INIT_CMD_WIFI_DECOMPRESSION_START { + UINT_32 u4Override; + UINT_32 u4Address; + UINT_32 u4Region1length; + UINT_32 u4Region2length; + UINT_32 u4Region1Address; + UINT_32 u4Region2Address; + UINT_32 u4BlockSize; + UINT_32 u4Region1CRC; + UINT_32 u4Region2CRC; + UINT_32 u4DecompressTmpAddress; +} INIT_CMD_WIFI_DECOMPRESSION_START, *P_INIT_CMD_WIFI_DECOMPRESSION_START; +#endif + +typedef struct _INIT_CMD_WIFI_START { + UINT_32 u4Override; + UINT_32 u4Address; +} INIT_CMD_WIFI_START, *P_INIT_CMD_WIFI_START; + +#define PATCH_GET_SEMA_CONTROL 1 +#define PATCH_RELEASE_SEMA_CONTROL 0 +typedef struct _INIT_CMD_PATCH_SEMA_CONTROL { + UINT_8 ucGetSemaphore; + UINT_8 aucReserved[3]; +} INIT_CMD_PATCH_SEMA_CONTROL, *P_INIT_CMD_PATCH_SEMA_CONTROL; + +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 { +#if 1 + UINT_32 au4HwMacRxDesc[4]; +#endif + UINT_16 u2RxByteCount; + UINT_16 u2PacketType; /* Must be filled with 0xE000 (EVENT Packet) */ + UINT_8 ucEID; + UINT_8 ucSeqNum; + UINT_8 aucReserved[2]; + + 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 */ + /* 5: timeout */ + UINT_8 aucReserved[3]; +} INIT_EVENT_CMD_RESULT, *P_INIT_EVENT_CMD_RESULT, INIT_EVENT_PENDING_ERROR, *P_INIT_EVENT_PENDING_ERROR; + +typedef struct _INIT_EVENT_ACCESS_REG { + UINT_32 u4Address; + UINT_32 u4Data; +} INIT_EVENT_ACCESS_REG, *P_INIT_EVENT_ACCESS_REG; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _NIC_INIT_CMD_EVENT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/p2p_precomp.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/p2p_precomp.h new file mode 100644 index 0000000000000..7bb33a12b11cc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/p2p_precomp.h @@ -0,0 +1,248 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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" + +#include "nic_rate.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" + +#include "mt66xx_reg.h" + +#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_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" + +#include "rsn.h" + +#if CFG_SUPPORT_WAPI +#include "wapi.h" +#endif + +/*------------------------------------------------------------------------------ + * NVRAM structure + *------------------------------------------------------------------------------ + */ +#include "CFG_Wifi_File.h" + +#include "gl_p2p_kal.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /*_P2P_PRECOMP_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/p2p_typedef.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/p2p_typedef.h new file mode 100644 index 0000000000000..95b734895b8b7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/p2p_typedef.h @@ -0,0 +1,219 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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_DEV_FSM_INFO_T P2P_DEV_FSM_INFO_T, *P_P2P_DEV_FSM_INFO_T; + +typedef struct _P2P_ROLE_FSM_INFO_T P2P_ROLE_FSM_INFO_T, *P_P2P_ROLE_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 UINT_8 ucBssIndex, IN P_STA_RECORD_T prStaRec); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /*CFG_ENABLE_WIFI_DIRECT */ + +#endif /* _P2P_TYPEDEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/precomp.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/precomp.h new file mode 100644 index 0000000000000..9e251c4612cdf --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/precomp.h @@ -0,0 +1,304 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + +#ifndef _PRECOMP_H +#define _PRECOMP_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +#ifdef __GNUC__ +#if (DBG == 0) +#pragma GCC diagnostic ignored "-Wformat" +#endif +#endif + +/******************************************************************************* +* 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 "nic_umac.h" + +#include "bss.h" + +#include "nic_rate.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 "wlan_lib.h" +#include "wlan_oid.h" +#include "wlan_bow.h" + +#if CFG_ENABLE_WIFI_DIRECT +#include "wlan_p2p.h" +#endif + +#include "hal.h" + +#include "mt66xx_reg.h" + +#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" + +#include "que_mgt.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_rlm.h" +#include "p2p_assoc.h" +#include "p2p_ie.h" +#include "p2p_role.h" + +#include "p2p_func.h" +#include "p2p_scan.h" +#include "p2p_dev.h" +#include "p2p_fsm.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" + +#include "rsn.h" + +#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 + +#if CFG_SUPPORT_TDLS +#include "tdls.h" +#endif + +#if CFG_SUPPORT_QA_TOOL +#include "gl_qa_agent.h" +#endif + +/*------------------------------------------------------------------------------ + * Memory Prealloc + *------------------------------------------------------------------------------ + */ +#ifdef CFG_PREALLOC_MEMORY +#include "prealloc.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 +******************************************************************************** +*/ +#ifdef _HIF_SDIO +#if MTK_WCN_HIF_SDIO +extern INT_32 mtk_sdio_probe(MTK_WCN_HIF_SDIO_CLTCTX cltCtx, + const MTK_WCN_HIF_SDIO_FUNCINFO * prFuncInfo); +extern INT_32 mtk_sdio_remove(MTK_WCN_HIF_SDIO_CLTCTX cltCtx); +#else +extern int mtk_sdio_probe(struct sdio_func *func, + const struct sdio_device_id *id); +extern void mtk_sdio_remove(struct sdio_func *func); +#endif +#endif + +#endif /* _PRECOMP_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/pwr_mgt.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/pwr_mgt.h new file mode 100644 index 0000000000000..19f588659b922 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/pwr_mgt.h @@ -0,0 +1,149 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + +#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 + +#define LP_OWN_BACK_TOTAL_DELAY_MS 2048 /* 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 */ +#define LP_OWN_BACK_FAILED_RETRY_CNT 5 +#define LP_OWN_BACK_FAILED_LOG_SKIP_MS 2000 +#define LP_OWN_BACK_FAILED_RESET_CNT 5 +#define LP_OWN_BACK_FAILED_DBGCR_POLL_ROUND 5 +#define LP_DBGCR_POLL_ROUND 1 + +/******************************************************************************* +* 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) \ + { \ + nicpmSetDriverOwn(_prAdapter); \ + } + +#define RECLAIM_POWER_CONTROL_TO_PM(_prAdapter, _fgEnableGINT_in_IST) \ + { \ + nicpmSetFWOwn(_prAdapter, _fgEnableGINT_in_IST); \ + } +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _PWR_MGT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/queue.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/queue.h new file mode 100644 index 0000000000000..cd5fc29cdbe1d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/queue.h @@ -0,0 +1,231 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + +#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 MAXNUM_TDLS_PEER 4 + +#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); \ + } \ + } + +#define QUEUE_CONCATENATE_QUEUES_HEAD(prDestQueue, prSrcQueue) \ + { \ + ASSERT(prDestQueue); \ + ASSERT(prSrcQueue); \ + if ((prSrcQueue)->u4NumElem > 0) { \ + ((prSrcQueue)->prTail)->prNext = (prDestQueue)->prHead; \ + (prDestQueue)->prHead = (prSrcQueue)->prHead; \ + ((prDestQueue)->u4NumElem) += ((prSrcQueue)->u4NumElem); \ + if ((prDestQueue)->prTail == NULL) { \ + (prDestQueue)->prTail = (prSrcQueue)->prTail; \ + } \ + QUEUE_INITIALIZE(prSrcQueue); \ + } \ + } + +/******************************************************************************* +* E X T E R N A L D A T A +******************************************************************************** +*/ +extern UINT_8 g_arTdlsLink[MAXNUM_TDLS_PEER]; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _QUEUE_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/rftest.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/rftest.h new file mode 100644 index 0000000000000..4b785fffc36e9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/rftest.h @@ -0,0 +1,428 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/rftest.h#1 +*/ + +/*! \file "rftest.h" +* \brief definitions for RF Productino test +* +*/ + +#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, + RF_AT_FUNCID_PWR_DETECTOR, + RF_AT_FUNCID_WBRSSI_IBSSI, + + /* 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, + RF_AT_FUNCID_SET_TA, + RF_AT_FUNCID_SET_RX_MATCH_RULE, + + /* 80211AC & Jmode */ + RF_AT_FUNCID_SET_CBW = 71, + RF_AT_FUNCID_SET_DBW, + RF_AT_FUNCID_SET_PRIMARY_CH, + RF_AT_FUNCID_SET_ENCODE_MODE, + RF_AT_FUNCID_SET_J_MODE, + + /* ICAP command */ + RF_AT_FUNCID_SET_ICAP_CONTENT = 80, + RF_AT_FUNCID_SET_ICAP_MODE, + RF_AT_FUNCID_SET_ICAP_STARTCAP, + RF_AT_FUNCID_SET_ICAP_SIZE = 83, + RF_AT_FUNCID_SET_ICAP_TRIGGER_OFFSET, + RF_AT_FUNCID_QUERY_ICAP_DUMP_FILE = 85, + +#if CFG_SUPPORT_QA_TOOL + /* 2G 5G Band */ + RF_AT_FUNCID_SET_BAND = 90, + + /* Reset Counter */ + RF_AT_FUNCID_RESETTXRXCOUNTER = 91, + + /* FAGC RSSI Path */ + RF_AT_FUNCID_FAGC_RSSI_PATH = 92, + + /* Set RX Filter Packet Length */ + RF_AT_FUNCID_RX_FILTER_PKT_LEN = 93, + + /* Tone */ + RF_AT_FUNCID_SET_TONE_RF_GAIN = 96, + RF_AT_FUNCID_SET_TONE_DIGITAL_GAIN = 97, + RF_AT_FUNCID_SET_TONE_TYPE = 98, + RF_AT_FUNCID_SET_TONE_DC_OFFSET = 99, + RF_AT_FUNCID_SET_TONE_BW = 100, + + /* MT6632 Add */ + RF_AT_FUNCID_SET_MAC_HEADER = 101, + RF_AT_FUNCID_SET_SEQ_CTRL = 102, + RF_AT_FUNCID_SET_PAYLOAD = 103, + RF_AT_FUNCID_SET_DBDC_BAND_IDX = 104, + RF_AT_FUNCID_SET_BYPASS_CAL_STEP = 105, + + /* Set RX Path */ + RF_AT_FUNCID_SET_RX_PATH = 106, + + /* Set Frequency Offset */ + RF_AT_FUNCID_SET_FRWQ_OFFSET = 107, + + /* Get Frequency Offset */ + RF_AT_FUNCID_GET_FREQ_OFFSET = 108, + + /* Set RXV Debug Index */ + RF_AT_FUNCID_SET_RXV_INDEX = 109, + + /* Set Test Mode DBDC Enable */ + RF_AT_FUNCID_SET_DBDC_ENABLE = 110, + + /* Get Test Mode DBDC Enable */ + RF_AT_FUNCID_GET_DBDC_ENABLE = 111, + + /* Set ICAP Ring Capture */ + RF_AT_FUNCID_SET_ICAP_RING = 112, + + /* Set TX Path */ + RF_AT_FUNCID_SET_TX_PATH = 113, + + /* Set Nss */ + RF_AT_FUNCID_SET_NSS = 114, + + /* Set TX Antenna Mask */ + RF_AT_FUNCID_SET_ANTMASK = 115, + + /* TMR set command */ + RF_AT_FUNCID_SET_TMR_ROLE = 116, + RF_AT_FUNCID_SET_TMR_MODULE = 117, + RF_AT_FUNCID_SET_TMR_DBM = 118, + RF_AT_FUNCID_SET_TMR_ITER = 119, + + /* Set ADC For IRR Feature */ + RF_AT_FUNCID_SET_ADC = 120, + + /* Set RX Gain For IRR Feature */ + RF_AT_FUNCID_SET_RX_GAIN = 121, + + /* Set TTG For IRR Feature */ + RF_AT_FUNCID_SET_TTG = 122, + + /* Set TTG ON/OFF For IRR Feature */ + RF_AT_FUNCID_TTG_ON_OFF = 123, + + /* Set TSSI for QA Tool Setting */ + RF_AT_FUNCID_SET_TSSI = 124, + + /* Set Recal Cal Step */ + RF_AT_FUNCID_SET_RECAL_CAL_STEP = 125, + + /* Set iBF/eBF enable */ + RF_AT_FUNCID_SET_IBF_ENABLE = 126, + RF_AT_FUNCID_SET_EBF_ENABLE = 127, + + /* Set MPS Setting */ + RF_AT_FUNCID_SET_MPS_SIZE = 128, + RF_AT_FUNCID_SET_MPS_SEQ_DATA = 129, + RF_AT_FUNCID_SET_MPS_PAYLOAD_LEN = 130, + RF_AT_FUNCID_SET_MPS_PKT_CNT = 131, + RF_AT_FUNCID_SET_MPS_PWR_GAIN = 132, + RF_AT_FUNCID_SET_MPS_NSS = 133, + RF_AT_FUNCID_SET_MPS_PACKAGE_BW = 134 +#endif +} 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_ICAP, + RF_AT_COMMAND_RDD, + RF_AT_COMMAND_CH_SWITCH_FOR_ICAP, + RF_AT_COMMAND_RESET_DUMP_NAME, + RF_AT_COMMAND_SINGLE_TONE, + RF_AT_COMMAND_RDD_OFF, + 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_11AC, + RF_AT_PREAMBLE_NUM +} ENUM_RF_AT_PREAMBLE_T; + +/* Ack Policy */ +typedef enum _ENUM_RF_AT_ACK_POLICY_T { + RF_AT_ACK_POLICY_NORMAL = 0, + RF_AT_ACK_POLICY_NOACK, + RF_AT_ACK_POLICY_NOEXPLICTACK, + RF_AT_ACK_POLICY_BLOCKACK, + RF_AT_ACK_POLICY_NUM +} ENUM_RF_AT_ACK_POLICY_T; + +typedef enum _ENUM_RF_AUTOTEST_STATE_T { + RF_AUTOTEST_STATE_STANDBY = 0, + RF_AUTOTEST_STATE_TX, + RF_AUTOTEST_STATE_RX, + RF_AUTOTEST_STATE_RESET, + RF_AUTOTEST_STATE_OUTPUT_POWER, + RF_AUTOTEST_STATE_LOCA_FREQUENCY, + RF_AUTOTEST_STATE_CARRIER_SUPRRESION, + RF_AUTOTEST_STATE_NUM +} ENUM_RF_AUTOTEST_STATE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +WLAN_STATUS rftestSetATInfo(IN P_ADAPTER_T prAdapter, UINT_32 u4FuncIndex, UINT_32 u4FuncData); + +WLAN_STATUS +rftestQueryATInfo(IN P_ADAPTER_T prAdapter, + UINT_32 u4FuncIndex, UINT_32 u4FuncData, OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen); + +WLAN_STATUS rftestSetFrequency(IN P_ADAPTER_T prAdapter, IN UINT_32 u4FreqInKHz, IN PUINT_32 pu4SetInfoLen); + +#endif /* _RFTEST_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/typedef.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/typedef.h new file mode 100644 index 0000000000000..a8a10df759bc5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/typedef.h @@ -0,0 +1,202 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + +#ifndef _TYPEDEF_H +#define _TYPEDEF_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/* ieee80211.h of linux has duplicated definitions */ +#if defined(WLAN_STATUS_SUCCESS) +#undef WLAN_STATUS_SUCCESS +#endif + +#define WLAN_STATUS_SUCCESS ((WLAN_STATUS) 0x00000000L) +#define WLAN_STATUS_PENDING ((WLAN_STATUS) 0x00000103L) +#define WLAN_STATUS_NOT_ACCEPTED ((WLAN_STATUS) 0x00010003L) + +#define WLAN_STATUS_MEDIA_CONNECT ((WLAN_STATUS) 0x4001000BL) +#define WLAN_STATUS_MEDIA_DISCONNECT ((WLAN_STATUS) 0x4001000CL) +#define WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY ((WLAN_STATUS) 0x4001000DL) +#define WLAN_STATUS_MEDIA_SPECIFIC_INDICATION ((WLAN_STATUS) 0x40010012L) + +#define WLAN_STATUS_SCAN_COMPLETE ((WLAN_STATUS) 0x60010001L) +#define WLAN_STATUS_SCAN_ABORT ((WLAN_STATUS) 0x60010002L) +#define WLAN_STATUS_MSDU_OK ((WLAN_STATUS) 0x60010003L) + + +/* 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_JOIN_TIMEOUT ((WLAN_STATUS) 0xc0010018L) + +/* NIC status flags */ +#define ADAPTER_FLAG_HW_ERR 0x00400000 + +/******************************************************************************* +* 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 WLAN configuration */ +typedef struct _WLAN_CFG_T WLAN_CFG_T, *P_WLAN_CFG_T; + +typedef struct _WLAN_CFG_REC_T WLAN_CFG_REC_T, *P_WLAN_CFG_REC_T; + + +/* Type definition for WLAN configuration entry */ +typedef struct _WLAN_CFG_ENTRY_T WLAN_CFG_ENTRY_T, *P_WLAN_CFG_ENTRY_T; + +/* Type definition for WLAN configuration callback */ +typedef WLAN_STATUS(*WLAN_CFG_SET_CB) (P_ADAPTER_T prAdapter, + PUINT_8 pucKey, PUINT_8 pucValue, PVOID pPrivate, UINT_32 u4Flags); + +/* Type definition for STA_RECORD_T structure to handle the connectivity and packet reception + * for a particular STA. + */ +typedef struct _STA_RECORD_T STA_RECORD_T, *P_STA_RECORD_T, **PP_STA_RECORD_T; + +/* CMD_INFO_T is used by Glue Layer to send a cluster of Command(OID) information to + * the TX Path to reduce the parameters of a function call. + */ +typedef struct _CMD_INFO_T CMD_INFO_T, *P_CMD_INFO_T; + +/* Following typedef should be removed later, because Glue Layer should not + * be aware of following data type. + */ +typedef struct _SW_RFB_T SW_RFB_T, *P_SW_RFB_T, **PP_SW_RFB_T; + +typedef struct _MSDU_INFO_T MSDU_INFO_T, *P_MSDU_INFO_T; + +typedef struct _REG_ENTRY_T REG_ENTRY_T, *P_REG_ENTRY_T; + +/* IST handler definition */ +typedef VOID(*IST_EVENT_FUNCTION) (P_ADAPTER_T); + +/* Type definition for function pointer of timer handler */ +typedef VOID(*PFN_TIMER_CALLBACK) (IN P_GLUE_INFO_T); +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _TYPEDEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/wlan_bow.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/wlan_bow.h new file mode 100644 index 0000000000000..289b7e202ea4f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/wlan_bow.h @@ -0,0 +1,302 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +#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 + +extern UINT_32 g_arBowRevPalPacketTime[32]; + +/******************************************************************************* +* 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, + IN UINT_8 ucBssIdx, + 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); + +UINT_8 bowInit(IN P_ADAPTER_T prAdapter); + +VOID bowUninit(IN P_ADAPTER_T prAdapter); + +VOID wlanbowCmdTimeoutHandler(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +VOID bowStopping(IN P_ADAPTER_T prAdapter); + +VOID bowStarting(IN P_ADAPTER_T prAdapter); + +VOID bowAssignSsid(IN PUINT_8 pucSsid, IN PUINT_8 pucSsidLen); + +BOOLEAN bowValidateProbeReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_32 pu4ControlFlags); + +VOID bowSendBeacon(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr); + +VOID bowResponderScan(IN P_ADAPTER_T prAdapter); + +VOID bowResponderScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID bowResponderCancelScan(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsChannelExtention); + +VOID bowResponderJoin(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc); + +VOID bowFsmRunEventJoinComplete(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID +bowIndicationOfMediaStateToHost(IN P_ADAPTER_T prAdapter, + ENUM_PARAM_MEDIA_STATE_T eConnectionState, BOOLEAN fgDelayIndication); + +VOID bowRunEventAAATxFail(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +WLAN_STATUS bowRunEventAAAComplete(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +WLAN_STATUS bowRunEventRxDeAuth(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb); + +VOID bowDisconnectLink(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +BOOLEAN bowValidateAssocReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu2StatusCode); + +BOOLEAN +bowValidateAuth(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, IN PP_STA_RECORD_T pprStaRec, OUT PUINT_16 pu2StatusCode); + +VOID bowRunEventChGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID bowRequestCh(IN P_ADAPTER_T prAdapter); + +VOID bowReleaseCh(IN P_ADAPTER_T prAdapter); + +VOID bowChGrantedTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); + +BOOLEAN bowNotifyAllLinkDisconnected(IN P_ADAPTER_T prAdapter); + +BOOLEAN bowCheckBowTableIfVaild(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6]); + +BOOLEAN bowGetBowTableContent(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBowTableIdx, OUT P_BOW_TABLE_T prBowTable); + +BOOLEAN +bowGetBowTableEntryByPeerAddress(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6], OUT PUINT_8 pucBowTableIdx); + +BOOLEAN bowGetBowTableFreeEntry(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucBowTableIdx); + +ENUM_BOW_DEVICE_STATE bowGetBowTableState(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6]); + +BOOLEAN bowSetBowTableState(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6], IN ENUM_BOW_DEVICE_STATE eState); + +BOOLEAN bowSetBowTableContent(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBowTableIdx, IN P_BOW_TABLE_T prBowTable); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif +#endif /* _WLAN_BOW_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/wlan_lib.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/wlan_lib.h new file mode 100644 index 0000000000000..d2ce3244e3336 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/wlan_lib.h @@ -0,0 +1,1508 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/wlan_lib.h#3 +*/ + +/*! \file "wlan_lib.h" +* \brief The declaration of the functions of the wlanAdpater objects +* +* Detail description. +*/ + + +#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 "nic_init_cmd_event.h" + +#if CFG_SUPPORT_CSI +struct CSI_DATA_T; +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define MAX_NUM_GROUP_ADDR 32 /* max number of group addresses */ +#define AUTO_RATE_NUM 8 +#define AR_RATE_TABLE_ENTRY_MAX 25 +#define AR_RATE_ENTRY_INDEX_NULL 0x80 + +#define TX_CS_TCP_UDP_GEN BIT(1) +#define TX_CS_IP_GEN BIT(0) + +#define CSUM_OFFLOAD_EN_TX_TCP BIT(0) +#define CSUM_OFFLOAD_EN_TX_UDP BIT(1) +#define CSUM_OFFLOAD_EN_TX_IP BIT(2) +#define CSUM_OFFLOAD_EN_RX_TCP BIT(3) +#define CSUM_OFFLOAD_EN_RX_UDP BIT(4) +#define CSUM_OFFLOAD_EN_RX_IPv4 BIT(5) +#define CSUM_OFFLOAD_EN_RX_IPv6 BIT(6) +#define CSUM_OFFLOAD_EN_TX_MASK BITS(0, 2) +#define CSUM_OFFLOAD_EN_ALL BITS(0, 6) + +/* TCP, UDP, IP Checksum */ +#define RX_CS_TYPE_UDP BIT(7) +#define RX_CS_TYPE_TCP BIT(6) +#define RX_CS_TYPE_IPv6 BIT(5) +#define RX_CS_TYPE_IPv4 BIT(4) + +#define RX_CS_STATUS_UDP BIT(3) +#define RX_CS_STATUS_TCP BIT(2) +#define RX_CS_STATUS_IP BIT(0) + +#define CSUM_NOT_SUPPORTED 0x0 + +#define TXPWR_USE_PDSLOPE 0 + +/* NVRAM error code definitions */ +#define NVRAM_ERROR_VERSION_MISMATCH BIT(1) +#define NVRAM_ERROR_INVALID_TXPWR BIT(2) +#define NVRAM_ERROR_INVALID_DPD BIT(3) +#define NVRAM_ERROR_INVALID_MAC_ADDR BIT(4) +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY +#define NVRAM_POWER_LIMIT_TABLE_INVALID BIT(5) +#endif + +#define NUM_TC_RESOURCE_TO_STATISTICS 4 + +#define WLAN_CFG_ARGV_MAX 23 +#define WLAN_CFG_ARGV_MAX_LONG 22 /* for WOW, 2+20 */ +#define WLAN_CFG_ENTRY_NUM_MAX 200 /* 128 */ +#define WLAN_CFG_KEY_LEN_MAX 32 /* include \x00 EOL */ +#define WLAN_CFG_VALUE_LEN_MAX 32 /* include \x00 EOL */ +#define WLAN_CFG_FLAG_SKIP_CB BIT(0) +#define WLAN_CFG_FILE_BUF_SIZE 2048 + +#define WLAN_CFG_REC_ENTRY_NUM_MAX 200 +#define WLAN_CFG_REC_FLAG_BIT BIT(0) + + +#define WLAN_CFG_SET_CHIP_LEN_MAX 10 +#define WLAN_CFG_SET_DEBUG_LEVEL_LEN_MAX 10 +#define WLAN_CFG_SET_SW_CTRL_LEN_MAX 10 + + +#define WLAN_OID_TIMEOUT_THRESHOLD 2000 /* OID timeout (in ms) */ +#define WLAN_OID_TIMEOUT_THRESHOLD_MAX 10000 /* OID max timeout (in ms) */ +#define WLAN_OID_TIMEOUT_THRESHOLD_IN_RESETTING 300 /* OID timeout during chip-resetting (in ms) */ + +#define WLAN_OID_NO_ACK_THRESHOLD 3 + +#define WLAN_THREAD_TASK_PRIORITY 0 /* If not setting the priority, 0 is the default */ +#define WLAN_THREAD_TASK_NICE (-10) /* If not setting the nice, -10 is the default */ + +#define WLAN_TX_STATS_LOG_TIMEOUT 30000 +#define WLAN_TX_STATS_LOG_DURATION 1500 + +/* Define for wifi path usage */ +#define WLAN_FLAG_2G4_WF0 BIT(0) /*1: support, 0: NOT support */ +#define WLAN_FLAG_5G_WF0 BIT(1) /*1: support, 0: NOT support */ +#define WLAN_FLAG_2G4_WF1 BIT(2) /*1: support, 0: NOT support */ +#define WLAN_FLAG_5G_WF1 BIT(3) /*1: support, 0: NOT support */ +#define WLAN_FLAG_2G4_COANT_SUPPORT BIT(4) /*1: support, 0: NOT support */ +#define WLAN_FLAG_2G4_COANT_PATH BIT(5) /*1: WF1, 0:WF0 */ +#define WLAN_FLAG_5G_COANT_SUPPORT BIT(6) /*1: support, 0: NOT support */ +#define WLAN_FLAG_5G_COANT_PATH BIT(7) /*1: WF1, 0:WF0 */ + +#if CFG_SUPPORT_EASY_DEBUG + +#define MAX_CMD_ITEM_MAX 4 /* Max item per cmd. */ +#define MAX_CMD_NAME_MAX_LENGTH 32 /* Max name string length */ +#define MAX_CMD_VALUE_MAX_LENGTH 32 /* Max value string length */ +#define MAX_CMD_TYPE_LENGTH 1 +#define MAX_CMD_STRING_LENGTH 1 +#define MAX_CMD_VALUE_LENGTH 1 +#define MAX_CMD_RESERVE_LENGTH 1 + +#define CMD_FORMAT_V1_LENGTH \ + (MAX_CMD_NAME_MAX_LENGTH + MAX_CMD_VALUE_MAX_LENGTH + \ + MAX_CMD_TYPE_LENGTH + MAX_CMD_STRING_LENGTH + MAX_CMD_VALUE_LENGTH + MAX_CMD_RESERVE_LENGTH) + +#define MAX_CMD_BUFFER_LENGTH (CMD_FORMAT_V1_LENGTH * MAX_CMD_ITEM_MAX) + +#if 1 +#define ED_STRING_SITE 0 +#define ED_VALUE_SITE 1 + + +#else +#define ED_ITEMTYPE_SITE 0 +#define ED_STRING_SITE 1 +#define ED_VALUE_SITE 2 +#endif + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +#define ACS_AP_RSSI_LEVEL_HIGH -50 +#define ACS_AP_RSSI_LEVEL_LOW -80 +#define ACS_DIRTINESS_LEVEL_HIGH 52 +#define ACS_DIRTINESS_LEVEL_MID 40 +#define ACS_DIRTINESS_LEVEL_LOW 32 +#endif + +#if CFG_WOW_SUPPORT +#define INVALID_WOW_WAKE_UP_REASON 255 +#endif + +#if CFG_SUPPORT_ADVANCE_CONTROL +#define KEEP_FULL_PWR_TRAFFIC_REPORT_BIT BIT(0) +#define KEEP_FULL_PWR_NOISE_HISTOGRAM_BIT BIT(1) +#endif + +typedef enum _CMD_VER_T { + CMD_VER_1, /* Type[2]+String[32]+Value[32] */ + CMD_VER_2 /* for furtur define. */ +} CMD_VER_T, *P_CMD_VER_T; + + +#if 0 +typedef enum _ENUM_AIS_REQUEST_TYPE_T { + AIS_REQUEST_SCAN, + AIS_REQUEST_RECONNECT, + AIS_REQUEST_ROAMING_SEARCH, + AIS_REQUEST_ROAMING_CONNECT, + AIS_REQUEST_REMAIN_ON_CHANNEL, + AIS_REQUEST_NUM +} ENUM_AIS_REQUEST_TYPE_T; +#endif +typedef enum _CMD_TYPE_T { + CMD_TYPE_QUERY, + CMD_TYPE_SET +} CMD_TYPE_T, *P_CMD_TYPE_T; + + +#define ITEM_TYPE_DEC 1 +#define ITEM_TYPE_HEX 2 +#define ITEM_TYPE_STR 3 + +typedef enum _CMD_DEFAULT_SETTING_VALUE { + CMD_PNO_ENABLE, + CMD_PNO_SCAN_PERIOD, + CMD_SCN_CHANNEL_PLAN, + CMD_SCN_DWELL_TIME, + CMD_SCN_STOP_SCAN, + CMD_MAX, +} CMD_DEFAULT_SETTING_VALUE; + +typedef enum _CMD_DEFAULT_STR_SETTING_VALUE { + CMD_STR_TEST_STR, + CMD_STR_MAX, +} CMD_DEFAULT_STR_SETTING_VALUE; + +typedef struct _CMD_FORMAT_V1_T { + UINT_8 itemType; + UINT_8 itemStringLength; + UINT_8 itemValueLength; + UINT_8 Reserved; + UINT_8 itemString[MAX_CMD_NAME_MAX_LENGTH]; + UINT_8 itemValue[MAX_CMD_VALUE_MAX_LENGTH]; +} CMD_FORMAT_V1_T, *P_CMD_FORMAT_V1_T; + +typedef struct _CMD_HEADER_T { + CMD_VER_T cmdVersion; + CMD_TYPE_T cmdType; + UINT_8 itemNum; + UINT_16 cmdBufferLen; + UINT_8 buffer[MAX_CMD_BUFFER_LENGTH]; +} CMD_HEADER_T, *P_CMD_HEADER_T; + +typedef struct _CFG_DEFAULT_SETTING_TABLE_T { + UINT_32 itemNum; + const char *String; + UINT_8 itemType; + UINT_32 defaultValue; + UINT_32 minValue; + UINT_32 maxValue; +} CFG_DEFAULT_SETTING_TABLE_T, *P_CFG_DEFAULT_SETTING_TABLE_T; + +typedef struct _CFG_DEFAULT_SETTING_STR_TABLE_T { + UINT_32 itemNum; + const char *String; + UINT_8 itemType; + const char *DefString; + UINT_16 minLen; + UINT_16 maxLen; +} CFG_DEFAULT_SETTING_STR_TABLE_T, *P_CFG_DEFAULT_SETTING_STR_TABLE_T; + +typedef struct _CFG_QUERY_FORMAT_T { + UINT_32 Length; + UINT_32 Value; + UINT_32 Type; + PUINT_32 ptr; +} CFG_QUERY_FORMAT_T, *P_CFG_QUERY_FORMAT_T; + +/*Globol Configure define */ +typedef struct _CFG_SETTING_T { + UINT_8 PnoEnable; + UINT_32 PnoScanPeriod; + UINT_8 ScnChannelPlan; + UINT_16 ScnDwellTime; + UINT_8 ScnStopScan; + UINT_8 TestStr[80]; + +} CFG_SETTING_T, *P_CFG_SETTING_T; + +#endif + +/******************************************************************************* +* 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 enum _ENUM_FEATURE_OPTION_T { + FEATURE_DISABLED, + FEATURE_ENABLED, + FEATURE_FORCE_ENABLED +} ENUM_FEATURE_OPTION_T, *P_ENUM_FEATURE_OPTION_T; + +/* This enum is for later added feature options which use command reserved field as option switch */ +typedef enum _ENUM_FEATURE_OPTION_IN_CMD_T { + FEATURE_OPT_CMD_AUTO, + FEATURE_OPT_CMD_DISABLED, + FEATURE_OPT_CMD_ENABLED, + FEATURE_OPT_CMD_FORCE_ENABLED +} ENUM_FEATURE_OPTION_IN_CMD_T, *P_ENUM_FEATURE_OPTION_IN_CMD_T; + +#define DEBUG_MSG_SIZE_MAX 1200 +enum { + DEBUG_MSG_ID_UNKNOWN = 0x00, + DEBUG_MSG_ID_PRINT = 0x01, + DEBUG_MSG_ID_FWLOG = 0x02, + DEBUG_MSG_ID_END +}; + +enum { + DEBUG_MSG_TYPE_UNKNOWN = 0x00, + DEBUG_MSG_TYPE_MEM8 = 0x01, + DEBUG_MSG_TYPE_MEM32 = 0x02, + DEBUG_MSG_TYPE_ASCII = 0x03, + DEBUG_MSG_TYPE_BINARY = 0x04, + DEBUG_MSG_TYPE_END +}; + +#define CHIP_CONFIG_RESP_SIZE 320 +enum { + CHIP_CONFIG_TYPE_WO_RESPONSE = 0x00, + CHIP_CONFIG_TYPE_MEM8 = 0x01, + CHIP_CONFIG_TYPE_MEM32 = 0x02, + CHIP_CONFIG_TYPE_ASCII = 0x03, + CHIP_CONFIG_TYPE_BINARY = 0x04, + CHIP_CONFIG_TYPE_DRV_PASSTHROUGH = 0x05, + CHIP_CONFIG_TYPE_END +}; + +typedef struct _SET_TXPWR_CTRL_T { + INT_8 c2GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0 */ + INT_8 c2GHotspotPwrOffset; + INT_8 c2GP2pPwrOffset; + INT_8 c2GBowPwrOffset; + INT_8 c5GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0 */ + INT_8 c5GHotspotPwrOffset; + INT_8 c5GP2pPwrOffset; + INT_8 c5GBowPwrOffset; + UINT_8 ucConcurrencePolicy; /* TX power policy when concurrence + * in the same channel + * 0: Highest power has priority + * 1: Lowest power has priority + */ + INT_8 acReserved1[3]; /* Must be zero */ + + /* Power limit by channel for all data rates */ + INT_8 acTxPwrLimit2G[14]; /* Channel 1~14, Unit: 0.5dBm */ + INT_8 acTxPwrLimit5G[4]; /* UNII 1~4 */ + INT_8 acReserved2[2]; /* Must be zero */ +} SET_TXPWR_CTRL_T, *P_SET_TXPWR_CTRL_T; + +#if CFG_WOW_SUPPORT + +typedef struct _WOW_WAKE_HIF_T { + UINT_8 ucWakeupHif; /* use in-band signal to wakeup system, ENUM_HIF_TYPE */ + UINT_8 ucGpioPin; /* GPIO Pin */ + UINT_8 ucTriggerLvl; /* refer to PF_WAKEUP_CMD_BIT0_OUTPUT_MODE_EN */ + UINT_32 u4GpioInterval;/* non-zero means output reverse wakeup signal after delay time */ + UINT_8 aucResv[5]; +} WOW_WAKE_HIF_T, *P_WOW_WAKE_HIF_T; + +typedef struct _WOW_PORT_T { + UINT_8 ucIPv4UdpPortCnt; + UINT_8 ucIPv4TcpPortCnt; + UINT_8 ucIPv6UdpPortCnt; + UINT_8 ucIPv6TcpPortCnt; + UINT_16 ausIPv4UdpPort[MAX_TCP_UDP_PORT]; + UINT_16 ausIPv4TcpPort[MAX_TCP_UDP_PORT]; + UINT_16 ausIPv6UdpPort[MAX_TCP_UDP_PORT]; + UINT_16 ausIPv6TcpPort[MAX_TCP_UDP_PORT]; +} WOW_PORT_T, *P_WOW_PORT_T; + +typedef struct _WOW_CTRL_T { + UINT_8 fgWowEnable; /* 0: disable, 1: wow enable */ + UINT_8 ucScenarioId; /* just a profile ID */ + UINT_8 ucBlockCount; + UINT_8 aucReserved1[1]; + WOW_WAKE_HIF_T astWakeHif[2]; + WOW_PORT_T stWowPort; + UINT_8 ucReason; +} WOW_CTRL_T, *P_WOW_CTRL_T; + +#define MDNS_NAME_MAX_LEN 100 +#define MDNS_RESPONSE_RECORD_MAX_LEN 500 +#define MDNS_TXT_RR_DATA_MAX_LEN 300 +#define MDNS_SRV_RR_LEN 16 +#define MDNS_TXT_RR_MAX_LEN 310 +#define MDNS_QUESTION_NAME_MAX_LEN 102 +#define MDNS_SERVICE_NAME_MAX_LEN 102 +#define MDNS_A_RR_LEN 14 + +struct MDNS_PARAM_T { + UINT_8 ucCmd; + UINT_32 u4RecordId; + UINT_8 ucQueryName[MDNS_NAME_MAX_LEN]; + UINT_16 u2QueryNameLen; + UINT_16 u2QueryType; + UINT_16 u2QueryClass; + UINT_8 ucResponseRecord[MDNS_RESPONSE_RECORD_MAX_LEN]; + UINT_16 u2ResponseRecordLen; + UINT_8 ucServiceName[MDNS_NAME_MAX_LEN]; + UINT_16 u2ServiceNameLen; + UINT_8 ucServiceType[MDNS_NAME_MAX_LEN]; + UINT_16 u2ServiceTypeLen; + UINT_8 ucDomainName[MDNS_NAME_MAX_LEN]; + UINT_16 u2DomainNameLen; + UINT_8 ucHostName[MDNS_NAME_MAX_LEN]; + UINT_16 u2HostNameLen; + UINT_32 u4Port; + UINT_8 ucTxtRecord[MDNS_TXT_RR_DATA_MAX_LEN]; + UINT_16 u2TxtRecordLen; +}; + +struct WLAN_MAC_HEADER_QoS_T { + UINT_16 u2FrameCtrl; + UINT_16 DurationID; + UINT_8 aucAddr1[MAC_ADDR_LEN]; + UINT_8 aucAddr2[MAC_ADDR_LEN]; + UINT_8 aucAddr3[MAC_ADDR_LEN]; + UINT_16 u2SeqCtrl; + UINT_16 u2QosCtrl; +}; + +#define UDP_HEADER_LENGTH 8 +#define IPV4_HEADER_LENGTH 20 + +struct MDNS_ANSWER_RR { + UINT_8 data[MDNS_RESPONSE_RECORD_MAX_LEN]; + UINT_16 data_length; +}; + +struct MDNS_SRV_RR { + UINT_8 data[MDNS_SRV_RR_LEN]; + UINT_16 data_length; +}; + +struct MDNS_TXT_RR { + UINT_8 data[MDNS_TXT_RR_MAX_LEN]; + UINT_16 data_length; +}; + +struct MDNS_QUESTION { + UINT_8 name[MDNS_QUESTION_NAME_MAX_LEN]; + UINT_8 name_length; + UINT_8 label_count; + UINT_16 class; + UINT_16 type; +}; + +struct MDNS_Template_Record { + UINT_32 u4RecordId; + struct MDNS_QUESTION mdnsQuestionTemplate; + struct MDNS_ANSWER_RR mdnsResponseRecord; + UINT_8 ucServiceName[MDNS_SERVICE_NAME_MAX_LEN]; + UINT_16 ServiceNameLen; + struct MDNS_TXT_RR mdnsTxtRecord; + struct MDNS_SRV_RR mdnsSrvRecord; + BOOLEAN bIsUsed; +}; + +struct CMD_MDNS_PARAM_T { + UINT_8 ucCmd; + UINT_32 u4RecordId; + struct WLAN_MAC_HEADER_QoS_T aucMdnsMacHdr; + UINT_8 aucMdnsIPHdr[IPV4_HEADER_LENGTH]; + UINT_8 aucMdnsUdpHdr[UDP_HEADER_LENGTH]; + UINT_8 mdnsARecord[MDNS_A_RR_LEN]; + struct MDNS_Template_Record mdnsQueryRespTemplate; +}; +#endif + +typedef enum _ENUM_NVRAM_MTK_FEATURE_T { + MTK_FEATURE_2G_256QAM_DISABLED = 0, + MTK_FEATURE_NUM +} ENUM_NVRAM_MTK_FEATURES_T, *P_ENUM_NVRAM_MTK_FEATURES_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 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- */ +#if 1 + UINT_16 u2Part1OwnVersion; + UINT_16 u2Part1PeerVersion; +#endif + 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; + RSSI_PATH_COMPASATION_T rRssiPathCompasation; + UINT_8 ucRssiPathCompasationUsed; + /* NVRAM - MP Data -END- */ + + /* NVRAM - Functional Data -START- */ + UINT_8 uc2G4BwFixed20M; + UINT_8 uc5GBwFixed20M; + UINT_8 ucEnable5GBand; + UINT_8 ucGpsDesense; + UINT_8 ucRxDiversity; + /* NVRAM - Functional Data -END- */ + + P_NEW_EFUSE_MAPPING2NVRAM_T prOldEfuseMapping; + + UINT_8 aucNvram[512]; + P_WIFI_CFG_PARAM_STRUCT prNvramSettings; + +} REG_INFO_T, *P_REG_INFO_T; + +/* for divided firmware loading */ +typedef struct _FWDL_SECTION_INFO_T { +#if 0 + UINT_32 u4Offset; + UINT_32 u4Reserved; + UINT_32 u4Length; + UINT_32 u4DestAddr; +#endif + UINT_32 u4DestAddr; + UINT_8 ucChipInfo; + UINT_8 ucFeatureSet; + UINT_8 ucEcoCode; + UINT_8 aucReserved[9]; + UINT_8 aucBuildDate[16]; + UINT_32 u4Length; +} FWDL_SECTION_INFO_T, *P_FWDL_SECTION_INFO_T; + +typedef struct _FIRMWARE_DIVIDED_DOWNLOAD_T { +#if 0 + UINT_32 u4Signature; + UINT_32 u4CRC; /* CRC calculated without first 8 bytes included */ + UINT_32 u4NumOfEntries; + UINT_32 u4Reserved; + FWDL_SECTION_INFO_T arSection[]; +#endif + FWDL_SECTION_INFO_T arSection[2]; +} FIRMWARE_DIVIDED_DOWNLOAD_T, *P_FIRMWARE_DIVIDED_DOWNLOAD_T; + +#if (CFG_UMAC_GENERATION >= 0x20) +#define LEN_4_BYTE_CRC (4) + +typedef struct _tailer_format_tag { + UINT_32 addr; + UINT_8 chip_info; + UINT_8 feature_set; + UINT_8 eco_code; + UINT_8 ram_version[10]; + UINT_8 ram_built_date[15]; + UINT_32 len; + +} tailer_format_t; + +typedef struct _fw_image_tailer_tag { + tailer_format_t ilm_info; + tailer_format_t dlm_info; +} fw_image_tailer_t; +#if CFG_SUPPORT_COMPRESSION_FW_OPTION +typedef struct _tailer_format_tag_2 { + UINT_32 crc; + UINT_32 addr; + UINT_32 block_size; + UINT_32 real_size; + UINT_8 chip_info; + UINT_8 feature_set; + UINT_8 eco_code; + UINT_8 ram_version[10]; + UINT_8 ram_built_date[15]; + UINT_32 len; +} tailer_format_t_2; +typedef struct _fw_image_tailer_tag_2 { + tailer_format_t_2 ilm_info; + tailer_format_t_2 dlm_info; +} fw_image_tailer_t_2; +typedef struct _fw_image_tailer_check { + UINT_8 chip_info; + UINT_8 feature_set; + UINT_8 eco_code; + UINT_8 ram_version[10]; + UINT_8 ram_built_date[15]; + UINT_32 len; +} fw_image_tailer_check; +#endif +typedef struct _PATCH_FORMAT_T { + UINT_8 aucBuildDate[16]; + UINT_8 aucPlatform[4]; + UINT_32 u4SwHwVersion; + UINT_32 u4PatchVersion; + UINT_16 u2CRC; /* CRC calculated for image only */ + UINT_8 ucPatchImage[0]; +} PATCH_FORMAT_T, *P_PATCH_FORMAT_T; + +#if 0 +#define DATA_MODE_BIT_SHFT_ENCRYPT_MODE (0) /* bit0 */ +#define DATA_MODE_MASK_ENCRYPT_MODE (0x01 << DATA_MODE_BIT_SHFT_ENCRYPT_MODE) /* bit0 */ + +#define DATA_MODE_BIT_SHFT_KEY_INDEX (1) /* bit[2:1] */ +#define DATA_MODE_MASK_KEY_INDEX (0x03 << DATA_MODE_BIT_SHFT_KEY_INDEX) /* bit[2:1] */ + +#define DATA_MODE_BIT_SHFT_RESET_IV (3) /* bit3 */ +#define DATA_MODE_MASK_RESET_IV (0x1 << DATA_MODE_BIT_SHFT_RESET_IV) + +#define DATA_MODE_BIT_SHFT_WORKING_PDA_OPTION (4) /* bit4 */ +#define DATA_MODE_MASK_WORKING_PDA_OPTION (0x1 << DATA_MODE_BIT_SHFT_WORKING_PDA_OPTION) + +#define DATA_MODE_BIT_SHFT_NEED_ACK (31) /* bit31 */ +#define DATA_MODE_MASK_NEED_ACK (0x01 << DATA_MODE_BIT_SHFT_NEED_ACK) /* bit31 */ +#endif + +/* PDA - Patch Decryption Accelerator */ +#define PDA_N9 0 +#define PDA_CR4 1 + +#define CR4_FWDL_SECTION_NUM HIF_CR4_FWDL_SECTION_NUM +#define IMG_DL_STATUS_PORT_IDX HIF_IMG_DL_STATUS_PORT_IDX + +typedef enum _ENUM_IMG_DL_IDX_T { + IMG_DL_IDX_N9_FW, + IMG_DL_IDX_CR4_FW, + IMG_DL_IDX_PATCH +} ENUM_IMG_DL_IDX_T, *P_ENUM_IMG_DL_IDX_T; + +#endif + +typedef struct _PARAM_MCR_RW_STRUCT_T { + UINT_32 u4McrOffset; + UINT_32 u4McrData; +} PARAM_MCR_RW_STRUCT_T, *P_PARAM_MCR_RW_STRUCT_T; + +/* per access category statistics */ +typedef struct _WIFI_WMM_AC_STAT_T { + UINT_32 u4TxMsdu; + UINT_32 u4RxMsdu; + UINT_32 u4TxDropMsdu; + UINT_32 u4TxFailMsdu; + UINT_32 u4TxRetryMsdu; +} WIFI_WMM_AC_STAT_T, *P_WIFI_WMM_AC_STAT_T; + +typedef struct _TX_VECTOR_BBP_LATCH_T { + UINT_32 u4TxVector1; + UINT_32 u4TxVector2; + UINT_32 u4TxVector4; +} TX_VECTOR_BBP_LATCH_T, *P_TX_VECTOR_BBP_LATCH_T; + +typedef struct _MIB_INFO_STAT_T { + UINT_32 u4RxMpduCnt; + UINT_32 u4FcsError; + UINT_32 u4RxFifoFull; + UINT_32 u4AmpduTxSfCnt; + UINT_32 u4AmpduTxAckSfCnt; + UINT_16 u2TxRange1AmpduCnt; + UINT_16 u2TxRange2AmpduCnt; + UINT_16 u2TxRange3AmpduCnt; + UINT_16 u2TxRange4AmpduCnt; + UINT_16 u2TxRange5AmpduCnt; + UINT_16 u2TxRange6AmpduCnt; + UINT_16 u2TxRange7AmpduCnt; + UINT_16 u2TxRange8AmpduCnt; +} MIB_INFO_STAT_T, *P_MIB_INFO_STAT_T; + +typedef struct _PARAM_GET_STA_STATISTICS { + /* Per-STA statistic */ + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + + UINT_32 u4Flag; + + UINT_8 ucReadClear; + UINT_8 ucLlsReadClear; + + /* From driver */ + UINT_32 u4TxTotalCount; + UINT_32 u4TxExceedThresholdCount; + + UINT_32 u4TxMaxTime; + UINT_32 u4TxAverageProcessTime; + + UINT_32 u4RxTotalCount; + + UINT_32 au4TcResourceEmptyCount[NUM_TC_RESOURCE_TO_STATISTICS]; + UINT_32 au4TcQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + + /* From FW */ + UINT_8 ucPer; /* base: 128 */ + UINT_8 ucRcpi; + UINT_32 u4PhyMode; + UINT_16 u2LinkSpeed; /* unit is 0.5 Mbits */ + + UINT_32 u4TxFailCount; + UINT_32 u4TxLifeTimeoutCount; + + UINT_32 u4TxAverageAirTime; + UINT_32 u4TransmitCount; /* Transmit in the air (wtbl) */ + UINT_32 u4TransmitFailCount; /* Transmit without ack/ba in the air (wtbl) */ + + WIFI_WMM_AC_STAT_T arLinkStatistics[AC_NUM]; /*link layer statistics */ + + /* Global queue management statistic */ + UINT_32 au4TcAverageQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + UINT_32 au4TcCurrentQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + + UINT_8 ucTemperature; + UINT_8 ucSkipAr; + UINT_8 ucArTableIdx; + UINT_8 ucRateEntryIdx; + UINT_8 ucRateEntryIdxPrev; + UINT_8 ucTxSgiDetectPassCnt; + UINT_8 ucAvePer; + UINT_8 aucArRatePer[AR_RATE_TABLE_ENTRY_MAX]; + UINT_8 aucRateEntryIndex[AUTO_RATE_NUM]; + UINT_8 ucArStateCurr; + UINT_8 ucArStatePrev; + UINT_8 ucArActionType; + UINT_8 ucHighestRateCnt; + UINT_8 ucLowestRateCnt; + UINT_16 u2TrainUp; + UINT_16 u2TrainDown; + UINT_32 u4Rate1TxCnt; + UINT_32 u4Rate1FailCnt; + TX_VECTOR_BBP_LATCH_T rTxVector[ENUM_BAND_NUM]; + MIB_INFO_STAT_T rMibInfo[ENUM_BAND_NUM]; + UINT_8 ucResetCounter; + BOOLEAN fgIsForceTxStream; + BOOLEAN fgIsForceSeOff; + + /* Reserved fields */ + UINT_8 au4Reserved[20]; +} PARAM_GET_STA_STA_STATISTICS, *P_PARAM_GET_STA_STATISTICS; + +typedef struct _PARAM_GET_BSS_STATISTICS { + /* Per-STA statistic */ + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + + UINT_32 u4Flag; + + UINT_8 ucReadClear; + + UINT_8 ucLlsReadClear; + + UINT_8 ucBssIndex; + + /* From driver */ + UINT_32 u4TxTotalCount; + UINT_32 u4TxExceedThresholdCount; + + UINT_32 u4TxMaxTime; + UINT_32 u4TxAverageProcessTime; + + UINT_32 u4RxTotalCount; + + UINT_32 au4TcResourceEmptyCount[NUM_TC_RESOURCE_TO_STATISTICS]; + UINT_32 au4TcQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + + /* From FW */ + UINT_8 ucPer; /* base: 128 */ + UINT_8 ucRcpi; + UINT_32 u4PhyMode; + UINT_16 u2LinkSpeed; /* unit is 0.5 Mbits */ + + UINT_32 u4TxFailCount; + UINT_32 u4TxLifeTimeoutCount; + + UINT_32 u4TxAverageAirTime; + UINT_32 u4TransmitCount; /* Transmit in the air (wtbl) */ + UINT_32 u4TransmitFailCount; /* Transmit without ack/ba in the air (wtbl) */ + + WIFI_WMM_AC_STAT_T arLinkStatistics[AC_NUM]; /*link layer statistics */ + + /* Global queue management statistic */ + UINT_32 au4TcAverageQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + UINT_32 au4TcCurrentQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + + /* Reserved fields */ + UINT_8 au4Reserved[32]; /* insufficient for LLS?? */ +} PARAM_GET_BSS_STATISTICS, *P_PARAM_GET_BSS_STATISTICS; + +typedef struct _PARAM_GET_DRV_STATISTICS { + INT_32 i4TxPendingFrameNum; + INT_32 i4TxPendingSecurityFrameNum; + INT_32 i4TxPendingCmdNum; + INT_32 i4PendingFwdFrameCount; /* sync i4PendingFwdFrameCount in _TX_CTRL_T */ + UINT_32 u4MsduNumElem; /* sync pad->rTxCtrl.rFreeMsduInfoList.u4NumElem */ + UINT_32 u4TxMgmtTxringQueueNumElem; /* sync pad->rTxCtrl.rTxMgmtTxingQueue.u4NumElem */ + + UINT_32 u4RxFreeSwRfbMsduNumElem; /* sync pad->prRxCtrl.rFreeSwRfbList.u4NumElem */ + UINT_32 u4RxReceivedRfbNumElem; /* sync pad->prRxCtrl.rReceivedRfbList.u4NumElem */ + UINT_32 u4RxIndicatedNumElem; /* sync pad->prRxCtrl.rIndicatedRfbList.u4NumElem */ +} PARAM_GET_DRV_STATISTICS, *P_PARAM_GET_DRV_STATISTICS; + +typedef struct _NET_INTERFACE_INFO_T { + UINT_8 ucBssIndex; + PVOID pvNetInterface; +} NET_INTERFACE_INFO_T, *P_NET_INTERFACE_INFO_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_BIP_ERROR, + TX_RESULT_UNSPECIFIED_ERROR, + TX_RESULT_DROPPED_IN_DRIVER = 32, + TX_RESULT_DROPPED_IN_FW, + TX_RESULT_QUEUE_CLEARANCE, + TX_RESULT_NUM +} ENUM_TX_RESULT_CODE_T, *P_ENUM_TX_RESULT_CODE_T; + +struct _WLAN_CFG_ENTRY_T { + UINT_8 aucKey[WLAN_CFG_KEY_LEN_MAX]; + UINT_8 aucValue[WLAN_CFG_VALUE_LEN_MAX]; + WLAN_CFG_SET_CB pfSetCb; + PVOID pPrivate; + UINT_32 u4Flags; +}; + +struct _WLAN_CFG_T { + UINT_32 u4WlanCfgEntryNumMax; + UINT_32 u4WlanCfgKeyLenMax; + UINT_32 u4WlanCfgValueLenMax; + WLAN_CFG_ENTRY_T arWlanCfgBuf[WLAN_CFG_ENTRY_NUM_MAX]; +}; + +struct _WLAN_CFG_REC_T { + UINT_32 u4WlanCfgEntryNumMax; + UINT_32 u4WlanCfgKeyLenMax; + UINT_32 u4WlanCfgValueLenMax; + WLAN_CFG_ENTRY_T arWlanCfgBuf[WLAN_CFG_REC_ENTRY_NUM_MAX]; +}; + + +typedef enum _ENUM_MAX_BANDWIDTH_SETTING_T { + MAX_BW_20MHZ = 0, + MAX_BW_40MHZ, + MAX_BW_80MHZ, + MAX_BW_160MHZ, + MAX_BW_80_80_MHZ +} ENUM_MAX_BANDWIDTH_SETTING, *P_ENUM_MAX_BANDWIDTH_SETTING_T; + +typedef struct _TX_PACKET_INFO { + UINT_8 ucPriorityParam; + UINT_32 u4PacketLen; + UINT_8 aucEthDestAddr[MAC_ADDR_LEN]; + UINT_16 u2Flag; + +#if 0 + BOOLEAN fgIs1X; + BOOLEAN fgIsPAL; + BOOLEAN fgIs802_3; + BOOLEAN fgIsVlanExists; + BOOLEAN fgIsDhcp; + BOOLEAN fgIsArp; +#endif +} TX_PACKET_INFO, *P_TX_PACKET_INFO; + +typedef enum _ENUM_TX_PROFILING_TAG_T { + TX_PROF_TAG_OS_TO_DRV = 0, + TX_PROF_TAG_DRV_ENQUE, + TX_PROF_TAG_DRV_DEQUE, + TX_PROF_TAG_DRV_TX_DONE, + TX_PROF_TAG_MAC_TX_DONE +} ENUM_TX_PROFILING_TAG_T, *P_ENUM_TX_PROFILING_TAG_T; + +enum ENUM_WF_PATH_FAVOR_T { + ENUM_WF_NON_FAVOR = 0xff, + ENUM_WF_0_ONE_STREAM_PATH_FAVOR = 0, + ENUM_WF_1_ONE_STREAM_PATH_FAVOR = 1, + ENUM_WF_0_1_TWO_STREAM_PATH_FAVOR = 2, + ENUM_WF_0_1_DUP_STREAM_PATH_FAVOR = 3, +}; + +/******************************************************************************* +* P U B 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') + +#define IS_FEATURE_ENABLED(_ucFeature) \ + (((_ucFeature) == FEATURE_ENABLED) || ((_ucFeature) == FEATURE_FORCE_ENABLED)) +#define IS_FEATURE_FORCE_ENABLED(_ucFeature) ((_ucFeature) == FEATURE_FORCE_ENABLED) +#define IS_FEATURE_DISABLED(_ucFeature) ((_ucFeature) == FEATURE_DISABLED) + +/* This macro is for later added feature options which use command reserved field as option switch */ +/* 0: AUTO + * 1: Disabled + * 2: Enabled + * 3: Force disabled + */ +#define FEATURE_OPT_IN_COMMAND(_ucFeature) ((_ucFeature) + 1) + +/******************************************************************************* +* 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); + +#if CFG_SUPPORT_MULTITHREAD +WLAN_STATUS wlanSendCommandMthread(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +WLAN_STATUS wlanTxCmdMthread(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS wlanTxCmdDoneMthread(IN P_ADAPTER_T prAdapter); + +VOID wlanClearTxCommandQueue(IN P_ADAPTER_T prAdapter); + +VOID wlanClearTxCommandDoneQueue(IN P_ADAPTER_T prAdapter); + +VOID wlanClearDataQueue(IN P_ADAPTER_T prAdapter); + +VOID wlanClearRxToOsQueue(IN P_ADAPTER_T prAdapter); +#endif + +VOID wlanReleaseCommand(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +VOID wlanReleasePendingOid(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); + +VOID wlanReleasePendingCMDbyBssIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex); + +VOID wlanReturnPacketDelaySetupTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); + +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); + +WLAN_STATUS wlanAdapterStop(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS wlanCheckWifiFunc(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgRdyChk); + +#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_SUPPORT_COMPRESSION_FW_OPTION +WLAN_STATUS wlanImageSectionDownloadStage(IN P_ADAPTER_T prAdapter, + IN PVOID pvFwImageMapFile, IN UINT_32 u4FwImageFileLength, + UINT_8 ucSectionNumber, IN ENUM_IMG_DL_IDX_T eDlIdx, + OUT PUINT_8 ucIsCompressed, + OUT P_INIT_CMD_WIFI_DECOMPRESSION_START prFwImageInFo); +#else +WLAN_STATUS wlanImageSectionDownloadStage(IN P_ADAPTER_T prAdapter, + IN PVOID pvFwImageMapFile, IN UINT_32 u4FwImageFileLength, + UINT_8 ucSectionNumber, IN ENUM_IMG_DL_IDX_T eDlIdx); + +#endif + +#if CFG_ENABLE_FW_DOWNLOAD +WLAN_STATUS wlanImageSectionConfig(IN P_ADAPTER_T prAdapter, + IN UINT_32 u4DestAddr, IN UINT_32 u4ImgSecSize, IN UINT_32 u4DataMode, + IN ENUM_IMG_DL_IDX_T eDlIdx); + +WLAN_STATUS wlanImageSectionDownload(IN P_ADAPTER_T prAdapter, IN UINT_32 u4ImgSecSize, IN PUINT_8 pucImgSecBuf); + +WLAN_STATUS wlanImageQueryStatus(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS wlanImageSectionDownloadStatus(IN P_ADAPTER_T prAdapter, IN UINT_8 ucCmdSeqNum); +#define wlanConfigWifiFuncStatus wlanImageSectionDownloadStatus + +WLAN_STATUS wlanConfigWifiFunc(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgEnable, IN UINT_32 u4StartAddress, IN UINT_8 ucPDA); + +UINT_32 wlanCRC32(PUINT_8 buf, UINT_32 len); +#endif + +WLAN_STATUS wlanSendDummyCmd(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsReqTxRsrc); + +WLAN_STATUS wlanSendNicPowerCtrlCmd(IN P_ADAPTER_T prAdapter, IN UINT_8 ucPowerMode); + +WLAN_STATUS wlanKeepFullPwr(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnable); + +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, IN UINT_32 u4Timeout); + +VOID wlanoidClearTimeoutCheck(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS wlanUpdateNetworkAddress(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS wlanUpdateBasicConfig(IN P_ADAPTER_T prAdapter); + +BOOLEAN wlanQueryTestMode(IN P_ADAPTER_T prAdapter); + +BOOLEAN wlanProcessTxFrame(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prPacket); + +/* 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 + +/*----------------------------------------------------------------------------*/ +/* 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_STRUCT_T prMcrRdInfo); + +/*----------------------------------------------------------------------------*/ +/* Loading Manufacture Data */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanLoadManufactureData(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo); + +/*----------------------------------------------------------------------------*/ +/* Media Stream Mode */ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanResetMediaStreamMode(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* Timer Timeout Check (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanTimerTimeoutCheck(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Check (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanProcessMboxMessage(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* TX Pending Packets Handling (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanEnqueueTxPacket(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prNativePacket); + +WLAN_STATUS wlanFlushTxPendingPackets(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS wlanTxPendingPackets(IN P_ADAPTER_T prAdapter, IN OUT PBOOLEAN pfgHwAccess); + +/*----------------------------------------------------------------------------*/ +/* Low Power Acquire/Release (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanAcquirePowerControl(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS wlanReleasePowerControl(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* Pending Packets Number Reporting (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +UINT_32 wlanGetTxPendingFrameCount(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* ACPI state inquiry (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +ENUM_ACPI_STATE_T wlanGetAcpiState(IN P_ADAPTER_T prAdapter); + +VOID wlanSetAcpiState(IN P_ADAPTER_T prAdapter, IN ENUM_ACPI_STATE_T ePowerState); + +VOID wlanDefTxPowerCfg(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* get ECO version from Revision ID register (for Win32) */ +/*----------------------------------------------------------------------------*/ +UINT_8 wlanGetEcoVersion(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* get Rom version */ +/*----------------------------------------------------------------------------*/ +uint8_t wlanGetRomVersion(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 UINT_8 ucBssIndex); + +/*----------------------------------------------------------------------------*/ +/* get currently operating channel information */ +/*----------------------------------------------------------------------------*/ +UINT_8 wlanGetChannelNumberByNetwork(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex); + +/*----------------------------------------------------------------------------*/ +/* check for system configuration to generate message on scan list */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanCheckSystemConfiguration(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* query bss statistics information from driver and firmware */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryBssStatistics(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +/*----------------------------------------------------------------------------*/ +/* dump per-BSS statistics */ +/*----------------------------------------------------------------------------*/ +VOID wlanDumpBssStatistics(IN P_ADAPTER_T prAdapter, UINT_8 ucBssIndex); + +/*----------------------------------------------------------------------------*/ +/* query sta statistics information from driver and firmware */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryStaStatistics(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +_wlanoidQueryStaStatistics(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen, IN BOOLEAN fgIsOid); + +/*----------------------------------------------------------------------------*/ +/* query NIC resource information from chip and reset Tx resource for normal operation */ +/*----------------------------------------------------------------------------*/ +VOID wlanQueryNicResourceInformation(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS wlanQueryNicCapabilityV2(IN P_ADAPTER_T prAdapter); + +VOID wlanUpdateNicResourceInformation(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* GET/SET BSS index mapping for network interfaces */ +/*----------------------------------------------------------------------------*/ +VOID wlanBindNetInterface(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucNetInterfaceIndex, IN PVOID pvNetInterface); + +VOID wlanBindBssIdxToNetInterface(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucBssIndex, IN PVOID pvNetInterface); + +UINT_8 wlanGetBssIdxByNetInterface(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvNetInterface); + +PVOID wlanGetNetInterfaceByBssIdx(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucBssIndex); + +/* for windows as windows glue cannot see through P_ADAPTER_T */ +UINT_8 wlanGetAisBssIndex(IN P_ADAPTER_T prAdapter); + +VOID wlanInitFeatureOption(IN P_ADAPTER_T prAdapter); + +VOID wlanCfgSetSwCtrl(IN P_ADAPTER_T prAdapter); + +VOID wlanCfgSetChip(IN P_ADAPTER_T prAdapter); + +VOID wlanCfgSetDebugLevel(IN P_ADAPTER_T prAdapter); + +VOID wlanCfgSetCountryCode(IN P_ADAPTER_T prAdapter); + +P_WLAN_CFG_ENTRY_T wlanCfgGetEntry(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, BOOLEAN fgGetCfgRec); + +WLAN_STATUS +wlanCfgGet(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, PCHAR pucValue, PCHAR pucValueDef, UINT_32 u4Flags); + +UINT_32 wlanCfgGetUint32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, UINT_32 u4ValueDef); + +INT_32 wlanCfgGetInt32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, INT_32 i4ValueDef); + +WLAN_STATUS wlanCfgSetUint32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, UINT_32 u4Value); + +WLAN_STATUS wlanCfgSet(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, PCHAR pucValue, UINT_32 u4Flags); + +WLAN_STATUS +wlanCfgSetCb(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, WLAN_CFG_SET_CB pfSetCb, void *pPrivate, UINT_32 u4Flags); + +#if CFG_SUPPORT_EASY_DEBUG + +WLAN_STATUS wlanCfgParse(IN P_ADAPTER_T prAdapter, PUINT_8 pucConfigBuf, UINT_32 u4ConfigBufLen, BOOLEAN isFwConfig); +VOID wlanFeatureToFw(IN P_ADAPTER_T prAdapter); +#endif + +VOID wlanLoadDefaultCustomerSetting(IN P_ADAPTER_T prAdapter); + + + + +WLAN_STATUS wlanCfgInit(IN P_ADAPTER_T prAdapter, PUINT_8 pucConfigBuf, UINT_32 u4ConfigBufLen, UINT_32 u4Flags); + +WLAN_STATUS wlanCfgParseArgument(CHAR *cmdLine, INT_32 *argc, CHAR *argv[]); + +#if CFG_WOW_SUPPORT +WLAN_STATUS wlanCfgParseArgumentLong(CHAR *cmdLine, INT_32 *argc, CHAR *argv[]); +#endif + +INT_32 wlanHexToNum(CHAR c); +INT_32 wlanHexToByte(PCHAR hex); + +INT_32 wlanHwAddrToBin(PCHAR txt, UINT_8 *addr); + +BOOLEAN wlanIsChipNoAck(IN P_ADAPTER_T prAdapter); + +BOOLEAN wlanIsChipRstRecEnabled(IN P_ADAPTER_T prAdapter); + +BOOLEAN wlanIsChipAssert(IN P_ADAPTER_T prAdapter); + +VOID wlanChipRstPreAct(IN P_ADAPTER_T prAdapter); + + +VOID wlanTxProfilingTagPacket(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prPacket, IN ENUM_TX_PROFILING_TAG_T eTag); + +VOID wlanTxProfilingTagMsdu(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_PROFILING_TAG_T eTag); +#if CFG_ASSERT_DUMP +VOID wlanCorDumpTimerReset(IN P_ADAPTER_T prAdapter, BOOLEAN fgIsResetN9); + +VOID wlanN9CorDumpTimeOut(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); + +VOID wlanCr4CorDumpTimeOut(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr); +#endif +#endif /* _WLAN_LIB_H */ + + +BOOL wlanGetWlanIdxByAddress(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucAddr, OUT PUINT_8 pucIndex); + +PUINT_8 wlanGetStaAddrByWlanIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucIndex); + +P_WLAN_CFG_ENTRY_T wlanCfgGetEntryByIndex(IN P_ADAPTER_T prAdapter, const UINT_8 ucIdx, UINT_32 flag); + +WLAN_STATUS wlanGetStaIdxByWlanIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucIndex, OUT PUINT_8 pucStaIdx); + +/*----------------------------------------------------------------------------*/ +/* update per-AC statistics for LLS */ +/*----------------------------------------------------------------------------*/ +VOID wlanUpdateTxStatistics(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, BOOLEAN fgTxDrop); + +VOID wlanUpdateRxStatistics(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +WLAN_STATUS wlanTriggerStatsLog(IN P_ADAPTER_T prAdapter, IN UINT_32 u4DurationInMs); + +WLAN_STATUS wlanDhcpTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +WLAN_STATUS wlanArpTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +WLAN_STATUS wlan1xTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, + IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +WLAN_STATUS wlanDownloadFW(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS wlanWakeUpWiFi(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS wlanDownloadPatch(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS wlanGetPatchInfo(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS wlanPowerOffWifi(IN P_ADAPTER_T prAdapter); + +VOID wlanPrintVersion(P_ADAPTER_T prAdapter); +WLAN_STATUS wlanAccessRegister(IN P_ADAPTER_T prAdapter, + IN UINT_32 u4Addr, IN UINT_32 *pru4Result, IN UINT_32 u4Data, + IN UINT_8 ucSetQuery); + +WLAN_STATUS wlanAccessRegisterStatus(IN P_ADAPTER_T prAdapter, IN UINT_8 ucCmdSeqNum, + IN UINT_8 ucSetQuery, IN PVOID prEvent, IN UINT_32 u4EventLen); + +WLAN_STATUS wlanSetChipEcoInfo(IN P_ADAPTER_T prAdapter); + +VOID wlanNotifyFwSuspend(P_GLUE_INFO_T prGlueInfo, struct net_device *prDev, BOOLEAN fgSuspend); + +VOID wlanClearPendingInterrupt(IN P_ADAPTER_T prAdapter); + +#if (MTK_WCN_HIF_SDIO && CFG_WMT_WIFI_PATH_SUPPORT) +extern INT_32 mtk_wcn_wmt_wifi_fem_cfg_report(PVOID pvInfoBuf); +#endif + +UINT_8 wlanGetAntPathType(IN P_ADAPTER_T prAdapter, IN enum ENUM_WF_PATH_FAVOR_T eWfPathFavor); + +UINT_8 wlanGetSpeIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN enum ENUM_WF_PATH_FAVOR_T eWfPathFavor); + +UINT_8 wlanGetSupportNss(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex); + +INT_32 wlanGetFileContent(P_ADAPTER_T prAdapter, + const PUINT_8 pcFileName, PUINT_8 pucBuf, + UINT_32 u4MaxFileLen, PUINT_32 pu4ReadFileLen, BOOL bReqFw); + +#if CFG_SUPPORT_ANT_SELECT +WLAN_STATUS wlanUpdateExtInfo(IN P_ADAPTER_T prAdapter); +#endif + +#if CFG_SUPPORT_CSI +bool wlanPushCSIData(P_ADAPTER_T prAdapter, struct CSI_DATA_T *prCSIData); +bool wlanPopCSIData(P_ADAPTER_T prAdapter, struct CSI_DATA_T *prCSIData); +VOID +wlanApplyCSIToneMask( + UINT_8 ucRxMode, + UINT_8 ucCBW, + UINT_8 ucDBW, + UINT_8 ucPrimaryChIdx, + INT_16 *ai2IData, + INT_16 *ai2QData); + +VOID +wlanShiftCSI( + UINT_8 ucRxMode, + UINT_8 ucCBW, + UINT_8 ucDBW, + UINT_8 ucPrimaryChIdx, + INT_16 *ai2IData, + INT_16 *ai2QData, + INT_16 *ai2ShiftIData, + INT_16 *ai2ShiftQData); +#endif + +int wlanSuspendRekeyOffload(P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRekeyMode); +VOID wlanSuspendPmHandle(P_GLUE_INFO_T prGlueInfo); +VOID wlanResumePmHandle(P_GLUE_INFO_T prGlueInfo); + +void disconnect_sta(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec); diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/wlan_oid.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/wlan_oid.h new file mode 100644 index 0000000000000..2bdeae06a308e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/wlan_oid.h @@ -0,0 +1,2950 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/wlan_oid.h#4 +*/ + +/*! \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. +*/ + + +#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 | \ + PARAM_PACKET_FILTER_ALL_MULTICAST) +#endif + +#define PARAM_MEM_DUMP_MAX_SIZE 1536 + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +#define PARAM_CAL_DATA_DUMP_MAX_SIZE 1200 +#define PARAM_CAL_DATA_DUMP_MAX_NUM 300 +#endif + +#define BT_PROFILE_PARAM_LEN 8 + +#define EFUSE_ADDR_MAX 0x3BF /* Based on EEPROM layout 20160120 */ +#if CFG_SUPPORT_BUFFER_MODE + +/* For MT7668 */ +#define EFUSE_CONTENT_BUFFER_START 0x03A +#define EFUSE_CONTENT_BUFFER_END 0x1D9 +#define EFUSE_CONTENT_BUFFER_SIZE (EFUSE_CONTENT_BUFFER_END - EFUSE_CONTENT_BUFFER_START + 1) + +#define DEFAULT_EFUSE_MACADDR_OFFSET 4 + + +/* For MT6632 */ +#define EFUSE_CONTENT_SIZE 16 + +#define EFUSE_BLOCK_SIZE 16 +#define EEPROM_SIZE 1184 +#define MAX_EEPROM_BUFFER_SIZE 1200 +#endif /* CFG_SUPPORT_BUFFER_MODE */ + +#if CFG_SUPPORT_TX_BF +#define TXBF_CMD_NEED_TO_RESPONSE(u4TxBfCmdId) (u4TxBfCmdId == BF_PFMU_TAG_READ || \ + u4TxBfCmdId == BF_PROFILE_READ) +#endif /* CFG_SUPPORT_TX_BF */ +#define MU_CMD_NEED_TO_RESPONSE(u4MuCmdId) (u4MuCmdId == MU_GET_CALC_INIT_MCS || \ + u4MuCmdId == MU_HQA_GET_QD || \ + u4MuCmdId == MU_HQA_GET_CALC_LQ) +#if CFG_SUPPORT_MU_MIMO +/* @NITESH: MACROS For Init MCS calculation (MU Metric Table) */ +#define NUM_MUT_FEC 2 +#define NUM_MUT_MCS 10 +#define NUM_MUT_NR_NUM 3 +#define NUM_MUT_INDEX 8 + +#define NUM_OF_USER 2 +#define NUM_OF_MODUL 5 +#endif /* CFG_SUPPORT_MU_MIMO */ + +/******************************************************************************* +* 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, +#if CFG_SUPPORT_CFG80211_AUTH + AUTH_MODE_WPA2_SAE, +#endif + 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, +#if CFG_SUPPORT_SUITB + ENUM_ENCRYPTION4_ENABLED, + ENUM_ENCRYPTION4_KEY_ABSENT, +#endif + ENUM_ENCRYPTION_NUM +} 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; + +typedef struct _PARAM_CONNECT_T { + UINT_32 u4SsidLen; /*!< SSID length in bytes. Zero length is broadcast(any) SSID */ + UINT_8 *pucSsid; + UINT_8 *pucBssid; + UINT_32 u4CenterFreq; +} PARAM_CONNECT_T, *P_PARAM_CONNECT_T; + +/* This is enum defined for user to select an AdHoc Mode */ +typedef enum _ENUM_PARAM_AD_HOC_MODE_T { + AD_HOC_MODE_11B = 0, /*!< Create 11b IBSS if we support 802.11abg/802.11bg. */ + AD_HOC_MODE_MIXED_11BG, /*!< Create 11bg mixed IBSS if we support 802.11abg/802.11bg/802.11g. */ + AD_HOC_MODE_11G, /*!< Create 11g only IBSS if we support 802.11abg/802.11bg/802.11g. */ + AD_HOC_MODE_11A, /*!< Create 11a only IBSS if we support 802.11abg. */ + AD_HOC_MODE_NUM /* 4 */ +} ENUM_PARAM_AD_HOC_MODE_T, *P_ENUM_PARAM_AD_HOC_MODE_T; + +typedef enum _ENUM_PARAM_MEDIA_STATE_T { + PARAM_MEDIA_STATE_CONNECTED, + PARAM_MEDIA_STATE_DISCONNECTED, + PARAM_MEDIA_STATE_TO_BE_INDICATED /* for following MSDN re-association behavior */ +} ENUM_PARAM_MEDIA_STATE_T, *P_ENUM_PARAM_MEDIA_STATE_T; + +typedef enum _ENUM_PARAM_NETWORK_TYPE_T { + PARAM_NETWORK_TYPE_FH, + PARAM_NETWORK_TYPE_DS, + PARAM_NETWORK_TYPE_OFDM5, + PARAM_NETWORK_TYPE_OFDM24, + PARAM_NETWORK_TYPE_AUTOMODE, + PARAM_NETWORK_TYPE_NUM /*!< Upper bound, not real case */ +} ENUM_PARAM_NETWORK_TYPE_T, *P_ENUM_PARAM_NETWORK_TYPE_T; + +typedef struct _PARAM_NETWORK_TYPE_LIST { + UINT_32 NumberOfItems; /*!< At least 1 */ + ENUM_PARAM_NETWORK_TYPE_T eNetworkType[1]; +} PARAM_NETWORK_TYPE_LIST, *PPARAM_NETWORK_TYPE_LIST; + +typedef enum _ENUM_PARAM_PRIVACY_FILTER_T { + PRIVACY_FILTER_ACCEPT_ALL, + PRIVACY_FILTER_8021xWEP, + PRIVACY_FILTER_NUM +} ENUM_PARAM_PRIVACY_FILTER_T, *P_ENUM_PARAM_PRIVACY_FILTER_T; + +typedef enum _ENUM_RELOAD_DEFAULTS { + ENUM_RELOAD_WEP_KEYS +} PARAM_RELOAD_DEFAULTS, *P_PARAM_RELOAD_DEFAULTS; + +typedef struct _PARAM_PM_PACKET_PATTERN { + UINT_32 Priority; /* Importance of the given pattern. */ + UINT_32 Reserved; /* Context information for transports. */ + UINT_32 MaskSize; /* Size in bytes of the pattern mask. */ + UINT_32 PatternOffset; /* Offset from beginning of this */ + /* structure to the pattern bytes. */ + UINT_32 PatternSize; /* Size in bytes of the pattern. */ + UINT_32 PatternFlags; /* Flags (TBD). */ +} PARAM_PM_PACKET_PATTERN, *P_PARAM_PM_PACKET_PATTERN; + + +/* Combine ucTpTestMode and ucSigmaTestMode in one flag */ +/* ucTpTestMode == 0, for normal driver */ +/* ucTpTestMode == 1, for pure throughput test mode (ex: RvR) */ +/* ucTpTestMode == 2, for sigma TGn/TGac/PMF */ +/* ucTpTestMode == 3, for sigma WMM PS */ +typedef enum _ENUM_TP_TEST_MODE_T { + ENUM_TP_TEST_MODE_NORMAL = 0, + ENUM_TP_TEST_MODE_THROUGHPUT, + ENUM_TP_TEST_MODE_SIGMA_AC_N_PMF, + ENUM_TP_TEST_MODE_SIGMA_WMM_PS, + ENUM_TP_TEST_MODE_NUM +} ENUM_TP_TEST_MODE_T, *P_ENUM_TP_TEST_MODE_T; + +/*--------------------------------------------------------------*/ +/*! \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 ucBssIdx; + UINT_8 ucCipher; + UINT_8 aucKeyMaterial[32]; /*!< Key content by above setting */ + /* Following add to change the original windows structure */ +} 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 */ + UINT_8 ucBssIdx; +} PARAM_REMOVE_KEY_T, *P_PARAM_REMOVE_KEY_T; + +/*! \brief Default key */ +typedef struct _PARAM_DEFAULT_KEY_T { + UINT_8 ucKeyID; + UINT_8 ucUnicast; + UINT_8 ucMulticast; + UINT_8 ucBssIdx; +} PARAM_DEFAULT_KEY_T, *P_PARAM_DEFAULT_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_FW_DBG_LEVEL_CTRL +/* FW debug control level related definition and enumerations */ +#define FW_DBG_LEVEL_DONT_SET 0 +#define FW_DBG_LEVEL_ERROR (1 << 0) +#define FW_DBG_LEVEL_WARN (1 << 1) +#define FW_DBG_LEVEL_STATE (1 << 2) +#define FW_DBG_LEVEL_INFO (1 << 3) +#define FW_DBG_LEVEL_LOUD (1 << 4) +#endif + +typedef struct _PARAM_POWER_MODE_T { + UINT_8 ucBssIdx; + PARAM_POWER_MODE ePowerMode; +} PARAM_POWER_MODE_T, *P_PARAM_POWER_MODE_T; + +#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 */ + +#define NL80211_KCK_LEN 16 +#define NL80211_KEK_LEN 16 +#define NL80211_REPLAY_CTR_LEN 8 +#define NL80211_KEYRSC_LEN 8 + +typedef struct _PARAM_GTK_REKEY_DATA { + UINT_8 aucKek[NL80211_KEK_LEN]; + UINT_8 aucKck[NL80211_KCK_LEN]; + UINT_8 aucReplayCtr[NL80211_REPLAY_CTR_LEN]; + UINT_8 ucBssIndex; + UINT_8 ucRekeyMode; + UINT_8 ucCurKeyId; + UINT_8 ucRsv; + UINT_32 u4Proto; + UINT_32 u4PairwiseCipher; + UINT_32 u4GroupCipher; + UINT_32 u4KeyMgmt; + UINT_32 u4MgmtGroupCipher; +} PARAM_GTK_REKEY_DATA, *P_PARAM_GTK_REKEY_DATA; + +typedef struct _PARAM_CUSTOM_MCR_RW_STRUCT_T { + UINT_32 u4McrOffset; + UINT_32 u4McrData; +} PARAM_CUSTOM_MCR_RW_STRUCT_T, *P_PARAM_CUSTOM_MCR_RW_STRUCT_T; + +#define COEX_CTRL_BUF_LEN 460 +#define COEX_INFO_LEN 115 + +/* CMD_COEX_CTRL & EVENT_COEX_CTRL */ +/************************************************/ +/* UINT_32 u4SubCmd : Coex Ctrl Sub Command */ +/* UINT_8 aucBuffer : Reserve for Sub Command */ +/* Data Structure */ +/************************************************/ +struct PARAM_COEX_CTRL { + UINT_32 u4SubCmd; + UINT_8 aucBuffer[COEX_CTRL_BUF_LEN]; +}; + +/* Isolation Structure */ +/************************************************/ +/* UINT_32 u4IsoPath : WF Path (WF0/WF1) */ +/* UINT_32 u4Channel : WF Channel */ +/* UINT_32 u4Band : WF Band (Band0/Band1)(Not used now) */ +/* UINT_32 u4Isolation : Isolation value */ +/************************************************/ +struct PARAM_COEX_ISO_DETECT { + UINT_32 u4IsoPath; + UINT_32 u4Channel; + /*UINT_32 u4Band;*/ + UINT_32 u4Isolation; +}; + +/* Coex Info Structure */ +/************************************************/ +/* char cCoexInfo[]; */ +/************************************************/ +struct PARAM_COEX_GET_INFO { + UINT_32 u4CoexInfo[COEX_INFO_LEN]; +}; + + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +/* + * Description of Each Parameters : + * ucReason : + * 0 : Query Information of Thermal or Cal Data Length + * 1 : Trigger FW do or don't All Cal + * 2 : Dump Data to Host + * 3 : Send Backupped Cal Data to FW + * 4 : For Debug Use, Tell FW Print Cal Data (Rom or Ram) + * ucAction : + * 0 : Read Thermal Value + * 1 : Ask the Cal Data Total Length (Rom and Ram) + * 2 : Tell FW do All Cal + * 3 : Tell FW don't do Cal + * 4 : Dump Data to Host (Rom or Ram) + * 5 : Send Backupped Cal Data to FW (Rom or Ram) + * 6 : For Debug Use, Tell FW Print Cal Data (Rom or Ram) + * ucNeedResp : + * 0 : FW No Need to Response an EVENT + * 1 : FW Need to Response an EVENT + * ucFragNum : + * Sequence Number + * ucRomRam : + * 0 : Operation for Rom Cal Data + * 1 : Operation for Ram Cal Data + * u4ThermalValue : + * Field for filling the Thermal Value in FW + * u4Address : + * Dumpped Starting Address + * Used for Dump and Send Cal Data Between Driver and FW + * u4Length : + * Memory Size need to allocated in Driver or Data Size in an EVENT + * Used for Dump and Send Cal Data Between Driver and FW + * u4RemainLength : + * Remain Length need to Dump + * Used for Dump and Send Cal Data Between Driver and FW + */ +typedef struct _PARAM_CAL_BACKUP_STRUCT_V2_T { + UINT_8 ucReason; + UINT_8 ucAction; + UINT_8 ucNeedResp; + UINT_8 ucFragNum; + UINT_8 ucRomRam; + UINT_32 u4ThermalValue; + UINT_32 u4Address; + UINT_32 u4Length; + UINT_32 u4RemainLength; +} PARAM_CAL_BACKUP_STRUCT_V2_T, *P_PARAM_CAL_BACKUP_STRUCT_V2_T; +#endif + +#if CFG_SUPPORT_QA_TOOL +#if CFG_SUPPORT_BUFFER_MODE +typedef struct _BIN_CONTENT_T { + UINT_16 u2Addr; + UINT_8 ucValue; + UINT_8 ucReserved; +} BIN_CONTENT_T, *P_BIN_CONTENT_T; + +typedef struct _PARAM_CUSTOM_EFUSE_BUFFER_MODE_T { + UINT_8 ucSourceMode; + UINT_8 ucCount; + UINT_8 ucCmdType; + UINT_8 ucReserved; + UINT_8 aBinContent[MAX_EEPROM_BUFFER_SIZE]; +} PARAM_CUSTOM_EFUSE_BUFFER_MODE_T, *P_PARAM_CUSTOM_EFUSE_BUFFER_MODE_T; + +/*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ +typedef struct _PARAM_CUSTOM_ACCESS_EFUSE_T { + UINT_32 u4Address; + UINT_32 u4Valid; + UINT_8 aucData[16]; +} PARAM_CUSTOM_ACCESS_EFUSE_T, *P_PARAM_CUSTOM_ACCESS_EFUSE_T; + + +typedef struct _PARAM_CUSTOM_EFUSE_FREE_BLOCK_T { + UINT_8 ucGetFreeBlock; + UINT_8 aucReserved[3]; +} PARAM_CUSTOM_EFUSE_FREE_BLOCK_T, *P_PARAM_CUSTOM_EFUSE_FREE_BLOCK_T; + + +typedef struct _PARAM_CUSTOM_GET_TX_POWER_T { + UINT_8 ucTxPwrType; + UINT_8 ucCenterChannel; + UINT_8 ucDbdcIdx; /* 0:Band 0, 1: Band1 */ + UINT_8 ucBand; /* 0:G-band 1: A-band*/ + UINT_8 ucReserved[4]; +} PARAM_CUSTOM_GET_TX_POWER_T, *P_PARAM_CUSTOM_GET_TX_POWER_T; + + +/*#endif*/ + +#endif /* CFG_SUPPORT_BUFFER_MODE */ + +typedef struct _PARAM_CUSTOM_SET_TX_TARGET_POWER_T { + INT_8 cTxPwr2G4Cck; /* signed, in unit of 0.5dBm */ + INT_8 cTxPwr2G4Dsss; /* signed, in unit of 0.5dBm */ + UINT_8 ucTxTargetPwr; /* Tx target power base for all*/ + UINT_8 ucReserved; + + 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; +} PARAM_CUSTOM_SET_TX_TARGET_POWER_T, *P_PARAM_CUSTOM_SET_TX_TARGET_POWER_T; + +#if (CFG_SUPPORT_DFS_MASTER == 1) +typedef struct _PARAM_CUSTOM_SET_RDD_REPORT_T { + UINT_8 ucDbdcIdx; /* 0:Band 0, 1: Band1 */ +} PARAM_CUSTOM_SET_RDD_REPORT_T, *P_PARAM_CUSTOM_SET_RDD_REPORT_T; + +struct PARAM_CUSTOM_SET_RADAR_DETECT_MODE { + UINT_8 ucRadarDetectMode; /* 0:Switch channel, 1: Don't switch channel */ +}; +#endif + +typedef struct _PARAM_CUSTOM_ACCESS_RX_STAT { + UINT_32 u4SeqNum; + UINT_32 u4TotalNum; +} PARAM_CUSTOM_ACCESS_RX_STAT, *P_PARAM_CUSTOM_ACCESS_RX_STAT; + +/* Ext DevInfo Tag */ +typedef enum _EXT_ENUM_DEVINFO_TAG_HANDLE_T { + DEV_INFO_ACTIVE = 0, + DEV_INFO_BSSID, + DEV_INFO_MAX_NUM +} EXT_ENUM_TAG_DEVINFO_HANDLE_T; + +/* STA record TLV tag */ +typedef enum _EXT_ENUM_STAREC_TAG_HANDLE_T { + STA_REC_BASIC = 0, + STA_REC_RA, + STA_REC_RA_COMMON_INFO, + STA_REC_RA_UPDATE, + STA_REC_BF, + STA_REC_MAUNAL_ASSOC, + STA_REC_BA = 6, + STA_REC_MAX_NUM +} EXT_ENUM_TAG_STAREC_HANDLE_T; + +#if CFG_SUPPORT_TX_BF +typedef enum _BF_ACTION_CATEGORY { + BF_SOUNDING_OFF = 0, + BF_SOUNDING_ON, + BF_HW_CTRL, + BF_DATA_PACKET_APPLY, + BF_PFMU_MEM_ALLOCATE, + BF_PFMU_MEM_RELEASE, + BF_PFMU_TAG_READ, + BF_PFMU_TAG_WRITE, + BF_PROFILE_READ, + BF_PROFILE_WRITE, + BF_PN_READ, + BF_PN_WRITE, + BF_PFMU_MEM_ALLOC_MAP_READ +} BF_ACTION_CATEGORY; + +enum { + DEVINFO_ACTIVE = 0, + DEVINFO_MAX_NUM = 1, +}; + +enum { + DEVINFO_ACTIVE_FEATURE = (1 << DEVINFO_ACTIVE), + DEVINFO_MAX_NUM_FEATURE = (1 << DEVINFO_MAX_NUM) +}; + +enum { + BSS_INFO_OWN_MAC = 0, + BSS_INFO_BASIC = 1, + BSS_INFO_RF_CH = 2, + BSS_INFO_PM = 3, + BSS_INFO_UAPSD = 4, + BSS_INFO_ROAM_DETECTION = 5, + BSS_INFO_LQ_RM = 6, + BSS_INFO_EXT_BSS = 7, + BSS_INFO_BROADCAST_INFO = 8, + BSS_INFO_SYNC_MODE = 9, + BSS_INFO_MAX_NUM +}; + +typedef union _PFMU_PROFILE_TAG1 { + struct { + UINT_32 ucProfileID:7; /* [6:0] : 0 ~ 63 */ + UINT_32 ucTxBf:1; /* [7] : 0: iBF, 1: eBF */ + UINT_32 ucDBW:2; /* [9:8] : 0/1/2/3: DW20/40/80/160NC */ + UINT_32 ucSU_MU:1; /* [10] : 0:SU, 1: MU */ + UINT_32 ucInvalidProf:1; /* [11] : 0:default, 1: This profile number is invalid by SW */ + UINT_32 ucRMSD:3; /* [14:12] : RMSD value from CE */ + UINT_32 ucMemAddr1ColIdx:3; /* [17 : 15] : column index : 0 ~ 5 */ + UINT_32 ucMemAddr1RowIdx:6; /* [23 : 18] : row index : 0 ~ 63 */ + UINT_32 ucMemAddr2ColIdx:3; /* [26 : 24] : column index : 0 ~ 5 */ + UINT_32 ucMemAddr2RowIdx:5; /* [31 : 27] : row index : 0 ~ 63 */ + UINT_32 ucMemAddr2RowIdxMsb:1; /* [32] : MSB of row index */ + UINT_32 ucMemAddr3ColIdx:3; /* [35 : 33] : column index : 0 ~ 5 */ + UINT_32 ucMemAddr3RowIdx:6; /* [41 : 36] : row index : 0 ~ 63 */ + UINT_32 ucMemAddr4ColIdx:3; /* [44 : 42] : column index : 0 ~ 5 */ + UINT_32 ucMemAddr4RowIdx:6; /* [50 : 45] : row index : 0 ~ 63 */ + UINT_32 ucReserved:1; /* [51] : Reserved */ + UINT_32 ucNrow:2; /* [53 : 52] : Nrow */ + UINT_32 ucNcol:2; /* [55 : 54] : Ncol */ + UINT_32 ucNgroup:2; /* [57 : 56] : Ngroup */ + UINT_32 ucLM:2; /* [59 : 58] : 0/1/2 */ + UINT_32 ucCodeBook:2; /* [61:60] : Code book */ + UINT_32 ucHtcExist:1; /* [62] : HtcExist */ + UINT_32 ucReserved1:1; /* [63] : Reserved */ + UINT_32 ucSNR_STS0:8; /* [71:64] : SNR_STS0 */ + UINT_32 ucSNR_STS1:8; /* [79:72] : SNR_STS1 */ + UINT_32 ucSNR_STS2:8; /* [87:80] : SNR_STS2 */ + UINT_32 ucSNR_STS3:8; /* [95:88] : SNR_STS3 */ + UINT_32 ucIBfLnaIdx:8; /* [103:96] : iBF LNA index */ + } rField; + UINT_32 au4RawData[4]; +} PFMU_PROFILE_TAG1, *P_PFMU_PROFILE_TAG1; + +typedef union _PFMU_PROFILE_TAG2 { + struct { + UINT_32 u2SmartAnt:12; /* [11:0] : Smart Ant config */ + UINT_32 ucReserved0:3; /* [14:12] : Reserved */ + UINT_32 ucSEIdx:5; /* [19:15] : SE index */ + UINT_32 ucRMSDThd:3; /* [22:20] : RMSD Threshold */ + UINT_32 ucReserved1:1; /* [23] : Reserved */ + UINT_32 ucMCSThL1SS:4; /* [27:24] : MCS TH long 1SS */ + UINT_32 ucMCSThS1SS:4; /* [31:28] : MCS TH short 1SS */ + UINT_32 ucMCSThL2SS:4; /* [35:32] : MCS TH long 2SS */ + UINT_32 ucMCSThS2SS:4; /* [39:36] : MCS TH short 2SS */ + UINT_32 ucMCSThL3SS:4; /* [43:40] : MCS TH long 3SS */ + UINT_32 ucMCSThS3SS:4; /* [47:44] : MCS TH short 3SS */ + UINT_32 uciBfTimeOut:8; /* [55:48] : iBF timeout limit */ + UINT_32 ucReserved2:8; /* [63:56] : Reserved */ + UINT_32 ucReserved3:8; /* [71:64] : Reserved */ + UINT_32 ucReserved4:8; /* [79:72] : Reserved */ + UINT_32 uciBfDBW:2; /* [81:80] : iBF desired DBW 0/1/2/3 : BW20/40/80/160NC */ + UINT_32 uciBfNcol:2; /* [83:82] : iBF desired Ncol = 1 ~ 3 */ + UINT_32 uciBfNrow:2; /* [85:84] : iBF desired Nrow = 1 ~ 4 */ + UINT_32 u2Reserved5:10; /* [95:86] : Reserved */ + } rField; + UINT_32 au4RawData[3]; +} PFMU_PROFILE_TAG2, *P_PFMU_PROFILE_TAG2; + +typedef union _PFMU_DATA { + struct { + UINT_32 u2Phi11:9; + UINT_32 ucPsi21:7; + UINT_32 u2Phi21:9; + UINT_32 ucPsi31:7; + UINT_32 u2Phi31:9; + UINT_32 ucPsi41:7; + UINT_32 u2Phi22:9; + UINT_32 ucPsi32:7; + UINT_32 u2Phi32:9; + UINT_32 ucPsi42:7; + UINT_32 u2Phi33:9; + UINT_32 ucPsi43:7; + UINT_32 u2dSNR00:4; + UINT_32 u2dSNR01:4; + UINT_32 u2dSNR02:4; + UINT_32 u2dSNR03:4; + UINT_32 u2Reserved:16; + } rField; + UINT_32 au4RawData[5]; +} PFMU_DATA, *P_PFMU_DATA; + +typedef struct _PROFILE_TAG_READ_T { + UINT_8 ucTxBfCategory; + UINT_8 ucProfileIdx; + BOOLEAN fgBfer; + UINT_8 ucRsv; +} PROFILE_TAG_READ_T, *P_PROFILE_TAG_READ_T; + +typedef struct _PROFILE_TAG_WRITE_T { + UINT_8 ucTxBfCategory; + UINT_8 ucPfmuId; + UINT_8 ucBuffer[28]; +} PROFILE_TAG_WRITE_T, *P_PROFILE_TAG_WRITE_T; + +typedef struct _PROFILE_DATA_READ_T { + UINT_8 ucTxBfCategory; + UINT_8 ucPfmuIdx; + BOOLEAN fgBFer; + UINT_8 ucReserved[3]; + UINT_8 ucSubCarrIdxLsb; + UINT_8 ucSubCarrIdxMsb; +} PROFILE_DATA_READ_T, *P_PROFILE_DATA_READ_T; + +typedef struct _PROFILE_DATA_WRITE_T { + UINT_8 ucTxBfCategory; + UINT_8 ucPfmuIdx; + UINT_8 u2SubCarrIdxLsb; + UINT_8 u2SubCarrIdxMsb; + PFMU_DATA rTxBfPfmuData; +} PROFILE_DATA_WRITE_T, *P_PROFILE_DATA_WRITE_T; + +typedef struct _PROFILE_PN_READ_T { + UINT_8 ucTxBfCategory; + UINT_8 ucPfmuIdx; + UINT_8 ucReserved[2]; +} PROFILE_PN_READ_T, *P_PROFILE_PN_READ_T; + +typedef struct _PROFILE_PN_WRITE_T { + UINT_8 ucTxBfCategory; + UINT_8 ucPfmuIdx; + UINT_16 u2bw; + UINT_8 ucBuf[32]; +} PROFILE_PN_WRITE_T, *P_PROFILE_PN_WRITE_T; + +typedef enum _BF_SOUNDING_MODE { + SU_SOUNDING = 0, + MU_SOUNDING, + SU_PERIODIC_SOUNDING, + MU_PERIODIC_SOUNDING, + AUTO_SU_PERIODIC_SOUNDING +} BF_SOUNDING_MODE; + +typedef struct _EXT_CMD_ETXBf_SND_PERIODIC_TRIGGER_CTRL_T { + UINT_8 ucCmdCategoryID; + UINT_8 ucSuMuSndMode; + UINT_8 ucWlanIdx; + UINT_32 u4SoundingInterval; /* By ms */ +} EXT_CMD_ETXBf_SND_PERIODIC_TRIGGER_CTRL_T, *P_EXT_CMD_ETXBf_SND_PERIODIC_TRIGGER_CTRL_T; + +typedef struct _EXT_CMD_ETXBf_MU_SND_PERIODIC_TRIGGER_CTRL_T { + UINT_8 ucCmdCategoryID; + UINT_8 ucSuMuSndMode; + UINT_8 ucWlanId[4]; + UINT_8 ucStaNum; + UINT_32 u4SoundingInterval; /* By ms */ +} EXT_CMD_ETXBf_MU_SND_PERIODIC_TRIGGER_CTRL_T, *P_EXT_CMD_ETXBf_MU_SND_PERIODIC_TRIGGER_CTRL_T; + +/* Device information (Tag0) */ +typedef struct _CMD_DEVINFO_ACTIVE_T { + UINT_16 u2Tag; /* Tag = 0x00 */ + UINT_16 u2Length; + UINT_8 ucActive; + UINT_8 ucBandNum; + UINT_8 aucOwnMacAddr[6]; + UINT_8 aucReserve[4]; +} CMD_DEVINFO_ACTIVE_T, *P_CMD_DEVINFO_ACTIVE_T; + +typedef struct _BSSINFO_BASIC_T { + /* Basic BSS information (Tag1) */ + UINT_16 u2Tag; /* Tag = 0x01 */ + UINT_16 u2Length; + UINT_32 u4NetworkType; + UINT_8 ucActive; + UINT_8 ucReserve0; + UINT_16 u2BcnInterval; + UINT_8 aucBSSID[6]; + UINT_8 ucWmmIdx; + UINT_8 ucDtimPeriod; + UINT_8 ucBcMcWlanidx; /* indicate which wlan-idx used for MC/BC transmission. */ + UINT_8 ucCipherSuit; + UINT_8 acuReserve[6]; +} CMD_BSSINFO_BASIC_T, *P_CMD_BSSINFO_BASIC_T; + +typedef struct _TXBF_PFMU_STA_INFO { + UINT_16 u2PfmuId; /* 0xFFFF means no access right for PFMU */ + UINT_8 fgSU_MU; /* 0 : SU, 1 : MU */ + UINT_8 fgETxBfCap; /* 0 : ITxBf, 1 : ETxBf */ + UINT_8 ucSoundingPhy; /* 0: legacy, 1: OFDM, 2: HT, 4: VHT */ + UINT_8 ucNdpaRate; + UINT_8 ucNdpRate; + UINT_8 ucReptPollRate; + UINT_8 ucTxMode; /* 0: legacy, 1: OFDM, 2: HT, 4: VHT */ + UINT_8 ucNc; + UINT_8 ucNr; + UINT_8 ucCBW; /* 0 : 20M, 1 : 40M, 2 : 80M, 3 : 80 + 80M */ + UINT_8 ucTotMemRequire; + UINT_8 ucMemRequire20M; + UINT_8 ucMemRow0; + UINT_8 ucMemCol0; + UINT_8 ucMemRow1; + UINT_8 ucMemCol1; + UINT_8 ucMemRow2; + UINT_8 ucMemCol2; + UINT_8 ucMemRow3; + UINT_8 ucMemCol3; + UINT_16 u2SmartAnt; + UINT_8 ucSEIdx; + UINT_8 uciBfTimeOut; + UINT_8 uciBfDBW; + UINT_8 uciBfNcol; + UINT_8 uciBfNrow; + UINT_8 aucReserved[3]; +} TXBF_PFMU_STA_INFO, *P_TXBF_PFMU_STA_INFO; + +typedef struct _STA_REC_UPD_ENTRY_T { + TXBF_PFMU_STA_INFO rTxBfPfmuStaInfo; + UINT_8 aucAddr[PARAM_MAC_ADDR_LEN]; + UINT_8 ucAid; + UINT_8 ucRsv; +} STA_REC_UPD_ENTRY_T, *P_STA_REC_UPD_ENTRY_T; + +typedef struct _STAREC_COMMON_T { + /* Basic STA record (Group0) */ + UINT_16 u2Tag; /* Tag = 0x00 */ + UINT_16 u2Length; + UINT_32 u4ConnectionType; + UINT_8 ucConnectionState; + UINT_8 ucIsQBSS; + UINT_16 u2AID; + UINT_8 aucPeerMacAddr[6]; + UINT_16 u2Reserve1; +} CMD_STAREC_COMMON_T, *P_CMD_STAREC_COMMON_T; + +typedef struct _CMD_STAREC_BF { + UINT_16 u2Tag; /* Tag = 0x02 */ + UINT_16 u2Length; + TXBF_PFMU_STA_INFO rTxBfPfmuInfo; + UINT_8 ucReserved[3]; +} CMD_STAREC_BF, *P_CMD_STAREC_BF; + +/* QA tool: maunal assoc */ +typedef struct _CMD_MANUAL_ASSOC_STRUCT_T { +/* +* UINT_8 ucBssIndex; +* UINT_8 ucWlanIdx; +* UINT_16 u2TotalElementNum; +* UINT_32 u4Reserve; +*/ + /* extension */ + UINT_16 u2Tag; /* Tag = 0x05 */ + UINT_16 u2Length; + UINT_8 aucMac[MAC_ADDR_LEN]; + UINT_8 ucType; + UINT_8 ucWtbl; + UINT_8 ucOwnmac; + UINT_8 ucMode; + UINT_8 ucBw; + UINT_8 ucNss; + UINT_8 ucPfmuId; + UINT_8 ucMarate; + UINT_8 ucSpeIdx; + UINT_8 ucaid; +} CMD_MANUAL_ASSOC_STRUCT_T, *P_CMD_MANUAL_ASSOC_STRUCT_T; + +typedef struct _TX_BF_SOUNDING_START_T { + union { + EXT_CMD_ETXBf_SND_PERIODIC_TRIGGER_CTRL_T rExtCmdExtBfSndPeriodicTriggerCtrl; + EXT_CMD_ETXBf_MU_SND_PERIODIC_TRIGGER_CTRL_T rExtCmdExtBfMuSndPeriodicTriggerCtrl; + } rTxBfSounding; +} TX_BF_SOUNDING_START_T, *P_TX_BF_SOUNDING_START_T; + +typedef struct _TX_BF_SOUNDING_STOP_T { + UINT_8 ucTxBfCategory; + UINT_8 ucSndgStop; + UINT_8 ucReserved[2]; +} TX_BF_SOUNDING_STOP_T, *P_TX_BF_SOUNDING_STOP_T; + +typedef struct _TX_BF_TX_APPLY_T { + UINT_8 ucTxBfCategory; + UINT_8 ucWlanId; + UINT_8 fgETxBf; + UINT_8 fgITxBf; + UINT_8 fgMuTxBf; + UINT_8 ucReserved[3]; +} TX_BF_TX_APPLY_T, *P_TX_BF_TX_APPLY_T; + +typedef struct _TX_BF_PFMU_MEM_ALLOC_T { + UINT_8 ucTxBfCategory; + UINT_8 ucSuMuMode; + UINT_8 ucWlanIdx; + UINT_8 ucReserved; +} TX_BF_PFMU_MEM_ALLOC_T, *P_TX_BF_PFMU_MEM_ALLOC_T; + +typedef struct _TX_BF_PFMU_MEM_RLS_T { + UINT_8 ucTxBfCategory; + UINT_8 ucWlanId; + UINT_8 ucReserved[2]; +} TX_BF_PFMU_MEM_RLS_T, *P_TX_BF_PFMU_MEM_RLS_T; + +typedef union _PARAM_CUSTOM_TXBF_ACTION_STRUCT_T { + PROFILE_TAG_READ_T rProfileTagRead; + PROFILE_TAG_WRITE_T rProfileTagWrite; + PROFILE_DATA_READ_T rProfileDataRead; + PROFILE_DATA_WRITE_T rProfileDataWrite; + PROFILE_PN_READ_T rProfilePnRead; + PROFILE_PN_WRITE_T rProfilePnWrite; + TX_BF_SOUNDING_START_T rTxBfSoundingStart; + TX_BF_SOUNDING_STOP_T rTxBfSoundingStop; + TX_BF_TX_APPLY_T rTxBfTxApply; + TX_BF_PFMU_MEM_ALLOC_T rTxBfPfmuMemAlloc; + TX_BF_PFMU_MEM_RLS_T rTxBfPfmuMemRls; +} PARAM_CUSTOM_TXBF_ACTION_STRUCT_T, *P_PARAM_CUSTOM_TXBF_ACTION_STRUCT_T; + +typedef struct _PARAM_CUSTOM_STA_REC_UPD_STRUCT_T { + UINT_8 ucBssIndex; + UINT_8 ucWlanIdx; + UINT_16 u2TotalElementNum; + UINT_8 ucAppendCmdTLV; + UINT_8 ucMuarIdx; + UINT_8 aucReserve[2]; + UINT_32 *prStaRec; + CMD_STAREC_BF rCmdStaRecBf; +} PARAM_CUSTOM_STA_REC_UPD_STRUCT_T, *P_PARAM_CUSTOM_STA_REC_UPD_STRUCT_T; + +typedef struct _BSSINFO_ARGUMENT_T { + UCHAR OwnMacIdx; + UINT_8 ucBssIndex; + UINT_8 Bssid[PARAM_MAC_ADDR_LEN]; + UINT_8 ucBcMcWlanIdx; + UINT_8 ucPeerWlanIdx; + UINT_32 NetworkType; + UINT_32 u4ConnectionType; + UINT_8 CipherSuit; + UINT_8 Active; + UINT_8 WmmIdx; + UINT_32 u4BssInfoFeature; + UINT_8 aucBuffer[0]; +} BSSINFO_ARGUMENT_T, *P_BSSINFO_ARGUMENT_T; + +typedef struct _PARAM_CUSTOM_PFMU_TAG_READ_STRUCT_T { + PFMU_PROFILE_TAG1 ru4TxBfPFMUTag1; + PFMU_PROFILE_TAG2 ru4TxBfPFMUTag2; +} PARAM_CUSTOM_PFMU_TAG_READ_STRUCT_T, *P_PARAM_CUSTOM_PFMU_TAG_READ_STRUCT_T; + +#if CFG_SUPPORT_MU_MIMO +typedef struct _PARAM_CUSTOM_SHOW_GROUP_TBL_ENTRY_STRUCT_T { + UINT_32 u4EventId; + UINT_8 index; + UINT_8 numUser:2; + UINT_8 BW:2; + UINT_8 NS0:2; + UINT_8 NS1:2; + /* UINT_8 NS2:1; */ + /* UINT_8 NS3:1; */ + UINT_8 PFIDUser0; + UINT_8 PFIDUser1; + /* UINT_8 PFIDUser2; */ + /* UINT_8 PFIDUser3; */ + BOOLEAN fgIsShortGI; + BOOLEAN fgIsUsed; + BOOLEAN fgIsDisable; + UINT_8 initMcsUser0:4; + UINT_8 initMcsUser1:4; + /* UINT_8 initMcsUser2:4; */ + /* UINT_8 initMcsUser3:4; */ + UINT_8 dMcsUser0:4; + UINT_8 dMcsUser1:4; + /* UINT_8 dMcsUser2:4; */ + /* UINT_8 dMcsUser3:4; */ +} PARAM_CUSTOM_SHOW_GROUP_TBL_ENTRY_STRUCT_T, *P_PARAM_CUSTOM_SHOW_GROUP_TBL_ENTRY_STRUCT_T; + +typedef struct _PARAM_CUSTOM_GET_QD_STRUCT_T { + UINT_32 u4EventId; + UINT_32 au4RawData[14]; +} PARAM_CUSTOM_GET_QD_STRUCT_T, *P_PARAM_CUSTOM_GET_QD_STRUCT_T; + +typedef struct _MU_STRUCT_LQ_REPORT { + int lq_report[NUM_OF_USER][NUM_OF_MODUL]; +} MU_STRUCT_LQ_REPORT, *P_MU_STRUCT_LQ_REPORT; + +typedef struct _PARAM_CUSTOM_GET_MU_CALC_LQ_STRUCT_T { + UINT_32 u4EventId; + MU_STRUCT_LQ_REPORT rEntry; +} PARAM_CUSTOM_GET_MU_CALC_LQ_STRUCT_T, *P_PARAM_CUSTOM_GET_MU_CALC_LQ_STRUCT_T; + +typedef struct _MU_GET_CALC_INIT_MCS_T { + UINT_8 ucgroupIdx; + UINT_8 ucRsv[3]; +} MU_GET_CALC_INIT_MCS_T, *P_MU_GET_CALC_INIT_MCS_T; + +typedef struct _MU_SET_INIT_MCS_T { + UINT_8 ucNumOfUser; /* zero-base : 0~3: means 1~2 users */ + UINT_8 ucBandwidth; /* zero-base : 0:20 hz 1:40 hz 2: 80 hz 3: 160 */ + UINT_8 ucNssOfUser0; /* zero-base : 0~1 means uesr0 use 1~2 ss , if no use keep 0 */ + UINT_8 ucNssOfUser1; /* zero-base : 0~1 means uesr0 use 1~2 ss , if no use keep 0 */ + UINT_8 ucPfMuIdOfUser0; /* zero-base : for now, uesr0 use pf mu id 0 */ + UINT_8 ucPfMuIdOfUser1; /* zero-base : for now, uesr1 use pf mu id 1 */ + UINT_8 ucNumOfTxer; /* 0~3: mean use 1~4 anntain, for now, should fix 3 */ + UINT_8 ucSpeIndex; /*add new field to fill special extension index which replace reserve */ + UINT_32 u4GroupIndex; /* 0~ :the index of group table entry for calculation */ +} MU_SET_INIT_MCS_T, *P_MU_SET_INIT_MCS_T; + +typedef struct _MU_SET_CALC_LQ_T { + UINT_8 ucNumOfUser; /* zero-base : 0~3: means 1~2 users */ + UINT_8 ucBandwidth; /* zero-base : 0:20 hz 1:40 hz 2: 80 hz 3: 160 */ + UINT_8 ucNssOfUser0; /* zero-base : 0~1 means uesr0 use 1~2 ss , if no use keep 0 */ + UINT_8 ucNssOfUser1; /* zero-base : 0~1 means uesr0 use 1~2 ss , if no use keep 0 */ + UINT_8 ucPfMuIdOfUser0; /* zero-base : for now, uesr0 use pf mu id 0 */ + UINT_8 ucPfMuIdOfUser1; /* zero-base : for now, uesr1 use pf mu id 1 */ + UINT_8 ucNumOfTxer; /* 0~3: mean use 1~4 anntain, for now, should fix 3 */ + UINT_8 ucSpeIndex; /*add new field to fill special extension index which replace reserve */ + UINT_32 u4GroupIndex; /* 0~ :the index of group table entry for calculation */ +} MU_SET_CALC_LQ_T, *P_MU_SET_CALC_LQ_T; + +typedef struct _MU_GET_LQ_T { + UINT_8 ucType; + UINT_8 ucRsv[3]; +} MU_GET_LQ_T, *P_MU_GET_LQ_T; + +typedef struct _MU_SET_SNR_OFFSET_T { + UINT_8 ucVal; + UINT_8 ucRsv[3]; +} MU_SET_SNR_OFFSET_T, *P_MU_SET_SNR_OFFSET_T; + +typedef struct _MU_SET_ZERO_NSS_T { + UINT_8 ucVal; + UINT_8 ucRsv[3]; +} MU_SET_ZERO_NSS_T, *P_MU_SET_ZERO_NSS_T; + +typedef struct _MU_SPEED_UP_LQ_T { + UINT_32 u4Val; +} MU_SPEED_UP_LQ_T, *P_MU_SPEED_UP_LQ_T; + +typedef struct _MU_SET_MU_TABLE_T { + /* UINT_16 u2Type; */ + /* UINT_32 u4Length; */ + UINT_8 aucMetricTable[NUM_MUT_NR_NUM * NUM_MUT_FEC * NUM_MUT_MCS * NUM_MUT_INDEX]; +} MU_SET_MU_TABLE_T, *P_MU_SET_MU_TABLE_T; + +typedef struct _MU_SET_GROUP_T { + UINT_32 u4GroupIndex; /* Group Table Idx */ + UINT_32 u4NumOfUser; + UINT_32 u4User0Ldpc; + UINT_32 u4User1Ldpc; + UINT_32 u4ShortGI; + UINT_32 u4Bw; + UINT_32 u4User0Nss; + UINT_32 u4User1Nss; + UINT_32 u4GroupId; + UINT_32 u4User0UP; + UINT_32 u4User1UP; + UINT_32 u4User0MuPfId; + UINT_32 u4User1MuPfId; + UINT_32 u4User0InitMCS; + UINT_32 u4User1InitMCS; + UINT_8 aucUser0MacAddr[PARAM_MAC_ADDR_LEN]; + UINT_8 aucUser1MacAddr[PARAM_MAC_ADDR_LEN]; +} MU_SET_GROUP_T, *P_MU_SET_GROUP_T; + +typedef struct _MU_GET_QD_T { + UINT_8 ucSubcarrierIndex; + /* UINT_32 u4Length; */ + /* UINT_8 *prQd; */ +} MU_GET_QD_T, *P_MU_GET_QD_T; + +typedef struct _MU_SET_ENABLE_T { + UINT_8 ucVal; + UINT_8 ucRsv[3]; +} MU_SET_ENABLE_T, *P_MU_SET_ENABLE_T; + +typedef struct _MU_SET_GID_UP_T { + UINT_32 au4Gid[2]; + UINT_32 au4Up[4]; +} MU_SET_GID_UP_T, *P_MU_SET_GID_UP_T; + +typedef struct _MU_TRIGGER_MU_TX_T { + UINT_8 fgIsRandomPattern; /* is random pattern or not */ + UINT_32 u4MsduPayloadLength0; /* payload length of the MSDU for user 0 */ + UINT_32 u4MsduPayloadLength1; /* payload length of the MSDU for user 1 */ + UINT_32 u4MuPacketCount; /* MU TX count */ + UINT_32 u4NumOfSTAs; /* number of user in the MU TX */ + UINT_8 aucMacAddrs[2][6]; /* MAC address of users*/ +} MU_TRIGGER_MU_TX_T, *P_MU_TRIGGER_MU_TX_T; + +typedef struct _PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T { + UINT_8 ucMuMimoCategory; + UINT_8 aucRsv[3]; + union { + MU_GET_CALC_INIT_MCS_T rMuGetCalcInitMcs; + MU_SET_INIT_MCS_T rMuSetInitMcs; + MU_SET_CALC_LQ_T rMuSetCalcLq; + MU_GET_LQ_T rMuGetLq; + MU_SET_SNR_OFFSET_T rMuSetSnrOffset; + MU_SET_ZERO_NSS_T rMuSetZeroNss; + MU_SPEED_UP_LQ_T rMuSpeedUpLq; + MU_SET_MU_TABLE_T rMuSetMuTable; + MU_SET_GROUP_T rMuSetGroup; + MU_GET_QD_T rMuGetQd; + MU_SET_ENABLE_T rMuSetEnable; + MU_SET_GID_UP_T rMuSetGidUp; + MU_TRIGGER_MU_TX_T rMuTriggerMuTx; + } unMuMimoParam; +} PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T, *P_PARAM_CUSTOM_MUMIMO_ACTION_STRUCT_T; +#endif /* CFG_SUPPORT_MU_MIMO */ +#endif /* CFG_SUPPORT_TX_BF */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +typedef struct _PARAM_CUSTOM_MEM_DUMP_STRUCT_T { + UINT_32 u4Address; + UINT_32 u4Length; + UINT_32 u4RemainLength; +#if CFG_SUPPORT_QA_TOOL + UINT_32 u4IcapContent; +#endif /* CFG_SUPPORT_QA_TOOL */ + UINT_8 ucFragNum; +} PARAM_CUSTOM_MEM_DUMP_STRUCT_T, *P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T; + +typedef struct _PARAM_CUSTOM_SW_CTRL_STRUCT_T { + UINT_32 u4Id; + UINT_32 u4Data; +} PARAM_CUSTOM_SW_CTRL_STRUCT_T, *P_PARAM_CUSTOM_SW_CTRL_STRUCT_T; + +typedef struct _PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T { + UINT_16 u2Id; + UINT_8 ucType; + UINT_8 ucRespType; + UINT_16 u2MsgSize; + UINT_8 aucReserved0[2]; + UINT_8 aucCmd[CHIP_CONFIG_RESP_SIZE]; +} PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T, *P_PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T; + +typedef struct _PARAM_CUSTOM_KEY_CFG_STRUCT_T { + UINT_8 aucKey[WLAN_CFG_KEY_LEN_MAX]; + UINT_8 aucValue[WLAN_CFG_VALUE_LEN_MAX]; +} PARAM_CUSTOM_KEY_CFG_STRUCT_T, *P_PARAM_CUSTOM_KEY_CFG_STRUCT_T; + +typedef struct _PARAM_CUSTOM_EEPROM_RW_STRUCT_T { + UINT_8 ucEepromMethod; /* For read only read: 1, query size: 0 */ + UINT_8 ucEepromIndex; + UINT_8 reserved; + UINT_16 u2EepromData; +} PARAM_CUSTOM_EEPROM_RW_STRUCT_T, *P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T, +PARAM_CUSTOM_NVRAM_RW_STRUCT_T, *P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T; + +typedef struct _PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T { + UINT_8 bmfgApsdEnAc; /* b0~3: trigger-en AC0~3. b4~7: delivery-en AC0~3 */ + UINT_8 ucIsEnterPsAtOnce; /* enter PS immediately without 5 second guard after connected */ + UINT_8 ucIsDisableUcTrigger; /* not to trigger UC on beacon TIM is matched (under U-APSD) */ + UINT_8 reserved; +} PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T, *P_PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T; + +typedef struct _PARAM_CUSTOM_NOA_PARAM_STRUCT_T { + UINT_32 u4NoaDurationMs; + UINT_32 u4NoaIntervalMs; + UINT_32 u4NoaCount; + UINT_8 ucBssIdx; +} PARAM_CUSTOM_NOA_PARAM_STRUCT_T, *P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T; + +typedef struct _PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T { + UINT_8 ucBssIdx; + UINT_8 ucLegcyPS; + UINT_8 ucOppPs; + UINT_8 aucResv[1]; + UINT_32 u4CTwindowMs; +} PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T, *P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T; + +typedef struct _PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T { + UINT_8 ucBssIdx; + UINT_8 fgEnAPSD; + UINT_8 fgEnAPSD_AcBe; + UINT_8 fgEnAPSD_AcBk; + UINT_8 fgEnAPSD_AcVo; + UINT_8 fgEnAPSD_AcVi; + UINT_8 ucMaxSpLen; + UINT_8 aucResv[2]; +} PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T, *P_PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T; + +typedef struct _PARAM_CUSTOM_P2P_SET_STRUCT_T { + UINT_32 u4Enable; + UINT_32 u4Mode; +} PARAM_CUSTOM_P2P_SET_STRUCT_T, *P_PARAM_CUSTOM_P2P_SET_STRUCT_T; + +#define MAX_NUMBER_OF_ACL 20 + +typedef enum _ENUM_PARAM_CUSTOM_ACL_POLICY_T { + PARAM_CUSTOM_ACL_POLICY_DISABLE, + PARAM_CUSTOM_ACL_POLICY_ACCEPT, + PARAM_CUSTOM_ACL_POLICY_DENY, + PARAM_CUSTOM_ACL_POLICY_NUM +} ENUM_PARAM_CUSTOM_ACL_POLICY_T, *P_ENUM_PARAM_CUSTOM_ACL_POLICY_T; + +typedef struct _PARAM_CUSTOM_ACL_ENTRY { + UINT_8 aucAddr[MAC_ADDR_LEN]; + UINT_16 u2Rsv; +} PARAM_CUSTOM_ACL_ENTRY, *PPARAM_CUSTOM_ACL_ENTRY; + +typedef struct _PARAM_CUSTOM_ACL { + ENUM_PARAM_CUSTOM_ACL_POLICY_T ePolicy; + UINT_32 u4Num; + PARAM_CUSTOM_ACL_ENTRY rEntry[MAX_NUMBER_OF_ACL]; +} PARAM_CUSTOM_ACL, *PPARAM_CUSTOM_ACL; + +typedef enum _ENUM_CFG_SRC_TYPE_T { + CFG_SRC_TYPE_EEPROM, + CFG_SRC_TYPE_NVRAM, + CFG_SRC_TYPE_UNKNOWN, + CFG_SRC_TYPE_NUM +} ENUM_CFG_SRC_TYPE_T, *P_ENUM_CFG_SRC_TYPE_T; + +typedef enum _ENUM_EEPROM_TYPE_T { + EEPROM_TYPE_NO, + EEPROM_TYPE_PRESENT, + EEPROM_TYPE_NUM +} ENUM_EEPROM_TYPE_T, *P_ENUM_EEPROM_TYPE_T; + +typedef struct _PARAM_QOS_TSINFO { + UINT_8 ucTrafficType; /* Traffic Type: 1 for isochronous 0 for asynchronous */ + UINT_8 ucTid; /* TSID: must be between 8 ~ 15 */ + UINT_8 ucDirection; /* direction */ + UINT_8 ucAccessPolicy; /* access policy */ + UINT_8 ucAggregation; /* aggregation */ + UINT_8 ucApsd; /* APSD */ + UINT_8 ucuserPriority; /* user priority */ + UINT_8 ucTsInfoAckPolicy; /* TSINFO ACK policy */ + UINT_8 ucSchedule; /* Schedule */ +} PARAM_QOS_TSINFO, *P_PARAM_QOS_TSINFO; + +typedef struct _PARAM_QOS_TSPEC { + PARAM_QOS_TSINFO rTsInfo; /* TS info field */ + UINT_16 u2NominalMSDUSize; /* nominal MSDU size */ + UINT_16 u2MaxMSDUsize; /* maximum MSDU size */ + UINT_32 u4MinSvcIntv; /* minimum service interval */ + UINT_32 u4MaxSvcIntv; /* maximum service interval */ + UINT_32 u4InactIntv; /* inactivity interval */ + UINT_32 u4SpsIntv; /* suspension interval */ + UINT_32 u4SvcStartTime; /* service start time */ + UINT_32 u4MinDataRate; /* minimum Data rate */ + UINT_32 u4MeanDataRate; /* mean data rate */ + UINT_32 u4PeakDataRate; /* peak data rate */ + UINT_32 u4MaxBurstSize; /* maximum burst size */ + UINT_32 u4DelayBound; /* delay bound */ + UINT_32 u4MinPHYRate; /* minimum PHY rate */ + UINT_16 u2Sba; /* surplus bandwidth allowance */ + UINT_16 u2MediumTime; /* medium time */ +} PARAM_QOS_TSPEC, *P_PARAM_QOS_TSPEC; + +typedef struct _PARAM_QOS_ADDTS_REQ_INFO { + PARAM_QOS_TSPEC rTspec; +} PARAM_QOS_ADDTS_REQ_INFO, *P_PARAM_QOS_ADDTS_REQ_INFO; + +typedef struct _PARAM_VOIP_CONFIG { + UINT_32 u4VoipTrafficInterval; /* 0: disable VOIP configuration */ +} PARAM_VOIP_CONFIG, *P_PARAM_VOIP_CONFIG; + +/*802.11 Statistics Struct*/ +typedef struct _PARAM_802_11_STATISTICS_STRUCT_T { + UINT_32 u4Length; /* Length of structure */ + LARGE_INTEGER rTransmittedFragmentCount; + LARGE_INTEGER rMulticastTransmittedFrameCount; + LARGE_INTEGER rFailedCount; + LARGE_INTEGER rRetryCount; + LARGE_INTEGER rMultipleRetryCount; + LARGE_INTEGER rRTSSuccessCount; + LARGE_INTEGER rRTSFailureCount; + LARGE_INTEGER rACKFailureCount; + LARGE_INTEGER rFrameDuplicateCount; + LARGE_INTEGER rReceivedFragmentCount; + LARGE_INTEGER rMulticastReceivedFrameCount; + LARGE_INTEGER rFCSErrorCount; + LARGE_INTEGER rTKIPLocalMICFailures; + LARGE_INTEGER rTKIPICVErrors; + LARGE_INTEGER rTKIPCounterMeasuresInvoked; + LARGE_INTEGER rTKIPReplays; + LARGE_INTEGER rCCMPFormatErrors; + LARGE_INTEGER rCCMPReplays; + LARGE_INTEGER rCCMPDecryptErrors; + LARGE_INTEGER rFourWayHandshakeFailures; + LARGE_INTEGER rWEPUndecryptableCount; + LARGE_INTEGER rWEPICVErrorCount; + LARGE_INTEGER rDecryptSuccessCount; + LARGE_INTEGER rDecryptFailureCount; +} PARAM_802_11_STATISTICS_STRUCT_T, *P_PARAM_802_11_STATISTICS_STRUCT_T; + +/* Linux Network Device Statistics Struct */ +typedef struct _PARAM_LINUX_NETDEV_STATISTICS_T { + UINT_32 u4RxPackets; + UINT_32 u4TxPackets; + UINT_32 u4RxBytes; + UINT_32 u4TxBytes; + UINT_32 u4RxErrors; + UINT_32 u4TxErrors; + UINT_32 u4Multicast; +} PARAM_LINUX_NETDEV_STATISTICS_T, *P_PARAM_LINUX_NETDEV_STATISTICS_T; + +typedef struct _PARAM_MTK_WIFI_TEST_STRUCT_T { + UINT_32 u4FuncIndex; + UINT_32 u4FuncData; +} PARAM_MTK_WIFI_TEST_STRUCT_T, *P_PARAM_MTK_WIFI_TEST_STRUCT_T; + +/* 802.11 Media stream constraints */ +typedef enum _ENUM_MEDIA_STREAM_MODE { + ENUM_MEDIA_STREAM_OFF, + ENUM_MEDIA_STREAM_ON +} ENUM_MEDIA_STREAM_MODE, *P_ENUM_MEDIA_STREAM_MODE; + +/* for NDIS 5.1 Media Streaming Change */ +typedef struct _PARAM_MEDIA_STREAMING_INDICATION { + PARAM_STATUS_INDICATION_T rStatus; + ENUM_MEDIA_STREAM_MODE eMediaStreamMode; +} PARAM_MEDIA_STREAMING_INDICATION, *P_PARAM_MEDIA_STREAMING_INDICATION; + +#define PARAM_PROTOCOL_ID_DEFAULT 0x00 +#define PARAM_PROTOCOL_ID_TCP_IP 0x02 +#define PARAM_PROTOCOL_ID_IPX 0x06 +#define PARAM_PROTOCOL_ID_NBF 0x07 +#define PARAM_PROTOCOL_ID_MAX 0x0F +#define PARAM_PROTOCOL_ID_MASK 0x0F + +/* for NDIS OID_GEN_NETWORK_LAYER_ADDRESSES */ +typedef struct _PARAM_NETWORK_ADDRESS_IP { + UINT_16 sin_port; + UINT_32 in_addr; + UINT_8 sin_zero[8]; +} PARAM_NETWORK_ADDRESS_IP, *P_PARAM_NETWORK_ADDRESS_IP; + +typedef struct _PARAM_NETWORK_ADDRESS { + UINT_16 u2AddressLength; /* length in bytes of Address[] in this */ + UINT_16 u2AddressType; /* type of this address (PARAM_PROTOCOL_ID_XXX above) */ + UINT_8 aucAddress[1]; /* actually AddressLength bytes long */ +} PARAM_NETWORK_ADDRESS, *P_PARAM_NETWORK_ADDRESS; + +/* The following is used with OID_GEN_NETWORK_LAYER_ADDRESSES to set network layer addresses on an interface */ + +typedef struct _PARAM_NETWORK_ADDRESS_LIST { + UINT_8 ucBssIdx; + UINT_32 u4AddressCount; /* number of addresses following */ + UINT_16 u2AddressType; /* type of this address (NDIS_PROTOCOL_ID_XXX above) */ + PARAM_NETWORK_ADDRESS arAddress[1]; /* actually AddressCount elements long */ +} PARAM_NETWORK_ADDRESS_LIST, *P_PARAM_NETWORK_ADDRESS_LIST; + +#if CFG_SLT_SUPPORT + +#define FIXED_BW_LG20 0x0000 +#define FIXED_BW_UL20 0x2000 +#define FIXED_BW_DL40 0x3000 + +#define FIXED_EXT_CHNL_U20 0x4000 /* For AGG register. */ +#define FIXED_EXT_CHNL_L20 0xC000 /* For AGG regsiter. */ + +typedef enum _ENUM_MTK_LP_TEST_MODE_T { + ENUM_MTK_LP_TEST_NORMAL, + ENUM_MTK_LP_TEST_GOLDEN_SAMPLE, + ENUM_MTK_LP_TEST_DUT, + ENUM_MTK_LP_TEST_MODE_NUM +} ENUM_MTK_LP_TEST_MODE_T, *P_ENUM_MTK_LP_TEST_MODE_T; + +typedef enum _ENUM_MTK_SLT_FUNC_IDX_T { + ENUM_MTK_SLT_FUNC_DO_NOTHING, + ENUM_MTK_SLT_FUNC_INITIAL, + ENUM_MTK_SLT_FUNC_RATE_SET, + ENUM_MTK_SLT_FUNC_LP_SET, + ENUM_MTK_SLT_FUNC_NUM +} ENUM_MTK_SLT_FUNC_IDX_T, *P_ENUM_MTK_SLT_FUNC_IDX_T; + +typedef struct _PARAM_MTK_SLT_LP_TEST_STRUCT_T { + ENUM_MTK_LP_TEST_MODE_T rLpTestMode; + UINT_32 u4BcnRcvNum; +} PARAM_MTK_SLT_LP_TEST_STRUCT_T, *P_PARAM_MTK_SLT_LP_TEST_STRUCT_T; + +typedef struct _PARAM_MTK_SLT_TR_TEST_STRUCT_T { + ENUM_PARAM_NETWORK_TYPE_T rNetworkType; /* Network Type OFDM5G or OFDM2.4G */ + UINT_32 u4FixedRate; /* Fixed Rate including BW */ +} PARAM_MTK_SLT_TR_TEST_STRUCT_T, *P_PARAM_MTK_SLT_TR_TEST_STRUCT_T; + +typedef struct _PARAM_MTK_SLT_INITIAL_STRUCT_T { + UINT_8 aucTargetMacAddr[PARAM_MAC_ADDR_LEN]; + UINT_16 u2SiteID; +} PARAM_MTK_SLT_INITIAL_STRUCT_T, *P_PARAM_MTK_SLT_INITIAL_STRUCT_T; + +typedef struct _PARAM_MTK_SLT_TEST_STRUCT_T { + ENUM_MTK_SLT_FUNC_IDX_T rSltFuncIdx; + UINT_32 u4Length; /* Length of structure, */ + /* including myself */ + UINT_32 u4FuncInfoLen; /* Include following content */ + /* field and myself */ + union { + PARAM_MTK_SLT_INITIAL_STRUCT_T rMtkInitTest; + PARAM_MTK_SLT_LP_TEST_STRUCT_T rMtkLpTest; + PARAM_MTK_SLT_TR_TEST_STRUCT_T rMtkTRTest; + } unFuncInfoContent; + +} PARAM_MTK_SLT_TEST_STRUCT_T, *P_PARAM_MTK_SLT_TEST_STRUCT_T; + +#endif + +#if CFG_SUPPORT_MSP +/* Should by chip */ +typedef struct _PARAM_SEC_CONFIG_T { + BOOL fgWPIFlag; + BOOL fgRV; + BOOL fgIKV; + BOOL fgRKV; + + BOOL fgRCID; + BOOL fgRCA1; + BOOL fgRCA2; + BOOL fgEvenPN; + + UINT_8 ucKeyID; + UINT_8 ucMUARIdx; + UINT_8 ucCipherSuit; + UINT_8 aucReserved[1]; +} PARAM_SEC_CONFIG_T, *P_PARAM_SEC_CONFIG_T; + +typedef struct _PARAM_TX_CONFIG_T { + UINT_8 aucPA[6]; + BOOL fgSW; + BOOL fgDisRxHdrTran; + + BOOL fgAADOM; + UINT_8 ucPFMUIdx; + UINT_16 u2PartialAID; + + BOOL fgTIBF; + BOOL fgTEBF; + BOOL fgIsHT; + BOOL fgIsVHT; + + BOOL fgMesh; + BOOL fgBAFEn; + BOOL fgCFAck; + BOOL fgRdgBA; + + BOOL fgRDG; + BOOL fgIsPwrMgt; + BOOL fgRTS; + BOOL fgSMPS; + + BOOL fgTxopPS; + BOOL fgDonotUpdateIPSM; + BOOL fgSkipTx; + BOOL fgLDPC; + + BOOL fgIsQoS; + BOOL fgIsFromDS; + BOOL fgIsToDS; + BOOL fgDynBw; + + BOOL fgIsAMSDUCrossLG; + BOOL fgCheckPER; + BOOL fgIsGID63; + UINT_8 aucReserved[1]; + +#if (1 /* CFG_SUPPORT_VHT == 1 */) + BOOL fgVhtTIBF; + BOOL fgVhtTEBF; + BOOL fgVhtLDPC; + UINT_8 aucReserved2[1]; +#endif +} PARAM_TX_CONFIG_T, *P_PARAM_TX_CONFIG_T; + +typedef struct _PARAM_KEY_CONFIG_T { + UINT_8 aucKey[32]; +} PARAM_KEY_CONFIG_T, *P_PARAM_KEY_CONFIG_T; + +typedef struct _PARAM_PEER_RATE_INFO_T { + UINT_8 ucCounterMPDUFail; + UINT_8 ucCounterMPDUTx; + UINT_8 ucRateIdx; + UINT_8 ucReserved[1]; + + UINT_16 au2RateCode[AUTO_RATE_NUM]; +} PARAM_PEER_RATE_INFO_T, *P_PARAM_PEER_RATE_INFO_T; + +typedef struct _PARAM_PEER_BA_CONFIG_T { + UINT_8 ucBaEn; + UINT_8 ucRsv[3]; + UINT_32 u4BaWinSize; +} PARAM_PEER_BA_CONFIG_T, *P_PARAM_PEER_BA_CONFIG_T; + +typedef struct _PARAM_ANT_ID_CONFIG_T { + UINT_8 ucANTIDSts0; + UINT_8 ucANTIDSts1; + UINT_8 ucANTIDSts2; + UINT_8 ucANTIDSts3; +} PARAM_ANT_ID_CONFIG_T, *P_PARAM_ANT_ID_CONFIG_T; + +typedef struct _PARAM_PEER_CAP_T { + PARAM_ANT_ID_CONFIG_T rAntIDConfig; + + UINT_8 ucTxPowerOffset; + UINT_8 ucCounterBWSelector; + UINT_8 ucChangeBWAfterRateN; + UINT_8 ucFrequencyCapability; + UINT_8 ucSpatialExtensionIndex; + + BOOL fgG2; + BOOL fgG4; + BOOL fgG8; + BOOL fgG16; + + UINT_8 ucMMSS; + UINT_8 ucAmpduFactor; + UINT_8 ucReserved[1]; +} PARAM_PEER_CAP_T, *P_PARAM_PEER_CAP_T; + +typedef struct _PARAM_PEER_RX_COUNTER_ALL_T { + UINT_8 ucRxRcpi0; + UINT_8 ucRxRcpi1; + UINT_8 ucRxRcpi2; + UINT_8 ucRxRcpi3; + + UINT_8 ucRxCC0; + UINT_8 ucRxCC1; + UINT_8 ucRxCC2; + UINT_8 ucRxCC3; + + BOOL fgRxCCSel; + UINT_8 ucCeRmsd; + UINT_8 aucReserved[2]; +} PARAM_PEER_RX_COUNTER_ALL_T, *P_PARAM_PEER_RX_COUNTER_ALL_T; + +typedef struct _PARAM_PEER_TX_COUNTER_ALL_T { + UINT_16 u2Rate1TxCnt; + UINT_16 u2Rate1FailCnt; + UINT_16 u2Rate2OkCnt; + UINT_16 u2Rate3OkCnt; + UINT_16 u2CurBwTxCnt; + UINT_16 u2CurBwFailCnt; + UINT_16 u2OtherBwTxCnt; + UINT_16 u2OtherBwFailCnt; +} PARAM_PEER_TX_COUNTER_ALL_T, *P_PARAM_PEER_TX_COUNTER_ALL_T; + +typedef struct _PARAM_HW_WLAN_INFO_T { + UINT_32 u4Index; + PARAM_TX_CONFIG_T rWtblTxConfig; + PARAM_SEC_CONFIG_T rWtblSecConfig; + PARAM_KEY_CONFIG_T rWtblKeyConfig; + PARAM_PEER_RATE_INFO_T rWtblRateInfo; + PARAM_PEER_BA_CONFIG_T rWtblBaConfig; + PARAM_PEER_CAP_T rWtblPeerCap; + PARAM_PEER_RX_COUNTER_ALL_T rWtblRxCounter; + PARAM_PEER_TX_COUNTER_ALL_T rWtblTxCounter; +} PARAM_HW_WLAN_INFO_T, *P_PARAM_HW_WLAN_INFO_T; + +typedef struct _HW_TX_AMPDU_METRICS_T { + UINT_32 u4TxSfCnt; + UINT_32 u4TxAckSfCnt; + UINT_32 u2TxAmpduCnt; + UINT_32 u2TxRspBaCnt; + UINT_16 u2TxEarlyStopCnt; + UINT_16 u2TxRange1AmpduCnt; + UINT_16 u2TxRange2AmpduCnt; + UINT_16 u2TxRange3AmpduCnt; + UINT_16 u2TxRange4AmpduCnt; + UINT_16 u2TxRange5AmpduCnt; + UINT_16 u2TxRange6AmpduCnt; + UINT_16 u2TxRange7AmpduCnt; + UINT_16 u2TxRange8AmpduCnt; + UINT_16 u2TxRange9AmpduCnt; +} HW_TX_AMPDU_METRICS_T, *P_HW_TX_AMPDU_METRICS_T; + +typedef struct _HW_MIB_COUNTER_T { + UINT_32 u4RxFcsErrCnt; + UINT_32 u4RxFifoFullCnt; + UINT_32 u4RxMpduCnt; + UINT_32 u4RxAMPDUCnt; + UINT_32 u4RxTotalByte; + UINT_32 u4RxValidAMPDUSF; + UINT_32 u4RxValidByte; + UINT_32 u4ChannelIdleCnt; + UINT_32 u4RxVectorDropCnt; + UINT_32 u4DelimiterFailedCnt; + UINT_32 u4RxVectorMismatchCnt; + UINT_32 u4MdrdyCnt; + UINT_32 u4CCKMdrdyCnt; + UINT_32 u4OFDMLGMixMdrdy; + UINT_32 u4OFDMGreenMdrdy; + UINT_32 u4PFDropCnt; + UINT_32 u4RxLenMismatchCnt; + UINT_32 u4PCcaTime; + UINT_32 u4SCcaTime; + UINT_32 u4CcaNavTx; + UINT_32 u4PEDTime; + UINT_32 u4BeaconTxCnt; + UINT_32 au4BaMissedCnt[BSSID_NUM]; + UINT_32 au4RtsTxCnt[BSSID_NUM]; + UINT_32 au4FrameRetryCnt[BSSID_NUM]; + UINT_32 au4FrameRetry2Cnt[BSSID_NUM]; + UINT_32 au4RtsRetryCnt[BSSID_NUM]; + UINT_32 au4AckFailedCnt[BSSID_NUM]; +} HW_MIB_COUNTER_T, *P_HW_MIB_COUNTER_T; + +typedef struct _HW_MIB2_COUNTER_T { + UINT_32 u4Tx40MHzCnt; + UINT_32 u4Tx80MHzCnt; + UINT_32 u4Tx160MHzCnt; +} HW_MIB2_COUNTER_T, *P_HW_MIB2_COUNTER_T; + +typedef struct _PARAM_HW_MIB_INFO_T { + UINT_32 u4Index; + HW_MIB_COUNTER_T rHwMibCnt; + HW_MIB2_COUNTER_T rHwMib2Cnt; + HW_TX_AMPDU_METRICS_T rHwTxAmpduMts; +} PARAM_HW_MIB_INFO_T, *P_PARAM_HW_MIB_INFO_T; +#endif + +#if CFG_SUPPORT_LAST_SEC_MCS_INFO +struct PARAM_TX_MCS_INFO { + UINT_8 ucStaIndex; + UINT_16 au2TxRateCode[MCS_INFO_SAMPLE_CNT]; + UINT_8 aucTxRatePer[MCS_INFO_SAMPLE_CNT]; +}; +#endif + +struct PARAM_CMD_GET_TXPWR_TBL { + UINT_8 ucDbdcIdx; + UINT_8 ucCenterCh; + struct POWER_LIMIT tx_pwr_tbl[TXPWR_TBL_NUM]; +}; + +enum ENUM_TXPWR_TYPE { + DSSS = 0, + OFDM_24G, + OFDM_5G, + HT20, + HT40, + VHT20, + VHT40, + VHT80, + TXPWR_TYPE_NUM, +}; + +enum ENUM_STREAM_MODE { + STREAM_SISO, + STREAM_CDD, + STREAM_MIMO, + STREAM_NUM +}; + +struct txpwr_table_entry { + char mcs[STREAM_NUM][8]; + unsigned int idx; +}; + +struct txpwr_table { + char phy_mode[8]; + struct txpwr_table_entry *tables; + int n_tables; +}; + +/*--------------------------------------------------------------*/ +/*! \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; + +typedef struct _PARAM_SCAN_REQUEST_ADV_T { + UINT_32 u4SsidNum; + PARAM_SSID_T rSsid[CFG_SCAN_SSID_MAX_NUM]; + UINT_32 u4IELength; + PUINT_8 pucIE; +#if CFG_SCAN_CHANNEL_SPECIFIED + UINT_8 ucChannelListNum; + RF_CHANNEL_INFO_T arChnlInfoList[MAXIMUM_OPERATION_CHANNEL_LIST]; +#endif +} PARAM_SCAN_REQUEST_ADV_T, *P_PARAM_SCAN_REQUEST_ADV_T; + +/*--------------------------------------------------------------*/ +/*! \brief CFG80211 Scheduled Scan Request Container */ +/*--------------------------------------------------------------*/ +typedef struct _PARAM_SCHED_SCAN_REQUEST_T { + UINT_32 u4SsidNum; + PARAM_SSID_T arSsid[CFG_SCAN_SSID_MATCH_MAX_NUM]; + UINT_32 u4IELength; + PUINT_8 pucIE; + UINT_16 u2ScanInterval; /* in milliseconds */ +} PARAM_SCHED_SCAN_REQUEST, *P_PARAM_SCHED_SCAN_REQUEST; + +#if CFG_SUPPORT_PASSPOINT +typedef struct _PARAM_HS20_SET_BSSID_POOL { + BOOLEAN fgIsEnable; + UINT_8 ucNumBssidPool; + PARAM_MAC_ADDRESS arBSSID[8]; +} PARAM_HS20_SET_BSSID_POOL, *P_PARAM_HS20_SET_BSSID_POOL; + +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_SNIFFER +typedef struct _PARAM_CUSTOM_MONITOR_SET_STRUCT_T { + UINT_8 ucEnable; + UINT_8 ucBand; + UINT_8 ucPriChannel; + UINT_8 ucSco; + UINT_8 ucChannelWidth; + UINT_8 ucChannelS1; + UINT_8 ucChannelS2; + UINT_8 aucResv[9]; +} PARAM_CUSTOM_MONITOR_SET_STRUCT_T, *P_PARAM_CUSTOM_MONITOR_SET_STRUCT_T; +#endif + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +/*--------------------------------------------------------------*/ +/*! \brief MTK Auto Channel Selection related Container */ +/*--------------------------------------------------------------*/ +typedef struct _LTE_SAFE_CHN_INFO_T { + UINT_32 au4SafeChannelBitmask[5]; /* NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_MAX */ +} LTE_SAFE_CHN_INFO_T, *P_CMD_LTE_SAFE_CHN_INFO_T; + +typedef struct _PARAM_CHN_LOAD_INFO { + /* Per-CHN Load */ + UINT_8 ucChannel; + UINT_16 u2APNum; + UINT_32 u4Dirtiness; + UINT_8 ucReserved; +} PARAM_CHN_LOAD_INFO, *P_PARAM_CHN_LOAD_INFO; + +typedef struct _PARAM_CHN_RANK_INFO { + UINT_8 ucChannel; + UINT_32 u4Dirtiness; + UINT_8 ucReserved; +} PARAM_CHN_RANK_INFO, *P_PARAM_CHN_RANK_INFO; + +typedef struct _PARAM_GET_CHN_INFO { + LTE_SAFE_CHN_INFO_T rLteSafeChnList; + PARAM_CHN_LOAD_INFO rEachChnLoad[MAX_CHN_NUM]; + BOOLEAN fgDataReadyBit; + PARAM_CHN_RANK_INFO rChnRankList[MAX_CHN_NUM]; + UINT_8 aucReserved[3]; +} PARAM_GET_CHN_INFO, *P_PARAM_GET_CHN_INFO; + +typedef struct _PARAM_PREFER_CHN_INFO { + UINT_8 ucChannel; + UINT_16 u2APNumScore; + UINT_8 ucReserved; +} PARAM_PREFER_CHN_INFO, *P_PARAM_PREFER_CHN_INFO; +#endif + + +typedef struct _UMAC_STAT2_GET_T { + UINT_16 u2PleRevPgHif0Group0; + UINT_16 u2PleRevPgCpuGroup2; + + UINT_16 u2PseRevPgHif0Group0; + UINT_16 u2PseRevPgHif1Group1; + UINT_16 u2PseRevPgCpuGroup2; + UINT_16 u2PseRevPgLmac0Group3; + UINT_16 u2PseRevPgLmac1Group4; + UINT_16 u2PseRevPgLmac2Group5; + UINT_16 u2PseRevPgPleGroup6; + + UINT_16 u2PleSrvPgHif0Group0; + UINT_16 u2PleSrvPgCpuGroup2; + + UINT_16 u2PseSrvPgHif0Group0; + UINT_16 u2PseSrvPgHif1Group1; + UINT_16 u2PseSrvPgCpuGroup2; + UINT_16 u2PseSrvPgLmac0Group3; + UINT_16 u2PseSrvPgLmac1Group4; + UINT_16 u2PseSrvPgLmac2Group5; + UINT_16 u2PseSrvPgPleGroup6; + + UINT_16 u2PleTotalPageNum; + UINT_16 u2PleFreePageNum; + UINT_16 u2PleFfaNum; + + UINT_16 u2PseTotalPageNum; + UINT_16 u2PseFreePageNum; + UINT_16 u2PseFfaNum; +} UMAC_STAT2_GET_T, *P_UMAC_STAT2_GET_T; + +typedef struct _CNM_STATUS_T { + UINT_8 fgDbDcModeEn; + UINT_8 ucChNumB0; + UINT_8 ucChNumB1; + UINT_8 usReserved; +} CNM_STATUS_T, *P_CNM_STATUS_T; + +typedef struct _CNM_CH_LIST_T { + UINT_8 ucChNum[4]; +} CNM_CH_LIST_T, *P_CNM_CH_LIST_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 +wlanoidSetBssidListScanAdv(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 +wlanoidSetConnect(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 +_wlanoidQueryRssi(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen, IN BOOLEAN fgIsOid); + +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); + +#if CFG_SUPPORT_QA_TOOL +#if CFG_SUPPORT_BUFFER_MODE +WLAN_STATUS wlanoidSetEfusBufferMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +/*#if (CFG_EEPROM_PAGE_ACCESS == 1)*/ +WLAN_STATUS +wlanoidQueryProcessAccessEfuseRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryProcessAccessEfuseWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryEfuseFreeBlock(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryGetTxPower(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +/*#endif*/ + +#endif /* CFG_SUPPORT_BUFFER_MODE */ +WLAN_STATUS +wlanoidQueryRxStatistics(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidBssInfoBasic(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidDevInfoActive(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidManualAssoc(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +#if CFG_SUPPORT_TX_BF +WLAN_STATUS +wlanoidTxBfAction(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen); +WLAN_STATUS wlanoidMuMimoAction(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen); +WLAN_STATUS wlanoidStaRecUpdate(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen); +WLAN_STATUS wlanoidStaRecBFUpdate(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen); +#endif /* CFG_SUPPORT_TX_BF */ +#endif /* CFG_SUPPORT_QA_TOOL */ + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +WLAN_STATUS +wlanoidSendCalBackupV2Cmd(IN P_ADAPTER_T prAdapter, IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen); + +WLAN_STATUS +wlanoidSetCalBackup(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryCalBackupV2(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); +#endif + +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 +wlanoidQueryDrvMcrRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetDrvMcrWrite(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 +wlanoidSetChipConfig(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryChipConfig(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetKeyCfg(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryEepromRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetEepromWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryRfTestRxStatus(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryRfTestTxStatus(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryOidInterfaceVersion(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryVendorId(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryMulticastList(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetMulticastList(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryRcvError(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryRcvNoBuffer(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryRcvCrcError(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryStatistics(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryCoexIso(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryCoexGetInfo(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 +wlanoidRftestSetTestIcapMode(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 CFG_SUPPORT_ADVANCE_CONTROL +WLAN_STATUS +wlanoidAdvCtrl(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +_wlanoidAdvCtrl(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen, IN BOOLEAN fgIsOid); + +#endif + +WLAN_STATUS +wlanoidQueryWlanInfo(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +_wlanoidQueryWlanInfo(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen, IN BOOLEAN fgIsOid); + + +WLAN_STATUS +wlanoidQueryMibInfo(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); +#if CFG_SUPPORT_LAST_SEC_MCS_INFO +WLAN_STATUS +wlanoidTxMcsInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); +#endif + +WLAN_STATUS +wlanoidSetFwLog2Host( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen); + +#if 0 +WLAN_STATUS +wlanoidSetNoaParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetOppPsParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetUApsdParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBT(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryBT(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetTxPower(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +#if 0 +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); +#endif + +#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 + +WLAN_STATUS +wlanoidSetDefaultKey(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetGtkRekeyData(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetStartSchedScan(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetStopSchedScan(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +#if CFG_M0VE_BA_TO_DRIVER +WLAN_STATUS wlanoidResetBAScoreboard(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen); +#endif + +#if CFG_SUPPORT_BATCH_SCAN +WLAN_STATUS +wlanoidSetBatchScanReq(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryBatchScanResult(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); +#endif + +#if CFG_SUPPORT_PASSPOINT +WLAN_STATUS +wlanoidSetHS20Info(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetInterworkingInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetRoamingConsortiumIEInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetHS20BssidPool(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_SNIFFER +WLAN_STATUS wlanoidSetMonitor(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +WLAN_STATUS +wlanoidNotifyFwSuspend(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen); +#if CFG_SUPPORT_DBDC +WLAN_STATUS +wlanoidSetDbdcEnable( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen); +#endif /*#if CFG_SUPPORT_DBDC*/ + +WLAN_STATUS +wlanoidQuerySetTxTargetPower(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +#if (CFG_SUPPORT_DFS_MASTER == 1) +WLAN_STATUS +wlanoidQuerySetRddReport(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQuerySetRadarDetectMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +WLAN_STATUS +wlanoidQueryLteSafeChannel(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); +WLAN_STATUS +wlanCalculateAllChannelDirtiness(IN P_ADAPTER_T prAdapter); +VOID +wlanInitChnLoadInfoChannelList(IN P_ADAPTER_T prAdapter); +UINT_8 +wlanGetChannelIndex(IN UINT_8 channel); +UINT_8 +wlanGetChannelNumFromIndex(IN UINT_8 ucIdx); +VOID +wlanSortChannel(IN P_ADAPTER_T prAdapter); +#endif + +WLAN_STATUS +wlanoidLinkDown(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +WLAN_STATUS +wlanoidSetCSIControl( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidGetTxPwrTbl(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidEnableRoaming(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidConfigRoaming(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _WLAN_OID_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/wlan_p2p.h b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/wlan_p2p.h new file mode 100644 index 0000000000000..b684e9552a35e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/include/wlan_p2p.h @@ -0,0 +1,271 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +#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; + /* Following add to change the original windows structure */ + UINT_8 ucBssIdx; /* for specific P2P BSS interface. */ + UINT_8 ucCipher; + UINT_8 aucKeyMaterial[32]; /*!< Key content by above setting */ +} P2P_PARAM_KEY_T, *P_P2P_PARAM_KEY_T; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/*--------------------------------------------------------------*/ +/* Routines to handle command */ +/*--------------------------------------------------------------*/ +/* WLAN_STATUS */ +/* wlanoidSetAddP2PKey(IN P_ADAPTER_T prAdapter, */ +/* IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); */ + +/* WLAN_STATUS */ +/* wlanoidSetRemoveP2PKey(IN P_ADAPTER_T prAdapter, */ +/* IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); */ + +WLAN_STATUS +wlanoidSetNetworkAddress(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetP2PMulticastList(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +/*--------------------------------------------------------------*/ +/* Service Discovery Subroutines */ +/*--------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendP2PSDRequest(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSendP2PSDResponse(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidGetP2PSDRequest(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidGetP2PSDResponse(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 puQueryInfoLen); + +WLAN_STATUS +wlanoidSetP2PTerminateSDPhase(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +#if CFG_SUPPORT_ANTI_PIRACY +WLAN_STATUS +wlanoidSetSecCheckRequest(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +/*WLAN_STATUS +*wlanoidGetSecCheckResponse(IN P_ADAPTER_T prAdapter, +* IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); +*/ +#endif + +WLAN_STATUS +wlanoidSetNoaParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetOppPsParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetUApsdParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryP2pPowerSaveProfile(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetP2pPowerSaveProfile(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetP2pSetNetworkAddress(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +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_HOTSPOT_WPS_MANAGER +WLAN_STATUS +wlanoidSetP2pWPSmode(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); +#endif + +#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 */ From e0d1413b48e750a0a3deedd9dc9c3ff5bd3bb795 Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 22:27:34 +0800 Subject: [PATCH 31/32] Add files via upload --- .../wlan/core/gen4-mt7668/mgmt/aaa_fsm.c | 1378 +++++ .../wlan/core/gen4-mt7668/mgmt/ais_fsm.c | 4833 +++++++++++++++++ .../wlan/core/gen4-mt7668/mgmt/assoc.c | 1721 ++++++ .../wlan/core/gen4-mt7668/mgmt/auth.c | 1236 +++++ .../wlan/core/gen4-mt7668/mgmt/bss.c | 2464 +++++++++ .../wlan/core/gen4-mt7668/mgmt/cnm.c | 1614 ++++++ .../wlan/core/gen4-mt7668/mgmt/cnm_mem.c | 1582 ++++++ .../wlan/core/gen4-mt7668/mgmt/cnm_timer.c | 462 ++ .../wlan/core/gen4-mt7668/mgmt/hem_mbox.c | 560 ++ .../wlan/core/gen4-mt7668/mgmt/hs20.c | 554 ++ .../wlan/core/gen4-mt7668/mgmt/mib.c | 139 + .../wlan/core/gen4-mt7668/mgmt/p2p_assoc.c | 138 + .../wlan/core/gen4-mt7668/mgmt/p2p_bss.c | 109 + .../wlan/core/gen4-mt7668/mgmt/p2p_dev_fsm.c | 862 +++ .../core/gen4-mt7668/mgmt/p2p_dev_state.c | 345 ++ .../wlan/core/gen4-mt7668/mgmt/p2p_fsm.c | 327 ++ .../wlan/core/gen4-mt7668/mgmt/p2p_func.c | 4364 +++++++++++++++ .../wlan/core/gen4-mt7668/mgmt/p2p_ie.c | 194 + .../wlan/core/gen4-mt7668/mgmt/p2p_rlm.c | 1158 ++++ .../wlan/core/gen4-mt7668/mgmt/p2p_rlm_obss.c | 360 ++ .../wlan/core/gen4-mt7668/mgmt/p2p_role_fsm.c | 2637 +++++++++ .../core/gen4-mt7668/mgmt/p2p_role_state.c | 499 ++ .../wlan/core/gen4-mt7668/mgmt/p2p_scan.c | 284 + .../wlan/core/gen4-mt7668/mgmt/privacy.c | 1250 +++++ .../wlan/core/gen4-mt7668/mgmt/rate.c | 499 ++ .../wlan/core/gen4-mt7668/mgmt/reg_rule.c | 387 ++ .../wlan/core/gen4-mt7668/mgmt/rlm.c | 4601 ++++++++++++++++ .../wlan/core/gen4-mt7668/mgmt/rlm_domain.c | 3247 +++++++++++ .../wlan/core/gen4-mt7668/mgmt/rlm_obss.c | 400 ++ .../core/gen4-mt7668/mgmt/rlm_protection.c | 104 + .../wlan/core/gen4-mt7668/mgmt/roaming_fsm.c | 652 +++ .../wlan/core/gen4-mt7668/mgmt/rsn.c | 3116 +++++++++++ .../wlan/core/gen4-mt7668/mgmt/saa_fsm.c | 2248 ++++++++ .../wlan/core/gen4-mt7668/mgmt/scan.c | 2778 ++++++++++ .../wlan/core/gen4-mt7668/mgmt/scan_fsm.c | 1067 ++++ .../wlan/core/gen4-mt7668/mgmt/swcr.c | 1234 +++++ .../wlan/core/gen4-mt7668/mgmt/tdls.c | 1979 +++++++ .../wlan/core/gen4-mt7668/mgmt/tkip_mic.c | 627 +++ .../wlan/core/gen4-mt7668/mgmt/wapi.c | 503 ++ 39 files changed, 52512 insertions(+) create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/aaa_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/ais_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/assoc.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/auth.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/bss.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/cnm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/cnm_mem.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/cnm_timer.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/hem_mbox.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/hs20.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/mib.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_assoc.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_bss.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_dev_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_dev_state.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_func.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_ie.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_rlm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_rlm_obss.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_role_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_role_state.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_scan.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/privacy.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/rate.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/reg_rule.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/rlm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/rlm_domain.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/rlm_obss.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/rlm_protection.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/roaming_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/rsn.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/saa_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/scan.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/scan_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/swcr.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/tdls.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/tkip_mic.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/wapi.c diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/aaa_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/aaa_fsm.c new file mode 100644 index 0000000000000..4ea097cce03d1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/aaa_fsm.c @@ -0,0 +1,1378 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/aaa_fsm.c#3 $ +*/ + +/*! \file "aaa_fsm.c" +* \brief This file defines the FSM for AAA MODULE. +* +* This file defines the FSM for AAA MODULE. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send Event to AIS/BOW/P2P +* +* @param[in] rJoinStatus To indicate JOIN success or failure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] prSwRfb Pointer to the SW_RFB_T + +* @return none +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS aaaFsmSendEventJoinComplete(WLAN_STATUS rJoinStatus, P_STA_RECORD_T prStaRec, P_SW_RFB_T prSwRfb) +{ + P_MSG_SAA_JOIN_COMP_T prJoinCompMsg; + + ASSERT(prStaRec); + + prJoinCompMsg = cnmMemAlloc(RAM_TYPE_TCM, sizeof(MSG_SAA_JOIN_COMP_T)); + if (!prJoinCompMsg) + return WLAN_STATUS_RESOURCES; + + if (IS_STA_IN_AIS(prStaRec)) + prJoinCompMsg->rMsgHdr.eMsgId = MID_SAA_AIS_JOIN_COMPLETE; + else if (IS_STA_IN_P2P(prStaRec)) + prJoinCompMsg->rMsgHdr.eMsgId = MID_SAA_P2P_JOIN_COMPLETE; + else if (IS_STA_IN_BOW(prStaRec)) + prJoinCompMsg->rMsgHdr.eMsgId = MID_SAA_BOW_JOIN_COMPLETE; + else + ASSERT(0); + + prJoinCompMsg->rJoinStatus = rJoinStatus; + prJoinCompMsg->prStaRec = prStaRec; + prJoinCompMsg->prSwRfb = prSwRfb; + + mboxSendMsg(MBOX_ID_0, (P_MSG_HDR_T) prJoinCompMsg, MSG_SEND_METHOD_BUF); + + return WLAN_STATUS_SUCCESS; + +} /* end of saaFsmSendEventJoinComplete() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Start Event to AAA FSM. +* +* @param[in] prMsgHdr Message of Join Request for a particular STA. +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID aaaFsmRunEventStart(IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_SAA_JOIN_REQ_T prJoinReqMsg; + P_STA_RECORD_T prStaRec; + P_AIS_BSS_INFO_T prAisBssInfo; + + ASSERT(prMsgHdr); + + prJoinReqMsg = (P_MSG_SAA_JOIN_REQ_T) prMsgHdr; + prStaRec = prJoinReqMsg->prStaRec; + + ASSERT(prStaRec); + + DBGLOG(SAA, LOUD, "EVENT-START: Trigger SAA FSM\n"); + + cnmMemFree(prMsgHdr); + + /* 4 <1> Validation of SAA Start Event */ + if (!IS_AP_STA(prStaRec->eStaType)) { + + DBGLOG(SAA, ERROR, "EVENT-START: STA Type - %d was not supported.\n", prStaRec->eStaType); + + /* Ignore the return value because don't care the prSwRfb */ + saaFsmSendEventJoinComplete(WLAN_STATUS_FAILURE, prStaRec, NULL); + + return; + } + /* 4 <2> The previous JOIN process is not completed ? */ + if (prStaRec->eAuthAssocState != AA_STATE_IDLE) { + DBGLOG(SAA, ERROR, "EVENT-START: Reentry of SAA Module.\n"); + prStaRec->eAuthAssocState = AA_STATE_IDLE; + } + /* 4 <3> Reset Status Code and Time */ + /* Update Station Record - Status/Reason Code */ + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + + /* Update the record join time. */ + GET_CURRENT_SYSTIME(&prStaRec->rLastJoinTime); + + prStaRec->ucTxAuthAssocRetryCount = 0; + + if (prStaRec->prChallengeText) { + cnmMemFree(prStaRec->prChallengeText); + prStaRec->prChallengeText = (P_IE_CHALLENGE_TEXT_T) NULL; + } + + cnmTimerStopTimer(&prStaRec->rTxReqDoneOrRxRespTimer); + + prStaRec->ucStaState = STA_STATE_1; + + /* Trigger SAA MODULE */ + saaFsmSteps(prStaRec, SAA_STATE_SEND_AUTH1, (P_SW_RFB_T) NULL); +} /* end of saaFsmRunEventStart() */ +#endif + +#if CFG_SUPPORT_AAA + +VOID aaaFsmRunEventTxReqTimeOut(IN P_ADAPTER_T prAdapter, IN ULONG plParamPtr) +{ + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) plParamPtr; + P_BSS_INFO_T prBssInfo; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + ASSERT(prStaRec); + if (!prStaRec) + return; + + DBGLOG(AAA, LOUD, "EVENT-TIMER: TX REQ TIMEOUT, Current Time = %d\n", kalGetTimeTick()); + + /* Trigger statistics log if Auth/Assoc Tx timeout */ + wlanTriggerStatsLog(prAdapter, prAdapter->rWifiVar.u4StatsLogDuration); + + switch (prStaRec->eAuthAssocState) { + case AAA_STATE_SEND_AUTH2: + DBGLOG(AAA, ERROR, + "LOST EVENT ,Auth Tx done disappear for (%d)Ms\n", + TU_TO_MSEC(TX_AUTHENTICATION_RESPONSE_TIMEOUT_TU)); + + prStaRec->eAuthAssocState = AA_STATE_IDLE; + + /* NOTE(Kevin): Change to STATE_1 */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + +#if CFG_ENABLE_WIFI_DIRECT + if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) + p2pRoleFsmRunEventAAATxFail(prAdapter, prStaRec, prBssInfo); +#endif /* CFG_ENABLE_WIFI_DIRECT */ + break; +#if 0 + /*state 2 to state 3 only check Assoc_req valid, no need for time out + *the fail case already handle at aaaFsmRunEventRxAssoc + */ + case AAA_STATE_SEND_ASSOC2: + DBGLOG(AAA, ERROR, + "LOST EVENT ,Assoc Tx done disappear for (%d)Ms\n", + TU_TO_MSEC(TX_AUTHENTICATION_RESPONSE_TIMEOUT_TU)); + + + prStaRec->eAuthAssocState = AAA_STATE_SEND_AUTH2; + + /* NOTE(Kevin): Change to STATE_2 */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + +#if CFG_ENABLE_WIFI_DIRECT + if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) + p2pRoleFsmRunEventAAATxFail(prAdapter, prStaRec, prBssInfo); +#endif /* CFG_ENABLE_WIFI_DIRECT */ + break; +#endif + + default: + return; + } + + +} /* end of saaFsmRunEventTxReqTimeOut() */ + + + + + +/*----------------------------------------------------------------------------*/ +/*! +* @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_BSS_INFO_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + UINT_16 u2StatusCode; + BOOLEAN fgReplyAuth = FALSE; + P_WLAN_AUTH_FRAME_T prAuthFrame = (P_WLAN_AUTH_FRAME_T) NULL; + + ASSERT(prAdapter); + + do { + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; + +#if CFG_ENABLE_WIFI_DIRECT + prBssInfo = p2pFuncBSSIDFindBssInfo(prAdapter, prAuthFrame->aucBSSID); + + /* 4 <1> Check P2P network conditions */ + + /* if (prBssInfo && prAdapter->fgIsP2PRegistered) */ + /* modify coding sytle to reduce indent */ + + if (!prAdapter->fgIsP2PRegistered) + goto bow_proc; + + if (prBssInfo && 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 (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + DBGLOG(AAA, TRACE, "process RxAuth status success\n"); + /* 4 <1.2> Validate Auth Frame for Network Specific Conditions */ + fgReplyAuth = p2pFuncValidateAuth(prAdapter, + prBssInfo, + prSwRfb, &prStaRec, &u2StatusCode); + +#if CFG_SUPPORT_802_11W + /* AP PMF, if PMF connection, ignore Rx auth */ + /* Certification 4.3.3.4 */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(AAA, INFO, "Drop RxAuth\n"); + return; + } +#endif + } else { + fgReplyAuth = TRUE; + } + break; + } + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +bow_proc: + + /* 4 <2> Check BOW network conditions */ +#if CFG_ENABLE_BT_OVER_WIFI + { + P_BOW_FSM_INFO_T prBowFsmInfo = (P_BOW_FSM_INFO_T) NULL; + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prBowFsmInfo->ucBssIndex); + + if ((prBssInfo->fgIsNetActive) && (prBssInfo->eCurrentOPMode == OP_MODE_BOW)) { + + /* 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 (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + + /* 4 <2.2> Validate Auth Frame for Network Specific Conditions */ + fgReplyAuth = + bowValidateAuth(prAdapter, prSwRfb, &prStaRec, &u2StatusCode); + + } else { + + fgReplyAuth = TRUE; + } + /* TODO(Kevin): Allocate a STA_RECORD_T for new client */ + break; + } + } + } +#endif /* CFG_ENABLE_BT_OVER_WIFI */ + + return; + } while (FALSE); + + if (prStaRec) { + /* update RCPI */ + ASSERT(prSwRfb->prRxStatusGroup3); + prStaRec->ucRCPI = nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0, prSwRfb); + } + /* 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); + } + if (prStaRec->eAuthAssocState + == AAA_STATE_SEND_AUTH2) + return; + + 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, prBssInfo->ucBssIndex, prSwRfb, AUTH_TRANSACTION_SEQ_2, u2StatusCode); + + + /*sta_rec might be removed when client list full, skip timer setting*/ + if (prStaRec && prStaRec->fgIsInUse == TRUE) { + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + /*ToDo:Init Timer to check get Auth Txdone avoid sta_rec not clear*/ + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, (PFN_MGMT_TIMEOUT_FUNC) + aaaFsmRunEventTxReqTimeOut, (ULONG) prStaRec); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC(TX_AUTHENTICATION_RESPONSE_TIMEOUT_TU)); + } + + + + } else if (prStaRec) + cnmStaRecFree(prAdapter, prStaRec); +} /* 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; + BOOLEAN fgSendSAQ = FALSE; + + ASSERT(prAdapter); + DBGLOG(AAA, INFO, "aaaFsmRunEventRxAssoc\n"); + + 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)) { + /* Not to reply association response with failure code due to lack of STA_REC */ + break; + } + + if (!IS_CLIENT_STA(prStaRec)) + break; + + DBGLOG(AAA, TRACE, "RxAssoc enter ucStaState:%d, eAuthassocState:%d\n", + prStaRec->ucStaState, prStaRec->eAuthAssocState); + + 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); + + /* Maybe Auth Response TX fail, but actually it success. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + } + + /* update RCPI */ + ASSERT(prSwRfb->prRxStatusGroup3); + prStaRec->ucRCPI = nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0, prSwRfb); + + /* 4 <2> Check P2P network conditions */ +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) { + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + 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 (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + /* 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_BOW_TYPE(prStaRec)) { + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + if ((prBssInfo->fgIsNetActive) && (prBssInfo->eCurrentOPMode == OP_MODE_BOW)) { + + /* 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 (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + + /* 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; + + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + + 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))) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + if (p2pRoleFsmRunEventAAAComplete(prAdapter, prStaRec, prBssInfo) == + WLAN_STATUS_SUCCESS) { + prStaRec->u2AssocId = bssAssignAssocID(prStaRec); + /* prStaRec->eAuthAssocState = AA_STATE_IDLE; */ + /* NOTE(Kevin): for TX done */ + prStaRec->eAuthAssocState = AAA_STATE_SEND_ASSOC2; + /* NOTE(Kevin): Method A: Change to STATE_3 before handle TX Done */ + /* cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); */ + } else { + /* Client List FULL. */ + u2StatusCode = STATUS_CODE_REQ_DECLINED; + + prStaRec->u2AssocId = 0; /* Invalid Association ID */ + + /* If(Re)association fail,remove sta record and use class error to handle sta */ + prStaRec->eAuthAssocState = AA_STATE_IDLE; + + /* 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_BOW_TYPE(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); */ + } +#endif + } else { + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + /* don't change state, just send assoc resp (NO need TX done, TIE + code30) and then SAQ */ + if (u2StatusCode == STATUS_CODE_ASSOC_REJECTED_TEMPORARILY) { + DBGLOG(AAA, INFO, "AP send SAQ\n"); + fgSendSAQ = TRUE; + } else +#endif + { + prStaRec->u2AssocId = 0; /* Invalid Association ID */ + + /* If (Re)association fail, remove sta record and use class error to handle sta */ + prStaRec->eAuthAssocState = AA_STATE_IDLE; + /* Remove from client list if it was previously associated */ + if ((prStaRec->ucStaState > STA_STATE_1) && prAdapter->fgIsP2PRegistered + && (IS_STA_IN_P2P(prStaRec))) { + P_BSS_INFO_T prBssInfo = NULL; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + if (prBssInfo) { + DBGLOG(AAA, INFO, "Remove client!\n"); + bssRemoveClient(prAdapter, prBssInfo, prStaRec); + } + } + /* 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); + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if (fgSendSAQ) { + /* if PMF connection, and return code 30, send SAQ */ + rsnApStartSaQuery(prAdapter, prStaRec); + } +#endif + + } + + 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 = %d\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->ucBssIndex <= MAX_BSS_INDEX); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + DBGLOG(AAA, LOUD, "TxDone ucStaState:%d, eAuthAssocState:%d\n", + prStaRec->ucStaState, prStaRec->eAuthAssocState); + + /* Trigger statistics log if Auth/Assoc Tx failed */ + if (rTxDoneStatus != TX_RESULT_SUCCESS) + wlanTriggerStatsLog(prAdapter, prAdapter->rWifiVar.u4StatsLogDuration); + + 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; + + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + + if (prStaRec->u2StatusCode == STATUS_CODE_SUCCESSFUL) { + if (rTxDoneStatus == TX_RESULT_SUCCESS) { + + /* NOTE(Kevin): Change to STATE_2 at TX Done */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + /* Error handle if can not complete the ASSOC flow */ + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC(TX_ASSOCIATE_TIMEOUT_TU)); + } else { + + prStaRec->eAuthAssocState = AA_STATE_IDLE; + + /* NOTE(Kevin): Change to STATE_1 */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + +#if CFG_ENABLE_WIFI_DIRECT + if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) + p2pRoleFsmRunEventAAATxFail(prAdapter, prStaRec, prBssInfo); +#endif /* CFG_ENABLE_WIFI_DIRECT */ +#if CFG_ENABLE_BT_OVER_WIFI + if (IS_STA_BOW_TYPE(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 (prStaRec->u2StatusCode == STATUS_CODE_SUCCESSFUL) { + if (rTxDoneStatus == TX_RESULT_SUCCESS) { + + prStaRec->eAuthAssocState = AA_STATE_IDLE; + + /* NOTE(Kevin): Change to STATE_3 at TX Done */ +#if CFG_ENABLE_WIFI_DIRECT + if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) + p2pRoleFsmRunEventAAASuccess(prAdapter, prStaRec, prBssInfo); +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +#if CFG_ENABLE_BT_OVER_WIFI + + if (IS_STA_BOW_TYPE(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 (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) + p2pRoleFsmRunEventAAATxFail(prAdapter, prStaRec, prBssInfo); +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +#if CFG_ENABLE_BT_OVER_WIFI + if (IS_STA_BOW_TYPE(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 AA_STATE_IDLE: + /* 2013-08-27 frog: Do nothing. + * Somtimes we may send Assoc Resp twice. (Rx Assoc Req before the first Assoc TX Done) + * The AssocState is changed to IDLE after first TX done. + * Free station record when IDLE is seriously wrong. + */ + /* 2017-01-12 Do nothing only when STA is in state 3 */ + /* Free the StaRec if found any unexpected status */ + if (prStaRec->ucStaState != STA_STATE_3) + cnmStaRecFree(prAdapter, prStaRec); + break; + + default: + break; /* Ignore other cases */ + } + + DBGLOG(AAA, LOUD, "TxDone end ucStaState:%d, eAuthAssocState:%d\n", + prStaRec->ucStaState, prStaRec->eAuthAssocState); + + return WLAN_STATUS_SUCCESS; + +} /* end of aaaFsmRunEventTxDone() */ +#endif /* CFG_SUPPORT_AAA */ + +#if 0 /* TODO(Kevin): for abort event, just reset the STA_RECORD_T. */ +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will send ABORT Event to JOIN FSM. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID saaFsmRunEventAbort(IN P_MSG_HDR_T prMsgHdr) +{ + P_JOIN_INFO_T prJoinInfo; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("joinFsmRunEventAbort"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + + DBGLOG(JOIN, EVENT, "JOIN EVENT: ABORT\n"); + + /* NOTE(Kevin): when reach here, the ARB_STATE should be in ARB_STATE_JOIN. */ + ASSERT(prJoinInfo->prBssDesc); + + /* 4 <1> Update Flags and Elements of JOIN Module. */ + /* Reset Send Auth/(Re)Assoc Frame Count */ + prJoinInfo->ucTxAuthAssocRetryCount = 0; + + /* Cancel all JOIN relative Timer */ + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rTxRequestTimer); + + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rRxResponseTimer); + + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rJoinTimer); + + /* 4 <2> Update the associated STA_RECORD_T during JOIN. */ + /* Get a Station Record if possible, TA == BSSID for AP */ + prStaRec = staRecGetStaRecordByAddr(prAdapter, prJoinInfo->prBssDesc->aucBSSID); + if (prStaRec) + prStaRec->ucStaState = STA_STATE_1; /* Update Station Record - Class 1 Flag */ +#if DBG + else + ASSERT(0); /* Shouldn't happened, because we already add this STA_RECORD_T at JOIN_STATE_INIT */ + +#endif /* DBG */ + + /* 4 <3> Pull back to IDLE. */ + joinFsmSteps(prAdapter, JOIN_STATE_IDLE); + + /* 4 <4> If we are in Roaming, recover the settings of previous BSS. */ + /* NOTE: JOIN FAIL - + * Restore original setting from current BSS_INFO_T. + */ + if (prAdapter->eConnectionState == MEDIA_STATE_CONNECTED) + joinAdoptParametersFromCurrentBss(prAdapter); +} /* end of joinFsmRunEventAbort() */ +#endif + +/* TODO(Kevin): following code will be modified and move to AIS FSM */ +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will send Join Timeout Event to JOIN FSM. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \retval WLAN_STATUS_FAILURE Fail because of Join Timeout +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS joinFsmRunEventJoinTimeOut(IN P_ADAPTER_T prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("joinFsmRunEventJoinTimeOut"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + + DBGLOG(JOIN, EVENT, "JOIN EVENT: JOIN TIMEOUT\n"); + + /* Get a Station Record if possible, TA == BSSID for AP */ + prStaRec = staRecGetStaRecordByAddr(prAdapter, prJoinInfo->prBssDesc->aucBSSID); + + /* We have renew this Sta Record when in JOIN_STATE_INIT */ + ASSERT(prStaRec); + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_JOIN_TIMEOUT; + + /* Increase Failure Count */ + prStaRec->ucJoinFailureCount++; + + /* Reset Send Auth/(Re)Assoc Frame Count */ + prJoinInfo->ucTxAuthAssocRetryCount = 0; + + /* Cancel other JOIN relative Timer */ + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rTxRequestTimer); + + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rRxResponseTimer); + + /* Restore original setting from current BSS_INFO_T */ + if (prAdapter->eConnectionState == MEDIA_STATE_CONNECTED) + joinAdoptParametersFromCurrentBss(prAdapter); + + /* Pull back to IDLE */ + joinFsmSteps(prAdapter, JOIN_STATE_IDLE); + + return WLAN_STATUS_FAILURE; + +} /* end of joinFsmRunEventJoinTimeOut() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will adopt the parameters from Peer BSS. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID joinAdoptParametersFromPeerBss(IN P_ADAPTER_T prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + P_BSS_DESC_T prBssDesc; + + DEBUGFUNC("joinAdoptParametersFromPeerBss"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + prBssDesc = prJoinInfo->prBssDesc; + + /* 4 <1> Adopt Peer BSS' PHY TYPE */ + prAdapter->eCurrentPhyType = prBssDesc->ePhyType; + + DBGLOG(JOIN, INFO, "Target BSS[%s]'s PhyType = %s\n", + prBssDesc->aucSSID, (prBssDesc->ePhyType == PHY_TYPE_ERP_INDEX) ? "ERP" : "HR_DSSS"); + + /* 4 <2> Adopt Peer BSS' Frequency(Band/Channel) */ + DBGLOG(JOIN, INFO, "Target BSS's Channel = %d, Band = %d\n", prBssDesc->ucChannelNum, prBssDesc->eBand); + + nicSwitchChannel(prAdapter, prBssDesc->eBand, prBssDesc->ucChannelNum, 10); + + prJoinInfo->fgIsParameterAdopted = TRUE; +} /* end of joinAdoptParametersFromPeerBss() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will adopt the parameters from current associated BSS. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID joinAdoptParametersFromCurrentBss(IN P_ADAPTER_T prAdapter) +{ + /* P_JOIN_INFO_T prJoinInfo = &prAdapter->rJoinInfo; */ + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + prBssInfo = &prAdapter->rBssInfo; + + /* 4 <1> Adopt current BSS' PHY TYPE */ + prAdapter->eCurrentPhyType = prBssInfo->ePhyType; + + /* 4 <2> Adopt current BSS' Frequency(Band/Channel) */ + DBGLOG(JOIN, INFO, "Current BSS's Channel = %d, Band = %d\n", prBssInfo->ucChnl, prBssInfo->eBand); + + nicSwitchChannel(prAdapter, prBssInfo->eBand, prBssInfo->ucChnl, 10); +} /* end of joinAdoptParametersFromCurrentBss() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will update all the SW variables and HW MCR registers after +* the association with target BSS. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID joinComplete(IN P_ADAPTER_T prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + P_BSS_DESC_T prBssDesc; + P_PEER_BSS_INFO_T prPeerBssInfo; + P_BSS_INFO_T prBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_STA_RECORD_T prStaRec; + P_TX_CTRL_T prTxCtrl; +#if CFG_SUPPORT_802_11D + P_IE_COUNTRY_T prIECountry; +#endif + + DEBUGFUNC("joinComplete"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + prBssDesc = prJoinInfo->prBssDesc; + prPeerBssInfo = &prAdapter->rPeerBssInfo; + prBssInfo = &prAdapter->rBssInfo; + prConnSettings = &prAdapter->rConnSettings; + prTxCtrl = &prAdapter->rTxCtrl; + +/* 4 <1> Update Connecting & Connected Flag of BSS_DESC_T. */ + /* Remove previous AP's Connection Flags if have */ + scanRemoveConnectionFlagOfBssDescByBssid(prAdapter, prBssInfo->aucBSSID); + + prBssDesc->fgIsConnected = TRUE; /* Mask as Connected */ + + if (prBssDesc->fgIsHiddenSSID) { + /* NOTE(Kevin): This is for the case of Passive Scan and the target BSS didn't + * broadcast SSID on its Beacon Frame. + */ + COPY_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, prAdapter->rConnSettings.aucSSID, prAdapter->rConnSettings.ucSSIDLen); + + if (prBssDesc->ucSSIDLen) + prBssDesc->fgIsHiddenSSID = FALSE; + +#if DBG + else + ASSERT(0); + +#endif /* DBG */ + + DBGLOG(JOIN, INFO, "Hidden SSID! - Update SSID : %s\n", prBssDesc->aucSSID); + } + +/* 4 <2> Update BSS_INFO_T from BSS_DESC_T */ + /* 4 <2.A> PHY Type */ + prBssInfo->ePhyType = prBssDesc->ePhyType; + + /* 4 <2.B> BSS Type */ + prBssInfo->eBSSType = BSS_TYPE_INFRASTRUCTURE; + + /* 4 <2.C> BSSID */ + COPY_MAC_ADDR(prBssInfo->aucBSSID, prBssDesc->aucBSSID); + + DBGLOG(JOIN, INFO, "JOIN to BSSID: [" 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 Information */ + if (prAdapter->fgIsEnableWMM && (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_SUPPORT_WMM)) { + + prBssInfo->fgIsWmmAssoc = TRUE; + prTxCtrl->rTxQForVoipAccess = TXQ_AC3; + + qosWmmInfoInit(&prBssInfo->rWmmInfo, (prBssInfo->ePhyType == PHY_TYPE_HR_DSSS_INDEX) ? TRUE : FALSE); + + if (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_AC_PARAM_PRESENT) { + kalMemCopy(&prBssInfo->rWmmInfo, &prPeerBssInfo->rWmmInfo, sizeof(WMM_INFO_T)); + } else { + kalMemCopy(&prBssInfo->rWmmInfo, + &prPeerBssInfo->rWmmInfo, + sizeof(WMM_INFO_T) - sizeof(prPeerBssInfo->rWmmInfo.arWmmAcParams)); + } + } else { + prBssInfo->fgIsWmmAssoc = FALSE; + prTxCtrl->rTxQForVoipAccess = TXQ_AC1; + + kalMemZero(&prBssInfo->rWmmInfo, sizeof(WMM_INFO_T)); + } + + /* 4 <3.C> Operational Rate Set & BSS Basic Rate Set */ + prBssInfo->u2OperationalRateSet = prPeerBssInfo->u2OperationalRateSet; + prBssInfo->u2BSSBasicRateSet = prPeerBssInfo->u2BSSBasicRateSet; + + /* 4 <3.D> Short Preamble */ + if (prBssInfo->fgIsERPPresent) { + + /* NOTE(Kevin 2007/12/24): Truth Table. + * Short Preamble Bit in + * Final Driver Setting(Short) + * TRUE FALSE FALSE FALSE(shouldn't have such case, + * use the AssocResp) + * TRUE FALSE TRUE FALSE + * FALSE FALSE FALSE FALSE(shouldn't have such case, + * use the AssocResp) + * FALSE FALSE TRUE FALSE + * TRUE TRUE FALSE TRUE(follow ERP) + * TRUE TRUE TRUE FALSE(follow ERP) + * FALSE TRUE FALSE FALSE(shouldn't have such case, + * and we should set to FALSE) + * FALSE TRUE TRUE FALSE(we should set to FALSE) + */ + if ((prPeerBssInfo->fgIsShortPreambleAllowed) && + ((prConnSettings->ePreambleType == PREAMBLE_TYPE_SHORT) || + /* Short Preamble Option Enable is TRUE */ + ((prConnSettings->ePreambleType == PREAMBLE_TYPE_AUTO) + && (prBssDesc->u2CapInfo & CAP_INFO_SHORT_PREAMBLE)))) { + + prBssInfo->fgIsShortPreambleAllowed = TRUE; + + if (prBssInfo->ucERP & ERP_INFO_BARKER_PREAMBLE_MODE) + prBssInfo->fgUseShortPreamble = FALSE; + else + prBssInfo->fgUseShortPreamble = TRUE; + + } else { + prBssInfo->fgIsShortPreambleAllowed = FALSE; + prBssInfo->fgUseShortPreamble = FALSE; + } + } else { + /* NOTE(Kevin 2007/12/24): Truth Table. + * Short Preamble Bit in + * Final Driver Setting(Short) + * TRUE FALSE FALSE + * FALSE FALSE FALSE + * TRUE TRUE TRUE + * FALSE TRUE(status success) TRUE + * --> Honor the result of prPeerBssInfo. + */ + + prBssInfo->fgIsShortPreambleAllowed = prBssInfo->fgUseShortPreamble = + prPeerBssInfo->fgIsShortPreambleAllowed; + } + + DBGLOG(JOIN, INFO, + "prBssInfo->fgIsShortPreambleAllowed = %d, prBssInfo->fgUseShortPreamble = %d\n", + prBssInfo->fgIsShortPreambleAllowed, prBssInfo->fgUseShortPreamble); + + /* 4 <3.E> Short Slot Time */ + prBssInfo->fgUseShortSlotTime = prPeerBssInfo->fgUseShortSlotTime; /* AP support Short Slot Time */ + + DBGLOG(JOIN, INFO, "prBssInfo->fgUseShortSlotTime = %d\n", prBssInfo->fgUseShortSlotTime); + + nicSetSlotTime(prAdapter, + prBssInfo->ePhyType, + ((prConnSettings->fgIsShortSlotTimeOptionEnable && + prBssInfo->fgUseShortSlotTime) ? TRUE : FALSE)); + + /* 4 <3.F> Update Tx Rate for Control Frame */ + bssUpdateTxRateForControlFrame(prAdapter); + + /* 4 <3.G> Save the available Auth Types during Roaming (Design for Fast BSS Transition). */ + /* if (prAdapter->fgIsEnableRoaming) *//* NOTE(Kevin): Always prepare info for roaming */ + { + + if (prJoinInfo->ucCurrAuthAlgNum == AUTH_ALGORITHM_NUM_OPEN_SYSTEM) + prJoinInfo->ucRoamingAuthTypes |= AUTH_TYPE_OPEN_SYSTEM; + else if (prJoinInfo->ucCurrAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY) + prJoinInfo->ucRoamingAuthTypes |= AUTH_TYPE_SHARED_KEY; + + prBssInfo->ucRoamingAuthTypes = prJoinInfo->ucRoamingAuthTypes; + + /* Set the stable time of the associated BSS. We won't do roaming decision + * during the stable time. + */ + SET_EXPIRATION_TIME(prBssInfo->rRoamingStableExpirationTime, + SEC_TO_SYSTIME(ROAMING_STABLE_TIMEOUT_SEC)); + } + + /* 4 <3.H> Update Parameter for TX Fragmentation Threshold */ +#if CFG_TX_FRAGMENT + txFragInfoUpdate(prAdapter); +#endif /* CFG_TX_FRAGMENT */ + +/* 4 <4> Update STA_RECORD_T */ + /* Get a Station Record if possible */ + prStaRec = staRecGetStaRecordByAddr(prAdapter, prBssDesc->aucBSSID); + + if (prStaRec) { + UINT_16 u2OperationalRateSet, u2DesiredRateSet; + + /* 4 <4.A> Desired Rate Set */ + u2OperationalRateSet = (rPhyAttributes[prBssInfo->ePhyType].u2SupportedRateSet & + prBssInfo->u2OperationalRateSet); + + u2DesiredRateSet = (u2OperationalRateSet & prConnSettings->u2DesiredRateSet); + if (u2DesiredRateSet) { + prStaRec->u2DesiredRateSet = u2DesiredRateSet; + } else { + /* For Error Handling - The Desired Rate Set is not covered in Operational Rate Set. */ + prStaRec->u2DesiredRateSet = u2OperationalRateSet; + } + + /* Try to set the best initial rate for this entry */ + if (!rateGetBestInitialRateIndex(prStaRec->u2DesiredRateSet, + prStaRec->rRcpi, &prStaRec->ucCurrRate1Index)) { + + if (!rateGetLowestRateIndexFromRateSet(prStaRec->u2DesiredRateSet, &prStaRec->ucCurrRate1Index)) + ASSERT(0); + } + + DBGLOG(JOIN, INFO, "prStaRec->ucCurrRate1Index = %d\n", prStaRec->ucCurrRate1Index); + + /* 4 <4.B> Preamble Mode */ + prStaRec->fgIsShortPreambleOptionEnable = prBssInfo->fgUseShortPreamble; + + /* 4 <4.C> QoS Flag */ + prStaRec->fgIsQoS = prBssInfo->fgIsWmmAssoc; + } +#if DBG + else + ASSERT(0); + +#endif /* DBG */ + +/* 4 <5> Update NIC */ + /* 4 <5.A> Update BSSID & Operation Mode */ + nicSetupBSS(prAdapter, prBssInfo); + + /* 4 <5.B> Update WLAN Table. */ + if (nicSetHwBySta(prAdapter, prStaRec) == FALSE) + ASSERT(FALSE); + + /* 4 <5.C> Update Desired Rate Set for BT. */ +#if CFG_TX_FRAGMENT + if (prConnSettings->fgIsEnableTxAutoFragmentForBT) + txRateSetInitForBT(prAdapter, prStaRec); + +#endif /* CFG_TX_FRAGMENT */ + + /* 4 <5.D> TX AC Parameter and TX/RX Queue Control */ + if (prBssInfo->fgIsWmmAssoc) { + +#if CFG_TX_AGGREGATE_HW_FIFO + nicTxAggregateTXQ(prAdapter, FALSE); +#endif /* CFG_TX_AGGREGATE_HW_FIFO */ + + qosUpdateWMMParametersAndAssignAllowedACI(prAdapter, &prBssInfo->rWmmInfo); + } else { + +#if CFG_TX_AGGREGATE_HW_FIFO + nicTxAggregateTXQ(prAdapter, TRUE); +#endif /* CFG_TX_AGGREGATE_HW_FIFO */ + + nicTxNonQoSAssignDefaultAdmittedTXQ(prAdapter); + + nicTxNonQoSUpdateTXQParameters(prAdapter, prBssInfo->ePhyType); + } + +#if CFG_TX_STOP_WRITE_TX_FIFO_UNTIL_JOIN + { + prTxCtrl->fgBlockTxDuringJoin = FALSE; + +#if !CFG_TX_AGGREGATE_HW_FIFO /* TX FIFO AGGREGATE already do flush once */ + nicTxFlushStopQueues(prAdapter, (UINT_8) TXQ_DATA_MASK, (UINT_8) NULL); +#endif /* CFG_TX_AGGREGATE_HW_FIFO */ + + nicTxRetransmitOfSendWaitQue(prAdapter); + + if (prTxCtrl->fgIsPacketInOsSendQueue) + nicTxRetransmitOfOsSendQue(prAdapter); + +#if CFG_SDIO_TX_ENHANCE + halTxLeftClusteredMpdu(prAdapter); +#endif /* CFG_SDIO_TX_ENHANCE */ + + } +#endif /* CFG_TX_STOP_WRITE_TX_FIFO_UNTIL_JOIN */ + +/* 4 <6> Setup CONNECTION flag. */ + prAdapter->eConnectionState = MEDIA_STATE_CONNECTED; + prAdapter->eConnectionStateIndicated = MEDIA_STATE_CONNECTED; + + if (prJoinInfo->fgIsReAssoc) + prAdapter->fgBypassPortCtrlForRoaming = TRUE; + else + prAdapter->fgBypassPortCtrlForRoaming = FALSE; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_CONNECT, (PVOID) NULL, 0); +} /* end of joinComplete() */ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/ais_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/ais_fsm.c new file mode 100644 index 0000000000000..a79a01b2fa752 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/ais_fsm.c @@ -0,0 +1,4833 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/ais_fsm.c#4 +*/ + +/*! \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. +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define AIS_ROAMING_CONNECTION_TRIAL_LIMIT 2 +#define AIS_JOIN_TIMEOUT 7 + +#define AIS_FSM_STATE_SEARCH_ACTION_PHASE_0 0 +#define AIS_FSM_STATE_SEARCH_ACTION_PHASE_1 1 +#define AIS_FSM_STATE_SEARCH_ACTION_PHASE_2 2 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +#if CFG_DISCONN_DEBUG_FEATURE +struct AIS_DISCONN_INFO_T g_rDisconnInfoTemp; +UINT_8 g_DisconnInfoIdx; +struct AIS_DISCONN_INFO_T *g_prDisconnInfo; +#endif + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static PUINT_8 apucDebugAisState[AIS_STATE_NUM] = { + (PUINT_8) DISP_STRING("IDLE"), + (PUINT_8) DISP_STRING("SEARCH"), + (PUINT_8) DISP_STRING("SCAN"), + (PUINT_8) DISP_STRING("ONLINE_SCAN"), + (PUINT_8) DISP_STRING("LOOKING_FOR"), + (PUINT_8) DISP_STRING("WAIT_FOR_NEXT_SCAN"), + (PUINT_8) DISP_STRING("REQ_CHANNEL_JOIN"), + (PUINT_8) DISP_STRING("JOIN"), + (PUINT_8) DISP_STRING("JOIN_FAILURE"), + (PUINT_8) DISP_STRING("IBSS_ALONE"), + (PUINT_8) DISP_STRING("IBSS_MERGE"), + (PUINT_8) DISP_STRING("NORMAL_TR"), + (PUINT_8) DISP_STRING("DISCONNECTING"), + (PUINT_8) DISP_STRING("REQ_REMAIN_ON_CHANNEL"), + (PUINT_8) DISP_STRING("REMAIN_ON_CHANNEL") +}; + +/******************************************************************************* +* M A 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 aisFsmRunEventScanDoneTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParam); +static VOID aisRemoveDisappearedBlacklist(P_ADAPTER_T prAdapter); + +/******************************************************************************* +* 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, prAdapter->prAisBssInfo->ucBssIndex); + + /* Features */ + prConnSettings->fgIsEnableRoaming = FALSE; +#if CFG_SUPPORT_ROAMING +#if 0 + if (prRegInfo) + prConnSettings->fgIsEnableRoaming = ((prRegInfo->fgDisRoaming > 0) ? (FALSE) : (TRUE)); +#else + if (prAdapter->rWifiVar.fgDisRoaming) + prConnSettings->fgIsEnableRoaming = FALSE; + else + prConnSettings->fgIsEnableRoaming = TRUE; +#endif +#endif /* CFG_SUPPORT_ROAMING */ + + prConnSettings->fgIsAdHocQoSEnable = FALSE; + +#if CFG_SUPPORT_802_11AC + prConnSettings->eDesiredPhyConfig = PHY_CONFIG_802_11ABGNAC; +#else + prConnSettings->eDesiredPhyConfig = PHY_CONFIG_802_11ABGN; +#endif + + /* 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.u4GroupMgmtKeyCipherSuite = 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; + prConnSettings->rRsnInfo.u2PmkidCnt = 0; + kalMemZero(prConnSettings->rRsnInfo.aucPmkidList, + (sizeof(UINT_8) * MAX_NUM_SUPPORTED_PMKID * RSN_PMKID_LEN)); +#if CFG_SUPPORT_CFG80211_AUTH + prConnSettings->bss = NULL; +#endif +#if CFG_SUPPORT_OWE + kalMemSet(&prConnSettings->rOweInfo, 0, sizeof(struct OWE_INFO_T)); +#endif +} /* 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; + UINT_8 i; + + DEBUGFUNC("aisFsmInit()"); + DBGLOG(SW1, INFO, "->aisFsmInit()\n"); + + prAdapter->prAisBssInfo = prAisBssInfo = cnmGetBssInfoAndInit(prAdapter, NETWORK_TYPE_AIS, FALSE); + ASSERT(prAisBssInfo); + + /* update MAC address */ + COPY_MAC_ADDR(prAdapter->prAisBssInfo->aucOwnMacAddr, prAdapter->rMyMacAddr); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisSpecificBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); + + /* 4 <1> Initiate FSM */ + prAisFsmInfo->ePreviousState = AIS_STATE_IDLE; + prAisFsmInfo->eCurrentState = AIS_STATE_IDLE; + + prAisFsmInfo->ucAvailableAuthTypes = 0; + + prAisFsmInfo->prTargetBssDesc = (P_BSS_DESC_T) NULL; + + prAisFsmInfo->ucSeqNumOfReqMsg = 0; + prAisFsmInfo->ucSeqNumOfChReq = 0; + prAisFsmInfo->ucSeqNumOfScanReq = 0; + + prAisFsmInfo->fgIsInfraChannelFinished = TRUE; +#if CFG_SUPPORT_ROAMING + prAisFsmInfo->fgIsRoamingScanPending = FALSE; +#endif /* CFG_SUPPORT_ROAMING */ + prAisFsmInfo->fgIsChannelRequested = FALSE; + prAisFsmInfo->fgIsChannelGranted = FALSE; + + /* 4 <1.1> Initiate FSM - Timer INIT */ + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rBGScanTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventBGSleepTimeOut, (ULONG) NULL); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rIbssAloneTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventIbssAloneTimeOut, (ULONG) NULL); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rIndicationOfDisconnectTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisPostponedEventOfDisconnTimeout, (ULONG) NULL); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rScanDoneTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventScanDoneTimeOut, (ULONG) NULL); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rJoinTimeoutTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventJoinTimeout, (ULONG) NULL); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rDeauthDoneTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventDeauthTimeout, (ULONG) NULL); + + /* 4 <1.2> Initiate PWR STATE */ + SET_NET_PWR_STATE_IDLE(prAdapter, prAisBssInfo->ucBssIndex); + + /* 4 <2> Initiate BSS_INFO_T - common part */ + BSS_INFO_INIT(prAdapter, prAisBssInfo); + 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; + prAisBssInfo->ucNss = wlanGetSupportNss(prAdapter, prAisBssInfo->ucBssIndex); + prAisBssInfo->eDBDCBand = ENUM_BAND_0; +#if (CFG_HW_WMM_BY_BSS == 0) + prAisBssInfo->ucWmmQueSet = + (prAdapter->rWifiVar.ucDbdcMode == DBDC_MODE_DISABLED) ? DBDC_5G_WMM_INDEX : DBDC_2G_WMM_INDEX; +#endif + /* 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); + } + + prAisBssInfo->ucBMCWlanIndex = WTBL_RESERVED_ENTRY; + + for (i = 0; i < MAX_KEY_NUM; i++) { + prAisBssInfo->ucBMCWlanIndexS[i] = WTBL_RESERVED_ENTRY; + prAisBssInfo->ucBMCWlanIndexSUsed[i] = FALSE; + prAisBssInfo->wepkeyUsed[i] = FALSE; + } +#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); + LINK_MGMT_INIT(&prAdapter->rWifiVar.rConnSettings.rBlackList); + + /* DBGPRINTF("[2] ucBmpDeliveryAC:0x%x, ucBmpTriggerAC:0x%x, ucUapsdSp:0x%x", */ + /* prAisBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC, */ + /* prAisBssInfo->rPmProfSetupInfo.ucBmpTriggerAC, */ + /* prAisBssInfo->rPmProfSetupInfo.ucUapsdSp); */ + + /* Bind NetDev & BssInfo */ + /* wlanBindBssIdxToNetInterface(prAdapter->prGlueInfo, NET_DEV_WLAN_IDX, prAisBssInfo->ucBssIndex); */ + +#if CFG_DISCONN_DEBUG_FEATURE + g_prDisconnInfo = (struct AIS_DISCONN_INFO_T *)kalMemAlloc( + sizeof(struct AIS_DISCONN_INFO_T) * MAX_DISCONNECT_RECORD, + VIR_MEM_TYPE); + if (g_prDisconnInfo != NULL) { + kalMemZero(g_prDisconnInfo, + sizeof(struct AIS_DISCONN_INFO_T) * + MAX_DISCONNECT_RECORD); + } else { + DBGLOG(AIS, ERROR, + "allocate memory for g_prDisconnInfo failed!\n"); + } + g_DisconnInfoIdx = 0; + + /* default value */ + kalMemZero(&g_rDisconnInfoTemp, sizeof(struct AIS_DISCONN_INFO_T)); + g_rDisconnInfoTemp.ucBcnTimeoutReason = BEACON_TIMEOUT_DUE_2_RESERVED; + g_rDisconnInfoTemp.u2DisassocSeqNum = 0xFFFF; +#endif + +} /* 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; + + DEBUGFUNC("aisFsmUninit()"); + DBGLOG(SW1, INFO, "->aisFsmUninit()\n"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = prAdapter->prAisBssInfo; + + /* 4 <1> Stop all timers */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rBGScanTimer); + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rIbssAloneTimer); + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rIndicationOfDisconnectTimer); + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rJoinTimeoutTimer); + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); + + /* 4 <2> flush pending request */ + aisFsmFlushRequest(prAdapter); + + /* 4 <3> Reset driver-domain BSS-INFO */ + if (prAisBssInfo) { + + if (prAisBssInfo->prBeacon) { + cnmMgtPktFree(prAdapter, prAisBssInfo->prBeacon); + prAisBssInfo->prBeacon = NULL; + } + + cnmFreeBssInfo(prAdapter, prAisBssInfo); + prAdapter->prAisBssInfo = NULL; + } + +#if CFG_SUPPORT_802_11W + rsnStopSaQuery(prAdapter); +#endif + +#if CFG_DISCONN_DEBUG_FEATURE + if (g_prDisconnInfo != NULL) { + kalMemFree(g_prDisconnInfo, + VIR_MEM_TYPE, + sizeof(struct AIS_DISCONN_INFO_T) * + MAX_DISCONNECT_RECORD); + g_prDisconnInfo = NULL; + } +#endif + LINK_MGMT_UNINIT(&prAdapter->rWifiVar.rConnSettings.rBlackList, struct +AIS_BLACKLIST_ITEM, VIR_MEM_TYPE); +} /* 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->prAisBssInfo; + 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, prAdapter->prAisBssInfo->ucBssIndex, prBssDesc); + if (!prStaRec) { + DBGLOG(AIS, ERROR, "prStaRec is NULL!\n"); + return; + } + + prAisFsmInfo->prTargetStaRec = prStaRec; + + /* 4 <2.1> sync. to firmware domain */ + if (prStaRec->ucStaState == STA_STATE_1) + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + /* 4 <3> Update ucAvailableAuthTypes which we can choice during SAA */ + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { + + prStaRec->fgIsReAssoc = FALSE; + + /*Fill Auth Type */ +#if CFG_SUPPORT_CFG80211_AUTH + prAisFsmInfo->ucAvailableAuthTypes = + (UINT_8) prAdapter->prGlueInfo->rWpaInfo.u4AuthAlg; + DBGLOG(AIS, INFO, "JOIN INIT: Auth Algorithm :%d\n", + prAisFsmInfo->ucAvailableAuthTypes); +#else + 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; + } +#endif + /* TODO(tyhsu): Assume that Roaming Auth Type is equal to ConnSettings eAuthMode */ + prAisSpecificBssInfo->ucRoamingAuthTypes = prAisFsmInfo->ucAvailableAuthTypes; + + prStaRec->ucTxAuthAssocRetryLimit = TX_AUTH_ASSOCI_RETRY_LIMIT; + + /* Update Bss info before join */ + prAisBssInfo->eBand = prBssDesc->eBand; + prAisBssInfo->ucPrimaryChannel = prBssDesc->ucChannelNum; + + } 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; +#if CFG_SUPPORT_SAE + } else if (prAisFsmInfo->ucAvailableAuthTypes & + (UINT_8) AUTH_TYPE_SAE) { + DBGLOG(AIS, LOUD, + "JOIN INIT: Try to do Authentication with AuthType == SAE.\n"); + + prAisFsmInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_SAE; + + prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_SAE; +#endif + } else { + ASSERT(0); + } + + /* 4 <5> Overwrite Connection Setting for eConnectionPolicy == ANY (Used by Assoc Req) */ + if (prBssDesc->ucSSIDLen) + COPY_SSID(prConnSettings->aucSSID, prConnSettings->ucSSIDLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + /* 4 <6> Send a Msg to trigger SAA to start JOIN process. */ + prJoinReqMsg = (P_MSG_JOIN_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_REQ_T)); + if (!prJoinReqMsg) { + + ASSERT(0); /* Can't trigger SAA FSM */ + return; + } + + prJoinReqMsg->rMsgHdr.eMsgId = MID_AIS_SAA_FSM_START; + prJoinReqMsg->ucSeqNum = ++prAisFsmInfo->ucSeqNumOfReqMsg; + prJoinReqMsg->prStaRec = prStaRec; + + if (1) { + int j; + P_FRAG_INFO_T prFragInfo; + + for (j = 0; j < MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS; j++) { + prFragInfo = &prStaRec->rFragInfo[j]; + + if (prFragInfo->pr1stFrag) { + /* nicRxReturnRFB(prAdapter, prFragInfo->pr1stFrag); */ + prFragInfo->pr1stFrag = (P_SW_RFB_T) NULL; + } + } + } +#if CFG_SUPPORT_CFG80211_AUTH + prConnSettings->fgIsConnInitialized = TRUE; +#endif + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinReqMsg, MSG_SEND_METHOD_BUF); +} /* end of aisFsmInit_JOIN() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Retry JOIN for AUTH_MODE_AUTO_SWITCH +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @retval TRUE We will retry JOIN +* @retval FALSE We will not retry JOIN +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN aisFsmStateInit_RetryJOIN(IN P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_MSG_JOIN_REQ_T prJoinReqMsg; + + DEBUGFUNC("aisFsmStateInit_RetryJOIN()"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + /* Retry other AuthType if possible */ + if (!prAisFsmInfo->ucAvailableAuthTypes) + return FALSE; + + if ((prStaRec->u2StatusCode != + STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED) && + (prStaRec->u2StatusCode != + STATUS_CODE_AUTH_TIMEOUT)) { + prAisFsmInfo->ucAvailableAuthTypes = 0; + return FALSE; + } + + if (prAisFsmInfo->ucAvailableAuthTypes & (uint8_t) + AUTH_TYPE_OPEN_SYSTEM) { + 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->prAisBssInfo; + + /* 4 <1> Check if IBSS was created before ? */ + if (prAisBssInfo->fgIsBeaconActivated) { + + /* 4 <2> Start IBSS Alone Timer for periodic SCAN and then SEARCH */ +#if !CFG_SLT_SUPPORT + cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rIbssAloneTimer, SEC_TO_MSEC(AIS_IBSS_ALONE_TIMEOUT_SEC)); +#endif + } + + aisFsmCreateIBSS(prAdapter); +} /* end of aisFsmStateInit_IBSS_ALONE() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief State Initialization of AIS_STATE_IBSS_MERGE +* +* @param[in] prBssDesc The pointer of BSS_DESC_T which is the IBSS we will try to merge with. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmStateInit_IBSS_MERGE(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_INFO_T prAisBssInfo; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + + ASSERT(prBssDesc); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prAisBssInfo = prAdapter->prAisBssInfo; + + /* 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, prAdapter->prAisBssInfo->ucBssIndex, prBssDesc); + if (!prStaRec) { + DBGLOG(AIS, ERROR, "prStaRec is NULL!\n"); + return; + } + prStaRec->fgIsMerging = TRUE; + + prAisFsmInfo->prTargetStaRec = prStaRec; + + /* 4 <2.1> sync. to firmware domain */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + /* 4 <3> IBSS-Merge */ + aisFsmMergeIBSS(prAdapter, prStaRec); +} /* end of aisFsmStateInit_IBSS_MERGE() */ + +#endif /* CFG_SUPPORT_ADHOC */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process of JOIN Abort +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmStateAbort_JOIN(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_MSG_JOIN_ABORT_T prJoinAbortMsg; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + /* 1. Abort JOIN process */ + prJoinAbortMsg = (P_MSG_JOIN_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_ABORT_T)); + if (!prJoinAbortMsg) { + + ASSERT(0); /* Can't abort SAA FSM */ + return; + } + + prJoinAbortMsg->rMsgHdr.eMsgId = MID_AIS_SAA_FSM_ABORT; + prJoinAbortMsg->ucSeqNum = prAisFsmInfo->ucSeqNumOfReqMsg; + prJoinAbortMsg->prStaRec = prAisFsmInfo->prTargetStaRec; + + scanRemoveConnFlagOfBssDescByBssid(prAdapter, prAisFsmInfo->prTargetStaRec->aucMacAddr); + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinAbortMsg, MSG_SEND_METHOD_BUF); + + /* 2. Return channel privilege */ + aisFsmReleaseCh(prAdapter); + + /* 3.1 stop join timeout timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rJoinTimeoutTimer); + + /* 3.2 reset local variable */ + prAisFsmInfo->fgIsInfraChannelFinished = TRUE; +} /* 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); + + DBGLOG(AIS, STATE, "aisFsmStateAbort_SCAN\n"); + + /* 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->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + prScanCancelMsg->fgIsChannelExt = FALSE; + + /* unbuffered message to guarantee scan is cancelled in sequence */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanCancelMsg, MSG_SEND_METHOD_UNBUF); +} /* end of aisFsmAbortSCAN() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process of NORMAL_TR Abort +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmStateAbort_NORMAL_TR(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + + ASSERT(prAdapter); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + /* TODO(Kevin): Do abort other MGMT func */ + + /* 1. Release channel to CNM */ + aisFsmReleaseCh(prAdapter); + + /* 2.1 stop join timeout timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rJoinTimeoutTimer); + + /* 2.2 reset local variable */ + prAisFsmInfo->fgIsInfraChannelFinished = TRUE; +} /* end of aisFsmAbortNORMAL_TR() */ + +#if CFG_SUPPORT_ADHOC +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process of NORMAL_TR Abort +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmStateAbort_IBSS(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_DESC_T prBssDesc; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + /* reset BSS-DESC */ + if (prAisFsmInfo->prTargetStaRec) { + prBssDesc = scanSearchBssDescByTA(prAdapter, prAisFsmInfo->prTargetStaRec->aucMacAddr); + + if (prBssDesc) { + prBssDesc->fgIsConnected = FALSE; + prBssDesc->fgIsConnecting = FALSE; + } + } + /* release channel privilege */ + aisFsmReleaseCh(prAdapter); +} +#endif /* CFG_SUPPORT_ADHOC */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief The Core FSM engine of AIS(Ad-hoc, Infra STA) +* +* @param[in] eNextState Enum value of next AIS STATE +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmSteps(IN P_ADAPTER_T prAdapter, ENUM_AIS_STATE_T eNextState) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_DESC_T prBssDesc; + P_MSG_CH_REQ_T prMsgChReq; + P_MSG_SCN_SCAN_REQ_V2 prScanReqMsg; + P_AIS_REQ_HDR_T prAisReq; + ENUM_BAND_T eBand; + UINT_8 ucChannel; + UINT_16 u2ScanIELen; + BOOLEAN fgIsTransition = (BOOLEAN) FALSE; + UINT_8 ucReasonCode; + +#if CFG_SUPPORT_DBDC + CNM_DBDC_CAP_T rDbdcCap; +#endif /*CFG_SUPPORT_DBDC*/ + P_GLUE_INFO_T prGlueInfo = NULL; + + DEBUGFUNC("aisFsmSteps()"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = prAdapter->prAisBssInfo; + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prGlueInfo = prAdapter->prGlueInfo; + + if (prGlueInfo == NULL) + return; + + do { + + /* Do entering Next State */ + prAisFsmInfo->ePreviousState = prAisFsmInfo->eCurrentState; + + DBGLOG(AIS, STATE, "[AIS]TRANSITION: [%s] -> [%s]\n", + apucDebugAisState[prAisFsmInfo->eCurrentState], apucDebugAisState[eNextState]); + + /* 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: +#if CFG_SUPPORT_CFG80211_AUTH + if (prAisFsmInfo->ePreviousState != + prAisFsmInfo->eCurrentState) + prConnSettings->fgIsConnInitialized = FALSE; +#endif + prAisReq = aisFsmGetNextRequest(prAdapter); + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); + if (prAisReq == NULL || prAisReq->eReqType == AIS_REQUEST_RECONNECT) { + if (prConnSettings->fgIsConnReqIssued == TRUE && + prConnSettings->fgIsDisconnectedByNonRequest + == FALSE && !atomic_read( + &prAdapter->prGlueInfo->cfgSuspend)) { + + prAisFsmInfo->fgTryScan = TRUE; + + if (!IS_NET_ACTIVE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex)) { + SET_NET_ACTIVE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + /* sync with firmware */ + nicActivateNetwork(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + } + + SET_NET_PWR_STATE_ACTIVE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + + prAisBssInfo->fgIsNetRequestInActive = FALSE; + + /* reset trial count */ + prAisFsmInfo->ucConnTrialCount = 0; + + eNextState = AIS_STATE_SEARCH; + fgIsTransition = TRUE; + } else { + SET_NET_PWR_STATE_IDLE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + + /* sync with firmware */ +#if CFG_SUPPORT_PNO + prAisBssInfo->fgIsNetRequestInActive = TRUE; + if (prAisBssInfo->fgIsPNOEnable) { + DBGLOG(BSS, INFO, + "[BSSidx][Network]=%d PNOEnable&&OP_MODE_INFRASTRUCTURE,KEEP ACTIVE\n", + prAisBssInfo->ucBssIndex); + } else +#endif + { + UNSET_NET_ACTIVE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + nicDeactivateNetwork(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + } + + /* check for other pending request */ + if (prAisReq && (aisFsmIsRequestPending + (prAdapter, AIS_REQUEST_SCAN, TRUE) == TRUE)) { + wlanClearScanningResult(prAdapter); + eNextState = AIS_STATE_SCAN; + + cnmTimerStartTimer(prAdapter, + &prAdapter->rWifiVar. + rAisFsmInfo. + rScanDoneTimer, + SEC_TO_MSEC( + AIS_SCN_DONE_TIMEOUT_SEC)); + 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; + cnmTimerStartTimer(prAdapter, + &prAdapter->rWifiVar. + rAisFsmInfo.rScanDoneTimer, + SEC_TO_MSEC(AIS_SCN_DONE_TIMEOUT_SEC)); + fgIsTransition = TRUE; + + /* free the message */ + cnmMemFree(prAdapter, prAisReq); + } else if (prAisReq->eReqType == AIS_REQUEST_ROAMING_CONNECT + || prAisReq->eReqType == AIS_REQUEST_ROAMING_SEARCH) { + /* ignore */ + /* free the message */ + cnmMemFree(prAdapter, prAisReq); + } else if (prAisReq->eReqType == AIS_REQUEST_REMAIN_ON_CHANNEL) { + eNextState = AIS_STATE_REQ_REMAIN_ON_CHANNEL; + fgIsTransition = TRUE; + + /* free the message */ + cnmMemFree(prAdapter, prAisReq); + } + + prAisFsmInfo->u4SleepInterval = AIS_BG_SCAN_INTERVAL_MIN_SEC; + + break; + + case AIS_STATE_SEARCH: + /* 4 <1> Search for a matched candidate and save it to prTargetBssDesc. */ +#if CFG_SLT_SUPPORT + prBssDesc = prAdapter->rWifiVar.rSltInfo.prPseudoBssDesc; +#else + prBssDesc = scanSearchBssDescByPolicy(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); +#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 Stored the Selected BSS security cipher. */ + /* or later asoc req compose IE */ + prAisBssInfo->u4RsnSelectedGroupCipher = prBssDesc->u4RsnSelectedGroupCipher; + prAisBssInfo->u4RsnSelectedPairwiseCipher = + prBssDesc->u4RsnSelectedPairwiseCipher; + prAisBssInfo->u4RsnSelectedAKMSuite = prBssDesc->u4RsnSelectedAKMSuite; +#if (CFG_HW_WMM_BY_BSS == 1) + prAisBssInfo->eBand = prBssDesc->eBand; + if (prAisBssInfo->fgIsWmmInited == FALSE) + prAisBssInfo->ucWmmQueSet = + cnmWmmIndexDecision(prAdapter, prAisBssInfo); +#endif +#if CFG_SUPPORT_DBDC + cnmDbdcEnableDecision(prAdapter, prAisBssInfo->ucBssIndex, prBssDesc->eBand); + cnmGetDbdcCapability(prAdapter, prAisBssInfo->ucBssIndex, + prBssDesc->eBand, prBssDesc->ucChannelNum, + wlanGetSupportNss(prAdapter, prAisBssInfo->ucBssIndex), &rDbdcCap); + + prAisBssInfo->eDBDCBand = ENUM_BAND_AUTO; + prAisBssInfo->ucNss = rDbdcCap.ucNss; +#if (CFG_HW_WMM_BY_BSS == 0) + prAisBssInfo->ucWmmQueSet = rDbdcCap.ucWmmSetIndex; +#endif +#endif /*CFG_SUPPORT_DBDC*/ + /* 4 Do STATE transition and update current Operation Mode. */ + if (prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) { + + prAisBssInfo->eCurrentOPMode = OP_MODE_INFRASTRUCTURE; + + /* Record the target BSS_DESC_T for next STATE. */ + prAisFsmInfo->prTargetBssDesc = prBssDesc; + + /* Transit to channel acquire */ + eNextState = AIS_STATE_REQ_CHANNEL_JOIN; + fgIsTransition = TRUE; + + /* increase connection trial count */ + prAisFsmInfo->ucConnTrialCount++; + } +#if CFG_SUPPORT_ADHOC + else if (prBssDesc->eBSSType == BSS_TYPE_IBSS) { + + prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; + + /* Record the target BSS_DESC_T for next STATE. */ + prAisFsmInfo->prTargetBssDesc = prBssDesc; + + eNextState = AIS_STATE_IBSS_MERGE; + fgIsTransition = TRUE; + } +#endif /* CFG_SUPPORT_ADHOC */ + else { + ASSERT(0); + eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; + fgIsTransition = TRUE; + } + } + /* 4 <2.b> If we don't have the matched one */ + else { + /* increase connection trial count for infrastructure connection */ + if (prConnSettings->eOPMode == NET_TYPE_INFRA) + prAisFsmInfo->ucConnTrialCount++; + + /* 4 Try to SCAN */ + if (prAisFsmInfo->fgTryScan) { + eNextState = AIS_STATE_LOOKING_FOR; + + fgIsTransition = TRUE; + } + /* 4 We've do SCAN already, now wait in some STATE. */ + else { + eNextState = aisFsmStateSearchAction(prAdapter, + AIS_FSM_STATE_SEARCH_ACTION_PHASE_0); + + fgIsTransition = TRUE; + } + + if (atomic_read( + &prGlueInfo->cfgSuspend)) { + eNextState = + AIS_STATE_JOIN_FAILURE; + + 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 (prAisBssInfo->ucReasonOfDisconnect != DISCONNECT_REASON_CODE_REASSOCIATION && + ((!prBssDesc) || /* CASE I */ + (prBssDesc->eBSSType != BSS_TYPE_INFRASTRUCTURE) || /* CASE II */ + (prBssDesc->fgIsConnected) || /* CASE III */ + (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID))) /* CASE 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 (prBssDesc == NULL) { + fgIsTransition = TRUE; + eNextState = aisFsmStateSearchAction(prAdapter, + AIS_FSM_STATE_SEARCH_ACTION_PHASE_1); + } else { + aisFsmStateSearchAction(prAdapter, AIS_FSM_STATE_SEARCH_ACTION_PHASE_2); + /* 4 Record the target BSS_DESC_T for next STATE. */ + prAisFsmInfo->prTargetBssDesc = prBssDesc; + + /* tyhsu: increase connection trial count */ + prAisFsmInfo->ucConnTrialCount++; + + /* Transit to channel acquire */ + eNextState = AIS_STATE_REQ_CHANNEL_JOIN; + fgIsTransition = TRUE; + } + } + } + + break; + + case AIS_STATE_WAIT_FOR_NEXT_SCAN: + + DBGLOG(AIS, LOUD, "SCAN: Idle Begin - Current Time = %u\n", kalGetTimeTick()); + + cnmTimerStartTimer(prAdapter, + &prAisFsmInfo->rBGScanTimer, SEC_TO_MSEC(prAisFsmInfo->u4SleepInterval)); + + SET_NET_PWR_STATE_IDLE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + + 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, prAdapter->prAisBssInfo->ucBssIndex)) { + SET_NET_ACTIVE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + + /* sync with firmware */ + nicActivateNetwork(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + prAisBssInfo->fgIsNetRequestInActive = FALSE; + } + + /* 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_V2) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + OFFSET_OF + (MSG_SCN_SCAN_REQ_V2, aucIE) + u2ScanIELen); + if (!prScanReqMsg) { + ASSERT(0); /* Can't trigger SCAN FSM */ + return; + } + + prScanReqMsg->rMsgHdr.eMsgId = MID_AIS_SCN_SCAN_REQ_V2; + prScanReqMsg->ucSeqNum = ++prAisFsmInfo->ucSeqNumOfScanReq; + prScanReqMsg->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + +#if CFG_SUPPORT_RDD_TEST_MODE + prScanReqMsg->eScanType = SCAN_TYPE_PASSIVE_SCAN; +#else + if (prAisFsmInfo->eCurrentState == AIS_STATE_SCAN + || prAisFsmInfo->eCurrentState == AIS_STATE_ONLINE_SCAN) { + if (prAisFsmInfo->ucScanSSIDNum == 0) { +#if CFG_SUPPORT_AIS_PASSIVE_SCAN + prScanReqMsg->eScanType = SCAN_TYPE_PASSIVE_SCAN; + + prScanReqMsg->ucSSIDType = 0; + prScanReqMsg->ucSSIDNum = 0; +#else + prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; + + prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_WILDCARD; + prScanReqMsg->ucSSIDNum = 0; +#endif + } else if (prAisFsmInfo->ucScanSSIDNum == 1 + && prAisFsmInfo->arScanSSID[0].u4SsidLen == 0) { + prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; + + prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_WILDCARD; + prScanReqMsg->ucSSIDNum = 0; + } else { + prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; + + prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_SPECIFIED; + prScanReqMsg->ucSSIDNum = prAisFsmInfo->ucScanSSIDNum; + prScanReqMsg->prSsid = prAisFsmInfo->arScanSSID; + } + } else { + prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; + + COPY_SSID(prAisFsmInfo->rRoamingSSID.aucSsid, + prAisFsmInfo->rRoamingSSID.u4SsidLen, + prConnSettings->aucSSID, prConnSettings->ucSSIDLen); + + /* Scan for determined SSID */ + prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_SPECIFIED; + prScanReqMsg->ucSSIDNum = 1; + prScanReqMsg->prSsid = &(prAisFsmInfo->rRoamingSSID); + } +#endif + + /* using default channel dwell time/timeout value */ + prScanReqMsg->u2ProbeDelay = 0; + prScanReqMsg->u2ChannelDwellTime = 0; + prScanReqMsg->u2TimeoutValue = 0; + + /* 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; +#if CFG_SCAN_CHANNEL_SPECIFIED + } else if (is_valid_scan_chnl_cnt(prAisFsmInfo->ucScanChannelListNum)) { + prScanReqMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; + prScanReqMsg->ucChannelListNum = prAisFsmInfo->ucScanChannelListNum; + kalMemCopy(prScanReqMsg->arChnlInfoList, prAisFsmInfo->arScanChnlInfoList, + sizeof(RF_CHANNEL_INFO_T) * prScanReqMsg->ucChannelListNum); +#endif + } else if (prAdapter->aePreferBand[prAdapter->prAisBssInfo->ucBssIndex] == BAND_NULL) { + if (prAdapter->fgEnable5GBand == TRUE) + prScanReqMsg->eScanChannel = SCAN_CHANNEL_FULL; + else + prScanReqMsg->eScanChannel = SCAN_CHANNEL_2G4; + + } else if (prAdapter->aePreferBand[prAdapter->prAisBssInfo->ucBssIndex] == BAND_2G4) { + prScanReqMsg->eScanChannel = SCAN_CHANNEL_2G4; + } else if (prAdapter->aePreferBand[prAdapter->prAisBssInfo->ucBssIndex] == 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->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + prMsgChReq->ucTokenID = ++prAisFsmInfo->ucSeqNumOfChReq; + prMsgChReq->eReqType = CH_REQ_TYPE_JOIN; +#ifdef CFG_SUPPORT_ADJUST_JOIN_CH_REQ_INTERVAL + prMsgChReq->u4MaxInterval = + prAdapter->rWifiVar.u4AisJoinChReqIntervel; +#else + prMsgChReq->u4MaxInterval = + AIS_JOIN_CH_REQUEST_INTERVAL; +#endif + DBGLOG(AIS, INFO, "Request join interval: %u\n", + prMsgChReq->u4MaxInterval); + prMsgChReq->ucPrimaryChannel = prAisFsmInfo->prTargetBssDesc->ucChannelNum; + prMsgChReq->eRfSco = prAisFsmInfo->prTargetBssDesc->eSco; + prMsgChReq->eRfBand = prAisFsmInfo->prTargetBssDesc->eBand; +#if CFG_SUPPORT_DBDC + prMsgChReq->eDBDCBand = ENUM_BAND_AUTO; +#endif /*CFG_SUPPORT_DBDC*/ + /* To do: check if 80/160MHz bandwidth is needed here */ + prMsgChReq->eRfChannelWidth = prAisFsmInfo->prTargetBssDesc->eChannelWidth; + prMsgChReq->ucRfCenterFreqSeg1 = prAisFsmInfo->prTargetBssDesc->ucCenterFreqS1; + prMsgChReq->ucRfCenterFreqSeg2 = prAisFsmInfo->prTargetBssDesc->ucCenterFreqS2; + + rlmReviseMaxBw(prAdapter, prAisBssInfo->ucBssIndex, &prMsgChReq->eRfSco, + (P_ENUM_CHANNEL_WIDTH_P)&prMsgChReq->eRfChannelWidth, + &prMsgChReq->ucRfCenterFreqSeg1, &prMsgChReq->ucPrimaryChannel); + + 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; + + case AIS_STATE_JOIN_FAILURE: + prConnSettings->fgIsDisconnectedByNonRequest = TRUE; + + nicMediaJoinFailure(prAdapter, prAdapter->prAisBssInfo->ucBssIndex, WLAN_STATUS_JOIN_TIMEOUT); + + eNextState = AIS_STATE_IDLE; + fgIsTransition = TRUE; + + break; + +#if CFG_SUPPORT_ADHOC + case AIS_STATE_IBSS_ALONE: + aisFsmStateInit_IBSS_ALONE(prAdapter); + break; + + case AIS_STATE_IBSS_MERGE: + aisFsmStateInit_IBSS_MERGE(prAdapter, prAisFsmInfo->prTargetBssDesc); + break; +#endif /* CFG_SUPPORT_ADHOC */ + + case AIS_STATE_NORMAL_TR: + if (prAisFsmInfo->fgIsInfraChannelFinished == FALSE) { + /* Don't do anything when rJoinTimeoutTimer is still ticking */ + } else { + /* 1. Process for pending scan */ + if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, TRUE) == TRUE) { + wlanClearScanningResult(prAdapter); + eNextState = AIS_STATE_ONLINE_SCAN; + fgIsTransition = TRUE; + } + /* 2. Process for pending roaming scan */ + else if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_SEARCH, TRUE) == TRUE) { + eNextState = AIS_STATE_LOOKING_FOR; + fgIsTransition = TRUE; + } + /* 3. Process for pending roaming scan */ + else if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, TRUE) == TRUE) { + eNextState = AIS_STATE_SEARCH; + fgIsTransition = TRUE; + } else + if (aisFsmIsRequestPending + (prAdapter, AIS_REQUEST_REMAIN_ON_CHANNEL, TRUE) == TRUE) { + eNextState = AIS_STATE_REQ_REMAIN_ON_CHANNEL; + fgIsTransition = TRUE; + } + } + + break; + + case AIS_STATE_DISCONNECTING: + /* send for deauth frame for disconnection */ + ucReasonCode = REASON_CODE_DEAUTH_LEAVING_BSS; +#if CFG_DISCONN_DEBUG_FEATURE + g_rDisconnInfoTemp.ucDisassocReason = ucReasonCode; +#endif + + authSendDeauthFrame(prAdapter, + prAisBssInfo, + prAisBssInfo->prStaRecOfAP, + (P_SW_RFB_T) NULL, + ucReasonCode, + aisDeauthXmitComplete); + cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rDeauthDoneTimer, 100); + break; + + case AIS_STATE_REQ_REMAIN_ON_CHANNEL: + /* send message to CNM for acquiring channel */ + prMsgChReq = (P_MSG_CH_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_REQ_T)); + if (!prMsgChReq) { + ASSERT(0); /* Can't indicate CNM for channel acquiring */ + return; + } + + /* zero-ize */ + kalMemZero(prMsgChReq, sizeof(MSG_CH_REQ_T)); + + /* filling */ + prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; + prMsgChReq->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + prMsgChReq->ucTokenID = ++prAisFsmInfo->ucSeqNumOfChReq; + prMsgChReq->eReqType = CH_REQ_TYPE_JOIN; + prMsgChReq->u4MaxInterval = prAisFsmInfo->rChReqInfo.u4DurationMs; + prMsgChReq->ucPrimaryChannel = prAisFsmInfo->rChReqInfo.ucChannelNum; + prMsgChReq->eRfSco = prAisFsmInfo->rChReqInfo.eSco; + prMsgChReq->eRfBand = prAisFsmInfo->rChReqInfo.eBand; +#if CFG_SUPPORT_DBDC + prMsgChReq->eDBDCBand = ENUM_BAND_AUTO; +#endif + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChReq, MSG_SEND_METHOD_BUF); + + prAisFsmInfo->fgIsChannelRequested = TRUE; + + break; + + case AIS_STATE_REMAIN_ON_CHANNEL: + SET_NET_ACTIVE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + + /* sync with firmware */ + nicActivateNetwork(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + prAisBssInfo->fgIsNetRequestInActive = FALSE; + break; + + default: + ASSERT(0); /* Make sure we have handle all STATEs */ + break; + + } + } while (fgIsTransition); + + return; + +} /* end of aisFsmSteps() */ + +enum _ENUM_AIS_STATE_T aisFsmStateSearchAction(IN struct _ADAPTER_T *prAdapter, UINT_8 ucPhase) +{ + struct _CONNECTION_SETTINGS_T *prConnSettings; + struct _BSS_INFO_T *prAisBssInfo; + struct _AIS_FSM_INFO_T *prAisFsmInfo; + struct _BSS_DESC_T *prBssDesc; + enum _ENUM_AIS_STATE_T eState = AIS_STATE_IDLE; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = prAdapter->prAisBssInfo; + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + +#if CFG_SLT_SUPPORT + prBssDesc = prAdapter->rWifiVar.rSltInfo.prPseudoBssDesc; +#else + prBssDesc = scanSearchBssDescByPolicy(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); +#endif + + if (ucPhase == AIS_FSM_STATE_SEARCH_ACTION_PHASE_0) { + if (prConnSettings->eOPMode == NET_TYPE_INFRA) { + + /* issue reconnect request, */ + /*and retreat to idle state for scheduling */ + aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); + eState = AIS_STATE_IDLE; + } +#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; + eState = AIS_STATE_IBSS_ALONE; + } +#endif /* CFG_SUPPORT_ADHOC */ + else { + ASSERT(0); + eState = AIS_STATE_WAIT_FOR_NEXT_SCAN; + } + } else if (ucPhase == AIS_FSM_STATE_SEARCH_ACTION_PHASE_1) { + /* increase connection trial count for infrastructure connection */ + if (prConnSettings->eOPMode == NET_TYPE_INFRA) + prAisFsmInfo->ucConnTrialCount++; + /* 4 Try to SCAN */ + if (prAisFsmInfo->fgTryScan) + eState = AIS_STATE_LOOKING_FOR; + + /* 4 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); + + eState = AIS_STATE_IDLE; + } +#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; + + eState = AIS_STATE_IBSS_ALONE; + } +#endif /* CFG_SUPPORT_ADHOC */ + else { + ASSERT(0); + eState = AIS_STATE_WAIT_FOR_NEXT_SCAN; + } + } + } else { +#if DBG + if (prAisBssInfo->ucReasonOfDisconnect != DISCONNECT_REASON_CODE_REASSOCIATION) + ASSERT(UNEQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID)); +#endif /* DBG */ + } + return eState; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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, INFO, "ScanDone\n"); + + DBGLOG(AIS, LOUD, "EVENT-SCAN DONE: Current Time = %u\n", kalGetTimeTick()); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + prScanDoneMsg = (P_MSG_SCN_SCAN_DONE) prMsgHdr; + ASSERT(prScanDoneMsg->ucBssIndex == prAdapter->prAisBssInfo->ucBssIndex); + + 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 { + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_SCAN: + prConnSettings->fgIsScanReqIssued = FALSE; + + /* reset scan IE buffer */ + prAisFsmInfo->u4ScanIELength = 0; + + kalScanDone(prAdapter->prGlueInfo, KAL_NETWORK_TYPE_AIS_INDEX, WLAN_STATUS_SUCCESS); + eNextState = AIS_STATE_IDLE; +#if CFG_SUPPORT_AGPS_ASSIST + scanReportScanResultToAgps(prAdapter); +#endif + + break; + + case AIS_STATE_ONLINE_SCAN: + prConnSettings->fgIsScanReqIssued = FALSE; + + /* reset scan IE buffer */ + prAisFsmInfo->u4ScanIELength = 0; + + kalScanDone(prAdapter->prGlueInfo, KAL_NETWORK_TYPE_AIS_INDEX, WLAN_STATUS_SUCCESS); +#if CFG_SUPPORT_ROAMING + eNextState = aisFsmRoamingScanResultsUpdate(prAdapter); +#else + eNextState = AIS_STATE_NORMAL_TR; +#endif /* CFG_SUPPORT_ROAMING */ +#if CFG_SUPPORT_AGPS_ASSIST + scanReportScanResultToAgps(prAdapter); +#endif + + break; + + case AIS_STATE_LOOKING_FOR: +#if CFG_SUPPORT_ROAMING + eNextState = aisFsmRoamingScanResultsUpdate(prAdapter); +#else + eNextState = AIS_STATE_SEARCH; +#endif /* CFG_SUPPORT_ROAMING */ + break; + + case AIS_STATE_IDLE: + prConnSettings->fgIsScanReqIssued = FALSE; + prAisFsmInfo->u4ScanIELength = 0; + kalScanDone(prAdapter->prGlueInfo, + KAL_NETWORK_TYPE_AIS_INDEX, + WLAN_STATUS_SUCCESS); + + break; + + case AIS_STATE_DISCONNECTING: + /* condition aisFsmStateAbort during scan + * AIS leave scanning state before SCN done + * driver should report scan done otherwise scan blocked + */ + prConnSettings->fgIsScanReqIssued = FALSE; + prAisFsmInfo->u4ScanIELength = 0; + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_SCAN_ABORT, NULL, 0); + + break; + + default: + prConnSettings->fgIsScanReqIssued = FALSE; + + /* reset scan IE buffer */ + prAisFsmInfo->u4ScanIELength = 0; + + kalScanDone(prAdapter->prGlueInfo, + KAL_NETWORK_TYPE_AIS_INDEX, + WLAN_STATUS_SUCCESS); +#if CFG_SUPPORT_AGPS_ASSIST + scanReportScanResultToAgps(prAdapter); +#endif + break; + + } + } + + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); +} /* end of aisFsmRunEventScanDone() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_AIS_ABORT_T prAisAbortMsg; + P_AIS_FSM_INFO_T prAisFsmInfo; + UINT_8 ucReasonOfDisconnect; + BOOLEAN fgDelayIndication; + P_CONNECTION_SETTINGS_T prConnSettings; + + DEBUGFUNC("aisFsmRunEventAbort()"); + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* 4 <1> Extract information of Abort Message and then free memory. */ + prAisAbortMsg = (P_MSG_AIS_ABORT_T) prMsgHdr; + ucReasonOfDisconnect = prAisAbortMsg->ucReasonOfDisconnect; + fgDelayIndication = prAisAbortMsg->fgDelayIndication; + + cnmMemFree(prAdapter, prMsgHdr); + + DBGLOG(AIS, STATE, "EVENT-ABORT: Current State %s, ucReasonOfDisconnect:%d\n", + apucDebugAisState[prAisFsmInfo->eCurrentState], ucReasonOfDisconnect); + + /* record join request time */ + GET_CURRENT_SYSTIME(&(prAisFsmInfo->rJoinReqTime)); + + /* 4 <2> clear previous pending connection request and insert new one */ + if (ucReasonOfDisconnect == DISCONNECT_REASON_CODE_DEAUTHENTICATED + || ucReasonOfDisconnect == DISCONNECT_REASON_CODE_DISASSOCIATED) { + prConnSettings->fgIsDisconnectedByNonRequest = TRUE; + } else { + prConnSettings->fgIsDisconnectedByNonRequest = FALSE; + } + + /* to support user space triggered roaming */ + if (ucReasonOfDisconnect == DISCONNECT_REASON_CODE_REASSOCIATION && + prAisFsmInfo->eCurrentState != AIS_STATE_DISCONNECTING) { + + if (prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR && + prAisFsmInfo->fgIsInfraChannelFinished == TRUE) { + aisFsmSteps(prAdapter, AIS_STATE_SEARCH); + } else { + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_SEARCH, TRUE); + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, TRUE); + aisFsmInsertRequest(prAdapter, AIS_REQUEST_ROAMING_CONNECT); + } + + /* check connection state */ + if (prAdapter->prAisBssInfo->eConnectionState == + PARAM_MEDIA_STATE_CONNECTED) { + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + + DBGLOG(REQ, STATE, "%d -> %d\n", + prGlueInfo->eParamMediaStateIndicated, + PARAM_MEDIA_STATE_CONNECTED); + kalSetMediaStateIndicated(prGlueInfo, + PARAM_MEDIA_STATE_CONNECTED); + } + + return; + } + + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_RECONNECT, TRUE); + aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); + + if (prAisFsmInfo->eCurrentState != AIS_STATE_DISCONNECTING) { + /* 4 <3> invoke abort handler */ + DBGLOG(AIS, STATE, "ucReasonOfDisconnect:%d\n", ucReasonOfDisconnect); + aisFsmStateAbort(prAdapter, ucReasonOfDisconnect, fgDelayIndication); + } +} /* end of aisFsmRunEventAbort() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function handles AIS-FSM abort event/command +* +* \param[in] prAdapter Pointer of ADAPTER_T +* ucReasonOfDisconnect Reason for disonnection +* fgDelayIndication Option to delay disconnection indication +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmStateAbort(IN P_ADAPTER_T prAdapter, UINT_8 ucReasonOfDisconnect, BOOLEAN fgDelayIndication) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + BOOLEAN fgIsCheckConnected; + + ASSERT(prAdapter); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = prAdapter->prAisBssInfo; + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + fgIsCheckConnected = FALSE; + + DBGLOG(AIS, STATE, "aisFsmStateAbort DiscReason[%d], CurState[%d]\n", + ucReasonOfDisconnect, prAisFsmInfo->eCurrentState); + + /* 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: + case AIS_STATE_JOIN_FAILURE: + /* Connect Abort Obss scan */ + rlmObssAbortScan(prAdapter); + 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); + + if (atomic_read(&prAdapter->prGlueInfo->cfgSuspend)) + break; + + /* 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); + + if (atomic_read(&prAdapter->prGlueInfo->cfgSuspend)) { + fgIsCheckConnected = TRUE; + break; + } + + /* 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); + /* Disconnect Abort Obss scan*/ + rlmObssAbortScan(prAdapter); + + break; + + case AIS_STATE_REQ_REMAIN_ON_CHANNEL: + /* release channel */ + aisFsmReleaseCh(prAdapter); + break; + + case AIS_STATE_REMAIN_ON_CHANNEL: + /* 1. release channel */ + aisFsmReleaseCh(prAdapter); + + /* 2. stop channel timeout timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer); + + break; + + default: + break; + } + + if (fgIsCheckConnected && (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED)) { + + /* switch into DISCONNECTING state for sending DEAUTH if necessary */ + if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE && +#if !CFG_SUPPORT_CFG80211_AUTH + prAisBssInfo->ucReasonOfDisconnect == DISCONNECT_REASON_CODE_NEW_CONNECTION && +#endif + prAisBssInfo->prStaRecOfAP && prAisBssInfo->prStaRecOfAP->fgIsInUse) { + aisFsmSteps(prAdapter, AIS_STATE_DISCONNECTING); + + return; + } + /* 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 struct _ADAPTER_T *prAdapter, IN struct _MSG_HDR_T *prMsgHdr) +{ + struct _MSG_SAA_FSM_COMP_T *prJoinCompMsg; + struct _AIS_FSM_INFO_T *prAisFsmInfo; + enum _ENUM_AIS_STATE_T eNextState; + struct _SW_RFB_T *prAssocRspSwRfb; + + DEBUGFUNC("aisFsmRunEventJoinComplete()"); + ASSERT(prMsgHdr); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prJoinCompMsg = (struct _MSG_SAA_FSM_COMP_T *)prMsgHdr; + prAssocRspSwRfb = prJoinCompMsg->prSwRfb; + + eNextState = prAisFsmInfo->eCurrentState; + + /* Check State and SEQ NUM */ + if (prAisFsmInfo->eCurrentState == AIS_STATE_JOIN) { + /* Check SEQ NUM */ + if (prJoinCompMsg->ucSeqNum == prAisFsmInfo->ucSeqNumOfReqMsg) + eNextState = aisFsmJoinCompleteAction(prAdapter, prMsgHdr); + /* try to remove timeout blacklist item */ + aisRemoveDisappearedBlacklist(prAdapter); +#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); +} /* end of aisFsmRunEventJoinComplete() */ + +enum _ENUM_AIS_STATE_T aisFsmJoinCompleteAction(IN struct _ADAPTER_T *prAdapter, IN struct _MSG_HDR_T *prMsgHdr) +{ + struct _MSG_SAA_FSM_COMP_T *prJoinCompMsg; + struct _AIS_FSM_INFO_T *prAisFsmInfo; + enum _ENUM_AIS_STATE_T eNextState; + struct _STA_RECORD_T *prStaRec; + struct _SW_RFB_T *prAssocRspSwRfb; + struct _BSS_INFO_T *prAisBssInfo; +#if CFG_SUPPORT_CFG80211_AUTH + P_CONNECTION_SETTINGS_T prConnSettings; +#endif + OS_SYSTIME rCurrentTime; + + DEBUGFUNC("aisFsmJoinCompleteAction()"); + + ASSERT(prMsgHdr); + + GET_CURRENT_SYSTIME(&rCurrentTime); +#if CFG_SUPPORT_CFG80211_AUTH + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); +#endif + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prJoinCompMsg = (struct _MSG_SAA_FSM_COMP_T *)prMsgHdr; + prStaRec = prJoinCompMsg->prStaRec; + prAssocRspSwRfb = prJoinCompMsg->prSwRfb; + prAisBssInfo = prAdapter->prAisBssInfo; + eNextState = prAisFsmInfo->eCurrentState; + + /* 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); + cnmStaRecFree(prAdapter, + prAisBssInfo->prStaRecOfAP); + } + + /* For temp solution, need to refine */ + /* 4 <1.4> Update BSS_INFO_T */ + aisUpdateBssInfoForJOIN(prAdapter, + prStaRec, prAssocRspSwRfb); + + /* 4 <1.3> Activate current AP's */ + /* STA_RECORD_T in Driver. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + /* 4 <1.5> Update RSSI if necessary */ + nicUpdateRSSI(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, + (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 (prAdapter->rWifiVar.ucTpTestMode == + ENUM_TP_TEST_MODE_THROUGHPUT) { + nicEnterTPTestMode(prAdapter, + TEST_MODE_THROUGHPUT); + } else if (prAdapter->rWifiVar.ucTpTestMode == + ENUM_TP_TEST_MODE_SIGMA_AC_N_PMF) { + nicEnterTPTestMode(prAdapter, + TEST_MODE_SIGMA_AC_N_PMF); + } else if (prAdapter->rWifiVar.ucTpTestMode == + ENUM_TP_TEST_MODE_SIGMA_WMM_PS) { + nicEnterTPTestMode(prAdapter, + TEST_MODE_SIGMA_WMM_PS); + } + } + +#if CFG_SUPPORT_ROAMING + /* if user space roaming is enabled, */ + /* we should disable driver/fw roaming */ +#ifdef CONFIG_CFG80211_ALLOW_RECONNECT + if (prAdapter->rWifiVar.rConnSettings.eConnectionPolicy != + CONNECT_BY_BSSID) +#endif + 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) { + struct _BSS_DESC_T *prBssDesc; + PARAM_SSID_T rParamSsid; + + /* 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; + + if (prAisBssInfo->ucSSIDLen) { + rParamSsid.u4SsidLen = prAisBssInfo->ucSSIDLen; + COPY_SSID(rParamSsid.aucSsid, + rParamSsid.u4SsidLen, + prAisBssInfo->aucSSID, + prAisBssInfo->ucSSIDLen); + prBssDesc = scanSearchBssDescByBssidAndSsid( + prAdapter, + prAisBssInfo->aucBSSID, + TRUE, + &rParamSsid); + } else { +#if CFG_SUPPORT_CFG80211_AUTH + prBssDesc = scanSearchBssDescByBssidAndChanNum( + prAdapter, + prConnSettings->aucBSSID, + TRUE, + prConnSettings->ucChannelNum); +#else + prBssDesc = scanSearchBssDescByBssid(prAdapter, + prStaRec->aucMacAddr); +#endif + } + + if (prBssDesc == NULL) + return eNextState; + + /* ASSERT(prBssDesc); */ + /* ASSERT(prBssDesc->fgIsConnecting); */ + prBssDesc->ucJoinFailureCount++; + if (prBssDesc->ucJoinFailureCount > + SCN_BSS_JOIN_FAIL_THRESOLD) { + GET_CURRENT_SYSTIME(&prBssDesc->rJoinFailTime); + DBGLOG(AIS, INFO, + "Bss " MACSTR " join fail %d times,", + MAC2STR(prBssDesc->aucBSSID), + SCN_BSS_JOIN_FAIL_THRESOLD); + DBGLOG(AIS, INFO, + " temp disable it at time: %u\n", + prBssDesc->rJoinFailTime); + } + + if (prBssDesc) + prBssDesc->fgIsConnecting = FALSE; + + /* 3.3 Free STA-REC */ + if (prStaRec != prAisBssInfo->prStaRecOfAP) + cnmStaRecFree(prAdapter, prStaRec); + + if (prAisBssInfo->eConnectionState == + PARAM_MEDIA_STATE_CONNECTED) { +#if CFG_SUPPORT_ROAMING + eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; +#endif /* CFG_SUPPORT_ROAMING */ + } else if (CHECK_FOR_TIMEOUT + (rCurrentTime, prAisFsmInfo->rJoinReqTime, + SEC_TO_SYSTIME(AIS_JOIN_TIMEOUT))) { + /* 4.a temrminate join operation */ + eNextState = AIS_STATE_JOIN_FAILURE; + } else { + /* 4.b send reconnect request */ + aisFsmInsertRequest(prAdapter, + AIS_REQUEST_RECONNECT); + + eNextState = AIS_STATE_IDLE; + } + } + } + return eNextState; +} + +#if CFG_SUPPORT_ADHOC +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Grant Msg of IBSS Create which was sent by +* CNM to indicate that channel was changed for creating IBSS. +* +* @param[in] prAdapter Pointer of ADAPTER_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmCreateIBSS(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + + ASSERT(prAdapter); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + do { + /* Check State */ + if (prAisFsmInfo->eCurrentState == AIS_STATE_IBSS_ALONE) + aisUpdateBssInfoForCreateIBSS(prAdapter); + + } while (FALSE); +} /* end of aisFsmCreateIBSS() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Grant Msg of IBSS Merge which was sent by +* CNM to indicate that channel was changed for merging IBSS. +* +* @param[in] prAdapter Pointer of ADAPTER_T +* @param[in] prStaRec Pointer of STA_RECORD_T for merge +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmMergeIBSS(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + P_BSS_INFO_T prAisBssInfo; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = prAdapter->prAisBssInfo; + + 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. */ + bssInitializeClientList(prAdapter, prAisBssInfo); + + /* 4 <1.3> Unmark connection flag of previous BSS_DESC_T. */ + prBssDesc = scanSearchBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); + if (prBssDesc != NULL) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = FALSE; + } + /* 4 <1.4> Add Peers' STA_RECORD_T to Client List */ + bssAddClient(prAdapter, prAisBssInfo, prStaRec); + + /* 4 <1.5> Activate current Peer's STA_RECORD_T in Driver. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + prStaRec->fgIsMerging = FALSE; + + /* 4 <1.6> Update BSS_INFO_T */ + aisUpdateBssInfoForMergeIBSS(prAdapter, prStaRec); + + /* 4 <1.7> Enable other features */ + + /* 4 <1.8> Indicate Connected Event to Host immediately. */ + aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, FALSE); + + /* 4 <1.9> Set the Next State of AIS FSM */ + eNextState = AIS_STATE_NORMAL_TR; + + /* 4 <1.10> Release channel privilege */ + aisFsmReleaseCh(prAdapter); + +#if CFG_SLT_SUPPORT + prAdapter->rWifiVar.rSltInfo.prPseudoStaRec = prStaRec; +#endif + } + break; + + default: + break; + } + + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); + + } while (FALSE); +} /* end of aisFsmMergeIBSS() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Notification of existing IBSS was found +* from SCN. +* +* @param[in] prMsgHdr Message of Notification of an IBSS was present. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventFoundIBSSPeer(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_AIS_IBSS_PEER_FOUND_T prAisIbssPeerFoundMsg; + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prAisBssInfo; + P_BSS_DESC_T prBssDesc; + BOOLEAN fgIsMergeIn; + + ASSERT(prMsgHdr); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = prAdapter->prAisBssInfo; + + prAisIbssPeerFoundMsg = (P_MSG_AIS_IBSS_PEER_FOUND_T) prMsgHdr; + + ASSERT(prAisIbssPeerFoundMsg->ucBssIndex == prAdapter->prAisBssInfo->ucBssIndex); + + 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 */ + bssAddClient(prAdapter, prAisBssInfo, prStaRec); + +#if CFG_SLT_SUPPORT + /* 4 <1.3> Mark connection flag of BSS_DESC_T. */ + prBssDesc = scanSearchBssDescByTA(prAdapter, prStaRec->aucMacAddr); + + if (prBssDesc != NULL) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + } else { + ASSERT(0); /* Should be able to find a BSS_DESC_T here. */ + } + + /* 4 <1.4> Activate current Peer's STA_RECORD_T in Driver. */ + prStaRec->fgIsQoS = TRUE; /* TODO(Kevin): TBD */ +#else + /* 4 <1.3> Mark connection flag of BSS_DESC_T. */ + prBssDesc = scanSearchBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); + + if (prBssDesc != NULL) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + } else { + ASSERT(0); /* Should be able to find a BSS_DESC_T here. */ + } + + /* 4 <1.4> Activate current Peer's STA_RECORD_T in Driver. */ + prStaRec->fgIsQoS = FALSE; /* TODO(Kevin): TBD */ + +#endif + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + prStaRec->fgIsMerging = FALSE; + + /* 4 <1.6> sync. to firmware */ + nicUpdateBss(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + + /* 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, prAdapter->prAisBssInfo->ucBssIndex); + + /* 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 */ + bssAddClient(prAdapter, prAisBssInfo, prStaRec); + +#if CFG_SLT_SUPPORT + /* 4 <3.2> Activate current Peer's STA_RECORD_T in Driver. */ + prStaRec->fgIsQoS = TRUE; /* TODO(Kevin): TBD */ +#else + /* 4 <3.2> Activate current Peer's STA_RECORD_T in Driver. */ + prStaRec->fgIsQoS = FALSE; /* TODO(Kevin): TBD */ +#endif + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + prStaRec->fgIsMerging = FALSE; + + } + /* 4 <4> We need 'merge out' to this IBSS */ + else { + + /* 4 <4.1> Get corresponding BSS_DESC_T */ + prBssDesc = scanSearchBssDescByTA(prAdapter, prStaRec->aucMacAddr); + + prAisFsmInfo->prTargetBssDesc = prBssDesc; + + /* 4 <4.2> Set the Next State of AIS FSM */ + eNextState = AIS_STATE_IBSS_MERGE; + + } + } + break; + + default: + break; + } + + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); +} /* end of aisFsmRunEventFoundIBSSPeer() */ +#endif /* CFG_SUPPORT_ADHOC */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Media State to HOST +* +* @param[in] eConnectionState Current Media State +* @param[in] fgDelayIndication Set TRUE for postponing the Disconnect Indication. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisIndicationOfMediaStateToHost(IN P_ADAPTER_T prAdapter, + ENUM_PARAM_MEDIA_STATE_T eConnectionState, BOOLEAN fgDelayIndication) +{ + EVENT_CONNECTION_STATUS rEventConnStatus; + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_INFO_T prAisBssInfo; + P_AIS_FSM_INFO_T prAisFsmInfo; + + DEBUGFUNC("aisIndicationOfMediaStateToHost()"); + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prAisBssInfo = prAdapter->prAisBssInfo; + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + DBGLOG(AIS, LOUD, "AIS indicate Media State to Host Current State [%d]\n", prAisBssInfo->eConnectionState); + + /* 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 { + /* Clear the pmkid cache while media disconnect */ + secClearPmkid(prAdapter); + rEventConnStatus.ucReasonOfDisconnect = prAisBssInfo->ucReasonOfDisconnect; + } + + /* 4 <2> Indication */ + nicMediaStateChange(prAdapter, prAdapter->prAisBssInfo->ucBssIndex, &rEventConnStatus); + prAisBssInfo->eConnectionStateIndicated = eConnectionState; + } else { + /* NOTE: Only delay the Indication of Disconnect Event */ + ASSERT(eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED); + + DBGLOG(AIS, INFO, "Postpone the indication of Disconnect for %d seconds\n", + prConnSettings->ucDelayTimeOfDisconnectEvent); + + cnmTimerStartTimer(prAdapter, + &prAisFsmInfo->rIndicationOfDisconnectTimer, + SEC_TO_MSEC(prConnSettings->ucDelayTimeOfDisconnectEvent)); + } +} /* end of aisIndicationOfMediaStateToHost() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Media Disconnect" to HOST +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisPostponedEventOfDisconnTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr) +{ + P_BSS_INFO_T prAisBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + + prAisBssInfo = prAdapter->prAisBssInfo; + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + DBGLOG(AIS, EVENT, "aisPostponedEventOfDisconnTimeout\n"); + + /* 4 <1> Deactivate previous AP's STA_RECORD_T in Driver if have. */ + if (prAisBssInfo->prStaRecOfAP) { + /* cnmStaRecChangeState(prAdapter, prAisBssInfo->prStaRecOfAP, STA_STATE_1); */ + + prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; + } + /* 4 <2> Remove pending connection request */ + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_RECONNECT, TRUE); + prConnSettings->fgIsDisconnectedByNonRequest = TRUE; + prAisBssInfo->u2DeauthReason = REASON_CODE_BEACON_TIMEOUT; + /* 4 <3> Indicate Disconnected Event to Host immediately. */ + aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED, FALSE); +} /* end of aisPostponedEventOfDisconnTimeout() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will update the contain of BSS_INFO_T for AIS network once +* the association was completed. +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] prAssocRspSwRfb Pointer to SW RFB of ASSOC RESP FRAME. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisUpdateBssInfoForJOIN(IN P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, P_SW_RFB_T prAssocRspSwRfb) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame; + P_BSS_DESC_T prBssDesc; + UINT_16 u2IELength; + PUINT_8 pucIE; + PARAM_SSID_T rParamSsid; + + DEBUGFUNC("aisUpdateBssInfoForJOIN()"); + + ASSERT(prStaRec); + ASSERT(prAssocRspSwRfb); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = prAdapter->prAisBssInfo; + 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; + +#if CFG_SUPPORT_TDLS + prAisBssInfo->fgTdlsIsProhibited = prStaRec->fgTdlsIsProhibited; + prAisBssInfo->fgTdlsIsChSwProhibited = prStaRec->fgTdlsIsChSwProhibited; +#endif /* CFG_SUPPORT_TDLS */ + + /* 4 <2.3> Setup PHY Attributes and Basic Rate Set/Operational Rate Set */ + prAisBssInfo->ucPhyTypeSet = prStaRec->ucDesiredPhyTypeSet; + + prAisBssInfo->ucNonHTBasicPhyType = prStaRec->ucNonHTBasicPhyType; + + prAisBssInfo->u2OperationalRateSet = prStaRec->u2OperationalRateSet; + prAisBssInfo->u2BSSBasicRateSet = prStaRec->u2BSSBasicRateSet; + + nicTxUpdateBssDefaultRate(prAisBssInfo); + + /* 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 */ + if (prAisBssInfo->ucSSIDLen) { + rParamSsid.u4SsidLen = prAisBssInfo->ucSSIDLen; + COPY_SSID(rParamSsid.aucSsid, rParamSsid.u4SsidLen, + prAisBssInfo->aucSSID, + prAisBssInfo->ucSSIDLen); + prBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, + prAisBssInfo->aucBSSID, + TRUE, + &rParamSsid); + } else { +#if CFG_SUPPORT_CFG80211_AUTH + prBssDesc = scanSearchBssDescByBssidAndChanNum( + prAdapter, + prConnSettings->aucBSSID, + TRUE, + prConnSettings->ucChannelNum); +#else + prBssDesc = scanSearchBssDescByBssid(prAdapter, + prAssocRspFrame->aucBSSID); +#endif + } + + if (prBssDesc) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + prBssDesc->ucJoinFailureCount = 0; + /* 4 <4.1> Setup MIB for current BSS */ + prAisBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval; + } else { + /* should never happen */ + ASSERT(0); + } + + /* NOTE: Defer ucDTIMPeriod updating to when beacon is received after connection */ + prAisBssInfo->ucDTIMPeriod = 0; + prAisBssInfo->u2ATIMWindow = 0; + + prAisBssInfo->ucBeaconTimeoutCount = AIS_BEACON_TIMEOUT_COUNT_INFRA; +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + prAisBssInfo->ucRoamSkipTimes = ROAMING_ONE_AP_SKIP_TIMES; + prAisBssInfo->fgGoodRcpiArea = FALSE; + prAisBssInfo->fgPoorRcpiArea = FALSE; +#endif + + /* 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); + + secPostUpdateAddr(prAdapter, prAdapter->prAisBssInfo); + + /* 4 <4.3> Sync with firmware for BSS-INFO */ + nicUpdateBss(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + + /* 4 <4.4> *DEFER OPERATION* nicPmIndicateBssConnected() will be invoked */ + /* inside scanProcessBeaconAndProbeResp() after 1st beacon is received */ +} /* end of aisUpdateBssInfoForJOIN() */ + +#if CFG_SUPPORT_ADHOC +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will create an Ad-Hoc network and start sending Beacon Frames. +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisUpdateBssInfoForCreateIBSS(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = prAdapter->prAisBssInfo; + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + if (prAisBssInfo->fgIsBeaconActivated) + return; + + /* 3 <1> Update BSS_INFO_T per Network Basis */ + /* 4 <1.1> Setup Operation Mode */ + prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; + + /* 4 <1.2> Setup SSID */ + COPY_SSID(prAisBssInfo->aucSSID, prAisBssInfo->ucSSIDLen, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); + + /* 4 <1.3> Clear current AP's STA_RECORD_T and current AID */ + prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; + prAisBssInfo->u2AssocId = 0; + + /* 4 <1.4> Setup Channel, Band and Phy Attributes */ + prAisBssInfo->ucPrimaryChannel = prConnSettings->ucAdHocChannelNum; + prAisBssInfo->eBand = prConnSettings->eAdHocBand; + + if (prAisBssInfo->eBand == BAND_2G4) { + /* Depend on eBand */ + prAisBssInfo->ucPhyTypeSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11BGN; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prAisBssInfo->ucConfigAdHocAPMode = AD_HOC_MODE_MIXED_11BG; + } else { + /* Depend on eBand */ + prAisBssInfo->ucPhyTypeSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11ANAC; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prAisBssInfo->ucConfigAdHocAPMode = AD_HOC_MODE_11A; + } + + /* 4 <1.5> Setup MIB for current BSS */ + prAisBssInfo->u2BeaconInterval = prConnSettings->u2BeaconPeriod; + prAisBssInfo->ucDTIMPeriod = 0; + prAisBssInfo->u2ATIMWindow = prConnSettings->u2AtimWindow; + + prAisBssInfo->ucBeaconTimeoutCount = AIS_BEACON_TIMEOUT_COUNT_ADHOC; + + if (prConnSettings->eEncStatus == ENUM_ENCRYPTION1_ENABLED || + prConnSettings->eEncStatus == ENUM_ENCRYPTION2_ENABLED || + prConnSettings->eEncStatus == ENUM_ENCRYPTION3_ENABLED) { + prAisBssInfo->fgIsProtection = TRUE; + } else { + prAisBssInfo->fgIsProtection = FALSE; + } + + /* 3 <2> Update BSS_INFO_T common part */ + ibssInitForAdHoc(prAdapter, prAisBssInfo); + /* 4 <2.1> Initialize client list */ + bssInitializeClientList(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, prAdapter->prAisBssInfo->ucBssIndex); + + /* 4 <3.3> enable beaconing */ + bssUpdateBeaconContent(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + + /* 4 <3.4> Update AdHoc PM parameter */ + nicPmIndicateBssCreated(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + + /* 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)); +} /* 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->prAisBssInfo; + 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 */ + nicTxUpdateBssDefaultRate(prAisBssInfo); + + /* 4 <5.2> Setup channel and bandwidth */ + rlmBssInitForAPandIbss(prAdapter, prAisBssInfo); + + /* 4 <5.3> use command packets to inform firmware */ + nicUpdateBss(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + + /* 4 <5.4> enable beaconing */ + bssUpdateBeaconContent(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + + /* 4 <5.5> Update AdHoc PM parameter */ + nicPmIndicateBssConnected(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + + /* 3 <6> Set ACTIVE flag. */ + prAisBssInfo->fgIsBeaconActivated = TRUE; + prAisBssInfo->fgHoldSameBssidForIBSS = TRUE; +} /* end of aisUpdateBssInfoForMergeIBSS() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Probe Request Frame and then return +* result to BSS to indicate if need to send the corresponding Probe Response +* Frame if the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu4ControlFlags Control flags for replying the Probe Response +* +* @retval TRUE Reply the Probe Response +* @retval FALSE Don't reply the Probe Response +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN aisValidateProbeReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_32 pu4ControlFlags) +{ + P_WLAN_MAC_MGMT_HEADER_T prMgtHdr; + P_BSS_INFO_T prBssInfo; + P_IE_SSID_T prIeSsid = (P_IE_SSID_T) NULL; + PUINT_8 pucIE; + UINT_16 u2IELength; + UINT_16 u2Offset = 0; + BOOLEAN fgReplyProbeResp = FALSE; + + ASSERT(prSwRfb); + ASSERT(pu4ControlFlags); + + prBssInfo = prAdapter->prAisBssInfo; + + /* 4 <1> Parse Probe Req IE and Get IE ptr (SSID, Supported Rate IE, ...) */ + prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T) prSwRfb->pvHeader; + + u2IELength = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen; + pucIE = (PUINT_8) ((ULONG) prSwRfb->pvHeader + prSwRfb->u2HeaderLen); + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (IE_ID(pucIE) == ELEM_ID_SSID) { + 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 */ + +#if CFG_DISCONN_DEBUG_FEATURE +VOID aisCollectDisconnInfo(IN P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prAisBssInfo; + UINT_32 u4BufLen = 0; + UINT_8 ucWlanIndex; + PUINT_8 pucMacAddr = NULL; + struct AIS_DISCONN_INFO_T *prDisconn = NULL; + + if (prAdapter == NULL) { + DBGLOG(AIS, ERROR, "Null adapter\n"); + return; + } + + if (g_prDisconnInfo == NULL) { + DBGLOG(AIS, ERROR, "Null g_prDisconnInfo\n"); + return; + } + + if (g_DisconnInfoIdx >= MAX_DISCONNECT_RECORD) { + DBGLOG(AIS, ERROR, "Invalid g_DisconnInfoIdx\n"); + return; + } + + prDisconn = g_prDisconnInfo + g_DisconnInfoIdx; + kalMemZero(prDisconn, sizeof(struct AIS_DISCONN_INFO_T)); + + prAisBssInfo = prAdapter->prAisBssInfo; + + do_gettimeofday(&prDisconn->tv); + + prDisconn->ucTrigger = g_rDisconnInfoTemp.ucTrigger; + prDisconn->ucDisConnReason = prAisBssInfo->ucReasonOfDisconnect; + prDisconn->ucBcnTimeoutReason = g_rDisconnInfoTemp.ucBcnTimeoutReason; + prDisconn->ucDisassocReason = g_rDisconnInfoTemp.ucDisassocReason; + prDisconn->u2DisassocSeqNum = g_rDisconnInfoTemp.u2DisassocSeqNum; + +#if CFG_SUPPORT_ADVANCE_CONTROL + /* Query Average noise info */ + prDisconn->rNoise.u2Type = CMD_NOISE_HISTOGRAM_TYPE; + prDisconn->rNoise.u2Len = sizeof(struct CMD_NOISE_HISTOGRAM_REPORT); + prDisconn->rNoise.ucAction = CMD_NOISE_HISTOGRAM_GET; + _wlanoidAdvCtrl(prAdapter, &prDisconn->rNoise, + sizeof(struct CMD_NOISE_HISTOGRAM_REPORT), &u4BufLen, FALSE); +#endif + + /* Query Beacon RSSI info */ + _wlanoidQueryRssi(prAdapter, &prDisconn->rBcnRssi, + sizeof(PARAM_RSSI), &u4BufLen, FALSE); + + /* Store target sta rec and get wlan index */ + if (prAisBssInfo->prStaRecOfAP) { + kalMemCopy(&prDisconn->rStaRec, + prAisBssInfo->prStaRecOfAP, + sizeof(STA_RECORD_T)); + + ucWlanIndex = prAisBssInfo->prStaRecOfAP->ucWlanIndex; + } else if (!wlanGetWlanIdxByAddress(prAdapter, NULL, &ucWlanIndex)) { + DBGLOG(AIS, LOUD, "Null wlan index\n"); + goto leave; + } + + /* Query WTBL info */ + prDisconn->rHwInfo.u4Index = ucWlanIndex; + prDisconn->rHwInfo.rWtblRxCounter.fgRxCCSel = FALSE; + _wlanoidQueryWlanInfo(prAdapter, &prDisconn->rHwInfo, + sizeof(PARAM_HW_WLAN_INFO_T), &u4BufLen, FALSE); + + /* Query Statistics info */ + prDisconn->rStaStatistics.ucResetCounter = FALSE; + pucMacAddr = wlanGetStaAddrByWlanIdx(prAdapter, ucWlanIndex); + + if (pucMacAddr) { + COPY_MAC_ADDR(prDisconn->rStaStatistics.aucMacAddr, + pucMacAddr); + + _wlanoidQueryStaStatistics(prAdapter, + &prDisconn->rStaStatistics, + sizeof(PARAM_GET_STA_STA_STATISTICS), + &u4BufLen, FALSE); + } + +leave: + g_DisconnInfoIdx = (g_DisconnInfoIdx + 1) % MAX_DISCONNECT_RECORD; + + /* Default value */ + kalMemZero(&g_rDisconnInfoTemp, sizeof(struct AIS_DISCONN_INFO_T)); + g_rDisconnInfoTemp.ucBcnTimeoutReason = BEACON_TIMEOUT_DUE_2_RESERVED; + g_rDisconnInfoTemp.u2DisassocSeqNum = 0xFFFF; +} +#endif /* CFG_DISCONN_DEBUG_FEATURE */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prAisBssInfo = prAdapter->prAisBssInfo; + + nicPmIndicateBssAbort(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + +#if CFG_SUPPORT_ADHOC + if (prAisBssInfo->fgIsBeaconActivated) { + nicUpdateBeaconIETemplate(prAdapter, + IE_UPD_METHOD_DELETE_ALL, prAdapter->prAisBssInfo->ucBssIndex, 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 (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + + { + if (prAdapter->rWifiVar.ucTpTestMode != ENUM_TP_TEST_MODE_NORMAL) + nicEnterTPTestMode(prAdapter, TEST_MODE_NONE); + +#if 0 + if (prAdapter->rWifiVar.ucSigmaTestMode) + nicEnterTPTestMode(prAdapter, TEST_MODE_NONE); +#endif + } + + 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 (prAisBssInfo->eCurrentOPMode != OP_MODE_IBSS) + prAisBssInfo->fgHoldSameBssidForIBSS = FALSE; + } else { + prAisBssInfo->fgHoldSameBssidForIBSS = FALSE; + } + } else { + prAisBssInfo->fgHoldSameBssidForIBSS = FALSE; + } + +#if CFG_DISCONN_DEBUG_FEATURE + aisCollectDisconnInfo(prAdapter); +#endif + + /* 4 <4> Change Media State immediately. */ + if (prAisBssInfo->ucReasonOfDisconnect != DISCONNECT_REASON_CODE_REASSOCIATION) { + aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + + /* 4 <4.1> sync. with firmware */ + nicUpdateBss(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + } + + if (!fgDelayIndication) { + /* 4 <5> Deactivate previous AP's STA_RECORD_T or all Clients in Driver if have. */ + GLUE_ACQUIRE_SPIN_LOCK(prAdapter->prGlueInfo, + SPIN_LOCK_STA_RECOFAP); + if (prAisBssInfo->prStaRecOfAP) { + /* cnmStaRecChangeState(prAdapter, prAisBssInfo->prStaRecOfAP, STA_STATE_1); */ + prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; + } + GLUE_RELEASE_SPIN_LOCK(prAdapter->prGlueInfo, + SPIN_LOCK_STA_RECOFAP); + } +#if CFG_SUPPORT_ROAMING + roamingFsmRunEventAbort(prAdapter); + + /* clear pending roaming connection request */ + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_SEARCH, TRUE); + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, TRUE); +#endif /* CFG_SUPPORT_ROAMING */ + + /* 4 <6> Indicate Disconnected Event to Host */ + aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED, fgDelayIndication); + + + /* 4 <7> Trigger AIS FSM */ + aisFsmSteps(prAdapter, AIS_STATE_IDLE); +} /* end of aisFsmDisconnect() */ + +static VOID aisFsmRunEventScanDoneTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParam) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + P_CONNECTION_SETTINGS_T prConnSettings; + + DEBUGFUNC("aisFsmRunEventScanDoneTimeOut()"); + + ASSERT(prAdapter); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + DBGLOG(AIS, STATE, "aisFsmRunEventScanDoneTimeOut Current[%d]\n", prAisFsmInfo->eCurrentState); + + /* report all scanned frames to upper layer to avoid scanned frame is timeout */ + /* must be put before kalScanDone */ +/* scanReportBss2Cfg80211(prAdapter,BSS_TYPE_INFRASTRUCTURE,NULL); */ + + prConnSettings->fgIsScanReqIssued = FALSE; + kalScanDone(prAdapter->prGlueInfo, KAL_NETWORK_TYPE_AIS_INDEX, WLAN_STATUS_SUCCESS); + eNextState = prAisFsmInfo->eCurrentState; + + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_SCAN: + prAisFsmInfo->u4ScanIELength = 0; + eNextState = AIS_STATE_IDLE; + break; + case AIS_STATE_ONLINE_SCAN: + /* reset scan IE buffer */ + prAisFsmInfo->u4ScanIELength = 0; +#if CFG_SUPPORT_ROAMING + eNextState = aisFsmRoamingScanResultsUpdate(prAdapter); +#else + eNextState = AIS_STATE_NORMAL_TR; +#endif /* CFG_SUPPORT_ROAMING */ + break; + default: + break; + } + + /* try to stop scan in CONNSYS */ + aisFsmStateAbort_SCAN(prAdapter); + + /* wlanQueryDebugCode(prAdapter); *//* display current SCAN FSM in FW, debug use */ + + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); + +} /* end of aisFsmBGSleepTimeout() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Background Scan Time-Out" to AIS FSM. +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventBGSleepTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + + DEBUGFUNC("aisFsmRunEventBGSleepTimeOut()"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + eNextState = prAisFsmInfo->eCurrentState; + + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_WAIT_FOR_NEXT_SCAN: + DBGLOG(AIS, LOUD, "EVENT - SCAN TIMER: Idle End - Current Time = %u\n", kalGetTimeTick()); + + eNextState = AIS_STATE_LOOKING_FOR; + + SET_NET_PWR_STATE_ACTIVE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + + break; + + default: + break; + } + + /* Call aisFsmSteps() when we are going to change AIS STATE */ + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); +} /* end of aisFsmBGSleepTimeout() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "IBSS ALONE Time-Out" to AIS FSM. +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventIbssAloneTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + + DEBUGFUNC("aisFsmRunEventIbssAloneTimeOut()"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + eNextState = prAisFsmInfo->eCurrentState; + + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_IBSS_ALONE: + + /* There is no one participate in our AdHoc during this TIMEOUT Interval + * so go back to search for a valid IBSS again. + */ + + DBGLOG(AIS, LOUD, "EVENT-IBSS ALONE TIMER: Start pairing\n"); + + prAisFsmInfo->fgTryScan = TRUE; + + /* abort timer */ + aisFsmReleaseCh(prAdapter); + + /* Pull back to SEARCH to find candidate again */ + eNextState = AIS_STATE_SEARCH; + + break; + + default: + break; + } + + /* Call aisFsmSteps() when we are going to change AIS STATE */ + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); +} /* end of aisIbssAloneTimeOut() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Join Time-Out" to AIS FSM. +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventJoinTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr) +{ + P_BSS_INFO_T prAisBssInfo; + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + OS_SYSTIME rCurrentTime; + + DEBUGFUNC("aisFsmRunEventJoinTimeout()"); + + prAisBssInfo = prAdapter->prAisBssInfo; + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + eNextState = prAisFsmInfo->eCurrentState; + + GET_CURRENT_SYSTIME(&rCurrentTime); + + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_JOIN: + DBGLOG(AIS, LOUD, "EVENT- JOIN TIMEOUT\n"); + + /* 1. Do abort JOIN */ + aisFsmStateAbort_JOIN(prAdapter); + + /* 2. Increase Join Failure Count */ + prAisFsmInfo->prTargetStaRec->ucJoinFailureCount++; + + 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 if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + /* roaming cases */ + /* 3.2 Retreat to AIS_STATE_WAIT_FOR_NEXT_SCAN state for next try */ + eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; + } else + if (!CHECK_FOR_TIMEOUT + (rCurrentTime, prAisFsmInfo->rJoinReqTime, SEC_TO_SYSTIME(AIS_JOIN_TIMEOUT))) { + /* 3.3 Retreat to AIS_STATE_WAIT_FOR_NEXT_SCAN state for next try */ + eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; + } else { + /* 3.4 Retreat to AIS_STATE_JOIN_FAILURE to terminate join operation */ + eNextState = AIS_STATE_JOIN_FAILURE; + } + + break; + + case AIS_STATE_NORMAL_TR: + /* 1. release channel */ + aisFsmReleaseCh(prAdapter); + prAisFsmInfo->fgIsInfraChannelFinished = TRUE; + + /* 2. process if there is pending scan */ + if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, TRUE) == TRUE) { + wlanClearScanningResult(prAdapter); + eNextState = AIS_STATE_ONLINE_SCAN; + } + + break; + + default: + /* release channel */ + aisFsmReleaseCh(prAdapter); + break; + + } + + /* Call aisFsmSteps() when we are going to change AIS STATE */ + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); +} /* end of aisFsmRunEventJoinTimeout() */ + +VOID aisFsmRunEventDeauthTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr) +{ + aisDeauthXmitComplete(prAdapter, NULL, TX_RESULT_LIFE_TIMEOUT); +} + +#if CFG_SUPPORT_LAST_SEC_MCS_INFO +VOID aisRxMcsCollectionTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr) +{ + static UINT_8 ucSmapleCnt; + UINT_8 ucStaIdx = 0; + + if (prAdapter->prAisBssInfo->prStaRecOfAP == NULL) + goto out; + + ucStaIdx = prAdapter->prAisBssInfo->prStaRecOfAP->ucIndex; + + if (prAdapter->arStaRec[ucStaIdx].fgIsValid && prAdapter->arStaRec[ucStaIdx].fgIsInUse) { + prAdapter->arStaRec[ucStaIdx].au4RxVect0Que[ucSmapleCnt] = prAdapter->arStaRec[ucStaIdx].u4RxVector0; + prAdapter->arStaRec[ucStaIdx].au4RxVect1Que[ucSmapleCnt] = prAdapter->arStaRec[ucStaIdx].u4RxVector1; + ucSmapleCnt = (ucSmapleCnt + 1) % MCS_INFO_SAMPLE_CNT; + } + +out: + cnmTimerStartTimer(prAdapter, &prAdapter->rRxMcsInfoTimer, 100); +} +#endif + +#if defined(CFG_TEST_MGMT_FSM) && (CFG_TEST_MGMT_FSM != 0) +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID aisTest(VOID) +{ + P_MSG_AIS_ABORT_T prAisAbortMsg; + P_CONNECTION_SETTINGS_T prConnSettings; + UINT_8 aucSSID[] = "pci-11n"; + UINT_8 ucSSIDLen = 7; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* Set Connection Request Issued Flag */ + prConnSettings->fgIsConnReqIssued = TRUE; + prConnSettings->ucSSIDLen = ucSSIDLen; + kalMemCopy(prConnSettings->aucSSID, aucSSID, ucSSIDLen); + + prAisAbortMsg = (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); + if (!prAisAbortMsg) { + + ASSERT(0); /* Can't trigger SCAN FSM */ + return; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_HEM_AIS_FSM_ABORT; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); + + wifi_send_msg(INDX_WIFI, MSG_ID_WIFI_IST, 0); +} +#endif /* CFG_TEST_MGMT_FSM */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to handle OID_802_11_BSSID_LIST_SCAN +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[in] prSsid Pointer of SSID_T if specified +* \param[in] pucIe Pointer to buffer of extra information elements to be attached +* \param[in] u4IeLength Length of information elements +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmScanRequest(IN P_ADAPTER_T prAdapter, IN P_PARAM_SSID_T prSsid, IN PUINT_8 pucIe, IN UINT_32 u4IeLength) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_INFO_T prAisBssInfo; + P_AIS_FSM_INFO_T prAisFsmInfo; + + DEBUGFUNC("aisFsmScanRequest()"); + + ASSERT(prAdapter); + ASSERT(u4IeLength <= MAX_IE_LENGTH); + + prAisBssInfo = prAdapter->prAisBssInfo; + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + if (!prConnSettings->fgIsScanReqIssued) { + prConnSettings->fgIsScanReqIssued = TRUE; + + if (prSsid == NULL) { + prAisFsmInfo->ucScanSSIDNum = 0; + } else { + prAisFsmInfo->ucScanSSIDNum = 1; + + COPY_SSID(prAisFsmInfo->arScanSSID[0].aucSsid, + prAisFsmInfo->arScanSSID[0].u4SsidLen, prSsid->aucSsid, prSsid->u4SsidLen); + } + + if (u4IeLength > 0) { + prAisFsmInfo->u4ScanIELength = u4IeLength; + kalMemCopy(prAisFsmInfo->aucScanIEBuf, pucIe, u4IeLength); + } else { + prAisFsmInfo->u4ScanIELength = 0; + } + + if (prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR) { + if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE + && prAisFsmInfo->fgIsInfraChannelFinished == FALSE) { + /* 802.1x might not finished yet, pend it for later handling .. */ + aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); + } else { + if (prAisFsmInfo->fgIsChannelGranted == TRUE) { + DBGLOG(AIS, WARN, + "Scan Request with channel granted for join operation: %d, %d", + prAisFsmInfo->fgIsChannelGranted, prAisFsmInfo->fgIsChannelRequested); + } + + /* start online scan */ + wlanClearScanningResult(prAdapter); + aisFsmSteps(prAdapter, AIS_STATE_ONLINE_SCAN); + } + } else if (prAisFsmInfo->eCurrentState == AIS_STATE_IDLE) { + wlanClearScanningResult(prAdapter); + aisFsmSteps(prAdapter, AIS_STATE_SCAN); + } else { + aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); + } + } else { + DBGLOG(AIS, WARN, "Scan Request dropped. (state: %d)\n", prAisFsmInfo->eCurrentState); + } +} /* end of aisFsmScanRequest() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to handle OID_802_11_BSSID_LIST_SCAN +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[in] ucSsidNum Number of SSID +* \param[in] prSsid Pointer to the array 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 +aisFsmScanRequestAdv(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucSsidNum, IN P_PARAM_SSID_T prSsid, + IN UINT_8 ucChannelListNum, IN P_RF_CHANNEL_INFO_T prChnlInfoList, + IN PUINT_8 pucIe, IN UINT_32 u4IeLength) +{ + UINT_32 i; + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_INFO_T prAisBssInfo; + P_AIS_FSM_INFO_T prAisFsmInfo; + + DEBUGFUNC("aisFsmScanRequestAdv()"); + + ASSERT(prAdapter); + ASSERT(ucSsidNum <= SCN_SSID_MAX_NUM); + ASSERT(u4IeLength <= MAX_IE_LENGTH); + + prAisBssInfo = prAdapter->prAisBssInfo; + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + if (!prConnSettings->fgIsScanReqIssued) { + prConnSettings->fgIsScanReqIssued = TRUE; + + if (ucSsidNum == 0) { + prAisFsmInfo->ucScanSSIDNum = 0; + } else { + prAisFsmInfo->ucScanSSIDNum = ucSsidNum; + + for (i = 0; i < ucSsidNum; i++) { + COPY_SSID(prAisFsmInfo->arScanSSID[i].aucSsid, + prAisFsmInfo->arScanSSID[i].u4SsidLen, + prSsid[i].aucSsid, prSsid[i].u4SsidLen); + } + } + + if (u4IeLength > 0) { + prAisFsmInfo->u4ScanIELength = u4IeLength; + kalMemCopy(prAisFsmInfo->aucScanIEBuf, pucIe, u4IeLength); + } else { + prAisFsmInfo->u4ScanIELength = 0; + } + +#if CFG_SCAN_CHANNEL_SPECIFIED + if (ucChannelListNum) { + prAisFsmInfo->ucScanChannelListNum = ucChannelListNum; + kalMemCopy(prAisFsmInfo->arScanChnlInfoList, prChnlInfoList, + sizeof(RF_CHANNEL_INFO_T) * prAisFsmInfo->ucScanChannelListNum); + } else + prAisFsmInfo->ucScanChannelListNum = 0; +#endif + + if (prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR) { + if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE + && prAisFsmInfo->fgIsInfraChannelFinished == FALSE) { + /* 802.1x might not finished yet, pend it for later handling .. */ + aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); + } else { + if (prAisFsmInfo->fgIsChannelGranted == TRUE) { + DBGLOG(AIS, WARN, + "Scan Request with channel granted for join operation: %d, %d", + prAisFsmInfo->fgIsChannelGranted, prAisFsmInfo->fgIsChannelRequested); + } + + /* start online scan */ + wlanClearScanningResult(prAdapter); + aisFsmSteps(prAdapter, AIS_STATE_ONLINE_SCAN); + } + } else if (prAisFsmInfo->eCurrentState == AIS_STATE_IDLE) { + wlanClearScanningResult(prAdapter); + aisFsmSteps(prAdapter, AIS_STATE_SCAN); + } else { + aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); + } + } else { + DBGLOG(AIS, WARN, "Scan Request dropped. (state: %d)\n", prAisFsmInfo->eCurrentState); + } +} /* end of aisFsmScanRequestAdv() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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->prAisBssInfo; + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prMsgChGrant = (P_MSG_CH_GRANT_T) prMsgHdr; + + ucTokenID = prMsgChGrant->ucTokenID; + u4GrantInterval = prMsgChGrant->u4GrantInterval; +#if CFG_SUPPORT_DBDC + if (prAisBssInfo->eDBDCBand == ENUM_BAND_AUTO) + prAisBssInfo->eDBDCBand = prMsgChGrant->eDBDCBand; +#endif + +#if CFG_SISO_SW_DEVELOP + /* Driver record granted CH in BSS info */ + prAisBssInfo->fgIsGranted = TRUE; + prAisBssInfo->eBandGranted = prMsgChGrant->eRfBand; + prAisBssInfo->ucPrimaryChannelGranted = prMsgChGrant->ucPrimaryChannel; +#endif + + /* 1. free message */ + cnmMemFree(prAdapter, prMsgHdr); + + if (prAisFsmInfo->eCurrentState == AIS_STATE_REQ_CHANNEL_JOIN && prAisFsmInfo->ucSeqNumOfChReq == ucTokenID) { + /* 2. channel privilege has been approved */ + prAisFsmInfo->u4ChGrantedInterval = u4GrantInterval; + + /* 3. state transition to join/ibss-alone/ibss-merge */ + /* 3.1 set timeout timer in cases join could not be completed */ + cnmTimerStartTimer(prAdapter, + &prAisFsmInfo->rJoinTimeoutTimer, + prAisFsmInfo->u4ChGrantedInterval - AIS_JOIN_CH_GRANT_THRESHOLD); + /* 3.2 set local variable to indicate join timer is ticking */ + prAisFsmInfo->fgIsInfraChannelFinished = FALSE; + + /* 3.3 switch to join state */ + aisFsmSteps(prAdapter, AIS_STATE_JOIN); + + prAisFsmInfo->fgIsChannelGranted = TRUE; + } else if (prAisFsmInfo->eCurrentState == AIS_STATE_REQ_REMAIN_ON_CHANNEL && + prAisFsmInfo->ucSeqNumOfChReq == ucTokenID) { + /* 2. channel privilege has been approved */ + prAisFsmInfo->u4ChGrantedInterval = u4GrantInterval; + + /* 3.1 set timeout timer in cases upper layer cancel_remain_on_channel never comes */ + cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer, prAisFsmInfo->u4ChGrantedInterval); + + /* 3.2 switch to remain_on_channel state */ + aisFsmSteps(prAdapter, AIS_STATE_REMAIN_ON_CHANNEL); + + /* 3.3. indicate upper layer for channel ready */ + kalReadyOnChannel(prAdapter->prGlueInfo, + prAisFsmInfo->rChReqInfo.u8Cookie, + prAisFsmInfo->rChReqInfo.eBand, + prAisFsmInfo->rChReqInfo.eSco, + prAisFsmInfo->rChReqInfo.ucChannelNum, prAisFsmInfo->rChReqInfo.u4DurationMs); + + prAisFsmInfo->fgIsChannelGranted = TRUE; + } else { /* mismatched grant */ + /* 2. return channel privilege to CNM immediately */ + aisFsmReleaseCh(prAdapter); + } +} /* end of aisFsmRunEventChGrant() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is to inform CNM that channel privilege +* has been released +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmReleaseCh(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_MSG_CH_ABORT_T prMsgChAbort; + + ASSERT(prAdapter); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + if (prAisFsmInfo->fgIsChannelGranted == TRUE || prAisFsmInfo->fgIsChannelRequested == TRUE) { + + prAisFsmInfo->fgIsChannelRequested = FALSE; + prAisFsmInfo->fgIsChannelGranted = FALSE; + + /* 1. return channel privilege to CNM immediately */ + prMsgChAbort = (P_MSG_CH_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_ABORT_T)); + if (!prMsgChAbort) { + ASSERT(0); /* Can't release Channel to CNM */ + return; + } + + prMsgChAbort->rMsgHdr.eMsgId = MID_MNY_CNM_CH_ABORT; + prMsgChAbort->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + prMsgChAbort->ucTokenID = prAisFsmInfo->ucSeqNumOfChReq; +#if CFG_SUPPORT_DBDC + prMsgChAbort->eDBDCBand = ENUM_BAND_AUTO; +#endif /*CFG_SUPPORT_DBDC*/ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChAbort, MSG_SEND_METHOD_BUF); + } +} /* end of aisFsmReleaseCh() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is to inform AIS that corresponding beacon has not +* been received for a while and probing is not successful +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID aisBssBeaconTimeout(IN P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prAisBssInfo; + BOOLEAN fgDoAbortIndication = FALSE; + P_CONNECTION_SETTINGS_T prConnSettings; + + ASSERT(prAdapter); + + prAisBssInfo = prAdapter->prAisBssInfo; + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* 4 <1> Diagnose Connection for Beacon Timeout Event */ + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + P_STA_RECORD_T prStaRec = prAisBssInfo->prStaRecOfAP; + + if (prStaRec) + fgDoAbortIndication = TRUE; + + } else if (prAisBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + fgDoAbortIndication = TRUE; + } + } + /* 4 <2> invoke abort handler */ + if (fgDoAbortIndication) { +#if CFG_DISCONN_DEBUG_FEATURE + g_rDisconnInfoTemp.ucTrigger = + DISCONNECT_TRIGGER_PASSIVE; +#endif + DBGLOG(AIS, EVENT, "aisBssBeaconTimeout\n"); +#if CFG_SUPPORT_ROAMING + prConnSettings->fgIsDisconnectedByNonRequest = FALSE; + aisFsmStateAbort(prAdapter, DISCONNECT_REASON_CODE_RADIO_LOST, + TRUE); +#else + prConnSettings->fgIsDisconnectedByNonRequest = TRUE; + aisFsmStateAbort(prAdapter, DISCONNECT_REASON_CODE_RADIO_LOST, + FALSE); +#endif + } +} /* end of aisBssBeaconTimeout() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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 aisBssLinkDown(IN P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prAisBssInfo; + BOOLEAN fgDoAbortIndication = FALSE; + P_CONNECTION_SETTINGS_T prConnSettings; + + ASSERT(prAdapter); + + prAisBssInfo = prAdapter->prAisBssInfo; + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* 4 <1> Diagnose Connection for Beacon Timeout Event */ + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + P_STA_RECORD_T prStaRec = prAisBssInfo->prStaRecOfAP; + + if (prStaRec) + fgDoAbortIndication = TRUE; + + } else if (prAisBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + fgDoAbortIndication = TRUE; + } + } + /* 4 <2> invoke abort handler */ + if (fgDoAbortIndication) { +#if CFG_DISCONN_DEBUG_FEATURE + g_rDisconnInfoTemp.ucTrigger = DISCONNECT_TRIGGER_ACTIVE; +#endif + prConnSettings->fgIsDisconnectedByNonRequest = TRUE; + DBGLOG(AIS, EVENT, "aisBssLinkDown\n"); + aisFsmStateAbort(prAdapter, DISCONNECT_REASON_CODE_DISASSOCIATED, FALSE); + } + + /* kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_SCAN_COMPLETE, NULL, 0); */ +} /* 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 (rTxDoneStatus == TX_RESULT_SUCCESS) + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rDeauthDoneTimer); + + if (prAisFsmInfo->eCurrentState == AIS_STATE_DISCONNECTING) { + DBGLOG(AIS, EVENT, "aisDeauthXmitComplete\n"); + if (rTxDoneStatus != TX_RESULT_DROPPED_IN_DRIVER && rTxDoneStatus != TX_RESULT_QUEUE_CLEARANCE) + 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; + + /* TODO: Stop roaming event in FW */ +#if CFG_SUPPORT_WFD +#if CFG_ENABLE_WIFI_DIRECT + { + /* Check WFD is running */ + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + + prWfdCfgSettings = &(prAdapter->rWifiVar.rWfdConfigureSettings); + if ((prWfdCfgSettings->ucWfdEnable != 0)) { + DBGLOG(ROAMING, INFO, "WFD is running. Stop roaming.\n"); + roamingFsmRunEventRoam(prAdapter); + roamingFsmRunEventFail(prAdapter, ROAMING_FAIL_REASON_NOCANDIDATE); + return; + } + } +#endif +#endif + + /* results are still new */ + if (!u4ReqScan) { + roamingFsmRunEventRoam(prAdapter); + eAisRequest = AIS_REQUEST_ROAMING_CONNECT; + } else { + if (prAisFsmInfo->eCurrentState == AIS_STATE_ONLINE_SCAN + || prAisFsmInfo->eCurrentState == AIS_STATE_LOOKING_FOR) { + eAisRequest = AIS_REQUEST_ROAMING_CONNECT; + } else { + eAisRequest = AIS_REQUEST_ROAMING_SEARCH; + } + } + + if (prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR && prAisFsmInfo->fgIsInfraChannelFinished == TRUE) { + if (eAisRequest == AIS_REQUEST_ROAMING_SEARCH) + aisFsmSteps(prAdapter, AIS_STATE_LOOKING_FOR); + else + aisFsmSteps(prAdapter, AIS_STATE_SEARCH); + } else { + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_SEARCH, TRUE); + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, TRUE); + + aisFsmInsertRequest(prAdapter, eAisRequest); + } +} /* end of aisFsmRunEventRoamingDiscovery() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Update the time of ScanDone for roaming and transit to Roam state. +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +ENUM_AIS_STATE_T aisFsmRoamingScanResultsUpdate(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_ROAMING_INFO_T prRoamingFsmInfo; + ENUM_AIS_STATE_T eNextState; + + DBGLOG(AIS, LOUD, "->aisFsmRoamingScanResultsUpdate()\n"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + roamingFsmScanResultsUpdate(prAdapter); + + eNextState = prAisFsmInfo->eCurrentState; + if (prRoamingFsmInfo->eCurrentState == ROAMING_STATE_DISCOVERY) { + roamingFsmRunEventRoam(prAdapter); + eNextState = AIS_STATE_SEARCH; + } else if (prAisFsmInfo->eCurrentState == AIS_STATE_LOOKING_FOR) { + eNextState = AIS_STATE_SEARCH; + } else if (prAisFsmInfo->eCurrentState == AIS_STATE_ONLINE_SCAN) { + eNextState = AIS_STATE_NORMAL_TR; + } + + return eNextState; +} /* end of aisFsmRoamingScanResultsUpdate() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will modify and update necessary information to firmware +* for disconnection of last AP before switching to roaming bss. +* +* @param IN prAdapter Pointer to the Adapter structure. +* prTargetStaRec Target of StaRec of roaming +* +* @retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRoamingDisconnectPrevAP(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prTargetStaRec) +{ + P_BSS_INFO_T prAisBssInfo; + + DBGLOG(AIS, EVENT, "aisFsmRoamingDisconnectPrevAP()"); + + ASSERT(prAdapter); + + prAisBssInfo = prAdapter->prAisBssInfo; + + nicPmIndicateBssAbort(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + + /* 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 (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) + scanRemoveConnFlagOfBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); + + /* 4 <4> Change Media State immediately. */ + aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + + /* 4 <4.1> sync. with firmware */ + prTargetStaRec->ucBssIndex = (MAX_BSS_INDEX + 1); /* Virtial BSSID */ + nicUpdateBss(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + + secRemoveBssBcEntry(prAdapter, prAisBssInfo, TRUE); + prTargetStaRec->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; +} /* 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->prAisBssInfo; + + /* 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); */ + cnmStaRecFree(prAdapter, prAisBssInfo->prStaRecOfAP); + } + + /* 4 <1.4> Update BSS_INFO_T */ + aisUpdateBssInfoForJOIN(prAdapter, prStaRec, prAssocRspSwRfb); + + /* 4 <1.3> Activate current AP's STA_RECORD_T in Driver. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + /* 4 <1.6> Indicate Connected Event to Host immediately. */ + /* Require BSSID, Association ID, Beacon Interval.. from AIS_BSS_INFO_T */ + aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, FALSE); +} /* end of aisFsmRoamingUpdateBss() */ + +#endif /* CFG_SUPPORT_ROAMING */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Check if there is any pending request and remove it (optional) +* +* @param prAdapter +* eReqType +* bRemove +* +* @return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN aisFsmIsRequestPending(IN P_ADAPTER_T prAdapter, IN ENUM_AIS_REQUEST_TYPE_T eReqType, IN BOOLEAN bRemove) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_AIS_REQ_HDR_T prPendingReqHdr, prPendingReqHdrNext; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + if (prAisFsmInfo->rPendingReqList.u4NumElem == 0) { + DBGLOG(AIS, LOUD, "prAisFsmInfo->rPendingReqList is null.\n"); + return FALSE; + } + + /* traverse through pending request list */ + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_REQ_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); + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_REQ_LIST); + return TRUE; + } + } + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_REQ_LIST); + + 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; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_REQ_LIST); + LINK_REMOVE_HEAD(&(prAisFsmInfo->rPendingReqList), prPendingReqHdr, P_AIS_REQ_HDR_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_REQ_LIST); + + 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; + + KAL_SPIN_LOCK_DECLARATION(); + + 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 */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_REQ_LIST); + LINK_INSERT_TAIL(&prAisFsmInfo->rPendingReqList, &prAisReq->rLinkEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_REQ_LIST); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Flush all pending requests +* +* @param prAdapter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmFlushRequest(IN P_ADAPTER_T prAdapter) +{ + P_AIS_REQ_HDR_T prAisReq; + + ASSERT(prAdapter); + + while ((prAisReq = aisFsmGetNextRequest(prAdapter)) != NULL) + cnmMemFree(prAdapter, prAisReq); +} + +VOID aisFsmRunEventRemainOnChannel(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_REMAIN_ON_CHANNEL_T prRemainOnChannel; + P_AIS_FSM_INFO_T prAisFsmInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + + DEBUGFUNC("aisFsmRunEventRemainOnChannel()"); + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + prRemainOnChannel = (P_MSG_REMAIN_ON_CHANNEL_T) prMsgHdr; + + /* record parameters */ + prAisFsmInfo->rChReqInfo.eBand = prRemainOnChannel->eBand; + prAisFsmInfo->rChReqInfo.eSco = prRemainOnChannel->eSco; + prAisFsmInfo->rChReqInfo.ucChannelNum = prRemainOnChannel->ucChannelNum; + prAisFsmInfo->rChReqInfo.u4DurationMs = prRemainOnChannel->u4DurationMs; + prAisFsmInfo->rChReqInfo.u8Cookie = prRemainOnChannel->u8Cookie; + + if (prAisFsmInfo->eCurrentState == AIS_STATE_IDLE || prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR) { + /* transit to next state */ + aisFsmSteps(prAdapter, AIS_STATE_REQ_REMAIN_ON_CHANNEL); + } else { + aisFsmInsertRequest(prAdapter, AIS_REQUEST_REMAIN_ON_CHANNEL); + } + + /* free messages */ + cnmMemFree(prAdapter, prMsgHdr); +} + +VOID aisFsmRunEventCancelRemainOnChannel(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_MSG_CANCEL_REMAIN_ON_CHANNEL_T prCancelRemainOnChannel; + + ASSERT(prAdapter); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = prAdapter->prAisBssInfo; + + prCancelRemainOnChannel = (P_MSG_CANCEL_REMAIN_ON_CHANNEL_T) prMsgHdr; + + /* 1. Check the cookie first */ + if (prCancelRemainOnChannel->u8Cookie == prAisFsmInfo->rChReqInfo.u8Cookie) { + + /* 2. release channel privilege/request */ + if (prAisFsmInfo->eCurrentState == AIS_STATE_REQ_REMAIN_ON_CHANNEL) { + /* 2.1 elease channel */ + aisFsmReleaseCh(prAdapter); + } else if (prAisFsmInfo->eCurrentState == AIS_STATE_REMAIN_ON_CHANNEL) { + /* 2.1 release channel */ + aisFsmReleaseCh(prAdapter); + + /* 2.2 stop channel timeout timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer); + } + + /* 3. clear pending request of remain_on_channel */ + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_REMAIN_ON_CHANNEL, TRUE); + + /* 4. decide which state to retreat */ + if (prAisFsmInfo->eCurrentState == + AIS_STATE_REQ_REMAIN_ON_CHANNEL || + prAisFsmInfo->eCurrentState == + AIS_STATE_REMAIN_ON_CHANNEL) { + if (prAisBssInfo->eConnectionState == + PARAM_MEDIA_STATE_CONNECTED) + aisFsmSteps(prAdapter, AIS_STATE_NORMAL_TR); + else + aisFsmSteps(prAdapter, AIS_STATE_IDLE); + } + } + + /* 5. free message */ + cnmMemFree(prAdapter, prMsgHdr); +} + +VOID aisFsmRunEventMgmtFrameTx(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_MSG_MGMT_TX_REQUEST_T prMgmtTxMsg = (P_MSG_MGMT_TX_REQUEST_T) NULL; + + do { + ASSERT((prAdapter != NULL) && (prMsgHdr != NULL)); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + if (prAisFsmInfo == NULL) + break; + + prMgmtTxMsg = (P_MSG_MGMT_TX_REQUEST_T) prMsgHdr; + + aisFuncTxMgmtFrame(prAdapter, + &prAisFsmInfo->rMgmtTxInfo, prMgmtTxMsg->prMgmtMsduInfo, prMgmtTxMsg->u8Cookie); + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* aisFsmRunEventMgmtFrameTx */ + +VOID aisFsmRunEventChannelTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + + DEBUGFUNC("aisFsmRunEventRemainOnChannel()"); + + ASSERT(prAdapter); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = prAdapter->prAisBssInfo; + + if (prAisFsmInfo->eCurrentState == AIS_STATE_REMAIN_ON_CHANNEL) { + /* 1. release channel */ + aisFsmReleaseCh(prAdapter); + + /* 2. stop channel timeout timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer); + + /* 3. expiration indication to upper layer */ + kalRemainOnChannelExpired(prAdapter->prGlueInfo, + prAisFsmInfo->rChReqInfo.u8Cookie, + prAisFsmInfo->rChReqInfo.eBand, + prAisFsmInfo->rChReqInfo.eSco, prAisFsmInfo->rChReqInfo.ucChannelNum); + + /* 4. decide which state to retreat */ + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) + aisFsmSteps(prAdapter, AIS_STATE_NORMAL_TR); + else + aisFsmSteps(prAdapter, AIS_STATE_IDLE); + + } else { + DBGLOG(AIS, WARN, "Unexpected remain_on_channel timeout event\n"); + DBGLOG(AIS, STATE, "CURRENT State: [%s]\n", apucDebugAisState[prAisFsmInfo->eCurrentState]); + } +} + +WLAN_STATUS +aisFsmRunEventMgmtFrameTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_AIS_MGMT_TX_REQ_INFO_T prMgmtTxReqInfo = (P_AIS_MGMT_TX_REQ_INFO_T) NULL; + BOOLEAN fgIsSuccess = FALSE; + + do { + ASSERT((prAdapter != NULL) && (prMsduInfo != NULL)); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prMgmtTxReqInfo = &(prAisFsmInfo->rMgmtTxInfo); + + if (rTxDoneStatus == TX_RESULT_SUCCESS) + fgIsSuccess = TRUE; + + if (prMgmtTxReqInfo->prMgmtTxMsdu == prMsduInfo) { + kalIndicateMgmtTxStatus(prAdapter->prGlueInfo, + prMgmtTxReqInfo->u8Cookie, + fgIsSuccess, prMsduInfo->prPacket, (UINT_32) prMsduInfo->u2FrameLength); + + prMgmtTxReqInfo->prMgmtTxMsdu = NULL; + } + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; + +} /* aisFsmRunEventMgmtFrameTxDone */ + + +WLAN_STATUS +aisFuncTxMgmtFrame(IN P_ADAPTER_T prAdapter, + IN P_AIS_MGMT_TX_REQ_INFO_T prMgmtTxReqInfo, IN P_MSDU_INFO_T prMgmtTxMsdu, IN UINT_64 u8Cookie) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_MSDU_INFO_T prTxMsduInfo = (P_MSDU_INFO_T) NULL; + P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + + do { + ASSERT((prAdapter != NULL) && (prMgmtTxReqInfo != NULL)); + + if (prMgmtTxReqInfo->fgIsMgmtTxRequested) { + + /* 1. prMgmtTxReqInfo->prMgmtTxMsdu != NULL */ + /* Packet on driver, not done yet, drop it. */ + prTxMsduInfo = prMgmtTxReqInfo->prMgmtTxMsdu; + if (prTxMsduInfo != NULL) { + + kalIndicateMgmtTxStatus(prAdapter->prGlueInfo, + prMgmtTxReqInfo->u8Cookie, + FALSE, + prTxMsduInfo->prPacket, (UINT_32) prTxMsduInfo->u2FrameLength); + + /* Leave it to TX Done handler. */ + /* cnmMgtPktFree(prAdapter, prTxMsduInfo); */ + prMgmtTxReqInfo->prMgmtTxMsdu = NULL; + } + /* 2. prMgmtTxReqInfo->prMgmtTxMsdu == NULL */ + /* Packet transmitted, wait tx done. (cookie issue) */ + } + + ASSERT(prMgmtTxReqInfo->prMgmtTxMsdu == NULL); + + prWlanHdr = (P_WLAN_MAC_HEADER_T) ((ULONG) prMgmtTxMsdu->prPacket + MAC_TX_RESERVED_FIELD); + prStaRec = cnmGetStaRecByAddress(prAdapter, prAdapter->prAisBssInfo->ucBssIndex, prWlanHdr->aucAddr1); + + TX_SET_MMPDU(prAdapter, + prMgmtTxMsdu, + (prStaRec != + NULL) ? (prStaRec->ucBssIndex) : (prAdapter->prAisBssInfo->ucBssIndex), + (prStaRec != NULL) ? (prStaRec->ucIndex) : (STA_REC_INDEX_NOT_FOUND), + WLAN_MAC_MGMT_HEADER_LEN, prMgmtTxMsdu->u2FrameLength, + aisFsmRunEventMgmtFrameTxDone, MSDU_RATE_MODE_AUTO); + prMgmtTxReqInfo->u8Cookie = u8Cookie; + prMgmtTxReqInfo->prMgmtTxMsdu = prMgmtTxMsdu; + prMgmtTxReqInfo->fgIsMgmtTxRequested = TRUE; + + nicTxConfigPktControlFlag(prMgmtTxMsdu, MSDU_CONTROL_FLAG_FORCE_TX, TRUE); + + /* send to TX queue */ + nicTxEnqueueMsdu(prAdapter, prMgmtTxMsdu); + + } while (FALSE); + + return rWlanStatus; +} /* aisFuncTxMgmtFrame */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Action Frame and indicate to uppoer layer +* if the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu4ControlFlags Control flags for replying the Probe Response +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFuncValidateRxActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_AIS_FSM_INFO_T prAisFsmInfo = (P_AIS_FSM_INFO_T) NULL; + + DEBUGFUNC("aisFuncValidateRxActionFrame"); + + do { + + ASSERT((prAdapter != NULL) && (prSwRfb != NULL)); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + if (1 /* prAisFsmInfo->u4AisPacketFilter & PARAM_PACKET_FILTER_ACTION_FRAME */) { + /* Leave the action frame to wpa_supplicant. */ + kalIndicateRxMgmtFrame(prAdapter->prGlueInfo, prSwRfb); + } + + } while (FALSE); + + return; + +} /* aisFuncValidateRxActionFrame */ + + +VOID aisRemoveBlacklistBySource(P_ADAPTER_T prAdapter, enum +_BLACK_LIST_SOURCE source) +{ + P_CONNECTION_SETTINGS_T prConnSettings = + &prAdapter->rWifiVar.rConnSettings; + struct AIS_BLACKLIST_ITEM *prEntry = NULL; + struct AIS_BLACKLIST_ITEM *prNextEntry = NULL; + P_LINK_T prFreeList = &prConnSettings->rBlackList.rFreeLink; + P_LINK_T prBlackList = &prConnSettings->rBlackList.rUsingLink; + + DBGLOG(AIS, INFO, + "Refresh all the BSSes' fgIsInFWKBlacklist to FALSE\n"); + LINK_FOR_EACH_ENTRY_SAFE(prEntry, prNextEntry, prBlackList, rLinkEntry, + struct AIS_BLACKLIST_ITEM) { + prEntry->blackListSource &= ~source; + if (!prEntry->blackListSource) { + LINK_REMOVE_KNOWN_ENTRY(prBlackList, + &prEntry->rLinkEntry); + LINK_INSERT_HEAD(prFreeList, &prEntry->rLinkEntry); + } + } +} + +struct AIS_BLACKLIST_ITEM * +aisAddBlacklist(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc, enum +_BLACK_LIST_SOURCE source) +{ + P_CONNECTION_SETTINGS_T prConnSettings = + &prAdapter->rWifiVar.rConnSettings; + struct AIS_BLACKLIST_ITEM *prEntry = NULL; + P_LINK_T prFreeList = &prConnSettings->rBlackList.rFreeLink; + P_LINK_T prBlackList = &prConnSettings->rBlackList.rUsingLink; + + if (!prBssDesc) { + DBGLOG(AIS, ERROR, "bss descriptor is NULL\n"); + return NULL; + } + if (prBssDesc->prBlack) { + GET_CURRENT_SYSTIME(&prBssDesc->prBlack->rAddTime); + prBssDesc->prBlack->ucCount++; + prBssDesc->prBlack->blackListSource |= source; + DBGLOG(AIS, INFO, "update blacklist for %pM, count %d\n", + prBssDesc->aucBSSID, prBssDesc->prBlack->ucCount); + return prBssDesc->prBlack; + } + + prEntry = aisQueryBlackList(prAdapter, prBssDesc); + + if (prEntry) { + GET_CURRENT_SYSTIME(&prEntry->rAddTime); + prBssDesc->prBlack = prEntry; + prEntry->ucCount++; + prEntry->blackListSource |= source; + DBGLOG(AIS, INFO, "update blacklist for %pM, count %d\n", + prBssDesc->aucBSSID, prEntry->ucCount); + return prEntry; + } + + LINK_REMOVE_HEAD(prFreeList, prEntry, struct AIS_BLACKLIST_ITEM *); + if (!prEntry) + prEntry = kalMemAlloc(sizeof(struct AIS_BLACKLIST_ITEM), + VIR_MEM_TYPE); + if (!prEntry) { + DBGLOG(AIS, WARN, "No memory to allocate\n"); + return NULL; + } + kalMemZero(prEntry, sizeof(*prEntry)); + prEntry->ucCount = 1; + prEntry->blackListSource |= source; + COPY_MAC_ADDR(prEntry->aucBSSID, prBssDesc->aucBSSID); + COPY_SSID(prEntry->aucSSID, prEntry->ucSSIDLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + GET_CURRENT_SYSTIME(&prEntry->rAddTime); + LINK_INSERT_HEAD(prBlackList, &prEntry->rLinkEntry); + prBssDesc->prBlack = prEntry; + + DBGLOG(AIS, INFO, "Add %pM to black List\n", prBssDesc->aucBSSID); + return prEntry; +} + +struct AIS_BLACKLIST_ITEM * +aisAddBlacklistByBssid(P_ADAPTER_T prAdapter, UINT_8 aucBSSID[], enum +_BLACK_LIST_SOURCE source) +{ + P_CONNECTION_SETTINGS_T prConnSettings = + &prAdapter->rWifiVar.rConnSettings; + struct AIS_BLACKLIST_ITEM *prEntry = NULL; + P_LINK_T prFreeList = &prConnSettings->rBlackList.rFreeLink; + P_LINK_T prBlackList = &prConnSettings->rBlackList.rUsingLink; + + prEntry = aisQueryBlackListByBssid(prAdapter, aucBSSID); + + if (prEntry) { + GET_CURRENT_SYSTIME(&prEntry->rAddTime); + prEntry->ucCount++; + prEntry->blackListSource |= source; + DBGLOG(AIS, INFO, "update blacklist for %pM, count %d\n", + aucBSSID, prEntry->ucCount); + return prEntry; + } + + LINK_REMOVE_HEAD(prFreeList, prEntry, struct AIS_BLACKLIST_ITEM *); + if (!prEntry) + prEntry = kalMemAlloc(sizeof(struct AIS_BLACKLIST_ITEM), + VIR_MEM_TYPE); + if (!prEntry) { + DBGLOG(AIS, WARN, "No memory to allocate\n"); + return NULL; + } + kalMemZero(prEntry, sizeof(*prEntry)); + prEntry->ucCount = 1; + prEntry->blackListSource |= source; + COPY_MAC_ADDR(prEntry->aucBSSID, aucBSSID); + COPY_SSID(prEntry->aucSSID, prEntry->ucSSIDLen, prConnSettings->aucSSID, +prConnSettings->ucSSIDLen); + GET_CURRENT_SYSTIME(&prEntry->rAddTime); + LINK_INSERT_HEAD(prBlackList, &prEntry->rLinkEntry); + + DBGLOG(AIS, INFO, "Add %pM to black List\n", aucBSSID); + return prEntry; +} +VOID aisRemoveBlackList(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc, enum +_BLACK_LIST_SOURCE source) +{ + P_CONNECTION_SETTINGS_T prConnSettings = + &prAdapter->rWifiVar.rConnSettings; + struct AIS_BLACKLIST_ITEM *prEntry = NULL; + P_LINK_T prFreeList = &prConnSettings->rBlackList.rFreeLink; + P_LINK_T prBlackList = &prConnSettings->rBlackList.rUsingLink; + + prEntry = aisQueryBlackList(prAdapter, prBssDesc); + if (!prEntry) + return; + prEntry->blackListSource &= ~source; + + if (!prEntry->blackListSource) { + LINK_REMOVE_KNOWN_ENTRY(prBlackList, &prEntry->rLinkEntry); + LINK_INSERT_HEAD(prFreeList, &prEntry->rLinkEntry); + prBssDesc->prBlack = NULL; + DBGLOG(AIS, INFO, "Remove %pM from blacklist\n", + prBssDesc->aucBSSID); + } +} + +struct AIS_BLACKLIST_ITEM * +aisQueryBlackList(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc) +{ + P_CONNECTION_SETTINGS_T prConnSettings = + &prAdapter->rWifiVar.rConnSettings; + struct AIS_BLACKLIST_ITEM *prEntry = NULL; + P_LINK_T prBlackList = &prConnSettings->rBlackList.rUsingLink; + + if (!prBssDesc) + return NULL; + else if (prBssDesc->prBlack) + return prBssDesc->prBlack; + + LINK_FOR_EACH_ENTRY(prEntry, prBlackList, rLinkEntry, struct +AIS_BLACKLIST_ITEM) { + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prEntry->aucBSSID) && + EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, + prEntry->aucSSID, prEntry->ucSSIDLen)) { + prBssDesc->prBlack = prEntry; + return prEntry; + } + } + DBGLOG(AIS, TRACE, "%pM is not in blacklist\n", prBssDesc->aucBSSID); + return NULL; +} + +struct AIS_BLACKLIST_ITEM * +aisQueryBlackListByBssid(P_ADAPTER_T prAdapter, UINT_8 aucBSSID[]) +{ + P_CONNECTION_SETTINGS_T prConnSettings = + &prAdapter->rWifiVar.rConnSettings; + struct AIS_BLACKLIST_ITEM *prEntry = NULL; + P_LINK_T prBlackList = &prConnSettings->rBlackList.rUsingLink; + + LINK_FOR_EACH_ENTRY(prEntry, prBlackList, rLinkEntry, struct +AIS_BLACKLIST_ITEM) { + if (EQUAL_MAC_ADDR(aucBSSID, prEntry->aucBSSID) && + EQUAL_SSID(prConnSettings->aucSSID, + prConnSettings->ucSSIDLen, + prEntry->aucSSID, prEntry->ucSSIDLen)) + return prEntry; + } + DBGLOG(AIS, TRACE, "%pM is not in blacklist\n", aucBSSID); + return NULL; +} + +VOID aisRemoveTimeoutBlacklist(P_ADAPTER_T prAdapter) +{ + P_CONNECTION_SETTINGS_T prConnSettings = + &prAdapter->rWifiVar.rConnSettings; + struct AIS_BLACKLIST_ITEM *prEntry = NULL; + struct AIS_BLACKLIST_ITEM *prNextEntry = NULL; + P_LINK_T prBlackList = &prConnSettings->rBlackList.rUsingLink; + P_LINK_T prFreeList = &prConnSettings->rBlackList.rFreeLink; + OS_SYSTIME rCurrent; + + GET_CURRENT_SYSTIME(&rCurrent); + + LINK_FOR_EACH_ENTRY_SAFE(prEntry, prNextEntry, prBlackList, rLinkEntry, +struct AIS_BLACKLIST_ITEM) { + if (prEntry->blackListSource & AIS_BLACK_LIST_FROM_FWK) + continue; + if (!CHECK_FOR_TIMEOUT(rCurrent, prEntry->rAddTime, SEC_TO_MSEC( +AIS_BLACKLIST_TIMEOUT))) + continue; + LINK_REMOVE_KNOWN_ENTRY(prBlackList, &prEntry->rLinkEntry); + LINK_INSERT_HEAD(prFreeList, &prEntry->rLinkEntry); + } +} + +static VOID aisRemoveDisappearedBlacklist(P_ADAPTER_T prAdapter) +{ + P_CONNECTION_SETTINGS_T prConnSettings = + &prAdapter->rWifiVar.rConnSettings; + struct AIS_BLACKLIST_ITEM *prEntry = NULL; + struct AIS_BLACKLIST_ITEM *prNextEntry = NULL; + P_LINK_T prBlackList = &prConnSettings->rBlackList.rUsingLink; + P_LINK_T prFreeList = &prConnSettings->rBlackList.rFreeLink; + P_BSS_DESC_T prBssDesc = NULL; + P_LINK_T prBSSDescList = &prAdapter->rWifiVar.rScanInfo.rBSSDescList; + UINT_64 u8Current = kalGetBootTime(); + BOOLEAN fgDisappeared = TRUE; + + LINK_FOR_EACH_ENTRY_SAFE(prEntry, prNextEntry, prBlackList, rLinkEntry, +struct AIS_BLACKLIST_ITEM) { + fgDisappeared = TRUE; + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, + rLinkEntry, BSS_DESC_T) { + if (prBssDesc->prBlack == prEntry + || (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, + prEntry->aucBSSID) && + EQUAL_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, + prEntry->aucSSID, prEntry->ucSSIDLen))) { + fgDisappeared = FALSE; + break; + } + } + if (!fgDisappeared + || (u8Current - prEntry->u8DisapperTime) + < 600 * USEC_PER_SEC) + continue; + DBGLOG(AIS, INFO, "Remove disappeared blacklist %s %pM\n", + prEntry->aucSSID, prEntry->aucBSSID); + LINK_REMOVE_KNOWN_ENTRY(prBlackList, &prEntry->rLinkEntry); + LINK_INSERT_HEAD(prFreeList, &prEntry->rLinkEntry); + } +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/assoc.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/assoc.c new file mode 100644 index 0000000000000..be0bdd9435cc9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/assoc.c @@ -0,0 +1,1721 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/assoc.c#5 +*/ + +/*! \file "assoc.c" +* \brief This file includes the 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 +******************************************************************************** +*/ +APPEND_VAR_IE_ENTRY_T txAssocReqIETable[] = { +#if CFG_SUPPORT_SPEC_MGMT + {(ELEM_HDR_LEN + ELEM_MAX_LEN_POWER_CAP), NULL, rlmReqGeneratePowerCapIE} + , /* 33 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_SUPPORTED_CHANNELS), NULL, rlmReqGenerateSupportedChIE} + , /* 36 */ +#endif + {(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_SUPPORT_PASSPOINT + {(ELEM_HDR_LEN + ELEM_MAX_LEN_INTERWORKING), NULL, hs20GenerateInterworkingIE} + , /* 107 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_ROAMING_CONSORTIUM), NULL, hs20GenerateRoamingConsortiumIE} + , /* 111 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_HS20_INDICATION), NULL, hs20GenerateHS20IE} + , /* 221 */ +#endif /* CFG_SUPPORT_PASSPOINT */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP), NULL, rlmReqGenerateExtCapIE} + , /* 127 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_INFO), NULL, mqmGenerateWmmInfoIE} + , /* 221 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_RSN), NULL, rsnGenerateRSNIE} + , /* 48 */ +#if CFG_SUPPORT_802_11AC + {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP), NULL, rlmReqGenerateVhtCapIE} + , /*191 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP_MODE_NOTIFICATION), NULL, rlmReqGenerateVhtOpNotificationIE} + , /*199 */ +#endif +#if CFG_SUPPORT_MTK_SYNERGY + {(ELEM_HDR_LEN + ELEM_MIN_LEN_MTK_OUI), NULL, rlmGenerateMTKOuiIE} + , /* 221 */ +#endif + {(ELEM_HDR_LEN + ELEM_MAX_LEN_WPA), NULL, rsnGenerateWPAIE} /* 221 */ +}; + +#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 */ +#if CFG_SUPPORT_802_11AC + {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP), NULL, rlmRspGenerateVhtCapIE} + , /*191 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP), NULL, rlmRspGenerateVhtOpIE} + , /*192 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP_MODE_NOTIFICATION), NULL, rlmRspGenerateVhtOpNotificationIE} + , /*199 */ +#endif + {(ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_PARAM), NULL, mqmGenerateWmmParamIE} + , /* 221 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_ASSOC_RSP_WSC_IE), NULL, rsnGenerateWSCIEForAssocRsp} + , /* 221 */ +#if CFG_SUPPORT_MTK_SYNERGY + {(ELEM_HDR_LEN + ELEM_MIN_LEN_MTK_OUI), NULL, rlmGenerateMTKOuiIE} /* 221 */ +#endif + , +#if CFG_SUPPORT_802_11W + {(ELEM_HDR_LEN + ELEM_MAX_LEN_TIMEOUT_IE), NULL, rsnPmfGenerateTimeoutIE} /* 56 */ +#endif + +}; +#endif /* 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 +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to compose the Capability Info Field. +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @retval Capability Info Field +*/ +/*----------------------------------------------------------------------------*/ + +UINT_16 assocBuildCapabilityInfo(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + UINT_32 u4NonHTPhyType; + UINT_16 u2CapInfo; + P_BSS_INFO_T prBssInfo; + + ASSERT(prStaRec); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + /* 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) && + /* Short Preamble Option Enable is TRUE */ + ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_SHORT) || + ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_AUTO) && + (prStaRec->u2CapInfo & CAP_INFO_SHORT_PREAMBLE)))) { + + /* Case I: Implemented == TRUE and Short Preamble Option Enable == TRUE. + * Case II: Implemented == TRUE and Short Preamble == AUTO (depends on + * BSS_DESC_T's capability) + */ + u2CapInfo |= CAP_INFO_SHORT_PREAMBLE; + } + +#if CFG_SUPPORT_SPEC_MGMT + /* 802.11h spectrum management is for 5G band, so + * now we only enable spectrum management bit for 5G case. + * In TGn 5.2.22, spectrum management bit should set to 1 + * to pass the UCC's check. + */ + if (prBssInfo && prBssInfo->eBand == BAND_5G) + u2CapInfo |= CAP_INFO_SPEC_MGT; +#endif + + 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) +*/ +/*----------------------------------------------------------------------------*/ +static __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_SW] = { 0 }; + UINT_8 ucAllSupportedRatesLen; + UINT_8 ucSupRatesLen; + UINT_8 ucExtSupRatesLen; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + ASSERT(prMsduInfo); + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + if (!prStaRec) + return; + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (ULONG) prMsduInfo->u2FrameLength); + ASSERT(pucBuffer); + + if (IS_STA_IN_AIS(prStaRec)) { + + /* Fill the SSID element. */ + SSID_IE(pucBuffer)->ucId = ELEM_ID_SSID; + + /* NOTE(Kevin): We copy the SSID from CONNECTION_SETTINGS for the case of + * Passive Scan and the target BSS didn't broadcast SSID on its Beacon Frame. + */ + + COPY_SSID(SSID_IE(pucBuffer)->aucSSID, + SSID_IE(pucBuffer)->ucLength, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + + } +#if CFG_ENABLE_WIFI_DIRECT + else if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) + pucBuffer = p2pBuildReAssocReqFrameCommonIEs(prAdapter, prMsduInfo, pucBuffer); + +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (IS_STA_BOW_TYPE(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 + + /* 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); + + if (!u2SupportedRateSet) { + DBGLOG(SAA, INFO, + "RateSet u4NonHTPhyType=%d u2OperationalRateSet=%d\n", + u4NonHTPhyType, prStaRec->u2OperationalRateSet); + 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); + } + } +} /* 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) +*/ +/*----------------------------------------------------------------------------*/ +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 by default. + */ + if (prStaRec->ucDTIMPeriod) { + u2ListenInterval = prStaRec->ucDTIMPeriod * prAdapter->rWifiVar.ucListenDtimInterval; + } 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_BSS_INFO_T prAisBssInfo = prAdapter->prAisBssInfo; + P_WLAN_REASSOC_REQ_FRAME_T prReAssocFrame = (P_WLAN_REASSOC_REQ_FRAME_T) prAssocFrame; + + COPY_MAC_ADDR(prReAssocFrame->aucCurrentAPAddr, prAisBssInfo->aucBSSID); + } else { + ASSERT(0); /* We don't support ReAssociation for other network */ + } + + *pu2PayloadLen = (CAP_INFO_FIELD_LEN + LISTEN_INTERVAL_FIELD_LEN + CURR_AP_ADDR_FIELD_LEN); + } else { + *pu2PayloadLen = (CAP_INFO_FIELD_LEN + LISTEN_INTERVAL_FIELD_LEN); + } +} /* end of assocComposeReAssocReqFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send the (Re)Association Request frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. +* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS assocSendReAssocReqFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + P_MSDU_INFO_T prMsduInfo; + P_BSS_INFO_T prBssInfo; + + UINT_16 u2PayloadLen; + UINT_16 u2EstimatedFrameLen; + UINT_16 u2EstimatedExtraIELen; + BOOLEAN fgIsReAssoc; + UINT_32 i; + + ASSERT(prStaRec); + + /* 4 <1> Allocate a PKT_INFO_T for Authentication Frame */ + fgIsReAssoc = prStaRec->fgIsReAssoc; + + /* Init with MGMT Header Length + Length of Fixed Fields + Common IE Length */ + if (fgIsReAssoc) { + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + + WLAN_MAC_MGMT_HEADER_LEN + + CAP_INFO_FIELD_LEN + + LISTEN_INTERVAL_FIELD_LEN + + CURR_AP_ADDR_FIELD_LEN + + (ELEM_HDR_LEN + ELEM_MAX_LEN_SSID) + + (ELEM_HDR_LEN + ELEM_MAX_LEN_SUP_RATES) + (ELEM_HDR_LEN + (RATE_NUM_SW - 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_SW - ELEM_MAX_LEN_SUP_RATES)); + } + + /* + Extra IE Length */ + u2EstimatedExtraIELen = 0; + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 && CFG_ENABLE_WIFI_DIRECT + if (IS_STA_IN_P2P(prStaRec)) { + if ((prAdapter->fgIsP2PRegistered)) { + u2EstimatedExtraIELen = p2pCalculate_IEForAssocReq(prAdapter, prStaRec->ucBssIndex, 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->ucBssIndex, + prStaRec); + } + } + /* calculate non-wfa vendor specific ie len */ + u2EstimatedExtraIELen += + assoc_get_nonwfa_vend_ie_len(prAdapter); + } +#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->ucBssIndex, prStaRec); + } + } + /* calculate non-wfa vendor specific ie len */ + u2EstimatedExtraIELen += assoc_get_nonwfa_vend_ie_len(prAdapter); +#endif + + ASSERT(prStaRec->ucBssIndex <= MAX_BSS_INDEX); + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SAA, WARN, "No PKT_INFO_T for sending (Re)Assoc Request.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose (Re)Association Request frame header and fixed fields in MSDU_INfO_T. */ + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + /* Compose Header and Fixed Field */ + assocComposeReAssocReqFrameHeaderAndFF(prAdapter, + prStaRec, + (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD), + prBssInfo->aucOwnMacAddr, &u2PayloadLen); + + /* 4 <3> Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, saaFsmRunEventTxDone, MSDU_RATE_MODE_AUTO); + + /* 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 (IS_STA_IN_P2P(prStaRec)) { + 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); + + } + /* Append non-wfa vendor specific ies for AIS mode */ + assoc_build_nonwfa_vend_ie(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); + + } + /* Append non-wfa vendor specific ies for AIS mode */ + assoc_build_nonwfa_vend_ie(prAdapter, prMsduInfo); +#endif + + /* 4 <6> Update the (Re)association request information */ + if (IS_STA_IN_AIS(prStaRec)) { + P_WLAN_ASSOC_REQ_FRAME_T prAssocFrame; + + prAssocFrame = (P_WLAN_ASSOC_REQ_FRAME_T) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + kalUpdateReAssocReqInfo(prAdapter->prGlueInfo, + (PUINT_8) &prAssocFrame->u2CapInfo, + prMsduInfo->u2FrameLength - offsetof(WLAN_ASSOC_REQ_FRAME_T, + u2CapInfo), fgIsReAssoc); + } +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) { + P_WLAN_ASSOC_REQ_FRAME_T prAssocFrame; + + prAssocFrame = (P_WLAN_ASSOC_REQ_FRAME_T) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + kalP2PUpdateAssocInfo(prAdapter->prGlueInfo, + (PUINT_8) &prAssocFrame->u2CapInfo, + prMsduInfo->u2FrameLength - offsetof(WLAN_ASSOC_REQ_FRAME_T, + u2CapInfo), fgIsReAssoc, prStaRec->ucBssIndex); + } +#endif + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ + + nicTxConfigPktControlFlag(prMsduInfo, MSDU_CONTROL_FLAG_FORCE_TX, TRUE); + + /* 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; + + if (!prSwRfb || !pu2StatusCode) { + DBGLOG(SAA, ERROR, "Invalid parameter, ignore!\n"); + return WLAN_STATUS_FAILURE; + } + + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < (CAP_INFO_FIELD_LEN + + STATUS_CODE_FIELD_LEN + AID_FIELD_LEN)) { + DBGLOG(SAA, WARN, + "Invalid AssocRsp packet length. u2PacketLen(%u) u2HeaderLen(%u)\n", + prSwRfb->u2PacketLen, prSwRfb->u2HeaderLen); + return WLAN_STATUS_FAILURE; + } + + DBGLOG(SAA, LOUD, "prSwRfb->u2PayloadLength = %d\n", prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (!prStaRec) { + DBGLOG(SAA, ERROR, "Invalid prStaRec, ignore!\n"); + return WLAN_STATUS_INVALID_PACKET; + } + + /* 4 <1> locate the (Re)Association Resp Frame. */ + prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) prSwRfb->pvHeader; + + /* if Association Response's BSSID doesn't match our target, ignore */ + if (!EQUAL_MAC_ADDR(prAssocRspFrame->aucBSSID, prStaRec->aucMacAddr)) { + DBGLOG(SAA, INFO, "Unknown BSSID\n"); + return WLAN_STATUS_FAILURE; + } + + /* 4 <2> Parse the Header of (Re)Association Resp Frame. */ + /* WLAN_GET_FIELD_16(&prAssocRspFrame->u2FrameCtrl, &u2RxFrameCtrl); */ + u2RxFrameCtrl = prAssocRspFrame->u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + u2RxFrameCtrl &= MASK_FRAME_TYPE; + if (prStaRec->fgIsReAssoc) { + if (u2RxFrameCtrl != MAC_FRAME_REASSOC_RSP) + return WLAN_STATUS_FAILURE; + + } else { + if (u2RxFrameCtrl != MAC_FRAME_ASSOC_RSP) + return WLAN_STATUS_FAILURE; + + } + + /* 4 <3> Parse the Fixed Fields of (Re)Association Resp Frame Body. */ + /* WLAN_GET_FIELD_16(&prAssocRspFrame->u2CapInfo, &u2RxCapInfo); */ + u2RxCapInfo = prAssocRspFrame->u2CapInfo; /* NOTE(Kevin): Optimized for ARM */ + + /* WLAN_GET_FIELD_16(&prAssocRspFrame->u2StatusCode, &u2RxStatusCode); */ + u2RxStatusCode = prAssocRspFrame->u2StatusCode; /* NOTE(Kevin): Optimized for ARM */ + + /* 4 <4> Check CAP_INFO */ + /* NOTE(Kevin): CM suggest to add MGMT workaround for those APs didn't check + * the CAP Privacy Bit to overcome a corner case that the Privacy Bit + * of our SCAN result didn't consist with AP's Association Resp. + */ + if (u2RxStatusCode == STATUS_CODE_SUCCESSFUL) { +#if CFG_SUPPORT_WAPI + if (prAdapter->rWifiVar.rConnSettings.fgWapiMode) { + /* WAPI AP allow the customer use WZC to join mode, the privacy bit is 0 */ + /* even at WAI & WAPI_PSK mode, but the assoc respose set the privacy bit set 1 */ + DBGLOG(SEC, TRACE, "Workaround the WAPI AP allow the customer to use WZC to join\n"); + } else +#endif +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered && 1) { + /* Todo:: Fixed this */ + } else +#endif + { + } + +#if CFG_STRICT_CHECK_CAPINFO_PRIVACY + if ((prStaRec->u2CapInfo & CAP_INFO_PRIVACY) ^ (u2RxCapInfo & CAP_INFO_PRIVACY)) + u2RxStatusCode = STATUS_CODE_CAP_NOT_SUPPORTED; + +#endif + } + + if (u2RxStatusCode == STATUS_CODE_SUCCESSFUL) { + /* 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)); + } + /* 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->eStaType == STA_TYPE_LEGACY_AP) { + P_AIS_SPECIFIC_BSS_INFO_T prBssSpecInfo; + + prBssSpecInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + ASSERT(prBssSpecInfo); + + prBssSpecInfo->ucSaQueryTimedOut = 0; + } +#endif + } + } +#if CFG_SUPPORT_802_11W + if (u2RxStatusCode == STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED) { + DBGLOG(SAA, INFO, "AP rejected due the authentication algorithm not support\n"); + } else if (u2RxStatusCode == STATUS_CODE_ASSOC_REJECTED_TEMPORARILY) { + PUINT_8 pucIE, pucTime; + UINT_16 u2IELength; + UINT_16 u2Offset = 0; + + u2IELength = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen; + pucIE = (PUINT_8) ((ULONG) prSwRfb->pvHeader + prSwRfb->u2HeaderLen); + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (IE_ID(pucIE) == ELEM_ID_TIMEOUT_INTERVAL && IE_LEN(pucIE) == 5) { + pucTime = ((P_IE_HDR_T) pucIE)->aucInfo; + if (pucTime[0] == ACTION_SA_TIMEOUT_ASSOC_COMEBACK) { + UINT_32 tu; + + WLAN_GET_FIELD_32(pucTime + 1, &tu); + DBGLOG(SAA, INFO, + "AP rejected association temporarily;comeback duration %u TU (%u ms)\n", + tu, TU_TO_MSEC(tu)); + if (tu > TX_ASSOCIATION_RETRY_TIMEOUT_TU) { + DBGLOG(SAA, INFO, "Update timer based on comeback duration\n"); + /* ieee80211_reschedule_timer(wpa_s, ms); */ + } + } + break; + } + } /* end of IE_FOR_EACH */ + } +#endif + *pu2StatusCode = u2RxStatusCode; + + return WLAN_STATUS_SUCCESS; + +} /* end of assocCheckRxReAssocRspFrameStatus() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will compose the Disassociation frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] aucMACAddress Given Our MAC Address. +* @param[in] u2ReasonCode The reason code of disassociation +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __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); +} /* 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); + ASSERT(prStaRec->ucBssIndex <= MAX_BSS_INDEX); + + DBGLOG(RSN, INFO, "assocSendDisAssocFrame\n"); + + /* 4 <1> Allocate a PKT_INFO_T for Disassociation Frame */ + /* Init with MGMT Header Length + Length of Fixed Fields + IE Length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + WLAN_MAC_MGMT_HEADER_LEN + REASON_CODE_FIELD_LEN; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SAA, WARN, "No PKT_INFO_T for sending DisAssoc.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Disassociation frame header and fixed fields in MSDU_INfO_T. */ + pucMacAddress = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex)->aucOwnMacAddr; + + /* Compose Header and Fixed Field */ + assocComposeDisassocFrame(prStaRec, + (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD), pucMacAddress, u2ReasonCode); + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + /* PMF certification 4.3.3.1, 4.3.3.2 send unprotected deauth reason 6/7 */ + if (prStaRec->rPmfCfg.fgRxDeauthResp != TRUE) { + + P_WLAN_DISASSOC_FRAME_T prDisassocFrame; + + prDisassocFrame = + (P_WLAN_DISASSOC_FRAME_T) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prDisassocFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + } + } +#endif + + u2PayloadLen = REASON_CODE_FIELD_LEN; + + /* 4 <3> Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, NULL, MSDU_RATE_MODE_AUTO); + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + /* caution: access prStaRec only if true */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + /* 4.3.3.1 send unprotected deauth reason 6/7 */ + if (prStaRec->rPmfCfg.fgRxDeauthResp != TRUE) { + DBGLOG(RSN, INFO, "Disassoc Set MSDU_OPT_PROTECTED_FRAME\n"); + nicTxConfigPktOption(prMsduInfo, MSDU_OPT_PROTECTED_FRAME, TRUE); + } + + prStaRec->rPmfCfg.fgRxDeauthResp = FALSE; + } +#endif + +#if CFG_SUPPORT_CFG80211_AUTH + { + P_WLAN_DISASSOC_FRAME_T prDisassocFrame; + + prDisassocFrame = (P_WLAN_DISASSOC_FRAME_T) + ((ULONG) (prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + DBGLOG(SAA, INFO, "notification of TX disassociation, %d\n", + prMsduInfo->u2FrameLength); + cfg80211_tx_mlme_mgmt(prAdapter->prGlueInfo->prDevHandler, + (UINT_8 *)prDisassocFrame, + (size_t)prMsduInfo->u2FrameLength); + DBGLOG(SAA, INFO, "notification of TX disassociation, Done\n"); + } +#endif + + /* 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; + + if (!prSwRfb || !aucBSSID || !pu2ReasonCode) { + DBGLOG(SAA, WARN, "Invalid parameters, ignore this pkt!\n"); + return WLAN_STATUS_FAILURE; + } + + /* 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) { + DBGLOG(SAA, WARN, + "Invalid DisAssoc packet length. u2PacketLen(%u) u2HeaderLen(%u)\n", + prSwRfb->u2PacketLen, prSwRfb->u2HeaderLen); + 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; + P_WIFI_VAR_T prWifiVar = NULL; + PUINT_8 pucIE, pucIEStart; + UINT_16 u2IELength; + UINT_16 u2Offset = 0; + UINT_16 u2StatusCode = STATUS_CODE_SUCCESSFUL; + UINT_16 u2RxFrameCtrl; + UINT_16 u2BSSBasicRateSet; + UINT_8 ucFixedFieldLength; + BOOLEAN fgIsUnknownBssBasicRate; + BOOLEAN fgIsTKIP = FALSE; + UINT_32 i; + + if (!prAdapter || !prSwRfb || !pu2StatusCode) { + DBGLOG(SAA, WARN, "Invalid parameters, ignore this pkt!\n"); + return WLAN_STATUS_FAILURE; + } + + prWifiVar = &(prAdapter->rWifiVar); + + 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; + + /* WLAN_GET_FIELD_16(&prAssocReqFrame->u2FrameCtrl, &u2RxFrameCtrl); */ + u2RxFrameCtrl = prAssocReqFrame->u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + u2RxFrameCtrl &= MASK_FRAME_TYPE; + + /* 4 <2> Parse the Header of Association Req Frame. */ + if (u2RxFrameCtrl == MAC_FRAME_REASSOC_REQ) + ucFixedFieldLength = CAP_INFO_FIELD_LEN + LISTEN_INTERVAL_FIELD_LEN + CURR_AP_ADDR_FIELD_LEN; + else + ucFixedFieldLength = CAP_INFO_FIELD_LEN + LISTEN_INTERVAL_FIELD_LEN; + + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) <= ucFixedFieldLength) { + /* Length of this (re)association req is invalid, ignore it */ + return WLAN_STATUS_FAILURE; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + /* 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 */ + + if (u2RxFrameCtrl == MAC_FRAME_REASSOC_REQ) { + prStaRec->fgIsReAssoc = TRUE; + + u2IELength = prSwRfb->u2PacketLen - + (UINT_16) OFFSET_OF(WLAN_REASSOC_REQ_FRAME_T, aucInfoElem[0]); + + pucIEStart = pucIE = ((P_WLAN_REASSOC_REQ_FRAME_T) (prSwRfb->pvHeader))->aucInfoElem; + } else { + prStaRec->fgIsReAssoc = FALSE; + + u2IELength = prSwRfb->u2PacketLen - + (UINT_16) OFFSET_OF(WLAN_ASSOC_REQ_FRAME_T, aucInfoElem[0]); + + pucIEStart = pucIE = prAssocReqFrame->aucInfoElem; + } + + /* 4 <3> Parse the Fixed Fields of Assoc Req Frame Body. */ + prStaRec->u2CapInfo = prAssocReqFrame->u2CapInfo; + +#if 0 /* CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_HOTSPOT_PRIVACY_CHECK */ + if (prAdapter->fgIsP2PRegistered && IS_STA_P2P_TYPE(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_SW)) + 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_VHT_CAP: + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_VHT; + 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, prStaRec, &u2StatusCode); + if (u2StatusCode != STATUS_CODE_SUCCESSFUL) { + *pu2StatusCode = u2StatusCode; + return WLAN_STATUS_SUCCESS; + } + } +#endif + break; + case ELEM_ID_VENDOR: + if (p2pFuncParseCheckForTKIPInfoElem(pucIE)) + fgIsTKIP = TRUE; + +#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; + case ELEM_ID_IBSS_PARAM_SET: + /* Check IBSS parameter set length to avoid abnormal content */ + if (IE_LEN(pucIE) != ELEM_MAX_LEN_IBSS_PARAMETER_SET) { + *pu2StatusCode = STATUS_CODE_UNSPECIFIED_FAILURE; + DBGLOG(SAA, WARN, "Invalid IBSS Parameter IE length!\n"); + return WLAN_STATUS_FAILURE; + } + break; + default: + for (i = 0; i < (sizeof(rxAssocReqIETable) / sizeof(VERIFY_IE_ENTRY_T)); i++) { + + if (((IE_ID(pucIE)) == rxAssocReqIETable[i].ucElemID) && + (rxAssocReqIETable[i].pfnVarifyIE != NULL)) { + 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 */ + + /* + * According to TGn & TGac 4.2.44, AP should not bring HT/VHT Cap IE in + * the IE of Assoc resp, if the STA request to use TKIP cipher + */ + if (fgIsTKIP && !prWifiVar->ucApAllowHtVhtTkip) + prStaRec->ucPhyTypeSet &= ~(PHY_TYPE_BIT_VHT | PHY_TYPE_BIT_HT); + + /* 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) { + DBGLOG(SAA, WARN, "Supported Rate IE not present!\n"); + u2StatusCode = STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED; + break; + } + /* Ignore any Basic Bit */ + rateGetRateSetFromIEs(prIeSupportedRate, prIeExtSupportedRate, + &prStaRec->u2OperationalRateSet, &u2BSSBasicRateSet, + &fgIsUnknownBssBasicRate); + + if ((prBssInfo->u2BSSBasicRateSet & prStaRec->u2OperationalRateSet) != + prBssInfo->u2BSSBasicRateSet) { + u2StatusCode = STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED; + DBGLOG(SAA, WARN, "Basic rate not supported!\n"); + break; + } + + /* Accpet the Sta, update BSSBasicRateSet from Bss */ + prStaRec->u2BSSBasicRateSet = prBssInfo->u2BSSBasicRateSet; + prStaRec->u2DesiredNonHTRateSet = (prStaRec->u2OperationalRateSet & RATE_SET_ALL_ABG); + + if (HAL_RX_STATUS_GET_RF_BAND(prSwRfb->prRxStatus) == BAND_2G4) { + 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; + } else { /* (BAND_5G == prBssDesc->eBande) */ + if (prStaRec->u2OperationalRateSet & RATE_SET_OFDM) + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_OFDM; + } + /* Update default Tx rate */ + nicTxUpdateStaRecDefaultRate(prStaRec); + +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_HOTSPOT_PRIVACY_CHECK + if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { + if (prIeRsn) { + if (!kalP2PGetCipher(prAdapter->prGlueInfo, (UINT_8) prBssInfo->u4PrivateData)) { + 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); + + if (prStaRec->pucAssocReqIe) + kalMemCopy(prStaRec->pucAssocReqIe, cp, u2IELength); + else + DBGLOG(SAA, LOUD, + "allocate memory for prStaRec->pucAssocReqIe failed!\n"); + } + } +#endif + kalP2PUpdateAssocInfo(prAdapter->prGlueInfo, (PUINT_8) &prAssocReqFrame->u2CapInfo, + u2IELength + (prStaRec->fgIsReAssoc ? 10 : 4), prStaRec->fgIsReAssoc, + prStaRec->ucBssIndex); + } +#endif + + *pu2StatusCode = u2StatusCode; + + return WLAN_STATUS_SUCCESS; + +} /* end of assocProcessRxAssocReqFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to compose Common Information Elements for Association +* Response Frame. +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* @param[in] prBssInfo Pointer to the BSS_INFO_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __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) ((ULONG) prMsduInfo->prPacket + (ULONG) prMsduInfo->u2FrameLength); + ASSERT(pucBuffer); + + if (prBssInfo->ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) { + + ucSupRatesLen = ELEM_MAX_LEN_SUP_RATES; + ucExtSupRatesLen = prBssInfo->ucAllSupportedRatesLen - ELEM_MAX_LEN_SUP_RATES; + } else { + ucSupRatesLen = prBssInfo->ucAllSupportedRatesLen; + ucExtSupRatesLen = 0; + } + + /* Fill the Supported Rates element. */ + if (ucSupRatesLen) { + SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_SUP_RATES; + SUP_RATES_IE(pucBuffer)->ucLength = ucSupRatesLen; + kalMemCopy(SUP_RATES_IE(pucBuffer)->aucSupportedRates, prBssInfo->aucAllSupportedRates, ucSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } + + /* Fill the Extended Supported Rates element. */ + if (ucExtSupRatesLen) { + + EXT_SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_EXTENDED_SUP_RATES; + EXT_SUP_RATES_IE(pucBuffer)->ucLength = ucExtSupRatesLen; + + kalMemCopy(EXT_SUP_RATES_IE(pucBuffer)->aucExtSupportedRates, + &prBssInfo->aucAllSupportedRates[ucSupRatesLen], ucExtSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + } +} /* end of assocBuildReAssocRespFrameCommonIEs() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the (Re)Association Response frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] aucBssid Given BSSID. +* @param[in] u2CapInfo Capability Field of current BSS. +* @param[in out] pu2PayloadLen Return the length of the composed fixed fields +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __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)); */ + /* NOTE(Kevin): Optimized for ARM */ + prAssocRspFrame->u2AssocId = ((prStaRec->u2AssocId & AID_MASK) | AID_MSB); + + *pu2PayloadLen = (CAP_INFO_FIELD_LEN + STATUS_CODE_FIELD_LEN + AID_FIELD_LEN); +} /* end of assocComposeReAssocRespFrameHeaderAndFF() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send the (Re)Association Resp frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. +* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS assocSendReAssocRespFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + P_BSS_INFO_T prBssInfo; + P_MSDU_INFO_T prMsduInfo; + + UINT_16 u2PayloadLen; + UINT_16 u2EstimatedFrameLen; + UINT_16 u2EstimatedExtraIELen; + BOOLEAN fgIsReAssoc; + UINT_32 i; + + ASSERT(prStaRec); + ASSERT(prStaRec->ucBssIndex <= MAX_BSS_INDEX); + + /* 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_SW - 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->ucBssIndex, prStaRec); + } + + } + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(AAA, WARN, "No PKT_INFO_T for sending (Re)Assoc Response.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose (Re)Association Request frame header and fixed fields in MSDU_INfO_T. */ + ASSERT(prStaRec->ucBssIndex != prAdapter->prAisBssInfo->ucBssIndex); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + /* Compose Header and Fixed Field */ + assocComposeReAssocRespFrameHeaderAndFF(prStaRec, + (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD), + prBssInfo->aucBSSID, prBssInfo->u2CapInfo, &u2PayloadLen); + + /* 4 <3> Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, aaaFsmRunEventTxDone, MSDU_RATE_MODE_AUTO); + + /* 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); + + } + +#if CFG_SUPPORT_WFD + /* TODO put WFD IE in assoc resp if driver will send assoc resp */ + +#endif + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ + + nicTxConfigPktControlFlag(prMsduInfo, MSDU_CONTROL_FLAG_FORCE_TX, TRUE); + + /* 4 <6> Enqueue the frame to send this (Re)Association request frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; + +} /* end of assocSendReAssocRespFrame() */ + +/*-----------------------------------------------------------------------*/ +/*! +* @brief Get the non-wfa vendor ie length that was previously set +* by wpa_supplicant for association request frame. +* +* @param prAdapter pointer to driver adapter +* +* @retval length of the non-wfa vendor ie +*/ +/*-----------------------------------------------------------------------*/ +u32 assoc_get_nonwfa_vend_ie_len(IN P_ADAPTER_T prAdapter) +{ + if (!prAdapter || !prAdapter->prGlueInfo) + return 0; + return prAdapter->prGlueInfo->non_wfa_vendor_ie_len; +} + +/*-----------------------------------------------------------------------*/ +/*! +* @brief Builds the non-wfa vendor specific ies into association +* request frame. +* +* @param prAdapter pointer to driver adapter +* prMsduInfo pointer to the msdu frame body +* +* @retval void +*/ +/*-----------------------------------------------------------------------*/ +void assoc_build_nonwfa_vend_ie(P_ADAPTER_T prAdapter, + P_MSDU_INFO_T prMsduInfo) +{ + u8 *ptr = NULL; + u32 len = 0; + + if (!prAdapter || !prMsduInfo) + return; + len = prAdapter->prGlueInfo->non_wfa_vendor_ie_len; + if (!len) + return; + + ptr = (u8 *)prMsduInfo->prPacket + (u16)prMsduInfo->u2FrameLength; + kalMemCopy(ptr, prAdapter->prGlueInfo->non_wfa_vendor_ie_buf, + len); + prMsduInfo->u2FrameLength += len; +} + +#endif /* CFG_SUPPORT_AAA */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/auth.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/auth.c new file mode 100644 index 0000000000000..fcbf15680bb20 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/auth.c @@ -0,0 +1,1236 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +APPEND_IE_ENTRY_T txAuthIETable[] = { + {(ELEM_HDR_LEN + ELEM_MAX_LEN_CHALLENGE_TEXT), authAddIEChallengeText} +}; + +HANDLE_IE_ENTRY_T rxAuthIETable[] = { + {ELEM_ID_CHALLENGE_TEXT, authHandleIEChallengeText} +}; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the Authentication frame header and fixed fields. +* +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] aucPeerMACAddress Given Peer MAC Address. +* @param[in] aucMACAddress Given Our MAC Address. +* @param[in] u2AuthAlgNum Authentication Algorithm Number +* @param[in] u2TransactionSeqNum Transaction Sequence Number +* @param[in] u2StatusCode Status Code +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __KAL_INLINE__ VOID +authComposeAuthFrameHeaderAndFF(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + 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; +#if CFG_SUPPORT_CFG80211_AUTH + P_CONNECTION_SETTINGS_T prConnSettings; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); +#endif + + 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); + + if (prStaRec != NULL && IS_AP_STA(prStaRec)) { + /* Fill the BSSID field with Target BSSID. */ + COPY_MAC_ADDR(prAuthFrame->aucBSSID, aucPeerMACAddress); + + } else if (prStaRec != NULL && IS_CLIENT_STA(prStaRec)) { + /* Fill the BSSID field with Current BSSID. */ + COPY_MAC_ADDR(prAuthFrame->aucBSSID, aucMACAddress); + } else { + COPY_MAC_ADDR(prAuthFrame->aucBSSID, aucMACAddress); + DBGLOG(SAA, INFO, + "Error status code flow!\n"); + } + /* 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 */ +#if CFG_SUPPORT_CFG80211_AUTH + if (prConnSettings->ucAuthDataLen != 0) { + kalMemCopy(prAuthFrame->aucAuthData, + prConnSettings->aucAuthData, + prConnSettings->ucAuthDataLen); + } else { + /* Fill the Authentication Transaction Sequence Number field. */ + /* NOTE(Kevin): Optimized for ARM */ + prAuthFrame->aucAuthData[0] = u2TransactionSeqNum; + + /* Fill the Status Code field. */ + /* NOTE(Kevin): Optimized for ARM */ + prAuthFrame->aucAuthData[2] = u2StatusCode; + } + DBGLOG(SAA, INFO, "Compose auth with TransSN = %d,Status = %d\n", + prAuthFrame->aucAuthData[0], prAuthFrame->aucAuthData[2]); +#else + /* 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 */ +#endif +} /* 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; +#if CFG_SUPPORT_CFG80211_AUTH + WLAN_GET_FIELD_16(&prAuthFrame->aucAuthData[0], &u2TransactionSeqNum) +#else + WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, &u2TransactionSeqNum) +#endif + /* Only consider SEQ_3 for Challenge Text */ + if ((u2TransactionSeqNum == AUTH_TRANSACTION_SEQ_3) && + (prStaRec->ucAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY) && (prStaRec->prChallengeText != NULL)) { + + COPY_IE(((ULONG) (prMsduInfo->prPacket) + prMsduInfo->u2FrameLength), (prStaRec->prChallengeText)); + + prMsduInfo->u2FrameLength += IE_SIZE(prStaRec->prChallengeText); + } + + return; + +} /* end of authAddIEChallengeText() */ + +#if !CFG_SUPPORT_AAA +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send the Authenticiation frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] u2TransactionSeqNum Transaction Sequence Number +* +* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. +* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS authSendAuthFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN UINT_16 u2TransactionSeqNum) +{ + P_MSDU_INFO_T prMsduInfo; + P_BSS_INFO_T prBssInfo; + UINT_16 u2EstimatedFrameLen; + UINT_16 u2EstimatedExtraIELen; + UINT_16 u2PayloadLen; + UINT_32 i; + + DBGLOG(SAA, LOUD, "Send Auth Frame\n"); + + ASSERT(prStaRec); + + /* 4 <1> Allocate a PKT_INFO_T for Authentication Frame */ + /* Init with MGMT Header Length + Length of Fixed Fields */ + u2EstimatedFrameLen = (MAC_TX_RESERVED_FIELD + + WLAN_MAC_MGMT_HEADER_LEN + + AUTH_ALGORITHM_NUM_FIELD_LEN + + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + STATUS_CODE_FIELD_LEN); + + /* + Extra IE Length */ + u2EstimatedExtraIELen = 0; + + for (i = 0; i < sizeof(txAuthIETable) / sizeof(APPEND_IE_ENTRY_T); i++) + u2EstimatedExtraIELen += txAuthIETable[i].u2EstimatedIELen; + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SAA, WARN, "No PKT_INFO_T for sending Auth Frame.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Authentication Request frame header and fixed fields in MSDU_INfO_T. */ + ASSERT(prStaRec->ucBssIndex <= MAX_BSS_INDEX); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex) + + /* Compose Header and some Fixed Fields */ + authComposeAuthFrameHeaderAndFF(prAdapter, prStaRec, (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 */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, saaFsmRunEventTxDone, MSDU_RATE_MODE_AUTO); + + /* 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 */ + + nicTxConfigPktControlFlag(prMsduInfo, MSDU_CONTROL_FLAG_FORCE_TX, TRUE); + + /* 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 UINT_8 ucBssIndex, + 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; +#if CFG_SUPPORT_CFG80211_AUTH + P_CONNECTION_SETTINGS_T prConnSettings; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); +#endif + + DBGLOG(SAA, LOUD, "Send Auth Frame %d, Status Code = %d\n", + u2TransactionSeqNum, u2StatusCode); +#if CFG_SUPPORT_CFG80211_AUTH + if (prConnSettings->ucAuthDataLen != 0) { + DBGLOG(SAA, INFO, "prConnSettings->ucAuthDataLen = %d\n", + prConnSettings->ucAuthDataLen); + u2EstimatedFrameLen = (MAC_TX_RESERVED_FIELD + + WLAN_MAC_MGMT_HEADER_LEN + + AUTH_ALGORITHM_NUM_FIELD_LEN + + prConnSettings->ucAuthDataLen); + } else + 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); +#else + /* 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); +#endif + /* + Extra IE Length */ + u2EstimatedExtraIELen = 0; + + for (i = 0; i < sizeof(txAuthIETable) / sizeof(APPEND_IE_ENTRY_T); i++) + u2EstimatedExtraIELen += txAuthIETable[i].u2EstimatedIELen; + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SAA, WARN, "No PKT_INFO_T for sending Auth Frame.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Authentication Request frame header and fixed fields in MSDU_INfO_T. */ + if (prStaRec) { + ASSERT(prStaRec->ucBssIndex <= MAX_BSS_INDEX); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + pucTransmitAddr = prBssInfo->aucOwnMacAddr; + + pucReceiveAddr = prStaRec->aucMacAddr; + + ucAuthAlgNum = prStaRec->ucAuthAlgNum; + +#if CFG_SUPPORT_CFG80211_AUTH + if (!IS_STA_IN_P2P(prStaRec)) { + if (IS_AP_STA(prStaRec)) + pfTxDoneHandler = saaFsmRunEventTxDone; + else if (IS_CLIENT_STA(prStaRec)) + pfTxDoneHandler = aaaFsmRunEventTxDone; + else { + DBGLOG(SAA, WARN, + "Can't send auth with unsupport peer's StaType:%d\n", + prStaRec->eStaType); + return WLAN_STATUS_FAILURE; + } + } else { +#endif + 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; + } +#if CFG_SUPPORT_CFG80211_AUTH + } +#endif + + } 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; +#if CFG_SUPPORT_CFG80211_AUTH + u2TransactionSeqNum = (prFalseAuthFrame->aucAuthData[0] + 1); +#else + u2TransactionSeqNum = (prFalseAuthFrame->u2AuthTransSeqNo + 1); +#endif + } + + /* Compose Header and some Fixed Fields */ + authComposeAuthFrameHeaderAndFF(prAdapter, prStaRec, (PUINT_8) + ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + pucReceiveAddr, pucTransmitAddr, ucAuthAlgNum, + u2TransactionSeqNum, u2StatusCode); + /* fill the length of auth frame body */ +#if CFG_SUPPORT_CFG80211_AUTH + if (prConnSettings->ucAuthDataLen != 0) + u2PayloadLen = (AUTH_ALGORITHM_NUM_FIELD_LEN + + prConnSettings->ucAuthDataLen); + else + u2PayloadLen = (AUTH_ALGORITHM_NUM_FIELD_LEN + + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + + STATUS_CODE_FIELD_LEN); +#else + u2PayloadLen = (AUTH_ALGORITHM_NUM_FIELD_LEN + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + STATUS_CODE_FIELD_LEN); +#endif + /* 4 <3> Update information of MSDU_INFO_T */ + + TX_SET_MMPDU(prAdapter, + prMsduInfo, + ucBssIndex, + (prStaRec != NULL) ? (prStaRec->ucIndex) : (STA_REC_INDEX_NOT_FOUND), + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, pfTxDoneHandler, MSDU_RATE_MODE_AUTO); + + if ((ucAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY) && (u2TransactionSeqNum == AUTH_TRANSACTION_SEQ_3)) + nicTxConfigPktOption(prMsduInfo, MSDU_OPT_PROTECTED_FRAME, 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 */ + + nicTxConfigPktControlFlag(prMsduInfo, MSDU_CONTROL_FLAG_FORCE_TX, TRUE); + + /* 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) */ +#if CFG_SUPPORT_CFG80211_AUTH + u2TxTransactionSeqNum = prAuthFrame->aucAuthData[0]; +#else + u2TxTransactionSeqNum = prAuthFrame->u2AuthTransSeqNo; /* NOTE(Kevin): Optimized for ARM */ +#endif + 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; + UINT_16 u2MinPayloadLen; +#if CFG_SUPPORT_SAE + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prBssInfo = NULL; +#endif + + ASSERT(prSwRfb); + + /* 4 <1> locate the Authentication Frame. */ + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; + + /* 4 <2> Parse the Header of Authentication Frame. */ + u2MinPayloadLen = (AUTH_ALGORITHM_NUM_FIELD_LEN + + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + STATUS_CODE_FIELD_LEN); + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < u2MinPayloadLen) { + DBGLOG(SAA, WARN, "Rx Auth payload: len[%u] < min expected len[%u]\n", + (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen), u2MinPayloadLen); + DBGLOG(SAA, WARN, "=== Dump Rx Auth ===\n"); + DBGLOG_MEM8(SAA, WARN, prAuthFrame, prSwRfb->u2PacketLen); + return WLAN_STATUS_SUCCESS; + } + /* 4 <3> Parse the Fixed Fields of Authentication Frame Body. */ + /* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, &u2RxTransactionSeqNum); */ +#if CFG_SUPPORT_CFG80211_AUTH + u2RxTransactionSeqNum = prAuthFrame->aucAuthData[0]; +#else + u2RxTransactionSeqNum = prAuthFrame->u2AuthTransSeqNo; /* NOTE(Kevin): Optimized for ARM */ +#endif + + if ((u2RxTransactionSeqNum < 0) || (u2RxTransactionSeqNum > 4)) { + DBGLOG(SAA, WARN, + "RX auth with unexpected TransactionSeqNum:%d\n", + u2RxTransactionSeqNum); + return WLAN_STATUS_SUCCESS; + } +#if CFG_SUPPORT_SAE + if (prAuthFrame->u2AuthAlgNum == AUTH_ALGORITHM_NUM_SAE) { + if ((u2RxTransactionSeqNum == + AUTH_TRANSACTION_SEQ_1) || + (u2RxTransactionSeqNum == + AUTH_TRANSACTION_SEQ_2)) { + prStaRec = prSwRfb->prStaRec; + if (prStaRec) + prBssInfo = + GET_BSS_INFO_BY_INDEX( + prAdapter, + prStaRec->ucBssIndex); + else + prBssInfo = + p2pFuncBSSIDFindBssInfo( + prAdapter, + prAuthFrame->aucBSSID); + + if (prBssInfo == NULL) + return WLAN_STATUS_SUCCESS; + + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) + saaFsmRunEventRxAuth(prAdapter, prSwRfb); +#if CFG_SUPPORT_AAA + else if (prBssInfo->eCurrentOPMode == + OP_MODE_ACCESS_POINT) + aaaFsmRunEventRxAuth(prAdapter, prSwRfb); +#endif + else + DBGLOG(SAA, WARN, + "Don't support SAE for non-AIS/P2P network\n"); + } else { + DBGLOG(SAA, WARN, + "RX SAE auth with unexpected TransSeqNum:%d\n", + u2RxTransactionSeqNum); + } + + } else { +#endif + 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\n", + u2RxTransactionSeqNum); + } +#if CFG_SUPPORT_SAE + } +#endif + 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); */ +#if CFG_SUPPORT_CFG80211_AUTH + u2RxTransactionSeqNum = prAuthFrame->aucAuthData[0]; + /* Still report to upper layer to let it do the error handling */ + if (u2RxTransactionSeqNum < u2TransactionSeqNum) + DBGLOG(SAA, WARN, + "Rx Auth frame with unexpected Transaction Seq No = %d\n", + u2RxTransactionSeqNum); +#else + u2RxTransactionSeqNum = prAuthFrame->u2AuthTransSeqNo; /* NOTE(Kevin): Optimized for ARM */ + if (u2RxTransactionSeqNum != u2TransactionSeqNum) { + DBGLOG(SAA, WARN, + "Discard Auth frame with Transaction Seq No = %d\n", + u2RxTransactionSeqNum); + return WLAN_STATUS_FAILURE; + } +#endif + /* 4 <3> Get the Status code */ + /* WLAN_GET_FIELD_16(&prAuthFrame->u2StatusCode, &u2RxStatusCode); */ + /* *pu2StatusCode = u2RxStatusCode; */ +#if CFG_SUPPORT_CFG80211_AUTH + *pu2StatusCode = prAuthFrame->aucAuthData[2]; +#else + *pu2StatusCode = prAuthFrame->u2StatusCode; /* NOTE(Kevin): Optimized for ARM */ +#endif + DBGLOG(SAA, INFO, + "Rx Auth frame with auth type = %d, SN = %d, Status Code = %d\n", + u2RxAuthAlgNum, u2RxTransactionSeqNum, *pu2StatusCode); + + 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) */ +#if CFG_SUPPORT_CFG80211_AUTH + u2TransactionSeqNum = prAuthFrame->aucAuthData[0]; +#else + u2TransactionSeqNum = prAuthFrame->u2AuthTransSeqNo; /* NOTE(Kevin): Optimized for ARM */ +#endif + /* Only consider SEQ_2 for Challenge Text */ + if ((u2TransactionSeqNum == AUTH_TRANSACTION_SEQ_2) && + (prStaRec->ucAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY)) { + + /* Free previous allocated TCM memory */ + if (prStaRec->prChallengeText) { + /* ASSERT(0); */ + cnmMemFree(prAdapter, prStaRec->prChallengeText); + prStaRec->prChallengeText = (P_IE_CHALLENGE_TEXT_T) NULL; + } + prStaRec->prChallengeText = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, IE_SIZE(prIEHdr)); + if (prStaRec->prChallengeText == NULL) + return; + + /* Save the Challenge Text from Auth Seq 2 Frame, before sending Auth Seq 3 Frame */ + COPY_IE(prStaRec->prChallengeText, prIEHdr); + } + + return; + +} /* end of authAddIEChallengeText() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will parse and process the incoming Authentication frame. +* +* @param[in] prSwRfb Pointer to SW RFB data structure. +* +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS authProcessRxAuth2_Auth4Frame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ +#if !CFG_SUPPORT_CFG80211_AUTH /* to modify for new connection flow */ + + 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 != NULL)) + rxAuthIETable[i].pfnHandleIE(prAdapter, prSwRfb, (P_IE_HDR_T) pucIEsBuffer); + } + } +#endif + return WLAN_STATUS_SUCCESS; + +} /* end of authProcessRxAuth2_Auth4Frame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the Deauthentication frame +* +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] aucPeerMACAddress Given Peer MAC Address. +* @param[in] aucMACAddress Given Our MAC Address. +* @param[in] u2StatusCode Status Code +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +static __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 */ +} /* 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_BSS_INFO_T prBssInfo, + IN P_STA_RECORD_T prStaRec, + IN P_SW_RFB_T prClassErrSwRfb, IN UINT_16 u2ReasonCode, IN PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + PUINT_8 pucReceiveAddr; + PUINT_8 pucTransmitAddr; + PUINT_8 pucBssid = NULL; + P_MSDU_INFO_T prMsduInfo; + UINT_16 u2EstimatedFrameLen; + + P_DEAUTH_INFO_T prDeauthInfo; + OS_SYSTIME rCurrentTime; + INT_32 i4NewEntryIndex, i; + UINT_8 ucStaRecIdx = STA_REC_INDEX_NOT_FOUND; + UINT_8 ucBssIndex = BSS_INFO_NUM; + UINT_8 aucBMC[] = BC_MAC_ADDR; + + DBGLOG(RSN, INFO, "authSendDeauthFrame\n"); + + /* NOTE(Kevin): The best way to reply the Deauth is according to the incoming data + * frame + */ + /* 4 <1.1> Find the Receiver Address */ + if (prClassErrSwRfb) { + BOOLEAN fgIsAbleToSendDeauth = FALSE; + UINT_16 u2RxFrameCtrl; + P_WLAN_MAC_HEADER_A4_T prWlanMacHeader = NULL; + + 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 = 0; i < BSS_INFO_NUM; i++) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, i); + + if (IS_NET_ACTIVE(prAdapter, i) && + (EQUAL_MAC_ADDR(prWlanMacHeader->aucAddr1, prBssInfo->aucOwnMacAddr))) { + + fgIsAbleToSendDeauth = TRUE; + ucBssIndex = (UINT_8) i; + break; + } + } + + if (!fgIsAbleToSendDeauth) + return WLAN_STATUS_FAILURE; + + pucReceiveAddr = prWlanMacHeader->aucAddr2; + } else if (prStaRec) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + ucStaRecIdx = prStaRec->ucIndex; + ucBssIndex = prBssInfo->ucBssIndex; + + pucReceiveAddr = prStaRec->aucMacAddr; + } else if (prBssInfo) { + ucBssIndex = prBssInfo->ucBssIndex; + ucStaRecIdx = STA_REC_INDEX_BMCAST; + + pucReceiveAddr = aucBMC; + } else { + DBGLOG(SAA, WARN, "Not to send Deauth, invalid data!\n"); + return WLAN_STATUS_INVALID_DATA; + } + + /* 4 <1.2> Find Transmitter Address and BSSID. */ + pucTransmitAddr = prBssInfo->aucOwnMacAddr; + pucBssid = prBssInfo->aucBSSID; + + if (ucStaRecIdx != STA_REC_INDEX_BMCAST) { + /* 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 <5> Allocate a PKT_INFO_T for Deauthentication Frame */ + /* Init with MGMT Header Length + Length of Fixed Fields + IE Length */ + u2EstimatedFrameLen = (MAC_TX_RESERVED_FIELD + WLAN_MAC_MGMT_HEADER_LEN + REASON_CODE_FIELD_LEN); + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SAA, WARN, "No PKT_INFO_T for sending Deauth Request.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <6> compose Deauthentication frame header and some fixed fields */ + authComposeDeauthFrameHeaderAndFF((PUINT_8) + ((ULONG) (prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD), pucReceiveAddr, pucTransmitAddr, + pucBssid, u2ReasonCode); + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + /* PMF certification 4.3.3.1, 4.3.3.2 send unprotected deauth reason 6/7 */ + /* if (AP mode & not for PMF reply case) OR (STA PMF) */ + if (((GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex)->eCurrentOPMode == + OP_MODE_ACCESS_POINT) && + (prStaRec->rPmfCfg.fgRxDeauthResp != TRUE)) || + (GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex)->eNetworkType == + (UINT_8) NETWORK_TYPE_AIS)) { + + P_WLAN_DEAUTH_FRAME_T prDeauthFrame; + + prDeauthFrame = (P_WLAN_DEAUTH_FRAME_T) (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD); + + prDeauthFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + } + } +#endif + nicTxSetPktLifeTime(prMsduInfo, 100); + + nicTxSetPktRetryLimit(prMsduInfo, TX_DESC_TX_COUNT_NO_LIMIT); + + /* 4 <7> Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + ucBssIndex, + ucStaRecIdx, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + REASON_CODE_FIELD_LEN, pfTxDoneHandler, MSDU_RATE_MODE_AUTO); + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + /* caution: access prStaRec only if true */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + /* 4.3.3.1 send unprotected deauth reason 6/7 */ + if (prStaRec->rPmfCfg.fgRxDeauthResp != TRUE) { + DBGLOG(RSN, INFO, "Deauth Set MSDU_OPT_PROTECTED_FRAME\n"); + nicTxConfigPktOption(prMsduInfo, MSDU_OPT_PROTECTED_FRAME, TRUE); + } + + prStaRec->rPmfCfg.fgRxDeauthResp = FALSE; + } + +#endif +#if CFG_SUPPORT_CFG80211_AUTH + { + P_WLAN_DEAUTH_FRAME_T prDeauthFrame; + + prDeauthFrame = (P_WLAN_DEAUTH_FRAME_T) (PUINT_8) ((ULONG) + (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + DBGLOG(SAA, INFO, "notification of TX deauthentication, %d\n", + prMsduInfo->u2FrameLength); + + cfg80211_tx_mlme_mgmt(prAdapter->prGlueInfo->prDevHandler, + (PUINT_8)prDeauthFrame, + (size_t)prMsduInfo->u2FrameLength); + DBGLOG(SAA, INFO, + "notification of TX deauthentication, Done\n"); + } +#endif + + /* 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; + + if (!prSwRfb || !aucBSSID || !pu2ReasonCode) { + DBGLOG(SAA, WARN, "Invalid parameters, ignore this pkt!\n"); + return WLAN_STATUS_FAILURE; + } + + /* 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) { + DBGLOG(SAA, WARN, + "Invalid Deauth packet length. u2PacketLen(%u), u2HeaderLen(%u)\n", + prSwRfb->u2PacketLen, prSwRfb->u2HeaderLen); + 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> Check the SA, which should not be MC/BC */ + if (prAuthFrame->aucSrcAddr[0] & BIT(0)) { + DBGLOG(P2P, WARN, "Invalid STA MAC with MC/BC bit set: " MACSTR "\n", MAC2STR(prAuthFrame->aucSrcAddr)); + return WLAN_STATUS_FAILURE; + } + + /* 4 <4> Parse the Fixed Fields of Authentication Frame Body. */ + if (prAuthFrame->u2AuthAlgNum != u2ExpectedAuthAlgNum) + u2ReturnStatusCode = STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED; +#if CFG_SUPPORT_CFG80211_AUTH + if (prAuthFrame->aucAuthData[0] != u2ExpectedTransSeqNum) +#else + if (prAuthFrame->u2AuthTransSeqNo != u2ExpectedTransSeqNum) +#endif + u2ReturnStatusCode = STATUS_CODE_AUTH_OUT_OF_SEQ; + + *pu2ReturnStatusCode = u2ReturnStatusCode; + + return WLAN_STATUS_SUCCESS; + +} /* end of authProcessRxAuth1Frame() */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/bss.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/bss.c new file mode 100644 index 0000000000000..7f768be22fa38 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/bss.c @@ -0,0 +1,2464 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/bss.c#7 +*/ + +/*! \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. +*/ + + +/******************************************************************************* +* C O M P I L E 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 +******************************************************************************** +*/ + +const PUINT_8 apucNetworkType[NETWORK_TYPE_NUM] = { + (PUINT_8) "AIS", + (PUINT_8) "P2P", + (PUINT_8) "BOW", + (PUINT_8) "MBSS" +}; + +const PUINT_8 apucNetworkOpMode[] = { + (PUINT_8) "INFRASTRUCTURE", + (PUINT_8) "IBSS", + (PUINT_8) "ACCESS_POINT", + (PUINT_8) "P2P_DEVICE", + (PUINT_8) "BOW" +}; + +#if (CFG_SUPPORT_ADHOC) || (CFG_SUPPORT_AAA) +APPEND_VAR_IE_ENTRY_T txBcnIETable[] = { + {(ELEM_HDR_LEN + (RATE_NUM_SW - 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 + , {0, p2pFuncCalculateP2P_IE_NoA, p2pFuncGenerateP2P_IE_NoA} /* 221 */ +#endif /* CFG_ENABLE_WIFI_DIRECT */ +#if CFG_SUPPORT_802_11AC + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP), NULL, rlmRspGenerateVhtCapIE} /*191 */ + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP), NULL, rlmRspGenerateVhtOpIE} /*192 */ + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP_MODE_NOTIFICATION), NULL, rlmRspGenerateVhtOpNotificationIE} /*199 */ +#endif +#if CFG_SUPPORT_MTK_SYNERGY + , {(ELEM_HDR_LEN + ELEM_MIN_LEN_MTK_OUI), NULL, rlmGenerateMTKOuiIE} /* 221 */ +#endif +#if (CFG_SUPPORT_DFS_MASTER == 1) + , {(ELEM_HDR_LEN + ELEM_MIN_LEN_CSA), NULL, rlmGenerateCsaIE} /* 37 */ +#endif + +}; + +APPEND_VAR_IE_ENTRY_T txProbRspIETable[] = { + {(ELEM_HDR_LEN + (RATE_NUM_SW - 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 */ +#if CFG_SUPPORT_802_11AC + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP), NULL, rlmRspGenerateVhtCapIE} /*191 */ + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP), NULL, rlmRspGenerateVhtOpIE} /*192 */ + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP_MODE_NOTIFICATION), NULL, rlmRspGenerateVhtOpNotificationIE} /*199 */ +#endif +#if CFG_SUPPORT_MTK_SYNERGY + , {(ELEM_HDR_LEN + ELEM_MIN_LEN_MTK_OUI), NULL, rlmGenerateMTKOuiIE} /* 221 */ +#endif + +}; + +#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 decide PHY type set of STA_RECORD_T by given BSS_DESC_T for +* Infrastructure or AdHoc Mode. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prBssDesc Received Beacon/ProbeResp from this STA +* @param[out] prStaRec StaRec to be decided PHY type set +* +* @retval VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID bssDetermineStaRecPhyTypeSet(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc, OUT P_STA_RECORD_T prStaRec) +{ + P_WIFI_VAR_T prWifiVar = &prAdapter->rWifiVar; + UINT_8 ucHtOption = FEATURE_ENABLED; + UINT_8 ucVhtOption = FEATURE_ENABLED; + + prStaRec->ucPhyTypeSet = prBssDesc->ucPhyTypeSet; +#if CFG_SUPPORT_BFEE + prStaRec->ucVhtCapNumSoundingDimensions = prBssDesc->ucVhtCapNumSoundingDimensions; +#endif + + /* Decide AIS PHY type set */ + if (prStaRec->eStaType == STA_TYPE_LEGACY_AP) { + 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) +#if CFG_SUPPORT_WAPI + || (prAdapter->prGlueInfo->u2WapiAssocInfoIESz) +#endif + )) { + DBGLOG(BSS, INFO, "Ignore the HT Bit for TKIP as pairwise cipher configed!\n"); + prStaRec->ucPhyTypeSet &= ~(PHY_TYPE_BIT_HT | PHY_TYPE_BIT_VHT); + } + + ucHtOption = prWifiVar->ucStaHt; + ucVhtOption = prWifiVar->ucStaVht; + } + /* Decide P2P GC PHY type set */ + else if (prStaRec->eStaType == STA_TYPE_P2P_GO) { + ucHtOption = prWifiVar->ucP2pGcHt; + ucVhtOption = prWifiVar->ucP2pGcVht; + } + + /* Set HT/VHT capability from Feature Option */ + if (IS_FEATURE_DISABLED(ucHtOption)) + prStaRec->ucPhyTypeSet &= ~PHY_TYPE_BIT_HT; + else if (IS_FEATURE_FORCE_ENABLED(ucHtOption)) + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HT; + + if (IS_FEATURE_DISABLED(ucVhtOption)) + prStaRec->ucPhyTypeSet &= ~PHY_TYPE_BIT_VHT; + else if (IS_FEATURE_FORCE_ENABLED(ucVhtOption)) + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_VHT; + + prStaRec->ucDesiredPhyTypeSet = prStaRec->ucPhyTypeSet & prAdapter->rWifiVar.ucAvailablePhyTypeSet; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will decide PHY type set of BSS_INFO for +* AP Mode. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] fgIsApMode Legacy AP mode or P2P GO +* @param[out] prBssInfo BssInfo to be decided PHY type set +* +* @retval VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID bssDetermineApBssInfoPhyTypeSet(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsPureAp, OUT P_BSS_INFO_T prBssInfo) +{ + P_WIFI_VAR_T prWifiVar = &prAdapter->rWifiVar; + UINT_8 ucHtOption = FEATURE_ENABLED; + UINT_8 ucVhtOption = FEATURE_ENABLED; + + /* Decide AP mode PHY type set */ + if (fgIsPureAp) { + ucHtOption = prWifiVar->ucApHt; + ucVhtOption = prWifiVar->ucApVht; + } + /* Decide P2P GO PHY type set */ + else { + ucHtOption = prWifiVar->ucP2pGoHt; + ucVhtOption = prWifiVar->ucP2pGoVht; + } + + /* Set HT/VHT capability from Feature Option */ + if (IS_FEATURE_DISABLED(ucHtOption)) + prBssInfo->ucPhyTypeSet &= ~PHY_TYPE_BIT_HT; + else if (IS_FEATURE_ENABLED(ucHtOption)) + prBssInfo->ucPhyTypeSet |= PHY_TYPE_BIT_HT; + + if (IS_FEATURE_DISABLED(ucVhtOption)) { + prBssInfo->ucPhyTypeSet &= ~PHY_TYPE_BIT_VHT; + } else if (IS_FEATURE_FORCE_ENABLED(ucVhtOption) || + (IS_FEATURE_ENABLED(ucVhtOption) && (prBssInfo->eBand == BAND_5G))) { + + /* Enable HT capability if VHT is enabled */ + prBssInfo->ucPhyTypeSet |= PHY_TYPE_BIT_VHT; + } + + prBssInfo->ucPhyTypeSet &= prAdapter->rWifiVar.ucAvailablePhyTypeSet; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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 UINT_8 ucBssIndex, IN P_BSS_DESC_T prBssDesc) +{ + P_STA_RECORD_T prStaRec; + UINT_8 ucNonHTPhyTypeSet; + P_CONNECTION_SETTINGS_T prConnSettings; + + ASSERT(prBssDesc); + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* 4 <1> Get a valid STA_RECORD_T */ + prStaRec = cnmGetStaRecByAddress(prAdapter, ucBssIndex, prBssDesc->aucSrcAddr); + if (!prStaRec) { + prStaRec = cnmStaRecAlloc(prAdapter, eStaType, ucBssIndex, prBssDesc->aucSrcAddr); + + if (!prStaRec) { + DBGLOG(BSS, WARN, + "STA_REC entry is full, cannot acquire new entry for [" MACSTR + "]!!\n", MAC2STR(prBssDesc->aucSrcAddr)); + ASSERT(FALSE); + return NULL; + } + + prStaRec->ucStaState = STA_STATE_1; + prStaRec->ucJoinFailureCount = 0; + /* TODO(Kevin): If this is an old entry, we may also reset the ucJoinFailureCount to 0. */ + } + /* 4 <2> Update information from BSS_DESC_T to current P_STA_RECORD_T */ + prStaRec->u2CapInfo = prBssDesc->u2CapInfo; + + prStaRec->u2OperationalRateSet = prBssDesc->u2OperationalRateSet; + prStaRec->u2BSSBasicRateSet = prBssDesc->u2BSSBasicRateSet; + +#if 1 + bssDetermineStaRecPhyTypeSet(prAdapter, prBssDesc, prStaRec); +#else + prStaRec->ucPhyTypeSet = prBssDesc->ucPhyTypeSet; + + if (IS_STA_IN_AIS(prStaRec)) { + if (!((prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION3_ENABLED) || + (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION3_KEY_ABSENT) + || (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION_DISABLED) + || (prAdapter->prGlueInfo->u2WSCAssocInfoIELen) +#if CFG_SUPPORT_WAPI + || (prAdapter->prGlueInfo->u2WapiAssocInfoIESz) +#endif + )) { + 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; +#endif + + 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 */ + prStaRec->u2DesiredNonHTRateSet = (prStaRec->u2OperationalRateSet & prConnSettings->u2DesiredNonHTRateSet); + + /* 4 <3> 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 <4> Update default value */ + prStaRec->fgDiagnoseConnection = FALSE; + + /* 4 <5> Update default value for other Modules */ + /* Determine WMM related parameters for STA_REC */ + mqmProcessScanResult(prAdapter, prBssDesc, prStaRec); + + /* 4 <6> Update Tx Rate */ + /* Update default Tx rate */ + nicTxUpdateStaRecDefaultRate(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; + UINT_8 ucBssIndex; + + ASSERT(prStaRec); + ucBssIndex = prStaRec->ucBssIndex; + + ASSERT(ucBssIndex <= MAX_BSS_INDEX); + + ASSERT(pucBuffer); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + 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; + UINT_8 ucBssIndex; + + ASSERT(prStaRec); + ucBssIndex = prStaRec->ucBssIndex; + + ASSERT(ucBssIndex <= MAX_BSS_INDEX); + + ASSERT(pucBuffer); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + ASSERT(prBssInfo); + + prQoSNullFrame = (P_WLAN_MAC_HEADER_QOS_T) pucBuffer; + + /* 4 <1> Decide the Frame Control Field */ + u2FrameCtrl = MAC_FRAME_QOS_NULL; + + if (IS_AP_STA(prStaRec)) { + u2FrameCtrl |= MASK_FC_TO_DS; + + if (prStaRec->fgSetPwrMgtBit) + u2FrameCtrl |= MASK_FC_PWR_MGT; + + } else if (IS_CLIENT_STA(prStaRec)) { + u2FrameCtrl |= MASK_FC_FROM_DS; + } else if (IS_DLS_STA(prStaRec)) { + /* TODO(Kevin) */ + } else { + /* NOTE(Kevin): We won't send QoS Null frame for IBSS */ + ASSERT(0); + return; + } + + /* 4 <2> Compose the QoS Null frame */ + /* Fill the Frame Control field. */ + /* WLAN_SET_FIELD_16(&prQoSNullFrame->u2FrameCtrl, u2FrameCtrl); */ + prQoSNullFrame->u2FrameCtrl = u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the Address 1 field with Target Peer Address. */ + COPY_MAC_ADDR(prQoSNullFrame->aucAddr1, prStaRec->aucMacAddr); + + /* Fill the Address 2 field with our MAC Address. */ + COPY_MAC_ADDR(prQoSNullFrame->aucAddr2, prBssInfo->aucOwnMacAddr); + + /* Fill the Address 3 field with Target BSSID. */ + COPY_MAC_ADDR(prQoSNullFrame->aucAddr3, prBssInfo->aucBSSID); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ + prQoSNullFrame->u2SeqCtrl = 0; + + u2QosControl = (UINT_16) (ucUP & WMM_QC_UP_MASK); + + if (fgSetEOSP) + u2QosControl |= WMM_QC_EOSP; + + /* WLAN_SET_FIELD_16(&prQoSNullFrame->u2QosCtrl, u2QosControl); */ + prQoSNullFrame->u2QosCtrl = u2QosControl; /* NOTE(Kevin): Optimized for ARM */ + + return; + +} /* end of bssComposeQoSNullFrameHeader() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Send the Null Frame +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] pfTxDoneHandler TX Done call back function +* +* @retval WLAN_STATUS_RESOURCE No available resources to send frame. +* @retval WLAN_STATUS_SUCCESS Succe]ss. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +bssSendNullFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + P_MSDU_INFO_T prMsduInfo; + UINT_16 u2EstimatedFrameLen; + + /* 4 <1> Allocate a PKT_INFO_T for Null Frame */ + /* Init with MGMT Header Length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + WLAN_MAC_HEADER_LEN; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(BSS, WARN, "No PKT_INFO_T for sending Null Frame.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Null frame in MSDU_INfO_T. */ + bssComposeNullFrame(prAdapter, (PUINT_8) ((ULONG) prMsduInfo->prPacket + MAC_TX_RESERVED_FIELD), prStaRec); +#if 0 + /* 4 <3> Update information of MSDU_INFO_T */ + TXM_SET_DATA_PACKET( + /* STA_REC ptr */ prStaRec, + /* MSDU_INFO ptr */ prMsduInfo, + /* MAC HDR ptr */ + (prMsduInfo->pucBuffer + MAC_TX_RESERVED_FIELD), + /* MAC HDR length */ WLAN_MAC_HEADER_LEN, + /* PAYLOAD ptr */ + (prMsduInfo->pucBuffer + MAC_TX_RESERVED_FIELD + WLAN_MAC_HEADER_LEN), + /* PAYLOAD length */ 0, + /* Network Type Index */ (UINT_8) prStaRec->ucNetTypeIndex, + /* TID */ 0 /* BE: AC1 */, + /* Flag 802.11 */ TRUE, + /* Pkt arrival time */ 0 /* TODO: Obtain the system time */, + /* Resource TC */ 0 /* Irrelevant */, + /* Flag 802.1x */ FALSE, + /* TX-done callback */ pfTxDoneHandler, + /* PS forwarding type */ PS_FORWARDING_TYPE_NON_PS, + /* PS Session ID */ 0 /* Irrelevant */, + /* Flag fixed rate */ TRUE, + /* Fixed tx rate */ + g_aprBssInfo[prStaRec->ucNetTypeIndex]->ucHwDefaultFixedRateCode, + /* Fixed-rate retry */ + BSS_DEFAULT_CONN_TEST_NULL_FRAME_RETRY_LIMIT, + /* PAL LLH */ 0 /* Irrelevant */, + /* ACL SN */ 0 /* Irrelevant */, + /* Flag No Ack */ FALSE + ); + + /* Terminate with a NULL pointer */ + NIC_HIF_TX_SET_NEXT_MSDU_INFO(prMsduInfo, NULL); + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ + + /* Indicate the packet to TXM */ + /* 4 <4> Inform TXM to send this Null frame. */ + txmSendFwDataPackets(prMsduInfo); +#endif + + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_HEADER_LEN, WLAN_MAC_HEADER_LEN, pfTxDoneHandler, MSDU_RATE_MODE_AUTO); + + /* 4 <4> Inform TXM to send this Null frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; + +} /* end of bssSendNullFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Send the QoS Null Frame +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] pfTxDoneHandler TX Done call back function +* +* @retval WLAN_STATUS_RESOURCE No available resources to send frame. +* @retval WLAN_STATUS_SUCCESS Success. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +bssSendQoSNullFrame(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, IN UINT_8 ucUP, IN PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + P_MSDU_INFO_T prMsduInfo; + UINT_16 u2EstimatedFrameLen; + + /* 4 <1> Allocate a PKT_INFO_T for Null Frame */ + /* Init with MGMT Header Length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + WLAN_MAC_HEADER_QOS_LEN; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(BSS, WARN, "No PKT_INFO_T for sending Null Frame.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Null frame in MSDU_INfO_T. */ + bssComposeQoSNullFrame(prAdapter, + (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + prStaRec, ucUP, FALSE); +#if 0 + /* 4 <3> Update information of MSDU_INFO_T */ + TXM_SET_DATA_PACKET( + /* STA_REC ptr */ prStaRec, + /* MSDU_INFO ptr */ prMsduInfo, + /* MAC HDR ptr */ + (prMsduInfo->pucBuffer + MAC_TX_RESERVED_FIELD), + /* MAC HDR length */ WLAN_MAC_HEADER_QOS_LEN, + /* PAYLOAD ptr */ + (prMsduInfo->pucBuffer + MAC_TX_RESERVED_FIELD + WLAN_MAC_HEADER_QOS_LEN), + /* PAYLOAD length */ 0, + /* Network Type Index */ (UINT_8) prStaRec->ucNetTypeIndex, + /* TID */ 0 /* BE: AC1 */, + /* Flag 802.11 */ TRUE, + /* Pkt arrival time */ 0 /* TODO: Obtain the system time */, + /* Resource TC */ 0 /* Irrelevant */, + /* Flag 802.1x */ FALSE, + /* TX-done callback */ pfTxDoneHandler, + /* PS forwarding type */ PS_FORWARDING_TYPE_NON_PS, + /* PS Session ID */ 0 /* Irrelevant */, + /* Flag fixed rate */ TRUE, + /* Fixed tx rate */ + g_aprBssInfo[prStaRec->ucNetTypeIndex]->ucHwDefaultFixedRateCode, + /* Fixed-rate retry */ TXM_DEFAULT_DATA_FRAME_RETRY_LIMIT, + /* PAL LLH */ 0 /* Irrelevant */, + /* ACL SN */ 0 /* Irrelevant */, + /* Flag No Ack */ FALSE + ); + + /* Terminate with a NULL pointer */ + NIC_HIF_TX_SET_NEXT_MSDU_INFO(prMsduInfo, NULL); + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ + + /* Indicate the packet to TXM */ + /* 4 <4> Inform TXM to send this Null frame. */ + txmSendFwDataPackets(prMsduInfo); +#endif + + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_HEADER_QOS_LEN, WLAN_MAC_HEADER_QOS_LEN, pfTxDoneHandler, MSDU_RATE_MODE_AUTO); + + /* 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 = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + ASSERT(prBssInfo); + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (ULONG) prMsduInfo->u2FrameLength); + ASSERT(pucBuffer); + + if (prBssInfo->ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) + + ucExtSupRatesLen = prBssInfo->ucAllSupportedRatesLen - ELEM_MAX_LEN_SUP_RATES; + else + ucExtSupRatesLen = 0; + + /* Fill the Extended Supported Rates element. */ + if (ucExtSupRatesLen) { + + EXT_SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_EXTENDED_SUP_RATES; + EXT_SUP_RATES_IE(pucBuffer)->ucLength = ucExtSupRatesLen; + + kalMemCopy(EXT_SUP_RATES_IE(pucBuffer)->aucExtSupportedRates, + &prBssInfo->aucAllSupportedRates[ELEM_MAX_LEN_SUP_RATES], ucExtSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + } +} /* end of bssGenerateExtSuppRate_IE() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to compose Common Information Elements for Beacon +* or Probe Response Frame. +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* @param[in] prBssInfo Pointer to the BSS_INFO_T. +* @param[in] pucDestAddr Pointer to the Destination Address, if NULL, means Beacon. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bssBuildBeaconProbeRespFrameCommonIEs(IN P_MSDU_INFO_T prMsduInfo, IN P_BSS_INFO_T prBssInfo, IN PUINT_8 pucDestAddr) +{ + PUINT_8 pucBuffer; + UINT_8 ucSupRatesLen; + + ASSERT(prMsduInfo); + ASSERT(prBssInfo); + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (ULONG) prMsduInfo->u2FrameLength); + ASSERT(pucBuffer); + + /* Compose the frame body of the Probe Response frame. */ + /* 4 <1> Fill the SSID element. */ + SSID_IE(pucBuffer)->ucId = ELEM_ID_SSID; +#if 0 + SSID_IE(pucBuffer)->ucLength = prBssInfo->ucSSIDLen; + if (prBssInfo->ucSSIDLen) + kalMemCopy(SSID_IE(pucBuffer)->aucSSID, prBssInfo->aucSSID, prBssInfo->ucSSIDLen); +#else + if (prBssInfo->eHiddenSsidType == ENUM_HIDDEN_SSID_LEN) { + if ((!pucDestAddr) && /* For Beacon only. */ + (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { + SSID_IE(pucBuffer)->ucLength = 0; + } else { /* probe response */ + SSID_IE(pucBuffer)->ucLength = prBssInfo->ucSSIDLen; + if (prBssInfo->ucSSIDLen) + kalMemCopy(SSID_IE(pucBuffer)->aucSSID, prBssInfo->aucSSID, prBssInfo->ucSSIDLen); + } + } else { + SSID_IE(pucBuffer)->ucLength = prBssInfo->ucSSIDLen; + if (prBssInfo->ucSSIDLen) + kalMemCopy(SSID_IE(pucBuffer)->aucSSID, prBssInfo->aucSSID, prBssInfo->ucSSIDLen); + } +#endif + + 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->eNetworkType == NETWORK_TYPE_P2P) { +#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 */ + /* Find the smallest number. */ + /* Find the largest even number. */ + u4N1 = (prP2pSpecificBssInfo->u2SmallestAID >> 4) << 1; + u4N2 = prP2pSpecificBssInfo->u2LargestAID >> 3; + + ASSERT(u4N2 >= u4N1); + + kalMemCopy(TIM_IE(pucBuffer)->aucPartialVirtualMap, + &prP2pSpecificBssInfo->aucPartialVirtualBitmap[u4N1], ((u4N2 - u4N1) + 1)); + + /* Set Virtual Bitmap for BMCAST */ + /* BMC bit only indicated when DTIM count == 0. */ + if (prBssInfo->ucDTIMCount == 0) + ucBitmapControl = prP2pSpecificBssInfo->ucBitmapCtrl; + + TIM_IE(pucBuffer)->ucBitmapControl = ucBitmapControl | (UINT_8) u4N1; + + TIM_IE(pucBuffer)->ucLength = ((u4N2 - u4N1) + 4); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); +#else + + /* IEEE 802.11 2007 - 7.3.2.6 */ + TIM_IE(pucBuffer)->ucId = ELEM_ID_TIM; + /* NOTE: fixed PVB length (AID is allocated from 8 ~ 15 only) */ + TIM_IE(pucBuffer)->ucLength = (3 + MAX_LEN_TIM_PARTIAL_BMP) /*((u4N2 - u4N1) + 4) */; + TIM_IE(pucBuffer)->ucDTIMCount = 0 /*prBssInfo->ucDTIMCount */; + /* will be overwritten by FW */ + TIM_IE(pucBuffer)->ucDTIMPeriod = prBssInfo->ucDTIMPeriod; + /* will be overwritten by FW */ + TIM_IE(pucBuffer)->ucBitmapControl = 0 /*ucBitmapControl | (UINT_8)u4N1 */; + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + +#endif + + } else +#endif /* CFG_ENABLE_WIFI_DIRECT */ + { + /* NOTE(Kevin): 1. AIS - Didn't Support AP Mode. + * 2. BOW - Didn't Support BCAST and PS. + */ + } + + } +} /* end of bssBuildBeaconProbeRespFrameCommonIEs() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the Beacon/Probe Response frame header and +* its fixed fields. +* +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] pucDestAddr Pointer to the Destination Address, if NULL, means Beacon. +* @param[in] pucOwnMACAddress Given Our MAC Address. +* @param[in] pucBSSID Given BSSID of the BSS. +* @param[in] u2BeaconInterval Given Beacon Interval. +* @param[in] u2CapInfo Given Capability Info. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bssComposeBeaconProbeRespFrameHeaderAndFF(IN PUINT_8 pucBuffer, + IN PUINT_8 pucDestAddr, + IN PUINT_8 pucOwnMACAddress, + IN PUINT_8 pucBSSID, IN UINT_16 u2BeaconInterval, IN UINT_16 u2CapInfo) +{ + P_WLAN_BEACON_FRAME_T prBcnProbRspFrame; + UINT_8 aucBCAddr[] = BC_MAC_ADDR; + UINT_16 u2FrameCtrl; + + DEBUGFUNC("bssComposeBeaconProbeRespFrameHeaderAndFF"); + /* DBGLOG(INIT, LOUD, ("\n")); */ + + ASSERT(pucBuffer); + ASSERT(pucOwnMACAddress); + ASSERT(pucBSSID); + + prBcnProbRspFrame = (P_WLAN_BEACON_FRAME_T) pucBuffer; + + /* 4 <1> Compose the frame header of the Beacon /ProbeResp frame. */ + /* Fill the Frame Control field. */ + if (pucDestAddr) { + u2FrameCtrl = MAC_FRAME_PROBE_RSP; + } else { + u2FrameCtrl = MAC_FRAME_BEACON; + pucDestAddr = aucBCAddr; + } + /* WLAN_SET_FIELD_16(&prBcnProbRspFrame->u2FrameCtrl, u2FrameCtrl); */ + prBcnProbRspFrame->u2FrameCtrl = u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the DA field with BCAST MAC ADDR or TA of ProbeReq. */ + COPY_MAC_ADDR(prBcnProbRspFrame->aucDestAddr, pucDestAddr); + + /* Fill the SA field with our MAC Address. */ + COPY_MAC_ADDR(prBcnProbRspFrame->aucSrcAddr, pucOwnMACAddress); + + /* Fill the BSSID field with current BSSID. */ + COPY_MAC_ADDR(prBcnProbRspFrame->aucBSSID, pucBSSID); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ + prBcnProbRspFrame->u2SeqCtrl = 0; + + /* 4 <2> Compose the frame body's common fixed field part of the Beacon /ProbeResp frame. */ + /* MAC will update TimeStamp field */ + + /* Fill the Beacon Interval field. */ + /* WLAN_SET_FIELD_16(&prBcnProbRspFrame->u2BeaconInterval, u2BeaconInterval); */ + prBcnProbRspFrame->u2BeaconInterval = u2BeaconInterval; /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the Capability Information field. */ + /* WLAN_SET_FIELD_16(&prBcnProbRspFrame->u2CapInfo, u2CapInfo); */ + prBcnProbRspFrame->u2CapInfo = u2CapInfo; /* NOTE(Kevin): Optimized for ARM */ +} /* end of bssComposeBeaconProbeRespFrameHeaderAndFF() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Update the Beacon Frame Template to FW for AIS AdHoc and P2P GO. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] ucBssIndex Specify which network reply the Probe Response. +* +* @retval WLAN_STATUS_SUCCESS Success. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS bssUpdateBeaconContent(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex) +{ + 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(ucBssIndex <= MAX_BSS_INDEX); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + /* 4 <1> Allocate a PKT_INFO_T for Beacon Frame */ + /* Allocate a MSDU_INFO_T */ + /* For Beacon */ + prMsduInfo = prBssInfo->prBeacon; + + /* beacon prMsduInfo will be NULLify once BSS deactivated, so skip if it is */ + if (prMsduInfo == NULL) + return WLAN_STATUS_SUCCESS; + + /* 4 <2> Compose header */ + bssComposeBeaconProbeRespFrameHeaderAndFF((PUINT_8) + ((ULONG) (prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD), NULL, + prBssInfo->aucOwnMacAddr, prBssInfo->aucBSSID, + prBssInfo->u2BeaconInterval, prBssInfo->u2CapInfo); + + prMsduInfo->u2FrameLength = (WLAN_MAC_MGMT_HEADER_LEN + + (TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN)); + + prMsduInfo->ucBssIndex = ucBssIndex; + + /* 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, + ucBssIndex, + 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] ucBssIndex 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 UINT_8 ucBssIndex, 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(ucBssIndex <= MAX_BSS_INDEX); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + 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, ucBssIndex, NULL); + } + } + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(BSS, WARN, "No PKT_INFO_T for sending %s.\n", ((!pucDestAddr) ? "Beacon" : "Probe Response")); + return WLAN_STATUS_RESOURCES; + } + + /* 4 <2> Compose Beacon/Probe Response frame header and fixed fields in MSDU_INfO_T. */ + /* Compose Header and Fixed Field */ +#if CFG_ENABLE_WIFI_DIRECT + if (u4ControlFlags & BSS_PROBE_RESP_USE_P2P_DEV_ADDR) { + if (prAdapter->fgIsP2PRegistered) { + bssComposeBeaconProbeRespFrameHeaderAndFF((PUINT_8) + ((ULONG) (prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD), + pucDestAddr, + prAdapter->rWifiVar.aucDeviceAddress, + prAdapter->rWifiVar.aucDeviceAddress, + DOT11_BEACON_PERIOD_DEFAULT, + (prBssInfo->u2CapInfo & ~(CAP_INFO_ESS | + CAP_INFO_IBSS))); + } + } else +#endif /* CFG_ENABLE_WIFI_DIRECT */ + { + bssComposeBeaconProbeRespFrameHeaderAndFF((PUINT_8) + ((ULONG) (prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD), pucDestAddr, + prBssInfo->aucOwnMacAddr, + prBssInfo->aucBSSID, + prBssInfo->u2BeaconInterval, prBssInfo->u2CapInfo); + } + + /* 4 <3> Update information of MSDU_INFO_T */ + + TX_SET_MMPDU(prAdapter, + prMsduInfo, + ucBssIndex, + STA_REC_INDEX_NOT_FOUND, + WLAN_MAC_MGMT_HEADER_LEN, + (WLAN_MAC_MGMT_HEADER_LEN + TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + + CAP_INFO_FIELD_LEN), NULL, MSDU_RATE_MODE_AUTO); + + /* 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); + + } + + /* Set limited retry count and lifetime for Probe Resp is reasonable */ + nicTxSetPktLifeTime(prMsduInfo, 100); + nicTxSetPktRetryLimit(prMsduInfo, 2); + + /* 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; + UINT_8 ucBssIndex; + 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 (ucBssIndex = 0; ucBssIndex <= P2P_DEV_BSS_INDEX; ucBssIndex++) { + + if (!IS_NET_ACTIVE(prAdapter, ucBssIndex)) + continue; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if ((!fgIsBcBssid) && UNEQUAL_MAC_ADDR(prBssInfo->aucBSSID, prMgtHdr->aucBSSID)) + continue; + + eBand = HAL_RX_STATUS_GET_RF_BAND(prSwRfb->prRxStatus); + ucHwChannelNum = HAL_RX_STATUS_GET_CHNL_NUM(prSwRfb->prRxStatus); + + if (prBssInfo->eBand != eBand) + continue; + + if (prBssInfo->ucPrimaryChannel != ucHwChannelNum) + continue; + + fgReplyProbeResp = FALSE; + + if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) { + +#if CFG_SUPPORT_ADHOC + fgReplyProbeResp = aisValidateProbeReq(prAdapter, prSwRfb, &u4CtrlFlagsForProbeResp); +#endif + } +#if CFG_ENABLE_WIFI_DIRECT + else if ((prAdapter->fgIsP2PRegistered) + && (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) + && (prAdapter->rP2PNetRegState + == ENUM_NET_REG_STATE_REGISTERED)) { + + fgReplyProbeResp = + p2pFuncValidateProbeReq(prAdapter, prSwRfb, &u4CtrlFlagsForProbeResp, + (prBssInfo->ucBssIndex == P2P_DEV_BSS_INDEX), + (UINT_8) prBssInfo->u4PrivateData); + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (prBssInfo->eNetworkType == NETWORK_TYPE_BOW) + fgReplyProbeResp = bowValidateProbeReq(prAdapter, prSwRfb, &u4CtrlFlagsForProbeResp); +#endif + + if (fgReplyProbeResp) { + if (nicTxGetFreeCmdCount(prAdapter) > (CFG_TX_MAX_CMD_PKT_NUM / 2)) { + /* Resource margin is enough */ + bssSendBeaconProbeResponse(prAdapter, ucBssIndex, + 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_SW) + 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 (eNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { + + if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + + /* TODO(Kevin): Check if we are IBSS Master. */ + + 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 (eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + + /* 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, 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) { + + if (prIeSupportedRate || prIeExtSupportedRate) { + UINT_16 u2OperationalRateSet, u2BSSBasicRateSet; + BOOLEAN fgIsUnknownBssBasicRate; + /* Ignore any Basic Bit */ + rateGetRateSetFromIEs(prIeSupportedRate, prIeExtSupportedRate, + &u2OperationalRateSet, + &u2BSSBasicRateSet, &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 (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) { */ +/* } */ + + /* TODO(Kevin): Check P2P IE and WPS IE */ + } +#endif + } +#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 initialize 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 bssInitializeClientList(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)) + LINK_INITIALIZE(prStaRecOfClientList); + + DBGLOG(BSS, INFO, "Init BSS[%u] Client List\n", prBssInfo->ucBssIndex); + + bssCheckClientList(prAdapter, prBssInfo); +} /* 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 bssAddClient(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_STA_RECORD_T prStaRec) +{ + P_LINK_T prClientList; + P_STA_RECORD_T prCurrStaRec; + + ASSERT(prBssInfo); + + prClientList = &prBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH_ENTRY(prCurrStaRec, prClientList, 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(prClientList, &prStaRec->rLinkEntry); + + bssCheckClientList(prAdapter, prBssInfo); +} /* 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) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN bssRemoveClient(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_STA_RECORD_T prStaRec) +{ + P_LINK_T prClientList; + P_STA_RECORD_T prCurrStaRec; + + ASSERT(prBssInfo); + + prClientList = &prBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH_ENTRY(prCurrStaRec, prClientList, rLinkEntry, STA_RECORD_T) { + + if (prCurrStaRec == prStaRec) { + + LINK_REMOVE_KNOWN_ENTRY(prClientList, &prStaRec->rLinkEntry); + + return TRUE; + } + } + + DBGLOG(BSS, INFO, "Current Client List didn't contain that STA_RECORD_T[" + MACSTR "] before removing.\n", MAC2STR(prStaRec->aucMacAddr)); + + bssCheckClientList(prAdapter, prBssInfo); + + return FALSE; +} /* end of bssRemoveStaRecFromClientList() */ + +P_STA_RECORD_T bssRemoveClientByMac(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN PUINT_8 pucMac) +{ + P_LINK_T prClientList; + P_STA_RECORD_T prCurrStaRec; + + ASSERT(prBssInfo); + + prClientList = &prBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH_ENTRY(prCurrStaRec, prClientList, rLinkEntry, STA_RECORD_T) { + + if (EQUAL_MAC_ADDR(prCurrStaRec->aucMacAddr, pucMac)) { + + LINK_REMOVE_KNOWN_ENTRY(prClientList, &prCurrStaRec->rLinkEntry); + + return prCurrStaRec; + } + } + + DBGLOG(BSS, INFO, "Current Client List didn't contain that STA_RECORD_T[" + MACSTR "] before removing.\n", MAC2STR(pucMac)); + + bssCheckClientList(prAdapter, prBssInfo); + + return NULL; +} + +P_STA_RECORD_T bssGetClientByMac(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN PUINT_8 pucMac) +{ + P_LINK_T prClientList; + P_STA_RECORD_T prCurrStaRec; + + ASSERT(prBssInfo); + + prClientList = &prBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH_ENTRY(prCurrStaRec, prClientList, rLinkEntry, STA_RECORD_T) { + + if (EQUAL_MAC_ADDR(prCurrStaRec->aucMacAddr, pucMac)) + return prCurrStaRec; + } + + DBGLOG(BSS, INFO, "Current Client List didn't contain that STA_RECORD_T[" + MACSTR "] before removing.\n", MAC2STR(pucMac)); + + bssCheckClientList(prAdapter, prBssInfo); + + return NULL; +} + +P_STA_RECORD_T bssRemoveHeadClient(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo) +{ + P_LINK_T prStaRecOfClientList; + P_STA_RECORD_T prStaRec = NULL; + + ASSERT(prBssInfo); + + prStaRecOfClientList = &prBssInfo->rStaRecOfClientList; + + if (!LINK_IS_EMPTY(prStaRecOfClientList)) + LINK_REMOVE_HEAD(prStaRecOfClientList, prStaRec, P_STA_RECORD_T); + + bssCheckClientList(prAdapter, prBssInfo); + + return prStaRec; +} + +UINT_32 bssGetClientCount(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo) +{ + return prBssInfo->rStaRecOfClientList.u4NumElem; +} + +VOID bssDumpClientList(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo) +{ + P_LINK_T prClientList; + P_STA_RECORD_T prCurrStaRec; + UINT_8 ucCount = 0; + + ASSERT(prBssInfo); + + prClientList = &prBssInfo->rStaRecOfClientList; + + DBGLOG(SW4, INFO, "Dump BSS[%u] Client List NUM[%u]\n", prBssInfo->ucBssIndex, prClientList->u4NumElem); + + LINK_FOR_EACH_ENTRY(prCurrStaRec, prClientList, rLinkEntry, STA_RECORD_T) { + + if (!prCurrStaRec) { + DBGLOG(SW4, INFO, "[%2u] is NULL STA_REC\n", ucCount); + break; + } + DBGLOG(SW4, INFO, "[%2u] STA[%u] [" MACSTR "]\n", ucCount, + prCurrStaRec->ucIndex, MAC2STR(prCurrStaRec->aucMacAddr)); + + ucCount++; + } +} + +VOID bssCheckClientList(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo) +{ + P_LINK_T prClientList; + P_STA_RECORD_T prCurrStaRec; + UINT_8 ucCount = 0; + BOOLEAN fgError = FALSE; + + ASSERT(prBssInfo); + + prClientList = &prBssInfo->rStaRecOfClientList; + + /* Check MAX number */ + if (prClientList->u4NumElem > P2P_MAXIMUM_CLIENT_COUNT) { + DBGLOG(SW4, INFO, "BSS[%u] Client List NUM[%u] ERR\n", prBssInfo->ucBssIndex, prClientList->u4NumElem); + + fgError = TRUE; + } + + /* Check default list status */ + if (prClientList->u4NumElem == 0) { + if ((PVOID) prClientList->prNext != (PVOID) prClientList) + fgError = TRUE; + if ((PVOID) prClientList->prPrev != (PVOID) prClientList) + fgError = TRUE; + + if (fgError) { + DBGLOG(SW4, INFO, "BSS[%u] Client List PTR next/prev[%p/%p] ERR\n", + prBssInfo->ucBssIndex, prClientList->prNext, prClientList->prPrev); + } + } + + /* Traverse list */ + LINK_FOR_EACH_ENTRY(prCurrStaRec, prClientList, rLinkEntry, STA_RECORD_T) { + if (!prCurrStaRec) { + fgError = TRUE; + DBGLOG(SW4, INFO, "BSS[%u] Client List NULL PTR ERR\n", prBssInfo->ucBssIndex); + + break; + } + + ucCount++; + } + + /* Check real count and list number */ + if (ucCount != prClientList->u4NumElem) { + DBGLOG(SW4, INFO, "BSS[%u] Client List NUM[%u] REAL CNT[%u] ERR\n", + prBssInfo->ucBssIndex, prClientList->u4NumElem, ucCount); + + fgError = TRUE; + } + + if (fgError) + bssDumpClientList(prAdapter, prBssInfo); + +} + +#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, prAdapter->prAisBssInfo->ucBssIndex, 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->ucBssIndex == prAdapter->prAisBssInfo->ucBssIndex) && 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, + prAdapter->prAisBssInfo->ucBssIndex, 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->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + prAisIbssPeerFoundMsg->prStaRec = prStaRec; + + /* Inform AIS to do STATE TRANSITION + * For Case I - If AIS in IBSS_ALONE, let it jump to NORMAL_TR after we know the new member. + * For Case III, IV - Now this new BSSID wins the TSF, follow it. + */ + if (fgIsSameBSSID) { + prAisIbssPeerFoundMsg->fgIsMergeIn = TRUE; + } else { +#if CFG_SLT_SUPPORT + prAisIbssPeerFoundMsg->fgIsMergeIn = TRUE; +#else + prAisIbssPeerFoundMsg->fgIsMergeIn = (prBssDesc->fgIsLargerTSF) ? FALSE : TRUE; +#endif + } + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisIbssPeerFoundMsg, MSG_SEND_METHOD_BUF); + + } +} /* end of ibssProcessMatchedBeacon() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will check the Capability for Ad-Hoc to decide if we are +* able to merge with(same capability). +* +* @param[in] prBSSDesc Pointer to the BSS Descriptor. +* +* @retval WLAN_STATUS_FAILURE Can't pass the check of Capability. +* @retval WLAN_STATUS_SUCCESS Pass the check of Capability. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS ibssCheckCapabilityForAdHocMode(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prBssDesc); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + do { + /* 4 <1> Check the BSS Basic Rate Set for current AdHoc Mode */ + if ((prConnSettings->eAdHocMode == AD_HOC_MODE_11B) && + (prBssDesc->u2BSSBasicRateSet & ~RATE_SET_HR_DSSS)) { + break; + } else if ((prConnSettings->eAdHocMode == AD_HOC_MODE_11A) && + (prBssDesc->u2BSSBasicRateSet & ~RATE_SET_OFDM)) { + break; + } + /* 4 <2> Check the Short Slot Time. */ +#if 0 /* Do not check ShortSlotTime until Wi-Fi define such policy */ + if (prConnSettings->eAdHocMode == AD_HOC_MODE_11G) { + if (((prConnSettings->fgIsShortSlotTimeOptionEnable) && + !(prBssDesc->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME)) || + (!(prConnSettings->fgIsShortSlotTimeOptionEnable) && + (prBssDesc->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME))) { + break; + } + } +#endif + + /* 4 <3> Check the ATIM window setting. */ + if (prBssDesc->u2ATIMWindow) { + DBGLOG(BSS, INFO, "AdHoc PS was not supported(ATIM Window: %d)\n", prBssDesc->u2ATIMWindow); + break; + } + /* 4 <4> Check the Security setting. */ + if (!rsnPerformPolicySelection(prAdapter, prBssDesc)) + break; + + 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 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 && + /* Short Preamble Option Enable is TRUE */ + ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_SHORT) || + (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 */ + nicTxUpdateBssDefaultRate(prBssInfo); +} /* 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) +{ + 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] = { 6, 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; + + /* 4 <1.1> Mask CCK 1M For Sco scenario except FDD mode */ + if (prAdapter->u4FddMode == FALSE) + prBssInfo->u2BSSBasicRateSet &= ~RATE_SET_BIT_1M; + /* prBssInfo->u2OperationalRateSet &= ~RATE_SET_BIT_1M; */ + + 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 && + /* Short Preamble Option Enable is TRUE */ + ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_SHORT) || + (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 */ + nicTxUpdateBssDefaultRate(prBssInfo); + + /* 4 <7> Fill the EDCA */ + + prACQueParms = prBssInfo->arACQueParmsForBcast; + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + + prACQueParms[eAci].ucIsACMSet = 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].ucIsACMSet, 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].ucIsACMSet = 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].ucIsACMSet, prACQueParms[eAci].u2Aifsn, + prACQueParms[eAci].u2CWmin, prACQueParms[eAci].u2CWmax, prACQueParms[eAci].u2TxopLimit); + } + + /* Note: Caller should update the EDCA setting to HW by nicQmUpdateWmmParms() it there is no AIS network */ + /* Note: In E2, only 4 HW queues. The the Edca parameters should be folow by AIS network */ + /* Note: In E3, 8 HW queues. the Wmm parameters should be updated to right queues according to BSS */ +} /* end of bssInitForAP() */ + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* @brief Update DTIM Count +* +* @param[in] eNetTypeIndex Specify which network to update +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bssUpdateDTIMCount(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex) +{ + P_BSS_INFO_T prBssInfo; + + ASSERT(eNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); + + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + + /* Setup DTIM Count for next TBTT. */ + if (prBssInfo->ucDTIMCount > 0) { + prBssInfo->ucDTIMCount--; + } else { + + ASSERT(prBssInfo->ucDTIMPeriod > 0); + + prBssInfo->ucDTIMCount = prBssInfo->ucDTIMPeriod - 1; + } + } +} /* end of bssUpdateDTIMIE() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to set the Virtual Bitmap in TIM Information Elements +* +* @param[in] prBssInfo Pointer to the BSS_INFO_T. +* @param[in] u2AssocId The association id to set in Virtual Bitmap. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bssSetTIMBitmap(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN UINT_16 u2AssocId) +{ + + ASSERT(prBssInfo); + + if (prBssInfo->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo; + + prP2pSpecificBssInfo = &(prAdapter->rWifiVar.rP2pSpecificBssInfo); + + /* Use Association ID == 0 for BMCAST indication */ + if (u2AssocId == 0) { + + prP2pSpecificBssInfo->ucBitmapCtrl |= (UINT_8) BIT(0); + } else { + PUINT_8 pucPartialVirtualBitmap; + UINT_8 ucBitmapToSet; + + pucPartialVirtualBitmap = &prP2pSpecificBssInfo->aucPartialVirtualBitmap[(u2AssocId >> 3)]; + ucBitmapToSet = (UINT_8) BIT((u2AssocId % 8)); + + if (*pucPartialVirtualBitmap & ucBitmapToSet) { + /* The virtual bitmap has been set */ + return; + } + + *pucPartialVirtualBitmap |= ucBitmapToSet; + + /* Update u2SmallestAID and u2LargestAID */ + if ((u2AssocId < prP2pSpecificBssInfo->u2SmallestAID) || + (prP2pSpecificBssInfo->u2SmallestAID == 0)) { + prP2pSpecificBssInfo->u2SmallestAID = u2AssocId; + } + + if ((u2AssocId > prP2pSpecificBssInfo->u2LargestAID) || + (prP2pSpecificBssInfo->u2LargestAID == 0)) { + prP2pSpecificBssInfo->u2LargestAID = u2AssocId; + } + } + } +} /* end of bssSetTIMBitmap() */ +#endif + +#endif /* CFG_SUPPORT_AAA */ + +VOID bssCreateStaRecFromAuth(IN P_ADAPTER_T prAdapter) +{ + +} + +VOID bssUpdateStaRecFromAssocReq(IN P_ADAPTER_T prAdapter) +{ + +} + +VOID bssDumpBssInfo(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex) +{ + P_BSS_INFO_T prBssInfo; + /* P_LINK_T prStaRecOfClientList = (P_LINK_T) NULL; */ + /* P_STA_RECORD_T prCurrStaRec = (P_STA_RECORD_T) NULL; */ + + if (ucBssIndex > MAX_BSS_INDEX) { + DBGLOG(SW4, INFO, "Invalid BssInfo index[%u], skip dump!\n", ucBssIndex); + return; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (!prBssInfo) { + DBGLOG(SW4, INFO, "Invalid BssInfo index[%u], skip dump!\n", ucBssIndex); + return; + } + + DBGLOG(SW4, INFO, "OWNMAC[" MACSTR "] BSSID[" MACSTR "] SSID[%s]\n", + MAC2STR(prBssInfo->aucOwnMacAddr), MAC2STR(prBssInfo->aucBSSID), prBssInfo->aucSSID); + + DBGLOG(SW4, INFO, "BSS IDX[%u] Type[%s] OPMode[%s] ConnState[%u] Absent[%u]\n", + prBssInfo->ucBssIndex, + apucNetworkType[prBssInfo->eNetworkType], + apucNetworkOpMode[prBssInfo->eCurrentOPMode], prBssInfo->eConnectionState, prBssInfo->fgIsNetAbsent); + + DBGLOG(SW4, INFO, + "Channel[%u] Band[%u] SCO[%u] Assoc40mBwAllowed[%u] 40mBwAllowed[%u] MaxBw[%u] Nss[%u] eDBDCBand[%u]\n", + prBssInfo->ucPrimaryChannel, prBssInfo->eBand, prBssInfo->eBssSCO, + prBssInfo->fgAssoc40mBwAllowed, prBssInfo->fg40mBwAllowed, + cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex), + prBssInfo->ucNss, prBssInfo->eDBDCBand); + + DBGLOG(SW4, INFO, "QBSS[%u] CapInfo[0x%04x] AID[%u]\n", + prBssInfo->fgIsQBSS, prBssInfo->u2CapInfo, prBssInfo->u2AssocId); + + DBGLOG(SW4, INFO, "ShortPreamble Allowed[%u] EN[%u], ShortSlotTime[%u]\n", + prBssInfo->fgIsShortPreambleAllowed, prBssInfo->fgUseShortPreamble, prBssInfo->fgUseShortSlotTime); + + DBGLOG(SW4, INFO, "PhyTypeSet: Basic[0x%02x] NonHtBasic[0x%02x]\n", + prBssInfo->ucPhyTypeSet, prBssInfo->ucNonHTBasicPhyType); + + DBGLOG(SW4, INFO, "RateSet: BssBasic[0x%04x] Operational[0x%04x]\n", + prBssInfo->u2BSSBasicRateSet, prBssInfo->u2OperationalRateSet); + + DBGLOG(SW4, INFO, "ATIMWindow[%u] DTIM Period[%u] Count[%u]\n", + prBssInfo->u2ATIMWindow, prBssInfo->ucDTIMPeriod, prBssInfo->ucDTIMCount); + + DBGLOG(SW4, INFO, "HT Operation Info1[0x%02x] Info2[0x%04x] Info3[0x%04x]\n", + prBssInfo->ucHtOpInfo1, prBssInfo->u2HtOpInfo2, prBssInfo->u2HtOpInfo3); + + DBGLOG(SW4, INFO, "ProtectMode HT[%u] ERP[%u], OperationMode GF[%u] RIFS[%u]\n", + prBssInfo->eHtProtectMode, + prBssInfo->fgErpProtectMode, prBssInfo->eGfOperationMode, prBssInfo->eRifsOperationMode); + + DBGLOG(SW4, INFO, "(OBSS) ProtectMode HT[%u] ERP[%u], OperationMode GF[%u] RIFS[%u]\n", + prBssInfo->eObssHtProtectMode, + prBssInfo->fgObssErpProtectMode, prBssInfo->eObssGfOperationMode, prBssInfo->fgObssRifsOperationMode); + + DBGLOG(SW4, INFO, "VhtChannelWidth[%u] OpChangeChannelWidth[%u], IsOpChangeChannelWidth[%u]\n", + prBssInfo->ucVhtChannelWidth, + prBssInfo->ucOpChangeChannelWidth, prBssInfo->fgIsOpChangeChannelWidth); + + DBGLOG(SW4, INFO, "======== Dump Connected Client ========\n"); + +#if 0 + DBGLOG(SW4, INFO, "NumOfClient[%u]\n", bssGetClientCount(prAdapter, prBssInfo)); + + prStaRecOfClientList = &prBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH_ENTRY(prCurrStaRec, prStaRecOfClientList, rLinkEntry, STA_RECORD_T) { + DBGLOG(SW4, INFO, "STA[%u] [" MACSTR "]\n", prCurrStaRec->ucIndex, MAC2STR(prCurrStaRec->aucMacAddr)); + } +#else + bssDumpClientList(prAdapter, prBssInfo); +#endif + + DBGLOG(SW4, INFO, "============== Dump Done ==============\n"); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/cnm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/cnm.c new file mode 100644 index 0000000000000..3b17b22c1d060 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/cnm.c @@ -0,0 +1,1614 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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 +*/ + + +/******************************************************************************* +* C O M P I L E 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 +******************************************************************************** +*/ +#if CFG_SUPPORT_DBDC +#define DBDC_SWITCH_GUARD_TIME (4*1000) /*ms*/ +#define DBDC_DISABLE_COUNTDOWN_TIME (2*1000) /*ms*/ +#endif /*CFG_SUPPORT_DBDC*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +#if CFG_SUPPORT_DBDC +typedef enum _ENUM_CNM_DBDC_DECISION_TIMER_T { + DBDC_DECISION_TIMER_SWITCH_GUARD_TIME, + DBDC_DECISION_TIMER_DISABLE_COUNT_DOWN, + DBDC_DECISION_STATE_NUM +} ENUM_CNM_DBDC_DECISION_TIMER_T, *P_ENUM_CNM_DBDC_DECISION_TIMER_T; +#endif /*CFG_SUPPORT_DBDC*/ + +/******************************************************************************* +* P U B 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) +{ + P_CNM_INFO_T prCnmInfo; + + ASSERT(prAdapter); + + prCnmInfo = &prAdapter->rCnmInfo; + prCnmInfo->fgChGranted = FALSE; +#if CFG_SUPPORT_DBDC + cnmTimerInitTimer(prAdapter, + &prAdapter->rWifiVar.rDBDCSwitchGuardTimer, + (PFN_MGMT_TIMEOUT_FUNC)cnmDbdcDecision, + (ULONG)DBDC_DECISION_TIMER_SWITCH_GUARD_TIME); + + cnmTimerInitTimer(prAdapter, + &prAdapter->rWifiVar.rDBDCDisableCountdownTimer, + (PFN_MGMT_TIMEOUT_FUNC)cnmDbdcDecision, + (ULONG)DBDC_DECISION_TIMER_DISABLE_COUNT_DOWN); +#endif /*CFG_SUPPORT_DBDC*/ +} /* end of cnmInit()*/ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to initialize variables in CNM_INFO_T. +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmUninit(P_ADAPTER_T prAdapter) +{ +} /* end of cnmUninit()*/ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Before handle the message from other module, it need to obtain +* the Channel privilege from Channel Manager +* +* @param[in] prMsgHdr The message need to be handled. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmChMngrRequestPrivilege(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr) +{ + P_MSG_CH_REQ_T prMsgChReq; + P_CMD_CH_PRIVILEGE_T prCmdBody; + WLAN_STATUS rStatus; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prMsgChReq = (P_MSG_CH_REQ_T)prMsgHdr; + + prCmdBody = (P_CMD_CH_PRIVILEGE_T) + cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_CH_PRIVILEGE_T)); + ASSERT(prCmdBody); + + /* To do: exception handle */ + if (!prCmdBody) { + DBGLOG(CNM, ERROR, "ChReq: fail to get buf (net=%d, token=%d)\n", + prMsgChReq->ucBssIndex, prMsgChReq->ucTokenID); + + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + DBGLOG(CNM, INFO, "ChReq net=%d token=%d b=%d c=%d s=%d w=%d\n", + prMsgChReq->ucBssIndex, prMsgChReq->ucTokenID, + prMsgChReq->eRfBand, prMsgChReq->ucPrimaryChannel, prMsgChReq->eRfSco, prMsgChReq->eRfChannelWidth); + + prCmdBody->ucBssIndex = prMsgChReq->ucBssIndex; + 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->ucRfChannelWidth = (UINT_8)prMsgChReq->eRfChannelWidth; + prCmdBody->ucRfCenterFreqSeg1 = (UINT_8)prMsgChReq->ucRfCenterFreqSeg1; + prCmdBody->ucRfCenterFreqSeg2 = (UINT_8)prMsgChReq->ucRfCenterFreqSeg2; + prCmdBody->ucReqType = (UINT_8)prMsgChReq->eReqType; + prCmdBody->ucDBDCBand = (UINT_8)prMsgChReq->eDBDCBand; + prCmdBody->aucReserved = 0; + prCmdBody->u4MaxInterval = prMsgChReq->u4MaxInterval; + prCmdBody->aucReserved2[0] = 0; + prCmdBody->aucReserved2[1] = 0; + prCmdBody->aucReserved2[2] = 0; + prCmdBody->aucReserved2[3] = 0; + prCmdBody->aucReserved2[4] = 0; + prCmdBody->aucReserved2[5] = 0; + prCmdBody->aucReserved2[6] = 0; + prCmdBody->aucReserved2[7] = 0; + + ASSERT(prCmdBody->ucBssIndex <= MAX_BSS_INDEX); + + /* For monkey testing 20110901 */ + if (prCmdBody->ucBssIndex > MAX_BSS_INDEX) + DBGLOG(CNM, ERROR, "CNM: ChReq with wrong netIdx=%d\n\n", prCmdBody->ucBssIndex); + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_CH_PRIVILEGE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_CH_PRIVILEGE_T), /* u4SetQueryInfoLen */ + (PUINT_8)prCmdBody, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + /* ASSERT(rStatus == WLAN_STATUS_PENDING); */ + + cnmMemFree(prAdapter, prCmdBody); + cnmMemFree(prAdapter, prMsgHdr); +} /* end of cnmChMngrRequestPrivilege()*/ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Before deliver the message to other module, it need to release +* the Channel privilege to Channel Manager. +* +* @param[in] prMsgHdr The message need to be delivered +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmChMngrAbortPrivilege(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr) +{ + P_MSG_CH_ABORT_T prMsgChAbort; + P_CMD_CH_PRIVILEGE_T prCmdBody; + P_CNM_INFO_T prCnmInfo; + WLAN_STATUS rStatus; +#if CFG_SISO_SW_DEVELOP + P_BSS_INFO_T prBssInfo; +#endif + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prMsgChAbort = (P_MSG_CH_ABORT_T)prMsgHdr; + + /* Check if being granted channel privilege is aborted */ + prCnmInfo = &prAdapter->rCnmInfo; + if (prCnmInfo->fgChGranted && + prCnmInfo->ucBssIndex == prMsgChAbort->ucBssIndex && prCnmInfo->ucTokenID == prMsgChAbort->ucTokenID) { + + prCnmInfo->fgChGranted = FALSE; + } + + 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->ucBssIndex, prMsgChAbort->ucTokenID); + + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + prCmdBody->ucBssIndex = prMsgChAbort->ucBssIndex; + prCmdBody->ucTokenID = prMsgChAbort->ucTokenID; + prCmdBody->ucAction = CMD_CH_ACTION_ABORT; /* Abort */ + prCmdBody->ucDBDCBand = (UINT_8)prMsgChAbort->eDBDCBand; + + DBGLOG(CNM, INFO, "ChAbort net=%d token=%d dbdc=%u\n", + prCmdBody->ucBssIndex, prCmdBody->ucTokenID, prCmdBody->ucDBDCBand); + + ASSERT(prCmdBody->ucBssIndex <= MAX_BSS_INDEX); + + /* For monkey testing 20110901 */ + if (prCmdBody->ucBssIndex > MAX_BSS_INDEX) + DBGLOG(CNM, ERROR, "CNM: ChAbort with wrong netIdx=%d\n\n", prCmdBody->ucBssIndex); + + 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); */ + +#if CFG_SISO_SW_DEVELOP + prBssInfo = prAdapter->aprBssInfo[prMsgChAbort->ucBssIndex]; + /* Driver clear granted CH in BSS info */ + prBssInfo->fgIsGranted = FALSE; + prBssInfo->eBandGranted = BAND_NULL; + prBssInfo->ucPrimaryChannelGranted = 0; +#endif + + cnmMemFree(prAdapter, prCmdBody); + cnmMemFree(prAdapter, prMsgHdr); +} /* end of cnmChMngrAbortPrivilege()*/ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmChMngrHandleChEvent(P_ADAPTER_T prAdapter, P_WIFI_EVENT_T prEvent) +{ + P_EVENT_CH_PRIVILEGE_T prEventBody; + P_MSG_CH_GRANT_T prChResp; + P_BSS_INFO_T prBssInfo; + P_CNM_INFO_T prCnmInfo; + + 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->ucBssIndex, prEventBody->ucTokenID); + + return; + } + + DBGLOG(CNM, INFO, "ChGrant net=%d token=%d ch=%d sco=%d\n", + prEventBody->ucBssIndex, prEventBody->ucTokenID, prEventBody->ucPrimaryChannel, prEventBody->ucRfSco); + + ASSERT(prEventBody->ucBssIndex <= MAX_BSS_INDEX); + ASSERT(prEventBody->ucStatus == EVENT_CH_STATUS_GRANT); + + prBssInfo = prAdapter->aprBssInfo[prEventBody->ucBssIndex]; + + /* Decide message ID based on network and response status */ + if (IS_BSS_AIS(prBssInfo)) + prChResp->rMsgHdr.eMsgId = MID_CNM_AIS_CH_GRANT; +#if CFG_ENABLE_WIFI_DIRECT + else if (prAdapter->fgIsP2PRegistered && IS_BSS_P2P(prBssInfo)) + prChResp->rMsgHdr.eMsgId = MID_CNM_P2P_CH_GRANT; +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (IS_BSS_BOW(prBssInfo)) + prChResp->rMsgHdr.eMsgId = MID_CNM_BOW_CH_GRANT; +#endif + else { + cnmMemFree(prAdapter, prChResp); + return; + } + + prChResp->ucBssIndex = prEventBody->ucBssIndex; + prChResp->ucTokenID = prEventBody->ucTokenID; + prChResp->ucPrimaryChannel = prEventBody->ucPrimaryChannel; + prChResp->eRfSco = (ENUM_CHNL_EXT_T)prEventBody->ucRfSco; + prChResp->eRfBand = (ENUM_BAND_T)prEventBody->ucRfBand; + prChResp->eRfChannelWidth = (ENUM_CHANNEL_WIDTH_T)prEventBody->ucRfChannelWidth; + prChResp->ucRfCenterFreqSeg1 = prEventBody->ucRfCenterFreqSeg1; + prChResp->ucRfCenterFreqSeg2 = prEventBody->ucRfCenterFreqSeg2; + prChResp->eReqType = (ENUM_CH_REQ_TYPE_T)prEventBody->ucReqType; + prChResp->eDBDCBand = (ENUM_DBDC_BN_T)prEventBody->ucDBDCBand; + prChResp->u4GrantInterval = prEventBody->u4GrantInterval; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T)prChResp, MSG_SEND_METHOD_BUF); + + /* Record current granted BSS for TXM's reference */ + prCnmInfo = &prAdapter->rCnmInfo; + prCnmInfo->ucBssIndex = prEventBody->ucBssIndex; + prCnmInfo->ucTokenID = prEventBody->ucTokenID; + prCnmInfo->fgChGranted = TRUE; +} + +#if (CFG_SUPPORT_DFS_MASTER == 1) +VOID cnmRadarDetectEvent(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_EVENT_RDD_REPORT_T prEventBody; + P_BSS_INFO_T prBssInfo; + P_MSG_P2P_RADAR_DETECT_T prP2pRddDetMsg; + UINT_8 ucBssIndex; + + DBGLOG(CNM, INFO, "cnmRadarDetectEvent.\n"); + + prEventBody = (P_EVENT_RDD_REPORT_T)(prEvent->aucBuffer); + + prP2pRddDetMsg = (P_MSG_P2P_RADAR_DETECT_T) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(*prP2pRddDetMsg)); + + if (!prP2pRddDetMsg) { + DBGLOG(CNM, ERROR, "cnmMemAlloc for prP2pRddDetMsg failed!\n"); + return; + } + + prP2pRddDetMsg->rMsgHdr.eMsgId = MID_CNM_P2P_RADAR_DETECT; + + for (ucBssIndex = 0; ucBssIndex < BSS_INFO_NUM; ucBssIndex++) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (prBssInfo && prBssInfo->fgIsDfsActive) { + prP2pRddDetMsg->ucBssIndex = ucBssIndex; + break; + } + } + + p2pFuncSetDfsState(DFS_STATE_DETECTED); + + p2pFuncRadarInfoInit(); + + g_rP2pRadarInfo.ucRadarReportMode = prEventBody->ucRadarReportMode; + g_rP2pRadarInfo.ucRddIdx = prEventBody->ucRddIdx; + g_rP2pRadarInfo.ucLongDetected = prEventBody->ucLongDetected; + g_rP2pRadarInfo.ucPeriodicDetected = prEventBody->ucPeriodicDetected; + g_rP2pRadarInfo.ucLPBNum = prEventBody->ucLPBNum; + g_rP2pRadarInfo.ucPPBNum = prEventBody->ucPPBNum; + g_rP2pRadarInfo.ucLPBPeriodValid = prEventBody->ucLPBPeriodValid; + g_rP2pRadarInfo.ucLPBWidthValid = prEventBody->ucLPBWidthValid; + g_rP2pRadarInfo.ucPRICountM1 = prEventBody->ucPRICountM1; + g_rP2pRadarInfo.ucPRICountM1TH = prEventBody->ucPRICountM1TH; + g_rP2pRadarInfo.ucPRICountM2 = prEventBody->ucPRICountM2; + g_rP2pRadarInfo.ucPRICountM2TH = prEventBody->ucPRICountM2TH; + g_rP2pRadarInfo.u4PRI1stUs = prEventBody->u4PRI1stUs; + kalMemCopy(&g_rP2pRadarInfo.arLpbContent[0], &prEventBody->arLpbContent[0], + prEventBody->ucLPBNum*sizeof(LONG_PULSE_BUFFER_T)); + kalMemCopy(&g_rP2pRadarInfo.arPpbContent[0], &prEventBody->arPpbContent[0], + prEventBody->ucPPBNum*sizeof(PERIODIC_PULSE_BUFFER_T)); + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T)prP2pRddDetMsg, MSG_SEND_METHOD_BUF); +} + +VOID cnmCsaDoneEvent(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_BSS_INFO_T prBssInfo; + P_MSG_P2P_CSA_DONE_T prP2pCsaDoneMsg; + UINT_8 ucBssIndex; + + DBGLOG(CNM, INFO, "cnmCsaDoneEvent.\n"); + + prP2pCsaDoneMsg = (P_MSG_P2P_CSA_DONE_T) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(*prP2pCsaDoneMsg)); + + if (!prP2pCsaDoneMsg) { + DBGLOG(CNM, ERROR, "cnmMemAlloc for prP2pCsaDoneMsg failed!\n"); + return; + } + + prAdapter->rWifiVar.fgCsaInProgress = FALSE; + + prP2pCsaDoneMsg->rMsgHdr.eMsgId = MID_CNM_P2P_CSA_DONE; + + for (ucBssIndex = 0; ucBssIndex < BSS_INFO_NUM; ucBssIndex++) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (prBssInfo && prBssInfo->fgIsDfsActive) { + prP2pCsaDoneMsg->ucBssIndex = ucBssIndex; + break; + } + } + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T)prP2pCsaDoneMsg, MSG_SEND_METHOD_BUF); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @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; + UINT_8 i; + + ASSERT(prAdapter); + ASSERT(prBand); + ASSERT(pucPrimaryChannel); + ASSERT(prBssSCO); + + for (i = 0; i < BSS_INFO_NUM; i++) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, i); + + if (prBssInfo) { + if (IS_BSS_AIS(prBssInfo) && 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) +{ + P_BSS_INFO_T prBssInfo; + UINT_8 i; + P_WIFI_VAR_T prWifiVar = &prAdapter->rWifiVar; + + ASSERT(prAdapter); + + if (prWifiVar->u4ScanCtrl & SCN_CTRL_DEFAULT_SCAN_CTRL) { + /*DBGLOG(CNM, INFO, "cnmAisInfraChannelFixed: ByPass AIS channel Fix check\n");*/ + return FALSE; + } + + for (i = 0; i < BSS_INFO_NUM; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + +#if 0 + DBGLOG(INIT, INFO, "%s BSS[%u] active[%u] netType[%u]\n", + __func__, i, prBssInfo->fgIsNetActive, prBssInfo->eNetworkType); +#endif + + if (!IS_NET_ACTIVE(prAdapter, i)) + continue; + +#if CFG_ENABLE_WIFI_DIRECT + if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) { + BOOLEAN fgFixedChannel = + p2pFuncIsAPMode(prAdapter->rWifiVar.prP2PConnSettings[prBssInfo->u4PrivateData]); + + if (fgFixedChannel) { + + *prBand = prBssInfo->eBand; + *pucPrimaryChannel = prBssInfo->ucPrimaryChannel; + + return TRUE; + + } + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI && CFG_BOW_LIMIT_AIS_CHNL + if (prBssInfo->eNetworkType == NETWORK_TYPE_BOW) { + *prBand = prBssInfo->eBand; + *pucPrimaryChannel = prBssInfo->ucPrimaryChannel; + + return TRUE; + } +#endif + + } + + return FALSE; +} + +#if CFG_SUPPORT_CHNL_CONFLICT_REVISE +BOOLEAN cnmAisDetectP2PChannel(P_ADAPTER_T prAdapter, P_ENUM_BAND_T prBand, PUINT_8 pucPrimaryChannel) +{ + UINT_8 i = 0; + P_BSS_INFO_T prBssInfo; +#if CFG_ENABLE_WIFI_DIRECT + for (; i < BSS_INFO_NUM; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + if (prBssInfo->eNetworkType != NETWORK_TYPE_P2P) + continue; + if (prBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED || + (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT && prBssInfo->eIntendOPMode == OP_MODE_NUM)) { + *prBand = prBssInfo->eBand; + *pucPrimaryChannel = prBssInfo->ucPrimaryChannel; + return TRUE; + } + } +#endif + return FALSE; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmAisInfraConnectNotify(P_ADAPTER_T prAdapter) +{ +#if CFG_ENABLE_BT_OVER_WIFI + P_BSS_INFO_T prBssInfo, prAisBssInfo, prBowBssInfo; + UINT_8 i; + + ASSERT(prAdapter); + + prAisBssInfo = NULL; + prBowBssInfo = NULL; + + for (i = 0; i < BSS_INFO_NUM; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + + if (prBssInfo && IS_BSS_ACTIVE(prBssInfo)) { + if (IS_BSS_AIS(prBssInfo)) + prAisBssInfo = prBssInfo; + else if (IS_BSS_BOW(prBssInfo)) + prBowBssInfo = prBssInfo; + } + } + + if (prAisBssInfo && prBowBssInfo && 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) +{ + P_BSS_INFO_T prBssInfo; + UINT_8 i; + + ASSERT(prAdapter); + + /* P2P device network shall be included */ + for (i = 0; i <= BSS_INFO_NUM; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + + if (prBssInfo && IS_BSS_ACTIVE(prBssInfo) && !IS_BSS_AIS(prBssInfo)) + return FALSE; + } + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param (none) +* +* @return TRUE: permitted +* FALSE: Not permitted +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN cnmP2PIsPermitted(P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prBssInfo; + UINT_8 i; + BOOLEAN fgBowIsActive; + + ASSERT(prAdapter); + + fgBowIsActive = FALSE; + + for (i = 0; i < BSS_INFO_NUM; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + + if (prBssInfo && IS_BSS_ACTIVE(prBssInfo)) { + if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) + return FALSE; + else if (IS_BSS_BOW(prBssInfo)) + fgBowIsActive = TRUE; + } + } + +#if CFG_ENABLE_BT_OVER_WIFI + if (fgBowIsActive) { + /* 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; + UINT_8 i; + + ASSERT(prAdapter); + + /* P2P device network shall be included */ + for (i = 0; i <= BSS_INFO_NUM; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + + if (prBssInfo && IS_BSS_ACTIVE(prBssInfo) && + (IS_BSS_P2P(prBssInfo) || prBssInfo->eCurrentOPMode == OP_MODE_IBSS)) { + return FALSE; + } + } + + return TRUE; +} + + + +static UINT_8 cnmGetAPBwPermitted(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex) +{ + P_BSS_INFO_T prBssInfo; + UINT_8 ucAPBandwidth = MAX_BW_160MHZ; + P_BSS_DESC_T prBssDesc = NULL; + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T)NULL; + UINT_8 i = 0; + UINT_8 ucOffset = (MAX_BW_80MHZ - CW_80MHZ); + + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + + if (IS_BSS_AIS(prBssInfo)) { + /*AIS station mode*/ + prBssDesc = prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc; + } else if (IS_BSS_P2P(prBssInfo)) { + /* P2P mode */ + + for (i = 0 ; i < BSS_P2P_NUM; i++) { + + if (!prAdapter->rWifiVar.aprP2pRoleFsmInfo[i]) + continue; + + if (prAdapter->rWifiVar.aprP2pRoleFsmInfo[i]->ucBssIndex == ucBssIndex) + break; + + } + + if (i >= BSS_P2P_NUM) { + prP2pRoleFsmInfo = NULL; + } else { + prP2pRoleFsmInfo = prAdapter->rWifiVar.aprP2pRoleFsmInfo[i]; + + /*only GC need to consider GO's BW*/ + if (!p2pFuncIsAPMode(prAdapter->rWifiVar.prP2PConnSettings[prBssInfo->u4PrivateData])) + prBssDesc = prP2pRoleFsmInfo->rJoinInfo.prTargetBssDesc; + + } + + + } + + if (prBssDesc) { + if (prBssDesc->eChannelWidth == CW_20_40MHZ) { + if ((prBssDesc->eSco == CHNL_EXT_SCA) || (prBssDesc->eSco == CHNL_EXT_SCB)) + ucAPBandwidth = MAX_BW_40MHZ; + else + ucAPBandwidth = MAX_BW_20MHZ; + } else { + ucAPBandwidth = prBssDesc->eChannelWidth + ucOffset; + } + + } + + return ucAPBandwidth; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param (none) +* +* @return TRUE: permitted +* FALSE: Not permitted +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN cnmBss40mBwPermitted(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex) +{ + ASSERT(prAdapter); + + /* 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 + */ + + /* Decide max bandwidth by feature option */ + if (cnmGetBssMaxBw(prAdapter, ucBssIndex) < MAX_BW_40MHZ) + return FALSE; + + /*check AP or GO capbility for Station or GC */ + if (cnmGetAPBwPermitted(prAdapter, ucBssIndex) < MAX_BW_40MHZ) + return FALSE; +#if 0 + /* Decide max by other BSS */ + for (i = 0; i < BSS_INFO_NUM; i++) { + if (i != ucBssIndex) { + prBssInfo = prAdapter->aprBssInfo[i]; + + if (prBssInfo && IS_BSS_ACTIVE(prBssInfo) && + (prBssInfo->fg40mBwAllowed || prBssInfo->fgAssoc40mBwAllowed)) + return FALSE; + } + } +#endif + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param (none) +* +* @return TRUE: permitted +* FALSE: Not permitted +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN cnmBss80mBwPermitted(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex) +{ + ASSERT(prAdapter); + + /* 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 + */ + + /* Check 40Mhz first */ + if (!cnmBss40mBwPermitted(prAdapter, ucBssIndex)) + return FALSE; + + /* Decide max bandwidth by feature option */ + if (cnmGetBssMaxBw(prAdapter, ucBssIndex) < MAX_BW_80MHZ) + return FALSE; + + /*check AP or GO capbility for Station or GC */ + if (cnmGetAPBwPermitted(prAdapter, ucBssIndex) < MAX_BW_80MHZ) + return FALSE; + + return TRUE; +} + +UINT_8 cnmGetBssMaxBw(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex) +{ + P_BSS_INFO_T prBssInfo; + UINT_8 ucMaxBandwidth = MAX_BW_80_80_MHZ; /*chip capability*/ + P_BSS_DESC_T prBssDesc = NULL; + ENUM_BAND_T eBand = BAND_NULL; + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + P_P2P_CONNECTION_REQ_INFO_T prP2pConnReqInfo = (P_P2P_CONNECTION_REQ_INFO_T) NULL; +#if (CFG_SUPPORT_SINGLE_SKU == 1) + UINT_8 ucChannelBw = MAX_BW_80_80_MHZ; +#endif + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (IS_BSS_AIS(prBssInfo)) { + /* STA mode */ + + + /*should check Bss_info could be used or not + *the info might not be trustable before state3 + */ + + prBssDesc = prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc; + if (prBssDesc) + eBand = prBssDesc->eBand; + else + eBand = prBssInfo->eBand; + + + ASSERT(eBand != BAND_NULL); + + if (eBand == BAND_2G4) + ucMaxBandwidth = prAdapter->rWifiVar.ucSta2gBandwidth; + else + ucMaxBandwidth = prAdapter->rWifiVar.ucSta5gBandwidth; + + if (ucMaxBandwidth > prAdapter->rWifiVar.ucStaBandwidth) + ucMaxBandwidth = prAdapter->rWifiVar.ucStaBandwidth; + } else if (IS_BSS_P2P(prBssInfo)) { + prP2pRoleFsmInfo = p2pFuncGetRoleByBssIdx(prAdapter, ucBssIndex); + if (!prAdapter->rWifiVar.ucApChnlDefFromCfg && prP2pRoleFsmInfo + && prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + prP2pConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + ucMaxBandwidth = prP2pConnReqInfo->eChnlBw; + } else { + /* AP mode */ + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2PConnSettings[prBssInfo->u4PrivateData])) { + if (prBssInfo->eBand == BAND_2G4) + ucMaxBandwidth = prAdapter->rWifiVar.ucAp2gBandwidth; + else + ucMaxBandwidth = prAdapter->rWifiVar.ucAp5gBandwidth; + + if (ucMaxBandwidth > prAdapter->rWifiVar.ucApBandwidth) + ucMaxBandwidth = prAdapter->rWifiVar.ucApBandwidth; + } + /* P2P mode */ + else { + if (prBssInfo->eBand == BAND_2G4) + ucMaxBandwidth = prAdapter->rWifiVar.ucP2p2gBandwidth; + else + ucMaxBandwidth = prAdapter->rWifiVar.ucP2p5gBandwidth; + } + + } + + } + +#if (CFG_SUPPORT_SINGLE_SKU == 1) + if (IS_BSS_AIS(prBssInfo) && prBssDesc) + ucChannelBw = rlmDomainGetChannelBw(prBssDesc->ucChannelNum); + else + ucChannelBw = + rlmDomainGetChannelBw(prBssInfo->ucPrimaryChannel); + if (ucMaxBandwidth > ucChannelBw) + ucMaxBandwidth = ucChannelBw; +#endif + DBGLOG(CNM, INFO, "pCH=%d, BW=%d\n", + prBssInfo->ucPrimaryChannel, ucMaxBandwidth); + + return ucMaxBandwidth; +} + + +UINT_8 cnmGetBssMaxBwToChnlBW(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex) +{ + UINT_8 ucMaxBandwidth = cnmGetBssMaxBw(prAdapter, ucBssIndex); + return ucMaxBandwidth == MAX_BW_20MHZ ? ucMaxBandwidth : (ucMaxBandwidth - 1); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Search available HW ID and BSS_INFO structure and initialize +* these parameters, i.e., fgIsNetActive, ucBssIndex, eNetworkType +* and ucOwnMacIndex +* +* @param (none) +* +* @return +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_INFO_T cnmGetBssInfoAndInit(P_ADAPTER_T prAdapter, ENUM_NETWORK_TYPE_T eNetworkType, BOOLEAN fgIsP2pDevice) +{ + P_BSS_INFO_T prBssInfo; + UINT_8 i, ucBssIndex, ucOwnMacIdx; + + ASSERT(prAdapter); + + /*specific case for p2p device scan*/ + if (eNetworkType == NETWORK_TYPE_P2P && fgIsP2pDevice) { + prBssInfo = prAdapter->aprBssInfo[P2P_DEV_BSS_INDEX]; + + prBssInfo->fgIsInUse = TRUE; + prBssInfo->ucBssIndex = P2P_DEV_BSS_INDEX; + prBssInfo->eNetworkType = eNetworkType; + prBssInfo->ucOwnMacIndex = HW_BSSID_NUM; +#if CFG_SUPPORT_PNO + prBssInfo->fgIsPNOEnable = FALSE; + prBssInfo->fgIsNetRequestInActive = FALSE; +#endif + + /* initialize wlan id and status for keys */ + prBssInfo->ucBMCWlanIndex = WTBL_RESERVED_ENTRY; + prBssInfo->wepkeyWlanIdx = WTBL_RESERVED_ENTRY; + for (i = 0; i < MAX_KEY_NUM; i++) { + prBssInfo->ucBMCWlanIndexSUsed[i] = FALSE; + prBssInfo->ucBMCWlanIndexS[i] = WTBL_RESERVED_ENTRY; + prBssInfo->wepkeyUsed[i] = FALSE; + } + return prBssInfo; + } + + /*reserve ownMAC0 for MBSS*/ + ucOwnMacIdx = (eNetworkType == NETWORK_TYPE_MBSS) ? 0 : 1; + + /* Find available HW set with the order 1,2,..*/ + do { + for (ucBssIndex = 0; ucBssIndex < BSS_INFO_NUM; ucBssIndex++) { + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + + if (prBssInfo && prBssInfo->fgIsInUse && ucOwnMacIdx == prBssInfo->ucOwnMacIndex) + break; + } + + if (ucBssIndex >= BSS_INFO_NUM) { + /* No hit the ucOwnMacIndex could be assigned to this new bss */ + break; + } + } while (++ucOwnMacIdx < HW_BSSID_NUM); + + + /*should not dispatch P2P_DEV_BSS_INDEX (HW_BSSID_NUM)to general bss, + *It means total BSS_INFO_NUM BSS are created, + *no more reseve for MBSS + */ + if (ucOwnMacIdx == HW_BSSID_NUM) { + + for (ucBssIndex = 0; ucBssIndex < BSS_INFO_NUM; ucBssIndex++) { + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + + /*If the Bss was alredy assigned, and in use*/ + if (prBssInfo && prBssInfo->fgIsInUse && prBssInfo->ucOwnMacIndex == 0) + break; + } + + if (ucBssIndex >= BSS_INFO_NUM) { + /*there is no NETWORK_TYPE_MBSS used before */ + DBGLOG(INIT, WARN, + "[Warning] too much Bss in use, take reserve OwnMac(%d)for usage!\n", + ucOwnMacIdx); + ucOwnMacIdx = 0; + } + + } + + /* Find available BSS_INFO */ + for (ucBssIndex = 0; ucBssIndex < BSS_INFO_NUM; ucBssIndex++) { + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + + if (prBssInfo && !prBssInfo->fgIsInUse) { + prBssInfo->fgIsInUse = TRUE; + prBssInfo->ucBssIndex = ucBssIndex; + prBssInfo->eNetworkType = eNetworkType; + prBssInfo->ucOwnMacIndex = ucOwnMacIdx; +#if (CFG_HW_WMM_BY_BSS == 1) + prBssInfo->ucWmmQueSet = DEFAULT_HW_WMM_INDEX; + prBssInfo->fgIsWmmInited = FALSE; +#endif + break; + } + } + + if (ucOwnMacIdx >= HW_BSSID_NUM || ucBssIndex >= BSS_INFO_NUM) + prBssInfo = NULL; + if (prBssInfo) { +#if CFG_SUPPORT_PNO + prBssInfo->fgIsPNOEnable = FALSE; + prBssInfo->fgIsNetRequestInActive = FALSE; +#endif + + /* initialize wlan id and status for keys */ + prBssInfo->ucBMCWlanIndex = WTBL_RESERVED_ENTRY; + prBssInfo->wepkeyWlanIdx = WTBL_RESERVED_ENTRY; + for (i = 0; i < MAX_KEY_NUM; i++) { + prBssInfo->ucBMCWlanIndexSUsed[i] = FALSE; + prBssInfo->ucBMCWlanIndexS[i] = WTBL_RESERVED_ENTRY; + prBssInfo->wepkeyUsed[i] = FALSE; + } + } + return prBssInfo; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Search available HW ID and BSS_INFO structure and initialize +* these parameters, i.e., ucBssIndex, eNetworkType and ucOwnMacIndex +* +* @param (none) +* +* @return +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmFreeBssInfo(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) +{ + ASSERT(prAdapter); + ASSERT(prBssInfo); + + prBssInfo->fgIsInUse = FALSE; +} + +#if CFG_SUPPORT_DBDC +VOID cnmInitDbdcSetting(IN P_ADAPTER_T prAdapter) +{ + /* Parameter decision */ + switch (prAdapter->rWifiVar.ucDbdcMode) { + case DBDC_MODE_DISABLED: + case DBDC_MODE_DYNAMIC: + cnmUpdateDbdcSetting(prAdapter, FALSE); + break; + + case DBDC_MODE_STATIC: + cnmUpdateDbdcSetting(prAdapter, TRUE); + break; + + default: + break; + } +} + +VOID cnmUpdateDbdcSetting(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgDbdcEn) +{ + UINT_8 ucWmmSetBitmap = 0; + CMD_DBDC_SETTING_T rDbdcSetting; + P_CMD_DBDC_SETTING_T prCmdBody; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_8 ucBssIndex; + P_BSS_INFO_T prBssInfo; + UINT_8 ucMaxBw; + + DBGLOG(CNM, INFO, "DBDC %s\n", fgDbdcEn ? "Enable" : "Disable"); + + /* Parameter decision */ +#if (CFG_HW_WMM_BY_BSS == 1) + if (fgDbdcEn) { + UINT_8 ucWmmSetBitmapPerBSS; + /* + * As DBDC enabled, for BSS use 2.4g Band, assign related WmmGroupSet bitmask to 1. + * This is used to indicate the WmmGroupSet is associated to Band#1 (otherwise, use for band#0) + */ + for (ucBssIndex = 0; ucBssIndex < BSS_INFO_NUM; ucBssIndex++) { + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + + if (!prBssInfo || prBssInfo->fgIsInUse == FALSE) + continue; + + if (prBssInfo->eBand == BAND_2G4) { + ucWmmSetBitmapPerBSS = prBssInfo->ucWmmQueSet; + ucWmmSetBitmap |= BIT(ucWmmSetBitmapPerBSS); + } + } + ucWmmSetBitmap |= BIT(MAX_HW_WMM_INDEX); /* For P2P Device*/ + } +#else + if (fgDbdcEn) + ucWmmSetBitmap |= BIT(DBDC_2G_WMM_INDEX); +#endif + + /* Send event to FW */ + prCmdBody = (P_CMD_DBDC_SETTING_T)&rDbdcSetting; + + kalMemZero(prCmdBody, sizeof(CMD_DBDC_SETTING_T)); + + prCmdBody->ucDbdcEn = fgDbdcEn; + prCmdBody->ucWmmBandBitmap = ucWmmSetBitmap; + + if (!fgDbdcEn) { + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_DBDC_PARMS, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_DBDC_SETTING_T), /* u4SetQueryInfoLen */ + (PUINT_8)prCmdBody, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */); + } + + for (ucBssIndex = 0; ucBssIndex <= HW_BSSID_NUM; ucBssIndex++) { + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + if (prBssInfo->fgIsInUse && + prBssInfo->fgIsNetActive && + (prBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED || + prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { + + switch (prBssInfo->ucVhtChannelWidth) { + case VHT_OP_CHANNEL_WIDTH_80P80: + ucMaxBw = MAX_BW_160MHZ; + break; + + case VHT_OP_CHANNEL_WIDTH_160: + ucMaxBw = MAX_BW_160MHZ; + break; + + case VHT_OP_CHANNEL_WIDTH_80: + ucMaxBw = MAX_BW_80MHZ; + break; + + case VHT_OP_CHANNEL_WIDTH_20_40: + default: + { + ucMaxBw = MAX_BW_20MHZ; + + if (prBssInfo->eBssSCO != CHNL_EXT_SCN) + ucMaxBw = MAX_BW_40MHZ; + } + break; + } + + if (fgDbdcEn) { + DBGLOG(CNM, INFO, "BSS index[%u] to 1SS\n", ucBssIndex); + rlmChangeOperationMode(prAdapter, + ucBssIndex, + ucMaxBw, + 1); + } else { + DBGLOG(CNM, INFO, "BSS index[%u] to %uSS\n", + ucBssIndex, wlanGetSupportNss(prAdapter, ucBssIndex)); + rlmChangeOperationMode(prAdapter, + ucBssIndex, + ucMaxBw, + wlanGetSupportNss(prAdapter, ucBssIndex)); + } + } + } + + if (fgDbdcEn) { + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_DBDC_PARMS, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_DBDC_SETTING_T), /* u4SetQueryInfoLen */ + (PUINT_8)prCmdBody, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */); + } + + /*DBGLOG(CNM, INFO, "DBDC CMD status %u\n", rStatus);*/ + + if (rStatus == WLAN_STATUS_SUCCESS || rStatus == WLAN_STATUS_PENDING) { + prAdapter->rWifiVar.fgDbDcModeEn = fgDbdcEn; + + for (ucBssIndex = 0; ucBssIndex <= HW_BSSID_NUM; ucBssIndex++) { + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + + if (prBssInfo->eBand == BAND_2G4) { + if (fgDbdcEn) + prBssInfo->eDBDCBand = ENUM_BAND_1; + else + prBssInfo->eDBDCBand = ENUM_BAND_0; + } + } + } +} + +VOID cnmGetDbdcCapability( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucBssIndex, + IN ENUM_BAND_T eRfBand, + IN UINT_8 ucPrimaryChannel, + IN UINT_8 ucNss, + OUT P_CNM_DBDC_CAP_T prDbdcCap +) +{ + if (!prDbdcCap) + return; + + /* BSS index */ + prDbdcCap->ucBssIndex = ucBssIndex; + +#if (CFG_HW_WMM_BY_BSS == 0) + /* WMM set */ + if (eRfBand == BAND_5G) + prDbdcCap->ucWmmSetIndex = DBDC_5G_WMM_INDEX; + else + prDbdcCap->ucWmmSetIndex = + (prAdapter->rWifiVar.ucDbdcMode == DBDC_MODE_DISABLED) ? DBDC_5G_WMM_INDEX : DBDC_2G_WMM_INDEX; +#endif + + /* Nss & band 0/1 */ + switch (prAdapter->rWifiVar.ucDbdcMode) { + case DBDC_MODE_DISABLED: + /* DBDC is disabled, all BSS run on band 0 */ + if (wlanGetSupportNss(prAdapter, ucBssIndex) < ucNss) + prDbdcCap->ucNss = wlanGetSupportNss(prAdapter, ucBssIndex); + else + prDbdcCap->ucNss = ucNss; + break; + + case DBDC_MODE_STATIC: + /* Static DBDC mode, 1SS only */ + prDbdcCap->ucNss = 1; + break; + + case DBDC_MODE_DYNAMIC: + if (prAdapter->rWifiVar.fgDbDcModeEn) + prDbdcCap->ucNss = 1; + else + prDbdcCap->ucNss = wlanGetSupportNss(prAdapter, ucBssIndex); + break; + + default: + break; + } +} + +VOID cnmDbdcEnableDecision( + IN P_ADAPTER_T prAdapter, + IN UINT_8 ucChangedBssIndex, + IN ENUM_BAND_T eRfBand +) +{ + P_BSS_INFO_T prBssInfo; + UINT_8 ucBssIndex; + + if ((prAdapter->rWifiVar.ucDbdcMode != DBDC_MODE_DYNAMIC) && + (prAdapter->rWifiVar.ucDbdcMode != DBDC_MODE_STATIC)) + return; + + if (prAdapter->rWifiVar.fgDbDcModeEn) { + if (timerPendingTimer(&prAdapter->rWifiVar.rDBDCSwitchGuardTimer)) { + /* update timer for connection retry */ + DBGLOG(CNM, INFO, "DBDC guard time extend\n"); + cnmTimerStopTimer(prAdapter, + &prAdapter->rWifiVar.rDBDCSwitchGuardTimer); + cnmTimerStartTimer(prAdapter, + &prAdapter->rWifiVar.rDBDCSwitchGuardTimer, + DBDC_SWITCH_GUARD_TIME); + } + /* The DBDC is already ON, so renew WMM band information only */ + cnmUpdateDbdcSetting(prAdapter, TRUE); + return; + } + + if (timerPendingTimer(&prAdapter->rWifiVar.rDBDCSwitchGuardTimer)) + return; + + if (eRfBand != BAND_2G4 && eRfBand != BAND_5G) + return; + + for (ucBssIndex = 0; ucBssIndex < HW_BSSID_NUM; ucBssIndex++) { + + if (ucBssIndex == ucChangedBssIndex) + continue; + + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + + if (!prBssInfo->fgIsInUse || + !prBssInfo->fgIsNetActive || + (prBssInfo->eConnectionState != PARAM_MEDIA_STATE_CONNECTED && + prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT)) + continue; + + if (prBssInfo->eBand != BAND_2G4 && prBssInfo->eBand != BAND_5G) + continue; + + if (prBssInfo->eBand != eRfBand) { + /* Enable DBDC */ + + /* if disable timer exist, close it*/ + if (timerPendingTimer(&prAdapter->rWifiVar.rDBDCDisableCountdownTimer)) { + cnmTimerStopTimer(prAdapter, + &prAdapter->rWifiVar.rDBDCDisableCountdownTimer); + } + + cnmUpdateDbdcSetting(prAdapter, TRUE); + + /* Start Switch Guard Time */ + cnmTimerStartTimer(prAdapter, + &prAdapter->rWifiVar.rDBDCSwitchGuardTimer, + DBDC_SWITCH_GUARD_TIME); + return; + } + } +} + +VOID cnmDbdcDisableDecision(IN P_ADAPTER_T prAdapter, IN UINT_8 ucChangedBssIndex) +{ + P_BSS_INFO_T prBssInfo; + UINT_8 ucBssIndex; + ENUM_BAND_T eBandCompare; + + if (prAdapter->rWifiVar.ucDbdcMode != DBDC_MODE_DYNAMIC) + return; + + if (!prAdapter->rWifiVar.fgDbDcModeEn) { + if (timerPendingTimer(&prAdapter->rWifiVar.rDBDCSwitchGuardTimer)) { + /* update timer for connection retry */ + DBGLOG(CNM, INFO, "DBDC guard time extend\n"); + cnmTimerStopTimer(prAdapter, + &prAdapter->rWifiVar.rDBDCSwitchGuardTimer); + cnmTimerStartTimer(prAdapter, + &prAdapter->rWifiVar.rDBDCSwitchGuardTimer, + DBDC_SWITCH_GUARD_TIME); + } + return; + } + + if (timerPendingTimer(&prAdapter->rWifiVar.rDBDCDisableCountdownTimer)) + return; + + if (timerPendingTimer(&prAdapter->rWifiVar.rDBDCSwitchGuardTimer)) + return; + + eBandCompare = BAND_NULL; + for (ucBssIndex = 0; ucBssIndex < HW_BSSID_NUM; ucBssIndex++) { + + if (ucBssIndex == ucChangedBssIndex) + continue; + + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + + if (!prBssInfo->fgIsInUse || + !prBssInfo->fgIsNetActive || + (prBssInfo->eConnectionState != PARAM_MEDIA_STATE_CONNECTED && + prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT)) + continue; + + if (prBssInfo->eBand != BAND_2G4 && prBssInfo->eBand != BAND_5G) + continue; + + if (eBandCompare == BAND_NULL) { + eBandCompare = prBssInfo->eBand; + continue; + } + + if (prBssInfo->eBand != eBandCompare) { + /*no need to disable DBDC*/ + return; + } + } + + /* start DBDC disable countdown timer */ + cnmTimerStartTimer(prAdapter, + &prAdapter->rWifiVar.rDBDCDisableCountdownTimer, + DBDC_DISABLE_COUNTDOWN_TIME); +} + + +VOID cnmDbdcDecision(IN P_ADAPTER_T prAdapter, IN ULONG plParamPtr) +{ + P_BSS_INFO_T prBssInfo; + UINT_8 ucBssIndex; + ENUM_BAND_T eBandCompare; + + if (prAdapter->rWifiVar.ucDbdcMode != DBDC_MODE_DYNAMIC) + return; + + /* MTK coding style limitation of "(A=B)?:" + * 1. one line is too long + * 2. cut in ?/: will encounter + * a. ?/: need to add one space after symbol + * b. line end could not have space + * so duplicated the code... + */ + if (plParamPtr == DBDC_DECISION_TIMER_SWITCH_GUARD_TIME) + DBGLOG(CNM, INFO, "DBDC timer timeout : switch guard time end\n"); + else + DBGLOG(CNM, INFO, "DBDC timer timeout : disable countdown finish\n"); + + eBandCompare = BAND_NULL; + for (ucBssIndex = 0; ucBssIndex < HW_BSSID_NUM; ucBssIndex++) { + + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + + if (!prBssInfo->fgIsInUse || + !prBssInfo->fgIsNetActive || + (prBssInfo->eConnectionState != PARAM_MEDIA_STATE_CONNECTED && + prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT)) + continue; + + if (prBssInfo->eBand != BAND_2G4 && prBssInfo->eBand != BAND_5G) + continue; + + if (eBandCompare == BAND_NULL) { + eBandCompare = prBssInfo->eBand; + continue; + } + + if (prBssInfo->eBand != eBandCompare) { + if (!prAdapter->rWifiVar.fgDbDcModeEn) { + /* DBDC Enable */ + cnmUpdateDbdcSetting(prAdapter, TRUE); + cnmTimerStartTimer(prAdapter, + &prAdapter->rWifiVar.rDBDCSwitchGuardTimer, + DBDC_SWITCH_GUARD_TIME); + } + return; + } + } + + if (prAdapter->rWifiVar.fgDbDcModeEn) { + /* DBDC Disable */ + cnmUpdateDbdcSetting(prAdapter, FALSE); + cnmTimerStartTimer(prAdapter, &prAdapter->rWifiVar.rDBDCSwitchGuardTimer, DBDC_SWITCH_GUARD_TIME); + return; + } +} + +#endif /*CFG_SUPPORT_DBDC*/ + +#if (CFG_HW_WMM_BY_BSS == 1) +/*----------------------------------------------------------------------------*/ +/*! +* @brief Search available HW WMM index. +* +* @param (none) +* +* @return +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 cnmWmmIndexDecision(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo) +{ + UINT_8 ucWmmIndex; + + for (ucWmmIndex = 0; ucWmmIndex < HW_WMM_NUM; ucWmmIndex++) { + if (prBssInfo && prBssInfo->fgIsInUse && prBssInfo->fgIsWmmInited == FALSE) { + if (!(prAdapter->ucHwWmmEnBit & BIT(ucWmmIndex))) { + prAdapter->ucHwWmmEnBit |= BIT(ucWmmIndex); + prBssInfo->fgIsWmmInited = TRUE; + break; + } + } + } + return (ucWmmIndex < HW_WMM_NUM) ? ucWmmIndex : MAX_HW_WMM_INDEX; +} +/*----------------------------------------------------------------------------*/ +/*! +* @brief Free BSS HW WMM index. +* +* @param (none) +* +* @return None +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmFreeWmmIndex(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo) +{ + prAdapter->ucHwWmmEnBit &= (~BIT(prBssInfo->ucWmmQueSet)); + prBssInfo->ucWmmQueSet = DEFAULT_HW_WMM_INDEX; + prBssInfo->fgIsWmmInited = FALSE; +} +#endif /* #if (CFG_HW_WMM_BY_BSS == 1) */ +/*----------------------------------------------------------------------------*/ +/*! +* @brief Release pending timer. +* +* @param (none) +* +* @return None +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmCheckPendingTimer(P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prAisBssInfo; + P_AIS_FSM_INFO_T prAisFsmInfo; + + if (prAdapter == NULL) + return; + + /* Timer 1: rJoinTimeoutTimer + * Driver couldn't get any CH_GRANT event of CH_REQ after resume + * Because pending AIS join timer should do CH_ABORT to FW. + * Without CH_ABORT cmd, FW CNM's FSM would keep in GRANT stage. + * FW's CNM couldn't service any other CH_REQ in GRANT stage. + * As a result, checking the timer in suspend flow. + */ + prAisBssInfo = prAdapter->prAisBssInfo; + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + if (timerPendingTimer(&prAisFsmInfo->rJoinTimeoutTimer)) { + DBGLOG(CNM, STATE, "[AIS] pending rJoinTimeoutTimer\n"); + cnmTimerStopTimer(prAdapter, + &prAisFsmInfo->rJoinTimeoutTimer); + /* Release Channel */ + aisFsmReleaseCh(prAdapter); + prAisFsmInfo->fgIsInfraChannelFinished = TRUE; + } +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/cnm_mem.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/cnm_mem.c new file mode 100644 index 0000000000000..de58e9274895d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/cnm_mem.c @@ -0,0 +1,1582 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +static PUINT_8 apucStaRecType[STA_TYPE_INDEX_NUM] = { + (PUINT_8) "LEGACY", + (PUINT_8) "P2P", + (PUINT_8) "BOW" +}; + +static PUINT_8 apucStaRecRole[STA_ROLE_INDEX_NUM] = { + (PUINT_8) "ADHOC", + (PUINT_8) "CLIENT", + (PUINT_8) "AP", + (PUINT_8) "DLS" +}; + +#if CFG_SUPPORT_TDLS +/* The list of valid data rates. */ +const UINT_8 aucValidDataRate[] = { + 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_VHT_PHY, /* RATE_VHT_PHY_INDEX */ + RATE_HT_PHY /* RATE_HT_PHY_INDEX */ +}; +#endif + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static VOID cnmStaRoutinesForAbort(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec); + +static VOID cnmStaRecHandleEventPkt(P_ADAPTER_T prAdapter, P_CMD_INFO_T prCmdInfo, PUINT_8 pucEventBuf); + +static VOID +cnmStaSendRemoveCmd(P_ADAPTER_T prAdapter, + ENUM_STA_REC_CMD_ACTION_T eActionType, UINT_8 ucStaRecIndex, UINT_8 ucBssIndex); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +P_MSDU_INFO_T cnmPktAllocWrapper(P_ADAPTER_T prAdapter, UINT_32 u4Length, PUINT_8 pucStr) +{ + P_MSDU_INFO_T prMsduInfo; + + prMsduInfo = cnmPktAlloc(prAdapter, u4Length); + DBGLOG(MEM, LOUD, "Alloc MSDU_INFO[0x%p] by [%s]\n", prMsduInfo, pucStr); + + return prMsduInfo; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmPktFreeWrapper(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo, PUINT_8 pucStr) +{ + DBGLOG(MEM, LOUD, "Free MSDU_INFO[0x%p] by [%s]\n", prMsduInfo, pucStr); + + cnmPktFree(prAdapter, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +P_MSDU_INFO_T cnmPktAlloc(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) { + if (u4Length) { + 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; + } + } else { + prMsduInfo->prPacket = 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 cnmPktFree(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + P_QUE_T prQueList; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + if (!prMsduInfo) + return; + + 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); + + if (u4Length == 0) { + DBGLOG(MEM, WARN, "%s: Length to be allocated is ZERO, skip!\n", __func__); + return NULL; + } + + if (eRamType == RAM_TYPE_MSG && u4Length <= 256) { + prBufInfo = &prAdapter->rMsgBufInfo; + u4BlkSzInPower = MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2; + + u4BlockNum = (u4Length + MSG_BUF_BLOCK_SIZE - 1) + >> 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; + + u4BlockNum = (u4Length + MGT_BUF_BLOCK_SIZE - 1) + >> MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2; + + ASSERT(u4BlockNum <= MAX_NUM_OF_BUF_BLOCKS); + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF); + +#if CFG_DBG_MGT_BUF + prBufInfo->u4AllocCount++; +#endif + + 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; + } + } + +#if CFG_DBG_MGT_BUF + prBufInfo->u4AllocNullCount++; +#endif + + /* kalMemAlloc() shall not included in spin_lock */ + KAL_RELEASE_SPIN_LOCK(prAdapter, eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF); + +#ifdef LINUX + pvMemory = (PVOID) kalMemAlloc(u4Length, PHY_MEM_TYPE); + if (!pvMemory) + DBGLOG(MEM, WARN, "kmalloc fail: %u\n", u4Length); +#else + pvMemory = (PVOID) NULL; +#endif + +#if CFG_DBG_MGT_BUF + if (pvMemory) + GLUE_INC_REF_CNT(prAdapter->u4MemAllocDynamicCount); +#endif + + 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); + + if (!pvMemory) + return; + + /* Judge it belongs to which RAM type */ + if (((ULONG) pvMemory >= (ULONG)&prAdapter->aucMsgBuf[0]) && + ((ULONG) pvMemory <= (ULONG)&prAdapter->aucMsgBuf[MSG_BUFFER_SIZE - 1])) { + + prBufInfo = &prAdapter->rMsgBufInfo; + u4BlockIndex = ((ULONG) pvMemory - (ULONG) prBufInfo->pucBuf) + >> MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2; + ASSERT(u4BlockIndex < MAX_NUM_OF_BUF_BLOCKS); + eRamType = RAM_TYPE_MSG; + } else if (((ULONG) pvMemory >= (ULONG) prAdapter->pucMgtBufCached) && + ((ULONG) pvMemory <= ((ULONG) prAdapter->pucMgtBufCached + MGT_BUFFER_SIZE - 1))) { + prBufInfo = &prAdapter->rMgtBufInfo; + u4BlockIndex = ((ULONG) pvMemory - (ULONG) prBufInfo->pucBuf) + >> MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2; + ASSERT(u4BlockIndex < MAX_NUM_OF_BUF_BLOCKS); + eRamType = RAM_TYPE_BUF; + } else { +#ifdef LINUX + /* For Linux, it is supported because size is not needed */ + kalMemFree(pvMemory, PHY_MEM_TYPE, 0); +#else + /* For Windows, it is not supported because of no size argument */ + ASSERT(0); +#endif + +#if CFG_DBG_MGT_BUF + GLUE_INC_REF_CNT(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; + prStaRec->eapol_re_enqueue_cnt = 0; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +P_STA_RECORD_T cnmStaRecAlloc(P_ADAPTER_T prAdapter, ENUM_STA_TYPE_T eStaType, UINT_8 ucBssIndex, PUINT_8 pucMacAddr) +{ + P_STA_RECORD_T prStaRec; + UINT_16 i, k; + + ASSERT(prAdapter); + + prStaRec = cnmGetAnyStaRecByAddress(prAdapter, pucMacAddr); + + if (prStaRec != NULL) + disconnect_sta(prAdapter, prStaRec); + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + + if (!prStaRec->fgIsInUse) { + kalMemZero(prStaRec, sizeof(STA_RECORD_T)); + prStaRec->ucIndex = (UINT_8) i; + prStaRec->ucBssIndex = ucBssIndex; + prStaRec->fgIsInUse = TRUE; + + prStaRec->eStaType = eStaType; + prStaRec->ucBssIndex = ucBssIndex; + + /* Initialize the SN caches for duplicate detection */ + for (k = 0; k < TID_NUM + 1; k++) { + prStaRec->au2CachedSeqCtrl[k] = 0xFFFF; + prStaRec->afgIsIgnoreAmsduDuplicate[k] = FALSE; + } + + /* Initialize SW TX queues in STA_REC */ + for (k = 0; k < STA_WAIT_QUEUE_NUM; k++) + LINK_INITIALIZE(&prStaRec->arStaWaitQueue[k]); + +#if CFG_ENABLE_PER_STA_STATISTICS && CFG_ENABLE_PKT_LIFETIME_PROFILE + prStaRec->u4TotalTxPktsNumber = 0; + prStaRec->u4TotalTxPktsTime = 0; + prStaRec->u4TotalRxPktsNumber = 0; + prStaRec->u4MaxTxPktsTime = 0; +#endif + + for (k = 0; k < NUM_OF_PER_STA_TX_QUEUES; k++) { + QUEUE_INITIALIZE(&prStaRec->arTxQueue[k]); + QUEUE_INITIALIZE(&prStaRec->arPendingTxQueue[k]); + prStaRec->aprTargetQueue[k] = &prStaRec->arTxQueue[k]; + } + + break; + } + } + + /* Sync to chip to allocate WTBL resource */ + if (i < CFG_STA_REC_NUM) { + COPY_MAC_ADDR(prStaRec->aucMacAddr, pucMacAddr); + if (secPrivacySeekForEntry(prAdapter, prStaRec)) + cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); +#if DBG + else { + prStaRec->fgIsInUse = FALSE; + prStaRec = NULL; + ASSERT(FALSE); + } +#endif + } else { + prStaRec = NULL; + } + + return prStaRec; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmStaRecFree(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec) +{ + UINT_8 ucStaRecIndex, ucBssIndex; + + ASSERT(prAdapter); + + if (!prStaRec) + return; + + DBGLOG(RSN, INFO, "cnmStaRecFree %d", prStaRec->ucIndex); + + ucStaRecIndex = prStaRec->ucIndex; + ucBssIndex = prStaRec->ucBssIndex; + + cnmStaRoutinesForAbort(prAdapter, prStaRec); + + cnmStaSendRemoveCmd(prAdapter, STA_REC_CMD_ACTION_STA, ucStaRecIndex, ucBssIndex); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static VOID cnmStaRoutinesForAbort(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec) +{ + ASSERT(prAdapter); + + if (!prStaRec) + return; + + /* To do: free related resources, e.g. timers, buffers, etc */ + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + cnmTimerStopTimer(prAdapter, &prStaRec->rDeauthTxDoneTimer); + 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); + + /* Update the driver part table setting */ + secPrivacyFreeSta(prAdapter, prStaRec); + + prStaRec->fgIsInUse = FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmStaFreeAllStaByNetwork(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex, UINT_8 ucStaRecIndexExcluded) +{ +#if CFG_ENABLE_WIFI_DIRECT + P_BSS_INFO_T prBssInfo; +#endif + P_STA_RECORD_T prStaRec; + UINT_16 i; + + if (ucBssIndex > MAX_BSS_INDEX) + return; + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = (P_STA_RECORD_T) &prAdapter->arStaRec[i]; + + if (prStaRec->fgIsInUse && prStaRec->ucBssIndex == ucBssIndex && i != ucStaRecIndexExcluded) + cnmStaRoutinesForAbort(prAdapter, prStaRec); + } /* end of for loop */ + + cnmStaSendRemoveCmd(prAdapter, + (ucStaRecIndexExcluded < CFG_STA_REC_NUM) ? + STA_REC_CMD_ACTION_BSS_EXCLUDE_STA : STA_REC_CMD_ACTION_BSS, + ucStaRecIndexExcluded, ucBssIndex); + +#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 + */ + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + if (prAdapter->fgIsP2PRegistered && prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) + rlmUpdateParamsForAP(prAdapter, prBssInfo, FALSE); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 ucBssIndex, PUINT_8 pucPeerMacAddr) +{ + P_STA_RECORD_T prStaRec; + UINT_16 i; + + ASSERT(prAdapter); + + if (!pucPeerMacAddr) + return NULL; + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + + if (prStaRec->fgIsInUse && + prStaRec->ucBssIndex == ucBssIndex && EQUAL_MAC_ADDR(prStaRec->aucMacAddr, pucPeerMacAddr)) { + break; + } + } + + return (i < CFG_STA_REC_NUM) ? prStaRec : NULL; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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 cnmGetAnyStaRecByAddress(P_ADAPTER_T prAdapter, + PUINT_8 pucPeerMacAddr) +{ + P_STA_RECORD_T prStaRec; + UINT_16 i; + + ASSERT(prAdapter); + + if (!pucPeerMacAddr) + return NULL; + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + + if (prStaRec->fgIsInUse && + EQUAL_MAC_ADDR(prStaRec->aucMacAddr, pucPeerMacAddr)) { + break; + } + } + + return (i < CFG_STA_REC_NUM) ? prStaRec : NULL; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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; + + if (!prAdapter) + return; + + if (!prStaRec) { + DBGLOG(MEM, WARN, "%s: StaRec is NULL, skip!\n", __func__); + return; + } + + if (!prStaRec->fgIsInUse) { + DBGLOG(MEM, WARN, "%s: StaRec[%u] is not in use, skip!\n", __func__, prStaRec->ucIndex); + return; + } + + /* 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; + cnmDumpStaRec(prAdapter, prStaRec->ucIndex); + } + } else { + if (ucNewState != prStaRec->ucStaState && prStaRec->ucStaState == STA_STATE_3) + qmDeactivateStaRec(prAdapter, prStaRec); + fgNeedResp = FALSE; + } + prStaRec->ucStaState = ucNewState; + + cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, fgNeedResp); + +#if 1 /* Marked for MT6630 */ +#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 = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) + rlmUpdateParamsForAP(prAdapter, prBssInfo, FALSE); + } +#endif +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmStaSendUpdateCmd(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, P_TXBF_PFMU_STA_INFO prTxBfPfmuStaInfo, + BOOLEAN fgNeedResp) +{ + P_CMD_UPDATE_STA_RECORD_T prCmdContent; + WLAN_STATUS rStatus; + + if (!prAdapter) + return; + + if (!prStaRec) { + DBGLOG(MEM, WARN, "%s: StaRec is NULL, skip!\n", __func__); + return; + } + + if (!prStaRec->fgIsInUse) { + DBGLOG(MEM, WARN, "%s: StaRec[%u] is not in use, skip!\n", __func__, prStaRec->ucIndex); + return; + } + + /* 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)); + + /* To do: exception handle */ + if (!prCmdContent) { + DBGLOG(MEM, WARN, "%s: CMD_ID_UPDATE_STA_RECORD command allocation failed\n", __func__); + return; + } + + /* Reset command buffer */ + kalMemZero(prCmdContent, sizeof(CMD_UPDATE_STA_RECORD_T)); + + if (prTxBfPfmuStaInfo) + memcpy(&prCmdContent->rTxBfPfmuInfo, prTxBfPfmuStaInfo, sizeof(TXBF_PFMU_STA_INFO)); + + prCmdContent->ucStaIndex = 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->ucBssIndex = prStaRec->ucBssIndex; + + prCmdContent->ucDesiredPhyTypeSet = prStaRec->ucDesiredPhyTypeSet; + prCmdContent->u2DesiredNonHTRateSet = prStaRec->u2DesiredNonHTRateSet; + prCmdContent->u2BSSBasicRateSet = prStaRec->u2BSSBasicRateSet; + prCmdContent->ucMcsSet = prStaRec->ucMcsSet; + prCmdContent->ucSupMcs32 = (UINT_8) prStaRec->fgSupMcs32; + prCmdContent->u2HwDefaultFixedRateCode = prStaRec->u2HwDefaultFixedRateCode; + + kalMemCopy(prCmdContent->aucRxMcsBitmask, prStaRec->aucRxMcsBitmask, + sizeof(prCmdContent->aucRxMcsBitmask) /*SUP_MCS_RX_BITMASK_OCTET_NUM */); + prCmdContent->u2RxHighestSupportedRate = prStaRec->u2RxHighestSupportedRate; + prCmdContent->u4TxRateInfo = prStaRec->u4TxRateInfo; + + 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->u4VhtCapInfo = prStaRec->u4VhtCapInfo; + prCmdContent->u2VhtRxMcsMap = prStaRec->u2VhtRxMcsMap; + prCmdContent->u2VhtRxHighestSupportedDataRate = prStaRec->u2VhtRxHighestSupportedDataRate; + prCmdContent->u2VhtTxMcsMap = prStaRec->u2VhtTxMcsMap; + prCmdContent->u2VhtTxHighestSupportedDataRate = prStaRec->u2VhtTxHighestSupportedDataRate; + prCmdContent->ucVhtOpMode = prStaRec->ucVhtOpMode; + + prCmdContent->ucUapsdAc = prStaRec->ucBmpTriggerAC | (prStaRec->ucBmpDeliveryAC << 4); + prCmdContent->ucUapsdSp = prStaRec->ucUapsdSp; + + prCmdContent->ucWlanIndex = prStaRec->ucWlanIndex; + prCmdContent->ucBMCWlanIndex = WTBL_RESERVED_ENTRY; + + prCmdContent->ucTrafficDataType = prStaRec->ucTrafficDataType; + prCmdContent->ucTxGfMode = prStaRec->ucTxGfMode; + prCmdContent->ucTxSgiMode = prStaRec->ucTxSgiMode; + prCmdContent->ucTxStbcMode = prStaRec->ucTxStbcMode; + prCmdContent->u4FixedPhyRate = prStaRec->u4FixedPhyRate; + prCmdContent->u2MaxLinkSpeed = prStaRec->u2MaxLinkSpeed; + prCmdContent->u2MinLinkSpeed = prStaRec->u2MinLinkSpeed; + prCmdContent->u4Flags = prStaRec->u4Flags; + + prCmdContent->ucTxAmpdu = prAdapter->rWifiVar.ucAmpduTx; + prCmdContent->ucRxAmpdu = prAdapter->rWifiVar.ucAmpduRx; + + /* AMSDU in AMPDU global configuration */ + prCmdContent->ucTxAmsduInAmpdu = prAdapter->rWifiVar.ucAmsduInAmpduTx; + prCmdContent->ucRxAmsduInAmpdu = prAdapter->rWifiVar.ucAmsduInAmpduRx; + if ((prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11AC) || + (prStaRec->u4Flags & MTK_SYNERGY_CAP_SUPPORT_24G_MCS89)) { + /* VHT pear AMSDU in AMPDU configuration */ + prCmdContent->ucTxAmsduInAmpdu &= prAdapter->rWifiVar.ucVhtAmsduInAmpduTx; + prCmdContent->ucRxAmsduInAmpdu &= prAdapter->rWifiVar.ucVhtAmsduInAmpduRx; + } else if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11N) { + /* HT peer AMSDU in AMPDU configuration */ + prCmdContent->ucTxAmsduInAmpdu &= prAdapter->rWifiVar.ucHtAmsduInAmpduTx; + prCmdContent->ucRxAmsduInAmpdu &= prAdapter->rWifiVar.ucHtAmsduInAmpduRx; + } + + prCmdContent->u4TxMaxAmsduInAmpduLen = prAdapter->rWifiVar.u4TxMaxAmsduInAmpduLen; + + prCmdContent->ucTxBaSize = prAdapter->rWifiVar.ucTxBaSize; + + if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11AC) + prCmdContent->ucRxBaSize = prAdapter->rWifiVar.ucRxVhtBaSize; + else + prCmdContent->ucRxBaSize = prAdapter->rWifiVar.ucRxHtBaSize; + + /* RTS Policy */ + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucSigTaRts)) { + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucDynBwRts)) + prCmdContent->ucRtsPolicy = RTS_POLICY_DYNAMIC_BW; + else + prCmdContent->ucRtsPolicy = RTS_POLICY_STATIC_BW; + } else + prCmdContent->ucRtsPolicy = RTS_POLICY_LEGACY; + + DBGLOG(REQ, INFO, "Update StaRec[%u] WIDX[%u] State[%u] Type[%u] BssIdx[%u] AID[%u]\n", + prCmdContent->ucStaIndex, + prCmdContent->ucWlanIndex, + prCmdContent->ucStaState, prCmdContent->ucStaType, prCmdContent->ucBssIndex, prCmdContent->u2AssocId); + + DBGLOG(REQ, INFO, "Update StaRec[%u] QoS[%u] UAPSD[%u]\n", + prCmdContent->ucStaIndex, prCmdContent->ucIsQoS, prCmdContent->ucIsUapsdSupported); + + 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 */ + ); + + cnmMemFree(prAdapter, prCmdContent); + + if (rStatus != WLAN_STATUS_PENDING) + DBGLOG(MEM, WARN, "%s: CMD_ID_UPDATE_STA_RECORD result 0x%08x\n", __func__, rStatus); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID +cnmStaSendRemoveCmd(P_ADAPTER_T prAdapter, + ENUM_STA_REC_CMD_ACTION_T eActionType, UINT_8 ucStaRecIndex, UINT_8 ucBssIndex) +{ + CMD_REMOVE_STA_RECORD_T rCmdContent; + WLAN_STATUS rStatus; + + ASSERT(prAdapter); + + rCmdContent.ucActionType = (UINT_8) eActionType; + rCmdContent.ucStaIndex = ucStaRecIndex; + rCmdContent.ucBssIndex = ucBssIndex; + rCmdContent.ucReserved = 0; + + 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 */ + ); + + if (rStatus != WLAN_STATUS_PENDING) + DBGLOG(MEM, WARN, "%s: CMD_ID_REMOVE_STA_RECORD result 0x%08x\n", __func__, rStatus); +} + +PUINT_8 cnmStaRecGetTypeString(ENUM_STA_TYPE_T eStaType) +{ + PUINT_8 pucTypeString = NULL; + + if (eStaType & STA_TYPE_LEGACY_MASK) + pucTypeString = apucStaRecType[STA_TYPE_LEGACY_INDEX]; + if (eStaType & STA_TYPE_P2P_MASK) + pucTypeString = apucStaRecType[STA_TYPE_P2P_INDEX]; + if (eStaType & STA_TYPE_BOW_MASK) + pucTypeString = apucStaRecType[STA_TYPE_BOW_INDEX]; + + return pucTypeString; +} + +PUINT_8 cnmStaRecGetRoleString(ENUM_STA_TYPE_T eStaType) +{ + PUINT_8 pucRoleString = NULL; + + if (eStaType & STA_TYPE_ADHOC_MASK) + pucRoleString = apucStaRecRole[STA_ROLE_ADHOC_INDEX - STA_ROLE_BASE_INDEX]; + if (eStaType & STA_TYPE_CLIENT_MASK) + pucRoleString = apucStaRecRole[STA_ROLE_CLIENT_INDEX - STA_ROLE_BASE_INDEX]; + if (eStaType & STA_TYPE_AP_MASK) + pucRoleString = apucStaRecRole[STA_ROLE_AP_INDEX - STA_ROLE_BASE_INDEX]; + if (eStaType & STA_TYPE_DLS_MASK) + pucRoleString = apucStaRecRole[STA_ROLE_DLS_INDEX - STA_ROLE_BASE_INDEX]; + + return pucRoleString; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmDumpStaRec(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIdx) +{ + UINT_8 ucWTEntry; + UINT_32 i; + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("cnmDumpStaRec"); + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIdx); + + if (!prStaRec) { + DBGLOG(SW4, INFO, "Invalid StaRec index[%u], skip dump!\n", ucStaRecIdx); + return; + } + + ucWTEntry = prStaRec->ucWlanIndex; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + ASSERT(prBssInfo); + + DBGLOG(SW4, INFO, "============= DUMP STA[%u] ===========\n", ucStaRecIdx); + + DBGLOG(SW4, INFO, + "STA_IDX[%u] BSS_IDX[%u] MAC[" MACSTR "] TYPE[%s %s] WTBL[%u] USED[%u] State[%u]\n", + prStaRec->ucIndex, prStaRec->ucBssIndex, MAC2STR(prStaRec->aucMacAddr), + cnmStaRecGetTypeString(prStaRec->eStaType), + cnmStaRecGetRoleString(prStaRec->eStaType), ucWTEntry, prStaRec->fgIsInUse, prStaRec->ucStaState); + + DBGLOG(SW4, INFO, "QoS[%u] HT/VHT[%u/%u] AID[%u] WMM[%u] UAPSD[%u] SEC[%u]\n", + prStaRec->fgIsQoS, + (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11N) ? TRUE : FALSE, + (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11AC) ? TRUE : FALSE, + prStaRec->u2AssocId, + prStaRec->fgIsWmmSupported, prStaRec->fgIsUapsdSupported, secIsProtectedBss(prAdapter, prBssInfo)); + + DBGLOG(SW4, INFO, "PhyTypeSet: BSS[0x%02x] Desired[0x%02x] NonHtBasic[0x%02x]\n", + prBssInfo->ucPhyTypeSet, prStaRec->ucDesiredPhyTypeSet, prStaRec->ucNonHTBasicPhyType); + + DBGLOG(SW4, INFO, + "RateSet: BssBasic[0x%04x] Operational[0x%04x] DesiredNonHT[0x%02x] DeafultFixedRate[0x%02x]\n", + prBssInfo->u2BSSBasicRateSet, prStaRec->u2OperationalRateSet, + prStaRec->u2DesiredNonHTRateSet, prStaRec->u2HwDefaultFixedRateCode); + + DBGLOG(SW4, INFO, "HT Cap[0x%04x] ExtCap[0x%04x] BeemCap[0x%08x] MCS[0x%02x] MCS32[%u]\n", + prStaRec->u2HtCapInfo, + prStaRec->u2HtExtendedCap, prStaRec->u4TxBeamformingCap, prStaRec->ucMcsSet, prStaRec->fgSupMcs32); + + DBGLOG(SW4, INFO, "VHT Cap[0x%08x] TxMCS[0x%04x] RxMCS[0x%04x] VhtOpMode[0x%02x]\n", + prStaRec->u4VhtCapInfo, prStaRec->u2VhtTxMcsMap, prStaRec->u2VhtRxMcsMap, prStaRec->ucVhtOpMode); + + DBGLOG(SW4, INFO, "RCPI[%u] InPS[%u] TxAllowed[%u] KeyRdy[%u] AMPDU T/R[%u/%u]\n", + prStaRec->ucRCPI, + prStaRec->fgIsInPS, + prStaRec->fgIsTxAllowed, prStaRec->fgIsTxKeyReady, prStaRec->fgTxAmpduEn, prStaRec->fgRxAmpduEn); + + DBGLOG(SW4, INFO, "TxQ LEN TC[0~5] [%03u:%03u:%03u:%03u]\n", + prStaRec->aprTargetQueue[0]->u4NumElem, + prStaRec->aprTargetQueue[1]->u4NumElem, + prStaRec->aprTargetQueue[2]->u4NumElem, + prStaRec->aprTargetQueue[3]->u4NumElem); + + DBGLOG(SW4, INFO, "BMP AC Delivery/Trigger[%02x/%02x]\n", prStaRec->ucBmpDeliveryAC, prStaRec->ucBmpTriggerAC); + + DBGLOG(SW4, INFO, "FreeQuota: Total[%u] Delivery/NonDelivery[%u/%u]\n", + prStaRec->ucFreeQuota, prStaRec->ucFreeQuotaForDelivery, prStaRec->ucFreeQuotaForNonDelivery); + + DBGLOG(SW4, INFO, "aucRxMcsBitmask: [0][0x%02x] [1][0x%02x]\n", + prStaRec->aucRxMcsBitmask[0], prStaRec->aucRxMcsBitmask[1]); + + for (i = 0; i < CFG_RX_MAX_BA_TID_NUM; i++) { + if (prStaRec->aprRxReorderParamRefTbl[i]) { + DBGLOG(SW4, INFO, "\n", prStaRec->aprRxReorderParamRefTbl[i]->ucTid); + DBGLOG(SW4, INFO, + " Valid[%u] WinStart/End[%u/%u] WinSize[%u] ReOrderQueLen[%u]\n", + prStaRec->aprRxReorderParamRefTbl[i]->fgIsValid, + prStaRec->aprRxReorderParamRefTbl[i]->u2WinStart, + prStaRec->aprRxReorderParamRefTbl[i]->u2WinEnd, + prStaRec->aprRxReorderParamRefTbl[i]->u2WinSize, + prStaRec->aprRxReorderParamRefTbl[i]->rReOrderQue.u4NumElem); + DBGLOG(SW4, INFO, + " Bubble Exist[%u] SN[%u]\n", + prStaRec->aprRxReorderParamRefTbl[i]->fgHasBubble, + prStaRec->aprRxReorderParamRefTbl[i]->u2FirstBubbleSn); + } + } + + DBGLOG(SW4, INFO, "============= DUMP END ===========\n"); + +} + +UINT_32 cnmDumpMemoryStatus(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuf, IN UINT_32 u4Max) +{ + UINT_32 u4Len = 0; +#if CFG_DBG_MGT_BUF + P_BUF_INFO_T prBufInfo; + + LOGBUF(pucBuf, u4Max, u4Len, "\n"); + LOGBUF(pucBuf, u4Max, u4Len, "============= DUMP Memory Status =============\n"); + + LOGBUF(pucBuf, u4Max, u4Len, "Dynamic alloc OS memory count: alloc[%u] free[%u]\n", + prAdapter->u4MemAllocDynamicCount, prAdapter->u4MemFreeDynamicCount); + + prBufInfo = &prAdapter->rMsgBufInfo; + LOGBUF(pucBuf, u4Max, u4Len, "MSG memory count: alloc[%u] free[%u] null[%u] bitmap[0x%08x]\n", + prBufInfo->u4AllocCount, prBufInfo->u4FreeCount, + prBufInfo->u4AllocNullCount, (UINT_32) prBufInfo->rFreeBlocksBitmap); + + prBufInfo = &prAdapter->rMgtBufInfo; + LOGBUF(pucBuf, u4Max, u4Len, "MGT memory count: alloc[%u] free[%u] null[%u] bitmap[0x%08x]\n", + prBufInfo->u4AllocCount, prBufInfo->u4FreeCount, + prBufInfo->u4AllocNullCount, (UINT_32) prBufInfo->rFreeBlocksBitmap); + + LOGBUF(pucBuf, u4Max, u4Len, "============= DUMP END =============\n"); + +#endif + + return u4Len; +} + +#if CFG_SUPPORT_TDLS +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to add a peer record. +* +* \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 /* TDLS_STATUS //prStaRec->ucNetTypeIndex */ +cnmPeerAdd(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, PUINT_32 pu4SetInfoLen) +{ + CMD_PEER_ADD_T *prCmd; + BSS_INFO_T *prAisBssInfo; + STA_RECORD_T *prStaRec; + + /* sanity check */ + + if ((prAdapter == NULL) || (pvSetBuffer == NULL) || (pu4SetInfoLen == NULL)) + return TDLS_STATUS_FAIL; + + /* init */ + *pu4SetInfoLen = sizeof(CMD_PEER_ADD_T); + prCmd = (CMD_PEER_ADD_T *) pvSetBuffer; + + prAisBssInfo = prAdapter->prAisBssInfo; /* for AIS only test */ + + if (prAisBssInfo == NULL) { + DBGLOG(TDLS, ERROR, "[%s]prAisBssInfo is NULL!", __func__); + return TDLS_STATUS_FAIL; + } + + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) prAdapter->prAisBssInfo->ucBssIndex, prCmd->aucPeerMac); + + if (prStaRec == NULL) { + prStaRec = + cnmStaRecAlloc(prAdapter, STA_TYPE_DLS_PEER, + (UINT_8) prAdapter->prAisBssInfo->ucBssIndex, prCmd->aucPeerMac); + + if (prStaRec == NULL) + return TDLS_STATUS_RESOURCES; + + if (prAisBssInfo) { + if (prAisBssInfo->ucBssIndex) + prStaRec->ucBssIndex = prAisBssInfo->ucBssIndex; + } + + /* init the prStaRec */ + /* prStaRec will be zero first in cnmStaRecAlloc() */ + COPY_MAC_ADDR(prStaRec->aucMacAddr, prCmd->aucPeerMac); + + prStaRec->u2BSSBasicRateSet = prAisBssInfo->u2BSSBasicRateSet; + + prStaRec->u2DesiredNonHTRateSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet; + + prStaRec->u2OperationalRateSet = prAisBssInfo->u2OperationalRateSet; + prStaRec->ucNonHTBasicPhyType = + prAisBssInfo->ucNonHTBasicPhyType; + prStaRec->ucPhyTypeSet = prAisBssInfo->ucPhyTypeSet; + prStaRec->eStaType = prCmd->eStaType; + + /* Init lowest rate to prevent CCK in 5G band */ + nicTxUpdateStaRecDefaultRate(prStaRec); + + /* Better to change state here, not at TX Done */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + } else { + if ((prStaRec->ucStaState > STA_STATE_1) && (IS_DLS_STA(prStaRec))) { + /* TODO: Teardown the peer */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + } + } + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to update a peer record. +* +* \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 /* TDLS_STATUS */ +cnmPeerUpdate(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, PUINT_32 pu4SetInfoLen) +{ + + CMD_PEER_UPDATE_T *prCmd; + BSS_INFO_T *prAisBssInfo; + STA_RECORD_T *prStaRec; + UINT_8 ucNonHTPhyTypeSet; + + UINT_16 u2OperationalRateSet = 0; + + UINT_8 ucRate; + UINT_16 i, j; + + /* sanity check */ + if ((!prAdapter) || (!pvSetBuffer) || (!pu4SetInfoLen)) + return TDLS_STATUS_FAIL; + + /* init */ + *pu4SetInfoLen = sizeof(CMD_PEER_ADD_T); + prCmd = (CMD_PEER_UPDATE_T *) pvSetBuffer; + + prAisBssInfo = prAdapter->prAisBssInfo; + + if (prAisBssInfo == NULL) { + DBGLOG(TDLS, ERROR, "[%s]prAisBssInfo is NULL!", __func__); + return TDLS_STATUS_FAIL; + } + + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) prAdapter->prAisBssInfo->ucBssIndex, prCmd->aucPeerMac); + + if ((!prStaRec) || !(prStaRec->fgIsInUse)) + return TDLS_STATUS_FAIL; + + if (!IS_DLS_STA(prStaRec)) + return TDLS_STATUS_FAIL; + + if (prAisBssInfo) { + if (prAisBssInfo->ucBssIndex) + prStaRec->ucBssIndex = prAisBssInfo->ucBssIndex; + } + + /* update the record join time. */ + GET_CURRENT_SYSTIME(&prStaRec->rUpdateTime); + + /* update Station Record - Status/Reason Code */ + prStaRec->u2StatusCode = prCmd->u2StatusCode; + prStaRec->u2AssocId = 0; /* no use */ + prStaRec->u2ListenInterval = 0; /* unknown */ + prStaRec->fgIsQoS = TRUE; + prStaRec->fgIsWmmSupported = TRUE; + prStaRec->fgIsUapsdSupported = (prCmd->UapsdBitmap == 0) ? FALSE : TRUE; + prStaRec->u4TxBeamformingCap = 0; /* no use */ + prStaRec->ucAselCap = 0; /* no use */ + /* In TDLS, it couldn't know peer TDLS device's RSSI before setup. + * Temporality, we use the AP's RSSI to judge the initialize Tx rate. + * Otherwise, the Tx rate would be the loweset rate CCK 1M. + */ + DBGLOG(TDLS, EVENT, "[TDLS] Change RCPI to to AP's RCPI: %d\n", + prAisBssInfo->prStaRecOfAP->ucRCPI); + prStaRec->ucRCPI = prAisBssInfo->prStaRecOfAP->ucRCPI; + prStaRec->ucBmpTriggerAC = prCmd->UapsdBitmap; + prStaRec->ucBmpDeliveryAC = prCmd->UapsdBitmap; + prStaRec->ucUapsdSp = prCmd->UapsdMaxSp; + prStaRec->eStaType = prCmd->eStaType; + + /* ++ support rate */ + if (prCmd->u2SupRateLen) { + for (i = 0; i < prCmd->u2SupRateLen; i++) { + if (prCmd->aucSupRate[i]) { + ucRate = prCmd->aucSupRate[i] & RATE_MASK; + /* Search all valid data rates */ + for (j = 0; j < sizeof(aucValidDataRate) / sizeof(UINT_8); j++) { + if (ucRate == aucValidDataRate[j]) { + u2OperationalRateSet |= BIT(j); + break; + } + } + } + + } + + prStaRec->u2OperationalRateSet = u2OperationalRateSet; + prStaRec->u2BSSBasicRateSet = prAisBssInfo->u2BSSBasicRateSet; + + /* 4 <5> PHY type setting */ + + prStaRec->ucPhyTypeSet = 0; + + if (prAisBssInfo->eBand == BAND_2G4) { + if (prCmd->fgIsSupHt) + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HT; + + /* if not 11n only */ + if (!(prStaRec->u2BSSBasicRateSet & RATE_SET_BIT_HT_PHY)) { + /* check if support 11g */ + if ((prStaRec->u2OperationalRateSet & RATE_SET_OFDM)) + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_ERP; + + /* if not 11g only */ + if (!(prStaRec->u2BSSBasicRateSet & RATE_SET_OFDM)) { + /* check if support 11b */ + if ((prStaRec->u2OperationalRateSet & RATE_SET_HR_DSSS)) + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HR_DSSS; + } + } + } else { + if (prCmd->rVHtCap.u2CapInfo) + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_VHT; + + if (prCmd->fgIsSupHt) + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HT; + + /* if not 11n only */ + if (!(prStaRec->u2BSSBasicRateSet & RATE_SET_BIT_HT_PHY)) { + /* Support 11a definitely */ + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_OFDM; + } + } + + if (IS_STA_IN_AIS(prStaRec)) { + if (!((prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION3_ENABLED) + || (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION3_KEY_ABSENT) + || (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION_DISABLED) + || (prAdapter->prGlueInfo->u2WSCAssocInfoIELen) +#if CFG_SUPPORT_WAPI + || (prAdapter->prGlueInfo->u2WapiAssocInfoIESz) +#endif + )) { + + 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 + 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; + } + + } + + /* ++HT capability */ + + if (prCmd->fgIsSupHt) { + prAdapter->rWifiVar.eRateSetting = FIXED_RATE_NONE; + prStaRec->ucDesiredPhyTypeSet |= PHY_TYPE_BIT_HT; + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HT; + prStaRec->u2HtCapInfo = prCmd->rHtCap.u2CapInfo; + prStaRec->ucAmpduParam = prCmd->rHtCap.ucAmpduParamsInfo; + prStaRec->u2HtExtendedCap = prCmd->rHtCap.u2ExtHtCapInfo; + prStaRec->u4TxBeamformingCap = prCmd->rHtCap.u4TxBfCapInfo; + prStaRec->ucAselCap = prCmd->rHtCap.ucAntennaSelInfo; + prStaRec->ucMcsSet = prCmd->rHtCap.rMCS.arRxMask[0]; + prStaRec->fgSupMcs32 = (prCmd->rHtCap.rMCS.arRxMask[32 / 8] & BIT(0)) ? TRUE : FALSE; + kalMemCopy(prStaRec->aucRxMcsBitmask, prCmd->rHtCap.rMCS.arRxMask, sizeof(prStaRec->aucRxMcsBitmask)); + } + /* TODO ++VHT */ + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Get TDLS peer 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 cnmGetTdlsPeerByAddress(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex, UINT_8 aucPeerMACAddress[]) +{ + P_STA_RECORD_T prStaRec; + UINT_16 i; + + ASSERT(prAdapter); + ASSERT(aucPeerMACAddress); + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + if (prStaRec) { + if (prStaRec->fgIsInUse && + prStaRec->eStaType == STA_TYPE_DLS_PEER && + EQUAL_MAC_ADDR(prStaRec->aucMacAddr, aucPeerMACAddress)) { + break; + } + } + } + + return prStaRec; +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/cnm_timer.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/cnm_timer.c new file mode 100644 index 0000000000000..b0b8dd1d1d4ee --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/cnm_timer.c @@ -0,0 +1,462 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/cnm_timer.c#1 +*/ + +/*! \file "cnm_timer.c" +* \brief +* +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the time to do the time out check. +* +* \param[in] rTimeout Time out interval from current time. +* +* \retval TRUE Success. +* +*/ +/*----------------------------------------------------------------------------*/ +static BOOLEAN cnmTimerSetTimer(IN P_ADAPTER_T prAdapter, IN OS_SYSTIME rTimeout) +{ + P_ROOT_TIMER prRootTimer; + BOOLEAN fgNeedWakeLock; + + ASSERT(prAdapter); + + prRootTimer = &prAdapter->rRootTimer; + + kalSetTimer(prAdapter->prGlueInfo, rTimeout); + + if (rTimeout <= SEC_TO_SYSTIME(WAKE_LOCK_MAX_TIME)) { + fgNeedWakeLock = TRUE; + + if (!prRootTimer->fgWakeLocked) { + KAL_WAKE_LOCK(prAdapter, &prRootTimer->rWakeLock); + prRootTimer->fgWakeLocked = TRUE; + } + } else { + fgNeedWakeLock = FALSE; + } + + return fgNeedWakeLock; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routines is called to initialize a root timer. +* +* \param[in] prAdapter +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmTimerInitialize(IN P_ADAPTER_T prAdapter) +{ + P_ROOT_TIMER prRootTimer; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prRootTimer = &prAdapter->rRootTimer; + + /* Note: glue layer have configured timer */ + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + LINK_INITIALIZE(&prRootTimer->rLinkHead); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + + KAL_WAKE_LOCK_INIT(prAdapter, &prRootTimer->rWakeLock, "WLAN Timer"); + prRootTimer->fgWakeLocked = FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routines is called to destroy a root timer. +* When WIFI is off, the token shall be returned back to system. +* +* \param[in] +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmTimerDestroy(IN P_ADAPTER_T prAdapter) +{ + P_ROOT_TIMER prRootTimer; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prRootTimer = &prAdapter->rRootTimer; + + if (prRootTimer->fgWakeLocked) { + KAL_WAKE_UNLOCK(prAdapter, &prRootTimer->rWakeLock); + prRootTimer->fgWakeLocked = FALSE; + } + KAL_WAKE_LOCK_DESTROY(prAdapter, &prRootTimer->rWakeLock); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + LINK_INITIALIZE(&prRootTimer->rLinkHead); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + + /* Note: glue layer will be responsible for timer destruction */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routines is called to initialize a timer. +* +* \param[in] prTimer Pointer to a timer structure. +* \param[in] pfnFunc Pointer to the call back function. +* \param[in] u4Data Parameter for call back function. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +cnmTimerInitTimer(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer, IN PFN_MGMT_TIMEOUT_FUNC pfFunc, IN ULONG ulDataPtr) +{ + 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 + + 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); + } + } + + LINK_ENTRY_INITIALIZE(&prTimer->rLinkEntry); + + prTimer->pfMgmtTimeOutFunc = pfFunc; + prTimer->ulDataPtr = ulDataPtr; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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); + if (rTimeoutSystime == 0) + rTimeoutSystime = 1; + rExpiredSysTime = kalGetTimeTick() + rTimeoutSystime; + + /* If no timer pending or the fast time interval is used. */ + if (LINK_IS_EMPTY(prTimerList) || TIME_BEFORE(rExpiredSysTime, prRootTimer->rNextExpiredSysTime)) { + + prRootTimer->rNextExpiredSysTime = rExpiredSysTime; + cnmTimerSetTimer(prAdapter, rTimeoutSystime); + } + + /* Add this timer to checking list */ + prTimer->rExpiredSysTime = rExpiredSysTime; + + if (!timerPendingTimer(prTimer)) + LINK_INSERT_TAIL(prTimerList, &prTimer->rLinkEntry); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routines is called to check the timer list. +* +* \param[in] +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmTimerDoTimeOutCheck(IN P_ADAPTER_T prAdapter) +{ + P_ROOT_TIMER prRootTimer; + P_LINK_T prTimerList; + P_LINK_ENTRY_T prLinkEntry; + P_TIMER_T prTimer; + OS_SYSTIME rCurSysTime; + PFN_MGMT_TIMEOUT_FUNC pfMgmtTimeOutFunc; + ULONG ulTimeoutDataPtr; + 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; + ulTimeoutDataPtr = prTimer->ulDataPtr; + + 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, ulTimeoutDataPtr); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + } + + /* Search entire list again because of nest del and add timers + * and current MGMT_TIMER could be volatile after stopped + */ + prLinkEntry = (P_LINK_ENTRY_T) prTimerList; + + prRootTimer->rNextExpiredSysTime = rCurSysTime + MGMT_MAX_TIMEOUT_INTERVAL; + } else if (TIME_BEFORE(prTimer->rExpiredSysTime, prRootTimer->rNextExpiredSysTime)) { + prRootTimer->rNextExpiredSysTime = prTimer->rExpiredSysTime; + } + } /* end of for loop */ + + /* Setup the prNext timeout event. It is possible the timer was already + * set in the above timeout callback function. + */ + fgNeedWakeLock = FALSE; + if (!LINK_IS_EMPTY(prTimerList)) { + ASSERT(TIME_AFTER(prRootTimer->rNextExpiredSysTime, rCurSysTime)); + + fgNeedWakeLock = cnmTimerSetTimer(prAdapter, (OS_SYSTIME) + ((INT_32) prRootTimer->rNextExpiredSysTime - (INT_32) rCurSysTime)); + } + + if (prRootTimer->fgWakeLocked && !fgNeedWakeLock) { + KAL_WAKE_UNLOCK(prAdapter, &prRootTimer->rWakeLock); + prRootTimer->fgWakeLocked = FALSE; + } + + /* release spin lock */ + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/hem_mbox.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/hem_mbox.c new file mode 100644 index 0000000000000..9eb1fa8798665 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/hem_mbox.c @@ -0,0 +1,560 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/hem_mbox.c#7 +*/ + +/*! \file "hem_mbox.c" +* \brief +* +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#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"), +#if (CFG_SUPPORT_DFS_MASTER == 1) + (PUINT_8) DISP_STRING("MID_CNM_P2P_RADAR_DETECT"), + (PUINT_8) DISP_STRING("MID_CNM_P2P_CSA_DONE"), + (PUINT_8) DISP_STRING("MID_MNY_P2P_DFS_CAC"), + (PUINT_8) DISP_STRING("MID_MNY_P2P_SET_NEW_CHANNEL"), +#endif + +#endif + +#if CFG_SUPPORT_ADHOC + /* (PUINT_8)DISP_STRING("MID_AIS_CNM_CREATE_IBSS_REQ"), */ + /* (PUINT_8)DISP_STRING("MID_CNM_AIS_CREATE_IBSS_GRANT"), */ + /* (PUINT_8)DISP_STRING("MID_AIS_CNM_MERGE_IBSS_REQ"), */ + /* (PUINT_8)DISP_STRING("MID_CNM_AIS_MERGE_IBSS_GRANT"), */ + (PUINT_8) DISP_STRING("MID_SCN_AIS_FOUND_IBSS"), +#endif /* CFG_SUPPORT_ADHOC */ + + (PUINT_8) DISP_STRING("MID_SAA_AIS_FSM_ABORT"), + (PUINT_8) DISP_STRING("MID_MNY_AIS_REMAIN_ON_CHANNEL"), + (PUINT_8) DISP_STRING("MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL"), + (PUINT_8) DISP_STRING("MID_MNY_AIS_MGMT_TX") + +}; + +/*lint -restore */ +#endif /* DBG */ + +/* This message entry will be re-ordered based on the message ID order + * by invoking mboxInitMsgMap() + */ +static MSG_HNDL_ENTRY_T arMsgMapTable[] = { + {MID_MNY_CNM_CH_REQ, cnmChMngrRequestPrivilege}, + {MID_MNY_CNM_CH_ABORT, cnmChMngrAbortPrivilege}, + {MID_CNM_AIS_CH_GRANT, aisFsmRunEventChGrant}, +#if CFG_ENABLE_WIFI_DIRECT + {MID_CNM_P2P_CH_GRANT, p2pFsmRunEventChGrant}, /*set in gl_p2p_init.c */ +#else + {MID_CNM_P2P_CH_GRANT, mboxDummy}, +#endif + +#if (CFG_SUPPORT_DFS_MASTER == 1) + {MID_CNM_P2P_RADAR_DETECT, p2pRoleFsmRunEventRadarDet}, + {MID_CNM_P2P_CSA_DONE, p2pRoleFsmRunEventCsaDone}, +#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, p2pRoleFsmRunEventJoinComplete}, /* V */ + + {MID_MNY_P2P_FUN_SWITCH, p2pRoleFsmRunEventSwitchOPMode}, + {MID_MNY_P2P_DEVICE_DISCOVERY, p2pFsmRunEventScanRequest}, /* V */ + {MID_MNY_P2P_CONNECTION_REQ, p2pRoleFsmRunEventConnectionRequest}, + {MID_MNY_P2P_CONNECTION_ABORT, p2pRoleFsmRunEventConnectionAbort}, + {MID_MNY_P2P_BEACON_UPDATE, p2pRoleFsmRunEventBeaconUpdate}, + {MID_MNY_P2P_STOP_AP, p2pRoleFsmRunEventStopAP}, + {MID_MNY_P2P_CHNL_REQ, p2pDevFsmRunEventChannelRequest}, /* V */ + {MID_MNY_P2P_CHNL_ABORT, p2pDevFsmRunEventChannelAbort}, /* V */ + {MID_MNY_P2P_MGMT_TX, p2pDevFsmRunEventMgmtTx}, /* V */ + {MID_MNY_P2P_GROUP_DISSOLVE, p2pRoleFsmRunEventDissolve}, + {MID_MNY_P2P_MGMT_FRAME_REGISTER, p2pDevFsmRunEventMgmtFrameRegister}, + {MID_MNY_P2P_NET_DEV_REGISTER, p2pFsmRunEventNetDeviceRegister}, + {MID_MNY_P2P_START_AP, p2pRoleFsmRunEventStartAP}, + {MID_MNY_P2P_DEL_IFACE, p2pRoleFsmRunEventDelIface}, + {MID_MNY_P2P_MGMT_FRAME_UPDATE, p2pFsmRunEventUpdateMgmtFrame}, +#if (CFG_SUPPORT_DFS_MASTER == 1) + {MID_MNY_P2P_DFS_CAC, p2pRoleFsmRunEventDfsCac}, + {MID_MNY_P2P_SET_NEW_CHANNEL, p2pRoleFsmRunEventSetNewChannel}, +#endif +#if CFG_SUPPORT_WFD + {MID_MNY_P2P_WFD_CFG_UPDATE, p2pFsmRunEventWfdSettingUpdate}, +#endif + {MID_MNY_P2P_ACTIVE_BSS, p2pDevFsmRunEventActiveDevBss}, +#endif + +#if CFG_SUPPORT_ADHOC + {MID_SCN_AIS_FOUND_IBSS, aisFsmRunEventFoundIBSSPeer}, +#endif /* CFG_SUPPORT_ADHOC */ + + {MID_SAA_AIS_FSM_ABORT, aisFsmRunEventAbort}, + {MID_MNY_AIS_REMAIN_ON_CHANNEL, aisFsmRunEventRemainOnChannel}, + {MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL, aisFsmRunEventCancelRemainOnChannel}, + {MID_MNY_AIS_MGMT_TX, aisFsmRunEventMgmtFrameTx} + +}; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#if DBG +#define MBOX_HNDL_MSG(prAdapter, prMsg) do { \ + ASSERT(arMsgMapTable[prMsg->eMsgId].pfMsgHndl); \ + if (arMsgMapTable[prMsg->eMsgId].pfMsgHndl) { \ + DBGLOG(CNM, LOUD, "DO MSG [%d: %s]\n", prMsg->eMsgId, apucDebugMsg[prMsg->eMsgId]); \ + arMsgMapTable[prMsg->eMsgId].pfMsgHndl(prAdapter, prMsg); \ + } \ + else { \ + DBGLOG(CNM, ERROR, "NULL fptr for MSG [%d]\n", prMsg->eMsgId); \ + cnmMemFree(prAdapter, prMsg); \ + } \ +} while (0) +#else +#define MBOX_HNDL_MSG(prAdapter, prMsg) do { \ + ASSERT(arMsgMapTable[prMsg->eMsgId].pfMsgHndl); \ + if (arMsgMapTable[prMsg->eMsgId].pfMsgHndl) { \ + DBGLOG(CNM, LOUD, "DO MSG [%d]\n", prMsg->eMsgId); \ + arMsgMapTable[prMsg->eMsgId].pfMsgHndl(prAdapter, prMsg); \ + } \ + else { \ + DBGLOG(CNM, ERROR, "NULL fptr for MSG [%d]\n", prMsg->eMsgId); \ + cnmMemFree(prAdapter, prMsg); \ + } \ +} while (0) +#endif +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mboxInitMsgMap(VOID) +{ + UINT_32 i, idx; + MSG_HNDL_ENTRY_T rTempEntry; + + ASSERT((sizeof(arMsgMapTable) / sizeof(MSG_HNDL_ENTRY_T)) == MID_TOTAL_NUM); + + for (i = 0; i < MID_TOTAL_NUM; i++) { + if (arMsgMapTable[i].eMsgId == (ENUM_MSG_ID_T) i) + continue; + for (idx = i + 1; idx < MID_TOTAL_NUM; idx++) { + if (arMsgMapTable[idx].eMsgId == (ENUM_MSG_ID_T) i) + break; + } + ASSERT(idx < MID_TOTAL_NUM); + if (idx >= MID_TOTAL_NUM) + continue; + + /* Swap target entry and current entry */ + rTempEntry.eMsgId = arMsgMapTable[idx].eMsgId; + rTempEntry.pfMsgHndl = arMsgMapTable[idx].pfMsgHndl; + + arMsgMapTable[idx].eMsgId = arMsgMapTable[i].eMsgId; + arMsgMapTable[idx].pfMsgHndl = arMsgMapTable[i].pfMsgHndl; + + arMsgMapTable[i].eMsgId = rTempEntry.eMsgId; + arMsgMapTable[i].pfMsgHndl = rTempEntry.pfMsgHndl; + } + + /* Verify the correctness of final message map */ + for (i = 0; i < MID_TOTAL_NUM; i++) { + ASSERT(arMsgMapTable[i].eMsgId == (ENUM_MSG_ID_T) i); + while (arMsgMapTable[i].eMsgId != (ENUM_MSG_ID_T) i) + ; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mboxSetup(IN P_ADAPTER_T prAdapter, IN ENUM_MBOX_ID_T eMboxId) +{ + P_MBOX_T prMbox; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(eMboxId < MBOX_ID_TOTAL_NUM); + ASSERT(prAdapter); + + prMbox = &(prAdapter->arMbox[eMboxId]); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); + LINK_INITIALIZE(&prMbox->rLinkHead); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +mboxSendMsg(IN P_ADAPTER_T prAdapter, + IN ENUM_MBOX_ID_T eMboxId, IN P_MSG_HDR_T prMsg, IN EUNM_MSG_SEND_METHOD_T eMethod) +{ + P_MBOX_T prMbox; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(eMboxId < MBOX_ID_TOTAL_NUM); + ASSERT(prMsg); + if (!prMsg) { + DBGLOG(CNM, ERROR, "prMsg is NULL\n"); + return; + } + + ASSERT(prAdapter); + if (!prAdapter) { + DBGLOG(CNM, ERROR, "prAdapter is NULL\n"); + return; + } + + 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); + if (!prMsg) { + DBGLOG(CNM, ERROR, "prMsg is NULL\n"); + continue; + } + MBOX_HNDL_MSG(prAdapter, prMsg); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mboxInitialize(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i; + + ASSERT(prAdapter); + + /* Initialize Mailbox */ + mboxInitMsgMap(); + + /* Setup/initialize each mailbox */ + for (i = 0; i < MBOX_ID_TOTAL_NUM; i++) + mboxSetup(prAdapter, i); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mboxDestroy(IN P_ADAPTER_T prAdapter) +{ + P_MBOX_T prMbox; + P_MSG_HDR_T prMsg; + UINT_8 i; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + for (i = 0; i < MBOX_ID_TOTAL_NUM; i++) { + prMbox = &(prAdapter->arMbox[i]); + + while (!LINK_IS_EMPTY(&prMbox->rLinkHead)) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); + LINK_REMOVE_HEAD(&prMbox->rLinkHead, prMsg, P_MSG_HDR_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); + + ASSERT(prMsg); + cnmMemFree(prAdapter, prMsg); + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is dummy function to prevent empty arMsgMapTable[] for compiling. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mboxDummy(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + ASSERT(prAdapter); + + cnmMemFree(prAdapter, prMsgHdr); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/hs20.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/hs20.c new file mode 100644 index 0000000000000..2b479597f9e21 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/hs20.c @@ -0,0 +1,554 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/HS2_DEV_SW/MT6620_WIFI_DRIVER_V2_1_HS_2_0/mgmt/hs20.c#2 +*/ + +/*! \file "hs20.c" +* \brief This file including the hotspot 2.0 related function. +* +* This file provided the macros and functions library support for the +* protocol layer hotspot 2.0 related function. +* +*/ + + + /******************************************************************************* +* C O M P I L E 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_PASSPOINT + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to generate Interworking IE for Probe Rsp, Bcn, Assoc Req/Rsp. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[out] prMsduInfo Pointer of the Msdu Info +* +* \return VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID hs20GenerateInterworkingIE(IN P_ADAPTER_T prAdapter, OUT P_MSDU_INFO_T prMsduInfo) +{ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to generate Roaming Consortium IE for Probe Rsp, Bcn, Assoc Req/Rsp. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[out] prMsduInfo Pointer of the Msdu Info +* +* \return VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID hs20GenerateRoamingConsortiumIE(IN P_ADAPTER_T prAdapter, OUT P_MSDU_INFO_T prMsduInfo) +{ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to generate HS2.0 IE for Probe Rsp, Bcn, Assoc Req/Rsp. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[out] prMsduInfo Pointer of the Msdu Info +* +* \return VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID hs20GenerateHS20IE(IN P_ADAPTER_T prAdapter, OUT P_MSDU_INFO_T prMsduInfo) +{ + PUINT_8 pucBuffer; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + if (prMsduInfo->ucBssIndex != KAL_NETWORK_TYPE_AIS_INDEX) { + pr_info("[%s] prMsduInfo->ucBssIndex(%d) is not KAL_NETWORK_TYPE_AIS_INDEX\n", + __func__, prMsduInfo->ucBssIndex); + return; + } + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (ULONG) prMsduInfo->u2FrameLength); + + /* ASSOC INFO IE ID: 221 :0xDD */ + if (prAdapter->prGlueInfo->u2HS20AssocInfoIELen) { + kalMemCopy(pucBuffer, &prAdapter->prGlueInfo->aucHS20AssocInfoIE, + prAdapter->prGlueInfo->u2HS20AssocInfoIELen); + prMsduInfo->u2FrameLength += prAdapter->prGlueInfo->u2HS20AssocInfoIELen; + } + +} + +VOID hs20FillExtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo) +{ + P_EXT_CAP_T prExtCap; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + /* Add Extended Capabilities IE */ + prExtCap = (P_EXT_CAP_T) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + + prExtCap->ucId = ELEM_ID_EXTENDED_CAP; + if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) + prExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + else + prExtCap->ucLength = 3 - ELEM_HDR_LEN; + + kalMemZero(prExtCap->aucCapabilities, prExtCap->ucLength); + + prExtCap->aucCapabilities[0] = ELEM_EXT_CAP_DEFAULT_VAL; + + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + prExtCap->aucCapabilities[0] &= ~ELEM_EXT_CAP_PSMP_CAP; + + if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) { + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_BSS_TRANSITION_BIT); + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_UTC_TSF_OFFSET_BIT); + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_INTERWORKING_BIT); + + /* For R2 WNM-Notification */ + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_WNM_NOTIFICATION_BIT); + } + + pr_info("IE_SIZE(prExtCap) = %d, %d %d\n", IE_SIZE(prExtCap), ELEM_HDR_LEN, ELEM_MAX_LEN_EXT_CAP); + ASSERT(IE_SIZE(prExtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP)); + + prMsduInfo->u2FrameLength += IE_SIZE(prExtCap); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to fill up the content of Ext Cap IE bit 31. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[out] pucIE Pointer of the IE buffer +* +* \return VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID hs20FillProreqExtCapIE(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucIE) +{ + P_EXT_CAP_T prExtCap; + + ASSERT(prAdapter); + + /* Add Extended Capabilities IE */ + prExtCap = (P_EXT_CAP_T) pucIE; + + prExtCap->ucId = ELEM_ID_EXTENDED_CAP; + if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) + prExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + else + prExtCap->ucLength = 3 - ELEM_HDR_LEN; + + kalMemZero(prExtCap->aucCapabilities, prExtCap->ucLength); + + prExtCap->aucCapabilities[0] = ELEM_EXT_CAP_DEFAULT_VAL; + + if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) { + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_BSS_TRANSITION_BIT); + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_UTC_TSF_OFFSET_BIT); + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_INTERWORKING_BIT); + + /* For R2 WNM-Notification */ + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_WNM_NOTIFICATION_BIT); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to fill up the content of HS2.0 IE. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[out] pucIE Pointer of the IE buffer +* +* \return VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID hs20FillHS20IE(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucIE) +{ + P_IE_HS20_INDICATION_T prHS20IndicationIe; + /* P_HS20_INFO_T prHS20Info; */ + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + + /* prHS20Info = &(prAdapter->rWifiVar.rHS20Info); */ + + prHS20IndicationIe = (P_IE_HS20_INDICATION_T) pucIE; + + prHS20IndicationIe->ucId = ELEM_ID_VENDOR; + prHS20IndicationIe->ucLength = sizeof(IE_HS20_INDICATION_T) - ELEM_HDR_LEN; + prHS20IndicationIe->aucOui[0] = aucWfaOui[0]; + prHS20IndicationIe->aucOui[1] = aucWfaOui[1]; + prHS20IndicationIe->aucOui[2] = aucWfaOui[2]; + prHS20IndicationIe->ucType = VENDOR_OUI_TYPE_HS20; + + /* prHS20IndicationIe->ucHotspotConfig = 0x00; *//* For PASSPOINT_R1 */ + prHS20IndicationIe->ucHotspotConfig = 0x10; /* For PASSPOINT_R2 */ + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called while calculating length of hotspot 2.0 indication IE for Probe Request. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[in] pucTargetBSSID Pointer of target HESSID +* +* \return the length of composed HS20 IE +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 hs20CalculateHS20RelatedIEForProbeReq(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucTargetBSSID) +{ + UINT_32 u4IeLength; + + if (0) /* Todo:: Not HS20 STA */ + return 0; + + u4IeLength = sizeof(IE_HS20_INDICATION_T) + /* sizeof(IE_INTERWORKING_T) */ + (ELEM_HDR_LEN + + ELEM_MAX_LEN_EXT_CAP); + + if (!pucTargetBSSID) { + /* Todo:: Nothing */ + /* u4IeLength -= MAC_ADDR_LEN; */ + } + + return u4IeLength; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called while composing hotspot 2.0 indication IE for Probe Request. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[in] pucTargetBSSID Pointer of target HESSID +* \param[out] prIE Pointer of the IE buffer +* +* \return the wlan status +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS hs20GenerateHS20RelatedIEForProbeReq(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucTargetBSSID, OUT PUINT_8 prIE) +{ + if (0) /* Todo:: Not HS20 STA */ + return 0; +#if 0 + P_HS20_INFO_T prHS20Info; + + prHS20Info = &(prAdapter->rWifiVar.rHS20Info); + + /* + * Generate 802.11u Interworking IE (107) + */ + hs20FillInterworkingIE(prAdapter, + prHS20Info->ucAccessNetworkOptions, + prHS20Info->ucVenueGroup, prHS20Info->ucVenueType, pucTargetBSSID, prIE); + prIE += IE_SIZE(prIE); +#endif + /* + * Generate Ext Cap IE (127) + */ + hs20FillProreqExtCapIE(prAdapter, prIE); + prIE += IE_SIZE(prIE); + + /* + * Generate HS2.0 Indication IE (221) + */ + hs20FillHS20IE(prAdapter, prIE); + prIE += IE_SIZE(prIE); + + return WLAN_STATUS_SUCCESS; +} + +BOOLEAN hs20IsGratuitousArp(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prCurrSwRfb) +{ + PUINT_8 pucSenderIP = prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + ARP_SENDER_IP_OFFSET; + PUINT_8 pucTargetIP = prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + ARP_TARGET_IP_OFFSET; + PUINT_8 pucSenderMac = ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + ARP_SNEDER_MAC_OFFSET); +#if CFG_HS20_DEBUG && 0 +/* UINT_8 aucIpAllZero[4] = {0,0,0,0}; */ +/* UINT_8 aucMACAllZero[MAC_ADDR_LEN] = {0,0,0,0,0,0}; */ + PUINT_8 pucTargetMac = ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + ARP_TARGET_MAC_OFFSET); +#endif + +#if CFG_HS20_DEBUG && 0 + PUINT_16 pu2ArpOper = (PUINT_16) ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + ARP_OPERATION_OFFSET); + + kalPrint("Recv ARP 0x%04X\n", htons(*pu2ArpOper)); + kalPrint("SENDER[" MACSTR "] [%d:%d:%d:%d]\n", MAC2STR(pucSenderMac), *pucSenderIP, + *(pucSenderIP + 1), *(pucSenderIP + 2), *(pucSenderIP + 3)); + kalPrint("TARGET[" MACSTR "] [%d:%d:%d:%d]\n", MAC2STR(pucTargetMac), *pucTargetIP, + *(pucTargetIP + 1), *(pucTargetIP + 2), *(pucTargetIP + 3)); +#endif + + /* IsGratuitousArp */ + if (!kalMemCmp(pucSenderIP, pucTargetIP, 4)) { + kalPrint("Drop Gratuitous ARP from [" MACSTR "] [%d:%d:%d:%d]\n", + MAC2STR(pucSenderMac), *pucTargetIP, *(pucTargetIP + 1), + *(pucTargetIP + 2), *(pucTargetIP + 3)); + return TRUE; + } + return FALSE; +} + +BOOLEAN hs20IsUnsolicitedNeighborAdv(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prCurrSwRfb) +{ + PUINT_8 pucIpv6Protocol = ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + IPV6_HDR_IP_PROTOCOL_OFFSET); + + /* kalPrint("pucIpv6Protocol [%02X:%02X]\n", *pucIpv6Protocol, IPV6_PROTOCOL_ICMPV6); */ + if (*pucIpv6Protocol == IPV6_PROTOCOL_ICMPV6) { + PUINT_8 pucICMPv6Type = + ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + IPV6_HDR_LEN + ICMPV6_TYPE_OFFSET); + /* kalPrint("pucICMPv6Type [%02X:%02X]\n", *pucICMPv6Type, ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT); */ + if (*pucICMPv6Type == ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT) { + PUINT_8 pucICMPv6Flag = + ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + IPV6_HDR_LEN + ICMPV6_FLAG_OFFSET); + PUINT_8 pucSrcMAC = ((PUINT_8) prCurrSwRfb->pvHeader + MAC_ADDR_LEN); + +#if CFG_HS20_DEBUG + kalPrint("NAdv Flag [%02X] [R(%d)\\S(%d)\\O(%d)]\n", + *pucICMPv6Flag, + (UINT_8) (*pucICMPv6Flag & ICMPV6_FLAG_ROUTER_BIT) >> 7, + (UINT_8) (*pucICMPv6Flag & ICMPV6_FLAG_SOLICITED_BIT) >> 6, + (UINT_8) (*pucICMPv6Flag & ICMPV6_FLAG_OVERWRITE_BIT) >> 5); +#endif + if (!(*pucICMPv6Flag & ICMPV6_FLAG_SOLICITED_BIT)) { + kalPrint("Drop Unsolicited Neighbor Advertisement from [" MACSTR + "]\n", MAC2STR(pucSrcMAC)); + return TRUE; + } + } + } + + return FALSE; +} + +#if CFG_ENABLE_GTK_FRAME_FILTER +BOOLEAN hs20IsForgedGTKFrame(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_SW_RFB_T prCurrSwRfb) +{ + P_CONNECTION_SETTINGS_T prConnSettings = &prAdapter->rWifiVar.rConnSettings; + PUINT_8 pucEthDestAddr = prCurrSwRfb->pvHeader; + + /* 3 TODO: Need to verify this function before enable it */ + return FALSE; + + if ((prConnSettings->eEncStatus != ENUM_ENCRYPTION_DISABLED) + && IS_BMCAST_MAC_ADDR(pucEthDestAddr)) { + UINT_8 ucIdx = 0; + PUINT_32 prIpAddr, prPacketDA; + PUINT_16 pu2PktIpVer = + (PUINT_16) ((PUINT_8) prCurrSwRfb->pvHeader + (ETHER_HEADER_LEN - ETHER_TYPE_LEN)); + + if (*pu2PktIpVer == htons(ETH_P_IPV4)) { + if (!prBssInfo->prIpV4NetAddrList) + return FALSE; + for (ucIdx = 0; ucIdx < prBssInfo->prIpV4NetAddrList->ucAddrCount; ucIdx++) { + prIpAddr = (PUINT_32) &prBssInfo->prIpV4NetAddrList->arNetAddr[ucIdx].aucIpAddr[0]; + prPacketDA = + (PUINT_32) ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + + IPV4_HDR_IP_DST_ADDR_OFFSET); + + if (kalMemCmp(prIpAddr, prPacketDA, 4) == 0) { + kalPrint("Drop FORGED IPv4 packet\n"); + return TRUE; + } + } + } +#ifdef CONFIG_IPV6 + else if (*pu2PktIpVer == htons(ETH_P_IPV6)) { + UINT_8 aucIPv6Mac[MAC_ADDR_LEN]; + PUINT_8 pucIdx = + prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + IPV6_HDR_IP_DST_ADDR_MAC_HIGH_OFFSET; + + kalMemCopy(&aucIPv6Mac[0], pucIdx, 3); + pucIdx += 5; + kalMemCopy(&aucIPv6Mac[3], pucIdx, 3); + kalPrint("Get IPv6 frame Dst IP MAC part " MACSTR "\n", MAC2STR(aucIPv6Mac)); + if (EQUAL_MAC_ADDR(aucIPv6Mac, prBssInfo->aucOwnMacAddr)) { + kalPrint("Drop FORGED IPv6 packet\n"); + return TRUE; + } + } +#endif + } + + return FALSE; +} +#endif + +BOOLEAN hs20IsUnsecuredFrame(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_SW_RFB_T prCurrSwRfb) +{ + PUINT_16 pu2PktIpVer = (PUINT_16) ((PUINT_8) prCurrSwRfb->pvHeader + (ETHER_HEADER_LEN - ETHER_TYPE_LEN)); + + /* kalPrint("IPVER 0x%4X\n", htons(*pu2PktIpVer)); */ +#if CFG_HS20_DEBUG & 0 + UINT_8 i = 0; + + kalPrint("==============================================="); + for (i = 0; i < 96; i++) { + if (!(i % 16)) + kalPrint("\n"); + kalPrint("%02X ", *((PUINT_8) prCurrSwRfb->pvHeader + i)); + } + kalPrint("\n"); +#endif + +#if CFG_ENABLE_GTK_FRAME_FILTER + if (hs20IsForgedGTKFrame(prAdapter, prBssInfo, prCurrSwRfb)) + return TRUE; +#endif + if (*pu2PktIpVer == htons(ETH_P_ARP)) + return hs20IsGratuitousArp(prAdapter, prCurrSwRfb); + else if (*pu2PktIpVer == htons(ETH_P_IPV6)) + return hs20IsUnsolicitedNeighborAdv(prAdapter, prCurrSwRfb); + + return FALSE; +} + +BOOLEAN hs20IsFrameFilterEnabled(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo) +{ +#if 1 + if (prAdapter->prGlueInfo->fgConnectHS20AP) + return TRUE; +#else + PARAM_SSID_T rParamSsid; + P_BSS_DESC_T prBssDesc; + + rParamSsid.u4SsidLen = prBssInfo->ucSSIDLen; + COPY_SSID(rParamSsid.aucSsid, rParamSsid.u4SsidLen, prBssInfo->aucSSID, prBssInfo->ucSSIDLen); + + prBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, prBssInfo->aucBSSID, TRUE, &rParamSsid); + if (!prBssDesc) + return FALSE; + + if (prBssDesc->fgIsSupportHS20) { + if (!(prBssDesc->ucHotspotConfig & ELEM_HS_CONFIG_DGAF_DISABLED_MASK)) + return TRUE; + /* Disable frame filter only if DGAF == 1 */ + return FALSE; + } +#endif + + /* For Now, always return true to run hs20 check even for legacy AP */ + return TRUE; +} + +WLAN_STATUS hs20SetBssidPool(IN P_ADAPTER_T prAdapter, IN PVOID pvBuffer, IN ENUM_KAL_NETWORK_TYPE_INDEX_T eNetTypeIdx) +{ + P_PARAM_HS20_SET_BSSID_POOL prParamBssidPool = (P_PARAM_HS20_SET_BSSID_POOL) pvBuffer; + P_HS20_INFO_T prHS20Info; + UINT_8 ucIdx; + + prHS20Info = &(prAdapter->rWifiVar.rHS20Info); + + pr_info("[%s]Set Bssid Pool! enable[%d] num[%d]\n", __func__, prParamBssidPool->fgIsEnable, + prParamBssidPool->ucNumBssidPool); + + for (ucIdx = 0; ucIdx < prParamBssidPool->ucNumBssidPool; ucIdx++) { + COPY_MAC_ADDR(prHS20Info->arBssidPool[ucIdx].aucBSSID, &prParamBssidPool->arBSSID[ucIdx]); + pr_info("[%s][%d][" MACSTR "]\n", __func__, ucIdx, MAC2STR(prHS20Info->arBssidPool[ucIdx].aucBSSID)); + } + prHS20Info->fgIsHS2SigmaMode = prParamBssidPool->fgIsEnable; + prHS20Info->ucNumBssidPoolEntry = prParamBssidPool->ucNumBssidPool; + +#if 0 + wlanClearScanningResult(prAdapter); +#endif + + return WLAN_STATUS_SUCCESS; +} + +#endif /* CFG_SUPPORT_PASSPOINT */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/mib.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/mib.c new file mode 100644 index 0000000000000..726736c3d05ce --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/mib.c @@ -0,0 +1,139 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +NON_HT_PHY_ATTRIBUTE_T rNonHTPhyAttributes[] = { + {RATE_SET_HR_DSSS, TRUE, FALSE} + , /* For PHY_TYPE_HR_DSSS_INDEX(0) */ + {RATE_SET_ERP, TRUE, TRUE} + , /* For PHY_TYPE_ERP_INDEX(1) */ + {RATE_SET_ERP_P2P, TRUE, TRUE} + , /* For PHY_TYPE_ERP_P2P_INDEX(2) */ + {RATE_SET_OFDM, FALSE, FALSE} + , /* For PHY_TYPE_OFDM_INDEX(3) */ +}; + +NON_HT_ADHOC_MODE_ATTRIBUTE_T rNonHTAdHocModeAttributes[AD_HOC_MODE_NUM] = { + {PHY_TYPE_HR_DSSS_INDEX, BASIC_RATE_SET_HR_DSSS} + , /* For AD_HOC_MODE_11B(0) */ + {PHY_TYPE_ERP_INDEX, BASIC_RATE_SET_HR_DSSS_ERP} + , /* For AD_HOC_MODE_MIXED_11BG(1) */ + {PHY_TYPE_ERP_INDEX, BASIC_RATE_SET_ERP} + , /* For AD_HOC_MODE_11G(2) */ + {PHY_TYPE_OFDM_INDEX, BASIC_RATE_SET_OFDM} + , /* For AD_HOC_MODE_11A(3) */ +}; + +NON_HT_AP_MODE_ATTRIBUTE_T rNonHTApModeAttributes[AP_MODE_NUM] = { + {PHY_TYPE_HR_DSSS_INDEX, BASIC_RATE_SET_HR_DSSS} + , /* For AP_MODE_11B(0) */ + {PHY_TYPE_ERP_INDEX, BASIC_RATE_SET_HR_DSSS_ERP} + , /* For AP_MODE_MIXED_11BG(1) */ + {PHY_TYPE_ERP_INDEX, BASIC_RATE_SET_ERP} + , /* For AP_MODE_11G(2) */ + {PHY_TYPE_ERP_P2P_INDEX, BASIC_RATE_SET_ERP_P2P} + , /* For AP_MODE_11G_P2P(3) */ + {PHY_TYPE_OFDM_INDEX, BASIC_RATE_SET_OFDM} + , /* For AP_MODE_11A(4) */ +}; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_assoc.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_assoc.c new file mode 100644 index 0000000000000..d3a352c4ab41c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_assoc.c @@ -0,0 +1,138 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + + /* 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, prP2pBssInfo->aucSSID, prP2pBssInfo->ucSSIDLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + return pucBuffer; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_bss.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_bss.c new file mode 100644 index 0000000000000..e990db9ff79ee --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_bss.c @@ -0,0 +1,109 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: @(#) p2p_bss.c@@ +*/ + +/*! \file "p2p_bss.c" + * \brief This file contains the functions for creating p2p BSS(AP). + * + * This file contains the functions for BSS(AP). We may create a BSS + * network, or merge with exist IBSS network and sending Beacon Frame or reply + * the Probe Response Frame for received Probe Request Frame. + */ + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ + +#include "precomp.h" + +/******************************************************************************* + * C O N S T A N T S + ******************************************************************************** + */ + +/******************************************************************************* + * D A T A T Y P E S + ******************************************************************************** + */ + +/******************************************************************************* + * P U B L I C D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************** + */ + +/******************************************************************************* + * M A C R O S + ******************************************************************************** + */ + +/******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************** + */ + +/******************************************************************************* + * F U N C T I O N S + ******************************************************************************** + */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_dev_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_dev_fsm.c new file mode 100644 index 0000000000000..095faf2ab0006 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_dev_fsm.c @@ -0,0 +1,862 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#include "precomp.h" +#include "p2p_dev_state.h" +#if CFG_ENABLE_WIFI_DIRECT + +#if 1 +/*lint -save -e64 Type mismatch */ +static PUINT_8 apucDebugP2pDevState[P2P_DEV_STATE_NUM] = { + (PUINT_8) DISP_STRING("P2P_DEV_STATE_IDLE"), + (PUINT_8) DISP_STRING("P2P_DEV_STATE_SCAN"), + (PUINT_8) DISP_STRING("P2P_DEV_STATE_REQING_CHANNEL"), + (PUINT_8) DISP_STRING("P2P_DEV_STATE_CHNL_ON_HAND"), + (PUINT_8) DISP_STRING("P2P_DEV_STATE_NUM") +}; + +/*lint -restore */ +#endif /* DBG */ + +UINT_8 p2pDevFsmInit(IN P_ADAPTER_T prAdapter) +{ + P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo = (P_P2P_DEV_FSM_INFO_T) NULL; + P_P2P_CHNL_REQ_INFO_T prP2pChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; + P_P2P_MGMT_TX_REQ_INFO_T prP2pMgmtTxReqInfo = (P_P2P_MGMT_TX_REQ_INFO_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + ASSERT_BREAK(prP2pDevFsmInfo != NULL); + + kalMemZero(prP2pDevFsmInfo, sizeof(P2P_DEV_FSM_INFO_T)); + + prP2pDevFsmInfo->eCurrentState = P2P_DEV_STATE_IDLE; + + cnmTimerInitTimer(prAdapter, + &(prP2pDevFsmInfo->rP2pFsmTimeoutTimer), + (PFN_MGMT_TIMEOUT_FUNC) p2pDevFsmRunEventTimeout, (ULONG) prP2pDevFsmInfo); + + prP2pBssInfo = cnmGetBssInfoAndInit(prAdapter, NETWORK_TYPE_P2P, TRUE); + + if (prP2pBssInfo != NULL) { + COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, prAdapter->rMyMacAddr); + prP2pBssInfo->aucOwnMacAddr[0] ^= 0x2; /* change to local administrated address */ + + prP2pDevFsmInfo->ucBssIndex = prP2pBssInfo->ucBssIndex; + + prP2pBssInfo->eCurrentOPMode = OP_MODE_P2P_DEVICE; + prP2pBssInfo->ucConfigAdHocAPMode = AP_MODE_11G_P2P; + prP2pBssInfo->u2HwDefaultFixedRateCode = RATE_OFDM_6M; + + prP2pBssInfo->eBand = BAND_2G4; + prP2pBssInfo->eDBDCBand = ENUM_BAND_0; +#if (CFG_HW_WMM_BY_BSS == 1) + prP2pBssInfo->ucWmmQueSet = MAX_HW_WMM_INDEX; +#else + prP2pBssInfo->ucWmmQueSet = + (prAdapter->rWifiVar.ucDbdcMode == DBDC_MODE_DISABLED) ? + DBDC_5G_WMM_INDEX : DBDC_2G_WMM_INDEX; +#endif + prP2pBssInfo->ucPhyTypeSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11GN; + + prP2pBssInfo->ucNonHTBasicPhyType = (UINT_8) + rNonHTApModeAttributes[prP2pBssInfo->ucConfigAdHocAPMode].ePhyTypeIndex; + prP2pBssInfo->u2BSSBasicRateSet = + rNonHTApModeAttributes[prP2pBssInfo->ucConfigAdHocAPMode].u2BSSBasicRateSet; + + prP2pBssInfo->u2OperationalRateSet = + rNonHTPhyAttributes[prP2pBssInfo->ucNonHTBasicPhyType].u2SupportedRateSet; + prP2pBssInfo->u4PrivateData = 0;/* TH3 Huang */ + + rateGetDataRatesFromRateSet(prP2pBssInfo->u2OperationalRateSet, + prP2pBssInfo->u2BSSBasicRateSet, + prP2pBssInfo->aucAllSupportedRates, &prP2pBssInfo->ucAllSupportedRatesLen); + } + prP2pChnlReqInfo = &prP2pDevFsmInfo->rChnlReqInfo; + LINK_INITIALIZE(&prP2pChnlReqInfo->rP2pChnlReqLink); + + prP2pMgmtTxReqInfo = &prP2pDevFsmInfo->rMgmtTxInfo; + LINK_INITIALIZE(&prP2pMgmtTxReqInfo->rP2pTxReqLink); + + p2pDevFsmStateTransition(prAdapter, prP2pDevFsmInfo, P2P_DEV_STATE_IDLE); + } while (FALSE); + + if (prP2pBssInfo) + return prP2pBssInfo->ucBssIndex; + else + return P2P_DEV_BSS_INDEX + 1; + +#if 0 + 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)); + + prP2pFsmInfo->eCurrentState = prP2pFsmInfo->ePreviousState = P2P_STATE_IDLE; + prP2pFsmInfo->prTargetBss = NULL; + + cnmTimerInitTimer(prAdapter, + &(prP2pFsmInfo->rP2pFsmTimeoutTimer), + (PFN_MGMT_TIMEOUT_FUNC) p2pFsmRunEventFsmTimeout, (ULONG) prP2pFsmInfo); + + /* 4 <2> Initiate BSS_INFO_T - common part */ + BSS_INFO_INIT(prAdapter, NETWORK_TYPE_P2P_INDEX); + + /* 4 <2.1> Initiate BSS_INFO_T - Setup HW ID */ + prP2pBssInfo->ucConfigAdHocAPMode = AP_MODE_11G_P2P; + prP2pBssInfo->ucHwDefaultFixedRateCode = RATE_OFDM_6M; + + prP2pBssInfo->ucNonHTBasicPhyType = (UINT_8) + rNonHTApModeAttributes[prP2pBssInfo->ucConfigAdHocAPMode].ePhyTypeIndex; + prP2pBssInfo->u2BSSBasicRateSet = + rNonHTApModeAttributes[prP2pBssInfo->ucConfigAdHocAPMode].u2BSSBasicRateSet; + + prP2pBssInfo->u2OperationalRateSet = + rNonHTPhyAttributes[prP2pBssInfo->ucNonHTBasicPhyType].u2SupportedRateSet; + + rateGetDataRatesFromRateSet(prP2pBssInfo->u2OperationalRateSet, + prP2pBssInfo->u2BSSBasicRateSet, + prP2pBssInfo->aucAllSupportedRates, &prP2pBssInfo->ucAllSupportedRatesLen); + + prP2pBssInfo->prBeacon = cnmMgtPktAlloc(prAdapter, + OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem[0]) + MAX_IE_LENGTH); + + if (prP2pBssInfo->prBeacon) { + prP2pBssInfo->prBeacon->eSrc = TX_PACKET_MGMT; + prP2pBssInfo->prBeacon->ucStaRecIndex = 0xFF; /* NULL STA_REC */ + prP2pBssInfo->prBeacon->ucNetworkType = NETWORK_TYPE_P2P_INDEX; + } else { + /* Out of memory. */ + ASSERT(FALSE); + } + + prP2pBssInfo->eCurrentOPMode = OP_MODE_NUM; + + prP2pBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC = PM_UAPSD_ALL; + prP2pBssInfo->rPmProfSetupInfo.ucBmpTriggerAC = PM_UAPSD_ALL; + prP2pBssInfo->rPmProfSetupInfo.ucUapsdSp = WMM_MAX_SP_LENGTH_2; + prP2pBssInfo->ucPrimaryChannel = P2P_DEFAULT_LISTEN_CHANNEL; + prP2pBssInfo->eBand = BAND_2G4; + prP2pBssInfo->eBssSCO = CHNL_EXT_SCN; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) + 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; +#endif +} /* p2pDevFsmInit */ + +VOID p2pDevFsmUninit(IN P_ADAPTER_T prAdapter) +{ + P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo = (P_P2P_DEV_FSM_INFO_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + ASSERT_BREAK(prP2pDevFsmInfo != NULL); + + prP2pBssInfo = prAdapter->aprBssInfo[prP2pDevFsmInfo->ucBssIndex]; + + cnmTimerStopTimer(prAdapter, &(prP2pDevFsmInfo->rP2pFsmTimeoutTimer)); + + /* Abort device FSM */ + p2pDevFsmStateTransition(prAdapter, prP2pDevFsmInfo, P2P_DEV_STATE_IDLE); + p2pDevFsmRunEventAbort(prAdapter, prP2pDevFsmInfo); + + if (prP2pBssInfo->ucBssIndex < BSS_INFO_NUM) { + SET_NET_PWR_STATE_IDLE(prAdapter, + prP2pBssInfo->ucBssIndex); + } + + /* Clear CmdQue */ + kalClearMgmtFramesByBssIdx(prAdapter->prGlueInfo, prP2pBssInfo->ucBssIndex); + kalClearSecurityFramesByBssIdx(prAdapter->prGlueInfo, prP2pBssInfo->ucBssIndex); + /* Clear PendingCmdQue */ + wlanReleasePendingCMDbyBssIdx(prAdapter, prP2pBssInfo->ucBssIndex); + /* Clear PendingTxMsdu */ + nicFreePendingTxMsduInfoByBssIdx(prAdapter, prP2pBssInfo->ucBssIndex); + + /* Deactivate BSS. */ + UNSET_NET_ACTIVE(prAdapter, prP2pBssInfo->ucBssIndex); + + nicDeactivateNetwork(prAdapter, prP2pBssInfo->ucBssIndex); + + cnmFreeBssInfo(prAdapter, prP2pBssInfo); + } while (FALSE); + +#if 0 + 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. + */ + kalClearMgmtFramesByBssIdx(prAdapter->prGlueInfo, NETWORK_TYPE_P2P_INDEX); + + /* Clear PendingCmdQue */ + wlanReleasePendingCMDbyBssIdx(prAdapter, NETWORK_TYPE_P2P_INDEX); + + if (prP2pBssInfo->prBeacon) { + cnmMgtPktFree(prAdapter, prP2pBssInfo->prBeacon); + prP2pBssInfo->prBeacon = NULL; + } + } while (FALSE); + + return; +#endif +} /* p2pDevFsmUninit */ + +VOID +p2pDevFsmStateTransition(IN P_ADAPTER_T prAdapter, + IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo, IN ENUM_P2P_DEV_STATE_T eNextState) +{ + BOOLEAN fgIsLeaveState = (BOOLEAN) FALSE; + + ASSERT(prP2pDevFsmInfo); + if (!prP2pDevFsmInfo) { + DBGLOG(P2P, ERROR, "prP2pDevFsmInfo is NULL!\n"); + return; + } + + ASSERT(prP2pDevFsmInfo->ucBssIndex == P2P_DEV_BSS_INDEX); + if (prP2pDevFsmInfo->ucBssIndex != P2P_DEV_BSS_INDEX) { + DBGLOG(P2P, ERROR, + "prP2pDevFsmInfo->ucBssIndex %d should be P2P_DEV_BSS_INDEX(%d)!\n", + prP2pDevFsmInfo->ucBssIndex, P2P_DEV_BSS_INDEX); + return; + } + + do { + if (!IS_BSS_ACTIVE(prAdapter->aprBssInfo[prP2pDevFsmInfo->ucBssIndex])) { + if (!cnmP2PIsPermitted(prAdapter)) + return; + + SET_NET_ACTIVE(prAdapter, prP2pDevFsmInfo->ucBssIndex); + nicActivateNetwork(prAdapter, prP2pDevFsmInfo->ucBssIndex); + } + + fgIsLeaveState = fgIsLeaveState ? FALSE : TRUE; + + if (!fgIsLeaveState) { + DBGLOG(P2P, STATE, "[P2P_DEV]TRANSITION: [%s] -> [%s]\n", + apucDebugP2pDevState[prP2pDevFsmInfo->eCurrentState], apucDebugP2pDevState[eNextState]); + + /* Transition into current state. */ + prP2pDevFsmInfo->eCurrentState = eNextState; + } + + switch (prP2pDevFsmInfo->eCurrentState) { + case P2P_DEV_STATE_IDLE: + if (!fgIsLeaveState) { + fgIsLeaveState = p2pDevStateInit_IDLE(prAdapter, + &prP2pDevFsmInfo->rChnlReqInfo, &eNextState); + } else { + p2pDevStateAbort_IDLE(prAdapter); + } + break; + case P2P_DEV_STATE_SCAN: + if (!fgIsLeaveState) { + p2pDevStateInit_SCAN(prAdapter, + prP2pDevFsmInfo->ucBssIndex, &prP2pDevFsmInfo->rScanReqInfo); + } else { + p2pDevStateAbort_SCAN(prAdapter, prP2pDevFsmInfo); + } + break; + case P2P_DEV_STATE_REQING_CHANNEL: + if (!fgIsLeaveState) { + fgIsLeaveState = p2pDevStateInit_REQING_CHANNEL(prAdapter, + prP2pDevFsmInfo->ucBssIndex, + &(prP2pDevFsmInfo->rChnlReqInfo), + &eNextState); + } else { + p2pDevStateAbort_REQING_CHANNEL(prAdapter, + &(prP2pDevFsmInfo->rChnlReqInfo), eNextState); + } + break; + case P2P_DEV_STATE_CHNL_ON_HAND: + if (!fgIsLeaveState) { + p2pDevStateInit_CHNL_ON_HAND(prAdapter, + prAdapter->aprBssInfo[prP2pDevFsmInfo->ucBssIndex], + prP2pDevFsmInfo, &(prP2pDevFsmInfo->rChnlReqInfo)); + } else { + p2pDevStateAbort_CHNL_ON_HAND(prAdapter, + prAdapter->aprBssInfo[prP2pDevFsmInfo->ucBssIndex], + prP2pDevFsmInfo, &(prP2pDevFsmInfo->rChnlReqInfo)); + } + break; + case P2P_DEV_STATE_OFF_CHNL_TX: + if (!fgIsLeaveState) { + fgIsLeaveState = p2pDevStateInit_OFF_CHNL_TX(prAdapter, + prP2pDevFsmInfo, + &(prP2pDevFsmInfo->rChnlReqInfo), + &(prP2pDevFsmInfo->rMgmtTxInfo), + &eNextState); + } else { + p2pDevStateAbort_OFF_CHNL_TX(prAdapter, + &(prP2pDevFsmInfo->rMgmtTxInfo), + &(prP2pDevFsmInfo->rChnlReqInfo), eNextState); + } + break; + default: + /* Unexpected state. */ + ASSERT(FALSE); + break; + } + } while (fgIsLeaveState); +} /* p2pDevFsmStateTransition */ + +VOID p2pDevFsmRunEventAbort(IN P_ADAPTER_T prAdapter, IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo) +{ + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pDevFsmInfo != NULL)); + + if (prP2pDevFsmInfo->eCurrentState != P2P_DEV_STATE_IDLE) { + /* Get into IDLE state. */ + p2pDevFsmStateTransition(prAdapter, prP2pDevFsmInfo, P2P_DEV_STATE_IDLE); + } + + /* Abort IDLE. */ + p2pDevStateAbort_IDLE(prAdapter); + } while (FALSE); +} /* p2pDevFsmRunEventAbort */ + +VOID p2pDevFsmRunEventTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr) +{ + P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo = (P_P2P_DEV_FSM_INFO_T) ulParamPtr; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pDevFsmInfo != NULL)); + + switch (prP2pDevFsmInfo->eCurrentState) { + case P2P_DEV_STATE_IDLE: + /* TODO: IDLE timeout for low power mode. */ + break; + case P2P_DEV_STATE_CHNL_ON_HAND: + p2pDevFsmStateTransition(prAdapter, prP2pDevFsmInfo, P2P_DEV_STATE_IDLE); + break; + default: + ASSERT(FALSE); + DBGLOG(P2P, ERROR, + "Current P2P Dev State %d is unexpected for FSM timeout event.\n", + prP2pDevFsmInfo->eCurrentState); + break; + } + } while (FALSE); +} /* p2pDevFsmRunEventTimeout */ + +/*================ Message Event =================*/ +VOID p2pDevFsmRunEventScanRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_P2P_SCAN_REQUEST_T prP2pScanReqMsg = (P_MSG_P2P_SCAN_REQUEST_T) NULL; + P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo = (P_P2P_DEV_FSM_INFO_T) NULL; + P_P2P_SCAN_REQ_INFO_T prScanReqInfo = (P_P2P_SCAN_REQ_INFO_T) NULL; + UINT_32 u4ChnlListSize = 0; + P_P2P_SSID_STRUCT_T prP2pSsidStruct = (P_P2P_SSID_STRUCT_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + if (prP2pDevFsmInfo == NULL) + break; + + if (prP2pDevFsmInfo->eCurrentState != P2P_DEV_STATE_IDLE) + p2pDevFsmRunEventAbort(prAdapter, prP2pDevFsmInfo); + + prP2pScanReqMsg = (P_MSG_P2P_SCAN_REQUEST_T) prMsgHdr; + prScanReqInfo = &(prP2pDevFsmInfo->rScanReqInfo); + + DBGLOG(P2P, TRACE, "p2pDevFsmRunEventScanRequest\n"); + + /* Do we need to be in IDLE state? */ + /* p2pDevFsmRunEventAbort(prAdapter, prP2pDevFsmInfo); */ + + ASSERT(prScanReqInfo->fgIsScanRequest == FALSE); + + prScanReqInfo->fgIsAbort = TRUE; + prScanReqInfo->eScanType = prP2pScanReqMsg->eScanType; + prScanReqInfo->u2PassiveDewellTime = 0; + + if (prP2pScanReqMsg->u4NumChannel) { + 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); + } else { + /* If channel number is ZERO. + * It means do a FULL channel scan. + */ + prScanReqInfo->eChannelSet = SCAN_CHANNEL_FULL; + } + + /* SSID */ + prP2pSsidStruct = prP2pScanReqMsg->prSSID; + for (prScanReqInfo->ucSsidNum = 0; + prScanReqInfo->ucSsidNum < prP2pScanReqMsg->i4SsidNum; prScanReqInfo->ucSsidNum++) { + kalMemCopy(prScanReqInfo->arSsidStruct[prScanReqInfo->ucSsidNum].aucSsid, + prP2pSsidStruct->aucSsid, prP2pSsidStruct->ucSsidLen); + + prScanReqInfo->arSsidStruct[prScanReqInfo->ucSsidNum].ucSsidLen = prP2pSsidStruct->ucSsidLen; + + prP2pSsidStruct++; + } + + /* IE Buffer */ + kalMemCopy(prScanReqInfo->aucIEBuf, prP2pScanReqMsg->pucIEBuf, prP2pScanReqMsg->u4IELen); + + prScanReqInfo->u4BufLength = prP2pScanReqMsg->u4IELen; + + p2pDevFsmStateTransition(prAdapter, prP2pDevFsmInfo, P2P_DEV_STATE_SCAN); + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventScanRequest */ + +VOID +p2pDevFsmRunEventScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr, IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo) +{ + P_MSG_SCN_SCAN_DONE prScanDoneMsg = (P_MSG_SCN_SCAN_DONE) prMsgHdr; + P_P2P_SCAN_REQ_INFO_T prP2pScanReqInfo = (P_P2P_SCAN_REQ_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL) && (prP2pDevFsmInfo != NULL)); + + if (!prP2pDevFsmInfo) { + DBGLOG(P2P, ERROR, "prP2pDevFsmInfo is null, maybe remove p2p already\n"); + break; + } + + prP2pScanReqInfo = &(prP2pDevFsmInfo->rScanReqInfo); + + if (prScanDoneMsg->ucSeqNum != prP2pScanReqInfo->ucSeqNumOfScnMsg) { + DBGLOG(P2P, TRACE, + "P2P Scan Done SeqNum:%d <-> P2P Dev FSM Scan SeqNum:%d", + prScanDoneMsg->ucSeqNum, prP2pScanReqInfo->ucSeqNumOfScnMsg); + break; + } + + ASSERT_BREAK(prScanDoneMsg->ucBssIndex == prP2pDevFsmInfo->ucBssIndex); + + prP2pScanReqInfo->fgIsAbort = FALSE; + prP2pScanReqInfo->fgIsScanRequest = FALSE; + + p2pDevFsmStateTransition(prAdapter, prP2pDevFsmInfo, P2P_DEV_STATE_IDLE); + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventScanDone */ + +VOID p2pDevFsmRunEventChannelRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo = (P_P2P_DEV_FSM_INFO_T) NULL; + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; + BOOLEAN fgIsChnlFound = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + DBGLOG(P2P, STATE, "p2pDevFsmRunEventChannelRequest\n"); + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + if (prP2pDevFsmInfo == NULL) + break; + + prChnlReqInfo = &(prP2pDevFsmInfo->rChnlReqInfo); + + DBGLOG(P2P, TRACE, "p2pDevFsmRunEventChannelRequest\n"); + + /* printk("p2pDevFsmRunEventChannelRequest check cookie =%lld\n",prChnlReqInfo->u8Cookie); */ + + if (!LINK_IS_EMPTY(&prChnlReqInfo->rP2pChnlReqLink)) { + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; + P_MSG_P2P_CHNL_REQUEST_T prP2pMsgChnlReq = (P_MSG_P2P_CHNL_REQUEST_T) NULL; + + LINK_FOR_EACH(prLinkEntry, &prChnlReqInfo->rP2pChnlReqLink) { + prP2pMsgChnlReq = + (P_MSG_P2P_CHNL_REQUEST_T) LINK_ENTRY(prLinkEntry, MSG_HDR_T, rLinkEntry); + + if (prP2pMsgChnlReq->eChnlReqType == CH_REQ_TYPE_P2P_LISTEN) { + LINK_REMOVE_KNOWN_ENTRY(&prChnlReqInfo->rP2pChnlReqLink, prLinkEntry); + cnmMemFree(prAdapter, prP2pMsgChnlReq); + /* DBGLOG(P2P, TRACE, */ + /* ("p2pDevFsmRunEventChannelAbort: Channel Abort, cookie found:%d\n", */ + /* prChnlAbortMsg->u8Cookie)); */ + fgIsChnlFound = TRUE; + break; + } + } + } + + /* Queue the channel request. */ + LINK_INSERT_TAIL(&(prChnlReqInfo->rP2pChnlReqLink), &(prMsgHdr->rLinkEntry)); + prMsgHdr = NULL; + + /* If channel is not requested, it may due to channel is released. */ + if ((!fgIsChnlFound) && + (prChnlReqInfo->eChnlReqType == CH_REQ_TYPE_P2P_LISTEN) && (prChnlReqInfo->fgIsChannelRequested)) { + ASSERT((prP2pDevFsmInfo->eCurrentState == P2P_DEV_STATE_REQING_CHANNEL) || + (prP2pDevFsmInfo->eCurrentState == P2P_DEV_STATE_CHNL_ON_HAND)); + + p2pDevFsmRunEventAbort(prAdapter, prP2pDevFsmInfo); + + break; + } + + if (prP2pDevFsmInfo->eCurrentState == P2P_DEV_STATE_IDLE) { + /* Re-enter IDLE state would trigger channel request. */ + p2pDevFsmStateTransition(prAdapter, prP2pDevFsmInfo, P2P_DEV_STATE_IDLE); + } + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventChannelRequest */ + +VOID p2pDevFsmRunEventChannelAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo = (P_P2P_DEV_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; + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + if (prP2pDevFsmInfo == NULL) + break; + + prChnlReqInfo = &(prP2pDevFsmInfo->rChnlReqInfo); + + DBGLOG(P2P, TRACE, "p2pDevFsmRunEventChannelAbort\n"); + + /* If channel is not requested, it may due to channel is released. */ + if ((prChnlAbortMsg->u8Cookie == prChnlReqInfo->u8Cookie) && (prChnlReqInfo->fgIsChannelRequested)) { + ASSERT((prP2pDevFsmInfo->eCurrentState == P2P_DEV_STATE_REQING_CHANNEL) || + (prP2pDevFsmInfo->eCurrentState == P2P_DEV_STATE_CHNL_ON_HAND)); + + p2pDevFsmRunEventAbort(prAdapter, prP2pDevFsmInfo); + + break; + } else if (!LINK_IS_EMPTY(&prChnlReqInfo->rP2pChnlReqLink)) { + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; + P_MSG_P2P_CHNL_REQUEST_T prP2pMsgChnlReq = (P_MSG_P2P_CHNL_REQUEST_T) NULL; + + LINK_FOR_EACH(prLinkEntry, &prChnlReqInfo->rP2pChnlReqLink) { + prP2pMsgChnlReq = + (P_MSG_P2P_CHNL_REQUEST_T) LINK_ENTRY(prLinkEntry, MSG_HDR_T, rLinkEntry); + + if (prP2pMsgChnlReq->u8Cookie == prChnlAbortMsg->u8Cookie) { + LINK_REMOVE_KNOWN_ENTRY(&prChnlReqInfo->rP2pChnlReqLink, prLinkEntry); + cnmMemFree(prAdapter, prP2pMsgChnlReq); + DBGLOG(P2P, TRACE, + "p2pDevFsmRunEventChannelAbort: Channel Abort, cookie found:0x%llx\n", + prChnlAbortMsg->u8Cookie); + break; + } + } + } else { + DBGLOG(P2P, WARN, + "p2pDevFsmRunEventChannelAbort: Channel Abort Fail, cookie not found:0x%llx\n", + prChnlAbortMsg->u8Cookie); + } + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventChannelAbort */ + +VOID +p2pDevFsmRunEventChnlGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr, IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo) +{ + P_MSG_CH_GRANT_T prMsgChGrant = (P_MSG_CH_GRANT_T) NULL; + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; + + do { + ASSERT((prAdapter != NULL) && (prMsgHdr != NULL) && (prP2pDevFsmInfo != NULL)); + if ((prAdapter == NULL) || (prMsgHdr == NULL) || (prP2pDevFsmInfo == NULL)) + break; + + prMsgChGrant = (P_MSG_CH_GRANT_T) prMsgHdr; + prChnlReqInfo = &(prP2pDevFsmInfo->rChnlReqInfo); + + if ((prMsgChGrant->ucTokenID != prChnlReqInfo->ucSeqNumOfChReq) || + (!prChnlReqInfo->fgIsChannelRequested)) { + break; + } + + ASSERT(prMsgChGrant->ucPrimaryChannel == prChnlReqInfo->ucReqChnlNum); + ASSERT(prMsgChGrant->eReqType == prChnlReqInfo->eChnlReqType); + ASSERT(prMsgChGrant->u4GrantInterval == prChnlReqInfo->u4MaxInterval); + prChnlReqInfo->u4MaxInterval = prMsgChGrant->u4GrantInterval; + + if (prMsgChGrant->eReqType == CH_REQ_TYPE_P2P_LISTEN) { + p2pDevFsmStateTransition(prAdapter, prP2pDevFsmInfo, P2P_DEV_STATE_CHNL_ON_HAND); + } else { + ASSERT(prMsgChGrant->eReqType == CH_REQ_TYPE_OFFCHNL_TX); + p2pDevFsmStateTransition(prAdapter, prP2pDevFsmInfo, P2P_DEV_STATE_OFF_CHNL_TX); + } + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventChnlGrant */ + +VOID p2pDevFsmRunEventMgmtTx(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo = (P_P2P_DEV_FSM_INFO_T) NULL; + P_MSG_P2P_MGMT_TX_REQUEST_T prMgmtTxMsg = (P_MSG_P2P_MGMT_TX_REQUEST_T) NULL; + P_P2P_CHNL_REQ_INFO_T prP2pChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; + P_P2P_MGMT_TX_REQ_INFO_T prP2pMgmtTxReqInfo = (P_P2P_MGMT_TX_REQ_INFO_T) NULL; + + prMgmtTxMsg = (P_MSG_P2P_MGMT_TX_REQUEST_T) prMsgHdr; + + if ((prMgmtTxMsg->ucBssIdx != P2P_DEV_BSS_INDEX) && (IS_NET_ACTIVE(prAdapter, prMgmtTxMsg->ucBssIdx))) { + DBGLOG(P2P, TRACE, " Role Interface\n"); + p2pFuncTxMgmtFrame(prAdapter, + prMgmtTxMsg->ucBssIdx, + prMgmtTxMsg->prMgmtMsduInfo, prMgmtTxMsg->fgNoneCckRate); + goto error; + } + + DBGLOG(P2P, TRACE, " Device Interface\n"); + DBGLOG(P2P, STATE, "p2pDevFsmRunEventMgmtTx\n"); + + prMgmtTxMsg->ucBssIdx = P2P_DEV_BSS_INDEX; + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + if (prP2pDevFsmInfo == NULL) { + DBGLOG(P2P, ERROR, "prP2pDevFsmInfo is NULL!\n"); + goto error; + } + + prP2pChnlReqInfo = &(prP2pDevFsmInfo->rChnlReqInfo); + prP2pMgmtTxReqInfo = &(prP2pDevFsmInfo->rMgmtTxInfo); + + if ((!prMgmtTxMsg->fgIsOffChannel) || + ((prP2pDevFsmInfo->eCurrentState == P2P_DEV_STATE_OFF_CHNL_TX) && + (LINK_IS_EMPTY(&prP2pMgmtTxReqInfo->rP2pTxReqLink)))) { + p2pFuncTxMgmtFrame(prAdapter, + prP2pDevFsmInfo->ucBssIndex, + prMgmtTxMsg->prMgmtMsduInfo, prMgmtTxMsg->fgNoneCckRate); + } else { + P_P2P_OFF_CHNL_TX_REQ_INFO_T prOffChnlTxReq = (P_P2P_OFF_CHNL_TX_REQ_INFO_T) NULL; + + prOffChnlTxReq = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(P2P_OFF_CHNL_TX_REQ_INFO_T)); + + if (prOffChnlTxReq == NULL) { + DBGLOG(P2P, ERROR, "Can not serve TX request due to MSG buffer not enough\n"); + ASSERT(FALSE); + goto error; + } + + prOffChnlTxReq->prMgmtTxMsdu = prMgmtTxMsg->prMgmtMsduInfo; + prOffChnlTxReq->fgNoneCckRate = prMgmtTxMsg->fgNoneCckRate; + kalMemCopy(&prOffChnlTxReq->rChannelInfo, &prMgmtTxMsg->rChannelInfo, + sizeof(RF_CHANNEL_INFO_T)); + prOffChnlTxReq->eChnlExt = prMgmtTxMsg->eChnlExt; + prOffChnlTxReq->fgIsWaitRsp = prMgmtTxMsg->fgIsWaitRsp; + + LINK_INSERT_TAIL(&prP2pMgmtTxReqInfo->rP2pTxReqLink, &prOffChnlTxReq->rLinkEntry); + + /* Channel Request if needed. */ + if (prP2pDevFsmInfo->eCurrentState != P2P_DEV_STATE_OFF_CHNL_TX) { + P_MSG_P2P_CHNL_REQUEST_T prP2pMsgChnlReq = (P_MSG_P2P_CHNL_REQUEST_T) NULL; + + prP2pMsgChnlReq = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_CHNL_REQUEST_T)); + + if (prP2pMsgChnlReq == NULL) { + cnmMemFree(prAdapter, prOffChnlTxReq); + ASSERT(FALSE); + DBGLOG(P2P, ERROR, "Not enough MSG buffer for channel request\n"); + goto error; + } + + prP2pMsgChnlReq->eChnlReqType = CH_REQ_TYPE_OFFCHNL_TX; + + /* Not used in TX OFFCHNL REQ fields. */ + prP2pMsgChnlReq->rMsgHdr.eMsgId = MID_MNY_P2P_CHNL_REQ; + prP2pMsgChnlReq->u8Cookie = 0; + prP2pMsgChnlReq->u4Duration = P2P_OFF_CHNL_TX_DEFAULT_TIME_MS; + + kalMemCopy(&prP2pMsgChnlReq->rChannelInfo, + &prMgmtTxMsg->rChannelInfo, sizeof(RF_CHANNEL_INFO_T)); + prP2pMsgChnlReq->eChnlSco = prMgmtTxMsg->eChnlExt; + + p2pDevFsmRunEventChannelRequest(prAdapter, (P_MSG_HDR_T) prP2pMsgChnlReq); + } + } + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventMgmtTx */ + +WLAN_STATUS +p2pDevFsmRunEventMgmtFrameTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + BOOLEAN fgIsSuccess = FALSE; + P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo = (P_P2P_DEV_FSM_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + if (prP2pDevFsmInfo->eCurrentState == P2P_DEV_STATE_OFF_CHNL_TX) + p2pDevFsmStateTransition(prAdapter, prP2pDevFsmInfo, P2P_DEV_STATE_OFF_CHNL_TX); + + 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"); + } + + kalP2PIndicateMgmtTxStatus(prAdapter->prGlueInfo, prMsduInfo, fgIsSuccess); + } while (FALSE); + + return WLAN_STATUS_SUCCESS; +} /* p2pDevFsmRunEventMgmtFrameTxDone */ + +VOID p2pDevFsmRunEventMgmtFrameRegister(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + /* TODO: RX Filter Management. */ + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventMgmtFrameRegister */ + +VOID p2pDevFsmRunEventActiveDevBss(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo = (P_P2P_DEV_FSM_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + if (prP2pDevFsmInfo->eCurrentState == P2P_DEV_STATE_IDLE) { + /* Get into IDLE state to let BSS be active and do not Deactive. */ + p2pDevFsmStateTransition(prAdapter, prP2pDevFsmInfo, P2P_DEV_STATE_IDLE); + } + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventActiveDevBss */ + + +#endif /* RunEventWfdSettingUpdate */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_dev_state.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_dev_state.c new file mode 100644 index 0000000000000..b8d6aa19bdfed --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_dev_state.c @@ -0,0 +1,345 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#include "precomp.h" + +BOOLEAN +p2pDevStateInit_IDLE(IN P_ADAPTER_T prAdapter, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, OUT P_ENUM_P2P_DEV_STATE_T peNextState) +{ + BOOLEAN fgIsTransition = FALSE, fgIsShareInterface = TRUE; + UINT_32 u4Idx = 0; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo) && (peNextState != NULL)); + + if (!LINK_IS_EMPTY(&(prChnlReqInfo->rP2pChnlReqLink))) { + fgIsTransition = TRUE; + *peNextState = P2P_DEV_STATE_REQING_CHANNEL; + break; + } + + /* Check the interface shared by P2P_DEV and P2P_ROLE or not? */ + /* If not shared, we shall let BSSID4 alive to receive PROVISION REQUEST from GC */ + prGlueInfo = prAdapter->prGlueInfo; + if (prGlueInfo) { + for (u4Idx = 0; u4Idx < KAL_P2P_NUM; u4Idx++) { + if ((prGlueInfo->prP2PInfo[u4Idx] != NULL) && + (prGlueInfo->prP2PInfo[u4Idx]->aprRoleHandler != NULL) && + (prGlueInfo->prP2PInfo[u4Idx]->aprRoleHandler != + prGlueInfo->prP2PInfo[u4Idx]->prDevHandler)) { + fgIsShareInterface = FALSE; + break; + } + } + } + /************************* End *************************/ + + if (fgIsShareInterface) { + /* Stay in IDLE state. */ + UNSET_NET_ACTIVE(prAdapter, P2P_DEV_BSS_INDEX); + nicDeactivateNetwork(prAdapter, P2P_DEV_BSS_INDEX); + } + } while (FALSE); + + return fgIsTransition; +} /* p2pDevStateInit_IDLE */ + +VOID p2pDevStateAbort_IDLE(IN P_ADAPTER_T prAdapter) +{ + /* Currently Aobrt IDLE do nothing. */ +} /* p2pDevStateAbort_IDLE */ + +BOOLEAN +p2pDevStateInit_REQING_CHANNEL(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucBssIdx, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, OUT P_ENUM_P2P_DEV_STATE_T peNextState) +{ + BOOLEAN fgIsTransition = FALSE; + P_MSG_P2P_CHNL_REQUEST_T prP2pMsgChnlReq = (P_MSG_P2P_CHNL_REQUEST_T) NULL; + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; +#if CFG_SUPPORT_DBDC + CNM_DBDC_CAP_T rDbdcCap; +#endif /*CFG_SUPPORT_DBDC*/ + + do { + ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL) && (peNextState != NULL)); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + + if (LINK_IS_EMPTY(&(prChnlReqInfo->rP2pChnlReqLink))) { + /* NO Channel Request Pending. */ + DBGLOG(P2P, ERROR, "NO Pending Channel Request, but enter Req Channel State\n"); + fgIsTransition = TRUE; + *peNextState = P2P_DEV_STATE_IDLE; + break; + } + + LINK_REMOVE_HEAD(&(prChnlReqInfo->rP2pChnlReqLink), prP2pMsgChnlReq, P_MSG_P2P_CHNL_REQUEST_T); + + if (!prP2pMsgChnlReq) + break; + +#if (CFG_HW_WMM_BY_BSS == 1) + if (prBssInfo->fgIsWmmInited == FALSE) + prBssInfo->ucWmmQueSet = MAX_HW_WMM_INDEX; +#endif +#if CFG_SUPPORT_DBDC + cnmGetDbdcCapability(prAdapter, + prBssInfo->ucBssIndex, + prP2pMsgChnlReq->rChannelInfo.eBand, + prP2pMsgChnlReq->rChannelInfo.ucChannelNum, + wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex), + &rDbdcCap); + + prBssInfo->eDBDCBand = ENUM_BAND_AUTO; + prBssInfo->ucNss = rDbdcCap.ucNss; +#if (CFG_HW_WMM_BY_BSS == 0) + prBssInfo->ucWmmQueSet = rDbdcCap.ucWmmSetIndex; +#endif +#endif /*CFG_SUPPORT_DBDC*/ + prChnlReqInfo->u4MaxInterval = prP2pMsgChnlReq->u4Duration; + prChnlReqInfo->ucReqChnlNum = prP2pMsgChnlReq->rChannelInfo.ucChannelNum; + prChnlReqInfo->eChnlSco = prP2pMsgChnlReq->eChnlSco; + prChnlReqInfo->eBand = prP2pMsgChnlReq->rChannelInfo.eBand; + prChnlReqInfo->u8Cookie = prP2pMsgChnlReq->u8Cookie; + prChnlReqInfo->eChnlReqType = prP2pMsgChnlReq->eChnlReqType; + prChnlReqInfo->eChannelWidth = prBssInfo->ucVhtChannelWidth; + prChnlReqInfo->ucCenterFreqS1 = prBssInfo->ucVhtChannelFrequencyS1; + prChnlReqInfo->ucCenterFreqS2 = prBssInfo->ucVhtChannelFrequencyS2; + + p2pFuncAcquireCh(prAdapter, ucBssIdx, prChnlReqInfo); + } while (FALSE); + + if (prP2pMsgChnlReq) + cnmMemFree(prAdapter, prP2pMsgChnlReq); + + return fgIsTransition; +} /* p2pDevStateInit_REQING_CHANNEL */ + +VOID +p2pDevStateAbort_REQING_CHANNEL(IN P_ADAPTER_T prAdapter, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, IN ENUM_P2P_DEV_STATE_T eNextState) +{ + do { + ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL) && (eNextState < P2P_DEV_STATE_NUM)); + + switch (eNextState) { + case P2P_DEV_STATE_IDLE: + /* Channel abort case. */ + p2pFuncReleaseCh(prAdapter, P2P_DEV_BSS_INDEX, prChnlReqInfo); + break; + case P2P_DEV_STATE_CHNL_ON_HAND: + /* Channel on hand case. */ + break; + default: + /* Un-expected state transition. */ + DBGLOG(P2P, ERROR, "Unexpected State Transition(eNextState=%d)\n", eNextState); + ASSERT(FALSE); + break; + } + } while (FALSE); +} /* p2pDevStateAbort_REQING_CHANNEL */ + +VOID +p2pDevStateInit_CHNL_ON_HAND(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, + IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo) +{ + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pDevFsmInfo != NULL) && (prChnlReqInfo != NULL)); + + ASSERT(prChnlReqInfo->eChnlReqType == CH_REQ_TYPE_P2P_LISTEN); + + prChnlReqInfo->ucOriChnlNum = prP2pBssInfo->ucPrimaryChannel; + prChnlReqInfo->eOriBand = prP2pBssInfo->eBand; + prChnlReqInfo->eOriChnlSco = prP2pBssInfo->eBssSCO; + + prP2pBssInfo->ucPrimaryChannel = prChnlReqInfo->ucReqChnlNum; + prP2pBssInfo->eBand = prChnlReqInfo->eBand; + prP2pBssInfo->eBssSCO = prChnlReqInfo->eChnlSco; + + cnmTimerStartTimer(prAdapter, &(prP2pDevFsmInfo->rP2pFsmTimeoutTimer), prChnlReqInfo->u4MaxInterval); + + kalP2PIndicateChannelReady(prAdapter->prGlueInfo, + prChnlReqInfo->u8Cookie, + prChnlReqInfo->ucReqChnlNum, + prChnlReqInfo->eBand, prChnlReqInfo->eChnlSco, prChnlReqInfo->u4MaxInterval); + } while (FALSE); +} /* p2pDevStateInit_CHNL_ON_HAND */ + +VOID +p2pDevStateAbort_CHNL_ON_HAND(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, + IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo) +{ + do { + ASSERT_BREAK((prAdapter != NULL) || (prChnlReqInfo != NULL)); + + cnmTimerStopTimer(prAdapter, &(prP2pDevFsmInfo->rP2pFsmTimeoutTimer)); + + prP2pBssInfo->ucPrimaryChannel = prChnlReqInfo->ucOriChnlNum; + prP2pBssInfo->eBand = prChnlReqInfo->eOriBand; + prP2pBssInfo->eBssSCO = prChnlReqInfo->eOriChnlSco; + + kalP2PIndicateChannelExpired(prAdapter->prGlueInfo, + prChnlReqInfo->u8Cookie, + prChnlReqInfo->ucReqChnlNum, + prChnlReqInfo->eBand, prChnlReqInfo->eChnlSco); + + p2pFuncReleaseCh(prAdapter, prP2pDevFsmInfo->ucBssIndex, prChnlReqInfo); + } while (FALSE); +} /* p2pDevStateAbort_CHNL_ON_HAND */ + +VOID p2pDevStateInit_SCAN(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo) +{ + do { + ASSERT_BREAK((prAdapter != NULL) && (prScanReqInfo != NULL)); + + prScanReqInfo->fgIsScanRequest = TRUE; + + p2pFuncRequestScan(prAdapter, ucBssIndex, prScanReqInfo); + } while (FALSE); +} /* p2pDevStateInit_CHNL_ON_HAND */ + +VOID p2pDevStateAbort_SCAN(IN P_ADAPTER_T prAdapter, IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo) +{ + P_P2P_SCAN_REQ_INFO_T prScanInfo = (P_P2P_SCAN_REQ_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pDevFsmInfo != NULL)); + + prScanInfo = &(prP2pDevFsmInfo->rScanReqInfo); + + p2pFuncCancelScan(prAdapter, prP2pDevFsmInfo->ucBssIndex, prScanInfo); + + kalP2PIndicateScanDone(prAdapter->prGlueInfo, 0xFF, prScanInfo->fgIsAbort); + } while (FALSE); +} /* p2pDevStateAbort_CHNL_ON_HAND */ + +BOOLEAN +p2pDevStateInit_OFF_CHNL_TX(IN P_ADAPTER_T prAdapter, + IN P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, + IN P_P2P_MGMT_TX_REQ_INFO_T prP2pMgmtTxInfo, OUT P_ENUM_P2P_DEV_STATE_T peNextState) +{ + P_P2P_OFF_CHNL_TX_REQ_INFO_T prP2pOffChnlTxPkt = (P_P2P_OFF_CHNL_TX_REQ_INFO_T) NULL; + BOOLEAN fgIsTransition = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pMgmtTxInfo != NULL) + && (peNextState != NULL)); + + if (!LINK_IS_EMPTY(&(prP2pMgmtTxInfo->rP2pTxReqLink))) { + prP2pOffChnlTxPkt = + LINK_PEEK_HEAD(&(prP2pMgmtTxInfo->rP2pTxReqLink), P2P_OFF_CHNL_TX_REQ_INFO_T, rLinkEntry); + + if (prP2pOffChnlTxPkt == NULL) { + DBGLOG(P2P, ERROR, "Fetal Error, Link not empty but get NULL pointer.\n"); + ASSERT(FALSE); + break; + } + + if (prChnlReqInfo->ucReqChnlNum != prP2pOffChnlTxPkt->rChannelInfo.ucChannelNum) { + prChnlReqInfo->ucReqChnlNum = prP2pOffChnlTxPkt->rChannelInfo.ucChannelNum; + prChnlReqInfo->eChnlSco = prP2pOffChnlTxPkt->eChnlExt; + prChnlReqInfo->eBand = prP2pOffChnlTxPkt->rChannelInfo.eBand; + prChnlReqInfo->u8Cookie = 0; + prChnlReqInfo->eChannelWidth = CW_20_40MHZ; + prChnlReqInfo->ucCenterFreqS1 = 0; + prChnlReqInfo->ucCenterFreqS2 = 0; + ASSERT(prChnlReqInfo->eChnlReqType == CH_REQ_TYPE_OFFCHNL_TX); + + p2pFuncAcquireCh(prAdapter, prP2pDevFsmInfo->ucBssIndex, prChnlReqInfo); + } else { + LINK_REMOVE_HEAD(&(prP2pMgmtTxInfo->rP2pTxReqLink), + prP2pOffChnlTxPkt, P_P2P_OFF_CHNL_TX_REQ_INFO_T); + + p2pFuncTxMgmtFrame(prAdapter, + prP2pDevFsmInfo->ucBssIndex, + prP2pOffChnlTxPkt->prMgmtTxMsdu, prP2pOffChnlTxPkt->fgNoneCckRate); + + prP2pMgmtTxInfo->prMgmtTxMsdu = prP2pOffChnlTxPkt->prMgmtTxMsdu; + prP2pMgmtTxInfo->fgIsWaitRsp = prP2pOffChnlTxPkt->fgIsWaitRsp; + } + } else { + /* Link is empty, return back to IDLE. */ + *peNextState = P2P_DEV_STATE_IDLE; + fgIsTransition = TRUE; + } + } while (FALSE); + + return fgIsTransition; +} /* p2pDevSateInit_OFF_CHNL_TX */ + +VOID +p2pDevStateAbort_OFF_CHNL_TX(IN P_ADAPTER_T prAdapter, + IN P_P2P_MGMT_TX_REQ_INFO_T prP2pMgmtTxInfo, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, IN ENUM_P2P_DEV_STATE_T eNextState) +{ + P_P2P_OFF_CHNL_TX_REQ_INFO_T prP2pOffChnlTxPkt = (P_P2P_OFF_CHNL_TX_REQ_INFO_T) NULL; + + if (eNextState != P2P_DEV_STATE_OFF_CHNL_TX) { + while (!LINK_IS_EMPTY(&(prP2pMgmtTxInfo->rP2pTxReqLink))) { + LINK_REMOVE_HEAD(&(prP2pMgmtTxInfo->rP2pTxReqLink), + prP2pOffChnlTxPkt, P_P2P_OFF_CHNL_TX_REQ_INFO_T); + + if (prP2pOffChnlTxPkt) + kalP2PIndicateMgmtTxStatus(prAdapter->prGlueInfo, + prP2pOffChnlTxPkt->prMgmtTxMsdu, FALSE); + else + DBGLOG(P2P, INFO, "No packet for indicating Tx status!\n"); + } + + p2pFuncReleaseCh(prAdapter, P2P_DEV_BSS_INDEX, prChnlReqInfo); + } +} /* p2pDevSateAbort_OFF_CHNL_TX */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_fsm.c new file mode 100644 index 0000000000000..4d25d72856971 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_fsm.c @@ -0,0 +1,327 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. + */ + + +/******************************************************************************* + * C O M P I L E 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 + ******************************************************************************** + */ + +/******************************************************************************* + * M A 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 p2pFsmRunEventScanRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_P2P_SCAN_REQUEST_T prP2pScanReqMsg = (P_MSG_P2P_SCAN_REQUEST_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + if ((prAdapter == NULL) || (prMsgHdr == NULL)) + break; + + prP2pScanReqMsg = (P_MSG_P2P_SCAN_REQUEST_T) prMsgHdr; + + if (prP2pScanReqMsg->ucBssIdx == P2P_DEV_BSS_INDEX) + p2pDevFsmRunEventScanRequest(prAdapter, prMsgHdr); + else + p2pRoleFsmRunEventScanRequest(prAdapter, prMsgHdr); + + prMsgHdr = NULL; + /* Both p2pDevFsmRunEventScanRequest and p2pRoleFsmRunEventScanRequest + * free prMsgHdr before return, so prMsgHdr is needed to be NULL. + */ + } while (FALSE); + + if (prMsgHdr != NULL) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventScanRequest */ + +/*----------------------------------------------------------------------------*/ +/*! + * \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_MSG_CH_GRANT_T prMsgChGrant = (P_MSG_CH_GRANT_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prMsgChGrant = (P_MSG_CH_GRANT_T) prMsgHdr; + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsgChGrant->ucBssIndex); + + DBGLOG(P2P, TRACE, "P2P Run Event Channel Grant\n"); + +#if CFG_SUPPORT_DBDC + if (prP2pBssInfo->eDBDCBand == ENUM_BAND_AUTO) + prP2pBssInfo->eDBDCBand = prMsgChGrant->eDBDCBand; +#endif + +#if CFG_SISO_SW_DEVELOP + /* Driver record granted CH in BSS info */ + prP2pBssInfo->fgIsGranted = TRUE; + prP2pBssInfo->eBandGranted = prMsgChGrant->eRfBand; + prP2pBssInfo->ucPrimaryChannelGranted = prMsgChGrant->ucPrimaryChannel; +#endif + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_P2P_DEVICE: + ASSERT(prP2pBssInfo->ucBssIndex == P2P_DEV_BSS_INDEX); + p2pDevFsmRunEventChnlGrant(prAdapter, prMsgHdr, prAdapter->rWifiVar.prP2pDevFsmInfo); + break; + case OP_MODE_INFRASTRUCTURE: + case OP_MODE_ACCESS_POINT: + ASSERT(prP2pBssInfo->ucBssIndex < P2P_DEV_BSS_INDEX); + p2pRoleFsmRunEventChnlGrant(prAdapter, prMsgHdr, + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData)); + break; + default: + ASSERT(FALSE); + break; + } + } while (FALSE); +} /* p2pFsmRunEventChGrant */ + +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; + + 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); + } + + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pFsmRunEventNetDeviceRegister */ + +VOID p2pFsmRunEventUpdateMgmtFrame(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_P2P_MGMT_FRAME_UPDATE_T prP2pMgmtFrameUpdateMsg = (P_MSG_P2P_MGMT_FRAME_UPDATE_T) NULL; + + DBGLOG(P2P, TRACE, "p2pFsmRunEventUpdateMgmtFrame\n"); + + 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; + } + + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pFsmRunEventUpdateMgmtFrame */ + +#if CFG_SUPPORT_WFD +VOID p2pFsmRunEventWfdSettingUpdate(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T prMsgWfdCfgSettings = (P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T) NULL; + UINT_32 i; + + /* WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; */ + + 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.rWfdConfigureSettings; + } + + DBGLOG(P2P, INFO, "WFD Enalbe %x info %x state %x flag %x adv %x\n", + prWfdCfgSettings->ucWfdEnable, + prWfdCfgSettings->u2WfdDevInfo, + (UINT_32) prWfdCfgSettings->u4WfdState, + (UINT_32) prWfdCfgSettings->u4WfdFlag, (UINT_32) prWfdCfgSettings->u4WfdAdvancedFlag); + + if (prWfdCfgSettings->ucWfdEnable == 0) + for (i = 0; i < KAL_P2P_NUM; i++) { + if (prAdapter->prGlueInfo->prP2PInfo[i]) + prAdapter->prGlueInfo->prP2PInfo[i]->u2WFDIELen = 0; + } + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} + +/* p2pFsmRunEventWfdSettingUpdate */ + +#endif /* CFG_SUPPORT_WFD */ + + +/*----------------------------------------------------------------------------*/ +/*! + * \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_MSG_SCN_SCAN_DONE prScanDoneMsg = (P_MSG_SCN_SCAN_DONE) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + prScanDoneMsg = (P_MSG_SCN_SCAN_DONE) prMsgHdr; + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prScanDoneMsg->ucBssIndex); + + if (prAdapter->fgIsP2PRegistered == FALSE) { + DBGLOG(P2P, TRACE, "P2P BSS Info is removed, break p2pFsmRunEventScanDone\n"); + + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + DBGLOG(P2P, TRACE, "P2P Scan Done Event\n"); + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_P2P_DEVICE: + ASSERT(prP2pBssInfo->ucBssIndex == P2P_DEV_BSS_INDEX); + p2pDevFsmRunEventScanDone(prAdapter, prMsgHdr, prAdapter->rWifiVar.prP2pDevFsmInfo); + break; + case OP_MODE_INFRASTRUCTURE: + case OP_MODE_ACCESS_POINT: + ASSERT(prP2pBssInfo->ucBssIndex < P2P_DEV_BSS_INDEX); + p2pRoleFsmRunEventScanDone(prAdapter, prMsgHdr, + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData)); + break; + default: + ASSERT(FALSE); + break; + } +} /* p2pFsmRunEventScanDone */ + + + +#endif /* CFG_ENABLE_WIFI_DIRECT */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_func.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_func.c new file mode 100644 index 0000000000000..158ebaf72c049 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_func.c @@ -0,0 +1,4364 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#include "precomp.h" + +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_SW - 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 */ +#if CFG_SUPPORT_802_11AC + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP), NULL, rlmRspGenerateVhtCapIE} /*191 */ + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP), NULL, rlmRspGenerateVhtOpIE} /*192 */ + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP_MODE_NOTIFICATION), NULL, rlmRspGenerateVhtOpNotificationIE} /*199 */ +#endif +#if CFG_SUPPORT_MTK_SYNERGY + , {(ELEM_HDR_LEN + ELEM_MIN_LEN_MTK_OUI), NULL, rlmGenerateMTKOuiIE} /* 221 */ +#endif + +}; + +#if (CFG_SUPPORT_DFS_MASTER == 1) +BOOLEAN g_fgManualCac = FALSE; +UINT_32 g_u4DriverCacTime; +UINT_32 g_u4CacStartBootTime; +UINT_8 g_ucRadarDetectMode = FALSE; +struct P2P_RADAR_INFO g_rP2pRadarInfo; +UINT_8 g_ucDfsState = DFS_STATE_INACTIVE; +static PUINT_8 apucDfsState[DFS_STATE_NUM] = { + (PUINT_8) DISP_STRING("DFS_STATE_INACTIVE"), + (PUINT_8) DISP_STRING("DFS_STATE_CHECKING"), + (PUINT_8) DISP_STRING("DFS_STATE_ACTIVE"), + (PUINT_8) DISP_STRING("DFS_STATE_DETECTED") +}; + +PUINT_8 apucW53RadarType[3] = { + (PUINT_8) DISP_STRING("Unknown Type"), + (PUINT_8) DISP_STRING("Type 1 (short pulse)"), + (PUINT_8) DISP_STRING("Type 2 (short pulse)") +}; +PUINT_8 apucW56RadarType[12] = { + (PUINT_8) DISP_STRING("Unknown Type"), + (PUINT_8) DISP_STRING("Type 1 (short pulse)"), + (PUINT_8) DISP_STRING("Type 2 (short pulse)"), + (PUINT_8) DISP_STRING("Type 3 (short pulse)"), + (PUINT_8) DISP_STRING("Type 4 (short pulse)"), + (PUINT_8) DISP_STRING("Type 5 (short pulse)"), + (PUINT_8) DISP_STRING("Type 6 (short pulse)"), + (PUINT_8) DISP_STRING("Type 7 (long pulse)"), + (PUINT_8) DISP_STRING("Type 8 (short pulse)"), + (PUINT_8) DISP_STRING("Type 4 or Type 5 or Type 6 (short pulse)"), + (PUINT_8) DISP_STRING("Type 5 or Type 6 or Type 8 (short pulse)"), + (PUINT_8) DISP_STRING("Type 5 or Type 6 (short pulse)") +}; +#endif + +static VOID +p2pFuncParseBeaconVenderId(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucIE, + IN P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo, IN UINT_8 ucRoleIndex); +#if 0 +static VOID +p2pFuncGetAttriListAction(IN P_ADAPTER_T prAdapter, + IN P_IE_P2P_T prIe, IN UINT_8 ucOuiType, + OUT PUINT_8 *pucAttriListStart, OUT UINT_16 *u2AttriListLen, + OUT BOOLEAN *fgIsAllocMem, OUT BOOLEAN *fgBackupAttributes, OUT UINT_16 *u2BufferSize); +#endif + +static VOID +p2pFuncProcessP2pProbeRspAction(IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucIEBuf, IN UINT_8 ucElemIdType, + OUT UINT_8 *ucBssIdx, OUT P_BSS_INFO_T *prP2pBssInfo, OUT BOOLEAN *fgIsWSCIE, + OUT BOOLEAN *fgIsP2PIE, OUT BOOLEAN *fgIsWFDIE); +static VOID +p2pFuncGetSpecAttriAction(IN P_IE_P2P_T prP2pIE, + IN UINT_8 ucOuiType, IN UINT_8 ucAttriID, OUT P_ATTRIBUTE_HDR_T *prTargetAttri); +/*----------------------------------------------------------------------------*/ +/*! +* @brief Function for requesting scan. There is an option to do ACTIVE or PASSIVE scan. +* +* @param eScanType - Specify the scan type of the scan request. It can be an ACTIVE/PASSIVE +* Scan. +* eChannelSet - Specify the preferred channel set. +* A FULL scan would request a legacy full channel normal scan.(usually ACTIVE). +* A P2P_SOCIAL scan would scan 1+6+11 channels.(usually ACTIVE) +* A SPECIFIC scan would only 1/6/11 channels scan. (Passive Listen/Specific Search) +* ucChannelNum - A specific channel number. (Only when channel is specified) +* eBand - A specific band. (Only when channel is specified) +* +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFuncRequestScan(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo) +{ + P_MSG_SCN_SCAN_REQ_V2 prScanReqV2 = (P_MSG_SCN_SCAN_REQ_V2) NULL; + +#ifdef CFG_SUPPORT_BEAM_PLUS + /*NFC Beam + Indication */ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; +#endif + + 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); + } + + prScanReqV2 = + (P_MSG_SCN_SCAN_REQ_V2) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + (sizeof(MSG_SCN_SCAN_REQ_V2) + + (sizeof(PARAM_SSID_T) * prScanReqInfo->ucSsidNum))); + if (!prScanReqV2) { + ASSERT(0); /* Can't trigger SCAN FSM */ + DBGLOG(P2P, ERROR, + "p2pFuncRequestScan: Memory allocation fail, can not send SCAN MSG to scan module\n"); + break; + } + + prScanReqV2->rMsgHdr.eMsgId = MID_P2P_SCN_SCAN_REQ_V2; + prScanReqV2->ucSeqNum = ++prScanReqInfo->ucSeqNumOfScnMsg; + prScanReqV2->ucBssIndex = ucBssIndex; + prScanReqV2->eScanType = prScanReqInfo->eScanType; + prScanReqV2->eScanChannel = prScanReqInfo->eChannelSet; + prScanReqV2->u2IELen = 0; + prScanReqV2->prSsid = (P_PARAM_SSID_T) ((ULONG) prScanReqV2 + sizeof(MSG_SCN_SCAN_REQ_V2)); + + /* Copy IE for Probe Request. */ + kalMemCopy(prScanReqV2->aucIE, prScanReqInfo->aucIEBuf, prScanReqInfo->u4BufLength); + prScanReqV2->u2IELen = (UINT_16) prScanReqInfo->u4BufLength; + + prScanReqV2->u2ChannelDwellTime = prScanReqInfo->u2PassiveDewellTime; + prScanReqV2->u2TimeoutValue = 0; + prScanReqV2->u2ProbeDelay = 0; + + 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++) { + prScanReqV2->arChnlInfoList[u4Idx].ucChannelNum = prDomainInfo->ucChannelNum; + prScanReqV2->arChnlInfoList[u4Idx].eBand = prDomainInfo->eBand; + prDomainInfo++; + } + + prScanReqV2->ucChannelListNum = prScanReqInfo->ucNumChannelList; + } + /* fallthrough */ + case SCAN_CHANNEL_FULL: + /* fallthrough */ + case SCAN_CHANNEL_2G4: + /* fallthrough */ + case SCAN_CHANNEL_P2P_SOCIAL: + { + /* UINT_8 aucP2pSsid[] = P2P_WILDCARD_SSID; */ + P_PARAM_SSID_T prParamSsid = (P_PARAM_SSID_T) NULL; + + prParamSsid = prScanReqV2->prSsid; + + for (prScanReqV2->ucSSIDNum = 0; + prScanReqV2->ucSSIDNum < prScanReqInfo->ucSsidNum; prScanReqV2->ucSSIDNum++) { + COPY_SSID(prParamSsid->aucSsid, + prParamSsid->u4SsidLen, + prScanReqInfo->arSsidStruct[prScanReqV2->ucSSIDNum].aucSsid, + prScanReqInfo->arSsidStruct[prScanReqV2->ucSSIDNum].ucSsidLen); + + prParamSsid++; + } + + /* For compatible. (in FW?) need to check. */ + if (prScanReqV2->ucSSIDNum == 0) + prScanReqV2->ucSSIDType = SCAN_REQ_SSID_P2P_WILDCARD; + else + prScanReqV2->ucSSIDType = SCAN_REQ_SSID_SPECIFIED; + } + break; + default: + /* Currently there is no other scan channel set. */ + ASSERT(FALSE); + break; + } + + prScanReqInfo->fgIsScanRequest = TRUE; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanReqV2, MSG_SEND_METHOD_BUF); + + } while (FALSE); +} /* p2pFuncRequestScan */ + +VOID p2pFuncCancelScan(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, 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->ucBssIndex = ucBssIndex; + prScanCancelMsg->ucSeqNum = prScanInfo->ucSeqNumOfScnMsg++; + prScanCancelMsg->fgIsChannelExt = FALSE; + prScanInfo->fgIsScanRequest = FALSE; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanCancelMsg, MSG_SEND_METHOD_BUF); + + } + + } while (FALSE); +} /* p2pFuncCancelScan */ + +VOID p2pFuncGCJoin(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo, IN P_P2P_JOIN_INFO_T prP2pJoinInfo) +{ + P_MSG_JOIN_REQ_T prJoinReqMsg = (P_MSG_JOIN_REQ_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL) && (prP2pJoinInfo != NULL)); + + prBssDesc = prP2pJoinInfo->prTargetBssDesc; + if ((prBssDesc) == NULL) { + DBGLOG(P2P, ERROR, "p2pFuncGCJoin: NO Target BSS Descriptor\n"); + ASSERT(FALSE); + break; + } + + if (prBssDesc->ucSSIDLen) { + COPY_SSID(prP2pBssInfo->aucSSID, + prP2pBssInfo->ucSSIDLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + } + + /* 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)), + prP2pBssInfo->ucBssIndex, prBssDesc); + + if (prStaRec == NULL) { + DBGLOG(P2P, TRACE, "Create station record fail\n"); + ASSERT(FALSE); + break; + } + + prP2pJoinInfo->prTargetStaRec = prStaRec; + prP2pJoinInfo->fgIsJoinComplete = FALSE; + prP2pJoinInfo->u4BufLength = 0; + + /* 2 <2.1> Sync. to FW domain */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + if (prP2pBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { + prStaRec->fgIsReAssoc = FALSE; + prP2pJoinInfo->ucAvailableAuthTypes = (UINT_8) AUTH_TYPE_OPEN_SYSTEM; + prStaRec->ucTxAuthAssocRetryLimit = TX_AUTH_ASSOCI_RETRY_LIMIT; + } else { + DBGLOG(P2P, ERROR, "JOIN INIT: Join Request when connected.\n"); + /* TODO: Shall we considering ROAMIN case for P2P Device?. */ + break; + } + + /* 2 <4> Use an appropriate Authentication Algorithm Number among the ucAvailableAuthTypes. */ + if (prP2pJoinInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_OPEN_SYSTEM) { + + DBGLOG(P2P, TRACE, "JOIN INIT: Try to do Authentication with AuthType == OPEN_SYSTEM.\n"); + + prP2pJoinInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_OPEN_SYSTEM; + + prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_OPEN_SYSTEM; + } else { + DBGLOG(P2P, ERROR, "JOIN INIT: ucAvailableAuthTypes Error.\n"); + ASSERT(FALSE); + break; + } + + /* 4 <5> Overwrite Connection Setting for eConnectionPolicy == ANY (Used by Assoc Req) */ + + /* 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 = ++prP2pJoinInfo->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); + +} /* p2pFuncGCJoin */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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_BSS_INFO_T prP2pBssInfo, IN P_SW_RFB_T prAssocRspSwRfb) +{ + P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) NULL; + UINT_16 u2IELength; + PUINT_8 pucIE; + + DEBUGFUNC("p2pUpdateBssInfoForJOIN()"); + + do { + ASSERT_BREAK((prAdapter != NULL) && + (prStaRec != NULL) && (prP2pBssInfo != NULL) && (prAssocRspSwRfb != NULL)); + + prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) prAssocRspSwRfb->pvHeader; + + if (prBssDesc == NULL) { + /* Target BSS NULL. */ + DBGLOG(P2P, TRACE, "Target BSS NULL\n"); + break; + } + + 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 */ + ASSERT_BREAK(prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE); + + if (UNEQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAssocRspFrame->aucBSSID)) + ASSERT(FALSE); + /* 4 <1.2> Setup SSID */ + COPY_SSID(prP2pBssInfo->aucSSID, prP2pBssInfo->ucSSIDLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + + /* 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; + + nicTxUpdateBssDefaultRate(prP2pBssInfo); + + /* 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 */ + + 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, prP2pBssInfo->ucBssIndex); + + /* 4 <4.4> *DEFER OPERATION* nicPmIndicateBssConnected() will be invoked */ + /* inside scanProcessBeaconAndProbeResp() after 1st beacon is received */ + + } while (FALSE); +} /* end of p2pUpdateBssInfoForJOIN() */ + +WLAN_STATUS +p2pFunMgmtFrameTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + BOOLEAN fgIsSuccess = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + 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"); + } + + kalP2PIndicateMgmtTxStatus(prAdapter->prGlueInfo, prMsduInfo, fgIsSuccess); + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; + +} /* p2pFunMgmtFrameTxDone */ + +WLAN_STATUS +p2pFuncTxMgmtFrame(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucBssIndex, IN P_MSDU_INFO_T prMgmtTxMsdu, IN BOOLEAN fgNonCckRate) +{ + 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; + UINT_8 ucRetryLimit = 30; /* TX_DESC_TX_COUNT_NO_LIMIT; */ + BOOLEAN fgDrop = FALSE; + P_BSS_INFO_T prBssInfo; + + do { + ASSERT_BREAK(prAdapter != NULL); + + /* Drop this frame if BSS inactive */ + if (!IS_NET_ACTIVE(prAdapter, ucBssIndex)) { + p2pDevFsmRunEventMgmtFrameTxDone(prAdapter, prMgmtTxMsdu, TX_RESULT_DROPPED_IN_DRIVER); + cnmMgtPktFree(prAdapter, prMgmtTxMsdu); + fgDrop = TRUE; + + break; + } + + prWlanHdr = (P_WLAN_MAC_HEADER_T) ((ULONG) prMgmtTxMsdu->prPacket + MAC_TX_RESERVED_FIELD); + prStaRec = cnmGetStaRecByAddress(prAdapter, ucBssIndex, prWlanHdr->aucAddr1); + /* prMgmtTxMsdu->ucBssIndex = ucBssIndex; */ + + switch (prWlanHdr->u2FrameCtrl & MASK_FRAME_TYPE) { + case MAC_FRAME_PROBE_RSP: + DBGLOG(P2P, TRACE, "TX Probe Resposne Frame\n"); + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + if ((!nicTxIsMgmtResourceEnough(prAdapter)) || (prBssInfo->fgIsNetAbsent)) { + DBGLOG(P2P, TRACE, "Drop Tx probe response due to resource issue\n"); + fgDrop = TRUE; + + break; + } + prMgmtTxMsdu->ucStaRecIndex = + (prStaRec != NULL) ? (prStaRec->ucIndex) : (STA_REC_INDEX_NOT_FOUND); + /* Modifiy Lie time to 100 mS due to the STA only wait 30-50mS */ + /* and AP do not need send it after STA left */ + nicTxSetPktLifeTime(prMgmtTxMsdu, 100); + prMgmtTxMsdu = p2pFuncProcessP2pProbeRsp(prAdapter, ucBssIndex, prMgmtTxMsdu); + ucRetryLimit = 6; + break; + default: + prMgmtTxMsdu->ucBssIndex = ucBssIndex; + break; + } + + if (fgDrop) { + /* Drop this frame */ + p2pDevFsmRunEventMgmtFrameTxDone(prAdapter, prMgmtTxMsdu, TX_RESULT_DROPPED_IN_DRIVER); + cnmMgtPktFree(prAdapter, prMgmtTxMsdu); + + break; + } + + TX_SET_MMPDU(prAdapter, + prMgmtTxMsdu, + prMgmtTxMsdu->ucBssIndex, + (prStaRec != NULL) ? (prStaRec->ucIndex) : (STA_REC_INDEX_NOT_FOUND), + WLAN_MAC_MGMT_HEADER_LEN, + prMgmtTxMsdu->u2FrameLength, p2pDevFsmRunEventMgmtFrameTxDone, MSDU_RATE_MODE_AUTO); + + nicTxSetPktRetryLimit(prMgmtTxMsdu, ucRetryLimit); + + nicTxConfigPktControlFlag(prMgmtTxMsdu, MSDU_CONTROL_FLAG_FORCE_TX, TRUE); + + nicTxEnqueueMsdu(prAdapter, prMgmtTxMsdu); + + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncTxMgmtFrame */ + +VOID p2pFuncStopComplete(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo) +{ + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); + + DBGLOG(P2P, TRACE, "p2pFuncStopComplete\n"); + + /* GO: It would stop Beacon TX. GC: Stop all BSS related PS function. */ + nicPmIndicateBssAbort(prAdapter, prP2pBssInfo->ucBssIndex); + /* Reset RLM related field of BSSINFO. */ + rlmBssAborted(prAdapter, prP2pBssInfo); + + UNSET_NET_ACTIVE(prAdapter, prP2pBssInfo->ucBssIndex); + nicDeactivateNetwork(prAdapter, prP2pBssInfo->ucBssIndex); + /* Release CNM channel */ + nicUpdateBss(prAdapter, prP2pBssInfo->ucBssIndex); + + /* Reset current OPMode */ + /* 20170628, remove reset opmode, otherwise we cannot free P2P beacon buffer */ + /* prP2pBssInfo->eCurrentOPMode = OP_MODE_INFRASTRUCTURE; */ + + /* Point StaRecOfAP to NULL when GC role stop Complete */ + prP2pBssInfo->prStaRecOfAP = NULL; + } while (FALSE); + +} /* p2pFuncStopComplete */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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 P_P2P_CONNECTION_REQ_INFO_T prP2pConnReqInfo, IN P_P2P_CHNL_REQ_INFO_T prP2pChnlReqInfo) +{ +#if (CFG_SUPPORT_DFS_MASTER == 1) + P_CMD_RDD_ON_OFF_CTRL_T prCmdRddOnOffCtrl; +#endif + +#ifdef CFG_SUPPORT_P2P_OPEN_SECURITY + BOOLEAN fgIsOpenP2P = TRUE; +#else + BOOLEAN fgIsOpenP2P = FALSE; +#endif + +#ifdef CFG_SUPPORT_P2P_GO_11B_RATE + BOOLEAN fgIs11bRate = TRUE; +#else + BOOLEAN fgIs11bRate = FALSE; +#endif + + do { + ASSERT_BREAK((prAdapter != NULL) && (prBssInfo != NULL)); + + if (prBssInfo->ucBssIndex >= MAX_BSS_INDEX) { + DBGLOG(P2P, ERROR, "P2P BSS exceed the number of P2P interface number."); + ASSERT(FALSE); + break; + } + + DBGLOG(P2P, TRACE, "p2pFuncStartGO:\n"); + +#if (CFG_SUPPORT_DFS_MASTER == 1) + prCmdRddOnOffCtrl = (P_CMD_RDD_ON_OFF_CTRL_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(*prCmdRddOnOffCtrl)); + + if (prCmdRddOnOffCtrl == NULL) { + DBGLOG(P2P, ERROR, "Allocate memory for prCmdRddOnOffCtrl failed."); + return; + } + + prCmdRddOnOffCtrl->ucDfsCtrl = RDD_START_TXQ; + prCmdRddOnOffCtrl->ucRddIdx = prAdapter-> + aprBssInfo[prBssInfo->ucBssIndex]->eDBDCBand; + + DBGLOG(P2P, INFO, "p2pFuncStartGO: Start TXQ - DFS ctrl: %.d\n", prCmdRddOnOffCtrl->ucDfsCtrl); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_RDD_ON_OFF_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(*prCmdRddOnOffCtrl), (PUINT_8) prCmdRddOnOffCtrl, NULL, 0); + + cnmMemFree(prAdapter, prCmdRddOnOffCtrl); +#endif + + /* Re-start AP mode. */ + p2pFuncSwitchOPMode(prAdapter, prBssInfo, prBssInfo->eIntendOPMode, FALSE); + + prBssInfo->eIntendOPMode = OP_MODE_NUM; + + /* 4 <1.1> Assign SSID */ + COPY_SSID(prBssInfo->aucSSID, + prBssInfo->ucSSIDLen, + prP2pConnReqInfo->rSsidStruct.aucSsid, prP2pConnReqInfo->rSsidStruct.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 = prP2pChnlReqInfo->ucReqChnlNum; + prBssInfo->eBand = prP2pChnlReqInfo->eBand; + prBssInfo->eBssSCO = prP2pChnlReqInfo->eChnlSco; + + DBGLOG(P2P, TRACE, "GO Channel:%d\n", prBssInfo->ucPrimaryChannel); + + if (prBssInfo->eBand == BAND_5G) { + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AN); + prBssInfo->ucConfigAdHocAPMode = AP_MODE_11A; /* Depend on eCurrentOPMode and ucPhyTypeSet */ + } else if ((prP2pConnReqInfo->eConnRequest == P2P_CONNECTION_TYPE_PURE_AP) || + fgIs11bRate) { + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11BGN); + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; + } else { + ASSERT(prP2pConnReqInfo->eConnRequest == P2P_CONNECTION_TYPE_GO); + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11GN); + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_11G_P2P; + } + + /* Overwrite BSS PHY type set by Feature Options */ + bssDetermineApBssInfoPhyTypeSet(prAdapter, + (prP2pConnReqInfo->eConnRequest == + P2P_CONNECTION_TYPE_PURE_AP) ? TRUE : FALSE, prBssInfo); + + prBssInfo->ucNonHTBasicPhyType = (UINT_8) + rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].ePhyTypeIndex; + prBssInfo->u2BSSBasicRateSet = rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].u2BSSBasicRateSet; + prBssInfo->u2OperationalRateSet = + rNonHTPhyAttributes[prBssInfo->ucNonHTBasicPhyType].u2SupportedRateSet; + + if ((prBssInfo->ucAllSupportedRatesLen == 0) || fgIs11bRate) { + 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 + prBssInfo->fgIsProtection = FALSE; + /* Always enable protection at P2P GO But OOBE AP */ + if ((prP2pConnReqInfo->eConnRequest == P2P_CONNECTION_TYPE_GO) && (!fgIsOpenP2P)) { + prBssInfo->fgIsProtection = TRUE; + } else { + if (!fgIsOpenP2P) + ASSERT(prP2pConnReqInfo->eConnRequest == P2P_CONNECTION_TYPE_PURE_AP); + if (kalP2PGetCipher(prAdapter->prGlueInfo, (UINT_8) prBssInfo->u4PrivateData)) + prBssInfo->fgIsProtection = TRUE; + } + + bssInitForAP(prAdapter, prBssInfo, TRUE); + +#if 0 + if (prBssInfo->ucBMCWlanIndex >= WTBL_SIZE) { + prBssInfo->ucBMCWlanIndex = + secPrivacySeekForBcEntry(prAdapter, prBssInfo->ucBssIndex, + prBssInfo->aucBSSID, 0xff, CIPHER_SUITE_NONE, 0xff); + } +#endif + nicQmUpdateWmmParms(prAdapter, prBssInfo->ucBssIndex); +#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, prBssInfo->ucBssIndex); + + /* 4 <3.3> Update Beacon again for network phy type confirmed. */ + bssUpdateBeaconContent(prAdapter, prBssInfo->ucBssIndex); + + /* 4 <3.4> Setup BSSID */ + nicPmIndicateBssCreated(prAdapter, prBssInfo->ucBssIndex); + + } while (FALSE); +} /* p2pFuncStartGO() */ + +VOID p2pFuncStopGO(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo) +{ + UINT_32 u4ClientCount = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); + + DBGLOG(P2P, TRACE, "p2pFuncStopGO\n"); + + u4ClientCount = bssGetClientCount(prAdapter, prP2pBssInfo); + + if ((prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) + && (prP2pBssInfo->eIntendOPMode == OP_MODE_NUM)) { + /* AP is created, Beacon Updated. */ + p2pFuncDissolve(prAdapter, prP2pBssInfo, TRUE, REASON_CODE_DEAUTH_LEAVING_BSS); + prP2pBssInfo->eIntendOPMode = OP_MODE_P2P_DEVICE; + } + + /* Do not Deactivate Network if any Client existed, we'll deactive it after Deauth Tx done */ + if (u4ClientCount == 0) { + DBGLOG(P2P, INFO, "No client! Deactive GO immediately.\n"); + p2pChangeMediaState(prAdapter, prP2pBssInfo, PARAM_MEDIA_STATE_DISCONNECTED); + p2pFuncStopComplete(prAdapter, prP2pBssInfo); + } + + } while (FALSE); + +} /* p2pFuncStopGO */ + +WLAN_STATUS p2pFuncRoleToBssIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucRoleIdx, OUT PUINT_8 pucBssIdx) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBssIdx != NULL)); + + if (ucRoleIdx >= BSS_P2P_NUM) { + rWlanStatus = WLAN_STATUS_FAILURE; + break; + } + if (!prAdapter->rWifiVar.aprP2pRoleFsmInfo[ucRoleIdx]) { + DBGLOG(P2P, WARN, "%s, invalid aprP2pRoleFsmInfo, ignore\n", __func__); + rWlanStatus = WLAN_STATUS_FAILURE; + } else + *pucBssIdx = prAdapter->rWifiVar.aprP2pRoleFsmInfo[ucRoleIdx]->ucBssIndex; + + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncRoleToBssIdx */ + +P_P2P_ROLE_FSM_INFO_T p2pFuncGetRoleByBssIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex) +{ + INT_32 i = 0; + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T)NULL; + + do { + ASSERT_BREAK((prAdapter != NULL)); + + for (i = 0 ; i < BSS_P2P_NUM; i++) { + if (!prAdapter->rWifiVar.aprP2pRoleFsmInfo[i]) + continue; + + if (prAdapter->rWifiVar.aprP2pRoleFsmInfo[i]->ucBssIndex == ucBssIndex) + break; + } + if (i < BSS_P2P_NUM) + prP2pRoleFsmInfo = prAdapter->rWifiVar.aprP2pRoleFsmInfo[i]; + + } while (FALSE); + + return prP2pRoleFsmInfo; +} + +/* ///////////////////////////////// MT6630 CODE END //////////////////////////////////////////////// */ + +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 will be done in p2pFuncStopGO(). */ + /* p2pFuncDissolve(prAdapter, prP2pBssInfo, TRUE, REASON_CODE_DEAUTH_LEAVING_BSS); */ + if (prP2pBssInfo->eIntendOPMode != OP_MODE_P2P_DEVICE) { + p2pFuncStopGO(prAdapter, prP2pBssInfo); + + SET_NET_PWR_STATE_IDLE(prAdapter, prP2pBssInfo->ucBssIndex); + } + break; + default: + break; + } + + prP2pBssInfo->eIntendOPMode = eOpMode; + + /* The state is in disconnecting and can not change any BSS status */ + if (IS_NET_PWR_STATE_IDLE(prAdapter, prP2pBssInfo->ucBssIndex) && + IS_NET_ACTIVE(prAdapter, prP2pBssInfo->ucBssIndex)) { + DBGLOG(P2P, TRACE, "under deauth procedure, Quit.\n"); + break; + } + + prP2pBssInfo->eCurrentOPMode = eOpMode; + switch (eOpMode) { + case OP_MODE_INFRASTRUCTURE: + DBGLOG(P2P, TRACE, "p2pFuncSwitchOPMode: Switch to Client.\n"); + /* fall through */ + case OP_MODE_ACCESS_POINT: + /* Change interface address. */ + if (eOpMode == OP_MODE_ACCESS_POINT) { + DBGLOG(P2P, TRACE, "p2pFuncSwitchOPMode: Switch to AP.\n"); + prP2pBssInfo->ucSSIDLen = 0; + } + +#if CFG_DUAL_P2PLIKE_INTERFACE + /*avoid ap1 Bss have diff A2 & A3, */ + /*ToDo : fix for P2P case*/ + +#else + COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, prAdapter->rWifiVar.aucInterfaceAddress); + COPY_MAC_ADDR(prP2pBssInfo->aucBSSID, prAdapter->rWifiVar.aucInterfaceAddress); +#endif + break; + case OP_MODE_P2P_DEVICE: + { + /* Change device address. */ + DBGLOG(P2P, TRACE, "p2pFuncSwitchOPMode: Switch back to P2P Device.\n"); + + p2pChangeMediaState(prAdapter, prP2pBssInfo, PARAM_MEDIA_STATE_DISCONNECTED); + + COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, + prAdapter->rWifiVar.aucDeviceAddress); + COPY_MAC_ADDR(prP2pBssInfo->aucBSSID, prAdapter->rWifiVar.aucDeviceAddress); + + } + break; + default: + 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, prP2pBssInfo->ucBssIndex); + } + + } while (FALSE); +} /* p2pFuncSwitchOPMode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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 UINT_8 ucBssIdx, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo) +{ + P_MSG_CH_ABORT_T prMsgChRelease = (P_MSG_CH_ABORT_T) NULL; + + DEBUGFUNC("p2pFuncReleaseCh()"); + + do { + ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL)); + + if (!prChnlReqInfo->fgIsChannelRequested) + break; + DBGLOG(P2P, TRACE, "P2P Release Channel\n"); + prChnlReqInfo->fgIsChannelRequested = FALSE; + + /* 1. return channel privilege to CNM immediately */ + prMsgChRelease = (P_MSG_CH_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_ABORT_T)); + if (!prMsgChRelease) { + ASSERT(0); /* Can't release Channel to CNM */ + break; + } + + prMsgChRelease->rMsgHdr.eMsgId = MID_MNY_CNM_CH_ABORT; + prMsgChRelease->ucBssIndex = ucBssIdx; + prMsgChRelease->ucTokenID = prChnlReqInfo->ucSeqNumOfChReq++; +#if CFG_SUPPORT_DBDC + prMsgChRelease->eDBDCBand = ENUM_BAND_AUTO; + + DBGLOG(P2P, INFO, + "p2pFuncReleaseCh: P2P abort channel on band %u.\n", + prMsgChRelease->eDBDCBand); +#endif /*CFG_SUPPORT_DBDC*/ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChRelease, MSG_SEND_METHOD_BUF); + + } while (FALSE); +} /* p2pFuncReleaseCh */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process of CHANNEL_REQ_JOIN Initial. Enter CHANNEL_REQ_JOIN State. +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFuncAcquireCh(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, 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, ucBssIdx, 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->ucBssIndex = ucBssIdx; + prMsgChReq->ucTokenID = ++prChnlReqInfo->ucSeqNumOfChReq; + prMsgChReq->eReqType = prChnlReqInfo->eChnlReqType; + prMsgChReq->u4MaxInterval = prChnlReqInfo->u4MaxInterval; + prMsgChReq->ucPrimaryChannel = prChnlReqInfo->ucReqChnlNum; + prMsgChReq->eRfSco = prChnlReqInfo->eChnlSco; + prMsgChReq->eRfBand = prChnlReqInfo->eBand; + prMsgChReq->eRfChannelWidth = prChnlReqInfo->eChannelWidth; + prMsgChReq->ucRfCenterFreqSeg1 = prChnlReqInfo->ucCenterFreqS1; + prMsgChReq->ucRfCenterFreqSeg2 = prChnlReqInfo->ucCenterFreqS2; +#if CFG_SUPPORT_DBDC + prMsgChReq->eDBDCBand = ENUM_BAND_AUTO; + + DBGLOG(P2P, INFO, + "p2pFuncAcquireCh: P2P Request channel on band %u.\n", + prMsgChReq->eDBDCBand); +#endif /*CFG_SUPPORT_DBDC*/ + /* Channel request join BSSID. */ + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChReq, MSG_SEND_METHOD_BUF); + + prChnlReqInfo->fgIsChannelRequested = TRUE; + + } while (FALSE); +} /* p2pFuncAcquireCh */ + +#if (CFG_SUPPORT_DFS_MASTER == 1) +VOID p2pFuncStartRdd(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx) +{ + P_CMD_RDD_ON_OFF_CTRL_T prCmdRddOnOffCtrl; + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + UINT_8 ucReqChnlNum; + + DEBUGFUNC("p2pFuncStartRdd()"); + + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prAdapter->aprBssInfo[ucBssIdx]->u4PrivateData); + + ucReqChnlNum = prP2pRoleFsmInfo->rChnlReqInfo.ucReqChnlNum; + + prCmdRddOnOffCtrl = (P_CMD_RDD_ON_OFF_CTRL_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(*prCmdRddOnOffCtrl)); + + if (!prCmdRddOnOffCtrl) { + DBGLOG(P2P, ERROR, "cnmMemAlloc for prCmdRddOnOffCtrl failed!\n"); + return; + } + + prCmdRddOnOffCtrl->ucDfsCtrl = RDD_START; + + prCmdRddOnOffCtrl->ucRddIdx = prAdapter->aprBssInfo[ucBssIdx]->eDBDCBand; + + if (rlmDomainGetDfsRegion() == NL80211_DFS_JP) { + if (ucReqChnlNum >= 52 && ucReqChnlNum <= 64) + prCmdRddOnOffCtrl->ucRegDomain = REG_JP_53; + else if (ucReqChnlNum >= 100 && ucReqChnlNum <= 140) + prCmdRddOnOffCtrl->ucRegDomain = REG_JP_56; + } else { + prCmdRddOnOffCtrl->ucRegDomain = REG_DEFAULT; + } + + if (prCmdRddOnOffCtrl->ucRddIdx) + prCmdRddOnOffCtrl->ucRddInSel = RDD_IN_SEL_1; + else + prCmdRddOnOffCtrl->ucRddInSel = RDD_IN_SEL_0; + + DBGLOG(P2P, INFO, "p2pFuncStartRdd: Start Radar detection - DFS ctrl: %d, RDD index: %d\n", + prCmdRddOnOffCtrl->ucDfsCtrl, prCmdRddOnOffCtrl->ucRddIdx); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_RDD_ON_OFF_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(*prCmdRddOnOffCtrl), (PUINT_8) prCmdRddOnOffCtrl, NULL, 0); + + cnmMemFree(prAdapter, prCmdRddOnOffCtrl); +} /* p2pFuncStartRdd */ + +VOID p2pFuncStopRdd(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx) +{ + P_CMD_RDD_ON_OFF_CTRL_T prCmdRddOnOffCtrl; + + DEBUGFUNC("p2pFuncStopRdd()"); + + prCmdRddOnOffCtrl = (P_CMD_RDD_ON_OFF_CTRL_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(*prCmdRddOnOffCtrl)); + + if (!prCmdRddOnOffCtrl) { + DBGLOG(P2P, ERROR, "cnmMemAlloc for prCmdRddOnOffCtrl failed!\n"); + return; + } + + prCmdRddOnOffCtrl->ucDfsCtrl = RDD_STOP; + + prCmdRddOnOffCtrl->ucRddIdx = prAdapter->aprBssInfo[ucBssIdx]->eDBDCBand; + + if (prCmdRddOnOffCtrl->ucRddIdx) + prCmdRddOnOffCtrl->ucRddInSel = RDD_IN_SEL_1; + else + prCmdRddOnOffCtrl->ucRddInSel = RDD_IN_SEL_0; + + DBGLOG(P2P, INFO, "p2pFuncStopRdd: Stop Radar detection - DFS ctrl: %d, RDD index: %d\n", + prCmdRddOnOffCtrl->ucDfsCtrl, prCmdRddOnOffCtrl->ucRddIdx); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_RDD_ON_OFF_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(*prCmdRddOnOffCtrl), (PUINT_8) prCmdRddOnOffCtrl, NULL, 0); + + cnmMemFree(prAdapter, prCmdRddOnOffCtrl); + +} /* p2pFuncStopRdd */ + +VOID p2pFuncDfsSwitchCh(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P2P_CHNL_REQ_INFO_T rP2pChnlReqInfo) +{ + + P_GLUE_INFO_T prGlueInfo; + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + P_CMD_RDD_ON_OFF_CTRL_T prCmdRddOnOffCtrl; + UINT_8 role_idx; + + DEBUGFUNC("p2pFuncDfsSwitchCh()"); + + if (!prBssInfo) { + DBGLOG(P2P, ERROR, "prBssInfo shouldn't be NULL!\n"); + return; + } + + /* Setup Channel, Band */ + prBssInfo->ucPrimaryChannel = rP2pChnlReqInfo.ucReqChnlNum; + prBssInfo->eBand = rP2pChnlReqInfo.eBand; + prBssInfo->eBssSCO = rP2pChnlReqInfo.eChnlSco; + + /* Setup channel and bandwidth */ + rlmBssInitForAPandIbss(prAdapter, prBssInfo); + + /* Update Beacon again for network phy type confirmed. */ + bssUpdateBeaconContent(prAdapter, prBssInfo->ucBssIndex); + + /* Reset HW TSF Update Mode and Beacon Mode */ + nicUpdateBss(prAdapter, prBssInfo->ucBssIndex); + + prCmdRddOnOffCtrl = (P_CMD_RDD_ON_OFF_CTRL_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(*prCmdRddOnOffCtrl)); + + if (!prCmdRddOnOffCtrl) { + DBGLOG(P2P, ERROR, "cnmMemAlloc for prCmdRddOnOffCtrl failed!\n"); + return; + } + + prCmdRddOnOffCtrl->ucDfsCtrl = RDD_START_TXQ; + prCmdRddOnOffCtrl->ucRddIdx = prAdapter-> + aprBssInfo[prBssInfo->ucBssIndex]->eDBDCBand; + + DBGLOG(P2P, INFO, "p2pFuncDfsSwitchCh: Start TXQ - DFS ctrl: %.d\n", prCmdRddOnOffCtrl->ucDfsCtrl); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_RDD_ON_OFF_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(*prCmdRddOnOffCtrl), (PUINT_8) prCmdRddOnOffCtrl, NULL, 0); + + cnmMemFree(prAdapter, prCmdRddOnOffCtrl); + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, prBssInfo->u4PrivateData); + + prGlueInfo = prAdapter->prGlueInfo; + + DBGLOG(P2P, INFO, "p2pFuncDfsSwitchCh: Update to OS\n"); + + role_idx = prP2pRoleFsmInfo->ucRoleIndex; + /* NL80211 event should send to p2p group netdevice. + * Otherwise wpa_supplicant wouldn't perform beacon update. + * Hostapd case: prDevHandler same with aprRoleHandler + * P2P GO case: p2p0=>prDevHandler, p2p-xxx-x=> aprRoleHandler + */ + cfg80211_ch_switch_notify( + prGlueInfo->prP2PInfo[role_idx]->aprRoleHandler, + prGlueInfo->prP2PInfo[role_idx]->chandef); + DBGLOG(P2P, INFO, "p2pFuncDfsSwitchCh: Update to OS Done\n"); + +} /* p2pFuncDfsSwitchCh */ + +BOOLEAN p2pFuncCheckWeatherRadarBand(IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo) +{ + UINT_8 ucReqChnlNum; + UINT_8 ucCenterFreqS1; + ENUM_CHANNEL_WIDTH_T eChannelWidth; + ENUM_CHNL_EXT_T eChnlSco; + + + ucReqChnlNum = prChnlReqInfo->ucReqChnlNum; + ucCenterFreqS1 = prChnlReqInfo->ucCenterFreqS1; + eChannelWidth = prChnlReqInfo->eChannelWidth; + eChnlSco = prChnlReqInfo->eChnlSco; + + if (rlmDomainGetDfsRegion() == NL80211_DFS_ETSI) { + if (eChannelWidth == VHT_OP_CHANNEL_WIDTH_80) { + if (ucCenterFreqS1 >= 120 && ucCenterFreqS1 <= 128) + return TRUE; + } else { + if ((ucReqChnlNum >= 120 && ucReqChnlNum <= 128)) + return TRUE; + else if (ucReqChnlNum == 116 && eChnlSco == CHNL_EXT_SCA) /* ch116, 120 BW40 */ + return TRUE; + } + } + + return FALSE; +} + +INT_32 p2pFuncSetDriverCacTime(IN UINT_32 u4CacTime) +{ + WLAN_STATUS i4Status = WLAN_STATUS_SUCCESS; + + g_u4DriverCacTime = u4CacTime; + + DBGLOG(P2P, INFO, "p2pFuncSetDriverCacTime: g_u4ManualCacTime = %dsec\n", g_u4DriverCacTime); + + return i4Status; +} + +VOID p2pFuncEnableManualCac(VOID) +{ + g_fgManualCac = TRUE; +} + +UINT_32 p2pFuncGetDriverCacTime(VOID) +{ + return g_u4DriverCacTime; +} + +BOOLEAN p2pFuncIsManualCac(VOID) +{ + return g_fgManualCac; +} + +VOID p2pFuncRadarInfoInit(VOID) +{ + kalMemZero(&g_rP2pRadarInfo, sizeof(g_rP2pRadarInfo)); +} + +VOID p2pFuncShowRadarInfo(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx) +{ + UINT_8 ucCnt = 0; + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + UINT_8 ucReqChnlNum; + + if (g_rP2pRadarInfo.ucRadarReportMode == 1) { + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prAdapter->aprBssInfo[ucBssIdx]->u4PrivateData); + + ucReqChnlNum = prP2pRoleFsmInfo->rChnlReqInfo.ucReqChnlNum; + + DBGLOG(P2P, INFO, "-----Radar Detected Event-----\n"); + DBGLOG(P2P, INFO, "Radar detected in DBDC band%d\n", g_rP2pRadarInfo.ucRddIdx); + + switch (rlmDomainGetDfsRegion()) { + case NL80211_DFS_FCC: + DBGLOG(P2P, INFO, "Regulation domain: FCC\n"); + break; + case NL80211_DFS_ETSI: + DBGLOG(P2P, INFO, "Regulation domain: ETSI\n"); + break; + case NL80211_DFS_JP: + DBGLOG(P2P, INFO, "Regulation domain: JP\n"); + + if (ucReqChnlNum >= 52 && ucReqChnlNum <= 64) + DBGLOG(P2P, INFO, "Radar type: W53 - %s\n", p2pFuncJpW53RadarType()); + else if (ucReqChnlNum >= 100 && ucReqChnlNum <= 140) + DBGLOG(P2P, INFO, "Radar type: W56 - %s\n", p2pFuncJpW56RadarType()); + break; + default: + break; + } + + DBGLOG(P2P, INFO, "Radar Content:\n"); + + DBGLOG(P2P, INFO, "start time pulse width PRI\n"); + + if (g_rP2pRadarInfo.ucPeriodicDetected) { + DBGLOG(P2P, INFO, "%-10d %-11d -\n" + , g_rP2pRadarInfo.arPpbContent[ucCnt].u4PeriodicStartTime + , g_rP2pRadarInfo.arPpbContent[ucCnt].u2PeriodicPulseWidth); + + for (ucCnt = 1; ucCnt < g_rP2pRadarInfo.ucPPBNum; ucCnt++) { + DBGLOG(P2P, INFO, "%-10d %-11d %d\n" + , g_rP2pRadarInfo.arPpbContent[ucCnt].u4PeriodicStartTime + , g_rP2pRadarInfo.arPpbContent[ucCnt].u2PeriodicPulseWidth + , (g_rP2pRadarInfo.arPpbContent[ucCnt].u4PeriodicStartTime + - g_rP2pRadarInfo.arPpbContent[ucCnt-1].u4PeriodicStartTime) * 2 / 5); + } + } else if (g_rP2pRadarInfo.ucLongDetected) { + DBGLOG(P2P, INFO, "%-10d %-11d -\n" + , g_rP2pRadarInfo.arLpbContent[ucCnt].u4LongStartTime + , g_rP2pRadarInfo.arLpbContent[ucCnt].u2LongPulseWidth); + + for (ucCnt = 1; ucCnt < g_rP2pRadarInfo.ucLPBNum; ucCnt++) { + DBGLOG(P2P, INFO, "%-10d %-11d %d\n" + , g_rP2pRadarInfo.arLpbContent[ucCnt].u4LongStartTime + , g_rP2pRadarInfo.arLpbContent[ucCnt].u2LongPulseWidth + , (g_rP2pRadarInfo.arLpbContent[ucCnt].u4LongStartTime + - g_rP2pRadarInfo.arLpbContent[ucCnt-1].u4LongStartTime) * 2 / 5); + } + } + } +} + +VOID p2pFuncGetRadarInfo(IN struct P2P_RADAR_INFO *prP2pRadarInfo) +{ + kalMemCopy(prP2pRadarInfo, &g_rP2pRadarInfo, sizeof(*prP2pRadarInfo)); +} + +PUINT_8 p2pFuncJpW53RadarType(VOID) +{ + UINT_32 u4Type1Diff; + UINT_32 u4Type2Diff; + + if (g_rP2pRadarInfo.u4PRI1stUs >= 1428) + u4Type1Diff = g_rP2pRadarInfo.u4PRI1stUs - 1428; + else + u4Type1Diff = 1428 - g_rP2pRadarInfo.u4PRI1stUs; + + if (g_rP2pRadarInfo.u4PRI1stUs >= 3846) + u4Type2Diff = g_rP2pRadarInfo.u4PRI1stUs - 3846; + else + u4Type2Diff = 3846 - g_rP2pRadarInfo.u4PRI1stUs; + + if (u4Type1Diff < u4Type2Diff) + return apucW53RadarType[1]; + else + return apucW53RadarType[2]; +} + +PUINT_8 p2pFuncJpW56RadarType(VOID) +{ + UINT_32 u4Type1Diff; + UINT_32 u4Type2Diff; + + if (g_rP2pRadarInfo.ucLongDetected) + return apucW56RadarType[7]; + + if (g_rP2pRadarInfo.u4PRI1stUs >= 3980 && g_rP2pRadarInfo.u4PRI1stUs <= 4020) + return apucW56RadarType[3]; + + if (g_rP2pRadarInfo.u4PRI1stUs >= 1368 && g_rP2pRadarInfo.u4PRI1stUs <= 1448) { + + if (g_rP2pRadarInfo.u4PRI1stUs >= 1388) + u4Type1Diff = g_rP2pRadarInfo.u4PRI1stUs - 1388; + else + u4Type1Diff = 1388 - g_rP2pRadarInfo.u4PRI1stUs; + + if (g_rP2pRadarInfo.u4PRI1stUs >= 1428) + u4Type2Diff = g_rP2pRadarInfo.u4PRI1stUs - 1428; + else + u4Type2Diff = 1428 - g_rP2pRadarInfo.u4PRI1stUs; + + if (u4Type1Diff < u4Type2Diff) + return apucW56RadarType[1]; + else + return apucW56RadarType[2]; + + } + + if (g_rP2pRadarInfo.u4PRI1stUs >= 130 && g_rP2pRadarInfo.u4PRI1stUs < 200) + return apucW56RadarType[4]; + + if (g_rP2pRadarInfo.u4PRI1stUs >= 200 && g_rP2pRadarInfo.u4PRI1stUs <= 520) { + + if (g_rP2pRadarInfo.u4PRI1stUs <= 230) + return apucW56RadarType[9]; + + if (g_rP2pRadarInfo.u4PRI1stUs >= 323 && g_rP2pRadarInfo.u4PRI1stUs <= 343) + return apucW56RadarType[10]; + + return apucW56RadarType[11]; + } + + return apucW56RadarType[0]; +} + +VOID p2pFuncSetRadarDetectMode(IN UINT_8 ucRadarDetectMode) +{ + g_ucRadarDetectMode = ucRadarDetectMode; + + DBGLOG(P2P, INFO, "p2pFuncSetRadarDetectMode: g_ucRadarDetectMode: %d\n", g_ucRadarDetectMode); +} + +UINT_8 p2pFuncGetRadarDetectMode(VOID) +{ + return g_ucRadarDetectMode; +} + +VOID p2pFuncSetDfsState(IN UINT_8 ucDfsState) +{ + DBGLOG(P2P, INFO, "[DFS_STATE] TRANSITION: [%s] -> [%s]\n", + apucDfsState[g_ucDfsState], apucDfsState[ucDfsState]); + + g_ucDfsState = ucDfsState; +} + +UINT_8 p2pFuncGetDfsState(VOID) +{ + return g_ucDfsState; +} + +PUINT_8 p2pFuncShowDfsState(VOID) +{ + return apucDfsState[g_ucDfsState]; +} + +VOID p2pFuncRecordCacStartBootTime(VOID) +{ + g_u4CacStartBootTime = kalGetBootTime(); +} + +UINT_32 p2pFuncGetCacRemainingTime(VOID) +{ + UINT_32 u4CurrentBootTime; + UINT_32 u4CacRemainingTime; + + u4CurrentBootTime = kalGetBootTime(); + + u4CacRemainingTime = g_u4DriverCacTime - (u4CurrentBootTime - g_u4CacStartBootTime)/1000000; + + return u4CacRemainingTime; +} +#endif + +#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) ((ULONG) 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) ((ULONG) prBcnUpdateInfo->pucBcnHdr + (ULONG) prBcnUpdateInfo->u4BcnHdrLen); + kalMemCopy(pucIEBuf, aucIEBuf, u4NewBodyLen); + prBcnUpdateInfo->pucBcnBody = pucIEBuf; + + /* Frame Length */ + prBcnMsduInfo->u2FrameLength = (UINT_16) (prBcnUpdateInfo->u4BcnHdrLen + prBcnUpdateInfo->u4BcnBodyLen); + + prBcnMsduInfo->ucPacketType = TX_PACKET_TYPE_MGMT; + prBcnMsduInfo->fgIs802_11 = TRUE; + prBcnMsduInfo->ucBssIndex = prP2pBssInfo->ucBssIndex; + + /* 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 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is to update extra IEs (ex: WPS) for assoc resp. +* Caller should sanity check the params. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[in] prP2pBssInfo Pointer to BSS_INFO_T structure +* \param[in] AssocRespIE Pointer to extra IEs for assoc resp +* \param[in] u4AssocRespLen Length of extra IEs for assoc resp +* +* \return WLAN_STATUS +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS +p2pFuncAssocRespUpdate(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, + IN PUINT_8 AssocRespIE, IN UINT_32 u4AssocRespLen) +{ + UINT_8 ucOuiType = 0; + UINT_16 u2SubTypeVersion = 0; + + if (!rsnParseCheckForWFAInfoElem(prAdapter, AssocRespIE, &ucOuiType, &u2SubTypeVersion)) + return WLAN_STATUS_FAILURE; + + if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + kalP2PUpdateWSC_IE(prAdapter->prGlueInfo, 3, (PUINT_8)AssocRespIE, IE_SIZE(AssocRespIE), + (UINT_8) (prP2pBssInfo->u4PrivateData)); + } + + return WLAN_STATUS_SUCCESS; +} + +#endif + +#if 0 +/* 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); */ + + } + + rWlanStatus = WLAN_STATUS_SUCCESS; + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncDisassoc */ + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @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) +{ + P_STA_RECORD_T prCurrStaRec, prStaRecNext; + P_LINK_T prClientList; + + DEBUGFUNC("p2pFuncDissolve()"); + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_INFRASTRUCTURE: + /* Reset station record status. */ + if (prP2pBssInfo->prStaRecOfAP) { +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + (UINT_8) prP2pBssInfo->u4PrivateData, NULL, NULL, 0, + REASON_CODE_DEAUTH_LEAVING_BSS, + WLAN_STATUS_MEDIA_DISCONNECT); +#else + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + (UINT_8) prP2pBssInfo->u4PrivateData, NULL, NULL, 0, + REASON_CODE_DEAUTH_LEAVING_BSS); +#endif + + /* 2012/02/14 frog: After formation before join group, prStaRecOfAP is NULL. */ + p2pFuncDisconnect(prAdapter, + prP2pBssInfo, prP2pBssInfo->prStaRecOfAP, fgSendDeauth, u2ReasonCode); + } + + /* Fix possible KE when RX Beacon & call nicPmIndicateBssConnected(). + * hit prStaRecOfAP == NULL. + */ + p2pChangeMediaState(prAdapter, prP2pBssInfo, 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. + */ + /* Send deauth. */ + authSendDeauthFrame(prAdapter, + prP2pBssInfo, + NULL, (P_SW_RFB_T) NULL, u2ReasonCode, (PFN_TX_DONE_HANDLER) NULL); + + prClientList = &prP2pBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH_ENTRY_SAFE(prCurrStaRec, prStaRecNext, + prClientList, rLinkEntry, STA_RECORD_T) { + ASSERT(prCurrStaRec); + p2pFuncDisconnect(prAdapter, prP2pBssInfo, prCurrStaRec, TRUE, u2ReasonCode); + } + break; + default: + return; /* 20110420 -- alreay in Device Mode. */ + } + + /* Make the deauth frame send to FW ASAP. */ +#if !CFG_SUPPORT_MULTITHREAD + wlanAcquirePowerControl(prAdapter); +#endif + wlanProcessCommandQueue(prAdapter, &prAdapter->prGlueInfo->rCmdQueue); +#if !CFG_SUPPORT_MULTITHREAD + wlanReleasePowerControl(prAdapter); +#endif + + /*kalMdelay(100);*/ + + /* Change Connection Status. *//* 20161025, can not set DISCONNECTED if clientcount > 0 */ + /*p2pChangeMediaState(prAdapter, prP2pBssInfo, PARAM_MEDIA_STATE_DISCONNECTED);*/ + + } while (FALSE); +} /* p2pFuncDissolve */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to dissolve from group or one group. (Would not change P2P FSM.) +* 1. GC: Disconnect from AP. (Send Deauth) +* 2. GO: Disconnect all STA +* +* @param[in] prAdapter Pointer to the adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFuncDisconnect(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, + IN P_STA_RECORD_T prStaRec, IN BOOLEAN fgSendDeauth, IN UINT_16 u2ReasonCode) +{ + ENUM_PARAM_MEDIA_STATE_T eOriMediaStatus; + + DBGLOG(P2P, INFO, "p2pFuncDisconnect()"); + + do { + ASSERT_BREAK((prAdapter != NULL) && (prStaRec != NULL) && (prP2pBssInfo != NULL)); + + ASSERT_BREAK(prP2pBssInfo->eNetworkType == NETWORK_TYPE_P2P); + + ASSERT_BREAK(prP2pBssInfo->ucBssIndex < P2P_DEV_BSS_INDEX); + + eOriMediaStatus = prP2pBssInfo->eConnectionState; + + /* Indicate disconnect. */ + if (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, prP2pBssInfo->u4PrivateData); + + kalP2PGOStationUpdate(prAdapter->prGlueInfo, prP2pRoleFsmInfo->ucRoleIndex, prStaRec, FALSE); + } else { + scanRemoveConnFlagOfBssDescByBssid(prAdapter, prP2pBssInfo->aucBSSID); + } + + if (fgSendDeauth) { + /* Send deauth. */ + authSendDeauthFrame(prAdapter, + prP2pBssInfo, + prStaRec, + (P_SW_RFB_T) NULL, + u2ReasonCode, (PFN_TX_DONE_HANDLER) p2pRoleFsmRunEventDeauthTxDone); + + /* Make the deauth frame send to FW ASAP. */ +#if !CFG_SUPPORT_MULTITHREAD + wlanAcquirePowerControl(prAdapter); +#endif + wlanProcessCommandQueue(prAdapter, &prAdapter->prGlueInfo->rCmdQueue); +#if !CFG_SUPPORT_MULTITHREAD + wlanReleasePowerControl(prAdapter); +#endif + } else { + /* Change station state. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + /* Reset Station Record Status. */ + p2pFuncResetStaRecStatus(prAdapter, prStaRec); + + cnmStaRecFree(prAdapter, prStaRec); + + if ((prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) || + (bssGetClientCount(prAdapter, prP2pBssInfo) == 0)) { + DBGLOG(P2P, TRACE, "No More Client, Media Status DISCONNECTED\n"); + p2pChangeMediaState(prAdapter, prP2pBssInfo, PARAM_MEDIA_STATE_DISCONNECTED); + } + + if (eOriMediaStatus != prP2pBssInfo->eConnectionState) { + /* Update Disconnected state to FW. */ + nicUpdateBss(prAdapter, prP2pBssInfo->ucBssIndex); + } + + } + } while (FALSE); + + return; + +} /* p2pFuncDisconnect */ + +VOID p2pFuncSetChannel(IN P_ADAPTER_T prAdapter, IN UINT_8 ucRoleIdx, IN P_RF_CHANNEL_INFO_T prRfChannelInfo) +{ + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + P_P2P_CONNECTION_REQ_INFO_T prP2pConnReqInfo = (P_P2P_CONNECTION_REQ_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prRfChannelInfo != NULL)); + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, ucRoleIdx); + if (!prP2pRoleFsmInfo) + break; + prP2pConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + + prP2pConnReqInfo->rChannelInfo.ucChannelNum = prRfChannelInfo->ucChannelNum; + prP2pConnReqInfo->rChannelInfo.eBand = prRfChannelInfo->eBand; + prP2pConnReqInfo->eChnlBw = prRfChannelInfo->ucChnlBw; + prP2pConnReqInfo->u2PriChnlFreq = prRfChannelInfo->u2PriChnlFreq; + prP2pConnReqInfo->u4CenterFreq1 = prRfChannelInfo->u4CenterFreq1; + prP2pConnReqInfo->u4CenterFreq2 = prRfChannelInfo->u4CenterFreq2; + + } while (FALSE); +} /* p2pFuncSetChannel */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Retry JOIN for AUTH_MODE_AUTO_SWITCH +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @retval TRUE We will retry JOIN +* @retval FALSE We will not retry JOIN +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2pFuncRetryJOIN(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_P2P_JOIN_INFO_T prJoinInfo) +{ + P_MSG_JOIN_REQ_T prJoinReqMsg = (P_MSG_JOIN_REQ_T) NULL; + BOOLEAN fgRetValue = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prStaRec != NULL) && (prJoinInfo != NULL)); + + /* Retry other AuthType if possible */ + if (!prJoinInfo->ucAvailableAuthTypes) + break; + + if (prJoinInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_SHARED_KEY) { + + DBGLOG(P2P, INFO, "RETRY JOIN INIT: Retry Authentication with AuthType == SHARED_KEY.\n"); + + prJoinInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_SHARED_KEY; + + prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_SHARED_KEY; + } else { + DBGLOG(P2P, ERROR, "RETRY JOIN INIT: Retry Authentication with Unexpected AuthType.\n"); + ASSERT(0); + break; + } + + prJoinInfo->ucAvailableAuthTypes = 0; /* No more available Auth Types */ + + /* Trigger SAA to start JOIN process. */ + prJoinReqMsg = (P_MSG_JOIN_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_REQ_T)); + if (!prJoinReqMsg) { + ASSERT(0); /* Can't trigger SAA FSM */ + break; + } + + prJoinReqMsg->rMsgHdr.eMsgId = MID_P2P_SAA_FSM_START; + prJoinReqMsg->ucSeqNum = ++prJoinInfo->ucSeqNumOfReqMsg; + prJoinReqMsg->prStaRec = prStaRec; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinReqMsg, MSG_SEND_METHOD_BUF); + + fgRetValue = TRUE; + } while (FALSE); + + return fgRetValue; + +} /* end of p2pFuncRetryJOIN() */ + +P_BSS_INFO_T p2pFuncBSSIDFindBssInfo(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBSSID) +{ + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; + UINT_8 ucBssIdx = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBSSID != NULL)); + + for (ucBssIdx = 0; ucBssIdx < BSS_INFO_NUM; ucBssIdx++) { + if (!IS_NET_ACTIVE(prAdapter, ucBssIdx)) + continue; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + + if (EQUAL_MAC_ADDR(prBssInfo->aucBSSID, pucBSSID) && IS_BSS_P2P(prBssInfo)) + break; + + prBssInfo = NULL; + } + + } while (FALSE); + + return prBssInfo; +} /* p2pFuncBSSIDFindBssInfo */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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_BSS_INFO_T prP2pBssInfo, + IN P_SW_RFB_T prSwRfb, IN PP_STA_RECORD_T pprStaRec, OUT PUINT_16 pu2StatusCode) +{ + BOOLEAN fgPmfConn = FALSE; + 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"); + + + /* P2P 3.2.8 */ + *pu2StatusCode = STATUS_CODE_REQ_DECLINED; + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; + + if ((prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) || + (prP2pBssInfo->eIntendOPMode != OP_MODE_NUM)) { + /* We are not under AP Mode yet. */ + DBGLOG(P2P, WARN, "Current OP mode is not under AP mode. (%d)\n", prP2pBssInfo->eCurrentOPMode); + return FALSE; + } + + prStaRec = cnmGetStaRecByAddress(prAdapter, prP2pBssInfo->ucBssIndex, prAuthFrame->aucSrcAddr); + + if (!prStaRec) { + prStaRec = cnmStaRecAlloc(prAdapter, STA_TYPE_P2P_GC, + prP2pBssInfo->ucBssIndex, prAuthFrame->aucSrcAddr); + + /* 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); + + 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; + + /* Update default Tx rate */ + nicTxUpdateStaRecDefaultRate(prStaRec); + + /* NOTE(Kevin): Better to change state here, not at TX Done */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + } else { +#if CFG_SUPPORT_802_11W + /* AP PMF. if PMF connection, do not reset state & FSM */ + fgPmfConn = rsnCheckBipKeyInstalled(prAdapter, prStaRec); + if (fgPmfConn) { + DBGLOG(P2P, WARN, "PMF Connction, return false\n"); + return FALSE; + } +#endif + + prSwRfb->ucStaRecIdx = prStaRec->ucIndex; + + if ((prStaRec->ucStaState > STA_STATE_1) && (IS_STA_IN_P2P(prStaRec))) { + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + p2pFuncResetStaRecStatus(prAdapter, prStaRec); + + bssRemoveClient(prAdapter, prP2pBssInfo, prStaRec); + } + + } + + if (bssGetClientCount(prAdapter, prP2pBssInfo) >= P2P_MAXIMUM_CLIENT_COUNT + || !p2pRoleProcessACLInspection(prAdapter, prStaRec->aucMacAddr, prP2pBssInfo->ucBssIndex) +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + || kalP2PMaxClients(prAdapter->prGlueInfo, bssGetClientCount(prAdapter, prP2pBssInfo), + (UINT_8) prP2pBssInfo->u4PrivateData) +#endif + ) { + /* GROUP limit full. */ + /* P2P 3.2.8 */ + DBGLOG(P2P, WARN, "Group Limit Full. (%d)\n", bssGetClientCount(prAdapter, prP2pBssInfo)); + cnmStaRecFree(prAdapter, prStaRec); + return TRUE; + } +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + else { + /* Hotspot Blacklist */ + if (kalP2PCmpBlackList(prAdapter->prGlueInfo, prAuthFrame->aucSrcAddr, + (UINT_8) prP2pBssInfo->u4PrivateData)) { + return FALSE; + } + + } +#endif + /* prStaRec->eStaType = STA_TYPE_INFRA_CLIENT; */ + prStaRec->eStaType = STA_TYPE_P2P_GC; + + /* Update Station Record - Status/Reason Code */ + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + + prStaRec->ucJoinFailureCount = 0; + + *pprStaRec = prStaRec; + + *pu2StatusCode = STATUS_CODE_SUCCESSFUL; + + + return TRUE; + +} /* p2pFuncValidateAuth */ + +VOID p2pFuncResetStaRecStatus(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + do { + if ((prAdapter == NULL) || (prStaRec == NULL)) { + ASSERT(FALSE); + break; + } + + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + prStaRec->u2ReasonCode = REASON_CODE_RESERVED; + prStaRec->ucJoinFailureCount = 0; + prStaRec->fgTransmitKeyExist = FALSE; + + prStaRec->fgSetPwrMgtBit = FALSE; + + } while (FALSE); +} /* p2pFuncResetStaRecStatus */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief The function is used to initialize the value of the connection settings for +* P2P network +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFuncInitConnectionSettings(IN P_ADAPTER_T prAdapter, + IN P_P2P_CONNECTION_SETTINGS_T prP2PConnSettings, IN BOOLEAN fgIsApMode) +{ + P_WIFI_VAR_T prWifiVar = NULL; + + ASSERT(prP2PConnSettings); + + prWifiVar = &(prAdapter->rWifiVar); + ASSERT(prWifiVar); + + prP2PConnSettings->fgIsApMode = fgIsApMode; + +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + prP2PConnSettings->fgIsWPSMode = prWifiVar->ucApWpsMode; +#endif +} /* p2pFuncInitConnectionSettings */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Assoc Req Frame and then return +* the status code to AAA to indicate if need to perform following actions +* when the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu2StatusCode The Status Code of Validation Result +* +* @retval TRUE Reply the Assoc Resp +* @retval FALSE Don't reply the Assoc Resp +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2pFuncValidateAssocReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu2StatusCode) +{ + BOOLEAN fgReplyAssocResp = TRUE; + P_WLAN_ASSOC_REQ_FRAME_T prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + /* 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; + prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) prSwRfb->pvHeader; + + prP2pBssInfo = p2pFuncBSSIDFindBssInfo(prAdapter, prAssocReqFrame->aucBSSID); + + if (prP2pBssInfo == NULL) { + DBGLOG(P2P, ERROR, "RX ASSOC frame without BSS active / BSSID match\n"); + ASSERT(FALSE); + break; + } + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prStaRec == NULL) { + /* Station record should be ready while RX AUTH frame. */ + fgReplyAssocResp = FALSE; + ASSERT(FALSE); + break; + } + ASSERT(prSwRfb->prRxStatusGroup3); + prStaRec->ucRCPI = nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0, prSwRfb); + + 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; + } + + *pu2StatusCode = STATUS_CODE_SUCCESSFUL; + + } while (FALSE); + + return fgReplyAssocResp; + +} /* p2pFuncValidateAssocReq */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to check the TKIP IE +* +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2pFuncParseCheckForTKIPInfoElem(IN PUINT_8 pucBuf) +{ + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + P_WPA_INFO_ELEM_T prWpaIE = (P_WPA_INFO_ELEM_T) NULL; + UINT_32 u4GroupKeyCipher = 0; + + if (pucBuf == NULL) + return FALSE; + + prWpaIE = (P_WPA_INFO_ELEM_T) pucBuf; + + if (prWpaIE->ucLength <= ELEM_MIN_LEN_WFA_OUI_TYPE_SUBTYPE) + return FALSE; + + if (kalMemCmp(prWpaIE->aucOui, aucWfaOui, sizeof(aucWfaOui))) + return FALSE; + + WLAN_GET_FIELD_32(&prWpaIE->u4GroupKeyCipherSuite, &u4GroupKeyCipher); + + if (prWpaIE->ucOuiType == VENDOR_OUI_TYPE_WPA && + u4GroupKeyCipher == WPA_CIPHER_SUITE_TKIP) + return TRUE; + else + return FALSE; +} /* p2pFuncParseCheckForP2PInfoElem */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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, IN BOOLEAN fgIsDevInterface, IN UINT_8 ucRoleIdx) +{ + BOOLEAN fgIsReplyProbeRsp = FALSE; + BOOLEAN fgApplyp2PDevFilter = FALSE; + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + DEBUGFUNC("p2pFuncValidateProbeReq"); + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + + prP2pRoleFsmInfo = prAdapter->rWifiVar.aprP2pRoleFsmInfo[ucRoleIdx]; + + /* Process both cases that with amd without add p2p interface */ + if (fgIsDevInterface) + fgApplyp2PDevFilter = TRUE; + else { + if (prAdapter->prGlueInfo->prP2PInfo[0]->prDevHandler == + prAdapter->prGlueInfo->prP2PInfo[ucRoleIdx]->aprRoleHandler) + fgApplyp2PDevFilter = TRUE; + else + fgApplyp2PDevFilter = FALSE; + } + /* TODO: */ + if ((fgApplyp2PDevFilter && + (prAdapter->u4OsPacketFilter & PARAM_PACKET_FILTER_PROBE_REQ)) + || (!fgApplyp2PDevFilter && + (prP2pRoleFsmInfo->u4P2pPacketFilter & PARAM_PACKET_FILTER_PROBE_REQ))) { + /* Leave the probe response to p2p_supplicant. */ + kalP2PIndicateRxMgmtFrame(prAdapter->prGlueInfo, prSwRfb, fgIsDevInterface, ucRoleIdx); + } + + } 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, IN BOOLEAN fgIsDevInterface, + IN UINT_8 ucRoleIdx) +{ + DEBUGFUNC("p2pFuncValidateRxActionFrame"); + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + + /* TODO: */ + + if (PARAM_PACKET_FILTER_ACTION_FRAME) { + /* Leave the probe response to p2p_supplicant. */ + kalP2PIndicateRxMgmtFrame(prAdapter->prGlueInfo, prSwRfb, fgIsDevInterface, ucRoleIdx); + } + + } while (FALSE); + + return; + +} /* p2pFuncValidateRxMgmtFrame */ + +BOOLEAN p2pFuncIsAPMode(IN P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings) +{ + if (prP2pConnSettings) { + if (prP2pConnSettings->fgIsWPSMode == 1) + return FALSE; + return prP2pConnSettings->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; + UINT_8 i = 0; + RSN_INFO_T rRsnIe; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); + + if (u4IELen == 0) + break; + + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo[prP2pBssInfo->u4PrivateData]; + prP2pSpecificBssInfo->u2AttributeLen = 0; + + ASSERT_BREAK(pucIEInfo != NULL); + + pucIE = pucIEInfo; + + if (prP2pBssInfo->u2CapInfo & CAP_INFO_PRIVACY) + kalP2PSetCipher(prAdapter->prGlueInfo, IW_AUTH_CIPHER_WEP40, + (UINT_8) prP2pBssInfo->u4PrivateData); + else + kalP2PSetCipher(prAdapter->prGlueInfo, IW_AUTH_CIPHER_NONE, + (UINT_8) prP2pBssInfo->u4PrivateData); + + IE_FOR_EACH(pucIE, u4IELen, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_SSID: /* 0 *//* V *//* Done */ + { + + /* DBGLOG(P2P, TRACE, ("SSID update\n")); */ + /* SSID is saved when start AP/GO */ + /* SSID IE set in beacon from supplicant will not always be + * the true since hidden SSID case + */ +#if 0 + 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); +#endif + + } + break; + case ELEM_ID_SUP_RATES: /* 1 *//* V *//* Done */ + { +#ifndef CFG_SUPPORT_P2P_GO_KEEP_RATE_SETTING + DBGLOG(P2P, TRACE, "Support Rate IE\n"); + if ((SUP_RATES_IE(pucIE)->ucLength) > ELEM_MAX_LEN_SUP_RATES) + SUP_RATES_IE(pucIE)->ucLength = ELEM_MAX_LEN_SUP_RATES; + 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); +#endif + } + break; + case ELEM_ID_DS_PARAM_SET: /* 3 *//* V *//* Done */ + { + DBGLOG(P2P, TRACE, "DS PARAM IE: %d.\n", DS_PARAM_IE(pucIE)->ucCurrChnl); + + /* prP2pBssInfo->ucPrimaryChannel = DS_PARAM_IE(pucIE)->ucCurrChnl; */ + + /* prP2pBssInfo->eBand = BAND_2G4; */ + } + break; + case ELEM_ID_TIM: /* 5 *//* V */ + TIM_IE(pucIE)->ucDTIMPeriod = prP2pBssInfo->ucDTIMPeriod; + DBGLOG(P2P, TRACE, + "TIM IE, Len:%d, DTIM:%d\n", IE_LEN(pucIE), TIM_IE(pucIE)->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:%x, TX Beamforming Cap:%x, Ant Selection Cap:%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 */ + + DBGLOG(P2P, TRACE, "RSN IE\n"); + kalP2PSetCipher(prAdapter->prGlueInfo, IW_AUTH_CIPHER_CCMP, + (UINT_8) prP2pBssInfo->u4PrivateData); + + if (rsnParseRsnIE(prAdapter, RSN_IE(pucIE), &rRsnIe)) { + prP2pBssInfo->u4RsnSelectedGroupCipher = RSN_CIPHER_SUITE_CCMP; + prP2pBssInfo->u4RsnSelectedPairwiseCipher = RSN_CIPHER_SUITE_CCMP; + prP2pBssInfo->u4RsnSelectedAKMSuite = RSN_AKM_SUITE_PSK; + prP2pBssInfo->u2RsnSelectedCapInfo = rRsnIe.u2RsnCap; + DBGLOG(RSN, TRACE, "RsnIe CAP:0x%x\n", rRsnIe.u2RsnCap); + } + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + prP2pBssInfo->rApPmfCfg.fgMfpc = (rRsnIe.u2RsnCap & ELEM_WPA_CAP_MFPC) ? 1 : 0; + prP2pBssInfo->rApPmfCfg.fgMfpr = (rRsnIe.u2RsnCap & ELEM_WPA_CAP_MFPR) ? 1 : 0; + + for (i = 0; i < rRsnIe.u4AuthKeyMgtSuiteCount; i++) { + if ((rRsnIe.au4AuthKeyMgtSuite[i] == RSN_AKM_SUITE_PSK_SHA256) || + (rRsnIe.au4AuthKeyMgtSuite[i] == RSN_AKM_SUITE_802_1X_SHA256)) { + DBGLOG(RSN, INFO, "SHA256 support\n"); + /* over-write u4RsnSelectedAKMSuite by SHA256 AKM */ + prP2pBssInfo->u4RsnSelectedAKMSuite = + rRsnIe.au4AuthKeyMgtSuite[i]; + prP2pBssInfo->rApPmfCfg.fgSha256 = TRUE; + break; + } + } + DBGLOG(RSN, ERROR, "bcn mfpc:%d, mfpr:%d, sha256:%d\n", + prP2pBssInfo->rApPmfCfg.fgMfpc, + prP2pBssInfo->rApPmfCfg.fgMfpr, + prP2pBssInfo->rApPmfCfg.fgSha256); +#endif + + break; + case ELEM_ID_EXTENDED_SUP_RATES: /* 50 *//* V */ +#ifndef CFG_SUPPORT_P2P_GO_KEEP_RATE_SETTING + /* 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; +#endif + 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"); + { + p2pFuncParseBeaconVenderId(prAdapter, pucIE, prP2pSpecificBssInfo, + (UINT_8) prP2pBssInfo->u4PrivateData); + /* TODO: Store other Vender IE except for WMM Param. */ + } + break; + default: + DBGLOG(P2P, TRACE, "Unprocessed element ID:%d\n", IE_ID(pucIE)); + break; + } + } + + } while (FALSE); +} /* p2pFuncParseBeaconContent */ + +/* Code refactoring for AOSP */ +static VOID +p2pFuncParseBeaconVenderId(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucIE, + IN P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo, IN UINT_8 ucRoleIndex) +{ + do { + UINT_8 ucOuiType; + UINT_16 u2SubTypeVersion; + + if (rsnParseCheckForWFAInfoElem(prAdapter, pucIE, &ucOuiType, &u2SubTypeVersion)) { + if ((ucOuiType == VENDOR_OUI_TYPE_WPA) && (u2SubTypeVersion == VERSION_WPA)) { + if (!kalP2PGetCcmpCipher(prAdapter->prGlueInfo, ucRoleIndex)) + kalP2PSetCipher(prAdapter->prGlueInfo, IW_AUTH_CIPHER_TKIP, ucRoleIndex); + kalMemCopy(prP2pSpecificBssInfo->aucWpaIeBuffer, pucIE, IE_SIZE(pucIE)); + prP2pSpecificBssInfo->u2WpaIeLen = IE_SIZE(pucIE); + DBGLOG(P2P, TRACE, "WPA IE in supplicant\n"); + } else if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + kalP2PUpdateWSC_IE(prAdapter->prGlueInfo, 0, pucIE, IE_SIZE(pucIE), ucRoleIndex); + DBGLOG(P2P, TRACE, "WPS IE in supplicant\n"); + } else if (ucOuiType == VENDOR_OUI_TYPE_WMM) { + DBGLOG(P2P, TRACE, "WMM IE in supplicant\n"); + } + /* 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); + DBGLOG(P2P, TRACE, "P2P IE in supplicant\n"); + } else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { + + kalMemCopy(&prP2pSpecificBssInfo->aucAttributesCache + [prP2pSpecificBssInfo->u2AttributeLen], pucIE, IE_SIZE(pucIE)); + + prP2pSpecificBssInfo->u2AttributeLen += IE_SIZE(pucIE); + } else { + DBGLOG(P2P, TRACE, "Unknown 50-6F-9A-%d IE.\n", ucOuiType); + } + } 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); + } + } while (0); +} + +P_BSS_DESC_T +p2pFuncKeepOnConnection(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, + 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; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prBssInfo != NULL) && + (prConnReqInfo != NULL) && (prChnlReqInfo != NULL) && (prScanReqInfo != NULL)); + + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + break; + /* Update connection request information. */ + ASSERT(prConnReqInfo->eConnRequest == P2P_CONNECTION_TYPE_GC); + + /* Find BSS Descriptor first. */ + prTargetBss = scanP2pSearchDesc(prAdapter, prConnReqInfo); + + if (prTargetBss == NULL) { + /* Update scan parameter... to scan target device. */ + /* TODO: Need refine. */ + 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->eChnlReqType = CH_REQ_TYPE_JOIN; + + prChnlReqInfo->eChannelWidth = prTargetBss->eChannelWidth; + prChnlReqInfo->ucCenterFreqS1 = prTargetBss->ucCenterFreqS1; + prChnlReqInfo->ucCenterFreqS2 = prTargetBss->ucCenterFreqS2; + } + + } while (FALSE); + + return prTargetBss; +} /* p2pFuncKeepOnConnection */ + +/* Currently Only for ASSOC Response Frame. */ +VOID p2pFuncStoreAssocRspIEBuffer(IN P_ADAPTER_T prAdapter, IN P_P2P_JOIN_INFO_T prP2pJoinInfo, IN P_SW_RFB_T prSwRfb) +{ + P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) NULL; + INT_16 i2IELen = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pJoinInfo != 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; + + prP2pJoinInfo->u4BufLength = (UINT_32) i2IELen; + + kalMemCopy(prP2pJoinInfo->aucIEBuf, prAssocRspFrame->aucInfoElem, prP2pJoinInfo->u4BufLength); + + } while (FALSE); +} /* p2pFuncStoreAssocRspIEBuffer */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set Packet Filter. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_NOT_SUPPORTED +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFuncMgmtFrameRegister(IN P_ADAPTER_T prAdapter, + IN UINT_16 u2FrameType, IN BOOLEAN fgIsRegistered, OUT PUINT_32 pu4P2pPacketFilter) +{ + UINT_32 u4NewPacketFilter = 0; + CMD_RX_PACKET_FILTER rSetRxPacketFilter; + + DEBUGFUNC("p2pFuncMgmtFrameRegister"); + + do { + ASSERT_BREAK(prAdapter != NULL); + + if (pu4P2pPacketFilter) + u4NewPacketFilter = *pu4P2pPacketFilter; + + switch (u2FrameType) { + case MAC_FRAME_PROBE_REQ: + if (fgIsRegistered) { + u4NewPacketFilter |= PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(P2P, TRACE, "Open packet filer probe request\n"); + } else { + u4NewPacketFilter &= ~PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(P2P, TRACE, "Close packet filer probe request\n"); + } + break; + case MAC_FRAME_ACTION: + if (fgIsRegistered) { + u4NewPacketFilter |= PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(P2P, TRACE, "Open packet filer action frame.\n"); + } else { + u4NewPacketFilter &= ~PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(P2P, TRACE, "Close packet filer action frame.\n"); + } + break; + default: + DBGLOG(P2P, TRACE, "Ask frog to add code for mgmt:%x\n", u2FrameType); + break; + } + + if (pu4P2pPacketFilter) + *pu4P2pPacketFilter = u4NewPacketFilter; + + /* u4NewPacketFilter |= prAdapter->u4OsPacketFilter; */ + + prAdapter->u4OsPacketFilter &= ~PARAM_PACKET_FILTER_P2P_MASK; + prAdapter->u4OsPacketFilter |= u4NewPacketFilter; + + DBGLOG(P2P, TRACE, "P2P Set PACKET filter:0x%x\n", + prAdapter->u4OsPacketFilter); + + rSetRxPacketFilter.u4RxPacketFilter = prAdapter->u4OsPacketFilter; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RX_FILTER, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_RX_PACKET_FILTER), + (PUINT_8) &rSetRxPacketFilter, + &u4NewPacketFilter, + sizeof(u4NewPacketFilter) + ); + + prAdapter->u4OsPacketFilter = rSetRxPacketFilter.u4RxPacketFilter; + + } while (FALSE); +} /* p2pFuncMgmtFrameRegister */ + +VOID p2pFuncUpdateMgmtFrameRegister(IN P_ADAPTER_T prAdapter, IN UINT_32 u4OsFilter) +{ + CMD_RX_PACKET_FILTER rSetRxPacketFilter; + + do { + + /* TODO: Filter need to be done. */ + /* 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); + + rSetRxPacketFilter.u4RxPacketFilter = prAdapter->u4OsPacketFilter; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RX_FILTER, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_RX_PACKET_FILTER), + (PUINT_8)&rSetRxPacketFilter, + &u4OsFilter, + sizeof(u4OsFilter) + ); + + prAdapter->u4OsPacketFilter = rSetRxPacketFilter.u4RxPacketFilter; + DBGLOG(P2P, TRACE, "P2P Set PACKET filter:0x%x\n", + prAdapter->u4OsPacketFilter); + } + + } while (FALSE); +} /* p2pFuncUpdateMgmtFrameRegister */ + +VOID p2pFuncGetStationInfo(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucMacAddr, OUT P_P2P_STATION_INFO_T prStaInfo) +{ + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucMacAddr != NULL) && (prStaInfo != NULL)); + + prStaInfo->u4InactiveTime = 0; + prStaInfo->u4RxBytes = 0; + prStaInfo->u4TxBytes = 0; + prStaInfo->u4RxPackets = 0; + prStaInfo->u4TxPackets = 0; + /* TODO: */ + + } while (FALSE); +} /* p2pFuncGetStationInfo */ +#if 0 +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; + BOOLEAN fgBackupAttributes = FALSE; + + u2BufferSize = 0; + + 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 (IE_ID(pucIE) == ELEM_ID_VENDOR) { + 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)) { + p2pFuncGetAttriListAction(prAdapter, + prIe, ucOuiType, + &pucAttriListStart, &u2AttriListLen, + &fgIsAllocMem, &fgBackupAttributes, &u2BufferSize); + } /* 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) { + /* Todo:: Nothing */ + } else if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + /* Big Endian: WSC, WFD. */ + WSC_ATTRI_FOR_EACH(pucAttribute, u2AttriListLen, u2Offset) { + DBGLOG(P2P, LOUD, "Attribute ID:%d, Length:%d.\n", + WSC_ATTRI_ID(pucAttribute), WSC_ATTRI_LEN(pucAttribute)); + } + } else { + } + + ASSERT(u2Offset == u2AttriListLen); + + *ppucAttriList = pucAttriListStart; + *pu2AttriListLen = u2AttriListLen; + + } else { + *ppucAttriList = (PUINT_8) NULL; + *pu2AttriListLen = 0; + } + + return fgIsAllocMem; +} /* p2pFuncGetAttriList */ + +/* Code refactoring for AOSP */ +static VOID +p2pFuncGetAttriListAction(IN P_ADAPTER_T prAdapter, + IN P_IE_P2P_T prIe, IN UINT_8 ucOuiType, + OUT PUINT_8 *pucAttriListStart, OUT UINT_16 *u2AttriListLen, + OUT BOOLEAN *fgIsAllocMem, OUT BOOLEAN *fgBackupAttributes, OUT UINT_16 *u2BufferSize) +{ + do { + 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 (*fgBackupAttributes == FALSE) { + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = + prAdapter->rWifiVar.prP2pSpecificBssInfo; + + *fgBackupAttributes = TRUE; + if (ucOuiType == VENDOR_OUI_TYPE_P2P) { + kalMemCopy(&prP2pSpecificBssInfo->aucAttributesCache[0], + *pucAttriListStart, *u2AttriListLen); + + *pucAttriListStart = &prP2pSpecificBssInfo->aucAttributesCache[0]; + *u2BufferSize = P2P_MAXIMUM_ATTRIBUTE_LEN; + } else if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + kalMemCopy(&prP2pSpecificBssInfo->aucWscAttributesCache[0], + *pucAttriListStart, *u2AttriListLen); + *pucAttriListStart = &prP2pSpecificBssInfo->aucWscAttributesCache[0]; + *u2BufferSize = WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE; + } +#if CFG_SUPPORT_WFD + else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { + PUINT_8 pucTmpBuf = (PUINT_8) NULL; + + pucTmpBuf = (PUINT_8) kalMemAlloc + (WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE, VIR_MEM_TYPE); + + if (pucTmpBuf != NULL) { + *fgIsAllocMem = TRUE; + } else { + /* Can't alloca memory for WFD IE relocate. */ + ASSERT(FALSE); + break; + } + + kalMemCopy(pucTmpBuf, *pucAttriListStart, *u2AttriListLen); + *pucAttriListStart = pucTmpBuf; + *u2BufferSize = WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE; + } +#endif + else + *fgBackupAttributes = FALSE; + } + u2CopyLen = (UINT_16) (prIe->ucLength - P2P_OUI_TYPE_LEN); + + if (((*u2AttriListLen) + u2CopyLen) > (*u2BufferSize)) { + u2CopyLen = (*u2BufferSize) - (*u2AttriListLen); + DBGLOG(P2P, WARN, "Length of received P2P attributes > maximum cache size.\n"); + } + + if (u2CopyLen) { + kalMemCopy((PUINT_8) ((ULONG) (*pucAttriListStart) + (ULONG) (*u2AttriListLen)), + &prIe->aucP2PAttributes[0], u2CopyLen); + *u2AttriListLen += u2CopyLen; + } + + } + } while (0); +} +#endif + +P_MSDU_INFO_T p2pFuncProcessP2pProbeRsp(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, 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; + BOOLEAN fgIsWFDIE = FALSE; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + UINT_16 u2EstimateSize = 0, u2EstimatedExtraIELen = 0; + UINT_32 u4IeArraySize = 0, u4Idx = 0, i = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMgmtTxMsdu != NULL)); + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + prGlueInfo = prAdapter->prGlueInfo; + if (!prGlueInfo) { + DBGLOG(P2P, ERROR, "NULL prGlueInfo\n"); + break; + } + + /* 3 Make sure this is probe response frame. */ + prProbeRspFrame = (P_WLAN_PROBE_RSP_FRAME_T) ((ULONG) prMgmtTxMsdu->prPacket + MAC_TX_RESERVED_FIELD); + ASSERT_BREAK((prProbeRspFrame->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_PROBE_RSP); + + /* 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[0]->u2VenderIELen = 0; */ + /* Reset in each time ?? */ + prAdapter->prGlueInfo->prP2PInfo[prP2pBssInfo->u4PrivateData]->u2WFDIELen = 0; +#endif + kalP2PResetP2P_IE(prGlueInfo, + (UINT_8) prP2pBssInfo->u4PrivateData); + IE_FOR_EACH(pucIEBuf, u2IELength, u2Offset) { + switch (IE_ID(pucIEBuf)) { + case ELEM_ID_SSID: + { + p2pFuncProcessP2pProbeRspAction(prAdapter, pucIEBuf, ELEM_ID_SSID, + &ucBssIdx, &prP2pBssInfo, &fgIsWSCIE, + &fgIsP2PIE, &fgIsWFDIE); + } + break; + case ELEM_ID_VENDOR: + { + p2pFuncProcessP2pProbeRspAction(prAdapter, pucIEBuf, ELEM_ID_VENDOR, + &ucBssIdx, &prP2pBssInfo, &fgIsWSCIE, + &fgIsP2PIE, &fgIsWFDIE); + } + 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, ucBssIdx, + NULL)); + } + + } + + if (fgIsWSCIE) + u2EstimatedExtraIELen += kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 2, + (UINT_8) prP2pBssInfo->u4PrivateData); + + if (fgIsP2PIE) { + for (i = 0; i < MAX_MULTI_P2P_IE_COUNT; i++) { + u2EstimatedExtraIELen += + kalP2PCalP2P_IELen(prGlueInfo, i, + (UINT_8) prP2pBssInfo->u4PrivateData); + } + u2EstimatedExtraIELen += p2pFuncCalculateP2P_IE_NoA(prAdapter, ucBssIdx, NULL); + } +#if CFG_SUPPORT_WFD + ASSERT(sizeof(prAdapter->prGlueInfo->prP2PInfo[prP2pBssInfo->u4PrivateData]->aucWFDIE) >= + prAdapter->prGlueInfo->prP2PInfo[prP2pBssInfo->u4PrivateData]->u2WFDIELen); + if (fgIsWFDIE) + u2EstimatedExtraIELen += + prAdapter->prGlueInfo->prP2PInfo[prP2pBssInfo->u4PrivateData]->u2WFDIELen; +#if 0 + u2EstimatedExtraIELen += prAdapter->prGlueInfo->prP2PInfo[0]->u2VenderIELen; +#endif +#endif + + u2EstimateSize += u2EstimatedExtraIELen; + if ((u2EstimateSize) > (prRetMsduInfo->u2FrameLength)) { + prRetMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimateSize); + + if (prRetMsduInfo == NULL) { + DBGLOG(P2P, WARN, "No packet for sending new probe response, use original one\n"); + prRetMsduInfo = prMgmtTxMsdu; + break; + } + + } + + prRetMsduInfo->ucBssIndex = ucBssIdx; + + /* 3 Compose / Re-compose probe response frame. */ + bssComposeBeaconProbeRespFrameHeaderAndFF((PUINT_8) + ((ULONG) (prRetMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD), + prProbeRspFrame->aucDestAddr, + prProbeRspFrame->aucSrcAddr, + prProbeRspFrame->aucBSSID, + prProbeRspFrame->u2BeaconInterval, + 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); + + prRetMsduInfo->ucStaRecIndex = prMgmtTxMsdu->ucStaRecIndex; + + for (u4Idx = 0; u4Idx < u4IeArraySize; u4Idx++) { + if (txProbeRspIETable[u4Idx].pfnAppendIE) + txProbeRspIETable[u4Idx].pfnAppendIE(prAdapter, prRetMsduInfo); + + } + + if (fgIsWSCIE) { + kalP2PGenWSC_IE(prAdapter->prGlueInfo, + 2, + (PUINT_8) ((ULONG) prRetMsduInfo->prPacket + + (ULONG) prRetMsduInfo->u2FrameLength), + (UINT_8) prP2pBssInfo->u4PrivateData); + + prRetMsduInfo->u2FrameLength += (UINT_16) kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 2, + (UINT_8) prP2pBssInfo->u4PrivateData); + } + + if (fgIsP2PIE) { + for (i = 0; i < MAX_MULTI_P2P_IE_COUNT; i++) { + kalP2PGenP2P_IE(prGlueInfo, i, + (PUINT_8) ((ULONG) prRetMsduInfo->prPacket + + (ULONG) prRetMsduInfo->u2FrameLength), + (UINT_8) prP2pBssInfo->u4PrivateData); + prRetMsduInfo->u2FrameLength += + kalP2PCalP2P_IELen(prGlueInfo, i, + (UINT_8) prP2pBssInfo->u4PrivateData); + } + + p2pFuncGenerateP2P_IE_NoA(prAdapter, prRetMsduInfo); + } +#if CFG_SUPPORT_WFD + + if (fgIsWFDIE > 0) { + ASSERT(prAdapter->prGlueInfo->prP2PInfo[prP2pBssInfo->u4PrivateData]->u2WFDIELen > 0); + kalMemCopy((PUINT_8) + ((ULONG) prRetMsduInfo->prPacket + + (ULONG) prRetMsduInfo->u2FrameLength), + prAdapter->prGlueInfo->prP2PInfo[prP2pBssInfo->u4PrivateData]->aucWFDIE, + prAdapter->prGlueInfo->prP2PInfo[prP2pBssInfo->u4PrivateData]->u2WFDIELen); + prRetMsduInfo->u2FrameLength += + (UINT_16) prAdapter->prGlueInfo->prP2PInfo[prP2pBssInfo->u4PrivateData]->u2WFDIELen; + + } +#if 0 + if (prAdapter->prGlueInfo->prP2PInfo[0]->u2VenderIELen > 0) { + kalMemCopy((PUINT_8) + ((UINT_32) prRetMsduInfo->prPacket + + (UINT_32) prRetMsduInfo->u2FrameLength), + prAdapter->prGlueInfo->prP2PInfo[0]->aucVenderIE, + prAdapter->prGlueInfo->prP2PInfo[0]->u2VenderIELen); + prRetMsduInfo->u2FrameLength += (UINT_16) prAdapter->prGlueInfo->prP2PInfo[0]->u2VenderIELen; + } +#endif +#endif /* CFG_SUPPORT_WFD */ + + } while (FALSE); + + if (prRetMsduInfo != prMgmtTxMsdu) + cnmMgtPktFree(prAdapter, prMgmtTxMsdu); + + return prRetMsduInfo; +} /* p2pFuncProcessP2pProbeRsp */ + +/* Code refactoring for AOSP */ +static VOID +p2pFuncProcessP2pProbeRspAction(IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucIEBuf, IN UINT_8 ucElemIdType, + OUT UINT_8 *ucBssIdx, OUT P_BSS_INFO_T *prP2pBssInfo, OUT BOOLEAN *fgIsWSCIE, + OUT BOOLEAN *fgIsP2PIE, OUT BOOLEAN *fgIsWFDIE) +{ + UINT_8 ucOuiType = 0; + UINT_16 u2SubTypeVersion = 0; + + switch (ucElemIdType) { + case ELEM_ID_SSID: + { + if (SSID_IE(pucIEBuf)->ucLength > 7) { + for ((*ucBssIdx) = 0; (*ucBssIdx) < MAX_BSS_INDEX; (*ucBssIdx)++) { + *prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, *ucBssIdx); + if (!(*prP2pBssInfo)) + continue; + if (EQUAL_SSID((*prP2pBssInfo)->aucSSID, + (*prP2pBssInfo)->ucSSIDLen, + SSID_IE(pucIEBuf)->aucSSID, SSID_IE(pucIEBuf)->ucLength)) { + break; + } + } + if ((*ucBssIdx) == P2P_DEV_BSS_INDEX) + *prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, *ucBssIdx); + } else { + *prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, P2P_DEV_BSS_INDEX); + COPY_SSID((*prP2pBssInfo)->aucSSID, + (*prP2pBssInfo)->ucSSIDLen, + SSID_IE(pucIEBuf)->aucSSID, SSID_IE(pucIEBuf)->ucLength); + + } + } + break; + case ELEM_ID_VENDOR: + if (rsnParseCheckForWFAInfoElem(prAdapter, pucIEBuf, &ucOuiType, &u2SubTypeVersion)) { + if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + kalP2PUpdateWSC_IE(prAdapter->prGlueInfo, 2, pucIEBuf, IE_SIZE(pucIEBuf), + (UINT_8) ((P_BSS_INFO_T)*prP2pBssInfo)->u4PrivateData); + *fgIsWSCIE = TRUE; + } + + } else if (p2pFuncParseCheckForP2PInfoElem(prAdapter, pucIEBuf, &ucOuiType)) { + if (ucOuiType == VENDOR_OUI_TYPE_P2P) { + kalP2PUpdateP2P_IE(prAdapter->prGlueInfo, + pucIEBuf, IE_SIZE(pucIEBuf), + (UINT_8) ((P_BSS_INFO_T)*prP2pBssInfo)->u4PrivateData); + *fgIsP2PIE = TRUE; + } +#if CFG_SUPPORT_WFD + else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { + DBGLOG(P2P, INFO, + "WFD IE is found in probe resp (supp). Len %u\n", IE_SIZE(pucIEBuf)); + if ((sizeof( + prAdapter->prGlueInfo->prP2PInfo[((P_BSS_INFO_T)*prP2pBssInfo)->u4PrivateData] + ->aucWFDIE) >= (prAdapter->prGlueInfo->prP2PInfo[((P_BSS_INFO_T)*prP2pBssInfo) + ->u4PrivateData]->u2WFDIELen + IE_SIZE(pucIEBuf)))) { + *fgIsWFDIE = TRUE; + kalMemCopy(prAdapter->prGlueInfo->prP2PInfo[((P_BSS_INFO_T)*prP2pBssInfo) + ->u4PrivateData]->aucWFDIE, pucIEBuf, IE_SIZE(pucIEBuf)); + prAdapter->prGlueInfo->prP2PInfo[((P_BSS_INFO_T)*prP2pBssInfo) + ->u4PrivateData]->u2WFDIELen += IE_SIZE(pucIEBuf); + } + } /* VENDOR_OUI_TYPE_WFD */ +#endif + } else { + DBGLOG(P2P, INFO, + "Other vender IE is found in probe resp (supp). Len %u\n", IE_SIZE(pucIEBuf)); + } + break; + default: + break; + } +} + +#if 0 /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */ +UINT_32 +p2pFuncCalculateExtra_IELenForBeacon(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec) +{ + + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpeBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + UINT_32 u4IELen = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (eNetTypeIndex == NETWORK_TYPE_P2P_INDEX)); + + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) + break; + + prP2pSpeBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + u4IELen = prP2pSpeBssInfo->u2IELenForBCN; + + } while (FALSE); + + return u4IELen; +} /* p2pFuncCalculateP2p_IELenForBeacon */ + +VOID p2pFuncGenerateExtra_IEForBeacon(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpeBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + PUINT_8 pucIEBuf = (PUINT_8) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + prP2pSpeBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) + break; + + pucIEBuf = (PUINT_8) ((UINT_32) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + + kalMemCopy(pucIEBuf, prP2pSpeBssInfo->aucBeaconIECache, prP2pSpeBssInfo->u2IELenForBCN); + + prMsduInfo->u2FrameLength += prP2pSpeBssInfo->u2IELenForBCN; + + } while (FALSE); +} /* p2pFuncGenerateExtra_IEForBeacon */ + +#else +UINT_32 p2pFuncCalculateP2p_IELenForBeacon(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, IN P_STA_RECORD_T prStaRec) +{ + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpeBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + UINT_32 u4IELen = 0; + P_BSS_INFO_T prBssInfo; + + do { + ASSERT_BREAK((prAdapter != NULL) && (ucBssIdx < BSS_INFO_NUM)); + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + if (!prAdapter->fgIsP2PRegistered) + break; + + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2PConnSettings[prBssInfo->u4PrivateData])) + break; + + prP2pSpeBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo[prBssInfo->u4PrivateData]; + + 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; + P_BSS_INFO_T prBssInfo; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + if (!prAdapter->fgIsP2PRegistered) + break; + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + + prP2pSpeBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo[prBssInfo->u4PrivateData]; + + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2PConnSettings[prBssInfo->u4PrivateData])) + break; + + pucIEBuf = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (ULONG) prMsduInfo->u2FrameLength); + + kalMemCopy(pucIEBuf, prP2pSpeBssInfo->aucAttributesCache, prP2pSpeBssInfo->u2AttributeLen); + + prMsduInfo->u2FrameLength += prP2pSpeBssInfo->u2AttributeLen; + + } while (FALSE); +} /* p2pFuncGenerateP2p_IEForBeacon */ + +UINT_32 p2pFuncCalculateWSC_IELenForBeacon(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, IN P_STA_RECORD_T prStaRec) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + + if (prP2pBssInfo->eNetworkType != NETWORK_TYPE_P2P) + return 0; + + return kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 0, (UINT_8) prP2pBssInfo->u4PrivateData); +} /* p2pFuncCalculateP2p_IELenForBeacon */ + +VOID p2pFuncGenerateWSC_IEForBeacon(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + PUINT_8 pucBuffer; + UINT_16 u2IELen = 0; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + + if (prP2pBssInfo->eNetworkType != NETWORK_TYPE_P2P) + return; + + u2IELen = (UINT_16) kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 0, (UINT_8) prP2pBssInfo->u4PrivateData); + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (ULONG) prMsduInfo->u2FrameLength); + + ASSERT(pucBuffer); + + /* TODO: Check P2P FSM State. */ + kalP2PGenWSC_IE(prAdapter->prGlueInfo, 0, pucBuffer, (UINT_8) prP2pBssInfo->u4PrivateData); + + prMsduInfo->u2FrameLength += u2IELen; +} /* p2pFuncGenerateP2p_IEForBeacon */ + +#endif +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to calculate P2P IE length for Beacon frame. +* +* @param[in] eNetTypeIndex Specify which network +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return The length of P2P IE added +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 p2pFuncCalculateP2p_IELenForAssocRsp(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN P_STA_RECORD_T prStaRec) +{ + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (prBssInfo->eNetworkType != NETWORK_TYPE_P2P) + return 0; + + return p2pFuncCalculateP2P_IELen(prAdapter, + ucBssIndex, + 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_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (!prStaRec) { + DBGLOG(P2P, ERROR, "prStaRec of ucStaRecIndex %d is NULL!\n", + prMsduInfo->ucStaRecIndex); + return; + } + + if (IS_STA_IN_P2P(prStaRec)) { + DBGLOG(P2P, TRACE, "Generate NULL P2P IE for Assoc Rsp.\n"); + + p2pFuncGenerateP2P_IE(prAdapter, + prMsduInfo->ucBssIndex, + 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"); + } +} /* p2pFuncGenerateP2p_IEForAssocRsp */ + +UINT_32 +p2pFuncCalculateP2P_IELen(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucBssIndex, + 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 UINT_8 ucBssIndex, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize, + IN APPEND_VAR_ATTRI_ENTRY_T arAppendAttriTable[], IN UINT_32 u4AttriTableSize) +{ + PUINT_8 pucBuffer = (PUINT_8) NULL; + P_IE_P2P_T prIeP2P = (P_IE_P2P_T) NULL; + UINT_32 u4OverallAttriLen; + UINT_32 u4AttriLen; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + UINT_8 aucTempBuffer[P2P_MAXIMUM_ATTRIBUTE_LEN]; + UINT_32 i; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL)); + + pucBuffer = (PUINT_8) ((ULONG) pucBuf + (*pu2Offset)); + + ASSERT_BREAK(pucBuffer != NULL); + + /* Check buffer length is still enough. */ + ASSERT_BREAK((u2BufSize - (*pu2Offset)) >= P2P_IE_OUI_HDR); + + prIeP2P = (P_IE_P2P_T) pucBuffer; + + prIeP2P->ucId = ELEM_ID_P2P; + + prIeP2P->aucOui[0] = aucWfaOui[0]; + prIeP2P->aucOui[1] = aucWfaOui[1]; + prIeP2P->aucOui[2] = aucWfaOui[2]; + prIeP2P->ucOuiType = VENDOR_OUI_TYPE_P2P; + + (*pu2Offset) += P2P_IE_OUI_HDR; + + /* Overall length of all Attributes */ + u4OverallAttriLen = 0; + + for (i = 0; i < u4AttriTableSize; i++) { + + if (arAppendAttriTable[i].pfnAppendAttri) { + u4AttriLen = + arAppendAttriTable[i].pfnAppendAttri(prAdapter, ucBssIndex, fgIsAssocFrame, + pu2Offset, pucBuf, u2BufSize); + + u4OverallAttriLen += u4AttriLen; + + if (u4OverallAttriLen > P2P_MAXIMUM_ATTRIBUTE_LEN) { + u4OverallAttriLen -= P2P_MAXIMUM_ATTRIBUTE_LEN; + + prIeP2P->ucLength = (VENDOR_OUI_TYPE_LEN + P2P_MAXIMUM_ATTRIBUTE_LEN); + + pucBuffer = + (PUINT_8) ((ULONG) prIeP2P + + (VENDOR_OUI_TYPE_LEN + P2P_MAXIMUM_ATTRIBUTE_LEN)); + + prIeP2P = (P_IE_P2P_T) ((ULONG) prIeP2P + + (ELEM_HDR_LEN + + (VENDOR_OUI_TYPE_LEN + P2P_MAXIMUM_ATTRIBUTE_LEN))); + + kalMemCopy(aucTempBuffer, pucBuffer, u4OverallAttriLen); + + prIeP2P->ucId = ELEM_ID_P2P; + + prIeP2P->aucOui[0] = aucWfaOui[0]; + prIeP2P->aucOui[1] = aucWfaOui[1]; + prIeP2P->aucOui[2] = aucWfaOui[2]; + prIeP2P->ucOuiType = VENDOR_OUI_TYPE_P2P; + + kalMemCopy(prIeP2P->aucP2PAttributes, aucTempBuffer, u4OverallAttriLen); + (*pu2Offset) += P2P_IE_OUI_HDR; + } + + } + + } + + prIeP2P->ucLength = (UINT_8) (VENDOR_OUI_TYPE_LEN + u4OverallAttriLen); + + } while (FALSE); +} /* p2pFuncGenerateP2P_IE */ + +UINT_32 +p2pFuncAppendAttriStatusForAssocRsp(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucBssIndex, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize) +{ + PUINT_8 pucBuffer; + P_P2P_ATTRI_STATUS_T prAttriStatus; + UINT_32 u4AttriLen = 0; + + ASSERT(prAdapter); + ASSERT(pucBuf); + + if (fgIsAssocFrame) + return u4AttriLen; + /* TODO: For assoc request P2P IE check in driver & return status in P2P IE. */ + + pucBuffer = (PUINT_8) ((ULONG) pucBuf + (ULONG) (*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_SUCCESS; + + 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 UINT_8 ucBssIndex, + 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; + P_BSS_INFO_T prBssInfo = NULL; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + ASSERT(prAdapter); + ASSERT(pucBuf); + ASSERT(prBssInfo); + + if (fgIsAssocFrame) + return u4AttriLen; + /* TODO: For extend listen timing. */ + + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo[prBssInfo->u4PrivateData]; + + u4AttriLen = (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_EXT_LISTEN_TIMING); + + ASSERT(u2BufSize >= ((*pu2Offset) + (UINT_16) u4AttriLen)); + + pucBuffer = (PUINT_8) ((ULONG) pucBuf + (ULONG) (*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; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (pucIEBuf != NULL)); + + pucIE = pucIEBuf; + + if (pfgIsMore) + *pfgIsMore = FALSE; + + IE_FOR_EACH(pucIE, u2BufferLen, u2Offset) { + if (IE_ID(pucIE) == ucElemID) { + if ((prTargetIE) && (pfgIsMore)) { + + *pfgIsMore = TRUE; + break; + } + prTargetIE = (P_IE_HDR_T) pucIE; + + if (pfgIsMore == NULL) + break; + + } + } + + } while (FALSE); + + return prTargetIE; +} /* p2pFuncGetSpecIE */ + +P_ATTRIBUTE_HDR_T +p2pFuncGetSpecAttri(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucOuiType, IN PUINT_8 pucIEBuf, IN UINT_16 u2BufferLen, IN UINT_8 ucAttriID) +{ + 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; + UINT_16 u2BufferLenLeft = 0; + + DBGLOG(P2P, INFO, "Check AssocReq Oui type %u attri %u for len %u\n", ucOuiType, ucAttriID, 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((ULONG) prP2pIE >= (ULONG) pucIE); + u2BufferLenLeft = u2BufferLen - (UINT_16) (((ULONG) prP2pIE) - ((ULONG) pucIEBuf)); + + DBGLOG(P2P, INFO, "Find vendor id %u len %u oui %u more %u LeftLen %u\n", + IE_ID(prP2pIE), IE_LEN(prP2pIE), prP2pIE->ucOuiType, fgIsMore, u2BufferLenLeft); + + if (IE_LEN(prP2pIE) > P2P_OUI_TYPE_LEN) + p2pFuncGetSpecAttriAction(prP2pIE, ucOuiType, ucAttriID, &prTargetAttri); + /* P2P_OUI_TYPE_LEN */ + pucIE = (PUINT_8) (((ULONG) prP2pIE) + IE_SIZE(prP2pIE)); + } + /* prP2pIE */ + } while (prP2pIE && fgIsMore && u2BufferLenLeft); + + } while (FALSE); + + return prTargetAttri; +} + +/* p2pFuncGetSpecAttri */ + +/* Code refactoring for AOSP */ +static VOID +p2pFuncGetSpecAttriAction(IN P_IE_P2P_T prP2pIE, + IN UINT_8 ucOuiType, IN UINT_8 ucAttriID, OUT P_ATTRIBUTE_HDR_T *prTargetAttri) +{ + PUINT_8 pucAttri = (PUINT_8) NULL; + UINT_16 u2OffsetAttri = 0; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + + 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_IE_OUI_HDR), u2OffsetAttri) { + if (WSC_ATTRI_ID(pucAttri) == ucAttriID) { + *prTargetAttri = (P_ATTRIBUTE_HDR_T) pucAttri; + break; + } + + } + + } else if (ucOuiType == VENDOR_OUI_TYPE_P2P) { + P2P_ATTRI_FOR_EACH(pucAttri, (IE_LEN(prP2pIE) - P2P_IE_OUI_HDR), u2OffsetAttri) { + if (ATTRI_ID(pucAttri) == ucAttriID) { + *prTargetAttri = (P_ATTRIBUTE_HDR_T) pucAttri; + break; + } + } + + } +#if CFG_SUPPORT_WFD + else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { + WFD_ATTRI_FOR_EACH(pucAttri, (IE_LEN(prP2pIE) - P2P_IE_OUI_HDR), u2OffsetAttri) { + if (ATTRI_ID(pucAttri) == (UINT_8) ucAttriID) { + *prTargetAttri = (P_ATTRIBUTE_HDR_T) pucAttri; + break; + } + } + } +#endif + else { + /* Todo:: Nothing */ + /* Possible or else. */ + } + } + } /* ucOuiType */ +} + +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, + prBssInfo->ucBssIndex, + 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 P_BSS_INFO_T prP2pBssInfo, + 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; + + PUINT_8 pucBuffer = (PUINT_8) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBcnBuffer != NULL) + && (prP2pBssInfo != 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); + if (!prP2pProbeRspInfo->prProbeRspMsduTemplate) { + DBGLOG(P2P, ERROR, "cnmMgtPktAlloc fail!\n"); + rWlanStatus = WLAN_STATUS_FAILURE; + break; + } + + prMsduInfo = prP2pProbeRspInfo->prProbeRspMsduTemplate; + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucStaRecIndex = 0xFF; + prMsduInfo->ucBssIndex = prP2pBssInfo->ucBssIndex; + + } else { + prMsduInfo = prP2pBssInfo->prBeacon; + + if (prMsduInfo == NULL) { + rWlanStatus = WLAN_STATUS_FAILURE; + break; + } + + if (u4BcnBufLen > (OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem[0]) + MAX_IE_LENGTH)) { + /* Unexpected error, buffer overflow. */ + ASSERT(FALSE); + break; + } + + } + + pucBuffer = (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + kalMemCopy(pucBuffer, pucBcnBuffer, u4BcnBufLen); + + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = (UINT_16) u4BcnBufLen; + + if (fgSynToFW) + rWlanStatus = p2pFuncGenerateBeaconProbeRsp(prAdapter, prP2pBssInfo, prMsduInfo, fgIsProbeRsp); + + } while (FALSE); + + return rWlanStatus; + +} /* p2pFuncComposeBeaconTemplate */ + +UINT_32 wfdFuncCalculateWfdIELenForAssocRsp(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN P_STA_RECORD_T prStaRec) +{ +#if CFG_SUPPORT_WFD_COMPOSE_IE + UINT_16 u2EstimatedExtraIELen = 0; + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + if (prBssInfo->eNetworkType != NETWORK_TYPE_P2P) + return 0; + + if (!IS_STA_P2P_TYPE(prStaRec)) + return 0; + + u2EstimatedExtraIELen = prAdapter->prGlueInfo->prP2PInfo[0]->u2WFDIELen; + + if (u2EstimatedExtraIELen < VENDOR_SPECIFIC_IE_LENGTH) + return u2EstimatedExtraIELen; + else + return 0; +#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_STA_RECORD_T prStaRec; + UINT_16 u2EstimatedExtraIELen; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_GLUE_INFO_T prGlueInfo; + P_GL_P2P_INFO_T prP2PInfo; + + if (!prAdapter) + return; + + if (!prMsduInfo) + return; + + prGlueInfo = prAdapter->prGlueInfo; + if (!prGlueInfo) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + if (!prStaRec) + return; + + if (!IS_STA_P2P_TYPE(prStaRec)) + return; + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + prP2PInfo = prGlueInfo->prP2PInfo[prP2pBssInfo->u4PrivateData]; + if (!prP2PInfo) + return; + + u2EstimatedExtraIELen = prP2PInfo->u2WFDIELen; + if (u2EstimatedExtraIELen > 0 + && u2EstimatedExtraIELen < VENDOR_SPECIFIC_IE_LENGTH) { + kalMemCopy((prMsduInfo->prPacket + prMsduInfo->u2FrameLength), + prP2PInfo->aucWFDIE, u2EstimatedExtraIELen); + prMsduInfo->u2FrameLength += u2EstimatedExtraIELen; + } + return; +#else + return; +#endif +} /* wfdFuncGenerateWfdIEForAssocRsp */ + +VOID +p2pFuncComposeNoaAttribute(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucBssIndex, OUT PUINT_8 aucNoaAttrArray, OUT PUINT_32 pu4Len) +{ + P_BSS_INFO_T prBssInfo = NULL; + P_P2P_ATTRI_NOA_T prNoaAttr = NULL; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = NULL; + P_NOA_DESCRIPTOR_T prNoaDesc = NULL; + UINT_32 u4NumOfNoaDesc = 0; + UINT_32 i = 0; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo[prBssInfo->u4PrivateData]; + + prNoaAttr = (P_P2P_ATTRI_NOA_T) aucNoaAttrArray; + + prNoaAttr->ucId = P2P_ATTRI_ID_NOTICE_OF_ABSENCE; + prNoaAttr->ucIndex = prP2pSpecificBssInfo->ucNoAIndex; + + if (prP2pSpecificBssInfo->fgEnableOppPS) { + prNoaAttr->ucCTWOppPSParam = P2P_CTW_OPPPS_PARAM_OPPPS_FIELD | + (prP2pSpecificBssInfo->u2CTWindow & P2P_CTW_OPPPS_PARAM_CTWINDOW_MASK); + } else { + prNoaAttr->ucCTWOppPSParam = 0; + } + + for (i = 0; i < prP2pSpecificBssInfo->ucNoATimingCount; i++) { + if (prP2pSpecificBssInfo->arNoATiming[i].fgIsInUse) { + prNoaDesc = (P_NOA_DESCRIPTOR_T) &prNoaAttr->aucNoADesc[u4NumOfNoaDesc]; + + prNoaDesc->ucCountType = prP2pSpecificBssInfo->arNoATiming[i].ucCount; + prNoaDesc->u4Duration = prP2pSpecificBssInfo->arNoATiming[i].u4Duration; + prNoaDesc->u4Interval = prP2pSpecificBssInfo->arNoATiming[i].u4Interval; + prNoaDesc->u4StartTime = prP2pSpecificBssInfo->arNoATiming[i].u4StartTime; + + u4NumOfNoaDesc++; + } + } + + /* include "index" + "OppPs Params" + "NOA descriptors" */ + prNoaAttr->u2Length = 2 + u4NumOfNoaDesc * sizeof(NOA_DESCRIPTOR_T); + + /* include "Attribute ID" + "Length" + "index" + "OppPs Params" + "NOA descriptors" */ + *pu4Len = P2P_ATTRI_HDR_LEN + prNoaAttr->u2Length; +} + +UINT_32 p2pFuncCalculateP2P_IE_NoA(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, IN P_STA_RECORD_T prStaRec) +{ + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = NULL; + UINT_8 ucIdx; + UINT_32 u4NumOfNoaDesc = 0; + P_BSS_INFO_T prBssInfo; + + prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2PConnSettings[prBssInfo->u4PrivateData])) + return 0; + + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo[prBssInfo->u4PrivateData]; + + for (ucIdx = 0; ucIdx < prP2pSpecificBssInfo->ucNoATimingCount; ucIdx++) { + if (prP2pSpecificBssInfo->arNoATiming[ucIdx].fgIsInUse) + u4NumOfNoaDesc++; + } + + /* include "index" + "OppPs Params" + "NOA descriptors" */ + /* include "Attribute ID" + "Length" + "index" + "OppPs Params" + "NOA descriptors" */ + return P2P_ATTRI_HDR_LEN + 2 + (u4NumOfNoaDesc * sizeof(NOA_DESCRIPTOR_T)); +} + +VOID p2pFuncGenerateP2P_IE_NoA(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_IE_P2P_T prIeP2P; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + UINT_32 u4AttributeLen; + P_BSS_INFO_T prBssInfo; + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2PConnSettings[prBssInfo->u4PrivateData])) + return; + + prIeP2P = (P_IE_P2P_T) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + + prIeP2P->ucId = ELEM_ID_P2P; + prIeP2P->aucOui[0] = aucWfaOui[0]; + prIeP2P->aucOui[1] = aucWfaOui[1]; + prIeP2P->aucOui[2] = aucWfaOui[2]; + prIeP2P->ucOuiType = VENDOR_OUI_TYPE_P2P; + + /* Compose NoA attribute */ + p2pFuncComposeNoaAttribute(prAdapter, prMsduInfo->ucBssIndex, prIeP2P->aucP2PAttributes, &u4AttributeLen); + + prIeP2P->ucLength = VENDOR_OUI_TYPE_LEN + u4AttributeLen; + + prMsduInfo->u2FrameLength += (ELEM_HDR_LEN + prIeP2P->ucLength); + +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_ie.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_ie.c new file mode 100644 index 0000000000000..3f9dc837453d9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_ie.c @@ -0,0 +1,194 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#include "precomp.h" + +UINT_32 p2pCalculate_IEForAssocReq(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN P_STA_RECORD_T prStaRec) +{ + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo = (P_P2P_CONNECTION_REQ_INFO_T) NULL; + UINT_32 u4RetValue = 0; + + do { + ASSERT_BREAK((prStaRec != NULL) && (prAdapter != NULL)); + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, (UINT_8) prP2pBssInfo->u4PrivateData); + + prConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + + u4RetValue = prConnReqInfo->u4BufLength; + + /* ADD WMM Information Element */ + u4RetValue += (ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_INFO); + + /* ADD HT Capability */ + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) && + (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) { + u4RetValue += (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP); + } +#if CFG_SUPPORT_802_11AC + /* ADD VHT Capability */ + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AC) && + (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11AC)) { + u4RetValue += (ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP); + } +#endif + +#if CFG_SUPPORT_MTK_SYNERGY + if (prAdapter->rWifiVar.ucMtkOui == FEATURE_ENABLED) + u4RetValue += (ELEM_HDR_LEN + ELEM_MIN_LEN_MTK_OUI); +#endif + } 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_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_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)); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, (UINT_8) prBssInfo->u4PrivateData); + + prConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + + pucIEBuf = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (ULONG) prMsduInfo->u2FrameLength); + + kalMemCopy(pucIEBuf, prConnReqInfo->aucIEBuf, prConnReqInfo->u4BufLength); + + prMsduInfo->u2FrameLength += prConnReqInfo->u4BufLength; + + /* Add WMM IE */ + mqmGenerateWmmInfoIE(prAdapter, prMsduInfo); + + /* Add HT IE */ + rlmReqGenerateHtCapIE(prAdapter, prMsduInfo); + +#if CFG_SUPPORT_802_11AC + /* Add VHT IE */ + rlmReqGenerateVhtCapIE(prAdapter, prMsduInfo); +#endif + +#if CFG_SUPPORT_MTK_SYNERGY + rlmGenerateMTKOuiIE(prAdapter, prMsduInfo); +#endif + } 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.rWfdConfigureSettings); + + ASSERT_BREAK((prWfdCfgSettings != NULL)); + + if ((prWfdCfgSettings->ucWfdEnable == 0) || + ((prWfdCfgSettings->u4WfdFlag & WFD_FLAGS_DEV_INFO_VALID) == 0)) { + break; + } + + pucBuffer = (PUINT_8) ((ULONG) pucBuf + (ULONG) (*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 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_rlm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_rlm.c new file mode 100644 index 0000000000000..78c3c1f68f46d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_rlm.c @@ -0,0 +1,1158 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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" +#include "rlm.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 +******************************************************************************** +*/ +ENUM_CHNL_EXT_T MAP_SECONDATY_CHANNEL_5KHZ(UINT_32 ch) +{ + ENUM_CHNL_EXT_T eSCO = CHNL_EXT_SCN; + + switch (ch) { + case 36: + case 44: + case 52: + case 60: + case 100: + case 108: + case 116: + case 124: + case 132: + case 140: + case 149: + case 157: + eSCO = CHNL_EXT_SCA; + break; + case 40: + case 48: + case 56: + case 64: + case 104: + case 112: + case 120: + case 128: + case 136: + case 144: + case 153: + case 161: + eSCO = CHNL_EXT_SCB; + break; + case 165: + default: + eSCO = CHNL_EXT_SCN; + break; + } + return eSCO; +} + + + +/******************************************************************************* +* 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) +{ + UINT_8 i; + + 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; + + /* Check if AP can set its bw to 40MHz + * But if any of BSS is setup in 40MHz, the second BSS would prefer to use 20MHz + * in order to remain in SCC case + */ + if (cnmBss40mBwPermitted(prAdapter, prBssInfo->ucBssIndex)) { + + prBssInfo->eBssSCO = rlmGetScoForAP(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); + } + } + + /* Filled the VHT BW/S1/S2 and MCS rate set */ + if (prBssInfo->ucPhyTypeSet & PHY_TYPE_BIT_VHT) { + for (i = 0; i < 8; i++) + prBssInfo->u2VhtBasicMcsSet |= BITS(2 * i, (2 * i + 1)); + prBssInfo->u2VhtBasicMcsSet &= (VHT_CAP_INFO_MCS_MAP_MCS9 << VHT_CAP_INFO_MCS_1SS_OFFSET); + + prBssInfo->ucVhtChannelWidth = cnmGetBssMaxBwToChnlBW(prAdapter, prBssInfo->ucBssIndex); + if (prBssInfo->ucVhtChannelWidth == VHT_OP_CHANNEL_WIDTH_80P80) { + /* TODO: BW80+80 support */ + DBGLOG(RLM, WARN, "BW80+80 not support. Fallback to VHT_OP_CHANNEL_WIDTH_20_40\n"); + prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_20_40; + prBssInfo->ucVhtChannelFrequencyS1 = 0; + prBssInfo->ucVhtChannelFrequencyS2 = 0; + } else { + prBssInfo->ucVhtChannelFrequencyS1 = + rlmGetVhtS1ForAP(prAdapter, prBssInfo); + prBssInfo->ucVhtChannelFrequencyS2 = 0; + } + + /* If the S1 is invalid, force to change bandwidth */ + if (prBssInfo->ucVhtChannelFrequencyS1 == 0) + prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_20_40; + } else { + prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_20_40; + prBssInfo->ucVhtChannelFrequencyS1 = 0; + prBssInfo->ucVhtChannelFrequencyS2 = 0; + } + + + /*ERROR HANDLE*/ + if ((prBssInfo->ucVhtChannelWidth == VHT_OP_CHANNEL_WIDTH_80) + || (prBssInfo->ucVhtChannelWidth == VHT_OP_CHANNEL_WIDTH_160) + || (prBssInfo->ucVhtChannelWidth == VHT_OP_CHANNEL_WIDTH_80P80)) { + + if (prBssInfo->ucVhtChannelFrequencyS1 == 0) { + DBGLOG(RLM, INFO, "Wrong AP S1 parameter setting, back to BW20!!!\n"); + + prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_20_40; + prBssInfo->ucVhtChannelFrequencyS1 = 0; + prBssInfo->ucVhtChannelFrequencyS2 = 0; + } + } + + DBGLOG(RLM, INFO, "WLAN AP SCO=%d BW=%d S1=%d S2=%d CH=%d Band=%d\n", + prBssInfo->eBssSCO, + prBssInfo->ucVhtChannelWidth, + prBssInfo->ucVhtChannelFrequencyS1, + prBssInfo->ucVhtChannelFrequencyS2, prBssInfo->ucPrimaryChannel, prBssInfo->eBand); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + if (!prBssInfo) + return; + + if (!IS_BSS_ACTIVE(prBssInfo)) + return; + + if (RLM_NET_IS_11N(prBssInfo) && /* !RLM_NET_IS_BOW(prBssInfo) && FIXME. */ + 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 (!(prSwRfb->prStaRec)) { + DBGLOG(P2P, ERROR, "prSwRfb->prStaRec is null.\n"); + return; + } + + if (prRxFrame->ucAction != ACTION_PUBLIC_20_40_COEXIST || !prStaRec || prStaRec->ucStaState != STA_STATE_3 || + prSwRfb->u2PacketLen < (WLAN_MAC_MGMT_HEADER_LEN + 5) || prSwRfb->prStaRec->ucBssIndex != + /* HIF_RX_HDR_GET_NETWORK_IDX(prSwRfb->prHifRxHdr) != */ + prStaRec->ucBssIndex) { + return; + } + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + 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->ucBssIndex); + 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 rlmHandleObssStatusEventPkt(P_ADAPTER_T prAdapter, P_EVENT_AP_OBSS_STATUS_T prObssStatus) +{ + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(prObssStatus); + ASSERT(prObssStatus->ucBssIndex < MAX_BSS_INDEX); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prObssStatus->ucBssIndex); + + if (prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) + return; + + 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) { + if (!prStaRec) { + DBGLOG(P2P, WARN, "NULL STA_REC ptr in BSS client list\n"); + bssDumpClientList(prAdapter, prBssInfo); + break; + } + + if (prStaRec->fgIsInUse && prStaRec->ucStaState == STA_STATE_3 && + prStaRec->ucBssIndex == prBssInfo->ucBssIndex) { + 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 (prBssInfo->fg40mBwAllowed && + !(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 1 + /*ap mode throughput enhancement + * only 2.4G with B mode client connecion use long slot time + */ + if ((!(prStaRec->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME)) + && fgErpProtectMode + && prBssInfo->eBand == BAND_2G4) + fgUseShortSlotTime = FALSE; +#else + if (!(prStaRec->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME)) + fgUseShortSlotTime = FALSE; +#endif + 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->ucBssIndex); +} +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief Initial the channel list from the domain information. +* This function is called after P2P initial and Domain information changed. +* Make sure the device is disconnected while changing domain information. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return boolean value if probe response frame is +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmFuncInitialChannelList(IN P_ADAPTER_T prAdapter) +{ + P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T) NULL; + P_DOMAIN_INFO_ENTRY prDomainInfoEntry = (P_DOMAIN_INFO_ENTRY) NULL; + P_DOMAIN_SUBBAND_INFO prDomainSubBand = (P_DOMAIN_SUBBAND_INFO) NULL; + P_CHANNEL_ENTRY_FIELD_T prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) NULL; + UINT_32 u4Idx = 0, u4IdxII = 0; + UINT_8 ucBufferSize = P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE; +#if 0 + UINT_8 ucSocialChnlSupport = 0, ucAutoChnl = 0; +#endif + + do { + ASSERT_BREAK(prAdapter != NULL); + + prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings; +#if 0 + ucAutoChnl = prP2pConnSetting->ucOperatingChnl; +#endif + + prDomainInfoEntry = rlmDomainGetDomainInfo(prAdapter); + + ASSERT_BREAK((prDomainInfoEntry != NULL) && (prP2pConnSetting != NULL)); + + prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) prP2pConnSetting->aucChannelEntriesField; + + for (u4Idx = 0; u4Idx < MAX_SUBBAND_NUM; u4Idx++) { + prDomainSubBand = &prDomainInfoEntry->rSubBand[u4Idx]; + + if (((prDomainSubBand->ucBand == BAND_5G) && (!prAdapter->fgEnable5GBand)) + || (prDomainSubBand->ucBand == BAND_NULL)) { + continue; + } + + if (ucBufferSize < (P2P_ATTRI_LEN_CHANNEL_ENTRY + prDomainSubBand->ucNumChannels)) { + /* Buffer is not enough to include all supported channels. */ + break; /* for */ + } + + prChannelEntryField->ucRegulatoryClass = prDomainSubBand->ucRegClass; + prChannelEntryField->ucNumberOfChannels = prDomainSubBand->ucNumChannels; + + for (u4IdxII = 0; u4IdxII < prDomainSubBand->ucNumChannels; u4IdxII++) { + prChannelEntryField->aucChannelList[u4IdxII] = + prDomainSubBand->ucFirstChannelNum + (u4IdxII * prDomainSubBand->ucChannelSpan); + +#if 0 + switch (prChannelEntryField->aucChannelList[u4IdxII]) { + case 1: + ucSocialChnlSupport = 1; + break; + case 6: + ucSocialChnlSupport = 6; + break; + case 11: + ucSocialChnlSupport = 11; + break; + default: + break; + } + +#endif + } + + if (ucBufferSize >= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels)) + ucBufferSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels); + else + break; + + prChannelEntryField = + (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntryField + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (ULONG) prChannelEntryField->ucNumberOfChannels); + + } + +#if 0 + if (prP2pConnSetting->ucListenChnl == 0) { + prP2pConnSetting->ucListenChnl = P2P_DEFAULT_LISTEN_CHANNEL; + + if (ucSocialChnlSupport != 0) { + /* 1. User Not Set LISTEN channel. + * 2. Social channel is not empty. + */ + prP2pConnSetting->ucListenChnl = ucSocialChnlSupport; + } + } +#endif + + /* TODO: 20110921 frog - */ + /* If LISTEN channel is not set, + * a random supported channel would be set. + * If no social channel is supported, DEFAULT channel would be set. + */ + + prP2pConnSetting->ucRfChannelListSize = P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE - ucBufferSize; + +#if 0 + if (prP2pConnSetting->ucOperatingChnl == 0) { /* User not set OPERATE channel. */ + + if (scnQuerySparseChannel(prAdapter, NULL, &ucAutoChnl)) + break; /* while */ + + ucBufferSize = prP2pConnSetting->ucRfChannelListSize; + + prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) prP2pConnSetting->aucChannelEntriesField; + + while (ucBufferSize != 0) { + if (prChannelEntryField->ucNumberOfChannels != 0) { + ucAutoChnl = prChannelEntryField->aucChannelList[0]; + break; /* while */ + } + + else { + prChannelEntryField = + (P_CHANNEL_ENTRY_FIELD_T) ((UINT_32) prChannelEntryField + + P2P_ATTRI_LEN_CHANNEL_ENTRY + (UINT_32) + prChannelEntryField->ucNumberOfChannels); + + ucBufferSize -= + (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels); + } + + } + + } +#endif + /* We assume user would not set a channel not in the channel list. + * If so, the operating channel still depends on target device supporting capability. + */ + + /* TODO: 20110921 frog - */ + /* If the Operating channel is not set, a channel from supported channel list is set automatically. + * If there is no supported channel in channel list, a DEFAULT channel is set. + */ + + } while (FALSE); + +#if 0 + prP2pConnSetting->ucOperatingChnl = ucAutoChnl; +#endif +} /* rlmFuncInitialChannelList */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find a common channel list from the local channel list info & target channel list info. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return boolean value if probe response frame is +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmFuncCommonChannelList(IN P_ADAPTER_T prAdapter, + IN P_CHANNEL_ENTRY_FIELD_T prChannelEntryII, IN UINT_8 ucChannelListSize) +{ + P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T) NULL; + P_CHANNEL_ENTRY_FIELD_T prChannelEntryI = + (P_CHANNEL_ENTRY_FIELD_T) NULL, prChannelEntryIII = (P_CHANNEL_ENTRY_FIELD_T) NULL; + UINT_8 aucCommonChannelList[P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE]; + UINT_8 ucOriChnlSize = 0, ucNewChnlSize = 0; + + do { + + ASSERT_BREAK(prAdapter != NULL); + + prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings; + + prChannelEntryIII = (P_CHANNEL_ENTRY_FIELD_T) aucCommonChannelList; + + while (ucChannelListSize > 0) { + + prChannelEntryI = (P_CHANNEL_ENTRY_FIELD_T) prP2pConnSetting->aucChannelEntriesField; + ucOriChnlSize = prP2pConnSetting->ucRfChannelListSize; + + while (ucOriChnlSize > 0) { + if (prChannelEntryI->ucRegulatoryClass == prChannelEntryII->ucRegulatoryClass) { + prChannelEntryIII->ucRegulatoryClass = prChannelEntryI->ucRegulatoryClass; + /* TODO: Currently we assume that the regulatory class the same, + * the channels are the same. + */ + kalMemCopy(prChannelEntryIII->aucChannelList, + prChannelEntryII->aucChannelList, + prChannelEntryII->ucNumberOfChannels); + prChannelEntryIII->ucNumberOfChannels = prChannelEntryII->ucNumberOfChannels; + + ucNewChnlSize += + P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryIII->ucNumberOfChannels; + + prChannelEntryIII = + (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntryIII + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (ULONG) prChannelEntryIII->ucNumberOfChannels); + } + + ucOriChnlSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryI->ucNumberOfChannels); + + prChannelEntryI = + (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntryI + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (ULONG) prChannelEntryI->ucNumberOfChannels); + + } + + ucChannelListSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryII->ucNumberOfChannels); + + prChannelEntryII = (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntryII + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (ULONG) prChannelEntryII->ucNumberOfChannels); + + } + + kalMemCopy(prP2pConnSetting->aucChannelEntriesField, aucCommonChannelList, ucNewChnlSize); + prP2pConnSetting->ucRfChannelListSize = ucNewChnlSize; + + } while (FALSE); +} /* rlmFuncCommonChannelList */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 rlmFuncFindOperatingClass(IN P_ADAPTER_T prAdapter, IN UINT_8 ucChannelNum) +{ + UINT_8 ucRegulatoryClass = 0, ucBufferSize = 0; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T) NULL; + P_CHANNEL_ENTRY_FIELD_T prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) NULL; + UINT_32 u4Idx = 0; + + do { + ASSERT_BREAK(prAdapter != NULL); + + prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings; + ucBufferSize = prP2pConnSetting->ucRfChannelListSize; + prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) prP2pConnSetting->aucChannelEntriesField; + + while (ucBufferSize != 0) { + + for (u4Idx = 0; u4Idx < prChannelEntryField->ucNumberOfChannels; u4Idx++) { + if (prChannelEntryField->aucChannelList[u4Idx] == ucChannelNum) { + ucRegulatoryClass = prChannelEntryField->ucRegulatoryClass; + break; + } + + } + + if (ucRegulatoryClass != 0) + break; /* while */ + prChannelEntryField = + (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntryField + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (ULONG) prChannelEntryField->ucNumberOfChannels); + + ucBufferSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels); + + } + + } while (FALSE); + + return ucRegulatoryClass; +} /* rlmFuncFindOperatingClass */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rlmFuncFindAvailableChannel(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucCheckChnl, + IN PUINT_8 pucSuggestChannel, IN BOOLEAN fgIsSocialChannel, IN BOOLEAN fgIsDefaultChannel) +{ + BOOLEAN fgIsResultAvailable = FALSE; + P_CHANNEL_ENTRY_FIELD_T prChannelEntry = (P_CHANNEL_ENTRY_FIELD_T) NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T) NULL; + UINT_8 ucBufferSize = 0, ucIdx = 0, ucChannelSelected = 0; + + do { + ASSERT_BREAK(prAdapter != NULL); + + if (fgIsDefaultChannel) + ucChannelSelected = P2P_DEFAULT_LISTEN_CHANNEL; + + prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings; + ucBufferSize = prP2pConnSetting->ucRfChannelListSize; + prChannelEntry = (P_CHANNEL_ENTRY_FIELD_T) prP2pConnSetting->aucChannelEntriesField; + + while ((ucBufferSize != 0) && (!fgIsResultAvailable)) { + + for (ucIdx = 0; ucIdx < prChannelEntry->ucNumberOfChannels; ucIdx++) { + if ((!fgIsSocialChannel) || + (prChannelEntry->aucChannelList[ucIdx] == 1) || + (prChannelEntry->aucChannelList[ucIdx] == 6) || + (prChannelEntry->aucChannelList[ucIdx] == 11)) { + + if (prChannelEntry->aucChannelList[ucIdx] <= 11) { + /* 2.4G. */ + ucChannelSelected = prChannelEntry->aucChannelList[ucIdx]; + } else if ((prChannelEntry->aucChannelList[ucIdx] < 52) + && (prChannelEntry->aucChannelList[ucIdx] > 14)) { + /* 2.4G + 5G. */ + ucChannelSelected = prChannelEntry->aucChannelList[ucIdx]; + } + + if (ucChannelSelected == ucCheckChnl) { + fgIsResultAvailable = TRUE; + break; + } + } + + } + + ucBufferSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntry->ucNumberOfChannels); + + prChannelEntry = (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntry + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (ULONG) prChannelEntry->ucNumberOfChannels); + + } + + if ((!fgIsResultAvailable) && (pucSuggestChannel != NULL)) { + DBGLOG(P2P, TRACE, + "The request channel %d is not available, sugguested channel:%d\n", + ucCheckChnl, ucChannelSelected); + /* Given a suggested channel. */ + *pucSuggestChannel = ucChannelSelected; + } + + } while (FALSE); + + return fgIsResultAvailable; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \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; + ENUM_CHNL_EXT_T eTempSCO; + UINT_8 ucMaxBandwidth = MAX_BW_80_80_MHZ; /*chip capability*/ + + eSCO = CHNL_EXT_SCN; + eTempSCO = CHNL_EXT_SCN; + + if (prBssInfo->eBand == BAND_2G4) { + if (prBssInfo->ucPrimaryChannel != 14) + eSCO = (prBssInfo->ucPrimaryChannel > 7) ? CHNL_EXT_SCB : CHNL_EXT_SCA; + } else { + if (regd_is_single_sku_en()) { + if (rlmDomainIsLegalChannel(prAdapter, prBssInfo->eBand, + prBssInfo->ucPrimaryChannel)) + eSCO = MAP_SECONDATY_CHANNEL_5KHZ + ((UINT_32)prBssInfo->ucPrimaryChannel); + } 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 + CHNL_SPAN_20) : (prBssInfo->ucPrimaryChannel - CHNL_SPAN_20); + + if (!rlmDomainIsLegalChannel(prAdapter, prBssInfo->eBand, ucSecondChannel)) + eSCO = CHNL_EXT_SCN; + } + + /* Overwrite SCO settings by wifi cfg */ + if (IS_BSS_P2P(prBssInfo)) { + /* AP mode */ + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2PConnSettings[prBssInfo->u4PrivateData])) { + if (prAdapter->rWifiVar.ucApSco == CHNL_EXT_SCA || prAdapter->rWifiVar.ucApSco == CHNL_EXT_SCB) + eTempSCO = (ENUM_CHNL_EXT_T) prAdapter->rWifiVar.ucApSco; + } + /* P2P mode */ + else { + if (prAdapter->rWifiVar.ucP2pGoSco == CHNL_EXT_SCA || + prAdapter->rWifiVar.ucP2pGoSco == CHNL_EXT_SCB) { + eTempSCO = (ENUM_CHNL_EXT_T) prAdapter->rWifiVar.ucP2pGoSco; + } + } + + /* Check again if it is boundary channel and 40MHz BW is permitted */ + if (eTempSCO != CHNL_EXT_SCN) { + ucSecondChannel = (eTempSCO == CHNL_EXT_SCA) ? + (prBssInfo->ucPrimaryChannel + 4) : (prBssInfo->ucPrimaryChannel - 4); + if (rlmDomainIsLegalChannel(prAdapter, prBssInfo->eBand, ucSecondChannel)) + eSCO = eTempSCO; + } + } + + /* Overwrite SCO settings by wifi cfg bandwidth setting */ + if (IS_BSS_P2P(prBssInfo)) { + /* AP mode */ + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2PConnSettings[prBssInfo->u4PrivateData])) { + if (prBssInfo->eBand == BAND_2G4) + ucMaxBandwidth = prAdapter->rWifiVar.ucAp2gBandwidth; + else + ucMaxBandwidth = prAdapter->rWifiVar.ucAp5gBandwidth; + } + /* P2P mode */ + else { + if (prBssInfo->eBand == BAND_2G4) + ucMaxBandwidth = prAdapter->rWifiVar.ucP2p2gBandwidth; + else + ucMaxBandwidth = prAdapter->rWifiVar.ucP2p5gBandwidth; + } + + if (ucMaxBandwidth < MAX_BW_40MHZ) + eSCO = CHNL_EXT_SCN; + } + + return eSCO; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief: Get AP secondary channel offset from cfg80211 or wifi.cfg +* +* \param[in] prAdapter Pointer of ADAPTER_T, prBssInfo Pointer of BSS_INFO_T, +* +* \return ENUM_CHNL_EXT_T AP secondary channel offset +*/ +/*----------------------------------------------------------------------------*/ +ENUM_CHNL_EXT_T rlmGetScoForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) +{ + ENUM_BAND_T eBand; + UINT_8 ucChannel; + ENUM_CHNL_EXT_T eSCO; + INT_32 i4DeltaBw; + UINT_32 u4AndOneSCO; + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + P_P2P_CONNECTION_REQ_INFO_T prP2pConnReqInfo = (P_P2P_CONNECTION_REQ_INFO_T) NULL; + + prP2pRoleFsmInfo = p2pFuncGetRoleByBssIdx(prAdapter, prBssInfo->ucBssIndex); + + if (!prAdapter->rWifiVar.ucApChnlDefFromCfg && prP2pRoleFsmInfo) { + prP2pConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + eSCO = CHNL_EXT_SCN; + if (cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex) == MAX_BW_40MHZ) { + /* If BW 40, compare S0 and primary channel freq */ + if (prP2pConnReqInfo->u4CenterFreq1 > prP2pConnReqInfo->u2PriChnlFreq) + eSCO = CHNL_EXT_SCA; + else + eSCO = CHNL_EXT_SCB; + } else if (cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex) > MAX_BW_40MHZ) { + /* P: PriChnlFreq, A:CHNL_EXT_SCA, B: CHNL_EXT_SCB, -:BW SPAN 5M */ + /* --|----|--CenterFreq1--|----|-- */ + /* --|----|--CenterFreq1--B----P-- */ + /* --|----|--CenterFreq1--P----A-- */ + i4DeltaBw = prP2pConnReqInfo->u2PriChnlFreq - prP2pConnReqInfo->u4CenterFreq1; + u4AndOneSCO = CHNL_EXT_SCB; + eSCO = CHNL_EXT_SCA; + if (i4DeltaBw < 0) { + /* --|----|--CenterFreq1--|----|-- */ + /* --P----A--CenterFreq1--|----|-- */ + /* --B----P--CenterFreq1--|----|-- */ + u4AndOneSCO = CHNL_EXT_SCA; + eSCO = CHNL_EXT_SCB; + i4DeltaBw = -i4DeltaBw; + } + i4DeltaBw = i4DeltaBw - (CHANNEL_SPAN_20 >> 1); + if ((i4DeltaBw/CHANNEL_SPAN_20) & 1) + eSCO = u4AndOneSCO; + } + } else { + /* 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)) + eSCO = rlmDecideScoForAP(prAdapter, prBssInfo); + } + return eSCO; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief: Get AP channel number of Channel Center Frequency Segment 0 from cfg80211 or wifi.cfg +* +* \param[in] prAdapter Pointer of ADAPTER_T, prBssInfo Pointer of BSS_INFO_T, +* +* \return UINT_8 AP channel number of Channel Center Frequency Segment 0 +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 rlmGetVhtS1ForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) +{ + UINT_32 ucFreq1Channel; + UINT_8 ucPrimaryChannel = prBssInfo->ucPrimaryChannel; + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + P_P2P_CONNECTION_REQ_INFO_T prP2pConnReqInfo = (P_P2P_CONNECTION_REQ_INFO_T) NULL; + + prP2pRoleFsmInfo = p2pFuncGetRoleByBssIdx(prAdapter, prBssInfo->ucBssIndex); + + if (prBssInfo->ucVhtChannelWidth == VHT_OP_CHANNEL_WIDTH_20_40) + return 0; + + if (!prAdapter->rWifiVar.ucApChnlDefFromCfg && prP2pRoleFsmInfo) { + prP2pConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + ucFreq1Channel = nicFreq2ChannelNum(prP2pConnReqInfo->u4CenterFreq1 * 1000); + } else + ucFreq1Channel = nicGetVhtS1(ucPrimaryChannel, prBssInfo->ucVhtChannelWidth); + + return ucFreq1Channel; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_rlm_obss.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_rlm_obss.c new file mode 100644 index 0000000000000..8068cb7fff025 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_rlm_obss.c @@ -0,0 +1,360 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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); + + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prBssInfo->ucBssIndex, + prSwRfb->ucStaRecIdx, + WLAN_MAC_MGMT_HEADER_LEN, WLAN_MAC_MGMT_HEADER_HTC_LEN + 5, NULL, MSDU_RATE_MODE_AUTO); + + /* Send them to HW queue */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_role_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_role_fsm.c new file mode 100644 index 0000000000000..f0598ce59b147 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_role_fsm.c @@ -0,0 +1,2637 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#include "precomp.h" +#include "p2p_role_state.h" +#include "gl_p2p_os.h" + +#if 1 +/*lint -save -e64 Type mismatch */ +static PUINT_8 apucDebugP2pRoleState[P2P_ROLE_STATE_NUM] = { + (PUINT_8) DISP_STRING("P2P_ROLE_STATE_IDLE"), + (PUINT_8) DISP_STRING("P2P_ROLE_STATE_SCAN"), + (PUINT_8) DISP_STRING("P2P_ROLE_STATE_REQING_CHANNEL"), + (PUINT_8) DISP_STRING("P2P_ROLE_STATE_AP_CHNL_DETECTION"), +#if (CFG_SUPPORT_DFS_MASTER == 1) + (PUINT_8) DISP_STRING("P2P_ROLE_STATE_GC_JOIN"), + (PUINT_8) DISP_STRING("P2P_ROLE_STATE_DFS_CAC"), + (PUINT_8) DISP_STRING("P2P_ROLE_STATE_SWITCH_CHANNEL") +#else + (PUINT_8) DISP_STRING("P2P_ROLE_STATE_GC_JOIN") +#endif +}; + +/*lint -restore */ +#endif /* DBG */ + +VOID +p2pRoleFsmStateTransition(IN P_ADAPTER_T prAdapter, + IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo, IN ENUM_P2P_ROLE_STATE_T eNextState); + +UINT_8 p2pRoleFsmInit(IN P_ADAPTER_T prAdapter, IN UINT_8 ucRoleIdx) +{ + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_P2P_CHNL_REQ_INFO_T prP2pChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + ASSERT_BREAK(P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, ucRoleIdx) == NULL); + + prP2pRoleFsmInfo = kalMemAlloc(sizeof(P2P_ROLE_FSM_INFO_T), VIR_MEM_TYPE); + if (!prP2pRoleFsmInfo) { + DBGLOG(INIT, ERROR, + "Allocate p2p role fsm memory FAILED\n"); + break; + } + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, ucRoleIdx) = prP2pRoleFsmInfo; + + + ASSERT_BREAK(prP2pRoleFsmInfo != NULL); + + kalMemZero(prP2pRoleFsmInfo, sizeof(P2P_ROLE_FSM_INFO_T)); + + prP2pRoleFsmInfo->ucRoleIndex = ucRoleIdx; + + prP2pRoleFsmInfo->eCurrentState = P2P_ROLE_STATE_IDLE; + + prP2pRoleFsmInfo->u4P2pPacketFilter = PARAM_PACKET_FILTER_SUPPORTED; + + prP2pChnlReqInfo = &prP2pRoleFsmInfo->rChnlReqInfo; + LINK_INITIALIZE(&(prP2pChnlReqInfo->rP2pChnlReqLink)); + + cnmTimerInitTimer(prAdapter, + &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer), + (PFN_MGMT_TIMEOUT_FUNC) p2pRoleFsmRunEventTimeout, (ULONG) prP2pRoleFsmInfo); + +#if (CFG_SUPPORT_DFS_MASTER == 1) + cnmTimerInitTimer(prAdapter, + &(prP2pRoleFsmInfo->rDfsShutDownTimer), + (PFN_MGMT_TIMEOUT_FUNC) p2pRoleFsmRunEventDfsShutDownTimeout, + (ULONG) prP2pRoleFsmInfo); +#endif + + prP2pBssInfo = cnmGetBssInfoAndInit(prAdapter, NETWORK_TYPE_P2P, FALSE); + + if (!prP2pBssInfo) { + DBGLOG(P2P, ERROR, "Error allocating BSS Info Structure\n"); + break; + } + + BSS_INFO_INIT(prAdapter, prP2pBssInfo); + prP2pRoleFsmInfo->ucBssIndex = prP2pBssInfo->ucBssIndex; + + /* For state identify, not really used. */ + prP2pBssInfo->eIntendOPMode = OP_MODE_P2P_DEVICE; + + COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, prAdapter->rMyMacAddr); + /*prP2pBssInfo->aucOwnMacAddr[0] ^= 0x2;*/ /* change to local administrated address */ + prP2pBssInfo->aucOwnMacAddr[0] |= 0x2; + prP2pBssInfo->aucOwnMacAddr[0] ^= ucRoleIdx << 2; /* change to local administrated address */ + + /* For BSS_INFO back trace to P2P Role & get Role FSM. */ + prP2pBssInfo->u4PrivateData = ucRoleIdx; + + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2PConnSettings[ucRoleIdx])) { + prP2pBssInfo->ucConfigAdHocAPMode = AP_MODE_11G; + prP2pBssInfo->u2HwDefaultFixedRateCode = RATE_CCK_1M_LONG; + } else { + prP2pBssInfo->ucConfigAdHocAPMode = AP_MODE_11G_P2P; + prP2pBssInfo->u2HwDefaultFixedRateCode = 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 = STA_REC_INDEX_BMCAST; /* NULL STA_REC */ + prP2pBssInfo->prBeacon->ucBssIndex = prP2pBssInfo->ucBssIndex; + } else { + /* Out of memory. */ + ASSERT(FALSE); + } + + 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; + prP2pBssInfo->ucNss = wlanGetSupportNss(prAdapter, prP2pBssInfo->ucBssIndex); + prP2pBssInfo->eDBDCBand = ENUM_BAND_0; +#if (CFG_HW_WMM_BY_BSS == 0) + prP2pBssInfo->ucWmmQueSet = + (prAdapter->rWifiVar.ucDbdcMode == DBDC_MODE_DISABLED) ? DBDC_5G_WMM_INDEX : DBDC_2G_WMM_INDEX; +#endif + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) + prP2pBssInfo->fgIsQBSS = TRUE; + else + prP2pBssInfo->fgIsQBSS = FALSE; + +#if (CFG_SUPPORT_DFS_MASTER == 1) + p2pFuncRadarInfoInit(); +#endif + + /* SET_NET_PWR_STATE_IDLE(prAdapter, prP2pBssInfo->ucBssIndex); */ + + p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, P2P_ROLE_STATE_IDLE); + + } while (FALSE); + + if (prP2pBssInfo) + return prP2pBssInfo->ucBssIndex; + else + return P2P_DEV_BSS_INDEX; +} /* p2pFsmInit */ + +VOID p2pRoleFsmUninit(IN P_ADAPTER_T prAdapter, IN UINT_8 ucRoleIdx) +{ + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + DEBUGFUNC("p2pRoleFsmUninit()"); + DBGLOG(P2P, INFO, "->p2pRoleFsmUninit()\n"); + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, ucRoleIdx); + + ASSERT_BREAK(prP2pRoleFsmInfo != NULL); + + if (!prP2pRoleFsmInfo) + return; + + prP2pBssInfo = prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex]; + + p2pFuncDissolve(prAdapter, prP2pBssInfo, TRUE, REASON_CODE_DEAUTH_LEAVING_BSS); + + SET_NET_PWR_STATE_IDLE(prAdapter, prP2pBssInfo->ucBssIndex); + + /* Function Dissolve should already enter IDLE state. */ + p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, P2P_ROLE_STATE_IDLE); + + p2pRoleFsmRunEventAbort(prAdapter, prP2pRoleFsmInfo); + + /* Clear CmdQue */ + kalClearMgmtFramesByBssIdx(prAdapter->prGlueInfo, prP2pBssInfo->ucBssIndex); + kalClearSecurityFramesByBssIdx(prAdapter->prGlueInfo, prP2pBssInfo->ucBssIndex); + /* Clear PendingCmdQue */ + wlanReleasePendingCMDbyBssIdx(prAdapter, prP2pBssInfo->ucBssIndex); + /* Clear PendingTxMsdu */ + nicFreePendingTxMsduInfoByBssIdx(prAdapter, prP2pBssInfo->ucBssIndex); + + /* Deactivate BSS. */ + UNSET_NET_ACTIVE(prAdapter, prP2pRoleFsmInfo->ucBssIndex); + + nicDeactivateNetwork(prAdapter, prP2pRoleFsmInfo->ucBssIndex); + + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, ucRoleIdx) = NULL; + + if (prP2pBssInfo->prBeacon) { + cnmMgtPktFree(prAdapter, prP2pBssInfo->prBeacon); + prP2pBssInfo->prBeacon = NULL; + } + + cnmFreeBssInfo(prAdapter, prP2pBssInfo); + + /* ensure the timer be stopped */ + cnmTimerStopTimer(prAdapter, &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer)); + +#if (CFG_SUPPORT_DFS_MASTER == 1) + cnmTimerStopTimer(prAdapter, &(prP2pRoleFsmInfo->rDfsShutDownTimer)); +#endif + + if (prP2pRoleFsmInfo) + kalMemFree(prP2pRoleFsmInfo, VIR_MEM_TYPE, sizeof(P2P_ROLE_FSM_INFO_T)); + + } while (FALSE); + + return; +#if 0 + 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. + */ + kalClearMgmtFramesByBssIdx(prAdapter->prGlueInfo, NETWORK_TYPE_P2P_INDEX); + + /* Clear PendingCmdQue */ + wlanReleasePendingCMDbyBssIdx(prAdapter, NETWORK_TYPE_P2P_INDEX); + + if (prP2pBssInfo->prBeacon) { + cnmMgtPktFree(prAdapter, prP2pBssInfo->prBeacon); + prP2pBssInfo->prBeacon = NULL; + } + + } while (FALSE); + + return; +#endif +} /* p2pRoleFsmUninit */ + +VOID +p2pRoleFsmStateTransition(IN P_ADAPTER_T prAdapter, + IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo, IN ENUM_P2P_ROLE_STATE_T eNextState) +{ + BOOLEAN fgIsTransitionOut = (BOOLEAN) FALSE; + P_BSS_INFO_T prP2pRoleBssInfo = (P_BSS_INFO_T) NULL; + + prP2pRoleBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prP2pRoleFsmInfo->ucBssIndex); + + do { + if (!IS_BSS_ACTIVE(prP2pRoleBssInfo)) { + if (!cnmP2PIsPermitted(prAdapter)) + return; + + SET_NET_ACTIVE(prAdapter, prP2pRoleBssInfo->ucBssIndex); + nicActivateNetwork(prAdapter, prP2pRoleBssInfo->ucBssIndex); + } + + fgIsTransitionOut = fgIsTransitionOut ? FALSE : TRUE; + + if (!fgIsTransitionOut) { + DBGLOG(P2P, STATE, "[P2P_ROLE][%d]TRANSITION(Bss%d): [%s] -> [%s]\n", + prP2pRoleFsmInfo->ucRoleIndex, + prP2pRoleFsmInfo->ucBssIndex, + apucDebugP2pRoleState[prP2pRoleFsmInfo->eCurrentState], + apucDebugP2pRoleState[eNextState]); + + /* Transition into current state. */ + prP2pRoleFsmInfo->eCurrentState = eNextState; + } + + switch (prP2pRoleFsmInfo->eCurrentState) { + case P2P_ROLE_STATE_IDLE: + if (!fgIsTransitionOut) + p2pRoleStateInit_IDLE(prAdapter, prP2pRoleFsmInfo, prP2pRoleBssInfo); + else + p2pRoleStateAbort_IDLE(prAdapter, prP2pRoleFsmInfo, &(prP2pRoleFsmInfo->rChnlReqInfo)); + break; + case P2P_ROLE_STATE_SCAN: + if (!fgIsTransitionOut) { + p2pRoleStateInit_SCAN(prAdapter, prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rScanReqInfo)); + } else { + p2pRoleStateAbort_SCAN(prAdapter, prP2pRoleFsmInfo); + } + break; + case P2P_ROLE_STATE_REQING_CHANNEL: + if (!fgIsTransitionOut) { + p2pRoleStateInit_REQING_CHANNEL(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rChnlReqInfo)); + } else { + p2pRoleStateAbort_REQING_CHANNEL(prAdapter, prP2pRoleBssInfo, + prP2pRoleFsmInfo, eNextState); + } + break; + case P2P_ROLE_STATE_AP_CHNL_DETECTION: + if (!fgIsTransitionOut) { + p2pRoleStateInit_AP_CHNL_DETECTION(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rScanReqInfo), + &(prP2pRoleFsmInfo->rConnReqInfo)); + } else { + p2pRoleStateAbort_AP_CHNL_DETECTION(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rConnReqInfo), + &(prP2pRoleFsmInfo->rChnlReqInfo), + &(prP2pRoleFsmInfo->rScanReqInfo), eNextState); + } + break; + case P2P_ROLE_STATE_GC_JOIN: + if (!fgIsTransitionOut) { + p2pRoleStateInit_GC_JOIN(prAdapter, + prP2pRoleFsmInfo, &(prP2pRoleFsmInfo->rChnlReqInfo)); + } else { + p2pRoleStateAbort_GC_JOIN(prAdapter, + prP2pRoleFsmInfo, &(prP2pRoleFsmInfo->rJoinInfo), eNextState); + } + break; + +#if (CFG_SUPPORT_DFS_MASTER == 1) + case P2P_ROLE_STATE_DFS_CAC: + if (!fgIsTransitionOut) { + p2pRoleStateInit_DFS_CAC(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rChnlReqInfo)); + } else { + p2pRoleStateAbort_DFS_CAC(prAdapter, prP2pRoleBssInfo, + prP2pRoleFsmInfo, eNextState); + } + break; + case P2P_ROLE_STATE_SWITCH_CHANNEL: + if (!fgIsTransitionOut) { + p2pRoleStateInit_SWITCH_CHANNEL(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rChnlReqInfo)); + } else { + p2pRoleStateAbort_SWITCH_CHANNEL(prAdapter, prP2pRoleBssInfo, + prP2pRoleFsmInfo, eNextState); + } + break; +#endif + default: + ASSERT(FALSE); + break; + } + } while (fgIsTransitionOut); + +} /* p2pRoleFsmStateTransition */ + +VOID p2pRoleFsmRunEventTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr) +{ + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) ulParamPtr; + P_P2P_CHNL_REQ_INFO_T prP2pChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pRoleFsmInfo != NULL)); + + switch (prP2pRoleFsmInfo->eCurrentState) { + case P2P_ROLE_STATE_IDLE: + prP2pChnlReqInfo = &(prP2pRoleFsmInfo->rChnlReqInfo); + if (prP2pChnlReqInfo->fgIsChannelRequested) { + p2pFuncReleaseCh(prAdapter, prP2pRoleFsmInfo->ucBssIndex, prP2pChnlReqInfo); + if (IS_NET_PWR_STATE_IDLE(prAdapter, prP2pRoleFsmInfo->ucBssIndex)) + ASSERT(FALSE); + } + + if (IS_NET_PWR_STATE_IDLE(prAdapter, prP2pRoleFsmInfo->ucBssIndex)) { + DBGLOG(P2P, TRACE, "Role BSS IDLE, deactive network.\n"); + UNSET_NET_ACTIVE(prAdapter, prP2pRoleFsmInfo->ucBssIndex); + nicDeactivateNetwork(prAdapter, prP2pRoleFsmInfo->ucBssIndex); + nicUpdateBss(prAdapter, prP2pRoleFsmInfo->ucBssIndex); + } + break; + case P2P_ROLE_STATE_GC_JOIN: + DBGLOG(P2P, ERROR, + "Current P2P Role State P2P_ROLE_STATE_GC_JOIN is unexpected for FSM timeout event.\n"); + break; +#if (CFG_SUPPORT_DFS_MASTER == 1) + case P2P_ROLE_STATE_DFS_CAC: + p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, P2P_ROLE_STATE_IDLE); + kalP2PCacFinishedUpdate(prAdapter->prGlueInfo, prP2pRoleFsmInfo->ucRoleIndex); + p2pFuncSetDfsState(DFS_STATE_ACTIVE); + cnmTimerStartTimer(prAdapter, &(prP2pRoleFsmInfo->rDfsShutDownTimer), 5000); + break; +#endif + default: + DBGLOG(P2P, ERROR, + "Current P2P Role State %d is unexpected for FSM timeout event.\n", + prP2pRoleFsmInfo->eCurrentState); + ASSERT(FALSE); + break; + } + } while (FALSE); +} /* p2pRoleFsmRunEventTimeout */ + +static VOID +p2pRoleFsmDeauhComplete(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + ENUM_PARAM_MEDIA_STATE_T eOriMediaStatus; + + if (!prAdapter) { + DBGLOG(P2P, ERROR, "prAdapter shouldn't be NULL!\n"); + return; + } + + if (!prStaRec) { + DBGLOG(P2P, ERROR, "prStaRec shouldn't be NULL!\n"); + return; + } + + DBGLOG(P2P, INFO, "Deauth TX Complete!\n"); + + prP2pBssInfo = prAdapter->aprBssInfo[prStaRec->ucBssIndex]; + ASSERT_BREAK(prP2pBssInfo != NULL); + eOriMediaStatus = prP2pBssInfo->eConnectionState; + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, prP2pBssInfo->u4PrivateData); + + ASSERT_BREAK(prP2pRoleFsmInfo != NULL); + + /* Change station state. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + /* Reset Station Record Status. */ + p2pFuncResetStaRecStatus(prAdapter, prStaRec); + + /* Try to remove StaRec in BSS client list before free it */ + bssRemoveClient(prAdapter, prP2pBssInfo, prStaRec); + + /* STA_RECORD free */ + cnmStaRecFree(prAdapter, prStaRec); + + if ((prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) || + (bssGetClientCount(prAdapter, prP2pBssInfo) == 0)) { + if (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) + DBGLOG(P2P, TRACE, "No More Client, Media Status DISCONNECTED\n"); + else + DBGLOG(P2P, TRACE, "Deauth done, Media Status DISCONNECTED\n"); + p2pChangeMediaState(prAdapter, prP2pBssInfo, PARAM_MEDIA_STATE_DISCONNECTED); + } + + /* STOP BSS if power is IDLE */ + if (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + if (IS_NET_PWR_STATE_IDLE(prAdapter, prP2pRoleFsmInfo->ucBssIndex) && + (bssGetClientCount(prAdapter, prP2pBssInfo) == 0)) { + /* All Peer disconnected !! Stop BSS now!! */ + p2pFuncStopComplete(prAdapter, prP2pBssInfo); + } else if (eOriMediaStatus != prP2pBssInfo->eConnectionState) + /* Update the Media State if necessary */ + nicUpdateBss(prAdapter, prP2pBssInfo->ucBssIndex); + } else + p2pFuncStopComplete(prAdapter, prP2pBssInfo);/* GC : Stop BSS when Deauth done */ + +} + +VOID p2pRoleFsmDeauthTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr) +{ + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) ulParamPtr; + + p2pRoleFsmDeauhComplete(prAdapter, prStaRec); +} /* p2pRoleFsmRunEventTimeout */ + +VOID p2pRoleFsmRunEventAbort(IN P_ADAPTER_T prAdapter, IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo) +{ + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pRoleFsmInfo != NULL)); + + if (prP2pRoleFsmInfo->eCurrentState != P2P_ROLE_STATE_IDLE) { + /* Get into IDLE state. */ + p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, P2P_ROLE_STATE_IDLE); + } + + /* Abort IDLE. */ + p2pRoleStateAbort_IDLE(prAdapter, prP2pRoleFsmInfo, &(prP2pRoleFsmInfo->rChnlReqInfo)); + + } while (FALSE); +} /* p2pRoleFsmRunEventAbort */ + +WLAN_STATUS +p2pRoleFsmRunEventDeauthTxDone(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; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + DBGLOG(P2P, INFO, "Deauth TX Done,rTxDoneStatus = %d\n", rTxDoneStatus); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (prStaRec == NULL) { + DBGLOG(P2P, TRACE, "Station Record NULL, Index:%d\n", prMsduInfo->ucStaRecIndex); + break; + } + + p2pRoleFsmDeauhComplete(prAdapter, prStaRec); + /* Avoid re-entry */ + cnmTimerStopTimer(prAdapter, &(prStaRec->rDeauthTxDoneTimer)); + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; + +} /* p2pRoleFsmRunEventDeauthTxDone */ + +VOID p2pRoleFsmRunEventRxDeauthentication(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; + BOOLEAN fgSendDeauth = FALSE; /* flag to send deauth when rx sta disassc/deauth */ + + do { + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + + if (prStaRec == NULL) + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (!prStaRec) + break; + + prP2pBssInfo = prAdapter->aprBssInfo[prStaRec->ucBssIndex]; + + 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); + + +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) +/* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + (UINT_8) prP2pBssInfo->u4PrivateData, NULL, + prDeauthFrame->aucInfoElem, u2IELength, u2ReasonCode, + WLAN_STATUS_MEDIA_DISCONNECT); + +#else +/* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + (UINT_8) prP2pBssInfo->u4PrivateData, NULL, + prDeauthFrame->aucInfoElem, u2IELength, u2ReasonCode); +#endif + + prP2pBssInfo->prStaRecOfAP = NULL; + + p2pFuncDisconnect(prAdapter, prP2pBssInfo, prStaRec, FALSE, u2ReasonCode); + + p2pFuncStopComplete(prAdapter, prP2pBssInfo); + + SET_NET_PWR_STATE_IDLE(prAdapter, prP2pBssInfo->ucBssIndex); + + p2pRoleFsmStateTransition(prAdapter, + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData), + P2P_ROLE_STATE_IDLE); + } + break; + case OP_MODE_ACCESS_POINT: + /* Delete client from client list. */ + if (authProcessRxDeauthFrame(prSwRfb, + prP2pBssInfo->aucBSSID, &u2ReasonCode) == WLAN_STATUS_SUCCESS) { + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + if (HAL_RX_STATUS_IS_CIPHER_MISMATCH(prSwRfb->prRxStatus) || + HAL_RX_STATUS_IS_CLM_ERROR(prSwRfb->prRxStatus)) { + /* if cipher mismatch, or incorrect encrypt, just drop */ + DBGLOG(P2P, ERROR, "Rx deauth CM/CLM=1\n"); + return; + } + + /* 4.3.3.1 send unprotected deauth reason 6/7 */ + DBGLOG(P2P, INFO, "deauth reason=6\n"); + fgSendDeauth = TRUE; + u2ReasonCode = REASON_CODE_CLASS_2_ERR; + prStaRec->rPmfCfg.fgRxDeauthResp = TRUE; + } +#endif + + if (bssRemoveClient(prAdapter, prP2pBssInfo, prStaRec)) { + /* Indicate disconnect to Host. */ + p2pFuncDisconnect(prAdapter, prP2pBssInfo, prStaRec, fgSendDeauth, + u2ReasonCode); + /* Deactive BSS if PWR is IDLE and no peer */ + if (IS_NET_PWR_STATE_IDLE(prAdapter, prP2pBssInfo->ucBssIndex) && + (bssGetClientCount(prAdapter, prP2pBssInfo) == 0)) { + /* All Peer disconnected !! Stop BSS now!! */ + p2pFuncStopComplete(prAdapter, prP2pBssInfo); + } + } + } + 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); +} /* p2pRoleFsmRunEventRxDeauthentication */ + +VOID p2pRoleFsmRunEventRxDisassociation(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; + BOOLEAN fgSendDeauth = FALSE; /* flag to send deauth when rx sta disassc/deauth */ + + + if (prStaRec == NULL) + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (!prStaRec) { + DBGLOG(P2P, ERROR, "prStaRec of prSwRfb->ucStaRecIdx %d is NULL!\n", + prSwRfb->ucStaRecIdx); + return; + } + + prP2pBssInfo = prAdapter->aprBssInfo[prStaRec->ucBssIndex]; + + if (prStaRec->ucStaState == STA_STATE_1) + return; + + 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); + +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) + /* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + (UINT_8) prP2pBssInfo->u4PrivateData, NULL, + prDisassocFrame->aucInfoElem, + u2IELength, prStaRec->u2ReasonCode, + WLAN_STATUS_MEDIA_DISCONNECT); + +#else + /* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + (UINT_8) prP2pBssInfo->u4PrivateData, NULL, + prDisassocFrame->aucInfoElem, + u2IELength, prStaRec->u2ReasonCode); +#endif + + prP2pBssInfo->prStaRecOfAP = NULL; + + p2pFuncDisconnect(prAdapter, prP2pBssInfo, prStaRec, FALSE, prStaRec->u2ReasonCode); + + p2pFuncStopComplete(prAdapter, prP2pBssInfo); + + SET_NET_PWR_STATE_IDLE(prAdapter, prP2pBssInfo->ucBssIndex); + + p2pRoleFsmStateTransition(prAdapter, + P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, + prP2pBssInfo->u4PrivateData), + P2P_ROLE_STATE_IDLE); + } + break; + case OP_MODE_ACCESS_POINT: + /* Delete client from client list. */ + if (assocProcessRxDisassocFrame(prAdapter, + prSwRfb, + prP2pBssInfo->aucBSSID, &u2ReasonCode) == WLAN_STATUS_SUCCESS) { + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + if (HAL_RX_STATUS_IS_CIPHER_MISMATCH(prSwRfb->prRxStatus) || + HAL_RX_STATUS_IS_CLM_ERROR(prSwRfb->prRxStatus)) { + /* if cipher mismatch, or incorrect encrypt, just drop */ + DBGLOG(P2P, ERROR, "Rx disassoc CM/CLM=1\n"); + return; + } + + /* 4.3.3.1 send unprotected deauth reason 6/7 */ + DBGLOG(P2P, INFO, "deauth reason=6\n"); + fgSendDeauth = TRUE; + u2ReasonCode = REASON_CODE_CLASS_2_ERR; + prStaRec->rPmfCfg.fgRxDeauthResp = TRUE; + } +#endif + + if (bssRemoveClient(prAdapter, prP2pBssInfo, prStaRec)) { + /* Indicate disconnect to Host. */ + p2pFuncDisconnect(prAdapter, prP2pBssInfo, prStaRec, fgSendDeauth, + u2ReasonCode); + /* Deactive BSS if PWR is IDLE and no peer */ + if (IS_NET_PWR_STATE_IDLE(prAdapter, prP2pBssInfo->ucBssIndex) && + (bssGetClientCount(prAdapter, prP2pBssInfo) == 0)) { + /* All Peer disconnected !! Stop BSS now!! */ + p2pFuncStopComplete(prAdapter, prP2pBssInfo); + } + + } + } + break; + case OP_MODE_P2P_DEVICE: + default: + ASSERT(FALSE); + break; + } + +} /* p2pRoleFsmRunEventRxDisassociation */ + +VOID p2pRoleFsmRunEventBeaconTimeout(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo) +{ + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, prP2pBssInfo->u4PrivateData); + + /* Only client mode would have beacon lost event. */ + if (prP2pBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) { + DBGLOG(P2P, ERROR, + "Error case, P2P BSS %d not INFRA mode but beacon timeout\n", + prP2pRoleFsmInfo->ucRoleIndex); + break; + } + + DBGLOG(P2P, TRACE, + "p2pFsmRunEventBeaconTimeout: BSS %d Beacon Timeout\n", prP2pRoleFsmInfo->ucRoleIndex); + + if (prP2pBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) + /* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, + NULL, NULL, 0, REASON_CODE_DISASSOC_INACTIVITY, + WLAN_STATUS_MEDIA_DISCONNECT); + + +#else + /* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, + NULL, NULL, 0, REASON_CODE_DISASSOC_INACTIVITY); +#endif + + if (prP2pBssInfo->prStaRecOfAP != NULL) { + P_STA_RECORD_T prStaRec = prP2pBssInfo->prStaRecOfAP; + + prP2pBssInfo->prStaRecOfAP = NULL; + + p2pFuncDisconnect(prAdapter, prP2pBssInfo, prStaRec, FALSE, + REASON_CODE_DISASSOC_LEAVING_BSS); + + SET_NET_PWR_STATE_IDLE(prAdapter, prP2pBssInfo->ucBssIndex); + /* 20120830 moved into p2pFuncDisconnect() */ + /* cnmStaRecFree(prAdapter, prP2pBssInfo->prStaRecOfAP); */ + p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, P2P_ROLE_STATE_IDLE); + + } + } + } while (FALSE); +} /* p2pFsmRunEventBeaconTimeout */ + +/*================== Message Event ==================*/ +VOID p2pRoleFsmRunEventStartAP(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + P_MSG_P2P_START_AP_T prP2pStartAPMsg = (P_MSG_P2P_START_AP_T) NULL; + P_P2P_CONNECTION_REQ_INFO_T prP2pConnReqInfo = (P_P2P_CONNECTION_REQ_INFO_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; +#if CFG_SUPPORT_DBDC + CNM_DBDC_CAP_T rDbdcCap; +#endif /*CFG_SUPPORT_DBDC*/ + + DBGLOG(P2P, INFO, "p2pRoleFsmRunEventStartAP\n"); + + prP2pStartAPMsg = (P_MSG_P2P_START_AP_T) prMsgHdr; + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, prP2pStartAPMsg->ucRoleIdx); + + DBGLOG(P2P, INFO, "p2pRoleFsmRunEventStartAP with Role(%d)\n", prP2pStartAPMsg->ucRoleIdx); + + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, ERROR, + "p2pRoleFsmRunEventStartAP: Corresponding P2P Role FSM empty: %d.\n", + prP2pStartAPMsg->ucRoleIdx); + goto error; + } + + prP2pBssInfo = prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex]; + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo[prP2pBssInfo->u4PrivateData]; + prP2pConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + + if (prP2pStartAPMsg->u4BcnInterval) { + DBGLOG(P2P, TRACE, "Beacon interval updated to :%u\n", + prP2pStartAPMsg->u4BcnInterval); + prP2pBssInfo->u2BeaconInterval = (UINT_16) prP2pStartAPMsg->u4BcnInterval; + } else if (prP2pBssInfo->u2BeaconInterval == 0) { + prP2pBssInfo->u2BeaconInterval = DOT11_BEACON_PERIOD_DEFAULT; + } + + if (prP2pStartAPMsg->u4DtimPeriod) { + DBGLOG(P2P, TRACE, "DTIM interval updated to :%u\n", + prP2pStartAPMsg->u4DtimPeriod); + prP2pBssInfo->ucDTIMPeriod = (UINT_8) prP2pStartAPMsg->u4DtimPeriod; + } else if (prP2pBssInfo->ucDTIMPeriod == 0) { + prP2pBssInfo->ucDTIMPeriod = DOT11_DTIM_PERIOD_DEFAULT; + } + + if (prP2pStartAPMsg->u2SsidLen != 0) { + kalMemCopy(prP2pConnReqInfo->rSsidStruct.aucSsid, prP2pStartAPMsg->aucSsid, + prP2pStartAPMsg->u2SsidLen); + prP2pConnReqInfo->rSsidStruct.ucSsidLen = + prP2pSpecificBssInfo->u2GroupSsidLen = prP2pStartAPMsg->u2SsidLen; + kalMemCopy(prP2pSpecificBssInfo->aucGroupSsid, prP2pStartAPMsg->aucSsid, + prP2pStartAPMsg->u2SsidLen); + } + + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2PConnSettings[prP2pStartAPMsg->ucRoleIdx])) { + prP2pConnReqInfo->eConnRequest = P2P_CONNECTION_TYPE_PURE_AP; + + /* Overwrite AP channel */ + if (prAdapter->rWifiVar.ucApChannel && + prAdapter->rWifiVar.ucApChnlDefFromCfg) { + prP2pConnReqInfo->rChannelInfo.ucChannelNum = prAdapter->rWifiVar.ucApChannel; + + if (prAdapter->rWifiVar.ucApChannel <= 14) + prP2pConnReqInfo->rChannelInfo.eBand = BAND_2G4; + else + prP2pConnReqInfo->rChannelInfo.eBand = BAND_5G; + } + } else { + prP2pConnReqInfo->eConnRequest = P2P_CONNECTION_TYPE_GO; + } + + /* The supplicant may start AP before rP2pRoleFsmTimeoutTimer is time out */ + /* We need to make sure the BSS was deactivated and all StaRec can be free */ + if (timerPendingTimer(&(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer))) { + /* call p2pRoleFsmRunEventTimeout() to deactive BSS and free channel */ + p2pRoleFsmRunEventTimeout(prAdapter, (ULONG)prP2pRoleFsmInfo); + cnmTimerStopTimer(prAdapter, &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer)); + } + +#if (CFG_SUPPORT_DFS_MASTER == 1) + if (timerPendingTimer(&(prP2pRoleFsmInfo->rDfsShutDownTimer))) { + DBGLOG(P2P, INFO, "p2pRoleFsmRunEventStartAP: Stop DFS shut down timer.\n"); + cnmTimerStopTimer(prAdapter, &(prP2pRoleFsmInfo->rDfsShutDownTimer)); + } +#endif + +#if (CFG_HW_WMM_BY_BSS == 1) + if (prP2pBssInfo->fgIsWmmInited == FALSE) + prP2pBssInfo->ucWmmQueSet = cnmWmmIndexDecision(prAdapter, prP2pBssInfo); + prP2pBssInfo->eBand = prP2pConnReqInfo->rChannelInfo.eBand; +#endif +#if CFG_SUPPORT_DBDC + cnmDbdcEnableDecision(prAdapter, prP2pBssInfo->ucBssIndex, prP2pConnReqInfo->rChannelInfo.eBand); + cnmGetDbdcCapability(prAdapter, + prP2pBssInfo->ucBssIndex, + prP2pConnReqInfo->rChannelInfo.eBand, + prP2pConnReqInfo->rChannelInfo.ucChannelNum, + wlanGetSupportNss(prAdapter, prP2pBssInfo->ucBssIndex), + &rDbdcCap); + + DBGLOG(P2P, INFO, + "p2pRoleFsmRunEventStartAP: start AP at CH %u NSS=%u.\n", + prP2pConnReqInfo->rChannelInfo.ucChannelNum, + rDbdcCap.ucNss); + + prP2pBssInfo->eDBDCBand = ENUM_BAND_AUTO; + prP2pBssInfo->ucNss = rDbdcCap.ucNss; +#if (CFG_HW_WMM_BY_BSS == 0) + prP2pBssInfo->ucWmmQueSet = rDbdcCap.ucWmmSetIndex; +#endif +#endif /*CFG_SUPPORT_DBDC*/ + prP2pBssInfo->eHiddenSsidType = prP2pStartAPMsg->ucHiddenSsidType; + + /* + *beacon content is related with Nss number , + *need to update because of modification + */ + bssUpdateBeaconContent(prAdapter, prP2pBssInfo->ucBssIndex); + + if ((prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) || + (prP2pBssInfo->eIntendOPMode != OP_MODE_NUM)) { + /* 1. No switch to AP mode. + * 2. Not started yet. + */ + + if (prP2pRoleFsmInfo->eCurrentState != P2P_ROLE_STATE_AP_CHNL_DETECTION && + prP2pRoleFsmInfo->eCurrentState != P2P_ROLE_STATE_IDLE) { + /* Make sure the state is in IDLE state. */ + p2pRoleFsmRunEventAbort(prAdapter, prP2pRoleFsmInfo); + } else if (prP2pRoleFsmInfo->eCurrentState == P2P_ROLE_STATE_AP_CHNL_DETECTION) { + goto error; + } + + /* Leave IDLE state. */ + SET_NET_PWR_STATE_ACTIVE(prAdapter, prP2pBssInfo->ucBssIndex); + + prP2pBssInfo->eIntendOPMode = OP_MODE_ACCESS_POINT; + +#if 0 + prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.ucChannelNum = 8; + prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.eBand = BAND_2G4; + /*prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.ucBandwidth = 0;*/ + /*prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.eSCO= CHNL_EXT_SCN;*/ +#endif + + if (prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.ucChannelNum != 0) { + DBGLOG(P2P, INFO, "Role(%d) StartAP at CH(%d)\n", + prP2pStartAPMsg->ucRoleIdx, + prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.ucChannelNum); + + p2pRoleStatePrepare_To_REQING_CHANNEL_STATE(prAdapter, + GET_BSS_INFO_BY_INDEX(prAdapter, + prP2pRoleFsmInfo->ucBssIndex), + &(prP2pRoleFsmInfo->rConnReqInfo), + &(prP2pRoleFsmInfo->rChnlReqInfo)); + p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, P2P_ROLE_STATE_REQING_CHANNEL); + } else { + DBGLOG(P2P, INFO, "Role(%d) StartAP Scan for working channel\n", + prP2pStartAPMsg->ucRoleIdx); + + /* For AP/GO mode with specific channel or non-specific channel. */ + p2pRoleFsmStateTransition(prAdapter, + prP2pRoleFsmInfo, P2P_ROLE_STATE_AP_CHNL_DETECTION); + } + } + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pRoleFsmRunEventStartAP */ + + +VOID p2pRoleFsmRunEventDelIface(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_MSG_P2P_DEL_IFACE_T prP2pDelIfaceMsg = (P_MSG_P2P_DEL_IFACE_T) NULL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + UINT_8 ucRoleIdx; + P_GL_P2P_INFO_T prP2pInfo = (P_GL_P2P_INFO_T) NULL; + + + DBGLOG(P2P, INFO, "p2pRoleFsmRunEventDelIface\n"); + + prGlueInfo = prAdapter->prGlueInfo; + if (prGlueInfo == NULL) { + DBGLOG(P2P, ERROR, "prGlueInfo shouldn't be NULL!\n"); + goto error; + } + + prP2pDelIfaceMsg = (P_MSG_P2P_DEL_IFACE_T) prMsgHdr; + ucRoleIdx = prP2pDelIfaceMsg->ucRoleIdx; + prAdapter = prGlueInfo->prAdapter; + prP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx]; + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, ucRoleIdx); + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, ERROR, + "p2pRoleFsmRunEventDelIface: Corresponding P2P Role FSM empty: %d.\n", + prP2pDelIfaceMsg->ucRoleIdx); + goto error; + } + + prP2pBssInfo = prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex]; + + /* The state is in disconnecting and can not change any BSS status */ + if (IS_NET_PWR_STATE_IDLE(prAdapter, prP2pBssInfo->ucBssIndex) && + IS_NET_ACTIVE(prAdapter, prP2pBssInfo->ucBssIndex)) { + DBGLOG(P2P, TRACE, "under deauth procedure, Quit.\n"); + } else { + /*p2pFuncDissolve(prAdapter, prP2pBssInfo, TRUE, REASON_CODE_DEAUTH_LEAVING_BSS);*/ + + SET_NET_PWR_STATE_IDLE(prAdapter, prP2pBssInfo->ucBssIndex); + + /* Function Dissolve should already enter IDLE state. */ + p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, P2P_ROLE_STATE_IDLE); + + p2pRoleFsmRunEventAbort(prAdapter, prP2pRoleFsmInfo); + + /* Clear CmdQue */ + kalClearMgmtFramesByBssIdx(prAdapter->prGlueInfo, prP2pBssInfo->ucBssIndex); + kalClearSecurityFramesByBssIdx(prAdapter->prGlueInfo, prP2pBssInfo->ucBssIndex); + /* Clear PendingCmdQue */ + wlanReleasePendingCMDbyBssIdx(prAdapter, prP2pBssInfo->ucBssIndex); + /* Clear PendingTxMsdu */ + nicFreePendingTxMsduInfoByBssIdx(prAdapter, prP2pBssInfo->ucBssIndex); + + /* Deactivate BSS. */ + UNSET_NET_ACTIVE(prAdapter, prP2pRoleFsmInfo->ucBssIndex); + + nicDeactivateNetwork(prAdapter, prP2pRoleFsmInfo->ucBssIndex); + nicUpdateBss(prAdapter, prP2pRoleFsmInfo->ucBssIndex); + } + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pRoleFsmRunEventStartAP */ + + +VOID p2pRoleFsmRunEventStopAP(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 prP2pSwitchMode = (P_MSG_P2P_SWITCH_OP_MODE_T) NULL; + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + P_STA_RECORD_T prCurrStaRec; + P_LINK_T prClientList; + + prP2pSwitchMode = (P_MSG_P2P_SWITCH_OP_MODE_T) prMsgHdr; + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, prP2pSwitchMode->ucRoleIdx); + + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, ERROR, + "p2pRoleFsmRunEventStopAP: Corresponding P2P Role FSM empty: %d.\n", + prP2pSwitchMode->ucRoleIdx); + goto error; + } + + prP2pBssInfo = prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex]; + + if (!prP2pBssInfo) { + DBGLOG(P2P, ERROR, + "prP2pBssInfo of prP2pRoleFsmInfo->ucBssIndex %d is NULL!\n", + prP2pRoleFsmInfo->ucBssIndex); + goto error; + } + +#if (CFG_SUPPORT_DFS_MASTER == 1) + p2pFuncSetDfsState(DFS_STATE_INACTIVE); + p2pFuncStopRdd(prAdapter, prP2pBssInfo->ucBssIndex); +#endif + + if (prP2pRoleFsmInfo->eCurrentState != P2P_ROLE_STATE_REQING_CHANNEL) { + p2pFuncStopGO(prAdapter, prP2pBssInfo); + + /* Start all Deauth done timer for all client */ + prClientList = &prP2pBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH_ENTRY(prCurrStaRec, prClientList, rLinkEntry, STA_RECORD_T) { + ASSERT(prCurrStaRec); + /* Do not restart timer if the timer is pending, */ + /* (start in p2pRoleFsmRunEventConnectionAbort()) */ + if (!timerPendingTimer(&(prCurrStaRec->rDeauthTxDoneTimer))) { + cnmTimerInitTimer(prAdapter, + &(prCurrStaRec->rDeauthTxDoneTimer), + (PFN_MGMT_TIMEOUT_FUNC) p2pRoleFsmDeauthTimeout, + (ULONG) prCurrStaRec); + + cnmTimerStartTimer(prAdapter, &(prCurrStaRec->rDeauthTxDoneTimer), + P2P_DEAUTH_TIMEOUT_TIME_MS); + } + } + } + + SET_NET_PWR_STATE_IDLE(prAdapter, prP2pBssInfo->ucBssIndex); + + p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, P2P_ROLE_STATE_IDLE); + +error: + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pRoleFsmRunEventStopAP */ + +#if (CFG_SUPPORT_DFS_MASTER == 1) +VOID p2pRoleFsmRunEventDfsCac(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + P_MSG_P2P_DFS_CAC_T prP2pDfsCacMsg = (P_MSG_P2P_DFS_CAC_T) NULL; + P_P2P_CONNECTION_REQ_INFO_T prP2pConnReqInfo = (P_P2P_CONNECTION_REQ_INFO_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + ENUM_CHANNEL_WIDTH_T rChannelWidth; +#if CFG_SUPPORT_DBDC + CNM_DBDC_CAP_T rDbdcCap; +#endif /*CFG_SUPPORT_DBDC*/ + + + DBGLOG(P2P, INFO, "p2pRoleFsmRunEventDfsCac\n"); + + prP2pDfsCacMsg = (P_MSG_P2P_DFS_CAC_T) prMsgHdr; + + rChannelWidth = prP2pDfsCacMsg->eChannelWidth; + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, prP2pDfsCacMsg->ucRoleIdx); + + DBGLOG(P2P, INFO, "p2pRoleFsmRunEventDfsCac with Role(%d)\n", prP2pDfsCacMsg->ucRoleIdx); + + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, ERROR, + "p2pRoleFsmRunEventDfsCac: Corresponding P2P Role FSM empty: %d.\n", + prP2pDfsCacMsg->ucRoleIdx); + goto error; + } + + if (timerPendingTimer(&(prP2pRoleFsmInfo->rDfsShutDownTimer))) { + DBGLOG(P2P, INFO, "p2pRoleFsmRunEventDfsCac: Stop DFS shut down timer.\n"); + cnmTimerStopTimer(prAdapter, &(prP2pRoleFsmInfo->rDfsShutDownTimer)); + } + + prP2pBssInfo = prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex]; + + prP2pConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2PConnSettings[prP2pDfsCacMsg->ucRoleIdx])) + prP2pConnReqInfo->eConnRequest = P2P_CONNECTION_TYPE_PURE_AP; + else + prP2pConnReqInfo->eConnRequest = P2P_CONNECTION_TYPE_GO; + +#if (CFG_HW_WMM_BY_BSS == 1) + if (prP2pBssInfo->fgIsWmmInited == FALSE) + prP2pBssInfo->ucWmmQueSet = cnmWmmIndexDecision(prAdapter, prP2pBssInfo); + prP2pBssInfo->eBand = prP2pConnReqInfo->rChannelInfo.eBand; +#endif +#if CFG_SUPPORT_DBDC + cnmDbdcEnableDecision(prAdapter, prP2pBssInfo->ucBssIndex, prP2pConnReqInfo->rChannelInfo.eBand); + cnmGetDbdcCapability(prAdapter, + prP2pBssInfo->ucBssIndex, + prP2pConnReqInfo->rChannelInfo.eBand, + prP2pConnReqInfo->rChannelInfo.ucChannelNum, + prAdapter->rWifiVar.ucNSS, + &rDbdcCap); + + DBGLOG(P2P, INFO, + "p2pRoleFsmRunEventDfsCac: Set channel at CH %u.\n", + prP2pConnReqInfo->rChannelInfo.ucChannelNum); + + prP2pBssInfo->eDBDCBand = ENUM_BAND_AUTO; + prP2pBssInfo->ucNss = rDbdcCap.ucNss; +#if (CFG_HW_WMM_BY_BSS == 0) + prP2pBssInfo->ucWmmQueSet = rDbdcCap.ucWmmSetIndex; +#endif +#endif /*CFG_SUPPORT_DBDC*/ + + if (prP2pRoleFsmInfo->eCurrentState != P2P_ROLE_STATE_IDLE) { + /* Make sure the state is in IDLE state. */ + p2pRoleFsmRunEventAbort(prAdapter, prP2pRoleFsmInfo); + } + + /* Leave IDLE state. */ + SET_NET_PWR_STATE_ACTIVE(prAdapter, prP2pBssInfo->ucBssIndex); + + prP2pBssInfo->eIntendOPMode = OP_MODE_ACCESS_POINT; + prP2pBssInfo->fgIsDfsActive = TRUE; + + if (prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.ucChannelNum != 0) { + DBGLOG(P2P, INFO, "Role(%d) Set channel at CH(%d)\n", + prP2pDfsCacMsg->ucRoleIdx, + prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.ucChannelNum); + + p2pRoleStatePrepare_To_DFS_CAC_STATE(prAdapter, + GET_BSS_INFO_BY_INDEX(prAdapter, prP2pRoleFsmInfo->ucBssIndex), + rChannelWidth, + &(prP2pRoleFsmInfo->rConnReqInfo), + &(prP2pRoleFsmInfo->rChnlReqInfo)); + p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, P2P_ROLE_STATE_DFS_CAC); + } else { + DBGLOG(P2P, ERROR, + "prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.ucChannelNum shouldn't be 0\n"); + } + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /*p2pRoleFsmRunEventDfsCac*/ + +VOID p2pRoleFsmRunEventRadarDet(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_MSG_P2P_RADAR_DETECT_T prMsgP2pRddDetMsg; + + + DBGLOG(P2P, INFO, "p2pRoleFsmRunEventRadarDet\n"); + + prMsgP2pRddDetMsg = (P_MSG_P2P_RADAR_DETECT_T) prMsgHdr; + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsgP2pRddDetMsg->ucBssIndex); + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, prP2pBssInfo->u4PrivateData); + + DBGLOG(P2P, INFO, "p2pRoleFsmRunEventRadarDet with Role(%d)\n", prP2pRoleFsmInfo->ucRoleIndex); + + if (prP2pRoleFsmInfo->eCurrentState != P2P_ROLE_STATE_DFS_CAC && + prP2pRoleFsmInfo->eCurrentState != P2P_ROLE_STATE_IDLE) { + DBGLOG(P2P, ERROR, "Wrong prP2pRoleFsmInfo->eCurrentState \"%s\"!", + (prP2pRoleFsmInfo->eCurrentState < P2P_ROLE_STATE_NUM ? + (const char *) apucDebugP2pRoleState[prP2pRoleFsmInfo->eCurrentState] : "")); + goto error; + } + + if (p2pFuncGetRadarDetectMode()) { + DBGLOG(P2P, INFO, "p2pRoleFsmRunEventRadarDet: Ignore radar event\n"); + if (prP2pRoleFsmInfo->eCurrentState == P2P_ROLE_STATE_DFS_CAC) + p2pFuncSetDfsState(DFS_STATE_CHECKING); + else + p2pFuncSetDfsState(DFS_STATE_ACTIVE); + } else { + if (prP2pRoleFsmInfo->eCurrentState == P2P_ROLE_STATE_DFS_CAC) + p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, P2P_ROLE_STATE_IDLE); + + kalP2PRddDetectUpdate(prAdapter->prGlueInfo, prP2pRoleFsmInfo->ucRoleIndex); + cnmTimerStartTimer(prAdapter, &(prP2pRoleFsmInfo->rDfsShutDownTimer), 5000); + } + + p2pFuncShowRadarInfo(prAdapter, prMsgP2pRddDetMsg->ucBssIndex); + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /*p2pRoleFsmRunEventRadarDet*/ + +VOID p2pRoleFsmRunEventSetNewChannel(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_MSG_P2P_SET_NEW_CHANNEL_T prMsgP2pSetNewChannelMsg; + + + DBGLOG(P2P, INFO, "p2pRoleFsmRunEventSetNewChannel\n"); + + prMsgP2pSetNewChannelMsg = (P_MSG_P2P_SET_NEW_CHANNEL_T) prMsgHdr; + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsgP2pSetNewChannelMsg->ucBssIndex); + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, prMsgP2pSetNewChannelMsg->ucRoleIdx); + + prP2pRoleFsmInfo->rChnlReqInfo.ucReqChnlNum = prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.ucChannelNum; + prP2pRoleFsmInfo->rChnlReqInfo.eBand = prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.eBand; + prP2pRoleFsmInfo->rChnlReqInfo.eChannelWidth = prMsgP2pSetNewChannelMsg->eChannelWidth; + prP2pBssInfo->ucPrimaryChannel = prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.ucChannelNum; + + prP2pRoleFsmInfo->rChnlReqInfo.ucCenterFreqS1 = + nicGetVhtS1(prP2pBssInfo->ucPrimaryChannel, prP2pRoleFsmInfo->rChnlReqInfo.eChannelWidth); + prP2pRoleFsmInfo->rChnlReqInfo.ucCenterFreqS2 = 0; +#if GO_STA_SCC + nicUpdateBss(prAdapter, prP2pBssInfo->ucBssIndex); +#endif + + cnmMemFree(prAdapter, prMsgHdr); +} /*p2pRoleFsmRunEventCsaDone*/ + +VOID p2pRoleFsmRunEventCsaDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_MSG_P2P_CSA_DONE_T prMsgP2pCsaDoneMsg; + + + DBGLOG(P2P, INFO, "p2pRoleFsmRunEventCsaDone\n"); + + prMsgP2pCsaDoneMsg = (P_MSG_P2P_CSA_DONE_T) prMsgHdr; + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsgP2pCsaDoneMsg->ucBssIndex); + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, prP2pBssInfo->u4PrivateData); + + p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, P2P_ROLE_STATE_SWITCH_CHANNEL); + + cnmMemFree(prAdapter, prMsgHdr); +} /*p2pRoleFsmRunEventCsaDone*/ + +VOID p2pRoleFsmRunEventDfsShutDownTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr) +{ + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) ulParamPtr; + + DBGLOG(P2P, INFO, "p2pRoleFsmRunEventDfsShutDownTimeout: DFS shut down.\n"); + + p2pFuncSetDfsState(DFS_STATE_INACTIVE); + p2pFuncStopRdd(prAdapter, prP2pRoleFsmInfo->ucBssIndex); + +} /* p2pRoleFsmRunEventDfsShutDownTimeout */ + +#endif + + +VOID p2pRoleFsmRunEventConnectionRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + P_MSG_P2P_CONNECTION_REQUEST_T prP2pConnReqMsg = (P_MSG_P2P_CONNECTION_REQUEST_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + + P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo = (P_P2P_CONNECTION_REQ_INFO_T) NULL; + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; + P_P2P_JOIN_INFO_T prJoinInfo = (P_P2P_JOIN_INFO_T) NULL; +#if CFG_SUPPORT_DBDC + CNM_DBDC_CAP_T rDbdcCap; +#endif /*CFG_SUPPORT_DBDC*/ + + prP2pConnReqMsg = (P_MSG_P2P_CONNECTION_REQUEST_T) prMsgHdr; + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, prP2pConnReqMsg->ucRoleIdx); + + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, ERROR, + "Corresponding P2P Role FSM empty: %d.\n", + prP2pConnReqMsg->ucRoleIdx); + goto error; + } + + prP2pBssInfo = prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex]; + + if (!prP2pBssInfo) { + DBGLOG(P2P, ERROR, + "prP2pRoleFsmInfo->ucBssIndex %d of prAdapter->aprBssInfo is NULL!\n", + prP2pRoleFsmInfo->ucBssIndex); + goto error; + } + + prConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + prChnlReqInfo = &(prP2pRoleFsmInfo->rChnlReqInfo); + prJoinInfo = &(prP2pRoleFsmInfo->rJoinInfo); + + DBGLOG(P2P, TRACE, "p2pFsmRunEventConnectionRequest\n"); + + if (prP2pBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + goto error; + + SET_NET_PWR_STATE_ACTIVE(prAdapter, prP2pBssInfo->ucBssIndex); + + /* In P2P GC case, the interval of two ASSOC flow could be very short, */ + /* we must start to connect directly before Deauth done */ + prStaRec = prP2pBssInfo->prStaRecOfAP; + if (prStaRec) { + if (timerPendingTimer(&prStaRec->rDeauthTxDoneTimer)) { + cnmTimerStopTimer(prAdapter, &(prStaRec->rDeauthTxDoneTimer)); + p2pRoleFsmDeauhComplete(prAdapter, prStaRec);/* Force to stop */ + } + } + /* Make sure the state is in IDLE state. */ + if (prP2pRoleFsmInfo->eCurrentState != P2P_ROLE_STATE_IDLE) + p2pRoleFsmRunEventAbort(prAdapter, prP2pRoleFsmInfo); + /* Update connection request information. */ + prConnReqInfo->eConnRequest = P2P_CONNECTION_TYPE_GC; + COPY_MAC_ADDR(prConnReqInfo->aucBssid, prP2pConnReqMsg->aucBssid); + COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, prP2pConnReqMsg->aucSrcMacAddr); + kalMemCopy(&(prConnReqInfo->rSsidStruct), &(prP2pConnReqMsg->rSsid), sizeof(P2P_SSID_STRUCT_T)); + kalMemCopy(prConnReqInfo->aucIEBuf, prP2pConnReqMsg->aucIEBuf, prP2pConnReqMsg->u4IELen); + prConnReqInfo->u4BufLength = prP2pConnReqMsg->u4IELen; + + /* Find BSS Descriptor first. */ + prJoinInfo->prTargetBssDesc = scanP2pSearchDesc(prAdapter, prConnReqInfo); + + if (prJoinInfo->prTargetBssDesc == NULL) { + /* Update scan parameter... to scan target device. */ + P_P2P_SCAN_REQ_INFO_T prScanReqInfo = &(prP2pRoleFsmInfo->rScanReqInfo); + + prScanReqInfo->ucNumChannelList = 1; + prScanReqInfo->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prScanReqInfo->eChannelSet = SCAN_CHANNEL_SPECIFIED; + prScanReqInfo->arScanChannelList[0].ucChannelNum = prP2pConnReqMsg->rChannelInfo.ucChannelNum; + prScanReqInfo->ucSsidNum = 1; + kalMemCopy(&(prScanReqInfo->arSsidStruct[0]), &(prP2pConnReqMsg->rSsid), + sizeof(P2P_SSID_STRUCT_T)); + prScanReqInfo->u4BufLength = 0; /* Prevent other P2P ID in IE. */ + prScanReqInfo->fgIsAbort = TRUE; + + p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, P2P_ROLE_STATE_SCAN); + } else { + prChnlReqInfo->u8Cookie = 0; + prChnlReqInfo->ucReqChnlNum = prP2pConnReqMsg->rChannelInfo.ucChannelNum; + prChnlReqInfo->eBand = prP2pConnReqMsg->rChannelInfo.eBand; + prChnlReqInfo->eChnlSco = prP2pConnReqMsg->eChnlSco; + prChnlReqInfo->u4MaxInterval = AIS_JOIN_CH_REQUEST_INTERVAL; + prChnlReqInfo->eChnlReqType = CH_REQ_TYPE_JOIN; + + prChnlReqInfo->eChannelWidth = prJoinInfo->prTargetBssDesc->eChannelWidth; + prChnlReqInfo->ucCenterFreqS1 = prJoinInfo->prTargetBssDesc->ucCenterFreqS1; + prChnlReqInfo->ucCenterFreqS2 = prJoinInfo->prTargetBssDesc->ucCenterFreqS2; + + rlmReviseMaxBw(prAdapter, prP2pBssInfo->ucBssIndex, &prChnlReqInfo->eChnlSco, + (P_ENUM_CHANNEL_WIDTH_P)&prChnlReqInfo->eChannelWidth, + &prChnlReqInfo->ucCenterFreqS1, &prChnlReqInfo->ucReqChnlNum); + +#if (CFG_HW_WMM_BY_BSS == 1) + if (prP2pBssInfo->fgIsWmmInited == FALSE) + prP2pBssInfo->ucWmmQueSet = cnmWmmIndexDecision(prAdapter, prP2pBssInfo); + prP2pBssInfo->eBand = prChnlReqInfo->eBand; +#endif +#if CFG_SUPPORT_DBDC + cnmDbdcEnableDecision(prAdapter, prP2pBssInfo->ucBssIndex, prChnlReqInfo->eBand); + cnmGetDbdcCapability(prAdapter, + prP2pBssInfo->ucBssIndex, + prChnlReqInfo->eBand, + prChnlReqInfo->ucReqChnlNum, + wlanGetSupportNss(prAdapter, prP2pBssInfo->ucBssIndex), + &rDbdcCap); + + DBGLOG(P2P, INFO, + "p2pRoleFsmRunEventConnectionRequest: start GC at CH %u, NSS=%u.\n", + prChnlReqInfo->ucReqChnlNum, + rDbdcCap.ucNss); + + prP2pBssInfo->eDBDCBand = ENUM_BAND_AUTO; + prP2pBssInfo->ucNss = rDbdcCap.ucNss; +#if (CFG_HW_WMM_BY_BSS == 0) + prP2pBssInfo->ucWmmQueSet = rDbdcCap.ucWmmSetIndex; +#endif +#endif + p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, P2P_ROLE_STATE_REQING_CHANNEL); + } + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pRoleFsmRunEventConnectionRequest */ + +VOID p2pRoleFsmRunEventConnectionAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + P_MSG_P2P_CONNECTION_ABORT_T prDisconnMsg = (P_MSG_P2P_CONNECTION_ABORT_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + + + prDisconnMsg = (P_MSG_P2P_CONNECTION_ABORT_T) prMsgHdr; + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, prDisconnMsg->ucRoleIdx); + + DBGLOG(P2P, TRACE, "p2pFsmRunEventConnectionAbort: Connection Abort.\n"); + + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, ERROR, + "p2pRoleFsmRunEventConnectionAbort: Corresponding P2P Role FSM empty: %d.\n", + prDisconnMsg->ucRoleIdx); + goto error; + } + + prP2pBssInfo = prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex]; + + if (!prP2pBssInfo) { + DBGLOG(P2P, ERROR, + "prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex(%d)] is NULL!", + prP2pRoleFsmInfo->ucBssIndex); + goto error; + } + + 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; + } + +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, + NULL, NULL, 0, 0, + WLAN_STATUS_MEDIA_DISCONNECT); +#else + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, NULL, NULL, 0, 0); +#endif + + prStaRec = prP2pBssInfo->prStaRecOfAP; + + /* Stop rejoin timer if it is started. */ + /* TODO: If it has. */ + + p2pFuncDisconnect(prAdapter, prP2pBssInfo, + prStaRec, + prDisconnMsg->fgSendDeauth, prDisconnMsg->u2ReasonCode); + + cnmTimerStopTimer(prAdapter, &(prStaRec->rDeauthTxDoneTimer)); + + cnmTimerInitTimer(prAdapter, + &(prStaRec->rDeauthTxDoneTimer), + (PFN_MGMT_TIMEOUT_FUNC) p2pRoleFsmDeauthTimeout, (ULONG) prStaRec); + + cnmTimerStartTimer(prAdapter, &(prStaRec->rDeauthTxDoneTimer), + P2P_DEAUTH_TIMEOUT_TIME_MS); + + SET_NET_PWR_STATE_IDLE(prAdapter, prP2pBssInfo->ucBssIndex); + + p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, P2P_ROLE_STATE_IDLE); + } + break; + case OP_MODE_ACCESS_POINT: + { + /* Search specific client device, and disconnect. */ + /* 1. Send deauthentication frame. */ + /* 2. Indication: Device disconnect. */ + P_STA_RECORD_T prCurrStaRec = (P_STA_RECORD_T) NULL; + + DBGLOG(P2P, TRACE, "Disconnecting with Target ID: " MACSTR "\n", + MAC2STR(prDisconnMsg->aucTargetID)); + + prCurrStaRec = bssGetClientByMac(prAdapter, prP2pBssInfo, prDisconnMsg->aucTargetID); + + if (prCurrStaRec) { + DBGLOG(P2P, TRACE, "Disconnecting: " MACSTR "\n", + MAC2STR(prCurrStaRec->aucMacAddr)); + + if (!prDisconnMsg->fgSendDeauth) { + p2pRoleFsmDeauhComplete(prAdapter, + prCurrStaRec); + break; + } + + /* Glue layer indication. */ + /* kalP2PGOStationUpdate(prAdapter->prGlueInfo, prCurrStaRec, FALSE); */ + + /* Send deauth & do indication. */ + p2pFuncDisconnect(prAdapter, prP2pBssInfo, prCurrStaRec, + prDisconnMsg->fgSendDeauth, prDisconnMsg->u2ReasonCode); + + cnmTimerStopTimer(prAdapter, &(prCurrStaRec->rDeauthTxDoneTimer)); + + cnmTimerInitTimer(prAdapter, + &(prCurrStaRec->rDeauthTxDoneTimer), + (PFN_MGMT_TIMEOUT_FUNC) p2pRoleFsmDeauthTimeout, + (ULONG) prCurrStaRec); + + cnmTimerStartTimer(prAdapter, &(prCurrStaRec->rDeauthTxDoneTimer), + P2P_DEAUTH_TIMEOUT_TIME_MS); + } +#if 0 + 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, prP2pBssInfo, + prCurrStaRec, + prDisconnMsg->fgSendDeauth, + prDisconnMsg->u2ReasonCode); + + /* prTargetStaRec = prCurrStaRec; */ + + break; + } + } +#endif + + } + break; + case OP_MODE_P2P_DEVICE: + default: + ASSERT(FALSE); + break; + } + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pRoleFsmRunEventConnectionAbort */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called when JOIN complete message event is received from SAA. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pRoleFsmRunEventJoinComplete(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_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_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + prJoinCompMsg = (P_MSG_JOIN_COMP_T) prMsgHdr; + prStaRec = prJoinCompMsg->prStaRec; + prAssocRspSwRfb = prJoinCompMsg->prSwRfb; + + DBGLOG(P2P, TRACE, "P2P BSS %d, Join Complete\n", prStaRec->ucBssIndex); + + ASSERT(prStaRec); + if (!prStaRec) { + DBGLOG(P2P, ERROR, "prJoinCompMsg->prStaRec is NULL!\n"); + goto error; + } + + ASSERT(prStaRec->ucBssIndex < P2P_DEV_BSS_INDEX); + if (!(prStaRec->ucBssIndex < P2P_DEV_BSS_INDEX)) { + DBGLOG(P2P, ERROR, + "prStaRec->ucBssIndex %d should < P2P_DEV_BSS_INDEX(%d)!\n", + prStaRec->ucBssIndex, + P2P_DEV_BSS_INDEX); + goto error; + } + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + ASSERT(prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE); + if (prP2pBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) { + DBGLOG(P2P, ERROR, "prP2pBssInfo->eCurrentOPMode %d != OP_MODE_INFRASTRUCTURE(%d)!\n", + prP2pBssInfo->eCurrentOPMode, OP_MODE_INFRASTRUCTURE); + goto error; + } + + ASSERT(prP2pBssInfo->u4PrivateData < BSS_P2P_NUM); + if (!(prP2pBssInfo->u4PrivateData < BSS_P2P_NUM)) { + DBGLOG(P2P, ERROR, + "prP2pBssInfo->u4PrivateData %d should < BSS_P2P_NUM(%d)!\n", + prP2pBssInfo->u4PrivateData, + BSS_P2P_NUM); + goto error; + } + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, prP2pBssInfo->u4PrivateData); + + prJoinInfo = &(prP2pRoleFsmInfo->rJoinInfo); + + /* 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, prP2pBssInfo, 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); + + prP2pBssInfo->prStaRecOfAP = NULL; + } + /* 4 <1.3> Update BSS_INFO_T */ + if (prAssocRspSwRfb) { + p2pFuncUpdateBssInfoForJOIN(prAdapter, + prJoinInfo->prTargetBssDesc, + prStaRec, prP2pBssInfo, prAssocRspSwRfb); + } else { + DBGLOG(P2P, INFO, + "prAssocRspSwRfb is NULL! Skip p2pFuncUpdateBssInfoForJOIN\n"); + } + + /* 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, prP2pBssInfo->ucBssIndex, + (INT_8) (RCPI_TO_dBm(prStaRec->ucRCPI)), 0); +#endif + + /* 4 <1.6> Indicate Connected Event to Host immediately. */ + /* Require BSSID, Association ID, Beacon Interval.. from AIS_BSS_INFO_T */ + /* p2pIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, + * prStaRec->aucMacAddr); + */ + if (prJoinInfo->prTargetBssDesc) + scanReportBss2Cfg80211(prAdapter, + BSS_TYPE_P2P_DEVICE, prJoinInfo->prTargetBssDesc); +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, + &prP2pRoleFsmInfo->rConnReqInfo, + prJoinInfo->aucIEBuf, + prJoinInfo->u4BufLength, + prStaRec->u2StatusCode, + WLAN_STATUS_MEDIA_DISCONNECT); +#else + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, + &prP2pRoleFsmInfo->rConnReqInfo, + prJoinInfo->aucIEBuf, + prJoinInfo->u4BufLength, + prStaRec->u2StatusCode); + +#endif + + + + } 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 = prJoinInfo->prTargetBssDesc; + + ASSERT(prBssDesc); + ASSERT(prBssDesc->fgIsConnecting); + + prBssDesc->fgIsConnecting = FALSE; + +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, + &prP2pRoleFsmInfo->rConnReqInfo, + prJoinInfo->aucIEBuf, + prJoinInfo->u4BufLength, + prStaRec->u2StatusCode, + WLAN_STATUS_MEDIA_DISCONNECT); +#else + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + prP2pRoleFsmInfo->ucRoleIndex, + &prP2pRoleFsmInfo->rConnReqInfo, + prJoinInfo->aucIEBuf, + prJoinInfo->u4BufLength, + prStaRec->u2StatusCode); +#endif + + } + + } + } + + if (prP2pRoleFsmInfo->eCurrentState == P2P_ROLE_STATE_GC_JOIN) { + /* Return to IDLE state. */ + p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, P2P_ROLE_STATE_IDLE); + } + +error: + if (prAssocRspSwRfb) + nicRxReturnRFB(prAdapter, prAssocRspSwRfb); + + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pRoleFsmRunEventJoinComplete */ + +VOID p2pRoleFsmRunEventScanRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_P2P_SCAN_REQUEST_T prP2pScanReqMsg = (P_MSG_P2P_SCAN_REQUEST_T) NULL; + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + P_P2P_SCAN_REQ_INFO_T prScanReqInfo = (P_P2P_SCAN_REQ_INFO_T) NULL; + UINT_32 u4ChnlListSize = 0; + P_P2P_SSID_STRUCT_T prP2pSsidStruct = (P_P2P_SSID_STRUCT_T) NULL; + P_BSS_INFO_T prP2pBssInfo = NULL; + + + prP2pScanReqMsg = (P_MSG_P2P_SCAN_REQUEST_T) prMsgHdr; + + prP2pBssInfo = prAdapter->aprBssInfo[prP2pScanReqMsg->ucBssIdx]; + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, prP2pBssInfo->u4PrivateData); + + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, ERROR, "prP2pRoleFsmInfo is NULL!"); + goto error; + } + + prP2pScanReqMsg = (P_MSG_P2P_SCAN_REQUEST_T) prMsgHdr; + prScanReqInfo = &(prP2pRoleFsmInfo->rScanReqInfo); + + DBGLOG(P2P, TRACE, "p2pDevFsmRunEventScanRequest\n"); + + /* Do we need to be in IDLE state? */ + /* p2pDevFsmRunEventAbort(prAdapter, prP2pDevFsmInfo); */ + + ASSERT(prScanReqInfo->fgIsScanRequest == FALSE); + + prScanReqInfo->fgIsAbort = TRUE; + prScanReqInfo->eScanType = prP2pScanReqMsg->eScanType; + + if (prP2pScanReqMsg->u4NumChannel) { + 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); + } else { + /* If channel number is ZERO. + * It means do a FULL channel scan. + */ + prScanReqInfo->eChannelSet = SCAN_CHANNEL_FULL; + } + + /* SSID */ + prP2pSsidStruct = prP2pScanReqMsg->prSSID; + for (prScanReqInfo->ucSsidNum = 0; + prScanReqInfo->ucSsidNum < prP2pScanReqMsg->i4SsidNum; prScanReqInfo->ucSsidNum++) { + + kalMemCopy(prScanReqInfo->arSsidStruct[prScanReqInfo->ucSsidNum].aucSsid, + prP2pSsidStruct->aucSsid, prP2pSsidStruct->ucSsidLen); + + prScanReqInfo->arSsidStruct[prScanReqInfo->ucSsidNum].ucSsidLen = prP2pSsidStruct->ucSsidLen; + + prP2pSsidStruct++; + } + + /* IE Buffer */ + kalMemCopy(prScanReqInfo->aucIEBuf, prP2pScanReqMsg->pucIEBuf, prP2pScanReqMsg->u4IELen); + + prScanReqInfo->u4BufLength = prP2pScanReqMsg->u4IELen; + + p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, P2P_ROLE_STATE_SCAN); + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pDevFsmRunEventScanRequest */ + +VOID +p2pRoleFsmRunEventScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr, IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo) +{ + P_MSG_SCN_SCAN_DONE prScanDoneMsg = (P_MSG_SCN_SCAN_DONE) prMsgHdr; + P_P2P_SCAN_REQ_INFO_T prScanReqInfo = (P_P2P_SCAN_REQ_INFO_T) NULL; + ENUM_P2P_ROLE_STATE_T eNextState = P2P_ROLE_STATE_NUM; + P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); + P_P2P_JOIN_INFO_T prP2pJoinInfo = &(prP2pRoleFsmInfo->rJoinInfo); + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; +#if CFG_SUPPORT_DBDC + CNM_DBDC_CAP_T rDbdcCap; +#endif /*CFG_SUPPORT_DBDC*/ + + if (prP2pRoleFsmInfo == NULL) { + DBGLOG(P2P, TRACE, "prP2pRoleFsmInfo is NULL\n"); + goto error; + } + + DBGLOG(P2P, TRACE, "P2P Role Scan Done Event\n"); + + prScanReqInfo = &(prP2pRoleFsmInfo->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 Role Scan Don SeqNum Received:%d <-> P2P Role Fsm SCAN Seq Issued:%d\n", + prScanDoneMsg->ucSeqNum, prScanReqInfo->ucSeqNumOfScnMsg); + + goto error; + } + + switch (prP2pRoleFsmInfo->eCurrentState) { + case P2P_ROLE_STATE_SCAN: + prScanReqInfo->fgIsAbort = FALSE; + + if (prConnReqInfo->eConnRequest == P2P_CONNECTION_TYPE_GC) { + + prP2pJoinInfo->prTargetBssDesc = + p2pFuncKeepOnConnection(prAdapter, + prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex], + prConnReqInfo, + &prP2pRoleFsmInfo->rChnlReqInfo, + &prP2pRoleFsmInfo->rScanReqInfo); + if ((prP2pJoinInfo->prTargetBssDesc) == NULL) { + eNextState = P2P_ROLE_STATE_SCAN; + } else { + prP2pBssInfo = prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex]; + if (!prP2pBssInfo) + break; + prChnlReqInfo = &(prP2pRoleFsmInfo->rChnlReqInfo); + if (!prChnlReqInfo) + break; +#if (CFG_HW_WMM_BY_BSS == 1) + if (prP2pBssInfo->fgIsWmmInited == FALSE) + prP2pBssInfo->ucWmmQueSet = cnmWmmIndexDecision(prAdapter, prP2pBssInfo); + prP2pBssInfo->eBand = prChnlReqInfo->eBand; +#endif +#if CFG_SUPPORT_DBDC + cnmDbdcEnableDecision(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + prChnlReqInfo->eBand); + cnmGetDbdcCapability(prAdapter, + prP2pRoleFsmInfo->ucBssIndex, + prChnlReqInfo->eBand, + prChnlReqInfo->ucReqChnlNum, + wlanGetSupportNss(prAdapter, prP2pRoleFsmInfo->ucBssIndex), + &rDbdcCap); + + DBGLOG(P2P, INFO, + "p2pRoleFsmRunEventScanDone: start GC at CH %u, NSS=%u.\n", + prChnlReqInfo->ucReqChnlNum, + rDbdcCap.ucNss); + + prP2pBssInfo->eDBDCBand = ENUM_BAND_AUTO; + prP2pBssInfo->ucNss = rDbdcCap.ucNss; +#if (CFG_HW_WMM_BY_BSS == 0) + prP2pBssInfo->ucWmmQueSet = rDbdcCap.ucWmmSetIndex; +#endif +#endif + /* For GC join. */ + eNextState = P2P_ROLE_STATE_REQING_CHANNEL; + } + } else { + eNextState = P2P_ROLE_STATE_IDLE; + } + break; + case P2P_ROLE_STATE_AP_CHNL_DETECTION: + eNextState = P2P_ROLE_STATE_REQING_CHANNEL; + break; + default: + /* Unexpected channel scan done event without being chanceled. */ + ASSERT(FALSE); + break; + } + + prScanReqInfo->fgIsScanRequest = FALSE; + + p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, eNextState); + +error: + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pRoleFsmRunEventScanDone */ + +VOID +p2pRoleFsmRunEventChnlGrant(IN P_ADAPTER_T prAdapter, + IN P_MSG_HDR_T prMsgHdr, IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo) +{ + 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; +#if (CFG_SUPPORT_DFS_MASTER == 1) + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + UINT_32 u4CacTimeMs; +#endif + UINT_8 ucTokenID = 0; + + + if (!prP2pRoleFsmInfo) { + DBGLOG(P2P, ERROR, "prP2pRoleFsmInfo is NULL!\n"); + goto error; + } + + DBGLOG(P2P, TRACE, "P2P Run Event Role Channel Grant\n"); + + prMsgChGrant = (P_MSG_CH_GRANT_T) prMsgHdr; + ucTokenID = prMsgChGrant->ucTokenID; + prChnlReqInfo = &(prP2pRoleFsmInfo->rChnlReqInfo); + +#if (CFG_SUPPORT_DFS_MASTER == 1) + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsgChGrant->ucBssIndex); +#endif + if (prChnlReqInfo->u4MaxInterval != prMsgChGrant->u4GrantInterval) { + DBGLOG(P2P, WARN, + "P2P Role:%d Request Channel Interval:%d, Grant Interval:%d\n", + prP2pRoleFsmInfo->ucRoleIndex, prChnlReqInfo->u4MaxInterval, + prMsgChGrant->u4GrantInterval); + prChnlReqInfo->u4MaxInterval = prMsgChGrant->u4GrantInterval; + } + + if (ucTokenID == prChnlReqInfo->ucSeqNumOfChReq) { + ENUM_P2P_ROLE_STATE_T eNextState = P2P_ROLE_STATE_NUM; + + switch (prP2pRoleFsmInfo->eCurrentState) { + case P2P_ROLE_STATE_REQING_CHANNEL: + switch (prChnlReqInfo->eChnlReqType) { + case CH_REQ_TYPE_JOIN: + eNextState = P2P_ROLE_STATE_GC_JOIN; + break; + case CH_REQ_TYPE_GO_START_BSS: + eNextState = P2P_ROLE_STATE_IDLE; + break; + default: + DBGLOG(P2P, WARN, + "p2pRoleFsmRunEventChnlGrant: Invalid Channel Request Type:%d\n", + prChnlReqInfo->eChnlReqType); + ASSERT(FALSE); + break; + } + + p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, eNextState); + break; + +#if (CFG_SUPPORT_DFS_MASTER == 1) + case P2P_ROLE_STATE_DFS_CAC: + p2pFuncStartRdd(prAdapter, prMsgChGrant->ucBssIndex); + + if (p2pFuncCheckWeatherRadarBand(prChnlReqInfo)) + u4CacTimeMs = P2P_AP_CAC_WEATHER_CHNL_HOLD_TIME_MS; + else + u4CacTimeMs = prP2pRoleFsmInfo->rChnlReqInfo.u4MaxInterval; + + if (p2pFuncIsManualCac()) + u4CacTimeMs = p2pFuncGetDriverCacTime() * 1000; + else + p2pFuncSetDriverCacTime(u4CacTimeMs/1000); + + cnmTimerStartTimer(prAdapter, &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer), + u4CacTimeMs); + + p2pFuncRecordCacStartBootTime(); + + p2pFuncSetDfsState(DFS_STATE_CHECKING); + + DBGLOG(P2P, INFO, "p2pRoleFsmRunEventChnlGrant: CAC time = %ds\n", + u4CacTimeMs/1000); + break; + case P2P_ROLE_STATE_SWITCH_CHANNEL: + p2pFuncDfsSwitchCh(prAdapter, prP2pBssInfo, prP2pRoleFsmInfo->rChnlReqInfo); + p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, P2P_ROLE_STATE_IDLE); + break; +#endif + default: + /* Channel is granted under unexpected state. + * Driver should cancel channel privileagea before leaving the states. + */ + if (IS_BSS_ACTIVE(prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex])) { + DBGLOG(P2P, WARN, + "p2pRoleFsmRunEventChnlGrant: Invalid CurrentState:%d\n", + prP2pRoleFsmInfo->eCurrentState); + ASSERT(FALSE); + } + break; + } + } else { + /* Channel requsted, but released. */ + ASSERT(!prChnlReqInfo->fgIsChannelRequested); + if (prChnlReqInfo->fgIsChannelRequested) + DBGLOG(P2P, ERROR, + "fgIsChannelRequested is TRUE!Channel was requested, but released!\n"); + } + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pRoleFsmRunEventChnlGrant */ + +/* ////////////////////////////////////// */ +VOID p2pRoleFsmRunEventDissolve(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + /* TODO: */ + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pRoleFsmRunEventDissolve */ + +/*----------------------------------------------------------------------------*/ +/*! +* @ This routine update the current MAC table based on the current ACL. +* If ACL change causing an associated STA become un-authorized. This STA +* will be kicked out immediately. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] ucBssIdx Bss index. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pRoleUpdateACLEntry(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx) +{ + BOOLEAN bMatchACL = FALSE; + INT_32 i = 0, i4Ret = 0; + P_LINK_T prClientList; + P_STA_RECORD_T prCurrStaRec, prNextStaRec; + P_BSS_INFO_T prP2pBssInfo; + + if ((!prAdapter) || (ucBssIdx > HW_BSSID_NUM)) + return; + DBGLOG(P2P, TRACE, "Update ACL Entry ucBssIdx = %d\n", ucBssIdx); + prP2pBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + /* ACL is disabled. Do nothing about the MAC table. */ + if (prP2pBssInfo->rACL.ePolicy == PARAM_CUSTOM_ACL_POLICY_DISABLE) + return; + + prClientList = &prP2pBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH_ENTRY_SAFE(prCurrStaRec, prNextStaRec, prClientList, rLinkEntry, STA_RECORD_T) { + bMatchACL = FALSE; + for (i = 0; i < prP2pBssInfo->rACL.u4Num; i++) { + if (EQUAL_MAC_ADDR(prCurrStaRec->aucMacAddr, prP2pBssInfo->rACL.rEntry[i].aucAddr)) { + bMatchACL = TRUE; + break; + } + } + + if (((!bMatchACL) && (prP2pBssInfo->rACL.ePolicy == PARAM_CUSTOM_ACL_POLICY_ACCEPT)) || + ((bMatchACL) && (prP2pBssInfo->rACL.ePolicy == PARAM_CUSTOM_ACL_POLICY_DENY))) { + + DBGLOG(P2P, TRACE, "ucBssIdx=%d, ACL Policy=%d\n", ucBssIdx, prP2pBssInfo->rACL.ePolicy); + + i4Ret = assocSendDisAssocFrame(prAdapter, prCurrStaRec, STATUS_CODE_REQ_DECLINED); + if (!i4Ret) + DBGLOG(P2P, TRACE, "Send DISASSOC to [" MACSTR "], Reason = %d\n", + MAC2STR(prCurrStaRec->aucMacAddr), STATUS_CODE_REQ_DECLINED); + LINK_REMOVE_KNOWN_ENTRY(prClientList, &prCurrStaRec->rLinkEntry); + } + } +} /* p2pRoleUpdateACLEntry */ + +/*----------------------------------------------------------------------------*/ +/*! +* @ Check if the specified STA pass the Access Control List inspection. +* If fails to pass the checking, then no authentication or association is allowed. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] pMacAddr Pointer to the mac address. +* @param[in] ucBssIdx Bss index. +* +* @return TRUE - pass ACL inspection, FALSE - ACL inspection fail +*/ +/*----------------------------------------------------------------------------*/ +BOOL p2pRoleProcessACLInspection(IN P_ADAPTER_T prAdapter, IN PUCHAR pMacAddr, IN UINT_8 ucBssIdx) +{ + BOOLEAN bPassACL = TRUE; + INT_32 i = 0; + P_BSS_INFO_T prP2pBssInfo; + + if ((!prAdapter) || (!pMacAddr) || (ucBssIdx > HW_BSSID_NUM)) + return FALSE; + + prP2pBssInfo = prAdapter->aprBssInfo[ucBssIdx]; + + if (prP2pBssInfo->rACL.ePolicy == PARAM_CUSTOM_ACL_POLICY_DISABLE) + return TRUE; + + if (prP2pBssInfo->rACL.ePolicy == PARAM_CUSTOM_ACL_POLICY_ACCEPT) + bPassACL = FALSE; + else + bPassACL = TRUE; + + for (i = 0; i < prP2pBssInfo->rACL.u4Num; i++) { + if (EQUAL_MAC_ADDR(pMacAddr, prP2pBssInfo->rACL.rEntry[i].aucAddr)) { + bPassACL = !bPassACL; + break; + } + } + + if (bPassACL == FALSE) + DBGLOG(P2P, WARN, "this mac [" MACSTR "] is fail to pass ACL inspection.\n", MAC2STR(pMacAddr)); + + return bPassACL; +} /* p2pRoleProcessACLInspection */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Event of Successful Completion of AAA Module. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +p2pRoleFsmRunEventAAAComplete(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_BSS_INFO_T prP2pBssInfo) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + ENUM_PARAM_MEDIA_STATE_T eOriMediaState; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prStaRec != NULL) && (prP2pBssInfo != NULL)); + + eOriMediaState = prP2pBssInfo->eConnectionState; + + bssRemoveClient(prAdapter, prP2pBssInfo, prStaRec); + + if (prP2pBssInfo->rStaRecOfClientList.u4NumElem >= P2P_MAXIMUM_CLIENT_COUNT + || !p2pRoleProcessACLInspection(prAdapter, prStaRec->aucMacAddr, prP2pBssInfo->ucBssIndex) +#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER + || kalP2PMaxClients(prAdapter->prGlueInfo, prP2pBssInfo->rStaRecOfClientList.u4NumElem, + (UINT_8) prP2pBssInfo->u4PrivateData) +#endif + ) { + rStatus = WLAN_STATUS_RESOURCES; + break; + } + + bssAddClient(prAdapter, prP2pBssInfo, prStaRec); + + prStaRec->u2AssocId = bssAssignAssocID(prStaRec); + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + p2pChangeMediaState(prAdapter, prP2pBssInfo, PARAM_MEDIA_STATE_CONNECTED); + + /* Update Connected state to FW. */ + if (eOriMediaState != prP2pBssInfo->eConnectionState) + nicUpdateBss(prAdapter, prP2pBssInfo->ucBssIndex); + + } while (FALSE); + + return rStatus; +} /* p2pRunEventAAAComplete */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Event of Successful Completion of AAA Module. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +p2pRoleFsmRunEventAAASuccess(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_BSS_INFO_T prP2pBssInfo) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prStaRec != NULL) && (prP2pBssInfo != NULL)); + + if ((prP2pBssInfo->eNetworkType != NETWORK_TYPE_P2P) || (prP2pBssInfo->u4PrivateData >= BSS_P2P_NUM)) { + ASSERT(FALSE); + rStatus = WLAN_STATUS_INVALID_DATA; + break; + } + + ASSERT(prP2pBssInfo->ucBssIndex < P2P_DEV_BSS_INDEX); + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, prP2pBssInfo->u4PrivateData); + + /* Glue layer indication. */ + kalP2PGOStationUpdate(prAdapter->prGlueInfo, prP2pRoleFsmInfo->ucRoleIndex, prStaRec, TRUE); + + } while (FALSE); + + return rStatus; +} /* p2pRoleFsmRunEventAAASuccess */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Event of Tx Fail of AAA Module. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pRoleFsmRunEventAAATxFail(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_BSS_INFO_T prP2pBssInfo) +{ + ASSERT(prAdapter); + ASSERT(prStaRec); + + bssRemoveClient(prAdapter, prP2pBssInfo, prStaRec); + + p2pFuncDisconnect(prAdapter, prP2pBssInfo, prStaRec, FALSE, REASON_CODE_UNSPECIFIED); + + /* 20120830 moved into p2puUncDisconnect. */ + /* cnmStaRecFree(prAdapter, prStaRec); */ +} /* p2pRoleFsmRunEventAAATxFail */ + +VOID p2pRoleFsmRunEventSwitchOPMode(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_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + + + ASSERT(prSwitchOpMode->ucRoleIdx < BSS_P2P_NUM); + if (!(prSwitchOpMode->ucRoleIdx < BSS_P2P_NUM)) { + DBGLOG(P2P, ERROR, + "prSwitchOpMode->ucRoleIdx %d should < BSS_P2P_NUM(%d)\n", + prSwitchOpMode->ucRoleIdx, BSS_P2P_NUM); + goto error; + } + + DBGLOG(P2P, TRACE, "p2pRoleFsmRunEventSwitchOPMode\n"); + + prP2pRoleFsmInfo = prAdapter->rWifiVar.aprP2pRoleFsmInfo[prSwitchOpMode->ucRoleIdx]; + + ASSERT(prP2pRoleFsmInfo->ucBssIndex < P2P_DEV_BSS_INDEX); + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prP2pRoleFsmInfo->ucBssIndex); + + if (!(prSwitchOpMode->eOpMode < OP_MODE_NUM)) { + DBGLOG(P2P, ERROR, + "prSwitchOpMode->eOpMode %d should < OP_MODE_NUM(%d)\n", + prSwitchOpMode->eOpMode, OP_MODE_NUM); + goto error; + } + + /* P2P Device / GC. */ + p2pFuncSwitchOPMode(prAdapter, prP2pBssInfo, prSwitchOpMode->eOpMode, TRUE); + +error: + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pRoleFsmRunEventSwitchOPMode */ + +/* /////////////////////////////// TO BE REFINE //////////////////////////////// */ + +VOID p2pRoleFsmRunEventBeaconUpdate(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_ROLE_FSM_INFO_T prRoleP2pFsmInfo = (P_P2P_ROLE_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; + P_P2P_BEACON_UPDATE_INFO_T prBcnUpdateInfo = (P_P2P_BEACON_UPDATE_INFO_T) NULL; + + + DBGLOG(P2P, TRACE, "p2pRoleFsmRunEventBeaconUpdate\n"); + prBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T) prMsgHdr; + if (prBcnUpdateMsg->ucRoleIndex >= BSS_P2P_NUM) { + DBGLOG(P2P, ERROR, "prBcnUpdateMsg->ucRoleIndex %d should < BSS_P2P_NUM(%d)\n", + prBcnUpdateMsg->ucRoleIndex, BSS_P2P_NUM); + goto error; + } + + prRoleP2pFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, prBcnUpdateMsg->ucRoleIndex); + if (!prRoleP2pFsmInfo) { + DBGLOG(P2P, ERROR, "prRoleP2pFsmInfo of prBcnUpdateMsg->ucRoleIndex %d is NULL\n", + prBcnUpdateMsg->ucRoleIndex); + goto error; + } + + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prRoleP2pFsmInfo->ucBssIndex); + + prP2pBssInfo->fgIsWepCipherGroup = prBcnUpdateMsg->fgIsWepCipher; + + prBcnUpdateInfo = &(prRoleP2pFsmInfo->rBeaconUpdateInfo); + + p2pFuncBeaconUpdate(prAdapter, + prP2pBssInfo, + prBcnUpdateInfo, + prBcnUpdateMsg->pucBcnHdr, + prBcnUpdateMsg->u4BcnHdrLen, + prBcnUpdateMsg->pucBcnBody, prBcnUpdateMsg->u4BcnBodyLen); + + if (prBcnUpdateMsg->pucAssocRespIE != NULL && prBcnUpdateMsg->u4AssocRespLen > 0) { + DBGLOG(P2P, TRACE, "Copy extra IEs for assoc resp (Length= %d)\n", + prBcnUpdateMsg->u4AssocRespLen); + DBGLOG_MEM8(P2P, INFO, prBcnUpdateMsg->pucAssocRespIE, prBcnUpdateMsg->u4AssocRespLen); + + if (p2pFuncAssocRespUpdate(prAdapter, + prP2pBssInfo, + prBcnUpdateMsg->pucAssocRespIE, + prBcnUpdateMsg->u4AssocRespLen) == WLAN_STATUS_FAILURE) + DBGLOG(P2P, ERROR, "Update extra IEs for asso resp fail!\n"); + + } + + if ((prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) && + (prP2pBssInfo->eIntendOPMode == OP_MODE_NUM)) { + /* AP is created, Beacon Update. */ + /* nicPmIndicateBssAbort(prAdapter, NETWORK_TYPE_P2P_INDEX); */ + + DBGLOG(P2P, TRACE, "p2pRoleFsmRunEventBeaconUpdate with Bssidex(%d)\n", + prRoleP2pFsmInfo->ucBssIndex); + + bssUpdateBeaconContent(prAdapter, prRoleP2pFsmInfo->ucBssIndex); + + /* nicPmIndicateBssCreated(prAdapter, NETWORK_TYPE_P2P_INDEX); */ + } + +error: + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pRoleFsmRunEventBeaconUpdate */ + +VOID +p2pProcessEvent_UpdateNOAParam(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucBssIdx, IN 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 = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo[prBssInfo->u4PrivateData]; + + prP2pSpecificBssInfo->fgEnableOppPS = prEventUpdateNoaParam->ucEnableOppPS; + 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].ucIsInUse; + /* 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; + + DBGLOG(P2P, TRACE, "p2pProcessEvent_UpdateNOAParam\n"); + /* update beacon content by the change */ + bssUpdateBeaconContent(prAdapter, ucBssIdx); +} /* p2pProcessEvent_UpdateNOAParam */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will clean p2p connection before suspend. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pProcessPreSuspendFlow(IN P_ADAPTER_T prAdapter) +{ + UINT_8 idx; + P_BSS_INFO_T prBssInfo; + UINT_32 u4ClientCount = 0; + P_LINK_T prClientList; + P_STA_RECORD_T prCurrStaRec, prStaRecNext; + P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo = (P_P2P_DEV_FSM_INFO_T) NULL; + + if (prAdapter == NULL) + return; + + if (!wlanGetHifState(prAdapter->prGlueInfo)) + return; + + for (idx = 0; idx < MAX_BSS_INDEX; idx++) { + prBssInfo = prAdapter->aprBssInfo[idx]; + if (!prBssInfo) + continue; + + /* Skip AIS BSS */ + if (idx == prAdapter->prAisBssInfo->ucBssIndex) + continue; + + if (!IS_BSS_ACTIVE(prBssInfo)) + continue; + + /* Non-P2P network type */ + if (prBssInfo->eNetworkType != NETWORK_TYPE_P2P) { + DBGLOG(HAL, STATE, "[Suspend] eNetworkType %d.\n", + prBssInfo->eNetworkType); + nicPmIndicateBssAbort(prAdapter, idx); + nicDeactivateNetwork(prAdapter, idx); + nicUpdateBss(prAdapter, idx); + } + + /* P2P network type. Deactive GO/AP bss to let TOP sleep */ + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + /* Force to deactivate Network of GO case */ + u4ClientCount = bssGetClientCount(prAdapter, prBssInfo); + if (u4ClientCount == 0) + continue; + + DBGLOG(HAL, STATE, "[Suspend] Force Deactive GO.\n"); + prClientList = &prBssInfo->rStaRecOfClientList; + LINK_FOR_EACH_ENTRY_SAFE(prCurrStaRec, prStaRecNext, + prClientList, rLinkEntry, STA_RECORD_T) { + p2pFuncDisconnect(prAdapter, prBssInfo, + prCurrStaRec, FALSE, + REASON_CODE_DEAUTH_LEAVING_BSS); + LINK_REMOVE_KNOWN_ENTRY(prClientList, + &prCurrStaRec->rLinkEntry); + } + + p2pChangeMediaState(prAdapter, prBssInfo, + PARAM_MEDIA_STATE_DISCONNECTED); + p2pFuncStopComplete(prAdapter, prBssInfo); + } + + /* P2P network type. Deactive GC bss to let TOP sleep */ + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + if (prBssInfo->prStaRecOfAP == NULL) + continue; + + /* Force to deactivate Network of GC case */ + DBGLOG(HAL, STATE, "[Suspend] Force Deactive GC.\n"); +#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + (UINT_8) prBssInfo->u4PrivateData, + NULL, NULL, 0, 0, + WLAN_STATUS_MEDIA_DISCONNECT); +#else + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + (UINT_8) prBssInfo->u4PrivateData, + NULL, NULL, 0, 0); +#endif + + p2pFuncDisconnect(prAdapter, prBssInfo, + prBssInfo->prStaRecOfAP, FALSE, + REASON_CODE_DEAUTH_LEAVING_BSS); + p2pFuncStopComplete(prAdapter, prBssInfo); + } + } + + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + + if (prP2pDevFsmInfo) { + DBGLOG(HAL, STATE, "Force P2P to IDLE state when suspend\n"); + cnmTimerStopTimer(prAdapter, + &(prP2pDevFsmInfo->rP2pFsmTimeoutTimer)); + + /* Abort device FSM */ + p2pDevFsmStateTransition(prAdapter, prP2pDevFsmInfo, + P2P_DEV_STATE_IDLE); + } +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_role_state.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_role_state.c new file mode 100644 index 0000000000000..185baa9cce397 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_role_state.c @@ -0,0 +1,499 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#include "precomp.h" + +VOID +p2pRoleStateInit_IDLE(IN P_ADAPTER_T prAdapter, IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo, IN P_BSS_INFO_T prP2pBssInfo) +{ + + cnmTimerStartTimer(prAdapter, &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer), P2P_AP_CHNL_HOLD_TIME_MS); +} /* p2pRoleStateInit_IDLE */ + +VOID +p2pRoleStateAbort_IDLE(IN P_ADAPTER_T prAdapter, + IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo, IN P_P2P_CHNL_REQ_INFO_T prP2pChnlReqInfo) +{ + + /* AP mode channel hold time. */ + if (prP2pChnlReqInfo->fgIsChannelRequested) + p2pFuncReleaseCh(prAdapter, prP2pRoleFsmInfo->ucBssIndex, prP2pChnlReqInfo); + + cnmTimerStopTimer(prAdapter, &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer)); +} /* p2pRoleStateAbort_IDLE */ + +VOID p2pRoleStateInit_SCAN(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo) +{ + P_P2P_DEV_FSM_INFO_T prP2pDevFsmInfo = (P_P2P_DEV_FSM_INFO_T) NULL; + P_P2P_SCAN_REQ_INFO_T prDevScanReqInfo = NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prScanReqInfo != NULL)); + + prScanReqInfo->fgIsScanRequest = TRUE; + if (prScanReqInfo->u4BufLength == 0) { + /* If we let u4BufLength be zero, scan module will copy the IE buf from ScanParam */ + /* Sometime this content is from AIS, so we need copy it from P2Pdev */ + prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; + if (prP2pDevFsmInfo) { + prDevScanReqInfo = &(prP2pDevFsmInfo->rScanReqInfo); + if (prDevScanReqInfo->u4BufLength != 0) { + /* IE Buffer */ + kalMemCopy(prScanReqInfo->aucIEBuf, prDevScanReqInfo->aucIEBuf, + prDevScanReqInfo->u4BufLength); + prScanReqInfo->u4BufLength = prDevScanReqInfo->u4BufLength; + DBGLOG(P2P, TRACE, "p2pRoleStateInit_SCAN Copy p2p IE from P2P dev\n"); + } + } else + DBGLOG(P2P, ERROR, "No prP2pDevFsmInfo ptr\n"); + } + p2pFuncRequestScan(prAdapter, ucBssIndex, prScanReqInfo); + } while (FALSE); +} /* p2pRoleStateInit_SCAN */ + +VOID p2pRoleStateAbort_SCAN(IN P_ADAPTER_T prAdapter, IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo) +{ + P_P2P_SCAN_REQ_INFO_T prScanInfo = (P_P2P_SCAN_REQ_INFO_T) NULL; + + do { + prScanInfo = &prP2pRoleFsmInfo->rScanReqInfo; + + p2pFuncCancelScan(prAdapter, prP2pRoleFsmInfo->ucBssIndex, prScanInfo); + + /* TODO: May need indicate port index to upper layer. */ + kalP2PIndicateScanDone(prAdapter->prGlueInfo, prP2pRoleFsmInfo->ucRoleIndex, prScanInfo->fgIsAbort); + } while (FALSE); +} /* p2pRoleStateAbort_SCAN */ + +VOID +p2pRoleStateInit_REQING_CHANNEL(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo) +{ + + do { + ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL)); + + p2pFuncAcquireCh(prAdapter, ucBssIdx, prChnlReqInfo); + + } while (FALSE); +} /* p2pRoleStateInit_REQING_CHANNEL */ + +VOID +p2pRoleStateAbort_REQING_CHANNEL(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pRoleBssInfo, + IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo, IN ENUM_P2P_ROLE_STATE_T eNextState) +{ + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pRoleBssInfo != NULL) && (prP2pRoleFsmInfo != NULL)); + + if (eNextState == P2P_ROLE_STATE_IDLE) { + if (prP2pRoleBssInfo->eIntendOPMode == OP_MODE_ACCESS_POINT) { + P_P2P_CHNL_REQ_INFO_T prP2pChnlReqInfo = &(prP2pRoleFsmInfo->rChnlReqInfo); + + if (IS_NET_PWR_STATE_ACTIVE(prAdapter, prP2pRoleFsmInfo->ucBssIndex)) + p2pFuncStartGO(prAdapter, + prP2pRoleBssInfo, + &(prP2pRoleFsmInfo->rConnReqInfo), + &(prP2pRoleFsmInfo->rChnlReqInfo)); + else if (prP2pChnlReqInfo->fgIsChannelRequested) + p2pFuncReleaseCh(prAdapter, prP2pRoleFsmInfo->ucBssIndex, prP2pChnlReqInfo); + } else { + p2pFuncReleaseCh(prAdapter, prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rChnlReqInfo)); + } + } + } while (FALSE); +} /* p2pRoleStateAbort_REQING_CHANNEL */ + +VOID +p2pRoleStateInit_AP_CHNL_DETECTION(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucBssIndex, + IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo, IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo) +{ + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + P_BSS_INFO_T prBssInfo = NULL; + UINT_8 ucPreferedChnl = 0; + ENUM_BAND_T eBand = BAND_NULL; + ENUM_CHNL_EXT_T eSco = CHNL_EXT_SCN; + + do { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + ASSERT_BREAK((prAdapter != NULL) && (prScanReqInfo != NULL) + && (prConnReqInfo != NULL) && (prBssInfo != NULL)); + + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo[prBssInfo->u4PrivateData]; + + if ((cnmPreferredChannel(prAdapter, + &eBand, + &ucPreferedChnl, + &eSco) == FALSE) && (prConnReqInfo->rChannelInfo.ucChannelNum == 0)) { + /* Sparse channel detection. */ + prP2pSpecificBssInfo->ucPreferredChannel = 0; + + prScanReqInfo->eScanType = SCAN_TYPE_PASSIVE_SCAN; + prScanReqInfo->u2PassiveDewellTime = 50; /* 50ms for passive channel load detection */ + } else { + /* Active scan to shorten scan time. */ + prScanReqInfo->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prScanReqInfo->u2PassiveDewellTime = 0; + + if (prConnReqInfo->rChannelInfo.ucChannelNum != 0) { + prP2pSpecificBssInfo->ucPreferredChannel = prConnReqInfo->rChannelInfo.ucChannelNum; + prP2pSpecificBssInfo->eRfBand = prConnReqInfo->rChannelInfo.eBand; + prP2pSpecificBssInfo->eRfSco = CHNL_EXT_SCN; + } else { + prP2pSpecificBssInfo->ucPreferredChannel = ucPreferedChnl; + prP2pSpecificBssInfo->eRfBand = eBand; + prP2pSpecificBssInfo->eRfSco = eSco; + } + + } + + /* TODO: See if channel set to include 5G or only 2.4G */ + prScanReqInfo->eChannelSet = SCAN_CHANNEL_2G4; + + prScanReqInfo->fgIsAbort = TRUE; + prScanReqInfo->fgIsScanRequest = TRUE; + prScanReqInfo->ucNumChannelList = 0; + prScanReqInfo->u4BufLength = 0; + prScanReqInfo->ucSsidNum = 1; + prScanReqInfo->arSsidStruct[0].ucSsidLen = 0; + + p2pFuncRequestScan(prAdapter, ucBssIndex, prScanReqInfo); + + } while (FALSE); + + return; + +} /* p2pRoleStateInit_AP_CHNL_DETECTION */ + +VOID +p2pRoleStateAbort_AP_CHNL_DETECTION(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucBssIndex, + IN P_P2P_CONNECTION_REQ_INFO_T prP2pConnReqInfo, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, + IN P_P2P_SCAN_REQ_INFO_T prP2pScanReqInfo, IN ENUM_P2P_ROLE_STATE_T eNextState) +{ + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + P_BSS_INFO_T prBssInfo = NULL; + + do { + if (eNextState == P2P_ROLE_STATE_REQING_CHANNEL) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo[prBssInfo->u4PrivateData]; + + if (prP2pSpecificBssInfo->ucPreferredChannel == 0) { + if (scnQuerySparseChannel(prAdapter, + &prP2pSpecificBssInfo->eRfBand, + &prP2pSpecificBssInfo->ucPreferredChannel)) { + prP2pSpecificBssInfo->eRfSco = CHNL_EXT_SCN; + } else { + DBGLOG(P2P, ERROR, "Sparse Channel Error, use default settings\n"); + /* Sparse channel false. */ + prP2pSpecificBssInfo->ucPreferredChannel = P2P_DEFAULT_LISTEN_CHANNEL; + prP2pSpecificBssInfo->eRfBand = BAND_2G4; + prP2pSpecificBssInfo->eRfSco = CHNL_EXT_SCN; + } + } + + prChnlReqInfo->u8Cookie = 0; + prChnlReqInfo->ucReqChnlNum = prP2pSpecificBssInfo->ucPreferredChannel; + prChnlReqInfo->eBand = prP2pSpecificBssInfo->eRfBand; + prChnlReqInfo->eChnlSco = prP2pSpecificBssInfo->eRfSco; + prChnlReqInfo->u4MaxInterval = P2P_AP_CHNL_HOLD_TIME_MS; + prChnlReqInfo->eChnlReqType = CH_REQ_TYPE_GO_START_BSS; + + prChnlReqInfo->eChannelWidth = CW_20_40MHZ; + prChnlReqInfo->ucCenterFreqS1 = 0; + prChnlReqInfo->ucCenterFreqS2 = 0; + + } else { + p2pFuncCancelScan(prAdapter, ucBssIndex, prP2pScanReqInfo); + } + } while (FALSE); +} + +VOID +p2pRoleStateInit_GC_JOIN(IN P_ADAPTER_T prAdapter, + IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo) +{ + /* P_MSG_JOIN_REQ_T prJoinReqMsg = (P_MSG_JOIN_REQ_T)NULL; */ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pRoleFsmInfo != NULL) && (prChnlReqInfo != NULL)); + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prP2pRoleFsmInfo->ucBssIndex); + + /* Setup a join timer. */ + DBGLOG(P2P, TRACE, "Start a join init timer\n"); + cnmTimerStartTimer(prAdapter, + &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer), + (prChnlReqInfo->u4MaxInterval - AIS_JOIN_CH_GRANT_THRESHOLD)); + + p2pFuncGCJoin(prAdapter, prP2pBssInfo, &(prP2pRoleFsmInfo->rJoinInfo)); + + } while (FALSE); +} /* p2pRoleStateInit_GC_JOIN */ + +VOID +p2pRoleStateAbort_GC_JOIN(IN P_ADAPTER_T prAdapter, + IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo, + IN P_P2P_JOIN_INFO_T prJoinInfo, IN ENUM_P2P_ROLE_STATE_T eNextState) +{ + do { + + if (prJoinInfo->fgIsJoinComplete == FALSE) { + P_MSG_JOIN_ABORT_T prJoinAbortMsg = (P_MSG_JOIN_ABORT_T) NULL; + + 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, &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer)); + + /* Release channel requested. */ + p2pFuncReleaseCh(prAdapter, prP2pRoleFsmInfo->ucBssIndex, &(prP2pRoleFsmInfo->rChnlReqInfo)); + } while (FALSE); +} + +#if (CFG_SUPPORT_DFS_MASTER == 1) +VOID +p2pRoleStateInit_DFS_CAC(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo) +{ + + do { + ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL)); + + p2pFuncAcquireCh(prAdapter, ucBssIdx, prChnlReqInfo); + } while (FALSE); +} /* p2pRoleStateInit_DFS_CAC */ + +VOID +p2pRoleStateAbort_DFS_CAC(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pRoleBssInfo, + IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo, IN ENUM_P2P_ROLE_STATE_T eNextState) +{ + do { + cnmTimerStopTimer(prAdapter, &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer)); + + p2pFuncReleaseCh(prAdapter, prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rChnlReqInfo)); + } while (FALSE); +} /* p2pRoleStateAbort_DFS_CAC */ + +VOID +p2pRoleStateInit_SWITCH_CHANNEL(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo) +{ + + do { + ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL)); + + p2pFuncAcquireCh(prAdapter, ucBssIdx, prChnlReqInfo); + } while (FALSE); +} /* p2pRoleStateInit_SWITCH_CHANNEL */ + +VOID +p2pRoleStateAbort_SWITCH_CHANNEL(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pRoleBssInfo, + IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo, IN ENUM_P2P_ROLE_STATE_T eNextState) +{ + do { + p2pFuncReleaseCh(prAdapter, prP2pRoleFsmInfo->ucBssIndex, + &(prP2pRoleFsmInfo->rChnlReqInfo)); + } while (FALSE); +} /* p2pRoleStateAbort_SWITCH_CHANNEL */ +#endif + +VOID +p2pRoleStatePrepare_To_REQING_CHANNEL_STATE(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, + IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo, + OUT P_P2P_CHNL_REQ_INFO_T prChnlReqInfo) +{ + ENUM_BAND_T eBandBackup; + UINT_8 ucChannelBackup; + ENUM_CHNL_EXT_T eSCOBackup; + + do { + /* P2P BSS info is for temporarily use + * Request a 80MHz channel before starting AP/GO + * to prevent from STA/GC connected too early (before CH abort) + * Therefore, STA/GC Rate will drop during DHCP exchange packets + */ + + /* Previous issue: + * Always request 20MHz channel, but carry 40MHz HT cap/80MHz VHT cap, + * then if GC/STA connected before CH abort, + * GO/AP cannot listen to GC/STA's 40MHz/80MHz packets. + */ + + eBandBackup = prBssInfo->eBand; + ucChannelBackup = prBssInfo->ucPrimaryChannel; + eSCOBackup = prBssInfo->eBssSCO; + + prBssInfo->ucPrimaryChannel = prConnReqInfo->rChannelInfo.ucChannelNum; + prBssInfo->eBand = prConnReqInfo->rChannelInfo.eBand; + + prBssInfo->eBssSCO = rlmGetScoForAP(prAdapter, prBssInfo); + + ASSERT_BREAK((prAdapter != NULL) && (prConnReqInfo != NULL) && (prChnlReqInfo != NULL)); + prChnlReqInfo->u8Cookie = 0; + prChnlReqInfo->ucReqChnlNum = prConnReqInfo->rChannelInfo.ucChannelNum; + prChnlReqInfo->eBand = prConnReqInfo->rChannelInfo.eBand; + prChnlReqInfo->eChnlSco = prBssInfo->eBssSCO; + prChnlReqInfo->u4MaxInterval = P2P_AP_CHNL_HOLD_TIME_MS; + prChnlReqInfo->eChnlReqType = CH_REQ_TYPE_GO_START_BSS; + + + /*rlmBssInitForAP would decide the real AP bandwidth*/ + prBssInfo->ucVhtChannelWidth = + cnmGetBssMaxBwToChnlBW(prAdapter, prBssInfo->ucBssIndex); + prChnlReqInfo->eChannelWidth = prBssInfo->ucVhtChannelWidth; + if (prChnlReqInfo->eChannelWidth == VHT_OP_CHANNEL_WIDTH_80P80) { + /* TODO: BW80+80 support */ + DBGLOG(RLM, WARN, "BW80+80 not support. Fallback to VHT_OP_CHANNEL_WIDTH_20_40\n"); + prChnlReqInfo->eChannelWidth = VHT_OP_CHANNEL_WIDTH_20_40; + prChnlReqInfo->ucCenterFreqS1 = 0; + prChnlReqInfo->ucCenterFreqS2 = 0; + } else { + prChnlReqInfo->ucCenterFreqS1 = + rlmGetVhtS1ForAP(prAdapter, prBssInfo); + prChnlReqInfo->ucCenterFreqS2 = 0; + } + + /* If the S1 is invalid, force to change bandwidth */ + if ((prBssInfo->eBand == BAND_5G) && + (prChnlReqInfo->ucCenterFreqS1 == 0)) + prChnlReqInfo->eChannelWidth = VHT_OP_CHANNEL_WIDTH_20_40; + + DBGLOG(P2P, TRACE, "p2pRoleStatePrepare_To_REQING_CHANNEL_STATE\n"); + + /* Reset */ + prBssInfo->ucPrimaryChannel = ucChannelBackup; + prBssInfo->eBand = eBandBackup; + prBssInfo->eBssSCO = eSCOBackup; + } while (FALSE); +} + +#if (CFG_SUPPORT_DFS_MASTER == 1) +VOID +p2pRoleStatePrepare_To_DFS_CAC_STATE(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, + IN ENUM_CHANNEL_WIDTH_T rChannelWidth, + IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo, + OUT P_P2P_CHNL_REQ_INFO_T prChnlReqInfo) +{ + ENUM_BAND_T eBandBackup; + UINT_8 ucChannelBackup; + ENUM_CHNL_EXT_T eSCOBackup; + P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL; + + do { + + eBandBackup = prBssInfo->eBand; + ucChannelBackup = prBssInfo->ucPrimaryChannel; + eSCOBackup = prBssInfo->eBssSCO; + + prBssInfo->ucPrimaryChannel = prConnReqInfo->rChannelInfo.ucChannelNum; + prBssInfo->eBand = prConnReqInfo->rChannelInfo.eBand; + + prBssInfo->eBssSCO = rlmGetScoForAP(prAdapter, prBssInfo); + + prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, prBssInfo->u4PrivateData); + + ASSERT_BREAK((prAdapter != NULL) && (prConnReqInfo != NULL) && (prChnlReqInfo != NULL)); + prChnlReqInfo->u8Cookie = 0; + prChnlReqInfo->ucReqChnlNum = prConnReqInfo->rChannelInfo.ucChannelNum; + prChnlReqInfo->eBand = prConnReqInfo->rChannelInfo.eBand; + prChnlReqInfo->eChnlSco = prBssInfo->eBssSCO; + prChnlReqInfo->u4MaxInterval = + prAdapter->prGlueInfo->prP2PInfo[prP2pRoleFsmInfo->ucRoleIndex]->cac_time_ms; + prChnlReqInfo->eChnlReqType = CH_REQ_TYPE_DFS_CAC; + + prBssInfo->ucVhtChannelWidth = + cnmGetBssMaxBwToChnlBW(prAdapter, prBssInfo->ucBssIndex); + prChnlReqInfo->eChannelWidth = prBssInfo->ucVhtChannelWidth; + + if (prChnlReqInfo->eChannelWidth == VHT_OP_CHANNEL_WIDTH_80P80) { + /* TODO: BW80+80 support */ + DBGLOG(RLM, WARN, "BW80+80 not support. Fallback to VHT_OP_CHANNEL_WIDTH_20_40\n"); + prChnlReqInfo->eChannelWidth = VHT_OP_CHANNEL_WIDTH_20_40; + prChnlReqInfo->ucCenterFreqS1 = 0; + prChnlReqInfo->ucCenterFreqS2 = 0; + } else { + prChnlReqInfo->ucCenterFreqS1 = + rlmGetVhtS1ForAP(prAdapter, prBssInfo); + prChnlReqInfo->ucCenterFreqS2 = 0; + } + + DBGLOG(P2P, TRACE, "p2pRoleStatePrepare_To_REQING_CHANNEL_STATE\n"); + + /* Reset */ + prBssInfo->ucPrimaryChannel = ucChannelBackup; + prBssInfo->eBand = eBandBackup; + prBssInfo->eBssSCO = eSCOBackup; + } while (FALSE); +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_scan.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_scan.c new file mode 100644 index 0000000000000..50a453aa76dc6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/p2p_scan.c @@ -0,0 +1,284 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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 +******************************************************************************** +*/ + +VOID +scanP2pProcessBeaconAndProbeResp(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN P_WLAN_STATUS prStatus, + IN P_BSS_DESC_T prBssDesc, IN P_WLAN_BEACON_FRAME_T prWlanBeaconFrame) +{ + BOOLEAN fgIsSkipThisBeacon = FALSE; + + /* Indicate network to kernel for P2P interface when: + * 1. This is P2P network + * 2. Driver is configured to report all networks + */ + if (prBssDesc->fgIsP2PPresent || prAdapter->p2p_scan_report_all_bss) { + if ((prBssDesc->fgIsConnected) && /* P2P GC connected. */ + ((prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_BEACON) /* TX Beacon */ + ) { + UINT_32 u4Idx = 0; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + for (u4Idx = 0; u4Idx < BSS_INFO_NUM; u4Idx++) { + /* Check BSS for P2P. */ + /* Check BSSID. */ + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, (UINT_8) u4Idx); + + if (!IS_BSS_ACTIVE(prP2pBssInfo)) + continue; + + if ((prP2pBssInfo->eNetworkType != NETWORK_TYPE_P2P) || + (UNEQUAL_MAC_ADDR(prP2pBssInfo->aucBSSID, prBssDesc->aucBSSID) + || + (!EQUAL_SSID + (prP2pBssInfo->aucSSID, prP2pBssInfo->ucSSIDLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen)))) { + continue; + } + if ((prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) && /* P2P GC */ + (prP2pBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED)) { /* Connected */ + fgIsSkipThisBeacon = TRUE; + if ((!prP2pBssInfo->ucDTIMPeriod)) { /* First Time. */ + prP2pBssInfo->ucDTIMPeriod = prBssDesc->ucDTIMPeriod; + nicPmIndicateBssConnected(prAdapter, prP2pBssInfo->ucBssIndex); + } + } + + } + + } + + 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 except passive scan. */ + /* Probe response collect much more information. */ + if (fgIsSkipThisBeacon) + break; + } + + rChannelInfo.ucChannelNum = prBssDesc->ucChannelNum; + rChannelInfo.eBand = prBssDesc->eBand; + prBssDesc->fgIsP2PReport = TRUE; + + DBGLOG(P2P, INFO, "indicate %s [%d]\n", + prBssDesc->aucSSID, + prBssDesc->ucChannelNum); + + kalP2PIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) prSwRfb->pvHeader, + (UINT_32) prSwRfb->u2PacketLen, + &rChannelInfo, RCPI_TO_dBm(prBssDesc->ucRCPI)); + + } while (FALSE); + } +} + +VOID scnEventReturnChannel(IN P_ADAPTER_T prAdapter, IN UINT_8 ucScnSeqNum) +{ + + CMD_SCAN_CANCEL rCmdScanCancel; + + /* send cancel message to firmware domain */ + rCmdScanCancel.ucSeqNum = ucScnSeqNum; + rCmdScanCancel.ucIsExtChannel = (UINT_8) FALSE; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SCAN_CANCEL, + TRUE, + FALSE, FALSE, NULL, NULL, sizeof(CMD_SCAN_CANCEL), (PUINT_8)&rCmdScanCancel, NULL, 0); +} /* scnEventReturnChannel */ + +VOID scanRemoveAllP2pBssDesc(IN P_ADAPTER_T prAdapter) +{ + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc; + P_BSS_DESC_T prBSSDescNext; + + ASSERT(prAdapter); + + prBSSDescList = &(prAdapter->rWifiVar.rScanInfo.rBSSDescList); + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) { + scanRemoveP2pBssDesc(prAdapter, prBssDesc); + } +} /* scanRemoveAllP2pBssDesc */ + +VOID scanRemoveP2pBssDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) +{ +} /* scanRemoveP2pBssDesc */ + +P_BSS_DESC_T scanP2pSearchDesc(IN P_ADAPTER_T prAdapter, IN P_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) || (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); *//*let p2p re-scan again */ + continue; + } + + if (!prBssDesc->fgIsP2PPresent) { + DBGLOG(P2P, ERROR, "SSID, BSSID, BSSTYPE match, but no P2P IE present.\n"); + continue; + } + + /* Final decision. */ + prCandidateBssDesc = prBssDesc; + break; + } + + } while (FALSE); + + return prCandidateBssDesc; +} /* scanP2pSearchDesc */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/privacy.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/privacy.c new file mode 100644 index 0000000000000..17c6a0bf09661 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/privacy.c @@ -0,0 +1,1250 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: 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 +* +*/ + + +/******************************************************************************* +* C O M P I L E 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 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 ucBssIndex) +{ + 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 = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + prBssInfo->u4RsnSelectedGroupCipher = 0; + prBssInfo->u4RsnSelectedPairwiseCipher = 0; + prBssInfo->u4RsnSelectedAKMSuite = 0; + +#if 0 /* CFG_ENABLE_WIFI_DIRECT */ + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P]; + + prBssInfo->u4RsnSelectedGroupCipher = RSN_CIPHER_SUITE_CCMP; + prBssInfo->u4RsnSelectedPairwiseCipher = RSN_CIPHER_SUITE_CCMP; + prBssInfo->u4RsnSelectedAKMSuite = RSN_AKM_SUITE_PSK; +#endif + +#if 0 /* CFG_ENABLE_BT_OVER_WIFI */ + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW]; + + 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; +#if CFG_SUPPORT_CFG80211_AUTH + prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[8] + .dot11RSNAConfigPairwiseCipher = + RSN_CIPHER_SUITE_GROUP_NOT_USED; + prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[9] + .dot11RSNAConfigPairwiseCipher = RSN_CIPHER_SUITE_GCMP_256; +#endif + + 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 +#if CFG_SUPPORT_CFG80211_AUTH + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[8] + .dot11RSNAConfigAuthenticationSuite + = RSN_AKM_SUITE_8021X_SUITE_B; + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[9] + .dot11RSNAConfigAuthenticationSuite + = RSN_AKM_SUITE_8021X_SUITE_B_192; + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[10] + .dot11RSNAConfigAuthenticationSuite + = RSN_AKM_SUITE_SAE; + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[11] + .dot11RSNAConfigAuthenticationSuite + = RSN_AKM_SUITE_OWE; +#endif + + + for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) { + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[i].dot11RSNAConfigAuthenticationSuiteEnabled = + FALSE; + } + + secClearPmkid(prAdapter); + + cnmTimerInitTimer(prAdapter, + &prAisSpecBssInfo->rPreauthenticationTimer, + (PFN_MGMT_TIMEOUT_FUNC) rsnIndicatePmkidCand, (ULONG) NULL); + +#if CFG_SUPPORT_802_11W + cnmTimerInitTimer(prAdapter, + &prAisSpecBssInfo->rSaQueryTimer, (PFN_MGMT_TIMEOUT_FUNC) rsnStartSaQueryTimer, (ULONG) NULL); +#endif + + prAisSpecBssInfo->fgCounterMeasure = FALSE; + prAdapter->prAisBssInfo->ucBcDefaultKeyIdx = 0xff; + prAdapter->prAisBssInfo->fgBcDefaultKeyExist = FALSE; + +#if 0 + for (i = 0; i < WTBL_SIZE; i++) { + g_prWifiVar->arWtbl[i].ucUsed = 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) +{ + P_HW_MAC_RX_DESC_T prRxStatus; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxStatus = prSwRfb->prRxStatus; + +#if 1 + if (!prStaRec || (prRxStatus->u2StatusFlag & RXS_DW2_RX_CLASSERR_BITMAP) == RXS_DW2_RX_CLASSERR_VALUE) { + + DBGLOG(RSN, TRACE, + "prStaRec=%p RX Status = 0x%x RX_CLASSERR check!\n", + prStaRec, + prRxStatus->u2StatusFlag); + + /* if (IS_NET_ACTIVE(prAdapter, ucBssIndex)) { */ + authSendDeauthFrame(prAdapter, + NULL, NULL, prSwRfb, REASON_CODE_CLASS_3_ERR, (PFN_TX_DONE_HANDLER) NULL); + return FALSE; + /* } */ + } +#else + if ((prStaRec) && 1 /* RXM_IS_DATA_FRAME(prSwRfb) */) { + UINT_8 ucBssIndex = prStaRec->ucBssIndex; + + if (IS_NET_ACTIVE(prAdapter, ucBssIndex)) { + /* P_BSS_INFO_T prBssInfo; */ + /* prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); */ + + if ((prRxStatus->u2StatusFlag & RXS_DW2_RX_CLASSERR_BITMAP) == RXS_DW2_RX_CLASSERR_VALUE) { + /*if ((STA_STATE_3 != prStaRec->ucStaState) && + * IS_BSS_ACTIVE(prBssInfo) && + * prBssInfo->fgIsNetAbsent == FALSE) { + * (IS_AP_STA(prStaRec) || IS_CLIENT_STA(prStaRec))) { + */ + if (authSendDeauthFrame(prAdapter, + prStaRec, + NULL, + REASON_CODE_CLASS_3_ERR, + (PFN_TX_DONE_HANDLER) + NULL) == WLAN_STATUS_SUCCESS) { + DBGLOG(RSN, TRACE, + ("Send Deauth to MAC:[" MACSTR + "] for Rx Class 3 Error.\n", MAC2STR(prStaRec->aucMacAddr))); + } + + return FALSE; + } + + return secRxPortControlCheck(prAdapter, prSwRfb); + } + } +#endif + return TRUE; + +} /* 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 0 /* Marked for MT6630 */ + if (prSta == NULL) + return; + + prSta->fgPortBlock = fgPortBlock; + + DBGLOG(RSN, TRACE, + "The STA " MACSTR " port %s\n", MAC2STR(prSta->aucMacAddr), fgPortBlock == TRUE ? "BLOCK" : " OPEN"); +#endif +} + +#if 0 /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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; +} +#endif /* Marked for MT6630 */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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) { +#if CFG_SUPPORT_SUITB + case RSN_CIPHER_SUITE_GCMP_256: + if (u4CipherSuitesFlags & CIPHER_FLAG_GCMP256) + prEntry->dot11RSNAConfigPairwiseCipherEnabled + = TRUE; + else + prEntry->dot11RSNAConfigPairwiseCipherEnabled + = FALSE; + break; +#endif + 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; +#if CFG_SUPPORT_SUITB + else if (rsnSearchSupportedCipher(prAdapter, + RSN_CIPHER_SUITE_GROUP_NOT_USED, &i)) + prMib->dot11RSNAConfigGroupCipher = + RSN_CIPHER_SUITE_GROUP_NOT_USED; + else if (rsnSearchSupportedCipher(prAdapter, + RSN_CIPHER_SUITE_GCMP_256, &i)) + prMib->dot11RSNAConfigGroupCipher = + RSN_CIPHER_SUITE_GCMP_256; +#endif + else + prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_NONE; + +} /* secSetCipherSuite */ + +/*----------------------------------------------------------------------------*/ +/*! +* \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 802.11 privacy is enabled. +* +* \param[in] prAdapter Pointer to the Adapter structure +* +* \retval BOOLEAN +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN secEnabledInAis(IN P_ADAPTER_T prAdapter) +{ + DEBUGFUNC("secEnabledInAis"); + + ASSERT(prAdapter->rWifiVar.rConnSettings.eEncStatus < + ENUM_ENCRYPTION_NUM); + + if ((prAdapter->rWifiVar.rConnSettings.eEncStatus + == ENUM_ENCRYPTION1_ENABLED) + || (prAdapter->rWifiVar.rConnSettings.eEncStatus + == ENUM_ENCRYPTION2_ENABLED) + || (prAdapter->rWifiVar.rConnSettings.eEncStatus + == ENUM_ENCRYPTION3_ENABLED) +#if CFG_SUPPORT_SUITB + || (prAdapter->rWifiVar.rConnSettings.eEncStatus + == ENUM_ENCRYPTION4_ENABLED) +#endif + ) + return TRUE; + else if (prAdapter->rWifiVar.rConnSettings.eEncStatus + == ENUM_ENCRYPTION_DISABLED) + DBGLOG(RSN, TRACE, "Unknown encryption setting %d\n", + prAdapter->rWifiVar.rConnSettings.eEncStatus); + return FALSE; +} /* secEnabledInAis */ + +BOOLEAN secIsProtected1xFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + + if (prStaRec) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + if (prBssInfo && prBssInfo->eNetworkType == NETWORK_TYPE_AIS) { +#if CFG_SUPPORT_WAPI + if (wlanQueryWapiMode(prAdapter)) + return FALSE; +#endif + } + + return prStaRec->fgTransmitKeyExist; + } + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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) +{ + /* P_BSS_INFO_T prBssInfo; */ + + ASSERT(prAdapter); + ASSERT(prMsdu); + /* ASSERT(prStaRec); */ + +#if CFG_SUPPORT_802_11W + if (prMsdu->ucPacketType == TX_PACKET_TYPE_MGMT) { +#if 0 /* Decide by Compose module */ + BOOL fgRobustActionWithProtect = FALSE; + P_BSS_INFO_T prBssInfo; + + if (prStaRec) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + ASSERT(prBssInfo); + if ((prBssInfo->eNetworkType == NETWORK_TYPE_AIS) && + prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection /* Use MFP */) { + + fgRobustActionWithProtect = TRUE; + return TRUE; /* AIS & Robust action frame */ + } + } +#endif + return FALSE; + } +#else + if (prMsdu->ucPacketType == TX_PACKET_TYPE_MGMT) + return FALSE; +#endif + + return secIsProtectedBss(prAdapter, GET_BSS_INFO_BY_INDEX(prAdapter, prMsdu->ucBssIndex)); +} + +BOOLEAN secIsProtectedBss(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo) +{ + ASSERT(prBssInfo); + + if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) { +#if CFG_SUPPORT_WAPI + if (wlanQueryWapiMode(prAdapter)) + return TRUE; +#endif + return secEnabledInAis(prAdapter); + } +#if CFG_ENABLE_WIFI_DIRECT + else if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) + return kalP2PGetCipher(prAdapter->prGlueInfo, (UINT_8) prBssInfo->u4PrivateData); +#endif + else if (prBssInfo->eNetworkType == NETWORK_TYPE_BOW) + return TRUE; + + ASSERT(FALSE); + return FALSE; +} + +BOOLEAN secIsUsedByStaRecEntry(IN P_ADAPTER_T prAdapter, IN UINT_8 Index) +{ + P_STA_RECORD_T prStaRec = NULL; + UINT_8 i = 0; + BOOLEAN fgIsUsed = FALSE; + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + if (prStaRec->fgIsInUse && prStaRec->ucWlanIndex == Index) { + fgIsUsed = TRUE; + DBGLOG(RSN, INFO, + "[Wlan index]: Duplicated entry #%d\n", Index); + break; + } + } + return fgIsUsed; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used before add/update a WLAN entry. +* Info the WLAN Table has available entry for this request +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] prSta the P_STA_RECORD_T for store +* +* \return TRUE Free Wlan table is reserved for this request +* FALSE No free entry for this request +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOL secPrivacySeekForEntry(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + P_BSS_INFO_T prP2pBssInfo; + UINT_8 ucEntry = WTBL_RESERVED_ENTRY; + UINT_8 i; + UINT_8 ucStartIDX = 0, ucMaxIDX = 0; + P_WLAN_TABLE_T prWtbl; + UINT_8 ucRoleIdx = 0; + + ASSERT(prSta); + + if (!prSta->fgIsInUse) + ASSERT(FALSE); + + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prSta->ucBssIndex); + ucRoleIdx = prP2pBssInfo->u4PrivateData; + + prWtbl = prAdapter->rWifiVar.arWtbl; + + ucStartIDX = 0; + ucMaxIDX = NIC_TX_DEFAULT_WLAN_INDEX - 1; + + DBGLOG(RSN, INFO, "secPrivacySeekForEntry\n"); + + for (i = ucStartIDX; i <= ucMaxIDX; i++) { + if (prWtbl[i].ucUsed && EQUAL_MAC_ADDR(prSta->aucMacAddr, prWtbl[i].aucMacAddr) + && prWtbl[i].ucPairwise /* This function for ucPairwise only */) { + ucEntry = i; + DBGLOG(RSN, INFO, "[Wlan index]: Reuse entry #%d\n", i); + break; + } + } + + if (i == (ucMaxIDX + 1)) { + for (i = ucStartIDX; i <= ucMaxIDX; i++) { + if (prWtbl[i].ucUsed == FALSE) { + if (!secIsUsedByStaRecEntry(prAdapter, i)) { + ucEntry = i; + DBGLOG(RSN, INFO, + "[Wlan index]: Assign entry #%d\n", i); + break; + } + } + } + } + + /* Save to the driver maintain table */ + if (ucEntry < NIC_TX_DEFAULT_WLAN_INDEX) { + + prWtbl[ucEntry].ucUsed = TRUE; + prWtbl[ucEntry].ucBssIndex = prSta->ucBssIndex; + prWtbl[ucEntry].ucKeyId = 0xFF; + prWtbl[ucEntry].ucPairwise = 1; + COPY_MAC_ADDR(prWtbl[ucEntry].aucMacAddr, prSta->aucMacAddr); + prWtbl[ucEntry].ucStaIndex = prSta->ucIndex; + + prSta->ucWlanIndex = ucEntry; + + { + P_BSS_INFO_T prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prSta->ucBssIndex); + /* for AP mode , if wep key exist, peer sta should also fgTransmitKeyExist */ + if (IS_BSS_P2P(prBssInfo) && kalP2PGetRole(prAdapter->prGlueInfo, ucRoleIdx) == 2) { + if (prBssInfo->fgBcDefaultKeyExist && + !(kalP2PGetCcmpCipher(prAdapter->prGlueInfo, ucRoleIdx) || + kalP2PGetTkipCipher(prAdapter->prGlueInfo, ucRoleIdx))) { + prSta->fgTransmitKeyExist = TRUE; + prWtbl[ucEntry].ucKeyId = prBssInfo->ucBcDefaultKeyIdx; + DBGLOG(RSN, INFO, "peer sta set fgTransmitKeyExist\n"); + } + } + } + + DBGLOG(RSN, INFO, + "[Wlan index] BSS#%d keyid#%d P=%d use WlanIndex#%d STAIdx=%d " MACSTR + " staType=%x\n", prSta->ucBssIndex, 0, prWtbl[ucEntry].ucPairwise, ucEntry, + prSta->ucIndex, MAC2STR(prSta->aucMacAddr), prSta->eStaType); +#if 1 /* DBG */ + secCheckWTBLAssign(prAdapter); +#endif + return TRUE; + } +#if DBG + secCheckWTBLAssign(prAdapter); +#endif + DBGLOG(RSN, WARN, "[Wlan index] No more wlan table entry available!!!!\n"); + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used free a WLAN entry. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] ucEntry the wlan table index to free +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID secPrivacyFreeForEntry(IN P_ADAPTER_T prAdapter, IN UINT_8 ucEntry) +{ + P_WLAN_TABLE_T prWtbl; + + ASSERT(prAdapter); + + if (ucEntry >= WTBL_SIZE) + return; + + DBGLOG(RSN, INFO, "secPrivacyFreeForEntry %d", ucEntry); + + prWtbl = prAdapter->rWifiVar.arWtbl; + + if (prWtbl[ucEntry].ucUsed) { + prWtbl[ucEntry].ucUsed = FALSE; + prWtbl[ucEntry].ucKeyId = 0xff; + prWtbl[ucEntry].ucBssIndex = MAX_BSS_INDEX + 1; + prWtbl[ucEntry].ucPairwise = 0; + kalMemZero(prWtbl[ucEntry].aucMacAddr, MAC_ADDR_LEN); + prWtbl[ucEntry].ucStaIndex = STA_REC_INDEX_NOT_FOUND; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used free a STA WLAN entry. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] prStaRec the sta which want to free +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID secPrivacyFreeSta(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + UINT_32 entry; + P_WLAN_TABLE_T prWtbl; + + if (!prStaRec) + return; + + prWtbl = prAdapter->rWifiVar.arWtbl; + + for (entry = 0; entry < WTBL_SIZE; entry++) { + /* Consider GTK case !! */ + if (prWtbl[entry].ucUsed && + EQUAL_MAC_ADDR(prStaRec->aucMacAddr, prWtbl[entry].aucMacAddr) && prWtbl[entry].ucPairwise) { +#if 1 /* DBG */ + DBGLOG(RSN, INFO, "Free STA entry (%d)!\n", entry); +#endif + secPrivacyFreeForEntry(prAdapter, entry); + prStaRec->ucWlanIndex = WTBL_RESERVED_ENTRY; + /* prStaRec->ucBMCWlanIndex = WTBL_RESERVED_ENTRY; */ + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used for remove the BC entry of the BSS +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] ucBssIndex The BSS index +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +VOID secRemoveBssBcEntry(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN BOOL fgRoam) +{ + int i; + P_CONNECTION_SETTINGS_T prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + if (!prBssInfo) + return; + + DBGLOG(RSN, INFO, "remove all the key related with BSS!"); + + if (fgRoam) { + if (IS_BSS_AIS(prBssInfo) && + prBssInfo->prStaRecOfAP && (prConnSettings->eAuthMode >= AUTH_MODE_WPA && + prConnSettings->eAuthMode != AUTH_MODE_WPA_NONE)) { + + for (i = 0; i < MAX_KEY_NUM; i++) { + if (prBssInfo->ucBMCWlanIndexSUsed[i]) + secPrivacyFreeForEntry(prAdapter, prBssInfo->ucBMCWlanIndexS[i]); + +#if 0 + /* move to cfg delete cb function for sync. */ + prBssInfo->ucBMCWlanIndexSUsed[i] = FALSE; + prBssInfo->ucBMCWlanIndexS[i] = WTBL_RESERVED_ENTRY; +#endif + } + + prBssInfo->fgBcDefaultKeyExist = FALSE; + prBssInfo->ucBcDefaultKeyIdx = 0xff; + } + } else { + /* According to wh.su's comment, it's ok to change to + * reserved_entry here so that the entry is _NOT_ freed at all. + * In this way, the same BSS(ucBssIndex) could reuse the same + * entry next time in secPrivacySeekForBcEntry(), and we could + * see the following log: "[Wlan index]: Reuse entry ...". + */ + prBssInfo->ucBMCWlanIndex = WTBL_RESERVED_ENTRY; + secPrivacyFreeForEntry(prAdapter, prBssInfo->ucBMCWlanIndex); + + for (i = 0; i < MAX_KEY_NUM; i++) { + /* Not to remove BMC WTBL entries to + * sync with FW's behavior + * + * if (prBssInfo->ucBMCWlanIndexSUsed[i]) + * secPrivacyFreeForEntry(prAdapter, + * prBssInfo->ucBMCWlanIndexS[i]); + */ +#if 0 + /* move to cfg delete cb function for sync. */ + prBssInfo->ucBMCWlanIndexSUsed[i] = FALSE; + prBssInfo->ucBMCWlanIndexS[i] = WTBL_RESERVED_ENTRY; +#endif + } + for (i = 0; i < MAX_KEY_NUM; i++) { + if (prBssInfo->wepkeyUsed[i]) + secPrivacyFreeForEntry(prAdapter, prBssInfo->wepkeyWlanIdx); + prBssInfo->wepkeyUsed[i] = FALSE; + } + prBssInfo->wepkeyWlanIdx = WTBL_RESERVED_ENTRY; + prBssInfo->fgBcDefaultKeyExist = FALSE; + prBssInfo->ucBcDefaultKeyIdx = 0xff; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used for adding the broadcast key used, to assign a wlan table entry +* for reserved the specific entry for these key for +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] ucBssIndex The BSS index +* \param[in] ucNetTypeIdx The Network index +* \param[in] ucAlg the entry assign related with algorithm +* \param[in] ucKeyId The key id +* \param[in] ucTxRx The Type of the key +* +* \return ucEntryIndex The entry to be used, WTBL_ALLOC_FAIL for allocation fail +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 +secPrivacySeekForBcEntry(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucBssIndex, + IN PUINT_8 pucAddr, IN UINT_8 ucStaIdx, IN UINT_8 ucAlg, IN UINT_8 ucKeyId) +{ + UINT_8 ucEntry = WTBL_ALLOC_FAIL; + UINT_8 ucStartIDX = 0, ucMaxIDX = 0; + UINT_8 i; + BOOLEAN fgCheckKeyId = TRUE; + P_WLAN_TABLE_T prWtbl; + P_BSS_INFO_T prBSSInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + prWtbl = prAdapter->rWifiVar.arWtbl; + ASSERT(prAdapter); + ASSERT(pucAddr); + + if (ucAlg == CIPHER_SUITE_WPI || /* CIPHER_SUITE_GCM_WPI || */ + ucAlg == CIPHER_SUITE_WEP40 || + ucAlg == CIPHER_SUITE_WEP104 || ucAlg == CIPHER_SUITE_WEP128 || ucAlg == CIPHER_SUITE_NONE) + fgCheckKeyId = FALSE; + + if (ucKeyId == 0xFF || ucAlg == CIPHER_SUITE_BIP) + fgCheckKeyId = FALSE; + + if (prBSSInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) + fgCheckKeyId = FALSE; + + ucStartIDX = 0; + ucMaxIDX = NIC_TX_DEFAULT_WLAN_INDEX - 1; + + DBGLOG(INIT, INFO, "secPrivacySeekForBcEntry\n"); + DBGLOG(INIT, INFO, "OpMode:%d, NetworkType:%d, CheckKeyId:%d\n", + prBSSInfo->eCurrentOPMode, prBSSInfo->eNetworkType, fgCheckKeyId); + + for (i = ucStartIDX; i <= ucMaxIDX; i++) { + + if (prWtbl[i].ucUsed && !prWtbl[i].ucPairwise && prWtbl[i].ucBssIndex == ucBssIndex) { + + if (!fgCheckKeyId) { + ucEntry = i; + DBGLOG(RSN, INFO, "[Wlan index]: Reuse entry #%d for open/wep/wpi\n", i); + break; + } + + if (fgCheckKeyId && (prWtbl[i].ucKeyId == ucKeyId || prWtbl[i].ucKeyId == 0xFF)) { + ucEntry = i; + DBGLOG(RSN, INFO, "[Wlan index]: Reuse entry #%d\n", i); + break; + } + } + } + + if (i == (ucMaxIDX + 1)) { + for (i = ucStartIDX; i <= ucMaxIDX; i++) { + if (prWtbl[i].ucUsed == FALSE) { + ucEntry = i; + DBGLOG(RSN, INFO, "[Wlan index]: Assign entry #%d\n", i); + break; + } + } + } + + if (ucEntry < NIC_TX_DEFAULT_WLAN_INDEX) { + if (ucAlg != CIPHER_SUITE_BIP) { + prWtbl[ucEntry].ucUsed = TRUE; + prWtbl[ucEntry].ucKeyId = ucKeyId; + prWtbl[ucEntry].ucBssIndex = ucBssIndex; + prWtbl[ucEntry].ucPairwise = 0; + kalMemCopy(prWtbl[ucEntry].aucMacAddr, pucAddr, MAC_ADDR_LEN); + prWtbl[ucEntry].ucStaIndex = ucStaIdx; + } else { + /* BIP no need to dump secCheckWTBLAssign */ + return ucEntry; + } + + DBGLOG(RSN, INFO, + "[Wlan index] BSS#%d keyid#%d P=%d use WlanIndex#%d STAIdx=%d " MACSTR + "\n", ucBssIndex, ucKeyId, prWtbl[ucEntry].ucPairwise, ucEntry, ucStaIdx, MAC2STR(pucAddr)); + + /* DBG */ + secCheckWTBLAssign(prAdapter); + + } else { + secCheckWTBLAssign(prAdapter); + DBGLOG(RSN, ERROR, "[Wlan index] No more wlan entry available!!!!\n"); + } + + return ucEntry; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] prAdapter Pointer to the Adapter structure +* +* \return ucEntryIndex The entry to be used, WTBL_ALLOC_FAIL for allocation fail +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN secCheckWTBLAssign(IN P_ADAPTER_T prAdapter) +{ + + BOOLEAN fgCheckFail = FALSE; + + secPrivacyDumpWTBL(prAdapter); + + /* AIS STA should just has max 2 entry */ + /* Max STA check */ + if (fgCheckFail) + ASSERT(FALSE); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Got the STA record index by wlan index +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] ucWlanIdx The Rx wlan index +* +* \return The STA record index, 0xff for invalid sta index +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 secGetStaIdxByWlanIdx(P_ADAPTER_T prAdapter, UINT_8 ucWlanIdx) +{ + P_WLAN_TABLE_T prWtbl; + + ASSERT(prAdapter); + + if (ucWlanIdx >= WTBL_SIZE) + return STA_REC_INDEX_NOT_FOUND; + + prWtbl = prAdapter->rWifiVar.arWtbl; + + /* DBGLOG(RSN, TRACE, ("secGetStaIdxByWlanIdx=%d "MACSTR" used=%d\n", ucWlanIdx, + * MAC2STR(prWtbl[ucWlanIdx].aucMacAddr), prWtbl[ucWlanIdx].ucUsed)); + */ + + if (prWtbl[ucWlanIdx].ucUsed) + return prWtbl[ucWlanIdx].ucStaIndex; + else + return STA_REC_INDEX_NOT_FOUND; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief At Sw wlan table, got the BSS index by wlan index +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] ucWlanIdx The Rx wlan index +* +* \return The BSS index, 0xff for invalid bss index +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 secGetBssIdxByWlanIdx(P_ADAPTER_T prAdapter, UINT_8 ucWlanIdx) +{ + P_WLAN_TABLE_T prWtbl; + + ASSERT(prAdapter); + + if (ucWlanIdx >= WTBL_SIZE) + return WTBL_RESERVED_ENTRY; + + prWtbl = prAdapter->rWifiVar.arWtbl; + + if (prWtbl[ucWlanIdx].ucUsed) + return prWtbl[ucWlanIdx].ucBssIndex; + else + return WTBL_RESERVED_ENTRY; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Got the STA record index by mac addr +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pucMacAddress MAC Addr +* +* \return The STA record index, 0xff for invalid sta index +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 secLookupStaRecIndexFromTA(P_ADAPTER_T prAdapter, PUINT_8 pucMacAddress) +{ + int i; + P_WLAN_TABLE_T prWtbl; + + ASSERT(prAdapter); + prWtbl = prAdapter->rWifiVar.arWtbl; + + for (i = 0; i < WTBL_SIZE; i++) { + if (prWtbl[i].ucUsed) { + if (EQUAL_MAC_ADDR(pucMacAddress, prWtbl[i].aucMacAddr) && prWtbl[i].ucPairwise) + return prWtbl[i].ucStaIndex; + } + } + + return STA_REC_INDEX_NOT_FOUND; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] prAdapter Pointer to the Adapter structure +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +void secPrivacyDumpWTBL(IN P_ADAPTER_T prAdapter) +{ + P_WLAN_TABLE_T prWtbl; + UINT_8 i; + + prWtbl = prAdapter->rWifiVar.arWtbl; + + DBGLOG(RSN, INFO, "The Wlan index\n"); + + for (i = 0; i < WTBL_SIZE; i++) { + if (prWtbl[i].ucUsed) + DBGLOG(RSN, INFO, + "#%d Used=%d BSSIdx=%d keyid=%d P=%d STA=%d Addr=" MACSTR "\n", i, + prWtbl[i].ucUsed, prWtbl[i].ucBssIndex, prWtbl[i].ucKeyId, + prWtbl[i].ucPairwise, prWtbl[i].ucStaIndex, MAC2STR(prWtbl[i].aucMacAddr)); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Assin the wlan table with the join AP info +* +* \param[in] prAdapter Pointer to the Adapter structure +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +void secPostUpdateAddr(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo) +{ + P_CONNECTION_SETTINGS_T prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + P_WLAN_TABLE_T prWtbl; + + if (IS_BSS_AIS(prBssInfo) && prBssInfo->prStaRecOfAP) { + + if (prConnSettings->eEncStatus == ENUM_ENCRYPTION1_ENABLED) { + + if (prBssInfo->fgBcDefaultKeyExist) { + + prWtbl = &prAdapter->rWifiVar.arWtbl[prBssInfo->wepkeyWlanIdx]; + + kalMemCopy(prWtbl->aucMacAddr, prBssInfo->prStaRecOfAP->aucMacAddr, MAC_ADDR_LEN); + prWtbl->ucStaIndex = prBssInfo->prStaRecOfAP->ucIndex; + DBGLOG(RSN, INFO, "secPostUpdateAddr at [%d] " MACSTR "= STA Index=%d\n", + prBssInfo->wepkeyWlanIdx, MAC2STR(prWtbl->aucMacAddr), + prBssInfo->prStaRecOfAP->ucIndex); + + /* Update the wlan table of the prStaRecOfAP */ + prWtbl = &prAdapter->rWifiVar.arWtbl[prBssInfo->prStaRecOfAP->ucWlanIndex]; + prWtbl->ucKeyId = prBssInfo->ucBcDefaultKeyIdx; + prBssInfo->prStaRecOfAP->fgTransmitKeyExist = TRUE; + } + } + if (prConnSettings->eEncStatus == ENUM_ENCRYPTION_DISABLED) { + prWtbl = &prAdapter->rWifiVar.arWtbl[prBssInfo->ucBMCWlanIndex]; + + kalMemCopy(prWtbl->aucMacAddr, prBssInfo->prStaRecOfAP->aucMacAddr, MAC_ADDR_LEN); + prWtbl->ucStaIndex = prBssInfo->prStaRecOfAP->ucIndex; + DBGLOG(RSN, INFO, "secPostUpdateAddr at [%d] " MACSTR "= STA Index=%d\n", + prBssInfo->ucBMCWlanIndex, MAC2STR(prWtbl->aucMacAddr), + prBssInfo->prStaRecOfAP->ucIndex); + } + } +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/rate.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/rate.c new file mode 100644 index 0000000000000..fd97f312bbe86 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/rate.c @@ -0,0 +1,499 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +/******************************************************************************* +* C O M P I L E 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_VHT_PHY, /* RATE_VHT_PHY_INDEX */ + RATE_HT_PHY /* RATE_HT_PHY_INDEX */ +}; + +static const UINT_8 aucDefaultAckCtsRateIndex[RATE_NUM_SW] = { + RATE_1M_SW_INDEX, /* RATE_1M_SW_INDEX = 0 */ + RATE_2M_SW_INDEX, /* RATE_2M_SW_INDEX */ + RATE_5_5M_SW_INDEX, /* RATE_5_5M_SW_INDEX */ + RATE_11M_SW_INDEX, /* RATE_11M_SW_INDEX */ + RATE_1M_SW_INDEX, /* RATE_22M_SW_INDEX - Not supported */ + RATE_1M_SW_INDEX, /* RATE_33M_SW_INDEX - Not supported */ + RATE_6M_SW_INDEX, /* RATE_6M_SW_INDEX */ + RATE_6M_SW_INDEX, /* RATE_9M_SW_INDEX */ + RATE_12M_SW_INDEX, /* RATE_12M_SW_INDEX */ + RATE_12M_SW_INDEX, /* RATE_18M_SW_INDEX */ + RATE_24M_SW_INDEX, /* RATE_24M_SW_INDEX */ + RATE_24M_SW_INDEX, /* RATE_36M_SW_INDEX */ + RATE_24M_SW_INDEX, /* RATE_48M_SW_INDEX */ + RATE_24M_SW_INDEX /* RATE_54M_SW_INDEX */ +}; + +const BOOLEAN afgIsOFDMRate[RATE_NUM_SW] = { + 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_SW); + + 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_SW_INDEX, j = 0; i < RATE_NUM_SW; 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_SW_INDEX; i >= RATE_1M_SW_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_SW_INDEX; i <= RATE_54M_SW_INDEX; i++) { + if (u2RateSet & BIT(i)) { + *pucLowestRateIndex = (UINT_8) i; + return TRUE; + } + } + + return FALSE; + +} /* end of rateGetLowestRateIndexFromRateSet() */ + +#if 0 /* NOTE(Kevin): For reference */ +/*----------------------------------------------------------------------------*/ +/*! +* \brief Convert the given Data Rates to the Rate Set. +* +* \param[in] pucDataRates Pointer to the Data Rates +* \param[in] ucDataRatesLen Length of given Data Rates +* \param[out] pu2RateSet Pointer to the Rate Set +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rateGetRateSetFromDataRates(IN PUINT_8 pucDataRates, IN UINT_8 ucDataRatesLen, OUT PUINT_16 pu2RateSet) +{ + UINT_16 u2RateSet = 0; + UINT_8 ucRate; + UINT_32 i, j; + + ASSERT(pucDataRates); + ASSERT(pu2RateSet); + + if (pucDataRates) { + for (i = 0; i < ucDataRatesLen; i++) { + ucRate = pucDataRates[i] & RATE_MASK; + + /* Search all valid data rates */ + for (j = 0; j < sizeof(aucDataRate) / sizeof(UINT_8); j++) { + if (ucRate == aucDataRate[j]) { + u2RateSet |= BIT(j); + break; + } + } + } + } + + *pu2RateSet = u2RateSet; + + return; + +} /* end of rateGetRateSetFromDataRates() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Parse the Operational Rate Set and Basic Rate Set to get the corresponding +* ACK/CTS(Respnose) TX Rates. +* +* \param[in] u2OperationalRateSet Operational Rate Set +* \param[in] u2BSSBasicRateSet Basic Rate Set +* \param[out] aucAckCtsRateIndex Pointer to the Ack/Cts Data Rate Buffer +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +rateSetAckCtsDataRatesFromRateSet(IN UINT_16 u2OperationalRateSet, + IN UINT_16 u2BSSBasicRateSet, IN OUT UINT_8 aucAckCtsRateIndex[]) +{ + INT_32 i, j; + + ASSERT(aucAckCtsRateIndex); + ASSERT(u2BSSBasicRateSet == (u2OperationalRateSet & u2BSSBasicRateSet)); + + /* Setup default ACK/CTS response rate */ + kalMemCopy(aucAckCtsRateIndex, (PVOID) aucDefaultAckCtsRateIndex, sizeof(aucDefaultAckCtsRateIndex)); + + for (i = RATE_54M_INDEX; i >= RATE_1M_INDEX; i--) { + if (u2OperationalRateSet & BIT(i)) { + for (j = i; j >= RATE_1M_INDEX; j--) { + if (u2BSSBasicRateSet & BIT(j)) { + /* Reply ACK Frame at the same Modulation Scheme. */ + if ((afgIsOFDMRate[i] && afgIsOFDMRate[j]) || + (!afgIsOFDMRate[i] && !afgIsOFDMRate[j])) + aucAckCtsRateIndex[i] = (UINT_8) j; + break; + } + } + + /* NOTE(Kevin 2008/03/25): Following code is used for those AP which has + * NULL BasicRateSet. + * e.g. If input Operational Rate Set = [18M 12M 9M], Basic Rate Set = NULL. + * Originally we'll get Ack Rate for [18M 12M 9M] is [12M 12M "6M"]. + * Now we'll get Ack Rate for [18M 12M 9M] is [12M 12M 9M], + * The Ack Rate for Tx Rates which are not list in Operational Rate Set is still + * use highest mandatory rate as default. + */ + if (j < RATE_1M_INDEX) { /* The ACK/CTS rate was not found in BasicRateSet */ + if (!(BIT(aucAckCtsRateIndex[i]) & u2OperationalRateSet)) + aucAckCtsRateIndex[i] = (UINT_8) i; + } + } + } + + return; + +} /* end of rateSetAckCtsDataRatesFromRateSet() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Get the proper initial rate from Rate Set according to given RCPI value +* +* \param[in] u2RateSet Rate Set +* \param[in] rRcpi RCPI value from AP or Peer STA +* \param[out] pucInitialRateIndex Pointer to buffer of the initial Rate Index +* +* \retval TRUE Initial Rate Index was found +* \retval FALSE Initial Rate Index was not found +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rateGetBestInitialRateIndex(IN UINT_16 u2RateSet, IN RCPI rRcpi, OUT PUINT_8 pucInitialRateIndex) +{ + UINT_16 u2InitRateSet; + INT_32 i; + + ASSERT(pucInitialRateIndex); + + DBGLOG(MGT, TRACE, "rRcpi = %d\n", rRcpi); + + if (rRcpi >= RCPI_100) { /* Best Signal */ + u2InitRateSet = INITIAL_RATE_SET(RCPI_100); + } else if (rRcpi >= RCPI_80) { /* Better Signal */ + u2InitRateSet = INITIAL_RATE_SET(RCPI_80); + } else if (rRcpi >= RCPI_60) { /* Good Signal */ + u2InitRateSet = INITIAL_RATE_SET(RCPI_60); + } else { /* Worse Signal */ + /* NOTE(Kevin): If return FALSE, we should assign the BSS Basic Rate Index + * (prBssInfo->ucBasicRateIndex) to the initial rate. It was determined in + * function - bssUpdateTxRateForControlFrame(). + */ + return FALSE; + } + + u2RateSet &= u2InitRateSet; + + for (i = RATE_54M_INDEX; i >= RATE_1M_INDEX; i--) { + if (u2RateSet & BIT(i)) { + *pucInitialRateIndex = (UINT_8) i; + return TRUE; + } + } + + return FALSE; + +} /* end of rateGetBestInitialRateIndex() */ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/reg_rule.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/reg_rule.c new file mode 100644 index 0000000000000..adf60f2a47061 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/reg_rule.c @@ -0,0 +1,387 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +/******************************************************************************* +* C O M P I L E 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_SINGLE_SKU == 1) +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) +#include "rlm_domain.h" + +#if 0 +/** + * enum ieee80211_channel_flags - channel flags + * + * Channel flags set by the regulatory control code. + * + * @IEEE80211_CHAN_DISABLED: This channel is disabled. + * @IEEE80211_CHAN_NO_IR: do not initiate radiation, this includes + * sending probe requests or beaconing. + * @IEEE80211_CHAN_RADAR: Radar detection is required on this channel. + * @IEEE80211_CHAN_NO_HT40PLUS: extension channel above this channel + * is not permitted. + * @IEEE80211_CHAN_NO_HT40MINUS: extension channel below this channel + * is not permitted. + * @IEEE80211_CHAN_NO_OFDM: OFDM is not allowed on this channel. + * @IEEE80211_CHAN_NO_80MHZ: If the driver supports 80 MHz on the band, + * this flag indicates that an 80 MHz channel cannot use this + * channel as the control or any of the secondary channels. + * This may be due to the driver or due to regulatory bandwidth + * restrictions. + * @IEEE80211_CHAN_NO_160MHZ: If the driver supports 160 MHz on the band, + * this flag indicates that an 160 MHz channel cannot use this + * channel as the control or any of the secondary channels. + * This may be due to the driver or due to regulatory bandwidth + * restrictions. + * @IEEE80211_CHAN_INDOOR_ONLY: see %NL80211_FREQUENCY_ATTR_INDOOR_ONLY + * @IEEE80211_CHAN_GO_CONCURRENT: see %NL80211_FREQUENCY_ATTR_GO_CONCURRENT + * @IEEE80211_CHAN_NO_20MHZ: 20 MHz bandwidth is not permitted + * on this channel. + * @IEEE80211_CHAN_NO_10MHZ: 10 MHz bandwidth is not permitted + * on this channel. + * + */ +enum ieee80211_channel_flags { + IEEE80211_CHAN_DISABLED = 1<<0, + IEEE80211_CHAN_NO_IR = 1<<1, + /* hole at 1<<2 */ + IEEE80211_CHAN_RADAR = 1<<3, + IEEE80211_CHAN_NO_HT40PLUS = 1<<4, + IEEE80211_CHAN_NO_HT40MINUS = 1<<5, + IEEE80211_CHAN_NO_OFDM = 1<<6, + IEEE80211_CHAN_NO_80MHZ = 1<<7, + IEEE80211_CHAN_NO_160MHZ = 1<<8, + IEEE80211_CHAN_INDOOR_ONLY = 1<<9, + IEEE80211_CHAN_GO_CONCURRENT = 1<<10, + IEEE80211_CHAN_NO_20MHZ = 1<<11, + IEEE80211_CHAN_NO_10MHZ = 1<<12, +}; + +#define IEEE80211_CHAN_NO_HT40 \ + (IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS) + + +struct ieee80211_freq_range { + u32 start_freq_khz; + u32 end_freq_khz; + u32 max_bandwidth_khz; +}; + +struct ieee80211_power_rule { + u32 max_antenna_gain; + u32 max_eirp; +}; + +/** +* enum reg_flags (the same as nl80211_reg_rule_flags) - regulatory rule flags +* +* @NL80211_RRF_NO_OFDM: OFDM modulation not allowed +* @NL80211_RRF_NO_CCK: CCK modulation not allowed +* @NL80211_RRF_NO_INDOOR: indoor operation not allowed +* @NL80211_RRF_NO_OUTDOOR: outdoor operation not allowed +* @NL80211_RRF_DFS: DFS support is required to be used +* @NL80211_RRF_PTP_ONLY: this is only for Point To Point links +* @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links +* @NL80211_RRF_NO_IR: no mechanisms that initiate radiation are allowed, +* this includes probe requests or modes of operation that require +* beaconing. +* @NL80211_RRF_AUTO_BW: maximum available bandwidth should be calculated +* base on contiguous rules and wider channels will be allowed to cross +* multiple contiguous/overlapping frequency ranges. +* @NL80211_RRF_IR_CONCURRENT: See &NL80211_FREQUENCY_ATTR_IR_CONCURRENT +* @NL80211_RRF_NO_HT40MINUS: channels can't be used in HT40- operation +* @NL80211_RRF_NO_HT40PLUS: channels can't be used in HT40+ operation +* @NL80211_RRF_NO_80MHZ: 80MHz operation not allowed +* @NL80211_RRF_NO_160MHZ: 160MHz operation not allowed +*/ +enum reg_flags { + NL80211_RRF_NO_OFDM = 1<<0, + NL80211_RRF_NO_CCK = 1<<1, + NL80211_RRF_NO_INDOOR = 1<<2, + NL80211_RRF_NO_OUTDOOR = 1<<3, + NL80211_RRF_DFS = 1<<4, + NL80211_RRF_PTP_ONLY = 1<<5, + NL80211_RRF_PTMP_ONLY = 1<<6, + NL80211_RRF_NO_IR = 1<<7, + NL80211_RRF_NO_IBSS = 1<<8, + NL80211_RRF_AUTO_BW = 1<<11, + NL80211_RRF_IR_CONCURRENT = 1<<12, + NL80211_RRF_NO_HT40MINUS = 1<<13, + NL80211_RRF_NO_HT40PLUS = 1<<14, + NL80211_RRF_NO_80MHZ = 1<<15, + NL80211_RRF_NO_160MHZ = 1<<16, +}; + +#define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR +#define NL80211_RRF_NO_IBSS NL80211_RRF_NO_IR +#define NL80211_RRF_NO_IR NL80211_RRF_NO_IR +#define NL80211_RRF_NO_HT40 (NL80211_RRF_NO_HT40MINUS |\ + NL80211_RRF_NO_HT40PLUS) +#define NL80211_RRF_GO_CONCURRENT NL80211_RRF_IR_CONCURRENT + +/* For backport compatibility with older userspace */ +#define NL80211_RRF_NO_IR_ALL (NL80211_RRF_NO_IR | __NL80211_RRF_NO_IBSS) + +struct ieee80211_reg_rule { + struct ieee80211_freq_range freq_range; + struct ieee80211_power_rule power_rule; + u32 reg_flags; /*enum reg_flags*/ + u32 dfs_cac_ms; +}; + +struct ieee80211_regdomain { +#define MAX_NUMER_REG_RULES 6 + char alpha2[3]; + u32 n_reg_rules; + enum nl80211_dfs_regions dfs_region; + struct ieee80211_reg_rule reg_rules[MAX_NUMER_REG_RULES]; +}; + + +#define MHZ_TO_KHZ(freq) ((freq) * 1000) +#define KHZ_TO_MHZ(freq) ((freq) / 1000) +#define DBI_TO_MBI(gain) ((gain) * 100) +#define MBI_TO_DBI(gain) ((gain) / 100) +#define DBM_TO_MBM(gain) ((gain) * 100) +#define MBM_TO_DBM(gain) ((gain) / 100) + +#define REG_RULE_EXT(start, end, bw, gain, eirp, dfs_cac, reg_flags) \ +{ \ + .freq_range.start_freq_khz = MHZ_TO_KHZ(start), \ + .freq_range.end_freq_khz = MHZ_TO_KHZ(end), \ + .freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw), \ + .power_rule.max_eirp = DBM_TO_MBM(eirp), \ + .flags = reg_flags, \ + .dfs_cac_ms = dfs_cac, \ +} + +#define REG_RULE(start, end, bw, gain, eirp, reg_flags) \ +{ \ + .freq_range.start_freq_khz = MHZ_TO_KHZ(start), \ + .freq_range.end_freq_khz = MHZ_TO_KHZ(end), \ + .freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw), \ + .power_rule.max_antenna_gain = DBI_TO_MBI(gain),\ + .power_rule.max_eirp = DBM_TO_MBM(eirp), \ + .flags = reg_flags, \ +} +#endif + +/*************************************************** + * Hello ^++++^ + * Here to describe the regulatory rules of yours. + **************************************************/ + +/* + * Step1. Decclare struct ieee80211_regdomain + */ + +const struct ieee80211_regdomain regdom_us01 = { + .n_reg_rules = 6, + .reg_rules = { + /* channels 1..11 */ + REG_RULE_LIGHT(2412-10, 2462+10, 40, 0), + /* channels 36..48 */ + REG_RULE_LIGHT(5180-10, 5240+10, 40, 0), + /* channels 56..64 */ + REG_RULE_LIGHT(5260-10, 5320+10, 40, KAL_RRF_DFS), + /* channels 100..118 */ + REG_RULE_LIGHT(5500-10, 5590+10, 40, KAL_RRF_DFS), + /* channels 132..140 */ + REG_RULE_LIGHT(5660-10, 5700+10, 40, KAL_RRF_DFS), + /* channels 149..165 */ + REG_RULE_LIGHT(5745-10, 5825+10, 40, 0) } +}; + +const struct ieee80211_regdomain regdom_us = { + .n_reg_rules = 5, + .dfs_region = NL80211_DFS_FCC, + .reg_rules = { + /* channels 1..11 */ + REG_RULE_LIGHT(2412-10, 2462+10, 40, 0), + /* channels 36..48 */ + REG_RULE_LIGHT(5180-10, 5240+10, 80, KAL_RRF_AUTO_BW), + /* channels 52..64 */ + REG_RULE_LIGHT(5260-10, 5320+10, 80, KAL_RRF_DFS | KAL_RRF_AUTO_BW), + /* channels 100..140 */ + REG_RULE_LIGHT(5500-10, 5720+10, 160, KAL_RRF_DFS), + /* channels 149..165 */ + REG_RULE_LIGHT(5745-10, 5825+10, 80, 0) } +}; + +const struct ieee80211_regdomain regdom_cn = { + .n_reg_rules = 4, + .dfs_region = NL80211_DFS_FCC, + .reg_rules = { + /* channels 1..13 */ + REG_RULE_LIGHT(2412-10, 2472+10, 40, 0), + /* channels 36..48 */ + REG_RULE_LIGHT(5180-10, 5240+10, 80, KAL_RRF_AUTO_BW), + /* channels 52..64 */ + REG_RULE_LIGHT(5260-10, 5320+10, 80, KAL_RRF_DFS | KAL_RRF_AUTO_BW), + /* channels 149..165 */ + REG_RULE_LIGHT(5745-10, 5825+10, 80, 0) } +}; + +const struct ieee80211_regdomain regdom_cz_nl = { + .n_reg_rules = 5, + .reg_rules = { + /* channels 1..11 */ + REG_RULE_LIGHT(2412-10, 2462+10, 40, 0), + /* channels 12,13 */ + REG_RULE_LIGHT(2467-10, 2472+10, 40, 0), + /* channels 36..48 */ + REG_RULE_LIGHT(5180-10, 5240+10, 80, 0), + /* channels 52..64 */ + REG_RULE_LIGHT(5260-10, 5320+10, 80, KAL_RRF_DFS), + /* channels 100..140 */ + REG_RULE_LIGHT(5500-10, 5700+10, 160, KAL_RRF_DFS) } +}; + +const struct ieee80211_regdomain regdom_jp = { + .n_reg_rules = 7, + .dfs_region = NL80211_DFS_JP, + .reg_rules = { + /* channels 1..13 */ + REG_RULE_LIGHT(2412-10, 2472+10, 40, 0), + /* channels 14 */ + REG_RULE_LIGHT(2484-10, 2484+10, 20, KAL_RRF_NO_OFDM), + /* channels 184..196 */ + REG_RULE_LIGHT(4920-10, 4980+10, 40, 0), + /* channels 8..16 */ + REG_RULE_LIGHT(5040-10, 5080+10, 40, 0), + /* channels 36..48 */ + REG_RULE_LIGHT(5180-10, 5240+10, 80, KAL_RRF_AUTO_BW), + /* channels 52..64 */ + REG_RULE_LIGHT(5260-10, 5320+10, 80, KAL_RRF_DFS | KAL_RRF_AUTO_BW), + /* channels 100..140 */ + REG_RULE_LIGHT(5500-10, 5700+10, 160, KAL_RRF_DFS) } +}; + +const struct ieee80211_regdomain regdom_tr = { + .n_reg_rules = 4, + .dfs_region = NL80211_DFS_ETSI, + .reg_rules = { + /* channels 1..13 */ + REG_RULE_LIGHT(2412-10, 2472+10, 40, 0), + /* channels 36..48 */ + REG_RULE_LIGHT(5180-10, 5240+10, 80, KAL_RRF_AUTO_BW), + /* channels 52..64 */ + REG_RULE_LIGHT(5260-10, 5320+10, 80, KAL_RRF_DFS | KAL_RRF_AUTO_BW), + /* channels 100..140 */ + REG_RULE_LIGHT(5500-10, 5700+10, 160, KAL_RRF_DFS) } +}; + +/* + * Step2. Decclare struct mtk_regdomain + */ + +const struct mtk_regdomain my_regdom_us01 = { + .country_code = "US01", + .prRegdRules = ®dom_us01 +}; + +const struct mtk_regdomain my_regdom_us = { + .country_code = "US", + .prRegdRules = ®dom_us +}; + +const struct mtk_regdomain my_regdom_cn = { + .country_code = "CN", + .prRegdRules = ®dom_cn +}; + +const struct mtk_regdomain my_regdom_nl = { + .country_code = "NL", + .prRegdRules = ®dom_cz_nl +}; + +const struct mtk_regdomain my_regdom_cz = { + .country_code = "CZ", + .prRegdRules = ®dom_cz_nl +}; + +const struct mtk_regdomain my_regdom_jp = { + .country_code = "JP", + .prRegdRules = ®dom_jp +}; + +const struct mtk_regdomain my_regdom_tr = { + .country_code = "TR", + .prRegdRules = ®dom_tr +}; + +/* + * Step3. Register to table + */ + +const struct mtk_regdomain *g_prRegRuleTable[] = { + &my_regdom_us01, + &my_regdom_us, + &my_regdom_cn, + &my_regdom_nl, + &my_regdom_cz, + &my_regdom_jp, + &my_regdom_tr, + NULL /* this NULL SHOULD be at the end of the array */ +}; + +#endif +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/rlm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/rlm.c new file mode 100644 index 0000000000000..d612809913760 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/rlm.c @@ -0,0 +1,4601 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rlm.c#3 +*/ + +/*! \file "rlm.c" +* \brief +* +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +BOOLEAN g_bCaptureDone = FALSE; +BOOLEAN g_bIcapEnable = FALSE; +UINT_16 g_u2DumpIndex; +BOOLEAN g_fgHasStopTx = FALSE; + +#if CFG_SUPPORT_QA_TOOL +UINT_32 g_au4Offset[2][2]; +UINT_32 g_au4IQData[256]; +#endif + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +RLM_CAL_RESULT_ALL_V2_T g_rBackupCalDataAllV2; +#endif + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static 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); + +#if CFG_SUPPORT_802_11AC +static VOID rlmFillVhtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo); +static VOID rlmFillVhtOpNotificationIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, + P_MSDU_INFO_T prMsduInfo, BOOLEAN fgIsMaxCap); + +#endif +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmFsmEventInit(P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + /* Note: assume TIMER_T structures are reset to zero or stopped + * before invoking this function. + */ + + /* Initialize OBSS FSM */ + rlmObssInit(prAdapter); + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + rlmDomainCheckCountryPowerLimitTable(prAdapter); +#endif + + g_bCaptureDone = FALSE; + g_bIcapEnable = FALSE; + g_u2DumpIndex = 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmFsmEventUninit(P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prBssInfo; + UINT_8 i; + + ASSERT(prAdapter); + + for (i = 0; i < BSS_INFO_NUM; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + + /* Note: all RLM timers will also be stopped. + * Now only one OBSS scan timer. + */ + rlmBssReset(prAdapter, prBssInfo); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief For association request, power capability +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmReqGeneratePowerCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + PUINT_8 pucBuffer; + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + + /* We should add power capability IE in assoc/reassoc req if the spectrum + * management bit is set to 1 in Capability Infor field, or the connection + * will be rejected by Marvell APs in some TGn items. (e.g. 5.2.32). + * Spectrum management related feature (802.11h) is for 5G band. + */ + if (!prBssInfo || prBssInfo->eBand != BAND_5G) + return; + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (ULONG) prMsduInfo->u2FrameLength); + + POWER_CAP_IE(pucBuffer)->ucId = ELEM_ID_PWR_CAP; + POWER_CAP_IE(pucBuffer)->ucLength = ELEM_MAX_LEN_POWER_CAP; + POWER_CAP_IE(pucBuffer)->cMinTxPowerCap = 15; + POWER_CAP_IE(pucBuffer)->cMaxTxPowerCap = 20; + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief For association request, supported channels +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmReqGenerateSupportedChIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + PUINT_8 pucBuffer; + P_BSS_INFO_T prBssInfo; + RF_CHANNEL_INFO_T auc2gChannelList[MAX_2G_BAND_CHN_NUM]; + RF_CHANNEL_INFO_T auc5gChannelList[MAX_5G_BAND_CHN_NUM]; + UINT_8 ucNumOf2gChannel = 0; + UINT_8 ucNumOf5gChannel = 0; + UINT_8 ucChIdx = 0; + UINT_8 ucIdx = 0; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + + /* We should add supported channels IE in assoc/reassoc req if the spectrum + * management bit is set to 1 in Capability Infor field, or the connection + * will be rejected by Marvell APs in some TGn items. (e.g. 5.2.3). + * Spectrum management related feature (802.11h) is for 5G band. + */ + if (!prBssInfo || prBssInfo->eBand != BAND_5G) + return; + + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (ULONG) prMsduInfo->u2FrameLength); + + rlmDomainGetChnlList(prAdapter, BAND_2G4, TRUE, + MAX_2G_BAND_CHN_NUM, &ucNumOf2gChannel, auc2gChannelList); + rlmDomainGetChnlList(prAdapter, BAND_5G, TRUE, + MAX_5G_BAND_CHN_NUM, &ucNumOf5gChannel, auc5gChannelList); + + SUP_CH_IE(pucBuffer)->ucId = ELEM_ID_SUP_CHS; + SUP_CH_IE(pucBuffer)->ucLength = (ucNumOf2gChannel + ucNumOf5gChannel) * 2; + + for (ucIdx = 0; ucIdx < ucNumOf2gChannel; ucIdx++, ucChIdx += 2) { + SUP_CH_IE(pucBuffer)->ucChannelNum[ucChIdx] = + auc2gChannelList[ucIdx].ucChannelNum; + SUP_CH_IE(pucBuffer)->ucChannelNum[ucChIdx + 1] = 1; + } + + for (ucIdx = 0; ucIdx < ucNumOf5gChannel; ucIdx++, ucChIdx += 2) { + SUP_CH_IE(pucBuffer)->ucChannelNum[ucChIdx] = + auc5gChannelList[ucIdx].ucChannelNum; + SUP_CH_IE(pucBuffer)->ucChannelNum[ucChIdx + 1] = 1; + } + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + 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->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) && + (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N))) + rlmFillExtCapIE(prAdapter, prBssInfo, prMsduInfo); +#if CFG_SUPPORT_PASSPOINT + else if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) + hs20FillExtCapIE(prAdapter, prBssInfo, prMsduInfo); +#endif /* CFG_SUPPORT_PASSPOINT */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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; + UINT_8 ucPhyTypeSet; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + if (!IS_BSS_ACTIVE(prBssInfo)) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + /* Decide PHY type set source */ + if (prStaRec) { + /* Get PHY type set from target STA */ + ucPhyTypeSet = prStaRec->ucPhyTypeSet; + } else { + /* Get PHY type set from current BSS */ + ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + } + + if (RLM_NET_IS_11N(prBssInfo) && (ucPhyTypeSet & PHY_TYPE_SET_802_11N) && + (!prBssInfo->fgIsWepCipherGroup)) + 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; + UINT_8 ucPhyTypeSet; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + if (!IS_BSS_ACTIVE(prBssInfo)) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + /* Decide PHY type set source */ + if (prStaRec) { + /* Get PHY type set from target STA */ + ucPhyTypeSet = prStaRec->ucPhyTypeSet; + } else { + /* Get PHY type set from current BSS */ + ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + } + + if (RLM_NET_IS_11N(prBssInfo) && (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; + UINT_8 ucPhyTypeSet; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + if (!IS_BSS_ACTIVE(prBssInfo)) + return; + + /* Decide PHY type set source */ + if (prStaRec) { + /* Get PHY type set from target STA */ + ucPhyTypeSet = prStaRec->ucPhyTypeSet; + } else { + /* Get PHY type set from current BSS */ + ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + } + + if (RLM_NET_IS_11N(prBssInfo) && (ucPhyTypeSet & PHY_TYPE_SET_802_11N) && + (!prBssInfo->fgIsWepCipherGroup)) + 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; + UINT_8 ucPhyTypeSet; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + if (!IS_BSS_ACTIVE(prBssInfo)) + return; + + /* Decide PHY type set source */ + if (prStaRec) { + /* Get PHY type set from target STA */ + ucPhyTypeSet = prStaRec->ucPhyTypeSet; + } else { + /* Get PHY type set from current BSS */ + ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + } + + if (RLM_NET_IS_11GN(prBssInfo) && prBssInfo->eBand == BAND_2G4 && (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); + } +} + +#if CFG_SUPPORT_MTK_SYNERGY +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to generate MTK Vendor Specific OUI +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmGenerateMTKOuiIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + P_BSS_INFO_T prBssInfo; + PUINT_8 pucBuffer; + UINT_8 aucMtkOui[] = VENDOR_OUI_MTK; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + if (prAdapter->rWifiVar.ucMtkOui == FEATURE_DISABLED) + return; + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (ULONG) prMsduInfo->u2FrameLength); + + MTK_OUI_IE(pucBuffer)->ucId = ELEM_ID_VENDOR; + MTK_OUI_IE(pucBuffer)->ucLength = ELEM_MIN_LEN_MTK_OUI; + MTK_OUI_IE(pucBuffer)->aucOui[0] = aucMtkOui[0]; + MTK_OUI_IE(pucBuffer)->aucOui[1] = aucMtkOui[1]; + MTK_OUI_IE(pucBuffer)->aucOui[2] = aucMtkOui[2]; + MTK_OUI_IE(pucBuffer)->aucCapability[0] = MTK_SYNERGY_CAP0 & (prAdapter->rWifiVar.aucMtkFeature[0]); + MTK_OUI_IE(pucBuffer)->aucCapability[1] = MTK_SYNERGY_CAP1 & (prAdapter->rWifiVar.aucMtkFeature[1]); + MTK_OUI_IE(pucBuffer)->aucCapability[2] = MTK_SYNERGY_CAP2 & (prAdapter->rWifiVar.aucMtkFeature[2]); + MTK_OUI_IE(pucBuffer)->aucCapability[3] = MTK_SYNERGY_CAP3 & (prAdapter->rWifiVar.aucMtkFeature[3]); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); +} /* rlmGenerateMTKOuiIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to check MTK Vendor Specific OUI +* +* +* @return true: correct MTK OUI +* false: incorrect MTK OUI +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rlmParseCheckMTKOuiIE(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuf, IN PUINT_32 pu4Cap) +{ + UINT_8 aucMtkOui[] = VENDOR_OUI_MTK; + P_IE_MTK_OUI_T prMtkOuiIE = (P_IE_MTK_OUI_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL)); + + prMtkOuiIE = (P_IE_MTK_OUI_T) pucBuf; + + if (prAdapter->rWifiVar.ucMtkOui == FEATURE_DISABLED) + break; + else if (IE_LEN(pucBuf) < ELEM_MIN_LEN_MTK_OUI) + break; + else if (prMtkOuiIE->aucOui[0] != aucMtkOui[0] || + prMtkOuiIE->aucOui[1] != aucMtkOui[1] || prMtkOuiIE->aucOui[2] != aucMtkOui[2]) + break; + /* apply NvRam setting */ + prMtkOuiIE->aucCapability[0] = prMtkOuiIE->aucCapability[0] & (prAdapter->rWifiVar.aucMtkFeature[0]); + prMtkOuiIE->aucCapability[1] = prMtkOuiIE->aucCapability[1] & (prAdapter->rWifiVar.aucMtkFeature[1]); + prMtkOuiIE->aucCapability[2] = prMtkOuiIE->aucCapability[2] & (prAdapter->rWifiVar.aucMtkFeature[2]); + prMtkOuiIE->aucCapability[3] = prMtkOuiIE->aucCapability[3] & (prAdapter->rWifiVar.aucMtkFeature[3]); + + kalMemCopy(pu4Cap, prMtkOuiIE->aucCapability, sizeof(UINT_32)); + + return TRUE; + } while (FALSE); + + return FALSE; +} /* rlmParseCheckMTKOuiIE */ + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmGenerateCsaIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + PUINT_8 pucBuffer; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + if (prAdapter->rWifiVar.fgCsaInProgress) { + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (ULONG) prMsduInfo->u2FrameLength); + + CSA_IE(pucBuffer)->ucId = ELEM_ID_CH_SW_ANNOUNCEMENT; + CSA_IE(pucBuffer)->ucLength = ELEM_MIN_LEN_CSA; + CSA_IE(pucBuffer)->ucChannelSwitchMode = prAdapter->rWifiVar.ucChannelSwitchMode; + CSA_IE(pucBuffer)->ucNewChannelNum = prAdapter->rWifiVar.ucNewChannelNumber; + CSA_IE(pucBuffer)->ucChannelSwitchCount = prAdapter->rWifiVar.ucChannelSwitchCount; + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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; + UINT_8 ucIdx; + + 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 (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxShortGI)) + prHtCap->u2HtCapInfo |= (HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxLdpc)) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_LDPC_CAP; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucTxStbc)) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_TX_STBC; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxStbc)) { + + UINT_8 tempRxStbcNss; + + tempRxStbcNss = prAdapter->rWifiVar.ucRxStbcNss; + tempRxStbcNss = (tempRxStbcNss > wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex)) ? + wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex) : (tempRxStbcNss); + if (tempRxStbcNss != prAdapter->rWifiVar.ucRxStbcNss) { + DBGLOG(RLM, WARN, "Apply Nss:%d as RxStbcNss in HT Cap", + wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex)); + DBGLOG(RLM, WARN, " due to set RxStbcNss more than Nss is not appropriate.\n"); + } + if (tempRxStbcNss == 1) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_RX_STBC_1_SS; + else if (tempRxStbcNss == 2) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_RX_STBC_2_SS; + else if (tempRxStbcNss >= 3) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_RX_STBC_3_SS; + } + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxGf)) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + + if (prAdapter->rWifiVar.ucRxMaxMpduLen > VHT_CAP_INFO_MAX_MPDU_LEN_3K) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_MAX_AMSDU_LEN; + + if (!fg40mAllowed) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | + HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_DSSS_CCK_IN_40M); + + /* SM power saving */ /* TH3_Huang */ + if (prBssInfo->ucNss < wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex)) + prHtCap->u2HtCapInfo &= ~HT_CAP_INFO_SM_POWER_SAVE;/*Set as static power save */ + + prHtCap->ucAmpduParam = AMPDU_PARAM_DEFAULT_VAL; + + prSupMcsSet = &prHtCap->rSupMcsSet; + kalMemZero((PVOID)&prSupMcsSet->aucRxMcsBitmask[0], SUP_MCS_RX_BITMASK_OCTET_NUM); + + for (ucIdx = 0; ucIdx < wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex); ucIdx++) + prSupMcsSet->aucRxMcsBitmask[ucIdx] = BITS(0, 7); + + /* prSupMcsSet->aucRxMcsBitmask[0] = BITS(0, 7); */ + + if (fg40mAllowed && IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucMCS32)) + 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; + if ((prAdapter->rWifiVar.ucDbdcMode == DBDC_MODE_DISABLED) || + (prBssInfo->eBand == BAND_5G)) { + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaHtBfee)) + prHtCap->u4TxBeamformingCap = TX_BEAMFORMING_CAP_BFEE; + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaHtBfer)) + prHtCap->u4TxBeamformingCap |= TX_BEAMFORMING_CAP_BFER; + } + + 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, fgAppendVhtCap; + P_STA_RECORD_T prStaRec; + + 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; +#if 0 /* CFG_SUPPORT_HOTSPOT_2_0 */ + if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) + prExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + else +#endif + prExtCap->ucLength = 1; + + /* Reset memory */ + kalMemZero(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP); + + 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; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + +#if CFG_SUPPORT_802_11AC + fgAppendVhtCap = FALSE; + + /* Check append rule */ + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AC) { + /* Note: For AIS connecting state, structure in BSS_INFO will not be inited */ + /* So, we check StaRec instead of BssInfo */ + if (prStaRec) { + if (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11AC) + fgAppendVhtCap = TRUE; + } else if ((RLM_NET_IS_11AC(prBssInfo)) && ((prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) || + (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT))) + fgAppendVhtCap = TRUE; + } + + if (fgAppendVhtCap) { + if (prExtCap->ucLength < ELEM_MAX_LEN_EXT_CAP) + prExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_OP_MODE_NOTIFICATION_BIT); + + } +#endif + +#if CFG_SUPPORT_PASSPOINT + if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) { + + if (prExtCap->ucLength < ELEM_MAX_LEN_EXT_CAP) + prExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_INTERWORKING_BIT); + + /* For R2 WNM-Notification */ + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_WNM_NOTIFICATION_BIT); + } +#endif /* CFG_SUPPORT_PASSPOINT */ + + 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); +} + +#if CFG_SUPPORT_802_11AC + +/*----------------------------------------------------------------------------*/ +/*! +* \brief For probe request, association request +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmReqGenerateVhtCapIE(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->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AC) && + (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11AC))) + rlmFillVhtCapIE(prAdapter, prBssInfo, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief For probe response (GO, IBSS) and association response +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmRspGenerateVhtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + UINT_8 ucPhyTypeSet; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + if (!IS_BSS_ACTIVE(prBssInfo)) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + /* Decide PHY type set source */ + if (prStaRec) { + /* Get PHY type set from target STA */ + ucPhyTypeSet = prStaRec->ucPhyTypeSet; + } else { + /* Get PHY type set from current BSS */ + ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + } + + if (RLM_NET_IS_11AC(prBssInfo) && (ucPhyTypeSet & PHY_TYPE_SET_802_11AC)) + rlmFillVhtCapIE(prAdapter, prBssInfo, prMsduInfo); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmRspGenerateVhtOpIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + UINT_8 ucPhyTypeSet; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + if (!IS_BSS_ACTIVE(prBssInfo)) + return; + + /* Decide PHY type set source */ + if (prStaRec) { + /* Get PHY type set from target STA */ + ucPhyTypeSet = prStaRec->ucPhyTypeSet; + } else { + /* Get PHY type set from current BSS */ + ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + } + + if (RLM_NET_IS_11AC(prBssInfo) && (ucPhyTypeSet & PHY_TYPE_SET_802_11AC)) + rlmFillVhtOpIE(prAdapter, prBssInfo, prMsduInfo); +} + + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief For probe request, association request +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmReqGenerateVhtOpNotificationIE(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->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + /* [TGac 5.2.46 STBC Receive Test with UCC 9.2.x] + * Operating Notification IE of Nss=2 will make Ralink testbed send data frames without STBC + * Enable the Operating Notification IE only for DBDC enable case. + */ + if (!prAdapter->rWifiVar.fgDbDcModeEn) + return; + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AC) && + (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11AC))) + rlmFillVhtOpNotificationIE(prAdapter, prBssInfo, prMsduInfo, TRUE); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmRspGenerateVhtOpNotificationIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + UINT_8 ucPhyTypeSet; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; + if (!prBssInfo) + return; + + if (!IS_BSS_ACTIVE(prBssInfo)) + return; + + /* Decide PHY type set source */ + if (prStaRec) { + /* Get PHY type set from target STA */ + ucPhyTypeSet = prStaRec->ucPhyTypeSet; + } else { + /* Get PHY type set from current BSS */ + ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + } + + if (RLM_NET_IS_11AC(prBssInfo) && (ucPhyTypeSet & PHY_TYPE_SET_802_11AC)) + rlmFillVhtOpNotificationIE(prAdapter, prBssInfo, prMsduInfo, FALSE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* add VHT operation notification IE for VHT-BW40 case specific +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static VOID rlmFillVhtOpNotificationIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, + P_MSDU_INFO_T prMsduInfo, BOOLEAN fgIsMaxCap) +{ + P_IE_VHT_OP_MODE_NOTIFICATION_T prVhtOpMode; + UINT_8 ucMaxBw; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(prMsduInfo); + + prVhtOpMode = (P_IE_VHT_OP_MODE_NOTIFICATION_T) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + + kalMemZero((PVOID) prVhtOpMode, sizeof(IE_VHT_OP_MODE_NOTIFICATION_T)); + + prVhtOpMode->ucId = ELEM_ID_OP_MODE; + prVhtOpMode->ucLength = sizeof(IE_VHT_OP_MODE_NOTIFICATION_T) - ELEM_HDR_LEN; + + DBGLOG(RLM, INFO, "rlmFillVhtOpNotificationIE(%d) %u %u\n", + prBssInfo->ucBssIndex, fgIsMaxCap, prBssInfo->ucNss); + + if (fgIsMaxCap) { + + ucMaxBw = cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex); + + /*handle 80P80 case*/ + if (ucMaxBw >= MAX_BW_160MHZ) + ucMaxBw = MAX_BW_160MHZ; + + prVhtOpMode->ucOperatingMode |= ucMaxBw; + + prVhtOpMode->ucOperatingMode |= + (((prBssInfo->ucNss-1) << VHT_OP_MODE_RX_NSS_OFFSET) & VHT_OP_MODE_RX_NSS); + + } else { + + switch (prBssInfo->ucVhtChannelWidth) { + case VHT_OP_CHANNEL_WIDTH_80P80: + ucMaxBw = MAX_BW_160MHZ; + break; + + case VHT_OP_CHANNEL_WIDTH_160: + ucMaxBw = MAX_BW_160MHZ; + break; + + case VHT_OP_CHANNEL_WIDTH_80: + ucMaxBw = MAX_BW_80MHZ; + break; + + case VHT_OP_CHANNEL_WIDTH_20_40: + { + ucMaxBw = MAX_BW_20MHZ; + + if (prBssInfo->eBssSCO != CHNL_EXT_SCN) + ucMaxBw = MAX_BW_40MHZ; + } + break; + + default: + /*VHT default IE should support BW 80*/ + ucMaxBw = MAX_BW_80MHZ; + break; + } + + prVhtOpMode->ucOperatingMode |= ucMaxBw; + + prVhtOpMode->ucOperatingMode |= (((prBssInfo->ucNss-1) + << VHT_OP_MODE_RX_NSS_OFFSET) & VHT_OP_MODE_RX_NSS); + } + + + prMsduInfo->u2FrameLength += IE_SIZE(prVhtOpMode); + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static VOID rlmFillVhtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo) +{ + P_IE_VHT_CAP_T prVhtCap; + P_VHT_SUPPORTED_MCS_FIELD prVhtSupportedMcsSet; + UINT_8 i; + UINT_8 ucMaxBw; + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(prMsduInfo); + + prVhtCap = (P_IE_VHT_CAP_T) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + + prVhtCap->ucId = ELEM_ID_VHT_CAP; + prVhtCap->ucLength = sizeof(IE_VHT_CAP_T) - ELEM_HDR_LEN; + prVhtCap->u4VhtCapInfo = VHT_CAP_INFO_DEFAULT_VAL; + + ucMaxBw = cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex); + + prVhtCap->u4VhtCapInfo |= (prAdapter->rWifiVar.ucRxMaxMpduLen & VHT_CAP_INFO_MAX_MPDU_LEN_MASK); + + if (ucMaxBw == MAX_BW_160MHZ) + prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_SET_160; + else if (ucMaxBw == MAX_BW_80_80_MHZ) + prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_SET_160_80P80; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaVhtBfee)) { + prVhtCap->u4VhtCapInfo |= FIELD_VHT_CAP_INFO_BFEE; +#if CFG_SUPPORT_BFEE + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (prStaRec && (prStaRec->ucVhtCapNumSoundingDimensions == 0x2)) { + /* For the compatibility with netgear R7000 AP */ + prVhtCap->u4VhtCapInfo |= (((UINT_32)prStaRec->ucVhtCapNumSoundingDimensions) << + VHT_CAP_INFO_COMP_STEERING_NUM_OF_BFER_ANT_SUP_OFFSET); + DBGLOG(RLM, INFO, "Set VHT Cap BFEE STS CAP=%d\n", + prStaRec->ucVhtCapNumSoundingDimensions); + } else { + /* For 11ac cert. VHT-5.2.63C MU-BFee step3, + * it requires STAUT to set its maximum STS capability here + */ + prVhtCap->u4VhtCapInfo |= + VHT_CAP_INFO_COMPRESSED_STEERING_NUMBER_OF_BEAMFORMER_ANTENNAS_4_SUPPOERTED; + DBGLOG(RLM, INFO, "Set VHT Cap BFEE STS CAP=%d\n", VHT_CAP_INFO_BEAMFORMEE_STS_CAP_MAX); + } +#endif + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaVhtMuBfee)) + prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_MU_BEAMFOMEE_CAPABLE; + } + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaVhtBfer)) + prVhtCap->u4VhtCapInfo |= FIELD_VHT_CAP_INFO_BFER; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxShortGI)) { + if (ucMaxBw >= MAX_BW_80MHZ) + prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_SHORT_GI_80; + + if (ucMaxBw >= MAX_BW_160MHZ) + prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_SHORT_GI_160_80P80; + } + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxLdpc)) + prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_RX_LDPC; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxStbc)) { + UINT_8 tempRxStbcNss; + + if (prAdapter->rWifiVar.u4SwTestMode == ENUM_SW_TEST_MODE_SIGMA_AC) { + tempRxStbcNss = 1; + DBGLOG(RLM, INFO, "Set RxStbcNss to 1 for 11ac certification.\n"); + } else { + tempRxStbcNss = prAdapter->rWifiVar.ucRxStbcNss; + tempRxStbcNss = (tempRxStbcNss > wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex)) ? + wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex) : (tempRxStbcNss); + if (tempRxStbcNss != prAdapter->rWifiVar.ucRxStbcNss) { + DBGLOG(RLM, WARN, "Apply Nss:%d as RxStbcNss in VHT Cap", + wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex)); + DBGLOG(RLM, WARN, "due to set RxStbcNss more than Nss is not appropriate.\n"); + } + } + prVhtCap->u4VhtCapInfo |= ((tempRxStbcNss << VHT_CAP_INFO_RX_STBC_OFFSET) & VHT_CAP_INFO_RX_STBC_MASK); + } + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucTxStbc)) + prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_TX_STBC; + + /*set MCS map */ + prVhtSupportedMcsSet = &prVhtCap->rVhtSupportedMcsSet; + kalMemZero((PVOID) prVhtSupportedMcsSet, sizeof(VHT_SUPPORTED_MCS_FIELD)); + + for (i = 0; i < 8; i++) { + UINT_8 ucOffset = i * 2; + UINT_8 ucMcsMap; + + if (i < wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex)) + ucMcsMap = VHT_CAP_INFO_MCS_MAP_MCS9; + else + ucMcsMap = VHT_CAP_INFO_MCS_NOT_SUPPORTED; + + prVhtSupportedMcsSet->u2RxMcsMap |= (ucMcsMap << ucOffset); + prVhtSupportedMcsSet->u2TxMcsMap |= (ucMcsMap << ucOffset); + } + +#if 0 + for (i = 0; i < wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex); i++) { + UINT_8 ucOffset = i * 2; + + prVhtSupportedMcsSet->u2RxMcsMap &= + ((VHT_CAP_INFO_MCS_MAP_MCS9 << ucOffset) & BITS(ucOffset, ucOffset + 1)); + prVhtSupportedMcsSet->u2TxMcsMap &= + ((VHT_CAP_INFO_MCS_MAP_MCS9 << ucOffset) & BITS(ucOffset, ucOffset + 1)); + } +#endif + + prVhtSupportedMcsSet->u2RxHighestSupportedDataRate = VHT_CAP_INFO_DEFAULT_HIGHEST_DATA_RATE; + prVhtSupportedMcsSet->u2TxHighestSupportedDataRate = VHT_CAP_INFO_DEFAULT_HIGHEST_DATA_RATE; + + ASSERT(IE_SIZE(prVhtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP)); + + prMsduInfo->u2FrameLength += IE_SIZE(prVhtCap); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmFillVhtOpIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo) +{ + P_IE_VHT_OP_T prVhtOp; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(prMsduInfo); + + prVhtOp = (P_IE_VHT_OP_T) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + + /* Add HT operation IE */ + prVhtOp->ucId = ELEM_ID_VHT_OP; + prVhtOp->ucLength = sizeof(IE_VHT_OP_T) - ELEM_HDR_LEN; + + ASSERT(IE_SIZE(prVhtOp) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP)); + + prVhtOp->ucVhtOperation[0] = prBssInfo->ucVhtChannelWidth; /* (UINT8)VHT_OP_CHANNEL_WIDTH_80; */ + prVhtOp->ucVhtOperation[1] = prBssInfo->ucVhtChannelFrequencyS1; + prVhtOp->ucVhtOperation[2] = prBssInfo->ucVhtChannelFrequencyS2; + +#if 0 + if (cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex) < MAX_BW_80MHZ) { + prVhtOp->ucVhtOperation[0] = VHT_OP_CHANNEL_WIDTH_20_40; + prVhtOp->ucVhtOperation[1] = 0; + prVhtOp->ucVhtOperation[2] = 0; + } else if (cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex) == MAX_BW_80MHZ) { + prVhtOp->ucVhtOperation[0] = VHT_OP_CHANNEL_WIDTH_80; + prVhtOp->ucVhtOperation[1] = nicGetVhtS1(prBssInfo->ucPrimaryChannel); + prVhtOp->ucVhtOperation[2] = 0; + } else { + /* TODO: BW80 + 80/160 support */ + } +#endif + + prVhtOp->u2VhtBasicMcsSet = prBssInfo->u2VhtBasicMcsSet; + + prMsduInfo->u2FrameLength += IE_SIZE(prVhtOp); +} + +#endif + +#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST +WLAN_STATUS rlmCalBackup( + P_ADAPTER_T prAdapter, + UINT_8 ucReason, + UINT_8 ucAction, + UINT_8 ucRomRam + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_CAL_BACKUP_STRUCT_V2_T rCalBackupDataV2; + UINT_32 u4BufLen = 0; + + ASSERT(prAdapter); + ASSERT(prAdapter->prGlueInfo); + + prGlueInfo = prAdapter->prGlueInfo; + + rCalBackupDataV2.ucReason = ucReason; + rCalBackupDataV2.ucAction = ucAction; + rCalBackupDataV2.ucNeedResp = 1; + rCalBackupDataV2.ucFragNum = 0; + rCalBackupDataV2.ucRomRam = ucRomRam; + rCalBackupDataV2.u4ThermalValue = 0; + rCalBackupDataV2.u4Address = 0; + rCalBackupDataV2.u4Length = 0; + rCalBackupDataV2.u4RemainLength = 0; + + if (ucReason == 0 && ucAction == 0) { + DBGLOG(RFTEST, INFO, "RLM CMD : Get Thermal Temp from FW.\n"); + /* Step 1 : Get Thermal Temp from FW */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryCalBackupV2, + &rCalBackupDataV2, + sizeof(PARAM_CAL_BACKUP_STRUCT_V2_T), + TRUE, + TRUE, + TRUE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Get Thermal Temp from FW Return Fail (0x%08x)!!!!!!!!!!!\n", rStatus); + return rStatus; + } + + DBGLOG(RFTEST, INFO, "CMD : Get Thermal Temp (%d) from FW. Finish!!!!!!!!!!!\n", + rCalBackupDataV2.u4ThermalValue); + } else if (ucReason == 1 && ucAction == 2) { + DBGLOG(RFTEST, INFO, "RLM CMD : Trigger FW Do All Cal.\n"); + /* Step 2 : Trigger All Cal Function */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetCalBackup, + &rCalBackupDataV2, + sizeof(PARAM_CAL_BACKUP_STRUCT_V2_T), + FALSE, + FALSE, + TRUE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Trigger FW Do All Cal Return Fail (0x%08x)!!!!!!!!!!!\n", rStatus); + return rStatus; + } + + DBGLOG(RFTEST, INFO, "CMD : Trigger FW Do All Cal. Finish!!!!!!!!!!!\n"); + } else if (ucReason == 0 && ucAction == 1) { + DBGLOG(RFTEST, INFO, "RLM CMD : Get Cal Data (%s) Size from FW.\n", + ucRomRam == 0 ? "ROM" : "RAM"); + /* Step 3 : Get Cal Data Size from FW */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryCalBackupV2, + &rCalBackupDataV2, + sizeof(PARAM_CAL_BACKUP_STRUCT_V2_T), + TRUE, + TRUE, + TRUE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Get Cal Data (%s) Size from FW Return Fail (0x%08x)!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM", rStatus); + return rStatus; + } + + DBGLOG(RFTEST, INFO, "CMD : Get Cal Data (%s) Size from FW. Finish!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM"); + } else if (ucReason == 2 && ucAction == 4) { + DBGLOG(RFTEST, INFO, "RLM CMD : Get Cal Data from FW (%s). Start!!!!!!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM"); + DBGLOG(RFTEST, INFO, "Thermal Temp = %d\n", g_rBackupCalDataAllV2.u4ThermalInfo); + /* Step 4 : Get Cal Data from FW */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryCalBackupV2, + &rCalBackupDataV2, + sizeof(PARAM_CAL_BACKUP_STRUCT_V2_T), + TRUE, + TRUE, + TRUE, + &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Get Cal Data (%s) Size from FW Return Fail (0x%08x)!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM", rStatus); + return rStatus; + } + + DBGLOG(RFTEST, INFO, "CMD : Get Cal Data from FW (%s). Finish!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM"); + + if (ucRomRam == 0) { + DBGLOG(RFTEST, INFO, + "Check some of elements (0x%08x), (0x%08x), (0x%08x), (0x%08x), (0x%08x)\n", + g_rBackupCalDataAllV2.au4RomCalData[670], g_rBackupCalDataAllV2.au4RomCalData[671], + g_rBackupCalDataAllV2.au4RomCalData[672], g_rBackupCalDataAllV2.au4RomCalData[673], + g_rBackupCalDataAllV2.au4RomCalData[674]); + DBGLOG(RFTEST, INFO, + "Check some of elements (0x%08x), (0x%08x), (0x%08x), (0x%08x), (0x%08x)\n", + g_rBackupCalDataAllV2.au4RomCalData[675], g_rBackupCalDataAllV2.au4RomCalData[676], + g_rBackupCalDataAllV2.au4RomCalData[677], g_rBackupCalDataAllV2.au4RomCalData[678], + g_rBackupCalDataAllV2.au4RomCalData[679]); + } + } else if (ucReason == 4 && ucAction == 6) { + DBGLOG(RFTEST, INFO, "RLM CMD : Print Cal Data in FW (%s).\n", + ucRomRam == 0 ? "ROM" : "RAM"); + /* Debug Use : Print Cal Data in FW */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetCalBackup, + &rCalBackupDataV2, + sizeof(PARAM_CAL_BACKUP_STRUCT_V2_T), + TRUE, + TRUE, + TRUE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Print Cal Data in FW (%s) Return Fail (0x%08x)!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM", rStatus); + return rStatus; + } + + DBGLOG(RFTEST, INFO, "CMD : Print Cal Data in FW (%s). Finish!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM"); + } else if (ucReason == 3 && ucAction == 5) { + DBGLOG(RFTEST, INFO, "RLM CMD : Send Cal Data to FW (%s).\n", + ucRomRam == 0 ? "ROM" : "RAM"); + /* Send Cal Data to FW */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetCalBackup, + &rCalBackupDataV2, + sizeof(PARAM_CAL_BACKUP_STRUCT_V2_T), + TRUE, + TRUE, + TRUE, + &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(RFTEST, INFO, + "RLM CMD : Send Cal Data to FW (%s) Return Fail (0x%08x)!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM", rStatus); + return rStatus; + } + + DBGLOG(RFTEST, INFO, "CMD : Send Cal Data to FW (%s). Finish!!!!!!!!!!!\n", + ucRomRam == 0 ? "ROM" : "RAM"); + } else { + DBGLOG(RFTEST, INFO, "CMD : Undefined Reason (%d) and Action (%d) for Cal Backup in Host Side!\n", + ucReason, ucAction); + + return rStatus; + } + + return rStatus; +} + +WLAN_STATUS rlmTriggerCalBackup( + P_ADAPTER_T prAdapter, + BOOLEAN fgIsCalDataBackuped + ) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + if (!fgIsCalDataBackuped) { + DBGLOG(RFTEST, INFO, "======== Boot Time Wi-Fi Enable........\n"); + DBGLOG(RFTEST, INFO, "Step 0 : Reset All Cal Data in Driver.\n"); + memset(&g_rBackupCalDataAllV2, 1, sizeof(RLM_CAL_RESULT_ALL_V2_T)); + g_rBackupCalDataAllV2.u4MagicNum1 = 6632; + g_rBackupCalDataAllV2.u4MagicNum2 = 6632; + + DBGLOG(RFTEST, INFO, "Step 1 : Get Thermal Temp from FW.\n"); + if (rlmCalBackup(prAdapter, 0, 0, 0) == WLAN_STATUS_FAILURE) { + DBGLOG(RFTEST, INFO, "Step 1 : Return Failure.\n"); + return WLAN_STATUS_FAILURE; + } + + DBGLOG(RFTEST, INFO, "Step 2 : Get Rom Cal Data Size from FW.\n"); + if (rlmCalBackup(prAdapter, 0, 1, 0) == WLAN_STATUS_FAILURE) { + DBGLOG(RFTEST, INFO, "Step 2 : Return Failure.\n"); + return WLAN_STATUS_FAILURE; + } + + DBGLOG(RFTEST, INFO, "Step 3 : Get Ram Cal Data Size from FW.\n"); + if (rlmCalBackup(prAdapter, 0, 1, 1) == WLAN_STATUS_FAILURE) { + DBGLOG(RFTEST, INFO, "Step 3 : Return Failure.\n"); + return WLAN_STATUS_FAILURE; + } + + DBGLOG(RFTEST, INFO, "Step 4 : Trigger FW Do Full Cal.\n"); + if (rlmCalBackup(prAdapter, 1, 2, 0) == WLAN_STATUS_FAILURE) { + DBGLOG(RFTEST, INFO, "Step 4 : Return Failure.\n"); + return WLAN_STATUS_FAILURE; + } + } else { + DBGLOG(RFTEST, INFO, "======== Normal Wi-Fi Enable........\n"); + DBGLOG(RFTEST, INFO, "Step 0 : Sent Rom Cal data to FW.\n"); + if (rlmCalBackup(prAdapter, 3, 5, 0) == WLAN_STATUS_FAILURE) { + DBGLOG(RFTEST, INFO, "Step 0 : Return Failure.\n"); + return WLAN_STATUS_FAILURE; + } + + DBGLOG(RFTEST, INFO, "Step 1 : Sent Ram Cal data to FW.\n"); + if (rlmCalBackup(prAdapter, 3, 5, 1) == WLAN_STATUS_FAILURE) { + DBGLOG(RFTEST, INFO, "Step 1 : Return Failure.\n"); + return WLAN_STATUS_FAILURE; + } + } + + return rStatus; +} +#endif + +VOID rlmModifyVhtBwPara( + PUINT_8 pucVhtChannelFrequencyS1, + PUINT_8 pucVhtChannelFrequencyS2, + PUINT_8 pucVhtChannelWidth + ) +{ + UINT_8 i = 0, ucTempS = 0; + + if ((*pucVhtChannelFrequencyS1 != 0) && + (*pucVhtChannelFrequencyS2 != 0)) { + + UINT_8 ucBW160Inteval = 8; + + DBGLOG(RLM, WARN, "S1=%d, S2=%d\n", *pucVhtChannelFrequencyS1, *pucVhtChannelFrequencyS2); + + if (((*pucVhtChannelFrequencyS2 - *pucVhtChannelFrequencyS1) == ucBW160Inteval) || + ((*pucVhtChannelFrequencyS1 - *pucVhtChannelFrequencyS2) == ucBW160Inteval)) { + /*C160 case*/ + + /*NEW spec should set central ch of bw80 at S1, + *set central ch of bw160 at S2 + */ + for (i = 0; i < 2; i++) { + + if (i == 0) + ucTempS = *pucVhtChannelFrequencyS1; + else + ucTempS = *pucVhtChannelFrequencyS2; + + if ((ucTempS == 50) || (ucTempS == 82) || + (ucTempS == 114) || (ucTempS == 163)) + break; + } + + + if (ucTempS == 0) { + DBGLOG(RLM, WARN, "please check BW160 setting, find central freq fail\n"); + return; + } + + *pucVhtChannelFrequencyS1 = ucTempS; + *pucVhtChannelFrequencyS2 = 0; + *pucVhtChannelWidth = CW_160MHZ; + DBGLOG(RLM, WARN, "[BW160][new spec] S1 change to %d\n", *pucVhtChannelFrequencyS1); + } else { + /*real 80P80 case*/ + } + + } + +} + +static VOID rlmRevisePreferBandwidthNss( + P_ADAPTER_T prAdapter, + UINT_8 ucBssIndex, + P_STA_RECORD_T prStaRec + ) +{ + ENUM_CHANNEL_WIDTH_T eChannelWidth = CW_20_40MHZ; + P_BSS_INFO_T prBssInfo; + +#define VHT_MCS_TX_RX_MAX_2SS BITS(2, 3) +#define VHT_MCS_TX_RX_MAX_2SS_SHIFT 2 + +#define AR_STA_2AC_MCS(prStaRec) \ + (((prStaRec)->u2VhtRxMcsMap & VHT_MCS_TX_RX_MAX_2SS) >> VHT_MCS_TX_RX_MAX_2SS_SHIFT) + +#define AR_IS_STA_2SS_AC(prStaRec) \ + ((AR_STA_2AC_MCS(prStaRec) != BITS(0, 1))) + + + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + eChannelWidth = prBssInfo->ucVhtChannelWidth; + + /* + *Prefer setting modification + *80+80 1x1 and 80 2x2 have the same phy rate, choose the 80 2x2 + */ + + if (AR_IS_STA_2SS_AC(prStaRec)) { + /* + *DBGLOG(RLM, WARN, "support 2ss\n"); + */ + + if ((eChannelWidth == CW_80P80MHZ && prBssInfo->ucVhtChannelFrequencyS2 != 0)) { + DBGLOG(RLM, WARN, "support (2Nss) and (80+80)\n"); + DBGLOG(RLM, WARN, "choose (2Nss) and (80) for Bss_info\n"); + prBssInfo->ucVhtChannelWidth = CW_80MHZ; + prBssInfo->ucVhtChannelFrequencyS2 = 0; + } + } +} + +VOID rlmReviseMaxBw( + P_ADAPTER_T prAdapter, + UINT_8 ucBssIndex, + P_ENUM_CHNL_EXT_T peExtend, + P_ENUM_CHANNEL_WIDTH_P peChannelWidth, + PUINT_8 pucS1, + PUINT_8 pucPrimaryCh) +{ + UINT_8 ucMaxBandwidth = MAX_BW_80MHZ; + UINT_8 ucCurrentBandwidth = MAX_BW_20MHZ; + UINT_8 ucOffset = (MAX_BW_80MHZ - CW_80MHZ); + + ucMaxBandwidth = cnmGetBssMaxBw(prAdapter, ucBssIndex); + + if (*peChannelWidth > CW_20_40MHZ) { + /*case BW > 80 , 160 80P80 */ + ucCurrentBandwidth = (UINT_8)*peChannelWidth + ucOffset; + } else { + /*case BW20 BW40 */ + if (*peExtend != CHNL_EXT_SCN) { + /*case BW40 */ + ucCurrentBandwidth = MAX_BW_40MHZ; + } + } + + if (ucCurrentBandwidth > ucMaxBandwidth) { + DBGLOG(RLM, INFO, "Decreasse the BW to (%d)\n", ucMaxBandwidth); + + if (ucMaxBandwidth <= MAX_BW_40MHZ) { + /*BW20 * BW40*/ + *peChannelWidth = CW_20_40MHZ; + + if (ucMaxBandwidth == MAX_BW_20MHZ) + *peExtend = CHNL_EXT_SCN; + } else { + /* BW80, BW160, BW80P80 */ + /* ucMaxBandwidth Must be MAX_BW_80MHZ,MAX_BW_160MHZ,MAX_BW_80MHZ */ + /* peExtend should not change */ + *peChannelWidth = (ucMaxBandwidth - ucOffset); + + if (ucMaxBandwidth == MAX_BW_80MHZ) { + /* modify S1 for Bandwidth 160 downgrade 80 case */ + if (ucCurrentBandwidth == MAX_BW_160MHZ) { + if ((*pucPrimaryCh >= 36) && (*pucPrimaryCh <= 48)) + *pucS1 = 42; + else if ((*pucPrimaryCh >= 52) && (*pucPrimaryCh <= 64)) + *pucS1 = 58; + else if ((*pucPrimaryCh >= 100) && (*pucPrimaryCh <= 112)) + *pucS1 = 106; + else if ((*pucPrimaryCh >= 116) && (*pucPrimaryCh <= 128)) + *pucS1 = 122; + else if ((*pucPrimaryCh >= 132) && (*pucPrimaryCh <= 144)) + *pucS1 = 138; /*160 downgrade should not in this case*/ + else if ((*pucPrimaryCh >= 149) && (*pucPrimaryCh <= 161)) + *pucS1 = 155; /*160 downgrade should not in this case*/ + else + DBGLOG(RLM, INFO, "Check connect 160 downgrde (%d) case\n" + , ucMaxBandwidth); + + DBGLOG(RLM, INFO, "Decreasse the BW160 to BW80, shift S1 to (%d)\n", *pucS1); + } + } + } + + DBGLOG(RLM, INFO, "Modify ChannelWidth (%d) and Extend (%d)\n", *peChannelWidth, *peExtend); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Change VHT OP Channel Width, S1, S2 +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmChangeVhtOpBwPara(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex, UINT_8 ucChannelWidth) +{ + P_BSS_INFO_T prBssInfo; + UINT_8 ucVhtLowerChannelFrequency, ucVhtUpperChannelFrequency = 0; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + if (!prBssInfo) + return; + + if (ucChannelWidth == MAX_BW_80_80_MHZ) + prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_80P80; + else if (ucChannelWidth == MAX_BW_160MHZ) + prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_160; + else if (ucChannelWidth == MAX_BW_80MHZ) { + prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_80; + if (prBssInfo->ucVhtPeerChannelWidth == VHT_OP_CHANNEL_WIDTH_160) + prBssInfo->ucVhtChannelFrequencyS1 = + (prBssInfo->ucVhtPeerChannelFrequencyS1 > prBssInfo->ucPrimaryChannel) ? + (prBssInfo->ucVhtPeerChannelFrequencyS1 - 8) : (prBssInfo->ucVhtPeerChannelFrequencyS1 + 8); + else if (prBssInfo->ucVhtPeerChannelWidth == VHT_OP_CHANNEL_WIDTH_80P80) { + if (prBssInfo->ucVhtChannelFrequencyS1 < prBssInfo->ucVhtChannelFrequencyS2) { + ucVhtLowerChannelFrequency = prBssInfo->ucVhtChannelFrequencyS1; + ucVhtUpperChannelFrequency = prBssInfo->ucVhtChannelFrequencyS2; + } else { + ucVhtLowerChannelFrequency = prBssInfo->ucVhtChannelFrequencyS2; + ucVhtUpperChannelFrequency = prBssInfo->ucVhtChannelFrequencyS1; + } + prBssInfo->ucVhtChannelFrequencyS1 = prBssInfo->ucPrimaryChannel < + ((ucVhtLowerChannelFrequency + ucVhtUpperChannelFrequency)/2) ? + ucVhtLowerChannelFrequency : ucVhtUpperChannelFrequency; + prBssInfo->ucVhtChannelFrequencyS2 = 0; + } + } else if ((ucChannelWidth == MAX_BW_40MHZ) || (ucChannelWidth == MAX_BW_20MHZ)) + prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_20_40; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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; + P_WIFI_VAR_T prWifiVar = &prAdapter->rWifiVar; +#if CFG_SUPPORT_QUIET && 0 + BOOLEAN fgHasQuietIE = FALSE; +#endif + BOOLEAN IsfgHtCapChange = FALSE; + +#if CFG_SUPPORT_802_11AC + P_IE_VHT_OP_T prVhtOp; + P_IE_VHT_CAP_T prVhtCap; + P_IE_OP_MODE_NOTIFICATION_T prOPModeNotification; /* Operation Mode Notification */ + BOOLEAN fgHasOPModeIE = FALSE; + UINT_8 ucVhtOpModeChannelWidth = 0; + UINT_8 ucVhtOpModeRxNss = 0; + UINT_8 ucVhtCapMcsOwnNotSupportOffset; + UINT_8 ucMaxBwAllowed; + UINT_8 ucInitVhtOpMode = 0; +#endif + +#if CFG_SUPPORT_DFS + BOOLEAN fgHasWideBandIE = FALSE; + BOOLEAN fgHasSCOIE = FALSE; + BOOLEAN fgHasChannelSwitchIE = FALSE; + BOOLEAN fgNeedSwitchChannel = FALSE; + UINT_8 ucChannelAnnouncePri; + ENUM_CHNL_EXT_T eChannelAnnounceSco; + UINT_8 ucChannelAnnounceChannelS1 = 0; + UINT_8 ucChannelAnnounceChannelS2 = 0; + UINT_8 ucChannelAnnounceVhtBw; + P_IE_CHANNEL_SWITCH_T prChannelSwitchAnnounceIE; + P_IE_SECONDARY_OFFSET_T prSecondaryOffsetIE; + P_IE_WIDE_BAND_CHANNEL_T prWideBandChannelIE; +#endif + PUINT_8 pucDumpIE; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(pucIE); + + prStaRec = prBssInfo->prStaRecOfAP; + ASSERT(prStaRec); + if (!prStaRec) + return 0; + + prBssInfo->fgUseShortPreamble = prBssInfo->fgIsShortPreambleAllowed; + ucPrimaryChannel = 0; + prObssScnParam = NULL; + ucMaxBwAllowed = cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex); + pucDumpIE = pucIE; + + /* Note: HT-related members in staRec may not be zero before, so + * if following IE does not exist, they are still not zero. + * These HT-related parameters are valid only when the corresponding + * BssInfo supports 802.11n, i.e., RLM_NET_IS_11N() + */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_HT_CAP: + if (!RLM_NET_IS_11N(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_HT_CAP_T) - 2)) + break; + prHtCap = (P_IE_HT_CAP_T) pucIE; + prStaRec->ucMcsSet = prHtCap->rSupMcsSet.aucRxMcsBitmask[0]; + prStaRec->fgSupMcs32 = (prHtCap->rSupMcsSet.aucRxMcsBitmask[32 / 8] & BIT(0)) ? TRUE : FALSE; + + kalMemCopy(prStaRec->aucRxMcsBitmask, prHtCap->rSupMcsSet.aucRxMcsBitmask, + sizeof(prStaRec->aucRxMcsBitmask) /*SUP_MCS_RX_BITMASK_OCTET_NUM */); + + prStaRec->u2RxHighestSupportedRate = prHtCap->rSupMcsSet.u2RxHighestSupportedRate; + prStaRec->u4TxRateInfo = prHtCap->rSupMcsSet.u4TxRateInfo; + + if ((prStaRec->u2HtCapInfo & HT_CAP_INFO_SM_POWER_SAVE) != + (prHtCap->u2HtCapInfo & HT_CAP_INFO_SM_POWER_SAVE)) + IsfgHtCapChange = TRUE;/* Purpose : To detect SMPS change */ + + prStaRec->u2HtCapInfo = prHtCap->u2HtCapInfo; + /* Set LDPC Tx capability */ + if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxLdpc)) + prStaRec->u2HtCapInfo |= HT_CAP_INFO_LDPC_CAP; + else if (IS_FEATURE_DISABLED(prWifiVar->ucTxLdpc)) + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_LDPC_CAP; + + /* Set STBC Tx capability */ + if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxStbc)) + prStaRec->u2HtCapInfo |= HT_CAP_INFO_RX_STBC; + else if (IS_FEATURE_DISABLED(prWifiVar->ucTxStbc)) + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_RX_STBC; + + /* Set Short GI Tx capability */ + if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxShortGI)) { + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SHORT_GI_20M; + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SHORT_GI_40M; + } else if (IS_FEATURE_DISABLED(prWifiVar->ucTxShortGI)) { + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SHORT_GI_20M; + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SHORT_GI_40M; + } + + /* Set HT Greenfield Tx capability */ + if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxGf)) + prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + else if (IS_FEATURE_DISABLED(prWifiVar->ucTxGf)) + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_HT_GF; + + 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; + + /*Backup peer HT OP Info*/ + prBssInfo->ucHtPeerOpInfo1 = prHtOp->ucInfo1; + + 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); + + if (prBssInfo->ucOpChangeChannelWidth == MAX_BW_20MHZ && prBssInfo->fgIsOpChangeChannelWidth) { + prBssInfo->ucHtOpInfo1 &= ~(HT_OP_INFO1_SCO | HT_OP_INFO1_STA_CHNL_WIDTH); + prBssInfo->eBssSCO = CHNL_EXT_SCN; + } + + 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; + +#if CFG_SUPPORT_802_11AC + case ELEM_ID_VHT_CAP: + if (!RLM_NET_IS_11AC(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_VHT_CAP_T) - 2)) + break; + + prVhtCap = (P_IE_VHT_CAP_T) pucIE; + + prStaRec->u4VhtCapInfo = prVhtCap->u4VhtCapInfo; + /* Set Tx LDPC capability */ + if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxLdpc)) + prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_RX_LDPC; + else if (IS_FEATURE_DISABLED(prWifiVar->ucTxLdpc)) + prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_RX_LDPC; + + /* Set Tx STBC capability */ + if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxStbc)) + prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_RX_STBC_MASK; + else if (IS_FEATURE_DISABLED(prWifiVar->ucTxStbc)) + prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_RX_STBC_MASK; + + /* Set Tx TXOP PS capability */ + if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxopPsTx)) + prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_VHT_TXOP_PS; + else if (IS_FEATURE_DISABLED(prWifiVar->ucTxopPsTx)) + prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_VHT_TXOP_PS; + + /* Set Tx Short GI capability */ + if (IS_FEATURE_FORCE_ENABLED(prWifiVar->ucTxShortGI)) { + prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_SHORT_GI_80; + prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_SHORT_GI_160_80P80; + } else if (IS_FEATURE_DISABLED(prWifiVar->ucTxShortGI)) { + prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_SHORT_GI_80; + prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_SHORT_GI_160_80P80; + } + + /*Set Vht Rx Mcs Map upon peer's capability and our capability */ + prStaRec->u2VhtRxMcsMap = prVhtCap->rVhtSupportedMcsSet.u2RxMcsMap; + if (wlanGetSupportNss(prAdapter, prStaRec->ucBssIndex) < 8) { + ucVhtCapMcsOwnNotSupportOffset = wlanGetSupportNss(prAdapter, prStaRec->ucBssIndex) * 2; + /*Mark Rx Mcs Map which we don't support*/ + prStaRec->u2VhtRxMcsMap |= BITS(ucVhtCapMcsOwnNotSupportOffset, 15); + } + if (prStaRec->u2VhtRxMcsMap != prVhtCap->rVhtSupportedMcsSet.u2RxMcsMap) + DBGLOG(RLM, INFO, "Change VhtRxMcsMap from 0x%x to 0x%x due to our Nss setting\n", + prVhtCap->rVhtSupportedMcsSet.u2RxMcsMap, prStaRec->u2VhtRxMcsMap); + + prStaRec->u2VhtRxHighestSupportedDataRate = + prVhtCap->rVhtSupportedMcsSet.u2RxHighestSupportedDataRate; + prStaRec->u2VhtTxMcsMap = prVhtCap->rVhtSupportedMcsSet.u2TxMcsMap; + prStaRec->u2VhtTxHighestSupportedDataRate = + prVhtCap->rVhtSupportedMcsSet.u2TxHighestSupportedDataRate; + + break; + + case ELEM_ID_VHT_OP: + if (!RLM_NET_IS_11AC(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_VHT_OP_T) - 2)) + break; + + prVhtOp = (P_IE_VHT_OP_T) pucIE; + + /*Backup peer VHT OpInfo*/ + prBssInfo->ucVhtPeerChannelWidth = prVhtOp->ucVhtOperation[0]; + prBssInfo->ucVhtPeerChannelFrequencyS1 = prVhtOp->ucVhtOperation[1]; + prBssInfo->ucVhtPeerChannelFrequencyS2 = prVhtOp->ucVhtOperation[2]; + + rlmModifyVhtBwPara(&prBssInfo->ucVhtPeerChannelFrequencyS1, + &prBssInfo->ucVhtPeerChannelFrequencyS2, + &prBssInfo->ucVhtPeerChannelWidth); + + prBssInfo->ucVhtChannelWidth = prVhtOp->ucVhtOperation[0]; + prBssInfo->ucVhtChannelFrequencyS1 = prVhtOp->ucVhtOperation[1]; + prBssInfo->ucVhtChannelFrequencyS2 = prVhtOp->ucVhtOperation[2]; + prBssInfo->u2VhtBasicMcsSet = prVhtOp->u2VhtBasicMcsSet; + + rlmModifyVhtBwPara(&prBssInfo->ucVhtChannelFrequencyS1, + &prBssInfo->ucVhtChannelFrequencyS2, + &prBssInfo->ucVhtChannelWidth); + + if (prBssInfo->fgIsOpChangeChannelWidth) + rlmChangeVhtOpBwPara(prAdapter, prBssInfo->ucBssIndex, + prBssInfo->ucOpChangeChannelWidth); + + /* Set initial value of VHT OP mode */ + ucInitVhtOpMode = 0; + switch (prBssInfo->ucVhtChannelWidth) { + case VHT_OP_CHANNEL_WIDTH_20_40: + ucInitVhtOpMode |= VHT_OP_MODE_CHANNEL_WIDTH_40; + break; + case VHT_OP_CHANNEL_WIDTH_80: + ucInitVhtOpMode |= VHT_OP_MODE_CHANNEL_WIDTH_80; + break; + case VHT_OP_CHANNEL_WIDTH_160: + case VHT_OP_CHANNEL_WIDTH_80P80: + ucInitVhtOpMode |= VHT_OP_MODE_CHANNEL_WIDTH_160_80P80; + break; + default: + ucInitVhtOpMode |= VHT_OP_MODE_CHANNEL_WIDTH_80; + break; + } + ucInitVhtOpMode |= ((prBssInfo->ucNss-1) << VHT_OP_MODE_RX_NSS_OFFSET) & VHT_OP_MODE_RX_NSS; + break; + case ELEM_ID_OP_MODE: + if (!RLM_NET_IS_11AC(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_OP_MODE_NOTIFICATION_T) - 2)) + break; + prOPModeNotification = (P_IE_OP_MODE_NOTIFICATION_T) pucIE; + + if ((prOPModeNotification->ucOpMode & VHT_OP_MODE_RX_NSS_TYPE) + != VHT_OP_MODE_RX_NSS_TYPE) { + if (prStaRec->ucVhtOpMode != prOPModeNotification->ucOpMode) { + prStaRec->ucVhtOpMode = prOPModeNotification->ucOpMode; + fgHasOPModeIE = TRUE; + ucVhtOpModeChannelWidth = + ((prOPModeNotification->ucOpMode) & VHT_OP_MODE_CHANNEL_WIDTH); + ucVhtOpModeRxNss = + ((prOPModeNotification->ucOpMode) & VHT_OP_MODE_RX_NSS) >> + VHT_OP_MODE_RX_NSS_OFFSET; + } else /* Let the further flow not to update VhtOpMode */ + ucInitVhtOpMode = prStaRec->ucVhtOpMode; + } + + break; +#if CFG_SUPPORT_DFS + case ELEM_ID_WIDE_BAND_CHANNEL_SWITCH: + if (!RLM_NET_IS_11AC(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_WIDE_BAND_CHANNEL_T) - 2)) + break; + DBGLOG(RLM, INFO, "[Channel Switch] ELEM_ID_WIDE_BAND_CHANNEL_SWITCH, 11AC\n"); + prWideBandChannelIE = (P_IE_WIDE_BAND_CHANNEL_T) pucIE; + ucChannelAnnounceVhtBw = prWideBandChannelIE->ucNewChannelWidth; + ucChannelAnnounceChannelS1 = prWideBandChannelIE->ucChannelS1; + ucChannelAnnounceChannelS2 = prWideBandChannelIE->ucChannelS2; + fgHasWideBandIE = TRUE; + DBGLOG(RLM, INFO, + "[Ch] BW=%d, s1=%d, s2=%d\n", ucChannelAnnounceVhtBw, ucChannelAnnounceChannelS1, + ucChannelAnnounceChannelS2); + break; +#endif + +#endif + case ELEM_ID_20_40_BSS_COEXISTENCE: + if (!RLM_NET_IS_11N(prBssInfo)) + break; + /* To do: store if scanning exemption grant to BssInfo */ + break; + + case ELEM_ID_OBSS_SCAN_PARAMS: + if (!RLM_NET_IS_11N(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_OBSS_SCAN_PARAM_T) - 2)) + break; + /* Store OBSS parameters to BssInfo */ + prObssScnParam = (P_IE_OBSS_SCAN_PARAM_T) pucIE; + break; + + case ELEM_ID_EXTENDED_CAP: + if (!RLM_NET_IS_11N(prBssInfo)) + break; + /* To do: store extended capability (PSMP, coexist) to BssInfo */ + break; + + case ELEM_ID_ERP_INFO: + if (IE_LEN(pucIE) != (sizeof(IE_ERP_T) - 2) || prBssInfo->eBand != BAND_2G4) + break; + ucERP = ERP_INFO_IE(pucIE)->ucERP; + prBssInfo->fgErpProtectMode = (ucERP & ERP_INFO_USE_PROTECTION) ? TRUE : FALSE; + + if (ucERP & ERP_INFO_BARKER_PREAMBLE_MODE) + prBssInfo->fgUseShortPreamble = FALSE; + break; + + case ELEM_ID_DS_PARAM_SET: + if (IE_LEN(pucIE) == ELEM_MAX_LEN_DS_PARAMETER_SET) + ucPrimaryChannel = DS_PARAM_IE(pucIE)->ucCurrChnl; + break; +#if CFG_SUPPORT_DFS + case ELEM_ID_CH_SW_ANNOUNCEMENT: + if (IE_LEN(pucIE) != (sizeof(IE_CHANNEL_SWITCH_T) - 2)) + break; + + prChannelSwitchAnnounceIE = (P_IE_CHANNEL_SWITCH_T) pucIE; + + DBGLOG(RLM, INFO, "[Ch] Count=%d\n", prChannelSwitchAnnounceIE->ucChannelSwitchCount); + + if (prChannelSwitchAnnounceIE->ucChannelSwitchMode == 1) { + /* Need to stop data transmission immediately */ + fgHasChannelSwitchIE = TRUE; + if (!g_fgHasStopTx) { + g_fgHasStopTx = TRUE; +#if CFG_SUPPORT_TDLS + /* TDLS peers */ + TdlsTxCtrl(prAdapter, prBssInfo, FALSE); +#endif + /* AP */ + qmSetStaRecTxAllowed(prAdapter, prStaRec, FALSE); + DBGLOG(RLM, EVENT, "[Ch] TxAllowed = FALSE\n"); + } + + if (prChannelSwitchAnnounceIE->ucChannelSwitchCount <= 3) { + DBGLOG(RLM, INFO, + "[Ch] switch channel [%d]->[%d]\n", prBssInfo->ucPrimaryChannel, + prChannelSwitchAnnounceIE->ucNewChannelNum); + ucChannelAnnouncePri = prChannelSwitchAnnounceIE->ucNewChannelNum; + fgNeedSwitchChannel = TRUE; + } + } + + break; + case ELEM_ID_SCO: + if (IE_LEN(pucIE) != (sizeof(IE_SECONDARY_OFFSET_T) - 2)) + break; + + prSecondaryOffsetIE = (P_IE_SECONDARY_OFFSET_T) pucIE; + DBGLOG(RLM, INFO, + "[Channel Switch] SCO [%d]->[%d]\n", prBssInfo->eBssSCO, + prSecondaryOffsetIE->ucSecondaryOffset); + eChannelAnnounceSco = (ENUM_CHNL_EXT_T) prSecondaryOffsetIE->ucSecondaryOffset; + fgHasSCOIE = TRUE; + break; +#endif + +#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 */ + + if (IsfgHtCapChange && (prStaRec->ucStaState == STA_STATE_3)) + cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); + + /* 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_802_11AC + /* Check whether the Operation Mode IE is exist or not. + * If exists, then the channel bandwidth of VHT operation field is changed + * with the channel bandwidth setting of Operation Mode field. + * The channel bandwidth of OP Mode IE is 0, represent as 20MHz. + * The channel bandwidth of OP Mode IE is 1, represent as 40MHz. + * The channel bandwidth of OP Mode IE is 2, represent as 80MHz. + * The channel bandwidth of OP Mode IE is 3, represent as 160/80+80MHz. + */ + if (fgHasOPModeIE == TRUE) { + /* 1.Channel width change */ + + if (ucVhtOpModeChannelWidth == VHT_OP_MODE_CHANNEL_WIDTH_20) { + prBssInfo->ucVhtChannelWidth = CW_20_40MHZ; + prBssInfo->ucHtOpInfo1 &= ~HT_OP_INFO1_STA_CHNL_WIDTH; + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SUP_CHNL_WIDTH; + +#if CFG_WORKAROUND_OPMODE_CONFLICT_OPINFO + if (prBssInfo->eBssSCO != CHNL_EXT_SCN) { + DBGLOG(RLM, WARN, "HT_OP_Info != OPmode_Notifify, follow OPmode_Notify to BW20.\n"); + prBssInfo->eBssSCO = CHNL_EXT_SCN; + } +#endif + } + + else if (ucVhtOpModeChannelWidth == VHT_OP_MODE_CHANNEL_WIDTH_40) { + prBssInfo->ucVhtChannelWidth = CW_20_40MHZ; + prBssInfo->ucHtOpInfo1 |= HT_OP_INFO1_STA_CHNL_WIDTH; + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; + +#if CFG_WORKAROUND_OPMODE_CONFLICT_OPINFO + if (prBssInfo->eBssSCO == CHNL_EXT_SCN) { + prBssInfo->ucHtOpInfo1 &= ~HT_OP_INFO1_STA_CHNL_WIDTH; + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SUP_CHNL_WIDTH; + DBGLOG(RLM, WARN, "HT_OP_Info != OPmode_Notifify, follow HT_OP_Info to BW20.\n"); + } +#endif + } + + else if (ucVhtOpModeChannelWidth == VHT_OP_MODE_CHANNEL_WIDTH_80) { + prBssInfo->ucVhtChannelWidth = CW_80MHZ; + prBssInfo->ucHtOpInfo1 |= HT_OP_INFO1_STA_CHNL_WIDTH; + prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_MASK; + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; + } + + else if (ucVhtOpModeChannelWidth == VHT_OP_MODE_CHANNEL_WIDTH_160_80P80) { + prBssInfo->ucHtOpInfo1 |= HT_OP_INFO1_STA_CHNL_WIDTH; + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; + + /* Use VHT OP Info to determine it's BW160 or BW80+BW80 */ + prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_MASK; + if (prBssInfo->ucVhtChannelWidth == VHT_OP_CHANNEL_WIDTH_160) + prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_SET_160; + else if (prBssInfo->ucVhtChannelWidth == VHT_OP_CHANNEL_WIDTH_80P80) + prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_MAX_SUP_CHANNEL_WIDTH_SET_160_80P80; + } + + if (prStaRec->ucStaState == STA_STATE_3) { + DBGLOG(RLM, INFO, "Update OpMode to 0x%x", prStaRec->ucVhtOpMode); + DBGLOG(RLM, INFO, "to FW due to OpMode Notificaition\n"); + cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); + } + } else {/* Set Default if the VHT OP mode field is not present */ + if ((prStaRec->ucVhtOpMode != ucInitVhtOpMode) && (prStaRec->ucStaState == STA_STATE_3)) { + prStaRec->ucVhtOpMode = ucInitVhtOpMode; + DBGLOG(RLM, INFO, "Update OpMode to 0x%x", prStaRec->ucVhtOpMode); + DBGLOG(RLM, INFO, "to FW due to NO OpMode Notificaition\n"); + cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); + } else + prStaRec->ucVhtOpMode = ucInitVhtOpMode; + } +#endif + +#if CFG_SUPPORT_DFS + /*Check whether Channel Announcement IE, Secondary Offset IE & + * Wide Bandwidth Channel Switch IE exist or not. If exist, the priority is + the highest. + */ + + if (fgNeedSwitchChannel) { + P_BSS_DESC_T prBssDesc; + + prBssInfo->ucPrimaryChannel = ucChannelAnnouncePri; + prBssInfo->ucVhtChannelWidth = 0; + prBssInfo->ucVhtChannelFrequencyS1 = 0; + prBssInfo->ucVhtChannelFrequencyS2 = 0; + prBssInfo->eBssSCO = 0; + + prBssDesc = scanSearchBssDescByBssid(prAdapter, prBssInfo->aucBSSID); + + if (prBssDesc) { + DBGLOG(RLM, INFO, "DFS: BSS: " MACSTR " Desc found, channel from %u to %u\n ", + MAC2STR(prBssInfo->aucBSSID), prBssDesc->ucChannelNum, ucChannelAnnouncePri); + prBssDesc->ucChannelNum = ucChannelAnnouncePri; + } else { + DBGLOG(RLM, INFO, "DFS: BSS: " MACSTR " Desc is not found\n ", MAC2STR(prBssInfo->aucBSSID)); + } + + if (fgHasWideBandIE != FALSE) { + prBssInfo->ucVhtChannelWidth = ucChannelAnnounceVhtBw; + prBssInfo->ucVhtChannelFrequencyS1 = ucChannelAnnounceChannelS1; + prBssInfo->ucVhtChannelFrequencyS2 = ucChannelAnnounceChannelS2; + } + if (fgHasSCOIE != FALSE) + prBssInfo->eBssSCO = eChannelAnnounceSco; + + if (prBssDesc) { + kalIndicateChannelSwitch(prAdapter->prGlueInfo, + prBssInfo->eBssSCO, + prBssDesc->ucChannelNum); + } + } + + if (!fgHasChannelSwitchIE && g_fgHasStopTx) { +#if CFG_SUPPORT_TDLS + /* TDLS peers */ + TdlsTxCtrl(prAdapter, prBssInfo, TRUE); +#endif + /* AP */ + qmSetStaRecTxAllowed(prAdapter, prStaRec, TRUE); + + DBGLOG(RLM, EVENT, "[Ch] TxAllowed = TRUE\n"); + g_fgHasStopTx = FALSE; + } + +#endif + rlmReviseMaxBw(prAdapter, prBssInfo->ucBssIndex, &prBssInfo->eBssSCO, + (P_ENUM_CHANNEL_WIDTH_P)&prBssInfo->ucVhtChannelWidth, + &prBssInfo->ucVhtChannelFrequencyS1, &prBssInfo->ucPrimaryChannel); + + rlmRevisePreferBandwidthNss(prAdapter, prBssInfo->ucBssIndex, prStaRec); + + /*printk("Modify ChannelWidth (%d) and Extend (%d)\n",prBssInfo->eBssSCO,prBssInfo->ucVhtChannelWidth);*/ + + if (!rlmDomainIsValidRfSetting(prAdapter, prBssInfo->eBand, + prBssInfo->ucPrimaryChannel, prBssInfo->eBssSCO, + prBssInfo->ucVhtChannelWidth, prBssInfo->ucVhtChannelFrequencyS1, + prBssInfo->ucVhtChannelFrequencyS2)) { + + /*Dump IE Inforamtion */ + DBGLOG(RLM, WARN, "rlmRecIeInfoForClient IE Information\n"); + DBGLOG(RLM, WARN, "IE Length = %d\n", u2IELength); + DBGLOG_MEM8(RLM, WARN, pucDumpIE, u2IELength); + + /*Error Handling for Non-predicted IE - Fixed to set 20MHz */ + prBssInfo->ucVhtChannelWidth = CW_20_40MHZ; + prBssInfo->ucVhtChannelFrequencyS1 = 0; + prBssInfo->ucVhtChannelFrequencyS2 = 0; + prBssInfo->eBssSCO = CHNL_EXT_SCN; + prBssInfo->ucHtOpInfo1 &= ~(HT_OP_INFO1_SCO | HT_OP_INFO1_STA_CHNL_WIDTH); + } +#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) { + DBGLOG(RLM, EVENT, "Start Obss Scan timer [%d--%d]\n", + 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 Update parameters from Association Response frame +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static VOID +rlmRecAssocRespIeInfoForClient(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, PUINT_8 pucIE, UINT_16 u2IELength) +{ + UINT_16 u2Offset; + P_STA_RECORD_T prStaRec; + BOOLEAN fgIsHasHtCap = FALSE; + BOOLEAN fgIsHasVhtCap = FALSE; + P_BSS_DESC_T prBssDesc; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(pucIE); + + prStaRec = prBssInfo->prStaRecOfAP; + + ASSERT(prStaRec); + if (!prStaRec) + return; + + prBssDesc = scanSearchBssDescByBssid(prAdapter, prStaRec->aucMacAddr); + + 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; + fgIsHasHtCap = TRUE; + break; +#if CFG_SUPPORT_802_11AC + case ELEM_ID_VHT_CAP: + if (!RLM_NET_IS_11AC(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_VHT_CAP_T) - 2)) + break; + fgIsHasVhtCap = TRUE; + break; +#endif + default: + break; + } /* end of switch */ + } /* end of IE_FOR_EACH */ + + if (!fgIsHasHtCap) { + prStaRec->ucDesiredPhyTypeSet &= ~PHY_TYPE_BIT_HT; + if (prBssDesc) { + if (prBssDesc->ucPhyTypeSet & PHY_TYPE_BIT_HT) { + DBGLOG(RLM, WARN, "PhyTypeSet in Beacon and AssocResp are unsync. "); + DBGLOG(RLM, WARN, "Follow AssocResp to disable HT.\n"); + } + } + } + if (!fgIsHasVhtCap) { + prStaRec->ucDesiredPhyTypeSet &= ~PHY_TYPE_BIT_VHT; + if (prBssDesc) { + if (prBssDesc->ucPhyTypeSet & PHY_TYPE_BIT_VHT) { + DBGLOG(RLM, WARN, "PhyTypeSet in Beacon and AssocResp are unsync. "); + DBGLOG(RLM, WARN, "Follow AssocResp to disable VHT.\n"); + } + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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 (HAL_RX_STATUS_GET_RF_BAND(prSwRfb->prRxStatus) != BAND_2G4) + return FALSE; + + if (ucPriChannel == 0 || ucPriChannel > 14) + ucPriChannel = HAL_RX_STATUS_GET_CHNL_NUM(prSwRfb->prRxStatus); + + 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) + || (prBssInfo->eBand != BAND_2G4)) ? 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 i; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + ASSERT(pucIE); + + fgNewParameter = FALSE; + + /* When concurrent networks exist, GO shall have the same handle as + * the other BSS, so the Beacon shall be processed for bandwidth and + * protection mechanism. + * Note1: we do not have 2 AP (GO) cases simultaneously now. + * Note2: If we are GO, concurrent AIS AP should detect it and reflect + * action in its Beacon, so AIS STA just follows Beacon from AP. + */ + for (i = 0; i < BSS_INFO_NUM; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + + if (IS_BSS_BOW(prBssInfo)) + continue; + + 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: Nothing */ + /* To do: Ad-hoc */ + } + + /* Appy new parameters if necessary */ + if (fgNewParameter) { + rlmSyncOperationParams(prAdapter, prBssInfo); + fgNewParameter = FALSE; + } + } /* end of IS_BSS_ACTIVE() */ + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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); + if (!prStaRec) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + if (!prBssInfo) + return; + + if (prStaRec != prBssInfo->prStaRecOfAP) + return; + + /* 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) + || (prBssInfo->eBand != BAND_2G4)) ? TRUE : FALSE; + ucPriChannel = rlmRecIeInfoForClient(prAdapter, prBssInfo, pucIE, u2IELength); + + /*Update the parameters from Association Response only, + *if the parameters need to be updated by both Beacon and Association Response, + *user should use another function, rlmRecIeInfoForClient() + */ + rlmRecAssocRespIeInfoForClient(prAdapter, prBssInfo, pucIE, u2IELength); + + if (prBssInfo->ucPrimaryChannel != ucPriChannel) { + DBGLOG(RLM, INFO, + "Use RF pri channel[%u].Pri channel in HT OP IE is :[%u]\n", prBssInfo->ucPrimaryChannel, + ucPriChannel); + } + /*Avoid wrong primary channel info in HT operation IE info when accept association response */ +#if 0 + if (ucPriChannel > 0) + prBssInfo->ucPrimaryChannel = ucPriChannel; +#endif + + 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 +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmProcessHtAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) +{ + P_ACTION_NOTIFY_CHNL_WIDTH_FRAME prRxFrame; + P_ACTION_SM_POWER_SAVE_FRAME prRxSmpsFrame; + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prBssInfo; + UINT_16 u2HtCapInfoBitmask = 0; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxFrame = (P_ACTION_NOTIFY_CHNL_WIDTH_FRAME) prSwRfb->pvHeader; + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (!prStaRec) + return; + + switch (prRxFrame->ucAction) { + case ACTION_HT_NOTIFY_CHANNEL_WIDTH: + if (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 + */ + /* 1. Update StaRec for AP/STA mode */ + 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; + + cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); + + /* 2. Update BssInfo for STA mode */ + prBssInfo = prAdapter->aprBssInfo[prStaRec->ucBssIndex]; + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + if (prRxFrame->ucChannelWidth == 0) + prBssInfo->ucHtOpInfo1 &= ~HT_OP_INFO1_STA_CHNL_WIDTH; + if (prRxFrame->ucChannelWidth == 1) + prBssInfo->ucHtOpInfo1 |= HT_OP_INFO1_STA_CHNL_WIDTH; + + nicUpdateBss(prAdapter, prBssInfo->ucBssIndex); + } + break; + /* Support SM power save */ /* TH3_Huang */ + case ACTION_HT_SM_POWER_SAVE: + prRxSmpsFrame = (P_ACTION_SM_POWER_SAVE_FRAME) prSwRfb->pvHeader; + if (prStaRec->ucStaState != STA_STATE_3 || + prSwRfb->u2PacketLen < sizeof(ACTION_SM_POWER_SAVE_FRAME)) { + return; + } + + /* The SM power enable bit is different definition in HtCap and SMpower IE field */ + if (!(prRxSmpsFrame->ucSmPowerCtrl & + (HT_SM_POWER_SAVE_CONTROL_ENABLED|HT_SM_POWER_SAVE_CONTROL_SM_MODE))) + u2HtCapInfoBitmask |= HT_CAP_INFO_SM_POWER_SAVE; + + /* Support SMPS action frame, TH3_Huang */ + /* Update StaRec if SM power state changed */ + if ((prStaRec->u2HtCapInfo & HT_CAP_INFO_SM_POWER_SAVE) != u2HtCapInfoBitmask) { + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SM_POWER_SAVE; + prStaRec->u2HtCapInfo |= u2HtCapInfoBitmask; + DBGLOG(RLM, INFO, + "rlmProcessHtAction -- SMPS change u2HtCapInfo to (%x)\n", + prStaRec->u2HtCapInfo); + cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); + } + break; + default: + break; + } +} + +#if CFG_SUPPORT_802_11AC +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmProcessVhtAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) +{ + P_ACTION_OP_MODE_NOTIFICATION_FRAME prRxFrame; + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxFrame = (P_ACTION_OP_MODE_NOTIFICATION_FRAME) prSwRfb->pvHeader; + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (!prStaRec) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + if (!prBssInfo) + return; + + switch (prRxFrame->ucAction) { + /* Support Operating mode notification action frame, TH3_Huang */ + case ACTION_OPERATING_MODE_NOTIFICATION: + if (prStaRec->ucStaState != STA_STATE_3 || + prSwRfb->u2PacketLen < sizeof(ACTION_OP_MODE_NOTIFICATION_FRAME)) { + return; + } + + if (((prRxFrame->ucOperatingMode & VHT_OP_MODE_RX_NSS_TYPE) + != VHT_OP_MODE_RX_NSS_TYPE) && + (prStaRec->ucVhtOpMode != prRxFrame->ucOperatingMode)) { + prStaRec->ucVhtOpMode = prRxFrame->ucOperatingMode; + DBGLOG(RLM, INFO, + "rlmProcessVhtAction -- Update ucVhtOpMode to 0x%x\n", prStaRec->ucVhtOpMode); + cnmStaSendUpdateCmd(prAdapter, prStaRec, NULL, FALSE); + } + break; + default: + break; + } +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function should be invoked after judging successful association. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmFillSyncCmdParam(P_CMD_SET_BSS_RLM_PARAM_T prCmdBody, P_BSS_INFO_T prBssInfo) +{ + ASSERT(prCmdBody && prBssInfo); + if (!prCmdBody || !prBssInfo) + return; + + prCmdBody->ucBssIndex = prBssInfo->ucBssIndex; + 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->ucVhtChannelWidth = prBssInfo->ucVhtChannelWidth; + prCmdBody->ucVhtChannelFrequencyS1 = prBssInfo->ucVhtChannelFrequencyS1; + prCmdBody->ucVhtChannelFrequencyS2 = prBssInfo->ucVhtChannelFrequencyS2; + prCmdBody->u2VhtBasicMcsSet = prBssInfo->u2BSSBasicRateSet; + prCmdBody->ucNss = prBssInfo->ucNss; + + 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 w=%d s1=%d s2=%d n=%d\n", + prCmdBody->ucBssIndex, prCmdBody->ucRfBand, + prCmdBody->ucPrimaryChannel, prCmdBody->ucRfSco, + prCmdBody->ucErpProtectMode, prCmdBody->ucHtProtectMode, + prCmdBody->ucHtOpInfo1, prCmdBody->ucUseShortSlotTime, + prCmdBody->ucUseShortPreamble, + prCmdBody->ucVhtChannelWidth, + prCmdBody->ucVhtChannelFrequencyS1, prCmdBody->ucVhtChannelFrequencyS2, + prCmdBody->ucNss); + } else { + DBGLOG(RLM, INFO, "N=%d closed\n", prCmdBody->ucBssIndex); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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->ucBssIndex); + 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); */ + if (rStatus != WLAN_STATUS_PENDING) + DBGLOG(RLM, WARN, "rlmSyncOperationParams set cmd fail\n"); + + 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; +#if CFG_SUPPORT_802_11AC + P_IE_VHT_CAP_T prVhtCap; + UINT_8 ucVhtCapMcsOwnNotSupportOffset; + /* UINT_8 ucVhtCapMcsPeerNotSupportOffset; */ + P_IE_OP_MODE_NOTIFICATION_T prOPModeNotification; /* Operation Mode Notification */ +#endif + + ASSERT(prAdapter); + ASSERT(prSwRfb); + ASSERT(pucIE); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (!prStaRec) + return; + ASSERT(prStaRec->ucBssIndex <= MAX_BSS_INDEX); + + prBssInfo = prAdapter->aprBssInfo[prStaRec->ucBssIndex]; + + 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; + + kalMemCopy(prStaRec->aucRxMcsBitmask, prHtCap->rSupMcsSet.aucRxMcsBitmask, + sizeof(prStaRec->aucRxMcsBitmask) /*SUP_MCS_RX_BITMASK_OCTET_NUM */); + + prStaRec->u2HtCapInfo = prHtCap->u2HtCapInfo; + + /* Set Short LDPC Tx capability */ + if (IS_FEATURE_FORCE_ENABLED(prAdapter->rWifiVar.ucTxLdpc)) + prStaRec->u2HtCapInfo |= HT_CAP_INFO_LDPC_CAP; + else if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucTxLdpc)) + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_LDPC_CAP; + + /* Set STBC Tx capability */ + if (IS_FEATURE_FORCE_ENABLED(prAdapter->rWifiVar.ucTxStbc)) + prStaRec->u2HtCapInfo |= HT_CAP_INFO_RX_STBC; + else if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucTxStbc)) + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_RX_STBC; + /* Set Short GI Tx capability */ + if (IS_FEATURE_FORCE_ENABLED(prAdapter->rWifiVar.ucTxShortGI)) { + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SHORT_GI_20M; + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SHORT_GI_40M; + } else if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucTxShortGI)) { + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SHORT_GI_20M; + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SHORT_GI_40M; + } + + /* Set HT Greenfield Tx capability */ + if (IS_FEATURE_FORCE_ENABLED(prAdapter->rWifiVar.ucTxGf)) + prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + else if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucTxGf)) + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_HT_GF; + + prStaRec->ucAmpduParam = prHtCap->ucAmpduParam; + prStaRec->u2HtExtendedCap = prHtCap->u2HtExtendedCap; + prStaRec->u4TxBeamformingCap = prHtCap->u4TxBeamformingCap; + prStaRec->ucAselCap = prHtCap->ucAselCap; + break; + +#if CFG_SUPPORT_802_11AC + case ELEM_ID_VHT_CAP: + if (!RLM_NET_IS_11AC(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_VHT_CAP_T) - 2)) + break; + + prVhtCap = (P_IE_VHT_CAP_T) pucIE; + + prStaRec->u4VhtCapInfo = prVhtCap->u4VhtCapInfo; + + /* Set Tx LDPC capability */ + if (IS_FEATURE_FORCE_ENABLED(prAdapter->rWifiVar.ucTxLdpc)) + prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_RX_LDPC; + else if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucTxLdpc)) + prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_RX_LDPC; + + /* Set Tx STBC capability */ + if (IS_FEATURE_FORCE_ENABLED(prAdapter-> + rWifiVar.ucTxStbc)) { + prStaRec->u4VhtCapInfo |= + VHT_CAP_INFO_RX_STBC_MASK; + } else if (IS_FEATURE_DISABLED(prAdapter-> + rWifiVar.ucTxStbc)) { + prStaRec->u4VhtCapInfo &= + ~VHT_CAP_INFO_RX_STBC_MASK; + } + /* Set Tx TXOP PS capability */ + if (IS_FEATURE_FORCE_ENABLED(prAdapter->rWifiVar.ucTxopPsTx)) + prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_VHT_TXOP_PS; + else if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucTxopPsTx)) + prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_VHT_TXOP_PS; + + /* Set Tx Short GI capability */ + if (IS_FEATURE_FORCE_ENABLED(prAdapter->rWifiVar.ucTxShortGI)) { + prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_SHORT_GI_80; + prStaRec->u4VhtCapInfo |= VHT_CAP_INFO_SHORT_GI_160_80P80; + } else if (IS_FEATURE_DISABLED(prAdapter->rWifiVar.ucTxShortGI)) { + prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_SHORT_GI_80; + prStaRec->u4VhtCapInfo &= ~VHT_CAP_INFO_SHORT_GI_160_80P80; + } + + /*Set Vht Rx Mcs Map upon peer's capability and our capability */ + prStaRec->u2VhtRxMcsMap = prVhtCap->rVhtSupportedMcsSet.u2RxMcsMap; + if (wlanGetSupportNss(prAdapter, prStaRec->ucBssIndex) < 8) { + ucVhtCapMcsOwnNotSupportOffset = + wlanGetSupportNss(prAdapter, prStaRec->ucBssIndex) * 2; + prStaRec->u2VhtRxMcsMap |= BITS(ucVhtCapMcsOwnNotSupportOffset, 15); + /*Mark Rx Mcs Map which we don't support*/ + } + if (prStaRec->u2VhtRxMcsMap != prVhtCap->rVhtSupportedMcsSet.u2RxMcsMap) + DBGLOG(RLM, INFO, "Change VhtRxMcsMap from 0x%x to 0x%x due to our Nss setting\n", + prVhtCap->rVhtSupportedMcsSet.u2RxMcsMap, + prStaRec->u2VhtRxMcsMap); + + prStaRec->u2VhtRxHighestSupportedDataRate = + prVhtCap->rVhtSupportedMcsSet.u2RxHighestSupportedDataRate; + prStaRec->u2VhtTxMcsMap = prVhtCap->rVhtSupportedMcsSet.u2TxMcsMap; + prStaRec->u2VhtTxHighestSupportedDataRate = + prVhtCap->rVhtSupportedMcsSet.u2TxHighestSupportedDataRate; + + /* Set initial value of VHT OP mode */ + prStaRec->ucVhtOpMode = 0; + switch (prBssInfo->ucVhtChannelWidth) { + case VHT_OP_CHANNEL_WIDTH_20_40: + prStaRec->ucVhtOpMode |= VHT_OP_MODE_CHANNEL_WIDTH_40; + break; + case VHT_OP_CHANNEL_WIDTH_80: + prStaRec->ucVhtOpMode |= VHT_OP_MODE_CHANNEL_WIDTH_80; + break; + case VHT_OP_CHANNEL_WIDTH_160: + case VHT_OP_CHANNEL_WIDTH_80P80: + prStaRec->ucVhtOpMode |= VHT_OP_MODE_CHANNEL_WIDTH_160_80P80; + break; + default: + prStaRec->ucVhtOpMode |= VHT_OP_MODE_CHANNEL_WIDTH_80; + break; + } + prStaRec->ucVhtOpMode |= ((prBssInfo->ucNss-1) << + VHT_OP_MODE_RX_NSS_OFFSET) & VHT_OP_MODE_RX_NSS; + + break; + case ELEM_ID_OP_MODE: + if (!RLM_NET_IS_11AC(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_OP_MODE_NOTIFICATION_T) - 2)) + break; + prOPModeNotification = (P_IE_OP_MODE_NOTIFICATION_T) pucIE; + + if ((prOPModeNotification->ucOpMode & VHT_OP_MODE_RX_NSS_TYPE) + != VHT_OP_MODE_RX_NSS_TYPE) { + prStaRec->ucVhtOpMode = prOPModeNotification->ucOpMode; + } + + break; + +#endif + + 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; + +#if CFG_SUPPORT_802_11AC + prBssInfo->ucVhtChannelWidth = 0; /* VHT_OP_CHANNEL_WIDTH_80; */ + prBssInfo->ucVhtChannelFrequencyS1 = 0; /* 42; */ + prBssInfo->ucVhtChannelFrequencyS2 = 0; + prBssInfo->u2VhtBasicMcsSet = 0; /* 0xFFFF; */ +#endif + + prBssInfo->eBssSCO = 0; + prBssInfo->fgErpProtectMode = 0; + prBssInfo->eHtProtectMode = 0; + prBssInfo->eGfOperationMode = 0; + prBssInfo->eRifsOperationMode = 0; + + /* OBSS related parameters */ + prBssInfo->auc2G_20mReqChnlList[0] = 0; + prBssInfo->auc2G_NonHtChnlList[0] = 0; + prBssInfo->auc2G_PriChnlList[0] = 0; + prBssInfo->auc2G_SecChnlList[0] = 0; + prBssInfo->auc5G_20mReqChnlList[0] = 0; + prBssInfo->auc5G_NonHtChnlList[0] = 0; + prBssInfo->auc5G_PriChnlList[0] = 0; + prBssInfo->auc5G_SecChnlList[0] = 0; + + /* All RLM timers will also be stopped */ + cnmTimerStopTimer(prAdapter, &prBssInfo->rObssScanTimer); + prBssInfo->u2ObssScanInterval = 0; + + prBssInfo->fgObssErpProtectMode = 0; /* GO only */ + prBssInfo->eObssHtProtectMode = 0; /* GO only */ + prBssInfo->eObssGfOperationMode = 0; /* GO only */ + prBssInfo->fgObssRifsOperationMode = 0; /* GO only */ + prBssInfo->fgObssActionForcedTo20M = 0; /* GO only */ + prBssInfo->fgObssBeaconForcedTo20M = 0; /* GO only */ +} + +#if CFG_SUPPORT_TDLS +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 rlmFillVhtCapIEByAdapter(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, UINT_8 *pOutBuf) +{ + P_IE_VHT_CAP_T prVhtCap; + P_VHT_SUPPORTED_MCS_FIELD prVhtSupportedMcsSet; + UINT_8 i; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + /* ASSERT(prMsduInfo); */ + + prVhtCap = (P_IE_VHT_CAP_T) pOutBuf; + + prVhtCap->ucId = ELEM_ID_VHT_CAP; + prVhtCap->ucLength = sizeof(IE_VHT_CAP_T) - ELEM_HDR_LEN; + prVhtCap->u4VhtCapInfo = VHT_CAP_INFO_DEFAULT_VAL; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxShortGI)) + prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_SHORT_GI_80; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxLdpc)) + prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_RX_LDPC; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxStbc)) + prVhtCap->u4VhtCapInfo |= VHT_CAP_INFO_RX_STBC_ONE_STREAM; + + /*set MCS map */ + prVhtSupportedMcsSet = &prVhtCap->rVhtSupportedMcsSet; + kalMemZero((PVOID) prVhtSupportedMcsSet, sizeof(VHT_SUPPORTED_MCS_FIELD)); + + for (i = 0; i < 8; i++) { + prVhtSupportedMcsSet->u2RxMcsMap |= BITS(2 * i, (2 * i + 1)); + prVhtSupportedMcsSet->u2TxMcsMap |= BITS(2 * i, (2 * i + 1)); + } + + prVhtSupportedMcsSet->u2RxMcsMap &= (VHT_CAP_INFO_MCS_MAP_MCS9 << VHT_CAP_INFO_MCS_1SS_OFFSET); + prVhtSupportedMcsSet->u2TxMcsMap &= (VHT_CAP_INFO_MCS_MAP_MCS9 << VHT_CAP_INFO_MCS_1SS_OFFSET); + prVhtSupportedMcsSet->u2RxHighestSupportedDataRate = VHT_CAP_INFO_DEFAULT_HIGHEST_DATA_RATE; + prVhtSupportedMcsSet->u2TxHighestSupportedDataRate = VHT_CAP_INFO_DEFAULT_HIGHEST_DATA_RATE; + + ASSERT(IE_SIZE(prVhtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP)); + + return IE_SIZE(prVhtCap); +} +#endif + +#if CFG_SUPPORT_TDLS +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +rlmFillHtCapIEByParams(BOOLEAN fg40mAllowed, + BOOLEAN fgShortGIDisabled, + UINT_8 u8SupportRxSgi20, + UINT_8 u8SupportRxSgi40, UINT_8 u8SupportRxGf, ENUM_OP_MODE_T eCurrentOPMode, UINT_8 *pOutBuf) +{ + P_IE_HT_CAP_T prHtCap; + P_SUP_MCS_SET_FIELD prSupMcsSet; + + ASSERT(pOutBuf); + + prHtCap = (P_IE_HT_CAP_T) pOutBuf; + + /* Add HT capabilities IE */ + prHtCap->ucId = ELEM_ID_HT_CAP; + prHtCap->ucLength = sizeof(IE_HT_CAP_T) - ELEM_HDR_LEN; + + prHtCap->u2HtCapInfo = HT_CAP_INFO_DEFAULT_VAL; + if (!fg40mAllowed) { + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | + HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_DSSS_CCK_IN_40M); + } + if (fgShortGIDisabled) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); + + if (u8SupportRxSgi20 == 2) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_20M); + if (u8SupportRxSgi40 == 2) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_40M); + if (u8SupportRxGf == 2) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_HT_GF); + + prHtCap->ucAmpduParam = AMPDU_PARAM_DEFAULT_VAL; + + prSupMcsSet = &prHtCap->rSupMcsSet; + kalMemZero((PVOID)&prSupMcsSet->aucRxMcsBitmask[0], SUP_MCS_RX_BITMASK_OCTET_NUM); + + prSupMcsSet->aucRxMcsBitmask[0] = BITS(0, 7); + + if (fg40mAllowed) + prSupMcsSet->aucRxMcsBitmask[32 / 8] = BIT(0); /* MCS32 */ + prSupMcsSet->u2RxHighestSupportedRate = SUP_MCS_RX_DEFAULT_HIGHEST_RATE; + prSupMcsSet->u4TxRateInfo = SUP_MCS_TX_DEFAULT_VAL; + + prHtCap->u2HtExtendedCap = HT_EXT_CAP_DEFAULT_VAL; + if (!fg40mAllowed || eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + prHtCap->u2HtExtendedCap &= ~(HT_EXT_CAP_PCO | HT_EXT_CAP_PCO_TRANS_TIME_NONE); + + prHtCap->u4TxBeamformingCap = TX_BEAMFORMING_CAP_DEFAULT_VAL; + + prHtCap->ucAselCap = ASEL_CAP_DEFAULT_VAL; + + ASSERT(IE_SIZE(prHtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP)); + + return IE_SIZE(prHtCap); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 rlmFillHtCapIEByAdapter(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, UINT_8 *pOutBuf) +{ + P_IE_HT_CAP_T prHtCap; + P_SUP_MCS_SET_FIELD prSupMcsSet; + BOOLEAN fg40mAllowed; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(pOutBuf); + + fg40mAllowed = prBssInfo->fgAssoc40mBwAllowed; + + prHtCap = (P_IE_HT_CAP_T) pOutBuf; + + /* Add HT capabilities IE */ + prHtCap->ucId = ELEM_ID_HT_CAP; + prHtCap->ucLength = sizeof(IE_HT_CAP_T) - ELEM_HDR_LEN; + + prHtCap->u2HtCapInfo = HT_CAP_INFO_DEFAULT_VAL; + if (!fg40mAllowed) { + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | + HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_DSSS_CCK_IN_40M); + } + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxShortGI)) + prHtCap->u2HtCapInfo |= (HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxLdpc)) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_LDPC_CAP; + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxStbc)) + prHtCap->u2HtCapInfo |= HT_CAP_INFO_RX_STBC_1_SS; + + prHtCap->ucAmpduParam = AMPDU_PARAM_DEFAULT_VAL; + + prSupMcsSet = &prHtCap->rSupMcsSet; + kalMemZero((PVOID)&prSupMcsSet->aucRxMcsBitmask[0], SUP_MCS_RX_BITMASK_OCTET_NUM); + + prSupMcsSet->aucRxMcsBitmask[0] = BITS(0, 7); + + if (fg40mAllowed && IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucMCS32)) + 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)); + + return IE_SIZE(prHtCap); + +} + +#endif + +#if CFG_SUPPORT_DFS +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the TPC Report frame. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID +tpcComposeReportFrame(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_TPC_REPORT_FRAME prTxFrame; + UINT_16 u2PayloadLen; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + prBssInfo = &prAdapter->rWifiVar.arBssInfoPool[prStaRec->ucBssIndex]; + ASSERT(prBssInfo); + + prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + prTxFrame = (P_ACTION_TPC_REPORT_FRAME) + ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + + COPY_MAC_ADDR(prTxFrame->aucDestAddr, prStaRec->aucMacAddr); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); + + prTxFrame->ucCategory = CATEGORY_SPEC_MGT; + prTxFrame->ucAction = ACTION_TPC_REPORT; + + /* 3 Compose the frame body's frame. */ + prTxFrame->ucDialogToken = prStaRec->ucSmDialogToken; + prTxFrame->ucElemId = ELEM_ID_TPC_REPORT; + prTxFrame->ucLength = sizeof(prTxFrame->ucLinkMargin)+sizeof(prTxFrame->ucTransPwr); + prTxFrame->ucTransPwr = prAdapter->u4GetTxPower; + prTxFrame->ucLinkMargin = prAdapter->rLinkQuality.cRssi - (0 - MIN_RCV_PWR); + + u2PayloadLen = ACTION_SM_TPC_REPORT_LEN; + + /* 4 Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, pfTxDoneHandler, MSDU_RATE_MODE_AUTO); + + DBGLOG(RLM, TRACE, "ucDialogToken %d ucTransPwr %d ucLinkMargin %d\n", + prTxFrame->ucDialogToken, prTxFrame->ucTransPwr, prTxFrame->ucLinkMargin); + + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return; + +} /* end of tpcComposeReportFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the Measurement Report frame. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID +msmtComposeReportFrame(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_SM_REPORT_FRAME prTxFrame; + P_IE_MEASUREMENT_REPORT_T prMeasurementRepIE; + PUINT_8 pucIE; + UINT_16 u2PayloadLen; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + prBssInfo = &prAdapter->rWifiVar.arBssInfoPool[prStaRec->ucBssIndex]; + ASSERT(prBssInfo); + + prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + prTxFrame = (P_ACTION_SM_REPORT_FRAME) + ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + pucIE = prTxFrame->aucInfoElem; + prMeasurementRepIE = SM_MEASUREMENT_REP_IE(pucIE); + + 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_SPEC_MGT; + prTxFrame->ucAction = ACTION_MEASUREMENT_REPORT; + + /* 3 Compose the frame body's frame. */ + prTxFrame->ucDialogToken = prStaRec->ucSmDialogToken; + prMeasurementRepIE->ucId = ELEM_ID_MEASUREMENT_REPORT; + +#if 0 + if (prStaRec->ucSmMsmtRequestMode == ELEM_RM_TYPE_BASIC_REQ) { + prMeasurementRepIE->ucLength = sizeof(SM_BASIC_REPORT_T) + 3; + u2PayloadLen = ACTION_SM_MEASURE_REPORT_LEN+ACTION_SM_BASIC_REPORT_LEN; + } else if (prStaRec->ucSmMsmtRequestMode == ELEM_RM_TYPE_CCA_REQ) { + prMeasurementRepIE->ucLength = sizeof(SM_CCA_REPORT_T) + 3; + u2PayloadLen = ACTION_SM_MEASURE_REPORT_LEN+ACTION_SM_CCA_REPORT_LEN; + } else if (prStaRec->ucSmMsmtRequestMode == ELEM_RM_TYPE_RPI_HISTOGRAM_REQ) { + prMeasurementRepIE->ucLength = sizeof(SM_RPI_REPORT_T) + 3; + u2PayloadLen = ACTION_SM_MEASURE_REPORT_LEN+ACTION_SM_PRI_REPORT_LEN; + } else { + prMeasurementRepIE->ucLength = 3; + u2PayloadLen = ACTION_SM_MEASURE_REPORT_LEN; + } +#else + prMeasurementRepIE->ucLength = 3; + u2PayloadLen = ACTION_SM_MEASURE_REPORT_LEN; + prMeasurementRepIE->ucToken = prStaRec->ucSmMsmtToken; + prMeasurementRepIE->ucReportMode = BIT(1); + prMeasurementRepIE->ucMeasurementType = prStaRec->ucSmMsmtRequestMode; +#endif + + /* 4 Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, pfTxDoneHandler, MSDU_RATE_MODE_AUTO); + + DBGLOG(RLM, TRACE, "ucDialogToken %d ucToken %d ucReportMode %d ucMeasurementType %d\n", + prTxFrame->ucDialogToken, prMeasurementRepIE->ucToken, + prMeasurementRepIE->ucReportMode, prMeasurementRepIE->ucMeasurementType); + + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return; + +} /* end of msmtComposeReportFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function handle spectrum management action frame +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmProcessSpecMgtAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) +{ + PUINT_8 pucIE; + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prBssInfo; + UINT_16 u2IELength; + UINT_16 u2Offset = 0; + P_IE_CHANNEL_SWITCH_T prChannelSwitchAnnounceIE; + P_IE_SECONDARY_OFFSET_T prSecondaryOffsetIE; + P_IE_WIDE_BAND_CHANNEL_T prWideBandChannelIE; + P_IE_TPC_REQ_T prTpcReqIE; + P_IE_TPC_REPORT_T prTpcRepIE; + P_IE_MEASUREMENT_REQ_T prMeasurementReqIE; + P_IE_MEASUREMENT_REPORT_T prMeasurementRepIE; + P_ACTION_SM_REQ_FRAME prRxFrame; + BOOLEAN fgHasWideBandIE = FALSE; + BOOLEAN fgHasSCOIE = FALSE; + BOOLEAN fgHasChannelSwitchIE = FALSE; + BOOLEAN fgNeedSwitchChannel = FALSE; + + DBGLOG(RLM, INFO, "[Mgt Action]rlmProcessSpecMgtAction\n"); + ASSERT(prAdapter); + ASSERT(prSwRfb); + + u2IELength = prSwRfb->u2PacketLen - + (UINT_16) OFFSET_OF(ACTION_SM_REQ_FRAME, aucInfoElem[0]); + + prRxFrame = (P_ACTION_SM_REQ_FRAME) prSwRfb->pvHeader; + pucIE = prRxFrame->aucInfoElem; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (!prStaRec) + return; + + if (prStaRec->ucBssIndex > MAX_BSS_INDEX) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + prStaRec->ucSmDialogToken = prRxFrame->ucDialogToken; + + DBGLOG_MEM8(RLM, INFO, pucIE, u2IELength); + switch (prRxFrame->ucAction) { + case ACTION_MEASUREMENT_REQ: + DBGLOG(RLM, INFO, "[Mgt Action] Measure Request\n"); + prMeasurementReqIE = SM_MEASUREMENT_REQ_IE(pucIE); + if (prMeasurementReqIE->ucId == ELEM_ID_MEASUREMENT_REQ) { + prStaRec->ucSmMsmtRequestMode = prMeasurementReqIE->ucRequestMode; + prStaRec->ucSmMsmtToken = prMeasurementReqIE->ucToken; + msmtComposeReportFrame(prAdapter, prStaRec, NULL); + } + + break; + case ACTION_MEASUREMENT_REPORT: + DBGLOG(RLM, INFO, "[Mgt Action] Measure Report\n"); + prMeasurementRepIE = SM_MEASUREMENT_REP_IE(pucIE); + if (prMeasurementRepIE->ucId == ELEM_ID_MEASUREMENT_REPORT) + DBGLOG(RLM, TRACE, "[Mgt Action] Correct Measurement report IE !!\n"); + break; + case ACTION_TPC_REQ: + DBGLOG(RLM, INFO, "[Mgt Action] TPC Request\n"); + prTpcReqIE = SM_TPC_REQ_IE(pucIE); + + if (prTpcReqIE->ucId == ELEM_ID_TPC_REQ) + tpcComposeReportFrame(prAdapter, prStaRec, NULL); + + break; + case ACTION_TPC_REPORT: + DBGLOG(RLM, INFO, "[Mgt Action] TPC Report\n"); + prTpcRepIE = SM_TPC_REP_IE(pucIE); + + if (prTpcRepIE->ucId == ELEM_ID_TPC_REPORT) + DBGLOG(RLM, TRACE, "[Mgt Action] Correct TPC report IE !!\n"); + + break; + case ACTION_CHNL_SWITCH: + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + + case ELEM_ID_WIDE_BAND_CHANNEL_SWITCH: + if (!RLM_NET_IS_11AC(prBssInfo) || + IE_LEN(pucIE) != (sizeof(IE_WIDE_BAND_CHANNEL_T) - 2)) { + DBGLOG(RLM, INFO, "[Mgt Action] ELEM_ID_WIDE_BAND_CHANNEL_SWITCH, Length\n"); + break; + } + DBGLOG(RLM, INFO, "[Mgt Action] ELEM_ID_WIDE_BAND_CHANNEL_SWITCH, 11AC\n"); + prWideBandChannelIE = (P_IE_WIDE_BAND_CHANNEL_T) pucIE; + prBssInfo->ucVhtChannelWidth = prWideBandChannelIE->ucNewChannelWidth; + prBssInfo->ucVhtChannelFrequencyS1 = prWideBandChannelIE->ucChannelS1; + prBssInfo->ucVhtChannelFrequencyS2 = prWideBandChannelIE->ucChannelS2; + fgHasWideBandIE = TRUE; + break; + + case ELEM_ID_CH_SW_ANNOUNCEMENT: + if (IE_LEN(pucIE) != (sizeof(IE_CHANNEL_SWITCH_T) - 2)) { + DBGLOG(RLM, INFO, "[Mgt Action] ELEM_ID_CH_SW_ANNOUNCEMENT, Length\n"); + break; + } + + prChannelSwitchAnnounceIE = (P_IE_CHANNEL_SWITCH_T) pucIE; + + if (prChannelSwitchAnnounceIE->ucChannelSwitchMode == 1) { + /* Need to stop data transmission immediately */ + if (!g_fgHasStopTx) { + g_fgHasStopTx = TRUE; +#if CFG_SUPPORT_TDLS + /* TDLS peers */ + TdlsTxCtrl(prAdapter, prBssInfo, FALSE); +#endif + /* AP */ + qmSetStaRecTxAllowed(prAdapter, prStaRec, FALSE); + DBGLOG(RLM, EVENT, "[Ch] TxAllowed = FALSE\n"); + } + + if (prChannelSwitchAnnounceIE->ucChannelSwitchCount <= 3) { + DBGLOG(RLM, INFO, + "[Mgt Action] switch channel [%d]->[%d]\n", + prBssInfo->ucPrimaryChannel, + prChannelSwitchAnnounceIE->ucNewChannelNum); + prBssInfo->ucPrimaryChannel = + prChannelSwitchAnnounceIE->ucNewChannelNum; + fgNeedSwitchChannel = TRUE; + } + } else { + DBGLOG(RLM, INFO, "[Mgt Action] ucChannelSwitchMode = 0\n"); + } + + fgHasChannelSwitchIE = TRUE; + break; + case ELEM_ID_SCO: + if (IE_LEN(pucIE) != (sizeof(IE_SECONDARY_OFFSET_T) - 2)) { + DBGLOG(RLM, INFO, "[Mgt Action] ELEM_ID_SCO, Length\n"); + break; + } + prSecondaryOffsetIE = (P_IE_SECONDARY_OFFSET_T) pucIE; + DBGLOG(RLM, INFO, + "[Mgt Action] SCO [%d]->[%d]\n", prBssInfo->eBssSCO, + prSecondaryOffsetIE->ucSecondaryOffset); + prBssInfo->eBssSCO = prSecondaryOffsetIE->ucSecondaryOffset; + fgHasSCOIE = TRUE; + break; + default: + break; + } /*end of switch IE_ID */ + } /*end of IE_FOR_EACH */ + if (fgHasChannelSwitchIE != FALSE) { + if (fgHasWideBandIE == FALSE) { + prBssInfo->ucVhtChannelWidth = 0; + prBssInfo->ucVhtChannelFrequencyS1 = prBssInfo->ucPrimaryChannel; + prBssInfo->ucVhtChannelFrequencyS2 = 0; + } + if (fgHasSCOIE == FALSE) + prBssInfo->eBssSCO = CHNL_EXT_SCN; + if (fgNeedSwitchChannel) + kalIndicateChannelSwitch( + prAdapter->prGlueInfo, + prBssInfo->eBssSCO, + prBssInfo->ucPrimaryChannel); + } + nicUpdateBss(prAdapter, prBssInfo->ucBssIndex); + break; + default: + break; + } +} + +#endif + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Send OpMode Norification frame (VHT action frame) +* +* \param[in] ucChannelWidth 0:20MHz, 1:40MHz, 2:80MHz, 3:160MHz or 80+80MHz +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmSendOpModeNotificationFrame(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, UINT_8 ucChannelWidth, UINT_8 ucNss) +{ + + P_MSDU_INFO_T prMsduInfo; + P_ACTION_OP_MODE_NOTIFICATION_FRAME prTxFrame; + P_BSS_INFO_T prBssInfo; + UINT_16 u2EstimatedFrameLen; + /* PFN_TX_DONE_HANDLER pfTxDoneHandler = (PFN_TX_DONE_HANDLER) NULL; */ + + /* Sanity Check */ + if (!prStaRec) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + if (!prBssInfo) + return; + + /* Calculate MSDU buffer length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + sizeof(ACTION_OP_MODE_NOTIFICATION_FRAME); + + /* Alloc MSDU_INFO */ + prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + + if (!prMsduInfo) + return; + + kalMemZero(prMsduInfo->prPacket, u2EstimatedFrameLen); + + prTxFrame = prMsduInfo->prPacket; + + /* Fill frame ctrl */ + 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); + + /* 3 Compose the frame body's frame */ + prTxFrame->ucCategory = CATEGORY_VHT_ACTION; + prTxFrame->ucAction = ACTION_OPERATING_MODE_NOTIFICATION; + + prTxFrame->ucOperatingMode |= (ucChannelWidth & VHT_OP_MODE_CHANNEL_WIDTH); + + if (ucNss == 0) + ucNss = 1; + prTxFrame->ucOperatingMode |= (((ucNss - 1) << 4) & VHT_OP_MODE_RX_NSS); + prTxFrame->ucOperatingMode &= ~VHT_OP_MODE_RX_NSS_TYPE; + + /* 4 Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prBssInfo->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, sizeof(ACTION_OP_MODE_NOTIFICATION_FRAME), NULL, MSDU_RATE_MODE_AUTO); + + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Send SM Power Save frame (HT action frame) +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmSendSmPowerSaveFrame(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, UINT_8 ucNss) +{ + P_MSDU_INFO_T prMsduInfo; + P_ACTION_SM_POWER_SAVE_FRAME prTxFrame; + P_BSS_INFO_T prBssInfo; + UINT_16 u2EstimatedFrameLen; + /* PFN_TX_DONE_HANDLER pfTxDoneHandler = (PFN_TX_DONE_HANDLER) NULL; */ + + /* Sanity Check */ + if (!prStaRec) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + if (!prBssInfo) + return; + + /* Calculate MSDU buffer length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + sizeof(ACTION_SM_POWER_SAVE_FRAME); + + /* Alloc MSDU_INFO */ + prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + + if (!prMsduInfo) + return; + + kalMemZero(prMsduInfo->prPacket, u2EstimatedFrameLen); + + prTxFrame = prMsduInfo->prPacket; + + /* Fill frame ctrl */ + 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); + + /* 3 Compose the frame body's frame */ + prTxFrame->ucCategory = CATEGORY_HT_ACTION; + prTxFrame->ucAction = ACTION_HT_SM_POWER_SAVE; + + if (ucNss == 1) + prTxFrame->ucSmPowerCtrl |= HT_SM_POWER_SAVE_CONTROL_ENABLED; + else if (ucNss == 2) + prTxFrame->ucSmPowerCtrl &= ~HT_SM_POWER_SAVE_CONTROL_ENABLED; + else { + DBGLOG(RLM, WARN, "Can't switch to Nss = %d since we don't support.\n", ucNss); + return; + } + + prTxFrame->ucSmPowerCtrl &= (~HT_SM_POWER_SAVE_CONTROL_SM_MODE); /* Static SM power save mode */ + + /* 4 Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prBssInfo->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, sizeof(ACTION_SM_POWER_SAVE_FRAME), NULL, MSDU_RATE_MODE_AUTO); + + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Send Notify Channel Width frame (HT action frame) +* +* \param[in] ucChannelWidth 0:20MHz, 1:Any channel width in the STA¡¦s Supported Channel Width Set subfield +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmSendNotifyChannelWidthFrame(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, UINT_8 ucChannelWidth) +{ + P_MSDU_INFO_T prMsduInfo; + P_ACTION_NOTIFY_CHANNEL_WIDTH_FRAME prTxFrame; + P_BSS_INFO_T prBssInfo; + UINT_16 u2EstimatedFrameLen; + /* PFN_TX_DONE_HANDLER pfTxDoneHandler = (PFN_TX_DONE_HANDLER) NULL; */ + + /* Sanity Check */ + if (!prStaRec) + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + if (!prBssInfo) + return; + + /* Calculate MSDU buffer length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + sizeof(ACTION_NOTIFY_CHANNEL_WIDTH_FRAME); + + /* Alloc MSDU_INFO */ + prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + + if (!prMsduInfo) + return; + + kalMemZero(prMsduInfo->prPacket, u2EstimatedFrameLen); + + prTxFrame = prMsduInfo->prPacket; + + /* Fill frame ctrl */ + 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); + + /* 3 Compose the frame body's frame */ + prTxFrame->ucCategory = CATEGORY_HT_ACTION; + prTxFrame->ucAction = ACTION_HT_NOTIFY_CHANNEL_WIDTH; + + prTxFrame->ucChannelWidth = ucChannelWidth; + + /* 4 Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prBssInfo->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, sizeof(ACTION_NOTIFY_CHANNEL_WIDTH_FRAME), NULL, MSDU_RATE_MODE_AUTO); + + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Change OpMode Nss/Channel Width +* +* \param[in] ucChannelWidth 0:20MHz, 1:40MHz, 2:80MHz, 3:160MHz 4:80+80MHz +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rlmChangeOperationMode(P_ADAPTER_T prAdapter, UINT_8 ucBssIndex, UINT_8 ucChannelWidth, UINT_8 ucNss) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + /*BOOLEAN fgIsSuccess = FALSE;*/ + BOOLEAN fgIsChangeVhtBw = TRUE, fgIsChangeHtBw = TRUE; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + /* No need to change BSS 4 rlm parameter */ + if (ucBssIndex >= HW_BSSID_NUM) + return FALSE; + + if (!prBssInfo) + return FALSE; + + DBGLOG(RLM, INFO, "Intend to change BSS[%d] OP Mode to BW[%d] Nss[%d]\n", ucBssIndex, ucChannelWidth, ucNss); + +#if CFG_SUPPORT_802_11AC + /* Check peer VHT/HT OP Channel Width */ + if (ucChannelWidth == prBssInfo->ucOpChangeChannelWidth) + fgIsChangeVhtBw = FALSE; + else if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + switch (ucChannelWidth) { + case MAX_BW_80_80_MHZ: + if (prBssInfo->ucVhtPeerChannelWidth != VHT_OP_CHANNEL_WIDTH_80P80) { + DBGLOG(RLM, INFO, + "Can't change to BW80_80 due to peer VHT OP BW is BW[%d]\n" + , prBssInfo->ucVhtPeerChannelWidth); + fgIsChangeVhtBw = FALSE; + } + break; + case MAX_BW_160MHZ: + if (prBssInfo->ucVhtPeerChannelWidth != VHT_OP_CHANNEL_WIDTH_160) { + DBGLOG(RLM, INFO, + "Can't change to BW160 due to peer VHT OP BW is BW[%d]\n", + prBssInfo->ucVhtPeerChannelWidth); + fgIsChangeVhtBw = FALSE; + } + break; + case MAX_BW_80MHZ: + if (prBssInfo->ucVhtPeerChannelWidth < VHT_OP_CHANNEL_WIDTH_80) { + DBGLOG(RLM, INFO, + "Can't change to BW80 due to peer VHT OP BW is BW[%d]\n", + prBssInfo->ucVhtPeerChannelWidth); + fgIsChangeVhtBw = FALSE; + } + break; + case MAX_BW_40MHZ: + if (!(prBssInfo->ucHtPeerOpInfo1 & HT_OP_INFO1_STA_CHNL_WIDTH) || + (!prBssInfo->fg40mBwAllowed)) { + DBGLOG(RLM, INFO, + "Can't change to BW40: PeerOpBw[%d] fg40mBwAllowed[%d]\n", + (UINT_8)(prBssInfo->ucHtPeerOpInfo1 & + HT_OP_INFO1_STA_CHNL_WIDTH), + prBssInfo->fg40mBwAllowed); + fgIsChangeVhtBw = FALSE; + } + break; + case MAX_BW_20MHZ: + break; + default: + DBGLOG(RLM, WARN, "BW[%d] is invalid for OpMode change\n", ucChannelWidth); + fgIsChangeVhtBw = FALSE; + } + } +#endif + + /* Check HT OP Channel Width */ + if (ucChannelWidth == prBssInfo->ucOpChangeChannelWidth) + fgIsChangeHtBw = FALSE; + else if (ucChannelWidth >= MAX_BW_80MHZ) { + DBGLOG(RLM, WARN, "BW[%d] is invalid for HT OpMode change\n", ucChannelWidth); + fgIsChangeHtBw = FALSE; + } else if (ucChannelWidth == MAX_BW_40MHZ) { + if (!(prBssInfo->ucHtPeerOpInfo1 & HT_OP_INFO1_STA_CHNL_WIDTH) || + (!prBssInfo->fg40mBwAllowed)) { + DBGLOG(RLM, INFO, + "Can't change to BW40: PeerOpBw[%d] fg40mBwAllowed[%d]\n", + (UINT_8)(prBssInfo->ucHtPeerOpInfo1 & + HT_OP_INFO1_STA_CHNL_WIDTH), + prBssInfo->fg40mBwAllowed); + fgIsChangeHtBw = FALSE; + } + } + + if (fgIsChangeHtBw) { + /* <4>Update HT Channel Width */ + if (ucChannelWidth == MAX_BW_20MHZ) { + prBssInfo->ucHtOpInfo1 &= ~HT_OP_INFO1_STA_CHNL_WIDTH; + prBssInfo->eBssSCO = CHNL_EXT_SCN; + } else if (ucChannelWidth == MAX_BW_40MHZ) { + prBssInfo->ucHtOpInfo1 |= HT_OP_INFO1_STA_CHNL_WIDTH; + if ((prBssInfo->ucHtPeerOpInfo1 & HT_OP_INFO1_SCO) != CHNL_EXT_RES) + prBssInfo->eBssSCO = + (ENUM_CHNL_EXT_T) (prBssInfo->ucHtPeerOpInfo1 & HT_OP_INFO1_SCO); + } else + fgIsChangeHtBw = FALSE; + } + +#if CFG_SUPPORT_802_11AC + if (fgIsChangeVhtBw) { + prBssInfo->ucOpChangeChannelWidth = ucChannelWidth; + prBssInfo->fgIsOpChangeChannelWidth = TRUE; + /* <3>Update VHT Channel Width*/ + rlmChangeVhtOpBwPara(prAdapter, ucBssIndex, prBssInfo->ucOpChangeChannelWidth); + + DBGLOG(RLM, INFO, "Update VHT Channel Width Info to w=%d s1=%d s2=%d\n", + prBssInfo->ucVhtChannelWidth, + prBssInfo->ucVhtChannelFrequencyS1, + prBssInfo->ucVhtChannelFrequencyS2); + } +#endif + if (fgIsChangeHtBw) { + prBssInfo->ucOpChangeChannelWidth = ucChannelWidth; + prBssInfo->fgIsOpChangeChannelWidth = TRUE; + + DBGLOG(RLM, INFO, "Update HT Channel Width Info to bw=%d s=%d\n", + (UINT_8)(prBssInfo->ucHtOpInfo1 & + HT_OP_INFO1_STA_CHNL_WIDTH) >> 2, + prBssInfo->eBssSCO); + } + + if ((prBssInfo->ucNss != ucNss) || fgIsChangeVhtBw || fgIsChangeHtBw) { + /* 1. Update BSS Info */ + prBssInfo->ucNss = ucNss; + rlmSyncOperationParams(prAdapter, prBssInfo); + + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { /* For infrastructure, GC */ + if (prBssInfo->prStaRecOfAP) { + prStaRec = prBssInfo->prStaRecOfAP; +#if CFG_SUPPORT_802_11AC + /* 2. Check if we can change OpMode and Send OPmode notification frame */ + if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_VHT) { /*Send VHT notification frame*/ + /* <1> Notify VHT Nss and Channel Width change*/ + rlmSendOpModeNotificationFrame(prAdapter, prStaRec, ucChannelWidth, + prBssInfo->ucNss); + DBGLOG(RLM, INFO, "Send VHT OPmode notification frame, BW=%d, Nss=%d\n" + , ucChannelWidth, prBssInfo->ucNss); + } else +#endif + if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_HT) { /*Send HT notification frame*/ + /* <1> Notify HT Nss change */ + rlmSendSmPowerSaveFrame(prAdapter, prStaRec, prBssInfo->ucNss); + DBGLOG(RLM, INFO, "Send HT SM Power Save frame, Nss=%d\n", + prBssInfo->ucNss); + } + + if (fgIsChangeHtBw) { + /* <3> Notify HT Channel Width change */ + rlmSendNotifyChannelWidthFrame(prAdapter, prStaRec, ucChannelWidth); + DBGLOG(RLM, INFO, "Send HT Notify Channel Width frame, BW=%d\n", + ucChannelWidth); + } + } else + DBGLOG(RLM, WARN, "Can't change OpMode at legacy mode\n"); + } else if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + P_LINK_T prClientList; + + /* 4. Update BCN/Probe Resp IE to notify peers the OP is be changed */ + DBGLOG(RLM, INFO, "Beacon content update with Bssidex(%d)\n", + prBssInfo->ucBssIndex); + + prClientList = &prBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH_ENTRY(prStaRec, prClientList, rLinkEntry, STA_RECORD_T) { +#if CFG_SUPPORT_802_11AC + /* 2. Check if we can change OpMode and Send OPmode notification frame */ + if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_VHT) { /*Send VHT notification frame*/ + /* <1> Notify VHT Nss and Channel Width change*/ + rlmSendOpModeNotificationFrame(prAdapter, prStaRec, ucChannelWidth, + prBssInfo->ucNss); + DBGLOG(RLM, INFO, "Send VHT OPmode notification frame, BW=%d, Nss=%d\n" + , ucChannelWidth, prBssInfo->ucNss); + } else +#endif + if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_BIT_HT) { /*Send HT notification frame*/ + /* <1> Notify HT Nss change */ + rlmSendSmPowerSaveFrame(prAdapter, prStaRec, prBssInfo->ucNss); + DBGLOG(RLM, INFO, "Send HT SM Power Save frame, Nss=%d\n", + prBssInfo->ucNss); + } + + if (fgIsChangeHtBw) { + /* <3> Notify HT Channel Width change */ + rlmSendNotifyChannelWidthFrame(prAdapter, prStaRec, ucChannelWidth); + DBGLOG(RLM, INFO, "Send HT Notify Channel Width frame, BW=%d\n", + ucChannelWidth); + } + } + + bssUpdateBeaconContent(prAdapter, prBssInfo->ucBssIndex); + } else + return FALSE; + } + return TRUE; +} + +#if CFG_SUPPORT_BFER +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmBfStaRecPfmuUpdate(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec) +{ + UINT_8 ucBFerMaxNr, ucBFeeMaxNr, ucMode; + P_BSS_INFO_T prBssInfo; + P_CMD_STAREC_BF prStaRecBF; + P_CMD_STAREC_UPDATE_T prStaRecUpdateInfo; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4SetBufferLen = sizeof(CMD_STAREC_BF); + + prBssInfo = prAdapter->aprBssInfo[prStaRec->ucBssIndex]; + + if (RLM_NET_IS_11AC(prBssInfo) && + IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaVhtBfer)) + ucMode = MODE_VHT; + else if (RLM_NET_IS_11N(prBssInfo) && + IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucStaHtBfer)) + ucMode = MODE_HT; + else + ucMode = MODE_LEGACY; + + prStaRecBF = + (P_CMD_STAREC_BF) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, u4SetBufferLen); + + if (!prStaRecBF) { + DBGLOG(RLM, ERROR, "STA Rec memory alloc fail\n"); + return; + } + + prStaRecUpdateInfo = + (P_CMD_STAREC_UPDATE_T) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, (CMD_STAREC_UPDATE_HDR_SIZE + u4SetBufferLen)); + + if (!prStaRecUpdateInfo) { + cnmMemFree(prAdapter, prStaRecBF); + DBGLOG(RLM, ERROR, "STA Rec Update Info memory alloc fail\n"); + return; + } + + switch (ucMode) { + case MODE_VHT: + prStaRec->rTxBfPfmuStaInfo.fgSU_MU = FALSE; + prStaRec->rTxBfPfmuStaInfo.fgETxBfCap = + rlmClientSupportsVhtETxBF(prStaRec); + + if (prStaRec->rTxBfPfmuStaInfo.fgETxBfCap) { + /* OFDM, NDPA/Report Poll/CTS2Self tx mode */ + prStaRec->rTxBfPfmuStaInfo.ucSoundingPhy = + TX_RATE_MODE_OFDM; + + /* 9: OFDM 24M */ + prStaRec->rTxBfPfmuStaInfo.ucNdpaRate = PHY_RATE_24M; + + /* VHT mode, NDP tx mode */ + prStaRec->rTxBfPfmuStaInfo.ucTxMode = TX_RATE_MODE_VHT; + + /* 0: MCS0 */ + prStaRec->rTxBfPfmuStaInfo.ucNdpRate = PHY_RATE_MCS0; + + + switch (prBssInfo->ucVhtChannelWidth) { + case VHT_OP_CHANNEL_WIDTH_80: + prStaRec->rTxBfPfmuStaInfo.ucCBW = + MAX_BW_80MHZ; + break; + + case VHT_OP_CHANNEL_WIDTH_20_40: + default: + prStaRec->rTxBfPfmuStaInfo.ucCBW = + MAX_BW_20MHZ; + if (prBssInfo->eBssSCO != CHNL_EXT_SCN) + prStaRec->rTxBfPfmuStaInfo.ucCBW = + MAX_BW_40MHZ; + break; + } + + ucBFerMaxNr = 1; /* 7668 is 2x2 */ + ucBFeeMaxNr = rlmClientSupportsVhtBfeeStsCap(prStaRec); + prStaRec->rTxBfPfmuStaInfo.ucNr = + (ucBFerMaxNr < ucBFeeMaxNr) ? + ucBFerMaxNr : ucBFeeMaxNr; + prStaRec->rTxBfPfmuStaInfo.ucNc = + ((prStaRec->u2VhtRxMcsMap & + VHT_CAP_INFO_MCS_2SS_MASK) + != BITS(2, 3)) ? 1 : 0; + } + break; + + case MODE_HT: + prStaRec->rTxBfPfmuStaInfo.fgSU_MU = FALSE; + prStaRec->rTxBfPfmuStaInfo.fgETxBfCap = + rlmClientSupportsHtETxBF(prStaRec); + + if (prStaRec->rTxBfPfmuStaInfo.fgETxBfCap) { + /* 0: HT MCS0 */ + prStaRec->rTxBfPfmuStaInfo.ucNdpaRate = PHY_RATE_MCS0; + + /* HT mode, NDPA/NDP tx mode */ + prStaRec->rTxBfPfmuStaInfo.ucTxMode = + TX_RATE_MODE_HTMIX; + + prStaRec->rTxBfPfmuStaInfo.ucCBW = MAX_BW_20MHZ; + if (prBssInfo->eBssSCO != CHNL_EXT_SCN) + prStaRec->rTxBfPfmuStaInfo.ucCBW = MAX_BW_40MHZ; + + ucBFerMaxNr = 1; /* 7668 is 2x2 */ + ucBFeeMaxNr = + (prStaRec->u4TxBeamformingCap & + TXBF_COMPRESSED_TX_ANTENNANUM_SUPPORTED) >> + TXBF_COMPRESSED_TX_ANTENNANUM_SUPPORTED_OFFSET; + prStaRec->rTxBfPfmuStaInfo.ucNr = + (ucBFerMaxNr < ucBFeeMaxNr) ? + ucBFerMaxNr : ucBFeeMaxNr; + prStaRec->rTxBfPfmuStaInfo.ucNc = + (prStaRec->aucRxMcsBitmask[1] > 0) ? 1 : 0; + prStaRec->rTxBfPfmuStaInfo.ucNdpRate = + prStaRec->rTxBfPfmuStaInfo.ucNr * 8; + } + break; + default: + break; + } + + DBGLOG(RLM, INFO, "ucMode=%d\n", ucMode); + DBGLOG(RLM, INFO, "rlmClientSupportsVhtETxBF(prStaRec)=%d\n", + rlmClientSupportsVhtETxBF(prStaRec)); + DBGLOG(RLM, INFO, "rlmClientSupportsVhtBfeeStsCap(prStaRec)=%d\n", + rlmClientSupportsVhtBfeeStsCap(prStaRec)); + DBGLOG(RLM, INFO, "prStaRec->u2VhtRxMcsMap=%x\n", + prStaRec->u2VhtRxMcsMap); + + DBGLOG(RLM, INFO, + "====================== BF StaRec Info =====================\n"); + DBGLOG(RLM, INFO, "u2PfmuId =%d\n", + prStaRec->rTxBfPfmuStaInfo.u2PfmuId); + DBGLOG(RLM, INFO, "fgSU_MU =%d\n", + prStaRec->rTxBfPfmuStaInfo.fgSU_MU); + DBGLOG(RLM, INFO, "fgETxBfCap =%d\n", + prStaRec->rTxBfPfmuStaInfo.fgETxBfCap); + DBGLOG(RLM, INFO, "ucSoundingPhy =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucSoundingPhy); + DBGLOG(RLM, INFO, "ucNdpaRate =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucNdpaRate); + DBGLOG(RLM, INFO, "ucNdpRate =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucNdpRate); + DBGLOG(RLM, INFO, "ucReptPollRate =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucReptPollRate); + DBGLOG(RLM, INFO, "ucTxMode =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucTxMode); + DBGLOG(RLM, INFO, "ucNc =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucNc); + DBGLOG(RLM, INFO, "ucNr =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucNr); + DBGLOG(RLM, INFO, "ucCBW =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucCBW); + DBGLOG(RLM, INFO, "ucTotMemRequire=%d\n", + prStaRec->rTxBfPfmuStaInfo.ucTotMemRequire); + DBGLOG(RLM, INFO, "ucMemRequire20M=%d\n", + prStaRec->rTxBfPfmuStaInfo.ucMemRequire20M); + DBGLOG(RLM, INFO, "ucMemRow0 =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucMemRow0); + DBGLOG(RLM, INFO, "ucMemCol0 =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucMemCol0); + DBGLOG(RLM, INFO, "ucMemRow1 =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucMemRow1); + DBGLOG(RLM, INFO, "ucMemCol1 =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucMemCol1); + DBGLOG(RLM, INFO, "ucMemRow2 =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucMemRow2); + DBGLOG(RLM, INFO, "ucMemCol2 =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucMemCol2); + DBGLOG(RLM, INFO, "ucMemRow3 =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucMemRow3); + DBGLOG(RLM, INFO, "ucMemCol3 =%d\n", + prStaRec->rTxBfPfmuStaInfo.ucMemCol3); + DBGLOG(RLM, INFO, + "===========================================================\n"); + + + + prStaRecBF->u2Tag = STA_REC_BF; + prStaRecBF->u2Length = u4SetBufferLen; + kalMemCopy(&prStaRecBF->rTxBfPfmuInfo, + &prStaRec->rTxBfPfmuStaInfo, sizeof(TXBF_PFMU_STA_INFO)); + + + prStaRecUpdateInfo->ucBssIndex = prStaRec->ucBssIndex; + prStaRecUpdateInfo->ucWlanIdx = prStaRec->ucWlanIndex; + prStaRecUpdateInfo->u2TotalElementNum = 1; + kalMemCopy(prStaRecUpdateInfo->aucBuffer, prStaRecBF, u4SetBufferLen); + + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_STAREC_UPDATE, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + (CMD_STAREC_UPDATE_HDR_SIZE + u4SetBufferLen), + (PUINT_8) prStaRecUpdateInfo, NULL, 0); + + if (rWlanStatus == WLAN_STATUS_FAILURE) + DBGLOG(RLM, ERROR, "Send starec update cmd fail\n"); + + cnmMemFree(prAdapter, prStaRecBF); + cnmMemFree(prAdapter, prStaRecUpdateInfo); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmETxBfTriggerPeriodicSounding(P_ADAPTER_T prAdapter) +{ + UINT_32 u4SetBufferLen = sizeof(PARAM_CUSTOM_TXBF_ACTION_STRUCT_T); + PARAM_CUSTOM_TXBF_ACTION_STRUCT_T rTxBfActionInfo; + CMD_TXBF_ACTION_T rCmdTxBfActionInfo; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DBGLOG(RLM, INFO, "rlmETxBfTriggerPeriodicSounding\n"); + + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding. + rExtCmdExtBfSndPeriodicTriggerCtrl.ucCmdCategoryID = + BF_SOUNDING_ON; + + rTxBfActionInfo.rTxBfSoundingStart.rTxBfSounding. + rExtCmdExtBfSndPeriodicTriggerCtrl.ucSuMuSndMode = + AUTO_SU_PERIODIC_SOUNDING; + + kalMemCopy(&rCmdTxBfActionInfo, &rTxBfActionInfo, + sizeof(CMD_TXBF_ACTION_T)); + + rWlanStatus = wlanSendSetQueryExtCmd(prAdapter, + CMD_ID_LAYER_0_EXT_MAGIC_NUM, + EXT_CMD_ID_BF_ACTION, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_TXBF_ACTION_T), + (PUINT_8) & rCmdTxBfActionInfo, + &rTxBfActionInfo, u4SetBufferLen); + + if (rWlanStatus == WLAN_STATUS_FAILURE) + DBGLOG(RLM, ERROR, "Send BF sounding cmd fail\n"); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rlmClientSupportsVhtETxBF(P_STA_RECORD_T prStaRec) +{ + UINT_8 ucVhtCapSuBfeeCap; + + ucVhtCapSuBfeeCap = + (prStaRec->u4VhtCapInfo & VHT_CAP_INFO_SU_BEAMFORMEE_CAPABLE) + >> VHT_CAP_INFO_SU_BEAMFORMEE_CAPABLE_OFFSET; + + return (ucVhtCapSuBfeeCap) ? TRUE : FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 +rlmClientSupportsVhtBfeeStsCap(P_STA_RECORD_T prStaRec) +{ + UINT_8 ucVhtCapBfeeStsCap; + + ucVhtCapBfeeStsCap = + (prStaRec->u4VhtCapInfo & + VHT_CAP_INFO_COMP_STEERING_NUM_OF_BFER_ANT_SUP) >> + VHT_CAP_INFO_COMP_STEERING_NUM_OF_BFER_ANT_SUP_OFFSET; + + return ucVhtCapBfeeStsCap; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rlmClientSupportsHtETxBF(P_STA_RECORD_T prStaRec) +{ + UINT_32 u4RxNDPCap, u4ComBfFbkCap; + + u4RxNDPCap = (prStaRec->u4TxBeamformingCap & TXBF_RX_NDP_CAPABLE) + >> TXBF_RX_NDP_CAPABLE_OFFSET; + /* Support compress feedback */ + u4ComBfFbkCap = (prStaRec->u4TxBeamformingCap & + TXBF_EXPLICIT_COMPRESSED_FEEDBACK_IMMEDIATE_CAPABLE) + >> TXBF_EXPLICIT_COMPRESSED_FEEDBACK_CAPABLE_OFFSET; + + return (u4RxNDPCap == 1) && (u4ComBfFbkCap > 0); +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/rlm_domain.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/rlm_domain.c new file mode 100644 index 0000000000000..f6beca476a4dc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/rlm_domain.c @@ -0,0 +1,3247 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rlm_domain.c#2 +*/ + +/*! \file "rlm_domain.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" + +#include "rlm_txpwr_init.h" + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/* The following country or domain shall be set from host driver. + * And host driver should pass specified DOMAIN_INFO_ENTRY to MT6620 as + * the channel list of being a STA to do scanning/searching AP or being an + * AP to choose an adequate channel if auto-channel is set. + */ + +/* Define mapping tables between country code and its channel set + */ +static const UINT_16 g_u2CountryGroup0[] = { + COUNTRY_CODE_AO, COUNTRY_CODE_BZ, COUNTRY_CODE_BJ, COUNTRY_CODE_BT, + COUNTRY_CODE_BO, COUNTRY_CODE_BI, COUNTRY_CODE_CM, COUNTRY_CODE_CF, + COUNTRY_CODE_TD, COUNTRY_CODE_KM, COUNTRY_CODE_CD, COUNTRY_CODE_CG, + COUNTRY_CODE_CI, COUNTRY_CODE_DJ, COUNTRY_CODE_GQ, COUNTRY_CODE_ER, + COUNTRY_CODE_FJ, COUNTRY_CODE_GA, COUNTRY_CODE_GM, COUNTRY_CODE_GN, + COUNTRY_CODE_GW, COUNTRY_CODE_RKS, COUNTRY_CODE_KG, COUNTRY_CODE_LY, + COUNTRY_CODE_MG, COUNTRY_CODE_ML, COUNTRY_CODE_NR, COUNTRY_CODE_NC, + COUNTRY_CODE_ST, COUNTRY_CODE_SC, COUNTRY_CODE_SL, COUNTRY_CODE_SB, + COUNTRY_CODE_SO, COUNTRY_CODE_SR, COUNTRY_CODE_SZ, COUNTRY_CODE_TJ, + COUNTRY_CODE_TG, COUNTRY_CODE_TO, COUNTRY_CODE_TM, COUNTRY_CODE_TV, + COUNTRY_CODE_VU, COUNTRY_CODE_YE +}; + +static const UINT_16 g_u2CountryGroup1[] = { + COUNTRY_CODE_AS, COUNTRY_CODE_AI, COUNTRY_CODE_BM, COUNTRY_CODE_CA, + COUNTRY_CODE_KY, COUNTRY_CODE_GU, COUNTRY_CODE_FM, COUNTRY_CODE_PR, + COUNTRY_CODE_US, COUNTRY_CODE_VI, + +}; + +static const UINT_16 g_u2CountryGroup2[] = { + COUNTRY_CODE_AR, COUNTRY_CODE_AU, COUNTRY_CODE_AZ, COUNTRY_CODE_BW, + COUNTRY_CODE_KH, COUNTRY_CODE_CX, COUNTRY_CODE_CO, COUNTRY_CODE_CR, + COUNTRY_CODE_EC, COUNTRY_CODE_GD, COUNTRY_CODE_GT, COUNTRY_CODE_HK, + COUNTRY_CODE_KI, COUNTRY_CODE_LB, COUNTRY_CODE_LR, COUNTRY_CODE_MN, + COUNTRY_CODE_AN, COUNTRY_CODE_NZ, COUNTRY_CODE_NI, COUNTRY_CODE_PW, + COUNTRY_CODE_PY, COUNTRY_CODE_PE, COUNTRY_CODE_PH, COUNTRY_CODE_WS, + COUNTRY_CODE_SG, COUNTRY_CODE_LK, COUNTRY_CODE_TH, COUNTRY_CODE_TT, + COUNTRY_CODE_UY, COUNTRY_CODE_VN +}; + +static const UINT_16 g_u2CountryGroup3[] = { + COUNTRY_CODE_AW, COUNTRY_CODE_LA, COUNTRY_CODE_SA, COUNTRY_CODE_AE, + COUNTRY_CODE_UG +}; + +static const UINT_16 g_u2CountryGroup4[] = { COUNTRY_CODE_MM }; + +static const UINT_16 g_u2CountryGroup5[] = { + COUNTRY_CODE_AL, COUNTRY_CODE_DZ, COUNTRY_CODE_AD, COUNTRY_CODE_AT, + COUNTRY_CODE_BY, COUNTRY_CODE_BE, COUNTRY_CODE_BA, COUNTRY_CODE_VG, + COUNTRY_CODE_BG, COUNTRY_CODE_CV, COUNTRY_CODE_HR, COUNTRY_CODE_CY, + COUNTRY_CODE_CZ, COUNTRY_CODE_DK, COUNTRY_CODE_EE, COUNTRY_CODE_ET, + COUNTRY_CODE_FI, COUNTRY_CODE_FR, COUNTRY_CODE_GF, COUNTRY_CODE_PF, + COUNTRY_CODE_TF, COUNTRY_CODE_GE, COUNTRY_CODE_DE, COUNTRY_CODE_GH, + COUNTRY_CODE_GR, COUNTRY_CODE_GP, COUNTRY_CODE_HU, COUNTRY_CODE_IS, + COUNTRY_CODE_IQ, COUNTRY_CODE_IE, COUNTRY_CODE_IT, COUNTRY_CODE_KE, + COUNTRY_CODE_LV, COUNTRY_CODE_LS, COUNTRY_CODE_LI, COUNTRY_CODE_LT, + COUNTRY_CODE_LU, COUNTRY_CODE_MK, COUNTRY_CODE_MT, COUNTRY_CODE_MQ, + COUNTRY_CODE_MR, COUNTRY_CODE_MU, COUNTRY_CODE_YT, COUNTRY_CODE_MD, + COUNTRY_CODE_MC, COUNTRY_CODE_ME, COUNTRY_CODE_MS, COUNTRY_CODE_NL, + COUNTRY_CODE_NO, COUNTRY_CODE_OM, COUNTRY_CODE_PL, COUNTRY_CODE_PT, + COUNTRY_CODE_RE, COUNTRY_CODE_RO, COUNTRY_CODE_MF, COUNTRY_CODE_SM, + COUNTRY_CODE_SN, COUNTRY_CODE_RS, COUNTRY_CODE_SK, COUNTRY_CODE_SI, + COUNTRY_CODE_ZA, COUNTRY_CODE_ES, COUNTRY_CODE_SE, COUNTRY_CODE_CH, + COUNTRY_CODE_TR, COUNTRY_CODE_TC, COUNTRY_CODE_GB, COUNTRY_CODE_VA, + COUNTRY_CODE_EU +}; +static const UINT_16 g_u2CountryGroup6[] = { COUNTRY_CODE_JP }; + +static const UINT_16 g_u2CountryGroup7[] = { + COUNTRY_CODE_AM, COUNTRY_CODE_IL, COUNTRY_CODE_KW, COUNTRY_CODE_MA, + COUNTRY_CODE_NE, COUNTRY_CODE_TN, +}; +static const UINT_16 g_u2CountryGroup8[] = { COUNTRY_CODE_NP }; +static const UINT_16 g_u2CountryGroup9[] = { COUNTRY_CODE_AF }; + +static const UINT_16 g_u2CountryGroup10[] = { + COUNTRY_CODE_AG, COUNTRY_CODE_BS, COUNTRY_CODE_BH, COUNTRY_CODE_BB, + COUNTRY_CODE_BN, COUNTRY_CODE_CL, COUNTRY_CODE_CN, COUNTRY_CODE_EG, + COUNTRY_CODE_SV, COUNTRY_CODE_IN, COUNTRY_CODE_MY, COUNTRY_CODE_MV, + COUNTRY_CODE_PA, COUNTRY_CODE_VE, COUNTRY_CODE_ZM, + +}; +static const UINT_16 g_u2CountryGroup11[] = { COUNTRY_CODE_JO, COUNTRY_CODE_PG }; + +static const UINT_16 g_u2CountryGroup12[] = { + COUNTRY_CODE_BF, COUNTRY_CODE_GY, COUNTRY_CODE_HT, COUNTRY_CODE_HN, + COUNTRY_CODE_JM, COUNTRY_CODE_MO, COUNTRY_CODE_MW, COUNTRY_CODE_PK, + COUNTRY_CODE_QA, COUNTRY_CODE_RW, COUNTRY_CODE_KN, COUNTRY_CODE_TZ, + +}; +static const UINT_16 g_u2CountryGroup13[] = { COUNTRY_CODE_ID }; +static const UINT_16 g_u2CountryGroup14[] = { COUNTRY_CODE_KR }; +static const UINT_16 g_u2CountryGroup15[] = { COUNTRY_CODE_NG }; + +static const UINT_16 g_u2CountryGroup16[] = { + COUNTRY_CODE_BD, COUNTRY_CODE_BR, COUNTRY_CODE_DM, COUNTRY_CODE_DO, + COUNTRY_CODE_FK, COUNTRY_CODE_KZ, COUNTRY_CODE_MX, COUNTRY_CODE_MZ, + COUNTRY_CODE_NA, COUNTRY_CODE_RU, COUNTRY_CODE_LC, COUNTRY_CODE_VC, + COUNTRY_CODE_UA, COUNTRY_CODE_UZ, COUNTRY_CODE_ZW +}; +static const UINT_16 g_u2CountryGroup17[] = { COUNTRY_CODE_MP }; +static const UINT_16 g_u2CountryGroup18[] = { COUNTRY_CODE_TW }; + +static const UINT_16 g_u2CountryGroup19[] = { + COUNTRY_CODE_CK, COUNTRY_CODE_CU, COUNTRY_CODE_TL, COUNTRY_CODE_FO, + COUNTRY_CODE_GI, COUNTRY_CODE_GG, COUNTRY_CODE_IR, COUNTRY_CODE_IM, + COUNTRY_CODE_JE, COUNTRY_CODE_KP, COUNTRY_CODE_MH, COUNTRY_CODE_NU, + COUNTRY_CODE_NF, COUNTRY_CODE_PS, COUNTRY_CODE_PN, COUNTRY_CODE_PM, + COUNTRY_CODE_SS, COUNTRY_CODE_SD, COUNTRY_CODE_SY +}; + +static const UINT_16 g_u2CountryGroup20[] = { + COUNTRY_CODE_DF + /* When country code is not found, this domain info will be used. + * So mark all country codes to reduce search time. 20110908 + */ +}; + +#if (CFG_SUPPORT_SINGLE_SKU == 1) +mtk_regd_control g_mtk_regd_control = { + .en = FALSE, + .state = REGD_STATE_UNDEFINED +}; + +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) +const struct ieee80211_regdomain default_regdom_ww = { + .n_reg_rules = 4, + .alpha2 = "99", + .reg_rules = { + /* channels 1..13 */ + REG_RULE_LIGHT(2412-10, 2472+10, 40, 0), + /* channels 14 */ + REG_RULE_LIGHT(2484-10, 2484+10, 20, 0), + /* channel 36..64 */ + REG_RULE_LIGHT(5150-10, 5350+10, 80, 0), + /* channel 100..165 */ + REG_RULE_LIGHT(5470-10, 5850+10, 80, 0), + } +}; +#endif + +const char *gTx_Pwr_Limit_Section[TX_PWR_LIMIT_SECTION_NUM] = { + "legacy", "ht20", "ht40", "vht20", "offset" +}; + +const u8 gTx_Pwr_Limit_Element_Num[TX_PWR_LIMIT_SECTION_NUM] = { + 7, 6, 7, 7, 5 +}; + +const char *gTx_Pwr_Limit_Element[TX_PWR_LIMIT_SECTION_NUM][TX_PWR_LIMIT_ELEMENT_NUM] = { + {"cck1_2", "cck_5_11", "ofdm6_9", "ofdm12_18", "ofdm24_36", "ofdm48", "ofdm54"}, + {"mcs0_8", "mcs1_2_9_10", "mcs3_4_11_12", "mcs5_13", "mcs6_14", "mcs7_15"}, + {"mcs0_8", "mcs1_2_9_10", "mcs3_4_11_12", "mcs5_13", "mcs6_14", "mcs7_15", "mcs32"}, + {"mcs0", "mcs1_2", "mcs3_4", "mcs5_6", "mcs7", "mcs8", "mcs9"}, + {"lg40", "lg80", "vht40", "vht80", "vht160nc"} +}; + +static const INT_8 gTx_Pwr_Limit_2g_Ch[] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; +static const INT_8 gTx_Pwr_Limit_5g_Ch[] = { + 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 100, 102, + 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 132, + 134, 136, 138, 140, 142, 144, 149, 151, 153, 155, 157, 159, 161, 165}; + +#define TX_PWR_LIMIT_2G_CH_NUM (ARRAY_SIZE(gTx_Pwr_Limit_2g_Ch)) +#define TX_PWR_LIMIT_5G_CH_NUM (ARRAY_SIZE(gTx_Pwr_Limit_5g_Ch)) + + +#endif + +DOMAIN_INFO_ENTRY arSupportedRegDomains[] = { + { + (PUINT_16) g_u2CountryGroup0, sizeof(g_u2CountryGroup0) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_LOW_NA */ + {118, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_MID_NA */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup1, sizeof(g_u2CountryGroup1) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 11, FALSE} + , /* CH_SET_2G4_1_11 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup2, sizeof(g_u2CountryGroup2) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup3, sizeof(g_u2CountryGroup3) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE} + , /* CH_SET_UNII_UPPER_149_161 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup4, sizeof(g_u2CountryGroup4) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup5, sizeof(g_u2CountryGroup5) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup6, sizeof(g_u2CountryGroup6) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + {82, BAND_2G4, CHNL_SPAN_5, 14, 1, FALSE} + , /* CH_SET_2G4_14_14 */ + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + } + } + , + { + (PUINT_16) g_u2CountryGroup7, sizeof(g_u2CountryGroup7) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup8, sizeof(g_u2CountryGroup8) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE} + , /* CH_SET_UNII_UPPER_149_161 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup9, sizeof(g_u2CountryGroup9) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_MID_NA */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup10, sizeof(g_u2CountryGroup10) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup11, sizeof(g_u2CountryGroup11) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_MID_NA */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup12, sizeof(g_u2CountryGroup12) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_LOW_NA */ + {118, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_MID_NA */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup13, sizeof(g_u2CountryGroup13) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_LOW_NA */ + {118, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_MID_NA */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE} + , /* CH_SET_UNII_UPPER_149_161 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup14, sizeof(g_u2CountryGroup14) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, FALSE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 8, FALSE} + , /* CH_SET_UNII_WW_100_128 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE} + , /* CH_SET_UNII_UPPER_149_161 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup15, sizeof(g_u2CountryGroup15) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup16, sizeof(g_u2CountryGroup16) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, FALSE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup17, sizeof(g_u2CountryGroup17) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 11, FALSE} + , /* CH_SET_2G4_1_11 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup18, sizeof(g_u2CountryGroup18) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 11, FALSE} + , /* CH_SET_2G4_1_11 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, FALSE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, FALSE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup19, sizeof(g_u2CountryGroup19) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + /* Note: The final one is for Europe union now.(Default group if no matched country code) */ + (PUINT_16) g_u2CountryGroup20, sizeof(g_u2CountryGroup20) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 7, FALSE} + , /* CH_SET_UNII_UPPER_149_173 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } +}; + +#define REG_DOMAIN_PASSIVE_DEF_IDX 1 + +static const UINT_16 g_u2CountryGroup0_Passive[] = { + COUNTRY_CODE_TW +}; + +DOMAIN_INFO_ENTRY arSupportedRegDomains_Passive[] = { + { + (PUINT_16) g_u2CountryGroup0_Passive, sizeof(g_u2CountryGroup0_Passive) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 0, 0} + , /* CH_SET_2G4_1_14_NA */ + {82, BAND_2G4, CHNL_SPAN_5, 14, 0, 0} + , + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, 0} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, 0} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, 0} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 0, 0} + , /* CH_SET_UNII_UPPER_NA */ + } + } + , + + { + /* default passive channel table is empty */ + NULL, 0, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 0, 0} + , /* CH_SET_2G4_1_14_NA */ + {82, BAND_2G4, CHNL_SPAN_5, 14, 0, 0} + , + + {115, BAND_5G, CHNL_SPAN_20, 36, 0, 0} + , /* CH_SET_UNII_LOW_NA */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, 0} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, 0} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 0, 0} + , /* CH_SET_UNII_UPPER_NA */ + } + } + +}; + +#define REG_DOMAIN_PASSIVE_GROUP_NUM \ + (sizeof(arSupportedRegDomains_Passive) / sizeof(DOMAIN_INFO_ENTRY)) + + +SUBBAND_CHANNEL_T g_rRlmSubBand[] = { + + {BAND_2G4_LOWER_BOUND, BAND_2G4_UPPER_BOUND, 1, 0} + , /* 2.4G */ + {UNII1_LOWER_BOUND, UNII1_UPPER_BOUND, 2, 0} + , /* ch36,38,40,..,48 */ + {UNII2A_LOWER_BOUND, UNII2A_UPPER_BOUND, 2, 0} + , /* ch52,54,56,..,64 */ + {UNII2C_LOWER_BOUND, UNII2C_UPPER_BOUND, 2, 0} + , /* ch100,102,104,...,144 */ + {UNII3_LOWER_BOUND, UNII3_UPPER_BOUND, 2, 0} /* ch149,151,153,....,173 */ + +}; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in/out] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +P_DOMAIN_INFO_ENTRY rlmDomainGetDomainInfo(P_ADAPTER_T prAdapter) +{ +#define REG_DOMAIN_DEF_IDX 20 /* EU (Europe Union) */ +#define REG_DOMAIN_GROUP_NUM \ + (sizeof(arSupportedRegDomains) / sizeof(DOMAIN_INFO_ENTRY)) + + P_DOMAIN_INFO_ENTRY prDomainInfo; + P_REG_INFO_T prRegInfo; + UINT_16 u2TargetCountryCode; + UINT_16 i, j; + + ASSERT(prAdapter); + + if (prAdapter->prDomainInfo) + return prAdapter->prDomainInfo; + + prRegInfo = &prAdapter->prGlueInfo->rRegInfo; + + DBGLOG(RLM, TRACE, "eRegChannelListMap=%d, u2CountryCode=0x%04x\n", + prRegInfo->eRegChannelListMap, + prAdapter->rWifiVar.rConnSettings.u2CountryCode); + + /* + * Domain info can be specified by given idx of arSupportedRegDomains table, + * customized, or searched by country code, + * only one is set among these three methods in NVRAM. + */ + if (prRegInfo->eRegChannelListMap == REG_CH_MAP_TBL_IDX && + prRegInfo->ucRegChannelListIndex < REG_DOMAIN_GROUP_NUM) { + /* by given table idx */ + DBGLOG(RLM, TRACE, "ucRegChannelListIndex=%d\n", prRegInfo->ucRegChannelListIndex); + prDomainInfo = &arSupportedRegDomains[prRegInfo->ucRegChannelListIndex]; + } else if (prRegInfo->eRegChannelListMap == REG_CH_MAP_CUSTOMIZED) { + /* by customized */ + prDomainInfo = &prRegInfo->rDomainInfo; + } else { + /* by country code */ + u2TargetCountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode; + + for (i = 0; i < REG_DOMAIN_GROUP_NUM; i++) { + prDomainInfo = &arSupportedRegDomains[i]; + + if ((prDomainInfo->u4CountryNum && prDomainInfo->pu2CountryGroup) || + prDomainInfo->u4CountryNum == 0) { + for (j = 0; j < prDomainInfo->u4CountryNum; j++) { + if (prDomainInfo->pu2CountryGroup[j] == u2TargetCountryCode) + break; + } + if (j < prDomainInfo->u4CountryNum) + break; /* Found */ + } + } + + /* If no matched country code, use the default regulatory domain */ + if (i >= REG_DOMAIN_GROUP_NUM) { + DBGLOG(RLM, INFO, "No matched country code, use the default regulatory domain\n"); + prDomainInfo = &arSupportedRegDomains[REG_DOMAIN_DEF_IDX]; + } + } + + prAdapter->prDomainInfo = prDomainInfo; + return prDomainInfo; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in/out] The input variable pointed by pucNumOfChannel is the max +* arrary size. The return value indciates meaning list size. +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmDomainGetChnlList_V2(P_ADAPTER_T prAdapter, + ENUM_BAND_T eSpecificBand, BOOLEAN fgNoDfs, + UINT_8 ucMaxChannelNum, PUINT_8 pucNumOfChannel, P_RF_CHANNEL_INFO_T paucChannelList) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + ENUM_BAND_T band; + UINT_8 max_count, i, ucNum; + struct channel *prCh; + + if (eSpecificBand == BAND_2G4) { + i = 0; + max_count = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + } else if (eSpecificBand == BAND_5G) { + i = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + max_count = rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ) + + rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + } else { + i = 0; + max_count = rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ) + + rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + } + + ucNum = 0; + for (; i < max_count; i++) { + prCh = rlmDomainGetActiveChannels() + i; + if (fgNoDfs && (prCh->flags & IEEE80211_CHAN_RADAR)) + continue; /*not match*/ + + if (i < rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ)) + band = BAND_2G4; + else + band = BAND_5G; + + paucChannelList[ucNum].eBand = band; + paucChannelList[ucNum].ucChannelNum = prCh->chNum; + + ucNum++; + if (ucMaxChannelNum == ucNum) + break; + } + + *pucNumOfChannel = ucNum; +#else + *pucNumOfChannel = 0; +#endif +} + + +VOID +rlmDomainGetChnlList(P_ADAPTER_T prAdapter, + ENUM_BAND_T eSpecificBand, BOOLEAN fgNoDfs, + UINT_8 ucMaxChannelNum, PUINT_8 pucNumOfChannel, P_RF_CHANNEL_INFO_T paucChannelList) +{ + UINT_8 i, j, ucNum; + P_DOMAIN_SUBBAND_INFO prSubband; + P_DOMAIN_INFO_ENTRY prDomainInfo; + + ASSERT(prAdapter); + ASSERT(paucChannelList); + ASSERT(pucNumOfChannel); + + if (regd_is_single_sku_en()) + return rlmDomainGetChnlList_V2(prAdapter, eSpecificBand, + fgNoDfs, ucMaxChannelNum, + pucNumOfChannel, paucChannelList); + + /* 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; + + /*repoert to upper layer only non-DFS channel for ap mode usage*/ + if (fgNoDfs == TRUE && prSubband->fgDfs == TRUE) + continue; + + if (eSpecificBand == BAND_NULL || prSubband->ucBand == eSpecificBand) { + for (j = 0; j < prSubband->ucNumChannels; j++) { + if (ucNum >= ucMaxChannelNum) + break; + paucChannelList[ucNum].eBand = prSubband->ucBand; + paucChannelList[ucNum].ucChannelNum = + prSubband->ucFirstChannelNum + j * prSubband->ucChannelSpan; + ucNum++; + } + } + } + + *pucNumOfChannel = ucNum; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmDomainSendCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid) +{ + if (!regd_is_single_sku_en()) + rlmDomainSendPassiveScanInfoCmd(prAdapter, fgIsOid); + rlmDomainSendDomainInfoCmd(prAdapter, fgIsOid); +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + rlmDomainSendPwrLimitCmd(prAdapter); +#endif + + +} + + +VOID rlmDomainSendDomainInfoCmd_V2(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + u8 max_channel_count = 0; + u32 buff_max_size, buff_valid_size; + P_CMD_SET_DOMAIN_INFO_V2_T prCmd; + struct acctive_channel_list *prChs; + struct wiphy *pWiphy; + + + pWiphy = priv_to_wiphy(prAdapter->prGlueInfo); + if (pWiphy->bands[KAL_BAND_2GHZ] != NULL) + max_channel_count += pWiphy->bands[KAL_BAND_2GHZ]->n_channels; + if (pWiphy->bands[KAL_BAND_5GHZ] != NULL) + max_channel_count += pWiphy->bands[KAL_BAND_5GHZ]->n_channels; + + if (max_channel_count == 0) { + DBGLOG(RLM, ERROR, "%s, invalid channel count.\n", __func__); + ASSERT(0); + } + + + buff_max_size = sizeof(CMD_SET_DOMAIN_INFO_V2_T) + + max_channel_count * sizeof(struct channel); + + prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, buff_max_size); + prChs = &(prCmd->active_chs); + + + + /* + * Fill in the active channels + */ + rlmExtractChannelInfo(max_channel_count, prChs); + + prCmd->u4CountryCode = rlmDomainGetCountryCode(); + prCmd->uc2G4Bandwidth = prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode; + prCmd->uc5GBandwidth = prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode; + prCmd->aucReserved[0] = 0; + prCmd->aucReserved[1] = 0; + + buff_valid_size = sizeof(CMD_SET_DOMAIN_INFO_V2_T) + + (prChs->n_channels_2g + prChs->n_channels_5g) * + sizeof(struct channel); + + DBGLOG(RLM, INFO, "rlmDomainSendDomainInfoCmd_V2(), buff_valid_size = 0x%x\n", buff_valid_size); + + + /* Set domain info to chip */ + wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_DOMAIN_INFO, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + fgIsOid, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + buff_valid_size, + (PUINT_8) prCmd, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + cnmMemFree(prAdapter, prCmd); +#endif +} + + +VOID rlmDomainSendDomainInfoCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid) +{ + P_DOMAIN_INFO_ENTRY prDomainInfo; + P_CMD_SET_DOMAIN_INFO_T prCmd; + P_DOMAIN_SUBBAND_INFO prSubBand; + UINT_8 i; + + if (regd_is_single_sku_en()) + return rlmDomainSendDomainInfoCmd_V2(prAdapter, fgIsOid); + + + prDomainInfo = rlmDomainGetDomainInfo(prAdapter); + ASSERT(prDomainInfo); + + prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_SET_DOMAIN_INFO_T)); + if (!prCmd) { + DBGLOG(RLM, ERROR, "Alloc cmd buffer failed\n"); + return; + } + kalMemZero(prCmd, sizeof(CMD_SET_DOMAIN_INFO_T)); + + prCmd->u2CountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode; + prCmd->u2IsSetPassiveScan = 0; + prCmd->uc2G4Bandwidth = prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode; + prCmd->uc5GBandwidth = prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode; + prCmd->aucReserved[0] = 0; + prCmd->aucReserved[1] = 0; + + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubBand = &prDomainInfo->rSubBand[i]; + + prCmd->rSubBand[i].ucRegClass = prSubBand->ucRegClass; + prCmd->rSubBand[i].ucBand = prSubBand->ucBand; + + if (prSubBand->ucBand != BAND_NULL && prSubBand->ucBand < BAND_NUM) { + prCmd->rSubBand[i].ucChannelSpan = prSubBand->ucChannelSpan; + prCmd->rSubBand[i].ucFirstChannelNum = prSubBand->ucFirstChannelNum; + prCmd->rSubBand[i].ucNumChannels = prSubBand->ucNumChannels; + } + } + + /* Set domain info to chip */ + wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_DOMAIN_INFO, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + fgIsOid, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_SET_DOMAIN_INFO_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmd, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + cnmMemFree(prAdapter, prCmd); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmDomainSendPassiveScanInfoCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid) +{ + P_DOMAIN_INFO_ENTRY prDomainInfo; + P_CMD_SET_DOMAIN_INFO_T prCmd; + WLAN_STATUS rStatus; + P_DOMAIN_SUBBAND_INFO prSubBand; + UINT_16 u2TargetCountryCode; + UINT_8 i, j; + + prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_SET_DOMAIN_INFO_T)); + if (!prCmd) { + DBGLOG(RLM, ERROR, "Alloc cmd buffer failed\n"); + return; + } + kalMemZero(prCmd, sizeof(CMD_SET_DOMAIN_INFO_T)); + + prCmd->u2CountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode; + prCmd->u2IsSetPassiveScan = 1; + prCmd->uc2G4Bandwidth = prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode; + prCmd->uc5GBandwidth = prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode; + prCmd->aucReserved[0] = 0; + prCmd->aucReserved[1] = 0; + + DBGLOG(RLM, TRACE, "u2CountryCode=0x%04x\n", prAdapter->rWifiVar.rConnSettings.u2CountryCode); + + u2TargetCountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode; + + for (i = 0; i < REG_DOMAIN_PASSIVE_GROUP_NUM; i++) { + prDomainInfo = &arSupportedRegDomains_Passive[i]; + + for (j = 0; j < prDomainInfo->u4CountryNum; j++) { + if (prDomainInfo->pu2CountryGroup[j] == u2TargetCountryCode) + break; + } + if (j < prDomainInfo->u4CountryNum) + break; /* Found */ + } + + if (i >= REG_DOMAIN_PASSIVE_GROUP_NUM) + prDomainInfo = &arSupportedRegDomains_Passive[REG_DOMAIN_PASSIVE_DEF_IDX]; + + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubBand = &prDomainInfo->rSubBand[i]; + + prCmd->rSubBand[i].ucRegClass = prSubBand->ucRegClass; + prCmd->rSubBand[i].ucBand = prSubBand->ucBand; + + if (prSubBand->ucBand != BAND_NULL && prSubBand->ucBand < BAND_NUM) { + prCmd->rSubBand[i].ucChannelSpan = prSubBand->ucChannelSpan; + prCmd->rSubBand[i].ucFirstChannelNum = prSubBand->ucFirstChannelNum; + prCmd->rSubBand[i].ucNumChannels = prSubBand->ucNumChannels; + } + } + + /* Set passive scan channel info to chip */ + 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_V2(P_ADAPTER_T prAdapter, ENUM_BAND_T eBand, UINT_8 ucChannel) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + UINT_8 idx, start_idx, end_idx; + struct channel *prCh; + + if (eBand == BAND_2G4) { + start_idx = 0; + end_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + } else { + start_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + end_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ) + + rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ); + } + + for (idx = start_idx; idx < end_idx; idx++) { + prCh = rlmDomainGetActiveChannels() + idx; + + if (prCh->chNum == ucChannel) + return TRUE; + } + + return FALSE; +#else + return FALSE; +#endif +} + +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; + + if (regd_is_single_sku_en()) + return rlmDomainIsLegalChannel_V2(prAdapter, eBand, ucChannel); + + + prDomainInfo = rlmDomainGetDomainInfo(prAdapter); + ASSERT(prDomainInfo); + + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubband = &prDomainInfo->rSubBand[i]; + + if (prSubband->ucBand == BAND_5G && !prAdapter->fgEnable5GBand) + continue; + + if (prSubband->ucBand == eBand) { + for (j = 0; j < prSubband->ucNumChannels; j++) { + if ((prSubband->ucFirstChannelNum + j * prSubband->ucChannelSpan) + == ucChannel) { + return TRUE; + } + } + } + } + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in/out] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ + +UINT_32 rlmDomainSupOperatingClassIeFill(PUINT_8 pBuf) +{ + /* + * The Country element should only be included for Status Code 0 (Successful). + */ + UINT_32 u4IeLen; + UINT_8 aucClass[12] = { 0x01, 0x02, 0x03, 0x05, 0x16, 0x17, 0x19, 0x1b, + 0x1c, 0x1e, 0x20, 0x21 + }; + + /* + * The Supported Operating Classes element is used by a STA to advertise the + * operating classes that it is capable of operating with in this country. + * + * The Country element (see 8.4.2.10) allows a STA to configure its PHY and MAC + * for operation when the operating triplet of Operating Extension Identifier, + * Operating Class, and Coverage Class fields is present. + */ + SUP_OPERATING_CLASS_IE(pBuf)->ucId = ELEM_ID_SUP_OPERATING_CLASS; + SUP_OPERATING_CLASS_IE(pBuf)->ucLength = 1 + sizeof(aucClass); + SUP_OPERATING_CLASS_IE(pBuf)->ucCur = 0x0c; /* 0x51 */ + kalMemCopy(SUP_OPERATING_CLASS_IE(pBuf)->ucSup, aucClass, sizeof(aucClass)); + u4IeLen = (SUP_OPERATING_CLASS_IE(pBuf)->ucLength + 2); + pBuf += u4IeLen; + + COUNTRY_IE(pBuf)->ucId = ELEM_ID_COUNTRY_INFO; + COUNTRY_IE(pBuf)->ucLength = 6; + COUNTRY_IE(pBuf)->aucCountryStr[0] = 0x55; + COUNTRY_IE(pBuf)->aucCountryStr[1] = 0x53; + COUNTRY_IE(pBuf)->aucCountryStr[2] = 0x20; + COUNTRY_IE(pBuf)->arCountryStr[0].ucFirstChnlNum = 1; + COUNTRY_IE(pBuf)->arCountryStr[0].ucNumOfChnl = 11; + COUNTRY_IE(pBuf)->arCountryStr[0].cMaxTxPwrLv = 0x1e; + u4IeLen += (COUNTRY_IE(pBuf)->ucLength + 2); + + return u4IeLen; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (fgValid) : 0 -> inValid, 1 -> Valid +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rlmDomainCheckChannelEntryValid(P_ADAPTER_T prAdapter, UINT_8 ucCentralCh) +{ + BOOLEAN fgValid = FALSE; + UINT_8 ucTemp = 0xff; + UINT_8 i; + /*Check Power limit table channel efficient or not */ + + for (i = POWER_LIMIT_2G4; i < POWER_LIMIT_SUBAND_NUM; i++) { + if ((ucCentralCh >= g_rRlmSubBand[i].ucStartCh) && (ucCentralCh <= g_rRlmSubBand[i].ucEndCh)) + ucTemp = (ucCentralCh - g_rRlmSubBand[i].ucStartCh) % g_rRlmSubBand[i].ucInterval; + } + +#if 0 + /*2.4G, ex 1, 2, 3 */ + if (ucCentralCh >= BAND_2G4_LOWER_BOUND && ucCentralCh <= BAND_2G4_UPPER_BOUND) + ucTemp = 0; + /*FCC- Spec : Band UNII-1, ex 36, 38, 40.... */ + else if (ucCentralCh >= UNII1_LOWER_BOUND && ucCentralCh <= UNII1_UPPER_BOUND) + ucTemp = (ucCentralCh - UNII1_LOWER_BOUND) % 2; + /*FCC- Spec : Band UNII-2A, ex 52, 54, 56.... */ + else if (ucCentralCh >= UNII2A_LOWER_BOUND && ucCentralCh <= UNII2A_UPPER_BOUND) + ucTemp = (ucCentralCh - UNII2A_LOWER_BOUND) % 2; + /*FCC- Spec : Band UNII-2C, ex 100, 102, 104.... */ + else if (ucCentralCh >= UNII2C_LOWER_BOUND && ucCentralCh <= UNII2C_UPPER_BOUND) + ucTemp = (ucCentralCh - UNII2C_LOWER_BOUND) % 2; + /*FCC- Spec : Band UNII-3, ex 149, 151, 153... */ + else if (ucCentralCh >= UNII3_LOWER_BOUND && ucCentralCh <= UNII3_UPPER_BOUND) + ucTemp = (ucCentralCh - UNII3_LOWER_BOUND) % 2; +#endif + if (ucTemp == 0) + fgValid = TRUE; + return fgValid; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 rlmDomainGetCenterChannel(ENUM_BAND_T eBand, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend) +{ + UINT_8 ucCenterChannel; + + if (eExtend == CHNL_EXT_SCA) + ucCenterChannel = ucPriChannel + 2; + else if (eExtend == CHNL_EXT_SCB) + ucCenterChannel = ucPriChannel - 2; + else + ucCenterChannel = ucPriChannel; + + return ucCenterChannel; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rlmDomainIsValidRfSetting(P_ADAPTER_T prAdapter, + ENUM_BAND_T eBand, + UINT_8 ucPriChannel, + ENUM_CHNL_EXT_T eExtend, + ENUM_CHANNEL_WIDTH_T eChannelWidth, UINT_8 ucChannelS1, UINT_8 ucChannelS2) +{ + UINT_8 ucCenterChannel = 0; + UINT_8 ucUpperChannel; + UINT_8 ucLowerChannel; + BOOLEAN fgValidChannel = TRUE; + BOOLEAN fgUpperChannel = TRUE; + BOOLEAN fgLowerChannel = TRUE; + BOOLEAN fgValidBW = TRUE; + BOOLEAN fgValidRfSetting = TRUE; + UINT_32 u4PrimaryOffset; + + /*DBG msg for Channel InValid */ + if (eChannelWidth == CW_20_40MHZ) { + ucCenterChannel = rlmDomainGetCenterChannel(eBand, ucPriChannel, eExtend); + + /* Check Central Channel Valid or Not */ + fgValidChannel = rlmDomainCheckChannelEntryValid(prAdapter, ucCenterChannel); + if (fgValidChannel == FALSE) + DBGLOG(RLM, WARN, "Rf20: CentralCh=%d\n", ucCenterChannel); + + /* Check Upper Channel and Lower Channel */ + switch (eExtend) { + case CHNL_EXT_SCA: + ucUpperChannel = ucPriChannel + 4; + ucLowerChannel = ucPriChannel; + break; + case CHNL_EXT_SCB: + ucUpperChannel = ucPriChannel; + ucLowerChannel = ucPriChannel - 4; + break; + default: + ucUpperChannel = ucPriChannel; + ucLowerChannel = ucPriChannel; + break; + } + + fgUpperChannel = rlmDomainCheckChannelEntryValid(prAdapter, ucUpperChannel); + if (fgUpperChannel == FALSE) + DBGLOG(RLM, WARN, "Rf20: UpperCh=%d\n", ucUpperChannel); + + fgLowerChannel = rlmDomainCheckChannelEntryValid(prAdapter, ucLowerChannel); + if (fgLowerChannel == FALSE) + DBGLOG(RLM, WARN, "Rf20: LowerCh=%d\n", ucLowerChannel); + + } else if ((eChannelWidth == CW_80MHZ) || (eChannelWidth == CW_160MHZ)) { + ucCenterChannel = ucChannelS1; + + /* Check Central Channel Valid or Not */ + if (eChannelWidth != CW_160MHZ) { + /*BW not check , ex: primary 36 and central channel 50 will fail the check*/ + fgValidChannel = rlmDomainCheckChannelEntryValid(prAdapter, ucCenterChannel); + } + + if (fgValidChannel == FALSE) + DBGLOG(RLM, WARN, "Rf80/160C: CentralCh=%d\n", ucCenterChannel); + } else if (eChannelWidth == CW_80P80MHZ) { + ucCenterChannel = ucChannelS1; + + fgValidChannel = rlmDomainCheckChannelEntryValid(prAdapter, ucCenterChannel); + + if (fgValidChannel == FALSE) + DBGLOG(RLM, WARN, "Rf160NC: CentralCh1=%d\n", ucCenterChannel); + + ucCenterChannel = ucChannelS2; + + fgValidChannel = rlmDomainCheckChannelEntryValid(prAdapter, ucCenterChannel); + + if (fgValidChannel == FALSE) + DBGLOG(RLM, WARN, "Rf160NC: CentralCh2=%d\n", ucCenterChannel); + + /* Check Central Channel Valid or Not */ + } else { + DBGLOG(RLM, ERROR, "Wrong BW =%d\n", eChannelWidth); + fgValidChannel = FALSE; + } + + /* Check BW Setting Correct or Not */ + if (eBand == BAND_2G4) { + if (eChannelWidth != CW_20_40MHZ) { + fgValidBW = FALSE; + DBGLOG(RLM, WARN, "Rf: B=%d, W=%d\n", eBand, eChannelWidth); + } + } else { + if ((eChannelWidth == CW_80MHZ) || (eChannelWidth == CW_80P80MHZ)) { + u4PrimaryOffset = CAL_CH_OFFSET_80M(ucPriChannel, ucChannelS1); + if (u4PrimaryOffset >= 4) { + fgValidBW = FALSE; + DBGLOG(RLM, WARN, "Rf: PriOffSet=%d, W=%d\n", u4PrimaryOffset, eChannelWidth); + } + } else if (eChannelWidth == CW_160MHZ) { + u4PrimaryOffset = CAL_CH_OFFSET_160M(ucPriChannel, ucCenterChannel); + if (u4PrimaryOffset >= 8) { + fgValidBW = FALSE; + DBGLOG(RLM, WARN, "Rf: PriOffSet=%d, W=%d\n", u4PrimaryOffset, eChannelWidth); + } + } + } + + if ((fgValidBW == FALSE) || (fgValidChannel == FALSE) || (fgUpperChannel == FALSE) || (fgLowerChannel == FALSE)) + fgValidRfSetting = FALSE; + + return fgValidRfSetting; + +} + +#if (CFG_SUPPORT_SINGLE_SKU == 1) + +/* + * This function coverts country code from alphabet chars to u32, + * the caller need to pass country code chars and do size check + */ +UINT_32 rlmDomainAlpha2ToU32(PCHAR pcAlpha2, UINT_8 ucAlpha2Size) +{ + UINT_8 ucIdx; + UINT_32 u4CountryCode = 0; + + if (ucAlpha2Size > TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN) { + DBGLOG(RLM, ERROR, "alpha2 size %d is invalid!(max: %d)\n", + ucAlpha2Size, TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN); + ucAlpha2Size = TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN; + } + + for (ucIdx = 0; ucIdx < ucAlpha2Size; ucIdx++) + u4CountryCode |= (pcAlpha2[ucIdx] << (ucIdx * 8)); + + return u4CountryCode; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Search the tx power limit setting range of the specified in the text file +* +* \param[IN] u4CountryCode The u32 type of the specified country. +* \param[IN] pucBuf The content of the text file. +* \param[IN] u4cBufLen End boundary of the text file. +* \param[OUT] pu4CountryStart Store the start position of the desired country settings. +* \param[OUT] pu4CountryEnd Store the end position of the desired country settings. +* +* \retval TRUE Success. +* \retval FALSE Failure. +*/ +/*----------------------------------------------------------------------------*/ + +BOOL rlmDomainTxPwrLimitGetCountryRange( + UINT_32 u4CountryCode, PUINT_8 pucBuf, UINT_32 u4BufLen, + PUINT_32 pu4CountryStart, PUINT_32 pu4CountryEnd) +{ + UINT_32 u4TmpPos = 0; + char pcrCountryStr[TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN + 1] = {0}; + UINT_8 cIdx = 0; + bool search_next = false; + + while (1) { + if (!search_next) { + /* Search country code entry */ + while (u4TmpPos < u4BufLen && pucBuf[u4TmpPos] != '[') + u4TmpPos++; + /* skip the '[' char */ + u4TmpPos++; + } + + cIdx = 0; + while (u4TmpPos < u4BufLen && + cIdx < TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN && + pucBuf[u4TmpPos] != ']' && pucBuf[u4TmpPos] != ',') { + pcrCountryStr[cIdx++] = pucBuf[u4TmpPos]; + u4TmpPos++; + } + + if (pucBuf[u4TmpPos] == ',') + search_next = true; + else + search_next = false; + + /* skip the ']' or ',' char */ + u4TmpPos++; + + if (u4TmpPos >= u4BufLen || cIdx > TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN) + return FALSE; + + if (u4CountryCode == rlmDomainAlpha2ToU32(pcrCountryStr, cIdx)) { + DBGLOG(RLM, INFO, "Found TxPwrLimit table for CountryCode \"%s\"\n", + pcrCountryStr); + /* the location after char ']' or ',' */ + *pu4CountryStart = u4TmpPos; + break; + } + } + + while (u4TmpPos < u4BufLen && pucBuf[u4TmpPos] != '[') + u4TmpPos++; + + *pu4CountryEnd = u4TmpPos; + + return TRUE; +} + +BOOL rlmDomainTxPwrLimitSearchSection(const char *pSectionName, + PINT_8 pucBuf, PUINT_32 pu4Pos, UINT_32 u4BufEnd) +{ + UINT_32 u4TmpPos = *pu4Pos; + UINT_8 uSectionNameLen = kalStrLen(pSectionName); + + while (1) { + while (u4TmpPos < u4BufEnd && pucBuf[u4TmpPos] != '<') + u4TmpPos++; + + u4TmpPos++; /* skip char '<' */ + + if (u4TmpPos + uSectionNameLen >= u4BufEnd) + return FALSE; + + if (kalStrnCmp(&pucBuf[u4TmpPos], pSectionName, uSectionNameLen) == 0) { + + /* Go to the end of section header line */ + while (u4TmpPos < u4BufEnd && pucBuf[u4TmpPos] != '\n') + u4TmpPos++; + + *pu4Pos = u4TmpPos; + + break; + } + } + + return TRUE; +} + +BOOL rlmDomainTxPwrLimitSectionEnd(PUINT_8 pucBuf, + const char *pSectionName, PUINT_32 pu4Pos, UINT_32 u4BufEnd) +{ + UINT_32 u4TmpPos = *pu4Pos; + char cTmpChar = 0; + UINT_8 uSectionNameLen = kalStrLen(pSectionName); + + while (u4TmpPos < u4BufEnd) { + cTmpChar = pucBuf[u4TmpPos]; + + /* skip blank lines */ + if (cTmpChar == ' ' || cTmpChar == '\t' || + cTmpChar == '\n' || cTmpChar == '\r') { + u4TmpPos++; + continue; + } + + break; + } + + if (u4TmpPos + uSectionNameLen + 2 >= u4BufEnd) {/* 2 means '/' and '>' */ + *pu4Pos = u4BufEnd; + return FALSE; + } + + if (pucBuf[u4TmpPos] != '<') + return FALSE; + + if (pucBuf[u4TmpPos + 1] != '/' || + pucBuf[u4TmpPos + 2 + uSectionNameLen] != '>' || + kalStrnCmp(&pucBuf[u4TmpPos + 2], pSectionName, uSectionNameLen)) { + + *pu4Pos = u4TmpPos + uSectionNameLen + 2; + return FALSE; + } + + *pu4Pos = u4TmpPos + uSectionNameLen + 3; /* 3 means go to the location after '>' */ + + return TRUE; +} + +INT_8 rlmDomainTxPwrLimitGetChIdx( + struct TX_PWR_LIMIT_DATA *pTxPwrLimit, UINT_8 ucChannel) +{ + INT_8 cIdx = 0; + + for (cIdx = 0; cIdx < pTxPwrLimit->ucChNum; cIdx++) + if (ucChannel == pTxPwrLimit->rChannelTxPwrLimit[cIdx].ucChannel) + return cIdx; + + DBGLOG(RLM, ERROR, "Can't find idx of channel %d in TxPwrLimit data\n", + ucChannel); + + return -1; +} + +BOOL rlmDomainTxPwrLimitLoadChannelSetting( + PUINT_8 pucBuf, PUINT_32 pu4Pos, UINT_32 u4BufEnd, + struct TX_PWR_LIMIT_DATA *pTxPwrLimit, UINT_8 ucSectionIdx) +{ + UINT_32 u4TmpPos = *pu4Pos; + char cTmpChar = 0; + struct CHANNEL_TX_PWR_LIMIT *prChTxPwrLimit = NULL; + BOOL bNeg = FALSE; + INT_8 cLimitValue = 0, cChIdx = 0; + UINT_8 ucIdx = 0, ucChannel = 0; + + /* skip blank lines */ + while (u4TmpPos < u4BufEnd) { + cTmpChar = pucBuf[u4TmpPos]; + + if (cTmpChar == ' ' || cTmpChar == '\t' || + cTmpChar == '\n' || cTmpChar == '\r') { + u4TmpPos++; + continue; + } + + break; + } + + /* current is at the location of 'c', check remaining buf length for 'chxxx' */ + if (u4TmpPos + 5 >= u4BufEnd) { + DBGLOG(RLM, ERROR, + "Invalid location of ch setting: %u/%u\n", + u4TmpPos, u4BufEnd); + return FALSE; + } + + if (pucBuf[u4TmpPos] == 'c' && pucBuf[u4TmpPos + 1] == 'h') { + ucChannel = (pucBuf[u4TmpPos + 2] - '0') * 100 + + (pucBuf[u4TmpPos + 3] - '0') * 10 + + (pucBuf[u4TmpPos + 4] - '0'); + } else { /* invalid format */ + *pu4Pos = u4TmpPos; + DBGLOG(RLM, ERROR, "Invalid ch setting starting chars: %c%c\n", + pucBuf[u4TmpPos], pucBuf[u4TmpPos + 1]); + + /* goto next line */ + while (*pu4Pos < u4BufEnd && pucBuf[*pu4Pos] != '\n') + (*pu4Pos)++; + + return TRUE; + } + + cChIdx = rlmDomainTxPwrLimitGetChIdx(pTxPwrLimit, ucChannel); + + if (cChIdx == -1) { + *pu4Pos = u4TmpPos; + DBGLOG(RLM, ERROR, "Invalid ch %u %c%c%c\n", ucChannel, + pucBuf[u4TmpPos + 2], pucBuf[u4TmpPos + 3], pucBuf[u4TmpPos + 4]); + + /* goto next line */ + while (*pu4Pos < u4BufEnd && pucBuf[*pu4Pos] != '\n') + (*pu4Pos)++; + + return TRUE; + } + + u4TmpPos += 5; + + prChTxPwrLimit = &pTxPwrLimit->rChannelTxPwrLimit[cChIdx]; + + /* read the channel TxPwrLimit settings */ + for (ucIdx = 0; ucIdx < gTx_Pwr_Limit_Element_Num[ucSectionIdx]; ucIdx++) { + + /* skip blank and comma */ + while (u4TmpPos < u4BufEnd) { + cTmpChar = pucBuf[u4TmpPos]; + + if (cTmpChar == ' ' || cTmpChar == '\t' || cTmpChar == ',') { + u4TmpPos++; + continue; + } + break; + } + + if (u4TmpPos >= u4BufEnd) { + *pu4Pos = u4BufEnd; + DBGLOG(RLM, ERROR, + "Invalid location of ch tx pwr limit val: %u/%u\n", + u4TmpPos, u4BufEnd); + return FALSE; + } + + bNeg = FALSE; + + cTmpChar = pucBuf[u4TmpPos]; + + if (cTmpChar == '-') { + bNeg = TRUE; + u4TmpPos++; + } else if (cTmpChar == 'x') { + prChTxPwrLimit->rTxPwrLimitValue[ucSectionIdx][ucIdx] = + TX_PWR_LIMIT_MAX_VAL; + u4TmpPos++; + continue; + } + + cLimitValue = 0; + while (u4TmpPos < u4BufEnd) { + cTmpChar = pucBuf[u4TmpPos]; + + if (cTmpChar < '0' || cTmpChar > '9') + break; + + cLimitValue = (cLimitValue * 10) + (cTmpChar - '0'); + u4TmpPos++; + } + + if (bNeg) + cLimitValue = -cLimitValue; + + prChTxPwrLimit->rTxPwrLimitValue[ucSectionIdx][ucIdx] = cLimitValue; + } + + *pu4Pos = u4TmpPos; + return TRUE; +} + +VOID rlmDomainTxPwrLimitRemoveComments( + PUINT_8 pucBuf, UINT_32 u4BufLen) +{ + UINT_32 u4TmpPos = 0; + char cTmpChar = 0; + + while (u4TmpPos < u4BufLen) { + cTmpChar = pucBuf[u4TmpPos]; + + if (cTmpChar == '#') { + while (cTmpChar != '\n') { + pucBuf[u4TmpPos] = ' '; + + u4TmpPos++; + if (u4TmpPos >= u4BufLen) + break; + + cTmpChar = pucBuf[u4TmpPos]; + } + } + u4TmpPos++; + } +} + +BOOL rlmDomainTxPwrLimitLoad( + P_ADAPTER_T prAdapter, PUINT_8 pucBuf, UINT_32 u4BufLen, + UINT_32 u4CountryCode, struct TX_PWR_LIMIT_DATA *pTxPwrLimit) +{ + UINT_8 uSecIdx = 0; + UINT_32 u4CountryStart = 0, u4CountryEnd = 0, u4Pos = 0; + + rlmDomainTxPwrLimitRemoveComments(pucBuf, u4BufLen); + + if (!rlmDomainTxPwrLimitGetCountryRange(u4CountryCode, pucBuf, + u4BufLen, &u4CountryStart, &u4CountryEnd)) { + DBGLOG(RLM, ERROR, "Can't find specified table in %s\n", + WLAN_TX_PWR_LIMIT_FILE_NAME); + + /* Use WW as default country */ + if (!rlmDomainTxPwrLimitGetCountryRange(COUNTRY_CODE_WW, pucBuf, + u4BufLen, &u4CountryStart, &u4CountryEnd)) { + DBGLOG(RLM, ERROR, + "Can't find default table (WW) in %s\n", + WLAN_TX_PWR_LIMIT_FILE_NAME); + return FALSE; + } + } + + u4Pos = u4CountryStart; + + for (uSecIdx = 0; uSecIdx < TX_PWR_LIMIT_SECTION_NUM; uSecIdx++) { + if (!rlmDomainTxPwrLimitSearchSection(gTx_Pwr_Limit_Section[uSecIdx], + pucBuf, &u4Pos, u4CountryEnd)) { + DBGLOG(RLM, ERROR, "Can't find specified section %s in %s\n", + gTx_Pwr_Limit_Section[uSecIdx], WLAN_TX_PWR_LIMIT_FILE_NAME); + return FALSE; + } + + DBGLOG(RLM, INFO, "Find specified section %s in %s\n", + gTx_Pwr_Limit_Section[uSecIdx], WLAN_TX_PWR_LIMIT_FILE_NAME); + + while (!rlmDomainTxPwrLimitSectionEnd(pucBuf, + gTx_Pwr_Limit_Section[uSecIdx], &u4Pos, u4CountryEnd) && + u4Pos < u4CountryEnd) { + if (!rlmDomainTxPwrLimitLoadChannelSetting(pucBuf, &u4Pos, + u4CountryEnd, pTxPwrLimit, uSecIdx)) + return FALSE; + } + } + + DBGLOG(RLM, INFO, "Load %s finished\n", WLAN_TX_PWR_LIMIT_FILE_NAME); + return TRUE; +} + +VOID rlmDomainTxPwrLimitSetChValues( + P_CMD_CHANNEL_POWER_LIMIT_V2 pCmd, struct CHANNEL_TX_PWR_LIMIT *pChTxPwrLimit) +{ + UINT_8 section = 0, e = 0; + + pCmd->tx_pwr_dsss_cck = pChTxPwrLimit->rTxPwrLimitValue[0][0]; + pCmd->tx_pwr_dsss_bpsk = pChTxPwrLimit->rTxPwrLimitValue[0][1]; + + pCmd->tx_pwr_ofdm_bpsk = pChTxPwrLimit->rTxPwrLimitValue[0][2]; /* 6M, 9M */ + pCmd->tx_pwr_ofdm_qpsk = pChTxPwrLimit->rTxPwrLimitValue[0][3]; /* 12M, 18M */ + pCmd->tx_pwr_ofdm_16qam = pChTxPwrLimit->rTxPwrLimitValue[0][4]; /* 24M, 36M */ + pCmd->tx_pwr_ofdm_48m = pChTxPwrLimit->rTxPwrLimitValue[0][5]; + pCmd->tx_pwr_ofdm_54m = pChTxPwrLimit->rTxPwrLimitValue[0][6]; + + pCmd->tx_pwr_ht20_bpsk = pChTxPwrLimit->rTxPwrLimitValue[1][0]; /* MCS0*/ + pCmd->tx_pwr_ht20_qpsk = pChTxPwrLimit->rTxPwrLimitValue[1][1]; /* MCS1, MCS2*/ + pCmd->tx_pwr_ht20_16qam = pChTxPwrLimit->rTxPwrLimitValue[1][2]; /* MCS3, MCS4*/ + pCmd->tx_pwr_ht20_mcs5 = pChTxPwrLimit->rTxPwrLimitValue[1][3]; /* MCS5*/ + pCmd->tx_pwr_ht20_mcs6 = pChTxPwrLimit->rTxPwrLimitValue[1][4]; /* MCS6*/ + pCmd->tx_pwr_ht20_mcs7 = pChTxPwrLimit->rTxPwrLimitValue[1][5]; /* MCS7*/ + + pCmd->tx_pwr_ht40_bpsk = pChTxPwrLimit->rTxPwrLimitValue[2][0]; /* MCS0*/ + pCmd->tx_pwr_ht40_qpsk = pChTxPwrLimit->rTxPwrLimitValue[2][1]; /* MCS1, MCS2*/ + pCmd->tx_pwr_ht40_16qam = pChTxPwrLimit->rTxPwrLimitValue[2][2]; /* MCS3, MCS4*/ + pCmd->tx_pwr_ht40_mcs5 = pChTxPwrLimit->rTxPwrLimitValue[2][3]; /* MCS5*/ + pCmd->tx_pwr_ht40_mcs6 = pChTxPwrLimit->rTxPwrLimitValue[2][4]; /* MCS6*/ + pCmd->tx_pwr_ht40_mcs7 = pChTxPwrLimit->rTxPwrLimitValue[2][5]; /* MCS7*/ + pCmd->tx_pwr_ht40_mcs32 = pChTxPwrLimit->rTxPwrLimitValue[2][6]; /* MCS32*/ + + pCmd->tx_pwr_vht20_bpsk = pChTxPwrLimit->rTxPwrLimitValue[3][0]; /* MCS0*/ + pCmd->tx_pwr_vht20_qpsk = pChTxPwrLimit->rTxPwrLimitValue[3][1]; /* MCS1, MCS2*/ + pCmd->tx_pwr_vht20_16qam = pChTxPwrLimit->rTxPwrLimitValue[3][2]; /* MCS3, MCS4*/ + pCmd->tx_pwr_vht20_64qam = pChTxPwrLimit->rTxPwrLimitValue[3][3]; /* MCS5, MCS6*/ + pCmd->tx_pwr_vht20_mcs7 = pChTxPwrLimit->rTxPwrLimitValue[3][4]; + pCmd->tx_pwr_vht20_mcs8 = pChTxPwrLimit->rTxPwrLimitValue[3][5]; + pCmd->tx_pwr_vht20_mcs9 = pChTxPwrLimit->rTxPwrLimitValue[3][6]; + + pCmd->tx_pwr_vht_40 = pChTxPwrLimit->rTxPwrLimitValue[4][2]; + pCmd->tx_pwr_vht_80 = pChTxPwrLimit->rTxPwrLimitValue[4][3]; + pCmd->tx_pwr_vht_160c = pChTxPwrLimit->rTxPwrLimitValue[4][5]; + pCmd->tx_pwr_vht_160nc = pChTxPwrLimit->rTxPwrLimitValue[4][4]; + pCmd->tx_pwr_lg_40 = pChTxPwrLimit->rTxPwrLimitValue[4][0]; + pCmd->tx_pwr_lg_80 = pChTxPwrLimit->rTxPwrLimitValue[4][1]; + + + DBGLOG(RLM, TRACE, "ch %d\n", pCmd->ucCentralCh); + for (section = 0; section < TX_PWR_LIMIT_SECTION_NUM; section++) + for (e = 0; e < gTx_Pwr_Limit_Element_Num[section]; e++) + DBGLOG(RLM, TRACE, "TxPwrLimit[%s][%s]= %d\n", + gTx_Pwr_Limit_Section[section], + gTx_Pwr_Limit_Element[section][e], + pChTxPwrLimit->rTxPwrLimitValue[section][e]); +} + +VOID rlmDomainTxPwrLimitSetValues( + P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T pSetCmd, + struct TX_PWR_LIMIT_DATA *pTxPwrLimit) +{ + UINT_8 ucIdx = 0; + INT_8 cChIdx = 0; + P_CMD_CHANNEL_POWER_LIMIT_V2 pCmd = NULL; + struct CHANNEL_TX_PWR_LIMIT *pChTxPwrLimit = NULL; + + if (!pSetCmd || !pTxPwrLimit) { + DBGLOG(RLM, ERROR, "%s: Invalid request!!!\n", __func__); + return; + } + + for (ucIdx = 0; ucIdx < pSetCmd->ucNum; ucIdx++) { + pCmd = &(pSetCmd->rChannelPowerLimit[ucIdx]); + cChIdx = rlmDomainTxPwrLimitGetChIdx(pTxPwrLimit, pCmd->ucCentralCh); + if (cChIdx == -1) { + DBGLOG(RLM, ERROR, "Invalid ch idx found while assigning values\n"); + continue; + } + pChTxPwrLimit = &pTxPwrLimit->rChannelTxPwrLimit[cChIdx]; + rlmDomainTxPwrLimitSetChValues(pCmd, pChTxPwrLimit); + } +} + +BOOL rlmDomainTxPwrLimitLoadFromFile(P_ADAPTER_T prAdapter, + UINT_32 u4CountryCode, struct TX_PWR_LIMIT_DATA *pTxPwrLimit) +{ + PUINT_8 pucConfigBuf; + UINT_32 u4ConfigReadLen; + BOOL bRet = TRUE; + + pucConfigBuf = (PUINT_8) kalMemAlloc(WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE, VIR_MEM_TYPE); + + if (!pucConfigBuf) + return FALSE; + + kalMemZero(pucConfigBuf, WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE); + u4ConfigReadLen = 0; + + if (wlanGetFileContent(prAdapter, WLAN_TX_PWR_LIMIT_FILE_NAME, pucConfigBuf, + WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE, &u4ConfigReadLen, TRUE) == 0) { + /* ToDo:: Nothing */ + } else if (wlanGetFileContent(prAdapter, "/storage/sdcard0/" WLAN_TX_PWR_LIMIT_FILE_NAME, pucConfigBuf, + WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE, &u4ConfigReadLen, FALSE) == 0) { + /* ToDo:: Nothing */ + } else if (wlanGetFileContent(prAdapter, "/data/misc/" WLAN_TX_PWR_LIMIT_FILE_NAME, pucConfigBuf, + WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE, &u4ConfigReadLen, FALSE) == 0) { + /* ToDo:: Nothing */ + } else if (wlanGetFileContent(prAdapter, "/data/misc/wifi/" WLAN_TX_PWR_LIMIT_FILE_NAME, pucConfigBuf, + WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE, &u4ConfigReadLen, FALSE) == 0) { + /* ToDo:: Nothing */ + } else { + bRet = FALSE; + goto error; + } + + if (pucConfigBuf[0] == '\0' || u4ConfigReadLen == 0) { + bRet = FALSE; + goto error; + } + + if (!rlmDomainTxPwrLimitLoad(prAdapter, pucConfigBuf, u4ConfigReadLen, + u4CountryCode, pTxPwrLimit)) { + bRet = FALSE; + goto error; + } + +error: + kalMemFree(pucConfigBuf, VIR_MEM_TYPE, WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE); + return bRet; +} + +BOOLEAN rlmDomainGetTxPwrLimit(u32 country_code, + P_GLUE_INFO_T prGlueInfo, + P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T pSetCmd_2g, + P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T pSetCmd_5g + ) +{ + int bRet = TRUE; + UINT_8 ucIdx = 0, ucCnt = 0; + struct TX_PWR_LIMIT_DATA *pTxPwrLimit = + (struct TX_PWR_LIMIT_DATA *) kalMemAlloc(sizeof(struct TX_PWR_LIMIT_DATA), VIR_MEM_TYPE); + + if (!pTxPwrLimit) { + bRet = FALSE; + DBGLOG(RLM, ERROR, "Alloc buffer for TxPwrLimit main struct failed\n"); + return bRet; + } + + pTxPwrLimit->ucChNum = (pSetCmd_2g ? pSetCmd_2g->ucNum : 0) + (pSetCmd_5g ? pSetCmd_5g->ucNum : 0); + + pTxPwrLimit->rChannelTxPwrLimit = + (struct CHANNEL_TX_PWR_LIMIT *) kalMemAlloc(sizeof(struct CHANNEL_TX_PWR_LIMIT) * + (pTxPwrLimit->ucChNum), VIR_MEM_TYPE); + + if (!pTxPwrLimit->rChannelTxPwrLimit) { + bRet = FALSE; + DBGLOG(RLM, ERROR, "Alloc buffer for TxPwrLimit ch values failed\n"); + goto error; + } + + kalMemSet(pTxPwrLimit->rChannelTxPwrLimit, MAX_TX_POWER, + sizeof(struct CHANNEL_TX_PWR_LIMIT) * (pTxPwrLimit->ucChNum)); + + if (pSetCmd_2g) + for (ucIdx = 0; ucIdx < pSetCmd_2g->ucNum; ucIdx++) { + pTxPwrLimit->rChannelTxPwrLimit[ucCnt].ucChannel = + pSetCmd_2g->rChannelPowerLimit[ucIdx].ucCentralCh; + ucCnt++; + } + + if (pSetCmd_5g) + for (ucIdx = 0; ucIdx < pSetCmd_5g->ucNum; ucIdx++) { + pTxPwrLimit->rChannelTxPwrLimit[ucCnt].ucChannel = + pSetCmd_5g->rChannelPowerLimit[ucIdx].ucCentralCh; + ucCnt++; + } + + bRet = rlmDomainTxPwrLimitLoadFromFile(prGlueInfo->prAdapter, + country_code, pTxPwrLimit); + + if (bRet) { + rlmDomainTxPwrLimitSetValues(pSetCmd_2g, pTxPwrLimit); + rlmDomainTxPwrLimitSetValues(pSetCmd_5g, pTxPwrLimit); + } + + kalMemFree(pTxPwrLimit->rChannelTxPwrLimit, VIR_MEM_TYPE, + sizeof(CHANNEL_TX_PWR_LIMIT) * pTxPwrLimit->ucChNum); + +error: + kalMemFree(pTxPwrLimit, VIR_MEM_TYPE, sizeof(TX_PWR_LIMIT_DATA)); + + return bRet; +} + +#endif + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (fgValid) : 0 -> inValid, 1 -> Valid +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rlmDomainCheckPowerLimitValid(P_ADAPTER_T prAdapter, + COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION rPowerLimitTableConfiguration, + UINT_8 ucPwrLimitNum) +{ + UINT_8 i; + BOOLEAN fgValid = TRUE; + PINT_8 prPwrLimit; + + prPwrLimit = &rPowerLimitTableConfiguration.aucPwrLimit[0]; + + for (i = 0; i < ucPwrLimitNum; i++, prPwrLimit++) { + if (*prPwrLimit > MAX_TX_POWER || *prPwrLimit < MIN_TX_POWER) { + fgValid = FALSE; + break; /*Find out Wrong Power limit */ + } + } + return fgValid; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmDomainCheckCountryPowerLimitTable(P_ADAPTER_T prAdapter) +{ + UINT_8 i, j; + UINT_16 u2CountryCodeTable, u2CountryCodeCheck; + BOOLEAN fgChannelValid = FALSE; + BOOLEAN fgPowerLimitValid = FALSE; + BOOLEAN fgEntryRepetetion = FALSE; + BOOLEAN fgTableValid = TRUE; + + /*Configuration Table Check */ + for (i = 0; i < sizeof(g_rRlmPowerLimitConfiguration) / sizeof(COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION); i++) { + /*Table Country Code */ + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitConfiguration[i].aucCountryCode[0], &u2CountryCodeTable); + + /*Repetition Entry Check */ + for (j = i + 1; + j < ARRAY_SIZE(g_rRlmPowerLimitConfiguration); + j++) { + + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitConfiguration[j].aucCountryCode[0], &u2CountryCodeCheck); + if (((g_rRlmPowerLimitConfiguration[i].ucCentralCh) == + g_rRlmPowerLimitConfiguration[j].ucCentralCh) + && (u2CountryCodeTable == u2CountryCodeCheck)) { + fgEntryRepetetion = TRUE; + DBGLOG(RLM, INFO, "Domain: Configuration Repetition CC=%c%c, Ch=%d\n", + g_rRlmPowerLimitConfiguration[i].aucCountryCode[0], + g_rRlmPowerLimitConfiguration[i].aucCountryCode[1], + g_rRlmPowerLimitConfiguration[i].ucCentralCh); + } + } + + /*Channel Number Check */ + fgChannelValid = + rlmDomainCheckChannelEntryValid(prAdapter, g_rRlmPowerLimitConfiguration[i].ucCentralCh); + + /*Power Limit Check */ + fgPowerLimitValid = + rlmDomainCheckPowerLimitValid(prAdapter, g_rRlmPowerLimitConfiguration[i], PWR_LIMIT_NUM); + + if (fgChannelValid == FALSE || fgPowerLimitValid == FALSE) { + fgTableValid = FALSE; + DBGLOG(RLM, INFO, "Domain: CC=%c%c, Ch=%d, Limit: %d,%d,%d,%d,%d\n", + g_rRlmPowerLimitConfiguration[i].aucCountryCode[0], + g_rRlmPowerLimitConfiguration[i].aucCountryCode[1], + g_rRlmPowerLimitConfiguration[i].ucCentralCh, + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_CCK], + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_20M], + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_40M], + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_80M], + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_160M]); + } + + if (u2CountryCodeTable == COUNTRY_CODE_NULL) { + DBGLOG(RLM, INFO, "Domain: Full search down\n"); + break; /*End of country table entry */ + } + + } + + if (fgEntryRepetetion == FALSE) + DBGLOG(RLM, INFO, "Domain: Configuration Table no Repetiton.\n"); + + /*Configuration Table no error */ + if (fgTableValid == TRUE) + prAdapter->fgIsPowerLimitTableValid = TRUE; + else + prAdapter->fgIsPowerLimitTableValid = FALSE; + + /*Default Table Check */ + fgEntryRepetetion = FALSE; + for (i = 0; i < sizeof(g_rRlmPowerLimitDefault) / sizeof(COUNTRY_POWER_LIMIT_TABLE_DEFAULT); i++) { + + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[i].aucCountryCode[0], &u2CountryCodeTable); + + for (j = i + 1; j < sizeof(g_rRlmPowerLimitDefault) / sizeof(COUNTRY_POWER_LIMIT_TABLE_DEFAULT); j++) { + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[j].aucCountryCode[0], &u2CountryCodeCheck); + if (u2CountryCodeTable == u2CountryCodeCheck) { + fgEntryRepetetion = TRUE; + DBGLOG(RLM, INFO, + "Domain: Default Repetition CC=%c%c\n", + g_rRlmPowerLimitDefault[j].aucCountryCode[0], + g_rRlmPowerLimitDefault[j].aucCountryCode[1]); + } + } + } + if (fgEntryRepetetion == FALSE) + DBGLOG(RLM, INFO, "Domain: Default Table no Repetiton.\n"); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (u2TableIndex) : if 0xFFFF -> No Table Match +*/ +/*----------------------------------------------------------------------------*/ +UINT_16 rlmDomainPwrLimitDefaultTableDecision(P_ADAPTER_T prAdapter, UINT_16 u2CountryCode) +{ + + UINT_16 i; + UINT_16 u2CountryCodeTable = COUNTRY_CODE_NULL; + UINT_16 u2TableIndex = POWER_LIMIT_TABLE_NULL; /* No Table Match */ + + /*Default Table Index */ + for (i = 0; i < sizeof(g_rRlmPowerLimitDefault) / sizeof(COUNTRY_POWER_LIMIT_TABLE_DEFAULT); i++) { + + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[i].aucCountryCode[0], &u2CountryCodeTable); + + if (u2CountryCodeTable == u2CountryCode) { + u2TableIndex = i; + break; /*match country code */ + } else if (u2CountryCodeTable == COUNTRY_CODE_NULL) { + u2TableIndex = i; + break; /*find last one country- Default */ + } + } + + DBGLOG(RLM, INFO, "Domain: Default Table Index = %d\n", u2TableIndex); + + return u2TableIndex; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmDomainBuildCmdByDefaultTable(P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T prCmd, UINT_16 u2DefaultTableIndex) +{ + UINT_8 i, k; + P_COUNTRY_POWER_LIMIT_TABLE_DEFAULT prPwrLimitSubBand; + P_CMD_CHANNEL_POWER_LIMIT prCmdPwrLimit; + + prCmdPwrLimit = &prCmd->rChannelPowerLimit[0]; + prPwrLimitSubBand = &g_rRlmPowerLimitDefault[u2DefaultTableIndex]; + + /*Build power limit cmd by default table information */ + + for (i = POWER_LIMIT_2G4; i < POWER_LIMIT_SUBAND_NUM; i++) { + if (prPwrLimitSubBand->aucPwrLimitSubBand[i] < MAX_TX_POWER) { + for (k = g_rRlmSubBand[i].ucStartCh; k <= g_rRlmSubBand[i].ucEndCh; + k += g_rRlmSubBand[i].ucInterval) { + if ((prPwrLimitSubBand->ucPwrUnit & BIT(i)) == 0) { + prCmdPwrLimit->ucCentralCh = k; + kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, + prPwrLimitSubBand->aucPwrLimitSubBand[i], PWR_LIMIT_NUM); + prCmdPwrLimit++; + prCmd->ucNum++; + + } else { + /* ex: 40MHz power limit(mW\MHz) = 20MHz power limit(mW\MHz) * 2 + * ---> 40MHz power limit(dBm) = 20MHz power limit(dBm) + 6; + */ + prCmdPwrLimit->ucCentralCh = k; + prCmdPwrLimit->cPwrLimitCCK = prPwrLimitSubBand->aucPwrLimitSubBand[i]; + prCmdPwrLimit->cPwrLimit20 = prPwrLimitSubBand->aucPwrLimitSubBand[i]; + prCmdPwrLimit->cPwrLimit40 = prPwrLimitSubBand->aucPwrLimitSubBand[i] + 6; + if (prCmdPwrLimit->cPwrLimit40 > MAX_TX_POWER) + prCmdPwrLimit->cPwrLimit40 = MAX_TX_POWER; + prCmdPwrLimit->cPwrLimit80 = prPwrLimitSubBand->aucPwrLimitSubBand[i] + 12; + if (prCmdPwrLimit->cPwrLimit80 > MAX_TX_POWER) + prCmdPwrLimit->cPwrLimit80 = MAX_TX_POWER; + prCmdPwrLimit->cPwrLimit160 = prPwrLimitSubBand->aucPwrLimitSubBand[i] + 18; + if (prCmdPwrLimit->cPwrLimit160 > MAX_TX_POWER) + prCmdPwrLimit->cPwrLimit160 = MAX_TX_POWER; + prCmdPwrLimit++; + prCmd->ucNum++; + } + } + } + } + +#if 0 + if (prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_2G4] < MAX_TX_POWER) { + for (i = BAND_2G4_LOWER_BOUND; i <= BAND_2G4_UPPER_BOUND; i++) { + prCmdPwrLimit->ucCentralCh = i; + kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_2G4], + PWR_LIMIT_NUM); + prCmdPwrLimit++; + prCmd->ucNum++; + } + } + + if (prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII1] < MAX_TX_POWER) { + if (prCmd->u2CountryCode != COUNTRY_CODE_KR) { + for (i = UNII1_LOWER_BOUND; i <= UNII1_UPPER_BOUND; i += 2) { + prCmdPwrLimit->ucCentralCh = i; + kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, + prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII1], PWR_LIMIT_NUM); + prCmdPwrLimit++; + prCmd->ucNum++; + } + } else { + for (i = UNII1_LOWER_BOUND; i <= UNII1_UPPER_BOUND; i += 2) { + /* ex: 40MHz power limit(mW\MHz) = 20MHz power limit(mW\MHz) * 2 + * ---> 40MHz power limit(dBm) = 20MHz power limit(dBm) + 6; + */ + prCmdPwrLimit->ucCentralCh = i; + prCmdPwrLimit->cPwrLimitCCK = + g_rRlmPowerLimitDefault[u2DefaultTableIndex].cPwrLimitUnii1; + prCmdPwrLimit->cPwrLimit20 = + g_rRlmPowerLimitDefault[u2DefaultTableIndex].cPwrLimitUnii1; + prCmdPwrLimit->cPwrLimit40 = + g_rRlmPowerLimitDefault[u2DefaultTableIndex].cPwrLimitUnii1 + 6; + prCmdPwrLimit->cPwrLimit80 = + g_rRlmPowerLimitDefault[u2DefaultTableIndex].cPwrLimitUnii1 + 12; + prCmdPwrLimit->cPwrLimit160 = + g_rRlmPowerLimitDefault[u2DefaultTableIndex].cPwrLimitUnii1 + 18; + prCmdPwrLimit++; + prCmd->ucNum++; + } + } + } + + if (prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII2A] < MAX_TX_POWER) { + for (i = UNII2A_LOWER_BOUND; i <= UNII2A_UPPER_BOUND; i += 2) { + prCmdPwrLimit->ucCentralCh = i; + kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, + prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII2A], PWR_LIMIT_NUM); + prCmdPwrLimit++; + prCmd->ucNum++; + } + } + + if (prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII2C] < MAX_TX_POWER) { + for (i = UNII2C_LOWER_BOUND; i <= UNII2C_UPPER_BOUND; i += 2) { + prCmdPwrLimit->ucCentralCh = i; + kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, + prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII2C], PWR_LIMIT_NUM); + prCmdPwrLimit++; + prCmd->ucNum++; + } + } + if (prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII3] < MAX_TX_POWER) { + for (i = UNII3_LOWER_BOUND; i <= UNII3_UPPER_BOUND; i += 2) { + prCmdPwrLimit->ucCentralCh = i; + kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, + prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII3], PWR_LIMIT_NUM); + prCmdPwrLimit++; + prCmd->ucNum++; + } + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmDomainBuildCmdByConfigTable(P_ADAPTER_T prAdapter, P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T prCmd) +{ + UINT_8 i, k; + UINT_16 u2CountryCodeTable = COUNTRY_CODE_NULL; + P_CMD_CHANNEL_POWER_LIMIT prCmdPwrLimit; + BOOLEAN fgChannelValid; + + /*Build power limit cmd by configuration table information */ + + for (i = 0; i < sizeof(g_rRlmPowerLimitConfiguration) / sizeof(COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION); i++) { + + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitConfiguration[i].aucCountryCode[0], &u2CountryCodeTable); + + fgChannelValid = + rlmDomainCheckChannelEntryValid(prAdapter, g_rRlmPowerLimitConfiguration[i].ucCentralCh); + + if (u2CountryCodeTable == COUNTRY_CODE_NULL) { + DBGLOG(RLM, INFO, "Domain: full search configuration table done.\n"); + break; /*end of configuration table */ + } else if ((u2CountryCodeTable == prCmd->u2CountryCode) && (fgChannelValid == TRUE)) { + + prCmdPwrLimit = &prCmd->rChannelPowerLimit[0]; + + if (prCmd->ucNum != 0) { + for (k = 0; k < prCmd->ucNum; k++) { + if (prCmdPwrLimit->ucCentralCh == + g_rRlmPowerLimitConfiguration[i].ucCentralCh) { + + /*Cmd setting (Default table information) and + * Configuration table has repetition channel entry, + * ex : Default table (ex: 2.4G, limit = 20dBm) --> + * ch1~14 limit =20dBm, + * Configuration table (ex: ch1, limit = 22dBm) --> + * ch 1 = 22 dBm + * Cmd final setting --> ch1 = 22dBm, ch12~14 = 20dBm + */ + kalMemCopy(&prCmdPwrLimit->cPwrLimitCCK, + &g_rRlmPowerLimitConfiguration[i].aucPwrLimit, + PWR_LIMIT_NUM); + + DBGLOG(RLM, INFO, + "Domain: CC=%c%c,ConfigCh=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", + ((prCmd->u2CountryCode & 0xff00) >> 8), + (prCmd->u2CountryCode & 0x00ff), prCmdPwrLimit->ucCentralCh, + prCmdPwrLimit->cPwrLimitCCK, prCmdPwrLimit->cPwrLimit20, + prCmdPwrLimit->cPwrLimit40, prCmdPwrLimit->cPwrLimit80, + prCmdPwrLimit->cPwrLimit160, prCmdPwrLimit->ucFlag); + + break; + } + prCmdPwrLimit++; + } + if (k == prCmd->ucNum) { + + /*Full search cmd (Default table setting) no match channey, + * ex : Default table (ex: 2.4G, limit = 20dBm) --> + * ch1~14 limit =20dBm, + * Configuration table (ex: ch36, limit = 22dBm) --> + * ch 36 = 22 dBm + * Cmd final setting --> ch1~14 = 20dBm, ch36= 22dBm + */ + kalMemCopy(&prCmdPwrLimit->cPwrLimitCCK, + &g_rRlmPowerLimitConfiguration[i].aucPwrLimit, PWR_LIMIT_NUM); + prCmd->ucNum++; + + DBGLOG(RLM, INFO, + "Domain: Full CC=%c%c,ConfigCh=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", + ((prCmd->u2CountryCode & 0xff00) >> 8), (prCmd->u2CountryCode & 0x00ff), + prCmdPwrLimit->ucCentralCh, prCmdPwrLimit->cPwrLimitCCK, + prCmdPwrLimit->cPwrLimit20, prCmdPwrLimit->cPwrLimit40, + prCmdPwrLimit->cPwrLimit80, prCmdPwrLimit->cPwrLimit160, + prCmdPwrLimit->ucFlag); + + } + } else { + + /*Default table power limit value are 63--> cmd table no channel entry + * ex : Default table (ex: 2.4G, limit = 63Bm) --> no channel entry in cmd, + * Configuration table (ex: ch36, limit = 22dBm) --> ch 36 = 22 dBm + * Cmd final setting --> ch36= 22dBm + */ + prCmdPwrLimit->ucCentralCh = g_rRlmPowerLimitConfiguration[i].ucCentralCh; + kalMemCopy(&prCmdPwrLimit->cPwrLimitCCK, &g_rRlmPowerLimitConfiguration[i].aucPwrLimit, + PWR_LIMIT_NUM); + prCmd->ucNum++; + + DBGLOG(RLM, INFO, "Domain: Default table power limit value are 63.\n"); + DBGLOG(RLM, INFO, "Domain: CC=%c%c,ConfigCh=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", + ((prCmd->u2CountryCode & 0xff00) >> 8), + (prCmd->u2CountryCode & 0x00ff), prCmdPwrLimit->ucCentralCh, + prCmdPwrLimit->cPwrLimitCCK, prCmdPwrLimit->cPwrLimit20, + prCmdPwrLimit->cPwrLimit40, prCmdPwrLimit->cPwrLimit80, + prCmdPwrLimit->cPwrLimit160, prCmdPwrLimit->ucFlag); + + } + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmDomainSendPwrLimitCmd_V2(P_ADAPTER_T prAdapter) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + WLAN_STATUS rStatus; + UINT_32 u4SetQueryInfoLen; + UINT_32 ch_cnt; + struct wiphy *wiphy; + u8 band_idx, ch_idx; + P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T prCmd[KAL_NUM_BANDS] = {NULL}; + UINT_32 u4SetCmdTableMaxSize[KAL_NUM_BANDS] = {0}; + const INT_8 *prChannelList = NULL; + + + DBGLOG(RLM, INFO, "rlmDomainSendPwrLimitCmd()\n"); + + wiphy = priv_to_wiphy(prAdapter->prGlueInfo); + for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { + if (band_idx != KAL_BAND_2GHZ && band_idx != KAL_BAND_5GHZ) + continue; + + prChannelList = (band_idx == KAL_BAND_2GHZ) ? + gTx_Pwr_Limit_2g_Ch : gTx_Pwr_Limit_5g_Ch; + + ch_cnt = (band_idx == KAL_BAND_2GHZ) ? TX_PWR_LIMIT_2G_CH_NUM : + TX_PWR_LIMIT_5G_CH_NUM; + + if (!ch_cnt) + continue; + + u4SetCmdTableMaxSize[band_idx] = + sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T) + + ch_cnt * sizeof(CMD_CHANNEL_POWER_LIMIT_V2); + + /* compile time assertion on firmware command structs */ + DATA_STRUCT_INSPECTING_ASSERT(sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T) == 8); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(CMD_CHANNEL_POWER_LIMIT_V2) == 40); + DATA_STRUCT_INSPECTING_ASSERT( + OFFSET_OF(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T, rChannelPowerLimit) == + sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T)); + DATA_STRUCT_INSPECTING_ASSERT( + OFFSET_OF(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T, rChannelPowerLimit[1]) == + sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T) + 1 * sizeof(CMD_CHANNEL_POWER_LIMIT_V2)); + DATA_STRUCT_INSPECTING_ASSERT( + OFFSET_OF(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T, rChannelPowerLimit[2]) == + sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T) + 2 * sizeof(CMD_CHANNEL_POWER_LIMIT_V2)); + + prCmd[band_idx] = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4SetCmdTableMaxSize[band_idx]); + + + if (!prCmd[band_idx]) { + DBGLOG(RLM, ERROR, "Domain: no buf to send cmd\n"); + goto error; + } + + /*initialize tw pwr table*/ + kalMemSet(prCmd[band_idx], MAX_TX_POWER, u4SetCmdTableMaxSize[band_idx]); + + prCmd[band_idx]->ucNum = ch_cnt; + prCmd[band_idx]->eband = (band_idx == KAL_BAND_2GHZ) ? BAND_2G4 : BAND_5G; + prCmd[band_idx]->countryCode = rlmDomainGetCountryCode(); + + DBGLOG(RLM, INFO, "%s, active n_channels=%d, band=%d\n", __func__, ch_cnt, prCmd[band_idx]->eband); + + for (ch_idx = 0; ch_idx < ch_cnt; ch_idx++) { + prCmd[band_idx]->rChannelPowerLimit[ch_idx].ucCentralCh = + prChannelList[ch_idx]; + } + } + + + /* + * Get Max Tx Power from MT_TxPwrLimit.dat + */ + rlmDomainGetTxPwrLimit(rlmDomainGetCountryCode(), + prAdapter->prGlueInfo, + prCmd[KAL_BAND_2GHZ], + prCmd[KAL_BAND_5GHZ]); + + + for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { + UINT_8 ucRemainChNum, i, ucTempChNum, prCmdBatchNum; + UINT_32 u4BufSize = 0; + P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T prTempCmd = NULL; + ENUM_BAND_T eBand = (band_idx == KAL_BAND_2GHZ) ? + BAND_2G4 : BAND_5G; + + if (!prCmd[band_idx]) + continue; + + ucRemainChNum = prCmd[band_idx]->ucNum; + prCmdBatchNum = + (ucRemainChNum + TX_PWR_LIMIT_CMD_CH_NUM_THRESHOLD - 1) / + TX_PWR_LIMIT_CMD_CH_NUM_THRESHOLD; + + for (i = 0; i < prCmdBatchNum; i++) { + if (i == prCmdBatchNum - 1) + ucTempChNum = ucRemainChNum; + else + ucTempChNum = TX_PWR_LIMIT_CMD_CH_NUM_THRESHOLD; + + u4BufSize = sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T) + + ucTempChNum * sizeof(CMD_CHANNEL_POWER_LIMIT_V2); + + prTempCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4BufSize); + + if (!prTempCmd) { + DBGLOG(RLM, ERROR, "Domain: no buf to send cmd\n"); + goto error; + } + + /*copy partial tx pwr limit*/ + prTempCmd->ucNum = ucTempChNum; + prTempCmd->eband = eBand; + prTempCmd->countryCode = rlmDomainGetCountryCode(); + kalMemCopy(&prTempCmd->rChannelPowerLimit[0], + &prCmd[band_idx]->rChannelPowerLimit[i * TX_PWR_LIMIT_CMD_CH_NUM_THRESHOLD], + ucTempChNum * sizeof(CMD_CHANNEL_POWER_LIMIT_V2)); + + u4SetQueryInfoLen = u4BufSize; + /* Update tx max. power info to chip */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_COUNTRY_POWER_LIMIT, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + u4SetQueryInfoLen, /* u4SetQueryInfoLen */ + (PUINT_8) prTempCmd, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + cnmMemFree(prAdapter, prTempCmd); + + ucRemainChNum -= ucTempChNum; + } + } + +error: + for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { + if (prCmd[band_idx]) + cnmMemFree(prAdapter, prCmd[band_idx]); + } +#endif +} + +VOID rlmDomainSendPwrLimitCmd(P_ADAPTER_T prAdapter) +{ + P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T prCmd; + WLAN_STATUS rStatus; + UINT_8 i; + UINT_16 u2DefaultTableIndex; + UINT_32 u4SetCmdTableMaxSize; + UINT_32 u4SetQueryInfoLen; + P_CMD_CHANNEL_POWER_LIMIT prCmdPwrLimit; /* for print usage */ + + if (regd_is_single_sku_en()) + return rlmDomainSendPwrLimitCmd_V2(prAdapter); + + + u4SetCmdTableMaxSize = + sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T) + + MAX_CMD_SUPPORT_CHANNEL_NUM * sizeof(CMD_CHANNEL_POWER_LIMIT); + + prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4SetCmdTableMaxSize); + + if (!prCmd) { + DBGLOG(RLM, ERROR, "Domain: no buf to send cmd\n"); + return; + } + kalMemZero(prCmd, u4SetCmdTableMaxSize); + + u2DefaultTableIndex = + rlmDomainPwrLimitDefaultTableDecision(prAdapter, prAdapter->rWifiVar.rConnSettings.u2CountryCode); + + if (u2DefaultTableIndex != POWER_LIMIT_TABLE_NULL) { + + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[u2DefaultTableIndex].aucCountryCode[0], + &prCmd->u2CountryCode); + + prCmd->ucNum = 0; + + if (prCmd->u2CountryCode != COUNTRY_CODE_NULL) { + /*Command - default table information */ + rlmDomainBuildCmdByDefaultTable(prCmd, u2DefaultTableIndex); + + /*Command - configuration table information */ + rlmDomainBuildCmdByConfigTable(prAdapter, prCmd); + } + } +#if 0 + u4SetCmdTableMaxSize = + sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T) + + MAX_CMD_SUPPORT_CHANNEL_NUM * sizeof(CMD_CHANNEL_POWER_LIMIT); + + prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4SetCmdTableMaxSize); + ASSERT(prCmd); + + /* To do: exception handle */ + if (!prCmd) { + DBGLOG(RLM, ERROR, "Domain: no buf to send cmd\n"); + return; + } + kalMemZero(prCmd, u4SetCmdTableMaxSize); /* TODO memzero */ + + if (u2TableIndex != POWER_LIMIT_TABLE_NULL && u2TableIndex < MAX_DEFAULT_TABLE_COUNTRY_NUM) { + + prCmd->u2CountryCode = (((UINT_16) g_rRlmCountryPowerLimitTable[u2TableIndex].aucCountryCode[0]) << 8) | + (((UINT_16) g_rRlmCountryPowerLimitTable[u2TableIndex].aucCountryCode[1]) & BITS(0, 7)); + prChPwrLimit = &g_rRlmCountryPowerLimitTable[u2TableIndex].rChannelPowerLimit[0]; + prCmdPwrLimit = &prCmd->rChannelPowerLimit[0]; + prCmd->ucNum = 0; + for (i = 0; i < MAX_CMD_SUPPORT_CHANNEL_NUM; i++) { + + if (prChPwrLimit->ucCentralCh != ENDCH) { + + /*Check Power limit table channel efficient or not */ + fgChannelValid = rlmDomainCheckChannelEntryValid(prAdapter, prChPwrLimit->ucCentralCh); + + /*Cmd set up */ + if (fgChannelValid) { + kalMemCopy(prCmdPwrLimit, prChPwrLimit, sizeof(CMD_CHANNEL_POWER_LIMIT)); + DBGLOG(RLM, INFO, + "Domain: ValidCh=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", + prCmdPwrLimit->ucCentralCh, prCmdPwrLimit->cPwrLimitCCK, + prCmdPwrLimit->cPwrLimit20, prCmdPwrLimit->cPwrLimit40, + prCmdPwrLimit->cPwrLimit80, prCmdPwrLimit->cPwrLimit160, + prCmdPwrLimit->ucFlag); + prCmd->ucNum++; + prCmdPwrLimit++; + } else { + DBGLOG(RLM, INFO, + "Domain: Non-Ch=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", + prChPwrLimit->ucCentralCh, prChPwrLimit->cPwrLimitCCK, + prChPwrLimit->cPwrLimit20, prChPwrLimit->cPwrLimit40, + prChPwrLimit->cPwrLimit80, prChPwrLimit->cPwrLimit160, + prChPwrLimit->ucFlag); + } + prChPwrLimit++; + } else { + /*End of the chanel entry */ + break; + } + }; + } +#endif + + if (prCmd->u2CountryCode != 0) { + DBGLOG(RLM, INFO, + "Domain: ValidCC =%c%c, ChNum=%d\n", ((prCmd->u2CountryCode & 0xff00) >> 8), + (prCmd->u2CountryCode & 0x00ff), prCmd->ucNum); + } else { + DBGLOG(RLM, INFO, "Domain: ValidCC =0x%04x, ChNum=%d\n", prCmd->u2CountryCode, prCmd->ucNum); + } + prCmdPwrLimit = &prCmd->rChannelPowerLimit[0]; + + for (i = 0; i < prCmd->ucNum; i++) { + DBGLOG(RLM, INFO, "Domain: Ch=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", prCmdPwrLimit->ucCentralCh, + prCmdPwrLimit->cPwrLimitCCK, prCmdPwrLimit->cPwrLimit20, prCmdPwrLimit->cPwrLimit40, + prCmdPwrLimit->cPwrLimit80, prCmdPwrLimit->cPwrLimit160, prCmdPwrLimit->ucFlag); + prCmdPwrLimit++; + } + + u4SetQueryInfoLen = + (sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T) + (prCmd->ucNum) * sizeof(CMD_CHANNEL_POWER_LIMIT)); + + /* Update domain info to chip */ + if (prCmd->ucNum <= MAX_CMD_SUPPORT_CHANNEL_NUM) { + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_COUNTRY_POWER_LIMIT, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + u4SetQueryInfoLen, /* u4SetQueryInfoLen */ + (PUINT_8) prCmd, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + } else { + DBGLOG(RLM, INFO, "Domain: illegal power limit table"); + } + + /* ASSERT(rStatus == WLAN_STATUS_PENDING); */ + + cnmMemFree(prAdapter, prCmd); + +} +#endif +BOOLEAN regd_is_single_sku_en(void) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + return g_mtk_regd_control.en; +#else + return FALSE; +#endif +} + +#if (CFG_SUPPORT_SINGLE_SKU == 1) +BOOLEAN rlmDomainIsCtrlStateEqualTo(enum regd_state state) +{ + return (g_mtk_regd_control.state == state) ? TRUE : FALSE; +} + +enum regd_state rlmDomainGetCtrlState(void) +{ + return g_mtk_regd_control.state; +} + + +void rlmDomainResetActiveChannel(void) +{ + g_mtk_regd_control.n_channel_active_2g = 0; + g_mtk_regd_control.n_channel_active_5g = 0; +} + +void rlmDomainAddActiveChannel(u8 band) + +{ + if (band == KAL_BAND_2GHZ) + g_mtk_regd_control.n_channel_active_2g += 1; + else if (band == KAL_BAND_5GHZ) + g_mtk_regd_control.n_channel_active_5g += 1; +} + +u8 rlmDomainGetActiveChannelCount(u8 band) +{ + if (band == KAL_BAND_2GHZ) + return g_mtk_regd_control.n_channel_active_2g; + else if (band == KAL_BAND_5GHZ) + return g_mtk_regd_control.n_channel_active_5g; + else + return 0; +} + +struct channel *rlmDomainGetActiveChannels(void) +{ + return g_mtk_regd_control.channels; +} + +void rlmDomainSetDefaultCountryCode(void) +{ + g_mtk_regd_control.alpha2 = COUNTRY_CODE_WW; +} + +void rlmDomainResetCtrlInfo(void) +{ + if (g_mtk_regd_control.state == REGD_STATE_UNDEFINED) { + + memset(&g_mtk_regd_control, 0, sizeof(mtk_regd_control)); + + g_mtk_regd_control.state = REGD_STATE_INIT; + + rlmDomainSetDefaultCountryCode(); + +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) + g_mtk_regd_control.flag |= REGD_CTRL_FLAG_SUPPORT_LOCAL_REGD_DB; +#endif + } +} + +BOOLEAN rlmDomainIsUsingLocalRegDomainDataBase(void) +{ +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) + return (g_mtk_regd_control.flag & REGD_CTRL_FLAG_SUPPORT_LOCAL_REGD_DB) ? TRUE : FALSE; +#else + return FALSE; +#endif +} + +bool rlmDomainIsSameCountryCode(char *alpha2, u8 size_of_alpha2) +{ + u8 idx; + u32 alpha2_hex = 0; + + for (idx = 0; idx < size_of_alpha2; idx++) + alpha2_hex |= (alpha2[idx] << (idx * 8)); + + return (rlmDomainGetCountryCode() == alpha2_hex) ? TRUE : FALSE; +} + +void rlmDomainSetCountryCode(char *alpha2, u8 size_of_alpha2) +{ + u8 max; + u8 buf_size; + + buf_size = sizeof(g_mtk_regd_control.alpha2); + max = (buf_size < size_of_alpha2) ? buf_size : size_of_alpha2; + + g_mtk_regd_control.alpha2 = rlmDomainAlpha2ToU32(alpha2, max); +} +void rlmDomainSetDfsRegion(enum nl80211_dfs_regions dfs_region) +{ + g_mtk_regd_control.dfs_region = dfs_region; +} + +enum nl80211_dfs_regions rlmDomainGetDfsRegion(void) +{ + return g_mtk_regd_control.dfs_region; +} + +void rlmDomainSetTempCountryCode(char *alpha2, u8 size_of_alpha2) +{ + u8 idx, max; + u8 buf_size; + + buf_size = sizeof(g_mtk_regd_control.tmp_alpha2); + max = (buf_size < size_of_alpha2) ? buf_size : size_of_alpha2; + + g_mtk_regd_control.tmp_alpha2 = 0; + + for (idx = 0; idx < max; idx++) + g_mtk_regd_control.tmp_alpha2 |= (alpha2[idx] << (idx * 8)); + +} + +enum regd_state rlmDomainStateTransition(enum regd_state request_state, struct regulatory_request *pRequest) +{ + enum regd_state next_state, old_state; + bool the_same = 0; + + old_state = g_mtk_regd_control.state; + next_state = REGD_STATE_INVALID; + + if (old_state == REGD_STATE_INVALID) + DBGLOG(RLM, ERROR, "%s(): invalid state. trasntion is not allowed.\n", __func__); + + + switch (request_state) { + case REGD_STATE_SET_WW_CORE: + if ((old_state == REGD_STATE_SET_WW_CORE) || (old_state == REGD_STATE_INIT) + || old_state == REGD_STATE_SET_COUNTRY_USER + || old_state == REGD_STATE_SET_COUNTRY_IE) + next_state = request_state; + + break; + + case REGD_STATE_SET_COUNTRY_USER: + /* Allow user to set multiple times */ + if ((old_state == REGD_STATE_SET_WW_CORE) || (old_state == REGD_STATE_INIT) + || old_state == REGD_STATE_SET_COUNTRY_USER + || old_state == REGD_STATE_SET_COUNTRY_IE) + next_state = request_state; + else + DBGLOG(RLM, ERROR, "Invalid old state = %d\n", old_state); + break; + case REGD_STATE_SET_COUNTRY_DRIVER: + if (old_state == REGD_STATE_SET_COUNTRY_USER) { + /* + * Error. + * Mixing using set_country_by_user and set_country_by_driver + * is not allowed. + */ + break; + } + + next_state = request_state; + break; + + case REGD_STATE_SET_COUNTRY_IE: + next_state = request_state; + break; + + default: + break; + } + + if (next_state == REGD_STATE_INVALID) { + DBGLOG(RLM, ERROR, "%s(): ERROR. trasntion to invalid state. o=%x, r=%x, s=%x\n", + __func__, old_state, request_state, the_same); + } else + DBGLOG(RLM, INFO, "%s(): trasntion to state = %x (old = %x)\n", + __func__, next_state, g_mtk_regd_control.state); + + g_mtk_regd_control.state = next_state; + + return g_mtk_regd_control.state; +} + +void rlmDomainSetRefWiphy(struct wiphy *pWiphy) +{ + g_mtk_regd_control.pRefWiphy = pWiphy; +} + +struct wiphy *rlmDomainGetRefWiphy(void) +{ + return g_mtk_regd_control.pRefWiphy; +} + +/** + * rlmDomainChannelFlagString - Transform channel flags to readable string + * + * @ flags: the ieee80211_channel->flags for a channel + * @ buf: string buffer to put the transformed string + * @ buf_size: size of the buf + **/ +void rlmDomainChannelFlagString(u32 flags, char *buf, size_t buf_size) +{ + INT_32 buf_written = 0; + + if (!flags || !buf || !buf_size) + return; + + if (flags & IEEE80211_CHAN_DISABLED) { + LOGBUF(buf, ((INT_32)buf_size), buf_written, "DISABLED "); + /* If DISABLED, don't need to check other flags */ + return; + } + if (flags & IEEE80211_CHAN_PASSIVE_FLAG) + LOGBUF(buf, ((INT_32)buf_size), buf_written, IEEE80211_CHAN_PASSIVE_STR " "); + if (flags & IEEE80211_CHAN_RADAR) + LOGBUF(buf, ((INT_32)buf_size), buf_written, "RADAR "); + if (flags & IEEE80211_CHAN_NO_HT40PLUS) + LOGBUF(buf, ((INT_32)buf_size), buf_written, "NO_HT40PLUS "); + if (flags & IEEE80211_CHAN_NO_HT40MINUS) + LOGBUF(buf, ((INT_32)buf_size), buf_written, "NO_HT40MINUS "); + if (flags & IEEE80211_CHAN_NO_80MHZ) + LOGBUF(buf, ((INT_32)buf_size), buf_written, "NO_80MHZ "); + if (flags & IEEE80211_CHAN_NO_160MHZ) + LOGBUF(buf, ((INT_32)buf_size), buf_written, "NO_160MHZ "); +} + +void rlmDomainParsingChannel(IN struct wiphy *pWiphy) +{ + u32 band_idx, ch_idx; + u32 ch_count; + struct ieee80211_supported_band *sband; + struct ieee80211_channel *chan; + struct channel *pCh; + char chan_flag_string[64] = {0}; + P_GLUE_INFO_T prGlueInfo; + UINT_8 ucChannelNum = 0; + BOOLEAN fgDisconnection = FALSE; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + + + if (!pWiphy) { + DBGLOG(RLM, ERROR, "%s(): ERROR. pWiphy = NULL.\n", __func__); + ASSERT(0); + return; + } + + /* Retrieve connected channel */ + prGlueInfo = rlmDomainGetGlueInfo(); + if (prGlueInfo && kalGetMediaStateIndicated(prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + ucChannelNum = wlanGetChannelNumberByNetwork(prGlueInfo->prAdapter, + prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex); + } + + /* + * Ready to parse the channel for bands + */ + + rlmDomainResetActiveChannel(); + rlmDomainSetRefWiphy(pWiphy); + + ch_count = 0; + for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { + sband = pWiphy->bands[band_idx]; + if (!sband) + continue; + + for (ch_idx = 0; ch_idx < sband->n_channels; ch_idx++) { + chan = &sband->channels[ch_idx]; + pCh = (rlmDomainGetActiveChannels() + ch_count); + /* Parse flags and get readable string */ + rlmDomainChannelFlagString(chan->flags, chan_flag_string, sizeof(chan_flag_string)); + + if (chan->flags & IEEE80211_CHAN_DISABLED) { + DBGLOG(RLM, INFO, "channels[%d][%d]: ch%d (freq = %d) flags=0x%x [ %s]\n", + band_idx, ch_idx, chan->hw_value, chan->center_freq, chan->flags, + chan_flag_string); + + /* Disconnect AP in the end of this function*/ + if (chan->hw_value == ucChannelNum) + fgDisconnection = TRUE; + + continue; + } + + /* Allowable channel */ + if (ch_count == MAX_SUPPORTED_CH_COUNT) { + DBGLOG(RLM, ERROR, "%s(): no buffer to store channel information.\n", __func__); + break; + } + + rlmDomainAddActiveChannel(band_idx); + + DBGLOG(RLM, INFO, "channels[%d][%d]: ch%d (freq = %d) flgs=0x%x [ %s]\n", + band_idx, ch_idx, chan->hw_value, chan->center_freq, chan->flags, + chan_flag_string); + + pCh->chNum = chan->hw_value; + pCh->flags = chan->flags; + + ch_count += 1; + } + + } + + /* Disconnect with AP if connected channel is disabled in new country */ + if (fgDisconnection) { + DBGLOG(RLM, STATE, "Disconnect! CH%d is DISABLED in this country\n", ucChannelNum); + rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, NULL, 0, FALSE, FALSE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(RLM, WARN, "disassociate error:%x\n", rStatus); + } +} +void rlmExtractChannelInfo(u32 max_ch_count, struct acctive_channel_list *prBuff) +{ + u32 ch_count, idx; + struct channel *pCh; + + prBuff->n_channels_2g = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); + prBuff->n_channels_5g = rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ); + ch_count = prBuff->n_channels_2g + prBuff->n_channels_5g; + + if (ch_count > max_ch_count) { + ch_count = max_ch_count; + DBGLOG(RLM, WARN, "%s(); active channel list is not a complete one.\n", __func__); + } + + for (idx = 0; idx < ch_count; idx++) { + pCh = &(prBuff->channels[idx]); + + pCh->chNum = (rlmDomainGetActiveChannels() + idx)->chNum; + pCh->flags = (rlmDomainGetActiveChannels() + idx)->flags; + } + +} + +const struct ieee80211_regdomain *rlmDomainSearchRegdomainFromLocalDataBase(char *alpha2) +{ +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) + u8 idx; + const struct mtk_regdomain *prRegd; + + idx = 0; + while (g_prRegRuleTable[idx]) { + prRegd = g_prRegRuleTable[idx]; + + if ((prRegd->country_code[0] == alpha2[0]) && + (prRegd->country_code[1] == alpha2[1]) && + (prRegd->country_code[2] == alpha2[2]) && + (prRegd->country_code[3] == alpha2[3])) + return prRegd->prRegdRules; + + idx++; + } + + DBGLOG(RLM, ERROR, "%s(): Error, Cannot find the correct RegDomain. country = %s.\n", + __func__, alpha2); + DBGLOG(RLM, INFO, " Set as default WW.\n"); + + return &default_regdom_ww; /*default world wide*/ +#else + return NULL; +#endif +} + + +const struct ieee80211_regdomain *rlmDomainGetLocalDefaultRegd(void) +{ +#if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) + return &default_regdom_ww; +#else + return NULL; +#endif +} +P_GLUE_INFO_T rlmDomainGetGlueInfo(void) +{ + return g_mtk_regd_control.pGlueInfo; +} + +bool rlmDomainIsEfuseUsed(void) +{ + return g_mtk_regd_control.isEfuseCountryCodeUsed; +} + +UINT_8 rlmDomainGetChannelBw(UINT_8 channelNum) +{ + UINT_32 ch_idx = 0, start_idx = 0, end_idx = 0; + UINT_8 channelBw = MAX_BW_80_80_MHZ; + struct channel *pCh; + + end_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ) + + rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ); + + for (ch_idx = start_idx; ch_idx < end_idx; ch_idx++) { + pCh = (rlmDomainGetActiveChannels() + ch_idx); + + if (pCh->chNum != channelNum) + continue; + + /* Max BW */ + if ((pCh->flags & IEEE80211_CHAN_NO_160MHZ) + == IEEE80211_CHAN_NO_160MHZ) + channelBw = MAX_BW_80MHZ; + if ((pCh->flags & IEEE80211_CHAN_NO_80MHZ) + == IEEE80211_CHAN_NO_80MHZ) + channelBw = MAX_BW_40MHZ; + if ((pCh->flags & IEEE80211_CHAN_NO_HT40) + == IEEE80211_CHAN_NO_HT40) + channelBw = MAX_BW_20MHZ; + } + + DBGLOG(RLM, INFO, "ch=%d, BW=%d\n", channelNum, channelBw); + return channelBw; +} +#endif + +WLAN_STATUS rlmDomainExtractSingleSkuInfoFromFirmware(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEventBuf) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + P_SINGLE_SKU_INFO prSkuInfo = (P_SINGLE_SKU_INFO)pucEventBuf; + + g_mtk_regd_control.en = TRUE; + + if (prSkuInfo->isEfuseValid) { + if (!rlmDomainIsUsingLocalRegDomainDataBase()) { + + DBGLOG(RLM, ERROR, "%s(): Error. In efuse mode, must use local data base.\n", __func__); + + ASSERT(0); + return WLAN_STATUS_NOT_SUPPORTED; /*force using local db if getting country code from efuse*/ + } + + rlmDomainSetCountryCode((char *)&prSkuInfo->u4EfuseCountryCode, sizeof(prSkuInfo->u4EfuseCountryCode)); + g_mtk_regd_control.isEfuseCountryCodeUsed = TRUE; + + } +#endif + + return WLAN_STATUS_SUCCESS; +} + +void rlmDomainSendInfoToFirmware(IN P_ADAPTER_T prAdapter) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + struct regulatory_request request; + struct regulatory_request *prReq = NULL; + + if (!regd_is_single_sku_en()) + return; /*not support single sku*/ + + if (g_mtk_regd_control.isEfuseCountryCodeUsed) { + request.initiator = NL80211_REGDOM_SET_BY_DRIVER; + prReq = &request; + } + + g_mtk_regd_control.pGlueInfo = prAdapter->prGlueInfo; + mtk_reg_notify(priv_to_wiphy(prAdapter->prGlueInfo), prReq); +#endif +} + +ENUM_CHNL_EXT_T rlmSelectSecondaryChannelType(P_ADAPTER_T prAdapter, ENUM_BAND_T band, u8 primary_ch) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + u8 below_ch, above_ch; + + below_ch = primary_ch - CHNL_SPAN_20; + above_ch = primary_ch + CHNL_SPAN_20; + + if (rlmDomainIsLegalChannel(prAdapter, band, above_ch)) + return CHNL_EXT_SCA; + + if (rlmDomainIsLegalChannel(prAdapter, band, below_ch)) + return CHNL_EXT_SCB; + +#endif + + return CHNL_EXT_SCN; +} + +void rlmDomainOidSetCountry(IN P_ADAPTER_T prAdapter, char *country, u8 size_of_country) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + struct regulatory_request request; + + if (rlmDomainIsUsingLocalRegDomainDataBase()) { + rlmDomainSetTempCountryCode(country, size_of_country); + request.initiator = NL80211_REGDOM_SET_BY_DRIVER; + mtk_reg_notify(priv_to_wiphy(prAdapter->prGlueInfo), &request); + } else { + DBGLOG(RLM, INFO, "%s(): Using driver hint to query CRDA getting regd.\n", __func__); + regulatory_hint(priv_to_wiphy(prAdapter->prGlueInfo), country); + } +#endif +} + +u32 rlmDomainGetCountryCode(void) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + return g_mtk_regd_control.alpha2; +#else + return 0; +#endif +} + +u32 rlmDomainGetTempCountryCode(void) +{ +#if (CFG_SUPPORT_SINGLE_SKU == 1) + return g_mtk_regd_control.tmp_alpha2; +#else + return 0; +#endif +} + +void rlmDomainAssert(BOOLEAN cond) +{ + /* bypass this check because single sku is not enable */ + if (!regd_is_single_sku_en()) + return; + + if (!cond) { + WARN_ON(1); + DBGLOG(RLM, ERROR, "[WARNING!!] RLM unexpected case.\n"); + } + +} + + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/rlm_obss.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/rlm_obss.c new file mode 100644 index 0000000000000..971b3b76bd368 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/rlm_obss.c @@ -0,0 +1,400 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rlm_obss.c#2 +*/ + +/*! \file "rlm_obss.c" +* \brief +* +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static VOID rlmObssScanTimeout(P_ADAPTER_T prAdapter, ULONG ulParamPtr); + +/******************************************************************************* +* 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 i; + + for (i = 0; i < BSS_INFO_NUM; i++) { + prBssInfo = prAdapter->aprBssInfo[i]; + + cnmTimerInitTimer(prAdapter, &prBssInfo->rObssScanTimer, + (PFN_MGMT_TIMEOUT_FUNC) rlmObssScanTimeout, (ULONG) prBssInfo); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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->aprBssInfo[prScanDoneMsg->ucBssIndex]; + ASSERT(prBssInfo); + + DBGLOG(RLM, INFO, "OBSS Scan Done (NetIdx=%d, Mode=%d)\n", + prScanDoneMsg->ucBssIndex, prBssInfo->eCurrentOPMode); + + cnmMemFree(prAdapter, prMsgHdr); + +#if CFG_ENABLE_WIFI_DIRECT + /* AP mode */ + if ((prAdapter->fgIsP2PRegistered) && + (IS_NET_ACTIVE(prAdapter, prBssInfo->ucBssIndex)) && (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->ucBssIndex); + 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) { + + DBGLOG(RLM, INFO, "Send 20/40 coexistence mgmt(20mReq=%d, NonHt=%d)\n", + prBssInfo->auc2G_20mReqChnlList[0], prBssInfo->auc2G_NonHtChnlList[0]); + + prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + + if (prMsduInfo) { + prTxFrame = (P_ACTION_20_40_COEXIST_FRAME) + ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + COPY_MAC_ADDR(prTxFrame->aucDestAddr, prBssInfo->aucBSSID); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); + + prTxFrame->ucCategory = CATEGORY_PUBLIC_ACTION; + prTxFrame->ucAction = ACTION_PUBLIC_20_40_COEXIST; + + /* To do: find correct algorithm */ + prTxFrame->rBssCoexist.ucId = ELEM_ID_20_40_BSS_COEXISTENCE; + prTxFrame->rBssCoexist.ucLength = 1; + prTxFrame->rBssCoexist.ucData = + (prBssInfo->auc2G_20mReqChnlList[0] > 0) ? BSS_COEXIST_20M_REQ : 0; + + u2PayloadLen = 2 + 3; + + if (prBssInfo->auc2G_NonHtChnlList[0] > 0) { + ASSERT(prBssInfo->auc2G_NonHtChnlList[0] <= CHNL_LIST_SZ_2G); + + prTxFrame->rChnlReport.ucId = ELEM_ID_20_40_INTOLERANT_CHNL_REPORT; + prTxFrame->rChnlReport.ucLength = prBssInfo->auc2G_NonHtChnlList[0] + 1; + prTxFrame->rChnlReport.ucRegulatoryClass = 81; /* 2.4GHz, ch1~13 */ + for (i = 0; i < prBssInfo->auc2G_NonHtChnlList[0] && i < CHNL_LIST_SZ_2G; i++) + prTxFrame->rChnlReport.aucChannelList[i] = + prBssInfo->auc2G_NonHtChnlList[i + 1]; + + u2PayloadLen += IE_SIZE(&prTxFrame->rChnlReport); + } + ASSERT((WLAN_MAC_HEADER_LEN + u2PayloadLen) <= PUBLIC_ACTION_MAX_LEN); + + /* Clear up channel lists in 2.4G band */ + prBssInfo->auc2G_20mReqChnlList[0] = 0; + prBssInfo->auc2G_NonHtChnlList[0] = 0; + + /* 4 Update information of MSDU_INFO_T */ + + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prBssInfo->ucBssIndex, + prBssInfo->prStaRecOfAP->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, + WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, NULL, MSDU_RATE_MODE_AUTO); + + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + } + } + /* end of prMsduInfo != NULL */ + if (prBssInfo->u2ObssScanInterval > 0) { + DBGLOG(RLM, EVENT, "Set OBSS timer (NetIdx=%d, %d sec)\n", + prBssInfo->ucBssIndex, prBssInfo->u2ObssScanInterval); + + cnmTimerStartTimer(prAdapter, &prBssInfo->rObssScanTimer, prBssInfo->u2ObssScanInterval * MSEC_PER_SEC); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static VOID rlmObssScanTimeout(P_ADAPTER_T prAdapter, ULONG ulParamPtr) +{ + P_BSS_INFO_T prBssInfo; + + prBssInfo = (P_BSS_INFO_T) ulParamPtr; + ASSERT(prBssInfo); + +#if CFG_ENABLE_WIFI_DIRECT + /* AP mode */ + if (prAdapter->fgIsP2PRegistered && + (IS_NET_ACTIVE(prAdapter, prBssInfo->ucBssIndex)) && (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { + + prBssInfo->fgObssActionForcedTo20M = FALSE; + + /* Check if Beacon content need to be updated */ + rlmUpdateParamsForAP(prAdapter, prBssInfo, FALSE); + + return; + } +#if CFG_SUPPORT_WFD + /* WFD streaming */ + else { + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = &prAdapter->rWifiVar.rWfdConfigureSettings; + + /* If WFD is enabled & connected */ + if (prWfdCfgSettings->ucWfdEnable) { + + /* Skip OBSS scan */ + prBssInfo->u2ObssScanInterval = 0; + DBGLOG(RLM, INFO, "WFD is running. Stop OBSS scan.\n"); + return; + } /* WFD is enabled */ + } +#endif +#endif /* end of CFG_ENABLE_WIFI_DIRECT */ + + /* STA mode */ + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE || + !RLM_NET_PARAM_VALID(prBssInfo) || prBssInfo->u2ObssScanInterval == 0) { + DBGLOG(RLM, WARN, "OBSS Scan timeout (NetIdx=%d) -- Aborted!!\n", prBssInfo->ucBssIndex); + 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->ucBssIndex); + + 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->ucBssIndex = prBssInfo->ucBssIndex; + 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, EVENT, "Timeout to trigger OBSS scan (NetIdx=%d)!!\n", + prBssInfo->ucBssIndex); +} + +VOID rlmObssAbortScan(P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prBssInfo = NULL; + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + CMD_SCAN_CANCEL rCmdScanCancel; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex); + if (prScanInfo->eCurrentState == SCAN_STATE_IDLE) { + DBGLOG(RLM, STATE, "SCAN IDLE Do Nothing\n"); + return; + } + if (prBssInfo && (prScanParam->ucSeqNum == 0x33) + && (prScanParam->fgIsObssScan == TRUE)) { + /* obss scan no scan done change IDLE */ + /* Cancel obss scan */ + rCmdScanCancel.ucSeqNum = prScanParam->ucSeqNum; + 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); + /* Init the Obss Timer */ + cnmTimerStopTimer(prAdapter, + &prBssInfo->rObssScanTimer); + prBssInfo->u2ObssScanInterval = 0; + DBGLOG(RLM, STATE, + "Obss can timeout change IDLE\n"); + scnFsmSteps(prAdapter, SCAN_STATE_IDLE); + } +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/rlm_protection.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/rlm_protection.c new file mode 100644 index 0000000000000..4bcbe5c3528f5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/rlm_protection.c @@ -0,0 +1,104 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rlm_protection.c#1 +*/ + +/*! \file "rlm_protection.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 +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/roaming_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/roaming_fsm.c new file mode 100644 index 0000000000000..04dfff1992b14 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/roaming_fsm.c @@ -0,0 +1,652 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: +*/ + +/*! \file "roaming_fsm.c" +* \brief This file defines the FSM for Roaming MODULE. +* +* This file defines the FSM for Roaming MODULE. +*/ + + +/******************************************************************************* +* C O M P I L E 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 +******************************************************************************** +*/ +static PUINT_8 apucDebugRoamingState[ROAMING_STATE_NUM] = { + (PUINT_8) DISP_STRING("IDLE"), + (PUINT_8) DISP_STRING("DECISION"), + (PUINT_8) DISP_STRING("DISCOVERY"), + (PUINT_8) DISP_STRING("ROAM") +}; + +#if 0 +static PUINT_8 apucDebugRoamingReason[ROAMING_REASON_NUM] = { + (PUINT_8) DISP_STRING("ROAMING_REASON_POOR_RCPI"), + (PUINT_8) DISP_STRING("ROAMING_REASON_TX_ERR"), + (PUINT_8) DISP_STRING("ROAMING_REASON_RETRY") +}; +#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 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 = %d\n", + kalGetTimeTick()); + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* 4 <1> Initiate FSM */ + prRoamingFsmInfo->fgIsEnableRoaming = prConnSettings->fgIsEnableRoaming; + prRoamingFsmInfo->eCurrentState = ROAMING_STATE_IDLE; + prRoamingFsmInfo->rRoamingDiscoveryUpdateTime = 0; +} /* end of roamingFsmInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Uninitialize the value in AIS_FSM_INFO_T for AIS FSM operation +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID roamingFsmUninit(IN P_ADAPTER_T prAdapter) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + + DBGLOG(ROAMING, LOUD, + "->roamingFsmUninit(): Current Time = %d\n", + kalGetTimeTick()); + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + prRoamingFsmInfo->eCurrentState = ROAMING_STATE_IDLE; +} /* end of roamingFsmUninit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Send commands to firmware +* +* @param [IN P_ADAPTER_T] prAdapter +* [IN P_ROAMING_PARAM_T] prParam +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID roamingFsmSendCmd(IN P_ADAPTER_T prAdapter, IN P_CMD_ROAMING_TRANSIT_T prTransit) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + WLAN_STATUS rStatus; + + DBGLOG(ROAMING, LOUD, + "->roamingFsmSendCmd(): Current Time = %d\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(CMD_ROAMING_TRANSIT_T), /* u4SetQueryInfoLen */ + (PUINT_8) prTransit, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + /* ASSERT(rStatus == WLAN_STATUS_PENDING); */ +} /* end of roamingFsmSendCmd() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Update the recent time when ScanDone occurred +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID roamingFsmScanResultsUpdate(IN P_ADAPTER_T prAdapter) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + + DBGLOG(ROAMING, LOUD, + "->roamingFsmScanResultsUpdate(): Current Time = %d\n", + kalGetTimeTick()); + + GET_CURRENT_SYSTIME(&prRoamingFsmInfo->rRoamingDiscoveryUpdateTime); +} /* end of roamingFsmScanResultsUpdate() */ + +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP +/*----------------------------------------------------------------------------*/ +/* +* @brief Check if need to do scan for roaming +* +* @param[out] fgIsNeedScan Set to TRUE if need to scan since +* there is roaming candidate in current scan result or skip roaming times > limit times +* @return +*/ +/*----------------------------------------------------------------------------*/ +static BOOLEAN roamingFsmIsNeedScan(IN P_ADAPTER_T prAdapter) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prRoamBSSDescList; + P_ROAM_BSS_DESC_T prRoamBssDesc; + P_BSS_INFO_T prAisBssInfo; + P_BSS_DESC_T prBssDesc; + /*CMD_SW_DBG_CTRL_T rCmdSwCtrl;*/ + CMD_ROAMING_SKIP_ONE_AP_T rCmdRoamingSkipOneAP; + BOOLEAN fgIsNeedScan, fgIsRoamingSSID; + + fgIsNeedScan = FALSE; + fgIsRoamingSSID = FALSE; /*Whether there's roaming candidate in RoamBssDescList*/ + + kalMemZero(&rCmdRoamingSkipOneAP, sizeof(CMD_ROAMING_SKIP_ONE_AP_T)); + + prAisBssInfo = prAdapter->prAisBssInfo; + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prRoamBSSDescList = &prScanInfo->rRoamBSSDescList; + /* <1> Count same BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prRoamBssDesc, prRoamBSSDescList, rLinkEntry, ROAM_BSS_DESC_T) { + if (EQUAL_SSID(prRoamBssDesc->aucSSID, + prRoamBssDesc->ucSSIDLen, + prAisBssInfo->aucSSID, prAisBssInfo->ucSSIDLen)) { + fgIsRoamingSSID = TRUE; + fgIsNeedScan = TRUE; + DBGLOG(ROAMING, INFO, "roamingFsmSteps: IsRoamingSSID:%d\n", fgIsRoamingSSID); + break; + } + } + + /* <2> Start skip roaming scan mechanism if there is no candidate in current SCAN result list */ + if (!fgIsRoamingSSID) { + prBssDesc = scanSearchBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); /* Get current BssDesc */ + if (prBssDesc) { + + /*rCmdSwCtrl.u4Id = 0xa0280000;*/ + /*rCmdSwCtrl.u4Data = 0x1;*/ + rCmdRoamingSkipOneAP.fgIsRoamingSkipOneAP = 1; + + DBGLOG(ROAMING, INFO, "roamingFsmSteps: RCPI:%d RoamSkipTimes:%d\n", + prBssDesc->ucRCPI, prAisBssInfo->ucRoamSkipTimes); + if (prBssDesc->ucRCPI > 90) { /* Set parameters related to Good Area */ + prAisBssInfo->ucRoamSkipTimes = 3; + prAisBssInfo->fgGoodRcpiArea = TRUE; + prAisBssInfo->fgPoorRcpiArea = FALSE; + } else { + if (prAisBssInfo->fgGoodRcpiArea) { + prAisBssInfo->ucRoamSkipTimes--; + } else if (prBssDesc->ucRCPI > 67) { + if (!prAisBssInfo->fgPoorRcpiArea) { /* Set parameters related to Poor Area */ + prAisBssInfo->ucRoamSkipTimes = 2; + prAisBssInfo->fgPoorRcpiArea = TRUE; + prAisBssInfo->fgGoodRcpiArea = FALSE; + } else { + prAisBssInfo->ucRoamSkipTimes--; + } + } else { + prAisBssInfo->fgPoorRcpiArea = FALSE; + prAisBssInfo->fgGoodRcpiArea = FALSE; + prAisBssInfo->ucRoamSkipTimes--; + } + } + + if (prAisBssInfo->ucRoamSkipTimes == 0) { + prAisBssInfo->ucRoamSkipTimes = 3; + prAisBssInfo->fgPoorRcpiArea = FALSE; + prAisBssInfo->fgGoodRcpiArea = FALSE; + DBGLOG(ROAMING, INFO, "roamingFsmSteps: Need Scan\n"); + fgIsNeedScan = TRUE; + } else + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_ROAMING_SKIP, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_ROAMING_SKIP_ONE_AP_T), + (PUINT_8)&rCmdRoamingSkipOneAP, NULL, 0); + } else + DBGLOG(ROAMING, WARN, "Can't find the current associated AP in BssDescList\n"); + } + + return fgIsNeedScan; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @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; + BOOLEAN fgIsNeedScan = FALSE; + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + do { + + /* Do entering Next State */ + DBGLOG(ROAMING, STATE, "[ROAMING]TRANSITION: [%s] -> [%s]\n", + apucDebugRoamingState[prRoamingFsmInfo->eCurrentState], apucDebugRoamingState[eNextState]); + + /* 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; +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + fgIsNeedScan = roamingFsmIsNeedScan(prAdapter); +#else + fgIsNeedScan = TRUE; +#endif + + GET_CURRENT_SYSTIME(&rCurrentTime); + if (CHECK_FOR_TIMEOUT(rCurrentTime, + prRoamingFsmInfo->rRoamingDiscoveryUpdateTime, + SEC_TO_SYSTIME(ROAMING_DISCOVERY_TIMEOUT_SEC)) && fgIsNeedScan) { + DBGLOG(ROAMING, LOUD, "roamingFsmSteps: DiscoveryUpdateTime Timeout\n"); + aisFsmRunEventRoamingDiscovery(prAdapter, TRUE); + } else { + DBGLOG(ROAMING, LOUD, "roamingFsmSteps: DiscoveryUpdateTime Updated\n"); + 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; + CMD_ROAMING_TRANSIT_T rTransit; + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + + prAisBssInfo = prAdapter->prAisBssInfo; + if (prAisBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + return; + + DBGLOG(ROAMING, EVENT, + "EVENT-ROAMING START: Current Time = %d\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) { + rTransit.u2Event = ROAMING_EVENT_START; + rTransit.u2Data = prAisBssInfo->ucBssIndex; + roamingFsmSendCmd(prAdapter, (P_CMD_ROAMING_TRANSIT_T) & rTransit); + + /* Step to next state */ + roamingFsmSteps(prAdapter, eNextState); + } +} /* end of roamingFsmRunEventStart() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Transit to Discovery state when deciding to find a candidate +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID roamingFsmRunEventDiscovery(IN P_ADAPTER_T prAdapter, IN P_CMD_ROAMING_TRANSIT_T prTransit) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + ENUM_ROAMING_STATE_T eNextState; + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + DBGLOG(ROAMING, EVENT, + "EVENT-ROAMING DISCOVERY: Current Time = %d\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->prAisBssInfo; + prBssDesc = scanSearchBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); + if (prBssDesc) + prBssDesc->ucRCPI = (UINT_8) (prTransit->u2Data & 0xff); + + roamingFsmSteps(prAdapter, eNextState); + } +} /* end of roamingFsmRunEventDiscovery() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Transit to Roam state after Scan Done +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID roamingFsmRunEventRoam(IN P_ADAPTER_T prAdapter) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + ENUM_ROAMING_STATE_T eNextState; + CMD_ROAMING_TRANSIT_T rTransit; + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + + DBGLOG(ROAMING, EVENT, + "EVENT-ROAMING ROAM: Current Time = %d\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) { + rTransit.u2Event = ROAMING_EVENT_ROAM; + roamingFsmSendCmd(prAdapter, (P_CMD_ROAMING_TRANSIT_T) & rTransit); + + /* Step to next state */ + roamingFsmSteps(prAdapter, eNextState); + } +} /* end of roamingFsmRunEventRoam() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Transit to Decision state as being failed to find out any candidate +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID roamingFsmRunEventFail(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Param) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + ENUM_ROAMING_STATE_T eNextState; + CMD_ROAMING_TRANSIT_T rTransit; + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + + DBGLOG(ROAMING, EVENT, + "EVENT-ROAMING FAIL: reason %x Current Time = %d\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) { + rTransit.u2Event = ROAMING_EVENT_FAIL; + rTransit.u2Data = (UINT_16) (u4Param & 0xffff); + roamingFsmSendCmd(prAdapter, (P_CMD_ROAMING_TRANSIT_T) & rTransit); + + /* Step to next state */ + roamingFsmSteps(prAdapter, eNextState); + } +} /* end of roamingFsmRunEventFail() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Transit to Idle state as beging aborted by other moduels, AIS +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID roamingFsmRunEventAbort(IN P_ADAPTER_T prAdapter) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + ENUM_ROAMING_STATE_T eNextState; + CMD_ROAMING_TRANSIT_T rTransit; + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + + DBGLOG(ROAMING, EVENT, + "EVENT-ROAMING ABORT: Current Time = %d\n", + kalGetTimeTick()); + + eNextState = ROAMING_STATE_IDLE; + /* IDLE, DECISION, DISCOVERY, ROAM -> IDLE */ + if (eNextState != prRoamingFsmInfo->eCurrentState) { + rTransit.u2Event = ROAMING_EVENT_ABORT; + roamingFsmSendCmd(prAdapter, (P_CMD_ROAMING_TRANSIT_T) & rTransit); + + /* Step to next state */ + roamingFsmSteps(prAdapter, eNextState); + } +} /* end of roamingFsmRunEventAbort() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process events from firmware +* +* @param [IN P_ADAPTER_T] prAdapter +* [IN P_ROAMING_PARAM_T] prParam +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS roamingFsmProcessEvent(IN P_ADAPTER_T prAdapter, IN P_CMD_ROAMING_TRANSIT_T prTransit) +{ + DBGLOG(ROAMING, LOUD, + "ROAMING Process Events: Current Time = %d\n", + kalGetTimeTick()); + + if (prTransit->u2Event == ROAMING_EVENT_DISCOVERY) { + roamingFsmRunEventDiscovery(prAdapter, prTransit); + +#if 0 + DBGLOG(ROAMING, INFO, "RX ROAMING_EVENT_DISCOVERY RCPI[%d] Thr[%d] Reason[%d] Time[%ld]\n", + prTransit->u2Data, + prTransit->u2RcpiLowThreshold, + prTransit->eReason, + prTransit->u4RoamingTriggerTime); +#endif + } + + return WLAN_STATUS_SUCCESS; +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/rsn.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/rsn.c new file mode 100644 index 0000000000000..d6175d738ada5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/rsn.c @@ -0,0 +1,3116 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: mgmt/rsn.c#3 +*/ + +/*! \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. +*/ + + +/******************************************************************************* +* C O M P I L E 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 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_32 u4GroupMgmtSuite = 0; + UINT_16 u2PairSuiteCount = 0; + UINT_16 u2AuthSuiteCount = 0; + PUINT_8 pucPairSuite = NULL; + PUINT_8 pucAuthSuite = NULL; + PUINT_8 cp; +#if CFG_SUPPORT_CFG80211_AUTH + UINT_16 u2DesiredPmkidCnt = 0; + UINT_16 u2SupportedPmkidCnt = 0; +#endif + + 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); + cp += 2; + u4RemainRsnIeLen -= 2; + + if (u4RemainRsnIeLen == 0) + break; +#if CFG_SUPPORT_CFG80211_AUTH + /* 9.4.2.25.5 PMKID + * The PMKID Count and List fields are used only in + * the RSNE in the (Re)Association Request frame to an AP + * and in FT authentication sequence frames. + */ + /* Parse PMKID count field */ + if (u4RemainRsnIeLen < 2) { + DBGLOG(RSN, TRACE, + "Fail to parse RSN IE in PMKID (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + WLAN_GET_FIELD_16(cp, &u2DesiredPmkidCnt); + cp += 2; + u4RemainRsnIeLen -= 2; + + if (u2DesiredPmkidCnt > MAX_NUM_SUPPORTED_PMKID) { + u2SupportedPmkidCnt = MAX_NUM_SUPPORTED_PMKID; + DBGLOG(RSN, WARN, + "Support maximum PMKID Cnt = %d with desired PMKID Cnt = %d\n", + MAX_NUM_SUPPORTED_PMKID, u2DesiredPmkidCnt); + } else + u2SupportedPmkidCnt = u2DesiredPmkidCnt; + + /* Parse PMKID List field */ + i = (uint32_t) u2DesiredPmkidCnt * RSN_PMKID_LEN; + if (u4RemainRsnIeLen < (int32_t) i) { + DBGLOG(RSN, TRACE, + "Fail to parse RSN IE in pairwise cipher suite list (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + if (u2SupportedPmkidCnt > 0) { + kalMemCopy(prRsnInfo->aucPmkidList, cp, + (u2SupportedPmkidCnt * RSN_PMKID_LEN)); + + DBGLOG(RSN, INFO, "== Dump cached PMKIDs ==\n"); + DBGLOG_MEM8(RSN, INFO, prRsnInfo->aucPmkidList, + (u2SupportedPmkidCnt * RSN_PMKID_LEN)); + } + cp += u2DesiredPmkidCnt * RSN_PMKID_LEN; + u4RemainRsnIeLen -= + (int32_t)(u2DesiredPmkidCnt * RSN_PMKID_LEN); + + if (u4RemainRsnIeLen == 0) + break; +#endif + + /* Parse Group Mgmt Cipher Suite field */ + if (u4RemainRsnIeLen < 4) { + DBGLOG(RSN, TRACE, + "Fail to parse RSN IE in GroupMgmtCipher (IELen: %d)\n", + prInfoElem->ucLength); + /* Continued to connect + * when PMKID List field is truncated. + */ + break; + } + WLAN_GET_FIELD_32(cp, &u4GroupMgmtSuite); + } while (FALSE); + + /* Save the RSN information for the BSS. */ + prRsnInfo->ucElemId = ELEM_ID_RSN; + + prRsnInfo->ucRsneLen = prInfoElem->ucLength; + + prRsnInfo->u2Version = u2Version; + + prRsnInfo->u4GroupKeyCipherSuite = u4GroupSuite; + + prRsnInfo->u4GroupMgmtKeyCipherSuite = u4GroupMgmtSuite; +#if CFG_SUPPORT_CFG80211_AUTH + prRsnInfo->u2PmkidCnt = u2SupportedPmkidCnt; +#endif + + DBGLOG(RSN, LOUD, + "RSN: version %d, group mgmt key cipher suite %02x-%02x-%02x-%02x\n", + u2Version, (UCHAR) (u4GroupMgmtSuite & 0x000000FF), + (UCHAR) ((u4GroupMgmtSuite >> 8) & 0x000000FF), + (UCHAR) ((u4GroupMgmtSuite >> 16) & 0x000000FF), + (UCHAR) ((u4GroupMgmtSuite >> 24) & 0x000000FF)); + + 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; + prRsnInfo->fgRsnCapPresent = TRUE; + 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; + UINT_8 ucBssIndex; + BOOLEAN fgIsWpsActive = (BOOLEAN) FALSE; + + DEBUGFUNC("rsnPerformPolicySelection"); + + ASSERT(prBss); + + DBGLOG(RSN, TRACE, "rsnPerformPolicySelection\n"); + /* Todo:: */ + ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + + prBss->u4RsnSelectedPairwiseCipher = 0; + prBss->u4RsnSelectedGroupCipher = 0; + prBss->u4RsnSelectedAKMSuite = 0; + prBss->ucEncLevel = 0; + + prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = FALSE; + +#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, INFO, "-- 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, INFO, "-- No Protected BSS\n"); + return TRUE; + } + DBGLOG(RSN, INFO, "-- Protected BSS but No need\n"); + return FALSE; + } + + /* Protection is required in this BSS. */ + if ((prBss->u2CapInfo & CAP_INFO_PRIVACY) != 0) { + if (secEnabledInAis(prAdapter) == FALSE) { + DBGLOG(RSN, INFO, "-- 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, INFO, "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 CFG_SUPPORT_SAE + || prAdapter->rWifiVar.rConnSettings.eAuthMode + == AUTH_MODE_WPA2_SAE +#endif + ) { + + if (prBss->fgIERSN) { + prBssRsnInfo = &prBss->rRSNInfo; + } else { + DBGLOG(RSN, INFO, "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, INFO, "-- 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, INFO, "-- WEP-only legacy BSS\n"); + return TRUE; + } + + if (!rsnIsSuitableBSS(prAdapter, prBssRsnInfo)) { + DBGLOG(RSN, INFO, "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) { +#if CFG_SUPPORT_SUITB + case RSN_CIPHER_SUITE_GCMP_256: + if (prAdapter->rWifiVar.rConnSettings.eEncStatus == + ENUM_ENCRYPTION4_ENABLED) + fgSuiteSupported = TRUE; + break; +#endif + 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%08x\n", + prAdapter->rWifiVar.rConnSettings.eEncStatus, + prBssRsnInfo->u4PairwiseKeyCipherSuiteCount, + prBssRsnInfo->au4PairwiseKeyCipherSuite[0]); + /* Select pairwise/group ciphers */ + switch (prAdapter->rWifiVar.rConnSettings.eEncStatus) { +#if CFG_SUPPORT_SUITB + case ENUM_ENCRYPTION4_ENABLED: + for (i = 0; + i < prBssRsnInfo->u4PairwiseKeyCipherSuiteCount; + i++) { + /* TODO: WTBL cipher filed cannot 1-1 mapping + * to spec cipher suite number + */ + if (prBssRsnInfo->au4PairwiseKeyCipherSuite[i] + == RSN_CIPHER_SUITE_GCMP_256) + u4PairwiseCipher = prBssRsnInfo + ->au4PairwiseKeyCipherSuite[i]; + } + u4GroupCipher = prBssRsnInfo->u4GroupKeyCipherSuite; + break; +#endif + case ENUM_ENCRYPTION3_ENABLED: + for (i = 0; i < prBssRsnInfo->u4PairwiseKeyCipherSuiteCount; i++) { + if (GET_SELECTOR_TYPE(prBssRsnInfo->au4PairwiseKeyCipherSuite[i]) + == CIPHER_SUITE_CCMP) { + u4PairwiseCipher = prBssRsnInfo->au4PairwiseKeyCipherSuite[i]; + } + } + u4GroupCipher = prBssRsnInfo->u4GroupKeyCipherSuite; + break; + + case ENUM_ENCRYPTION2_ENABLED: + for (i = 0; i < prBssRsnInfo->u4PairwiseKeyCipherSuiteCount; i++) { + if (GET_SELECTOR_TYPE(prBssRsnInfo->au4PairwiseKeyCipherSuite[i]) + == CIPHER_SUITE_TKIP) { + u4PairwiseCipher = prBssRsnInfo->au4PairwiseKeyCipherSuite[i]; + } + } + if (GET_SELECTOR_TYPE(prBssRsnInfo + ->u4GroupKeyCipherSuite) == CIPHER_SUITE_CCMP) + DBGLOG(RSN, TRACE, "Cannot join CCMP BSS\n"); + else + u4GroupCipher = prBssRsnInfo->u4GroupKeyCipherSuite; + break; + + case ENUM_ENCRYPTION1_ENABLED: + for (i = 0; i < prBssRsnInfo->u4PairwiseKeyCipherSuiteCount; i++) { + if (GET_SELECTOR_TYPE(prBssRsnInfo->au4PairwiseKeyCipherSuite[i]) + == CIPHER_SUITE_WEP40 || + GET_SELECTOR_TYPE(prBssRsnInfo->au4PairwiseKeyCipherSuite[i]) + == CIPHER_SUITE_WEP104) { + u4PairwiseCipher = prBssRsnInfo->au4PairwiseKeyCipherSuite[i]; + } + } + if (GET_SELECTOR_TYPE(prBssRsnInfo + ->u4GroupKeyCipherSuite) == CIPHER_SUITE_CCMP || + GET_SELECTOR_TYPE(prBssRsnInfo + ->u4GroupKeyCipherSuite) == CIPHER_SUITE_TKIP) { + DBGLOG(RSN, TRACE, "Cannot join CCMP/TKIP BSS\n"); + } else { + u4GroupCipher = prBssRsnInfo->u4GroupKeyCipherSuite; + } + break; + + default: + break; + } + } + + /* Exception handler */ + /* If we cannot find proper pairwise and group cipher suites to join the */ + /* BSS, do not check the supported AKM suites. */ + if (u4PairwiseCipher == 0 || u4GroupCipher == 0) { + DBGLOG(RSN, TRACE, + "Failed to select pairwise/group cipher (0x%08x/0x%08x)\n", + u4PairwiseCipher, u4GroupCipher); + return FALSE; + } +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && + (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType == NETWORK_TYPE_P2P)) { + if (u4PairwiseCipher != RSN_CIPHER_SUITE_CCMP || + u4GroupCipher != RSN_CIPHER_SUITE_CCMP || u4AkmSuite != RSN_AKM_SUITE_PSK) { + DBGLOG(RSN, TRACE, + "Failed to select pairwise/group cipher for P2P network (0x%08x/0x%08x)\n", + u4PairwiseCipher, u4GroupCipher); + return FALSE; + } + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + if (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType == NETWORK_TYPE_BOW) { + 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%08x/0x%08x)\n", + u4PairwiseCipher, u4GroupCipher); + return FALSE; + } + } +#endif + + /* Verify if selected pairwisse cipher is supported */ + fgSuiteSupported = rsnSearchSupportedCipher(prAdapter, u4PairwiseCipher, &i); + + /* Verify if selected group cipher is supported */ + if (fgSuiteSupported) + fgSuiteSupported = rsnSearchSupportedCipher(prAdapter, u4GroupCipher, &i); + + if (!fgSuiteSupported) { + DBGLOG(RSN, TRACE, + "Failed to support selected pairwise/group cipher (0x%08x/0x%08x)\n", + u4PairwiseCipher, u4GroupCipher); + return FALSE; + } + + /* Select AKM */ + /* If the driver cannot support any authentication suites advertised in + * the given BSS, we fail to perform RSNA policy selection. + */ + /* Attempt to find any overlapping supported AKM suite. */ +#if CFG_SUPPORT_802_11W + if (i != 0) + for (i = (prBssRsnInfo->u4AuthKeyMgtSuiteCount - 1); i >= 0; i--) { +#else + for (i = 0; i < prBssRsnInfo->u4AuthKeyMgtSuiteCount; i++) { +#endif + if (rsnSearchAKMSuite(prAdapter, prBssRsnInfo->au4AuthKeyMgtSuite[i], &j)) { + u4AkmSuite = prBssRsnInfo->au4AuthKeyMgtSuite[i]; + break; + } + } + + if (u4AkmSuite == 0) { + DBGLOG(RSN, TRACE, "Cannot support any AKM suites\n"); + return FALSE; + } + + DBGLOG(RSN, TRACE, + "Selected pairwise/group cipher: %02x-%02x-%02x-%02x/%02x-%02x-%02x-%02x\n", + (UINT_8) (u4PairwiseCipher & 0x000000FF), + (UINT_8) ((u4PairwiseCipher >> 8) & 0x000000FF), + (UINT_8) ((u4PairwiseCipher >> 16) & 0x000000FF), + (UINT_8) ((u4PairwiseCipher >> 24) & 0x000000FF), + (UINT_8) (u4GroupCipher & 0x000000FF), (UINT_8) ((u4GroupCipher >> 8) & 0x000000FF), + (UINT_8) ((u4GroupCipher >> 16) & 0x000000FF), (UINT_8) ((u4GroupCipher >> 24) & 0x000000FF)); + + DBGLOG(RSN, TRACE, "Selected AKM suite: %02x-%02x-%02x-%02x\n", + (UINT_8) (u4AkmSuite & 0x000000FF), + (UINT_8) ((u4AkmSuite >> 8) & 0x000000FF), + (UINT_8) ((u4AkmSuite >> 16) & 0x000000FF), (UINT_8) ((u4AkmSuite >> 24) & 0x000000FF)); + +#if CFG_SUPPORT_802_11W + DBGLOG(RSN, TRACE, "[MFP] MFP setting = %d\n ", + kalGetMfpSetting(prAdapter->prGlueInfo)); + + if (kalGetMfpSetting(prAdapter->prGlueInfo) == RSN_AUTH_MFP_REQUIRED) { + if (!prBssRsnInfo->fgRsnCapPresent) { + DBGLOG(RSN, TRACE, "[MFP] Skip RSN IE, No MFP Required Capability.\n"); + return FALSE; + } else if (!(prBssRsnInfo->u2RsnCap & ELEM_WPA_CAP_MFPC)) { + DBGLOG(RSN, TRACE, "[MFP] 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 & + (ELEM_WPA_CAP_MFPR | ELEM_WPA_CAP_MFPC)) + prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection + = TRUE; + } else { + if (prBssRsnInfo->fgRsnCapPresent && (prBssRsnInfo->u2RsnCap & ELEM_WPA_CAP_MFPR)) { + DBGLOG(RSN, INFO, "[MFP] Try to join even MFP Required bit set\n"); + return FALSE; + } + prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = FALSE; + } + DBGLOG(RSN, TRACE, "[MFP] fgMgmtProtection = %d\n ", prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection); + + prAdapter->rWifiVar.rAisSpecificBssInfo.fgAPApplyPmfReq = FALSE; + if (prBssRsnInfo->fgRsnCapPresent && (prBssRsnInfo->u2RsnCap & ELEM_WPA_CAP_MFPR)) + prAdapter->rWifiVar.rAisSpecificBssInfo.fgAPApplyPmfReq = TRUE; +#endif + + if (GET_SELECTOR_TYPE(u4GroupCipher) == CIPHER_SUITE_CCMP) { + prBss->ucEncLevel = 3; +#if CFG_SUPPORT_SUITB + } else if (u4GroupCipher == RSN_CIPHER_SUITE_GCMP_256) { + prBss->ucEncLevel = 4; +#endif + } 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; + UINT_8 ucBssIndex; + + DEBUGFUNC("rsnGenerateWpaNoneIE"); + + ASSERT(prMsduInfo); + + if (prAdapter->rWifiVar.rConnSettings.eAuthMode != AUTH_MODE_WPA_NONE) + return; + + ucBssIndex = prMsduInfo->ucBssIndex; + + if (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType != NETWORK_TYPE_AIS) + return; + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (ULONG) 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 = pucBuffer + sizeof(WPA_INFO_ELEM_T); + + /* Fill the Group Key Cipher Suite field as the same in pair-wise key. */ + WLAN_SET_FIELD_32(&prWpaIE->u4GroupKeyCipherSuite, u4Suite); + ucExpendedLen += 4; + + /* Fill the Pairwise Key Cipher Suite Count field. */ + WLAN_SET_FIELD_16(&prWpaIE->u2PairwiseKeyCipherSuiteCount, u2SuiteCount); + ucExpendedLen += 2; + + cp2 = cp; + + /* Fill the Authentication and Key Management Suite List field. */ + u2SuiteCount = 0; + cp += 2; + + if (rsnSearchAKMSuite(prAdapter, WPA_AKM_SUITE_802_1X, &i)) + u4Suite = WPA_AKM_SUITE_802_1X; + else if (rsnSearchAKMSuite(prAdapter, WPA_AKM_SUITE_PSK, &i)) + u4Suite = WPA_AKM_SUITE_PSK; + else + u4Suite = WPA_AKM_SUITE_NONE; + + /* This shall be the only available value for current implementation */ + ASSERT(u4Suite == WPA_AKM_SUITE_NONE); + + WLAN_SET_FIELD_32(cp, u4Suite); + u2SuiteCount++; + ucExpendedLen += 4; + cp += 4; + + /* Fill the Authentication and Key Management Suite Count field. */ + WLAN_SET_FIELD_16(cp2, u2SuiteCount); + ucExpendedLen += 2; + + /* Fill the Length field. */ + prWpaIE->ucLength = (UINT_8) ucExpendedLen; + + /* Increment the total IE length for the Element ID and Length fields. */ + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + +} /* rsnGenerateWpaNoneIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to generate WPA IE for +* associate request frame. +* +* \param[in] prCurrentBss The Selected BSS description +* +* \retval The append WPA IE length +* +* \note +* Called by: AIS module, Associate request +*/ +/*----------------------------------------------------------------------------*/ +VOID rsnGenerateWPAIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + PUCHAR cp; + PUINT_8 pucBuffer; + UINT_8 ucBssIndex; + P_BSS_INFO_T prBssInfo; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo; + + DEBUGFUNC("rsnGenerateWPAIE"); + + ASSERT(prMsduInfo); + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (ULONG) prMsduInfo->u2FrameLength); + + ASSERT(pucBuffer); + + ucBssIndex = prMsduInfo->ucBssIndex; + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo[prBssInfo->u4PrivateData]; + + /* if (eNetworkId != NETWORK_TYPE_AIS_INDEX) */ + /* return; */ + +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered && + GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType == NETWORK_TYPE_P2P && + kalP2PGetTkipCipher(prAdapter->prGlueInfo, (UINT_8) prBssInfo->u4PrivateData)) || + (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType == NETWORK_TYPE_AIS && + (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA || + prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA_PSK))) { +#else + if (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType == NETWORK_TYPE_AIS && + (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA || + prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA_PSK)) { +#endif + if (prAdapter->fgIsP2PRegistered && prP2pSpecificBssInfo && (prP2pSpecificBssInfo->u2WpaIeLen != 0)) { + kalMemCopy(pucBuffer, prP2pSpecificBssInfo->aucWpaIeBuffer, prP2pSpecificBssInfo->u2WpaIeLen); + prMsduInfo->u2FrameLength += prP2pSpecificBssInfo->u2WpaIeLen; + return; + } + /* Construct a WPA IE for association request frame. */ + WPA_IE(pucBuffer)->ucElemId = ELEM_ID_WPA; + WPA_IE(pucBuffer)->ucLength = ELEM_ID_WPA_LEN_FIXED; + WPA_IE(pucBuffer)->aucOui[0] = 0x00; + WPA_IE(pucBuffer)->aucOui[1] = 0x50; + WPA_IE(pucBuffer)->aucOui[2] = 0xF2; + WPA_IE(pucBuffer)->ucOuiType = VENDOR_OUI_TYPE_WPA; + WLAN_SET_FIELD_16(&WPA_IE(pucBuffer)->u2Version, 1); + +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered + && GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType == NETWORK_TYPE_P2P) { + WLAN_SET_FIELD_32(&WPA_IE(pucBuffer)->u4GroupKeyCipherSuite, WPA_CIPHER_SUITE_TKIP); + } else +#endif + WLAN_SET_FIELD_32(&WPA_IE(pucBuffer)->u4GroupKeyCipherSuite, + prAdapter->prAisBssInfo->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 + && GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType == NETWORK_TYPE_P2P) { + WLAN_SET_FIELD_32(cp, WPA_CIPHER_SUITE_TKIP); + } else +#endif + WLAN_SET_FIELD_32(cp, prAdapter->prAisBssInfo->u4RsnSelectedPairwiseCipher); + cp = pucBuffer + sizeof(WPA_INFO_ELEM_T); + + WLAN_SET_FIELD_16(cp, 1); + cp += 2; +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered + && GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType == NETWORK_TYPE_P2P) { + WLAN_SET_FIELD_32(cp, WPA_AKM_SUITE_PSK); + } else +#endif + WLAN_SET_FIELD_32(cp, prAdapter->prAisBssInfo->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) +{ + PUCHAR cp; + /* UINT_8 ucExpendedLen = 0; */ + PUINT_8 pucBuffer; + UINT_8 ucBssIndex; + P_BSS_INFO_T prBssInfo; +#if !CFG_SUPPORT_CFG80211_AUTH + UINT_32 u4Entry; + P_STA_RECORD_T prStaRec; +#endif +#if CFG_SUPPORT_CFG80211_AUTH + UINT_32 u4GroupMgmt = 0; + P_CONNECTION_SETTINGS_T prConnSettings = NULL; + + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + ASSERT(prConnSettings); +#endif + + DEBUGFUNC("rsnGenerateRSNIE"); + + ASSERT(prMsduInfo); + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (ULONG) prMsduInfo->u2FrameLength); + + ASSERT(pucBuffer); + + /* Todo:: network id */ + ucBssIndex = prMsduInfo->ucBssIndex; + prBssInfo = prAdapter->aprBssInfo[ucBssIndex]; + ASSERT(prBssInfo); + + if ( +#if CFG_ENABLE_WIFI_DIRECT + ((prAdapter->fgIsP2PRegistered) && + (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType == NETWORK_TYPE_P2P) + && (kalP2PGetCcmpCipher(prAdapter->prGlueInfo, (UINT_8) prBssInfo->u4PrivateData))) || +#endif +#if CFG_ENABLE_BT_OVER_WIFI + (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType == NETWORK_TYPE_BOW) + || +#endif + (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType == + NETWORK_TYPE_AIS /* prCurrentBss->fgIERSN */ && + ((prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) + || (prAdapter->rWifiVar.rConnSettings.eAuthMode == + AUTH_MODE_WPA2_PSK) +#if CFG_SUPPORT_CFG80211_AUTH + || (prAdapter->rWifiVar.rConnSettings.eAuthMode == + AUTH_MODE_WPA2_SAE) +#endif + ))) { + /* Construct a RSN IE for association request frame. */ + RSN_IE(pucBuffer)->ucElemId = ELEM_ID_RSN; +#if CFG_SUPPORT_CFG80211_AUTH + RSN_IE(pucBuffer)->ucLength = + prAdapter->prGlueInfo->rWpaInfo.ucRsneLen; + if (RSN_IE(pucBuffer)->ucLength < 2) { + if ((prBssInfo->eCurrentOPMode == + OP_MODE_ACCESS_POINT) || + (prBssInfo->eNetworkType == NETWORK_TYPE_P2P)) { + RSN_IE(pucBuffer)->ucLength = + ELEM_ID_RSN_LEN_FIXED; + } else { + DBGLOG(RSN, WARN, + "Desired RSN IE from upper is too short (length=%d)\n", + RSN_IE(pucBuffer)->ucLength); + return; + } + } +#else + RSN_IE(pucBuffer)->ucLength = ELEM_ID_RSN_LEN_FIXED; +#endif + WLAN_SET_FIELD_16(&RSN_IE(pucBuffer)->u2Version, 1); /* Version */ + WLAN_SET_FIELD_32(&RSN_IE(pucBuffer)->u4GroupKeyCipherSuite, + GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)-> + 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, GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->u4RsnSelectedPairwiseCipher); + cp = pucBuffer + sizeof(RSN_INFO_ELEM_T); + WLAN_SET_FIELD_16(cp, 1); /* AKM suite count */ + cp += 2; + /* AKM suite */ + WLAN_SET_FIELD_32(cp, GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->u4RsnSelectedAKMSuite); + cp += 4; +#if CFG_SUPPORT_802_11W + /* Capabilities */ + WLAN_SET_FIELD_16(cp, GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->u2RsnSelectedCapInfo); + DBGLOG(RSN, TRACE, + "Gen RSN IE = %x\n", GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->u2RsnSelectedCapInfo); + if (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType == NETWORK_TYPE_AIS) { + if (kalGetRsnIeMfpCap(prAdapter->prGlueInfo) == RSN_AUTH_MFP_REQUIRED) { + WLAN_SET_FIELD_16(cp, ELEM_WPA_CAP_MFPC | ELEM_WPA_CAP_MFPR); /* Capabilities */ + DBGLOG(RSN, TRACE, "RSN_AUTH_MFP - MFPC & MFPR\n"); + } else if (kalGetRsnIeMfpCap(prAdapter->prGlueInfo) == RSN_AUTH_MFP_OPTIONAL) { + WLAN_SET_FIELD_16(cp, ELEM_WPA_CAP_MFPC); /* Capabilities */ + DBGLOG(RSN, TRACE, "RSN_AUTH_MFP - MFPC\n"); + } else { + DBGLOG(RSN, TRACE, "!RSN_AUTH_MFP - No MFPC!\n"); + } + } else if ((GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType == NETWORK_TYPE_P2P) && + (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eCurrentOPMode == + (UINT_8) OP_MODE_ACCESS_POINT)) { + /* AP PMF */ + /* for AP mode, keep origin RSN IE content w/o update */ + } +#else + /* Capabilities */ + WLAN_SET_FIELD_16(cp, GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->u2RsnSelectedCapInfo); +#endif +#if CFG_SUPPORT_802_11W + if (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType + == NETWORK_TYPE_AIS) { + /* MFP Capabilities */ + if (kalGetRsnIeMfpCap(prAdapter->prGlueInfo) + == RSN_AUTH_MFP_REQUIRED) { + WLAN_SET_FIELD_16(cp, + ELEM_WPA_CAP_MFPC | ELEM_WPA_CAP_MFPR); + DBGLOG(RSN, TRACE, + "RSN_AUTH_MFP - MFPC & MFPR\n"); + } else if (kalGetRsnIeMfpCap( + prAdapter->prGlueInfo) + == RSN_AUTH_MFP_OPTIONAL) { + WLAN_SET_FIELD_16(cp, ELEM_WPA_CAP_MFPC); + DBGLOG(RSN, TRACE, "RSN_AUTH_MFP - MFPC\n"); + } else { + DBGLOG(RSN, TRACE, "!RSN_AUTH_MFP- No MFPC!\n"); + } + } else if ((GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex) + ->eNetworkType == NETWORK_TYPE_P2P) && + (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex) + ->eCurrentOPMode == (UINT_8) OP_MODE_ACCESS_POINT)) { + /* AP PMF */ + /* for AP mode, keep origin RSN IE content w/o update */ + } +#endif + cp += 2; + +#if CFG_SUPPORT_CFG80211_AUTH + /*Fill PMKID and Group Management Cipher for AIS */ + if (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType + == NETWORK_TYPE_AIS) { + /* Fill PMKID Count field */ + WLAN_SET_FIELD_16(cp, + prConnSettings->rRsnInfo.u2PmkidCnt); + cp += 2; + + /* Fill PMKID List field */ + if (prConnSettings->rRsnInfo.u2PmkidCnt > 0) { + kalMemCopy(cp, + &prConnSettings->rRsnInfo.aucPmkidList, + (prConnSettings + ->rRsnInfo.u2PmkidCnt * RSN_PMKID_LEN)); + DBGLOG(RSN, INFO, + "Dump PMDID when gen rsn ie & len:%d\n", + RSN_IE(pucBuffer)->ucLength); + DBGLOG_MEM8(RSN, INFO, cp, + (prConnSettings + ->rRsnInfo.u2PmkidCnt * RSN_PMKID_LEN)); + } + + cp += (prConnSettings + ->rRsnInfo.u2PmkidCnt * RSN_PMKID_LEN); + +#if CFG_SUPPORT_802_11W + /* Fill Group Management Cipher field */ + u4GroupMgmt = + prAdapter->prGlueInfo->rWpaInfo.u4CipherGroupMgmt; + WLAN_SET_FIELD_32(cp, u4GroupMgmt); +#endif + } +#else + if (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType == NETWORK_TYPE_AIS) + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType == NETWORK_TYPE_AIS + && rsnSearchPmkidEntry(prAdapter, prStaRec->aucMacAddr, &u4Entry)) { +#if 0 + 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))); +#endif + 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 + if ((GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType == NETWORK_TYPE_AIS) + && prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection + && (kalGetMfpSetting(prAdapter->prGlueInfo) != RSN_AUTH_MFP_DISABLED) + /* (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) */ + ) { + cp += 2; + RSN_IE(pucBuffer)->ucLength += 2; + } +#endif + } + +#if CFG_SUPPORT_802_11W + if ((GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType == NETWORK_TYPE_AIS) + && prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection + && (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 +#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, + P_STA_RECORD_T prStaRec, PUINT_16 pu2StatusCode) +{ + + RSN_INFO_T rRsnIe; + P_BSS_INFO_T prBssInfo; + UINT_8 i; + UINT_16 statusCode; + + ASSERT(prAdapter); + ASSERT(prIe); + ASSERT(prStaRec); + 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; + +#if CFG_SUPPORT_802_11W + /* AP PMF */ + /* 1st check: if already PMF connection, reject assoc req: error 30 ASSOC_REJECTED_TEMPORARILY */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + *pu2StatusCode = STATUS_CODE_ASSOC_REJECTED_TEMPORARILY; + return; + } + + /* if RSN capability not exist, just return */ + if (!rRsnIe.fgRsnCapPresent) { + *pu2StatusCode = WLAN_STATUS_SUCCESS; + return; + } + + prStaRec->rPmfCfg.fgMfpc = (rRsnIe.u2RsnCap & ELEM_WPA_CAP_MFPC) ? 1 : 0; + prStaRec->rPmfCfg.fgMfpr = (rRsnIe.u2RsnCap & ELEM_WPA_CAP_MFPR) ? 1 : 0; + + for (i = 0; i < rRsnIe.u4AuthKeyMgtSuiteCount; i++) { + if ((rRsnIe.au4AuthKeyMgtSuite[i] == RSN_AKM_SUITE_802_1X_SHA256) || + (rRsnIe.au4AuthKeyMgtSuite[i] == RSN_AKM_SUITE_PSK_SHA256)) { + DBGLOG(RSN, INFO, "STA SHA256 support\n"); + prStaRec->rPmfCfg.fgSha256 = TRUE; + break; + } + } + + DBGLOG(RSN, INFO, "STA Assoc req mfpc:%d, mfpr:%d, sha256:%d, bssIndex:%d, applyPmf:%d\n", + prStaRec->rPmfCfg.fgMfpc, prStaRec->rPmfCfg.fgMfpr, + prStaRec->rPmfCfg.fgSha256, prStaRec->ucBssIndex, prStaRec->rPmfCfg.fgApplyPmf); + + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + /* if PMF validation fail, return success as legacy association */ + statusCode = rsnPmfCapableValidation(prAdapter, prBssInfo, prStaRec); + *pu2StatusCode = statusCode; +#endif + } + +} +#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->prAisBssInfo->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_BSS_INFO_T prAisBssInfo; + + DEBUGFUNC("rsnSelectPmkidCandidateList"); + + ASSERT(prBssDesc); + + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + prAisBssInfo = prAdapter->prAisBssInfo; + + /* 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 ULONG ulParamPtr) +{ + 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->prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED && + prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) { + rsnGeneratePmkidIndication(prAdapter); + } +} /* end of rsnIndicatePmkidCand() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to check the BSS Desc at scan result +* with pre-auth cap at wpa2 mode. If there +* is candicate that no cache entry is available, then +* add a new entry for the new candicate in the PMKID cache +* and set the PMKID indication flag to TRUE. +* +* \param[in] prBss The BSS Desc at scan result +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rsnCheckPmkidCache(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBss) +{ + P_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->prAisBssInfo; + 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 " %x\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 */ + +#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->ucBssIndex != prAdapter->prAisBssInfo->ucBssIndex) + return; + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (ULONG) 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) +{ + /* caution: prStaRec might be null ! */ + if (prStaRec) { + if (GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex)->eNetworkType == (UINT_8) NETWORK_TYPE_AIS) { + return prAdapter->rWifiVar.rAisSpecificBssInfo.fgBipKeyInstalled; + } else if ((GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex)->eNetworkType == NETWORK_TYPE_P2P) && + (GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex)->eCurrentOPMode == + OP_MODE_ACCESS_POINT)) { + DBGLOG(RSN, INFO, "AP-STA PMF capable:%d\n", prStaRec->rPmfCfg.fgApplyPmf); + return prStaRec->rPmfCfg.fgApplyPmf; + } else { + return FALSE; + } + } 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))) { + DBGLOG(RSN, INFO, "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); +#if 1 + if (prAdapter->prAisBssInfo->eConnectionState == + PARAM_MEDIA_STATE_CONNECTED /* 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) + return 0; + prAisAbortMsg->rMsgHdr.eMsgId = MID_SAA_AIS_FSM_ABORT; + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_DISASSOCIATED; + prAisAbortMsg->fgDelayIndication = FALSE; +#if CFG_DISCONN_DEBUG_FEATURE + g_rDisconnInfoTemp.ucTrigger = + DISCONNECT_TRIGGER_ACTIVE; +#endif + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); + } +#else + /* Re-connect */ + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); +#endif + 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, IN ULONG ulParamPtr) +{ + 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->prAisBssInfo; + ASSERT(prBssInfo); + + prBssSpecInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + ASSERT(prBssSpecInfo); + + DBGLOG(RSN, INFO, "MFP: Start Sa Query\n"); + + if (prBssInfo->prStaRecOfAP == NULL) { + if (prBssSpecInfo->u4SaQueryCount > 0) + rsnStopSaQuery(prAdapter); + DBGLOG(RSN, INFO, "MFP: unassociated AP!\n"); + return; + } + + if (prBssSpecInfo->u4SaQueryCount > 0 && rsnCheckSaQueryTimeout(prAdapter)) { + DBGLOG(RSN, INFO, + "MFP: u4SaQueryCount count =%d\n", + prBssSpecInfo->u4SaQueryCount); + return; + } + + prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + prTxFrame = (P_ACTION_SA_QUERY_FRAME) + ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + if (rsnCheckBipKeyInstalled(prAdapter, prBssInfo->prStaRecOfAP)) + 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_QUERY_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"); + cnmMgtPktFree(prAdapter, prMsduInfo); + 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) { + kalMemFree(pucTmp, VIR_MEM_TYPE, (prBssSpecInfo->u4SaQueryCount - 1) * ACTION_SA_QUERY_TR_ID_LEN); + DBGLOG(RSN, INFO, "MFP: Fail to alloc buffer for sa query id list\n"); + cnmMgtPktFree(prAdapter, prMsduInfo); + 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 <3> Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prBssInfo->prStaRecOfAP->ucBssIndex, + prBssInfo->prStaRecOfAP->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, NULL, MSDU_RATE_MODE_AUTO); + + if (rsnCheckBipKeyInstalled(prAdapter, prBssInfo->prStaRecOfAP)) { + DBGLOG(RSN, INFO, "Set MSDU_OPT_PROTECTED_FRAME\n"); + nicTxConfigPktOption(prMsduInfo, MSDU_OPT_PROTECTED_FRAME, TRUE); + } + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + DBGLOG(RSN, INFO, + "Set SA Query timer %d (%d Tu)\n", + prBssSpecInfo->u4SaQueryCount, 201); + + 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) +{ + P_AIS_SPECIFIC_BSS_INFO_T prBssSpecInfo; + + prBssSpecInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + ASSERT(prBssSpecInfo); + DBGLOG(RSN, INFO, "prBssSpecInfo->u4SaQueryCount %d\n", + prBssSpecInfo->u4SaQueryCount); + + if (prBssSpecInfo->u4SaQueryCount == 0) + rsnStartSaQueryTimer(prAdapter, (ULONG) NULL); +} + +/*----------------------------------------------------------------------------*/ +/*! +* +* \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->prAisBssInfo; + ASSERT(prBssInfo); + + if (!prSwRfb) + return; + + prRxFrame = (P_ACTION_SA_QUERY_FRAME) prSwRfb->pvHeader; + if (!prRxFrame) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (!prStaRec) /* Todo:: for not AIS check */ + return; + + DBGLOG(RSN, INFO, "IEEE 802.11: Received SA Query Request from " MACSTR "\n", MAC2STR(prStaRec->aucMacAddr)); + + DBGLOG_MEM8(RSN, INFO, prRxFrame->ucTransId, ACTION_SA_QUERY_TR_ID_LEN); + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_DISCONNECTED) { + DBGLOG(RSN, INFO, "IEEE 802.11: Ignore SA Query Request from unassociated STA " + MACSTR "\n", MAC2STR(prStaRec->aucMacAddr)); + return; + } + + DBGLOG(RSN, INFO, "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) + ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + if (rsnCheckBipKeyInstalled(prAdapter, prBssInfo->prStaRecOfAP)) + 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_QUERY_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 <3> Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prBssInfo->prStaRecOfAP->ucBssIndex, + prBssInfo->prStaRecOfAP->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, NULL, MSDU_RATE_MODE_AUTO); + + if (rsnCheckBipKeyInstalled(prAdapter, prBssInfo->prStaRecOfAP)) { + DBGLOG(RSN, INFO, "Set MSDU_OPT_PROTECTED_FRAME\n"); + nicTxConfigPktOption(prMsduInfo, MSDU_OPT_PROTECTED_FRAME, TRUE); + } +#if 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->ucPID = nicAssignPID(prAdapter); + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->fgIsBasicRate = FALSE; +#endif + /* 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, INFO, "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, INFO, "IEEE 802.11: Unexpected SA Query Action %d\n", prRxFrame->ucAction); + return; + } + + DBGLOG(RSN, INFO, "IEEE 802.11: Received SA Query Response from " MACSTR "\n", MAC2STR(prStaRec->aucMacAddr)); + + DBGLOG_MEM8(RSN, INFO, 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, INFO, "IEEE 802.11: No matching SA Query transaction identifier found\n"); + return; + } + + DBGLOG(RSN, INFO, "Reply to pending SA Query received\n"); + + rsnStopSaQuery(prAdapter); +} +#endif + +#if CFG_SUPPORT_AAA +#define WPS_DEV_OUI_WFA 0x0050f204 +#define ATTR_RESPONSE_TYPE 0x103b + +#define ATTR_VERSION 0x104a +#define ATTR_VENDOR_EXT 0x1049 +#define WPS_VENDOR_ID_WFA 14122 + +VOID rsnGenerateWSCIEForAssocRsp(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + P_WIFI_VAR_T prWifiVar = NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + UINT_16 u2IELen = 0; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + ASSERT(IS_NET_ACTIVE(prAdapter, prMsduInfo->ucBssIndex)); + + prWifiVar = &(prAdapter->rWifiVar); + ASSERT(prWifiVar); + + DBGLOG(RSN, TRACE, "WPS: Building WPS IE for (Re)Association Response"); + prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); + + if (prP2pBssInfo->eNetworkType != NETWORK_TYPE_P2P) + return; + + u2IELen = kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 3, (UINT_8) prP2pBssInfo->u4PrivateData); + + kalP2PGenWSC_IE(prAdapter->prGlueInfo, + 3, + (PUINT_8) ((ULONG) prMsduInfo->prPacket + + (ULONG) prMsduInfo->u2FrameLength), + (UINT_8) prP2pBssInfo->u4PrivateData); + prMsduInfo->u2FrameLength += (UINT_16) kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 3, + (UINT_8) prP2pBssInfo->u4PrivateData); +} + +#endif + +#if CFG_SUPPORT_802_11W +/* AP PMF */ +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to validate setting if PMF connection capable or not +* If AP MFPC=1, and STA MFPC=1, we let this as PMF connection +* +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +UINT_16 rsnPmfCapableValidation(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_STA_RECORD_T prStaRec) +{ + BOOLEAN selfMfpc, selfMfpr, peerMfpc, peerMfpr; + + selfMfpc = prBssInfo->rApPmfCfg.fgMfpc; + selfMfpr = prBssInfo->rApPmfCfg.fgMfpr; + peerMfpc = prStaRec->rPmfCfg.fgMfpc; + peerMfpr = prStaRec->rPmfCfg.fgMfpr; + + DBGLOG(RSN, INFO, "AP mfpc:%d, mfpr:%d / STA mfpc:%d, mfpr:%d\n", + selfMfpc, selfMfpr, peerMfpc, peerMfpr); + + if ((selfMfpc == TRUE) && (peerMfpc == FALSE)) { + if ((selfMfpr == TRUE) && (peerMfpr == FALSE)) { + DBGLOG(RSN, ERROR, "PMF policy violation for case 4\n"); + return STATUS_CODE_ROBUST_MGMT_FRAME_POLICY_VIOLATION; + } + + if (peerMfpr == TRUE) { + DBGLOG(RSN, ERROR, "PMF policy violation for case 7\n"); + return STATUS_CODE_ROBUST_MGMT_FRAME_POLICY_VIOLATION; + } + } + + if ((selfMfpc == TRUE) && (peerMfpc == TRUE)) { + DBGLOG(RSN, ERROR, "PMF Connection\n"); + prStaRec->rPmfCfg.fgApplyPmf = TRUE; + } + + return STATUS_CODE_SUCCESSFUL; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to generate TIMEOUT INTERVAL IE for association resp +* Add Timeout interval IE (56) when PMF invalid association +* +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rsnPmfGenerateTimeoutIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + IE_TIMEOUT_INTERVAL_T *prTimeout; + P_STA_RECORD_T prStaRec = NULL; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (!prStaRec) + return; + + prTimeout = (IE_TIMEOUT_INTERVAL_T *) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + + /* only when PMF connection, and association error code is 30 */ + if ((rsnCheckBipKeyInstalled(prAdapter, prStaRec) == TRUE) && + (prStaRec->u2StatusCode == STATUS_CODE_ASSOC_REJECTED_TEMPORARILY)) { + + DBGLOG(RSN, INFO, "rsnPmfGenerateTimeoutIE TRUE\n"); + prTimeout->ucId = ELEM_ID_TIMEOUT_INTERVAL; + prTimeout->ucLength = ELEM_MAX_LEN_TIMEOUT_IE; + prTimeout->ucType = IE_TIMEOUT_INTERVAL_TYPE_ASSOC_COMEBACK; + prTimeout->u4Value = 1<<10; + prMsduInfo->u2FrameLength += IE_SIZE(prTimeout); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to check the Sa query timeout. +* check if total retry time is greater than 1000ms +* +* \retval 1: retry max timeout. 0: not timeout +* \note +* Called by: AAA module, Handle by Sa Query timeout +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 rsnApCheckSaQueryTimeout(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + P_BSS_INFO_T prBssInfo; + UINT_32 now; + + GET_CURRENT_SYSTIME(&now); + + if (CHECK_FOR_TIMEOUT(now, prStaRec->rPmfCfg.u4SAQueryStart, TU_TO_MSEC(1000))) { + DBGLOG(RSN, INFO, "association SA Query timed out\n"); + + /* XXX PMF TODO how to report STA REC disconnect?? */ + /* when SAQ retry count timeout, clear this STA */ + prStaRec->rPmfCfg.ucSAQueryTimedOut = 1; + prStaRec->rPmfCfg.u2TransactionID = 0; + prStaRec->rPmfCfg.u4SAQueryCount = 0; + cnmTimerStopTimer(prAdapter, &prStaRec->rPmfCfg.rSAQueryTimer); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + /* refer to p2pRoleFsmRunEventRxDeauthentication*/ + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + if (bssRemoveClient(prAdapter, prBssInfo, prStaRec)) { + /* Indicate disconnect to Host. */ + p2pFuncDisconnect(prAdapter, prBssInfo, prStaRec, FALSE, 0); + /* Deactive BSS if PWR is IDLE and no peer */ + if (IS_NET_PWR_STATE_IDLE(prAdapter, prBssInfo->ucBssIndex) && + (bssGetClientCount(prAdapter, prBssInfo) == 0)) { + /* All Peer disconnected !! Stop BSS now!! */ + p2pFuncStopComplete(prAdapter, prBssInfo); + } + } + } + + return 1; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to start the 802.11w sa query timer. +* This routine is triggered every 201ms, and every time enter function, check max timeout +* +* \note +* Called by: AAA module, Handle TX SAQ request +*/ +/*----------------------------------------------------------------------------*/ +void rsnApStartSaQueryTimer(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN ULONG ulParamPtr) +{ + P_BSS_INFO_T prBssInfo; + P_MSDU_INFO_T prMsduInfo; + P_ACTION_SA_QUERY_FRAME prTxFrame; + UINT_16 u2PayloadLen; + + ASSERT(prStaRec); + + DBGLOG(RSN, INFO, "MFP: AP Start Sa Query timer\n"); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + if (prStaRec->rPmfCfg.u4SAQueryCount > 0 && rsnApCheckSaQueryTimeout(prAdapter, prStaRec)) { + DBGLOG(RSN, INFO, + "MFP: retry max timeout, u4SaQueryCount count =%d\n", + prStaRec->rPmfCfg.u4SAQueryCount); + return; + } + + prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + prTxFrame = (P_ACTION_SA_QUERY_FRAME) + ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) + prTxFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + COPY_MAC_ADDR(prTxFrame->aucDestAddr, prStaRec->aucMacAddr); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucBSSID); + COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); + + prTxFrame->ucCategory = CATEGORY_SA_QUERY_ACTION; + prTxFrame->ucAction = ACTION_SA_QUERY_REQUEST; + + if (prStaRec->rPmfCfg.u4SAQueryCount == 0) + GET_CURRENT_SYSTIME(&prStaRec->rPmfCfg.u4SAQueryStart); + + /* if retry, transcation id ++ */ + if (prStaRec->rPmfCfg.u4SAQueryCount) { + prStaRec->rPmfCfg.u2TransactionID++; + } else { + /* if first SAQ request, random pick transaction id */ + prStaRec->rPmfCfg.u2TransactionID = (UINT_16) (kalRandomNumber() & 0xFFFF); + } + + DBGLOG(RSN, INFO, "SAQ transaction id:%d\n", prStaRec->rPmfCfg.u2TransactionID); + + /* trnsform U16 to U8 array */ + prTxFrame->ucTransId[0] = ((prStaRec->rPmfCfg.u2TransactionID & 0xff00) >> 8); + prTxFrame->ucTransId[1] = ((prStaRec->rPmfCfg.u2TransactionID & 0x00ff) >> 0); + + prStaRec->rPmfCfg.u4SAQueryCount++; + + u2PayloadLen = 2 + ACTION_SA_QUERY_TR_ID_LEN; + + /* 4 <3> Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, NULL, MSDU_RATE_MODE_AUTO); + + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(RSN, INFO, "SAQ Set MSDU_OPT_PROTECTED_FRAME\n"); + nicTxConfigPktOption(prMsduInfo, MSDU_OPT_PROTECTED_FRAME, TRUE); + } + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + DBGLOG(RSN, INFO, + "AP Set SA Query timer %d (%d Tu)\n", + prStaRec->rPmfCfg.u4SAQueryCount, 201); + + cnmTimerStartTimer(prAdapter, &prStaRec->rPmfCfg.rSAQueryTimer, TU_TO_MSEC(201)); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to start the 802.11w TX SA query. +* +* +* \note +* Called by: AAA module, Handle Tx action frame request +*/ +/*----------------------------------------------------------------------------*/ +void rsnApStartSaQuery(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + if (!prStaRec) + return; + + DBGLOG(RSN, INFO, "rsnApStartSaQuery\n"); + + cnmTimerStopTimer(prAdapter, &prStaRec->rPmfCfg.rSAQueryTimer); + cnmTimerInitTimer(prAdapter, &prStaRec->rPmfCfg.rSAQueryTimer, + (PFN_MGMT_TIMEOUT_FUNC)rsnApStartSaQueryTimer, + (ULONG) prStaRec); + + if (prStaRec->rPmfCfg.u4SAQueryCount == 0) + rsnApStartSaQueryTimer(prAdapter, prStaRec, (ULONG) NULL); +} + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to stop the 802.11w SA query. +* +* +* \note +* Called by: AAA module, stop TX SAQ if receive correct SAQ response +*/ +/*----------------------------------------------------------------------------*/ +void rsnApStopSaQuery(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + ASSERT(prStaRec); + + cnmTimerStopTimer(prAdapter, &prStaRec->rPmfCfg.rSAQueryTimer); + prStaRec->rPmfCfg.u2TransactionID = 0; + prStaRec->rPmfCfg.u4SAQueryCount = 0; + prStaRec->rPmfCfg.ucSAQueryTimedOut = 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to process the 802.11w sa query action frame. +* +* +* \note +* Called by: AAA module, Handle Rx action request +*/ +/*----------------------------------------------------------------------------*/ +void rsnApSaQueryRequest(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; + + if (!prSwRfb) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (!prStaRec) /* Todo:: for not AIS check */ + return; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + ASSERT(prBssInfo); + + prRxFrame = (P_ACTION_SA_QUERY_FRAME) prSwRfb->pvHeader; + if (!prRxFrame) + return; + + DBGLOG(RSN, INFO, "IEEE 802.11: AP Received SA Query Request from " MACSTR "\n", MAC2STR(prStaRec->aucMacAddr)); + + DBGLOG_MEM8(RSN, INFO, prRxFrame->ucTransId, ACTION_SA_QUERY_TR_ID_LEN); + + if (!rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(RSN, INFO, "IEEE 802.11: AP Ignore SA Query Request non-PMF STA " + MACSTR "\n", MAC2STR(prStaRec->aucMacAddr)); + return; + } + + DBGLOG(RSN, INFO, "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; + + /* drop cipher mismatch */ + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + if (HAL_RX_STATUS_IS_CIPHER_MISMATCH(prSwRfb->prRxStatus) || + HAL_RX_STATUS_IS_CLM_ERROR(prSwRfb->prRxStatus)) { + /* if cipher mismatch, or incorrect encrypt, just drop */ + DBGLOG(RSN, ERROR, "drop SAQ req CM/CLM=1\n"); + return; + } + } + + prTxFrame = (P_ACTION_SA_QUERY_FRAME) + ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + prTxFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + DBGLOG(RSN, INFO, "AP SAQ resp set FC PF bit\n"); + } + COPY_MAC_ADDR(prTxFrame->aucDestAddr, prStaRec->aucMacAddr); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucBSSID); + COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); + + prTxFrame->ucCategory = CATEGORY_SA_QUERY_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 <3> Update information of MSDU_INFO_T */ + TX_SET_MMPDU(prAdapter, + prMsduInfo, + prStaRec->ucBssIndex, + prStaRec->ucIndex, + WLAN_MAC_MGMT_HEADER_LEN, WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, NULL, MSDU_RATE_MODE_AUTO); + + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + DBGLOG(RSN, INFO, "AP SAQ resp set MSDU_OPT_PROTECTED_FRAME\n"); + nicTxConfigPktOption(prMsduInfo, MSDU_OPT_PROTECTED_FRAME, TRUE); + } + + /* 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: AAA module, Handle Rx action request +*/ +/*----------------------------------------------------------------------------*/ +void rsnApSaQueryAction(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_ACTION_SA_QUERY_FRAME prRxFrame; + P_STA_RECORD_T prStaRec; + UINT_16 u2SwapTrID; + + prRxFrame = (P_ACTION_SA_QUERY_FRAME) prSwRfb->pvHeader; + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (!prStaRec) { + DBGLOG(RSN, WARN, "NULL prStaRec!\n"); + return; + } + + DBGLOG(RSN, TRACE, "AP PMF SAQ action enter from " MACSTR "\n", MAC2STR(prStaRec->aucMacAddr)); + if (prSwRfb->u2PacketLen < ACTION_SA_QUERY_TR_ID_LEN) { + DBGLOG(RSN, INFO, "IEEE 802.11: Too short SA Query Action frame (len=%lu)\n", + (unsigned long)prSwRfb->u2PacketLen); + return; + } + + if (prRxFrame->ucAction == ACTION_SA_QUERY_REQUEST) { + rsnApSaQueryRequest(prAdapter, prSwRfb); + return; + } + + if (prRxFrame->ucAction != ACTION_SA_QUERY_RESPONSE) { + DBGLOG(RSN, INFO, "IEEE 802.11: Unexpected SA Query Action %d\n", prRxFrame->ucAction); + return; + } + + DBGLOG(RSN, INFO, "IEEE 802.11: Received SA Query Response from " MACSTR "\n", MAC2STR(prStaRec->aucMacAddr)); + + DBGLOG_MEM8(RSN, INFO, prRxFrame->ucTransId, ACTION_SA_QUERY_TR_ID_LEN); + + /* MLME-SAQuery.confirm */ + /* transform to network byte order */ + u2SwapTrID = htons(prStaRec->rPmfCfg.u2TransactionID); + if (kalMemCmp((UINT_8 *)&u2SwapTrID, prRxFrame->ucTransId, ACTION_SA_QUERY_TR_ID_LEN) == 0) { + DBGLOG(RSN, INFO, "AP Reply to SA Query received\n"); + rsnApStopSaQuery(prAdapter, prStaRec); + } else { + DBGLOG(RSN, INFO, "IEEE 802.11: AP No matching SA Query transaction identifier found\n"); + } + +} + +#endif /* CFG_SUPPORT_802_11W */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/saa_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/saa_fsm.c new file mode 100644 index 0000000000000..c89078fe3d0fc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/saa_fsm.c @@ -0,0 +1,2248 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static PUINT_8 apucDebugAAState[AA_STATE_NUM] = { + (PUINT_8) DISP_STRING("AA_IDLE"), + (PUINT_8) DISP_STRING("SAA_SEND_AUTH1"), + (PUINT_8) DISP_STRING("SAA_WAIT_AUTH2"), + (PUINT_8) DISP_STRING("SAA_SEND_AUTH3"), + (PUINT_8) DISP_STRING("SAA_WAIT_AUTH4"), + (PUINT_8) DISP_STRING("SAA_SEND_ASSOC1"), + (PUINT_8) DISP_STRING("SAA_WAIT_ASSOC2"), + (PUINT_8) DISP_STRING("AAA_SEND_AUTH2"), + (PUINT_8) DISP_STRING("AAA_SEND_AUTH4"), + (PUINT_8) DISP_STRING("AAA_SEND_ASSOC2"), + (PUINT_8) DISP_STRING("AA_RESOURCE") +}; + +/******************************************************************************* +* M A 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_SUPPORT_CFG80211_AUTH +/*----------------------------------------------------------------------------*/ +/* + * @brief prepare to send authentication or association frame + * + * @param[in] prStaRec Pointer to the STA_RECORD_T + * + * @return (none) + */ +/*----------------------------------------------------------------------------*/ +void saaSendAuthAssoc(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + /* This function do the things like + * "case SAA_STATE_SEND_AUTH1/ASSOC1" in SAA FSM steps + */ + + UINT_32 rStatus = WLAN_STATUS_FAILURE; + P_CONNECTION_SETTINGS_T prConnSettings = NULL; + UINT_16 u2AuthTransSN = AUTH_TRANSACTION_SEQ_1; /* default for OPEN */ + P_BSS_DESC_T prBssDesc = NULL; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo = NULL; + PARAM_SSID_T rParamSsid; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + DBGLOG(SAA, INFO, "[SAA]saaSendAuthAssoc, StaState:%d\n", + prStaRec->ucStaState); + + if (prStaRec->ucTxAuthAssocRetryCount >= + prStaRec->ucTxAuthAssocRetryLimit) { + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = (prConnSettings->fgIsSendAssoc) ? + STATUS_CODE_ASSOC_TIMEOUT : STATUS_CODE_AUTH_TIMEOUT; + + if (saaFsmSendEventJoinComplete(prAdapter, + WLAN_STATUS_FAILURE, + prStaRec, NULL) == + WLAN_STATUS_RESOURCES) { + /* can set a timer and retry later */ + DBGLOG(SAA, WARN, + "[SAA]can't alloc msg for inform AIS join complete\n"); + } + } else { + prStaRec->ucTxAuthAssocRetryCount++; + /* Prepare to send authentication frame */ + if (!prConnSettings->fgIsSendAssoc) { + /* Fill authentication transaction sequence number + * depends on auth type + */ + if ((prAdapter->prGlueInfo->rWpaInfo.u4AuthAlg & + AUTH_TYPE_SAE) || + (prAdapter->prGlueInfo->rWpaInfo.u4AuthAlg & + AUTH_TYPE_SHARED_KEY)) { + kalMemCopy(&u2AuthTransSN, + prConnSettings->aucAuthData, + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN); + DBGLOG(SAA, INFO, + "[SAA]Get auth SN = %d from Conn Settings\n", + u2AuthTransSN); + } + /* Update Station Record - Class 1 Flag */ + if (prStaRec->ucStaState != STA_STATE_1) { + DBGLOG(SAA, WARN, + "[SAA]Rx send auth CMD at unexpect state:%d\n", + prStaRec->ucStaState); + cnmStaRecChangeState(prAdapter, + prStaRec, STA_STATE_1); + } +#if !CFG_SUPPORT_AAA + rStatus = authSendAuthFrame(prAdapter, + prStaRec, u2AuthTransSN); +#else + rStatus = authSendAuthFrame(prAdapter, + prStaRec, + prStaRec->ucBssIndex, + NULL, + u2AuthTransSN, + STATUS_CODE_RESERVED); +#endif /* CFG_SUPPORT_AAA */ + prStaRec->eAuthAssocSent = u2AuthTransSN; + } else { /* Prepare to send association frame */ +#if 1 + /* Fill Cipher/AKM before sending association request, + * copy fro m AIS search step + */ + if (prConnSettings->ucSSIDLen) { + rParamSsid.u4SsidLen = + prConnSettings->ucSSIDLen; + COPY_SSID(rParamSsid.aucSsid, + rParamSsid.u4SsidLen, + prConnSettings->aucSSID, + prConnSettings->ucSSIDLen); + prBssDesc = scanSearchBssDescByBssidAndSsid( + prAdapter, + prStaRec->aucMacAddr, + TRUE, + &rParamSsid); + DBGLOG(RSN, INFO, "[RSN] prBssDesc[" + MACSTR" ,%s] Searched by BSSID[" + MACSTR"] & SSID %s.\n", + MAC2STR(prBssDesc->aucBSSID), + prBssDesc->aucSSID, + MAC2STR(prStaRec->aucMacAddr), + prConnSettings->aucSSID); + } else { + prBssDesc = scanSearchBssDescByBssidAndChanNum( + prAdapter, + prStaRec->aucMacAddr, + TRUE, + prConnSettings->ucChannelNum); + DBGLOG(RSN, INFO, "[RSN] prBssDesc[" + MACSTR" ,%s] Searched by BSSID[" + MACSTR"] & ChanNum %d.\n", + MAC2STR(prBssDesc->aucBSSID), + prBssDesc->aucSSID, + MAC2STR(prStaRec->aucMacAddr), + prConnSettings->ucChannelNum); + } + + prAisSpecBssInfo = + &(prAdapter->rWifiVar.rAisSpecificBssInfo); + if (rsnPerformPolicySelection(prAdapter, prBssDesc)) { + if (prAisSpecBssInfo->fgCounterMeasure) + DBGLOG(RSN, WARN, + "Skip whle at counter measure perid\n"); + else { + DBGLOG(RSN, INFO, "Bss RSN matched!\n"); + prAdapter->prAisBssInfo + ->u4RsnSelectedGroupCipher = + prBssDesc + ->u4RsnSelectedGroupCipher; + prAdapter->prAisBssInfo + ->u4RsnSelectedPairwiseCipher = + prBssDesc + ->u4RsnSelectedPairwiseCipher; + prAdapter->prAisBssInfo + ->u4RsnSelectedAKMSuite = + prBssDesc + ->u4RsnSelectedAKMSuite; + } + } else + DBGLOG(RSN, WARN, "Bss fail for RSN check\n"); +#endif + if (prStaRec->ucStaState == STA_STATE_1) { + /* don't change to state2 for reassociation */ + /* Update Station Record - Class 2 Flag */ + cnmStaRecChangeState(prAdapter, + prStaRec, STA_STATE_2); + } + + rStatus = assocSendReAssocReqFrame(prAdapter, prStaRec); + prStaRec->eAuthAssocSent = AA_SENT_ASSOC1; + } + + if (rStatus != WLAN_STATUS_SUCCESS) { + /* maybe can't alloc msdu info, retry after timeout */ + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC) + saaFsmRunEventTxReqTimeOut, + (unsigned long) prStaRec); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC(TX_AUTHENTICATION_RETRY_TIMEOUT_TU)); + } + + } +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @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) +{ + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + ENUM_AA_STATE_T ePreviousState; + BOOLEAN fgIsTransition; + + ASSERT(prStaRec); + if (!prStaRec || g_u4HaltFlag) + return; + + do { + + DBGLOG(SAA, STATE, "[SAA]TRANSITION: [%s] -> [%s]\n", + apucDebugAAState[prStaRec->eAuthAssocState], apucDebugAAState[eNextState]); + + 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) { + /* ToDo:: Nothing */ + } else { + eNextState = AA_STATE_RESOURCE; + fgIsTransition = TRUE; + } + } else { + if (saaFsmSendEventJoinComplete(prAdapter, + WLAN_STATUS_FAILURE, + prStaRec, NULL) == WLAN_STATUS_RESOURCES) { + eNextState = AA_STATE_RESOURCE; + fgIsTransition = TRUE; + } + } + + } + + /* Free allocated TCM memory */ + if (prStaRec->prChallengeText) { + cnmMemFree(prAdapter, prStaRec->prChallengeText); + prStaRec->prChallengeText = (P_IE_CHALLENGE_TEXT_T) NULL; + } + + break; + + case SAA_STATE_SEND_AUTH1: + + /* Do tasks in INIT STATE */ + if (prStaRec->ucTxAuthAssocRetryCount >= prStaRec->ucTxAuthAssocRetryLimit) { + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_AUTH_TIMEOUT; + + eNextState = AA_STATE_IDLE; + fgIsTransition = TRUE; + } else { + prStaRec->ucTxAuthAssocRetryCount++; + + /* Update Station Record - Class 1 Flag */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + +#if !CFG_SUPPORT_AAA + rStatus = authSendAuthFrame(prAdapter, prStaRec, AUTH_TRANSACTION_SEQ_1); +#else + rStatus = authSendAuthFrame(prAdapter, + prStaRec, + prStaRec->ucBssIndex, + NULL, + AUTH_TRANSACTION_SEQ_1, + STATUS_CODE_RESERVED); +#endif /* CFG_SUPPORT_AAA */ + if (rStatus != WLAN_STATUS_SUCCESS) { + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, (PFN_MGMT_TIMEOUT_FUNC) + saaFsmRunEventTxReqTimeOut, (ULONG) prStaRec); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC(TX_AUTHENTICATION_RETRY_TIMEOUT_TU)); + } + } + + break; + + case SAA_STATE_WAIT_AUTH2: + break; + + case SAA_STATE_SEND_AUTH3: + + /* Do tasks in INIT STATE */ + if (prStaRec->ucTxAuthAssocRetryCount >= prStaRec->ucTxAuthAssocRetryLimit) { + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_AUTH_TIMEOUT; + + eNextState = AA_STATE_IDLE; + fgIsTransition = TRUE; + } else { + prStaRec->ucTxAuthAssocRetryCount++; + +#if !CFG_SUPPORT_AAA + rStatus = authSendAuthFrame(prAdapter, prStaRec, AUTH_TRANSACTION_SEQ_3); +#else + rStatus = authSendAuthFrame(prAdapter, + prStaRec, + prStaRec->ucBssIndex, + NULL, + AUTH_TRANSACTION_SEQ_3, + STATUS_CODE_RESERVED); +#endif /* CFG_SUPPORT_AAA */ + if (rStatus != WLAN_STATUS_SUCCESS) { + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, (PFN_MGMT_TIMEOUT_FUNC) + saaFsmRunEventTxReqTimeOut, (ULONG) prStaRec); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC(TX_AUTHENTICATION_RETRY_TIMEOUT_TU)); + } + } + + break; + + case SAA_STATE_WAIT_AUTH4: + break; + + case SAA_STATE_SEND_ASSOC1: + /* Do tasks in INIT STATE */ + if (prStaRec->ucTxAuthAssocRetryCount >= prStaRec->ucTxAuthAssocRetryLimit) { + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_ASSOC_TIMEOUT; + + eNextState = AA_STATE_IDLE; + fgIsTransition = TRUE; + } else { + prStaRec->ucTxAuthAssocRetryCount++; + + rStatus = assocSendReAssocReqFrame(prAdapter, prStaRec); + if (rStatus != WLAN_STATUS_SUCCESS) { + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, (PFN_MGMT_TIMEOUT_FUNC) + saaFsmRunEventTxReqTimeOut, (ULONG) prStaRec); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC(TX_ASSOCIATION_RETRY_TIMEOUT_TU)); + } + } + + break; + + case SAA_STATE_WAIT_ASSOC2: + break; + + case AA_STATE_RESOURCE: + /* TODO(Kevin) Can setup a timer and send message later */ + break; + + default: + DBGLOG(SAA, ERROR, "Unknown AA STATE\n"); + ASSERT(0); + break; + } + + } while (fgIsTransition); + + return; + +} /* end of saaFsmSteps() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send Event to AIS/BOW/P2P +* +* @param[in] rJoinStatus To indicate JOIN success or failure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] prSwRfb Pointer to the SW_RFB_T + +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +saaFsmSendEventJoinComplete(IN P_ADAPTER_T prAdapter, + IN WLAN_STATUS rJoinStatus, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb) +{ + P_BSS_INFO_T prBssInfo; + + ASSERT(prStaRec); + if (!prStaRec) { + DBGLOG(SAA, ERROR, "[%s]prStaRec is NULL\n", __func__); + return WLAN_STATUS_INVALID_PACKET; + } + if (!prAdapter) { + DBGLOG(SAA, ERROR, "[%s]prAdapter is NULL\n", __func__); + return WLAN_STATUS_INVALID_PACKET; + } + if (!prAdapter->prAisBssInfo) { + DBGLOG(SAA, ERROR, "[%s]prAdapter->prAisBssInfo is NULL\n", __func__); + return WLAN_STATUS_INVALID_PACKET; + } + + /* Store limitation about 40Mhz bandwidth capability during association */ + if (prStaRec->ucBssIndex < BSS_INFO_NUM) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + if (rJoinStatus == WLAN_STATUS_SUCCESS) { + prBssInfo->fg40mBwAllowed = prBssInfo->fgAssoc40mBwAllowed; + /* Initialize OpMode Channel Width change indicator */ + prBssInfo->fgIsOpChangeChannelWidth = FALSE; + } + prBssInfo->fgAssoc40mBwAllowed = FALSE; + } + + if (prStaRec->ucBssIndex == prAdapter->prAisBssInfo->ucBssIndex) { + 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; +#if CFG_SUPPORT_CFG80211_AUTH + if (rJoinStatus == WLAN_STATUS_SUCCESS) + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; +#endif + 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; +#if CFG_SUPPORT_CFG80211_AUTH + if (rJoinStatus == WLAN_STATUS_SUCCESS) + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; +#endif + 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 (IS_STA_BOW_TYPE(prStaRec)) { + /* @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 { + DBGLOG(SAA, ERROR, "Invalid case in %s.\n", __func__); + 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 */ +#if CFG_SUPPORT_CFG80211_AUTH + prStaRec->u2StatusCode = STATUS_CODE_UNSPECIFIED_FAILURE; +#else + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; +#endif + + /* 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); + + /* 4 <4> Init the sec fsm */ + /* secFsmInit(prAdapter, prStaRec); */ + + /* 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->ucBssIndex < BSS_INFO_NUM) { + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) + && (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) { + prBssInfo->fgAssoc40mBwAllowed = cnmBss40mBwPermitted(prAdapter, prBssInfo->ucBssIndex); + } else { + prBssInfo->fgAssoc40mBwAllowed = FALSE; + } + DBGLOG(RLM, TRACE, "STA 40mAllowed=%d\n", prBssInfo->fgAssoc40mBwAllowed); + } + +#if CFG_SUPPORT_CFG80211_AUTH + if (!IS_STA_IN_P2P(prStaRec)) { + /* skip SAA FSM */ + prStaRec->eAuthAssocSent = AA_SENT_NONE; + saaSendAuthAssoc(prAdapter, prStaRec); + } else { +#endif + /* 4 <7> Trigger SAA FSM */ + if (prStaRec->ucStaState == STA_STATE_1) + saaFsmSteps(prAdapter, prStaRec, SAA_STATE_SEND_AUTH1, (P_SW_RFB_T) NULL); + else if (prStaRec->ucStaState == STA_STATE_2 || prStaRec->ucStaState == STA_STATE_3) + saaFsmSteps(prAdapter, prStaRec, SAA_STATE_SEND_ASSOC1, (P_SW_RFB_T) NULL); +#if CFG_SUPPORT_CFG80211_AUTH + } +#endif +} /* 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; + + if ((rTxDoneStatus == TX_RESULT_DROPPED_IN_DRIVER) || + (rTxDoneStatus == TX_RESULT_QUEUE_CLEARANCE)) + return WLAN_STATUS_SUCCESS; + + ASSERT(prStaRec); + + DBGLOG(SAA, LOUD, "EVENT-TX DONE: Current Time = %d\n", kalGetTimeTick()); + + /* Trigger statistics log if Auth/Assoc Tx failed */ + if (rTxDoneStatus != TX_RESULT_SUCCESS) + wlanTriggerStatsLog(prAdapter, prAdapter->rWifiVar.u4StatsLogDuration); + +#if CFG_SUPPORT_CFG80211_AUTH + if (!IS_STA_IN_P2P(prStaRec)) { + /* check the outgoing frame is matched with + * the last sent frame, ignore the unmatched txdone + */ + if ((prStaRec->eAuthAssocSent >= AA_SENT_AUTH1) && + (prStaRec->eAuthAssocSent <= AA_SENT_AUTH4)) { + if (authCheckTxAuthFrame(prAdapter, prMsduInfo, + prStaRec->eAuthAssocSent) != + WLAN_STATUS_SUCCESS) + return WLAN_STATUS_SUCCESS; + } else if (prStaRec->eAuthAssocSent == AA_SENT_ASSOC1) { + if (assocCheckTxReAssocReqFrame(prAdapter, + prMsduInfo) != WLAN_STATUS_SUCCESS) + return WLAN_STATUS_SUCCESS; + } else + DBGLOG(SAA, WARN, "unexpected sent frame = %d\n", + prStaRec->eAuthAssocSent); + + cnmTimerStopTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer); + + if (rTxDoneStatus == TX_RESULT_SUCCESS) { + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC) + saaFsmRunEventRxRespTimeOut, + (unsigned long) prStaRec); +#if CFG_SUPPORT_CFG80211_AUTH + if (prAdapter->prGlueInfo->rWpaInfo.u4AuthAlg & + AUTH_TYPE_SAE) + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC( + DOT11_RSNA_SAE_RETRANS_PERIOD_TU)); + else +#endif + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC( + DOT11_AUTHENTICATION_RESPONSE_TIMEOUT_TU)); + } else /* Tx failed, do retry if possible */ + saaSendAuthAssoc(prAdapter, prStaRec); + } else { +#endif + eNextState = prStaRec->eAuthAssocState; + + switch (prStaRec->eAuthAssocState) { + case SAA_STATE_SEND_AUTH1: + { + /* Strictly check the outgoing frame is matched with current AA STATE */ + if (authCheckTxAuthFrame(prAdapter, prMsduInfo, AUTH_TRANSACTION_SEQ_1) != WLAN_STATUS_SUCCESS) + break; + + if (rTxDoneStatus == TX_RESULT_SUCCESS) { + eNextState = SAA_STATE_WAIT_AUTH2; + + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + + cnmTimerInitTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer, (PFN_MGMT_TIMEOUT_FUNC) + saaFsmRunEventRxRespTimeOut, (ULONG) prStaRec); +#if CFG_SUPPORT_CFG80211_AUTH + if (prAdapter->prGlueInfo + ->rWpaInfo.u4AuthAlg & AUTH_TYPE_SAE) + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC(DOT11_RSNA_SAE_RETRANS_PERIOD_TU)); + else +#endif + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC(DOT11_AUTHENTICATION_RESPONSE_TIMEOUT_TU)); + } + + /* if TX was successful, change to next state. + * if TX was failed, do retry if possible. + */ + saaFsmSteps(prAdapter, prStaRec, eNextState, (P_SW_RFB_T) NULL); + } + break; + + case SAA_STATE_SEND_AUTH3: + { + /* Strictly check the outgoing frame is matched with current JOIN STATE */ + if (authCheckTxAuthFrame(prAdapter, prMsduInfo, AUTH_TRANSACTION_SEQ_3) != WLAN_STATUS_SUCCESS) + break; + + if (rTxDoneStatus == TX_RESULT_SUCCESS) { + eNextState = SAA_STATE_WAIT_AUTH4; + + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + + cnmTimerInitTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer, (PFN_MGMT_TIMEOUT_FUNC) + saaFsmRunEventRxRespTimeOut, (ULONG) prStaRec); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC(DOT11_AUTHENTICATION_RESPONSE_TIMEOUT_TU)); + } + + /* if TX was successful, change to next state. + * if TX was failed, do retry if possible. + */ + saaFsmSteps(prAdapter, prStaRec, eNextState, (P_SW_RFB_T) NULL); + } + break; + + case SAA_STATE_SEND_ASSOC1: + { + /* Strictly check the outgoing frame is matched with current SAA STATE */ + if (assocCheckTxReAssocReqFrame(prAdapter, prMsduInfo) != WLAN_STATUS_SUCCESS) + break; + + if (rTxDoneStatus == TX_RESULT_SUCCESS) { + eNextState = SAA_STATE_WAIT_ASSOC2; + + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + + cnmTimerInitTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer, (PFN_MGMT_TIMEOUT_FUNC) + saaFsmRunEventRxRespTimeOut, (ULONG) prStaRec); + + cnmTimerStartTimer(prAdapter, + &(prStaRec->rTxReqDoneOrRxRespTimer), + TU_TO_MSEC(DOT11_ASSOCIATION_RESPONSE_TIMEOUT_TU)); + } + + /* if TX was successful, change to next state. + * if TX was failed, do retry if possible. + */ + saaFsmSteps(prAdapter, prStaRec, eNextState, (P_SW_RFB_T) NULL); + } + break; + + default: + break; /* Ignore other cases */ + } +#if CFG_SUPPORT_CFG80211_AUTH + } +#endif + 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 ULONG plParamPtr) +{ + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) plParamPtr; + + ASSERT(prStaRec); + if (!prStaRec) + return; + + DBGLOG(SAA, LOUD, "EVENT-TIMER: TX REQ TIMEOUT, Current Time = %d\n", kalGetTimeTick()); + + /* Trigger statistics log if Auth/Assoc Tx timeout */ + wlanTriggerStatsLog(prAdapter, prAdapter->rWifiVar.u4StatsLogDuration); +#if CFG_SUPPORT_CFG80211_AUTH + if (!IS_STA_IN_P2P(prStaRec)) { + saaSendAuthAssoc(prAdapter, prStaRec); + } else { +#endif + 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; + } +#if CFG_SUPPORT_CFG80211_AUTH + } +#endif +} /* 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 ULONG ulParamPtr) +{ + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) ulParamPtr; + ENUM_AA_STATE_T eNextState; + DBGLOG(SAA, LOUD, "EVENT-TIMER: RX RESP TIMEOUT, Current Time = %d\n", kalGetTimeTick()); + + ASSERT(prStaRec); + if (!prStaRec) + return; + +#if CFG_SUPPORT_CFG80211_AUTH + if (!IS_STA_IN_P2P(prStaRec)) { + /* Retry the last sent frame if possible */ + saaSendAuthAssoc(prAdapter, prStaRec); + } else { +#endif + 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); +#if CFG_SUPPORT_CFG80211_AUTH + } +#endif +} /* 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; + UINT_8 ucWlanIdx; +#if CFG_SUPPORT_CFG80211_AUTH + P_GLUE_INFO_T prGlueInfo = NULL; + P_WLAN_AUTH_FRAME_T prAuthFrame = (P_WLAN_AUTH_FRAME_T) NULL; +#endif + + ASSERT(prSwRfb); + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ucWlanIdx = (UINT_8) HAL_RX_STATUS_GET_WLAN_IDX(prSwRfb->prRxStatus); +#if CFG_SUPPORT_CFG80211_AUTH + prGlueInfo = prAdapter->prGlueInfo; + ASSERT(prGlueInfo); +#endif + + /* We should have the corresponding Sta Record. */ + if (!prStaRec) { + DBGLOG(SAA, WARN, "Received a AuthResp: wlanIdx[%d] w/o corresponding staRec\n", ucWlanIdx); + return; + } + + if (!IS_AP_STA(prStaRec)) + return; + +#if CFG_SUPPORT_CFG80211_AUTH + /* check received auth frame */ + if ((authCheckRxAuthFrameStatus(prAdapter, prSwRfb, + prStaRec->eAuthAssocSent, &u2StatusCode) == + WLAN_STATUS_SUCCESS) && (!(IS_STA_IN_P2P(prStaRec)))) { + + cnmTimerStopTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer); + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = u2StatusCode; + + /*Report Rx auth frame to upper layer*/ + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; + + DBGLOG(INIT, INFO, "Dump rx auth data\n"); + DBGLOG_MEM8(REQ, INFO, prAuthFrame, prSwRfb->u2PacketLen); + + DBGLOG(SAA, INFO, + "Report RX auth to upper layer with alg:%d, SN:%d, status:%d\n", + prAuthFrame->u2AuthAlgNum, prAuthFrame->aucAuthData[0], + prAuthFrame->aucAuthData[2]); + + cfg80211_rx_mlme_mgmt(prGlueInfo->prDevHandler, + (const u8 *)prAuthFrame, (size_t)prSwRfb->u2PacketLen); + DBGLOG(SAA, INFO, "notification of RX Authentication Done\n"); + + /* Reset Send Auth/(Re)Assoc Frame Count */ + prStaRec->ucTxAuthAssocRetryCount = 0; + if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + + authProcessRxAuth2_Auth4Frame(prAdapter, prSwRfb); + } else { + DBGLOG(SAA, INFO, + "Auth Req was rejected by [" MACSTR + "], Status Code = %d\n", + MAC2STR(prStaRec->aucMacAddr), u2StatusCode); + + /* AIS retry JOIN or indicate JOIN FAILURE to upper layer*/ + if (saaFsmSendEventJoinComplete(prAdapter, + WLAN_STATUS_FAILURE, prStaRec, NULL) == + WLAN_STATUS_RESOURCES) { + /* can set a timer and retry later */ + DBGLOG(SAA, WARN, + "[SAA]can't alloc msg for inform AIS join complete\n"); + } + } + } else { +#endif + 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 */ + } +#if CFG_SUPPORT_CFG80211_AUTH + } +#endif +} /* 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; + UINT_8 ucWlanIdx; +#if CFG_SUPPORT_CFG80211_AUTH + P_GLUE_INFO_T prGlueInfo = NULL; + P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame = NULL; + P_CONNECTION_SETTINGS_T prConnSettings = NULL; +#endif + + ASSERT(prSwRfb); + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ucWlanIdx = (UINT_8) HAL_RX_STATUS_GET_WLAN_IDX(prSwRfb->prRxStatus); +#if CFG_SUPPORT_CFG80211_AUTH + prGlueInfo = prAdapter->prGlueInfo; + ASSERT(prGlueInfo); + prConnSettings = &prGlueInfo->prAdapter->rWifiVar.rConnSettings; +#endif + DBGLOG(SAA, INFO, "RX Assoc Resp\n"); + + /* We should have the corresponding Sta Record. */ + if (!prStaRec) { + /* ASSERT(0); */ + DBGLOG(SAA, WARN, "Received a AssocResp: wlanIdx[%d] w/o corresponding staRec\n", ucWlanIdx); + return rStatus; + } + + if (!IS_AP_STA(prStaRec)) + return rStatus; + +#if CFG_SUPPORT_CFG80211_AUTH + /* TRUE if the incoming frame is what we are waiting for */ + if ((assocCheckRxReAssocRspFrameStatus( + prAdapter, prSwRfb, &u2StatusCode) == WLAN_STATUS_SUCCESS) && + (!(IS_STA_IN_P2P(prStaRec)))) { + + cnmTimerStopTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer); + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = u2StatusCode; + + /*Report Rx assoc frame to upper layer*/ + prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) prSwRfb->pvHeader; + + + /* The BSS from cfg80211_ops.assoc must give back to + * cfg80211_send_rx_assoc() or to cfg80211_assoc_timeout(). + * To ensure proper refcounting, new association requests + * while already associating must be rejected. + */ + DBGLOG(SAA, INFO, "Report RX Assoc to upper layer, %s\n", + prConnSettings->bss ? "DO IT" : "Oops"); + if (prConnSettings->bss) { +#if KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE + /* [TODO] Set uapsd_queues field to zero first, + * fill it if needed + */ + cfg80211_rx_assoc_resp(prGlueInfo->prDevHandler, + prConnSettings->bss, + (const u8 *)prAssocRspFrame, + (size_t)prSwRfb->u2PacketLen, 0); +#else + cfg80211_rx_assoc_resp(prGlueInfo->prDevHandler, + prConnSettings->bss, + (const u8 *)prAssocRspFrame, + (size_t)prSwRfb->u2PacketLen); +#endif + DBGLOG(SAA, INFO, + "Report RX Assoc to upper layer, Done\n"); + prConnSettings->bss = NULL; + } else + DBGLOG(SAA, WARN, + "Rx Assoc Resp without specific BSS\n"); + /* Reset Send Auth/(Re)Assoc Frame Count */ + prStaRec->ucTxAuthAssocRetryCount = 0; + + /* update RCPI */ + ASSERT(prSwRfb->prRxStatusGroup3); + prStaRec->ucRCPI = + nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0, prSwRfb); + + if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + + /* Update Station Record - Class 3 Flag */ + /* NOTE(Kevin): Moved to AIS FSM for roaming issue + * We should deactivate the struct STA_RECORD of + * previous AP before activate new one in Driver. + */ + /* cnmStaRecChangeState(prStaRec, STA_STATE_3); */ + /* Clear history. */ + prStaRec->ucJoinFailureCount = 0; + + if (saaFsmSendEventJoinComplete(prAdapter, + WLAN_STATUS_SUCCESS, + prStaRec, prSwRfb) == WLAN_STATUS_RESOURCES) { + /* can set a timer and retry later */ + DBGLOG(SAA, WARN, + "[SAA]can't alloc msg for inform AIS join complete\n"); + } + + rStatus = WLAN_STATUS_PENDING; + } else { + DBGLOG(SAA, INFO, + "Assoc Req was rejected by [" MACSTR + "], Status Code = %d\n", + MAC2STR(prStaRec->aucMacAddr), u2StatusCode); + + if (saaFsmSendEventJoinComplete(prAdapter, + WLAN_STATUS_FAILURE, + prStaRec, NULL) == WLAN_STATUS_RESOURCES) { + /* can set a timer and retry later */ + DBGLOG(SAA, WARN, + "[SAA]can't alloc msg for inform AIS join complete\n"); + } + } + } else { +#endif + 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 */ + ASSERT(prSwRfb->prRxStatusGroup3); + prStaRec->ucRCPI = nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0, prSwRfb); + + eNextState = AA_STATE_IDLE; + + saaFsmSteps(prAdapter, prStaRec, eNextState, prRetainedSwRfb); + } + break; + + default: + break; /* Ignore other cases */ + } +#if CFG_SUPPORT_CFG80211_AUTH + } +#endif + return rStatus; + +} /* end of saaFsmRunEventRxAssoc() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will check the incoming Deauth Frame. +* +* @param[in] prSwRfb Pointer to the SW_RFB_T structure. +* +* @retval WLAN_STATUS_SUCCESS Always not retain deauthentication frames +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS saaFsmRunEventRxDeauth(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_STA_RECORD_T prStaRec; + P_WLAN_DEAUTH_FRAME_T prDeauthFrame; + UINT_8 ucWlanIdx; + + ASSERT(prSwRfb); + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + prDeauthFrame = (P_WLAN_DEAUTH_FRAME_T) prSwRfb->pvHeader; + ucWlanIdx = (UINT_8) HAL_RX_STATUS_GET_WLAN_IDX(prSwRfb->prRxStatus); + + DBGLOG(SAA, EVENT, + "Rx Deauth frame ,DA[" MACSTR "] SA[" MACSTR "] BSSID[" + MACSTR "] ReasonCode[0x%x]\n", + MAC2STR(prDeauthFrame->aucDestAddr), MAC2STR(prDeauthFrame->aucSrcAddr), + MAC2STR(prDeauthFrame->aucBSSID), prDeauthFrame->u2ReasonCode); + + do { + + /* We should have the corresponding Sta Record. */ + if (!prStaRec) { + DBGLOG(SAA, WARN, "Received a Deauth: wlanIdx[%d] w/o corresponding staRec\n", ucWlanIdx); + break; + } + + if (IS_STA_IN_AIS(prStaRec)) { + P_BSS_INFO_T prAisBssInfo; + + if (!IS_AP_STA(prStaRec)) + break; + + prAisBssInfo = prAdapter->prAisBssInfo; + + 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 CFG_SUPPORT_802_11W + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + prAisSpecBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); + + DBGLOG(RSN, INFO, + "QM RX MGT: Deauth frame, P=%d Sec=%d CM=%d BC=%d fc=%02x\n", + prAisSpecBssInfo-> + fgMgmtProtection, (uint8_t) + HAL_RX_STATUS_GET_SEC_MODE + (prSwRfb->prRxStatus), + HAL_RX_STATUS_IS_CIPHER_MISMATCH + (prSwRfb->prRxStatus), + IS_BMCAST_MAC_ADDR + (prDeauthFrame->aucDestAddr), + prDeauthFrame->u2FrameCtrl); + if (prAisSpecBssInfo->fgMgmtProtection + && HAL_RX_STATUS_IS_CIPHER_MISMATCH(prSwRfb->prRxStatus) + /* HAL_RX_STATUS_GET_SEC_MODE(prSwRfb->prRxStatus) != CIPHER_SUITE_BIP */ + ) { + saaChkDeauthfrmParamHandler(prAdapter, prSwRfb, prStaRec); + return WLAN_STATUS_SUCCESS; + } +#endif +#if CFG_SUPPORT_CFG80211_AUTH + DBGLOG(SAA, INFO, "notification of RX deauthentication %d\n", + prSwRfb->u2PacketLen); + cfg80211_rx_mlme_mgmt(prAdapter->prGlueInfo->prDevHandler, + (PUINT_8)prDeauthFrame, (size_t)prSwRfb->u2PacketLen); + DBGLOG(SAA, INFO, "notification of RX deauthentication Done\n"); +#endif +#if CFG_DISCONN_DEBUG_FEATURE + g_rDisconnInfoTemp.u2DisassocSeqNum = + (prDeauthFrame->u2SeqCtrl & + MASK_SC_SEQ_NUM) >> + MASK_SC_SEQ_NUM_OFFSET; +#endif + saaSendDisconnectMsgHandler(prAdapter, prStaRec, prAisBssInfo, FRM_DEAUTH); + } + } + } +#if CFG_ENABLE_WIFI_DIRECT + else if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { + /* TODO(Kevin) */ +#if CFG_SUPPORT_CFG80211_AUTH + DBGLOG(SAA, INFO, "notification of RX deauthentication %d\n", + prSwRfb->u2PacketLen); + cfg80211_rx_mlme_mgmt(prAdapter->prGlueInfo->prDevHandler, + (PUINT_8)prDeauthFrame, (size_t)prSwRfb->u2PacketLen); + DBGLOG(SAA, INFO, "notification of RX deauthentication Done\n"); +#endif + p2pRoleFsmRunEventRxDeauthentication(prAdapter, prStaRec, prSwRfb); + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (IS_STA_BOW_TYPE(prStaRec)) + bowRunEventRxDeAuth(prAdapter, prStaRec, prSwRfb); +#endif + else + ASSERT(0); + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; + +} /* end of saaFsmRunEventRxDeauth() */ + +/* for AOSP */ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will check param of deauth frame and reson code for deauth +* +* @param[in] +* +* @retval +*/ +/*----------------------------------------------------------------------------*/ + +VOID saaChkDeauthfrmParamHandler(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN P_STA_RECORD_T prStaRec) +{ + P_WLAN_DEAUTH_FRAME_T prDeauthFrame; + + do { + prDeauthFrame = (P_WLAN_DEAUTH_FRAME_T) prSwRfb->pvHeader; + if (!IS_BMCAST_MAC_ADDR(prDeauthFrame->aucDestAddr) && + (prStaRec->u2ReasonCode == REASON_CODE_CLASS_2_ERR + || prStaRec->u2ReasonCode == REASON_CODE_CLASS_3_ERR)) { + DBGLOG(RSN, INFO, "QM RX MGT: rsnStartSaQuery\n"); + /* MFP test plan 5.3.3.5 */ + rsnStartSaQuery(prAdapter); + } else { + DBGLOG(RSN, INFO, "RXM: Drop unprotected Mgmt frame\n"); + DBGLOG(RSN, INFO, + "RXM: (MAC RX Done) RX (u2StatusFlag=0x%x) (ucKIdxSecMode=0x%x) (ucWlanIdx=0x%x)\n", + prSwRfb->prRxStatus->u2StatusFlag, + prSwRfb->prRxStatus->ucTidSecMode, prSwRfb->prRxStatus->ucWlanIdx); + } + } while (0); +} + +/* for AOSP */ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will check and send disconnect message to AIS module +* +* @param[in] +* +* @retval +*/ +/*----------------------------------------------------------------------------*/ +VOID +saaSendDisconnectMsgHandler(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_BSS_INFO_T prAisBssInfo, + IN ENUM_AA_FRM_TYPE_T eFrmType) +{ + do { + if (eFrmType == FRM_DEAUTH) { + if (prStaRec->ucStaState == STA_STATE_3) { + 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 */ + } + } else { /* FRM_DISASSOC */ + if (prStaRec->ucStaState == STA_STATE_3) { + 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 (prAisBssInfo) + prAisBssInfo->u2DeauthReason = prStaRec->u2ReasonCode; +#if CFG_DISCONN_DEBUG_FEATURE + g_rDisconnInfoTemp.ucTrigger = + DISCONNECT_TRIGGER_PASSIVE; + g_rDisconnInfoTemp.ucDisassocReason = + prStaRec->u2ReasonCode; +#endif + } while (0); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will check the incoming Disassociation Frame. +* +* @param[in] prSwRfb Pointer to the SW_RFB_T structure. +* +* @retval WLAN_STATUS_SUCCESS Always not retain disassociation frames +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS saaFsmRunEventRxDisassoc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_STA_RECORD_T prStaRec; + P_WLAN_DISASSOC_FRAME_T prDisassocFrame; + UINT_8 ucWlanIdx; + + ASSERT(prSwRfb); + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + prDisassocFrame = (P_WLAN_DISASSOC_FRAME_T) prSwRfb->pvHeader; + ucWlanIdx = (UINT_8) HAL_RX_STATUS_GET_WLAN_IDX(prSwRfb->prRxStatus); + + DBGLOG(SAA, EVENT, + "Rx Disassoc frame from BSSID[" MACSTR "] DA[" MACSTR "] ReasonCode[0x%x]\n", + MAC2STR(prDisassocFrame->aucBSSID), MAC2STR(prDisassocFrame->aucDestAddr), + prDisassocFrame->u2ReasonCode); + + do { + + /* We should have the corresponding Sta Record. */ + if (!prStaRec) { + DBGLOG(SAA, WARN, "Received a DisAssoc: wlanIdx[%d] w/o corresponding staRec\n", ucWlanIdx); + break; + } + + if (IS_STA_IN_AIS(prStaRec)) { + P_BSS_INFO_T prAisBssInfo; + + if (!IS_AP_STA(prStaRec)) + break; + + prAisBssInfo = prAdapter->prAisBssInfo; + + 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 CFG_SUPPORT_802_11W + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + prAisSpecBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); + + DBGLOG(RSN, INFO, + "QM RX MGT: Disassoc frame, P=%d Sec=%d CM=%d BC=%d fc=%02x\n", + prAisSpecBssInfo-> + fgMgmtProtection, (uint8_t) + HAL_RX_STATUS_GET_SEC_MODE + (prSwRfb->prRxStatus), + HAL_RX_STATUS_IS_CIPHER_MISMATCH + (prSwRfb->prRxStatus), + IS_BMCAST_MAC_ADDR + (prDisassocFrame->aucDestAddr), + prDisassocFrame->u2FrameCtrl); + + if (IS_STA_IN_AIS(prStaRec) + && prAisSpecBssInfo->fgMgmtProtection + && HAL_RX_STATUS_IS_CIPHER_MISMATCH(prSwRfb->prRxStatus) + /* HAL_RX_STATUS_GET_SEC_MODE(prSwRfb->prRxStatus) != CIPHER_SUITE_CCMP */ + ) { + /* prDisassocFrame = (P_WLAN_DISASSOC_FRAME_T) prSwRfb->pvHeader; */ + saaChkDisassocfrmParamHandler(prAdapter, prDisassocFrame, prStaRec, + prSwRfb); + return WLAN_STATUS_SUCCESS; + } +#endif +#if CFG_SUPPORT_CFG80211_AUTH + DBGLOG(SAA, INFO, "notification of RX disassociation %d\n", + prSwRfb->u2PacketLen); + cfg80211_rx_mlme_mgmt(prAdapter->prGlueInfo->prDevHandler, + (PUINT_8)prDisassocFrame, (size_t)prSwRfb->u2PacketLen); + DBGLOG(SAA, INFO, "notification of RX disassociation Done\n"); +#endif +#if CFG_DISCONN_DEBUG_FEATURE + g_rDisconnInfoTemp.u2DisassocSeqNum = + (prDisassocFrame->u2SeqCtrl & + MASK_SC_SEQ_NUM) >> + MASK_SC_SEQ_NUM_OFFSET; +#endif + saaSendDisconnectMsgHandler(prAdapter, prStaRec, prAisBssInfo, FRM_DISASSOC); + } + } + } +#if CFG_ENABLE_WIFI_DIRECT + else if (prAdapter->fgIsP2PRegistered && (IS_STA_IN_P2P(prStaRec))) { + /* TODO(Kevin) */ +#if CFG_SUPPORT_CFG80211_AUTH + DBGLOG(SAA, INFO, "notification of RX disassociation %d\n", + prSwRfb->u2PacketLen); + cfg80211_rx_mlme_mgmt(prAdapter->prGlueInfo->prDevHandler, + (PUINT_8)prDisassocFrame, (size_t)prSwRfb->u2PacketLen); + DBGLOG(SAA, INFO, "notification of RX disassociation Done\n"); +#endif + p2pRoleFsmRunEventRxDisassociation(prAdapter, prStaRec, prSwRfb); + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (IS_STA_BOW_TYPE(prStaRec)) { + /* ToDo:: nothing */ + /* TODO(Kevin) */ +#if CFG_SUPPORT_CFG80211_AUTH + DBGLOG(SAA, INFO, "notification of RX disassociation %d\n", + prSwRfb->u2PacketLen); + cfg80211_rx_mlme_mgmt(prAdapter->prGlueInfo->prDevHandler, + (PUINT_8)prDisassocFrame, (size_t)prSwRfb->u2PacketLen); + DBGLOG(SAA, INFO, "notification of RX disassociation Done\n"); +#endif + } +#endif + else + ASSERT(0); + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; + +} /* end of saaFsmRunEventRxDisassoc() */ + +/* for AOSP */ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will check param of Disassoc frame and reson code for Disassoc +* +* @param[in] +* +* @retval +*/ +/*----------------------------------------------------------------------------*/ + +VOID +saaChkDisassocfrmParamHandler(IN P_ADAPTER_T prAdapter, + IN P_WLAN_DISASSOC_FRAME_T prDisassocFrame, IN P_STA_RECORD_T prStaRec, + IN P_SW_RFB_T prSwRfb) +{ + if (!IS_BMCAST_MAC_ADDR(prDisassocFrame->aucDestAddr) && + (prStaRec->u2ReasonCode == REASON_CODE_CLASS_2_ERR || prStaRec->u2ReasonCode == REASON_CODE_CLASS_3_ERR)) { + /* MFP test plan 5.3.3.5 */ + DBGLOG(RSN, INFO, "QM RX MGT: rsnStartSaQuery\n"); + rsnStartSaQuery(prAdapter); + } else { + DBGLOG(RSN, INFO, "RXM: Drop unprotected Mgmt frame\n"); + DBGLOG(RSN, INFO, + "RXM: (MAC RX Done) RX (u2StatusFlag=0x%x) (ucKIdxSecMode=0x%x) (ucWlanIdx=0x%x)\n", + prSwRfb->prRxStatus->u2StatusFlag, + prSwRfb->prRxStatus->ucTidSecMode, prSwRfb->prRxStatus->ucWlanIdx); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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) { + DBGLOG(SAA, LOUD, "EVENT-ABORT: Previous Auth/Assoc State == %s.\n", + apucDebugAAState[prStaRec->eAuthAssocState]); + } +#if 0 + /* For the Auth/Assoc State to IDLE */ + prStaRec->eAuthAssocState = AA_STATE_IDLE; +#else + /* Free this StaRec */ + cnmStaRecFree(prAdapter, prStaRec); +#endif +} /* end of saaFsmRunEventAbort() */ + +/* TODO(Kevin): following code will be modified and move to AIS FSM */ +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will send Join Timeout Event to JOIN FSM. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \retval WLAN_STATUS_FAILURE Fail because of Join Timeout +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS joinFsmRunEventJoinTimeOut(IN P_ADAPTER_T prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("joinFsmRunEventJoinTimeOut"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + + DBGLOG(JOIN, EVENT, "JOIN EVENT: JOIN TIMEOUT\n"); + + /* Get a Station Record if possible, TA == BSSID for AP */ + prStaRec = staRecGetStaRecordByAddr(prAdapter, prJoinInfo->prBssDesc->aucBSSID); + + /* We have renew this Sta Record when in JOIN_STATE_INIT */ + ASSERT(prStaRec); + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_JOIN_TIMEOUT; + + /* Increase Failure Count */ + prStaRec->ucJoinFailureCount++; + + /* Reset Send Auth/(Re)Assoc Frame Count */ + prJoinInfo->ucTxAuthAssocRetryCount = 0; + + /* Cancel other JOIN relative Timer */ + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rTxRequestTimer); + + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rRxResponseTimer); + + /* Restore original setting from current BSS_INFO_T */ + if (prAdapter->eConnectionState == MEDIA_STATE_CONNECTED) + joinAdoptParametersFromCurrentBss(prAdapter); + + /* Pull back to IDLE */ + joinFsmSteps(prAdapter, JOIN_STATE_IDLE); + + return WLAN_STATUS_FAILURE; + +} /* end of joinFsmRunEventJoinTimeOut() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will adopt the parameters from Peer BSS. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID joinAdoptParametersFromPeerBss(IN P_ADAPTER_T prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + P_BSS_DESC_T prBssDesc; + + DEBUGFUNC("joinAdoptParametersFromPeerBss"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + prBssDesc = prJoinInfo->prBssDesc; + + /* 4 <1> Adopt Peer BSS' PHY TYPE */ + prAdapter->eCurrentPhyType = prBssDesc->ePhyType; + + DBGLOG(JOIN, INFO, "Target BSS[%s]'s PhyType = %s\n", + prBssDesc->aucSSID, (prBssDesc->ePhyType == PHY_TYPE_ERP_INDEX) ? "ERP" : "HR_DSSS"); + + /* 4 <2> Adopt Peer BSS' Frequency(Band/Channel) */ + DBGLOG(JOIN, INFO, "Target BSS's Channel = %d, Band = %d\n", prBssDesc->ucChannelNum, prBssDesc->eBand); + + nicSwitchChannel(prAdapter, prBssDesc->eBand, prBssDesc->ucChannelNum, 10); + + prJoinInfo->fgIsParameterAdopted = TRUE; +} /* end of joinAdoptParametersFromPeerBss() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will adopt the parameters from current associated BSS. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID joinAdoptParametersFromCurrentBss(IN P_ADAPTER_T prAdapter) +{ + /* P_JOIN_INFO_T prJoinInfo = &prAdapter->rJoinInfo; */ + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + prBssInfo = &prAdapter->rBssInfo; + + /* 4 <1> Adopt current BSS' PHY TYPE */ + prAdapter->eCurrentPhyType = prBssInfo->ePhyType; + + /* 4 <2> Adopt current BSS' Frequency(Band/Channel) */ + DBGLOG(JOIN, INFO, "Current BSS's Channel = %d, Band = %d\n", prBssInfo->ucChnl, prBssInfo->eBand); + + nicSwitchChannel(prAdapter, prBssInfo->eBand, prBssInfo->ucChnl, 10); +} /* end of joinAdoptParametersFromCurrentBss() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will update all the SW variables and HW MCR registers after +* the association with target BSS. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID joinComplete(IN P_ADAPTER_T prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + P_BSS_DESC_T prBssDesc; + P_PEER_BSS_INFO_T prPeerBssInfo; + P_BSS_INFO_T prBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_STA_RECORD_T prStaRec; + P_TX_CTRL_T prTxCtrl; +#if CFG_SUPPORT_802_11D + P_IE_COUNTRY_T prIECountry; +#endif + + DEBUGFUNC("joinComplete"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + prBssDesc = prJoinInfo->prBssDesc; + prPeerBssInfo = &prAdapter->rPeerBssInfo; + prBssInfo = &prAdapter->rBssInfo; + prConnSettings = &prAdapter->rConnSettings; + prTxCtrl = &prAdapter->rTxCtrl; + +/* 4 <1> Update Connecting & Connected Flag of BSS_DESC_T. */ + /* Remove previous AP's Connection Flags if have */ + scanRemoveConnectionFlagOfBssDescByBssid(prAdapter, prBssInfo->aucBSSID); + + prBssDesc->fgIsConnected = TRUE; /* Mask as Connected */ + + if (prBssDesc->fgIsHiddenSSID) { + /* NOTE(Kevin): This is for the case of Passive Scan and the target BSS didn't + * broadcast SSID on its Beacon Frame. + */ + COPY_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, prAdapter->rConnSettings.aucSSID, prAdapter->rConnSettings.ucSSIDLen); + + if (prBssDesc->ucSSIDLen) + prBssDesc->fgIsHiddenSSID = FALSE; +#if DBG + else + ASSERT(0); +#endif /* DBG */ + + DBGLOG(JOIN, INFO, "Hidden SSID! - Update SSID : %s\n", prBssDesc->aucSSID); + } + +/* 4 <2> Update BSS_INFO_T from BSS_DESC_T */ + /* 4 <2.A> PHY Type */ + prBssInfo->ePhyType = prBssDesc->ePhyType; + + /* 4 <2.B> BSS Type */ + prBssInfo->eBSSType = BSS_TYPE_INFRASTRUCTURE; + + /* 4 <2.C> BSSID */ + COPY_MAC_ADDR(prBssInfo->aucBSSID, prBssDesc->aucBSSID); + + DBGLOG(JOIN, INFO, "JOIN to BSSID: [" 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 Information */ + if (prAdapter->fgIsEnableWMM && (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_SUPPORT_WMM)) { + + prBssInfo->fgIsWmmAssoc = TRUE; + prTxCtrl->rTxQForVoipAccess = TXQ_AC3; + + qosWmmInfoInit(&prBssInfo->rWmmInfo, (prBssInfo->ePhyType == PHY_TYPE_HR_DSSS_INDEX) ? TRUE : FALSE); + + if (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_AC_PARAM_PRESENT) { + kalMemCopy(&prBssInfo->rWmmInfo, &prPeerBssInfo->rWmmInfo, sizeof(WMM_INFO_T)); + } else { + kalMemCopy(&prBssInfo->rWmmInfo, + &prPeerBssInfo->rWmmInfo, + sizeof(WMM_INFO_T) - sizeof(prPeerBssInfo->rWmmInfo.arWmmAcParams)); + } + } else { + prBssInfo->fgIsWmmAssoc = FALSE; + prTxCtrl->rTxQForVoipAccess = TXQ_AC1; + + kalMemZero(&prBssInfo->rWmmInfo, sizeof(WMM_INFO_T)); + } + + /* 4 <3.C> Operational Rate Set & BSS Basic Rate Set */ + prBssInfo->u2OperationalRateSet = prPeerBssInfo->u2OperationalRateSet; + prBssInfo->u2BSSBasicRateSet = prPeerBssInfo->u2BSSBasicRateSet; + + /* 4 <3.D> Short Preamble */ + if (prBssInfo->fgIsERPPresent) { + + /* NOTE(Kevin 2007/12/24): Truth Table. + * Short Preamble Bit in + * Final Driver Setting(Short) + * TRUE FALSE FALSE FALSE(shouldn't have such case, use the AssocResp) + * TRUE FALSE TRUE FALSE + * FALSE FALSE FALSE FALSE(shouldn't have such case, use the AssocResp) + * FALSE FALSE TRUE FALSE + * TRUE TRUE FALSE TRUE(follow ERP) + * TRUE TRUE TRUE FALSE(follow ERP) + * FALSE TRUE FALSE FALSE(shouldn't have such case, and we should set to FALSE) + * FALSE TRUE TRUE FALSE(we should set to FALSE) + */ + if ((prPeerBssInfo->fgIsShortPreambleAllowed) && + ((prConnSettings->ePreambleType == PREAMBLE_TYPE_SHORT) || + /* Short Preamble Option Enable is TRUE */ + ((prConnSettings->ePreambleType == PREAMBLE_TYPE_AUTO) && + (prBssDesc->u2CapInfo & CAP_INFO_SHORT_PREAMBLE)))) { + + prBssInfo->fgIsShortPreambleAllowed = TRUE; + + if (prBssInfo->ucERP & ERP_INFO_BARKER_PREAMBLE_MODE) + prBssInfo->fgUseShortPreamble = FALSE; + else + prBssInfo->fgUseShortPreamble = TRUE; + } else { + prBssInfo->fgIsShortPreambleAllowed = FALSE; + prBssInfo->fgUseShortPreamble = FALSE; + } + } else { + /* NOTE(Kevin 2007/12/24): Truth Table. + * Short Preamble Bit in + * Final Driver Setting(Short) + * TRUE FALSE FALSE + * FALSE FALSE FALSE + * TRUE TRUE TRUE + * FALSE TRUE(status success) TRUE + * --> Honor the result of prPeerBssInfo. + */ + + prBssInfo->fgIsShortPreambleAllowed = prBssInfo->fgUseShortPreamble = + prPeerBssInfo->fgIsShortPreambleAllowed; + } + + DBGLOG(JOIN, INFO, + "prBssInfo->fgIsShortPreambleAllowed = %d, prBssInfo->fgUseShortPreamble = %d\n", + prBssInfo->fgIsShortPreambleAllowed, prBssInfo->fgUseShortPreamble); + + /* 4 <3.E> Short Slot Time */ + prBssInfo->fgUseShortSlotTime = prPeerBssInfo->fgUseShortSlotTime; /* AP support Short Slot Time */ + + DBGLOG(JOIN, INFO, "prBssInfo->fgUseShortSlotTime = %d\n", prBssInfo->fgUseShortSlotTime); + + nicSetSlotTime(prAdapter, + prBssInfo->ePhyType, + ((prConnSettings->fgIsShortSlotTimeOptionEnable && + prBssInfo->fgUseShortSlotTime) ? TRUE : FALSE)); + + /* 4 <3.F> Update Tx Rate for Control Frame */ + bssUpdateTxRateForControlFrame(prAdapter); + + /* 4 <3.G> Save the available Auth Types during Roaming (Design for Fast BSS Transition). */ + /* if (prAdapter->fgIsEnableRoaming) *//* NOTE(Kevin): Always prepare info for roaming */ + { + + if (prJoinInfo->ucCurrAuthAlgNum == AUTH_ALGORITHM_NUM_OPEN_SYSTEM) + prJoinInfo->ucRoamingAuthTypes |= AUTH_TYPE_OPEN_SYSTEM; + else if (prJoinInfo->ucCurrAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY) + prJoinInfo->ucRoamingAuthTypes |= AUTH_TYPE_SHARED_KEY; + + prBssInfo->ucRoamingAuthTypes = prJoinInfo->ucRoamingAuthTypes; + + /* Set the stable time of the associated BSS. We won't do roaming decision + * during the stable time. + */ + SET_EXPIRATION_TIME(prBssInfo->rRoamingStableExpirationTime, + SEC_TO_SYSTIME(ROAMING_STABLE_TIMEOUT_SEC)); + } + + /* 4 <3.H> Update Parameter for TX Fragmentation Threshold */ +#if CFG_TX_FRAGMENT + txFragInfoUpdate(prAdapter); +#endif /* CFG_TX_FRAGMENT */ + +/* 4 <4> Update STA_RECORD_T */ + /* Get a Station Record if possible */ + prStaRec = staRecGetStaRecordByAddr(prAdapter, prBssDesc->aucBSSID); + + if (prStaRec) { + UINT_16 u2OperationalRateSet, u2DesiredRateSet; + + /* 4 <4.A> Desired Rate Set */ + u2OperationalRateSet = (rPhyAttributes[prBssInfo->ePhyType].u2SupportedRateSet & + prBssInfo->u2OperationalRateSet); + + u2DesiredRateSet = (u2OperationalRateSet & prConnSettings->u2DesiredRateSet); + if (u2DesiredRateSet) { + prStaRec->u2DesiredRateSet = u2DesiredRateSet; + } else { + /* For Error Handling - The Desired Rate Set is not covered in Operational Rate Set. */ + prStaRec->u2DesiredRateSet = u2OperationalRateSet; + } + + /* Try to set the best initial rate for this entry */ + if (!rateGetBestInitialRateIndex(prStaRec->u2DesiredRateSet, + prStaRec->rRcpi, &prStaRec->ucCurrRate1Index)) { + + if (!rateGetLowestRateIndexFromRateSet(prStaRec->u2DesiredRateSet, &prStaRec->ucCurrRate1Index)) + ASSERT(0); + } + + DBGLOG(JOIN, INFO, "prStaRec->ucCurrRate1Index = %d\n", prStaRec->ucCurrRate1Index); + + /* 4 <4.B> Preamble Mode */ + prStaRec->fgIsShortPreambleOptionEnable = prBssInfo->fgUseShortPreamble; + + /* 4 <4.C> QoS Flag */ + prStaRec->fgIsQoS = prBssInfo->fgIsWmmAssoc; + } +#if DBG + else + ASSERT(0); +#endif /* DBG */ + +/* 4 <5> Update NIC */ + /* 4 <5.A> Update BSSID & Operation Mode */ + nicSetupBSS(prAdapter, prBssInfo); + + /* 4 <5.B> Update WLAN Table. */ + if (nicSetHwBySta(prAdapter, prStaRec) == FALSE) + ASSERT(FALSE); + /* 4 <5.C> Update Desired Rate Set for BT. */ +#if CFG_TX_FRAGMENT + if (prConnSettings->fgIsEnableTxAutoFragmentForBT) + txRateSetInitForBT(prAdapter, prStaRec); +#endif /* CFG_TX_FRAGMENT */ + + /* 4 <5.D> TX AC Parameter and TX/RX Queue Control */ + if (prBssInfo->fgIsWmmAssoc) { + +#if CFG_TX_AGGREGATE_HW_FIFO + nicTxAggregateTXQ(prAdapter, FALSE); +#endif /* CFG_TX_AGGREGATE_HW_FIFO */ + + qosUpdateWMMParametersAndAssignAllowedACI(prAdapter, &prBssInfo->rWmmInfo); + } else { + +#if CFG_TX_AGGREGATE_HW_FIFO + nicTxAggregateTXQ(prAdapter, TRUE); +#endif /* CFG_TX_AGGREGATE_HW_FIFO */ + + nicTxNonQoSAssignDefaultAdmittedTXQ(prAdapter); + + nicTxNonQoSUpdateTXQParameters(prAdapter, prBssInfo->ePhyType); + } + +#if CFG_TX_STOP_WRITE_TX_FIFO_UNTIL_JOIN + { + prTxCtrl->fgBlockTxDuringJoin = FALSE; + +#if !CFG_TX_AGGREGATE_HW_FIFO /* TX FIFO AGGREGATE already do flush once */ + nicTxFlushStopQueues(prAdapter, (UINT_8) TXQ_DATA_MASK, (UINT_8) NULL); +#endif /* CFG_TX_AGGREGATE_HW_FIFO */ + + nicTxRetransmitOfSendWaitQue(prAdapter); + + if (prTxCtrl->fgIsPacketInOsSendQueue) + nicTxRetransmitOfOsSendQue(prAdapter); +#if CFG_SDIO_TX_ENHANCE + halTxLeftClusteredMpdu(prAdapter); +#endif /* CFG_SDIO_TX_ENHANCE */ + + } +#endif /* CFG_TX_STOP_WRITE_TX_FIFO_UNTIL_JOIN */ + +/* 4 <6> Setup CONNECTION flag. */ + prAdapter->eConnectionState = MEDIA_STATE_CONNECTED; + prAdapter->eConnectionStateIndicated = MEDIA_STATE_CONNECTED; + + if (prJoinInfo->fgIsReAssoc) + prAdapter->fgBypassPortCtrlForRoaming = TRUE; + else + prAdapter->fgBypassPortCtrlForRoaming = FALSE; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_CONNECT, (PVOID) NULL, 0); +} /* end of joinComplete() */ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/scan.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/scan.c new file mode 100644 index 0000000000000..e4b560a5c9f5a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/scan.c @@ -0,0 +1,2778 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/scan.c#4 +*/ + +/*! \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. +*/ + + +/******************************************************************************* +* C O M P I L E 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; +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + P_ROAM_BSS_DESC_T prRoamBSSDesc; + PUINT_8 pucRoamBSSBuff; +#endif + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + pucBSSBuff = &prScanInfo->aucScanBuffer[0]; +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + pucRoamBSSBuff = &prScanInfo->aucScanRoamBuffer[0]; +#endif + + 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); +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + kalMemZero((PVOID) pucRoamBSSBuff, SCN_ROAM_MAX_BUFFER_SIZE); +#endif + + LINK_INITIALIZE(&prScanInfo->rFreeBSSDescList); + LINK_INITIALIZE(&prScanInfo->rBSSDescList); +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + LINK_INITIALIZE(&prScanInfo->rRoamFreeBSSDescList); + LINK_INITIALIZE(&prScanInfo->rRoamBSSDescList); +#endif + + for (i = 0; i < CFG_MAX_NUM_BSS_LIST; i++) { + + prBSSDesc = (P_BSS_DESC_T) pucBSSBuff; + + LINK_INSERT_TAIL(&prScanInfo->rFreeBSSDescList, &prBSSDesc->rLinkEntry); + + pucBSSBuff += ALIGN_4(sizeof(BSS_DESC_T)); + } + /* Check if the memory allocation consist with this initialization function */ + ASSERT(((ULONG) pucBSSBuff - (ULONG)&prScanInfo->aucScanBuffer[0]) == SCN_MAX_BUFFER_SIZE); + +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + for (i = 0; i < CFG_MAX_NUM_ROAM_BSS_LIST; i++) { + prRoamBSSDesc = (P_ROAM_BSS_DESC_T) pucRoamBSSBuff; + + LINK_INSERT_TAIL(&prScanInfo->rRoamFreeBSSDescList, &prRoamBSSDesc->rLinkEntry); + + pucRoamBSSBuff += ALIGN_4(sizeof(ROAM_BSS_DESC_T)); + } + ASSERT(((ULONG) pucRoamBSSBuff - (ULONG)&prScanInfo->aucScanRoamBuffer[0]) == + SCN_ROAM_MAX_BUFFER_SIZE); +#endif + /* reset freest channel information */ + prScanInfo->fgIsSparseChannelValid = FALSE; + + /* reset NLO state */ + prScanInfo->fgNloScanning = FALSE; +} /* end of scnInit() */ + +VOID scnFreeAllPendingScanRquests(IN P_ADAPTER_T prAdapter) +{ + P_SCAN_INFO_T prScanInfo; + P_MSG_HDR_T prMsgHdr; + P_MSG_SCN_SCAN_REQ prScanReqMsg; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + /* check for pending scanning requests */ + while (!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) { + prScanReqMsg = (P_MSG_SCN_SCAN_REQ) prMsgHdr; + DBGLOG(SCN, INFO, + "free scan request eMsgId[%d] ucSeqNum [%d] BSSID[%d]!!\n", prMsgHdr->eMsgId, + prScanReqMsg->ucSeqNum, prScanReqMsg->ucBssIndex); + cnmMemFree(prAdapter, prMsgHdr); + } else { + /* should not deliver to this function */ + ASSERT(0); + } + /* switch to next state */ + } + + DBGLOG(SCN, INFO, "%s()\n", __func__); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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, "%s()\n", __func__); + + scnFreeAllPendingScanRquests(prAdapter); + + /* 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); +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + LINK_INITIALIZE(&prScanInfo->rRoamFreeBSSDescList); + LINK_INITIALIZE(&prScanInfo->rRoamBSSDescList); +#endif +} /* 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))) + continue; + if (fgCheckSsid == FALSE || prSsid == NULL) + return prBssDesc; + if (EQUAL_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, prSsid->aucSsid, prSsid->u4SsidLen)) { + return prBssDesc; + } + if (prDstBssDesc == NULL && prBssDesc->fgIsHiddenSSID == TRUE) { + prDstBssDesc = prBssDesc; + continue; + } + if (prBssDesc->eBSSType == BSS_TYPE_P2P_DEVICE) { + /* 20120206 frog: Equal BSSID but not SSID, + * SSID not hidden, SSID must be updated. + */ + COPY_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, prSsid->aucSsid, + (UINT_8) (prSsid->u4SsidLen)); + return prBssDesc; + } + } + + return prDstBssDesc; + +} /* end of scanSearchBssDescByBssid() */ + +#if CFG_SUPPORT_CFG80211_AUTH +/*----------------------------------------------------------------------------*/ +/*! +* @brief Find the corresponding BSS Descriptor +* according to given BSSID & ChanNum +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] aucBSSID Given BSSID. +* @param[in] fgCheckChanNum Need to check ChanNum or not. +* @param[in] ucChannelNum Specified Channel Num +* +* @return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T scanSearchBssDescByBssidAndChanNum(IN P_ADAPTER_T prAdapter, + IN UINT_8 aucBSSID[], IN BOOLEAN fgCheckChanNum, IN UINT_8 ucChannelNum) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; + + ASSERT(prAdapter); + ASSERT(aucBSSID); + ASSERT(ucChannelNum); + + 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))) + continue; + if (fgCheckChanNum == FALSE || ucChannelNum == 0) + return prBssDesc; + if (prBssDesc->ucChannelNum == ucChannelNum) + return prBssDesc; + } + + return prBssDesc; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Find the corresponding BSS Descriptor according to given Transmitter Address. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] aucSrcAddr Given Source Address(TA). +* +* @return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T scanSearchBssDescByTA(IN P_ADAPTER_T prAdapter, IN UINT_8 aucSrcAddr[]) +{ + return scanSearchBssDescByTAAndSsid(prAdapter, aucSrcAddr, FALSE, NULL); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Find the corresponding BSS Descriptor according to given Transmitter Address. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] aucSrcAddr Given Source Address(TA). +* @param[in] fgCheckSsid Need to check SSID or not. (for multiple SSID with single BSSID cases) +* @param[in] prSsid Specified SSID +* +* @return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T +scanSearchBssDescByTAAndSsid(IN P_ADAPTER_T prAdapter, + IN UINT_8 aucSrcAddr[], IN BOOLEAN fgCheckSsid, IN P_PARAM_SSID_T prSsid) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc; + P_BSS_DESC_T prDstBssDesc = (P_BSS_DESC_T) NULL; + + ASSERT(prAdapter); + ASSERT(aucSrcAddr); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prBSSDescList = &prScanInfo->rBSSDescList; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if (EQUAL_MAC_ADDR(prBssDesc->aucSrcAddr, aucSrcAddr)) { + if (fgCheckSsid == FALSE || prSsid == NULL) + return prBssDesc; + if (EQUAL_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, prSsid->aucSsid, prSsid->u4SsidLen)) { + return prBssDesc; + } else if (prDstBssDesc == NULL && prBssDesc->fgIsHiddenSSID == TRUE) { + prDstBssDesc = prBssDesc; + } + } + } + + return prDstBssDesc; + +} /* end of scanSearchBssDescByTA() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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); +} + +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param +* +* @return +*/ +/*----------------------------------------------------------------------------*/ +VOID scanRemoveRoamBssDescsByTime(IN P_ADAPTER_T prAdapter, IN UINT_32 u4RemoveTime) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prRoamBSSDescList; + P_LINK_T prRoamFreeBSSDescList; + P_ROAM_BSS_DESC_T prRoamBssDesc; + P_ROAM_BSS_DESC_T prRoamBSSDescNext; + OS_SYSTIME rCurrentTime; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prRoamBSSDescList = &prScanInfo->rRoamBSSDescList; + prRoamFreeBSSDescList = &prScanInfo->rRoamFreeBSSDescList; + + GET_CURRENT_SYSTIME(&rCurrentTime); + + LINK_FOR_EACH_ENTRY_SAFE(prRoamBssDesc, prRoamBSSDescNext, prRoamBSSDescList, rLinkEntry, + ROAM_BSS_DESC_T) { + + if (CHECK_FOR_TIMEOUT(rCurrentTime, prRoamBssDesc->rUpdateTime, + SEC_TO_SYSTIME(u4RemoveTime))) { + + LINK_REMOVE_KNOWN_ENTRY(prRoamBSSDescList, prRoamBssDesc); + LINK_INSERT_TAIL(prRoamFreeBSSDescList, &prRoamBssDesc->rLinkEntry); + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param +* +* @return +*/ +/*----------------------------------------------------------------------------*/ +P_ROAM_BSS_DESC_T +scanSearchRoamBssDescBySsid(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prRoamBSSDescList; + P_ROAM_BSS_DESC_T prRoamBssDesc; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prRoamBSSDescList = &prScanInfo->rRoamBSSDescList; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prRoamBssDesc, prRoamBSSDescList, rLinkEntry, ROAM_BSS_DESC_T) { + if (EQUAL_SSID(prRoamBssDesc->aucSSID, prRoamBssDesc->ucSSIDLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen)) { + return prRoamBssDesc; + } + } + + return NULL; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param +* +* @return +*/ +/*----------------------------------------------------------------------------*/ +P_ROAM_BSS_DESC_T scanAllocateRoamBssDesc(IN P_ADAPTER_T prAdapter) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prRoamFreeBSSDescList; + P_ROAM_BSS_DESC_T prRoamBssDesc = NULL; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prRoamFreeBSSDescList = &prScanInfo->rRoamFreeBSSDescList; + + LINK_REMOVE_HEAD(prRoamFreeBSSDescList, prRoamBssDesc, P_ROAM_BSS_DESC_T); + + if (prRoamBssDesc) { + P_LINK_T prRoamBSSDescList; + + kalMemZero(prRoamBssDesc, sizeof(ROAM_BSS_DESC_T)); + + prRoamBSSDescList = &prScanInfo->rRoamBSSDescList; + + LINK_INSERT_HEAD(prRoamBSSDescList, &prRoamBssDesc->rLinkEntry); + } + + return prRoamBssDesc; +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param +* +* @return +*/ +/*----------------------------------------------------------------------------*/ +VOID scanAddToRoamBssDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) +{ + P_ROAM_BSS_DESC_T prRoamBssDesc; + + prRoamBssDesc = scanSearchRoamBssDescBySsid(prAdapter, prBssDesc); + + if (prRoamBssDesc == NULL) { + UINT_32 u4RemoveTime = REMOVE_TIMEOUT_TWO_DAY; + + do { + prRoamBssDesc = scanAllocateRoamBssDesc(prAdapter); + if (prRoamBssDesc) + break; + scanRemoveRoamBssDescsByTime(prAdapter, u4RemoveTime); + u4RemoveTime = u4RemoveTime / 2; + } while (u4RemoveTime > 0); + + if (prRoamBssDesc != NULL) + COPY_SSID(prRoamBssDesc->aucSSID, prRoamBssDesc->ucSSIDLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + } + + if (prRoamBssDesc != NULL) + GET_CURRENT_SYSTIME(&prRoamBssDesc->rUpdateTime); +} + + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param +* +* @return +*/ +/*----------------------------------------------------------------------------*/ +VOID scanSearchBssDescOfRoamSsid(IN P_ADAPTER_T prAdapter) +{ +#define SSID_ONLY_EXIST_ONE_AP 1 /* If only exist one same ssid AP, avoid unnecessary scan */ + + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc; + P_BSS_INFO_T prAisBssInfo; + UINT_32 u4SameSSIDCount = 0; + + prAisBssInfo = prAdapter->prAisBssInfo; + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + + if (prAisBssInfo->eConnectionState != PARAM_MEDIA_STATE_CONNECTED) + return; + + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + if (EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, + prAisBssInfo->aucSSID, prAisBssInfo->ucSSIDLen)) { + u4SameSSIDCount++; + if (u4SameSSIDCount > SSID_ONLY_EXIST_ONE_AP) { + scanAddToRoamBssDesc(prAdapter, prBssDesc); + break; + } + } + } +} + +#endif /* CFG_SUPPORT_ROAMING_SKIP_ONE_AP */ + +/*----------------------------------------------------------------------------*/ +/*! +* @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; + /* CASE III */ + P_LINK_T prBSSDescList; + P_LINK_T prFreeBSSDescList; + + ASSERT(prAdapter); + ASSERT(aucSrcAddr); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + switch (eBSSType) { + case BSS_TYPE_P2P_DEVICE: + fgCheckSsid = FALSE; + /* fall through */ + case BSS_TYPE_INFRASTRUCTURE: +#if CFG_SUPPORT_ROAMING_SKIP_ONE_AP + scanSearchBssDescOfRoamSsid(prAdapter); + /* fall through */ +#endif + 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; + } + + + 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 bypass BSS Descriptors from current list according to specific BSSID. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] aucBSSID Given BSSID. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN scanByPassRemoveBssDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + UINT_8 ucIndex = 0; + BOOLEAN fgIsByPassRemove = FALSE; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + for (ucIndex = 0; ucIndex < prScanParam->ucSSIDNum; ucIndex++) { + if (EQUAL_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, + prScanParam->aucSpecifiedSSID[ucIndex], + prScanParam->ucSpecifiedSSIDLen[ucIndex])) { + fgIsByPassRemove = TRUE; + DBGLOG(INIT, INFO, "scanByPassRemoveBssDesc %s | %s\n", + prBssDesc->aucSSID, prScanParam->aucSpecifiedSSID[ucIndex]); + break; + } + } + return fgIsByPassRemove; +} + + + +/*----------------------------------------------------------------------------*/ +/*! +* @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 ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_SPECIFIC_SSID) && + scanByPassRemoveBssDesc(prAdapter, prBssDesc)) { + /* Don't remove the one currently we are looking for specifi SSID. */ + 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); + } + } + } + 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 ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_SPECIFIC_SSID) && + scanByPassRemoveBssDesc(prAdapter, prBssDesc)) { + /* Don't remove the one currently we are looking for specifi SSID. */ + 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); + } + } + 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 ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_SPECIFIC_SSID) && + scanByPassRemoveBssDesc(prAdapter, prBssDesc)) { + /* Don't remove the one currently we are looking for specifi SSID. */ + 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); + } + } + 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; + } + if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_SPECIFIC_SSID) && + scanByPassRemoveBssDesc(prAdapter, prBssDesc)) { + /* Don't remove the one currently we are looking for specifi SSID. */ + continue; + } + + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); + + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); + } + + } + + return; + +} /* end of scanRemoveBssDescsByPolicy() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Delete BSS Descriptors from current list according to given BSSID. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] aucBSSID Given BSSID. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID scanRemoveBssDescByBssid(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_LINK_T prFreeBSSDescList; + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; + P_BSS_DESC_T prBSSDescNext; + + ASSERT(prAdapter); + ASSERT(aucBSSID); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; + + /* Check if such BSS Descriptor exists in a valid list */ + LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { + + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); + + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); + + /* BSSID is not unique, so need to traverse whols link-list */ + } + } +} /* end of scanRemoveBssDescByBssid() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Delete BSS Descriptors from current list according to given band configuration +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] eBand Given band +* @param[in] ucBssIndex 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 UINT_8 ucBssIndex) +{ + 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(ucBssIndex <= MAX_BSS_INDEX); + + 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 (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType) { + case NETWORK_TYPE_AIS: + if ((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) + || (prBssDesc->eBSSType == BSS_TYPE_IBSS)) { + fgToRemove = TRUE; + } + break; + + case NETWORK_TYPE_P2P: + if (prBssDesc->eBSSType == BSS_TYPE_P2P_DEVICE) + fgToRemove = TRUE; + break; + + case NETWORK_TYPE_BOW: + if (prBssDesc->eBSSType == BSS_TYPE_BOW_DEVICE) + fgToRemove = TRUE; + break; + + default: + ASSERT(0); + break; + } + } + + if (fgToRemove == TRUE) { + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); + + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); + } + } +} /* end of scanRemoveBssDescByBand() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Clear the CONNECTION FLAG of a specified BSS Descriptor. +* +* @param[in] aucBSSID Given BSSID. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID scanRemoveConnFlagOfBssDescByBssid(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; + + ASSERT(prAdapter); + ASSERT(aucBSSID); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { + prBssDesc->fgIsConnected = FALSE; + prBssDesc->fgIsConnecting = FALSE; + + /* BSSID is not unique, so need to traverse whols link-list */ + } + } + + return; + +} /* end of scanRemoveConnectionFlagOfBssDescByBssid() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Allocate new BSS_DESC_T +* +* @param[in] prAdapter Pointer to the Adapter structure. +* +* @return Pointer to BSS Descriptor, if has free space. NULL, if has no space. +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T scanAllocateBssDesc(IN P_ADAPTER_T prAdapter) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prFreeBSSDescList; + P_BSS_DESC_T prBssDesc; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; + + LINK_REMOVE_HEAD(prFreeBSSDescList, prBssDesc, P_BSS_DESC_T); + + if (prBssDesc) { + P_LINK_T prBSSDescList; + + kalMemZero(prBssDesc, sizeof(BSS_DESC_T)); + +#if CFG_ENABLE_WIFI_DIRECT + LINK_INITIALIZE(&(prBssDesc->rP2pDeviceList)); + prBssDesc->fgIsP2PPresent = FALSE; +#endif /* CFG_ENABLE_WIFI_DIRECT */ + + prBSSDescList = &prScanInfo->rBSSDescList; + + /* NOTE(Kevin): In current design, this new empty BSS_DESC_T will be + * inserted to BSSDescList immediately. + */ + LINK_INSERT_TAIL(prBSSDescList, &prBssDesc->rLinkEntry); + } + + return prBssDesc; + +} /* end of scanAllocateBssDesc() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This API parses Beacon/ProbeResp frame and insert extracted BSS_DESC_T +* with IEs into prAdapter->rWifiVar.rScanInfo.aucScanBuffer +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to the receiving frame buffer. +* +* @return Pointer to BSS Descriptor +* NULL if the Beacon/ProbeResp frame is invalid +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T scanAddToBssDesc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_BSS_DESC_T prBssDesc = NULL; + UINT_16 u2CapInfo; + ENUM_BSS_TYPE_T eBSSType = BSS_TYPE_INFRASTRUCTURE; + + PUINT_8 pucIE; + UINT_16 u2IELength; + UINT_16 u2Offset = 0; + + P_WLAN_BEACON_FRAME_T prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T) NULL; + P_IE_SSID_T prIeSsid = (P_IE_SSID_T) NULL; + P_IE_SUPPORTED_RATE_T prIeSupportedRate = (P_IE_SUPPORTED_RATE_T) NULL; + P_IE_EXT_SUPPORTED_RATE_T prIeExtSupportedRate = (P_IE_EXT_SUPPORTED_RATE_T) NULL; + UINT_8 ucHwChannelNum = 0; + UINT_8 ucIeDsChannelNum = 0; + UINT_8 ucIeHtChannelNum = 0; + BOOLEAN fgIsValidSsid = FALSE, fgEscape = FALSE, fgIsCopy = FALSE; + PARAM_SSID_T rSsid; + UINT_64 u8Timestamp; + BOOLEAN fgIsNewBssDesc = FALSE; + + UINT_32 i; + UINT_8 ucSSIDChar; + /* PUINT_8 pucDumpIE; */ + + 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; + DBGLOG(SCN, WARN, "IE len(%u) > Max IE buffer size(%u), truncate IE!\n", + 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/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 | SCN_RM_POLICY_TIMEOUT | + SCN_RM_POLICY_EXCLUDE_SPECIFIC_SSID)); + + /* 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 | + SCN_RM_POLICY_EXCLUDE_SPECIFIC_SSID)); + + /* 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); + + ASSERT(prSwRfb->prRxStatusGroup3); + + if (prBssDesc->eBSSType != eBSSType) { + prBssDesc->eBSSType = eBSSType; + } else if (HAL_RX_STATUS_GET_CHNL_NUM(prSwRfb->prRxStatus) != + prBssDesc->ucChannelNum + && prBssDesc->ucRCPI > nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0, prSwRfb)) { + + /* for signal strength is too much weaker and previous beacon is not stale */ + ASSERT(prSwRfb->prRxStatusGroup3); + if ((prBssDesc->ucRCPI - + nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0, prSwRfb)) >= + 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; + } + } + + /* 2018/04/17 frog: always update IE is not a good choice. */ + /* Because of not considering hidden BSS. */ + /* Hidden BSS Beacon v.s. hidden BSS probe response. */ + if ((prBssDesc->u2RawLength == 0) || (fgIsValidSsid)) { + prBssDesc->u2RawLength = prSwRfb->u2PacketLen; + if (prBssDesc->u2RawLength > CFG_RAW_BUFFER_SIZE) + prBssDesc->u2RawLength = CFG_RAW_BUFFER_SIZE; + kalMemCopy(prBssDesc->aucRawBuf, prWlanBeaconFrame, + prBssDesc->u2RawLength); + fgIsCopy = TRUE; + } + + /* 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 (fgIsCopy) { + 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->fgIsVHTPresent = FALSE; + prBssDesc->eSco = CHNL_EXT_SCN; + prBssDesc->fgIEWAPI = FALSE; + prBssDesc->fgIERSN = FALSE; + prBssDesc->fgIEWPA = FALSE; + prBssDesc->eChannelWidth = CW_20_40MHZ; /*Reset VHT OP IE relative settings */ + prBssDesc->ucCenterFreqS1 = 0; + prBssDesc->ucCenterFreqS2 = 0; + + /* 4 <3.1> Full IE parsing on SW_RFB_T */ + pucIE = prWlanBeaconFrame->aucInfoElem; + /* pucDumpIE = pucIE; */ + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + + switch (IE_ID(pucIE)) { + case ELEM_ID_SSID: + if ((!prIeSsid) && /* NOTE(Kevin): for Atheros IOT #1 */ + (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) { + BOOLEAN fgIsHiddenSSID = FALSE; + + ucSSIDChar = '\0'; + + prIeSsid = (P_IE_SSID_T) pucIE; + + /* D-Link DWL-900AP+ */ + if (IE_LEN(pucIE) == 0) + fgIsHiddenSSID = TRUE; + /* Cisco AP1230A - (IE_LEN(pucIE) == 1) && (SSID_IE(pucIE)->aucSSID[0] == '\0') */ + /* Linksys WRK54G/WL520g - (IE_LEN(pucIE) == n) && + * (SSID_IE(pucIE)->aucSSID[0~(n-1)] == '\0') = + */ + else { + for (i = 0; i < IE_LEN(pucIE); i++) + ucSSIDChar |= SSID_IE(pucIE)->aucSSID[i]; + + if (!ucSSIDChar) + fgIsHiddenSSID = TRUE; + } + + /* Update SSID to BSS Descriptor only if SSID is not hidden. */ + if (!fgIsHiddenSSID) { + COPY_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, + SSID_IE(pucIE)->aucSSID, SSID_IE(pucIE)->ucLength); + } + + } + 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_SW)) + 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; + + 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; + + 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; + case ELEM_ID_VHT_CAP: + prBssDesc->fgIsVHTPresent = TRUE; +#if CFG_SUPPORT_BFEE + prBssDesc->ucVhtCapNumSoundingDimensions = + ((((P_IE_VHT_CAP_T) pucIE)->u4VhtCapInfo) & VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS) + >> VHT_CAP_INFO_NUMBER_OF_SOUNDING_DIMENSIONS_OFFSET; +#endif + break; + + case ELEM_ID_VHT_OP: + if (IE_LEN(pucIE) != (sizeof(IE_VHT_OP_T) - 2)) + break; + + prBssDesc->eChannelWidth = (ENUM_CHANNEL_WIDTH_T) (((P_IE_VHT_OP_T) pucIE)->ucVhtOperation[0]); + prBssDesc->ucCenterFreqS1 = (ENUM_CHANNEL_WIDTH_T) (((P_IE_VHT_OP_T) pucIE)->ucVhtOperation[1]); + prBssDesc->ucCenterFreqS2 = (ENUM_CHANNEL_WIDTH_T) (((P_IE_VHT_OP_T) pucIE)->ucVhtOperation[2]); + + /*add IEEE BW160 patch*/ + rlmModifyVhtBwPara(&prBssDesc->ucCenterFreqS1, + &prBssDesc->ucCenterFreqS2, + (PUINT_8)&prBssDesc->eChannelWidth); + + + + 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 (rsnParseCheckForWFAInfoElem(prAdapter, pucIE, &ucOuiType, &u2SubTypeVersion)) { + if ((ucOuiType == VENDOR_OUI_TYPE_WPA) + && (u2SubTypeVersion == VERSION_WPA) + && (rsnParseWpaIE(prAdapter, WPA_IE(pucIE), &prBssDesc->rWPAInfo))) { + prBssDesc->fgIEWPA = TRUE; + } + } +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { + if ((p2pFuncParseCheckForP2PInfoElem(prAdapter, pucIE, &ucOuiType)) + && (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 */ + { + P_HW_MAC_RX_DESC_T prRxStatus; + UINT_8 ucRxRCPI; + UINT_8 ucRxRCPI1; + + prRxStatus = prSwRfb->prRxStatus; + ASSERT(prRxStatus); + + /* 4 <4.1> Get TSF comparison result */ + prBssDesc->fgIsLargerTSF = HAL_RX_STATUS_GET_TCL(prRxStatus); + + /* 4 <4.2> Get Band information */ + prBssDesc->eBand = HAL_RX_STATUS_GET_RF_BAND(prRxStatus); + + /* 4 <4.2> Get channel and RCPI information */ + ucHwChannelNum = HAL_RX_STATUS_GET_CHNL_NUM(prRxStatus); + + ASSERT(prSwRfb->prRxStatusGroup3); + ucRxRCPI = nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0, prSwRfb); + ucRxRCPI1 = nicRxGetRcpiValueFromRxv(RCPI_MODE_WF1, prSwRfb); + + if (prBssDesc->eBand == BAND_2G4) { + + /* Update RCPI if in right channel */ + + if (ucIeDsChannelNum >= 1 && ucIeDsChannelNum <= 14) { + + /* Receive Beacon/ProbeResp frame from adjacent channel. */ + if ((ucIeDsChannelNum == ucHwChannelNum) || + (ucRxRCPI > prBssDesc->ucRCPI)) { + prBssDesc->ucRCPI = ucRxRCPI; + prBssDesc->ucRCPI1 = ucRxRCPI1; + } + /* 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) || + (ucRxRCPI > prBssDesc->ucRCPI)) { + prBssDesc->ucRCPI = ucRxRCPI; + prBssDesc->ucRCPI1 = ucRxRCPI1; + } + /* trust channel information brought by IE */ + prBssDesc->ucChannelNum = ucIeHtChannelNum; + } else { + prBssDesc->ucRCPI = ucRxRCPI; + prBssDesc->ucRCPI1 = ucRxRCPI1; + prBssDesc->ucChannelNum = ucHwChannelNum; + } + } + /* 5G Band */ + else { + if (ucIeHtChannelNum >= 1 && ucIeHtChannelNum < 200) { + /* Receive Beacon/ProbeResp frame from adjacent channel. */ + if ((ucIeHtChannelNum == ucHwChannelNum) || + (ucRxRCPI > prBssDesc->ucRCPI)) { + prBssDesc->ucRCPI = ucRxRCPI; + prBssDesc->ucRCPI1 = ucRxRCPI1; + } + /* trust channel information brought by IE */ + prBssDesc->ucChannelNum = ucIeHtChannelNum; + } else { + /* Always update RCPI */ + prBssDesc->ucRCPI = ucRxRCPI; + prBssDesc->ucRCPI1 = ucRxRCPI1; + prBssDesc->ucChannelNum = ucHwChannelNum; + } + } + } + + /* 4 <5> Check IE information corret or not */ + if (!rlmDomainIsValidRfSetting(prAdapter, prBssDesc->eBand, prBssDesc->ucChannelNum, prBssDesc->eSco, + prBssDesc->eChannelWidth, prBssDesc->ucCenterFreqS1, + prBssDesc->ucCenterFreqS2)) { + /* Dump IE Inforamtion */ + /* DBGLOG(RLM, WARN, "ScanAddToBssDesc IE Information\n"); */ + /* DBGLOG(RLM, WARN, "IE Length = %d\n", u2IELength); */ + /* DBGLOG_MEM8(RLM, WARN, pucDumpIE, u2IELength); */ + + /* Error Handling for Non-predicted IE - Fixed to set 20MHz */ + prBssDesc->eChannelWidth = CW_20_40MHZ; + prBssDesc->ucCenterFreqS1 = 0; + prBssDesc->ucCenterFreqS2 = 0; + prBssDesc->eSco = CHNL_EXT_SCN; + } + + /* 4 <6> PHY type setting */ + prBssDesc->ucPhyTypeSet = 0; + + if (prBssDesc->eBand == BAND_2G4) { + /* 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->fgIsVHTPresent) + prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_VHT; + + 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 <7> 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 < ARRAY_SIZE(aucRatesEx); i++) + aucRatesEx[i] = 0; + + switch (prBssDesc->eBSSType) { + case BSS_TYPE_IBSS: + eOpMode = NET_TYPE_IBSS; + break; + + case BSS_TYPE_INFRASTRUCTURE: + case BSS_TYPE_P2P_DEVICE: + case BSS_TYPE_BOW_DEVICE: + default: + eOpMode = NET_TYPE_INFRA; + break; + } + + DBGLOG(SCN, TRACE, "ind %s %d %d\n", prBssDesc->aucSSID, prBssDesc->ucChannelNum, prBssDesc->ucRCPI); + + kalIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) prSwRfb->pvHeader, + prSwRfb->u2PacketLen, prBssDesc->ucChannelNum, RCPI_TO_dBm(prBssDesc->ucRCPI)); + + nicAddScanResult(prAdapter, + rMacAddr, + &rSsid, + prWlanBeaconFrame->u2CapInfo & CAP_INFO_PRIVACY ? 1 : 0, + RCPI_TO_dBm(prBssDesc->ucRCPI), + eNetworkType, + &rConfiguration, + eOpMode, + aucRatesEx, + prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen, + (PUINT_8) ((ULONG) (prSwRfb->pvHeader) + WLAN_MAC_MGMT_HEADER_LEN)); + + return WLAN_STATUS_SUCCESS; + +} /* end of scanAddScanResult() */ + +BOOLEAN scanCheckBssIsLegal(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc) +{ + BOOLEAN fgAddToScanResult = FALSE; + ENUM_BAND_T eBand; + UINT_8 ucChannel; + + ASSERT(prAdapter); + /* check the channel is in the legal doamin */ + if (rlmDomainIsLegalChannel(prAdapter, prBssDesc->eBand, prBssDesc->ucChannelNum) == TRUE) { + /* check ucChannelNum/eBand for adjacement channel filtering */ + if (cnmAisInfraChannelFixed(prAdapter, &eBand, &ucChannel) == TRUE && + (eBand != prBssDesc->eBand || ucChannel != prBssDesc->ucChannelNum)) { + fgAddToScanResult = FALSE; + } else { + fgAddToScanResult = TRUE; + } + } + + return fgAddToScanResult; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @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_SCAN_INFO_T prScanInfo; + 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); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + /* 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->prAisBssInfo; + prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T) prSwRfb->pvHeader; + + /* 4 <1> Parse and add into BSS_DESC_T */ + prBssDesc = scanAddToBssDesc(prAdapter, prSwRfb); + + if (prBssDesc) { +#if CFG_SUPPORT_BEACON_CHANGE_DETECTION + /* 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; + + /* <1.1.2> check if supported rate differs */ + if (prAisBssInfo->u2OperationalRateSet != prBssDesc->u2OperationalRateSet) + fgNeedDisconnect = TRUE; + + /* <1.1.3> beacon content change detected, disconnect immediately */ + if (fgNeedDisconnect == TRUE) + aisBssBeaconTimeout(prAdapter); + } +#endif + /* 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, prAisBssInfo->ucBssIndex); + } + } +#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)) { + + ASSERT(prSwRfb->prRxStatusGroup3); + + ibssProcessMatchedBeacon(prAdapter, prAisBssInfo, prBssDesc, + nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0, prSwRfb)); + } +#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]))); + + mqmProcessBcn(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) { + BOOLEAN fgAddToScanResult; + + fgAddToScanResult = scanCheckBssIsLegal(prAdapter, prBssDesc); + + if (fgAddToScanResult == TRUE) + rStatus = scanAddScanResult(prAdapter, prBssDesc, prSwRfb); + } + } +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) + scanP2pProcessBeaconAndProbeResp(prAdapter, prSwRfb, &rStatus, prBssDesc, prWlanBeaconFrame); +#endif + } + + return rStatus; + +} /* end of scanProcessBeaconAndProbeResp() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Search the Candidate of BSS Descriptor for JOIN(Infrastructure) or +* MERGE(AdHoc) according to current Connection Policy. +* +* \return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T scanSearchBssDescByPolicy(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex) +{ + 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; +#if !CFG_SUPPORT_CFG80211_AUTH + BOOLEAN fgIsFindBestEncryptionLevel = (BOOLEAN) FALSE; +#endif + /* 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 = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + prAisSpecBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + + GET_CURRENT_SYSTIME(&rCurrentTime); + + /* check for fixed channel operation */ + if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) { +#if CFG_SUPPORT_CHNL_CONFLICT_REVISE + fgIsFixedChannel = cnmAisDetectP2PChannel(prAdapter, &eBand, &ucChannel); +#else + fgIsFixedChannel = cnmAisInfraChannelFixed(prAdapter, &eBand, &ucChannel); +#endif + } else + fgIsFixedChannel = FALSE; + +#if DBG + if (prConnSettings->ucSSIDLen < ELEM_MAX_LEN_SSID) + prConnSettings->aucSSID[prConnSettings->ucSSIDLen] = '\0'; +#endif + +#if 0 + DBGLOG(SCN, INFO, "SEARCH: Num Of BSS_DESC_T = %d, Look for SSID: %s\n", + prBSSDescList->u4NumElem, prConnSettings->aucSSID); +#endif + + /* 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 */ + +#if 0 + DBGLOG(SCN, INFO, "SEARCH: [" MACSTR "], SSID:%s\n", MAC2STR(prBssDesc->aucBSSID), prBssDesc->aucSSID); +#endif + + /* 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) { + DBGLOG(SCN, LOUD, "SEARCH: Ignore Unknown Bss Basic Rate\n"); + continue; + } + /* 4 <2.3> Check if fixed operation cases should be aware */ + if (fgIsFixedChannel == TRUE && (prBssDesc->eBand != eBand || prBssDesc->ucChannelNum != ucChannel)) { + DBGLOG(SCN, LOUD, + "SEARCH: Ignore BssBand[%d] != FixBand[%d] or BssCH[%d] != FixCH[%d]\n", + 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) { + DBGLOG(SCN, LOUD, "SEARCH: Ignore illegal CH Band[%d] CH[%d]\n", + prBssDesc->eBand, prBssDesc->ucChannelNum); + 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_STALE_SEC))) { + DBGLOG(SCN, LOUD, + "SEARCH: Ignore stale Bss, CurrTime[%u] BssUpdateTime[%u]\n", + rCurrentTime, prBssDesc->rUpdateTime); + continue; + } + /* 4 <3> Check if reach the excessive join retry limit */ + /* NOTE(Kevin): STA_RECORD_T is recorded by TA. */ + prStaRec = cnmGetStaRecByAddress(prAdapter, ucBssIndex, prBssDesc->aucSrcAddr); + + if (prStaRec) { + /* NOTE(Kevin): + * The Status Code is the result of a Previous Connection Request, + * we use this as SCORE for choosing a proper + * candidate (Also used for compare see <6>) + * The Reason Code is an indication of the reason why AP reject us, + * we use this Code for "Reject" + * a SCAN result to become our candidate(Like a blacklist). + */ +#if 0 /* TODO(Kevin): */ + if (prStaRec->u2ReasonCode != REASON_CODE_RESERVED) { + DBGLOG(SCN, INFO, + "SEARCH: Ignore BSS with previous Reason Code = %d\n", prStaRec->u2ReasonCode); + continue; + } else +#endif + if (prStaRec->u2StatusCode != STATUS_CODE_SUCCESSFUL) { + /* NOTE(Kevin): greedy association - after timeout, we'll still + * try to associate to the AP whose STATUS of conection attempt + * was not success. + * We may also use (ucJoinFailureCount x JOIN_RETRY_INTERVAL_SEC) for + * time bound. + */ + if ((prStaRec->ucJoinFailureCount < JOIN_MAX_RETRY_FAILURE_COUNT) || + (CHECK_FOR_TIMEOUT(rCurrentTime, + prStaRec->rLastJoinTime, + SEC_TO_SYSTIME(JOIN_RETRY_INTERVAL_SEC)))) { + + /* NOTE(Kevin): Every JOIN_RETRY_INTERVAL_SEC interval, we can retry + * JOIN_MAX_RETRY_FAILURE_COUNT times. + */ + if (prStaRec->ucJoinFailureCount >= JOIN_MAX_RETRY_FAILURE_COUNT) + prStaRec->ucJoinFailureCount = 0; + DBGLOG(SCN, INFO, + "SEARCH:Try to join BSS again,Status Code=%u(Curr=%u/Last Join=%u)\n", + prStaRec->u2StatusCode, rCurrentTime, prStaRec->rLastJoinTime); + } else { + DBGLOG(SCN, INFO, + "SEARCH: Ignore BSS which reach maximum Join Retry Count = %d\n", + JOIN_MAX_RETRY_FAILURE_COUNT); + continue; + } + + } + } + + /* 4 <4> Check for various NETWORK conditions */ + if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) { + + /* 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, TRACE, + "SEARCH: Ignore due to BSSID was not matched!\n"); + continue; + } + } +#if CFG_SUPPORT_ADHOC + /* 4 <4.3> Check for AdHoc Mode */ + if (prBssDesc->eBSSType == BSS_TYPE_IBSS) { + OS_SYSTIME rCurrentTime; + + /* 4 <4.3.1> Check if this SCAN record has been updated recently for IBSS. */ + /* NOTE(Kevin): Because some STA may change its BSSID frequently after it + * create the IBSS - e.g. IPN2220, so we need to make sure we get the new one. + * For BSS, if the old record was matched, however it won't be able to pass + * the Join Process later. + */ + GET_CURRENT_SYSTIME(&rCurrentTime); + if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, + SEC_TO_SYSTIME(SCN_ADHOC_BSS_DESC_TIMEOUT_SEC))) { + DBGLOG(SCN, LOUD, + "SEARCH: Skip old record of BSS Descriptor - BSSID:[" + 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; + DBGLOG(SCN, LOUD, "SEARCH: Found BSS by SSID, [" MACSTR "], SSID:%s\n", + MAC2STR(prBssDesc->aucBSSID), prBssDesc->aucSSID); + } + 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)) { + /* Make sure to match with SSID if supplied. + * Some dual band APs share a single BSSID among different BSSes. + */ + if ((prBssDesc->ucSSIDLen > 0 && prConnSettings->ucSSIDLen > 0 && + EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, + prConnSettings->aucSSID, prConnSettings->ucSSIDLen)) || + prConnSettings->ucSSIDLen == 0) { +#if CFG_SUPPORT_CFG80211_AUTH + if (prBssDesc->ucChannelNum == + prConnSettings->ucChannelNum) { + prPrimaryBssDesc = prBssDesc; + fgIsFindFirst = TRUE; + } +#else + prPrimaryBssDesc = prBssDesc; +#endif + } + } + 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_CFG80211_AUTH +#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 */ + DBGLOG(RSN, INFO, "Ignore BSS can't pass WAPI policy selection\n"); + continue; + } + } else +#endif + 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; + } + } else { + /* Can't pass the Encryption Status Check, get next one */ + DBGLOG(RSN, INFO, "Ignore BSS can't pass Encryption Status Check\n"); + 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 { + /* 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, joinFailCnt=%d, Primary [" MACSTR + "]: RCPI = %d, joinFailCnt=%d\n", MAC2STR(prCandidateBssDesc->aucBSSID), + prCandidateBssDesc->ucRCPI, prCandidateBssDesc->ucJoinFailureCount, + MAC2STR(prPrimaryBssDesc->aucBSSID), prPrimaryBssDesc->ucRCPI, + prPrimaryBssDesc->ucJoinFailureCount); + + ASSERT(!(prCandidateBssDesc->fgIsConnected && prPrimaryBssDesc->fgIsConnected)); + if (prPrimaryBssDesc->ucJoinFailureCount > SCN_BSS_JOIN_FAIL_THRESOLD) { + /* give a chance to do join if join fail before + * SCN_BSS_DECRASE_JOIN_FAIL_CNT_SEC seconds + */ + if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rJoinFailTime, + SEC_TO_SYSTIME(SCN_BSS_JOIN_FAIL_CNT_RESET_SEC))) { + prBssDesc->ucJoinFailureCount -= SCN_BSS_JOIN_FAIL_RESET_STEP; + DBGLOG(AIS, INFO, + "decrease join fail count for Bss " MACSTR + " to %u, timeout second %d\n", MAC2STR(prBssDesc->aucBSSID), + prBssDesc->ucJoinFailureCount, SCN_BSS_JOIN_FAIL_CNT_RESET_SEC); + } + } + /* NOTE: To prevent SWING, we do roaming only if target AP + * has at least 5dBm larger than us. + */ + if (prCandidateBssDesc->fgIsConnected) { + if ((prCandidateBssDesc->ucRCPI + ROAMING_NO_SWING_RCPI_STEP <= + prPrimaryBssDesc->ucRCPI) + && prPrimaryBssDesc->ucJoinFailureCount <= SCN_BSS_JOIN_FAIL_THRESOLD) { + + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } else if (prPrimaryBssDesc->fgIsConnected) { + if ((prCandidateBssDesc->ucRCPI < + prPrimaryBssDesc->ucRCPI + ROAMING_NO_SWING_RCPI_STEP) + || (prCandidateBssDesc->ucJoinFailureCount > SCN_BSS_JOIN_FAIL_THRESOLD)) { + + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } else if (prPrimaryBssDesc->ucJoinFailureCount > SCN_BSS_JOIN_FAIL_THRESOLD) + continue; + else if (prCandidateBssDesc->ucJoinFailureCount > SCN_BSS_JOIN_FAIL_THRESOLD || + prCandidateBssDesc->ucRCPI < prPrimaryBssDesc->ucRCPI) { + + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } +#if 0 + /* If reach here, that means they have the same Encryption Score, and + * both RSSI value are close too. + */ + /* 4 <6F> Seek the minimum Channel Load for less interference. */ + if (fgIsFindMinChannelLoad) { + /* ToDo:: Nothing */ + /* TODO(Kevin): Check which one has minimum channel load in its channel */ + } +#endif + } + } + + return prCandidateBssDesc; + +} /* end of scanSearchBssDescByPolicy() */ + +VOID scanReportBss2Cfg80211(IN P_ADAPTER_T prAdapter, IN ENUM_BSS_TYPE_T eBSSType, IN P_BSS_DESC_T SpecificprBssDesc) +{ + P_SCAN_INFO_T prScanInfo = NULL; + P_LINK_T prBSSDescList = NULL; + P_BSS_DESC_T prBssDesc = NULL; + RF_CHANNEL_INFO_T rChannelInfo; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prBSSDescList = &prScanInfo->rBSSDescList; + + DBGLOG(SCN, TRACE, "scanReportBss2Cfg80211\n"); + + if (SpecificprBssDesc) { + { + /* check BSSID is legal channel */ + if (!scanCheckBssIsLegal(prAdapter, SpecificprBssDesc)) { + DBGLOG(SCN, TRACE, "Remove specific SSID[%s %d]\n", + SpecificprBssDesc->aucSSID, SpecificprBssDesc->ucChannelNum); + return; + } + + DBGLOG(SCN, TRACE, "Report Specific SSID[%s]\n", SpecificprBssDesc->aucSSID); + if (eBSSType == BSS_TYPE_INFRASTRUCTURE) { + + kalIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) SpecificprBssDesc->aucRawBuf, + SpecificprBssDesc->u2RawLength, + SpecificprBssDesc->ucChannelNum, + RCPI_TO_dBm(SpecificprBssDesc->ucRCPI)); + } else { + + rChannelInfo.ucChannelNum = SpecificprBssDesc->ucChannelNum; + rChannelInfo.eBand = SpecificprBssDesc->eBand; + kalP2PIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) SpecificprBssDesc->aucRawBuf, + SpecificprBssDesc->u2RawLength, + &rChannelInfo, RCPI_TO_dBm(SpecificprBssDesc->ucRCPI)); + + } + +#if CFG_ENABLE_WIFI_DIRECT + SpecificprBssDesc->fgIsP2PReport = FALSE; +#endif + } + } else { + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + /* Clear old ACS data (APNum, Dirtiness, ...) and initialize the ch number */ + kalMemZero(&(prAdapter->rWifiVar.rChnLoadInfo), + sizeof(prAdapter->rWifiVar.rChnLoadInfo)); + wlanInitChnLoadInfoChannelList(prAdapter); +#endif + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + /* Record channel loading with channel's AP number */ + UINT_8 ucIdx = wlanGetChannelIndex(prBssDesc->ucChannelNum); + + if (ucIdx < MAX_CHN_NUM) + prAdapter->rWifiVar.rChnLoadInfo.rEachChnLoad[ucIdx].u2APNum++; +#endif + + /* check BSSID is legal channel */ + if (!scanCheckBssIsLegal(prAdapter, prBssDesc)) { + DBGLOG(SCN, TRACE, "Remove SSID[%s %d]\n", prBssDesc->aucSSID, prBssDesc->ucChannelNum); + continue; + } + + if ((prBssDesc->eBSSType == eBSSType) +#if CFG_ENABLE_WIFI_DIRECT + || (eBSSType == BSS_TYPE_P2P_DEVICE && + prBssDesc->fgIsP2PReport == TRUE) +#endif + ) { + DBGLOG(SCN, TRACE, "Report ALL SSID[%s %d]\n", + prBssDesc->aucSSID, prBssDesc->ucChannelNum); + + if (eBSSType == BSS_TYPE_INFRASTRUCTURE) { + if (prBssDesc->u2RawLength != 0) { + kalIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) prBssDesc->aucRawBuf, + prBssDesc->u2RawLength, + prBssDesc->ucChannelNum, + RCPI_TO_dBm(prBssDesc->ucRCPI)); + kalMemZero(prBssDesc->aucRawBuf, CFG_RAW_BUFFER_SIZE); + prBssDesc->u2RawLength = 0; + +#if CFG_ENABLE_WIFI_DIRECT + prBssDesc->fgIsP2PReport = FALSE; +#endif + } + } else { +#if CFG_ENABLE_WIFI_DIRECT + if ((prBssDesc->fgIsP2PReport == TRUE) + && prBssDesc->u2RawLength != 0) { +#endif + rChannelInfo.ucChannelNum = prBssDesc->ucChannelNum; + rChannelInfo.eBand = prBssDesc->eBand; + + kalP2PIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) prBssDesc->aucRawBuf, + prBssDesc->u2RawLength, + &rChannelInfo, RCPI_TO_dBm(prBssDesc->ucRCPI)); + + /* do not clear it then we can pass the bss in Specific report */ + /* kalMemZero(prBssDesc->aucRawBuf,CFG_RAW_BUFFER_SIZE); */ + + /* + * the BSS entry will not be cleared after scan done. + * So if we dont receive the BSS in next scan, we cannot + * pass it. We use u2RawLength for the purpose. + */ + /* prBssDesc->u2RawLength=0; */ +#if CFG_ENABLE_WIFI_DIRECT + prBssDesc->fgIsP2PReport = FALSE; + } +#endif + } + } + + } +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + wlanCalculateAllChannelDirtiness(prAdapter); + wlanSortChannel(prAdapter); + + prAdapter->rWifiVar.rChnLoadInfo.fgDataReadyBit = TRUE; +#endif + + } + +} + +#if CFG_SUPPORT_PASSPOINT +/*----------------------------------------------------------------------------*/ +/*! +* @brief Find the corresponding BSS Descriptor according to given BSSID +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] aucBSSID Given BSSID. +* @param[in] fgCheckSsid Need to check SSID or not. (for multiple SSID with single BSSID cases) +* @param[in] prSsid Specified SSID +* +* @return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T scanSearchBssDescByBssidAndLatestUpdateTime(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc; + P_BSS_DESC_T prDstBssDesc = (P_BSS_DESC_T) NULL; + OS_SYSTIME rLatestUpdateTime = 0; + + ASSERT(prAdapter); + ASSERT(aucBSSID); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prBSSDescList = &prScanInfo->rBSSDescList; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { + if (!rLatestUpdateTime || CHECK_FOR_EXPIRATION(prBssDesc->rUpdateTime, rLatestUpdateTime)) { + prDstBssDesc = prBssDesc; + COPY_SYSTIME(rLatestUpdateTime, prBssDesc->rUpdateTime); + } + } + } + + return prDstBssDesc; + +} /* end of scanSearchBssDescByBssid() */ + +#endif /* CFG_SUPPORT_PASSPOINT */ + +#if CFG_SUPPORT_AGPS_ASSIST +VOID scanReportScanResultToAgps(P_ADAPTER_T prAdapter) +{ + P_LINK_T prBSSDescList = &prAdapter->rWifiVar.rScanInfo.rBSSDescList; + P_BSS_DESC_T prBssDesc = NULL; + P_AGPS_AP_LIST_T prAgpsApList = NULL; + P_AGPS_AP_INFO_T prAgpsInfo = NULL; + P_SCAN_INFO_T prScanInfo = &prAdapter->rWifiVar.rScanInfo; + UINT_8 ucIndex = 0; + + prAgpsApList = kalMemAlloc(sizeof(AGPS_AP_LIST_T), VIR_MEM_TYPE); + if (!prAgpsApList) { + DBGLOG(INIT, ERROR, "Allocate ap list memory ==> FAILED\n"); + return; + } + prAgpsInfo = &prAgpsApList->arApInfo[0]; + + + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + if (prBssDesc->rUpdateTime < prScanInfo->rLastScanCompletedTime) + continue; + COPY_MAC_ADDR(prAgpsInfo->aucBSSID, prBssDesc->aucBSSID); + prAgpsInfo->ePhyType = AGPS_PHY_G; + prAgpsInfo->u2Channel = prBssDesc->ucChannelNum; + prAgpsInfo->i2ApRssi = RCPI_TO_dBm(prBssDesc->ucRCPI); + prAgpsInfo++; + ucIndex++; + if (ucIndex == SCN_AGPS_AP_LIST_MAX_NUM) + break; + } + prAgpsApList->ucNum = ucIndex; + GET_CURRENT_SYSTIME(&prScanInfo->rLastScanCompletedTime); + /* DBGLOG(SCN, INFO, ("num of scan list:%d\n", ucIndex)); */ + kalIndicateAgpsNotify(prAdapter, AGPS_EVENT_WLAN_AP_LIST, (PUINT_8) prAgpsApList, sizeof(AGPS_AP_LIST_T)); + kalMemFree(prAgpsApList, VIR_MEM_TYPE, sizeof(AGPS_AP_LIST_T)); +} +#endif /* CFG_SUPPORT_AGPS_ASSIST */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/scan_fsm.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/scan_fsm.c new file mode 100644 index 0000000000000..886963d7d3747 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/scan_fsm.c @@ -0,0 +1,1067 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/scan_fsm.c#2 +*/ + +/*! \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 . +*/ + + +/******************************************************************************* +* C O M P I L E 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 +******************************************************************************** +*/ +UINT_8 g_aucScanChannelNum[SCN_SCAN_DONE_PRINT_BUFFER_LENGTH]; +UINT_8 g_aucScanChannelIdleTime[SCN_SCAN_DONE_PRINT_BUFFER_LENGTH]; +UINT_8 g_aucScanChannelMDRDY[SCN_SCAN_DONE_PRINT_BUFFER_LENGTH]; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static PUINT_8 apucDebugScanState[SCAN_STATE_NUM] = { + (PUINT_8) DISP_STRING("IDLE"), + (PUINT_8) DISP_STRING("SCANNING"), +}; + +/******************************************************************************* +* M A 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 { + DBGLOG(SCN, STATE, "[SCAN]TRANSITION: [%s] -> [%s]\n", + apucDebugScanState[prScanInfo->eCurrentState], apucDebugScanState[eNextState]); + + /* 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); + + eNextState = SCAN_STATE_SCANNING; + fgIsTransition = TRUE; + } 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); + + eNextState = SCAN_STATE_SCANNING; + fgIsTransition = TRUE; + } else { + /* should not happen */ + ASSERT(0); + } + + /* switch to next state */ + cnmMemFree(prAdapter, prMsgHdr); + } + break; + + case SCAN_STATE_SCANNING: + if (prScanParam->fgIsScanV2 == FALSE) + scnSendScanReq(prAdapter); + else + scnSendScanReqV2(prAdapter); + break; + + default: + ASSERT(0); + break; + + } + } while (fgIsTransition); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Generate CMD_ID_SCAN_REQ command +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID 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.ucBssIndex = prScanParam->ucBssIndex; + 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; + } + } + + rCmdScanReq.u2ChannelDwellTime = prScanParam->u2ChannelDwellTime; + rCmdScanReq.u2TimeoutValue = prScanParam->u2TimeoutValue; + + 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.ucBssIndex = prScanParam->ucBssIndex; + rCmdScanReq.ucScanType = (UINT_8) prScanParam->eScanType; + rCmdScanReq.ucSSIDType = prScanParam->ucSSIDType; + rCmdScanReq.ucSSIDNum = prScanParam->ucSSIDNum; + + 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; + } + } + + rCmdScanReq.u2ChannelDwellTime = prScanParam->u2ChannelDwellTime; + rCmdScanReq.u2TimeoutValue = prScanParam->u2TimeoutValue; + + 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); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \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; + + DBGLOG(AIS, STATE, "Abort Scan [%d - [%d %d] - %d]\n", + prScanInfo->eCurrentState, + prScanCancel->ucSeqNum, prScanParam->ucSeqNum, + prScanParam->fgIsObssScan); + + if (prScanInfo->eCurrentState != SCAN_STATE_IDLE) { + if (prScanCancel->ucSeqNum == prScanParam->ucSeqNum && + prScanCancel->ucBssIndex == prScanParam->ucBssIndex) { + /* send cancel message to firmware domain */ + rCmdScanCancel.ucSeqNum = prScanParam->ucSeqNum; + rCmdScanCancel.ucIsExtChannel = (UINT_8) prScanCancel->fgIsChannelExt; + + 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, + prScanParam->ucBssIndex, SCAN_STATUS_CANCELLED); + + /* switch to next pending scan */ + scnFsmSteps(prAdapter, SCAN_STATE_IDLE); + } else if (prScanParam->fgIsObssScan == TRUE) { + rlmObssAbortScan(prAdapter); + } else { + scnFsmRemovePendingMsg(prAdapter, prScanCancel->ucSeqNum, prScanCancel->ucBssIndex); + } + } + + cnmMemFree(prAdapter, prMsgHdr); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Scan Message Parsing (Legacy) +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnFsmHandleScanMsg(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_SCAN_REQ prScanReqMsg) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + UINT_32 i; + + ASSERT(prAdapter); + ASSERT(prScanReqMsg); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + prScanParam->eScanType = prScanReqMsg->eScanType; + prScanParam->ucBssIndex = prScanReqMsg->ucBssIndex; + 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); + + prScanParam->u2ChannelDwellTime = prScanReqMsg->u2ChannelDwellTime; + prScanParam->u2TimeoutValue = prScanReqMsg->u2TimeoutValue; + prScanParam->ucSeqNum = prScanReqMsg->ucSeqNum; + + if (prScanReqMsg->rMsgHdr.eMsgId == MID_RLM_SCN_SCAN_REQ) + prScanParam->fgIsObssScan = TRUE; + else + prScanParam->fgIsObssScan = FALSE; + + prScanParam->fgIsScanV2 = FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Scan Message Parsing - V2 with multiple SSID support +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnFsmHandleScanMsgV2(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_SCAN_REQ_V2 prScanReqMsg) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + UINT_32 i; + + ASSERT(prAdapter); + ASSERT(prScanReqMsg); + ASSERT(prScanReqMsg->ucSSIDNum <= SCN_SSID_MAX_NUM); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + prScanParam->eScanType = prScanReqMsg->eScanType; + prScanParam->ucBssIndex = prScanReqMsg->ucBssIndex; + 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); + + prScanParam->u2ChannelDwellTime = prScanReqMsg->u2ChannelDwellTime; + prScanParam->u2TimeoutValue = prScanReqMsg->u2TimeoutValue; + prScanParam->ucSeqNum = prScanReqMsg->ucSeqNum; + + if (prScanReqMsg->rMsgHdr.eMsgId == MID_RLM_SCN_SCAN_REQ) + prScanParam->fgIsObssScan = TRUE; + else + prScanParam->fgIsObssScan = FALSE; + + prScanParam->fgIsScanV2 = TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Remove pending scan request +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnFsmRemovePendingMsg(IN P_ADAPTER_T prAdapter, IN UINT_8 ucSeqNum, IN UINT_8 ucBssIndex) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + P_MSG_HDR_T prPendingMsgHdr, prPendingMsgHdrNext, prRemoveMsgHdr = NULL; + P_LINK_ENTRY_T prRemoveLinkEntry = NULL; + BOOLEAN fgIsRemovingScan = FALSE; + + 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 && ucBssIndex == prScanReqMsg->ucBssIndex) { + prRemoveLinkEntry = &(prScanReqMsg->rMsgHdr.rLinkEntry); + prRemoveMsgHdr = prPendingMsgHdr; + fgIsRemovingScan = TRUE; + } + } 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 && ucBssIndex == prScanReqMsgV2->ucBssIndex) { + prRemoveLinkEntry = &(prScanReqMsgV2->rMsgHdr.rLinkEntry); + prRemoveMsgHdr = prPendingMsgHdr; + fgIsRemovingScan = TRUE; + } + } + + if (prRemoveLinkEntry) { + if (fgIsRemovingScan == TRUE) { + /* generate scan-done event for caller */ + scnFsmGenerateScanDoneMsg(prAdapter, ucSeqNum, ucBssIndex, SCAN_STATUS_CANCELLED); + } + + /* remove from pending list */ + LINK_REMOVE_KNOWN_ENTRY(&(prScanInfo->rPendingMsgList), prRemoveLinkEntry); + cnmMemFree(prAdapter, prRemoveMsgHdr); + + break; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnEventScanDone(IN P_ADAPTER_T prAdapter, IN P_EVENT_SCAN_DONE prScanDone, BOOLEAN fgIsNewVersion) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + UINT_32 u4ChCnt; + UINT_32 u4PrintfIdx = 0; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + kalMemZero(g_aucScanChannelNum, SCN_SCAN_DONE_PRINT_BUFFER_LENGTH); + kalMemZero(g_aucScanChannelIdleTime, SCN_SCAN_DONE_PRINT_BUFFER_LENGTH); + kalMemZero(g_aucScanChannelMDRDY, SCN_SCAN_DONE_PRINT_BUFFER_LENGTH); + + if (fgIsNewVersion) { + DBGLOG(SCN, INFO, + "scnEventScanDone Version%u!size of ScanDone%zu,ucCompleteChanCount[%u],ucCurrentState%u, u4ScanDurBcnCnt[%u]\n", + prScanDone->ucScanDoneVersion, sizeof(EVENT_SCAN_DONE), prScanDone->ucCompleteChanCount, + prScanDone->ucCurrentState, prScanDone->u4ScanDurBcnCnt); + + if (prScanDone->ucCurrentState != FW_SCAN_STATE_SCAN_DONE) { + DBGLOG(SCN, INFO, + "FW Scan timeout!generate ScanDone event at State%d complete chan count%d ucChannelListNum%d\n", + prScanDone->ucCurrentState, prScanDone->ucCompleteChanCount, + prScanParam->ucChannelListNum); + + } else { + DBGLOG(SCN, INFO, " scnEventScanDone at FW_SCAN_STATE_SCAN_DONE state\n"); + } + } else { + DBGLOG(SCN, INFO, "Old scnEventScanDone Version\n"); + } + + /* 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; + prScanInfo->ucSparseChannelArrayValidNum = prScanDone->ucSparseChannelArrayValidNum; + DBGLOG(SCN, INFO, "Detected_Channel_Num = %d\n", prScanInfo->ucSparseChannelArrayValidNum); + + for (u4ChCnt = 0; u4ChCnt < prScanInfo->ucSparseChannelArrayValidNum; u4ChCnt++) { + prScanInfo->aucChannelNum[u4ChCnt] = prScanDone->aucChannelNum[u4ChCnt]; + prScanInfo->au2ChannelIdleTime[u4ChCnt] = prScanDone->au2ChannelIdleTime[u4ChCnt]; + prScanInfo->aucChannelMDRDYCnt[u4ChCnt] = prScanDone->aucChannelMDRDYCnt[u4ChCnt]; + + if (u4PrintfIdx % 10 == 0 && u4PrintfIdx != 0) { + DBGLOG(SCN, INFO, "Channel : %s\n", g_aucScanChannelNum); + DBGLOG(SCN, INFO, "IdleTime : %s\n", g_aucScanChannelIdleTime); + DBGLOG(SCN, INFO, "MdrdyCnt : %s\n", g_aucScanChannelMDRDY); + DBGLOG(SCN, INFO, + "==================================================================================\n"); + kalMemZero(g_aucScanChannelNum, SCN_SCAN_DONE_PRINT_BUFFER_LENGTH); + kalMemZero(g_aucScanChannelIdleTime, SCN_SCAN_DONE_PRINT_BUFFER_LENGTH); + kalMemZero(g_aucScanChannelMDRDY, SCN_SCAN_DONE_PRINT_BUFFER_LENGTH); + u4PrintfIdx = 0; + } + kalSnprintf(g_aucScanChannelNum + u4PrintfIdx * 7, + sizeof(g_aucScanChannelNum) - u4PrintfIdx * 7, + "%7d", prScanInfo->aucChannelNum[u4ChCnt]); + kalSnprintf(g_aucScanChannelIdleTime + u4PrintfIdx * 7, + sizeof(g_aucScanChannelIdleTime) - u4PrintfIdx * 7, + "%7d", prScanInfo->au2ChannelIdleTime[u4ChCnt]); + kalSnprintf(g_aucScanChannelMDRDY + u4PrintfIdx * 7, + sizeof(g_aucScanChannelMDRDY) - u4PrintfIdx * 7, + "%7d", prScanInfo->aucChannelMDRDYCnt[u4ChCnt]); + u4PrintfIdx++; + } + + DBGLOG(SCN, INFO, "Channel : %s\n", g_aucScanChannelNum); + DBGLOG(SCN, INFO, "IdleTime : %s\n", g_aucScanChannelIdleTime); + DBGLOG(SCN, INFO, "MdrdyCnt : %s\n", g_aucScanChannelMDRDY); + } else { + prScanInfo->fgIsSparseChannelValid = FALSE; + } + } + + if (prScanInfo->eCurrentState == SCAN_STATE_SCANNING && prScanDone->ucSeqNum == prScanParam->ucSeqNum) { + /* generate scan-done event for caller */ + scnFsmGenerateScanDoneMsg(prAdapter, prScanParam->ucSeqNum, prScanParam->ucBssIndex, SCAN_STATUS_DONE); + + /* switch to next pending scan */ + scnFsmSteps(prAdapter, SCAN_STATE_IDLE); + } else { + DBGLOG(SCN, INFO, "Unexpected SCAN-DONE event: SeqNum = %d, Current State = %d\n", + prScanDone->ucSeqNum, prScanInfo->eCurrentState); + } +} /* end of scnEventScanDone */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +scnFsmGenerateScanDoneMsg(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucSeqNum, IN UINT_8 ucBssIndex, 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 (GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType) { + case NETWORK_TYPE_AIS: + prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_AIS_SCAN_DONE; + break; + + case NETWORK_TYPE_P2P: + prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_P2P_SCAN_DONE; + break; + + case NETWORK_TYPE_BOW: + prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_BOW_SCAN_DONE; + break; + + default: + DBGLOG(SCN, LOUD, + "Unexpected Network Type: %d\n", + GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex)->eNetworkType); + ASSERT(0); + break; + } + } + + prScanDoneMsg->ucSeqNum = ucSeqNum; + prScanDoneMsg->ucBssIndex = ucBssIndex; + prScanDoneMsg->eScanStatus = eScanStatus; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanDoneMsg, MSG_SEND_METHOD_BUF); + +} /* end of scnFsmGenerateScanDoneMsg() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Query for most sparse channel +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnQuerySparseChannel(IN P_ADAPTER_T prAdapter, P_ENUM_BAND_T prSparseBand, PUINT_8 pucSparseChannel) +{ + P_SCAN_INFO_T prScanInfo; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + if (prScanInfo->fgIsSparseChannelValid == TRUE) { + if (prSparseBand) + *prSparseBand = prScanInfo->rSparseChannel.eBand; + + if (pucSparseChannel) + *pucSparseChannel = prScanInfo->rSparseChannel.ucChannelNum; + + return TRUE; + } else { + return FALSE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Event handler for NLO done event +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnEventNloDone(IN P_ADAPTER_T prAdapter, IN P_EVENT_NLO_DONE_T prNloDone) +{ + P_SCAN_INFO_T prScanInfo; + P_NLO_PARAM_T prNloParam; + P_SCAN_PARAM_T prScanParam; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prNloParam = &prScanInfo->rNloParam; + prScanParam = &prNloParam->rScanParam; + + if (prScanInfo->fgNloScanning == TRUE && prNloDone->ucSeqNum == prScanParam->ucSeqNum) { + + DBGLOG(SCN, INFO, "scnEventNloDone reporting to uplayer\n"); + + kalSchedScanResults(prAdapter->prGlueInfo); + + if (prNloParam->fgStopAfterIndication == TRUE) + prScanInfo->fgNloScanning = FALSE; + } else { + DBGLOG(SCN, INFO, "Unexpected NLO-DONE event: SeqNum = %d, Current State = %d\n", + prNloDone->ucSeqNum, prScanInfo->eCurrentState); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief OID handler for starting scheduled scan +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +scnFsmSchedScanRequest(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucSsidNum, + IN P_PARAM_SSID_T prSsid, IN UINT_32 u4IeLength, IN PUINT_8 pucIe, IN UINT_16 u2Interval) +{ + P_SCAN_INFO_T prScanInfo; + P_NLO_PARAM_T prNloParam; + P_SCAN_PARAM_T prScanParam; + P_CMD_NLO_REQ prCmdNloReq; + UINT_32 i, j; + + ASSERT(prAdapter); + + DBGLOG(SCN, INFO, "scnFsmSchedScanRequest\n"); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prNloParam = &prScanInfo->rNloParam; + prScanParam = &prNloParam->rScanParam; + + /* ASSERT(prScanInfo->fgNloScanning == FALSE); */ + if (prScanInfo->fgNloScanning) { + DBGLOG(SCN, INFO, "prScanInfo->fgNloScanning == FALSE already scanning\n"); + return TRUE; + } + + prScanInfo->fgNloScanning = TRUE; + + /* 1. load parameters */ + prScanParam->ucSeqNum++; + prScanParam->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; + prNloParam->fgStopAfterIndication = FALSE; + prNloParam->ucFastScanIteration = 0; + + if (u2Interval < SCAN_NLO_DEFAULT_INTERVAL) { + u2Interval = SCAN_NLO_DEFAULT_INTERVAL; + DBGLOG(SCN, INFO, "force interval to SCAN_NLO_DEFAULT_INTERVAL\n"); + } + prAdapter->prAisBssInfo->fgIsPNOEnable = TRUE; + + if (!IS_NET_ACTIVE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex)) { + SET_NET_ACTIVE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + + DBGLOG(SCN, INFO, "ACTIVE AIS from INACTIVE to enable PNO\n"); + /* sync with firmware */ + nicActivateNetwork(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + } + prNloParam->u2FastScanPeriod = u2Interval; + prNloParam->u2SlowScanPeriod = u2Interval; + + if (ucSsidNum > CFG_SCAN_SSID_MAX_NUM) + prScanParam->ucSSIDNum = CFG_SCAN_SSID_MAX_NUM; + else + prScanParam->ucSSIDNum = ucSsidNum; + + if (ucSsidNum > CFG_SCAN_SSID_MATCH_MAX_NUM) + prNloParam->ucMatchSSIDNum = CFG_SCAN_SSID_MATCH_MAX_NUM; + else + prNloParam->ucMatchSSIDNum = ucSsidNum; + + for (i = 0; i < prNloParam->ucMatchSSIDNum; i++) { + if (i < CFG_SCAN_SSID_MAX_NUM) { + COPY_SSID(prScanParam->aucSpecifiedSSID[i], + prScanParam->ucSpecifiedSSIDLen[i], prSsid[i].aucSsid, (UINT_8) prSsid[i].u4SsidLen); + } + + COPY_SSID(prNloParam->aucMatchSSID[i], + prNloParam->ucMatchSSIDLen[i], prSsid[i].aucSsid, (UINT_8) prSsid[i].u4SsidLen); + + /* for linux the Ciper,Auth Algo will be zero */ + prNloParam->aucCipherAlgo[i] = 0; + prNloParam->au2AuthAlgo[i] = 0; + + for (j = 0; j < SCN_NLO_NETWORK_CHANNEL_NUM; j++) + prNloParam->aucChannelHint[i][j] = 0; + } + + /* 2. prepare command for sending */ + prCmdNloReq = (P_CMD_NLO_REQ) cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_NLO_REQ) + u4IeLength); + + if (!prCmdNloReq) { + ASSERT(0); /* Can't initiate NLO operation */ + return FALSE; + } + + /* 3. send command packet for NLO operation */ + kalMemZero(prCmdNloReq, sizeof(CMD_NLO_REQ)); + + prCmdNloReq->ucSeqNum = prScanParam->ucSeqNum; + prCmdNloReq->ucBssIndex = prScanParam->ucBssIndex; + prCmdNloReq->fgStopAfterIndication = prNloParam->fgStopAfterIndication; + prCmdNloReq->ucFastScanIteration = prNloParam->ucFastScanIteration; + prCmdNloReq->u2FastScanPeriod = prNloParam->u2FastScanPeriod; + prCmdNloReq->u2SlowScanPeriod = prNloParam->u2SlowScanPeriod; + prCmdNloReq->ucEntryNum = prNloParam->ucMatchSSIDNum; + +#ifdef LINUX + prCmdNloReq->ucFlag = SCAN_NLO_CHECK_SSID_ONLY; + DBGLOG(SCN, INFO, "LINUX only check SSID for PNO SCAN\n"); +#endif + for (i = 0; i < prNloParam->ucMatchSSIDNum; i++) { + COPY_SSID(prCmdNloReq->arNetworkList[i].aucSSID, + prCmdNloReq->arNetworkList[i].ucSSIDLength, + prNloParam->aucMatchSSID[i], prNloParam->ucMatchSSIDLen[i]); + + prCmdNloReq->arNetworkList[i].ucCipherAlgo = prNloParam->aucCipherAlgo[i]; + prCmdNloReq->arNetworkList[i].u2AuthAlgo = prNloParam->au2AuthAlgo[i]; + DBGLOG(SCN, INFO, "prCmdNloReq->arNetworkList[i].aucSSID %s\n", prCmdNloReq->arNetworkList[i].aucSSID); + DBGLOG(SCN, INFO, + "prCmdNloReq->arNetworkList[i].ucSSIDLength %d\n", prCmdNloReq->arNetworkList[i].ucSSIDLength); + DBGLOG(SCN, INFO, + "prCmdNloReq->arNetworkList[i].ucCipherAlgo %d\n", prCmdNloReq->arNetworkList[i].ucCipherAlgo); + DBGLOG(SCN, INFO, + "prCmdNloReq->arNetworkList[i].u2AuthAlgo %d\n", prCmdNloReq->arNetworkList[i].u2AuthAlgo); + + for (j = 0; j < SCN_NLO_NETWORK_CHANNEL_NUM; j++) + prCmdNloReq->arNetworkList[i].ucNumChannelHint[j] = prNloParam->aucChannelHint[i][j]; + } + + if (u4IeLength <= MAX_IE_LENGTH) + prCmdNloReq->u2IELen = prScanParam->u2IELen; + else + prCmdNloReq->u2IELen = MAX_IE_LENGTH; + + if (u4IeLength) { + kalMemCopy(prScanParam->aucIE, pucIe, prCmdNloReq->u2IELen); + kalMemCopy(prCmdNloReq->aucIE, pucIe, prCmdNloReq->u2IELen); + } + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_NLO_REQ, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_NLO_REQ) + prCmdNloReq->u2IELen, (PUINT_8) prCmdNloReq, NULL, 0); + + cnmMemFree(prAdapter, (PVOID) prCmdNloReq); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief OID handler for stopping scheduled scan +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnFsmSchedScanStopRequest(IN P_ADAPTER_T prAdapter) +{ + P_SCAN_INFO_T prScanInfo; + P_NLO_PARAM_T prNloParam; + P_SCAN_PARAM_T prScanParam; + CMD_NLO_CANCEL rCmdNloCancel; + WLAN_STATUS rStatus; + + ASSERT(prAdapter); + DBGLOG(SCN, INFO, "scnFsmSchedScanStopRequest\n"); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prNloParam = &prScanInfo->rNloParam; + prScanParam = &prNloParam->rScanParam; + + if (prAdapter->prAisBssInfo->fgIsNetRequestInActive && prAdapter->prAisBssInfo->fgIsPNOEnable) { + UNSET_NET_ACTIVE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + + DBGLOG(SCN, INFO, "INACTIVE AIS from ACTIVE to DISABLE PNO\n"); + /* sync with firmware */ + nicDeactivateNetwork(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); + } else { + DBGLOG(SCN, INFO, + "fgIsNetRequestInActive %d, fgIsPNOEnable %d\n", + prAdapter->prAisBssInfo->fgIsNetRequestInActive, prAdapter->prAisBssInfo->fgIsPNOEnable); + } + + prAdapter->prAisBssInfo->fgIsPNOEnable = FALSE; + + /* send cancel message to firmware domain */ + rCmdNloCancel.ucSeqNum = prScanParam->ucSeqNum; + + rStatus = wlanSendSetQueryCmd(prAdapter, CMD_ID_SET_NLO_CANCEL, TRUE, FALSE, TRUE, nicCmdEventSetStopSchedScan, + /* nicCmdEventSetCommon, */ + nicOidCmdTimeoutCommon, + sizeof(CMD_NLO_CANCEL), (PUINT_8) &rCmdNloCancel, NULL, 0); + + prScanInfo->fgNloScanning = FALSE; + if (rStatus != WLAN_STATUS_FAILURE) + return TRUE; + else + return FALSE; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/swcr.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/swcr.c new file mode 100644 index 0000000000000..def4ad190d418 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/swcr.c @@ -0,0 +1,1234 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/swcr.c#1 +*/ + +/*! \file "swcr.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" +#include "swcr.h" + +#if CFG_SUPPORT_SWCR + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +UINT_32 g_au4SwCr[SWCR_CR_NUM]; /*: 0: command other: data */ + +/* JB mDNS Filter*/ +UINT_32 g_u4RXFilter; /* [31] 0: stop 1: start, [3] IPv6 [2] IPv4 */ + +static TIMER_T g_rSwcrDebugTimer; +static BOOLEAN g_fgSwcrDebugTimer = FALSE; +static UINT_32 g_u4SwcrDebugCheckTimeout; +static ENUM_SWCR_DBG_TYPE_T g_ucSwcrDebugCheckType; +static UINT_32 g_u4SwcrDebugFrameDumpType; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static const PFN_CMD_RW_T g_arSwCtrlCmd[] = { + swCtrlCmdCategory0, + swCtrlCmdCategory1 +#if TEST_PS + , testPsCmdCategory0, testPsCmdCategory1 +#endif +#if CFG_SUPPORT_802_11V +#if (CFG_SUPPORT_802_11V_TIMING_MEASUREMENT == 1) && (WNM_UNIT_TEST == 1) + , testWNMCmdCategory0 +#endif +#endif +}; + +const PFN_SWCR_RW_T g_arSwCrModHandle[] = { + swCtrlSwCr, + NULL +}; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +enum { + SWCTRL_MAGIC, + SWCTRL_DEBUG, + SWCTRL_WIFI_VAR, + SWCTRL_ENABLE_INT, + SWCTRL_DISABLE_INT, + SWCTRL_TXM_INFO, + SWCTRL_RXM_INFO, + SWCTRL_DUMP_BSS, + SWCTRL_QM_INFO, + SWCTRL_DUMP_ALL_QUEUE_LEN, + SWCTRL_DUMP_MEM, + SWCTRL_TX_CTRL_INFO, + SWCTRL_DUMP_QUEUE, + SWCTRL_DUMP_QM_DBG_CNT, + SWCTRL_QM_DBG_CNT, + SWCTRL_RX_PKTS_DUMP, + SWCTRL_RX_FILTER, +#if CFG_INIT_ENABLE_PATTERN_FILTER_ARP + SWCTRL_RX_ARP_OFFLOAD, +#endif + SWCTRL_PS_DTIM_SKIP, + SWCTRL_ROAMING, + SWCTRL_CATA0_INDEX_NUM +}; + +enum { + SWCTRL_STA_INFO, + SWCTRL_DUMP_STA, + SWCTRL_STA_QUE_INFO, + SWCTRL_CATA1_INDEX_NUM +}; + +/* JB mDNS Filter*/ +#define RX_FILTER_START (1<<31) +#define RX_FILTER_IPV4 (1<<2) +#define RX_FILTER_IPV6 (1<<3) +typedef enum _ENUM_SWCR_RX_FILTER_CMD_T { + SWCR_RX_FILTER_CMD_STOP = 0, + SWCR_RX_FILTER_CMD_START, + SWCR_RX_FILTER_CMD_ADD, + SWCR_RX_FILTER_CMD_REMOVE, + SWCR_RX_FILTER_NUM +} ENUM_SWCR_RX_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; +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + 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.au4MaxNumOfBuffer[i], prTxCtrl->rTc.au4FreeBufferCount[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]); + + } +#endif + +#if QM_FORWARDING_FAIRNESS + 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->au4ResourceUsedCount[i]); + } +#endif + + 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->ucWlanIndex; + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); + 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->aprTargetQueue[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, "eNetworkType %u\n", prBssInfo->eNetworkType); + DBGLOG(SW4, INFO, "ucBssIndex %u\n", prBssInfo->ucBssIndex); + 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; + CMD_RX_PACKET_FILTER rSetRxPacketFilter; + + 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: + 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_FILTER: + { + UINT_32 u4rxfilter; + BOOLEAN fgUpdate = FALSE; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + if (ucOpt0 == SWCR_RX_FILTER_CMD_STOP) { + g_u4RXFilter &= ~(RX_FILTER_START); +/* changed by jeffrey to align Android behavior */ +#if 0 + if (prAdapter->fgAllMulicastFilter == FALSE) + prAdapter->u4OsPacketFilter &= ~PARAM_PACKET_FILTER_ALL_MULTICAST; +#endif + prAdapter->u4OsPacketFilter &= ~PARAM_PACKET_FILTER_MULTICAST; + u4rxfilter = prAdapter->u4OsPacketFilter; + fgUpdate = TRUE; + } else if (ucOpt0 == SWCR_RX_FILTER_CMD_START) { + g_u4RXFilter |= (RX_FILTER_START); + + if ((g_u4RXFilter & RX_FILTER_IPV4) || (g_u4RXFilter & RX_FILTER_IPV6)) { +#if 0 + prAdapter->u4OsPacketFilter |= PARAM_PACKET_FILTER_ALL_MULTICAST; +#endif + prAdapter->u4OsPacketFilter |= PARAM_PACKET_FILTER_MULTICAST; + } + u4rxfilter = prAdapter->u4OsPacketFilter; + fgUpdate = TRUE; + } else if (ucOpt0 == SWCR_RX_FILTER_CMD_ADD) { + if (ucOpt1 < 31) + g_u4RXFilter |= (1 << ucOpt1); + } else if (ucOpt0 == SWCR_RX_FILTER_CMD_REMOVE) { + if (ucOpt1 < 31) + g_u4RXFilter &= ~(1 << ucOpt1); + } + + if (fgUpdate == TRUE) { + rSetRxPacketFilter.u4RxPacketFilter = u4rxfilter; + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_RX_FILTER, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_RX_PACKET_FILTER),/*u4SetQueryInfoLen*/ + (PUINT_8)&rSetRxPacketFilter,/*pucInfoBuffer*/ + NULL, /* pvSetQueryBuffer */ + 0 /* un4SetQueryBufferLen */ + ); + u4rxfilter = rSetRxPacketFilter.u4RxPacketFilter; + } + /* DBGLOG(SW4, INFO,("SWCTRL_RX_FILTER: + * g_u4RXFilter %x ucOpt0 %x ucOpt1 %x fgUpdate %x u4rxfilter %x, rStatus %x\n", + */ + /* g_u4RXFilter, ucOpt0, ucOpt1, fgUpdate, u4rxfilter, rStatus)); */ + } + break; + +#if CFG_INIT_ENABLE_PATTERN_FILTER_ARP + case SWCTRL_RX_ARP_OFFLOAD: + { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_32 u4SetInfoLen = 0; + UINT_32 u4Len = OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress); + UINT_32 u4NumIPv4 = 0, u4NumIPv6 = 0; + UINT_32 i = 0; + PUINT_8 pucBufIpAddr = NULL; + P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = NULL; + P_PARAM_NETWORK_ADDRESS_IP prParamIpAddr = NULL; + PUINT_8 pucIp = NULL; + /* PUINT_8 pucIpv6 = NULL; */ + UINT_32 bufSize = + u4Len + (OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + + sizeof(PARAM_NETWORK_ADDRESS_IP)) * 3; + P_PARAM_NETWORK_ADDRESS prParamNetAddr = NULL; + + /* <1> allocate IP address buffer */ + pucBufIpAddr = kalMemAlloc(bufSize, VIR_MEM_TYPE); + pucIp = kalMemAlloc(3 * 4, VIR_MEM_TYPE); /* TODO: replace 3 to macro */ + + prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST) pucBufIpAddr; + prParamNetAddr = prParamNetAddrList->arAddress; + /* <2> clear IP address buffer */ + kalMemZero(pucBufIpAddr, bufSize); + kalMemZero(pucIp, 3 * 4); + + /* <3> setup the number of IP address */ + if (ucOpt1 == 1) { + if (wlanGetIPV4Address(prAdapter->prGlueInfo, pucIp, &u4NumIPv4) && + u4NumIPv4 > 3) /* TODO: repleace 3 to macro */ + u4NumIPv4 = 3; + } else if (ucOpt1 == 0) { + u4NumIPv4 = u4NumIPv6 = 0; + } + DBGLOG(INIT, INFO, "u4Len:%d bufSize:%d u4NumIPv4:%d\n", u4Len, bufSize, u4NumIPv4); + + prParamNetAddrList->u4AddressCount = u4NumIPv6 + u4NumIPv4; + prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + + for (i = 0; i < u4NumIPv4; i++) { + prParamNetAddr->u2AddressLength = sizeof(PARAM_NETWORK_ADDRESS_IP); + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + prParamIpAddr = (P_PARAM_NETWORK_ADDRESS_IP) prParamNetAddr->aucAddress; + kalMemCopy(&prParamIpAddr->in_addr, pucIp + (i * 4), 4); + prParamNetAddr = + (P_PARAM_NETWORK_ADDRESS) ((UINT_32) prParamNetAddr + + OFFSET_OF + (PARAM_NETWORK_ADDRESS, + aucAddress) + sizeof(PARAM_NETWORK_ADDRESS_IP)); + u4Len += + OFFSET_OF(PARAM_NETWORK_ADDRESS, + aucAddress) + sizeof(PARAM_NETWORK_ADDRESS_IP); + } + +#if 0 +#ifdef CONFIG_IPV6 + if (!wlanGetIPV6Address(prAdapter->prGlueInfo, pucIp, &u4NumIPv6) + || (u4NumIPv6 + u4NumIPv4) > 3) { + goto bailout; + } + + pucIpv6 = kalMemAlloc(u4NumIPv6 * 16, VIR_MEM_TYPE); + + for (i = 0; i < u4NumIPv6; i++) { + prParamNetAddr->u2AddressLength = 6; + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + kalMemCopy(prParamNetAddr->aucAddress, pucIpv6 + (i * 16), 16); + prParamNetAddr = + (P_PARAM_NETWORK_ADDRESS) ((UINT_32) prParamNetAddr + sizeof(ip6)); + u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip6); + } +#endif +#endif + + ASSERT(u4Len <= bufSize); + + rStatus = wlanoidSetNetworkAddress(prAdapter, + (PVOID) prParamNetAddrList, u4Len, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "set HW packet filter fail 0x%1x\n", rStatus); + + if (pucIp) + kalMemFree(pucIp, VIR_MEM_TYPE, 3 * 4); /* TODO: replace 3 to marco */ + if (pucBufIpAddr) + kalMemFree(pucBufIpAddr, VIR_MEM_TYPE, bufSize); + + } + break; +#endif + case SWCTRL_PS_DTIM_SKIP: + break; + case SWCTRL_ROAMING: + break; + default: + break; + } + } else { + switch (ucIndex) { + case SWCTRL_DEBUG: + break; + case SWCTRL_MAGIC: + g_au4SwCr[1] = _SWCTRL_MAGIC; + break; + case SWCTRL_QM_INFO: + { + P_QUE_MGT_T prQM = &prAdapter->rQM; + + switch (ucOpt0) { + case 0: +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + 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]; +#endif + break; + + case 1: +#if QM_FORWARDING_FAIRNESS + g_au4SwCr[1] = prQM->au4ResourceUsedCount[ucOpt1]; + g_au4SwCr[2] = prQM->au4HeadStaRecIndex[ucOpt1]; +#endif + break; + + case 2: + g_au4SwCr[1] = prQM->arTxQueue[ucOpt1].u4NumElem; /* only one */ + + break; + } + } + break; + case SWCTRL_TX_CTRL_INFO: + { + P_TX_CTRL_T prTxCtrl; + + prTxCtrl = &prAdapter->rTxCtrl; + switch (ucOpt0) { + case 0: + g_au4SwCr[1] = prAdapter->rTxCtrl.rTc.au4FreeBufferCount[ucOpt1]; + g_au4SwCr[2] = prAdapter->rTxCtrl.rTc.au4MaxNumOfBuffer[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, GET_BSS_INFO_BY_INDEX(prAdapter, 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->ucWlanIndex; + if (ucRead == SWCR_WRITE) { + /* ToDo:: Nothing */ + } else { + /* Read */ + switch (ucIndex) { + case SWCTRL_STA_QUE_INFO: + { + g_au4SwCr[1] = prStaRec->arTxQueue[ucOpt1].u4NumElem; + } + break; + case SWCTRL_STA_INFO: + switch (ucOpt1) { + case 0: + g_au4SwCr[1] = prStaRec->fgIsInPS; + break; + } + + break; + + case SWCTRL_DUMP_STA: + { + dumpSTA(prAdapter, prStaRec); + } + break; + + default: + + break; + } + } + +} + +#if TEST_PS + +VOID +testPsSendQoSNullFrame(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN UINT_8 ucUP, + IN UINT_8 ucBssIndex, + IN BOOLEAN fgBMC, + IN BOOLEAN fgIsBurstEnd, IN BOOLEAN ucPacketType, IN BOOLEAN ucPsSessionID, IN BOOLEAN fgSetEOSP) +{ + P_MSDU_INFO_T prMsduInfo; + UINT_16 u2EstimatedFrameLen; + P_WLAN_MAC_HEADER_QOS_T prQoSNullFrame; + + DEBUGFUNC("testPsSendQoSNullFrame"); + DBGLOG(SW4, LOUD, "\n"); + + /* 4 <1> Allocate a PKT_INFO_T for Null Frame */ + /* Init with MGMT Header Length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + WLAN_MAC_HEADER_QOS_LEN; + + /* Allocate a MSDU_INFO_T */ + + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + + if (prMsduInfo == NULL) { + DBGLOG(SW4, WARN, "No PKT_INFO_T for sending Null Frame.\n"); + return; + } + /* 4 <2> Compose Null frame in MSDU_INfO_T. */ + bssComposeQoSNullFrame(prAdapter, + (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + prStaRec, ucUP, fgSetEOSP); + + TX_SET_MMPDU(prAdapter, + prMsduInfo, + ucBssIndex, + prStaRec->ucIndex, WLAN_MAC_HEADER_QOS_LEN, WLAN_MAC_HEADER_QOS_LEN, NULL, MSDU_RATE_MODE_AUTO); + + prMsduInfo->ucUserPriority = ucUP; + prMsduInfo->ucPacketType = ucPacketType; + + prQoSNullFrame = (P_WLAN_MAC_HEADER_QOS_T) ((PUINT_8) + ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD)); + + if (fgBMC) + prQoSNullFrame->aucAddr1[0] = 0xfd; + else + prQoSNullFrame->aucAddr1[5] = 0xdd; + + /* 4 <4> Inform TXM to send this Null frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + +} + +VOID testPsSetupBss(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex) +{ + P_BSS_INFO_T prBssInfo; + UINT_8 _aucZeroMacAddr[] = NULL_MAC_ADDR; + + DEBUGFUNC("testPsSetupBss()"); + DBGLOG(SW4, INFO, "index %d\n", ucBssIndex); + + prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); + + /* 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, prBssInfo); + + prBssInfo->eConnectionState = PARAM_MEDIA_STATE_DISCONNECTED; + prBssInfo->eConnectionStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; + prBssInfo->eCurrentOPMode = OP_MODE_ACCESS_POINT; + prBssInfo->fgIsNetActive = TRUE; + prBssInfo->ucBssIndex = ucBssIndex; + 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->u2HwDefaultFixedRateCode = 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->ucBssIndex = ucBssIndex; + } 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].ucIsACMSet = 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].ucIsACMSet, + prBssInfo->arACQueParms[eAci].u2Aifsn, + prBssInfo->arACQueParms[eAci].u2CWmin, + prBssInfo->arACQueParms[eAci].u2CWmax, prBssInfo->arACQueParms[eAci].u2TxopLimit); + + } +#endif + + DBGLOG(SW4, INFO, "[2] ucBmpDeliveryAC:0x%x, ucBmpTriggerAC:0x%x, ucUapsdSp:0x%x", + prBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC, + prBssInfo->rPmProfSetupInfo.ucBmpTriggerAC, prBssInfo->rPmProfSetupInfo.ucUapsdSp); +} + +VOID testPsCmdCategory0(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1) +{ + UINT_8 ucIndex, ucRead; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("testPsCmdCategory0"); + SWCR_GET_RW_INDEX(ucAction, ucRead, ucIndex); + + DBGLOG(SW4, LOUD, "Read %u Index %u\n", ucRead, ucIndex); + + prStaRec = cnmGetStaRecByIndex(prAdapter, 0); + + if (ucIndex >= TEST_PS_CATA0_INDEX_NUM) + return; + + if (ucRead == SWCR_WRITE) { + switch (ucIndex) { + case TEST_PS_SETUP_BSS: + testPsSetupBss(prAdapter, ucOpt0); + break; + + case TEST_PS_ENABLE_BEACON: + break; + + case TEST_PS_TRIGGER_BMC: + /* txmForwardQueuedBmcPkts (ucOpt0); */ + break; + case TEST_PS_SEND_NULL: + { + + testPsSendQoSNullFrame(prAdapter, prStaRec, (UINT_8) (g_au4SwCr[1] & 0xFF), /* UP */ + ucOpt0, (BOOLEAN) ((g_au4SwCr[1] >> 8) & 0xFF), /* BMC */ + (BOOLEAN) ((g_au4SwCr[1] >> 16) & 0xFF), /* BurstEnd */ + (BOOLEAN) ((g_au4SwCr[1] >> 24) & 0xFF), /* Packet type */ + (UINT_8) ((g_au4SwCr[2]) & 0xFF), /* PS sesson ID 7: NOACK */ + FALSE /* EOSP */ + ); + } + break; + case TEST_PS_BUFFER_BMC: + /* g_aprBssInfo[ucOpt0]->fgApToBufferBMC = (g_au4SwCr[1] & 0xFF); */ + break; + case TEST_PS_UPDATE_BEACON: + bssUpdateBeaconContent(prAdapter, ucOpt0 /*networktype */); + break; + + default: + break; + } + } else { + switch (ucIndex) { + + case TEST_PS_MAGIC: + g_au4SwCr[1] = 0x88660011; + break; + + } + } +} + +#endif /* TEST_PS */ + +#if TEST_PS + +VOID testPsCmdCategory1(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1) +{ + UINT_8 ucIndex, ucRead; + UINT_8 ucWTEntry; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("testPsCmdCategory1"); + + SWCR_GET_RW_INDEX(ucAction, ucRead, ucIndex); + + if (ucOpt0 >= CFG_STA_REC_NUM) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucOpt0); + + if (!prStaRec) { + DBGLOG(SW4, INFO, "prStaRec is NULL, ucOpt0:%d\n", ucOpt0); + return; + } + + ucWTEntry = prStaRec->ucWlanIndex; + 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 < ARRAY_SIZE(g_arSwCtrlCmd)) { + 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 < (ARRAY_SIZE(g_arSwCrModHandle))) { + + 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; +#if CFG_RX_PKTS_DUMP + prAdapter->rRxCtrl.u4RxPktsDumpTypeMask = u4DumpType; +#endif +} + +VOID swCrDebugInit(P_ADAPTER_T prAdapter) +{ + /* frame dump */ + if (g_u4SwcrDebugFrameDumpType) + swCrFrameCheckEnable(prAdapter, g_u4SwcrDebugFrameDumpType); + /* debug counter */ + g_fgSwcrDebugTimer = FALSE; + + cnmTimerInitTimer(prAdapter, &g_rSwcrDebugTimer, (PFN_MGMT_TIMEOUT_FUNC) swCrDebugCheckTimeout, (ULONG) NULL); + + if (g_u4SwcrDebugCheckTimeout) + swCrDebugCheckEnable(prAdapter, TRUE, g_ucSwcrDebugCheckType, g_u4SwcrDebugCheckTimeout); +} + +VOID swCrDebugUninit(P_ADAPTER_T prAdapter) +{ + cnmTimerStopTimer(prAdapter, &g_rSwcrDebugTimer); + + g_fgSwcrDebugTimer = FALSE; +} + +VOID swCrDebugCheckEnable(P_ADAPTER_T prAdapter, BOOLEAN fgIsEnable, UINT_8 ucType, UINT_32 u4Timeout) +{ + if (fgIsEnable) { + g_ucSwcrDebugCheckType = ucType; + g_u4SwcrDebugCheckTimeout = u4Timeout; + if (g_fgSwcrDebugTimer == FALSE) + swCrDebugCheckTimeout(prAdapter, 0); + } else { + cnmTimerStopTimer(prAdapter, &g_rSwcrDebugTimer); + g_u4SwcrDebugCheckTimeout = 0; + } + + g_fgSwcrDebugTimer = fgIsEnable; +} + +VOID swCrDebugCheck(P_ADAPTER_T prAdapter, P_CMD_SW_DBG_CTRL_T prCmdSwCtrl) +{ + P_RX_CTRL_T prRxCtrl; + P_TX_CTRL_T prTxCtrl; + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + + /* dump counters */ + if (prCmdSwCtrl) { + if (prCmdSwCtrl->u4Data == SWCR_DBG_TYPE_ALL) { + + /* TX Counter from fw */ + DBGLOG(SW4, INFO, "TX0\n" + "%08x %08x %08x %08x\n" + "%08x %08x %08x %08x\n", + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_BCN_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_FAILED_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_RETRY_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_AGING_TIMEOUT_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_PS_OVERFLOW_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_MGNT_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_ERROR_CNT]); +#if 1 + /* TX Counter from drv */ + DBGLOG(SW4, INFO, "TX1\n" + "%08x %08x %08x %08x\n", + (UINT_32) TX_GET_CNT(prTxCtrl, TX_INACTIVE_BSS_DROP), + (UINT_32) TX_GET_CNT(prTxCtrl, TX_INACTIVE_STA_DROP), + (UINT_32) TX_GET_CNT(prTxCtrl, TX_FORWARD_OVERFLOW_DROP), + (UINT_32) TX_GET_CNT(prTxCtrl, TX_AP_BORADCAST_DROP)); +#endif + + /* RX Counter */ + DBGLOG(SW4, INFO, "RX0\n" + "%08x %08x %08x %08x\n" + "%08x %08x %08x %08x\n" + "%08x %08x %08x %08x\n" + "%08x %08x %08x %08x\n", + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_DUP_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_TYPE_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_CLASS_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_AMPDU_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_STATUS_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_FORMAT_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_ICV_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_KEY_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_TKIP_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_MIC_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_BIP_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_FCSERR_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_FIFOFULL_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_PFDROP_CNT]); + + DBGLOG(SW4, INFO, "RX1\n" + "%08x %08x %08x %08x\n" + "%08x %08x %08x %08x\n", + (UINT_32) RX_GET_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT), + (UINT_32) RX_GET_CNT(prRxCtrl, RX_DATA_INDICATION_COUNT), + (UINT_32) RX_GET_CNT(prRxCtrl, RX_DATA_RETURNED_COUNT), + (UINT_32) RX_GET_CNT(prRxCtrl, RX_DATA_RETAINED_COUNT), + (UINT_32) RX_GET_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT), + (UINT_32) RX_GET_CNT(prRxCtrl, RX_TYPE_ERR_DROP_COUNT), + (UINT_32) RX_GET_CNT(prRxCtrl, RX_CLASS_ERR_DROP_COUNT), + (UINT_32) RX_GET_CNT(prRxCtrl, RX_DST_NULL_DROP_COUNT)); + + DBGLOG(SW4, INFO, "PWR\n" + "%08x %08x %08x %08x\n" + "%08x %08x %08x %08x\n", + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_PS_POLL_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_TRIGGER_NULL_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_BCN_IND_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_BCN_TIMEOUT_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_PM_STATE0], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_PM_STATE1], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_CUR_PS_PROF0], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_CUR_PS_PROF1]); + + DBGLOG(SW4, INFO, "ARM\n" + "%08x %08x %08x %08x\n" + "%08x %08x\n", + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_AR_STA0_RATE], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_AR_STA0_BWGI], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_AR_STA0_RX_RATE_RCPI], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_ROAMING_ENABLE], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_ROAMING_ROAM_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_ROAMING_INT_CNT]); + + DBGLOG(SW4, INFO, "BB\n" + "%08x %08x %08x %08x\n" + "%08x %08x %08x %08x\n", + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_RX_MDRDY_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_RX_FCSERR_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_CCK_PD_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_OFDM_PD_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_CCK_SFDERR_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_CCK_SIGERR_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_OFDM_TAGERR_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_OFDM_SIGERR_CNT]); + + } + } + /* start the next check */ + if (g_u4SwcrDebugCheckTimeout) + cnmTimerStartTimer(prAdapter, &g_rSwcrDebugTimer, g_u4SwcrDebugCheckTimeout * MSEC_PER_SEC); +} + +VOID swCrDebugCheckTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr) +{ + CMD_SW_DBG_CTRL_T rCmdSwCtrl; + WLAN_STATUS rStatus; + + rCmdSwCtrl.u4Id = (0xb000 << 16) + g_ucSwcrDebugCheckType; + rCmdSwCtrl.u4Data = 0; + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SW_DBG_CTRL, /* ucCID */ + FALSE, /* fgSetQuery */ + TRUE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + swCrDebugQuery, /* pfCmdDoneHandler */ + swCrDebugQueryTimeout, /* pfCmdTimeoutHandler */ + sizeof(CMD_SW_DBG_CTRL_T), /* u4SetQueryInfoLen */ + (PUINT_8) &rCmdSwCtrl, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); +} + +VOID swCrDebugQuery(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + ASSERT(prAdapter); + + swCrDebugCheck(prAdapter, (P_CMD_SW_DBG_CTRL_T) (pucEventBuf)); +} + +VOID swCrDebugQueryTimeout(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + ASSERT(prAdapter); + + swCrDebugCheck(prAdapter, NULL); +} + +#endif /* CFG_SUPPORT_SWCR */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/tdls.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/tdls.c new file mode 100644 index 0000000000000..53eda9472d4f0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/tdls.c @@ -0,0 +1,1979 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: tdls.c#1 +*/ + +/*! \file tdls.c +* \brief This file includes IEEE802.11z TDLS support. +*/ + + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ +#include "precomp.h" + +#if CFG_SUPPORT_TDLS +#include "tdls.h" +#include "gl_cfg80211.h" +#include "queue.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + /* The list of valid data rates. */ +/* The list of valid data rates. */ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +static BOOLEAN fgIsPtiTimeoutSkip = FALSE; + +/******************************************************************************* +* P R I V A T E F U N C T I O N S +******************************************************************************** +*/ + +#define ELEM_ID_LINK_IDENTIFIER_LENGTH 16 + +#define TDLS_KEY_TIMEOUT_INTERVAL 43200 + +#define UNREACH_ABLE 25 +#define TDLS_REASON_CODE_UNREACHABLE 25 +#define TDLS_REASON_CODE_UNSPECIFIED 26 + +#define WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE 25 +#define WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED 26 + +UINT_8 g_arTdlsLink[MAXNUM_TDLS_PEER] = { + 0, + 0, + 0, + 0 +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to hadel TDLS link oper from nl80211. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] +* \param[in] +* \param[in] buf includes RSN IE + FT IE + Lifetimeout IE +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 TdlsexLinkMgt(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, PUINT_32 pu4SetInfoLen) +{ + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + + STA_RECORD_T *prStaRec; + P_BSS_INFO_T prBssInfo; + TDLS_CMD_LINK_MGT_T *prCmd; + + prCmd = (TDLS_CMD_LINK_MGT_T *) pvSetBuffer; + prBssInfo = prAdapter->prAisBssInfo; + + DBGLOG(TDLS, INFO, "u4SetBufferLen=%d", u4SetBufferLen); + +#if 1 + /* AIS only */ + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + prStaRec = prBssInfo->prStaRecOfAP; + if (prStaRec == NULL) + return 0; + } else { + return -EINVAL; + } +#endif + + DBGLOG(TDLS, INFO, "prCmd->ucActionCode=%d, prCmd->ucDialogToken=%d", + prCmd->ucActionCode, prCmd->ucDialogToken); + + switch (prCmd->ucActionCode) { + + case TDLS_FRM_ACTION_DISCOVERY_REQ: + /* printk("\n\n\n TDLS_FRM_ACTION_DISCOVERY_REQ\n\n\n"); */ + if (TdlsDataFrameSend_DISCOVERY_REQ(prAdapter, + prStaRec, + prCmd->aucPeer, + prCmd->ucActionCode, + prCmd->ucDialogToken, + prCmd->u2StatusCode, + (UINT_8 *) (prCmd->aucSecBuf), + prCmd->u4SecBufLen) != TDLS_STATUS_SUCCESS) { + return -1; + } + + break; + + case TDLS_FRM_ACTION_SETUP_REQ: + /* printk("\n\n\n TDLS_FRM_ACTION_SETUP_REQ\n\n\n"); */ + prStaRec = cnmGetTdlsPeerByAddress(prAdapter, prAdapter->prAisBssInfo->ucBssIndex, prCmd->aucPeer); + g_arTdlsLink[prStaRec->ucTdlsIndex] = 0; + if (TdlsDataFrameSend_SETUP_REQ(prAdapter, + prStaRec, + prCmd->aucPeer, + prCmd->ucActionCode, + prCmd->ucDialogToken, + prCmd->u2StatusCode, + (UINT_8 *) (prCmd->aucSecBuf), + prCmd->u4SecBufLen) != TDLS_STATUS_SUCCESS) { + return -1; + } + + break; + + case TDLS_FRM_ACTION_SETUP_RSP: + + /* fix sigma bug 5.2.4.2, 5.2.4.7, we sent Status code decline, + * but the sigma recogniezis it as scucess, and it will fail + */ + /* if(prCmd->u2StatusCode != 0) */ + if (prBssInfo->fgTdlsIsProhibited) + return 0; + + /* printk("\n\n\n TDLS_FRM_ACTION_SETUP_RSP\n\n\n"); */ + if (TdlsDataFrameSend_SETUP_RSP(prAdapter, + prStaRec, + prCmd->aucPeer, + prCmd->ucActionCode, + prCmd->ucDialogToken, + prCmd->u2StatusCode, + (UINT_8 *) (prCmd->aucSecBuf), + prCmd->u4SecBufLen) != TDLS_STATUS_SUCCESS) { + return -1; + } + + break; + + case TDLS_FRM_ACTION_DISCOVERY_RSP: + /* printk("\n\n\n TDLS_FRM_ACTION_DISCOVERY_RSP\n\n\n"); */ + if (TdlsDataFrameSend_DISCOVERY_RSP(prAdapter, + prStaRec, + prCmd->aucPeer, + prCmd->ucActionCode, + prCmd->ucDialogToken, + prCmd->u2StatusCode, + (UINT_8 *) (prCmd->aucSecBuf), + prCmd->u4SecBufLen) != TDLS_STATUS_SUCCESS) { + return -1; + } + + break; + + case TDLS_FRM_ACTION_CONFIRM: + /* printk("\n\n\n TDLS_FRM_ACTION_CONFIRM\n\n\n"); */ + if (TdlsDataFrameSend_CONFIRM(prAdapter, + prStaRec, + prCmd->aucPeer, + prCmd->ucActionCode, + prCmd->ucDialogToken, + prCmd->u2StatusCode, + (UINT_8 *) (prCmd->aucSecBuf), + prCmd->u4SecBufLen) != TDLS_STATUS_SUCCESS) { + return -1; + } + break; + + case TDLS_FRM_ACTION_TEARDOWN: + + prStaRec = cnmGetTdlsPeerByAddress(prAdapter, prAdapter->prAisBssInfo->ucBssIndex, prCmd->aucPeer); + if (prCmd->u2StatusCode == TDLS_REASON_CODE_UNREACHABLE) { + /* printk("\n\n\n u2StatusCode == TDLS_REASON_CODE_UNREACHABLE\n\n\n"); */ + g_arTdlsLink[prStaRec->ucTdlsIndex] = 0; + } + /* printk("\n\n\n TDLS_FRM_ACTION_TEARDOWN\n\n\n"); */ + if (TdlsDataFrameSend_TearDown(prAdapter, + prStaRec, + prCmd->aucPeer, + prCmd->ucActionCode, + prCmd->ucDialogToken, + prCmd->u2StatusCode, + (UINT_8 *) (prCmd->aucSecBuf), + prCmd->u4SecBufLen) != TDLS_STATUS_SUCCESS) { + /* printk("\n teardown frrame send failure\n"); */ + return -1; + } + break; + + default: + /* printk("\n\n\n default\n\n\n"); */ + return -EINVAL; + } + + return 0; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to hadel TDLS link mgt from nl80211. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] +* \param[in] +* \param[in] buf includes RSN IE + FT IE + Lifetimeout IE +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 TdlsexLinkOper(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, PUINT_32 pu4SetInfoLen) +{ + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + UINT_16 i; + STA_RECORD_T *prStaRec; + + TDLS_CMD_LINK_OPER_T *prCmd; + + prCmd = (TDLS_CMD_LINK_OPER_T *) pvSetBuffer; + + DBGLOG(TDLS, INFO, "prCmd->oper=%d, u4SetBufferLen=%d", + prCmd->oper, u4SetBufferLen); + + switch (prCmd->oper) { + + case TDLS_ENABLE_LINK: + + for (i = 0; i < MAXNUM_TDLS_PEER; i++) { + if (!g_arTdlsLink[i]) { + g_arTdlsLink[i] = 1; + prStaRec = + cnmGetTdlsPeerByAddress(prAdapter, + prAdapter->prAisBssInfo->ucBssIndex, prCmd->aucPeerMac); + prStaRec->ucTdlsIndex = i; + break; + } + } + + /* printk("TDLS_ENABLE_LINK %d\n", i); */ + break; + case TDLS_DISABLE_LINK: + + prStaRec = cnmGetTdlsPeerByAddress(prAdapter, prAdapter->prAisBssInfo->ucBssIndex, prCmd->aucPeerMac); + + /* printk("TDLS_ENABLE_LINK %d\n", prStaRec->ucTdlsIndex); */ + g_arTdlsLink[prStaRec->ucTdlsIndex] = 0; + if (IS_DLS_STA(prStaRec)) + cnmStaRecFree(prAdapter, prStaRec); + + break; + default: + return 0; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to append general IEs. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] +* +* \retval append length +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 TdlsFrameGeneralIeAppend(ADAPTER_T *prAdapter, STA_RECORD_T *prStaRec, UINT_8 *pPkt) +{ + GLUE_INFO_T *prGlueInfo; + BSS_INFO_T *prBssInfo; + PM_PROFILE_SETUP_INFO_T *prPmProfSetupInfo; + UINT_32 u4NonHTPhyType; + UINT_16 u2SupportedRateSet; + UINT_8 aucAllSupportedRates[RATE_NUM_SW] = { 0 }; /* 6628 RATE_NUM -> 6630 RATE_NUM_SW */ + UINT_8 ucAllSupportedRatesLen; + UINT_8 ucSupRatesLen; + UINT_8 ucExtSupRatesLen; + UINT_32 u4PktLen, u4IeLen; + + /* init */ + prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; + prBssInfo = prAdapter->prAisBssInfo; /* AIS only */ + + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + + /* 3. Frame Formation - (5) Supported Rates element */ + /* use all sup rate we can support */ + u4NonHTPhyType = prStaRec->ucNonHTBasicPhyType; + u2SupportedRateSet = rNonHTPhyAttributes[u4NonHTPhyType].u2SupportedRateSet; + rateGetDataRatesFromRateSet(u2SupportedRateSet, 0, aucAllSupportedRates, &ucAllSupportedRatesLen); + + ucSupRatesLen = ((ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) ? + ELEM_MAX_LEN_SUP_RATES : ucAllSupportedRatesLen); + + ucExtSupRatesLen = ucAllSupportedRatesLen - ucSupRatesLen; + + if (ucSupRatesLen) { + SUP_RATES_IE(pPkt)->ucId = ELEM_ID_SUP_RATES; + SUP_RATES_IE(pPkt)->ucLength = ucSupRatesLen; + kalMemCopy(SUP_RATES_IE(pPkt)->aucSupportedRates, aucAllSupportedRates, ucSupRatesLen); + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + } + + /* 3. Frame Formation - (7) Extended sup rates element */ + if (ucExtSupRatesLen) { + + EXT_SUP_RATES_IE(pPkt)->ucId = ELEM_ID_EXTENDED_SUP_RATES; + EXT_SUP_RATES_IE(pPkt)->ucLength = ucExtSupRatesLen; + + kalMemCopy(EXT_SUP_RATES_IE(pPkt)->aucExtSupportedRates, + &aucAllSupportedRates[ucSupRatesLen], ucExtSupRatesLen); + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + } + + /* 3. Frame Formation - (8) Supported channels element */ + SUPPORTED_CHANNELS_IE(pPkt)->ucId = ELEM_ID_SUP_CHS; + SUPPORTED_CHANNELS_IE(pPkt)->ucLength = 2; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[0] = 1; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[1] = 13; + + if (prAdapter->fgEnable5GBand == TRUE) { + SUPPORTED_CHANNELS_IE(pPkt)->ucLength = 10; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[2] = 36; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[3] = 4; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[4] = 52; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[5] = 4; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[6] = 149; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[7] = 4; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[8] = 165; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[9] = 1; + } + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + + return u4PktLen; +} + + /******************************************************************************* + * P U B L I C F U N C T I O N S + ******************************************************************************** + */ + +/*! +* \brief This routine is called to transmit a TDLS data frame. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] +* \param[in] +* \param[in] buf includes RSN IE + FT IE + Lifetimeout IE +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +TdlsDataFrameSend_TearDown(ADAPTER_T *prAdapter, + STA_RECORD_T *prStaRec, + UINT_8 *pPeerMac, + UINT_8 ucActionCode, + UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen) +{ + + GLUE_INFO_T *prGlueInfo; + BSS_INFO_T *prBssInfo; + PM_PROFILE_SETUP_INFO_T *prPmProfSetupInfo; + struct sk_buff *prMsduInfo; + UINT_8 *pPkt; + UINT_32 u4PktLen, u4IeLen; + UINT_16 ReasonCode; + + /* allocate/init packet */ + prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; + prBssInfo = prAdapter->prAisBssInfo; /* AIS only */ + + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + + prMsduInfo = kalPacketAlloc(prGlueInfo, 512, &pPkt); + if (prMsduInfo == NULL) + return TDLS_STATUS_RESOURCES; + + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + kalPacketFree(prGlueInfo, prMsduInfo); + return TDLS_STATUS_FAIL; + } + + /* make up frame content */ + /* 1. 802.3 header */ + kalMemCopy(pPkt, pPeerMac, TDLS_FME_MAC_ADDR_LEN); + pPkt += TDLS_FME_MAC_ADDR_LEN; + kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); + pPkt += TDLS_FME_MAC_ADDR_LEN; + *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); + pPkt += 2; + u4PktLen += TDLS_FME_MAC_ADDR_LEN * 2 + 2; + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + pPkt++; + u4PktLen++; + + /* 3. Frame Formation - (1) Category */ + *pPkt = TDLS_FRM_CATEGORY; + pPkt++; + u4PktLen++; + + /* 3. Frame Formation - (2) Action */ + *pPkt = ucActionCode; + pPkt++; + u4PktLen++; + + /* 3. Frame Formation - status code */ + + ReasonCode = u2StatusCode; + + /* printk("\n\n ReasonCode = %u\n\n",ReasonCode ); */ + + kalMemCopy(pPkt, &ReasonCode, 2); + pPkt = pPkt + 2; + u4PktLen = u4PktLen + 2; + + if (pAppendIe != NULL) { + if ((ucActionCode != TDLS_FRM_ACTION_TEARDOWN) || + ((ucActionCode == TDLS_FRM_ACTION_TEARDOWN) && (prStaRec != NULL))) { + kalMemCopy(pPkt, pAppendIe, AppendIeLen); + LR_TDLS_FME_FIELD_FILL(AppendIeLen); + } + } + + /* 7. Append Supported Operating Classes IE */ + if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { + /* Note: if we do not put the IE, Marvell STA will decline our TDLS setup request */ + u4IeLen = rlmDomainSupOperatingClassIeFill(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } + + /* 3. Frame Formation - (16) Link identifier element */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, prAdapter->rMyMacAddr, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, pPeerMac, 6); + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + + /* 5. Update packet length */ + prMsduInfo->len = u4PktLen; + + /* if(u2StatusCode == UNREACH_ABLE ){ */ + /* g_arTdlsLink[prStaRec->ucTdlsIndex] = FALSE; */ + /* } */ + + /* printk(" TdlsDataFrameSend_TearDown !!\n"); */ + + /* 5. send the data frame */ + wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); + + return TDLS_STATUS_SUCCESS; +} + +/*! +* \brief This routine is called to transmit a TDLS data frame. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] +* \param[in] +* \param[in] buf includes RSN IE + FT IE + Lifetimeout IE +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS /* TDLS_STATUS */ +TdlsDataFrameSend_SETUP_REQ(ADAPTER_T *prAdapter, + STA_RECORD_T *prStaRec, + UINT_8 *pPeerMac, + UINT_8 ucActionCode, + UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen) +{ + + GLUE_INFO_T *prGlueInfo; + BSS_INFO_T *prBssInfo; + PM_PROFILE_SETUP_INFO_T *prPmProfSetupInfo; + struct sk_buff *prMsduInfo; + UINT_8 *pPkt; + UINT_32 u4PktLen, u4IeLen; + BOOLEAN fg40mAllowed; + UINT_16 u2CapInfo; + + /* allocate/init packet */ + prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; + prBssInfo = prAdapter->prAisBssInfo; /* AIS only */ + + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + + prMsduInfo = kalPacketAlloc(prGlueInfo, 512, &pPkt); + if (prMsduInfo == NULL) + return TDLS_STATUS_RESOURCES; + + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + kalPacketFree(prGlueInfo, prMsduInfo); + return TDLS_STATUS_FAIL; + } + + /* make up frame content */ + /* 1. 802.3 header */ + kalMemCopy(pPkt, pPeerMac, TDLS_FME_MAC_ADDR_LEN); + pPkt += TDLS_FME_MAC_ADDR_LEN; + kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); + pPkt += TDLS_FME_MAC_ADDR_LEN; + *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); + pPkt += 2; + u4PktLen += TDLS_FME_MAC_ADDR_LEN * 2 + 2; + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + pPkt++; + u4PktLen++; + + /* 3. Frame Formation - (1) Category */ + *pPkt = TDLS_FRM_CATEGORY; + pPkt++; + u4PktLen++; + + /* 3. Frame Formation - (2) Action */ + *pPkt = ucActionCode; + pPkt++; + u4PktLen++; + + /* 3. Frame Formation - (3) Dialog token */ + *pPkt = ucDialogToken; + pPkt++; + u4PktLen++; + + /* 3. Frame Formation - (4) Capability */ + u2CapInfo = assocBuildCapabilityInfo(prAdapter, prStaRec); + WLAN_SET_FIELD_16(pPkt, u2CapInfo); + pPkt = pPkt + 2; + u4PktLen = u4PktLen + 2; + + /* 4. Append general IEs */ + u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, prStaRec, pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + + /* 4. Append extra IEs */ + kalMemCopy(pPkt, pAppendIe, AppendIeLen); + pPkt += AppendIeLen; + u4PktLen += AppendIeLen; + + /* 3. Frame Formation - (10) Extended capabilities element */ + EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP; + EXT_CAP_IE(pPkt)->ucLength = 5; +/* 0320 !! */ + EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */ + EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */ + EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0xFF; /* bit32 ~ bit39 */ + + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24)); + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24)); + EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32)); + + /* EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; *//* bit24 ~ bit31 */ + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + + /* HT capability IE append 0122 */ + HT_CAP_IE(pPkt)->ucId = ELEM_ID_HT_CAP; + HT_CAP_IE(pPkt)->ucLength = 26; + + /* 3. Frame Formation - (14) HT capabilities element */ + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N)) { + /* TODO: prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode */ + if (cnmBss40mBwPermitted(prAdapter, prBssInfo->ucBssIndex)) + fg40mAllowed = TRUE; + else + fg40mAllowed = FALSE; + + /* Add HT IE *//* try to reuse p2p path */ + u4IeLen = rlmFillHtCapIEByAdapter(prAdapter, prBssInfo, pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + /* 0320 !! check newest driver !!! */ + } +/* check */ + + /* 3. Frame Formation - (12) Timeout interval element (TPK Key Lifetime) */ + TIMEOUT_INTERVAL_IE(pPkt)->ucId = ELEM_ID_TIMEOUT_INTERVAL; + TIMEOUT_INTERVAL_IE(pPkt)->ucLength = 5; + + TIMEOUT_INTERVAL_IE(pPkt)->ucType = 2; /* IE_TIMEOUT_INTERVAL_TYPE_KEY_LIFETIME; */ + TIMEOUT_INTERVAL_IE(pPkt)->u4Value = TDLS_KEY_TIMEOUT_INTERVAL; /* htonl(prCmd->u4Timeout); */ + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + + if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { + /* + * bit0 = 1: The Information Request field is used to indicate that a + * transmitting STA is requesting the recipient to transmit a 20/40 BSS + * Coexistence Management frame with the transmitting STA as the + * recipient. + * bit1 = 0: The Forty MHz Intolerant field is set to 1 to prohibit an AP + * that receives this information or reports of this information from + * operating a 20/40 MHz BSS. + * bit2 = 0: The 20 MHz BSS Width Request field is set to 1 to prohibit + * a receiving AP from operating its BSS as a 20/40 MHz BSS. + */ + BSS_20_40_COEXIST_IE(pPkt)->ucId = ELEM_ID_20_40_BSS_COEXISTENCE; + BSS_20_40_COEXIST_IE(pPkt)->ucLength = 1; + BSS_20_40_COEXIST_IE(pPkt)->ucData = 0x01; + LR_TDLS_FME_FIELD_FILL(3); + } + + if (pAppendIe != NULL) { + kalMemCopy(pPkt, pAppendIe, AppendIeLen); + LR_TDLS_FME_FIELD_FILL(AppendIeLen); + } + + /* 7. Append Supported Operating Classes IE */ + if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { + /* Note: if we do not put the IE, Marvell STA will decline our TDLS setup request */ + u4IeLen = rlmDomainSupOperatingClassIeFill(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } + + /* 3. Frame Formation - (16) Link identifier element */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, prAdapter->rMyMacAddr, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, pPeerMac, 6); + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + + /* 3. Frame Formation - (17) WMM Information element */ + + /* HT WMM IE append */ + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) { + + /* Add WMM IE *//* try to reuse p2p path */ + u4IeLen = mqmGenerateWmmInfoIEByStaRec(prAdapter, prBssInfo, prStaRec, pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + } + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) { + u4IeLen = mqmGenerateWmmParamIEByParam(prAdapter, prBssInfo, pPkt); + + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } +#if CFG_SUPPORT_802_11AC + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AC) { + /* Add VHT IE *//* try to reuse p2p path */ + u4IeLen = rlmFillVhtCapIEByAdapter(prAdapter, prBssInfo, pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + } +#endif + + /* 5. Update packet length */ + prMsduInfo->len = u4PktLen; + + DBGLOG(TDLS, INFO, "wlanHardStartXmit, u4PktLen=%d", u4PktLen); + + /* 5. send the data frame */ + wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); + /* wlanTx ??? */ + return TDLS_STATUS_SUCCESS; +} + +WLAN_STATUS +TdlsDataFrameSend_SETUP_RSP(ADAPTER_T *prAdapter, + STA_RECORD_T *prStaRec, + UINT_8 *pPeerMac, + UINT_8 ucActionCode, + UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen) +{ + + GLUE_INFO_T *prGlueInfo; + BSS_INFO_T *prBssInfo; + PM_PROFILE_SETUP_INFO_T *prPmProfSetupInfo; + struct sk_buff *prMsduInfo; + UINT_8 *pPkt; + UINT_32 u4PktLen, u4IeLen; + UINT_16 u2CapInfo; + UINT_16 StatusCode; + BOOLEAN fg40mAllowed; + + /* allocate/init packet */ + prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; + prBssInfo = prAdapter->prAisBssInfo; /* AIS only */ + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + + prMsduInfo = kalPacketAlloc(prGlueInfo, 512, &pPkt); + if (prMsduInfo == NULL) + return TDLS_STATUS_RESOURCES; + + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + kalPacketFree(prGlueInfo, prMsduInfo); + return TDLS_STATUS_FAIL; + } + + /* make up frame content */ + /* 1. 802.3 header */ + kalMemCopy(pPkt, pPeerMac, TDLS_FME_MAC_ADDR_LEN); + pPkt += TDLS_FME_MAC_ADDR_LEN; + kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); + pPkt += TDLS_FME_MAC_ADDR_LEN; + *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); + pPkt += 2; + u4PktLen += TDLS_FME_MAC_ADDR_LEN * 2 + 2; + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + pPkt++; + u4PktLen++; + + /* 3. Frame Formation - (1) Category */ + *pPkt = TDLS_FRM_CATEGORY; + pPkt++; + u4PktLen++; + + /* 3. Frame Formation - (2) Action */ + *pPkt = ucActionCode; + pPkt++; + u4PktLen++; + + /* 3. Frame Formation - status code */ + StatusCode = u2StatusCode; + kalMemCopy(pPkt, &StatusCode, 2); + pPkt = pPkt + 2; + u4PktLen = u4PktLen + 2; + + /* 3. Frame Formation - (3) Dialog token */ + *pPkt = ucDialogToken; + pPkt++; + u4PktLen++; + + /* 3. Frame Formation - (4) Capability */ + u2CapInfo = assocBuildCapabilityInfo(prAdapter, prStaRec); + WLAN_SET_FIELD_16(pPkt, u2CapInfo); + pPkt = pPkt + 2; + u4PktLen = u4PktLen + 2; + + /* 4. Append general IEs */ + u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, prStaRec, pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + + /* 4. Append extra IEs */ + kalMemCopy(pPkt, pAppendIe, AppendIeLen); + pPkt += AppendIeLen; + u4PktLen += AppendIeLen; + + /* 3. Frame Formation - (10) Extended capabilities element */ + EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP; + EXT_CAP_IE(pPkt)->ucLength = 5; + + EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */ + EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */ + EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0xFF; /* bit32 ~ bit39 */ + + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24)); + + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24)); + EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32)); + /* EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; *//* bit24 ~ bit31 */ + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + + /* HT capability IE append */ + HT_CAP_IE(pPkt)->ucId = ELEM_ID_HT_CAP; + HT_CAP_IE(pPkt)->ucLength = 26; + + /* 3. Frame Formation - (14) HT capabilities element */ + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N)) { + /* TODO: prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode */ + if (cnmBss40mBwPermitted(prAdapter, prBssInfo->ucBssIndex)) + fg40mAllowed = TRUE; + else + fg40mAllowed = FALSE; + + /* Add HT IE *//* try to reuse p2p path */ + u4IeLen = rlmFillHtCapIEByAdapter(prAdapter, prBssInfo, pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + } + + /* 3. Frame Formation - (12) Timeout interval element (TPK Key Lifetime) */ + TIMEOUT_INTERVAL_IE(pPkt)->ucId = ELEM_ID_TIMEOUT_INTERVAL; + TIMEOUT_INTERVAL_IE(pPkt)->ucLength = 5; + TIMEOUT_INTERVAL_IE(pPkt)->ucType = 2; /* IE_TIMEOUT_INTERVAL_TYPE_KEY_LIFETIME; */ + TIMEOUT_INTERVAL_IE(pPkt)->u4Value = TDLS_KEY_TIMEOUT_INTERVAL; /* htonl(prCmd->u4Timeout); */ + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + + if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { + /* + * bit0 = 1: The Information Request field is used to indicate that a + * transmitting STA is requesting the recipient to transmit a 20/40 BSS + * Coexistence Management frame with the transmitting STA as the + * recipient. + * bit1 = 0: The Forty MHz Intolerant field is set to 1 to prohibit an AP + * that receives this information or reports of this information from + * operating a 20/40 MHz BSS. + * bit2 = 0: The 20 MHz BSS Width Request field is set to 1 to prohibit + * a receiving AP from operating its BSS as a 20/40 MHz BSS. + */ + BSS_20_40_COEXIST_IE(pPkt)->ucId = ELEM_ID_20_40_BSS_COEXISTENCE; + BSS_20_40_COEXIST_IE(pPkt)->ucLength = 1; + BSS_20_40_COEXIST_IE(pPkt)->ucData = 0x01; + LR_TDLS_FME_FIELD_FILL(3); + } + + if (pAppendIe != NULL) { + if ((ucActionCode != TDLS_FRM_ACTION_TEARDOWN) || + ((ucActionCode == TDLS_FRM_ACTION_TEARDOWN))) { + kalMemCopy(pPkt, pAppendIe, AppendIeLen); + LR_TDLS_FME_FIELD_FILL(AppendIeLen); + } + } + + /* 7. Append Supported Operating Classes IE */ + if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { + /* Note: if we do not put the IE, Marvell STA will decline our TDLS setup request */ + u4IeLen = rlmDomainSupOperatingClassIeFill(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } + + /* 3. Frame Formation - (16) Link identifier element */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, pPeerMac, 6); /* prAdapter->rMyMacAddr */ + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prAdapter->rMyMacAddr, 6); /* pPeerMac */ + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + + /* HT WMM IE append */ + /* HT WMM IE append */ + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) { + + /* Add WMM IE *//* try to reuse p2p path */ + u4IeLen = mqmGenerateWmmInfoIEByStaRec(prAdapter, prBssInfo, prStaRec, pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + } + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) { + u4IeLen = mqmGenerateWmmParamIEByParam(prAdapter, prBssInfo, pPkt); + + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } +#if CFG_SUPPORT_802_11AC + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AC) { + /* Add VHT IE *//* try to reuse p2p path */ + u4IeLen = rlmFillVhtCapIEByAdapter(prAdapter, prBssInfo, pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + } +#endif + + /* 5. Update packet length */ + prMsduInfo->len = u4PktLen; + + /* 5. send the data frame */ + wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); + + return TDLS_STATUS_SUCCESS; +} + +WLAN_STATUS +TdlsDataFrameSend_CONFIRM(ADAPTER_T *prAdapter, + STA_RECORD_T *prStaRec, + UINT_8 *pPeerMac, + UINT_8 ucActionCode, + UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen) +{ + + GLUE_INFO_T *prGlueInfo; + BSS_INFO_T *prBssInfo; + PM_PROFILE_SETUP_INFO_T *prPmProfSetupInfo; + struct sk_buff *prMsduInfo; + UINT_8 *pPkt; + UINT_32 u4PktLen, u4IeLen; + UINT_16 StatusCode; + + /* allocate/init packet */ + prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; + prBssInfo = prAdapter->prAisBssInfo; /* AIS only */ + + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + + prMsduInfo = kalPacketAlloc(prGlueInfo, 512, &pPkt); + if (prMsduInfo == NULL) + return TDLS_STATUS_RESOURCES; + + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + kalPacketFree(prGlueInfo, prMsduInfo); + return TDLS_STATUS_FAIL; + } + + /* make up frame content */ + /* 1. 802.3 header */ + kalMemCopy(pPkt, pPeerMac, TDLS_FME_MAC_ADDR_LEN); + pPkt += TDLS_FME_MAC_ADDR_LEN; + kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); + pPkt += TDLS_FME_MAC_ADDR_LEN; + *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); + pPkt += 2; + u4PktLen += TDLS_FME_MAC_ADDR_LEN * 2 + 2; + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + pPkt++; + u4PktLen++; + + /* 3. Frame Formation - (1) Category */ + *pPkt = TDLS_FRM_CATEGORY; + pPkt++; + u4PktLen++; + + /* 3. Frame Formation - (2) Action */ + *pPkt = ucActionCode; + pPkt++; + u4PktLen++; + + /* 3. Frame Formation - status code */ + + StatusCode = u2StatusCode; /* 0; //u2StatusCode; //ahiu 0224 */ + kalMemCopy(pPkt, &StatusCode, 2); + pPkt = pPkt + 2; + u4PktLen = u4PktLen + 2; + + /* 3. Frame Formation - (3) Dialog token */ + *pPkt = ucDialogToken; + pPkt++; + u4PktLen++; + + /* 4. Append extra IEs */ + kalMemCopy(pPkt, pAppendIe, AppendIeLen); + pPkt += AppendIeLen; + u4PktLen += AppendIeLen; + + /* 3. Frame Formation - (12) Timeout interval element (TPK Key Lifetime) */ + TIMEOUT_INTERVAL_IE(pPkt)->ucId = ELEM_ID_TIMEOUT_INTERVAL; + TIMEOUT_INTERVAL_IE(pPkt)->ucLength = 5; + + TIMEOUT_INTERVAL_IE(pPkt)->ucType = 2; + TIMEOUT_INTERVAL_IE(pPkt)->u4Value = TDLS_KEY_TIMEOUT_INTERVAL; /* htonl(prCmd->u4Timeout); */ + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + + if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { + /* + * bit0 = 1: The Information Request field is used to indicate that a + * transmitting STA is requesting the recipient to transmit a 20/40 BSS + * Coexistence Management frame with the transmitting STA as the + * recipient. + * bit1 = 0: The Forty MHz Intolerant field is set to 1 to prohibit an AP + * that receives this information or reports of this information from + * operating a 20/40 MHz BSS. + * bit2 = 0: The 20 MHz BSS Width Request field is set to 1 to prohibit + * a receiving AP from operating its BSS as a 20/40 MHz BSS. + */ + BSS_20_40_COEXIST_IE(pPkt)->ucId = ELEM_ID_20_40_BSS_COEXISTENCE; + BSS_20_40_COEXIST_IE(pPkt)->ucLength = 1; + BSS_20_40_COEXIST_IE(pPkt)->ucData = 0x01; + LR_TDLS_FME_FIELD_FILL(3); + } + + if (pAppendIe != NULL) { + if ((ucActionCode != TDLS_FRM_ACTION_TEARDOWN) || + ((ucActionCode == TDLS_FRM_ACTION_TEARDOWN) && (prStaRec != NULL))) { + kalMemCopy(pPkt, pAppendIe, AppendIeLen); + LR_TDLS_FME_FIELD_FILL(AppendIeLen); + } + } + + /* 7. Append Supported Operating Classes IE */ + if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { + /* Note: if we do not put the IE, Marvell STA will decline our TDLS setup request */ + u4IeLen = rlmDomainSupOperatingClassIeFill(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } + + /* 3. Frame Formation - (16) Link identifier element */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, prAdapter->rMyMacAddr, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, pPeerMac, 6); + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + + /* HT WMM IE append */ + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) { + + /* Add WMM IE *//* try to reuse p2p path */ + u4IeLen = mqmGenerateWmmInfoIEByStaRec(prAdapter, prBssInfo, prStaRec, pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + } + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) { + u4IeLen = mqmGenerateWmmParamIEByParam(prAdapter, prBssInfo, pPkt); + + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } + + /* 5. Update packet length */ + prMsduInfo->len = u4PktLen; + + /* 5. send the data frame */ + wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); + + return TDLS_STATUS_SUCCESS; +} + +/* +* \brief This routine is called to transmit a TDLS data frame. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] +* \param[in] +* \param[in] buf includes RSN IE + FT IE + Lifetimeout IE +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS /* TDLS_STATUS */ +TdlsDataFrameSend_DISCOVERY_REQ(ADAPTER_T *prAdapter, + STA_RECORD_T *prStaRec, + UINT_8 *pPeerMac, + UINT_8 ucActionCode, + UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen) +{ + GLUE_INFO_T *prGlueInfo; + BSS_INFO_T *prBssInfo; + PM_PROFILE_SETUP_INFO_T *prPmProfSetupInfo; + struct sk_buff *prMsduInfo; + MSDU_INFO_T *prMsduInfoMgmt; + UINT_8 *pPkt, *pucInitiator, *pucResponder; + UINT_32 u4PktLen, u4IeLen; + UINT_16 u2CapInfo; + + prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; + + if (prStaRec != NULL) + prBssInfo = prAdapter->prAisBssInfo; /* AIS only */ + else + return TDLS_STATUS_FAIL; + + /* allocate/init packet */ + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + prMsduInfo = NULL; + prMsduInfoMgmt = NULL; + + /* make up frame content */ + if (ucActionCode != TDLS_FRM_ACTION_DISCOVERY_RSP) { + /* TODO: reduce 1600 to correct size */ + prMsduInfo = kalPacketAlloc(prGlueInfo, 512, &pPkt); + if (prMsduInfo == NULL) + return TDLS_STATUS_RESOURCES; + + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + + kalPacketFree(prGlueInfo, prMsduInfo); + return TDLS_STATUS_FAIL; + } + + /* 1. 802.3 header */ + kalMemCopy(pPkt, pPeerMac, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(pPkt, prBssInfo->aucOwnMacAddr, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); + LR_TDLS_FME_FIELD_FILL(2); + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (1) Category */ + *pPkt = TDLS_FRM_CATEGORY; + LR_TDLS_FME_FIELD_FILL(1); + } else { + WLAN_MAC_HEADER_T *prHdr; + + prMsduInfoMgmt = (MSDU_INFO_T *) + cnmMgtPktAlloc(prAdapter, PUBLIC_ACTION_MAX_LEN); + if (prMsduInfoMgmt == NULL) + return TDLS_STATUS_RESOURCES; + + pPkt = (UINT_8 *) prMsduInfoMgmt->prPacket; + prHdr = (WLAN_MAC_HEADER_T *) pPkt; + + /* 1. 802.11 header */ + prHdr->u2FrameCtrl = MAC_FRAME_ACTION; + prHdr->u2DurationID = 0; + kalMemCopy(prHdr->aucAddr1, pPeerMac, TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(prHdr->aucAddr2, prBssInfo->aucOwnMacAddr, TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(prHdr->aucAddr3, prBssInfo->aucBSSID, TDLS_FME_MAC_ADDR_LEN); + prHdr->u2SeqCtrl = 0; + LR_TDLS_FME_FIELD_FILL(sizeof(WLAN_MAC_HEADER_T)); + + /* Frame Formation - (1) Category */ + *pPkt = CATEGORY_PUBLIC_ACTION; + LR_TDLS_FME_FIELD_FILL(1); + } + + /* 3. Frame Formation - (2) Action */ + *pPkt = ucActionCode; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - Status Code */ + switch (ucActionCode) { + case TDLS_FRM_ACTION_SETUP_RSP: + case TDLS_FRM_ACTION_CONFIRM: + case TDLS_FRM_ACTION_TEARDOWN: + WLAN_SET_FIELD_16(pPkt, u2StatusCode); + LR_TDLS_FME_FIELD_FILL(2); + break; + } + + /* 3. Frame Formation - (3) Dialog token */ + if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { + *pPkt = ucDialogToken; + LR_TDLS_FME_FIELD_FILL(1); + } + + /* Fill elements */ + if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { + /* + * Capability + * Support Rates + * Extended Support Rates + * Supported Channels + * HT Capabilities + * WMM Information Element + * Extended Capabilities + * Link Identifier + * RSNIE + * FTIE + * Timeout Interval + */ + + if (ucActionCode != TDLS_FRM_ACTION_CONFIRM && ucActionCode != TDLS_FRM_ACTION_DISCOVERY_REQ) { + /* 3. Frame Formation - (4) Capability: 0x31 0x04, privacy bit will be set */ + u2CapInfo = assocBuildCapabilityInfo(prAdapter, prStaRec); + WLAN_SET_FIELD_16(pPkt, u2CapInfo); + LR_TDLS_FME_FIELD_FILL(2); + } + + if (ucActionCode != TDLS_FRM_ACTION_CONFIRM) { + /* 4. Append general IEs */ + /* + * TODO check HT: prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode + * must be CONFIG_BW_20_40M. + * TODO check HT: HT_CAP_INFO_40M_INTOLERANT must be clear if + * Tdls 20/40 is enabled. + */ + u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, prStaRec, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 5. Frame Formation - Extended capabilities element */ + EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP; + EXT_CAP_IE(pPkt)->ucLength = 5; + + EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */ + EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */ + EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */ + + /* if (prCmd->ucExCap & TDLS_EX_CAP_PEER_UAPSD) */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24)); + /* if (prCmd->ucExCap & TDLS_EX_CAP_CHAN_SWITCH) */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24)); + /* if (prCmd->ucExCap & TDLS_EX_CAP_TDLS) */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32)); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } else { + /* 5. Frame Formation - WMM Information element */ + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) { + + /* Add WMM IE *//* try to reuse p2p path */ + u4IeLen = mqmGenerateWmmInfoIEByStaRec(prAdapter, prBssInfo, prStaRec, pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + } + + } + } + + /* 6. Frame Formation - 20/40 BSS Coexistence */ + /* + * Follow WiFi test plan, add 20/40 element to request/response/confirm. + */ +#if 0 + if (prGlueInfo->fgTdlsIs2040Supported == TRUE) { + /* + * bit0 = 1: The Information Request field is used to indicate that a + * transmitting STA is requesting the recipient to transmit a 20/40 BSS + * Coexistence Management frame with the transmitting STA as the + * recipient. + * bit1 = 0: The Forty MHz Intolerant field is set to 1 to prohibit an AP + * that receives this information or reports of this information from + * operating a 20/40 MHz BSS. + * bit2 = 0: The 20 MHz BSS Width Request field is set to 1 to prohibit + * a receiving AP from operating its BSS as a 20/40 MHz BSS. + */ + BSS_20_40_COEXIST_IE(pPkt)->ucId = ELEM_ID_20_40_BSS_COEXISTENCE; + BSS_20_40_COEXIST_IE(pPkt)->ucLength = 1; + BSS_20_40_COEXIST_IE(pPkt)->ucData = 0x01; + LR_TDLS_FME_FIELD_FILL(3); + } +#endif + /* 6. Frame Formation - HT Operation element */ + /* u4IeLen = rlmFillHtOpIeBody(prBssInfo, pPkt); */ + /* LR_TDLS_FME_FIELD_FILL(u4IeLen); */ + + /* 7. Frame Formation - Link identifier element */ + /* Note: Link ID sequence must be correct; Or the calculated MIC will be error */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); + + switch (ucActionCode) { + case TDLS_FRM_ACTION_SETUP_REQ: + case TDLS_FRM_ACTION_CONFIRM: + case TDLS_FRM_ACTION_DISCOVERY_RSP: + default: + /* we are initiator */ + pucInitiator = prBssInfo->aucOwnMacAddr; + pucResponder = pPeerMac; + prStaRec->flgTdlsIsInitiator = TRUE; + break; + + case TDLS_FRM_ACTION_SETUP_RSP: + /* peer is initiator */ + pucInitiator = pPeerMac; + pucResponder = prBssInfo->aucOwnMacAddr; + prStaRec->flgTdlsIsInitiator = FALSE; + break; + + case TDLS_FRM_ACTION_TEARDOWN: + if (prStaRec->flgTdlsIsInitiator == TRUE) { + /* we are initiator */ + pucInitiator = prBssInfo->aucOwnMacAddr; + pucResponder = pPeerMac; + } else { + /* peer is initiator */ + pucInitiator = pPeerMac; + pucResponder = prBssInfo->aucOwnMacAddr; + } + break; + } + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, pucInitiator, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, pucResponder, 6); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 8. Append security IEs */ + if ((ucActionCode != TDLS_FRM_ACTION_TEARDOWN) && (pAppendIe != NULL)) { + kalMemCopy(pPkt, pAppendIe, AppendIeLen); + LR_TDLS_FME_FIELD_FILL(AppendIeLen); + } + + /* 10. send the data or management frame */ + if (ucActionCode != TDLS_FRM_ACTION_DISCOVERY_RSP) { + /* 9. Update packet length */ + prMsduInfo->len = u4PktLen; + + wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); + } else { + prMsduInfoMgmt->ucPacketType = TX_PACKET_TYPE_MGMT; + prMsduInfoMgmt->ucStaRecIndex = prBssInfo->prStaRecOfAP->ucIndex; + prMsduInfoMgmt->ucBssIndex = prBssInfo->ucBssIndex; + prMsduInfoMgmt->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfoMgmt->fgIs802_1x = FALSE; + prMsduInfoMgmt->fgIs802_11 = TRUE; + prMsduInfoMgmt->u2FrameLength = u4PktLen; + prMsduInfoMgmt->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfoMgmt->pfTxDoneHandler = NULL; + + /* Send them to HW queue */ + nicTxEnqueueMsdu(prAdapter, prMsduInfoMgmt); + } + + return TDLS_STATUS_SUCCESS; +} + +WLAN_STATUS +TdlsDataFrameSend_DISCOVERY_RSP(ADAPTER_T *prAdapter, + STA_RECORD_T *prStaRec, + UINT_8 *pPeerMac, + UINT_8 ucActionCode, + UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen) +{ + GLUE_INFO_T *prGlueInfo; + BSS_INFO_T *prBssInfo; + PM_PROFILE_SETUP_INFO_T *prPmProfSetupInfo; + struct sk_buff *prMsduInfo; + MSDU_INFO_T *prMsduInfoMgmt; + UINT_8 *pPkt, *pucInitiator, *pucResponder; + UINT_32 u4PktLen, u4IeLen; + UINT_16 u2CapInfo; + WLAN_MAC_HEADER_T *prHdr; + + prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; + + /* sanity check */ + if (prStaRec != NULL) + prBssInfo = prAdapter->prAisBssInfo; /* AIS only */ + else + return TDLS_STATUS_FAIL; + + /* allocate/init packet */ + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + prMsduInfo = NULL; + prMsduInfoMgmt = NULL; + + /* make up frame content */ + prMsduInfoMgmt = (MSDU_INFO_T *) + cnmMgtPktAlloc(prAdapter, PUBLIC_ACTION_MAX_LEN); + if (prMsduInfoMgmt == NULL) { + DBGLOG(TDLS, ERROR, "cnmMgtPktAlloc for prMsduInfoMgmt failed!\n"); + return TDLS_STATUS_RESOURCES; + } + + pPkt = (UINT_8 *) prMsduInfoMgmt->prPacket; + prHdr = (WLAN_MAC_HEADER_T *) pPkt; + + /* 1. 802.11 header */ + prHdr->u2FrameCtrl = MAC_FRAME_ACTION; + prHdr->u2DurationID = 0; + kalMemCopy(prHdr->aucAddr1, pPeerMac, TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(prHdr->aucAddr2, prBssInfo->aucOwnMacAddr, TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(prHdr->aucAddr3, prBssInfo->aucBSSID, TDLS_FME_MAC_ADDR_LEN); + prHdr->u2SeqCtrl = 0; + LR_TDLS_FME_FIELD_FILL(sizeof(WLAN_MAC_HEADER_T)); + + /* Frame Formation - (1) Category */ + *pPkt = CATEGORY_PUBLIC_ACTION; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (2) Action */ + *pPkt = ucActionCode; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (3) Dialog token */ + *pPkt = ucDialogToken; + LR_TDLS_FME_FIELD_FILL(1); + + /* Fill elements */ + /* + * Capability + * Support Rates + * Extended Support Rates + * Supported Channels + * HT Capabilities + * WMM Information Element + * Extended Capabilities + * Link Identifier + * RSNIE + * FTIE + * Timeout Interval + */ + /* 3. Frame Formation - (4) Capability: 0x31 0x04, privacy bit will be set */ + u2CapInfo = assocBuildCapabilityInfo(prAdapter, prStaRec); + WLAN_SET_FIELD_16(pPkt, u2CapInfo); + LR_TDLS_FME_FIELD_FILL(2); + + /* 4. Append general IEs */ + /* + * TODO check HT: prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode + * must be CONFIG_BW_20_40M. + * TODO check HT: HT_CAP_INFO_40M_INTOLERANT must be clear if + * Tdls 20/40 is enabled. + */ + u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, prStaRec, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 5. Frame Formation - Extended capabilities element */ + EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP; + EXT_CAP_IE(pPkt)->ucLength = 5; + + EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */ + EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */ + EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */ + + /* if (prCmd->ucExCap & TDLS_EX_CAP_PEER_UAPSD) */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24)); + /* if (prCmd->ucExCap & TDLS_EX_CAP_CHAN_SWITCH) */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24)); + /* if (prCmd->ucExCap & TDLS_EX_CAP_TDLS) */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32)); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + + /* 6. Frame Formation - 20/40 BSS Coexistence */ + /* + * Follow WiFi test plan, add 20/40 element to request/response/confirm. + */ +#if 0 + if (prGlueInfo->fgTdlsIs2040Supported == TRUE) { + /* + * bit0 = 1: The Information Request field is used to indicate that a + * transmitting STA is requesting the recipient to transmit a 20/40 BSS + * Coexistence Management frame with the transmitting STA as the + * recipient. + * bit1 = 0: The Forty MHz Intolerant field is set to 1 to prohibit an AP + * that receives this information or reports of this information from + * operating a 20/40 MHz BSS. + * bit2 = 0: The 20 MHz BSS Width Request field is set to 1 to prohibit + * a receiving AP from operating its BSS as a 20/40 MHz BSS. + */ + BSS_20_40_COEXIST_IE(pPkt)->ucId = ELEM_ID_20_40_BSS_COEXISTENCE; + BSS_20_40_COEXIST_IE(pPkt)->ucLength = 1; + BSS_20_40_COEXIST_IE(pPkt)->ucData = 0x01; + LR_TDLS_FME_FIELD_FILL(3); + } +#endif + /* 6. Frame Formation - HT Operation element */ + /* u4IeLen = rlmFillHtOpIeBody(prBssInfo, pPkt); */ + /* LR_TDLS_FME_FIELD_FILL(u4IeLen); */ + + /* 7. Frame Formation - Link identifier element */ + /* Note: Link ID sequence must be correct; Or the calculated MIC will be error */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); + + + + /* peer is initiator */ + pucInitiator = pPeerMac; + pucResponder = prBssInfo->aucOwnMacAddr; + + if (prStaRec != NULL) + prStaRec->flgTdlsIsInitiator = FALSE; + + + /* 3. Frame Formation - (12) Timeout interval element (TPK Key Lifetime) */ + TIMEOUT_INTERVAL_IE(pPkt)->ucId = ELEM_ID_TIMEOUT_INTERVAL; + TIMEOUT_INTERVAL_IE(pPkt)->ucLength = 5; + TIMEOUT_INTERVAL_IE(pPkt)->ucType = 2; /* IE_TIMEOUT_INTERVAL_TYPE_KEY_LIFETIME; */ + TIMEOUT_INTERVAL_IE(pPkt)->u4Value = TDLS_KEY_TIMEOUT_INTERVAL; /* htonl(prCmd->u4Timeout); */ + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + + + /* + * bit0 = 1: The Information Request field is used to indicate that a + * transmitting STA is requesting the recipient to transmit a 20/40 BSS + * Coexistence Management frame with the transmitting STA as the + * recipient. + * bit1 = 0: The Forty MHz Intolerant field is set to 1 to prohibit an AP + * that receives this information or reports of this information from + * operating a 20/40 MHz BSS. + * bit2 = 0: The 20 MHz BSS Width Request field is set to 1 to prohibit + * a receiving AP from operating its BSS as a 20/40 MHz BSS. + */ + BSS_20_40_COEXIST_IE(pPkt)->ucId = ELEM_ID_20_40_BSS_COEXISTENCE; + BSS_20_40_COEXIST_IE(pPkt)->ucLength = 1; + BSS_20_40_COEXIST_IE(pPkt)->ucData = 0x01; + LR_TDLS_FME_FIELD_FILL(3); + + if (pAppendIe != NULL) { + + kalMemCopy(pPkt, pAppendIe, AppendIeLen); + LR_TDLS_FME_FIELD_FILL(AppendIeLen); + + } + + /* 7. Append Supported Operating Classes IE */ + /* Note: if we do not put the IE, Marvell STA will decline our TDLS setup request */ + u4IeLen = rlmDomainSupOperatingClassIeFill(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + + /* 3. Frame Formation - (16) Link identifier element */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, pPeerMac, 6); /* prAdapter->rMyMacAddr */ + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prAdapter->rMyMacAddr, 6); /* pPeerMac */ + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + + /* HT WMM IE append */ + /* HT WMM IE append */ + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) { + + /* Add WMM IE *//* try to reuse p2p path */ + u4IeLen = mqmGenerateWmmInfoIEByStaRec(prAdapter, prBssInfo, prStaRec, pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + } + + if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) { + u4IeLen = mqmGenerateWmmParamIEByParam(prAdapter, prBssInfo, pPkt); + + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } +#if CFG_SUPPORT_802_11AC + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AC) { + /* Add VHT IE *//* try to reuse p2p path */ + u4IeLen = rlmFillVhtCapIEByAdapter(prAdapter, prBssInfo, pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + } +#endif + + /* 8. Append security IEs */ + if (pAppendIe != NULL) { + kalMemCopy(pPkt, pAppendIe, AppendIeLen); + LR_TDLS_FME_FIELD_FILL(AppendIeLen); + } + + prMsduInfoMgmt->ucPacketType = TX_PACKET_TYPE_MGMT; + prMsduInfoMgmt->ucStaRecIndex = prBssInfo->prStaRecOfAP->ucIndex; + prMsduInfoMgmt->ucBssIndex = prBssInfo->ucBssIndex; + prMsduInfoMgmt->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfoMgmt->fgIs802_1x = FALSE; + prMsduInfoMgmt->fgIs802_11 = TRUE; + prMsduInfoMgmt->u2FrameLength = u4PktLen; + prMsduInfoMgmt->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfoMgmt->pfTxDoneHandler = NULL; + + /* Send them to HW queue */ + nicTxEnqueueMsdu(prAdapter, prMsduInfoMgmt); + + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to send a command to TDLS module. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID TdlsexEventHandle(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + UINT_32 u4EventId; + + DBGLOG(TDLS, INFO, "TdlsexEventHandle\n"); + + /* sanity check */ + if ((prGlueInfo == NULL) || (prInBuf == NULL)) + return; /* shall not be here */ + + /* handle */ + u4EventId = *(UINT_32 *) prInBuf; + u4InBufLen -= 4; + + switch (u4EventId) { + case TDLS_HOST_EVENT_TEAR_DOWN: + DBGLOG(TDLS, INFO, "TDLS_HOST_EVENT_TEAR_DOWN\n"); + TdlsEventTearDown(prGlueInfo, prInBuf + 4, u4InBufLen); + break; + + case TDLS_HOST_EVENT_TX_DONE: + + break; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to do tear down. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +*/ +/*----------------------------------------------------------------------------*/ +VOID TdlsEventTearDown(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + STA_RECORD_T *prStaRec; + UINT_16 u2ReasonCode; + UINT_32 u4TearDownSubId; + UINT_8 *pMac, aucZeroMac[6]; + + /* init */ + u4TearDownSubId = *(UINT_32 *) prInBuf; + kalMemZero(aucZeroMac, sizeof(aucZeroMac)); + pMac = aucZeroMac; + + prStaRec = cnmGetStaRecByIndex(prGlueInfo->prAdapter, *(prInBuf + 4)); + if (prStaRec != NULL) + pMac = prStaRec->aucMacAddr; + + /* handle */ + + /* sanity check */ + if (prStaRec == NULL) + return; + + if (fgIsPtiTimeoutSkip == TRUE) { + /* skip PTI timeout event */ + if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_TIMEOUT) + return; + } + + if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_TIMEOUT) { + DBGLOG(TDLS, INFO, "TDLS_HOST_EVENT_TD_PTI_TIMEOUT TDLS_REASON_CODE_UNSPECIFIED\n"); + u2ReasonCode = TDLS_REASON_CODE_UNSPECIFIED; + + cfg80211_tdls_oper_request(prGlueInfo->prDevHandler, + prStaRec->aucMacAddr, NL80211_TDLS_TEARDOWN, + WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE, GFP_ATOMIC); + } + + if (u4TearDownSubId == TDLS_HOST_EVENT_TD_AGE_TIMEOUT) { + DBGLOG(TDLS, INFO, "TDLS_HOST_EVENT_TD_AGE_TIMEOUT TDLS_REASON_CODE_UNREACHABLE\n"); + u2ReasonCode = TDLS_REASON_CODE_UNREACHABLE; + + cfg80211_tdls_oper_request(prGlueInfo->prDevHandler, + prStaRec->aucMacAddr, NL80211_TDLS_TEARDOWN, + WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE, GFP_ATOMIC); + + } + + + /* + * modify the value when supplicant sends tear down to us in TdlsexMgmtCtrl(), not here + * we want to send tear down to AP (not peer) if PTI timeout or AGE timeout. + */ + + /* 16 Nov 21:49 2012 http://permalink.gmane.org/gmane.linux.kernel.wireless.general/99712 */ + +} + +#if 0 + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to send a TDLS event to supplicant. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +*/ +/*----------------------------------------------------------------------------*/ +VOID tdls_oper_request(struct net_device *dev, const u8 *peer, u16 oper, u16 reason_code, gfp_t gfp) +{ + GLUE_INFO_T *prGlueInfo; + ADAPTER_T *prAdapter; + struct sk_buff *prMsduInfo; + UINT_8 *pPkt; + UINT_32 u4PktLen; + + /* sanity check */ + if ((dev == NULL) || (peer == NULL)) + return; /* shall not be here */ + + /* init */ + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(dev)); + prAdapter = prGlueInfo->prAdapter; + u4PktLen = 0; + + /* allocate/init packet */ + prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); + if (prMsduInfo == NULL) + return; + prMsduInfo->dev = dev; + + /* make up frame content */ + /* 1. 802.3 header */ + kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(pPkt, peer, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); + LR_TDLS_FME_FIELD_FILL(2); + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (1) Category */ + *pPkt = TDLS_FRM_CATEGORY; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (2) Action */ + *pPkt = TDLS_FRM_ACTION_EVENT_TEAR_DOWN_TO_SUPPLICANT; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (3) Operation */ + *pPkt = oper; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (4) Reason Code */ + *pPkt = reason_code; + *(pPkt + 1) = 0x00; + LR_TDLS_FME_FIELD_FILL(2); + + /* 3. Frame Formation - (5) Peer MAC */ + kalMemCopy(pPkt, peer, 6); + LR_TDLS_FME_FIELD_FILL(6); + + /* 4. Update packet length */ + prMsduInfo->len = u4PktLen; + + /* pass to OS */ + TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to indicate packets to upper layer. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prSkb A pointer to the received packet +* +* \retval None +* +*/ +/*----------------------------------------------------------------------------*/ +VOID TdlsCmdTestRxIndicatePkts(GLUE_INFO_T *prGlueInfo, struct sk_buff *prSkb) +{ + struct net_device *prNetDev; + + /* init */ + prNetDev = prGlueInfo->prDevHandler; + prGlueInfo->rNetDevStats.rx_bytes += prSkb->len; + prGlueInfo->rNetDevStats.rx_packets++; + + /* pass to upper layer */ + prNetDev->last_rx = jiffies; + prSkb->protocol = eth_type_trans(prSkb, prNetDev); + prSkb->dev = prNetDev; + + if (!in_interrupt()) + netif_rx_ni(prSkb); /* only in non-interrupt context */ + else + netif_rx(prSkb); +} +#endif + +VOID TdlsBssExtCapParse(P_STA_RECORD_T prStaRec, P_UINT_8 pucIE) +{ + UINT_8 *pucIeExtCap; + + /* sanity check */ + if ((prStaRec == NULL) || (pucIE == NULL)) + return; + + if (IE_ID(pucIE) != ELEM_ID_EXTENDED_CAP) + return; + + /* + * from bit0 ~ + * bit 38: TDLS Prohibited + * The TDLS Prohibited subfield indicates whether the use of TDLS is prohibited. The + * field is set to 1 to indicate that TDLS is prohibited and to 0 to indicate that TDLS is + * allowed. + */ + if (IE_LEN(pucIE) < 5) + return; /* we need 39/8 = 5 bytes */ + + /* init */ + prStaRec->fgTdlsIsProhibited = FALSE; + prStaRec->fgTdlsIsChSwProhibited = FALSE; + + /* parse */ + pucIeExtCap = pucIE + 2; + pucIeExtCap += 4; /* shift to the byte we care about */ + + if ((*pucIeExtCap) & BIT(38 - 32)) + prStaRec->fgTdlsIsProhibited = TRUE; + if ((*pucIeExtCap) & BIT(39 - 32)) + prStaRec->fgTdlsIsChSwProhibited = TRUE; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Generate CMD_ID_SET_TDLS_CH_SW command +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +TdlsSendChSwControlCmd(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, PUINT_32 pu4SetInfoLen) +{ + + CMD_TDLS_CH_SW_T rCmdTdlsChSwCtrl; + + ASSERT(prAdapter); + + /* send command packet for scan */ + kalMemZero(&rCmdTdlsChSwCtrl, sizeof(CMD_TDLS_CH_SW_T)); + + rCmdTdlsChSwCtrl.fgIsTDLSChSwProhibit = prAdapter->prAisBssInfo->fgTdlsIsChSwProhibited; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_TDLS_CH_SW, + TRUE, + FALSE, FALSE, NULL, NULL, sizeof(CMD_TDLS_CH_SW_T), (PUINT_8)&rCmdTdlsChSwCtrl, NULL, 0); + return TDLS_STATUS_SUCCESS; +} + +WLAN_STATUS +TdlsTxCtrl(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, BOOLEAN fgEnable) +{ + int i; + P_STA_RECORD_T prStaRec; + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + + if (prStaRec->eStaType != STA_TYPE_DLS_PEER) + continue; + + if (prStaRec->fgIsInUse && prStaRec->ucBssIndex == prBssInfo->ucBssIndex) { + qmSetStaRecTxAllowed(prAdapter, prStaRec, fgEnable); + DBGLOG(TDLS, EVENT, "TDLS STA[%d], TX ctrl=%d\n", i, fgEnable); + } + } + + return TDLS_STATUS_SUCCESS; +} +#endif /* CFG_SUPPORT_TDLS */ + +/* End of tdls.c */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/tkip_mic.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/tkip_mic.c new file mode 100644 index 0000000000000..3b2729bc02ca2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/tkip_mic.c @@ -0,0 +1,627 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** Id: //Department/DaVinci/TRUNK/MT6620_WiFi_Firmware/mcu/wifi/mgmt/tkip_mic.c#7 +*/ + +/*! \file tkip_sw.c +* \brief This file include the tkip encrypted / decrypted mic function. +*/ +/******************************************************************************* +* Copyright (c) 2003-2004 Inprocomm, 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 +* Inprocomm, Inc. +******************************************************************************** +*/ + +/******************************************************************************* +* C O M P I L E 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 +******************************************************************************** +*/ + +#define WLAN_MAC_MIC_LEN 8 /* length of TKIP and CCMP MIC field */ + +#define MK16_TKIP(x, y) (((UINT_16) (x) << 8) | (UINT_16) (y)) + +#define LO_8BITS(x) ((x) & 0x00ff) /* obtain low 8-bit from 16-bit value, OK */ +#define HI_8BITS(x) ((x) >> 8) /* obtain high 8-bit from 16-bit value, OK */ + +#define ROTR32(x, y) (((x) >> (y)) | ((x) << (32 - (y)))) +#define ROTL32(x, y) (((x) << (y)) | ((x) >> (32 - (y)))) +#define ROTR16(x, y) (((x) >> (y)) | ((x) << (16 - (y)))) +#define ROTL16(x, y) (((x) << (y)) | ((x) >> (16 - (y)))) + +#define XSWAP32(x) ((((x) & 0xFF00FF00) >> 8) | (((x) & 0x00FF00FF) << 8)) + +/* obtain 16-bit entries SBOX form two 8-bit entries SBOX1 and SBOX2 */ +#define SBOX(x) (tkipSBOX1[LO_8BITS(x)] ^ tkipSBOX2[HI_8BITS(x)]) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +const UINT_16 tkipSBOX1[256] = { + 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, + 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A, + 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B, + 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B, + 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F, + 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F, + 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5, + 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F, + 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB, + 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397, + 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED, + 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A, + 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194, + 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3, + 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104, + 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D, + 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39, + 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695, + 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83, + 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76, + 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4, + 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B, + 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0, + 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018, + 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751, + 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85, + 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12, + 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9, + 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7, + 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A, + 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8, + 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A +}; + +const UINT_16 tkipSBOX2[256] = { + 0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491, + 0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC, + 0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB, + 0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B, + 0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83, + 0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A, + 0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F, + 0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA, + 0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B, + 0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713, + 0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6, + 0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85, + 0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411, + 0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B, + 0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1, + 0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF, + 0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E, + 0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6, + 0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B, + 0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD, + 0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8, + 0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2, + 0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049, + 0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810, + 0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197, + 0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F, + 0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C, + 0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927, + 0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733, + 0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5, + 0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0, + 0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C +}; + +/******************************************************************************* +* 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 +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief TKIP Michael block function +* +* \param[in][out] pu4L - pointer to left value +* \param[in][out] pu4PR - pointer to right value +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID tkipMicB(IN OUT PUINT_32 pu4L, IN OUT PUINT_32 pu4R) +{ + ASSERT(pu4L); + ASSERT(pu4R); + + *pu4R = *pu4R ^ ROTL32(*pu4L, 17); /* r <- r ^ (l<<<17) */ + *pu4L = (*pu4L + *pu4R); /* l <- (l+r) mod 2^32 */ + *pu4R = *pu4R ^ XSWAP32(*pu4L); /* r <- r ^ XSWAP(l) */ + *pu4L = (*pu4L + *pu4R); /* l <- (l+r) mod 2^32 */ + *pu4R = *pu4R ^ ROTL32(*pu4L, 3); /* r <- r ^ (l<<<3) */ + *pu4L = (*pu4L + *pu4R); /* l <- (l+r) mod 2^32 */ + *pu4R = *pu4R ^ ROTR32(*pu4L, 2); /* r <- r ^ (l>>>2) */ + *pu4L = (*pu4L + *pu4R); /* l <- (l+r) mod 2^32 */ +} /* tkipMicB */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief TKIP Michael generation function +* +* \param[in] pucMickey Pointer to MIC key +* \param[in] pucData Pointer to message +* \param[in] u4DataLen Message length, in byte(s) +* \param[in] pucSa Pointer to source address SA +* \param[in] pucDa Pointer to destination address DA +* \param[in] ucPriority Priority of IEEE 802.11 traffic class +* \param[out] pucMic Pointer to 64-bit MIC +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +tkipMicGen(IN PUCHAR pucMickey, + IN PUCHAR pucData, + IN UINT_32 u4DataLen, IN PUCHAR pucSa, IN PUCHAR pucDa, IN UCHAR ucPriority, OUT PUCHAR pucMic) +{ + + UINT_32 i; + UINT_32 l, r; + UINT_32 au4Msg[3]; + + ASSERT(pucMickey); + ASSERT(pucData); + ASSERT(pucSa); + ASSERT(pucDa); + ASSERT(pucMic); + + WLAN_GET_FIELD_32(pucMickey, &l); + WLAN_GET_FIELD_32(pucMickey + 4, &r); + + /* Michael message processing for DA and SA. */ + WLAN_GET_FIELD_32(pucDa, &au4Msg[0]); + au4Msg[1] = ((UINT_32) pucDa[4]) | ((UINT_32) pucDa[5] << 8) | + ((UINT_32) pucSa[0] << 16) | ((UINT_32) pucSa[1] << 24); + WLAN_GET_FIELD_32(pucSa + 2, &au4Msg[2]); + + for (i = 0; i < 3; i++) { + l = l ^ au4Msg[i]; + tkipMicB(&l, &r); + } + + /* Michael message processing for priority. */ + au4Msg[0] = (UINT_32) ucPriority; + + l = l ^ au4Msg[0]; + tkipMicB(&l, &r); + + /* Michael message processing for MSDU data playload except the last octets + * which cannot be partitioned into a 32-bit word. + */ + for (i = 0; i < (UINT_32) u4DataLen / 4; i++) { + WLAN_GET_FIELD_32(pucData + i * 4, &au4Msg[0]); + l = l ^ au4Msg[0]; + tkipMicB(&l, &r); + } + + /* Michael message processing for the last uncomplete octets, if present, + * and the padding. + */ + switch (u4DataLen & 3) { + case 1: + au4Msg[0] = ((UINT_32) pucData[u4DataLen - 1]) | 0x00005A00; + break; + + case 2: + au4Msg[0] = ((UINT_32) pucData[u4DataLen - 2]) | ((UINT_32) pucData[u4DataLen - 1] << 8) | 0x005A0000; + break; + + case 3: + au4Msg[0] = ((UINT_32) pucData[u4DataLen - 3]) | + ((UINT_32) pucData[u4DataLen - 2] << 8) | ((UINT_32) pucData[u4DataLen - 1] << 16) | 0x5A000000; + break; + + default: + au4Msg[0] = 0x0000005A; + } + au4Msg[1] = 0; + for (i = 0; i < 2; i++) { + l = l ^ au4Msg[i]; + tkipMicB(&l, &r); + } + + /* return ( l, r ), i.e. MIC */ + WLAN_SET_FIELD_32(pucMic, l); + WLAN_SET_FIELD_32(pucMic + 4, r); + +} /* tkipMicGen */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief this function decapsulate MSDU frame body( with MIC ) according +* to IEEE 802.11i TKIP sepcification. +* +* \param[in] prAdapter Pointer to the adapter object data area. +* \param[in] pucDa Pointer to destination address DA +* \param[in] pucSa Pointer to source address SA +* \param[in] ucPriority Priority of IEEE 802.11 traffic class +* \param[in] pucPayload Pointer to message +* \param[in] u2PayloadLen Message length, in byte(s) +* \param[out] pucMic Pointer to 64-bit MIC +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +VOID +tkipMicEncapsulate(IN PUINT_8 pucDa, + IN PUINT_8 pucSa, + IN UINT_8 ucPriority, + IN UINT_16 u2PayloadLen, IN PUINT_8 pucPayload, IN PUINT_8 pucMic, IN PUINT_8 pucMicKey) +{ + UCHAR aucMic[8]; /* MIC' */ + + DEBUGFUNC("tkipSwMsduEncapsulate"); + + ASSERT(pucDa); + ASSERT(pucSa); + ASSERT(pucPayload); + ASSERT(pucMic); + ASSERT(pucMicKey); + + DBGLOG(RSN, LOUD, "MIC key %02x-%02x-%02x-%02x %02x-%02x-%02x-%02x\n", + pucMicKey[0], pucMicKey[1], pucMicKey[2], pucMicKey[3], + pucMicKey[4], pucMicKey[5], pucMicKey[6], pucMicKey[7]); + + tkipMicGen(pucMicKey, (PUINT_8) pucPayload, u2PayloadLen, pucSa, pucDa, ucPriority, aucMic); + + kalMemCopy((PUINT_8) pucMic, &aucMic[0], WLAN_MAC_MIC_LEN); + + DBGLOG(RSN, LOUD, "Mic %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n", + pucMic[0], pucMic[1], pucMic[2], pucMic[3], pucMic[4], pucMic[5], pucMic[6], pucMic[7]); + +} /* tkipSwMsduEncapsulate */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function decapsulate MSDU frame body (with MIC) according +* to IEEE 802.11i TKIP sepcification. +* +* \param[in] prAdapter Pointer to the adapter object data area. +* \param[in] prMacHeader Pointer to frame MAC header +* \param[in] pucFrameBody Pointer to frame body +* \param[in] u4FrameBodyLen Length of frame body (in bytes), include +* length of ICV and MIC +* \param[in] pucMickey Pointer to MIC key +* \param[out] pu4ResultFrameBodyLen Pointer to put the result frame body length. +* +* \retval FALSE(TKIP_MIC_ERR), if this MSDU is not decapsulatable, i.e. MIC +* verification is failure. +* TRUE(TKIP_DECAPSULATE_SUCCESS), if this TKIP MSDU is decapsulated +* successfully, i.e. MIC verification is successful. +* +* \note 1 If return TRUE, result frame body length +* is only equal to data payload legth, and the result frame +* body's format is MSDU +* 2. If return FALSE, result frame body length is equal +* to data payload legth plus MIC and MIC', and the result +* frame body's format is: MSDU + MIC +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN tkipMicDecapsulate(IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucMicKey) +{ + PUCHAR pucMic1; /* MIC */ + UCHAR aucMic2[8]; /* MIC' */ + UCHAR ucPriority; + BOOLEAN fgStatus; + PUCHAR pucSa, pucDa; + /* PUCHAR pucMickey; */ + PUCHAR pucFrameBody; + UINT_16 u2FrameBodyLen; + P_WLAN_MAC_HEADER_T prMacHeader; + + DEBUGFUNC("tkipMicDecapsulate"); + + ASSERT(prSwRfb); + ASSERT(pucMicKey); + + /* prRxStatus = prSwRfb->prRxStatus; */ + pucFrameBody = prSwRfb->pucPayload; + u2FrameBodyLen = prSwRfb->u2PayloadLength; + + /* if ((prRxStatus->ucKIdxSecMode & BITS(0,3)) != CIPHER_SUITE_TKIP_WO_MIC){ */ + /* return TRUE; */ + /* } */ + + DBGLOG(RSN, LOUD, "Before TKIP MSDU Decapsulate:\n"); + DBGLOG(RSN, LOUD, "MIC key:\n"); + /* DBGLOG_MEM8(RSN, LOUD, pucMicKey, 8); */ + + prMacHeader = (P_WLAN_MAC_HEADER_T) prSwRfb->pvHeader; + ASSERT(prMacHeader); + + pucDa = prMacHeader->aucAddr1; + pucSa = prMacHeader->aucAddr3; + + switch (prMacHeader->u2FrameCtrl & MASK_TO_DS_FROM_DS) { + case 0: + pucDa = prMacHeader->aucAddr1; + pucSa = prMacHeader->aucAddr2; + break; + case MASK_FC_FROM_DS: + pucDa = prMacHeader->aucAddr1; + pucSa = prMacHeader->aucAddr3; + break; + default: + ASSERT((prMacHeader->u2FrameCtrl & MASK_FC_TO_DS) == 0); + return TRUE; + } + + if (RXM_IS_QOS_DATA_FRAME(prSwRfb->u2FrameCtrl)) + ucPriority = (UCHAR) ((((P_WLAN_MAC_HEADER_QOS_T) prSwRfb->pvHeader)->u2QosCtrl) & MASK_QC_TID); + else + ucPriority = 0; + + /* generate MIC' */ + tkipMicGen(pucMicKey, pucFrameBody, u2FrameBodyLen - WLAN_MAC_MIC_LEN, pucSa, pucDa, ucPriority, aucMic2); + + /* verify MIC and MIC' */ + pucMic1 = &pucFrameBody[u2FrameBodyLen - WLAN_MAC_MIC_LEN]; + if (pucMic1[0] == aucMic2[0] && pucMic1[1] == aucMic2[1] && + pucMic1[2] == aucMic2[2] && pucMic1[3] == aucMic2[3] && + pucMic1[4] == aucMic2[4] && pucMic1[5] == aucMic2[5] && + pucMic1[6] == aucMic2[6] && pucMic1[7] == aucMic2[7]) { + u2FrameBodyLen -= WLAN_MAC_MIC_LEN; + fgStatus = TRUE; + } else { + fgStatus = FALSE; + } + + /* DBGLOG(RSN, LOUD, ("TKIP MIC:\n")); */ + /* DBGLOG_MEM8(RSN, LOUD, pucMic1, 8); */ + /* DBGLOG(RSN, LOUD, ("TKIP MIC':\n")); */ + /* DBGLOG_MEM8(RSN, LOUD, aucMic2, 8); */ + + prSwRfb->u2PayloadLength = u2FrameBodyLen; + + DBGLOG(RSN, LOUD, "After TKIP MSDU Decapsulate:\n"); + DBGLOG(RSN, LOUD, "Frame body: (length = %u)\n", u2FrameBodyLen); + /* DBGLOG_MEM8(RSN, LOUD, pucFrameBody, u2FrameBodyLen); */ + + return fgStatus; + +} /* tkipMicDecapsulate */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function decapsulate MSDU frame body (with MIC) according +* to IEEE 802.11i TKIP sepcification. +* +* \param[in] prAdapter Pointer to the adapter object data area. +* \param[in] prMacHeader Pointer to frame MAC header +* \param[in] pucFrameBody Pointer to frame body +* \param[in] u4FrameBodyLen Length of frame body (in bytes), include +* length of ICV and MIC +* \param[in] pucMickey Pointer to MIC key +* \param[out] pu4ResultFrameBodyLen Pointer to put the result frame body length. +* +* \retval FALSE(TKIP_MIC_ERR), if this MSDU is not decapsulatable, i.e. MIC +* verification is failure. +* TRUE(TKIP_DECAPSULATE_SUCCESS), if this TKIP MSDU is decapsulated +* successfully, i.e. MIC verification is successful. +* +* \note 1 If return TRUE, result frame body length +* is only equal to data payload legth, and the result frame +* body's format is MSDU +* 2. If return FALSE, result frame body length is equal +* to data payload legth plus MIC and MIC', and the result +* frame body's format is: MSDU + MIC +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN tkipMicDecapsulateInRxHdrTransMode(IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucMicKey) +{ + PUCHAR pucMic1; /* MIC */ + UCHAR aucMic2[8]; /* MIC' */ + BOOLEAN fgStatus = FALSE; + /* PUCHAR pucMickey; */ + PUCHAR pucFrameBody; + UINT_16 u2FrameBodyLen; + struct sk_buff *prSkb = NULL; +#if 0 + P_WLAN_MAC_HEADER_T prMacHeader; + PUCHAR pucSa, pucDa; + UCHAR ucPriority; + UCHAR aucDA[6]; + UCHAR aucSA[6]; + UCHAR aucType[2]; +#endif + + DEBUGFUNC("tkipMicDecapsulateInRxHdrTransMode"); + + ASSERT(prSwRfb); + ASSERT(pucMicKey); + + /* prRxStatus = prSwRfb->prRxStatus; */ + pucFrameBody = prSwRfb->pucPayload; + u2FrameBodyLen = prSwRfb->u2PayloadLength; + + /* if ((prRxStatus->ucKIdxSecMode & BITS(0,3)) != CIPHER_SUITE_TKIP_WO_MIC){ */ + /* return TRUE; */ + /* } */ + + DBGLOG(RSN, LOUD, "Before TKIP MSDU Decapsulate:\n"); + DBGLOG(RSN, LOUD, "MIC key:\n"); + /* DBGLOG_MEM8(RSN, LOUD, pucMicKey, 8); */ + + prSkb = dev_alloc_skb(u2FrameBodyLen + ETHERNET_HEADER_SZ*4); + if (prSkb) { + /* copy to etherhdr + payload to skb data */ + kalMemCopy(prSkb->data, prSwRfb->pvHeader, u2FrameBodyLen + ETHERNET_HEADER_SZ); + *(prSkb->data+6) = ETH_LLC_DSAP_SNAP; + *(prSkb->data+7) = ETH_LLC_SSAP_SNAP; + *(prSkb->data+8) = ETH_LLC_CONTROL_UNNUMBERED_INFORMATION; + *(prSkb->data+9) = 0x00; + *(prSkb->data+10) = 0x00; + *(prSkb->data+11) = 0x00; + *(prSkb->data+12) = *(PUCHAR)(prSwRfb->pvHeader + 12); + *(prSkb->data+13) = *(PUCHAR)(prSwRfb->pvHeader + 13); + + tkipMicGen(pucMicKey, + prSkb->data + 6, + u2FrameBodyLen - WLAN_MAC_MIC_LEN + 8, + prSwRfb->pvHeader + 6, + prSwRfb->pvHeader, + prSwRfb->ucTid, aucMic2); + + if (prSkb) + kfree_skb((struct sk_buff *)prSkb); + } else { + DBGLOG(RX, ERROR, "MIC SW DEC1\n"); + return fgStatus; + } + + + /* verify MIC and MIC' */ + pucMic1 = &pucFrameBody[u2FrameBodyLen - WLAN_MAC_MIC_LEN]; + if (pucMic1[0] == aucMic2[0] && pucMic1[1] == aucMic2[1] && + pucMic1[2] == aucMic2[2] && pucMic1[3] == aucMic2[3] && + pucMic1[4] == aucMic2[4] && pucMic1[5] == aucMic2[5] && + pucMic1[6] == aucMic2[6] && pucMic1[7] == aucMic2[7]) { + u2FrameBodyLen -= WLAN_MAC_MIC_LEN; + fgStatus = TRUE; + } else { + fgStatus = FALSE; + DBGLOG(RX, ERROR, "MIC SW DEC2\n"); + } + +#if 0 + /* perform header transfer for tkip defragment frame, if receiving 802.11 pkt */ + if (fgStatus == TRUE) { + /* reassign payload address */ + prSwRfb->pucPayload += (ETH_LLC_LEN + ETH_SNAP_LEN); + + /* reassign payload length */ + u2FrameBodyLen -= (ETH_LLC_LEN + ETH_SNAP_LEN); + + prSwRfb->pvHeader = prSwRfb->pucPayload - (ETHERNET_HEADER_SZ); + + kalMemCopy(&aucDA[0], pucDa, MAC_ADDR_LEN); + kalMemCopy(&aucSA[0], pucSa, MAC_ADDR_LEN); + kalMemCopy(&aucType[0], prSwRfb->pucPayload - 2, 2); + + kalMemCopy(prSwRfb->pvHeader, &aucDA[0], MAC_ADDR_LEN); + kalMemCopy(prSwRfb->pvHeader + MAC_ADDR_LEN, &aucSA[0], MAC_ADDR_LEN); + kalMemCopy(prSwRfb->pvHeader + MAC_ADDR_LEN + 2, &aucType[0], 2); + + prSwRfb->u2HeaderLen = ETHERNET_HEADER_SZ; + } +#endif + + /* DBGLOG(RSN, LOUD, ("TKIP MIC:\n")); */ + /* DBGLOG_MEM8(RSN, LOUD, pucMic1, 8); */ + /* DBGLOG(RSN, LOUD, ("TKIP MIC':\n")); */ + /* DBGLOG_MEM8(RSN, LOUD, aucMic2, 8); */ + + prSwRfb->u2PayloadLength = u2FrameBodyLen; + + DBGLOG(RSN, LOUD, "After TKIP MSDU Decapsulate:\n"); + DBGLOG(RSN, LOUD, "Frame body: (length = %u)\n", u2FrameBodyLen); + /* DBGLOG_MEM8(RSN, LOUD, pucFrameBody, u2FrameBodyLen); */ + + return fgStatus; + +} /* tkipMicDecapsulate */ diff --git a/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/wapi.c b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/wapi.c new file mode 100644 index 0000000000000..261c9401b3ff0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/core/gen4-mt7668/mgmt/wapi.c @@ -0,0 +1,503 @@ +/****************************************************************************** + * + * This file is provided under a dual license. When you use or + * distribute this software, you may choose to be licensed under + * version 2 of the GNU General Public License ("GPLv2 License") + * or BSD License. + * + * GPLv2 License + * + * Copyright(C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See http://www.gnu.org/licenses/gpl-2.0.html for more details. + * + * BSD LICENSE + * + * Copyright(C) 2016 MediaTek Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* +** 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. +*/ + + +/******************************************************************************* +* C O M P I L E 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->ucBssIndex != prAdapter->prAisBssInfo->ucBssIndex) + return; + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (ULONG) 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; + UINT_8 *pucPairSuite = NULL; + UINT_8 *pucAuthSuite = NULL; + UINT_8 *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 = (UINT_8 *) &prInfoElem->u2AuthKeyMgtSuiteCount; + u4RemainWapiIeLen = (INT_32) prInfoElem->ucLength - 2; + + do { + if (u4RemainWapiIeLen == 0) + break; + + /* + * AuthCount : 2 + * AuthSuite : 4 * authSuiteCount + * PairwiseCount: 2 + * PairwiseSuite: 4 * pairSuiteCount + * GroupSuite : 4 + * Cap : 2 + */ + + /* Parse the Authentication and Key Management Cipher Suite Count field. */ + if (u4RemainWapiIeLen < 2) { + DBGLOG(SEC, TRACE, + "Fail to parse WAPI IE in auth & key mgt suite count (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + WLAN_GET_FIELD_16(cp, &u2AuthSuiteCount); + cp += 2; + u4RemainWapiIeLen -= 2; + + /* Parse the Authentication and Key Management Cipher Suite List field. */ + i = (UINT_32) u2AuthSuiteCount * 4; + if (u4RemainWapiIeLen < (INT_32) i) { + DBGLOG(SEC, TRACE, + "Fail to parse WAPI IE in auth & key mgt suite list (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + pucAuthSuite = cp; + + cp += i; + u4RemainWapiIeLen -= (INT_32) i; + + if (u4RemainWapiIeLen == 0) + break; + + /* Parse the Pairwise Key Cipher Suite Count field. */ + if (u4RemainWapiIeLen < 2) { + DBGLOG(SEC, TRACE, + "Fail to parse WAPI IE in pairwise cipher suite count (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + WLAN_GET_FIELD_16(cp, &u2PairSuiteCount); + cp += 2; + u4RemainWapiIeLen -= 2; + + /* Parse the Pairwise Key Cipher Suite List field. */ + i = (UINT_32) u2PairSuiteCount * 4; + if (u4RemainWapiIeLen < (INT_32) i) { + DBGLOG(SEC, TRACE, + "Fail to parse WAPI IE in pairwise cipher suite list (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + pucPairSuite = cp; + + cp += i; + u4RemainWapiIeLen -= (INT_32) i; + + /* Parse the Group Key Cipher Suite field. */ + if (u4RemainWapiIeLen < 4) { + DBGLOG(SEC, TRACE, + "Fail to parse WAPI IE in group cipher suite (IE len: %d)\n", prInfoElem->ucLength); + return FALSE; + } + + WLAN_GET_FIELD_32(cp, &u4GroupSuite); + cp += 4; + u4RemainWapiIeLen -= 4; + + /* Parse the WAPI u2Capabilities field. */ + if (u4RemainWapiIeLen < 2) { + DBGLOG(SEC, TRACE, + "Fail to parse WAPI IE in WAPI capabilities (IE len: %d)\n", prInfoElem->ucLength); + return FALSE; + } + + WLAN_GET_FIELD_16(cp, &u2Cap); + u4RemainWapiIeLen -= 2; + + /* Todo:: BKID support */ + } while (FALSE); + + /* Save the WAPI information for the BSS. */ + + prWapiInfo->ucElemId = ELEM_ID_WAPI; + + prWapiInfo->u2Version = u2Version; + + prWapiInfo->u4GroupKeyCipherSuite = u4GroupSuite; + + DBGLOG(SEC, LOUD, "WAPI: version %d, group key cipher suite %02x-%02x-%02x-%02x\n", + u2Version, (UCHAR) (u4GroupSuite & 0x000000FF), + (UCHAR) ((u4GroupSuite >> 8) & 0x000000FF), + (UCHAR) ((u4GroupSuite >> 16) & 0x000000FF), (UCHAR) ((u4GroupSuite >> 24) & 0x000000FF)); + + if (pucPairSuite) { + /* The information about the pairwise key cipher suites is present. */ + if (u2PairSuiteCount > MAX_NUM_SUPPORTED_WAPI_CIPHER_SUITES) + u2PairSuiteCount = MAX_NUM_SUPPORTED_WAPI_CIPHER_SUITES; + + prWapiInfo->u4PairwiseKeyCipherSuiteCount = (UINT_32) u2PairSuiteCount; + + for (i = 0; i < (UINT_32) u2PairSuiteCount; i++) { + WLAN_GET_FIELD_32(pucPairSuite, &prWapiInfo->au4PairwiseKeyCipherSuite[i]); + pucPairSuite += 4; + + DBGLOG(SEC, LOUD, + "WAPI: pairwise key cipher suite [%d]: %02x-%02x-%02x-%02x\n", + (UINT_8) i, + (UCHAR) (prWapiInfo->au4PairwiseKeyCipherSuite[i] & 0x000000FF), + (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[i] >> 8) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[i] >> 16) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[i] >> 24) & 0x000000FF)); + } + } else { + /* The information about the pairwise key cipher suites is not present. + * Use the default chipher suite for WAPI: WPI. + */ + prWapiInfo->u4PairwiseKeyCipherSuiteCount = 1; + prWapiInfo->au4PairwiseKeyCipherSuite[0] = WAPI_CIPHER_SUITE_WPI; + + DBGLOG(SEC, LOUD, + "WAPI: pairwise key cipher suite: %02x-%02x-%02x-%02x (default)\n", + (UCHAR) (prWapiInfo->au4PairwiseKeyCipherSuite[0] & 0x000000FF), + (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[0] >> 8) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[0] >> 16) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[0] >> 24) & 0x000000FF)); + } + + if (pucAuthSuite) { + /* The information about the authentication and key management suites + * is present. + */ + if (u2AuthSuiteCount > MAX_NUM_SUPPORTED_WAPI_AKM_SUITES) + u2AuthSuiteCount = MAX_NUM_SUPPORTED_WAPI_AKM_SUITES; + + prWapiInfo->u4AuthKeyMgtSuiteCount = (UINT_32) u2AuthSuiteCount; + + for (i = 0; i < (UINT_32) u2AuthSuiteCount; i++) { + WLAN_GET_FIELD_32(pucAuthSuite, &prWapiInfo->au4AuthKeyMgtSuite[i]); + pucAuthSuite += 4; + + DBGLOG(SEC, LOUD, "WAPI: AKM suite [%d]: %02x-%02x-%02x-%02x\n", + (UINT_8) i, + (UCHAR) (prWapiInfo->au4AuthKeyMgtSuite[i] & 0x000000FF), + (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[i] >> 8) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[i] >> 16) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[i] >> 24) & 0x000000FF)); + } + } else { + /* The information about the authentication and key management suites + * is not present. Use the default AKM suite for WAPI. + */ + prWapiInfo->u4AuthKeyMgtSuiteCount = 1; + prWapiInfo->au4AuthKeyMgtSuite[0] = WAPI_AKM_SUITE_802_1X; + + DBGLOG(SEC, LOUD, "WAPI: AKM suite: %02x-%02x-%02x-%02x (default)\n", + (UCHAR) (prWapiInfo->au4AuthKeyMgtSuite[0] & 0x000000FF), + (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[0] >> 8) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[0] >> 16) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[0] >> 24) & 0x000000FF)); + } + + prWapiInfo->u2WapiCap = u2Cap; + DBGLOG(SEC, LOUD, "WAPI: cap: 0x%04x\n", prWapiInfo->u2WapiCap); + + return TRUE; +} /* wapiParseWapiIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to perform WAPI policy selection for a given BSS. +* +* \param[in] prAdapter Pointer to the adapter object data area. +* \param[in] prBss Pointer to the BSS description +* +* \retval TRUE - The WAPI policy selection for the given BSS is +* successful. The selected pairwise and group cipher suites +* are returned in the BSS description. +* \retval FALSE - The WAPI policy selection for the given BSS is failed. +* The driver shall not attempt to join the given BSS. +* +* \note The Encrypt status matched score will save to bss for final ap select. +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wapiPerformPolicySelection(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBss) +{ + UINT_32 i; + UINT_32 u4PairwiseCipher = 0; + UINT_32 u4GroupCipher = 0; + UINT_32 u4AkmSuite = 0; + P_WAPI_INFO_T prBssWapiInfo; + P_WLAN_INFO_T prWlanInfo; + + DEBUGFUNC("wapiPerformPolicySelection"); + + ASSERT(prBss); + + /* Notice!!!! WAPI AP not set the privacy bit for WAI and WAI-PSK at WZC configuration mode */ + prWlanInfo = &prAdapter->rWlanInfo; + + if (prBss->fgIEWAPI) { + prBssWapiInfo = &prBss->rIEWAPI; + } else { + if (prAdapter->rWifiVar.rConnSettings.fgWapiMode == FALSE) { + DBGLOG(SEC, TRACE, "-- No Protected BSS\n"); + return TRUE; + } + DBGLOG(SEC, TRACE, "WAPI Information Element does not exist.\n"); + return FALSE; + } + + /* Select pairwise/group ciphers */ + for (i = 0; i < prBssWapiInfo->u4PairwiseKeyCipherSuiteCount; i++) { + if (prBssWapiInfo->au4PairwiseKeyCipherSuite[i] == + prAdapter->rWifiVar.rConnSettings.u4WapiSelectedPairwiseCipher) { + u4PairwiseCipher = prBssWapiInfo->au4PairwiseKeyCipherSuite[i]; + } + } + if (prBssWapiInfo->u4GroupKeyCipherSuite == prAdapter->rWifiVar.rConnSettings.u4WapiSelectedGroupCipher) + u4GroupCipher = prBssWapiInfo->u4GroupKeyCipherSuite; + + /* Exception handler */ + /* If we cannot find proper pairwise and group cipher suites to join the + * BSS, do not check the supported AKM suites. + */ + if (u4PairwiseCipher == 0 || u4GroupCipher == 0) { + DBGLOG(SEC, TRACE, + "Failed to select pairwise/group cipher (0x%08x/0x%08x)\n", + u4PairwiseCipher, u4GroupCipher); + return FALSE; + } + + /* Select AKM */ + /* If the driver cannot support any authentication suites advertised in + * the given BSS, we fail to perform RSNA policy selection. + */ + /* Attempt to find any overlapping supported AKM suite. */ + for (i = 0; i < prBssWapiInfo->u4AuthKeyMgtSuiteCount; i++) { + if (prBssWapiInfo->au4AuthKeyMgtSuite[i] == prAdapter->rWifiVar.rConnSettings.u4WapiSelectedAKMSuite) { + u4AkmSuite = prBssWapiInfo->au4AuthKeyMgtSuite[i]; + break; + } + } + + if (u4AkmSuite == 0) { + DBGLOG(SEC, TRACE, "Cannot support any AKM suites\n"); + return FALSE; + } + + DBGLOG(SEC, TRACE, + "Selected pairwise/group cipher: %02x-%02x-%02x-%02x/%02x-%02x-%02x-%02x\n", + (UINT_8) (u4PairwiseCipher & 0x000000FF), + (UINT_8) ((u4PairwiseCipher >> 8) & 0x000000FF), + (UINT_8) ((u4PairwiseCipher >> 16) & 0x000000FF), + (UINT_8) ((u4PairwiseCipher >> 24) & 0x000000FF), + (UINT_8) (u4GroupCipher & 0x000000FF), (UINT_8) ((u4GroupCipher >> 8) & 0x000000FF), + (UINT_8) ((u4GroupCipher >> 16) & 0x000000FF), (UINT_8) ((u4GroupCipher >> 24) & 0x000000FF)); + + DBGLOG(SEC, TRACE, "Selected AKM suite: %02x-%02x-%02x-%02x\n", + (UINT_8) (u4AkmSuite & 0x000000FF), + (UINT_8) ((u4AkmSuite >> 8) & 0x000000FF), + (UINT_8) ((u4AkmSuite >> 16) & 0x000000FF), (UINT_8) ((u4AkmSuite >> 24) & 0x000000FF)); + + return TRUE; +} /* wapiPerformPolicySelection */ + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is use for wapi mode, to update the current wpi tx idx ? 0 :1 . +* +* \param[in] prStaRec Pointer to the Sta record +* \param[out] ucWlanIdx The Rx status->wlanidx field +* +* \retval TRUE - Succeeded +* \retval FALSE - Failed +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wapiUpdateTxKeyIdx(IN P_STA_RECORD_T prStaRec, IN UINT_8 ucWlanIdx) +{ + UINT_8 ucKeyId; + + if ((ucWlanIdx & BITS(0, 3)) == CIPHER_SUITE_WPI) { + + ucKeyId = ((ucWlanIdx & BITS(4, 5)) >> 4); + + if (ucKeyId != g_prWifiVar->rAisSpecificBssInfo.ucWpiActivedPWKey) { + DBGLOG(RSN, STATE, + "Change wapi key index from %d->%d\n", + g_prWifiVar->rAisSpecificBssInfo.ucWpiActivedPWKey, ucKeyId); + g_prWifiVar->rAisSpecificBssInfo.ucWpiActivedPWKey = ucKeyId; + + prStaRec->ucWlanIndex = + (ucKeyId == + WTBL_AIS_BSSID_WAPI_IDX_0) ? WTBL_AIS_BSSID_WAPI_IDX_0 : WTBL_AIS_BSSID_WAPI_IDX_1; + } + } +} +#endif +#endif From 6cec8f626b326791992b2f6ac54e51c49ff94d79 Mon Sep 17 00:00:00 2001 From: SunsetDreamer <134821284+jumitenei@users.noreply.github.com> Date: Mon, 16 Sep 2024 22:46:58 +0800 Subject: [PATCH 32/32] Update ares_user_defconfig --- arch/arm64/configs/ares_user_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/ares_user_defconfig b/arch/arm64/configs/ares_user_defconfig index 686a4f1930be6..28cb8a9d93de2 100644 --- a/arch/arm64/configs/ares_user_defconfig +++ b/arch/arm64/configs/ares_user_defconfig @@ -518,3 +518,4 @@ CONFIG_MODULES=y CONFIG_MODULE_FORCE_LOAD=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_WLAN_DRV_BUILD_IN=y